summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRémy Coutable <remy@rymai.me>2018-12-04 13:39:35 +0000
committerRémy Coutable <remy@rymai.me>2018-12-04 13:39:35 +0000
commit4bcec7439b6228af84a902d4a7d1a3ad9d3b24c5 (patch)
treee56f967952045b119de78cc30d04c7d4528a9af0
parent8c94d245db71105f299622b31ff4192400fe8ffa (diff)
parent77f215b3f4feaab49f9d10975554b8c866e865f9 (diff)
downloadgitlab-ce-4bcec7439b6228af84a902d4a7d1a3ad9d3b24c5.tar.gz
Merge branch 'master' into 'patch-28'
# Conflicts: # doc/development/i18n/proofreader.md
-rw-r--r--.babelrc25
-rw-r--r--.babelrc.js38
-rw-r--r--.eslintrc.yml77
-rw-r--r--.gitattributes1
-rw-r--r--.gitignore1
-rw-r--r--.gitlab-ci.yml458
-rw-r--r--.gitlab/CODEOWNERS17
-rw-r--r--.gitlab/CODEOWNERS.disabled20
-rw-r--r--.gitlab/issue_templates/Research proposal.md17
-rw-r--r--.gitlab/issue_templates/Security developer workflow.md6
-rw-r--r--.gitlab/issue_templates/Test plan.md38
-rw-r--r--.gitlab/merge_request_templates/Database changes.md28
-rw-r--r--.gitlab/merge_request_templates/Documentation.md1
-rw-r--r--.nvmrc2
-rw-r--r--.prettierignore4
-rw-r--r--.rubocop.yml35
-rw-r--r--.rubocop_todo.yml80
-rw-r--r--.ruby-version2
-rw-r--r--CHANGELOG.md794
-rw-r--r--CONTRIBUTING.md156
-rw-r--r--Dangerfile3
-rw-r--r--Dockerfile.assets4
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--GITLAB_WORKHORSE_VERSION2
-rw-r--r--Gemfile88
-rw-r--r--Gemfile.lock356
-rw-r--r--Gemfile.rails47
-rw-r--r--Gemfile.rails4.lock1161
-rw-r--r--Gemfile.rails57
-rw-r--r--Gemfile.rails5.lock1205
-rw-r--r--PHILOSOPHY.md1
-rw-r--r--PROCESS.md7
-rw-r--r--README.md2
-rw-r--r--VERSION2
-rw-r--r--app/assets/images/ci_favicons/canary/favicon_status_scheduled.icobin0 -> 5430 bytes
-rw-r--r--app/assets/images/ci_favicons/favicon_status_scheduled.pngbin0 -> 1072 bytes
-rw-r--r--app/assets/images/cluster_app_logos/cert_manager.pngbin0 -> 1287 bytes
-rw-r--r--app/assets/images/cluster_app_logos/knative.pngbin0 -> 11259 bytes
-rw-r--r--app/assets/images/koding-logo.svg8
-rw-r--r--app/assets/javascripts/activities.js10
-rw-r--r--app/assets/javascripts/api.js86
-rw-r--r--app/assets/javascripts/awards_handler.js32
-rw-r--r--app/assets/javascripts/badges/components/badge.vue34
-rw-r--r--app/assets/javascripts/badges/components/badge_form.vue55
-rw-r--r--app/assets/javascripts/badges/components/badge_list.vue29
-rw-r--r--app/assets/javascripts/badges/components/badge_list_row.vue27
-rw-r--r--app/assets/javascripts/badges/components/badge_settings.vue13
-rw-r--r--app/assets/javascripts/behaviors/copy_to_clipboard.js2
-rw-r--r--app/assets/javascripts/behaviors/details_behavior.js8
-rw-r--r--app/assets/javascripts/behaviors/markdown/copy_as_gfm.js109
-rw-r--r--app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js4
-rw-r--r--app/assets/javascripts/behaviors/markdown/highlight_current_user.js17
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_gfm.js2
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_math.js8
-rw-r--r--app/assets/javascripts/behaviors/markdown/render_mermaid.js61
-rw-r--r--app/assets/javascripts/behaviors/preview_markdown.js111
-rw-r--r--app/assets/javascripts/behaviors/quick_submit.js40
-rw-r--r--app/assets/javascripts/behaviors/requires_input.js3
-rw-r--r--app/assets/javascripts/behaviors/secret_values.js16
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts.js33
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js31
-rw-r--r--app/assets/javascripts/behaviors/toggler_behavior.js4
-rw-r--r--app/assets/javascripts/blob/3d_viewer/index.js58
-rw-r--r--app/assets/javascripts/blob/3d_viewer/mesh_object.js21
-rw-r--r--app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js2
-rw-r--r--app/assets/javascripts/blob/blob_file_dropzone.js28
-rw-r--r--app/assets/javascripts/blob/blob_line_permalink_updater.js18
-rw-r--r--app/assets/javascripts/blob/file_template_mediator.js44
-rw-r--r--app/assets/javascripts/blob/file_template_selector.js8
-rw-r--r--app/assets/javascripts/blob/notebook/index.js7
-rw-r--r--app/assets/javascripts/blob/sketch/index.js2
-rw-r--r--app/assets/javascripts/blob/stl_viewer.js4
-rw-r--r--app/assets/javascripts/blob/template_selector.js11
-rw-r--r--app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js4
-rw-r--r--app/assets/javascripts/blob/template_selectors/dockerfile_selector.js4
-rw-r--r--app/assets/javascripts/blob/template_selectors/gitignore_selector.js4
-rw-r--r--app/assets/javascripts/blob/template_selectors/license_selector.js6
-rw-r--r--app/assets/javascripts/blob/template_selectors/type_selector.js1
-rw-r--r--app/assets/javascripts/blob/viewer/index.js50
-rw-r--r--app/assets/javascripts/blob_edit/blob_bundle.js13
-rw-r--r--app/assets/javascripts/blob_edit/edit_blob.js32
-rw-r--r--app/assets/javascripts/boards/components/board.js59
-rw-r--r--app/assets/javascripts/boards/components/board_blank_state.vue56
-rw-r--r--app/assets/javascripts/boards/components/board_card.vue134
-rw-r--r--app/assets/javascripts/boards/components/board_delete.js14
-rw-r--r--app/assets/javascripts/boards/components/board_list.vue105
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue.vue52
-rw-r--r--app/assets/javascripts/boards/components/board_sidebar.js59
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner.vue364
-rw-r--r--app/assets/javascripts/boards/components/issue_due_date.vue82
-rw-r--r--app/assets/javascripts/boards/components/issue_time_estimate.vue44
-rw-r--r--app/assets/javascripts/boards/components/modal/empty_state.vue14
-rw-r--r--app/assets/javascripts/boards/components/modal/footer.vue42
-rw-r--r--app/assets/javascripts/boards/components/modal/header.vue88
-rw-r--r--app/assets/javascripts/boards/components/modal/index.vue246
-rw-r--r--app/assets/javascripts/boards/components/modal/list.vue240
-rw-r--r--app/assets/javascripts/boards/components/modal/lists_dropdown.vue40
-rw-r--r--app/assets/javascripts/boards/components/modal/tabs.vue56
-rw-r--r--app/assets/javascripts/boards/components/new_list_dropdown.js63
-rw-r--r--app/assets/javascripts/boards/components/project_select.vue69
-rw-r--r--app/assets/javascripts/boards/components/sidebar/remove_issue.vue133
-rw-r--r--app/assets/javascripts/boards/filtered_search_boards.js12
-rw-r--r--app/assets/javascripts/boards/index.js77
-rw-r--r--app/assets/javascripts/boards/mixins/sortable_default_options.js33
-rw-r--r--app/assets/javascripts/boards/models/issue.js37
-rw-r--r--app/assets/javascripts/boards/models/list.js15
-rw-r--r--app/assets/javascripts/boards/services/board_service.js12
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js82
-rw-r--r--app/assets/javascripts/boards/stores/modal_store.js12
-rw-r--r--app/assets/javascripts/breadcrumb.js15
-rw-r--r--app/assets/javascripts/build_artifacts.js22
-rw-r--r--app/assets/javascripts/build_variables.js10
-rw-r--r--app/assets/javascripts/ci_variable_list/ajax_variable_list.js64
-rw-r--r--app/assets/javascripts/ci_variable_list/ci_variable_list.js41
-rw-r--r--app/assets/javascripts/ci_variable_list/native_form_variable_list.js5
-rw-r--r--app/assets/javascripts/clusters/clusters_bundle.js27
-rw-r--r--app/assets/javascripts/clusters/clusters_index.js24
-rw-r--r--app/assets/javascripts/clusters/components/application_row.vue345
-rw-r--r--app/assets/javascripts/clusters/components/applications.vue278
-rw-r--r--app/assets/javascripts/clusters/constants.js9
-rw-r--r--app/assets/javascripts/clusters/services/clusters_service.js2
-rw-r--r--app/assets/javascripts/clusters/stores/clusters_store.js31
-rw-r--r--app/assets/javascripts/comment_type_toggle.js56
-rw-r--r--app/assets/javascripts/commit/image_file.js322
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_bundle.js10
-rw-r--r--app/assets/javascripts/commit/pipelines/pipelines_table.vue151
-rw-r--r--app/assets/javascripts/commit_merge_requests.js7
-rw-r--r--app/assets/javascripts/commits.js38
-rw-r--r--app/assets/javascripts/commons/bootstrap.js12
-rw-r--r--app/assets/javascripts/commons/gitlab_ui.js16
-rw-r--r--app/assets/javascripts/commons/index.js1
-rw-r--r--app/assets/javascripts/commons/polyfills.js1
-rw-r--r--app/assets/javascripts/compare_autocomplete.js4
-rw-r--r--app/assets/javascripts/confirm_danger_modal.js24
-rw-r--r--app/assets/javascripts/contextual_sidebar.js10
-rw-r--r--app/assets/javascripts/create_item_dropdown.js13
-rw-r--r--app/assets/javascripts/create_label.js63
-rw-r--r--app/assets/javascripts/cycle_analytics/components/banner.vue64
-rw-r--r--app/assets/javascripts/cycle_analytics/components/limit_warning_component.vue38
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_code_component.vue67
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_component.vue74
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_plan_component.vue80
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_review_component.vue93
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue109
-rw-r--r--app/assets/javascripts/cycle_analytics/components/stage_test_component.vue115
-rw-r--r--app/assets/javascripts/cycle_analytics/components/total_time_component.vue46
-rw-r--r--app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js24
-rw-r--r--app/assets/javascripts/cycle_analytics/cycle_analytics_service.js5
-rw-r--r--app/assets/javascripts/cycle_analytics/cycle_analytics_store.js36
-rw-r--r--app/assets/javascripts/deploy_keys/components/action_btn.vue12
-rw-r--r--app/assets/javascripts/deploy_keys/components/app.vue30
-rw-r--r--app/assets/javascripts/deploy_keys/components/key.vue71
-rw-r--r--app/assets/javascripts/deploy_keys/components/keys_panel.vue23
-rw-r--r--app/assets/javascripts/deploy_keys/service/index.js9
-rw-r--r--app/assets/javascripts/diff.js14
-rw-r--r--app/assets/javascripts/diff_notes/components/comment_resolve_btn.js32
-rw-r--r--app/assets/javascripts/diff_notes/components/diff_note_avatars.js28
-rw-r--r--app/assets/javascripts/diff_notes/components/jump_to_discussion.js39
-rw-r--r--app/assets/javascripts/diff_notes/components/resolve_count.js12
-rw-r--r--app/assets/javascripts/diff_notes/mixins/discussion.js12
-rw-r--r--app/assets/javascripts/diff_notes/models/discussion.js18
-rw-r--r--app/assets/javascripts/diff_notes/stores/comments.js16
-rw-r--r--app/assets/javascripts/diffs/components/app.vue132
-rw-r--r--app/assets/javascripts/diffs/components/changed_files.vue171
-rw-r--r--app/assets/javascripts/diffs/components/changed_files_dropdown.vue126
-rw-r--r--app/assets/javascripts/diffs/components/commit_item.vue111
-rw-r--r--app/assets/javascripts/diffs/components/commit_widget.vue38
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions.vue129
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions_dropdown.vue54
-rw-r--r--app/assets/javascripts/diffs/components/diff_content.vue83
-rw-r--r--app/assets/javascripts/diffs/components/diff_discussions.vue52
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue94
-rw-r--r--app/assets/javascripts/diffs/components/diff_file_header.vue119
-rw-r--r--app/assets/javascripts/diffs/components/diff_gutter_avatars.vue14
-rw-r--r--app/assets/javascripts/diffs/components/diff_line_gutter_content.vue49
-rw-r--r--app/assets/javascripts/diffs/components/diff_line_note_form.vue59
-rw-r--r--app/assets/javascripts/diffs/components/diff_table_cell.vue17
-rw-r--r--app/assets/javascripts/diffs/components/edit_button.vue8
-rw-r--r--app/assets/javascripts/diffs/components/file_row_stats.vue23
-rw-r--r--app/assets/javascripts/diffs/components/hidden_files_warning.vue21
-rw-r--r--app/assets/javascripts/diffs/components/image_diff_overlay.vue132
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_comment_row.vue34
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_table_row.vue27
-rw-r--r--app/assets/javascripts/diffs/components/inline_diff_view.vue32
-rw-r--r--app/assets/javascripts/diffs/components/no_changes.vue21
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue62
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_table_row.vue43
-rw-r--r--app/assets/javascripts/diffs/components/parallel_diff_view.vue26
-rw-r--r--app/assets/javascripts/diffs/components/tree_list.vue150
-rw-r--r--app/assets/javascripts/diffs/constants.js3
-rw-r--r--app/assets/javascripts/diffs/index.js5
-rw-r--r--app/assets/javascripts/diffs/mixins/changed_files.js38
-rw-r--r--app/assets/javascripts/diffs/store/actions.js90
-rw-r--r--app/assets/javascripts/diffs/store/getters.js51
-rw-r--r--app/assets/javascripts/diffs/store/modules/diff_state.js14
-rw-r--r--app/assets/javascripts/diffs/store/mutation_types.js11
-rw-r--r--app/assets/javascripts/diffs/store/mutations.js227
-rw-r--r--app/assets/javascripts/diffs/store/utils.js194
-rw-r--r--app/assets/javascripts/dirty_submit/dirty_submit_collection.js13
-rw-r--r--app/assets/javascripts/dirty_submit/dirty_submit_factory.js9
-rw-r--r--app/assets/javascripts/dirty_submit/dirty_submit_form.js83
-rw-r--r--app/assets/javascripts/dismissable_callout.js27
-rw-r--r--app/assets/javascripts/droplab/constants.js9
-rw-r--r--app/assets/javascripts/droplab/drop_down.js4
-rw-r--r--app/assets/javascripts/droplab/drop_lab.js5
-rw-r--r--app/assets/javascripts/droplab/keyboard.js53
-rw-r--r--app/assets/javascripts/droplab/plugins/ajax.js4
-rw-r--r--app/assets/javascripts/droplab/plugins/ajax_filter.js18
-rw-r--r--app/assets/javascripts/droplab/plugins/filter.js39
-rw-r--r--app/assets/javascripts/droplab/plugins/input_setter.js4
-rw-r--r--app/assets/javascripts/droplab/utils.js15
-rw-r--r--app/assets/javascripts/dropzone_input.js41
-rw-r--r--app/assets/javascripts/due_date_select.js10
-rw-r--r--app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js55
-rw-r--r--app/assets/javascripts/environments/components/container.vue72
-rw-r--r--app/assets/javascripts/environments/components/empty_state.vue69
-rw-r--r--app/assets/javascripts/environments/components/environment_actions.vue53
-rw-r--r--app/assets/javascripts/environments/components/environment_external_url.vue9
-rw-r--r--app/assets/javascripts/environments/components/environment_item.vue207
-rw-r--r--app/assets/javascripts/environments/components/environment_monitoring.vue15
-rw-r--r--app/assets/javascripts/environments/components/environment_rollback.vue22
-rw-r--r--app/assets/javascripts/environments/components/environment_stop.vue16
-rw-r--r--app/assets/javascripts/environments/components/environment_terminal_button.vue7
-rw-r--r--app/assets/javascripts/environments/components/environments_app.vue170
-rw-r--r--app/assets/javascripts/environments/components/environments_table.vue70
-rw-r--r--app/assets/javascripts/environments/components/stop_environment_modal.vue24
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_bundle.js57
-rw-r--r--app/assets/javascripts/environments/folder/environments_folder_view.vue85
-rw-r--r--app/assets/javascripts/environments/index.js65
-rw-r--r--app/assets/javascripts/environments/mixins/environments_mixin.js20
-rw-r--r--app/assets/javascripts/environments/stores/environments_store.js30
-rw-r--r--app/assets/javascripts/experimental_flags.js2
-rw-r--r--app/assets/javascripts/feature_highlight/feature_highlight.js16
-rw-r--r--app/assets/javascripts/feature_highlight/feature_highlight_helper.js18
-rw-r--r--app/assets/javascripts/files_comment_button.js14
-rw-r--r--app/assets/javascripts/filterable_list.js25
-rw-r--r--app/assets/javascripts/filtered_search/admin_runners_filtered_search_token_keys.js26
-rw-r--r--app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue33
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_emoji.js26
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_hint.js25
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_non_user.js8
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_user.js7
-rw-r--r--app/assets/javascripts/filtered_search/dropdown_utils.js58
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_dropdown.js14
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js41
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js145
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_token_keys.js55
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_tokenizer.js63
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js156
-rw-r--r--app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js157
-rw-r--r--app/assets/javascripts/filtered_search/recent_searches_root.js11
-rw-r--r--app/assets/javascripts/filtered_search/stores/recent_searches_store.js13
-rw-r--r--app/assets/javascripts/flash.js46
-rw-r--r--app/assets/javascripts/fly_out_nav.js52
-rw-r--r--app/assets/javascripts/frequent_items/components/app.vue11
-rw-r--r--app/assets/javascripts/frequent_items/components/frequent_items_list.vue6
-rw-r--r--app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue33
-rw-r--r--app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue11
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js141
-rw-r--r--app/assets/javascripts/gl_dropdown.js2
-rw-r--r--app/assets/javascripts/gl_field_error.js3
-rw-r--r--app/assets/javascripts/gl_field_errors.js16
-rw-r--r--app/assets/javascripts/gl_form.js19
-rw-r--r--app/assets/javascripts/group.js12
-rw-r--r--app/assets/javascripts/group_avatar.js5
-rw-r--r--app/assets/javascripts/group_label_subscription.js10
-rw-r--r--app/assets/javascripts/groups/components/app.vue2
-rw-r--r--app/assets/javascripts/groups/components/group_folder.vue15
-rw-r--r--app/assets/javascripts/groups/components/group_item.vue81
-rw-r--r--app/assets/javascripts/groups/components/groups.vue16
-rw-r--r--app/assets/javascripts/groups/components/item_actions.vue14
-rw-r--r--app/assets/javascripts/groups/components/item_caret.vue7
-rw-r--r--app/assets/javascripts/groups/components/item_stats.vue82
-rw-r--r--app/assets/javascripts/groups/components/item_stats_value.vue94
-rw-r--r--app/assets/javascripts/groups/components/item_type_icon.vue4
-rw-r--r--app/assets/javascripts/groups/index.js3
-rw-r--r--app/assets/javascripts/groups/new_group_child.js22
-rw-r--r--app/assets/javascripts/groups/store/groups_store.js23
-rw-r--r--app/assets/javascripts/groups/transfer_dropdown.js2
-rw-r--r--app/assets/javascripts/groups_select.js16
-rw-r--r--app/assets/javascripts/header.js56
-rw-r--r--app/assets/javascripts/helpers/avatar_helper.js4
-rw-r--r--app/assets/javascripts/ide/components/activity_bar.vue24
-rw-r--r--app/assets/javascripts/ide/components/branches/item.vue24
-rw-r--r--app/assets/javascripts/ide/components/branches/search_list.vue31
-rw-r--r--app/assets/javascripts/ide/components/changed_file_icon.vue90
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/actions.vue6
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue18
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/empty_state.vue20
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/form.vue30
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list.vue58
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue36
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/list_item.vue17
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/message_field.vue43
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue19
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/stage_button.vue26
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/success_message.vue20
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/unstage_button.vue13
-rw-r--r--app/assets/javascripts/ide/components/editor_mode_dropdown.vue20
-rw-r--r--app/assets/javascripts/ide/components/error_message.vue19
-rw-r--r--app/assets/javascripts/ide/components/external_link.vue11
-rw-r--r--app/assets/javascripts/ide/components/file_finder/index.vue36
-rw-r--r--app/assets/javascripts/ide/components/file_finder/item.vue31
-rw-r--r--app/assets/javascripts/ide/components/file_row_extra.vue11
-rw-r--r--app/assets/javascripts/ide/components/file_templates/bar.vue15
-rw-r--r--app/assets/javascripts/ide/components/file_templates/dropdown.vue43
-rw-r--r--app/assets/javascripts/ide/components/ide.vue71
-rw-r--r--app/assets/javascripts/ide/components/ide_project_header.vue14
-rw-r--r--app/assets/javascripts/ide/components/ide_review.vue15
-rw-r--r--app/assets/javascripts/ide/components/ide_side_bar.vue39
-rw-r--r--app/assets/javascripts/ide/components/ide_status_bar.vue60
-rw-r--r--app/assets/javascripts/ide/components/ide_tree.vue14
-rw-r--r--app/assets/javascripts/ide/components/ide_tree_list.vue25
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail.vue37
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail/description.vue19
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue4
-rw-r--r--app/assets/javascripts/ide/components/jobs/item.vue12
-rw-r--r--app/assets/javascripts/ide/components/jobs/list.vue8
-rw-r--r--app/assets/javascripts/ide/components/jobs/stage.vue45
-rw-r--r--app/assets/javascripts/ide/components/merge_requests/info.vue9
-rw-r--r--app/assets/javascripts/ide/components/merge_requests/item.vue19
-rw-r--r--app/assets/javascripts/ide/components/merge_requests/list.vue48
-rw-r--r--app/assets/javascripts/ide/components/nav_dropdown.vue13
-rw-r--r--app/assets/javascripts/ide/components/nav_dropdown_button.vue29
-rw-r--r--app/assets/javascripts/ide/components/nav_form.vue12
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/button.vue5
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/index.vue29
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/modal.vue23
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/upload.vue38
-rw-r--r--app/assets/javascripts/ide/components/panes/right.vue138
-rw-r--r--app/assets/javascripts/ide/components/pipelines/list.vue91
-rw-r--r--app/assets/javascripts/ide/components/preview/clientside.vue23
-rw-r--r--app/assets/javascripts/ide/components/preview/navigator.vue29
-rw-r--r--app/assets/javascripts/ide/components/repo_commit_section.vue22
-rw-r--r--app/assets/javascripts/ide/components/repo_editor.vue54
-rw-r--r--app/assets/javascripts/ide/components/repo_file_status_icon.vue12
-rw-r--r--app/assets/javascripts/ide/components/repo_loading_file.vue42
-rw-r--r--app/assets/javascripts/ide/components/repo_tab.vue33
-rw-r--r--app/assets/javascripts/ide/components/repo_tabs.vue11
-rw-r--r--app/assets/javascripts/ide/components/resizable_panel.vue4
-rw-r--r--app/assets/javascripts/ide/components/shared/tokened_input.vue31
-rw-r--r--app/assets/javascripts/ide/constants.js8
-rw-r--r--app/assets/javascripts/ide/index.js39
-rw-r--r--app/assets/javascripts/ide/lib/diff/diff.js14
-rw-r--r--app/assets/javascripts/ide/lib/diff/diff_worker.js2
-rw-r--r--app/assets/javascripts/ide/services/index.js6
-rw-r--r--app/assets/javascripts/ide/stores/actions.js4
-rw-r--r--app/assets/javascripts/ide/stores/actions/file.js13
-rw-r--r--app/assets/javascripts/ide/stores/actions/merge_request.js101
-rw-r--r--app/assets/javascripts/ide/stores/actions/project.js38
-rw-r--r--app/assets/javascripts/ide/stores/actions/tree.js2
-rw-r--r--app/assets/javascripts/ide/stores/getters.js2
-rw-r--r--app/assets/javascripts/ide/stores/index.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/actions.js6
-rw-r--r--app/assets/javascripts/ide/stores/modules/file_templates/actions.js23
-rw-r--r--app/assets/javascripts/ide/stores/modules/file_templates/mutations.js3
-rw-r--r--app/assets/javascripts/ide/stores/modules/merge_requests/actions.js15
-rw-r--r--app/assets/javascripts/ide/stores/modules/pane/actions.js30
-rw-r--r--app/assets/javascripts/ide/stores/modules/pane/getters.js4
-rw-r--r--app/assets/javascripts/ide/stores/modules/pane/index.js12
-rw-r--r--app/assets/javascripts/ide/stores/modules/pane/mutation_types.js3
-rw-r--r--app/assets/javascripts/ide/stores/modules/pane/mutations.js19
-rw-r--r--app/assets/javascripts/ide/stores/modules/pane/state.js5
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/actions.js8
-rw-r--r--app/assets/javascripts/ide/stores/modules/pipelines/getters.js10
-rw-r--r--app/assets/javascripts/ide/stores/mutation_types.js2
-rw-r--r--app/assets/javascripts/ide/stores/mutations.js5
-rw-r--r--app/assets/javascripts/ide/stores/state.js1
-rw-r--r--app/assets/javascripts/image_diff/image_diff.js6
-rw-r--r--app/assets/javascripts/image_diff/init_discussion_tab.js3
-rw-r--r--app/assets/javascripts/image_diff/replaced_image_diff.js15
-rw-r--r--app/assets/javascripts/importer_status.js126
-rw-r--r--app/assets/javascripts/init_changes_dropdown.js2
-rw-r--r--app/assets/javascripts/init_legacy_filters.js14
-rw-r--r--app/assets/javascripts/init_notes.js8
-rw-r--r--app/assets/javascripts/integrations/integration_settings_form.js5
-rw-r--r--app/assets/javascripts/issuable/auto_width_dropdown_select.js5
-rw-r--r--app/assets/javascripts/issuable_bulk_update_actions.js12
-rw-r--r--app/assets/javascripts/issuable_form.js34
-rw-r--r--app/assets/javascripts/issuable_index.js9
-rw-r--r--app/assets/javascripts/issuable_suggestions/components/app.vue96
-rw-r--r--app/assets/javascripts/issuable_suggestions/components/item.vue137
-rw-r--r--app/assets/javascripts/issuable_suggestions/index.js38
-rw-r--r--app/assets/javascripts/issuable_suggestions/queries/issues.graphql26
-rw-r--r--app/assets/javascripts/issue.js75
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue523
-rw-r--r--app/assets/javascripts/issue_show/components/description.vue195
-rw-r--r--app/assets/javascripts/issue_show/components/edit_actions.vue125
-rw-r--r--app/assets/javascripts/issue_show/components/edited.vue70
-rw-r--r--app/assets/javascripts/issue_show/components/fields/description.vue86
-rw-r--r--app/assets/javascripts/issue_show/components/fields/description_template.vue128
-rw-r--r--app/assets/javascripts/issue_show/components/fields/title.vue29
-rw-r--r--app/assets/javascripts/issue_show/components/form.vue148
-rw-r--r--app/assets/javascripts/issue_show/components/locked_warning.vue19
-rw-r--r--app/assets/javascripts/issue_show/components/title.vue13
-rw-r--r--app/assets/javascripts/issue_show/index.js7
-rw-r--r--app/assets/javascripts/issue_show/stores/index.js6
-rw-r--r--app/assets/javascripts/job.js213
-rw-r--r--app/assets/javascripts/jobs/components/artifacts_block.vue110
-rw-r--r--app/assets/javascripts/jobs/components/commit_block.vue54
-rw-r--r--app/assets/javascripts/jobs/components/empty_state.vue100
-rw-r--r--app/assets/javascripts/jobs/components/environments_block.vue201
-rw-r--r--app/assets/javascripts/jobs/components/erased_block.vue37
-rw-r--r--app/assets/javascripts/jobs/components/header.vue95
-rw-r--r--app/assets/javascripts/jobs/components/job_app.vue297
-rw-r--r--app/assets/javascripts/jobs/components/job_container_item.vue68
-rw-r--r--app/assets/javascripts/jobs/components/job_log.vue56
-rw-r--r--app/assets/javascripts/jobs/components/job_log_controllers.vue187
-rw-r--r--app/assets/javascripts/jobs/components/jobs_container.vue77
-rw-r--r--app/assets/javascripts/jobs/components/sidebar.vue239
-rw-r--r--app/assets/javascripts/jobs/components/sidebar_detail_row.vue81
-rw-r--r--app/assets/javascripts/jobs/components/sidebar_details_block.vue239
-rw-r--r--app/assets/javascripts/jobs/components/stages_dropdown.vue135
-rw-r--r--app/assets/javascripts/jobs/components/stuck_block.vue57
-rw-r--r--app/assets/javascripts/jobs/components/trigger_block.vue93
-rw-r--r--app/assets/javascripts/jobs/index.js25
-rw-r--r--app/assets/javascripts/jobs/job_details_bundle.js62
-rw-r--r--app/assets/javascripts/jobs/job_details_mediator.js67
-rw-r--r--app/assets/javascripts/jobs/mixins/delayed_job_mixin.js50
-rw-r--r--app/assets/javascripts/jobs/services/job_service.js11
-rw-r--r--app/assets/javascripts/jobs/store/actions.js150
-rw-r--r--app/assets/javascripts/jobs/store/getters.js53
-rw-r--r--app/assets/javascripts/jobs/store/index.js13
-rw-r--r--app/assets/javascripts/jobs/store/mutation_types.js19
-rw-r--r--app/assets/javascripts/jobs/store/mutations.js80
-rw-r--r--app/assets/javascripts/jobs/store/state.js31
-rw-r--r--app/assets/javascripts/jobs/stores/job_store.js11
-rw-r--r--app/assets/javascripts/jobs/svg/scroll_down.svg5
-rw-r--r--app/assets/javascripts/label_manager.js16
-rw-r--r--app/assets/javascripts/labels.js2
-rw-r--r--app/assets/javascripts/labels_select.js255
-rw-r--r--app/assets/javascripts/landing.js3
-rw-r--r--app/assets/javascripts/layout_nav.js60
-rw-r--r--app/assets/javascripts/lazy_loader.js115
-rw-r--r--app/assets/javascripts/lib/ace.js1
-rw-r--r--app/assets/javascripts/lib/graphql.js9
-rw-r--r--app/assets/javascripts/lib/utils/ace_utils.js6
-rw-r--r--app/assets/javascripts/lib/utils/ajax_cache.js7
-rw-r--r--app/assets/javascripts/lib/utils/axios_utils.js23
-rw-r--r--app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js10
-rw-r--r--app/assets/javascripts/lib/utils/cache.js2
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js65
-rw-r--r--app/assets/javascripts/lib/utils/datefix.js29
-rw-r--r--app/assets/javascripts/lib/utils/datetime_utility.js149
-rw-r--r--app/assets/javascripts/lib/utils/logoutput_behaviours.js17
-rw-r--r--app/assets/javascripts/lib/utils/notify.js6
-rw-r--r--app/assets/javascripts/lib/utils/number_utils.js2
-rw-r--r--app/assets/javascripts/lib/utils/pretty_time.js61
-rw-r--r--app/assets/javascripts/lib/utils/regexp.js3
-rw-r--r--app/assets/javascripts/lib/utils/scroll_utils.js24
-rw-r--r--app/assets/javascripts/lib/utils/simple_poll.js2
-rw-r--r--app/assets/javascripts/lib/utils/sticky.js24
-rw-r--r--app/assets/javascripts/lib/utils/text_markdown.js108
-rw-r--r--app/assets/javascripts/lib/utils/text_utility.js22
-rw-r--r--app/assets/javascripts/lib/utils/tick_formats.js2
-rw-r--r--app/assets/javascripts/lib/utils/url_utility.js38
-rw-r--r--app/assets/javascripts/lib/utils/users_cache.js25
-rw-r--r--app/assets/javascripts/line_highlighter.js30
-rw-r--r--app/assets/javascripts/locale/sprintf.js2
-rw-r--r--app/assets/javascripts/main.js1
-rw-r--r--app/assets/javascripts/member_expiration_date.js10
-rw-r--r--app/assets/javascripts/members.js10
-rw-r--r--app/assets/javascripts/merge_conflicts/components/diff_file_editor.js22
-rw-r--r--app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js2
-rw-r--r--app/assets/javascripts/merge_conflicts/merge_conflict_store.js53
-rw-r--r--app/assets/javascripts/merge_request.js25
-rw-r--r--app/assets/javascripts/merge_request_tabs.js55
-rw-r--r--app/assets/javascripts/milestone.js34
-rw-r--r--app/assets/javascripts/milestone_select.js12
-rw-r--r--app/assets/javascripts/mini_pipeline_graph_dropdown.js17
-rw-r--r--app/assets/javascripts/mirrors/constants.js4
-rw-r--r--app/assets/javascripts/mirrors/mirror_repos.js109
-rw-r--r--app/assets/javascripts/mirrors/ssh_mirror.js299
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue69
-rw-r--r--app/assets/javascripts/monitoring/components/empty_state.vue61
-rw-r--r--app/assets/javascripts/monitoring/components/graph.vue111
-rw-r--r--app/assets/javascripts/monitoring/components/graph/axis.vue36
-rw-r--r--app/assets/javascripts/monitoring/components/graph/deployment.vue41
-rw-r--r--app/assets/javascripts/monitoring/components/graph/flag.vue59
-rw-r--r--app/assets/javascripts/monitoring/components/graph/legend.vue20
-rw-r--r--app/assets/javascripts/monitoring/components/graph/path.vue6
-rw-r--r--app/assets/javascripts/monitoring/components/graph/track_info.vue1
-rw-r--r--app/assets/javascripts/monitoring/components/graph/track_line.vue5
-rw-r--r--app/assets/javascripts/monitoring/components/graph_group.vue16
-rw-r--r--app/assets/javascripts/monitoring/mixins/monitoring_mixins.js4
-rw-r--r--app/assets/javascripts/monitoring/monitoring_bundle.js4
-rw-r--r--app/assets/javascripts/monitoring/services/monitoring_service.js49
-rw-r--r--app/assets/javascripts/monitoring/stores/monitoring_store.js34
-rw-r--r--app/assets/javascripts/monitoring/utils/measurements.js6
-rw-r--r--app/assets/javascripts/monitoring/utils/multiple_time_series.js108
-rw-r--r--app/assets/javascripts/mr_notes/index.js2
-rw-r--r--app/assets/javascripts/mr_notes/stores/index.js17
-rw-r--r--app/assets/javascripts/namespace_select.js13
-rw-r--r--app/assets/javascripts/network/branch_graph.js164
-rw-r--r--app/assets/javascripts/network/raphael.js2
-rw-r--r--app/assets/javascripts/new_branch_form.js16
-rw-r--r--app/assets/javascripts/new_commit_form.js4
-rw-r--r--app/assets/javascripts/notebook/cells/code.vue6
-rw-r--r--app/assets/javascripts/notebook/cells/code/index.vue83
-rw-r--r--app/assets/javascripts/notebook/cells/markdown.vue134
-rw-r--r--app/assets/javascripts/notebook/cells/output/html.vue44
-rw-r--r--app/assets/javascripts/notebook/cells/output/image.vue33
-rw-r--r--app/assets/javascripts/notebook/cells/output/index.vue128
-rw-r--r--app/assets/javascripts/notebook/cells/prompt.vue48
-rw-r--r--app/assets/javascripts/notebook/index.vue84
-rw-r--r--app/assets/javascripts/notes.js10
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue282
-rw-r--r--app/assets/javascripts/notes/components/diff_file_header.vue94
-rw-r--r--app/assets/javascripts/notes/components/diff_with_note.vue156
-rw-r--r--app/assets/javascripts/notes/components/discussion_counter.vue79
-rw-r--r--app/assets/javascripts/notes/components/discussion_filter.vue90
-rw-r--r--app/assets/javascripts/notes/components/discussion_locked_widget.vue6
-rw-r--r--app/assets/javascripts/notes/components/note_actions.vue142
-rw-r--r--app/assets/javascripts/notes/components/note_attachment.vue23
-rw-r--r--app/assets/javascripts/notes/components/note_awards_list.vue81
-rw-r--r--app/assets/javascripts/notes/components/note_body.vue31
-rw-r--r--app/assets/javascripts/notes/components/note_edited_text.vue12
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue75
-rw-r--r--app/assets/javascripts/notes/components/note_header.vue72
-rw-r--r--app/assets/javascripts/notes/components/note_signed_out_widget.vue6
-rw-r--r--app/assets/javascripts/notes/components/noteable_discussion.vue430
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue121
-rw-r--r--app/assets/javascripts/notes/components/notes_app.vue133
-rw-r--r--app/assets/javascripts/notes/components/toggle_replies_widget.vue73
-rw-r--r--app/assets/javascripts/notes/constants.js2
-rw-r--r--app/assets/javascripts/notes/discussion_filters.js35
-rw-r--r--app/assets/javascripts/notes/index.js3
-rw-r--r--app/assets/javascripts/notes/mixins/resolvable.js2
-rw-r--r--app/assets/javascripts/notes/services/notes_service.js5
-rw-r--r--app/assets/javascripts/notes/stores/actions.js109
-rw-r--r--app/assets/javascripts/notes/stores/collapse_utils.js7
-rw-r--r--app/assets/javascripts/notes/stores/getters.js73
-rw-r--r--app/assets/javascripts/notes/stores/index.js3
-rw-r--r--app/assets/javascripts/notes/stores/modules/index.js5
-rw-r--r--app/assets/javascripts/notes/stores/mutation_types.js3
-rw-r--r--app/assets/javascripts/notes/stores/mutations.js49
-rw-r--r--app/assets/javascripts/notes/stores/utils.js12
-rw-r--r--app/assets/javascripts/notifications_dropdown.js4
-rw-r--r--app/assets/javascripts/notifications_form.js10
-rw-r--r--app/assets/javascripts/pager.js44
-rw-r--r--app/assets/javascripts/pages/admin/abuse_reports/abuse_reports.js5
-rw-r--r--app/assets/javascripts/pages/admin/admin.js15
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/account_and_limits.js8
-rw-r--r--app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js36
-rw-r--r--app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue65
-rw-r--r--app/assets/javascripts/pages/admin/projects/index.js3
-rw-r--r--app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue163
-rw-r--r--app/assets/javascripts/pages/admin/projects/index/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue216
-rw-r--r--app/assets/javascripts/pages/admin/users/index.js6
-rw-r--r--app/assets/javascripts/pages/admin/users/new/index.js6
-rw-r--r--app/assets/javascripts/pages/dashboard/issues/index.js10
-rw-r--r--app/assets/javascripts/pages/dashboard/merge_requests/index.js12
-rw-r--r--app/assets/javascripts/pages/dashboard/todos/index/todos.js25
-rw-r--r--app/assets/javascripts/pages/groups/clusters/destroy/index.js5
-rw-r--r--app/assets/javascripts/pages/groups/clusters/index/index.js7
-rw-r--r--app/assets/javascripts/pages/groups/clusters/show/index.js5
-rw-r--r--app/assets/javascripts/pages/groups/clusters/update/index.js5
-rw-r--r--app/assets/javascripts/pages/groups/edit/index.js11
-rw-r--r--app/assets/javascripts/pages/groups/index.js22
-rw-r--r--app/assets/javascripts/pages/groups/merge_requests/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js2
-rw-r--r--app/assets/javascripts/pages/ide/index.js10
-rw-r--r--app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue178
-rw-r--r--app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue103
-rw-r--r--app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js16
-rw-r--r--app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js16
-rw-r--r--app/assets/javascripts/pages/profiles/index.js7
-rw-r--r--app/assets/javascripts/pages/profiles/show/index.js4
-rw-r--r--app/assets/javascripts/pages/profiles/two_factor_auths/index.js7
-rw-r--r--app/assets/javascripts/pages/projects/branches/new/index.js11
-rw-r--r--app/assets/javascripts/pages/projects/clusters/gcp/new/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/clusters/index/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/commit/show/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/graphs/charts/index.js22
-rw-r--r--app/assets/javascripts/pages/projects/graphs/show/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors.js93
-rw-r--r--app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js223
-rw-r--r--app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js66
-rw-r--r--app/assets/javascripts/pages/projects/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/init_blob.js3
-rw-r--r--app/assets/javascripts/pages/projects/init_form.js2
-rw-r--r--app/assets/javascripts/pages/projects/issues/form.js5
-rw-r--r--app/assets/javascripts/pages/projects/issues/show.js5
-rw-r--r--app/assets/javascripts/pages/projects/jobs/index/index.js16
-rw-r--r--app/assets/javascripts/pages/projects/jobs/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue132
-rw-r--r--app/assets/javascripts/pages/projects/labels/index/index.js16
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/index/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/network/network.js12
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js22
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue140
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue84
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js3
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js4
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/charts/index.js59
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/index/index.js68
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/init_pipelines.js7
-rw-r--r--app/assets/javascripts/pages/projects/project.js7
-rw-r--r--app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/settings/repository/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/settings/repository/show/mirror_repos.js94
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue132
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue62
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue387
-rw-r--r--app/assets/javascripts/pages/projects/shared/permissions/constants.js6
-rw-r--r--app/assets/javascripts/pages/projects/shared/project_avatar.js5
-rw-r--r--app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue39
-rw-r--r--app/assets/javascripts/pages/projects/wikis/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/wikis/wikis.js4
-rw-r--r--app/assets/javascripts/pages/root/index.js5
-rw-r--r--app/assets/javascripts/pages/search/show/search.js25
-rw-r--r--app/assets/javascripts/pages/sessions/new/signin_tabs_memoizer.js2
-rw-r--r--app/assets/javascripts/pages/sessions/new/username_validator.js12
-rw-r--r--app/assets/javascripts/pages/snippets/form.js1
-rw-r--r--app/assets/javascripts/pages/users/activity_calendar.js31
-rw-r--r--app/assets/javascripts/pages/users/index.js6
-rw-r--r--app/assets/javascripts/pages/users/user_overview_block.js52
-rw-r--r--app/assets/javascripts/pages/users/user_tabs.js103
-rw-r--r--app/assets/javascripts/pdf/index.vue107
-rw-r--r--app/assets/javascripts/pdf/page/index.vue110
-rw-r--r--app/assets/javascripts/performance_bar/components/detailed_metric.vue36
-rw-r--r--app/assets/javascripts/performance_bar/components/performance_bar_app.vue64
-rw-r--r--app/assets/javascripts/performance_bar/components/request_selector.vue6
-rw-r--r--app/assets/javascripts/performance_bar/components/simple_metric.vue27
-rw-r--r--app/assets/javascripts/performance_bar/index.js3
-rw-r--r--app/assets/javascripts/performance_bar/services/performance_bar_service.js15
-rw-r--r--app/assets/javascripts/performance_bar/stores/performance_bar_store.js4
-rw-r--r--app/assets/javascripts/persistent_user_callout.js34
-rw-r--r--app/assets/javascripts/pipelines/components/blank_state.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/empty_state.vue33
-rw-r--r--app/assets/javascripts/pipelines/components/graph/action_component.vue26
-rw-r--r--app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue122
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component.vue22
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_component.vue140
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue92
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_item.vue134
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_name_component.vue4
-rw-r--r--app/assets/javascripts/pipelines/components/graph/stage_column_component.vue52
-rw-r--r--app/assets/javascripts/pipelines/components/header_component.vue8
-rw-r--r--app/assets/javascripts/pipelines/components/nav_controls.vue20
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_url.vue51
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines.vue67
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_actions.vue64
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_artifacts.vue43
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_table.vue36
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_table_row.vue51
-rw-r--r--app/assets/javascripts/pipelines/components/stage.vue39
-rw-r--r--app/assets/javascripts/pipelines/components/time_ago.vue31
-rw-r--r--app/assets/javascripts/pipelines/mixins/pipelines.js40
-rw-r--r--app/assets/javascripts/profile/account/components/delete_account_modal.vue159
-rw-r--r--app/assets/javascripts/profile/account/components/update_username.vue8
-rw-r--r--app/assets/javascripts/profile/gl_crop.js49
-rw-r--r--app/assets/javascripts/profile/profile.js9
-rw-r--r--app/assets/javascripts/project_find_file.js97
-rw-r--r--app/assets/javascripts/project_import.js1
-rw-r--r--app/assets/javascripts/project_label_subscription.js43
-rw-r--r--app/assets/javascripts/project_select.js56
-rw-r--r--app/assets/javascripts/project_select_combo_button.js27
-rw-r--r--app/assets/javascripts/project_visibility.js5
-rw-r--r--app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_dropdown_mixin.js2
-rw-r--r--app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue27
-rw-r--r--app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue31
-rw-r--r--app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown.vue25
-rw-r--r--app/assets/javascripts/projects/project_new.js46
-rw-r--r--app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue13
-rw-r--r--app/assets/javascripts/prometheus_metrics/prometheus_metrics.js36
-rw-r--r--app/assets/javascripts/protected_branches/protected_branch_create.js8
-rw-r--r--app/assets/javascripts/protected_branches/protected_branch_edit.js59
-rw-r--r--app/assets/javascripts/protected_tags/protected_tag_create.js4
-rw-r--r--app/assets/javascripts/protected_tags/protected_tag_edit.js37
-rw-r--r--app/assets/javascripts/raven/raven_config.js2
-rw-r--r--app/assets/javascripts/ref_select_dropdown.js5
-rw-r--r--app/assets/javascripts/registry/components/app.vue78
-rw-r--r--app/assets/javascripts/registry/components/collapsible_container.vue139
-rw-r--r--app/assets/javascripts/registry/components/table_registry.vue133
-rw-r--r--app/assets/javascripts/registry/index.js39
-rw-r--r--app/assets/javascripts/registry/stores/mutations.js1
-rw-r--r--app/assets/javascripts/reports/components/grouped_test_reports_app.vue147
-rw-r--r--app/assets/javascripts/reports/components/issue_status_icon.vue11
-rw-r--r--app/assets/javascripts/reports/components/issues_list.vue89
-rw-r--r--app/assets/javascripts/reports/components/modal.vue59
-rw-r--r--app/assets/javascripts/reports/components/modal_open_name.vue2
-rw-r--r--app/assets/javascripts/reports/components/report_issues.vue59
-rw-r--r--app/assets/javascripts/reports/components/report_item.vue41
-rw-r--r--app/assets/javascripts/reports/components/report_link.vue10
-rw-r--r--app/assets/javascripts/reports/components/report_section.vue14
-rw-r--r--app/assets/javascripts/reports/components/summary_row.vue22
-rw-r--r--app/assets/javascripts/reports/components/test_issue_body.vue52
-rw-r--r--app/assets/javascripts/reports/store/actions.js8
-rw-r--r--app/assets/javascripts/reports/store/index.js13
-rw-r--r--app/assets/javascripts/reports/store/mutation_types.js1
-rw-r--r--app/assets/javascripts/reports/store/mutations.js3
-rw-r--r--app/assets/javascripts/reports/store/state.js1
-rw-r--r--app/assets/javascripts/right_sidebar.js61
-rw-r--r--app/assets/javascripts/search_autocomplete.js17
-rw-r--r--app/assets/javascripts/set_status_modal/emoji_menu_in_modal.js21
-rw-r--r--app/assets/javascripts/set_status_modal/event_hub.js3
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_trigger.vue27
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue231
-rw-r--r--app/assets/javascripts/settings_panels.js16
-rw-r--r--app/assets/javascripts/shared/milestones/form.js1
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignee_title.vue21
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignees.vue61
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue3
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue26
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/edit_form.vue10
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue12
-rw-r--r--app/assets/javascripts/sidebar/components/lock/edit_form.vue17
-rw-r--r--app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue12
-rw-r--r--app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue55
-rw-r--r--app/assets/javascripts/sidebar/components/participants/participants.vue162
-rw-r--r--app/assets/javascripts/sidebar/components/participants/sidebar_participants.vue34
-rw-r--r--app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue7
-rw-r--r--app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue133
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue196
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue27
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/estimate_only_pane.vue5
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/help_state.vue35
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/no_tracking_pane.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue14
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/spent_only_pane.vue3
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue76
-rw-r--r--app/assets/javascripts/sidebar/components/todo_toggle/todo.vue20
-rw-r--r--app/assets/javascripts/sidebar/lib/sidebar_move_issue.js20
-rw-r--r--app/assets/javascripts/sidebar/mount_milestone_sidebar.js21
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js39
-rw-r--r--app/assets/javascripts/sidebar/services/sidebar_service.js14
-rw-r--r--app/assets/javascripts/sidebar/sidebar_mediator.js20
-rw-r--r--app/assets/javascripts/single_file_diff.js34
-rw-r--r--app/assets/javascripts/smart_interval.js20
-rw-r--r--app/assets/javascripts/star.js12
-rw-r--r--app/assets/javascripts/task_list.js9
-rw-r--r--app/assets/javascripts/templates/issuable_template_selector.js20
-rw-r--r--app/assets/javascripts/terminal/terminal.js12
-rw-r--r--app/assets/javascripts/test_utils/simulate_drag.js56
-rw-r--r--app/assets/javascripts/test_utils/simulate_input.js2
-rw-r--r--app/assets/javascripts/toggle_buttons.js8
-rw-r--r--app/assets/javascripts/tree.js20
-rw-r--r--app/assets/javascripts/u2f/authenticate.js14
-rw-r--r--app/assets/javascripts/u2f/register.js13
-rw-r--r--app/assets/javascripts/u2f/util.js5
-rw-r--r--app/assets/javascripts/ui_development_kit.js18
-rw-r--r--app/assets/javascripts/usage_ping_consent.js11
-rw-r--r--app/assets/javascripts/users_select.js1101
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment.vue131
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/memory_usage.vue54
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue68
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author_time.vue60
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_container.vue6
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue107
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_icon.vue17
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.vue40
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue149
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue74
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue60
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue67
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/review_app_link.vue24
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue40
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue28
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue65
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue23
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue45
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue56
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue34
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue185
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue233
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue32
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue87
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.vue25
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue25
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue176
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_squash_before_merge.js15
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_squash_before_merge.vue63
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue17
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue11
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue104
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue11
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue61
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue9
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue24
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/dependencies.js47
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/ee_switch_mr_widget_options.js3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/index.js5
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue229
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/services/ee_switch_mr_widget_service.js3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_get_state_key.js3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_mr_widget_store.js3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_state_maps.js3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js5
-rw-r--r--app/assets/javascripts/vue_shared/components/bar_chart.vue97
-rw-r--r--app/assets/javascripts/vue_shared/components/callout.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/changed_file_icon.vue101
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_badge_link.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_icon.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/clipboard_button.vue18
-rw-r--r--app/assets/javascripts/vue_shared/components/commit.vue53
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue17
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue72
-rw-r--r--app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue15
-rw-r--r--app/assets/javascripts/vue_shared/components/deprecated_modal.vue202
-rw-r--r--app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue9
-rw-r--r--app/assets/javascripts/vue_shared/components/diff_viewer/viewers/download_diff_viewer.vue32
-rw-r--r--app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/onion_skin_viewer.vue46
-rw-r--r--app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue71
-rw-r--r--app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/two_up_viewer.vue33
-rw-r--r--app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue93
-rw-r--r--app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue31
-rw-r--r--app/assets/javascripts/vue_shared/components/dropdown/dropdown_hidden_input.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/dropdown/dropdown_search_input.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/expand_button.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/file_icon.vue21
-rw-r--r--app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js5
-rw-r--r--app/assets/javascripts/vue_shared/components/file_row.vue70
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue122
-rw-r--r--app/assets/javascripts/vue_shared/components/gl_countdown.vue47
-rw-r--r--app/assets/javascripts/vue_shared/components/gl_modal.vue39
-rw-r--r--app/assets/javascripts/vue_shared/components/header_ci_component.vue92
-rw-r--r--app/assets/javascripts/vue_shared/components/help_popover.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/icon.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/identicon.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/issue/issue_warning.vue67
-rw-r--r--app/assets/javascripts/vue_shared/components/loading_button.vue76
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/field.vue295
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/header.vue162
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar.vue130
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue74
-rw-r--r--app/assets/javascripts/vue_shared/components/memory_graph.vue18
-rw-r--r--app/assets/javascripts/vue_shared/components/navigation_tabs.vue13
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue114
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/placeholder_system_note.vue47
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue31
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/system_note.vue66
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/timeline_entry_item.vue11
-rw-r--r--app/assets/javascripts/vue_shared/components/pagination_links.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/panel_resizer.vue156
-rw-r--r--app/assets/javascripts/vue_shared/components/pikaday.vue123
-rw-r--r--app/assets/javascripts/vue_shared/components/project_avatar/default.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/project_avatar/image.vue125
-rw-r--r--app/assets/javascripts/vue_shared/components/recaptcha_modal.vue104
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue73
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue156
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue229
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue28
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button.vue11
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue24
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer.vue13
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue14
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/toggle_sidebar.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/skeleton_loading_container.vue37
-rw-r--r--app/assets/javascripts/vue_shared/components/smart_virtual_list.vue33
-rw-r--r--app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue18
-rw-r--r--app/assets/javascripts/vue_shared/components/svg_gradient.vue17
-rw-r--r--app/assets/javascripts/vue_shared/components/table_pagination.vue218
-rw-r--r--app/assets/javascripts/vue_shared/components/tabs/tab.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue17
-rw-r--r--app/assets/javascripts/vue_shared/components/toggle_button.vue111
-rw-r--r--app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue8
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue51
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue22
-rw-r--r--app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_svg.vue9
-rw-r--r--app/assets/javascripts/vue_shared/directives/tooltip.js8
-rw-r--r--app/assets/javascripts/vue_shared/mixins/ci_pagination_api_mixin.js28
-rw-r--r--app/assets/javascripts/vue_shared/models/label.js2
-rw-r--r--app/assets/javascripts/vue_shared/translate.js9
-rw-r--r--app/assets/javascripts/vue_shared/vue_resource_interceptor.js2
-rw-r--r--app/assets/javascripts/zen_mode.js34
-rw-r--r--app/assets/stylesheets/application.scss2
-rw-r--r--app/assets/stylesheets/bootstrap.scss2
-rw-r--r--app/assets/stylesheets/bootstrap_migration.scss21
-rw-r--r--app/assets/stylesheets/framework.scss1
-rw-r--r--app/assets/stylesheets/framework/awards.scss5
-rw-r--r--app/assets/stylesheets/framework/blocks.scss11
-rw-r--r--app/assets/stylesheets/framework/buttons.scss46
-rw-r--r--app/assets/stylesheets/framework/calendar.scss12
-rw-r--r--app/assets/stylesheets/framework/callout.scss6
-rw-r--r--app/assets/stylesheets/framework/common.scss27
-rw-r--r--app/assets/stylesheets/framework/contextual_sidebar.scss14
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss26
-rw-r--r--app/assets/stylesheets/framework/files.scss2
-rw-r--r--app/assets/stylesheets/framework/filters.scss16
-rw-r--r--app/assets/stylesheets/framework/flash.scss10
-rw-r--r--app/assets/stylesheets/framework/gfm.scss4
-rw-r--r--app/assets/stylesheets/framework/gitlab_theme.scss1
-rw-r--r--app/assets/stylesheets/framework/header.scss61
-rw-r--r--app/assets/stylesheets/framework/highlight.scss3
-rw-r--r--app/assets/stylesheets/framework/icons.scss13
-rw-r--r--app/assets/stylesheets/framework/images.scss2
-rw-r--r--app/assets/stylesheets/framework/issue_box.scss2
-rw-r--r--app/assets/stylesheets/framework/markdown_area.scss13
-rw-r--r--app/assets/stylesheets/framework/mixins.scss170
-rw-r--r--app/assets/stylesheets/framework/modal.scss13
-rw-r--r--app/assets/stylesheets/framework/page_title.scss18
-rw-r--r--app/assets/stylesheets/framework/panels.scss5
-rw-r--r--app/assets/stylesheets/framework/responsive_tables.scss2
-rw-r--r--app/assets/stylesheets/framework/secondary_navigation_elements.scss24
-rw-r--r--app/assets/stylesheets/framework/selects.scss2
-rw-r--r--app/assets/stylesheets/framework/tables.scss6
-rw-r--r--app/assets/stylesheets/framework/terms.scss15
-rw-r--r--app/assets/stylesheets/framework/timeline.scss16
-rw-r--r--app/assets/stylesheets/framework/typography.scss8
-rw-r--r--app/assets/stylesheets/framework/variables.scss24
-rw-r--r--app/assets/stylesheets/framework/variables_overrides.scss1
-rw-r--r--app/assets/stylesheets/page_bundles/ide.scss23
-rw-r--r--app/assets/stylesheets/pages/boards.scss210
-rw-r--r--app/assets/stylesheets/pages/builds.scss119
-rw-r--r--app/assets/stylesheets/pages/clusters.scss35
-rw-r--r--app/assets/stylesheets/pages/commits.scss3
-rw-r--r--app/assets/stylesheets/pages/cycle_analytics.scss2
-rw-r--r--app/assets/stylesheets/pages/diff.scss212
-rw-r--r--app/assets/stylesheets/pages/editor.scss8
-rw-r--r--app/assets/stylesheets/pages/environments.scss23
-rw-r--r--app/assets/stylesheets/pages/events.scss78
-rw-r--r--app/assets/stylesheets/pages/groups.scss2
-rw-r--r--app/assets/stylesheets/pages/issuable.scss57
-rw-r--r--app/assets/stylesheets/pages/issues.scss23
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss76
-rw-r--r--app/assets/stylesheets/pages/note_form.scss22
-rw-r--r--app/assets/stylesheets/pages/notes.scss441
-rw-r--r--app/assets/stylesheets/pages/pages.scss7
-rw-r--r--app/assets/stylesheets/pages/pipeline_schedules.scss8
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss5
-rw-r--r--app/assets/stylesheets/pages/profile.scss22
-rw-r--r--app/assets/stylesheets/pages/projects.scss41
-rw-r--r--app/assets/stylesheets/pages/settings.scss4
-rw-r--r--app/assets/stylesheets/pages/status.scss1
-rw-r--r--app/assets/stylesheets/pages/tree.scss12
-rw-r--r--app/assets/stylesheets/performance_bar.scss7
-rw-r--r--app/controllers/admin/appearances_controller.rb6
-rw-r--r--app/controllers/admin/application_settings_controller.rb8
-rw-r--r--app/controllers/admin/applications_controller.rb8
-rw-r--r--app/controllers/admin/background_jobs_controller.rb5
-rw-r--r--app/controllers/admin/dashboard_controller.rb4
-rw-r--r--app/controllers/admin/health_check_controller.rb7
-rw-r--r--app/controllers/admin/impersonation_tokens_controller.rb3
-rw-r--r--app/controllers/admin/impersonations_controller.rb13
-rw-r--r--app/controllers/admin/requests_profiles_controller.rb2
-rw-r--r--app/controllers/admin/users_controller.rb5
-rw-r--r--app/controllers/application_controller.rb85
-rw-r--r--app/controllers/autocomplete_controller.rb2
-rw-r--r--app/controllers/boards/issues_controller.rb17
-rw-r--r--app/controllers/chaos_controller.rb56
-rw-r--r--app/controllers/clusters/applications_controller.rb28
-rw-r--r--app/controllers/clusters/base_controller.rb37
-rw-r--r--app/controllers/clusters/clusters_controller.rb218
-rw-r--r--app/controllers/concerns/boards_responses.rb5
-rw-r--r--app/controllers/concerns/invalid_utf8_error_handler.rb27
-rw-r--r--app/controllers/concerns/issuable_actions.rb33
-rw-r--r--app/controllers/concerns/issuable_collections.rb36
-rw-r--r--app/controllers/concerns/labels_as_hash.rb28
-rw-r--r--app/controllers/concerns/members_presentation.rb7
-rw-r--r--app/controllers/concerns/merge_requests_action.rb2
-rw-r--r--app/controllers/concerns/notes_actions.rb75
-rw-r--r--app/controllers/concerns/project_unauthorized.rb10
-rw-r--r--app/controllers/concerns/routable_actions.rb16
-rw-r--r--app/controllers/concerns/send_file_upload.rb4
-rw-r--r--app/controllers/concerns/sends_blob.rb2
-rw-r--r--app/controllers/concerns/sessionless_authentication.rb28
-rw-r--r--app/controllers/concerns/uploads_actions.rb13
-rw-r--r--app/controllers/concerns/with_performance_bar.rb6
-rw-r--r--app/controllers/dashboard/application_controller.rb2
-rw-r--r--app/controllers/dashboard/groups_controller.rb2
-rw-r--r--app/controllers/dashboard/labels_controller.rb2
-rw-r--r--app/controllers/dashboard/milestones_controller.rb9
-rw-r--r--app/controllers/dashboard/projects_controller.rb3
-rw-r--r--app/controllers/dashboard/snippets_controller.rb2
-rw-r--r--app/controllers/dashboard/todos_controller.rb12
-rw-r--r--app/controllers/dashboard_controller.rb15
-rw-r--r--app/controllers/explore/application_controller.rb2
-rw-r--r--app/controllers/explore/groups_controller.rb2
-rw-r--r--app/controllers/explore/projects_controller.rb2
-rw-r--r--app/controllers/explore/snippets_controller.rb2
-rw-r--r--app/controllers/google_api/authorizations_controller.rb2
-rw-r--r--app/controllers/graphql_controller.rb1
-rw-r--r--app/controllers/groups/application_controller.rb2
-rw-r--r--app/controllers/groups/avatars_controller.rb2
-rw-r--r--app/controllers/groups/boards_controller.rb20
-rw-r--r--app/controllers/groups/children_controller.rb2
-rw-r--r--app/controllers/groups/clusters/applications_controller.rb18
-rw-r--r--app/controllers/groups/clusters_controller.rb25
-rw-r--r--app/controllers/groups/group_members_controller.rb2
-rw-r--r--app/controllers/groups/labels_controller.rb8
-rw-r--r--app/controllers/groups/milestones_controller.rb4
-rw-r--r--app/controllers/groups/runners_controller.rb2
-rw-r--r--app/controllers/groups/settings/ci_cd_controller.rb13
-rw-r--r--app/controllers/groups/shared_projects_controller.rb2
-rw-r--r--app/controllers/groups/uploads_controller.rb2
-rw-r--r--app/controllers/groups/variables_controller.rb2
-rw-r--r--app/controllers/groups_controller.rb3
-rw-r--r--app/controllers/health_controller.rb11
-rw-r--r--app/controllers/import/base_controller.rb2
-rw-r--r--app/controllers/import/bitbucket_controller.rb2
-rw-r--r--app/controllers/import/bitbucket_server_controller.rb24
-rw-r--r--app/controllers/import/fogbugz_controller.rb2
-rw-r--r--app/controllers/import/gitea_controller.rb4
-rw-r--r--app/controllers/import/github_controller.rb6
-rw-r--r--app/controllers/import/gitlab_controller.rb2
-rw-r--r--app/controllers/import/gitlab_projects_controller.rb2
-rw-r--r--app/controllers/import/google_code_controller.rb2
-rw-r--r--app/controllers/import/manifest_controller.rb2
-rw-r--r--app/controllers/koding_controller.rb17
-rw-r--r--app/controllers/ldap/omniauth_callbacks_controller.rb2
-rw-r--r--app/controllers/metrics_controller.rb2
-rw-r--r--app/controllers/oauth/applications_controller.rb4
-rw-r--r--app/controllers/oauth/authorizations_controller.rb4
-rw-r--r--app/controllers/oauth/authorized_applications_controller.rb2
-rw-r--r--app/controllers/profiles/accounts_controller.rb2
-rw-r--r--app/controllers/profiles/active_sessions_controller.rb2
-rw-r--r--app/controllers/profiles/application_controller.rb2
-rw-r--r--app/controllers/profiles/avatars_controller.rb2
-rw-r--r--app/controllers/profiles/chat_names_controller.rb2
-rw-r--r--app/controllers/profiles/emails_controller.rb2
-rw-r--r--app/controllers/profiles/gpg_keys_controller.rb2
-rw-r--r--app/controllers/profiles/keys_controller.rb9
-rw-r--r--app/controllers/profiles/notifications_controller.rb2
-rw-r--r--app/controllers/profiles/passwords_controller.rb2
-rw-r--r--app/controllers/profiles/personal_access_tokens_controller.rb2
-rw-r--r--app/controllers/profiles/preferences_controller.rb2
-rw-r--r--app/controllers/profiles/two_factor_auths_controller.rb4
-rw-r--r--app/controllers/profiles/u2f_registrations_controller.rb2
-rw-r--r--app/controllers/projects/application_controller.rb5
-rw-r--r--app/controllers/projects/artifacts_controller.rb19
-rw-r--r--app/controllers/projects/autocomplete_sources_controller.rb22
-rw-r--r--app/controllers/projects/avatars_controller.rb4
-rw-r--r--app/controllers/projects/badges_controller.rb2
-rw-r--r--app/controllers/projects/blame_controller.rb2
-rw-r--r--app/controllers/projects/blob_controller.rb39
-rw-r--r--app/controllers/projects/boards_controller.rb22
-rw-r--r--app/controllers/projects/branches_controller.rb4
-rw-r--r--app/controllers/projects/build_artifacts_controller.rb6
-rw-r--r--app/controllers/projects/builds_controller.rb2
-rw-r--r--app/controllers/projects/ci/lints_controller.rb2
-rw-r--r--app/controllers/projects/clusters/applications_controller.rb48
-rw-r--r--app/controllers/projects/clusters_controller.rb222
-rw-r--r--app/controllers/projects/commit_controller.rb5
-rw-r--r--app/controllers/projects/commits_controller.rb17
-rw-r--r--app/controllers/projects/compare_controller.rb19
-rw-r--r--app/controllers/projects/cycle_analytics/events_controller.rb2
-rw-r--r--app/controllers/projects/cycle_analytics_controller.rb2
-rw-r--r--app/controllers/projects/deploy_keys_controller.rb13
-rw-r--r--app/controllers/projects/deploy_tokens_controller.rb2
-rw-r--r--app/controllers/projects/deployments_controller.rb2
-rw-r--r--app/controllers/projects/discussions_controller.rb2
-rw-r--r--app/controllers/projects/environments_controller.rb4
-rw-r--r--app/controllers/projects/find_file_controller.rb2
-rw-r--r--app/controllers/projects/forks_controller.rb2
-rw-r--r--app/controllers/projects/git_http_client_controller.rb2
-rw-r--r--app/controllers/projects/git_http_controller.rb7
-rw-r--r--app/controllers/projects/graphs_controller.rb2
-rw-r--r--app/controllers/projects/group_links_controller.rb2
-rw-r--r--app/controllers/projects/hook_logs_controller.rb2
-rw-r--r--app/controllers/projects/hooks_controller.rb2
-rw-r--r--app/controllers/projects/imports_controller.rb18
-rw-r--r--app/controllers/projects/issues_controller.rb37
-rw-r--r--app/controllers/projects/jobs_controller.rb15
-rw-r--r--app/controllers/projects/labels_controller.rb10
-rw-r--r--app/controllers/projects/lfs_api_controller.rb2
-rw-r--r--app/controllers/projects/lfs_locks_api_controller.rb2
-rw-r--r--app/controllers/projects/lfs_storage_controller.rb2
-rw-r--r--app/controllers/projects/mattermosts_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests/application_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests/conflicts_controller.rb2
-rw-r--r--app/controllers/projects/merge_requests/creations_controller.rb6
-rw-r--r--app/controllers/projects/merge_requests/diffs_controller.rb22
-rw-r--r--app/controllers/projects/merge_requests_controller.rb77
-rw-r--r--app/controllers/projects/milestones_controller.rb30
-rw-r--r--app/controllers/projects/mirrors_controller.rb22
-rw-r--r--app/controllers/projects/network_controller.rb10
-rw-r--r--app/controllers/projects/notes_controller.rb4
-rw-r--r--app/controllers/projects/pages_controller.rb2
-rw-r--r--app/controllers/projects/pages_domains_controller.rb2
-rw-r--r--app/controllers/projects/pipeline_schedules_controller.rb2
-rw-r--r--app/controllers/projects/pipelines_controller.rb2
-rw-r--r--app/controllers/projects/pipelines_settings_controller.rb2
-rw-r--r--app/controllers/projects/project_members_controller.rb2
-rw-r--r--app/controllers/projects/prometheus/metrics_controller.rb2
-rw-r--r--app/controllers/projects/protected_branches_controller.rb2
-rw-r--r--app/controllers/projects/protected_refs_controller.rb2
-rw-r--r--app/controllers/projects/protected_tags_controller.rb2
-rw-r--r--app/controllers/projects/raw_controller.rb4
-rw-r--r--app/controllers/projects/refs_controller.rb2
-rw-r--r--app/controllers/projects/registry/application_controller.rb2
-rw-r--r--app/controllers/projects/registry/repositories_controller.rb2
-rw-r--r--app/controllers/projects/registry/tags_controller.rb2
-rw-r--r--app/controllers/projects/releases_controller.rb2
-rw-r--r--app/controllers/projects/repositories_controller.rb2
-rw-r--r--app/controllers/projects/runner_projects_controller.rb2
-rw-r--r--app/controllers/projects/runners_controller.rb2
-rw-r--r--app/controllers/projects/services_controller.rb2
-rw-r--r--app/controllers/projects/settings/ci_cd_controller.rb13
-rw-r--r--app/controllers/projects/settings/integrations_controller.rb2
-rw-r--r--app/controllers/projects/settings/repository_controller.rb2
-rw-r--r--app/controllers/projects/snippets_controller.rb2
-rw-r--r--app/controllers/projects/tags_controller.rb4
-rw-r--r--app/controllers/projects/templates_controller.rb2
-rw-r--r--app/controllers/projects/todos_controller.rb2
-rw-r--r--app/controllers/projects/tree_controller.rb2
-rw-r--r--app/controllers/projects/triggers_controller.rb2
-rw-r--r--app/controllers/projects/uploads_controller.rb2
-rw-r--r--app/controllers/projects/variables_controller.rb2
-rw-r--r--app/controllers/projects/wikis_controller.rb25
-rw-r--r--app/controllers/projects_controller.rb10
-rw-r--r--app/controllers/root_controller.rb4
-rw-r--r--app/controllers/sessions_controller.rb2
-rw-r--r--app/controllers/sherlock/application_controller.rb2
-rw-r--r--app/controllers/sherlock/file_samples_controller.rb2
-rw-r--r--app/controllers/sherlock/queries_controller.rb2
-rw-r--r--app/controllers/sherlock/transactions_controller.rb2
-rw-r--r--app/controllers/snippets/notes_controller.rb2
-rw-r--r--app/controllers/snippets_controller.rb6
-rw-r--r--app/controllers/users/terms_controller.rb2
-rw-r--r--app/controllers/users_controller.rb16
-rw-r--r--app/finders/admin/runners_finder.rb18
-rw-r--r--app/finders/applications_finder.rb22
-rw-r--r--app/finders/autocomplete/users_finder.rb2
-rw-r--r--app/finders/branches_finder.rb41
-rw-r--r--app/finders/clusters_finder.rb8
-rw-r--r--app/finders/concerns/finder_with_cross_project_access.rb2
-rw-r--r--app/finders/events_finder.rb3
-rw-r--r--app/finders/group_descendants_finder.rb4
-rw-r--r--app/finders/group_labels_finder.rb29
-rw-r--r--app/finders/groups_finder.rb4
-rw-r--r--app/finders/issuable_finder.rb130
-rw-r--r--app/finders/issues_finder.rb20
-rw-r--r--app/finders/joined_groups_finder.rb19
-rw-r--r--app/finders/labels_finder.rb19
-rw-r--r--app/finders/license_template_finder.rb40
-rw-r--r--app/finders/merge_requests_finder.rb23
-rw-r--r--app/finders/milestones_finder.rb2
-rw-r--r--app/finders/notes_finder.rb6
-rw-r--r--app/finders/pending_todos_finder.rb64
-rw-r--r--app/finders/personal_access_tokens_finder.rb2
-rw-r--r--app/finders/pipelines_finder.rb2
-rw-r--r--app/finders/projects_finder.rb29
-rw-r--r--app/finders/snippets_finder.rb211
-rw-r--r--app/finders/template_finder.rb19
-rw-r--r--app/finders/todos_finder.rb93
-rw-r--r--app/finders/user_finder.rb52
-rw-r--r--app/finders/user_recent_events_finder.rb3
-rw-r--r--app/finders/users_finder.rb4
-rw-r--r--app/finders/users_with_pending_todos_finder.rb16
-rw-r--r--app/graphql/resolvers/full_path_resolver.rb7
-rw-r--r--app/graphql/resolvers/issues_resolver.rb25
-rw-r--r--app/graphql/resolvers/merge_request_resolver.rb7
-rw-r--r--app/graphql/types/issue_type.rb47
-rw-r--r--app/graphql/types/label_type.rb12
-rw-r--r--app/graphql/types/milestone_type.rb17
-rw-r--r--app/graphql/types/order.rb8
-rw-r--r--app/graphql/types/permission_types/issue.rb14
-rw-r--r--app/graphql/types/permission_types/project.rb2
-rw-r--r--app/graphql/types/project_type.rb5
-rw-r--r--app/graphql/types/sort.rb10
-rw-r--r--app/graphql/types/user_type.rb14
-rw-r--r--app/helpers/application_helper.rb15
-rw-r--r--app/helpers/application_settings_helper.rb51
-rw-r--r--app/helpers/auth_helper.rb17
-rw-r--r--app/helpers/avatars_helper.rb23
-rw-r--r--app/helpers/blob_helper.rb38
-rw-r--r--app/helpers/boards_helper.rb4
-rw-r--r--app/helpers/ci_status_helper.rb6
-rw-r--r--app/helpers/clusters_helper.rb9
-rw-r--r--app/helpers/count_helper.rb14
-rw-r--r--app/helpers/dashboard_helper.rb4
-rw-r--r--app/helpers/events_helper.rb51
-rw-r--r--app/helpers/groups_helper.rb13
-rw-r--r--app/helpers/icons_helper.rb4
-rw-r--r--app/helpers/import_helper.rb4
-rw-r--r--app/helpers/issuables_helper.rb16
-rw-r--r--app/helpers/issues_helper.rb6
-rw-r--r--app/helpers/labels_helper.rb20
-rw-r--r--app/helpers/merge_requests_helper.rb6
-rw-r--r--app/helpers/milestones_helper.rb13
-rw-r--r--app/helpers/mirror_helper.rb5
-rw-r--r--app/helpers/nav_helper.rb16
-rw-r--r--app/helpers/notes_helper.rb4
-rw-r--r--app/helpers/page_layout_helper.rb2
-rw-r--r--app/helpers/preferences_helper.rb36
-rw-r--r--app/helpers/profiles_helper.rb14
-rw-r--r--app/helpers/projects_helper.rb31
-rw-r--r--app/helpers/repository_languages_helper.rb3
-rw-r--r--app/helpers/search_helper.rb15
-rw-r--r--app/helpers/sorting_helper.rb14
-rw-r--r--app/helpers/storage_health_helper.rb34
-rw-r--r--app/helpers/time_helper.rb12
-rw-r--r--app/helpers/tree_helper.rb20
-rw-r--r--app/helpers/user_callouts_helper.rb5
-rw-r--r--app/helpers/users_helper.rb6
-rw-r--r--app/helpers/version_check_helper.rb13
-rw-r--r--app/helpers/workhorse_helper.rb2
-rw-r--r--app/mailers/emails/issues.rb14
-rw-r--r--app/mailers/emails/merge_requests.rb26
-rw-r--r--app/mailers/emails/notes.rb2
-rw-r--r--app/mailers/notify.rb1
-rw-r--r--app/mailers/previews/notify_preview.rb20
-rw-r--r--app/models/ability.rb2
-rw-r--r--app/models/application_record.rb5
-rw-r--r--app/models/application_setting.rb78
-rw-r--r--app/models/blob.rb25
-rw-r--r--app/models/blob_viewer/package_json.rb3
-rw-r--r--app/models/board_group_recent_visit.rb25
-rw-r--r--app/models/board_project_recent_visit.rb25
-rw-r--r--app/models/ci/artifact_blob.rb2
-rw-r--r--app/models/ci/build.rb224
-rw-r--r--app/models/ci/build_trace_chunk.rb21
-rw-r--r--app/models/ci/job_artifact.rb58
-rw-r--r--app/models/ci/pipeline.rb94
-rw-r--r--app/models/ci/pipeline_enums.rb28
-rw-r--r--app/models/ci/pipeline_variable.rb4
-rw-r--r--app/models/ci/runner.rb27
-rw-r--r--app/models/ci/stage.rb5
-rw-r--r--app/models/clusters/applications/cert_manager.rb63
-rw-r--r--app/models/clusters/applications/ingress.rb4
-rw-r--r--app/models/clusters/applications/jupyter.rb13
-rw-r--r--app/models/clusters/applications/knative.rb67
-rw-r--r--app/models/clusters/applications/runner.rb2
-rw-r--r--app/models/clusters/cluster.rb71
-rw-r--r--app/models/clusters/concerns/application_core.rb2
-rw-r--r--app/models/clusters/concerns/application_status.rb35
-rw-r--r--app/models/clusters/group.rb10
-rw-r--r--app/models/clusters/kubernetes_namespace.rb83
-rw-r--r--app/models/clusters/platforms/kubernetes.rb80
-rw-r--r--app/models/clusters/project.rb3
-rw-r--r--app/models/commit.rb33
-rw-r--r--app/models/commit_status.rb28
-rw-r--r--app/models/commit_status_enums.rb20
-rw-r--r--app/models/compare.rb11
-rw-r--r--app/models/concerns/avatarable.rb2
-rw-r--r--app/models/concerns/awardable.rb18
-rw-r--r--app/models/concerns/blob_language_from_git_attributes.rb13
-rw-r--r--app/models/concerns/blob_like.rb2
-rw-r--r--app/models/concerns/blocks_json_serialization.rb2
-rw-r--r--app/models/concerns/bulk_member_access_load.rb6
-rw-r--r--app/models/concerns/cache_markdown_field.rb2
-rw-r--r--app/models/concerns/cacheable_attributes.rb10
-rw-r--r--app/models/concerns/deployable.rb30
-rw-r--r--app/models/concerns/deployment_platform.rb1
-rw-r--r--app/models/concerns/diff_positionable_note.rb81
-rw-r--r--app/models/concerns/each_batch.rb17
-rw-r--r--app/models/concerns/fast_destroy_all.rb2
-rw-r--r--app/models/concerns/has_status.rb19
-rw-r--r--app/models/concerns/issuable.rb7
-rw-r--r--app/models/concerns/mentionable.rb4
-rw-r--r--app/models/concerns/mentionable/reference_regexes.rb22
-rw-r--r--app/models/concerns/mirror_authentication.rb91
-rw-r--r--app/models/concerns/noteable.rb2
-rw-r--r--app/models/concerns/redactable.rb33
-rw-r--r--app/models/concerns/relative_positioning.rb121
-rw-r--r--app/models/concerns/shardable.rb18
-rw-r--r--app/models/concerns/storage/legacy_namespace.rb8
-rw-r--r--app/models/concerns/subscribable.rb8
-rw-r--r--app/models/concerns/token_authenticatable.rb65
-rw-r--r--app/models/concerns/token_authenticatable_strategies/base.rb73
-rw-r--r--app/models/concerns/token_authenticatable_strategies/digest.rb50
-rw-r--r--app/models/concerns/token_authenticatable_strategies/insecure.rb23
-rw-r--r--app/models/concerns/with_uploads.rb2
-rw-r--r--app/models/deploy_token.rb5
-rw-r--r--app/models/deployment.rb89
-rw-r--r--app/models/diff_note.rb119
-rw-r--r--app/models/discussion_note.rb6
-rw-r--r--app/models/environment.rb9
-rw-r--r--app/models/environment_status.rb74
-rw-r--r--app/models/event.rb14
-rw-r--r--app/models/forked_project_link.rb6
-rw-r--r--app/models/global_milestone.rb44
-rw-r--r--app/models/group.rb35
-rw-r--r--app/models/hooks/service_hook.rb4
-rw-r--r--app/models/hooks/web_hook.rb10
-rw-r--r--app/models/identity.rb8
-rw-r--r--app/models/identity/uniqueness_scopes.rb11
-rw-r--r--app/models/instance_configuration.rb4
-rw-r--r--app/models/issue.rb25
-rw-r--r--app/models/key.rb4
-rw-r--r--app/models/label.rb20
-rw-r--r--app/models/legacy_diff_note.rb6
-rw-r--r--app/models/lfs_object.rb4
-rw-r--r--app/models/license_template.rb8
-rw-r--r--app/models/list.rb1
-rw-r--r--app/models/member.rb24
-rw-r--r--app/models/members_preloader.rb16
-rw-r--r--app/models/merge_request.rb31
-rw-r--r--app/models/merge_request_diff.rb16
-rw-r--r--app/models/milestone.rb18
-rw-r--r--app/models/namespace.rb18
-rw-r--r--app/models/note.rb43
-rw-r--r--app/models/notification_setting.rb2
-rw-r--r--app/models/personal_access_token.rb16
-rw-r--r--app/models/pool_repository.rb20
-rw-r--r--app/models/postgresql/replication_slot.rb11
-rw-r--r--app/models/project.rb448
-rw-r--r--app/models/project_auto_devops.rb20
-rw-r--r--app/models/project_feature.rb51
-rw-r--r--app/models/project_import_state.rb42
-rw-r--r--app/models/project_repository.rb13
-rw-r--r--app/models/project_services/bamboo_service.rb29
-rw-r--r--app/models/project_services/chat_message/push_message.rb47
-rw-r--r--app/models/project_services/discord_service.rb57
-rw-r--r--app/models/project_services/drone_ci_service.rb16
-rw-r--r--app/models/project_services/flowdock_service.rb48
-rw-r--r--app/models/project_services/hipchat_service.rb2
-rw-r--r--app/models/project_services/issue_tracker_service.rb6
-rw-r--r--app/models/project_services/jira_service.rb9
-rw-r--r--app/models/project_services/kubernetes_service.rb17
-rw-r--r--app/models/project_services/microsoft_teams_service.rb2
-rw-r--r--app/models/project_services/mock_ci_service.rb14
-rw-r--r--app/models/project_services/prometheus_service.rb11
-rw-r--r--app/models/project_services/teamcity_service.rb2
-rw-r--r--app/models/remote_mirror.rb47
-rw-r--r--app/models/repository.rb99
-rw-r--r--app/models/service.rb1
-rw-r--r--app/models/shard.rb25
-rw-r--r--app/models/site_statistic.rb76
-rw-r--r--app/models/snippet.rb80
-rw-r--r--app/models/ssh_host_key.rb130
-rw-r--r--app/models/storage/hashed_project.rb8
-rw-r--r--app/models/system_note_metadata.rb5
-rw-r--r--app/models/todo.rb43
-rw-r--r--app/models/tree.rb51
-rw-r--r--app/models/upload.rb18
-rw-r--r--app/models/user.rb114
-rw-r--r--app/models/user_callout.rb8
-rw-r--r--app/models/user_callout_enums.rb16
-rw-r--r--app/models/user_preference.rb53
-rw-r--r--app/models/wiki_page.rb25
-rw-r--r--app/policies/ci/build_policy.rb7
-rw-r--r--app/policies/ci/pipeline_policy.rb4
-rw-r--r--app/policies/clusters/cluster_policy.rb6
-rw-r--r--app/policies/commit_policy.rb2
-rw-r--r--app/policies/deployment_policy.rb9
-rw-r--r--app/policies/group_policy.rb4
-rw-r--r--app/policies/milestone_policy.rb5
-rw-r--r--app/policies/note_policy.rb9
-rw-r--r--app/policies/project_policy.rb13
-rw-r--r--app/presenters/blob_presenter.rb16
-rw-r--r--app/presenters/ci/build_presenter.rb4
-rw-r--r--app/presenters/ci/build_runner_presenter.rb10
-rw-r--r--app/presenters/ci/pipeline_presenter.rb10
-rw-r--r--app/presenters/clusterable_presenter.rb58
-rw-r--r--app/presenters/clusters/cluster_presenter.rb10
-rw-r--r--app/presenters/commit_status_presenter.rb7
-rw-r--r--app/presenters/group_clusterable_presenter.rb36
-rw-r--r--app/presenters/issue_presenter.rb9
-rw-r--r--app/presenters/merge_request_presenter.rb12
-rw-r--r--app/presenters/project_clusterable_presenter.rb31
-rw-r--r--app/presenters/project_presenter.rb54
-rw-r--r--app/presenters/user_presenter.rb9
-rw-r--r--app/serializers/build_action_entity.rb10
-rw-r--r--app/serializers/build_details_entity.rb13
-rw-r--r--app/serializers/commit_entity.rb38
-rw-r--r--app/serializers/current_user_entity.rb8
-rw-r--r--app/serializers/deployment_entity.rb1
-rw-r--r--app/serializers/detailed_status_entity.rb8
-rw-r--r--app/serializers/diff_file_entity.rb6
-rw-r--r--app/serializers/diff_line_entity.rb2
-rw-r--r--app/serializers/diff_viewer_entity.rb7
-rw-r--r--app/serializers/diffs_entity.rb9
-rw-r--r--app/serializers/discussion_entity.rb2
-rw-r--r--app/serializers/environment_status_entity.rb67
-rw-r--r--app/serializers/environment_status_serializer.rb5
-rw-r--r--app/serializers/issue_entity.rb2
-rw-r--r--app/serializers/job_entity.rb27
-rw-r--r--app/serializers/merge_request_user_entity.rb2
-rw-r--r--app/serializers/merge_request_widget_entity.rb3
-rw-r--r--app/serializers/pipeline_details_entity.rb1
-rw-r--r--app/serializers/pipeline_serializer.rb1
-rw-r--r--app/serializers/project_mirror_entity.rb8
-rw-r--r--app/serializers/remote_mirror_entity.rb15
-rw-r--r--app/serializers/user_preference_entity.rb14
-rw-r--r--app/services/access_token_validation_service.rb6
-rw-r--r--app/services/applications/create_service.rb1
-rw-r--r--app/services/audit_event_service.rb26
-rw-r--r--app/services/auth/container_registry_authentication_service.rb2
-rw-r--r--app/services/boards/issues/move_service.rb4
-rw-r--r--app/services/boards/lists/list_service.rb2
-rw-r--r--app/services/boards/visits/create_service.rb17
-rw-r--r--app/services/boards/visits/latest_service.rb17
-rw-r--r--app/services/ci/archive_trace_service.rb35
-rw-r--r--app/services/ci/create_pipeline_service.rb10
-rw-r--r--app/services/ci/destroy_pipeline_service.rb13
-rw-r--r--app/services/ci/enqueue_build_service.rb8
-rw-r--r--app/services/ci/process_build_service.rb45
-rw-r--r--app/services/ci/process_pipeline_service.rb34
-rw-r--r--app/services/ci/register_job_service.rb9
-rw-r--r--app/services/ci/run_scheduled_build_service.rb13
-rw-r--r--app/services/clusters/applications/base_helm_service.rb19
-rw-r--r--app/services/clusters/applications/check_ingress_ip_address_service.rb2
-rw-r--r--app/services/clusters/applications/check_installation_progress_service.rb15
-rw-r--r--app/services/clusters/applications/create_service.rb83
-rw-r--r--app/services/clusters/applications/install_service.rb8
-rw-r--r--app/services/clusters/applications/schedule_installation_service.rb10
-rw-r--r--app/services/clusters/create_service.rb42
-rw-r--r--app/services/clusters/gcp/finalize_creation_service.rb30
-rw-r--r--app/services/clusters/gcp/kubernetes.rb11
-rw-r--r--app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb52
-rw-r--r--app/services/clusters/gcp/kubernetes/create_service_account_service.rb78
-rw-r--r--app/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service.rb13
-rw-r--r--app/services/clusters/update_service.rb8
-rw-r--r--app/services/commits/change_service.rb8
-rw-r--r--app/services/commits/commit_patch_service.rb61
-rw-r--r--app/services/commits/create_service.rb7
-rw-r--r--app/services/create_deployment_service.rb74
-rw-r--r--app/services/delete_merged_branches_service.rb4
-rw-r--r--app/services/files/multi_service.rb13
-rw-r--r--app/services/groups/update_service.rb6
-rw-r--r--app/services/issuable/clone/attributes_rewriter.rb62
-rw-r--r--app/services/issuable/clone/base_service.rb60
-rw-r--r--app/services/issuable/clone/content_rewriter.rb65
-rw-r--r--app/services/issuable_base_service.rb12
-rw-r--r--app/services/issues/move_service.rb157
-rw-r--r--app/services/issues/related_branches_service.rb26
-rw-r--r--app/services/issues/update_service.rb27
-rw-r--r--app/services/keys/destroy_service.rb2
-rw-r--r--app/services/labels/transfer_service.rb2
-rw-r--r--app/services/members/base_service.rb2
-rw-r--r--app/services/merge_requests/base_service.rb6
-rw-r--r--app/services/merge_requests/build_service.rb7
-rw-r--r--app/services/merge_requests/create_from_issue_service.rb6
-rw-r--r--app/services/merge_requests/merge_service.rb5
-rw-r--r--app/services/merge_requests/refresh_service.rb76
-rw-r--r--app/services/merge_requests/reload_diffs_service.rb9
-rw-r--r--app/services/merge_requests/update_service.rb14
-rw-r--r--app/services/milestones/destroy_service.rb2
-rw-r--r--app/services/notes/base_service.rb13
-rw-r--r--app/services/notes/build_service.rb6
-rw-r--r--app/services/notes/create_service.rb3
-rw-r--r--app/services/notes/destroy_service.rb4
-rw-r--r--app/services/notification_service.rb43
-rw-r--r--app/services/projects/after_rename_service.rb135
-rw-r--r--app/services/projects/autocomplete_service.rb33
-rw-r--r--app/services/projects/create_service.rb29
-rw-r--r--app/services/projects/disable_deploy_key_service.rb13
-rw-r--r--app/services/projects/enable_deploy_key_service.rb14
-rw-r--r--app/services/projects/fork_service.rb68
-rw-r--r--app/services/projects/forks_count_service.rb5
-rw-r--r--app/services/projects/hashed_storage/migrate_repository_service.rb1
-rw-r--r--app/services/projects/move_forks_service.rb13
-rw-r--r--app/services/projects/move_project_authorizations_service.rb2
-rw-r--r--app/services/projects/move_project_group_links_service.rb2
-rw-r--r--app/services/projects/move_project_members_service.rb2
-rw-r--r--app/services/projects/unlink_fork_service.rb1
-rw-r--r--app/services/projects/update_pages_configuration_service.rb8
-rw-r--r--app/services/projects/update_remote_mirror_service.rb3
-rw-r--r--app/services/projects/update_service.rb12
-rw-r--r--app/services/quick_actions/interpret_service.rb72
-rw-r--r--app/services/resource_events/merge_into_notes_service.rb2
-rw-r--r--app/services/search/group_service.rb2
-rw-r--r--app/services/submodules/update_service.rb38
-rw-r--r--app/services/system_note_service.rb10
-rw-r--r--app/services/todo_service.rb26
-rw-r--r--app/services/todos/destroy/entity_leave_service.rb2
-rw-r--r--app/services/todos/destroy/private_features_service.rb6
-rw-r--r--app/services/update_deployment_service.rb53
-rw-r--r--app/services/users/build_service.rb16
-rw-r--r--app/services/web_hook_service.rb8
-rw-r--r--app/uploaders/file_uploader.rb6
-rw-r--r--app/uploaders/gitlab_uploader.rb10
-rw-r--r--app/uploaders/job_artifact_uploader.rb2
-rw-r--r--app/uploaders/legacy_artifact_uploader.rb2
-rw-r--r--app/uploaders/lfs_object_uploader.rb2
-rw-r--r--app/views/abuse_reports/new.html.haml14
-rw-r--r--app/views/admin/appearances/_form.html.haml6
-rw-r--r--app/views/admin/application_settings/_background_jobs.html.haml27
-rw-r--r--app/views/admin/application_settings/_ci_cd.html.haml8
-rw-r--r--app/views/admin/application_settings/_diff_limits.html.haml16
-rw-r--r--app/views/admin/application_settings/_email.html.haml6
-rw-r--r--app/views/admin/application_settings/_koding.html.haml22
-rw-r--r--app/views/admin/application_settings/_repository_storage.html.haml31
-rw-r--r--app/views/admin/application_settings/preferences.html.haml11
-rw-r--r--app/views/admin/application_settings/repository.html.haml4
-rw-r--r--app/views/admin/application_settings/show.html.haml25
-rw-r--r--app/views/admin/applications/_form.html.haml4
-rw-r--r--app/views/admin/applications/show.html.haml21
-rw-r--r--app/views/admin/background_jobs/show.html.haml35
-rw-r--r--app/views/admin/dashboard/index.html.haml2
-rw-r--r--app/views/admin/groups/_form.html.haml4
-rw-r--r--app/views/admin/groups/show.html.haml9
-rw-r--r--app/views/admin/health_check/_failing_storages.html.haml15
-rw-r--r--app/views/admin/health_check/show.html.haml3
-rw-r--r--app/views/admin/impersonation_tokens/index.html.haml5
-rw-r--r--app/views/admin/projects/show.html.haml6
-rw-r--r--app/views/admin/runners/_sort_dropdown.html.haml2
-rw-r--r--app/views/admin/runners/index.html.haml178
-rw-r--r--app/views/admin/users/_head.html.haml2
-rw-r--r--app/views/ci/runner/_how_to_setup_runner.html.haml4
-rw-r--r--app/views/ci/runner/_how_to_setup_shared_runner.html.haml3
-rw-r--r--app/views/ci/runner/_how_to_setup_specific_runner.html.haml26
-rw-r--r--app/views/ci/variables/_index.html.haml4
-rw-r--r--app/views/clusters/clusters/_advanced_settings.html.haml15
-rw-r--r--app/views/clusters/clusters/_banner.html.haml9
-rw-r--r--app/views/clusters/clusters/_buttons.html.haml4
-rw-r--r--app/views/clusters/clusters/_cluster.html.haml16
-rw-r--r--app/views/clusters/clusters/_empty_state.html.haml14
-rw-r--r--app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml12
-rw-r--r--app/views/clusters/clusters/_integration_form.html.haml31
-rw-r--r--app/views/clusters/clusters/_sidebar.html.haml6
-rw-r--r--app/views/clusters/clusters/gcp/_form.html.haml74
-rw-r--r--app/views/clusters/clusters/gcp/_header.html.haml (renamed from app/views/projects/clusters/gcp/_header.html.haml)0
-rw-r--r--app/views/clusters/clusters/gcp/_show.html.haml50
-rw-r--r--app/views/clusters/clusters/index.html.haml23
-rw-r--r--app/views/clusters/clusters/new.html.haml36
-rw-r--r--app/views/clusters/clusters/show.html.haml56
-rw-r--r--app/views/clusters/clusters/user/_form.html.haml39
-rw-r--r--app/views/clusters/clusters/user/_header.html.haml (renamed from app/views/projects/clusters/user/_header.html.haml)0
-rw-r--r--app/views/clusters/clusters/user/_show.html.haml39
-rw-r--r--app/views/dashboard/_activity_head.html.haml3
-rw-r--r--app/views/dashboard/_groups_head.html.haml9
-rw-r--r--app/views/dashboard/_projects_head.html.haml9
-rw-r--r--app/views/dashboard/_snippets_head.html.haml11
-rw-r--r--app/views/dashboard/activity.html.haml3
-rw-r--r--app/views/dashboard/groups/index.html.haml2
-rw-r--r--app/views/dashboard/issues.html.haml14
-rw-r--r--app/views/dashboard/merge_requests.html.haml15
-rw-r--r--app/views/dashboard/milestones/index.html.haml12
-rw-r--r--app/views/dashboard/projects/index.html.haml2
-rw-r--r--app/views/dashboard/projects/starred.html.haml2
-rw-r--r--app/views/dashboard/snippets/index.html.haml5
-rw-r--r--app/views/dashboard/todos/index.html.haml5
-rw-r--r--app/views/devise/mailer/email_changed.html.haml12
-rw-r--r--app/views/devise/mailer/email_changed.text.erb10
-rw-r--r--app/views/devise/shared/_omniauth_box.html.haml2
-rw-r--r--app/views/devise/shared/_signin_box.html.haml6
-rw-r--r--app/views/devise/shared/_signup_box.html.haml14
-rw-r--r--app/views/devise/shared/_tabs_ldap.html.haml9
-rw-r--r--app/views/discussions/_discussion.html.haml8
-rw-r--r--app/views/doorkeeper/applications/show.html.haml19
-rw-r--r--app/views/errors/precondition_failed.html.haml8
-rw-r--r--app/views/events/_event.html.haml2
-rw-r--r--app/views/events/event/_common.html.haml27
-rw-r--r--app/views/events/event/_created_project.html.haml8
-rw-r--r--app/views/events/event/_note.html.haml10
-rw-r--r--app/views/events/event/_private.html.haml13
-rw-r--r--app/views/events/event/_push.html.haml10
-rw-r--r--app/views/explore/groups/index.html.haml4
-rw-r--r--app/views/explore/projects/_filter.html.haml6
-rw-r--r--app/views/explore/projects/index.html.haml2
-rw-r--r--app/views/explore/projects/starred.html.haml2
-rw-r--r--app/views/explore/projects/trending.html.haml2
-rw-r--r--app/views/groups/_group_admin_settings.html.haml4
-rw-r--r--app/views/groups/edit.html.haml27
-rw-r--r--app/views/groups/issues.html.haml2
-rw-r--r--app/views/groups/labels/edit.html.haml4
-rw-r--r--app/views/groups/labels/index.html.haml23
-rw-r--r--app/views/groups/labels/new.html.haml5
-rw-r--r--app/views/groups/merge_requests.html.haml2
-rw-r--r--app/views/groups/milestones/edit.html.haml5
-rw-r--r--app/views/groups/milestones/new.html.haml15
-rw-r--r--app/views/groups/new.html.haml36
-rw-r--r--app/views/groups/runners/_group_runners.html.haml4
-rw-r--r--app/views/groups/settings/_advanced.html.haml24
-rw-r--r--app/views/groups/settings/_general.html.haml48
-rw-r--r--app/views/groups/settings/_lfs.html.haml15
-rw-r--r--app/views/groups/settings/_permissions.html.haml37
-rw-r--r--app/views/groups/settings/_two_factor_auth.html.haml16
-rw-r--r--app/views/groups/settings/ci_cd/show.html.haml2
-rw-r--r--app/views/groups/show.html.haml12
-rw-r--r--app/views/help/_shortcuts.html.haml7
-rw-r--r--app/views/help/index.html.haml3
-rw-r--r--app/views/import/bitbucket/status.html.haml5
-rw-r--r--app/views/import/bitbucket_server/status.html.haml7
-rw-r--r--app/views/import/fogbugz/status.html.haml5
-rw-r--r--app/views/import/gitlab/status.html.haml5
-rw-r--r--app/views/import/gitlab_projects/new.html.haml2
-rw-r--r--app/views/import/google_code/status.html.haml5
-rw-r--r--app/views/instance_statistics/conversational_development_index/_disabled.html.haml2
-rw-r--r--app/views/invites/show.html.haml17
-rw-r--r--app/views/koding/index.html.haml6
-rw-r--r--app/views/layouts/_flash.html.haml2
-rw-r--r--app/views/layouts/_page.html.haml5
-rw-r--r--app/views/layouts/dashboard.html.haml1
-rw-r--r--app/views/layouts/explore.html.haml2
-rw-r--r--app/views/layouts/header/_current_user_dropdown.html.haml16
-rw-r--r--app/views/layouts/header/_default.html.haml11
-rw-r--r--app/views/layouts/header/_help_dropdown.html.haml6
-rw-r--r--app/views/layouts/header/_new_dropdown.haml26
-rw-r--r--app/views/layouts/koding.html.haml5
-rw-r--r--app/views/layouts/nav/_dashboard.html.haml3
-rw-r--r--app/views/layouts/nav/sidebar/_admin.html.haml14
-rw-r--r--app/views/layouts/nav/sidebar/_group.html.haml37
-rw-r--r--app/views/layouts/nav/sidebar/_project.html.haml15
-rw-r--r--app/views/layouts/terms.html.haml29
-rw-r--r--app/views/notify/changed_milestone_issue_email.html.haml3
-rw-r--r--app/views/notify/changed_milestone_issue_email.text.erb1
-rw-r--r--app/views/notify/changed_milestone_merge_request_email.html.haml3
-rw-r--r--app/views/notify/changed_milestone_merge_request_email.text.erb1
-rw-r--r--app/views/notify/new_merge_request_email.html.haml2
-rw-r--r--app/views/notify/new_merge_request_email.text.erb2
-rw-r--r--app/views/notify/note_project_snippet_email.html.haml (renamed from app/views/notify/note_snippet_email.html.haml)0
-rw-r--r--app/views/notify/note_project_snippet_email.text.erb (renamed from app/views/notify/note_snippet_email.text.erb)0
-rw-r--r--app/views/notify/removed_milestone_issue_email.html.haml2
-rw-r--r--app/views/notify/removed_milestone_issue_email.text.erb1
-rw-r--r--app/views/notify/removed_milestone_merge_request_email.html.haml2
-rw-r--r--app/views/notify/removed_milestone_merge_request_email.text.erb1
-rw-r--r--app/views/peek/views/_gc.html.haml4
-rw-r--r--app/views/profiles/personal_access_tokens/index.html.haml14
-rw-r--r--app/views/profiles/preferences/show.html.haml4
-rw-r--r--app/views/profiles/show.html.haml12
-rw-r--r--app/views/profiles/two_factor_auths/_codes.html.haml2
-rw-r--r--app/views/profiles/two_factor_auths/show.html.haml6
-rw-r--r--app/views/projects/_home_panel.html.haml4
-rw-r--r--app/views/projects/_import_project_pane.html.haml26
-rw-r--r--app/views/projects/_md_preview.html.haml22
-rw-r--r--app/views/projects/_new_project_fields.html.haml15
-rw-r--r--app/views/projects/_project_templates.html.haml2
-rw-r--r--app/views/projects/_wiki.html.haml16
-rw-r--r--app/views/projects/artifacts/browse.html.haml2
-rw-r--r--app/views/projects/artifacts/file.html.haml2
-rw-r--r--app/views/projects/blob/_editor.html.haml4
-rw-r--r--app/views/projects/blob/_template_selectors.html.haml10
-rw-r--r--app/views/projects/blob/edit.html.haml2
-rw-r--r--app/views/projects/blob/new.html.haml2
-rw-r--r--app/views/projects/blob/viewers/_highlight_embed.html.haml4
-rw-r--r--app/views/projects/blob/viewers/_text.html.haml2
-rw-r--r--app/views/projects/branches/_panel.html.haml3
-rw-r--r--app/views/projects/branches/new.html.haml4
-rw-r--r--app/views/projects/buttons/_dropdown.html.haml4
-rw-r--r--app/views/projects/buttons/_koding.html.haml3
-rw-r--r--app/views/projects/ci/builds/_build.html.haml26
-rw-r--r--app/views/projects/clusters/_advanced_settings.html.haml15
-rw-r--r--app/views/projects/clusters/_banner.html.haml15
-rw-r--r--app/views/projects/clusters/_cluster.html.haml24
-rw-r--r--app/views/projects/clusters/_empty_state.html.haml12
-rw-r--r--app/views/projects/clusters/_gcp_signup_offer_banner.html.haml12
-rw-r--r--app/views/projects/clusters/_integration_form.html.haml31
-rw-r--r--app/views/projects/clusters/_sidebar.html.haml9
-rw-r--r--app/views/projects/clusters/gcp/_form.html.haml75
-rw-r--r--app/views/projects/clusters/gcp/_show.html.haml50
-rw-r--r--app/views/projects/clusters/index.html.haml24
-rw-r--r--app/views/projects/clusters/new.html.haml36
-rw-r--r--app/views/projects/clusters/show.html.haml52
-rw-r--r--app/views/projects/clusters/user/_form.html.haml39
-rw-r--r--app/views/projects/clusters/user/_show.html.haml39
-rw-r--r--app/views/projects/commit/show.html.haml2
-rw-r--r--app/views/projects/commits/_commit.html.haml98
-rw-r--r--app/views/projects/compare/_form.html.haml4
-rw-r--r--app/views/projects/deploy_tokens/_form.html.haml10
-rw-r--r--app/views/projects/deploy_tokens/_index.html.haml2
-rw-r--r--app/views/projects/deploy_tokens/_new_deploy_token.html.haml6
-rw-r--r--app/views/projects/deployments/_rollback.haml2
-rw-r--r--app/views/projects/diffs/_collapsed.html.haml4
-rw-r--r--app/views/projects/diffs/_diffs.html.haml8
-rw-r--r--app/views/projects/diffs/_file.html.haml5
-rw-r--r--app/views/projects/diffs/_file_header.html.haml2
-rw-r--r--app/views/projects/diffs/_render_error.html.haml2
-rw-r--r--app/views/projects/diffs/_stats.html.haml2
-rw-r--r--app/views/projects/diffs/_text_file.html.haml4
-rw-r--r--app/views/projects/diffs/_warning.html.haml14
-rw-r--r--app/views/projects/diffs/viewers/_added.html.haml2
-rw-r--r--app/views/projects/diffs/viewers/_deleted.html.haml2
-rw-r--r--app/views/projects/diffs/viewers/_mode_changed.html.haml2
-rw-r--r--app/views/projects/diffs/viewers/_no_preview.html.haml2
-rw-r--r--app/views/projects/diffs/viewers/_not_diffable.html.haml2
-rw-r--r--app/views/projects/diffs/viewers/_renamed.html.haml2
-rw-r--r--app/views/projects/edit.html.haml10
-rw-r--r--app/views/projects/empty.html.haml4
-rw-r--r--app/views/projects/environments/_external_url.html.haml4
-rw-r--r--app/views/projects/environments/_form.html.haml15
-rw-r--r--app/views/projects/environments/_metrics_button.html.haml4
-rw-r--r--app/views/projects/environments/edit.html.haml4
-rw-r--r--app/views/projects/environments/empty.html.haml18
-rw-r--r--app/views/projects/environments/folder.html.haml2
-rw-r--r--app/views/projects/environments/index.html.haml4
-rw-r--r--app/views/projects/environments/metrics.html.haml2
-rw-r--r--app/views/projects/environments/new.html.haml6
-rw-r--r--app/views/projects/environments/show.html.haml31
-rw-r--r--app/views/projects/environments/terminal.html.haml4
-rw-r--r--app/views/projects/find_file/show.html.haml2
-rw-r--r--app/views/projects/forks/_fork_button.html.haml4
-rw-r--r--app/views/projects/forks/index.html.haml2
-rw-r--r--app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml2
-rw-r--r--app/views/projects/graphs/charts.html.haml2
-rw-r--r--app/views/projects/imports/new.html.haml2
-rw-r--r--app/views/projects/issues/_discussion.html.haml4
-rw-r--r--app/views/projects/issues/_new_branch.html.haml3
-rw-r--r--app/views/projects/issues/show.html.haml7
-rw-r--r--app/views/projects/jobs/_empty_state.html.haml18
-rw-r--r--app/views/projects/jobs/_empty_states.html.haml9
-rw-r--r--app/views/projects/jobs/_header.html.haml10
-rw-r--r--app/views/projects/jobs/_sidebar.html.haml95
-rw-r--r--app/views/projects/jobs/show.html.haml99
-rw-r--r--app/views/projects/labels/edit.html.haml2
-rw-r--r--app/views/projects/labels/index.html.haml27
-rw-r--r--app/views/projects/labels/new.html.haml3
-rw-r--r--app/views/projects/merge_requests/_form.html.haml2
-rw-r--r--app/views/projects/merge_requests/_mr_title.html.haml2
-rw-r--r--app/views/projects/merge_requests/creations/_new_compare.html.haml4
-rw-r--r--app/views/projects/merge_requests/creations/_new_submit.html.haml2
-rw-r--r--app/views/projects/merge_requests/diffs/_commit_widget.html.haml4
-rw-r--r--app/views/projects/merge_requests/show.html.haml13
-rw-r--r--app/views/projects/milestones/edit.html.haml3
-rw-r--r--app/views/projects/milestones/new.html.haml3
-rw-r--r--app/views/projects/mirrors/_authentication_method.html.haml36
-rw-r--r--app/views/projects/mirrors/_mirror_repos.html.haml4
-rw-r--r--app/views/projects/mirrors/_mirror_repos_form.html.haml15
-rw-r--r--app/views/projects/mirrors/_mirror_repos_push.html.haml8
-rw-r--r--app/views/projects/mirrors/_regenerate_public_ssh_key_confirm_modal.html.haml13
-rw-r--r--app/views/projects/mirrors/_show.html.haml1
-rw-r--r--app/views/projects/mirrors/_ssh_host_keys.html.haml33
-rw-r--r--app/views/projects/new.html.haml15
-rw-r--r--app/views/projects/notes/_more_actions_dropdown.html.haml5
-rw-r--r--app/views/projects/pages/_https_only.html.haml10
-rw-r--r--app/views/projects/pages/_list.html.haml8
-rw-r--r--app/views/projects/pipelines/_info.html.haml8
-rw-r--r--app/views/projects/pipelines/_with_tabs.html.haml51
-rw-r--r--app/views/projects/pipelines/charts.html.haml3
-rw-r--r--app/views/projects/pipelines/new.html.haml2
-rw-r--r--app/views/projects/pipelines/show.html.haml10
-rw-r--r--app/views/projects/project_members/_new_project_member.html.haml4
-rw-r--r--app/views/projects/project_members/_team.html.haml2
-rw-r--r--app/views/projects/project_templates/_built_in_templates.html.haml8
-rw-r--r--app/views/projects/protected_branches/shared/_branches_list.html.haml3
-rw-r--r--app/views/projects/protected_branches/shared/_create_protected_branch.html.haml3
-rw-r--r--app/views/projects/protected_branches/shared/_dropdown.html.haml2
-rw-r--r--app/views/projects/protected_tags/shared/_create_protected_tag.html.haml3
-rw-r--r--app/views/projects/protected_tags/shared/_dropdown.html.haml2
-rw-r--r--app/views/projects/protected_tags/shared/_tags_list.html.haml3
-rw-r--r--app/views/projects/registry/repositories/index.html.haml3
-rw-r--r--app/views/projects/runners/_index.html.haml2
-rw-r--r--app/views/projects/runners/_shared_runners.html.haml10
-rw-r--r--app/views/projects/runners/_specific_runners.html.haml34
-rw-r--r--app/views/projects/runners/edit.html.haml2
-rw-r--r--app/views/projects/services/prometheus/_configuration_banner.html.haml2
-rw-r--r--app/views/projects/services/prometheus/_metrics.html.haml12
-rw-r--r--app/views/projects/settings/ci_cd/_autodevops_form.html.haml9
-rw-r--r--app/views/projects/settings/ci_cd/_badge.html.haml4
-rw-r--r--app/views/projects/settings/ci_cd/_form.html.haml12
-rw-r--r--app/views/projects/settings/ci_cd/show.html.haml2
-rw-r--r--app/views/projects/settings/repository/show.html.haml2
-rw-r--r--app/views/projects/show.html.haml6
-rw-r--r--app/views/projects/tags/index.html.haml2
-rw-r--r--app/views/projects/tags/new.html.haml3
-rw-r--r--app/views/projects/tree/_blob_item.html.haml12
-rw-r--r--app/views/projects/tree/_spinner.html.haml3
-rw-r--r--app/views/projects/tree/_submodule_item.html.haml6
-rw-r--r--app/views/projects/tree/_tree_commit_column.html.haml2
-rw-r--r--app/views/projects/tree/_tree_content.html.haml4
-rw-r--r--app/views/projects/tree/_tree_header.html.haml2
-rw-r--r--app/views/projects/tree/_tree_item.html.haml9
-rw-r--r--app/views/projects/tree/_tree_row.html.haml33
-rw-r--r--app/views/projects/triggers/_index.html.haml3
-rw-r--r--app/views/projects/wikis/_pages_wiki_page.html.haml3
-rw-r--r--app/views/projects/wikis/_sidebar_wiki_page.html.haml2
-rw-r--r--app/views/projects/wikis/edit.html.haml10
-rw-r--r--app/views/projects/wikis/history.html.haml4
-rw-r--r--app/views/projects/wikis/show.html.haml11
-rw-r--r--app/views/repository_check_mailer/notify.html.haml4
-rw-r--r--app/views/repository_check_mailer/notify.text.haml5
-rw-r--r--app/views/search/results/_snippet_blob.html.haml2
-rw-r--r--app/views/shared/_allow_request_access.html.haml6
-rw-r--r--app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml2
-rw-r--r--app/views/shared/_event_filter.html.haml12
-rw-r--r--app/views/shared/_field.html.haml2
-rw-r--r--app/views/shared/_file_highlight.html.haml6
-rw-r--r--app/views/shared/_group_form.html.haml45
-rw-r--r--app/views/shared/_label.html.haml45
-rw-r--r--app/views/shared/_labels_row.html.haml5
-rw-r--r--app/views/shared/_milestones_sort_dropdown.html.haml2
-rw-r--r--app/views/shared/_new_project_item_select.html.haml2
-rw-r--r--app/views/shared/_old_visibility_level.html.haml6
-rw-r--r--app/views/shared/_personal_access_tokens_created_container.html.haml14
-rw-r--r--app/views/shared/_personal_access_tokens_table.html.haml6
-rw-r--r--app/views/shared/_sort_dropdown.html.haml2
-rw-r--r--app/views/shared/_user_dropdown_contributing_link.html.haml2
-rw-r--r--app/views/shared/_visibility_level.html.haml30
-rw-r--r--app/views/shared/_visibility_radios.html.haml2
-rw-r--r--app/views/shared/boards/_show.html.haml4
-rw-r--r--app/views/shared/boards/components/_board.html.haml15
-rw-r--r--app/views/shared/boards/components/sidebar/_labels.html.haml4
-rw-r--r--app/views/shared/empty_states/_issues.html.haml7
-rw-r--r--app/views/shared/empty_states/_labels.html.haml9
-rw-r--r--app/views/shared/empty_states/_merge_requests.html.haml21
-rw-r--r--app/views/shared/empty_states/_wikis.html.haml2
-rw-r--r--app/views/shared/groups/_dropdown.html.haml2
-rw-r--r--app/views/shared/groups/_empty_state.html.haml2
-rw-r--r--app/views/shared/groups/_search_form.html.haml2
-rw-r--r--app/views/shared/icons/_icon_status_scheduled.svg1
-rw-r--r--app/views/shared/icons/_icon_status_scheduled_borderless.svg1
-rw-r--r--app/views/shared/issuable/_close_reopen_button.html.haml16
-rw-r--r--app/views/shared/issuable/_filter.html.haml32
-rw-r--r--app/views/shared/issuable/_form.html.haml5
-rw-r--r--app/views/shared/issuable/_label_dropdown.html.haml4
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml70
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml6
-rw-r--r--app/views/shared/issuable/_sidebar_todo.html.haml4
-rw-r--r--app/views/shared/issuable/form/_title.html.haml2
-rw-r--r--app/views/shared/labels/_form.html.haml8
-rw-r--r--app/views/shared/labels/_nav.html.haml20
-rw-r--r--app/views/shared/labels/_sort_dropdown.html.haml4
-rw-r--r--app/views/shared/members/_filter_2fa_dropdown.html.haml4
-rw-r--r--app/views/shared/members/_group.html.haml10
-rw-r--r--app/views/shared/members/_member.html.haml31
-rw-r--r--app/views/shared/members/_requests.html.haml2
-rw-r--r--app/views/shared/members/_sort_dropdown.html.haml2
-rw-r--r--app/views/shared/milestones/_milestone.html.haml4
-rw-r--r--app/views/shared/notes/_note.html.haml2
-rw-r--r--app/views/shared/notes/_notes_with_form.html.haml4
-rw-r--r--app/views/shared/notifications/_button.html.haml4
-rw-r--r--app/views/shared/projects/_list.html.haml3
-rw-r--r--app/views/shared/projects/_search_form.html.haml2
-rw-r--r--app/views/shared/runners/show.html.haml2
-rw-r--r--app/views/shared/snippets/_form.html.haml2
-rw-r--r--app/views/sherlock/queries/_general.html.haml2
-rw-r--r--app/views/sherlock/transactions/_queries.html.haml2
-rw-r--r--app/views/snippets/_actions.html.haml26
-rw-r--r--app/views/snippets/_snippets.html.haml2
-rw-r--r--app/views/snippets/_snippets_scope_menu.html.haml8
-rw-r--r--app/views/snippets/edit.html.haml5
-rw-r--r--app/views/snippets/index.html.haml6
-rw-r--r--app/views/snippets/new.html.haml14
-rw-r--r--app/views/snippets/notes/_actions.html.haml4
-rw-r--r--app/views/snippets/show.html.haml4
-rw-r--r--app/views/u2f/_authenticate.html.haml10
-rw-r--r--app/views/u2f/_register.html.haml22
-rw-r--r--app/views/users/_overview.html.haml30
-rw-r--r--app/views/users/calendar_activities.html.haml2
-rw-r--r--app/views/users/show.html.haml42
-rw-r--r--app/workers/all_queues.yml6
-rw-r--r--app/workers/archive_trace_worker.rb2
-rw-r--r--app/workers/build_finished_worker.rb2
-rw-r--r--app/workers/build_success_worker.rb16
-rw-r--r--app/workers/ci/archive_traces_cron_worker.rb14
-rw-r--r--app/workers/ci/build_schedule_worker.rb19
-rw-r--r--app/workers/cluster_platform_configure_worker.rb22
-rw-r--r--app/workers/cluster_provision_worker.rb2
-rw-r--r--app/workers/concerns/gitlab/github_import/stage_methods.rb2
-rw-r--r--app/workers/concerns/project_import_options.rb2
-rw-r--r--app/workers/concerns/project_start_import.rb6
-rw-r--r--app/workers/deployments/success_worker.rb17
-rw-r--r--app/workers/email_receiver_worker.rb2
-rw-r--r--app/workers/expire_build_instance_artifacts_worker.rb2
-rw-r--r--app/workers/gitlab/github_import/advance_stage_worker.rb13
-rw-r--r--app/workers/gitlab/github_import/refresh_import_jid_worker.rb14
-rw-r--r--app/workers/gitlab/github_import/stage/import_base_data_worker.rb2
-rw-r--r--app/workers/gitlab/github_import/stage/import_pull_requests_worker.rb2
-rw-r--r--app/workers/namespaceless_project_destroy_worker.rb2
-rw-r--r--app/workers/pipeline_schedule_worker.rb32
-rw-r--r--app/workers/post_receive.rb13
-rw-r--r--app/workers/process_commit_worker.rb2
-rw-r--r--app/workers/prune_old_events_worker.rb7
-rw-r--r--app/workers/repository_fork_worker.rb4
-rw-r--r--app/workers/repository_import_worker.rb4
-rw-r--r--app/workers/stuck_ci_jobs_worker.rb30
-rw-r--r--app/workers/stuck_import_jobs_worker.rb48
-rwxr-xr-xbin/profile-url2
-rwxr-xr-xbin/rails2
-rwxr-xr-xbin/rake2
-rwxr-xr-xbin/rspec2
-rwxr-xr-xbin/secpick14
-rwxr-xr-xbin/setup2
-rwxr-xr-xbin/storage_check11
-rwxr-xr-xbin/web5
-rwxr-xr-xbin/web_puma63
-rw-r--r--changelogs/archive.md2
-rw-r--r--changelogs/unreleased/1979-redesign-mr-widget-approvals-ce.yml5
-rw-r--r--changelogs/unreleased/21307-send-deployment-information-in-job-api.yml5
-rw-r--r--changelogs/unreleased/21617-initialize-projects-with-readme.yml5
-rw-r--r--changelogs/unreleased/23986-choose-commit-email.yml5
-rw-r--r--changelogs/unreleased/28682-can-merge-branch-before-build-is-started.yml5
-rw-r--r--changelogs/unreleased/29398-support-rbac-for-gitlab-provisioned-clusters.yml5
-rw-r--r--changelogs/unreleased/31887-remove-images-from-todos.yml5
-rw-r--r--changelogs/unreleased/33705-merge-request-rebase-api.yml5
-rw-r--r--changelogs/unreleased/34758-group-cluster-controller.yml5
-rw-r--r--changelogs/unreleased/38495-calendar-activities-in-timezone.yml5
-rw-r--r--changelogs/unreleased/40085-add-a-create_merge_request-quick-action.yml5
-rw-r--r--changelogs/unreleased/40260-reduce-gitaly-calls-project-pipeline-status.yml5
-rw-r--r--changelogs/unreleased/40385-prohibit_impersonation.yml5
-rw-r--r--changelogs/unreleased/41040-long-webhook-url-problem.yml5
-rw-r--r--changelogs/unreleased/41875-allow-pipelines-to-be-deleted-by-project-owners.yml5
-rw-r--r--changelogs/unreleased/42861-move-include-external-files-in-gitlab-ci-yml-from-starter-to-libre.yml5
-rw-r--r--changelogs/unreleased/44596-double-title-merge-request-message.yml5
-rw-r--r--changelogs/unreleased/44768-lazy-load-xterm-css.yml5
-rw-r--r--changelogs/unreleased/44998-split-admin-settings-into-multiple-sub-pages.yml5
-rw-r--r--changelogs/unreleased/45754-issue-mr-and-archived-projects.yml5
-rw-r--r--changelogs/unreleased/45754-open-issues-from-archived-project-listed-in-group-issue-board.yml5
-rw-r--r--changelogs/unreleased/46544-webide-ctrl-enter-commit-shortcut.yml5
-rw-r--r--changelogs/unreleased/46733-move-filter-dropdown-from-font-awesome-to-our-own-icons.yml5
-rw-r--r--changelogs/unreleased/46950-systemcheck-ruby-version.yml5
-rw-r--r--changelogs/unreleased/47398-user-is-unable-revoke-a-authorized-application-unless-user-oauth-applications-is-checked-in-admin-settings.yml6
-rw-r--r--changelogs/unreleased/48475-gitlab-pages-settings-regressions.yml5
-rw-r--r--changelogs/unreleased/48496-merge-request-refactor-does-not-highlight-selected-line.yml5
-rw-r--r--changelogs/unreleased/48902-fix-diff-vertical-alignment.yml5
-rw-r--r--changelogs/unreleased/49479-hide-unmerged-env-perf-stats.yml5
-rw-r--r--changelogs/unreleased/49565-ssh-push-mirroring.yml5
-rw-r--r--changelogs/unreleased/49726-upgrade-helm-to-2-11.yml5
-rw-r--r--changelogs/unreleased/49943-resolve-filter-bar-height-changes.yml5
-rw-r--r--changelogs/unreleased/49990-enable-omniauth-by-default.yml5
-rw-r--r--changelogs/unreleased/50111-improve-design-of-cluster-apps-to-handle-larger-quantity.yml5
-rw-r--r--changelogs/unreleased/50264-add-border-around-the-repository-file-tree.yml5
-rw-r--r--changelogs/unreleased/50341-cleanup-useless-project-import-attributes.yml6
-rw-r--r--changelogs/unreleased/50461-add-retried-builds-in-pipeline-stage-endpoint.yml5
-rw-r--r--changelogs/unreleased/50677-fix-cherry-pick-branch-empty-name.yml5
-rw-r--r--changelogs/unreleased/50678-ignores-project-pending-delete.yml5
-rw-r--r--changelogs/unreleased/50808-choosing-initialize-repo-with-a-readme-breaks-project-created-from-template.yml5
-rw-r--r--changelogs/unreleased/50835-add-filtering-sorting-for-labels-on-labels-page.yml5
-rw-r--r--changelogs/unreleased/50839-webide-mr-dropdown-filter.yml5
-rw-r--r--changelogs/unreleased/50989-add-trigger-information-to-job-api.yml5
-rw-r--r--changelogs/unreleased/51029-status-emoji-currently-replaces-avatar-on-mobile.yml5
-rw-r--r--changelogs/unreleased/51061-readme-url-n-1-rpc-call-resolved.yml5
-rw-r--r--changelogs/unreleased/51083-fix-move-api.yml5
-rw-r--r--changelogs/unreleased/51112-add-status-illustration-in-job-api.yml5
-rw-r--r--changelogs/unreleased/51259-ci-cd-gitlab-ui-1.yml5
-rw-r--r--changelogs/unreleased/51259-ci-cd-tooltips.yml6
-rw-r--r--changelogs/unreleased/51273-expose-runners-for-build-in-job-api.yml5
-rw-r--r--changelogs/unreleased/51450-vendor-refactor-registry-login.yml5
-rw-r--r--changelogs/unreleased/51549-runners-table.yml5
-rw-r--r--changelogs/unreleased/51564-fix-commit-email-usage.yml5
-rw-r--r--changelogs/unreleased/51571-wrapper-rake-task-uploads-migrate-os.yml5
-rw-r--r--changelogs/unreleased/51792-dont-delete-failed-install-pods.yml5
-rw-r--r--changelogs/unreleased/51959-branch-and-tag-name-links.yml5
-rw-r--r--changelogs/unreleased/52276-jump-to-top-in-merge-request.yml5
-rw-r--r--changelogs/unreleased/52370-filter-by-none-any-for-labels-in-issues-mrs-boards.yml5
-rw-r--r--changelogs/unreleased/52371-filter-by-none-any-for-labels-in-issues-mrs-api.yml5
-rw-r--r--changelogs/unreleased/52371-removes-patially-matching-no-label-and-makes-it-case-insensitive.yml5
-rw-r--r--changelogs/unreleased/52385-search-bar-for-dashboard-list.yml5
-rw-r--r--changelogs/unreleased/52453-show-subgroups-in-group-create-issue.yml5
-rw-r--r--changelogs/unreleased/52712-further-ui-improvements-to-profile-overview-tab.yml5
-rw-r--r--changelogs/unreleased/52828-inconsistency-in-fonts-used-for-branch-name-and-create-from-fields-when-creating-new-branch-from-ui.yml5
-rw-r--r--changelogs/unreleased/52940-fix-internal-email-pattern-not-respected.yml5
-rw-r--r--changelogs/unreleased/53289-update-haml_lint-to-0-28-0.yml5
-rw-r--r--changelogs/unreleased/53290-incorrect-project-list-order-select-default-label.yml5
-rw-r--r--changelogs/unreleased/53291-update-ffaker-to-2-10-0.yml5
-rw-r--r--changelogs/unreleased/53326-improve-issues-empty-state.yml5
-rw-r--r--changelogs/unreleased/53400-unstar-icon-button-is-misaligned.yml5
-rw-r--r--changelogs/unreleased/53578-fe-deployment-status.yml5
-rw-r--r--changelogs/unreleased/53626-update-config-map-on-install-retry.yml5
-rw-r--r--changelogs/unreleased/53640-follow-up-from-resolve-redesign-activity-feed.yml4
-rw-r--r--changelogs/unreleased/53700-hashed-storagemigration.yml5
-rw-r--r--changelogs/unreleased/53728-warn-in-web-editor-when-user-navigates-away.yml5
-rw-r--r--changelogs/unreleased/53816-empty-label-menu-if-not-logged-in.yml5
-rw-r--r--changelogs/unreleased/53874-navbar-lowres.yml5
-rw-r--r--changelogs/unreleased/53988-remove-notes-index-on-updated-at.yml5
-rw-r--r--changelogs/unreleased/53992-add-events-index-on-project-id-and-created-at.yml5
-rw-r--r--changelogs/unreleased/54004-update-asana-to-0-8-1.yml5
-rw-r--r--changelogs/unreleased/54010-update-asciidoctor-to-1-5-8.yml5
-rw-r--r--changelogs/unreleased/54015-Markdown-Editor-improve-Cursor-placement.yml5
-rw-r--r--changelogs/unreleased/54021-empty-button.yml5
-rw-r--r--changelogs/unreleased/54032-reply-shortcut-only-discussion-text.yml5
-rw-r--r--changelogs/unreleased/54048-Line-numbers-are-misaligned-in-file-blame-view.yml5
-rw-r--r--changelogs/unreleased/54093-the-default_value_for-gem-doesn-t-handle-actioncontroller-parameters-correctly.yml7
-rw-r--r--changelogs/unreleased/54201-update-rack-to-2-0-6.yml5
-rw-r--r--changelogs/unreleased/54218-fix-mergeUrlParams.yml5
-rw-r--r--changelogs/unreleased/54391-tag.yml5
-rw-r--r--changelogs/unreleased/54407-fix-limited-intersection-observers.yml5
-rw-r--r--changelogs/unreleased/54571-runner-tags.yml5
-rw-r--r--changelogs/unreleased/54648-fix-order-by-dropdown-tablet-screens.yml5
-rw-r--r--changelogs/unreleased/_acet-fix-flash-styling.yml5
-rw-r--r--changelogs/unreleased/ab-approximate-counts.yml5
-rw-r--r--changelogs/unreleased/add-2fa-button.yml5
-rw-r--r--changelogs/unreleased/add-most-stars-for-filter-option.yml5
-rw-r--r--changelogs/unreleased/added-glob-for-ci-changes-detection.yml5
-rw-r--r--changelogs/unreleased/an-gitaly-version-0-133-0.yml5
-rw-r--r--changelogs/unreleased/ashmckenzie-hmac-token-decode-and-tests.yml5
-rw-r--r--changelogs/unreleased/auto_devops_kubernetes_active.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-add-discord-service.yml5
-rw-r--r--changelogs/unreleased/bump_gpgme_gem.yml5
-rw-r--r--changelogs/unreleased/bvl-use-shell-writeref.yml5
-rw-r--r--changelogs/unreleased/ccr-50483_add_filter_for_group_milestones.yml5
-rw-r--r--changelogs/unreleased/ce-52811-fix_namespaces_api_routing.yml5
-rw-r--r--changelogs/unreleased/ce-54109-fix_user_by_any_email.yml5
-rw-r--r--changelogs/unreleased/certmanager-temp.yml5
-rw-r--r--changelogs/unreleased/check-if-fetched-data-does-is-complete.yml5
-rw-r--r--changelogs/unreleased/clean-gitlab-git.yml5
-rw-r--r--changelogs/unreleased/da-synchronize-the-default-branch-when-updating-a-remote-mirror.yml5
-rw-r--r--changelogs/unreleased/discussion-perf-improvement.yml5
-rw-r--r--changelogs/unreleased/dm-batch-loader-key.yml5
-rw-r--r--changelogs/unreleased/docs-minor-aws-fixes.yml5
-rw-r--r--changelogs/unreleased/document-raw-snippet-api.yml5
-rw-r--r--changelogs/unreleased/drop-default-value-status-deployments.yml5
-rw-r--r--changelogs/unreleased/drop-gcp-cluster-table.yml5
-rw-r--r--changelogs/unreleased/feature-runner-state-filter-for-admin-view.yml5
-rw-r--r--changelogs/unreleased/fix-chat-notification-service-for-ee.yml5
-rw-r--r--changelogs/unreleased/fix-deadlock-chunked-io.yml5
-rw-r--r--changelogs/unreleased/fix-leading-slash-in-redirects-plus-rubocop.yml5
-rw-r--r--changelogs/unreleased/fix-mention-in-edit-mr.yml5
-rw-r--r--changelogs/unreleased/fix-mr-widget-unrelated-deployment-status.yml5
-rw-r--r--changelogs/unreleased/fj-47494-upgrade-git-to-2-18-0.yml5
-rw-r--r--changelogs/unreleased/fj-force-content-disposition.yml5
-rw-r--r--changelogs/unreleased/force-post-migration-dir-schema-load.yml5
-rw-r--r--changelogs/unreleased/force-reload-arguments-1.yml5
-rw-r--r--changelogs/unreleased/frozen-string-app-controller.yml5
-rw-r--r--changelogs/unreleased/frozen-string-app-finders-graphql.yml5
-rw-r--r--changelogs/unreleased/frozen-string-enable-app-helpers.yml5
-rw-r--r--changelogs/unreleased/frozen-string-enable-vestigial.yml5
-rw-r--r--changelogs/unreleased/frozen-string-lib-gitlab-even-even-even-more.yml5
-rw-r--r--changelogs/unreleased/frozen-string-lib-gitlab-even-even-more.yml5
-rw-r--r--changelogs/unreleased/frozen-string-lib-gitlab-even-more.yml5
-rw-r--r--changelogs/unreleased/frozen-string-lib-gitlab-more.yml5
-rw-r--r--changelogs/unreleased/frozen-string-lib-rubocop.yml5
-rw-r--r--changelogs/unreleased/gt-align-issue-status-and-confidential-icon.yml5
-rw-r--r--changelogs/unreleased/gt-change-breadcrumb-title-for-contribution-charts.yml5
-rw-r--r--changelogs/unreleased/gt-externalize-app-views-invites.yml5
-rw-r--r--changelogs/unreleased/gt-externalize-app-views-project-runners.yml5
-rw-r--r--changelogs/unreleased/gt-externalize-app-views-snippets.yml5
-rw-r--r--changelogs/unreleased/gt-fix-typo-in-notebook-props.yml5
-rw-r--r--changelogs/unreleased/gt-fix-typos-in-lib.yml5
-rw-r--r--changelogs/unreleased/gt-remove-instances-of-extend-monospace.yml5
-rw-r--r--changelogs/unreleased/gt-remove-unused-project-method.yml5
-rw-r--r--changelogs/unreleased/gt-rename-diffs-store-variable.yml5
-rw-r--r--changelogs/unreleased/gt-update-env-metrics-empty-state.yml5
-rw-r--r--changelogs/unreleased/gt-use-gl-tooltip-directive.yml5
-rw-r--r--changelogs/unreleased/ide-open-all-mr-files.yml5
-rw-r--r--changelogs/unreleased/ignore-failed-pipeline-creation-on-pipeline-schedule.yml5
-rw-r--r--changelogs/unreleased/improve_auto_devops_migration_debug.yml6
-rw-r--r--changelogs/unreleased/include-new-link-in-breadcrumb.yml5
-rw-r--r--changelogs/unreleased/issue_50528.yml5
-rw-r--r--changelogs/unreleased/jivl-add-empty-state-graphs-null-values.yml5
-rw-r--r--changelogs/unreleased/jupyter-tls.yml5
-rw-r--r--changelogs/unreleased/kcj-add-philosophy.yml5
-rw-r--r--changelogs/unreleased/kubernetes-http-response-code.yml5
-rw-r--r--changelogs/unreleased/legacy_fallback_for_project_clusters_only.yml5
-rw-r--r--changelogs/unreleased/lock-trace-writes.yml5
-rw-r--r--changelogs/unreleased/lock-unlock-quick-actions.yml5
-rw-r--r--changelogs/unreleased/mr-file-tree-commit.yml5
-rw-r--r--changelogs/unreleased/mr-legacy-diff-notes.yml5
-rw-r--r--changelogs/unreleased/mr-origin-23218.yml5
-rw-r--r--changelogs/unreleased/mr-sticky-headers.yml5
-rw-r--r--changelogs/unreleased/mr-tree-filter-path-name.yml5
-rw-r--r--changelogs/unreleased/mr-widget-discussion-state-fix.yml5
-rw-r--r--changelogs/unreleased/non-webkit-scrollbar-fixing.yml5
-rw-r--r--changelogs/unreleased/optimise-job-request.yml5
-rw-r--r--changelogs/unreleased/order-of-notification-settings.yml5
-rw-r--r--changelogs/unreleased/osw-fallback-on-blank-refs.yml5
-rw-r--r--changelogs/unreleased/osw-gitaly-diff-stats-client.yml5
-rw-r--r--changelogs/unreleased/osw-use-diff-stats-rpc-on-comparison-views.yml5
-rw-r--r--changelogs/unreleased/project_identicon_fix.yml5
-rw-r--r--changelogs/unreleased/rails5-active-record-class-value.yml5
-rw-r--r--changelogs/unreleased/rails5-deprecation-render-nothing.yml6
-rw-r--r--changelogs/unreleased/rails5-env-deprecated.yml5
-rw-r--r--changelogs/unreleased/rails5-fix-issue-move-service.yml6
-rw-r--r--changelogs/unreleased/remove-deployment-status-hack-from-backend.yml5
-rw-r--r--changelogs/unreleased/remove-duplicate-primary-button-in-dashboard-snippets.yml5
-rw-r--r--changelogs/unreleased/remove-sidekiq.yml5
-rw-r--r--changelogs/unreleased/render-text-deprecated.yml6
-rw-r--r--changelogs/unreleased/rs-cherry-pick-api.yml5
-rw-r--r--changelogs/unreleased/security-182-update-workhorse.yml5
-rw-r--r--changelogs/unreleased/security-2717-xss-username-autocomplete.yml5
-rw-r--r--changelogs/unreleased/security-2736-prometheus-ssrf.yml5
-rw-r--r--changelogs/unreleased/security-bvl-exposure-in-commits-list.yml5
-rw-r--r--changelogs/unreleased/security-email-change-notification.yml5
-rw-r--r--changelogs/unreleased/security-fix-pat-web-access.yml5
-rw-r--r--changelogs/unreleased/security-fix-uri-xss-applications.yml5
-rw-r--r--changelogs/unreleased/security-fix-webhook-ssrf-ipv6.yml5
-rw-r--r--changelogs/unreleased/security-fj-crlf-injection.yml5
-rw-r--r--changelogs/unreleased/security-guest-comments.yml5
-rw-r--r--changelogs/unreleased/security-guest-comments_2.yml5
-rw-r--r--changelogs/unreleased/security-issue_51301.yml5
-rw-r--r--changelogs/unreleased/security-mermaid-xss.yml5
-rw-r--r--changelogs/unreleased/security-pages-toctou-race.yml6
-rw-r--r--changelogs/unreleased/security-private-group.yml6
-rw-r--r--changelogs/unreleased/security-stored-xss-for-environments.yml5
-rw-r--r--changelogs/unreleased/security-xss-in-markdown-following-unrecognized-html-element.yml5
-rw-r--r--changelogs/unreleased/sh-53180-append-path.yml5
-rw-r--r--changelogs/unreleased/sh-allow-key-id-in-params.yml5
-rw-r--r--changelogs/unreleased/sh-bump-gems-security.yml5
-rw-r--r--changelogs/unreleased/sh-bump-ruby-2-5-3.yml5
-rw-r--r--changelogs/unreleased/sh-delete-tags-outside-transaction.yml5
-rw-r--r--changelogs/unreleased/sh-disable-autocomplete-mirror-settings.yml5
-rw-r--r--changelogs/unreleased/sh-fix-issue-38317.yml5
-rw-r--r--changelogs/unreleased/sh-fix-issue-51220.yml5
-rw-r--r--changelogs/unreleased/sh-fix-issue-53783-ce.yml5
-rw-r--r--changelogs/unreleased/sh-fix-mirrors-protected-branches.yml5
-rw-r--r--changelogs/unreleased/sh-fix-multipart-upload-signed-urls.yml5
-rw-r--r--changelogs/unreleased/sh-handle-string-null-bytes.yml5
-rw-r--r--changelogs/unreleased/sh-remove-local-sidekiq-admin-check.yml5
-rw-r--r--changelogs/unreleased/sh-support-adding-confirmed-emails.yml5
-rw-r--r--changelogs/unreleased/sh-upgrade-katex-0-9-0.yml5
-rw-r--r--changelogs/unreleased/sh-use-nakayoshi-fork.yml5
-rw-r--r--changelogs/unreleased/sh-use-nokogiri-xml-backend.yml5
-rw-r--r--changelogs/unreleased/speed-up-relative-positioning.yml5
-rw-r--r--changelogs/unreleased/switch-rails.yml5
-rw-r--r--changelogs/unreleased/tc-backfill-full-path-config.yml5
-rw-r--r--changelogs/unreleased/tc-repo-full-path-in-db.yml5
-rw-r--r--changelogs/unreleased/triggermesh-phase2-external-ip.yml5
-rw-r--r--changelogs/unreleased/triggermesh-phase2-knative-description.yml5
-rw-r--r--changelogs/unreleased/triggermesh-phase2-serverless.yml5
-rw-r--r--changelogs/unreleased/unicorn-monkey-patch.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-version.yml5
-rw-r--r--changelogs/unreleased/upgrade_kubeclient_400.yml5
-rw-r--r--changelogs/unreleased/validate-foreign-keys-being-indexed.yml5
-rw-r--r--changelogs/unreleased/vendor-auto-devops-gitlab-ci-fix-503-on-deploy.yml6
-rw-r--r--changelogs/unreleased/vendor-gitlab-ci-auto-devops-yml.yml5
-rw-r--r--changelogs/unreleased/winh-collapse-discussions.yml5
-rw-r--r--changelogs/unreleased/winh-merge-request-commit-discussion.yml5
-rw-r--r--changelogs/unreleased/workhorse-7-3-0.yml5
-rw-r--r--changelogs/unreleased/zj-improve-gitaly-pb.yml5
-rw-r--r--changelogs/unreleased/zj-remove-broken-storage.yml5
-rw-r--r--config.ru4
-rw-r--r--config/application.rb19
-rw-r--r--config/boot.rb6
-rw-r--r--config/dependency_decisions.yml23
-rw-r--r--config/environment.rb6
-rw-r--r--config/environments/development.rb2
-rw-r--r--config/environments/production.rb6
-rw-r--r--config/gitlab.yml.example13
-rw-r--r--config/initializers/1_settings.rb2
-rw-r--r--config/initializers/7_prometheus_metrics.rb22
-rw-r--r--config/initializers/8_metrics.rb22
-rw-r--r--config/initializers/action_dispatch_http_mime_negotiation.rb19
-rw-r--r--config/initializers/active_record_lifecycle.rb23
-rw-r--r--config/initializers/asset_sync.rb31
-rw-r--r--config/initializers/attr_encrypted_no_db_connection.rb24
-rw-r--r--config/initializers/devise.rb3
-rw-r--r--config/initializers/doorkeeper.rb7
-rw-r--r--config/initializers/fill_shards.rb3
-rw-r--r--config/initializers/gollum.rb28
-rw-r--r--config/initializers/hipchat_client_patch.rb14
-rw-r--r--config/initializers/kubeclient.rb32
-rw-r--r--config/initializers/macos.rb13
-rw-r--r--config/initializers/mysql_set_length_for_binary_indexes.rb50
-rw-r--r--config/initializers/postgresql_opclasses_support.rb4
-rw-r--r--config/initializers/rack_attack_global.rb10
-rw-r--r--config/initializers/rbtrace.rb9
-rw-r--r--config/initializers/routing_draw.rb8
-rw-r--r--config/initializers/sidekiq.rb15
-rw-r--r--config/initializers/warden.rb5
-rw-r--r--config/karma.config.js9
-rw-r--r--config/locales/en.yml2
-rw-r--r--config/puma.example.development.rb77
-rw-r--r--config/routes.rb29
-rw-r--r--config/routes/admin.rb8
-rw-r--r--config/routes/group.rb9
-rw-r--r--config/routes/project.rb21
-rw-r--r--config/routes/user.rb1
-rw-r--r--config/routes/wiki.rb2
-rw-r--r--config/sidekiq_queues.yml1
-rw-r--r--config/unicorn.rb.example37
-rw-r--r--config/unicorn.rb.example.development67
-rw-r--r--config/webpack.config.js14
-rw-r--r--danger/database/Dangerfile4
-rw-r--r--danger/documentation/Dangerfile28
-rw-r--r--danger/eslint/Dangerfile29
-rw-r--r--danger/metadata/Dangerfile7
-rw-r--r--danger/plugins/helper.rb34
-rw-r--r--danger/prettier/Dangerfile39
-rw-r--r--danger/specs/Dangerfile6
-rw-r--r--db/fixtures/development/04_project.rb10
-rw-r--r--db/fixtures/development/09_issues.rb3
-rw-r--r--db/fixtures/development/14_pipelines.rb75
-rw-r--r--db/fixtures/development/17_cycle_analytics.rb10
-rw-r--r--db/migrate/20140313092127_init_schema.rb2
-rw-r--r--db/migrate/20140407135544_fix_namespaces.rb2
-rw-r--r--db/migrate/20140414131055_change_state_to_allow_empty_merge_request_diffs.rb2
-rw-r--r--db/migrate/20140416074002_add_index_on_iid.rb2
-rw-r--r--db/migrate/20140416185734_index_on_current_sign_in_at.rb2
-rw-r--r--db/migrate/20140428105831_add_notes_index_updated_at.rb2
-rw-r--r--db/migrate/20140502115131_add_repo_size_to_db.rb2
-rw-r--r--db/migrate/20140502125220_migrate_repo_size.rb2
-rw-r--r--db/migrate/20140611135229_add_position_to_merge_request.rb2
-rw-r--r--db/migrate/20140625115202_create_users_star_projects.rb2
-rw-r--r--db/migrate/20140729134820_create_labels.rb2
-rw-r--r--db/migrate/20140729140420_create_label_links.rb2
-rw-r--r--db/migrate/20140729145339_migrate_project_tags.rb2
-rw-r--r--db/migrate/20140729152420_migrate_taggable_labels.rb2
-rw-r--r--db/migrate/20140730111702_add_index_to_labels.rb2
-rw-r--r--db/migrate/20140903115954_migrate_to_new_shell.rb2
-rw-r--r--db/migrate/20140907220153_serialize_service_properties.rb2
-rw-r--r--db/migrate/20140914113604_add_members_table.rb2
-rw-r--r--db/migrate/20140914145549_migrate_to_new_members_model.rb2
-rw-r--r--db/migrate/20140914173417_remove_old_member_tables.rb2
-rw-r--r--db/migrate/20141006143943_move_slack_service_to_webhook.rb2
-rw-r--r--db/migrate/20141007100818_add_visibility_level_to_snippet.rb2
-rw-r--r--db/migrate/20141118150935_add_audit_event.rb2
-rw-r--r--db/migrate/20141121133009_add_timestamps_to_members.rb2
-rw-r--r--db/migrate/20141121161704_add_identity_table.rb2
-rw-r--r--db/migrate/20141126120926_add_merge_request_rebase_enabled_to_projects.rb2
-rw-r--r--db/migrate/20141205134006_add_locked_at_to_merge_request.rb2
-rw-r--r--db/migrate/20141216155758_create_doorkeeper_tables.rb2
-rw-r--r--db/migrate/20141217125223_add_owner_to_application.rb2
-rw-r--r--db/migrate/20141223135007_add_import_data_to_project_table.rb2
-rw-r--r--db/migrate/20141226080412_add_developers_can_push_to_protected_branches.rb2
-rw-r--r--db/migrate/20150108073740_create_application_settings.rb2
-rw-r--r--db/migrate/20150116234544_add_home_page_url_for_application_settings.rb2
-rw-r--r--db/migrate/20150116234545_add_gitlab_access_token_to_user.rb2
-rw-r--r--db/migrate/20150125163100_add_default_branch_protection_setting.rb2
-rw-r--r--db/migrate/20150205211843_add_timestamps_to_identities.rb2
-rw-r--r--db/migrate/20150206181414_add_index_to_created_at.rb2
-rw-r--r--db/migrate/20150206222854_add_notification_email_to_user.rb2
-rw-r--r--db/migrate/20150209222013_add_missing_index.rb2
-rw-r--r--db/migrate/20150211172122_add_template_to_service.rb2
-rw-r--r--db/migrate/20150211174341_allow_null_in_services_project_id.rb2
-rw-r--r--db/migrate/20150213104043_add_twitter_sharing_enabled_to_application_settings.rb2
-rw-r--r--db/migrate/20150213114800_add_hide_no_password_to_user.rb2
-rw-r--r--db/migrate/20150213121042_add_password_automatically_set_to_user.rb2
-rw-r--r--db/migrate/20150217123345_add_bitbucket_access_token_and_secret_to_user.rb2
-rw-r--r--db/migrate/20150219004514_add_events_to_services.rb2
-rw-r--r--db/migrate/20150223022001_set_missing_last_activity_at.rb2
-rw-r--r--db/migrate/20150225065047_add_note_events_to_services.rb2
-rw-r--r--db/migrate/20150301014758_add_restricted_visibility_levels_to_application_settings.rb2
-rw-r--r--db/migrate/20150306023106_fix_namespace_duplication.rb2
-rw-r--r--db/migrate/20150306023112_add_unique_index_to_namespace.rb2
-rw-r--r--db/migrate/20150310194358_add_version_check_to_application_settings.rb2
-rw-r--r--db/migrate/20150313012111_create_subscriptions_table.rb2
-rw-r--r--db/migrate/20150320234437_add_location_to_user.rb2
-rw-r--r--db/migrate/20150324155957_set_incorrect_assignee_id_to_null.rb2
-rw-r--r--db/migrate/20150327122227_add_public_to_key.rb2
-rw-r--r--db/migrate/20150327150017_add_import_data_to_project.rb2
-rw-r--r--db/migrate/20150327223628_add_devise_two_factor_to_users.rb2
-rw-r--r--db/migrate/20150328132231_add_max_attachment_size_to_application_settings.rb2
-rw-r--r--db/migrate/20150331183602_add_devise_two_factor_backupable_to_users.rb2
-rw-r--r--db/migrate/20150406133311_add_invite_data_to_member.rb2
-rw-r--r--db/migrate/20150411000035_fix_identities.rb2
-rw-r--r--db/migrate/20150411180045_rename_buildbox_service.rb2
-rw-r--r--db/migrate/20150413192223_add_public_email_to_users.rb2
-rw-r--r--db/migrate/20150417121913_create_project_import_data.rb2
-rw-r--r--db/migrate/20150417122318_remove_import_data_from_project.rb2
-rw-r--r--db/migrate/20150421120000_remove_periods_at_ends_of_usernames.rb2
-rw-r--r--db/migrate/20150423033240_add_default_project_visibililty_to_application_settings.rb2
-rw-r--r--db/migrate/20150425164646_gitlab_change_collation_for_tag_names.acts_as_taggable_on_engine.rb2
-rw-r--r--db/migrate/20150425164647_remove_duplicate_tags.rb2
-rw-r--r--db/migrate/20150425164648_add_missing_unique_indices.acts_as_taggable_on_engine.rb2
-rw-r--r--db/migrate/20150425164649_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb2
-rw-r--r--db/migrate/20150425164650_add_missing_taggable_index.acts_as_taggable_on_engine.rb2
-rw-r--r--db/migrate/20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb2
-rw-r--r--db/migrate/20150425173433_add_default_snippet_visibility_to_app_settings.rb2
-rw-r--r--db/migrate/20150429002313_remove_abandoned_group_members_records.rb2
-rw-r--r--db/migrate/20150502064022_add_restricted_signup_domains_to_application_settings.rb2
-rw-r--r--db/migrate/20150509180749_convert_legacy_reference_notes.rb2
-rw-r--r--db/migrate/20150516060434_add_note_events_to_web_hooks.rb2
-rw-r--r--db/migrate/20150529111607_add_user_oauth_applications_to_application_settings.rb2
-rw-r--r--db/migrate/20150529150354_add_after_sign_out_path_for_application_settings.rb2
-rw-r--r--db/migrate/20150609141121_add_session_expire_delay_for_application_settings.rb2
-rw-r--r--db/migrate/20150610065936_add_dashboard_to_users.rb2
-rw-r--r--db/migrate/20150620233230_add_default_otp_required_for_login_value.rb2
-rw-r--r--db/migrate/20150713160110_add_project_view_to_users.rb2
-rw-r--r--db/migrate/20150717130904_add_commits_count_to_project.rb2
-rw-r--r--db/migrate/20150730122406_add_updated_by_to_issuables_and_notes.rb2
-rw-r--r--db/migrate/20150806104937_create_abuse_reports.rb2
-rw-r--r--db/migrate/20150812080800_add_settings_import_sources.rb2
-rw-r--r--db/migrate/20150814065925_remove_oauth_tokens_from_users.rb2
-rw-r--r--db/migrate/20150817163600_deduplicate_user_identities.rb2
-rw-r--r--db/migrate/20150818213832_add_sent_notifications.rb2
-rw-r--r--db/migrate/20150824002011_add_enable_ssl_verification.rb2
-rw-r--r--db/migrate/20150826001931_add_ci_tables.rb2
-rw-r--r--db/migrate/20150827121444_add_fast_forward_option_to_project.rb2
-rw-r--r--db/migrate/20150902001023_add_template_to_label.rb2
-rw-r--r--db/migrate/20150914215247_add_ci_tags.rb2
-rw-r--r--db/migrate/20150915001905_enable_ssl_verification_by_default.rb2
-rw-r--r--db/migrate/20150916000405_enable_ssl_verification_for_web_hooks.rb2
-rw-r--r--db/migrate/20150916114643_add_help_page_text_to_application_settings.rb2
-rw-r--r--db/migrate/20150916145038_add_index_for_committed_at_and_id.rb2
-rw-r--r--db/migrate/20150918084513_add_ci_enabled_to_application_settings.rb2
-rw-r--r--db/migrate/20150918161719_remove_invalid_milestones_from_merge_requests.rb2
-rw-r--r--db/migrate/20150920010715_add_consumed_timestep_to_users.rb2
-rw-r--r--db/migrate/20150920161119_add_line_code_to_sent_notification.rb2
-rw-r--r--db/migrate/20150924125150_add_project_id_to_ci_commit.rb2
-rw-r--r--db/migrate/20150924125436_migrate_project_id_for_ci_commits.rb2
-rw-r--r--db/migrate/20150930001110_merge_request_error_field.rb2
-rw-r--r--db/migrate/20150930095736_add_null_to_name_for_ci_projects.rb2
-rw-r--r--db/migrate/20150930110012_add_group_share_lock.rb2
-rw-r--r--db/migrate/20151002112914_add_stage_idx_to_builds.rb2
-rw-r--r--db/migrate/20151002121400_add_index_for_builds.rb2
-rw-r--r--db/migrate/20151002122929_add_ref_and_tag_to_builds.rb2
-rw-r--r--db/migrate/20151002122943_migrate_ref_and_tag_to_build.rb2
-rw-r--r--db/migrate/20151005075649_add_user_id_to_build.rb2
-rw-r--r--db/migrate/20151005150751_add_layout_option_for_users.rb2
-rw-r--r--db/migrate/20151005162154_remove_ci_enabled_from_application_settings.rb2
-rw-r--r--db/migrate/20151007120511_namespaces_projects_path_lower_indexes.rb2
-rw-r--r--db/migrate/20151008110232_add_users_lower_username_email_indexes.rb2
-rw-r--r--db/migrate/20151008123042_add_type_and_description_to_builds.rb2
-rw-r--r--db/migrate/20151008130321_migrate_name_to_description_for_builds.rb2
-rw-r--r--db/migrate/20151008143519_add_admin_notification_email_setting.rb2
-rw-r--r--db/migrate/20151012173029_set_jira_service_api_url.rb2
-rw-r--r--db/migrate/20151013092124_add_artifacts_file_to_builds.rb2
-rw-r--r--db/migrate/20151016131433_add_ci_projects_gl_project_id_index.rb2
-rw-r--r--db/migrate/20151016195451_add_ci_builds_and_projects_indexes.rb2
-rw-r--r--db/migrate/20151016195706_add_notes_line_code_index.rb2
-rw-r--r--db/migrate/20151019111551_fix_build_tags.rb2
-rw-r--r--db/migrate/20151019111703_fail_build_without_names.rb2
-rw-r--r--db/migrate/20151020145526_add_services_template_index.rb2
-rw-r--r--db/migrate/20151020173516_ci_limits_to_mysql.rb2
-rw-r--r--db/migrate/20151020173906_add_ci_builds_index_for_status.rb2
-rw-r--r--db/migrate/20151023112551_fail_build_with_empty_name.rb2
-rw-r--r--db/migrate/20151023144219_remove_satellites.rb2
-rw-r--r--db/migrate/20151026182941_add_project_path_index.rb2
-rw-r--r--db/migrate/20151028152939_add_merge_when_build_succeeds_to_merge_request.rb2
-rw-r--r--db/migrate/20151103001141_add_public_to_group.rb2
-rw-r--r--db/migrate/20151103133339_add_shared_runners_setting.rb2
-rw-r--r--db/migrate/20151103134857_create_lfs_objects.rb2
-rw-r--r--db/migrate/20151103134958_create_lfs_objects_projects.rb2
-rw-r--r--db/migrate/20151104105513_add_file_to_lfs_objects.rb2
-rw-r--r--db/migrate/20151105094515_create_releases.rb2
-rw-r--r--db/migrate/20151106000015_add_is_award_to_notes.rb2
-rw-r--r--db/migrate/20151109100728_add_max_artifacts_size_to_application_settings.rb2
-rw-r--r--db/migrate/20151109134526_add_issues_state_index.rb2
-rw-r--r--db/migrate/20151109134916_add_projects_visibility_level_index.rb2
-rw-r--r--db/migrate/20151110125604_add_import_error_to_project.rb2
-rw-r--r--db/migrate/20151114113410_add_index_for_lfs_oid_and_size.rb2
-rw-r--r--db/migrate/20151116144118_add_unique_for_lfs_oid_index.rb2
-rw-r--r--db/migrate/20151118162244_add_projects_public_index.rb2
-rw-r--r--db/migrate/20151201203948_raise_hook_url_limit.rb2
-rw-r--r--db/migrate/20151203162133_add_hide_project_limit_to_users.rb2
-rw-r--r--db/migrate/20151203162134_add_build_events_to_services.rb2
-rw-r--r--db/migrate/20151209144329_migrate_ci_web_hooks.rb2
-rw-r--r--db/migrate/20151209145909_migrate_ci_emails.rb2
-rw-r--r--db/migrate/20151210030143_add_unlock_token_to_user.rb2
-rw-r--r--db/migrate/20151210072243_add_runners_registration_token_to_application_settings.rb2
-rw-r--r--db/migrate/20151210125232_migrate_ci_slack_service.rb2
-rw-r--r--db/migrate/20151210125927_migrate_ci_hip_chat_service.rb2
-rw-r--r--db/migrate/20151210125928_add_ci_to_project.rb2
-rw-r--r--db/migrate/20151210125929_add_project_id_to_ci.rb2
-rw-r--r--db/migrate/20151210125930_migrate_ci_to_project.rb2
-rw-r--r--db/migrate/20151210125931_add_index_to_ci_tables.rb2
-rw-r--r--db/migrate/20151210125932_drop_null_for_ci_tables.rb2
-rw-r--r--db/migrate/20151215132013_add_pages_size_to_application_settings.rb2
-rw-r--r--db/migrate/20151218154042_add_tfa_to_application_settings.rb2
-rw-r--r--db/migrate/20151221234414_add_tfa_additional_fields.rb2
-rw-r--r--db/migrate/20151224123230_rename_emojis.rb2
-rw-r--r--db/migrate/20151228111122_remove_public_from_namespace.rb2
-rw-r--r--db/migrate/20151228150906_influxdb_settings.rb2
-rw-r--r--db/migrate/20151228175719_add_recaptcha_to_application_settings.rb2
-rw-r--r--db/migrate/20151229102248_influxdb_udp_port_setting.rb2
-rw-r--r--db/migrate/20151229112614_influxdb_remote_database_setting.rb2
-rw-r--r--db/migrate/20151230132518_add_artifacts_metadata_to_ci_build.rb2
-rw-r--r--db/migrate/20151231152326_add_akismet_to_application_settings.rb2
-rw-r--r--db/migrate/20151231202530_remove_alert_type_from_broadcast_messages.rb2
-rw-r--r--db/migrate/20160106162223_add_index_milestones_title.rb2
-rw-r--r--db/migrate/20160106164438_remove_influxdb_credentials.rb2
-rw-r--r--db/migrate/20160109054846_create_spam_logs.rb2
-rw-r--r--db/migrate/20160113111034_add_metrics_sample_interval.rb2
-rw-r--r--db/migrate/20160118155830_add_sentry_to_application_settings.rb2
-rw-r--r--db/migrate/20160118232755_add_ip_blocking_settings_to_application_settings.rb2
-rw-r--r--db/migrate/20160119111158_add_services_category.rb2
-rw-r--r--db/migrate/20160119112418_add_services_default.rb2
-rw-r--r--db/migrate/20160119145451_add_ldap_email_to_users.rb2
-rw-r--r--db/migrate/20160120172143_add_base_commit_sha_to_merge_request_diffs.rb2
-rw-r--r--db/migrate/20160121030729_add_email_author_in_body_to_application_settings.rb2
-rw-r--r--db/migrate/20160122185421_add_pending_delete_to_project.rb2
-rw-r--r--db/migrate/20160128212447_remove_ip_blocking_settings_from_application_settings.rb2
-rw-r--r--db/migrate/20160128233227_change_lfs_objects_size_column.rb2
-rw-r--r--db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb2
-rw-r--r--db/migrate/20160129155512_add_merge_commit_sha_to_merge_requests.rb2
-rw-r--r--db/migrate/20160202091601_add_erasable_to_ci_build.rb2
-rw-r--r--db/migrate/20160202164642_add_allow_guest_to_access_builds_project.rb2
-rw-r--r--db/migrate/20160204144558_add_real_size_to_merge_request_diffs.rb2
-rw-r--r--db/migrate/20160209130428_add_index_to_snippet.rb2
-rw-r--r--db/migrate/20160210105555_create_pages_domain.rb2
-rw-r--r--db/migrate/20160212123307_create_tasks.rb2
-rw-r--r--db/migrate/20160217100506_add_description_to_label.rb2
-rw-r--r--db/migrate/20160217174422_add_note_to_tasks.rb2
-rw-r--r--db/migrate/20160220123949_rename_tasks_to_todos.rb2
-rw-r--r--db/migrate/20160222153918_create_appearances_ce.rb2
-rw-r--r--db/migrate/20160223192159_add_confidential_to_issues.rb2
-rw-r--r--db/migrate/20160225090018_add_delete_at_to_issues.rb2
-rw-r--r--db/migrate/20160225101956_add_delete_at_to_merge_requests.rb2
-rw-r--r--db/migrate/20160226114608_add_trigram_indexes_for_searching.rb2
-rw-r--r--db/migrate/20160227120001_add_event_field_for_web_hook.rb2
-rw-r--r--db/migrate/20160227120047_add_event_to_services.rb2
-rw-r--r--db/migrate/20160229193553_add_main_language_to_repository.rb2
-rw-r--r--db/migrate/20160301124843_add_visibility_level_to_groups.rb2
-rw-r--r--db/migrate/20160301174731_add_fingerprint_index.rb2
-rw-r--r--db/migrate/20160302151724_add_import_credentials_to_project_import_data.rb2
-rw-r--r--db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb2
-rw-r--r--db/migrate/20160305220806_remove_expires_at_from_snippets.rb2
-rw-r--r--db/migrate/20160307221555_disallow_blank_line_code_on_note.rb2
-rw-r--r--db/migrate/20160308212903_add_default_group_visibility_to_application_settings.rb2
-rw-r--r--db/migrate/20160309140734_fix_todos.rb2
-rw-r--r--db/migrate/20160310124959_add_due_date_to_issues.rb2
-rw-r--r--db/migrate/20160310185910_add_external_flag_to_users.rb2
-rw-r--r--db/migrate/20160314094147_add_priority_to_label.rb2
-rw-r--r--db/migrate/20160314114439_add_requested_at_to_members.rb2
-rw-r--r--db/migrate/20160314143402_projects_add_pushes_since_gc.rb2
-rw-r--r--db/migrate/20160315135439_project_add_repository_check.rb2
-rw-r--r--db/migrate/20160316123110_ci_runners_token_index.rb2
-rw-r--r--db/migrate/20160316192622_change_target_id_to_null_on_todos.rb2
-rw-r--r--db/migrate/20160316204731_add_commit_id_to_todos.rb2
-rw-r--r--db/migrate/20160317092222_add_moved_to_to_issue.rb2
-rw-r--r--db/migrate/20160320204112_index_namespaces_on_visibility_level.rb2
-rw-r--r--db/migrate/20160324020319_remove_todos_for_deleted_issues.rb2
-rw-r--r--db/migrate/20160328112808_create_notification_settings.rb2
-rw-r--r--db/migrate/20160328115649_migrate_new_notification_setting.rb2
-rw-r--r--db/migrate/20160328121138_add_notification_setting_index.rb2
-rw-r--r--db/migrate/20160329144452_add_index_on_pending_delete_projects.rb2
-rw-r--r--db/migrate/20160331133914_remove_todos_for_deleted_merge_requests.rb2
-rw-r--r--db/migrate/20160331223143_remove_twitter_sharing_enabled_from_application_settings.rb2
-rw-r--r--db/migrate/20160407120251_add_images_enabled_for_project.rb2
-rw-r--r--db/migrate/20160412140240_add_repository_checks_enabled_setting.rb2
-rw-r--r--db/migrate/20160412173416_add_fields_to_ci_commit.rb2
-rw-r--r--db/migrate/20160412173417_update_ci_commit.rb2
-rw-r--r--db/migrate/20160412173418_add_ci_commit_indexes.rb2
-rw-r--r--db/migrate/20160413115152_add_token_to_web_hooks.rb2
-rw-r--r--db/migrate/20160415062917_create_personal_access_tokens.rb2
-rw-r--r--db/migrate/20160415133440_add_shared_runners_text_to_application_settings.rb2
-rw-r--r--db/migrate/20160416180807_add_award_emoji.rb2
-rw-r--r--db/migrate/20160416182152_convert_award_note_to_emoji_award.rb2
-rw-r--r--db/migrate/20160419120017_add_metrics_packet_size.rb2
-rw-r--r--db/migrate/20160419122101_add_only_allow_merge_if_build_succeeds_to_projects.rb2
-rw-r--r--db/migrate/20160421130527_disable_repository_checks.rb2
-rw-r--r--db/migrate/20160425045124_create_u2f_registrations.rb2
-rw-r--r--db/migrate/20160504091942_add_disabled_oauth_sign_in_sources_to_application_settings.rb2
-rw-r--r--db/migrate/20160504112519_add_run_untagged_to_ci_runner.rb2
-rw-r--r--db/migrate/20160508194200_remove_wall_enabled_from_projects.rb2
-rw-r--r--db/migrate/20160508202603_add_head_commit_id_to_merge_request_diffs.rb2
-rw-r--r--db/migrate/20160508215820_add_type_to_notes.rb2
-rw-r--r--db/migrate/20160508215920_add_positions_to_diff_notes.rb2
-rw-r--r--db/migrate/20160508221410_set_type_on_legacy_diff_notes.rb2
-rw-r--r--db/migrate/20160509091049_add_locked_to_ci_runner.rb2
-rw-r--r--db/migrate/20160509201028_add_health_check_access_token_to_application_settings.rb2
-rw-r--r--db/migrate/20160516174813_add_send_user_confirmation_email_to_application_settings.rb2
-rw-r--r--db/migrate/20160516224534_add_start_commit_id_to_merge_request_diffs.rb2
-rw-r--r--db/migrate/20160518200441_add_artifacts_expire_date_to_ci_builds.rb2
-rw-r--r--db/migrate/20160519203051_add_developers_can_merge_to_protected_branches.rb2
-rw-r--r--db/migrate/20160522215720_add_note_type_and_position_to_sent_notification.rb2
-rw-r--r--db/migrate/20160525205328_remove_main_language_from_projects.rb2
-rw-r--r--db/migrate/20160527020117_remove_notification_settings_for_deleted_projects.rb2
-rw-r--r--db/migrate/20160528043124_add_users_state_index.rb2
-rw-r--r--db/migrate/20160530150109_add_container_registry_token_expire_delay_to_application_settings.rb2
-rw-r--r--db/migrate/20160603075128_add_has_external_issue_tracker_to_projects.rb2
-rw-r--r--db/migrate/20160603180330_remove_duplicated_notification_settings.rb2
-rw-r--r--db/migrate/20160603182247_add_index_to_notification_settings.rb2
-rw-r--r--db/migrate/20160608155312_add_after_sign_up_text_to_application_settings.rb2
-rw-r--r--db/migrate/20160608195742_add_repository_storage_to_projects.rb2
-rw-r--r--db/migrate/20160608211215_add_user_default_external_to_application_settings.rb2
-rw-r--r--db/migrate/20160610140403_remove_notification_setting_not_null_constraints.rb2
-rw-r--r--db/migrate/20160610194713_remove_deprecated_issues_tracker_columns_from_projects.rb2
-rw-r--r--db/migrate/20160610201627_migrate_users_notification_level.rb2
-rw-r--r--db/migrate/20160610204157_add_deployments.rb2
-rw-r--r--db/migrate/20160610204158_add_environments.rb2
-rw-r--r--db/migrate/20160610211845_add_environment_to_builds.rb2
-rw-r--r--db/migrate/20160610301627_remove_notification_level_from_users.rb2
-rw-r--r--db/migrate/20160614182521_add_repository_storage_to_application_settings.rb2
-rw-r--r--db/migrate/20160615142710_add_index_on_requested_at_to_members.rb2
-rw-r--r--db/migrate/20160615173316_add_enabled_git_access_protocols_to_application_settings.rb2
-rw-r--r--db/migrate/20160615191922_set_missing_stage_on_ci_builds.rb2
-rw-r--r--db/migrate/20160616084004_change_project_of_environment.rb2
-rw-r--r--db/migrate/20160616102642_remove_duplicated_keys.rb2
-rw-r--r--db/migrate/20160616103005_remove_keys_fingerprint_index_if_exists.rb2
-rw-r--r--db/migrate/20160616103948_add_unique_index_to_keys_fingerprint.rb2
-rw-r--r--db/migrate/20160617301627_add_events_to_notification_settings.rb2
-rw-r--r--db/migrate/20160620115026_add_index_on_runners_locked.rb2
-rw-r--r--db/migrate/20160621123729_add_rebase_commit_sha_to_merge_requests.rb2
-rw-r--r--db/migrate/20160628085157_add_artifacts_size_to_ci_builds.rb2
-rw-r--r--db/migrate/20160629025435_add_column_in_progress_merge_commit_sha_to_merge_requests.rb2
-rw-r--r--db/migrate/20160703180340_add_index_on_award_emoji_user_and_name.rb2
-rw-r--r--db/migrate/20160705054938_add_protected_branches_push_access.rb2
-rw-r--r--db/migrate/20160705054952_add_protected_branches_merge_access.rb2
-rw-r--r--db/migrate/20160705055254_move_from_developers_can_merge_to_protected_branches_merge_access.rb2
-rw-r--r--db/migrate/20160705055308_move_from_developers_can_push_to_protected_branches_push_access.rb2
-rw-r--r--db/migrate/20160705055809_remove_developers_can_push_from_protected_branches.rb2
-rw-r--r--db/migrate/20160705055813_remove_developers_can_merge_from_protected_branches.rb2
-rw-r--r--db/migrate/20160705163108_remove_requesters_that_are_owners.rb2
-rw-r--r--db/migrate/20160707104333_add_lock_to_issuables.rb2
-rw-r--r--db/migrate/20160712171823_remove_award_emojis_with_no_user.rb2
-rw-r--r--db/migrate/20160713200638_add_repository_read_only_to_projects.rb2
-rw-r--r--db/migrate/20160713205315_add_domain_blacklist_to_application_settings.rb2
-rw-r--r--db/migrate/20160713222618_add_usage_ping_to_application_settings.rb2
-rw-r--r--db/migrate/20160715132507_add_user_id_to_pipeline.rb2
-rw-r--r--db/migrate/20160715134306_add_index_for_pipeline_user_id.rb2
-rw-r--r--db/migrate/20160715154212_add_request_access_enabled_to_projects.rb2
-rw-r--r--db/migrate/20160715204316_add_request_access_enabled_to_groups.rb2
-rw-r--r--db/migrate/20160715230841_rename_application_settings_restricted_signup_domains.rb2
-rw-r--r--db/migrate/20160716115710_add_when_and_yaml_variables_to_ci_builds.rb2
-rw-r--r--db/migrate/20160716115711_add_queued_at_to_ci_builds.rb2
-rw-r--r--db/migrate/20160718153603_add_has_external_wiki_to_projects.rb2
-rw-r--r--db/migrate/20160721081015_drop_and_readd_has_external_wiki_in_projects.rb2
-rw-r--r--db/migrate/20160722221922_nullify_blank_type_on_notes.rb2
-rw-r--r--db/migrate/20160724205507_add_resolved_to_notes.rb2
-rw-r--r--db/migrate/20160725083350_add_external_url_to_enviroments.rb2
-rw-r--r--db/migrate/20160725104020_merge_request_diff_remove_uniq.rb2
-rw-r--r--db/migrate/20160725104452_merge_request_diff_add_index.rb2
-rw-r--r--db/migrate/20160727163552_create_user_agent_details.rb2
-rw-r--r--db/migrate/20160727191041_create_boards.rb2
-rw-r--r--db/migrate/20160727193336_create_lists.rb2
-rw-r--r--db/migrate/20160728081025_add_pipeline_events_to_web_hooks.rb2
-rw-r--r--db/migrate/20160728103734_add_pipeline_events_to_services.rb2
-rw-r--r--db/migrate/20160729173930_remove_project_id_from_spam_logs.rb2
-rw-r--r--db/migrate/20160801163421_add_expires_at_to_member.rb2
-rw-r--r--db/migrate/20160801163709_add_submitted_as_ham_to_spam_logs.rb2
-rw-r--r--db/migrate/20160802010328_remove_builds_enable_index_on_projects.rb2
-rw-r--r--db/migrate/20160803161903_add_unique_index_to_lists_label_id.rb2
-rw-r--r--db/migrate/20160804142904_add_ci_config_file_to_project.rb2
-rw-r--r--db/migrate/20160804150737_add_timestamps_to_members_again.rb2
-rw-r--r--db/migrate/20160805041956_add_deleted_at_to_namespaces.rb2
-rw-r--r--db/migrate/20160808085531_add_token_to_build.rb2
-rw-r--r--db/migrate/20160808085602_add_index_for_build_token.rb2
-rw-r--r--db/migrate/20160810102349_remove_ci_runner_trigram_indexes.rb2
-rw-r--r--db/migrate/20160810142633_remove_redundant_indexes.rb2
-rw-r--r--db/migrate/20160811172945_add_can_push_to_keys.rb2
-rw-r--r--db/migrate/20160816161312_add_column_name_to_u2f_registrations.rb2
-rw-r--r--db/migrate/20160817133006_add_koding_to_application_settings.rb2
-rw-r--r--db/migrate/20160817154936_add_discussion_ids_to_notes.rb2
-rw-r--r--db/migrate/20160818205718_add_expires_at_to_project_group_links.rb2
-rw-r--r--db/migrate/20160819221631_add_index_to_note_discussion_id.rb2
-rw-r--r--db/migrate/20160819221833_reset_diff_note_discussion_id_because_it_was_calculated_wrongly.rb2
-rw-r--r--db/migrate/20160819232256_add_incoming_email_token_to_users.rb2
-rw-r--r--db/migrate/20160823081327_change_merge_error_to_text.rb2
-rw-r--r--db/migrate/20160823083941_add_column_scopes_to_personal_access_tokens.rb2
-rw-r--r--db/migrate/20160823213309_add_lfs_enabled_to_projects.rb2
-rw-r--r--db/migrate/20160824103857_drop_unused_ci_tables.rb2
-rw-r--r--db/migrate/20160824124900_add_table_issue_metrics.rb2
-rw-r--r--db/migrate/20160825052008_add_table_merge_request_metrics.rb2
-rw-r--r--db/migrate/20160827011312_ensure_lock_version_has_no_default.rb2
-rw-r--r--db/migrate/20160829114652_add_markdown_cache_columns.rb2
-rw-r--r--db/migrate/20160830203109_add_confidential_issues_events_to_web_hooks.rb2
-rw-r--r--db/migrate/20160830211132_add_confidential_issues_events_to_services.rb2
-rw-r--r--db/migrate/20160830232601_change_lock_version_not_null.rb2
-rw-r--r--db/migrate/20160831214002_create_project_features.rb2
-rw-r--r--db/migrate/20160831214543_migrate_project_features.rb2
-rw-r--r--db/migrate/20160831223750_remove_features_enabled_from_projects.rb2
-rw-r--r--db/migrate/20160901141443_set_confidential_issues_events_on_webhooks.rb2
-rw-r--r--db/migrate/20160901213340_add_lfs_enabled_to_namespaces.rb2
-rw-r--r--db/migrate/20160902122721_drop_gitorious_field_from_application_settings.rb2
-rw-r--r--db/migrate/20160907131111_add_environment_type_to_environments.rb2
-rw-r--r--db/migrate/20160913162434_remove_projects_pushes_since_gc.rb2
-rw-r--r--db/migrate/20160913212128_change_artifacts_size_column.rb2
-rw-r--r--db/migrate/20160914131004_only_allow_merge_if_all_discussions_are_resolved.rb2
-rw-r--r--db/migrate/20160915042921_create_merge_requests_closing_issues.rb2
-rw-r--r--db/migrate/20160919144305_add_type_to_labels.rb2
-rw-r--r--db/migrate/20160919145149_add_group_id_to_labels.rb2
-rw-r--r--db/migrate/20160920160832_add_index_to_labels_title.rb2
-rw-r--r--db/migrate/20160926145521_add_organization_to_user.rb2
-rw-r--r--db/migrate/20161006104309_add_state_to_environment.rb2
-rw-r--r--db/migrate/20161007073613_create_user_activities.rb2
-rw-r--r--db/migrate/20161007133303_precalculate_trending_projects.rb2
-rw-r--r--db/migrate/20161010142410_create_project_authorizations.rb2
-rw-r--r--db/migrate/20161012180455_add_repository_access_level_to_project_feature.rb2
-rw-r--r--db/migrate/20161014173530_create_label_priorities.rb2
-rw-r--r--db/migrate/20161017091941_add_authorized_projects_populated_to_users.rb2
-rw-r--r--db/migrate/20161017095000_add_properties_to_deployment.rb2
-rw-r--r--db/migrate/20161017125927_add_unique_index_to_labels.rb2
-rw-r--r--db/migrate/20161018024215_migrate_labels_priority.rb2
-rw-r--r--db/migrate/20161018024550_remove_priority_from_labels.rb2
-rw-r--r--db/migrate/20161018124658_make_project_owners_masters.rb2
-rw-r--r--db/migrate/20161019190736_migrate_sidekiq_queues_from_default.rb2
-rw-r--r--db/migrate/20161019213545_generate_project_feature_for_projects.rb2
-rw-r--r--db/migrate/20161020075734_default_request_access_groups.rb2
-rw-r--r--db/migrate/20161020075830_default_request_access_projects.rb2
-rw-r--r--db/migrate/20161020083353_add_pipeline_id_to_merge_request_metrics.rb2
-rw-r--r--db/migrate/20161020180657_add_minimum_key_length_to_application_settings.rb2
-rw-r--r--db/migrate/20161021114307_add_lock_version_to_build_and_pipelines.rb2
-rw-r--r--db/migrate/20161024042317_migrate_mailroom_queue_from_default.rb2
-rw-r--r--db/migrate/20161025231710_migrate_jira_to_gem.rb2
-rw-r--r--db/migrate/20161031155516_add_housekeeping_to_application_settings.rb2
-rw-r--r--db/migrate/20161031171301_add_project_id_to_subscriptions.rb2
-rw-r--r--db/migrate/20161031174110_migrate_subscriptions_project_id.rb2
-rw-r--r--db/migrate/20161031181638_add_unique_index_to_subscriptions.rb2
-rw-r--r--db/migrate/20161103171205_rename_repository_storage_column.rb2
-rw-r--r--db/migrate/20161103191444_add_sidekiq_throttling_to_application_settings.rb2
-rw-r--r--db/migrate/20161106185620_add_project_import_data_project_index.rb2
-rw-r--r--db/migrate/20161113184239_create_user_chat_names_table.rb2
-rw-r--r--db/migrate/20161114024742_add_coverage_regex_to_builds.rb2
-rw-r--r--db/migrate/20161115173905_add_start_date_to_milestones.rb2
-rw-r--r--db/migrate/20161117114805_remove_undeleted_groups.rb2
-rw-r--r--db/migrate/20161118183841_add_commit_events_to_services.rb2
-rw-r--r--db/migrate/20161124111390_add_parent_id_to_namespace.rb2
-rw-r--r--db/migrate/20161124111395_add_index_to_parent_id.rb2
-rw-r--r--db/migrate/20161124111402_add_routes_table.rb2
-rw-r--r--db/migrate/20161124141322_migrate_process_commit_worker_jobs.rb2
-rw-r--r--db/migrate/20161128095517_add_in_reply_to_discussion_id_to_sent_notifications.rb2
-rw-r--r--db/migrate/20161128142110_remove_unnecessary_indexes.rb2
-rw-r--r--db/migrate/20161128161412_add_html_emails_enabled_to_application_settings.rb2
-rw-r--r--db/migrate/20161130095245_fill_routes_table.rb2
-rw-r--r--db/migrate/20161130101252_fill_projects_routes_table.rb2
-rw-r--r--db/migrate/20161201001911_add_plant_uml_url_to_application_settings.rb2
-rw-r--r--db/migrate/20161201155511_create_project_statistics.rb2
-rw-r--r--db/migrate/20161201160452_migrate_project_statistics.rb2
-rw-r--r--db/migrate/20161202152031_remove_duplicates_from_routes.rb2
-rw-r--r--db/migrate/20161202152035_add_index_to_routes.rb2
-rw-r--r--db/migrate/20161206003819_add_plant_uml_enabled_to_application_settings.rb2
-rw-r--r--db/migrate/20161206153749_remove_uniq_path_index_from_namespace.rb2
-rw-r--r--db/migrate/20161206153751_add_path_index_to_namespace.rb2
-rw-r--r--db/migrate/20161206153753_remove_uniq_name_index_from_namespace.rb2
-rw-r--r--db/migrate/20161206153754_add_name_index_to_namespace.rb2
-rw-r--r--db/migrate/20161207231620_fixup_environment_name_uniqueness.rb2
-rw-r--r--db/migrate/20161207231621_create_environment_name_unique_index.rb2
-rw-r--r--db/migrate/20161207231626_add_environment_slug.rb2
-rw-r--r--db/migrate/20161209153400_add_unique_index_for_environment_slug.rb2
-rw-r--r--db/migrate/20161209165216_create_doorkeeper_openid_connect_tables.rb2
-rw-r--r--db/migrate/20161212142807_add_lower_path_index_to_routes.rb2
-rw-r--r--db/migrate/20161213172958_change_slack_service_to_slack_notification_service.rb2
-rw-r--r--db/migrate/20161220141214_remove_dot_git_from_group_names.rb2
-rw-r--r--db/migrate/20161221152132_add_last_used_at_to_key.rb2
-rw-r--r--db/migrate/20161223034433_add_estimate_to_issuables_ce.rb2
-rw-r--r--db/migrate/20161223034646_create_timelogs_ce.rb2
-rw-r--r--db/migrate/20161226122833_remove_dot_git_from_usernames.rb2
-rw-r--r--db/migrate/20161227192806_rename_slack_and_mattermost_notification_services.rb2
-rw-r--r--db/migrate/20161228124936_change_expires_at_to_date_in_personal_access_tokens.rb2
-rw-r--r--db/migrate/20161228135550_add_impersonation_to_personal_access_tokens.rb2
-rw-r--r--db/migrate/20170120131253_create_chat_teams.rb2
-rw-r--r--db/migrate/20170121123724_add_index_to_ci_builds_for_status_runner_id_and_type.rb2
-rw-r--r--db/migrate/20170121130655_add_index_to_ci_runners_for_is_shared.rb2
-rw-r--r--db/migrate/20170124174637_add_foreign_keys_to_timelogs.rb2
-rw-r--r--db/migrate/20170124193147_add_two_factor_columns_to_namespaces.rb2
-rw-r--r--db/migrate/20170124193205_add_two_factor_columns_to_users.rb2
-rw-r--r--db/migrate/20170126174819_add_terminal_max_session_time_to_application_settings.rb2
-rw-r--r--db/migrate/20170127032550_remove_backlog_lists_from_boards.rb2
-rw-r--r--db/migrate/20170130204620_add_index_to_project_authorizations.rb2
-rw-r--r--db/migrate/20170130221926_create_uploads.rb2
-rw-r--r--db/migrate/20170131221752_add_relative_position_to_issues.rb2
-rw-r--r--db/migrate/20170204172458_add_name_to_route.rb2
-rw-r--r--db/migrate/20170204181513_add_index_to_labels_for_type_and_project.rb2
-rw-r--r--db/migrate/20170206071414_add_recaptcha_verified_to_spam_logs.rb2
-rw-r--r--db/migrate/20170206115204_add_column_ghost_to_users.rb2
-rw-r--r--db/migrate/20170210062829_add_index_to_labels_for_title_and_project.rb2
-rw-r--r--db/migrate/20170210075922_add_index_to_ci_trigger_requests_for_commit_id.rb2
-rw-r--r--db/migrate/20170210103609_add_index_to_user_agent_detail.rb2
-rw-r--r--db/migrate/20170210131347_add_unique_ips_limit_to_application_settings.rb2
-rw-r--r--db/migrate/20170214084746_add_default_artifacts_expiration_to_application_settings.rb2
-rw-r--r--db/migrate/20170216135621_add_index_for_latest_successful_pipeline.rb2
-rw-r--r--db/migrate/20170216141440_drop_index_for_builds_project_status.rb2
-rw-r--r--db/migrate/20170217132157_rename_merge_when_build_succeeds.rb2
-rw-r--r--db/migrate/20170217151947_rename_only_allow_merge_if_build_succeeds.rb2
-rw-r--r--db/migrate/20170217151948_add_owner_id_to_triggers.rb2
-rw-r--r--db/migrate/20170217151949_add_description_to_triggers.rb2
-rw-r--r--db/migrate/20170222111732_create_gpg_keys.rb8
-rw-r--r--db/migrate/20170222143317_drop_ci_projects.rb2
-rw-r--r--db/migrate/20170222143500_remove_old_project_id_columns.rb2
-rw-r--r--db/migrate/20170222143603_rename_gl_project_id_to_project_id.rb2
-rw-r--r--db/migrate/20170301101006_add_ci_runner_namespaces.rb2
-rw-r--r--db/migrate/20170301125302_add_printing_merge_request_link_enabled_to_project.rb2
-rw-r--r--db/migrate/20170301195939_rename_ci_commits_to_ci_pipelines.rb2
-rw-r--r--db/migrate/20170301205639_remove_unused_ci_tables_and_columns.rb2
-rw-r--r--db/migrate/20170305180853_add_auto_cancel_pending_pipelines_to_project.rb2
-rw-r--r--db/migrate/20170305203726_add_owner_id_foreign_key.rb2
-rw-r--r--db/migrate/20170307125949_add_last_activity_on_to_users.rb2
-rw-r--r--db/migrate/20170309173138_create_protected_tags.rb2
-rw-r--r--db/migrate/20170312114329_add_auto_canceled_by_id_to_pipeline.rb2
-rw-r--r--db/migrate/20170312114529_add_auto_canceled_by_id_foreign_key_to_pipeline.rb2
-rw-r--r--db/migrate/20170313213916_add_index_to_user_ghost.rb2
-rw-r--r--db/migrate/20170314082049_create_system_note_metadata.rb2
-rw-r--r--db/migrate/20170315174634_revert_add_notified_of_own_activity_to_users.rb2
-rw-r--r--db/migrate/20170315194013_add_closed_at_to_issues.rb2
-rw-r--r--db/migrate/20170316061730_readd_notified_of_own_activity_to_users.rb2
-rw-r--r--db/migrate/20170316163845_move_uploads_to_system_dir.rb2
-rw-r--r--db/migrate/20170317203554_index_routes_path_for_like.rb2
-rw-r--r--db/migrate/20170320173259_migrate_assignees.rb2
-rw-r--r--db/migrate/20170322013926_create_container_repository.rb2
-rw-r--r--db/migrate/20170327091750_add_created_at_index_to_deployments.rb2
-rw-r--r--db/migrate/20170328010804_add_uuid_to_application_settings.rb2
-rw-r--r--db/migrate/20170329095325_add_ref_to_triggers.rb2
-rw-r--r--db/migrate/20170329095907_create_ci_trigger_schedules.rb2
-rw-r--r--db/migrate/20170329124448_add_polling_interval_multiplier_to_application_settings.rb2
-rw-r--r--db/migrate/20170330141723_disable_invalid_service_templates2.rb2
-rw-r--r--db/migrate/20170402231018_remove_index_for_users_current_sign_in_at.rb2
-rw-r--r--db/migrate/20170404163427_add_trigger_id_foreign_key.rb2
-rw-r--r--db/migrate/20170405080720_add_import_jid_to_projects.rb2
-rw-r--r--db/migrate/20170406114958_add_auto_canceled_by_id_to_ci_builds.rb2
-rw-r--r--db/migrate/20170406115029_add_auto_canceled_by_id_foreign_key_to_ci_builds.rb2
-rw-r--r--db/migrate/20170407114956_add_ref_to_ci_trigger_schedule.rb2
-rw-r--r--db/migrate/20170407122426_add_active_to_ci_trigger_schedule.rb2
-rw-r--r--db/migrate/20170407135259_add_foreigh_key_trigger_requests_trigger.rb2
-rw-r--r--db/migrate/20170407140450_add_index_to_next_run_at_and_active.rb2
-rw-r--r--db/migrate/20170410133135_add_version_field_to_markdown_cache.rb2
-rw-r--r--db/migrate/20170413035209_add_preferred_language_to_users.rb2
-rw-r--r--db/migrate/20170418103908_delete_orphan_notification_settings.rb2
-rw-r--r--db/migrate/20170419001229_add_index_to_system_note_metadata.rb2
-rw-r--r--db/migrate/20170421102337_remove_nil_type_services.rb2
-rw-r--r--db/migrate/20170423064036_add_index_on_ci_builds_updated_at.rb2
-rw-r--r--db/migrate/20170424095707_add_index_on_ci_builds_user_id.rb2
-rw-r--r--db/migrate/20170424142900_add_index_to_web_hooks_type.rb2
-rw-r--r--db/migrate/20170425112128_create_pipeline_schedules_table.rb2
-rw-r--r--db/migrate/20170425112628_remove_foreigh_key_ci_trigger_schedules.rb2
-rw-r--r--db/migrate/20170425114731_add_pipeline_schedule_id_to_pipelines.rb2
-rw-r--r--db/migrate/20170426175636_fill_missing_uuid_on_application_settings.rb2
-rw-r--r--db/migrate/20170426181740_add_index_on_ci_runners_contacted_at.rb2
-rw-r--r--db/migrate/20170427103502_create_web_hook_logs.rb2
-rw-r--r--db/migrate/20170427215854_create_redirect_routes.rb2
-rw-r--r--db/migrate/20170428064307_add_column_delete_error_to_projects.rb2
-rw-r--r--db/migrate/20170502065653_make_auto_cancel_pending_pipelines_on_by_default.rb2
-rw-r--r--db/migrate/20170502135553_create_index_ci_pipelines_auto_canceled_by_id.rb2
-rw-r--r--db/migrate/20170502140503_create_index_ci_builds_auto_canceled_by_id.rb2
-rw-r--r--db/migrate/20170503004125_add_last_repository_updated_at_to_projects.rb2
-rw-r--r--db/migrate/20170503004425_add_index_to_last_repository_updated_at_on_projects.rb2
-rw-r--r--db/migrate/20170503004426_add_retried_to_ci_build.rb2
-rw-r--r--db/migrate/20170503021915_add_last_edited_at_and_last_edited_by_id_to_issues.rb2
-rw-r--r--db/migrate/20170503022548_add_last_edited_at_and_last_edited_by_id_to_merge_requests.rb2
-rw-r--r--db/migrate/20170503023315_add_repository_update_events_to_web_hooks.rb2
-rw-r--r--db/migrate/20170503114228_add_description_to_snippets.rb2
-rw-r--r--db/migrate/20170503140201_reschedule_project_authorizations.rb2
-rw-r--r--db/migrate/20170503140202_turn_nested_groups_into_regular_groups_for_mysql.rb2
-rw-r--r--db/migrate/20170503184421_add_index_to_redirect_routes.rb2
-rw-r--r--db/migrate/20170503185032_index_redirect_routes_path_for_like.rb2
-rw-r--r--db/migrate/20170504102911_add_clientside_sentry_to_application_settings.rb2
-rw-r--r--db/migrate/20170504182103_add_index_project_group_links_group_id.rb2
-rw-r--r--db/migrate/20170506085040_add_index_to_pipeline_pipeline_schedule_id.rb2
-rw-r--r--db/migrate/20170506091344_add_foreign_key_to_pipeline_schedules.rb2
-rw-r--r--db/migrate/20170506185517_add_foreign_key_pipeline_schedules_and_pipelines.rb4
-rw-r--r--db/migrate/20170507205316_add_head_pipeline_id_to_merge_requests.rb2
-rw-r--r--db/migrate/20170508153950_add_not_null_contraints_to_ci_variables.rb2
-rw-r--r--db/migrate/20170508190732_add_foreign_key_to_ci_variables.rb2
-rw-r--r--db/migrate/20170511082759_rename_web_hooks_build_events_to_job_events.rb2
-rw-r--r--db/migrate/20170511083824_rename_services_build_events_to_job_events.rb2
-rw-r--r--db/migrate/20170516153305_migrate_assignee_to_separate_table.rb2
-rw-r--r--db/migrate/20170516183131_add_indices_to_issue_assignees.rb2
-rw-r--r--db/migrate/20170519102115_add_prometheus_settings_to_metrics_settings.rb2
-rw-r--r--db/migrate/20170521184006_add_change_position_to_notes.rb2
-rw-r--r--db/migrate/20170523091700_add_rss_token_to_users.rb2
-rw-r--r--db/migrate/20170523121229_create_conversational_development_index_metrics.rb2
-rw-r--r--db/migrate/20170524125940_add_source_to_ci_pipeline.rb2
-rw-r--r--db/migrate/20170524161101_add_protected_to_ci_variables.rb2
-rw-r--r--db/migrate/20170525130346_create_group_variables_table.rb2
-rw-r--r--db/migrate/20170525130758_add_foreign_key_to_group_variables.rb2
-rw-r--r--db/migrate/20170525132202_create_pipeline_stages.rb2
-rw-r--r--db/migrate/20170525174156_create_feature_tables.rb2
-rw-r--r--db/migrate/20170526185602_add_stage_id_to_ci_builds.rb2
-rw-r--r--db/migrate/20170530130129_project_foreign_keys_with_cascading_deletes.rb2
-rw-r--r--db/migrate/20170531180233_add_authorized_keys_enabled_to_application_settings.rb2
-rw-r--r--db/migrate/20170531202042_rename_users_ldap_email_to_external_email.rb2
-rw-r--r--db/migrate/20170601163708_add_artifacts_store_to_ci_build.rb2
-rw-r--r--db/migrate/20170602154736_add_help_page_hide_commercial_content_to_application_settings.rb2
-rw-r--r--db/migrate/20170602154813_add_help_page_support_url_to_application_settings.rb2
-rw-r--r--db/migrate/20170603200744_add_email_provider_to_users.rb2
-rw-r--r--db/migrate/20170606154216_add_notification_setting_columns.rb2
-rw-r--r--db/migrate/20170608152747_prepare_events_table_for_push_events_migration.rb2
-rw-r--r--db/migrate/20170608152748_create_push_event_payloads_tables.rb2
-rw-r--r--db/migrate/20170608171156_create_merge_request_diff_files.rb2
-rw-r--r--db/migrate/20170613154149_create_gpg_signatures.rb8
-rw-r--r--db/migrate/20170616133147_create_merge_request_diff_commits.rb2
-rw-r--r--db/migrate/20170619144837_add_index_for_head_pipeline_merge_request.rb2
-rw-r--r--db/migrate/20170620064728_create_ci_pipeline_schedule_variables.rb2
-rw-r--r--db/migrate/20170620065449_add_foreign_key_to_ci_pipeline_schedule_variables.rb2
-rw-r--r--db/migrate/20170622130029_correct_protected_branches_foreign_keys.rb2
-rw-r--r--db/migrate/20170622132212_add_foreign_key_for_merge_request_diffs.rb2
-rw-r--r--db/migrate/20170622135451_rename_duplicated_variable_key.rb2
-rw-r--r--db/migrate/20170622135628_add_environment_scope_to_ci_variables.rb2
-rw-r--r--db/migrate/20170622135728_add_unique_constraint_to_ci_variables.rb2
-rw-r--r--db/migrate/20170622162730_add_ref_fetched_to_merge_request.rb2
-rw-r--r--db/migrate/20170623080805_remove_ci_variables_project_id_index.rb2
-rw-r--r--db/migrate/20170629171610_rename_application_settings_signin_enabled_to_password_authentication_enabled.rb2
-rw-r--r--db/migrate/20170703102400_add_stage_id_foreign_key_to_builds.rb2
-rw-r--r--db/migrate/20170706151212_add_performance_bar_allowed_group_id_to_application_settings.rb2
-rw-r--r--db/migrate/20170707183807_add_group_id_to_milestones.rb2
-rw-r--r--db/migrate/20170707184243_add_group_milestone_id_indexes.rb2
-rw-r--r--db/migrate/20170707184244_remove_wrong_versions_from_schema_versions.rb2
-rw-r--r--db/migrate/20170710083355_clean_stage_id_reference_migration.rb2
-rw-r--r--db/migrate/20170711145320_add_status_to_ci_stages.rb2
-rw-r--r--db/migrate/20170713104829_add_foreign_key_to_merge_requests.rb2
-rw-r--r--db/migrate/20170717074009_move_system_upload_folder.rb2
-rw-r--r--db/migrate/20170717200542_add_trusted_column_to_oauth_applications.rb2
-rw-r--r--db/migrate/20170720111708_add_lock_version_to_ci_stages.rb2
-rw-r--r--db/migrate/20170720122741_create_user_custom_attributes.rb2
-rw-r--r--db/migrate/20170720130522_create_ci_pipeline_variables.rb2
-rw-r--r--db/migrate/20170720130749_add_foreign_key_to_ci_pipeline_variables.rb2
-rw-r--r--db/migrate/20170724214302_add_lower_path_index_to_redirect_routes.rb2
-rw-r--r--db/migrate/20170725145659_add_binary_to_merge_request_diff_files.rb2
-rw-r--r--db/migrate/20170727123534_add_index_on_events_project_id_id.rb2
-rw-r--r--db/migrate/20170731175128_add_percentages_to_conv_dev.rb2
-rw-r--r--db/migrate/20170731183033_add_merge_jid_to_merge_requests.rb2
-rw-r--r--db/migrate/20170802013652_add_storage_fields_to_project.rb2
-rw-r--r--db/migrate/20170803130232_reorganise_issues_indexes_for_faster_sorting.rb2
-rw-r--r--db/migrate/20170807071105_add_hashed_storage_to_settings.rb2
-rw-r--r--db/migrate/20170809133343_add_broadcast_messages_index.rb2
-rw-r--r--db/migrate/20170809134534_add_broadcast_message_not_null_constraints.rb2
-rw-r--r--db/migrate/20170809142252_cleanup_appearances_schema.rb2
-rw-r--r--db/migrate/20170809161910_add_project_export_enabled_to_application_settings.rb2
-rw-r--r--db/migrate/20170815221154_add_discussion_locked_to_issuable.rb2
-rw-r--r--db/migrate/20170816133938_add_access_level_to_ci_runners.rb2
-rw-r--r--db/migrate/20170816133940_add_protected_to_ci_builds.rb2
-rw-r--r--db/migrate/20170816143940_add_protected_to_ci_pipelines.rb2
-rw-r--r--db/migrate/20170816153940_add_index_on_ci_builds_protected.rb2
-rw-r--r--db/migrate/20170816234252_add_theme_id_to_users.rb2
-rw-r--r--db/migrate/20170817123339_add_verification_status_to_gpg_signatures.rb2
-rw-r--r--db/migrate/20170820100558_correct_protected_tags_foreign_keys.rb2
-rw-r--r--db/migrate/20170820120108_create_user_synced_attributes_metadata.rb2
-rw-r--r--db/migrate/20170824101926_add_auto_devops_enabled_to_application_settings.rb2
-rw-r--r--db/migrate/20170824162758_allow_appearances_description_html_null.rb2
-rw-r--r--db/migrate/20170825015534_add_file_store_to_lfs_objects.rb2
-rw-r--r--db/migrate/20170825104051_migrate_issues_to_ghost_user.rb2
-rw-r--r--db/migrate/20170825154015_resolve_outdated_diff_discussions.rb2
-rw-r--r--db/migrate/20170827123848_add_index_on_merge_request_diff_commit_sha.rb4
-rw-r--r--db/migrate/20170828093725_create_project_auto_dev_ops.rb2
-rw-r--r--db/migrate/20170828135939_migrate_user_external_mail_data.rb2
-rw-r--r--db/migrate/20170830125940_add_failure_reason_to_ci_builds.rb2
-rw-r--r--db/migrate/20170830130119_steal_remaining_event_migration_jobs.rb2
-rw-r--r--db/migrate/20170830131015_swap_event_migration_tables.rb2
-rw-r--r--db/migrate/20170831092813_add_config_source_to_pipelines.rb2
-rw-r--r--db/migrate/20170901071411_add_foreign_key_to_issue_author.rb2
-rw-r--r--db/migrate/20170904092148_add_email_confirmation.rb2
-rw-r--r--db/migrate/20170905112933_add_resolved_by_push_to_notes.rb2
-rw-r--r--db/migrate/20170906133745_add_runners_token_to_groups.rb2
-rw-r--r--db/migrate/20170909090114_add_email_confirmation_index.rb2
-rw-r--r--db/migrate/20170909150936_add_spent_at_to_timelogs.rb2
-rw-r--r--db/migrate/20170912113435_clean_stages_statuses_migration.rb2
-rw-r--r--db/migrate/20170913131410_environments_project_id_not_null.rb2
-rw-r--r--db/migrate/20170914135630_add_index_for_recent_push_events.rb2
-rw-r--r--db/migrate/20170918072948_create_job_artifacts.rb2
-rw-r--r--db/migrate/20170918072949_add_file_store_job_artifacts.rb2
-rw-r--r--db/migrate/20170918111708_create_project_custom_attributes.rb2
-rw-r--r--db/migrate/20170918140927_create_group_custom_attributes.rb2
-rw-r--r--db/migrate/20170918222253_reorganize_deployments_indexes.rb2
-rw-r--r--db/migrate/20170918223303_add_deployments_index_for_last_deployment.rb2
-rw-r--r--db/migrate/20170919211300_remove_temporary_ci_builds_index.rb2
-rw-r--r--db/migrate/20170921115009_add_project_repository_storage_index.rb2
-rw-r--r--db/migrate/20170924094327_create_gcp_clusters.rb2
-rw-r--r--db/migrate/20170925184228_add_favicon_to_appearances.rb2
-rw-r--r--db/migrate/20170927095921_add_ci_builds_index_for_jobscontroller.rb2
-rw-r--r--db/migrate/20170927122209_add_partial_index_for_labels_template.rb2
-rw-r--r--db/migrate/20170927161718_create_gpg_key_subkeys.rb8
-rw-r--r--db/migrate/20170928100231_add_composite_index_on_merge_requests_merge_commit_sha.rb2
-rw-r--r--db/migrate/20170928124105_create_fork_networks.rb2
-rw-r--r--db/migrate/20170928133643_create_fork_network_members.rb2
-rw-r--r--db/migrate/20170929080234_add_failure_reason_to_pipelines.rb2
-rw-r--r--db/migrate/20170929131201_populate_fork_networks.rb2
-rw-r--r--db/migrate/20171004121444_make_sure_fast_forward_option_exists.rb2
-rw-r--r--db/migrate/20171006090001_create_ci_build_trace_sections.rb2
-rw-r--r--db/migrate/20171006090010_add_build_foreign_key_to_ci_build_trace_sections.rb2
-rw-r--r--db/migrate/20171006090100_create_ci_build_trace_section_names.rb2
-rw-r--r--db/migrate/20171006091000_add_name_foreign_key_to_ci_build_trace_sections.rb2
-rw-r--r--db/migrate/20171006220837_add_global_rate_limits_to_application_settings.rb2
-rw-r--r--db/migrate/20171012101043_add_circuit_breaker_properties_to_application_settings.rb2
-rw-r--r--db/migrate/20171012125712_migrate_user_authentication_token_to_personal_access_token.rb2
-rw-r--r--db/migrate/20171013094327_create_new_clusters_architectures.rb2
-rw-r--r--db/migrate/20171017145932_add_new_circuitbreaker_settings_to_application_settings.rb2
-rw-r--r--db/migrate/20171019141859_fix_dev_timezone_schema.rb2
-rw-r--r--db/migrate/20171025110159_add_latest_merge_request_diff_id_to_merge_requests.rb2
-rw-r--r--db/migrate/20171031100710_create_clusters_kubernetes_helm_apps.rb2
-rw-r--r--db/migrate/20171101130535_add_gitaly_timeout_properties_to_application_settings.rb2
-rw-r--r--db/migrate/20171103000000_set_uploads_path_size_for_mysql.rb2
-rw-r--r--db/migrate/20171106101200_create_clusters_kubernetes_ingress_apps.rb2
-rw-r--r--db/migrate/20171106132212_issues_confidential_not_null.rb2
-rw-r--r--db/migrate/20171106133143_rename_application_settings_password_authentication_enabled_to_password_authentication_enabled_for_web.rb2
-rw-r--r--db/migrate/20171106133911_add_password_authentication_enabled_for_git_to_application_settings.rb2
-rw-r--r--db/migrate/20171106135924_issues_milestone_id_foreign_key.rb2
-rw-r--r--db/migrate/20171106150657_issues_updated_by_id_foreign_key.rb2
-rw-r--r--db/migrate/20171106151218_issues_moved_to_id_foreign_key.rb2
-rw-r--r--db/migrate/20171106155656_turn_issues_due_date_index_to_partial_index.rb2
-rw-r--r--db/migrate/20171106171453_add_timezone_to_issues_closed_at.rb2
-rw-r--r--db/migrate/20171114150259_merge_requests_author_id_foreign_key.rb2
-rw-r--r--db/migrate/20171114160005_merge_requests_assignee_id_foreign_key.rb2
-rw-r--r--db/migrate/20171114160904_merge_requests_updated_by_id_foreign_key.rb2
-rw-r--r--db/migrate/20171114161720_merge_requests_merge_user_id_foreign_key.rb2
-rw-r--r--db/migrate/20171114161914_merge_requests_source_project_id_foreign_key.rb2
-rw-r--r--db/migrate/20171114162227_merge_requests_milestone_id_foreign_key.rb2
-rw-r--r--db/migrate/20171115164540_populate_merge_requests_latest_merge_request_diff_id_take_two.rb2
-rw-r--r--db/migrate/20171116135628_add_environment_scope_to_clusters.rb2
-rw-r--r--db/migrate/20171121135738_clean_up_from_merge_request_diffs_and_commits.rb2
-rw-r--r--db/migrate/20171121144800_ci_pipelines_index_on_project_id_ref_status_id.rb2
-rw-r--r--db/migrate/20171122131600_add_new_project_guidelines_to_appearances.rb2
-rw-r--r--db/migrate/20171123094802_add_circuitbreaker_check_interval_to_application_settings.rb2
-rw-r--r--db/migrate/20171124125042_add_default_values_to_merge_request_states.rb2
-rw-r--r--db/migrate/20171124125748_populate_missing_merge_request_statuses.rb2
-rw-r--r--db/migrate/20171124132536_make_merge_request_statuses_not_null.rb2
-rw-r--r--db/migrate/20171127151038_add_events_related_columns_to_merge_request_metrics.rb2
-rw-r--r--db/migrate/20171204204233_add_permanent_to_redirect_route.rb2
-rw-r--r--db/migrate/20171206221519_add_permanent_index_to_redirect_route.rb2
-rw-r--r--db/migrate/20171207185153_add_merge_request_state_index.rb2
-rw-r--r--db/migrate/20171211145425_add_can_push_to_deploy_keys_projects.rb2
-rw-r--r--db/migrate/20171212203433_create_clusters_applications_prometheus.rb2
-rw-r--r--db/migrate/20171214144320_add_store_column_to_uploads.rb2
-rw-r--r--db/migrate/20171215113714_populate_can_push_from_deploy_keys_projects.rb2
-rw-r--r--db/migrate/20171216111734_clean_up_for_members.rb2
-rw-r--r--db/migrate/20171216112339_add_foreign_key_for_members.rb2
-rw-r--r--db/migrate/20171220191323_add_index_on_namespaces_lower_name.rb2
-rw-r--r--db/migrate/20171222115326_add_confidential_note_events_to_web_hooks.rb2
-rw-r--r--db/migrate/20171222183504_add_jobs_cache_index_to_project.rb2
-rw-r--r--db/migrate/20171229225929_change_user_project_limit_not_null_and_remove_default.rb2
-rw-r--r--db/migrate/20171230123729_add_rebase_commit_sha_to_merge_requests_ce.rb2
-rw-r--r--db/migrate/20180101160629_create_prometheus_metrics.rb2
-rw-r--r--db/migrate/20180101160630_change_project_id_for_prometheus_metrics.rb2
-rw-r--r--db/migrate/20180102220145_add_pages_https_only_to_projects.rb2
-rw-r--r--db/migrate/20180103123548_add_confidential_note_events_to_services.rb2
-rw-r--r--db/migrate/20180105212544_add_commits_count_to_merge_request_diff.rb2
-rw-r--r--db/migrate/20180109183319_change_default_value_for_pages_https_only.rb2
-rw-r--r--db/migrate/20180113220114_rework_redirect_routes_indexes.rb2
-rw-r--r--db/migrate/20180115201419_add_index_updated_at_to_issues.rb2
-rw-r--r--db/migrate/20180116193854_create_lfs_file_locks.rb2
-rw-r--r--db/migrate/20180119135717_add_uploader_index_to_uploads.rb2
-rw-r--r--db/migrate/20180119160751_optimize_ci_job_artifacts.rb2
-rw-r--r--db/migrate/20180122162010_add_auto_devops_domain_to_application_settings.rb2
-rw-r--r--db/migrate/20180125214301_create_user_callouts.rb2
-rw-r--r--db/migrate/20180129193323_add_uploads_builder_context.rb2
-rw-r--r--db/migrate/20180201102129_add_unique_constraint_to_trending_projects_project_id.rb2
-rw-r--r--db/migrate/20180201110056_add_foreign_keys_to_todos.rb2
-rw-r--r--db/migrate/20180201145907_migrate_remaining_issues_closed_at.rb2
-rw-r--r--db/migrate/20180206200543_reset_events_primary_key_sequence.rb2
-rw-r--r--db/migrate/20180208183958_schedule_populate_untracked_uploads_if_needed.rb2
-rw-r--r--db/migrate/20180209165249_add_closed_by_to_issues.rb2
-rw-r--r--db/migrate/20180212030105_add_external_ip_to_clusters_applications_ingress.rb2
-rw-r--r--db/migrate/20180213131630_add_partial_index_to_projects_for_index_only_scans.rb2
-rw-r--r--db/migrate/20180214093516_create_badges.rb2
-rw-r--r--db/migrate/20180214155405_create_clusters_applications_runners.rb2
-rw-r--r--db/migrate/20180215181245_users_name_lower_index.rb2
-rw-r--r--db/migrate/20180216120000_add_pages_domain_verification.rb2
-rw-r--r--db/migrate/20180216120010_add_pages_domain_verified_at_index.rb2
-rw-r--r--db/migrate/20180216120020_allow_domain_verification_to_be_disabled.rb2
-rw-r--r--db/migrate/20180216120030_add_pages_domain_enabled_until.rb2
-rw-r--r--db/migrate/20180216120040_add_pages_domain_enabled_until_index.rb2
-rw-r--r--db/migrate/20180216120050_pages_domains_verification_grace_period.rb2
-rw-r--r--db/migrate/20180219153455_add_maximum_timeout_to_ci_runners.rb2
-rw-r--r--db/migrate/20180221151752_add_allow_maintainer_to_push_to_merge_requests.rb2
-rw-r--r--db/migrate/20180222043024_add_ip_address_to_runner.rb2
-rw-r--r--db/migrate/20180223120443_create_user_interacted_projects_table.rb2
-rw-r--r--db/migrate/20180223144945_add_allow_local_requests_from_hooks_and_services_to_application_settings.rb2
-rw-r--r--db/migrate/20180226050030_add_checksum_to_ci_job_artifacts.rb2
-rw-r--r--db/migrate/20180227182112_add_group_id_to_boards_ce.rb2
-rw-r--r--db/migrate/20180228172924_add_include_private_contributions_to_users.rb2
-rw-r--r--db/migrate/20180301010859_create_ci_builds_metadata_table.rb2
-rw-r--r--db/migrate/20180302152117_ensure_foreign_keys_on_clusters_applications.rb2
-rw-r--r--db/migrate/20180305095250_create_internal_ids_table.rb2
-rw-r--r--db/migrate/20180305144721_add_privileged_to_runner.rb2
-rw-r--r--db/migrate/20180306134842_add_missing_indexes_acts_as_taggable_on_engine.rb2
-rw-r--r--db/migrate/20180308052825_add_section_name_id_index_on_ci_build_trace_sections.rb2
-rw-r--r--db/migrate/20180308125206_add_user_internal_regex_to_application_setting.rb2
-rw-r--r--db/migrate/20180309121820_reschedule_commits_count_for_merge_request_diff.rb2
-rw-r--r--db/migrate/20180309160427_add_partial_indexes_on_todos.rb2
-rw-r--r--db/migrate/20180319190020_create_deploy_tokens.rb2
-rw-r--r--db/migrate/20180320182229_add_indexes_for_user_activity_queries.rb2
-rw-r--r--db/migrate/20180323150945_add_push_to_merge_request_to_notification_settings.rb2
-rw-r--r--db/migrate/20180326202229_create_ci_build_trace_chunks.rb2
-rw-r--r--db/migrate/20180327101207_remove_index_from_events_table.rb2
-rw-r--r--db/migrate/20180330121048_add_issue_due_to_notification_settings.rb2
-rw-r--r--db/migrate/20180403035759_create_project_ci_cd_settings.rb2
-rw-r--r--db/migrate/20180405142733_create_project_deploy_tokens.rb2
-rw-r--r--db/migrate/20180406204716_add_limits_ci_build_trace_chunks_raw_data_for_mysql.rb2
-rw-r--r--db/migrate/20180408143354_rename_users_rss_token_to_feed_token.rb2
-rw-r--r--db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb6
-rw-r--r--db/migrate/20180416155103_add_further_scope_columns_to_internal_id_table.rb2
-rw-r--r--db/migrate/20180417090132_add_index_constraints_to_internal_id_table.rb2
-rw-r--r--db/migrate/20180417101040_add_tmp_stage_priority_index_to_ci_builds.rb2
-rw-r--r--db/migrate/20180417101940_add_index_to_ci_stage.rb2
-rw-r--r--db/migrate/20180418053107_add_index_to_ci_job_artifacts_file_store.rb2
-rw-r--r--db/migrate/20180420010016_add_pipeline_build_foreign_key.rb2
-rw-r--r--db/migrate/20180420010616_cleanup_build_stage_migration.rb2
-rw-r--r--db/migrate/20180423204600_add_pages_access_level_to_project_feature.rb16
-rw-r--r--db/migrate/20180424090541_add_enforce_terms_to_application_settings.rb2
-rw-r--r--db/migrate/20180424134533_create_application_setting_terms.rb2
-rw-r--r--db/migrate/20180424160449_add_pipeline_iid_to_ci_pipelines.rb2
-rw-r--r--db/migrate/20180425075446_create_term_agreements.rb2
-rw-r--r--db/migrate/20180425131009_assure_commits_count_for_merge_request_diff.rb2
-rw-r--r--db/migrate/20180425205249_add_index_constraints_to_pipeline_iid.rb2
-rw-r--r--db/migrate/20180426102016_add_accepted_term_to_users.rb2
-rw-r--r--db/migrate/20180430101916_add_runner_type_to_ci_runners.rb2
-rw-r--r--db/migrate/20180502122856_create_project_mirror_data.rb2
-rw-r--r--db/migrate/20180503131624_create_remote_mirrors.rb2
-rw-r--r--db/migrate/20180503141722_add_remote_mirror_available_overridden_to_projects.rb2
-rw-r--r--db/migrate/20180503150427_add_index_to_namespaces_runners_token.rb2
-rw-r--r--db/migrate/20180503175053_ensure_missing_columns_to_project_mirror_data.rb2
-rw-r--r--db/migrate/20180503175054_add_indexes_to_project_mirror_data.rb2
-rw-r--r--db/migrate/20180503193542_add_indexes_to_remote_mirror.rb2
-rw-r--r--db/migrate/20180503193953_add_mirror_available_to_application_settings.rb2
-rw-r--r--db/migrate/20180503200320_enable_prometheus_metrics_by_default.rb2
-rw-r--r--db/migrate/20180504195842_project_name_lower_index.rb2
-rw-r--r--db/migrate/20180508055821_make_remote_mirrors_disabled_by_default.rb2
-rw-r--r--db/migrate/20180508100222_add_not_null_constraint_to_project_mirror_data_foreign_key.rb2
-rw-r--r--db/migrate/20180508102840_add_unique_constraint_to_project_mirror_data_project_id_index.rb2
-rw-r--r--db/migrate/20180508135515_set_runner_type_not_null.rb2
-rw-r--r--db/migrate/20180511090724_add_index_on_ci_runners_runner_type.rb2
-rw-r--r--db/migrate/20180511131058_create_clusters_applications_jupyter.rb2
-rw-r--r--db/migrate/20180515005612_add_squash_to_merge_requests.rb2
-rw-r--r--db/migrate/20180515121227_create_notes_diff_files.rb2
-rw-r--r--db/migrate/20180517082340_add_not_null_constraints_to_project_authorizations.rb2
-rw-r--r--db/migrate/20180523042841_rename_merge_requests_allow_maintainer_to_push.rb2
-rw-r--r--db/migrate/20180524132016_merge_requests_target_id_iid_state_partial_index.rb2
-rw-r--r--db/migrate/20180529093006_ensure_remote_mirror_columns.rb2
-rw-r--r--db/migrate/20180530135500_add_index_to_stages_position.rb2
-rw-r--r--db/migrate/20180531185349_add_repository_languages.rb2
-rw-r--r--db/migrate/20180531220618_change_default_value_for_dsa_key_restriction.rb2
-rw-r--r--db/migrate/20180601213245_add_deploy_strategy_to_project_auto_devops.rb2
-rw-r--r--db/migrate/20180607071808_add_push_events_branch_filter_to_web_hooks.rb2
-rw-r--r--db/migrate/20180608091413_add_group_to_todos.rb2
-rw-r--r--db/migrate/20180608110058_rename_merge_requests_allow_collaboration.rb2
-rw-r--r--db/migrate/20180612103626_add_columns_for_helm_tiller_certificates.rb2
-rw-r--r--db/migrate/20180613081317_create_ci_builds_runner_session.rb2
-rw-r--r--db/migrate/20180625113853_create_import_export_uploads.rb2
-rw-r--r--db/migrate/20180626125654_add_index_on_deployable_for_deployments.rb2
-rw-r--r--db/migrate/20180628124813_alter_web_hook_logs_indexes.rb4
-rw-r--r--db/migrate/20180629153018_create_site_statistics.rb2
-rw-r--r--db/migrate/20180702124358_remove_orphaned_routes.rb2
-rw-r--r--db/migrate/20180702134423_generate_missing_routes.rb2
-rw-r--r--db/migrate/20180704204006_add_hide_third_party_offers_to_application_settings.rb2
-rw-r--r--db/migrate/20180705160945_add_file_format_to_ci_job_artifacts.rb2
-rw-r--r--db/migrate/20180710162338_add_foreign_key_from_notification_settings_to_users.rb2
-rw-r--r--db/migrate/20180711103851_drop_duplicate_protected_tags.rb2
-rw-r--r--db/migrate/20180711103922_add_protected_tags_index.rb2
-rw-r--r--db/migrate/20180713092803_create_user_statuses.rb2
-rw-r--r--db/migrate/20180717125853_remove_restricted_todos.rb2
-rw-r--r--db/migrate/20180718005113_add_instance_statistics_visibility_to_application_setting.rb2
-rw-r--r--db/migrate/20180720023512_add_receive_max_input_size_to_application_settings.rb2
-rw-r--r--db/migrate/20180722103201_add_private_profile_to_users.rb2
-rw-r--r--db/migrate/20180723135214_add_web_ide_client_side_preview_enabled_to_application_settings.rb2
-rw-r--r--db/migrate/20180726172057_create_resource_label_events.rb2
-rw-r--r--db/migrate/20180807153545_remove_redundant_status_index_on_ci_builds.rb2
-rw-r--r--db/migrate/20180808162000_add_user_show_add_ssh_key_message_to_application_settings.rb2
-rw-r--r--db/migrate/20180813101999_change_default_of_auto_devops_instance_wide.rb2
-rw-r--r--db/migrate/20180813102000_enable_auto_devops_instance_wide_for_everyone.rb2
-rw-r--r--db/migrate/20180814153625_add_commit_email_to_users.rb2
-rw-r--r--db/migrate/20180815040323_add_authorization_type_to_cluster_platforms_kubernetes.rb2
-rw-r--r--db/migrate/20180815160409_add_file_location_to_ci_job_artifacts.rb2
-rw-r--r--db/migrate/20180815170510_add_partial_index_to_ci_builds_artifacts_file.rb2
-rw-r--r--db/migrate/20180815175440_add_index_on_list_type.rb2
-rw-r--r--db/migrate/20180831164904_fix_prometheus_metric_query_limits.rb2
-rw-r--r--db/migrate/20180831164905_add_common_to_prometheus_metrics.rb2
-rw-r--r--db/migrate/20180831164907_add_index_on_common_for_prometheus_metrics.rb2
-rw-r--r--db/migrate/20180831164908_add_identifier_to_prometheus_metric.rb2
-rw-r--r--db/migrate/20180831164909_add_index_for_identifier_to_prometheus_metric.rb2
-rw-r--r--db/migrate/20180831164910_import_common_metrics.rb2
-rw-r--r--db/migrate/20180901171833_add_project_config_source_status_index_to_pipeline.rb2
-rw-r--r--db/migrate/20180901200537_add_resource_label_event_reference_fields.rb2
-rw-r--r--db/migrate/20180906101639_add_user_ping_consent_to_application_settings.rb2
-rw-r--r--db/migrate/20180907015926_add_legacy_abac_to_cluster_providers_gcp.rb2
-rw-r--r--db/migrate/20180910115836_add_attr_encrypted_columns_to_web_hook.rb15
-rw-r--r--db/migrate/20180910153412_add_token_digest_to_personal_access_tokens.rb19
-rw-r--r--db/migrate/20180910153413_add_index_to_token_digest_on_personal_access_tokens.rb17
-rw-r--r--db/migrate/20180912111628_add_knative_application.rb20
-rw-r--r--db/migrate/20180916011959_add_index_pipelines_project_id_source.rb20
-rw-r--r--db/migrate/20180924141949_add_diff_max_patch_bytes_to_application_settings.rb25
-rw-r--r--db/migrate/20180924190739_add_scheduled_at_to_ci_builds.rb9
-rw-r--r--db/migrate/20180924201039_add_partial_index_to_scheduled_at.rb18
-rw-r--r--db/migrate/20180925200829_create_user_preferences.rb31
-rw-r--r--db/migrate/20180927073410_add_index_to_project_deploy_tokens_deploy_token_id.rb18
-rw-r--r--db/migrate/20181002172433_remove_restricted_todos_with_cte.rb32
-rw-r--r--db/migrate/20181005110927_add_index_to_lfs_objects_file_store.rb17
-rw-r--r--db/migrate/20181005125926_add_index_to_uploads_store.rb17
-rw-r--r--db/migrate/20181009190428_create_clusters_kubernetes_namespaces.rb24
-rw-r--r--db/migrate/20181010235606_create_board_project_recent_visits.rb19
-rw-r--r--db/migrate/20181014203236_create_cluster_groups.rb17
-rw-r--r--db/migrate/20181015155839_add_finished_at_to_deployments.rb15
-rw-r--r--db/migrate/20181016141739_add_status_to_deployments.rb29
-rw-r--r--db/migrate/20181016152238_create_board_group_recent_visits.rb20
-rw-r--r--db/migrate/20181017001059_add_cluster_type_to_clusters.rb18
-rw-r--r--db/migrate/20181019032400_add_shards_table.rb11
-rw-r--r--db/migrate/20181019032408_add_repositories_table.rb15
-rw-r--r--db/migrate/20181019105553_add_projects_pool_repository_id_foreign_key.rb22
-rw-r--r--db/migrate/20181022135539_add_index_on_status_to_deployments.rb19
-rw-r--r--db/migrate/20181023104858_add_archive_builds_duration_to_application_settings.rb11
-rw-r--r--db/migrate/20181023144439_add_partial_index_for_legacy_successful_deployments.rb18
-rw-r--r--db/migrate/20181025115728_add_private_commit_email_hostname_to_application_settings.rb11
-rw-r--r--db/migrate/20181026143227_migrate_snippets_access_level_default_value.rb42
-rw-r--r--db/migrate/20181030154446_add_missing_indexes_for_foreign_keys.rb65
-rw-r--r--db/migrate/20181031190558_drop_fk_gcp_clusters_table.rb37
-rw-r--r--db/migrate/20181031190559_drop_gcp_clusters_table.rb53
-rw-r--r--db/migrate/20181101144347_add_index_for_stuck_mr_query.rb16
-rw-r--r--db/migrate/20181101191341_create_clusters_applications_cert_manager.rb19
-rw-r--r--db/migrate/20181106135939_add_index_to_deployments.rb17
-rw-r--r--db/migrate/20181108091549_cleanup_environments_external_url.rb18
-rw-r--r--db/migrate/20181112103239_drop_default_value_on_status_deployments.rb14
-rw-r--r--db/migrate/20181116050532_knative_external_ip.rb14
-rw-r--r--db/migrate/20181120082911_rename_repositories_pool_repositories.rb11
-rw-r--r--db/migrate/20181122160027_create_project_repositories.rb18
-rw-r--r--db/migrate/20181123135036_drop_not_null_constraint_pool_repository_disk_path.rb9
-rw-r--r--db/migrate/20181126150622_add_events_index_on_project_id_and_created_at.rb32
-rw-r--r--db/migrate/20181126153547_remove_notes_index_on_updated_at.rb32
-rw-r--r--db/migrate/gpg_keys_limits_to_mysql.rb2
-rw-r--r--db/migrate/limits_ci_build_trace_chunks_raw_data_for_mysql.rb2
-rw-r--r--db/migrate/limits_to_mysql.rb2
-rw-r--r--db/migrate/markdown_cache_limits_to_mysql.rb2
-rw-r--r--db/migrate/merge_request_diff_file_limits_to_mysql.rb2
-rw-r--r--db/migrate/prometheus_metrics_limits_to_mysql.rb2
-rw-r--r--db/optional_migrations/composite_primary_keys.rb2
-rw-r--r--db/post_migrate/20160824121037_change_personal_access_tokens_default_back_to_empty_array.rb2
-rw-r--r--db/post_migrate/20161011222551_remove_inactive_jira_service_properties.rb2
-rw-r--r--db/post_migrate/20161109150329_fix_project_records_with_invalid_visibility.rb2
-rw-r--r--db/post_migrate/20161128170531_drop_user_activities_table.rb2
-rw-r--r--db/post_migrate/20161221140236_remove_unneeded_services.rb2
-rw-r--r--db/post_migrate/20161221153951_rename_reserved_project_names.rb10
-rw-r--r--db/post_migrate/20170104150317_requeue_pending_delete_projects.rb2
-rw-r--r--db/post_migrate/20170106142508_fill_authorized_projects.rb2
-rw-r--r--db/post_migrate/20170106172224_remove_project_authorizations_id_column.rb2
-rw-r--r--db/post_migrate/20170131214021_reset_users_authorized_projects_populated.rb2
-rw-r--r--db/post_migrate/20170206040400_remove_inactive_default_email_services.rb2
-rw-r--r--db/post_migrate/20170206101007_remove_trackable_columns_from_timelogs.rb2
-rw-r--r--db/post_migrate/20170206101030_validate_foreign_keys_on_timelogs.rb2
-rw-r--r--db/post_migrate/20170209140523_validate_foreign_keys_on_oauth_openid_requests.rb2
-rw-r--r--db/post_migrate/20170211073944_disable_invalid_service_templates.rb2
-rw-r--r--db/post_migrate/20170214111112_delete_deprecated_gitlab_ci_service.rb2
-rw-r--r--db/post_migrate/20170215200045_remove_theme_id_from_users.rb2
-rw-r--r--db/post_migrate/20170301205640_migrate_build_events_to_pipeline_events.rb2
-rw-r--r--db/post_migrate/20170306170512_migrate_legacy_manual_actions.rb2
-rw-r--r--db/post_migrate/20170309171644_reset_relative_position_for_issue.rb2
-rw-r--r--db/post_migrate/20170313133418_rename_more_reserved_project_names.rb10
-rw-r--r--db/post_migrate/20170317162059_update_upload_paths_to_system.rb2
-rw-r--r--db/post_migrate/20170324160416_migrate_user_activities_to_users_last_activity_on.rb2
-rw-r--r--db/post_migrate/20170404170532_remove_notes_original_discussion_id.rb2
-rw-r--r--db/post_migrate/20170406111121_clean_upload_symlinks.rb2
-rw-r--r--db/post_migrate/20170406142253_migrate_user_project_view.rb2
-rw-r--r--db/post_migrate/20170408033905_remove_old_cache_directories.rb2
-rw-r--r--db/post_migrate/20170412174900_rename_reserved_dynamic_paths.rb2
-rw-r--r--db/post_migrate/20170425121605_migrate_trigger_schedules_to_pipeline_schedules.rb2
-rw-r--r--db/post_migrate/20170425130047_drop_ci_trigger_schedules_table.rb2
-rw-r--r--db/post_migrate/20170502070007_enable_auto_cancel_pending_pipelines_for_all.rb2
-rw-r--r--db/post_migrate/20170502101023_cleanup_namespaceless_pending_delete_projects.rb2
-rw-r--r--db/post_migrate/20170503004427_update_retried_for_ci_build.rb2
-rw-r--r--db/post_migrate/20170503120310_remove_users_authorized_projects_populated.rb2
-rw-r--r--db/post_migrate/20170508170547_add_head_pipeline_for_each_merge_request.rb2
-rw-r--r--db/post_migrate/20170510101043_add_foreign_key_on_pipeline_schedule_owner.rb2
-rw-r--r--db/post_migrate/20170511100900_cleanup_rename_web_hooks_build_events_to_job_events.rb2
-rw-r--r--db/post_migrate/20170511101000_cleanup_rename_services_build_events_to_job_events.rb2
-rw-r--r--db/post_migrate/20170516165238_cleanup_trigger_for_issues.rb2
-rw-r--r--db/post_migrate/20170516181025_add_constraints_to_issue_assignees_table.rb2
-rw-r--r--db/post_migrate/20170518200835_rename_users_with_renamed_namespace.rb2
-rw-r--r--db/post_migrate/20170518231126_fix_wrongly_renamed_routes.rb2
-rw-r--r--db/post_migrate/20170523073948_remove_assignee_id_from_issue.rb2
-rw-r--r--db/post_migrate/20170523083112_migrate_old_artifacts.rb2
-rw-r--r--db/post_migrate/20170525140254_rename_all_reserved_paths_again.rb2
-rw-r--r--db/post_migrate/20170526185842_migrate_pipeline_stages.rb2
-rw-r--r--db/post_migrate/20170526185858_create_index_in_pipeline_stages.rb2
-rw-r--r--db/post_migrate/20170526185901_remove_stage_id_index_from_builds.rb2
-rw-r--r--db/post_migrate/20170526185921_migrate_build_stage_reference.rb2
-rw-r--r--db/post_migrate/20170526190000_migrate_build_stage_reference_again.rb2
-rw-r--r--db/post_migrate/20170531203055_cleanup_users_ldap_email_rename.rb2
-rw-r--r--db/post_migrate/20170606202615_move_appearance_to_system_dir.rb2
-rw-r--r--db/post_migrate/20170607121233_convert_custom_notification_settings_to_columns.rb2
-rw-r--r--db/post_migrate/20170609183112_remove_position_from_issuables.rb2
-rw-r--r--db/post_migrate/20170612071012_move_personal_snippets_files.rb2
-rw-r--r--db/post_migrate/20170613111224_clean_appearance_symlinks.rb2
-rw-r--r--db/post_migrate/20170621102400_add_stage_id_index_to_builds.rb2
-rw-r--r--db/post_migrate/20170627101016_schedule_event_migrations.rb2
-rw-r--r--db/post_migrate/20170628080858_migrate_stage_id_reference_in_background.rb2
-rw-r--r--db/post_migrate/20170629180131_cleanup_application_settings_signin_enabled_rename.rb2
-rw-r--r--db/post_migrate/20170703130158_schedule_merge_request_diff_migrations.rb2
-rw-r--r--db/post_migrate/20170711145558_migrate_stages_statuses.rb2
-rw-r--r--db/post_migrate/20170717111152_cleanup_move_system_upload_folder_symlink.rb4
-rw-r--r--db/post_migrate/20170717150329_enqueue_migrate_system_uploads_to_new_folder.rb2
-rw-r--r--db/post_migrate/20170719150301_merge_issuable_reopened_into_opened_state.rb2
-rw-r--r--db/post_migrate/20170728101014_remove_events_from_notification_settings.rb2
-rw-r--r--db/post_migrate/20170803090603_calculate_conv_dev_index_percentages.rb2
-rw-r--r--db/post_migrate/20170807160457_remove_locked_at_column_from_merge_requests.rb2
-rw-r--r--db/post_migrate/20170807190736_move_personal_snippet_files_into_correct_folder.rb2
-rw-r--r--db/post_migrate/20170815060945_remove_duplicate_mr_events.rb2
-rw-r--r--db/post_migrate/20170816102555_cleanup_nonexisting_namespace_pending_delete_projects.rb2
-rw-r--r--db/post_migrate/20170822101017_migrate_pipeline_sidekiq_queues.rb2
-rw-r--r--db/post_migrate/20170828170502_post_deploy_migrate_user_external_mail_data.rb2
-rw-r--r--db/post_migrate/20170828170513_remove_user_email_provider_column.rb2
-rw-r--r--db/post_migrate/20170828170516_remove_user_external_mail_columns.rb2
-rw-r--r--db/post_migrate/20170830084744_destroy_gpg_signatures.rb2
-rw-r--r--db/post_migrate/20170830150306_drop_events_for_migration_table.rb2
-rw-r--r--db/post_migrate/20170831195038_remove_valid_signature_from_gpg_signatures.rb2
-rw-r--r--db/post_migrate/20170907170235_delete_conflicting_redirect_routes.rb2
-rw-r--r--db/post_migrate/20170913180600_fix_projects_without_project_feature.rb2
-rw-r--r--db/post_migrate/20170921101004_normalize_ldap_extern_uids.rb2
-rw-r--r--db/post_migrate/20170926150348_schedule_merge_request_diff_migrations_take_two.rb2
-rw-r--r--db/post_migrate/20170927112318_update_legacy_diff_notes_type_for_import.rb2
-rw-r--r--db/post_migrate/20170927112319_update_notes_type_for_import.rb2
-rw-r--r--db/post_migrate/20171005130944_schedule_create_gpg_key_subkeys_from_gpg_keys.rb2
-rw-r--r--db/post_migrate/20171012150314_remove_user_authentication_token.rb2
-rw-r--r--db/post_migrate/20171013104327_migrate_gcp_clusters_to_new_clusters_architectures.rb2
-rw-r--r--db/post_migrate/20171026082505_schedule_merge_request_latest_merge_request_diff_id_migrations.rb2
-rw-r--r--db/post_migrate/20171101134435_remove_ref_fetched_from_merge_requests.rb2
-rw-r--r--db/post_migrate/20171103140253_track_untracked_uploads.rb2
-rw-r--r--db/post_migrate/20171106133144_cleanup_application_settings_password_authentication_enabled_rename.rb2
-rw-r--r--db/post_migrate/20171106154015_remove_issues_branch_name.rb2
-rw-r--r--db/post_migrate/20171106180641_cleanup_add_timezone_to_issues_closed_at.rb2
-rw-r--r--db/post_migrate/20171114104051_remove_empty_fork_networks.rb2
-rw-r--r--db/post_migrate/20171121160421_remove_merge_request_diff_st_commits_and_st_diffs.rb2
-rw-r--r--db/post_migrate/20171123101020_update_circuitbreaker_defaults.rb2
-rw-r--r--db/post_migrate/20171123101046_remove_old_circuitbreaker_config.rb2
-rw-r--r--db/post_migrate/20171124095655_add_index_on_merge_request_diffs_merge_request_id_and_id.rb2
-rw-r--r--db/post_migrate/20171124100152_remove_index_on_merge_request_diffs_merge_request_diff_id.rb2
-rw-r--r--db/post_migrate/20171124104327_migrate_kubernetes_service_to_new_clusters_architectures.rb2
-rw-r--r--db/post_migrate/20171124150326_reschedule_fork_network_creation.rb2
-rw-r--r--db/post_migrate/20171128214150_schedule_populate_merge_request_metrics_with_events_data.rb2
-rw-r--r--db/post_migrate/20171205190711_reschedule_fork_network_creation_caller.rb2
-rw-r--r--db/post_migrate/20171207150300_remove_project_labels_group_id_copy.rb2
-rw-r--r--db/post_migrate/20171207150343_remove_soft_removed_objects.rb2
-rw-r--r--db/post_migrate/20171207150344_remove_deleted_at_columns.rb2
-rw-r--r--db/post_migrate/20171213160445_migrate_github_importer_advance_stage_sidekiq_queue.rb2
-rw-r--r--db/post_migrate/20171215121205_post_populate_can_push_from_deploy_keys_projects.rb2
-rw-r--r--db/post_migrate/20171215121259_remove_can_push_from_keys.rb2
-rw-r--r--db/post_migrate/20171219121201_normalize_extern_uid_from_identities.rb2
-rw-r--r--db/post_migrate/20171221140220_schedule_issues_closed_at_type_change.rb2
-rw-r--r--db/post_migrate/20180104131052_schedule_set_confidential_note_events_on_webhooks.rb2
-rw-r--r--db/post_migrate/20180119121225_remove_redundant_pipeline_stages.rb2
-rw-r--r--db/post_migrate/20180122154930_schedule_set_confidential_note_events_on_services.rb2
-rw-r--r--db/post_migrate/20180202111106_remove_project_labels_group_id.rb2
-rw-r--r--db/post_migrate/20180204200836_change_author_id_to_not_null_in_todos.rb2
-rw-r--r--db/post_migrate/20180212101828_add_tmp_partial_null_index_to_builds.rb2
-rw-r--r--db/post_migrate/20180212101928_schedule_build_stage_migration.rb2
-rw-r--r--db/post_migrate/20180212102028_remove_tmp_partial_null_index_from_builds.rb2
-rw-r--r--db/post_migrate/20180216121020_fill_pages_domain_verification_code.rb2
-rw-r--r--db/post_migrate/20180216121030_enqueue_verify_pages_domain_workers.rb2
-rw-r--r--db/post_migrate/20180220150310_remove_empty_extern_uid_auth0_identities.rb2
-rw-r--r--db/post_migrate/20180223124427_build_user_interacted_projects_table.rb6
-rw-r--r--db/post_migrate/20180301084653_change_project_namespace_id_not_null.rb2
-rw-r--r--db/post_migrate/20180305100050_remove_permanent_from_redirect_routes.rb2
-rw-r--r--db/post_migrate/20180306074045_migrate_create_trace_artifact_sidekiq_queue.rb2
-rw-r--r--db/post_migrate/20180306164012_add_path_index_to_redirect_routes.rb2
-rw-r--r--db/post_migrate/20180307012445_migrate_update_head_pipeline_for_merge_request_sidekiq_queue.rb2
-rw-r--r--db/post_migrate/20180405101928_reschedule_builds_stages_migration.rb2
-rw-r--r--db/post_migrate/20180408143355_cleanup_users_rss_token_rename.rb2
-rw-r--r--db/post_migrate/20180409170809_populate_missing_project_ci_cd_settings.rb2
-rw-r--r--db/post_migrate/20180420080616_schedule_stages_index_migration.rb2
-rw-r--r--db/post_migrate/20180424151928_fill_file_store.rb2
-rw-r--r--db/post_migrate/20180430143705_backfill_runner_type_for_ci_runners_post_migrate.rb2
-rw-r--r--db/post_migrate/20180502134117_migrate_import_attributes_data_from_projects_to_project_mirror_data.rb2
-rw-r--r--db/post_migrate/20180507083701_set_minimal_project_build_timeout.rb2
-rw-r--r--db/post_migrate/20180511174224_add_unique_constraint_to_project_features_project_id.rb2
-rw-r--r--db/post_migrate/20180512061621_add_not_null_constraint_to_project_features_project_id.rb2
-rw-r--r--db/post_migrate/20180514161336_remove_gemnasium_service.rb2
-rw-r--r--db/post_migrate/20180521162137_migrate_remaining_mr_metrics_populating_background_migration.rb2
-rw-r--r--db/post_migrate/20180523125103_cleanup_merge_requests_allow_maintainer_to_push_rename.rb2
-rw-r--r--db/post_migrate/20180529152628_schedule_to_archive_legacy_traces.rb2
-rw-r--r--db/post_migrate/20180603190921_migrate_object_storage_upload_sidekiq_queue.rb2
-rw-r--r--db/post_migrate/20180604123514_cleanup_stages_position_migration.rb2
-rw-r--r--db/post_migrate/20180608201435_cleanup_merge_requests_allow_collaboration_rename.rb2
-rw-r--r--db/post_migrate/20180619121030_enqueue_delete_diff_files_workers.rb2
-rw-r--r--db/post_migrate/20180629191052_add_partial_index_to_projects_for_last_repository_check_at.rb2
-rw-r--r--db/post_migrate/20180702120647_enqueue_fix_cross_project_label_links.rb2
-rw-r--r--db/post_migrate/20180704145007_update_project_indexes.rb2
-rw-r--r--db/post_migrate/20180706223200_populate_site_statistics.rb2
-rw-r--r--db/post_migrate/20180723130817_delete_inconsistent_internal_id_records.rb2
-rw-r--r--db/post_migrate/20180809195358_migrate_null_wiki_access_levels.rb2
-rw-r--r--db/post_migrate/20180816161409_migrate_legacy_artifacts_to_job_artifacts.rb2
-rw-r--r--db/post_migrate/20180816193530_rename_login_root_namespaces.rb4
-rw-r--r--db/post_migrate/20180826111825_recalculate_site_statistics.rb2
-rw-r--r--db/post_migrate/20180906051323_remove_orphaned_label_links.rb2
-rw-r--r--db/post_migrate/20180913051323_consume_remaining_diff_files_deletion_jobs.rb23
-rw-r--r--db/post_migrate/20180913142237_schedule_digest_personal_access_tokens.rb28
-rw-r--r--db/post_migrate/20180914162043_encrypt_web_hooks_columns.rb33
-rw-r--r--db/post_migrate/20180914201132_remove_sidekiq_throttling_from_application_settings.rb17
-rw-r--r--db/post_migrate/20180916014356_populate_external_pipeline_source.rb33
-rw-r--r--db/post_migrate/20180917172041_remove_wikis_count_from_site_statistics.rb6
-rw-r--r--db/post_migrate/20181008145341_steal_encrypt_columns.rb15
-rw-r--r--db/post_migrate/20181008145359_remove_web_hooks_token_and_url.rb10
-rw-r--r--db/post_migrate/20181008200441_remove_circuit_breaker.rb30
-rw-r--r--db/post_migrate/20181010133639_backfill_store_project_full_path_in_repo.rb27
-rw-r--r--db/post_migrate/20181013005024_remove_koding_from_application_settings.rb17
-rw-r--r--db/post_migrate/20181014121030_enqueue_redact_links.rb65
-rw-r--r--db/post_migrate/20181022173835_enqueue_populate_cluster_kubernetes_namespace.rb18
-rw-r--r--db/post_migrate/20181026091631_migrate_forbidden_redirect_uris.rb32
-rw-r--r--db/post_migrate/20181030135124_fill_empty_finished_at_in_deployments.rb27
-rw-r--r--db/post_migrate/20181105201455_steal_fill_store_upload.rb31
-rw-r--r--db/post_migrate/20181107054254_remove_restricted_todos_again.rb32
-rw-r--r--db/post_migrate/20181123042307_drop_site_statistics.rb22
-rw-r--r--db/schema.rb1068
-rw-r--r--doc/README.md584
-rw-r--r--doc/administration/auth/authentiq.md36
-rw-r--r--doc/administration/auth/ldap.md4
-rw-r--r--doc/administration/auth/okta.md2
-rw-r--r--doc/administration/container_registry.md5
-rw-r--r--doc/administration/custom_hooks.md5
-rw-r--r--doc/administration/external_database.md2
-rw-r--r--doc/administration/git_protocol.md103
-rw-r--r--doc/administration/gitaly/index.md39
-rw-r--r--doc/administration/high_availability/database.md2
-rw-r--r--doc/administration/high_availability/gitlab.md2
-rw-r--r--doc/administration/high_availability/nfs.md55
-rw-r--r--doc/administration/high_availability/redis.md26
-rw-r--r--doc/administration/high_availability/redis_source.md8
-rw-r--r--doc/administration/img/circuitbreaker_config.pngbin29130 -> 0 bytes
-rw-r--r--doc/administration/img/failing_storage.pngbin16291 -> 0 bytes
-rw-r--r--doc/administration/index.md7
-rw-r--r--doc/administration/integration/koding.md246
-rw-r--r--doc/administration/integration/plantuml.md4
-rw-r--r--doc/administration/job_artifacts.md15
-rw-r--r--doc/administration/logs.md53
-rw-r--r--doc/administration/monitoring/performance/img/request_profiling_token.pngbin10217 -> 50774 bytes
-rw-r--r--doc/administration/monitoring/performance/influxdb_configuration.md6
-rw-r--r--doc/administration/monitoring/performance/performance_bar.md4
-rw-r--r--doc/administration/monitoring/performance/request_profiling.md17
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md4
-rw-r--r--doc/administration/monitoring/prometheus/index.md129
-rw-r--r--doc/administration/operations/fast_ssh_key_lookup.md16
-rw-r--r--doc/administration/operations/filesystem_benchmarking.md55
-rw-r--r--doc/administration/operations/img/sidekiq_job_throttling.pngbin32224 -> 0 bytes
-rw-r--r--doc/administration/operations/index.md6
-rw-r--r--doc/administration/operations/moving_repositories.md26
-rw-r--r--doc/administration/operations/sidekiq_job_throttling.md33
-rw-r--r--doc/administration/operations/ssh_certificates.md4
-rw-r--r--doc/administration/pages/index.md104
-rw-r--r--doc/administration/pages/source.md43
-rw-r--r--doc/administration/raketasks/github_import.md32
-rw-r--r--doc/administration/raketasks/maintenance.md11
-rw-r--r--doc/administration/reply_by_email.md2
-rw-r--r--doc/administration/reply_by_email_postfix_setup.md4
-rw-r--r--doc/administration/repository_checks.md5
-rw-r--r--doc/administration/repository_storage_paths.md49
-rw-r--r--doc/administration/repository_storage_types.md5
-rw-r--r--doc/administration/troubleshooting/debug.md6
-rw-r--r--doc/administration/uploads.md9
-rw-r--r--doc/api/README.md47
-rw-r--r--doc/api/applications.md51
-rw-r--r--doc/api/avatar.md2
-rw-r--r--doc/api/commits.md55
-rw-r--r--doc/api/deployments.md45
-rw-r--r--doc/api/discussions.md8
-rw-r--r--doc/api/events.md6
-rw-r--r--doc/api/groups.md13
-rw-r--r--doc/api/issues.md113
-rw-r--r--doc/api/jobs.md95
-rw-r--r--doc/api/keys.md8
-rw-r--r--doc/api/members.md2
-rw-r--r--doc/api/merge_requests.md834
-rw-r--r--doc/api/notes.md2
-rw-r--r--doc/api/oauth2.md8
-rw-r--r--doc/api/pipelines.md17
-rw-r--r--doc/api/project_templates.md139
-rw-r--r--doc/api/projects.md55
-rw-r--r--doc/api/repositories.md13
-rw-r--r--doc/api/repository_files.md21
-rw-r--r--doc/api/repository_storage_health.md75
-rw-r--r--doc/api/repository_submodules.md49
-rw-r--r--doc/api/runners.md26
-rw-r--r--doc/api/services.md36
-rw-r--r--doc/api/settings.md20
-rw-r--r--doc/api/snippets.md40
-rw-r--r--doc/api/tags.md2
-rw-r--r--doc/api/templates/dockerfiles.md113
-rw-r--r--doc/api/templates/gitignores.md520
-rw-r--r--doc/api/templates/gitlab_ci_ymls.md75
-rw-r--r--doc/api/users.md58
-rw-r--r--doc/api/wikis.md14
-rw-r--r--doc/ci/README.md2
-rw-r--r--doc/ci/autodeploy/quick_start_guide.md10
-rw-r--r--doc/ci/caching/index.md16
-rw-r--r--doc/ci/docker/using_docker_build.md96
-rw-r--r--doc/ci/docker/using_docker_images.md35
-rw-r--r--doc/ci/docker/using_kaniko.md5
-rw-r--r--doc/ci/environments.md40
-rw-r--r--doc/ci/examples/README.md18
-rw-r--r--doc/ci/examples/artifactory_and_gitlab/index.md4
-rw-r--r--doc/ci/examples/browser_performance.md75
-rw-r--r--doc/ci/examples/code_quality.md82
-rw-r--r--doc/ci/examples/container_scanning.md85
-rw-r--r--doc/ci/examples/dast.md67
-rw-r--r--doc/ci/examples/deploy_spring_boot_to_cloud_foundry/img/cloud_foundry_secret_variables.pngbin49735 -> 0 bytes
-rw-r--r--doc/ci/examples/deploy_spring_boot_to_cloud_foundry/img/cloud_foundry_variables.pngbin0 -> 28170 bytes
-rw-r--r--doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md6
-rw-r--r--doc/ci/examples/deployment/README.md10
-rw-r--r--doc/ci/examples/deployment/composer-npm-deploy.md26
-rw-r--r--doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md4
-rw-r--r--doc/ci/examples/laravel_with_gitlab_and_envoy/img/container_registry_checkbox.pngbin4730 -> 0 bytes
-rw-r--r--doc/ci/examples/laravel_with_gitlab_and_envoy/img/secret_variables_page.pngbin96864 -> 0 bytes
-rw-r--r--doc/ci/examples/laravel_with_gitlab_and_envoy/img/variables_page.pngbin0 -> 27538 bytes
-rw-r--r--doc/ci/examples/laravel_with_gitlab_and_envoy/index.md38
-rw-r--r--doc/ci/examples/php.md4
-rw-r--r--doc/ci/examples/test-and-deploy-python-application-to-heroku.md12
-rw-r--r--doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md11
-rw-r--r--doc/ci/examples/test-scala-application.md4
-rw-r--r--doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md6
-rw-r--r--doc/ci/img/pipeline_incremental_rollout.pngbin0 -> 4794 bytes
-rw-r--r--doc/ci/img/pipelines-goal.pngbin0 -> 36933 bytes
-rw-r--r--doc/ci/img/pipelines-goal.svg4
-rw-r--r--doc/ci/img/types-of-pipelines.pngbin0 -> 31245 bytes
-rw-r--r--doc/ci/img/types-of-pipelines.svg4
-rw-r--r--doc/ci/img/view_on_env_blob.pngbin32924 -> 11889 bytes
-rw-r--r--doc/ci/img/view_on_mr_widget.pngbin0 -> 21969 bytes
-rw-r--r--doc/ci/interactive_web_terminal/index.md19
-rw-r--r--doc/ci/junit_test_reports.md27
-rw-r--r--doc/ci/pipelines.md19
-rw-r--r--doc/ci/quick_start/README.md2
-rw-r--r--doc/ci/review_apps/img/continuous-delivery-review-apps.svg48
-rw-r--r--doc/ci/review_apps/img/review_apps_preview_in_mr.pngbin11664 -> 29800 bytes
-rw-r--r--doc/ci/review_apps/index.md163
-rw-r--r--doc/ci/runners/README.md14
-rw-r--r--doc/ci/services/mysql.md2
-rw-r--r--doc/ci/services/redis.md2
-rw-r--r--doc/ci/triggers/README.md7
-rw-r--r--doc/ci/variables/README.md16
-rw-r--r--doc/ci/variables/img/secret_variables.pngbin32886 -> 0 bytes
-rw-r--r--doc/ci/variables/img/variables.pngbin0 -> 116263 bytes
-rw-r--r--doc/ci/variables/where_variables_can_be_used.md20
-rw-r--r--doc/ci/yaml/README.md307
-rw-r--r--doc/development/README.md9
-rw-r--r--doc/development/adding_database_indexes.md6
-rw-r--r--doc/development/api_graphql_styleguide.md2
-rw-r--r--doc/development/architecture.md189
-rw-r--r--doc/development/automatic_ce_ee_merge.md5
-rw-r--r--doc/development/build_test_package.md13
-rw-r--r--doc/development/changelog.md21
-rw-r--r--doc/development/chaos_endpoints.md117
-rw-r--r--doc/development/code_review.md217
-rw-r--r--doc/development/contributing/community_roles.md16
-rw-r--r--doc/development/contributing/design.md44
-rw-r--r--doc/development/contributing/index.md199
-rw-r--r--doc/development/contributing/issue_workflow.md188
-rw-r--r--doc/development/contributing/merge_request_workflow.md49
-rw-r--r--doc/development/contributing/style_guides.md39
-rw-r--r--doc/development/database_debugging.md2
-rw-r--r--doc/development/database_merge_request_checklist.md10
-rw-r--r--doc/development/db_dump.md2
-rw-r--r--doc/development/diffs.md49
-rw-r--r--doc/development/documentation/index.md452
-rw-r--r--doc/development/documentation/structure.md89
-rw-r--r--doc/development/documentation/styleguide.md297
-rw-r--r--doc/development/documentation/workflow.md33
-rw-r--r--doc/development/ee_features.md184
-rw-r--r--doc/development/fe_guide/components.md4
-rw-r--r--doc/development/fe_guide/droplab/droplab.md2
-rw-r--r--doc/development/fe_guide/graphql.md83
-rw-r--r--doc/development/fe_guide/icons.md4
-rw-r--r--doc/development/fe_guide/index.md3
-rw-r--r--doc/development/fe_guide/style_guide_js.md109
-rw-r--r--doc/development/fe_guide/style_guide_scss.md6
-rw-r--r--doc/development/fe_guide/vue.md8
-rw-r--r--doc/development/fe_guide/vuex.md12
-rw-r--r--doc/development/feature_flags.md38
-rw-r--r--doc/development/gitaly.md59
-rw-r--r--doc/development/github_importer.md20
-rw-r--r--doc/development/gotchas.md6
-rw-r--r--doc/development/i18n/index.md2
-rw-r--r--doc/development/i18n/merging_translations.md60
-rw-r--r--doc/development/i18n/proofreader.md51
-rw-r--r--doc/development/instrumentation.md12
-rw-r--r--doc/development/logging.md144
-rw-r--r--doc/development/merge_request_performance_guidelines.md5
-rw-r--r--doc/development/migration_style_guide.md13
-rw-r--r--doc/development/module_with_instance_variables.md2
-rw-r--r--doc/development/new_fe_guide/development/performance.md2
-rw-r--r--doc/development/new_fe_guide/development/testing.md295
-rw-r--r--doc/development/new_fe_guide/index.md4
-rw-r--r--doc/development/new_fe_guide/modules/dirty_submit.md23
-rw-r--r--doc/development/new_fe_guide/modules/index.md5
-rw-r--r--doc/development/new_fe_guide/style/prettier.md4
-rw-r--r--doc/development/ordering_table_columns.md73
-rw-r--r--doc/development/performance.md31
-rw-r--r--doc/development/post_deployment_migrations.md6
-rw-r--r--doc/development/query_count_limits.md4
-rw-r--r--doc/development/rake_tasks.md2
-rw-r--r--doc/development/rolling_out_changes_using_feature_flags.md37
-rw-r--r--doc/development/sidekiq_style_guide.md4
-rw-r--r--doc/development/swapping_tables.md4
-rw-r--r--doc/development/switching_to_rails5.md27
-rw-r--r--doc/development/testing_guide/best_practices.md163
-rw-r--r--doc/development/testing_guide/end_to_end_tests.md69
-rw-r--r--doc/development/testing_guide/review_apps.md123
-rw-r--r--doc/development/testing_guide/smoke.md9
-rw-r--r--doc/development/testing_guide/testing_levels.md93
-rw-r--r--doc/development/ui_guide.md110
-rw-r--r--doc/development/utilities.md4
-rw-r--r--doc/development/ux_guide/animation.md68
-rw-r--r--doc/development/ux_guide/basics.md81
-rw-r--r--doc/development/ux_guide/components.md386
-rw-r--r--doc/development/ux_guide/copy.md203
-rw-r--r--doc/development/ux_guide/features.md56
-rw-r--r--doc/development/ux_guide/illustrations.md87
-rw-r--r--doc/development/ux_guide/index.md69
-rw-r--r--doc/development/ux_guide/principles.md20
-rw-r--r--doc/development/ux_guide/resources.md20
-rw-r--r--doc/development/ux_guide/surfaces.md46
-rw-r--r--doc/development/ux_guide/tips.md45
-rw-r--r--doc/development/ux_guide/users.md309
-rw-r--r--doc/development/what_requires_downtime.md2
-rw-r--r--doc/gitlab-basics/add-image.md2
-rw-r--r--doc/gitlab-basics/create-your-ssh-keys.md2
-rw-r--r--doc/img/devops-stages.pngbin0 -> 35549 bytes
-rw-r--r--doc/img/devops_lifecycle.pngbin18611 -> 0 bytes
-rw-r--r--doc/install/README.md6
-rw-r--r--doc/install/aws/img/add_tags.pngbin0 -> 17834 bytes
-rw-r--r--doc/install/aws/img/associate_subnet_gateway.pngbin0 -> 16522 bytes
-rw-r--r--doc/install/aws/img/associate_subnet_gateway_2.pngbin0 -> 10617 bytes
-rw-r--r--doc/install/aws/img/aws_diagram.pngbin0 -> 502497 bytes
-rw-r--r--doc/install/aws/img/choose_ami.pngbin0 -> 4892 bytes
-rw-r--r--doc/install/aws/img/create_gateway.pngbin0 -> 13927 bytes
-rw-r--r--doc/install/aws/img/create_route_table.pngbin0 -> 8293 bytes
-rw-r--r--doc/install/aws/img/create_security_group.pngbin0 -> 12594 bytes
-rw-r--r--doc/install/aws/img/create_subnet.pngbin0 -> 16679 bytes
-rw-r--r--doc/install/aws/img/create_vpc.pngbin0 -> 15613 bytes
-rw-r--r--doc/install/aws/img/ec_az.pngbin0 -> 10476 bytes
-rw-r--r--doc/install/aws/img/ec_subnet.pngbin0 -> 23517 bytes
-rw-r--r--doc/install/aws/img/policies.pngbin0 -> 39723 bytes
-rw-r--r--doc/install/aws/img/rds_subnet_group.pngbin0 -> 30107 bytes
-rw-r--r--doc/install/aws/index.md655
-rw-r--r--doc/install/azure/index.md14
-rw-r--r--doc/install/database_mysql.md59
-rw-r--r--doc/install/digitaloceandocker.md102
-rw-r--r--doc/install/installation.md22
-rw-r--r--doc/install/kubernetes/gitlab_chart.md7
-rw-r--r--doc/install/kubernetes/gitlab_runner_chart.md6
-rw-r--r--doc/install/openshift_and_gitlab/index.md4
-rw-r--r--doc/install/relative_url.md2
-rw-r--r--doc/install/requirements.md14
-rw-r--r--doc/integration/akismet.md16
-rw-r--r--doc/integration/auth0.md2
-rw-r--r--doc/integration/bitbucket.md1
-rw-r--r--doc/integration/github.md36
-rw-r--r--doc/integration/gmail_action_buttons_for_gitlab.md2
-rw-r--r--doc/integration/google.md2
-rw-r--r--doc/integration/img/github_app.pngbin29330 -> 128040 bytes
-rw-r--r--doc/integration/img/github_app_entry.pngbin0 -> 83603 bytes
-rw-r--r--doc/integration/img/github_register_app.pngbin0 -> 120981 bytes
-rw-r--r--doc/integration/recaptcha.md20
-rw-r--r--doc/integration/saml.md17
-rw-r--r--doc/integration/shibboleth.md170
-rw-r--r--doc/policy/maintenance.md3
-rw-r--r--doc/raketasks/backup_restore.md348
-rw-r--r--doc/raketasks/import.md72
-rw-r--r--doc/security/rack_attack.md30
-rw-r--r--doc/security/two_factor_authentication.md6
-rw-r--r--doc/security/user_email_confirmation.md2
-rw-r--r--doc/ssh/README.md243
-rw-r--r--doc/topics/authentication/index.md9
-rw-r--r--doc/topics/autodevops/index.md256
-rw-r--r--doc/topics/autodevops/quick_start_guide.md11
-rw-r--r--doc/topics/git/how_to_install_git/index.md2
-rw-r--r--doc/topics/git/troubleshooting_git.md15
-rw-r--r--doc/university/README.md15
-rw-r--r--doc/university/bookclub/booklist.md52
-rw-r--r--doc/university/glossary/README.md8
-rw-r--r--doc/university/high-availability/aws/README.md36
-rw-r--r--doc/university/support/README.md2
-rw-r--r--doc/university/training/end-user/README.md73
-rw-r--r--doc/university/training/topics/additional_resources.md12
-rw-r--r--doc/university/training/topics/bisect.md12
-rw-r--r--doc/university/training/topics/getting_started.md9
-rw-r--r--doc/university/training/topics/git_log.md10
-rw-r--r--doc/university/training/topics/merge_conflicts.md18
-rw-r--r--doc/university/training/topics/rollback_commits.md18
-rw-r--r--doc/university/training/topics/stash.md12
-rw-r--r--doc/university/training/topics/tags.md2
-rw-r--r--doc/university/training/user_training.md267
-rw-r--r--doc/update/11.2-to-11-3.md378
-rw-r--r--doc/update/11.2-to-11.3.md378
-rw-r--r--doc/update/11.3-to-11.4.md378
-rw-r--r--doc/update/11.4-to-11.5.md390
-rw-r--r--doc/update/4.2-to-5.0.md2
-rw-r--r--doc/update/6.x-or-7.x-to-7.14.md2
-rw-r--r--doc/update/7.5-to-7.6.md2
-rw-r--r--doc/update/7.6-to-7.7.md2
-rw-r--r--doc/update/7.7-to-7.8.md2
-rw-r--r--doc/update/7.8-to-7.9.md2
-rw-r--r--doc/update/7.9-to-7.10.md2
-rw-r--r--doc/update/8.17-to-9.0.md2
-rw-r--r--doc/update/9.0-to-9.1.md2
-rw-r--r--doc/update/9.1-to-9.2.md2
-rw-r--r--doc/update/9.2-to-9.3.md2
-rw-r--r--doc/update/9.3-to-9.4.md2
-rw-r--r--doc/update/README.md9
-rw-r--r--doc/update/patch_versions.md2
-rw-r--r--doc/user/admin_area/custom_project_templates.md25
-rw-r--r--doc/user/admin_area/diff_limits.md21
-rw-r--r--doc/user/admin_area/settings/continuous_integration.md16
-rw-r--r--doc/user/admin_area/settings/email.md17
-rw-r--r--doc/user/admin_area/settings/img/import_sources.pngbin0 -> 10971 bytes
-rw-r--r--doc/user/admin_area/settings/sign_up_restrictions.md2
-rw-r--r--doc/user/admin_area/settings/terms.md8
-rw-r--r--doc/user/admin_area/settings/usage_statistics.md6
-rw-r--r--doc/user/admin_area/settings/visibility_and_access_controls.md7
-rw-r--r--doc/user/discussions/img/index_notes_filters.pngbin0 -> 21284 bytes
-rw-r--r--doc/user/discussions/index.md22
-rw-r--r--doc/user/gitlab_com/index.md2
-rw-r--r--doc/user/group/custom_project_templates.md23
-rw-r--r--doc/user/group/img/access_requests_management.pngbin11186 -> 22616 bytes
-rw-r--r--doc/user/group/img/add_new_members.pngbin18048 -> 66523 bytes
-rw-r--r--doc/user/group/img/create_new_group_info.pngbin30175 -> 51072 bytes
-rw-r--r--doc/user/group/img/create_new_project_from_group.pngbin3185 -> 37234 bytes
-rw-r--r--doc/user/group/img/group_settings.pngbin9704 -> 51335 bytes
-rw-r--r--doc/user/group/img/request_access_button.pngbin35908 -> 36258 bytes
-rw-r--r--doc/user/group/img/select_group_dropdown.pngbin3482 -> 74893 bytes
-rw-r--r--doc/user/group/img/withdraw_access_request_button.pngbin36393 -> 36782 bytes
-rw-r--r--doc/user/group/index.md13
-rw-r--r--doc/user/group/subgroups/index.md32
-rw-r--r--doc/user/img/color_inline_colorchip_render_gfm.pngbin0 -> 11534 bytes
-rw-r--r--doc/user/img/math_inline_sup_render_gfm.pngbin0 -> 1359 bytes
-rw-r--r--doc/user/img/mermaid_diagram_render_gfm.pngbin0 -> 4587 bytes
-rw-r--r--doc/user/img/task_list_ordered_render_gfm.pngbin0 -> 6247 bytes
-rw-r--r--doc/user/img/unordered_check_list_render_gfm.pngbin0 -> 6207 bytes
-rw-r--r--doc/user/index.md2
-rw-r--r--doc/user/instance_statistics/convdev.md15
-rw-r--r--doc/user/markdown.md211
-rw-r--r--doc/user/permissions.md16
-rw-r--r--doc/user/profile/account/two_factor_authentication.md30
-rw-r--r--doc/user/profile/index.md53
-rw-r--r--doc/user/profile/personal_access_tokens.md8
-rw-r--r--doc/user/project/clusters/eks_and_gitlab/img/new_project.pngbin7813 -> 0 bytes
-rw-r--r--doc/user/project/clusters/eks_and_gitlab/img/rbac.pngbin0 -> 15960 bytes
-rw-r--r--doc/user/project/clusters/eks_and_gitlab/index.md259
-rw-r--r--doc/user/project/clusters/index.md271
-rw-r--r--doc/user/project/clusters/runbooks/img/authorize-jupyter.pngbin0 -> 126425 bytes
-rw-r--r--doc/user/project/clusters/runbooks/img/demo-runbook.pngbin0 -> 132436 bytes
-rw-r--r--doc/user/project/clusters/runbooks/img/gitlab-variables.pngbin0 -> 179611 bytes
-rw-r--r--doc/user/project/clusters/runbooks/img/helm-install.pngbin0 -> 201348 bytes
-rw-r--r--doc/user/project/clusters/runbooks/img/ingress-install.pngbin0 -> 140880 bytes
-rw-r--r--doc/user/project/clusters/runbooks/img/jupyterhub-install.pngbin0 -> 116775 bytes
-rw-r--r--doc/user/project/clusters/runbooks/img/postgres-query.pngbin0 -> 209435 bytes
-rw-r--r--doc/user/project/clusters/runbooks/img/sample-runbook.pngbin0 -> 145728 bytes
-rw-r--r--doc/user/project/clusters/runbooks/index.md137
-rw-r--r--doc/user/project/clusters/serverless/img/deploy-stage.pngbin0 -> 12029 bytes
-rw-r--r--doc/user/project/clusters/serverless/img/dns-entry.pngbin0 -> 56600 bytes
-rw-r--r--doc/user/project/clusters/serverless/img/install-knative.pngbin0 -> 102861 bytes
-rw-r--r--doc/user/project/clusters/serverless/img/knative-app.pngbin0 -> 28998 bytes
-rw-r--r--doc/user/project/clusters/serverless/index.md137
-rw-r--r--doc/user/project/container_registry.md25
-rw-r--r--doc/user/project/deploy_tokens/index.md45
-rw-r--r--doc/user/project/img/issue_board.pngbin327718 -> 289964 bytes
-rw-r--r--doc/user/project/img/issue_board_milestone_lists.pngbin0 -> 58740 bytes
-rw-r--r--doc/user/project/img/issue_board_summed_weights.pngbin0 -> 26691 bytes
-rw-r--r--doc/user/project/img/issue_boards_core.pngbin0 -> 119989 bytes
-rw-r--r--doc/user/project/img/issue_boards_premium.pngbin0 -> 99171 bytes
-rw-r--r--doc/user/project/img/koding_build-in-progress.pngbin21937 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_build-logs.pngbin91364 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_build-success.pngbin73005 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_commit-koding.yml.pngbin86023 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_different-stack-on-mr-try.pngbin93404 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_edit-on-ide.pngbin90638 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_enable-koding.pngbin20291 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_landing.pngbin80985 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_open-gitlab-from-koding.pngbin10851 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_run-in-ide.pngbin22178 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_run-mr-in-ide.pngbin93780 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_set-up-ide.pngbin54062 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_stack-import.pngbin137582 -> 0 bytes
-rw-r--r--doc/user/project/img/koding_start-build.pngbin27925 -> 0 bytes
-rw-r--r--doc/user/project/import/clearcase.md2
-rw-r--r--doc/user/project/import/github.md31
-rw-r--r--doc/user/project/import/index.md3
-rw-r--r--doc/user/project/import/manifest.md10
-rw-r--r--doc/user/project/import/svn.md7
-rw-r--r--doc/user/project/integrations/bugzilla.md5
-rw-r--r--doc/user/project/integrations/discord_notifications.md29
-rw-r--r--doc/user/project/integrations/hangouts_chat.md2
-rw-r--r--doc/user/project/integrations/img/jira_api_token.pngbin0 -> 160587 bytes
-rw-r--r--doc/user/project/integrations/img/jira_api_token_menu.pngbin0 -> 68564 bytes
-rw-r--r--doc/user/project/integrations/img/jira_service_page.pngbin47533 -> 74893 bytes
-rw-r--r--doc/user/project/integrations/jira.md235
-rw-r--r--doc/user/project/integrations/jira_cloud_configuration.md18
-rw-r--r--doc/user/project/integrations/jira_server_configuration.md53
-rw-r--r--doc/user/project/integrations/mattermost.md8
-rw-r--r--doc/user/project/integrations/mattermost_slash_commands.md2
-rw-r--r--doc/user/project/integrations/microsoft_teams.md2
-rw-r--r--doc/user/project/integrations/mock_ci.md2
-rw-r--r--doc/user/project/integrations/project_services.md1
-rw-r--r--doc/user/project/integrations/prometheus.md6
-rw-r--r--doc/user/project/integrations/prometheus_library/cloudwatch.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/haproxy.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/index.md33
-rw-r--r--doc/user/project/integrations/prometheus_library/metrics.md20
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx.md2
-rw-r--r--doc/user/project/integrations/prometheus_library/nginx_ingress.md6
-rw-r--r--doc/user/project/integrations/redmine.md7
-rw-r--r--doc/user/project/integrations/services_templates.md6
-rw-r--r--doc/user/project/integrations/webhooks.md31
-rw-r--r--doc/user/project/issue_board.md292
-rw-r--r--doc/user/project/issues/automatic_issue_closing.md9
-rw-r--r--doc/user/project/issues/create_new_issue.md18
-rw-r--r--doc/user/project/issues/img/issue_board.pngbin55931 -> 86095 bytes
-rw-r--r--doc/user/project/issues/issues_functionalities.md11
-rw-r--r--doc/user/project/koding.md131
-rw-r--r--doc/user/project/labels.md4
-rw-r--r--doc/user/project/merge_requests/cherry_pick_changes.md8
-rw-r--r--doc/user/project/merge_requests/img/comment-on-any-diff-line.pngbin0 -> 177323 bytes
-rw-r--r--doc/user/project/merge_requests/img/filter_wip_merge_requests.pngbin0 -> 17346 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_request_diff_file_navigation.pngbin112288 -> 68704 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_request_pipeline.pngbin0 -> 31046 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_request_widget.pngbin11036 -> 8936 bytes
-rw-r--r--doc/user/project/merge_requests/index.md94
-rw-r--r--doc/user/project/merge_requests/resolve_conflicts.md36
-rw-r--r--doc/user/project/merge_requests/revert_changes.md6
-rw-r--r--doc/user/project/merge_requests/work_in_progress_merge_requests.md11
-rw-r--r--doc/user/project/milestones/index.md23
-rw-r--r--doc/user/project/new_ci_build_permissions_model.md2
-rw-r--r--doc/user/project/pages/getting_started_part_three.md8
-rw-r--r--doc/user/project/pages/img/icons/click.pngbin0 -> 10148 bytes
-rw-r--r--doc/user/project/pages/img/icons/cogs.pngbin0 -> 9670 bytes
-rw-r--r--doc/user/project/pages/img/icons/fork.pngbin0 -> 9597 bytes
-rw-r--r--doc/user/project/pages/img/icons/free.pngbin0 -> 8689 bytes
-rw-r--r--doc/user/project/pages/img/icons/lock.pngbin0 -> 7892 bytes
-rw-r--r--doc/user/project/pages/img/icons/monitor.pngbin0 -> 5039 bytes
-rw-r--r--doc/user/project/pages/img/icons/terminal.pngbin0 -> 4972 bytes
-rw-r--r--doc/user/project/pages/img/ssgs_pages.pngbin0 -> 12010 bytes
-rw-r--r--doc/user/project/pages/index.md188
-rw-r--r--doc/user/project/pages/introduction.md42
-rw-r--r--doc/user/project/pipelines/job_artifacts.md14
-rw-r--r--doc/user/project/pipelines/schedules.md12
-rw-r--r--doc/user/project/quick_actions.md129
-rw-r--r--doc/user/project/repository/branches/img/branch_filter_search_box.pngbin0 -> 83225 bytes
-rw-r--r--doc/user/project/repository/branches/index.md23
-rw-r--r--doc/user/project/repository/gpg_signed_commits/index.md2
-rw-r--r--doc/user/project/repository/index.md57
-rw-r--r--doc/user/project/settings/img/sharing_and_permissions_settings.pngbin50602 -> 46275 bytes
-rw-r--r--doc/user/project/settings/index.md2
-rw-r--r--doc/user/project/web_ide/index.md21
-rw-r--r--doc/user/reserved_names.md1
-rw-r--r--doc/user/search/img/dashboard_links.pngbin0 -> 27164 bytes
-rw-r--r--doc/user/search/img/issues_assigned_to_you.pngbin49079 -> 50433 bytes
-rw-r--r--doc/user/search/img/issues_filter_none_any.pngbin0 -> 27717 bytes
-rw-r--r--doc/user/search/img/left_menu_bar.pngbin37433 -> 0 bytes
-rw-r--r--doc/user/search/index.md26
-rw-r--r--doc/workflow/img/repository_mirroring_force_update.pngbin0 -> 45730 bytes
-rw-r--r--doc/workflow/img/repository_mirroring_pull_settings_lower.pngbin0 -> 58056 bytes
-rw-r--r--doc/workflow/img/repository_mirroring_pull_settings_upper.pngbin0 -> 64118 bytes
-rw-r--r--doc/workflow/img/repository_mirroring_push_settings.pngbin0 -> 50526 bytes
-rw-r--r--doc/workflow/lfs/lfs_administration.md2
-rw-r--r--doc/workflow/lfs/manage_large_binaries_with_git_lfs.md4
-rw-r--r--doc/workflow/notifications.md47
-rw-r--r--doc/workflow/repository_mirroring.md558
-rw-r--r--doc/workflow/repository_mirroring/repository_mirroring_detect_host_keys.pngbin22952 -> 0 bytes
-rw-r--r--doc/workflow/repository_mirroring/repository_mirroring_diverged_branch.pngbin22668 -> 0 bytes
-rw-r--r--doc/workflow/repository_mirroring/repository_mirroring_diverged_branch_push.pngbin9509 -> 0 bytes
-rw-r--r--doc/workflow/repository_mirroring/repository_mirroring_github_edit_personal_access_token.pngbin20739 -> 0 bytes
-rw-r--r--doc/workflow/repository_mirroring/repository_mirroring_gitlab_push_to_a_remote_repository.pngbin16538 -> 0 bytes
-rw-r--r--doc/workflow/repository_mirroring/repository_mirroring_gitlab_push_to_a_remote_repository_update_now.pngbin16765 -> 0 bytes
-rw-r--r--doc/workflow/repository_mirroring/repository_mirroring_hard_failed_main.pngbin15555 -> 0 bytes
-rw-r--r--doc/workflow/repository_mirroring/repository_mirroring_hard_failed_settings.pngbin16414 -> 0 bytes
-rw-r--r--doc/workflow/repository_mirroring/repository_mirroring_new_project.pngbin20364 -> 0 bytes
-rw-r--r--doc/workflow/repository_mirroring/repository_mirroring_pull_advanced_host_keys.pngbin40414 -> 0 bytes
-rw-r--r--doc/workflow/repository_mirroring/repository_mirroring_pull_settings.pngbin39909 -> 0 bytes
-rw-r--r--doc/workflow/repository_mirroring/repository_mirroring_pull_settings_for_ssh.pngbin26234 -> 0 bytes
-rw-r--r--doc/workflow/repository_mirroring/repository_mirroring_push_settings.pngbin18226 -> 0 bytes
-rw-r--r--doc/workflow/repository_mirroring/repository_mirroring_ssh_host_keys_verified.pngbin9343 -> 0 bytes
-rw-r--r--doc/workflow/repository_mirroring/repository_mirroring_ssh_public_key_authentication.pngbin27440 -> 0 bytes
-rw-r--r--doc/workflow/shortcuts.md3
-rw-r--r--doc/workflow/time_tracking.md3
-rw-r--r--generator_templates/active_record/migration/create_table_migration.rb2
-rw-r--r--generator_templates/active_record/migration/migration.rb2
-rw-r--r--generator_templates/rails/post_deployment_migration/migration.rb2
-rw-r--r--lib/after_commit_queue.rb2
-rw-r--r--lib/api/access_requests.rb4
-rw-r--r--lib/api/api.rb12
-rw-r--r--lib/api/api_guard.rb8
-rw-r--r--lib/api/applications.rb18
-rw-r--r--lib/api/avatar.rb2
-rw-r--r--lib/api/award_emoji.rb4
-rw-r--r--lib/api/badges.rb4
-rw-r--r--lib/api/boards.rb4
-rw-r--r--lib/api/boards_responses.rb2
-rw-r--r--lib/api/branches.rb6
-rw-r--r--lib/api/broadcast_messages.rb2
-rw-r--r--lib/api/circuit_breakers.rb19
-rw-r--r--lib/api/commit_statuses.rb4
-rw-r--r--lib/api/commits.rb73
-rw-r--r--lib/api/custom_attributes_endpoints.rb2
-rw-r--r--lib/api/deploy_keys.rb4
-rw-r--r--lib/api/deployments.rb4
-rw-r--r--lib/api/discussions.rb4
-rw-r--r--lib/api/entities.rb92
-rw-r--r--lib/api/environments.rb4
-rw-r--r--lib/api/events.rb26
-rw-r--r--lib/api/features.rb4
-rw-r--r--lib/api/files.rb4
-rw-r--r--lib/api/group_boards.rb4
-rw-r--r--lib/api/group_milestones.rb4
-rw-r--r--lib/api/group_variables.rb4
-rw-r--r--lib/api/groups.rb18
-rw-r--r--lib/api/helpers.rb14
-rw-r--r--lib/api/helpers/badges_helpers.rb2
-rw-r--r--lib/api/helpers/common_helpers.rb2
-rw-r--r--lib/api/helpers/custom_attributes.rb2
-rw-r--r--lib/api/helpers/custom_validators.rb15
-rw-r--r--lib/api/helpers/headers_helpers.rb2
-rw-r--r--lib/api/helpers/internal_helpers.rb2
-rw-r--r--lib/api/helpers/members_helpers.rb2
-rw-r--r--lib/api/helpers/notes_helpers.rb2
-rw-r--r--lib/api/helpers/pagination.rb2
-rw-r--r--lib/api/helpers/project_snapshots_helpers.rb2
-rw-r--r--lib/api/helpers/projects_helpers.rb2
-rw-r--r--lib/api/helpers/related_resources_helpers.rb2
-rw-r--r--lib/api/helpers/runner.rb2
-rw-r--r--lib/api/internal.rb8
-rw-r--r--lib/api/issues.rb52
-rw-r--r--lib/api/job_artifacts.rb4
-rw-r--r--lib/api/jobs.rb6
-rw-r--r--lib/api/keys.rb2
-rw-r--r--lib/api/labels.rb4
-rw-r--r--lib/api/lint.rb2
-rw-r--r--lib/api/markdown.rb9
-rw-r--r--lib/api/members.rb4
-rw-r--r--lib/api/merge_request_diffs.rb4
-rw-r--r--lib/api/merge_requests.rb48
-rw-r--r--lib/api/milestone_responses.rb2
-rw-r--r--lib/api/namespaces.rb4
-rw-r--r--lib/api/notes.rb4
-rw-r--r--lib/api/notification_settings.rb4
-rw-r--r--lib/api/pages_domains.rb6
-rw-r--r--lib/api/pagination_params.rb2
-rw-r--r--lib/api/pipeline_schedules.rb4
-rw-r--r--lib/api/pipelines.rb19
-rw-r--r--lib/api/project_export.rb2
-rw-r--r--lib/api/project_hooks.rb4
-rw-r--r--lib/api/project_import.rb4
-rw-r--r--lib/api/project_milestones.rb4
-rw-r--r--lib/api/project_snapshots.rb2
-rw-r--r--lib/api/project_snippets.rb4
-rw-r--r--lib/api/project_templates.rb59
-rw-r--r--lib/api/projects.rb21
-rw-r--r--lib/api/projects_relation_builder.rb2
-rw-r--r--lib/api/protected_branches.rb6
-rw-r--r--lib/api/protected_tags.rb6
-rw-r--r--lib/api/repositories.rb13
-rw-r--r--lib/api/resource_label_events.rb2
-rw-r--r--lib/api/runner.rb5
-rw-r--r--lib/api/runners.rb37
-rw-r--r--lib/api/scope.rb2
-rw-r--r--lib/api/search.rb6
-rw-r--r--lib/api/services.rb13
-rw-r--r--lib/api/settings.rb11
-rw-r--r--lib/api/sidekiq_metrics.rb2
-rw-r--r--lib/api/snippets.rb5
-rw-r--r--lib/api/submodules.rb47
-rw-r--r--lib/api/subscriptions.rb4
-rw-r--r--lib/api/system_hooks.rb2
-rw-r--r--lib/api/tags.rb6
-rw-r--r--lib/api/templates.rb11
-rw-r--r--lib/api/time_tracking_endpoints.rb2
-rw-r--r--lib/api/todos.rb4
-rw-r--r--lib/api/triggers.rb4
-rw-r--r--lib/api/users.rb32
-rw-r--r--lib/api/validations/types/safe_file.rb15
-rw-r--r--lib/api/variables.rb4
-rw-r--r--lib/api/version.rb2
-rw-r--r--lib/api/wikis.rb10
-rw-r--r--lib/backup.rb2
-rw-r--r--lib/backup/artifacts.rb2
-rw-r--r--lib/backup/builds.rb2
-rw-r--r--lib/backup/database.rb2
-rw-r--r--lib/backup/files.rb2
-rw-r--r--lib/backup/helper.rb2
-rw-r--r--lib/backup/lfs.rb2
-rw-r--r--lib/backup/manager.rb5
-rw-r--r--lib/backup/pages.rb2
-rw-r--r--lib/backup/registry.rb2
-rw-r--r--lib/backup/repository.rb2
-rw-r--r--lib/backup/uploads.rb2
-rw-r--r--lib/banzai.rb9
-rw-r--r--lib/banzai/color_parser.rb2
-rw-r--r--lib/banzai/commit_renderer.rb2
-rw-r--r--lib/banzai/cross_project_reference.rb3
-rw-r--r--lib/banzai/filter.rb2
-rw-r--r--lib/banzai/filter/absolute_link_filter.rb1
-rw-r--r--lib/banzai/filter/abstract_reference_filter.rb4
-rw-r--r--lib/banzai/filter/epic_reference_filter.rb6
-rw-r--r--lib/banzai/filter/external_issue_reference_filter.rb4
-rw-r--r--lib/banzai/filter/issuable_state_filter.rb11
-rw-r--r--lib/banzai/filter/label_reference_filter.rb2
-rw-r--r--lib/banzai/filter/markdown_engines/common_mark.rb2
-rw-r--r--lib/banzai/filter/markdown_engines/redcarpet.rb2
-rw-r--r--lib/banzai/filter/relative_link_filter.rb6
-rw-r--r--lib/banzai/filter/spaced_link_filter.rb3
-rw-r--r--lib/banzai/filter/wiki_link_filter/rewriter.rb2
-rw-r--r--lib/banzai/filter_array.rb2
-rw-r--r--lib/banzai/issuable_extractor.rb43
-rw-r--r--lib/banzai/object_renderer.rb3
-rw-r--r--lib/banzai/pipeline.rb2
-rw-r--r--lib/banzai/pipeline/ascii_doc_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/atom_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/base_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/broadcast_message_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/combined_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/commit_description_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/description_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/email_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/full_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/gfm_pipeline.rb7
-rw-r--r--lib/banzai/pipeline/markup_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/note_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/plain_markdown_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/post_process_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/pre_process_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/relative_link_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/single_line_pipeline.rb2
-rw-r--r--lib/banzai/pipeline/wiki_pipeline.rb2
-rw-r--r--lib/banzai/querying.rb2
-rw-r--r--lib/banzai/redactor.rb10
-rw-r--r--lib/banzai/reference_extractor.rb2
-rw-r--r--lib/banzai/reference_parser.rb2
-rw-r--r--lib/banzai/reference_parser/base_parser.rb8
-rw-r--r--lib/banzai/reference_parser/commit_parser.rb2
-rw-r--r--lib/banzai/reference_parser/commit_range_parser.rb2
-rw-r--r--lib/banzai/reference_parser/directly_addressed_user_parser.rb2
-rw-r--r--lib/banzai/reference_parser/epic_parser.rb2
-rw-r--r--lib/banzai/reference_parser/external_issue_parser.rb2
-rw-r--r--lib/banzai/reference_parser/issuable_parser.rb2
-rw-r--r--lib/banzai/reference_parser/issue_parser.rb2
-rw-r--r--lib/banzai/reference_parser/label_parser.rb2
-rw-r--r--lib/banzai/reference_parser/merge_request_parser.rb2
-rw-r--r--lib/banzai/reference_parser/milestone_parser.rb2
-rw-r--r--lib/banzai/reference_parser/snippet_parser.rb2
-rw-r--r--lib/banzai/reference_parser/user_parser.rb2
-rw-r--r--lib/banzai/renderer.rb2
-rw-r--r--lib/banzai/renderer/common_mark/html.rb2
-rw-r--r--lib/banzai/renderer/redcarpet/html.rb2
-rw-r--r--lib/banzai/request_store_reference_cache.rb6
-rw-r--r--lib/bitbucket/client.rb2
-rw-r--r--lib/bitbucket/collection.rb2
-rw-r--r--lib/bitbucket/connection.rb2
-rw-r--r--lib/bitbucket/error/unauthorized.rb2
-rw-r--r--lib/bitbucket/page.rb2
-rw-r--r--lib/bitbucket/paginator.rb2
-rw-r--r--lib/bitbucket/representation/base.rb2
-rw-r--r--lib/bitbucket/representation/comment.rb2
-rw-r--r--lib/bitbucket/representation/issue.rb2
-rw-r--r--lib/bitbucket/representation/pull_request.rb2
-rw-r--r--lib/bitbucket/representation/pull_request_comment.rb2
-rw-r--r--lib/bitbucket/representation/repo.rb2
-rw-r--r--lib/bitbucket/representation/user.rb2
-rw-r--r--lib/bitbucket_server/client.rb8
-rw-r--r--lib/bitbucket_server/collection.rb24
-rw-r--r--lib/bitbucket_server/connection.rb22
-rw-r--r--lib/bitbucket_server/paginator.rb27
-rw-r--r--lib/carrier_wave_string_file.rb2
-rw-r--r--lib/constraints/feature_constrainer.rb2
-rw-r--r--lib/constraints/group_url_constrainer.rb2
-rw-r--r--lib/constraints/project_url_constrainer.rb2
-rw-r--r--lib/constraints/user_url_constrainer.rb2
-rw-r--r--lib/container_registry/blob.rb2
-rw-r--r--lib/container_registry/client.rb2
-rw-r--r--lib/container_registry/config.rb2
-rw-r--r--lib/container_registry/path.rb2
-rw-r--r--lib/container_registry/registry.rb2
-rw-r--r--lib/container_registry/tag.rb2
-rw-r--r--lib/declarative_policy.rb4
-rw-r--r--lib/declarative_policy/base.rb2
-rw-r--r--lib/declarative_policy/cache.rb2
-rw-r--r--lib/declarative_policy/condition.rb2
-rw-r--r--lib/declarative_policy/delegate_dsl.rb2
-rw-r--r--lib/declarative_policy/policy_dsl.rb2
-rw-r--r--lib/declarative_policy/preferred_scope.rb5
-rw-r--r--lib/declarative_policy/rule.rb2
-rw-r--r--lib/declarative_policy/rule_dsl.rb2
-rw-r--r--lib/declarative_policy/runner.rb2
-rw-r--r--lib/declarative_policy/step.rb2
-rw-r--r--lib/event_filter.rb86
-rw-r--r--lib/expand_variables.rb2
-rw-r--r--lib/extracts_path.rb19
-rw-r--r--lib/feature.rb12
-rw-r--r--lib/file_size_validator.rb2
-rw-r--r--lib/flowdock/git.rb67
-rw-r--r--lib/flowdock/git/builder.rb145
-rw-r--r--lib/forever.rb2
-rw-r--r--lib/generators/rails/post_deployment_migration/post_deployment_migration_generator.rb2
-rw-r--r--lib/gitaly/server.rb2
-rw-r--r--lib/gitlab.rb10
-rw-r--r--lib/gitlab/access.rb2
-rw-r--r--lib/gitlab/action_rate_limiter.rb2
-rw-r--r--lib/gitlab/allowable.rb2
-rw-r--r--lib/gitlab/app_logger.rb2
-rw-r--r--lib/gitlab/asciidoc.rb2
-rw-r--r--lib/gitlab/audit_json_logger.rb9
-rw-r--r--lib/gitlab/auth.rb6
-rw-r--r--lib/gitlab/auth/activity.rb2
-rw-r--r--lib/gitlab/auth/database/authentication.rb2
-rw-r--r--lib/gitlab/auth/ip_rate_limiter.rb2
-rw-r--r--lib/gitlab/auth/ldap/access.rb2
-rw-r--r--lib/gitlab/auth/ldap/adapter.rb2
-rw-r--r--lib/gitlab/auth/ldap/auth_hash.rb2
-rw-r--r--lib/gitlab/auth/ldap/authentication.rb2
-rw-r--r--lib/gitlab/auth/ldap/config.rb2
-rw-r--r--lib/gitlab/auth/ldap/dn.rb1
-rw-r--r--lib/gitlab/auth/ldap/ldap_connection_error.rb2
-rw-r--r--lib/gitlab/auth/ldap/person.rb2
-rw-r--r--lib/gitlab/auth/ldap/user.rb2
-rw-r--r--lib/gitlab/auth/o_auth/auth_hash.rb4
-rw-r--r--lib/gitlab/auth/o_auth/authentication.rb2
-rw-r--r--lib/gitlab/auth/o_auth/identity_linker.rb2
-rw-r--r--lib/gitlab/auth/o_auth/provider.rb2
-rw-r--r--lib/gitlab/auth/o_auth/session.rb2
-rw-r--r--lib/gitlab/auth/o_auth/user.rb2
-rw-r--r--lib/gitlab/auth/omniauth_identity_linker_base.rb2
-rw-r--r--lib/gitlab/auth/request_authenticator.rb16
-rw-r--r--lib/gitlab/auth/result.rb5
-rw-r--r--lib/gitlab/auth/saml/auth_hash.rb4
-rw-r--r--lib/gitlab/auth/saml/config.rb2
-rw-r--r--lib/gitlab/auth/saml/identity_linker.rb2
-rw-r--r--lib/gitlab/auth/saml/user.rb2
-rw-r--r--lib/gitlab/auth/too_many_ips.rb2
-rw-r--r--lib/gitlab/auth/unique_ips_limiter.rb2
-rw-r--r--lib/gitlab/auth/user_access_denied_reason.rb2
-rw-r--r--lib/gitlab/auth/user_auth_finders.rb48
-rw-r--r--lib/gitlab/background_migration.rb2
-rw-r--r--lib/gitlab/background_migration/backfill_project_fullpath_in_repo_config.rb209
-rw-r--r--lib/gitlab/background_migration/digest_column.rb25
-rw-r--r--lib/gitlab/background_migration/encrypt_columns.rb94
-rw-r--r--lib/gitlab/background_migration/models/encrypt_columns/web_hook.rb28
-rw-r--r--lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table.rb82
-rw-r--r--lib/gitlab/background_migration/populate_external_pipeline_source.rb50
-rw-r--r--lib/gitlab/background_migration/redact_links.rb51
-rw-r--r--lib/gitlab/background_migration/redact_links/redactable.rb21
-rw-r--r--lib/gitlab/background_migration/remove_restricted_todos.rb86
-rw-r--r--lib/gitlab/background_migration/set_confidential_note_events_on_services.rb4
-rw-r--r--lib/gitlab/background_migration/set_confidential_note_events_on_webhooks.rb4
-rw-r--r--lib/gitlab/badge/base.rb2
-rw-r--r--lib/gitlab/badge/coverage/metadata.rb2
-rw-r--r--lib/gitlab/badge/coverage/report.rb2
-rw-r--r--lib/gitlab/badge/coverage/template.rb2
-rw-r--r--lib/gitlab/badge/metadata.rb2
-rw-r--r--lib/gitlab/badge/pipeline/metadata.rb2
-rw-r--r--lib/gitlab/badge/pipeline/status.rb2
-rw-r--r--lib/gitlab/badge/pipeline/template.rb2
-rw-r--r--lib/gitlab/badge/template.rb2
-rw-r--r--lib/gitlab/bare_repository_import/importer.rb7
-rw-r--r--lib/gitlab/bare_repository_import/repository.rb7
-rw-r--r--lib/gitlab/base_doorkeeper_controller.rb2
-rw-r--r--lib/gitlab/bitbucket_import/importer.rb4
-rw-r--r--lib/gitlab/bitbucket_import/project_creator.rb2
-rw-r--r--lib/gitlab/bitbucket_server_import/importer.rb2
-rw-r--r--lib/gitlab/bitbucket_server_import/project_creator.rb2
-rw-r--r--lib/gitlab/blame.rb5
-rw-r--r--lib/gitlab/blob_helper.rb147
-rw-r--r--lib/gitlab/build_access.rb2
-rw-r--r--lib/gitlab/cache/ci/project_pipeline_status.rb48
-rw-r--r--lib/gitlab/cache/request_cache.rb6
-rw-r--r--lib/gitlab/changes_list.rb2
-rw-r--r--lib/gitlab/chat_name_token.rb2
-rw-r--r--lib/gitlab/checks/base_checker.rb38
-rw-r--r--lib/gitlab/checks/branch_check.rb110
-rw-r--r--lib/gitlab/checks/change_access.rb206
-rw-r--r--lib/gitlab/checks/commit_check.rb63
-rw-r--r--lib/gitlab/checks/diff_check.rb99
-rw-r--r--lib/gitlab/checks/force_push.rb2
-rw-r--r--lib/gitlab/checks/lfs_check.rb22
-rw-r--r--lib/gitlab/checks/lfs_integrity.rb7
-rw-r--r--lib/gitlab/checks/matching_merge_request.rb2
-rw-r--r--lib/gitlab/checks/post_push_message.rb2
-rw-r--r--lib/gitlab/checks/project_created.rb2
-rw-r--r--lib/gitlab/checks/project_moved.rb2
-rw-r--r--lib/gitlab/checks/push_check.rb22
-rw-r--r--lib/gitlab/checks/tag_check.rb46
-rw-r--r--lib/gitlab/checks/timed_logger.rb83
-rw-r--r--lib/gitlab/ci/ansi2html.rb4
-rw-r--r--lib/gitlab/ci/build/artifacts/adapters/gzip_stream.rb50
-rw-r--r--lib/gitlab/ci/build/artifacts/adapters/raw_stream.rb29
-rw-r--r--lib/gitlab/ci/build/artifacts/gzip_file_adapter.rb46
-rw-r--r--lib/gitlab/ci/build/artifacts/metadata.rb9
-rw-r--r--lib/gitlab/ci/build/artifacts/metadata/entry.rb2
-rw-r--r--lib/gitlab/ci/build/artifacts/path.rb2
-rw-r--r--lib/gitlab/ci/build/credentials/base.rb2
-rw-r--r--lib/gitlab/ci/build/credentials/factory.rb2
-rw-r--r--lib/gitlab/ci/build/credentials/registry.rb2
-rw-r--r--lib/gitlab/ci/build/image.rb2
-rw-r--r--lib/gitlab/ci/build/policy.rb2
-rw-r--r--lib/gitlab/ci/build/policy/changes.rb25
-rw-r--r--lib/gitlab/ci/build/policy/kubernetes.rb2
-rw-r--r--lib/gitlab/ci/build/policy/refs.rb2
-rw-r--r--lib/gitlab/ci/build/policy/specification.rb2
-rw-r--r--lib/gitlab/ci/build/policy/variables.rb2
-rw-r--r--lib/gitlab/ci/build/step.rb2
-rw-r--r--lib/gitlab/ci/charts.rb2
-rw-r--r--lib/gitlab/ci/config.rb12
-rw-r--r--lib/gitlab/ci/config/entry/artifacts.rb10
-rw-r--r--lib/gitlab/ci/config/entry/attributable.rb27
-rw-r--r--lib/gitlab/ci/config/entry/boolean.rb18
-rw-r--r--lib/gitlab/ci/config/entry/cache.rb10
-rw-r--r--lib/gitlab/ci/config/entry/commands.rb6
-rw-r--r--lib/gitlab/ci/config/entry/configurable.rb81
-rw-r--r--lib/gitlab/ci/config/entry/coverage.rb6
-rw-r--r--lib/gitlab/ci/config/entry/environment.rb6
-rw-r--r--lib/gitlab/ci/config/entry/factory.rb73
-rw-r--r--lib/gitlab/ci/config/entry/global.rb8
-rw-r--r--lib/gitlab/ci/config/entry/hidden.rb6
-rw-r--r--lib/gitlab/ci/config/entry/image.rb6
-rw-r--r--lib/gitlab/ci/config/entry/job.rb45
-rw-r--r--lib/gitlab/ci/config/entry/jobs.rb8
-rw-r--r--lib/gitlab/ci/config/entry/key.rb6
-rw-r--r--lib/gitlab/ci/config/entry/legacy_validation_helpers.rb61
-rw-r--r--lib/gitlab/ci/config/entry/node.rb101
-rw-r--r--lib/gitlab/ci/config/entry/paths.rb6
-rw-r--r--lib/gitlab/ci/config/entry/policy.rb22
-rw-r--r--lib/gitlab/ci/config/entry/reports.rb17
-rw-r--r--lib/gitlab/ci/config/entry/retry.rb92
-rw-r--r--lib/gitlab/ci/config/entry/script.rb6
-rw-r--r--lib/gitlab/ci/config/entry/service.rb4
-rw-r--r--lib/gitlab/ci/config/entry/services.rb8
-rw-r--r--lib/gitlab/ci/config/entry/simplifiable.rb43
-rw-r--r--lib/gitlab/ci/config/entry/stage.rb6
-rw-r--r--lib/gitlab/ci/config/entry/stages.rb6
-rw-r--r--lib/gitlab/ci/config/entry/undefined.rb40
-rw-r--r--lib/gitlab/ci/config/entry/unspecified.rb19
-rw-r--r--lib/gitlab/ci/config/entry/validatable.rb38
-rw-r--r--lib/gitlab/ci/config/entry/validator.rb26
-rw-r--r--lib/gitlab/ci/config/entry/validators.rb172
-rw-r--r--lib/gitlab/ci/config/entry/variables.rb6
-rw-r--r--lib/gitlab/ci/config/external/file/base.rb75
-rw-r--r--lib/gitlab/ci/config/external/file/local.rb42
-rw-r--r--lib/gitlab/ci/config/external/file/remote.rb49
-rw-r--r--lib/gitlab/ci/config/external/mapper.rb33
-rw-r--r--lib/gitlab/ci/config/external/processor.rb50
-rw-r--r--lib/gitlab/ci/config/loader.rb27
-rw-r--r--lib/gitlab/ci/config/normalizer.rb65
-rw-r--r--lib/gitlab/ci/cron_parser.rb2
-rw-r--r--lib/gitlab/ci/external/file/base.rb29
-rw-r--r--lib/gitlab/ci/external/file/local.rb34
-rw-r--r--lib/gitlab/ci/external/file/remote.rb30
-rw-r--r--lib/gitlab/ci/external/mapper.rb32
-rw-r--r--lib/gitlab/ci/external/processor.rb52
-rw-r--r--lib/gitlab/ci/mask_secret.rb4
-rw-r--r--lib/gitlab/ci/model.rb2
-rw-r--r--lib/gitlab/ci/parsers.rb9
-rw-r--r--lib/gitlab/ci/parsers/junit.rb66
-rw-r--r--lib/gitlab/ci/parsers/test.rb21
-rw-r--r--lib/gitlab/ci/parsers/test/junit.rb70
-rw-r--r--lib/gitlab/ci/pipeline/chain/base.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/build.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/command.rb5
-rw-r--r--lib/gitlab/ci/pipeline/chain/create.rb19
-rw-r--r--lib/gitlab/ci/pipeline/chain/helpers.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/populate.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/sequence.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/skip.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/validate/abilities.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/validate/config.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/validate/repository.rb2
-rw-r--r--lib/gitlab/ci/pipeline/duration.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/base.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/equals.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/matches.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/null.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/operator.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/string.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/value.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/variable.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexer.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression/parser.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression/statement.rb2
-rw-r--r--lib/gitlab/ci/pipeline/expression/token.rb2
-rw-r--r--lib/gitlab/ci/pipeline/seed/base.rb2
-rw-r--r--lib/gitlab/ci/pipeline/seed/build.rb2
-rw-r--r--lib/gitlab/ci/pipeline/seed/stage.rb2
-rw-r--r--lib/gitlab/ci/reports/test_case.rb2
-rw-r--r--lib/gitlab/ci/reports/test_reports.rb2
-rw-r--r--lib/gitlab/ci/reports/test_reports_comparer.rb2
-rw-r--r--lib/gitlab/ci/reports/test_suite.rb2
-rw-r--r--lib/gitlab/ci/reports/test_suite_comparer.rb2
-rw-r--r--lib/gitlab/ci/status/build/action.rb2
-rw-r--r--lib/gitlab/ci/status/build/cancelable.rb2
-rw-r--r--lib/gitlab/ci/status/build/canceled.rb2
-rw-r--r--lib/gitlab/ci/status/build/common.rb2
-rw-r--r--lib/gitlab/ci/status/build/created.rb2
-rw-r--r--lib/gitlab/ci/status/build/erased.rb2
-rw-r--r--lib/gitlab/ci/status/build/factory.rb4
-rw-r--r--lib/gitlab/ci/status/build/failed.rb7
-rw-r--r--lib/gitlab/ci/status/build/failed_allowed.rb2
-rw-r--r--lib/gitlab/ci/status/build/manual.rb2
-rw-r--r--lib/gitlab/ci/status/build/pending.rb2
-rw-r--r--lib/gitlab/ci/status/build/play.rb2
-rw-r--r--lib/gitlab/ci/status/build/retried.rb2
-rw-r--r--lib/gitlab/ci/status/build/retryable.rb2
-rw-r--r--lib/gitlab/ci/status/build/scheduled.rb31
-rw-r--r--lib/gitlab/ci/status/build/skipped.rb2
-rw-r--r--lib/gitlab/ci/status/build/stop.rb2
-rw-r--r--lib/gitlab/ci/status/build/unschedule.rb43
-rw-r--r--lib/gitlab/ci/status/canceled.rb2
-rw-r--r--lib/gitlab/ci/status/core.rb2
-rw-r--r--lib/gitlab/ci/status/created.rb2
-rw-r--r--lib/gitlab/ci/status/extended.rb2
-rw-r--r--lib/gitlab/ci/status/external/common.rb2
-rw-r--r--lib/gitlab/ci/status/external/factory.rb2
-rw-r--r--lib/gitlab/ci/status/factory.rb2
-rw-r--r--lib/gitlab/ci/status/failed.rb2
-rw-r--r--lib/gitlab/ci/status/group/common.rb2
-rw-r--r--lib/gitlab/ci/status/group/factory.rb2
-rw-r--r--lib/gitlab/ci/status/manual.rb2
-rw-r--r--lib/gitlab/ci/status/pending.rb2
-rw-r--r--lib/gitlab/ci/status/pipeline/blocked.rb2
-rw-r--r--lib/gitlab/ci/status/pipeline/common.rb2
-rw-r--r--lib/gitlab/ci/status/pipeline/delayed.rb23
-rw-r--r--lib/gitlab/ci/status/pipeline/factory.rb3
-rw-r--r--lib/gitlab/ci/status/running.rb2
-rw-r--r--lib/gitlab/ci/status/scheduled.rb25
-rw-r--r--lib/gitlab/ci/status/skipped.rb2
-rw-r--r--lib/gitlab/ci/status/stage/common.rb2
-rw-r--r--lib/gitlab/ci/status/stage/factory.rb2
-rw-r--r--lib/gitlab/ci/status/success.rb2
-rw-r--r--lib/gitlab/ci/status/success_warning.rb2
-rw-r--r--lib/gitlab/ci/templates/Android.gitlab-ci.yml45
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml901
-rw-r--r--lib/gitlab/ci/templates/Bash.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Bash.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/C++.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/C++.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Chef.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Chef.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Clojure.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Clojure.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Crystal.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Crystal.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Django.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Django.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Docker.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Docker.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Elixir.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Elixir.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Go.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Go.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Gradle.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Gradle.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Grails.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Grails.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Julia.gitlab-ci.yml76
-rw-r--r--lib/gitlab/ci/templates/LaTeX.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/LaTeX.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Laravel.gitlab-ci.yml85
-rw-r--r--lib/gitlab/ci/templates/Maven.gitlab-ci.yml102
-rw-r--r--lib/gitlab/ci/templates/Mono.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Mono.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Nodejs.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/OpenShift.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/OpenShift.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/PHP.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/PHP.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Packer.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Packer.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Pages/Brunch.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/Brunch.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Pages/Doxygen.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/Doxygen.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Pages/Gatsby.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/Gatsby.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/HTML.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Pages/Harp.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/Harp.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Pages/Hexo.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/Hexo.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/Hugo.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Pages/Hyde.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/Hyde.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Pages/JBake.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/JBake.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Pages/Jekyll.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/Jekyll.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml42
-rw-r--r--lib/gitlab/ci/templates/Pages/Lektor.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/Lektor.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Pages/Metalsmith.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/Metalsmith.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Pages/Middleman.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/Middleman.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Pages/Nanoc.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/Nanoc.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Pages/Octopress.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/Octopress.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Pages/Pelican.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/Pelican.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Python.gitlab-ci.yml51
-rw-r--r--lib/gitlab/ci/templates/Ruby.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Rust.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Rust.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Scala.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Scala.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/Swift.gitlab-ci.yml30
-rw-r--r--lib/gitlab/ci/templates/Terraform.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Terraform.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/templates/dotNET.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/dotNET.gitlab-ci.yml)0
-rw-r--r--lib/gitlab/ci/trace.rb65
-rw-r--r--lib/gitlab/ci/trace/chunked_io.rb44
-rw-r--r--lib/gitlab/ci/trace/section_parser.rb2
-rw-r--r--lib/gitlab/ci/trace/stream.rb16
-rw-r--r--lib/gitlab/ci/variables/collection.rb2
-rw-r--r--lib/gitlab/ci/variables/collection/item.rb4
-rw-r--r--lib/gitlab/ci/yaml_processor.rb11
-rw-r--r--lib/gitlab/ci_access.rb2
-rw-r--r--lib/gitlab/closing_issue_extractor.rb2
-rw-r--r--lib/gitlab/cluster/lifecycle_events.rb99
-rw-r--r--lib/gitlab/cluster/puma_worker_killer_initializer.rb36
-rw-r--r--lib/gitlab/color_schemes.rb2
-rw-r--r--lib/gitlab/config/entry/attributable.rb27
-rw-r--r--lib/gitlab/config/entry/boolean.rb18
-rw-r--r--lib/gitlab/config/entry/configurable.rb81
-rw-r--r--lib/gitlab/config/entry/factory.rb73
-rw-r--r--lib/gitlab/config/entry/legacy_validation_helpers.rb70
-rw-r--r--lib/gitlab/config/entry/node.rb101
-rw-r--r--lib/gitlab/config/entry/simplifiable.rb43
-rw-r--r--lib/gitlab/config/entry/undefined.rb40
-rw-r--r--lib/gitlab/config/entry/unspecified.rb19
-rw-r--r--lib/gitlab/config/entry/validatable.rb38
-rw-r--r--lib/gitlab/config/entry/validator.rb26
-rw-r--r--lib/gitlab/config/entry/validators.rb196
-rw-r--r--lib/gitlab/config/loader/format_error.rb9
-rw-r--r--lib/gitlab/config/loader/yaml.rb27
-rw-r--r--lib/gitlab/config_helper.rb2
-rw-r--r--lib/gitlab/conflict/file.rb39
-rw-r--r--lib/gitlab/conflict/file_collection.rb2
-rw-r--r--lib/gitlab/contributions_calendar.rb4
-rw-r--r--lib/gitlab/contributor.rb2
-rw-r--r--lib/gitlab/cross_project_access.rb2
-rw-r--r--lib/gitlab/cross_project_access/check_collection.rb2
-rw-r--r--lib/gitlab/cross_project_access/check_info.rb2
-rw-r--r--lib/gitlab/cross_project_access/class_methods.rb2
-rw-r--r--lib/gitlab/crypto_helper.rb30
-rw-r--r--lib/gitlab/current_settings.rb8
-rw-r--r--lib/gitlab/cycle_analytics/base_event_fetcher.rb2
-rw-r--r--lib/gitlab/cycle_analytics/base_query.rb2
-rw-r--r--lib/gitlab/cycle_analytics/base_stage.rb2
-rw-r--r--lib/gitlab/cycle_analytics/code_event_fetcher.rb2
-rw-r--r--lib/gitlab/cycle_analytics/code_stage.rb2
-rw-r--r--lib/gitlab/cycle_analytics/event_fetcher.rb2
-rw-r--r--lib/gitlab/cycle_analytics/issue_event_fetcher.rb2
-rw-r--r--lib/gitlab/cycle_analytics/issue_stage.rb2
-rw-r--r--lib/gitlab/cycle_analytics/metrics_tables.rb2
-rw-r--r--lib/gitlab/cycle_analytics/permissions.rb2
-rw-r--r--lib/gitlab/cycle_analytics/plan_event_fetcher.rb2
-rw-r--r--lib/gitlab/cycle_analytics/plan_stage.rb2
-rw-r--r--lib/gitlab/cycle_analytics/production_event_fetcher.rb2
-rw-r--r--lib/gitlab/cycle_analytics/production_helper.rb2
-rw-r--r--lib/gitlab/cycle_analytics/production_stage.rb2
-rw-r--r--lib/gitlab/cycle_analytics/review_event_fetcher.rb2
-rw-r--r--lib/gitlab/cycle_analytics/review_stage.rb2
-rw-r--r--lib/gitlab/cycle_analytics/stage.rb2
-rw-r--r--lib/gitlab/cycle_analytics/stage_summary.rb2
-rw-r--r--lib/gitlab/cycle_analytics/staging_event_fetcher.rb2
-rw-r--r--lib/gitlab/cycle_analytics/staging_stage.rb2
-rw-r--r--lib/gitlab/cycle_analytics/summary/base.rb2
-rw-r--r--lib/gitlab/cycle_analytics/summary/commit.rb2
-rw-r--r--lib/gitlab/cycle_analytics/summary/deploy.rb2
-rw-r--r--lib/gitlab/cycle_analytics/summary/issue.rb2
-rw-r--r--lib/gitlab/cycle_analytics/test_event_fetcher.rb2
-rw-r--r--lib/gitlab/cycle_analytics/test_stage.rb2
-rw-r--r--lib/gitlab/cycle_analytics/updater.rb2
-rw-r--r--lib/gitlab/cycle_analytics/usage_data.rb2
-rw-r--r--lib/gitlab/daemon.rb2
-rw-r--r--lib/gitlab/data_builder/build.rb2
-rw-r--r--lib/gitlab/data_builder/note.rb2
-rw-r--r--lib/gitlab/data_builder/pipeline.rb5
-rw-r--r--lib/gitlab/data_builder/push.rb2
-rw-r--r--lib/gitlab/data_builder/repository.rb2
-rw-r--r--lib/gitlab/data_builder/wiki_page.rb2
-rw-r--r--lib/gitlab/database.rb23
-rw-r--r--lib/gitlab/database/arel_methods.rb2
-rw-r--r--lib/gitlab/database/count.rb81
-rw-r--r--lib/gitlab/database/count/exact_count_strategy.rb31
-rw-r--r--lib/gitlab/database/count/reltuples_count_strategy.rb79
-rw-r--r--lib/gitlab/database/count/tablesample_count_strategy.rb66
-rw-r--r--lib/gitlab/database/date_time.rb2
-rw-r--r--lib/gitlab/database/grant.rb2
-rw-r--r--lib/gitlab/database/median.rb2
-rw-r--r--lib/gitlab/database/migration_helpers.rb10
-rw-r--r--lib/gitlab/database/multi_threaded_migration.rb2
-rw-r--r--lib/gitlab/database/read_only_relation.rb2
-rw-r--r--lib/gitlab/database/rename_reserved_paths_migration/v1.rb2
-rw-r--r--lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb2
-rw-r--r--lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb2
-rw-r--r--lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb2
-rw-r--r--lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects.rb2
-rw-r--r--lib/gitlab/database/sha_attribute.rb2
-rw-r--r--lib/gitlab/database/subquery.rb10
-rw-r--r--lib/gitlab/dependency_linker.rb2
-rw-r--r--lib/gitlab/dependency_linker/base_linker.rb2
-rw-r--r--lib/gitlab/dependency_linker/cartfile_linker.rb2
-rw-r--r--lib/gitlab/dependency_linker/cocoapods.rb2
-rw-r--r--lib/gitlab/dependency_linker/composer_json_linker.rb2
-rw-r--r--lib/gitlab/dependency_linker/gemfile_linker.rb2
-rw-r--r--lib/gitlab/dependency_linker/gemspec_linker.rb2
-rw-r--r--lib/gitlab/dependency_linker/godeps_json_linker.rb2
-rw-r--r--lib/gitlab/dependency_linker/json_linker.rb2
-rw-r--r--lib/gitlab/dependency_linker/method_linker.rb2
-rw-r--r--lib/gitlab/dependency_linker/package_json_linker.rb2
-rw-r--r--lib/gitlab/dependency_linker/podfile_linker.rb2
-rw-r--r--lib/gitlab/dependency_linker/podspec_json_linker.rb2
-rw-r--r--lib/gitlab/dependency_linker/podspec_linker.rb2
-rw-r--r--lib/gitlab/dependency_linker/requirements_txt_linker.rb2
-rw-r--r--lib/gitlab/diff/diff_refs.rb4
-rw-r--r--lib/gitlab/diff/file.rb21
-rw-r--r--lib/gitlab/diff/file_collection/base.rb9
-rw-r--r--lib/gitlab/diff/file_collection/commit.rb2
-rw-r--r--lib/gitlab/diff/file_collection/compare.rb2
-rw-r--r--lib/gitlab/diff/file_collection/merge_request_diff.rb2
-rw-r--r--lib/gitlab/diff/formatters/base_formatter.rb2
-rw-r--r--lib/gitlab/diff/formatters/image_formatter.rb2
-rw-r--r--lib/gitlab/diff/formatters/text_formatter.rb2
-rw-r--r--lib/gitlab/diff/highlight.rb6
-rw-r--r--lib/gitlab/diff/image_point.rb2
-rw-r--r--lib/gitlab/diff/inline_diff.rb4
-rw-r--r--lib/gitlab/diff/inline_diff_markdown_marker.rb2
-rw-r--r--lib/gitlab/diff/inline_diff_marker.rb2
-rw-r--r--lib/gitlab/diff/line.rb15
-rw-r--r--lib/gitlab/diff/line_mapper.rb2
-rw-r--r--lib/gitlab/diff/lines_unfolder.rb235
-rw-r--r--lib/gitlab/diff/parallel_diff.rb2
-rw-r--r--lib/gitlab/diff/parser.rb2
-rw-r--r--lib/gitlab/diff/position.rb38
-rw-r--r--lib/gitlab/diff/position_tracer.rb4
-rw-r--r--lib/gitlab/downtime_check.rb2
-rw-r--r--lib/gitlab/downtime_check/message.rb8
-rw-r--r--lib/gitlab/ee_compat_check.rb12
-rw-r--r--lib/gitlab/email/attachment_uploader.rb2
-rw-r--r--lib/gitlab/email/handler/create_merge_request_handler.rb50
-rw-r--r--lib/gitlab/email/hook/additional_headers_interceptor.rb2
-rw-r--r--lib/gitlab/email/hook/delivery_metrics_observer.rb2
-rw-r--r--lib/gitlab/email/hook/disable_email_interceptor.rb2
-rw-r--r--lib/gitlab/email/hook/email_template_interceptor.rb2
-rw-r--r--lib/gitlab/email/html_parser.rb2
-rw-r--r--lib/gitlab/email/message/repository_push.rb6
-rw-r--r--lib/gitlab/email/receiver.rb3
-rw-r--r--lib/gitlab/email/reply_parser.rb2
-rw-r--r--lib/gitlab/emoji.rb2
-rw-r--r--lib/gitlab/encoding_helper.rb2
-rw-r--r--lib/gitlab/environment.rb2
-rw-r--r--lib/gitlab/environment_logger.rb2
-rw-r--r--lib/gitlab/etag_caching/middleware.rb2
-rw-r--r--lib/gitlab/etag_caching/router.rb2
-rw-r--r--lib/gitlab/etag_caching/store.rb2
-rw-r--r--lib/gitlab/exclusive_lease.rb2
-rw-r--r--lib/gitlab/exclusive_lease_helpers.rb4
-rw-r--r--lib/gitlab/fake_application_settings.rb2
-rw-r--r--lib/gitlab/favicon.rb4
-rw-r--r--lib/gitlab/file_detector.rb5
-rw-r--r--lib/gitlab/file_finder.rb2
-rw-r--r--lib/gitlab/file_markdown_link_builder.rb4
-rw-r--r--lib/gitlab/fogbugz_import/client.rb2
-rw-r--r--lib/gitlab/fogbugz_import/importer.rb2
-rw-r--r--lib/gitlab/fogbugz_import/project_creator.rb2
-rw-r--r--lib/gitlab/fogbugz_import/repository.rb2
-rw-r--r--lib/gitlab/gfm/reference_rewriter.rb24
-rw-r--r--lib/gitlab/gfm/uploads_rewriter.rb9
-rw-r--r--lib/gitlab/git.rb2
-rw-r--r--lib/gitlab/git/attributes_at_ref_parser.rb2
-rw-r--r--lib/gitlab/git/attributes_parser.rb2
-rw-r--r--lib/gitlab/git/blame.rb2
-rw-r--r--lib/gitlab/git/blob.rb13
-rw-r--r--lib/gitlab/git/blob_snippet.rb34
-rw-r--r--lib/gitlab/git/branch.rb2
-rw-r--r--lib/gitlab/git/commit.rb51
-rw-r--r--lib/gitlab/git/commit_stats.rb6
-rw-r--r--lib/gitlab/git/compare.rb2
-rw-r--r--lib/gitlab/git/conflict/file.rb2
-rw-r--r--lib/gitlab/git/conflict/parser.rb2
-rw-r--r--lib/gitlab/git/conflict/resolution.rb2
-rw-r--r--lib/gitlab/git/conflict/resolver.rb8
-rw-r--r--lib/gitlab/git/diff.rb66
-rw-r--r--lib/gitlab/git/diff_collection.rb4
-rw-r--r--lib/gitlab/git/diff_stats_collection.rb4
-rw-r--r--lib/gitlab/git/gitmodules_parser.rb2
-rw-r--r--lib/gitlab/git/hook_env.rb12
-rw-r--r--lib/gitlab/git/index.rb2
-rw-r--r--lib/gitlab/git/lfs_changes.rb6
-rw-r--r--lib/gitlab/git/lfs_pointer_file.rb2
-rw-r--r--lib/gitlab/git/operation_service.rb2
-rw-r--r--lib/gitlab/git/patches/collection.rb33
-rw-r--r--lib/gitlab/git/patches/commit_patches.rb31
-rw-r--r--lib/gitlab/git/patches/patch.rb19
-rw-r--r--lib/gitlab/git/path_helper.rb2
-rw-r--r--lib/gitlab/git/pre_receive_error.rb2
-rw-r--r--lib/gitlab/git/push.rb56
-rw-r--r--lib/gitlab/git/raw_diff_change.rb2
-rw-r--r--lib/gitlab/git/ref.rb9
-rw-r--r--lib/gitlab/git/remote_mirror.rb22
-rw-r--r--lib/gitlab/git/remote_repository.rb2
-rw-r--r--lib/gitlab/git/repository.rb134
-rw-r--r--lib/gitlab/git/repository_mirroring.rb2
-rw-r--r--lib/gitlab/git/storage.rb25
-rw-r--r--lib/gitlab/git/storage/checker.rb120
-rw-r--r--lib/gitlab/git/storage/circuit_breaker.rb78
-rw-r--r--lib/gitlab/git/storage/circuit_breaker_settings.rb37
-rw-r--r--lib/gitlab/git/storage/failure_info.rb39
-rw-r--r--lib/gitlab/git/storage/forked_storage_check.rb65
-rw-r--r--lib/gitlab/git/storage/health.rb92
-rw-r--r--lib/gitlab/git/storage/null_circuit_breaker.rb50
-rw-r--r--lib/gitlab/git/tag.rb16
-rw-r--r--lib/gitlab/git/tree.rb5
-rw-r--r--lib/gitlab/git/user.rb2
-rw-r--r--lib/gitlab/git/util.rb2
-rw-r--r--lib/gitlab/git/version.rb2
-rw-r--r--lib/gitlab/git/wiki.rb96
-rw-r--r--lib/gitlab/git/wiki_file.rb19
-rw-r--r--lib/gitlab/git/wiki_page.rb30
-rw-r--r--lib/gitlab/git/wiki_page_version.rb7
-rw-r--r--lib/gitlab/git/wraps_gitaly_errors.rb17
-rw-r--r--lib/gitlab/git_access.rb28
-rw-r--r--lib/gitlab/git_access_wiki.rb2
-rw-r--r--lib/gitlab/git_logger.rb2
-rw-r--r--lib/gitlab/git_post_receive.rb4
-rw-r--r--lib/gitlab/git_ref_validator.rb8
-rw-r--r--lib/gitlab/gitaly_client.rb200
-rw-r--r--lib/gitlab/gitaly_client/attributes_bag.rb2
-rw-r--r--lib/gitlab/gitaly_client/blob_service.rb23
-rw-r--r--lib/gitlab/gitaly_client/blobs_stitcher.rb2
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb47
-rw-r--r--lib/gitlab/gitaly_client/conflict_files_stitcher.rb4
-rw-r--r--lib/gitlab/gitaly_client/conflicts_service.rb2
-rw-r--r--lib/gitlab/gitaly_client/diff.rb2
-rw-r--r--lib/gitlab/gitaly_client/diff_stitcher.rb4
-rw-r--r--lib/gitlab/gitaly_client/health_check_service.rb2
-rw-r--r--lib/gitlab/gitaly_client/namespace_service.rb2
-rw-r--r--lib/gitlab/gitaly_client/notification_service.rb2
-rw-r--r--lib/gitlab/gitaly_client/operation_service.rb55
-rw-r--r--lib/gitlab/gitaly_client/queue_enumerator.rb2
-rw-r--r--lib/gitlab/gitaly_client/ref_service.rb4
-rw-r--r--lib/gitlab/gitaly_client/remote_service.rb11
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb21
-rw-r--r--lib/gitlab/gitaly_client/server_service.rb2
-rw-r--r--lib/gitlab/gitaly_client/storage_service.rb2
-rw-r--r--lib/gitlab/gitaly_client/storage_settings.rb2
-rw-r--r--lib/gitlab/gitaly_client/util.rb2
-rw-r--r--lib/gitlab/gitaly_client/wiki_file.rb2
-rw-r--r--lib/gitlab/gitaly_client/wiki_page.rb2
-rw-r--r--lib/gitlab/gitaly_client/wiki_service.rb8
-rw-r--r--lib/gitlab/github_import.rb2
-rw-r--r--lib/gitlab/github_import/importer/repository_importer.rb2
-rw-r--r--lib/gitlab/github_import/parallel_importer.rb3
-rw-r--r--lib/gitlab/gitlab_import/client.rb2
-rw-r--r--lib/gitlab/gitlab_import/importer.rb12
-rw-r--r--lib/gitlab/gitlab_import/project_creator.rb2
-rw-r--r--lib/gitlab/gl_id.rb2
-rw-r--r--lib/gitlab/gl_repository.rb2
-rw-r--r--lib/gitlab/gon_helper.rb22
-rw-r--r--lib/gitlab/google_code_import/client.rb2
-rw-r--r--lib/gitlab/google_code_import/importer.rb4
-rw-r--r--lib/gitlab/google_code_import/project_creator.rb2
-rw-r--r--lib/gitlab/google_code_import/repository.rb2
-rw-r--r--lib/gitlab/gpg.rb2
-rw-r--r--lib/gitlab/gpg/commit.rb2
-rw-r--r--lib/gitlab/gpg/invalid_gpg_signature_updater.rb2
-rw-r--r--lib/gitlab/grape_logging/formatters/lograge_with_timestamp.rb12
-rw-r--r--lib/gitlab/grape_logging/loggers/queue_duration_logger.rb2
-rw-r--r--lib/gitlab/grape_logging/loggers/user_logger.rb2
-rw-r--r--lib/gitlab/graphql.rb2
-rw-r--r--lib/gitlab/graphql/authorize.rb2
-rw-r--r--lib/gitlab/graphql/authorize/authorize_resource.rb2
-rw-r--r--lib/gitlab/graphql/authorize/instrumentation.rb2
-rw-r--r--lib/gitlab/graphql/connections.rb2
-rw-r--r--lib/gitlab/graphql/connections/keyset_connection.rb2
-rw-r--r--lib/gitlab/graphql/errors.rb2
-rw-r--r--lib/gitlab/graphql/expose_permissions.rb2
-rw-r--r--lib/gitlab/graphql/loaders/batch_model_loader.rb29
-rw-r--r--lib/gitlab/graphql/present.rb2
-rw-r--r--lib/gitlab/graphql/present/instrumentation.rb2
-rw-r--r--lib/gitlab/graphql/variables.rb2
-rw-r--r--lib/gitlab/graphs/commits.rb2
-rw-r--r--lib/gitlab/group_hierarchy.rb2
-rw-r--r--lib/gitlab/hashed_storage/migrator.rb2
-rw-r--r--lib/gitlab/hashed_storage/rake_helper.rb2
-rw-r--r--lib/gitlab/health_checks/base_abstract_check.rb2
-rw-r--r--lib/gitlab/health_checks/db_check.rb2
-rw-r--r--lib/gitlab/health_checks/gitaly_check.rb2
-rw-r--r--lib/gitlab/health_checks/metric.rb5
-rw-r--r--lib/gitlab/health_checks/prometheus_text_format.rb2
-rw-r--r--lib/gitlab/health_checks/redis/cache_check.rb2
-rw-r--r--lib/gitlab/health_checks/redis/queues_check.rb2
-rw-r--r--lib/gitlab/health_checks/redis/redis_check.rb2
-rw-r--r--lib/gitlab/health_checks/redis/shared_state_check.rb2
-rw-r--r--lib/gitlab/health_checks/result.rb5
-rw-r--r--lib/gitlab/health_checks/simple_abstract_check.rb2
-rw-r--r--lib/gitlab/highlight.rb33
-rw-r--r--lib/gitlab/hook_data/base_builder.rb13
-rw-r--r--lib/gitlab/hook_data/issuable_builder.rb2
-rw-r--r--lib/gitlab/hook_data/issue_builder.rb2
-rw-r--r--lib/gitlab/hook_data/merge_request_builder.rb2
-rw-r--r--lib/gitlab/hook_data/note_builder.rb2
-rw-r--r--lib/gitlab/hook_data/wiki_page_builder.rb2
-rw-r--r--lib/gitlab/http.rb9
-rw-r--r--lib/gitlab/http_io.rb35
-rw-r--r--lib/gitlab/i18n.rb2
-rw-r--r--lib/gitlab/i18n/metadata_entry.rb2
-rw-r--r--lib/gitlab/i18n/po_linter.rb4
-rw-r--r--lib/gitlab/i18n/translation_entry.rb2
-rw-r--r--lib/gitlab/identifier.rb23
-rw-r--r--lib/gitlab/import/logger.rb2
-rw-r--r--lib/gitlab/import/merge_request_creator.rb8
-rw-r--r--lib/gitlab/import/merge_request_helpers.rb2
-rw-r--r--lib/gitlab/import_export.rb2
-rw-r--r--lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb2
-rw-r--r--lib/gitlab/import_export/after_export_strategies/download_notification_strategy.rb2
-rw-r--r--lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb2
-rw-r--r--lib/gitlab/import_export/after_export_strategy_builder.rb2
-rw-r--r--lib/gitlab/import_export/attribute_cleaner.rb2
-rw-r--r--lib/gitlab/import_export/attributes_finder.rb2
-rw-r--r--lib/gitlab/import_export/avatar_restorer.rb2
-rw-r--r--lib/gitlab/import_export/avatar_saver.rb2
-rw-r--r--lib/gitlab/import_export/command_line_util.rb2
-rw-r--r--lib/gitlab/import_export/error.rb2
-rw-r--r--lib/gitlab/import_export/file_importer.rb2
-rw-r--r--lib/gitlab/import_export/group_project_object_builder.rb2
-rw-r--r--lib/gitlab/import_export/hash_util.rb2
-rw-r--r--lib/gitlab/import_export/import_export.yml14
-rw-r--r--lib/gitlab/import_export/importer.rb2
-rw-r--r--lib/gitlab/import_export/json_hash_builder.rb2
-rw-r--r--lib/gitlab/import_export/lfs_restorer.rb2
-rw-r--r--lib/gitlab/import_export/lfs_saver.rb2
-rw-r--r--lib/gitlab/import_export/members_mapper.rb2
-rw-r--r--lib/gitlab/import_export/merge_request_parser.rb2
-rw-r--r--lib/gitlab/import_export/project_tree_restorer.rb19
-rw-r--r--lib/gitlab/import_export/project_tree_saver.rb2
-rw-r--r--lib/gitlab/import_export/reader.rb2
-rw-r--r--lib/gitlab/import_export/relation_factory.rb7
-rw-r--r--lib/gitlab/import_export/repo_restorer.rb2
-rw-r--r--lib/gitlab/import_export/repo_saver.rb2
-rw-r--r--lib/gitlab/import_export/saver.rb2
-rw-r--r--lib/gitlab/import_export/shared.rb2
-rw-r--r--lib/gitlab/import_export/statistics_restorer.rb2
-rw-r--r--lib/gitlab/import_export/uploads_manager.rb2
-rw-r--r--lib/gitlab/import_export/uploads_restorer.rb2
-rw-r--r--lib/gitlab/import_export/uploads_saver.rb2
-rw-r--r--lib/gitlab/import_export/version_checker.rb2
-rw-r--r--lib/gitlab/import_export/version_saver.rb2
-rw-r--r--lib/gitlab/import_export/wiki_repo_saver.rb2
-rw-r--r--lib/gitlab/import_export/wiki_restorer.rb2
-rw-r--r--lib/gitlab/import_formatter.rb2
-rw-r--r--lib/gitlab/import_sources.rb2
-rw-r--r--lib/gitlab/incoming_email.rb2
-rw-r--r--lib/gitlab/insecure_key_fingerprint.rb2
-rw-r--r--lib/gitlab/issuable_metadata.rb2
-rw-r--r--lib/gitlab/issuable_sorter.rb2
-rw-r--r--lib/gitlab/issuables_count_for_state.rb11
-rw-r--r--lib/gitlab/issues_labels.rb2
-rw-r--r--lib/gitlab/job_waiter.rb2
-rw-r--r--lib/gitlab/json_logger.rb2
-rw-r--r--lib/gitlab/kubernetes.rb2
-rw-r--r--lib/gitlab/kubernetes/config_map.rb2
-rw-r--r--lib/gitlab/kubernetes/helm.rb5
-rw-r--r--lib/gitlab/kubernetes/helm/api.rb56
-rw-r--r--lib/gitlab/kubernetes/helm/base_command.rb10
-rw-r--r--lib/gitlab/kubernetes/helm/client_command.rb28
-rw-r--r--lib/gitlab/kubernetes/helm/init_command.rb4
-rw-r--r--lib/gitlab/kubernetes/helm/install_command.rb47
-rw-r--r--lib/gitlab/kubernetes/helm/pod.rb4
-rw-r--r--lib/gitlab/kubernetes/helm/upgrade_command.rb65
-rw-r--r--lib/gitlab/kubernetes/kube_client.rb71
-rw-r--r--lib/gitlab/kubernetes/logger.rb11
-rw-r--r--lib/gitlab/kubernetes/namespace.rb6
-rw-r--r--lib/gitlab/kubernetes/pod.rb2
-rw-r--r--lib/gitlab/kubernetes/role_binding.rb48
-rw-r--r--lib/gitlab/language_data.rb33
-rw-r--r--lib/gitlab/language_detection.rb2
-rw-r--r--lib/gitlab/lazy.rb2
-rw-r--r--lib/gitlab/legacy_github_import/base_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/branch_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/client.rb2
-rw-r--r--lib/gitlab/legacy_github_import/comment_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/importer.rb5
-rw-r--r--lib/gitlab/legacy_github_import/issuable_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/issue_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/label_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/milestone_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/project_creator.rb2
-rw-r--r--lib/gitlab/legacy_github_import/pull_request_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/release_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/user_formatter.rb2
-rw-r--r--lib/gitlab/legacy_github_import/wiki_formatter.rb2
-rw-r--r--lib/gitlab/lfs_token.rb2
-rw-r--r--lib/gitlab/logger.rb4
-rw-r--r--lib/gitlab/mail_room.rb2
-rw-r--r--lib/gitlab/manifest_import/manifest.rb4
-rw-r--r--lib/gitlab/manifest_import/project_creator.rb2
-rw-r--r--lib/gitlab/markup_helper.rb15
-rw-r--r--lib/gitlab/metrics.rb2
-rw-r--r--lib/gitlab/metrics/background_transaction.rb2
-rw-r--r--lib/gitlab/metrics/delta.rb2
-rw-r--r--lib/gitlab/metrics/influx_db.rb4
-rw-r--r--lib/gitlab/metrics/instrumentation.rb2
-rw-r--r--lib/gitlab/metrics/method_call.rb2
-rw-r--r--lib/gitlab/metrics/methods.rb2
-rw-r--r--lib/gitlab/metrics/methods/metric_options.rb2
-rw-r--r--lib/gitlab/metrics/metric.rb2
-rw-r--r--lib/gitlab/metrics/null_metric.rb2
-rw-r--r--lib/gitlab/metrics/prometheus.rb2
-rw-r--r--lib/gitlab/metrics/rack_middleware.rb2
-rw-r--r--lib/gitlab/metrics/requests_rack_middleware.rb2
-rw-r--r--lib/gitlab/metrics/samplers/base_sampler.rb2
-rw-r--r--lib/gitlab/metrics/samplers/influx_sampler.rb2
-rw-r--r--lib/gitlab/metrics/samplers/ruby_sampler.rb2
-rw-r--r--lib/gitlab/metrics/samplers/unicorn_sampler.rb2
-rw-r--r--lib/gitlab/metrics/sidekiq_metrics_exporter.rb2
-rw-r--r--lib/gitlab/metrics/sidekiq_middleware.rb2
-rw-r--r--lib/gitlab/metrics/subscribers/action_view.rb2
-rw-r--r--lib/gitlab/metrics/subscribers/active_record.rb2
-rw-r--r--lib/gitlab/metrics/subscribers/rails_cache.rb2
-rw-r--r--lib/gitlab/metrics/system.rb2
-rw-r--r--lib/gitlab/metrics/transaction.rb2
-rw-r--r--lib/gitlab/metrics/web_transaction.rb4
-rw-r--r--lib/gitlab/middleware/go.rb4
-rw-r--r--lib/gitlab/middleware/multipart.rb2
-rw-r--r--lib/gitlab/middleware/rails_queue_duration.rb2
-rw-r--r--lib/gitlab/middleware/read_only.rb2
-rw-r--r--lib/gitlab/middleware/read_only/controller.rb2
-rw-r--r--lib/gitlab/middleware/release_env.rb5
-rw-r--r--lib/gitlab/middleware/static.rb2
-rw-r--r--lib/gitlab/multi_collection_paginator.rb2
-rw-r--r--lib/gitlab/namespace_sanitizer.rb9
-rw-r--r--lib/gitlab/null_request_store.rb41
-rw-r--r--lib/gitlab/omniauth_initializer.rb2
-rw-r--r--lib/gitlab/optimistic_locking.rb2
-rw-r--r--lib/gitlab/other_markup.rb2
-rw-r--r--lib/gitlab/otp_key_rotator.rb2
-rw-r--r--lib/gitlab/pages.rb2
-rw-r--r--lib/gitlab/pages_client.rb2
-rw-r--r--lib/gitlab/pages_transfer.rb2
-rw-r--r--lib/gitlab/patch/draw_route.rb38
-rw-r--r--lib/gitlab/path_regex.rb5
-rw-r--r--lib/gitlab/performance_bar.rb2
-rw-r--r--lib/gitlab/performance_bar/peek_query_tracker.rb4
-rw-r--r--lib/gitlab/plugin.rb2
-rw-r--r--lib/gitlab/plugin_logger.rb2
-rw-r--r--lib/gitlab/polling_interval.rb2
-rw-r--r--lib/gitlab/popen.rb4
-rw-r--r--lib/gitlab/popen/runner.rb2
-rw-r--r--lib/gitlab/private_commit_email.rb32
-rw-r--r--lib/gitlab/profiler.rb41
-rw-r--r--lib/gitlab/profiler/total_time_flat_printer.rb2
-rw-r--r--lib/gitlab/project_authorizations/with_nested_groups.rb2
-rw-r--r--lib/gitlab/project_authorizations/without_nested_groups.rb2
-rw-r--r--lib/gitlab/project_search_results.rb9
-rw-r--r--lib/gitlab/project_service_logger.rb2
-rw-r--r--lib/gitlab/project_template.rb2
-rw-r--r--lib/gitlab/project_transfer.rb2
-rw-r--r--lib/gitlab/prometheus/additional_metrics_parser.rb2
-rw-r--r--lib/gitlab/prometheus/metric.rb2
-rw-r--r--lib/gitlab/prometheus/metric_group.rb2
-rw-r--r--lib/gitlab/prometheus/parsing_error.rb2
-rw-r--r--lib/gitlab/prometheus/queries/additional_metrics_deployment_query.rb2
-rw-r--r--lib/gitlab/prometheus/queries/additional_metrics_environment_query.rb2
-rw-r--r--lib/gitlab/prometheus/queries/base_query.rb2
-rw-r--r--lib/gitlab/prometheus/queries/deployment_query.rb2
-rw-r--r--lib/gitlab/prometheus/queries/environment_query.rb2
-rw-r--r--lib/gitlab/prometheus/queries/matched_metric_query.rb2
-rw-r--r--lib/gitlab/prometheus/queries/query_additional_metrics.rb9
-rw-r--r--lib/gitlab/prometheus/query_variables.rb15
-rw-r--r--lib/gitlab/prometheus_client.rb2
-rw-r--r--lib/gitlab/protocol_access.rb2
-rw-r--r--lib/gitlab/proxy_http_connection_adapter.rb4
-rw-r--r--lib/gitlab/query_limiting.rb2
-rw-r--r--lib/gitlab/query_limiting/active_support_subscriber.rb2
-rw-r--r--lib/gitlab/query_limiting/transaction.rb4
-rw-r--r--lib/gitlab/quick_actions/command_definition.rb18
-rw-r--r--lib/gitlab/quick_actions/dsl.rb8
-rw-r--r--lib/gitlab/quick_actions/extractor.rb16
-rw-r--r--lib/gitlab/quick_actions/spend_time_and_date_separator.rb2
-rw-r--r--lib/gitlab/quick_actions/substitution_definition.rb2
-rw-r--r--lib/gitlab/recaptcha.rb2
-rw-r--r--lib/gitlab/redis/cache.rb2
-rw-r--r--lib/gitlab/redis/queues.rb2
-rw-r--r--lib/gitlab/redis/shared_state.rb2
-rw-r--r--lib/gitlab/redis/wrapper.rb2
-rw-r--r--lib/gitlab/reference_counter.rb2
-rw-r--r--lib/gitlab/reference_extractor.rb2
-rw-r--r--lib/gitlab/regex.rb2
-rw-r--r--lib/gitlab/repo_path.rb2
-rw-r--r--lib/gitlab/repository_cache.rb24
-rw-r--r--lib/gitlab/repository_cache_adapter.rb183
-rw-r--r--lib/gitlab/repository_check_logger.rb2
-rw-r--r--lib/gitlab/request_context.rb6
-rw-r--r--lib/gitlab/request_forgery_protection.rb2
-rw-r--r--lib/gitlab/request_profiler.rb2
-rw-r--r--lib/gitlab/request_profiler/middleware.rb2
-rw-r--r--lib/gitlab/request_profiler/profile.rb2
-rw-r--r--lib/gitlab/route_map.rb2
-rw-r--r--lib/gitlab/routing.rb4
-rw-r--r--lib/gitlab/safe_request_store.rb23
-rw-r--r--lib/gitlab/sanitizers/svg.rb2
-rw-r--r--lib/gitlab/sanitizers/svg/whitelist.rb2
-rw-r--r--lib/gitlab/search/parsed_query.rb2
-rw-r--r--lib/gitlab/search/query.rb2
-rw-r--r--lib/gitlab/search_results.rb19
-rw-r--r--lib/gitlab/seeder.rb2
-rw-r--r--lib/gitlab/sentry.rb16
-rw-r--r--lib/gitlab/serializer/ci/variables.rb2
-rw-r--r--lib/gitlab/serializer/pagination.rb2
-rw-r--r--lib/gitlab/setup_helper.rb7
-rw-r--r--lib/gitlab/shard_health_cache.rb2
-rw-r--r--lib/gitlab/shell.rb19
-rw-r--r--lib/gitlab/shell_adapter.rb2
-rw-r--r--lib/gitlab/sherlock.rb2
-rw-r--r--lib/gitlab/sherlock/collection.rb2
-rw-r--r--lib/gitlab/sherlock/file_sample.rb2
-rw-r--r--lib/gitlab/sherlock/line_profiler.rb2
-rw-r--r--lib/gitlab/sherlock/line_sample.rb2
-rw-r--r--lib/gitlab/sherlock/location.rb2
-rw-r--r--lib/gitlab/sherlock/middleware.rb2
-rw-r--r--lib/gitlab/sherlock/query.rb4
-rw-r--r--lib/gitlab/sherlock/transaction.rb2
-rw-r--r--lib/gitlab/sidekiq_config.rb11
-rw-r--r--lib/gitlab/sidekiq_logger.rb2
-rw-r--r--lib/gitlab/sidekiq_logging/json_formatter.rb2
-rw-r--r--lib/gitlab/sidekiq_logging/structured_logger.rb2
-rw-r--r--lib/gitlab/sidekiq_middleware/arguments_logger.rb2
-rw-r--r--lib/gitlab/sidekiq_middleware/batch_loader.rb13
-rw-r--r--lib/gitlab/sidekiq_middleware/request_store_middleware.rb2
-rw-r--r--lib/gitlab/sidekiq_middleware/shutdown.rb2
-rw-r--r--lib/gitlab/sidekiq_status.rb2
-rw-r--r--lib/gitlab/sidekiq_status/client_middleware.rb2
-rw-r--r--lib/gitlab/sidekiq_status/server_middleware.rb2
-rw-r--r--lib/gitlab/sidekiq_throttler.rb25
-rw-r--r--lib/gitlab/sidekiq_versioning.rb2
-rw-r--r--lib/gitlab/sidekiq_versioning/manager.rb2
-rw-r--r--lib/gitlab/slash_commands/base_command.rb2
-rw-r--r--lib/gitlab/slash_commands/command.rb2
-rw-r--r--lib/gitlab/slash_commands/deploy.rb2
-rw-r--r--lib/gitlab/slash_commands/help.rb2
-rw-r--r--lib/gitlab/slash_commands/issue_command.rb2
-rw-r--r--lib/gitlab/slash_commands/issue_move.rb2
-rw-r--r--lib/gitlab/slash_commands/issue_new.rb4
-rw-r--r--lib/gitlab/slash_commands/issue_search.rb2
-rw-r--r--lib/gitlab/slash_commands/issue_show.rb2
-rw-r--r--lib/gitlab/slash_commands/presenters/access.rb2
-rw-r--r--lib/gitlab/slash_commands/presenters/base.rb2
-rw-r--r--lib/gitlab/slash_commands/presenters/deploy.rb2
-rw-r--r--lib/gitlab/slash_commands/presenters/help.rb2
-rw-r--r--lib/gitlab/slash_commands/presenters/issue_base.rb2
-rw-r--r--lib/gitlab/slash_commands/presenters/issue_move.rb2
-rw-r--r--lib/gitlab/slash_commands/presenters/issue_new.rb2
-rw-r--r--lib/gitlab/slash_commands/presenters/issue_search.rb2
-rw-r--r--lib/gitlab/slash_commands/presenters/issue_show.rb8
-rw-r--r--lib/gitlab/slash_commands/result.rb5
-rw-r--r--lib/gitlab/snippet_search_results.rb2
-rw-r--r--lib/gitlab/sql/cte.rb2
-rw-r--r--lib/gitlab/sql/glob.rb2
-rw-r--r--lib/gitlab/sql/pattern.rb2
-rw-r--r--lib/gitlab/sql/recursive_cte.rb2
-rw-r--r--lib/gitlab/sql/union.rb2
-rw-r--r--lib/gitlab/ssh_public_key.rb4
-rw-r--r--lib/gitlab/storage_check.rb11
-rw-r--r--lib/gitlab/storage_check/cli.rb71
-rw-r--r--lib/gitlab/storage_check/gitlab_caller.rb39
-rw-r--r--lib/gitlab/storage_check/option_parser.rb39
-rw-r--r--lib/gitlab/storage_check/response.rb77
-rw-r--r--lib/gitlab/string_placeholder_replacer.rb2
-rw-r--r--lib/gitlab/string_range_marker.rb2
-rw-r--r--lib/gitlab/string_regex_marker.rb2
-rw-r--r--lib/gitlab/task_helpers.rb4
-rw-r--r--lib/gitlab/tcp_checker.rb2
-rw-r--r--lib/gitlab/template/base_template.rb15
-rw-r--r--lib/gitlab/template/dockerfile_template.rb2
-rw-r--r--lib/gitlab/template/finders/base_template_finder.rb2
-rw-r--r--lib/gitlab/template/finders/global_template_finder.rb4
-rw-r--r--lib/gitlab/template/finders/repo_template_finder.rb4
-rw-r--r--lib/gitlab/template/gitignore_template.rb2
-rw-r--r--lib/gitlab/template/gitlab_ci_yml_template.rb4
-rw-r--r--lib/gitlab/template/issue_template.rb2
-rw-r--r--lib/gitlab/template/merge_request_template.rb2
-rw-r--r--lib/gitlab/template_helper.rb2
-rw-r--r--lib/gitlab/temporarily_allow.rb8
-rw-r--r--lib/gitlab/testing/request_blocker_middleware.rb2
-rw-r--r--lib/gitlab/testing/request_inspector_middleware.rb8
-rw-r--r--lib/gitlab/themes.rb2
-rw-r--r--lib/gitlab/time_tracking_formatter.rb2
-rw-r--r--lib/gitlab/timeless.rb2
-rw-r--r--lib/gitlab/tree_summary.rb30
-rw-r--r--lib/gitlab/untrusted_regexp.rb2
-rw-r--r--lib/gitlab/update_path_error.rb2
-rw-r--r--lib/gitlab/upgrader.rb2
-rw-r--r--lib/gitlab/uploads_transfer.rb2
-rw-r--r--lib/gitlab/url_blocker.rb46
-rw-r--r--lib/gitlab/url_builder.rb2
-rw-r--r--lib/gitlab/url_sanitizer.rb4
-rw-r--r--lib/gitlab/usage_data.rb29
-rw-r--r--lib/gitlab/user_access.rb2
-rw-r--r--lib/gitlab/user_extractor.rb4
-rw-r--r--lib/gitlab/utils.rb7
-rw-r--r--lib/gitlab/utils/merge_hash.rb2
-rw-r--r--lib/gitlab/utils/override.rb2
-rw-r--r--lib/gitlab/utils/strong_memoize.rb2
-rw-r--r--lib/gitlab/verify/batch_verifier.rb2
-rw-r--r--lib/gitlab/verify/job_artifacts.rb2
-rw-r--r--lib/gitlab/verify/lfs_objects.rb2
-rw-r--r--lib/gitlab/verify/rake_task.rb2
-rw-r--r--lib/gitlab/verify/uploads.rb2
-rw-r--r--lib/gitlab/version_info.rb2
-rw-r--r--lib/gitlab/view/presenter/base.rb6
-rw-r--r--lib/gitlab/view/presenter/delegated.rb2
-rw-r--r--lib/gitlab/view/presenter/factory.rb2
-rw-r--r--lib/gitlab/view/presenter/simple.rb2
-rw-r--r--lib/gitlab/visibility_level.rb2
-rw-r--r--lib/gitlab/web_ide_commits_counter.rb17
-rw-r--r--lib/gitlab/webpack/dev_server_middleware.rb2
-rw-r--r--lib/gitlab/webpack/manifest.rb2
-rw-r--r--lib/gitlab/wiki_file_finder.rb2
-rw-r--r--lib/gitlab/workhorse.rb4
-rw-r--r--lib/google_api/auth.rb4
-rw-r--r--lib/google_api/cloud_platform/client.rb2
-rw-r--r--lib/gt_one_coercion.rb2
-rw-r--r--lib/haml_lint/inline_javascript.rb11
-rw-r--r--lib/json_web_token/hmac_token.rb28
-rw-r--r--lib/json_web_token/rsa_token.rb2
-rw-r--r--lib/json_web_token/token.rb11
-rw-r--r--lib/mattermost/client.rb2
-rw-r--r--lib/mattermost/command.rb2
-rw-r--r--lib/mattermost/error.rb2
-rw-r--r--lib/mattermost/session.rb2
-rw-r--r--lib/mattermost/team.rb2
-rw-r--r--lib/microsoft_teams/activity.rb2
-rw-r--r--lib/microsoft_teams/notifier.rb2
-rw-r--r--lib/milestone_array.rb2
-rw-r--r--lib/mysql_zero_date.rb2
-rw-r--r--lib/object_storage/direct_upload.rb2
-rw-r--r--lib/omni_auth/strategies/bitbucket.rb2
-rw-r--r--lib/omni_auth/strategies/jwt.rb2
-rw-r--r--lib/peek/rblineprof/custom_controller_helpers.rb6
-rw-r--r--lib/peek/views/gitaly.rb3
-rw-r--r--lib/peek/views/host.rb7
-rw-r--r--lib/quality/helm_client.rb113
-rw-r--r--lib/quality/kubernetes_client.rb42
-rw-r--r--lib/rails4_migration_version.rb16
-rw-r--r--lib/rouge/formatters/html_gitlab.rb2
-rw-r--r--lib/rouge/plugins/common_mark.rb2
-rw-r--r--lib/rspec_flaky/config.rb2
-rw-r--r--lib/rspec_flaky/example.rb2
-rw-r--r--lib/rspec_flaky/flaky_example.rb2
-rw-r--r--lib/rspec_flaky/flaky_examples_collection.rb2
-rw-r--r--lib/rspec_flaky/listener.rb2
-rw-r--r--lib/rspec_flaky/report.rb2
-rw-r--r--lib/static_model.rb2
-rw-r--r--lib/system_check.rb2
-rw-r--r--lib/system_check/app/active_users_check.rb2
-rw-r--r--lib/system_check/app/database_config_exists_check.rb2
-rw-r--r--lib/system_check/app/git_config_check.rb2
-rw-r--r--lib/system_check/app/git_user_default_ssh_config_check.rb2
-rw-r--r--lib/system_check/app/git_version_check.rb4
-rw-r--r--lib/system_check/app/gitlab_config_exists_check.rb2
-rw-r--r--lib/system_check/app/gitlab_config_up_to_date_check.rb2
-rw-r--r--lib/system_check/app/init_script_exists_check.rb2
-rw-r--r--lib/system_check/app/init_script_up_to_date_check.rb2
-rw-r--r--lib/system_check/app/log_writable_check.rb2
-rw-r--r--lib/system_check/app/migrations_are_up_check.rb2
-rw-r--r--lib/system_check/app/orphaned_group_members_check.rb2
-rw-r--r--lib/system_check/app/projects_have_namespace_check.rb2
-rw-r--r--lib/system_check/app/redis_version_check.rb2
-rw-r--r--lib/system_check/app/ruby_version_check.rb4
-rw-r--r--lib/system_check/app/tmp_writable_check.rb2
-rw-r--r--lib/system_check/app/uploads_directory_exists_check.rb2
-rw-r--r--lib/system_check/app/uploads_path_permission_check.rb2
-rw-r--r--lib/system_check/app/uploads_path_tmp_permission_check.rb2
-rw-r--r--lib/system_check/base_check.rb2
-rw-r--r--lib/system_check/helpers.rb2
-rw-r--r--lib/system_check/incoming_email/foreman_configured_check.rb2
-rw-r--r--lib/system_check/incoming_email/imap_authentication_check.rb2
-rw-r--r--lib/system_check/incoming_email/initd_configured_check.rb2
-rw-r--r--lib/system_check/incoming_email/mail_room_running_check.rb2
-rw-r--r--lib/system_check/orphans/namespace_check.rb2
-rw-r--r--lib/system_check/orphans/repository_check.rb2
-rw-r--r--lib/system_check/simple_executor.rb2
-rw-r--r--lib/tasks/gettext.rake4
-rw-r--r--lib/tasks/gitlab/artifacts/migrate.rake2
-rw-r--r--lib/tasks/gitlab/check.rake174
-rw-r--r--lib/tasks/gitlab/cleanup.rake4
-rw-r--r--lib/tasks/gitlab/ldap.rake2
-rw-r--r--lib/tasks/gitlab/shell.rake46
-rw-r--r--lib/tasks/gitlab/site_statistics.rake23
-rw-r--r--lib/tasks/gitlab/update_templates.rake4
-rw-r--r--lib/tasks/haml-lint.rake11
-rw-r--r--lib/tasks/import.rake6
-rw-r--r--lib/tasks/tokens.rake14
-rw-r--r--lib/unfold_form.rb2
-rw-r--r--lib/uploaded_file.rb2
-rw-r--r--lib/version_check.rb2
-rw-r--r--locale/ar_SA/gitlab.po1780
-rw-r--r--locale/bg/gitlab.po1700
-rw-r--r--locale/ca_ES/gitlab.po1762
-rw-r--r--locale/cs_CZ/gitlab.po1738
-rw-r--r--locale/cy_GB/gitlab.po10259
-rw-r--r--locale/da_DK/gitlab.po1694
-rw-r--r--locale/de/gitlab.po6792
-rw-r--r--locale/el_GR/gitlab.po9995
-rw-r--r--locale/en/gitlab.po3
-rw-r--r--locale/eo/gitlab.po1700
-rw-r--r--locale/es/gitlab.po1716
-rw-r--r--locale/et_EE/gitlab.po1694
-rw-r--r--locale/fil_PH/gitlab.po1694
-rw-r--r--locale/fr/gitlab.po2224
-rw-r--r--locale/gitlab.pot1042
-rw-r--r--locale/gl_ES/gitlab.po1696
-rw-r--r--locale/he_IL/gitlab.po1738
-rw-r--r--locale/hu_HU/gitlab.po9995
-rw-r--r--locale/id_ID/gitlab.po1671
-rw-r--r--locale/it/gitlab.po1706
-rw-r--r--locale/ja/gitlab.po2191
-rw-r--r--locale/ko/gitlab.po4067
-rw-r--r--locale/mn_MN/gitlab.po9995
-rw-r--r--locale/nb_NO/gitlab.po9995
-rw-r--r--locale/nl_NL/gitlab.po1708
-rw-r--r--locale/pl_PL/gitlab.po1738
-rw-r--r--locale/pt_BR/gitlab.po2130
-rw-r--r--locale/pt_PT/gitlab.po9995
-rw-r--r--locale/ro_RO/gitlab.po1717
-rw-r--r--locale/ru/gitlab.po1806
-rw-r--r--locale/sk_SK/gitlab.po10127
-rw-r--r--locale/sq_AL/gitlab.po1694
-rw-r--r--locale/sr_CS/gitlab.po10061
-rw-r--r--locale/sr_SP/gitlab.po10061
-rw-r--r--locale/tr_TR/gitlab.po1696
-rw-r--r--locale/uk/gitlab.po2312
-rw-r--r--locale/zh_CN/gitlab.po2119
-rw-r--r--locale/zh_HK/gitlab.po1681
-rw-r--r--locale/zh_TW/gitlab.po2057
-rw-r--r--package.json87
-rw-r--r--public/robots.txt2
-rw-r--r--qa/Dockerfile12
-rw-r--r--qa/Gemfile.lock4
-rw-r--r--qa/README.md9
-rw-r--r--qa/qa.rb130
-rw-r--r--qa/qa/factory/base.rb60
-rw-r--r--qa/qa/factory/dependency.rb39
-rw-r--r--qa/qa/factory/product.rb30
-rw-r--r--qa/qa/factory/repository/project_push.rb48
-rw-r--r--qa/qa/factory/repository/push.rb79
-rw-r--r--qa/qa/factory/repository/wiki_push.rb32
-rw-r--r--qa/qa/factory/resource/branch.rb77
-rw-r--r--qa/qa/factory/resource/deploy_key.rb43
-rw-r--r--qa/qa/factory/resource/file.rb34
-rw-r--r--qa/qa/factory/resource/fork.rb29
-rw-r--r--qa/qa/factory/resource/group.rb41
-rw-r--r--qa/qa/factory/resource/issue.rb32
-rw-r--r--qa/qa/factory/resource/kubernetes_cluster.rb59
-rw-r--r--qa/qa/factory/resource/merge_request.rb65
-rw-r--r--qa/qa/factory/resource/merge_request_from_fork.rb24
-rw-r--r--qa/qa/factory/resource/personal_access_token.rb27
-rw-r--r--qa/qa/factory/resource/project.rb54
-rw-r--r--qa/qa/factory/resource/project_imported_from_github.rb37
-rw-r--r--qa/qa/factory/resource/project_milestone.rb36
-rw-r--r--qa/qa/factory/resource/runner.rb47
-rw-r--r--qa/qa/factory/resource/sandbox.rb34
-rw-r--r--qa/qa/factory/resource/secret_variable.rb28
-rw-r--r--qa/qa/factory/resource/ssh_key.rb40
-rw-r--r--qa/qa/factory/resource/user.rb58
-rw-r--r--qa/qa/factory/resource/wiki.rb25
-rw-r--r--qa/qa/factory/settings/hashed_storage.rb24
-rw-r--r--qa/qa/fixtures/auto_devops_rack/Gemfile.lock4
-rw-r--r--qa/qa/git/repository.rb156
-rw-r--r--qa/qa/page/README.md40
-rw-r--r--qa/qa/page/admin/menu.rb47
-rw-r--r--qa/qa/page/admin/settings/component/repository_storage.rb26
-rw-r--r--qa/qa/page/admin/settings/main.rb21
-rw-r--r--qa/qa/page/admin/settings/repository.rb23
-rw-r--r--qa/qa/page/admin/settings/repository_storage.rb23
-rw-r--r--qa/qa/page/base.rb32
-rw-r--r--qa/qa/page/component/clone_panel.rb4
-rw-r--r--qa/qa/page/component/dropdown_filter.rb18
-rw-r--r--qa/qa/page/component/groups_filter.rb24
-rw-r--r--qa/qa/page/component/issuable/common.rb35
-rw-r--r--qa/qa/page/component/select2.rb7
-rw-r--r--qa/qa/page/component/users_select.rb14
-rw-r--r--qa/qa/page/dashboard/groups.rb12
-rw-r--r--qa/qa/page/dashboard/projects.rb2
-rw-r--r--qa/qa/page/file/form.rb34
-rw-r--r--qa/qa/page/file/shared/commit_message.rb2
-rw-r--r--qa/qa/page/file/show.rb6
-rw-r--r--qa/qa/page/group/new.rb10
-rw-r--r--qa/qa/page/group/show.rb45
-rw-r--r--qa/qa/page/issuable/sidebar.rb4
-rw-r--r--qa/qa/page/label/index.rb15
-rw-r--r--qa/qa/page/label/new.rb30
-rw-r--r--qa/qa/page/layout/banner.rb2
-rw-r--r--qa/qa/page/main/login.rb49
-rw-r--r--qa/qa/page/main/menu.rb97
-rw-r--r--qa/qa/page/main/oauth.rb2
-rw-r--r--qa/qa/page/main/sign_up.rb36
-rw-r--r--qa/qa/page/menu/admin.rb15
-rw-r--r--qa/qa/page/menu/main.rb88
-rw-r--r--qa/qa/page/menu/profile.rb34
-rw-r--r--qa/qa/page/menu/side.rb125
-rw-r--r--qa/qa/page/merge_request/new.rb10
-rw-r--r--qa/qa/page/merge_request/show.rb84
-rw-r--r--qa/qa/page/profile/menu.rb36
-rw-r--r--qa/qa/page/profile/personal_access_tokens.rb10
-rw-r--r--qa/qa/page/project/activity.rb2
-rw-r--r--qa/qa/page/project/fork/new.rb2
-rw-r--r--qa/qa/page/project/import/github.rb12
-rw-r--r--qa/qa/page/project/issue/index.rb2
-rw-r--r--qa/qa/page/project/issue/new.rb6
-rw-r--r--qa/qa/page/project/issue/show.rb38
-rw-r--r--qa/qa/page/project/job/show.rb25
-rw-r--r--qa/qa/page/project/menu.rb168
-rw-r--r--qa/qa/page/project/new.rb16
-rw-r--r--qa/qa/page/project/operations/environments/index.rb23
-rw-r--r--qa/qa/page/project/operations/environments/show.rb23
-rw-r--r--qa/qa/page/project/operations/kubernetes/add.rb4
-rw-r--r--qa/qa/page/project/operations/kubernetes/add_existing.rb17
-rw-r--r--qa/qa/page/project/operations/kubernetes/index.rb4
-rw-r--r--qa/qa/page/project/operations/kubernetes/show.rb8
-rw-r--r--qa/qa/page/project/pipeline/index.rb2
-rw-r--r--qa/qa/page/project/pipeline/show.rb12
-rw-r--r--qa/qa/page/project/settings/advanced.rb6
-rw-r--r--qa/qa/page/project/settings/ci_cd.rb14
-rw-r--r--qa/qa/page/project/settings/ci_variables.rb52
-rw-r--r--qa/qa/page/project/settings/common.rb2
-rw-r--r--qa/qa/page/project/settings/deploy_keys.rb12
-rw-r--r--qa/qa/page/project/settings/deploy_tokens.rb64
-rw-r--r--qa/qa/page/project/settings/members.rb27
-rw-r--r--qa/qa/page/project/settings/repository.rb6
-rw-r--r--qa/qa/page/project/settings/runners.rb6
-rw-r--r--qa/qa/page/project/settings/secret_variables.rb52
-rw-r--r--qa/qa/page/project/show.rb38
-rw-r--r--qa/qa/page/project/web_ide/edit.rb79
-rw-r--r--qa/qa/page/project/wiki/edit.rb6
-rw-r--r--qa/qa/page/project/wiki/new.rb12
-rw-r--r--qa/qa/page/project/wiki/show.rb2
-rw-r--r--qa/qa/resource/README.md392
-rw-r--r--qa/qa/resource/api_fabricator.rb96
-rw-r--r--qa/qa/resource/base.rb155
-rw-r--r--qa/qa/resource/branch.rb77
-rw-r--r--qa/qa/resource/ci_variable.rb30
-rw-r--r--qa/qa/resource/deploy_key.rb43
-rw-r--r--qa/qa/resource/deploy_token.rb50
-rw-r--r--qa/qa/resource/file.rb36
-rw-r--r--qa/qa/resource/fork.rb43
-rw-r--r--qa/qa/resource/group.rb72
-rw-r--r--qa/qa/resource/issue.rb30
-rw-r--r--qa/qa/resource/kubernetes_cluster.rb57
-rw-r--r--qa/qa/resource/label.rb39
-rw-r--r--qa/qa/resource/merge_request.rb75
-rw-r--r--qa/qa/resource/merge_request_from_fork.rb31
-rw-r--r--qa/qa/resource/personal_access_token.rb27
-rw-r--r--qa/qa/resource/project.rb80
-rw-r--r--qa/qa/resource/project_imported_from_github.rb36
-rw-r--r--qa/qa/resource/project_milestone.rb36
-rw-r--r--qa/qa/resource/repository/project_push.rb44
-rw-r--r--qa/qa/resource/repository/push.rb93
-rw-r--r--qa/qa/resource/repository/wiki_push.rb36
-rw-r--r--qa/qa/resource/runner.rb49
-rw-r--r--qa/qa/resource/sandbox.rb60
-rw-r--r--qa/qa/resource/settings/hashed_storage.rb26
-rw-r--r--qa/qa/resource/ssh_key.rb26
-rw-r--r--qa/qa/resource/user.rb113
-rw-r--r--qa/qa/resource/wiki.rb30
-rw-r--r--qa/qa/runtime/api/client.rb29
-rw-r--r--qa/qa/runtime/browser.rb13
-rw-r--r--qa/qa/runtime/env.rb85
-rw-r--r--qa/qa/runtime/fixtures.rb19
-rw-r--r--qa/qa/runtime/logger.rb25
-rw-r--r--qa/qa/runtime/namespace.rb2
-rw-r--r--qa/qa/runtime/path.rb13
-rw-r--r--qa/qa/scenario/test/integration/instance_saml.rb13
-rw-r--r--qa/qa/scenario/test/integration/ldap.rb11
-rw-r--r--qa/qa/scenario/test/integration/ldap_no_tls.rb13
-rw-r--r--qa/qa/scenario/test/integration/ldap_tls.rb13
-rw-r--r--qa/qa/service/kubernetes_cluster.rb72
-rw-r--r--qa/qa/service/shellout.rb6
-rw-r--r--qa/qa/specs/features/api/1_manage/users_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb17
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb30
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb26
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb12
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb39
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb28
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb11
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb9
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb77
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/add_ssh_key_spec.rb10
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb49
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb84
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb32
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb6
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb10
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb10
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb88
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_ci_variable_spec.rb28
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb10
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/secret_variable/add_secret_variable_spec.rb28
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb16
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb23
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb108
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/mattermost/create_group_with_mattermost_team_spec.rb4
-rw-r--r--qa/qa/specs/features/sanity/framework_spec.rb4
-rw-r--r--qa/qa/specs/runner.rb6
-rw-r--r--qa/qa/support/api.rb28
-rw-r--r--qa/qa/support/page/logging.rb100
-rw-r--r--qa/qa/vendor/saml_idp/page/base.rb14
-rw-r--r--qa/qa/vendor/saml_idp/page/login.rb19
-rw-r--r--qa/spec/factory/base_spec.rb132
-rw-r--r--qa/spec/factory/dependency_spec.rb72
-rw-r--r--qa/spec/factory/product_spec.rb39
-rw-r--r--qa/spec/factory/resource/user_spec.rb36
-rw-r--r--qa/spec/git/repository_spec.rb43
-rw-r--r--qa/spec/page/base_spec.rb6
-rw-r--r--qa/spec/page/logging_spec.rb94
-rw-r--r--qa/spec/page/validator_spec.rb2
-rw-r--r--qa/spec/page/view_spec.rb4
-rw-r--r--qa/spec/resource/api_fabricator_spec.rb161
-rw-r--r--qa/spec/resource/base_spec.rb246
-rw-r--r--qa/spec/resource/repository/push_spec.rb26
-rw-r--r--qa/spec/runtime/api/client_spec.rb25
-rw-r--r--qa/spec/runtime/api/request_spec.rb18
-rw-r--r--qa/spec/runtime/api_request_spec.rb0
-rw-r--r--qa/spec/runtime/env_spec.rb132
-rw-r--r--qa/spec/runtime/logger_spec.rb33
-rw-r--r--qa/spec/scenario/test/integration/instance_saml_spec.rb9
-rw-r--r--qa/spec/scenario/test/integration/ldap_spec.rb12
-rw-r--r--qa/spec/spec_helper.rb4
-rw-r--r--qa/spec/specs/runner_spec.rb28
-rw-r--r--rubocop/cop/code_reuse/active_record.rb1
-rw-r--r--rubocop/cop/group_public_or_visible_to_user.rb22
-rw-r--r--rubocop/cop/migration/add_reference.rb9
-rw-r--r--rubocop/cop/qa/element_with_pattern.rb39
-rw-r--r--rubocop/cop/safe_params.rb34
-rw-r--r--rubocop/qa_helpers.rb11
-rw-r--r--rubocop/rubocop.rb3
-rwxr-xr-xscripts/build_assets_image27
-rw-r--r--scripts/frontend/frontend_script_utils.js3
-rw-r--r--scripts/frontend/prettier.js206
-rwxr-xr-xscripts/lint-rugged14
-rwxr-xr-xscripts/rails4-gemfile-lock-check19
-rwxr-xr-xscripts/rails5-gemfile-lock-check19
-rwxr-xr-xscripts/review_apps/automated_cleanup.rb161
-rwxr-xr-xscripts/review_apps/review-apps.sh350
-rwxr-xr-xscripts/static-analysis1
-rwxr-xr-xscripts/trigger-build249
-rwxr-xr-xscripts/trigger-build-docs6
-rw-r--r--spec/bin/storage_check_spec.rb13
-rw-r--r--spec/controllers/admin/application_settings_controller_spec.rb18
-rw-r--r--spec/controllers/admin/health_check_controller_spec.rb12
-rw-r--r--spec/controllers/admin/projects_controller_spec.rb11
-rw-r--r--spec/controllers/admin/users_controller_spec.rb12
-rw-r--r--spec/controllers/application_controller_spec.rb337
-rw-r--r--spec/controllers/boards/issues_controller_spec.rb68
-rw-r--r--spec/controllers/concerns/controller_with_cross_project_access_check_spec.rb10
-rw-r--r--spec/controllers/concerns/issuable_collections_spec.rb15
-rw-r--r--spec/controllers/concerns/lfs_request_spec.rb2
-rw-r--r--spec/controllers/concerns/send_file_upload_spec.rb31
-rw-r--r--spec/controllers/dashboard/milestones_controller_spec.rb9
-rw-r--r--spec/controllers/dashboard/projects_controller_spec.rb5
-rw-r--r--spec/controllers/dashboard/todos_controller_spec.rb10
-rw-r--r--spec/controllers/dashboard_controller_spec.rb31
-rw-r--r--spec/controllers/graphql_controller_spec.rb47
-rw-r--r--spec/controllers/groups/boards_controller_spec.rb59
-rw-r--r--spec/controllers/groups/clusters/applications_controller_spec.rb87
-rw-r--r--spec/controllers/groups/clusters_controller_spec.rb574
-rw-r--r--spec/controllers/groups/milestones_controller_spec.rb4
-rw-r--r--spec/controllers/groups/settings/ci_cd_controller_spec.rb14
-rw-r--r--spec/controllers/groups_controller_spec.rb51
-rw-r--r--spec/controllers/health_controller_spec.rb42
-rw-r--r--spec/controllers/import/bitbucket_server_controller_spec.rb11
-rw-r--r--spec/controllers/oauth/applications_controller_spec.rb17
-rw-r--r--spec/controllers/profiles/keys_controller_spec.rb9
-rw-r--r--spec/controllers/profiles/personal_access_tokens_controller_spec.rb6
-rw-r--r--spec/controllers/projects/artifacts_controller_spec.rb63
-rw-r--r--spec/controllers/projects/blob_controller_spec.rb83
-rw-r--r--spec/controllers/projects/boards_controller_spec.rb57
-rw-r--r--spec/controllers/projects/clusters/applications_controller_spec.rb2
-rw-r--r--spec/controllers/projects/clusters_controller_spec.rb334
-rw-r--r--spec/controllers/projects/commit_controller_spec.rb1
-rw-r--r--spec/controllers/projects/commits_controller_spec.rb138
-rw-r--r--spec/controllers/projects/compare_controller_spec.rb24
-rw-r--r--spec/controllers/projects/deploy_keys_controller_spec.rb149
-rw-r--r--spec/controllers/projects/deployments_controller_spec.rb12
-rw-r--r--spec/controllers/projects/environments_controller_spec.rb11
-rw-r--r--spec/controllers/projects/imports_controller_spec.rb9
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb55
-rw-r--r--spec/controllers/projects/jobs_controller_spec.rb158
-rw-r--r--spec/controllers/projects/merge_requests/conflicts_controller_spec.rb1
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb108
-rw-r--r--spec/controllers/projects/milestones_controller_spec.rb35
-rw-r--r--spec/controllers/projects/mirrors_controller_spec.rb88
-rw-r--r--spec/controllers/projects/notes_controller_spec.rb142
-rw-r--r--spec/controllers/projects/pipelines_controller_spec.rb5
-rw-r--r--spec/controllers/projects/settings/ci_cd_controller_spec.rb13
-rw-r--r--spec/controllers/projects/tags_controller_spec.rb22
-rw-r--r--spec/controllers/projects/wikis_controller_spec.rb56
-rw-r--r--spec/controllers/projects_controller_spec.rb22
-rw-r--r--spec/controllers/registrations_controller_spec.rb2
-rw-r--r--spec/controllers/root_controller_spec.rb4
-rw-r--r--spec/controllers/sessions_controller_spec.rb2
-rw-r--r--spec/controllers/uploads_controller_spec.rb25
-rw-r--r--spec/controllers/users_controller_spec.rb8
-rw-r--r--spec/db/schema_spec.rb96
-rw-r--r--spec/factories/board_group_recent_visit.rb9
-rw-r--r--spec/factories/board_project_recent_visit.rb9
-rw-r--r--spec/factories/broadcast_messages.rb12
-rw-r--r--spec/factories/ci/builds.rb59
-rw-r--r--spec/factories/ci/job_artifacts.rb37
-rw-r--r--spec/factories/ci/pipelines.rb4
-rw-r--r--spec/factories/ci/runners.rb12
-rw-r--r--spec/factories/clusters/applications/helm.rb26
-rw-r--r--spec/factories/clusters/clusters.rb15
-rw-r--r--spec/factories/clusters/kubernetes_namespaces.rb20
-rw-r--r--spec/factories/clusters/platforms/kubernetes.rb5
-rw-r--r--spec/factories/clusters/projects.rb8
-rw-r--r--spec/factories/commit_statuses.rb4
-rw-r--r--spec/factories/deployments.rb31
-rw-r--r--spec/factories/emails.rb2
-rw-r--r--spec/factories/environments.rb1
-rw-r--r--spec/factories/events.rb2
-rw-r--r--spec/factories/forked_project_links.rb15
-rw-r--r--spec/factories/gpg_keys.rb4
-rw-r--r--spec/factories/group_members.rb2
-rw-r--r--spec/factories/import_state.rb7
-rw-r--r--spec/factories/issues.rb4
-rw-r--r--spec/factories/merge_request_diff_files.rb47
-rw-r--r--spec/factories/merge_request_diffs.rb13
-rw-r--r--spec/factories/merge_requests.rb16
-rw-r--r--spec/factories/notes.rb2
-rw-r--r--spec/factories/oauth_access_grants.rb2
-rw-r--r--spec/factories/pool_repositories.rb5
-rw-r--r--spec/factories/project_auto_devops.rb12
-rw-r--r--spec/factories/project_members.rb2
-rw-r--r--spec/factories/projects.rb27
-rw-r--r--spec/factories/services.rb11
-rw-r--r--spec/factories/shards.rb5
-rw-r--r--spec/factories/site_statistics.rb7
-rw-r--r--spec/factories/todos.rb2
-rw-r--r--spec/factories/uploads.rb10
-rw-r--r--spec/factories/user_preferences.rb12
-rw-r--r--spec/fast_spec_helper.rb2
-rw-r--r--spec/features/admin/admin_groups_spec.rb28
-rw-r--r--spec/features/admin/admin_health_check_spec.rb26
-rw-r--r--spec/features/admin/admin_manage_applications_spec.rb4
-rw-r--r--spec/features/admin/admin_runners_spec.rb74
-rw-r--r--spec/features/admin/admin_settings_spec.rb10
-rw-r--r--spec/features/admin/admin_users_impersonation_tokens_spec.rb5
-rw-r--r--spec/features/admin/admin_users_spec.rb119
-rw-r--r--spec/features/admin/dashboard_spec.rb28
-rw-r--r--spec/features/atom/dashboard_issues_spec.rb12
-rw-r--r--spec/features/boards/add_issues_modal_spec.rb2
-rw-r--r--spec/features/boards/issue_ordering_spec.rb4
-rw-r--r--spec/features/boards/modal_filter_spec.rb4
-rw-r--r--spec/features/boards/new_issue_spec.rb10
-rw-r--r--spec/features/boards/reload_boards_on_browser_back_spec.rb48
-rw-r--r--spec/features/calendar_spec.rb21
-rw-r--r--spec/features/commits_spec.rb60
-rw-r--r--spec/features/dashboard/archived_projects_spec.rb2
-rw-r--r--spec/features/dashboard/datetime_on_tooltips_spec.rb2
-rw-r--r--spec/features/dashboard/group_spec.rb8
-rw-r--r--spec/features/dashboard/issuables_counter_spec.rb4
-rw-r--r--spec/features/dashboard/issues_filter_spec.rb31
-rw-r--r--spec/features/dashboard/issues_spec.rb27
-rw-r--r--spec/features/dashboard/label_filter_spec.rb15
-rw-r--r--spec/features/dashboard/merge_requests_spec.rb16
-rw-r--r--spec/features/dashboard/milestone_filter_spec.rb77
-rw-r--r--spec/features/dashboard/project_member_activity_index_spec.rb16
-rw-r--r--spec/features/dashboard/shortcuts_spec.rb8
-rw-r--r--spec/features/explore/new_menu_spec.rb167
-rw-r--r--spec/features/groups/board_sidebar_spec.rb45
-rw-r--r--spec/features/groups/group_settings_spec.rb18
-rw-r--r--spec/features/groups/labels/subscription_spec.rb50
-rw-r--r--spec/features/groups/milestone_spec.rb12
-rw-r--r--spec/features/groups/settings/ci_cd_spec.rb39
-rw-r--r--spec/features/groups/share_lock_spec.rb4
-rw-r--r--spec/features/groups/show_spec.rb21
-rw-r--r--spec/features/groups_spec.rb41
-rw-r--r--spec/features/help_pages_spec.rb2
-rw-r--r--spec/features/import/manifest_import_spec.rb2
-rw-r--r--spec/features/issuables/close_reopen_report_toggle_spec.rb40
-rw-r--r--spec/features/issues/filtered_search/dropdown_assignee_spec.rb12
-rw-r--r--spec/features/issues/filtered_search/dropdown_emoji_spec.rb22
-rw-r--r--spec/features/issues/filtered_search/dropdown_hint_spec.rb18
-rw-r--r--spec/features/issues/filtered_search/dropdown_label_spec.rb13
-rw-r--r--spec/features/issues/filtered_search/dropdown_milestone_spec.rb10
-rw-r--r--spec/features/issues/filtered_search/filter_issues_spec.rb4
-rw-r--r--spec/features/issues/filtered_search/visual_tokens_spec.rb2
-rw-r--r--spec/features/issues/form_spec.rb2
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb89
-rw-r--r--spec/features/issues/issue_detail_spec.rb17
-rw-r--r--spec/features/issues/notes_on_issues_spec.rb23
-rw-r--r--spec/features/issues/resource_label_events_spec.rb7
-rw-r--r--spec/features/issues/user_comments_on_issue_spec.rb12
-rw-r--r--spec/features/issues/user_creates_branch_and_merge_request_spec.rb8
-rw-r--r--spec/features/issues/user_creates_issue_spec.rb6
-rw-r--r--spec/features/issues/user_edits_issue_spec.rb4
-rw-r--r--spec/features/issues/user_sees_breadcrumb_links_spec.rb8
-rw-r--r--spec/features/issues/user_sorts_issues_spec.rb6
-rw-r--r--spec/features/issues/user_uses_quick_actions_spec.rb58
-rw-r--r--spec/features/issues/user_views_issue_spec.rb6
-rw-r--r--spec/features/issues_spec.rb27
-rw-r--r--spec/features/markdown/markdown_spec.rb6
-rw-r--r--spec/features/markdown/mermaid_spec.rb2
-rw-r--r--spec/features/merge_request/user_assigns_themselves_spec.rb2
-rw-r--r--spec/features/merge_request/user_comments_on_diff_spec.rb18
-rw-r--r--spec/features/merge_request/user_creates_image_diff_notes_spec.rb9
-rw-r--r--spec/features/merge_request/user_creates_mr_spec.rb25
-rw-r--r--spec/features/merge_request/user_edits_mr_spec.rb4
-rw-r--r--spec/features/merge_request/user_posts_diff_notes_spec.rb13
-rw-r--r--spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb96
-rw-r--r--spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb17
-rw-r--r--spec/features/merge_request/user_sees_breadcrumb_links_spec.rb8
-rw-r--r--spec/features/merge_request/user_sees_deployment_widget_spec.rb110
-rw-r--r--spec/features/merge_request/user_sees_discussions_spec.rb21
-rw-r--r--spec/features/merge_request/user_sees_empty_state_spec.rb12
-rw-r--r--spec/features/merge_request/user_sees_merge_widget_spec.rb28
-rw-r--r--spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb8
-rw-r--r--spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb8
-rw-r--r--spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb8
-rw-r--r--spec/features/merge_request/user_sees_pipelines_spec.rb3
-rw-r--r--spec/features/merge_request/user_sees_versions_spec.rb12
-rw-r--r--spec/features/merge_request/user_views_diffs_spec.rb2
-rw-r--r--spec/features/merge_request/user_views_open_merge_request_spec.rb6
-rw-r--r--spec/features/merge_requests/user_sorts_merge_requests_spec.rb10
-rw-r--r--spec/features/milestones/user_creates_milestone_spec.rb2
-rw-r--r--spec/features/milestones/user_deletes_milestone_spec.rb2
-rw-r--r--spec/features/milestones/user_promotes_milestone_spec.rb32
-rw-r--r--spec/features/milestones/user_sees_breadcrumb_links_spec.rb19
-rw-r--r--spec/features/profiles/personal_access_tokens_spec.rb3
-rw-r--r--spec/features/profiles/user_edit_profile_spec.rb256
-rw-r--r--spec/features/profiles/user_manages_applications_spec.rb4
-rw-r--r--spec/features/projects/activity/user_sees_activity_spec.rb14
-rw-r--r--spec/features/projects/activity/user_sees_private_activity_spec.rb2
-rw-r--r--spec/features/projects/artifacts/user_downloads_artifacts_spec.rb14
-rw-r--r--spec/features/projects/badges/pipeline_badge_spec.rb2
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb5
-rw-r--r--spec/features/projects/clusters/user_spec.rb6
-rw-r--r--spec/features/projects/clusters_spec.rb31
-rw-r--r--spec/features/projects/commit/comments/user_adds_comment_spec.rb10
-rw-r--r--spec/features/projects/commit/user_comments_on_commit_spec.rb6
-rw-r--r--spec/features/projects/commits/user_browses_commits_spec.rb23
-rw-r--r--spec/features/projects/environments/environment_spec.rb85
-rw-r--r--spec/features/projects/environments/environments_spec.rb99
-rw-r--r--spec/features/projects/files/user_creates_files_spec.rb4
-rw-r--r--spec/features/projects/files/user_deletes_files_spec.rb2
-rw-r--r--spec/features/projects/fork_spec.rb12
-rw-r--r--spec/features/projects/import_export/export_file_spec.rb2
-rw-r--r--spec/features/projects/import_export/import_file_spec.rb7
-rw-r--r--spec/features/projects/jobs/permissions_spec.rb2
-rw-r--r--spec/features/projects/jobs/user_browses_job_spec.rb16
-rw-r--r--spec/features/projects/jobs_spec.rb412
-rw-r--r--spec/features/projects/labels/issues_sorted_by_priority_spec.rb4
-rw-r--r--spec/features/projects/labels/user_sees_breadcrumb_links_spec.rb17
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb119
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb54
-rw-r--r--spec/features/projects/settings/pipelines_settings_spec.rb24
-rw-r--r--spec/features/projects/settings/repository_settings_spec.rb63
-rw-r--r--spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb6
-rw-r--r--spec/features/projects/settings/user_tags_project_spec.rb14
-rw-r--r--spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb35
-rw-r--r--spec/features/projects/tree/create_directory_spec.rb2
-rw-r--r--spec/features/projects/tree/create_file_spec.rb2
-rw-r--r--spec/features/projects/view_on_env_spec.rb2
-rw-r--r--spec/features/projects/wiki/user_creates_wiki_page_spec.rb18
-rw-r--r--spec/features/projects/wiki/user_updates_wiki_page_spec.rb298
-rw-r--r--spec/features/projects/wiki/user_views_wiki_empty_spec.rb2
-rw-r--r--spec/features/projects/wiki/user_views_wiki_page_spec.rb227
-rw-r--r--spec/features/projects_spec.rb33
-rw-r--r--spec/features/search/user_searches_for_wiki_pages_spec.rb2
-rw-r--r--spec/features/search/user_uses_header_search_field_spec.rb16
-rw-r--r--spec/features/search/user_uses_search_filters_spec.rb4
-rw-r--r--spec/features/security/dashboard_access_spec.rb14
-rw-r--r--spec/features/signed_commits_spec.rb94
-rw-r--r--spec/features/snippets/user_sees_breadcrumb_links.rb17
-rw-r--r--spec/features/u2f_spec.rb4
-rw-r--r--spec/features/uploads/user_uploads_avatar_to_group_spec.rb2
-rw-r--r--spec/features/user_sorts_things_spec.rb2
-rw-r--r--spec/features/users/login_spec.rb24
-rw-r--r--spec/features/users/overview_spec.rb150
-rw-r--r--spec/features/users/show_spec.rb2
-rw-r--r--spec/finders/admin/runners_finder_spec.rb8
-rw-r--r--spec/finders/applications_finder_spec.rb22
-rw-r--r--spec/finders/branches_finder_spec.rb33
-rw-r--r--spec/finders/environments_finder_spec.rb16
-rw-r--r--spec/finders/fork_projects_finder_spec.rb15
-rw-r--r--spec/finders/group_descendants_finder_spec.rb7
-rw-r--r--spec/finders/group_labels_finder_spec.rb42
-rw-r--r--spec/finders/issues_finder_spec.rb108
-rw-r--r--spec/finders/labels_finder_spec.rb10
-rw-r--r--spec/finders/license_template_finder_spec.rb4
-rw-r--r--spec/finders/merge_requests_finder_spec.rb84
-rw-r--r--spec/finders/notes_finder_spec.rb29
-rw-r--r--spec/finders/pending_todos_finder_spec.rb63
-rw-r--r--spec/finders/personal_access_tokens_finder_spec.rb8
-rw-r--r--spec/finders/pipeline_schedules_finder_spec.rb2
-rw-r--r--spec/finders/pipelines_finder_spec.rb2
-rw-r--r--spec/finders/snippets_finder_spec.rb45
-rw-r--r--spec/finders/template_finder_spec.rb11
-rw-r--r--spec/finders/todos_finder_spec.rb17
-rw-r--r--spec/finders/user_finder_spec.rb154
-rw-r--r--spec/finders/users_finder_spec.rb6
-rw-r--r--spec/finders/users_with_pending_todos_finder_spec.rb19
-rw-r--r--spec/fixtures/api/schemas/deployment.json31
-rw-r--r--spec/fixtures/api/schemas/entities/commit.json5
-rw-r--r--spec/fixtures/api/schemas/entities/diff_viewer.json8
-rw-r--r--spec/fixtures/api/schemas/entities/issue_board.json39
-rw-r--r--spec/fixtures/api/schemas/entities/merge_request_widget.json1
-rw-r--r--spec/fixtures/api/schemas/entities/note_user_entity.json21
-rw-r--r--spec/fixtures/api/schemas/issue.json2
-rw-r--r--spec/fixtures/api/schemas/job/deployment_status.json2
-rw-r--r--spec/fixtures/api/schemas/job/job.json6
-rw-r--r--spec/fixtures/api/schemas/job/job_details.json12
-rw-r--r--spec/fixtures/api/schemas/job/runners.json3
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/license.json30
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/merge_requests.json26
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/template.json12
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/template_list.json15
-rw-r--r--spec/fixtures/authentication/saml2_response.xml56
-rw-r--r--spec/fixtures/codequality/codequality.json1
-rw-r--r--spec/fixtures/codequality/codequality.json.gzbin0 -> 101478 bytes
-rw-r--r--spec/fixtures/emails/merge_request_multiple_patches.eml181
-rw-r--r--spec/fixtures/emails/merge_request_with_conflicting_patch.eml45
-rw-r--r--spec/fixtures/emails/merge_request_with_patch_and_target_branch.eml44
-rw-r--r--spec/fixtures/emails/paragraphs.eml2
-rw-r--r--spec/fixtures/emails/valid_merge_request_with_patch.eml151
-rw-r--r--spec/fixtures/git-cheat-sheet.pdf130423
-rw-r--r--spec/fixtures/patchfiles/0001-A-commit-from-a-patch.patch19
-rw-r--r--spec/fixtures/patchfiles/0001-This-does-not-apply-to-the-feature-branch.patch23
-rw-r--r--spec/fixtures/security-reports/feature-branch.zipbin0 -> 7163 bytes
-rw-r--r--spec/fixtures/security-reports/feature-branch/gl-container-scanning-report.json18
-rw-r--r--spec/fixtures/security-reports/feature-branch/gl-dast-report.json40
-rw-r--r--spec/fixtures/security-reports/feature-branch/gl-dependency-scanning-report.json154
-rw-r--r--spec/fixtures/security-reports/feature-branch/gl-license-management-report.json242
-rw-r--r--spec/fixtures/security-reports/feature-branch/gl-sast-report.json944
-rw-r--r--spec/fixtures/security-reports/master.zipbin0 -> 6710 bytes
-rw-r--r--spec/fixtures/security-reports/master/gl-container-scanning-report.json18
-rw-r--r--spec/fixtures/security-reports/master/gl-dast-report.json40
-rw-r--r--spec/fixtures/security-reports/master/gl-dependency-scanning-report.json154
-rw-r--r--spec/fixtures/security-reports/master/gl-license-management-report.json150
-rw-r--r--spec/fixtures/security-reports/master/gl-sast-report.json944
-rw-r--r--spec/fixtures/ssh_host_example_key.pub2
-rw-r--r--spec/fixtures/trace/sample_trace24
-rw-r--r--spec/fixtures/valid.po3
-rw-r--r--spec/graphql/resolvers/issues_resolver_spec.rb40
-rw-r--r--spec/graphql/types/issue_type_spec.rb7
-rw-r--r--spec/graphql/types/permission_types/issue_spec.rb12
-rw-r--r--spec/graphql/types/permission_types/project_spec.rb2
-rw-r--r--spec/graphql/types/project_type_spec.rb4
-rw-r--r--spec/helpers/application_helper_spec.rb4
-rw-r--r--spec/helpers/auth_helper_spec.rb10
-rw-r--r--spec/helpers/avatars_helper_spec.rb24
-rw-r--r--spec/helpers/blob_helper_spec.rb58
-rw-r--r--spec/helpers/commits_helper_spec.rb2
-rw-r--r--spec/helpers/events_helper_spec.rb46
-rw-r--r--spec/helpers/labels_helper_spec.rb25
-rw-r--r--spec/helpers/preferences_helper_spec.rb7
-rw-r--r--spec/helpers/profiles_helper_spec.rb34
-rw-r--r--spec/helpers/search_helper_spec.rb35
-rw-r--r--spec/helpers/storage_health_helper_spec.rb20
-rw-r--r--spec/helpers/time_helper_spec.rb23
-rw-r--r--spec/helpers/tree_helper_spec.rb73
-rw-r--r--spec/helpers/visibility_level_helper_spec.rb12
-rw-r--r--spec/initializers/attr_encrypted_no_db_connection_spec.rb30
-rw-r--r--spec/initializers/secret_token_spec.rb2
-rw-r--r--spec/javascripts/.eslintrc.yml2
-rw-r--r--spec/javascripts/ajax_loading_spinner_spec.js9
-rw-r--r--spec/javascripts/api_spec.js76
-rw-r--r--spec/javascripts/avatar_helper_spec.js2
-rw-r--r--spec/javascripts/awards_handler_spec.js692
-rw-r--r--spec/javascripts/badges/components/badge_form_spec.js11
-rw-r--r--spec/javascripts/badges/components/badge_list_row_spec.js5
-rw-r--r--spec/javascripts/badges/components/badge_list_spec.js3
-rw-r--r--spec/javascripts/badges/components/badge_settings_spec.js9
-rw-r--r--spec/javascripts/badges/components/badge_spec.js3
-rw-r--r--spec/javascripts/badges/store/actions_spec.js7
-rw-r--r--spec/javascripts/behaviors/autosize_spec.js1
-rw-r--r--spec/javascripts/behaviors/bind_in_out_spec.js113
-rw-r--r--spec/javascripts/behaviors/copy_as_gfm_spec.js6
-rw-r--r--spec/javascripts/behaviors/gl_emoji/unicode_support_map_spec.js4
-rw-r--r--spec/javascripts/behaviors/markdown/highlight_current_user_spec.js55
-rw-r--r--spec/javascripts/behaviors/quick_submit_spec.js19
-rw-r--r--spec/javascripts/behaviors/requires_input_spec.js30
-rw-r--r--spec/javascripts/behaviors/secret_values_spec.js36
-rw-r--r--spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js147
-rw-r--r--spec/javascripts/blob/3d_viewer/mesh_object_spec.js20
-rw-r--r--spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js14
-rw-r--r--spec/javascripts/blob/balsamiq/balsamiq_viewer_spec.js18
-rw-r--r--spec/javascripts/blob/blob_file_dropzone_spec.js2
-rw-r--r--spec/javascripts/blob/blob_fork_suggestion_spec.js5
-rw-r--r--spec/javascripts/blob/notebook/index_spec.js86
-rw-r--r--spec/javascripts/blob/pdf/index_spec.js32
-rw-r--r--spec/javascripts/blob/sketch/index_spec.js108
-rw-r--r--spec/javascripts/blob/viewer/index_spec.js48
-rw-r--r--spec/javascripts/blob_edit/blob_bundle_spec.js30
-rw-r--r--spec/javascripts/boards/board_blank_state_spec.js80
-rw-r--r--spec/javascripts/boards/board_card_spec.js65
-rw-r--r--spec/javascripts/boards/board_list_spec.js93
-rw-r--r--spec/javascripts/boards/board_new_issue_spec.js35
-rw-r--r--spec/javascripts/boards/boards_store_spec.js133
-rw-r--r--spec/javascripts/boards/components/board_spec.js41
-rw-r--r--spec/javascripts/boards/components/issue_due_date_spec.js64
-rw-r--r--spec/javascripts/boards/components/issue_time_estimate_spec.js40
-rw-r--r--spec/javascripts/boards/issue_card_spec.js26
-rw-r--r--spec/javascripts/boards/issue_spec.js52
-rw-r--r--spec/javascripts/boards/list_spec.js107
-rw-r--r--spec/javascripts/boards/mock_data.js3
-rw-r--r--spec/javascripts/bootstrap_jquery_spec.js74
-rw-r--r--spec/javascripts/bootstrap_linked_tabs_spec.js87
-rw-r--r--spec/javascripts/breakpoints_spec.js6
-rw-r--r--spec/javascripts/ci_variable_list/ajax_variable_list_spec.js66
-rw-r--r--spec/javascripts/ci_variable_list/ci_variable_list_spec.js26
-rw-r--r--spec/javascripts/ci_variable_list/native_form_variable_list_spec.js10
-rw-r--r--spec/javascripts/close_reopen_report_toggle_spec.js10
-rw-r--r--spec/javascripts/clusters/clusters_bundle_spec.js213
-rw-r--r--spec/javascripts/clusters/components/application_row_spec.js41
-rw-r--r--spec/javascripts/clusters/components/applications_spec.js24
-rw-r--r--spec/javascripts/clusters/services/mock_data.js139
-rw-r--r--spec/javascripts/clusters/stores/clusters_store_spec.js28
-rw-r--r--spec/javascripts/collapsed_sidebar_todo_spec.js50
-rw-r--r--spec/javascripts/comment_type_toggle_spec.js114
-rw-r--r--spec/javascripts/commit/commit_pipeline_status_component_spec.js35
-rw-r--r--spec/javascripts/commit/pipelines/pipelines_spec.js37
-rw-r--r--spec/javascripts/commit_merge_requests_spec.js11
-rw-r--r--spec/javascripts/create_item_dropdown_spec.js49
-rw-r--r--spec/javascripts/create_merge_request_dropdown_spec.js1
-rw-r--r--spec/javascripts/cycle_analytics/banner_spec.js23
-rw-r--r--spec/javascripts/datetime_utility_spec.js170
-rw-r--r--spec/javascripts/deploy_keys/components/app_spec.js5
-rw-r--r--spec/javascripts/deploy_keys/components/key_spec.js3
-rw-r--r--spec/javascripts/diff_comments_store_spec.js12
-rw-r--r--spec/javascripts/diffs/components/app_spec.js30
-rw-r--r--spec/javascripts/diffs/components/changed_files_spec.js105
-rw-r--r--spec/javascripts/diffs/components/commit_item_spec.js164
-rw-r--r--spec/javascripts/diffs/components/commit_widget_spec.js24
-rw-r--r--spec/javascripts/diffs/components/compare_versions_spec.js147
-rw-r--r--spec/javascripts/diffs/components/diff_content_spec.js82
-rw-r--r--spec/javascripts/diffs/components/diff_discussions_spec.js78
-rw-r--r--spec/javascripts/diffs/components/diff_file_header_spec.js121
-rw-r--r--spec/javascripts/diffs/components/diff_file_spec.js46
-rw-r--r--spec/javascripts/diffs/components/diff_gutter_avatars_spec.js2
-rw-r--r--spec/javascripts/diffs/components/diff_line_gutter_content_spec.js30
-rw-r--r--spec/javascripts/diffs/components/diff_line_note_form_spec.js40
-rw-r--r--spec/javascripts/diffs/components/diff_table_cell_spec.js37
-rw-r--r--spec/javascripts/diffs/components/file_row_stats_spec.js33
-rw-r--r--spec/javascripts/diffs/components/image_diff_overlay_spec.js146
-rw-r--r--spec/javascripts/diffs/components/inline_diff_table_row_spec.js42
-rw-r--r--spec/javascripts/diffs/components/inline_diff_view_spec.js13
-rw-r--r--spec/javascripts/diffs/components/parallel_diff_table_row_spec.js85
-rw-r--r--spec/javascripts/diffs/components/parallel_diff_view_spec.js2
-rw-r--r--spec/javascripts/diffs/components/tree_list_spec.js188
-rw-r--r--spec/javascripts/diffs/mock_data/diff_discussions.js37
-rw-r--r--spec/javascripts/diffs/mock_data/diff_file.js242
-rw-r--r--spec/javascripts/diffs/mock_data/diff_with_commit.js7
-rw-r--r--spec/javascripts/diffs/mock_data/merge_request_diffs.js42
-rw-r--r--spec/javascripts/diffs/store/actions_spec.js258
-rw-r--r--spec/javascripts/diffs/store/getters_spec.js122
-rw-r--r--spec/javascripts/diffs/store/mutations_spec.js292
-rw-r--r--spec/javascripts/diffs/store/utils_spec.js296
-rw-r--r--spec/javascripts/dirty_submit/dirty_submit_collection_spec.js29
-rw-r--r--spec/javascripts/dirty_submit/dirty_submit_factory_spec.js18
-rw-r--r--spec/javascripts/dirty_submit/dirty_submit_form_spec.js36
-rw-r--r--spec/javascripts/dirty_submit/helper.js31
-rw-r--r--spec/javascripts/droplab/drop_down_spec.js251
-rw-r--r--spec/javascripts/droplab/hook_spec.js34
-rw-r--r--spec/javascripts/droplab/plugins/ajax_filter_spec.js10
-rw-r--r--spec/javascripts/droplab/plugins/ajax_spec.js7
-rw-r--r--spec/javascripts/droplab/plugins/input_setter_spec.js100
-rw-r--r--spec/javascripts/dropzone_input_spec.js6
-rw-r--r--spec/javascripts/emoji_spec.js62
-rw-r--r--spec/javascripts/environments/emtpy_state_spec.js23
-rw-r--r--spec/javascripts/environments/environment_actions_spec.js123
-rw-r--r--spec/javascripts/environments/environment_item_spec.js56
-rw-r--r--spec/javascripts/environments/environments_app_spec.js104
-rw-r--r--spec/javascripts/environments/environments_store_spec.js15
-rw-r--r--spec/javascripts/environments/folder/environments_folder_view_spec.js104
-rw-r--r--spec/javascripts/feature_highlight/feature_highlight_helper_spec.js17
-rw-r--r--spec/javascripts/feature_highlight/feature_highlight_spec.js8
-rw-r--r--spec/javascripts/filtered_search/components/recent_searches_dropdown_content_spec.js26
-rw-r--r--spec/javascripts/filtered_search/dropdown_user_spec.js9
-rw-r--r--spec/javascripts/filtered_search/dropdown_utils_spec.js113
-rw-r--r--spec/javascripts/filtered_search/filtered_search_manager_spec.js48
-rw-r--r--spec/javascripts/filtered_search/filtered_search_token_keys_spec.js83
-rw-r--r--spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js38
-rw-r--r--spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js258
-rw-r--r--spec/javascripts/filtered_search/recent_searches_root_spec.js2
-rw-r--r--spec/javascripts/filtered_search/services/recent_searches_service_spec.js27
-rw-r--r--spec/javascripts/filtered_search/stores/recent_searches_store_spec.js10
-rw-r--r--spec/javascripts/fixtures/groups.rb10
-rw-r--r--spec/javascripts/fixtures/jobs.rb23
-rw-r--r--spec/javascripts/fixtures/merge_requests_diffs.rb14
-rw-r--r--spec/javascripts/flash_spec.js149
-rw-r--r--spec/javascripts/fly_out_nav_spec.js127
-rw-r--r--spec/javascripts/frequent_items/components/app_spec.js3
-rw-r--r--spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js6
-rw-r--r--spec/javascripts/frequent_items/components/frequent_items_list_spec.js6
-rw-r--r--spec/javascripts/frequent_items/components/frequent_items_search_input_spec.js1
-rw-r--r--spec/javascripts/gfm_auto_complete_spec.js98
-rw-r--r--spec/javascripts/gl_dropdown_spec.js106
-rw-r--r--spec/javascripts/gl_field_errors_spec.js41
-rw-r--r--spec/javascripts/gl_form_spec.js7
-rw-r--r--spec/javascripts/gpg_badges_spec.js2
-rw-r--r--spec/javascripts/graphs/stat_graph_contributors_graph_spec.js106
-rw-r--r--spec/javascripts/graphs/stat_graph_contributors_spec.js4
-rw-r--r--spec/javascripts/graphs/stat_graph_contributors_util_spec.js245
-rw-r--r--spec/javascripts/groups/components/app_spec.js25
-rw-r--r--spec/javascripts/groups/components/group_folder_spec.js3
-rw-r--r--spec/javascripts/groups/components/group_item_spec.js15
-rw-r--r--spec/javascripts/groups/components/groups_spec.js17
-rw-r--r--spec/javascripts/groups/components/item_actions_spec.js9
-rw-r--r--spec/javascripts/groups/components/item_caret_spec.js3
-rw-r--r--spec/javascripts/groups/components/item_stats_spec.js25
-rw-r--r--spec/javascripts/groups/components/item_stats_value_spec.js6
-rw-r--r--spec/javascripts/groups/components/item_type_icon_spec.js5
-rw-r--r--spec/javascripts/groups/mock_data.js3
-rw-r--r--spec/javascripts/groups/service/groups_service_spec.js3
-rw-r--r--spec/javascripts/groups/store/groups_store_spec.js29
-rw-r--r--spec/javascripts/header_spec.js5
-rw-r--r--spec/javascripts/helpers/class_spec_helper_spec.js6
-rw-r--r--spec/javascripts/helpers/locale_helper.js2
-rw-r--r--spec/javascripts/helpers/scroll_into_view_promise.js28
-rw-r--r--spec/javascripts/helpers/set_timeout_promise_helper.js7
-rw-r--r--spec/javascripts/helpers/user_mock_data_helper.js14
-rw-r--r--spec/javascripts/helpers/vue_resource_helper.js2
-rw-r--r--spec/javascripts/helpers/wait_for_attribute_change.js16
-rw-r--r--spec/javascripts/ide/components/branches/item_spec.js5
-rw-r--r--spec/javascripts/ide/components/branches/search_list_spec.js5
-rw-r--r--spec/javascripts/ide/components/changed_file_icon_spec.js46
-rw-r--r--spec/javascripts/ide/components/commit_sidebar/list_item_spec.js4
-rw-r--r--spec/javascripts/ide/components/commit_sidebar/message_field_spec.js23
-rw-r--r--spec/javascripts/ide/components/file_finder/index_spec.js9
-rw-r--r--spec/javascripts/ide/components/file_row_extra_spec.js8
-rw-r--r--spec/javascripts/ide/components/ide_spec.js11
-rw-r--r--spec/javascripts/ide/components/ide_status_bar_spec.js10
-rw-r--r--spec/javascripts/ide/components/jobs/detail_spec.js3
-rw-r--r--spec/javascripts/ide/components/merge_requests/item_spec.js5
-rw-r--r--spec/javascripts/ide/components/merge_requests/list_spec.js5
-rw-r--r--spec/javascripts/ide/components/new_dropdown/index_spec.js1
-rw-r--r--spec/javascripts/ide/components/new_dropdown/upload_spec.js40
-rw-r--r--spec/javascripts/ide/components/panes/right_spec.js24
-rw-r--r--spec/javascripts/ide/components/preview/clientside_spec.js3
-rw-r--r--spec/javascripts/ide/components/repo_commit_section_spec.js59
-rw-r--r--spec/javascripts/ide/components/repo_editor_spec.js16
-rw-r--r--spec/javascripts/ide/components/repo_loading_file_spec.js63
-rw-r--r--spec/javascripts/ide/components/repo_tab_spec.js4
-rw-r--r--spec/javascripts/ide/components/shared/tokened_input_spec.js5
-rw-r--r--spec/javascripts/ide/helpers.js2
-rw-r--r--spec/javascripts/ide/stores/actions/file_spec.js4
-rw-r--r--spec/javascripts/ide/stores/actions/merge_request_spec.js65
-rw-r--r--spec/javascripts/ide/stores/actions/project_spec.js5
-rw-r--r--spec/javascripts/ide/stores/actions/tree_spec.js3
-rw-r--r--spec/javascripts/ide/stores/actions_spec.js2
-rw-r--r--spec/javascripts/ide/stores/modules/branches/actions_spec.js3
-rw-r--r--spec/javascripts/ide/stores/modules/file_templates/actions_spec.js46
-rw-r--r--spec/javascripts/ide/stores/modules/file_templates/mutations_spec.js8
-rw-r--r--spec/javascripts/ide/stores/modules/merge_requests/actions_spec.js58
-rw-r--r--spec/javascripts/ide/stores/modules/pane/actions_spec.js66
-rw-r--r--spec/javascripts/ide/stores/modules/pane/getters_spec.js55
-rw-r--r--spec/javascripts/ide/stores/modules/pane/mutations_spec.js42
-rw-r--r--spec/javascripts/ide/stores/modules/pipelines/actions_spec.js16
-rw-r--r--spec/javascripts/ide/stores/mutations/merge_request_spec.js2
-rw-r--r--spec/javascripts/image_diff/helpers/badge_helper_spec.js1
-rw-r--r--spec/javascripts/image_diff/helpers/comment_indicator_helper_spec.js7
-rw-r--r--spec/javascripts/image_diff/helpers/dom_helper_spec.js2
-rw-r--r--spec/javascripts/image_diff/helpers/utils_helper_spec.js18
-rw-r--r--spec/javascripts/image_diff/image_badge_spec.js30
-rw-r--r--spec/javascripts/image_diff/image_diff_spec.js20
-rw-r--r--spec/javascripts/image_diff/init_discussion_tab_spec.js15
-rw-r--r--spec/javascripts/image_diff/replaced_image_diff_spec.js95
-rw-r--r--spec/javascripts/importer_status_spec.js64
-rw-r--r--spec/javascripts/integrations/integration_settings_form_spec.js82
-rw-r--r--spec/javascripts/issuable_spec.js5
-rw-r--r--spec/javascripts/issuable_suggestions/components/app_spec.js96
-rw-r--r--spec/javascripts/issuable_suggestions/components/item_spec.js139
-rw-r--r--spec/javascripts/issuable_suggestions/mock_data.js26
-rw-r--r--spec/javascripts/issue_show/components/app_spec.js275
-rw-r--r--spec/javascripts/issue_show/components/description_spec.js49
-rw-r--r--spec/javascripts/issue_show/components/edit_actions_spec.js66
-rw-r--r--spec/javascripts/issue_show/components/edited_spec.js10
-rw-r--r--spec/javascripts/issue_show/components/fields/description_spec.js24
-rw-r--r--spec/javascripts/issue_show/components/fields/description_template_spec.js16
-rw-r--r--spec/javascripts/issue_show/components/fields/title_spec.js12
-rw-r--r--spec/javascripts/issue_show/components/form_spec.js23
-rw-r--r--spec/javascripts/issue_show/components/title_spec.js21
-rw-r--r--spec/javascripts/issue_show/index_spec.js19
-rw-r--r--spec/javascripts/issue_spec.js20
-rw-r--r--spec/javascripts/job_spec.js314
-rw-r--r--spec/javascripts/jobs/components/artifacts_block_spec.js66
-rw-r--r--spec/javascripts/jobs/components/commit_block_spec.js41
-rw-r--r--spec/javascripts/jobs/components/empty_state_spec.js7
-rw-r--r--spec/javascripts/jobs/components/environments_block_spec.js62
-rw-r--r--spec/javascripts/jobs/components/erased_block_spec.js8
-rw-r--r--spec/javascripts/jobs/components/header_spec.js98
-rw-r--r--spec/javascripts/jobs/components/job_app_spec.js633
-rw-r--r--spec/javascripts/jobs/components/job_container_item_spec.js99
-rw-r--r--spec/javascripts/jobs/components/job_details_mediator_spec.js39
-rw-r--r--spec/javascripts/jobs/components/job_log_controllers_spec.js167
-rw-r--r--spec/javascripts/jobs/components/job_log_spec.js44
-rw-r--r--spec/javascripts/jobs/components/job_store_spec.js26
-rw-r--r--spec/javascripts/jobs/components/jobs_container_spec.js23
-rw-r--r--spec/javascripts/jobs/components/sidebar_detail_row_spec.js6
-rw-r--r--spec/javascripts/jobs/components/sidebar_details_block_spec.js139
-rw-r--r--spec/javascripts/jobs/components/sidebar_spec.js189
-rw-r--r--spec/javascripts/jobs/components/stages_dropdown_spec.js44
-rw-r--r--spec/javascripts/jobs/components/trigger_block_spec.js76
-rw-r--r--spec/javascripts/jobs/components/trigger_value_spec.js66
-rw-r--r--spec/javascripts/jobs/mixins/delayed_job_mixin_spec.js93
-rw-r--r--spec/javascripts/jobs/mock_data.js1053
-rw-r--r--spec/javascripts/jobs/store/actions_spec.js243
-rw-r--r--spec/javascripts/jobs/store/getters_spec.js212
-rw-r--r--spec/javascripts/jobs/store/helpers.js6
-rw-r--r--spec/javascripts/jobs/store/mutations_spec.js92
-rw-r--r--spec/javascripts/labels_issue_sidebar_spec.js134
-rw-r--r--spec/javascripts/labels_select_spec.js14
-rw-r--r--spec/javascripts/landing_spec.js70
-rw-r--r--spec/javascripts/lazy_loader_spec.js241
-rw-r--r--spec/javascripts/lib/utils/accessor_spec.js14
-rw-r--r--spec/javascripts/lib/utils/ajax_cache_spec.js66
-rw-r--r--spec/javascripts/lib/utils/common_utils_spec.js246
-rw-r--r--spec/javascripts/lib/utils/csrf_token_spec.js5
-rw-r--r--spec/javascripts/lib/utils/datefix_spec.js27
-rw-r--r--spec/javascripts/lib/utils/datetime_utility_spec.js378
-rw-r--r--spec/javascripts/lib/utils/dom_utils_spec.js2
-rw-r--r--spec/javascripts/lib/utils/mock_data.js9
-rw-r--r--spec/javascripts/lib/utils/number_utility_spec.js12
-rw-r--r--spec/javascripts/lib/utils/poll_spec.js28
-rw-r--r--spec/javascripts/lib/utils/sticky_spec.js29
-rw-r--r--spec/javascripts/lib/utils/text_markdown_spec.js173
-rw-r--r--spec/javascripts/lib/utils/text_utility_spec.js2
-rw-r--r--spec/javascripts/lib/utils/url_utility_spec.js24
-rw-r--r--spec/javascripts/lib/utils/users_cache_spec.js52
-rw-r--r--spec/javascripts/line_highlighter_spec.js417
-rw-r--r--spec/javascripts/locale/ensure_single_line_spec.js3
-rw-r--r--spec/javascripts/merge_request_spec.js185
-rw-r--r--spec/javascripts/merge_request_tabs_spec.js42
-rw-r--r--spec/javascripts/mini_pipeline_graph_dropdown_spec.js12
-rw-r--r--spec/javascripts/monitoring/dashboard_spec.js96
-rw-r--r--spec/javascripts/monitoring/dashboard_state_spec.js28
-rw-r--r--spec/javascripts/monitoring/graph/deployment_spec.js6
-rw-r--r--spec/javascripts/monitoring/graph/flag_spec.js33
-rw-r--r--spec/javascripts/monitoring/graph/legend_spec.js2
-rw-r--r--spec/javascripts/monitoring/graph/track_info_spec.js2
-rw-r--r--spec/javascripts/monitoring/graph/track_line_spec.js2
-rw-r--r--spec/javascripts/monitoring/graph_path_spec.js6
-rw-r--r--spec/javascripts/monitoring/graph_spec.js41
-rw-r--r--spec/javascripts/monitoring/mock_data.js54
-rw-r--r--spec/javascripts/monitoring/monitoring_store_spec.js36
-rw-r--r--spec/javascripts/monitoring/utils/multiple_time_series_spec.js2
-rw-r--r--spec/javascripts/new_branch_spec.js355
-rw-r--r--spec/javascripts/notebook/cells/code_spec.js4
-rw-r--r--spec/javascripts/notebook/cells/markdown_spec.js30
-rw-r--r--spec/javascripts/notebook/cells/output/html_sanitize_tests.js8
-rw-r--r--spec/javascripts/notebook/cells/output/html_spec.js2
-rw-r--r--spec/javascripts/notebook/cells/output/index_spec.js14
-rw-r--r--spec/javascripts/notebook/cells/prompt_spec.js4
-rw-r--r--spec/javascripts/notebook/index_spec.js10
-rw-r--r--spec/javascripts/notes/components/comment_form_spec.js12
-rw-r--r--spec/javascripts/notes/components/diff_with_note_spec.js10
-rw-r--r--spec/javascripts/notes/components/discussion_filter_spec.js86
-rw-r--r--spec/javascripts/notes/components/note_actions_spec.js2
-rw-r--r--spec/javascripts/notes/components/note_app_spec.js9
-rw-r--r--spec/javascripts/notes/components/note_form_spec.js2
-rw-r--r--spec/javascripts/notes/components/noteable_discussion_spec.js78
-rw-r--r--spec/javascripts/notes/components/noteable_note_spec.js1
-rw-r--r--spec/javascripts/notes/components/toggle_replies_widget_spec.js78
-rw-r--r--spec/javascripts/notes/helpers.js2
-rw-r--r--spec/javascripts/notes/mock_data.js39
-rw-r--r--spec/javascripts/notes/stores/actions_spec.js76
-rw-r--r--spec/javascripts/notes/stores/collapse_utils_spec.js13
-rw-r--r--spec/javascripts/notes/stores/getters_spec.js27
-rw-r--r--spec/javascripts/notes/stores/mutation_spec.js74
-rw-r--r--spec/javascripts/notes_spec.js1593
-rw-r--r--spec/javascripts/oauth_remember_me_spec.js9
-rw-r--r--spec/javascripts/pager_spec.js5
-rw-r--r--spec/javascripts/pages/admin/abuse_reports/abuse_reports_spec.js14
-rw-r--r--spec/javascripts/pages/admin/application_settings/account_and_limits_spec.js9
-rw-r--r--spec/javascripts/pages/admin/jobs/index/components/stop_jobs_modal_spec.js20
-rw-r--r--spec/javascripts/pages/admin/users/new/index_spec.js4
-rw-r--r--spec/javascripts/pages/labels/components/promote_label_modal_spec.js36
-rw-r--r--spec/javascripts/pages/milestones/shared/components/delete_milestone_modal_spec.js43
-rw-r--r--spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js36
-rw-r--r--spec/javascripts/pages/profiles/show/emoji_menu_spec.js2
-rw-r--r--spec/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js74
-rw-r--r--spec/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js8
-rw-r--r--spec/javascripts/pdf/index_spec.js6
-rw-r--r--spec/javascripts/pdf/page_spec.js1
-rw-r--r--spec/javascripts/performance_bar/components/detailed_metric_spec.js10
-rw-r--r--spec/javascripts/performance_bar/components/request_selector_spec.js3
-rw-r--r--spec/javascripts/performance_bar/index_spec.js5
-rw-r--r--spec/javascripts/performance_bar/services/performance_bar_service_spec.js37
-rw-r--r--spec/javascripts/pipelines/blank_state_spec.js14
-rw-r--r--spec/javascripts/pipelines/empty_state_spec.js27
-rw-r--r--spec/javascripts/pipelines/graph/action_component_spec.js18
-rw-r--r--spec/javascripts/pipelines/graph/dropdown_job_component_spec.js85
-rw-r--r--spec/javascripts/pipelines/graph/graph_component_spec.js8
-rw-r--r--spec/javascripts/pipelines/graph/job_component_spec.js164
-rw-r--r--spec/javascripts/pipelines/graph/job_group_dropdown_spec.js85
-rw-r--r--spec/javascripts/pipelines/graph/job_item_spec.js155
-rw-r--r--spec/javascripts/pipelines/graph/stage_column_component_spec.js17
-rw-r--r--spec/javascripts/pipelines/header_component_spec.js9
-rw-r--r--spec/javascripts/pipelines/nav_controls_spec.js12
-rw-r--r--spec/javascripts/pipelines/pipeline_store_spec.js1
-rw-r--r--spec/javascripts/pipelines/pipeline_url_spec.js8
-rw-r--r--spec/javascripts/pipelines/pipelines_actions_spec.js110
-rw-r--r--spec/javascripts/pipelines/pipelines_artifacts_spec.js16
-rw-r--r--spec/javascripts/pipelines/pipelines_spec.js204
-rw-r--r--spec/javascripts/pipelines/pipelines_store_spec.js5
-rw-r--r--spec/javascripts/pipelines/pipelines_table_row_spec.js22
-rw-r--r--spec/javascripts/pipelines/pipelines_table_spec.js20
-rw-r--r--spec/javascripts/pipelines/stage_spec.js16
-rw-r--r--spec/javascripts/pipelines_spec.js4
-rw-r--r--spec/javascripts/polyfills/element_spec.js2
-rw-r--r--spec/javascripts/pretty_time_spec.js133
-rw-r--r--spec/javascripts/profile/account/components/delete_account_modal_spec.js16
-rw-r--r--spec/javascripts/profile/account/components/update_username_spec.js7
-rw-r--r--spec/javascripts/project_select_combo_button_spec.js56
-rw-r--r--spec/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown_spec.js22
-rw-r--r--spec/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown_spec.js62
-rw-r--r--spec/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown_spec.js22
-rw-r--r--spec/javascripts/projects/project_new_spec.js5
-rw-r--r--spec/javascripts/prometheus_metrics/prometheus_metrics_spec.js18
-rw-r--r--spec/javascripts/raven/raven_config_spec.js2
-rw-r--r--spec/javascripts/registry/components/app_spec.js53
-rw-r--r--spec/javascripts/registry/components/collapsible_container_spec.js16
-rw-r--r--spec/javascripts/registry/components/table_registry_spec.js14
-rw-r--r--spec/javascripts/registry/getters_spec.js41
-rw-r--r--spec/javascripts/registry/mock_data.js3
-rw-r--r--spec/javascripts/registry/stores/mutations_spec.js4
-rw-r--r--spec/javascripts/reports/components/grouped_test_reports_app_spec.js8
-rw-r--r--spec/javascripts/reports/components/modal_spec.js17
-rw-r--r--spec/javascripts/reports/components/report_link_spec.js6
-rw-r--r--spec/javascripts/reports/components/report_section_spec.js5
-rw-r--r--spec/javascripts/reports/components/test_issue_body_spec.js1
-rw-r--r--spec/javascripts/reports/store/mutations_spec.js2
-rw-r--r--spec/javascripts/right_sidebar_spec.js169
-rw-r--r--spec/javascripts/search_autocomplete_spec.js23
-rw-r--r--spec/javascripts/search_spec.js10
-rw-r--r--spec/javascripts/settings_panels_spec.js30
-rw-r--r--spec/javascripts/shared/popover_spec.js34
-rw-r--r--spec/javascripts/sidebar/assignees_spec.js94
-rw-r--r--spec/javascripts/sidebar/components/time_tracking/time_tracker_spec.js48
-rw-r--r--spec/javascripts/sidebar/confidential_edit_buttons_spec.js12
-rw-r--r--spec/javascripts/sidebar/confidential_edit_form_buttons_spec.js12
-rw-r--r--spec/javascripts/sidebar/confidential_issue_sidebar_spec.js32
-rw-r--r--spec/javascripts/sidebar/lock/edit_form_buttons_spec.js12
-rw-r--r--spec/javascripts/sidebar/lock/edit_form_spec.js12
-rw-r--r--spec/javascripts/sidebar/lock/lock_issue_sidebar_spec.js28
-rw-r--r--spec/javascripts/sidebar/participants_spec.js17
-rw-r--r--spec/javascripts/sidebar/sidebar_assignees_spec.js16
-rw-r--r--spec/javascripts/sidebar/sidebar_mediator_spec.js33
-rw-r--r--spec/javascripts/sidebar/sidebar_move_issue_spec.js24
-rw-r--r--spec/javascripts/sidebar/sidebar_store_spec.js18
-rw-r--r--spec/javascripts/sidebar/sidebar_subscriptions_spec.js2
-rw-r--r--spec/javascripts/sidebar/subscriptions_spec.js16
-rw-r--r--spec/javascripts/sidebar/todo_spec.js15
-rw-r--r--spec/javascripts/signin_tabs_memoizer_spec.js240
-rw-r--r--spec/javascripts/smart_interval_spec.js43
-rw-r--r--spec/javascripts/syntax_highlight_spec.js27
-rw-r--r--spec/javascripts/todos_spec.js4
-rw-r--r--spec/javascripts/toggle_buttons_spec.js18
-rw-r--r--spec/javascripts/u2f/authenticate_spec.js36
-rw-r--r--spec/javascripts/u2f/mock_u2f_device.js14
-rw-r--r--spec/javascripts/u2f/register_spec.js29
-rw-r--r--spec/javascripts/u2f/util_spec.js32
-rw-r--r--spec/javascripts/version_check_image_spec.js14
-rw-r--r--spec/javascripts/vue_mr_widget/components/deployment_spec.js213
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_author_spec.js10
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_author_time_spec.js8
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_container_spec.js51
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js25
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_icon_spec.js30
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_memory_usage_spec.js55
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_merge_help_spec.js32
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js90
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js79
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_rebase_spec.js20
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_related_links_spec.js5
-rw-r--r--spec/javascripts/vue_mr_widget/components/mr_widget_status_icon_spec.js4
-rw-r--r--spec/javascripts/vue_mr_widget/components/review_app_link_spec.js38
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_archived_spec.js6
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js6
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_checking_spec.js4
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_closed_spec.js55
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js10
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js2
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js56
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js60
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_merging_spec.js27
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js3
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_not_allowed_spec.js4
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_nothing_to_merge_spec.js9
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js6
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js6
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js136
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js6
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js18
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_wip_spec.js26
-rw-r--r--spec/javascripts/vue_mr_widget/mock_data.js17
-rw-r--r--spec/javascripts/vue_mr_widget/mr_widget_options_spec.js297
-rw-r--r--spec/javascripts/vue_mr_widget/stores/get_state_key_spec.js14
-rw-r--r--spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js10
-rw-r--r--spec/javascripts/vue_shared/components/bar_chart_spec.js6
-rw-r--r--spec/javascripts/vue_shared/components/changed_file_icon_spec.js46
-rw-r--r--spec/javascripts/vue_shared/components/ci_badge_link_spec.js6
-rw-r--r--spec/javascripts/vue_shared/components/clipboard_button_spec.js3
-rw-r--r--spec/javascripts/vue_shared/components/commit_spec.js7
-rw-r--r--spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/deprecated_modal_spec.js12
-rw-r--r--spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js5
-rw-r--r--spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js38
-rw-r--r--spec/javascripts/vue_shared/components/dropdown/dropdown_button_spec.js10
-rw-r--r--spec/javascripts/vue_shared/components/expand_button_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/file_icon_spec.js18
-rw-r--r--spec/javascripts/vue_shared/components/file_row_spec.js36
-rw-r--r--spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js91
-rw-r--r--spec/javascripts/vue_shared/components/gl_countdown_spec.js77
-rw-r--r--spec/javascripts/vue_shared/components/gl_modal_spec.js7
-rw-r--r--spec/javascripts/vue_shared/components/header_ci_component_spec.js12
-rw-r--r--spec/javascripts/vue_shared/components/icon_spec.js17
-rw-r--r--spec/javascripts/vue_shared/components/identicon_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/issue/issue_warning_spec.js17
-rw-r--r--spec/javascripts/vue_shared/components/loading_button_spec.js4
-rw-r--r--spec/javascripts/vue_shared/components/markdown/field_spec.js81
-rw-r--r--spec/javascripts/vue_shared/components/markdown/header_spec.js32
-rw-r--r--spec/javascripts/vue_shared/components/markdown/toolbar_spec.js9
-rw-r--r--spec/javascripts/vue_shared/components/memory_graph_spec.js16
-rw-r--r--spec/javascripts/vue_shared/components/navigation_tabs_spec.js5
-rw-r--r--spec/javascripts/vue_shared/components/notes/placeholder_note_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/notes/placeholder_system_note_spec.js4
-rw-r--r--spec/javascripts/vue_shared/components/notes/timeline_entry_item_spec.js40
-rw-r--r--spec/javascripts/vue_shared/components/pagination_links_spec.js35
-rw-r--r--spec/javascripts/vue_shared/components/panel_resizer_spec.js27
-rw-r--r--spec/javascripts/vue_shared/components/pikaday_spec.js1
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js1
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js34
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/date_picker_spec.js16
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/base_spec.js7
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js4
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js22
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js12
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js6
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js5
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js1
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js8
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js23
-rw-r--r--spec/javascripts/vue_shared/components/skeleton_loading_container_spec.js49
-rw-r--r--spec/javascripts/vue_shared/components/smart_virtual_list_spec.js83
-rw-r--r--spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js23
-rw-r--r--spec/javascripts/vue_shared/components/table_pagination_spec.js27
-rw-r--r--spec/javascripts/vue_shared/components/time_ago_tooltip_spec.js18
-rw-r--r--spec/javascripts/vue_shared/components/toggle_button_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/tooltip_on_truncate_spec.js16
-rw-r--r--spec/javascripts/vue_shared/components/user_avatar/user_avatar_image_spec.js57
-rw-r--r--spec/javascripts/vue_shared/components/user_avatar/user_avatar_link_spec.js59
-rw-r--r--spec/javascripts/vue_shared/components/user_avatar/user_avatar_svg_spec.js10
-rw-r--r--spec/javascripts/vue_shared/directives/tooltip_spec.js45
-rw-r--r--spec/javascripts/zen_mode_spec.js7
-rw-r--r--spec/lib/api/helpers/custom_validators_spec.rb64
-rw-r--r--spec/lib/backup/manager_spec.rb4
-rw-r--r--spec/lib/backup/repository_spec.rb4
-rw-r--r--spec/lib/banzai/cross_project_reference_spec.rb19
-rw-r--r--spec/lib/banzai/filter/absolute_link_filter_spec.rb2
-rw-r--r--spec/lib/banzai/filter/autolink_filter_spec.rb2
-rw-r--r--spec/lib/banzai/filter/commit_range_reference_filter_spec.rb1
-rw-r--r--spec/lib/banzai/filter/external_issue_reference_filter_spec.rb34
-rw-r--r--spec/lib/banzai/filter/relative_link_filter_spec.rb7
-rw-r--r--spec/lib/banzai/pipeline/gfm_pipeline_spec.rb12
-rw-r--r--spec/lib/banzai/reference_parser/base_parser_spec.rb3
-rw-r--r--spec/lib/banzai/reference_parser/commit_parser_spec.rb18
-rw-r--r--spec/lib/bitbucket_server/client_spec.rb12
-rw-r--r--spec/lib/bitbucket_server/collection_spec.rb29
-rw-r--r--spec/lib/bitbucket_server/paginator_spec.rb10
-rw-r--r--spec/lib/container_registry/blob_spec.rb2
-rw-r--r--spec/lib/event_filter_spec.rb131
-rw-r--r--spec/lib/extracts_path_spec.rb26
-rw-r--r--spec/lib/feature_spec.rb20
-rw-r--r--spec/lib/gitaly/server_spec.rb8
-rw-r--r--spec/lib/gitlab/auth/o_auth/user_spec.rb2
-rw-r--r--spec/lib/gitlab/auth/request_authenticator_spec.rb18
-rw-r--r--spec/lib/gitlab/auth/saml/auth_hash_spec.rb11
-rw-r--r--spec/lib/gitlab/auth/user_auth_finders_spec.rb94
-rw-r--r--spec/lib/gitlab/background_migration/backfill_project_fullpath_in_repo_config_spec.rb85
-rw-r--r--spec/lib/gitlab/background_migration/create_fork_network_memberships_range_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb8
-rw-r--r--spec/lib/gitlab/background_migration/digest_column_spec.rb46
-rw-r--r--spec/lib/gitlab/background_migration/encrypt_columns_spec.rb94
-rw-r--r--spec/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table_spec.rb97
-rw-r--r--spec/lib/gitlab/background_migration/populate_external_pipeline_source_spec.rb62
-rw-r--r--spec/lib/gitlab/background_migration/redact_links_spec.rb96
-rw-r--r--spec/lib/gitlab/bitbucket_import/project_creator_spec.rb4
-rw-r--r--spec/lib/gitlab/blob_helper_spec.rb125
-rw-r--r--spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb120
-rw-r--r--spec/lib/gitlab/checks/branch_check_spec.rb90
-rw-r--r--spec/lib/gitlab/checks/change_access_spec.rb225
-rw-r--r--spec/lib/gitlab/checks/diff_check_spec.rb51
-rw-r--r--spec/lib/gitlab/checks/lfs_check_spec.rb52
-rw-r--r--spec/lib/gitlab/checks/lfs_integrity_spec.rb5
-rw-r--r--spec/lib/gitlab/checks/push_check_spec.rb22
-rw-r--r--spec/lib/gitlab/checks/tag_check_spec.rb64
-rw-r--r--spec/lib/gitlab/checks/timed_logger_spec.rb63
-rw-r--r--spec/lib/gitlab/ci/ansi2html_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/build/artifacts/adapters/gzip_stream_spec.rb56
-rw-r--r--spec/lib/gitlab/ci/build/artifacts/adapters/raw_stream_spec.rb47
-rw-r--r--spec/lib/gitlab/ci/build/artifacts/gzip_file_adapter_spec.rb56
-rw-r--r--spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb30
-rw-r--r--spec/lib/gitlab/ci/build/policy/changes_spec.rb119
-rw-r--r--spec/lib/gitlab/ci/build/policy/refs_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/build/policy/variables_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/config/entry/artifacts_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/entry/attributable_spec.rb60
-rw-r--r--spec/lib/gitlab/ci/config/entry/boolean_spec.rb34
-rw-r--r--spec/lib/gitlab/ci/config/entry/configurable_spec.rb53
-rw-r--r--spec/lib/gitlab/ci/config/entry/factory_spec.rb87
-rw-r--r--spec/lib/gitlab/ci/config/entry/global_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/entry/job_spec.rb102
-rw-r--r--spec/lib/gitlab/ci/config/entry/policy_spec.rb22
-rw-r--r--spec/lib/gitlab/ci/config/entry/reports_spec.rb63
-rw-r--r--spec/lib/gitlab/ci/config/entry/retry_spec.rb236
-rw-r--r--spec/lib/gitlab/ci/config/entry/simplifiable_spec.rb88
-rw-r--r--spec/lib/gitlab/ci/config/entry/undefined_spec.rb41
-rw-r--r--spec/lib/gitlab/ci/config/entry/unspecified_spec.rb32
-rw-r--r--spec/lib/gitlab/ci/config/entry/validatable_spec.rb54
-rw-r--r--spec/lib/gitlab/ci/config/entry/validator_spec.rb55
-rw-r--r--spec/lib/gitlab/ci/config/external/file/base_spec.rb52
-rw-r--r--spec/lib/gitlab/ci/config/external/file/local_spec.rb78
-rw-r--r--spec/lib/gitlab/ci/config/external/file/remote_spec.rb157
-rw-r--r--spec/lib/gitlab/ci/config/external/mapper_spec.rb98
-rw-r--r--spec/lib/gitlab/ci/config/external/processor_spec.rb190
-rw-r--r--spec/lib/gitlab/ci/config/loader_spec.rb60
-rw-r--r--spec/lib/gitlab/ci/config/normalizer_spec.rb66
-rw-r--r--spec/lib/gitlab/ci/config_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/external/file/local_spec.rb78
-rw-r--r--spec/lib/gitlab/ci/external/file/remote_spec.rb114
-rw-r--r--spec/lib/gitlab/ci/external/mapper_spec.rb96
-rw-r--r--spec/lib/gitlab/ci/external/processor_spec.rb182
-rw-r--r--spec/lib/gitlab/ci/parsers/junit_spec.rb172
-rw-r--r--spec/lib/gitlab/ci/parsers/test/junit_spec.rb172
-rw-r--r--spec/lib/gitlab/ci/parsers/test_spec.rb23
-rw-r--r--spec/lib/gitlab/ci/parsers_spec.rb23
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexeme/string_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/status/build/factory_spec.rb49
-rw-r--r--spec/lib/gitlab/ci/status/build/scheduled_spec.rb44
-rw-r--r--spec/lib/gitlab/ci/status/build/unschedule_spec.rb94
-rw-r--r--spec/lib/gitlab/ci/status/pipeline/delayed_spec.rb42
-rw-r--r--spec/lib/gitlab/ci/status/pipeline/factory_spec.rb24
-rw-r--r--spec/lib/gitlab/ci/status/scheduled_spec.rb27
-rw-r--r--spec/lib/gitlab/ci/templates/templates_spec.rb11
-rw-r--r--spec/lib/gitlab/ci/trace/chunked_io_spec.rb63
-rw-r--r--spec/lib/gitlab/ci/trace/stream_spec.rb25
-rw-r--r--spec/lib/gitlab/ci/variables/collection/item_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb70
-rw-r--r--spec/lib/gitlab/config/entry/attributable_spec.rb60
-rw-r--r--spec/lib/gitlab/config/entry/boolean_spec.rb34
-rw-r--r--spec/lib/gitlab/config/entry/configurable_spec.rb53
-rw-r--r--spec/lib/gitlab/config/entry/factory_spec.rb95
-rw-r--r--spec/lib/gitlab/config/entry/simplifiable_spec.rb88
-rw-r--r--spec/lib/gitlab/config/entry/undefined_spec.rb41
-rw-r--r--spec/lib/gitlab/config/entry/unspecified_spec.rb32
-rw-r--r--spec/lib/gitlab/config/entry/validatable_spec.rb54
-rw-r--r--spec/lib/gitlab/config/entry/validator_spec.rb55
-rw-r--r--spec/lib/gitlab/config/loader/yaml_spec.rb60
-rw-r--r--spec/lib/gitlab/conflict/file_spec.rb9
-rw-r--r--spec/lib/gitlab/contributions_calendar_spec.rb2
-rw-r--r--spec/lib/gitlab/cross_project_access/check_info_spec.rb4
-rw-r--r--spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb6
-rw-r--r--spec/lib/gitlab/data_builder/pipeline_spec.rb47
-rw-r--r--spec/lib/gitlab/database/count/exact_count_strategy_spec.rb34
-rw-r--r--spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb48
-rw-r--r--spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb65
-rw-r--r--spec/lib/gitlab/database/count_spec.rb72
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb7
-rw-r--r--spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb2
-rw-r--r--spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb2
-rw-r--r--spec/lib/gitlab/database_spec.rb22
-rw-r--r--spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb14
-rw-r--r--spec/lib/gitlab/diff/file_spec.rb46
-rw-r--r--spec/lib/gitlab/diff/highlight_spec.rb28
-rw-r--r--spec/lib/gitlab/diff/inline_diff_marker_spec.rb2
-rw-r--r--spec/lib/gitlab/diff/lines_unfolder_spec.rb750
-rw-r--r--spec/lib/gitlab/diff/position_spec.rb92
-rw-r--r--spec/lib/gitlab/diff/position_tracer_spec.rb2
-rw-r--r--spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb69
-rw-r--r--spec/lib/gitlab/email/reply_parser_spec.rb2
-rw-r--r--spec/lib/gitlab/exclusive_lease_helpers_spec.rb8
-rw-r--r--spec/lib/gitlab/favicon_spec.rb1
-rw-r--r--spec/lib/gitlab/file_detector_spec.rb19
-rw-r--r--spec/lib/gitlab/git/attributes_at_ref_parser_spec.rb2
-rw-r--r--spec/lib/gitlab/git/attributes_parser_spec.rb4
-rw-r--r--spec/lib/gitlab/git/blob_snippet_spec.rb19
-rw-r--r--spec/lib/gitlab/git/blob_spec.rb29
-rw-r--r--spec/lib/gitlab/git/branch_spec.rb8
-rw-r--r--spec/lib/gitlab/git/commit_spec.rb233
-rw-r--r--spec/lib/gitlab/git/diff_spec.rb61
-rw-r--r--spec/lib/gitlab/git/diff_stats_collection_spec.rb8
-rw-r--r--spec/lib/gitlab/git/hook_env_spec.rb20
-rw-r--r--spec/lib/gitlab/git/lfs_changes_spec.rb4
-rw-r--r--spec/lib/gitlab/git/merge_base_spec.rb2
-rw-r--r--spec/lib/gitlab/git/patches/collection_spec.rb28
-rw-r--r--spec/lib/gitlab/git/patches/commit_patches_spec.rb49
-rw-r--r--spec/lib/gitlab/git/patches/patch_spec.rb16
-rw-r--r--spec/lib/gitlab/git/push_spec.rb166
-rw-r--r--spec/lib/gitlab/git/remote_mirror_spec.rb28
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb290
-rw-r--r--spec/lib/gitlab/git/storage/checker_spec.rb132
-rw-r--r--spec/lib/gitlab/git/storage/circuit_breaker_spec.rb187
-rw-r--r--spec/lib/gitlab/git/storage/failure_info_spec.rb70
-rw-r--r--spec/lib/gitlab/git/storage/forked_storage_check_spec.rb73
-rw-r--r--spec/lib/gitlab/git/storage/health_spec.rb58
-rw-r--r--spec/lib/gitlab/git/storage/null_circuit_breaker_spec.rb70
-rw-r--r--spec/lib/gitlab/git/tag_spec.rb33
-rw-r--r--spec/lib/gitlab/git/tree_spec.rb14
-rw-r--r--spec/lib/gitlab/git/wiki_spec.rb47
-rw-r--r--spec/lib/gitlab/git/wraps_gitaly_errors_spec.rb28
-rw-r--r--spec/lib/gitlab/git_access_spec.rb39
-rw-r--r--spec/lib/gitlab/git_ref_validator_spec.rb1
-rw-r--r--spec/lib/gitlab/gitaly_client/operation_service_spec.rb33
-rw-r--r--spec/lib/gitlab/gitaly_client/remote_service_spec.rb4
-rw-r--r--spec/lib/gitlab/gitaly_client/repository_service_spec.rb61
-rw-r--r--spec/lib/gitlab/gitaly_client/wiki_service_spec.rb4
-rw-r--r--spec/lib/gitlab/gitaly_client_spec.rb126
-rw-r--r--spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb7
-rw-r--r--spec/lib/gitlab/github_import/importer/repository_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/parallel_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/gon_helper_spec.rb32
-rw-r--r--spec/lib/gitlab/gpg_spec.rb4
-rw-r--r--spec/lib/gitlab/graphql/loaders/batch_model_loader_spec.rb28
-rw-r--r--spec/lib/gitlab/highlight_spec.rb100
-rw-r--r--spec/lib/gitlab/hook_data/base_builder_spec.rb129
-rw-r--r--spec/lib/gitlab/hook_data/issue_builder_spec.rb5
-rw-r--r--spec/lib/gitlab/hook_data/merge_request_builder_spec.rb7
-rw-r--r--spec/lib/gitlab/http_spec.rb26
-rw-r--r--spec/lib/gitlab/identifier_spec.rb49
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml9
-rw-r--r--spec/lib/gitlab/import_export/attribute_configuration_spec.rb15
-rw-r--r--spec/lib/gitlab/import_export/project.json14
-rw-r--r--spec/lib/gitlab/import_export/project.light.json22
-rw-r--r--spec/lib/gitlab/import_export/project_tree_restorer_spec.rb19
-rw-r--r--spec/lib/gitlab/import_export/relation_factory_spec.rb4
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml2
-rw-r--r--spec/lib/gitlab/kubernetes/helm/api_spec.rb114
-rw-r--r--spec/lib/gitlab/kubernetes/helm/init_command_spec.rb4
-rw-r--r--spec/lib/gitlab/kubernetes/helm/install_command_spec.rb87
-rw-r--r--spec/lib/gitlab/kubernetes/helm/pod_spec.rb2
-rw-r--r--spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb140
-rw-r--r--spec/lib/gitlab/kubernetes/kube_client_spec.rb123
-rw-r--r--spec/lib/gitlab/kubernetes/namespace_spec.rb2
-rw-r--r--spec/lib/gitlab/kubernetes/role_binding_spec.rb48
-rw-r--r--spec/lib/gitlab/language_data_spec.rb22
-rw-r--r--spec/lib/gitlab/legacy_github_import/importer_spec.rb2
-rw-r--r--spec/lib/gitlab/multi_collection_paginator_spec.rb2
-rw-r--r--spec/lib/gitlab/null_request_store_spec.rb75
-rw-r--r--spec/lib/gitlab/patch/draw_route_spec.rb30
-rw-r--r--spec/lib/gitlab/private_commit_email_spec.rb51
-rw-r--r--spec/lib/gitlab/profiler_spec.rb42
-rw-r--r--spec/lib/gitlab/prometheus/query_variables_spec.rb33
-rw-r--r--spec/lib/gitlab/quick_actions/command_definition_spec.rb13
-rw-r--r--spec/lib/gitlab/quick_actions/dsl_spec.rb8
-rw-r--r--spec/lib/gitlab/quick_actions/extractor_spec.rb19
-rw-r--r--spec/lib/gitlab/repository_cache_adapter_spec.rb138
-rw-r--r--spec/lib/gitlab/repository_cache_spec.rb97
-rw-r--r--spec/lib/gitlab/safe_request_store_spec.rb245
-rw-r--r--spec/lib/gitlab/sentry_spec.rb24
-rw-r--r--spec/lib/gitlab/shell_spec.rb120
-rw-r--r--spec/lib/gitlab/sidekiq_throttler_spec.rb44
-rw-r--r--spec/lib/gitlab/slash_commands/command_spec.rb2
-rw-r--r--spec/lib/gitlab/slash_commands/deploy_spec.rb2
-rw-r--r--spec/lib/gitlab/storage_check/cli_spec.rb19
-rw-r--r--spec/lib/gitlab/storage_check/gitlab_caller_spec.rb46
-rw-r--r--spec/lib/gitlab/storage_check/option_parser_spec.rb31
-rw-r--r--spec/lib/gitlab/storage_check/response_spec.rb54
-rw-r--r--spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb2
-rw-r--r--spec/lib/gitlab/url_blocker_spec.rb136
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb21
-rw-r--r--spec/lib/gitlab/utils_spec.rb23
-rw-r--r--spec/lib/gitlab/version_info_spec.rb3
-rw-r--r--spec/lib/gitlab/view/presenter/base_spec.rb2
-rw-r--r--spec/lib/gitlab/web_ide_commits_counter_spec.rb19
-rw-r--r--spec/lib/json_web_token/hmac_token_spec.rb133
-rw-r--r--spec/lib/microsoft_teams/notifier_spec.rb2
-rw-r--r--spec/lib/quality/helm_client_spec.rb111
-rw-r--r--spec/lib/quality/kubernetes_client_spec.rb33
-rw-r--r--spec/mailers/notify_spec.rb2
-rw-r--r--spec/migrations/add_pages_access_level_to_project_feature_spec.rb30
-rw-r--r--spec/migrations/backfill_store_project_full_path_in_repo_spec.rb98
-rw-r--r--spec/migrations/clean_up_for_members_spec.rb5
-rw-r--r--spec/migrations/cleanup_environments_external_url_spec.rb28
-rw-r--r--spec/migrations/delete_inconsistent_internal_id_records_spec.rb30
-rw-r--r--spec/migrations/enqueue_redact_links_spec.rb42
-rw-r--r--spec/migrations/fill_empty_finished_at_in_deployments_spec.rb70
-rw-r--r--spec/migrations/migrate_forbidden_redirect_uris_spec.rb48
-rw-r--r--spec/migrations/migrate_issues_to_ghost_user_spec.rb12
-rw-r--r--spec/migrations/migrate_old_artifacts_spec.rb2
-rw-r--r--spec/migrations/rename_more_reserved_project_names_spec.rb11
-rw-r--r--spec/migrations/rename_reserved_project_names_spec.rb11
-rw-r--r--spec/migrations/schedule_digest_personal_access_tokens_spec.rb46
-rw-r--r--spec/migrations/steal_fill_store_upload_spec.rb40
-rw-r--r--spec/models/application_setting_spec.rb59
-rw-r--r--spec/models/blob_spec.rb21
-rw-r--r--spec/models/blob_viewer/package_json_spec.rb21
-rw-r--r--spec/models/board_group_recent_visit_spec.rb64
-rw-r--r--spec/models/board_project_recent_visit_spec.rb64
-rw-r--r--spec/models/ci/build_metadata_spec.rb2
-rw-r--r--spec/models/ci/build_spec.rb969
-rw-r--r--spec/models/ci/build_trace_chunk_spec.rb128
-rw-r--r--spec/models/ci/job_artifact_spec.rb72
-rw-r--r--spec/models/ci/pipeline_spec.rb161
-rw-r--r--spec/models/ci/pipeline_variable_spec.rb9
-rw-r--r--spec/models/ci/runner_spec.rb2
-rw-r--r--spec/models/ci/stage_spec.rb26
-rw-r--r--spec/models/clusters/applications/cert_manager_spec.rb79
-rw-r--r--spec/models/clusters/applications/ingress_spec.rb28
-rw-r--r--spec/models/clusters/applications/jupyter_spec.rb31
-rw-r--r--spec/models/clusters/applications/knative_spec.rb124
-rw-r--r--spec/models/clusters/applications/prometheus_spec.rb38
-rw-r--r--spec/models/clusters/applications/runner_spec.rb34
-rw-r--r--spec/models/clusters/cluster_spec.rb107
-rw-r--r--spec/models/clusters/group_spec.rb8
-rw-r--r--spec/models/clusters/kubernetes_namespace_spec.rb123
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb208
-rw-r--r--spec/models/clusters/project_spec.rb2
-rw-r--r--spec/models/commit_spec.rb34
-rw-r--r--spec/models/commit_status_spec.rb22
-rw-r--r--spec/models/compare_spec.rb29
-rw-r--r--spec/models/concerns/awardable_spec.rb18
-rw-r--r--spec/models/concerns/blob_language_from_git_attributes_spec.rb25
-rw-r--r--spec/models/concerns/cache_markdown_field_spec.rb5
-rw-r--r--spec/models/concerns/cacheable_attributes_spec.rb4
-rw-r--r--spec/models/concerns/deployable_spec.rb74
-rw-r--r--spec/models/concerns/each_batch_spec.rb51
-rw-r--r--spec/models/concerns/has_status_spec.rb52
-rw-r--r--spec/models/concerns/issuable_spec.rb4
-rw-r--r--spec/models/concerns/redactable_spec.rb69
-rw-r--r--spec/models/concerns/relative_positioning_spec.rb42
-rw-r--r--spec/models/concerns/token_authenticatable_spec.rb272
-rw-r--r--spec/models/deployment_spec.rb217
-rw-r--r--spec/models/environment_spec.rb146
-rw-r--r--spec/models/environment_status_spec.rb194
-rw-r--r--spec/models/event_collection_spec.rb2
-rw-r--r--spec/models/event_spec.rb124
-rw-r--r--spec/models/forked_project_link_spec.rb68
-rw-r--r--spec/models/global_milestone_spec.rb35
-rw-r--r--spec/models/gpg_signature_spec.rb2
-rw-r--r--spec/models/group_spec.rb60
-rw-r--r--spec/models/hooks/web_hook_spec.rb6
-rw-r--r--spec/models/instance_configuration_spec.rb6
-rw-r--r--spec/models/internal_id_spec.rb5
-rw-r--r--spec/models/issue_spec.rb68
-rw-r--r--spec/models/label_spec.rb36
-rw-r--r--spec/models/lfs_object_spec.rb21
-rw-r--r--spec/models/license_template_spec.rb2
-rw-r--r--spec/models/list_spec.rb6
-rw-r--r--spec/models/merge_request_diff_spec.rb46
-rw-r--r--spec/models/merge_request_spec.rb176
-rw-r--r--spec/models/milestone_spec.rb37
-rw-r--r--spec/models/namespace_spec.rb40
-rw-r--r--spec/models/note_spec.rb93
-rw-r--r--spec/models/notification_setting_spec.rb2
-rw-r--r--spec/models/personal_access_token_spec.rb28
-rw-r--r--spec/models/pool_repository_spec.rb26
-rw-r--r--spec/models/postgresql/replication_slot_spec.rb20
-rw-r--r--spec/models/project_auto_devops_spec.rb29
-rw-r--r--spec/models/project_feature_spec.rb73
-rw-r--r--spec/models/project_import_state_spec.rb112
-rw-r--r--spec/models/project_repository_spec.rb23
-rw-r--r--spec/models/project_services/bamboo_service_spec.rb3
-rw-r--r--spec/models/project_services/chat_message/push_message_spec.rb65
-rw-r--r--spec/models/project_services/discord_service_spec.rb11
-rw-r--r--spec/models/project_services/hangouts_chat_service_spec.rb249
-rw-r--r--spec/models/project_services/hipchat_service_spec.rb18
-rw-r--r--spec/models/project_services/kubernetes_service_spec.rb6
-rw-r--r--spec/models/project_services/prometheus_service_spec.rb40
-rw-r--r--spec/models/project_spec.rb758
-rw-r--r--spec/models/project_wiki_spec.rb250
-rw-r--r--spec/models/prometheus_metric_spec.rb2
-rw-r--r--spec/models/push_event_payload_spec.rb2
-rw-r--r--spec/models/remote_mirror_spec.rb28
-rw-r--r--spec/models/repository_spec.rb600
-rw-r--r--spec/models/resource_label_event_spec.rb2
-rw-r--r--spec/models/shard_spec.rb50
-rw-r--r--spec/models/site_statistic_spec.rb83
-rw-r--r--spec/models/snippet_spec.rb211
-rw-r--r--spec/models/ssh_host_key_spec.rb164
-rw-r--r--spec/models/todo_spec.rb126
-rw-r--r--spec/models/upload_spec.rb64
-rw-r--r--spec/models/user_callout_spec.rb2
-rw-r--r--spec/models/user_preference_spec.rb53
-rw-r--r--spec/models/user_spec.rb169
-rw-r--r--spec/models/wiki_page_spec.rb335
-rw-r--r--spec/policies/ci/pipeline_policy_spec.rb18
-rw-r--r--spec/policies/ci/pipeline_schedule_policy_spec.rb4
-rw-r--r--spec/policies/clusters/cluster_policy_spec.rb42
-rw-r--r--spec/policies/group_policy_spec.rb6
-rw-r--r--spec/policies/issue_policy_spec.rb2
-rw-r--r--spec/policies/note_policy_spec.rb79
-rw-r--r--spec/policies/project_policy_spec.rb6
-rw-r--r--spec/presenters/blob_presenter_spec.rb44
-rw-r--r--spec/presenters/ci/build_presenter_spec.rb38
-rw-r--r--spec/presenters/ci/build_runner_presenter_spec.rb53
-rw-r--r--spec/presenters/clusterable_presenter_spec.rb17
-rw-r--r--spec/presenters/clusters/cluster_presenter_spec.rb21
-rw-r--r--spec/presenters/group_clusterable_presenter_spec.rb77
-rw-r--r--spec/presenters/merge_request_presenter_spec.rb9
-rw-r--r--spec/presenters/project_clusterable_presenter_spec.rb77
-rw-r--r--spec/presenters/project_presenter_spec.rb33
-rw-r--r--spec/rack_servers/configs/config.ru12
-rw-r--r--spec/rack_servers/configs/puma.rb32
-rw-r--r--spec/rack_servers/puma_spec.rb84
-rw-r--r--spec/rack_servers/unicorn_spec.rb105
-rw-r--r--spec/requests/api/applications_spec.rb82
-rw-r--r--spec/requests/api/circuit_breakers_spec.rb19
-rw-r--r--spec/requests/api/commits_spec.rb214
-rw-r--r--spec/requests/api/deployments_spec.rb12
-rw-r--r--spec/requests/api/files_spec.rb8
-rw-r--r--spec/requests/api/graphql/project/issues_spec.rb59
-rw-r--r--spec/requests/api/groups_spec.rb42
-rw-r--r--spec/requests/api/helpers_spec.rb29
-rw-r--r--spec/requests/api/internal_spec.rb18
-rw-r--r--spec/requests/api/issues_spec.rb238
-rw-r--r--spec/requests/api/jobs_spec.rb2
-rw-r--r--spec/requests/api/markdown_spec.rb46
-rw-r--r--spec/requests/api/merge_requests_spec.rb85
-rw-r--r--spec/requests/api/namespaces_spec.rb2
-rw-r--r--spec/requests/api/pages/internal_access_spec.rb88
-rw-r--r--spec/requests/api/pages/private_access_spec.rb88
-rw-r--r--spec/requests/api/pages/public_access_spec.rb88
-rw-r--r--spec/requests/api/pipelines_spec.rb61
-rw-r--r--spec/requests/api/project_import_spec.rb10
-rw-r--r--spec/requests/api/project_templates_spec.rb145
-rw-r--r--spec/requests/api/projects_spec.rb40
-rw-r--r--spec/requests/api/redacted_events_spec.rb68
-rw-r--r--spec/requests/api/repositories_spec.rb10
-rw-r--r--spec/requests/api/runner_spec.rb42
-rw-r--r--spec/requests/api/runners_spec.rb221
-rw-r--r--spec/requests/api/settings_spec.rb25
-rw-r--r--spec/requests/api/snippets_spec.rb6
-rw-r--r--spec/requests/api/submodules_spec.rb99
-rw-r--r--spec/requests/api/users_spec.rb85
-rw-r--r--spec/requests/api/wikis_spec.rb10
-rw-r--r--spec/requests/git_http_spec.rb2
-rw-r--r--spec/routing/project_routing_spec.rb31
-rw-r--r--spec/routing/routing_spec.rb7
-rw-r--r--spec/rubocop/cop/group_public_or_visible_to_user_spec.rb28
-rw-r--r--spec/rubocop/cop/migration/add_reference_spec.rb12
-rw-r--r--spec/rubocop/cop/qa/element_with_pattern_spec.rb50
-rw-r--r--spec/rubocop/cop/safe_params_spec.rb39
-rw-r--r--spec/rubocop/qa_helpers_spec.rb37
-rw-r--r--spec/serializers/build_action_entity_spec.rb16
-rw-r--r--spec/serializers/commit_entity_spec.rb59
-rw-r--r--spec/serializers/deployment_entity_spec.rb22
-rw-r--r--spec/serializers/deployment_serializer_spec.rb35
-rw-r--r--spec/serializers/diff_file_entity_spec.rb5
-rw-r--r--spec/serializers/diff_line_entity_spec.rb45
-rw-r--r--spec/serializers/diff_viewer_entity_spec.rb19
-rw-r--r--spec/serializers/discussion_entity_spec.rb7
-rw-r--r--spec/serializers/environment_serializer_spec.rb3
-rw-r--r--spec/serializers/environment_status_entity_spec.rb79
-rw-r--r--spec/serializers/job_entity_spec.rb13
-rw-r--r--spec/serializers/merge_request_widget_entity_spec.rb42
-rw-r--r--spec/serializers/pipeline_details_entity_spec.rb2
-rw-r--r--spec/serializers/project_mirror_entity_spec.rb12
-rw-r--r--spec/serializers/remote_mirror_entity_spec.rb16
-rw-r--r--spec/services/application_settings/update_service_spec.rb3
-rw-r--r--spec/services/applications/create_service_spec.rb13
-rw-r--r--spec/services/audit_event_service_spec.rb26
-rw-r--r--spec/services/boards/visits/create_service_spec.rb53
-rw-r--r--spec/services/boards/visits/latest_service_spec.rb47
-rw-r--r--spec/services/ci/archive_trace_service_spec.rb51
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb126
-rw-r--r--spec/services/ci/destroy_pipeline_service_spec.rb60
-rw-r--r--spec/services/ci/enqueue_build_service_spec.rb16
-rw-r--r--spec/services/ci/process_build_service_spec.rb117
-rw-r--r--spec/services/ci/process_pipeline_service_spec.rb213
-rw-r--r--spec/services/ci/register_job_service_spec.rb14
-rw-r--r--spec/services/ci/retry_build_service_spec.rb25
-rw-r--r--spec/services/ci/run_scheduled_build_service_spec.rb62
-rw-r--r--spec/services/clusters/applications/check_ingress_ip_address_service_spec.rb38
-rw-r--r--spec/services/clusters/applications/check_installation_progress_service_spec.rb57
-rw-r--r--spec/services/clusters/applications/create_service_spec.rb130
-rw-r--r--spec/services/clusters/applications/install_service_spec.rb72
-rw-r--r--spec/services/clusters/applications/schedule_installation_service_spec.rb7
-rw-r--r--spec/services/clusters/create_service_spec.rb31
-rw-r--r--spec/services/clusters/gcp/fetch_operation_service_spec.rb2
-rw-r--r--spec/services/clusters/gcp/finalize_creation_service_spec.rb278
-rw-r--r--spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb115
-rw-r--r--spec/services/clusters/gcp/kubernetes/create_service_account_service_spec.rb212
-rw-r--r--spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb58
-rw-r--r--spec/services/clusters/gcp/provision_service_spec.rb2
-rw-r--r--spec/services/clusters/update_service_spec.rb36
-rw-r--r--spec/services/commits/commit_patch_service_spec.rb92
-rw-r--r--spec/services/create_deployment_service_spec.rb335
-rw-r--r--spec/services/files/multi_service_spec.rb75
-rw-r--r--spec/services/git_tag_push_service_spec.rb5
-rw-r--r--spec/services/groups/destroy_service_spec.rb8
-rw-r--r--spec/services/groups/transfer_service_spec.rb4
-rw-r--r--spec/services/groups/update_service_spec.rb6
-rw-r--r--spec/services/issuable/bulk_update_service_spec.rb2
-rw-r--r--spec/services/issuable/clone/attributes_rewriter_spec.rb79
-rw-r--r--spec/services/issuable/clone/content_rewriter_spec.rb153
-rw-r--r--spec/services/issues/move_service_spec.rb268
-rw-r--r--spec/services/issues/related_branches_service_spec.rb39
-rw-r--r--spec/services/issues/update_service_spec.rb48
-rw-r--r--spec/services/merge_requests/build_service_spec.rb42
-rw-r--r--spec/services/merge_requests/create_from_issue_service_spec.rb10
-rw-r--r--spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb2
-rw-r--r--spec/services/merge_requests/rebase_service_spec.rb2
-rw-r--r--spec/services/merge_requests/refresh_service_spec.rb60
-rw-r--r--spec/services/merge_requests/reload_diffs_service_spec.rb32
-rw-r--r--spec/services/merge_requests/squash_service_spec.rb6
-rw-r--r--spec/services/merge_requests/update_service_spec.rb50
-rw-r--r--spec/services/milestones/destroy_service_spec.rb2
-rw-r--r--spec/services/notes/build_service_spec.rb15
-rw-r--r--spec/services/notes/create_service_spec.rb51
-rw-r--r--spec/services/notes/destroy_service_spec.rb33
-rw-r--r--spec/services/notes/quick_actions_service_spec.rb2
-rw-r--r--spec/services/notification_recipient_service_spec.rb47
-rw-r--r--spec/services/notification_service_spec.rb160
-rw-r--r--spec/services/projects/after_import_service_spec.rb4
-rw-r--r--spec/services/projects/after_rename_service_spec.rb198
-rw-r--r--spec/services/projects/autocomplete_service_spec.rb4
-rw-r--r--spec/services/projects/create_from_template_service_spec.rb2
-rw-r--r--spec/services/projects/create_service_spec.rb17
-rw-r--r--spec/services/projects/destroy_service_spec.rb24
-rw-r--r--spec/services/projects/fork_service_spec.rb25
-rw-r--r--spec/services/projects/hashed_storage/migrate_repository_service_spec.rb6
-rw-r--r--spec/services/projects/import_service_spec.rb4
-rw-r--r--spec/services/projects/transfer_service_spec.rb8
-rw-r--r--spec/services/projects/unlink_fork_service_spec.rb9
-rw-r--r--spec/services/projects/update_remote_mirror_service_spec.rb44
-rw-r--r--spec/services/projects/update_service_spec.rb21
-rw-r--r--spec/services/quick_actions/interpret_service_spec.rb154
-rw-r--r--spec/services/resource_events/merge_into_notes_service_spec.rb9
-rw-r--r--spec/services/submodules/update_service_spec.rb212
-rw-r--r--spec/services/system_hooks_service_spec.rb2
-rw-r--r--spec/services/system_note_service_spec.rb16
-rw-r--r--spec/services/todo_service_spec.rb2
-rw-r--r--spec/services/update_deployment_service_spec.rb217
-rw-r--r--spec/services/users/build_service_spec.rb51
-rw-r--r--spec/services/users/set_status_service_spec.rb2
-rw-r--r--spec/services/web_hook_service_spec.rb2
-rw-r--r--spec/spec_helper.rb9
-rw-r--r--spec/support/active_record_enum.rb12
-rw-r--r--spec/support/capybara.rb2
-rw-r--r--spec/support/controllers/githubish_import_controller_shared_examples.rb12
-rw-r--r--spec/support/controllers/sessionless_auth_controller_shared_examples.rb92
-rw-r--r--spec/support/features/discussion_comments_shared_example.rb35
-rw-r--r--spec/support/features/issuable_quick_actions_shared_examples.rb9
-rw-r--r--spec/support/features/reportable_note_shared_examples.rb4
-rw-r--r--spec/support/features/variable_list_shared_examples.rb2
-rw-r--r--spec/support/gitaly.rb16
-rw-r--r--spec/support/helpers/ci_artifact_metadata_generator.rb48
-rw-r--r--spec/support/helpers/cycle_analytics_helpers.rb21
-rw-r--r--spec/support/helpers/devise_helpers.rb9
-rw-r--r--spec/support/helpers/features/branches_helpers.rb2
-rw-r--r--spec/support/helpers/features/sorting_helpers.rb2
-rw-r--r--spec/support/helpers/filter_item_select_helper.rb19
-rw-r--r--spec/support/helpers/filtered_search_helpers.rb8
-rw-r--r--spec/support/helpers/git_helpers.rb6
-rw-r--r--spec/support/helpers/git_http_helpers.rb5
-rw-r--r--spec/support/helpers/gpg_helpers.rb6
-rw-r--r--spec/support/helpers/kubernetes_helpers.rb40
-rw-r--r--spec/support/helpers/migrations_helpers.rb26
-rw-r--r--spec/support/helpers/project_forks_helper.rb4
-rw-r--r--spec/support/helpers/prometheus_helpers.rb4
-rw-r--r--spec/support/helpers/reference_parser_helpers.rb6
-rw-r--r--spec/support/helpers/seed_helper.rb20
-rw-r--r--spec/support/helpers/sorting_helper.rb2
-rw-r--r--spec/support/helpers/stub_configuration.rb5
-rw-r--r--spec/support/helpers/test_env.rb24
-rw-r--r--spec/support/helpers/test_request_helpers.rb11
-rw-r--r--spec/support/helpers/user_login_helper.rb26
-rw-r--r--spec/support/helpers/wiki_helpers.rb13
-rw-r--r--spec/support/import_export/export_file_helper.rb2
-rw-r--r--spec/support/services/clusters/create_service_shared.rb4
-rw-r--r--spec/support/shared_contexts/change_access_checks_shared_context.rb29
-rw-r--r--spec/support/shared_contexts/url_shared_context.rb17
-rw-r--r--spec/support/shared_examples/ci_trace_shared_examples.rb9
-rw-r--r--spec/support/shared_examples/controllers/issuable_notes_filter_shared_examples.rb66
-rw-r--r--spec/support/shared_examples/dirty_submit_form_shared_examples.rb24
-rw-r--r--spec/support/shared_examples/helm_generated_script.rb10
-rw-r--r--spec/support/shared_examples/models/chat_service_spec.rb242
-rw-r--r--spec/support/shared_examples/models/cluster_application_core_shared_examples.rb56
-rw-r--r--spec/support/shared_examples/models/cluster_application_helm_cert_examples.rb25
-rw-r--r--spec/support/shared_examples/models/cluster_application_status_shared_examples.rb113
-rw-r--r--spec/support/shared_examples/notify_shared_examples.rb17
-rw-r--r--spec/support/shared_examples/requests/api/merge_requests_list.rb24
-rw-r--r--spec/support/shared_examples/services/boards/issues_move_service.rb2
-rw-r--r--spec/support/shared_examples/services/boards/lists_move_service.rb12
-rw-r--r--spec/support/shared_examples/services/check_ingress_ip_address_service_shared_examples.rb33
-rw-r--r--spec/support/shared_examples/uploaders/gitlab_uploader_shared_examples.rb8
-rw-r--r--spec/support/stored_repositories.rb23
-rw-r--r--spec/support/stub_version.rb8
-rw-r--r--spec/tasks/cache/clear/redis_spec.rb5
-rw-r--r--spec/tasks/gitlab/backup_rake_spec.rb2
-rw-r--r--spec/tasks/gitlab/site_statistics_rake_spec.rb24
-rw-r--r--spec/tasks/gitlab/uploads/migrate_rake_spec.rb8
-rw-r--r--spec/unicorn/unicorn_spec.rb114
-rw-r--r--spec/uploaders/file_uploader_spec.rb27
-rw-r--r--spec/uploaders/namespace_file_uploader_spec.rb58
-rw-r--r--spec/validators/url_validator_spec.rb26
-rw-r--r--spec/views/help/index.html.haml_spec.rb41
-rw-r--r--spec/views/layouts/header/_new_dropdown.haml_spec.rb134
-rw-r--r--spec/views/projects/blob/_viewer.html.haml_spec.rb2
-rw-r--r--spec/views/projects/jobs/show.html.haml_spec.rb191
-rw-r--r--spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb1
-rw-r--r--spec/views/projects/merge_requests/edit.html.haml_spec.rb1
-rw-r--r--spec/views/projects/notes/_more_actions_dropdown.html.haml_spec.rb8
-rw-r--r--spec/views/projects/tree/_blob_item.html.haml_spec.rb40
-rw-r--r--spec/views/projects/tree/_tree_row.html.haml_spec.rb37
-rw-r--r--spec/views/shared/runners/show.html.haml_spec.rb155
-rw-r--r--spec/workers/archive_trace_worker_spec.rb8
-rw-r--r--spec/workers/build_success_worker_spec.rb54
-rw-r--r--spec/workers/ci/archive_traces_cron_worker_spec.rb10
-rw-r--r--spec/workers/ci/build_schedule_worker_spec.rb40
-rw-r--r--spec/workers/cluster_platform_configure_worker_spec.rb47
-rw-r--r--spec/workers/cluster_provision_worker_spec.rb9
-rw-r--r--spec/workers/concerns/gitlab/github_import/stage_methods_spec.rb6
-rw-r--r--spec/workers/concerns/project_import_options_spec.rb14
-rw-r--r--spec/workers/deployments/success_worker_spec.rb36
-rw-r--r--spec/workers/email_receiver_worker_spec.rb15
-rw-r--r--spec/workers/emails_on_push_worker_spec.rb2
-rw-r--r--spec/workers/every_sidekiq_worker_spec.rb6
-rw-r--r--spec/workers/git_garbage_collect_worker_spec.rb6
-rw-r--r--spec/workers/gitlab/github_import/advance_stage_worker_spec.rb30
-rw-r--r--spec/workers/gitlab/github_import/refresh_import_jid_worker_spec.rb22
-rw-r--r--spec/workers/gitlab/github_import/stage/import_base_data_worker_spec.rb3
-rw-r--r--spec/workers/gitlab/github_import/stage/import_pull_requests_worker_spec.rb5
-rw-r--r--spec/workers/namespaceless_project_destroy_worker_spec.rb4
-rw-r--r--spec/workers/pipeline_schedule_worker_spec.rb78
-rw-r--r--spec/workers/post_receive_spec.rb133
-rw-r--r--spec/workers/prune_old_events_worker_spec.rb20
-rw-r--r--spec/workers/rebase_worker_spec.rb12
-rw-r--r--spec/workers/repository_check/batch_worker_spec.rb2
-rw-r--r--spec/workers/repository_fork_worker_spec.rb32
-rw-r--r--spec/workers/repository_import_worker_spec.rb29
-rw-r--r--spec/workers/repository_remove_remote_worker_spec.rb5
-rw-r--r--spec/workers/stuck_ci_jobs_worker_spec.rb43
-rw-r--r--spec/workers/stuck_import_jobs_worker_spec.rb22
-rw-r--r--vendor/cert_manager/cluster_issuer.yaml11
-rw-r--r--vendor/cert_manager/values.yaml5
-rw-r--r--vendor/gitignore/Android.gitignore4
-rw-r--r--vendor/gitignore/Delphi.gitignore3
-rw-r--r--vendor/gitignore/Elixir.gitignore1
-rw-r--r--vendor/gitignore/Global/Images.gitignore63
-rw-r--r--vendor/gitignore/Global/JetBrains.gitignore3
-rw-r--r--vendor/gitignore/Global/NetBeans.gitignore2
-rw-r--r--vendor/gitignore/Global/PSoCCreator.gitignore18
-rw-r--r--vendor/gitignore/Global/Xcode.gitignore74
-rw-r--r--vendor/gitignore/Laravel.gitignore2
-rw-r--r--vendor/gitignore/Magento.gitignore2
-rw-r--r--vendor/gitignore/Node.gitignore5
-rw-r--r--vendor/gitignore/Python.gitignore3
-rw-r--r--vendor/gitignore/Rails.gitignore1
-rw-r--r--vendor/gitignore/TeX.gitignore6
-rw-r--r--vendor/gitignore/Unity.gitignore1
-rw-r--r--vendor/gitignore/VisualStudio.gitignore6
-rw-r--r--vendor/gitlab-ci-yml/.gitlab-ci.yml4
-rw-r--r--vendor/gitlab-ci-yml/Android.gitlab-ci.yml51
-rw-r--r--vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml823
-rw-r--r--vendor/gitlab-ci-yml/CONTRIBUTING.md46
-rw-r--r--vendor/gitlab-ci-yml/Julia.gitlab-ci.yml54
-rw-r--r--vendor/gitlab-ci-yml/LICENSE25
-rw-r--r--vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml82
-rw-r--r--vendor/gitlab-ci-yml/Maven.gitlab-ci.yml102
-rw-r--r--vendor/gitlab-ci-yml/Python.gitlab-ci.yml51
-rw-r--r--vendor/gitlab-ci-yml/Swift.gitlab-ci.yml30
-rw-r--r--vendor/jupyter/values.yaml5
-rwxr-xr-xvendor/languages.yml5488
-rw-r--r--vendor/licenses.csv456
-rw-r--r--vendor/prometheus/values.yaml4
-rw-r--r--yarn.lock4811
6561 files changed, 391515 insertions, 79017 deletions
diff --git a/.babelrc b/.babelrc
deleted file mode 100644
index 50d85f58d69..00000000000
--- a/.babelrc
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "presets": [["latest", { "es2015": { "modules": false } }], "stage-2"],
- "env": {
- "karma": {
- "plugins": ["rewire"]
- },
- "coverage": {
- "plugins": [
- [
- "istanbul",
- {
- "exclude": ["spec/javascripts/**/*", "app/assets/javascripts/locale/**/app.js"]
- }
- ],
- [
- "transform-define",
- {
- "process.env.BABEL_ENV": "coverage"
- }
- ],
- "rewire"
- ]
- }
- }
-}
diff --git a/.babelrc.js b/.babelrc.js
new file mode 100644
index 00000000000..27caf378b99
--- /dev/null
+++ b/.babelrc.js
@@ -0,0 +1,38 @@
+const BABEL_ENV = process.env.BABEL_ENV || process.env.NODE_ENV || null;
+
+const presets = [
+ [
+ '@babel/preset-env',
+ {
+ modules: false,
+ targets: {
+ ie: '11',
+ },
+ },
+ ],
+];
+
+// include stage 3 proposals
+const plugins = [
+ '@babel/plugin-syntax-dynamic-import',
+ '@babel/plugin-syntax-import-meta',
+ '@babel/plugin-proposal-class-properties',
+ '@babel/plugin-proposal-json-strings',
+];
+
+// add code coverage tooling if necessary
+if (BABEL_ENV === 'coverage') {
+ plugins.push([
+ 'babel-plugin-istanbul',
+ {
+ exclude: ['spec/javascripts/**/*', 'app/assets/javascripts/locale/**/app.js'],
+ },
+ ]);
+}
+
+// add rewire support when running tests
+if (BABEL_ENV === 'karma' || BABEL_ENV === 'coverage') {
+ plugins.push('babel-plugin-rewire');
+}
+
+module.exports = { presets, plugins };
diff --git a/.eslintrc.yml b/.eslintrc.yml
index ebf8048f19c..ecd9f57b075 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -1,80 +1,35 @@
----
-env:
- browser: true
- es6: true
extends:
- - airbnb-base
- - plugin:vue/recommended
+ - '@gitlab'
globals:
__webpack_public_path__: true
gl: false
gon: false
localStorage: false
-parserOptions:
- parser: babel-eslint
plugins:
- - filenames
- import
- html
- - promise
settings:
html/html-extensions:
- - ".html"
- - ".html.raw"
+ - '.html'
+ - '.html.raw'
import/resolver:
webpack:
- config: "./config/webpack.config.js"
+ config: './config/webpack.config.js'
rules:
- filenames/match-regex:
- - error
- - "^[a-z0-9_]+$"
import/no-commonjs: error
- no-multiple-empty-lines:
- - error
- - max: 1
- promise/catch-or-return: error
- no-param-reassign:
- - error
- - props: true
- ignorePropertyModificationsFor:
- - "acc" # for reduce accumulators
- - "accumulator" # for reduce accumulators
- - "el" # for DOM elements
- - "element" # for DOM elements
- - "state" # for Vuex mutations
no-underscore-dangle:
- error
- allow:
- - __
- - _links
- no-mixed-operators: off
- vue/html-self-closing:
- - error
- - html:
- void: always
- normal: never
- component: always
- svg: always
- math: always
- ## Conflicting rules with prettier:
- space-before-function-paren: off
- curly: off
- arrow-parens: off
- function-paren-newline: off
- object-curly-newline: off
- padded-blocks: off
- # Disabled for now, to make the eslint 3 -> eslint 4 update smoother
- ## Indent rule. We are using the old for now: https://eslint.org/docs/user-guide/migrating-to-4.0.0#indent-rewrite
- indent: off
- indent-legacy:
+ - __
+ - _links
+ # Disabled for now, to make the airbnb-base 12.1.0 -> 13.1.0 update smoother
+ no-else-return:
- error
- - 2
- - SwitchCase: 1
- VariableDeclarator: 1
- outerIIFEBody: 1
- FunctionDeclaration:
- parameters: 1
- body: 1
- FunctionExpression:
- parameters: 1
- body: 1
+ - allowElseIf: true
+ import/no-useless-path-segments: off
+ lines-between-class-members: off
+ # Disabled for now, to make the plugin-vue 4.5 -> 5.0 update smoother
+ vue/no-confusing-v-for-v-if: error
+ vue/no-unused-components: off
+ vue/no-use-v-if-with-v-for: off
+ vue/no-v-html: off
diff --git a/.gitattributes b/.gitattributes
index f1c41c9bb76..7282c9e61b1 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1 +1,2 @@
Dangerfile gitlab-language=ruby
+db/schema.rb merge=merge_db_schema
diff --git a/.gitignore b/.gitignore
index 82b3d08f7a8..aecaae95b8c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -40,6 +40,7 @@ eslint-report.html
/config/redis.queues.yml
/config/redis.shared_state.yml
/config/unicorn.rb
+/config/puma.rb
/config/secrets.yml
/config/sidekiq.yml
/config/registry.key
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 488d2f261e7..79ec1b881d4 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,4 @@
-image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.4.4-golang-1.9-git-2.18-chrome-69.0-node-8.x-yarn-1.2-postgresql-9.6-graphicsmagick-1.3.29"
+image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-golang-1.9-git-2.18-chrome-69.0-node-10.x-yarn-1.12-postgresql-9.6-graphicsmagick-1.3.29"
.dedicated-runner: &dedicated-runner
retry: 1
@@ -6,7 +6,7 @@ image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.4.4-golang-1.9-git
- gitlab-org
.default-cache: &default-cache
- key: "ruby-2.4.4-debian-stretch-with-yarn"
+ key: "debian-stretch-ruby-2.5.3-node-10.x"
paths:
- vendor/ruby
- .yarn-cache/
@@ -32,6 +32,7 @@ variables:
GET_SOURCES_ATTEMPTS: "3"
KNAPSACK_RSPEC_SUITE_REPORT_PATH: knapsack/${CI_PROJECT_NAME}/rspec_report-master.json
FLAKY_RSPEC_SUITE_REPORT_PATH: rspec_flaky/report-suite.json
+ BUILD_ASSETS_IMAGE: "false"
before_script:
- bundle --version
@@ -67,10 +68,7 @@ stages:
.use-pg: &use-pg
services:
- # As of Jan 2018, we don't have a strong reason to upgrade to 9.6 for CI yet,
- # so using the least common denominator ensures backwards compatibility
- # (as many users are still using 9.2).
- - postgres:9.2
+ - postgres:9.6
- redis:alpine
.use-mysql: &use-mysql
@@ -78,24 +76,21 @@ stages:
- mysql:5.7
- redis:alpine
-.rails5-variables: &rails5-variables
- script:
- - export RAILS5=${RAILS5}
- - export BUNDLE_GEMFILE=${BUNDLE_GEMFILE}
-
-.rails5: &rails5
- allow_failure: true
- only:
+.rails4: &rails4
+ allow_failure: false
+ except:
variables:
- - $CI_COMMIT_REF_NAME =~ /rails5/
- - $RAILS5_ENABLED
+ - $CI_COMMIT_REF_NAME =~ /(^docs[\/-].*|.*-docs$)/
+ - $CI_COMMIT_REF_NAME =~ /(^qa[\/-].*|.*-qa$)/
+ - $CI_COMMIT_REF_NAME =~ /norails4/
+ - $RAILS5_DISABLED
variables:
- BUNDLE_GEMFILE: "Gemfile.rails5"
- RAILS5: "true"
+ BUNDLE_GEMFILE: "Gemfile.rails4"
+ RAILS5: "false"
# Skip all jobs except the ones that begin with 'docs/'.
# Used for commits including ONLY documentation changes.
-# https://docs.gitlab.com/ce/development/writing_documentation.html#testing
+# https://docs.gitlab.com/ce/development/documentation/#testing
.except-docs: &except-docs
except:
- /(^docs[\/-].*|.*-docs$)/
@@ -129,8 +124,7 @@ stages:
<<: *except-docs-and-qa
.single-script-job: &single-script-job
- image: ruby:2.4-alpine
- before_script: []
+ image: ruby:2.5-alpine
stage: test
cache: {}
dependencies: []
@@ -143,7 +137,7 @@ stages:
- export SCRIPT_NAME="${SCRIPT_NAME:-$CI_JOB_NAME}"
- apk add --update openssl
- wget $CI_PROJECT_URL/raw/$CI_COMMIT_SHA/scripts/$SCRIPT_NAME
- - chmod 755 $SCRIPT_NAME
+ - chmod 755 $(basename $SCRIPT_NAME)
.rake-exec: &rake-exec
<<: *dedicated-no-docs-no-db-pull-cache-job
@@ -154,17 +148,15 @@ stages:
<<: *dedicated-runner
<<: *except-docs-and-qa
<<: *pull-cache
- <<: *rails5-variables
stage: test
script:
- JOB_NAME=( $CI_JOB_NAME )
- - export CI_NODE_INDEX=${JOB_NAME[-2]}
- - export CI_NODE_TOTAL=${JOB_NAME[-1]}
- - export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${JOB_NAME[0]}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
+ - TEST_TOOL=${JOB_NAME[0]}
+ - export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${TEST_TOOL}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
- export KNAPSACK_GENERATE_REPORT=true
- export SUITE_FLAKY_RSPEC_REPORT_PATH=${FLAKY_RSPEC_SUITE_REPORT_PATH}
- - export FLAKY_RSPEC_REPORT_PATH=rspec_flaky/all_${JOB_NAME[0]}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
- - export NEW_FLAKY_RSPEC_REPORT_PATH=rspec_flaky/new_${JOB_NAME[0]}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
+ - export FLAKY_RSPEC_REPORT_PATH=rspec_flaky/all_${TEST_TOOL}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
+ - export NEW_FLAKY_RSPEC_REPORT_PATH=rspec_flaky/new_${TEST_TOOL}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
- export FLAKY_RSPEC_GENERATE_REPORT=true
- export CACHE_CLASSES=true
- cp ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} ${KNAPSACK_REPORT_PATH}
@@ -187,17 +179,17 @@ stages:
<<: *rspec-metadata
<<: *use-pg
-.rspec-metadata-pg-rails5: &rspec-metadata-pg-rails5
+.rspec-metadata-pg-rails4: &rspec-metadata-pg-rails4
<<: *rspec-metadata-pg
- <<: *rails5
+ <<: *rails4
.rspec-metadata-mysql: &rspec-metadata-mysql
<<: *rspec-metadata
<<: *use-mysql
-.rspec-metadata-mysql-rails5: &rspec-metadata-mysql-rails5
+.rspec-metadata-mysql-rails4: &rspec-metadata-mysql-rails4
<<: *rspec-metadata-mysql
- <<: *rails5
+ <<: *rails4
.only-canonical-masters: &only-canonical-masters
only:
@@ -237,6 +229,8 @@ stages:
script:
- git fetch https://gitlab.com/gitlab-org/gitlab-ce.git v9.3.0
- git checkout -f FETCH_HEAD
+ - sed -i "s/gem 'oj', '~> 2.17.4'//" Gemfile
+ - bundle update google-protobuf grpc
- bundle install $BUNDLE_INSTALL_FLAGS
- date
- cp config/gitlab.yml.example config/gitlab.yml
@@ -259,6 +253,7 @@ package-and-qa:
SCRIPT_NAME: trigger-build
retry: 0
script:
+ - gem install gitlab --no-document
- ./$SCRIPT_NAME omnibus
when: manual
only:
@@ -274,7 +269,7 @@ package-and-qa:
SCRIPT_NAME: trigger-build-docs
environment:
name: review-docs/$CI_COMMIT_REF_SLUG
- # DOCS_REVIEW_APPS_DOMAIN and DOCS_GITLAB_REPO_SUFFIX are secret variables
+ # DOCS_REVIEW_APPS_DOMAIN and DOCS_GITLAB_REPO_SUFFIX are CI variables
# Discussion: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14236/diffs#note_40140693
url: http://$CI_ENVIRONMENT_SLUG.$DOCS_REVIEW_APPS_DOMAIN/$DOCS_GITLAB_REPO_SUFFIX
on_stop: review-docs-cleanup
@@ -285,7 +280,7 @@ review-docs-deploy-manual:
<<: *review-docs
stage: build
script:
- - gem install gitlab --no-ri --no-rdoc
+ - gem install gitlab --no-document
- ./$SCRIPT_NAME deploy
when: manual
only:
@@ -299,7 +294,7 @@ review-docs-deploy:
<<: *review-docs
stage: post-test
script:
- - gem install gitlab --no-ri --no-rdoc
+ - gem install gitlab --no-document
- ./$SCRIPT_NAME deploy
only:
- /(^docs[\/-].*|.*-docs$)/@gitlab-org/gitlab-ce
@@ -314,7 +309,7 @@ review-docs-cleanup:
name: review-docs/$CI_COMMIT_REF_SLUG
action: stop
script:
- - gem install gitlab --no-ri --no-rdoc
+ - gem install gitlab --no-document
- ./$SCRIPT_NAME cleanup
when: manual
only:
@@ -325,16 +320,17 @@ review-docs-cleanup:
# Trigger a docker image build in CNG (Cloud Native GitLab) repository
#
cloud-native-image:
- image: ruby:2.4-alpine
+ image: ruby:2.5-alpine
before_script: []
- stage: test
+ dependencies: []
+ stage: post-test
allow_failure: true
variables:
GIT_DEPTH: "1"
cache: {}
script:
- - gem install gitlab --no-ri --no-rdoc
- - BUILD_TRIGGER_TOKEN=$CI_JOB_TOKEN scripts/trigger-build cng
+ - gem install gitlab --no-document
+ - CNG_PROJECT_PATH="gitlab-org/build/CNG" BUILD_TRIGGER_TOKEN=$CI_JOB_TOKEN ./scripts/trigger-build cng
only:
- tags@gitlab-org/gitlab-ce
- tags@gitlab-org/gitlab-ee
@@ -366,7 +362,7 @@ update-tests-metadata:
- rspec_flaky/
policy: push
script:
- - retry gem install fog-aws mime-types activesupport --no-ri --no-rdoc
+ - retry gem install fog-aws mime-types activesupport --no-document
- scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec-pg_node_*.json
- scripts/merge-reports ${FLAKY_RSPEC_SUITE_REPORT_PATH} rspec_flaky/all_*_*.json
- FLAKY_RSPEC_GENERATE_REPORT=1 scripts/prune-old-flaky-specs ${FLAKY_RSPEC_SUITE_REPORT_PATH}
@@ -377,7 +373,7 @@ update-tests-metadata:
flaky-examples-check:
<<: *dedicated-runner
- image: ruby:2.4-alpine
+ image: ruby:2.5-alpine
services: []
before_script: []
variables:
@@ -435,7 +431,7 @@ setup-test-env:
script:
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
- scripts/gitaly-test-build # Do not use 'bundle exec' here
- - BUNDLE_GEMFILE=Gemfile.rails5 bundle install $BUNDLE_INSTALL_FLAGS
+ - BUNDLE_GEMFILE=Gemfile.rails4 bundle install $BUNDLE_INSTALL_FLAGS
artifacts:
expire_in: 7d
paths:
@@ -443,11 +439,55 @@ setup-test-env:
- config/secrets.yml
- vendor/gitaly-ruby
+# GitLab Review apps
+.review-base: &review-base
+ <<: *dedicated-no-docs-no-db-pull-cache-job
+ image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-charts-build-base
+ stage: test
+ cache: {}
+ dependencies: []
+ environment: &review-environment
+ name: review/${CI_COMMIT_REF_NAME}
+ url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}
+ only:
+ refs:
+ - branches@gitlab-org/gitlab-ce
+ - branches@gitlab-org/gitlab-ee
+ kubernetes: active
+ except:
+ refs:
+ - master
+ - /(^docs[\/-].*|.*-docs$)/
+ before_script: []
+
+.review-docker: &review-docker
+ <<: *review-base
+ image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-alpine
+ services:
+ - docker:stable-dind
+ tags:
+ - gitlab-org
+ - docker
+ variables: &review-docker-variables
+ GIT_DEPTH: "1"
+ DOCKER_DRIVER: overlay2
+ DOCKER_HOST: tcp://docker:2375
+ LATEST_QA_IMAGE: "gitlab/${CI_PROJECT_NAME}-qa:nightly"
+ QA_IMAGE: "${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab/${CI_PROJECT_NAME}-qa:${CI_COMMIT_REF_SLUG}"
+
+build-qa-image:
+ <<: *review-docker
+ stage: prepare
+ script:
+ - time docker build --cache-from ${LATEST_QA_IMAGE} --tag ${QA_IMAGE} ./qa/
+ - echo "${CI_JOB_TOKEN}" | docker login --username gitlab-ci-token --password-stdin ${CI_REGISTRY}
+ - time docker push ${QA_IMAGE}
+
danger-review:
+ <<: *pull-cache
image: registry.gitlab.com/gitlab-org/gitlab-build-images:danger
stage: test
allow_failure: true
- cache: {}
dependencies: []
before_script: []
only:
@@ -461,131 +501,25 @@ danger-review:
- $CI_COMMIT_REF_NAME =~ /.*-stable(-ee)?-prepare-.*/
script:
- git version
+ - node --version
+ - yarn install --frozen-lockfile --cache-folder .yarn-cache
- danger --fail-on-errors=true
-rspec-pg 0 30: *rspec-metadata-pg
-rspec-pg 1 30: *rspec-metadata-pg
-rspec-pg 2 30: *rspec-metadata-pg
-rspec-pg 3 30: *rspec-metadata-pg
-rspec-pg 4 30: *rspec-metadata-pg
-rspec-pg 5 30: *rspec-metadata-pg
-rspec-pg 6 30: *rspec-metadata-pg
-rspec-pg 7 30: *rspec-metadata-pg
-rspec-pg 8 30: *rspec-metadata-pg
-rspec-pg 9 30: *rspec-metadata-pg
-rspec-pg 10 30: *rspec-metadata-pg
-rspec-pg 11 30: *rspec-metadata-pg
-rspec-pg 12 30: *rspec-metadata-pg
-rspec-pg 13 30: *rspec-metadata-pg
-rspec-pg 14 30: *rspec-metadata-pg
-rspec-pg 15 30: *rspec-metadata-pg
-rspec-pg 16 30: *rspec-metadata-pg
-rspec-pg 17 30: *rspec-metadata-pg
-rspec-pg 18 30: *rspec-metadata-pg
-rspec-pg 19 30: *rspec-metadata-pg
-rspec-pg 20 30: *rspec-metadata-pg
-rspec-pg 21 30: *rspec-metadata-pg
-rspec-pg 22 30: *rspec-metadata-pg
-rspec-pg 23 30: *rspec-metadata-pg
-rspec-pg 24 30: *rspec-metadata-pg
-rspec-pg 25 30: *rspec-metadata-pg
-rspec-pg 26 30: *rspec-metadata-pg
-rspec-pg 27 30: *rspec-metadata-pg
-rspec-pg 28 30: *rspec-metadata-pg
-rspec-pg 29 30: *rspec-metadata-pg
-
-rspec-mysql 0 30: *rspec-metadata-mysql
-rspec-mysql 1 30: *rspec-metadata-mysql
-rspec-mysql 2 30: *rspec-metadata-mysql
-rspec-mysql 3 30: *rspec-metadata-mysql
-rspec-mysql 4 30: *rspec-metadata-mysql
-rspec-mysql 5 30: *rspec-metadata-mysql
-rspec-mysql 6 30: *rspec-metadata-mysql
-rspec-mysql 7 30: *rspec-metadata-mysql
-rspec-mysql 8 30: *rspec-metadata-mysql
-rspec-mysql 9 30: *rspec-metadata-mysql
-rspec-mysql 10 30: *rspec-metadata-mysql
-rspec-mysql 11 30: *rspec-metadata-mysql
-rspec-mysql 12 30: *rspec-metadata-mysql
-rspec-mysql 13 30: *rspec-metadata-mysql
-rspec-mysql 14 30: *rspec-metadata-mysql
-rspec-mysql 15 30: *rspec-metadata-mysql
-rspec-mysql 16 30: *rspec-metadata-mysql
-rspec-mysql 17 30: *rspec-metadata-mysql
-rspec-mysql 18 30: *rspec-metadata-mysql
-rspec-mysql 19 30: *rspec-metadata-mysql
-rspec-mysql 20 30: *rspec-metadata-mysql
-rspec-mysql 21 30: *rspec-metadata-mysql
-rspec-mysql 22 30: *rspec-metadata-mysql
-rspec-mysql 23 30: *rspec-metadata-mysql
-rspec-mysql 24 30: *rspec-metadata-mysql
-rspec-mysql 25 30: *rspec-metadata-mysql
-rspec-mysql 26 30: *rspec-metadata-mysql
-rspec-mysql 27 30: *rspec-metadata-mysql
-rspec-mysql 28 30: *rspec-metadata-mysql
-rspec-mysql 29 30: *rspec-metadata-mysql
-
-rspec-pg-rails5 0 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 1 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 2 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 3 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 4 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 5 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 6 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 7 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 8 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 9 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 10 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 11 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 12 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 13 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 14 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 15 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 16 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 17 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 18 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 19 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 20 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 21 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 22 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 23 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 24 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 25 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 26 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 27 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 28 30: *rspec-metadata-pg-rails5
-rspec-pg-rails5 29 30: *rspec-metadata-pg-rails5
-
-rspec-mysql-rails5 0 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 1 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 2 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 3 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 4 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 5 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 6 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 7 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 8 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 9 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 10 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 11 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 12 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 13 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 14 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 15 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 16 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 17 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 18 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 19 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 20 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 21 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 22 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 23 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 24 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 25 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 26 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 27 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 28 30: *rspec-metadata-mysql-rails5
-rspec-mysql-rails5 29 30: *rspec-metadata-mysql-rails5
+rspec-pg:
+ <<: *rspec-metadata-pg
+ parallel: 50
+
+rspec-mysql:
+ <<: *rspec-metadata-mysql
+ parallel: 50
+
+rspec-pg-rails4:
+ <<: *rspec-metadata-pg-rails4
+ parallel: 50
+
+rspec-mysql-rails4:
+ <<: *rspec-metadata-mysql-rails4
+ parallel: 50
static-analysis:
<<: *dedicated-no-docs-no-db-pull-cache-job
@@ -595,7 +529,7 @@ static-analysis:
script:
- scripts/static-analysis
cache:
- key: "ruby-2.4.4-debian-stretch-with-yarn-and-rubocop"
+ key: "debian-stretch-ruby-2.5.3-node-10.x-and-rubocop"
paths:
- vendor/ruby
- .yarn-cache/
@@ -607,7 +541,7 @@ static-analysis:
docs lint:
<<: *dedicated-runner
<<: *except-qa
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:nanoc-bootstrap-ruby-2.4-alpine"
+ image: "registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-docs-lint"
stage: test
cache: {}
dependencies: []
@@ -615,8 +549,8 @@ docs lint:
script:
- scripts/lint-doc.sh
- scripts/lint-changelog-yaml
- - mv doc/ /nanoc/content/
- - cd /nanoc
+ - mv doc/ /tmp/gitlab-docs/content/
+ - cd /tmp/gitlab-docs
# Build HTML from Markdown
- bundle exec nanoc
# Check the internal links
@@ -631,14 +565,15 @@ downtime_check:
- /(^docs[\/-].*|.*-docs$)/
- /(^qa[\/-].*|.*-qa$)/
-rails5_gemfile_lock_check:
+rails4_gemfile_lock_check:
<<: *dedicated-no-docs-no-db-pull-cache-job
<<: *except-docs-and-qa
script:
- - scripts/rails5-gemfile-lock-check
+ - scripts/rails4-gemfile-lock-check
ee_compat_check:
<<: *rake-exec
+ dependencies: []
except:
- master
- tags
@@ -701,7 +636,10 @@ gitlab:setup-mysql:
# Frontend-related jobs
gitlab:assets:compile:
<<: *dedicated-no-docs-and-no-qa-pull-cache-job
+ image: dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-git-2.18-chrome-69.0-node-8.x-yarn-1.2-graphicsmagick-1.3.29-docker-18.06.1
dependencies: []
+ services:
+ - docker:stable-dind
variables:
NODE_ENV: "production"
RAILS_ENV: "production"
@@ -710,25 +648,39 @@ gitlab:assets:compile:
WEBPACK_REPORT: "true"
# we override the max_old_space_size to prevent OOM errors
NODE_OPTIONS: --max_old_space_size=3584
+ DOCKER_DRIVER: overlay2
+ DOCKER_HOST: tcp://docker:2375
script:
- date
- yarn install --frozen-lockfile --production --cache-folder .yarn-cache
- date
- free -m
- bundle exec rake gitlab:assets:compile
+ - scripts/build_assets_image
artifacts:
name: webpack-report
expire_in: 31d
paths:
- webpack-report/
- public/assets/
+ only:
+ - //@gitlab-org/gitlab-ce
+ - //@gitlab-org/gitlab-ee
+ - //@gitlab/gitabhq
+ - //@gitlab/gitlab-ee
+ tags:
+ - gitlab-org-delivery
+ - high-cpu
karma:
- <<: *dedicated-no-docs-and-no-qa-pull-cache-job
+ <<: *dedicated-no-docs-pull-cache-job
<<: *use-pg
dependencies:
- compile-assets
- setup-test-env
+ variables:
+ # we override the max_old_space_size to prevent OOM errors
+ NODE_OPTIONS: --max_old_space_size=3584
script:
- export BABEL_ENV=coverage CHROME_LOG_FILE=chrome_debug.log
- date
@@ -770,7 +722,8 @@ code_quality:
--volume /var/run/docker.sock:/var/run/docker.sock
"registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
artifacts:
- paths: [gl-code-quality-report.json]
+ reports:
+ codequality: gl-code-quality-report.json
expire_in: 1 week
sast:
@@ -794,7 +747,8 @@ sast:
--volume /var/run/docker.sock:/var/run/docker.sock
"registry.gitlab.com/gitlab-org/security-products/sast:$SP_VERSION" /app/bin/run /code
artifacts:
- paths: [gl-sast-report.json]
+ reports:
+ sast: gl-sast-report.json
dependency_scanning:
<<: *dedicated-no-docs-no-db-pull-cache-job
@@ -816,7 +770,8 @@ dependency_scanning:
--volume /var/run/docker.sock:/var/run/docker.sock
"registry.gitlab.com/gitlab-org/security-products/dependency-scanning:$SP_VERSION" /code
artifacts:
- paths: [gl-dependency-scanning-report.json]
+ reports:
+ dependency_scanning: gl-dependency-scanning-report.json
qa:internal:
<<: *dedicated-no-docs-no-db-pull-cache-job
@@ -834,6 +789,40 @@ qa:selectors:
- bundle install
- bundle exec bin/qa Test::Sanity::Selectors
+.qa-frontend-node: &qa-frontend-node
+ stage: test
+ variables:
+ NODE_OPTIONS: --max_old_space_size=3584
+ cache:
+ key: "$CI_JOB_NAME"
+ paths:
+ - .yarn-cache/
+ dependencies: []
+ before_script: []
+ script:
+ - date
+ - yarn install --frozen-lockfile --cache-folder .yarn-cache
+ - date
+ - yarn run webpack-prod
+ <<: *except-docs
+
+qa-frontend-node:6:
+ <<: *qa-frontend-node
+ image: node:6-alpine
+
+qa-frontend-node:8:
+ <<: *qa-frontend-node
+ image: node:8-alpine
+
+qa-frontend-node:10:
+ <<: *qa-frontend-node
+ image: node:10-alpine
+
+qa-frontend-node:latest:
+ <<: *qa-frontend-node
+ image: node:alpine
+ allow_failure: true
+
coverage:
# Don't include dedicated-no-docs-no-db-pull-cache-job here since we need to
# download artifacts from all the rspec jobs instead of from setup-test-env only
@@ -856,9 +845,7 @@ coverage:
lint:javascript:report:
<<: *dedicated-no-docs-and-no-qa-pull-cache-job
stage: post-test
- dependencies:
- - compile-assets
- - setup-test-env
+ dependencies: []
before_script: []
script:
- date
@@ -885,6 +872,8 @@ pages:
- mv coverage-javascript/ public/coverage-javascript/ || true
- mv eslint-report.html public/ || true
- mv webpack-report/ public/webpack-report/ || true
+ - cp .public/assets/application-*.css public/application.css || true
+ - cp .public/assets/application-*.css.gz public/application.css.gz || true
artifacts:
paths:
- public
@@ -912,6 +901,7 @@ gitlab_git_test:
variables:
SETUP_DB: "false"
before_script: []
+ dependencies: []
cache: {}
script:
- spec/support/prepare-gitlab-git-test-for-commit --check-for-changes
@@ -922,8 +912,116 @@ no_ee_check:
variables:
SETUP_DB: "false"
before_script: []
+ dependencies: []
cache: {}
script:
- scripts/no-ee-check
only:
- //@gitlab-org/gitlab-ce
+
+# GitLab Review apps
+review-deploy:
+ <<: *review-base
+ variables:
+ GIT_DEPTH: "1"
+ HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}"
+ DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
+ GITLAB_HELM_CHART_REF: "master"
+ API_TOKEN: "${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}"
+ environment:
+ <<: *review-environment
+ on_stop: review-stop
+ before_script:
+ - apk update && apk add jq
+ - gem install gitlab --no-document
+ script:
+ - export GITLAB_SHELL_VERSION=$(<GITLAB_SHELL_VERSION)
+ - export GITALY_VERSION=$(<GITALY_SERVER_VERSION)
+ - export GITLAB_WORKHORSE_VERSION=$(<GITLAB_WORKHORSE_VERSION)
+ - source ./scripts/review_apps/review-apps.sh
+ - wait_for_job_to_be_done "gitlab:assets:compile"
+ - BUILD_TRIGGER_TOKEN=$REVIEW_APPS_BUILD_TRIGGER_TOKEN ./scripts/trigger-build cng
+ - check_kube_domain
+ - download_gitlab_chart
+ - ensure_namespace
+ - install_tiller
+ - install_external_dns
+ - time deploy
+ - add_license
+
+.review-qa-base: &review-qa-base
+ <<: *review-docker
+ variables:
+ <<: *review-docker-variables
+ API_TOKEN: "${GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN}"
+ QA_ARTIFACTS_DIR: "${CI_PROJECT_DIR}/qa"
+ QA_CAN_TEST_GIT_PROTOCOL_V2: "false"
+ GITLAB_USERNAME: "root"
+ GITLAB_PASSWORD: "${REVIEW_APPS_ROOT_PASSWORD}"
+ GITLAB_ADMIN_USERNAME: "root"
+ GITLAB_ADMIN_PASSWORD: "${REVIEW_APPS_ROOT_PASSWORD}"
+ GITHUB_ACCESS_TOKEN: "${REVIEW_APPS_QA_GITHUB_ACCESS_TOKEN}"
+ EE_LICENSE: "${REVIEW_APPS_EE_LICENSE}"
+ QA_DEBUG: "true"
+ artifacts:
+ paths:
+ - ./qa/gitlab-qa-run-*
+ expire_in: 7 days
+ when: always
+ before_script:
+ - echo "${QA_IMAGE}"
+ - echo "${CI_ENVIRONMENT_URL}"
+ - apk update && apk add curl jq
+ - source ./scripts/review_apps/review-apps.sh
+ - gem install gitlab-qa --no-document ${GITLAB_QA_VERSION:+ --version ${GITLAB_QA_VERSION}}
+ - wait_for_job_to_be_done "review-deploy"
+
+review-qa-smoke:
+ <<: *review-qa-base
+ retry: 2
+ script:
+ - gitlab-qa Test::Instance::Smoke "${QA_IMAGE}" "${CI_ENVIRONMENT_URL}"
+
+review-qa-all:
+ <<: *review-qa-base
+ script:
+ - gitlab-qa Test::Instance::Any "${QA_IMAGE}" "${CI_ENVIRONMENT_URL}"
+ when: manual
+
+review-stop:
+ <<: *review-base
+ <<: *single-script-job
+ image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-charts-build-base
+ allow_failure: true
+ variables:
+ <<: *single-script-job-variables
+ SCRIPT_NAME: "review_apps/review-apps.sh"
+ when: manual
+ environment:
+ <<: *review-environment
+ action: stop
+ script:
+ - source $(basename "${SCRIPT_NAME}")
+ - delete
+ - cleanup
+
+schedule:review-cleanup:
+ <<: *review-base
+ stage: build
+ allow_failure: true
+ variables:
+ GIT_DEPTH: "1"
+ environment:
+ name: review/auto-cleanup
+ only:
+ refs:
+ - schedules@gitlab-org/gitlab-ce
+ - schedules@gitlab-org/gitlab-ee
+ kubernetes: active
+ except:
+ - tags
+ - /(^docs[\/-].*|.*-docs$)/
+ before_script:
+ - gem install gitlab --no-document
+ script:
+ - ruby -rrubygems scripts/review_apps/automated_cleanup.rb
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
deleted file mode 100644
index 7fd32563696..00000000000
--- a/.gitlab/CODEOWNERS
+++ /dev/null
@@ -1,17 +0,0 @@
-# Backend Maintainers are the default for all ruby files
-*.rb @ayufan @DouweM @dzaporozhets @grzesiek @nick.thomas @rspeicher @rymai @smcgivern
-*.rake @ayufan @DouweM @dzaporozhets @grzesiek @nick.thomas @rspeicher @rymai @smcgivern
-
-# Technical writing team are the default reviewers for everything in `doc/`
-/doc/ @axil @marcia
-
-# Frontend maintainers should see everything in `app/assets/`
-app/assets/ @annabeldunstone @ClemMakesApps @fatihacet @filipa @iamphill @mikegreiling @timzallmann
-
-# Someone from the database team should review changes in `db/`
-db/ @abrandl @NikolayS
-
-# Feature specific owners
-/ee/lib/gitlab/code_owners/ @reprazent
-/ee/lib/ee/gitlab/auth/ldap/ @dblessing @mkozono
-/lib/gitlab/auth/ldap/ @dblessing @mkozono
diff --git a/.gitlab/CODEOWNERS.disabled b/.gitlab/CODEOWNERS.disabled
new file mode 100644
index 00000000000..a4b773b15a9
--- /dev/null
+++ b/.gitlab/CODEOWNERS.disabled
@@ -0,0 +1,20 @@
+# Backend Maintainers are the default for all ruby files
+*.rb @ayufan @DouweM @dzaporozhets @grzesiek @nick.thomas @rspeicher @rymai @smcgivern
+*.rake @ayufan @DouweM @dzaporozhets @grzesiek @nick.thomas @rspeicher @rymai @smcgivern
+
+# Technical writing team are the default reviewers for everything in `doc/`
+/doc/ @axil @marcia
+
+# Frontend maintainers should see everything in `app/assets/`
+app/assets/ @ClemMakesApps @fatihacet @filipa @iamphill @mikegreiling @timzallmann
+*.scss @annabeldunstone @ClemMakesApps @fatihacet @filipa @iamphill @mikegreiling @timzallmann
+
+# Someone from the database team should review changes in `db/`
+db/ @abrandl @NikolayS
+
+# Feature specific owners
+/ee/lib/gitlab/code_owners/ @reprazent
+/ee/lib/ee/gitlab/auth/ldap/ @dblessing @mkozono
+/lib/gitlab/auth/ldap/ @dblessing @mkozono
+/lib/gitlab/ci/templates/ @nolith @zj
+/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml @DylanGriffith @mayra-cabrera @tkuah
diff --git a/.gitlab/issue_templates/Research proposal.md b/.gitlab/issue_templates/Research proposal.md
deleted file mode 100644
index 5676656793d..00000000000
--- a/.gitlab/issue_templates/Research proposal.md
+++ /dev/null
@@ -1,17 +0,0 @@
-### Background:
-
-(Include problem, use cases, benefits, and/or goals)
-
-**What questions are you trying to answer?**
-
-**Are you looking to verify an existing hypothesis or uncover new issues you should be exploring?**
-
-**What is the backstory of this project and how does it impact the approach?**
-
-**What do you already know about the areas you are exploring?**
-
-**What does success look like at the end of the project?**
-
-### Links / references:
-
-/label ~"UX research"
diff --git a/.gitlab/issue_templates/Security developer workflow.md b/.gitlab/issue_templates/Security developer workflow.md
index 64b54b171f7..08651195d98 100644
--- a/.gitlab/issue_templates/Security developer workflow.md
+++ b/.gitlab/issue_templates/Security developer workflow.md
@@ -16,7 +16,7 @@ Set the title to: `[Security] Description of the original issue`
- [ ] Add a link to the MR to the [links section](#links)
- [ ] Add a link to an EE MR if required
- [ ] Make sure the MR remains in-progress and gets approved after the review cycle, **but never merged**.
-- [ ] Assign the MR to a RM once is reviewed and ready to be merged. Check the [RM list] to see who to ping.
+- [ ] Add a link to this issue on the original security issue.
#### Backports
@@ -26,7 +26,8 @@ Set the title to: `[Security] Description of the original issue`
- [ ] Create the branch `security-X-Y` from `X-Y-stable` if it doesn't exist (and make sure it's up to date with stable)
- [ ] Create each MR targetting the security branch `security-X-Y`
- [ ] Add the ~security label and prefix with the version `WIP: [X.Y]` the title of the MR
-- [ ] Make sure all MRs have a link in the [links section](#links) and are assigned to a Release Manager.
+- [ ] Add the ~"Merge into Security" label to all of the MRs.
+- [ ] Make sure all MRs have a link in the [links section](#links)
[secpick documentation]: https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md#secpick-script
@@ -37,6 +38,7 @@ Set the title to: `[Security] Description of the original issue`
- [ ] Fill in any upgrade notes that users may need to take into account in the [details section](#details)
- [ ] Add Yes/No and further details if needed to the migration and settings columns in the [details section](#details)
- [ ] Add the nickname of the external user who found the issue (and/or HackerOne profile) to the Thanks row in the [details section](#details)
+- [ ] Once your `master` MR is merged, comment on the original security issue with a link to that MR indicating the issue is fixed.
### Summary
diff --git a/.gitlab/issue_templates/Test plan.md b/.gitlab/issue_templates/Test plan.md
index 580fab206b3..a3c3f4a6509 100644
--- a/.gitlab/issue_templates/Test plan.md
+++ b/.gitlab/issue_templates/Test plan.md
@@ -38,22 +38,22 @@ test plan](https://testing.googleblog.com/2011/09/10-minute-test-plan.html) and
[this wiki page from an open-source tool that implements the ACC
model](https://code.google.com/archive/p/test-analytics/wikis/AccExplained.wiki). -->
-| | Simple | Secure | Responsive | Obvious | Stable |
-|------------|:------:|:------:|:----------:|:-------:|:------:|
-| Admin | | | | | |
-| Groups | | | | | |
-| Project | | | | | |
-| Repository | | | | | |
-| Issues | | | | | |
-| MRs | | | | | |
-| CI/CD | | | | | |
-| Ops | | | | | |
-| Registry | | | | | |
-| Wiki | | | | | |
-| Snippets | | | | | |
-| Settings | | | | | |
-| Tracking | | | | | |
-| API | | | | | |
+| | Secure | Responsive | Intuitive | Reliable |
+|------------|:------:|:----------:|:---------:|:--------:|
+| Admin | | | | |
+| Groups | | | | |
+| Project | | | | |
+| Repository | | | | |
+| Issues | | | | |
+| MRs | | | | |
+| CI/CD | | | | |
+| Ops | | | | |
+| Registry | | | | |
+| Wiki | | | | |
+| Snippets | | | | |
+| Settings | | | | |
+| Tracking | | | | |
+| API | | | | |
## Capabilities
@@ -64,8 +64,8 @@ Some features might be simple enough that they only involve one Component, while
more complex features could involve multiple or even all.
Example (from https://gitlab.com/gitlab-org/gitlab-ce/issues/50353):
-* Respository is
- * Simple
+* Repository is
+ * Intuitive
* It's easy to select the desired file template
* It doesn't require unnecessary actions to save the change
* It's easy to undo the change after selecting a template
@@ -93,4 +93,4 @@ When adding new automated tests, please keep [testing levels](https://docs.gitla
in mind.
-->
-/label ~Quality \ No newline at end of file
+/label ~Quality ~"test plan"
diff --git a/.gitlab/merge_request_templates/Database changes.md b/.gitlab/merge_request_templates/Database changes.md
index e636ec313df..354393b60e0 100644
--- a/.gitlab/merge_request_templates/Database changes.md
+++ b/.gitlab/merge_request_templates/Database changes.md
@@ -1,8 +1,23 @@
-Add a description of your merge request here. Merge requests without an adequate
-description will not be reviewed until one is added.
+## What does this MR do?
+
+<!--
+Describe in detail what your merge request does, why it does that, etc. Merge
+requests without an adequate description will not be reviewed until one is
+added.
+
+Please also keep this description up-to-date with any discussion that takes
+place so that reviewers can understand your intent. This is especially
+important if they didn't participate in the discussion.
+
+Make sure to remove this comment when you are done.
+-->
+
+Add a description of your merge request here.
## Database checklist
+- [ ] Conforms to the [database guides](https://docs.gitlab.com/ee/development/README.html#databases-guides)
+
When adding migrations:
- [ ] Updated `db/schema.rb`
@@ -35,16 +50,9 @@ When removing columns, tables, indexes or other structures:
- [ ] [Changelog entry](https://docs.gitlab.com/ee/development/changelog.html) added, if necessary
- [ ] [Documentation created/updated](https://docs.gitlab.com/ee/development/documentation/index.html#contributing-to-docs)
-- [ ] [API support added](https://docs.gitlab.com/ee/development/api_styleguide.html)
- [ ] [Tests added for this feature/bug](https://docs.gitlab.com/ee/development/testing_guide/index.html)
-- Conforms to the [code review guidelines](https://docs.gitlab.com/ee/development/code_review.html)
- - [ ] Has been reviewed by a Backend [maintainer](https://about.gitlab.com/handbook/engineering/#maintainer)
- - [ ] Has been reviewed by a Database [specialist](https://about.gitlab.com/team/structure/#specialist)
+- [ ] Conforms to the [code review guidelines](https://docs.gitlab.com/ee/development/code_review.html)
- [ ] Conforms to the [merge request performance guidelines](https://docs.gitlab.com/ee/development/merge_request_performance_guidelines.html)
- [ ] Conforms to the [style guides](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/CONTRIBUTING.md#style-guides)
-- [ ] If you have multiple commits, please combine them into a few logically organized commits by [squashing them](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)
-- [ ] [Internationalization required/considered](https://docs.gitlab.com/ee/development/i18n/index.html)
-- [ ] For a paid feature, have we considered GitLab.com plans, how it works for groups, and is there a design for promoting it to users who aren't on the correct plan?
-- [ ] [End-to-end tests](https://docs.gitlab.com/ee/development/testing_guide/end_to_end_tests.html#testing-code-in-merge-requests) pass (`package-and-qa` manual pipeline job)
/label ~database
diff --git a/.gitlab/merge_request_templates/Documentation.md b/.gitlab/merge_request_templates/Documentation.md
index ca38c881c66..8b7e7119790 100644
--- a/.gitlab/merge_request_templates/Documentation.md
+++ b/.gitlab/merge_request_templates/Documentation.md
@@ -19,6 +19,7 @@ Closes
- [ ] [Apply the correct labels and milestone](https://docs.gitlab.com/ee/development/documentation/workflow.html#2-developer-s-role-in-the-documentation-process)
- [ ] Crosslink the document from the higher-level index
- [ ] Crosslink the document from other subject-related docs
+- [ ] Feature moving tiers? Make sure the change is also reflected in [`features.yml`](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/features.yml)
- [ ] Correctly apply the product [badges](https://docs.gitlab.com/ee/development/documentation/styleguide.html#product-badges) and [tiers](https://docs.gitlab.com/ee/development/documentation/styleguide.html#gitlab-versions-and-tiers)
- [ ] [Port the MR to EE (or backport from CE)](https://docs.gitlab.com/ee/development/documentation/index.html#cherry-picking-from-ce-to-ee): _always recommended, required when the `ee-compat-check` job fails_
diff --git a/.nvmrc b/.nvmrc
index dba04c1e178..db24ab967fb 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-8.11.3
+10.13.0
diff --git a/.prettierignore b/.prettierignore
index b674ccd50cf..dc9e572ab54 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -3,3 +3,7 @@
/public/
/vendor/
/tmp/
+
+# ignore stylesheets for now as this clashes with our linter
+*.css
+*.scss
diff --git a/.rubocop.yml b/.rubocop.yml
index ce7be208186..741403af009 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -3,7 +3,9 @@ inherit_gem:
- rubocop-default.yml
inherit_from: .rubocop_todo.yml
-require: ./rubocop/rubocop
+require:
+ - ./rubocop/rubocop
+ - rubocop-rspec
AllCops:
TargetRailsVersion: 4.2
@@ -35,6 +37,32 @@ Style/MutableConstant:
Style/SafeNavigation:
Enabled: false
+# Frozen String Literal
+Style/FrozenStringLiteralComment:
+ Enabled: true
+ Exclude:
+ - 'config.ru'
+ - 'Dangerfile'
+ - 'Gemfile'
+ - 'Rakefile'
+ - 'app/views/**/*'
+ - 'config/**/*'
+ - 'danger/**/*'
+ - 'db/**/*'
+ - 'ee/**/*'
+ - 'lib/tasks/**/*'
+ - 'qa/**/*'
+ - 'rubocop/**/*'
+ - 'scripts/**/*'
+ - 'spec/**/*'
+
+RSpec/FilePath:
+ Exclude:
+ - 'qa/**/*'
+ - 'spec/javascripts/fixtures/*'
+ - 'ee/spec/javascripts/fixtures/*'
+ - 'spec/requests/api/v3/*'
+
Naming/FileName:
ExpectMatchingDefinition: true
Exclude:
@@ -47,15 +75,20 @@ Naming/FileName:
- 'qa/qa/specs/**/*'
- 'qa/bin/*'
- 'config/**/*'
+ - 'ee/config/**/*'
- 'lib/generators/**/*'
- 'locale/unfound_translations.rb'
- 'ee/locale/unfound_translations.rb'
- 'ee/lib/generators/**/*'
+ - 'qa/qa/scenario/test/integration/ldap_no_tls.rb'
+ - 'qa/qa/scenario/test/integration/ldap_tls.rb'
+
IgnoreExecutableScripts: true
AllowedAcronyms:
- EE
- JSON
- LDAP
+ - SAML
- IO
- HMAC
- QA
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index d8c4e965190..571df7534cb 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -10,24 +10,6 @@
Capybara/CurrentPathExpectation:
Enabled: false
-# Offense count: 23
-FactoryBot/DynamicAttributeDefinedStatically:
- Exclude:
- - 'spec/factories/broadcast_messages.rb'
- - 'spec/factories/ci/builds.rb'
- - 'spec/factories/ci/runners.rb'
- - 'spec/factories/clusters/applications/helm.rb'
- - 'spec/factories/clusters/platforms/kubernetes.rb'
- - 'spec/factories/emails.rb'
- - 'spec/factories/gpg_keys.rb'
- - 'spec/factories/group_members.rb'
- - 'spec/factories/merge_requests.rb'
- - 'spec/factories/notes.rb'
- - 'spec/factories/oauth_access_grants.rb'
- - 'spec/factories/project_members.rb'
- - 'spec/factories/todos.rb'
- - 'spec/factories/uploads.rb'
-
# Offense count: 167
# Cop supports --auto-correct.
Layout/EmptyLinesAroundArguments:
@@ -53,20 +35,6 @@ Layout/IndentArray:
Layout/IndentHash:
Enabled: false
-# Offense count: 11
-# Cop supports --auto-correct.
-# Configuration parameters: AllowForAlignment.
-Layout/SpaceBeforeFirstArg:
- Exclude:
- - 'config/routes/project.rb'
- - 'db/migrate/20170506185517_add_foreign_key_pipeline_schedules_and_pipelines.rb'
- - 'features/steps/project/source/browse_files.rb'
- - 'features/steps/project/source/markdown_render.rb'
- - 'lib/api/runners.rb'
- - 'spec/features/search/user_uses_search_filters_spec.rb'
- - 'spec/routing/project_routing_spec.rb'
- - 'spec/services/system_note_service_spec.rb'
-
# Offense count: 93
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
@@ -74,15 +42,6 @@ Layout/SpaceBeforeFirstArg:
Layout/SpaceInLambdaLiteral:
Enabled: false
-# Offense count: 1
-# Cop supports --auto-correct.
-# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBrackets.
-# SupportedStyles: space, no_space, compact
-# SupportedStylesForEmptyBrackets: space, no_space
-Layout/SpaceInsideArrayLiteralBrackets:
- Exclude:
- - 'spec/lib/gitlab/import_export/relation_factory_spec.rb'
-
# Offense count: 327
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
@@ -96,14 +55,6 @@ Layout/SpaceInsideBlockBraces:
Layout/SpaceInsideParens:
Enabled: false
-# Offense count: 14
-# Cop supports --auto-correct.
-Layout/SpaceInsidePercentLiteralDelimiters:
- Exclude:
- - 'lib/gitlab/git_access.rb'
- - 'lib/gitlab/health_checks/fs_shards_check.rb'
- - 'spec/lib/gitlab/health_checks/fs_shards_check_spec.rb'
-
# Offense count: 26
Lint/DuplicateMethods:
Exclude:
@@ -135,31 +86,11 @@ Lint/InterpolationCheck:
Lint/MissingCopEnableDirective:
Enabled: false
-# Offense count: 2
-Lint/NestedPercentLiteral:
- Exclude:
- - 'lib/gitlab/git/repository.rb'
- - 'spec/support/shared_examples/email_format_shared_examples.rb'
-
# Offense count: 1
Lint/ReturnInVoidContext:
Exclude:
- 'app/models/project.rb'
-# Offense count: 1
-# Configuration parameters: IgnoreImplicitReferences.
-Lint/ShadowedArgument:
- Exclude:
- - 'lib/gitlab/database/sha_attribute.rb'
-
-# Offense count: 3
-# Cop supports --auto-correct.
-Lint/UnneededRequireStatement:
- Exclude:
- - 'db/post_migrate/20161221153951_rename_reserved_project_names.rb'
- - 'db/post_migrate/20170313133418_rename_more_reserved_project_names.rb'
- - 'lib/declarative_policy.rb'
-
# Offense count: 9
Lint/UriEscapeUnescape:
Exclude:
@@ -199,16 +130,6 @@ Naming/HeredocDelimiterCase:
Naming/HeredocDelimiterNaming:
Enabled: false
-# Offense count: 1
-Performance/UnfreezeString:
- Exclude:
- - 'features/steps/project/commits/commits.rb'
-
-# Offense count: 1
-# Cop supports --auto-correct.
-Performance/UriDefaultParser:
- Exclude:
- - 'lib/gitlab/url_sanitizer.rb'
# Offense count: 3821
# Configuration parameters: Prefixes.
@@ -445,7 +366,6 @@ Style/Dir:
# Cop supports --auto-correct.
Style/EachWithObject:
Exclude:
- - 'config/initializers/gollum.rb'
- 'lib/expand_variables.rb'
- 'lib/gitlab/ci/ansi2html.rb'
- 'lib/gitlab/ee_compat_check.rb'
diff --git a/.ruby-version b/.ruby-version
index 79a614418f7..aedc15bb0c6 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-2.4.4
+2.5.3
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e514a42108c..d41e5c8642f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,736 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 11.5.2 (2018-12-03)
+
+### Removed (1 change)
+
+- Removed Site Statistics optimization as it was causing problems. !23314
+
+### Fixed (6 changes, 1 of them is from the community)
+
+- Display impersonation token value only after creation. !22916
+- Fix not render emoji in filter dropdown. !23112 (Hiroyuki Sato)
+- Fixes stuck tooltip on stop env button. !23244
+- Correctly handle data-loss scenarios when encrypting columns. !23306
+- Clear BatchLoader context between Sidekiq jobs. !23308
+- Fix handling of filenames with hash characters in tree view. !23368
+
+
+## 11.5.1 (2018-11-26)
+
+### Security (17 changes)
+
+- Escape user fullname while rendering autocomplete template to prevent XSS.
+- Fix CRLF vulnerability in Project hooks.
+- Fix possible XSS attack in Markdown urls with spaces.
+- Redact sensitive information on gitlab-workhorse log.
+- Do not follow redirects in Prometheus service when making http requests to the configured api url.
+- Don't expose confidential information in commit message list.
+- Provide email notification when a user changes their email address.
+- Restrict Personal Access Tokens to API scope on web requests.
+- Resolve reflected XSS in Ouath authorize window.
+- Fix SSRF in project integrations.
+- Fixed ability to comment on locked/confidential issues.
+- Fixed ability of guest users to edit/delete comments on locked or confidential issues.
+- Fix milestone promotion authorization check.
+- Configure mermaid to not render HTML content in diagrams.
+- Fix a possible symlink time of check to time of use race condition in GitLab Pages.
+- Removed ability to see private group names when the group id is entered in the url.
+- Fix stored XSS for Environments.
+
+
+## 11.5.0 (2018-11-22)
+
+### Security (10 changes, 1 of them is from the community)
+
+- Escape entity title while autocomplete template rendering to prevent XSS. !2556
+- Update moment to 2.22.2. !22648 (Takuya Noguchi)
+- Redact personal tokens in unsubscribe links.
+- Escape user fullname while rendering autocomplete template to prevent XSS.
+- Persist only SHA digest of PersonalAccessToken#token.
+- Monkey kubeclient to not follow any redirects.
+- Prevent SSRF attacks in HipChat integration.
+- Prevent templated services from being imported.
+- Validate Wiki attachments are valid temporary files.
+- Fix XSS in merge request source branch name.
+
+### Removed (2 changes)
+
+- Remove Git circuit breaker. !22212
+- Remove Koding integration and documentation. !22334
+
+### Fixed (74 changes, 15 of them are from the community)
+
+- Hide all tables on Pipeline when no Jobs for the Pipeline. !18540 (Takuya Noguchi)
+- Fixing count on Milestones. !21446
+- Use case insensitve username lookups. !21728 (William George)
+- Correctly process Bamboo API result array. !21970 (Alex Lossent)
+- Fix 'merged with' UI being displayed when merge request has no merge commit. !22022
+- Fix broken file name navigation on MRs. !22109
+- Fix incorrect spacing between buttons when commenting on a MR. !22135
+- Vertical align Pipeline Graph in Commit Page. !22173 (Johann Hubert Sonntagbauer)
+- Reject invalid branch names in repository compare controller. !22186
+- Fix size of emojis of user status in user menu. !22194
+- Use the standard PIP_CACHE_DIR for Python dependency caching template. !22211 (Takuya Noguchi)
+- Fix bug with wiki attachments content disposition. !22220
+- Does not allow a SSH URI when importing new projects. !22309
+- fix duplicated key in license management job auto devops gitlab ci template. !22311 (Adam Lemanski)
+- Fix commit signature error when project is disabled. !22344
+- Show available clusters when installed or updated. !22356
+- Fix auto-corrected upload URLs in webhooks. !22361
+- Fix a bug displaying certain wiki pages. !22377
+- Fix prometheus graphs in firefox. !22400
+- Resolve assign-me quick action doesn't work if there is extra white space. !22402
+- Remove base64 encoding from files that contain plain text. !22425
+- Strip whitespace around GitHub personal access tokens. !22432
+- Fix 500 error when testing webhooks with redirect loops. !22447 (Heinrich Lee Yu)
+- Fix rendering of 'Protected' value on Runner details page. !22459
+- Fix bug stopping non-admin users from changing visibility level on group creation. !22468
+- Make Issue Board sidebar show project-specific labels based on selected Issue. !22475
+- Fix EOF detection with CI artifacts metadata. !22479
+- Fix transient spec error in the bar_chart component. !22495
+- Resolve LFS not correctly showing enabled. !22501
+- If user was not found, service hooks won't run on post receive background job. !22519
+- Fix broken "Show whitespace changes" button on MRs. !22539
+- Always show new issue button in boards' Open list. !22557 (Heinrich Lee Yu)
+- Add transparent background to markdown header tabs. !22565 (George Tsiolis)
+- Use gitlab_environment for ldap rake task. !22582
+- Add commit message to commit tree anchor title. !22585
+- Cache pipeline status per SHA. !22589
+- Change HELM_HOST in Auto-DevOps template to work behind proxy. !22596 (Sergej Nikolaev <kinolaev@gmail.com>)
+- Show user status for label events in system notes. !22609
+- Fix extra merge request versions created from forked merge requests. !22611
+- Remove PersonalAccessTokensFinder#find_by method. !22617
+- Fix search "all in GitLab" not working with relative URLs. !22644
+- Fix quick links button styles. !22657 (George Tsiolis)
+- Fix #53298: JupyterHub restarts should work without errors. !22671 (Amit Rathi)
+- Fix incompatibility with IE11 due to non-transpiled gitlab-ui components. !22695
+- Fix bug when links in tabs of the labels index pages ends with .html. !22716
+- Fixed label removal from issue. !22762
+- Align toggle sidebar button across all browsers and OSs. !22771
+- Disable replication lag check for Aurora PostgreSQL databases. !22786
+- Render unescaped link for failed pipeline status. !22807
+- Fix misaligned approvers dropdown. !22832
+- Fix bug with wiki page create message. !22849
+- Fix rendering of filter bar tokens for special values. !22865 (Heinrich Lee Yu)
+- Align sign in button. !22888 (George Tsiolis)
+- Fix error handling bugs in kubernetes integration. !22922
+- Fix deployment jobs using nil KUBE_TOKEN due to migration issue. !23009
+- Avoid returning deployment metrics url to MR widget when the deployment is not successful. !23010
+- Fix a race condition intermittently breaking GitLab startup. !23028
+- Adds margin after a deleted branch name in the activity feed. !23038
+- Ignore environment validation failure. !23100
+- Fixes broken borders for reports section in MR widget.
+- Adds CI favicon back to jobs page.
+- Redirect to the pipeline builds page when a build is canceled. (Eva Kadlecova)
+- Fixed diff stats not showing when performance bar is enabled.
+- Show expand all diffs button when a single diff file is collapsed.
+- Clear fetched file templates when changing template type in Web IDE.
+- Fix bug causing not all emails to show up in commit email selectbox.
+- Remove duplicate escape in job sidebar.
+- Fixing styling issues on the scheduled pipelines page.
+- Renders stuck block when runners are stuck.
+- Removes extra border from test reports in the merge request widget.
+- Only render link to branch when branch still exists in pipeline page.
+- Fixed source project not filtering in merge request creation compare form.
+- Do not reload self on hooks when creating deployment.
+- Fixes broken test in master.
+
+### Changed (38 changes, 12 of them are from the community)
+
+- Link button in markdown editor recognize URLs. !1983 (Johann Hubert Sonntagbauer)
+- Replace i to icons in vue components. !20748 (George Tsiolis)
+- Remove Linguist gem, reducing Rails memory usage by 128MB per process. !21008
+- Issue board card design. !21229
+- On deletion of a file in sub directory in web IDE redirect to the sub directory instead of project root. !21465 (George Thomas @thegeorgeous)
+- Change single-item breadcrumbs to page titles. !22155
+- Improving branch filter sorting by listing exact matches first and added support for begins_with (^) and ends_with ($) matching. !22166 (Jason Rutherford)
+- Remove legacy unencrypted webhook columns from the database. !22199
+- Show canary status in the performance bar. !22222
+- Add failure reason for execution timeout. !22224
+- Rename "scheduled" label/badge of delayed jobs to "delayed". !22245
+- Update the empty state on wiki-only projects to display an empty state that is more consistent with the rest of the system. !22262
+- Add IID headers to E-Mail notifications. !22263
+- Allow finding the common ancestor for multiple revisions through the API. !22295
+- Add status to Deployment. !22380
+- Add dynamic timer to delayed jobs. !22382
+- No longer require a deploy to start Prometheus monitoring. !22401
+- Secret Variables renamed to CI Variables in the codebase, to match UX. !22414 (Marcel Amirault @ravlen)
+- Automatically navigate to last board visited. !22430
+- Use merge request prefix symbol in event feed title. !22449 (George Tsiolis)
+- Update Ruby version in README. !22466 (J.D. Bean)
+- Reword error message for internal CI unknown pipeline status. !22474
+- Bump mermaid to 8.0.0-rc.8. !22509 (@blackst0ne)
+- Update Todo icons in collapsed sidebar for Issues and MRs. !22534
+- Support backward compatibility when introduce new failure reason. !22566
+- Add dynamic timer for delayed jobs in pipelines list. !22621
+- Truncate milestone title on collapsed sidebar. !22624 (George Tsiolis)
+- Standardize milestones filter in APIs to None / Any. !22637 (Heinrich Lee Yu)
+- Add dynamic timer for delayed jobs in job list. !22656
+- Allowing issues with single letter identifiers to be linked to external issue tracker (f.ex T-123). !22717 (Dídac Rodríguez Arbonès)
+- Update project and group labels empty state. !22745 (George Tsiolis)
+- Fix environment status in merge request widget. !22799
+- Paginate Bitbucket Server importer projects. !22825
+- Drop `allow_overflow` option in `TimeHelper.duration_in_numbers`. !52284
+- Add 'only history' option to notes filter.
+- Adds filtered dropdown with changed files in review.
+- Expose {closed,merged}_{at,by} in merge requests API index.
+- Make all legacy security reports to use raw format.
+
+### Performance (27 changes, 6 of them are from the community)
+
+- Add preload for routes and namespaces for issues controller. !21651
+- Enhance performance of counting local LFS objects. !22143
+- Use cached readme contents when available. !22325
+- Experimental support for running Puma multithreaded web-server. !22372
+- Enhance performance of counting local Uploads. !22522
+- Reduce SQL queries needed to load open merge requests. !22709
+- Significantly cut memory usage and SQL queries when reloading diffs. !22725
+- Optimize merge request refresh by using the database to check commit SHAs. !22731
+- Remove dind from license_management auto-devops job definition. !22732
+- Add index to find stuck merge requests. !22749
+- Allow Rails concurrency when running in Puma. !22751
+- Improve performance of rendering large reports. !22835
+- Improves performance of stuck import jobs detection. !22879
+- Rewrite SnippetsFinder to improve performance by a factor of 1500.
+- Enable more frozen string in lib/**/*.rb. (gfyoung)
+- Enable some frozen string in lib/gitlab. (gfyoung)
+- Enable even more frozen string in lib/**/*.rb. (gfyoung)
+- Improve performance of tree rendering in repositories with lots of items.
+- Remove gitlab-ui's tooltip from global.
+- Remove gitlab-ui's progress bar from global.
+- Remove gitlab-ui's pagination from global.
+- Remove gitlab-ui's modal from global.
+- Remove gitlab-ui's loading icon from global.
+- Enable frozen string for lib/gitlab/*.rb. (gfyoung)
+- Enable frozen string for lib/gitlab/ci. (gfyoung)
+- Enable frozen string for remaining lib/gitlab/ci/**/*.rb. (gfyoung)
+- Adds pagination to pipelines table in merge request page.
+
+### Added (33 changes, 11 of them are from the community)
+
+- Add endpoint to update a git submodule reference. !20949
+- Add license data to projects endpoint. !21606 (J.D. Bean (@jdbean))
+- Allow to configure when to retry failed CI jobs. !21758 (Markus Doits)
+- Add API endpoint to list issue related merge requests. !21806 (Helmut Januschka)
+- Add the Play button for delayed jobs in environment page. !22106
+- Switch between tree list & file list in diffs file browser. !22191
+- Re-arrange help-related user menu items into new Help menu. !22195
+- Adds trace of each access check when git push times out. !22265
+- Add email for milestone change. !22279
+- Show post-merge pipeline in merge request page. !22292
+- Add Applications API endpoints for listing and deleting entries. !22296 (Jean-Baptiste Vasseur)
+- Added `Any` option to milestones filter. !22351 (Heinrich Lee Yu)
+- Improve validation errors for external CI/CD configuration. !22394
+- Introduce new model to persist specific cluster information. !22404
+- Add background migration to populate Kubernetes namespaces. !22433
+- Add support for JSON logging for audit events. !22471
+- Adds option to override commit email with a noreply private email. !22560
+- Add None/Any option for assignee_id in Issues and Merge Requests API. !22598 (Heinrich Lee Yu)
+- Add None/Any option for assignee_id in search bar. !22599 (Heinrich Lee Yu)
+- Implement parallel job keyword. !22631
+- Add None / Any options to reactions filter. !22638 (Heinrich Lee Yu)
+- Make index.* render like README.* when it's present in a repository. !22639 (Jakub Jirutka)
+- Allow adding patches when creating a merge request via email. !22723 (Serdar Dogruyol)
+- Bump Gitaly to 0.129.0. !22868
+- Allow commenting on any diff line in Merge Requests. !22914
+- Add revert to commits API. !22919
+- Introduce Knative support. !43959 (Chris Baumbauer)
+- Reimplemented image commenting in merge request diffs.
+- Soft-archive old jobs.
+- Renders warning info when job is archieved.
+- Support licenses and performance.
+- Filter notes by comments or activity for issues and merge requests.
+- Bump Gitaly to 0.128.0.
+
+### Other (54 changes, 18 of them are from the community)
+
+- Remove .card-title from .card-header for BS4 migration. !19335 (Takuya Noguchi)
+- Update group settings/edit page to new design. !21115
+- Change markdown header tab anchor links to buttons. !21988 (George Tsiolis)
+- Replace tooltip in markdown component with gl-tooltip. !21989 (George Tsiolis)
+- Extend RBAC by having a service account restricted to project's namespace. !22011
+- Update images in group docs. !22031 (Marc Schwede)
+- Add gitlab:gitaly:check task for Gitaly health check. !22063
+- Add new sort option "most_stars" to "Group > Children" pages. !22121 (Rene Hennig)
+- Fix inaccessible dropdown for code-less projects. !22137
+- Rails5: fix user edit profile clear status spec. !22169 (Jasper Maes)
+- Rails 5: fix mysql milliseconds problems in scheduled build specs. !22170 (Jasper Maes)
+- Focus project slug on tab navigation. !22198
+- Redesign activity feed. !22217
+- Update used version of Runner Helm Chart to 0.1.34. !22274
+- Update environments empty state. !22297 (George Tsiolis)
+- Adds model and migrations to enable group level clusters. !22307
+- Use literal instead of constructor for creating regex. !22367
+- Remove prometheus configuration help text. !22413 (George Tsiolis)
+- Rails5: fix deployment model spec. !22428 (Jasper Maes)
+- Change to top level controller for clusters so that we can use it for project clusters (now) and group clusters (later). !22438
+- Remove empty spec describe blocks. !22451 (George Tsiolis)
+- Change branch font type in tag creation. !22454 (George Tsiolis)
+- Rails5: fix delete blob. !22456 (Jasper Maes)
+- Start tracking shards and pool repositories in the database. !22482
+- Allow kubeclient to call RoleBinding methods. !22524
+- Introduce new kubernetes helpers. !22525
+- Adds container to pager to enable scoping. !22529
+- Update used version of Runner Helm Chart to 0.1.35. !22541
+- Removes experimental labels from cluster views. !22550
+- Combine all datetime library functions into 'datetime_utility.js'. !22570
+- Upgrade Prometheus to 2.4.3 and Alertmanager to 0.15.2. !22600
+- Fix stage dropdown not rendering in different languages. !22604
+- Remove asset_sync gem from Gemfile and related code from codebase. !22610
+- Use key-value pair arrays for API query parameter logging instead of hashes. !22623
+- Replace deprecated uniq on a Relation with distinct. !22625 (Jasper Maes)
+- Remove mousetrap-rails gem. !22647 (Takuya Noguchi)
+- Fix IDE typos in props. !22685 (George Tsiolis)
+- Add scheduled flag to job entity. !22710
+- Remove `ci_enable_scheduled_build` feature flag. !22742
+- Add endpoints for simulating certain failure modes in the application. !22746
+- Bump KUBERNETES_VERSION for Auto DevOps to latest 1.10 series. !22757
+- Fix statement timeouts in RemoveRestrictedTodos migration. !22795
+- Rails5: fix mysql milliseconds issue in deployment model specs. !22850 (Jasper Maes)
+- Update GitLab-Workhorse to v7.1.0. !22883
+- Update JIRA service UI to accept email and API token.
+- Update wiki empty state. (George Tsiolis)
+- Only renders dropdown for review app changes when we have a list of files to show. Otherwise will render the regular review app button.
+- Associate Rakefile with Ruby icon in diffs.
+- Uses gitlab-ui components in jobs components.
+- Create new group: Rename form fields and update UI.
+- Transform job page into a single Vue+Vuex application.
+- Updates svg dependency.
+- Adds missing i18n to pipelines table.
+- Disables stop environment button while the deploy is in progress.
+
+
+## 11.4.9 (2018-12-03)
+
+### Fixed (2 changes)
+
+- Display impersonation token value only after creation. !22916
+- Correctly handle data-loss scenarios when encrypting columns. !23306
+
+
+## 11.4.8 (2018-11-27)
+
+### Security (24 changes)
+
+- Escape entity title while autocomplete template rendering to prevent XSS. !2571
+- Resolve reflected XSS in Ouath authorize window.
+- Fix XSS in merge request source branch name.
+- Escape user fullname while rendering autocomplete template to prevent XSS.
+- Fix CRLF vulnerability in Project hooks.
+- Fix possible XSS attack in Markdown urls with spaces.
+- Redact sensitive information on gitlab-workhorse log.
+- Do not follow redirects in Prometheus service when making http requests to the configured api url.
+- Persist only SHA digest of PersonalAccessToken#token.
+- Don't expose confidential information in commit message list.
+- Provide email notification when a user changes their email address.
+- Restrict Personal Access Tokens to API scope on web requests.
+- Redact personal tokens in unsubscribe links.
+- Fix SSRF in project integrations.
+- Fixed ability to comment on locked/confidential issues.
+- Fixed ability of guest users to edit/delete comments on locked or confidential issues.
+- Fix milestone promotion authorization check.
+- Monkey kubeclient to not follow any redirects.
+- Configure mermaid to not render HTML content in diagrams.
+- Fix a possible symlink time of check to time of use race condition in GitLab Pages.
+- Removed ability to see private group names when the group id is entered in the url.
+- Fix stored XSS for Environments.
+- Prevent SSRF attacks in HipChat integration.
+- Validate Wiki attachments are valid temporary files.
+
+
+## 11.4.7 (2018-11-20)
+
+- No changes.
+
+## 11.4.6 (2018-11-18)
+
+### Security (1 change)
+
+- Escape user fullname while rendering autocomplete template to prevent XSS.
+
+
+## 11.4.5 (2018-11-04)
+
+### Fixed (4 changes, 1 of them is from the community)
+
+- fix link to enable usage ping from convdev index. !22545 (Anand Capur)
+- Update gitlab-ui dependency to 1.8.0-hotfix.1 to fix IE11 bug.
+- Remove duplicate escape in job sidebar.
+- Fixed merge request fill tree toggling not respecting fluid width preference.
+
+### Other (1 change)
+
+- Fix stage dropdown not rendering in different languages.
+
+
+## 11.4.4 (2018-10-30)
+
+### Security (1 change)
+
+- Monkey kubeclient to not follow any redirects.
+
+
+## 11.4.3 (2018-10-26)
+
+- No changes.
+
+## 11.4.2 (2018-10-25)
+
+### Security (5 changes)
+
+- Escape entity title while autocomplete template rendering to prevent XSS. !2571
+- Persist only SHA digest of PersonalAccessToken#token.
+- Redact personal tokens in unsubscribe links.
+- Block loopback addresses in UrlBlocker.
+- Validate Wiki attachments are valid temporary files.
+
+
+## 11.4.1 (2018-10-23)
+
+### Security (2 changes)
+
+- Fix XSS in merge request source branch name.
+- Prevent SSRF attacks in HipChat integration.
+
+
+## 11.4.0 (2018-10-22)
+
+### Security (9 changes)
+
+- Filter user sensitive data from discussions JSON. !2536
+- Encrypt webhook tokens and URLs in the database. !21645
+- Redact confidential events in the API.
+- Set timeout for syntax highlighting.
+- Sanitize JSON data properly to fix XSS on Issue details page.
+- Markdown API no longer displays confidential title references unless authorized.
+- Properly filter private references from system notes.
+- Fix stored XSS in merge requests from imported repository.
+- Fix xss vulnerability sourced from package.json.
+
+### Removed (2 changes)
+
+- Remove background job throttling feature. !21748
+- Remove sidekiq info from performance bar.
+
+### Fixed (68 changes, 18 of them are from the community)
+
+- Fixes 500 for cherry pick API with empty branch name. !21501 (Jacopo Beschi @jacopo-beschi)
+- Fix sorting by priority or popularity on group issues page, when also searching issue content. !21521
+- Fix vertical alignment of text in diffs. !21573
+- Fix performance bar modal position. !21577
+- Bump KaTeX version to 0.9.0. !21625
+- Correctly show legacy diff notes in the merge request changes tab. !21652
+- Synchronize the default branch when updating a remote mirror. !21653
+- Filter group milestones based on user membership. !21660
+- Fix double title in merge request chat messages. !21670 (Kukovskii Vladimir)
+- Delete container repository tags outside of transaction. !21679
+- Images are no longer displayed in Todo descriptions. !21704
+- Fixed merge request widget discussion state not updating after resolving discussions. !21705
+- Vendor Auto-DevOps.gitlab-ci.yml to fix bug where the deploy job does not wait for Deployment to complete. !21713
+- Use Reliable Sidekiq fetch. !21715
+- No longer show open issues from archived projects in group issue board. !21721
+- Issue and MR count now ignores archived projects. !21721
+- Fix resizing of monitoring dashboard. !21730
+- Fix object storage uploads not working with AWS v2. !21731
+- Don't ignore first action when assign and unassign quick actions are used in the same comment. !21749
+- Align form labels following Bootstrap 4 docs. !21752
+- Respect the user commit email in more places. !21773
+- Use stats RPC when comparing diffs. !21778
+- Show commit details for selected commit in MR diffs. !21784
+- Resolve "Geo: Does not mark repositories as missing on primary due to stale cache". !21789
+- Fix leading slash in redirects and add rubocop cop. !21828 (Sanad Liaquat)
+- Fix activity titles for MRs in chat notification services. !21834
+- Hides Close Merge request btn on merged Merge request. !21840 (Jacopo Beschi @jacopo-beschi)
+- Doesn't synchronize the default branch for push mirrors. !21861
+- Fix broken styling when issue board is collapsed. !21868 (Andrea Leone)
+- Set a header for custom error pages to prevent them from being intercepted by gitlab-workhorse. !21870 (David Piegza)
+- Fix resolved discussions being unresolved when commented on. !21881
+- Fix timeout when running the RemoveRestrictedTodos background migration. !21893
+- Enable the ability to use the force env for rebuilding authorized_keys during a restore. !21896
+- Fix link handling for issue cards to avoid too sensitive drag events. !21910 (Johann Hubert Sonntagbauer)
+- Guard against a login attempt with invalid CSRF token. !21934
+- Allow setting user's organization and location attributes through the API by adding them to the list of allowed parameters. !21938 (Alexis Reigel)
+- Includes commit stats in POST project commits API. !21968 (Jacopo Beschi @jacopo-beschi)
+- Fix loading issue on some merge request discussion. !21982
+- Prevent Error 500s with invalid relative links. !22001
+- Fix stale issue boards after browser back. !22006 (Johann Hubert Sonntagbauer)
+- Filter issues without an Assignee via the API. !22009 (Eva Kadlecová)
+- Fixes modal button alignment. !22024 (Jacopo Beschi @jacopo-beschi)
+- Fix rendering placeholder notes. !22078
+- Instance Configuration page now displays correct SSH fingerprints. !22081
+- Fix showing diff file header for renamed files. !22089
+- Fix LFS uploaded images not being rendered. !22092
+- Fix the issue where long environment names aren't being truncated, causing the environment name to overlap into the column next to it. !22104
+- Trim whitespace when inviting a new user by email. !22119 (Jacopo Beschi @jacopo-beschi)
+- Fix incorrect parent path on group settings page. !22142
+- Update copy to clipboard button data for application secret. !22268 (George Tsiolis)
+- Improve MR file tree in smaller screens. !22273
+- Fix project deletion when there is a export available. !22276
+- Fixes stuck block URL linking to documentation instead of settings page. !22286
+- Fix caching issue with pipelines URL. !22293
+- Fix erased block not being rendered when job was erased. !22294
+- Load correct stage in the stages dropdown. !22317
+- Fixes close/reopen quick actions preview for issues and merge_requests. !22343 (Jacopo Beschi @jacopo-beschi)
+- Allow Issue and Merge Request sidebar to be toggled from collapsed state. !22353
+- Fix filter bar height bug when a tag is added.
+- Fix the state of the Done button when there is an error in the GitLab Todos section. (marcos8896)
+- Fix wrong text color of help text in merge request creation. (Gerard Montemayor)
+- Add borders and white background to markdown tables.
+- Fixed mention autocomplete in edit merge request.
+- Fix long webhook URL overflow for custom integration. (Kukovskii Vladimir)
+- Fixed file templates not fully being fetched in Web IDE.
+- Fixes performance bar looking for a key in a undefined prop.
+- Hides sidebar for job page in mobile.
+- Fixes triggered/created labeled in job header.
+
+### Changed (26 changes, 4 of them are from the community)
+
+- Enable unauthenticated access to public SSH keys via the API. !20118 (Ronald Claveau)
+- Support Kubernetes RBAC for GitLab Managed Apps when creating new clusters. !21401
+- Highlight current user in comments. !21406
+- Excludes project marked from deletion to projects API. !21542 (Jacopo Beschi @jacopo-beschi)
+- Improve install flow of Kubernetes cluster apps. !21567
+- Move including external files in .gitlab-ci.yml from Starter to Libre. !21603
+- Simplify runner registration token resetting. !21658
+- Filter any parameters ending with "key" in logs. !21688
+- Ensure the schema is loaded with post_migrations included. !21689
+- Updated icons used in filtered search dropdowns. !21694
+- Enable omniauth by default. !21700
+- Vendor Auto-DevOps.gitlab-ci.yml to refactor registry_login. !21714 (Laurent Goderre @LaurentGoderre)
+- Add Gitaly diff stats RPC client. !21732
+- Allow user to revoke an authorized application even if User OAuth applications setting is disabled in admin settings. !21835
+- Change vertical margin of page titles to 16px. !21888
+- Preserve order of project tags list. !21897
+- Avoid close icon leaving the modal header. !21904
+- Allow /copy_metadata for new issues and MRs. !21953
+- Link to the tag for a version on the help page instead of to the commit. !22015
+- Show SHA for pre-release versions on the help page. !22026
+- Use local tiller for Auto DevOps. !22036
+- Remove 'rbac_clusters' feature flag. !22096
+- Increased retained event data by extending events pruner timeframe to 2 years. !22145
+- Add installation type to backup information file. !22150
+- Remove duplicate button from the markdown header toolbar. !22192 (George Tsiolis)
+- Update to Rouge 3.3.0 including frozen string literals for improved memory usage.
+
+### Performance (17 changes, 6 of them are from the community)
+
+- Enable frozen string in app/controllers/**/*.rb.
+- Improve lazy image loading performance by using IntersectionObserver where available. !21565
+- Adds support for Gitaly ListLastCommitsForTree RPC in order to make bulk-fetch of commits more performant. !21921
+- Dont create license_management build when not included in license. !21958
+- Skip creating auto devops jobs for sast, container_scanning, dast, dependency_scanning when not licensed. !21959
+- Reduce queries needed to compute notification recipients. !22050
+- Banzai label ref finder - minimize SQL calls by sharing context more aggresively. !22070
+- Removes expensive dead code on main MR page request. !22153
+- Lazy load xterm custom colors css.
+- Mitigate N+1 queries when parsing commit references in comments.
+- Enable more frozen string in app/controllers/. (gfyoung)
+- Increase performance when creating discussions on diff.
+- Enable frozen string in lib/api and lib/backup. (gfyoung)
+- Enable frozen string in vestigial files. (gfyoung)
+- Enable frozen string for app/helpers/**/*.rb. (gfyoung)
+- Enable frozen string in app/graphql + app/finders. (gfyoung)
+- Enable even more frozen string in app/controllers. (gfyoung)
+
+### Added (37 changes, 21 of them are from the community)
+
+- Allow file templates to be requested at the project level. !7776
+- Add /lock and /unlock quick actions. !15197 (Mehdi Lahmam (@mehlah))
+- Added search functionality for Work In Progress (WIP) merge requests. !18119 (Chantal Rollison)
+- pipeline webhook event now contain pipeline variables. !18171 (Pierre Tardy)
+- Add markdown header toolbar button to insert table. !18480 (George Tsiolis)
+- Add link button to markdown editor toolbar. !18579 (Jan Beckmann)
+- Add access control to GitLab pages and make it possible to enable/disable it in project settings. !18589 (Tuomo Ala-Vannesluoma)
+- Add a filter bar to the admin runners view and add a state filter. !19625 (Alexis Reigel)
+- Add a type filter to the admin runners view. !19649 (Alexis Reigel)
+- Allow user to choose the email used for commits made through GitLab's UI. !21213 (Joshua Campbell)
+- Add autocomplete drop down filter for project snippets. !21458 (Fabian Schneider)
+- Allow events filter to be set in the URL in addition to cookie. !21557 (Igor @igas)
+- Adds a initialize_with_readme parameter to POST /projects. !21617 (Steve)
+- Add ability to skip user email confirmation with API. !21630
+- Add sorting for labels on labels page. !21642
+- Set user status from within user menu. !21643
+- Copy nurtch demo notebooks at Jupyter startup. !21698 (Amit Rathi)
+- Allows to sort projects by most stars. !21762 (Jacopo Beschi @jacopo-beschi)
+- Allow pipelines to schedule delayed job runs. !21767
+- Added tree of changed files to merge request diffs. !21833
+- Add GitLab version components to CI environment variables. !21853
+- Allows to chmod file with commits API. !21866 (Jacopo Beschi @jacopo-beschi)
+- Make single diff patch limit configurable. !21886
+- Extend reports feature to support Security Products. !21892
+- Adds the user's public_email attribute to the API. !21909 (Alexis Reigel)
+- Update all gitlab CI templates from gitlab-org/gitlab-ci-yml. !21929
+- Add support for setting the public email through the api. !21938 (Alexis Reigel)
+- Support db migration and initialization for Auto DevOps. !21955
+- Add subscribe filter to group and project labels pages. !21965
+- Add support for pipeline only/except policy for modified paths. !21981
+- Docs for Project/Groups members API with inherited members. !21984 (Jacopo Beschi @jacopo-beschi)
+- Adds Web IDE commits to usage ping. !22007
+- Add timed incremental rollout to Auto DevOps. !22023
+- Show percentage of language detection on the language bar. !22056 (Johann Hubert Sonntagbauer)
+- Allows to filter issues by Any milestone in the API. !22080 (Jacopo Beschi @jacopo-beschi)
+- Add button to download 2FA codes. (Luke Picciau)
+- Render log artifact files in GitLab.
+
+### Other (42 changes, 16 of them are from the community)
+
+- Send deployment information in job API. !21307
+- Split admin settings into multiple sub pages. !21467
+- Remove Rugged and shell code from Gitlab::Git. !21488
+- Add trigger information in job API. !21495
+- Add empty state illustration information in job API. !21532
+- Add retried jobs to pipeline stage. !21558
+- Rails 5: fix issue move service In rails 5, the attributes method for an enum returns the name instead of the database integer. !21616 (Jasper Maes)
+- Expose project runners in job API. !21618
+- create from template: hide checkbox for initializing repository with readme. !21646
+- Adds new 'Overview' tab on user profile page. !21663
+- Add clean-up phase for ScheduleDiffFilesDeletion migration. !21734
+- Prevents private profile help link from toggling checkbox. !21757
+- Make AutoDevOps work behind proxy. !21775 (Sergej - @kinolaev)
+- Use Vue components and new API to render Artifacts, Trigger Variables and Commit blocks on Job page. !21777
+- Add wrapper rake task to migrate all uploads to OS. !21779
+- Retroactively fill pipeline source for external pipelines. !21814
+- Rename squash before merge vue component. !21851 (George Tsiolis)
+- Fix merge request header margins. !21878
+- Fix committer typo. !21899 (George Tsiolis)
+- Adds an extra width to the responsive tables. !21928
+- Expose has_trace in job API. !21950
+- Rename block scope local variable in table pagination spec. !21969 (George Tsiolis)
+- Fix blue, orange, and red color inconsistencies. !21972
+- Update operations metrics empty state. !21974 (George Tsiolis)
+- Improve empty project placeholder for non-members and members without write access. !21977 (George Tsiolis)
+- Add copy to clipboard button for application id and secret. !21978 (George Tsiolis)
+- Add link component to UserAvatarLink component. !21986 (George Tsiolis)
+- Add link component to DownloadViewer component. !21987 (George Tsiolis)
+- Rephrase 2FA and TOTP documentation and view. !21998 (Marc Schwede)
+- Update project path on project name autofill. !22016
+- Improve logging when username update fails due to registry tags. !22038
+- Align collapsed sidebar avatar container. !22044 (George Tsiolis)
+- Rails5: fix artifacts controller download spec Rails5 has params[:file_type] as '' if file_type is included as nil in the request. !22123 (Jasper Maes)
+- Hide pagination for personal projects on profile overview tab. !22321
+- Extracts scroll position check into reusable functions.
+- Uses Vuex store in job details page and removes old mediator pattern.
+- Render 412 when invalid UTF-8 parameters are passed to controller.
+- Renders Job show page in new Vue app.
+- Add link to User Snippets in breadcrumbs of New User Snippet page. (J.D. Bean)
+- Log project services errors when executing async.
+- Update docs regarding frozen string. (gfyoung)
+- Check frozen string in style builds. (gfyoung)
+
+
+## 11.3.11 (2018-11-26)
+
+### Security (33 changes)
+
+- Filter user sensitive data from discussions JSON. !2537
+- Escape entity title while autocomplete template rendering to prevent XSS. !2557
+- Restrict Personal Access Tokens to API scope on web requests.
+- Fix XSS in merge request source branch name.
+- Escape user fullname while rendering autocomplete template to prevent XSS.
+- Fix CRLF vulnerability in Project hooks.
+- Fix possible XSS attack in Markdown urls with spaces.
+- Redact sensitive information on gitlab-workhorse log.
+- Set timeout for syntax highlighting.
+- Do not follow redirects in Prometheus service when making http requests to the configured api url.
+- Persist only SHA digest of PersonalAccessToken#token.
+- Sanitize JSON data properly to fix XSS on Issue details page.
+- Don't expose confidential information in commit message list.
+- Markdown API no longer displays confidential title references unless authorized.
+- Provide email notification when a user changes their email address.
+- Properly filter private references from system notes.
+- Redact personal tokens in unsubscribe links.
+- Resolve reflected XSS in Ouath authorize window.
+- Fix SSRF in project integrations.
+- Fix stored XSS in merge requests from imported repository.
+- Fixed ability to comment on locked/confidential issues.
+- Fixed ability of guest users to edit/delete comments on locked or confidential issues.
+- Fix milestone promotion authorization check.
+- Monkey kubeclient to not follow any redirects.
+- Configure mermaid to not render HTML content in diagrams.
+- Redact confidential events in the API.
+- Fix xss vulnerability sourced from package.json.
+- Fix a possible symlink time of check to time of use race condition in GitLab Pages.
+- Removed ability to see private group names when the group id is entered in the url.
+- Fix stored XSS for Environments.
+- Block loopback addresses in UrlBlocker.
+- Prevent SSRF attacks in HipChat integration.
+- Validate Wiki attachments are valid temporary files.
+
+
+## 11.3.10 (2018-11-18)
+
+### Security (1 change)
+
+- Escape user fullname while rendering autocomplete template to prevent XSS.
+
+
+## 11.3.9 (2018-10-31)
+
+### Security (1 change)
+
+- Monkey kubeclient to not follow any redirects.
+
+
+## 11.3.8 (2018-10-27)
+
+- No changes.
+
+## 11.3.7 (2018-10-26)
+
+### Security (6 changes)
+
+- Escape entity title while autocomplete template rendering to prevent XSS. !2557
+- Persist only SHA digest of PersonalAccessToken#token.
+- Fix XSS in merge request source branch name.
+- Redact personal tokens in unsubscribe links.
+- Prevent SSRF attacks in HipChat integration.
+- Validate Wiki attachments are valid temporary files.
+
+
+## 11.3.6 (2018-10-17)
+
+- No changes.
+
+## 11.3.5 (2018-10-15)
+
+### Fixed (2 changes)
+
+- Fix loading issue on some merge request discussion. !21982
+- Fix project deletion when there is a export available. !22276
+
+
+## 11.3.3 (2018-10-04)
+
+- No changes.
+
+## 11.3.2 (2018-10-03)
+
+### Fixed (4 changes)
+
+- Fix NULL pipeline import problem and pipeline user mapping issue. !21875
+- Fix migration to avoid an exception during upgrade. !22055
+- Fixes admin runners table not wrapping content.
+- Fix Error 500 when forking projects with Gravatar disabled.
+
+### Other (1 change)
+
+- Removes the 'required' attribute from the 'project name' field. !21770
+
+
+## 11.3.1 (2018-09-26)
+
+### Security (6 changes)
+
+- Redact confidential events in the API.
+- Set timeout for syntax highlighting.
+- Sanitize JSON data properly to fix XSS on Issue details page.
+- Fix stored XSS in merge requests from imported repository.
+- Fix xss vulnerability sourced from package.json.
+- Block loopback addresses in UrlBlocker.
+
+
## 11.3.0 (2018-09-22)
### Security (5 changes, 1 of them is from the community)
@@ -249,6 +979,49 @@ entry.
- Creates Vue component for artifacts block on job page.
+## 11.2.8 (2018-10-31)
+
+### Security (1 change)
+
+- Monkey kubeclient to not follow any redirects.
+
+
+## 11.2.7 (2018-10-27)
+
+- No changes.
+
+## 11.2.6 (2018-10-26)
+
+### Security (5 changes)
+
+- Escape entity title while autocomplete template rendering to prevent XSS. !2558
+- Fix XSS in merge request source branch name.
+- Redact personal tokens in unsubscribe links.
+- Persist only SHA digest of PersonalAccessToken#token.
+- Prevent SSRF attacks in HipChat integration.
+
+
+## 11.2.5 (2018-10-05)
+
+### Security (3 changes)
+
+- Filter user sensitive data from discussions JSON. !2538
+- Properly filter private references from system notes.
+- Markdown API no longer displays confidential title references unless authorized.
+
+
+## 11.2.4 (2018-09-26)
+
+### Security (6 changes)
+
+- Redact confidential events in the API.
+- Set timeout for syntax highlighting.
+- Sanitize JSON data properly to fix XSS on Issue details page.
+- Fix stored XSS in merge requests from imported repository.
+- Fix xss vulnerability sourced from package.json.
+- Block loopback addresses in UrlBlocker.
+
+
## 11.2.3 (2018-08-28)
### Fixed (1 change)
@@ -516,6 +1289,27 @@ entry.
- Moves help_popover component to a common location.
+## 11.1.8 (2018-10-05)
+
+### Security (3 changes)
+
+- Filter user sensitive data from discussions JSON. !2539
+- Properly filter private references from system notes.
+- Markdown API no longer displays confidential title references unless authorized.
+
+
+## 11.1.7 (2018-09-26)
+
+### Security (6 changes)
+
+- Redact confidential events in the API.
+- Set timeout for syntax highlighting.
+- Sanitize JSON data properly to fix XSS on Issue details page.
+- Fix stored XSS in merge requests from imported repository.
+- Fix xss vulnerability sourced from package.json.
+- Block loopback addresses in UrlBlocker.
+
+
## 11.1.6 (2018-08-28)
### Fixed (1 change)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8596037afa3..4304f6c8744 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -64,182 +64,56 @@ As of July 2018, all the documentation for contributing to the GitLab project ha
## Contribute to GitLab
-Thank you for your interest in contributing to GitLab. This guide details how
-to contribute to GitLab in a way that is easy for everyone.
-
-For a first-time step-by-step guide to the contribution process, please see
-["Contributing to GitLab"](https://about.gitlab.com/contributing/).
-
-Looking for something to work on? Look for issues in the [Backlog (Accepting merge requests) milestone](#i-want-to-contribute).
-
-GitLab comes into two flavors, GitLab Community Edition (CE) our free and open
-source edition, and GitLab Enterprise Edition (EE) which is our commercial
-edition. Throughout this guide you will see references to CE and EE for
-abbreviation.
-
-If you want to know how the GitLab [core team]
-operates please see [the GitLab contributing process](PROCESS.md).
-
-[GitLab Inc engineers should refer to the engineering workflow document](https://about.gitlab.com/handbook/engineering/workflow/)
+This [documentation](doc/development/contributing/index.md#contribute-to-gitlab) has been moved.
## Security vulnerability disclosure
-Please report suspected security vulnerabilities in private to
-`support@gitlab.com`, also see the
-[disclosure section on the GitLab.com website](https://about.gitlab.com/disclosure/).
-Please do **NOT** create publicly viewable issues for suspected security
-vulnerabilities.
-
-## Code of conduct
-
-As contributors and maintainers of this project, we pledge to respect all
-people who contribute through reporting issues, posting feature requests,
-updating documentation, submitting pull requests or patches, and other
-activities.
-
-We are committed to making participation in this project a harassment-free
-experience for everyone, regardless of level of experience, gender, gender
-identity and expression, sexual orientation, disability, personal appearance,
-body size, race, ethnicity, age, or religion.
-
-Examples of unacceptable behavior by participants include the use of sexual
-language or imagery, derogatory comments or personal attacks, trolling, public
-or private harassment, insults, or other unprofessional conduct.
+This [documentation](doc/development/contributing/index.md#security-vulnerability-disclosure) has been moved.
-Project maintainers have the right and responsibility to remove, edit, or
-reject comments, commits, code, wiki edits, issues, and other contributions
-that are not aligned to this Code of Conduct. Project maintainers who do not
-follow the Code of Conduct may be removed from the project team.
+## Code of Conduct
-This code of conduct applies both within project spaces and in public spaces
-when an individual is representing the project or its community.
-
-Instances of abusive, harassing, or otherwise unacceptable behavior can be
-reported by emailing `contact@gitlab.com`.
-
-This Code of Conduct is adapted from the [Contributor Covenant][contributor-covenant], version 1.1.0,
-available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/).
+This [documentation](https://about.gitlab.com/contributing/code-of-conduct/) has been moved.
## Closing policy for issues and merge requests
-GitLab is a popular open source project and the capacity to deal with issues
-and merge requests is limited. Out of respect for our volunteers, issues and
-merge requests not in line with the guidelines listed in this document may be
-closed without notice.
-
-Please treat our volunteers with courtesy and respect, it will go a long way
-towards getting your issue resolved.
-
-Issues and merge requests should be in English and contain appropriate language
-for audiences of all ages.
-
-If a contributor is no longer actively working on a submitted merge request
-we can decide that the merge request will be finished by one of our
-[Merge request coaches][team] or close the merge request. We make this decision
-based on how important the change is for our product vision. If a Merge request
-coach is going to finish the merge request we assign the
-~"coach will finish" label.
+This [documentation](doc/development/contributing/index.md#closing-policy-for-issues-and-merge-requests) has been moved.
## Helping others
-Please help other GitLab users when you can.
-The methods people will use to seek help can be found on the [getting help page][getting-help].
-
-Sign up for the mailing list, answer GitLab questions on StackOverflow or
-respond in the IRC channel. You can also sign up on [CodeTriage][codetriage] to help with
-the remaining issues on the GitHub issue tracker.
+This [documentation](doc/development/contributing/index.md#helping-others) has been moved.
## I want to contribute!
-If you want to contribute to GitLab, [issues in the Backlog (Accepting merge requests)](https://gitlab.com/gitlab-org/gitlab-ce/issues?scope=all&utf8=✓&state=opened&assignee_id=0&milestone_title=Backlog%20&#40;Accepting%20merge%20requests&#41;)
-are a great place to start. Issues with a lower weight (1 or 2) are deemed
-suitable for beginners. These issues will be of reasonable size and challenge,
-for anyone to start contributing to GitLab. If you have any questions or need help visit [Getting Help](https://about.gitlab.com/getting-help/#discussion) to
-learn how to communicate with GitLab. If you're looking for a Gitter or Slack channel
-please consider we favor
-[asynchronous communication](https://about.gitlab.com/handbook/communication/#internal-communication) over real time communication. Thanks for your contribution!
+This [documentation](doc/development/contributing/index.md#i-want-to-contribute) has been moved.
## Contribution Flow
-When contributing to GitLab, your merge request is subject to review by merge request maintainers of a particular specialty.
-
-When you submit code to GitLab, we really want it to get merged, but there will be times when it will not be merged.
-
-When maintainers are reading through a merge request they may request guidance from other maintainers. If merge request maintainers conclude that the code should not be merged, our reasons will be fully disclosed. If it has been decided that the code quality is not up to GitLab’s standards, the merge request maintainer will refer the author to our docs and code style guides, and provide some guidance.
-
-Sometimes style guides will be followed but the code will lack structural integrity, or the maintainer will have reservations about the code’s overall quality. When there is a reservation the maintainer will inform the author and provide some guidance. The author may then choose to update the merge request. Once the merge request has been updated and reassigned to the maintainer, they will review the code again. Once the code has been resubmitted any number of times, the maintainer may choose to close the merge request with a summary of why it will not be merged, as well as some guidance. If the merge request is closed the maintainer will be open to discussion as to how to improve the code so it can be approved in the future.
-
-GitLab will do its best to review community contributions as quickly as possible. Specially appointed developers review community contributions daily. You may take a look at the [team page](https://about.gitlab.com/team/) for the merge request coach who specializes in the type of code you have written and mention them in the merge request. For example, if you have written some JavaScript in your code then you should mention the frontend merge request coach. If your code has multiple disciplines you may mention multiple merge request coaches.
-
-GitLab receives a lot of community contributions, so if your code has not been reviewed within 4 days of its initial submission feel free to re-mention the appropriate merge request coach.
-
-When submitting code to GitLab, you may feel that your contribution requires the aid of an external library. If your code includes an external library please provide a link to the library, as well as reasons for including it.
-
-When your code contains more than 500 changes, any major breaking changes, or an external library, `@mention` a maintainer in the merge request. If you are not sure who to mention, the reviewer will add one early in the merge request process.
-
-[core team]: https://about.gitlab.com/core-team/
-[team]: https://about.gitlab.com/team/
-[getting-help]: https://about.gitlab.com/getting-help/
-[codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq
-[accepting-mrs-weight]: https://gitlab.com/gitlab-org/gitlab-ce/issues?assignee_id=0&label_name[]=Accepting%20Merge%20Requests&sort=weight_asc
-[ce-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/issues
-[ee-tracker]: https://gitlab.com/gitlab-org/gitlab-ee/issues
-[google-group]: https://groups.google.com/forum/#!forum/gitlabhq
-[stackoverflow]: https://stackoverflow.com/questions/tagged/gitlab
-[fpl]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=feature+proposal
-[accepting-mrs-ce]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=Accepting+Merge+Requests
-[accepting-mrs-ee]: https://gitlab.com/gitlab-org/gitlab-ee/issues?label_name=Accepting+Merge+Requests
-[gitlab-mr-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests
-[gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit
-[git-squash]: https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits
-[closed-merge-requests]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?assignee_id=&label_name=&milestone_id=&scope=&sort=&state=closed
-[definition-of-done]: http://guide.agilealliance.org/guide/definition-of-done.html
-[contributor-covenant]: http://contributor-covenant.org
-[rss-source]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#source-code-layout
-[rss-naming]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#naming
-[changelog]: doc/development/changelog.md "Generate a changelog entry"
-[doc-guidelines]: doc/development/documentation/index.md "Documentation guidelines"
-[js-styleguide]: doc/development/fe_guide/style_guide_js.md "JavaScript styleguide"
-[scss-styleguide]: doc/development/fe_guide/style_guide_scss.md "SCSS styleguide"
-[newlines-styleguide]: doc/development/newlines_styleguide.md "Newlines styleguide"
-[UX Guide for GitLab]: http://docs.gitlab.com/ce/development/ux_guide/
-[license-finder-doc]: doc/development/licensing.md
-[GitLab Inc engineering workflow]: https://about.gitlab.com/handbook/engineering/workflow/#labelling-issues
-[polling-etag]: https://docs.gitlab.com/ce/development/polling.html
-[testing]: doc/development/testing_guide/index.md
-[us-english]: https://en.wikipedia.org/wiki/American_English
-
+This [documentation](doc/development/contributing/index.md) has been moved.
## Workflow labels
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Type labels
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Subject labels
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Team labels
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Release Scoping labels
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Priority labels
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Severity labels
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
@@ -248,17 +122,14 @@ This [documentation](doc/development/contributing/issue_workflow.md) has been mo
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Label for community contributors
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
## Implement design & UI elements
This [documentation](doc/development/contributing/design.md) has been moved.
-
## Issue tracker
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
@@ -267,7 +138,6 @@ This [documentation](doc/development/contributing/issue_workflow.md) has been mo
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Feature proposals
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
@@ -276,32 +146,26 @@ This [documentation](doc/development/contributing/issue_workflow.md) has been mo
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Issue weight
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Regression issues
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Technical and UX debt
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
### Stewardship
This [documentation](doc/development/contributing/issue_workflow.md) has been moved.
-
## Merge requests
This [documentation](doc/development/contributing/merge_request_workflow.md) has been moved.
-
### Merge request guidelines
This [documentation](doc/development/contributing/merge_request_workflow.md) has been moved.
@@ -311,12 +175,10 @@ This [documentation](doc/development/contributing/merge_request_workflow.md) has
This [documentation](doc/development/contributing/merge_request_workflow.md) has been moved.
-
## Definition of done
This [documentation](doc/development/contributing/merge_request_workflow.md) has been moved.
-
## Style guides
-This [documentation](doc/development/contributing/design.md) has been moved.
+This [documentation](doc/development/contributing/style_guides.md) has been moved.
diff --git a/Dangerfile b/Dangerfile
index 46e53edcac4..469e77b2514 100644
--- a/Dangerfile
+++ b/Dangerfile
@@ -1,3 +1,4 @@
+danger.import_plugin('danger/plugins/helper.rb')
danger.import_dangerfile(path: 'danger/metadata')
danger.import_dangerfile(path: 'danger/changes_size')
danger.import_dangerfile(path: 'danger/changelog')
@@ -7,3 +8,5 @@ danger.import_dangerfile(path: 'danger/database')
danger.import_dangerfile(path: 'danger/documentation')
danger.import_dangerfile(path: 'danger/frozen_string')
danger.import_dangerfile(path: 'danger/commit_messages')
+danger.import_dangerfile(path: 'danger/prettier')
+danger.import_dangerfile(path: 'danger/eslint')
diff --git a/Dockerfile.assets b/Dockerfile.assets
new file mode 100644
index 00000000000..403d16cc4ab
--- /dev/null
+++ b/Dockerfile.assets
@@ -0,0 +1,4 @@
+# Simple container to store assets for later use
+FROM scratch
+ADD public/assets /assets/
+CMD /bin/true
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 61825a7bf03..26aaba0e866 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-0.121.0
+1.2.0
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index 9084fa2f716..3a3cd8cc8b0 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-1.1.0
+1.3.1
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index d127a0ff9f1..016dac34bf9 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-8.3.3
+8.4.3
diff --git a/GITLAB_WORKHORSE_VERSION b/GITLAB_WORKHORSE_VERSION
index dfda3e0b4f0..1502020768a 100644
--- a/GITLAB_WORKHORSE_VERSION
+++ b/GITLAB_WORKHORSE_VERSION
@@ -1 +1 @@
-6.1.0
+7.3.0
diff --git a/Gemfile b/Gemfile
index 106ae35efa4..e37cadc128a 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,13 +1,17 @@
# --- Special code for migrating to Rails 5.0 ---
def rails5?
- %w[1 true].include?(ENV["RAILS5"])
+ !%w[0 false].include?(ENV["RAILS5"])
end
gem_versions = {}
-gem_versions['activerecord_sane_schema_dumper'] = rails5? ? '1.0' : '0.2'
-gem_versions['default_value_for'] = rails5? ? '~> 3.0.5' : '~> 3.0.0'
-gem_versions['rails'] = rails5? ? '5.0.7' : '4.2.10'
-gem_versions['rails-i18n'] = rails5? ? '~> 5.1' : '~> 4.0.9'
+gem_versions['activerecord_sane_schema_dumper'] = rails5? ? '1.0' : '0.2'
+gem_versions['rails'] = rails5? ? '5.0.7' : '4.2.10'
+gem_versions['rails-i18n'] = rails5? ? '~> 5.1' : '~> 4.0.9'
+
+# The 2.0.6 version of rack requires monkeypatch to be present in
+# `config.ru`. This can be removed once a new update for Rack
+# is available that contains https://github.com/rack/rack/pull/1201.
+gem_versions['rack'] = rails5? ? '2.0.6' : '1.6.11'
# --- The end of special code for migrating to Rails 5.0 ---
source 'https://rubygems.org'
@@ -15,13 +19,20 @@ source 'https://rubygems.org'
gem 'rails', gem_versions['rails']
gem 'rails-deprecated_sanitizer', '~> 1.0.3'
+# Improves copy-on-write performance for MRI
+gem 'nakayoshi_fork', '~> 0.0.4'
+
# Responders respond_to and respond_with
gem 'responders', '~> 2.0'
gem 'sprockets', '~> 3.7.0'
# Default values for AR models
-gem 'default_value_for', gem_versions['default_value_for']
+if rails5?
+ gem 'gitlab-default_value_for', '~> 3.1.1', require: 'default_value_for'
+else
+ gem 'default_value_for', '~> 3.0.0'
+end
# Supported DBs
gem 'mysql2', '~> 0.4.10', group: :mysql
@@ -71,7 +82,7 @@ gem 'validates_hostname', '~> 1.0.6'
gem 'browser', '~> 2.5'
# GPG
-gem 'gpgme'
+gem 'gpgme', '~> 2.0.18'
# LDAP Auth
# GitLab fork with several improvements to original library. For full list of changes
@@ -79,17 +90,8 @@ gem 'gpgme'
gem 'gitlab_omniauth-ldap', '~> 2.0.4', require: 'omniauth-ldap'
gem 'net-ldap'
-# Git Wiki
-# Required manually in config/initializers/gollum.rb to control load order
-gem 'gitlab-gollum-lib', '~> 4.2', require: false
-
-gem 'gitlab-gollum-rugged_adapter', '~> 0.4.4', require: false
-
-# Language detection
-gem 'github-linguist', '~> 5.3.3', require: 'linguist'
-
# API
-gem 'grape', '~> 1.0'
+gem 'grape', '~> 1.1.0'
gem 'grape-entity', '~> 0.7.1'
gem 'rack-cors', '~> 1.0.0', require: 'rack/cors'
@@ -112,9 +114,6 @@ gem 'hamlit', '~> 2.8.8'
gem 'carrierwave', '= 1.2.3'
gem 'mini_magick'
-# Drag and Drop UI
-gem 'dropzonejs-rails', '~> 0.7.1'
-
# for backups
gem 'fog-aws', '~> 2.0.1'
gem 'fog-core', '~> 1.44'
@@ -136,7 +135,8 @@ gem 'seed-fu', '~> 2.3.7'
# Markdown and HTML processing
gem 'html-pipeline', '~> 2.8'
gem 'deckar01-task_list', '2.0.0'
-gem 'gitlab-markup', '~> 1.6.4'
+gem 'gitlab-markup', '~> 1.6.5'
+gem 'github-markup', '~> 1.7.0', require: 'github/markup'
gem 'redcarpet', '~> 3.4'
gem 'commonmarker', '~> 0.17'
gem 'RedCloth', '~> 4.3.2'
@@ -144,12 +144,13 @@ gem 'rdoc', '~> 6.0'
gem 'org-ruby', '~> 0.9.12'
gem 'creole', '~> 0.5.0'
gem 'wikicloth', '0.8.1'
-gem 'asciidoctor', '~> 1.5.6'
+gem 'asciidoctor', '~> 1.5.8'
gem 'asciidoctor-plantuml', '0.0.8'
gem 'rouge', '~> 3.1'
gem 'truncato', '~> 0.7.9'
gem 'bootstrap_form', '~> 2.7.0'
gem 'nokogiri', '~> 1.8.2'
+gem 'escape_utils', '~> 1.1'
# Calendar rendering
gem 'icalendar'
@@ -158,11 +159,18 @@ gem 'icalendar'
gem 'diffy', '~> 3.1.0'
# Application server
+gem 'rack', gem_versions['rack']
+
group :unicorn do
gem 'unicorn', '~> 5.1.0'
gem 'unicorn-worker-killer', '~> 0.4.4'
end
+group :puma do
+ gem 'puma', '~> 3.12', require: false
+ gem 'puma_worker_killer', require: false
+end
+
# State machine
gem 'state_machines-activerecord', '~> 0.5.1'
@@ -173,7 +181,6 @@ gem 'acts-as-taggable-on', '~> 5.0'
gem 'sidekiq', '~> 5.2.1'
gem 'sidekiq-cron', '~> 0.6.0'
gem 'redis-namespace', '~> 1.6.0'
-gem 'sidekiq-limit_fetch', '~> 3.4', require: false
# Cron Parser
gem 'rufus-scheduler', '~> 3.4'
@@ -210,6 +217,9 @@ gem 'redis-rails', '~> 5.0.2'
gem 'redis', '~> 3.2'
gem 'connection_pool', '~> 2.0'
+# Discord integration
+gem 'discordrb-webhooks-blackst0ne', '~> 3.3', require: false
+
# HipChat integration
gem 'hipchat', '~> 1.5.0'
@@ -217,7 +227,7 @@ gem 'hipchat', '~> 1.5.0'
gem 'jira-ruby', '~> 1.4'
# Flowdock integration
-gem 'gitlab-flowdock-git-hook', '~> 1.0.1'
+gem 'flowdock', '~> 0.7'
# Slack integration
gem 'slack-notifier', '~> 1.5.1'
@@ -226,13 +236,13 @@ gem 'slack-notifier', '~> 1.5.1'
gem 'hangouts-chat', '~> 0.0.5'
# Asana integration
-gem 'asana', '~> 0.6.0'
+gem 'asana', '~> 0.8.1'
# FogBugz integration
gem 'ruby-fogbugz', '~> 0.2.1'
# Kubernetes integration
-gem 'kubeclient', '~> 3.1.0'
+gem 'kubeclient', '~> 4.0.0'
# Sanitize user input
gem 'sanitize', '~> 4.6'
@@ -250,9 +260,6 @@ gem 'rack-attack', '~> 4.4.1'
# Ace editor
gem 'ace-rails-ap', '~> 4.1.0'
-# Keyboard shortcuts
-gem 'mousetrap-rails', '~> 1.4.6'
-
# Detect and convert string character encoding
gem 'charlock_holmes', '~> 0.7.5'
@@ -300,6 +307,7 @@ gem 'peek-mysql2', '~> 1.1.0', group: :mysql
gem 'peek-pg', '~> 1.3.0', group: :postgres
gem 'peek-rblineprof', '~> 0.2.0'
gem 'peek-redis', '~> 1.2.0'
+gem 'gitlab-sidekiq-fetcher', require: 'sidekiq-reliable-fetch'
# Metrics
group :metrics do
@@ -319,8 +327,8 @@ group :development do
gem 'rblineprof', '~> 0.3.6', platform: :mri, require: false
# Better errors handler
- gem 'better_errors', '~> 2.1.0'
- gem 'binding_of_caller', '~> 0.7.2'
+ gem 'better_errors', '~> 2.5.0'
+ gem 'binding_of_caller', '~> 0.8.0'
# thin instead webrick
gem 'thin', '~> 1.7.0'
@@ -347,7 +355,7 @@ group :development, :test do
gem 'minitest', '~> 5.7.0'
# Generate Fake data
- gem 'ffaker', '~> 2.4'
+ gem 'ffaker', '~> 2.10'
gem 'capybara', '~> 2.15'
gem 'capybara-screenshot', '~> 1.0.0'
@@ -362,14 +370,14 @@ group :development, :test do
gem 'rubocop-rspec', '~> 1.22.1'
gem 'scss_lint', '~> 0.56.0', require: false
- gem 'haml_lint', '~> 0.26.0', require: false
+ gem 'haml_lint', '~> 0.28.0', require: false
gem 'simplecov', '~> 0.14.0', require: false
gem 'bundler-audit', '~> 0.5.0', require: false
gem 'benchmark-ips', '~> 2.3.0', require: false
gem 'license_finder', '~> 5.4', require: false
- gem 'knapsack', '~> 1.16'
+ gem 'knapsack', '~> 1.17'
gem 'activerecord_sane_schema_dumper', gem_versions['activerecord_sane_schema_dumper']
@@ -388,7 +396,7 @@ group :test do
gem 'rails-controller-testing' if rails5? # Rails5 only gem.
gem 'test_after_commit', '~> 1.1' unless rails5? # Remove this gem when migrated to rails 5.0. It's been integrated to rails 5.0.
gem 'sham_rack', '~> 1.3.6'
- gem 'concurrent-ruby', '~> 1.0.5'
+ gem 'concurrent-ruby', '~> 1.1'
gem 'test-prof', '~> 0.2.5'
gem 'rspec_junit_formatter'
end
@@ -424,11 +432,10 @@ group :ed25519 do
end
# Gitaly GRPC client
-gem 'gitaly-proto', '~> 0.117.0', require: 'gitaly'
-gem 'grpc', '~> 1.11.0'
+gem 'gitaly-proto', '~> 1.2.0', require: 'gitaly'
+gem 'grpc', '~> 1.15.0'
-# Locked until https://github.com/google/protobuf/issues/4210 is closed
-gem 'google-protobuf', '= 3.5.1'
+gem 'google-protobuf', '~> 3.6'
gem 'toml-rb', '~> 1.0.0', require: false
@@ -440,6 +447,3 @@ gem 'flipper-active_support_cache_store', '~> 0.13.0'
# Structured logging
gem 'lograge', '~> 0.5'
gem 'grape_logging', '~> 1.7'
-
-# Asset synchronization
-gem 'asset_sync', '~> 2.4'
diff --git a/Gemfile.lock b/Gemfile.lock
index 328cc55cb8c..e7873932dad 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -4,41 +4,44 @@ GEM
RedCloth (4.3.2)
abstract_type (0.0.7)
ace-rails-ap (4.1.2)
- actionmailer (4.2.10)
- actionpack (= 4.2.10)
- actionview (= 4.2.10)
- activejob (= 4.2.10)
+ actioncable (5.0.7)
+ actionpack (= 5.0.7)
+ nio4r (>= 1.2, < 3.0)
+ websocket-driver (~> 0.6.1)
+ actionmailer (5.0.7)
+ actionpack (= 5.0.7)
+ actionview (= 5.0.7)
+ activejob (= 5.0.7)
mail (~> 2.5, >= 2.5.4)
- rails-dom-testing (~> 1.0, >= 1.0.5)
- actionpack (4.2.10)
- actionview (= 4.2.10)
- activesupport (= 4.2.10)
- rack (~> 1.6)
- rack-test (~> 0.6.2)
- rails-dom-testing (~> 1.0, >= 1.0.5)
+ rails-dom-testing (~> 2.0)
+ actionpack (5.0.7)
+ actionview (= 5.0.7)
+ activesupport (= 5.0.7)
+ rack (~> 2.0)
+ rack-test (~> 0.6.3)
+ rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
- actionview (4.2.10)
- activesupport (= 4.2.10)
+ actionview (5.0.7)
+ activesupport (= 5.0.7)
builder (~> 3.1)
erubis (~> 2.7.0)
- rails-dom-testing (~> 1.0, >= 1.0.5)
+ rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
- activejob (4.2.10)
- activesupport (= 4.2.10)
- globalid (>= 0.3.0)
- activemodel (4.2.10)
- activesupport (= 4.2.10)
- builder (~> 3.1)
- activerecord (4.2.10)
- activemodel (= 4.2.10)
- activesupport (= 4.2.10)
- arel (~> 6.0)
- activerecord_sane_schema_dumper (0.2)
- rails (>= 4, < 5)
- activesupport (4.2.10)
- i18n (~> 0.7)
+ activejob (5.0.7)
+ activesupport (= 5.0.7)
+ globalid (>= 0.3.6)
+ activemodel (5.0.7)
+ activesupport (= 5.0.7)
+ activerecord (5.0.7)
+ activemodel (= 5.0.7)
+ activesupport (= 5.0.7)
+ arel (~> 7.0)
+ activerecord_sane_schema_dumper (1.0)
+ rails (>= 5, < 6)
+ activesupport (5.0.7)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ i18n (>= 0.7, < 2)
minitest (~> 5.1)
- thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
acts-as-taggable-on (5.0.0)
activerecord (>= 4.2.8)
@@ -49,20 +52,15 @@ GEM
public_suffix (>= 2.0.2, < 4.0)
aes_key_wrap (1.0.1)
akismet (2.0.0)
- arel (6.0.4)
- asana (0.6.0)
+ arel (7.1.4)
+ asana (0.8.1)
faraday (~> 0.9)
faraday_middleware (~> 0.9)
faraday_middleware-multi_json (~> 0.0)
oauth2 (~> 1.0)
- asciidoctor (1.5.6.2)
+ asciidoctor (1.5.8)
asciidoctor-plantuml (0.0.8)
asciidoctor (~> 1.5)
- asset_sync (2.4.0)
- activemodel (>= 4.1.0)
- fog-core
- mime-types (>= 2.99)
- unf
ast (2.4.0)
atomic (1.1.99)
attr_encrypted (3.1.0)
@@ -79,14 +77,14 @@ GEM
bcrypt (3.1.12)
bcrypt_pbkdf (1.0.0)
benchmark-ips (2.3.0)
- better_errors (2.1.1)
+ better_errors (2.5.0)
coderay (>= 1.0.0)
- erubis (>= 2.6.6)
+ erubi (>= 1.0.0)
rack (>= 0.9.0)
bindata (2.4.3)
- binding_of_caller (0.7.2)
+ binding_of_caller (0.8.0)
debug_inspector (>= 0.0.1)
- bootsnap (1.3.1)
+ bootsnap (1.3.2)
msgpack (~> 1.0)
bootstrap_form (2.7.0)
brakeman (4.2.1)
@@ -130,9 +128,9 @@ GEM
concord (0.1.5)
adamantium (~> 0.2.0)
equalizer (~> 0.0.9)
- concurrent-ruby (1.0.5)
- concurrent-ruby-ext (1.0.5)
- concurrent-ruby (= 1.0.5)
+ concurrent-ruby (1.1.3)
+ concurrent-ruby-ext (1.1.3)
+ concurrent-ruby (= 1.1.3)
connection_pool (2.2.2)
crack (0.4.3)
safe_yaml (~> 1.0.0)
@@ -140,16 +138,14 @@ GEM
creole (0.5.0)
css_parser (1.5.0)
addressable
- daemons (1.2.3)
+ daemons (1.2.6)
database_cleaner (1.5.3)
- debug_inspector (0.0.2)
+ debug_inspector (0.0.3)
debugger-ruby_core_source (1.3.8)
deckar01-task_list (2.0.0)
html-pipeline
declarative (0.0.10)
declarative-option (0.1.0)
- default_value_for (3.0.2)
- activerecord (>= 3.2.0, < 5.1)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
device_detector (1.0.0)
@@ -167,6 +163,8 @@ GEM
rotp (~> 2.0)
diff-lcs (1.3)
diffy (3.1.0)
+ discordrb-webhooks-blackst0ne (3.3.0)
+ rest-client (~> 2.0)
docile (1.1.5)
domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
@@ -175,8 +173,6 @@ GEM
doorkeeper-openid_connect (1.5.0)
doorkeeper (~> 4.3)
json-jwt (~> 1.6)
- dropzonejs-rails (0.7.2)
- rails (> 3.1)
ed25519 (1.2.4)
email_reply_trimmer (0.1.6)
email_spec (2.2.0)
@@ -185,11 +181,12 @@ GEM
mail (~> 2.7)
encryptor (3.0.0)
equalizer (0.0.11)
+ erubi (1.7.1)
erubis (2.7.0)
- escape_utils (1.1.1)
+ escape_utils (1.2.1)
et-orbi (1.0.3)
tzinfo
- eventmachine (1.0.8)
+ eventmachine (1.2.7)
excon (0.62.0)
execjs (2.6.0)
expression_parser (0.9.0)
@@ -207,7 +204,7 @@ GEM
multi_json
fast_blank (1.0.0)
fast_gettext (1.6.0)
- ffaker (2.4.0)
+ ffaker (2.10.0)
ffi (1.9.25)
flipper (0.13.0)
flipper-active_record (0.13.0)
@@ -276,36 +273,14 @@ GEM
gettext_i18n_rails (>= 0.7.1)
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
- gitaly-proto (0.117.0)
- google-protobuf (~> 3.1)
- grpc (~> 1.10)
- github-linguist (5.3.3)
- charlock_holmes (~> 0.7.5)
- escape_utils (~> 1.1.0)
- mime-types (>= 1.19)
- rugged (>= 0.25.1)
+ gitaly-proto (1.2.0)
+ grpc (~> 1.0)
github-markup (1.7.0)
- gitlab-flowdock-git-hook (1.0.1)
- flowdock (~> 0.7)
- gitlab-grit (>= 2.4.1)
- multi_json
- gitlab-gollum-lib (4.2.7.5)
- gemojione (~> 3.2)
- github-markup (~> 1.6)
- gollum-grit_adapter (~> 1.0)
- nokogiri (>= 1.6.1, < 2.0)
- rouge (~> 3.1)
- sanitize (~> 4.6.4)
- stringex (~> 2.6)
- gitlab-gollum-rugged_adapter (0.4.4.1)
- mime-types (>= 1.15)
- rugged (~> 0.25)
- gitlab-grit (2.8.2)
- charlock_holmes (~> 0.6)
- diff-lcs (~> 1.1)
- mime-types (>= 1.16)
- posix-spawn (~> 0.3)
- gitlab-markup (1.6.4)
+ gitlab-default_value_for (3.1.1)
+ activerecord (>= 3.2.0, < 6.0)
+ gitlab-markup (1.6.5)
+ gitlab-sidekiq-fetcher (0.3.0)
+ sidekiq (~> 5)
gitlab-styles (2.4.1)
rubocop (~> 0.54.0)
rubocop-gitlab-security (~> 0.1.0)
@@ -317,8 +292,6 @@ GEM
rubyntlm (~> 0.5)
globalid (0.4.1)
activesupport (>= 4.2.0)
- gollum-grit_adapter (1.0.1)
- gitlab-grit (~> 2.7, >= 2.7.1)
gon (6.2.0)
actionpack (>= 3.0)
multi_json
@@ -330,20 +303,19 @@ GEM
mime-types (~> 3.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
- google-protobuf (3.5.1)
- googleapis-common-protos-types (1.0.1)
+ google-protobuf (3.6.1)
+ googleapis-common-protos-types (1.0.2)
google-protobuf (~> 3.0)
- googleauth (0.6.2)
+ googleauth (0.6.6)
faraday (~> 0.12)
jwt (>= 1.4, < 3.0)
- logging (~> 2.0)
memoist (~> 0.12)
multi_json (~> 1.11)
- os (~> 0.9)
+ os (>= 0.9, < 2.0)
signet (~> 0.7)
- gpgme (2.0.13)
- mini_portile2 (~> 2.1)
- grape (1.0.3)
+ gpgme (2.0.18)
+ mini_portile2 (~> 2.3)
+ grape (1.1.0)
activesupport
builder
mustermann-grape (~> 1.0.0)
@@ -363,18 +335,17 @@ GEM
railties
sprockets-rails
graphql (1.8.1)
- grpc (1.11.0)
+ grpc (1.15.0)
google-protobuf (~> 3.1)
googleapis-common-protos-types (~> 1.0.0)
- googleauth (>= 0.5.1, < 0.7)
haml (5.0.4)
temple (>= 0.8.0)
tilt
- haml_lint (0.26.0)
+ haml_lint (0.28.0)
haml (>= 4.0, < 5.1)
rainbow
rake (>= 10, < 13)
- rubocop (>= 0.49.0)
+ rubocop (>= 0.50.0)
sysexits (~> 1.1)
hamlit (2.8.8)
temple (>= 0.8.0)
@@ -396,20 +367,20 @@ GEM
html2text (0.2.0)
nokogiri (~> 1.6)
htmlentities (4.3.4)
- http (2.2.2)
+ http (3.3.0)
addressable (~> 2.3)
http-cookie (~> 1.0)
- http-form_data (~> 1.0.1)
+ http-form_data (~> 2.0)
http_parser.rb (~> 0.6.0)
http-cookie (1.0.3)
domain_name (~> 0.5)
- http-form_data (1.0.3)
+ http-form_data (2.1.1)
http_parser.rb (0.6.0)
httparty (0.13.7)
json (~> 1.8)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
- i18n (0.9.5)
+ i18n (1.1.1)
concurrent-ruby (~> 1.0)
icalendar (2.4.1)
ice_nine (0.11.2)
@@ -445,10 +416,10 @@ GEM
kaminari-core (= 1.0.1)
kaminari-core (1.0.1)
kgio (2.10.0)
- knapsack (1.16.0)
+ knapsack (1.17.0)
rake
- kubeclient (3.1.0)
- http (~> 2.2.2)
+ kubeclient (4.0.0)
+ http (~> 3.0)
recursive-open-struct (~> 1.0, >= 1.0.4)
rest-client (~> 2.0)
launchy (2.4.3)
@@ -468,17 +439,13 @@ GEM
xml-simple
licensee (8.9.2)
rugged (~> 0.24)
- little-plugger (1.1.4)
locale (2.1.2)
- logging (2.2.2)
- little-plugger (~> 1.1)
- multi_json (~> 1.10)
lograge (0.10.0)
actionpack (>= 4)
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
- loofah (2.2.2)
+ loofah (2.2.3)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.0)
@@ -487,28 +454,29 @@ GEM
memoist (0.16.0)
memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1)
- method_source (0.9.0)
- mime-types (3.1)
+ method_source (0.9.2)
+ mime-types (3.2.2)
mime-types-data (~> 3.2015)
- mime-types-data (3.2016.0521)
+ mime-types-data (3.2018.0812)
mimemagic (0.3.0)
mini_magick (4.8.0)
- mini_mime (1.0.0)
+ mini_mime (1.0.1)
mini_portile2 (2.3.0)
minitest (5.7.0)
- mousetrap-rails (1.4.6)
msgpack (1.2.4)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
- mustermann (1.0.2)
+ mustermann (1.0.3)
mustermann-grape (1.0.0)
mustermann (~> 1.0.0)
mysql2 (0.4.10)
+ nakayoshi_fork (0.0.4)
net-ldap (0.16.0)
net-ssh (5.0.1)
netrc (0.11.0)
- nokogiri (1.8.4)
+ nio4r (2.3.1)
+ nokogiri (1.8.5)
mini_portile2 (~> 2.3.0)
nokogumbo (1.5.0)
nokogiri
@@ -578,9 +546,9 @@ GEM
org-ruby (0.9.12)
rubypants (~> 0.2)
orm_adapter (0.5.0)
- os (0.9.6)
+ os (1.0.0)
parallel (1.12.1)
- parser (2.5.1.0)
+ parser (2.5.3.0)
ast (~> 2.4.0)
parslet (1.8.2)
peek (1.0.1)
@@ -608,7 +576,6 @@ GEM
pg (0.18.4)
po_to_json (1.0.1)
json (>= 1.6.0)
- posix-spawn (0.3.13)
powerpack (0.1.1)
premailer (1.10.4)
addressable
@@ -629,11 +596,15 @@ GEM
pry-byebug (3.4.3)
byebug (>= 9.0, < 9.1)
pry (~> 0.10)
- pry-rails (0.3.5)
- pry (>= 0.9.10)
- public_suffix (3.0.2)
+ pry-rails (0.3.6)
+ pry (>= 0.10.4)
+ public_suffix (3.0.3)
+ puma (3.12.0)
+ puma_worker_killer (0.1.0)
+ get_process_mem (~> 0.2)
+ puma (>= 2.7, < 4)
pyu-ruby-sasl (0.0.3.3)
- rack (1.6.10)
+ rack (2.0.6)
rack-accept (0.4.5)
rack (>= 0.4)
rack-attack (4.4.1)
@@ -645,37 +616,42 @@ GEM
httpclient (>= 2.4)
multi_json (>= 1.3.6)
rack (>= 1.1)
- rack-protection (2.0.3)
+ rack-protection (2.0.4)
rack
rack-proxy (0.6.0)
rack
rack-test (0.6.3)
rack (>= 1.0)
- rails (4.2.10)
- actionmailer (= 4.2.10)
- actionpack (= 4.2.10)
- actionview (= 4.2.10)
- activejob (= 4.2.10)
- activemodel (= 4.2.10)
- activerecord (= 4.2.10)
- activesupport (= 4.2.10)
- bundler (>= 1.3.0, < 2.0)
- railties (= 4.2.10)
- sprockets-rails
+ rails (5.0.7)
+ actioncable (= 5.0.7)
+ actionmailer (= 5.0.7)
+ actionpack (= 5.0.7)
+ actionview (= 5.0.7)
+ activejob (= 5.0.7)
+ activemodel (= 5.0.7)
+ activerecord (= 5.0.7)
+ activesupport (= 5.0.7)
+ bundler (>= 1.3.0)
+ railties (= 5.0.7)
+ sprockets-rails (>= 2.0.0)
+ rails-controller-testing (1.0.2)
+ actionpack (~> 5.x, >= 5.0.1)
+ actionview (~> 5.x, >= 5.0.1)
+ activesupport (~> 5.x)
rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha)
- rails-dom-testing (1.0.9)
- activesupport (>= 4.2.0, < 5.0)
- nokogiri (~> 1.6)
- rails-deprecated_sanitizer (>= 1.0.1)
+ rails-dom-testing (2.0.3)
+ activesupport (>= 4.2.0)
+ nokogiri (>= 1.6)
rails-html-sanitizer (1.0.4)
loofah (~> 2.2, >= 2.2.2)
- rails-i18n (4.0.9)
- i18n (~> 0.7)
- railties (~> 4.0)
- railties (4.2.10)
- actionpack (= 4.2.10)
- activesupport (= 4.2.10)
+ rails-i18n (5.1.1)
+ i18n (>= 0.7, < 2)
+ railties (>= 5.0, < 6)
+ railties (5.0.7)
+ actionpack (= 5.0.7)
+ activesupport (= 5.0.7)
+ method_source
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (3.0.0)
@@ -713,7 +689,7 @@ GEM
redis-actionpack (>= 5.0, < 6)
redis-activesupport (>= 5.0, < 6)
redis-store (>= 1.2, < 2)
- redis-store (1.4.1)
+ redis-store (1.6.0)
redis (>= 2.2, < 5)
regexp_parser (0.5.0)
representable (3.0.4)
@@ -731,7 +707,7 @@ GEM
retriable (3.1.2)
rinku (2.0.0)
rotp (2.1.2)
- rouge (3.2.1)
+ rouge (3.3.0)
rqrcode (0.7.0)
chunky_png
rqrcode-rails3 (0.1.7)
@@ -766,8 +742,7 @@ GEM
rspec-core
rspec-set (0.1.3)
rspec-support (3.7.1)
- rspec_junit_formatter (0.2.3)
- builder (< 4)
+ rspec_junit_formatter (0.4.1)
rspec-core (>= 2, < 4, != 2.12.0)
rspec_profiling (0.0.5)
activerecord
@@ -793,14 +768,14 @@ GEM
ruby-progressbar (1.9.0)
ruby-saml (1.7.2)
nokogiri (>= 1.5.10)
- ruby_parser (3.9.0)
- sexp_processor (~> 4.1)
+ ruby_parser (3.11.0)
+ sexp_processor (~> 4.9)
rubyntlm (0.6.2)
rubypants (0.2.0)
rubyzip (1.2.2)
rufus-scheduler (3.4.0)
et-orbi (~> 1.0)
- rugged (0.27.4)
+ rugged (0.27.5)
safe_yaml (1.0.4)
sanitize (4.6.6)
crass (~> 1.0.2)
@@ -834,21 +809,19 @@ GEM
sentry-raven (2.7.2)
faraday (>= 0.7.6, < 1.0)
settingslogic (2.0.9)
- sexp_processor (4.9.0)
+ sexp_processor (4.11.0)
sham_rack (1.3.6)
rack
shoulda-matchers (3.1.2)
activesupport (>= 4.0.0)
- sidekiq (5.2.1)
+ sidekiq (5.2.3)
connection_pool (~> 2.2, >= 2.2.2)
rack-protection (>= 1.5.0)
redis (>= 3.3.5, < 5)
sidekiq-cron (0.6.0)
rufus-scheduler (>= 3.3.0)
sidekiq (>= 4.2.1)
- sidekiq-limit_fetch (3.4.0)
- sidekiq (>= 4)
- signet (0.8.1)
+ signet (0.11.0)
addressable (~> 2.3)
faraday (~> 0.9)
jwt (>= 1.5, < 3.0)
@@ -860,7 +833,7 @@ GEM
simplecov-html (~> 0.10.0)
simplecov-html (0.10.0)
slack-notifier (1.5.1)
- spring (2.0.1)
+ spring (2.0.2)
activesupport (>= 4.2)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
@@ -881,16 +854,13 @@ GEM
state_machines-activerecord (0.5.1)
activerecord (>= 4.1, < 6.0)
state_machines-activemodel (>= 0.5.0)
- stringex (2.8.4)
sys-filesystem (1.1.6)
ffi
sysexits (1.2.0)
temple (0.8.0)
test-prof (0.2.5)
- test_after_commit (1.1.0)
- activerecord (>= 3.2)
text (1.3.1)
- thin (1.7.0)
+ thin (1.7.2)
daemons (~> 1.0, >= 1.0.9)
eventmachine (~> 1.0, >= 1.0.4)
rack (>= 1, < 3)
@@ -949,8 +919,11 @@ GEM
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff
- webpack-rails (0.9.10)
+ webpack-rails (0.9.11)
railties (>= 3.2.0)
+ websocket-driver (0.6.5)
+ websocket-extensions (>= 0.1.0)
+ websocket-extensions (0.1.3)
wikicloth (0.8.1)
builder
expression_parser
@@ -966,14 +939,13 @@ PLATFORMS
DEPENDENCIES
RedCloth (~> 4.3.2)
ace-rails-ap (~> 4.1.0)
- activerecord_sane_schema_dumper (= 0.2)
+ activerecord_sane_schema_dumper (= 1.0)
acts-as-taggable-on (~> 5.0)
addressable (~> 2.5.2)
akismet (~> 2.0)
- asana (~> 0.6.0)
- asciidoctor (~> 1.5.6)
+ asana (~> 0.8.1)
+ asciidoctor (~> 1.5.8)
asciidoctor-plantuml (= 0.0.8)
- asset_sync (~> 2.4)
attr_encrypted (~> 3.1.0)
awesome_print
babosa (~> 1.0.2)
@@ -981,8 +953,8 @@ DEPENDENCIES
batch-loader (~> 1.2.1)
bcrypt_pbkdf (~> 1.0)
benchmark-ips (~> 2.3.0)
- better_errors (~> 2.1.0)
- binding_of_caller (~> 0.7.2)
+ better_errors (~> 2.5.0)
+ binding_of_caller (~> 0.8.0)
bootsnap (~> 1.3)
bootstrap_form (~> 2.7.0)
brakeman (~> 4.2)
@@ -996,29 +968,30 @@ DEPENDENCIES
chronic (~> 0.10.2)
chronic_duration (~> 0.10.6)
commonmarker (~> 0.17)
- concurrent-ruby (~> 1.0.5)
+ concurrent-ruby (~> 1.1)
connection_pool (~> 2.0)
creole (~> 0.5.0)
database_cleaner (~> 1.5.0)
deckar01-task_list (= 2.0.0)
- default_value_for (~> 3.0.0)
device_detector
devise (~> 4.4)
devise-two-factor (~> 3.0.0)
diffy (~> 3.1.0)
+ discordrb-webhooks-blackst0ne (~> 3.3)
doorkeeper (~> 4.3)
doorkeeper-openid_connect (~> 1.5)
- dropzonejs-rails (~> 0.7.1)
ed25519 (~> 1.2)
email_reply_trimmer (~> 0.1)
email_spec (~> 2.2.0)
+ escape_utils (~> 1.1)
factory_bot_rails (~> 4.8.2)
faraday (~> 0.12)
fast_blank
- ffaker (~> 2.4)
+ ffaker (~> 2.10)
flipper (~> 0.13.0)
flipper-active_record (~> 0.13.0)
flipper-active_support_cache_store (~> 0.13.0)
+ flowdock (~> 0.7)
fog-aliyun (~> 0.2.0)
fog-aws (~> 2.0.1)
fog-core (~> 1.44)
@@ -1033,26 +1006,25 @@ DEPENDENCIES
gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
- gitaly-proto (~> 0.117.0)
- github-linguist (~> 5.3.3)
- gitlab-flowdock-git-hook (~> 1.0.1)
- gitlab-gollum-lib (~> 4.2)
- gitlab-gollum-rugged_adapter (~> 0.4.4)
- gitlab-markup (~> 1.6.4)
+ gitaly-proto (~> 1.2.0)
+ github-markup (~> 1.7.0)
+ gitlab-default_value_for (~> 3.1.1)
+ gitlab-markup (~> 1.6.5)
+ gitlab-sidekiq-fetcher
gitlab-styles (~> 2.4)
gitlab_omniauth-ldap (~> 2.0.4)
gon (~> 6.2)
google-api-client (~> 0.23)
- google-protobuf (= 3.5.1)
- gpgme
- grape (~> 1.0)
+ google-protobuf (~> 3.6)
+ gpgme (~> 2.0.18)
+ grape (~> 1.1.0)
grape-entity (~> 0.7.1)
grape-path-helpers (~> 1.0)
grape_logging (~> 1.7)
graphiql-rails (~> 1.4.10)
graphql (~> 1.8.0)
- grpc (~> 1.11.0)
- haml_lint (~> 0.26.0)
+ grpc (~> 1.15.0)
+ haml_lint (~> 0.28.0)
hamlit (~> 2.8.8)
hangouts-chat (~> 0.0.5)
hashie-forbidden_attributes
@@ -1069,8 +1041,8 @@ DEPENDENCIES
json-schema (~> 2.8.0)
jwt (~> 1.5.6)
kaminari (~> 1.0)
- knapsack (~> 1.16)
- kubeclient (~> 3.1.0)
+ knapsack (~> 1.17)
+ kubeclient (~> 4.0.0)
letter_opener_web (~> 1.3.0)
license_finder (~> 5.4)
licensee (~> 8.9)
@@ -1080,8 +1052,8 @@ DEPENDENCIES
method_source (~> 0.8)
mini_magick
minitest (~> 5.7.0)
- mousetrap-rails (~> 1.4.6)
mysql2 (~> 0.4.10)
+ nakayoshi_fork (~> 0.0.4)
net-ldap
net-ssh (~> 5.0)
nokogiri (~> 1.8.2)
@@ -1114,13 +1086,17 @@ DEPENDENCIES
prometheus-client-mmap (~> 0.9.4)
pry-byebug (~> 3.4.1)
pry-rails (~> 0.3.4)
+ puma (~> 3.12)
+ puma_worker_killer
+ rack (= 2.0.6)
rack-attack (~> 4.4.1)
rack-cors (~> 1.0.0)
rack-oauth2 (~> 1.2.1)
rack-proxy (~> 0.6.0)
- rails (= 4.2.10)
+ rails (= 5.0.7)
+ rails-controller-testing
rails-deprecated_sanitizer (~> 1.0.3)
- rails-i18n (~> 4.0.9)
+ rails-i18n (~> 5.1)
rainbow (~> 3.0)
raindrops (~> 0.18)
rblineprof (~> 0.3.6)
@@ -1162,7 +1138,6 @@ DEPENDENCIES
shoulda-matchers (~> 3.1.2)
sidekiq (~> 5.2.1)
sidekiq-cron (~> 0.6.0)
- sidekiq-limit_fetch (~> 3.4)
simple_po_parser (~> 1.1.2)
simplecov (~> 0.14.0)
slack-notifier (~> 1.5.1)
@@ -1174,7 +1149,6 @@ DEPENDENCIES
state_machines-activerecord (~> 0.5.1)
sys-filesystem (~> 1.1.6)
test-prof (~> 0.2.5)
- test_after_commit (~> 1.1)
thin (~> 1.7.0)
timecop (~> 0.8.0)
toml-rb (~> 1.0.0)
@@ -1193,4 +1167,4 @@ DEPENDENCIES
wikicloth (= 0.8.1)
BUNDLED WITH
- 1.16.4
+ 1.17.1
diff --git a/Gemfile.rails4 b/Gemfile.rails4
new file mode 100644
index 00000000000..0ec00e702aa
--- /dev/null
+++ b/Gemfile.rails4
@@ -0,0 +1,7 @@
+# BUNDLE_GEMFILE=Gemfile.rails4 bundle install
+
+ENV["RAILS5"] = "false"
+
+gemfile = File.expand_path("../Gemfile", __FILE__)
+
+eval(File.read(gemfile), nil, gemfile)
diff --git a/Gemfile.rails4.lock b/Gemfile.rails4.lock
new file mode 100644
index 00000000000..7478e2173bd
--- /dev/null
+++ b/Gemfile.rails4.lock
@@ -0,0 +1,1161 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ RedCloth (4.3.2)
+ abstract_type (0.0.7)
+ ace-rails-ap (4.1.2)
+ actionmailer (4.2.10)
+ actionpack (= 4.2.10)
+ actionview (= 4.2.10)
+ activejob (= 4.2.10)
+ mail (~> 2.5, >= 2.5.4)
+ rails-dom-testing (~> 1.0, >= 1.0.5)
+ actionpack (4.2.10)
+ actionview (= 4.2.10)
+ activesupport (= 4.2.10)
+ rack (~> 1.6)
+ rack-test (~> 0.6.2)
+ rails-dom-testing (~> 1.0, >= 1.0.5)
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
+ actionview (4.2.10)
+ activesupport (= 4.2.10)
+ builder (~> 3.1)
+ erubis (~> 2.7.0)
+ rails-dom-testing (~> 1.0, >= 1.0.5)
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
+ activejob (4.2.10)
+ activesupport (= 4.2.10)
+ globalid (>= 0.3.0)
+ activemodel (4.2.10)
+ activesupport (= 4.2.10)
+ builder (~> 3.1)
+ activerecord (4.2.10)
+ activemodel (= 4.2.10)
+ activesupport (= 4.2.10)
+ arel (~> 6.0)
+ activerecord_sane_schema_dumper (0.2)
+ rails (>= 4, < 5)
+ activesupport (4.2.10)
+ i18n (~> 0.7)
+ minitest (~> 5.1)
+ thread_safe (~> 0.3, >= 0.3.4)
+ tzinfo (~> 1.1)
+ acts-as-taggable-on (5.0.0)
+ activerecord (>= 4.2.8)
+ adamantium (0.2.0)
+ ice_nine (~> 0.11.0)
+ memoizable (~> 0.4.0)
+ addressable (2.5.2)
+ public_suffix (>= 2.0.2, < 4.0)
+ aes_key_wrap (1.0.1)
+ akismet (2.0.0)
+ arel (6.0.4)
+ asana (0.8.1)
+ faraday (~> 0.9)
+ faraday_middleware (~> 0.9)
+ faraday_middleware-multi_json (~> 0.0)
+ oauth2 (~> 1.0)
+ asciidoctor (1.5.8)
+ asciidoctor-plantuml (0.0.8)
+ asciidoctor (~> 1.5)
+ ast (2.4.0)
+ atomic (1.1.99)
+ attr_encrypted (3.1.0)
+ encryptor (~> 3.0.0)
+ attr_required (1.0.0)
+ awesome_print (1.8.0)
+ axiom-types (0.1.1)
+ descendants_tracker (~> 0.0.4)
+ ice_nine (~> 0.11.0)
+ thread_safe (~> 0.3, >= 0.3.1)
+ babosa (1.0.2)
+ base32 (0.3.2)
+ batch-loader (1.2.1)
+ bcrypt (3.1.12)
+ bcrypt_pbkdf (1.0.0)
+ benchmark-ips (2.3.0)
+ better_errors (2.5.0)
+ coderay (>= 1.0.0)
+ erubi (>= 1.0.0)
+ rack (>= 0.9.0)
+ bindata (2.4.3)
+ binding_of_caller (0.8.0)
+ debug_inspector (>= 0.0.1)
+ bootsnap (1.3.2)
+ msgpack (~> 1.0)
+ bootstrap_form (2.7.0)
+ brakeman (4.2.1)
+ browser (2.5.3)
+ builder (3.2.3)
+ bullet (5.5.1)
+ activesupport (>= 3.0.0)
+ uniform_notifier (~> 1.10.0)
+ bundler-audit (0.5.0)
+ bundler (~> 1.2)
+ thor (~> 0.18)
+ byebug (9.0.6)
+ capybara (2.15.1)
+ addressable
+ mini_mime (>= 0.1.3)
+ nokogiri (>= 1.3.3)
+ rack (>= 1.0.0)
+ rack-test (>= 0.5.4)
+ xpath (~> 2.0)
+ capybara-screenshot (1.0.14)
+ capybara (>= 1.0, < 3)
+ launchy
+ carrierwave (1.2.3)
+ activemodel (>= 4.0.0)
+ activesupport (>= 4.0.0)
+ mime-types (>= 1.16)
+ cause (0.1)
+ charlock_holmes (0.7.6)
+ childprocess (0.9.0)
+ ffi (~> 1.0, >= 1.0.11)
+ chronic (0.10.2)
+ chronic_duration (0.10.6)
+ numerizer (~> 0.1.1)
+ chunky_png (1.3.5)
+ citrus (3.0.2)
+ coderay (1.1.2)
+ coercible (1.0.0)
+ descendants_tracker (~> 0.0.1)
+ commonmarker (0.17.13)
+ ruby-enum (~> 0.5)
+ concord (0.1.5)
+ adamantium (~> 0.2.0)
+ equalizer (~> 0.0.9)
+ concurrent-ruby (1.1.3)
+ concurrent-ruby-ext (1.1.3)
+ concurrent-ruby (= 1.1.3)
+ connection_pool (2.2.2)
+ crack (0.4.3)
+ safe_yaml (~> 1.0.0)
+ crass (1.0.4)
+ creole (0.5.0)
+ css_parser (1.5.0)
+ addressable
+ daemons (1.2.6)
+ database_cleaner (1.5.3)
+ debug_inspector (0.0.3)
+ debugger-ruby_core_source (1.3.8)
+ deckar01-task_list (2.0.0)
+ html-pipeline
+ declarative (0.0.10)
+ declarative-option (0.1.0)
+ default_value_for (3.0.2)
+ activerecord (>= 3.2.0, < 5.1)
+ descendants_tracker (0.0.4)
+ thread_safe (~> 0.3, >= 0.3.1)
+ device_detector (1.0.0)
+ devise (4.4.3)
+ bcrypt (~> 3.0)
+ orm_adapter (~> 0.1)
+ railties (>= 4.1.0, < 6.0)
+ responders
+ warden (~> 1.2.3)
+ devise-two-factor (3.0.0)
+ activesupport
+ attr_encrypted (>= 1.3, < 4, != 2)
+ devise (~> 4.0)
+ railties
+ rotp (~> 2.0)
+ diff-lcs (1.3)
+ diffy (3.1.0)
+ discordrb-webhooks-blackst0ne (3.3.0)
+ rest-client (~> 2.0)
+ docile (1.1.5)
+ domain_name (0.5.20180417)
+ unf (>= 0.0.5, < 1.0.0)
+ doorkeeper (4.3.2)
+ railties (>= 4.2)
+ doorkeeper-openid_connect (1.5.0)
+ doorkeeper (~> 4.3)
+ json-jwt (~> 1.6)
+ ed25519 (1.2.4)
+ email_reply_trimmer (0.1.6)
+ email_spec (2.2.0)
+ htmlentities (~> 4.3.3)
+ launchy (~> 2.1)
+ mail (~> 2.7)
+ encryptor (3.0.0)
+ equalizer (0.0.11)
+ erubi (1.7.1)
+ erubis (2.7.0)
+ escape_utils (1.2.1)
+ et-orbi (1.0.3)
+ tzinfo
+ eventmachine (1.2.7)
+ excon (0.62.0)
+ execjs (2.6.0)
+ expression_parser (0.9.0)
+ factory_bot (4.8.2)
+ activesupport (>= 3.0.0)
+ factory_bot_rails (4.8.2)
+ factory_bot (~> 4.8.2)
+ railties (>= 3.0.0)
+ faraday (0.12.2)
+ multipart-post (>= 1.2, < 3)
+ faraday_middleware (0.12.2)
+ faraday (>= 0.7.4, < 1.0)
+ faraday_middleware-multi_json (0.0.6)
+ faraday_middleware
+ multi_json
+ fast_blank (1.0.0)
+ fast_gettext (1.6.0)
+ ffaker (2.10.0)
+ ffi (1.9.25)
+ flipper (0.13.0)
+ flipper-active_record (0.13.0)
+ activerecord (>= 3.2, < 6)
+ flipper (~> 0.13.0)
+ flipper-active_support_cache_store (0.13.0)
+ activesupport (>= 3.2, < 6)
+ flipper (~> 0.13.0)
+ flowdock (0.7.1)
+ httparty (~> 0.7)
+ multi_json
+ fog-aliyun (0.2.0)
+ fog-core (~> 1.27)
+ fog-json (~> 1.0)
+ ipaddress (~> 0.8)
+ xml-simple (~> 1.1)
+ fog-aws (2.0.1)
+ fog-core (~> 1.38)
+ fog-json (~> 1.0)
+ fog-xml (~> 0.1)
+ ipaddress (~> 0.8)
+ fog-core (1.45.0)
+ builder
+ excon (~> 0.58)
+ formatador (~> 0.2)
+ fog-google (1.7.1)
+ fog-core
+ fog-json
+ fog-xml
+ google-api-client (~> 0.23.0)
+ fog-json (1.0.2)
+ fog-core (~> 1.0)
+ multi_json (~> 1.10)
+ fog-local (0.3.1)
+ fog-core (~> 1.27)
+ fog-openstack (0.1.21)
+ fog-core (>= 1.40)
+ fog-json (>= 1.0)
+ ipaddress (>= 0.8)
+ fog-rackspace (0.1.1)
+ fog-core (>= 1.35)
+ fog-json (>= 1.0)
+ fog-xml (>= 0.1)
+ ipaddress (>= 0.8)
+ fog-xml (0.1.3)
+ fog-core
+ nokogiri (>= 1.5.11, < 2.0.0)
+ font-awesome-rails (4.7.0.1)
+ railties (>= 3.2, < 5.1)
+ foreman (0.84.0)
+ thor (~> 0.19.1)
+ formatador (0.2.5)
+ fuubar (2.2.0)
+ rspec-core (~> 3.0)
+ ruby-progressbar (~> 1.4)
+ gemojione (3.3.0)
+ json
+ get_process_mem (0.2.0)
+ gettext (3.2.9)
+ locale (>= 2.0.5)
+ text (>= 1.3.0)
+ gettext_i18n_rails (1.8.0)
+ fast_gettext (>= 0.9.0)
+ gettext_i18n_rails_js (1.3.0)
+ gettext (>= 3.0.2)
+ gettext_i18n_rails (>= 0.7.1)
+ po_to_json (>= 1.0.0)
+ rails (>= 3.2.0)
+ gitaly-proto (1.2.0)
+ grpc (~> 1.0)
+ github-markup (1.7.0)
+ gitlab-markup (1.6.5)
+ gitlab-sidekiq-fetcher (0.3.0)
+ sidekiq (~> 5)
+ gitlab-styles (2.4.1)
+ rubocop (~> 0.54.0)
+ rubocop-gitlab-security (~> 0.1.0)
+ rubocop-rspec (~> 1.19)
+ gitlab_omniauth-ldap (2.0.4)
+ net-ldap (~> 0.16)
+ omniauth (~> 1.3)
+ pyu-ruby-sasl (>= 0.0.3.3, < 0.1)
+ rubyntlm (~> 0.5)
+ globalid (0.4.1)
+ activesupport (>= 4.2.0)
+ gon (6.2.0)
+ actionpack (>= 3.0)
+ multi_json
+ request_store (>= 1.0)
+ google-api-client (0.23.4)
+ addressable (~> 2.5, >= 2.5.1)
+ googleauth (>= 0.5, < 0.7.0)
+ httpclient (>= 2.8.1, < 3.0)
+ mime-types (~> 3.0)
+ representable (~> 3.0)
+ retriable (>= 2.0, < 4.0)
+ google-protobuf (3.6.1)
+ googleapis-common-protos-types (1.0.2)
+ google-protobuf (~> 3.0)
+ googleauth (0.6.6)
+ faraday (~> 0.12)
+ jwt (>= 1.4, < 3.0)
+ memoist (~> 0.12)
+ multi_json (~> 1.11)
+ os (>= 0.9, < 2.0)
+ signet (~> 0.7)
+ gpgme (2.0.18)
+ mini_portile2 (~> 2.3)
+ grape (1.1.0)
+ activesupport
+ builder
+ mustermann-grape (~> 1.0.0)
+ rack (>= 1.3.0)
+ rack-accept
+ virtus (>= 1.0.0)
+ grape-entity (0.7.1)
+ activesupport (>= 4.0)
+ multi_json (>= 1.3.2)
+ grape-path-helpers (1.0.6)
+ activesupport (>= 4, < 5.1)
+ grape (~> 1.0)
+ rake (~> 12)
+ grape_logging (1.7.0)
+ grape
+ graphiql-rails (1.4.10)
+ railties
+ sprockets-rails
+ graphql (1.8.1)
+ grpc (1.15.0)
+ google-protobuf (~> 3.1)
+ googleapis-common-protos-types (~> 1.0.0)
+ haml (5.0.4)
+ temple (>= 0.8.0)
+ tilt
+ haml_lint (0.28.0)
+ haml (>= 4.0, < 5.1)
+ rainbow
+ rake (>= 10, < 13)
+ rubocop (>= 0.50.0)
+ sysexits (~> 1.1)
+ hamlit (2.8.8)
+ temple (>= 0.8.0)
+ thor
+ tilt
+ hangouts-chat (0.0.5)
+ hashdiff (0.3.4)
+ hashie (3.5.7)
+ hashie-forbidden_attributes (0.1.1)
+ hashie (>= 3.0)
+ health_check (2.6.0)
+ rails (>= 4.0)
+ hipchat (1.5.2)
+ httparty
+ mimemagic
+ html-pipeline (2.8.4)
+ activesupport (>= 2)
+ nokogiri (>= 1.4)
+ html2text (0.2.0)
+ nokogiri (~> 1.6)
+ htmlentities (4.3.4)
+ http (3.3.0)
+ addressable (~> 2.3)
+ http-cookie (~> 1.0)
+ http-form_data (~> 2.0)
+ http_parser.rb (~> 0.6.0)
+ http-cookie (1.0.3)
+ domain_name (~> 0.5)
+ http-form_data (2.1.1)
+ http_parser.rb (0.6.0)
+ httparty (0.13.7)
+ json (~> 1.8)
+ multi_xml (>= 0.5.2)
+ httpclient (2.8.3)
+ i18n (0.9.5)
+ concurrent-ruby (~> 1.0)
+ icalendar (2.4.1)
+ ice_nine (0.11.2)
+ influxdb (0.2.3)
+ cause
+ json
+ ipaddress (0.8.3)
+ jira-ruby (1.4.1)
+ activesupport
+ multipart-post
+ oauth (~> 0.5, >= 0.5.0)
+ jquery-atwho-rails (1.3.2)
+ js_regex (2.2.1)
+ regexp_parser (>= 0.4.11, <= 0.5.0)
+ json (1.8.6)
+ json-jwt (1.9.4)
+ activesupport
+ aes_key_wrap
+ bindata
+ json-schema (2.8.0)
+ addressable (>= 2.4)
+ jwt (1.5.6)
+ kaminari (1.0.1)
+ activesupport (>= 4.1.0)
+ kaminari-actionview (= 1.0.1)
+ kaminari-activerecord (= 1.0.1)
+ kaminari-core (= 1.0.1)
+ kaminari-actionview (1.0.1)
+ actionview
+ kaminari-core (= 1.0.1)
+ kaminari-activerecord (1.0.1)
+ activerecord
+ kaminari-core (= 1.0.1)
+ kaminari-core (1.0.1)
+ kgio (2.10.0)
+ knapsack (1.17.0)
+ rake
+ kubeclient (4.0.0)
+ http (~> 3.0)
+ recursive-open-struct (~> 1.0, >= 1.0.4)
+ rest-client (~> 2.0)
+ launchy (2.4.3)
+ addressable (~> 2.3)
+ letter_opener (1.4.1)
+ launchy (~> 2.2)
+ letter_opener_web (1.3.0)
+ actionmailer (>= 3.2)
+ letter_opener (~> 1.0)
+ railties (>= 3.2)
+ license_finder (5.4.0)
+ bundler
+ rubyzip
+ thor
+ toml (= 0.2.0)
+ with_env (= 1.1.0)
+ xml-simple
+ licensee (8.9.2)
+ rugged (~> 0.24)
+ locale (2.1.2)
+ lograge (0.10.0)
+ actionpack (>= 4)
+ activesupport (>= 4)
+ railties (>= 4)
+ request_store (~> 1.0)
+ loofah (2.2.3)
+ crass (~> 1.0.2)
+ nokogiri (>= 1.5.9)
+ mail (2.7.0)
+ mini_mime (>= 0.1.1)
+ mail_room (0.9.1)
+ memoist (0.16.0)
+ memoizable (0.4.2)
+ thread_safe (~> 0.3, >= 0.3.1)
+ method_source (0.9.0)
+ mime-types (3.2.2)
+ mime-types-data (~> 3.2015)
+ mime-types-data (3.2018.0812)
+ mimemagic (0.3.0)
+ mini_magick (4.8.0)
+ mini_mime (1.0.1)
+ mini_portile2 (2.3.0)
+ minitest (5.7.0)
+ msgpack (1.2.4)
+ multi_json (1.13.1)
+ multi_xml (0.6.0)
+ multipart-post (2.0.0)
+ mustermann (1.0.3)
+ mustermann-grape (1.0.0)
+ mustermann (~> 1.0.0)
+ mysql2 (0.4.10)
+ nakayoshi_fork (0.0.4)
+ net-ldap (0.16.0)
+ net-ssh (5.0.1)
+ netrc (0.11.0)
+ nokogiri (1.8.5)
+ mini_portile2 (~> 2.3.0)
+ nokogumbo (1.5.0)
+ nokogiri
+ numerizer (0.1.1)
+ oauth (0.5.4)
+ oauth2 (1.4.0)
+ faraday (>= 0.8, < 0.13)
+ jwt (~> 1.0)
+ multi_json (~> 1.3)
+ multi_xml (~> 0.5)
+ rack (>= 1.2, < 3)
+ octokit (4.9.0)
+ sawyer (~> 0.8.0, >= 0.5.3)
+ omniauth (1.8.1)
+ hashie (>= 3.4.6, < 3.6.0)
+ rack (>= 1.6.2, < 3)
+ omniauth-auth0 (2.0.0)
+ omniauth-oauth2 (~> 1.4)
+ omniauth-authentiq (0.3.3)
+ jwt (>= 1.5)
+ omniauth-oauth2 (>= 1.5)
+ omniauth-azure-oauth2 (0.0.9)
+ jwt (~> 1.0)
+ omniauth (~> 1.0)
+ omniauth-oauth2 (~> 1.4)
+ omniauth-cas3 (1.1.4)
+ addressable (~> 2.3)
+ nokogiri (~> 1.7, >= 1.7.1)
+ omniauth (~> 1.2)
+ omniauth-facebook (4.0.0)
+ omniauth-oauth2 (~> 1.2)
+ omniauth-github (1.3.0)
+ omniauth (~> 1.5)
+ omniauth-oauth2 (>= 1.4.0, < 2.0)
+ omniauth-gitlab (1.0.3)
+ omniauth (~> 1.0)
+ omniauth-oauth2 (~> 1.0)
+ omniauth-google-oauth2 (0.5.3)
+ jwt (>= 1.5)
+ omniauth (>= 1.1.1)
+ omniauth-oauth2 (>= 1.5)
+ omniauth-kerberos (0.3.0)
+ omniauth-multipassword
+ timfel-krb5-auth (~> 0.8)
+ omniauth-multipassword (0.4.2)
+ omniauth (~> 1.0)
+ omniauth-oauth (1.1.0)
+ oauth
+ omniauth (~> 1.0)
+ omniauth-oauth2 (1.5.0)
+ oauth2 (~> 1.1)
+ omniauth (~> 1.2)
+ omniauth-oauth2-generic (0.2.2)
+ omniauth-oauth2 (~> 1.0)
+ omniauth-saml (1.10.0)
+ omniauth (~> 1.3, >= 1.3.2)
+ ruby-saml (~> 1.7)
+ omniauth-shibboleth (1.3.0)
+ omniauth (>= 1.0.0)
+ omniauth-twitter (1.4.0)
+ omniauth-oauth (~> 1.1)
+ rack
+ omniauth_crowd (2.2.3)
+ activesupport
+ nokogiri (>= 1.4.4)
+ omniauth (~> 1.0)
+ org-ruby (0.9.12)
+ rubypants (~> 0.2)
+ orm_adapter (0.5.0)
+ os (1.0.0)
+ parallel (1.12.1)
+ parser (2.5.3.0)
+ ast (~> 2.4.0)
+ parslet (1.8.2)
+ peek (1.0.1)
+ concurrent-ruby (>= 0.9.0)
+ concurrent-ruby-ext (>= 0.9.0)
+ railties (>= 4.0.0)
+ peek-gc (0.0.2)
+ peek
+ peek-mysql2 (1.1.0)
+ atomic (>= 1.0.0)
+ mysql2
+ peek
+ peek-pg (1.3.0)
+ concurrent-ruby
+ concurrent-ruby-ext
+ peek
+ pg
+ peek-rblineprof (0.2.0)
+ peek
+ rblineprof
+ peek-redis (1.2.0)
+ atomic (>= 1.0.0)
+ peek
+ redis
+ pg (0.18.4)
+ po_to_json (1.0.1)
+ json (>= 1.6.0)
+ powerpack (0.1.1)
+ premailer (1.10.4)
+ addressable
+ css_parser (>= 1.4.10)
+ htmlentities (>= 4.0.0)
+ premailer-rails (1.9.7)
+ actionmailer (>= 3, < 6)
+ premailer (~> 1.7, >= 1.7.9)
+ proc_to_ast (0.1.0)
+ coderay
+ parser
+ unparser
+ procto (0.0.3)
+ prometheus-client-mmap (0.9.4)
+ pry (0.11.3)
+ coderay (~> 1.1.0)
+ method_source (~> 0.9.0)
+ pry-byebug (3.4.3)
+ byebug (>= 9.0, < 9.1)
+ pry (~> 0.10)
+ pry-rails (0.3.6)
+ pry (>= 0.10.4)
+ public_suffix (3.0.3)
+ puma (3.12.0)
+ puma_worker_killer (0.1.0)
+ get_process_mem (~> 0.2)
+ puma (>= 2.7, < 4)
+ pyu-ruby-sasl (0.0.3.3)
+ rack (1.6.11)
+ rack-accept (0.4.5)
+ rack (>= 0.4)
+ rack-attack (4.4.1)
+ rack
+ rack-cors (1.0.2)
+ rack-oauth2 (1.2.3)
+ activesupport (>= 2.3)
+ attr_required (>= 0.0.5)
+ httpclient (>= 2.4)
+ multi_json (>= 1.3.6)
+ rack (>= 1.1)
+ rack-protection (2.0.4)
+ rack
+ rack-proxy (0.6.0)
+ rack
+ rack-test (0.6.3)
+ rack (>= 1.0)
+ rails (4.2.10)
+ actionmailer (= 4.2.10)
+ actionpack (= 4.2.10)
+ actionview (= 4.2.10)
+ activejob (= 4.2.10)
+ activemodel (= 4.2.10)
+ activerecord (= 4.2.10)
+ activesupport (= 4.2.10)
+ bundler (>= 1.3.0, < 2.0)
+ railties (= 4.2.10)
+ sprockets-rails
+ rails-deprecated_sanitizer (1.0.3)
+ activesupport (>= 4.2.0.alpha)
+ rails-dom-testing (1.0.9)
+ activesupport (>= 4.2.0, < 5.0)
+ nokogiri (~> 1.6)
+ rails-deprecated_sanitizer (>= 1.0.1)
+ rails-html-sanitizer (1.0.4)
+ loofah (~> 2.2, >= 2.2.2)
+ rails-i18n (4.0.9)
+ i18n (~> 0.7)
+ railties (~> 4.0)
+ railties (4.2.10)
+ actionpack (= 4.2.10)
+ activesupport (= 4.2.10)
+ rake (>= 0.8.7)
+ thor (>= 0.18.1, < 2.0)
+ rainbow (3.0.0)
+ raindrops (0.18.0)
+ rake (12.3.1)
+ rb-fsevent (0.10.2)
+ rb-inotify (0.9.10)
+ ffi (>= 0.5.0, < 2)
+ rblineprof (0.3.6)
+ debugger-ruby_core_source (~> 1.3)
+ rbtrace (0.4.10)
+ ffi (>= 1.0.6)
+ msgpack (>= 0.4.3)
+ trollop (>= 1.16.2)
+ rdoc (6.0.4)
+ re2 (1.1.1)
+ recaptcha (3.0.0)
+ json
+ recursive-open-struct (1.1.0)
+ redcarpet (3.4.0)
+ redis (3.3.5)
+ redis-actionpack (5.0.2)
+ actionpack (>= 4.0, < 6)
+ redis-rack (>= 1, < 3)
+ redis-store (>= 1.1.0, < 2)
+ redis-activesupport (5.0.4)
+ activesupport (>= 3, < 6)
+ redis-store (>= 1.3, < 2)
+ redis-namespace (1.6.0)
+ redis (>= 3.0.4)
+ redis-rack (2.0.4)
+ rack (>= 1.5, < 3)
+ redis-store (>= 1.2, < 2)
+ redis-rails (5.0.2)
+ redis-actionpack (>= 5.0, < 6)
+ redis-activesupport (>= 5.0, < 6)
+ redis-store (>= 1.2, < 2)
+ redis-store (1.6.0)
+ redis (>= 2.2, < 5)
+ regexp_parser (0.5.0)
+ representable (3.0.4)
+ declarative (< 0.1.0)
+ declarative-option (< 0.2.0)
+ uber (< 0.2.0)
+ request_store (1.3.1)
+ responders (2.4.0)
+ actionpack (>= 4.2.0, < 5.3)
+ railties (>= 4.2.0, < 5.3)
+ rest-client (2.0.2)
+ http-cookie (>= 1.0.2, < 2.0)
+ mime-types (>= 1.16, < 4.0)
+ netrc (~> 0.8)
+ retriable (3.1.2)
+ rinku (2.0.0)
+ rotp (2.1.2)
+ rouge (3.3.0)
+ rqrcode (0.7.0)
+ chunky_png
+ rqrcode-rails3 (0.1.7)
+ rqrcode (>= 0.4.2)
+ rspec (3.7.0)
+ rspec-core (~> 3.7.0)
+ rspec-expectations (~> 3.7.0)
+ rspec-mocks (~> 3.7.0)
+ rspec-core (3.7.1)
+ rspec-support (~> 3.7.0)
+ rspec-expectations (3.7.0)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.7.0)
+ rspec-mocks (3.7.0)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.7.0)
+ rspec-parameterized (0.4.0)
+ binding_of_caller
+ parser
+ proc_to_ast
+ rspec (>= 2.13, < 4)
+ unparser
+ rspec-rails (3.7.2)
+ actionpack (>= 3.0)
+ activesupport (>= 3.0)
+ railties (>= 3.0)
+ rspec-core (~> 3.7.0)
+ rspec-expectations (~> 3.7.0)
+ rspec-mocks (~> 3.7.0)
+ rspec-support (~> 3.7.0)
+ rspec-retry (0.4.5)
+ rspec-core
+ rspec-set (0.1.3)
+ rspec-support (3.7.1)
+ rspec_junit_formatter (0.2.3)
+ builder (< 4)
+ rspec-core (>= 2, < 4, != 2.12.0)
+ rspec_profiling (0.0.5)
+ activerecord
+ pg
+ rails
+ sqlite3
+ rubocop (0.54.0)
+ parallel (~> 1.10)
+ parser (>= 2.5)
+ powerpack (~> 0.1)
+ rainbow (>= 2.2.2, < 4.0)
+ ruby-progressbar (~> 1.7)
+ unicode-display_width (~> 1.0, >= 1.0.1)
+ rubocop-gitlab-security (0.1.1)
+ rubocop (>= 0.51)
+ rubocop-rspec (1.22.2)
+ rubocop (>= 0.52.1)
+ ruby-enum (0.7.2)
+ i18n
+ ruby-fogbugz (0.2.1)
+ crack (~> 0.4)
+ ruby-prof (0.17.0)
+ ruby-progressbar (1.9.0)
+ ruby-saml (1.7.2)
+ nokogiri (>= 1.5.10)
+ ruby_parser (3.11.0)
+ sexp_processor (~> 4.9)
+ rubyntlm (0.6.2)
+ rubypants (0.2.0)
+ rubyzip (1.2.2)
+ rufus-scheduler (3.4.0)
+ et-orbi (~> 1.0)
+ rugged (0.27.5)
+ safe_yaml (1.0.4)
+ sanitize (4.6.6)
+ crass (~> 1.0.2)
+ nokogiri (>= 1.4.4)
+ nokogumbo (~> 1.4)
+ sass (3.5.5)
+ sass-listen (~> 4.0.0)
+ sass-listen (4.0.0)
+ rb-fsevent (~> 0.9, >= 0.9.4)
+ rb-inotify (~> 0.9, >= 0.9.7)
+ sass-rails (5.0.6)
+ railties (>= 4.0.0, < 6)
+ sass (~> 3.1)
+ sprockets (>= 2.8, < 4.0)
+ sprockets-rails (>= 2.0, < 4.0)
+ tilt (>= 1.1, < 3)
+ sawyer (0.8.1)
+ addressable (>= 2.3.5, < 2.6)
+ faraday (~> 0.8, < 1.0)
+ scss_lint (0.56.0)
+ rake (>= 0.9, < 13)
+ sass (~> 3.5.3)
+ seed-fu (2.3.7)
+ activerecord (>= 3.1)
+ activesupport (>= 3.1)
+ select2-rails (3.5.9.3)
+ thor (~> 0.14)
+ selenium-webdriver (3.12.0)
+ childprocess (~> 0.5)
+ rubyzip (~> 1.2)
+ sentry-raven (2.7.2)
+ faraday (>= 0.7.6, < 1.0)
+ settingslogic (2.0.9)
+ sexp_processor (4.11.0)
+ sham_rack (1.3.6)
+ rack
+ shoulda-matchers (3.1.2)
+ activesupport (>= 4.0.0)
+ sidekiq (5.2.3)
+ connection_pool (~> 2.2, >= 2.2.2)
+ rack-protection (>= 1.5.0)
+ redis (>= 3.3.5, < 5)
+ sidekiq-cron (0.6.0)
+ rufus-scheduler (>= 3.3.0)
+ sidekiq (>= 4.2.1)
+ signet (0.11.0)
+ addressable (~> 2.3)
+ faraday (~> 0.9)
+ jwt (>= 1.5, < 3.0)
+ multi_json (~> 1.10)
+ simple_po_parser (1.1.2)
+ simplecov (0.14.1)
+ docile (~> 1.1.0)
+ json (>= 1.8, < 3)
+ simplecov-html (~> 0.10.0)
+ simplecov-html (0.10.0)
+ slack-notifier (1.5.1)
+ spring (2.0.2)
+ activesupport (>= 4.2)
+ spring-commands-rspec (1.0.4)
+ spring (>= 0.9.1)
+ sprockets (3.7.2)
+ concurrent-ruby (~> 1.0)
+ rack (> 1, < 3)
+ sprockets-rails (3.2.1)
+ actionpack (>= 4.0)
+ activesupport (>= 4.0)
+ sprockets (>= 3.0.0)
+ sqlite3 (1.3.13)
+ sshkey (1.9.0)
+ stackprof (0.2.10)
+ state_machines (0.5.0)
+ state_machines-activemodel (0.5.1)
+ activemodel (>= 4.1, < 6.0)
+ state_machines (>= 0.5.0)
+ state_machines-activerecord (0.5.1)
+ activerecord (>= 4.1, < 6.0)
+ state_machines-activemodel (>= 0.5.0)
+ sys-filesystem (1.1.6)
+ ffi
+ sysexits (1.2.0)
+ temple (0.8.0)
+ test-prof (0.2.5)
+ test_after_commit (1.1.0)
+ activerecord (>= 3.2)
+ text (1.3.1)
+ thin (1.7.2)
+ daemons (~> 1.0, >= 1.0.9)
+ eventmachine (~> 1.0, >= 1.0.4)
+ rack (>= 1, < 3)
+ thor (0.19.4)
+ thread_safe (0.3.6)
+ tilt (2.0.8)
+ timecop (0.8.1)
+ timfel-krb5-auth (0.8.3)
+ toml (0.2.0)
+ parslet (~> 1.8.0)
+ toml-rb (1.0.0)
+ citrus (~> 3.0, > 3.0)
+ trollop (2.1.3)
+ truncato (0.7.10)
+ htmlentities (~> 4.3.1)
+ nokogiri (~> 1.8.0, >= 1.7.0)
+ tzinfo (1.2.5)
+ thread_safe (~> 0.1)
+ u2f (0.2.1)
+ uber (0.1.0)
+ uglifier (2.7.2)
+ execjs (>= 0.3.0)
+ json (>= 1.8.0)
+ unf (0.1.4)
+ unf_ext
+ unf_ext (0.0.7.5)
+ unicode-display_width (1.3.2)
+ unicorn (5.1.0)
+ kgio (~> 2.6)
+ raindrops (~> 0.7)
+ unicorn-worker-killer (0.4.4)
+ get_process_mem (~> 0)
+ unicorn (>= 4, < 6)
+ uniform_notifier (1.10.0)
+ unparser (0.2.7)
+ abstract_type (~> 0.0.7)
+ adamantium (~> 0.2.0)
+ concord (~> 0.1.5)
+ diff-lcs (~> 1.3)
+ equalizer (~> 0.0.9)
+ parser (>= 2.3.1.2, < 2.6)
+ procto (~> 0.0.2)
+ validates_hostname (1.0.6)
+ activerecord (>= 3.0)
+ activesupport (>= 3.0)
+ version_sorter (2.1.0)
+ virtus (1.0.5)
+ axiom-types (~> 0.1)
+ coercible (~> 1.0)
+ descendants_tracker (~> 0.0, >= 0.0.3)
+ equalizer (~> 0.0, >= 0.0.9)
+ vmstat (2.3.0)
+ warden (1.2.7)
+ rack (>= 1.0)
+ webmock (2.3.2)
+ addressable (>= 2.3.6)
+ crack (>= 0.3.2)
+ hashdiff
+ webpack-rails (0.9.11)
+ railties (>= 3.2.0)
+ wikicloth (0.8.1)
+ builder
+ expression_parser
+ rinku
+ with_env (1.1.0)
+ xml-simple (1.1.5)
+ xpath (2.1.0)
+ nokogiri (~> 1.3)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ RedCloth (~> 4.3.2)
+ ace-rails-ap (~> 4.1.0)
+ activerecord_sane_schema_dumper (= 0.2)
+ acts-as-taggable-on (~> 5.0)
+ addressable (~> 2.5.2)
+ akismet (~> 2.0)
+ asana (~> 0.8.1)
+ asciidoctor (~> 1.5.8)
+ asciidoctor-plantuml (= 0.0.8)
+ attr_encrypted (~> 3.1.0)
+ awesome_print
+ babosa (~> 1.0.2)
+ base32 (~> 0.3.0)
+ batch-loader (~> 1.2.1)
+ bcrypt_pbkdf (~> 1.0)
+ benchmark-ips (~> 2.3.0)
+ better_errors (~> 2.5.0)
+ binding_of_caller (~> 0.8.0)
+ bootsnap (~> 1.3)
+ bootstrap_form (~> 2.7.0)
+ brakeman (~> 4.2)
+ browser (~> 2.5)
+ bullet (~> 5.5.0)
+ bundler-audit (~> 0.5.0)
+ capybara (~> 2.15)
+ capybara-screenshot (~> 1.0.0)
+ carrierwave (= 1.2.3)
+ charlock_holmes (~> 0.7.5)
+ chronic (~> 0.10.2)
+ chronic_duration (~> 0.10.6)
+ commonmarker (~> 0.17)
+ concurrent-ruby (~> 1.1)
+ connection_pool (~> 2.0)
+ creole (~> 0.5.0)
+ database_cleaner (~> 1.5.0)
+ deckar01-task_list (= 2.0.0)
+ default_value_for (~> 3.0.0)
+ device_detector
+ devise (~> 4.4)
+ devise-two-factor (~> 3.0.0)
+ diffy (~> 3.1.0)
+ discordrb-webhooks-blackst0ne (~> 3.3)
+ doorkeeper (~> 4.3)
+ doorkeeper-openid_connect (~> 1.5)
+ ed25519 (~> 1.2)
+ email_reply_trimmer (~> 0.1)
+ email_spec (~> 2.2.0)
+ escape_utils (~> 1.1)
+ factory_bot_rails (~> 4.8.2)
+ faraday (~> 0.12)
+ fast_blank
+ ffaker (~> 2.10)
+ flipper (~> 0.13.0)
+ flipper-active_record (~> 0.13.0)
+ flipper-active_support_cache_store (~> 0.13.0)
+ flowdock (~> 0.7)
+ fog-aliyun (~> 0.2.0)
+ fog-aws (~> 2.0.1)
+ fog-core (~> 1.44)
+ fog-google (~> 1.7.1)
+ fog-local (~> 0.3)
+ fog-openstack (~> 0.1)
+ fog-rackspace (~> 0.1.1)
+ font-awesome-rails (~> 4.7)
+ foreman (~> 0.84.0)
+ fuubar (~> 2.2.0)
+ gemojione (~> 3.3)
+ gettext (~> 3.2.2)
+ gettext_i18n_rails (~> 1.8.0)
+ gettext_i18n_rails_js (~> 1.3)
+ gitaly-proto (~> 1.2.0)
+ github-markup (~> 1.7.0)
+ gitlab-markup (~> 1.6.5)
+ gitlab-sidekiq-fetcher
+ gitlab-styles (~> 2.4)
+ gitlab_omniauth-ldap (~> 2.0.4)
+ gon (~> 6.2)
+ google-api-client (~> 0.23)
+ google-protobuf (~> 3.6)
+ gpgme (~> 2.0.18)
+ grape (~> 1.1.0)
+ grape-entity (~> 0.7.1)
+ grape-path-helpers (~> 1.0)
+ grape_logging (~> 1.7)
+ graphiql-rails (~> 1.4.10)
+ graphql (~> 1.8.0)
+ grpc (~> 1.15.0)
+ haml_lint (~> 0.28.0)
+ hamlit (~> 2.8.8)
+ hangouts-chat (~> 0.0.5)
+ hashie-forbidden_attributes
+ health_check (~> 2.6.0)
+ hipchat (~> 1.5.0)
+ html-pipeline (~> 2.8)
+ html2text
+ httparty (~> 0.13.3)
+ icalendar
+ influxdb (~> 0.2)
+ jira-ruby (~> 1.4)
+ jquery-atwho-rails (~> 1.3.2)
+ js_regex (~> 2.2.1)
+ json-schema (~> 2.8.0)
+ jwt (~> 1.5.6)
+ kaminari (~> 1.0)
+ knapsack (~> 1.17)
+ kubeclient (~> 4.0.0)
+ letter_opener_web (~> 1.3.0)
+ license_finder (~> 5.4)
+ licensee (~> 8.9)
+ lograge (~> 0.5)
+ loofah (~> 2.2)
+ mail_room (~> 0.9.1)
+ method_source (~> 0.8)
+ mini_magick
+ minitest (~> 5.7.0)
+ mysql2 (~> 0.4.10)
+ nakayoshi_fork (~> 0.0.4)
+ net-ldap
+ net-ssh (~> 5.0)
+ nokogiri (~> 1.8.2)
+ oauth2 (~> 1.4)
+ octokit (~> 4.9)
+ omniauth (~> 1.8)
+ omniauth-auth0 (~> 2.0.0)
+ omniauth-authentiq (~> 0.3.3)
+ omniauth-azure-oauth2 (~> 0.0.9)
+ omniauth-cas3 (~> 1.1.4)
+ omniauth-facebook (~> 4.0.0)
+ omniauth-github (~> 1.3)
+ omniauth-gitlab (~> 1.0.2)
+ omniauth-google-oauth2 (~> 0.5.3)
+ omniauth-kerberos (~> 0.3.0)
+ omniauth-oauth2-generic (~> 0.2.2)
+ omniauth-saml (~> 1.10)
+ omniauth-shibboleth (~> 1.3.0)
+ omniauth-twitter (~> 1.4)
+ omniauth_crowd (~> 2.2.0)
+ org-ruby (~> 0.9.12)
+ peek (~> 1.0.1)
+ peek-gc (~> 0.0.2)
+ peek-mysql2 (~> 1.1.0)
+ peek-pg (~> 1.3.0)
+ peek-rblineprof (~> 0.2.0)
+ peek-redis (~> 1.2.0)
+ pg (~> 0.18.2)
+ premailer-rails (~> 1.9.7)
+ prometheus-client-mmap (~> 0.9.4)
+ pry-byebug (~> 3.4.1)
+ pry-rails (~> 0.3.4)
+ puma (~> 3.12)
+ puma_worker_killer
+ rack (= 1.6.11)
+ rack-attack (~> 4.4.1)
+ rack-cors (~> 1.0.0)
+ rack-oauth2 (~> 1.2.1)
+ rack-proxy (~> 0.6.0)
+ rails (= 4.2.10)
+ rails-deprecated_sanitizer (~> 1.0.3)
+ rails-i18n (~> 4.0.9)
+ rainbow (~> 3.0)
+ raindrops (~> 0.18)
+ rblineprof (~> 0.3.6)
+ rbtrace (~> 0.4)
+ rdoc (~> 6.0)
+ re2 (~> 1.1.1)
+ recaptcha (~> 3.0)
+ redcarpet (~> 3.4)
+ redis (~> 3.2)
+ redis-namespace (~> 1.6.0)
+ redis-rails (~> 5.0.2)
+ request_store (~> 1.3)
+ responders (~> 2.0)
+ rouge (~> 3.1)
+ rqrcode-rails3 (~> 0.1.7)
+ rspec-parameterized
+ rspec-rails (~> 3.7.0)
+ rspec-retry (~> 0.4.5)
+ rspec-set (~> 0.1.3)
+ rspec_junit_formatter
+ rspec_profiling (~> 0.0.5)
+ rubocop (~> 0.54.0)
+ rubocop-rspec (~> 1.22.1)
+ ruby-fogbugz (~> 0.2.1)
+ ruby-prof (~> 0.17.0)
+ ruby-progressbar
+ ruby_parser (~> 3.8)
+ rufus-scheduler (~> 3.4)
+ rugged (~> 0.27)
+ sanitize (~> 4.6)
+ sass-rails (~> 5.0.6)
+ scss_lint (~> 0.56.0)
+ seed-fu (~> 2.3.7)
+ select2-rails (~> 3.5.9)
+ selenium-webdriver (~> 3.12)
+ sentry-raven (~> 2.7)
+ settingslogic (~> 2.0.9)
+ sham_rack (~> 1.3.6)
+ shoulda-matchers (~> 3.1.2)
+ sidekiq (~> 5.2.1)
+ sidekiq-cron (~> 0.6.0)
+ simple_po_parser (~> 1.1.2)
+ simplecov (~> 0.14.0)
+ slack-notifier (~> 1.5.1)
+ spring (~> 2.0.0)
+ spring-commands-rspec (~> 1.0.4)
+ sprockets (~> 3.7.0)
+ sshkey (~> 1.9.0)
+ stackprof (~> 0.2.10)
+ state_machines-activerecord (~> 0.5.1)
+ sys-filesystem (~> 1.1.6)
+ test-prof (~> 0.2.5)
+ test_after_commit (~> 1.1)
+ thin (~> 1.7.0)
+ timecop (~> 0.8.0)
+ toml-rb (~> 1.0.0)
+ truncato (~> 0.7.9)
+ u2f (~> 0.2.1)
+ uglifier (~> 2.7.2)
+ unf (~> 0.1.4)
+ unicorn (~> 5.1.0)
+ unicorn-worker-killer (~> 0.4.4)
+ validates_hostname (~> 1.0.6)
+ version_sorter (~> 2.1.0)
+ virtus (~> 1.0.1)
+ vmstat (~> 2.3.0)
+ webmock (~> 2.3.2)
+ webpack-rails (~> 0.9.10)
+ wikicloth (= 0.8.1)
+
+BUNDLED WITH
+ 1.17.1
diff --git a/Gemfile.rails5 b/Gemfile.rails5
deleted file mode 100644
index 2b526b19ba0..00000000000
--- a/Gemfile.rails5
+++ /dev/null
@@ -1,7 +0,0 @@
-# BUNDLE_GEMFILE=Gemfile.rails5 bundle install
-
-ENV["RAILS5"] = "true"
-
-gemfile = File.expand_path("../Gemfile", __FILE__)
-
-eval(File.read(gemfile), nil, gemfile)
diff --git a/Gemfile.rails5.lock b/Gemfile.rails5.lock
deleted file mode 100644
index aa6a32fa84e..00000000000
--- a/Gemfile.rails5.lock
+++ /dev/null
@@ -1,1205 +0,0 @@
-GEM
- remote: https://rubygems.org/
- specs:
- RedCloth (4.3.2)
- abstract_type (0.0.7)
- ace-rails-ap (4.1.2)
- actioncable (5.0.7)
- actionpack (= 5.0.7)
- nio4r (>= 1.2, < 3.0)
- websocket-driver (~> 0.6.1)
- actionmailer (5.0.7)
- actionpack (= 5.0.7)
- actionview (= 5.0.7)
- activejob (= 5.0.7)
- mail (~> 2.5, >= 2.5.4)
- rails-dom-testing (~> 2.0)
- actionpack (5.0.7)
- actionview (= 5.0.7)
- activesupport (= 5.0.7)
- rack (~> 2.0)
- rack-test (~> 0.6.3)
- rails-dom-testing (~> 2.0)
- rails-html-sanitizer (~> 1.0, >= 1.0.2)
- actionview (5.0.7)
- activesupport (= 5.0.7)
- builder (~> 3.1)
- erubis (~> 2.7.0)
- rails-dom-testing (~> 2.0)
- rails-html-sanitizer (~> 1.0, >= 1.0.3)
- activejob (5.0.7)
- activesupport (= 5.0.7)
- globalid (>= 0.3.6)
- activemodel (5.0.7)
- activesupport (= 5.0.7)
- activerecord (5.0.7)
- activemodel (= 5.0.7)
- activesupport (= 5.0.7)
- arel (~> 7.0)
- activerecord_sane_schema_dumper (1.0)
- rails (>= 5, < 6)
- activesupport (5.0.7)
- concurrent-ruby (~> 1.0, >= 1.0.2)
- i18n (>= 0.7, < 2)
- minitest (~> 5.1)
- tzinfo (~> 1.1)
- acts-as-taggable-on (5.0.0)
- activerecord (>= 4.2.8)
- adamantium (0.2.0)
- ice_nine (~> 0.11.0)
- memoizable (~> 0.4.0)
- addressable (2.5.2)
- public_suffix (>= 2.0.2, < 4.0)
- aes_key_wrap (1.0.1)
- akismet (2.0.0)
- arel (7.1.4)
- asana (0.6.0)
- faraday (~> 0.9)
- faraday_middleware (~> 0.9)
- faraday_middleware-multi_json (~> 0.0)
- oauth2 (~> 1.0)
- asciidoctor (1.5.6.2)
- asciidoctor-plantuml (0.0.8)
- asciidoctor (~> 1.5)
- asset_sync (2.4.0)
- activemodel (>= 4.1.0)
- fog-core
- mime-types (>= 2.99)
- unf
- ast (2.4.0)
- atomic (1.1.99)
- attr_encrypted (3.1.0)
- encryptor (~> 3.0.0)
- attr_required (1.0.0)
- awesome_print (1.8.0)
- axiom-types (0.1.1)
- descendants_tracker (~> 0.0.4)
- ice_nine (~> 0.11.0)
- thread_safe (~> 0.3, >= 0.3.1)
- babosa (1.0.2)
- base32 (0.3.2)
- batch-loader (1.2.1)
- bcrypt (3.1.12)
- bcrypt_pbkdf (1.0.0)
- benchmark-ips (2.3.0)
- better_errors (2.1.1)
- coderay (>= 1.0.0)
- erubis (>= 2.6.6)
- rack (>= 0.9.0)
- bindata (2.4.3)
- binding_of_caller (0.7.2)
- debug_inspector (>= 0.0.1)
- bootsnap (1.3.1)
- msgpack (~> 1.0)
- bootstrap_form (2.7.0)
- brakeman (4.2.1)
- browser (2.5.3)
- builder (3.2.3)
- bullet (5.5.1)
- activesupport (>= 3.0.0)
- uniform_notifier (~> 1.10.0)
- bundler-audit (0.5.0)
- bundler (~> 1.2)
- thor (~> 0.18)
- byebug (9.0.6)
- capybara (2.15.1)
- addressable
- mini_mime (>= 0.1.3)
- nokogiri (>= 1.3.3)
- rack (>= 1.0.0)
- rack-test (>= 0.5.4)
- xpath (~> 2.0)
- capybara-screenshot (1.0.14)
- capybara (>= 1.0, < 3)
- launchy
- carrierwave (1.2.3)
- activemodel (>= 4.0.0)
- activesupport (>= 4.0.0)
- mime-types (>= 1.16)
- cause (0.1)
- charlock_holmes (0.7.6)
- childprocess (0.9.0)
- ffi (~> 1.0, >= 1.0.11)
- chronic (0.10.2)
- chronic_duration (0.10.6)
- numerizer (~> 0.1.1)
- chunky_png (1.3.5)
- citrus (3.0.2)
- coderay (1.1.2)
- coercible (1.0.0)
- descendants_tracker (~> 0.0.1)
- commonmarker (0.17.13)
- ruby-enum (~> 0.5)
- concord (0.1.5)
- adamantium (~> 0.2.0)
- equalizer (~> 0.0.9)
- concurrent-ruby (1.0.5)
- concurrent-ruby-ext (1.0.5)
- concurrent-ruby (= 1.0.5)
- connection_pool (2.2.2)
- crack (0.4.3)
- safe_yaml (~> 1.0.0)
- crass (1.0.4)
- creole (0.5.0)
- css_parser (1.5.0)
- addressable
- daemons (1.2.3)
- database_cleaner (1.5.3)
- debug_inspector (0.0.2)
- debugger-ruby_core_source (1.3.8)
- deckar01-task_list (2.0.0)
- html-pipeline
- declarative (0.0.10)
- declarative-option (0.1.0)
- default_value_for (3.0.5)
- activerecord (>= 3.2.0, < 5.2)
- descendants_tracker (0.0.4)
- thread_safe (~> 0.3, >= 0.3.1)
- device_detector (1.0.0)
- devise (4.4.3)
- bcrypt (~> 3.0)
- orm_adapter (~> 0.1)
- railties (>= 4.1.0, < 6.0)
- responders
- warden (~> 1.2.3)
- devise-two-factor (3.0.0)
- activesupport
- attr_encrypted (>= 1.3, < 4, != 2)
- devise (~> 4.0)
- railties
- rotp (~> 2.0)
- diff-lcs (1.3)
- diffy (3.1.0)
- docile (1.1.5)
- domain_name (0.5.20180417)
- unf (>= 0.0.5, < 1.0.0)
- doorkeeper (4.3.2)
- railties (>= 4.2)
- doorkeeper-openid_connect (1.5.0)
- doorkeeper (~> 4.3)
- json-jwt (~> 1.6)
- dropzonejs-rails (0.7.2)
- rails (> 3.1)
- ed25519 (1.2.4)
- email_reply_trimmer (0.1.6)
- email_spec (2.2.0)
- htmlentities (~> 4.3.3)
- launchy (~> 2.1)
- mail (~> 2.7)
- encryptor (3.0.0)
- equalizer (0.0.11)
- erubis (2.7.0)
- escape_utils (1.1.1)
- et-orbi (1.0.3)
- tzinfo
- eventmachine (1.0.8)
- excon (0.62.0)
- execjs (2.6.0)
- expression_parser (0.9.0)
- factory_bot (4.8.2)
- activesupport (>= 3.0.0)
- factory_bot_rails (4.8.2)
- factory_bot (~> 4.8.2)
- railties (>= 3.0.0)
- faraday (0.12.2)
- multipart-post (>= 1.2, < 3)
- faraday_middleware (0.12.2)
- faraday (>= 0.7.4, < 1.0)
- faraday_middleware-multi_json (0.0.6)
- faraday_middleware
- multi_json
- fast_blank (1.0.0)
- fast_gettext (1.6.0)
- ffaker (2.4.0)
- ffi (1.9.25)
- flipper (0.13.0)
- flipper-active_record (0.13.0)
- activerecord (>= 3.2, < 6)
- flipper (~> 0.13.0)
- flipper-active_support_cache_store (0.13.0)
- activesupport (>= 3.2, < 6)
- flipper (~> 0.13.0)
- flowdock (0.7.1)
- httparty (~> 0.7)
- multi_json
- fog-aliyun (0.2.0)
- fog-core (~> 1.27)
- fog-json (~> 1.0)
- ipaddress (~> 0.8)
- xml-simple (~> 1.1)
- fog-aws (2.0.1)
- fog-core (~> 1.38)
- fog-json (~> 1.0)
- fog-xml (~> 0.1)
- ipaddress (~> 0.8)
- fog-core (1.45.0)
- builder
- excon (~> 0.58)
- formatador (~> 0.2)
- fog-google (1.7.1)
- fog-core
- fog-json
- fog-xml
- google-api-client (~> 0.23.0)
- fog-json (1.0.2)
- fog-core (~> 1.0)
- multi_json (~> 1.10)
- fog-local (0.3.1)
- fog-core (~> 1.27)
- fog-openstack (0.1.21)
- fog-core (>= 1.40)
- fog-json (>= 1.0)
- ipaddress (>= 0.8)
- fog-rackspace (0.1.1)
- fog-core (>= 1.35)
- fog-json (>= 1.0)
- fog-xml (>= 0.1)
- ipaddress (>= 0.8)
- fog-xml (0.1.3)
- fog-core
- nokogiri (>= 1.5.11, < 2.0.0)
- font-awesome-rails (4.7.0.1)
- railties (>= 3.2, < 5.1)
- foreman (0.84.0)
- thor (~> 0.19.1)
- formatador (0.2.5)
- fuubar (2.2.0)
- rspec-core (~> 3.0)
- ruby-progressbar (~> 1.4)
- gemojione (3.3.0)
- json
- get_process_mem (0.2.0)
- gettext (3.2.9)
- locale (>= 2.0.5)
- text (>= 1.3.0)
- gettext_i18n_rails (1.8.0)
- fast_gettext (>= 0.9.0)
- gettext_i18n_rails_js (1.3.0)
- gettext (>= 3.0.2)
- gettext_i18n_rails (>= 0.7.1)
- po_to_json (>= 1.0.0)
- rails (>= 3.2.0)
- gitaly-proto (0.117.0)
- google-protobuf (~> 3.1)
- grpc (~> 1.10)
- github-linguist (5.3.3)
- charlock_holmes (~> 0.7.5)
- escape_utils (~> 1.1.0)
- mime-types (>= 1.19)
- rugged (>= 0.25.1)
- github-markup (1.7.0)
- gitlab-flowdock-git-hook (1.0.1)
- flowdock (~> 0.7)
- gitlab-grit (>= 2.4.1)
- multi_json
- gitlab-gollum-lib (4.2.7.5)
- gemojione (~> 3.2)
- github-markup (~> 1.6)
- gollum-grit_adapter (~> 1.0)
- nokogiri (>= 1.6.1, < 2.0)
- rouge (~> 3.1)
- sanitize (~> 4.6.4)
- stringex (~> 2.6)
- gitlab-gollum-rugged_adapter (0.4.4.1)
- mime-types (>= 1.15)
- rugged (~> 0.25)
- gitlab-grit (2.8.2)
- charlock_holmes (~> 0.6)
- diff-lcs (~> 1.1)
- mime-types (>= 1.16)
- posix-spawn (~> 0.3)
- gitlab-markup (1.6.4)
- gitlab-styles (2.4.1)
- rubocop (~> 0.54.0)
- rubocop-gitlab-security (~> 0.1.0)
- rubocop-rspec (~> 1.19)
- gitlab_omniauth-ldap (2.0.4)
- net-ldap (~> 0.16)
- omniauth (~> 1.3)
- pyu-ruby-sasl (>= 0.0.3.3, < 0.1)
- rubyntlm (~> 0.5)
- globalid (0.4.1)
- activesupport (>= 4.2.0)
- gollum-grit_adapter (1.0.1)
- gitlab-grit (~> 2.7, >= 2.7.1)
- gon (6.2.0)
- actionpack (>= 3.0)
- multi_json
- request_store (>= 1.0)
- google-api-client (0.23.4)
- addressable (~> 2.5, >= 2.5.1)
- googleauth (>= 0.5, < 0.7.0)
- httpclient (>= 2.8.1, < 3.0)
- mime-types (~> 3.0)
- representable (~> 3.0)
- retriable (>= 2.0, < 4.0)
- google-protobuf (3.5.1)
- googleapis-common-protos-types (1.0.1)
- google-protobuf (~> 3.0)
- googleauth (0.6.2)
- faraday (~> 0.12)
- jwt (>= 1.4, < 3.0)
- logging (~> 2.0)
- memoist (~> 0.12)
- multi_json (~> 1.11)
- os (~> 0.9)
- signet (~> 0.7)
- gpgme (2.0.13)
- mini_portile2 (~> 2.1)
- grape (1.0.3)
- activesupport
- builder
- mustermann-grape (~> 1.0.0)
- rack (>= 1.3.0)
- rack-accept
- virtus (>= 1.0.0)
- grape-entity (0.7.1)
- activesupport (>= 4.0)
- multi_json (>= 1.3.2)
- grape-path-helpers (1.0.6)
- activesupport (>= 4, < 5.1)
- grape (~> 1.0)
- rake (~> 12)
- grape_logging (1.7.0)
- grape
- graphiql-rails (1.4.10)
- railties
- sprockets-rails
- graphql (1.8.1)
- grpc (1.11.0)
- google-protobuf (~> 3.1)
- googleapis-common-protos-types (~> 1.0.0)
- googleauth (>= 0.5.1, < 0.7)
- haml (5.0.4)
- temple (>= 0.8.0)
- tilt
- haml_lint (0.26.0)
- haml (>= 4.0, < 5.1)
- rainbow
- rake (>= 10, < 13)
- rubocop (>= 0.49.0)
- sysexits (~> 1.1)
- hamlit (2.8.8)
- temple (>= 0.8.0)
- thor
- tilt
- hangouts-chat (0.0.5)
- hashdiff (0.3.4)
- hashie (3.5.7)
- hashie-forbidden_attributes (0.1.1)
- hashie (>= 3.0)
- health_check (2.6.0)
- rails (>= 4.0)
- hipchat (1.5.2)
- httparty
- mimemagic
- html-pipeline (2.8.4)
- activesupport (>= 2)
- nokogiri (>= 1.4)
- html2text (0.2.0)
- nokogiri (~> 1.6)
- htmlentities (4.3.4)
- http (2.2.2)
- addressable (~> 2.3)
- http-cookie (~> 1.0)
- http-form_data (~> 1.0.1)
- http_parser.rb (~> 0.6.0)
- http-cookie (1.0.3)
- domain_name (~> 0.5)
- http-form_data (1.0.3)
- http_parser.rb (0.6.0)
- httparty (0.13.7)
- json (~> 1.8)
- multi_xml (>= 0.5.2)
- httpclient (2.8.3)
- i18n (1.0.1)
- concurrent-ruby (~> 1.0)
- icalendar (2.4.1)
- ice_nine (0.11.2)
- influxdb (0.2.3)
- cause
- json
- ipaddress (0.8.3)
- jira-ruby (1.4.1)
- activesupport
- multipart-post
- oauth (~> 0.5, >= 0.5.0)
- jquery-atwho-rails (1.3.2)
- js_regex (2.2.1)
- regexp_parser (>= 0.4.11, <= 0.5.0)
- json (1.8.6)
- json-jwt (1.9.4)
- activesupport
- aes_key_wrap
- bindata
- json-schema (2.8.0)
- addressable (>= 2.4)
- jwt (1.5.6)
- kaminari (1.0.1)
- activesupport (>= 4.1.0)
- kaminari-actionview (= 1.0.1)
- kaminari-activerecord (= 1.0.1)
- kaminari-core (= 1.0.1)
- kaminari-actionview (1.0.1)
- actionview
- kaminari-core (= 1.0.1)
- kaminari-activerecord (1.0.1)
- activerecord
- kaminari-core (= 1.0.1)
- kaminari-core (1.0.1)
- kgio (2.10.0)
- knapsack (1.16.0)
- rake
- kubeclient (3.1.0)
- http (~> 2.2.2)
- recursive-open-struct (~> 1.0, >= 1.0.4)
- rest-client (~> 2.0)
- launchy (2.4.3)
- addressable (~> 2.3)
- letter_opener (1.4.1)
- launchy (~> 2.2)
- letter_opener_web (1.3.0)
- actionmailer (>= 3.2)
- letter_opener (~> 1.0)
- railties (>= 3.2)
- license_finder (5.4.0)
- bundler
- rubyzip
- thor
- toml (= 0.2.0)
- with_env (= 1.1.0)
- xml-simple
- licensee (8.9.2)
- rugged (~> 0.24)
- little-plugger (1.1.4)
- locale (2.1.2)
- logging (2.2.2)
- little-plugger (~> 1.1)
- multi_json (~> 1.10)
- lograge (0.10.0)
- actionpack (>= 4)
- activesupport (>= 4)
- railties (>= 4)
- request_store (~> 1.0)
- loofah (2.2.2)
- crass (~> 1.0.2)
- nokogiri (>= 1.5.9)
- mail (2.7.0)
- mini_mime (>= 0.1.1)
- mail_room (0.9.1)
- memoist (0.16.0)
- memoizable (0.4.2)
- thread_safe (~> 0.3, >= 0.3.1)
- method_source (0.9.0)
- mime-types (3.1)
- mime-types-data (~> 3.2015)
- mime-types-data (3.2016.0521)
- mimemagic (0.3.0)
- mini_magick (4.8.0)
- mini_mime (1.0.0)
- mini_portile2 (2.3.0)
- minitest (5.7.0)
- mousetrap-rails (1.4.6)
- msgpack (1.2.4)
- multi_json (1.13.1)
- multi_xml (0.6.0)
- multipart-post (2.0.0)
- mustermann (1.0.2)
- mustermann-grape (1.0.0)
- mustermann (~> 1.0.0)
- mysql2 (0.4.10)
- net-ldap (0.16.0)
- net-ssh (5.0.1)
- netrc (0.11.0)
- nio4r (2.3.1)
- nokogiri (1.8.4)
- mini_portile2 (~> 2.3.0)
- nokogumbo (1.5.0)
- nokogiri
- numerizer (0.1.1)
- oauth (0.5.4)
- oauth2 (1.4.0)
- faraday (>= 0.8, < 0.13)
- jwt (~> 1.0)
- multi_json (~> 1.3)
- multi_xml (~> 0.5)
- rack (>= 1.2, < 3)
- octokit (4.9.0)
- sawyer (~> 0.8.0, >= 0.5.3)
- omniauth (1.8.1)
- hashie (>= 3.4.6, < 3.6.0)
- rack (>= 1.6.2, < 3)
- omniauth-auth0 (2.0.0)
- omniauth-oauth2 (~> 1.4)
- omniauth-authentiq (0.3.3)
- jwt (>= 1.5)
- omniauth-oauth2 (>= 1.5)
- omniauth-azure-oauth2 (0.0.9)
- jwt (~> 1.0)
- omniauth (~> 1.0)
- omniauth-oauth2 (~> 1.4)
- omniauth-cas3 (1.1.4)
- addressable (~> 2.3)
- nokogiri (~> 1.7, >= 1.7.1)
- omniauth (~> 1.2)
- omniauth-facebook (4.0.0)
- omniauth-oauth2 (~> 1.2)
- omniauth-github (1.3.0)
- omniauth (~> 1.5)
- omniauth-oauth2 (>= 1.4.0, < 2.0)
- omniauth-gitlab (1.0.3)
- omniauth (~> 1.0)
- omniauth-oauth2 (~> 1.0)
- omniauth-google-oauth2 (0.5.3)
- jwt (>= 1.5)
- omniauth (>= 1.1.1)
- omniauth-oauth2 (>= 1.5)
- omniauth-kerberos (0.3.0)
- omniauth-multipassword
- timfel-krb5-auth (~> 0.8)
- omniauth-multipassword (0.4.2)
- omniauth (~> 1.0)
- omniauth-oauth (1.1.0)
- oauth
- omniauth (~> 1.0)
- omniauth-oauth2 (1.5.0)
- oauth2 (~> 1.1)
- omniauth (~> 1.2)
- omniauth-oauth2-generic (0.2.2)
- omniauth-oauth2 (~> 1.0)
- omniauth-saml (1.10.0)
- omniauth (~> 1.3, >= 1.3.2)
- ruby-saml (~> 1.7)
- omniauth-shibboleth (1.3.0)
- omniauth (>= 1.0.0)
- omniauth-twitter (1.4.0)
- omniauth-oauth (~> 1.1)
- rack
- omniauth_crowd (2.2.3)
- activesupport
- nokogiri (>= 1.4.4)
- omniauth (~> 1.0)
- org-ruby (0.9.12)
- rubypants (~> 0.2)
- orm_adapter (0.5.0)
- os (0.9.6)
- parallel (1.12.1)
- parser (2.5.1.0)
- ast (~> 2.4.0)
- parslet (1.8.2)
- peek (1.0.1)
- concurrent-ruby (>= 0.9.0)
- concurrent-ruby-ext (>= 0.9.0)
- railties (>= 4.0.0)
- peek-gc (0.0.2)
- peek
- peek-mysql2 (1.1.0)
- atomic (>= 1.0.0)
- mysql2
- peek
- peek-pg (1.3.0)
- concurrent-ruby
- concurrent-ruby-ext
- peek
- pg
- peek-rblineprof (0.2.0)
- peek
- rblineprof
- peek-redis (1.2.0)
- atomic (>= 1.0.0)
- peek
- redis
- pg (0.18.4)
- po_to_json (1.0.1)
- json (>= 1.6.0)
- posix-spawn (0.3.13)
- powerpack (0.1.1)
- premailer (1.10.4)
- addressable
- css_parser (>= 1.4.10)
- htmlentities (>= 4.0.0)
- premailer-rails (1.9.7)
- actionmailer (>= 3, < 6)
- premailer (~> 1.7, >= 1.7.9)
- proc_to_ast (0.1.0)
- coderay
- parser
- unparser
- procto (0.0.3)
- prometheus-client-mmap (0.9.4)
- pry (0.11.3)
- coderay (~> 1.1.0)
- method_source (~> 0.9.0)
- pry-byebug (3.4.3)
- byebug (>= 9.0, < 9.1)
- pry (~> 0.10)
- pry-rails (0.3.5)
- pry (>= 0.9.10)
- public_suffix (3.0.2)
- pyu-ruby-sasl (0.0.3.3)
- rack (2.0.5)
- rack-accept (0.4.5)
- rack (>= 0.4)
- rack-attack (4.4.1)
- rack
- rack-cors (1.0.2)
- rack-oauth2 (1.2.3)
- activesupport (>= 2.3)
- attr_required (>= 0.0.5)
- httpclient (>= 2.4)
- multi_json (>= 1.3.6)
- rack (>= 1.1)
- rack-protection (2.0.3)
- rack
- rack-proxy (0.6.0)
- rack
- rack-test (0.6.3)
- rack (>= 1.0)
- rails (5.0.7)
- actioncable (= 5.0.7)
- actionmailer (= 5.0.7)
- actionpack (= 5.0.7)
- actionview (= 5.0.7)
- activejob (= 5.0.7)
- activemodel (= 5.0.7)
- activerecord (= 5.0.7)
- activesupport (= 5.0.7)
- bundler (>= 1.3.0)
- railties (= 5.0.7)
- sprockets-rails (>= 2.0.0)
- rails-controller-testing (1.0.2)
- actionpack (~> 5.x, >= 5.0.1)
- actionview (~> 5.x, >= 5.0.1)
- activesupport (~> 5.x)
- rails-deprecated_sanitizer (1.0.3)
- activesupport (>= 4.2.0.alpha)
- rails-dom-testing (2.0.3)
- activesupport (>= 4.2.0)
- nokogiri (>= 1.6)
- rails-html-sanitizer (1.0.4)
- loofah (~> 2.2, >= 2.2.2)
- rails-i18n (5.1.1)
- i18n (>= 0.7, < 2)
- railties (>= 5.0, < 6)
- railties (5.0.7)
- actionpack (= 5.0.7)
- activesupport (= 5.0.7)
- method_source
- rake (>= 0.8.7)
- thor (>= 0.18.1, < 2.0)
- rainbow (3.0.0)
- raindrops (0.18.0)
- rake (12.3.1)
- rb-fsevent (0.10.2)
- rb-inotify (0.9.10)
- ffi (>= 0.5.0, < 2)
- rblineprof (0.3.6)
- debugger-ruby_core_source (~> 1.3)
- rbtrace (0.4.10)
- ffi (>= 1.0.6)
- msgpack (>= 0.4.3)
- trollop (>= 1.16.2)
- rdoc (6.0.4)
- re2 (1.1.1)
- recaptcha (3.0.0)
- json
- recursive-open-struct (1.1.0)
- redcarpet (3.4.0)
- redis (3.3.5)
- redis-actionpack (5.0.2)
- actionpack (>= 4.0, < 6)
- redis-rack (>= 1, < 3)
- redis-store (>= 1.1.0, < 2)
- redis-activesupport (5.0.4)
- activesupport (>= 3, < 6)
- redis-store (>= 1.3, < 2)
- redis-namespace (1.6.0)
- redis (>= 3.0.4)
- redis-rack (2.0.4)
- rack (>= 1.5, < 3)
- redis-store (>= 1.2, < 2)
- redis-rails (5.0.2)
- redis-actionpack (>= 5.0, < 6)
- redis-activesupport (>= 5.0, < 6)
- redis-store (>= 1.2, < 2)
- redis-store (1.4.1)
- redis (>= 2.2, < 5)
- regexp_parser (0.5.0)
- representable (3.0.4)
- declarative (< 0.1.0)
- declarative-option (< 0.2.0)
- uber (< 0.2.0)
- request_store (1.3.1)
- responders (2.4.0)
- actionpack (>= 4.2.0, < 5.3)
- railties (>= 4.2.0, < 5.3)
- rest-client (2.0.2)
- http-cookie (>= 1.0.2, < 2.0)
- mime-types (>= 1.16, < 4.0)
- netrc (~> 0.8)
- retriable (3.1.2)
- rinku (2.0.0)
- rotp (2.1.2)
- rouge (3.2.1)
- rqrcode (0.7.0)
- chunky_png
- rqrcode-rails3 (0.1.7)
- rqrcode (>= 0.4.2)
- rspec (3.7.0)
- rspec-core (~> 3.7.0)
- rspec-expectations (~> 3.7.0)
- rspec-mocks (~> 3.7.0)
- rspec-core (3.7.1)
- rspec-support (~> 3.7.0)
- rspec-expectations (3.7.0)
- diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.7.0)
- rspec-mocks (3.7.0)
- diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.7.0)
- rspec-parameterized (0.4.0)
- binding_of_caller
- parser
- proc_to_ast
- rspec (>= 2.13, < 4)
- unparser
- rspec-rails (3.7.2)
- actionpack (>= 3.0)
- activesupport (>= 3.0)
- railties (>= 3.0)
- rspec-core (~> 3.7.0)
- rspec-expectations (~> 3.7.0)
- rspec-mocks (~> 3.7.0)
- rspec-support (~> 3.7.0)
- rspec-retry (0.4.5)
- rspec-core
- rspec-set (0.1.3)
- rspec-support (3.7.1)
- rspec_junit_formatter (0.4.1)
- rspec-core (>= 2, < 4, != 2.12.0)
- rspec_profiling (0.0.5)
- activerecord
- pg
- rails
- sqlite3
- rubocop (0.54.0)
- parallel (~> 1.10)
- parser (>= 2.5)
- powerpack (~> 0.1)
- rainbow (>= 2.2.2, < 4.0)
- ruby-progressbar (~> 1.7)
- unicode-display_width (~> 1.0, >= 1.0.1)
- rubocop-gitlab-security (0.1.1)
- rubocop (>= 0.51)
- rubocop-rspec (1.22.2)
- rubocop (>= 0.52.1)
- ruby-enum (0.7.2)
- i18n
- ruby-fogbugz (0.2.1)
- crack (~> 0.4)
- ruby-prof (0.17.0)
- ruby-progressbar (1.9.0)
- ruby-saml (1.7.2)
- nokogiri (>= 1.5.10)
- ruby_parser (3.9.0)
- sexp_processor (~> 4.1)
- rubyntlm (0.6.2)
- rubypants (0.2.0)
- rubyzip (1.2.2)
- rufus-scheduler (3.4.0)
- et-orbi (~> 1.0)
- rugged (0.27.4)
- safe_yaml (1.0.4)
- sanitize (4.6.6)
- crass (~> 1.0.2)
- nokogiri (>= 1.4.4)
- nokogumbo (~> 1.4)
- sass (3.5.5)
- sass-listen (~> 4.0.0)
- sass-listen (4.0.0)
- rb-fsevent (~> 0.9, >= 0.9.4)
- rb-inotify (~> 0.9, >= 0.9.7)
- sass-rails (5.0.6)
- railties (>= 4.0.0, < 6)
- sass (~> 3.1)
- sprockets (>= 2.8, < 4.0)
- sprockets-rails (>= 2.0, < 4.0)
- tilt (>= 1.1, < 3)
- sawyer (0.8.1)
- addressable (>= 2.3.5, < 2.6)
- faraday (~> 0.8, < 1.0)
- scss_lint (0.56.0)
- rake (>= 0.9, < 13)
- sass (~> 3.5.3)
- seed-fu (2.3.7)
- activerecord (>= 3.1)
- activesupport (>= 3.1)
- select2-rails (3.5.9.3)
- thor (~> 0.14)
- selenium-webdriver (3.12.0)
- childprocess (~> 0.5)
- rubyzip (~> 1.2)
- sentry-raven (2.7.2)
- faraday (>= 0.7.6, < 1.0)
- settingslogic (2.0.9)
- sexp_processor (4.9.0)
- sham_rack (1.3.6)
- rack
- shoulda-matchers (3.1.2)
- activesupport (>= 4.0.0)
- sidekiq (5.2.1)
- connection_pool (~> 2.2, >= 2.2.2)
- rack-protection (>= 1.5.0)
- redis (>= 3.3.5, < 5)
- sidekiq-cron (0.6.0)
- rufus-scheduler (>= 3.3.0)
- sidekiq (>= 4.2.1)
- sidekiq-limit_fetch (3.4.0)
- sidekiq (>= 4)
- signet (0.8.1)
- addressable (~> 2.3)
- faraday (~> 0.9)
- jwt (>= 1.5, < 3.0)
- multi_json (~> 1.10)
- simple_po_parser (1.1.2)
- simplecov (0.14.1)
- docile (~> 1.1.0)
- json (>= 1.8, < 3)
- simplecov-html (~> 0.10.0)
- simplecov-html (0.10.0)
- slack-notifier (1.5.1)
- spring (2.0.1)
- activesupport (>= 4.2)
- spring-commands-rspec (1.0.4)
- spring (>= 0.9.1)
- sprockets (3.7.2)
- concurrent-ruby (~> 1.0)
- rack (> 1, < 3)
- sprockets-rails (3.2.1)
- actionpack (>= 4.0)
- activesupport (>= 4.0)
- sprockets (>= 3.0.0)
- sqlite3 (1.3.13)
- sshkey (1.9.0)
- stackprof (0.2.10)
- state_machines (0.5.0)
- state_machines-activemodel (0.5.1)
- activemodel (>= 4.1, < 6.0)
- state_machines (>= 0.5.0)
- state_machines-activerecord (0.5.1)
- activerecord (>= 4.1, < 6.0)
- state_machines-activemodel (>= 0.5.0)
- stringex (2.8.4)
- sys-filesystem (1.1.6)
- ffi
- sysexits (1.2.0)
- temple (0.8.0)
- test-prof (0.2.5)
- text (1.3.1)
- thin (1.7.0)
- daemons (~> 1.0, >= 1.0.9)
- eventmachine (~> 1.0, >= 1.0.4)
- rack (>= 1, < 3)
- thor (0.19.4)
- thread_safe (0.3.6)
- tilt (2.0.8)
- timecop (0.8.1)
- timfel-krb5-auth (0.8.3)
- toml (0.2.0)
- parslet (~> 1.8.0)
- toml-rb (1.0.0)
- citrus (~> 3.0, > 3.0)
- trollop (2.1.3)
- truncato (0.7.10)
- htmlentities (~> 4.3.1)
- nokogiri (~> 1.8.0, >= 1.7.0)
- tzinfo (1.2.5)
- thread_safe (~> 0.1)
- u2f (0.2.1)
- uber (0.1.0)
- uglifier (2.7.2)
- execjs (>= 0.3.0)
- json (>= 1.8.0)
- unf (0.1.4)
- unf_ext
- unf_ext (0.0.7.5)
- unicode-display_width (1.3.2)
- unicorn (5.1.0)
- kgio (~> 2.6)
- raindrops (~> 0.7)
- unicorn-worker-killer (0.4.4)
- get_process_mem (~> 0)
- unicorn (>= 4, < 6)
- uniform_notifier (1.10.0)
- unparser (0.2.7)
- abstract_type (~> 0.0.7)
- adamantium (~> 0.2.0)
- concord (~> 0.1.5)
- diff-lcs (~> 1.3)
- equalizer (~> 0.0.9)
- parser (>= 2.3.1.2, < 2.6)
- procto (~> 0.0.2)
- validates_hostname (1.0.6)
- activerecord (>= 3.0)
- activesupport (>= 3.0)
- version_sorter (2.1.0)
- virtus (1.0.5)
- axiom-types (~> 0.1)
- coercible (~> 1.0)
- descendants_tracker (~> 0.0, >= 0.0.3)
- equalizer (~> 0.0, >= 0.0.9)
- vmstat (2.3.0)
- warden (1.2.7)
- rack (>= 1.0)
- webmock (2.3.2)
- addressable (>= 2.3.6)
- crack (>= 0.3.2)
- hashdiff
- webpack-rails (0.9.10)
- railties (>= 3.2.0)
- websocket-driver (0.6.5)
- websocket-extensions (>= 0.1.0)
- websocket-extensions (0.1.3)
- wikicloth (0.8.1)
- builder
- expression_parser
- rinku
- with_env (1.1.0)
- xml-simple (1.1.5)
- xpath (2.1.0)
- nokogiri (~> 1.3)
-
-PLATFORMS
- ruby
-
-DEPENDENCIES
- RedCloth (~> 4.3.2)
- ace-rails-ap (~> 4.1.0)
- activerecord_sane_schema_dumper (= 1.0)
- acts-as-taggable-on (~> 5.0)
- addressable (~> 2.5.2)
- akismet (~> 2.0)
- asana (~> 0.6.0)
- asciidoctor (~> 1.5.6)
- asciidoctor-plantuml (= 0.0.8)
- asset_sync (~> 2.4)
- attr_encrypted (~> 3.1.0)
- awesome_print
- babosa (~> 1.0.2)
- base32 (~> 0.3.0)
- batch-loader (~> 1.2.1)
- bcrypt_pbkdf (~> 1.0)
- benchmark-ips (~> 2.3.0)
- better_errors (~> 2.1.0)
- binding_of_caller (~> 0.7.2)
- bootsnap (~> 1.3)
- bootstrap_form (~> 2.7.0)
- brakeman (~> 4.2)
- browser (~> 2.5)
- bullet (~> 5.5.0)
- bundler-audit (~> 0.5.0)
- capybara (~> 2.15)
- capybara-screenshot (~> 1.0.0)
- carrierwave (= 1.2.3)
- charlock_holmes (~> 0.7.5)
- chronic (~> 0.10.2)
- chronic_duration (~> 0.10.6)
- commonmarker (~> 0.17)
- concurrent-ruby (~> 1.0.5)
- connection_pool (~> 2.0)
- creole (~> 0.5.0)
- database_cleaner (~> 1.5.0)
- deckar01-task_list (= 2.0.0)
- default_value_for (~> 3.0.5)
- device_detector
- devise (~> 4.4)
- devise-two-factor (~> 3.0.0)
- diffy (~> 3.1.0)
- doorkeeper (~> 4.3)
- doorkeeper-openid_connect (~> 1.5)
- dropzonejs-rails (~> 0.7.1)
- ed25519 (~> 1.2)
- email_reply_trimmer (~> 0.1)
- email_spec (~> 2.2.0)
- factory_bot_rails (~> 4.8.2)
- faraday (~> 0.12)
- fast_blank
- ffaker (~> 2.4)
- flipper (~> 0.13.0)
- flipper-active_record (~> 0.13.0)
- flipper-active_support_cache_store (~> 0.13.0)
- fog-aliyun (~> 0.2.0)
- fog-aws (~> 2.0.1)
- fog-core (~> 1.44)
- fog-google (~> 1.7.1)
- fog-local (~> 0.3)
- fog-openstack (~> 0.1)
- fog-rackspace (~> 0.1.1)
- font-awesome-rails (~> 4.7)
- foreman (~> 0.84.0)
- fuubar (~> 2.2.0)
- gemojione (~> 3.3)
- gettext (~> 3.2.2)
- gettext_i18n_rails (~> 1.8.0)
- gettext_i18n_rails_js (~> 1.3)
- gitaly-proto (~> 0.117.0)
- github-linguist (~> 5.3.3)
- gitlab-flowdock-git-hook (~> 1.0.1)
- gitlab-gollum-lib (~> 4.2)
- gitlab-gollum-rugged_adapter (~> 0.4.4)
- gitlab-markup (~> 1.6.4)
- gitlab-styles (~> 2.4)
- gitlab_omniauth-ldap (~> 2.0.4)
- gon (~> 6.2)
- google-api-client (~> 0.23)
- google-protobuf (= 3.5.1)
- gpgme
- grape (~> 1.0)
- grape-entity (~> 0.7.1)
- grape-path-helpers (~> 1.0)
- grape_logging (~> 1.7)
- graphiql-rails (~> 1.4.10)
- graphql (~> 1.8.0)
- grpc (~> 1.11.0)
- haml_lint (~> 0.26.0)
- hamlit (~> 2.8.8)
- hangouts-chat (~> 0.0.5)
- hashie-forbidden_attributes
- health_check (~> 2.6.0)
- hipchat (~> 1.5.0)
- html-pipeline (~> 2.8)
- html2text
- httparty (~> 0.13.3)
- icalendar
- influxdb (~> 0.2)
- jira-ruby (~> 1.4)
- jquery-atwho-rails (~> 1.3.2)
- js_regex (~> 2.2.1)
- json-schema (~> 2.8.0)
- jwt (~> 1.5.6)
- kaminari (~> 1.0)
- knapsack (~> 1.16)
- kubeclient (~> 3.1.0)
- letter_opener_web (~> 1.3.0)
- license_finder (~> 5.4)
- licensee (~> 8.9)
- lograge (~> 0.5)
- loofah (~> 2.2)
- mail_room (~> 0.9.1)
- method_source (~> 0.8)
- mini_magick
- minitest (~> 5.7.0)
- mousetrap-rails (~> 1.4.6)
- mysql2 (~> 0.4.10)
- net-ldap
- net-ssh (~> 5.0)
- nokogiri (~> 1.8.2)
- oauth2 (~> 1.4)
- octokit (~> 4.9)
- omniauth (~> 1.8)
- omniauth-auth0 (~> 2.0.0)
- omniauth-authentiq (~> 0.3.3)
- omniauth-azure-oauth2 (~> 0.0.9)
- omniauth-cas3 (~> 1.1.4)
- omniauth-facebook (~> 4.0.0)
- omniauth-github (~> 1.3)
- omniauth-gitlab (~> 1.0.2)
- omniauth-google-oauth2 (~> 0.5.3)
- omniauth-kerberos (~> 0.3.0)
- omniauth-oauth2-generic (~> 0.2.2)
- omniauth-saml (~> 1.10)
- omniauth-shibboleth (~> 1.3.0)
- omniauth-twitter (~> 1.4)
- omniauth_crowd (~> 2.2.0)
- org-ruby (~> 0.9.12)
- peek (~> 1.0.1)
- peek-gc (~> 0.0.2)
- peek-mysql2 (~> 1.1.0)
- peek-pg (~> 1.3.0)
- peek-rblineprof (~> 0.2.0)
- peek-redis (~> 1.2.0)
- pg (~> 0.18.2)
- premailer-rails (~> 1.9.7)
- prometheus-client-mmap (~> 0.9.4)
- pry-byebug (~> 3.4.1)
- pry-rails (~> 0.3.4)
- rack-attack (~> 4.4.1)
- rack-cors (~> 1.0.0)
- rack-oauth2 (~> 1.2.1)
- rack-proxy (~> 0.6.0)
- rails (= 5.0.7)
- rails-controller-testing
- rails-deprecated_sanitizer (~> 1.0.3)
- rails-i18n (~> 5.1)
- rainbow (~> 3.0)
- raindrops (~> 0.18)
- rblineprof (~> 0.3.6)
- rbtrace (~> 0.4)
- rdoc (~> 6.0)
- re2 (~> 1.1.1)
- recaptcha (~> 3.0)
- redcarpet (~> 3.4)
- redis (~> 3.2)
- redis-namespace (~> 1.6.0)
- redis-rails (~> 5.0.2)
- request_store (~> 1.3)
- responders (~> 2.0)
- rouge (~> 3.1)
- rqrcode-rails3 (~> 0.1.7)
- rspec-parameterized
- rspec-rails (~> 3.7.0)
- rspec-retry (~> 0.4.5)
- rspec-set (~> 0.1.3)
- rspec_junit_formatter
- rspec_profiling (~> 0.0.5)
- rubocop (~> 0.54.0)
- rubocop-rspec (~> 1.22.1)
- ruby-fogbugz (~> 0.2.1)
- ruby-prof (~> 0.17.0)
- ruby-progressbar
- ruby_parser (~> 3.8)
- rufus-scheduler (~> 3.4)
- rugged (~> 0.27)
- sanitize (~> 4.6)
- sass-rails (~> 5.0.6)
- scss_lint (~> 0.56.0)
- seed-fu (~> 2.3.7)
- select2-rails (~> 3.5.9)
- selenium-webdriver (~> 3.12)
- sentry-raven (~> 2.7)
- settingslogic (~> 2.0.9)
- sham_rack (~> 1.3.6)
- shoulda-matchers (~> 3.1.2)
- sidekiq (~> 5.2.1)
- sidekiq-cron (~> 0.6.0)
- sidekiq-limit_fetch (~> 3.4)
- simple_po_parser (~> 1.1.2)
- simplecov (~> 0.14.0)
- slack-notifier (~> 1.5.1)
- spring (~> 2.0.0)
- spring-commands-rspec (~> 1.0.4)
- sprockets (~> 3.7.0)
- sshkey (~> 1.9.0)
- stackprof (~> 0.2.10)
- state_machines-activerecord (~> 0.5.1)
- sys-filesystem (~> 1.1.6)
- test-prof (~> 0.2.5)
- thin (~> 1.7.0)
- timecop (~> 0.8.0)
- toml-rb (~> 1.0.0)
- truncato (~> 0.7.9)
- u2f (~> 0.2.1)
- uglifier (~> 2.7.2)
- unf (~> 0.1.4)
- unicorn (~> 5.1.0)
- unicorn-worker-killer (~> 0.4.4)
- validates_hostname (~> 1.0.6)
- version_sorter (~> 2.1.0)
- virtus (~> 1.0.1)
- vmstat (~> 2.3.0)
- webmock (~> 2.3.2)
- webpack-rails (~> 0.9.10)
- wikicloth (= 0.8.1)
-
-BUNDLED WITH
- 1.16.4
diff --git a/PHILOSOPHY.md b/PHILOSOPHY.md
new file mode 100644
index 00000000000..e966d88ef78
--- /dev/null
+++ b/PHILOSOPHY.md
@@ -0,0 +1 @@
+This document is intended to communicate the product philosophy GitLab uses in creating GitLab Community Edition. The principles can be found in the [Product Section of the GitLab Handbook](https://about.gitlab.com/handbook/product/#product-at-gitlab). \ No newline at end of file
diff --git a/PROCESS.md b/PROCESS.md
index 38ec01f9de0..aadd6a321f0 100644
--- a/PROCESS.md
+++ b/PROCESS.md
@@ -95,6 +95,12 @@ picked into the stable branches) up to the 19th of the month. Such merge
requests should have the ~"feature flag" label assigned, and don't require a
corresponding exception request to be created.
+In order to build the final package and present the feature for self-hosted
+customers, the feature flag should be removed. This should happen before the
+22nd, ideally _at least_ 2 days before. That means MRs with feature
+flags being picked at the 19th would have a quite tight schedule, so picking
+these _earlier_ is preferable.
+
While rare, release managers may decide to reject picking a change into a stable
branch, even when feature flags are used. This might be necessary if the changes
are deemed problematic, too invasive, or there simply isn't enough time to
@@ -208,6 +214,7 @@ the stable branch are:
* Fixes or improvements to automated QA scenarios
* [Documentation updates](https://docs.gitlab.com/ee/development/documentation/workflow.html#documentation-shipped-late) for changes in the same release
* New or updated translations (as long as they do not touch application code)
+* Changes that are behind a feature flag and have the ~"feature flag" label
During the feature freeze all merge requests that are meant to go into the
upcoming release should have the correct milestone assigned _and_ the
diff --git a/README.md b/README.md
index 335736e53f5..133c15a83a7 100644
--- a/README.md
+++ b/README.md
@@ -83,7 +83,7 @@ Instructions on how to start GitLab and how to run the tests can be found in the
GitLab is a Ruby on Rails application that runs on the following software:
- Ubuntu/Debian/CentOS/RHEL/OpenSUSE
-- Ruby (MRI) 2.3
+- Ruby (MRI) 2.4
- Git 2.8.4+
- Redis 2.8+
- PostgreSQL (preferred) or MySQL
diff --git a/VERSION b/VERSION
index 39a87ed80d7..35167c50c26 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-11.4.0-pre
+11.6.0-pre
diff --git a/app/assets/images/ci_favicons/canary/favicon_status_scheduled.ico b/app/assets/images/ci_favicons/canary/favicon_status_scheduled.ico
new file mode 100644
index 00000000000..5444b8e41dc
--- /dev/null
+++ b/app/assets/images/ci_favicons/canary/favicon_status_scheduled.ico
Binary files differ
diff --git a/app/assets/images/ci_favicons/favicon_status_scheduled.png b/app/assets/images/ci_favicons/favicon_status_scheduled.png
new file mode 100644
index 00000000000..d198c255fdd
--- /dev/null
+++ b/app/assets/images/ci_favicons/favicon_status_scheduled.png
Binary files differ
diff --git a/app/assets/images/cluster_app_logos/cert_manager.png b/app/assets/images/cluster_app_logos/cert_manager.png
new file mode 100644
index 00000000000..bbc867858da
--- /dev/null
+++ b/app/assets/images/cluster_app_logos/cert_manager.png
Binary files differ
diff --git a/app/assets/images/cluster_app_logos/knative.png b/app/assets/images/cluster_app_logos/knative.png
new file mode 100644
index 00000000000..0a2510c8549
--- /dev/null
+++ b/app/assets/images/cluster_app_logos/knative.png
Binary files differ
diff --git a/app/assets/images/koding-logo.svg b/app/assets/images/koding-logo.svg
deleted file mode 100644
index ad89d684d94..00000000000
--- a/app/assets/images/koding-logo.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 14">
- <g fill="#d6d7d9">
- <path d="M8.7 0L5.3.3l3.2 6.8-3.2 6.6 3.5.3L12 6.9z"/>
- <ellipse cx="1.7" cy="11.1" rx="1.7" ry="1.7"/>
- <ellipse cx="1.7" cy="5.6" rx="1.7" ry="1.7"/>
- </g>
-</svg> \ No newline at end of file
diff --git a/app/assets/javascripts/activities.js b/app/assets/javascripts/activities.js
index de4566bb119..05de970e387 100644
--- a/app/assets/javascripts/activities.js
+++ b/app/assets/javascripts/activities.js
@@ -6,10 +6,12 @@ import Pager from './pager';
import { localTimeAgo } from './lib/utils/datetime_utility';
export default class Activities {
- constructor() {
- Pager.init(20, true, false, data => data, this.updateTooltips);
+ constructor(container = '') {
+ this.container = container;
- $('.event-filter-link').on('click', (e) => {
+ Pager.init(20, true, false, data => data, this.updateTooltips, this.container);
+
+ $('.event-filter-link').on('click', e => {
e.preventDefault();
this.toggleFilter(e.currentTarget);
this.reloadActivities();
@@ -22,7 +24,7 @@ export default class Activities {
reloadActivities() {
$('.content_list').html('');
- Pager.init(20, true, false, data => data, this.updateTooltips);
+ Pager.init(20, true, false, data => data, this.updateTooltips, this.container);
}
toggleFilter(sender) {
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index cd800d75f7a..f8dbe412f80 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -5,23 +5,22 @@ import axios from './lib/utils/axios_utils';
const Api = {
groupsPath: '/api/:version/groups.json',
groupPath: '/api/:version/groups/:id',
+ subgroupsPath: '/api/:version/groups/:id/subgroups',
namespacesPath: '/api/:version/namespaces.json',
groupProjectsPath: '/api/:version/groups/:id/projects.json',
projectsPath: '/api/:version/projects.json',
projectPath: '/api/:version/projects/:id',
projectLabelsPath: '/:namespace_path/:project_path/labels',
- mergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid',
+ projectMergeRequestPath: '/api/:version/projects/:id/merge_requests/:mrid',
+ projectMergeRequestChangesPath: '/api/:version/projects/:id/merge_requests/:mrid/changes',
+ projectMergeRequestVersionsPath: '/api/:version/projects/:id/merge_requests/:mrid/versions',
mergeRequestsPath: '/api/:version/merge_requests',
- mergeRequestChangesPath: '/api/:version/projects/:id/merge_requests/:mrid/changes',
- mergeRequestVersionsPath: '/api/:version/projects/:id/merge_requests/:mrid/versions',
groupLabelsPath: '/groups/:namespace_path/-/labels',
- templatesPath: '/api/:version/templates/:key',
- licensePath: '/api/:version/templates/licenses/:key',
- gitignorePath: '/api/:version/templates/gitignores/:key',
- gitlabCiYmlPath: '/api/:version/templates/gitlab_ci_ymls/:key',
- dockerfilePath: '/api/:version/templates/dockerfiles/:key',
issuableTemplatePath: '/:namespace_path/:project_path/templates/:type/:key',
+ projectTemplatePath: '/api/:version/projects/:id/templates/:type/:key',
+ projectTemplatesPath: '/api/:version/projects/:id/templates/:type',
usersPath: '/api/:version/users.json',
+ userStatusPath: '/api/:version/user/status',
commitPath: '/api/:version/projects/:id/repository/commits',
commitPipelinesPath: '/:project_id/commit/:sha/pipelines',
branchSinglePath: '/api/:version/projects/:id/repository/branches/:branch',
@@ -101,36 +100,36 @@ const Api = {
},
// Return Merge Request for project
- mergeRequest(projectPath, mergeRequestId, params = {}) {
- const url = Api.buildUrl(Api.mergeRequestPath)
+ projectMergeRequest(projectPath, mergeRequestId, params = {}) {
+ const url = Api.buildUrl(Api.projectMergeRequestPath)
.replace(':id', encodeURIComponent(projectPath))
.replace(':mrid', mergeRequestId);
return axios.get(url, { params });
},
- mergeRequests(params = {}) {
- const url = Api.buildUrl(Api.mergeRequestsPath);
-
- return axios.get(url, { params });
- },
-
- mergeRequestChanges(projectPath, mergeRequestId) {
- const url = Api.buildUrl(Api.mergeRequestChangesPath)
+ projectMergeRequestChanges(projectPath, mergeRequestId) {
+ const url = Api.buildUrl(Api.projectMergeRequestChangesPath)
.replace(':id', encodeURIComponent(projectPath))
.replace(':mrid', mergeRequestId);
return axios.get(url);
},
- mergeRequestVersions(projectPath, mergeRequestId) {
- const url = Api.buildUrl(Api.mergeRequestVersionsPath)
+ projectMergeRequestVersions(projectPath, mergeRequestId) {
+ const url = Api.buildUrl(Api.projectMergeRequestVersionsPath)
.replace(':id', encodeURIComponent(projectPath))
.replace(':mrid', mergeRequestId);
return axios.get(url);
},
+ mergeRequests(params = {}) {
+ const url = Api.buildUrl(Api.mergeRequestsPath);
+
+ return axios.get(url, { params });
+ },
+
newLabel(namespacePath, projectPath, data, callback) {
let url;
@@ -195,29 +194,29 @@ const Api = {
return axios.get(url);
},
- // Return text for a specific license
- licenseText(key, data, callback) {
- const url = Api.buildUrl(Api.licensePath).replace(':key', key);
- return axios
- .get(url, {
- params: data,
- })
- .then(res => callback(res.data));
- },
+ projectTemplate(id, type, key, options, callback) {
+ const url = Api.buildUrl(this.projectTemplatePath)
+ .replace(':id', encodeURIComponent(id))
+ .replace(':type', type)
+ .replace(':key', encodeURIComponent(key));
- gitignoreText(key, callback) {
- const url = Api.buildUrl(Api.gitignorePath).replace(':key', key);
- return axios.get(url).then(({ data }) => callback(data));
- },
+ return axios.get(url, { params: options }).then(res => {
+ if (callback) callback(res.data);
- gitlabCiYml(key, callback) {
- const url = Api.buildUrl(Api.gitlabCiYmlPath).replace(':key', key);
- return axios.get(url).then(({ data }) => callback(data));
+ return res;
+ });
},
- dockerfileYml(key, callback) {
- const url = Api.buildUrl(Api.dockerfilePath).replace(':key', key);
- return axios.get(url).then(({ data }) => callback(data));
+ projectTemplates(id, type, params = {}, callback) {
+ const url = Api.buildUrl(this.projectTemplatesPath)
+ .replace(':id', encodeURIComponent(id))
+ .replace(':type', type);
+
+ return axios.get(url, { params }).then(res => {
+ if (callback) callback(res.data);
+
+ return res;
+ });
},
issueTemplate(namespacePath, projectPath, key, type, callback) {
@@ -266,10 +265,13 @@ const Api = {
});
},
- templates(key, params = {}) {
- const url = Api.buildUrl(this.templatesPath).replace(':key', key);
+ postUserStatus({ emoji, message }) {
+ const url = Api.buildUrl(this.userStatusPath);
- return axios.get(url, { params });
+ return axios.put(url, {
+ emoji,
+ message,
+ });
},
buildUrl(url) {
diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js
index 5b0c4285339..cace8bb9dba 100644
--- a/app/assets/javascripts/awards_handler.js
+++ b/app/assets/javascripts/awards_handler.js
@@ -42,10 +42,11 @@ export class AwardsHandler {
}
bindEvents() {
+ const $parentEl = this.targetContainerEl ? $(this.targetContainerEl) : $(document);
// If the user shows intent let's pre-build the menu
this.registerEventListener(
'one',
- $(document),
+ $parentEl,
'mouseenter focus',
this.toggleButtonSelector,
'mouseenter focus',
@@ -58,7 +59,7 @@ export class AwardsHandler {
}
},
);
- this.registerEventListener('on', $(document), 'click', this.toggleButtonSelector, e => {
+ this.registerEventListener('on', $parentEl, 'click', this.toggleButtonSelector, e => {
e.stopPropagation();
e.preventDefault();
this.showEmojiMenu($(e.currentTarget));
@@ -76,7 +77,7 @@ export class AwardsHandler {
});
const emojiButtonSelector = `.js-awards-block .js-emoji-btn, .${this.menuClass} .js-emoji-btn`;
- this.registerEventListener('on', $(document), 'click', emojiButtonSelector, e => {
+ this.registerEventListener('on', $parentEl, 'click', emojiButtonSelector, e => {
e.preventDefault();
const $target = $(e.currentTarget);
const $glEmojiElement = $target.find('gl-emoji');
@@ -168,7 +169,8 @@ export class AwardsHandler {
</div>
`;
- document.body.insertAdjacentHTML('beforeend', emojiMenuMarkup);
+ const targetEl = this.targetContainerEl ? this.targetContainerEl : document.body;
+ targetEl.insertAdjacentHTML('beforeend', emojiMenuMarkup);
this.addRemainingEmojiMenuCategories();
this.setupSearch();
@@ -250,6 +252,12 @@ export class AwardsHandler {
}
positionMenu($menu, $addBtn) {
+ if (this.targetContainerEl) {
+ return $menu.css({
+ top: `${$addBtn.outerHeight()}px`,
+ });
+ }
+
const position = $addBtn.data('position');
// The menu could potentially be off-screen or in a hidden overflow element
// So we position the element absolute in the body
@@ -424,9 +432,7 @@ export class AwardsHandler {
users = origTitle.trim().split(FROM_SENTENCE_REGEX);
}
users.unshift('You');
- return awardBlock
- .attr('title', this.toSentence(users))
- .tooltip('_fixTitle');
+ return awardBlock.attr('title', this.toSentence(users)).tooltip('_fixTitle');
}
createAwardButtonForVotesBlock(votesBlock, emojiName) {
@@ -609,13 +615,11 @@ export class AwardsHandler {
let awardsHandlerPromise = null;
export default function loadAwardsHandler(reload = false) {
if (!awardsHandlerPromise || reload) {
- awardsHandlerPromise = import(/* webpackChunkName: 'emoji' */ './emoji').then(
- Emoji => {
- const awardsHandler = new AwardsHandler(Emoji);
- awardsHandler.bindEvents();
- return awardsHandler;
- },
- );
+ awardsHandlerPromise = import(/* webpackChunkName: 'emoji' */ './emoji').then(Emoji => {
+ const awardsHandler = new AwardsHandler(Emoji);
+ awardsHandler.bindEvents();
+ return awardsHandler;
+ });
}
return awardsHandlerPromise;
}
diff --git a/app/assets/javascripts/badges/components/badge.vue b/app/assets/javascripts/badges/components/badge.vue
index b08dc454d12..ae2916e3a3b 100644
--- a/app/assets/javascripts/badges/components/badge.vue
+++ b/app/assets/javascripts/badges/components/badge.vue
@@ -1,15 +1,15 @@
<script>
import Icon from '~/vue_shared/components/icon.vue';
-import Tooltip from '~/vue_shared/directives/tooltip';
+import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
export default {
name: 'Badge',
components: {
Icon,
- Tooltip,
+ GlLoadingIcon,
},
directives: {
- Tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
imageUrl: {
@@ -63,12 +63,7 @@ export default {
<template>
<div>
- <a
- v-show="!isLoading && !hasError"
- :href="linkUrl"
- target="_blank"
- rel="noopener noreferrer"
- >
+ <a v-show="!isLoading && !hasError" :href="linkUrl" target="_blank" rel="noopener noreferrer">
<img
:src="imageUrlWithRetries"
class="project-badge"
@@ -78,15 +73,9 @@ export default {
/>
</a>
- <gl-loading-icon
- v-show="isLoading"
- :inline="true"
- />
+ <gl-loading-icon v-show="isLoading" :inline="true" />
- <div
- v-show="hasError"
- class="btn-group"
- >
+ <div v-show="hasError" class="btn-group">
<div class="btn btn-default btn-sm disabled">
<icon
:size="16"
@@ -95,25 +84,20 @@ export default {
aria-hidden="true"
/>
</div>
- <div
- class="btn btn-default btn-sm disabled"
- >
+ <div class="btn btn-default btn-sm disabled">
<span class="prepend-left-8 append-right-8">{{ s__('Badges|No badge image') }}</span>
</div>
</div>
<button
- v-tooltip
v-show="hasError"
+ v-gl-tooltip.hover
:title="s__('Badges|Reload badge image')"
class="btn btn-transparent btn-sm text-primary"
type="button"
@click="reloadImage"
>
- <icon
- :size="16"
- name="retry"
- />
+ <icon :size="16" name="retry" />
</button>
</div>
</template>
diff --git a/app/assets/javascripts/badges/components/badge_form.vue b/app/assets/javascripts/badges/components/badge_form.vue
index aff7c4180e3..85a15b38de1 100644
--- a/app/assets/javascripts/badges/components/badge_form.vue
+++ b/app/assets/javascripts/badges/components/badge_form.vue
@@ -4,6 +4,7 @@ import { mapActions, mapState } from 'vuex';
import createFlash from '~/flash';
import { s__, sprintf } from '~/locale';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
import createEmptyBadge from '../empty_badge';
import Badge from './badge.vue';
@@ -14,6 +15,7 @@ export default {
components: {
Badge,
LoadingButton,
+ GlLoadingIcon,
},
props: {
isEditing: {
@@ -153,10 +155,7 @@ export default {
@submit.prevent.stop="onSubmit"
>
<div class="form-group">
- <label
- for="badge-link-url"
- class="label-bold"
- >{{ s__('Badges|Link') }}</label>
+ <label for="badge-link-url" class="label-bold">{{ s__('Badges|Link') }}</label>
<p v-html="helpText"></p>
<input
id="badge-link-url"
@@ -166,19 +165,12 @@ export default {
required
@input="debouncedPreview"
/>
- <div class="invalid-feedback">
- {{ s__('Badges|Please fill in a valid URL') }}
- </div>
- <span class="form-text text-muted">
- {{ badgeLinkUrlExample }}
- </span>
+ <div class="invalid-feedback">{{ s__('Badges|Please fill in a valid URL') }}</div>
+ <span class="form-text text-muted"> {{ badgeLinkUrlExample }} </span>
</div>
<div class="form-group">
- <label
- for="badge-image-url"
- class="label-bold"
- >{{ s__('Badges|Badge image URL') }}</label>
+ <label for="badge-image-url" class="label-bold">{{ s__('Badges|Badge image URL') }}</label>
<p v-html="helpText"></p>
<input
id="badge-image-url"
@@ -188,12 +180,8 @@ export default {
required
@input="debouncedPreview"
/>
- <div class="invalid-feedback">
- {{ s__('Badges|Please fill in a valid URL') }}
- </div>
- <span class="form-text text-muted">
- {{ badgeImageUrlExample }}
- </span>
+ <div class="invalid-feedback">{{ s__('Badges|Please fill in a valid URL') }}</div>
+ <span class="form-text text-muted"> {{ badgeImageUrlExample }} </span>
</div>
<div class="form-group">
@@ -204,37 +192,22 @@ export default {
:image-url="renderedImageUrl"
:link-url="renderedLinkUrl"
/>
- <p v-show="isRendering">
- <gl-loading-icon
- :inline="true"
- />
+ <p v-show="isRendering"><gl-loading-icon :inline="true" /></p>
+ <p v-show="!renderedBadge && !isRendering" class="disabled-content">
+ {{ s__('Badges|No image to preview') }}
</p>
- <p
- v-show="!renderedBadge && !isRendering"
- class="disabled-content"
- >{{ s__('Badges|No image to preview') }}</p>
</div>
- <div
- v-if="isEditing"
- class="row-content-block"
- >
+ <div v-if="isEditing" class="row-content-block">
<loading-button
:loading="isSaving"
:label="s__('Badges|Save changes')"
type="submit"
container-class="btn btn-success"
/>
- <button
- class="btn btn-cancel"
- type="button"
- @click="onCancel"
- >{{ __('Cancel') }}</button>
+ <button class="btn btn-cancel" type="button" @click="onCancel">{{ __('Cancel') }}</button>
</div>
- <div
- v-else
- class="form-group"
- >
+ <div v-else class="form-group">
<loading-button
:loading="isSaving"
:label="s__('Badges|Add badge')"
diff --git a/app/assets/javascripts/badges/components/badge_list.vue b/app/assets/javascripts/badges/components/badge_list.vue
index 359d3e10380..d2767dd6c64 100644
--- a/app/assets/javascripts/badges/components/badge_list.vue
+++ b/app/assets/javascripts/badges/components/badge_list.vue
@@ -1,5 +1,6 @@
<script>
import { mapState } from 'vuex';
+import { GlLoadingIcon } from '@gitlab/ui';
import BadgeListRow from './badge_list_row.vue';
import { GROUP_BADGE } from '../constants';
@@ -7,6 +8,7 @@ export default {
name: 'BadgeList',
components: {
BadgeListRow,
+ GlLoadingIcon,
},
computed: {
...mapState(['badges', 'isLoading', 'kind']),
@@ -24,32 +26,15 @@ export default {
<div class="card">
<div class="card-header">
{{ s__('Badges|Your badges') }}
- <span
- v-show="!isLoading"
- class="badge badge-pill"
- >{{ badges.length }}</span>
+ <span v-show="!isLoading" class="badge badge-pill">{{ badges.length }}</span>
</div>
- <gl-loading-icon
- v-show="isLoading"
- :size="2"
- class="card-body"
- />
- <div
- v-if="hasNoBadges"
- class="card-body"
- >
+ <gl-loading-icon v-show="isLoading" :size="2" class="card-body" />
+ <div v-if="hasNoBadges" class="card-body">
<span v-if="isGroupBadge">{{ s__('Badges|This group has no badges') }}</span>
<span v-else>{{ s__('Badges|This project has no badges') }}</span>
</div>
- <div
- v-else
- class="card-body"
- >
- <badge-list-row
- v-for="badge in badges"
- :key="badge.id"
- :badge="badge"
- />
+ <div v-else class="card-body">
+ <badge-list-row v-for="badge in badges" :key="badge.id" :badge="badge" />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/badges/components/badge_list_row.vue b/app/assets/javascripts/badges/components/badge_list_row.vue
index 5d16ba3ce6d..9051be1e102 100644
--- a/app/assets/javascripts/badges/components/badge_list_row.vue
+++ b/app/assets/javascripts/badges/components/badge_list_row.vue
@@ -2,6 +2,7 @@
import { mapActions, mapState } from 'vuex';
import { s__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
import { PROJECT_BADGE } from '../constants';
import Badge from './badge.vue';
@@ -10,6 +11,7 @@ export default {
components: {
Badge,
Icon,
+ GlLoadingIcon,
},
props: {
badge: {
@@ -48,20 +50,14 @@ export default {
<span class="badge badge-pill">{{ badgeKindText }}</span>
</div>
<div class="table-section section-15 table-button-footer">
- <div
- v-if="canEditBadge"
- class="table-action-buttons">
+ <div v-if="canEditBadge" class="table-action-buttons">
<button
:disabled="badge.isDeleting"
class="btn btn-default append-right-8"
type="button"
- @click="editBadge(badge)"
+ @click="editBadge(badge);"
>
- <icon
- :size="16"
- :aria-label="__('Edit')"
- name="pencil"
- />
+ <icon :size="16" :aria-label="__('Edit')" name="pencil" />
</button>
<button
:disabled="badge.isDeleting"
@@ -69,18 +65,11 @@ export default {
type="button"
data-toggle="modal"
data-target="#delete-badge-modal"
- @click="updateBadgeInModal(badge)"
+ @click="updateBadgeInModal(badge);"
>
- <icon
- :size="16"
- :aria-label="__('Delete')"
- name="remove"
- />
+ <icon :size="16" :aria-label="__('Delete')" name="remove" />
</button>
- <gl-loading-icon
- v-show="badge.isDeleting"
- :inline="true"
- />
+ <gl-loading-icon v-show="badge.isDeleting" :inline="true" />
</div>
</div>
</div>
diff --git a/app/assets/javascripts/badges/components/badge_settings.vue b/app/assets/javascripts/badges/components/badge_settings.vue
index cc47e56dd1e..75a522efe7e 100644
--- a/app/assets/javascripts/badges/components/badge_settings.vue
+++ b/app/assets/javascripts/badges/components/badge_settings.vue
@@ -46,7 +46,8 @@ export default {
:header-title-text="s__('Badges|Delete badge?')"
:footer-primary-button-text="s__('Badges|Delete badge')"
footer-primary-button-variant="danger"
- @submit="onSubmitModal">
+ @submit="onSubmitModal"
+ >
<div class="well">
<badge
:image-url="badgeInModal ? badgeInModal.renderedImageUrl : ''"
@@ -56,15 +57,9 @@ export default {
<p v-html="deleteModalText"></p>
</gl-modal>
- <badge-form
- v-show="isEditing"
- :is-editing="true"
- />
+ <badge-form v-show="isEditing" :is-editing="true" />
- <badge-form
- v-show="!isEditing"
- :is-editing="false"
- />
+ <badge-form v-show="!isEditing" :is-editing="false" />
<badge-list v-show="!isEditing" />
</div>
</template>
diff --git a/app/assets/javascripts/behaviors/copy_to_clipboard.js b/app/assets/javascripts/behaviors/copy_to_clipboard.js
index 00419e80cbb..9a33a060c76 100644
--- a/app/assets/javascripts/behaviors/copy_to_clipboard.js
+++ b/app/assets/javascripts/behaviors/copy_to_clipboard.js
@@ -51,7 +51,7 @@ export default function initCopyToClipboard() {
* the last minute to deconstruct this JSON hash and set the `text/plain` and `text/x-gfm` copy
* data types to the intended values.
*/
- $(document).on('copy', 'body > textarea[readonly]', (e) => {
+ $(document).on('copy', 'body > textarea[readonly]', e => {
const { clipboardData } = e.originalEvent;
if (!clipboardData) return;
diff --git a/app/assets/javascripts/behaviors/details_behavior.js b/app/assets/javascripts/behaviors/details_behavior.js
index 1d63f5baeee..9bdfc21c7e4 100644
--- a/app/assets/javascripts/behaviors/details_behavior.js
+++ b/app/assets/javascripts/behaviors/details_behavior.js
@@ -2,7 +2,9 @@ import $ from 'jquery';
$(() => {
$('body').on('click', '.js-details-target', function target() {
- $(this).closest('.js-details-container').toggleClass('open');
+ $(this)
+ .closest('.js-details-container')
+ .toggleClass('open');
});
// Show details content. Hides link after click.
@@ -13,7 +15,9 @@ $(() => {
//
$('body').on('click', '.js-details-expand', function expand(e) {
e.preventDefault();
- $(this).next('.js-details-content').removeClass('hide');
+ $(this)
+ .next('.js-details-content')
+ .removeClass('hide');
$(this).hide();
const truncatedItem = $(this).siblings('.js-details-short');
diff --git a/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js b/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js
index 5d7a3bed301..fe02096d903 100644
--- a/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js
+++ b/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js
@@ -1,4 +1,4 @@
-/* eslint-disable object-shorthand, no-unused-vars, no-use-before-define, max-len, no-restricted-syntax, guard-for-in, no-continue */
+/* eslint-disable object-shorthand, no-unused-vars, no-use-before-define, no-restricted-syntax, guard-for-in, no-continue */
import $ from 'jquery';
import _ from 'underscore';
@@ -34,7 +34,7 @@ const gfmRules = {
},
},
AutolinkFilter: {
- 'a'(el, text) {
+ a(el, text) {
// Fallback on the regular MarkdownFilter's `a` handler.
if (text !== el.getAttribute('href')) return false;
@@ -60,7 +60,7 @@ const gfmRules = {
},
},
ImageLazyLoadFilter: {
- 'img'(el, text) {
+ img(el, text) {
return `![${el.getAttribute('alt')}](${el.getAttribute('src')})`;
},
},
@@ -71,7 +71,7 @@ const gfmRules = {
return CopyAsGFM.nodeToGFM(videoEl);
},
- 'video'(el) {
+ video(el) {
return `![${el.dataset.title}](${el.getAttribute('src')})`;
},
},
@@ -118,11 +118,14 @@ const gfmRules = {
'a[name]:not([href]):empty'(el) {
return el.outerHTML;
},
- 'dl'(el, text) {
- let lines = text.replace(/\n\n/g, '\n').trim().split('\n');
+ dl(el, text) {
+ let lines = text
+ .replace(/\n\n/g, '\n')
+ .trim()
+ .split('\n');
// Add two spaces to the front of subsequent list items lines,
// or leave the line entirely blank.
- lines = lines.map((l) => {
+ lines = lines.map(l => {
const line = l.trim();
if (line.length === 0) return '';
@@ -151,27 +154,30 @@ const gfmRules = {
// Prefixes lines with 4 spaces if the code contains triple backticks
if (lang === '' && text.match(/^```/gm)) {
- return text.split('\n').map((l) => {
- const line = l.trim();
- if (line.length === 0) return '';
-
- return ` ${line}`;
- }).join('\n');
+ return text
+ .split('\n')
+ .map(l => {
+ const line = l.trim();
+ if (line.length === 0) return '';
+
+ return ` ${line}`;
+ })
+ .join('\n');
}
return `\`\`\`${lang}\n${text}\n\`\`\``;
},
'pre > code'(el, text) {
- // Don't wrap code blocks in ``
+ // Don't wrap code blocks in ``
return text;
},
},
MarkdownFilter: {
- 'br'(el) {
+ br(el) {
// Two spaces at the end of a line are turned into a BR
return ' ';
},
- 'code'(el, text) {
+ code(el, text) {
let backtickCount = 1;
const backtickMatch = text.match(/`+/);
if (backtickMatch) {
@@ -183,27 +189,31 @@ const gfmRules = {
return backticks + spaceOrNoSpace + text.trim() + spaceOrNoSpace + backticks;
},
- 'blockquote'(el, text) {
- return text.trim().split('\n').map(s => `> ${s}`.trim()).join('\n');
+ blockquote(el, text) {
+ return text
+ .trim()
+ .split('\n')
+ .map(s => `> ${s}`.trim())
+ .join('\n');
},
- 'img'(el) {
+ img(el) {
const imageSrc = el.src;
- const imageUrl = imageSrc && imageSrc !== placeholderImage ? imageSrc : (el.dataset.src || '');
+ const imageUrl = imageSrc && imageSrc !== placeholderImage ? imageSrc : el.dataset.src || '';
return `![${el.getAttribute('alt')}](${imageUrl})`;
},
'a.anchor'(el, text) {
// Don't render a Markdown link for the anchor link inside a heading
return text;
},
- 'a'(el, text) {
+ a(el, text) {
return `[${text}](${el.getAttribute('href')})`;
},
- 'li'(el, text) {
+ li(el, text) {
const lines = text.trim().split('\n');
const firstLine = `- ${lines.shift()}`;
// Add four spaces to the front of subsequent list items lines,
// or leave the line entirely blank.
- const nextLines = lines.map((s) => {
+ const nextLines = lines.map(s => {
if (s.trim().length === 0) return '';
return ` ${s}`;
@@ -211,49 +221,49 @@ const gfmRules = {
return `${firstLine}\n${nextLines.join('\n')}`;
},
- 'ul'(el, text) {
+ ul(el, text) {
return text;
},
- 'ol'(el, text) {
+ ol(el, text) {
// LIs get a `- ` prefix by default, which we replace by `1. ` for ordered lists.
- return text.replace(/^- /mg, '1. ');
+ return text.replace(/^- /gm, '1. ');
},
- 'h1'(el, text) {
+ h1(el, text) {
return `# ${text.trim()}\n`;
},
- 'h2'(el, text) {
+ h2(el, text) {
return `## ${text.trim()}\n`;
},
- 'h3'(el, text) {
+ h3(el, text) {
return `### ${text.trim()}\n`;
},
- 'h4'(el, text) {
+ h4(el, text) {
return `#### ${text.trim()}\n`;
},
- 'h5'(el, text) {
+ h5(el, text) {
return `##### ${text.trim()}\n`;
},
- 'h6'(el, text) {
+ h6(el, text) {
return `###### ${text.trim()}\n`;
},
- 'strong'(el, text) {
+ strong(el, text) {
return `**${text}**`;
},
- 'em'(el, text) {
+ em(el, text) {
return `_${text}_`;
},
- 'del'(el, text) {
+ del(el, text) {
return `~~${text}~~`;
},
- 'hr'(el) {
+ hr(el) {
// extra leading \n is to ensure that there is a blank line between
// a list followed by an hr, otherwise this breaks old redcarpet rendering
return '\n-----\n';
},
- 'p'(el, text) {
+ p(el, text) {
return `${text.trim()}\n`;
},
- 'table'(el) {
+ table(el) {
const theadEl = el.querySelector('thead');
const tbodyEl = el.querySelector('tbody');
if (!theadEl || !tbodyEl) return false;
@@ -263,8 +273,8 @@ const gfmRules = {
return [theadText, tbodyText].join('\n');
},
- 'thead'(el, text) {
- const cells = _.map(el.querySelectorAll('th'), (cell) => {
+ thead(el, text) {
+ const cells = _.map(el.querySelectorAll('th'), cell => {
let chars = CopyAsGFM.nodeToGFM(cell).length + 2;
let before = '';
@@ -296,7 +306,7 @@ const gfmRules = {
return [text, separatorRow].join('\n');
},
- 'tr'(el) {
+ tr(el) {
const cellEls = el.querySelectorAll('td, th');
if (cellEls.length === 0) return false;
@@ -315,8 +325,12 @@ export class CopyAsGFM {
const isIOS = /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent);
if (isIOS) return;
- $(document).on('copy', '.md, .wiki', (e) => { CopyAsGFM.copyAsGFM(e, CopyAsGFM.transformGFMSelection); });
- $(document).on('copy', 'pre.code.highlight, .diff-content .line_content', (e) => { CopyAsGFM.copyAsGFM(e, CopyAsGFM.transformCodeSelection); });
+ $(document).on('copy', '.md, .wiki', e => {
+ CopyAsGFM.copyAsGFM(e, CopyAsGFM.transformGFMSelection);
+ });
+ $(document).on('copy', 'pre.code.highlight, .diff-content .line_content', e => {
+ CopyAsGFM.copyAsGFM(e, CopyAsGFM.transformCodeSelection);
+ });
$(document).on('paste', '.js-gfm-input', CopyAsGFM.pasteGFM);
}
@@ -356,7 +370,7 @@ export class CopyAsGFM {
// This will break down when the actual code block contains an uneven
// number of backticks, but this is a rare edge case.
const backtickMatch = textBefore.match(/`/g);
- const insideCodeBlock = backtickMatch && (backtickMatch.length % 2) === 1;
+ const insideCodeBlock = backtickMatch && backtickMatch.length % 2 === 1;
if (insideCodeBlock) {
return text;
@@ -393,7 +407,9 @@ export class CopyAsGFM {
let lineSelector = '.line';
if (target) {
- const lineClass = ['left-side', 'right-side'].filter(name => target.classList.contains(name))[0];
+ const lineClass = ['left-side', 'right-side'].filter(name =>
+ target.classList.contains(name),
+ )[0];
if (lineClass) {
lineSelector = `.line_content.${lineClass} ${lineSelector}`;
}
@@ -436,7 +452,8 @@ export class CopyAsGFM {
return node.textContent;
}
- const respectWhitespace = respectWhitespaceParam || (node.nodeName === 'PRE' || node.nodeName === 'CODE');
+ const respectWhitespace =
+ respectWhitespaceParam || (node.nodeName === 'PRE' || node.nodeName === 'CODE');
const text = this.innerGFM(node, respectWhitespace);
diff --git a/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js b/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js
index a303e504cc7..55c68139ded 100644
--- a/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js
+++ b/app/assets/javascripts/behaviors/markdown/gfm_auto_complete.js
@@ -1,11 +1,11 @@
import $ from 'jquery';
-import { convertPermissionToBoolean } from '~/lib/utils/common_utils';
+import { parseBoolean } from '~/lib/utils/common_utils';
import GfmAutoComplete from '~/gfm_auto_complete';
export default function initGFMInput() {
$('.js-gfm-input:not(.js-vue-textarea)').each((i, el) => {
const gfm = new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources);
- const enableGFM = convertPermissionToBoolean(el.dataset.supportsAutocomplete);
+ const enableGFM = parseBoolean(el.dataset.supportsAutocomplete);
gfm.setup($(el), {
emojis: true,
diff --git a/app/assets/javascripts/behaviors/markdown/highlight_current_user.js b/app/assets/javascripts/behaviors/markdown/highlight_current_user.js
new file mode 100644
index 00000000000..6208b3f0032
--- /dev/null
+++ b/app/assets/javascripts/behaviors/markdown/highlight_current_user.js
@@ -0,0 +1,17 @@
+/**
+ * Highlights the current user in existing elements with a user ID data attribute.
+ *
+ * @param elements DOM elements that represent user mentions
+ */
+export default function highlightCurrentUser(elements) {
+ const currentUserId = gon && gon.current_user_id;
+ if (!currentUserId) {
+ return;
+ }
+
+ elements.forEach(element => {
+ if (parseInt(element.dataset.user, 10) === currentUserId) {
+ element.classList.add('current-user');
+ }
+ });
+}
diff --git a/app/assets/javascripts/behaviors/markdown/render_gfm.js b/app/assets/javascripts/behaviors/markdown/render_gfm.js
index 429455f97ec..a2d4331b6d1 100644
--- a/app/assets/javascripts/behaviors/markdown/render_gfm.js
+++ b/app/assets/javascripts/behaviors/markdown/render_gfm.js
@@ -2,6 +2,7 @@ import $ from 'jquery';
import syntaxHighlight from '~/syntax_highlight';
import renderMath from './render_math';
import renderMermaid from './render_mermaid';
+import highlightCurrentUser from './highlight_current_user';
// Render GitLab flavoured Markdown
//
@@ -11,6 +12,7 @@ $.fn.renderGFM = function renderGFM() {
syntaxHighlight(this.find('.js-syntax-highlight'));
renderMath(this.find('.js-render-math'));
renderMermaid(this.find('.js-render-mermaid'));
+ highlightCurrentUser(this.find('.gfm-project_member').get());
return this;
};
diff --git a/app/assets/javascripts/behaviors/markdown/render_math.js b/app/assets/javascripts/behaviors/markdown/render_math.js
index eb4e59d12b1..a68936d79e2 100644
--- a/app/assets/javascripts/behaviors/markdown/render_math.js
+++ b/app/assets/javascripts/behaviors/markdown/render_math.js
@@ -32,7 +32,9 @@ export default function renderMath($els) {
Promise.all([
import(/* webpackChunkName: 'katex' */ 'katex'),
import(/* webpackChunkName: 'katex' */ 'katex/dist/katex.min.css'),
- ]).then(([katex]) => {
- renderWithKaTeX($els, katex);
- }).catch(() => flash(__('An error occurred while rendering KaTeX')));
+ ])
+ .then(([katex]) => {
+ renderWithKaTeX($els, katex);
+ })
+ .catch(() => flash(__('An error occurred while rendering KaTeX')));
}
diff --git a/app/assets/javascripts/behaviors/markdown/render_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
index 56b1896e9f1..35380ca49fb 100644
--- a/app/assets/javascripts/behaviors/markdown/render_mermaid.js
+++ b/app/assets/javascripts/behaviors/markdown/render_mermaid.js
@@ -17,41 +17,46 @@ import flash from '~/flash';
export default function renderMermaid($els) {
if (!$els.length) return;
- import(/* webpackChunkName: 'mermaid' */ 'blackst0ne-mermaid').then((mermaid) => {
- mermaid.initialize({
- // mermaid core options
- mermaid: {
- startOnLoad: false,
- },
- // mermaidAPI options
- theme: 'neutral',
- });
+ import(/* webpackChunkName: 'mermaid' */ 'mermaid')
+ .then(mermaid => {
+ mermaid.initialize({
+ // mermaid core options
+ mermaid: {
+ startOnLoad: false,
+ },
+ // mermaidAPI options
+ theme: 'neutral',
+ flowchart: {
+ htmlLabels: false,
+ },
+ });
- $els.each((i, el) => {
- const source = el.textContent;
+ $els.each((i, el) => {
+ const source = el.textContent;
- // Remove any extra spans added by the backend syntax highlighting.
- Object.assign(el, { textContent: source });
+ // Remove any extra spans added by the backend syntax highlighting.
+ Object.assign(el, { textContent: source });
- mermaid.init(undefined, el, (id) => {
- const svg = document.getElementById(id);
+ mermaid.init(undefined, el, id => {
+ const svg = document.getElementById(id);
- svg.classList.add('mermaid');
+ svg.classList.add('mermaid');
- // pre > code > svg
- svg.closest('pre').replaceWith(svg);
+ // pre > code > svg
+ svg.closest('pre').replaceWith(svg);
- // We need to add the original source into the DOM to allow Copy-as-GFM
- // to access it.
- const sourceEl = document.createElement('text');
- sourceEl.classList.add('source');
- sourceEl.setAttribute('display', 'none');
- sourceEl.textContent = source;
+ // We need to add the original source into the DOM to allow Copy-as-GFM
+ // to access it.
+ const sourceEl = document.createElement('text');
+ sourceEl.classList.add('source');
+ sourceEl.setAttribute('display', 'none');
+ sourceEl.textContent = source;
- svg.appendChild(sourceEl);
+ svg.appendChild(sourceEl);
+ });
});
+ })
+ .catch(err => {
+ flash(`Can't load mermaid module: ${err}`);
});
- }).catch((err) => {
- flash(`Can't load mermaid module: ${err}`);
- });
}
diff --git a/app/assets/javascripts/behaviors/preview_markdown.js b/app/assets/javascripts/behaviors/preview_markdown.js
index 0964baf8954..35f1bb6b080 100644
--- a/app/assets/javascripts/behaviors/preview_markdown.js
+++ b/app/assets/javascripts/behaviors/preview_markdown.js
@@ -26,7 +26,7 @@ MarkdownPreview.prototype.emptyMessage = 'Nothing to preview.';
MarkdownPreview.prototype.ajaxCache = {};
-MarkdownPreview.prototype.showPreview = function ($form) {
+MarkdownPreview.prototype.showPreview = function($form) {
var mdText;
var markdownVersion;
var url;
@@ -44,34 +44,40 @@ MarkdownPreview.prototype.showPreview = function ($form) {
this.hideReferencedUsers($form);
} else {
preview.addClass('md-preview-loading').text('Loading...');
- this.fetchMarkdownPreview(mdText, url, (function (response) {
- var body;
- if (response.body.length > 0) {
- ({ body } = response);
- } else {
- body = this.emptyMessage;
- }
-
- preview.removeClass('md-preview-loading').html(body);
- preview.renderGFM();
- this.renderReferencedUsers(response.references.users, $form);
-
- if (response.references.commands) {
- this.renderReferencedCommands(response.references.commands, $form);
- }
- }).bind(this));
+ this.fetchMarkdownPreview(
+ mdText,
+ url,
+ function(response) {
+ var body;
+ if (response.body.length > 0) {
+ ({ body } = response);
+ } else {
+ body = this.emptyMessage;
+ }
+
+ preview.removeClass('md-preview-loading').html(body);
+ preview.renderGFM();
+ this.renderReferencedUsers(response.references.users, $form);
+
+ if (response.references.commands) {
+ this.renderReferencedCommands(response.references.commands, $form);
+ }
+ }.bind(this),
+ );
}
};
-MarkdownPreview.prototype.versionedPreviewPath = function (markdownPreviewPath, markdownVersion) {
+MarkdownPreview.prototype.versionedPreviewPath = function(markdownPreviewPath, markdownVersion) {
if (typeof markdownVersion === 'undefined') {
return markdownPreviewPath;
}
- return `${markdownPreviewPath}${markdownPreviewPath.indexOf('?') === -1 ? '?' : '&'}markdown_version=${markdownVersion}`;
+ return `${markdownPreviewPath}${
+ markdownPreviewPath.indexOf('?') === -1 ? '?' : '&'
+ }markdown_version=${markdownVersion}`;
};
-MarkdownPreview.prototype.fetchMarkdownPreview = function (text, url, success) {
+MarkdownPreview.prototype.fetchMarkdownPreview = function(text, url, success) {
if (!url) {
return;
}
@@ -79,24 +85,25 @@ MarkdownPreview.prototype.fetchMarkdownPreview = function (text, url, success) {
success(this.ajaxCache.response);
return;
}
- axios.post(url, {
- text,
- })
- .then(({ data }) => {
- this.ajaxCache = {
- text: text,
- response: data,
- };
- success(data);
- })
- .catch(() => flash(__('An error occurred while fetching markdown preview')));
+ axios
+ .post(url, {
+ text,
+ })
+ .then(({ data }) => {
+ this.ajaxCache = {
+ text: text,
+ response: data,
+ };
+ success(data);
+ })
+ .catch(() => flash(__('An error occurred while fetching markdown preview')));
};
-MarkdownPreview.prototype.hideReferencedUsers = function ($form) {
+MarkdownPreview.prototype.hideReferencedUsers = function($form) {
$form.find('.referenced-users').hide();
};
-MarkdownPreview.prototype.renderReferencedUsers = function (users, $form) {
+MarkdownPreview.prototype.renderReferencedUsers = function(users, $form) {
var referencedUsers;
referencedUsers = $form.find('.referenced-users');
if (referencedUsers.length) {
@@ -109,11 +116,11 @@ MarkdownPreview.prototype.renderReferencedUsers = function (users, $form) {
}
};
-MarkdownPreview.prototype.hideReferencedCommands = function ($form) {
+MarkdownPreview.prototype.hideReferencedCommands = function($form) {
$form.find('.referenced-commands').hide();
};
-MarkdownPreview.prototype.renderReferencedCommands = function (commands, $form) {
+MarkdownPreview.prototype.renderReferencedCommands = function(commands, $form) {
var referencedCommands;
referencedCommands = $form.find('.referenced-commands');
if (commands.length > 0) {
@@ -132,14 +139,14 @@ writeButtonSelector = '.js-md-write-button';
lastTextareaPreviewed = null;
const markdownToolbar = $('.md-header-toolbar');
-$.fn.setupMarkdownPreview = function () {
+$.fn.setupMarkdownPreview = function() {
var $form = $(this);
- $form.find('textarea.markdown-area').on('input', function () {
+ $form.find('textarea.markdown-area').on('input', function() {
markdownPreview.hideReferencedUsers($form);
});
};
-$(document).on('markdown-preview:show', function (e, $form) {
+$(document).on('markdown-preview:show', function(e, $form) {
if (!$form) {
return;
}
@@ -148,8 +155,14 @@ $(document).on('markdown-preview:show', function (e, $form) {
lastTextareaHeight = lastTextareaPreviewed.height();
// toggle tabs
- $form.find(writeButtonSelector).parent().removeClass('active');
- $form.find(previewButtonSelector).parent().addClass('active');
+ $form
+ .find(writeButtonSelector)
+ .parent()
+ .removeClass('active');
+ $form
+ .find(previewButtonSelector)
+ .parent()
+ .addClass('active');
// toggle content
$form.find('.md-write-holder').hide();
@@ -158,7 +171,7 @@ $(document).on('markdown-preview:show', function (e, $form) {
markdownPreview.showPreview($form);
});
-$(document).on('markdown-preview:hide', function (e, $form) {
+$(document).on('markdown-preview:hide', function(e, $form) {
if (!$form) {
return;
}
@@ -169,8 +182,14 @@ $(document).on('markdown-preview:hide', function (e, $form) {
}
// toggle tabs
- $form.find(writeButtonSelector).parent().addClass('active');
- $form.find(previewButtonSelector).parent().removeClass('active');
+ $form
+ .find(writeButtonSelector)
+ .parent()
+ .addClass('active');
+ $form
+ .find(previewButtonSelector)
+ .parent()
+ .removeClass('active');
// toggle content
$form.find('.md-write-holder').show();
@@ -181,7 +200,7 @@ $(document).on('markdown-preview:hide', function (e, $form) {
markdownPreview.hideReferencedCommands($form);
});
-$(document).on('markdown-preview:toggle', function (e, keyboardEvent) {
+$(document).on('markdown-preview:toggle', function(e, keyboardEvent) {
var $target;
$target = $(keyboardEvent.target);
if ($target.is('textarea.markdown-area')) {
@@ -194,14 +213,14 @@ $(document).on('markdown-preview:toggle', function (e, keyboardEvent) {
}
});
-$(document).on('click', previewButtonSelector, function (e) {
+$(document).on('click', previewButtonSelector, function(e) {
var $form;
e.preventDefault();
$form = $(this).closest('form');
$(document).triggerHandler('markdown-preview:show', [$form]);
});
-$(document).on('click', writeButtonSelector, function (e) {
+$(document).on('click', writeButtonSelector, function(e) {
var $form;
e.preventDefault();
$form = $(this).closest('form');
diff --git a/app/assets/javascripts/behaviors/quick_submit.js b/app/assets/javascripts/behaviors/quick_submit.js
index b6e2781773c..c1ea67f9293 100644
--- a/app/assets/javascripts/behaviors/quick_submit.js
+++ b/app/assets/javascripts/behaviors/quick_submit.js
@@ -28,7 +28,7 @@ function keyCodeIs(e, keyCode) {
return e.keyCode === keyCode;
}
-$(document).on('keydown.quick_submit', '.js-quick-submit', (e) => {
+$(document).on('keydown.quick_submit', '.js-quick-submit', e => {
// Enter
if (!keyCodeIs(e, 13)) {
return;
@@ -55,23 +55,25 @@ $(document).on('keydown.quick_submit', '.js-quick-submit', (e) => {
// If the user tabs to a submit button on a `js-quick-submit` form, display a
// tooltip to let them know they could've used the hotkey
-$(document).on('keyup.quick_submit', '.js-quick-submit input[type=submit], .js-quick-submit button[type=submit]', function displayTooltip(e) {
- // Tab
- if (!keyCodeIs(e, 9)) {
- return;
- }
+$(document).on(
+ 'keyup.quick_submit',
+ '.js-quick-submit input[type=submit], .js-quick-submit button[type=submit]',
+ function displayTooltip(e) {
+ // Tab
+ if (!keyCodeIs(e, 9)) {
+ return;
+ }
- const $this = $(this);
- const title = isMac() ?
- 'You can also press &#8984;-Enter' :
- 'You can also press Ctrl-Enter';
+ const $this = $(this);
+ const title = isMac() ? 'You can also press &#8984;-Enter' : 'You can also press Ctrl-Enter';
- $this.tooltip({
- container: 'body',
- html: 'true',
- placement: 'top',
- title,
- trigger: 'manual',
- });
- $this.tooltip('show').one('blur click', () => $this.tooltip('hide'));
-});
+ $this.tooltip({
+ container: 'body',
+ html: 'true',
+ placement: 'top',
+ title,
+ trigger: 'manual',
+ });
+ $this.tooltip('show').one('blur click', () => $this.tooltip('hide'));
+ },
+);
diff --git a/app/assets/javascripts/behaviors/requires_input.js b/app/assets/javascripts/behaviors/requires_input.js
index a8b6dbf0948..c09d9ccddd6 100644
--- a/app/assets/javascripts/behaviors/requires_input.js
+++ b/app/assets/javascripts/behaviors/requires_input.js
@@ -18,7 +18,8 @@ import '../commons/bootstrap';
$.fn.requiresInput = function requiresInput() {
const $form = $(this);
const $button = $('button[type=submit], input[type=submit]', $form);
- const fieldSelector = 'input[required=required], select[required=required], textarea[required=required]';
+ const fieldSelector =
+ 'input[required=required], select[required=required], textarea[required=required]';
function requireInput() {
// Collect the input values of *all* required fields
diff --git a/app/assets/javascripts/behaviors/secret_values.js b/app/assets/javascripts/behaviors/secret_values.js
index 0d6e0dbefcc..5b92608d536 100644
--- a/app/assets/javascripts/behaviors/secret_values.js
+++ b/app/assets/javascripts/behaviors/secret_values.js
@@ -1,5 +1,5 @@
import { n__ } from '../locale';
-import { convertPermissionToBoolean } from '../lib/utils/common_utils';
+import { parseBoolean } from '../lib/utils/common_utils';
export default class SecretValues {
constructor({
@@ -16,7 +16,7 @@ export default class SecretValues {
this.revealButton = this.container.querySelector('.js-secret-value-reveal-button');
if (this.revealButton) {
- const isRevealed = convertPermissionToBoolean(this.revealButton.dataset.secretRevealStatus);
+ const isRevealed = parseBoolean(this.revealButton.dataset.secretRevealStatus);
this.updateDom(isRevealed);
this.revealButton.addEventListener('click', this.onRevealButtonClicked.bind(this));
@@ -24,24 +24,24 @@ export default class SecretValues {
}
onRevealButtonClicked() {
- const previousIsRevealed = convertPermissionToBoolean(
- this.revealButton.dataset.secretRevealStatus,
- );
+ const previousIsRevealed = parseBoolean(this.revealButton.dataset.secretRevealStatus);
this.updateDom(!previousIsRevealed);
}
updateDom(isRevealed) {
const values = this.container.querySelectorAll(this.valueSelector);
- values.forEach((value) => {
+ values.forEach(value => {
value.classList.toggle('hide', !isRevealed);
});
const placeholders = this.container.querySelectorAll(this.placeholderSelector);
- placeholders.forEach((placeholder) => {
+ placeholders.forEach(placeholder => {
placeholder.classList.toggle('hide', isRevealed);
});
- this.revealButton.textContent = isRevealed ? n__('Hide value', 'Hide values', values.length) : n__('Reveal value', 'Reveal values', values.length);
+ this.revealButton.textContent = isRevealed
+ ? n__('Hide value', 'Hide values', values.length)
+ : n__('Reveal value', 'Reveal values', values.length);
this.revealButton.dataset.secretRevealStatus = isRevealed;
}
}
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
index 6719bfd6d22..eade1283513 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js
@@ -4,6 +4,7 @@ import Mousetrap from 'mousetrap';
import axios from '../../lib/utils/axios_utils';
import { refreshCurrentPage, visitUrl } from '../../lib/utils/url_utility';
import findAndFollowLink from '../../lib/utils/navigation_utility';
+import { parseBoolean } from '~/lib/utils/common_utils';
const defaultStopCallback = Mousetrap.stopCallback;
Mousetrap.stopCallback = (e, element, combo) => {
@@ -61,7 +62,7 @@ export default class Shortcuts {
static onTogglePerfBar(e) {
e.preventDefault();
const performanceBarCookieName = 'perf_bar_enabled';
- if (Cookies.get(performanceBarCookieName) === 'true') {
+ if (parseBoolean(Cookies.get(performanceBarCookieName))) {
Cookies.set(performanceBarCookieName, 'false', { path: '/' });
} else {
Cookies.set(performanceBarCookieName, 'true', { path: '/' });
@@ -88,22 +89,24 @@ export default class Shortcuts {
return null;
}
- return axios.get(gon.shortcuts_path, {
- responseType: 'text',
- }).then(({ data }) => {
- $.globalEval(data);
-
- if (location && location.length > 0) {
- const results = [];
- for (let i = 0, len = location.length; i < len; i += 1) {
- results.push($(location[i]).show());
+ return axios
+ .get(gon.shortcuts_path, {
+ responseType: 'text',
+ })
+ .then(({ data }) => {
+ $.globalEval(data);
+
+ if (location && location.length > 0) {
+ const results = [];
+ for (let i = 0, len = location.length; i < len; i += 1) {
+ results.push($(location[i]).show());
+ }
+ return results;
}
- return results;
- }
- $('.hidden-shortcut').show();
- return $('.js-more-help-button').remove();
- });
+ $('.hidden-shortcut').show();
+ return $('.js-more-help-button').remove();
+ });
}
focusFilter(e) {
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
index 5e48bf5a35c..2918e1486a7 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
@@ -4,6 +4,7 @@ import _ from 'underscore';
import Sidebar from '../../right_sidebar';
import Shortcuts from './shortcuts';
import { CopyAsGFM } from '../markdown/copy_as_gfm';
+import { getSelectedFragment } from '~/lib/utils/common_utils';
export default class ShortcutsIssuable extends Shortcuts {
constructor(isMergeRequest) {
@@ -24,17 +25,43 @@ export default class ShortcutsIssuable extends Shortcuts {
static replyWithSelectedText() {
const $replyField = $('.js-main-target-form .js-vue-comment-form');
- const documentFragment = window.gl.utils.getSelectedFragment();
- if (!$replyField.length) {
+ if (!$replyField.length || $replyField.is(':hidden') /* Other tab selected in MR */) {
return false;
}
+ const documentFragment = getSelectedFragment(document.querySelector('#content-body'));
+
if (!documentFragment) {
$replyField.focus();
return false;
}
+ // Sanity check: Make sure the selected text comes from a discussion : it can either contain a message...
+ let foundMessage = !!documentFragment.querySelector('.md, .wiki');
+
+ // ... Or come from a message
+ if (!foundMessage) {
+ if (documentFragment.originalNodes) {
+ documentFragment.originalNodes.forEach(e => {
+ let node = e;
+ do {
+ // Text nodes don't define the `matches` method
+ if (node.matches && node.matches('.md, .wiki')) {
+ foundMessage = true;
+ }
+ node = node.parentNode;
+ } while (node && !foundMessage);
+ });
+ }
+
+ // If there is no message, just select the reply field
+ if (!foundMessage) {
+ $replyField.focus();
+ return false;
+ }
+ }
+
const el = CopyAsGFM.transformGFMSelection(documentFragment.cloneNode(true));
const selected = CopyAsGFM.nodeToGFM(el);
diff --git a/app/assets/javascripts/behaviors/toggler_behavior.js b/app/assets/javascripts/behaviors/toggler_behavior.js
index 4446be0e52f..ef8b8788abf 100644
--- a/app/assets/javascripts/behaviors/toggler_behavior.js
+++ b/app/assets/javascripts/behaviors/toggler_behavior.js
@@ -18,9 +18,7 @@ $(() => {
.toggleClass('fa-chevron-up', toggleState)
.toggleClass('fa-chevron-down', toggleState !== undefined ? !toggleState : undefined);
- $container
- .find('.js-toggle-content')
- .toggle(toggleState);
+ $container.find('.js-toggle-content').toggle(toggleState);
}
$('body').on('click', '.js-toggle-button', function toggleButton(e) {
diff --git a/app/assets/javascripts/blob/3d_viewer/index.js b/app/assets/javascripts/blob/3d_viewer/index.js
index 1bdf1aeb76c..2d4f45cc365 100644
--- a/app/assets/javascripts/blob/3d_viewer/index.js
+++ b/app/assets/javascripts/blob/3d_viewer/index.js
@@ -18,12 +18,7 @@ export default class Renderer {
this.loader = new STLLoader();
this.fov = 45;
- this.camera = new THREE.PerspectiveCamera(
- this.fov,
- this.width / this.height,
- 1,
- 1000,
- );
+ this.camera = new THREE.PerspectiveCamera(this.fov, this.width / this.height, 1, 1000);
this.scene = new THREE.Scene();
@@ -35,10 +30,7 @@ export default class Renderer {
this.setupLight();
// Set up OrbitControls
- this.controls = new OrbitControls(
- this.camera,
- this.renderer.domElement,
- );
+ this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.controls.minDistance = 5;
this.controls.maxDistance = 30;
this.controls.enableKeys = false;
@@ -51,47 +43,32 @@ export default class Renderer {
antialias: true,
});
- this.renderer.setClearColor(0xFFFFFF);
+ this.renderer.setClearColor(0xffffff);
this.renderer.setPixelRatio(window.devicePixelRatio);
- this.renderer.setSize(
- this.width,
- this.height,
- );
+ this.renderer.setSize(this.width, this.height);
}
setupLight() {
// Point light illuminates the object
- const pointLight = new THREE.PointLight(
- 0xFFFFFF,
- 2,
- 0,
- );
+ const pointLight = new THREE.PointLight(0xffffff, 2, 0);
pointLight.castShadow = true;
this.camera.add(pointLight);
// Ambient light illuminates the scene
- const ambientLight = new THREE.AmbientLight(
- 0xFFFFFF,
- 1,
- );
+ const ambientLight = new THREE.AmbientLight(0xffffff, 1);
this.scene.add(ambientLight);
}
setupGrid() {
- this.grid = new THREE.GridHelper(
- 20,
- 20,
- 0x000000,
- 0x000000,
- );
+ this.grid = new THREE.GridHelper(20, 20, 0x000000, 0x000000);
this.scene.add(this.grid);
}
loadFile() {
- this.loader.load(this.container.dataset.endpoint, (geo) => {
+ this.loader.load(this.container.dataset.endpoint, geo => {
const obj = new MeshObject(geo);
this.objects.push(obj);
@@ -116,30 +93,23 @@ export default class Renderer {
}
render() {
- this.renderer.render(
- this.scene,
- this.camera,
- );
+ this.renderer.render(this.scene, this.camera);
requestAnimationFrame(this.renderWrapper);
}
changeObjectMaterials(type) {
- this.objects.forEach((obj) => {
+ this.objects.forEach(obj => {
obj.changeMaterial(type);
});
}
setDefaultCameraPosition() {
const obj = this.objects[0];
- const radius = (obj.geometry.boundingSphere.radius / 1.5);
- const dist = radius / (Math.sin((this.fov * (Math.PI / 180)) / 2));
-
- this.camera.position.set(
- 0,
- dist + 1,
- dist,
- );
+ const radius = obj.geometry.boundingSphere.radius / 1.5;
+ const dist = radius / Math.sin((this.fov * (Math.PI / 180)) / 2);
+
+ this.camera.position.set(0, dist + 1, dist);
this.camera.lookAt(this.grid);
this.controls.update();
diff --git a/app/assets/javascripts/blob/3d_viewer/mesh_object.js b/app/assets/javascripts/blob/3d_viewer/mesh_object.js
index 96758884abf..cb7fcff8674 100644
--- a/app/assets/javascripts/blob/3d_viewer/mesh_object.js
+++ b/app/assets/javascripts/blob/3d_viewer/mesh_object.js
@@ -1,10 +1,6 @@
-import {
- Matrix4,
- MeshLambertMaterial,
- Mesh,
-} from 'three/build/three.module';
+import { Matrix4, MeshLambertMaterial, Mesh } from 'three/build/three.module';
-const defaultColor = 0xE24329;
+const defaultColor = 0xe24329;
const materials = {
default: new MeshLambertMaterial({
color: defaultColor,
@@ -17,10 +13,7 @@ const materials = {
export default class MeshObject extends Mesh {
constructor(geo) {
- super(
- geo,
- materials.default,
- );
+ super(geo, materials.default);
this.geometry.computeBoundingSphere();
@@ -29,13 +22,7 @@ export default class MeshObject extends Mesh {
if (this.geometry.boundingSphere.radius > 4) {
const scale = 4 / this.geometry.boundingSphere.radius;
- this.geometry.applyMatrix(
- new Matrix4().makeScale(
- scale,
- scale,
- scale,
- ),
- );
+ this.geometry.applyMatrix(new Matrix4().makeScale(scale, scale, scale));
this.geometry.computeBoundingSphere();
this.position.x = -this.geometry.boundingSphere.center.x;
diff --git a/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js b/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js
index 7986287f7e7..75777b910ca 100644
--- a/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js
+++ b/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js
@@ -42,7 +42,7 @@ class BalsamiqViewer {
this.initDatabase(loadEvent.target.response);
const previews = this.getPreviews();
- previews.forEach((preview) => {
+ previews.forEach(preview => {
const renderedPreview = this.renderPreview(preview);
container.appendChild(renderedPreview);
diff --git a/app/assets/javascripts/blob/blob_file_dropzone.js b/app/assets/javascripts/blob/blob_file_dropzone.js
index ff1739b1679..cd3251ad1ca 100644
--- a/app/assets/javascripts/blob/blob_file_dropzone.js
+++ b/app/assets/javascripts/blob/blob_file_dropzone.js
@@ -41,39 +41,45 @@ export default class BlobFileDropzone {
addRemoveLinks: true,
previewsContainer: '.dropzone-previews',
headers: csrf.headers,
- init: function () {
- this.on('addedfile', function () {
+ init: function() {
+ this.on('addedfile', function() {
toggleLoading(submitButton, submitButtonLoadingIcon, false);
dropzoneMessage.addClass(HIDDEN_CLASS);
- $('.dropzone-alerts').html('').hide();
+ $('.dropzone-alerts')
+ .html('')
+ .hide();
});
- this.on('removedfile', function () {
+ this.on('removedfile', function() {
toggleLoading(submitButton, submitButtonLoadingIcon, false);
dropzoneMessage.removeClass(HIDDEN_CLASS);
});
- this.on('success', function (header, response) {
+ this.on('success', function(header, response) {
$('#modal-upload-blob').modal('hide');
visitUrl(response.filePath);
});
- this.on('maxfilesexceeded', function (file) {
+ this.on('maxfilesexceeded', function(file) {
dropzoneMessage.addClass(HIDDEN_CLASS);
this.removeFile(file);
});
- this.on('sending', function (file, xhr, formData) {
+ this.on('sending', function(file, xhr, formData) {
formData.append('branch_name', form.find('.js-branch-name').val());
formData.append('create_merge_request', form.find('.js-create-merge-request').val());
formData.append('commit_message', form.find('.js-commit-message').val());
});
},
// Override behavior of adding error underneath preview
- error: function (file, errorMessage) {
- const stripped = $('<div/>').html(errorMessage).text();
- $('.dropzone-alerts').html(`Error uploading file: "${stripped}"`).show();
+ error: function(file, errorMessage) {
+ const stripped = $('<div/>')
+ .html(errorMessage)
+ .text();
+ $('.dropzone-alerts')
+ .html(`Error uploading file: "${stripped}"`)
+ .show();
this.removeFile(file);
},
});
- submitButton.on('click', (e) => {
+ submitButton.on('click', e => {
e.preventDefault();
e.stopPropagation();
if (dropzone[0].dropzone.getQueuedFiles().length === 0) {
diff --git a/app/assets/javascripts/blob/blob_line_permalink_updater.js b/app/assets/javascripts/blob/blob_line_permalink_updater.js
index d36d9f0de2d..62f0a56ed75 100644
--- a/app/assets/javascripts/blob/blob_line_permalink_updater.js
+++ b/app/assets/javascripts/blob/blob_line_permalink_updater.js
@@ -2,17 +2,19 @@ import { getLocationHash } from '../lib/utils/url_utility';
const lineNumberRe = /^L[0-9]+/;
-const updateLineNumbersOnBlobPermalinks = (linksToUpdate) => {
+const updateLineNumbersOnBlobPermalinks = linksToUpdate => {
const hash = getLocationHash();
if (hash && lineNumberRe.test(hash)) {
const hashUrlString = `#${hash}`;
- [].concat(Array.prototype.slice.call(linksToUpdate)).forEach((permalinkButton) => {
- const baseHref = permalinkButton.getAttribute('data-original-href') || (() => {
- const href = permalinkButton.getAttribute('href');
- permalinkButton.setAttribute('data-original-href', href);
- return href;
- })();
+ [].concat(Array.prototype.slice.call(linksToUpdate)).forEach(permalinkButton => {
+ const baseHref =
+ permalinkButton.getAttribute('data-original-href') ||
+ (() => {
+ const href = permalinkButton.getAttribute('href');
+ permalinkButton.setAttribute('data-original-href', href);
+ return href;
+ })();
permalinkButton.setAttribute('href', `${baseHref}${hashUrlString}`);
});
}
@@ -26,7 +28,7 @@ function BlobLinePermalinkUpdater(blobContentHolder, lineNumberSelector, element
}, 0);
};
- blobContentHolder.addEventListener('click', (e) => {
+ blobContentHolder.addEventListener('click', e => {
if (e.target.matches(lineNumberSelector)) {
updateBlameAndBlobPermalinkCb();
}
diff --git a/app/assets/javascripts/blob/file_template_mediator.js b/app/assets/javascripts/blob/file_template_mediator.js
index ff1cbcad145..106fe2e0cef 100644
--- a/app/assets/javascripts/blob/file_template_mediator.js
+++ b/app/assets/javascripts/blob/file_template_mediator.js
@@ -1,4 +1,4 @@
-/* eslint-disable class-methods-use-this */
+import Api from '~/api';
import $ from 'jquery';
import Flash from '../flash';
@@ -9,9 +9,10 @@ import GitignoreSelector from './template_selectors/gitignore_selector';
import LicenseSelector from './template_selectors/license_selector';
export default class FileTemplateMediator {
- constructor({ editor, currentAction }) {
+ constructor({ editor, currentAction, projectId }) {
this.editor = editor;
this.currentAction = currentAction;
+ this.projectId = projectId;
this.initTemplateSelectors();
this.initTemplateTypeSelector();
@@ -33,15 +34,14 @@ export default class FileTemplateMediator {
initTemplateTypeSelector() {
this.typeSelector = new FileTemplateTypeSelector({
mediator: this,
- dropdownData: this.templateSelectors
- .map((templateSelector) => {
- const cfg = templateSelector.config;
-
- return {
- name: cfg.name,
- key: cfg.key,
- };
- }),
+ dropdownData: this.templateSelectors.map(templateSelector => {
+ const cfg = templateSelector.config;
+
+ return {
+ name: cfg.name,
+ key: cfg.key,
+ };
+ }),
});
}
@@ -89,7 +89,7 @@ export default class FileTemplateMediator {
}
listenForPreviewMode() {
- this.$navLinks.on('click', 'a', (e) => {
+ this.$navLinks.on('click', 'a', e => {
const urlPieces = e.target.href.split('#');
const hash = urlPieces[1];
if (hash === 'preview') {
@@ -105,7 +105,7 @@ export default class FileTemplateMediator {
e.preventDefault();
}
- this.templateSelectors.forEach((selector) => {
+ this.templateSelectors.forEach(selector => {
if (selector.config.key === item.key) {
selector.show();
} else {
@@ -124,10 +124,10 @@ export default class FileTemplateMediator {
selectTemplateFile(selector, query, data) {
selector.renderLoading();
- // in case undo menu is already already there
+ // in case undo menu is already there
this.destroyUndoMenu();
- this.fetchFileTemplate(selector.config.endpoint, query, data)
- .then((file) => {
+ this.fetchFileTemplate(selector.config.type, query, data)
+ .then(file => {
this.showUndoMenu();
this.setEditorContent(file);
this.setFilename(selector.config.name);
@@ -138,7 +138,7 @@ export default class FileTemplateMediator {
displayMatchedTemplateSelector() {
const currentInput = this.getFilename();
- this.templateSelectors.forEach((selector) => {
+ this.templateSelectors.forEach(selector => {
const match = selector.config.pattern.test(currentInput);
if (match) {
@@ -149,15 +149,11 @@ export default class FileTemplateMediator {
});
}
- fetchFileTemplate(apiCall, query, data) {
- return new Promise((resolve) => {
+ fetchFileTemplate(type, query, data = {}) {
+ return new Promise(resolve => {
const resolveFile = file => resolve(file);
- if (!data) {
- apiCall(query, resolveFile);
- } else {
- apiCall(query, data, resolveFile);
- }
+ Api.projectTemplate(this.projectId, type, query, data, resolveFile);
});
}
diff --git a/app/assets/javascripts/blob/file_template_selector.js b/app/assets/javascripts/blob/file_template_selector.js
index 02228434a29..476901aae75 100644
--- a/app/assets/javascripts/blob/file_template_selector.js
+++ b/app/assets/javascripts/blob/file_template_selector.js
@@ -45,15 +45,11 @@ export default class FileTemplateSelector {
}
renderLoading() {
- this.$loadingIcon
- .addClass('fa-spinner fa-spin')
- .removeClass('fa-chevron-down');
+ this.$loadingIcon.addClass('fa-spinner fa-spin').removeClass('fa-chevron-down');
}
renderLoaded() {
- this.$loadingIcon
- .addClass('fa-chevron-down')
- .removeClass('fa-spinner fa-spin');
+ this.$loadingIcon.addClass('fa-chevron-down').removeClass('fa-spinner fa-spin');
}
reportSelection(options) {
diff --git a/app/assets/javascripts/blob/notebook/index.js b/app/assets/javascripts/blob/notebook/index.js
index 6f1350e80fc..071022a9a75 100644
--- a/app/assets/javascripts/blob/notebook/index.js
+++ b/app/assets/javascripts/blob/notebook/index.js
@@ -40,13 +40,14 @@ export default () => {
},
methods: {
loadFile() {
- axios.get(el.dataset.endpoint)
+ axios
+ .get(el.dataset.endpoint)
.then(res => res.data)
- .then((data) => {
+ .then(data => {
this.json = data;
this.loading = false;
})
- .catch((e) => {
+ .catch(e => {
if (e.status !== 200) {
this.loadError = true;
}
diff --git a/app/assets/javascripts/blob/sketch/index.js b/app/assets/javascripts/blob/sketch/index.js
index 13318c58006..57c1baa9886 100644
--- a/app/assets/javascripts/blob/sketch/index.js
+++ b/app/assets/javascripts/blob/sketch/index.js
@@ -13,7 +13,7 @@ export default class SketchLoader {
return this.getZipFile()
.then(data => JSZip.loadAsync(data))
.then(asyncResult => asyncResult.files['previews/preview.png'].async('uint8array'))
- .then((content) => {
+ .then(content => {
const url = window.URL || window.webkitURL;
const blob = new Blob([new Uint8Array(content)], {
type: 'image/png',
diff --git a/app/assets/javascripts/blob/stl_viewer.js b/app/assets/javascripts/blob/stl_viewer.js
index 339906adc34..f129b6e631e 100644
--- a/app/assets/javascripts/blob/stl_viewer.js
+++ b/app/assets/javascripts/blob/stl_viewer.js
@@ -3,8 +3,8 @@ import Renderer from './3d_viewer';
export default () => {
const viewer = new Renderer(document.getElementById('js-stl-viewer'));
- [].slice.call(document.querySelectorAll('.js-material-changer')).forEach((el) => {
- el.addEventListener('click', (e) => {
+ [].slice.call(document.querySelectorAll('.js-material-changer')).forEach(el => {
+ el.addEventListener('click', e => {
const { target } = e;
e.preventDefault();
diff --git a/app/assets/javascripts/blob/template_selector.js b/app/assets/javascripts/blob/template_selector.js
index 9dfdb06007d..37e348d93d3 100644
--- a/app/assets/javascripts/blob/template_selector.js
+++ b/app/assets/javascripts/blob/template_selector.js
@@ -66,9 +66,6 @@ export default class TemplateSelector {
// be added by all subclasses.
}
- // To be implemented on the extending class
- // e.g. Api.gitlabCiYml(query.name, file => this.setEditorContent(file));
-
setEditorContent(file, { skipFocus } = {}) {
if (!file) return;
@@ -84,14 +81,10 @@ export default class TemplateSelector {
}
startLoadingSpinner() {
- this.$dropdownIcon
- .addClass('fa-spinner fa-spin')
- .removeClass('fa-chevron-down');
+ this.$dropdownIcon.addClass('fa-spinner fa-spin').removeClass('fa-chevron-down');
}
stopLoadingSpinner() {
- this.$dropdownIcon
- .addClass('fa-chevron-down')
- .removeClass('fa-spinner fa-spin');
+ this.$dropdownIcon.addClass('fa-chevron-down').removeClass('fa-spinner fa-spin');
}
}
diff --git a/app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js b/app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js
index 9c41e429c8d..43f7aead8b9 100644
--- a/app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js
@@ -1,5 +1,3 @@
-import Api from '../../api';
-
import FileTemplateSelector from '../file_template_selector';
export default class BlobCiYamlSelector extends FileTemplateSelector {
@@ -9,7 +7,7 @@ export default class BlobCiYamlSelector extends FileTemplateSelector {
key: 'gitlab-ci-yaml',
name: '.gitlab-ci.yml',
pattern: /(.gitlab-ci.yml)/,
- endpoint: Api.gitlabCiYml,
+ type: 'gitlab_ci_ymls',
dropdown: '.js-gitlab-ci-yml-selector',
wrapper: '.js-gitlab-ci-yml-selector-wrap',
};
diff --git a/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js b/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js
index 45fb614fe00..4718b642617 100644
--- a/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/dockerfile_selector.js
@@ -1,5 +1,3 @@
-import Api from '../../api';
-
import FileTemplateSelector from '../file_template_selector';
export default class DockerfileSelector extends FileTemplateSelector {
@@ -9,7 +7,7 @@ export default class DockerfileSelector extends FileTemplateSelector {
key: 'dockerfile',
name: 'Dockerfile',
pattern: /(Dockerfile)/,
- endpoint: Api.dockerfileYml,
+ type: 'dockerfiles',
dropdown: '.js-dockerfile-selector',
wrapper: '.js-dockerfile-selector-wrap',
};
diff --git a/app/assets/javascripts/blob/template_selectors/gitignore_selector.js b/app/assets/javascripts/blob/template_selectors/gitignore_selector.js
index a894953cc86..a8067ec5c84 100644
--- a/app/assets/javascripts/blob/template_selectors/gitignore_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/gitignore_selector.js
@@ -1,5 +1,3 @@
-import Api from '../../api';
-
import FileTemplateSelector from '../file_template_selector';
export default class BlobGitignoreSelector extends FileTemplateSelector {
@@ -9,7 +7,7 @@ export default class BlobGitignoreSelector extends FileTemplateSelector {
key: 'gitignore',
name: '.gitignore',
pattern: /(.gitignore)/,
- endpoint: Api.gitignoreText,
+ type: 'gitignores',
dropdown: '.js-gitignore-selector',
wrapper: '.js-gitignore-selector-wrap',
};
diff --git a/app/assets/javascripts/blob/template_selectors/license_selector.js b/app/assets/javascripts/blob/template_selectors/license_selector.js
index b7c4da0f62e..d01ab9257d6 100644
--- a/app/assets/javascripts/blob/template_selectors/license_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/license_selector.js
@@ -1,5 +1,3 @@
-import Api from '../../api';
-
import FileTemplateSelector from '../file_template_selector';
export default class BlobLicenseSelector extends FileTemplateSelector {
@@ -9,7 +7,7 @@ export default class BlobLicenseSelector extends FileTemplateSelector {
key: 'license',
name: 'LICENSE',
pattern: /^(.+\/)?(licen[sc]e|copying)($|\.)/i,
- endpoint: Api.licenseText,
+ type: 'licenses',
dropdown: '.js-license-selector',
wrapper: '.js-license-selector-wrap',
};
@@ -24,7 +22,7 @@ export default class BlobLicenseSelector extends FileTemplateSelector {
search: {
fields: ['name'],
},
- clicked: (options) => {
+ clicked: options => {
const { e } = options;
const el = options.$el;
const query = options.selectedObj;
diff --git a/app/assets/javascripts/blob/template_selectors/type_selector.js b/app/assets/javascripts/blob/template_selectors/type_selector.js
index a09381014a7..db3c144cbe3 100644
--- a/app/assets/javascripts/blob/template_selectors/type_selector.js
+++ b/app/assets/javascripts/blob/template_selectors/type_selector.js
@@ -21,5 +21,4 @@ export default class FileTemplateTypeSelector extends FileTemplateSelector {
text: item => item.name,
});
}
-
}
diff --git a/app/assets/javascripts/blob/viewer/index.js b/app/assets/javascripts/blob/viewer/index.js
index 5485248cfaf..d0359fc5fe9 100644
--- a/app/assets/javascripts/blob/viewer/index.js
+++ b/app/assets/javascripts/blob/viewer/index.js
@@ -22,12 +22,13 @@ export default class BlobViewer {
const viewer = document.querySelector('.blob-viewer[data-type="rich"]');
if (!viewer || !viewer.dataset.richType) return;
- const initViewer = promise => promise
- .then(module => module.default(viewer))
- .catch((error) => {
- Flash('Error loading file viewer.');
- throw error;
- });
+ const initViewer = promise =>
+ promise
+ .then(module => module.default(viewer))
+ .catch(error => {
+ Flash('Error loading file viewer.');
+ throw error;
+ });
switch (viewer.dataset.richType) {
case 'balsamiq':
@@ -79,10 +80,9 @@ export default class BlobViewer {
initBindings() {
if (this.switcherBtns.length) {
- Array.from(this.switcherBtns)
- .forEach((el) => {
- el.addEventListener('click', this.switchViewHandler.bind(this));
- });
+ Array.from(this.switcherBtns).forEach(el => {
+ el.addEventListener('click', this.switchViewHandler.bind(this));
+ });
}
if (this.copySourceBtn) {
@@ -109,7 +109,10 @@ export default class BlobViewer {
this.copySourceBtn.setAttribute('title', 'Copy source to clipboard');
this.copySourceBtn.classList.remove('disabled');
} else if (this.activeViewer === this.simpleViewer) {
- this.copySourceBtn.setAttribute('title', 'Wait for the source to load to copy it to the clipboard');
+ this.copySourceBtn.setAttribute(
+ 'title',
+ 'Wait for the source to load to copy it to the clipboard',
+ );
this.copySourceBtn.classList.add('disabled');
} else {
this.copySourceBtn.setAttribute('title', 'Switch to the source to copy it to the clipboard');
@@ -147,15 +150,15 @@ export default class BlobViewer {
this.toggleCopyButtonState();
BlobViewer.loadViewer(newViewer)
- .then((viewer) => {
- $(viewer).renderGFM();
+ .then(viewer => {
+ $(viewer).renderGFM();
- this.$fileHolder.trigger('highlight:line');
- handleLocationHash();
+ this.$fileHolder.trigger('highlight:line');
+ handleLocationHash();
- this.toggleCopyButtonState();
- })
- .catch(() => new Flash('Error loading viewer'));
+ this.toggleCopyButtonState();
+ })
+ .catch(() => new Flash('Error loading viewer'));
}
static loadViewer(viewerParam) {
@@ -168,12 +171,11 @@ export default class BlobViewer {
viewer.setAttribute('data-loading', 'true');
- return axios.get(url)
- .then(({ data }) => {
- viewer.innerHTML = data.html;
- viewer.setAttribute('data-loaded', 'true');
+ return axios.get(url).then(({ data }) => {
+ viewer.innerHTML = data.html;
+ viewer.setAttribute('data-loaded', 'true');
- return viewer;
- });
+ return viewer;
+ });
}
}
diff --git a/app/assets/javascripts/blob_edit/blob_bundle.js b/app/assets/javascripts/blob_edit/blob_bundle.js
index a603d89b84a..9f547471170 100644
--- a/app/assets/javascripts/blob_edit/blob_bundle.js
+++ b/app/assets/javascripts/blob_edit/blob_bundle.js
@@ -13,11 +13,20 @@ export default () => {
if (editBlobForm.length) {
const urlRoot = editBlobForm.data('relativeUrlRoot');
const assetsPath = editBlobForm.data('assetsPrefix');
- const blobLanguage = editBlobForm.data('blobLanguage');
+ const filePath = editBlobForm.data('blobFilename');
const currentAction = $('.js-file-title').data('currentAction');
+ const projectId = editBlobForm.data('project-id');
+ const commitButton = $('.js-commit-button');
- new EditBlob(`${urlRoot}${assetsPath}`, blobLanguage, currentAction);
+ commitButton.on('click', () => {
+ window.onbeforeunload = null;
+ });
+
+ new EditBlob(`${urlRoot}${assetsPath}`, filePath, currentAction, projectId);
new NewCommitForm(editBlobForm);
+
+ // returning here blocks page navigation
+ window.onbeforeunload = () => '';
}
if (uploadBlobForm.length) {
diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js
index 82a3d494b67..6e19548eed2 100644
--- a/app/assets/javascripts/blob_edit/edit_blob.js
+++ b/app/assets/javascripts/blob_edit/edit_blob.js
@@ -5,18 +5,20 @@ import axios from '~/lib/utils/axios_utils';
import createFlash from '~/flash';
import { __ } from '~/locale';
import TemplateSelectorMediator from '../blob/file_template_mediator';
+import getModeByFileExtension from '~/lib/utils/ace_utils';
export default class EditBlob {
- constructor(assetsPath, aceMode, currentAction) {
+ constructor(assetsPath, aceMode, currentAction, projectId) {
this.configureAceEditor(aceMode, assetsPath);
this.initModePanesAndLinks();
this.initSoftWrap();
- this.initFileSelectors(currentAction);
+ this.initFileSelectors(currentAction, projectId);
}
- configureAceEditor(aceMode, assetsPath) {
+ configureAceEditor(filePath, assetsPath) {
ace.config.set('modePath', `${assetsPath}/ace`);
ace.config.loadModule('ace/ext/searchbox');
+ ace.config.loadModule('ace/ext/modelist');
this.editor = ace.edit('editor');
@@ -25,15 +27,16 @@ export default class EditBlob {
this.editor.focus();
- if (aceMode) {
- this.editor.getSession().setMode(`ace/mode/${aceMode}`);
+ if (filePath) {
+ this.editor.getSession().setMode(getModeByFileExtension(filePath));
}
}
- initFileSelectors(currentAction) {
+ initFileSelectors(currentAction, projectId) {
this.fileTemplateMediator = new TemplateSelectorMediator({
currentAction,
editor: this.editor,
+ projectId,
});
}
@@ -60,14 +63,15 @@ export default class EditBlob {
if (paneId === '#preview') {
this.$toggleButton.hide();
- axios.post(currentLink.data('previewUrl'), {
- content: this.editor.getValue(),
- })
- .then(({ data }) => {
- currentPane.empty().append(data);
- currentPane.renderGFM();
- })
- .catch(() => createFlash(__('An error occurred previewing the blob')));
+ axios
+ .post(currentLink.data('previewUrl'), {
+ content: this.editor.getValue(),
+ })
+ .then(({ data }) => {
+ currentPane.empty().append(data);
+ currentPane.renderGFM();
+ })
+ .catch(() => createFlash(__('An error occurred previewing the blob')));
}
this.$toggleButton.show();
diff --git a/app/assets/javascripts/boards/components/board.js b/app/assets/javascripts/boards/components/board.js
index 9ad451fa375..fb6e5291a61 100644
--- a/app/assets/javascripts/boards/components/board.js
+++ b/app/assets/javascripts/boards/components/board.js
@@ -1,25 +1,20 @@
-/* eslint-disable comma-dangle */
-
import Sortable from 'sortablejs';
import Vue from 'vue';
import { n__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import Tooltip from '~/vue_shared/directives/tooltip';
import AccessorUtilities from '../../lib/utils/accessor';
-import boardList from './board_list.vue';
import BoardBlankState from './board_blank_state.vue';
-import './board_delete';
-
-const Store = gl.issueBoards.BoardsStore;
-
-window.gl = window.gl || {};
-window.gl.issueBoards = window.gl.issueBoards || {};
+import BoardDelete from './board_delete';
+import BoardList from './board_list.vue';
+import boardsStore from '../stores/boards_store';
+import { getBoardSortableDefaultOptions, sortableEnd } from '../mixins/sortable_default_options';
-gl.issueBoards.Board = Vue.extend({
+export default Vue.extend({
components: {
- boardList,
- 'board-delete': gl.issueBoards.BoardDelete,
BoardBlankState,
+ BoardDelete,
+ BoardList,
Icon,
},
directives: {
@@ -47,10 +42,10 @@ gl.issueBoards.Board = Vue.extend({
required: true,
},
},
- data () {
+ data() {
return {
- detailIssue: Store.detail,
- filter: Store.filter,
+ detailIssue: boardsStore.detail,
+ filter: boardsStore.filter,
};
},
computed: {
@@ -58,44 +53,47 @@ gl.issueBoards.Board = Vue.extend({
const { issuesSize } = this.list;
return `${n__('%d issue', '%d issues', issuesSize)}`;
},
+ isNewIssueShown() {
+ return this.list.type === 'backlog' || (!this.disabled && this.list.type !== 'closed');
+ },
},
watch: {
filter: {
handler() {
this.list.page = 1;
- this.list.getIssues(true)
- .catch(() => {
- // TODO: handle request error
- });
+ this.list.getIssues(true).catch(() => {
+ // TODO: handle request error
+ });
},
deep: true,
- }
+ },
},
- mounted () {
- this.sortableOptions = gl.issueBoards.getBoardSortableDefaultOptions({
+ mounted() {
+ this.sortableOptions = getBoardSortableDefaultOptions({
disabled: this.disabled,
group: 'boards',
draggable: '.is-draggable',
handle: '.js-board-handle',
- onEnd: (e) => {
- gl.issueBoards.onEnd();
+ onEnd: e => {
+ sortableEnd();
if (e.newIndex !== undefined && e.oldIndex !== e.newIndex) {
const order = this.sortable.toArray();
- const list = Store.findList('id', parseInt(e.item.dataset.id, 10));
+ const list = boardsStore.findList('id', parseInt(e.item.dataset.id, 10));
this.$nextTick(() => {
- Store.moveList(list, order);
+ boardsStore.moveList(list, order);
});
}
- }
+ },
});
this.sortable = Sortable.create(this.$el.parentNode, this.sortableOptions);
},
created() {
if (this.list.isExpandable && AccessorUtilities.isLocalStorageAccessSafe()) {
- const isCollapsed = localStorage.getItem(`boards.${this.boardId}.${this.list.type}.expanded`) === 'false';
+ const isCollapsed =
+ localStorage.getItem(`boards.${this.boardId}.${this.list.type}.expanded`) === 'false';
this.list.isExpanded = !isCollapsed;
}
@@ -109,7 +107,10 @@ gl.issueBoards.Board = Vue.extend({
this.list.isExpanded = !this.list.isExpanded;
if (AccessorUtilities.isLocalStorageAccessSafe()) {
- localStorage.setItem(`boards.${this.boardId}.${this.list.type}.expanded`, this.list.isExpanded);
+ localStorage.setItem(
+ `boards.${this.boardId}.${this.list.type}.expanded`,
+ this.list.isExpanded,
+ );
}
}
},
diff --git a/app/assets/javascripts/boards/components/board_blank_state.vue b/app/assets/javascripts/boards/components/board_blank_state.vue
index cde22725a89..667eea17d44 100644
--- a/app/assets/javascripts/boards/components/board_blank_state.vue
+++ b/app/assets/javascripts/boards/components/board_blank_state.vue
@@ -2,8 +2,7 @@
/* global ListLabel */
import _ from 'underscore';
import Cookies from 'js-cookie';
-
-const Store = gl.issueBoards.BoardsStore;
+import boardsStore from '../stores/boards_store';
export default {
data() {
@@ -19,7 +18,7 @@ export default {
this.clearBlankState();
this.predefinedLabels.forEach((label, i) => {
- Store.addList({
+ boardsStore.addList({
title: label.title,
position: i,
list_type: 'label',
@@ -30,68 +29,57 @@ export default {
});
});
- Store.state.lists = _.sortBy(Store.state.lists, 'position');
+ boardsStore.state.lists = _.sortBy(boardsStore.state.lists, 'position');
// Save the labels
- gl.boardService.generateDefaultLists()
+ gl.boardService
+ .generateDefaultLists()
.then(res => res.data)
- .then((data) => {
- data.forEach((listObj) => {
- const list = Store.findList('title', listObj.title);
+ .then(data => {
+ data.forEach(listObj => {
+ const list = boardsStore.findList('title', listObj.title);
list.id = listObj.id;
list.label.id = listObj.label.id;
- list.getIssues()
- .catch(() => {
- // TODO: handle request error
- });
+ list.getIssues().catch(() => {
+ // TODO: handle request error
+ });
});
})
.catch(() => {
- Store.removeList(undefined, 'label');
+ boardsStore.removeList(undefined, 'label');
Cookies.remove('issue_board_welcome_hidden', {
path: '',
});
- Store.addBlankState();
+ boardsStore.addBlankState();
});
},
- clearBlankState: Store.removeBlankState.bind(Store),
+ clearBlankState: boardsStore.removeBlankState.bind(boardsStore),
},
};
-
</script>
<template>
<div class="board-blank-state">
- <p>
- Add the following default lists to your Issue Board with one click:
- </p>
+ <p>Add the following default lists to your Issue Board with one click:</p>
<ul class="board-blank-state-list">
- <li
- v-for="(label, index) in predefinedLabels"
- :key="index"
- >
- <span
- :style="{ backgroundColor: label.color }"
- class="label-color">
- </span>
+ <li v-for="(label, index) in predefinedLabels" :key="index">
+ <span :style="{ backgroundColor: label.color }" class="label-color"> </span>
{{ label.title }}
</li>
</ul>
<p>
- Starting out with the default set of lists will get you
- right on the way to making the most of your board.
+ Starting out with the default set of lists will get you right on the way to making the most of
+ your board.
</p>
<button
class="btn btn-success btn-inverted btn-block"
type="button"
- @click.stop="addDefaultLists">
+ @click.stop="addDefaultLists"
+ >
Add default lists
</button>
- <button
- class="btn btn-default btn-block"
- type="button"
- @click.stop="clearBlankState">
+ <button class="btn btn-default btn-block" type="button" @click.stop="clearBlankState">
Nevermind, I'll use my own
</button>
</div>
diff --git a/app/assets/javascripts/boards/components/board_card.vue b/app/assets/javascripts/boards/components/board_card.vue
index 0398102ad02..30fbdb9e97f 100644
--- a/app/assets/javascripts/boards/components/board_card.vue
+++ b/app/assets/javascripts/boards/components/board_card.vue
@@ -1,78 +1,77 @@
<script>
- /* eslint-disable vue/require-default-prop */
- import IssueCardInner from './issue_card_inner.vue';
- import eventHub from '../eventhub';
+/* eslint-disable vue/require-default-prop */
+import IssueCardInner from './issue_card_inner.vue';
+import eventHub from '../eventhub';
+import boardsStore from '../stores/boards_store';
- const Store = gl.issueBoards.BoardsStore;
-
- export default {
- name: 'BoardsIssueCard',
- components: {
- IssueCardInner,
+export default {
+ name: 'BoardsIssueCard',
+ components: {
+ IssueCardInner,
+ },
+ props: {
+ list: {
+ type: Object,
+ default: () => ({}),
},
- props: {
- list: {
- type: Object,
- default: () => ({}),
- },
- issue: {
- type: Object,
- default: () => ({}),
- },
- issueLinkBase: {
- type: String,
- default: '',
- },
- disabled: {
- type: Boolean,
- default: false,
- },
- index: {
- type: Number,
- default: 0,
- },
- rootPath: {
- type: String,
- default: '',
- },
- groupId: {
- type: Number,
- },
+ issue: {
+ type: Object,
+ default: () => ({}),
},
- data() {
- return {
- showDetail: false,
- detailIssue: Store.detail,
- };
+ issueLinkBase: {
+ type: String,
+ default: '',
},
- computed: {
- issueDetailVisible() {
- return this.detailIssue.issue && this.detailIssue.issue.id === this.issue.id;
- },
+ disabled: {
+ type: Boolean,
+ default: false,
},
- methods: {
- mouseDown() {
- this.showDetail = true;
- },
- mouseMove() {
- this.showDetail = false;
- },
- showIssue(e) {
- if (e.target.classList.contains('js-no-trigger')) return;
+ index: {
+ type: Number,
+ default: 0,
+ },
+ rootPath: {
+ type: String,
+ default: '',
+ },
+ groupId: {
+ type: Number,
+ },
+ },
+ data() {
+ return {
+ showDetail: false,
+ detailIssue: boardsStore.detail,
+ };
+ },
+ computed: {
+ issueDetailVisible() {
+ return this.detailIssue.issue && this.detailIssue.issue.id === this.issue.id;
+ },
+ },
+ methods: {
+ mouseDown() {
+ this.showDetail = true;
+ },
+ mouseMove() {
+ this.showDetail = false;
+ },
+ showIssue(e) {
+ if (e.target.classList.contains('js-no-trigger')) return;
- if (this.showDetail) {
- this.showDetail = false;
+ if (this.showDetail) {
+ this.showDetail = false;
- if (Store.detail.issue && Store.detail.issue.id === this.issue.id) {
- eventHub.$emit('clearDetailIssue');
- } else {
- eventHub.$emit('newDetailIssue', this.issue);
- Store.detail.list = this.list;
- }
+ if (boardsStore.detail.issue && boardsStore.detail.issue.id === this.issue.id) {
+ eventHub.$emit('clearDetailIssue');
+ } else {
+ eventHub.$emit('newDetailIssue', this.issue);
+ boardsStore.detail.list = this.list;
}
- },
+ }
},
- };
+ },
+};
</script>
<template>
@@ -80,14 +79,15 @@
:class="{
'user-can-drag': !disabled && issue.id,
'is-disabled': disabled || !issue.id,
- 'is-active': issueDetailVisible
+ 'is-active': issueDetailVisible,
}"
:index="index"
:data-issue-id="issue.id"
class="board-card"
@mousedown="mouseDown"
@mousemove="mouseMove"
- @mouseup="showIssue($event)">
+ @mouseup="showIssue($event);"
+ >
<issue-card-inner
:list="list"
:issue="issue"
diff --git a/app/assets/javascripts/boards/components/board_delete.js b/app/assets/javascripts/boards/components/board_delete.js
index c5945e8098d..a5f9d65e4d5 100644
--- a/app/assets/javascripts/boards/components/board_delete.js
+++ b/app/assets/javascripts/boards/components/board_delete.js
@@ -1,12 +1,7 @@
-/* eslint-disable comma-dangle, no-alert */
-
import $ from 'jquery';
import Vue from 'vue';
-window.gl = window.gl || {};
-window.gl.issueBoards = window.gl.issueBoards || {};
-
-gl.issueBoards.BoardDelete = Vue.extend({
+export default Vue.extend({
props: {
list: {
type: Object,
@@ -14,12 +9,13 @@ gl.issueBoards.BoardDelete = Vue.extend({
},
},
methods: {
- deleteBoard () {
+ deleteBoard() {
$(this.$el).tooltip('hide');
+ // eslint-disable-next-line no-alert
if (window.confirm('Are you sure you want to delete this list?')) {
this.list.destroy();
}
- }
- }
+ },
+ },
});
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index 606c9e81db4..f3f341ece5c 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -1,16 +1,18 @@
<script>
import Sortable from 'sortablejs';
+import { GlLoadingIcon } from '@gitlab/ui';
import boardNewIssue from './board_new_issue.vue';
import boardCard from './board_card.vue';
import eventHub from '../eventhub';
-
-const Store = gl.issueBoards.BoardsStore;
+import boardsStore from '../stores/boards_store';
+import { getBoardSortableDefaultOptions, sortableStart } from '../mixins/sortable_default_options';
export default {
name: 'BoardList',
components: {
boardCard,
boardNewIssue,
+ GlLoadingIcon,
},
props: {
groupId: {
@@ -46,7 +48,7 @@ export default {
data() {
return {
scrollOffset: 250,
- filters: Store.state.filters,
+ filters: boardsStore.state.filters,
showCount: false,
showIssueForm: false,
};
@@ -61,13 +63,14 @@ export default {
},
issues() {
this.$nextTick(() => {
- if (this.scrollHeight() <= this.listHeight() &&
- this.list.issuesSize > this.list.issues.length) {
+ if (
+ this.scrollHeight() <= this.listHeight() &&
+ this.list.issuesSize > this.list.issues.length
+ ) {
this.list.page += 1;
- this.list.getIssues(false)
- .catch(() => {
- // TODO: handle request error
- });
+ this.list.getIssues(false).catch(() => {
+ // TODO: handle request error
+ });
}
if (this.scrollHeight() > Math.ceil(this.listHeight())) {
@@ -83,7 +86,7 @@ export default {
eventHub.$on(`scroll-board-list-${this.list.id}`, this.scrollToTop);
},
mounted() {
- const options = gl.issueBoards.getBoardSortableDefaultOptions({
+ const options = getBoardSortableDefaultOptions({
scroll: true,
disabled: this.disabled,
filter: '.board-list-count, .is-disabled',
@@ -108,7 +111,8 @@ export default {
// So from there, we can get reference to actual container
// and thus the container type to enable Copy or Move
if (e.target) {
- const containerEl = e.target.closest('.js-board-list') || e.target.querySelector('.js-board-list');
+ const containerEl =
+ e.target.closest('.js-board-list') || e.target.querySelector('.js-board-list');
const toBoardType = containerEl.dataset.boardType;
const cloneActions = {
label: ['milestone', 'assignee'],
@@ -120,8 +124,9 @@ export default {
const fromBoardType = this.list.type;
// For each list we check if the destination list is
// a the list were we should clone the issue
- const shouldClone = Object.entries(cloneActions).some(entry => (
- fromBoardType === entry[0] && entry[1].includes(toBoardType)));
+ const shouldClone = Object.entries(cloneActions).some(
+ entry => fromBoardType === entry[0] && entry[1].includes(toBoardType),
+ );
if (shouldClone) {
return 'clone';
@@ -133,28 +138,36 @@ export default {
},
revertClone: true,
},
- onStart: (e) => {
+ onStart: e => {
const card = this.$refs.issue[e.oldIndex];
card.showDetail = false;
- Store.moving.list = card.list;
- Store.moving.issue = Store.moving.list.findIssue(+e.item.dataset.issueId);
+ boardsStore.moving.list = card.list;
+ boardsStore.moving.issue = boardsStore.moving.list.findIssue(+e.item.dataset.issueId);
- gl.issueBoards.onStart();
+ sortableStart();
},
- onAdd: (e) => {
- gl.issueBoards.BoardsStore
- .moveIssueToList(Store.moving.list, this.list, Store.moving.issue, e.newIndex);
+ onAdd: e => {
+ boardsStore.moveIssueToList(
+ boardsStore.moving.list,
+ this.list,
+ boardsStore.moving.issue,
+ e.newIndex,
+ );
this.$nextTick(() => {
e.item.remove();
});
},
- onUpdate: (e) => {
- const sortedArray = this.sortable.toArray()
- .filter(id => id !== '-1');
- gl.issueBoards.BoardsStore
- .moveIssueInList(this.list, Store.moving.issue, e.oldIndex, e.newIndex, sortedArray);
+ onUpdate: e => {
+ const sortedArray = this.sortable.toArray().filter(id => id !== '-1');
+ boardsStore.moveIssueInList(
+ this.list,
+ boardsStore.moving.issue,
+ e.oldIndex,
+ e.newIndex,
+ sortedArray,
+ );
},
onMove(e) {
return !e.related.classList.contains('board-list-count');
@@ -192,16 +205,14 @@ export default {
if (getIssues) {
this.list.loadingMore = true;
- getIssues
- .then(loadingDone)
- .catch(loadingDone);
+ getIssues.then(loadingDone).catch(loadingDone);
}
},
toggleForm() {
this.showIssueForm = !this.showIssueForm;
},
onScroll() {
- if (!this.list.loadingMore && (this.scrollTop() > this.scrollHeight() - this.scrollOffset)) {
+ if (!this.list.loadingMore && this.scrollTop() > this.scrollHeight() - this.scrollOffset) {
this.loadNextPage();
}
},
@@ -211,26 +222,26 @@ export default {
<template>
<div class="board-list-component">
- <div
- v-if="loading"
- class="board-list-loading text-center"
- aria-label="Loading issues">
+ <div v-if="loading" class="board-list-loading text-center" aria-label="Loading issues">
<gl-loading-icon />
</div>
<board-new-issue
v-if="list.type !== 'closed' && showIssueForm"
:group-id="groupId"
- :list="list"/>
+ :list="list"
+ />
<ul
v-show="!loading"
ref="list"
:data-board="list.id"
:data-board-type="list.type"
:class="{ 'is-smaller': showIssueForm }"
- class="board-list js-board-list">
+ class="board-list js-board-list"
+ >
<board-card
v-for="(issue, index) in issues"
ref="issue"
+ :key="issue.id"
:index="index"
:list="list"
:issue="issue"
@@ -238,25 +249,11 @@ export default {
:group-id="groupId"
:root-path="rootPath"
:disabled="disabled"
- :key="issue.id" />
- <li
- v-if="showCount"
- class="board-list-count text-center"
- data-issue-id="-1">
- <gl-loading-icon
- v-show="list.loadingMore"
- label="Loading more issues"
- />
- <span
- v-if="list.issues.length === list.issuesSize"
- >
- Showing all issues
- </span>
- <span
- v-else
- >
- Showing {{ list.issues.length }} of {{ list.issuesSize }} issues
- </span>
+ />
+ <li v-if="showCount" class="board-list-count text-center" data-issue-id="-1">
+ <gl-loading-icon v-show="list.loadingMore" label="Loading more issues" />
+ <span v-if="list.issues.length === list.issuesSize"> Showing all issues </span>
+ <span v-else> Showing {{ list.issues.length }} of {{ list.issuesSize }} issues </span>
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue
index 1e3cd43d1f0..93bcb4e129e 100644
--- a/app/assets/javascripts/boards/components/board_new_issue.vue
+++ b/app/assets/javascripts/boards/components/board_new_issue.vue
@@ -1,15 +1,16 @@
<script>
import $ from 'jquery';
+import { GlButton } from '@gitlab/ui';
import eventHub from '../eventhub';
import ProjectSelect from './project_select.vue';
import ListIssue from '../models/issue';
-
-const Store = gl.issueBoards.BoardsStore;
+import boardsStore from '../stores/boards_store';
export default {
name: 'BoardNewIssue',
components: {
ProjectSelect,
+ GlButton,
},
props: {
groupId: {
@@ -61,13 +62,14 @@ export default {
eventHub.$emit(`scroll-board-list-${this.list.id}`);
this.cancel();
- return this.list.newIssue(issue)
+ return this.list
+ .newIssue(issue)
.then(() => {
// Need this because our jQuery very kindly disables buttons on ALL form submissions
$(this.$refs.submitButton).enable();
- Store.detail.issue = issue;
- Store.detail.list = this.list;
+ boardsStore.detail.issue = issue;
+ boardsStore.detail.list = this.list;
})
.catch(() => {
// Need this because our jQuery very kindly disables buttons on ALL form submissions
@@ -94,50 +96,34 @@ export default {
<template>
<div class="board-new-issue-form">
<div class="board-card">
- <form @submit="submit($event)">
- <div
- v-if="error"
- class="flash-container"
- >
- <div class="flash-alert">
- An error occurred. Please try again.
- </div>
+ <form @submit="submit($event);">
+ <div v-if="error" class="flash-container">
+ <div class="flash-alert">An error occurred. Please try again.</div>
</div>
- <label
- :for="list.id + '-title'"
- class="label-bold"
- >
- Title
- </label>
+ <label :for="list.id + '-title'" class="label-bold"> Title </label>
<input
+ :id="list.id + '-title'"
ref="input"
v-model="title"
- :id="list.id + '-title'"
class="form-control"
type="text"
name="issue_title"
autocomplete="off"
/>
- <project-select
- v-if="groupId"
- :group-id="groupId"
- />
+ <project-select v-if="groupId" :group-id="groupId" />
<div class="clearfix prepend-top-10">
- <button
+ <gl-button
ref="submit-button"
:disabled="disabled"
- class="btn btn-success float-left"
+ class="float-left"
+ variant="success"
type="submit"
>
Submit issue
- </button>
- <button
- class="btn btn-default float-right"
- type="button"
- @click="cancel"
- >
+ </gl-button>
+ <gl-button class="float-right" type="button" variant="default" @click="cancel">
Cancel
- </button>
+ </gl-button>
</div>
</form>
</div>
diff --git a/app/assets/javascripts/boards/components/board_sidebar.js b/app/assets/javascripts/boards/components/board_sidebar.js
index 109e60cbde2..e637e1f1223 100644
--- a/app/assets/javascripts/boards/components/board_sidebar.js
+++ b/app/assets/javascripts/boards/components/board_sidebar.js
@@ -1,4 +1,4 @@
-/* eslint-disable comma-dangle, no-new */
+/* eslint-disable no-new */
import $ from 'jquery';
import Vue from 'vue';
@@ -14,13 +14,9 @@ import IssuableContext from '../../issuable_context';
import LabelsSelect from '../../labels_select';
import Subscriptions from '../../sidebar/components/subscriptions/subscriptions.vue';
import MilestoneSelect from '../../milestone_select';
+import boardsStore from '../stores/boards_store';
-const Store = gl.issueBoards.BoardsStore;
-
-window.gl = window.gl || {};
-window.gl.issueBoards = window.gl.issueBoards || {};
-
-gl.issueBoards.BoardSidebar = Vue.extend({
+export default Vue.extend({
components: {
AssigneeTitle,
Assignees,
@@ -35,14 +31,14 @@ gl.issueBoards.BoardSidebar = Vue.extend({
},
data() {
return {
- detail: Store.detail,
+ detail: boardsStore.detail,
issue: {},
list: {},
loadingAssignees: false,
};
},
computed: {
- showSidebar () {
+ showSidebar() {
return Object.keys(this.issue).length;
},
milestoneTitle() {
@@ -55,18 +51,20 @@ gl.issueBoards.BoardSidebar = Vue.extend({
return this.issue.labels && this.issue.labels.length;
},
labelDropdownTitle() {
- return this.hasLabels ? sprintf(__('%{firstLabel} +%{labelCount} more'), {
- firstLabel: this.issue.labels[0].title,
- labelCount: this.issue.labels.length - 1
- }) : __('Label');
+ return this.hasLabels
+ ? sprintf(__('%{firstLabel} +%{labelCount} more'), {
+ firstLabel: this.issue.labels[0].title,
+ labelCount: this.issue.labels.length - 1,
+ })
+ : __('Label');
},
selectedLabels() {
return this.hasLabels ? this.issue.labels.map(l => l.title).join(',') : '';
- }
+ },
},
watch: {
detail: {
- handler () {
+ handler() {
if (this.issue.id !== this.detail.issue.id) {
$('.block.assignee')
.find('input:not(.js-vue)[name="issue[assignee_ids][]"]')
@@ -75,17 +73,19 @@ gl.issueBoards.BoardSidebar = Vue.extend({
});
$('.js-issue-board-sidebar', this.$el).each((i, el) => {
- $(el).data('glDropdown').clearMenu();
+ $(el)
+ .data('glDropdown')
+ .clearMenu();
});
}
this.issue = this.detail.issue;
this.list = this.detail.list;
},
- deep: true
+ deep: true,
},
},
- created () {
+ created() {
// Get events from glDropdown
eventHub.$on('sidebar.removeAssignee', this.removeAssignee);
eventHub.$on('sidebar.addAssignee', this.addAssignee);
@@ -98,7 +98,7 @@ gl.issueBoards.BoardSidebar = Vue.extend({
eventHub.$off('sidebar.removeAllAssignees', this.removeAllAssignees);
eventHub.$off('sidebar.saveAssignees', this.saveAssignees);
},
- mounted () {
+ mounted() {
new IssuableContext(this.currentUser);
new MilestoneSelect();
new DueDateSelectors();
@@ -106,29 +106,30 @@ gl.issueBoards.BoardSidebar = Vue.extend({
new Sidebar();
},
methods: {
- closeSidebar () {
+ closeSidebar() {
this.detail.issue = {};
},
- assignSelf () {
+ assignSelf() {
// Notify gl dropdown that we are now assigning to current user
this.$refs.assigneeBlock.dispatchEvent(new Event('assignYourself'));
this.addAssignee(this.currentUser);
this.saveAssignees();
},
- removeAssignee (a) {
- gl.issueBoards.BoardsStore.detail.issue.removeAssignee(a);
+ removeAssignee(a) {
+ boardsStore.detail.issue.removeAssignee(a);
},
- addAssignee (a) {
- gl.issueBoards.BoardsStore.detail.issue.addAssignee(a);
+ addAssignee(a) {
+ boardsStore.detail.issue.addAssignee(a);
},
- removeAllAssignees () {
- gl.issueBoards.BoardsStore.detail.issue.removeAllAssignees();
+ removeAllAssignees() {
+ boardsStore.detail.issue.removeAllAssignees();
},
- saveAssignees () {
+ saveAssignees() {
this.loadingAssignees = true;
- gl.issueBoards.BoardsStore.detail.issue.update()
+ boardsStore.detail.issue
+ .update()
.then(() => {
this.loadingAssignees = false;
})
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.vue b/app/assets/javascripts/boards/components/issue_card_inner.vue
index d50641dc3a9..0f581c3d37d 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner.vue
+++ b/app/assets/javascripts/boards/components/issue_card_inner.vue
@@ -1,162 +1,217 @@
<script>
- import $ from 'jquery';
- import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
- import eventHub from '../eventhub';
- import tooltip from '../../vue_shared/directives/tooltip';
+import { GlTooltipDirective } from '@gitlab/ui';
+import { sprintf, __ } from '~/locale';
+import Icon from '~/vue_shared/components/icon.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
+import eventHub from '../eventhub';
+import IssueDueDate from './issue_due_date.vue';
+import IssueTimeEstimate from './issue_time_estimate.vue';
+import boardsStore from '../stores/boards_store';
- const Store = gl.issueBoards.BoardsStore;
+export default {
+ components: {
+ Icon,
+ UserAvatarLink,
+ TooltipOnTruncate,
+ IssueDueDate,
+ IssueTimeEstimate,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ issue: {
+ type: Object,
+ required: true,
+ },
+ issueLinkBase: {
+ type: String,
+ required: true,
+ },
+ list: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ rootPath: {
+ type: String,
+ required: true,
+ },
+ updateFilters: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ groupId: {
+ type: Number,
+ required: false,
+ default: null,
+ },
+ },
+ data() {
+ return {
+ limitBeforeCounter: 2,
+ maxRender: 3,
+ maxCounter: 99,
+ };
+ },
+ computed: {
+ numberOverLimit() {
+ return this.issue.assignees.length - this.limitBeforeCounter;
+ },
+ assigneeCounterTooltip() {
+ const { numberOverLimit, maxCounter } = this;
+ const count = numberOverLimit > maxCounter ? maxCounter : numberOverLimit;
+ return sprintf(__('%{count} more assignees'), { count });
+ },
+ assigneeCounterLabel() {
+ if (this.numberOverLimit > this.maxCounter) {
+ return `${this.maxCounter}+`;
+ }
- export default {
- components: {
- UserAvatarLink,
- },
- directives: {
- tooltip,
- },
- props: {
- issue: {
- type: Object,
- required: true,
- },
- issueLinkBase: {
- type: String,
- required: true,
- },
- list: {
- type: Object,
- required: false,
- default: () => ({}),
- },
- rootPath: {
- type: String,
- required: true,
- },
- updateFilters: {
- type: Boolean,
- required: false,
- default: false,
- },
- groupId: {
- type: Number,
- required: false,
- default: null,
- },
- },
- data() {
- return {
- limitBeforeCounter: 3,
- maxRender: 4,
- maxCounter: 99,
- };
+ return `+${this.numberOverLimit}`;
},
- computed: {
- numberOverLimit() {
- return this.issue.assignees.length - this.limitBeforeCounter;
- },
- assigneeCounterTooltip() {
- return `${this.assigneeCounterLabel} more`;
- },
- assigneeCounterLabel() {
- if (this.numberOverLimit > this.maxCounter) {
- return `${this.maxCounter}+`;
- }
+ shouldRenderCounter() {
+ if (this.issue.assignees.length <= this.maxRender) {
+ return false;
+ }
- return `+${this.numberOverLimit}`;
- },
- shouldRenderCounter() {
- if (this.issue.assignees.length <= this.maxRender) {
- return false;
- }
+ return this.issue.assignees.length > this.numberOverLimit;
+ },
+ issueId() {
+ if (this.issue.iid) {
+ return `#${this.issue.iid}`;
+ }
+ return false;
+ },
+ showLabelFooter() {
+ return this.issue.labels.find(l => this.showLabel(l)) !== undefined;
+ },
+ issueReferencePath() {
+ const { referencePath, groupId } = this.issue;
+ return !groupId ? referencePath.split('#')[0] : null;
+ },
+ },
+ methods: {
+ isIndexLessThanlimit(index) {
+ return index < this.limitBeforeCounter;
+ },
+ shouldRenderAssignee(index) {
+ // Eg. maxRender is 4,
+ // Render up to all 4 assignees if there are only 4 assigness
+ // Otherwise render up to the limitBeforeCounter
+ if (this.issue.assignees.length <= this.maxRender) {
+ return index < this.maxRender;
+ }
- return this.issue.assignees.length > this.numberOverLimit;
- },
- issueId() {
- if (this.issue.iid) {
- return `#${this.issue.iid}`;
- }
- return false;
- },
- showLabelFooter() {
- return this.issue.labels.find(l => this.showLabel(l)) !== undefined;
- },
- },
- methods: {
- isIndexLessThanlimit(index) {
- return index < this.limitBeforeCounter;
- },
- shouldRenderAssignee(index) {
- // Eg. maxRender is 4,
- // Render up to all 4 assignees if there are only 4 assigness
- // Otherwise render up to the limitBeforeCounter
- if (this.issue.assignees.length <= this.maxRender) {
- return index < this.maxRender;
- }
+ return index < this.limitBeforeCounter;
+ },
+ assigneeUrl(assignee) {
+ if (!assignee) return '';
+ return `${this.rootPath}${assignee.username}`;
+ },
+ avatarUrlTitle(assignee) {
+ return `Avatar for ${assignee.name}`;
+ },
+ showLabel(label) {
+ if (!label.id) return false;
+ return true;
+ },
+ filterByLabel(label) {
+ if (!this.updateFilters) return;
+ const labelTitle = encodeURIComponent(label.title);
+ const filter = `label_name[]=${labelTitle}`;
+
+ this.applyFilter(filter);
+ },
+ filterByWeight(weight) {
+ if (!this.updateFilters) return;
- return index < this.limitBeforeCounter;
- },
- assigneeUrl(assignee) {
- return `${this.rootPath}${assignee.username}`;
- },
- assigneeUrlTitle(assignee) {
- return `Assigned to ${assignee.name}`;
- },
- avatarUrlTitle(assignee) {
- return `Avatar for ${assignee.name}`;
- },
- showLabel(label) {
- if (!label.id) return false;
- return true;
- },
- filterByLabel(label, e) {
- if (!this.updateFilters) return;
+ const issueWeight = encodeURIComponent(weight);
+ const filter = `weight=${issueWeight}`;
- const filterPath = gl.issueBoards.BoardsStore.filter.path.split('&');
- const labelTitle = encodeURIComponent(label.title);
- const param = `label_name[]=${labelTitle}`;
- const labelIndex = filterPath.indexOf(param);
- $(e.currentTarget).tooltip('hide');
+ this.applyFilter(filter);
+ },
+ applyFilter(filter) {
+ const filterPath = boardsStore.filter.path.split('&');
+ const filterIndex = filterPath.indexOf(filter);
- if (labelIndex === -1) {
- filterPath.push(param);
- } else {
- filterPath.splice(labelIndex, 1);
- }
+ if (filterIndex === -1) {
+ filterPath.push(filter);
+ } else {
+ filterPath.splice(filterIndex, 1);
+ }
- gl.issueBoards.BoardsStore.filter.path = filterPath.join('&');
+ boardsStore.filter.path = filterPath.join('&');
- Store.updateFiltersUrl();
+ boardsStore.updateFiltersUrl();
- eventHub.$emit('updateTokens');
- },
- labelStyle(label) {
- return {
- backgroundColor: label.color,
- color: label.textColor,
- };
- },
- },
- };
+ eventHub.$emit('updateTokens');
+ },
+ labelStyle(label) {
+ return {
+ backgroundColor: label.color,
+ color: label.textColor,
+ };
+ },
+ },
+};
</script>
<template>
<div>
<div class="board-card-header">
- <h4 class="board-card-title">
- <i
+ <h4 class="board-card-title append-bottom-0 prepend-top-0">
+ <icon
v-if="issue.confidential"
- class="fa fa-eye-slash confidential-icon"
- aria-hidden="true"
- ></i>
- <a
- :href="issue.path"
- :title="issue.title"
- class="js-no-trigger">{{ issue.title }}</a>
+ v-gl-tooltip
+ name="eye-slash"
+ :title="__('Confidential')"
+ class="confidential-icon append-right-4"
+ :aria-label="__('Confidential')"
+ /><a :href="issue.path" :title="issue.title" class="js-no-trigger" @mousemove.stop>{{
+ issue.title
+ }}</a>
+ </h4>
+ </div>
+ <div v-if="showLabelFooter" class="board-card-labels prepend-top-4 d-flex flex-wrap">
+ <button
+ v-for="label in issue.labels"
+ v-if="showLabel(label)"
+ :key="label.id"
+ v-gl-tooltip
+ :style="labelStyle(label)"
+ :title="label.description"
+ class="badge color-label append-right-4 prepend-top-4"
+ type="button"
+ @click="filterByLabel(label);"
+ >
+ {{ label.title }}
+ </button>
+ </div>
+ <div class="board-card-footer d-flex justify-content-between align-items-end">
+ <div
+ class="d-flex align-items-start flex-wrap-reverse board-card-number-container js-board-card-number-container"
+ >
<span
- v-if="issueId"
- class="board-card-number"
+ v-if="issue.referencePath"
+ class="board-card-number d-flex append-right-8 prepend-top-8"
>
- {{ issue.referencePath }}
+ <tooltip-on-truncate
+ v-if="issueReferencePath"
+ :title="issueReferencePath"
+ placement="bottom"
+ class="board-issue-path block-truncated bold"
+ >{{ issueReferencePath }}</tooltip-on-truncate
+ >#{{ issue.iid }}
</span>
- </h4>
+ <span class="board-info-items prepend-top-8 d-inline-block">
+ <issue-due-date v-if="issue.dueDate" :date="issue.dueDate" /><issue-time-estimate
+ v-if="issue.timeEstimate"
+ :estimate="issue.timeEstimate"
+ />
+ </span>
+ </div>
<div class="board-card-assignee">
<user-avatar-link
v-for="(assignee, index) in issue.assignees"
@@ -165,38 +220,25 @@
:link-href="assigneeUrl(assignee)"
:img-alt="avatarUrlTitle(assignee)"
:img-src="assignee.avatar"
- :tooltip-text="assigneeUrlTitle(assignee)"
+ :img-size="24"
class="js-no-trigger"
tooltip-placement="bottom"
- />
+ >
+ <span class="js-assignee-tooltip">
+ <span class="bold d-block">Assignee</span> {{ assignee.name }}
+ <span class="text-white-50">@{{ assignee.username }}</span>
+ </span>
+ </user-avatar-link>
<span
- v-tooltip
v-if="shouldRenderCounter"
+ v-gl-tooltip
:title="assigneeCounterTooltip"
class="avatar-counter"
+ data-placement="bottom"
>
{{ assigneeCounterLabel }}
</span>
</div>
</div>
- <div
- v-if="showLabelFooter"
- class="board-card-footer"
- >
- <button
- v-tooltip
- v-for="label in issue.labels"
- v-if="showLabel(label)"
- :key="label.id"
- :style="labelStyle(label)"
- :title="label.description"
- class="badge color-label"
- type="button"
- data-container="body"
- @click="filterByLabel(label, $event)"
- >
- {{ label.title }}
- </button>
- </div>
</div>
</template>
diff --git a/app/assets/javascripts/boards/components/issue_due_date.vue b/app/assets/javascripts/boards/components/issue_due_date.vue
new file mode 100644
index 00000000000..15937b1091a
--- /dev/null
+++ b/app/assets/javascripts/boards/components/issue_due_date.vue
@@ -0,0 +1,82 @@
+<script>
+import dateFormat from 'dateformat';
+import { GlTooltip } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
+import { __ } from '~/locale';
+import { getDayDifference, getTimeago, dateInWords } from '~/lib/utils/datetime_utility';
+
+export default {
+ components: {
+ Icon,
+ GlTooltip,
+ },
+ props: {
+ date: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ title() {
+ const timeago = getTimeago();
+ const { timeDifference, standardDateFormat } = this;
+ const formatedDate = standardDateFormat;
+
+ if (timeDifference >= -1 && timeDifference < 7) {
+ return `${timeago.format(this.issueDueDate)} (${formatedDate})`;
+ }
+
+ return timeago.format(this.issueDueDate);
+ },
+ body() {
+ const { timeDifference, issueDueDate, standardDateFormat } = this;
+
+ if (timeDifference === 0) {
+ return __('Today');
+ } else if (timeDifference === 1) {
+ return __('Tomorrow');
+ } else if (timeDifference === -1) {
+ return __('Yesterday');
+ } else if (timeDifference > 0 && timeDifference < 7) {
+ return dateFormat(issueDueDate, 'dddd', true);
+ }
+
+ return standardDateFormat;
+ },
+ issueDueDate() {
+ return new Date(this.date);
+ },
+ timeDifference() {
+ const today = new Date();
+ return getDayDifference(today, this.issueDueDate);
+ },
+ isPastDue() {
+ if (this.timeDifference >= 0) return false;
+ return true;
+ },
+ standardDateFormat() {
+ const today = new Date();
+ const isDueInCurrentYear = today.getFullYear() === this.issueDueDate.getFullYear();
+
+ return dateInWords(this.issueDueDate, true, isDueInCurrentYear);
+ },
+ },
+};
+</script>
+
+<template>
+ <span>
+ <span ref="issueDueDate" class="board-card-info card-number">
+ <icon
+ :class="{ 'text-danger': isPastDue, 'board-card-info-icon': true }"
+ name="calendar"
+ /><time :class="{ 'text-danger': isPastDue }" datetime="date" class="board-card-info-text">{{
+ body
+ }}</time>
+ </span>
+ <gl-tooltip :target="() => $refs.issueDueDate" placement="bottom">
+ <span class="bold">{{ __('Due date') }}</span> <br />
+ <span :class="{ 'text-danger-muted': isPastDue }">{{ title }}</span>
+ </gl-tooltip>
+ </span>
+</template>
diff --git a/app/assets/javascripts/boards/components/issue_time_estimate.vue b/app/assets/javascripts/boards/components/issue_time_estimate.vue
new file mode 100644
index 00000000000..5acc3025b2c
--- /dev/null
+++ b/app/assets/javascripts/boards/components/issue_time_estimate.vue
@@ -0,0 +1,44 @@
+<script>
+import { GlTooltip } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
+import { parseSeconds, stringifyTime } from '~/lib/utils/datetime_utility';
+
+export default {
+ components: {
+ Icon,
+ GlTooltip,
+ },
+ props: {
+ estimate: {
+ type: Number,
+ required: true,
+ },
+ },
+ computed: {
+ title() {
+ return stringifyTime(parseSeconds(this.estimate), true);
+ },
+ timeEstimate() {
+ return stringifyTime(parseSeconds(this.estimate));
+ },
+ },
+};
+</script>
+
+<template>
+ <span>
+ <span ref="issueTimeEstimate" class="board-card-info card-number">
+ <icon name="hourglass" css-classes="board-card-info-icon" /><time
+ class="board-card-info-text"
+ >{{ timeEstimate }}</time
+ >
+ </span>
+ <gl-tooltip
+ :target="() => $refs.issueTimeEstimate"
+ placement="bottom"
+ class="js-issue-time-estimate"
+ >
+ <span class="bold d-block">{{ __('Time estimate') }}</span> {{ title }}
+ </gl-tooltip>
+ </span>
+</template>
diff --git a/app/assets/javascripts/boards/components/modal/empty_state.vue b/app/assets/javascripts/boards/components/modal/empty_state.vue
index dbd69f84526..08408eb0b52 100644
--- a/app/assets/javascripts/boards/components/modal/empty_state.vue
+++ b/app/assets/javascripts/boards/components/modal/empty_state.vue
@@ -20,7 +20,7 @@ export default {
computed: {
contents() {
const obj = {
- title: 'You haven\'t added any issues to your project yet',
+ title: "You haven't added any issues to your project yet",
content: `
An issue can be a bug, a todo or a feature request that needs to be
discussed in a project. Besides, issues are searchable and filterable.
@@ -28,7 +28,7 @@ export default {
};
if (this.activeTab === 'selected') {
- obj.title = 'You haven\'t selected any issues yet';
+ obj.title = "You haven't selected any issues yet";
obj.content = `
Go back to <strong>Open issues</strong> and select some issues
to add to your board.
@@ -45,24 +45,20 @@ export default {
<section class="empty-state">
<div class="row">
<div class="col-12 col-md-6 order-md-last">
- <aside class="svg-content"><img :src="emptyStateSvg"/></aside>
+ <aside class="svg-content"><img :src="emptyStateSvg" /></aside>
</div>
<div class="col-12 col-md-6 order-md-first">
<div class="text-content">
<h4>{{ contents.title }}</h4>
<p v-html="contents.content"></p>
- <a
- v-if="activeTab === 'all'"
- :href="newIssuePath"
- class="btn btn-success btn-inverted"
- >
+ <a v-if="activeTab === 'all'" :href="newIssuePath" class="btn btn-success btn-inverted">
New issue
</a>
<button
v-if="activeTab === 'selected'"
class="btn btn-default"
type="button"
- @click="changeTab('all')"
+ @click="changeTab('all');"
>
Open issues
</button>
diff --git a/app/assets/javascripts/boards/components/modal/footer.vue b/app/assets/javascripts/boards/components/modal/footer.vue
index d4affc8c3de..b1bc7d87086 100644
--- a/app/assets/javascripts/boards/components/modal/footer.vue
+++ b/app/assets/javascripts/boards/components/modal/footer.vue
@@ -5,6 +5,7 @@ import ListsDropdown from './lists_dropdown.vue';
import { pluralize } from '../../../lib/utils/text_utility';
import ModalStore from '../../stores/modal_store';
import modalMixin from '../../mixins/modal_mixins';
+import boardsStore from '../../stores/boards_store';
export default {
components: {
@@ -14,7 +15,7 @@ export default {
data() {
return {
modal: ModalStore.store,
- state: gl.issueBoards.BoardsStore.state,
+ state: boardsStore.state,
};
},
computed: {
@@ -41,19 +42,17 @@ export default {
const req = this.buildUpdateRequest(list);
// Post the data to the backend
- gl.boardService
- .bulkUpdate(issueIds, req)
- .catch(() => {
- Flash(__('Failed to update issues, please try again.'));
+ gl.boardService.bulkUpdate(issueIds, req).catch(() => {
+ Flash(__('Failed to update issues, please try again.'));
- selectedIssues.forEach((issue) => {
- list.removeIssue(issue);
- list.issuesSize -= 1;
- });
+ selectedIssues.forEach(issue => {
+ list.removeIssue(issue);
+ list.issuesSize -= 1;
});
+ });
// Add the issues on the frontend
- selectedIssues.forEach((issue) => {
+ selectedIssues.forEach(issue => {
list.addIssue(issue);
list.issuesSize += 1;
});
@@ -64,28 +63,15 @@ export default {
};
</script>
<template>
- <footer
- class="form-actions add-issues-footer"
- >
+ <footer class="form-actions add-issues-footer">
<div class="float-left">
- <button
- :disabled="submitDisabled"
- class="btn btn-success"
- type="button"
- @click="addIssues"
- >
+ <button :disabled="submitDisabled" class="btn btn-success" type="button" @click="addIssues">
{{ submitText }}
</button>
- <span class="inline add-issues-footer-to-list">
- to list
- </span>
- <lists-dropdown/>
+ <span class="inline add-issues-footer-to-list"> to list </span>
+ <lists-dropdown />
</div>
- <button
- class="btn btn-default float-right"
- type="button"
- @click="toggleModal(false)"
- >
+ <button class="btn btn-default float-right" type="button" @click="toggleModal(false);">
Cancel
</button>
</footer>
diff --git a/app/assets/javascripts/boards/components/modal/header.vue b/app/assets/javascripts/boards/components/modal/header.vue
index 979fb4d7199..d0e285a149e 100644
--- a/app/assets/javascripts/boards/components/modal/header.vue
+++ b/app/assets/javascripts/boards/components/modal/header.vue
@@ -1,52 +1,52 @@
<script>
- import ModalFilters from './filters';
- import ModalTabs from './tabs.vue';
- import ModalStore from '../../stores/modal_store';
- import modalMixin from '../../mixins/modal_mixins';
+import ModalFilters from './filters';
+import ModalTabs from './tabs.vue';
+import ModalStore from '../../stores/modal_store';
+import modalMixin from '../../mixins/modal_mixins';
- export default {
- components: {
- ModalTabs,
- ModalFilters,
+export default {
+ components: {
+ ModalTabs,
+ ModalFilters,
+ },
+ mixins: [modalMixin],
+ props: {
+ projectId: {
+ type: Number,
+ required: true,
},
- mixins: [modalMixin],
- props: {
- projectId: {
- type: Number,
- required: true,
- },
- milestonePath: {
- type: String,
- required: true,
- },
- labelPath: {
- type: String,
- required: true,
- },
+ milestonePath: {
+ type: String,
+ required: true,
},
- data() {
- return ModalStore.store;
+ labelPath: {
+ type: String,
+ required: true,
},
- computed: {
- selectAllText() {
- if (ModalStore.selectedCount() !== this.issues.length || this.issues.length === 0) {
- return 'Select all';
- }
+ },
+ data() {
+ return ModalStore.store;
+ },
+ computed: {
+ selectAllText() {
+ if (ModalStore.selectedCount() !== this.issues.length || this.issues.length === 0) {
+ return 'Select all';
+ }
- return 'Deselect all';
- },
- showSearch() {
- return this.activeTab === 'all' && !this.loading && this.issuesCount > 0;
- },
+ return 'Deselect all';
},
- methods: {
- toggleAll() {
- this.$refs.selectAllBtn.blur();
+ showSearch() {
+ return this.activeTab === 'all' && !this.loading && this.issuesCount > 0;
+ },
+ },
+ methods: {
+ toggleAll() {
+ this.$refs.selectAllBtn.blur();
- ModalStore.toggleAll();
- },
+ ModalStore.toggleAll();
},
- };
+ },
+};
</script>
<template>
<div>
@@ -58,16 +58,14 @@
class="close"
data-dismiss="modal"
aria-label="Close"
- @click="toggleModal(false)"
+ @click="toggleModal(false);"
>
<span aria-hidden="true">×</span>
</button>
</h2>
</header>
- <modal-tabs v-if="!loading && issuesCount > 0"/>
- <div
- v-if="showSearch"
- class="add-issues-search append-bottom-10">
+ <modal-tabs v-if="!loading && issuesCount > 0" />
+ <div v-if="showSearch" class="add-issues-search append-bottom-10">
<modal-filters :store="filter" />
<button
ref="selectAllBtn"
diff --git a/app/assets/javascripts/boards/components/modal/index.vue b/app/assets/javascripts/boards/components/modal/index.vue
index 0c4c709324d..1e5761cf268 100644
--- a/app/assets/javascripts/boards/components/modal/index.vue
+++ b/app/assets/javascripts/boards/components/modal/index.vue
@@ -1,148 +1,149 @@
<script>
- /* global ListIssue */
- import { urlParamsToObject } from '~/lib/utils/common_utils';
- import ModalHeader from './header.vue';
- import ModalList from './list.vue';
- import ModalFooter from './footer.vue';
- import EmptyState from './empty_state.vue';
- import ModalStore from '../../stores/modal_store';
+/* global ListIssue */
+import { urlParamsToObject } from '~/lib/utils/common_utils';
+import ModalHeader from './header.vue';
+import ModalList from './list.vue';
+import ModalFooter from './footer.vue';
+import EmptyState from './empty_state.vue';
+import ModalStore from '../../stores/modal_store';
+import { GlLoadingIcon } from '@gitlab/ui';
- export default {
- components: {
- EmptyState,
- ModalHeader,
- ModalList,
- ModalFooter,
+export default {
+ components: {
+ EmptyState,
+ ModalHeader,
+ ModalList,
+ ModalFooter,
+ GlLoadingIcon,
+ },
+ props: {
+ newIssuePath: {
+ type: String,
+ required: true,
},
- props: {
- newIssuePath: {
- type: String,
- required: true,
- },
- emptyStateSvg: {
- type: String,
- required: true,
- },
- issueLinkBase: {
- type: String,
- required: true,
- },
- rootPath: {
- type: String,
- required: true,
- },
- projectId: {
- type: Number,
- required: true,
- },
- milestonePath: {
- type: String,
- required: true,
- },
- labelPath: {
- type: String,
- required: true,
- },
+ emptyStateSvg: {
+ type: String,
+ required: true,
},
- data() {
- return ModalStore.store;
+ issueLinkBase: {
+ type: String,
+ required: true,
},
- computed: {
- showList() {
- if (this.activeTab === 'selected') {
- return this.selectedIssues.length > 0;
- }
+ rootPath: {
+ type: String,
+ required: true,
+ },
+ projectId: {
+ type: Number,
+ required: true,
+ },
+ milestonePath: {
+ type: String,
+ required: true,
+ },
+ labelPath: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return ModalStore.store;
+ },
+ computed: {
+ showList() {
+ if (this.activeTab === 'selected') {
+ return this.selectedIssues.length > 0;
+ }
- return this.issuesCount > 0;
- },
- showEmptyState() {
- if (!this.loading && this.issuesCount === 0) {
- return true;
- }
+ return this.issuesCount > 0;
+ },
+ showEmptyState() {
+ if (!this.loading && this.issuesCount === 0) {
+ return true;
+ }
- return this.activeTab === 'selected' && this.selectedIssues.length === 0;
- },
+ return this.activeTab === 'selected' && this.selectedIssues.length === 0;
},
- watch: {
- page() {
- this.loadIssues();
- },
- showAddIssuesModal() {
- if (this.showAddIssuesModal && !this.issues.length) {
- this.loading = true;
+ },
+ watch: {
+ page() {
+ this.loadIssues();
+ },
+ showAddIssuesModal() {
+ if (this.showAddIssuesModal && !this.issues.length) {
+ this.loading = true;
+ const loadingDone = () => {
+ this.loading = false;
+ };
+
+ this.loadIssues()
+ .then(loadingDone)
+ .catch(loadingDone);
+ } else if (!this.showAddIssuesModal) {
+ this.issues = [];
+ this.selectedIssues = [];
+ this.issuesCount = false;
+ }
+ },
+ filter: {
+ handler() {
+ if (this.$el.tagName) {
+ this.page = 1;
+ this.filterLoading = true;
const loadingDone = () => {
- this.loading = false;
+ this.filterLoading = false;
};
- this.loadIssues()
+ this.loadIssues(true)
.then(loadingDone)
.catch(loadingDone);
- } else if (!this.showAddIssuesModal) {
- this.issues = [];
- this.selectedIssues = [];
- this.issuesCount = false;
}
},
- filter: {
- handler() {
- if (this.$el.tagName) {
- this.page = 1;
- this.filterLoading = true;
- const loadingDone = () => {
- this.filterLoading = false;
- };
-
- this.loadIssues(true)
- .then(loadingDone)
- .catch(loadingDone);
- }
- },
- deep: true,
- },
+ deep: true,
},
- created() {
- this.page = 1;
- },
- methods: {
- loadIssues(clearIssues = false) {
- if (!this.showAddIssuesModal) return false;
+ },
+ created() {
+ this.page = 1;
+ },
+ methods: {
+ loadIssues(clearIssues = false) {
+ if (!this.showAddIssuesModal) return false;
- return gl.boardService.getBacklog({
+ return gl.boardService
+ .getBacklog({
...urlParamsToObject(this.filter.path),
page: this.page,
per: this.perPage,
})
- .then(res => res.data)
- .then(data => {
- if (clearIssues) {
- this.issues = [];
- }
+ .then(res => res.data)
+ .then(data => {
+ if (clearIssues) {
+ this.issues = [];
+ }
- data.issues.forEach(issueObj => {
- const issue = new ListIssue(issueObj);
- const foundSelectedIssue = ModalStore.findSelectedIssue(issue);
- issue.selected = !!foundSelectedIssue;
+ data.issues.forEach(issueObj => {
+ const issue = new ListIssue(issueObj);
+ const foundSelectedIssue = ModalStore.findSelectedIssue(issue);
+ issue.selected = !!foundSelectedIssue;
- this.issues.push(issue);
- });
+ this.issues.push(issue);
+ });
- this.loadingNewPage = false;
+ this.loadingNewPage = false;
- if (!this.issuesCount) {
- this.issuesCount = data.size;
- }
- })
- .catch(() => {
- // TODO: handle request error
- });
- },
+ if (!this.issuesCount) {
+ this.issuesCount = data.size;
+ }
+ })
+ .catch(() => {
+ // TODO: handle request error
+ });
},
- };
+ },
+};
</script>
<template>
- <div
- v-if="showAddIssuesModal"
- class="add-issues-modal">
+ <div v-if="showAddIssuesModal" class="add-issues-modal">
<div class="add-issues-container">
<modal-header
:project-id="projectId"
@@ -160,15 +161,10 @@
:new-issue-path="newIssuePath"
:empty-state-svg="emptyStateSvg"
/>
- <section
- v-if="loading || filterLoading"
- class="add-issues-list text-center"
- >
- <div class="add-issues-list-loading">
- <gl-loading-icon />
- </div>
+ <section v-if="loading || filterLoading" class="add-issues-list text-center">
+ <div class="add-issues-list-loading"><gl-loading-icon /></div>
</section>
- <modal-footer/>
+ <modal-footer />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/boards/components/modal/list.vue b/app/assets/javascripts/boards/components/modal/list.vue
index a58b5afe970..878bb002c6c 100644
--- a/app/assets/javascripts/boards/components/modal/list.vue
+++ b/app/assets/javascripts/boards/components/modal/list.vue
@@ -1,159 +1,145 @@
<script>
- import bp from '../../../breakpoints';
- import ModalStore from '../../stores/modal_store';
- import IssueCardInner from '../issue_card_inner.vue';
+import Icon from '~/vue_shared/components/icon.vue';
+import bp from '../../../breakpoints';
+import ModalStore from '../../stores/modal_store';
+import IssueCardInner from '../issue_card_inner.vue';
- export default {
- components: {
- IssueCardInner,
+export default {
+ components: {
+ IssueCardInner,
+ Icon,
+ },
+ props: {
+ issueLinkBase: {
+ type: String,
+ required: true,
},
- props: {
- issueLinkBase: {
- type: String,
- required: true,
- },
- rootPath: {
- type: String,
- required: true,
- },
- emptyStateSvg: {
- type: String,
- required: true,
- },
+ rootPath: {
+ type: String,
+ required: true,
},
- data() {
- return ModalStore.store;
+ emptyStateSvg: {
+ type: String,
+ required: true,
},
- computed: {
- loopIssues() {
- if (this.activeTab === 'all') {
- return this.issues;
- }
+ },
+ data() {
+ return ModalStore.store;
+ },
+ computed: {
+ loopIssues() {
+ if (this.activeTab === 'all') {
+ return this.issues;
+ }
- return this.selectedIssues;
- },
- groupedIssues() {
- const groups = [];
- this.loopIssues.forEach((issue, i) => {
- const index = i % this.columns;
+ return this.selectedIssues;
+ },
+ groupedIssues() {
+ const groups = [];
+ this.loopIssues.forEach((issue, i) => {
+ const index = i % this.columns;
- if (!groups[index]) {
- groups.push([]);
- }
+ if (!groups[index]) {
+ groups.push([]);
+ }
- groups[index].push(issue);
- });
+ groups[index].push(issue);
+ });
- return groups;
- },
+ return groups;
},
- watch: {
- activeTab() {
- if (this.activeTab === 'all') {
- ModalStore.purgeUnselectedIssues();
- }
- },
+ },
+ watch: {
+ activeTab() {
+ if (this.activeTab === 'all') {
+ ModalStore.purgeUnselectedIssues();
+ }
},
- mounted() {
- this.scrollHandlerWrapper = this.scrollHandler.bind(this);
- this.setColumnCountWrapper = this.setColumnCount.bind(this);
- this.setColumnCount();
+ },
+ mounted() {
+ this.scrollHandlerWrapper = this.scrollHandler.bind(this);
+ this.setColumnCountWrapper = this.setColumnCount.bind(this);
+ this.setColumnCount();
- this.$refs.list.addEventListener('scroll', this.scrollHandlerWrapper);
- window.addEventListener('resize', this.setColumnCountWrapper);
+ this.$refs.list.addEventListener('scroll', this.scrollHandlerWrapper);
+ window.addEventListener('resize', this.setColumnCountWrapper);
+ },
+ beforeDestroy() {
+ this.$refs.list.removeEventListener('scroll', this.scrollHandlerWrapper);
+ window.removeEventListener('resize', this.setColumnCountWrapper);
+ },
+ methods: {
+ scrollHandler() {
+ const currentPage = Math.floor(this.issues.length / this.perPage);
+
+ if (
+ this.scrollTop() > this.scrollHeight() - 100 &&
+ !this.loadingNewPage &&
+ currentPage === this.page
+ ) {
+ this.loadingNewPage = true;
+ this.page += 1;
+ }
},
- beforeDestroy() {
- this.$refs.list.removeEventListener('scroll', this.scrollHandlerWrapper);
- window.removeEventListener('resize', this.setColumnCountWrapper);
+ toggleIssue(e, issue) {
+ if (e.target.tagName !== 'A') {
+ ModalStore.toggleIssue(issue);
+ }
},
- methods: {
- scrollHandler() {
- const currentPage = Math.floor(this.issues.length / this.perPage);
-
- if (
- this.scrollTop() > this.scrollHeight() - 100 &&
- !this.loadingNewPage &&
- currentPage === this.page
- ) {
- this.loadingNewPage = true;
- this.page += 1;
- }
- },
- toggleIssue(e, issue) {
- if (e.target.tagName !== 'A') {
- ModalStore.toggleIssue(issue);
- }
- },
- listHeight() {
- return this.$refs.list.getBoundingClientRect().height;
- },
- scrollHeight() {
- return this.$refs.list.scrollHeight;
- },
- scrollTop() {
- return this.$refs.list.scrollTop + this.listHeight();
- },
- showIssue(issue) {
- if (this.activeTab === 'all') return true;
+ listHeight() {
+ return this.$refs.list.getBoundingClientRect().height;
+ },
+ scrollHeight() {
+ return this.$refs.list.scrollHeight;
+ },
+ scrollTop() {
+ return this.$refs.list.scrollTop + this.listHeight();
+ },
+ showIssue(issue) {
+ if (this.activeTab === 'all') return true;
- const index = ModalStore.selectedIssueIndex(issue);
+ const index = ModalStore.selectedIssueIndex(issue);
- return index !== -1;
- },
- setColumnCount() {
- const breakpoint = bp.getBreakpointSize();
+ return index !== -1;
+ },
+ setColumnCount() {
+ const breakpoint = bp.getBreakpointSize();
- if (breakpoint === 'lg' || breakpoint === 'md') {
- this.columns = 3;
- } else if (breakpoint === 'sm') {
- this.columns = 2;
- } else {
- this.columns = 1;
- }
- },
+ if (breakpoint === 'lg' || breakpoint === 'md') {
+ this.columns = 3;
+ } else if (breakpoint === 'sm') {
+ this.columns = 2;
+ } else {
+ this.columns = 1;
+ }
},
- };
+ },
+};
</script>
<template>
- <section
- ref="list"
- class="add-issues-list add-issues-list-columns">
+ <section ref="list" class="add-issues-list add-issues-list-columns">
<div
v-if="issuesCount > 0 && issues.length === 0"
- class="empty-state add-issues-empty-state-filter text-center">
- <div class="svg-content">
- <img :src="emptyStateSvg" />
- </div>
- <div class="text-content">
- <h4>
- There are no issues to show.
- </h4>
- </div>
+ class="empty-state add-issues-empty-state-filter text-center"
+ >
+ <div class="svg-content"><img :src="emptyStateSvg" /></div>
+ <div class="text-content"><h4>There are no issues to show.</h4></div>
</div>
- <div
- v-for="(group, index) in groupedIssues"
- :key="index"
- class="add-issues-list-column">
- <div
- v-for="issue in group"
- v-if="showIssue(issue)"
- :key="issue.id"
- class="board-card-parent">
+ <div v-for="(group, index) in groupedIssues" :key="index" class="add-issues-list-column">
+ <div v-for="issue in group" v-if="showIssue(issue)" :key="issue.id" class="board-card-parent">
<div
:class="{ 'is-active': issue.selected }"
class="board-card"
- @click="toggleIssue($event, issue)">
- <issue-card-inner
- :issue="issue"
- :issue-link-base="issueLinkBase"
- :root-path="rootPath"/>
- <span
+ @click="toggleIssue($event, issue);"
+ >
+ <issue-card-inner :issue="issue" :issue-link-base="issueLinkBase" :root-path="rootPath" />
+ <icon
v-if="issue.selected"
:aria-label="'Issue #' + issue.id + ' selected'"
+ name="mobile-issue-close"
aria-checked="true"
- class="issue-card-selected text-center">
- <i class="fa fa-check"></i>
- </span>
+ class="issue-card-selected text-center"
+ />
</div>
</div>
</div>
diff --git a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue b/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
index 6a5a39099bd..820d0679df5 100644
--- a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
+++ b/app/assets/javascripts/boards/components/modal/lists_dropdown.vue
@@ -1,11 +1,18 @@
<script>
+import { GlLink } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
import ModalStore from '../../stores/modal_store';
+import boardsStore from '../../stores/boards_store';
export default {
+ components: {
+ GlLink,
+ Icon,
+ },
data() {
return {
modal: ModalStore.store,
- state: gl.issueBoards.BoardsStore.state,
+ state: boardsStore.state,
};
},
computed: {
@@ -20,35 +27,22 @@ export default {
</script>
<template>
<div class="dropdown inline">
- <button
- class="dropdown-menu-toggle"
- type="button"
- data-toggle="dropdown"
- aria-expanded="false">
- <span
- :style="{ backgroundColor: selected.label.color }"
- class="dropdown-label-box">
- </span>
- {{ selected.title }}
- <i class="fa fa-chevron-down"></i>
+ <button class="dropdown-menu-toggle" type="button" data-toggle="dropdown" aria-expanded="false">
+ <span :style="{ backgroundColor: selected.label.color }" class="dropdown-label-box"> </span>
+ {{ selected.title }} <icon name="chevron-down" />
</button>
<div class="dropdown-menu dropdown-menu-selectable dropdown-menu-drop-up">
<ul>
- <li
- v-for="(list, i) in state.lists"
- v-if="list.type == 'label'"
- :key="i">
- <a
+ <li v-for="(list, i) in state.lists" v-if="list.type == 'label'" :key="i">
+ <gl-link
:class="{ 'is-active': list.id == selected.id }"
href="#"
role="button"
- @click.prevent="modal.selectedList = list">
- <span
- :style="{ backgroundColor: list.label.color }"
- class="dropdown-label-box">
- </span>
+ @click.prevent="modal.selectedList = list;"
+ >
+ <span :style="{ backgroundColor: list.label.color }" class="dropdown-label-box"> </span>
{{ list.title }}
- </a>
+ </gl-link>
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/boards/components/modal/tabs.vue b/app/assets/javascripts/boards/components/modal/tabs.vue
index d926b080094..7b800a6ab97 100644
--- a/app/assets/javascripts/boards/components/modal/tabs.vue
+++ b/app/assets/javascripts/boards/components/modal/tabs.vue
@@ -1,47 +1,33 @@
<script>
- import ModalStore from '../../stores/modal_store';
- import modalMixin from '../../mixins/modal_mixins';
+import ModalStore from '../../stores/modal_store';
+import modalMixin from '../../mixins/modal_mixins';
- export default {
- mixins: [modalMixin],
- data() {
- return ModalStore.store;
+export default {
+ mixins: [modalMixin],
+ data() {
+ return ModalStore.store;
+ },
+ computed: {
+ selectedCount() {
+ return ModalStore.selectedCount();
},
- computed: {
- selectedCount() {
- return ModalStore.selectedCount();
- },
- },
- destroyed() {
- this.activeTab = 'all';
- },
- };
+ },
+ destroyed() {
+ this.activeTab = 'all';
+ },
+};
</script>
<template>
<div class="top-area prepend-top-10 append-bottom-10">
<ul class="nav-links issues-state-filters">
- <li :class="{ 'active': activeTab == 'all' }">
- <a
- href="#"
- role="button"
- @click.prevent="changeTab('all')"
- >
- Open issues
- <span class="badge badge-pill">
- {{ issuesCount }}
- </span>
+ <li :class="{ active: activeTab == 'all' }">
+ <a href="#" role="button" @click.prevent="changeTab('all');">
+ Open issues <span class="badge badge-pill"> {{ issuesCount }} </span>
</a>
</li>
- <li :class="{ 'active': activeTab == 'selected' }">
- <a
- href="#"
- role="button"
- @click.prevent="changeTab('selected')"
- >
- Selected issues
- <span class="badge badge-pill">
- {{ selectedCount }}
- </span>
+ <li :class="{ active: activeTab == 'selected' }">
+ <a href="#" role="button" @click.prevent="changeTab('selected');">
+ Selected issues <span class="badge badge-pill"> {{ selectedCount }} </span>
</a>
</li>
</ul>
diff --git a/app/assets/javascripts/boards/components/new_list_dropdown.js b/app/assets/javascripts/boards/components/new_list_dropdown.js
index 448ab9ed135..f7016561f93 100644
--- a/app/assets/javascripts/boards/components/new_list_dropdown.js
+++ b/app/assets/javascripts/boards/components/new_list_dropdown.js
@@ -4,42 +4,43 @@ import $ from 'jquery';
import axios from '~/lib/utils/axios_utils';
import _ from 'underscore';
import CreateLabelDropdown from '../../create_label';
+import boardsStore from '../stores/boards_store';
-window.gl = window.gl || {};
-window.gl.issueBoards = window.gl.issueBoards || {};
-
-const Store = gl.issueBoards.BoardsStore;
-
-$(document).off('created.label').on('created.label', (e, label) => {
- Store.new({
- title: label.title,
- position: Store.state.lists.length - 2,
- list_type: 'label',
- label: {
- id: label.id,
+$(document)
+ .off('created.label')
+ .on('created.label', (e, label) => {
+ boardsStore.new({
title: label.title,
- color: label.color,
- },
+ position: boardsStore.state.lists.length - 2,
+ list_type: 'label',
+ label: {
+ id: label.id,
+ title: label.title,
+ color: label.color,
+ },
+ });
});
-});
-gl.issueBoards.newListDropdownInit = () => {
- $('.js-new-board-list').each(function () {
+export default function initNewListDropdown() {
+ $('.js-new-board-list').each(function() {
const $this = $(this);
- new CreateLabelDropdown($this.closest('.dropdown').find('.dropdown-new-label'), $this.data('namespacePath'), $this.data('projectPath'));
+ new CreateLabelDropdown(
+ $this.closest('.dropdown').find('.dropdown-new-label'),
+ $this.data('namespacePath'),
+ $this.data('projectPath'),
+ );
$this.glDropdown({
data(term, callback) {
- axios.get($this.attr('data-list-labels-path'))
- .then(({ data }) => {
- callback(data);
- });
+ axios.get($this.attr('data-list-labels-path')).then(({ data }) => {
+ callback(data);
+ });
},
- renderRow (label) {
- const active = Store.findList('title', label.title);
+ renderRow(label) {
+ const active = boardsStore.findList('title', label.title);
const $li = $('<li />');
const $a = $('<a />', {
- class: (active ? `is-active js-board-list-${active.id}` : ''),
+ class: active ? `is-active js-board-list-${active.id}` : '',
text: label.title,
href: '#',
});
@@ -57,15 +58,15 @@ gl.issueBoards.newListDropdownInit = () => {
selectable: true,
multiSelect: true,
containerSelector: '.js-tab-container-labels .dropdown-page-one .dropdown-content',
- clicked (options) {
+ clicked(options) {
const { e } = options;
const label = options.selectedObj;
e.preventDefault();
- if (!Store.findList('title', label.title)) {
- Store.new({
+ if (!boardsStore.findList('title', label.title)) {
+ boardsStore.new({
title: label.title,
- position: Store.state.lists.length - 2,
+ position: boardsStore.state.lists.length - 2,
list_type: 'label',
label: {
id: label.id,
@@ -74,9 +75,9 @@ gl.issueBoards.newListDropdownInit = () => {
},
});
- Store.state.lists = _.sortBy(Store.state.lists, 'position');
+ boardsStore.state.lists = _.sortBy(boardsStore.state.lists, 'position');
}
},
});
});
-};
+}
diff --git a/app/assets/javascripts/boards/components/project_select.vue b/app/assets/javascripts/boards/components/project_select.vue
index d4676914e02..31651658fe6 100644
--- a/app/assets/javascripts/boards/components/project_select.vue
+++ b/app/assets/javascripts/boards/components/project_select.vue
@@ -1,11 +1,17 @@
<script>
import $ from 'jquery';
import _ from 'underscore';
+import Icon from '~/vue_shared/components/icon.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '../eventhub';
import Api from '../../api';
export default {
name: 'BoardProjectSelect',
+ components: {
+ Icon,
+ GlLoadingIcon,
+ },
props: {
groupId: {
type: Number,
@@ -42,15 +48,26 @@ export default {
selectable: true,
data: (term, callback) => {
this.loading = true;
- return Api.groupProjects(this.groupId, term, {}, projects => {
- this.loading = false;
- callback(projects);
- });
+ return Api.groupProjects(
+ this.groupId,
+ term,
+ {
+ with_issues_enabled: true,
+ with_shared: false,
+ include_subgroups: true,
+ },
+ projects => {
+ this.loading = false;
+ callback(projects);
+ },
+ );
},
renderRow(project) {
return `
<li>
- <a href='#' class='dropdown-menu-link' data-project-id="${project.id}" data-project-name="${project.name}">
+ <a href='#' class='dropdown-menu-link' data-project-id="${
+ project.id
+ }" data-project-name="${project.name}">
${_.escape(project.name)}
</a>
</li>
@@ -64,25 +81,15 @@ export default {
<template>
<div>
- <label class="label-bold prepend-top-10">
- Project
- </label>
- <div
- ref="projectsDropdown"
- class="dropdown"
- >
+ <label class="label-bold prepend-top-10"> Project </label>
+ <div ref="projectsDropdown" class="dropdown">
<button
class="dropdown-menu-toggle wide"
type="button"
data-toggle="dropdown"
aria-expanded="false"
>
- {{ selectedProjectName }}
- <i
- class="fa fa-chevron-down"
- aria-hidden="true"
- >
- </i>
+ {{ selectedProjectName }} <icon name="chevron-down" />
</button>
<div class="dropdown-menu dropdown-menu-selectable dropdown-menu-full-width">
<div class="dropdown-title">
@@ -92,31 +99,19 @@ export default {
type="button"
class="dropdown-title-button dropdown-menu-close"
>
- <i
- aria-hidden="true"
+ <icon
+ name="merge-request-close-m"
data-hidden="true"
- class="fa fa-times dropdown-menu-close-icon"
- >
- </i>
+ class="dropdown-menu-close-icon"
+ />
</button>
</div>
<div class="dropdown-input">
- <input
- class="dropdown-input-field"
- type="search"
- placeholder="Search projects"
- />
- <i
- aria-hidden="true"
- data-hidden="true"
- class="fa fa-search dropdown-input-search"
- >
- </i>
+ <input class="dropdown-input-field" type="search" placeholder="Search projects" />
+ <icon name="search" class="dropdown-input-search" data-hidden="true" />
</div>
<div class="dropdown-content"></div>
- <div class="dropdown-loading">
- <gl-loading-icon />
- </div>
+ <div class="dropdown-loading"><gl-loading-icon /></div>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/boards/components/sidebar/remove_issue.vue b/app/assets/javascripts/boards/components/sidebar/remove_issue.vue
index 90d4c710daf..a2b8a0af236 100644
--- a/app/assets/javascripts/boards/components/sidebar/remove_issue.vue
+++ b/app/assets/javascripts/boards/components/sidebar/remove_issue.vue
@@ -1,90 +1,81 @@
<script>
- import Vue from 'vue';
- import Flash from '../../../flash';
- import { __ } from '../../../locale';
+import Vue from 'vue';
+import Flash from '../../../flash';
+import { __ } from '../../../locale';
+import boardsStore from '../../stores/boards_store';
- const Store = gl.issueBoards.BoardsStore;
-
- export default Vue.extend({
- props: {
- issue: {
- type: Object,
- required: true,
- },
- list: {
- type: Object,
- required: true,
- },
+export default Vue.extend({
+ props: {
+ issue: {
+ type: Object,
+ required: true,
},
- computed: {
- updateUrl() {
- return this.issue.path;
- },
+ list: {
+ type: Object,
+ required: true,
},
- methods: {
- removeIssue() {
- const { issue } = this;
- const lists = issue.getLists();
- const req = this.buildPatchRequest(issue, lists);
-
- const data = {
- issue: this.seedPatchRequest(issue, req),
- };
+ },
+ computed: {
+ updateUrl() {
+ return this.issue.path;
+ },
+ },
+ methods: {
+ removeIssue() {
+ const { issue } = this;
+ const lists = issue.getLists();
+ const req = this.buildPatchRequest(issue, lists);
- if (data.issue.label_ids.length === 0) {
- data.issue.label_ids = [''];
- }
+ const data = {
+ issue: this.seedPatchRequest(issue, req),
+ };
- // Post the remove data
- Vue.http.patch(this.updateUrl, data).catch(() => {
- Flash(__('Failed to remove issue from board, please try again.'));
+ if (data.issue.label_ids.length === 0) {
+ data.issue.label_ids = [''];
+ }
- lists.forEach(list => {
- list.addIssue(issue);
- });
- });
+ // Post the remove data
+ Vue.http.patch(this.updateUrl, data).catch(() => {
+ Flash(__('Failed to remove issue from board, please try again.'));
- // Remove from the frontend store
lists.forEach(list => {
- list.removeIssue(issue);
+ list.addIssue(issue);
});
+ });
- Store.detail.issue = {};
- },
- /**
- * Build the default patch request.
- */
- buildPatchRequest(issue, lists) {
- const listLabelIds = lists.map(list => list.label.id);
+ // Remove from the frontend store
+ lists.forEach(list => {
+ list.removeIssue(issue);
+ });
- const labelIds = issue.labels
- .map(label => label.id)
- .filter(id => !listLabelIds.includes(id));
+ boardsStore.detail.issue = {};
+ },
+ /**
+ * Build the default patch request.
+ */
+ buildPatchRequest(issue, lists) {
+ const listLabelIds = lists.map(list => list.label.id);
+
+ const labelIds = issue.labels.map(label => label.id).filter(id => !listLabelIds.includes(id));
- return {
- label_ids: labelIds,
- };
- },
- /**
- * Seed the given patch request.
- *
- * (This is overridden in EE)
- */
- seedPatchRequest(issue, req) {
- return req;
- },
+ return {
+ label_ids: labelIds,
+ };
+ },
+ /**
+ * Seed the given patch request.
+ *
+ * (This is overridden in EE)
+ */
+ seedPatchRequest(issue, req) {
+ return req;
},
- });
+ },
+});
</script>
<template>
- <div
- class="block list"
- >
- <button
- class="btn btn-default btn-block"
- type="button"
- @click="removeIssue"
- >
+ <div class="block list">
+ <button class="btn btn-default btn-block" type="button" @click="removeIssue">
Remove from board
</button>
</div>
diff --git a/app/assets/javascripts/boards/filtered_search_boards.js b/app/assets/javascripts/boards/filtered_search_boards.js
index 46d61ebbf24..c14d69c5d18 100644
--- a/app/assets/javascripts/boards/filtered_search_boards.js
+++ b/app/assets/javascripts/boards/filtered_search_boards.js
@@ -1,5 +1,6 @@
import FilteredSearchContainer from '../filtered_search/container';
import FilteredSearchManager from '../filtered_search/filtered_search_manager';
+import boardsStore from './stores/boards_store';
export default class FilteredSearchBoards extends FilteredSearchManager {
constructor(store, updateUrl = false, cantEdit = []) {
@@ -23,7 +24,7 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
this.store.path = path.substr(1);
if (this.updateUrl) {
- gl.issueBoards.BoardsStore.updateFiltersUrl();
+ boardsStore.updateFiltersUrl();
}
}
@@ -31,7 +32,7 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
const tokens = FilteredSearchContainer.container.querySelectorAll('.js-visual-token');
// Remove all the tokens as they will be replaced by the search manager
- [].forEach.call(tokens, (el) => {
+ [].forEach.call(tokens, el => {
el.parentNode.removeChild(el);
});
@@ -49,7 +50,10 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
canEdit(tokenName, tokenValue) {
if (this.cantEdit.includes(tokenName)) return false;
- return this.cantEditWithValue.findIndex(token => token.name === tokenName &&
- token.value === tokenValue) === -1;
+ return (
+ this.cantEditWithValue.findIndex(
+ token => token.name === tokenName && token.value === tokenValue,
+ ) === -1
+ );
}
}
diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js
index 8be99566f09..f88e9b55988 100644
--- a/app/assets/javascripts/boards/index.js
+++ b/app/assets/javascripts/boards/index.js
@@ -9,57 +9,62 @@ import '~/vue_shared/models/assignee';
import FilteredSearchBoards from './filtered_search_boards';
import eventHub from './eventhub';
-import sidebarEventHub from '~/sidebar/event_hub'; // eslint-disable-line import/first
+import sidebarEventHub from '~/sidebar/event_hub';
import './models/issue';
import './models/list';
import './models/milestone';
import './models/project';
-import './stores/boards_store';
+import boardsStore from './stores/boards_store';
import ModalStore from './stores/modal_store';
import BoardService from './services/board_service';
import modalMixin from './mixins/modal_mixins';
-import './mixins/sortable_default_options';
import './filters/due_date_filters';
-import './components/board';
-import './components/board_sidebar';
-import './components/new_list_dropdown';
+import Board from './components/board';
+import BoardSidebar from './components/board_sidebar';
+import initNewListDropdown from './components/new_list_dropdown';
import BoardAddIssuesModal from './components/modal/index.vue';
-import '~/vue_shared/vue_resource_interceptor'; // eslint-disable-line import/first
+import '~/vue_shared/vue_resource_interceptor';
+import { NavigationType, parseBoolean } from '~/lib/utils/common_utils';
+
+let issueBoardsApp;
export default () => {
const $boardApp = document.getElementById('board-app');
- const Store = gl.issueBoards.BoardsStore;
- window.gl = window.gl || {};
+ // check for browser back and trigger a hard reload to circumvent browser caching.
+ window.addEventListener('pageshow', event => {
+ const isNavTypeBackForward =
+ window.performance && window.performance.navigation.type === NavigationType.TYPE_BACK_FORWARD;
- if (gl.IssueBoardsApp) {
- gl.IssueBoardsApp.$destroy(true);
- }
+ if (event.persisted || isNavTypeBackForward) {
+ window.location.reload();
+ }
+ });
- Store.create();
+ if (issueBoardsApp) {
+ issueBoardsApp.$destroy(true);
+ }
- // hack to allow sidebar scripts like milestone_select manipulate the BoardsStore
- gl.issueBoards.boardStoreIssueSet = (...args) => Vue.set(Store.detail.issue, ...args);
- gl.issueBoards.boardStoreIssueDelete = (...args) => Vue.delete(Store.detail.issue, ...args);
+ boardsStore.create();
- gl.IssueBoardsApp = new Vue({
+ issueBoardsApp = new Vue({
el: $boardApp,
components: {
- board: gl.issueBoards.Board,
- 'board-sidebar': gl.issueBoards.BoardSidebar,
+ Board,
+ BoardSidebar,
BoardAddIssuesModal,
},
data: {
- state: Store.state,
+ state: boardsStore.state,
loading: true,
boardsEndpoint: $boardApp.dataset.boardsEndpoint,
listsEndpoint: $boardApp.dataset.listsEndpoint,
boardId: $boardApp.dataset.boardId,
- disabled: $boardApp.dataset.disabled === 'true',
+ disabled: parseBoolean($boardApp.dataset.disabled),
issueLinkBase: $boardApp.dataset.issueLinkBase,
rootPath: $boardApp.dataset.rootPath,
bulkUpdatePath: $boardApp.dataset.bulkUpdatePath,
- detailIssue: Store.detail,
+ detailIssue: boardsStore.detail,
defaultAvatar: $boardApp.dataset.defaultAvatar,
},
computed: {
@@ -74,7 +79,7 @@ export default () => {
bulkUpdatePath: this.bulkUpdatePath,
boardId: this.boardId,
});
- Store.rootPath = this.boardsEndpoint;
+ boardsStore.rootPath = this.boardsEndpoint;
eventHub.$on('updateTokens', this.updateTokens);
eventHub.$on('newDetailIssue', this.updateDetailIssue);
@@ -88,16 +93,16 @@ export default () => {
sidebarEventHub.$off('toggleSubscription', this.toggleSubscription);
},
mounted() {
- this.filterManager = new FilteredSearchBoards(Store.filter, true, Store.cantEdit);
+ this.filterManager = new FilteredSearchBoards(boardsStore.filter, true, boardsStore.cantEdit);
this.filterManager.setup();
- Store.disabled = this.disabled;
+ boardsStore.disabled = this.disabled;
gl.boardService
.all()
.then(res => res.data)
.then(data => {
data.forEach(board => {
- const list = Store.addList(board, this.defaultAvatar);
+ const list = boardsStore.addList(board, this.defaultAvatar);
if (list.type === 'closed') {
list.position = Infinity;
@@ -108,7 +113,7 @@ export default () => {
this.state.lists = _.sortBy(this.state.lists, 'position');
- Store.addBlankState();
+ boardsStore.addBlankState();
this.loading = false;
})
.catch(() => {
@@ -137,13 +142,13 @@ export default () => {
});
}
- Store.detail.issue = newIssue;
+ boardsStore.detail.issue = newIssue;
},
clearDetailIssue() {
- Store.detail.issue = {};
+ boardsStore.detail.issue = {};
},
toggleSubscription(id) {
- const { issue } = Store.detail;
+ const { issue } = boardsStore.detail;
if (issue.id === id && issue.toggleSubscriptionEndpoint) {
issue.setFetchingState('subscriptions', true);
BoardService.toggleIssueSubscription(issue.toggleSubscriptionEndpoint)
@@ -162,26 +167,28 @@ export default () => {
},
});
- gl.IssueBoardsSearch = new Vue({
+ // eslint-disable-next-line no-new
+ new Vue({
el: document.getElementById('js-add-list'),
data: {
- filters: Store.state.filters,
+ filters: boardsStore.state.filters,
},
mounted() {
- gl.issueBoards.newListDropdownInit();
+ initNewListDropdown();
},
});
const issueBoardsModal = document.getElementById('js-add-issues-btn');
if (issueBoardsModal) {
- gl.IssueBoardsModalAddBtn = new Vue({
+ // eslint-disable-next-line no-new
+ new Vue({
el: issueBoardsModal,
mixins: [modalMixin],
data() {
return {
modal: ModalStore.store,
- store: Store.state,
+ store: boardsStore.state,
canAdminList: this.$options.el.hasAttribute('data-can-admin-list'),
};
},
diff --git a/app/assets/javascripts/boards/mixins/sortable_default_options.js b/app/assets/javascripts/boards/mixins/sortable_default_options.js
index a8df45fc473..983b28d2e67 100644
--- a/app/assets/javascripts/boards/mixins/sortable_default_options.js
+++ b/app/assets/javascripts/boards/mixins/sortable_default_options.js
@@ -3,32 +3,33 @@
import $ from 'jquery';
import sortableConfig from '../../sortable/sortable_config';
-window.gl = window.gl || {};
-window.gl.issueBoards = window.gl.issueBoards || {};
-
-gl.issueBoards.onStart = () => {
- $('.has-tooltip').tooltip('hide')
+export function sortableStart() {
+ $('.has-tooltip')
+ .tooltip('hide')
.tooltip('disable');
document.body.classList.add('is-dragging');
-};
+}
-gl.issueBoards.onEnd = () => {
+export function sortableEnd() {
$('.has-tooltip').tooltip('enable');
document.body.classList.remove('is-dragging');
-};
+}
-gl.issueBoards.touchEnabled = ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch;
+export function getBoardSortableDefaultOptions(obj) {
+ const touchEnabled =
+ 'ontouchstart' in window || (window.DocumentTouch && document instanceof DocumentTouch);
-gl.issueBoards.getBoardSortableDefaultOptions = (obj) => {
const defaultSortOptions = Object.assign({}, sortableConfig, {
filter: '.board-delete, .btn',
- delay: gl.issueBoards.touchEnabled ? 100 : 0,
- scrollSensitivity: gl.issueBoards.touchEnabled ? 60 : 100,
+ delay: touchEnabled ? 100 : 0,
+ scrollSensitivity: touchEnabled ? 60 : 100,
scrollSpeed: 20,
- onStart: gl.issueBoards.onStart,
- onEnd: gl.issueBoards.onEnd,
+ onStart: sortableStart,
+ onEnd: sortableEnd,
});
- Object.keys(obj).forEach((key) => { defaultSortOptions[key] = obj[key]; });
+ Object.keys(obj).forEach(key => {
+ defaultSortOptions[key] = obj[key];
+ });
return defaultSortOptions;
-};
+}
diff --git a/app/assets/javascripts/boards/models/issue.js b/app/assets/javascripts/boards/models/issue.js
index c7cfb72067c..5e0f0b07247 100644
--- a/app/assets/javascripts/boards/models/issue.js
+++ b/app/assets/javascripts/boards/models/issue.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-unused-vars, comma-dangle */
+/* eslint-disable no-unused-vars */
/* global ListLabel */
/* global ListMilestone */
/* global ListAssignee */
@@ -6,9 +6,10 @@
import Vue from 'vue';
import '~/vue_shared/models/label';
import IssueProject from './project';
+import boardsStore from '../stores/boards_store';
class ListIssue {
- constructor (obj, defaultAvatar) {
+ constructor(obj, defaultAvatar) {
this.id = obj.id;
this.iid = obj.iid;
this.title = obj.title;
@@ -29,6 +30,8 @@ class ListIssue {
this.toggleSubscriptionEndpoint = obj.toggle_subscription_endpoint;
this.milestone_id = obj.milestone_id;
this.project_id = obj.project_id;
+ this.timeEstimate = obj.time_estimate;
+ this.assignableLabelsEndpoint = obj.assignable_labels_endpoint;
if (obj.project) {
this.project = new IssueProject(obj.project);
@@ -38,55 +41,55 @@ class ListIssue {
this.milestone = new ListMilestone(obj.milestone);
}
- obj.labels.forEach((label) => {
+ obj.labels.forEach(label => {
this.labels.push(new ListLabel(label));
});
this.assignees = obj.assignees.map(a => new ListAssignee(a, defaultAvatar));
}
- addLabel (label) {
+ addLabel(label) {
if (!this.findLabel(label)) {
this.labels.push(new ListLabel(label));
}
}
- findLabel (findLabel) {
+ findLabel(findLabel) {
return this.labels.filter(label => label.title === findLabel.title)[0];
}
- removeLabel (removeLabel) {
+ removeLabel(removeLabel) {
if (removeLabel) {
this.labels = this.labels.filter(label => removeLabel.title !== label.title);
}
}
- removeLabels (labels) {
+ removeLabels(labels) {
labels.forEach(this.removeLabel.bind(this));
}
- addAssignee (assignee) {
+ addAssignee(assignee) {
if (!this.findAssignee(assignee)) {
this.assignees.push(new ListAssignee(assignee));
}
}
- findAssignee (findAssignee) {
+ findAssignee(findAssignee) {
return this.assignees.filter(assignee => assignee.id === findAssignee.id)[0];
}
- removeAssignee (removeAssignee) {
+ removeAssignee(removeAssignee) {
if (removeAssignee) {
this.assignees = this.assignees.filter(assignee => assignee.id !== removeAssignee.id);
}
}
- removeAllAssignees () {
+ removeAllAssignees() {
this.assignees = [];
}
- getLists () {
- return gl.issueBoards.BoardsStore.state.lists.filter(list => list.findIssue(this.id));
+ getLists() {
+ return boardsStore.state.lists.filter(list => list.findIssue(this.id));
}
updateData(newData) {
@@ -101,14 +104,14 @@ class ListIssue {
this.isLoading[key] = value;
}
- update () {
+ update() {
const data = {
issue: {
milestone_id: this.milestone ? this.milestone.id : null,
due_date: this.dueDate,
- assignee_ids: this.assignees.length > 0 ? this.assignees.map((u) => u.id) : [0],
- label_ids: this.labels.map((label) => label.id)
- }
+ assignee_ids: this.assignees.length > 0 ? this.assignees.map(u => u.id) : [0],
+ label_ids: this.labels.map(label => label.id),
+ },
};
if (!data.issue.label_ids.length) {
diff --git a/app/assets/javascripts/boards/models/list.js b/app/assets/javascripts/boards/models/list.js
index d416b76f0f4..dd3feedbc0e 100644
--- a/app/assets/javascripts/boards/models/list.js
+++ b/app/assets/javascripts/boards/models/list.js
@@ -1,10 +1,11 @@
-/* eslint-disable no-underscore-dangle, class-methods-use-this, consistent-return, no-shadow, no-param-reassign, max-len */
+/* eslint-disable no-underscore-dangle, class-methods-use-this, consistent-return, no-shadow, no-param-reassign */
/* global ListIssue */
import { __ } from '~/locale';
import ListLabel from '~/vue_shared/models/label';
import ListAssignee from '~/vue_shared/models/assignee';
import { urlParamsToObject } from '~/lib/utils/common_utils';
+import boardsStore from '../stores/boards_store';
const PER_PAGE = 20;
@@ -89,9 +90,9 @@ class List {
}
destroy() {
- const index = gl.issueBoards.BoardsStore.state.lists.indexOf(this);
- gl.issueBoards.BoardsStore.state.lists.splice(index, 1);
- gl.issueBoards.BoardsStore.updateNewListDropdown(this.id);
+ const index = boardsStore.state.lists.indexOf(this);
+ boardsStore.state.lists.splice(index, 1);
+ boardsStore.updateNewListDropdown(this.id);
gl.boardService.destroyList(this.id).catch(() => {
// TODO: handle request error
@@ -116,7 +117,7 @@ class List {
getIssues(emptyIssues = true) {
const data = {
- ...urlParamsToObject(gl.issueBoards.BoardsStore.filter.path),
+ ...urlParamsToObject(boardsStore.filter.path),
page: this.page,
};
@@ -233,11 +234,11 @@ class List {
});
}
- getTypeInfo (type) {
+ getTypeInfo(type) {
return TYPES[type] || {};
}
- onNewIssueResponse (issue, data) {
+ onNewIssueResponse(issue, data) {
issue.id = data.id;
issue.iid = data.iid;
issue.project = data.project;
diff --git a/app/assets/javascripts/boards/services/board_service.js b/app/assets/javascripts/boards/services/board_service.js
index 029b0971f2c..3de6eb056c2 100644
--- a/app/assets/javascripts/boards/services/board_service.js
+++ b/app/assets/javascripts/boards/services/board_service.js
@@ -19,7 +19,9 @@ export default class BoardService {
}
static generateIssuePath(boardId, id) {
- return `${gon.relative_url_root}/-/boards/${boardId ? `${boardId}` : ''}/issues${id ? `/${id}` : ''}`;
+ return `${gon.relative_url_root}/-/boards/${boardId ? `${boardId}` : ''}/issues${
+ id ? `/${id}` : ''
+ }`;
}
all() {
@@ -54,7 +56,9 @@ export default class BoardService {
getIssuesForList(id, filter = {}) {
const data = { id };
- Object.keys(filter).forEach((key) => { data[key] = filter[key]; });
+ Object.keys(filter).forEach(key => {
+ data[key] = filter[key];
+ });
return axios.get(mergeUrlParams(data, this.generateIssuesPath(id)));
}
@@ -75,7 +79,9 @@ export default class BoardService {
}
getBacklog(data) {
- return axios.get(mergeUrlParams(data, `${gon.relative_url_root}/-/boards/${this.boardId}/issues.json`));
+ return axios.get(
+ mergeUrlParams(data, `${gon.relative_url_root}/-/boards/${this.boardId}/issues.json`),
+ );
}
bulkUpdate(issueIds, extraData = {}) {
diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js
index 957114cf420..cf88a973d33 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js
+++ b/app/assets/javascripts/boards/stores/boards_store.js
@@ -1,15 +1,13 @@
-/* eslint-disable comma-dangle, no-shadow */
+/* eslint-disable no-shadow */
/* global List */
import $ from 'jquery';
import _ from 'underscore';
+import Vue from 'vue';
import Cookies from 'js-cookie';
-import { getUrlParamsArray } from '~/lib/utils/common_utils';
+import { getUrlParamsArray, parseBoolean } from '~/lib/utils/common_utils';
-window.gl = window.gl || {};
-window.gl.issueBoards = window.gl.issueBoards || {};
-
-gl.issueBoards.BoardsStore = {
+const boardsStore = {
disabled: false,
filter: {
path: '',
@@ -22,20 +20,20 @@ gl.issueBoards.BoardsStore = {
issue: {},
list: {},
},
- create () {
+ create() {
this.state.lists = [];
this.filter.path = getUrlParamsArray().join('&');
this.detail = {
issue: {},
};
},
- addList (listObj, defaultAvatar) {
+ addList(listObj, defaultAvatar) {
const list = new List(listObj, defaultAvatar);
this.state.lists.push(list);
return list;
},
- new (listObj) {
+ new(listObj) {
const list = this.addList(listObj);
const backlogList = this.findList('type', 'backlog', 'backlog');
@@ -52,44 +50,44 @@ gl.issueBoards.BoardsStore = {
});
this.removeBlankState();
},
- updateNewListDropdown (listId) {
+ updateNewListDropdown(listId) {
$(`.js-board-list-${listId}`).removeClass('is-active');
},
- shouldAddBlankState () {
+ shouldAddBlankState() {
// Decide whether to add the blank state
- return !(this.state.lists.filter(list => list.type !== 'backlog' && list.type !== 'closed')[0]);
+ return !this.state.lists.filter(list => list.type !== 'backlog' && list.type !== 'closed')[0];
},
- addBlankState () {
+ addBlankState() {
if (!this.shouldAddBlankState() || this.welcomeIsHidden() || this.disabled) return;
this.addList({
id: 'blank',
list_type: 'blank',
title: 'Welcome to your Issue Board!',
- position: 0
+ position: 0,
});
this.state.lists = _.sortBy(this.state.lists, 'position');
},
- removeBlankState () {
+ removeBlankState() {
this.removeList('blank');
Cookies.set('issue_board_welcome_hidden', 'true', {
expires: 365 * 10,
- path: ''
+ path: '',
});
},
- welcomeIsHidden () {
- return Cookies.get('issue_board_welcome_hidden') === 'true';
+ welcomeIsHidden() {
+ return parseBoolean(Cookies.get('issue_board_welcome_hidden'));
},
- removeList (id, type = 'blank') {
+ removeList(id, type = 'blank') {
const list = this.findList('id', id, type);
if (!list) return;
this.state.lists = this.state.lists.filter(list => list.id !== id);
},
- moveList (listFrom, orderLists) {
+ moveList(listFrom, orderLists) {
orderLists.forEach((id, i) => {
const list = this.findList('id', parseInt(id, 10));
@@ -97,22 +95,25 @@ gl.issueBoards.BoardsStore = {
});
listFrom.update();
},
- moveIssueToList (listFrom, listTo, issue, newIndex) {
+ moveIssueToList(listFrom, listTo, issue, newIndex) {
const issueTo = listTo.findIssue(issue.id);
const issueLists = issue.getLists();
const listLabels = issueLists.map(listIssue => listIssue.label);
if (!issueTo) {
// Check if target list assignee is already present in this issue
- if ((listTo.type === 'assignee' && listFrom.type === 'assignee') &&
- issue.findAssignee(listTo.assignee)) {
+ if (
+ listTo.type === 'assignee' &&
+ listFrom.type === 'assignee' &&
+ issue.findAssignee(listTo.assignee)
+ ) {
const targetIssue = listTo.findIssue(issue.id);
targetIssue.removeAssignee(listFrom.assignee);
} else if (listTo.type === 'milestone') {
const currentMilestone = issue.milestone;
const currentLists = this.state.lists
- .filter(list => (list.type === 'milestone' && list.id !== listTo.id))
- .filter(list => list.issues.some(listIssue => issue.id === listIssue.id));
+ .filter(list => list.type === 'milestone' && list.id !== listTo.id)
+ .filter(list => list.issues.some(listIssue => issue.id === listIssue.id));
issue.removeMilestone(currentMilestone);
issue.addMilestone(listTo.milestone);
@@ -128,7 +129,7 @@ gl.issueBoards.BoardsStore = {
}
if (listTo.type === 'closed' && listFrom.type !== 'backlog') {
- issueLists.forEach((list) => {
+ issueLists.forEach(list => {
list.removeIssue(issue);
});
issue.removeLabels(listLabels);
@@ -146,24 +147,39 @@ gl.issueBoards.BoardsStore = {
return (
(listTo.type !== 'label' && listFrom.type === 'assignee') ||
(listTo.type !== 'assignee' && listFrom.type === 'label') ||
- (listFrom.type === 'backlog')
+ listFrom.type === 'backlog'
);
},
- moveIssueInList (list, issue, oldIndex, newIndex, idArray) {
+ moveIssueInList(list, issue, oldIndex, newIndex, idArray) {
const beforeId = parseInt(idArray[newIndex - 1], 10) || null;
const afterId = parseInt(idArray[newIndex + 1], 10) || null;
list.moveIssue(issue, oldIndex, newIndex, beforeId, afterId);
},
- findList (key, val, type = 'label') {
- const filteredList = this.state.lists.filter((list) => {
- const byType = type ? (list.type === type) || (list.type === 'assignee') || (list.type === 'milestone') : true;
+ findList(key, val, type = 'label') {
+ const filteredList = this.state.lists.filter(list => {
+ const byType = type
+ ? list.type === type || list.type === 'assignee' || list.type === 'milestone'
+ : true;
return list[key] === val && byType;
});
return filteredList[0];
},
- updateFiltersUrl () {
+ updateFiltersUrl() {
window.history.pushState(null, null, `?${this.filter.path}`);
- }
+ },
};
+
+// hacks added in order to allow milestone_select to function properly
+// TODO: remove these
+
+export function boardStoreIssueSet(...args) {
+ Vue.set(boardsStore.detail.issue, ...args);
+}
+
+export function boardStoreIssueDelete(...args) {
+ Vue.delete(boardsStore.detail.issue, ...args);
+}
+
+export default boardsStore;
diff --git a/app/assets/javascripts/boards/stores/modal_store.js b/app/assets/javascripts/boards/stores/modal_store.js
index 0d9ac367a70..b7228bf7bf5 100644
--- a/app/assets/javascripts/boards/stores/modal_store.js
+++ b/app/assets/javascripts/boards/stores/modal_store.js
@@ -40,7 +40,7 @@ class ModalStore {
toggleAll() {
const select = this.selectedCount() !== this.store.issues.length;
- this.store.issues.forEach((issue) => {
+ this.store.issues.forEach(issue => {
const issueUpdate = issue;
if (issueUpdate.selected !== select) {
@@ -69,13 +69,14 @@ class ModalStore {
removeSelectedIssue(issue, forcePurge = false) {
if (this.store.activeTab === 'all' || forcePurge) {
- this.store.selectedIssues = this.store.selectedIssues
- .filter(fIssue => fIssue.id !== issue.id);
+ this.store.selectedIssues = this.store.selectedIssues.filter(
+ fIssue => fIssue.id !== issue.id,
+ );
}
}
purgeUnselectedIssues() {
- this.store.selectedIssues.forEach((issue) => {
+ this.store.selectedIssues.forEach(issue => {
if (!issue.selected) {
this.removeSelectedIssue(issue, true);
}
@@ -87,8 +88,7 @@ class ModalStore {
}
findSelectedIssue(issue) {
- return this.store.selectedIssues
- .filter(filteredIssue => filteredIssue.id === issue.id)[0];
+ return this.store.selectedIssues.filter(filteredIssue => filteredIssue.id === issue.id)[0];
}
}
diff --git a/app/assets/javascripts/breadcrumb.js b/app/assets/javascripts/breadcrumb.js
index 1474d93dde6..a37838694ec 100644
--- a/app/assets/javascripts/breadcrumb.js
+++ b/app/assets/javascripts/breadcrumb.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
-export const addTooltipToEl = (el) => {
+export const addTooltipToEl = el => {
const textEl = el.querySelector('.js-breadcrumb-item-text');
if (textEl && textEl.scrollWidth > textEl.offsetWidth) {
@@ -14,17 +14,18 @@ export default () => {
const breadcrumbs = document.querySelector('.js-breadcrumbs-list');
if (breadcrumbs) {
- const topLevelLinks = [...breadcrumbs.children].filter(el => !el.classList.contains('dropdown'))
+ const topLevelLinks = [...breadcrumbs.children]
+ .filter(el => !el.classList.contains('dropdown'))
.map(el => el.querySelector('a'))
.filter(el => el);
const $expander = $('.js-breadcrumbs-collapsed-expander');
topLevelLinks.forEach(el => addTooltipToEl(el));
- $expander.closest('.dropdown')
- .on('show.bs.dropdown hide.bs.dropdown', (e) => {
- $('.js-breadcrumbs-collapsed-expander', e.currentTarget).toggleClass('open')
- .tooltip('hide');
- });
+ $expander.closest('.dropdown').on('show.bs.dropdown hide.bs.dropdown', e => {
+ $('.js-breadcrumbs-collapsed-expander', e.currentTarget)
+ .toggleClass('open')
+ .tooltip('hide');
+ });
}
};
diff --git a/app/assets/javascripts/build_artifacts.js b/app/assets/javascripts/build_artifacts.js
index e338376fcaa..b2c88e8c14e 100644
--- a/app/assets/javascripts/build_artifacts.js
+++ b/app/assets/javascripts/build_artifacts.js
@@ -2,7 +2,7 @@
import $ from 'jquery';
import { visitUrl } from './lib/utils/url_utility';
-import { convertPermissionToBoolean } from './lib/utils/common_utils';
+import { parseBoolean } from './lib/utils/common_utils';
export default class BuildArtifacts {
constructor() {
@@ -12,17 +12,17 @@ export default class BuildArtifacts {
}
// eslint-disable-next-line class-methods-use-this
disablePropagation() {
- $('.top-block').on('click', '.download', function (e) {
+ $('.top-block').on('click', '.download', function(e) {
return e.stopPropagation();
});
- return $('.tree-holder').on('click', 'tr[data-link] a', function (e) {
+ return $('.tree-holder').on('click', 'tr[data-link] a', function(e) {
return e.stopImmediatePropagation();
});
}
// eslint-disable-next-line class-methods-use-this
setupEntryClick() {
- return $('.tree-holder').on('click', 'tr[data-link]', function () {
- visitUrl(this.dataset.link, convertPermissionToBoolean(this.dataset.externalLink));
+ return $('.tree-holder').on('click', 'tr[data-link]', function() {
+ visitUrl(this.dataset.link, parseBoolean(this.dataset.externalLink));
});
}
// eslint-disable-next-line class-methods-use-this
@@ -37,11 +37,15 @@ export default class BuildArtifacts {
// We want the tooltip to show if you hover anywhere on the row
// But be placed below and in the middle of the file name
$('.js-artifact-tree-row')
- .on('mouseenter', (e) => {
- $(e.currentTarget).find('.js-artifact-tree-tooltip').tooltip('show');
+ .on('mouseenter', e => {
+ $(e.currentTarget)
+ .find('.js-artifact-tree-tooltip')
+ .tooltip('show');
})
- .on('mouseleave', (e) => {
- $(e.currentTarget).find('.js-artifact-tree-tooltip').tooltip('hide');
+ .on('mouseleave', e => {
+ $(e.currentTarget)
+ .find('.js-artifact-tree-tooltip')
+ .tooltip('hide');
});
}
}
diff --git a/app/assets/javascripts/build_variables.js b/app/assets/javascripts/build_variables.js
deleted file mode 100644
index d398e4a4c83..00000000000
--- a/app/assets/javascripts/build_variables.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import $ from 'jquery';
-
-export default function handleRevealVariables() {
- $('.js-reveal-variables')
- .off('click')
- .on('click', function click() {
- $('.js-build-variables').toggle();
- $(this).hide();
- });
-}
diff --git a/app/assets/javascripts/ci_variable_list/ajax_variable_list.js b/app/assets/javascripts/ci_variable_list/ajax_variable_list.js
index b33adff609f..592e1fd1c31 100644
--- a/app/assets/javascripts/ci_variable_list/ajax_variable_list.js
+++ b/app/assets/javascripts/ci_variable_list/ajax_variable_list.js
@@ -2,16 +2,18 @@ import _ from 'underscore';
import axios from '../lib/utils/axios_utils';
import { s__ } from '../locale';
import Flash from '../flash';
-import { convertPermissionToBoolean } from '../lib/utils/common_utils';
+import { parseBoolean } from '../lib/utils/common_utils';
import statusCodes from '../lib/utils/http_status';
import VariableList from './ci_variable_list';
function generateErrorBoxContent(errors) {
- const errorList = [].concat(errors).map(errorString => `
+ const errorList = [].concat(errors).map(
+ errorString => `
<li>
${_.escape(errorString)}
</li>
- `);
+ `,
+ );
return `
<p>
@@ -25,13 +27,7 @@ function generateErrorBoxContent(errors) {
// Used for the variable list on CI/CD projects/groups settings page
export default class AjaxVariableList {
- constructor({
- container,
- saveButton,
- errorBox,
- formField = 'variables',
- saveEndpoint,
- }) {
+ constructor({ container, saveButton, errorBox, formField = 'variables', saveEndpoint }) {
this.container = container;
this.saveButton = saveButton;
this.errorBox = errorBox;
@@ -51,25 +47,28 @@ export default class AjaxVariableList {
}
onSaveClicked() {
- const loadingIcon = this.saveButton.querySelector('.js-secret-variables-save-loading-icon');
+ const loadingIcon = this.saveButton.querySelector('.js-ci-variables-save-loading-icon');
loadingIcon.classList.toggle('hide', false);
this.errorBox.classList.toggle('hide', true);
// We use this to prevent a user from changing a key before we have a chance
// to match it up in `updateRowsWithPersistedVariables`
this.variableList.toggleEnableRow(false);
- return axios.patch(this.saveEndpoint, {
- variables_attributes: this.variableList.getAllData(),
- }, {
- // We want to be able to process the `res.data` from a 400 error response
- // and print the validation messages such as duplicate variable keys
- validateStatus: status => (
- status >= statusCodes.OK &&
- status < statusCodes.MULTIPLE_CHOICES
- ) ||
- status === statusCodes.BAD_REQUEST,
- })
- .then((res) => {
+ return axios
+ .patch(
+ this.saveEndpoint,
+ {
+ variables_attributes: this.variableList.getAllData(),
+ },
+ {
+ // We want to be able to process the `res.data` from a 400 error response
+ // and print the validation messages such as duplicate variable keys
+ validateStatus: status =>
+ (status >= statusCodes.OK && status < statusCodes.MULTIPLE_CHOICES) ||
+ status === statusCodes.BAD_REQUEST,
+ },
+ )
+ .then(res => {
loadingIcon.classList.toggle('hide', true);
this.variableList.toggleEnableRow(true);
@@ -85,23 +84,26 @@ export default class AjaxVariableList {
.catch(() => {
loadingIcon.classList.toggle('hide', true);
this.variableList.toggleEnableRow(true);
- Flash(s__('CiVariable|Error occured while saving variables'));
+ Flash(s__('CiVariable|Error occurred while saving variables'));
});
}
updateRowsWithPersistedVariables(persistedVariables = []) {
- const persistedVariableMap = [].concat(persistedVariables).reduce((variableMap, variable) => ({
- ...variableMap,
- [variable.key]: variable,
- }), {});
+ const persistedVariableMap = [].concat(persistedVariables).reduce(
+ (variableMap, variable) => ({
+ ...variableMap,
+ [variable.key]: variable,
+ }),
+ {},
+ );
- this.container.querySelectorAll('.js-row').forEach((row) => {
+ this.container.querySelectorAll('.js-row').forEach(row => {
// If we submitted a row that was destroyed, remove it so we don't try
// to destroy it again which would cause a BE error
const destroyInput = row.querySelector('.js-ci-variable-input-destroy');
- if (convertPermissionToBoolean(destroyInput.value)) {
+ if (parseBoolean(destroyInput.value)) {
row.remove();
- // Update the ID input so any future edits and `_destroy` will apply on the BE
+ // Update the ID input so any future edits and `_destroy` will apply on the BE
} else {
const key = row.querySelector('.js-ci-variable-input-key').value;
const persistedVariable = persistedVariableMap[key];
diff --git a/app/assets/javascripts/ci_variable_list/ci_variable_list.js b/app/assets/javascripts/ci_variable_list/ci_variable_list.js
index 47efb3a8cee..ee0f7cda189 100644
--- a/app/assets/javascripts/ci_variable_list/ci_variable_list.js
+++ b/app/assets/javascripts/ci_variable_list/ci_variable_list.js
@@ -1,5 +1,5 @@
import $ from 'jquery';
-import { convertPermissionToBoolean } from '../lib/utils/common_utils';
+import { parseBoolean } from '../lib/utils/common_utils';
import { s__ } from '../locale';
import setupToggleButtons from '../toggle_buttons';
import CreateItemDropdown from '../create_item_dropdown';
@@ -16,10 +16,7 @@ function createEnvironmentItem(value) {
}
export default class VariableList {
- constructor({
- container,
- formField,
- }) {
+ constructor({ container, formField }) {
this.$container = $(container);
this.formField = formField;
this.environmentDropdownMap = new WeakMap();
@@ -71,7 +68,7 @@ export default class VariableList {
this.initRow(rowEl);
});
- this.$container.on('click', '.js-row-remove-button', (e) => {
+ this.$container.on('click', '.js-row-remove-button', e => {
e.preventDefault();
this.removeRow($(e.currentTarget).closest('.js-row'));
});
@@ -81,7 +78,7 @@ export default class VariableList {
.join(',');
// Remove any empty rows except the last row
- this.$container.on('blur', inputSelector, (e) => {
+ this.$container.on('blur', inputSelector, e => {
const $row = $(e.currentTarget).closest('.js-row');
if ($row.is(':not(:last-child)') && !this.checkIfRowTouched($row)) {
@@ -136,7 +133,7 @@ export default class VariableList {
$rowClone.removeAttr('data-is-persisted');
// Reset the inputs to their defaults
- Object.keys(this.inputMap).forEach((name) => {
+ Object.keys(this.inputMap).forEach(name => {
const entry = this.inputMap[name];
$rowClone.find(entry.selector).val(entry.default);
});
@@ -153,7 +150,7 @@ export default class VariableList {
removeRow(row) {
const $row = $(row);
- const isPersisted = convertPermissionToBoolean($row.attr('data-is-persisted'));
+ const isPersisted = parseBoolean($row.attr('data-is-persisted'));
if (isPersisted) {
$row.hide();
@@ -171,7 +168,7 @@ export default class VariableList {
}
checkIfRowTouched($row) {
- return Object.keys(this.inputMap).some((name) => {
+ return Object.keys(this.inputMap).some(name => {
const entry = this.inputMap[name];
const $el = $row.find(entry.selector);
return $el.length && $el.val() !== entry.default;
@@ -190,11 +187,14 @@ export default class VariableList {
getAllData() {
// Ignore the last empty row because we don't want to try persist
// a blank variable and run into validation problems.
- const validRows = this.$container.find('.js-row').toArray().slice(0, -1);
+ const validRows = this.$container
+ .find('.js-row')
+ .toArray()
+ .slice(0, -1);
- return validRows.map((rowEl) => {
+ return validRows.map(rowEl => {
const resultant = {};
- Object.keys(this.inputMap).forEach((name) => {
+ Object.keys(this.inputMap).forEach(name => {
const entry = this.inputMap[name];
const $input = $(rowEl).find(entry.selector);
if ($input.length) {
@@ -207,11 +207,16 @@ export default class VariableList {
}
getEnvironmentValues() {
- const valueMap = this.$container.find(this.inputMap.environment_scope.selector).toArray()
- .reduce((prevValueMap, envInput) => ({
- ...prevValueMap,
- [envInput.value]: envInput.value,
- }), {});
+ const valueMap = this.$container
+ .find(this.inputMap.environment_scope.selector)
+ .toArray()
+ .reduce(
+ (prevValueMap, envInput) => ({
+ ...prevValueMap,
+ [envInput.value]: envInput.value,
+ }),
+ {},
+ );
return Object.keys(valueMap).map(createEnvironmentItem);
}
diff --git a/app/assets/javascripts/ci_variable_list/native_form_variable_list.js b/app/assets/javascripts/ci_variable_list/native_form_variable_list.js
index 7cd5916ac9c..e7111c666a2 100644
--- a/app/assets/javascripts/ci_variable_list/native_form_variable_list.js
+++ b/app/assets/javascripts/ci_variable_list/native_form_variable_list.js
@@ -2,10 +2,7 @@ import $ from 'jquery';
import VariableList from './ci_variable_list';
// Used for the variable list on scheduled pipeline edit page
-export default function setupNativeFormVariableList({
- container,
- formField = 'variables',
-}) {
+export default function setupNativeFormVariableList({ container, formField = 'variables' }) {
const $container = $(container);
const variableList = new VariableList({
diff --git a/app/assets/javascripts/clusters/clusters_bundle.js b/app/assets/javascripts/clusters/clusters_bundle.js
index ebf76af5966..aff32d95db1 100644
--- a/app/assets/javascripts/clusters/clusters_bundle.js
+++ b/app/assets/javascripts/clusters/clusters_bundle.js
@@ -1,6 +1,6 @@
import Visibility from 'visibilityjs';
import Vue from 'vue';
-import initDismissableCallout from '~/dismissable_callout';
+import PersistentUserCallout from '../persistent_user_callout';
import { s__, sprintf } from '../locale';
import Flash from '../flash';
import Poll from '../lib/utils/poll';
@@ -9,7 +9,7 @@ import eventHub from './event_hub';
import { APPLICATION_STATUS, REQUEST_LOADING, REQUEST_SUCCESS, REQUEST_FAILURE } from './constants';
import ClustersService from './services/clusters_service';
import ClustersStore from './stores/clusters_store';
-import applications from './components/applications.vue';
+import Applications from './components/applications.vue';
import setupToggleButtons from '../toggle_buttons';
/**
@@ -26,10 +26,13 @@ export default class Clusters {
statusPath,
installHelmPath,
installIngressPath,
+ installCertManagerPath,
installRunnerPath,
installJupyterPath,
+ installKnativePath,
installPrometheusPath,
managePrometheusPath,
+ clusterType,
clusterStatus,
clusterStatusReason,
helpPath,
@@ -46,9 +49,11 @@ export default class Clusters {
endpoint: statusPath,
installHelmEndpoint: installHelmPath,
installIngressEndpoint: installIngressPath,
+ installCertManagerEndpoint: installCertManagerPath,
installRunnerEndpoint: installRunnerPath,
installPrometheusEndpoint: installPrometheusPath,
installJupyterEndpoint: installJupyterPath,
+ installKnativeEndpoint: installKnativePath,
});
this.installApplication = this.installApplication.bind(this);
@@ -62,10 +67,10 @@ export default class Clusters {
this.showTokenButton = document.querySelector('.js-show-cluster-token');
this.tokenField = document.querySelector('.js-cluster-token');
- initDismissableCallout('.js-cluster-security-warning');
+ Clusters.initDismissableCallout();
initSettingsPanels();
setupToggleButtons(document.querySelector('.js-cluster-enable-toggle-area'));
- this.initApplications();
+ this.initApplications(clusterType);
if (this.store.state.status !== 'created') {
this.updateContainer(null, this.store.state.status, this.store.state.statusReason);
@@ -77,23 +82,21 @@ export default class Clusters {
}
}
- initApplications() {
+ initApplications(type) {
const { store } = this;
const el = document.querySelector('#js-cluster-applications');
this.applications = new Vue({
el,
- components: {
- applications,
- },
data() {
return {
state: store.state,
};
},
render(createElement) {
- return createElement('applications', {
+ return createElement(Applications, {
props: {
+ type,
applications: this.state.applications,
helpPath: this.state.helpPath,
ingressHelpPath: this.state.ingressHelpPath,
@@ -105,6 +108,12 @@ export default class Clusters {
});
}
+ static initDismissableCallout() {
+ const callout = document.querySelector('.js-cluster-security-warning');
+
+ if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new
+ }
+
addListeners() {
if (this.showTokenButton) this.showTokenButton.addEventListener('click', this.showToken);
eventHub.$on('installApplication', this.installApplication);
diff --git a/app/assets/javascripts/clusters/clusters_index.js b/app/assets/javascripts/clusters/clusters_index.js
deleted file mode 100644
index 789c8360124..00000000000
--- a/app/assets/javascripts/clusters/clusters_index.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import createFlash from '~/flash';
-import { __ } from '~/locale';
-import setupToggleButtons from '~/toggle_buttons';
-import initDismissableCallout from '~/dismissable_callout';
-
-import ClustersService from './services/clusters_service';
-
-export default () => {
- const clusterList = document.querySelector('.js-clusters-list');
-
- initDismissableCallout('.gcp-signup-offer');
-
- // The empty state won't have a clusterList
- if (clusterList) {
- setupToggleButtons(document.querySelector('.js-clusters-list'), (value, toggle) =>
- ClustersService.updateCluster(toggle.dataset.endpoint, { cluster: { enabled: value } }).catch(
- err => {
- createFlash(__('Something went wrong on our end.'));
- throw err;
- },
- ),
- );
- }
-};
diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue
index 0452729d3ff..d4354dcfebd 100644
--- a/app/assets/javascripts/clusters/components/application_row.vue
+++ b/app/assets/javascripts/clusters/components/application_row.vue
@@ -1,153 +1,162 @@
<script>
- /* eslint-disable vue/require-default-prop */
- import { s__, sprintf } from '../../locale';
- import eventHub from '../event_hub';
- import identicon from '../../vue_shared/components/identicon.vue';
- import loadingButton from '../../vue_shared/components/loading_button.vue';
- import {
- APPLICATION_STATUS,
- REQUEST_LOADING,
- REQUEST_SUCCESS,
- REQUEST_FAILURE,
- } from '../constants';
+/* eslint-disable vue/require-default-prop */
+import { s__, sprintf } from '../../locale';
+import eventHub from '../event_hub';
+import identicon from '../../vue_shared/components/identicon.vue';
+import loadingButton from '../../vue_shared/components/loading_button.vue';
+import {
+ APPLICATION_STATUS,
+ REQUEST_LOADING,
+ REQUEST_SUCCESS,
+ REQUEST_FAILURE,
+} from '../constants';
- export default {
- components: {
- loadingButton,
- identicon,
+export default {
+ components: {
+ loadingButton,
+ identicon,
+ },
+ props: {
+ id: {
+ type: String,
+ required: true,
},
- props: {
- id: {
- type: String,
- required: true,
- },
- title: {
- type: String,
- required: true,
- },
- titleLink: {
- type: String,
- required: false,
- },
- manageLink: {
- type: String,
- required: false,
- },
- logoUrl: {
- type: String,
- required: false,
- default: null,
- },
- disabled: {
- type: Boolean,
- required: false,
- default: false,
- },
- status: {
- type: String,
- required: false,
- },
- statusReason: {
- type: String,
- required: false,
- },
- requestStatus: {
- type: String,
- required: false,
- },
- requestReason: {
- type: String,
- required: false,
- },
- installApplicationRequestParams: {
- type: Object,
- required: false,
- default: () => ({}),
- },
+ title: {
+ type: String,
+ required: true,
},
- computed: {
- isUnknownStatus() {
- return !this.isKnownStatus && this.status !== null;
- },
- isKnownStatus() {
- return Object.values(APPLICATION_STATUS).includes(this.status);
- },
- isInstalled() {
- return (
- this.status === APPLICATION_STATUS.INSTALLED || this.status === APPLICATION_STATUS.UPDATED
- );
- },
- hasLogo() {
- return !!this.logoUrl;
- },
- identiconId() {
- // generate a deterministic integer id for the identicon background
- return this.id.charCodeAt(0);
- },
- rowJsClass() {
- return `js-cluster-application-row-${this.id}`;
- },
- installButtonLoading() {
- return !this.status ||
- this.status === APPLICATION_STATUS.SCHEDULED ||
- this.status === APPLICATION_STATUS.INSTALLING ||
- this.requestStatus === REQUEST_LOADING;
- },
- installButtonDisabled() {
- // Avoid the potential for the real-time data to say APPLICATION_STATUS.INSTALLABLE but
- // we already made a request to install and are just waiting for the real-time
- // to sync up.
- return ((this.status !== APPLICATION_STATUS.INSTALLABLE
- && this.status !== APPLICATION_STATUS.ERROR) ||
+ titleLink: {
+ type: String,
+ required: false,
+ },
+ manageLink: {
+ type: String,
+ required: false,
+ },
+ logoUrl: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ disabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ status: {
+ type: String,
+ required: false,
+ },
+ statusReason: {
+ type: String,
+ required: false,
+ },
+ requestStatus: {
+ type: String,
+ required: false,
+ },
+ requestReason: {
+ type: String,
+ required: false,
+ },
+ installApplicationRequestParams: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ },
+ computed: {
+ isUnknownStatus() {
+ return !this.isKnownStatus && this.status !== null;
+ },
+ isKnownStatus() {
+ return Object.values(APPLICATION_STATUS).includes(this.status);
+ },
+ isInstalled() {
+ return (
+ this.status === APPLICATION_STATUS.INSTALLED ||
+ this.status === APPLICATION_STATUS.UPDATED ||
+ this.status === APPLICATION_STATUS.UPDATING
+ );
+ },
+ hasLogo() {
+ return !!this.logoUrl;
+ },
+ identiconId() {
+ // generate a deterministic integer id for the identicon background
+ return this.id.charCodeAt(0);
+ },
+ rowJsClass() {
+ return `js-cluster-application-row-${this.id}`;
+ },
+ installButtonLoading() {
+ return (
+ !this.status ||
+ this.status === APPLICATION_STATUS.SCHEDULED ||
+ this.status === APPLICATION_STATUS.INSTALLING ||
+ this.requestStatus === REQUEST_LOADING
+ );
+ },
+ installButtonDisabled() {
+ // Avoid the potential for the real-time data to say APPLICATION_STATUS.INSTALLABLE but
+ // we already made a request to install and are just waiting for the real-time
+ // to sync up.
+ return (
+ ((this.status !== APPLICATION_STATUS.INSTALLABLE &&
+ this.status !== APPLICATION_STATUS.ERROR) ||
this.requestStatus === REQUEST_LOADING ||
- this.requestStatus === REQUEST_SUCCESS) && this.isKnownStatus;
- },
- installButtonLabel() {
- let label;
- if (
- this.status === APPLICATION_STATUS.NOT_INSTALLABLE ||
- this.status === APPLICATION_STATUS.INSTALLABLE ||
- this.status === APPLICATION_STATUS.ERROR ||
- this.isUnknownStatus
- ) {
- label = s__('ClusterIntegration|Install');
- } else if (this.status === APPLICATION_STATUS.SCHEDULED ||
- this.status === APPLICATION_STATUS.INSTALLING) {
- label = s__('ClusterIntegration|Installing');
- } else if (this.status === APPLICATION_STATUS.INSTALLED ||
- this.status === APPLICATION_STATUS.UPDATED) {
- label = s__('ClusterIntegration|Installed');
- }
+ this.requestStatus === REQUEST_SUCCESS) &&
+ this.isKnownStatus
+ );
+ },
+ installButtonLabel() {
+ let label;
+ if (
+ this.status === APPLICATION_STATUS.NOT_INSTALLABLE ||
+ this.status === APPLICATION_STATUS.INSTALLABLE ||
+ this.status === APPLICATION_STATUS.ERROR ||
+ this.isUnknownStatus
+ ) {
+ label = s__('ClusterIntegration|Install');
+ } else if (
+ this.status === APPLICATION_STATUS.SCHEDULED ||
+ this.status === APPLICATION_STATUS.INSTALLING
+ ) {
+ label = s__('ClusterIntegration|Installing');
+ } else if (
+ this.status === APPLICATION_STATUS.INSTALLED ||
+ this.status === APPLICATION_STATUS.UPDATED ||
+ this.status === APPLICATION_STATUS.UPDATING
+ ) {
+ label = s__('ClusterIntegration|Installed');
+ }
- return label;
- },
- showManageButton() {
- return this.manageLink && this.status === APPLICATION_STATUS.INSTALLED;
- },
- manageButtonLabel() {
- return s__('ClusterIntegration|Manage');
- },
- hasError() {
- return this.status === APPLICATION_STATUS.ERROR ||
- this.requestStatus === REQUEST_FAILURE;
- },
- generalErrorDescription() {
- return sprintf(
- s__('ClusterIntegration|Something went wrong while installing %{title}'), {
- title: this.title,
- },
- );
- },
+ return label;
+ },
+ showManageButton() {
+ return this.manageLink && this.status === APPLICATION_STATUS.INSTALLED;
},
- methods: {
- installClicked() {
- eventHub.$emit('installApplication', {
- id: this.id,
- params: this.installApplicationRequestParams,
- });
- },
+ manageButtonLabel() {
+ return s__('ClusterIntegration|Manage');
},
- };
+ hasError() {
+ return this.status === APPLICATION_STATUS.ERROR || this.requestStatus === REQUEST_FAILURE;
+ },
+ generalErrorDescription() {
+ return sprintf(s__('ClusterIntegration|Something went wrong while installing %{title}'), {
+ title: this.title,
+ });
+ },
+ },
+ methods: {
+ installClicked() {
+ eventHub.$emit('installApplication', {
+ id: this.id,
+ params: this.installApplicationRequestParams,
+ });
+ },
+ },
+};
</script>
<template>
@@ -155,35 +164,21 @@
:class="[
rowJsClass,
isInstalled && 'cluster-application-installed',
- disabled && 'cluster-application-disabled'
+ disabled && 'cluster-application-disabled',
]"
class="cluster-application-row gl-responsive-table-row gl-responsive-table-row-col-span"
>
- <div
- class="gl-responsive-table-row-layout"
- role="row"
- >
- <div
- class="table-section append-right-8 section-align-top"
- role="gridcell"
- >
+ <div class="gl-responsive-table-row-layout" role="row">
+ <div class="table-section append-right-8 section-align-top" role="gridcell">
<img
v-if="hasLogo"
:src="logoUrl"
:alt="`${title} logo`"
class="cluster-application-logo avatar s40"
/>
- <identicon
- v-else
- :entity-id="identiconId"
- :entity-name="title"
- size-class="s40"
- />
+ <identicon v-else :entity-id="identiconId" :entity-name="title" size-class="s40" />
</div>
- <div
- class="table-section cluster-application-description section-wrap"
- role="gridcell"
- >
+ <div class="table-section cluster-application-description section-wrap" role="gridcell">
<strong>
<a
v-if="titleLink"
@@ -194,12 +189,7 @@
>
{{ title }}
</a>
- <span
- v-else
- class="js-cluster-application-title"
- >
- {{ title }}
- </span>
+ <span v-else class="js-cluster-application-title"> {{ title }} </span>
</strong>
<slot name="description"></slot>
<div
@@ -210,16 +200,10 @@
{{ generalErrorDescription }}
</p>
<ul v-if="statusReason || requestReason">
- <li
- v-if="statusReason"
- class="js-cluster-application-status-error-message"
- >
+ <li v-if="statusReason" class="js-cluster-application-status-error-message">
{{ statusReason }}
</li>
- <li
- v-if="requestReason"
- class="js-cluster-application-request-error-message"
- >
+ <li v-if="requestReason" class="js-cluster-application-request-error-message">
{{ requestReason }}
</li>
</ul>
@@ -230,15 +214,8 @@
class="table-section table-button-footer section-align-top"
role="gridcell"
>
- <div
- v-if="showManageButton"
- class="btn-group table-action-buttons"
- >
- <a
- :href="manageLink"
- :class="{ disabled: disabled }"
- class="btn"
- >
+ <div v-if="showManageButton" class="btn-group table-action-buttons">
+ <a :href="manageLink" :class="{ disabled: disabled }" class="btn">
{{ manageButtonLabel }}
</a>
</div>
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue
index a1069985178..a37cb4def28 100644
--- a/app/assets/javascripts/clusters/components/applications.vue
+++ b/app/assets/javascripts/clusters/components/applications.vue
@@ -1,18 +1,20 @@
<script>
import _ from 'underscore';
-import helmInstallIllustration from '@gitlab-org/gitlab-svgs/illustrations/kubernetes-installation.svg';
+import helmInstallIllustration from '@gitlab/svgs/dist/illustrations/kubernetes-installation.svg';
import elasticsearchLogo from 'images/cluster_app_logos/elasticsearch.png';
import gitlabLogo from 'images/cluster_app_logos/gitlab.png';
import helmLogo from 'images/cluster_app_logos/helm.png';
import jeagerLogo from 'images/cluster_app_logos/jeager.png';
import jupyterhubLogo from 'images/cluster_app_logos/jupyterhub.png';
import kubernetesLogo from 'images/cluster_app_logos/kubernetes.png';
+import certManagerLogo from 'images/cluster_app_logos/cert_manager.png';
+import knativeLogo from 'images/cluster_app_logos/knative.png';
import meltanoLogo from 'images/cluster_app_logos/meltano.png';
import prometheusLogo from 'images/cluster_app_logos/prometheus.png';
import { s__, sprintf } from '../../locale';
import applicationRow from './application_row.vue';
import clipboardButton from '../../vue_shared/components/clipboard_button.vue';
-import { APPLICATION_STATUS, INGRESS } from '../constants';
+import { CLUSTER_TYPE, APPLICATION_STATUS, INGRESS } from '../constants';
export default {
components: {
@@ -20,6 +22,11 @@ export default {
clipboardButton,
},
props: {
+ type: {
+ type: String,
+ required: false,
+ default: CLUSTER_TYPE.PROJECT,
+ },
applications: {
type: Object,
required: false,
@@ -53,10 +60,15 @@ export default {
jeagerLogo,
jupyterhubLogo,
kubernetesLogo,
+ certManagerLogo,
+ knativeLogo,
meltanoLogo,
prometheusLogo,
}),
computed: {
+ isProjectCluster() {
+ return this.type === CLUSTER_TYPE.PROJECT;
+ },
helmInstalled() {
return (
this.applications.helm.status === APPLICATION_STATUS.INSTALLED ||
@@ -114,6 +126,23 @@ export default {
</p>
`;
},
+ certManagerDescription() {
+ return sprintf(
+ _.escape(
+ s__(
+ `ClusterIntegration|cert-manager is a native Kubernetes certificate management controller that helps with issuing certificates.
+ Installing cert-manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates
+ are valid and up to date.`,
+ ),
+ ),
+ {
+ letsEncrypt: `<a href="https://letsencrypt.org/"
+ target="_blank" rel="noopener noreferrer">
+ ${_.escape(s__("ClusterIntegration|Let's Encrypt"))}</a>`,
+ },
+ false,
+ );
+ },
prometheusDescription() {
return sprintf(
_.escape(
@@ -136,6 +165,12 @@ export default {
jupyterHostname() {
return this.applications.jupyter.hostname;
},
+ knativeInstalled() {
+ return this.applications.knative.status === APPLICATION_STATUS.INSTALLED;
+ },
+ knativeExternalIp() {
+ return this.applications.knative.externalIp;
+ },
},
created() {
this.helmInstallIllustration = helmInstallIllustration;
@@ -145,15 +180,13 @@ export default {
<template>
<section id="cluster-applications">
- <h4>
- {{ s__('ClusterIntegration|Applications') }}
- </h4>
+ <h4>{{ s__('ClusterIntegration|Applications') }}</h4>
<p class="append-bottom-0">
- {{ s__(`ClusterIntegration|Choose which applications to install on your Kubernetes cluster.
- Helm Tiller is required to install any of the following applications.`) }}
- <a :href="helpPath">
- {{ __('More information') }}
- </a>
+ {{
+ s__(`ClusterIntegration|Choose which applications to install on your Kubernetes cluster.
+ Helm Tiller is required to install any of the following applications.`)
+ }}
+ <a :href="helpPath"> {{ __('More information') }} </a>
</p>
<div class="cluster-application-list prepend-top-10">
@@ -169,23 +202,20 @@ export default {
title-link="https://docs.helm.sh/"
>
<div slot="description">
- {{ s__(`ClusterIntegration|Helm streamlines installing
+ {{
+ s__(`ClusterIntegration|Helm streamlines installing
and managing Kubernetes applications.
Tiller runs inside of your Kubernetes Cluster,
- and manages releases of your charts.`) }}
+ and manages releases of your charts.`)
+ }}
</div>
</application-row>
- <div
- v-show="!helmInstalled"
- class="cluster-application-warning"
- >
- <div
- class="svg-container"
- v-html="helmInstallIllustration"
- >
- </div>
- {{ s__(`ClusterIntegration|You must first install Helm Tiller before
- installing the applications below`) }}
+ <div v-show="!helmInstalled" class="cluster-application-warning">
+ <div class="svg-container" v-html="helmInstallIllustration"></div>
+ {{
+ s__(`ClusterIntegration|You must first install Helm Tiller before
+ installing the applications below`)
+ }}
</div>
<application-row
:id="ingressId"
@@ -200,9 +230,11 @@ export default {
>
<div slot="description">
<p>
- {{ s__(`ClusterIntegration|Ingress gives you a way to route
+ {{
+ s__(`ClusterIntegration|Ingress gives you a way to route
requests to services based on the request host or path,
- centralizing a number of services into a single entrypoint.`) }}
+ centralizing a number of services into a single entrypoint.`)
+ }}
</p>
<template v-if="ingressInstalled">
@@ -210,10 +242,7 @@ export default {
<label for="ingress-ip-address">
{{ s__('ClusterIntegration|Ingress IP Address') }}
</label>
- <div
- v-if="ingressExternalIp"
- class="input-group"
- >
+ <div v-if="ingressExternalIp" class="input-group">
<input
id="ingress-ip-address"
:value="ingressExternalIp"
@@ -229,53 +258,51 @@ export default {
/>
</span>
</div>
- <input
- v-else
- type="text"
- class="form-control js-ip-address"
- readonly
- value="?"
- />
+ <input v-else type="text" class="form-control js-ip-address" readonly value="?" />
</div>
- <p
- v-if="!ingressExternalIp"
- class="settings-message js-no-ip-message"
- >
- {{ s__(`ClusterIntegration|The IP address is in
+ <p v-if="!ingressExternalIp" class="settings-message js-no-ip-message">
+ {{
+ s__(`ClusterIntegration|The IP address is in
the process of being assigned. Please check your Kubernetes
- cluster or Quotas on Google Kubernetes Engine if it takes a long time.`) }}
+ cluster or Quotas on Google Kubernetes Engine if it takes a long time.`)
+ }}
- <a
- :href="ingressHelpPath"
- target="_blank"
- rel="noopener noreferrer"
- >
+ <a :href="ingressHelpPath" target="_blank" rel="noopener noreferrer">
{{ __('More information') }}
</a>
</p>
<p>
- {{ s__(`ClusterIntegration|Point a wildcard DNS to this
+ {{
+ s__(`ClusterIntegration|Point a wildcard DNS to this
generated IP address in order to access
- your application after it has been deployed.`) }}
- <a
- :href="ingressDnsHelpPath"
- target="_blank"
- rel="noopener noreferrer"
- >
+ your application after it has been deployed.`)
+ }}
+ <a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
{{ __('More information') }}
</a>
</p>
-
</template>
- <div
- v-html="ingressDescription"
- >
- </div>
+ <div v-html="ingressDescription"></div>
</div>
</application-row>
<application-row
+ id="cert_manager"
+ :logo-url="certManagerLogo"
+ :title="applications.cert_manager.title"
+ :status="applications.cert_manager.status"
+ :status-reason="applications.cert_manager.statusReason"
+ :request-status="applications.cert_manager.requestStatus"
+ :request-reason="applications.cert_manager.requestReason"
+ :disabled="!helmInstalled"
+ class="hide-bottom-border rounded-bottom"
+ title-link="https://cert-manager.readthedocs.io/en/latest/#"
+ >
+ <div slot="description" v-html="certManagerDescription"></div>
+ </application-row>
+ <application-row
+ v-if="isProjectCluster"
id="prometheus"
:logo-url="prometheusLogo"
:title="applications.prometheus.title"
@@ -287,13 +314,10 @@ export default {
:disabled="!helmInstalled"
title-link="https://prometheus.io/docs/introduction/overview/"
>
- <div
- slot="description"
- v-html="prometheusDescription"
- >
- </div>
+ <div slot="description" v-html="prometheusDescription"></div>
</application-row>
<application-row
+ v-if="isProjectCluster"
id="runner"
:logo-url="gitlabLogo"
:title="applications.runner.title"
@@ -305,13 +329,16 @@ export default {
title-link="https://docs.gitlab.com/runner/"
>
<div slot="description">
- {{ s__(`ClusterIntegration|GitLab Runner connects to this
+ {{
+ s__(`ClusterIntegration|GitLab Runner connects to this
project's repository and executes CI/CD jobs,
pushing results back and deploying,
- applications to production.`) }}
+ applications to production.`)
+ }}
</div>
</application-row>
<application-row
+ v-if="isProjectCluster"
id="jupyter"
:logo-url="jupyterhubLogo"
:title="applications.jupyter.title"
@@ -321,16 +348,17 @@ export default {
:request-reason="applications.jupyter.requestReason"
:install-application-request-params="{ hostname: applications.jupyter.hostname }"
:disabled="!helmInstalled"
- class="hide-bottom-border rounded-bottom"
title-link="https://jupyterhub.readthedocs.io/en/stable/"
>
<div slot="description">
<p>
- {{ s__(`ClusterIntegration|JupyterHub, a multi-user Hub, spawns,
+ {{
+ s__(`ClusterIntegration|JupyterHub, a multi-user Hub, spawns,
manages, and proxies multiple instances of the single-user
Jupyter notebook server. JupyterHub can be used to serve
notebooks to a class of students, a corporate data science group,
- or a scientific research group.`) }}
+ or a scientific research group.`)
+ }}
</p>
<template v-if="ingressExternalIp">
@@ -346,9 +374,7 @@ export default {
type="text"
class="form-control js-hostname"
/>
- <span
- class="input-group-btn"
- >
+ <span class="input-group-btn">
<clipboard-button
:text="jupyterHostname"
:title="s__('ClusterIntegration|Copy Jupyter Hostname to clipboard')"
@@ -358,13 +384,107 @@ export default {
</div>
</div>
<p v-if="ingressInstalled">
- {{ s__(`ClusterIntegration|Replace this with your own hostname if you want.
- If you do so, point hostname to Ingress IP Address from above.`) }}
- <a
- :href="ingressDnsHelpPath"
- target="_blank"
- rel="noopener noreferrer"
- >
+ {{
+ s__(`ClusterIntegration|Replace this with your own hostname if you want.
+ If you do so, point hostname to Ingress IP Address from above.`)
+ }}
+ <a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
+ {{ __('More information') }}
+ </a>
+ </p>
+ </template>
+ </div>
+ </application-row>
+ <application-row
+ id="knative"
+ :logo-url="knativeLogo"
+ :title="applications.knative.title"
+ :status="applications.knative.status"
+ :status-reason="applications.knative.statusReason"
+ :request-status="applications.knative.requestStatus"
+ :request-reason="applications.knative.requestReason"
+ :install-application-request-params="{ hostname: applications.knative.hostname }"
+ :disabled="!helmInstalled"
+ class="hide-bottom-border rounded-bottom"
+ title-link="https://github.com/knative/docs"
+ >
+ <div slot="description">
+ <p>
+ {{
+ s__(`ClusterIntegration|Knative (pronounced kay-nay-tiv) extends
+ Kubernetes to provide a set of middleware components that are
+ essential to build modern, source-centric, and container-based
+ applications that can run anywhere: on premises, in the cloud, or
+ even in a third-party data center.`)
+ }}
+ </p>
+
+ <template v-if="knativeInstalled">
+ <div class="form-group">
+ <label for="knative-domainname">
+ {{ s__('ClusterIntegration|Knative Domain Name:') }}
+ </label>
+ <input
+ id="knative-domainname"
+ v-model="applications.knative.hostname"
+ type="text"
+ class="form-control js-domainname"
+ readonly
+ />
+ </div>
+ </template>
+ <template v-else>
+ <div class="form-group">
+ <label for="knative-domainname">
+ {{ s__('ClusterIntegration|Knative Domain Name:') }}
+ </label>
+ <input
+ id="knative-domainname"
+ v-model="applications.knative.hostname"
+ type="text"
+ class="form-control js-domainname"
+ />
+ </div>
+ </template>
+ <template v-if="knativeInstalled">
+ <div class="form-group">
+ <label for="knative-ip-address">
+ {{ s__('ClusterIntegration|Knative IP Address:') }}
+ </label>
+ <div v-if="knativeExternalIp" class="input-group">
+ <input
+ id="knative-ip-address"
+ :value="knativeExternalIp"
+ type="text"
+ class="form-control js-ip-address"
+ readonly
+ />
+ <span class="input-group-append">
+ <clipboard-button
+ :text="knativeExternalIp"
+ :title="s__('ClusterIntegration|Copy Knative IP Address to clipboard')"
+ class="input-group-text js-clipboard-btn"
+ />
+ </span>
+ </div>
+ <input v-else type="text" class="form-control js-ip-address" readonly value="?" />
+ </div>
+
+ <p v-if="!knativeExternalIp" class="settings-message js-no-ip-message">
+ {{
+ s__(`ClusterIntegration|The IP address is in
+ the process of being assigned. Please check your Kubernetes
+ cluster or Quotas on Google Kubernetes Engine if it takes a long time.`)
+ }}
+ </p>
+
+ <p>
+ {{
+ s__(`ClusterIntegration|Point a wildcard DNS to this
+ generated IP address in order to access
+ your application after it has been deployed.`)
+ }}
+ <a :href="ingressDnsHelpPath" target="_blank" rel="noopener noreferrer">
{{ __('More information') }}
</a>
</p>
diff --git a/app/assets/javascripts/clusters/constants.js b/app/assets/javascripts/clusters/constants.js
index 72fc9355d82..15cf4a56138 100644
--- a/app/assets/javascripts/clusters/constants.js
+++ b/app/assets/javascripts/clusters/constants.js
@@ -1,3 +1,10 @@
+// These need to match the enum found in app/models/clusters/cluster.rb
+export const CLUSTER_TYPE = {
+ INSTANCE: 'instance_type',
+ GROUP: 'group_type',
+ PROJECT: 'project_type',
+};
+
// These need to match what is returned from the server
export const APPLICATION_STATUS = {
NOT_INSTALLABLE: 'not_installable',
@@ -6,6 +13,7 @@ export const APPLICATION_STATUS = {
INSTALLING: 'installing',
INSTALLED: 'installed',
UPDATED: 'updated',
+ UPDATING: 'updating',
ERROR: 'errored',
};
@@ -15,3 +23,4 @@ export const REQUEST_SUCCESS = 'request-success';
export const REQUEST_FAILURE = 'request-failure';
export const INGRESS = 'ingress';
export const JUPYTER = 'jupyter';
+export const KNATIVE = 'knative';
diff --git a/app/assets/javascripts/clusters/services/clusters_service.js b/app/assets/javascripts/clusters/services/clusters_service.js
index a7d82292ba9..89dda4b7902 100644
--- a/app/assets/javascripts/clusters/services/clusters_service.js
+++ b/app/assets/javascripts/clusters/services/clusters_service.js
@@ -6,9 +6,11 @@ export default class ClusterService {
this.appInstallEndpointMap = {
helm: this.options.installHelmEndpoint,
ingress: this.options.installIngressEndpoint,
+ cert_manager: this.options.installCertManagerEndpoint,
runner: this.options.installRunnerEndpoint,
prometheus: this.options.installPrometheusEndpoint,
jupyter: this.options.installJupyterEndpoint,
+ knative: this.options.installKnativeEndpoint,
};
}
diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js
index d90db7b103c..2d69da8eaec 100644
--- a/app/assets/javascripts/clusters/stores/clusters_store.js
+++ b/app/assets/javascripts/clusters/stores/clusters_store.js
@@ -1,5 +1,5 @@
import { s__ } from '../../locale';
-import { INGRESS, JUPYTER } from '../constants';
+import { INGRESS, JUPYTER, KNATIVE } from '../constants';
export default class ClusterStore {
constructor() {
@@ -24,6 +24,13 @@ export default class ClusterStore {
requestReason: null,
externalIp: null,
},
+ cert_manager: {
+ title: s__('ClusterIntegration|Cert-Manager'),
+ status: null,
+ statusReason: null,
+ requestStatus: null,
+ requestReason: null,
+ },
runner: {
title: s__('ClusterIntegration|GitLab Runner'),
status: null,
@@ -46,6 +53,15 @@ export default class ClusterStore {
requestReason: null,
hostname: null,
},
+ knative: {
+ title: s__('ClusterIntegration|Knative'),
+ status: null,
+ statusReason: null,
+ requestStatus: null,
+ requestReason: null,
+ hostname: null,
+ externalIp: null,
+ },
},
};
}
@@ -76,12 +92,8 @@ export default class ClusterStore {
this.state.status = serverState.status;
this.state.statusReason = serverState.status_reason;
- serverState.applications.forEach((serverAppEntry) => {
- const {
- name: appId,
- status,
- status_reason: statusReason,
- } = serverAppEntry;
+ serverState.applications.forEach(serverAppEntry => {
+ const { name: appId, status, status_reason: statusReason } = serverAppEntry;
this.state.applications[appId] = {
...(this.state.applications[appId] || {}),
@@ -97,6 +109,11 @@ export default class ClusterStore {
(this.state.applications.ingress.externalIp
? `jupyter.${this.state.applications.ingress.externalIp}.nip.io`
: '');
+ } else if (appId === KNATIVE) {
+ this.state.applications.knative.hostname =
+ serverAppEntry.hostname || this.state.applications.knative.hostname;
+ this.state.applications.knative.externalIp =
+ serverAppEntry.external_ip || this.state.applications.knative.externalIp;
}
});
}
diff --git a/app/assets/javascripts/comment_type_toggle.js b/app/assets/javascripts/comment_type_toggle.js
index c74184949df..a259667bb75 100644
--- a/app/assets/javascripts/comment_type_toggle.js
+++ b/app/assets/javascripts/comment_type_toggle.js
@@ -24,36 +24,44 @@ class CommentTypeToggle {
setConfig() {
const config = {
- InputSetter: [{
- input: this.noteTypeInput,
- valueAttribute: 'data-value',
- },
- {
- input: this.submitButton,
- valueAttribute: 'data-submit-text',
- }],
+ InputSetter: [
+ {
+ input: this.noteTypeInput,
+ valueAttribute: 'data-value',
+ },
+ {
+ input: this.submitButton,
+ valueAttribute: 'data-submit-text',
+ },
+ ],
};
if (this.closeButton) {
- config.InputSetter.push({
- input: this.closeButton,
- valueAttribute: 'data-close-text',
- }, {
- input: this.closeButton,
- valueAttribute: 'data-close-text',
- inputAttribute: 'data-alternative-text',
- });
+ config.InputSetter.push(
+ {
+ input: this.closeButton,
+ valueAttribute: 'data-close-text',
+ },
+ {
+ input: this.closeButton,
+ valueAttribute: 'data-close-text',
+ inputAttribute: 'data-alternative-text',
+ },
+ );
}
if (this.reopenButton) {
- config.InputSetter.push({
- input: this.reopenButton,
- valueAttribute: 'data-reopen-text',
- }, {
- input: this.reopenButton,
- valueAttribute: 'data-reopen-text',
- inputAttribute: 'data-alternative-text',
- });
+ config.InputSetter.push(
+ {
+ input: this.reopenButton,
+ valueAttribute: 'data-reopen-text',
+ },
+ {
+ input: this.reopenButton,
+ valueAttribute: 'data-reopen-text',
+ inputAttribute: 'data-alternative-text',
+ },
+ );
}
return config;
diff --git a/app/assets/javascripts/commit/image_file.js b/app/assets/javascripts/commit/image_file.js
index 410580b4c25..d4ecfa4aa93 100644
--- a/app/assets/javascripts/commit/image_file.js
+++ b/app/assets/javascripts/commit/image_file.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, wrap-iife, no-var, prefer-arrow-callback, no-else-return, consistent-return, prefer-template, quotes, one-var, one-var-declaration-per-line, no-unused-vars, no-return-assign, comma-dangle, quote-props, no-unused-expressions, no-sequences, max-len */
+/* eslint-disable func-names, no-var, prefer-arrow-callback, no-else-return, consistent-return, prefer-template, one-var, no-unused-vars, no-return-assign, no-unused-expressions, no-sequences */
import $ from 'jquery';
@@ -9,44 +9,60 @@ const viewModes = ['two-up', 'swipe'];
export default class ImageFile {
constructor(file) {
this.file = file;
- this.requestImageInfo($('.two-up.view .frame.deleted img', this.file), (function(_this) {
- return function(deletedWidth, deletedHeight) {
- return _this.requestImageInfo($('.two-up.view .frame.added img', _this.file), function(width, height) {
- _this.initViewModes();
-
- // Load two-up view after images are loaded
- // so that we can display the correct width and height information
- const $images = $('.two-up.view img', _this.file);
-
- $images.waitForImages(function() {
- _this.initView('two-up');
+ this.requestImageInfo(
+ $('.two-up.view .frame.deleted img', this.file),
+ (function(_this) {
+ return function(deletedWidth, deletedHeight) {
+ return _this.requestImageInfo($('.two-up.view .frame.added img', _this.file), function(
+ width,
+ height,
+ ) {
+ _this.initViewModes();
+
+ // Load two-up view after images are loaded
+ // so that we can display the correct width and height information
+ const $images = $('.two-up.view img', _this.file);
+
+ $images.waitForImages(function() {
+ _this.initView('two-up');
+ });
});
- });
- };
- })(this));
+ };
+ })(this),
+ );
}
initViewModes() {
const viewMode = viewModes[0];
$('.view-modes', this.file).removeClass('hide');
- $('.view-modes-menu', this.file).on('click', 'li', (function(_this) {
- return function(event) {
- if (!$(event.currentTarget).hasClass('active')) {
- return _this.activateViewMode(event.currentTarget.className);
- }
- };
- })(this));
+ $('.view-modes-menu', this.file).on(
+ 'click',
+ 'li',
+ (function(_this) {
+ return function(event) {
+ if (!$(event.currentTarget).hasClass('active')) {
+ return _this.activateViewMode(event.currentTarget.className);
+ }
+ };
+ })(this),
+ );
return this.activateViewMode(viewMode);
}
activateViewMode(viewMode) {
- $('.view-modes-menu li', this.file).removeClass('active').filter("." + viewMode).addClass('active');
- return $(".view:visible:not(." + viewMode + ")", this.file).fadeOut(200, (function(_this) {
- return function() {
- $(".view." + viewMode, _this.file).fadeIn(200);
- return _this.initView(viewMode);
- };
- })(this));
+ $('.view-modes-menu li', this.file)
+ .removeClass('active')
+ .filter('.' + viewMode)
+ .addClass('active');
+ return $('.view:visible:not(.' + viewMode + ')', this.file).fadeOut(
+ 200,
+ (function(_this) {
+ return function() {
+ $('.view.' + viewMode, _this.file).fadeIn(200);
+ return _this.initView(viewMode);
+ };
+ })(this),
+ );
}
initView(viewMode) {
@@ -63,135 +79,154 @@ export default class ImageFile {
$body.css('user-select', 'none');
});
- $body.off('mouseup').off('mousemove').on('mouseup', function() {
- dragging = false;
- $body.css('user-select', '');
- })
- .on('mousemove', function(e) {
- var left;
- if (!dragging) return;
-
- left = e.pageX - ($offsetEl.offset().left + padding);
-
- callback(e, left);
- });
+ $body
+ .off('mouseup')
+ .off('mousemove')
+ .on('mouseup', function() {
+ dragging = false;
+ $body.css('user-select', '');
+ })
+ .on('mousemove', function(e) {
+ var left;
+ if (!dragging) return;
+
+ left = e.pageX - ($offsetEl.offset().left + padding);
+
+ callback(e, left);
+ });
}
prepareFrames(view) {
var maxHeight, maxWidth;
maxWidth = 0;
maxHeight = 0;
- $('.frame', view).each((function(_this) {
- return function(index, frame) {
- var height, width;
- width = $(frame).width();
- height = $(frame).height();
- maxWidth = width > maxWidth ? width : maxWidth;
- return maxHeight = height > maxHeight ? height : maxHeight;
- };
- })(this)).css({
- width: maxWidth,
- height: maxHeight
- });
+ $('.frame', view)
+ .each(
+ (function(_this) {
+ return function(index, frame) {
+ var height, width;
+ width = $(frame).width();
+ height = $(frame).height();
+ maxWidth = width > maxWidth ? width : maxWidth;
+ return (maxHeight = height > maxHeight ? height : maxHeight);
+ };
+ })(this),
+ )
+ .css({
+ width: maxWidth,
+ height: maxHeight,
+ });
return [maxWidth, maxHeight];
}
views = {
'two-up': function() {
- return $('.two-up.view .wrap', this.file).each((function(_this) {
- return function(index, wrap) {
- $('img', wrap).each(function() {
- var currentWidth;
- currentWidth = $(this).width();
- if (currentWidth > availWidth / 2) {
- return $(this).width(availWidth / 2);
- }
- });
- return _this.requestImageInfo($('img', wrap), function(width, height) {
- $('.image-info .meta-width', wrap).text(width + "px");
- $('.image-info .meta-height', wrap).text(height + "px");
- return $('.image-info', wrap).removeClass('hide');
- });
- };
- })(this));
+ return $('.two-up.view .wrap', this.file).each(
+ (function(_this) {
+ return function(index, wrap) {
+ $('img', wrap).each(function() {
+ var currentWidth;
+ currentWidth = $(this).width();
+ if (currentWidth > availWidth / 2) {
+ return $(this).width(availWidth / 2);
+ }
+ });
+ return _this.requestImageInfo($('img', wrap), function(width, height) {
+ $('.image-info .meta-width', wrap).text(width + 'px');
+ $('.image-info .meta-height', wrap).text(height + 'px');
+ return $('.image-info', wrap).removeClass('hide');
+ });
+ };
+ })(this),
+ );
},
- 'swipe': function() {
+ swipe() {
var maxHeight, maxWidth;
maxWidth = 0;
maxHeight = 0;
- return $('.swipe.view', this.file).each((function(_this) {
- return function(index, view) {
- var $swipeWrap, $swipeBar, $swipeFrame, wrapPadding, ref;
- ref = _this.prepareFrames(view), [maxWidth, maxHeight] = ref;
- $swipeFrame = $('.swipe-frame', view);
- $swipeWrap = $('.swipe-wrap', view);
- $swipeBar = $('.swipe-bar', view);
-
- $swipeFrame.css({
- width: maxWidth + 16,
- height: maxHeight + 28
- });
- $swipeWrap.css({
- width: maxWidth + 1,
- height: maxHeight + 2
- });
- // Set swipeBar left position to match image frame
- $swipeBar.css({
- left: 1
- });
-
- wrapPadding = parseInt($swipeWrap.css('right').replace('px', ''), 10);
-
- _this.initDraggable($swipeBar, wrapPadding, function(e, left) {
- if (left > 0 && left < $swipeFrame.width() - (wrapPadding * 2)) {
- $swipeWrap.width((maxWidth + 1) - left);
- $swipeBar.css('left', left);
- }
- });
- };
- })(this));
+ return $('.swipe.view', this.file).each(
+ (function(_this) {
+ return function(index, view) {
+ var $swipeWrap, $swipeBar, $swipeFrame, wrapPadding, ref;
+ (ref = _this.prepareFrames(view)), ([maxWidth, maxHeight] = ref);
+ $swipeFrame = $('.swipe-frame', view);
+ $swipeWrap = $('.swipe-wrap', view);
+ $swipeBar = $('.swipe-bar', view);
+
+ $swipeFrame.css({
+ width: maxWidth + 16,
+ height: maxHeight + 28,
+ });
+ $swipeWrap.css({
+ width: maxWidth + 1,
+ height: maxHeight + 2,
+ });
+ // Set swipeBar left position to match image frame
+ $swipeBar.css({
+ left: 1,
+ });
+
+ wrapPadding = parseInt($swipeWrap.css('right').replace('px', ''), 10);
+
+ _this.initDraggable($swipeBar, wrapPadding, function(e, left) {
+ if (left > 0 && left < $swipeFrame.width() - wrapPadding * 2) {
+ $swipeWrap.width(maxWidth + 1 - left);
+ $swipeBar.css('left', left);
+ }
+ });
+ };
+ })(this),
+ );
},
'onion-skin': function() {
var dragTrackWidth, maxHeight, maxWidth;
maxWidth = 0;
maxHeight = 0;
dragTrackWidth = $('.drag-track', this.file).width() - $('.dragger', this.file).width();
- return $('.onion-skin.view', this.file).each((function(_this) {
- return function(index, view) {
- var $frame, $track, $dragger, $frameAdded, framePadding, ref, dragging = false;
- ref = _this.prepareFrames(view), [maxWidth, maxHeight] = ref;
- $frame = $('.onion-skin-frame', view);
- $frameAdded = $('.frame.added', view);
- $track = $('.drag-track', view);
- $dragger = $('.dragger', $track);
-
- $frame.css({
- width: maxWidth + 16,
- height: maxHeight + 28
- });
- $('.swipe-wrap', view).css({
- width: maxWidth + 1,
- height: maxHeight + 2
- });
- $dragger.css({
- left: dragTrackWidth
- });
-
- $frameAdded.css('opacity', 1);
- framePadding = parseInt($frameAdded.css('right').replace('px', ''), 10);
-
- _this.initDraggable($dragger, framePadding, function(e, left) {
- var opacity = left / dragTrackWidth;
-
- if (opacity >= 0 && opacity <= 1) {
- $dragger.css('left', left);
- $frameAdded.css('opacity', opacity);
- }
- });
- };
- })(this));
- }
- }
+ return $('.onion-skin.view', this.file).each(
+ (function(_this) {
+ return function(index, view) {
+ var $frame,
+ $track,
+ $dragger,
+ $frameAdded,
+ framePadding,
+ ref,
+ dragging = false;
+ (ref = _this.prepareFrames(view)), ([maxWidth, maxHeight] = ref);
+ $frame = $('.onion-skin-frame', view);
+ $frameAdded = $('.frame.added', view);
+ $track = $('.drag-track', view);
+ $dragger = $('.dragger', $track);
+
+ $frame.css({
+ width: maxWidth + 16,
+ height: maxHeight + 28,
+ });
+ $('.swipe-wrap', view).css({
+ width: maxWidth + 1,
+ height: maxHeight + 2,
+ });
+ $dragger.css({
+ left: dragTrackWidth,
+ });
+
+ $frameAdded.css('opacity', 1);
+ framePadding = parseInt($frameAdded.css('right').replace('px', ''), 10);
+
+ _this.initDraggable($dragger, framePadding, function(e, left) {
+ var opacity = left / dragTrackWidth;
+
+ if (opacity >= 0 && opacity <= 1) {
+ $dragger.css('left', left);
+ $frameAdded.css('opacity', opacity);
+ }
+ });
+ };
+ })(this),
+ );
+ },
+ };
requestImageInfo(img, callback) {
const domImg = img.get(0);
@@ -199,11 +234,14 @@ export default class ImageFile {
if (domImg.complete) {
return callback.call(this, domImg.naturalWidth, domImg.naturalHeight);
} else {
- return img.on('load', (function(_this) {
- return function() {
- return callback.call(_this, domImg.naturalWidth, domImg.naturalHeight);
- };
- })(this));
+ return img.on(
+ 'load',
+ (function(_this) {
+ return function() {
+ return callback.call(_this, domImg.naturalWidth, domImg.naturalHeight);
+ };
+ })(this),
+ );
}
}
}
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
index 3d89bf1316e..340a93e4e66 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
+++ b/app/assets/javascripts/commit/pipelines/pipelines_bundle.js
@@ -19,11 +19,13 @@ export default () => {
const pipelineTableViewEl = document.querySelector('#commit-pipeline-table-view');
if (pipelineTableViewEl) {
- // Update MR and Commits tabs
- pipelineTableViewEl.addEventListener('update-pipelines-count', (event) => {
- if (event.detail.pipelines &&
+ // Update MR and Commits tabs
+ pipelineTableViewEl.addEventListener('update-pipelines-count', event => {
+ if (
+ event.detail.pipelines &&
event.detail.pipelines.count &&
- event.detail.pipelines.count.all) {
+ event.detail.pipelines.count.all
+ ) {
const badge = document.querySelector('.js-pipelines-mr-count');
badge.textContent = event.detail.pipelines.count.all;
diff --git a/app/assets/javascripts/commit/pipelines/pipelines_table.vue b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
index 4849b0fa3db..3e01841d563 100644
--- a/app/assets/javascripts/commit/pipelines/pipelines_table.vue
+++ b/app/assets/javascripts/commit/pipelines/pipelines_table.vue
@@ -1,81 +1,87 @@
<script>
- import PipelinesService from '../../pipelines/services/pipelines_service';
- import PipelineStore from '../../pipelines/stores/pipelines_store';
- import pipelinesMixin from '../../pipelines/mixins/pipelines';
+import PipelinesService from '../../pipelines/services/pipelines_service';
+import PipelineStore from '../../pipelines/stores/pipelines_store';
+import pipelinesMixin from '../../pipelines/mixins/pipelines';
+import TablePagination from '../../vue_shared/components/table_pagination.vue';
+import { getParameterByName } from '../../lib/utils/common_utils';
+import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin';
- export default {
- mixins: [
- pipelinesMixin,
- ],
- props: {
- endpoint: {
- type: String,
- required: true,
- },
- helpPagePath: {
- type: String,
- required: true,
- },
- autoDevopsHelpPath: {
- type: String,
- required: true,
- },
- errorStateSvgPath: {
- type: String,
- required: true,
- },
- viewType: {
- type: String,
- required: false,
- default: 'child',
- },
+export default {
+ components: {
+ TablePagination,
+ },
+ mixins: [pipelinesMixin, CIPaginationMixin],
+ props: {
+ endpoint: {
+ type: String,
+ required: true,
},
+ helpPagePath: {
+ type: String,
+ required: true,
+ },
+ autoDevopsHelpPath: {
+ type: String,
+ required: true,
+ },
+ errorStateSvgPath: {
+ type: String,
+ required: true,
+ },
+ viewType: {
+ type: String,
+ required: false,
+ default: 'child',
+ },
+ },
- data() {
- const store = new PipelineStore();
+ data() {
+ const store = new PipelineStore();
- return {
- store,
- state: store.state,
- };
- },
+ return {
+ store,
+ state: store.state,
+ page: getParameterByName('page') || '1',
+ requestData: {},
+ };
+ },
- computed: {
- shouldRenderTable() {
- return !this.isLoading &&
- this.state.pipelines.length > 0 &&
- !this.hasError;
- },
- shouldRenderErrorState() {
- return this.hasError && !this.isLoading;
- },
+ computed: {
+ shouldRenderTable() {
+ return !this.isLoading && this.state.pipelines.length > 0 && !this.hasError;
},
- created() {
- this.service = new PipelinesService(this.endpoint);
+ shouldRenderErrorState() {
+ return this.hasError && !this.isLoading;
},
- methods: {
- successCallback(resp) {
- // depending of the endpoint the response can either bring a `pipelines` key or not.
- const pipelines = resp.data.pipelines || resp.data;
- this.setCommonData(pipelines);
+ },
+ created() {
+ this.service = new PipelinesService(this.endpoint);
+ this.requestData = { page: this.page };
+ },
+ methods: {
+ successCallback(resp) {
+ // depending of the endpoint the response can either bring a `pipelines` key or not.
+ const pipelines = resp.data.pipelines || resp.data;
- const updatePipelinesEvent = new CustomEvent('update-pipelines-count', {
- detail: {
- pipelines: resp.data,
- },
- });
+ this.store.storePagination(resp.headers);
+ this.setCommonData(pipelines);
- // notifiy to update the count in tabs
- if (this.$el.parentElement) {
- this.$el.parentElement.dispatchEvent(updatePipelinesEvent);
- }
- },
+ const updatePipelinesEvent = new CustomEvent('update-pipelines-count', {
+ detail: {
+ pipelines: resp.data,
+ },
+ });
+
+ // notifiy to update the count in tabs
+ if (this.$el.parentElement) {
+ this.$el.parentElement.dispatchEvent(updatePipelinesEvent);
+ }
},
- };
+ },
+};
</script>
<template>
<div class="content-list pipelines">
-
<gl-loading-icon
v-if="isLoading"
:label="s__('Pipelines|Loading Pipelines')"
@@ -86,14 +92,13 @@
<svg-blank-state
v-else-if="shouldRenderErrorState"
:svg-path="errorStateSvgPath"
- :message="s__(`Pipelines|There was an error fetching the pipelines.
- Try again in a few moments or contact your support team.`)"
+ :message="
+ s__(`Pipelines|There was an error fetching the pipelines.
+ Try again in a few moments or contact your support team.`)
+ "
/>
- <div
- v-else-if="shouldRenderTable"
- class="table-holder"
- >
+ <div v-else-if="shouldRenderTable" class="table-holder">
<pipelines-table-component
:pipelines="state.pipelines"
:update-graph-dropdown="updateGraphDropdown"
@@ -101,5 +106,11 @@
:view-type="viewType"
/>
</div>
+
+ <table-pagination
+ v-if="shouldRenderPagination"
+ :change="onChangePage"
+ :page-info="state.pageInfo"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/commit_merge_requests.js b/app/assets/javascripts/commit_merge_requests.js
index 102b4ee8463..3a0ab119df6 100644
--- a/app/assets/javascripts/commit_merge_requests.js
+++ b/app/assets/javascripts/commit_merge_requests.js
@@ -50,7 +50,7 @@ export function createContent(mergeRequests) {
if (mergeRequests.length === 0) {
$content.text(s__('Commits|No related merge requests found'));
} else {
- mergeRequests.forEach((mergeRequest) => {
+ mergeRequests.forEach(mergeRequest => {
const $header = createHeader($content.children().length, mergeRequests.length);
const $item = createItem(mergeRequest);
$content.append($header);
@@ -64,8 +64,9 @@ export function createContent(mergeRequests) {
export function fetchCommitMergeRequests() {
const $container = $('.merge-requests');
- axios.get($container.data('projectCommitPath'))
- .then((response) => {
+ axios
+ .get($container.data('projectCommitPath'))
+ .then(response => {
const $content = createContent(response.data);
$container.html($content);
diff --git a/app/assets/javascripts/commits.js b/app/assets/javascripts/commits.js
index 9a3ea7a55b6..54e2589c707 100644
--- a/app/assets/javascripts/commits.js
+++ b/app/assets/javascripts/commits.js
@@ -32,22 +32,31 @@ export default class CommitsList {
if (search === this.lastSearch) return Promise.resolve();
const commitsUrl = `${form.attr('action')}?${form.serialize()}`;
this.content.fadeTo('fast', 0.5);
- const params = form.serializeArray().reduce((acc, obj) => Object.assign(acc, {
- [obj.name]: obj.value,
- }), {});
+ const params = form.serializeArray().reduce(
+ (acc, obj) =>
+ Object.assign(acc, {
+ [obj.name]: obj.value,
+ }),
+ {},
+ );
- return axios.get(form.attr('action'), {
- params,
- })
+ return axios
+ .get(form.attr('action'), {
+ params,
+ })
.then(({ data }) => {
this.lastSearch = search;
this.content.html(data.html);
this.content.fadeTo('fast', 1.0);
// Change url so if user reload a page - search results are saved
- window.history.replaceState({
- page: commitsUrl,
- }, document.title, commitsUrl);
+ window.history.replaceState(
+ {
+ page: commitsUrl,
+ },
+ document.title,
+ commitsUrl,
+ );
})
.catch(() => {
this.content.fadeTo('fast', 1.0);
@@ -75,8 +84,15 @@ export default class CommitsList {
processedData = $processedData.not(`li.js-commit-header[data-day='${loadedShownDayFirst}']`);
// Update commits count in the previous commits header.
- commitsCount += Number($(processedData).nextUntil('li.js-commit-header').first().find('li.commit').length);
- $commitsHeadersLast.find('span.commits-count').text(`${commitsCount} ${pluralize('commit', commitsCount)}`);
+ commitsCount += Number(
+ $(processedData)
+ .nextUntil('li.js-commit-header')
+ .first()
+ .find('li.commit').length,
+ );
+ $commitsHeadersLast
+ .find('span.commits-count')
+ .text(`${commitsCount} ${pluralize('commit', commitsCount)}`);
}
localTimeAgo($processedData.find('.js-timeago'));
diff --git a/app/assets/javascripts/commons/bootstrap.js b/app/assets/javascripts/commons/bootstrap.js
index 50e2949ab55..fba30aea9ae 100644
--- a/app/assets/javascripts/commons/bootstrap.js
+++ b/app/assets/javascripts/commons/bootstrap.js
@@ -5,6 +5,14 @@ import 'bootstrap';
// custom jQuery functions
$.fn.extend({
- disable() { return $(this).prop('disabled', true).addClass('disabled'); },
- enable() { return $(this).prop('disabled', false).removeClass('disabled'); },
+ disable() {
+ return $(this)
+ .prop('disabled', true)
+ .addClass('disabled');
+ },
+ enable() {
+ return $(this)
+ .prop('disabled', false)
+ .removeClass('disabled');
+ },
});
diff --git a/app/assets/javascripts/commons/gitlab_ui.js b/app/assets/javascripts/commons/gitlab_ui.js
deleted file mode 100644
index aed26adfa5c..00000000000
--- a/app/assets/javascripts/commons/gitlab_ui.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import Vue from 'vue';
-import Pagination from '@gitlab-org/gitlab-ui/dist/components/base/pagination';
-import progressBar from '@gitlab-org/gitlab-ui/dist/components/base/progress_bar';
-import modal from '@gitlab-org/gitlab-ui/dist/components/base/modal';
-import loadingIcon from '@gitlab-org/gitlab-ui/dist/components/base/loading_icon';
-
-import dModal from '@gitlab-org/gitlab-ui/dist/directives/modal';
-import dTooltip from '@gitlab-org/gitlab-ui/dist/directives/tooltip';
-
-Vue.component('gl-pagination', Pagination);
-Vue.component('gl-progress-bar', progressBar);
-Vue.component('gl-ui-modal', modal);
-Vue.component('gl-loading-icon', loadingIcon);
-
-Vue.directive('gl-modal', dModal);
-Vue.directive('gl-tooltip', dTooltip);
diff --git a/app/assets/javascripts/commons/index.js b/app/assets/javascripts/commons/index.js
index ea945cd3fa5..0d2fe2925d8 100644
--- a/app/assets/javascripts/commons/index.js
+++ b/app/assets/javascripts/commons/index.js
@@ -3,5 +3,4 @@ import './polyfills';
import './jquery';
import './bootstrap';
import './vue';
-import './gitlab_ui';
import '../lib/utils/axios_utils';
diff --git a/app/assets/javascripts/commons/polyfills.js b/app/assets/javascripts/commons/polyfills.js
index 539d0d29e0d..bffc025ced3 100644
--- a/app/assets/javascripts/commons/polyfills.js
+++ b/app/assets/javascripts/commons/polyfills.js
@@ -5,6 +5,7 @@ import 'core-js/fn/array/find-index';
import 'core-js/fn/array/from';
import 'core-js/fn/array/includes';
import 'core-js/fn/object/assign';
+import 'core-js/fn/object/values';
import 'core-js/fn/promise';
import 'core-js/fn/string/code-point-at';
import 'core-js/fn/string/from-code-point';
diff --git a/app/assets/javascripts/compare_autocomplete.js b/app/assets/javascripts/compare_autocomplete.js
index a252036d657..37a3ceb5341 100644
--- a/app/assets/javascripts/compare_autocomplete.js
+++ b/app/assets/javascripts/compare_autocomplete.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, one-var, no-var, one-var-declaration-per-line, object-shorthand, no-else-return, max-len */
+/* eslint-disable func-names, one-var, no-var, object-shorthand, no-else-return */
import $ from 'jquery';
import { __ } from './locale';
@@ -40,7 +40,7 @@ export default function initCompareAutocomplete(limitTo = null, clickHandler = (
},
selectable: true,
filterable: true,
- filterRemote: true,
+ filterRemote: !!$dropdown.data('refsUrl'),
fieldName: $dropdown.data('fieldName'),
filterInput: 'input[type="search"]',
renderRow: function(ref) {
diff --git a/app/assets/javascripts/confirm_danger_modal.js b/app/assets/javascripts/confirm_danger_modal.js
index b0c85c2572e..1000c310e35 100644
--- a/app/assets/javascripts/confirm_danger_modal.js
+++ b/app/assets/javascripts/confirm_danger_modal.js
@@ -13,19 +13,23 @@ function openConfirmDangerModal($form, text) {
$submit.disable();
$input.focus();
- $('.js-confirm-danger-input').off('input').on('input', function handleInput() {
- const confirmText = rstrip($(this).val());
- if (confirmText === confirmTextMatch) {
- $submit.enable();
- } else {
- $submit.disable();
- }
- });
- $('.js-confirm-danger-submit').off('click').on('click', () => $form.submit());
+ $('.js-confirm-danger-input')
+ .off('input')
+ .on('input', function handleInput() {
+ const confirmText = rstrip($(this).val());
+ if (confirmText === confirmTextMatch) {
+ $submit.enable();
+ } else {
+ $submit.disable();
+ }
+ });
+ $('.js-confirm-danger-submit')
+ .off('click')
+ .on('click', () => $form.submit());
}
export default function initConfirmDangerModal() {
- $(document).on('click', '.js-confirm-danger', (e) => {
+ $(document).on('click', '.js-confirm-danger', e => {
e.preventDefault();
const $btn = $(e.target);
const $form = $btn.closest('form');
diff --git a/app/assets/javascripts/contextual_sidebar.js b/app/assets/javascripts/contextual_sidebar.js
index 3a50e73ad85..10f02739ec8 100644
--- a/app/assets/javascripts/contextual_sidebar.js
+++ b/app/assets/javascripts/contextual_sidebar.js
@@ -2,6 +2,7 @@ import $ from 'jquery';
import Cookies from 'js-cookie';
import _ from 'underscore';
import bp from './breakpoints';
+import { parseBoolean } from '~/lib/utils/common_utils';
export default class ContextualSidebar {
constructor() {
@@ -20,8 +21,11 @@ export default class ContextualSidebar {
}
bindEvents() {
- document.addEventListener('click', (e) => {
- if (!e.target.closest('.nav-sidebar') && (bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'md')) {
+ document.addEventListener('click', e => {
+ if (
+ !e.target.closest('.nav-sidebar') &&
+ (bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'md')
+ ) {
this.toggleCollapsedSidebar(true);
}
});
@@ -75,7 +79,7 @@ export default class ContextualSidebar {
if (breakpoint === 'sm' || breakpoint === 'md') {
this.toggleCollapsedSidebar(true);
} else if (breakpoint === 'lg') {
- const collapse = Cookies.get('sidebar_collapsed') === 'true';
+ const collapse = parseBoolean(Cookies.get('sidebar_collapsed'));
this.toggleCollapsedSidebar(collapse);
}
}
diff --git a/app/assets/javascripts/create_item_dropdown.js b/app/assets/javascripts/create_item_dropdown.js
index 8ef9aa7f529..916b190f469 100644
--- a/app/assets/javascripts/create_item_dropdown.js
+++ b/app/assets/javascripts/create_item_dropdown.js
@@ -36,7 +36,7 @@ export default class CreateItemDropdown {
},
selectable: true,
toggleLabel(selected) {
- return (selected && 'id' in selected) ? _.escape(selected.title) : this.defaultToggleLabel;
+ return selected && 'id' in selected ? _.escape(selected.title) : this.defaultToggleLabel;
},
fieldName: this.fieldName,
text(item) {
@@ -46,7 +46,7 @@ export default class CreateItemDropdown {
return _.escape(item.id);
},
onFilter: this.toggleCreateNewButton.bind(this),
- clicked: (options) => {
+ clicked: options => {
options.e.preventDefault();
this.onSelect();
},
@@ -77,9 +77,8 @@ export default class CreateItemDropdown {
getData(term, callback) {
this.getDataOption(term, (data = []) => {
// Ensure the selected item isn't already in the data to avoid duplicates
- const alreadyHasSelectedItem = this.selectedItem && data.some(item =>
- item.id === this.selectedItem.id,
- );
+ const alreadyHasSelectedItem =
+ this.selectedItem && data.some(item => item.id === this.selectedItem.id);
let uniqueData = data;
if (!alreadyHasSelectedItem) {
@@ -106,9 +105,7 @@ export default class CreateItemDropdown {
if (newValue) {
this.selectedItem = this.createNewItemFromValue(newValue);
- this.$dropdownContainer
- .find('.js-dropdown-create-new-item code')
- .text(newValue);
+ this.$dropdownContainer.find('.js-dropdown-create-new-item code').text(newValue);
}
this.toggleFooter(!newValue);
diff --git a/app/assets/javascripts/create_label.js b/app/assets/javascripts/create_label.js
index a999c21b2e9..28ca7d97314 100644
--- a/app/assets/javascripts/create_label.js
+++ b/app/assets/javascripts/create_label.js
@@ -37,7 +37,7 @@ export default class CreateLabelDropdown {
addBinding() {
const self = this;
- this.$colorSuggestions.on('click', function (e) {
+ this.$colorSuggestions.on('click', function(e) {
const $this = $(this);
self.addColorValue(e, $this);
});
@@ -47,7 +47,7 @@ export default class CreateLabelDropdown {
this.$dropdownBack.on('click', this.resetForm.bind(this));
- this.$cancelButton.on('click', function (e) {
+ this.$cancelButton.on('click', function(e) {
e.preventDefault();
e.stopPropagation();
@@ -79,13 +79,9 @@ export default class CreateLabelDropdown {
}
resetForm() {
- this.$newLabelField
- .val('')
- .trigger('change');
+ this.$newLabelField.val('').trigger('change');
- this.$newColorField
- .val('')
- .trigger('change');
+ this.$newColorField.val('').trigger('change');
this.$colorPreview
.css('background-color', '')
@@ -97,31 +93,34 @@ export default class CreateLabelDropdown {
e.preventDefault();
e.stopPropagation();
- Api.newLabel(this.namespacePath, this.projectPath, {
- title: this.$newLabelField.val(),
- color: this.$newColorField.val(),
- }, (label) => {
- this.$newLabelCreateButton.enable();
-
- if (label.message) {
- let errors;
-
- if (typeof label.message === 'string') {
- errors = label.message;
+ Api.newLabel(
+ this.namespacePath,
+ this.projectPath,
+ {
+ title: this.$newLabelField.val(),
+ color: this.$newColorField.val(),
+ },
+ label => {
+ this.$newLabelCreateButton.enable();
+
+ if (label.message) {
+ let errors;
+
+ if (typeof label.message === 'string') {
+ errors = label.message;
+ } else {
+ errors = Object.keys(label.message)
+ .map(key => `${humanize(key)} ${label.message[key].join(', ')}`)
+ .join('<br/>');
+ }
+
+ this.$newLabelError.html(errors).show();
} else {
- errors = Object.keys(label.message).map(key =>
- `${humanize(key)} ${label.message[key].join(', ')}`,
- ).join('<br/>');
- }
+ this.$dropdownBack.trigger('click');
- this.$newLabelError
- .html(errors)
- .show();
- } else {
- this.$dropdownBack.trigger('click');
-
- $(document).trigger('created.label', label);
- }
- });
+ $(document).trigger('created.label', label);
+ }
+ },
+ );
}
}
diff --git a/app/assets/javascripts/cycle_analytics/components/banner.vue b/app/assets/javascripts/cycle_analytics/components/banner.vue
index 410d4873e55..e44588efbfc 100644
--- a/app/assets/javascripts/cycle_analytics/components/banner.vue
+++ b/app/assets/javascripts/cycle_analytics/components/banner.vue
@@ -1,24 +1,28 @@
<script>
- import iconCycleAnalyticsSplash from 'icons/_icon_cycle_analytics_splash.svg';
+import Icon from '~/vue_shared/components/icon.vue';
+import iconCycleAnalyticsSplash from 'icons/_icon_cycle_analytics_splash.svg';
- export default {
- props: {
- documentationLink: {
- type: String,
- required: true,
- },
+export default {
+ components: {
+ Icon,
+ },
+ props: {
+ documentationLink: {
+ type: String,
+ required: true,
},
- computed: {
- iconCycleAnalyticsSplash() {
- return iconCycleAnalyticsSplash;
- },
+ },
+ computed: {
+ iconCycleAnalyticsSplash() {
+ return iconCycleAnalyticsSplash;
},
- methods: {
- dismissOverviewDialog() {
- this.$emit('dismiss-overview-dialog');
- },
+ },
+ methods: {
+ dismissOverviewDialog() {
+ this.$emit('dismiss-overview-dialog');
},
- };
+ },
+};
</script>
<template>
<div class="landing content-block">
@@ -28,31 +32,19 @@
type="button"
@click="dismissOverviewDialog"
>
- <i
- class="fa fa-times"
- aria-hidden="true">
- </i>
+ <icon name="close" />
</button>
- <div
- class="svg-container"
- v-html="iconCycleAnalyticsSplash"
- >
- </div>
+ <div class="svg-container" v-html="iconCycleAnalyticsSplash"></div>
<div class="inner-content">
- <h4>
- {{ __('Introducing Cycle Analytics') }}
- </h4>
+ <h4>{{ __('Introducing Cycle Analytics') }}</h4>
<p>
- {{ __(`Cycle Analytics gives an overview
-of how much time it takes to go from idea to production in your project.`) }}
+ {{
+ __(`Cycle Analytics gives an overview
+of how much time it takes to go from idea to production in your project.`)
+ }}
</p>
<p>
- <a
- :href="documentationLink"
- target="_blank"
- rel="nofollow"
- class="btn"
- >
+ <a :href="documentationLink" target="_blank" rel="nofollow" class="btn">
{{ __('Read more') }}
</a>
</p>
diff --git a/app/assets/javascripts/cycle_analytics/components/limit_warning_component.vue b/app/assets/javascripts/cycle_analytics/components/limit_warning_component.vue
index b626b187651..ff0f352b333 100644
--- a/app/assets/javascripts/cycle_analytics/components/limit_warning_component.vue
+++ b/app/assets/javascripts/cycle_analytics/components/limit_warning_component.vue
@@ -1,33 +1,27 @@
<script>
- import tooltip from '../../vue_shared/directives/tooltip';
+import { GlTooltipDirective } from '@gitlab/ui';
- export default {
- directives: {
- tooltip,
+export default {
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ count: {
+ type: Number,
+ required: true,
},
- props: {
- count: {
- type: Number,
- required: true,
- },
- },
- };
+ },
+};
</script>
<template>
- <span
- v-if="count === 50"
- class="events-info float-right"
- >
+ <span v-if="count === 50" class="events-info float-right">
<i
- v-tooltip
- :title="n__(
- 'Limited to showing %d event at most',
- 'Limited to showing %d events at most',
- 50
- )"
+ v-gl-tooltip
+ :title="
+ n__('Limited to showing %d event at most', 'Limited to showing %d events at most', 50)
+ "
class="fa fa-warning"
aria-hidden="true"
- data-placement="top"
>
</i>
{{ n__('Showing %d event', 'Showing %d events', 50) }}
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_code_component.vue b/app/assets/javascripts/cycle_analytics/components/stage_code_component.vue
index a71dcf78103..333ea111cd6 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_code_component.vue
+++ b/app/assets/javascripts/cycle_analytics/components/stage_code_component.vue
@@ -1,25 +1,25 @@
<script>
- import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
- import limitWarning from './limit_warning_component.vue';
- import totalTime from './total_time_component.vue';
+import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
+import limitWarning from './limit_warning_component.vue';
+import totalTime from './total_time_component.vue';
- export default {
- components: {
- userAvatarImage,
- limitWarning,
- totalTime,
+export default {
+ components: {
+ userAvatarImage,
+ limitWarning,
+ totalTime,
+ },
+ props: {
+ items: {
+ type: Array,
+ default: () => [],
},
- props: {
- items: {
- type: Array,
- default: () => [],
- },
- stage: {
- type: Object,
- default: () => ({}),
- },
+ stage: {
+ type: Object,
+ default: () => ({}),
},
- };
+ },
+};
</script>
<template>
<div>
@@ -28,45 +28,26 @@
<limit-warning :count="items.length" />
</div>
<ul class="stage-event-list">
- <li
- v-for="(mergeRequest, i) in items"
- :key="i"
- class="stage-event-item"
- >
+ <li v-for="(mergeRequest, i) in items" :key="i" class="stage-event-item">
<div class="item-details">
<!-- FIXME: Pass an alt attribute here for accessibility -->
<user-avatar-image :img-src="mergeRequest.author.avatarUrl" />
<h5 class="item-title merge-merquest-title">
- <a :href="mergeRequest.url">
- {{ mergeRequest.title }}
- </a>
+ <a :href="mergeRequest.url"> {{ mergeRequest.title }} </a>
</h5>
- <a
- :href="mergeRequest.url"
- class="issue-link">
- !{{ mergeRequest.iid }}
- </a>
- &middot;
+ <a :href="mergeRequest.url" class="issue-link"> !{{ mergeRequest.iid }} </a> &middot;
<span>
{{ s__('OpenedNDaysAgo|Opened') }}
- <a
- :href="mergeRequest.url"
- class="issue-date">
- {{ mergeRequest.createdAt }}
- </a>
+ <a :href="mergeRequest.url" class="issue-date"> {{ mergeRequest.createdAt }} </a>
</span>
<span>
{{ s__('ByAuthor|by') }}
- <a
- :href="mergeRequest.author.webUrl"
- class="issue-author-link">
+ <a :href="mergeRequest.author.webUrl" class="issue-author-link">
{{ mergeRequest.author.name }}
</a>
</span>
</div>
- <div class="item-time">
- <total-time :time="mergeRequest.totalTime" />
- </div>
+ <div class="item-time"><total-time :time="mergeRequest.totalTime" /></div>
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_component.vue b/app/assets/javascripts/cycle_analytics/components/stage_component.vue
index 312fe75dde4..c4f5172df3b 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_component.vue
+++ b/app/assets/javascripts/cycle_analytics/components/stage_component.vue
@@ -1,25 +1,25 @@
<script>
- import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
- import limitWarning from './limit_warning_component.vue';
- import totalTime from './total_time_component.vue';
+import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
+import limitWarning from './limit_warning_component.vue';
+import totalTime from './total_time_component.vue';
- export default {
- components: {
- userAvatarImage,
- limitWarning,
- totalTime,
+export default {
+ components: {
+ userAvatarImage,
+ limitWarning,
+ totalTime,
+ },
+ props: {
+ items: {
+ type: Array,
+ default: () => [],
},
- props: {
- items: {
- type: Array,
- default: () => [],
- },
- stage: {
- type: Object,
- default: () => ({}),
- },
+ stage: {
+ type: Object,
+ default: () => ({}),
},
- };
+ },
+};
</script>
<template>
<div>
@@ -28,49 +28,25 @@
<limit-warning :count="items.length" />
</div>
<ul class="stage-event-list">
- <li
- v-for="(issue, i) in items"
- :key="i"
- class="stage-event-item"
- >
+ <li v-for="(issue, i) in items" :key="i" class="stage-event-item">
<div class="item-details">
<!-- FIXME: Pass an alt attribute here for accessibility -->
- <user-avatar-image :img-src="issue.author.avatarUrl"/>
+ <user-avatar-image :img-src="issue.author.avatarUrl" />
<h5 class="item-title issue-title">
- <a
- :href="issue.url"
- class="issue-title"
- >
- {{ issue.title }}
- </a>
+ <a :href="issue.url" class="issue-title"> {{ issue.title }} </a>
</h5>
- <a
- :href="issue.url"
- class="issue-link"
- >#{{ issue.iid }}</a>
- &middot;
+ <a :href="issue.url" class="issue-link">#{{ issue.iid }}</a> &middot;
<span>
{{ s__('OpenedNDaysAgo|Opened') }}
- <a
- :href="issue.url"
- class="issue-date"
- >{{ issue.createdAt }}</a>
+ <a :href="issue.url" class="issue-date">{{ issue.createdAt }}</a>
</span>
<span>
{{ s__('ByAuthor|by') }}
- <a
- :href="issue.author.webUrl"
- class="issue-author-link"
- >
- {{ issue.author.name }}
- </a>
+ <a :href="issue.author.webUrl" class="issue-author-link"> {{ issue.author.name }} </a>
</span>
</div>
- <div class="item-time">
- <total-time :time="issue.totalTime" />
- </div>
+ <div class="item-time"><total-time :time="issue.totalTime" /></div>
</li>
</ul>
</div>
</template>
-
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_plan_component.vue b/app/assets/javascripts/cycle_analytics/components/stage_plan_component.vue
index cee294b4ac2..6c256fa6736 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_plan_component.vue
+++ b/app/assets/javascripts/cycle_analytics/components/stage_plan_component.vue
@@ -1,31 +1,31 @@
<script>
- import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
- import iconCommit from '../svg/icon_commit.svg';
- import limitWarning from './limit_warning_component.vue';
- import totalTime from './total_time_component.vue';
+import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
+import iconCommit from '../svg/icon_commit.svg';
+import limitWarning from './limit_warning_component.vue';
+import totalTime from './total_time_component.vue';
- export default {
- components: {
- userAvatarImage,
- totalTime,
- limitWarning,
+export default {
+ components: {
+ userAvatarImage,
+ totalTime,
+ limitWarning,
+ },
+ props: {
+ items: {
+ type: Array,
+ default: () => [],
},
- props: {
- items: {
- type: Array,
- default: () => [],
- },
- stage: {
- type: Object,
- default: () => ({}),
- },
+ stage: {
+ type: Object,
+ default: () => ({}),
},
- computed: {
- iconCommit() {
- return iconCommit;
- },
+ },
+ computed: {
+ iconCommit() {
+ return iconCommit;
},
- };
+ },
+};
</script>
<template>
<div>
@@ -34,44 +34,26 @@
<limit-warning :count="items.length" />
</div>
<ul class="stage-event-list">
- <li
- v-for="(commit, i) in items"
- :key="i"
- class="stage-event-item"
- >
+ <li v-for="(commit, i) in items" :key="i" class="stage-event-item">
<div class="item-details item-conmmit-component">
<!-- FIXME: Pass an alt attribute here for accessibility -->
<user-avatar-image :img-src="commit.author.avatarUrl" />
<h5 class="item-title commit-title">
- <a :href="commit.commitUrl">
- {{ commit.title }}
- </a>
+ <a :href="commit.commitUrl"> {{ commit.title }} </a>
</h5>
<span>
- {{ s__('FirstPushedBy|First') }}
- <span
- class="commit-icon"
- v-html="iconCommit"
- >
- </span>
- <a
- :href="commit.commitUrl"
- class="commit-hash-link commit-sha"
- >{{ commit.shortSha }}</a>
+ {{ s__('FirstPushedBy|First') }} <span class="commit-icon" v-html="iconCommit"> </span>
+ <a :href="commit.commitUrl" class="commit-hash-link commit-sha">{{
+ commit.shortSha
+ }}</a>
{{ s__('FirstPushedBy|pushed by') }}
- <a
- :href="commit.author.webUrl"
- class="commit-author-link"
- >
+ <a :href="commit.author.webUrl" class="commit-author-link">
{{ commit.author.name }}
</a>
</span>
</div>
- <div class="item-time">
- <total-time :time="commit.totalTime" />
- </div>
+ <div class="item-time"><total-time :time="commit.totalTime" /></div>
</li>
</ul>
</div>
</template>
-
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_review_component.vue b/app/assets/javascripts/cycle_analytics/components/stage_review_component.vue
index d4735d030fc..f874f11aff0 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_review_component.vue
+++ b/app/assets/javascripts/cycle_analytics/components/stage_review_component.vue
@@ -1,27 +1,27 @@
<script>
- import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
- import limitWarning from './limit_warning_component.vue';
- import totalTime from './total_time_component.vue';
- import icon from '../../vue_shared/components/icon.vue';
+import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
+import limitWarning from './limit_warning_component.vue';
+import totalTime from './total_time_component.vue';
+import icon from '../../vue_shared/components/icon.vue';
- export default {
- components: {
- userAvatarImage,
- totalTime,
- limitWarning,
- icon,
+export default {
+ components: {
+ userAvatarImage,
+ totalTime,
+ limitWarning,
+ icon,
+ },
+ props: {
+ items: {
+ type: Array,
+ default: () => [],
},
- props: {
- items: {
- type: Array,
- default: () => [],
- },
- stage: {
- type: Object,
- default: () => ({}),
- },
+ stage: {
+ type: Object,
+ default: () => ({}),
},
- };
+ },
+};
</script>
<template>
<div>
@@ -30,66 +30,37 @@
<limit-warning :count="items.length" />
</div>
<ul class="stage-event-list">
- <li
- v-for="(mergeRequest, i) in items"
- :key="i"
- class="stage-event-item"
- >
+ <li v-for="(mergeRequest, i) in items" :key="i" class="stage-event-item">
<div class="item-details">
<!-- FIXME: Pass an alt attribute here for accessibility -->
<user-avatar-image :img-src="mergeRequest.author.avatarUrl" />
<h5 class="item-title merge-merquest-title">
- <a :href="mergeRequest.url">
- {{ mergeRequest.title }}
- </a>
+ <a :href="mergeRequest.url"> {{ mergeRequest.title }} </a>
</h5>
- <a
- :href="mergeRequest.url"
- class="issue-link"
- >!{{ mergeRequest.iid }}</a>
- &middot;
+ <a :href="mergeRequest.url" class="issue-link">!{{ mergeRequest.iid }}</a> &middot;
<span>
{{ s__('OpenedNDaysAgo|Opened') }}
- <a
- :href="mergeRequest.url"
- class="issue-date"
- >{{ mergeRequest.createdAt }}</a>
+ <a :href="mergeRequest.url" class="issue-date">{{ mergeRequest.createdAt }}</a>
</span>
<span>
{{ s__('ByAuthor|by') }}
- <a
- :href="mergeRequest.author.webUrl"
- class="issue-author-link"
- >{{ mergeRequest.author.name }}</a>
+ <a :href="mergeRequest.author.webUrl" class="issue-author-link">{{
+ mergeRequest.author.name
+ }}</a>
</span>
<template v-if="mergeRequest.state === 'closed'">
<span class="merge-request-state">
- <i
- class="fa fa-ban"
- aria-hidden="true"
- >
- </i>
- {{ mergeRequest.state.toUpperCase() }}
+ <i class="fa fa-ban" aria-hidden="true"> </i> {{ mergeRequest.state.toUpperCase() }}
</span>
</template>
<template v-else>
- <span
- v-if="mergeRequest.branch"
- class="merge-request-branch"
- >
- <icon
- :size="16"
- name="fork"
- />
- <a :href="mergeRequest.branch.url">
- {{ mergeRequest.branch.name }}
- </a>
+ <span v-if="mergeRequest.branch" class="merge-request-branch">
+ <icon :size="16" name="fork" />
+ <a :href="mergeRequest.branch.url"> {{ mergeRequest.branch.name }} </a>
</span>
</template>
</div>
- <div class="item-time">
- <total-time :time="mergeRequest.totalTime" />
- </div>
+ <div class="item-time"><total-time :time="mergeRequest.totalTime" /></div>
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue b/app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue
index 22637485c01..c5146c3bf88 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue
+++ b/app/assets/javascripts/cycle_analytics/components/stage_staging_component.vue
@@ -1,33 +1,33 @@
<script>
- import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
- import iconBranch from '../svg/icon_branch.svg';
- import limitWarning from './limit_warning_component.vue';
- import totalTime from './total_time_component.vue';
- import icon from '../../vue_shared/components/icon.vue';
+import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
+import iconBranch from '../svg/icon_branch.svg';
+import limitWarning from './limit_warning_component.vue';
+import totalTime from './total_time_component.vue';
+import icon from '../../vue_shared/components/icon.vue';
- export default {
- components: {
- userAvatarImage,
- totalTime,
- limitWarning,
- icon,
+export default {
+ components: {
+ userAvatarImage,
+ totalTime,
+ limitWarning,
+ icon,
+ },
+ props: {
+ items: {
+ type: Array,
+ default: () => [],
},
- props: {
- items: {
- type: Array,
- default: () => [],
- },
- stage: {
- type: Object,
- default: () => ({}),
- },
+ stage: {
+ type: Object,
+ default: () => ({}),
},
- computed: {
- iconBranch() {
- return iconBranch;
- },
+ },
+ computed: {
+ iconBranch() {
+ return iconBranch;
},
- };
+ },
+};
</script>
<template>
<div>
@@ -36,62 +36,23 @@
<limit-warning :count="items.length" />
</div>
<ul class="stage-event-list">
- <li
- v-for="(build, i) in items"
- :key="i"
- class="stage-event-item item-build-component"
- >
+ <li v-for="(build, i) in items" :key="i" class="stage-event-item item-build-component">
<div class="item-details">
<!-- FIXME: Pass an alt attribute here for accessibility -->
- <user-avatar-image :img-src="build.author.avatarUrl"/>
+ <user-avatar-image :img-src="build.author.avatarUrl" />
<h5 class="item-title">
- <a
- :href="build.url"
- class="pipeline-id"
- >
- #{{ build.id }}
- </a>
- <icon
- :size="16"
- name="fork"
- />
- <a
- :href="build.branch.url"
- class="ref-name"
- >
- {{ build.branch.name }}
- </a>
- <span
- class="icon-branch"
- v-html="iconBranch"
- >
- </span>
- <a
- :href="build.commitUrl"
- class="commit-sha"
- >
- {{ build.shortSha }}
- </a>
+ <a :href="build.url" class="pipeline-id"> #{{ build.id }} </a>
+ <icon :size="16" name="fork" />
+ <a :href="build.branch.url" class="ref-name"> {{ build.branch.name }} </a>
+ <span class="icon-branch" v-html="iconBranch"> </span>
+ <a :href="build.commitUrl" class="commit-sha"> {{ build.shortSha }} </a>
</h5>
<span>
- <a
- :href="build.url"
- class="build-date"
- >
- {{ build.date }}
- </a>
- {{ s__('ByAuthor|by') }}
- <a
- :href="build.author.webUrl"
- class="issue-author-link"
- >
- {{ build.author.name }}
- </a>
+ <a :href="build.url" class="build-date"> {{ build.date }} </a> {{ s__('ByAuthor|by') }}
+ <a :href="build.author.webUrl" class="issue-author-link"> {{ build.author.name }} </a>
</span>
</div>
- <div class="item-time">
- <total-time :time="build.totalTime" />
- </div>
+ <div class="item-time"><total-time :time="build.totalTime" /></div>
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/cycle_analytics/components/stage_test_component.vue b/app/assets/javascripts/cycle_analytics/components/stage_test_component.vue
index a0796f299e7..35721384210 100644
--- a/app/assets/javascripts/cycle_analytics/components/stage_test_component.vue
+++ b/app/assets/javascripts/cycle_analytics/components/stage_test_component.vue
@@ -1,35 +1,35 @@
<script>
- import iconBuildStatus from '../svg/icon_build_status.svg';
- import iconBranch from '../svg/icon_branch.svg';
- import limitWarning from './limit_warning_component.vue';
- import totalTime from './total_time_component.vue';
- import icon from '../../vue_shared/components/icon.vue';
+import iconBuildStatus from '../svg/icon_build_status.svg';
+import iconBranch from '../svg/icon_branch.svg';
+import limitWarning from './limit_warning_component.vue';
+import totalTime from './total_time_component.vue';
+import icon from '../../vue_shared/components/icon.vue';
- export default {
- components: {
- totalTime,
- limitWarning,
- icon,
+export default {
+ components: {
+ totalTime,
+ limitWarning,
+ icon,
+ },
+ props: {
+ items: {
+ type: Array,
+ default: () => [],
},
- props: {
- items: {
- type: Array,
- default: () => [],
- },
- stage: {
- type: Object,
- default: () => ({}),
- },
+ stage: {
+ type: Object,
+ default: () => ({}),
},
- computed: {
- iconBuildStatus() {
- return iconBuildStatus;
- },
- iconBranch() {
- return iconBranch;
- },
+ },
+ computed: {
+ iconBuildStatus() {
+ return iconBuildStatus;
},
- };
+ iconBranch() {
+ return iconBranch;
+ },
+ },
+};
</script>
<template>
<div>
@@ -38,63 +38,22 @@
<limit-warning :count="items.length" />
</div>
<ul class="stage-event-list">
- <li
- v-for="(build, i) in items"
- :key="i"
- class="stage-event-item item-build-component"
- >
+ <li v-for="(build, i) in items" :key="i" class="stage-event-item item-build-component">
<div class="item-details">
<h5 class="item-title">
- <span
- class="icon-build-status"
- v-html="iconBuildStatus"
- >
- </span>
- <a
- :href="build.url"
- class="item-build-name"
- >
- {{ build.name }}
- </a>
- &middot;
- <a
- :href="build.url"
- class="pipeline-id"
- >
- #{{ build.id }}
- </a>
- <icon
- :size="16"
- name="fork"
- />
- <a
- :href="build.branch.url"
- class="ref-name"
- >
- {{ build.branch.name }}
- </a>
- <span
- class="icon-branch"
- v-html="iconBranch"
- >
- </span>
- <a
- :href="build.commitUrl"
- class="commit-sha">
- {{ build.shortSha }}
- </a>
+ <span class="icon-build-status" v-html="iconBuildStatus"> </span>
+ <a :href="build.url" class="item-build-name"> {{ build.name }} </a> &middot;
+ <a :href="build.url" class="pipeline-id"> #{{ build.id }} </a>
+ <icon :size="16" name="fork" />
+ <a :href="build.branch.url" class="ref-name"> {{ build.branch.name }} </a>
+ <span class="icon-branch" v-html="iconBranch"> </span>
+ <a :href="build.commitUrl" class="commit-sha"> {{ build.shortSha }} </a>
</h5>
<span>
- <a
- :href="build.url"
- class="issue-date">
- {{ build.date }}
- </a>
+ <a :href="build.url" class="issue-date"> {{ build.date }} </a>
</span>
</div>
- <div class="item-time">
- <total-time :time="build.totalTime" />
- </div>
+ <div class="item-time"><total-time :time="build.totalTime" /></div>
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/cycle_analytics/components/total_time_component.vue b/app/assets/javascripts/cycle_analytics/components/total_time_component.vue
index 7758bf0cb3f..b93a7d3c4f9 100644
--- a/app/assets/javascripts/cycle_analytics/components/total_time_component.vue
+++ b/app/assets/javascripts/cycle_analytics/components/total_time_component.vue
@@ -1,45 +1,33 @@
<script>
- export default {
- props: {
- time: {
- type: Object,
- required: false,
- default: () => ({}),
- },
+export default {
+ props: {
+ time: {
+ type: Object,
+ required: false,
+ default: () => ({}),
},
- computed: {
- hasData() {
- return Object.keys(this.time).length;
- },
+ },
+ computed: {
+ hasData() {
+ return Object.keys(this.time).length;
},
- };
+ },
+};
</script>
<template>
<span class="total-time">
<template v-if="hasData">
<template v-if="time.days">
- {{ time.days }}
- <span>
- {{ n__('day', 'days', time.days) }}
- </span>
+ {{ time.days }} <span> {{ n__('day', 'days', time.days) }} </span>
</template>
<template v-if="time.hours">
- {{ time.hours }}
- <span>
- {{ n__('Time|hr', 'Time|hrs', time.hours) }}
- </span>
+ {{ time.hours }} <span> {{ n__('Time|hr', 'Time|hrs', time.hours) }} </span>
</template>
<template v-if="time.mins && !time.days">
- {{ time.mins }}
- <span>
- {{ n__('Time|min', 'Time|mins', time.mins) }}
- </span>
+ {{ time.mins }} <span> {{ n__('Time|min', 'Time|mins', time.mins) }} </span>
</template>
- <template v-if="time.seconds && hasData === 1 || time.seconds === 0">
- {{ time.seconds }}
- <span>
- {{ s__('Time|s') }}
- </span>
+ <template v-if="(time.seconds && hasData === 1) || time.seconds === 0">
+ {{ time.seconds }} <span> {{ s__('Time|s') }} </span>
</template>
</template>
<template v-else>
diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
index 1c43fc3cdc7..4de425b48e7 100644
--- a/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
+++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_bundle.js
@@ -18,7 +18,8 @@ Vue.use(Translate);
export default () => {
const OVERVIEW_DIALOG_COOKIE = 'cycle_analytics_help_dismissed';
- new Vue({ // eslint-disable-line no-new
+ // eslint-disable-next-line no-new
+ new Vue({
el: '#cycle-analytics',
name: 'CycleAnalytics',
components: {
@@ -66,14 +67,17 @@ export default () => {
const $dropdown = $('.js-ca-dropdown');
const $label = $dropdown.find('.dropdown-label');
- $dropdown.find('li a').off('click').on('click', (e) => {
- e.preventDefault();
- const $target = $(e.currentTarget);
- this.startDate = $target.data('value');
+ $dropdown
+ .find('li a')
+ .off('click')
+ .on('click', e => {
+ e.preventDefault();
+ const $target = $(e.currentTarget);
+ this.startDate = $target.data('value');
- $label.text($target.text().trim());
- this.fetchCycleAnalyticsData({ startDate: this.startDate });
- });
+ $label.text($target.text().trim());
+ this.fetchCycleAnalyticsData({ startDate: this.startDate });
+ });
},
fetchCycleAnalyticsData(options) {
const fetchOptions = options || { startDate: this.startDate };
@@ -82,7 +86,7 @@ export default () => {
this.service
.fetchCycleAnalyticsData(fetchOptions)
- .then((response) => {
+ .then(response => {
this.store.setCycleAnalyticsData(response);
this.selectDefaultStage();
this.initDropdown();
@@ -115,7 +119,7 @@ export default () => {
stage,
startDate: this.startDate,
})
- .then((response) => {
+ .then(response => {
this.isEmptyStage = !response.events.length;
this.store.setStageEvents(response.events, stage);
this.isLoadingStage = false;
diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js
index 4cf416c50e5..a0426301a0a 100644
--- a/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js
+++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_service.js
@@ -18,10 +18,7 @@ export default class CycleAnalyticsService {
}
fetchStageData(options) {
- const {
- stage,
- startDate,
- } = options;
+ const { stage, startDate } = options;
return this.axios
.get(`events/${stage.name}.json`, {
diff --git a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js
index a8cd8c20f8f..18fb57c8b4f 100644
--- a/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js
+++ b/app/assets/javascripts/cycle_analytics/cycle_analytics_store.js
@@ -5,13 +5,27 @@ import { dasherize } from '../lib/utils/text_utility';
import DEFAULT_EVENT_OBJECTS from './default_event_objects';
const EMPTY_STAGE_TEXTS = {
- issue: __('The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.'),
- plan: __('The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.'),
- code: __('The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.'),
- test: __('The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.'),
- review: __('The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request.'),
- staging: __('The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.'),
- production: __('The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.'),
+ issue: __(
+ 'The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.',
+ ),
+ plan: __(
+ 'The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit.',
+ ),
+ code: __(
+ 'The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request.',
+ ),
+ test: __(
+ 'The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running.',
+ ),
+ review: __(
+ 'The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request.',
+ ),
+ staging: __(
+ 'The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time.',
+ ),
+ production: __(
+ 'The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle.',
+ ),
};
export default {
@@ -31,11 +45,11 @@ export default {
newData.stages = data.stats || [];
newData.summary = data.summary || [];
- newData.summary.forEach((item) => {
+ newData.summary.forEach(item => {
item.value = item.value || '-';
});
- newData.stages.forEach((item) => {
+ newData.stages.forEach(item => {
const stageSlug = dasherize(item.name.toLowerCase());
item.active = false;
item.isUserAllowed = data.permissions[stageSlug];
@@ -53,7 +67,7 @@ export default {
this.state.hasError = state;
},
deactivateAllStages() {
- this.state.stages.forEach((stage) => {
+ this.state.stages.forEach(stage => {
stage.active = false;
});
},
@@ -67,7 +81,7 @@ export default {
decorateEvents(events, stage) {
const newEvents = [];
- events.forEach((item) => {
+ events.forEach(item => {
if (!item) return;
const eventItem = Object.assign({}, DEFAULT_EVENT_OBJECTS[stage.slug], item);
diff --git a/app/assets/javascripts/deploy_keys/components/action_btn.vue b/app/assets/javascripts/deploy_keys/components/action_btn.vue
index 10548da8ec5..af7c391ab70 100644
--- a/app/assets/javascripts/deploy_keys/components/action_btn.vue
+++ b/app/assets/javascripts/deploy_keys/components/action_btn.vue
@@ -1,7 +1,11 @@
<script>
+import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '../eventhub';
export default {
+ components: {
+ GlLoadingIcon,
+ },
props: {
deployKey: {
type: Object,
@@ -39,11 +43,9 @@ export default {
:class="[{ disabled: isLoading }, btnCssClass]"
:disabled="isLoading"
class="btn"
- @click="doAction">
+ @click="doAction"
+ >
<slot></slot>
- <gl-loading-icon
- v-if="isLoading"
- :inline="true"
- />
+ <gl-loading-icon v-if="isLoading" :inline="true" />
</button>
</template>
diff --git a/app/assets/javascripts/deploy_keys/components/app.vue b/app/assets/javascripts/deploy_keys/components/app.vue
index aa52f120fe7..922c907bb36 100644
--- a/app/assets/javascripts/deploy_keys/components/app.vue
+++ b/app/assets/javascripts/deploy_keys/components/app.vue
@@ -6,11 +6,13 @@ import eventHub from '../eventhub';
import DeployKeysService from '../service';
import DeployKeysStore from '../store';
import KeysPanel from './keys_panel.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
components: {
KeysPanel,
NavigationTabs,
+ GlLoadingIcon,
},
props: {
endpoint: {
@@ -95,8 +97,10 @@ export default {
.catch(() => new Flash(s__('DeployKeys|Error enabling deploy key')));
},
disableKey(deployKey, callback) {
- // eslint-disable-next-line no-alert
- if (window.confirm(s__('DeployKeys|You are going to remove this deploy key. Are you sure?'))) {
+ if (
+ // eslint-disable-next-line no-alert
+ window.confirm(s__('DeployKeys|You are going to remove this deploy key. Are you sure?'))
+ ) {
this.service
.disableKey(deployKey.id)
.then(this.fetchKeys)
@@ -119,26 +123,10 @@ export default {
/>
<template v-else-if="hasKeys">
<div class="top-area scrolling-tabs-container inner-page-scroll-tabs">
- <div class="fade-left">
- <i
- class="fa fa-angle-left"
- aria-hidden="true"
- >
- </i>
- </div>
- <div class="fade-right">
- <i
- class="fa fa-angle-right"
- aria-hidden="true"
- >
- </i>
- </div>
+ <div class="fade-left"><i class="fa fa-angle-left" aria-hidden="true"> </i></div>
+ <div class="fade-right"><i class="fa fa-angle-right" aria-hidden="true"> </i></div>
- <navigation-tabs
- :tabs="tabs"
- scope="deployKeys"
- @onChangeTab="onChangeTab"
- />
+ <navigation-tabs :tabs="tabs" scope="deployKeys" @onChangeTab="onChangeTab" />
</div>
<keys-panel
:project-id="projectId"
diff --git a/app/assets/javascripts/deploy_keys/components/key.vue b/app/assets/javascripts/deploy_keys/components/key.vue
index f66ca070445..f01e6f2a639 100644
--- a/app/assets/javascripts/deploy_keys/components/key.vue
+++ b/app/assets/javascripts/deploy_keys/components/key.vue
@@ -112,26 +112,14 @@ export default {
<template>
<div class="gl-responsive-table-row deploy-key">
<div class="table-section section-40">
- <div
- role="rowheader"
- class="table-mobile-header">
- {{ s__('DeployKeys|Deploy key') }}
- </div>
+ <div role="rowheader" class="table-mobile-header">{{ s__('DeployKeys|Deploy key') }}</div>
<div class="table-mobile-content">
- <strong class="title qa-key-title">
- {{ deployKey.title }}
- </strong>
- <div class="fingerprint qa-key-fingerprint">
- {{ deployKey.fingerprint }}
- </div>
+ <strong class="title qa-key-title"> {{ deployKey.title }} </strong>
+ <div class="fingerprint qa-key-fingerprint">{{ deployKey.fingerprint }}</div>
</div>
</div>
<div class="table-section section-30 section-wrap">
- <div
- role="rowheader"
- class="table-mobile-header">
- {{ s__('DeployKeys|Project usage') }}
- </div>
+ <div role="rowheader" class="table-mobile-header">{{ s__('DeployKeys|Project usage') }}</div>
<div class="table-mobile-content deploy-project-list">
<template v-if="projects.length > 0">
<a
@@ -139,14 +127,12 @@ export default {
:title="projectTooltipTitle(firstProject)"
class="label deploy-project-label"
>
- <span>
- {{ firstProject.project.full_name }}
- </span>
- <icon :name="firstProject.can_push ? 'lock-open' : 'lock'"/>
+ <span> {{ firstProject.project.full_name }} </span>
+ <icon :name="firstProject.can_push ? 'lock-open' : 'lock'" />
</a>
<a
- v-tooltip
v-if="isExpandable"
+ v-tooltip
:title="restProjectsTooltip"
class="label deploy-project-label"
@click="toggleExpanded"
@@ -154,80 +140,65 @@ export default {
<span>{{ restProjectsLabel }}</span>
</a>
<a
- v-tooltip
v-for="deployKeysProject in restProjects"
v-else-if="isExpanded"
:key="deployKeysProject.project.full_path"
+ v-tooltip
:href="deployKeysProject.project.full_path"
:title="projectTooltipTitle(deployKeysProject)"
class="label deploy-project-label"
>
- <span>
- {{ deployKeysProject.project.full_name }}
- </span>
- <icon :name="deployKeysProject.can_push ? 'lock-open' : 'lock'"/>
+ <span> {{ deployKeysProject.project.full_name }} </span>
+ <icon :name="deployKeysProject.can_push ? 'lock-open' : 'lock'" />
</a>
</template>
- <span
- v-else
- class="text-secondary">{{ __('None') }}</span>
+ <span v-else class="text-secondary">{{ __('None') }}</span>
</div>
</div>
<div class="table-section section-15 text-right">
- <div
- role="rowheader"
- class="table-mobile-header">
- {{ __('Created') }}
- </div>
+ <div role="rowheader" class="table-mobile-header">{{ __('Created') }}</div>
<div class="table-mobile-content text-secondary key-created-at">
- <span
- v-tooltip
- :title="tooltipTitle(deployKey.created_at)">
- <icon name="calendar"/>
- <span>{{ timeFormated(deployKey.created_at) }}</span>
+ <span v-tooltip :title="tooltipTitle(deployKey.created_at)">
+ <icon name="calendar" /> <span>{{ timeFormated(deployKey.created_at) }}</span>
</span>
</div>
</div>
<div class="table-section section-15 table-button-footer deploy-key-actions">
<div class="btn-group table-action-buttons">
- <action-btn
- v-if="!isEnabled"
- :deploy-key="deployKey"
- type="enable"
- >
+ <action-btn v-if="!isEnabled" :deploy-key="deployKey" type="enable">
{{ __('Enable') }}
</action-btn>
<a
- v-tooltip
v-if="deployKey.can_edit"
+ v-tooltip
:href="editDeployKeyPath"
:title="__('Edit')"
class="btn btn-default text-secondary"
data-container="body"
>
- <icon name="pencil"/>
+ <icon name="pencil" />
</a>
<action-btn
- v-tooltip
v-if="isRemovable"
+ v-tooltip
:deploy-key="deployKey"
:title="__('Remove')"
btn-css-class="btn-danger"
type="remove"
data-container="body"
>
- <icon name="remove"/>
+ <icon name="remove" />
</action-btn>
<action-btn
- v-tooltip
v-else-if="isEnabled"
+ v-tooltip
:deploy-key="deployKey"
:title="__('Disable')"
btn-css-class="btn-warning"
type="disable"
data-container="body"
>
- <icon name="cancel"/>
+ <icon name="cancel" />
</action-btn>
</div>
</div>
diff --git a/app/assets/javascripts/deploy_keys/components/keys_panel.vue b/app/assets/javascripts/deploy_keys/components/keys_panel.vue
index 2f057ca29f6..2693cd08cc3 100644
--- a/app/assets/javascripts/deploy_keys/components/keys_panel.vue
+++ b/app/assets/javascripts/deploy_keys/components/keys_panel.vue
@@ -30,24 +30,14 @@ export default {
<template>
<div class="deploy-keys-panel table-holder">
<template v-if="keys.length > 0">
- <div
- role="row"
- class="gl-responsive-table-row table-row-header">
- <div
- role="rowheader"
- class="table-section section-40">
+ <div role="row" class="gl-responsive-table-row table-row-header">
+ <div role="rowheader" class="table-section section-40">
{{ s__('DeployKeys|Deploy key') }}
</div>
- <div
- role="rowheader"
- class="table-section section-30">
+ <div role="rowheader" class="table-section section-30">
{{ s__('DeployKeys|Project usage') }}
</div>
- <div
- role="rowheader"
- class="table-section section-15 text-right">
- {{ __('Created') }}
- </div>
+ <div role="rowheader" class="table-section section-15 text-right">{{ __('Created') }}</div>
</div>
<deploy-key
v-for="deployKey in keys"
@@ -58,10 +48,7 @@ export default {
:project-id="projectId"
/>
</template>
- <div
- v-else
- class="settings-message text-center"
- >
+ <div v-else class="settings-message text-center">
{{ s__('DeployKeys|No deploy keys found. Create one with the form above.') }}
</div>
</div>
diff --git a/app/assets/javascripts/deploy_keys/service/index.js b/app/assets/javascripts/deploy_keys/service/index.js
index 9dc3b21f6f6..268a37008c5 100644
--- a/app/assets/javascripts/deploy_keys/service/index.js
+++ b/app/assets/javascripts/deploy_keys/service/index.js
@@ -8,17 +8,14 @@ export default class DeployKeysService {
}
getKeys() {
- return this.axios.get()
- .then(response => response.data);
+ return this.axios.get().then(response => response.data);
}
enableKey(id) {
- return this.axios.put(`${id}/enable`)
- .then(response => response.data);
+ return this.axios.put(`${id}/enable`).then(response => response.data);
}
disableKey(id) {
- return this.axios.put(`${id}/disable`)
- .then(response => response.data);
+ return this.axios.put(`${id}/disable`).then(response => response.data);
}
}
diff --git a/app/assets/javascripts/diff.js b/app/assets/javascripts/diff.js
index a044fc1ab42..245f1a7c558 100644
--- a/app/assets/javascripts/diff.js
+++ b/app/assets/javascripts/diff.js
@@ -21,9 +21,12 @@ export default class Diff {
});
const tab = document.getElementById('diffs');
- if (!tab || (tab && tab.dataset && tab.dataset.isLocked !== '')) FilesCommentButton.init($diffFile);
+ if (!tab || (tab && tab.dataset && tab.dataset.isLocked !== ''))
+ FilesCommentButton.init($diffFile);
- const firstFile = $('.files').first().get(0);
+ const firstFile = $('.files')
+ .first()
+ .get(0);
const canCreateNote = firstFile && firstFile.hasAttribute('data-can-create-note');
$diffFile.each((index, file) => imageDiffHelper.initImageDiff(file, canCreateNote));
@@ -73,9 +76,10 @@ export default class Diff {
const view = file.data('view');
const params = { since, to, bottom, offset, unfold, view };
- axios.get(link, { params })
- .then(({ data }) => $target.parent().replaceWith(data))
- .catch(() => flash(__('An error occurred while loading diff')));
+ axios
+ .get(link, { params })
+ .then(({ data }) => $target.parent().replaceWith(data))
+ .catch(() => flash(__('An error occurred while loading diff')));
}
openAnchoredDiff(cb) {
diff --git a/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js b/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js
index ed24d1775f4..4ae4ceabc21 100644
--- a/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js
+++ b/app/assets/javascripts/diff_notes/components/comment_resolve_btn.js
@@ -1,4 +1,4 @@
-/* eslint-disable comma-dangle, object-shorthand, func-names, no-else-return, quotes, no-lonely-if, max-len */
+/* eslint-disable object-shorthand, func-names, no-else-return, no-lonely-if */
/* global CommentsStore */
import $ from 'jquery';
@@ -18,52 +18,56 @@ const CommentAndResolveBtn = Vue.extend({
};
},
computed: {
- showButton: function () {
+ showButton: function() {
if (this.discussion) {
return this.discussion.isResolvable();
} else {
return false;
}
},
- isDiscussionResolved: function () {
+ isDiscussionResolved: function() {
return this.discussion.isResolved();
},
- buttonText: function () {
+ buttonText: function() {
if (this.isDiscussionResolved) {
if (this.textareaIsEmpty) {
- return "Unresolve discussion";
+ return 'Unresolve discussion';
} else {
- return "Comment & unresolve discussion";
+ return 'Comment & unresolve discussion';
}
} else {
if (this.textareaIsEmpty) {
- return "Resolve discussion";
+ return 'Resolve discussion';
} else {
- return "Comment & resolve discussion";
+ return 'Comment & resolve discussion';
}
}
- }
+ },
},
created() {
if (this.discussionId) {
this.discussion = CommentsStore.state[this.discussionId];
}
},
- mounted: function () {
+ mounted: function() {
if (!this.discussionId) return;
- const $textarea = $(`.js-discussion-note-form[data-discussion-id=${this.discussionId}] .note-textarea`);
+ const $textarea = $(
+ `.js-discussion-note-form[data-discussion-id=${this.discussionId}] .note-textarea`,
+ );
this.textareaIsEmpty = $textarea.val() === '';
$textarea.on('input.comment-and-resolve-btn', () => {
this.textareaIsEmpty = $textarea.val() === '';
});
},
- destroyed: function () {
+ destroyed: function() {
if (!this.discussionId) return;
- $(`.js-discussion-note-form[data-discussion-id=${this.discussionId}] .note-textarea`).off('input.comment-and-resolve-btn');
- }
+ $(`.js-discussion-note-form[data-discussion-id=${this.discussionId}] .note-textarea`).off(
+ 'input.comment-and-resolve-btn',
+ );
+ },
});
Vue.component('comment-and-resolve-btn', CommentAndResolveBtn);
diff --git a/app/assets/javascripts/diff_notes/components/diff_note_avatars.js b/app/assets/javascripts/diff_notes/components/diff_note_avatars.js
index 5528d2a542b..5bdeaaade68 100644
--- a/app/assets/javascripts/diff_notes/components/diff_note_avatars.js
+++ b/app/assets/javascripts/diff_notes/components/diff_note_avatars.js
@@ -83,7 +83,11 @@ const DiffNoteAvatars = Vue.extend({
this.addNoCommentClass();
this.setDiscussionVisible();
- this.lineType = $(this.$el).closest('.diff-line-num').hasClass('old_line') ? 'old' : 'new';
+ this.lineType = $(this.$el)
+ .closest('.diff-line-num')
+ .hasClass('old_line')
+ ? 'old'
+ : 'new';
});
$(document).on('toggle.comments', () => {
@@ -113,20 +117,30 @@ const DiffNoteAvatars = Vue.extend({
addNoCommentClass() {
const { notesCount } = this;
- $(this.$el).closest('.js-avatar-container')
+ $(this.$el)
+ .closest('.js-avatar-container')
.toggleClass('no-comment-btn', notesCount > 0)
.nextUntil('.js-avatar-container')
.toggleClass('no-comment-btn', notesCount > 0);
},
toggleDiscussionsToggleState() {
- const $notesHolders = $(this.$el).closest('.code').find('.notes_holder');
+ const $notesHolders = $(this.$el)
+ .closest('.code')
+ .find('.notes_holder');
const $visibleNotesHolders = $notesHolders.filter(':visible');
- const $toggleDiffCommentsBtn = $(this.$el).closest('.diff-file').find('.js-toggle-diff-comments');
-
- $toggleDiffCommentsBtn.toggleClass('active', $notesHolders.length === $visibleNotesHolders.length);
+ const $toggleDiffCommentsBtn = $(this.$el)
+ .closest('.diff-file')
+ .find('.js-toggle-diff-comments');
+
+ $toggleDiffCommentsBtn.toggleClass(
+ 'active',
+ $notesHolders.length === $visibleNotesHolders.length,
+ );
},
setDiscussionVisible() {
- this.isVisible = $(`.diffs .notes[data-discussion-id="${this.discussion.id}"]`).is(':visible');
+ this.isVisible = $(`.diffs .notes[data-discussion-id="${this.discussion.id}"]`).is(
+ ':visible',
+ );
},
getTooltipText(note) {
return `${note.authorName}: ${note.noteTruncated}`;
diff --git a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js
index 2b893e35b6d..8542a6e718a 100644
--- a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js
+++ b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js
@@ -1,4 +1,4 @@
-/* eslint-disable comma-dangle, object-shorthand, func-names, no-else-return, guard-for-in, no-restricted-syntax, no-lonely-if, no-continue, brace-style, max-len, quotes */
+/* eslint-disable object-shorthand, func-names, no-else-return, guard-for-in, no-restricted-syntax, no-lonely-if, no-continue */
/* global CommentsStore */
import $ from 'jquery';
@@ -14,24 +14,24 @@ const JumpToDiscussion = Vue.extend({
required: true,
},
},
- data: function () {
+ data: function() {
return {
discussions: CommentsStore.state,
discussion: {},
};
},
computed: {
- buttonText: function () {
+ buttonText: function() {
if (this.discussionId) {
return 'Jump to next unresolved discussion';
} else {
return 'Jump to first unresolved discussion';
}
},
- allResolved: function () {
+ allResolved: function() {
return this.unresolvedDiscussionCount === 0;
},
- showButton: function () {
+ showButton: function() {
if (this.discussionId) {
if (this.unresolvedDiscussionCount > 1) {
return true;
@@ -42,7 +42,7 @@ const JumpToDiscussion = Vue.extend({
return this.unresolvedDiscussionCount >= 1;
}
},
- lastResolvedId: function () {
+ lastResolvedId: function() {
let lastId;
for (const discussionId in this.discussions) {
const discussion = this.discussions[discussionId];
@@ -52,13 +52,13 @@ const JumpToDiscussion = Vue.extend({
}
}
return lastId;
- }
+ },
},
created() {
this.discussion = this.discussions[this.discussionId];
},
methods: {
- jumpToNextUnresolvedDiscussion: function () {
+ jumpToNextUnresolvedDiscussion: function() {
let discussionsSelector;
let discussionIdsInScope;
let firstUnresolvedDiscussionId;
@@ -68,9 +68,11 @@ const JumpToDiscussion = Vue.extend({
let jumpToFirstDiscussion = !this.discussionId;
const discussionIdsForElements = function(elements) {
- return elements.map(function() {
- return $(this).attr('data-discussion-id');
- }).toArray();
+ return elements
+ .map(function() {
+ return $(this).attr('data-discussion-id');
+ })
+ .toArray();
};
const { discussions } = this;
@@ -110,7 +112,7 @@ const JumpToDiscussion = Vue.extend({
if (!hasDiscussionsToJumpTo) {
// If there are no discussions to jump to on the current page,
- // switch to the notes tab and jump to the first disucssion there.
+ // switch to the notes tab and jump to the first discussion there.
window.mrTabs.activateTab('show');
activeTab = 'show';
jumpToFirstDiscussion = true;
@@ -144,8 +146,7 @@ const JumpToDiscussion = Vue.extend({
if (!discussion.isResolved()) {
nextUnresolvedDiscussionId = discussionId;
break;
- }
- else {
+ } else {
continue;
}
}
@@ -175,9 +176,9 @@ const JumpToDiscussion = Vue.extend({
// Resolved discussions are hidden in the diffs tab by default.
// If they are marked unresolved on the notes tab, they will still be hidden on the diffs tab.
// When jumping between unresolved discussions on the diffs tab, we show them.
- $target.closest(".content").show();
+ $target.closest('.content').show();
- const $notesHolder = $target.closest("tr.notes_holder");
+ const $notesHolder = $target.closest('tr.notes_holder');
// Image diff discussions does not use notes_holder
// so we should keep original $target value in those cases
@@ -194,7 +195,7 @@ const JumpToDiscussion = Vue.extend({
prevEl = $target.prev();
// If the discussion doesn't have 4 lines above it, we'll have to do with fewer.
- if (!prevEl.hasClass("line_holder")) {
+ if (!prevEl.hasClass('line_holder')) {
break;
}
@@ -203,9 +204,9 @@ const JumpToDiscussion = Vue.extend({
}
$.scrollTo($target, {
- offset: -150
+ offset: -150,
});
- }
+ },
},
});
diff --git a/app/assets/javascripts/diff_notes/components/resolve_count.js b/app/assets/javascripts/diff_notes/components/resolve_count.js
index e2683e09f40..d8b056096f4 100644
--- a/app/assets/javascripts/diff_notes/components/resolve_count.js
+++ b/app/assets/javascripts/diff_notes/components/resolve_count.js
@@ -1,4 +1,4 @@
-/* eslint-disable comma-dangle, object-shorthand, func-names */
+/* eslint-disable object-shorthand, func-names */
/* global CommentsStore */
import Vue from 'vue';
@@ -13,17 +13,17 @@ window.ResolveCount = Vue.extend({
required: true,
},
},
- data: function () {
+ data: function() {
return {
- discussions: CommentsStore.state
+ discussions: CommentsStore.state,
};
},
computed: {
- allResolved: function () {
+ allResolved: function() {
return this.resolvedDiscussionCount === this.discussionCount;
},
resolvedCountText() {
return this.discussionCount === 1 ? 'discussion' : 'discussions';
- }
- }
+ },
+ },
});
diff --git a/app/assets/javascripts/diff_notes/mixins/discussion.js b/app/assets/javascripts/diff_notes/mixins/discussion.js
index ef35b589e58..dea64dca132 100644
--- a/app/assets/javascripts/diff_notes/mixins/discussion.js
+++ b/app/assets/javascripts/diff_notes/mixins/discussion.js
@@ -1,11 +1,11 @@
-/* eslint-disable object-shorthand, func-names, guard-for-in, no-restricted-syntax, comma-dangle, */
+/* eslint-disable object-shorthand, func-names, guard-for-in, no-restricted-syntax, */
const DiscussionMixins = {
computed: {
- discussionCount: function () {
+ discussionCount: function() {
return Object.keys(this.discussions).length;
},
- resolvedDiscussionCount: function () {
+ resolvedDiscussionCount: function() {
let resolvedCount = 0;
for (const discussionId in this.discussions) {
@@ -18,7 +18,7 @@ const DiscussionMixins = {
return resolvedCount;
},
- unresolvedDiscussionCount: function () {
+ unresolvedDiscussionCount: function() {
let unresolvedCount = 0;
for (const discussionId in this.discussions) {
@@ -30,8 +30,8 @@ const DiscussionMixins = {
}
return unresolvedCount;
- }
- }
+ },
+ },
};
export default DiscussionMixins;
diff --git a/app/assets/javascripts/diff_notes/models/discussion.js b/app/assets/javascripts/diff_notes/models/discussion.js
index 787e6d8855f..daf61e5d467 100644
--- a/app/assets/javascripts/diff_notes/models/discussion.js
+++ b/app/assets/javascripts/diff_notes/models/discussion.js
@@ -6,22 +6,22 @@ import Vue from 'vue';
import { localTimeAgo } from '../../lib/utils/datetime_utility';
class DiscussionModel {
- constructor (discussionId) {
+ constructor(discussionId) {
this.id = discussionId;
this.notes = {};
this.loading = false;
this.canResolve = false;
}
- createNote (noteObj) {
+ createNote(noteObj) {
Vue.set(this.notes, noteObj.noteId, new NoteModel(this.id, noteObj));
}
- deleteNote (noteId) {
+ deleteNote(noteId) {
Vue.delete(this.notes, noteId);
}
- getNote (noteId) {
+ getNote(noteId) {
return this.notes[noteId];
}
@@ -29,7 +29,7 @@ class DiscussionModel {
return Object.keys(this.notes).length;
}
- isResolved () {
+ isResolved() {
for (const noteId in this.notes) {
const note = this.notes[noteId];
@@ -40,7 +40,7 @@ class DiscussionModel {
return true;
}
- resolveAllNotes (resolved_by) {
+ resolveAllNotes(resolved_by) {
for (const noteId in this.notes) {
const note = this.notes[noteId];
@@ -51,7 +51,7 @@ class DiscussionModel {
}
}
- unResolveAllNotes () {
+ unResolveAllNotes() {
for (const noteId in this.notes) {
const note = this.notes[noteId];
@@ -62,7 +62,7 @@ class DiscussionModel {
}
}
- updateHeadline (data) {
+ updateHeadline(data) {
const discussionSelector = `.discussion[data-discussion-id="${this.id}"]`;
const $discussionHeadline = $(`${discussionSelector} .js-discussion-headline`);
@@ -79,7 +79,7 @@ class DiscussionModel {
}
}
- isResolvable () {
+ isResolvable() {
if (!this.canResolve) {
return false;
}
diff --git a/app/assets/javascripts/diff_notes/stores/comments.js b/app/assets/javascripts/diff_notes/stores/comments.js
index d7da7d974f3..060bb044f78 100644
--- a/app/assets/javascripts/diff_notes/stores/comments.js
+++ b/app/assets/javascripts/diff_notes/stores/comments.js
@@ -1,14 +1,14 @@
-/* eslint-disable object-shorthand, func-names, camelcase, no-restricted-syntax, guard-for-in, comma-dangle, max-len */
+/* eslint-disable object-shorthand, func-names, camelcase, no-restricted-syntax, guard-for-in */
/* global DiscussionModel */
import Vue from 'vue';
window.CommentsStore = {
state: {},
- get: function (discussionId, noteId) {
+ get: function(discussionId, noteId) {
return this.state[discussionId].getNote(noteId);
},
- createDiscussion: function (discussionId, canResolve) {
+ createDiscussion: function(discussionId, canResolve) {
let discussion = this.state[discussionId];
if (!this.state[discussionId]) {
discussion = new DiscussionModel(discussionId);
@@ -21,18 +21,18 @@ window.CommentsStore = {
return discussion;
},
- create: function (noteObj) {
+ create: function(noteObj) {
const discussion = this.createDiscussion(noteObj.discussionId);
discussion.createNote(noteObj);
},
- update: function (discussionId, noteId, resolved, resolved_by) {
+ update: function(discussionId, noteId, resolved, resolved_by) {
const discussion = this.state[discussionId];
const note = discussion.getNote(noteId);
note.resolved = resolved;
note.resolved_by = resolved_by;
},
- delete: function (discussionId, noteId) {
+ delete: function(discussionId, noteId) {
const discussion = this.state[discussionId];
discussion.deleteNote(noteId);
@@ -40,7 +40,7 @@ window.CommentsStore = {
Vue.delete(this.state, discussionId);
}
},
- unresolvedDiscussionIds: function () {
+ unresolvedDiscussionIds: function() {
const ids = [];
for (const discussionId in this.state) {
@@ -52,5 +52,5 @@ window.CommentsStore = {
}
return ids;
- }
+ },
};
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index bfb992340bc..bf9244df7f7 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -3,22 +3,26 @@ import { mapState, mapGetters, mapActions } from 'vuex';
import Icon from '~/vue_shared/components/icon.vue';
import { __ } from '~/locale';
import createFlash from '~/flash';
+import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '../../notes/event_hub';
import CompareVersions from './compare_versions.vue';
-import ChangedFiles from './changed_files.vue';
import DiffFile from './diff_file.vue';
import NoChanges from './no_changes.vue';
import HiddenFilesWarning from './hidden_files_warning.vue';
+import CommitWidget from './commit_widget.vue';
+import TreeList from './tree_list.vue';
export default {
name: 'DiffsApp',
components: {
Icon,
CompareVersions,
- ChangedFiles,
DiffFile,
NoChanges,
HiddenFilesWarning,
+ CommitWidget,
+ TreeList,
+ GlLoadingIcon,
},
props: {
endpoint: {
@@ -39,6 +43,11 @@ export default {
required: true,
},
},
+ data() {
+ return {
+ assignedDiscussions: false,
+ };
+ },
computed: {
...mapState({
isLoading: state => state.diffs.isLoading,
@@ -46,8 +55,6 @@ export default {
diffViewType: state => state.diffs.diffViewType,
mergeRequestDiffs: state => state.diffs.mergeRequestDiffs,
mergeRequestDiff: state => state.diffs.mergeRequestDiff,
- latestVersionPath: state => state.diffs.latestVersionPath,
- startVersion: state => state.diffs.startVersion,
commit: state => state.diffs.commit,
targetBranchName: state => state.diffs.targetBranchName,
renderOverflowWarning: state => state.diffs.renderOverflowWarning,
@@ -56,8 +63,9 @@ export default {
plainDiffPath: state => state.diffs.plainDiffPath,
emailPatchPath: state => state.diffs.emailPatchPath,
}),
+ ...mapState('diffs', ['showTreeList', 'isLoading']),
...mapGetters('diffs', ['isParallelView']),
- ...mapGetters(['isNotesFetched', 'discussionsStructuredByLineCode']),
+ ...mapGetters(['isNotesFetched', 'getNoteableData']),
targetBranch() {
return {
branchName: this.targetBranchName,
@@ -65,26 +73,11 @@ export default {
path: '',
};
},
- notAllCommentsDisplayed() {
- if (this.commit) {
- return __('Only comments from the following commit are shown below');
- } else if (this.startVersion) {
- return __(
- "Not all comments are displayed because you're comparing two versions of the diff.",
- );
- }
- return __(
- "Not all comments are displayed because you're viewing an old version of the diff.",
- );
- },
- showLatestVersion() {
- if (this.commit) {
- return __('Show latest version of the diff');
- }
- return __('Show latest version');
- },
canCurrentUserFork() {
- return this.currentUser.canFork === true && this.currentUser.canCreateMergeRequest;
+ return this.currentUser.can_fork === true && this.currentUser.can_create_merge_request;
+ },
+ showCompareVersions() {
+ return this.mergeRequestDiffs && this.mergeRequestDiff;
},
},
watch: {
@@ -100,6 +93,8 @@ export default {
this.adjustView();
},
+ isLoading: 'adjustView',
+ showTreeList: 'adjustView',
},
mounted() {
this.setBaseConfig({ endpoint: this.endpoint, projectPath: this.projectPath });
@@ -107,19 +102,26 @@ export default {
if (this.shouldShow) {
this.fetchData();
}
+
+ const id = window && window.location && window.location.hash;
+
+ if (id) {
+ this.setHighlightedRow(id.slice(1));
+ }
},
created() {
this.adjustView();
eventHub.$once('fetchedNotesData', this.setDiscussions);
},
methods: {
+ ...mapActions(['startTaskList']),
...mapActions('diffs', [
'setBaseConfig',
'fetchDiffFiles',
'startRenderDiffsQueue',
'assignDiscussionsToDiff',
+ 'setHighlightedRow',
]),
-
fetchData() {
this.fetchDiffFiles()
.then(() => {
@@ -140,20 +142,24 @@ export default {
}
},
setDiscussions() {
- if (this.isNotesFetched) {
+ if (this.isNotesFetched && !this.assignedDiscussions && !this.isLoading) {
+ this.assignedDiscussions = true;
+
requestIdleCallback(
- () => {
- this.assignDiscussionsToDiff(this.discussionsStructuredByLineCode);
- },
+ () =>
+ this.assignDiscussionsToDiff()
+ .then(this.$nextTick)
+ .then(this.startTaskList),
{ timeout: 1000 },
);
}
},
adjustView() {
- if (this.shouldShow && this.isParallelView) {
- window.mrTabs.expandViewContainer();
- } else {
- window.mrTabs.resetViewContainer();
+ if (this.shouldShow) {
+ this.$nextTick(() => {
+ window.mrTabs.resetViewContainer();
+ window.mrTabs.expandViewContainer(this.showTreeList);
+ });
}
},
},
@@ -162,23 +168,11 @@ export default {
<template>
<div v-show="shouldShow">
- <div
- v-if="isLoading"
- class="loading"
- >
- <gl-loading-icon />
- </div>
- <div
- v-else
- id="diffs"
- :class="{ active: shouldShow }"
- class="diffs tab-pane"
- >
+ <div v-if="isLoading" class="loading"><gl-loading-icon /></div>
+ <div v-else id="diffs" :class="{ active: shouldShow }" class="diffs tab-pane">
<compare-versions
- v-if="!commit && mergeRequestDiffs.length > 1"
:merge-request-diffs="mergeRequestDiffs"
:merge-request-diff="mergeRequestDiff"
- :start-version="startVersion"
:target-branch="targetBranch"
/>
@@ -191,39 +185,23 @@ export default {
/>
<div
- v-if="commit || startVersion || (mergeRequestDiff && !mergeRequestDiff.latest)"
- class="mr-version-controls"
+ :data-can-create-note="getNoteableData.current_user.can_create_note"
+ class="files d-flex prepend-top-default"
>
- <div class="content-block comments-disabled-notif clearfix">
- <i class="fa fa-info-circle"></i>
- {{ notAllCommentsDisplayed }}
- <div class="pull-right">
- <a
- :href="latestVersionPath"
- class="btn btn-sm"
- >
- {{ showLatestVersion }}
- </a>
- </div>
+ <div v-show="showTreeList" class="diff-tree-list"><tree-list /></div>
+ <div class="diff-files-holder">
+ <commit-widget v-if="commit" :commit="commit" />
+ <template v-if="diffFiles.length > 0">
+ <diff-file
+ v-for="file in diffFiles"
+ :key="file.newPath"
+ :file="file"
+ :can-current-user-fork="canCurrentUserFork"
+ />
+ </template>
+ <no-changes v-else />
</div>
</div>
-
- <changed-files
- :diff-files="diffFiles"
- />
-
- <div
- v-if="diffFiles.length > 0"
- class="files"
- >
- <diff-file
- v-for="file in diffFiles"
- :key="file.newPath"
- :file="file"
- :can-current-user-fork="canCurrentUserFork"
- />
- </div>
- <no-changes v-else />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/diffs/components/changed_files.vue b/app/assets/javascripts/diffs/components/changed_files.vue
deleted file mode 100644
index 97751db1254..00000000000
--- a/app/assets/javascripts/diffs/components/changed_files.vue
+++ /dev/null
@@ -1,171 +0,0 @@
-<script>
-import { mapGetters, mapActions } from 'vuex';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import Icon from '~/vue_shared/components/icon.vue';
-import { pluralize } from '~/lib/utils/text_utility';
-import { getParameterValues, mergeUrlParams } from '~/lib/utils/url_utility';
-import { contentTop } from '~/lib/utils/common_utils';
-import { __ } from '~/locale';
-import ChangedFilesDropdown from './changed_files_dropdown.vue';
-import changedFilesMixin from '../mixins/changed_files';
-
-export default {
- components: {
- Icon,
- ChangedFilesDropdown,
- ClipboardButton,
- },
- mixins: [changedFilesMixin],
- data() {
- return {
- isStuck: false,
- maxWidth: 'auto',
- offsetTop: 0,
- };
- },
- computed: {
- ...mapGetters('diffs', ['isInlineView', 'isParallelView', 'areAllFilesCollapsed']),
- sumAddedLines() {
- return this.sumValues('addedLines');
- },
- sumRemovedLines() {
- return this.sumValues('removedLines');
- },
- whitespaceVisible() {
- return !getParameterValues('w')[0];
- },
- toggleWhitespaceText() {
- if (this.whitespaceVisible) {
- return __('Hide whitespace changes');
- }
- return __('Show whitespace changes');
- },
- toggleWhitespacePath() {
- if (this.whitespaceVisible) {
- return mergeUrlParams({ w: 1 }, window.location.href);
- }
-
- return mergeUrlParams({ w: 0 }, window.location.href);
- },
- top() {
- return `${this.offsetTop}px`;
- },
- },
- created() {
- document.addEventListener('scroll', this.handleScroll);
- this.offsetTop = contentTop();
- },
- beforeDestroy() {
- document.removeEventListener('scroll', this.handleScroll);
- },
- methods: {
- ...mapActions('diffs', ['setInlineDiffViewType', 'setParallelDiffViewType', 'expandAllFiles']),
- pluralize,
- handleScroll() {
- if (!this.updating) {
- this.$nextTick(this.updateIsStuck);
- this.updating = true;
- }
- },
- updateIsStuck() {
- if (!this.$refs.wrapper) {
- return;
- }
-
- const scrollPosition = window.scrollY;
-
- this.isStuck = scrollPosition + this.offsetTop >= this.$refs.placeholder.offsetTop;
- this.updating = false;
- },
- sumValues(key) {
- return this.diffFiles.reduce((total, file) => total + file[key], 0);
- },
- },
-};
-</script>
-
-<template>
- <span>
- <div ref="placeholder"></div>
- <div
- ref="wrapper"
- :style="{ top }"
- :class="{'is-stuck': isStuck}"
- class="content-block oneline-block diff-files-changed diff-files-changed-merge-request
- files-changed js-diff-files-changed"
- >
- <div class="files-changed-inner">
- <div
- class="inline-parallel-buttons d-none d-md-block"
- >
- <a
- v-if="areAllFilesCollapsed"
- class="btn btn-default"
- @click="expandAllFiles"
- >
- {{ __('Expand all') }}
- </a>
- <a
- :href="toggleWhitespacePath"
- class="btn btn-default"
- >
- {{ toggleWhitespaceText }}
- </a>
- <div class="btn-group">
- <button
- id="inline-diff-btn"
- :class="{ active: isInlineView }"
- type="button"
- class="btn js-inline-diff-button"
- data-view-type="inline"
- @click="setInlineDiffViewType"
- >
- {{ __('Inline') }}
- </button>
- <button
- id="parallel-diff-btn"
- :class="{ active: isParallelView }"
- type="button"
- class="btn js-parallel-diff-button"
- data-view-type="parallel"
- @click="setParallelDiffViewType"
- >
- {{ __('Side-by-side') }}
- </button>
- </div>
- </div>
-
- <div class="commit-stat-summary dropdown">
- <changed-files-dropdown
- :diff-files="diffFiles"
- />
-
- <span
- class="js-diff-stats-additions-deletions-expanded
- diff-stats-additions-deletions-expanded"
- >
- with
- <strong class="cgreen">
- {{ pluralize(`${sumAddedLines} addition`, sumAddedLines) }}
- </strong>
- and
- <strong class="cred">
- {{ pluralize(`${sumRemovedLines} deletion`, sumRemovedLines) }}
- </strong>
- </span>
- <div
- class="js-diff-stats-additions-deletions-collapsed
- diff-stats-additions-deletions-collapsed float-right d-sm-none"
- >
- <strong class="cgreen">
- +{{ sumAddedLines }}
- </strong>
- <strong class="cred">
- -{{ sumRemovedLines }}
- </strong>
- </div>
- </div>
- </div>
- </div>
- </span>
-</template>
diff --git a/app/assets/javascripts/diffs/components/changed_files_dropdown.vue b/app/assets/javascripts/diffs/components/changed_files_dropdown.vue
deleted file mode 100644
index 0ec6b8b7f21..00000000000
--- a/app/assets/javascripts/diffs/components/changed_files_dropdown.vue
+++ /dev/null
@@ -1,126 +0,0 @@
-<script>
-import Icon from '~/vue_shared/components/icon.vue';
-import changedFilesMixin from '../mixins/changed_files';
-
-export default {
- components: {
- Icon,
- },
- mixins: [changedFilesMixin],
- data() {
- return {
- searchText: '',
- };
- },
- computed: {
- filteredDiffFiles() {
- return this.diffFiles.filter(file =>
- file.filePath.toLowerCase().includes(this.searchText.toLowerCase()),
- );
- },
- },
- methods: {
- clearSearch() {
- this.searchText = '';
- },
- },
-};
-</script>
-
-<template>
- <span>
- Showing
- <button
- class="diff-stats-summary-toggler"
- data-toggle="dropdown"
- type="button"
- aria-expanded="false"
- >
- <span>
- {{ n__('%d changed file', '%d changed files', diffFiles.length) }}
- </span>
- <icon
- class="caret-icon"
- name="chevron-down"
- />
- </button>
- <div class="dropdown-menu diff-file-changes">
- <div class="dropdown-input">
- <input
- v-model="searchText"
- type="search"
- class="dropdown-input-field"
- placeholder="Search files"
- autocomplete="off"
- />
- <i
- v-if="searchText.length === 0"
- aria-hidden="true"
- data-hidden="true"
- class="fa fa-search dropdown-input-search">
- </i>
- <i
- v-else
- role="button"
- class="fa fa-times dropdown-input-search"
- @click.stop.prevent="clearSearch"
- ></i>
- </div>
- <div class="dropdown-content">
- <ul>
- <li
- v-for="diffFile in filteredDiffFiles"
- :key="diffFile.name"
- >
- <a
- :href="`#${diffFile.fileHash}`"
- :title="diffFile.newPath"
- class="diff-changed-file"
- >
- <icon
- :name="fileChangedIcon(diffFile)"
- :size="16"
- :class="fileChangedClass(diffFile)"
- class="diff-file-changed-icon append-right-8"
- />
- <span class="diff-changed-file-content append-right-8">
- <strong
- v-if="diffFile.blob && diffFile.blob.name"
- class="diff-changed-file-name"
- >
- {{ diffFile.blob.name }}
- </strong>
- <strong
- v-else
- class="diff-changed-blank-file-name"
- >
- {{ s__('Diffs|No file name available') }}
- </strong>
- <span class="diff-changed-file-path prepend-top-5">
- {{ truncatedDiffPath(diffFile.blob.path) }}
- </span>
- </span>
- <span class="diff-changed-stats">
- <span class="cgreen">
- +{{ diffFile.addedLines }}
- </span>
- <span class="cred">
- -{{ diffFile.removedLines }}
- </span>
- </span>
- </a>
- </li>
-
- <li
- v-show="filteredDiffFiles.length === 0"
- class="dropdown-menu-empty-item"
- >
- <a>
- {{ __('No files found') }}
- </a>
- </li>
- </ul>
- </div>
- </div>
- </span>
-</template>
diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue
new file mode 100644
index 00000000000..ebc4a83af4d
--- /dev/null
+++ b/app/assets/javascripts/diffs/components/commit_item.vue
@@ -0,0 +1,111 @@
+<script>
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import Icon from '~/vue_shared/components/icon.vue';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import CIIcon from '~/vue_shared/components/ci_icon.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
+
+/**
+ * CommitItem
+ *
+ * -----------------------------------------------------------------
+ * WARNING: Please keep changes up-to-date with the following files:
+ * - `views/projects/commits/_commit.html.haml`
+ * -----------------------------------------------------------------
+ *
+ * This Component was cloned from a HAML view. For the time being they
+ * coexist, but there is an issue to remove the duplication.
+ * https://gitlab.com/gitlab-org/gitlab-ce/issues/51613
+ *
+ */
+export default {
+ components: {
+ UserAvatarLink,
+ Icon,
+ ClipboardButton,
+ CIIcon,
+ TimeAgoTooltip,
+ CommitPipelineStatus,
+ },
+ props: {
+ commit: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ authorName() {
+ return (this.commit.author && this.commit.author.name) || this.commit.author_name;
+ },
+ authorUrl() {
+ return (
+ (this.commit.author && this.commit.author.web_url) || `mailto:${this.commit.author_email}`
+ );
+ },
+ authorAvatar() {
+ return (
+ (this.commit.author && this.commit.author.avatar_url) || this.commit.author_gravatar_url
+ );
+ },
+ },
+};
+</script>
+
+<template>
+ <li class="commit flex-row js-toggle-container">
+ <user-avatar-link
+ :link-href="authorUrl"
+ :img-src="authorAvatar"
+ :img-alt="authorName"
+ :img-size="36"
+ class="avatar-cell d-none d-sm-block"
+ />
+ <div class="commit-detail flex-list">
+ <div class="commit-content qa-commit-content">
+ <a
+ :href="commit.commit_url"
+ class="commit-row-message item-title"
+ v-html="commit.title_html"
+ ></a>
+
+ <span class="commit-row-message d-block d-sm-none"> &middot; {{ commit.short_id }} </span>
+
+ <button
+ v-if="commit.description_html"
+ class="text-expander js-toggle-button"
+ type="button"
+ :aria-label="__('Toggle commit description')"
+ >
+ <icon :size="12" name="ellipsis_h" />
+ </button>
+
+ <div class="commiter">
+ <a :href="authorUrl" v-text="authorName"></a> {{ s__('CommitWidget|authored') }}
+ <time-ago-tooltip :time="commit.authored_date" />
+ </div>
+
+ <pre
+ v-if="commit.description_html"
+ class="commit-row-description js-toggle-content append-bottom-8"
+ v-html="commit.description_html"
+ ></pre>
+ </div>
+ <div class="commit-actions flex-row d-none d-sm-flex">
+ <div v-if="commit.signature_html" v-html="commit.signature_html"></div>
+ <commit-pipeline-status
+ v-if="commit.pipeline_status_path"
+ :endpoint="commit.pipeline_status_path"
+ />
+ <div class="commit-sha-group">
+ <div class="label label-monospace" v-text="commit.short_id"></div>
+ <clipboard-button
+ :text="commit.id"
+ :title="__('Copy commit SHA to clipboard')"
+ class="btn btn-default"
+ />
+ </div>
+ </div>
+ </div>
+ </li>
+</template>
diff --git a/app/assets/javascripts/diffs/components/commit_widget.vue b/app/assets/javascripts/diffs/components/commit_widget.vue
new file mode 100644
index 00000000000..d45f91c7023
--- /dev/null
+++ b/app/assets/javascripts/diffs/components/commit_widget.vue
@@ -0,0 +1,38 @@
+<script>
+import CommitItem from './commit_item.vue';
+
+/**
+ * CommitWidget
+ *
+ * -----------------------------------------------------------------
+ * WARNING: Please keep changes up-to-date with the following files:
+ * - `views/projects/merge_requests/diffs/_commit_widget.html.haml`
+ * -----------------------------------------------------------------
+ *
+ * This Component was cloned from a HAML view. For the time being,
+ * they coexist, but there is an issue to remove the duplication.
+ * https://gitlab.com/gitlab-org/gitlab-ce/issues/51613
+ *
+ */
+export default {
+ components: {
+ CommitItem,
+ },
+ props: {
+ commit: {
+ type: Object,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="info-well w-100">
+ <div class="well-segment">
+ <ul class="blob-commit-info">
+ <commit-item :commit="commit" />
+ </ul>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/diffs/components/compare_versions.vue b/app/assets/javascripts/diffs/components/compare_versions.vue
index 1c9ad8e77f1..f75345d31f8 100644
--- a/app/assets/javascripts/diffs/components/compare_versions.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions.vue
@@ -1,9 +1,20 @@
<script>
+import { mapActions, mapGetters, mapState } from 'vuex';
+import { GlTooltipDirective, GlLink, GlButton } from '@gitlab/ui';
+import { __ } from '~/locale';
+import { getParameterValues, mergeUrlParams } from '~/lib/utils/url_utility';
+import Icon from '~/vue_shared/components/icon.vue';
import CompareVersionsDropdown from './compare_versions_dropdown.vue';
export default {
components: {
CompareVersionsDropdown,
+ Icon,
+ GlLink,
+ GlButton,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
},
props: {
mergeRequestDiffs: {
@@ -12,12 +23,8 @@ export default {
},
mergeRequestDiff: {
type: Object,
- required: true,
- },
- startVersion: {
- type: Object,
required: false,
- default: null,
+ default: () => ({}),
},
targetBranch: {
type: Object,
@@ -26,9 +33,38 @@ export default {
},
},
computed: {
+ ...mapState('diffs', ['commit', 'showTreeList', 'startVersion', 'latestVersionPath']),
+ ...mapGetters('diffs', ['isInlineView', 'isParallelView', 'hasCollapsedFile']),
comparableDiffs() {
return this.mergeRequestDiffs.slice(1);
},
+ toggleWhitespaceText() {
+ if (this.isWhitespaceVisible()) {
+ return __('Hide whitespace changes');
+ }
+ return __('Show whitespace changes');
+ },
+ toggleWhitespacePath() {
+ if (this.isWhitespaceVisible()) {
+ return mergeUrlParams({ w: 1 }, window.location.href);
+ }
+
+ return mergeUrlParams({ w: 0 }, window.location.href);
+ },
+ showDropdowns() {
+ return !this.commit && this.mergeRequestDiffs.length;
+ },
+ },
+ methods: {
+ ...mapActions('diffs', [
+ 'setInlineDiffViewType',
+ 'setParallelDiffViewType',
+ 'expandAllFiles',
+ 'toggleShowTreeList',
+ ]),
+ isWhitespaceVisible() {
+ return getParameterValues('w')[0] !== '1';
+ },
},
};
</script>
@@ -36,20 +72,75 @@ export default {
<template>
<div class="mr-version-controls">
<div class="mr-version-menus-container content-block">
- Changes between
- <compare-versions-dropdown
- :other-versions="mergeRequestDiffs"
- :merge-request-version="mergeRequestDiff"
- :show-commit-count="true"
- class="mr-version-dropdown"
- />
- and
- <compare-versions-dropdown
- :other-versions="comparableDiffs"
- :start-version="startVersion"
- :target-branch="targetBranch"
- class="mr-version-compare-dropdown"
- />
+ <button
+ v-gl-tooltip.hover
+ type="button"
+ class="btn btn-default append-right-8 js-toggle-tree-list"
+ :class="{
+ active: showTreeList,
+ }"
+ :title="__('Toggle file browser')"
+ @click="toggleShowTreeList"
+ >
+ <icon name="hamburger" />
+ </button>
+ <div v-if="showDropdowns" class="d-flex align-items-center compare-versions-container">
+ Changes between
+ <compare-versions-dropdown
+ :other-versions="mergeRequestDiffs"
+ :merge-request-version="mergeRequestDiff"
+ :show-commit-count="true"
+ class="mr-version-dropdown"
+ />
+ and
+ <compare-versions-dropdown
+ :other-versions="comparableDiffs"
+ :start-version="startVersion"
+ :target-branch="targetBranch"
+ class="mr-version-compare-dropdown"
+ />
+ </div>
+ <div v-else-if="commit">
+ {{ __('Viewing commit') }}
+ <gl-link :href="commit.commit_url" class="monospace">{{ commit.short_id }}</gl-link>
+ </div>
+ <div class="inline-parallel-buttons d-none d-md-flex ml-auto">
+ <gl-button
+ v-if="commit || startVersion"
+ :href="latestVersionPath"
+ class="append-right-8 js-latest-version"
+ >
+ {{ __('Show latest version') }}
+ </gl-button>
+ <a v-show="hasCollapsedFile" class="btn btn-default append-right-8" @click="expandAllFiles">
+ {{ __('Expand all') }}
+ </a>
+ <a :href="toggleWhitespacePath" class="btn btn-default qa-toggle-whitespace">
+ {{ toggleWhitespaceText }}
+ </a>
+ <div class="btn-group prepend-left-8">
+ <button
+ id="inline-diff-btn"
+ :class="{ active: isInlineView }"
+ type="button"
+ class="btn js-inline-diff-button"
+ data-view-type="inline"
+ @click="setInlineDiffViewType"
+ >
+ {{ __('Inline') }}
+ </button>
+ <button
+ id="parallel-diff-btn"
+ :class="{ active: isParallelView }"
+ type="button"
+ class="btn js-parallel-diff-button"
+ data-view-type="parallel"
+ @click="setParallelDiffViewType"
+ >
+ {{ __('Side-by-side') }}
+ </button>
+ </div>
+ </div>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/diffs/components/compare_versions_dropdown.vue b/app/assets/javascripts/diffs/components/compare_versions_dropdown.vue
index 96cccb49378..8da02ed0b7c 100644
--- a/app/assets/javascripts/diffs/components/compare_versions_dropdown.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions_dropdown.vue
@@ -56,16 +56,16 @@ export default {
methods: {
commitsText(version) {
return n__(
- `${version.commitsCount} commit,`,
- `${version.commitsCount} commits,`,
- version.commitsCount,
+ `${version.commits_count} commit,`,
+ `${version.commits_count} commits,`,
+ version.commits_count,
);
},
href(version) {
if (this.showCommitCount) {
- return version.versionPath;
+ return version.version_path;
}
- return version.comparePath;
+ return version.compare_path;
},
versionName(version) {
if (this.isLatest(version)) {
@@ -74,7 +74,7 @@ export default {
if (this.targetBranch && (this.isBase(version) || !version)) {
return this.targetBranch.branchName;
}
- return `version ${version.versionIndex}`;
+ return `version ${version.version_index}`;
},
isActive(version) {
if (!version) {
@@ -84,11 +84,11 @@ export default {
if (this.targetBranch) {
return (
(this.isBase(version) && !this.startVersion) ||
- (this.startVersion && this.startVersion.versionIndex === version.versionIndex)
+ (this.startVersion && this.startVersion.version_index === version.version_index)
);
}
- return version.versionIndex === this.mergeRequestVersion.versionIndex;
+ return version.version_index === this.mergeRequestVersion.version_index;
},
isBase(version) {
if (!version || !this.targetBranch) {
@@ -98,7 +98,7 @@ export default {
},
isLatest(version) {
return (
- this.mergeRequestVersion && version.versionIndex === this.targetVersions[0].versionIndex
+ this.mergeRequestVersion && version.version_index === this.targetVersions[0].version_index
);
},
},
@@ -108,29 +108,18 @@ export default {
<template>
<span class="dropdown inline">
<a
- class="dropdown-toggle btn btn-default"
+ class="dropdown-menu-toggle btn btn-default w-100"
data-toggle="dropdown"
aria-expanded="false"
>
- <span>
- {{ selectedVersionName }}
- </span>
- <Icon
- :size="12"
- name="angle-down"
- />
+ <span> {{ selectedVersionName }} </span>
+ <icon :size="12" name="angle-down" class="position-absolute" />
</a>
<div class="dropdown-menu dropdown-select dropdown-menu-selectable">
<div class="dropdown-content">
<ul>
- <li
- v-for="version in targetVersions"
- :key="version.id"
- >
- <a
- :class="{ 'is-active': isActive(version) }"
- :href="href(version)"
- >
+ <li v-for="version in targetVersions" :key="version.id">
+ <a :class="{ 'is-active': isActive(version) }" :href="href(version)">
<div>
<strong>
{{ versionName(version) }}
@@ -140,9 +129,7 @@ export default {
</strong>
</div>
<div>
- <small class="commit-sha">
- {{ version.truncatedCommitSha }}
- </small>
+ <small class="commit-sha"> {{ version.truncated_commit_sha }} </small>
</div>
<div>
<small>
@@ -150,8 +137,8 @@ export default {
{{ commitsText(version) }}
</template>
<time-ago
- v-if="version.createdAt"
- :time="version.createdAt"
+ v-if="version.created_at"
+ :time="version.created_at"
class="js-timeago js-timeago-render"
/>
</small>
@@ -163,3 +150,10 @@ export default {
</div>
</span>
</template>
+
+<style>
+.dropdown {
+ min-width: 0;
+ max-height: 170px;
+}
+</style>
diff --git a/app/assets/javascripts/diffs/components/diff_content.vue b/app/assets/javascripts/diffs/components/diff_content.vue
index 02d5be1821b..e405d8b20ae 100644
--- a/app/assets/javascripts/diffs/components/diff_content.vue
+++ b/app/assets/javascripts/diffs/components/diff_content.vue
@@ -1,15 +1,22 @@
<script>
-import { mapGetters, mapState } from 'vuex';
+import { mapActions, mapGetters, mapState } from 'vuex';
import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
-import { diffModes } from '~/ide/constants';
import InlineDiffView from './inline_diff_view.vue';
import ParallelDiffView from './parallel_diff_view.vue';
+import NoteForm from '../../notes/components/note_form.vue';
+import ImageDiffOverlay from './image_diff_overlay.vue';
+import DiffDiscussions from './diff_discussions.vue';
+import { IMAGE_DIFF_POSITION_TYPE } from '../constants';
+import { getDiffMode } from '../store/utils';
export default {
components: {
InlineDiffView,
ParallelDiffView,
DiffViewer,
+ NoteForm,
+ DiffDiscussions,
+ ImageDiffOverlay,
},
props: {
diffFile: {
@@ -23,12 +30,37 @@ export default {
endpoint: state => state.diffs.endpoint,
}),
...mapGetters('diffs', ['isInlineView', 'isParallelView']),
+ ...mapGetters('diffs', ['getCommentFormForDiffFile']),
+ ...mapGetters(['getNoteableData', 'noteableType']),
diffMode() {
- const diffModeKey = Object.keys(diffModes).find(key => this.diffFile[`${key}File`]);
- return diffModes[diffModeKey] || diffModes.replaced;
+ return getDiffMode(this.diffFile);
},
isTextFile() {
- return this.diffFile.text;
+ return this.diffFile.viewer.name === 'text';
+ },
+ diffFileCommentForm() {
+ return this.getCommentFormForDiffFile(this.diffFile.file_hash);
+ },
+ showNotesContainer() {
+ return this.diffFile.discussions.length || this.diffFileCommentForm;
+ },
+ },
+ methods: {
+ ...mapActions('diffs', ['saveDiffDiscussion', 'closeDiffFileCommentForm']),
+ handleSaveNote(note) {
+ this.saveDiffDiscussion({
+ note,
+ formData: {
+ noteableData: this.getNoteableData,
+ noteableType: this.noteableType,
+ diffFile: this.diffFile,
+ positionType: IMAGE_DIFF_POSITION_TYPE,
+ x: this.diffFileCommentForm.x,
+ y: this.diffFileCommentForm.y,
+ width: this.diffFileCommentForm.width,
+ height: this.diffFileCommentForm.height,
+ },
+ });
},
},
};
@@ -41,22 +73,49 @@ export default {
<inline-diff-view
v-if="isInlineView"
:diff-file="diffFile"
- :diff-lines="diffFile.highlightedDiffLines || []"
+ :diff-lines="diffFile.highlighted_diff_lines || []"
/>
<parallel-diff-view
v-if="isParallelView"
:diff-file="diffFile"
- :diff-lines="diffFile.parallelDiffLines || []"
+ :diff-lines="diffFile.parallel_diff_lines || []"
/>
</template>
<diff-viewer
v-else
:diff-mode="diffMode"
- :new-path="diffFile.newPath"
- :new-sha="diffFile.diffRefs.headSha"
- :old-path="diffFile.oldPath"
- :old-sha="diffFile.diffRefs.baseSha"
- :project-path="projectPath"/>
+ :new-path="diffFile.new_path"
+ :new-sha="diffFile.diff_refs.head_sha"
+ :old-path="diffFile.old_path"
+ :old-sha="diffFile.diff_refs.base_sha"
+ :file-hash="diffFile.file_hash"
+ :project-path="projectPath"
+ >
+ <image-diff-overlay
+ slot="image-overlay"
+ :discussions="diffFile.discussions"
+ :file-hash="diffFile.file_hash"
+ :can-comment="getNoteableData.current_user.can_create_note"
+ />
+ <div v-if="showNotesContainer" class="note-container">
+ <diff-discussions
+ v-if="diffFile.discussions.length"
+ class="diff-file-discussions"
+ :discussions="diffFile.discussions"
+ :should-collapse-discussions="true"
+ :render-avatar-badge="true"
+ />
+ <note-form
+ v-if="diffFileCommentForm"
+ ref="noteForm"
+ :is-editing="false"
+ :save-button-title="__('Comment')"
+ class="diff-comment-form new-note discussion-form discussion-form-container"
+ @handleFormUpdate="handleSaveNote"
+ @cancelForm="closeDiffFileCommentForm(diffFile.file_hash);"
+ />
+ </div>
+ </diff-viewer>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/diffs/components/diff_discussions.vue b/app/assets/javascripts/diffs/components/diff_discussions.vue
index cddbe554fbd..bee29b04e92 100644
--- a/app/assets/javascripts/diffs/components/diff_discussions.vue
+++ b/app/assets/javascripts/diffs/components/diff_discussions.vue
@@ -1,24 +1,40 @@
<script>
import { mapActions } from 'vuex';
+import Icon from '~/vue_shared/components/icon.vue';
import noteableDiscussion from '../../notes/components/noteable_discussion.vue';
export default {
components: {
noteableDiscussion,
+ Icon,
},
props: {
discussions: {
type: Array,
required: true,
},
+ shouldCollapseDiscussions: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ renderAvatarBadge: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
methods: {
+ ...mapActions(['toggleDiscussion']),
...mapActions('diffs', ['removeDiscussionsFromDiff']),
deleteNoteHandler(discussion) {
if (discussion.notes.length <= 1) {
this.removeDiscussionsFromDiff(discussion);
}
},
+ isExpanded(discussion) {
+ return this.shouldCollapseDiscussions ? discussion.expanded : true;
+ },
},
};
</script>
@@ -26,22 +42,42 @@ export default {
<template>
<div>
<div
- v-for="discussion in discussions"
+ v-for="(discussion, index) in discussions"
:key="discussion.id"
- class="discussion-notes diff-discussions"
+ :class="{
+ collapsed: !isExpanded(discussion),
+ }"
+ class="discussion-notes diff-discussions position-relative"
>
- <ul
- :data-discussion-id="discussion.id"
- class="notes"
- >
+ <ul :data-discussion-id="discussion.id" class="notes">
+ <template v-if="shouldCollapseDiscussions">
+ <button
+ :class="{
+ 'diff-notes-collapse': discussion.expanded,
+ 'btn-transparent badge badge-pill': !discussion.expanded,
+ }"
+ type="button"
+ class="js-diff-notes-toggle"
+ @click="toggleDiscussion({ discussionId: discussion.id });"
+ >
+ <icon v-if="discussion.expanded" name="collapse" class="collapse-icon" />
+ <template v-else>
+ {{ index + 1 }}
+ </template>
+ </button>
+ </template>
<noteable-discussion
+ v-show="isExpanded(discussion)"
:discussion="discussion"
- :render-header="false"
:render-diff-file="false"
:always-expanded="true"
:discussions-by-diff-order="true"
@noteDeleted="deleteNoteHandler"
- />
+ >
+ <span v-if="renderAvatarBadge" slot="avatar-badge" class="badge badge-pill">
+ {{ index + 1 }}
+ </span>
+ </noteable-discussion>
</ul>
</div>
</div>
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index bcbe374a90c..f7e3655ea40 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -1,8 +1,9 @@
<script>
-import { mapActions, mapGetters } from 'vuex';
+import { mapActions, mapGetters, mapState } from 'vuex';
import _ from 'underscore';
import { __, sprintf } from '~/locale';
import createFlash from '~/flash';
+import { GlLoadingIcon } from '@gitlab/ui';
import DiffFileHeader from './diff_file_header.vue';
import DiffContent from './diff_content.vue';
@@ -10,6 +11,7 @@ export default {
components: {
DiffFileHeader,
DiffContent,
+ GlLoadingIcon,
},
props: {
file: {
@@ -28,7 +30,9 @@ export default {
};
},
computed: {
- ...mapGetters(['isNotesFetched', 'discussionsStructuredByLineCode']),
+ ...mapState('diffs', ['currentDiffFileId']),
+ ...mapGetters(['isNotesFetched']),
+ ...mapGetters('diffs', ['getDiffFileDiscussions']),
isCollapsed() {
return this.file.collapsed || false;
},
@@ -36,7 +40,7 @@ export default {
return sprintf(
__('You can %{linkStart}view the blob%{linkEnd} instead.'),
{
- linkStart: `<a href="${_.escape(this.file.viewPath)}">`,
+ linkStart: `<a href="${_.escape(this.file.view_path)}">`,
linkEnd: '</a>',
},
false,
@@ -45,21 +49,34 @@ export default {
showExpandMessage() {
return (
this.isCollapsed ||
- !this.file.highlightedDiffLines &&
- !this.isLoadingCollapsedDiff &&
- !this.file.tooLarge &&
- this.file.text
+ (!this.file.highlighted_diff_lines &&
+ !this.isLoadingCollapsedDiff &&
+ !this.file.too_large &&
+ this.file.text)
);
},
showLoadingIcon() {
return this.isLoadingCollapsedDiff || (!this.file.renderIt && !this.isCollapsed);
},
+ hasDiffLines() {
+ return (
+ this.file.highlighted_diff_lines &&
+ this.file.parallel_diff_lines &&
+ this.file.parallel_diff_lines.length > 0
+ );
+ },
+ },
+ watch: {
+ 'file.collapsed': function fileCollapsedWatch(newVal, oldVal) {
+ if (!newVal && oldVal && !this.hasDiffLines) {
+ this.handleLoadCollapsedDiff();
+ }
+ },
},
methods: {
...mapActions('diffs', ['loadCollapsedDiff', 'assignDiscussionsToDiff']),
handleToggle() {
- const { highlightedDiffLines, parallelDiffLines } = this.file;
- if (!highlightedDiffLines && parallelDiffLines !== undefined && !parallelDiffLines.length) {
+ if (!this.hasDiffLines) {
this.handleLoadCollapsedDiff();
} else {
this.file.collapsed = !this.file.collapsed;
@@ -78,7 +95,7 @@ export default {
.then(() => {
requestIdleCallback(
() => {
- this.assignDiscussionsToDiff(this.discussionsStructuredByLineCode);
+ this.assignDiscussionsToDiff(this.getDiffFileDiscussions(this.file));
},
{ timeout: 1000 },
);
@@ -100,7 +117,10 @@ export default {
<template>
<div
- :id="file.fileHash"
+ :id="file.file_hash"
+ :class="{
+ 'is-active': currentDiffFileId === file.file_hash,
+ }"
class="diff-file file-holder"
>
<diff-file-header
@@ -114,16 +134,14 @@ export default {
@showForkMessage="showForkMessage"
/>
- <div
- v-if="forkMessageVisible"
- class="js-file-fork-suggestion-section file-fork-suggestion">
+ <div v-if="forkMessageVisible" class="js-file-fork-suggestion-section file-fork-suggestion">
<span class="file-fork-suggestion-note">
- You're not allowed to <span class="js-file-fork-suggestion-section-action">edit</span>
- files in this project directly. Please fork this project,
- make your changes there, and submit a merge request.
+ You're not allowed to <span class="js-file-fork-suggestion-section-action">edit</span> files
+ in this project directly. Please fork this project, make your changes there, and submit a
+ merge request.
</span>
<a
- :href="file.forkPath"
+ :href="file.fork_path"
class="js-fork-suggestion-button btn btn-grouped btn-inverted btn-success"
>
Fork
@@ -139,32 +157,36 @@ export default {
<diff-content
v-if="!isCollapsed && file.renderIt"
- :class="{ hidden: isCollapsed || file.tooLarge }"
+ :class="{ hidden: isCollapsed || file.too_large }"
:diff-file="file"
/>
- <gl-loading-icon
- v-if="showLoadingIcon"
- class="diff-content loading"
- />
- <div
- v-else-if="showExpandMessage"
- class="nothing-here-block diff-collapsed"
- >
+ <gl-loading-icon v-if="showLoadingIcon" class="diff-content loading" />
+ <div v-else-if="showExpandMessage" class="nothing-here-block diff-collapsed">
{{ __('This diff is collapsed.') }}
- <a
- class="click-to-expand js-click-to-expand"
- href="#"
- @click.prevent="handleToggle"
- >
+ <a class="click-to-expand js-click-to-expand" href="#" @click.prevent="handleToggle">
{{ __('Click to expand it.') }}
</a>
</div>
- <div
- v-if="file.tooLarge"
- class="nothing-here-block diff-collapsed js-too-large-diff"
- >
+ <div v-if="file.too_large" class="nothing-here-block diff-collapsed js-too-large-diff">
{{ __('This source diff could not be displayed because it is too large.') }}
<span v-html="viewBlobLink"></span>
</div>
</div>
</template>
+
+<style>
+@keyframes shadow-fade {
+ from {
+ box-shadow: 0 0 4px #919191;
+ }
+
+ to {
+ box-shadow: 0 0 0 #dfdfdf;
+ }
+}
+
+.diff-file.is-active {
+ box-shadow: 0 0 0 #dfdfdf;
+ animation: shadow-fade 1.2s 0.1s 1;
+}
+</style>
diff --git a/app/assets/javascripts/diffs/components/diff_file_header.vue b/app/assets/javascripts/diffs/components/diff_file_header.vue
index d3ffbe0415a..f75a01b023b 100644
--- a/app/assets/javascripts/diffs/components/diff_file_header.vue
+++ b/app/assets/javascripts/diffs/components/diff_file_header.vue
@@ -1,10 +1,11 @@
<script>
import _ from 'underscore';
import { mapActions, mapGetters } from 'vuex';
+import { polyfillSticky } from '~/lib/utils/sticky';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import Icon from '~/vue_shared/components/icon.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
-import Tooltip from '~/vue_shared/directives/tooltip';
+import { GlTooltipDirective } from '@gitlab/ui';
import { truncateSha } from '~/lib/utils/text_utility';
import { __, s__, sprintf } from '~/locale';
import EditButton from './edit_button.vue';
@@ -17,9 +18,14 @@ export default {
FileIcon,
},
directives: {
- Tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
+ discussionPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
diffFile: {
type: Object,
required: true,
@@ -63,33 +69,32 @@ export default {
},
titleLink() {
if (this.diffFile.submodule) {
- return this.diffFile.submoduleTreeUrl || this.diffFile.submoduleLink;
+ return this.diffFile.submodule_tree_url || this.diffFile.submodule_link;
}
-
- return `#${this.diffFile.fileHash}`;
+ return this.discussionPath;
},
filePath() {
if (this.diffFile.submodule) {
- return `${this.diffFile.filePath} @ ${truncateSha(this.diffFile.blob.id)}`;
+ return `${this.diffFile.file_path} @ ${truncateSha(this.diffFile.blob.id)}`;
}
- if (this.diffFile.deletedFile) {
- return sprintf(__('%{filePath} deleted'), { filePath: this.diffFile.filePath }, false);
+ if (this.diffFile.deleted_file) {
+ return sprintf(__('%{filePath} deleted'), { filePath: this.diffFile.file_path }, false);
}
- return this.diffFile.filePath;
+ return this.diffFile.file_path;
},
titleTag() {
- return this.diffFile.fileHash ? 'a' : 'span';
+ return this.diffFile.file_hash ? 'a' : 'span';
},
isUsingLfs() {
- return this.diffFile.storedExternally && this.diffFile.externalStorage === 'lfs';
+ return this.diffFile.stored_externally && this.diffFile.external_storage === 'lfs';
},
collapseIcon() {
return this.expanded ? 'chevron-down' : 'chevron-right';
},
viewFileButtonText() {
- const truncatedContentSha = _.escape(truncateSha(this.diffFile.contentSha));
+ const truncatedContentSha = _.escape(truncateSha(this.diffFile.content_sha));
return sprintf(
s__('MergeRequests|View file @ %{commitId}'),
{
@@ -99,7 +104,7 @@ export default {
);
},
viewReplacedFileButtonText() {
- const truncatedBaseSha = _.escape(truncateSha(this.diffFile.diffRefs.baseSha));
+ const truncatedBaseSha = _.escape(truncateSha(this.diffFile.diff_refs.base_sha));
return sprintf(
s__('MergeRequests|View replaced file @ %{commitId}'),
{
@@ -109,9 +114,12 @@ export default {
);
},
gfmCopyText() {
- return `\`${this.diffFile.filePath}\``;
+ return `\`${this.diffFile.file_path}\``;
},
},
+ mounted() {
+ polyfillSticky(this.$refs.header);
+ },
methods: {
...mapActions('diffs', ['toggleFileDiscussions']),
handleToggleFile(e, checkTarget) {
@@ -137,7 +145,7 @@ export default {
<div
ref="header"
class="js-file-title file-title file-title-flex-parent"
- @click="handleToggleFile($event, true)"
+ @click="handleToggleFile($event, true);"
>
<div class="file-header-content">
<icon
@@ -148,78 +156,53 @@ export default {
class="diff-toggle-caret append-right-5"
@click.stop="handleToggle"
/>
- <a
- v-once
- ref="titleWrapper"
- :href="titleLink"
- class="append-right-4"
- >
+ <a v-once ref="titleWrapper" :href="titleLink" class="append-right-4 js-title-wrapper">
<file-icon
:file-name="filePath"
:size="18"
aria-hidden="true"
css-classes="js-file-icon append-right-5"
/>
- <span v-if="diffFile.renamedFile">
+ <span v-if="diffFile.renamed_file">
<strong
- v-tooltip
- :title="diffFile.oldPath"
+ v-gl-tooltip
+ :title="diffFile.old_path"
class="file-title-name"
- data-container="body"
- >
- {{ diffFile.oldPath }}
- </strong>
+ v-html="diffFile.old_path_html"
+ ></strong>
→
<strong
- v-tooltip
- :title="diffFile.newPath"
+ v-gl-tooltip
+ :title="diffFile.new_path"
class="file-title-name"
- data-container="body"
- >
- {{ diffFile.newPath }}
- </strong>
+ v-html="diffFile.new_path_html"
+ ></strong>
</span>
- <strong
- v-tooltip
- v-else
- :title="filePath"
- class="file-title-name"
- data-container="body"
- >
+ <strong v-else v-gl-tooltip :title="filePath" class="file-title-name" data-container="body">
{{ filePath }}
</strong>
</a>
<clipboard-button
:title="__('Copy file path to clipboard')"
- :text="diffFile.filePath"
+ :text="diffFile.file_path"
:gfm="gfmCopyText"
css-class="btn-default btn-transparent btn-clipboard"
/>
- <small
- v-if="diffFile.modeChanged"
- ref="fileMode"
- >
- {{ diffFile.aMode }} → {{ diffFile.bMode }}
+ <small v-if="diffFile.mode_changed" ref="fileMode">
+ {{ diffFile.a_mode }} → {{ diffFile.b_mode }}
</small>
- <span
- v-if="isUsingLfs"
- class="label label-lfs append-right-5"
- >
- {{ __('LFS') }}
- </span>
+ <span v-if="isUsingLfs" class="label label-lfs append-right-5"> {{ __('LFS') }} </span>
</div>
<div
v-if="!diffFile.submodule && addMergeRequestButtons"
class="file-actions d-none d-sm-block"
>
- <template
- v-if="diffFile.blob && diffFile.blob.readableText"
- >
+ <template v-if="diffFile.blob && diffFile.blob.readable_text">
<button
:disabled="!diffHasDiscussions(diffFile)"
:class="{ active: hasExpandedDiscussions }"
@@ -232,33 +215,29 @@ export default {
</button>
<edit-button
- v-if="!diffFile.deletedFile"
+ v-if="!diffFile.deleted_file"
:can-current-user-fork="canCurrentUserFork"
- :edit-path="diffFile.editPath"
- :can-modify-blob="diffFile.canModifyBlob"
+ :edit-path="diffFile.edit_path"
+ :can-modify-blob="diffFile.can_modify_blob"
@showForkMessage="showForkMessage"
/>
</template>
<a
- v-if="diffFile.replacedViewPath"
- :href="diffFile.replacedViewPath"
+ v-if="diffFile.replaced_view_path"
+ :href="diffFile.replaced_view_path"
class="btn view-file js-view-file"
v-html="viewReplacedFileButtonText"
>
</a>
- <a
- :href="diffFile.viewPath"
- class="btn view-file js-view-file"
- v-html="viewFileButtonText"
- >
+ <a :href="diffFile.view_path" class="btn view-file js-view-file" v-html="viewFileButtonText">
</a>
<a
- v-tooltip
- v-if="diffFile.externalUrl"
- :href="diffFile.externalUrl"
- :title="`View on ${diffFile.formattedExternalUrl}`"
+ v-if="diffFile.external_url"
+ v-gl-tooltip.hover
+ :href="diffFile.external_url"
+ :title="`View on ${diffFile.formatted_external_url}`"
target="_blank"
rel="noopener noreferrer"
class="btn btn-file-option"
diff --git a/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue b/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
index a02c41f39ab..b969017a2bb 100644
--- a/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
+++ b/app/assets/javascripts/diffs/components/diff_gutter_avatars.vue
@@ -3,6 +3,7 @@ import { mapActions } from 'vuex';
import Icon from '~/vue_shared/components/icon.vue';
import { pluralize, truncate } from '~/lib/utils/text_utility';
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
+import { GlTooltipDirective } from '@gitlab/ui';
import { COUNT_OF_AVATARS_IN_GUTTER, LENGTH_OF_AVATAR_TOOLTIP } from '../constants';
export default {
@@ -10,6 +11,9 @@ export default {
Icon,
UserAvatarImage,
},
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
props: {
discussions: {
type: Array,
@@ -71,10 +75,7 @@ export default {
class="diff-notes-collapse js-diff-comment-avatar js-diff-comment-button"
@click="toggleDiscussions"
>
- <icon
- :size="12"
- name="collapse"
- />
+ <icon :size="12" name="collapse" />
</button>
<template v-else>
<user-avatar-image
@@ -87,15 +88,16 @@ export default {
@click.native="toggleDiscussions"
/>
<span
- v-gl-tooltip
v-if="moreText"
+ v-gl-tooltip
:title="moreText"
class="diff-comments-more-count js-diff-comment-avatar js-diff-comment-plus"
data-container="body"
data-placement="top"
role="button"
@click="toggleDiscussions"
- >+{{ moreCount }}</span>
+ >+{{ moreCount }}</span
+ >
</template>
</div>
</template>
diff --git a/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue b/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue
index 6eff3013dcd..c0613d80d37 100644
--- a/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue
+++ b/app/assets/javascripts/diffs/components/diff_line_gutter_content.vue
@@ -72,8 +72,15 @@ export default {
diffFiles: state => state.diffs.diffFiles,
}),
...mapGetters(['isLoggedIn']),
+ lineCode() {
+ return (
+ this.line.line_code ||
+ (this.line.left && this.line.line.left.line_code) ||
+ (this.line.right && this.line.right.line_code)
+ );
+ },
lineHref() {
- return `#${this.line.lineCode || ''}`;
+ return `#${this.line.line_code || ''}`;
},
shouldShowCommentButton() {
return (
@@ -97,9 +104,9 @@ export default {
},
},
methods: {
- ...mapActions('diffs', ['loadMoreLines', 'showCommentForm']),
+ ...mapActions('diffs', ['loadMoreLines', 'showCommentForm', 'setHighlightedRow']),
handleCommentButton() {
- this.showCommentForm({ lineCode: this.line.lineCode });
+ this.showCommentForm({ lineCode: this.line.line_code, fileHash: this.fileHash });
},
handleLoadMoreLines() {
if (this.isRequesting) {
@@ -108,8 +115,8 @@ export default {
this.isRequesting = true;
const endpoint = this.contextLinesPath;
- const oldLineNumber = this.line.metaData.oldPos || 0;
- const newLineNumber = this.line.metaData.newPos || 0;
+ const oldLineNumber = this.line.meta_data.old_pos || 0;
+ const newLineNumber = this.line.meta_data.new_pos || 0;
const offset = newLineNumber - oldLineNumber;
const bottom = this.isBottom;
const { fileHash } = this;
@@ -125,12 +132,12 @@ export default {
to = lineNumber + UNFOLD_COUNT;
} else {
const diffFile = utils.findDiffFile(this.diffFiles, this.fileHash);
- const indexForInline = utils.findIndexInInlineLines(diffFile.highlightedDiffLines, {
+ const indexForInline = utils.findIndexInInlineLines(diffFile.highlighted_diff_lines, {
oldLineNumber,
newLineNumber,
});
- const prevLine = diffFile.highlightedDiffLines[indexForInline - 2];
- const prevLineNumber = (prevLine && prevLine.newLine) || 0;
+ const prevLine = diffFile.highlighted_diff_lines[indexForInline - 2];
+ const prevLineNumber = (prevLine && prevLine.new_line) || 0;
if (since <= prevLineNumber + 1) {
since = prevLineNumber + 1;
@@ -155,37 +162,27 @@ export default {
<template>
<div>
- <span
- v-if="isMatchLine"
- class="context-cell"
- role="button"
- @click="handleLoadMoreLines"
- >...</span>
- <template
- v-else
+ <span v-if="isMatchLine" class="context-cell" role="button" @click="handleLoadMoreLines"
+ >...</span
>
+ <template v-else>
<button
- v-if="shouldShowCommentButton"
+ v-show="shouldShowCommentButton"
type="button"
- class="add-diff-note js-add-diff-note-button"
+ class="add-diff-note js-add-diff-note-button qa-diff-comment"
title="Add a comment to this line"
@click="handleCommentButton"
>
- <icon
- :size="12"
- name="comment"
- />
+ <icon :size="12" name="comment" />
</button>
<a
v-if="lineNumber"
:data-linenumber="lineNumber"
:href="lineHref"
+ @click="setHighlightedRow(lineCode);"
>
</a>
- <diff-gutter-avatars
- v-if="shouldShowAvatarsOnGutter"
- :discussions="line.discussions"
- />
+ <diff-gutter-avatars v-if="shouldShowAvatarsOnGutter" :discussions="line.discussions" />
</template>
</div>
</template>
diff --git a/app/assets/javascripts/diffs/components/diff_line_note_form.vue b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
index 0fa14615532..9fd02acbd6e 100644
--- a/app/assets/javascripts/diffs/components/diff_line_note_form.vue
+++ b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
@@ -1,12 +1,9 @@
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
-import createFlash from '~/flash';
import { s__ } from '~/locale';
import noteForm from '../../notes/components/note_form.vue';
-import { getNoteFormData } from '../store/utils';
import autosave from '../../notes/mixins/autosave';
import { DIFF_NOTE_TYPE } from '../constants';
-import { reduceDiscussionsToLineCodes } from '../../notes/stores/utils';
export default {
components: {
@@ -39,6 +36,16 @@ export default {
}),
...mapGetters('diffs', ['getDiffFileByHash']),
...mapGetters(['isLoggedIn', 'noteableType', 'getNoteableData', 'getNotesDataByProp']),
+ formData() {
+ return {
+ noteableData: this.noteableData,
+ noteableType: this.noteableType,
+ noteTargetLine: this.noteTargetLine,
+ diffViewType: this.diffViewType,
+ diffFile: this.getDiffFileByHash(this.diffFileHash),
+ linePosition: this.linePosition,
+ };
+ },
},
mounted() {
if (this.isLoggedIn) {
@@ -46,15 +53,14 @@ export default {
this.noteableData.diff_head_sha,
DIFF_NOTE_TYPE,
this.noteableData.source_project_id,
- this.line.lineCode,
+ this.line.line_code,
];
this.initAutoSave(this.noteableData, keys);
}
},
methods: {
- ...mapActions('diffs', ['cancelCommentForm', 'assignDiscussionsToDiff']),
- ...mapActions(['saveNote', 'refetchDiscussionById']),
+ ...mapActions('diffs', ['cancelCommentForm', 'assignDiscussionsToDiff', 'saveDiffDiscussion']),
handleCancelCommentForm(shouldConfirm, isDirty) {
if (shouldConfirm && isDirty) {
const msg = s__('Notes|Are you sure you want to cancel creating this comment?');
@@ -66,55 +72,28 @@ export default {
}
this.cancelCommentForm({
- lineCode: this.line.lineCode,
+ lineCode: this.line.line_code,
+ fileHash: this.diffFileHash,
});
this.$nextTick(() => {
this.resetAutoSave();
});
},
handleSaveNote(note) {
- const selectedDiffFile = this.getDiffFileByHash(this.diffFileHash);
- const postData = getNoteFormData({
- note,
- noteableData: this.noteableData,
- noteableType: this.noteableType,
- noteTargetLine: this.noteTargetLine,
- diffViewType: this.diffViewType,
- diffFile: selectedDiffFile,
- linePosition: this.linePosition,
- });
-
- this.saveNote(postData)
- .then(result => {
- const endpoint = this.getNotesDataByProp('discussionsPath');
-
- this.refetchDiscussionById({ path: endpoint, discussionId: result.discussion_id })
- .then(selectedDiscussion => {
- const lineCodeDiscussions = reduceDiscussionsToLineCodes([selectedDiscussion]);
- this.assignDiscussionsToDiff(lineCodeDiscussions);
-
- this.handleCancelCommentForm();
- })
- .catch(() => {
- createFlash(s__('MergeRequests|Updating discussions failed'));
- });
- })
- .catch(() => {
- createFlash(s__('MergeRequests|Saving the comment failed'));
- });
+ return this.saveDiffDiscussion({ note, formData: this.formData }).then(() =>
+ this.handleCancelCommentForm(),
+ );
},
},
};
</script>
<template>
- <div
- class="content discussion-form discussion-form-container discussion-notes"
- >
+ <div class="content discussion-form discussion-form-container discussion-notes">
<note-form
ref="noteForm"
:is-editing="true"
- :line-code="line.lineCode"
+ :line-code="line.line_code"
save-button-title="Comment"
class="diff-comment-form"
@cancelForm="handleCancelCommentForm"
diff --git a/app/assets/javascripts/diffs/components/diff_table_cell.vue b/app/assets/javascripts/diffs/components/diff_table_cell.vue
index 5d9a0b123fe..d174b13e133 100644
--- a/app/assets/javascripts/diffs/components/diff_table_cell.vue
+++ b/app/assets/javascripts/diffs/components/diff_table_cell.vue
@@ -1,5 +1,5 @@
<script>
-import { mapGetters } from 'vuex';
+import { mapGetters, mapActions } from 'vuex';
import DiffLineGutterContent from './diff_line_gutter_content.vue';
import {
MATCH_LINE_TYPE,
@@ -30,6 +30,11 @@ export default {
type: String,
required: true,
},
+ isHighlighted: {
+ type: Boolean,
+ required: true,
+ default: false,
+ },
diffViewType: {
type: String,
required: false,
@@ -85,6 +90,7 @@ export default {
const { type } = this.line;
return {
+ hll: this.isHighlighted,
[type]: type,
[LINE_UNFOLD_CLASS_NAME]: this.isMatchLine,
[LINE_HOVER_CLASS_NAME]:
@@ -96,18 +102,15 @@ export default {
};
},
lineNumber() {
- const { lineType } = this;
-
- return lineType === OLD_LINE_TYPE ? this.line.oldLine : this.line.newLine;
+ return this.lineType === OLD_LINE_TYPE ? this.line.old_line : this.line.new_line;
},
},
+ methods: mapActions('diffs', ['setHighlightedRow']),
};
</script>
<template>
- <td
- :class="classNameMap"
- >
+ <td :class="classNameMap">
<diff-line-gutter-content
:line="line"
:file-hash="fileHash"
diff --git a/app/assets/javascripts/diffs/components/edit_button.vue b/app/assets/javascripts/diffs/components/edit_button.vue
index 2fb85ca2f07..5d38d545ce8 100644
--- a/app/assets/javascripts/diffs/components/edit_button.vue
+++ b/app/assets/javascripts/diffs/components/edit_button.vue
@@ -32,11 +32,5 @@ export default {
</script>
<template>
- <a
- :href="editPath"
- class="btn btn-default js-edit-blob"
- @click="handleEditClick"
- >
- Edit
- </a>
+ <a :href="editPath" class="btn btn-default js-edit-blob" @click="handleEditClick"> Edit </a>
</template>
diff --git a/app/assets/javascripts/diffs/components/file_row_stats.vue b/app/assets/javascripts/diffs/components/file_row_stats.vue
new file mode 100644
index 00000000000..784f74e498f
--- /dev/null
+++ b/app/assets/javascripts/diffs/components/file_row_stats.vue
@@ -0,0 +1,23 @@
+<script>
+export default {
+ props: {
+ file: {
+ type: Object,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <span v-once class="file-row-stats">
+ <span class="cgreen"> +{{ file.addedLines }} </span>
+ <span class="cred"> -{{ file.removedLines }} </span>
+ </span>
+</template>
+
+<style>
+.file-row-stats {
+ font-size: 12px;
+}
+</style>
diff --git a/app/assets/javascripts/diffs/components/hidden_files_warning.vue b/app/assets/javascripts/diffs/components/hidden_files_warning.vue
index 017dcfcc357..119e139de21 100644
--- a/app/assets/javascripts/diffs/components/hidden_files_warning.vue
+++ b/app/assets/javascripts/diffs/components/hidden_files_warning.vue
@@ -26,26 +26,13 @@ export default {
<h4>
{{ __('Too many changes to show.') }}
<div class="pull-right">
- <a
- :href="plainDiffPath"
- class="btn btn-sm"
- >
- {{ __('Plain diff') }}
- </a>
- <a
- :href="emailPatchPath"
- class="btn btn-sm"
- >
- {{ __('Email patch') }}
- </a>
+ <a :href="plainDiffPath" class="btn btn-sm"> {{ __('Plain diff') }} </a>
+ <a :href="emailPatchPath" class="btn btn-sm"> {{ __('Email patch') }} </a>
</div>
</h4>
<p>
- To preserve performance only
- <strong>
- {{ visible }} of {{ total }}
- </strong>
- files are displayed.
+ To preserve performance only <strong> {{ visible }} of {{ total }} </strong> files are
+ displayed.
</p>
</div>
</template>
diff --git a/app/assets/javascripts/diffs/components/image_diff_overlay.vue b/app/assets/javascripts/diffs/components/image_diff_overlay.vue
new file mode 100644
index 00000000000..d30e64312aa
--- /dev/null
+++ b/app/assets/javascripts/diffs/components/image_diff_overlay.vue
@@ -0,0 +1,132 @@
+<script>
+import { mapActions, mapGetters } from 'vuex';
+import _ from 'underscore';
+import Icon from '~/vue_shared/components/icon.vue';
+
+export default {
+ name: 'ImageDiffOverlay',
+ components: {
+ Icon,
+ },
+ props: {
+ discussions: {
+ type: [Array, Object],
+ required: true,
+ },
+ fileHash: {
+ type: String,
+ required: true,
+ },
+ canComment: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ showCommentIcon: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ badgeClass: {
+ type: String,
+ required: false,
+ default: 'badge badge-pill',
+ },
+ shouldToggleDiscussion: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+ computed: {
+ ...mapGetters('diffs', ['getDiffFileByHash', 'getCommentFormForDiffFile']),
+ currentCommentForm() {
+ return this.getCommentFormForDiffFile(this.fileHash);
+ },
+ allDiscussions() {
+ return _.isArray(this.discussions) ? this.discussions : [this.discussions];
+ },
+ },
+ methods: {
+ ...mapActions(['toggleDiscussion']),
+ ...mapActions('diffs', ['openDiffFileCommentForm']),
+ getImageDimensions() {
+ return {
+ width: this.$parent.width,
+ height: this.$parent.height,
+ };
+ },
+ getPositionForObject(meta) {
+ const { x, y, width, height } = meta;
+ const imageWidth = this.getImageDimensions().width;
+ const imageHeight = this.getImageDimensions().height;
+ const widthRatio = imageWidth / width;
+ const heightRatio = imageHeight / height;
+
+ return {
+ x: Math.round(x * widthRatio),
+ y: Math.round(y * heightRatio),
+ };
+ },
+ getPosition(discussion) {
+ const { x, y } = this.getPositionForObject(discussion.position);
+
+ return {
+ left: `${x}px`,
+ top: `${y}px`,
+ };
+ },
+ clickedImage(x, y) {
+ const { width, height } = this.getImageDimensions();
+
+ this.openDiffFileCommentForm({
+ fileHash: this.fileHash,
+ width,
+ height,
+ x,
+ y,
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="position-absolute w-100 h-100 image-diff-overlay">
+ <button
+ v-if="canComment"
+ type="button"
+ class="btn-transparent position-absolute image-diff-overlay-add-comment w-100 h-100 js-add-image-diff-note-button"
+ @click="clickedImage($event.offsetX, $event.offsetY);"
+ >
+ <span class="sr-only"> {{ __('Add image comment') }} </span>
+ </button>
+ <button
+ v-for="(discussion, index) in allDiscussions"
+ :key="discussion.id"
+ :style="getPosition(discussion)"
+ :class="badgeClass"
+ :disabled="!shouldToggleDiscussion"
+ class="js-image-badge"
+ type="button"
+ @click="toggleDiscussion({ discussionId: discussion.id });"
+ >
+ <icon v-if="showCommentIcon" name="image-comment-dark" />
+ <template v-else>
+ {{ index + 1 }}
+ </template>
+ </button>
+ <button
+ v-if="currentCommentForm"
+ :style="{
+ left: `${currentCommentForm.x}px`,
+ top: `${currentCommentForm.y}px`,
+ }"
+ :aria-label="__('Comment form position')"
+ class="btn-transparent comment-indicator"
+ type="button"
+ >
+ <icon name="image-comment-dark" />
+ </button>
+ </div>
+</template>
diff --git a/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue b/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue
index 46a51859da5..aa40b24950a 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_comment_row.vue
@@ -1,5 +1,4 @@
<script>
-import { mapState } from 'vuex';
import diffDiscussions from './diff_discussions.vue';
import diffLineNoteForm from './diff_line_note_form.vue';
@@ -17,38 +16,31 @@ export default {
type: String,
required: true,
},
- lineIndex: {
- type: Number,
- required: true,
- },
},
computed: {
- ...mapState({
- diffLineCommentForms: state => state.diffs.diffLineCommentForms,
- }),
className() {
return this.line.discussions.length ? '' : 'js-temp-notes-holder';
},
+ shouldRender() {
+ if (this.line.hasForm) return true;
+
+ if (!this.line.discussions || !this.line.discussions.length) {
+ return false;
+ }
+
+ return this.line.discussions.every(discussion => discussion.expanded);
+ },
},
};
</script>
<template>
- <tr
- :class="className"
- class="notes_holder"
- >
- <td
- class="notes_content"
- colspan="3"
- >
+ <tr v-if="shouldRender" :class="className" class="notes_holder">
+ <td class="notes_content" colspan="3">
<div class="content">
- <diff-discussions
- v-if="line.discussions.length"
- :discussions="line.discussions"
- />
+ <diff-discussions v-if="line.discussions.length" :discussions="line.discussions" />
<diff-line-note-form
- v-if="diffLineCommentForms[line.lineCode]"
+ v-if="line.hasForm"
:diff-file-hash="diffFileHash"
:line="line"
:note-target-line="line"
diff --git a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
index 62fa34e835a..c764cbeb8e0 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue
@@ -1,5 +1,5 @@
<script>
-import { mapGetters, mapActions } from 'vuex';
+import { mapGetters, mapActions, mapState } from 'vuex';
import DiffTableCell from './diff_table_cell.vue';
import {
NEW_LINE_TYPE,
@@ -40,6 +40,11 @@ export default {
};
},
computed: {
+ ...mapState({
+ isHighlighted(state) {
+ return this.line.line_code !== null && this.line.line_code === state.diffs.highlightedRow;
+ },
+ }),
...mapGetters('diffs', ['isInlineView']),
isContextLine() {
return this.line.type === CONTEXT_LINE_TYPE;
@@ -52,9 +57,7 @@ export default {
};
},
inlineRowId() {
- const { lineCode, oldLine, newLine } = this.line;
-
- return lineCode || `${this.fileHash}_${oldLine}_${newLine}`;
+ return this.line.line_code || `${this.fileHash}_${this.line.old_line}_${this.line.new_line}`;
},
},
created() {
@@ -93,6 +96,7 @@ export default {
:is-bottom="isBottom"
:is-hover="isHover"
:show-comment-button="true"
+ :is-highlighted="isHighlighted"
class="diff-line-num old_line"
/>
<diff-table-cell
@@ -102,13 +106,18 @@ export default {
:line-type="newLineType"
:is-bottom="isBottom"
:is-hover="isHover"
- class="diff-line-num new_line"
+ :is-highlighted="isHighlighted"
+ class="diff-line-num new_line qa-new-diff-line"
/>
<td
- :class="line.type"
+ :class="[
+ line.type,
+ {
+ hll: isHighlighted,
+ },
+ ]"
class="line_content"
- v-html="line.richText"
- >
- </td>
+ v-html="line.rich_text"
+ ></td>
</tr>
</template>
diff --git a/app/assets/javascripts/diffs/components/inline_diff_view.vue b/app/assets/javascripts/diffs/components/inline_diff_view.vue
index 947e7c98fae..6a0ce760e6d 100644
--- a/app/assets/javascripts/diffs/components/inline_diff_view.vue
+++ b/app/assets/javascripts/diffs/components/inline_diff_view.vue
@@ -1,5 +1,5 @@
<script>
-import { mapGetters, mapState } from 'vuex';
+import { mapGetters } from 'vuex';
import inlineDiffTableRow from './inline_diff_table_row.vue';
import inlineDiffCommentRow from './inline_diff_comment_row.vue';
@@ -19,42 +19,34 @@ export default {
},
},
computed: {
- ...mapGetters('diffs', ['commitId', 'shouldRenderInlineCommentRow']),
- ...mapState({
- diffLineCommentForms: state => state.diffs.diffLineCommentForms,
- }),
+ ...mapGetters('diffs', ['commitId']),
diffLinesLength() {
return this.diffLines.length;
},
- userColorScheme() {
- return window.gon.user_color_scheme;
- },
},
+ userColorScheme: window.gon.user_color_scheme,
};
</script>
<template>
<table
- :class="userColorScheme"
+ :class="$options.userColorScheme"
:data-commit-id="commitId"
- class="code diff-wrap-lines js-syntax-highlight text-file js-diff-inline-view">
+ class="code diff-wrap-lines js-syntax-highlight text-file js-diff-inline-view"
+ >
<tbody>
- <template
- v-for="(line, index) in diffLines"
- >
+ <template v-for="(line, index) in diffLines">
<inline-diff-table-row
- :file-hash="diffFile.fileHash"
- :context-lines-path="diffFile.contextLinesPath"
+ :key="line.line_code"
+ :file-hash="diffFile.file_hash"
+ :context-lines-path="diffFile.context_lines_path"
:line="line"
:is-bottom="index + 1 === diffLinesLength"
- :key="line.lineCode"
/>
<inline-diff-comment-row
- v-if="shouldRenderInlineCommentRow(line)"
- :diff-file-hash="diffFile.fileHash"
+ :key="`icr-${index}`"
+ :diff-file-hash="diffFile.file_hash"
:line="line"
- :line-index="index"
- :key="index"
/>
</template>
</tbody>
diff --git a/app/assets/javascripts/diffs/components/no_changes.vue b/app/assets/javascripts/diffs/components/no_changes.vue
index 6905630ad8c..25ec157ed25 100644
--- a/app/assets/javascripts/diffs/components/no_changes.vue
+++ b/app/assets/javascripts/diffs/components/no_changes.vue
@@ -19,29 +19,16 @@ export default {
</script>
<template>
- <div
- class="row empty-state nothing-here-block"
- >
+ <div class="row empty-state nothing-here-block">
<div class="col-xs-12">
- <div class="svg-content">
- <span
- v-html="emptyImage"
- ></span>
- </div>
+ <div class="svg-content"><span v-html="emptyImage"></span></div>
</div>
<div class="col-xs-12">
<div class="text-content text-center">
- No changes between
- <span class="ref-name">{{ sourceBranch }}</span>
- and
+ No changes between <span class="ref-name">{{ sourceBranch }}</span> and
<span class="ref-name">{{ targetBranch }}</span>
<div class="text-center">
- <a
- :href="newBlobPath"
- class="btn btn-success"
- >
- {{ __('Create commit') }}
- </a>
+ <a :href="newBlobPath" class="btn btn-success"> {{ __('Create commit') }} </a>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue b/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue
index 3339c56cbb6..b98463d3dd3 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_comment_row.vue
@@ -1,5 +1,4 @@
<script>
-import { mapState } from 'vuex';
import diffDiscussions from './diff_discussions.vue';
import diffLineNoteForm from './diff_line_note_form.vue';
@@ -23,22 +22,13 @@ export default {
},
},
computed: {
- ...mapState({
- diffLineCommentForms: state => state.diffs.diffLineCommentForms,
- }),
- leftLineCode() {
- return this.line.left && this.line.left.lineCode;
- },
- rightLineCode() {
- return this.line.right && this.line.right.lineCode;
- },
hasExpandedDiscussionOnLeft() {
- return this.line.left && this.line.left.discussions
+ return this.line.left && this.line.left.discussions.length
? this.line.left.discussions.every(discussion => discussion.expanded)
: false;
},
hasExpandedDiscussionOnRight() {
- return this.line.right && this.line.right.discussions
+ return this.line.right && this.line.right.discussions.length
? this.line.right.discussions.every(discussion => discussion.expanded)
: false;
},
@@ -57,9 +47,10 @@ export default {
);
},
showRightSideCommentForm() {
- return (
- this.line.right && this.line.right.type && this.diffLineCommentForms[this.rightLineCode]
- );
+ return this.line.right && this.line.right.type && this.line.right.hasForm;
+ },
+ showLeftSideCommentForm() {
+ return this.line.left && this.line.left.hasForm;
},
className() {
return (this.left && this.line.left.discussions.length > 0) ||
@@ -67,40 +58,47 @@ export default {
? ''
: 'js-temp-notes-holder';
},
+ shouldRender() {
+ const { line } = this;
+ const hasDiscussion =
+ (line.left && line.left.discussions && line.left.discussions.length) ||
+ (line.right && line.right.discussions && line.right.discussions.length);
+
+ if (
+ hasDiscussion &&
+ (this.hasExpandedDiscussionOnLeft || this.hasExpandedDiscussionOnRight)
+ ) {
+ return true;
+ }
+
+ const hasCommentFormOnLeft = line.left && line.left.hasForm;
+ const hasCommentFormOnRight = line.right && line.right.hasForm;
+
+ return hasCommentFormOnLeft || hasCommentFormOnRight;
+ },
},
};
</script>
<template>
- <tr
- :class="className"
- class="notes_holder"
- >
- <td class="notes_line old"></td>
- <td class="notes_content parallel old">
- <div
- v-if="shouldRenderDiscussionsOnLeft"
- class="content"
- >
+ <tr v-if="shouldRender" :class="className" class="notes_holder">
+ <td class="notes_content parallel old" colspan="2">
+ <div v-if="shouldRenderDiscussionsOnLeft" class="content">
<diff-discussions
v-if="line.left.discussions.length"
:discussions="line.left.discussions"
/>
</div>
<diff-line-note-form
- v-if="diffLineCommentForms[leftLineCode]"
+ v-if="showLeftSideCommentForm"
:diff-file-hash="diffFileHash"
:line="line.left"
:note-target-line="line.left"
line-position="left"
/>
</td>
- <td class="notes_line new"></td>
- <td class="notes_content parallel new">
- <div
- v-if="shouldRenderDiscussionsOnRight"
- class="content"
- >
+ <td class="notes_content parallel new" colspan="2">
+ <div v-if="shouldRenderDiscussionsOnRight" class="content">
<diff-discussions
v-if="line.right.discussions.length"
:discussions="line.right.discussions"
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
index fcc3b3e9117..caf0df8a4e3 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue
@@ -1,5 +1,5 @@
<script>
-import { mapActions } from 'vuex';
+import { mapActions, mapState } from 'vuex';
import $ from 'jquery';
import DiffTableCell from './diff_table_cell.vue';
import {
@@ -43,6 +43,15 @@ export default {
};
},
computed: {
+ ...mapState({
+ isHighlighted(state) {
+ const lineCode =
+ (this.line.left && this.line.left.line_code) ||
+ (this.line.right && this.line.right.line_code);
+
+ return lineCode ? lineCode === state.diffs.highlightedRow : false;
+ },
+ }),
isContextLine() {
return this.line.left && this.line.left.type === CONTEXT_LINE_TYPE;
},
@@ -57,7 +66,14 @@ export default {
return OLD_NO_NEW_LINE_TYPE;
}
- return this.line.left ? this.line.left.type : EMPTY_CELL_TYPE;
+ const lineTypeClass = this.line.left ? this.line.left.type : EMPTY_CELL_TYPE;
+
+ return [
+ lineTypeClass,
+ {
+ hll: this.isHighlighted,
+ },
+ ];
},
},
created() {
@@ -114,19 +130,19 @@ export default {
:line-type="oldLineType"
:is-bottom="isBottom"
:is-hover="isLeftHover"
+ :is-highlighted="isHighlighted"
:show-comment-button="true"
:diff-view-type="parallelDiffViewType"
line-position="left"
class="diff-line-num old_line"
/>
<td
- :id="line.left.lineCode"
+ :id="line.left.line_code"
:class="parallelViewLeftLineType"
class="line_content parallel left-side"
@mousedown.native="handleParallelLineMouseDown"
- v-html="line.left.richText"
- >
- </td>
+ v-html="line.left.rich_text"
+ ></td>
</template>
<template v-else>
<td class="diff-line-num old_line empty-cell"></td>
@@ -140,19 +156,24 @@ export default {
:line-type="newLineType"
:is-bottom="isBottom"
:is-hover="isRightHover"
+ :is-highlighted="isHighlighted"
:show-comment-button="true"
:diff-view-type="parallelDiffViewType"
line-position="right"
class="diff-line-num new_line"
/>
<td
- :id="line.right.lineCode"
- :class="line.right.type"
+ :id="line.right.line_code"
+ :class="[
+ line.right.type,
+ {
+ hll: isHighlighted,
+ },
+ ]"
class="line_content parallel right-side"
@mousedown.native="handleParallelLineMouseDown"
- v-html="line.right.richText"
- >
- </td>
+ v-html="line.right.rich_text"
+ ></td>
</template>
<template v-else>
<td class="diff-line-num old_line empty-cell"></td>
diff --git a/app/assets/javascripts/diffs/components/parallel_diff_view.vue b/app/assets/javascripts/diffs/components/parallel_diff_view.vue
index 501bd4450d8..9a6e0e82529 100644
--- a/app/assets/javascripts/diffs/components/parallel_diff_view.vue
+++ b/app/assets/javascripts/diffs/components/parallel_diff_view.vue
@@ -1,5 +1,5 @@
<script>
-import { mapState, mapGetters } from 'vuex';
+import { mapGetters } from 'vuex';
import parallelDiffTableRow from './parallel_diff_table_row.vue';
import parallelDiffCommentRow from './parallel_diff_comment_row.vue';
@@ -19,43 +19,35 @@ export default {
},
},
computed: {
- ...mapGetters('diffs', ['commitId', 'shouldRenderParallelCommentRow']),
- ...mapState({
- diffLineCommentForms: state => state.diffs.diffLineCommentForms,
- }),
+ ...mapGetters('diffs', ['commitId']),
diffLinesLength() {
return this.diffLines.length;
},
- userColorScheme() {
- return window.gon.user_color_scheme;
- },
},
+ userColorScheme: window.gon.user_color_scheme,
};
</script>
<template>
<div
- :class="userColorScheme"
+ :class="$options.userColorScheme"
:data-commit-id="commitId"
class="code diff-wrap-lines js-syntax-highlight text-file"
>
<table>
<tbody>
- <template
- v-for="(line, index) in diffLines"
- >
+ <template v-for="(line, index) in diffLines">
<parallel-diff-table-row
- :file-hash="diffFile.fileHash"
- :context-lines-path="diffFile.contextLinesPath"
+ :key="index"
+ :file-hash="diffFile.file_hash"
+ :context-lines-path="diffFile.context_lines_path"
:line="line"
:is-bottom="index + 1 === diffLinesLength"
- :key="index"
/>
<parallel-diff-comment-row
- v-if="shouldRenderParallelCommentRow(line)"
:key="`dcr-${index}`"
:line="line"
- :diff-file-hash="diffFile.fileHash"
+ :diff-file-hash="diffFile.file_hash"
:line-index="index"
/>
</template>
diff --git a/app/assets/javascripts/diffs/components/tree_list.vue b/app/assets/javascripts/diffs/components/tree_list.vue
new file mode 100644
index 00000000000..f40a7b25fde
--- /dev/null
+++ b/app/assets/javascripts/diffs/components/tree_list.vue
@@ -0,0 +1,150 @@
+<script>
+import { mapActions, mapGetters, mapState } from 'vuex';
+import { GlTooltipDirective } from '@gitlab/ui';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import Icon from '~/vue_shared/components/icon.vue';
+import FileRow from '~/vue_shared/components/file_row.vue';
+import FileRowStats from './file_row_stats.vue';
+
+const treeListStorageKey = 'mr_diff_tree_list';
+
+export default {
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ components: {
+ Icon,
+ FileRow,
+ },
+ data() {
+ const treeListStored = localStorage.getItem(treeListStorageKey);
+ const renderTreeList = treeListStored !== null ? parseBoolean(treeListStored) : true;
+
+ return {
+ search: '',
+ renderTreeList,
+ focusSearch: false,
+ };
+ },
+ computed: {
+ ...mapState('diffs', ['tree', 'addedLines', 'removedLines']),
+ ...mapGetters('diffs', ['allBlobs', 'diffFilesLength']),
+ filteredTreeList() {
+ const search = this.search.toLowerCase().trim();
+
+ if (search === '') return this.renderTreeList ? this.tree : this.allBlobs;
+
+ return this.allBlobs.filter(f => f.path.toLowerCase().indexOf(search) >= 0);
+ },
+ rowDisplayTextKey() {
+ if (this.renderTreeList && this.search.trim() === '') {
+ return 'name';
+ }
+
+ return 'path';
+ },
+ },
+ methods: {
+ ...mapActions('diffs', ['toggleTreeOpen', 'scrollToFile']),
+ clearSearch() {
+ this.search = '';
+ this.toggleFocusSearch(false);
+ },
+ toggleRenderTreeList(toggle) {
+ this.renderTreeList = toggle;
+ localStorage.setItem(treeListStorageKey, this.renderTreeList);
+ },
+ toggleFocusSearch(toggle) {
+ this.focusSearch = toggle;
+ },
+ blurSearch() {
+ if (this.search.trim() === '') {
+ this.toggleFocusSearch(false);
+ }
+ },
+ },
+ FileRowStats,
+};
+</script>
+
+<template>
+ <div class="tree-list-holder d-flex flex-column">
+ <div class="append-bottom-8 position-relative tree-list-search d-flex">
+ <div class="flex-fill d-flex">
+ <icon name="search" class="position-absolute tree-list-icon" />
+ <input
+ v-model="search"
+ :placeholder="s__('MergeRequest|Filter files')"
+ type="search"
+ class="form-control"
+ @focus="toggleFocusSearch(true);"
+ @blur="blurSearch"
+ />
+ <button
+ v-show="search"
+ :aria-label="__('Clear search')"
+ type="button"
+ class="position-absolute bg-transparent tree-list-icon tree-list-clear-icon border-0 p-0"
+ @click="clearSearch"
+ >
+ <icon name="close" />
+ </button>
+ </div>
+ <div v-show="!focusSearch" class="btn-group prepend-left-8 tree-list-view-toggle">
+ <button
+ v-gl-tooltip.hover
+ :aria-label="__('List view')"
+ :title="__('List view')"
+ :class="{
+ active: !renderTreeList,
+ }"
+ class="btn btn-default pt-0 pb-0 d-flex align-items-center"
+ type="button"
+ @click="toggleRenderTreeList(false);"
+ >
+ <icon name="hamburger" />
+ </button>
+ <button
+ v-gl-tooltip.hover
+ :aria-label="__('Tree view')"
+ :title="__('Tree view')"
+ :class="{
+ active: renderTreeList,
+ }"
+ class="btn btn-default pt-0 pb-0 d-flex align-items-center"
+ type="button"
+ @click="toggleRenderTreeList(true);"
+ >
+ <icon name="file-tree" />
+ </button>
+ </div>
+ </div>
+ <div class="tree-list-scroll">
+ <template v-if="filteredTreeList.length">
+ <file-row
+ v-for="file in filteredTreeList"
+ :key="file.key"
+ :file="file"
+ :level="0"
+ :hide-extra-on-tree="true"
+ :extra-component="$options.FileRowStats"
+ :show-changed-icon="true"
+ :display-text-key="rowDisplayTextKey"
+ :should-truncate-start="true"
+ @toggleTreeOpen="toggleTreeOpen"
+ @clickFile="scrollToFile"
+ />
+ </template>
+ <p v-else class="prepend-top-20 append-bottom-20 text-center">
+ {{ s__('MergeRequest|No files found') }}
+ </p>
+ </div>
+ <div v-once class="pt-3 pb-3 text-center">
+ {{ n__('%d changed file', '%d changed files', diffFilesLength) }}
+ <div>
+ <span class="cgreen"> {{ n__('%d addition', '%d additions', addedLines) }} </span>
+ <span class="cred"> {{ n__('%d deleted', '%d deletions', removedLines) }} </span>
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/diffs/constants.js b/app/assets/javascripts/diffs/constants.js
index 2795dddfc48..78a39baa4cb 100644
--- a/app/assets/javascripts/diffs/constants.js
+++ b/app/assets/javascripts/diffs/constants.js
@@ -12,6 +12,7 @@ export const NOTE_TYPE = 'Note';
export const NEW_LINE_TYPE = 'new';
export const OLD_LINE_TYPE = 'old';
export const TEXT_DIFF_POSITION_TYPE = 'text';
+export const IMAGE_DIFF_POSITION_TYPE = 'image';
export const LINE_POSITION_LEFT = 'left';
export const LINE_POSITION_RIGHT = 'right';
@@ -29,3 +30,5 @@ export const LENGTH_OF_AVATAR_TOOLTIP = 17;
export const LINES_TO_BE_RENDERED_DIRECTLY = 100;
export const MAX_LINES_TO_BE_RENDERED = 2000;
+
+export const MR_TREE_SHOW_KEY = 'mr_tree_show';
diff --git a/app/assets/javascripts/diffs/index.js b/app/assets/javascripts/diffs/index.js
index aae89109c27..06ef4207d85 100644
--- a/app/assets/javascripts/diffs/index.js
+++ b/app/assets/javascripts/diffs/index.js
@@ -1,6 +1,5 @@
import Vue from 'vue';
import { mapState } from 'vuex';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import diffsApp from './components/app.vue';
export default function initDiffsApp(store) {
@@ -17,9 +16,7 @@ export default function initDiffsApp(store) {
return {
endpoint: dataset.endpoint,
projectPath: dataset.projectPath,
- currentUser: convertObjectPropsToCamelCase(JSON.parse(dataset.currentUserData), {
- deep: true,
- }),
+ currentUser: JSON.parse(dataset.currentUserData) || {},
};
},
computed: {
diff --git a/app/assets/javascripts/diffs/mixins/changed_files.js b/app/assets/javascripts/diffs/mixins/changed_files.js
deleted file mode 100644
index da1339f0ffa..00000000000
--- a/app/assets/javascripts/diffs/mixins/changed_files.js
+++ /dev/null
@@ -1,38 +0,0 @@
-export default {
- props: {
- diffFiles: {
- type: Array,
- required: true,
- },
- },
- methods: {
- fileChangedIcon(diffFile) {
- if (diffFile.deletedFile) {
- return 'file-deletion';
- } else if (diffFile.newFile) {
- return 'file-addition';
- }
- return 'file-modified';
- },
- fileChangedClass(diffFile) {
- if (diffFile.deletedFile) {
- return 'cred';
- } else if (diffFile.newFile) {
- return 'cgreen';
- }
-
- return '';
- },
- truncatedDiffPath(path) {
- const maxLength = 60;
-
- if (path.length > maxLength) {
- const start = path.length - maxLength;
- const end = start + maxLength;
- return `...${path.slice(start, end)}`;
- }
-
- return path;
- },
- },
-};
diff --git a/app/assets/javascripts/diffs/store/actions.js b/app/assets/javascripts/diffs/store/actions.js
index e60bb9dd7e3..8b477c678fd 100644
--- a/app/assets/javascripts/diffs/store/actions.js
+++ b/app/assets/javascripts/diffs/store/actions.js
@@ -1,14 +1,17 @@
import Vue from 'vue';
import axios from '~/lib/utils/axios_utils';
import Cookies from 'js-cookie';
+import createFlash from '~/flash';
+import { s__ } from '~/locale';
import { handleLocationHash, historyPushState } from '~/lib/utils/common_utils';
import { mergeUrlParams, getLocationHash } from '~/lib/utils/url_utility';
-import { getDiffPositionByLineCode } from './utils';
+import { getDiffPositionByLineCode, getNoteFormData } from './utils';
import * as types from './mutation_types';
import {
PARALLEL_DIFF_VIEW_TYPE,
INLINE_DIFF_VIEW_TYPE,
DIFF_VIEW_COOKIE_NAME,
+ MR_TREE_SHOW_KEY,
} from '../constants';
export const setBaseConfig = ({ commit }, options) => {
@@ -30,26 +33,31 @@ export const fetchDiffFiles = ({ state, commit }) => {
.then(handleLocationHash);
};
+export const setHighlightedRow = ({ commit }, lineCode) => {
+ commit(types.SET_HIGHLIGHTED_ROW, lineCode);
+};
+
// This is adding line discussions to the actual lines in the diff tree
// once for parallel and once for inline mode
-export const assignDiscussionsToDiff = ({ state, commit }, allLineDiscussions) => {
+export const assignDiscussionsToDiff = (
+ { commit, state, rootState },
+ discussions = rootState.notes.discussions,
+) => {
const diffPositionByLineCode = getDiffPositionByLineCode(state.diffFiles);
- Object.values(allLineDiscussions).forEach(discussions => {
- if (discussions.length > 0) {
- const { fileHash } = discussions[0];
+ discussions
+ .filter(discussion => discussion.diff_discussion)
+ .forEach(discussion => {
commit(types.SET_LINE_DISCUSSIONS_FOR_FILE, {
- fileHash,
- discussions,
+ discussion,
diffPositionByLineCode,
});
- }
- });
+ });
};
export const removeDiscussionsFromDiff = ({ commit }, removeDiscussion) => {
- const { fileHash, line_code } = removeDiscussion;
- commit(types.REMOVE_LINE_DISCUSSIONS_FOR_FILE, { fileHash, lineCode: line_code });
+ const { file_hash, line_code, id } = removeDiscussion;
+ commit(types.REMOVE_LINE_DISCUSSIONS_FOR_FILE, { fileHash: file_hash, lineCode: line_code, id });
};
export const startRenderDiffsQueue = ({ state, commit }) => {
@@ -95,12 +103,12 @@ export const setParallelDiffViewType = ({ commit }) => {
historyPushState(url);
};
-export const showCommentForm = ({ commit }, params) => {
- commit(types.ADD_COMMENT_FORM_LINE, params);
+export const showCommentForm = ({ commit }, { lineCode, fileHash }) => {
+ commit(types.TOGGLE_LINE_HAS_FORM, { lineCode, fileHash, hasForm: true });
};
-export const cancelCommentForm = ({ commit }, params) => {
- commit(types.REMOVE_COMMENT_FORM_LINE, params);
+export const cancelCommentForm = ({ commit }, { lineCode, fileHash }) => {
+ commit(types.TOGGLE_LINE_HAS_FORM, { lineCode, fileHash, hasForm: false });
};
export const loadMoreLines = ({ commit }, options) => {
@@ -123,7 +131,7 @@ export const loadMoreLines = ({ commit }, options) => {
export const scrollToLineIfNeededInline = (_, line) => {
const hash = getLocationHash();
- if (hash && line.lineCode === hash) {
+ if (hash && line.line_code === hash) {
handleLocationHash();
}
};
@@ -133,7 +141,7 @@ export const scrollToLineIfNeededParallel = (_, line) => {
if (
hash &&
- ((line.left && line.left.lineCode === hash) || (line.right && line.right.lineCode === hash))
+ ((line.left && line.left.line_code === hash) || (line.right && line.right.line_code === hash))
) {
handleLocationHash();
}
@@ -165,7 +173,7 @@ export const expandAllFiles = ({ commit }) => {
export const toggleFileDiscussions = ({ getters, dispatch }, diff) => {
const discussions = getters.getDiffFileDiscussions(diff);
const shouldCloseAll = getters.diffHasAllExpandedDiscussions(diff);
- const shouldExpandAll = getters.diffHasAllCollpasedDiscussions(diff);
+ const shouldExpandAll = getters.diffHasAllCollapsedDiscussions(diff);
discussions.forEach(discussion => {
const data = { discussionId: discussion.id };
@@ -178,5 +186,51 @@ export const toggleFileDiscussions = ({ getters, dispatch }, diff) => {
});
};
+export const saveDiffDiscussion = ({ dispatch }, { note, formData }) => {
+ const postData = getNoteFormData({
+ note,
+ ...formData,
+ });
+
+ return dispatch('saveNote', postData, { root: true })
+ .then(result => dispatch('updateDiscussion', result.discussion, { root: true }))
+ .then(discussion => dispatch('assignDiscussionsToDiff', [discussion]))
+ .then(() => dispatch('updateResolvableDiscussonsCounts', null, { root: true }))
+ .then(() => dispatch('closeDiffFileCommentForm', formData.diffFile.file_hash))
+ .catch(() => createFlash(s__('MergeRequests|Saving the comment failed')));
+};
+
+export const toggleTreeOpen = ({ commit }, path) => {
+ commit(types.TOGGLE_FOLDER_OPEN, path);
+};
+
+export const scrollToFile = ({ state, commit }, path) => {
+ const { fileHash } = state.treeEntries[path];
+ document.location.hash = fileHash;
+
+ commit(types.UPDATE_CURRENT_DIFF_FILE_ID, fileHash);
+
+ setTimeout(() => commit(types.UPDATE_CURRENT_DIFF_FILE_ID, ''), 1000);
+};
+
+export const toggleShowTreeList = ({ commit, state }) => {
+ commit(types.TOGGLE_SHOW_TREE_LIST);
+ localStorage.setItem(MR_TREE_SHOW_KEY, state.showTreeList);
+};
+
+export const openDiffFileCommentForm = ({ commit, getters }, formData) => {
+ const form = getters.getCommentFormForDiffFile(formData.fileHash);
+
+ if (form) {
+ commit(types.UPDATE_DIFF_FILE_COMMENT_FORM, formData);
+ } else {
+ commit(types.OPEN_DIFF_FILE_COMMENT_FORM, formData);
+ }
+};
+
+export const closeDiffFileCommentForm = ({ commit }, fileHash) => {
+ commit(types.CLOSE_DIFF_FILE_COMMENT_FORM, fileHash);
+};
+
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js
index 968ba3c5e13..fdf1efbb10e 100644
--- a/app/assets/javascripts/diffs/store/getters.js
+++ b/app/assets/javascripts/diffs/store/getters.js
@@ -1,11 +1,10 @@
-import _ from 'underscore';
import { PARALLEL_DIFF_VIEW_TYPE, INLINE_DIFF_VIEW_TYPE } from '../constants';
export const isParallelView = state => state.diffViewType === PARALLEL_DIFF_VIEW_TYPE;
export const isInlineView = state => state.diffViewType === INLINE_DIFF_VIEW_TYPE;
-export const areAllFilesCollapsed = state => state.diffFiles.every(file => file.collapsed);
+export const hasCollapsedFile = state => state.diffFiles.some(file => file.collapsed);
export const commitId = state => (state.commit && state.commit.id ? state.commit.id : null);
@@ -24,11 +23,11 @@ export const diffHasAllExpandedDiscussions = (state, getters) => diff => {
};
/**
- * Checks if the diff has all discussions collpased
+ * Checks if the diff has all discussions collapsed
* @param {Object} diff
* @returns {Boolean}
*/
-export const diffHasAllCollpasedDiscussions = (state, getters) => diff => {
+export const diffHasAllCollapsedDiscussions = (state, getters) => diff => {
const discussions = getters.getDiffFileDiscussions(diff);
return (
@@ -68,47 +67,19 @@ export const diffHasDiscussions = (state, getters) => diff =>
*/
export const getDiffFileDiscussions = (state, getters, rootState, rootGetters) => diff =>
rootGetters.discussions.filter(
- discussion =>
- discussion.diff_discussion && _.isEqual(discussion.diff_file.file_hash, diff.fileHash),
+ discussion => discussion.diff_discussion && discussion.diff_file.file_hash === diff.file_hash,
) || [];
-export const shouldRenderParallelCommentRow = state => line => {
- const hasDiscussion =
- (line.left && line.left.discussions && line.left.discussions.length) ||
- (line.right && line.right.discussions && line.right.discussions.length);
-
- const hasExpandedDiscussionOnLeft =
- line.left && line.left.discussions && line.left.discussions.length
- ? line.left.discussions.every(discussion => discussion.expanded)
- : false;
- const hasExpandedDiscussionOnRight =
- line.right && line.right.discussions && line.right.discussions.length
- ? line.right.discussions.every(discussion => discussion.expanded)
- : false;
-
- if (hasDiscussion && (hasExpandedDiscussionOnLeft || hasExpandedDiscussionOnRight)) {
- return true;
- }
-
- const hasCommentFormOnLeft = line.left && state.diffLineCommentForms[line.left.lineCode];
- const hasCommentFormOnRight = line.right && state.diffLineCommentForms[line.right.lineCode];
-
- return hasCommentFormOnLeft || hasCommentFormOnRight;
-};
-
-export const shouldRenderInlineCommentRow = state => line => {
- if (state.diffLineCommentForms[line.lineCode]) return true;
+// prevent babel-plugin-rewire from generating an invalid default during karma∂ tests
+export const getDiffFileByHash = state => fileHash =>
+ state.diffFiles.find(file => file.file_hash === fileHash);
- if (!line.discussions || line.discussions.length === 0) {
- return false;
- }
+export const allBlobs = state => Object.values(state.treeEntries).filter(f => f.type === 'blob');
- return line.discussions.every(discussion => discussion.expanded);
-};
+export const diffFilesLength = state => state.diffFiles.length;
-// prevent babel-plugin-rewire from generating an invalid default during karma∂ tests
-export const getDiffFileByHash = state => fileHash =>
- state.diffFiles.find(file => file.fileHash === fileHash);
+export const getCommentFormForDiffFile = state => fileHash =>
+ state.commentForms.find(form => form.fileHash === fileHash);
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/assets/javascripts/diffs/store/modules/diff_state.js b/app/assets/javascripts/diffs/store/modules/diff_state.js
index eb596b251c1..98e57d52d77 100644
--- a/app/assets/javascripts/diffs/store/modules/diff_state.js
+++ b/app/assets/javascripts/diffs/store/modules/diff_state.js
@@ -1,10 +1,13 @@
import Cookies from 'js-cookie';
import { getParameterValues } from '~/lib/utils/url_utility';
-import { INLINE_DIFF_VIEW_TYPE, DIFF_VIEW_COOKIE_NAME } from '../../constants';
+import bp from '~/breakpoints';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import { INLINE_DIFF_VIEW_TYPE, DIFF_VIEW_COOKIE_NAME, MR_TREE_SHOW_KEY } from '../../constants';
const viewTypeFromQueryString = getParameterValues('view')[0];
const viewTypeFromCookie = Cookies.get(DIFF_VIEW_COOKIE_NAME);
const defaultViewType = INLINE_DIFF_VIEW_TYPE;
+const storedTreeShow = localStorage.getItem(MR_TREE_SHOW_KEY);
export default () => ({
isLoading: true,
@@ -15,6 +18,13 @@ export default () => ({
diffFiles: [],
mergeRequestDiffs: [],
mergeRequestDiff: null,
- diffLineCommentForms: {},
diffViewType: viewTypeFromQueryString || viewTypeFromCookie || defaultViewType,
+ tree: [],
+ treeEntries: {},
+ showTreeList:
+ storedTreeShow === null ? bp.getBreakpointSize() !== 'xs' : parseBoolean(storedTreeShow),
+ currentDiffFileId: '',
+ projectPath: '',
+ commentForms: [],
+ highlightedRow: null,
});
diff --git a/app/assets/javascripts/diffs/store/mutation_types.js b/app/assets/javascripts/diffs/store/mutation_types.js
index f61efbe6e1e..0338cde3658 100644
--- a/app/assets/javascripts/diffs/store/mutation_types.js
+++ b/app/assets/javascripts/diffs/store/mutation_types.js
@@ -3,11 +3,18 @@ export const SET_LOADING = 'SET_LOADING';
export const SET_DIFF_DATA = 'SET_DIFF_DATA';
export const SET_DIFF_VIEW_TYPE = 'SET_DIFF_VIEW_TYPE';
export const SET_MERGE_REQUEST_DIFFS = 'SET_MERGE_REQUEST_DIFFS';
-export const ADD_COMMENT_FORM_LINE = 'ADD_COMMENT_FORM_LINE';
-export const REMOVE_COMMENT_FORM_LINE = 'REMOVE_COMMENT_FORM_LINE';
+export const TOGGLE_LINE_HAS_FORM = 'TOGGLE_LINE_HAS_FORM';
export const ADD_CONTEXT_LINES = 'ADD_CONTEXT_LINES';
export const ADD_COLLAPSED_DIFFS = 'ADD_COLLAPSED_DIFFS';
export const EXPAND_ALL_FILES = 'EXPAND_ALL_FILES';
export const RENDER_FILE = 'RENDER_FILE';
export const SET_LINE_DISCUSSIONS_FOR_FILE = 'SET_LINE_DISCUSSIONS_FOR_FILE';
export const REMOVE_LINE_DISCUSSIONS_FOR_FILE = 'REMOVE_LINE_DISCUSSIONS_FOR_FILE';
+export const TOGGLE_FOLDER_OPEN = 'TOGGLE_FOLDER_OPEN';
+export const TOGGLE_SHOW_TREE_LIST = 'TOGGLE_SHOW_TREE_LIST';
+export const UPDATE_CURRENT_DIFF_FILE_ID = 'UPDATE_CURRENT_DIFF_FILE_ID';
+
+export const OPEN_DIFF_FILE_COMMENT_FORM = 'OPEN_DIFF_FILE_COMMENT_FORM';
+export const UPDATE_DIFF_FILE_COMMENT_FORM = 'UPDATE_DIFF_FILE_COMMENT_FORM';
+export const CLOSE_DIFF_FILE_COMMENT_FORM = 'CLOSE_DIFF_FILE_COMMENT_FORM';
+export const SET_HIGHLIGHTED_ROW = 'SET_HIGHLIGHTED_ROW';
diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js
index 59a2c09e54f..f0895661bf2 100644
--- a/app/assets/javascripts/diffs/store/mutations.js
+++ b/app/assets/javascripts/diffs/store/mutations.js
@@ -1,5 +1,5 @@
-import Vue from 'vue';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { sortTree } from '~/ide/stores/utils';
import {
findDiffFile,
addLineReferences,
@@ -7,6 +7,7 @@ import {
addContextLines,
prepareDiffData,
isDiscussionApplicableToLine,
+ generateTreeList,
} from './utils';
import * as types from './mutation_types';
@@ -21,11 +22,13 @@ export default {
},
[types.SET_DIFF_DATA](state, data) {
- const diffData = convertObjectPropsToCamelCase(data, { deep: true });
- prepareDiffData(diffData);
+ prepareDiffData(data);
+ const { tree, treeEntries } = generateTreeList(data.diff_files);
Object.assign(state, {
- ...diffData,
+ ...convertObjectPropsToCamelCase(data),
+ tree: sortTree(tree),
+ treeEntries,
});
},
@@ -37,7 +40,7 @@ export default {
[types.SET_MERGE_REQUEST_DIFFS](state, mergeRequestDiffs) {
Object.assign(state, {
- mergeRequestDiffs: convertObjectPropsToCamelCase(mergeRequestDiffs, { deep: true }),
+ mergeRequestDiffs,
});
},
@@ -45,25 +48,49 @@ export default {
Object.assign(state, { diffViewType });
},
- [types.ADD_COMMENT_FORM_LINE](state, { lineCode }) {
- Vue.set(state.diffLineCommentForms, lineCode, true);
- },
+ [types.TOGGLE_LINE_HAS_FORM](state, { lineCode, fileHash, hasForm }) {
+ const diffFile = state.diffFiles.find(f => f.file_hash === fileHash);
+
+ if (!diffFile) return;
+
+ if (diffFile.highlighted_diff_lines) {
+ diffFile.highlighted_diff_lines.find(l => l.line_code === lineCode).hasForm = hasForm;
+ }
+
+ if (diffFile.parallel_diff_lines) {
+ const line = diffFile.parallel_diff_lines.find(l => {
+ const { left, right } = l;
+
+ return (left && left.line_code === lineCode) || (right && right.line_code === lineCode);
+ });
- [types.REMOVE_COMMENT_FORM_LINE](state, { lineCode }) {
- Vue.delete(state.diffLineCommentForms, lineCode);
+ if (line.left && line.left.line_code === lineCode) {
+ line.left.hasForm = hasForm;
+ }
+
+ if (line.right && line.right.line_code === lineCode) {
+ line.right.hasForm = hasForm;
+ }
+ }
},
[types.ADD_CONTEXT_LINES](state, options) {
const { lineNumbers, contextLines, fileHash } = options;
const { bottom } = options.params;
const diffFile = findDiffFile(state.diffFiles, fileHash);
- const { highlightedDiffLines, parallelDiffLines } = diffFile;
removeMatchLine(diffFile, lineNumbers, bottom);
- const lines = addLineReferences(contextLines, lineNumbers, bottom);
+
+ const lines = addLineReferences(contextLines, lineNumbers, bottom).map(line => ({
+ ...line,
+ line_code: line.line_code || `${fileHash}_${line.old_line}_${line.new_line}`,
+ discussions: line.discussions || [],
+ hasForm: false,
+ }));
+
addContextLines({
- inlineLines: highlightedDiffLines,
- parallelLines: parallelDiffLines,
+ inlineLines: diffFile.highlighted_diff_lines,
+ parallelLines: diffFile.parallel_diff_lines,
contextLines: lines,
bottom,
lineNumbers,
@@ -71,10 +98,9 @@ export default {
},
[types.ADD_COLLAPSED_DIFFS](state, { file, data }) {
- const normalizedData = convertObjectPropsToCamelCase(data, { deep: true });
- prepareDiffData(normalizedData);
- const [newFileData] = normalizedData.diffFiles.filter(f => f.fileHash === file.fileHash);
- const selectedFile = state.diffFiles.find(f => f.fileHash === file.fileHash);
+ prepareDiffData(data);
+ const [newFileData] = data.diff_files.filter(f => f.file_hash === file.file_hash);
+ const selectedFile = state.diffFiles.find(f => f.file_hash === file.file_hash);
Object.assign(selectedFile, { ...newFileData });
},
@@ -85,74 +111,90 @@ export default {
}));
},
- [types.SET_LINE_DISCUSSIONS_FOR_FILE](state, { fileHash, discussions, diffPositionByLineCode }) {
- const selectedFile = state.diffFiles.find(f => f.fileHash === fileHash);
- const firstDiscussion = discussions[0];
- const isDiffDiscussion = firstDiscussion.diff_discussion;
- const hasLineCode = firstDiscussion.line_code;
- const diffPosition = diffPositionByLineCode[firstDiscussion.line_code];
+ [types.SET_LINE_DISCUSSIONS_FOR_FILE](state, { discussion, diffPositionByLineCode }) {
+ const { latestDiff } = state;
- if (
- selectedFile &&
- isDiffDiscussion &&
- hasLineCode &&
- diffPosition &&
+ const discussionLineCode = discussion.line_code;
+ const fileHash = discussion.diff_file.file_hash;
+ const lineCheck = line =>
+ line.line_code === discussionLineCode &&
isDiscussionApplicableToLine({
- discussion: firstDiscussion,
- diffPosition,
- latestDiff: state.latestDiff,
- })
- ) {
- const targetLine = selectedFile.parallelDiffLines.find(
- line =>
- (line.left && line.left.lineCode === firstDiscussion.line_code) ||
- (line.right && line.right.lineCode === firstDiscussion.line_code),
- );
- if (targetLine) {
- if (targetLine.left && targetLine.left.lineCode === firstDiscussion.line_code) {
- Object.assign(targetLine.left, {
- discussions,
- });
- } else {
- Object.assign(targetLine.right, {
- discussions,
+ discussion,
+ diffPosition: diffPositionByLineCode[line.line_code],
+ latestDiff,
+ });
+
+ state.diffFiles = state.diffFiles.map(diffFile => {
+ if (diffFile.file_hash === fileHash) {
+ const file = { ...diffFile };
+
+ if (file.highlighted_diff_lines) {
+ file.highlighted_diff_lines = file.highlighted_diff_lines.map(line => {
+ if (lineCheck(line)) {
+ return {
+ ...line,
+ discussions: line.discussions.concat(discussion),
+ };
+ }
+
+ return line;
});
}
- }
-
- if (selectedFile.highlightedDiffLines) {
- const targetInlineLine = selectedFile.highlightedDiffLines.find(
- line => line.lineCode === firstDiscussion.line_code,
- );
- if (targetInlineLine) {
- Object.assign(targetInlineLine, {
- discussions,
+ if (file.parallel_diff_lines) {
+ file.parallel_diff_lines = file.parallel_diff_lines.map(line => {
+ const left = line.left && lineCheck(line.left);
+ const right = line.right && lineCheck(line.right);
+
+ if (left || right) {
+ return {
+ left: {
+ ...line.left,
+ discussions: left ? line.left.discussions.concat(discussion) : [],
+ },
+ right: {
+ ...line.right,
+ discussions: right && !left ? line.right.discussions.concat(discussion) : [],
+ },
+ };
+ }
+
+ return line;
});
}
+
+ if (!file.parallel_diff_lines || !file.highlighted_diff_lines) {
+ file.discussions = file.discussions.concat(discussion);
+ }
+
+ return file;
}
- }
+
+ return diffFile;
+ });
},
- [types.REMOVE_LINE_DISCUSSIONS_FOR_FILE](state, { fileHash, lineCode }) {
- const selectedFile = state.diffFiles.find(f => f.fileHash === fileHash);
+ [types.REMOVE_LINE_DISCUSSIONS_FOR_FILE](state, { fileHash, lineCode, id }) {
+ const selectedFile = state.diffFiles.find(f => f.file_hash === fileHash);
if (selectedFile) {
- const targetLine = selectedFile.parallelDiffLines.find(
- line =>
- (line.left && line.left.lineCode === lineCode) ||
- (line.right && line.right.lineCode === lineCode),
- );
- if (targetLine) {
- const side = targetLine.left && targetLine.left.lineCode === lineCode ? 'left' : 'right';
-
- Object.assign(targetLine[side], {
- discussions: [],
- });
+ if (selectedFile.parallel_diff_lines) {
+ const targetLine = selectedFile.parallel_diff_lines.find(
+ line =>
+ (line.left && line.left.line_code === lineCode) ||
+ (line.right && line.right.line_code === lineCode),
+ );
+ if (targetLine) {
+ const side = targetLine.left && targetLine.left.line_code === lineCode ? 'left' : 'right';
+
+ Object.assign(targetLine[side], {
+ discussions: [],
+ });
+ }
}
- if (selectedFile.highlightedDiffLines) {
- const targetInlineLine = selectedFile.highlightedDiffLines.find(
- line => line.lineCode === lineCode,
+ if (selectedFile.highlighted_diff_lines) {
+ const targetInlineLine = selectedFile.highlighted_diff_lines.find(
+ line => line.line_code === lineCode,
);
if (targetInlineLine) {
@@ -161,6 +203,45 @@ export default {
});
}
}
+
+ if (selectedFile.discussions && selectedFile.discussions.length) {
+ selectedFile.discussions = selectedFile.discussions.filter(
+ discussion => discussion.id !== id,
+ );
+ }
}
},
+ [types.TOGGLE_FOLDER_OPEN](state, path) {
+ state.treeEntries[path].opened = !state.treeEntries[path].opened;
+ },
+ [types.TOGGLE_SHOW_TREE_LIST](state) {
+ state.showTreeList = !state.showTreeList;
+ },
+ [types.UPDATE_CURRENT_DIFF_FILE_ID](state, fileId) {
+ state.currentDiffFileId = fileId;
+ },
+ [types.OPEN_DIFF_FILE_COMMENT_FORM](state, formData) {
+ state.commentForms.push({
+ ...formData,
+ });
+ },
+ [types.UPDATE_DIFF_FILE_COMMENT_FORM](state, formData) {
+ const { fileHash } = formData;
+
+ state.commentForms = state.commentForms.map(form => {
+ if (form.fileHash === fileHash) {
+ return {
+ ...formData,
+ };
+ }
+
+ return form;
+ });
+ },
+ [types.CLOSE_DIFF_FILE_COMMENT_FORM](state, fileHash) {
+ state.commentForms = state.commentForms.filter(form => form.fileHash !== fileHash);
+ },
+ [types.SET_HIGHLIGHTED_ROW](state, lineCode) {
+ state.highlightedRow = lineCode;
+ },
};
diff --git a/app/assets/javascripts/diffs/store/utils.js b/app/assets/javascripts/diffs/store/utils.js
index 834a94ea42a..54b9ee4d2d6 100644
--- a/app/assets/javascripts/diffs/store/utils.js
+++ b/app/assets/javascripts/diffs/store/utils.js
@@ -1,5 +1,5 @@
import _ from 'underscore';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { diffModes } from '~/ide/constants';
import {
LINE_POSITION_LEFT,
LINE_POSITION_RIGHT,
@@ -14,7 +14,7 @@ import {
} from '../constants';
export function findDiffFile(files, hash) {
- return files.filter(file => file.fileHash === hash)[0];
+ return files.filter(file => file.file_hash === hash)[0];
}
export const getReversePosition = linePosition => {
@@ -25,7 +25,7 @@ export const getReversePosition = linePosition => {
return LINE_POSITION_RIGHT;
};
-export function getNoteFormData(params) {
+export function getFormData(params) {
const {
note,
noteableType,
@@ -34,27 +34,33 @@ export function getNoteFormData(params) {
noteTargetLine,
diffViewType,
linePosition,
+ positionType,
} = params;
const position = JSON.stringify({
- base_sha: diffFile.diffRefs.baseSha,
- start_sha: diffFile.diffRefs.startSha,
- head_sha: diffFile.diffRefs.headSha,
- old_path: diffFile.oldPath,
- new_path: diffFile.newPath,
- position_type: TEXT_DIFF_POSITION_TYPE,
- old_line: noteTargetLine.oldLine,
- new_line: noteTargetLine.newLine,
+ base_sha: diffFile.diff_refs.base_sha,
+ start_sha: diffFile.diff_refs.start_sha,
+ head_sha: diffFile.diff_refs.head_sha,
+ old_path: diffFile.old_path,
+ new_path: diffFile.new_path,
+ position_type: positionType || TEXT_DIFF_POSITION_TYPE,
+ old_line: noteTargetLine ? noteTargetLine.old_line : null,
+ new_line: noteTargetLine ? noteTargetLine.new_line : null,
+ x: params.x,
+ y: params.y,
+ width: params.width,
+ height: params.height,
});
const postData = {
view: diffViewType,
line_type: linePosition === LINE_POSITION_RIGHT ? NEW_LINE_TYPE : OLD_LINE_TYPE,
- merge_request_diff_head_sha: diffFile.diffRefs.headSha,
+ merge_request_diff_head_sha: diffFile.diff_refs.head_sha,
in_reply_to_discussion_id: '',
note_project_id: '',
target_type: noteableData.targetType,
target_id: noteableData.id,
+ return_discussion: true,
note: {
note,
position,
@@ -62,16 +68,22 @@ export function getNoteFormData(params) {
noteable_id: noteableData.id,
commit_id: '',
type:
- diffFile.diffRefs.startSha && diffFile.diffRefs.headSha
+ diffFile.diff_refs.start_sha && diffFile.diff_refs.head_sha
? DIFF_NOTE_TYPE
: LEGACY_DIFF_NOTE_TYPE,
- line_code: noteTargetLine.lineCode,
+ line_code: noteTargetLine ? noteTargetLine.line_code : null,
},
};
+ return postData;
+}
+
+export function getNoteFormData(params) {
+ const data = getFormData(params);
+
return {
- endpoint: noteableData.create_note_path,
- data: postData,
+ endpoint: params.noteableData.create_note_path,
+ data,
};
}
@@ -80,7 +92,7 @@ export const findIndexInInlineLines = (lines, lineNumbers) => {
return _.findIndex(
lines,
- line => line.oldLine === oldLineNumber && line.newLine === newLineNumber,
+ line => line.old_line === oldLineNumber && line.new_line === newLineNumber,
);
};
@@ -92,18 +104,18 @@ export const findIndexInParallelLines = (lines, lineNumbers) => {
line =>
line.left &&
line.right &&
- line.left.oldLine === oldLineNumber &&
- line.right.newLine === newLineNumber,
+ line.left.old_line === oldLineNumber &&
+ line.right.new_line === newLineNumber,
);
};
export function removeMatchLine(diffFile, lineNumbers, bottom) {
- const indexForInline = findIndexInInlineLines(diffFile.highlightedDiffLines, lineNumbers);
- const indexForParallel = findIndexInParallelLines(diffFile.parallelDiffLines, lineNumbers);
+ const indexForInline = findIndexInInlineLines(diffFile.highlighted_diff_lines, lineNumbers);
+ const indexForParallel = findIndexInParallelLines(diffFile.parallel_diff_lines, lineNumbers);
const factor = bottom ? 1 : -1;
- diffFile.highlightedDiffLines.splice(indexForInline + factor, 1);
- diffFile.parallelDiffLines.splice(indexForParallel + factor, 1);
+ diffFile.highlighted_diff_lines.splice(indexForInline + factor, 1);
+ diffFile.parallel_diff_lines.splice(indexForParallel + factor, 1);
}
export function addLineReferences(lines, lineNumbers, bottom) {
@@ -112,18 +124,16 @@ export function addLineReferences(lines, lineNumbers, bottom) {
let matchLineIndex = -1;
const linesWithNumbers = lines.map((l, index) => {
- const line = convertObjectPropsToCamelCase(l);
-
- if (line.type === MATCH_LINE_TYPE) {
+ if (l.type === MATCH_LINE_TYPE) {
matchLineIndex = index;
} else {
- Object.assign(line, {
- oldLine: bottom ? oldLineNumber + index + 1 : oldLineNumber + index - lineCount,
- newLine: bottom ? newLineNumber + index + 1 : newLineNumber + index - lineCount,
+ Object.assign(l, {
+ old_line: bottom ? oldLineNumber + index + 1 : oldLineNumber + index - lineCount,
+ new_line: bottom ? newLineNumber + index + 1 : newLineNumber + index - lineCount,
});
}
- return line;
+ return l;
});
if (matchLineIndex > -1) {
@@ -133,9 +143,9 @@ export function addLineReferences(lines, lineNumbers, bottom) {
: linesWithNumbers[matchLineIndex + 1];
Object.assign(line, {
- metaData: {
- oldPos: targetLine.oldLine,
- newPos: targetLine.newLine,
+ meta_data: {
+ old_pos: targetLine.old_line,
+ new_pos: targetLine.new_line,
},
});
}
@@ -174,11 +184,11 @@ export function trimFirstCharOfLineContent(line = {}) {
const parsedLine = Object.assign({}, line);
- if (line.richText) {
- const firstChar = parsedLine.richText.charAt(0);
+ if (line.rich_text) {
+ const firstChar = parsedLine.rich_text.charAt(0);
if (firstChar === ' ' || firstChar === '+' || firstChar === '-') {
- parsedLine.richText = line.richText.substring(1);
+ parsedLine.rich_text = line.rich_text.substring(1);
}
}
@@ -188,61 +198,60 @@ export function trimFirstCharOfLineContent(line = {}) {
// This prepares and optimizes the incoming diff data from the server
// by setting up incremental rendering and removing unneeded data
export function prepareDiffData(diffData) {
- const filesLength = diffData.diffFiles.length;
+ const filesLength = diffData.diff_files.length;
let showingLines = 0;
for (let i = 0; i < filesLength; i += 1) {
- const file = diffData.diffFiles[i];
+ const file = diffData.diff_files[i];
- if (file.parallelDiffLines) {
- const linesLength = file.parallelDiffLines.length;
+ if (file.parallel_diff_lines) {
+ const linesLength = file.parallel_diff_lines.length;
for (let u = 0; u < linesLength; u += 1) {
- const line = file.parallelDiffLines[u];
+ const line = file.parallel_diff_lines[u];
if (line.left) {
line.left = trimFirstCharOfLineContent(line.left);
+ line.left.hasForm = false;
}
if (line.right) {
line.right = trimFirstCharOfLineContent(line.right);
+ line.right.hasForm = false;
}
}
}
- if (file.highlightedDiffLines) {
- const linesLength = file.highlightedDiffLines.length;
+ if (file.highlighted_diff_lines) {
+ const linesLength = file.highlighted_diff_lines.length;
for (let u = 0; u < linesLength; u += 1) {
- const line = file.highlightedDiffLines[u];
- Object.assign(line, { ...trimFirstCharOfLineContent(line) });
+ const line = file.highlighted_diff_lines[u];
+ Object.assign(line, { ...trimFirstCharOfLineContent(line), hasForm: false });
}
- showingLines += file.parallelDiffLines.length;
+ showingLines += file.parallel_diff_lines.length;
}
Object.assign(file, {
renderIt: showingLines < LINES_TO_BE_RENDERED_DIRECTLY,
collapsed: file.text && showingLines > MAX_LINES_TO_BE_RENDERED,
+ discussions: [],
});
}
}
export function getDiffPositionByLineCode(diffFiles) {
return diffFiles.reduce((acc, diffFile) => {
- const { baseSha, headSha, startSha } = diffFile.diffRefs;
- const { newPath, oldPath } = diffFile;
-
// We can only use highlightedDiffLines to create the map of diff lines because
// highlightedDiffLines will also include every parallel diff line in it.
- if (diffFile.highlightedDiffLines) {
- diffFile.highlightedDiffLines.forEach(line => {
- const { lineCode, oldLine, newLine } = line;
-
- if (lineCode) {
- acc[lineCode] = {
- baseSha,
- headSha,
- startSha,
- newPath,
- oldPath,
- oldLine,
- newLine,
- lineCode,
+ if (diffFile.highlighted_diff_lines) {
+ diffFile.highlighted_diff_lines.forEach(line => {
+ if (line.line_code) {
+ acc[line.line_code] = {
+ base_sha: diffFile.diff_refs.base_sha,
+ head_sha: diffFile.diff_refs.head_sha,
+ start_sha: diffFile.diff_refs.start_sha,
+ new_path: diffFile.new_path,
+ old_path: diffFile.old_path,
+ old_line: line.old_line,
+ new_line: line.new_line,
+ line_code: line.line_code,
+ position_type: 'text',
};
}
});
@@ -255,14 +264,65 @@ export function getDiffPositionByLineCode(diffFiles) {
// This method will check whether the discussion is still applicable
// to the diff line in question regarding different versions of the MR
export function isDiscussionApplicableToLine({ discussion, diffPosition, latestDiff }) {
- const { lineCode, ...diffPositionCopy } = diffPosition;
+ const { line_code, ...diffPositionCopy } = diffPosition;
if (discussion.original_position && discussion.position) {
- const originalRefs = convertObjectPropsToCamelCase(discussion.original_position.formatter);
- const refs = convertObjectPropsToCamelCase(discussion.position.formatter);
+ const originalRefs = discussion.original_position;
+ const refs = discussion.position;
return _.isEqual(refs, diffPositionCopy) || _.isEqual(originalRefs, diffPositionCopy);
}
- return latestDiff && discussion.active && lineCode === discussion.line_code;
+ // eslint-disable-next-line
+ return latestDiff && discussion.active && line_code === discussion.line_code;
}
+
+export const generateTreeList = files =>
+ files.reduce(
+ (acc, file) => {
+ const split = file.new_path.split('/');
+
+ split.forEach((name, i) => {
+ const parent = acc.treeEntries[split.slice(0, i).join('/')];
+ const path = `${parent ? `${parent.path}/` : ''}${name}`;
+
+ if (!acc.treeEntries[path]) {
+ const type = path === file.new_path ? 'blob' : 'tree';
+ acc.treeEntries[path] = {
+ key: path,
+ path,
+ name,
+ type,
+ tree: [],
+ };
+
+ const entry = acc.treeEntries[path];
+
+ if (type === 'blob') {
+ Object.assign(entry, {
+ changed: true,
+ tempFile: file.new_file,
+ deleted: file.deleted_file,
+ fileHash: file.file_hash,
+ addedLines: file.added_lines,
+ removedLines: file.removed_lines,
+ });
+ } else {
+ Object.assign(entry, {
+ opened: true,
+ });
+ }
+
+ (parent ? parent.tree : acc.tree).push(entry);
+ }
+ });
+
+ return acc;
+ },
+ { treeEntries: {}, tree: [] },
+ );
+
+export const getDiffMode = diffFile => {
+ const diffModeKey = Object.keys(diffModes).find(key => diffFile[`${key}_file`]);
+ return diffModes[diffModeKey] || diffModes.replaced;
+};
diff --git a/app/assets/javascripts/dirty_submit/dirty_submit_collection.js b/app/assets/javascripts/dirty_submit/dirty_submit_collection.js
new file mode 100644
index 00000000000..42b051b2270
--- /dev/null
+++ b/app/assets/javascripts/dirty_submit/dirty_submit_collection.js
@@ -0,0 +1,13 @@
+import DirtySubmitForm from './dirty_submit_form';
+
+class DirtySubmitCollection {
+ constructor(forms) {
+ this.forms = forms;
+
+ this.dirtySubmits = [];
+
+ this.forms.forEach(form => this.dirtySubmits.push(new DirtySubmitForm(form)));
+ }
+}
+
+export default DirtySubmitCollection;
diff --git a/app/assets/javascripts/dirty_submit/dirty_submit_factory.js b/app/assets/javascripts/dirty_submit/dirty_submit_factory.js
new file mode 100644
index 00000000000..95a896a7f0b
--- /dev/null
+++ b/app/assets/javascripts/dirty_submit/dirty_submit_factory.js
@@ -0,0 +1,9 @@
+import DirtySubmitCollection from './dirty_submit_collection';
+import DirtySubmitForm from './dirty_submit_form';
+
+export default function dirtySubmitFactory(formOrForms) {
+ const isCollection = formOrForms instanceof NodeList || formOrForms instanceof Array;
+ const DirtySubmitClass = isCollection ? DirtySubmitCollection : DirtySubmitForm;
+
+ return new DirtySubmitClass(formOrForms);
+}
diff --git a/app/assets/javascripts/dirty_submit/dirty_submit_form.js b/app/assets/javascripts/dirty_submit/dirty_submit_form.js
new file mode 100644
index 00000000000..d8d0fa1fac4
--- /dev/null
+++ b/app/assets/javascripts/dirty_submit/dirty_submit_form.js
@@ -0,0 +1,83 @@
+import _ from 'underscore';
+
+class DirtySubmitForm {
+ constructor(form) {
+ this.form = form;
+ this.dirtyInputs = [];
+ this.isDisabled = true;
+
+ this.init();
+ }
+
+ init() {
+ this.inputs = this.form.querySelectorAll('input, textarea, select');
+ this.submits = this.form.querySelectorAll('input[type=submit], button[type=submit]');
+
+ this.inputs.forEach(DirtySubmitForm.initInput);
+ this.toggleSubmission();
+
+ this.registerListeners();
+ }
+
+ registerListeners() {
+ const throttledUpdateDirtyInput = _.throttle(
+ event => this.updateDirtyInput(event),
+ DirtySubmitForm.THROTTLE_DURATION,
+ );
+ this.form.addEventListener('input', throttledUpdateDirtyInput);
+ this.form.addEventListener('submit', event => this.formSubmit(event));
+ }
+
+ updateDirtyInput(event) {
+ const input = event.target;
+
+ if (!input.dataset.isDirtySubmitInput) return;
+
+ this.updateDirtyInputs(input);
+ this.toggleSubmission();
+ }
+
+ updateDirtyInputs(input) {
+ const { name } = input;
+ const isDirty =
+ input.dataset.dirtySubmitOriginalValue !== DirtySubmitForm.inputCurrentValue(input);
+ const indexOfInputName = this.dirtyInputs.indexOf(name);
+ const isExisting = indexOfInputName !== -1;
+
+ if (isDirty && !isExisting) this.dirtyInputs.push(name);
+ if (!isDirty && isExisting) this.dirtyInputs.splice(indexOfInputName, 1);
+ }
+
+ toggleSubmission() {
+ this.isDisabled = this.dirtyInputs.length === 0;
+ this.submits.forEach(element => {
+ element.disabled = this.isDisabled;
+ });
+ }
+
+ formSubmit(event) {
+ if (this.isDisabled) {
+ event.preventDefault();
+ event.stopImmediatePropagation();
+ }
+
+ return !this.isDisabled;
+ }
+
+ static initInput(element) {
+ element.dataset.isDirtySubmitInput = true;
+ element.dataset.dirtySubmitOriginalValue = DirtySubmitForm.inputCurrentValue(element);
+ }
+
+ static isInputCheckable(input) {
+ return input.type === 'checkbox' || input.type === 'radio';
+ }
+
+ static inputCurrentValue(input) {
+ return DirtySubmitForm.isInputCheckable(input) ? input.checked.toString() : input.value;
+ }
+}
+
+DirtySubmitForm.THROTTLE_DURATION = 500;
+
+export default DirtySubmitForm;
diff --git a/app/assets/javascripts/dismissable_callout.js b/app/assets/javascripts/dismissable_callout.js
deleted file mode 100644
index 5185b019376..00000000000
--- a/app/assets/javascripts/dismissable_callout.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import $ from 'jquery';
-import axios from '~/lib/utils/axios_utils';
-import { __ } from '~/locale';
-import Flash from '~/flash';
-
-export default function initDismissableCallout(alertSelector) {
- const alertEl = document.querySelector(alertSelector);
- if (!alertEl) {
- return;
- }
-
- const closeButtonEl = alertEl.getElementsByClassName('close')[0];
- const { dismissEndpoint, featureId } = closeButtonEl.dataset;
-
- closeButtonEl.addEventListener('click', () => {
- axios
- .post(dismissEndpoint, {
- feature_name: featureId,
- })
- .then(() => {
- $(alertEl).alert('close');
- })
- .catch(() => {
- Flash(__('An error occurred while dismissing the alert. Refresh the page and try again.'));
- });
- });
-}
diff --git a/app/assets/javascripts/droplab/constants.js b/app/assets/javascripts/droplab/constants.js
index 868d47e91b3..6451af49d36 100644
--- a/app/assets/javascripts/droplab/constants.js
+++ b/app/assets/javascripts/droplab/constants.js
@@ -6,11 +6,4 @@ const IGNORE_CLASS = 'droplab-item-ignore';
// Matches `{{anything}}` and `{{ everything }}`.
const TEMPLATE_REGEX = /\{\{(.+?)\}\}/g;
-export {
- DATA_TRIGGER,
- DATA_DROPDOWN,
- SELECTED_CLASS,
- ACTIVE_CLASS,
- TEMPLATE_REGEX,
- IGNORE_CLASS,
-};
+export { DATA_TRIGGER, DATA_DROPDOWN, SELECTED_CLASS, ACTIVE_CLASS, TEMPLATE_REGEX, IGNORE_CLASS };
diff --git a/app/assets/javascripts/droplab/drop_down.js b/app/assets/javascripts/droplab/drop_down.js
index 3cc316c3f3e..ccb3d56ed8c 100644
--- a/app/assets/javascripts/droplab/drop_down.js
+++ b/app/assets/javascripts/droplab/drop_down.js
@@ -2,7 +2,7 @@ import utils from './utils';
import { SELECTED_CLASS, IGNORE_CLASS } from './constants';
class DropDown {
- constructor(list, config = { }) {
+ constructor(list, config = {}) {
this.currentIndex = 0;
this.hidden = true;
this.list = typeof list === 'string' ? document.querySelector(list) : list;
@@ -157,7 +157,7 @@ class DropDown {
static setImagesSrc(template) {
const images = [...template.querySelectorAll('img[data-src]')];
- images.forEach((image) => {
+ images.forEach(image => {
const img = image;
img.src = img.getAttribute('data-src');
diff --git a/app/assets/javascripts/droplab/drop_lab.js b/app/assets/javascripts/droplab/drop_lab.js
index 2a02ede72bf..1339e28d8b8 100644
--- a/app/assets/javascripts/droplab/drop_lab.js
+++ b/app/assets/javascripts/droplab/drop_lab.js
@@ -51,7 +51,7 @@ class DropLab {
}
processData(trigger, data, methodName) {
- this.hooks.forEach((hook) => {
+ this.hooks.forEach(hook => {
if (Array.isArray(trigger)) hook.list[methodName](trigger);
if (hook.trigger.id === trigger) hook.list[methodName](data);
@@ -78,7 +78,8 @@ class DropLab {
}
changeHookList(trigger, list, plugins, config) {
- const availableTrigger = typeof trigger === 'string' ? document.getElementById(trigger) : trigger;
+ const availableTrigger =
+ typeof trigger === 'string' ? document.getElementById(trigger) : trigger;
this.hooks.forEach((hook, i) => {
const aHook = hook;
diff --git a/app/assets/javascripts/droplab/keyboard.js b/app/assets/javascripts/droplab/keyboard.js
index 02f1b805ce4..40837ffdf8f 100644
--- a/app/assets/javascripts/droplab/keyboard.js
+++ b/app/assets/javascripts/droplab/keyboard.js
@@ -2,15 +2,18 @@
import { ACTIVE_CLASS } from './constants';
-const Keyboard = function () {
+const Keyboard = function() {
var currentKey;
var currentFocus;
var isUpArrow = false;
var isDownArrow = false;
var removeHighlight = function removeHighlight(list) {
- var itemElements = Array.prototype.slice.call(list.list.querySelectorAll('li:not(.divider):not(.hidden)'), 0);
+ var itemElements = Array.prototype.slice.call(
+ list.list.querySelectorAll('li:not(.divider):not(.hidden)'),
+ 0,
+ );
var listItems = [];
- for(var i = 0; i < itemElements.length; i++) {
+ for (var i = 0; i < itemElements.length; i++) {
var listItem = itemElements[i];
listItem.classList.remove(ACTIVE_CLASS);
@@ -23,13 +26,13 @@ const Keyboard = function () {
var setMenuForArrows = function setMenuForArrows(list) {
var listItems = removeHighlight(list);
- if(list.currentIndex>0){
- if(!listItems[list.currentIndex-1]){
- list.currentIndex = list.currentIndex-1;
+ if (list.currentIndex > 0) {
+ if (!listItems[list.currentIndex - 1]) {
+ list.currentIndex = list.currentIndex - 1;
}
- if (listItems[list.currentIndex-1]) {
- var el = listItems[list.currentIndex-1];
+ if (listItems[list.currentIndex - 1]) {
+ var el = listItems[list.currentIndex - 1];
var filterDropdownEl = el.closest('.filter-dropdown');
el.classList.add(ACTIVE_CLASS);
@@ -55,7 +58,7 @@ const Keyboard = function () {
};
var selectItem = function selectItem(list) {
var listItems = removeHighlight(list);
- var currentItem = listItems[list.currentIndex-1];
+ var currentItem = listItems[list.currentIndex - 1];
var listEvent = new CustomEvent('click.dl', {
detail: {
list: list,
@@ -65,43 +68,49 @@ const Keyboard = function () {
});
list.list.dispatchEvent(listEvent);
list.hide();
- }
+ };
- var keydown = function keydown(e){
+ var keydown = function keydown(e) {
var typedOn = e.target;
var list = e.detail.hook.list;
var currentIndex = list.currentIndex;
isUpArrow = false;
isDownArrow = false;
- if(e.detail.which){
+ if (e.detail.which) {
currentKey = e.detail.which;
- if(currentKey === 13){
+ if (currentKey === 13) {
selectItem(e.detail.hook.list);
return;
}
- if(currentKey === 38) {
+ if (currentKey === 38) {
isUpArrow = true;
}
- if(currentKey === 40) {
+ if (currentKey === 40) {
isDownArrow = true;
}
- } else if(e.detail.key) {
+ } else if (e.detail.key) {
currentKey = e.detail.key;
- if(currentKey === 'Enter'){
+ if (currentKey === 'Enter') {
selectItem(e.detail.hook.list);
return;
}
- if(currentKey === 'ArrowUp') {
+ if (currentKey === 'ArrowUp') {
isUpArrow = true;
}
- if(currentKey === 'ArrowDown') {
+ if (currentKey === 'ArrowDown') {
isDownArrow = true;
}
}
- if(isUpArrow){ currentIndex--; }
- if(isDownArrow){ currentIndex++; }
- if(currentIndex < 0){ currentIndex = 0; }
+ if (isUpArrow) {
+ currentIndex--;
+ }
+ if (isDownArrow) {
+ currentIndex++;
+ }
+ if (currentIndex < 0) {
+ currentIndex = 0;
+ }
list.currentIndex = currentIndex;
setMenuForArrows(e.detail.hook.list);
};
diff --git a/app/assets/javascripts/droplab/plugins/ajax.js b/app/assets/javascripts/droplab/plugins/ajax.js
index 267b53fa4f2..48b2a90c459 100644
--- a/app/assets/javascripts/droplab/plugins/ajax.js
+++ b/app/assets/javascripts/droplab/plugins/ajax.js
@@ -43,12 +43,12 @@ const Ajax = {
return AjaxCache.retrieve(config.endpoint)
.then(self.preprocessing.bind(null, config))
- .then((data) => self._loadData(data, config, self))
+ .then(data => self._loadData(data, config, self))
.catch(config.onError);
},
destroy: function() {
this.destroyed = true;
- }
+ },
};
export default Ajax;
diff --git a/app/assets/javascripts/droplab/plugins/ajax_filter.js b/app/assets/javascripts/droplab/plugins/ajax_filter.js
index 1db20227a16..66a52548417 100644
--- a/app/assets/javascripts/droplab/plugins/ajax_filter.js
+++ b/app/assets/javascripts/droplab/plugins/ajax_filter.js
@@ -41,8 +41,10 @@ const AjaxFilter = {
if (config.searchValueFunction) {
searchValue = config.searchValueFunction();
}
- if (config.loadingTemplate && this.hook.list.data === undefined ||
- this.hook.list.data.length === 0) {
+ if (
+ (config.loadingTemplate && this.hook.list.data === undefined) ||
+ this.hook.list.data.length === 0
+ ) {
var dynamicList = this.hook.list.list.querySelector('[data-dynamic]');
var loadingTemplate = document.createElement('div');
loadingTemplate.innerHTML = config.loadingTemplate;
@@ -61,7 +63,7 @@ const AjaxFilter = {
params[config.searchKey] = searchValue;
var url = config.endpoint + this.buildParams(params);
return AjaxCache.retrieve(url)
- .then((data) => {
+ .then(data => {
this._loadData(data, config);
if (config.onLoadingFinished) {
config.onLoadingFinished(data);
@@ -72,8 +74,7 @@ const AjaxFilter = {
_loadData(data, config) {
const list = this.hook.list;
- if (config.loadingTemplate && list.data === undefined ||
- list.data.length === 0) {
+ if ((config.loadingTemplate && list.data === undefined) || list.data.length === 0) {
const dataLoadingTemplate = list.list.querySelector('[data-loading-template]');
if (dataLoadingTemplate) {
dataLoadingTemplate.outerHTML = this.listTemplate;
@@ -81,7 +82,8 @@ const AjaxFilter = {
}
if (!this.destroyed) {
var hookListChildren = list.list.children;
- var onlyDynamicList = hookListChildren.length === 1 && hookListChildren[0].hasAttribute('data-dynamic');
+ var onlyDynamicList =
+ hookListChildren.length === 1 && hookListChildren[0].hasAttribute('data-dynamic');
if (onlyDynamicList && data.length === 0) {
list.hide();
}
@@ -100,12 +102,12 @@ const AjaxFilter = {
},
destroy: function destroy() {
- if (this.timeout)clearTimeout(this.timeout);
+ if (this.timeout) clearTimeout(this.timeout);
this.destroyed = true;
this.hook.trigger.removeEventListener('keydown.dl', this.eventWrapper.debounceTrigger);
this.hook.trigger.removeEventListener('focus', this.eventWrapper.debounceTrigger);
- }
+ },
};
export default AjaxFilter;
diff --git a/app/assets/javascripts/droplab/plugins/filter.js b/app/assets/javascripts/droplab/plugins/filter.js
index 404d707cf7a..6f1dc252d24 100644
--- a/app/assets/javascripts/droplab/plugins/filter.js
+++ b/app/assets/javascripts/droplab/plugins/filter.js
@@ -1,7 +1,7 @@
/* eslint-disable */
const Filter = {
- keydown: function(e){
+ keydown: function(e) {
if (this.destroyed) return;
var hiddenCount = 0;
@@ -14,14 +14,14 @@ const Filter = {
var matches = [];
var filterFunction;
// will only work on dynamically set data
- if(!data){
+ if (!data) {
return;
}
if (config && config.filterFunction && typeof config.filterFunction === 'function') {
filterFunction = config.filterFunction;
} else {
- filterFunction = function(o){
+ filterFunction = function(o) {
// cheap string search
o.droplab_hidden = o[config.template].toLowerCase().indexOf(value) === -1;
return o;
@@ -47,20 +47,23 @@ const Filter = {
},
debounceKeydown: function debounceKeydown(e) {
- if ([
- 13, // enter
- 16, // shift
- 17, // ctrl
- 18, // alt
- 20, // caps lock
- 37, // left arrow
- 38, // up arrow
- 39, // right arrow
- 40, // down arrow
- 91, // left window
- 92, // right window
- 93, // select
- ].indexOf(e.detail.which || e.detail.keyCode) > -1) return;
+ if (
+ [
+ 13, // enter
+ 16, // shift
+ 17, // ctrl
+ 18, // alt
+ 20, // caps lock
+ 37, // left arrow
+ 38, // up arrow
+ 39, // right arrow
+ 40, // down arrow
+ 91, // left window
+ 92, // right window
+ 93, // select
+ ].indexOf(e.detail.which || e.detail.keyCode) > -1
+ )
+ return;
if (this.timeout) clearTimeout(this.timeout);
this.timeout = setTimeout(this.keydown.bind(this, e), 200);
@@ -87,7 +90,7 @@ const Filter = {
this.hook.trigger.removeEventListener('keydown.dl', this.eventWrapper.debounceKeydown);
this.hook.trigger.removeEventListener('mousedown.dl', this.eventWrapper.debounceKeydown);
- }
+ },
};
export default Filter;
diff --git a/app/assets/javascripts/droplab/plugins/input_setter.js b/app/assets/javascripts/droplab/plugins/input_setter.js
index d01fbc5830d..6cfc738a1e3 100644
--- a/app/assets/javascripts/droplab/plugins/input_setter.js
+++ b/app/assets/javascripts/droplab/plugins/input_setter.js
@@ -36,8 +36,8 @@ const InputSetter = {
const inputAttribute = config.inputAttribute;
if (input.hasAttribute(inputAttribute)) return input.setAttribute(inputAttribute, newValue);
- if (input.tagName === 'INPUT') return input.value = newValue;
- return input.textContent = newValue;
+ if (input.tagName === 'INPUT') return (input.value = newValue);
+ return (input.textContent = newValue);
},
destroy() {
diff --git a/app/assets/javascripts/droplab/utils.js b/app/assets/javascripts/droplab/utils.js
index bfe056a0fcc..5272778ce2d 100644
--- a/app/assets/javascripts/droplab/utils.js
+++ b/app/assets/javascripts/droplab/utils.js
@@ -5,7 +5,12 @@ import { DATA_TRIGGER, DATA_DROPDOWN, TEMPLATE_REGEX } from './constants';
const utils = {
toCamelCase(attr) {
- return this.camelize(attr.split('-').slice(1).join(' '));
+ return this.camelize(
+ attr
+ .split('-')
+ .slice(1)
+ .join(' '),
+ );
},
template(templateString, data) {
@@ -17,9 +22,11 @@ const utils = {
},
camelize(str) {
- return str.replace(/(?:^\w|[A-Z]|\b\w)/g, (letter, index) => {
- return index === 0 ? letter.toLowerCase() : letter.toUpperCase();
- }).replace(/\s+/g, '');
+ return str
+ .replace(/(?:^\w|[A-Z]|\b\w)/g, (letter, index) => {
+ return index === 0 ? letter.toLowerCase() : letter.toUpperCase();
+ })
+ .replace(/\s+/g, '');
},
closest(thisTag, stopTag) {
diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js
index d2778bcdf1c..9987fbcb6a7 100644
--- a/app/assets/javascripts/dropzone_input.js
+++ b/app/assets/javascripts/dropzone_input.js
@@ -136,7 +136,7 @@ export default function dropzoneInput(form) {
// removeAllFiles(true) stops uploading files (if any)
// and remove them from dropzone files queue.
- $cancelButton.on('click', (e) => {
+ $cancelButton.on('click', e => {
e.preventDefault();
e.stopPropagation();
Dropzone.forElement($formDropzone.get(0)).removeAllFiles(true);
@@ -146,8 +146,10 @@ export default function dropzoneInput(form) {
// clear dropzone files queue, change status of failed files to undefined,
// and add that files to the dropzone files queue again.
// addFile() adds file to dropzone files queue and upload it.
- $retryLink.on('click', (e) => {
- const dropzoneInstance = Dropzone.forElement(e.target.closest('.js-main-target-form').querySelector('.div-dropzone'));
+ $retryLink.on('click', e => {
+ const dropzoneInstance = Dropzone.forElement(
+ e.target.closest('.js-main-target-form').querySelector('.div-dropzone'),
+ );
const failedFiles = dropzoneInstance.files;
e.preventDefault();
@@ -156,7 +158,7 @@ export default function dropzoneInput(form) {
// uploading of files that are being uploaded at the moment.
dropzoneInstance.removeAllFiles(true);
- failedFiles.map((failedFile) => {
+ failedFiles.map(failedFile => {
const file = failedFile;
if (file.status === Dropzone.ERROR) {
@@ -168,7 +170,7 @@ export default function dropzoneInput(form) {
});
});
// eslint-disable-next-line consistent-return
- handlePaste = (event) => {
+ handlePaste = event => {
const pasteEvent = event.originalEvent;
if (pasteEvent.clipboardData && pasteEvent.clipboardData.items) {
const image = isImage(pasteEvent);
@@ -182,7 +184,7 @@ export default function dropzoneInput(form) {
}
};
- isImage = (data) => {
+ isImage = data => {
let i = 0;
while (i < data.clipboardData.items.length) {
const item = data.clipboardData.items[i];
@@ -203,8 +205,12 @@ export default function dropzoneInput(form) {
const caretStart = textarea.selectionStart;
const caretEnd = textarea.selectionEnd;
const textEnd = $(child).val().length;
- const beforeSelection = $(child).val().substring(0, caretStart);
- const afterSelection = $(child).val().substring(caretEnd, textEnd);
+ const beforeSelection = $(child)
+ .val()
+ .substring(0, caretStart);
+ const afterSelection = $(child)
+ .val()
+ .substring(caretEnd, textEnd);
$(child).val(beforeSelection + formattedText + afterSelection);
textarea.setSelectionRange(caretStart + formattedText.length, caretEnd + formattedText.length);
textarea.style.height = `${textarea.scrollHeight}px`;
@@ -212,11 +218,11 @@ export default function dropzoneInput(form) {
return formTextarea.trigger('input');
};
- addFileToForm = (path) => {
+ addFileToForm = path => {
$(form).append(`<input type="hidden" name="files[]" value="${_.escape(path)}">`);
};
- getFilename = (e) => {
+ getFilename = e => {
let value;
if (window.clipboardData && window.clipboardData.getData) {
value = window.clipboardData.getData('Text');
@@ -231,7 +237,7 @@ export default function dropzoneInput(form) {
const closeSpinner = () => $uploadingProgressContainer.addClass('hide');
- const showError = (message) => {
+ const showError = message => {
$uploadingErrorContainer.removeClass('hide');
$uploadingErrorMessage.html(message);
};
@@ -252,14 +258,15 @@ export default function dropzoneInput(form) {
showSpinner();
closeAlertMessage();
- axios.post(uploadsPath, formData)
+ axios
+ .post(uploadsPath, formData)
.then(({ data }) => {
const md = data.link.markdown;
insertToTextArea(filename, md);
closeSpinner();
})
- .catch((e) => {
+ .catch(e => {
showError(e.response.data.message);
closeSpinner();
});
@@ -267,7 +274,8 @@ export default function dropzoneInput(form) {
updateAttachingMessage = (files, messageContainer) => {
let attachingMessage;
- const filesCount = files.filter(file => file.status === 'uploading' || file.status === 'queued').length;
+ const filesCount = files.filter(file => file.status === 'uploading' || file.status === 'queued')
+ .length;
// Dinamycally change uploading files text depending on files number in
// dropzone files queue.
@@ -282,7 +290,10 @@ export default function dropzoneInput(form) {
form.find('.markdown-selector').click(function onMarkdownClick(e) {
e.preventDefault();
- $(this).closest('.gfm-form').find('.div-dropzone').click();
+ $(this)
+ .closest('.gfm-form')
+ .find('.div-dropzone')
+ .click();
formTextarea.focus();
});
diff --git a/app/assets/javascripts/due_date_select.js b/app/assets/javascripts/due_date_select.js
index 8abd8bc581a..dbfcf8cc921 100644
--- a/app/assets/javascripts/due_date_select.js
+++ b/app/assets/javascripts/due_date_select.js
@@ -3,8 +3,8 @@ import Pikaday from 'pikaday';
import dateFormat from 'dateformat';
import { __ } from '~/locale';
import axios from './lib/utils/axios_utils';
-import { timeFor } from './lib/utils/datetime_utility';
-import { parsePikadayDate, pikadayToString } from './lib/utils/datefix';
+import { timeFor, parsePikadayDate, pikadayToString } from './lib/utils/datetime_utility';
+import boardsStore from './boards/stores/boards_store';
class DueDateSelect {
constructor({ $dropdown, $loading } = {}) {
@@ -58,7 +58,7 @@ class DueDateSelect {
$dueDateInput.val(calendar.toString(dateText));
if (this.$dropdown.hasClass('js-issue-boards-due-date')) {
- gl.issueBoards.BoardsStore.detail.issue.dueDate = $dueDateInput.val();
+ boardsStore.detail.issue.dueDate = $dueDateInput.val();
this.updateIssueBoardIssue();
} else {
this.saveDueDate(true);
@@ -79,7 +79,7 @@ class DueDateSelect {
calendar.setDate(null);
if (this.$dropdown.hasClass('js-issue-boards-due-date')) {
- gl.issueBoards.BoardsStore.detail.issue.dueDate = '';
+ boardsStore.detail.issue.dueDate = '';
this.updateIssueBoardIssue();
} else {
$(`input[name='${this.fieldName}']`).val('');
@@ -123,7 +123,7 @@ class DueDateSelect {
this.$loading.fadeOut();
};
- gl.issueBoards.BoardsStore.detail.issue
+ boardsStore.detail.issue
.update(this.$dropdown.attr('data-issue-update'))
.then(fadeOutLoader)
.catch(fadeOutLoader);
diff --git a/app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js b/app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js
index e9defb62cf8..c5f9fcf6358 100644
--- a/app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js
+++ b/app/assets/javascripts/emoji/support/is_emoji_unicode_supported.js
@@ -13,9 +13,11 @@ const rainbowCodePoint = 127752; // parseInt('1F308', 16)
function isRainbowFlagEmoji(emojiUnicode) {
const characters = Array.from(emojiUnicode);
// Length 4 because flags are made of 2 characters which are surrogate pairs
- return emojiUnicode.length === 4 &&
+ return (
+ emojiUnicode.length === 4 &&
characters[0].codePointAt(0) === baseFlagCodePoint &&
- characters[1].codePointAt(0) === rainbowCodePoint;
+ characters[1].codePointAt(0) === rainbowCodePoint
+ );
}
// Chrome <57 renders keycaps oddly
@@ -26,22 +28,28 @@ function isKeycapEmoji(emojiUnicode) {
}
// Check for a skin tone variation emoji which aren't always supported
-const tone1 = 127995;// parseInt('1F3FB', 16)
-const tone5 = 127999;// parseInt('1F3FF', 16)
+const tone1 = 127995; // parseInt('1F3FB', 16)
+const tone5 = 127999; // parseInt('1F3FF', 16)
function isSkinToneComboEmoji(emojiUnicode) {
- return emojiUnicode.length > 2 && Array.from(emojiUnicode).some((char) => {
- const cp = char.codePointAt(0);
- return cp >= tone1 && cp <= tone5;
- });
+ return (
+ emojiUnicode.length > 2 &&
+ Array.from(emojiUnicode).some(char => {
+ const cp = char.codePointAt(0);
+ return cp >= tone1 && cp <= tone5;
+ })
+ );
}
// macOS supports most skin tone emoji's but
// doesn't support the skin tone versions of horse racing
-const horseRacingCodePoint = 127943;// parseInt('1F3C7', 16)
+const horseRacingCodePoint = 127943; // parseInt('1F3C7', 16)
function isHorceRacingSkinToneComboEmoji(emojiUnicode) {
const firstCharacter = Array.from(emojiUnicode)[0];
- return firstCharacter && firstCharacter.codePointAt(0) === horseRacingCodePoint &&
- isSkinToneComboEmoji(emojiUnicode);
+ return (
+ firstCharacter &&
+ firstCharacter.codePointAt(0) === horseRacingCodePoint &&
+ isSkinToneComboEmoji(emojiUnicode)
+ );
}
// Check for `family_*`, `kiss_*`, `couple_*`
@@ -52,7 +60,7 @@ const personEndCodePoint = 128105; // parseInt('1F469', 16)
function isPersonZwjEmoji(emojiUnicode) {
let hasPersonEmoji = false;
let hasZwj = false;
- Array.from(emojiUnicode).forEach((character) => {
+ Array.from(emojiUnicode).forEach(character => {
const cp = character.codePointAt(0);
if (cp === zwj) {
hasZwj = true;
@@ -80,10 +88,7 @@ function checkFlagEmojiSupport(unicodeSupportMap, emojiUnicode) {
// in `isEmojiUnicodeSupported` logic
function checkSkinToneModifierSupport(unicodeSupportMap, emojiUnicode) {
const isSkinToneResult = isSkinToneComboEmoji(emojiUnicode);
- return (
- (unicodeSupportMap.skinToneModifier && isSkinToneResult) ||
- !isSkinToneResult
- );
+ return (unicodeSupportMap.skinToneModifier && isSkinToneResult) || !isSkinToneResult;
}
// Helper func so we don't have to run `isHorceRacingSkinToneComboEmoji` twice
@@ -91,8 +96,7 @@ function checkSkinToneModifierSupport(unicodeSupportMap, emojiUnicode) {
function checkHorseRacingSkinToneComboEmojiSupport(unicodeSupportMap, emojiUnicode) {
const isHorseRacingSkinToneResult = isHorceRacingSkinToneComboEmoji(emojiUnicode);
return (
- (unicodeSupportMap.horseRacing && isHorseRacingSkinToneResult) ||
- !isHorseRacingSkinToneResult
+ (unicodeSupportMap.horseRacing && isHorseRacingSkinToneResult) || !isHorseRacingSkinToneResult
);
}
@@ -100,10 +104,7 @@ function checkHorseRacingSkinToneComboEmojiSupport(unicodeSupportMap, emojiUnico
// in `isEmojiUnicodeSupported` logic
function checkPersonEmojiSupport(unicodeSupportMap, emojiUnicode) {
const isPersonZwjResult = isPersonZwjEmoji(emojiUnicode);
- return (
- (unicodeSupportMap.personZwj && isPersonZwjResult) ||
- !isPersonZwjResult
- );
+ return (unicodeSupportMap.personZwj && isPersonZwjResult) || !isPersonZwjResult;
}
// Takes in a support map and determines whether
@@ -111,16 +112,20 @@ function checkPersonEmojiSupport(unicodeSupportMap, emojiUnicode) {
//
// Combines all the edge case tests into a one-stop shop method
function isEmojiUnicodeSupported(unicodeSupportMap = {}, emojiUnicode, unicodeVersion) {
- const isOlderThanChrome57 = unicodeSupportMap.meta && unicodeSupportMap.meta.isChrome &&
+ const isOlderThanChrome57 =
+ unicodeSupportMap.meta &&
+ unicodeSupportMap.meta.isChrome &&
unicodeSupportMap.meta.chromeVersion < 57;
// For comments about each scenario, see the comments above each individual respective function
- return unicodeSupportMap[unicodeVersion] &&
+ return (
+ unicodeSupportMap[unicodeVersion] &&
!(isOlderThanChrome57 && isKeycapEmoji(emojiUnicode)) &&
checkFlagEmojiSupport(unicodeSupportMap, emojiUnicode) &&
checkSkinToneModifierSupport(unicodeSupportMap, emojiUnicode) &&
checkHorseRacingSkinToneComboEmojiSupport(unicodeSupportMap, emojiUnicode) &&
- checkPersonEmojiSupport(unicodeSupportMap, emojiUnicode);
+ checkPersonEmojiSupport(unicodeSupportMap, emojiUnicode)
+ );
}
export {
diff --git a/app/assets/javascripts/environments/components/container.vue b/app/assets/javascripts/environments/components/container.vue
index 9de851c9409..bd402c0eea5 100644
--- a/app/assets/javascripts/environments/components/container.vue
+++ b/app/assets/javascripts/environments/components/container.vue
@@ -1,45 +1,46 @@
<script>
- import tablePagination from '../../vue_shared/components/table_pagination.vue';
- import environmentTable from '../components/environments_table.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
+import tablePagination from '../../vue_shared/components/table_pagination.vue';
+import environmentTable from '../components/environments_table.vue';
- export default {
- components: {
- environmentTable,
- tablePagination,
+export default {
+ components: {
+ environmentTable,
+ tablePagination,
+ GlLoadingIcon,
+ },
+ props: {
+ isLoading: {
+ type: Boolean,
+ required: true,
},
- props: {
- isLoading: {
- type: Boolean,
- required: true,
- },
- environments: {
- type: Array,
- required: true,
- },
- pagination: {
- type: Object,
- required: true,
- },
- canCreateDeployment: {
- type: Boolean,
- required: true,
- },
- canReadEnvironment: {
- type: Boolean,
- required: true,
- },
+ environments: {
+ type: Array,
+ required: true,
},
- methods: {
- onChangePage(page) {
- this.$emit('onChangePage', page);
- },
+ pagination: {
+ type: Object,
+ required: true,
},
- };
+ canCreateDeployment: {
+ type: Boolean,
+ required: true,
+ },
+ canReadEnvironment: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ methods: {
+ onChangePage(page) {
+ this.$emit('onChangePage', page);
+ },
+ },
+};
</script>
<template>
<div class="environments-container">
-
<gl-loading-icon
v-if="isLoading"
:size="3"
@@ -49,10 +50,7 @@
<slot name="emptyState"></slot>
- <div
- v-if="!isLoading && environments.length > 0"
- class="table-holder">
-
+ <div v-if="!isLoading && environments.length > 0" class="table-holder">
<environment-table
:environments="environments"
:can-create-deployment="canCreateDeployment"
diff --git a/app/assets/javascripts/environments/components/empty_state.vue b/app/assets/javascripts/environments/components/empty_state.vue
index cf78f89981e..ca2ac4c3c53 100644
--- a/app/assets/javascripts/environments/components/empty_state.vue
+++ b/app/assets/javascripts/environments/components/empty_state.vue
@@ -1,44 +1,45 @@
<script>
- export default {
- name: 'EnvironmentsEmptyState',
- props: {
- newPath: {
- type: String,
- required: true,
- },
- canCreateEnvironment: {
- type: Boolean,
- required: true,
- },
- helpPath: {
- type: String,
- required: true,
- },
+export default {
+ name: 'EnvironmentsEmptyState',
+ props: {
+ newPath: {
+ type: String,
+ required: true,
},
- };
+ canCreateEnvironment: {
+ type: Boolean,
+ required: true,
+ },
+ helpPath: {
+ type: String,
+ required: true,
+ },
+ },
+};
</script>
<template>
- <div class="blank-state-row">
- <div class="blank-state-center">
- <h2 class="blank-state-title js-blank-state-title">
- {{ s__("Environments|You don't have any environments right now.") }}
- </h2>
+ <div class="empty-state">
+ <div class="text-content">
+ <h4 class="blank-state-title js-blank-state-title">
+ {{ s__("Environments|You don't have any environments right now") }}
+ </h4>
<p class="blank-state-text">
- {{ s__(`Environments|Environments are places where
-code gets deployed, such as staging or production.`) }}
- <br />
- <a :href="helpPath">
- {{ s__("Environments|Read more about environments") }}
- </a>
+ {{
+ s__(`Environments|Environments are places where
+ code gets deployed, such as staging or production.`)
+ }}
+ <a :href="helpPath"> {{ s__('Environments|Read more about environments') }} </a>
</p>
- <a
- v-if="canCreateEnvironment"
- :href="newPath"
- class="btn btn-success js-new-environment-button"
- >
- {{ s__("Environments|New environment") }}
- </a>
+ <div class="text-center">
+ <a
+ v-if="canCreateEnvironment"
+ :href="newPath"
+ class="btn btn-success js-new-environment-button"
+ >
+ {{ s__('Environments|New environment') }}
+ </a>
+ </div>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/environments/components/environment_actions.vue b/app/assets/javascripts/environments/components/environment_actions.vue
index e1f9248bc4c..1f7dab9fbd2 100644
--- a/app/assets/javascripts/environments/components/environment_actions.vue
+++ b/app/assets/javascripts/environments/components/environment_actions.vue
@@ -1,7 +1,10 @@
<script>
+import { s__, sprintf } from '~/locale';
+import { formatTime } from '~/lib/utils/datetime_utility';
import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '../event_hub';
import tooltip from '../../vue_shared/directives/tooltip';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
directives: {
@@ -9,6 +12,7 @@ export default {
},
components: {
Icon,
+ GlLoadingIcon,
},
props: {
actions: {
@@ -28,10 +32,24 @@ export default {
},
},
methods: {
- onClickAction(endpoint) {
+ onClickAction(action) {
+ if (action.scheduledAt) {
+ const confirmationMessage = sprintf(
+ s__(
+ "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes.",
+ ),
+ { jobName: action.name },
+ );
+ // https://gitlab.com/gitlab-org/gitlab-ce/issues/52156
+ // eslint-disable-next-line no-alert
+ if (!window.confirm(confirmationMessage)) {
+ return;
+ }
+ }
+
this.isLoading = true;
- eventHub.$emit('postAction', { endpoint });
+ eventHub.$emit('postAction', { endpoint: action.playPath });
},
isActionDisabled(action) {
@@ -41,47 +59,44 @@ export default {
return !action.playable;
},
+
+ remainingTime(action) {
+ const remainingMilliseconds = new Date(action.scheduledAt).getTime() - Date.now();
+ return formatTime(Math.max(0, remainingMilliseconds));
+ },
},
};
</script>
<template>
- <div
- class="btn-group"
- role="group">
+ <div class="btn-group" role="group">
<button
v-tooltip
:title="title"
:aria-label="title"
:disabled="isLoading"
type="button"
- class="dropdown btn btn-default dropdown-new js-dropdown-play-icon-container"
+ class="dropdown btn btn-default dropdown-new js-environment-actions-dropdown"
data-container="body"
data-toggle="dropdown"
>
<span>
- <icon name="play" />
- <i
- class="fa fa-caret-down"
- aria-hidden="true"
- >
- </i>
+ <icon name="play" /> <icon name="chevron-down" />
<gl-loading-icon v-if="isLoading" />
</span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
- <li
- v-for="(action, i) in actions"
- :key="i">
+ <li v-for="(action, i) in actions" :key="i">
<button
:class="{ disabled: isActionDisabled(action) }"
:disabled="isActionDisabled(action)"
type="button"
- class="js-manual-action-link no-btn btn"
- @click="onClickAction(action.play_path)"
+ class="js-manual-action-link no-btn btn d-flex align-items-center"
+ @click="onClickAction(action);"
>
- <span>
- {{ action.name }}
+ <span class="flex-fill"> {{ action.name }} </span>
+ <span v-if="action.scheduledAt" class="text-secondary">
+ <icon name="clock" /> {{ remainingTime(action) }}
</span>
</button>
</li>
diff --git a/app/assets/javascripts/environments/components/environment_external_url.vue b/app/assets/javascripts/environments/components/environment_external_url.vue
index 7446196de13..af537cfb991 100644
--- a/app/assets/javascripts/environments/components/environment_external_url.vue
+++ b/app/assets/javascripts/environments/components/environment_external_url.vue
@@ -1,7 +1,7 @@
<script>
+import { GlTooltipDirective } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
-import tooltip from '../../vue_shared/directives/tooltip';
-import { s__ } from '../../locale';
+import { s__ } from '~/locale';
/**
* Renders the external url link in environments table.
@@ -11,7 +11,7 @@ export default {
Icon,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
externalUrl: {
@@ -28,12 +28,11 @@ export default {
</script>
<template>
<a
- v-tooltip
+ v-gl-tooltip
:title="title"
:aria-label="title"
:href="externalUrl"
class="btn external-url"
- data-container="body"
target="_blank"
rel="noopener noreferrer nofollow"
>
diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue
index 11e3b781e5a..cd2f46fd07a 100644
--- a/app/assets/javascripts/environments/components/environment_item.vue
+++ b/app/assets/javascripts/environments/components/environment_item.vue
@@ -1,9 +1,10 @@
<script>
import Timeago from 'timeago.js';
import _ from 'underscore';
-import tooltip from '~/vue_shared/directives/tooltip';
+import { GlTooltipDirective } from '@gitlab/ui';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import { humanize } from '~/lib/utils/text_utility';
+import Icon from '~/vue_shared/components/icon.vue';
import ActionsComponent from './environment_actions.vue';
import ExternalUrlComponent from './environment_external_url.vue';
import StopComponent from './environment_stop.vue';
@@ -12,9 +13,10 @@ import TerminalButtonComponent from './environment_terminal_button.vue';
import MonitoringButtonComponent from './environment_monitoring.vue';
import CommitComponent from '../../vue_shared/components/commit.vue';
import eventHub from '../event_hub';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
/**
- * Envrionment Item Component
+ * Environment Item Component
*
* Renders a table row for each environment.
*/
@@ -24,6 +26,7 @@ export default {
components: {
UserAvatarLink,
CommitComponent,
+ Icon,
ActionsComponent,
ExternalUrlComponent,
StopComponent,
@@ -33,7 +36,7 @@ export default {
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
@@ -58,7 +61,7 @@ export default {
computed: {
/**
- * Verifies if `last_deployment` key exists in the current Envrionment.
+ * Verifies if `last_deployment` key exists in the current Environment.
* This key is required to render most of the html - this method works has
* an helper.
*
@@ -72,21 +75,6 @@ export default {
},
/**
- * Verifies is the given environment has manual actions.
- * Used to verify if we should render them or nor.
- *
- * @returns {Boolean|Undefined}
- */
- hasManualActions() {
- return (
- this.model &&
- this.model.last_deployment &&
- this.model.last_deployment.manual_actions &&
- this.model.last_deployment.manual_actions.length > 0
- );
- },
-
- /**
* Checkes whether the environment is protected.
* (`is_protected` currently only set in EE)
*
@@ -152,23 +140,20 @@ export default {
return '';
},
- /**
- * Returns the manual actions with the name parsed.
- *
- * @returns {Array.<Object>|Undefined}
- */
- manualActions() {
- if (this.hasManualActions) {
- return this.model.last_deployment.manual_actions.map(action => {
- const parsedAction = {
- name: humanize(action.name),
- play_path: action.play_path,
- playable: action.playable,
- };
- return parsedAction;
- });
+ actions() {
+ if (!this.model || !this.model.last_deployment || !this.canCreateDeployment) {
+ return [];
}
- return [];
+
+ const { manualActions, scheduledActions } = convertObjectPropsToCamelCase(
+ this.model.last_deployment,
+ { deep: true },
+ );
+ const combinedActions = (manualActions || []).concat(scheduledActions || []);
+ return combinedActions.map(action => ({
+ ...action,
+ name: humanize(action.name),
+ }));
},
/**
@@ -441,13 +426,17 @@ export default {
displayEnvironmentActions() {
return (
- this.hasManualActions ||
+ this.actions.length > 0 ||
this.externalURL ||
this.monitoringUrl ||
this.canStopEnvironment ||
this.canRetry
);
},
+
+ folderIconName() {
+ return this.model.isOpen ? 'chevron-down' : 'chevron-right';
+ },
},
methods: {
@@ -464,64 +453,28 @@ export default {
'folder-row': model.isFolder,
}"
class="gl-responsive-table-row"
- role="row">
+ role="row"
+ >
<div
- class="table-section section-wrap section-15"
+ v-gl-tooltip
+ :title="model.name"
+ class="table-section section-wrap section-15 text-truncate"
role="gridcell"
>
- <div
- v-if="!model.isFolder"
- class="table-mobile-header"
- role="rowheader"
- >
- {{ s__("Environments|Environment") }}
+ <div v-if="!model.isFolder" class="table-mobile-header" role="rowheader">
+ {{ s__('Environments|Environment') }}
</div>
- <span
- v-if="!model.isFolder"
- class="environment-name table-mobile-content">
- <a
- v-tooltip
- :href="environmentPath"
- :title="model.name"
- >
- {{ model.name }}
- </a>
+ <span v-if="!model.isFolder" class="environment-name table-mobile-content">
+ <a class="qa-environment-link" :href="environmentPath"> {{ model.name }} </a>
</span>
- <span
- v-else
- class="folder-name"
- role="button"
- @click="onClickFolder">
-
- <span class="folder-icon">
- <i
- v-show="model.isOpen"
- class="fa fa-caret-down"
- aria-hidden="true"
- >
- </i>
- <i
- v-show="!model.isOpen"
- class="fa fa-caret-right"
- aria-hidden="true"
- >
- </i>
- </span>
-
- <span class="folder-icon">
- <i
- class="fa fa-folder"
- aria-hidden="true">
- </i>
- </span>
-
- <span>
- {{ model.folderName }}
- </span>
-
- <span class="badge badge-pill">
- {{ model.size }}
- </span>
+ <span v-else class="folder-name" role="button" @click="onClickFolder">
+ <icon :name="folderIconName" class="folder-icon" />
+
+ <icon name="folder" class="folder-icon" />
+
+ <span> {{ model.folderName }} </span>
+
+ <span class="badge badge-pill"> {{ model.size }} </span>
</span>
</div>
@@ -529,9 +482,7 @@ export default {
class="table-section section-10 deployment-column d-none d-sm-none d-md-block"
role="gridcell"
>
- <span v-if="shouldRenderDeploymentID">
- {{ deploymentInternalId }}
- </span>
+ <span v-if="shouldRenderDeploymentID"> {{ deploymentInternalId }} </span>
<span v-if="!model.isFolder && deploymentHasUser">
by
@@ -545,61 +496,32 @@ export default {
</span>
</div>
- <div
- class="table-section section-15 d-none d-sm-none d-md-block"
- role="gridcell"
- >
- <a
- v-if="shouldRenderBuildName"
- :href="buildPath"
- class="build-link flex-truncate-parent"
- >
+ <div class="table-section section-15 d-none d-sm-none d-md-block" role="gridcell">
+ <a v-if="shouldRenderBuildName" :href="buildPath" class="build-link flex-truncate-parent">
<span class="flex-truncate-child">{{ buildName }}</span>
</a>
</div>
- <div
- v-if="!model.isFolder"
- class="table-section section-20"
- role="gridcell"
- >
- <div
- role="rowheader"
- class="table-mobile-header"
- >
- {{ s__("Environments|Commit") }}
- </div>
- <div
- v-if="hasLastDeploymentKey"
- class="js-commit-component table-mobile-content">
+ <div v-if="!model.isFolder" class="table-section section-20" role="gridcell">
+ <div role="rowheader" class="table-mobile-header">{{ s__('Environments|Commit') }}</div>
+ <div v-if="hasLastDeploymentKey" class="js-commit-component table-mobile-content">
<commit-component
:tag="commitTag"
:commit-ref="commitRef"
:commit-url="commitUrl"
:short-sha="commitShortSha"
:title="commitTitle"
- :author="commitAuthor"/>
+ :author="commitAuthor"
+ />
</div>
- <div
- v-if="!hasLastDeploymentKey"
- class="commit-title table-mobile-content">
- {{ s__("Environments|No deployments yet") }}
+ <div v-if="!hasLastDeploymentKey" class="commit-title table-mobile-content">
+ {{ s__('Environments|No deployments yet') }}
</div>
</div>
- <div
- v-if="!model.isFolder"
- class="table-section section-10"
- role="gridcell"
- >
- <div
- role="rowheader"
- class="table-mobile-header">
- {{ s__("Environments|Updated") }}
- </div>
- <span
- v-if="canShowDate"
- class="environment-created-date-timeago table-mobile-content">
+ <div v-if="!model.isFolder" class="table-section section-10" role="gridcell">
+ <div role="rowheader" class="table-mobile-header">{{ s__('Environments|Updated') }}</div>
+ <span v-if="canShowDate" class="environment-created-date-timeago table-mobile-content">
{{ createdDate }}
</span>
</div>
@@ -607,12 +529,9 @@ export default {
<div
v-if="!model.isFolder && displayEnvironmentActions"
class="table-section section-30 table-button-footer"
- role="gridcell">
-
- <div
- class="btn-group table-action-buttons"
- role="group">
-
+ role="gridcell"
+ >
+ <div class="btn-group table-action-buttons" role="group">
<external-url-component
v-if="externalURL && canReadEnvironment"
:external-url="externalURL"
@@ -623,10 +542,7 @@ export default {
:monitoring-url="monitoringUrl"
/>
- <actions-component
- v-if="hasManualActions && canCreateDeployment"
- :actions="manualActions"
- />
+ <actions-component v-if="actions.length > 0" :actions="actions" />
<terminal-button-component
v-if="model && model.terminal_path"
@@ -639,10 +555,7 @@ export default {
:retry-url="retryUrl"
/>
- <stop-component
- v-if="canStopEnvironment"
- :environment="model"
- />
+ <stop-component v-if="canStopEnvironment" :environment="model" />
</div>
</div>
</div>
diff --git a/app/assets/javascripts/environments/components/environment_monitoring.vue b/app/assets/javascripts/environments/components/environment_monitoring.vue
index ccc8419ca6d..ae4f07a71cd 100644
--- a/app/assets/javascripts/environments/components/environment_monitoring.vue
+++ b/app/assets/javascripts/environments/components/environment_monitoring.vue
@@ -2,15 +2,16 @@
/**
* Renders the Monitoring (Metrics) link in environments table.
*/
+import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
-import tooltip from '../../vue_shared/directives/tooltip';
export default {
components: {
Icon,
+ GlButton,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
monitoringUrl: {
@@ -26,15 +27,15 @@ export default {
};
</script>
<template>
- <a
- v-tooltip
+ <gl-button
+ v-gl-tooltip
:href="monitoringUrl"
:title="title"
:aria-label="title"
- class="btn monitoring-url d-none d-sm-none d-md-block"
- data-container="body"
+ class="monitoring-url d-none d-sm-none d-md-block"
rel="noopener noreferrer nofollow"
+ variant="default"
>
<icon name="chart" />
- </a>
+ </gl-button>
</template>
diff --git a/app/assets/javascripts/environments/components/environment_rollback.vue b/app/assets/javascripts/environments/components/environment_rollback.vue
index efbf88d0f11..50c86af057c 100644
--- a/app/assets/javascripts/environments/components/environment_rollback.vue
+++ b/app/assets/javascripts/environments/components/environment_rollback.vue
@@ -6,19 +6,18 @@
* Makes a post request when the button is clicked.
*/
import { s__ } from '~/locale';
+import { GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
-import tooltip from '~/vue_shared/directives/tooltip';
import eventHub from '../event_hub';
export default {
components: {
Icon,
+ GlLoadingIcon,
},
-
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
-
props: {
retryUrl: {
type: String,
@@ -38,7 +37,9 @@ export default {
computed: {
title() {
- return this.isLastDeployment ? s__('Environments|Re-deploy to environment') : s__('Environments|Rollback environment');
+ return this.isLastDeployment
+ ? s__('Environments|Re-deploy to environment')
+ : s__('Environments|Rollback environment');
},
},
@@ -53,21 +54,14 @@ export default {
</script>
<template>
<button
- v-tooltip
+ v-gl-tooltip
:disabled="isLoading"
:title="title"
type="button"
class="btn d-none d-sm-none d-md-block"
@click="onClick"
>
-
- <icon
- v-if="isLastDeployment"
- name="repeat" />
- <icon
- v-else
- name="redo"/>
-
+ <icon v-if="isLastDeployment" name="repeat" /> <icon v-else name="redo" />
<gl-loading-icon v-if="isLoading" />
</button>
</template>
diff --git a/app/assets/javascripts/environments/components/environment_stop.vue b/app/assets/javascripts/environments/components/environment_stop.vue
index a814b3405f5..99f50b499d0 100644
--- a/app/assets/javascripts/environments/components/environment_stop.vue
+++ b/app/assets/javascripts/environments/components/environment_stop.vue
@@ -5,49 +5,42 @@
*/
import $ from 'jquery';
+import { GlTooltipDirective } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import { s__ } from '~/locale';
import eventHub from '../event_hub';
import LoadingButton from '../../vue_shared/components/loading_button.vue';
-import tooltip from '../../vue_shared/directives/tooltip';
export default {
components: {
Icon,
LoadingButton,
},
-
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
-
props: {
environment: {
type: Object,
required: true,
},
},
-
data() {
return {
isLoading: false,
};
},
-
computed: {
title() {
return s__('Environments|Stop environment');
},
},
-
mounted() {
eventHub.$on('stopEnvironment', this.onStopEnvironment);
},
-
beforeDestroy() {
eventHub.$off('stopEnvironment', this.onStopEnvironment);
},
-
methods: {
onClick() {
$(this.$el).tooltip('dispose');
@@ -63,16 +56,15 @@ export default {
</script>
<template>
<loading-button
- v-tooltip
+ v-gl-tooltip
:loading="isLoading"
:title="title"
:aria-label="title"
container-class="btn btn-danger d-none d-sm-none d-md-block"
- data-container="body"
data-toggle="modal"
data-target="#stop-environment-modal"
@click="onClick"
>
- <icon name="stop"/>
+ <icon name="stop" />
</loading-button>
</template>
diff --git a/app/assets/javascripts/environments/components/environment_terminal_button.vue b/app/assets/javascripts/environments/components/environment_terminal_button.vue
index 350417e5ad0..83727caad16 100644
--- a/app/assets/javascripts/environments/components/environment_terminal_button.vue
+++ b/app/assets/javascripts/environments/components/environment_terminal_button.vue
@@ -3,15 +3,15 @@
* Renders a terminal button to open a web terminal.
* Used in environments table.
*/
+import { GlTooltipDirective } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
-import tooltip from '../../vue_shared/directives/tooltip';
export default {
components: {
Icon,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
terminalPath: {
@@ -29,12 +29,11 @@ export default {
</script>
<template>
<a
- v-tooltip
+ v-gl-tooltip
:title="title"
:aria-label="title"
:href="terminalPath"
class="btn terminal-button d-none d-sm-none d-md-block"
- data-container="body"
>
<icon name="terminal" />
</a>
diff --git a/app/assets/javascripts/environments/components/environments_app.vue b/app/assets/javascripts/environments/components/environments_app.vue
index e2ecf426e64..ae9459a2482 100644
--- a/app/assets/javascripts/environments/components/environments_app.vue
+++ b/app/assets/javascripts/environments/components/environments_app.vue
@@ -1,115 +1,103 @@
<script>
- import Flash from '../../flash';
- import { s__ } from '../../locale';
- import emptyState from './empty_state.vue';
- import eventHub from '../event_hub';
- import environmentsMixin from '../mixins/environments_mixin';
- import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin';
- import StopEnvironmentModal from './stop_environment_modal.vue';
+import Flash from '../../flash';
+import { s__ } from '../../locale';
+import emptyState from './empty_state.vue';
+import eventHub from '../event_hub';
+import environmentsMixin from '../mixins/environments_mixin';
+import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin';
+import StopEnvironmentModal from './stop_environment_modal.vue';
- export default {
- components: {
- emptyState,
- StopEnvironmentModal,
- },
+export default {
+ components: {
+ emptyState,
+ StopEnvironmentModal,
+ },
- mixins: [
- CIPaginationMixin,
- environmentsMixin,
- ],
+ mixins: [CIPaginationMixin, environmentsMixin],
- props: {
- endpoint: {
- type: String,
- required: true,
- },
- canCreateEnvironment: {
- type: Boolean,
- required: true,
- },
- canCreateDeployment: {
- type: Boolean,
- required: true,
- },
- canReadEnvironment: {
- type: Boolean,
- required: true,
- },
- cssContainerClass: {
- type: String,
- required: true,
- },
- newEnvironmentPath: {
- type: String,
- required: true,
- },
- helpPagePath: {
- type: String,
- required: true,
- },
+ props: {
+ endpoint: {
+ type: String,
+ required: true,
},
-
- created() {
- eventHub.$on('toggleFolder', this.toggleFolder);
+ canCreateEnvironment: {
+ type: Boolean,
+ required: true,
},
-
- beforeDestroy() {
- eventHub.$off('toggleFolder');
+ canCreateDeployment: {
+ type: Boolean,
+ required: true,
+ },
+ canReadEnvironment: {
+ type: Boolean,
+ required: true,
+ },
+ cssContainerClass: {
+ type: String,
+ required: true,
+ },
+ newEnvironmentPath: {
+ type: String,
+ required: true,
},
+ helpPagePath: {
+ type: String,
+ required: true,
+ },
+ },
+
+ created() {
+ eventHub.$on('toggleFolder', this.toggleFolder);
+ },
+
+ beforeDestroy() {
+ eventHub.$off('toggleFolder');
+ },
- methods: {
- toggleFolder(folder) {
- this.store.toggleFolder(folder);
+ methods: {
+ toggleFolder(folder) {
+ this.store.toggleFolder(folder);
- if (!folder.isOpen) {
- this.fetchChildEnvironments(folder, true);
- }
- },
+ if (!folder.isOpen) {
+ this.fetchChildEnvironments(folder, true);
+ }
+ },
- fetchChildEnvironments(folder, showLoader = false) {
- this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', showLoader);
+ fetchChildEnvironments(folder, showLoader = false) {
+ this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', showLoader);
- this.service.getFolderContent(folder.folder_path)
- .then(response => this.store.setfolderContent(folder, response.data.environments))
- .then(() => this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', false))
- .catch(() => {
- Flash(s__('Environments|An error occurred while fetching the environments.'));
- this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', false);
- });
- },
+ this.service
+ .getFolderContent(folder.folder_path)
+ .then(response => this.store.setfolderContent(folder, response.data.environments))
+ .then(() => this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', false))
+ .catch(() => {
+ Flash(s__('Environments|An error occurred while fetching the environments.'));
+ this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', false);
+ });
+ },
- successCallback(resp) {
- this.saveData(resp);
+ successCallback(resp) {
+ this.saveData(resp);
- // We need to verify if any folder is open to also update it
- const openFolders = this.store.getOpenFolders();
- if (openFolders.length) {
- openFolders.forEach(folder => this.fetchChildEnvironments(folder));
- }
- },
+ // We need to verify if any folder is open to also update it
+ const openFolders = this.store.getOpenFolders();
+ if (openFolders.length) {
+ openFolders.forEach(folder => this.fetchChildEnvironments(folder));
+ }
},
- };
+ },
+};
</script>
<template>
<div :class="cssContainerClass">
<stop-environment-modal :environment="environmentInStopModal" />
<div class="top-area">
- <tabs
- :tabs="tabs"
- scope="environments"
- @onChangeTab="onChangeTab"
- />
+ <tabs :tabs="tabs" scope="environments" @onChangeTab="onChangeTab" />
- <div
- v-if="canCreateEnvironment && !isLoading"
- class="nav-controls"
- >
- <a
- :href="newEnvironmentPath"
- class="btn btn-success"
- >
- {{ s__("Environments|New environment") }}
+ <div v-if="canCreateEnvironment && !isLoading" class="nav-controls">
+ <a :href="newEnvironmentPath" class="btn btn-success">
+ {{ s__('Environments|New environment') }}
</a>
</div>
</div>
diff --git a/app/assets/javascripts/environments/components/environments_table.vue b/app/assets/javascripts/environments/components/environments_table.vue
index a9d9d768c06..5164d87c5fa 100644
--- a/app/assets/javascripts/environments/components/environments_table.vue
+++ b/app/assets/javascripts/environments/components/environments_table.vue
@@ -2,11 +2,13 @@
/**
* Render environments table.
*/
+import { GlLoadingIcon } from '@gitlab/ui';
import environmentItem from './environment_item.vue';
export default {
components: {
environmentItem,
+ GlLoadingIcon,
},
props: {
@@ -39,62 +41,35 @@ export default {
};
</script>
<template>
- <div
- class="ci-table"
- role="grid"
- >
- <div
- class="gl-responsive-table-row table-row-header"
- role="row"
- >
- <div
- class="table-section section-15 environments-name"
- role="columnheader"
- >
- {{ s__("Environments|Environment") }}
+ <div class="ci-table" role="grid">
+ <div class="gl-responsive-table-row table-row-header" role="row">
+ <div class="table-section section-15 environments-name" role="columnheader">
+ {{ s__('Environments|Environment') }}
</div>
- <div
- class="table-section section-10 environments-deploy"
- role="columnheader"
- >
- {{ s__("Environments|Deployment") }}
+ <div class="table-section section-10 environments-deploy" role="columnheader">
+ {{ s__('Environments|Deployment') }}
</div>
- <div
- class="table-section section-15 environments-build"
- role="columnheader"
- >
- {{ s__("Environments|Job") }}
+ <div class="table-section section-15 environments-build" role="columnheader">
+ {{ s__('Environments|Job') }}
</div>
- <div
- class="table-section section-20 environments-commit"
- role="columnheader"
- >
- {{ s__("Environments|Commit") }}
+ <div class="table-section section-20 environments-commit" role="columnheader">
+ {{ s__('Environments|Commit') }}
</div>
- <div
- class="table-section section-10 environments-date"
- role="columnheader"
- >
- {{ s__("Environments|Updated") }}
+ <div class="table-section section-10 environments-date" role="columnheader">
+ {{ s__('Environments|Updated') }}
</div>
</div>
- <template
- v-for="(model, i) in environments"
- :model="model">
+ <template v-for="(model, i) in environments" :model="model">
<div
is="environment-item"
+ :key="`environment-item-${i}`"
:model="model"
:can-create-deployment="canCreateDeployment"
:can-read-environment="canReadEnvironment"
- :key="`environment-item-${i}`"
/>
- <template
- v-if="shouldRenderFolderContent(model)"
- >
- <div
- v-if="model.isLoadingFolderContent"
- :key="`loading-item-${i}`">
+ <template v-if="shouldRenderFolderContent(model)">
+ <div v-if="model.isLoadingFolderContent" :key="`loading-item-${i}`">
<gl-loading-icon :size="2" />
</div>
@@ -102,19 +77,16 @@ export default {
<div
is="environment-item"
v-for="(children, index) in model.children"
+ :key="`env-item-${i}-${index}`"
:model="children"
:can-create-deployment="canCreateDeployment"
:can-read-environment="canReadEnvironment"
- :key="`env-item-${i}-${index}`"
/>
<div :key="`sub-div-${i}`">
<div class="text-center prepend-top-10">
- <a
- :href="folderUrl(model)"
- class="btn btn-default"
- >
- {{ s__("Environments|Show all") }}
+ <a :href="folderUrl(model)" class="btn btn-default">
+ {{ s__('Environments|Show all') }}
</a>
</div>
</div>
diff --git a/app/assets/javascripts/environments/components/stop_environment_modal.vue b/app/assets/javascripts/environments/components/stop_environment_modal.vue
index 657cc8cd1aa..c78d86e9b97 100644
--- a/app/assets/javascripts/environments/components/stop_environment_modal.vue
+++ b/app/assets/javascripts/environments/components/stop_environment_modal.vue
@@ -1,7 +1,7 @@
<script>
+import { GlTooltipDirective } from '@gitlab/ui';
import GlModal from '~/vue_shared/components/gl_modal.vue';
import { s__, sprintf } from '~/locale';
-import tooltip from '~/vue_shared/directives/tooltip';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import eventHub from '../event_hub';
@@ -15,7 +15,7 @@ export default {
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
@@ -62,31 +62,25 @@ export default {
@submit="onSubmit"
>
<template slot="header">
- <h4
- class="modal-title d-flex mw-100"
- >
+ <h4 class="modal-title d-flex mw-100">
Stopping
- <span
- v-tooltip
- :title="environment.name"
- class="text-truncate ml-1 mr-1 flex-fill"
- >{{ environment.name }}</span>
+ <span v-gl-tooltip :title="environment.name" class="text-truncate ml-1 mr-1 flex-fill">{{
+ environment.name
+ }}</span>
?
</h4>
</template>
<p>{{ s__('Environments|Are you sure you want to stop this environment?') }}</p>
- <div
- v-if="!environment.has_stop_action"
- class="warning_message"
- >
+ <div v-if="!environment.has_stop_action" class="warning_message">
<p v-html="noStopActionMessage"></p>
<a
href="https://docs.gitlab.com/ee/ci/environments.html#stopping-an-environment"
target="_blank"
rel="noopener noreferrer"
- >{{ s__('Environments|Learn more about stopping environments') }}</a>
+ >{{ s__('Environments|Learn more about stopping environments') }}</a
+ >
</div>
</gl-modal>
</template>
diff --git a/app/assets/javascripts/environments/folder/environments_folder_bundle.js b/app/assets/javascripts/environments/folder/environments_folder_bundle.js
index de0fbdb2e91..3cf6e4ad14d 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_bundle.js
+++ b/app/assets/javascripts/environments/folder/environments_folder_bundle.js
@@ -1,35 +1,36 @@
import Vue from 'vue';
import environmentsFolderApp from './environments_folder_view.vue';
-import { convertPermissionToBoolean } from '../../lib/utils/common_utils';
+import { parseBoolean } from '../../lib/utils/common_utils';
import Translate from '../../vue_shared/translate';
Vue.use(Translate);
-export default () => new Vue({
- el: '#environments-folder-list-view',
- components: {
- environmentsFolderApp,
- },
- data() {
- const environmentsData = document.querySelector(this.$options.el).dataset;
+export default () =>
+ new Vue({
+ el: '#environments-folder-list-view',
+ components: {
+ environmentsFolderApp,
+ },
+ data() {
+ const environmentsData = document.querySelector(this.$options.el).dataset;
- return {
- endpoint: environmentsData.endpoint,
- folderName: environmentsData.folderName,
- cssContainerClass: environmentsData.cssClass,
- canCreateDeployment: convertPermissionToBoolean(environmentsData.canCreateDeployment),
- canReadEnvironment: convertPermissionToBoolean(environmentsData.canReadEnvironment),
- };
- },
- render(createElement) {
- return createElement('environments-folder-app', {
- props: {
- endpoint: this.endpoint,
- folderName: this.folderName,
- cssContainerClass: this.cssContainerClass,
- canCreateDeployment: this.canCreateDeployment,
- canReadEnvironment: this.canReadEnvironment,
- },
- });
- },
-});
+ return {
+ endpoint: environmentsData.endpoint,
+ folderName: environmentsData.folderName,
+ cssContainerClass: environmentsData.cssClass,
+ canCreateDeployment: parseBoolean(environmentsData.canCreateDeployment),
+ canReadEnvironment: parseBoolean(environmentsData.canReadEnvironment),
+ };
+ },
+ render(createElement) {
+ return createElement('environments-folder-app', {
+ props: {
+ endpoint: this.endpoint,
+ folderName: this.folderName,
+ cssContainerClass: this.cssContainerClass,
+ canCreateDeployment: this.canCreateDeployment,
+ canReadEnvironment: this.canReadEnvironment,
+ },
+ });
+ },
+ });
diff --git a/app/assets/javascripts/environments/folder/environments_folder_view.vue b/app/assets/javascripts/environments/folder/environments_folder_view.vue
index e69bfa0b2cc..d6f0b6115a6 100644
--- a/app/assets/javascripts/environments/folder/environments_folder_view.vue
+++ b/app/assets/javascripts/environments/folder/environments_folder_view.vue
@@ -1,65 +1,54 @@
<script>
- import environmentsMixin from '../mixins/environments_mixin';
- import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin';
- import StopEnvironmentModal from '../components/stop_environment_modal.vue';
+import environmentsMixin from '../mixins/environments_mixin';
+import CIPaginationMixin from '../../vue_shared/mixins/ci_pagination_api_mixin';
+import StopEnvironmentModal from '../components/stop_environment_modal.vue';
- export default {
- components: {
- StopEnvironmentModal,
- },
+export default {
+ components: {
+ StopEnvironmentModal,
+ },
- mixins: [
- environmentsMixin,
- CIPaginationMixin,
- ],
+ mixins: [environmentsMixin, CIPaginationMixin],
- props: {
- endpoint: {
- type: String,
- required: true,
- },
- folderName: {
- type: String,
- required: true,
- },
- cssContainerClass: {
- type: String,
- required: true,
- },
- canCreateDeployment: {
- type: Boolean,
- required: true,
- },
- canReadEnvironment: {
- type: Boolean,
- required: true,
- },
+ props: {
+ endpoint: {
+ type: String,
+ required: true,
+ },
+ folderName: {
+ type: String,
+ required: true,
+ },
+ cssContainerClass: {
+ type: String,
+ required: true,
},
- methods: {
- successCallback(resp) {
- this.saveData(resp);
- },
+ canCreateDeployment: {
+ type: Boolean,
+ required: true,
},
- };
+ canReadEnvironment: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ methods: {
+ successCallback(resp) {
+ this.saveData(resp);
+ },
+ },
+};
</script>
<template>
<div :class="cssContainerClass">
<stop-environment-modal :environment="environmentInStopModal" />
- <div
- v-if="!isLoading"
- class="top-area"
- >
-
+ <div v-if="!isLoading" class="top-area">
<h4 class="js-folder-name environments-folder-name">
- {{ s__("Environments|Environments") }} / <b>{{ folderName }}</b>
+ {{ s__('Environments|Environments') }} / <b>{{ folderName }}</b>
</h4>
- <tabs
- :tabs="tabs"
- scope="environments"
- @onChangeTab="onChangeTab"
- />
+ <tabs :tabs="tabs" scope="environments" @onChangeTab="onChangeTab" />
</div>
<container
diff --git a/app/assets/javascripts/environments/index.js b/app/assets/javascripts/environments/index.js
index afc4aba6554..d366e7550b7 100644
--- a/app/assets/javascripts/environments/index.js
+++ b/app/assets/javascripts/environments/index.js
@@ -1,39 +1,40 @@
import Vue from 'vue';
import environmentsComponent from './components/environments_app.vue';
-import { convertPermissionToBoolean } from '../lib/utils/common_utils';
+import { parseBoolean } from '../lib/utils/common_utils';
import Translate from '../vue_shared/translate';
Vue.use(Translate);
-export default () => new Vue({
- el: '#environments-list-view',
- components: {
- environmentsComponent,
- },
- data() {
- const environmentsData = document.querySelector(this.$options.el).dataset;
+export default () =>
+ new Vue({
+ el: '#environments-list-view',
+ components: {
+ environmentsComponent,
+ },
+ data() {
+ const environmentsData = document.querySelector(this.$options.el).dataset;
- return {
- endpoint: environmentsData.environmentsDataEndpoint,
- newEnvironmentPath: environmentsData.newEnvironmentPath,
- helpPagePath: environmentsData.helpPagePath,
- cssContainerClass: environmentsData.cssClass,
- canCreateEnvironment: convertPermissionToBoolean(environmentsData.canCreateEnvironment),
- canCreateDeployment: convertPermissionToBoolean(environmentsData.canCreateDeployment),
- canReadEnvironment: convertPermissionToBoolean(environmentsData.canReadEnvironment),
- };
- },
- render(createElement) {
- return createElement('environments-component', {
- props: {
- endpoint: this.endpoint,
- newEnvironmentPath: this.newEnvironmentPath,
- helpPagePath: this.helpPagePath,
- cssContainerClass: this.cssContainerClass,
- canCreateEnvironment: this.canCreateEnvironment,
- canCreateDeployment: this.canCreateDeployment,
- canReadEnvironment: this.canReadEnvironment,
- },
- });
- },
-});
+ return {
+ endpoint: environmentsData.environmentsDataEndpoint,
+ newEnvironmentPath: environmentsData.newEnvironmentPath,
+ helpPagePath: environmentsData.helpPagePath,
+ cssContainerClass: environmentsData.cssClass,
+ canCreateEnvironment: parseBoolean(environmentsData.canCreateEnvironment),
+ canCreateDeployment: parseBoolean(environmentsData.canCreateDeployment),
+ canReadEnvironment: parseBoolean(environmentsData.canReadEnvironment),
+ };
+ },
+ render(createElement) {
+ return createElement('environments-component', {
+ props: {
+ endpoint: this.endpoint,
+ newEnvironmentPath: this.newEnvironmentPath,
+ helpPagePath: this.helpPagePath,
+ cssContainerClass: this.cssContainerClass,
+ canCreateEnvironment: this.canCreateEnvironment,
+ canCreateDeployment: this.canCreateDeployment,
+ canReadEnvironment: this.canReadEnvironment,
+ },
+ });
+ },
+ });
diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js
index d71964612c5..96dc1f07cb9 100644
--- a/app/assets/javascripts/environments/mixins/environments_mixin.js
+++ b/app/assets/javascripts/environments/mixins/environments_mixin.js
@@ -4,9 +4,7 @@
import _ from 'underscore';
import Visibility from 'visibilityjs';
import Poll from '../../lib/utils/poll';
-import {
- getParameterByName,
-} from '../../lib/utils/common_utils';
+import { getParameterByName } from '../../lib/utils/common_utils';
import { s__ } from '../../locale';
import Flash from '../../flash';
import eventHub from '../event_hub';
@@ -19,7 +17,6 @@ import tabs from '../../vue_shared/components/navigation_tabs.vue';
import container from '../components/container.vue';
export default {
-
components: {
environmentTable,
container,
@@ -65,7 +62,8 @@ export default {
updateContent(parameters) {
this.updateInternalState(parameters);
// fetch new data
- return this.service.fetchEnvironments(this.requestData)
+ return this.service
+ .fetchEnvironments(this.requestData)
.then(response => this.successCallback(response))
.then(() => {
// restart polling
@@ -88,7 +86,8 @@ export default {
if (!this.isMakingRequest) {
this.isLoading = true;
- this.service.postAction(endpoint)
+ this.service
+ .postAction(endpoint)
.then(() => this.fetchEnvironments())
.catch(() => {
this.isLoading = false;
@@ -100,7 +99,8 @@ export default {
fetchEnvironments() {
this.isLoading = true;
- return this.service.fetchEnvironments(this.requestData)
+ return this.service
+ .fetchEnvironments(this.requestData)
.then(this.successCallback)
.catch(this.errorCallback);
},
@@ -111,7 +111,9 @@ export default {
stopEnvironment(environment) {
const endpoint = environment.stop_path;
- const errorMessage = s__('Environments|An error occurred while stopping the environment, please try again');
+ const errorMessage = s__(
+ 'Environments|An error occurred while stopping the environment, please try again',
+ );
this.postAction({ endpoint, errorMessage });
},
},
@@ -149,7 +151,7 @@ export default {
data: this.requestData,
successCallback: this.successCallback,
errorCallback: this.errorCallback,
- notificationCallback: (isMakingRequest) => {
+ notificationCallback: isMakingRequest => {
this.isMakingRequest = isMakingRequest;
},
});
diff --git a/app/assets/javascripts/environments/stores/environments_store.js b/app/assets/javascripts/environments/stores/environments_store.js
index 5ce9225a4bb..5808a2d4afa 100644
--- a/app/assets/javascripts/environments/stores/environments_store.js
+++ b/app/assets/javascripts/environments/stores/environments_store.js
@@ -34,14 +34,14 @@ export default class EnvironmentsStore {
* @returns {Array}
*/
storeEnvironments(environments = []) {
- const filteredEnvironments = environments.map((env) => {
- const oldEnvironmentState = this.state.environments
- .find((element) => {
- if (env.latest) {
- return element.id === env.latest.id;
- }
- return element.id === env.id;
- }) || {};
+ const filteredEnvironments = environments.map(env => {
+ const oldEnvironmentState =
+ this.state.environments.find(element => {
+ if (env.latest) {
+ return element.id === env.latest.id;
+ }
+ return element.id === env.id;
+ }) || {};
let filtered = {};
@@ -101,11 +101,11 @@ export default class EnvironmentsStore {
}
/**
- * Toggles folder open property for the given folder.
- *
- * @param {Object} folder
- * @return {Array}
- */
+ * Toggles folder open property for the given folder.
+ *
+ * @param {Object} folder
+ * @return {Array}
+ */
toggleFolder(folder) {
return this.updateEnvironmentProp(folder, 'isOpen', !folder.isOpen);
}
@@ -119,7 +119,7 @@ export default class EnvironmentsStore {
* @return {Object}
*/
setfolderContent(folder, environments) {
- const updatedEnvironments = environments.map((env) => {
+ const updatedEnvironments = environments.map(env => {
let updated = env;
if (env.latest) {
@@ -148,7 +148,7 @@ export default class EnvironmentsStore {
updateEnvironmentProp(environment, prop, newValue) {
const { environments } = this.state;
- const updatedEnvironments = environments.map((env) => {
+ const updatedEnvironments = environments.map(env => {
const updateEnv = Object.assign({}, env);
if (env.id === environment.id) {
updateEnv[prop] = newValue;
diff --git a/app/assets/javascripts/experimental_flags.js b/app/assets/javascripts/experimental_flags.js
index 1d60847147b..42b3fb8c6da 100644
--- a/app/assets/javascripts/experimental_flags.js
+++ b/app/assets/javascripts/experimental_flags.js
@@ -2,7 +2,7 @@ import $ from 'jquery';
import Cookies from 'js-cookie';
export default () => {
- $('.js-experiment-feature-toggle').on('change', (e) => {
+ $('.js-experiment-feature-toggle').on('change', e => {
const el = e.target;
Cookies.set(el.name, el.value, {
diff --git a/app/assets/javascripts/feature_highlight/feature_highlight.js b/app/assets/javascripts/feature_highlight/feature_highlight.js
index 03dfa942d69..173fe7c69de 100644
--- a/app/assets/javascripts/feature_highlight/feature_highlight.js
+++ b/app/assets/javascripts/feature_highlight/feature_highlight.js
@@ -1,13 +1,6 @@
import $ from 'jquery';
-import {
- getSelector,
- inserted,
-} from './feature_highlight_helper';
-import {
- togglePopover,
- mouseenter,
- debouncedMouseleave,
-} from '../shared/popover';
+import { getSelector, inserted } from './feature_highlight_helper';
+import { togglePopover, mouseenter, debouncedMouseleave } from '../shared/popover';
export function setupFeatureHighlightPopover(id, debounceTimeout = 300) {
const $selector = $(getSelector(id));
@@ -41,8 +34,9 @@ export function setupFeatureHighlightPopover(id, debounceTimeout = 300) {
export function findHighestPriorityFeature() {
let priorityFeature;
- const sortedFeatureEls = [].slice.call(document.querySelectorAll('.js-feature-highlight')).sort((a, b) =>
- (a.dataset.highlightPriority || 0) < (b.dataset.highlightPriority || 0));
+ const sortedFeatureEls = [].slice
+ .call(document.querySelectorAll('.js-feature-highlight'))
+ .sort((a, b) => (a.dataset.highlightPriority || 0) < (b.dataset.highlightPriority || 0));
const [priorityFeatureEl] = sortedFeatureEls;
if (priorityFeatureEl) {
diff --git a/app/assets/javascripts/feature_highlight/feature_highlight_helper.js b/app/assets/javascripts/feature_highlight/feature_highlight_helper.js
index d5b97ebb264..fd9433b625c 100644
--- a/app/assets/javascripts/feature_highlight/feature_highlight_helper.js
+++ b/app/assets/javascripts/feature_highlight/feature_highlight_helper.js
@@ -8,10 +8,17 @@ import { togglePopover } from '../shared/popover';
export const getSelector = highlightId => `.js-feature-highlight[data-highlight=${highlightId}]`;
export function dismiss(highlightId) {
- axios.post(this.attr('data-dismiss-endpoint'), {
- feature_name: highlightId,
- })
- .catch(() => Flash(__('An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again.')));
+ axios
+ .post(this.attr('data-dismiss-endpoint'), {
+ feature_name: highlightId,
+ })
+ .catch(() =>
+ Flash(
+ __(
+ 'An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again.',
+ ),
+ ),
+ );
togglePopover.call(this, false);
this.hide();
@@ -23,8 +30,7 @@ export function inserted() {
const $popover = $(this);
const dismissWrapper = dismiss.bind($popover, highlightId);
- $(`#${popoverId} .dismiss-feature-highlight`)
- .on('click', dismissWrapper);
+ $(`#${popoverId} .dismiss-feature-highlight`).on('click', dismissWrapper);
const lazyImg = $(`#${popoverId} .feature-highlight-illustration`)[0];
if (lazyImg) {
diff --git a/app/assets/javascripts/files_comment_button.js b/app/assets/javascripts/files_comment_button.js
index 6a4874e1ab8..aad5647c045 100644
--- a/app/assets/javascripts/files_comment_button.js
+++ b/app/assets/javascripts/files_comment_button.js
@@ -1,5 +1,5 @@
/* Developer beware! Do not add logic to showButton or hideButton
- * that will force a reflow. Doing so will create a signficant performance
+ * that will force a reflow. Doing so will create a significant performance
* bottleneck for pages with large diffs. For a comprehensive list of what
* causes reflows, visit https://gist.github.com/paulirish/5d52fb081b3570c81e3a
*/
@@ -25,13 +25,15 @@ export default {
if (!this.userCanCreateNote) {
// data-can-create-note is an empty string when true, otherwise undefined
- this.userCanCreateNote = $diffFile.closest(DIFF_CONTAINER_SELECTOR).data('canCreateNote') === '';
+ this.userCanCreateNote =
+ $diffFile.closest(DIFF_CONTAINER_SELECTOR).data('canCreateNote') === '';
}
this.isParallelView = Cookies.get('diff_view') === 'parallel';
if (this.userCanCreateNote) {
- $diffFile.on('mouseover', LINE_COLUMN_CLASSES, e => this.showButton(this.isParallelView, e))
+ $diffFile
+ .on('mouseover', LINE_COLUMN_CLASSES, e => this.showButton(this.isParallelView, e))
.on('mouseleave', LINE_COLUMN_CLASSES, e => this.hideButton(this.isParallelView, e));
}
},
@@ -64,9 +66,11 @@ export default {
},
validateButtonParent(buttonParentElement) {
- return !buttonParentElement.classList.contains(EMPTY_CELL_CLASS) &&
+ return (
+ !buttonParentElement.classList.contains(EMPTY_CELL_CLASS) &&
!buttonParentElement.classList.contains(UNFOLDABLE_LINE_CLASS) &&
!buttonParentElement.classList.contains(NO_COMMENT_CLASS) &&
- !buttonParentElement.parentNode.classList.contains(DIFF_EXPANDED_CLASS);
+ !buttonParentElement.parentNode.classList.contains(DIFF_EXPANDED_CLASS)
+ );
},
};
diff --git a/app/assets/javascripts/filterable_list.js b/app/assets/javascripts/filterable_list.js
index b17ba3c21db..64b09c8b62c 100644
--- a/app/assets/javascripts/filterable_list.js
+++ b/app/assets/javascripts/filterable_list.js
@@ -65,12 +65,15 @@ export default class FilterableList {
this.isBusy = true;
- return axios.get(this.getFilterEndpoint(), {
- params,
- }).then((res) => {
- this.onFilterSuccess(res, params);
- this.onFilterComplete();
- }).catch(() => this.onFilterComplete());
+ return axios
+ .get(this.getFilterEndpoint(), {
+ params,
+ })
+ .then(res => {
+ this.onFilterSuccess(res, params);
+ this.onFilterComplete();
+ })
+ .catch(() => this.onFilterComplete());
}
onFilterSuccess(response, queryData) {
@@ -81,9 +84,13 @@ export default class FilterableList {
// Change url so if user reload a page - search results are saved
const currentPath = this.getPagePath(queryData);
- return window.history.replaceState({
- page: currentPath,
- }, document.title, currentPath);
+ return window.history.replaceState(
+ {
+ page: currentPath,
+ },
+ document.title,
+ currentPath,
+ );
}
onFilterComplete() {
diff --git a/app/assets/javascripts/filtered_search/admin_runners_filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/admin_runners_filtered_search_token_keys.js
index b4588cc1318..934375023ba 100644
--- a/app/assets/javascripts/filtered_search/admin_runners_filtered_search_token_keys.js
+++ b/app/assets/javascripts/filtered_search/admin_runners_filtered_search_token_keys.js
@@ -1,13 +1,23 @@
import FilteredSearchTokenKeys from './filtered_search_token_keys';
-const tokenKeys = [{
- key: 'status',
- type: 'string',
- param: 'status',
- symbol: '',
- icon: 'messages',
- tag: 'status',
-}];
+const tokenKeys = [
+ {
+ key: 'status',
+ type: 'string',
+ param: 'status',
+ symbol: '',
+ icon: 'messages',
+ tag: 'status',
+ },
+ {
+ key: 'type',
+ type: 'string',
+ param: 'type',
+ symbol: '',
+ icon: 'cube',
+ tag: 'type',
+ },
+];
const AdminRunnersFilteredSearchTokenKeys = new FilteredSearchTokenKeys(tokenKeys);
diff --git a/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue b/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue
index a8eb8d94be3..6b1a934d3fe 100644
--- a/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue
+++ b/app/assets/javascripts/filtered_search/components/recent_searches_dropdown_content.vue
@@ -21,9 +21,11 @@ export default {
},
computed: {
processedItems() {
- return this.items.map((item) => {
- const { tokens, searchToken }
- = FilteredSearchTokenizer.processTokens(item, this.allowedKeys);
+ return this.items.map(item => {
+ const { tokens, searchToken } = FilteredSearchTokenizer.processTokens(
+ item,
+ this.allowedKeys,
+ );
const resultantTokens = tokens.map(token => ({
prefix: `${token.key}:`,
@@ -56,24 +58,20 @@ export default {
</script>
<template>
<div>
- <div
- v-if="!isLocalStorageAvailable"
- class="dropdown-info-note">
+ <div v-if="!isLocalStorageAvailable" class="dropdown-info-note">
This feature requires local storage to be enabled
</div>
<ul v-else-if="hasItems">
- <li
- v-for="(item, index) in processedItems"
- :key="`processed-items-${index}`"
- >
+ <li v-for="(item, index) in processedItems" :key="`processed-items-${index}`">
<button
type="button"
class="filtered-search-history-dropdown-item"
- @click="onItemActivated(item.text)">
+ @click="onItemActivated(item.text);"
+ >
<span>
<span
- v-for="(token, index) in item.tokens"
- :key="`dropdown-token-${index}`"
+ v-for="(token, tokenIndex) in item.tokens"
+ :key="`dropdown-token-${tokenIndex}`"
class="filtered-search-history-dropdown-token"
>
<span class="name">{{ token.prefix }}</span>
@@ -90,15 +88,12 @@ export default {
<button
type="button"
class="filtered-search-history-clear-button"
- @click="onRequestClearRecentSearches($event)">
+ @click="onRequestClearRecentSearches($event);"
+ >
Clear recent searches
</button>
</li>
</ul>
- <div
- v-else
- class="dropdown-info-note">
- You don't have any recent searches
- </div>
+ <div v-else class="dropdown-info-note">You don't have any recent searches</div>
</div>
</template>
diff --git a/app/assets/javascripts/filtered_search/dropdown_emoji.js b/app/assets/javascripts/filtered_search/dropdown_emoji.js
index 5ddd0e5e690..d9a4d06b549 100644
--- a/app/assets/javascripts/filtered_search/dropdown_emoji.js
+++ b/app/assets/javascripts/filtered_search/dropdown_emoji.js
@@ -24,8 +24,12 @@ export default class DropdownEmoji extends FilteredSearchDropdown {
};
import(/* webpackChunkName: 'emoji' */ '~/emoji')
- .then(({ glEmojiTag }) => { this.glEmojiTag = glEmojiTag; })
- .catch(() => { /* ignore error and leave emoji name in the search bar */ });
+ .then(({ glEmojiTag }) => {
+ this.glEmojiTag = glEmojiTag;
+ })
+ .catch(() => {
+ /* ignore error and leave emoji name in the search bar */
+ });
this.unbindEvents();
this.bindEvents();
@@ -48,7 +52,7 @@ export default class DropdownEmoji extends FilteredSearchDropdown {
}
itemClicked(e) {
- super.itemClicked(e, (selected) => {
+ super.itemClicked(e, selected => {
const name = selected.querySelector('.js-data-value').innerText.trim();
return DropdownUtils.getEscapedText(name);
});
@@ -64,16 +68,18 @@ export default class DropdownEmoji extends FilteredSearchDropdown {
// Replace empty gl-emoji tag to real content
const dropdownItems = [...this.dropdown.querySelectorAll('.filter-dropdown-item')];
- dropdownItems.forEach((dropdownItem) => {
- const name = dropdownItem.querySelector('.js-data-value').innerText;
- const emojiTag = this.glEmojiTag(name);
- const emojiElement = dropdownItem.querySelector('gl-emoji');
- emojiElement.outerHTML = emojiTag;
+ dropdownItems.forEach(dropdownItem => {
+ const valueElement = dropdownItem.querySelector('.js-data-value');
+ if (valueElement !== null) {
+ const name = valueElement.innerText;
+ const emojiTag = this.glEmojiTag(name);
+ const emojiElement = dropdownItem.querySelector('gl-emoji');
+ emojiElement.outerHTML = emojiTag;
+ }
});
}
init() {
- this.droplab
- .addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init();
+ this.droplab.addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init();
}
}
diff --git a/app/assets/javascripts/filtered_search/dropdown_hint.js b/app/assets/javascripts/filtered_search/dropdown_hint.js
index 8aecf9725e6..1a1135ae929 100644
--- a/app/assets/javascripts/filtered_search/dropdown_hint.js
+++ b/app/assets/javascripts/filtered_search/dropdown_hint.js
@@ -41,8 +41,10 @@ export default class DropdownHint extends FilteredSearchDropdown {
previousInputValues.forEach((value, index) => {
searchTerms.push(value);
- if (index === previousInputValues.length - 1
- && token.indexOf(value.toLowerCase()) !== -1) {
+ if (
+ index === previousInputValues.length - 1 &&
+ token.indexOf(value.toLowerCase()) !== -1
+ ) {
searchTerms.pop();
}
});
@@ -51,7 +53,11 @@ export default class DropdownHint extends FilteredSearchDropdown {
FilteredSearchVisualTokens.addSearchVisualToken(searchTerms.join(' '));
}
- FilteredSearchDropdownManager.addWordToInput(token.replace(':', ''), '', false, this.container);
+ const key = token.replace(':', '');
+ const { uppercaseTokenName } = this.tokenKeys.searchByKey(key);
+ FilteredSearchDropdownManager.addWordToInput(key, '', false, {
+ uppercaseTokenName,
+ });
}
this.dismissDropdown();
this.dispatchInputEvent();
@@ -60,13 +66,12 @@ export default class DropdownHint extends FilteredSearchDropdown {
}
renderContent() {
- const dropdownData = this.tokenKeys.get()
- .map(tokenKey => ({
- icon: `${gon.sprite_icons}#${tokenKey.icon}`,
- hint: tokenKey.key,
- tag: `:${tokenKey.tag}`,
- type: tokenKey.type,
- }));
+ const dropdownData = this.tokenKeys.get().map(tokenKey => ({
+ icon: `${gon.sprite_icons}#${tokenKey.icon}`,
+ hint: tokenKey.key,
+ tag: `:${tokenKey.tag}`,
+ type: tokenKey.type,
+ }));
this.droplab.changeHookList(this.hookId, this.dropdown, [Filter], this.config);
this.droplab.setData(this.hookId, dropdownData);
diff --git a/app/assets/javascripts/filtered_search/dropdown_non_user.js b/app/assets/javascripts/filtered_search/dropdown_non_user.js
index 2ffda7e2037..0264f934914 100644
--- a/app/assets/javascripts/filtered_search/dropdown_non_user.js
+++ b/app/assets/javascripts/filtered_search/dropdown_non_user.js
@@ -29,20 +29,18 @@ export default class DropdownNonUser extends FilteredSearchDropdown {
}
itemClicked(e) {
- super.itemClicked(e, (selected) => {
+ super.itemClicked(e, selected => {
const title = selected.querySelector('.js-data-value').innerText.trim();
return `${this.symbol}${DropdownUtils.getEscapedText(title)}`;
});
}
renderContent(forceShowList = false) {
- this.droplab
- .changeHookList(this.hookId, this.dropdown, [Ajax, Filter], this.config);
+ this.droplab.changeHookList(this.hookId, this.dropdown, [Ajax, Filter], this.config);
super.renderContent(forceShowList);
}
init() {
- this.droplab
- .addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init();
+ this.droplab.addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init();
}
}
diff --git a/app/assets/javascripts/filtered_search/dropdown_user.js b/app/assets/javascripts/filtered_search/dropdown_user.js
index d36f38a70b5..d5027590bb7 100644
--- a/app/assets/javascripts/filtered_search/dropdown_user.js
+++ b/app/assets/javascripts/filtered_search/dropdown_user.js
@@ -39,8 +39,9 @@ export default class DropdownUser extends FilteredSearchDropdown {
}
itemClicked(e) {
- super.itemClicked(e,
- selected => selected.querySelector('.dropdown-light-content').innerText.trim());
+ super.itemClicked(e, selected =>
+ selected.querySelector('.dropdown-light-content').innerText.trim(),
+ );
}
renderContent(forceShowList = false) {
@@ -68,7 +69,7 @@ export default class DropdownUser extends FilteredSearchDropdown {
// Removes the first character if it is a quotation so that we can search
// with multiple words
- if (value[0] === '"' || value[0] === '\'') {
+ if (value[0] === '"' || value[0] === "'") {
value = value.slice(1);
}
diff --git a/app/assets/javascripts/filtered_search/dropdown_utils.js b/app/assets/javascripts/filtered_search/dropdown_utils.js
index 27fff488603..1b79a3320c6 100644
--- a/app/assets/javascripts/filtered_search/dropdown_utils.js
+++ b/app/assets/javascripts/filtered_search/dropdown_utils.js
@@ -41,7 +41,7 @@ export default class DropdownUtils {
// Removes the first character if it is a quotation so that we can search
// with multiple words
- if ((value[0] === '"' || value[0] === '\'') && title.indexOf(' ') !== -1) {
+ if ((value[0] === '"' || value[0] === "'") && title.indexOf(' ') !== -1) {
value = value.slice(1);
}
@@ -82,11 +82,13 @@ export default class DropdownUtils {
// Reduce the colors to 4
colors.length = Math.min(colors.length, 4);
- const color = colors.map((c, i) => {
- const percentFirst = Math.floor(spacing * i);
- const percentSecond = Math.floor(spacing * (i + 1));
- return `${c} ${percentFirst}%, ${c} ${percentSecond}%`;
- }).join(', ');
+ const color = colors
+ .map((c, i) => {
+ const percentFirst = Math.floor(spacing * i);
+ const percentSecond = Math.floor(spacing * (i + 1));
+ return `${c} ${percentFirst}%, ${c} ${percentSecond}%`;
+ })
+ .join(', ');
return `linear-gradient(${color})`;
}
@@ -97,17 +99,16 @@ export default class DropdownUtils {
data.forEach(DropdownUtils.mergeDuplicateLabels.bind(null, dataMap));
- Object.keys(dataMap)
- .forEach((key) => {
- const label = dataMap[key];
+ Object.keys(dataMap).forEach(key => {
+ const label = dataMap[key];
- if (label.multipleColors) {
- label.color = DropdownUtils.duplicateLabelColor(label.multipleColors);
- label.text_color = '#000000';
- }
+ if (label.multipleColors) {
+ label.color = DropdownUtils.duplicateLabelColor(label.multipleColors);
+ label.text_color = '#000000';
+ }
- results.push(label);
- });
+ results.push(label);
+ });
results.preprocessed = true;
@@ -118,8 +119,7 @@ export default class DropdownUtils {
const { input, allowedKeys } = config;
const updatedItem = item;
const searchInput = DropdownUtils.getSearchQuery(input);
- const { lastToken, tokens } =
- FilteredSearchTokenizer.processTokens(searchInput, allowedKeys);
+ const { lastToken, tokens } = FilteredSearchTokenizer.processTokens(searchInput, allowedKeys);
const lastKey = lastToken.key || lastToken || '';
const allowMultiple = item.type === 'array';
const itemInExistingTokens = tokens.some(t => t.key === item.hint);
@@ -143,7 +143,9 @@ export default class DropdownUtils {
const dataValue = selected.getAttribute('data-value');
if (dataValue) {
- FilteredSearchDropdownManager.addWordToInput(filter, dataValue, true);
+ FilteredSearchDropdownManager.addWordToInput(filter, dataValue, true, {
+ capitalizeTokenValue: selected.hasAttribute('data-capitalize'),
+ });
}
// Return boolean based on whether it was set
@@ -152,7 +154,10 @@ export default class DropdownUtils {
static getVisualTokenValues(visualToken) {
const tokenName = visualToken && visualToken.querySelector('.name').textContent.trim();
- let tokenValue = visualToken && visualToken.querySelector('.value') && visualToken.querySelector('.value').textContent.trim();
+ let tokenValue =
+ visualToken &&
+ visualToken.querySelector('.value') &&
+ visualToken.querySelector('.value').textContent.trim();
if (tokenName === 'label' && tokenValue) {
// remove leading symbol and wrapping quotes
tokenValue = tokenValue.replace(/^~("|')?(.*)/, '$2').replace(/("|')$/, '');
@@ -172,7 +177,7 @@ export default class DropdownUtils {
tokens.splice(inputIndex + 1);
}
- tokens.forEach((token) => {
+ tokens.forEach(token => {
if (token.classList.contains('js-visual-token')) {
const name = token.querySelector('.name');
const value = token.querySelector('.value');
@@ -192,8 +197,9 @@ export default class DropdownUtils {
values.push(name.innerText);
}
} else if (token.classList.contains('input-token')) {
- const { isLastVisualTokenValid } =
- FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
+ const {
+ isLastVisualTokenValid,
+ } = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
const input = FilteredSearchContainer.container.querySelector('.filtered-search');
const inputValue = input && input.value;
@@ -207,9 +213,7 @@ export default class DropdownUtils {
}
});
- return values
- .map(value => value.trim())
- .join(' ');
+ return values.map(value => value.trim()).join(' ');
}
static getSearchInput(filteredSearchInput) {
@@ -225,7 +229,9 @@ export default class DropdownUtils {
// Replace all spaces inside quote marks with underscores
// (will continue to match entire string until an end quote is found if any)
// This helps with matching the beginning & end of a token:key
- inputValue = inputValue.replace(/(('[^']*'{0,1})|("[^"]*"{0,1})|:\s+)/g, str => str.replace(/\s/g, '_'));
+ inputValue = inputValue.replace(/(('[^']*'{0,1})|("[^"]*"{0,1})|:\s+)/g, str =>
+ str.replace(/\s/g, '_'),
+ );
// Get the right position for the word selected
// Regex matches first space
diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js
index fb4ae1d17dd..146d3ba963c 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_dropdown.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown.js
@@ -85,12 +85,14 @@ export default class FilteredSearchDropdown {
}
dispatchInputEvent() {
- // Propogate input change to FilteredSearchDropdownManager
+ // Propagate input change to FilteredSearchDropdownManager
// so that it can determine which dropdowns to open
- this.input.dispatchEvent(new CustomEvent('input', {
- bubbles: true,
- cancelable: true,
- }));
+ this.input.dispatchEvent(
+ new CustomEvent('input', {
+ bubbles: true,
+ cancelable: true,
+ }),
+ );
}
dispatchFormSubmitEvent() {
@@ -114,7 +116,7 @@ export default class FilteredSearchDropdown {
if (!data) return;
- const results = data.map((o) => {
+ const results = data.map(o => {
const updated = o;
updated.droplab_hidden = false;
return updated;
diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
index a750647f8be..57ec6603d80 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
@@ -91,14 +91,24 @@ export default class FilteredSearchDropdownManager {
gl: DropdownEmoji,
element: this.container.querySelector('#js-dropdown-my-reaction'),
},
+ wip: {
+ reference: null,
+ gl: DropdownNonUser,
+ element: this.container.querySelector('#js-dropdown-wip'),
+ },
status: {
reference: null,
gl: NullDropdown,
element: this.container.querySelector('#js-dropdown-admin-runner-status'),
},
+ type: {
+ reference: null,
+ gl: NullDropdown,
+ element: this.container.querySelector('#js-dropdown-admin-runner-type'),
+ },
};
- supportedTokens.forEach((type) => {
+ supportedTokens.forEach(type => {
if (availableMappings[type]) {
allowedMappings[type] = availableMappings[type];
}
@@ -131,10 +141,13 @@ export default class FilteredSearchDropdownManager {
return endpoint;
}
- static addWordToInput(tokenName, tokenValue = '', clicked = false) {
+ static addWordToInput(tokenName, tokenValue = '', clicked = false, options = {}) {
+ const { uppercaseTokenName = false, capitalizeTokenValue = false } = options;
const input = FilteredSearchContainer.container.querySelector('.filtered-search');
-
- FilteredSearchVisualTokens.addFilterVisualToken(tokenName, tokenValue);
+ FilteredSearchVisualTokens.addFilterVisualToken(tokenName, tokenValue, {
+ uppercaseTokenName,
+ capitalizeTokenValue,
+ });
input.value = '';
if (clicked) {
@@ -148,13 +161,16 @@ export default class FilteredSearchDropdownManager {
updateDropdownOffset(key) {
// Always align dropdown with the input field
- let offset = this.filteredSearchInput.getBoundingClientRect().left - this.container.querySelector('.scroll-container').getBoundingClientRect().left;
+ let offset =
+ this.filteredSearchInput.getBoundingClientRect().left -
+ this.container.querySelector('.scroll-container').getBoundingClientRect().left;
const maxInputWidth = 240;
const currentDropdownWidth = this.mapping[key].element.clientWidth || maxInputWidth;
// Make sure offset never exceeds the input container
- const offsetMaxWidth = this.container.querySelector('.scroll-container').clientWidth - currentDropdownWidth;
+ const offsetMaxWidth =
+ this.container.querySelector('.scroll-container').clientWidth - currentDropdownWidth;
if (offsetMaxWidth < offset) {
offset = offsetMaxWidth;
}
@@ -180,8 +196,7 @@ export default class FilteredSearchDropdownManager {
const glArguments = Object.assign({}, defaultArguments, extraArguments);
// Passing glArguments to `new glClass(<arguments>)`
- mappingKey.reference =
- new (Function.prototype.bind.apply(glClass, [null, glArguments]))();
+ mappingKey.reference = new (Function.prototype.bind.apply(glClass, [null, glArguments]))();
}
if (firstLoad) {
@@ -208,8 +223,8 @@ export default class FilteredSearchDropdownManager {
}
const match = this.filteredSearchTokenKeys.searchByKey(dropdownName.toLowerCase());
- const shouldOpenFilterDropdown = match && this.currentDropdown !== match.key
- && this.mapping[match.key];
+ const shouldOpenFilterDropdown =
+ match && this.currentDropdown !== match.key && this.mapping[match.key];
const shouldOpenHintDropdown = !match && this.currentDropdown !== 'hint';
if (shouldOpenFilterDropdown || shouldOpenHintDropdown) {
@@ -220,8 +235,10 @@ export default class FilteredSearchDropdownManager {
setDropdown() {
const query = DropdownUtils.getSearchQuery(true);
- const { lastToken, searchToken } =
- this.tokenizer.processTokens(query, this.filteredSearchTokenKeys.getKeys());
+ const { lastToken, searchToken } = this.tokenizer.processTokens(
+ query,
+ this.filteredSearchTokenKeys.getKeys(),
+ );
if (this.currentDropdown) {
this.updateCurrentDropdownOffset();
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js
index d25f6f95b22..4a2af02b40a 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js
@@ -1,8 +1,5 @@
import _ from 'underscore';
-import {
- getParameterByName,
- getUrlParamsArray,
-} from '~/lib/utils/common_utils';
+import { getParameterByName, getUrlParamsArray } from '~/lib/utils/common_utils';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
import { visitUrl } from '../lib/utils/url_utility';
import Flash from '../flash';
@@ -48,24 +45,28 @@ export default class FilteredSearchManager {
isLocalStorageAvailable: RecentSearchesService.isAvailable(),
allowedKeys: this.filteredSearchTokenKeys.getKeys(),
});
- this.searchHistoryDropdownElement = document.querySelector('.js-filtered-search-history-dropdown');
- const fullPath = this.searchHistoryDropdownElement ?
- this.searchHistoryDropdownElement.dataset.fullPath : 'project';
+ this.searchHistoryDropdownElement = document.querySelector(
+ '.js-filtered-search-history-dropdown',
+ );
+ const fullPath = this.searchHistoryDropdownElement
+ ? this.searchHistoryDropdownElement.dataset.fullPath
+ : 'project';
const recentSearchesKey = `${fullPath}-${this.recentsStorageKeyNames[this.page]}`;
this.recentSearchesService = new RecentSearchesService(recentSearchesKey);
}
setup() {
// Fetch recent searches from localStorage
- this.fetchingRecentSearchesPromise = this.recentSearchesService.fetch()
- .catch((error) => {
+ this.fetchingRecentSearchesPromise = this.recentSearchesService
+ .fetch()
+ .catch(error => {
if (error.name === 'RecentSearchesServiceError') return undefined;
// eslint-disable-next-line no-new
new Flash('An error occurred while parsing recent searches');
// Gracefully fail to empty array
return [];
})
- .then((searches) => {
+ .then(searches => {
if (!searches) {
return;
}
@@ -120,7 +121,7 @@ export default class FilteredSearchManager {
if (this.stateFilters) {
this.searchStateWrapper = this.searchState.bind(this);
- this.applyToStateFilters((filterEl) => {
+ this.applyToStateFilters(filterEl => {
filterEl.addEventListener('click', this.searchStateWrapper);
});
}
@@ -128,14 +129,14 @@ export default class FilteredSearchManager {
unbindStateEvents() {
if (this.stateFilters) {
- this.applyToStateFilters((filterEl) => {
+ this.applyToStateFilters(filterEl => {
filterEl.removeEventListener('click', this.searchStateWrapper);
});
}
}
applyToStateFilters(callback) {
- this.stateFilters.querySelectorAll('a[data-state]').forEach((filterEl) => {
+ this.stateFilters.querySelectorAll('a[data-state]').forEach(filterEl => {
if (this.states.indexOf(filterEl.dataset.state) > -1) {
callback(filterEl);
}
@@ -207,7 +208,7 @@ export default class FilteredSearchManager {
let backspaceCount = 0;
// closure for keeping track of the number of backspace keystrokes
- return (e) => {
+ return e => {
// 8 = Backspace Key
// 46 = Delete Key
if (e.keyCode === 8 || e.keyCode === 46) {
@@ -274,8 +275,12 @@ export default class FilteredSearchManager {
const isElementInDynamicFilterDropdown = e.target.closest('.filter-dropdown') !== null;
const isElementInStaticFilterDropdown = e.target.closest('ul[data-dropdown]') !== null;
- if (!isElementInFilteredSearch && !isElementInDynamicFilterDropdown &&
- !isElementInStaticFilterDropdown && inputContainer) {
+ if (
+ !isElementInFilteredSearch &&
+ !isElementInDynamicFilterDropdown &&
+ !isElementInStaticFilterDropdown &&
+ inputContainer
+ ) {
inputContainer.classList.remove('focus');
}
}
@@ -368,7 +373,7 @@ export default class FilteredSearchManager {
const removeElements = [];
- [].forEach.call(this.tokensContainer.children, (t) => {
+ [].forEach.call(this.tokensContainer.children, t => {
let canClearToken = t.classList.contains('js-visual-token');
if (canClearToken) {
@@ -381,7 +386,7 @@ export default class FilteredSearchManager {
}
});
- removeElements.forEach((el) => {
+ removeElements.forEach(el => {
el.parentElement.removeChild(el);
});
@@ -397,15 +402,19 @@ export default class FilteredSearchManager {
handleInputVisualToken() {
const input = this.filteredSearchInput;
- const { tokens, searchToken }
- = this.tokenizer.processTokens(input.value, this.filteredSearchTokenKeys.getKeys());
- const { isLastVisualTokenValid }
- = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
+ const { tokens, searchToken } = this.tokenizer.processTokens(
+ input.value,
+ this.filteredSearchTokenKeys.getKeys(),
+ );
+ const { isLastVisualTokenValid } = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
if (isLastVisualTokenValid) {
- tokens.forEach((t) => {
+ tokens.forEach(t => {
input.value = input.value.replace(`${t.key}:${t.symbol}${t.value}`, '');
- FilteredSearchVisualTokens.addFilterVisualToken(t.key, `${t.symbol}${t.value}`);
+ FilteredSearchVisualTokens.addFilterVisualToken(t.key, `${t.symbol}${t.value}`, {
+ uppercaseTokenName: this.filteredSearchTokenKeys.shouldUppercaseTokenName(t.key),
+ capitalizeTokenValue: this.filteredSearchTokenKeys.shouldCapitalizeTokenValue(t.key),
+ });
});
const fragments = searchToken.split(':');
@@ -421,7 +430,10 @@ export default class FilteredSearchManager {
FilteredSearchVisualTokens.addSearchVisualToken(searchTerms);
}
- FilteredSearchVisualTokens.addFilterVisualToken(tokenKey);
+ FilteredSearchVisualTokens.addFilterVisualToken(tokenKey, null, {
+ uppercaseTokenName: this.filteredSearchTokenKeys.shouldUppercaseTokenName(tokenKey),
+ capitalizeTokenValue: this.filteredSearchTokenKeys.shouldCapitalizeTokenValue(tokenKey),
+ });
input.value = input.value.replace(`${tokenKey}:`, '');
}
} else {
@@ -429,7 +441,10 @@ export default class FilteredSearchManager {
const valueCompletedRegex = /([~%@]{0,1}".+")|([~%@]{0,1}'.+')|^((?![~%@]')(?![~%@]")(?!')(?!")).*/g;
if (searchToken.match(valueCompletedRegex) && input.value[input.value.length - 1] === ' ') {
- FilteredSearchVisualTokens.addFilterVisualToken(searchToken);
+ const tokenKey = FilteredSearchVisualTokens.getLastTokenPartial();
+ FilteredSearchVisualTokens.addFilterVisualToken(searchToken, null, {
+ capitalizeTokenValue: this.filteredSearchTokenKeys.shouldCapitalizeTokenValue(tokenKey),
+ });
// Trim the last space as seen in the if statement above
input.value = input.value.replace(searchToken, '').trim();
@@ -444,15 +459,17 @@ export default class FilteredSearchManager {
saveCurrentSearchQuery() {
// Don't save before we have fetched the already saved searches
- this.fetchingRecentSearchesPromise.then(() => {
- const searchQuery = DropdownUtils.getSearchQuery();
- if (searchQuery.length > 0) {
- const resultantSearches = this.recentSearchesStore.addRecentSearch(searchQuery);
- this.recentSearchesService.save(resultantSearches);
- }
- }).catch(() => {
- // https://gitlab.com/gitlab-org/gitlab-ce/issues/30821
- });
+ this.fetchingRecentSearchesPromise
+ .then(() => {
+ const searchQuery = DropdownUtils.getSearchQuery();
+ if (searchQuery.length > 0) {
+ const resultantSearches = this.recentSearchesStore.addRecentSearch(searchQuery);
+ this.recentSearchesService.save(resultantSearches);
+ }
+ })
+ .catch(() => {
+ // https://gitlab.com/gitlab-org/gitlab-ce/issues/30821
+ });
}
// allows for modifying params array when a param can't be included in the URL (e.g. Service Desk)
@@ -466,7 +483,7 @@ export default class FilteredSearchManager {
const usernameParams = this.getUsernameParams();
let hasFilteredSearch = false;
- params.forEach((p) => {
+ params.forEach(p => {
const split = p.split('=');
const keyParam = decodeURIComponent(split[0]);
const value = split[1];
@@ -477,11 +494,9 @@ export default class FilteredSearchManager {
if (condition) {
hasFilteredSearch = true;
const canEdit = this.canEdit && this.canEdit(condition.tokenKey);
- FilteredSearchVisualTokens.addFilterVisualToken(
- condition.tokenKey,
- condition.value,
+ FilteredSearchVisualTokens.addFilterVisualToken(condition.tokenKey, condition.value, {
canEdit,
- );
+ });
} else {
// Sanitize value since URL converts spaces into +
// Replace before decode so that we know what was originally + versus the encoded +
@@ -501,15 +516,20 @@ export default class FilteredSearchManager {
if (sanitizedValue.indexOf(' ') !== -1) {
// Prefer ", but use ' if required
- quotationsToUse = sanitizedValue.indexOf('"') === -1 ? '"' : '\'';
+ quotationsToUse = sanitizedValue.indexOf('"') === -1 ? '"' : "'";
}
hasFilteredSearch = true;
const canEdit = this.canEdit && this.canEdit(sanitizedKey, sanitizedValue);
+ const { uppercaseTokenName, capitalizeTokenValue } = match;
FilteredSearchVisualTokens.addFilterVisualToken(
sanitizedKey,
`${symbol}${quotationsToUse}${sanitizedValue}${quotationsToUse}`,
- canEdit,
+ {
+ canEdit,
+ uppercaseTokenName,
+ capitalizeTokenValue,
+ },
);
} else if (!match && keyParam === 'assignee_id') {
const id = parseInt(value, 10);
@@ -517,7 +537,9 @@ export default class FilteredSearchManager {
hasFilteredSearch = true;
const tokenName = 'assignee';
const canEdit = this.canEdit && this.canEdit(tokenName);
- FilteredSearchVisualTokens.addFilterVisualToken(tokenName, `@${usernameParams[id]}`, canEdit);
+ FilteredSearchVisualTokens.addFilterVisualToken(tokenName, `@${usernameParams[id]}`, {
+ canEdit,
+ });
}
} else if (!match && keyParam === 'author_id') {
const id = parseInt(value, 10);
@@ -525,7 +547,9 @@ export default class FilteredSearchManager {
hasFilteredSearch = true;
const tokenName = 'author';
const canEdit = this.canEdit && this.canEdit(tokenName);
- FilteredSearchVisualTokens.addFilterVisualToken(tokenName, `@${usernameParams[id]}`, canEdit);
+ FilteredSearchVisualTokens.addFilterVisualToken(tokenName, `@${usernameParams[id]}`, {
+ canEdit,
+ });
}
} else if (!match && keyParam === 'search') {
hasFilteredSearch = true;
@@ -561,15 +585,19 @@ export default class FilteredSearchManager {
this.saveCurrentSearchQuery();
- const { tokens, searchToken }
- = this.tokenizer.processTokens(searchQuery, this.filteredSearchTokenKeys.getKeys());
+ const tokenKeys = this.filteredSearchTokenKeys.getKeys();
+ const { tokens, searchToken } = this.tokenizer.processTokens(searchQuery, tokenKeys);
const currentState = state || getParameterByName('state') || 'opened';
paths.push(`state=${currentState}`);
- tokens.forEach((token) => {
- const condition = this.filteredSearchTokenKeys
- .searchByConditionKeyValue(token.key, token.value.toLowerCase());
- const { param } = this.filteredSearchTokenKeys.searchByKey(token.key) || {};
+ tokens.forEach(token => {
+ const condition = this.filteredSearchTokenKeys.searchByConditionKeyValue(
+ token.key,
+ token.value.toLowerCase(),
+ );
+ const tokenConfig = this.filteredSearchTokenKeys.searchByKey(token.key) || {};
+ const { param } = tokenConfig;
+
// Replace hyphen with underscore to use as request parameter
// e.g. 'my-reaction' => 'my_reaction'
const underscoredKey = token.key.replace('-', '_');
@@ -581,8 +609,14 @@ export default class FilteredSearchManager {
} else {
let tokenValue = token.value;
- if ((tokenValue[0] === '\'' && tokenValue[tokenValue.length - 1] === '\'') ||
- (tokenValue[0] === '"' && tokenValue[tokenValue.length - 1] === '"')) {
+ if (tokenConfig.lowercaseValueOnSubmit) {
+ tokenValue = tokenValue.toLowerCase();
+ }
+
+ if (
+ (tokenValue[0] === "'" && tokenValue[tokenValue.length - 1] === "'") ||
+ (tokenValue[0] === '"' && tokenValue[tokenValue.length - 1] === '"')
+ ) {
tokenValue = tokenValue.slice(1, tokenValue.length - 1);
}
@@ -593,7 +627,10 @@ export default class FilteredSearchManager {
});
if (searchToken) {
- const sanitized = searchToken.split(' ').map(t => encodeURIComponent(t)).join('+');
+ const sanitized = searchToken
+ .split(' ')
+ .map(t => encodeURIComponent(t))
+ .join('+');
paths.push(`search=${sanitized}`);
}
@@ -610,7 +647,7 @@ export default class FilteredSearchManager {
const usernamesById = {};
try {
const attribute = this.filteredSearchInput.getAttribute('data-username-params');
- JSON.parse(attribute).forEach((user) => {
+ JSON.parse(attribute).forEach(user => {
usernamesById[user.id] = user.username;
});
} catch (e) {
diff --git a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
index 5d131b396a0..e01dedbb57c 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_token_keys.js
@@ -23,6 +23,16 @@ export default class FilteredSearchTokenKeys {
return this.conditions;
}
+ shouldUppercaseTokenName(tokenKey) {
+ const token = this.searchByKey(tokenKey.toLowerCase());
+ return token && token.uppercaseTokenName;
+ }
+
+ shouldCapitalizeTokenValue(tokenKey) {
+ const token = this.searchByKey(tokenKey.toLowerCase());
+ return token && token.capitalizeTokenValue;
+ }
+
searchByKey(key) {
return this.tokenKeys.find(tokenKey => tokenKey.key === key) || null;
}
@@ -32,19 +42,21 @@ export default class FilteredSearchTokenKeys {
}
searchByKeyParam(keyParam) {
- return this.tokenKeysWithAlternative.find((tokenKey) => {
- let tokenKeyParam = tokenKey.key;
+ return (
+ this.tokenKeysWithAlternative.find(tokenKey => {
+ let tokenKeyParam = tokenKey.key;
- // Replace hyphen with underscore to compare keyParam with tokenKeyParam
- // e.g. 'my-reaction' => 'my_reaction'
- tokenKeyParam = tokenKeyParam.replace('-', '_');
+ // Replace hyphen with underscore to compare keyParam with tokenKeyParam
+ // e.g. 'my-reaction' => 'my_reaction'
+ tokenKeyParam = tokenKeyParam.replace('-', '_');
- if (tokenKey.param) {
- tokenKeyParam += `_${tokenKey.param}`;
- }
+ if (tokenKey.param) {
+ tokenKeyParam += `_${tokenKey.param}`;
+ }
- return keyParam === tokenKeyParam;
- }) || null;
+ return keyParam === tokenKeyParam;
+ }) || null
+ );
}
searchByConditionUrl(url) {
@@ -52,7 +64,26 @@ export default class FilteredSearchTokenKeys {
}
searchByConditionKeyValue(key, value) {
- return this.conditions
- .find(condition => condition.tokenKey === key && condition.value === value) || null;
+ return (
+ this.conditions.find(condition => condition.tokenKey === key && condition.value === value) ||
+ null
+ );
+ }
+
+ addExtraTokensForMergeRequests() {
+ const wipToken = {
+ key: 'wip',
+ type: 'string',
+ param: '',
+ symbol: '',
+ icon: 'admin',
+ tag: 'Yes or No',
+ lowercaseValueOnSubmit: true,
+ uppercaseTokenName: true,
+ capitalizeTokenValue: true,
+ };
+
+ this.tokenKeys.push(wipToken);
+ this.tokenKeysWithAlternative.push(wipToken);
}
}
diff --git a/app/assets/javascripts/filtered_search/filtered_search_tokenizer.js b/app/assets/javascripts/filtered_search/filtered_search_tokenizer.js
index d75610f6d68..b5c4cb15aac 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_tokenizer.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_tokenizer.js
@@ -4,41 +4,48 @@ export default class FilteredSearchTokenizer {
static processTokens(input, allowedKeys) {
// Regex extracts `(token):(symbol)(value)`
// Values that start with a double quote must end in a double quote (same for single)
- const tokenRegex = new RegExp(`(${allowedKeys.join('|')}):([~%@]?)(?:('[^']*'{0,1})|("[^"]*"{0,1})|(\\S+))`, 'g');
+ const tokenRegex = new RegExp(
+ `(${allowedKeys.join('|')}):([~%@]?)(?:('[^']*'{0,1})|("[^"]*"{0,1})|(\\S+))`,
+ 'g',
+ );
const tokens = [];
const tokenIndexes = []; // stores key+value for simple search
let lastToken = null;
- const searchToken = input.replace(tokenRegex, (match, key, symbol, v1, v2, v3) => {
- let tokenValue = v1 || v2 || v3;
- let tokenSymbol = symbol;
- let tokenIndex = '';
-
- if (tokenValue === '~' || tokenValue === '%' || tokenValue === '@') {
- tokenSymbol = tokenValue;
- tokenValue = '';
- }
-
- tokenIndex = `${key}:${tokenValue}`;
-
- // Prevent adding duplicates
- if (tokenIndexes.indexOf(tokenIndex) === -1) {
- tokenIndexes.push(tokenIndex);
-
- tokens.push({
- key,
- value: tokenValue || '',
- symbol: tokenSymbol || '',
- });
- }
-
- return '';
- }).replace(/\s{2,}/g, ' ').trim() || '';
+ const searchToken =
+ input
+ .replace(tokenRegex, (match, key, symbol, v1, v2, v3) => {
+ let tokenValue = v1 || v2 || v3;
+ let tokenSymbol = symbol;
+ let tokenIndex = '';
+
+ if (tokenValue === '~' || tokenValue === '%' || tokenValue === '@') {
+ tokenSymbol = tokenValue;
+ tokenValue = '';
+ }
+
+ tokenIndex = `${key}:${tokenValue}`;
+
+ // Prevent adding duplicates
+ if (tokenIndexes.indexOf(tokenIndex) === -1) {
+ tokenIndexes.push(tokenIndex);
+
+ tokens.push({
+ key,
+ value: tokenValue || '',
+ symbol: tokenSymbol || '',
+ });
+ }
+
+ return '';
+ })
+ .replace(/\s{2,}/g, ' ')
+ .trim() || '';
if (tokens.length > 0) {
const last = tokens[tokens.length - 1];
const lastString = `${last.key}:${last.symbol}${last.value}`;
- lastToken = input.lastIndexOf(lastString) ===
- input.length - lastString.length ? last : searchToken;
+ lastToken =
+ input.lastIndexOf(lastString) === input.length - lastString.length ? last : searchToken;
} else {
lastToken = searchToken;
}
diff --git a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
index 56fe1ab4e90..89dcff74d0e 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_visual_tokens.js
@@ -13,7 +13,10 @@ export default class FilteredSearchVisualTokens {
return {
lastVisualToken,
- isLastVisualTokenValid: lastVisualToken === null || lastVisualToken.className.indexOf('filtered-search-term') !== -1 || (lastVisualToken && lastVisualToken.querySelector('.value') !== null),
+ isLastVisualTokenValid:
+ lastVisualToken === null ||
+ lastVisualToken.className.indexOf('filtered-search-term') !== -1 ||
+ (lastVisualToken && lastVisualToken.querySelector('.value') !== null),
};
}
@@ -33,7 +36,9 @@ export default class FilteredSearchVisualTokens {
}
static unselectTokens() {
- const otherTokens = FilteredSearchContainer.container.querySelectorAll('.js-visual-token .selectable.selected');
+ const otherTokens = FilteredSearchContainer.container.querySelectorAll(
+ '.js-visual-token .selectable.selected',
+ );
[].forEach.call(otherTokens, t => t.classList.remove('selected'));
}
@@ -55,12 +60,14 @@ export default class FilteredSearchVisualTokens {
}
}
- static createVisualTokenElementHTML(canEdit = true) {
+ static createVisualTokenElementHTML(options = {}) {
+ const { canEdit = true, uppercaseTokenName = false, capitalizeTokenValue = false } = options;
+
return `
<div class="${canEdit ? 'selectable' : 'hidden'}" role="button">
- <div class="name"></div>
+ <div class="${uppercaseTokenName ? 'text-uppercase' : ''} name"></div>
<div class="value-container">
- <div class="value"></div>
+ <div class="${capitalizeTokenValue ? 'text-capitalize' : ''} value"></div>
<div class="remove-token" role="button">
<i class="fa fa-close"></i>
</div>
@@ -109,58 +116,63 @@ export default class FilteredSearchVisualTokens {
return AjaxCache.retrieve(labelsEndpoint)
.then(FilteredSearchVisualTokens.preprocessLabel.bind(null, labelsEndpoint))
- .then((labels) => {
- const matchingLabel = (labels || []).find(label => `~${DropdownUtils.getEscapedText(label.title)}` === tokenValue);
+ .then(labels => {
+ const matchingLabel = (labels || []).find(
+ label => `~${DropdownUtils.getEscapedText(label.title)}` === tokenValue,
+ );
if (!matchingLabel) {
return;
}
- FilteredSearchVisualTokens
- .setTokenStyle(tokenValueContainer, matchingLabel.color, matchingLabel.text_color);
+ FilteredSearchVisualTokens.setTokenStyle(
+ tokenValueContainer,
+ matchingLabel.color,
+ matchingLabel.text_color,
+ );
})
.catch(() => new Flash('An error occurred while fetching label colors.'));
}
static updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue) {
- if (tokenValue === 'none') {
- return Promise.resolve();
- }
-
const username = tokenValue.replace(/^@/, '');
- return UsersCache.retrieve(username)
- .then((user) => {
- if (!user) {
- return;
- }
-
- /* eslint-disable no-param-reassign */
- tokenValueContainer.dataset.originalValue = tokenValue;
- tokenValueElement.innerHTML = `
+ return (
+ UsersCache.retrieve(username)
+ .then(user => {
+ if (!user) {
+ return;
+ }
+
+ /* eslint-disable no-param-reassign */
+ tokenValueContainer.dataset.originalValue = tokenValue;
+ tokenValueElement.innerHTML = `
<img class="avatar s20" src="${user.avatar_url}" alt="">
${_.escape(user.name)}
`;
- /* eslint-enable no-param-reassign */
- })
- // ignore error and leave username in the search bar
- .catch(() => { });
+ /* eslint-enable no-param-reassign */
+ })
+ // ignore error and leave username in the search bar
+ .catch(() => {})
+ );
}
static updateEmojiTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue) {
const container = tokenValueContainer;
const element = tokenValueElement;
- return import(/* webpackChunkName: 'emoji' */ '../emoji')
- .then((Emoji) => {
- if (!Emoji.isEmojiNameValid(tokenValue)) {
- return;
- }
-
- container.dataset.originalValue = tokenValue;
- element.innerHTML = Emoji.glEmojiTag(tokenValue);
- })
- // ignore error and leave emoji name in the search bar
- .catch(() => { });
+ return (
+ import(/* webpackChunkName: 'emoji' */ '../emoji')
+ .then(Emoji => {
+ if (!Emoji.isEmojiNameValid(tokenValue)) {
+ return;
+ }
+
+ container.dataset.originalValue = tokenValue;
+ element.innerHTML = Emoji.glEmojiTag(tokenValue);
+ })
+ // ignore error and leave emoji name in the search bar
+ .catch(() => {})
+ );
}
static renderVisualTokenValue(parentElement, tokenName, tokenValue) {
@@ -168,30 +180,44 @@ export default class FilteredSearchVisualTokens {
const tokenValueElement = tokenValueContainer.querySelector('.value');
tokenValueElement.innerText = tokenValue;
+ if (tokenValue === 'none' || tokenValue === 'any') {
+ return;
+ }
+
const tokenType = tokenName.toLowerCase();
+
if (tokenType === 'label') {
FilteredSearchVisualTokens.updateLabelTokenColor(tokenValueContainer, tokenValue);
- } else if ((tokenType === 'author') || (tokenType === 'assignee')) {
+ } else if (tokenType === 'author' || tokenType === 'assignee') {
FilteredSearchVisualTokens.updateUserTokenAppearance(
- tokenValueContainer, tokenValueElement, tokenValue,
+ tokenValueContainer,
+ tokenValueElement,
+ tokenValue,
);
} else if (tokenType === 'my-reaction') {
FilteredSearchVisualTokens.updateEmojiTokenAppearance(
- tokenValueContainer, tokenValueElement, tokenValue,
+ tokenValueContainer,
+ tokenValueElement,
+ tokenValue,
);
}
}
- static addVisualTokenElement(name, value, isSearchTerm, canEdit) {
+ static addVisualTokenElement(name, value, options = {}) {
+ const { isSearchTerm = false, canEdit, uppercaseTokenName, capitalizeTokenValue } = options;
const li = document.createElement('li');
li.classList.add('js-visual-token');
li.classList.add(isSearchTerm ? 'filtered-search-term' : 'filtered-search-token');
if (value) {
- li.innerHTML = FilteredSearchVisualTokens.createVisualTokenElementHTML(canEdit);
+ li.innerHTML = FilteredSearchVisualTokens.createVisualTokenElementHTML({
+ canEdit,
+ uppercaseTokenName,
+ capitalizeTokenValue,
+ });
FilteredSearchVisualTokens.renderVisualTokenValue(li, name, value);
} else {
- li.innerHTML = '<div class="name"></div>';
+ li.innerHTML = `<div class="${uppercaseTokenName ? 'text-uppercase' : ''} name"></div>`;
}
li.querySelector('.name').innerText = name;
@@ -201,8 +227,10 @@ export default class FilteredSearchVisualTokens {
}
static addValueToPreviousVisualTokenElement(value) {
- const { lastVisualToken, isLastVisualTokenValid } =
- FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
+ const {
+ lastVisualToken,
+ isLastVisualTokenValid,
+ } = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
if (!isLastVisualTokenValid && lastVisualToken.classList.contains('filtered-search-token')) {
const name = FilteredSearchVisualTokens.getLastTokenPartial();
@@ -212,20 +240,34 @@ export default class FilteredSearchVisualTokens {
}
}
- static addFilterVisualToken(tokenName, tokenValue, canEdit) {
- const { lastVisualToken, isLastVisualTokenValid }
- = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
+ static addFilterVisualToken(
+ tokenName,
+ tokenValue,
+ { canEdit, uppercaseTokenName = false, capitalizeTokenValue = false } = {},
+ ) {
+ const {
+ lastVisualToken,
+ isLastVisualTokenValid,
+ } = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
const { addVisualTokenElement } = FilteredSearchVisualTokens;
if (isLastVisualTokenValid) {
- addVisualTokenElement(tokenName, tokenValue, false, canEdit);
+ addVisualTokenElement(tokenName, tokenValue, {
+ canEdit,
+ uppercaseTokenName,
+ capitalizeTokenValue,
+ });
} else {
const previousTokenName = lastVisualToken.querySelector('.name').innerText;
const tokensContainer = FilteredSearchContainer.container.querySelector('.tokens-container');
tokensContainer.removeChild(lastVisualToken);
const value = tokenValue || tokenName;
- addVisualTokenElement(previousTokenName, value, false, canEdit);
+ addVisualTokenElement(previousTokenName, value, {
+ canEdit,
+ uppercaseTokenName,
+ capitalizeTokenValue,
+ });
}
}
@@ -235,7 +277,9 @@ export default class FilteredSearchVisualTokens {
if (lastVisualToken && lastVisualToken.classList.contains('filtered-search-term')) {
lastVisualToken.querySelector('.name').innerText += ` ${searchTerm}`;
} else {
- FilteredSearchVisualTokens.addVisualTokenElement(searchTerm, null, true);
+ FilteredSearchVisualTokens.addVisualTokenElement(searchTerm, null, {
+ isSearchTerm: true,
+ });
}
}
@@ -278,8 +322,7 @@ export default class FilteredSearchVisualTokens {
static tokenizeInput() {
const input = FilteredSearchContainer.container.querySelector('.filtered-search');
- const { isLastVisualTokenValid } =
- FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
+ const { isLastVisualTokenValid } = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
if (input.value) {
if (isLastVisualTokenValid) {
@@ -306,7 +349,9 @@ export default class FilteredSearchVisualTokens {
let value;
if (token.classList.contains('filtered-search-token')) {
- FilteredSearchVisualTokens.addFilterVisualToken(nameElement.innerText);
+ FilteredSearchVisualTokens.addFilterVisualToken(nameElement.innerText, null, {
+ uppercaseTokenName: nameElement.classList.contains('text-uppercase'),
+ });
const valueContainerElement = token.querySelector('.value-container');
value = valueContainerElement.dataset.originalValue;
@@ -343,8 +388,7 @@ export default class FilteredSearchVisualTokens {
FilteredSearchVisualTokens.tokenizeInput();
if (!tokenContainer.lastElementChild.isEqualNode(inputLi)) {
- const { isLastVisualTokenValid } =
- FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
+ const { isLastVisualTokenValid } = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
if (!isLastVisualTokenValid) {
const lastPartial = FilteredSearchVisualTokens.getLastTokenPartial();
diff --git a/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js b/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js
index cc7291c9f59..b494b7e2de0 100644
--- a/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js
+++ b/app/assets/javascripts/filtered_search/issuable_filtered_search_token_keys.js
@@ -1,34 +1,39 @@
import FilteredSearchTokenKeys from './filtered_search_token_keys';
-export const tokenKeys = [{
- key: 'author',
- type: 'string',
- param: 'username',
- symbol: '@',
- icon: 'pencil',
- tag: '@author',
-}, {
- key: 'assignee',
- type: 'string',
- param: 'username',
- symbol: '@',
- icon: 'user',
- tag: '@assignee',
-}, {
- key: 'milestone',
- type: 'string',
- param: 'title',
- symbol: '%',
- icon: 'clock',
- tag: '%milestone',
-}, {
- key: 'label',
- type: 'array',
- param: 'name[]',
- symbol: '~',
- icon: 'labels',
- tag: '~label',
-}];
+export const tokenKeys = [
+ {
+ key: 'author',
+ type: 'string',
+ param: 'username',
+ symbol: '@',
+ icon: 'pencil',
+ tag: '@author',
+ },
+ {
+ key: 'assignee',
+ type: 'string',
+ param: 'username',
+ symbol: '@',
+ icon: 'user',
+ tag: '@assignee',
+ },
+ {
+ key: 'milestone',
+ type: 'string',
+ param: 'title',
+ symbol: '%',
+ icon: 'clock',
+ tag: '%milestone',
+ },
+ {
+ key: 'label',
+ type: 'array',
+ param: 'name[]',
+ symbol: '~',
+ icon: 'labels',
+ tag: '~label',
+ },
+];
if (gon.current_user_id) {
// Appending tokenkeys only logged-in
@@ -42,36 +47,72 @@ if (gon.current_user_id) {
});
}
-export const alternativeTokenKeys = [{
- key: 'label',
- type: 'string',
- param: 'name',
- symbol: '~',
-}];
+export const alternativeTokenKeys = [
+ {
+ key: 'label',
+ type: 'string',
+ param: 'name',
+ symbol: '~',
+ },
+];
-export const conditions = [{
- url: 'assignee_id=0',
- tokenKey: 'assignee',
- value: 'none',
-}, {
- url: 'milestone_title=No+Milestone',
- tokenKey: 'milestone',
- value: 'none',
-}, {
- url: 'milestone_title=%23upcoming',
- tokenKey: 'milestone',
- value: 'upcoming',
-}, {
- url: 'milestone_title=%23started',
- tokenKey: 'milestone',
- value: 'started',
-}, {
- url: 'label_name[]=No+Label',
- tokenKey: 'label',
- value: 'none',
-}];
+export const conditions = [
+ {
+ url: 'assignee_id=None',
+ tokenKey: 'assignee',
+ value: 'none',
+ },
+ {
+ url: 'assignee_id=Any',
+ tokenKey: 'assignee',
+ value: 'any',
+ },
+ {
+ url: 'milestone_title=None',
+ tokenKey: 'milestone',
+ value: 'none',
+ },
+ {
+ url: 'milestone_title=Any',
+ tokenKey: 'milestone',
+ value: 'any',
+ },
+ {
+ url: 'milestone_title=%23upcoming',
+ tokenKey: 'milestone',
+ value: 'upcoming',
+ },
+ {
+ url: 'milestone_title=%23started',
+ tokenKey: 'milestone',
+ value: 'started',
+ },
+ {
+ url: 'label_name[]=None',
+ tokenKey: 'label',
+ value: 'none',
+ },
+ {
+ url: 'label_name[]=Any',
+ tokenKey: 'any',
+ value: 'any',
+ },
+ {
+ url: 'my_reaction_emoji=None',
+ tokenKey: 'my-reaction',
+ value: 'none',
+ },
+ {
+ url: 'my_reaction_emoji=Any',
+ tokenKey: 'my-reaction',
+ value: 'any',
+ },
+];
-const IssuableFilteredSearchTokenKeys =
- new FilteredSearchTokenKeys(tokenKeys, alternativeTokenKeys, conditions);
+const IssuableFilteredSearchTokenKeys = new FilteredSearchTokenKeys(
+ tokenKeys,
+ alternativeTokenKeys,
+ conditions,
+);
export default IssuableFilteredSearchTokenKeys;
diff --git a/app/assets/javascripts/filtered_search/recent_searches_root.js b/app/assets/javascripts/filtered_search/recent_searches_root.js
index c1efa9c86f4..6c8e77a7fe5 100644
--- a/app/assets/javascripts/filtered_search/recent_searches_root.js
+++ b/app/assets/javascripts/filtered_search/recent_searches_root.js
@@ -3,11 +3,7 @@ import RecentSearchesDropdownContent from './components/recent_searches_dropdown
import eventHub from './event_hub';
class RecentSearchesRoot {
- constructor(
- recentSearchesStore,
- recentSearchesService,
- wrapperElement,
- ) {
+ constructor(recentSearchesStore, recentSearchesService, wrapperElement) {
this.store = recentSearchesStore;
this.service = recentSearchesService;
this.wrapperElement = wrapperElement;
@@ -35,7 +31,9 @@ class RecentSearchesRoot {
components: {
RecentSearchesDropdownContent,
},
- data() { return state; },
+ data() {
+ return state;
+ },
template: `
<recent-searches-dropdown-content
:items="recentSearches"
@@ -57,7 +55,6 @@ class RecentSearchesRoot {
this.vm.$destroy();
}
}
-
}
export default RecentSearchesRoot;
diff --git a/app/assets/javascripts/filtered_search/stores/recent_searches_store.js b/app/assets/javascripts/filtered_search/stores/recent_searches_store.js
index aaa0c349d93..76d40bfdaf8 100644
--- a/app/assets/javascripts/filtered_search/stores/recent_searches_store.js
+++ b/app/assets/javascripts/filtered_search/stores/recent_searches_store.js
@@ -2,11 +2,14 @@ import _ from 'underscore';
class RecentSearchesStore {
constructor(initialState = {}, allowedKeys) {
- this.state = Object.assign({
- isLocalStorageAvailable: true,
- recentSearches: [],
- allowedKeys,
- }, initialState);
+ this.state = Object.assign(
+ {
+ isLocalStorageAvailable: true,
+ recentSearches: [],
+ allowedKeys,
+ },
+ initialState,
+ );
}
addRecentSearch(newSearch) {
diff --git a/app/assets/javascripts/flash.js b/app/assets/javascripts/flash.js
index a29de9ae899..c2397842125 100644
--- a/app/assets/javascripts/flash.js
+++ b/app/assets/javascripts/flash.js
@@ -8,14 +8,19 @@ const hideFlash = (flashEl, fadeTransition = true) => {
});
}
- flashEl.addEventListener('transitionend', () => {
- flashEl.remove();
- window.dispatchEvent(new Event('resize'));
- if (document.body.classList.contains('flash-shown')) document.body.classList.remove('flash-shown');
- }, {
- once: true,
- passive: true,
- });
+ flashEl.addEventListener(
+ 'transitionend',
+ () => {
+ flashEl.remove();
+ window.dispatchEvent(new Event('resize'));
+ if (document.body.classList.contains('flash-shown'))
+ document.body.classList.remove('flash-shown');
+ },
+ {
+ once: true,
+ passive: true,
+ },
+ );
if (!fadeTransition) flashEl.dispatchEvent(new Event('transitionend'));
};
@@ -30,12 +35,14 @@ const createAction = config => `
</a>
`;
-const createFlashEl = (message, type, isInContentWrapper = false) => `
+const createFlashEl = (message, type, isFixedLayout = false) => `
<div
class="flash-${type}"
>
<div
- class="flash-text ${isInContentWrapper ? 'container-fluid container-limited' : ''}"
+ class="flash-text ${
+ isFixedLayout ? 'container-fluid container-limited limit-container-width' : ''
+ }"
>
${_.escape(message)}
</div>
@@ -69,12 +76,15 @@ const createFlash = function createFlash(
addBodyClass = false,
) {
const flashContainer = parent.querySelector('.flash-container');
+ const navigation = parent.querySelector('.content');
if (!flashContainer) return null;
- const isInContentWrapper = flashContainer.parentNode.classList.contains('content-wrapper');
+ const isFixedLayout = navigation
+ ? navigation.parentNode.classList.contains('container-limited')
+ : true;
- flashContainer.innerHTML = createFlashEl(message, type, isInContentWrapper);
+ flashContainer.innerHTML = createFlashEl(message, type, isFixedLayout);
const flashEl = flashContainer.querySelector(`.flash-${type}`);
removeFlashClickListener(flashEl, fadeTransition);
@@ -83,7 +93,9 @@ const createFlash = function createFlash(
flashEl.innerHTML += createAction(actionConfig);
if (actionConfig.clickHandler) {
- flashEl.querySelector('.flash-action').addEventListener('click', e => actionConfig.clickHandler(e));
+ flashEl
+ .querySelector('.flash-action')
+ .addEventListener('click', e => actionConfig.clickHandler(e));
}
}
@@ -94,11 +106,5 @@ const createFlash = function createFlash(
return flashContainer;
};
-export {
- createFlash as default,
- createFlashEl,
- createAction,
- hideFlash,
- removeFlashClickListener,
-};
+export { createFlash as default, createFlashEl, createAction, hideFlash, removeFlashClickListener };
window.Flash = createFlash;
diff --git a/app/assets/javascripts/fly_out_nav.js b/app/assets/javascripts/fly_out_nav.js
index f820f0dc3f0..3ac00c51df4 100644
--- a/app/assets/javascripts/fly_out_nav.js
+++ b/app/assets/javascripts/fly_out_nav.js
@@ -11,9 +11,13 @@ let sidebar;
export const mousePos = [];
-export const setSidebar = (el) => { sidebar = el; };
+export const setSidebar = el => {
+ sidebar = el;
+};
export const getOpenMenu = () => currentOpenMenu;
-export const setOpenMenu = (menu = null) => { currentOpenMenu = menu; };
+export const setOpenMenu = (menu = null) => {
+ currentOpenMenu = menu;
+};
export const slope = (a, b) => (b.y - a.y) / (b.x - a.x);
@@ -21,9 +25,10 @@ let headerHeight = 50;
export const getHeaderHeight = () => headerHeight;
-export const isSidebarCollapsed = () => sidebar && sidebar.classList.contains('sidebar-collapsed-desktop');
+export const isSidebarCollapsed = () =>
+ sidebar && sidebar.classList.contains('sidebar-collapsed-desktop');
-export const canShowActiveSubItems = (el) => {
+export const canShowActiveSubItems = el => {
if (el.classList.contains('active') && !isSidebarCollapsed()) {
return false;
}
@@ -31,7 +36,10 @@ export const canShowActiveSubItems = (el) => {
return true;
};
-export const canShowSubItems = () => bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'md' || bp.getBreakpointSize() === 'lg';
+export const canShowSubItems = () =>
+ bp.getBreakpointSize() === 'sm' ||
+ bp.getBreakpointSize() === 'md' ||
+ bp.getBreakpointSize() === 'lg';
export const getHideSubItemsInterval = () => {
if (!currentOpenMenu || !mousePos.length) return 0;
@@ -41,11 +49,12 @@ export const getHideSubItemsInterval = () => {
const currentMousePosY = currentMousePos.y;
const [menuTop, menuBottom] = menuCornerLocs;
- if (currentMousePosY < menuTop.y ||
- currentMousePosY > menuBottom.y) return 0;
+ if (currentMousePosY < menuTop.y || currentMousePosY > menuBottom.y) return 0;
- if (slope(prevMousePos, menuBottom) < slope(currentMousePos, menuBottom) &&
- slope(prevMousePos, menuTop) > slope(currentMousePos, menuTop)) {
+ if (
+ slope(prevMousePos, menuBottom) < slope(currentMousePos, menuBottom) &&
+ slope(prevMousePos, menuTop) > slope(currentMousePos, menuTop)
+ ) {
return HIDE_INTERVAL_TIMEOUT;
}
@@ -56,11 +65,12 @@ export const calculateTop = (boundingRect, outerHeight) => {
const windowHeight = window.innerHeight;
const bottomOverflow = windowHeight - (boundingRect.top + outerHeight);
- return bottomOverflow < 0 ? (boundingRect.top - outerHeight) + boundingRect.height :
- boundingRect.top;
+ return bottomOverflow < 0
+ ? boundingRect.top - outerHeight + boundingRect.height
+ : boundingRect.top;
};
-export const hideMenu = (el) => {
+export const hideMenu = el => {
if (!el) return;
const parentEl = el.parentNode;
@@ -101,7 +111,7 @@ export const moveSubItemsToPosition = (el, subItems) => {
}
};
-export const showSubLevelItems = (el) => {
+export const showSubLevelItems = el => {
const subItems = el.querySelector('.sidebar-sub-level-items');
const isIconOnly = subItems && subItems.classList.contains('is-fly-out-only');
@@ -128,16 +138,20 @@ export const mouseEnterTopItems = (el, timeout = getHideSubItemsInterval()) => {
}, timeout);
};
-export const mouseLeaveTopItem = (el) => {
+export const mouseLeaveTopItem = el => {
const subItems = el.querySelector('.sidebar-sub-level-items');
- if (!canShowSubItems() || !canShowActiveSubItems(el) ||
- (subItems && subItems === currentOpenMenu)) return;
+ if (
+ !canShowSubItems() ||
+ !canShowActiveSubItems(el) ||
+ (subItems && subItems === currentOpenMenu)
+ )
+ return;
el.classList.remove(IS_OVER_CLASS);
};
-export const documentMouseMove = (e) => {
+export const documentMouseMove = e => {
mousePos.push({
x: e.clientX,
y: e.clientY,
@@ -146,7 +160,7 @@ export const documentMouseMove = (e) => {
if (mousePos.length > 6) mousePos.shift();
};
-export const subItemsMouseLeave = (relatedTarget) => {
+export const subItemsMouseLeave = relatedTarget => {
clearTimeout(timeoutId);
if (relatedTarget && !relatedTarget.closest(`.${IS_OVER_CLASS}`)) {
@@ -174,7 +188,7 @@ export default () => {
headerHeight = document.querySelector('.nav-sidebar').offsetTop;
- items.forEach((el) => {
+ items.forEach(el => {
const subItems = el.querySelector('.sidebar-sub-level-items');
if (subItems) {
diff --git a/app/assets/javascripts/frequent_items/components/app.vue b/app/assets/javascripts/frequent_items/components/app.vue
index 70a8838b772..63531f1f246 100644
--- a/app/assets/javascripts/frequent_items/components/app.vue
+++ b/app/assets/javascripts/frequent_items/components/app.vue
@@ -1,6 +1,7 @@
<script>
import { mapState, mapActions, mapGetters } from 'vuex';
import AccessorUtilities from '~/lib/utils/accessor';
+import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '../event_hub';
import store from '../store/';
import { FREQUENT_ITEMS, STORAGE_KEY } from '../constants';
@@ -14,6 +15,7 @@ export default {
components: {
FrequentItemsSearchInput,
FrequentItemsList,
+ GlLoadingIcon,
},
mixins: [frequentItemsMixin],
props: {
@@ -93,19 +95,14 @@ export default {
<template>
<div>
- <frequent-items-search-input
- :namespace="namespace"
- />
+ <frequent-items-search-input :namespace="namespace" />
<gl-loading-icon
v-if="isLoadingItems"
:label="translations.loadingMessage"
:size="2"
class="loading-animation prepend-top-20"
/>
- <div
- v-if="!isLoadingItems && !hasSearchQuery"
- class="section-header"
- >
+ <div v-if="!isLoadingItems && !hasSearchQuery" class="section-header">
{{ translations.header }}
</div>
<frequent-items-list
diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_list.vue b/app/assets/javascripts/frequent_items/components/frequent_items_list.vue
index 8e511aa2a36..67ffa97a046 100644
--- a/app/assets/javascripts/frequent_items/components/frequent_items_list.vue
+++ b/app/assets/javascripts/frequent_items/components/frequent_items_list.vue
@@ -55,11 +55,7 @@ export default {
<template>
<div class="frequent-items-list-container">
<ul class="list-unstyled">
- <li
- v-if="isListEmpty"
- :class="{ 'section-failure': isFetchFailed }"
- class="section-empty"
- >
+ <li v-if="isListEmpty" :class="{ 'section-failure': isFetchFailed }" class="section-empty">
{{ listEmptyMessage }}
</li>
<frequent-items-list-item
diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
index 1f1665ff7fe..2cbc7c7077b 100644
--- a/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
+++ b/app/assets/javascripts/frequent_items/components/frequent_items_list_item.vue
@@ -1,5 +1,5 @@
<script>
-/* eslint-disable vue/require-default-prop, vue/require-prop-types */
+/* eslint-disable vue/require-default-prop */
import Identicon from '../../vue_shared/components/identicon.vue';
export default {
@@ -80,35 +80,14 @@ export default {
<template>
<li class="frequent-items-list-item-container">
- <a
- :href="webUrl"
- class="clearfix"
- >
+ <a :href="webUrl" class="clearfix">
<div class="frequent-items-item-avatar-container">
- <img
- v-if="hasAvatar"
- :src="avatarUrl"
- class="avatar s32"
- />
- <identicon
- v-else
- :entity-id="itemId"
- :entity-name="itemName"
- size-class="s32"
- />
+ <img v-if="hasAvatar" :src="avatarUrl" class="avatar s32" />
+ <identicon v-else :entity-id="itemId" :entity-name="itemName" size-class="s32" />
</div>
<div class="frequent-items-item-metadata-container">
- <div
- :title="itemName"
- class="frequent-items-item-title"
- v-html="highlightedItemName"
- >
- </div>
- <div
- v-if="truncatedNamespace"
- :title="namespace"
- class="frequent-items-item-namespace"
- >
+ <div :title="itemName" class="frequent-items-item-title" v-html="highlightedItemName"></div>
+ <div v-if="truncatedNamespace" :title="namespace" class="frequent-items-item-namespace">
{{ truncatedNamespace }}
</div>
</div>
diff --git a/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue b/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue
index a6a265eb3fd..c69e1b792dc 100644
--- a/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue
+++ b/app/assets/javascripts/frequent_items/components/frequent_items_search_input.vue
@@ -1,10 +1,14 @@
<script>
import _ from 'underscore';
import { mapActions } from 'vuex';
+import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '../event_hub';
import frequentItemsMixin from './frequent_items_mixin';
export default {
+ components: {
+ Icon,
+ },
mixins: [frequentItemsMixin],
data() {
return {
@@ -45,11 +49,6 @@ export default {
type="search"
class="form-control"
/>
- <i
- v-if="!searchQuery"
- class="search-icon fa fa-fw fa-search"
- aria-hidden="true"
- >
- </i>
+ <icon v-if="!searchQuery" name="search" class="search-icon" />
</div>
</template>
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index 73b2cd0b2c7..c14eb936930 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -15,6 +15,7 @@ export const defaultAutocompleteConfig = {
epics: true,
milestones: true,
labels: true,
+ snippets: true,
};
class GfmAutoComplete {
@@ -50,6 +51,7 @@ class GfmAutoComplete {
if (this.enableMap.milestones) this.setupMilestones($input);
if (this.enableMap.mergeRequests) this.setupMergeRequests($input);
if (this.enableMap.labels) this.setupLabels($input);
+ if (this.enableMap.snippets) this.setupSnippets($input);
// We don't instantiate the quick actions autocomplete for note and issue/MR edit forms
$input.filter('[data-supports-quick-actions="true"]').atwho({
@@ -60,9 +62,11 @@ class GfmAutoComplete {
skipMarkdownCharacterTest: true,
data: GfmAutoComplete.defaultLoadingData,
displayTpl(value) {
+ const cssClasses = [];
+
if (GfmAutoComplete.isLoading(value)) return GfmAutoComplete.Loading.template;
// eslint-disable-next-line no-template-curly-in-string
- let tpl = '<li><span class="name">/${name}</span>';
+ let tpl = '<li class="<%- className %>"><span class="name">/${name}</span>';
if (value.aliases.length > 0) {
tpl += ' <small class="aliases">(or /<%- aliases.join(", /") %>)</small>';
}
@@ -70,10 +74,19 @@ class GfmAutoComplete {
tpl += ' <small class="params"><%- params.join(" ") %></small>';
}
if (value.description !== '') {
- tpl += '<small class="description"><i><%- description %></i></small>';
+ tpl += '<small class="description"><i><%- description %> <%- warningText %></i></small>';
}
tpl += '</li>';
- return _.template(tpl)(value);
+
+ if (value.warning) {
+ cssClasses.push('has-warning');
+ }
+
+ return _.template(tpl)({
+ ...value,
+ className: cssClasses.join(' '),
+ warningText: value.warning ? `(${value.warning})` : '',
+ });
},
insertTpl(value) {
// eslint-disable-next-line no-template-curly-in-string
@@ -92,7 +105,7 @@ class GfmAutoComplete {
...this.getDefaultCallbacks(),
beforeSave(commands) {
if (GfmAutoComplete.isLoading(commands)) return commands;
- return $.map(commands, (c) => {
+ return $.map(commands, c => {
let search = c.name;
if (c.aliases.length > 0) {
search = `${search} ${c.aliases.join(' ')}`;
@@ -102,6 +115,7 @@ class GfmAutoComplete {
aliases: c.aliases,
params: c.params,
description: c.description,
+ warning: c.warning,
search,
};
});
@@ -149,10 +163,16 @@ class GfmAutoComplete {
// Team Members
$input.atwho({
at: '@',
+ alias: 'users',
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
- if (value.username != null) {
- tmpl = GfmAutoComplete.Members.template;
+ const { avatarTag, username, title } = value;
+ if (username != null) {
+ tmpl = GfmAutoComplete.Members.templateFunction({
+ avatarTag,
+ username,
+ title,
+ });
}
return tmpl;
},
@@ -165,7 +185,7 @@ class GfmAutoComplete {
callbacks: {
...this.getDefaultCallbacks(),
beforeSave(members) {
- return $.map(members, (m) => {
+ return $.map(members, m => {
let title = '';
if (m.username == null) {
return m;
@@ -176,7 +196,9 @@ class GfmAutoComplete {
}
const autoCompleteAvatar = m.avatar_url || m.username.charAt(0).toUpperCase();
- const imgAvatar = `<img src="${m.avatar_url}" alt="${m.username}" class="avatar avatar-inline center s26"/>`;
+ const imgAvatar = `<img src="${m.avatar_url}" alt="${
+ m.username
+ }" class="avatar avatar-inline center s26"/>`;
const txtAvatar = `<div class="avatar center avatar-inline s26">${autoCompleteAvatar}</div>`;
return {
@@ -199,7 +221,7 @@ class GfmAutoComplete {
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
if (value.title != null) {
- tmpl = GfmAutoComplete.Issues.template;
+ tmpl = GfmAutoComplete.Issues.templateFunction(value.id, value.title);
}
return tmpl;
},
@@ -209,7 +231,7 @@ class GfmAutoComplete {
callbacks: {
...this.getDefaultCallbacks(),
beforeSave(issues) {
- return $.map(issues, (i) => {
+ return $.map(issues, i => {
if (i.title == null) {
return i;
}
@@ -242,7 +264,7 @@ class GfmAutoComplete {
callbacks: {
...this.getDefaultCallbacks(),
beforeSave(milestones) {
- return $.map(milestones, (m) => {
+ return $.map(milestones, m => {
if (m.title == null) {
return m;
}
@@ -265,7 +287,7 @@ class GfmAutoComplete {
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
if (value.title != null) {
- tmpl = GfmAutoComplete.Issues.template;
+ tmpl = GfmAutoComplete.Issues.templateFunction(value.id, value.title);
}
return tmpl;
},
@@ -275,7 +297,7 @@ class GfmAutoComplete {
callbacks: {
...this.getDefaultCallbacks(),
beforeSave(merges) {
- return $.map(merges, (m) => {
+ return $.map(merges, m => {
if (m.title == null) {
return m;
}
@@ -322,13 +344,20 @@ class GfmAutoComplete {
},
matcher(flag, subtext) {
const match = GfmAutoComplete.defaultMatcher(flag, subtext, this.app.controllers);
- const subtextNodes = subtext.split(/\n+/g).pop().split(GfmAutoComplete.regexSubtext);
+ const subtextNodes = subtext
+ .split(/\n+/g)
+ .pop()
+ .split(GfmAutoComplete.regexSubtext);
// Check if ~ is followed by '/label', '/relabel' or '/unlabel' commands.
- command = subtextNodes.find((node) => {
- if (node === LABEL_COMMAND.LABEL ||
- node === LABEL_COMMAND.RELABEL ||
- node === LABEL_COMMAND.UNLABEL) { return node; }
+ command = subtextNodes.find(node => {
+ if (
+ node === LABEL_COMMAND.LABEL ||
+ node === LABEL_COMMAND.RELABEL ||
+ node === LABEL_COMMAND.UNLABEL
+ ) {
+ return node;
+ }
return null;
});
@@ -360,6 +389,39 @@ class GfmAutoComplete {
});
}
+ setupSnippets($input) {
+ $input.atwho({
+ at: '$',
+ alias: 'snippets',
+ searchKey: 'search',
+ displayTpl(value) {
+ let tmpl = GfmAutoComplete.Loading.template;
+ if (value.title != null) {
+ tmpl = GfmAutoComplete.Issues.templateFunction(value.id, value.title);
+ }
+ return tmpl;
+ },
+ data: GfmAutoComplete.defaultLoadingData,
+ // eslint-disable-next-line no-template-curly-in-string
+ insertTpl: '${atwho-at}${id}',
+ callbacks: {
+ ...this.getDefaultCallbacks(),
+ beforeSave(snippets) {
+ return $.map(snippets, m => {
+ if (m.title == null) {
+ return m;
+ }
+ return {
+ id: m.id,
+ title: sanitize(m.title),
+ search: `${m.id} ${m.title}`,
+ };
+ });
+ },
+ },
+ });
+ }
+
getDefaultCallbacks() {
const fetchData = this.fetchData.bind(this);
@@ -423,13 +485,17 @@ class GfmAutoComplete {
this.loadData($input, at, validEmojiNames);
GfmAutoComplete.glEmojiTag = glEmojiTag;
})
- .catch(() => { this.isLoadingData[at] = false; });
+ .catch(() => {
+ this.isLoadingData[at] = false;
+ });
} else if (dataSource) {
AjaxCache.retrieve(dataSource, true)
- .then((data) => {
+ .then(data => {
this.loadData($input, at, data);
})
- .catch(() => { this.isLoadingData[at] = false; });
+ .catch(() => {
+ this.isLoadingData[at] = false;
+ });
} else {
this.isLoadingData[at] = false;
}
@@ -462,15 +528,16 @@ class GfmAutoComplete {
}
const loadingState = GfmAutoComplete.defaultLoadingData[0];
- return dataToInspect &&
- (dataToInspect === loadingState || dataToInspect.name === loadingState);
+ return dataToInspect && (dataToInspect === loadingState || dataToInspect.name === loadingState);
}
static defaultMatcher(flag, subtext, controllers) {
// The below is taken from At.js source
// Tweaked to commands to start without a space only if char before is a non-word character
// https://github.com/ichord/At.js
- const atSymbolsWithBar = Object.keys(controllers).join('|');
+ const atSymbolsWithBar = Object.keys(controllers)
+ .join('|')
+ .replace(/[$]/, '\\$&');
const atSymbolsWithoutBar = Object.keys(controllers).join('');
const targetSubtext = subtext.split(GfmAutoComplete.regexSubtext).pop();
const resultantFlag = flag.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
@@ -478,7 +545,10 @@ class GfmAutoComplete {
const accentAChar = decodeURI('%C3%80');
const accentYChar = decodeURI('%C3%BF');
- const regexp = new RegExp(`^(?:\\B|[^a-zA-Z0-9_\`${atSymbolsWithoutBar}]|\\s)${resultantFlag}(?!${atSymbolsWithBar})((?:[A-Za-z${accentAChar}-${accentYChar}0-9_'.+-]|[^\\x00-\\x7a])*)$`, 'gi');
+ const regexp = new RegExp(
+ `^(?:\\B|[^a-zA-Z0-9_\`${atSymbolsWithoutBar}]|\\s)${resultantFlag}(?!${atSymbolsWithBar})((?:[A-Za-z${accentAChar}-${accentYChar}0-9_'.+-]|[^\\x00-\\x7a])*)$`,
+ 'gi',
+ );
return regexp.exec(targetSubtext);
}
@@ -497,6 +567,7 @@ GfmAutoComplete.atTypeMap = {
'~': 'labels',
'%': 'milestones',
'/': 'commands',
+ $: 'snippets',
};
// Emoji
@@ -512,17 +583,20 @@ GfmAutoComplete.Emoji = {
};
// Team Members
GfmAutoComplete.Members = {
- // eslint-disable-next-line no-template-curly-in-string
- template: '<li>${avatarTag} ${username} <small>${title}</small></li>',
+ templateFunction({ avatarTag, username, title }) {
+ return `<li>${avatarTag} ${username} <small>${_.escape(title)}</small></li>`;
+ },
};
GfmAutoComplete.Labels = {
- // eslint-disable-next-line no-template-curly-in-string
- template: '<li><span class="dropdown-label-box" style="background: ${color}"></span> ${title}</li>',
+ template:
+ // eslint-disable-next-line no-template-curly-in-string
+ '<li><span class="dropdown-label-box" style="background: ${color}"></span> ${title}</li>',
};
-// Issues and MergeRequests
+// Issues, MergeRequests and Snippets
GfmAutoComplete.Issues = {
- // eslint-disable-next-line no-template-curly-in-string
- template: '<li><small>${id}</small> ${title}</li>',
+ templateFunction(id, title) {
+ return `<li><small>${id}</small> ${_.escape(title)}</li>`;
+ },
};
// Milestones
GfmAutoComplete.Milestones = {
@@ -530,7 +604,8 @@ GfmAutoComplete.Milestones = {
template: '<li>${title}</li>',
};
GfmAutoComplete.Loading = {
- template: '<li style="pointer-events: none;"><i class="fa fa-spinner fa-spin"></i> Loading...</li>',
+ template:
+ '<li style="pointer-events: none;"><i class="fa fa-spinner fa-spin"></i> Loading...</li>',
};
export default GfmAutoComplete;
diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js
index c3959ef3e9e..a8ac2f510a4 100644
--- a/app/assets/javascripts/gl_dropdown.js
+++ b/app/assets/javascripts/gl_dropdown.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, no-underscore-dangle, no-var, one-var, one-var-declaration-per-line, max-len, vars-on-top, wrap-iife, no-unused-vars, no-shadow, no-cond-assign, prefer-arrow-callback, no-return-assign, no-else-return, camelcase, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return, prefer-template, no-param-reassign, no-loop-func */
+/* eslint-disable func-names, no-underscore-dangle, no-var, one-var, vars-on-top, no-unused-vars, no-shadow, no-cond-assign, prefer-arrow-callback, no-return-assign, no-else-return, camelcase, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return, prefer-template, no-param-reassign, no-loop-func */
/* global fuzzaldrinPlus */
import $ from 'jquery';
diff --git a/app/assets/javascripts/gl_field_error.js b/app/assets/javascripts/gl_field_error.js
index 87c6e37b9fb..a5b8c357e8a 100644
--- a/app/assets/javascripts/gl_field_error.js
+++ b/app/assets/javascripts/gl_field_error.js
@@ -116,7 +116,8 @@ export default class GlFieldError {
this.form.focusOnFirstInvalid.apply(this.form);
// For UX, wait til after first invalid submission to check each keyup
- this.inputElement.off('keyup.fieldValidator')
+ this.inputElement
+ .off('keyup.fieldValidator')
.on('keyup.fieldValidator', this.updateValidity.bind(this));
}
diff --git a/app/assets/javascripts/gl_field_errors.js b/app/assets/javascripts/gl_field_errors.js
index b9c51045b1d..d5d5954ce6a 100644
--- a/app/assets/javascripts/gl_field_errors.js
+++ b/app/assets/javascripts/gl_field_errors.js
@@ -16,16 +16,19 @@ export default class GlFieldErrors {
initValidators() {
// register selectors here as needed
const validateSelectors = [':text', ':password', '[type=email]']
- .map(selector => `input${selector}`).join(',');
+ .map(selector => `input${selector}`)
+ .join(',');
- this.state.inputs = this.form.find(validateSelectors).toArray()
+ this.state.inputs = this.form
+ .find(validateSelectors)
+ .toArray()
.filter(input => !input.classList.contains(customValidationFlag))
.map(input => new GlFieldError({ input, formErrors: this }));
this.form.on('submit', GlFieldErrors.catchInvalidFormSubmit);
}
- /* Neccessary to prevent intercept and override invalid form submit
+ /* Necessary to prevent intercept and override invalid form submit
* because Safari & iOS quietly allow form submission when form is invalid
* and prevents disabling of invalid submit button by application.js */
@@ -42,7 +45,7 @@ export default class GlFieldErrors {
/* Public method for triggering validity updates manually */
updateFormValidityState() {
- this.state.inputs.forEach((field) => {
+ this.state.inputs.forEach(field => {
if (field.state.submitted) {
field.updateValidity();
}
@@ -50,8 +53,9 @@ export default class GlFieldErrors {
}
focusOnFirstInvalid() {
- const firstInvalid = this.state.inputs
- .filter(input => !input.inputDomElement.validity.valid)[0];
+ const firstInvalid = this.state.inputs.filter(
+ input => !input.inputDomElement.validity.valid,
+ )[0];
firstInvalid.inputElement.focus();
}
}
diff --git a/app/assets/javascripts/gl_form.js b/app/assets/javascripts/gl_form.js
index e672284a2d0..f842d2d74db 100644
--- a/app/assets/javascripts/gl_form.js
+++ b/app/assets/javascripts/gl_form.js
@@ -39,7 +39,10 @@ export default class GLForm {
this.form.find('.div-dropzone').remove();
this.form.addClass('gfm-form');
// remove notify commit author checkbox for non-commit notes
- gl.utils.disableButtonIfEmptyField(this.form.find('.js-note-text'), this.form.find('.js-comment-button, .js-note-new-discussion'));
+ gl.utils.disableButtonIfEmptyField(
+ this.form.find('.js-note-text'),
+ this.form.find('.js-comment-button, .js-note-new-discussion'),
+ );
this.autoComplete = new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources);
this.autoComplete.setup(this.form.find('.js-gfm-input'), this.enableGFM);
dropzoneInput(this.form);
@@ -55,11 +58,9 @@ export default class GLForm {
}
setupAutosize() {
- this.textarea.off('autosize:resized')
- .on('autosize:resized', this.setHeightData.bind(this));
+ this.textarea.off('autosize:resized').on('autosize:resized', this.setHeightData.bind(this));
- this.textarea.off('mouseup.autosize')
- .on('mouseup.autosize', this.destroyAutosize.bind(this));
+ this.textarea.off('mouseup.autosize').on('mouseup.autosize', this.destroyAutosize.bind(this));
setTimeout(() => {
autosize(this.textarea);
@@ -91,10 +92,14 @@ export default class GLForm {
addEventListeners() {
this.textarea.on('focus', function focusTextArea() {
- $(this).closest('.md-area').addClass('is-focused');
+ $(this)
+ .closest('.md-area')
+ .addClass('is-focused');
});
this.textarea.on('blur', function blurTextArea() {
- $(this).closest('.md-area').removeClass('is-focused');
+ $(this)
+ .closest('.md-area')
+ .removeClass('is-focused');
});
}
}
diff --git a/app/assets/javascripts/group.js b/app/assets/javascripts/group.js
index 4365305c168..903c838e266 100644
--- a/app/assets/javascripts/group.js
+++ b/app/assets/javascripts/group.js
@@ -1,4 +1,5 @@
import $ from 'jquery';
+import { slugifyWithHyphens } from './lib/utils/text_utility';
export default class Group {
constructor() {
@@ -7,17 +8,18 @@ export default class Group {
this.updateHandler = this.update.bind(this);
this.resetHandler = this.reset.bind(this);
if (this.groupName.val() === '') {
- this.groupPath.on('keyup', this.updateHandler);
- this.groupName.on('keydown', this.resetHandler);
+ this.groupName.on('keyup', this.updateHandler);
+ this.groupPath.on('keydown', this.resetHandler);
}
}
update() {
- this.groupName.val(this.groupPath.val());
+ const slug = slugifyWithHyphens(this.groupName.val());
+ this.groupPath.val(slug);
}
reset() {
- this.groupPath.off('keyup', this.updateHandler);
- this.groupName.off('keydown', this.resetHandler);
+ this.groupName.off('keyup', this.updateHandler);
+ this.groupPath.off('keydown', this.resetHandler);
}
}
diff --git a/app/assets/javascripts/group_avatar.js b/app/assets/javascripts/group_avatar.js
index beaac61e887..dcda625f587 100644
--- a/app/assets/javascripts/group_avatar.js
+++ b/app/assets/javascripts/group_avatar.js
@@ -7,8 +7,9 @@ export default function groupAvatar() {
});
$('.js-group-avatar-input').on('change', function onChangeAvatarInput() {
const form = $(this).closest('form');
- // eslint-disable-next-line no-useless-escape
- const filename = $(this).val().replace(/^.*[\\\/]/, '');
+ const filename = $(this)
+ .val()
+ .replace(/^.*[\\\/]/, ''); // eslint-disable-line no-useless-escape
return form.find('.js-avatar-filename').text(filename);
});
}
diff --git a/app/assets/javascripts/group_label_subscription.js b/app/assets/javascripts/group_label_subscription.js
index d33e3a37580..9b74560f914 100644
--- a/app/assets/javascripts/group_label_subscription.js
+++ b/app/assets/javascripts/group_label_subscription.js
@@ -23,7 +23,8 @@ export default class GroupLabelSubscription {
event.preventDefault();
const url = this.$unsubscribeButtons.attr('data-url');
- axios.post(url)
+ axios
+ .post(url)
.then(() => {
this.toggleSubscriptionButtons();
this.$unsubscribeButtons.removeAttr('data-url');
@@ -39,7 +40,8 @@ export default class GroupLabelSubscription {
this.$unsubscribeButtons.attr('data-url', url);
- axios.post(url)
+ axios
+ .post(url)
.then(() => GroupLabelSubscription.setNewTooltip($btn))
.then(() => this.toggleSubscriptionButtons())
.catch(() => flash(__('There was an error when subscribing to this label.')));
@@ -58,6 +60,8 @@ export default class GroupLabelSubscription {
const newTitle = tooltipTitles[type];
$('.js-unsubscribe-button', $button.closest('.label-actions-list'))
- .tooltip('hide').attr('title', newTitle).tooltip('_fixTitle');
+ .tooltip('hide')
+ .attr('title', newTitle)
+ .tooltip('_fixTitle');
}
}
diff --git a/app/assets/javascripts/groups/components/app.vue b/app/assets/javascripts/groups/components/app.vue
index a032f291546..29dc2d6a8a3 100644
--- a/app/assets/javascripts/groups/components/app.vue
+++ b/app/assets/javascripts/groups/components/app.vue
@@ -8,6 +8,7 @@ import { HIDDEN_CLASS } from '~/lib/utils/constants';
import { getParameterByName } from '~/lib/utils/common_utils';
import { mergeUrlParams } from '~/lib/utils/url_utility';
+import { GlLoadingIcon } from '@gitlab/ui';
import eventHub from '../event_hub';
import { COMMON_STR, CONTENT_LIST_CLASS } from '../constants';
import groupsComponent from './groups.vue';
@@ -16,6 +17,7 @@ export default {
components: {
DeprecatedModal,
groupsComponent,
+ GlLoadingIcon,
},
props: {
action: {
diff --git a/app/assets/javascripts/groups/components/group_folder.vue b/app/assets/javascripts/groups/components/group_folder.vue
index bcc7a638346..e885b2b5f41 100644
--- a/app/assets/javascripts/groups/components/group_folder.vue
+++ b/app/assets/javascripts/groups/components/group_folder.vue
@@ -43,18 +43,9 @@ export default {
:parent-group="parentGroup"
:action="action"
/>
- <li
- v-if="hasMoreChildren"
- class="group-row">
- <a
- :href="parentGroup.relativePath"
- class="group-row-contents has-more-items">
- <i
- class="fa fa-external-link"
- aria-hidden="true"
- >
- </i>
- {{ moreChildrenStats }}
+ <li v-if="hasMoreChildren" class="group-row">
+ <a :href="parentGroup.relativePath" class="group-row-contents has-more-items">
+ <i class="fa fa-external-link" aria-hidden="true"> </i> {{ moreChildrenStats }}
</a>
</li>
</ul>
diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue
index 44d6fa26914..688bd37cc56 100644
--- a/app/assets/javascripts/groups/components/group_item.vue
+++ b/app/assets/javascripts/groups/components/group_item.vue
@@ -77,89 +77,46 @@ export default {
</script>
<template>
- <li
- :id="groupDomId"
- :class="rowClass"
- class="group-row"
- @click.stop="onClickRowGroup"
- >
+ <li :id="groupDomId" :class="rowClass" class="group-row" @click.stop="onClickRowGroup">
<div
:class="{ 'project-row-contents': !isGroup }"
class="group-row-contents d-flex justify-content-end align-items-center"
>
- <div
- class="folder-toggle-wrap append-right-4 d-flex align-items-center"
- >
- <item-caret
- :is-group-open="group.isOpen"
- />
- <item-type-icon
- :item-type="group.type"
- :is-group-open="group.isOpen"
- />
+ <div class="folder-toggle-wrap append-right-4 d-flex align-items-center">
+ <item-caret :is-group-open="group.isOpen" />
+ <item-type-icon :item-type="group.type" :is-group-open="group.isOpen" />
</div>
<div
:class="{ 'content-loading': group.isChildrenLoading }"
class="avatar-container s24 d-none d-sm-flex"
>
- <a
- :href="group.relativePath"
- class="no-expand"
- >
- <img
- v-if="hasAvatar"
- :src="group.avatarUrl"
- class="avatar s24"
- />
- <identicon
- v-else
- :entity-id="group.id"
- :entity-name="group.name"
- size-class="s24"
- />
+ <a :href="group.relativePath" class="no-expand">
+ <img v-if="hasAvatar" :src="group.avatarUrl" class="avatar s24" />
+ <identicon v-else :entity-id="group.id" :entity-name="group.name" size-class="s24" />
</a>
</div>
- <div
- class="group-text flex-grow"
- >
- <div
- class="title namespace-title append-right-8"
- >
+ <div class="group-text flex-grow">
+ <div class="title namespace-title append-right-8">
<a
v-tooltip
:href="group.relativePath"
:title="group.fullName"
class="no-expand"
data-placement="bottom"
- >{{
- // ending bracket must be by closing tag to prevent
- // link hover text-decoration from over-extending
- group.name
- }}</a>
- <span
- v-if="group.permission"
- class="user-access-role"
+ >{{
+ // ending bracket must be by closing tag to prevent
+ // link hover text-decoration from over-extending
+ group.name
+ }}</a
>
- {{ group.permission }}
- </span>
+ <span v-if="group.permission" class="user-access-role"> {{ group.permission }} </span>
</div>
- <div
- v-if="group.description"
- class="description"
- >
- <span v-html="group.description">
- </span>
+ <div v-if="group.description" class="description">
+ <span v-html="group.description"> </span>
</div>
</div>
- <item-stats
- :item="group"
- class="group-stats prepend-top-2"
- />
- <item-actions
- v-if="isGroup"
- :group="group"
- :parent-group="parentGroup"
- />
+ <item-stats :item="group" class="group-stats prepend-top-2" />
+ <item-actions v-if="isGroup" :group="group" :parent-group="parentGroup" />
</div>
<group-folder
v-if="group.isOpen && hasChildren"
diff --git a/app/assets/javascripts/groups/components/groups.vue b/app/assets/javascripts/groups/components/groups.vue
index 81b2e5ea37b..f0f5b8395c9 100644
--- a/app/assets/javascripts/groups/components/groups.vue
+++ b/app/assets/javascripts/groups/components/groups.vue
@@ -43,19 +43,9 @@ export default {
<template>
<div class="groups-list-tree-container qa-groups-list-tree-container">
- <div
- v-if="searchEmpty"
- class="has-no-search-results"
- >
- {{ searchEmptyMessage }}
- </div>
- <template
- v-else
- >
- <group-folder
- :groups="groups"
- :action="action"
- />
+ <div v-if="searchEmpty" class="has-no-search-results">{{ searchEmptyMessage }}</div>
+ <template v-else>
+ <group-folder :groups="groups" :action="action" />
<pagination-links
:change="change"
:page-info="pageInfo"
diff --git a/app/assets/javascripts/groups/components/item_actions.vue b/app/assets/javascripts/groups/components/item_actions.vue
index 6e700b8bf8a..a7995865c77 100644
--- a/app/assets/javascripts/groups/components/item_actions.vue
+++ b/app/assets/javascripts/groups/components/item_actions.vue
@@ -46,27 +46,29 @@ export default {
<template>
<div class="controls">
<a
- v-tooltip
v-if="group.canEdit"
+ v-tooltip
:href="group.editPath"
:title="editBtnTitle"
:aria-label="editBtnTitle"
data-container="body"
data-placement="bottom"
- class="edit-group btn no-expand">
- <icon name="settings"/>
+ class="edit-group btn no-expand"
+ >
+ <icon name="settings" />
</a>
<a
- v-tooltip
v-if="group.canLeave"
+ v-tooltip
:href="group.leavePath"
:title="leaveBtnTitle"
:aria-label="leaveBtnTitle"
data-container="body"
data-placement="bottom"
class="leave-group btn no-expand"
- @click.prevent="onLeaveGroup">
- <icon name="leave"/>
+ @click.prevent="onLeaveGroup"
+ >
+ <icon name="leave" />
</a>
</div>
</template>
diff --git a/app/assets/javascripts/groups/components/item_caret.vue b/app/assets/javascripts/groups/components/item_caret.vue
index 2a5bec5e86c..43b9607ea8e 100644
--- a/app/assets/javascripts/groups/components/item_caret.vue
+++ b/app/assets/javascripts/groups/components/item_caret.vue
@@ -21,10 +21,5 @@ export default {
</script>
<template>
- <span class="folder-caret">
- <icon
- :size="12"
- :name="iconClass"
- />
- </span>
+ <span class="folder-caret"> <icon :size="12" :name="iconClass" /> </span>
</template>
diff --git a/app/assets/javascripts/groups/components/item_stats.vue b/app/assets/javascripts/groups/components/item_stats.vue
index 87ab5480c15..bc6851ea2bf 100644
--- a/app/assets/javascripts/groups/components/item_stats.vue
+++ b/app/assets/javascripts/groups/components/item_stats.vue
@@ -1,44 +1,44 @@
<script>
- import icon from '~/vue_shared/components/icon.vue';
- import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
- import {
- ITEM_TYPE,
- VISIBILITY_TYPE_ICON,
- GROUP_VISIBILITY_TYPE,
- PROJECT_VISIBILITY_TYPE,
- } from '../constants';
- import itemStatsValue from './item_stats_value.vue';
+import icon from '~/vue_shared/components/icon.vue';
+import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import {
+ ITEM_TYPE,
+ VISIBILITY_TYPE_ICON,
+ GROUP_VISIBILITY_TYPE,
+ PROJECT_VISIBILITY_TYPE,
+} from '../constants';
+import itemStatsValue from './item_stats_value.vue';
- export default {
- components: {
- icon,
- timeAgoTooltip,
- itemStatsValue,
+export default {
+ components: {
+ icon,
+ timeAgoTooltip,
+ itemStatsValue,
+ },
+ props: {
+ item: {
+ type: Object,
+ required: true,
},
- props: {
- item: {
- type: Object,
- required: true,
- },
+ },
+ computed: {
+ visibilityIcon() {
+ return VISIBILITY_TYPE_ICON[this.item.visibility];
},
- computed: {
- visibilityIcon() {
- return VISIBILITY_TYPE_ICON[this.item.visibility];
- },
- visibilityTooltip() {
- if (this.item.type === ITEM_TYPE.GROUP) {
- return GROUP_VISIBILITY_TYPE[this.item.visibility];
- }
- return PROJECT_VISIBILITY_TYPE[this.item.visibility];
- },
- isProject() {
- return this.item.type === ITEM_TYPE.PROJECT;
- },
- isGroup() {
- return this.item.type === ITEM_TYPE.GROUP;
- },
+ visibilityTooltip() {
+ if (this.item.type === ITEM_TYPE.GROUP) {
+ return GROUP_VISIBILITY_TYPE[this.item.visibility];
+ }
+ return PROJECT_VISIBILITY_TYPE[this.item.visibility];
},
- };
+ isProject() {
+ return this.item.type === ITEM_TYPE.PROJECT;
+ },
+ isGroup() {
+ return this.item.type === ITEM_TYPE.GROUP;
+ },
+ },
+};
</script>
<template>
@@ -76,14 +76,8 @@
css-class="item-visibility"
tooltip-placement="left"
/>
- <div
- v-if="isProject"
- class="last-updated"
- >
- <time-ago-tooltip
- :time="item.updatedAt"
- tooltip-placement="bottom"
- />
+ <div v-if="isProject" class="last-updated">
+ <time-ago-tooltip :time="item.updatedAt" tooltip-placement="bottom" />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/groups/components/item_stats_value.vue b/app/assets/javascripts/groups/components/item_stats_value.vue
index ef9f2bca76c..27b1c632643 100644
--- a/app/assets/javascripts/groups/components/item_stats_value.vue
+++ b/app/assets/javascripts/groups/components/item_stats_value.vue
@@ -1,52 +1,52 @@
<script>
- import tooltip from '~/vue_shared/directives/tooltip';
- import icon from '~/vue_shared/components/icon.vue';
+import tooltip from '~/vue_shared/directives/tooltip';
+import icon from '~/vue_shared/components/icon.vue';
- export default {
- components: {
- icon,
+export default {
+ components: {
+ icon,
+ },
+ directives: {
+ tooltip,
+ },
+ props: {
+ title: {
+ type: String,
+ required: false,
+ default: '',
},
- directives: {
- tooltip,
+ cssClass: {
+ type: String,
+ required: false,
+ default: '',
},
- props: {
- title: {
- type: String,
- required: false,
- default: '',
- },
- cssClass: {
- type: String,
- required: false,
- default: '',
- },
- iconName: {
- type: String,
- required: true,
- },
- tooltipPlacement: {
- type: String,
- required: false,
- default: 'bottom',
- },
- /**
- * value could either be number or string
- * as `memberCount` is always passed as string
- * while `subgroupCount` & `projectCount`
- * are always number
- */
- value: {
- type: [Number, String],
- required: false,
- default: '',
- },
+ iconName: {
+ type: String,
+ required: true,
},
- computed: {
- isValuePresent() {
- return this.value !== '';
- },
+ tooltipPlacement: {
+ type: String,
+ required: false,
+ default: 'bottom',
},
- };
+ /**
+ * value could either be number or string
+ * as `memberCount` is always passed as string
+ * while `subgroupCount` & `projectCount`
+ * are always number
+ */
+ value: {
+ type: [Number, String],
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ isValuePresent() {
+ return this.value !== '';
+ },
+ },
+};
</script>
<template>
@@ -57,12 +57,6 @@
:title="title"
data-container="body"
>
- <icon :name="iconName" />
- <span
- v-if="isValuePresent"
- class="stat-value"
- >
- {{ value }}
- </span>
+ <icon :name="iconName" /> <span v-if="isValuePresent" class="stat-value"> {{ value }} </span>
</span>
</template>
diff --git a/app/assets/javascripts/groups/components/item_type_icon.vue b/app/assets/javascripts/groups/components/item_type_icon.vue
index 118d94d4937..e1ebd03cb5f 100644
--- a/app/assets/javascripts/groups/components/item_type_icon.vue
+++ b/app/assets/javascripts/groups/components/item_type_icon.vue
@@ -29,7 +29,5 @@ export default {
</script>
<template>
- <span class="item-type-icon">
- <icon :name="iconClass"/>
- </span>
+ <span class="item-type-icon"> <icon :name="iconClass" /> </span>
</template>
diff --git a/app/assets/javascripts/groups/index.js b/app/assets/javascripts/groups/index.js
index 0f68f05b523..928f1fe409f 100644
--- a/app/assets/javascripts/groups/index.js
+++ b/app/assets/javascripts/groups/index.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
import Translate from '../vue_shared/translate';
import GroupFilterableList from './groups_filterable_list';
import GroupsStore from './store/groups_store';
@@ -38,7 +39,7 @@ export default (containerId = 'js-groups-tree', endpoint, action = '') => {
},
data() {
const { dataset } = dataEl || this.$options.el;
- const hideProjects = dataset.hideProjects === 'true';
+ const hideProjects = parseBoolean(dataset.hideProjects);
const service = new GroupsService(endpoint || dataset.endpoint);
const store = new GroupsStore(hideProjects);
diff --git a/app/assets/javascripts/groups/new_group_child.js b/app/assets/javascripts/groups/new_group_child.js
index a120d501e35..012177479c6 100644
--- a/app/assets/javascripts/groups/new_group_child.js
+++ b/app/assets/javascripts/groups/new_group_child.js
@@ -37,20 +37,22 @@ export default class NewGroupChild {
getDroplabConfig() {
return {
- InputSetter: [{
- input: this.newGroupChildButton,
- valueAttribute: 'data-value',
- inputAttribute: 'data-action',
- }, {
- input: this.newGroupChildButton,
- valueAttribute: 'data-text',
- }],
+ InputSetter: [
+ {
+ input: this.newGroupChildButton,
+ valueAttribute: 'data-value',
+ inputAttribute: 'data-action',
+ },
+ {
+ input: this.newGroupChildButton,
+ valueAttribute: 'data-text',
+ },
+ ],
};
}
bindEvents() {
- this.newGroupChildButton
- .addEventListener('click', this.onClickNewGroupChildButton.bind(this));
+ this.newGroupChildButton.addEventListener('click', this.onClickNewGroupChildButton.bind(this));
}
onClickNewGroupChildButton(e) {
diff --git a/app/assets/javascripts/groups/store/groups_store.js b/app/assets/javascripts/groups/store/groups_store.js
index 4a7569078a1..16f95d5a0cc 100644
--- a/app/assets/javascripts/groups/store/groups_store.js
+++ b/app/assets/javascripts/groups/store/groups_store.js
@@ -17,13 +17,14 @@ export default class GroupsStore {
}
setSearchedGroups(rawGroups) {
- const formatGroups = groups => groups.map((group) => {
- const formattedGroup = this.formatGroupItem(group);
- if (formattedGroup.children && formattedGroup.children.length) {
- formattedGroup.children = formatGroups(formattedGroup.children);
- }
- return formattedGroup;
- });
+ const formatGroups = groups =>
+ groups.map(group => {
+ const formattedGroup = this.formatGroupItem(group);
+ if (formattedGroup.children && formattedGroup.children.length) {
+ formattedGroup.children = formatGroups(formattedGroup.children);
+ }
+ return formattedGroup;
+ });
if (rawGroups && rawGroups.length) {
this.state.groups = formatGroups(rawGroups);
@@ -62,10 +63,10 @@ export default class GroupsStore {
formatGroupItem(rawGroupItem) {
const groupChildren = rawGroupItem.children || [];
- const groupIsOpen = (groupChildren.length > 0) || false;
- const childrenCount = this.hideProjects ?
- rawGroupItem.subgroup_count :
- rawGroupItem.children_count;
+ const groupIsOpen = groupChildren.length > 0 || false;
+ const childrenCount = this.hideProjects
+ ? rawGroupItem.subgroup_count
+ : rawGroupItem.children_count;
return {
id: rawGroupItem.id,
diff --git a/app/assets/javascripts/groups/transfer_dropdown.js b/app/assets/javascripts/groups/transfer_dropdown.js
index e0eb118ddf7..26510fcdb2a 100644
--- a/app/assets/javascripts/groups/transfer_dropdown.js
+++ b/app/assets/javascripts/groups/transfer_dropdown.js
@@ -22,7 +22,7 @@ export default class TransferDropdown {
search: { fields: ['text'] },
data: extraOptions.concat(this.data),
text: item => item.text,
- clicked: (options) => {
+ clicked: options => {
const { e } = options;
e.preventDefault();
this.assignSelected(options.selectedObj);
diff --git a/app/assets/javascripts/groups_select.js b/app/assets/javascripts/groups_select.js
index e37fc5c4be6..2049760fe29 100644
--- a/app/assets/javascripts/groups_select.js
+++ b/app/assets/javascripts/groups_select.js
@@ -10,20 +10,25 @@ export default function groupsSelect() {
const $select = $(this);
const allAvailable = $select.data('allAvailable');
const skipGroups = $select.data('skipGroups') || [];
+ const parentGroupID = $select.data('parentId');
+ const groupsPath = parentGroupID
+ ? Api.subgroupsPath.replace(':id', parentGroupID)
+ : Api.groupsPath;
+
$select.select2({
placeholder: 'Search for a group',
allowClear: $select.hasClass('allowClear'),
multiple: $select.hasClass('multiselect'),
minimumInputLength: 0,
ajax: {
- url: Api.buildUrl(Api.groupsPath),
+ url: Api.buildUrl(groupsPath),
dataType: 'json',
quietMillis: 250,
transport(params) {
axios[params.type.toLowerCase()](params.url, {
params: params.data,
})
- .then((res) => {
+ .then(res => {
const results = res.data || [];
const headers = normalizeHeaders(res.headers);
const currentPage = parseInt(headers['X-PAGE'], 10) || 0;
@@ -36,7 +41,8 @@ export default function groupsSelect() {
more,
},
});
- }).catch(params.error);
+ })
+ .catch(params.error);
},
data(search, page) {
return {
@@ -68,7 +74,9 @@ export default function groupsSelect() {
}
},
formatResult(object) {
- return `<div class='group-result'> <div class='group-name'>${object.full_name}</div> <div class='group-path'>${object.full_path}</div> </div>`;
+ return `<div class='group-result'> <div class='group-name'>${
+ object.full_name
+ }</div> <div class='group-path'>${object.full_path}</div> </div>`;
},
formatSelection(object) {
return object.full_name;
diff --git a/app/assets/javascripts/header.js b/app/assets/javascripts/header.js
index 4ae3a714bee..2fa7a219ea8 100644
--- a/app/assets/javascripts/header.js
+++ b/app/assets/javascripts/header.js
@@ -1,5 +1,10 @@
import $ from 'jquery';
+import Vue from 'vue';
+import Translate from '~/vue_shared/translate';
import { highCountTrim } from '~/lib/utils/text_utility';
+import SetStatusModalTrigger from './set_status_modal/set_status_modal_trigger.vue';
+import SetStatusModalWrapper from './set_status_modal/set_status_modal_wrapper.vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
/**
* Updates todo counter when todos are toggled.
@@ -17,3 +22,54 @@ export default function initTodoToggle() {
$todoPendingCount.toggleClass('hidden', parsedCount === 0);
});
}
+
+document.addEventListener('DOMContentLoaded', () => {
+ const setStatusModalTriggerEl = document.querySelector('.js-set-status-modal-trigger');
+ const setStatusModalWrapperEl = document.querySelector('.js-set-status-modal-wrapper');
+
+ if (setStatusModalTriggerEl || setStatusModalWrapperEl) {
+ Vue.use(Translate);
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: setStatusModalTriggerEl,
+ data() {
+ const { hasStatus } = this.$options.el.dataset;
+
+ return {
+ hasStatus: parseBoolean(hasStatus),
+ };
+ },
+ render(createElement) {
+ return createElement(SetStatusModalTrigger, {
+ props: {
+ hasStatus: this.hasStatus,
+ },
+ });
+ },
+ });
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: setStatusModalWrapperEl,
+ data() {
+ const { currentEmoji, currentMessage } = this.$options.el.dataset;
+
+ return {
+ currentEmoji,
+ currentMessage,
+ };
+ },
+ render(createElement) {
+ const { currentEmoji, currentMessage } = this;
+
+ return createElement(SetStatusModalWrapper, {
+ props: {
+ currentEmoji,
+ currentMessage,
+ },
+ });
+ },
+ });
+ }
+});
diff --git a/app/assets/javascripts/helpers/avatar_helper.js b/app/assets/javascripts/helpers/avatar_helper.js
index d3b1d0f11fd..35ac7b2629c 100644
--- a/app/assets/javascripts/helpers/avatar_helper.js
+++ b/app/assets/javascripts/helpers/avatar_helper.js
@@ -19,7 +19,9 @@ export function renderIdenticon(entity, options = {}) {
const bgClass = getIdenticonBackgroundClass(entity.id);
const title = getIdenticonTitle(entity.name);
- return `<div class="avatar identicon ${_.escape(sizeClass)} ${_.escape(bgClass)}">${_.escape(title)}</div>`;
+ return `<div class="avatar identicon ${_.escape(sizeClass)} ${_.escape(bgClass)}">${_.escape(
+ title,
+ )}</div>`;
}
export function renderAvatar(entity, options = {}) {
diff --git a/app/assets/javascripts/ide/components/activity_bar.vue b/app/assets/javascripts/ide/components/activity_bar.vue
index 2cebacc1c4c..a1f66ff764d 100644
--- a/app/assets/javascripts/ide/components/activity_bar.vue
+++ b/app/assets/javascripts/ide/components/activity_bar.vue
@@ -37,7 +37,7 @@ export default {
<button
v-tooltip
:class="{
- active: currentActivityView === $options.activityBarViews.edit
+ active: currentActivityView === $options.activityBarViews.edit,
}"
:title="s__('IDE|Edit')"
:aria-label="s__('IDE|Edit')"
@@ -45,18 +45,16 @@ export default {
data-placement="right"
type="button"
class="ide-sidebar-link js-ide-edit-mode"
- @click.prevent="changedActivityView($event, $options.activityBarViews.edit)"
+ @click.prevent="changedActivityView($event, $options.activityBarViews.edit);"
>
- <icon
- name="code"
- />
+ <icon name="code" />
</button>
</li>
<li>
<button
v-tooltip
:class="{
- active: currentActivityView === $options.activityBarViews.review
+ active: currentActivityView === $options.activityBarViews.review,
}"
:title="s__('IDE|Review')"
:aria-label="s__('IDE|Review')"
@@ -64,18 +62,16 @@ export default {
data-placement="right"
type="button"
class="ide-sidebar-link js-ide-review-mode"
- @click.prevent="changedActivityView($event, $options.activityBarViews.review)"
+ @click.prevent="changedActivityView($event, $options.activityBarViews.review);"
>
- <icon
- name="file-modified"
- />
+ <icon name="file-modified" />
</button>
</li>
<li v-show="hasChanges">
<button
v-tooltip
:class="{
- active: currentActivityView === $options.activityBarViews.commit
+ active: currentActivityView === $options.activityBarViews.commit,
}"
:title="s__('IDE|Commit')"
:aria-label="s__('IDE|Commit')"
@@ -83,11 +79,9 @@ export default {
data-placement="right"
type="button"
class="ide-sidebar-link js-ide-commit-mode"
- @click.prevent="changedActivityView($event, $options.activityBarViews.commit)"
+ @click.prevent="changedActivityView($event, $options.activityBarViews.commit);"
>
- <icon
- name="commit"
- />
+ <icon name="commit" />
</button>
</li>
</ul>
diff --git a/app/assets/javascripts/ide/components/branches/item.vue b/app/assets/javascripts/ide/components/branches/item.vue
index cc3e84e3f77..4dff3f7e755 100644
--- a/app/assets/javascripts/ide/components/branches/item.vue
+++ b/app/assets/javascripts/ide/components/branches/item.vue
@@ -32,28 +32,14 @@ export default {
</script>
<template>
- <a
- :href="branchHref"
- class="btn-link d-flex align-items-center"
- >
+ <a :href="branchHref" class="btn-link d-flex align-items-center">
<span class="d-flex append-right-default ide-search-list-current-icon">
- <icon
- v-if="isActive"
- :size="18"
- name="mobile-issue-close"
- />
+ <icon v-if="isActive" :size="18" name="mobile-issue-close" />
</span>
<span>
- <strong>
- {{ item.name }}
- </strong>
- <span
- class="ide-merge-request-project-path d-block mt-1"
- >
- Updated
- <timeago
- :time="item.committedDate || ''"
- />
+ <strong> {{ item.name }} </strong>
+ <span class="ide-merge-request-project-path d-block mt-1">
+ Updated <timeago :time="item.committedDate || ''" />
</span>
</span>
</a>
diff --git a/app/assets/javascripts/ide/components/branches/search_list.vue b/app/assets/javascripts/ide/components/branches/search_list.vue
index bf0ff6e35ec..3cfdc1a367a 100644
--- a/app/assets/javascripts/ide/components/branches/search_list.vue
+++ b/app/assets/javascripts/ide/components/branches/search_list.vue
@@ -2,12 +2,14 @@
import { mapActions, mapState } from 'vuex';
import _ from 'underscore';
import Icon from '~/vue_shared/components/icon.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
import Item from './item.vue';
export default {
components: {
Item,
Icon,
+ GlLoadingIcon,
},
data() {
return {
@@ -60,17 +62,13 @@ export default {
<div class="position-relative">
<input
ref="searchInput"
- :placeholder="__('Search branches')"
v-model="search"
+ :placeholder="__('Search branches')"
type="search"
class="form-control dropdown-input-field"
@input="searchBranches"
/>
- <icon
- :size="18"
- name="search"
- class="input-icon"
- />
+ <icon :size="18" name="search" class="input-icon" />
</div>
</div>
<div class="dropdown-content ide-merge-requests-dropdown-content d-flex">
@@ -79,26 +77,13 @@ export default {
:size="2"
class="mt-3 mb-3 align-self-center ml-auto mr-auto"
/>
- <ul
- v-else
- class="mb-3 w-100"
- >
+ <ul v-else class="mb-3 w-100">
<template v-if="hasBranches">
- <li
- v-for="item in branches"
- :key="item.name"
- >
- <item
- :item="item"
- :project-id="currentProjectId"
- :is-active="isActiveBranch(item)"
- />
+ <li v-for="item in branches" :key="item.name">
+ <item :item="item" :project-id="currentProjectId" :is-active="isActiveBranch(item)" />
</li>
</template>
- <li
- v-else
- class="ide-search-list-empty d-flex align-items-center justify-content-center"
- >
+ <li v-else class="ide-search-list-empty d-flex align-items-center justify-content-center">
<template v-if="hasNoSearchResults">
{{ __('No branches found') }}
</template>
diff --git a/app/assets/javascripts/ide/components/changed_file_icon.vue b/app/assets/javascripts/ide/components/changed_file_icon.vue
deleted file mode 100644
index 720ae11aaa6..00000000000
--- a/app/assets/javascripts/ide/components/changed_file_icon.vue
+++ /dev/null
@@ -1,90 +0,0 @@
-<script>
-import tooltip from '~/vue_shared/directives/tooltip';
-import Icon from '~/vue_shared/components/icon.vue';
-import { pluralize } from '~/lib/utils/text_utility';
-import { __, sprintf } from '~/locale';
-import { getCommitIconMap } from '../utils';
-
-export default {
- components: {
- Icon,
- },
- directives: {
- tooltip,
- },
- props: {
- file: {
- type: Object,
- required: true,
- },
- showTooltip: {
- type: Boolean,
- required: false,
- default: false,
- },
- showStagedIcon: {
- type: Boolean,
- required: false,
- default: false,
- },
- forceModifiedIcon: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- computed: {
- changedIcon() {
- const suffix = !this.file.changed && this.file.staged && !this.showStagedIcon ? '-solid' : '';
-
- if (this.forceModifiedIcon) return `file-modified${suffix}`;
-
- return `${getCommitIconMap(this.file).icon}${suffix}`;
- },
- changedIconClass() {
- return `ide-${this.changedIcon} float-left`;
- },
- tooltipTitle() {
- if (!this.showTooltip) return undefined;
-
- const type = this.file.tempFile ? 'addition' : 'modification';
-
- if (this.file.changed && !this.file.staged) {
- return sprintf(__('Unstaged %{type}'), {
- type,
- });
- } else if (!this.file.changed && this.file.staged) {
- return sprintf(__('Staged %{type}'), {
- type,
- });
- } else if (this.file.changed && this.file.staged) {
- return sprintf(__('Unstaged and staged %{type}'), {
- type: pluralize(type),
- });
- }
-
- return undefined;
- },
- showIcon() {
- return this.file.changed || this.file.tempFile || this.file.staged || this.file.deleted;
- },
- },
-};
-</script>
-
-<template>
- <span
- v-tooltip
- :title="tooltipTitle"
- data-container="body"
- data-placement="right"
- class="ide-file-changed-icon"
- >
- <icon
- v-if="showIcon"
- :name="changedIcon"
- :size="12"
- :css-classes="changedIconClass"
- />
- </span>
-</template>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
index a8b5c7a16d0..d360dc42cd3 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
@@ -57,11 +57,7 @@ export default {
:disabled="currentBranch && !currentBranch.can_push"
:title="$options.currentBranchPermissionsTooltip"
>
- <span
- class="ide-radio-label"
- v-html="commitToCurrentBranchText"
- >
- </span>
+ <span class="ide-radio-label" v-html="commitToCurrentBranchText"> </span>
</radio-group>
<radio-group
:value="$options.commitToNewBranch"
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue b/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
index c3ca147e850..5119dbf32eb 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/editor_header.vue
@@ -3,7 +3,7 @@ import $ from 'jquery';
import { mapActions } from 'vuex';
import { __ } from '~/locale';
import FileIcon from '~/vue_shared/components/file_icon.vue';
-import ChangedFileIcon from '../changed_file_icon.vue';
+import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
export default {
components: {
@@ -42,17 +42,9 @@ export default {
<template>
<div class="d-flex ide-commit-editor-header align-items-center">
- <file-icon
- :file-name="activeFile.name"
- :size="16"
- class="mr-2"
- />
- <strong class="mr-2">
- {{ activeFile.path }}
- </strong>
- <changed-file-icon
- :file="activeFile"
- />
+ <file-icon :file-name="activeFile.name" :size="16" class="mr-2" />
+ <strong class="mr-2"> {{ activeFile.path }} </strong>
+ <changed-file-icon :file="activeFile" class="ml-0" />
<div class="ml-auto">
<button
v-if="!isStaged"
@@ -65,7 +57,7 @@ export default {
<button
:class="{
'btn-success': !isStaged,
- 'btn-warning': isStaged
+ 'btn-warning': isStaged,
}"
type="button"
class="btn btn-inverted"
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/empty_state.vue b/app/assets/javascripts/ide/components/commit_sidebar/empty_state.vue
index d0a60d647e5..a23bae8e4c7 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/empty_state.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/empty_state.vue
@@ -13,22 +13,12 @@ export default {
v-if="!lastCommitMsg"
class="multi-file-commit-panel-section ide-commit-empty-state js-empty-state"
>
- <div
- class="ide-commit-empty-state-container"
- >
- <div class="svg-content svg-80">
- <img :src="noChangesStateSvgPath" />
- </div>
+ <div class="ide-commit-empty-state-container">
+ <div class="svg-content svg-80"><img :src="noChangesStateSvgPath" /></div>
<div class="append-right-default prepend-left-default">
- <div
- class="text-content text-center"
- >
- <h4>
- {{ __('No changes') }}
- </h4>
- <p>
- {{ __('Edit files in the editor and commit changes here') }}
- </p>
+ <div class="text-content text-center">
+ <h4>{{ __('No changes') }}</h4>
+ <p>{{ __('Edit files in the editor and commit changes here') }}</p>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/form.vue b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
index ee8eb206980..f7ed7006874 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/form.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/form.vue
@@ -96,7 +96,7 @@ export default {
<div
:class="{
'is-compact': isCompact,
- 'is-full': !isCompact
+ 'is-full': !isCompact,
}"
:style="{
height: componentHeight ? `${componentHeight}px` : null,
@@ -109,45 +109,31 @@ export default {
@enter="enterTransition"
@after-enter="afterEndTransition"
>
- <div
- v-if="isCompact"
- ref="compactEl"
- class="commit-form-compact"
- >
+ <div v-if="isCompact" ref="compactEl" class="commit-form-compact">
<button
:disabled="!hasChanges"
type="button"
- class="btn btn-primary btn-sm btn-block"
+ class="btn btn-primary btn-sm btn-block qa-begin-commit-button"
@click="toggleIsSmall"
>
{{ __('Commit…') }}
</button>
- <p
- class="text-center"
- v-html="overviewText"
- ></p>
+ <p class="text-center" v-html="overviewText"></p>
</div>
- <form
- v-if="!isCompact"
- ref="formEl"
- @submit.prevent.stop="commitChanges"
- >
- <transition name="fade">
- <success-message
- v-show="lastCommitMsg"
- />
- </transition>
+ <form v-if="!isCompact" ref="formEl" @submit.prevent.stop="commitChanges">
+ <transition name="fade"> <success-message v-show="lastCommitMsg" /> </transition>
<commit-message-field
:text="commitMessage"
:placeholder="preBuiltCommitMessage"
@input="updateCommitMessage"
+ @submit="commitChanges"
/>
<div class="clearfix prepend-top-15">
<actions />
<loading-button
:loading="submitCommitLoading"
:label="commitButtonText"
- container-class="btn btn-success btn-sm float-left"
+ container-class="btn btn-success btn-sm float-left qa-commit-button"
@click="commitChanges"
/>
<button
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list.vue b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
index 3fdd35ad228..a1094570275 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list.vue
@@ -93,33 +93,20 @@ export default {
</script>
<template>
- <div
- class="ide-commit-list-container"
- >
- <header
- class="multi-file-commit-panel-header d-flex mb-0"
- >
- <div
- class="d-flex align-items-center flex-fill"
- >
- <icon
- v-once
- :name="iconName"
- :size="18"
- class="append-right-8"
- />
- <strong>
- {{ titleText }}
- </strong>
+ <div class="ide-commit-list-container">
+ <header class="multi-file-commit-panel-header d-flex mb-0">
+ <div class="d-flex align-items-center flex-fill">
+ <icon v-once :name="iconName" :size="18" class="append-right-8" />
+ <strong> {{ titleText }} </strong>
<div class="d-flex ml-auto">
<button
- v-tooltip
ref="actionBtn"
+ v-tooltip
:title="actionBtnText"
:aria-label="actionBtnText"
:disabled="!filesLength"
:class="{
- 'disabled-content': !filesLength
+ 'disabled-content': !filesLength,
}"
type="button"
class="d-flex ide-staged-action-btn p-0 border-0 align-items-center"
@@ -128,20 +115,16 @@ export default {
data-boundary="viewport"
@click="actionBtnClicked"
>
- <icon
- :name="actionBtnIcon"
- :size="16"
- class="ml-auto mr-auto"
- />
+ <icon :name="actionBtnIcon" :size="16" class="ml-auto mr-auto" />
</button>
<button
- v-tooltip
v-if="!stagedList"
+ v-tooltip
:title="__('Discard all changes')"
:aria-label="__('Discard all changes')"
:disabled="!filesLength"
:class="{
- 'disabled-content': !filesLength
+ 'disabled-content': !filesLength,
}"
type="button"
class="d-flex ide-staged-action-btn p-0 border-0 align-items-center"
@@ -150,23 +133,13 @@ export default {
data-boundary="viewport"
@click="openDiscardModal"
>
- <icon
- :size="16"
- name="remove-all"
- class="ml-auto mr-auto"
- />
+ <icon :size="16" name="remove-all" class="ml-auto mr-auto" />
</button>
</div>
</div>
</header>
- <ul
- v-if="filesLength"
- class="multi-file-commit-list list-unstyled append-bottom-0"
- >
- <li
- v-for="file in fileList"
- :key="file.key"
- >
+ <ul v-if="filesLength" class="multi-file-commit-list list-unstyled append-bottom-0">
+ <li v-for="file in fileList" :key="file.key">
<list-item
:file="file"
:action-component="itemActionComponent"
@@ -176,10 +149,7 @@ export default {
/>
</li>
</ul>
- <p
- v-else
- class="multi-file-commit-list form-text text-muted text-center"
- >
+ <p v-else class="multi-file-commit-list form-text text-muted text-center">
{{ emptyStateText }}
</p>
<gl-modal
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue b/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue
index d376a004e84..3156a398113 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list_collapsed.vue
@@ -38,14 +38,18 @@ export default {
return this.modifiedFilesLength ? 'multi-file-modified' : '';
},
additionsTooltip() {
- return sprintf(n__('1 %{type} addition', '%{count} %{type} additions', this.addedFilesLength), {
- type: this.title.toLowerCase(),
- count: this.addedFilesLength,
- });
+ return sprintf(
+ n__('1 %{type} addition', '%{count} %{type} additions', this.addedFilesLength),
+ {
+ type: this.title.toLowerCase(),
+ count: this.addedFilesLength,
+ },
+ );
},
modifiedTooltip() {
return sprintf(
- n__('1 %{type} modification', '%{count} %{type} modifications', this.modifiedFilesLength), {
+ n__('1 %{type} modification', '%{count} %{type} modifications', this.modifiedFilesLength),
+ {
type: this.title.toLowerCase(),
count: this.modifiedFilesLength,
},
@@ -65,9 +69,7 @@ export default {
</script>
<template>
- <div
- class="multi-file-commit-list-collapsed text-center"
- >
+ <div class="multi-file-commit-list-collapsed text-center">
<div
v-tooltip
:title="titleTooltip"
@@ -75,11 +77,7 @@ export default {
data-placement="left"
class="append-bottom-15"
>
- <icon
- v-once
- :name="iconName"
- :size="18"
- />
+ <icon v-once :name="iconName" :size="18" />
</div>
<div
v-tooltip
@@ -88,11 +86,7 @@ export default {
data-placement="left"
class="append-bottom-10"
>
- <icon
- :name="additionIconName"
- :size="18"
- :css-classes="addedFilesIconClass"
- />
+ <icon :name="additionIconName" :size="18" :css-classes="addedFilesIconClass" />
</div>
{{ addedFilesLength }}
<div
@@ -102,11 +96,7 @@ export default {
data-placement="left"
class="prepend-top-10 append-bottom-10"
>
- <icon
- :name="modifiedIconName"
- :size="18"
- :css-classes="modifiedFilesClass"
- />
+ <icon :name="modifiedIconName" :size="18" :css-classes="modifiedFilesClass" />
</div>
{{ modifiedFilesLength }}
</div>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
index 10c78a80302..4be4b02ac1e 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/list_item.vue
@@ -99,7 +99,7 @@ export default {
v-tooltip
:title="tooltipTitle"
:class="{
- 'is-active': isActive
+ 'is-active': isActive,
}"
class="multi-file-commit-list-path w-100 border-0 ml-0 mr-0"
role="button"
@@ -107,23 +107,12 @@ export default {
@click="openFileInEditor"
>
<span class="multi-file-commit-list-file-path d-flex align-items-center">
- <file-icon
- :file-name="file.name"
- class="append-right-8"
- />{{ file.name }}
+ <file-icon :file-name="file.name" class="append-right-8" />{{ file.name }}
</span>
<div class="ml-auto d-flex align-items-center">
<div class="d-flex align-items-center ide-commit-list-changed-icon">
- <icon
- :name="iconName"
- :size="16"
- :css-classes="iconClass"
- />
+ <icon :name="iconName" :size="16" :css-classes="iconClass" />
</div>
- <component
- :is="actionComponent"
- :path="file.path"
- />
</div>
</div>
</div>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue b/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
index 37ca108fafc..6f1ded91753 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/message_field.vue
@@ -49,6 +49,10 @@ export default {
onInput(e) {
this.$emit('input', e.target.value);
},
+ onCtrlEnter() {
+ if (!this.isFocused) return;
+ this.$emit('submit');
+ },
updateIsFocused(isFocused) {
this.isFocused = isFocused;
},
@@ -71,24 +75,16 @@ export default {
<fieldset class="common-note-form ide-commit-message-field">
<div
:class="{
- 'is-focused': isFocused
+ 'is-focused': isFocused,
}"
class="md-area"
>
- <div
- v-once
- class="md-header"
- >
+ <div v-once class="md-header">
<ul class="nav-links">
<li>
{{ __('Commit Message') }}
- <span
- v-popover="$options.popoverOptions"
- class="form-text text-muted prepend-left-10"
- >
- <icon
- name="question"
- />
+ <span v-popover="$options.popoverOptions" class="form-text text-muted prepend-left-10">
+ <icon name="question" />
</span>
</li>
</ul>
@@ -97,22 +93,13 @@ export default {
<div class="ide-commit-message-highlights-container">
<div
:style="{
- transform: `translate3d(0, ${-scrollTop}px, 0)`
+ transform: `translate3d(0, ${-scrollTop}px, 0)`,
}"
class="note-textarea highlights monospace"
>
- <div
- v-for="(line, index) in allLines"
- :key="index"
- >
- <span
- v-text="line.text"
- >
- </span><mark
- v-show="line.highlightedText"
- v-text="line.highlightedText"
- >
- </mark>
+ <div v-for="(line, index) in allLines" :key="index">
+ <span v-text="line.text"> </span
+ ><mark v-show="line.highlightedText" v-text="line.highlightedText"> </mark>
</div>
</div>
</div>
@@ -124,8 +111,10 @@ export default {
name="commit-message"
@scroll="handleScroll"
@input="onInput"
- @focus="updateIsFocused(true)"
- @blur="updateIsFocused(false)"
+ @focus="updateIsFocused(true);"
+ @blur="updateIsFocused(false);"
+ @keydown.ctrl.enter="onCtrlEnter"
+ @keydown.meta.enter="onCtrlEnter"
>
</textarea>
</div>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue b/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
index 969e2aa61c4..3525084b1cb 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
@@ -56,7 +56,7 @@ export default {
v-tooltip
:title="tooltipTitle"
:class="{
- 'is-disabled': disabled
+ 'is-disabled': disabled,
}"
>
<input
@@ -65,27 +65,18 @@ export default {
:disabled="disabled"
type="radio"
name="commit-action"
- @change="updateCommitAction($event.target.value)"
+ @change="updateCommitAction($event.target.value);"
/>
<span class="prepend-left-10">
- <span
- v-if="label"
- class="ide-radio-label"
- >
- {{ label }}
- </span>
- <slot v-else></slot>
+ <span v-if="label" class="ide-radio-label"> {{ label }} </span> <slot v-else></slot>
</span>
</label>
- <div
- v-if="commitAction === value && showInput"
- class="ide-commit-new-branch"
- >
+ <div v-if="commitAction === value && showInput" class="ide-commit-new-branch">
<input
:placeholder="newBranchName"
type="text"
class="form-control monospace"
- @input="updateBranchName($event.target.value)"
+ @input="updateBranchName($event.target.value);"
/>
</div>
</fieldset>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/stage_button.vue b/app/assets/javascripts/ide/components/commit_sidebar/stage_button.vue
index 8a1836a5c92..02c2004d495 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/stage_button.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/stage_button.vue
@@ -25,10 +25,7 @@ export default {
return `discard-file-${this.path}`;
},
modalTitle() {
- return sprintf(
- __('Discard changes to %{path}?'),
- { path: this.path },
- );
+ return sprintf(__('Discard changes to %{path}?'), { path: this.path });
},
},
methods: {
@@ -41,10 +38,7 @@ export default {
</script>
<template>
- <div
- v-once
- class="multi-file-discard-btn d-flex"
- >
+ <div v-once class="multi-file-discard-btn d-flex">
<button
v-tooltip
:aria-label="__('Stage changes')"
@@ -54,13 +48,9 @@ export default {
data-container="body"
data-boundary="viewport"
data-placement="bottom"
- @click.stop.prevent="stageChange(path)"
+ @click.stop.prevent="stageChange(path);"
>
- <icon
- :size="16"
- name="mobile-issue-close"
- class="ml-auto mr-auto"
- />
+ <icon :size="16" name="mobile-issue-close" class="ml-auto mr-auto" />
</button>
<button
v-tooltip
@@ -73,18 +63,14 @@ export default {
data-placement="bottom"
@click.stop.prevent="showDiscardModal"
>
- <icon
- :size="16"
- name="remove"
- class="ml-auto mr-auto"
- />
+ <icon :size="16" name="remove" class="ml-auto mr-auto" />
</button>
<gl-modal
:id="modalId"
:header-title-text="modalTitle"
:footer-primary-button-text="__('Discard changes')"
footer-primary-button-variant="danger"
- @submit="discardFileChanges(path)"
+ @submit="discardFileChanges(path);"
>
{{ __("You will loose all changes you've made to this file. This action cannot be undone.") }}
</gl-modal>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/success_message.vue b/app/assets/javascripts/ide/components/commit_sidebar/success_message.vue
index a6df91b79c2..b1d5de8682d 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/success_message.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/success_message.vue
@@ -9,23 +9,11 @@ export default {
</script>
<template>
- <div
- class="multi-file-commit-panel-success-message"
- aria-live="assertive"
- >
- <div class="svg-content svg-80">
- <img
- :src="committedStateSvgPath"
- alt=""
- />
- </div>
+ <div class="multi-file-commit-panel-success-message" aria-live="assertive">
+ <div class="svg-content svg-80"><img :src="committedStateSvgPath" alt="" /></div>
<div class="append-right-default prepend-left-default">
- <div
- class="text-content text-center"
- >
- <h4>
- {{ __('All changes are committed') }}
- </h4>
+ <div class="text-content text-center">
+ <h4>{{ __('All changes are committed') }}</h4>
<p v-html="lastCommitMsg"></p>
</div>
</div>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/unstage_button.vue b/app/assets/javascripts/ide/components/commit_sidebar/unstage_button.vue
index 86c40602074..ce41fcdb087 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/unstage_button.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/unstage_button.vue
@@ -23,10 +23,7 @@ export default {
</script>
<template>
- <div
- v-once
- class="multi-file-discard-btn d-flex"
- >
+ <div v-once class="multi-file-discard-btn d-flex">
<button
v-tooltip
:aria-label="__('Unstage changes')"
@@ -36,13 +33,9 @@ export default {
data-container="body"
data-boundary="viewport"
data-placement="bottom"
- @click.stop.prevent="unstageChange(path)"
+ @click.stop.prevent="unstageChange(path);"
>
- <icon
- :size="16"
- name="redo"
- class="ml-auto mr-auto"
- />
+ <icon :size="16" name="redo" class="ml-auto mr-auto" />
</button>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/editor_mode_dropdown.vue b/app/assets/javascripts/ide/components/editor_mode_dropdown.vue
index 95598c9aca6..5f99261ec39 100644
--- a/app/assets/javascripts/ide/components/editor_mode_dropdown.vue
+++ b/app/assets/javascripts/ide/components/editor_mode_dropdown.vue
@@ -30,16 +30,8 @@ export default {
</script>
<template>
- <div
- class="dropdown"
- >
- <button
- type="button"
- class="btn btn-link"
- data-toggle="dropdown"
- >
- {{ __('Edit') }}
- </button>
+ <div class="dropdown">
+ <button type="button" class="btn btn-link" data-toggle="dropdown">{{ __('Edit') }}</button>
<div class="dropdown-menu dropdown-menu-selectable dropdown-open-left">
<ul>
<li>
@@ -48,11 +40,9 @@ export default {
'is-active': viewer === $options.viewerTypes.mr,
}"
href="#"
- @click.prevent="changeMode($options.viewerTypes.mr)"
+ @click.prevent="changeMode($options.viewerTypes.mr);"
>
- <strong class="dropdown-menu-inner-title">
- {{ mergeReviewLine }}
- </strong>
+ <strong class="dropdown-menu-inner-title"> {{ mergeReviewLine }} </strong>
<span class="dropdown-menu-inner-content">
{{ __('Compare changes with the merge request target branch') }}
</span>
@@ -64,7 +54,7 @@ export default {
'is-active': viewer === $options.viewerTypes.diff,
}"
href="#"
- @click.prevent="changeMode($options.viewerTypes.diff)"
+ @click.prevent="changeMode($options.viewerTypes.diff);"
>
<strong class="dropdown-menu-inner-title">{{ __('Reviewing') }}</strong>
<span class="dropdown-menu-inner-content">
diff --git a/app/assets/javascripts/ide/components/error_message.vue b/app/assets/javascripts/ide/components/error_message.vue
index a20dc0a7006..22113692968 100644
--- a/app/assets/javascripts/ide/components/error_message.vue
+++ b/app/assets/javascripts/ide/components/error_message.vue
@@ -1,7 +1,11 @@
<script>
import { mapActions } from 'vuex';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
+ components: {
+ GlLoadingIcon,
+ },
props: {
message: {
type: Object,
@@ -39,15 +43,9 @@ export default {
</script>
<template>
- <div
- class="flash-container flash-container-page"
- @click="clickFlash"
- >
+ <div class="flash-container flash-container-page" @click="clickFlash">
<div class="flash-alert">
- <span
- v-html="message.text"
- >
- </span>
+ <span v-html="message.text"> </span>
<button
v-if="message.action"
type="button"
@@ -55,10 +53,7 @@ export default {
@click.stop.prevent="clickAction"
>
{{ message.actionText }}
- <gl-loading-icon
- v-show="isLoading"
- inline
- />
+ <gl-loading-icon v-show="isLoading" inline />
</button>
</div>
</div>
diff --git a/app/assets/javascripts/ide/components/external_link.vue b/app/assets/javascripts/ide/components/external_link.vue
index e24fe5bbccb..954f84cea17 100644
--- a/app/assets/javascripts/ide/components/external_link.vue
+++ b/app/assets/javascripts/ide/components/external_link.vue
@@ -20,10 +20,7 @@ export default {
</script>
<template>
- <div
- v-if="showButtons"
- class="pull-right ide-btn-group"
- >
+ <div v-if="showButtons" class="pull-right ide-btn-group">
<a
:href="file.permalink"
:title="s__('IDE|Open in file view')"
@@ -31,11 +28,7 @@ export default {
rel="noopener noreferrer"
>
<span class="vertical-align-middle">Open in file view</span>
- <icon
- :size="16"
- name="external-link"
- css-classes="vertical-align-middle space-right"
- />
+ <icon :size="16" name="external-link" css-classes="vertical-align-middle space-right" />
</a>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/file_finder/index.vue b/app/assets/javascripts/ide/components/file_finder/index.vue
index 0ba33053717..bb391912572 100644
--- a/app/assets/javascripts/ide/components/file_finder/index.vue
+++ b/app/assets/javascripts/ide/components/file_finder/index.vue
@@ -164,27 +164,22 @@ export default {
</script>
<template>
- <div
- class="ide-file-finder-overlay"
- @mousedown.self="toggleFileFinder(false)"
- >
- <div
- class="dropdown-menu diff-file-changes ide-file-finder show"
- >
+ <div class="ide-file-finder-overlay" @mousedown.self="toggleFileFinder(false);">
+ <div class="dropdown-menu diff-file-changes ide-file-finder show">
<div class="dropdown-input">
<input
ref="searchInput"
- :placeholder="__('Search files')"
v-model="searchText"
+ :placeholder="__('Search files')"
type="search"
class="dropdown-input-field"
autocomplete="off"
- @keydown="onKeydown($event)"
- @keyup="onKeyup($event)"
+ @keydown="onKeydown($event);"
+ @keyup="onKeyup($event);"
/>
<i
:class="{
- hidden: showClearInputButton
+ hidden: showClearInputButton,
}"
aria-hidden="true"
class="fa fa-search dropdown-input-search"
@@ -192,7 +187,7 @@ export default {
<i
:aria-label="__('Clear search input')"
:class="{
- show: showClearInputButton
+ show: showClearInputButton,
}"
role="button"
class="fa fa-times dropdown-input-clear"
@@ -200,17 +195,9 @@ export default {
></i>
</div>
<div>
- <virtual-list
- ref="virtualScrollList"
- :size="listHeight"
- :remain="listShowCount"
- wtag="ul"
- >
+ <virtual-list ref="virtualScrollList" :size="listHeight" :remain="listShowCount" wtag="ul">
<template v-if="filteredBlobsLength">
- <li
- v-for="(file, index) in filteredBlobs"
- :key="file.key"
- >
+ <li v-for="(file, index) in filteredBlobs" :key="file.key">
<item
:file="file"
:search-text="searchText"
@@ -223,10 +210,7 @@ export default {
/>
</li>
</template>
- <li
- v-else
- class="dropdown-menu-empty-item"
- >
+ <li v-else class="dropdown-menu-empty-item">
<div class="append-right-default prepend-left-default prepend-top-8 append-bottom-8">
<template v-if="loading">
{{ __('Loading...') }}
diff --git a/app/assets/javascripts/ide/components/file_finder/item.vue b/app/assets/javascripts/ide/components/file_finder/item.vue
index f5252ce7706..83e80d50aff 100644
--- a/app/assets/javascripts/ide/components/file_finder/item.vue
+++ b/app/assets/javascripts/ide/components/file_finder/item.vue
@@ -1,7 +1,7 @@
<script>
import fuzzaldrinPlus from 'fuzzaldrin-plus';
import FileIcon from '../../../vue_shared/components/file_icon.vue';
-import ChangedFileIcon from '../changed_file_icon.vue';
+import ChangedFileIcon from '../../../vue_shared/components/changed_file_icon.vue';
const MAX_PATH_LENGTH = 60;
@@ -74,40 +74,31 @@ export default {
css-classes="diff-file-changed-icon append-right-8"
/>
<span class="diff-changed-file-content append-right-8">
- <strong
- class="diff-changed-file-name"
- >
+ <strong class="diff-changed-file-name">
<span
- v-for="(char, index) in file.name.split('')"
- :key="index + char"
+ v-for="(char, charIndex) in file.name.split('')"
+ :key="charIndex + char"
:class="{
- highlighted: nameSearchTextOccurences.indexOf(index) >= 0,
+ highlighted: nameSearchTextOccurences.indexOf(charIndex) >= 0,
}"
v-text="char"
>
</span>
</strong>
- <span
- class="diff-changed-file-path prepend-top-5"
- >
+ <span class="diff-changed-file-path prepend-top-5">
<span
- v-for="(char, index) in pathWithEllipsis.split('')"
- :key="index + char"
+ v-for="(char, charIndex) in pathWithEllipsis.split('')"
+ :key="charIndex + char"
:class="{
- highlighted: pathSearchTextOccurences.indexOf(index) >= 0,
+ highlighted: pathSearchTextOccurences.indexOf(charIndex) >= 0,
}"
v-text="char"
>
</span>
</span>
</span>
- <span
- v-if="file.changed || file.tempFile"
- class="diff-changed-stats"
- >
- <changed-file-icon
- :file="file"
- />
+ <span v-if="file.changed || file.tempFile" class="diff-changed-stats">
+ <changed-file-icon :file="file" />
</span>
</button>
</template>
diff --git a/app/assets/javascripts/ide/components/file_row_extra.vue b/app/assets/javascripts/ide/components/file_row_extra.vue
index 44a360ab909..d6673cf0421 100644
--- a/app/assets/javascripts/ide/components/file_row_extra.vue
+++ b/app/assets/javascripts/ide/components/file_row_extra.vue
@@ -3,8 +3,8 @@ import { mapGetters } from 'vuex';
import { n__, __, sprintf } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
+import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
import NewDropdown from './new_dropdown/index.vue';
-import ChangedFileIcon from './changed_file_icon.vue';
import MrFileIcon from './mr_file_icon.vue';
export default {
@@ -69,13 +69,8 @@ export default {
<template>
<div class="float-right ide-file-icon-holder">
- <mr-file-icon
- v-if="file.mrChange"
- />
- <span
- v-if="showTreeChangesCount"
- class="ide-tree-changes"
- >
+ <mr-file-icon v-if="file.mrChange" />
+ <span v-if="showTreeChangesCount" class="ide-tree-changes">
{{ changesCount }}
<icon
v-tooltip
diff --git a/app/assets/javascripts/ide/components/file_templates/bar.vue b/app/assets/javascripts/ide/components/file_templates/bar.vue
index 23be5f45f16..d459e3b43d3 100644
--- a/app/assets/javascripts/ide/components/file_templates/bar.vue
+++ b/app/assets/javascripts/ide/components/file_templates/bar.vue
@@ -47,10 +47,8 @@ export default {
</script>
<template>
- <div class="d-flex align-items-center ide-file-templates">
- <strong class="append-right-default">
- {{ __('File templates') }}
- </strong>
+ <div class="d-flex align-items-center ide-file-templates qa-file-templates-bar">
+ <strong class="append-right-default"> {{ __('File templates') }} </strong>
<dropdown
:data="templateTypes"
:label="selectedTemplateType.name || __('Choose a type...')"
@@ -63,16 +61,11 @@ export default {
:is-async-data="true"
:searchable="true"
:title="__('File templates')"
- class="mr-2"
+ class="mr-2 qa-file-template-dropdown"
@click="selectTemplate"
/>
<transition name="fade">
- <button
- v-show="updateSuccess"
- type="button"
- class="btn btn-default"
- @click="undo"
- >
+ <button v-show="updateSuccess" type="button" class="btn btn-default" @click="undo">
{{ __('Undo') }}
</button>
</transition>
diff --git a/app/assets/javascripts/ide/components/file_templates/dropdown.vue b/app/assets/javascripts/ide/components/file_templates/dropdown.vue
index ef1f6de3a86..414ea9c7d4d 100644
--- a/app/assets/javascripts/ide/components/file_templates/dropdown.vue
+++ b/app/assets/javascripts/ide/components/file_templates/dropdown.vue
@@ -2,10 +2,12 @@
import $ from 'jquery';
import { mapActions, mapState } from 'vuex';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
components: {
DropdownButton,
+ GlLoadingIcon,
},
props: {
data: {
@@ -73,48 +75,23 @@ export default {
<template>
<div class="dropdown">
- <dropdown-button
- :toggle-text="label"
- data-display="static"
- />
+ <dropdown-button :toggle-text="label" data-display="static" />
<div class="dropdown-menu pb-0">
- <div
- v-if="title"
- class="dropdown-title ml-0 mr-0"
- >
- {{ title }}
- </div>
- <div
- v-if="!showLoading && searchable"
- class="dropdown-input"
- >
+ <div v-if="title" class="dropdown-title ml-0 mr-0">{{ title }}</div>
+ <div v-if="!showLoading && searchable" class="dropdown-input">
<input
v-model="search"
:placeholder="__('Filter...')"
type="search"
- class="dropdown-input-field"
+ class="dropdown-input-field qa-dropdown-filter-input"
/>
- <i
- aria-hidden="true"
- class="fa fa-search dropdown-input-search"
- ></i>
+ <i aria-hidden="true" class="fa fa-search dropdown-input-search"></i>
</div>
<div class="dropdown-content">
- <gl-loading-icon
- v-if="showLoading"
- :size="2"
- />
+ <gl-loading-icon v-if="showLoading" :size="2" />
<ul v-else>
- <li
- v-for="(item, index) in outputData"
- :key="index"
- >
- <button
- type="button"
- @click="clickItem(item)"
- >
- {{ item.name }}
- </button>
+ <li v-for="(item, index) in outputData" :key="index">
+ <button type="button" @click="clickItem(item);">{{ item.name }}</button>
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index a3add3b778f..caec8779cac 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -1,4 +1,5 @@
<script>
+import Vue from 'vue';
import Mousetrap from 'mousetrap';
import { mapActions, mapState, mapGetters } from 'vuex';
import { __ } from '~/locale';
@@ -22,10 +23,16 @@ export default {
IdeStatusBar,
RepoEditor,
FindFile,
- RightPane,
ErrorMessage,
CommitEditorHeader,
},
+ props: {
+ rightPaneComponent: {
+ type: Vue.Component,
+ required: false,
+ default: () => RightPane,
+ },
+ },
computed: {
...mapState([
'openFiles',
@@ -36,7 +43,7 @@ export default {
'currentProjectId',
'errorMessage',
]),
- ...mapGetters(['activeFile', 'hasChanges', 'someUncommitedChanges', 'isCommitModeActive']),
+ ...mapGetters(['activeFile', 'hasChanges', 'someUncommittedChanges', 'isCommitModeActive']),
},
mounted() {
window.onbeforeunload = e => this.onBeforeUnload(e);
@@ -56,7 +63,7 @@ export default {
onBeforeUnload(e = {}) {
const returnValue = __('Are you sure you want to lose unsaved changes?');
- if (!this.someUncommitedChanges) return undefined;
+ if (!this.someUncommittedChanges) return undefined;
Object.assign(e, {
returnValue,
@@ -81,27 +88,13 @@ export default {
<template>
<article class="ide position-relative d-flex flex-column align-items-stretch">
- <error-message
- v-if="errorMessage"
- :message="errorMessage"
- />
- <div
- class="ide-view flex-grow d-flex"
- >
- <find-file
- v-show="fileFindVisible"
- />
+ <error-message v-if="errorMessage" :message="errorMessage" />
+ <div class="ide-view flex-grow d-flex">
+ <find-file v-show="fileFindVisible" />
<ide-sidebar />
- <div
- class="multi-file-edit-pane"
- >
- <template
- v-if="activeFile"
- >
- <commit-editor-header
- v-if="isCommitModeActive"
- :active-file="activeFile"
- />
+ <div class="multi-file-edit-pane">
+ <template v-if="activeFile">
+ <commit-editor-header v-if="isCommitModeActive" :active-file="activeFile" />
<repo-tabs
v-else
:active-file="activeFile"
@@ -110,32 +103,20 @@ export default {
:has-changes="hasChanges"
:merge-request-id="currentMergeRequestId"
/>
- <repo-editor
- :file="activeFile"
- class="multi-file-edit-pane-content"
- />
+ <repo-editor :file="activeFile" class="multi-file-edit-pane-content" />
</template>
- <template
- v-else
- >
- <div
- v-once
- class="ide-empty-state"
- >
+ <template v-else>
+ <div v-once class="ide-empty-state">
<div class="row js-empty-state">
<div class="col-12">
- <div class="svg-content svg-250">
- <img :src="emptyStateSvgPath" />
- </div>
+ <div class="svg-content svg-250"><img :src="emptyStateSvgPath" /></div>
</div>
<div class="col-12">
<div class="text-content text-center">
- <h4>
- Welcome to the GitLab IDE
- </h4>
+ <h4>Welcome to the GitLab IDE</h4>
<p>
- Select a file from the left sidebar to begin editing.
- Afterwards, you'll be able to commit your changes.
+ Select a file from the left sidebar to begin editing. Afterwards, you'll be able
+ to commit your changes.
</p>
</div>
</div>
@@ -143,11 +124,9 @@ export default {
</div>
</template>
</div>
- <right-pane
- v-if="currentProjectId"
- />
+ <component :is="rightPaneComponent" v-if="currentProjectId" />
</div>
- <ide-status-bar :file="activeFile"/>
+ <ide-status-bar :file="activeFile" />
<new-modal />
</article>
</template>
diff --git a/app/assets/javascripts/ide/components/ide_project_header.vue b/app/assets/javascripts/ide/components/ide_project_header.vue
index 6cf190288e8..36bc7c70196 100644
--- a/app/assets/javascripts/ide/components/ide_project_header.vue
+++ b/app/assets/javascripts/ide/components/ide_project_header.vue
@@ -16,18 +16,10 @@ export default {
<template>
<div class="context-header ide-context-header">
- <a
- :href="project.web_url"
- :title="s__('IDE|Go to project')"
- >
- <project-avatar-default
- :project="project"
- :size="48"
- />
+ <a :href="project.web_url" :title="s__('IDE|Go to project')">
+ <project-avatar-default :project="project" :size="48" />
<span class="ide-sidebar-project-title">
- <span class="sidebar-context-title">
- {{ project.name }}
- </span>
+ <span class="sidebar-context-title"> {{ project.name }} </span>
<span class="sidebar-context-title text-secondary">
{{ project.path_with_namespace }}
</span>
diff --git a/app/assets/javascripts/ide/components/ide_review.vue b/app/assets/javascripts/ide/components/ide_review.vue
index d09c99050fe..901b8892e80 100644
--- a/app/assets/javascripts/ide/components/ide_review.vue
+++ b/app/assets/javascripts/ide/components/ide_review.vue
@@ -42,13 +42,8 @@ export default {
</script>
<template>
- <ide-tree-list
- :viewer-type="viewer"
- header-class="ide-review-header"
- >
- <template
- slot="header"
- >
+ <ide-tree-list :viewer-type="viewer" header-class="ide-review-header">
+ <template slot="header">
<div class="ide-review-button-holder">
{{ __('Review') }}
<editor-mode-dropdown
@@ -63,12 +58,12 @@ export default {
{{ __('Latest changes') }}
</template>
<template v-else-if="showMergeRequestText">
- {{ __('Merge request') }}
- (<a
+ {{ __('Merge request') }} (<a
v-if="currentMergeRequest"
:href="currentMergeRequest.web_url"
v-text="mergeRequestId"
- ></a>)
+ ></a
+ >)
</template>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/ide_side_bar.vue b/app/assets/javascripts/ide/components/ide_side_bar.vue
index 4771c58a11d..6178d2b1fc7 100644
--- a/app/assets/javascripts/ide/components/ide_side_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_side_bar.vue
@@ -1,6 +1,6 @@
<script>
import { mapState, mapGetters } from 'vuex';
-import SkeletonLoadingContainer from '~/vue_shared/components/skeleton_loading_container.vue';
+import { GlSkeletonLoading } from '@gitlab/ui';
import IdeTree from './ide_tree.vue';
import ResizablePanel from './resizable_panel.vue';
import ActivityBar from './activity_bar.vue';
@@ -13,7 +13,7 @@ import { activityBarViews } from '../constants';
export default {
components: {
- SkeletonLoadingContainer,
+ GlSkeletonLoading,
ResizablePanel,
ActivityBar,
CommitSection,
@@ -24,18 +24,12 @@ export default {
IdeProjectHeader,
},
computed: {
- ...mapState([
- 'loading',
- 'currentActivityView',
- 'changedFiles',
- 'stagedFiles',
- 'lastCommitMsg',
- ]),
- ...mapGetters(['currentProject', 'someUncommitedChanges']),
+ ...mapState(['loading', 'currentActivityView', 'changedFiles', 'stagedFiles', 'lastCommitMsg']),
+ ...mapGetters(['currentProject', 'someUncommittedChanges']),
showSuccessMessage() {
return (
this.currentActivityView === activityBarViews.edit &&
- (this.lastCommitMsg && !this.someUncommitedChanges)
+ (this.lastCommitMsg && !this.someUncommittedChanges)
);
},
},
@@ -43,34 +37,21 @@ export default {
</script>
<template>
- <resizable-panel
- :collapsible="false"
- :initial-width="340"
- side="left"
- class="flex-column"
- >
+ <resizable-panel :collapsible="false" :initial-width="340" side="left" class="flex-column">
<template v-if="loading">
<div class="multi-file-commit-panel-inner">
- <div
- v-for="n in 3"
- :key="n"
- class="multi-file-loading-container"
- >
- <skeleton-loading-container />
+ <div v-for="n in 3" :key="n" class="multi-file-loading-container">
+ <gl-skeleton-loading />
</div>
</div>
</template>
<template v-else>
- <ide-project-header
- :project="currentProject"
- />
+ <ide-project-header :project="currentProject" />
<div class="ide-context-body d-flex flex-fill">
<activity-bar />
<div class="multi-file-commit-panel-inner">
<div class="multi-file-commit-panel-inner-content">
- <component
- :is="currentActivityView"
- />
+ <component :is="currentActivityView" />
</div>
<commit-form />
</div>
diff --git a/app/assets/javascripts/ide/components/ide_status_bar.vue b/app/assets/javascripts/ide/components/ide_status_bar.vue
index 715dc1bfb42..e2e0acc22b1 100644
--- a/app/assets/javascripts/ide/components/ide_status_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_status_bar.vue
@@ -50,7 +50,9 @@ export default {
this.stopPipelinePolling();
},
methods: {
- ...mapActions(['setRightPane']),
+ ...mapActions('rightPane', {
+ openRightPane: 'open',
+ }),
...mapActions('pipelines', ['fetchLatestPipeline', 'stopPipelinePolling']),
startTimer() {
this.intervalId = setInterval(() => {
@@ -77,18 +79,12 @@ export default {
<template>
<footer class="ide-status-bar">
- <div
- v-if="lastCommit"
- class="ide-status-branch"
- >
- <span
- v-if="latestPipeline && latestPipeline.details"
- class="ide-status-pipeline"
- >
+ <div v-if="lastCommit" class="ide-status-branch">
+ <span v-if="latestPipeline && latestPipeline.details" class="ide-status-pipeline">
<button
type="button"
class="p-0 border-0 h-50"
- @click="setRightPane($options.rightSidebarViews.pipelines)"
+ @click="openRightPane($options.rightSidebarViews.pipelines);"
>
<ci-icon
v-tooltip
@@ -97,24 +93,21 @@ export default {
/>
</button>
Pipeline
- <a
- :href="latestPipeline.details.status.details_path"
- class="monospace">#{{ latestPipeline.id }}</a>
- {{ latestPipeline.details.status.text }}
- for
+ <a :href="latestPipeline.details.status.details_path" class="monospace"
+ >#{{ latestPipeline.id }}</a
+ >
+ {{ latestPipeline.details.status.text }} for
</span>
- <icon
- name="commit"
- />
+ <icon name="commit" />
<a
v-tooltip
:title="lastCommit.message"
:href="getCommitPath(lastCommit.short_id)"
class="commit-sha"
- >{{ lastCommit.short_id }}</a>
- by
- {{ lastCommit.author_name }}
+ >{{ lastCommit.short_id }}</a
+ >
+ by {{ lastCommit.author_name }}
<time
v-tooltip
:datetime="lastCommit.committed_date"
@@ -125,28 +118,11 @@ export default {
{{ lastCommitFormatedAge }}
</time>
</div>
- <div
- v-if="file"
- class="ide-status-file"
- >
- {{ file.name }}
- </div>
- <div
- v-if="file"
- class="ide-status-file"
- >
- {{ file.eol }}
- </div>
- <div
- v-if="file && !file.binary"
- class="ide-status-file">
+ <div v-if="file" class="ide-status-file">{{ file.name }}</div>
+ <div v-if="file" class="ide-status-file">{{ file.eol }}</div>
+ <div v-if="file && !file.binary" class="ide-status-file">
{{ file.editorRow }}:{{ file.editorColumn }}
</div>
- <div
- v-if="file"
- class="ide-status-file"
- >
- {{ file.fileLanguage }}
- </div>
+ <div v-if="file" class="ide-status-file">{{ file.fileLanguage }}</div>
</footer>
</template>
diff --git a/app/assets/javascripts/ide/components/ide_tree.vue b/app/assets/javascripts/ide/components/ide_tree.vue
index 39d46a91731..9fc21adae7c 100644
--- a/app/assets/javascripts/ide/components/ide_tree.vue
+++ b/app/assets/javascripts/ide/components/ide_tree.vue
@@ -34,20 +34,16 @@ export default {
</script>
<template>
- <ide-tree-list
- viewer-type="editor"
- >
- <template
- slot="header"
- >
+ <ide-tree-list viewer-type="editor">
+ <template slot="header">
{{ __('Edit') }}
<div class="ide-tree-actions ml-auto d-flex">
<new-entry-button
:label="__('New file')"
:show-label="false"
- class="d-flex border-0 p-0 mr-3"
+ class="d-flex border-0 p-0 mr-3 qa-new-file"
icon="doc-new"
- @click="openNewEntryModal({ type: 'blob' })"
+ @click="openNewEntryModal({ type: 'blob' });"
/>
<upload
:show-label="false"
@@ -60,7 +56,7 @@ export default {
:show-label="false"
class="d-flex border-0 p-0"
icon="folder-new"
- @click="openNewEntryModal({ type: 'tree' })"
+ @click="openNewEntryModal({ type: 'tree' });"
/>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/ide_tree_list.vue b/app/assets/javascripts/ide/components/ide_tree_list.vue
index e658d1bf956..81374f26645 100644
--- a/app/assets/javascripts/ide/components/ide_tree_list.vue
+++ b/app/assets/javascripts/ide/components/ide_tree_list.vue
@@ -1,7 +1,7 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import Icon from '~/vue_shared/components/icon.vue';
-import SkeletonLoadingContainer from '~/vue_shared/components/skeleton_loading_container.vue';
+import { GlSkeletonLoading } from '@gitlab/ui';
import FileRow from '~/vue_shared/components/file_row.vue';
import NavDropdown from './nav_dropdown.vue';
import FileRowExtra from './file_row_extra.vue';
@@ -9,7 +9,7 @@ import FileRowExtra from './file_row_extra.vue';
export default {
components: {
Icon,
- SkeletonLoadingContainer,
+ GlSkeletonLoading,
NavDropdown,
FileRow,
},
@@ -42,29 +42,18 @@ export default {
</script>
<template>
- <div
- class="ide-file-list"
- >
+ <div class="ide-file-list qa-file-list">
<template v-if="showLoading">
- <div
- v-for="n in 3"
- :key="n"
- class="multi-file-loading-container"
- >
- <skeleton-loading-container />
+ <div v-for="n in 3" :key="n" class="multi-file-loading-container">
+ <gl-skeleton-loading />
</div>
</template>
<template v-else>
- <header
- :class="headerClass"
- class="ide-tree-header"
- >
+ <header :class="headerClass" class="ide-tree-header">
<nav-dropdown />
<slot name="header"></slot>
</header>
- <div
- class="ide-tree-body h-100"
- >
+ <div class="ide-tree-body h-100">
<file-row
v-for="file in currentTree.tree"
:key="file.key"
diff --git a/app/assets/javascripts/ide/components/jobs/detail.vue b/app/assets/javascripts/ide/components/jobs/detail.vue
index f884c26ed6a..e8fe5fc696d 100644
--- a/app/assets/javascripts/ide/components/jobs/detail.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail.vue
@@ -75,20 +75,12 @@ export default {
<template>
<div class="ide-pipeline build-page d-flex flex-column flex-fill">
<header class="ide-job-header d-flex align-items-center">
- <button
- class="btn btn-default btn-sm d-flex"
- @click="setDetailJob(null)"
- >
- <icon
- name="chevron-left"
- />
- {{ __('View jobs') }}
+ <button class="btn btn-default btn-sm d-flex" @click="setDetailJob(null);">
+ <icon name="chevron-left" /> {{ __('View jobs') }}
</button>
</header>
<div class="top-bar d-flex border-left-0">
- <job-description
- :job="detailJob"
- />
+ <job-description :job="detailJob" />
<div class="controllers ml-auto">
<a
v-tooltip
@@ -99,28 +91,13 @@ export default {
class="controllers-buttons"
target="_blank"
>
- <i
- aria-hidden="true"
- class="fa fa-file-text-o"
- ></i>
+ <i aria-hidden="true" class="fa fa-file-text-o"></i>
</a>
- <scroll-button
- :disabled="isScrolledToTop"
- direction="up"
- @click="scrollUp"
- />
- <scroll-button
- :disabled="isScrolledToBottom"
- direction="down"
- @click="scrollDown"
- />
+ <scroll-button :disabled="isScrolledToTop" direction="up" @click="scrollUp" />
+ <scroll-button :disabled="isScrolledToBottom" direction="down" @click="scrollDown" />
</div>
</div>
- <pre
- ref="buildTrace"
- class="build-trace mb-0 h-100"
- @scroll="scrollBuildLog"
- >
+ <pre ref="buildTrace" class="build-trace mb-0 h-100" @scroll="scrollBuildLog">
<code
v-show="!detailJob.isLoading"
class="bash"
diff --git a/app/assets/javascripts/ide/components/jobs/detail/description.vue b/app/assets/javascripts/ide/components/jobs/detail/description.vue
index 7e24974f7e5..7280fba9e7a 100644
--- a/app/assets/javascripts/ide/components/jobs/detail/description.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail/description.vue
@@ -23,24 +23,11 @@ export default {
<template>
<div class="d-flex align-items-center">
- <ci-icon
- :status="job.status"
- :borderless="true"
- :size="24"
- class="d-flex"
- />
+ <ci-icon :status="job.status" :borderless="true" :size="24" class="d-flex" />
<span class="prepend-left-8">
{{ job.name }}
- <a
- :href="job.path"
- target="_blank"
- class="ide-external-link"
- >
- {{ jobId }}
- <icon
- :size="12"
- name="external-link"
- />
+ <a :href="job.path" target="_blank" class="ide-external-link">
+ {{ jobId }} <icon :size="12" name="external-link" />
</a>
</span>
</div>
diff --git a/app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue b/app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue
index 103a407987f..5674d3ffa80 100644
--- a/app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail/scroll_button.vue
@@ -58,9 +58,7 @@ export default {
type="button"
@click="clickedScroll"
>
- <icon
- :name="iconName"
- />
+ <icon :name="iconName" />
</button>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/jobs/item.vue b/app/assets/javascripts/ide/components/jobs/item.vue
index 7f4695a0451..be8bf77bba0 100644
--- a/app/assets/javascripts/ide/components/jobs/item.vue
+++ b/app/assets/javascripts/ide/components/jobs/item.vue
@@ -26,17 +26,9 @@ export default {
<template>
<div class="ide-job-item">
- <job-description
- :job="job"
- class="append-right-default"
- />
+ <job-description :job="job" class="append-right-default" />
<div class="ml-auto align-self-center">
- <button
- v-if="job.started"
- type="button"
- class="btn btn-default btn-sm"
- @click="clickViewLog"
- >
+ <button v-if="job.started" type="button" class="btn btn-default btn-sm" @click="clickViewLog">
{{ __('View log') }}
</button>
</div>
diff --git a/app/assets/javascripts/ide/components/jobs/list.vue b/app/assets/javascripts/ide/components/jobs/list.vue
index acd37605d16..2cb5050c3f0 100644
--- a/app/assets/javascripts/ide/components/jobs/list.vue
+++ b/app/assets/javascripts/ide/components/jobs/list.vue
@@ -1,10 +1,12 @@
<script>
import { mapActions } from 'vuex';
+import { GlLoadingIcon } from '@gitlab/ui';
import Stage from './stage.vue';
export default {
components: {
Stage,
+ GlLoadingIcon,
},
props: {
stages: {
@@ -24,11 +26,7 @@ export default {
<template>
<div>
- <gl-loading-icon
- v-if="loading && !stages.length"
- :size="2"
- class="prepend-top-default"
- />
+ <gl-loading-icon v-if="loading && !stages.length" :size="2" class="prepend-top-default" />
<template v-else>
<stage
v-for="stage in stages"
diff --git a/app/assets/javascripts/ide/components/jobs/stage.vue b/app/assets/javascripts/ide/components/jobs/stage.vue
index 1c474acb4b2..b1be25ea602 100644
--- a/app/assets/javascripts/ide/components/jobs/stage.vue
+++ b/app/assets/javascripts/ide/components/jobs/stage.vue
@@ -1,4 +1,5 @@
<script>
+import { GlLoadingIcon } from '@gitlab/ui';
import tooltip from '../../../vue_shared/directives/tooltip';
import Icon from '../../../vue_shared/components/icon.vue';
import CiIcon from '../../../vue_shared/components/ci_icon.vue';
@@ -12,6 +13,7 @@ export default {
Icon,
CiIcon,
Item,
+ GlLoadingIcon,
},
props: {
stage: {
@@ -54,56 +56,33 @@ export default {
</script>
<template>
- <div
- class="ide-stage card prepend-top-default"
- >
+ <div class="ide-stage card prepend-top-default">
<div
:class="{
- 'border-bottom-0': stage.isCollapsed
+ 'border-bottom-0': stage.isCollapsed,
}"
class="card-header"
@click="toggleCollapsed"
>
- <ci-icon
- :status="stage.status"
- :size="24"
- />
+ <ci-icon :status="stage.status" :size="24" />
<strong
- v-tooltip="showTooltip"
ref="stageTitle"
+ v-tooltip="showTooltip"
:title="showTooltip ? stage.name : null"
data-container="body"
class="prepend-left-8 ide-stage-title"
>
{{ stage.name }}
</strong>
- <div
- v-if="!stage.isLoading || stage.jobs.length"
- class="append-right-8 prepend-left-4"
- >
- <span class="badge badge-pill">
- {{ jobsCount }}
- </span>
+ <div v-if="!stage.isLoading || stage.jobs.length" class="append-right-8 prepend-left-4">
+ <span class="badge badge-pill"> {{ jobsCount }} </span>
</div>
- <icon
- :name="collapseIcon"
- css-classes="ide-stage-collapse-icon"
- />
+ <icon :name="collapseIcon" css-classes="ide-stage-collapse-icon" />
</div>
- <div
- v-show="!stage.isCollapsed"
- class="card-body"
- >
- <gl-loading-icon
- v-if="showLoadingIcon"
- />
+ <div v-show="!stage.isCollapsed" class="card-body">
+ <gl-loading-icon v-if="showLoadingIcon" />
<template v-else>
- <item
- v-for="job in stage.jobs"
- :key="job.id"
- :job="job"
- @clickViewLog="clickViewLog"
- />
+ <item v-for="job in stage.jobs" :key="job.id" :job="job" @clickViewLog="clickViewLog" />
</template>
</div>
</div>
diff --git a/app/assets/javascripts/ide/components/merge_requests/info.vue b/app/assets/javascripts/ide/components/merge_requests/info.vue
index 199d2e74971..73ec992466c 100644
--- a/app/assets/javascripts/ide/components/merge_requests/info.vue
+++ b/app/assets/javascripts/ide/components/merge_requests/info.vue
@@ -19,13 +19,8 @@ export default {
<template>
<div class="ide-merge-request-info h-100 d-flex flex-column">
<div class="detail-page-header">
- <icon
- name="git-merge"
- class="align-self-center append-right-8"
- />
- <strong>
- !{{ currentMergeRequest.iid }}
- </strong>
+ <icon name="git-merge" class="align-self-center append-right-8" />
+ <strong> !{{ currentMergeRequest.iid }} </strong>
</div>
<div class="issuable-details">
<title-component
diff --git a/app/assets/javascripts/ide/components/merge_requests/item.vue b/app/assets/javascripts/ide/components/merge_requests/item.vue
index 0c4ea80ba08..60889c893cf 100644
--- a/app/assets/javascripts/ide/components/merge_requests/item.vue
+++ b/app/assets/javascripts/ide/components/merge_requests/item.vue
@@ -40,24 +40,13 @@ export default {
</script>
<template>
- <a
- :href="mergeRequestHref"
- class="btn-link d-flex align-items-center"
- >
+ <a :href="mergeRequestHref" class="btn-link d-flex align-items-center">
<span class="d-flex append-right-default ide-search-list-current-icon">
- <icon
- v-if="isActive"
- :size="18"
- name="mobile-issue-close"
- />
+ <icon v-if="isActive" :size="18" name="mobile-issue-close" />
</span>
<span>
- <strong>
- {{ item.title }}
- </strong>
- <span class="ide-merge-request-project-path d-block mt-1">
- {{ pathWithID }}
- </span>
+ <strong> {{ item.title }} </strong>
+ <span class="ide-merge-request-project-path d-block mt-1"> {{ pathWithID }} </span>
</span>
</a>
</template>
diff --git a/app/assets/javascripts/ide/components/merge_requests/list.vue b/app/assets/javascripts/ide/components/merge_requests/list.vue
index c8343e77860..ac2b0eddfb4 100644
--- a/app/assets/javascripts/ide/components/merge_requests/list.vue
+++ b/app/assets/javascripts/ide/components/merge_requests/list.vue
@@ -3,6 +3,7 @@ import { mapActions, mapState } from 'vuex';
import _ from 'underscore';
import { __ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
import Item from './item.vue';
import TokenedInput from '../shared/tokened_input.vue';
@@ -16,6 +17,7 @@ export default {
TokenedInput,
Item,
Icon,
+ GlLoadingIcon,
},
data() {
return {
@@ -37,14 +39,10 @@ export default {
return this.hasSearchFocus && !this.search && !this.currentSearchType;
},
type() {
- return this.currentSearchType
- ? this.currentSearchType.type
- : '';
+ return this.currentSearchType ? this.currentSearchType.type : '';
},
searchTokens() {
- return this.currentSearchType
- ? [this.currentSearchType]
- : [];
+ return this.currentSearchType ? [this.currentSearchType] : [];
},
},
watch: {
@@ -86,13 +84,9 @@ export default {
:placeholder="__('Search merge requests')"
@focus="onSearchFocus"
@input="searchMergeRequests"
- @removeToken="setSearchType(null)"
- />
- <icon
- :size="18"
- name="search"
- class="input-icon"
+ @removeToken="setSearchType(null);"
/>
+ <icon :size="18" name="search" class="input-icon" />
</div>
</div>
<div class="dropdown-content ide-merge-requests-dropdown-content d-flex">
@@ -102,36 +96,23 @@ export default {
class="mt-3 mb-3 align-self-center ml-auto mr-auto"
/>
<template v-else>
- <ul
- class="mb-3 w-100"
- >
+ <ul class="mb-3 w-100">
<template v-if="showSearchTypes">
- <li
- v-for="searchType in $options.searchTypes"
- :key="searchType.type"
- >
+ <li v-for="searchType in $options.searchTypes" :key="searchType.type">
<button
type="button"
class="btn-link d-flex align-items-center"
- @click.stop="setSearchType(searchType)"
+ @click.stop="setSearchType(searchType);"
>
<span class="d-flex append-right-default ide-search-list-current-icon">
- <icon
- :size="18"
- name="search"
- />
- </span>
- <span>
- {{ searchType.label }}
+ <icon :size="18" name="search" />
</span>
+ <span> {{ searchType.label }} </span>
</button>
</li>
</template>
<template v-else-if="hasMergeRequests">
- <li
- v-for="item in mergeRequests"
- :key="item.id"
- >
+ <li v-for="item in mergeRequests" :key="item.id">
<item
:item="item"
:current-id="currentMergeRequestId"
@@ -139,10 +120,7 @@ export default {
/>
</li>
</template>
- <li
- v-else
- class="ide-search-list-empty d-flex align-items-center justify-content-center"
- >
+ <li v-else class="ide-search-list-empty d-flex align-items-center justify-content-center">
{{ __('No merge requests found') }}
</li>
</ul>
diff --git a/app/assets/javascripts/ide/components/nav_dropdown.vue b/app/assets/javascripts/ide/components/nav_dropdown.vue
index db36779c395..e45d2a62dae 100644
--- a/app/assets/javascripts/ide/components/nav_dropdown.vue
+++ b/app/assets/javascripts/ide/components/nav_dropdown.vue
@@ -43,17 +43,8 @@ export default {
</script>
<template>
- <div
- ref="dropdown"
- class="btn-group ide-nav-dropdown dropdown"
- >
+ <div ref="dropdown" class="btn-group ide-nav-dropdown dropdown">
<nav-dropdown-button />
- <div
- class="dropdown-menu dropdown-menu-left p-0"
- >
- <nav-form
- v-if="isVisibleDropdown"
- />
- </div>
+ <div class="dropdown-menu dropdown-menu-left p-0"><nav-form v-if="isVisibleDropdown" /></div>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/nav_dropdown_button.vue b/app/assets/javascripts/ide/components/nav_dropdown_button.vue
index 7f98769d484..f1d44443125 100644
--- a/app/assets/javascripts/ide/components/nav_dropdown_button.vue
+++ b/app/assets/javascripts/ide/components/nav_dropdown_button.vue
@@ -13,9 +13,7 @@ export default {
computed: {
...mapState(['currentBranchId', 'currentMergeRequestId']),
mergeRequestLabel() {
- return this.currentMergeRequestId
- ? `!${this.currentMergeRequestId}`
- : EMPTY_LABEL;
+ return this.currentMergeRequestId ? `!${this.currentMergeRequestId}` : EMPTY_LABEL;
},
branchLabel() {
return this.currentBranchId || EMPTY_LABEL;
@@ -26,27 +24,12 @@ export default {
<template>
<dropdown-button>
- <span
- class="row"
- >
- <span
- class="col-7 text-truncate"
- >
- <icon
- :size="16"
- :aria-label="__('Current Branch')"
- name="branch"
- />
- {{ branchLabel }}
+ <span class="row">
+ <span class="col-7 text-truncate">
+ <icon :size="16" :aria-label="__('Current Branch')" name="branch" /> {{ branchLabel }}
</span>
- <span
- class="col-5 pl-0 text-truncate"
- >
- <icon
- :size="16"
- :aria-label="__('Merge Request')"
- name="merge-request"
- />
+ <span class="col-5 pl-0 text-truncate">
+ <icon :size="16" :aria-label="__('Merge Request')" name="merge-request" />
{{ mergeRequestLabel }}
</span>
</span>
diff --git a/app/assets/javascripts/ide/components/nav_form.vue b/app/assets/javascripts/ide/components/nav_form.vue
index 718b836e11c..23c068f329d 100644
--- a/app/assets/javascripts/ide/components/nav_form.vue
+++ b/app/assets/javascripts/ide/components/nav_form.vue
@@ -15,15 +15,9 @@ export default {
</script>
<template>
- <div
- class="ide-nav-form p-0"
- >
- <tabs
- stop-propagation
- >
- <tab
- active
- >
+ <div class="ide-nav-form p-0">
+ <tabs stop-propagation>
+ <tab active>
<template slot="title">
{{ __('Merge Requests') }}
</template>
diff --git a/app/assets/javascripts/ide/components/new_dropdown/button.vue b/app/assets/javascripts/ide/components/new_dropdown/button.vue
index aa5fce59dbf..062a64a19d7 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/button.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/button.vue
@@ -52,10 +52,7 @@ export default {
class="btn-blank"
@click.stop.prevent="clicked"
>
- <icon
- :name="icon"
- :css-classes="iconClasses"
- />
+ <icon :name="icon" :css-classes="iconClasses" />
<template v-if="showLabel">
{{ label }}
</template>
diff --git a/app/assets/javascripts/ide/components/new_dropdown/index.vue b/app/assets/javascripts/ide/components/new_dropdown/index.vue
index f02fd6cf7ea..a50d729036f 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/index.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/index.vue
@@ -73,19 +73,11 @@ export default {
:aria-label="__('Create new file or directory')"
type="button"
class="rounded border-0 d-flex ide-entry-dropdown-toggle"
- @click.stop="openDropdown()"
+ @click.stop="openDropdown();"
>
- <icon
- name="ellipsis_v"
- />
- <icon
- name="arrow-down"
- />
+ <icon name="ellipsis_v" /> <icon name="arrow-down" />
</button>
- <ul
- ref="dropdownMenu"
- class="dropdown-menu dropdown-menu-right"
- >
+ <ul ref="dropdownMenu" class="dropdown-menu dropdown-menu-right">
<template v-if="type === 'tree'">
<li>
<item-button
@@ -93,22 +85,17 @@ export default {
class="d-flex"
icon="doc-new"
icon-classes="mr-2"
- @click="createNewItem('blob')"
- />
- </li>
- <li>
- <upload
- :path="path"
- @create="createTempEntry"
+ @click="createNewItem('blob');"
/>
</li>
+ <li><upload :path="path" @create="createTempEntry" /></li>
<li>
<item-button
:label="__('New directory')"
class="d-flex"
icon="folder-new"
icon-classes="mr-2"
- @click="createNewItem($options.modalTypes.tree)"
+ @click="createNewItem($options.modalTypes.tree);"
/>
</li>
<li class="divider"></li>
@@ -119,7 +106,7 @@ export default {
class="d-flex"
icon="pencil"
icon-classes="mr-2"
- @click="createNewItem($options.modalTypes.rename)"
+ @click="createNewItem($options.modalTypes.rename);"
/>
</li>
<li>
@@ -128,7 +115,7 @@ export default {
class="d-flex"
icon="remove"
icon-classes="mr-2"
- @click="deleteEntry(path)"
+ @click="deleteEntry(path);"
/>
</li>
</ul>
diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
index bcd53ac1ba2..63cbf41b89b 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue
@@ -99,33 +99,22 @@ export default {
@open="focusInput"
@closed="closedModal"
>
- <div
- class="form-group row"
- >
- <label class="label-bold col-form-label col-sm-2">
- {{ __('Name') }}
- </label>
+ <div class="form-group row">
+ <label class="label-bold col-form-label col-sm-2"> {{ __('Name') }} </label>
<div class="col-sm-10">
<input
ref="fieldName"
v-model="entryName"
type="text"
- class="form-control"
+ class="form-control qa-full-file-path"
placeholder="/dir/file_name"
/>
- <ul
- v-if="isCreatingNew"
- class="prepend-top-default list-inline"
- >
- <li
- v-for="(template, index) in templateTypes"
- :key="index"
- class="list-inline-item"
- >
+ <ul v-if="isCreatingNew" class="prepend-top-default list-inline qa-template-list">
+ <li v-for="(template, index) in templateTypes" :key="index" class="list-inline-item">
<button
type="button"
class="btn btn-missing p-1 pr-2 pl-2"
- @click="createFromTemplate(template)"
+ @click="createFromTemplate(template);"
>
{{ template.name }}
</button>
diff --git a/app/assets/javascripts/ide/components/new_dropdown/upload.vue b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
index e2be805ed22..ec759043efc 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/upload.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/upload.vue
@@ -25,14 +25,32 @@ export default {
},
},
methods: {
- createFile(target, file, isText) {
+ isText(content, fileType) {
+ const knownBinaryFileTypes = ['image/'];
+ const knownTextFileTypes = ['text/'];
+ const isKnownBinaryFileType = knownBinaryFileTypes.find(type => fileType.includes(type));
+ const isKnownTextFileType = knownTextFileTypes.find(type => fileType.includes(type));
+ const asciiRegex = /^[ -~\t\n\r]+$/; // tests whether a string contains ascii characters only (ranges from space to tilde, tabs and new lines)
+
+ if (isKnownBinaryFileType) {
+ return false;
+ }
+
+ if (isKnownTextFileType) {
+ return true;
+ }
+
+ // if it's not a known file type, determine the type by evaluating the file contents
+ return asciiRegex.test(content);
+ },
+ createFile(target, file) {
const { name } = file;
let { result } = target;
+ const encodedContent = result.split('base64,')[1];
+ const rawContent = encodedContent ? atob(encodedContent) : '';
+ const isText = this.isText(rawContent, file.type);
- if (!isText) {
- // eslint-disable-next-line prefer-destructuring
- result = result.split('base64,')[1];
- }
+ result = isText ? rawContent : encodedContent;
this.$emit('create', {
name: `${this.path ? `${this.path}/` : ''}${name}`,
@@ -43,15 +61,9 @@ export default {
},
readFile(file) {
const reader = new FileReader();
- const isText = file.type.match(/text.*/) !== null;
- reader.addEventListener('load', e => this.createFile(e.target, file, isText), { once: true });
-
- if (isText) {
- reader.readAsText(file);
- } else {
- reader.readAsDataURL(file);
- }
+ reader.addEventListener('load', e => this.createFile(e.target, file), { once: true });
+ reader.readAsDataURL(file);
},
openFile() {
Array.from(this.$refs.fileUpload.files).forEach(file => this.readFile(file));
diff --git a/app/assets/javascripts/ide/components/panes/right.vue b/app/assets/javascripts/ide/components/panes/right.vue
index 79df225c432..7a57ccf2dd3 100644
--- a/app/assets/javascripts/ide/components/panes/right.vue
+++ b/app/assets/javascripts/ide/components/panes/right.vue
@@ -1,5 +1,7 @@
<script>
import { mapActions, mapState, mapGetters } from 'vuex';
+import _ from 'underscore';
+import { __ } from '~/locale';
import tooltip from '../../../vue_shared/directives/tooltip';
import Icon from '../../../vue_shared/components/icon.vue';
import { rightSidebarViews } from '../../constants';
@@ -21,108 +23,108 @@ export default {
MergeRequestInfo,
Clientside,
},
+ props: {
+ extensionTabs: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ },
computed: {
- ...mapState(['rightPane', 'currentMergeRequestId', 'clientsidePreviewEnabled']),
+ ...mapState(['currentMergeRequestId', 'clientsidePreviewEnabled']),
+ ...mapState('rightPane', ['isOpen', 'currentView']),
...mapGetters(['packageJson']),
- pipelinesActive() {
- return (
- this.rightPane === rightSidebarViews.pipelines ||
- this.rightPane === rightSidebarViews.jobsDetail
- );
- },
+ ...mapGetters('rightPane', ['isActiveView', 'isAliveView']),
showLivePreview() {
return this.packageJson && this.clientsidePreviewEnabled;
},
+ defaultTabs() {
+ return [
+ {
+ show: this.currentMergeRequestId,
+ title: __('Merge Request'),
+ views: [rightSidebarViews.mergeRequestInfo],
+ icon: 'text-description',
+ },
+ {
+ show: true,
+ title: __('Pipelines'),
+ views: [rightSidebarViews.pipelines, rightSidebarViews.jobsDetail],
+ icon: 'rocket',
+ },
+ {
+ show: this.showLivePreview,
+ title: __('Live preview'),
+ views: [rightSidebarViews.clientSidePreview],
+ icon: 'live-preview',
+ },
+ ];
+ },
+ tabs() {
+ return this.defaultTabs.concat(this.extensionTabs).filter(tab => tab.show);
+ },
+ tabViews() {
+ return _.flatten(this.tabs.map(tab => tab.views));
+ },
+ aliveTabViews() {
+ return this.tabViews.filter(view => this.isAliveView(view.name));
+ },
},
methods: {
- ...mapActions(['setRightPane']),
- clickTab(e, view) {
+ ...mapActions('rightPane', ['toggleOpen', 'open']),
+ clickTab(e, tab) {
e.target.blur();
- this.setRightPane(view);
+ if (this.isActiveTab(tab)) {
+ this.toggleOpen();
+ } else {
+ this.open(tab.views[0]);
+ }
+ },
+ isActiveTab(tab) {
+ return tab.views.some(view => this.isActiveView(view.name));
},
},
- rightSidebarViews,
};
</script>
<template>
- <div
- class="multi-file-commit-panel ide-right-sidebar"
- >
+ <div class="multi-file-commit-panel ide-right-sidebar">
<resizable-panel
- v-if="rightPane"
+ v-show="isOpen"
:collapsible="false"
:initial-width="350"
:min-size="350"
- :class="`ide-right-sidebar-${rightPane}`"
+ :class="`ide-right-sidebar-${currentView}`"
side="right"
class="multi-file-commit-panel-inner"
>
- <component :is="rightPane" />
+ <div
+ v-for="tabView in aliveTabViews"
+ v-show="isActiveView(tabView.name)"
+ :key="tabView.name"
+ class="h-100"
+ >
+ <component :is="tabView.component || tabView.name" />
+ </div>
</resizable-panel>
<nav class="ide-activity-bar">
<ul class="list-unstyled">
- <li
- v-if="currentMergeRequestId"
- >
- <button
- v-tooltip
- :title="__('Merge Request')"
- :aria-label="__('Merge Request')"
- :class="{
- active: rightPane === $options.rightSidebarViews.mergeRequestInfo
- }"
- data-container="body"
- data-placement="left"
- class="ide-sidebar-link is-right"
- type="button"
- @click="clickTab($event, $options.rightSidebarViews.mergeRequestInfo)"
- >
- <icon
- :size="16"
- name="text-description"
- />
- </button>
- </li>
- <li>
- <button
- v-tooltip
- :title="__('Pipelines')"
- :aria-label="__('Pipelines')"
- :class="{
- active: pipelinesActive
- }"
- data-container="body"
- data-placement="left"
- class="ide-sidebar-link is-right"
- type="button"
- @click="clickTab($event, $options.rightSidebarViews.pipelines)"
- >
- <icon
- :size="16"
- name="rocket"
- />
- </button>
- </li>
- <li v-if="showLivePreview">
+ <li v-for="tab of tabs" :key="tab.title">
<button
v-tooltip
- :title="__('Live preview')"
- :aria-label="__('Live preview')"
+ :title="tab.title"
+ :aria-label="tab.title"
:class="{
- active: rightPane === $options.rightSidebarViews.clientSidePreview
+ active: isActiveTab(tab) && isOpen,
}"
data-container="body"
data-placement="left"
class="ide-sidebar-link is-right"
type="button"
- @click="clickTab($event, $options.rightSidebarViews.clientSidePreview)"
+ @click="clickTab($event, tab);"
>
- <icon
- :size="16"
- name="live-preview"
- />
+ <icon :size="16" :name="tab.icon" />
</button>
</li>
</ul>
diff --git a/app/assets/javascripts/ide/components/pipelines/list.vue b/app/assets/javascripts/ide/components/pipelines/list.vue
index 0a2681b7a1e..451c8030e16 100644
--- a/app/assets/javascripts/ide/components/pipelines/list.vue
+++ b/app/assets/javascripts/ide/components/pipelines/list.vue
@@ -1,6 +1,7 @@
<script>
import { mapActions, mapGetters, mapState } from 'vuex';
import _ from 'underscore';
+import { GlLoadingIcon } from '@gitlab/ui';
import { sprintf, __ } from '../../../locale';
import Icon from '../../../vue_shared/components/icon.vue';
import CiIcon from '../../../vue_shared/components/ci_icon.vue';
@@ -17,6 +18,7 @@ export default {
Tab,
JobsList,
EmptyState,
+ GlLoadingIcon,
},
computed: {
...mapState(['pipelinesEmptyStateSvgPath', 'links']),
@@ -25,7 +27,7 @@ export default {
...mapState('pipelines', ['isLoadingPipeline', 'latestPipeline', 'stages', 'isLoadingJobs']),
ciLintText() {
return sprintf(
- __('You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}'),
+ __('You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}.'),
{
linkStart: `<a href="${_.escape(this.currentProject.web_url)}/-/ci/lint">`,
linkEnd: '</a>',
@@ -48,34 +50,14 @@ export default {
<template>
<div class="ide-pipeline">
- <gl-loading-icon
- v-if="showLoadingIcon"
- :size="2"
- class="prepend-top-default"
- />
+ <gl-loading-icon v-if="showLoadingIcon" :size="2" class="prepend-top-default" />
<template v-else-if="latestPipeline !== null">
- <header
- v-if="latestPipeline"
- class="ide-tree-header ide-pipeline-header"
- >
- <ci-icon
- :status="latestPipeline.details.status"
- :size="24"
- />
+ <header v-if="latestPipeline" class="ide-tree-header ide-pipeline-header">
+ <ci-icon :status="latestPipeline.details.status" :size="24" />
<span class="prepend-left-8">
- <strong>
- {{ __('Pipeline') }}
- </strong>
- <a
- :href="latestPipeline.path"
- target="_blank"
- class="ide-external-link"
- >
- #{{ latestPipeline.id }}
- <icon
- :size="12"
- name="external-link"
- />
+ <strong> {{ __('Pipeline') }} </strong>
+ <a :href="latestPipeline.path" target="_blank" class="ide-external-link">
+ #{{ latestPipeline.id }} <icon :size="12" name="external-link" />
</a>
</span>
</header>
@@ -85,58 +67,25 @@ export default {
:empty-state-svg-path="pipelinesEmptyStateSvgPath"
:can-set-ci="true"
/>
- <div
- v-else-if="latestPipeline.yamlError"
- class="bs-callout bs-callout-danger"
- >
- <p class="append-bottom-0">
- {{ __('Found errors in your .gitlab-ci.yml:') }}
- </p>
- <p class="append-bottom-0 break-word">
- {{ latestPipeline.yamlError }}
- </p>
- <p
- class="append-bottom-0"
- v-html="ciLintText"
- ></p>
+ <div v-else-if="latestPipeline.yamlError" class="bs-callout bs-callout-danger">
+ <p class="append-bottom-0">{{ __('Found errors in your .gitlab-ci.yml:') }}</p>
+ <p class="append-bottom-0 break-word">{{ latestPipeline.yamlError }}</p>
+ <p class="append-bottom-0" v-html="ciLintText"></p>
</div>
- <tabs
- v-else
- class="ide-pipeline-list"
- >
- <tab
- :active="!pipelineFailed"
- >
+ <tabs v-else class="ide-pipeline-list">
+ <tab :active="!pipelineFailed">
<template slot="title">
{{ __('Jobs') }}
- <span
- v-if="jobsCount"
- class="badge badge-pill"
- >
- {{ jobsCount }}
- </span>
+ <span v-if="jobsCount" class="badge badge-pill"> {{ jobsCount }} </span>
</template>
- <jobs-list
- :loading="isLoadingJobs"
- :stages="stages"
- />
+ <jobs-list :loading="isLoadingJobs" :stages="stages" />
</tab>
- <tab
- :active="pipelineFailed"
- >
+ <tab :active="pipelineFailed">
<template slot="title">
{{ __('Failed Jobs') }}
- <span
- v-if="failedJobsCount"
- class="badge badge-pill"
- >
- {{ failedJobsCount }}
- </span>
+ <span v-if="failedJobsCount" class="badge badge-pill"> {{ failedJobsCount }} </span>
</template>
- <jobs-list
- :loading="isLoadingJobs"
- :stages="failedStages"
- />
+ <jobs-list :loading="isLoadingJobs" :stages="failedStages" />
</tab>
</tabs>
</template>
diff --git a/app/assets/javascripts/ide/components/preview/clientside.vue b/app/assets/javascripts/ide/components/preview/clientside.vue
index 37a8ad36507..c98dda00817 100644
--- a/app/assets/javascripts/ide/components/preview/clientside.vue
+++ b/app/assets/javascripts/ide/components/preview/clientside.vue
@@ -3,6 +3,7 @@ import { mapActions, mapGetters, mapState } from 'vuex';
import _ from 'underscore';
import { Manager } from 'smooshpack';
import { listen } from 'codesandbox-api';
+import { GlLoadingIcon } from '@gitlab/ui';
import Navigator from './navigator.vue';
import { packageJsonPath } from '../../constants';
import { createPathWithExt } from '../../utils';
@@ -10,6 +11,7 @@ import { createPathWithExt } from '../../utils';
export default {
components: {
Navigator,
+ GlLoadingIcon,
},
data() {
return {
@@ -144,9 +146,7 @@ export default {
<template>
<div class="preview h-100 w-100 d-flex flex-column">
<template v-if="showPreview">
- <navigator
- :manager="manager"
- />
+ <navigator :manager="manager" />
<div id="ide-preview"></div>
</template>
<div
@@ -154,15 +154,8 @@ export default {
v-once
class="d-flex h-100 flex-column align-items-center justify-content-center svg-content"
>
- <img
- :src="promotionSvgPath"
- :alt="s__('IDE|Live Preview')"
- width="130"
- height="100"
- />
- <h3>
- {{ s__('IDE|Live Preview') }}
- </h3>
+ <img :src="promotionSvgPath" :alt="s__('IDE|Live Preview')" width="130" height="100" />
+ <h3>{{ s__('IDE|Live Preview') }}</h3>
<p class="text-center">
{{ s__('IDE|Preview your web application using Web IDE client-side evaluation.') }}
</p>
@@ -175,10 +168,6 @@ export default {
{{ s__('IDE|Get started with Live Preview') }}
</a>
</div>
- <gl-loading-icon
- v-else
- :size="2"
- class="align-self-center mt-auto mb-auto"
- />
+ <gl-loading-icon v-else :size="2" class="align-self-center mt-auto mb-auto" />
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/preview/navigator.vue b/app/assets/javascripts/ide/components/preview/navigator.vue
index 42f23801692..bc80e1dba25 100644
--- a/app/assets/javascripts/ide/components/preview/navigator.vue
+++ b/app/assets/javascripts/ide/components/preview/navigator.vue
@@ -1,10 +1,12 @@
<script>
import { listen } from 'codesandbox-api';
import Icon from '~/vue_shared/components/icon.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
components: {
Icon,
+ GlLoadingIcon,
},
props: {
manager: {
@@ -89,33 +91,25 @@ export default {
:aria-label="s__('IDE|Back')"
:disabled="backButtonDisabled"
:class="{
- 'disabled-content': backButtonDisabled
+ 'disabled-content': backButtonDisabled,
}"
type="button"
class="ide-navigator-btn d-flex align-items-center d-transparent border-0 bg-transparent"
@click="back"
>
- <icon
- :size="24"
- name="chevron-left"
- class="m-auto"
- />
+ <icon :size="24" name="chevron-left" class="m-auto" />
</button>
<button
:aria-label="s__('IDE|Back')"
:disabled="forwardButtonDisabled"
:class="{
- 'disabled-content': forwardButtonDisabled
+ 'disabled-content': forwardButtonDisabled,
}"
type="button"
class="ide-navigator-btn d-flex align-items-center d-transparent border-0 bg-transparent"
@click="forward"
>
- <icon
- :size="24"
- name="chevron-right"
- class="m-auto"
- />
+ <icon :size="24" name="chevron-right" class="m-auto" />
</button>
<button
:aria-label="s__('IDE|Refresh preview')"
@@ -123,11 +117,7 @@ export default {
class="ide-navigator-btn d-flex align-items-center d-transparent border-0 bg-transparent"
@click="refresh"
>
- <icon
- :size="18"
- name="retry"
- class="m-auto"
- />
+ <icon :size="18" name="retry" class="m-auto" />
</button>
<div class="position-relative w-100 prepend-left-4">
<input
@@ -136,10 +126,7 @@ export default {
class="ide-navigator-location form-control bg-white"
readonly
/>
- <gl-loading-icon
- v-if="loading"
- class="position-absolute ide-preview-loading-icon"
- />
+ <gl-loading-icon v-if="loading" class="position-absolute ide-preview-loading-icon" />
</div>
</header>
</template>
diff --git a/app/assets/javascripts/ide/components/repo_commit_section.vue b/app/assets/javascripts/ide/components/repo_commit_section.vue
index d3b24c5b793..8dd88f187d4 100644
--- a/app/assets/javascripts/ide/components/repo_commit_section.vue
+++ b/app/assets/javascripts/ide/components/repo_commit_section.vue
@@ -27,10 +27,10 @@ export default {
'unusedSeal',
]),
...mapState('commit', ['commitMessage', 'submitCommitLoading']),
- ...mapGetters(['lastOpenedFile', 'hasChanges', 'someUncommitedChanges', 'activeFile']),
+ ...mapGetters(['lastOpenedFile', 'hasChanges', 'someUncommittedChanges', 'activeFile']),
...mapGetters('commit', ['discardDraftButtonDisabled']),
showStageUnstageArea() {
- return !!(this.someUncommitedChanges || this.lastCommitMsg || !this.unusedSeal);
+ return !!(this.someUncommittedChanges || this.lastCommitMsg || !this.unusedSeal);
},
activeFileKey() {
return this.activeFile ? this.activeFile.key : null;
@@ -71,9 +71,7 @@ export default {
</script>
<template>
- <div
- class="multi-file-commit-panel-section"
- >
+ <div class="multi-file-commit-panel-section">
<deprecated-modal
id="ide-create-branch-modal"
:primary-button-label="__('Create new branch')"
@@ -82,13 +80,13 @@ export default {
@submit="forceCreateNewBranch"
>
<template slot="body">
- {{ __(`This branch has changed since you started editing.
- Would you like to create a new branch?`) }}
+ {{
+ __(`This branch has changed since you started editing.
+ Would you like to create a new branch?`)
+ }}
</template>
</deprecated-modal>
- <template
- v-if="showStageUnstageArea"
- >
+ <template v-if="showStageUnstageArea">
<commit-files-list
:title="__('Unstaged')"
:key-prefix="$options.stageKeys.unstaged"
@@ -116,8 +114,6 @@ export default {
icon-name="staged"
/>
</template>
- <empty-state
- v-if="unusedSeal"
- />
+ <empty-state v-if="unusedSeal" />
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
index d3a73e84cc7..c13d3ec094b 100644
--- a/app/assets/javascripts/ide/components/repo_editor.vue
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -22,13 +22,10 @@ export default {
},
},
computed: {
- ...mapState([
- 'rightPanelCollapsed',
- 'viewer',
- 'panelResizing',
- 'currentActivityView',
- 'rightPane',
- ]),
+ ...mapState('rightPane', {
+ rightPaneIsOpen: 'isOpen',
+ }),
+ ...mapState(['rightPanelCollapsed', 'viewer', 'panelResizing', 'currentActivityView']),
...mapGetters([
'currentMergeRequest',
'getStagedFile',
@@ -99,7 +96,7 @@ export default {
this.editor.updateDimensions();
}
},
- rightPane() {
+ rightPaneIsOpen() {
this.editor.updateDimensions();
},
},
@@ -215,20 +212,15 @@ export default {
</script>
<template>
- <div
- id="ide"
- class="blob-viewer-container blob-editor-container"
- >
+ <div id="ide" class="blob-viewer-container blob-editor-container">
<div class="ide-mode-tabs clearfix">
- <ul
- v-if="!shouldHideEditor && isEditModeActive"
- class="nav-links float-left"
- >
+ <ul v-if="!shouldHideEditor && isEditModeActive" class="nav-links float-left">
<li :class="editTabCSS">
<a
href="javascript:void(0);"
role="button"
- @click.prevent="setFileViewMode({ file, viewMode: 'editor' })">
+ @click.prevent="setFileViewMode({ file, viewMode: 'editor' });"
+ >
<template v-if="viewer === $options.viewerTypes.edit">
{{ __('Edit') }}
</template>
@@ -237,41 +229,36 @@ export default {
</template>
</a>
</li>
- <li
- v-if="file.previewMode"
- :class="previewTabCSS">
+ <li v-if="file.previewMode" :class="previewTabCSS">
<a
href="javascript:void(0);"
role="button"
- @click.prevent="setFileViewMode({ file, viewMode:'preview' })">
+ @click.prevent="setFileViewMode({ file, viewMode: 'preview' });"
+ >
{{ file.previewMode.previewTitle }}
</a>
</li>
</ul>
- <external-link
- :file="file"
- />
+ <external-link :file="file" />
</div>
- <file-templates-bar
- v-if="showFileTemplatesBar(file.name)"
- />
+ <file-templates-bar v-if="showFileTemplatesBar(file.name)" />
<div
- v-show="!shouldHideEditor && file.viewMode ==='editor'"
+ v-show="!shouldHideEditor && file.viewMode === 'editor'"
ref="editor"
:class="{
'is-readonly': isCommitModeActive,
'is-deleted': file.deleted,
- 'is-added': file.tempFile
+ 'is-added': file.tempFile,
}"
class="multi-file-editor-holder"
- >
- </div>
+ ></div>
<content-viewer
v-if="showContentViewer"
:content="file.content || file.raw"
:path="file.rawPath || file.path"
:file-size="file.size"
- :project-path="file.projectId"/>
+ :project-path="file.projectId"
+ />
<diff-viewer
v-if="showDiffViewer"
:diff-mode="file.mrChange.diffMode"
@@ -279,6 +266,7 @@ export default {
:new-sha="currentMergeRequest.sha"
:old-path="file.mrChange.old_path"
:old-sha="currentMergeRequest.baseCommitSha"
- :project-path="file.projectId"/>
+ :project-path="file.projectId"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/repo_file_status_icon.vue b/app/assets/javascripts/ide/components/repo_file_status_icon.vue
index 76a3333be50..a964d90b090 100644
--- a/app/assets/javascripts/ide/components/repo_file_status_icon.vue
+++ b/app/assets/javascripts/ide/components/repo_file_status_icon.vue
@@ -25,15 +25,7 @@ export default {
</script>
<template>
- <span
- v-tooltip
- v-if="file.file_lock"
- :title="lockTooltip"
- data-container="body"
- >
- <icon
- name="lock"
- css-classes="file-status-icon"
- />
+ <span v-if="file.file_lock" v-tooltip :title="lockTooltip" data-container="body">
+ <icon name="lock" css-classes="file-status-icon" />
</span>
</template>
diff --git a/app/assets/javascripts/ide/components/repo_loading_file.vue b/app/assets/javascripts/ide/components/repo_loading_file.vue
deleted file mode 100644
index 7a5ede82253..00000000000
--- a/app/assets/javascripts/ide/components/repo_loading_file.vue
+++ /dev/null
@@ -1,42 +0,0 @@
-<script>
- import { mapState } from 'vuex';
- import skeletonLoadingContainer from '~/vue_shared/components/skeleton_loading_container.vue';
-
- export default {
- components: {
- skeletonLoadingContainer,
- },
- computed: {
- ...mapState([
- 'leftPanelCollapsed',
- ]),
- },
- };
-</script>
-
-<template>
- <tr
- class="loading-file"
- aria-label="Loading files"
- >
- <td class="multi-file-table-col-name">
- <skeleton-loading-container
- :small="true"
- />
- </td>
- <template v-if="!leftPanelCollapsed">
- <td class="d-none d-sm-none d-md-block">
- <skeleton-loading-container
- :small="true"
- />
- </td>
-
- <td class="d-none d-sm-block">
- <skeleton-loading-container
- :small="true"
- class="animation-container-right"
- />
- </td>
- </template>
- </tr>
-</template>
diff --git a/app/assets/javascripts/ide/components/repo_tab.vue b/app/assets/javascripts/ide/components/repo_tab.vue
index db47b75ec5c..4b87b83db8a 100644
--- a/app/assets/javascripts/ide/components/repo_tab.vue
+++ b/app/assets/javascripts/ide/components/repo_tab.vue
@@ -3,8 +3,8 @@ import { mapActions } from 'vuex';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import Icon from '~/vue_shared/components/icon.vue';
+import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
import FileStatusIcon from './repo_file_status_icon.vue';
-import ChangedFileIcon from './changed_file_icon.vue';
export default {
components: {
@@ -72,41 +72,26 @@ export default {
<li
:class="{
active: tab.active,
- disabled: tab.pending
+ disabled: tab.pending,
}"
- @click="clickFile(tab)"
+ @click="clickFile(tab);"
@mouseover="mouseOverTab"
@mouseout="mouseOutTab"
>
- <div
- :title="tab.url"
- class="multi-file-tab"
- >
- <file-icon
- :file-name="tab.name"
- :size="16"
- />
+ <div :title="tab.url" class="multi-file-tab">
+ <file-icon :file-name="tab.name" :size="16" />
{{ tab.name }}
- <file-status-icon
- :file="tab"
- />
+ <file-status-icon :file="tab" />
</div>
<button
:aria-label="closeLabel"
:disabled="tab.pending"
type="button"
class="multi-file-tab-close"
- @click.stop.prevent="closeFile(tab)"
+ @click.stop.prevent="closeFile(tab);"
>
- <icon
- v-if="!showChangedIcon"
- :size="12"
- name="close"
- />
- <changed-file-icon
- v-else
- :file="tab"
- />
+ <icon v-if="!showChangedIcon" :size="12" name="close" />
+ <changed-file-icon v-else :file="tab" />
</button>
</li>
</template>
diff --git a/app/assets/javascripts/ide/components/repo_tabs.vue b/app/assets/javascripts/ide/components/repo_tabs.vue
index c12a63e26be..4dbc4383894 100644
--- a/app/assets/javascripts/ide/components/repo_tabs.vue
+++ b/app/assets/javascripts/ide/components/repo_tabs.vue
@@ -51,15 +51,8 @@ export default {
<template>
<div class="multi-file-tabs">
- <ul
- ref="tabsScroller"
- class="list-unstyled append-bottom-0"
- >
- <repo-tab
- v-for="tab in files"
- :key="tab.key"
- :tab="tab"
- />
+ <ul ref="tabsScroller" class="list-unstyled append-bottom-0">
+ <repo-tab v-for="tab in files" :key="tab.key" :tab="tab" />
</ul>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/resizable_panel.vue b/app/assets/javascripts/ide/components/resizable_panel.vue
index 7277fcb7617..a89de56ab5c 100644
--- a/app/assets/javascripts/ide/components/resizable_panel.vue
+++ b/app/assets/javascripts/ide/components/resizable_panel.vue
@@ -78,8 +78,8 @@ export default {
:min-size="minSize"
:max-size="$options.maxSize"
:side="side === 'right' ? 'left' : 'right'"
- @resize-start="setResizingStatus(true)"
- @resize-end="setResizingStatus(false)"
+ @resize-start="setResizingStatus(true);"
+ @resize-end="setResizingStatus(false);"
/>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/shared/tokened_input.vue b/app/assets/javascripts/ide/components/shared/tokened_input.vue
index a7a12f6785d..f58e08c2cc9 100644
--- a/app/assets/javascripts/ide/components/shared/tokened_input.vue
+++ b/app/assets/javascripts/ide/components/shared/tokened_input.vue
@@ -30,9 +30,7 @@ export default {
},
computed: {
placeholderText() {
- return this.tokens.length
- ? ''
- : this.placeholder;
+ return this.tokens.length ? '' : this.placeholder;
},
},
watch: {
@@ -74,31 +72,16 @@ export default {
<div class="filtered-search-wrapper">
<div class="filtered-search-box">
<div class="tokens-container list-unstyled">
- <div
- v-for="token in tokens"
- :key="token.label"
- class="filtered-search-token"
- >
+ <div v-for="token in tokens" :key="token.label" class="filtered-search-token">
<button
class="selectable btn-blank"
type="button"
- @click.stop="removeToken(token)"
- @keyup.delete="removeToken(token)"
+ @click.stop="removeToken(token);"
+ @keyup.delete="removeToken(token);"
>
- <div
- class="value-container rounded"
- >
- <div
- class="value"
- >{{ token.label }}</div>
- <div
- class="remove-token inverted"
- >
- <icon
- :size="10"
- name="close"
- />
- </div>
+ <div class="value-container rounded">
+ <div class="value">{{ token.label }}</div>
+ <div class="remove-token inverted"><icon :size="10" name="close" /></div>
</div>
</button>
</div>
diff --git a/app/assets/javascripts/ide/constants.js b/app/assets/javascripts/ide/constants.js
index 8caa5b86a9b..3b201f006aa 100644
--- a/app/assets/javascripts/ide/constants.js
+++ b/app/assets/javascripts/ide/constants.js
@@ -29,10 +29,10 @@ export const diffModes = {
};
export const rightSidebarViews = {
- pipelines: 'pipelines-list',
- jobsDetail: 'jobs-detail',
- mergeRequestInfo: 'merge-request-info',
- clientSidePreview: 'clientside',
+ pipelines: { name: 'pipelines-list', keepAlive: true },
+ jobsDetail: { name: 'jobs-detail', keepAlive: false },
+ mergeRequestInfo: { name: 'merge-request-info', keepAlive: true },
+ clientSidePreview: { name: 'clientside', keepAlive: false },
};
export const stageKeys = {
diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js
index 79e38ae911e..fbf944499d5 100644
--- a/app/assets/javascripts/ide/index.js
+++ b/app/assets/javascripts/ide/index.js
@@ -4,20 +4,29 @@ import Translate from '~/vue_shared/translate';
import ide from './components/ide.vue';
import store from './stores';
import router from './ide_router';
-import { convertPermissionToBoolean } from '../lib/utils/common_utils';
+import { parseBoolean } from '../lib/utils/common_utils';
Vue.use(Translate);
-export function initIde(el) {
+/**
+ * Initialize the IDE on the given element.
+ *
+ * @param {Element} el - The element that will contain the IDE.
+ * @param {Object} options - Extra options for the IDE (Used by EE).
+ * @param {(e:Element) => Object} options.extraInitialData -
+ * Function that returns extra properties to seed initial data.
+ * @param {Component} options.rootComponent -
+ * Component that overrides the root component.
+ */
+export function initIde(el, options = {}) {
if (!el) return null;
+ const { extraInitialData = () => ({}), rootComponent = ide } = options;
+
return new Vue({
el,
store,
router,
- components: {
- ide,
- },
created() {
this.setEmptyStateSvgs({
emptyStateSvgPath: el.dataset.emptyStateSvgPath,
@@ -31,14 +40,15 @@ export function initIde(el) {
webIDEHelpPagePath: el.dataset.webIdeHelpPagePath,
});
this.setInitialData({
- clientsidePreviewEnabled: convertPermissionToBoolean(el.dataset.clientsidePreviewEnabled),
+ clientsidePreviewEnabled: parseBoolean(el.dataset.clientsidePreviewEnabled),
+ ...extraInitialData(el),
});
},
methods: {
...mapActions(['setEmptyStateSvgs', 'setLinks', 'setInitialData']),
},
render(createElement) {
- return createElement('ide');
+ return createElement(rootComponent);
},
});
}
@@ -52,3 +62,18 @@ export function resetServiceWorkersPublicPath() {
const webpackAssetPath = `${relativeRootPath}/assets/webpack/`;
__webpack_public_path__ = webpackAssetPath; // eslint-disable-line camelcase
}
+
+/**
+ * Start the IDE.
+ *
+ * @param {Objects} options - Extra options for the IDE (Used by EE).
+ */
+export function startIde(options) {
+ document.addEventListener('DOMContentLoaded', () => {
+ const ideElement = document.getElementById('ide');
+ if (ideElement) {
+ resetServiceWorkersPublicPath();
+ initIde(ideElement, options);
+ }
+ });
+}
diff --git a/app/assets/javascripts/ide/lib/diff/diff.js b/app/assets/javascripts/ide/lib/diff/diff.js
index 0e37f5c4704..9b7ed68b893 100644
--- a/app/assets/javascripts/ide/lib/diff/diff.js
+++ b/app/assets/javascripts/ide/lib/diff/diff.js
@@ -11,14 +11,16 @@ export const computeDiff = (originalContent, newContent) => {
if (findOnLine) {
Object.assign(findOnLine, change, {
modified: true,
- endLineNumber: (lineNumber + change.count) - 1,
+ endLineNumber: lineNumber + change.count - 1,
});
} else if ('added' in change || 'removed' in change) {
- acc.push(Object.assign({}, change, {
- lineNumber,
- modified: undefined,
- endLineNumber: (lineNumber + change.count) - 1,
- }));
+ acc.push(
+ Object.assign({}, change, {
+ lineNumber,
+ modified: undefined,
+ endLineNumber: lineNumber + change.count - 1,
+ }),
+ );
}
if (!change.removed) {
diff --git a/app/assets/javascripts/ide/lib/diff/diff_worker.js b/app/assets/javascripts/ide/lib/diff/diff_worker.js
index 78b2eab6399..77416a8de9d 100644
--- a/app/assets/javascripts/ide/lib/diff/diff_worker.js
+++ b/app/assets/javascripts/ide/lib/diff/diff_worker.js
@@ -1,7 +1,7 @@
import { computeDiff } from './diff';
// eslint-disable-next-line no-restricted-globals
-self.addEventListener('message', (e) => {
+self.addEventListener('message', e => {
const { data } = e;
// eslint-disable-next-line no-restricted-globals
diff --git a/app/assets/javascripts/ide/services/index.js b/app/assets/javascripts/ide/services/index.js
index f0193d8e8ea..13449592e62 100644
--- a/app/assets/javascripts/ide/services/index.js
+++ b/app/assets/javascripts/ide/services/index.js
@@ -41,13 +41,13 @@ export default {
return Api.project(`${namespace}/${project}`);
},
getProjectMergeRequestData(projectId, mergeRequestId, params = {}) {
- return Api.mergeRequest(projectId, mergeRequestId, params);
+ return Api.projectMergeRequest(projectId, mergeRequestId, params);
},
getProjectMergeRequestChanges(projectId, mergeRequestId) {
- return Api.mergeRequestChanges(projectId, mergeRequestId);
+ return Api.projectMergeRequestChanges(projectId, mergeRequestId);
},
getProjectMergeRequestVersions(projectId, mergeRequestId) {
- return Api.mergeRequestVersions(projectId, mergeRequestId);
+ return Api.projectMergeRequestVersions(projectId, mergeRequestId);
},
getBranchData(projectId, currentBranchId) {
return Api.branchSingle(projectId, currentBranchId);
diff --git a/app/assets/javascripts/ide/stores/actions.js b/app/assets/javascripts/ide/stores/actions.js
index b8b64aead30..e10a132ab4b 100644
--- a/app/assets/javascripts/ide/stores/actions.js
+++ b/app/assets/javascripts/ide/stores/actions.js
@@ -184,10 +184,6 @@ export const burstUnusedSeal = ({ state, commit }) => {
}
};
-export const setRightPane = ({ commit }, view) => {
- commit(types.SET_RIGHT_PANE, view);
-};
-
export const setLinks = ({ commit }, links) => commit(types.SET_LINKS, links);
export const setErrorMessage = ({ commit }, errorMessage) =>
diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js
index 30dcf7ef4df..e74b880e02c 100644
--- a/app/assets/javascripts/ide/stores/actions/file.js
+++ b/app/assets/javascripts/ide/stores/actions/file.js
@@ -56,7 +56,10 @@ export const setFileActive = ({ commit, state, getters, dispatch }, path) => {
dispatch('scrollToTab');
};
-export const getFileData = ({ state, commit, dispatch }, { path, makeFileActive = true }) => {
+export const getFileData = (
+ { state, commit, dispatch },
+ { path, makeFileActive = true, openFile = makeFileActive },
+) => {
const file = state.entries[path];
if (file.raw || (file.tempFile && !file.prevPath)) return Promise.resolve();
@@ -71,15 +74,15 @@ export const getFileData = ({ state, commit, dispatch }, { path, makeFileActive
const normalizedHeaders = normalizeHeaders(headers);
setPageTitle(decodeURI(normalizedHeaders['PAGE-TITLE']));
- commit(types.SET_FILE_DATA, { data, file });
- if (makeFileActive) commit(types.TOGGLE_FILE_OPEN, path);
+ if (data) commit(types.SET_FILE_DATA, { data, file });
+ if (openFile) commit(types.TOGGLE_FILE_OPEN, path);
if (makeFileActive) dispatch('setFileActive', path);
commit(types.TOGGLE_LOADING, { entry: file });
})
.catch(() => {
commit(types.TOGGLE_LOADING, { entry: file });
dispatch('setErrorMessage', {
- text: __('An error occured whilst loading the file.'),
+ text: __('An error occurred whilst loading the file.'),
action: payload =>
dispatch('getFileData', payload).then(() => dispatch('setErrorMessage', null)),
actionText: __('Please try again'),
@@ -121,7 +124,7 @@ export const getRawFileData = ({ state, commit, dispatch, getters }, { path }) =
})
.catch(() => {
dispatch('setErrorMessage', {
- text: __('An error occured whilst loading the file content.'),
+ text: __('An error occurred whilst loading the file content.'),
action: payload =>
dispatch('getRawFileData', payload).then(() => dispatch('setErrorMessage', null)),
actionText: __('Please try again'),
diff --git a/app/assets/javascripts/ide/stores/actions/merge_request.js b/app/assets/javascripts/ide/stores/actions/merge_request.js
index 187f8c75d07..18c24369996 100644
--- a/app/assets/javascripts/ide/stores/actions/merge_request.js
+++ b/app/assets/javascripts/ide/stores/actions/merge_request.js
@@ -25,7 +25,7 @@ export const getMergeRequestData = (
})
.catch(() => {
dispatch('setErrorMessage', {
- text: __('An error occured whilst loading the merge request.'),
+ text: __('An error occurred whilst loading the merge request.'),
action: payload =>
dispatch('getMergeRequestData', payload).then(() =>
dispatch('setErrorMessage', null),
@@ -58,7 +58,7 @@ export const getMergeRequestChanges = (
})
.catch(() => {
dispatch('setErrorMessage', {
- text: __('An error occured whilst loading the merge request changes.'),
+ text: __('An error occurred whilst loading the merge request changes.'),
action: payload =>
dispatch('getMergeRequestChanges', payload).then(() =>
dispatch('setErrorMessage', null),
@@ -92,7 +92,7 @@ export const getMergeRequestVersions = (
})
.catch(() => {
dispatch('setErrorMessage', {
- text: __('An error occured whilst loading the merge request version data.'),
+ text: __('An error occurred whilst loading the merge request version data.'),
action: payload =>
dispatch('getMergeRequestVersions', payload).then(() =>
dispatch('setErrorMessage', null),
@@ -116,57 +116,58 @@ export const openMergeRequest = (
targetProjectId,
mergeRequestId,
})
- .then(mr => {
- dispatch('setCurrentBranchId', mr.source_branch);
+ .then(mr => {
+ dispatch('setCurrentBranchId', mr.source_branch);
- dispatch('getBranchData', {
- projectId,
- branchId: mr.source_branch,
- });
+ dispatch('getBranchData', {
+ projectId,
+ branchId: mr.source_branch,
+ });
- return dispatch('getFiles', {
- projectId,
- branchId: mr.source_branch,
- });
- })
- .then(() =>
- dispatch('getMergeRequestVersions', {
- projectId,
- targetProjectId,
- mergeRequestId,
- }),
- )
- .then(() =>
- dispatch('getMergeRequestChanges', {
- projectId,
- targetProjectId,
- mergeRequestId,
- }),
- )
- .then(mrChanges => {
- if (mrChanges.changes.length) {
- dispatch('updateActivityBarView', activityBarViews.review);
- }
+ return dispatch('getFiles', {
+ projectId,
+ branchId: mr.source_branch,
+ });
+ })
+ .then(() =>
+ dispatch('getMergeRequestVersions', {
+ projectId,
+ targetProjectId,
+ mergeRequestId,
+ }),
+ )
+ .then(() =>
+ dispatch('getMergeRequestChanges', {
+ projectId,
+ targetProjectId,
+ mergeRequestId,
+ }),
+ )
+ .then(mrChanges => {
+ if (mrChanges.changes.length) {
+ dispatch('updateActivityBarView', activityBarViews.review);
+ }
- mrChanges.changes.forEach((change, ind) => {
- const changeTreeEntry = state.entries[change.new_path];
+ mrChanges.changes.forEach((change, ind) => {
+ const changeTreeEntry = state.entries[change.new_path];
- if (changeTreeEntry) {
- dispatch('setFileMrChange', {
- file: changeTreeEntry,
- mrChange: change,
- });
-
- if (ind < 10) {
- dispatch('getFileData', {
- path: change.new_path,
- makeFileActive: ind === 0,
+ if (changeTreeEntry) {
+ dispatch('setFileMrChange', {
+ file: changeTreeEntry,
+ mrChange: change,
});
+
+ if (ind < 10) {
+ dispatch('getFileData', {
+ path: change.new_path,
+ makeFileActive: ind === 0,
+ openFile: true,
+ });
+ }
}
- }
+ });
+ })
+ .catch(e => {
+ flash(__('Error while loading the merge request. Please try again.'));
+ throw e;
});
- })
- .catch(e => {
- flash(__('Error while loading the merge request. Please try again.'));
- throw e;
- });
diff --git a/app/assets/javascripts/ide/stores/actions/project.js b/app/assets/javascripts/ide/stores/actions/project.js
index 543dc6c0461..b65f631c99c 100644
--- a/app/assets/javascripts/ide/stores/actions/project.js
+++ b/app/assets/javascripts/ide/stores/actions/project.js
@@ -103,7 +103,7 @@ export const createNewBranchFromDefault = ({ state, dispatch, getters }, branch)
})
.catch(() => {
dispatch('setErrorMessage', {
- text: __('An error occured creating the new branch.'),
+ text: __('An error occurred creating the new branch.'),
action: payload => dispatch('createNewBranchFromDefault', payload),
actionText: __('Please try again'),
actionPayload: branch,
@@ -125,10 +125,7 @@ export const showBranchNotFoundError = ({ dispatch }, branchId) => {
});
};
-export const openBranch = (
- { dispatch, state },
- { projectId, branchId, basePath },
-) => {
+export const openBranch = ({ dispatch, state }, { projectId, branchId, basePath }) => {
dispatch('setCurrentBranchId', branchId);
dispatch('getBranchData', {
@@ -136,23 +133,20 @@ export const openBranch = (
branchId,
});
- return (
- dispatch('getFiles', {
- projectId,
- branchId,
- })
- .then(() => {
- if (basePath) {
- const path = basePath.slice(-1) === '/' ? basePath.slice(0, -1) : basePath;
- const treeEntryKey = Object.keys(state.entries).find(
- key => key === path && !state.entries[key].pending,
- );
- const treeEntry = state.entries[treeEntryKey];
+ return dispatch('getFiles', {
+ projectId,
+ branchId,
+ }).then(() => {
+ if (basePath) {
+ const path = basePath.slice(-1) === '/' ? basePath.slice(0, -1) : basePath;
+ const treeEntryKey = Object.keys(state.entries).find(
+ key => key === path && !state.entries[key].pending,
+ );
+ const treeEntry = state.entries[treeEntryKey];
- if (treeEntry) {
- dispatch('handleTreeEntryAction', treeEntry);
- }
+ if (treeEntry) {
+ dispatch('handleTreeEntryAction', treeEntry);
}
- })
- );
+ }
+ });
};
diff --git a/app/assets/javascripts/ide/stores/actions/tree.js b/app/assets/javascripts/ide/stores/actions/tree.js
index 9288bbe32f5..de5f6050074 100644
--- a/app/assets/javascripts/ide/stores/actions/tree.js
+++ b/app/assets/javascripts/ide/stores/actions/tree.js
@@ -76,7 +76,7 @@ export const getFiles = ({ state, commit, dispatch }, { projectId, branchId } =
dispatch('showBranchNotFoundError', branchId);
} else {
dispatch('setErrorMessage', {
- text: __('An error occured whilst loading all the files.'),
+ text: __('An error occurred whilst loading all the files.'),
action: payload =>
dispatch('getFiles', payload).then(() => dispatch('setErrorMessage', null)),
actionText: __('Please try again'),
diff --git a/app/assets/javascripts/ide/stores/getters.js b/app/assets/javascripts/ide/stores/getters.js
index 709748fb530..8ad85074d6b 100644
--- a/app/assets/javascripts/ide/stores/getters.js
+++ b/app/assets/javascripts/ide/stores/getters.js
@@ -63,7 +63,7 @@ export const isEditModeActive = state => state.currentActivityView === activityB
export const isCommitModeActive = state => state.currentActivityView === activityBarViews.commit;
export const isReviewModeActive = state => state.currentActivityView === activityBarViews.review;
-export const someUncommitedChanges = state =>
+export const someUncommittedChanges = state =>
!!(state.changedFiles.length || state.stagedFiles.length);
export const getChangesInFolder = state => path => {
diff --git a/app/assets/javascripts/ide/stores/index.js b/app/assets/javascripts/ide/stores/index.js
index 877d88bb060..f1f544b52b2 100644
--- a/app/assets/javascripts/ide/stores/index.js
+++ b/app/assets/javascripts/ide/stores/index.js
@@ -9,6 +9,7 @@ import pipelines from './modules/pipelines';
import mergeRequests from './modules/merge_requests';
import branches from './modules/branches';
import fileTemplates from './modules/file_templates';
+import paneModule from './modules/pane';
Vue.use(Vuex);
@@ -24,6 +25,7 @@ export const createStore = () =>
mergeRequests,
branches,
fileTemplates: fileTemplates(),
+ rightPane: paneModule(),
},
});
diff --git a/app/assets/javascripts/ide/stores/modules/commit/actions.js b/app/assets/javascripts/ide/stores/modules/commit/actions.js
index 462ca45db9b..d97a950a8b2 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/actions.js
@@ -30,9 +30,9 @@ export const setLastCommitMessage = ({ rootState, commit }, data) => {
const currentProject = rootState.projects[rootState.currentProjectId];
const commitStats = data.stats
? sprintf(__('with %{additions} additions, %{deletions} deletions.'), {
- additions: data.stats.additions, // eslint-disable-line indent-legacy
- deletions: data.stats.deletions, // eslint-disable-line indent-legacy
- }) // eslint-disable-line indent-legacy
+ additions: data.stats.additions,
+ deletions: data.stats.deletions,
+ })
: '';
const commitMsg = sprintf(
__('Your changes have been committed. Commit %{commitId} %{commitStats}'),
diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/actions.js b/app/assets/javascripts/ide/stores/modules/file_templates/actions.js
index dd53213ed18..b7090e09daf 100644
--- a/app/assets/javascripts/ide/stores/modules/file_templates/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/file_templates/actions.js
@@ -1,5 +1,6 @@
import Api from '~/api';
import { __ } from '~/locale';
+import { normalizeHeaders } from '~/lib/utils/common_utils';
import * as types from './mutation_types';
import eventHub from '../../../eventhub';
@@ -22,13 +23,21 @@ export const receiveTemplateTypesError = ({ commit, dispatch }) => {
export const receiveTemplateTypesSuccess = ({ commit }, templates) =>
commit(types.RECEIVE_TEMPLATE_TYPES_SUCCESS, templates);
-export const fetchTemplateTypes = ({ dispatch, state }) => {
+export const fetchTemplateTypes = ({ dispatch, state, rootState }, page = 1) => {
if (!Object.keys(state.selectedTemplateType).length) return Promise.reject();
dispatch('requestTemplateTypes');
- return Api.templates(state.selectedTemplateType.key)
- .then(({ data }) => dispatch('receiveTemplateTypesSuccess', data))
+ return Api.projectTemplates(rootState.currentProjectId, state.selectedTemplateType.key, { page })
+ .then(({ data, headers }) => {
+ const nextPage = parseInt(normalizeHeaders(headers)['X-NEXT-PAGE'], 10);
+
+ dispatch('receiveTemplateTypesSuccess', data);
+
+ if (nextPage) {
+ dispatch('fetchTemplateTypes', nextPage);
+ }
+ })
.catch(() => dispatch('receiveTemplateTypesError'));
};
@@ -65,12 +74,16 @@ export const receiveTemplateError = ({ dispatch }, template) => {
);
};
-export const fetchTemplate = ({ dispatch, state }, template) => {
+export const fetchTemplate = ({ dispatch, state, rootState }, template) => {
if (template.content) {
return dispatch('setFileTemplate', template);
}
- return Api.templates(`${state.selectedTemplateType.key}/${template.key || template.name}`)
+ return Api.projectTemplate(
+ rootState.currentProjectId,
+ state.selectedTemplateType.key,
+ template.key || template.name,
+ )
.then(({ data }) => {
dispatch('setFileTemplate', data);
})
diff --git a/app/assets/javascripts/ide/stores/modules/file_templates/mutations.js b/app/assets/javascripts/ide/stores/modules/file_templates/mutations.js
index 674782a28ca..25a65b047f1 100644
--- a/app/assets/javascripts/ide/stores/modules/file_templates/mutations.js
+++ b/app/assets/javascripts/ide/stores/modules/file_templates/mutations.js
@@ -9,10 +9,11 @@ export default {
},
[types.RECEIVE_TEMPLATE_TYPES_SUCCESS](state, templates) {
state.isLoading = false;
- state.templates = templates;
+ state.templates = state.templates.concat(templates);
},
[types.SET_SELECTED_TEMPLATE_TYPE](state, type) {
state.selectedTemplateType = type;
+ state.templates = [];
},
[types.SET_UPDATE_SUCCESS](state, success) {
state.updateSuccess = success;
diff --git a/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js b/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js
index baa2497ec5b..8b5f7558654 100644
--- a/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js
@@ -3,8 +3,7 @@ import Api from '../../../../api';
import { scopes } from './constants';
import * as types from './mutation_types';
-export const requestMergeRequests = ({ commit }) =>
- commit(types.REQUEST_MERGE_REQUESTS);
+export const requestMergeRequests = ({ commit }) => commit(types.REQUEST_MERGE_REQUESTS);
export const receiveMergeRequestsError = ({ commit, dispatch }, { type, search }) => {
dispatch(
'setErrorMessage',
@@ -24,13 +23,19 @@ export const receiveMergeRequestsError = ({ commit, dispatch }, { type, search }
export const receiveMergeRequestsSuccess = ({ commit }, data) =>
commit(types.RECEIVE_MERGE_REQUESTS_SUCCESS, data);
-export const fetchMergeRequests = ({ dispatch, state: { state } }, { type, search = '' }) => {
+export const fetchMergeRequests = (
+ { dispatch, state: { state }, rootState: { currentProjectId } },
+ { type, search = '' },
+) => {
dispatch('requestMergeRequests');
dispatch('resetMergeRequests');
- const scope = type ? scopes[type] : 'all';
+ const scope = type && scopes[type];
+ const request = scope
+ ? Api.mergeRequests({ scope, state, search })
+ : Api.projectMergeRequest(currentProjectId, '', { state, search });
- return Api.mergeRequests({ scope, state, search })
+ return request
.then(({ data }) => dispatch('receiveMergeRequestsSuccess', data))
.catch(() => dispatch('receiveMergeRequestsError', { type, search }));
};
diff --git a/app/assets/javascripts/ide/stores/modules/pane/actions.js b/app/assets/javascripts/ide/stores/modules/pane/actions.js
new file mode 100644
index 00000000000..7f5d167a14f
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/pane/actions.js
@@ -0,0 +1,30 @@
+import * as types from './mutation_types';
+
+export const toggleOpen = ({ dispatch, state }, view) => {
+ if (state.isOpen) {
+ dispatch('close');
+ } else {
+ dispatch('open', view);
+ }
+};
+
+export const open = ({ commit }, view) => {
+ commit(types.SET_OPEN, true);
+
+ if (view) {
+ const { name, keepAlive } = view;
+
+ commit(types.SET_CURRENT_VIEW, name);
+
+ if (keepAlive) {
+ commit(types.KEEP_ALIVE_VIEW, name);
+ }
+ }
+};
+
+export const close = ({ commit }) => {
+ commit(types.SET_OPEN, false);
+};
+
+// prevent babel-plugin-rewire from generating an invalid default during karma tests
+export default () => {};
diff --git a/app/assets/javascripts/ide/stores/modules/pane/getters.js b/app/assets/javascripts/ide/stores/modules/pane/getters.js
new file mode 100644
index 00000000000..c346cf13689
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/pane/getters.js
@@ -0,0 +1,4 @@
+export const isActiveView = state => view => state.currentView === view;
+
+export const isAliveView = (state, getters) => view =>
+ state.keepAliveViews[view] || (state.isOpen && getters.isActiveView(view));
diff --git a/app/assets/javascripts/ide/stores/modules/pane/index.js b/app/assets/javascripts/ide/stores/modules/pane/index.js
new file mode 100644
index 00000000000..5f61cb732c8
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/pane/index.js
@@ -0,0 +1,12 @@
+import * as actions from './actions';
+import * as getters from './getters';
+import mutations from './mutations';
+import state from './state';
+
+export default () => ({
+ namespaced: true,
+ state: state(),
+ actions,
+ getters,
+ mutations,
+});
diff --git a/app/assets/javascripts/ide/stores/modules/pane/mutation_types.js b/app/assets/javascripts/ide/stores/modules/pane/mutation_types.js
new file mode 100644
index 00000000000..abdebc4d913
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/pane/mutation_types.js
@@ -0,0 +1,3 @@
+export const SET_OPEN = 'SET_OPEN';
+export const SET_CURRENT_VIEW = 'SET_CURRENT_VIEW';
+export const KEEP_ALIVE_VIEW = 'KEEP_ALIVE_VIEW';
diff --git a/app/assets/javascripts/ide/stores/modules/pane/mutations.js b/app/assets/javascripts/ide/stores/modules/pane/mutations.js
new file mode 100644
index 00000000000..c16484b4402
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/pane/mutations.js
@@ -0,0 +1,19 @@
+import * as types from './mutation_types';
+
+export default {
+ [types.SET_OPEN](state, isOpen) {
+ Object.assign(state, {
+ isOpen,
+ });
+ },
+ [types.SET_CURRENT_VIEW](state, currentView) {
+ Object.assign(state, {
+ currentView,
+ });
+ },
+ [types.KEEP_ALIVE_VIEW](state, viewName) {
+ Object.assign(state.keepAliveViews, {
+ [viewName]: true,
+ });
+ },
+};
diff --git a/app/assets/javascripts/ide/stores/modules/pane/state.js b/app/assets/javascripts/ide/stores/modules/pane/state.js
new file mode 100644
index 00000000000..353065b5735
--- /dev/null
+++ b/app/assets/javascripts/ide/stores/modules/pane/state.js
@@ -0,0 +1,5 @@
+export default () => ({
+ isOpen: false,
+ currentView: null,
+ keepAliveViews: {},
+});
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
index 3e67b222e66..51cf4dede42 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js
@@ -28,7 +28,7 @@ export const receiveLatestPipelineError = ({ commit, dispatch }, err) => {
dispatch(
'setErrorMessage',
{
- text: __('An error occured whilst fetching the latest pipline.'),
+ text: __('An error occurred whilst fetching the latest pipeline.'),
action: () =>
dispatch('forcePipelineRequest').then(() =>
dispatch('setErrorMessage', null, { root: true }),
@@ -84,7 +84,7 @@ export const receiveJobsError = ({ commit, dispatch }, stage) => {
dispatch(
'setErrorMessage',
{
- text: __('An error occured whilst loading the pipelines jobs.'),
+ text: __('An error occurred whilst loading the pipelines jobs.'),
action: payload =>
dispatch('fetchJobs', payload).then(() =>
dispatch('setErrorMessage', null, { root: true }),
@@ -113,7 +113,7 @@ export const toggleStageCollapsed = ({ commit }, stageId) =>
export const setDetailJob = ({ commit, dispatch }, job) => {
commit(types.SET_DETAIL_JOB, job);
- dispatch('setRightPane', job ? rightSidebarViews.jobsDetail : rightSidebarViews.pipelines, {
+ dispatch('rightPane/open', job ? rightSidebarViews.jobsDetail : rightSidebarViews.pipelines, {
root: true,
});
};
@@ -123,7 +123,7 @@ export const receiveJobTraceError = ({ commit, dispatch }) => {
dispatch(
'setErrorMessage',
{
- text: __('An error occured whilst fetching the job trace.'),
+ text: __('An error occurred whilst fetching the job trace.'),
action: () =>
dispatch('fetchJobTrace').then(() => dispatch('setErrorMessage', null, { root: true })),
actionText: __('Please try again'),
diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/getters.js b/app/assets/javascripts/ide/stores/modules/pipelines/getters.js
index f545453806f..ef7cd4ff8e8 100644
--- a/app/assets/javascripts/ide/stores/modules/pipelines/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/pipelines/getters.js
@@ -6,10 +6,12 @@ export const pipelineFailed = state =>
state.latestPipeline && state.latestPipeline.details.status.text === states.failed;
export const failedStages = state =>
- state.stages.filter(stage => stage.status.text.toLowerCase() === states.failed).map(stage => ({
- ...stage,
- jobs: stage.jobs.filter(job => job.status.text.toLowerCase() === states.failed),
- }));
+ state.stages
+ .filter(stage => stage.status.text.toLowerCase() === states.failed)
+ .map(stage => ({
+ ...stage,
+ jobs: stage.jobs.filter(job => job.status.text.toLowerCase() === states.failed),
+ }));
export const failedJobsCount = state =>
state.stages.reduce(
diff --git a/app/assets/javascripts/ide/stores/mutation_types.js b/app/assets/javascripts/ide/stores/mutation_types.js
index 5a7991d2fa7..a5f8098dc17 100644
--- a/app/assets/javascripts/ide/stores/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/mutation_types.js
@@ -68,8 +68,6 @@ export const UPDATE_TEMP_FLAG = 'UPDATE_TEMP_FLAG';
export const TOGGLE_FILE_FINDER = 'TOGGLE_FILE_FINDER';
export const BURST_UNUSED_SEAL = 'BURST_UNUSED_SEAL';
-export const SET_RIGHT_PANE = 'SET_RIGHT_PANE';
-
export const CLEAR_PROJECTS = 'CLEAR_PROJECTS';
export const RESET_OPEN_FILES = 'RESET_OPEN_FILES';
diff --git a/app/assets/javascripts/ide/stores/mutations.js b/app/assets/javascripts/ide/stores/mutations.js
index 2c8535bda59..78cdfda74f0 100644
--- a/app/assets/javascripts/ide/stores/mutations.js
+++ b/app/assets/javascripts/ide/stores/mutations.js
@@ -166,11 +166,6 @@ export default {
unusedSeal: false,
});
},
- [types.SET_RIGHT_PANE](state, view) {
- Object.assign(state, {
- rightPane: state.rightPane === view ? null : view,
- });
- },
[types.SET_LINKS](state, links) {
Object.assign(state, { links });
},
diff --git a/app/assets/javascripts/ide/stores/state.js b/app/assets/javascripts/ide/stores/state.js
index 46b52fa00fc..d400b9831a9 100644
--- a/app/assets/javascripts/ide/stores/state.js
+++ b/app/assets/javascripts/ide/stores/state.js
@@ -23,7 +23,6 @@ export default () => ({
currentActivityView: activityBarViews.edit,
unusedSeal: true,
fileFindVisible: false,
- rightPane: null,
links: {},
errorMessage: null,
entryModal: {
diff --git a/app/assets/javascripts/image_diff/image_diff.js b/app/assets/javascripts/image_diff/image_diff.js
index fab0255c378..3587f073a00 100644
--- a/app/assets/javascripts/image_diff/image_diff.js
+++ b/app/assets/javascripts/image_diff/image_diff.js
@@ -60,8 +60,10 @@ export default class ImageDiff {
}
renderBadge(discussionEl, index) {
- const imageBadge = imageDiffHelper
- .generateBadgeFromDiscussionDOM(this.imageFrameEl, discussionEl);
+ const imageBadge = imageDiffHelper.generateBadgeFromDiscussionDOM(
+ this.imageFrameEl,
+ discussionEl,
+ );
this.imageBadges.push(imageBadge);
diff --git a/app/assets/javascripts/image_diff/init_discussion_tab.js b/app/assets/javascripts/image_diff/init_discussion_tab.js
index 2f16c6ef115..dbe4c06a4e9 100644
--- a/app/assets/javascripts/image_diff/init_discussion_tab.js
+++ b/app/assets/javascripts/image_diff/init_discussion_tab.js
@@ -8,5 +8,6 @@ export default () => {
const diffFileEls = document.querySelectorAll('.timeline-content .diff-file.js-image-file');
[...diffFileEls].forEach(diffFileEl =>
- imageDiffHelper.initImageDiff(diffFileEl, canCreateNote, renderCommentBadge));
+ imageDiffHelper.initImageDiff(diffFileEl, canCreateNote, renderCommentBadge),
+ );
};
diff --git a/app/assets/javascripts/image_diff/replaced_image_diff.js b/app/assets/javascripts/image_diff/replaced_image_diff.js
index 4abd13fb472..8d9e65155d8 100644
--- a/app/assets/javascripts/image_diff/replaced_image_diff.js
+++ b/app/assets/javascripts/image_diff/replaced_image_diff.js
@@ -26,7 +26,7 @@ export default class ReplacedImageDiff extends ImageDiff {
this.imageEls = {};
const viewTypeNames = Object.getOwnPropertyNames(viewTypes);
- viewTypeNames.forEach((viewType) => {
+ viewTypeNames.forEach(viewType => {
this.imageEls[viewType] = this.imageFrameEls[viewType].querySelector('img');
});
}
@@ -79,13 +79,12 @@ export default class ReplacedImageDiff extends ImageDiff {
// Re-render indicator in new view
if (indicator.removed) {
- const normalizedIndicator = imageDiffHelper
- .resizeCoordinatesToImageElement(this.imageEl, {
- x: indicator.x,
- y: indicator.y,
- width: indicator.image.width,
- height: indicator.image.height,
- });
+ const normalizedIndicator = imageDiffHelper.resizeCoordinatesToImageElement(this.imageEl, {
+ x: indicator.x,
+ y: indicator.y,
+ width: indicator.image.width,
+ height: indicator.image.height,
+ });
imageDiffHelper.showCommentIndicator(this.imageFrameEl, normalizedIndicator);
}
}
diff --git a/app/assets/javascripts/importer_status.js b/app/assets/javascripts/importer_status.js
index eda8cdad908..1ffd5c61282 100644
--- a/app/assets/javascripts/importer_status.js
+++ b/app/assets/javascripts/importer_status.js
@@ -3,7 +3,7 @@ import _ from 'underscore';
import { __, sprintf } from './locale';
import axios from './lib/utils/axios_utils';
import flash from './flash';
-import { convertPermissionToBoolean } from './lib/utils/common_utils';
+import { parseBoolean } from './lib/utils/common_utils';
class ImporterStatus {
constructor({ jobsUrl, importUrl, ciCdOnly }) {
@@ -60,66 +60,71 @@ class ImporterStatus {
attributes = Object.assign(repoData, attributes);
}
- return axios.post(this.importUrl, attributes)
- .then(({ data }) => {
- const job = $(`tr#repo_${id}`);
- job.attr('id', `project_${data.id}`);
-
- job.find('.import-target').html(`<a href="${data.full_path}">${data.full_path}</a>`);
- $('table.import-jobs tbody').prepend(job);
-
- job.addClass('table-active');
- const connectingVerb = this.ciCdOnly ? __('connecting') : __('importing');
- job.find('.import-actions').html(sprintf(
- _.escape(__('%{loadingIcon} Started')), {
- loadingIcon: `<i class="fa fa-spinner fa-spin" aria-label="${_.escape(connectingVerb)}"></i>`,
- },
- false,
- ));
- })
- .catch((error) => {
- let details = error;
-
- const $statusField = $(`#repo_${this.id} .job-status`);
- $statusField.text(__('Failed'));
-
- if (error.response && error.response.data && error.response.data.errors) {
- details = error.response.data.errors;
- }
-
- flash(sprintf(__('An error occurred while importing project: %{details}'), { details }));
- });
+ return axios
+ .post(this.importUrl, attributes)
+ .then(({ data }) => {
+ const job = $(`tr#repo_${id}`);
+ job.attr('id', `project_${data.id}`);
+
+ job.find('.import-target').html(`<a href="${data.full_path}">${data.full_path}</a>`);
+ $('table.import-jobs tbody').prepend(job);
+
+ job.addClass('table-active');
+ const connectingVerb = this.ciCdOnly ? __('connecting') : __('importing');
+ job.find('.import-actions').html(
+ sprintf(
+ _.escape(__('%{loadingIcon} Started')),
+ {
+ loadingIcon: `<i class="fa fa-spinner fa-spin" aria-label="${_.escape(
+ connectingVerb,
+ )}"></i>`,
+ },
+ false,
+ ),
+ );
+ })
+ .catch(error => {
+ let details = error;
+
+ const $statusField = $(`#repo_${this.id} .job-status`);
+ $statusField.text(__('Failed'));
+
+ if (error.response && error.response.data && error.response.data.errors) {
+ details = error.response.data.errors;
+ }
+
+ flash(sprintf(__('An error occurred while importing project: %{details}'), { details }));
+ });
}
autoUpdate() {
- return axios.get(this.jobsUrl)
- .then(({ data = [] }) => {
- data.forEach((job) => {
- const jobItem = $(`#project_${job.id}`);
- const statusField = jobItem.find('.job-status');
-
- const spinner = '<i class="fa fa-spinner fa-spin"></i>';
-
- switch (job.import_status) {
- case 'finished':
- jobItem.removeClass('table-active').addClass('table-success');
- statusField.html(`<span><i class="fa fa-check"></i> ${__('Done')}</span>`);
- break;
- case 'scheduled':
- statusField.html(`${spinner} ${__('Scheduled')}`);
- break;
- case 'started':
- statusField.html(`${spinner} ${__('Started')}`);
- break;
- case 'failed':
- statusField.html(__('Failed'));
- break;
- default:
- statusField.html(job.import_status);
- break;
- }
- });
+ return axios.get(this.jobsUrl).then(({ data = [] }) => {
+ data.forEach(job => {
+ const jobItem = $(`#project_${job.id}`);
+ const statusField = jobItem.find('.job-status');
+
+ const spinner = '<i class="fa fa-spinner fa-spin"></i>';
+
+ switch (job.import_status) {
+ case 'finished':
+ jobItem.removeClass('table-active').addClass('table-success');
+ statusField.html(`<span><i class="fa fa-check"></i> ${__('Done')}</span>`);
+ break;
+ case 'scheduled':
+ statusField.html(`${spinner} ${__('Scheduled')}`);
+ break;
+ case 'started':
+ statusField.html(`${spinner} ${__('Started')}`);
+ break;
+ case 'failed':
+ statusField.html(__('Failed'));
+ break;
+ default:
+ statusField.html(job.import_status);
+ break;
+ }
});
+ });
}
setAutoUpdate() {
@@ -136,12 +141,9 @@ function initImporterStatus() {
return new ImporterStatus({
jobsUrl: data.jobsImportPath,
importUrl: data.importPath,
- ciCdOnly: convertPermissionToBoolean(data.ciCdOnly),
+ ciCdOnly: parseBoolean(data.ciCdOnly),
});
}
}
-export {
- initImporterStatus as default,
- ImporterStatus,
-};
+export { initImporterStatus as default, ImporterStatus };
diff --git a/app/assets/javascripts/init_changes_dropdown.js b/app/assets/javascripts/init_changes_dropdown.js
index 5c5a6e01848..e708e5d0978 100644
--- a/app/assets/javascripts/init_changes_dropdown.js
+++ b/app/assets/javascripts/init_changes_dropdown.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import { stickyMonitor } from './lib/utils/sticky';
-export default (stickyTop) => {
+export default stickyTop => {
stickyMonitor(document.querySelector('.js-diff-files-changed'), stickyTop);
$('.js-diff-stats-dropdown').glDropdown({
diff --git a/app/assets/javascripts/init_legacy_filters.js b/app/assets/javascripts/init_legacy_filters.js
deleted file mode 100644
index b6ff97d1279..00000000000
--- a/app/assets/javascripts/init_legacy_filters.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/* eslint-disable no-new */
-import LabelsSelect from './labels_select';
-import subscriptionSelect from './subscription_select';
-import UsersSelect from './users_select';
-import issueStatusSelect from './issue_status_select';
-import MilestoneSelect from './milestone_select';
-
-export default () => {
- new UsersSelect();
- new LabelsSelect();
- new MilestoneSelect();
- issueStatusSelect();
- subscriptionSelect();
-};
diff --git a/app/assets/javascripts/init_notes.js b/app/assets/javascripts/init_notes.js
index 3c71258e53b..a77828e8cf2 100644
--- a/app/assets/javascripts/init_notes.js
+++ b/app/assets/javascripts/init_notes.js
@@ -2,13 +2,7 @@ import Notes from './notes';
export default () => {
const dataEl = document.querySelector('.js-notes-data');
- const {
- notesUrl,
- notesIds,
- now,
- diffView,
- enableGFM,
- } = JSON.parse(dataEl.innerHTML);
+ const { notesUrl, notesIds, now, diffView, enableGFM } = JSON.parse(dataEl.innerHTML);
// Create a singleton so that we don't need to assign
// into the window object, we can just access the current isntance with Notes.instance
diff --git a/app/assets/javascripts/integrations/integration_settings_form.js b/app/assets/javascripts/integrations/integration_settings_form.js
index bd90d0eaa32..08b858305ab 100644
--- a/app/assets/javascripts/integrations/integration_settings_form.js
+++ b/app/assets/javascripts/integrations/integration_settings_form.js
@@ -97,7 +97,8 @@ export default class IntegrationSettingsForm {
testSettings(formData) {
this.toggleSubmitBtnState(true);
- return axios.put(this.testEndPoint, formData)
+ return axios
+ .put(this.testEndPoint, formData)
.then(({ data }) => {
if (data.error) {
let flashActions;
@@ -105,7 +106,7 @@ export default class IntegrationSettingsForm {
if (data.test_failed) {
flashActions = {
title: 'Save anyway',
- clickHandler: (e) => {
+ clickHandler: e => {
e.preventDefault();
this.$form.submit();
},
diff --git a/app/assets/javascripts/issuable/auto_width_dropdown_select.js b/app/assets/javascripts/issuable/auto_width_dropdown_select.js
index 07cf1eff279..612c524ca1c 100644
--- a/app/assets/javascripts/issuable/auto_width_dropdown_select.js
+++ b/app/assets/javascripts/issuable/auto_width_dropdown_select.js
@@ -27,7 +27,10 @@ class AutoWidthDropdownSelect {
// We have to look at the parent because
// `offsetParent` on a `display: none;` is `null`
- const offsetParentWidth = $(this).parent().offsetParent().width();
+ const offsetParentWidth = $(this)
+ .parent()
+ .offsetParent()
+ .width();
// Reset any width to let it naturally flow
$dropdown.css('width', 'auto');
if ($dropdown.outerWidth(false) > offsetParentWidth) {
diff --git a/app/assets/javascripts/issuable_bulk_update_actions.js b/app/assets/javascripts/issuable_bulk_update_actions.js
index 9e848699163..b844e4c5e5b 100644
--- a/app/assets/javascripts/issuable_bulk_update_actions.js
+++ b/app/assets/javascripts/issuable_bulk_update_actions.js
@@ -1,4 +1,4 @@
-/* eslint-disable comma-dangle, quotes, consistent-return, func-names, array-callback-return, prefer-arrow-callback, max-len, no-unused-vars */
+/* eslint-disable consistent-return, func-names, array-callback-return, prefer-arrow-callback, no-unused-vars */
import $ from 'jquery';
import _ from 'underscore';
@@ -32,7 +32,7 @@ export default {
onFormSubmitFailure() {
this.form.find('[type="submit"]').enable();
- return new Flash("Issue update failed");
+ return new Flash('Issue update failed');
},
getSelectedIssues() {
@@ -63,7 +63,7 @@ export default {
const result = [];
const labelsToKeep = this.$labelDropdown.data('indeterminate');
- this.getLabelsFromSelection().forEach((id) => {
+ this.getLabelsFromSelection().forEach(id => {
if (labelsToKeep.indexOf(id) === -1) {
result.push(id);
}
@@ -89,8 +89,8 @@ export default {
issuable_ids: this.form.find('input[name="update[issuable_ids]"]').val(),
subscription_event: this.form.find('input[name="update[subscription_event]"]').val(),
add_label_ids: [],
- remove_label_ids: []
- }
+ remove_label_ids: [],
+ },
};
if (this.willUpdateLabels) {
formData.update.add_label_ids = this.$labelDropdown.data('marked');
@@ -134,7 +134,7 @@ export default {
// Collect unique label IDs for all checked issues
this.getElement('.selected-issuable:checked').each((i, el) => {
issuableLabels = this.getElement(`#${this.prefixId}${el.dataset.id}`).data('labels');
- issuableLabels.forEach((labelId) => {
+ issuableLabels.forEach(labelId => {
// Store unique IDs
if (uniqueIds.indexOf(labelId) === -1) {
uniqueIds.push(labelId);
diff --git a/app/assets/javascripts/issuable_form.js b/app/assets/javascripts/issuable_form.js
index 0140960b367..c81a2230310 100644
--- a/app/assets/javascripts/issuable_form.js
+++ b/app/assets/javascripts/issuable_form.js
@@ -1,6 +1,3 @@
-/* eslint-disable no-new, no-unused-vars, consistent-return, no-else-return */
-/* global GitLab */
-
import $ from 'jquery';
import Pikaday from 'pikaday';
import Autosave from './autosave';
@@ -8,7 +5,7 @@ import UsersSelect from './users_select';
import GfmAutoComplete from './gfm_auto_complete';
import ZenMode from './zen_mode';
import AutoWidthDropdownSelect from './issuable/auto_width_dropdown_select';
-import { parsePikadayDate, pikadayToString } from './lib/utils/datefix';
+import { parsePikadayDate, pikadayToString } from './lib/utils/datetime_utility';
export default class IssuableForm {
constructor(form) {
@@ -19,9 +16,11 @@ export default class IssuableForm {
this.handleSubmit = this.handleSubmit.bind(this);
this.wipRegex = /^\s*(\[WIP\]\s*|WIP:\s*|WIP\s+)+\s*/i;
- new GfmAutoComplete(gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources).setup();
- new UsersSelect();
- new ZenMode();
+ this.gfmAutoComplete = new GfmAutoComplete(
+ gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources,
+ ).setup();
+ this.usersSelect = new UsersSelect();
+ this.zenMode = new ZenMode();
this.titleField = this.form.find('input[name*="[title]"]');
this.descriptionField = this.form.find('textarea[name*="[description]"]');
@@ -57,8 +56,16 @@ export default class IssuableForm {
}
initAutosave() {
- new Autosave(this.titleField, [document.location.pathname, document.location.search, 'title']);
- return new Autosave(this.descriptionField, [document.location.pathname, document.location.search, 'description']);
+ this.autosave = new Autosave(this.titleField, [
+ document.location.pathname,
+ document.location.search,
+ 'title',
+ ]);
+ return new Autosave(this.descriptionField, [
+ document.location.pathname,
+ document.location.search,
+ 'description',
+ ]);
}
handleSubmit() {
@@ -74,7 +81,7 @@ export default class IssuableForm {
this.$wipExplanation = this.form.find('.js-wip-explanation');
this.$noWipExplanation = this.form.find('.js-no-wip-explanation');
if (!(this.$wipExplanation.length && this.$noWipExplanation.length)) {
- return;
+ return undefined;
}
this.form.on('click', '.js-toggle-wip', this.toggleWip);
this.titleField.on('keyup blur', this.renderWipExplanation);
@@ -89,10 +96,9 @@ export default class IssuableForm {
if (this.workInProgress()) {
this.$wipExplanation.show();
return this.$noWipExplanation.hide();
- } else {
- this.$wipExplanation.hide();
- return this.$noWipExplanation.show();
}
+ this.$wipExplanation.hide();
+ return this.$noWipExplanation.show();
}
toggleWip(event) {
@@ -110,7 +116,7 @@ export default class IssuableForm {
}
addWip() {
- this.titleField.val(`WIP: ${(this.titleField.val())}`);
+ this.titleField.val(`WIP: ${this.titleField.val()}`);
}
initTargetBranchDropdown() {
diff --git a/app/assets/javascripts/issuable_index.js b/app/assets/javascripts/issuable_index.js
index 06ec4546164..ffcbd7cf28c 100644
--- a/app/assets/javascripts/issuable_index.js
+++ b/app/assets/javascripts/issuable_index.js
@@ -26,14 +26,17 @@ export default class IssuableIndex {
static resetIncomingEmailToken() {
const $resetToken = $('.incoming-email-token-reset');
- $resetToken.on('click', (e) => {
+ $resetToken.on('click', e => {
e.preventDefault();
$resetToken.text('resetting...');
- axios.put($resetToken.attr('href'))
+ axios
+ .put($resetToken.attr('href'))
.then(({ data }) => {
- $('#issuable_email').val(data.new_address).focus();
+ $('#issuable_email')
+ .val(data.new_address)
+ .focus();
$resetToken.text('reset it');
})
diff --git a/app/assets/javascripts/issuable_suggestions/components/app.vue b/app/assets/javascripts/issuable_suggestions/components/app.vue
new file mode 100644
index 00000000000..eea0701312b
--- /dev/null
+++ b/app/assets/javascripts/issuable_suggestions/components/app.vue
@@ -0,0 +1,96 @@
+<script>
+import _ from 'underscore';
+import { GlTooltipDirective } from '@gitlab/ui';
+import { __ } from '~/locale';
+import Icon from '~/vue_shared/components/icon.vue';
+import Suggestion from './item.vue';
+import query from '../queries/issues.graphql';
+
+export default {
+ components: {
+ Suggestion,
+ Icon,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ search: {
+ type: String,
+ required: true,
+ },
+ },
+ apollo: {
+ issues: {
+ query,
+ debounce: 250,
+ skip() {
+ return this.isSearchEmpty;
+ },
+ update: data => data.project.issues.edges.map(({ node }) => node),
+ variables() {
+ return {
+ fullPath: this.projectPath,
+ search: this.search,
+ };
+ },
+ },
+ },
+ data() {
+ return {
+ issues: [],
+ loading: 0,
+ };
+ },
+ computed: {
+ isSearchEmpty() {
+ return _.isEmpty(this.search);
+ },
+ showSuggestions() {
+ return !this.isSearchEmpty && this.issues.length && !this.loading;
+ },
+ },
+ watch: {
+ search() {
+ if (this.isSearchEmpty) {
+ this.issues = [];
+ }
+ },
+ },
+ helpText: __(
+ 'These existing issues have a similar title. It might be better to comment there instead of creating another similar issue.',
+ ),
+};
+</script>
+
+<template>
+ <div v-show="showSuggestions" class="form-group row issuable-suggestions">
+ <div v-once class="col-form-label col-sm-2 pt-0">
+ {{ __('Similar issues') }}
+ <icon
+ v-gl-tooltip.bottom
+ :title="$options.helpText"
+ :aria-label="$options.helpText"
+ name="question-o"
+ class="text-secondary suggestion-help-hover"
+ />
+ </div>
+ <div class="col-sm-10">
+ <ul class="list-unstyled m-0">
+ <li
+ v-for="(suggestion, index) in issues"
+ :key="suggestion.id"
+ :class="{
+ 'append-bottom-default': index !== issues.length - 1,
+ }"
+ >
+ <suggestion :suggestion="suggestion" />
+ </li>
+ </ul>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issuable_suggestions/components/item.vue b/app/assets/javascripts/issuable_suggestions/components/item.vue
new file mode 100644
index 00000000000..9a16b486bf5
--- /dev/null
+++ b/app/assets/javascripts/issuable_suggestions/components/item.vue
@@ -0,0 +1,137 @@
+<script>
+import _ from 'underscore';
+import { GlLink, GlTooltip, GlTooltipDirective } from '@gitlab/ui';
+import { __ } from '~/locale';
+import Icon from '~/vue_shared/components/icon.vue';
+import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
+import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import timeago from '~/vue_shared/mixins/timeago';
+
+export default {
+ components: {
+ GlTooltip,
+ GlLink,
+ Icon,
+ UserAvatarImage,
+ TimeagoTooltip,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ mixins: [timeago],
+ props: {
+ suggestion: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ isOpen() {
+ return this.suggestion.state === 'opened';
+ },
+ isClosed() {
+ return this.suggestion.state === 'closed';
+ },
+ counts() {
+ return [
+ {
+ id: _.uniqueId(),
+ icon: 'thumb-up',
+ tooltipTitle: __('Upvotes'),
+ count: this.suggestion.upvotes,
+ },
+ {
+ id: _.uniqueId(),
+ icon: 'comment',
+ tooltipTitle: __('Comments'),
+ count: this.suggestion.userNotesCount,
+ },
+ ].filter(({ count }) => count);
+ },
+ stateIcon() {
+ return this.isClosed ? 'issue-close' : 'issue-open-m';
+ },
+ stateTitle() {
+ return this.isClosed ? __('Closed') : __('Opened');
+ },
+ closedOrCreatedDate() {
+ return this.suggestion.closedAt || this.suggestion.createdAt;
+ },
+ hasUpdated() {
+ return this.suggestion.updatedAt !== this.suggestion.createdAt;
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="suggestion-item">
+ <div class="d-flex align-items-center">
+ <icon
+ v-if="suggestion.confidential"
+ v-gl-tooltip.bottom
+ :title="__('Confidential')"
+ name="eye-slash"
+ class="suggestion-help-hover mr-1 suggestion-confidential"
+ />
+ <gl-link :href="suggestion.webUrl" target="_blank" class="suggestion bold str-truncated-100">
+ {{ suggestion.title }}
+ </gl-link>
+ </div>
+ <div class="text-secondary suggestion-footer">
+ <icon
+ ref="state"
+ :name="stateIcon"
+ :class="{
+ 'suggestion-state-open': isOpen,
+ 'suggestion-state-closed': isClosed,
+ }"
+ class="suggestion-help-hover"
+ />
+ <gl-tooltip :target="() => $refs.state" placement="bottom">
+ <span class="d-block">
+ <span class="bold"> {{ stateTitle }} </span> {{ timeFormated(closedOrCreatedDate) }}
+ </span>
+ <span class="text-tertiary">{{ tooltipTitle(closedOrCreatedDate) }}</span>
+ </gl-tooltip>
+ #{{ suggestion.iid }} &bull;
+ <timeago-tooltip
+ :time="suggestion.createdAt"
+ tooltip-placement="bottom"
+ class="suggestion-help-hover"
+ />
+ by
+ <gl-link :href="suggestion.author.webUrl">
+ <user-avatar-image
+ :img-src="suggestion.author.avatarUrl"
+ :size="16"
+ css-classes="mr-0 float-none"
+ tooltip-placement="bottom"
+ class="d-inline-block"
+ >
+ <span class="bold d-block">{{ __('Author') }}</span> {{ suggestion.author.name }}
+ <span class="text-tertiary">@{{ suggestion.author.username }}</span>
+ </user-avatar-image>
+ </gl-link>
+ <template v-if="hasUpdated">
+ &bull; {{ __('updated') }}
+ <timeago-tooltip
+ :time="suggestion.updatedAt"
+ tooltip-placement="bottom"
+ class="suggestion-help-hover"
+ />
+ </template>
+ <span class="suggestion-counts">
+ <span
+ v-for="{ count, icon, tooltipTitle, id } in counts"
+ :key="id"
+ v-gl-tooltip.bottom
+ :title="tooltipTitle"
+ class="suggestion-help-hover prepend-left-8 text-tertiary"
+ >
+ <icon :name="icon" /> {{ count }}
+ </span>
+ </span>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issuable_suggestions/index.js b/app/assets/javascripts/issuable_suggestions/index.js
new file mode 100644
index 00000000000..2c80cf1797a
--- /dev/null
+++ b/app/assets/javascripts/issuable_suggestions/index.js
@@ -0,0 +1,38 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import defaultClient from '~/lib/graphql';
+import App from './components/app.vue';
+
+Vue.use(VueApollo);
+
+export default function() {
+ const el = document.getElementById('js-suggestions');
+ const issueTitle = document.getElementById('issue_title');
+ const { projectPath } = el.dataset;
+ const apolloProvider = new VueApollo({
+ defaultClient,
+ });
+
+ return new Vue({
+ el,
+ apolloProvider,
+ data() {
+ return {
+ search: issueTitle.value,
+ };
+ },
+ mounted() {
+ issueTitle.addEventListener('input', () => {
+ this.search = issueTitle.value;
+ });
+ },
+ render(h) {
+ return h(App, {
+ props: {
+ projectPath,
+ search: this.search,
+ },
+ });
+ },
+ });
+}
diff --git a/app/assets/javascripts/issuable_suggestions/queries/issues.graphql b/app/assets/javascripts/issuable_suggestions/queries/issues.graphql
new file mode 100644
index 00000000000..2384b381344
--- /dev/null
+++ b/app/assets/javascripts/issuable_suggestions/queries/issues.graphql
@@ -0,0 +1,26 @@
+query issueSuggestion($fullPath: ID!, $search: String) {
+ project(fullPath: $fullPath) {
+ issues(search: $search, sort: updated_desc, first: 5) {
+ edges {
+ node {
+ iid
+ title
+ confidential
+ userNotesCount
+ upvotes
+ webUrl
+ state
+ closedAt
+ createdAt
+ updatedAt
+ author {
+ name
+ username
+ avatarUrl
+ webUrl
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/issue.js b/app/assets/javascripts/issue.js
index 8c225cd7d91..94b78907d9a 100644
--- a/app/assets/javascripts/issue.js
+++ b/app/assets/javascripts/issue.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-var, one-var, one-var-declaration-per-line, no-unused-vars, consistent-return, quotes, max-len */
+/* eslint-disable no-var, one-var, no-unused-vars, consistent-return */
import $ from 'jquery';
import axios from './lib/utils/axios_utils';
@@ -28,7 +28,7 @@ export default class Issue {
}
// Listen to state changes in the Vue app
- document.addEventListener('issuable_vue_app:change', (event) => {
+ document.addEventListener('issuable_vue_app:change', event => {
this.updateTopState(event.detail.isClosed, event.detail.data);
});
}
@@ -55,7 +55,13 @@ export default class Issue {
$(document).trigger('issuable:change', isClosed);
this.toggleCloseReopenButton(isClosed);
- let numProjectIssues = Number(projectIssuesCounter.first().text().trim().replace(/[^\d]/, ''));
+ let numProjectIssues = Number(
+ projectIssuesCounter
+ .first()
+ .text()
+ .trim()
+ .replace(/[^\d]/, ''),
+ );
numProjectIssues = isClosed ? numProjectIssues - 1 : numProjectIssues + 1;
projectIssuesCounter.text(addDelimiter(numProjectIssues));
@@ -76,29 +82,34 @@ export default class Issue {
initIssueBtnEventListeners() {
const issueFailMessage = 'Unable to update this issue at this time.';
- return $(document).on('click', '.js-issuable-actions a.btn-close, .js-issuable-actions a.btn-reopen', (e) => {
- var $button, shouldSubmit, url;
- e.preventDefault();
- e.stopImmediatePropagation();
- $button = $(e.currentTarget);
- shouldSubmit = $button.hasClass('btn-comment');
- if (shouldSubmit) {
- Issue.submitNoteForm($button.closest('form'));
- }
-
- this.disableCloseReopenButton($button);
+ return $(document).on(
+ 'click',
+ '.js-issuable-actions a.btn-close, .js-issuable-actions a.btn-reopen',
+ e => {
+ var $button, shouldSubmit, url;
+ e.preventDefault();
+ e.stopImmediatePropagation();
+ $button = $(e.currentTarget);
+ shouldSubmit = $button.hasClass('btn-comment');
+ if (shouldSubmit) {
+ Issue.submitNoteForm($button.closest('form'));
+ }
- url = $button.attr('href');
- return axios.put(url)
- .then(({ data }) => {
- const isClosed = $button.hasClass('btn-close');
- this.updateTopState(isClosed, data);
- })
- .catch(() => flash(issueFailMessage))
- .then(() => {
- this.disableCloseReopenButton($button, false);
- });
- });
+ this.disableCloseReopenButton($button);
+
+ url = $button.attr('href');
+ return axios
+ .put(url)
+ .then(({ data }) => {
+ const isClosed = $button.hasClass('btn-close');
+ this.updateTopState(isClosed, data);
+ })
+ .catch(() => flash(issueFailMessage))
+ .then(() => {
+ this.disableCloseReopenButton($button, false);
+ });
+ },
+ );
}
initCloseReopenReport() {
@@ -124,7 +135,7 @@ export default class Issue {
static submitNoteForm(form) {
var noteText;
- noteText = form.find("textarea.js-note-text").val();
+ noteText = form.find('textarea.js-note-text').val();
if (noteText && noteText.trim().length > 0) {
return form.submit();
}
@@ -133,22 +144,26 @@ export default class Issue {
static initMergeRequests() {
var $container;
$container = $('#merge-requests');
- return axios.get($container.data('url'))
+ return axios
+ .get($container.data('url'))
.then(({ data }) => {
if ('html' in data) {
$container.html(data.html);
}
- }).catch(() => flash('Failed to load referenced merge requests'));
+ })
+ .catch(() => flash('Failed to load referenced merge requests'));
}
static initRelatedBranches() {
var $container;
$container = $('#related-branches');
- return axios.get($container.data('url'))
+ return axios
+ .get($container.data('url'))
.then(({ data }) => {
if ('html' in data) {
$container.html(data.html);
}
- }).catch(() => flash('Failed to load related branches'));
+ })
+ .catch(() => flash('Failed to load related branches'));
}
}
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index ad928484952..e4e2eab2acd 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -1,281 +1,279 @@
<script>
- import Visibility from 'visibilityjs';
- import { visitUrl } from '../../lib/utils/url_utility';
- import Poll from '../../lib/utils/poll';
- import eventHub from '../event_hub';
- import Service from '../services/index';
- import Store from '../stores';
- import titleComponent from './title.vue';
- import descriptionComponent from './description.vue';
- import editedComponent from './edited.vue';
- import formComponent from './form.vue';
- import recaptchaModalImplementor from '../../vue_shared/mixins/recaptcha_modal_implementor';
+import Visibility from 'visibilityjs';
+import { visitUrl } from '../../lib/utils/url_utility';
+import Poll from '../../lib/utils/poll';
+import eventHub from '../event_hub';
+import Service from '../services/index';
+import Store from '../stores';
+import titleComponent from './title.vue';
+import descriptionComponent from './description.vue';
+import editedComponent from './edited.vue';
+import formComponent from './form.vue';
+import recaptchaModalImplementor from '../../vue_shared/mixins/recaptcha_modal_implementor';
- export default {
- components: {
- descriptionComponent,
- titleComponent,
- editedComponent,
- formComponent,
- },
- mixins: [
- recaptchaModalImplementor,
- ],
- props: {
- endpoint: {
- required: true,
- type: String,
- },
- updateEndpoint: {
- required: true,
- type: String,
- },
- canUpdate: {
- required: true,
- type: Boolean,
- },
- canDestroy: {
- required: true,
- type: Boolean,
- },
- showInlineEditButton: {
- type: Boolean,
- required: false,
- default: true,
- },
- showDeleteButton: {
- type: Boolean,
- required: false,
- default: true,
- },
- enableAutocomplete: {
- type: Boolean,
- required: false,
- default: true,
- },
- issuableRef: {
- type: String,
- required: true,
- },
- initialTitleHtml: {
- type: String,
- required: true,
- },
- initialTitleText: {
- type: String,
- required: true,
- },
- initialDescriptionHtml: {
- type: String,
- required: false,
- default: '',
- },
- initialDescriptionText: {
- type: String,
- required: false,
- default: '',
- },
- initialTaskStatus: {
- type: String,
- required: false,
- default: '',
- },
- updatedAt: {
- type: String,
- required: false,
- default: '',
- },
- updatedByName: {
- type: String,
- required: false,
- default: '',
- },
- updatedByPath: {
- type: String,
- required: false,
- default: '',
- },
- issuableTemplates: {
- type: Array,
- required: false,
- default: () => [],
- },
- markdownPreviewPath: {
- type: String,
- required: true,
- },
- markdownDocsPath: {
- type: String,
- required: true,
- },
- markdownVersion: {
- type: Number,
- required: false,
- default: 0,
- },
- projectPath: {
- type: String,
- required: true,
- },
- projectNamespace: {
- type: String,
- required: true,
- },
- issuableType: {
- type: String,
- required: false,
- default: 'issue',
- },
- canAttachFile: {
- type: Boolean,
- required: false,
- default: true,
- },
+export default {
+ components: {
+ descriptionComponent,
+ titleComponent,
+ editedComponent,
+ formComponent,
+ },
+ mixins: [recaptchaModalImplementor],
+ props: {
+ endpoint: {
+ required: true,
+ type: String,
},
- data() {
- const store = new Store({
- titleHtml: this.initialTitleHtml,
- titleText: this.initialTitleText,
- descriptionHtml: this.initialDescriptionHtml,
- descriptionText: this.initialDescriptionText,
- updatedAt: this.updatedAt,
- updatedByName: this.updatedByName,
- updatedByPath: this.updatedByPath,
- taskStatus: this.initialTaskStatus,
- });
+ updateEndpoint: {
+ required: true,
+ type: String,
+ },
+ canUpdate: {
+ required: true,
+ type: Boolean,
+ },
+ canDestroy: {
+ required: true,
+ type: Boolean,
+ },
+ showInlineEditButton: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ showDeleteButton: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ enableAutocomplete: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ issuableRef: {
+ type: String,
+ required: true,
+ },
+ initialTitleHtml: {
+ type: String,
+ required: true,
+ },
+ initialTitleText: {
+ type: String,
+ required: true,
+ },
+ initialDescriptionHtml: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ initialDescriptionText: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ initialTaskStatus: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ updatedAt: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ updatedByName: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ updatedByPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ issuableTemplates: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ markdownPreviewPath: {
+ type: String,
+ required: true,
+ },
+ markdownDocsPath: {
+ type: String,
+ required: true,
+ },
+ markdownVersion: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ projectNamespace: {
+ type: String,
+ required: true,
+ },
+ issuableType: {
+ type: String,
+ required: false,
+ default: 'issue',
+ },
+ canAttachFile: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+ data() {
+ const store = new Store({
+ titleHtml: this.initialTitleHtml,
+ titleText: this.initialTitleText,
+ descriptionHtml: this.initialDescriptionHtml,
+ descriptionText: this.initialDescriptionText,
+ updatedAt: this.updatedAt,
+ updatedByName: this.updatedByName,
+ updatedByPath: this.updatedByPath,
+ taskStatus: this.initialTaskStatus,
+ });
- return {
- store,
- state: store.state,
- showForm: false,
- };
- },
- computed: {
- formState() {
- return this.store.formState;
- },
- hasUpdated() {
- return !!this.state.updatedAt;
- },
- issueChanged() {
- const descriptionChanged =
- this.initialDescriptionText !== this.store.formState.description;
- const titleChanged =
- this.initialTitleText !== this.store.formState.title;
- return descriptionChanged || titleChanged;
- },
+ return {
+ store,
+ state: store.state,
+ showForm: false,
+ };
+ },
+ computed: {
+ formState() {
+ return this.store.formState;
},
- created() {
- this.service = new Service(this.endpoint);
- this.poll = new Poll({
- resource: this.service,
- method: 'getData',
- successCallback: res => this.store.updateState(res.data),
- errorCallback(err) {
- throw new Error(err);
- },
- });
+ hasUpdated() {
+ return !!this.state.updatedAt;
+ },
+ issueChanged() {
+ const descriptionChanged = this.initialDescriptionText !== this.store.formState.description;
+ const titleChanged = this.initialTitleText !== this.store.formState.title;
+ return descriptionChanged || titleChanged;
+ },
+ },
+ created() {
+ this.service = new Service(this.endpoint);
+ this.poll = new Poll({
+ resource: this.service,
+ method: 'getData',
+ successCallback: res => this.store.updateState(res.data),
+ errorCallback(err) {
+ throw new Error(err);
+ },
+ });
+ if (!Visibility.hidden()) {
+ this.poll.makeRequest();
+ }
+
+ Visibility.change(() => {
if (!Visibility.hidden()) {
- this.poll.makeRequest();
+ this.poll.restart();
+ } else {
+ this.poll.stop();
}
+ });
- Visibility.change(() => {
- if (!Visibility.hidden()) {
- this.poll.restart();
- } else {
- this.poll.stop();
- }
- });
-
- window.addEventListener('beforeunload', this.handleBeforeUnloadEvent);
+ window.addEventListener('beforeunload', this.handleBeforeUnloadEvent);
- eventHub.$on('delete.issuable', this.deleteIssuable);
- eventHub.$on('update.issuable', this.updateIssuable);
- eventHub.$on('close.form', this.closeForm);
- eventHub.$on('open.form', this.openForm);
- },
- beforeDestroy() {
- eventHub.$off('delete.issuable', this.deleteIssuable);
- eventHub.$off('update.issuable', this.updateIssuable);
- eventHub.$off('close.form', this.closeForm);
- eventHub.$off('open.form', this.openForm);
- window.removeEventListener('beforeunload', this.handleBeforeUnloadEvent);
- },
- methods: {
- handleBeforeUnloadEvent(e) {
- const event = e;
- if (this.showForm && this.issueChanged) {
- event.returnValue = 'Are you sure you want to lose your issue information?';
- }
- return undefined;
- },
+ eventHub.$on('delete.issuable', this.deleteIssuable);
+ eventHub.$on('update.issuable', this.updateIssuable);
+ eventHub.$on('close.form', this.closeForm);
+ eventHub.$on('open.form', this.openForm);
+ },
+ beforeDestroy() {
+ eventHub.$off('delete.issuable', this.deleteIssuable);
+ eventHub.$off('update.issuable', this.updateIssuable);
+ eventHub.$off('close.form', this.closeForm);
+ eventHub.$off('open.form', this.openForm);
+ window.removeEventListener('beforeunload', this.handleBeforeUnloadEvent);
+ },
+ methods: {
+ handleBeforeUnloadEvent(e) {
+ const event = e;
+ if (this.showForm && this.issueChanged) {
+ event.returnValue = 'Are you sure you want to lose your issue information?';
+ }
+ return undefined;
+ },
- openForm() {
- if (!this.showForm) {
- this.showForm = true;
- this.store.setFormState({
- title: this.state.titleText,
- description: this.state.descriptionText,
- lockedWarningVisible: false,
- updateLoading: false,
- });
- }
- },
- closeForm() {
- this.showForm = false;
- },
+ openForm() {
+ if (!this.showForm) {
+ this.showForm = true;
+ this.store.setFormState({
+ title: this.state.titleText,
+ description: this.state.descriptionText,
+ lockedWarningVisible: false,
+ updateLoading: false,
+ });
+ }
+ },
+ closeForm() {
+ this.showForm = false;
+ },
- updateIssuable() {
- return this.service.updateIssuable(this.store.formState)
- .then(res => res.data)
- .then(data => this.checkForSpam(data))
- .then((data) => {
- if (window.location.pathname !== data.web_url) {
- visitUrl(data.web_url);
- }
+ updateIssuable() {
+ return this.service
+ .updateIssuable(this.store.formState)
+ .then(res => res.data)
+ .then(data => this.checkForSpam(data))
+ .then(data => {
+ if (window.location.pathname !== data.web_url) {
+ visitUrl(data.web_url);
+ }
- return this.service.getData();
- })
- .then(res => res.data)
- .then((data) => {
- this.store.updateState(data);
+ return this.service.getData();
+ })
+ .then(res => res.data)
+ .then(data => {
+ this.store.updateState(data);
+ eventHub.$emit('close.form');
+ })
+ .catch(error => {
+ if (error && error.name === 'SpamError') {
+ this.openRecaptcha();
+ } else {
eventHub.$emit('close.form');
- })
- .catch((error) => {
- if (error && error.name === 'SpamError') {
- this.openRecaptcha();
- } else {
- eventHub.$emit('close.form');
- window.Flash(`Error updating ${this.issuableType}`);
- }
- });
- },
-
- closeRecaptchaModal() {
- this.store.setFormState({
- updateLoading: false,
+ window.Flash(`Error updating ${this.issuableType}`);
+ }
});
+ },
- this.closeRecaptcha();
- },
+ closeRecaptchaModal() {
+ this.store.setFormState({
+ updateLoading: false,
+ });
- deleteIssuable() {
- this.service.deleteIssuable()
- .then(res => res.data)
- .then((data) => {
- // Stop the poll so we don't get 404's with the issuable not existing
- this.poll.stop();
+ this.closeRecaptcha();
+ },
- visitUrl(data.web_url);
- })
- .catch(() => {
- eventHub.$emit('close.form');
- window.Flash(`Error deleting ${this.issuableType}`);
- });
- },
+ deleteIssuable() {
+ this.service
+ .deleteIssuable()
+ .then(res => res.data)
+ .then(data => {
+ // Stop the poll so we don't get 404's with the issuable not existing
+ this.poll.stop();
+
+ visitUrl(data.web_url);
+ })
+ .catch(() => {
+ eventHub.$emit('close.form');
+ window.Flash(`Error deleting ${this.issuableType}`);
+ });
},
- };
+ },
+};
</script>
<template>
@@ -293,13 +291,10 @@
:show-delete-button="showDeleteButton"
:can-attach-file="canAttachFile"
:enable-autocomplete="enableAutocomplete"
+ :issuable-type="issuableType"
/>
- <recaptcha-modal
- v-show="showRecaptcha"
- :html="recaptchaHTML"
- @close="closeRecaptchaModal"
- />
+ <recaptcha-modal v-show="showRecaptcha" :html="recaptchaHTML" @close="closeRecaptchaModal" />
</div>
<div v-else>
<title-component
diff --git a/app/assets/javascripts/issue_show/components/description.vue b/app/assets/javascripts/issue_show/components/description.vue
index 1174177f561..5ca88d75063 100644
--- a/app/assets/javascripts/issue_show/components/description.vue
+++ b/app/assets/javascripts/issue_show/components/description.vue
@@ -1,117 +1,112 @@
<script>
- import $ from 'jquery';
- import animateMixin from '../mixins/animate';
- import TaskList from '../../task_list';
- import recaptchaModalImplementor from '../../vue_shared/mixins/recaptcha_modal_implementor';
+import $ from 'jquery';
+import animateMixin from '../mixins/animate';
+import TaskList from '../../task_list';
+import recaptchaModalImplementor from '../../vue_shared/mixins/recaptcha_modal_implementor';
- export default {
- mixins: [
- animateMixin,
- recaptchaModalImplementor,
- ],
+export default {
+ mixins: [animateMixin, recaptchaModalImplementor],
- props: {
- canUpdate: {
- type: Boolean,
- required: true,
- },
- descriptionHtml: {
- type: String,
- required: true,
- },
- descriptionText: {
- type: String,
- required: true,
- },
- taskStatus: {
- type: String,
- required: false,
- default: '',
- },
- issuableType: {
- type: String,
- required: false,
- default: 'issue',
- },
- updateUrl: {
- type: String,
- required: false,
- default: null,
- },
+ props: {
+ canUpdate: {
+ type: Boolean,
+ required: true,
},
- data() {
- return {
- preAnimation: false,
- pulseAnimation: false,
- };
+ descriptionHtml: {
+ type: String,
+ required: true,
},
- watch: {
- descriptionHtml() {
- this.animateChange();
+ descriptionText: {
+ type: String,
+ required: true,
+ },
+ taskStatus: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ issuableType: {
+ type: String,
+ required: false,
+ default: 'issue',
+ },
+ updateUrl: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+ data() {
+ return {
+ preAnimation: false,
+ pulseAnimation: false,
+ };
+ },
+ watch: {
+ descriptionHtml() {
+ this.animateChange();
- this.$nextTick(() => {
- this.renderGFM();
- });
- },
- taskStatus() {
- this.updateTaskStatusText();
- },
+ this.$nextTick(() => {
+ this.renderGFM();
+ });
},
- mounted() {
- this.renderGFM();
+ taskStatus() {
this.updateTaskStatusText();
},
- methods: {
- renderGFM() {
- $(this.$refs['gfm-content']).renderGFM();
+ },
+ mounted() {
+ this.renderGFM();
+ this.updateTaskStatusText();
+ },
+ methods: {
+ renderGFM() {
+ $(this.$refs['gfm-content']).renderGFM();
- if (this.canUpdate) {
- // eslint-disable-next-line no-new
- new TaskList({
- dataType: this.issuableType,
- fieldName: 'description',
- selector: '.detail-page-description',
- onSuccess: this.taskListUpdateSuccess.bind(this),
- });
- }
- },
+ if (this.canUpdate) {
+ // eslint-disable-next-line no-new
+ new TaskList({
+ dataType: this.issuableType,
+ fieldName: 'description',
+ selector: '.detail-page-description',
+ onSuccess: this.taskListUpdateSuccess.bind(this),
+ });
+ }
+ },
- taskListUpdateSuccess(data) {
- try {
- this.checkForSpam(data);
- this.closeRecaptcha();
- } catch (error) {
- if (error && error.name === 'SpamError') this.openRecaptcha();
- }
- },
+ taskListUpdateSuccess(data) {
+ try {
+ this.checkForSpam(data);
+ this.closeRecaptcha();
+ } catch (error) {
+ if (error && error.name === 'SpamError') this.openRecaptcha();
+ }
+ },
- updateTaskStatusText() {
- const taskRegexMatches = this.taskStatus.match(/(\d+) of ((?!0)\d+)/);
- const $issuableHeader = $('.issuable-meta');
- const $tasks = $('#task_status', $issuableHeader);
- const $tasksShort = $('#task_status_short', $issuableHeader);
+ updateTaskStatusText() {
+ const taskRegexMatches = this.taskStatus.match(/(\d+) of ((?!0)\d+)/);
+ const $issuableHeader = $('.issuable-meta');
+ const $tasks = $('#task_status', $issuableHeader);
+ const $tasksShort = $('#task_status_short', $issuableHeader);
- if (taskRegexMatches) {
- $tasks.text(this.taskStatus);
- $tasksShort.text(
- `${taskRegexMatches[1]}/${taskRegexMatches[2]} task${taskRegexMatches[2] > 1 ?
- 's' :
- ''}`,
- );
- } else {
- $tasks.text('');
- $tasksShort.text('');
- }
- },
+ if (taskRegexMatches) {
+ $tasks.text(this.taskStatus);
+ $tasksShort.text(
+ `${taskRegexMatches[1]}/${taskRegexMatches[2]} task${taskRegexMatches[2] > 1 ? 's' : ''}`,
+ );
+ } else {
+ $tasks.text('');
+ $tasksShort.text('');
+ }
},
- };
+ },
+};
</script>
<template>
<div
v-if="descriptionHtml"
:class="{
- 'js-task-list-container': canUpdate
+ 'js-task-list-container': canUpdate,
}"
class="description"
>
@@ -119,11 +114,11 @@
ref="gfm-content"
:class="{
'issue-realtime-pre-pulse': preAnimation,
- 'issue-realtime-trigger-pulse': pulseAnimation
+ 'issue-realtime-trigger-pulse': pulseAnimation,
}"
class="wiki"
- v-html="descriptionHtml">
- </div>
+ v-html="descriptionHtml"
+ ></div>
<textarea
v-if="descriptionText"
v-model="descriptionText"
@@ -132,10 +127,6 @@
>
</textarea>
- <recaptcha-modal
- v-show="showRecaptcha"
- :html="recaptchaHTML"
- @close="closeRecaptcha"
- />
+ <recaptcha-modal v-show="showRecaptcha" :html="recaptchaHTML" @close="closeRecaptcha" />
</div>
</template>
diff --git a/app/assets/javascripts/issue_show/components/edit_actions.vue b/app/assets/javascripts/issue_show/components/edit_actions.vue
index 7fd3ea61aa7..42a3de62772 100644
--- a/app/assets/javascripts/issue_show/components/edit_actions.vue
+++ b/app/assets/javascripts/issue_show/components/edit_actions.vue
@@ -1,51 +1,64 @@
<script>
- import updateMixin from '../mixins/update';
- import eventHub from '../event_hub';
+import { __, sprintf } from '~/locale';
+import updateMixin from '../mixins/update';
+import eventHub from '../event_hub';
- export default {
- mixins: [updateMixin],
- props: {
- canDestroy: {
- type: Boolean,
- required: true,
- },
- formState: {
- type: Object,
- required: true,
- },
- showDeleteButton: {
- type: Boolean,
- required: false,
- default: true,
- },
+const issuableTypes = {
+ issue: __('Issue'),
+ epic: __('Epic'),
+};
+
+export default {
+ mixins: [updateMixin],
+ props: {
+ canDestroy: {
+ type: Boolean,
+ required: true,
+ },
+ formState: {
+ type: Object,
+ required: true,
+ },
+ showDeleteButton: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ issuableType: {
+ type: String,
+ required: true,
},
- data() {
- return {
- deleteLoading: false,
- };
+ },
+ data() {
+ return {
+ deleteLoading: false,
+ };
+ },
+ computed: {
+ isSubmitEnabled() {
+ return this.formState.title.trim() !== '';
},
- computed: {
- isSubmitEnabled() {
- return this.formState.title.trim() !== '';
- },
- shouldShowDeleteButton() {
- return this.canDestroy && this.showDeleteButton;
- },
+ shouldShowDeleteButton() {
+ return this.canDestroy && this.showDeleteButton;
},
- methods: {
- closeForm() {
- eventHub.$emit('close.form');
- },
- deleteIssuable() {
- // eslint-disable-next-line no-alert
- if (window.confirm('Issue will be removed! Are you sure?')) {
- this.deleteLoading = true;
+ },
+ methods: {
+ closeForm() {
+ eventHub.$emit('close.form');
+ },
+ deleteIssuable() {
+ const confirmMessage = sprintf(__('%{issuableType} will be removed! Are you sure?'), {
+ issuableType: issuableTypes[this.issuableType],
+ });
+ // eslint-disable-next-line no-alert
+ if (window.confirm(confirmMessage)) {
+ this.deleteLoading = true;
- eventHub.$emit('delete.issuable');
- }
- },
+ eventHub.$emit('delete.issuable');
+ }
},
- };
+ },
+};
</script>
<template>
@@ -53,35 +66,23 @@
<button
:class="{ disabled: formState.updateLoading || !isSubmitEnabled }"
:disabled="formState.updateLoading || !isSubmitEnabled"
- class="btn btn-success float-left"
+ class="btn btn-success float-left qa-save-button"
type="submit"
- @click.prevent="updateIssuable">
+ @click.prevent="updateIssuable"
+ >
Save changes
- <i
- v-if="formState.updateLoading"
- class="fa fa-spinner fa-spin"
- aria-hidden="true">
- </i>
- </button>
- <button
- class="btn btn-default float-right"
- type="button"
- @click="closeForm">
- Cancel
+ <i v-if="formState.updateLoading" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
</button>
+ <button class="btn btn-default float-right" type="button" @click="closeForm">Cancel</button>
<button
v-if="shouldShowDeleteButton"
:class="{ disabled: deleteLoading }"
:disabled="deleteLoading"
- class="btn btn-danger float-right append-right-default"
+ class="btn btn-danger float-right append-right-default qa-delete-button"
type="button"
- @click="deleteIssuable">
- Delete
- <i
- v-if="deleteLoading"
- class="fa fa-spinner fa-spin"
- aria-hidden="true">
- </i>
+ @click="deleteIssuable"
+ >
+ Delete <i v-if="deleteLoading" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
</button>
</div>
</template>
diff --git a/app/assets/javascripts/issue_show/components/edited.vue b/app/assets/javascripts/issue_show/components/edited.vue
index 05cd976f196..14ad8d3b7c9 100644
--- a/app/assets/javascripts/issue_show/components/edited.vue
+++ b/app/assets/javascripts/issue_show/components/edited.vue
@@ -1,56 +1,44 @@
<script>
- import timeAgoTooltip from '../../vue_shared/components/time_ago_tooltip.vue';
+import timeAgoTooltip from '../../vue_shared/components/time_ago_tooltip.vue';
- export default {
- components: {
- timeAgoTooltip,
+export default {
+ components: {
+ timeAgoTooltip,
+ },
+ props: {
+ updatedAt: {
+ type: String,
+ required: false,
+ default: '',
},
- props: {
- updatedAt: {
- type: String,
- required: false,
- default: '',
- },
- updatedByName: {
- type: String,
- required: false,
- default: '',
- },
- updatedByPath: {
- type: String,
- required: false,
- default: '',
- },
+ updatedByName: {
+ type: String,
+ required: false,
+ default: '',
},
- computed: {
- hasUpdatedBy() {
- return this.updatedByName && this.updatedByPath;
- },
+ updatedByPath: {
+ type: String,
+ required: false,
+ default: '',
},
- };
+ },
+ computed: {
+ hasUpdatedBy() {
+ return this.updatedByName && this.updatedByPath;
+ },
+ },
+};
</script>
<template>
- <small
- class="edited-text"
- >
+ <small class="edited-text">
Edited
- <time-ago-tooltip
- v-if="updatedAt"
- :time="updatedAt"
- tooltip-placement="bottom"
- />
- <span
- v-if="hasUpdatedBy"
- >
+ <time-ago-tooltip v-if="updatedAt" :time="updatedAt" tooltip-placement="bottom" />
+ <span v-if="hasUpdatedBy">
by
- <a
- :href="updatedByPath"
- class="author-link"
- >
+ <a :href="updatedByPath" class="author-link">
<span>{{ updatedByName }}</span>
</a>
</span>
</small>
</template>
-
diff --git a/app/assets/javascripts/issue_show/components/fields/description.vue b/app/assets/javascripts/issue_show/components/fields/description.vue
index 97acc5ba385..90258c0e044 100644
--- a/app/assets/javascripts/issue_show/components/fields/description.vue
+++ b/app/assets/javascripts/issue_show/components/fields/description.vue
@@ -1,54 +1,50 @@
<script>
- import updateMixin from '../../mixins/update';
- import markdownField from '../../../vue_shared/components/markdown/field.vue';
+import updateMixin from '../../mixins/update';
+import markdownField from '../../../vue_shared/components/markdown/field.vue';
- export default {
- components: {
- markdownField,
+export default {
+ components: {
+ markdownField,
+ },
+ mixins: [updateMixin],
+ props: {
+ formState: {
+ type: Object,
+ required: true,
},
- mixins: [updateMixin],
- props: {
- formState: {
- type: Object,
- required: true,
- },
- markdownPreviewPath: {
- type: String,
- required: true,
- },
- markdownDocsPath: {
- type: String,
- required: true,
- },
- markdownVersion: {
- type: Number,
- required: false,
- default: 0,
- },
- canAttachFile: {
- type: Boolean,
- required: false,
- default: true,
- },
- enableAutocomplete: {
- type: Boolean,
- required: false,
- default: true,
- },
+ markdownPreviewPath: {
+ type: String,
+ required: true,
},
- mounted() {
- this.$refs.textarea.focus();
+ markdownDocsPath: {
+ type: String,
+ required: true,
},
- };
+ markdownVersion: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
+ canAttachFile: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ enableAutocomplete: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+ mounted() {
+ this.$refs.textarea.focus();
+ },
+};
</script>
<template>
<div class="common-note-form">
- <label
- class="sr-only"
- for="issue-description">
- Description
- </label>
+ <label class="sr-only" for="issue-description"> Description </label>
<markdown-field
:markdown-preview-path="markdownPreviewPath"
:markdown-docs-path="markdownDocsPath"
@@ -61,12 +57,14 @@
ref="textarea"
slot="textarea"
v-model="formState.description"
- class="note-textarea js-gfm-input js-autosize markdown-area"
+ class="note-textarea js-gfm-input js-autosize markdown-area
+ qa-description-textarea"
data-supports-quick-actions="false"
aria-label="Description"
placeholder="Write a comment or drag your files here…"
@keydown.meta.enter="updateIssuable"
- @keydown.ctrl.enter="updateIssuable">
+ @keydown.ctrl.enter="updateIssuable"
+ >
</textarea>
</markdown-field>
</div>
diff --git a/app/assets/javascripts/issue_show/components/fields/description_template.vue b/app/assets/javascripts/issue_show/components/fields/description_template.vue
index e90d9fad94e..14f0acf6540 100644
--- a/app/assets/javascripts/issue_show/components/fields/description_template.vue
+++ b/app/assets/javascripts/issue_show/components/fields/description_template.vue
@@ -1,52 +1,50 @@
<script>
- import $ from 'jquery';
- import IssuableTemplateSelectors from '../../../templates/issuable_template_selectors';
+import $ from 'jquery';
+import IssuableTemplateSelectors from '../../../templates/issuable_template_selectors';
- export default {
- props: {
- formState: {
- type: Object,
- required: true,
- },
- issuableTemplates: {
- type: Array,
- required: false,
- default: () => [],
- },
- projectPath: {
- type: String,
- required: true,
- },
- projectNamespace: {
- type: String,
- required: true,
- },
+export default {
+ props: {
+ formState: {
+ type: Object,
+ required: true,
},
- computed: {
- issuableTemplatesJson() {
- return JSON.stringify(this.issuableTemplates);
- },
+ issuableTemplates: {
+ type: Array,
+ required: false,
+ default: () => [],
},
- mounted() {
- // Create the editor for the template
- const editor = document.querySelector('.detail-page-description .note-textarea') || {};
- editor.setValue = (val) => {
- this.formState.description = val;
- };
- editor.getValue = () => this.formState.description;
-
- this.issuableTemplate = new IssuableTemplateSelectors({
- $dropdowns: $(this.$refs.toggle),
- editor,
- });
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ projectNamespace: {
+ type: String,
+ required: true,
},
- };
+ },
+ computed: {
+ issuableTemplatesJson() {
+ return JSON.stringify(this.issuableTemplates);
+ },
+ },
+ mounted() {
+ // Create the editor for the template
+ const editor = document.querySelector('.detail-page-description .note-textarea') || {};
+ editor.setValue = val => {
+ this.formState.description = val;
+ };
+ editor.getValue = () => this.formState.description;
+
+ this.issuableTemplate = new IssuableTemplateSelectors({
+ $dropdowns: $(this.$refs.toggle),
+ editor,
+ });
+ },
+};
</script>
<template>
- <div
- class="dropdown js-issuable-selector-wrap"
- data-issuable-type="issue">
+ <div class="dropdown js-issuable-selector-wrap" data-issuable-type="issue">
<button
ref="toggle"
:data-namespace-path="projectNamespace"
@@ -56,57 +54,33 @@
type="button"
data-field-name="issuable_template"
data-selected="null"
- data-toggle="dropdown">
- <span class="dropdown-toggle-text">
- Choose a template
- </span>
- <i
- aria-hidden="true"
- class="fa fa-chevron-down">
- </i>
+ data-toggle="dropdown"
+ >
+ <span class="dropdown-toggle-text"> Choose a template </span>
+ <i aria-hidden="true" class="fa fa-chevron-down"> </i>
</button>
<div class="dropdown-menu dropdown-select">
<div class="dropdown-title">
Choose a template
- <button
- class="dropdown-title-button dropdown-menu-close"
- aria-label="Close"
- type="button">
- <i
- aria-hidden="true"
- class="fa fa-times dropdown-menu-close-icon">
- </i>
+ <button class="dropdown-title-button dropdown-menu-close" aria-label="Close" type="button">
+ <i aria-hidden="true" class="fa fa-times dropdown-menu-close-icon"> </i>
</button>
</div>
<div class="dropdown-input">
- <input
- type="search"
- class="dropdown-input-field"
- placeholder="Filter"
- autocomplete="off" />
- <i
- aria-hidden="true"
- class="fa fa-search dropdown-input-search">
- </i>
+ <input type="search" class="dropdown-input-field" placeholder="Filter" autocomplete="off" />
+ <i aria-hidden="true" class="fa fa-search dropdown-input-search"> </i>
<i
role="button"
aria-label="Clear templates search input"
- class="fa fa-times dropdown-input-clear js-dropdown-input-clear">
+ class="fa fa-times dropdown-input-clear js-dropdown-input-clear"
+ >
</i>
</div>
<div class="dropdown-content"></div>
<div class="dropdown-footer">
<ul class="dropdown-footer-list">
- <li>
- <a class="no-template">
- No template
- </a>
- </li>
- <li>
- <a class="reset-template">
- Reset template
- </a>
- </li>
+ <li><a class="no-template"> No template </a></li>
+ <li><a class="reset-template"> Reset template </a></li>
</ul>
</div>
</div>
diff --git a/app/assets/javascripts/issue_show/components/fields/title.vue b/app/assets/javascripts/issue_show/components/fields/title.vue
index 7d1526a64b4..c3d7ba4907f 100644
--- a/app/assets/javascripts/issue_show/components/fields/title.vue
+++ b/app/assets/javascripts/issue_show/components/fields/title.vue
@@ -1,32 +1,29 @@
<script>
- import updateMixin from '../../mixins/update';
+import updateMixin from '../../mixins/update';
- export default {
- mixins: [updateMixin],
- props: {
- formState: {
- type: Object,
- required: true,
- },
+export default {
+ mixins: [updateMixin],
+ props: {
+ formState: {
+ type: Object,
+ required: true,
},
- };
+ },
+};
</script>
<template>
<fieldset>
- <label
- class="sr-only"
- for="issuable-title">
- Title
- </label>
+ <label class="sr-only" for="issuable-title"> Title </label>
<input
id="issuable-title"
v-model="formState.title"
- class="form-control"
+ class="form-control qa-title-input"
type="text"
placeholder="Title"
aria-label="Title"
@keydown.meta.enter="updateIssuable"
- @keydown.ctrl.enter="updateIssuable" />
+ @keydown.ctrl.enter="updateIssuable"
+ />
</fieldset>
</template>
diff --git a/app/assets/javascripts/issue_show/components/form.vue b/app/assets/javascripts/issue_show/components/form.vue
index e509bb52f7d..45b60bc3392 100644
--- a/app/assets/javascripts/issue_show/components/form.vue
+++ b/app/assets/javascripts/issue_show/components/form.vue
@@ -1,84 +1,86 @@
<script>
- import lockedWarning from './locked_warning.vue';
- import titleField from './fields/title.vue';
- import descriptionField from './fields/description.vue';
- import editActions from './edit_actions.vue';
- import descriptionTemplate from './fields/description_template.vue';
+import lockedWarning from './locked_warning.vue';
+import titleField from './fields/title.vue';
+import descriptionField from './fields/description.vue';
+import editActions from './edit_actions.vue';
+import descriptionTemplate from './fields/description_template.vue';
- export default {
- components: {
- lockedWarning,
- titleField,
- descriptionField,
- descriptionTemplate,
- editActions,
+export default {
+ components: {
+ lockedWarning,
+ titleField,
+ descriptionField,
+ descriptionTemplate,
+ editActions,
+ },
+ props: {
+ canDestroy: {
+ type: Boolean,
+ required: true,
},
- props: {
- canDestroy: {
- type: Boolean,
- required: true,
- },
- formState: {
- type: Object,
- required: true,
- },
- issuableTemplates: {
- type: Array,
- required: false,
- default: () => [],
- },
- markdownPreviewPath: {
- type: String,
- required: true,
- },
- markdownDocsPath: {
- type: String,
- required: true,
- },
- markdownVersion: {
- type: Number,
- required: false,
- default: 0,
- },
- projectPath: {
- type: String,
- required: true,
- },
- projectNamespace: {
- type: String,
- required: true,
- },
- showDeleteButton: {
- type: Boolean,
- required: false,
- default: true,
- },
- canAttachFile: {
- type: Boolean,
- required: false,
- default: true,
- },
- enableAutocomplete: {
- type: Boolean,
- required: false,
- default: true,
- },
+ formState: {
+ type: Object,
+ required: true,
},
- computed: {
- hasIssuableTemplates() {
- return this.issuableTemplates.length;
- },
+ issuableTemplates: {
+ type: Array,
+ required: false,
+ default: () => [],
},
- };
+ issuableType: {
+ type: String,
+ required: true,
+ },
+ markdownPreviewPath: {
+ type: String,
+ required: true,
+ },
+ markdownDocsPath: {
+ type: String,
+ required: true,
+ },
+ markdownVersion: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ projectNamespace: {
+ type: String,
+ required: true,
+ },
+ showDeleteButton: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ canAttachFile: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ enableAutocomplete: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+ computed: {
+ hasIssuableTemplates() {
+ return this.issuableTemplates.length;
+ },
+ },
+};
</script>
<template>
<form>
<locked-warning v-if="formState.lockedWarningVisible" />
<div class="row">
- <div
- v-if="hasIssuableTemplates"
- class="col-sm-4 col-lg-3">
+ <div v-if="hasIssuableTemplates" class="col-sm-4 col-lg-3">
<description-template
:form-state="formState"
:issuable-templates="issuableTemplates"
@@ -92,10 +94,7 @@
'col-12': !hasIssuableTemplates,
}"
>
- <title-field
- :form-state="formState"
- :issuable-templates="issuableTemplates"
- />
+ <title-field :form-state="formState" :issuable-templates="issuableTemplates" />
</div>
</div>
<description-field
@@ -110,6 +109,7 @@
:form-state="formState"
:can-destroy="canDestroy"
:show-delete-button="showDeleteButton"
+ :issuable-type="issuableType"
/>
</form>
</template>
diff --git a/app/assets/javascripts/issue_show/components/locked_warning.vue b/app/assets/javascripts/issue_show/components/locked_warning.vue
index ad0d40faf32..639221473b1 100644
--- a/app/assets/javascripts/issue_show/components/locked_warning.vue
+++ b/app/assets/javascripts/issue_show/components/locked_warning.vue
@@ -1,20 +1,17 @@
<script>
- export default {
- computed: {
- currentPath() {
- return window.location.pathname;
- },
+export default {
+ computed: {
+ currentPath() {
+ return window.location.pathname;
},
- };
+ },
+};
</script>
<template>
<div class="alert alert-danger">
Someone edited the issue at the same time you did. Please check out
- <a
- :href="currentPath"
- target="_blank"
- rel="nofollow">the issue</a>
- and make sure your changes will not unintentionally remove theirs.
+ <a :href="currentPath" target="_blank" rel="nofollow">the issue</a> and make sure your changes
+ will not unintentionally remove theirs.
</div>
</template>
diff --git a/app/assets/javascripts/issue_show/components/title.vue b/app/assets/javascripts/issue_show/components/title.vue
index b5e8e0ea44b..3b5c95ccded 100644
--- a/app/assets/javascripts/issue_show/components/title.vue
+++ b/app/assets/javascripts/issue_show/components/title.vue
@@ -69,23 +69,22 @@ export default {
<h2
:class="{
'issue-realtime-pre-pulse': preAnimation,
- 'issue-realtime-trigger-pulse': pulseAnimation
+ 'issue-realtime-trigger-pulse': pulseAnimation,
}"
class="title"
v-html="titleHtml"
- >
- </h2>
+ ></h2>
<button
- v-tooltip
v-if="showInlineEditButton && canUpdate"
+ v-tooltip
type="button"
- class="btn btn-default btn-edit btn-svg js-issuable-edit"
+ class="btn btn-default btn-edit btn-svg js-issuable-edit
+ qa-edit-button"
title="Edit title and description"
data-placement="bottom"
data-container="body"
@click="edit"
v-html="pencilIcon"
- >
- </button>
+ ></button>
</div>
</template>
diff --git a/app/assets/javascripts/issue_show/index.js b/app/assets/javascripts/issue_show/index.js
index 75dfdedcf1b..d08e8ba0c4b 100644
--- a/app/assets/javascripts/issue_show/index.js
+++ b/app/assets/javascripts/issue_show/index.js
@@ -1,10 +1,11 @@
import Vue from 'vue';
+import sanitize from 'sanitize-html';
import issuableApp from './components/app.vue';
import '../vue_shared/vue_resource_interceptor';
-document.addEventListener('DOMContentLoaded', () => {
+export default function initIssueableApp() {
const initialDataEl = document.getElementById('js-issuable-app-initial-data');
- const props = JSON.parse(initialDataEl.innerHTML.replace(/&quot;/g, '"'));
+ const props = JSON.parse(sanitize(initialDataEl.textContent).replace(/&quot;/g, '"'));
return new Vue({
el: document.getElementById('js-issuable-app'),
@@ -17,4 +18,4 @@ document.addEventListener('DOMContentLoaded', () => {
});
},
});
-});
+}
diff --git a/app/assets/javascripts/issue_show/stores/index.js b/app/assets/javascripts/issue_show/stores/index.js
index af8b0414266..32044d6da25 100644
--- a/app/assets/javascripts/issue_show/stores/index.js
+++ b/app/assets/javascripts/issue_show/stores/index.js
@@ -25,8 +25,10 @@ export default class Store {
}
stateShouldUpdate(data) {
- return this.state.titleText !== data.title_text ||
- this.state.descriptionText !== data.description_text;
+ return (
+ this.state.titleText !== data.title_text ||
+ this.state.descriptionText !== data.description_text
+ );
}
setFormState(state) {
diff --git a/app/assets/javascripts/job.js b/app/assets/javascripts/job.js
deleted file mode 100644
index d4f2a3ef7d3..00000000000
--- a/app/assets/javascripts/job.js
+++ /dev/null
@@ -1,213 +0,0 @@
-import $ from 'jquery';
-import _ from 'underscore';
-import { polyfillSticky } from './lib/utils/sticky';
-import axios from './lib/utils/axios_utils';
-import { visitUrl } from './lib/utils/url_utility';
-import bp from './breakpoints';
-import { numberToHumanSize } from './lib/utils/number_utils';
-import { setCiStatusFavicon } from './lib/utils/common_utils';
-import { isScrolledToBottom, scrollDown } from './lib/utils/scroll_utils';
-import LogOutputBehaviours from './lib/utils/logoutput_behaviours';
-
-export default class Job extends LogOutputBehaviours {
- constructor(options) {
- super();
- this.timeout = null;
- this.state = null;
- this.fetchingStatusFavicon = false;
- this.options = options || $('.js-build-options').data();
-
- this.pagePath = this.options.pagePath;
- this.buildStatus = this.options.buildStatus;
- this.state = this.options.logState;
- this.buildStage = this.options.buildStage;
- this.$document = $(document);
- this.$window = $(window);
- this.logBytes = 0;
- this.updateDropdown = this.updateDropdown.bind(this);
-
- this.$buildTrace = $('#build-trace');
- this.$buildRefreshAnimation = $('.js-build-refresh');
- this.$truncatedInfo = $('.js-truncated-info');
- this.$buildTraceOutput = $('.js-build-output');
- this.$topBar = $('.js-top-bar');
-
- clearTimeout(this.timeout);
-
- this.initSidebar();
- this.populateJobs(this.buildStage);
- this.updateStageDropdownText(this.buildStage);
- this.sidebarOnResize();
-
- this.$document
- .off('click', '.js-sidebar-build-toggle')
- .on('click', '.js-sidebar-build-toggle', this.sidebarOnClick.bind(this));
-
- this.$document
- .off('click', '.stage-item')
- .on('click', '.stage-item', this.updateDropdown);
-
- this.scrollThrottled = _.throttle(this.toggleScroll.bind(this), 100);
-
- this.$window
- .off('scroll')
- .on('scroll', () => {
- if (!isScrolledToBottom()) {
- this.toggleScrollAnimation(false);
- } else if (isScrolledToBottom() && !this.isLogComplete) {
- this.toggleScrollAnimation(true);
- }
- this.scrollThrottled();
- });
-
- this.$window
- .off('resize.build')
- .on('resize.build', _.throttle(this.sidebarOnResize.bind(this), 100));
-
- this.initAffixTopArea();
-
- this.getBuildTrace();
- }
-
- initAffixTopArea() {
- polyfillSticky(this.$topBar);
- }
-
- scrollToBottom() {
- scrollDown();
- this.hasBeenScrolled = true;
- this.toggleScroll();
- }
-
- scrollToTop() {
- $(document).scrollTop(0);
- this.hasBeenScrolled = true;
- this.toggleScroll();
- }
-
- toggleScrollAnimation(toggle) {
- this.$scrollBottomBtn.toggleClass('animate', toggle);
- }
-
- initSidebar() {
- this.$sidebar = $('.js-build-sidebar');
- }
-
- getBuildTrace() {
- return axios.get(`${this.pagePath}/trace.json`, {
- params: { state: this.state },
- })
- .then((res) => {
- const log = res.data;
-
- if (!this.fetchingStatusFavicon) {
- this.fetchingStatusFavicon = true;
-
- setCiStatusFavicon(`${this.pagePath}/status.json`)
- .then(() => {
- this.fetchingStatusFavicon = false;
- })
- .catch(() => {
- this.fetchingStatusFavicon = false;
- });
- }
-
- if (log.state) {
- this.state = log.state;
- }
-
- this.isScrollInBottom = isScrolledToBottom();
-
- if (log.append) {
- this.$buildTraceOutput.append(log.html);
- this.logBytes += log.size;
- } else {
- this.$buildTraceOutput.html(log.html);
- this.logBytes = log.size;
- }
-
- // if the incremental sum of logBytes we received is less than the total
- // we need to show a message warning the user about that.
- if (this.logBytes < log.total) {
- // size is in bytes, we need to calculate KiB
- const size = numberToHumanSize(this.logBytes);
- $('.js-truncated-info-size').html(`${size}`);
- this.$truncatedInfo.removeClass('hidden');
- } else {
- this.$truncatedInfo.addClass('hidden');
- }
- this.isLogComplete = log.complete;
-
- if (log.complete === false) {
- this.timeout = setTimeout(() => {
- this.getBuildTrace();
- }, 4000);
- } else {
- this.$buildRefreshAnimation.remove();
- this.toggleScrollAnimation(false);
- }
-
- if (log.status !== this.buildStatus) {
- visitUrl(this.pagePath);
- }
- })
- .catch(() => {
- this.$buildRefreshAnimation.remove();
- })
- .then(() => {
- if (this.isScrollInBottom) {
- scrollDown();
- }
- })
- .then(() => this.toggleScroll());
- }
- // eslint-disable-next-line class-methods-use-this
- shouldHideSidebarForViewport() {
- const bootstrapBreakpoint = bp.getBreakpointSize();
- return bootstrapBreakpoint === 'xs';
- }
-
- toggleSidebar(shouldHide) {
- const shouldShow = typeof shouldHide === 'boolean' ? !shouldHide : undefined;
- const $toggleButton = $('.js-sidebar-build-toggle-header');
-
- this.$sidebar
- .toggleClass('right-sidebar-expanded', shouldShow)
- .toggleClass('right-sidebar-collapsed', shouldHide);
-
- this.$topBar
- .toggleClass('sidebar-expanded', shouldShow)
- .toggleClass('sidebar-collapsed', shouldHide);
-
- if (this.$sidebar.hasClass('right-sidebar-expanded')) {
- $toggleButton.addClass('hidden');
- } else {
- $toggleButton.removeClass('hidden');
- }
- }
-
- sidebarOnResize() {
- this.toggleSidebar(this.shouldHideSidebarForViewport());
- }
-
- sidebarOnClick() {
- if (this.shouldHideSidebarForViewport()) this.toggleSidebar();
- }
-
- // eslint-disable-next-line class-methods-use-this
- populateJobs(stage) {
- $('.build-job').hide();
- $(`.build-job[data-stage="${stage}"]`).show();
- }
- // eslint-disable-next-line class-methods-use-this
- updateStageDropdownText(stage) {
- $('.stage-selection').text(stage);
- }
-
- updateDropdown(e) {
- e.preventDefault();
- const stage = e.currentTarget.text;
- this.updateStageDropdownText(stage);
- this.populateJobs(stage);
- }
-}
diff --git a/app/assets/javascripts/jobs/components/artifacts_block.vue b/app/assets/javascripts/jobs/components/artifacts_block.vue
index 525c5eec91a..309b7427b9e 100644
--- a/app/assets/javascripts/jobs/components/artifacts_block.vue
+++ b/app/assets/javascripts/jobs/components/artifacts_block.vue
@@ -1,98 +1,72 @@
<script>
- import TimeagoTooltiop from '~/vue_shared/components/time_ago_tooltip.vue';
+import { GlLink } from '@gitlab/ui';
+import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import timeagoMixin from '~/vue_shared/mixins/timeago';
- export default {
- components: {
- TimeagoTooltiop,
+export default {
+ components: {
+ TimeagoTooltip,
+ GlLink,
+ },
+ mixins: [timeagoMixin],
+ props: {
+ artifact: {
+ type: Object,
+ required: true,
},
- props: {
- // @build.artifacts_expired?
- haveArtifactsExpired: {
- type: Boolean,
- required: true,
- },
- // @build.has_expiring_artifacts?
- willArtifactsExpire: {
- type: Boolean,
- required: true,
- },
- expireAt: {
- type: String,
- required: false,
- default: null,
- },
- keepArtifactsPath: {
- type: String,
- required: false,
- default: null,
- },
- downloadArtifactsPath: {
- type: String,
- required: false,
- default: null,
- },
- browseArtifactsPath: {
- type: String,
- required: false,
- default: null,
- },
+ },
+ computed: {
+ isExpired() {
+ return this.artifact.expired;
},
- };
+ // Only when the key is `false` we can render this block
+ willExpire() {
+ return this.artifact.expired === false;
+ },
+ },
+};
</script>
<template>
<div class="block">
- <div class="title">
- {{ s__('Job|Job artifacts') }}
- </div>
+ <div class="title">{{ s__('Job|Job artifacts') }}</div>
- <p
- v-if="haveArtifactsExpired"
- class="js-artifacts-removed build-detail-row"
- >
+ <p v-if="isExpired" class="js-artifacts-removed build-detail-row">
{{ s__('Job|The artifacts were removed') }}
</p>
- <p
- v-else-if="willArtifactsExpire"
- class="js-artifacts-will-be-removed build-detail-row"
- >
- {{ s__('Job|The artifacts will be removed') }}
+
+ <p v-else-if="willExpire" class="js-artifacts-will-be-removed build-detail-row">
+ {{ s__('Job|The artifacts will be removed in') }}
</p>
- <timeago-tooltiop
- v-if="expireAt"
- :time="expireAt"
- />
+ <timeago-tooltip v-if="artifact.expire_at" :time="artifact.expire_at" />
- <div
- class="btn-group d-flex"
- role="group"
- >
- <a
- v-if="keepArtifactsPath"
- :href="keepArtifactsPath"
+ <div class="btn-group d-flex" role="group">
+ <gl-link
+ v-if="artifact.keep_path"
+ :href="artifact.keep_path"
class="js-keep-artifacts btn btn-sm btn-default"
data-method="post"
>
{{ s__('Job|Keep') }}
- </a>
+ </gl-link>
- <a
- v-if="downloadArtifactsPath"
- :href="downloadArtifactsPath"
+ <gl-link
+ v-if="artifact.download_path"
+ :href="artifact.download_path"
class="js-download-artifacts btn btn-sm btn-default"
download
rel="nofollow"
>
{{ s__('Job|Download') }}
- </a>
+ </gl-link>
- <a
- v-if="browseArtifactsPath"
- :href="browseArtifactsPath"
+ <gl-link
+ v-if="artifact.browse_path"
+ :href="artifact.browse_path"
class="js-browse-artifacts btn btn-sm btn-default"
>
{{ s__('Job|Browse') }}
- </a>
+ </gl-link>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/commit_block.vue b/app/assets/javascripts/jobs/components/commit_block.vue
index 7f485295513..3b9c61bd48c 100644
--- a/app/assets/javascripts/jobs/components/commit_block.vue
+++ b/app/assets/javascripts/jobs/components/commit_block.vue
@@ -1,64 +1,54 @@
<script>
+import { GlLink } from '@gitlab/ui';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
export default {
components: {
ClipboardButton,
+ GlLink,
},
props: {
- pipelineShortSha: {
- type: String,
+ commit: {
+ type: Object,
required: true,
},
- pipelineShaPath: {
- type: String,
- required: true,
- },
- mergeRequestReference: {
- type: String,
+ mergeRequest: {
+ type: Object,
required: false,
default: null,
},
- mergeRequestPath: {
- type: String,
- required: false,
- default: null,
- },
- gitCommitTitlte: {
- type: String,
+ isLastBlock: {
+ type: Boolean,
required: true,
},
},
};
</script>
<template>
- <div class="block">
+ <div
+ :class="{
+ 'block-last': isLastBlock,
+ block: !isLastBlock,
+ }"
+ >
<p>
{{ __('Commit') }}
- <a
- :href="pipelineShaPath"
- class="js-commit-sha commit-sha link-commit"
- >
- {{ pipelineShortSha }}
- </a>
+ <gl-link :href="commit.commit_path" class="js-commit-sha commit-sha link-commit">{{
+ commit.short_id
+ }}</gl-link>
<clipboard-button
- :text="pipelineShortSha"
+ :text="commit.short_id"
:title="__('Copy commit SHA to clipboard')"
+ css-class="btn btn-clipboard btn-transparent"
/>
- <a
- v-if="mergeRequestPath && mergeRequestReference"
- :href="mergeRequestPath"
- class="js-link-commit link-commit"
+ <gl-link v-if="mergeRequest" :href="mergeRequest.path" class="js-link-commit link-commit"
+ >!{{ mergeRequest.iid }}</gl-link
>
- {{ mergeRequestReference }}
- </a>
</p>
- <p class="build-light-text append-bottom-0">
- {{ gitCommitTitlte }}
- </p>
+ <p class="build-light-text append-bottom-0">{{ commit.title }}</p>
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/empty_state.vue b/app/assets/javascripts/jobs/components/empty_state.vue
index 4faf08387fb..668fcf3d673 100644
--- a/app/assets/javascripts/jobs/components/empty_state.vue
+++ b/app/assets/javascripts/jobs/components/empty_state.vue
@@ -1,74 +1,64 @@
<script>
- export default {
- props: {
- illustrationPath: {
- type: String,
- required: true,
- },
- illustrationSizeClass: {
- type: String,
- required: true,
- },
- title: {
- type: String,
- required: true,
- },
- content: {
- type: String,
- required: false,
- default: null,
- },
- action: {
- type: Object,
- required: false,
- default: null,
- validator(value) {
- return (
- value === null ||
- (Object.prototype.hasOwnProperty.call(value, 'link') &&
- Object.prototype.hasOwnProperty.call(value, 'method') &&
- Object.prototype.hasOwnProperty.call(value, 'title'))
- );
- },
+import { GlLink } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlLink,
+ },
+ props: {
+ illustrationPath: {
+ type: String,
+ required: true,
+ },
+ illustrationSizeClass: {
+ type: String,
+ required: true,
+ },
+ title: {
+ type: String,
+ required: true,
+ },
+ content: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ action: {
+ type: Object,
+ required: false,
+ default: null,
+ validator(value) {
+ return (
+ value === null ||
+ (Object.prototype.hasOwnProperty.call(value, 'path') &&
+ Object.prototype.hasOwnProperty.call(value, 'method') &&
+ Object.prototype.hasOwnProperty.call(value, 'button_title'))
+ );
},
},
- };
+ },
+};
</script>
<template>
<div class="row empty-state">
<div class="col-12">
- <div
- :class="illustrationSizeClass"
- class="svg-content"
- >
- <img :src="illustrationPath" />
- </div>
+ <div :class="illustrationSizeClass" class="svg-content"><img :src="illustrationPath" /></div>
</div>
<div class="col-12">
<div class="text-content">
- <h4 class="js-job-empty-state-title text-center">
- {{ title }}
- </h4>
+ <h4 class="js-job-empty-state-title text-center">{{ title }}</h4>
- <p
- v-if="content"
- class="js-job-empty-state-content"
- >
- {{ content }}
- </p>
+ <p v-if="content" class="js-job-empty-state-content">{{ content }}</p>
- <div
- v-if="action"
- class="text-center"
- >
- <a
- :href="action.link"
+ <div v-if="action" class="text-center">
+ <gl-link
+ :href="action.path"
:data-method="action.method"
class="js-job-empty-state-action btn btn-primary"
>
- {{ action.title }}
- </a>
+ {{ action.button_title }}
+ </gl-link>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/jobs/components/environments_block.vue b/app/assets/javascripts/jobs/components/environments_block.vue
index ca6386595c7..f7fbb9503a0 100644
--- a/app/assets/javascripts/jobs/components/environments_block.vue
+++ b/app/assets/javascripts/jobs/components/environments_block.vue
@@ -1,118 +1,137 @@
<script>
- import _ from 'underscore';
- import CiIcon from '~/vue_shared/components/ci_icon.vue';
- import { sprintf, __ } from '../../locale';
+import _ from 'underscore';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import { sprintf, __ } from '../../locale';
- export default {
- components: {
- CiIcon,
+export default {
+ components: {
+ CiIcon,
+ },
+ props: {
+ deploymentStatus: {
+ type: Object,
+ required: true,
},
- props: {
- deploymentStatus: {
- type: Object,
- required: true,
- },
+ iconStatus: {
+ type: Object,
+ required: true,
},
- computed: {
- environment() {
- let environmentText;
- switch (this.deploymentStatus.status) {
- case 'latest':
+ },
+ computed: {
+ environment() {
+ let environmentText;
+ switch (this.deploymentStatus.status) {
+ case 'last':
+ environmentText = sprintf(
+ __('This job is the most recent deployment to %{link}.'),
+ { link: this.environmentLink },
+ false,
+ );
+ break;
+ case 'out_of_date':
+ if (this.hasLastDeployment) {
environmentText = sprintf(
- __('This job is the most recent deployment to %{link}.'),
- { link: this.environmentLink },
+ __(
+ 'This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}.',
+ ),
+ {
+ environmentLink: this.environmentLink,
+ deploymentLink: this.deploymentLink(`#${this.lastDeployment.iid}`),
+ },
false,
);
- break;
- case 'out_of_date':
- if (this.hasLastDeployment) {
- environmentText = sprintf(
- __(
- 'This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}.',
- ),
- {
- environmentLink: this.environmentLink,
- deploymentLink: this.deploymentLink,
- },
- false,
- );
- } else {
- environmentText = sprintf(
- __('This job is an out-of-date deployment to %{environmentLink}.'),
- { environmentLink: this.environmentLink },
- false,
- );
- }
+ } else {
+ environmentText = sprintf(
+ __('This job is an out-of-date deployment to %{environmentLink}.'),
+ { environmentLink: this.environmentLink },
+ false,
+ );
+ }
- break;
- case 'failed':
+ break;
+ case 'failed':
+ environmentText = sprintf(
+ __('The deployment of this job to %{environmentLink} did not succeed.'),
+ { environmentLink: this.environmentLink },
+ false,
+ );
+ break;
+ case 'creating':
+ if (this.hasLastDeployment) {
+ environmentText = sprintf(
+ __(
+ 'This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}.',
+ ),
+ {
+ environmentLink: this.environmentLink,
+ deploymentLink: this.deploymentLink(__('latest deployment')),
+ },
+ false,
+ );
+ } else {
environmentText = sprintf(
- __('The deployment of this job to %{environmentLink} did not succeed.'),
+ __('This job is creating a deployment to %{environmentLink}.'),
{ environmentLink: this.environmentLink },
false,
);
- break;
- case 'creating':
- if (this.hasLastDeployment) {
- environmentText = sprintf(
- __(
- 'This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}.',
- ),
- {
- environmentLink: this.environmentLink,
- deploymentLink: this.deploymentLink,
- },
- false,
- );
- } else {
- environmentText = sprintf(
- __('This job is creating a deployment to %{environmentLink}.'),
- { environmentLink: this.environmentLink },
- false,
- );
- }
- break;
- default:
- break;
- }
- return environmentText;
- },
- environmentLink() {
+ }
+ break;
+ default:
+ break;
+ }
+ return environmentText;
+ },
+ environmentLink() {
+ if (this.hasEnvironment) {
return sprintf(
'%{startLink}%{name}%{endLink}',
{
- startLink: `<a href="${this.deploymentStatus.environment.path}">`,
+ startLink: `<a href="${
+ this.deploymentStatus.environment.environment_path
+ }" class="js-environment-link">`,
name: _.escape(this.deploymentStatus.environment.name),
endLink: '</a>',
},
false,
);
- },
- deploymentLink() {
- return sprintf(
- '%{startLink}%{name}%{endLink}',
- {
- startLink: `<a href="${this.lastDeployment.path}">`,
- name: _.escape(this.lastDeployment.name),
- endLink: '</a>',
- },
- false,
- );
- },
- hasLastDeployment() {
- return this.deploymentStatus.environment.last_deployment;
- },
- lastDeployment() {
- return this.deploymentStatus.environment.last_deployment;
- },
+ }
+ return '';
+ },
+ hasLastDeployment() {
+ return this.hasEnvironment && this.deploymentStatus.environment.last_deployment;
+ },
+ lastDeployment() {
+ return this.hasLastDeployment ? this.deploymentStatus.environment.last_deployment : {};
+ },
+ hasEnvironment() {
+ return !_.isEmpty(this.deploymentStatus.environment);
+ },
+ lastDeploymentPath() {
+ return !_.isEmpty(this.lastDeployment.deployable)
+ ? this.lastDeployment.deployable.build_path
+ : '';
+ },
+ },
+ methods: {
+ deploymentLink(name) {
+ return sprintf(
+ '%{startLink}%{name}%{endLink}',
+ {
+ startLink: `<a href="${this.lastDeploymentPath}" class="js-job-deployment-link">`,
+ name,
+ endLink: '</a>',
+ },
+ false,
+ );
},
- };
+ },
+};
</script>
<template>
- <div class="prepend-top-default js-environment-container">
+ <div class="prepend-top-default append-bottom-default js-environment-container">
<div class="environment-information">
- <ci-icon :status="deploymentStatus.icon" />
- <p v-html="environment"></p>
+ <ci-icon :status="iconStatus" />
+ <p class="inline append-bottom-0" v-html="environment"></p>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/erased_block.vue b/app/assets/javascripts/jobs/components/erased_block.vue
index d688eebfa95..8437ad89301 100644
--- a/app/assets/javascripts/jobs/components/erased_block.vue
+++ b/app/assets/javascripts/jobs/components/erased_block.vue
@@ -1,48 +1,43 @@
<script>
+import _ from 'underscore';
+import { GlLink } from '@gitlab/ui';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
components: {
TimeagoTooltip,
+ GlLink,
},
props: {
- erasedByUser: {
- type: Boolean,
- required: true,
- },
- username: {
- type: String,
- required: false,
- default: null,
- },
- linkToUser: {
- type: String,
+ user: {
+ type: Object,
required: false,
- default: null,
+ default: () => ({}),
},
erasedAt: {
type: String,
required: true,
},
},
+ computed: {
+ isErasedByUser() {
+ return !_.isEmpty(this.user);
+ },
+ },
};
</script>
<template>
<div class="prepend-top-default js-build-erased">
<div class="erased alert alert-warning">
- <template v-if="erasedByUser">
- {{ s__("Job|Job has been erased by") }}
- <a :href="linkToUser">
- {{ username }}
- </a>
+ <template v-if="isErasedByUser">
+ {{ s__('Job|Job has been erased by') }}
+ <gl-link :href="user.web_url"> {{ user.username }} </gl-link>
</template>
<template v-else>
- {{ s__("Job|Job has been erased") }}
+ {{ s__('Job|Job has been erased') }}
</template>
- <timeago-tooltip
- :time="erasedAt"
- />
+ <timeago-tooltip :time="erasedAt" />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/header.vue b/app/assets/javascripts/jobs/components/header.vue
deleted file mode 100644
index 63324e68d68..00000000000
--- a/app/assets/javascripts/jobs/components/header.vue
+++ /dev/null
@@ -1,95 +0,0 @@
-<script>
-import ciHeader from '../../vue_shared/components/header_ci_component.vue';
-import callout from '../../vue_shared/components/callout.vue';
-
-export default {
- name: 'JobHeaderSection',
- components: {
- ciHeader,
- callout,
- },
- props: {
- job: {
- type: Object,
- required: true,
- },
- isLoading: {
- type: Boolean,
- required: true,
- },
- },
- data() {
- return {
- actions: this.getActions(),
- };
- },
- computed: {
- status() {
- return this.job && this.job.status;
- },
- shouldRenderContent() {
- return !this.isLoading && Object.keys(this.job).length;
- },
- shouldRenderReason() {
- return !!(this.job.status && this.job.callout_message);
- },
- /**
- * When job has not started the key will be `false`
- * When job started the key will be a string with a date.
- */
- jobStarted() {
- return !this.job.started === false;
- },
- headerTime() {
- return this.jobStarted ? this.job.started : this.job.created_at;
- },
- },
- watch: {
- job() {
- this.actions = this.getActions();
- },
- },
- methods: {
- getActions() {
- const actions = [];
-
- if (this.job.new_issue_path) {
- actions.push({
- label: 'New issue',
- path: this.job.new_issue_path,
- cssClass: 'js-new-issue btn btn-success btn-inverted d-none d-md-block d-lg-block d-xl-block',
- type: 'link',
- });
- }
- return actions;
- },
- },
-};
-</script>
-<template>
- <header>
- <div class="js-build-header build-header top-area">
- <ci-header
- v-if="shouldRenderContent"
- :status="status"
- :item-id="job.id"
- :time="headerTime"
- :user="job.user"
- :actions="actions"
- :has-sidebar-button="true"
- :should-render-triggered-label="jobStarted"
- item-name="Job"
- />
- <gl-loading-icon
- v-if="isLoading"
- :size="2"
- class="prepend-top-default append-bottom-default"
- />
- </div>
-
- <callout
- v-if="shouldRenderReason"
- :message="job.callout_message"
- />
- </header>
-</template>
diff --git a/app/assets/javascripts/jobs/components/job_app.vue b/app/assets/javascripts/jobs/components/job_app.vue
new file mode 100644
index 00000000000..786ab16992d
--- /dev/null
+++ b/app/assets/javascripts/jobs/components/job_app.vue
@@ -0,0 +1,297 @@
+<script>
+import _ from 'underscore';
+import { mapGetters, mapState, mapActions } from 'vuex';
+import { GlLoadingIcon } from '@gitlab/ui';
+import { isScrolledToBottom } from '~/lib/utils/scroll_utils';
+import { polyfillSticky } from '~/lib/utils/sticky';
+import bp from '~/breakpoints';
+import CiHeader from '~/vue_shared/components/header_ci_component.vue';
+import Callout from '~/vue_shared/components/callout.vue';
+import Icon from '~/vue_shared/components/icon.vue';
+import createStore from '../store';
+import EmptyState from './empty_state.vue';
+import EnvironmentsBlock from './environments_block.vue';
+import ErasedBlock from './erased_block.vue';
+import Log from './job_log.vue';
+import LogTopBar from './job_log_controllers.vue';
+import StuckBlock from './stuck_block.vue';
+import Sidebar from './sidebar.vue';
+import { sprintf } from '~/locale';
+import delayedJobMixin from '../mixins/delayed_job_mixin';
+
+export default {
+ name: 'JobPageApp',
+ store: createStore(),
+ components: {
+ CiHeader,
+ Callout,
+ EmptyState,
+ EnvironmentsBlock,
+ ErasedBlock,
+ Icon,
+ Log,
+ LogTopBar,
+ StuckBlock,
+ Sidebar,
+ GlLoadingIcon,
+ },
+ mixins: [delayedJobMixin],
+ props: {
+ runnerSettingsUrl: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ runnerHelpUrl: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ endpoint: {
+ type: String,
+ required: true,
+ },
+ terminalPath: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ pagePath: {
+ type: String,
+ required: true,
+ },
+ logState: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ ...mapState([
+ 'isLoading',
+ 'job',
+ 'isSidebarOpen',
+ 'trace',
+ 'isTraceComplete',
+ 'traceSize',
+ 'isTraceSizeVisible',
+ 'isScrollBottomDisabled',
+ 'isScrollTopDisabled',
+ 'isScrolledToBottomBeforeReceivingTrace',
+ 'hasError',
+ ]),
+ ...mapGetters([
+ 'headerActions',
+ 'headerTime',
+ 'shouldRenderCalloutMessage',
+ 'shouldRenderTriggeredLabel',
+ 'hasEnvironment',
+ 'hasTrace',
+ 'emptyStateIllustration',
+ 'isScrollingDown',
+ 'emptyStateAction',
+ 'hasRunnersForProject',
+ ]),
+
+ shouldRenderContent() {
+ return !this.isLoading && !this.hasError;
+ },
+
+ emptyStateTitle() {
+ const { emptyStateIllustration, remainingTime } = this;
+ const { title } = emptyStateIllustration;
+
+ if (this.isDelayedJob) {
+ return sprintf(title, { remainingTime });
+ }
+
+ return title;
+ },
+ },
+ watch: {
+ // Once the job log is loaded,
+ // fetch the stages for the dropdown on the sidebar
+ job(newVal, oldVal) {
+ if (_.isEmpty(oldVal) && !_.isEmpty(newVal.pipeline)) {
+ this.fetchStages();
+ }
+
+ if (newVal.archived) {
+ this.$nextTick(() => {
+ if (this.$refs.sticky) {
+ polyfillSticky(this.$refs.sticky);
+ }
+ });
+ }
+ },
+ },
+ created() {
+ this.throttled = _.throttle(this.toggleScrollButtons, 100);
+
+ this.setJobEndpoint(this.endpoint);
+ this.setTraceOptions({
+ logState: this.logState,
+ pagePath: this.pagePath,
+ });
+
+ this.fetchJob();
+ this.fetchTrace();
+
+ window.addEventListener('resize', this.onResize);
+ window.addEventListener('scroll', this.updateScroll);
+ },
+ mounted() {
+ this.updateSidebar();
+ },
+ destroyed() {
+ window.removeEventListener('resize', this.onResize);
+ window.removeEventListener('scroll', this.updateScroll);
+ },
+ methods: {
+ ...mapActions([
+ 'setJobEndpoint',
+ 'setTraceOptions',
+ 'fetchJob',
+ 'fetchStages',
+ 'hideSidebar',
+ 'showSidebar',
+ 'toggleSidebar',
+ 'fetchTrace',
+ 'scrollBottom',
+ 'scrollTop',
+ 'toggleScrollButtons',
+ 'toggleScrollAnimation',
+ ]),
+ onResize() {
+ this.updateSidebar();
+ this.updateScroll();
+ },
+ updateSidebar() {
+ if (bp.getBreakpointSize() === 'xs') {
+ this.hideSidebar();
+ } else if (!this.isSidebarOpen) {
+ this.showSidebar();
+ }
+ },
+ updateScroll() {
+ if (!isScrolledToBottom()) {
+ this.toggleScrollAnimation(false);
+ } else if (this.isScrollingDown) {
+ this.toggleScrollAnimation(true);
+ }
+
+ this.throttled();
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-loading-icon
+ v-if="isLoading"
+ :size="2"
+ class="js-job-loading qa-loading-animation prepend-top-20"
+ />
+
+ <template v-else-if="shouldRenderContent">
+ <div class="js-job-content build-page">
+ <!-- Header Section -->
+ <header>
+ <div class="js-build-header build-header top-area">
+ <ci-header
+ :status="job.status"
+ :item-id="job.id"
+ :time="headerTime"
+ :user="job.user"
+ :actions="headerActions"
+ :has-sidebar-button="true"
+ :should-render-triggered-label="shouldRenderTriggeredLabel"
+ :item-name="__('Job')"
+ @clickedSidebarButton="toggleSidebar"
+ />
+ </div>
+
+ <callout v-if="shouldRenderCalloutMessage" :message="job.callout_message" />
+ </header>
+ <!-- EO Header Section -->
+
+ <!-- Body Section -->
+ <stuck-block
+ v-if="job.stuck"
+ class="js-job-stuck"
+ :has-no-runners-for-project="hasRunnersForProject"
+ :tags="job.tags"
+ :runners-path="runnerSettingsUrl"
+ />
+
+ <environments-block
+ v-if="hasEnvironment"
+ class="js-job-environment"
+ :deployment-status="job.deployment_status"
+ :icon-status="job.status"
+ />
+
+ <erased-block
+ v-if="job.erased_at"
+ class="js-job-erased-block"
+ :user="job.erased_by"
+ :erased-at="job.erased_at"
+ />
+
+ <div
+ v-if="job.archived"
+ ref="sticky"
+ class="js-archived-job prepend-top-default archived-sticky sticky-top"
+ >
+ <icon name="lock" class="align-text-bottom" />
+
+ {{ __('This job is archived. Only the complete pipeline can be retried.') }}
+ </div>
+ <!-- job log -->
+ <div v-if="hasTrace" class="build-trace-container">
+ <log-top-bar
+ :class="{
+ 'sidebar-expanded': isSidebarOpen,
+ 'sidebar-collapsed': !isSidebarOpen,
+ 'has-archived-block': job.archived,
+ }"
+ :erase-path="job.erase_path"
+ :size="traceSize"
+ :raw-path="job.raw_path"
+ :is-scroll-bottom-disabled="isScrollBottomDisabled"
+ :is-scroll-top-disabled="isScrollTopDisabled"
+ :is-trace-size-visible="isTraceSizeVisible"
+ :is-scrolling-down="isScrollingDown"
+ @scrollJobLogTop="scrollTop"
+ @scrollJobLogBottom="scrollBottom"
+ />
+ <log :trace="trace" :is-complete="isTraceComplete" />
+ </div>
+ <!-- EO job log -->
+
+ <!-- empty state -->
+ <empty-state
+ v-if="!hasTrace"
+ class="js-job-empty-state"
+ :illustration-path="emptyStateIllustration.image"
+ :illustration-size-class="emptyStateIllustration.size"
+ :title="emptyStateTitle"
+ :content="emptyStateIllustration.content"
+ :action="emptyStateAction"
+ />
+ <!-- EO empty state -->
+
+ <!-- EO Body Section -->
+ </div>
+ </template>
+
+ <sidebar
+ v-if="shouldRenderContent"
+ class="js-job-sidebar"
+ :class="{
+ 'right-sidebar-expanded': isSidebarOpen,
+ 'right-sidebar-collapsed': !isSidebarOpen,
+ }"
+ :runner-help-url="runnerHelpUrl"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/jobs/components/job_container_item.vue b/app/assets/javascripts/jobs/components/job_container_item.vue
new file mode 100644
index 00000000000..845699a90b5
--- /dev/null
+++ b/app/assets/javascripts/jobs/components/job_container_item.vue
@@ -0,0 +1,68 @@
+<script>
+import { GlLink } from '@gitlab/ui';
+import tooltip from '~/vue_shared/directives/tooltip';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import Icon from '~/vue_shared/components/icon.vue';
+import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
+import { sprintf } from '~/locale';
+
+export default {
+ components: {
+ CiIcon,
+ Icon,
+ GlLink,
+ },
+ directives: {
+ tooltip,
+ },
+ mixins: [delayedJobMixin],
+ props: {
+ job: {
+ type: Object,
+ required: true,
+ },
+ isActive: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ computed: {
+ tooltipText() {
+ const { name, status } = this.job;
+ const text = `${name} - ${status.tooltip}`;
+
+ if (this.isDelayedJob) {
+ return sprintf(text, { remainingTime: this.remainingTime });
+ }
+
+ return text;
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="build-job"
+ :class="{
+ retried: job.retried,
+ active: isActive,
+ }"
+ >
+ <gl-link
+ v-tooltip
+ :href="job.status.details_path"
+ :title="tooltipText"
+ data-boundary="viewport"
+ class="js-job-link"
+ >
+ <icon v-if="isActive" name="arrow-right" class="js-arrow-right icon-arrow-right" />
+
+ <ci-icon :status="job.status" />
+
+ <span>{{ job.name ? job.name : job.id }}</span>
+
+ <icon v-if="job.retried" name="retry" class="js-retry-icon" />
+ </gl-link>
+ </div>
+</template>
diff --git a/app/assets/javascripts/jobs/components/job_log.vue b/app/assets/javascripts/jobs/components/job_log.vue
index 3c4749d996b..92e20e92d66 100644
--- a/app/assets/javascripts/jobs/components/job_log.vue
+++ b/app/assets/javascripts/jobs/components/job_log.vue
@@ -1,20 +1,48 @@
<script>
- export default {
- name: 'JobLog',
- props: {
- trace: {
- type: String,
- required: true,
- },
- isReceivingBuildTrace: {
- type: Boolean,
- required: true,
- },
+import { mapState, mapActions } from 'vuex';
+
+export default {
+ name: 'JobLog',
+ props: {
+ trace: {
+ type: String,
+ required: true,
+ },
+ isComplete: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ computed: {
+ ...mapState(['isScrolledToBottomBeforeReceivingTrace']),
+ },
+ updated() {
+ this.$nextTick(() => this.handleScrollDown());
+ },
+ mounted() {
+ this.$nextTick(() => this.handleScrollDown());
+ },
+ methods: {
+ ...mapActions(['scrollBottom']),
+ /**
+ * The job log is sent in HTML, which means we need to use `v-html` to render it
+ * Using the updated hook with $nextTick is not enough to wait for the DOM to be updated
+ * in this case because it runs before `v-html` has finished running, since there's no
+ * Vue binding.
+ * In order to scroll the page down after `v-html` has finished, we need to use setTimeout
+ */
+ handleScrollDown() {
+ if (this.isScrolledToBottomBeforeReceivingTrace) {
+ setTimeout(() => {
+ this.scrollBottom();
+ }, 0);
+ }
},
- };
+ },
+};
</script>
<template>
- <pre class="build-trace">
+ <pre class="js-build-trace build-trace qa-build-trace">
<code
class="bash"
v-html="trace"
@@ -22,7 +50,7 @@
</code>
<div
- v-if="isReceivingBuildTrace"
+ v-if="!isComplete"
class="js-log-animation build-loader-animation"
>
<div class="dot"></div>
diff --git a/app/assets/javascripts/jobs/components/job_log_controllers.vue b/app/assets/javascripts/jobs/components/job_log_controllers.vue
index 513851e376f..52e14f954ee 100644
--- a/app/assets/javascripts/jobs/components/job_log_controllers.vue
+++ b/app/assets/javascripts/jobs/components/job_log_controllers.vue
@@ -1,137 +1,132 @@
<script>
- import Icon from '~/vue_shared/components/icon.vue';
- import tooltip from '~/vue_shared/directives/tooltip';
- import { numberToHumanSize } from '~/lib/utils/number_utils';
- import { s__, sprintf } from '~/locale';
+import { GlTooltipDirective, GlLink, GlButton } from '@gitlab/ui';
+import { polyfillSticky } from '~/lib/utils/sticky';
+import Icon from '~/vue_shared/components/icon.vue';
+import { numberToHumanSize } from '~/lib/utils/number_utils';
+import { sprintf } from '~/locale';
+import scrollDown from '../svg/scroll_down.svg';
- export default {
- components: {
- Icon,
+export default {
+ components: {
+ Icon,
+ GlLink,
+ GlButton,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ scrollDown,
+ props: {
+ erasePath: {
+ type: String,
+ required: false,
+ default: null,
},
- directives: {
- tooltip,
+ size: {
+ type: Number,
+ required: true,
},
- props: {
- canEraseJob: {
- type: Boolean,
- required: true,
- },
- size: {
- type: Number,
- required: true,
- },
- rawTracePath: {
- type: String,
- required: false,
- default: null,
- },
- canScrollToTop: {
- type: Boolean,
- required: true,
- },
- canScrollToBottom: {
- type: Boolean,
- required: true,
- },
+ rawPath: {
+ type: String,
+ required: false,
+ default: null,
},
- computed: {
- jobLogSize() {
- return sprintf('Showing last %{startSpanTag} %{size} %{endSpanTag} of log -', {
- startSpanTag: '<span class="s-truncated-info-size truncated-info-size">',
- endSpanTag: '</span>',
- size: numberToHumanSize(this.size),
- });
- },
+ isScrollTopDisabled: {
+ type: Boolean,
+ required: true,
},
- methods: {
- handleEraseJobClick() {
- // eslint-disable-next-line no-alert
- if (window.confirm(s__('Job|Are you sure you want to erase this job?'))) {
- this.$emit('eraseJob');
- }
- },
- handleScrollToTop() {
- this.$emit('scrollJobLogTop');
- },
- handleScrollToBottom() {
- this.$emit('scrollJobLogBottom');
- },
+ isScrollBottomDisabled: {
+ type: Boolean,
+ required: true,
},
- };
+ isScrollingDown: {
+ type: Boolean,
+ required: true,
+ },
+ isTraceSizeVisible: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ computed: {
+ jobLogSize() {
+ return sprintf('Showing last %{size} of log -', {
+ size: numberToHumanSize(this.size),
+ });
+ },
+ },
+ mounted() {
+ polyfillSticky(this.$el);
+ },
+ methods: {
+ handleScrollToTop() {
+ this.$emit('scrollJobLogTop');
+ },
+ handleScrollToBottom() {
+ this.$emit('scrollJobLogBottom');
+ },
+ },
+};
</script>
<template>
<div class="top-bar">
<!-- truncate information -->
<div class="js-truncated-info truncated-info d-none d-sm-block float-left">
- <p v-html="jobLogSize"></p>
+ <template v-if="isTraceSizeVisible">
+ {{ jobLogSize }}
- <a
- v-if="rawTracePath"
- :href="rawTracePath"
- class="js-raw-link raw-link"
- >
- {{ s__("Job|Complete Raw") }}
- </a>
+ <gl-link v-if="rawPath" :href="rawPath" class="js-raw-link raw-link">
+ {{ s__('Job|Complete Raw') }}
+ </gl-link>
+ </template>
</div>
<!-- eo truncate information -->
<div class="controllers float-right">
<!-- links -->
- <a
- v-tooltip
- v-if="rawTracePath"
+ <gl-link
+ v-if="rawPath"
+ v-gl-tooltip.body
:title="s__('Job|Show complete raw')"
- :href="rawTracePath"
+ :href="rawPath"
class="js-raw-link-controller controllers-buttons"
- data-container="body"
>
<icon name="doc-text" />
- </a>
+ </gl-link>
- <button
- v-tooltip
- v-if="canEraseJob"
+ <gl-link
+ v-if="erasePath"
+ v-gl-tooltip.body
:title="s__('Job|Erase job log')"
- type="button"
+ :href="erasePath"
+ :data-confirm="__('Are you sure you want to erase this build?')"
class="js-erase-link controllers-buttons"
- data-container="body"
- @click="handleEraseJobClick"
+ data-method="post"
>
<icon name="remove" />
- </button>
+ </gl-link>
<!-- eo links -->
<!-- scroll buttons -->
- <div
- v-tooltip
- :title="s__('Job|Scroll to top')"
- class="controllers-buttons"
- data-container="body"
- >
- <button
- :disabled="!canScrollToTop"
+ <div v-gl-tooltip :title="s__('Job|Scroll to top')" class="controllers-buttons">
+ <gl-button
+ :disabled="isScrollTopDisabled"
type="button"
class="js-scroll-top btn-scroll btn-transparent btn-blank"
@click="handleScrollToTop"
>
- <icon name="scroll_up"/>
- </button>
+ <icon name="scroll_up" />
+ </gl-button>
</div>
- <div
- v-tooltip
- :title="s__('Job|Scroll to bottom')"
- class="controllers-buttons"
- data-container="body"
- >
- <button
- :disabled="!canScrollToBottom"
- type="button"
+ <div v-gl-tooltip :title="s__('Job|Scroll to bottom')" class="controllers-buttons">
+ <gl-button
+ :disabled="isScrollBottomDisabled"
class="js-scroll-bottom btn-scroll btn-transparent btn-blank"
+ :class="{ animate: isScrollingDown }"
@click="handleScrollToBottom"
- >
- <icon name="scroll_down"/>
- </button>
+ v-html="$options.scrollDown"
+ />
</div>
<!-- eo scroll buttons -->
</div>
diff --git a/app/assets/javascripts/jobs/components/jobs_container.vue b/app/assets/javascripts/jobs/components/jobs_container.vue
index b81109bdd06..951bcb36600 100644
--- a/app/assets/javascripts/jobs/components/jobs_container.vue
+++ b/app/assets/javascripts/jobs/components/jobs_container.vue
@@ -1,60 +1,35 @@
<script>
- import CiIcon from '~/vue_shared/components/ci_icon.vue';
- import Icon from '~/vue_shared/components/icon.vue';
- import tooltip from '~/vue_shared/directives/tooltip';
+import JobContainerItem from './job_container_item.vue';
- export default {
- components: {
- CiIcon,
- Icon,
+export default {
+ components: {
+ JobContainerItem,
+ },
+
+ props: {
+ jobs: {
+ type: Array,
+ required: true,
},
- directives: {
- tooltip,
+ jobId: {
+ type: Number,
+ required: true,
},
- props: {
- jobs: {
- type: Array,
- required: true,
- },
+ },
+ methods: {
+ isJobActive(currentJobId) {
+ return this.jobId === currentJobId;
},
- };
+ },
+};
</script>
<template>
- <div class="builds-container">
- <div
- class="build-job"
- >
- <a
- v-tooltip
- v-for="job in jobs"
- :key="job.id"
- :href="job.path"
- :title="job.tooltip"
- :class="{ active: job.active, retried: job.retried }"
- >
- <icon
- v-if="job.active"
- name="arrow-right"
- class="js-arrow-right"
- />
-
- <ci-icon :status="job.status" />
-
- <span>
- <template v-if="job.name">
- {{ job.name }}
- </template>
- <template v-else>
- {{ job.id }}
- </template>
- </span>
-
- <icon
- v-if="job.retried"
- name="retry"
- class="js-retry-icon"
- />
- </a>
- </div>
+ <div class="js-jobs-container builds-container">
+ <job-container-item
+ v-for="job in jobs"
+ :key="job.id"
+ :job="job"
+ :is-active="isJobActive(job.id)"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/sidebar.vue b/app/assets/javascripts/jobs/components/sidebar.vue
new file mode 100644
index 00000000000..934ecd0e3ec
--- /dev/null
+++ b/app/assets/javascripts/jobs/components/sidebar.vue
@@ -0,0 +1,239 @@
+<script>
+import _ from 'underscore';
+import { mapActions, mapState } from 'vuex';
+import { GlLink, GlButton } from '@gitlab/ui';
+import timeagoMixin from '~/vue_shared/mixins/timeago';
+import { timeIntervalInWords } from '~/lib/utils/datetime_utility';
+import Icon from '~/vue_shared/components/icon.vue';
+import DetailRow from './sidebar_detail_row.vue';
+import ArtifactsBlock from './artifacts_block.vue';
+import TriggerBlock from './trigger_block.vue';
+import CommitBlock from './commit_block.vue';
+import StagesDropdown from './stages_dropdown.vue';
+import JobsContainer from './jobs_container.vue';
+
+export default {
+ name: 'JobSidebar',
+ components: {
+ ArtifactsBlock,
+ CommitBlock,
+ DetailRow,
+ Icon,
+ TriggerBlock,
+ StagesDropdown,
+ JobsContainer,
+ GlLink,
+ GlButton,
+ },
+ mixins: [timeagoMixin],
+ props: {
+ runnerHelpUrl: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ ...mapState(['job', 'stages', 'jobs', 'selectedStage', 'isLoadingStages']),
+ coverage() {
+ return `${this.job.coverage}%`;
+ },
+ duration() {
+ return timeIntervalInWords(this.job.duration);
+ },
+ queued() {
+ return timeIntervalInWords(this.job.queued);
+ },
+ runnerId() {
+ return `${this.job.runner.description} (#${this.job.runner.id})`;
+ },
+ retryButtonClass() {
+ let className =
+ 'js-retry-button float-right btn btn-retry d-none d-md-block d-lg-block d-xl-block';
+ className +=
+ this.job.status && this.job.recoverable ? ' btn-primary' : ' btn-inverted-secondary';
+ return className;
+ },
+ hasTimeout() {
+ return this.job.metadata != null && this.job.metadata.timeout_human_readable !== null;
+ },
+ timeout() {
+ if (this.job.metadata == null) {
+ return '';
+ }
+
+ let t = this.job.metadata.timeout_human_readable;
+ if (this.job.metadata.timeout_source !== '') {
+ t += ` (from ${this.job.metadata.timeout_source})`;
+ }
+
+ return t;
+ },
+ renderBlock() {
+ return (
+ this.job.merge_request ||
+ this.job.duration ||
+ this.job.finished_data ||
+ this.job.erased_at ||
+ this.job.queued ||
+ this.job.runner ||
+ this.job.coverage ||
+ this.job.tags.length ||
+ this.job.cancel_path
+ );
+ },
+ hasArtifact() {
+ return !_.isEmpty(this.job.artifact);
+ },
+ hasTriggers() {
+ return !_.isEmpty(this.job.trigger);
+ },
+ hasStages() {
+ return (
+ (this.job &&
+ this.job.pipeline &&
+ this.job.pipeline.stages &&
+ this.job.pipeline.stages.length > 0) ||
+ false
+ );
+ },
+ commit() {
+ return this.job.pipeline && this.job.pipeline.commit ? this.job.pipeline.commit : {};
+ },
+ },
+ methods: {
+ ...mapActions(['fetchJobsForStage', 'toggleSidebar']),
+ },
+};
+</script>
+<template>
+ <aside class="right-sidebar build-sidebar" data-offset-top="101" data-spy="affix">
+ <div class="sidebar-container">
+ <div class="blocks-container">
+ <div class="block">
+ <strong class="inline prepend-top-8"> {{ job.name }} </strong>
+ <gl-link
+ v-if="job.retry_path"
+ :class="retryButtonClass"
+ :href="job.retry_path"
+ data-method="post"
+ rel="nofollow"
+ >
+ {{ __('Retry') }}
+ </gl-link>
+ <gl-link
+ v-if="job.terminal_path"
+ :href="job.terminal_path"
+ class="js-terminal-link pull-right btn btn-primary
+ btn-inverted visible-md-block visible-lg-block"
+ target="_blank"
+ >
+ {{ __('Debug') }} <icon name="external-link" />
+ </gl-link>
+ <gl-button
+ :aria-label="__('Toggle Sidebar')"
+ type="button"
+ class="btn btn-blank gutter-toggle
+ float-right d-block d-md-none js-sidebar-build-toggle"
+ @click="toggleSidebar"
+ >
+ <i aria-hidden="true" data-hidden="true" class="fa fa-angle-double-right"></i>
+ </gl-button>
+ </div>
+ <div v-if="job.retry_path || job.new_issue_path" class="block retry-link">
+ <gl-link
+ v-if="job.new_issue_path"
+ :href="job.new_issue_path"
+ class="js-new-issue btn btn-success btn-inverted"
+ >
+ {{ __('New issue') }}
+ </gl-link>
+ <gl-link
+ v-if="job.retry_path"
+ :href="job.retry_path"
+ class="js-retry-job btn btn-inverted-secondary"
+ data-method="post"
+ rel="nofollow"
+ >
+ {{ __('Retry') }}
+ </gl-link>
+ </div>
+ <div :class="{ block: renderBlock }">
+ <p v-if="job.merge_request" class="build-detail-row js-job-mr">
+ <span class="build-light-text"> {{ __('Merge Request:') }} </span>
+ <gl-link :href="job.merge_request.path"> !{{ job.merge_request.iid }} </gl-link>
+ </p>
+
+ <detail-row
+ v-if="job.duration"
+ :value="duration"
+ class="js-job-duration"
+ title="Duration"
+ />
+ <detail-row
+ v-if="job.finished_at"
+ :value="timeFormated(job.finished_at)"
+ class="js-job-finished"
+ title="Finished"
+ />
+ <detail-row
+ v-if="job.erased_at"
+ :value="timeFormated(job.erased_at)"
+ class="js-job-erased"
+ title="Erased"
+ />
+ <detail-row v-if="job.queued" :value="queued" class="js-job-queued" title="Queued" />
+ <detail-row
+ v-if="hasTimeout"
+ :help-url="runnerHelpUrl"
+ :value="timeout"
+ class="js-job-timeout"
+ title="Timeout"
+ />
+ <detail-row v-if="job.runner" :value="runnerId" class="js-job-runner" title="Runner" />
+ <detail-row
+ v-if="job.coverage"
+ :value="coverage"
+ class="js-job-coverage"
+ title="Coverage"
+ />
+ <p v-if="job.tags.length" class="build-detail-row js-job-tags">
+ <span class="build-light-text"> {{ __('Tags:') }} </span>
+ <span v-for="(tag, i) in job.tags" :key="i" class="badge badge-primary">
+ {{ tag }}
+ </span>
+ </p>
+
+ <div v-if="job.cancel_path" class="btn-group prepend-top-5" role="group">
+ <gl-link
+ :href="job.cancel_path"
+ class="js-cancel-job btn btn-sm btn-default"
+ data-method="post"
+ rel="nofollow"
+ >
+ {{ __('Cancel') }}
+ </gl-link>
+ </div>
+ </div>
+
+ <artifacts-block v-if="hasArtifact" :artifact="job.artifact" />
+ <trigger-block v-if="hasTriggers" :trigger="job.trigger" />
+ <commit-block
+ :is-last-block="hasStages"
+ :commit="commit"
+ :merge-request="job.merge_request"
+ />
+
+ <stages-dropdown
+ v-if="!isLoadingStages"
+ :stages="stages"
+ :pipeline="job.pipeline"
+ :selected-stage="selectedStage"
+ @requestSidebarStageDropdown="fetchJobsForStage"
+ />
+ </div>
+
+ <jobs-container v-if="jobs.length" :jobs="jobs" :job-id="job.id" />
+ </div>
+ </aside>
+</template>
diff --git a/app/assets/javascripts/jobs/components/sidebar_detail_row.vue b/app/assets/javascripts/jobs/components/sidebar_detail_row.vue
index 83560a8ff0e..77be295e802 100644
--- a/app/assets/javascripts/jobs/components/sidebar_detail_row.vue
+++ b/app/assets/javascripts/jobs/components/sidebar_detail_row.vue
@@ -1,56 +1,45 @@
<script>
- export default {
- name: 'SidebarDetailRow',
- props: {
- title: {
- type: String,
- required: false,
- default: '',
- },
- value: {
- type: String,
- required: true,
- },
- helpUrl: {
- type: String,
- required: false,
- default: '',
- },
+import { GlLink } from '@gitlab/ui';
+
+export default {
+ name: 'SidebarDetailRow',
+ components: {
+ GlLink,
+ },
+ props: {
+ title: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ value: {
+ type: String,
+ required: true,
+ },
+ helpUrl: {
+ type: String,
+ required: false,
+ default: '',
},
- computed: {
- hasTitle() {
- return this.title.length > 0;
- },
- hasHelpURL() {
- return this.helpUrl.length > 0;
- },
+ },
+ computed: {
+ hasTitle() {
+ return this.title.length > 0;
},
- };
+ hasHelpURL() {
+ return this.helpUrl.length > 0;
+ },
+ },
+};
</script>
<template>
<p class="build-detail-row">
- <span
- v-if="hasTitle"
- class="build-light-text"
- >
- {{ title }}:
- </span>
- {{ value }}
+ <span v-if="hasTitle" class="build-light-text"> {{ title }}: </span> {{ value }}
- <span
- v-if="hasHelpURL"
- class="help-button float-right"
- >
- <a
- :href="helpUrl"
- target="_blank"
- rel="noopener noreferrer nofollow"
- >
- <i
- class="fa fa-question-circle"
- aria-hidden="true"
- ></i>
- </a>
+ <span v-if="hasHelpURL" class="help-button float-right">
+ <gl-link :href="helpUrl" target="_blank" rel="noopener noreferrer nofollow">
+ <i class="fa fa-question-circle" aria-hidden="true"></i>
+ </gl-link>
</span>
</p>
</template>
diff --git a/app/assets/javascripts/jobs/components/sidebar_details_block.vue b/app/assets/javascripts/jobs/components/sidebar_details_block.vue
deleted file mode 100644
index 80c2a5fb48b..00000000000
--- a/app/assets/javascripts/jobs/components/sidebar_details_block.vue
+++ /dev/null
@@ -1,239 +0,0 @@
-<script>
-import timeagoMixin from '~/vue_shared/mixins/timeago';
-import { timeIntervalInWords } from '~/lib/utils/datetime_utility';
-import Icon from '~/vue_shared/components/icon.vue';
-import DetailRow from './sidebar_detail_row.vue';
-
-export default {
- name: 'SidebarDetailsBlock',
- components: {
- DetailRow,
- Icon,
- },
- mixins: [timeagoMixin],
- props: {
- job: {
- type: Object,
- required: true,
- },
- isLoading: {
- type: Boolean,
- required: true,
- },
- runnerHelpUrl: {
- type: String,
- required: false,
- default: '',
- },
- terminalPath: {
- type: String,
- required: false,
- default: null,
- },
- },
- computed: {
- shouldRenderContent() {
- return !this.isLoading && Object.keys(this.job).length > 0;
- },
- coverage() {
- return `${this.job.coverage}%`;
- },
- duration() {
- return timeIntervalInWords(this.job.duration);
- },
- queued() {
- return timeIntervalInWords(this.job.queued);
- },
- runnerId() {
- return `${this.job.runner.description} (#${this.job.runner.id})`;
- },
- retryButtonClass() {
- let className =
- 'js-retry-button float-right btn btn-retry d-none d-md-block d-lg-block d-xl-block';
- className +=
- this.job.status && this.job.recoverable ? ' btn-primary' : ' btn-inverted-secondary';
- return className;
- },
- hasTimeout() {
- return this.job.metadata != null && this.job.metadata.timeout_human_readable !== null;
- },
- timeout() {
- if (this.job.metadata == null) {
- return '';
- }
-
- let t = this.job.metadata.timeout_human_readable;
- if (this.job.metadata.timeout_source !== '') {
- t += ` (from ${this.job.metadata.timeout_source})`;
- }
-
- return t;
- },
- renderBlock() {
- return (
- this.job.merge_request ||
- this.job.duration ||
- this.job.finished_data ||
- this.job.erased_at ||
- this.job.queued ||
- this.job.runner ||
- this.job.coverage ||
- this.job.tags.length ||
- this.job.cancel_path
- );
- },
- },
-};
-</script>
-<template>
- <div>
- <div class="block">
- <strong class="inline prepend-top-8">
- {{ job.name }}
- </strong>
- <a
- v-if="job.retry_path"
- :class="retryButtonClass"
- :href="job.retry_path"
- data-method="post"
- rel="nofollow"
- >
- {{ __('Retry') }}
- </a>
- <a
- v-if="terminalPath"
- :href="terminalPath"
- class="js-terminal-link pull-right btn btn-primary
- btn-inverted visible-md-block visible-lg-block"
- target="_blank"
- >
- {{ __('Debug') }}
- <icon name="external-link" />
- </a>
- <button
- :aria-label="__('Toggle Sidebar')"
- type="button"
- class="btn btn-blank gutter-toggle float-right d-block d-md-none js-sidebar-build-toggle"
- >
- <i
- aria-hidden="true"
- data-hidden="true"
- class="fa fa-angle-double-right"
- ></i>
- </button>
- </div>
- <template v-if="shouldRenderContent">
- <div
- v-if="job.retry_path || job.new_issue_path"
- class="block retry-link"
- >
- <a
- v-if="job.new_issue_path"
- :href="job.new_issue_path"
- class="js-new-issue btn btn-success btn-inverted"
- >
- {{ __('New issue') }}
- </a>
- <a
- v-if="job.retry_path"
- :href="job.retry_path"
- class="js-retry-job btn btn-inverted-secondary"
- data-method="post"
- rel="nofollow"
- >
- {{ __('Retry') }}
- </a>
- </div>
- <div :class="{block : renderBlock }">
- <p
- v-if="job.merge_request"
- class="build-detail-row js-job-mr"
- >
- <span class="build-light-text">
- {{ __('Merge Request:') }}
- </span>
- <a :href="job.merge_request.path">
- !{{ job.merge_request.iid }}
- </a>
- </p>
-
- <detail-row
- v-if="job.duration"
- :value="duration"
- class="js-job-duration"
- title="Duration"
- />
- <detail-row
- v-if="job.finished_at"
- :value="timeFormated(job.finished_at)"
- class="js-job-finished"
- title="Finished"
- />
- <detail-row
- v-if="job.erased_at"
- :value="timeFormated(job.erased_at)"
- class="js-job-erased"
- title="Erased"
- />
- <detail-row
- v-if="job.queued"
- :value="queued"
- class="js-job-queued"
- title="Queued"
- />
- <detail-row
- v-if="hasTimeout"
- :help-url="runnerHelpUrl"
- :value="timeout"
- class="js-job-timeout"
- title="Timeout"
- />
- <detail-row
- v-if="job.runner"
- :value="runnerId"
- class="js-job-runner"
- title="Runner"
- />
- <detail-row
- v-if="job.coverage"
- :value="coverage"
- class="js-job-coverage"
- title="Coverage"
- />
- <p
- v-if="job.tags.length"
- class="build-detail-row js-job-tags"
- >
- <span class="build-light-text">
- {{ __('Tags:') }}
- </span>
- <span
- v-for="(tag, i) in job.tags"
- :key="i"
- class="label label-primary">
- {{ tag }}
- </span>
- </p>
-
- <div
- v-if="job.cancel_path"
- class="btn-group prepend-top-5"
- role="group">
- <a
- :href="job.cancel_path"
- class="js-cancel-job btn btn-sm btn-default"
- data-method="post"
- rel="nofollow"
- >
- {{ __('Cancel') }}
- </a>
- </div>
- </div>
- </template>
- <gl-loading-icon
- v-if="isLoading"
- :size="2"
- class="prepend-top-10"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/jobs/components/stages_dropdown.vue b/app/assets/javascripts/jobs/components/stages_dropdown.vue
index d6d64fa32f7..90482500bbf 100644
--- a/app/assets/javascripts/jobs/components/stages_dropdown.vue
+++ b/app/assets/javascripts/jobs/components/stages_dropdown.vue
@@ -1,97 +1,64 @@
<script>
- import CiIcon from '~/vue_shared/components/ci_icon.vue';
- import Icon from '~/vue_shared/components/icon.vue';
+import _ from 'underscore';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import Icon from '~/vue_shared/components/icon.vue';
- import { sprintf, __ } from '~/locale';
-
- export default {
- components: {
- CiIcon,
- Icon,
+export default {
+ components: {
+ CiIcon,
+ Icon,
+ },
+ props: {
+ pipeline: {
+ type: Object,
+ required: true,
},
- props: {
- pipelineId: {
- type: Number,
- required: true,
- },
- pipelinePath: {
- type: String,
- required: true,
- },
- pipelineRef: {
- type: String,
- required: true,
- },
- pipelineRefPath: {
- type: String,
- required: true,
- },
- stages: {
- type: Array,
- required: true,
- },
- pipelineStatus: {
- type: Object,
- required: true,
- },
+ stages: {
+ type: Array,
+ required: true,
},
- data() {
- return {
- selectedStage: this.stages.length > 0 ? this.stages[0].name : __('More'),
- };
+ selectedStage: {
+ type: String,
+ required: true,
},
- computed: {
- pipelineLink() {
- return sprintf(__('Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}'), {
- pipelineLinkStart: `<a href=${this.pipelinePath} class="js-pipeline-path link-commit">`,
- pipelineId: this.pipelineId,
- pipelineLinkEnd: '</a>',
- pipelineLinkRefStart: `<a href=${this.pipelineRefPath} class="link-commit ref-name">`,
- pipelineRef: this.pipelineRef,
- pipelineLinkRefEnd: '</a>',
- }, false);
- },
+ },
+ computed: {
+ hasRef() {
+ return !_.isEmpty(this.pipeline.ref);
},
- methods: {
- onStageClick(stage) {
- // todo: consider moving into store
- this.selectedStage = stage.name;
-
- // update dropdown with jobs
- // jobs container is a new component.
- this.$emit('requestSidebarStageDropdown', stage);
- },
+ },
+ methods: {
+ onStageClick(stage) {
+ this.$emit('requestSidebarStageDropdown', stage);
},
- };
+ },
+};
</script>
<template>
- <div class="block-last">
- <ci-icon :status="pipelineStatus" />
+ <div class="block-last dropdown">
+ <ci-icon :status="pipeline.details.status" class="vertical-align-middle" />
+
+ {{ __('Pipeline') }}
+ <a :href="pipeline.path" class="js-pipeline-path link-commit"> #{{ pipeline.id }} </a>
+ <template v-if="hasRef">
+ {{ __('from') }}
+ <a :href="pipeline.ref.path" class="link-commit ref-name"> {{ pipeline.ref.name }} </a>
+ </template>
- <p v-html="pipelineLink"></p>
+ <button
+ type="button"
+ data-toggle="dropdown"
+ class="js-selected-stage dropdown-menu-toggle prepend-top-8"
+ >
+ {{ selectedStage }} <i class="fa fa-chevron-down"></i>
+ </button>
- <div class="dropdown">
- <button
- type="button"
- data-toggle="dropdown"
- >
- {{ selectedStage }}
- <icon name="chevron-down" />
- </button>
- <ul class="dropdown-menu">
- <li
- v-for="(stage, index) in stages"
- :key="index"
- >
- <button
- type="button"
- class="stage-item"
- @click="onStageClick(stage)"
- >
- {{ stage.name }}
- </button>
- </li>
- </ul>
- </div>
+ <ul class="dropdown-menu">
+ <li v-for="stage in stages" :key="stage.name">
+ <button type="button" class="js-stage-item stage-item" @click="onStageClick(stage);">
+ {{ stage.name }}
+ </button>
+ </li>
+ </ul>
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/stuck_block.vue b/app/assets/javascripts/jobs/components/stuck_block.vue
index 18883fea950..ec52d272168 100644
--- a/app/assets/javascripts/jobs/components/stuck_block.vue
+++ b/app/assets/javascripts/jobs/components/stuck_block.vue
@@ -1,8 +1,12 @@
<script>
+import { GlLink } from '@gitlab/ui';
/**
* Renders Stuck Runners block for job's view.
*/
export default {
+ components: {
+ GlLink,
+ },
props: {
hasNoRunnersForProject: {
type: Boolean,
@@ -22,42 +26,31 @@ export default {
</script>
<template>
<div class="bs-callout bs-callout-warning">
- <p
- v-if="hasNoRunnersForProject"
- class="js-stuck-no-runners"
- >
- {{ s__(`Job|This job is stuck, because the project
- doesn't have any runners online assigned to it.`) }}
- </p>
- <p
- v-else-if="tags.length"
- class="js-stuck-with-tags"
- >
- {{ s__(`This job is stuck, because you don't have
- any active runners online with any of these tags assigned to them:`) }}
- <span
- v-for="(tag, index) in tags"
- :key="index"
- class="badge badge-primary"
- >
+ <p v-if="tags.length" class="js-stuck-with-tags append-bottom-0">
+ {{
+ s__(`This job is stuck because you don't have
+ any active runners online with any of these tags assigned to them:`)
+ }}
+ <span v-for="(tag, index) in tags" :key="index" class="badge badge-primary append-right-4">
{{ tag }}
</span>
</p>
- <p
- v-else
- class="js-stuck-no-active-runner"
- >
- {{ s__(`This job is stuck, because you don't
- have any active runners that can run this job.`) }}
+ <p v-else-if="hasNoRunnersForProject" class="js-stuck-no-runners append-bottom-0">
+ {{
+ s__(`Job|This job is stuck because the project
+ doesn't have any runners online assigned to it.`)
+ }}
+ </p>
+ <p v-else class="js-stuck-no-active-runner append-bottom-0">
+ {{
+ s__(`This job is stuck because you don't
+ have any active runners that can run this job.`)
+ }}
</p>
- {{ __("Go to") }}
- <a
- v-if="runnersPath"
- :href="runnersPath"
- class="js-runners-path"
- >
- {{ __("Runners page") }}
- </a>
+ {{ __('Go to') }}
+ <gl-link v-if="runnersPath" :href="runnersPath" class="js-runners-path">
+ {{ __('Runners page') }}
+ </gl-link>
</div>
</template>
diff --git a/app/assets/javascripts/jobs/components/trigger_block.vue b/app/assets/javascripts/jobs/components/trigger_block.vue
index 8a88e5da6aa..4a9b2903eec 100644
--- a/app/assets/javascripts/jobs/components/trigger_block.vue
+++ b/app/assets/javascripts/jobs/components/trigger_block.vue
@@ -1,82 +1,61 @@
<script>
- export default {
- props: {
- shortToken: {
- type: String,
- required: false,
- default: null,
- },
+import { GlButton } from '@gitlab/ui';
- variables: {
- type: Object,
- required: false,
- default: () => ({}),
- },
+export default {
+ components: {
+ GlButton,
+ },
+ props: {
+ trigger: {
+ type: Object,
+ required: true,
},
- data() {
- return {
- areVariablesVisible: false,
- };
+ },
+ data() {
+ return {
+ areVariablesVisible: false,
+ };
+ },
+ computed: {
+ hasVariables() {
+ return this.trigger.variables && this.trigger.variables.length > 0;
},
- computed: {
- hasVariables() {
- return Object.keys(this.variables).length > 0;
- },
+ },
+ methods: {
+ revealVariables() {
+ this.areVariablesVisible = true;
},
- methods: {
- revealVariables() {
- this.areVariablesVisible = true;
- },
- },
- };
+ },
+};
</script>
<template>
<div class="build-widget block">
- <h4 class="title">
- {{ __('Trigger') }}
- </h4>
+ <h4 class="title">{{ __('Trigger') }}</h4>
- <p
- v-if="shortToken"
- class="js-short-token"
- >
- <span class="build-light-text">
- {{ __('Token') }}
- </span>
- {{ shortToken }}
+ <p v-if="trigger.short_token" class="js-short-token">
+ <span class="build-light-text"> {{ __('Token') }} </span> {{ trigger.short_token }}
</p>
<p v-if="hasVariables">
- <button
+ <gl-button
+ v-if="!areVariablesVisible"
type="button"
class="btn btn-default group js-reveal-variables"
@click="revealVariables"
>
{{ __('Reveal Variables') }}
- </button>
-
+ </gl-button>
</p>
- <dl
- v-if="areVariablesVisible"
- class="js-build-variables trigger-build-variables"
- >
- <template
- v-for="(value, key) in variables"
- >
- <dt
- :key="`${key}-variable`"
- class="js-build-variable trigger-build-variable"
- >
- {{ key }}
+ <dl v-if="areVariablesVisible" class="js-build-variables trigger-build-variables">
+ <template v-for="variable in trigger.variables">
+ <dt :key="`${variable.key}-variable`" class="js-build-variable trigger-build-variable">
+ {{ variable.key }}
</dt>
- <dd
- :key="`${key}-value`"
- class="js-build-value trigger-build-value"
- >
- {{ value }}
+ <dd :key="`${variable.key}-value`" class="js-build-value trigger-build-value">
+ {{ variable.value }}
</dd>
</template>
</dl>
diff --git a/app/assets/javascripts/jobs/index.js b/app/assets/javascripts/jobs/index.js
new file mode 100644
index 00000000000..a32e945627c
--- /dev/null
+++ b/app/assets/javascripts/jobs/index.js
@@ -0,0 +1,25 @@
+import Vue from 'vue';
+import JobApp from './components/job_app.vue';
+
+export default () => {
+ const element = document.getElementById('js-job-vue-app');
+
+ return new Vue({
+ el: element,
+ components: {
+ JobApp,
+ },
+ render(createElement) {
+ return createElement('job-app', {
+ props: {
+ runnerHelpUrl: element.dataset.runnerHelpUrl,
+ runnerSettingsUrl: element.dataset.runnerSettingsUrl,
+ endpoint: element.dataset.endpoint,
+ pagePath: element.dataset.buildOptionsPagePath,
+ logState: element.dataset.buildOptionsLogState,
+ buildStatus: element.dataset.buildOptionsBuildStatus,
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/jobs/job_details_bundle.js b/app/assets/javascripts/jobs/job_details_bundle.js
deleted file mode 100644
index a84324f14b2..00000000000
--- a/app/assets/javascripts/jobs/job_details_bundle.js
+++ /dev/null
@@ -1,62 +0,0 @@
-import Vue from 'vue';
-import JobMediator from './job_details_mediator';
-import jobHeader from './components/header.vue';
-import detailsBlock from './components/sidebar_details_block.vue';
-
-export default () => {
- const { dataset } = document.getElementById('js-job-details-vue');
- const mediator = new JobMediator({ endpoint: dataset.endpoint });
-
- mediator.fetchJob();
-
- // Header
- // eslint-disable-next-line no-new
- new Vue({
- el: '#js-build-header-vue',
- components: {
- jobHeader,
- },
- data() {
- return {
- mediator,
- };
- },
- mounted() {
- this.mediator.initBuildClass();
- },
- render(createElement) {
- return createElement('job-header', {
- props: {
- isLoading: this.mediator.state.isLoading,
- job: this.mediator.store.state.job,
- },
- });
- },
- });
-
- // Sidebar information block
- const detailsBlockElement = document.getElementById('js-details-block-vue');
- const detailsBlockDataset = detailsBlockElement.dataset;
- // eslint-disable-next-line
- new Vue({
- el: detailsBlockElement,
- components: {
- detailsBlock,
- },
- data() {
- return {
- mediator,
- };
- },
- render(createElement) {
- return createElement('details-block', {
- props: {
- isLoading: this.mediator.state.isLoading,
- job: this.mediator.store.state.job,
- runnerHelpUrl: dataset.runnerHelpUrl,
- terminalPath: detailsBlockDataset.terminalPath,
- },
- });
- },
- });
-};
diff --git a/app/assets/javascripts/jobs/job_details_mediator.js b/app/assets/javascripts/jobs/job_details_mediator.js
deleted file mode 100644
index 89019da9d1e..00000000000
--- a/app/assets/javascripts/jobs/job_details_mediator.js
+++ /dev/null
@@ -1,67 +0,0 @@
-import Visibility from 'visibilityjs';
-import Flash from '../flash';
-import Poll from '../lib/utils/poll';
-import JobStore from './stores/job_store';
-import JobService from './services/job_service';
-import Job from '../job';
-import handleRevealVariables from '../build_variables';
-
-export default class JobMediator {
- constructor(options = {}) {
- this.options = options;
-
- this.store = new JobStore();
- this.service = new JobService(options.endpoint);
-
- this.state = {
- isLoading: false,
- };
- }
-
- initBuildClass() {
- this.build = new Job();
- handleRevealVariables();
- }
-
- fetchJob() {
- this.poll = new Poll({
- resource: this.service,
- method: 'getJob',
- successCallback: response => this.successCallback(response),
- errorCallback: () => this.errorCallback(),
- });
-
- if (!Visibility.hidden()) {
- this.state.isLoading = true;
- this.poll.makeRequest();
- } else {
- this.getJob();
- }
-
- Visibility.change(() => {
- if (!Visibility.hidden()) {
- this.poll.restart();
- } else {
- this.poll.stop();
- }
- });
- }
-
- getJob() {
- return this.service
- .getJob()
- .then(response => this.successCallback(response))
- .catch(() => this.errorCallback());
- }
-
- successCallback(response) {
- this.state.isLoading = false;
- return this.store.storeJob(response.data);
- }
-
- errorCallback() {
- this.state.isLoading = false;
-
- return new Flash('An error occurred while fetching the job.');
- }
-}
diff --git a/app/assets/javascripts/jobs/mixins/delayed_job_mixin.js b/app/assets/javascripts/jobs/mixins/delayed_job_mixin.js
new file mode 100644
index 00000000000..8c7fb785a61
--- /dev/null
+++ b/app/assets/javascripts/jobs/mixins/delayed_job_mixin.js
@@ -0,0 +1,50 @@
+import { calculateRemainingMilliseconds, formatTime } from '~/lib/utils/datetime_utility';
+
+export default {
+ data() {
+ return {
+ remainingTime: formatTime(0),
+ remainingTimeIntervalId: null,
+ };
+ },
+
+ mounted() {
+ this.startRemainingTimeInterval();
+ },
+
+ beforeDestroy() {
+ if (this.remainingTimeIntervalId) {
+ clearInterval(this.remainingTimeIntervalId);
+ }
+ },
+
+ computed: {
+ isDelayedJob() {
+ return this.job && this.job.scheduled;
+ },
+ },
+
+ watch: {
+ isDelayedJob() {
+ this.startRemainingTimeInterval();
+ },
+ },
+
+ methods: {
+ startRemainingTimeInterval() {
+ if (this.remainingTimeIntervalId) {
+ clearInterval(this.remainingTimeIntervalId);
+ }
+
+ if (this.isDelayedJob) {
+ this.updateRemainingTime();
+ this.remainingTimeIntervalId = setInterval(() => this.updateRemainingTime(), 1000);
+ }
+ },
+
+ updateRemainingTime() {
+ const remainingMilliseconds = calculateRemainingMilliseconds(this.job.scheduled_at);
+ this.remainingTime = formatTime(remainingMilliseconds);
+ },
+ },
+};
diff --git a/app/assets/javascripts/jobs/services/job_service.js b/app/assets/javascripts/jobs/services/job_service.js
deleted file mode 100644
index b746489c45c..00000000000
--- a/app/assets/javascripts/jobs/services/job_service.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import axios from '../../lib/utils/axios_utils';
-
-export default class JobService {
- constructor(endpoint) {
- this.job = endpoint;
- }
-
- getJob() {
- return axios.get(this.job);
- }
-}
diff --git a/app/assets/javascripts/jobs/store/actions.js b/app/assets/javascripts/jobs/store/actions.js
index 7f5406d6f43..8045f6dc3ff 100644
--- a/app/assets/javascripts/jobs/store/actions.js
+++ b/app/assets/javascripts/jobs/store/actions.js
@@ -1,17 +1,32 @@
import Visibility from 'visibilityjs';
import * as types from './mutation_types';
-import axios from '../../lib/utils/axios_utils';
-import Poll from '../../lib/utils/poll';
-import { setCiStatusFavicon } from '../../lib/utils/common_utils';
-import flash from '../../flash';
-import { __ } from '../../locale';
+import axios from '~/lib/utils/axios_utils';
+import Poll from '~/lib/utils/poll';
+import { setFaviconOverlay, resetFavicon } from '~/lib/utils/common_utils';
+import flash from '~/flash';
+import { __ } from '~/locale';
+import {
+ canScroll,
+ isScrolledToBottom,
+ isScrolledToTop,
+ isScrolledToMiddle,
+ scrollDown,
+ scrollUp,
+} from '~/lib/utils/scroll_utils';
export const setJobEndpoint = ({ commit }, endpoint) => commit(types.SET_JOB_ENDPOINT, endpoint);
-export const setTraceEndpoint = ({ commit }, endpoint) =>
- commit(types.SET_TRACE_ENDPOINT, endpoint);
-export const setStagesEndpoint = ({ commit }, endpoint) =>
- commit(types.SET_STAGES_ENDPOINT, endpoint);
-export const setJobsEndpoint = ({ commit }, endpoint) => commit(types.SET_JOBS_ENDPOINT, endpoint);
+export const setTraceOptions = ({ commit }, options) => commit(types.SET_TRACE_OPTIONS, options);
+
+export const hideSidebar = ({ commit }) => commit(types.HIDE_SIDEBAR);
+export const showSidebar = ({ commit }) => commit(types.SHOW_SIDEBAR);
+
+export const toggleSidebar = ({ dispatch, state }) => {
+ if (state.isSidebarOpen) {
+ dispatch('hideSidebar');
+ } else {
+ dispatch('showSidebar');
+ }
+};
let eTagPoll;
@@ -62,39 +77,84 @@ export const fetchJob = ({ state, dispatch }) => {
});
};
-export const receiveJobSuccess = ({ commit }, data) => commit(types.RECEIVE_JOB_SUCCESS, data);
+export const receiveJobSuccess = ({ commit }, data = {}) => {
+ commit(types.RECEIVE_JOB_SUCCESS, data);
+
+ if (data.status && data.status.favicon) {
+ setFaviconOverlay(data.status.favicon);
+ } else {
+ resetFavicon();
+ }
+};
export const receiveJobError = ({ commit }) => {
commit(types.RECEIVE_JOB_ERROR);
flash(__('An error occurred while fetching the job.'));
+ resetFavicon();
};
/**
* Job's Trace
*/
-export const scrollTop = ({ commit }) => {
- commit(types.SCROLL_TO_TOP);
- window.scrollTo({ top: 0 });
+export const scrollTop = ({ dispatch }) => {
+ scrollUp();
+ dispatch('toggleScrollButtons');
};
-export const scrollBottom = ({ commit }) => {
- commit(types.SCROLL_TO_BOTTOM);
- window.scrollTo({ top: document.height });
+export const scrollBottom = ({ dispatch }) => {
+ scrollDown();
+ dispatch('toggleScrollButtons');
+};
+
+/**
+ * Responsible for toggling the disabled state of the scroll buttons
+ */
+export const toggleScrollButtons = ({ dispatch }) => {
+ if (canScroll()) {
+ if (isScrolledToMiddle()) {
+ dispatch('enableScrollTop');
+ dispatch('enableScrollBottom');
+ } else if (isScrolledToTop()) {
+ dispatch('disableScrollTop');
+ dispatch('enableScrollBottom');
+ } else if (isScrolledToBottom()) {
+ dispatch('disableScrollBottom');
+ dispatch('enableScrollTop');
+ }
+ } else {
+ dispatch('disableScrollBottom');
+ dispatch('disableScrollTop');
+ }
+};
+
+export const disableScrollBottom = ({ commit }) => commit(types.DISABLE_SCROLL_BOTTOM);
+export const disableScrollTop = ({ commit }) => commit(types.DISABLE_SCROLL_TOP);
+export const enableScrollBottom = ({ commit }) => commit(types.ENABLE_SCROLL_BOTTOM);
+export const enableScrollTop = ({ commit }) => commit(types.ENABLE_SCROLL_TOP);
+
+/**
+ * While the automatic scroll down is active,
+ * we show the scroll down button with an animation
+ */
+export const toggleScrollAnimation = ({ commit }, toggle) =>
+ commit(types.TOGGLE_SCROLL_ANIMATION, toggle);
+
+/**
+ * Responsible to handle automatic scroll
+ */
+export const toggleScrollisInBottom = ({ commit }, toggle) => {
+ commit(types.TOGGLE_IS_SCROLL_IN_BOTTOM_BEFORE_UPDATING_TRACE, toggle);
};
export const requestTrace = ({ commit }) => commit(types.REQUEST_TRACE);
let traceTimeout;
-export const fetchTrace = ({ dispatch, state }) => {
- dispatch('requestTrace');
-
+export const fetchTrace = ({ dispatch, state }) =>
axios
.get(`${state.traceEndpoint}/trace.json`, {
params: { state: state.traceState },
})
.then(({ data }) => {
- if (!state.fetchingStatusFavicon) {
- dispatch('fetchFavicon');
- }
+ dispatch('toggleScrollisInBottom', isScrolledToBottom());
dispatch('receiveTraceSuccess', data);
if (!data.complete) {
@@ -106,7 +166,7 @@ export const fetchTrace = ({ dispatch, state }) => {
}
})
.catch(() => dispatch('receiveTraceError'));
-};
+
export const stopPollingTrace = ({ commit }) => {
commit(types.STOP_POLLING_TRACE);
clearTimeout(traceTimeout);
@@ -118,17 +178,6 @@ export const receiveTraceError = ({ commit }) => {
flash(__('An error occurred while fetching the job log.'));
};
-export const fetchFavicon = ({ state, dispatch }) => {
- dispatch('requestStatusFavicon');
- setCiStatusFavicon(`${state.pagePath}/status.json`)
- .then(() => dispatch('receiveStatusFaviconSuccess'))
- .catch(() => dispatch('requestStatusFaviconError'));
-};
-export const requestStatusFavicon = ({ commit }) => commit(types.REQUEST_STATUS_FAVICON);
-export const receiveStatusFaviconSuccess = ({ commit }) =>
- commit(types.RECEIVE_STATUS_FAVICON_SUCCESS);
-export const requestStatusFaviconError = ({ commit }) => commit(types.RECEIVE_STATUS_FAVICON_ERROR);
-
/**
* Stages dropdown on sidebar
*/
@@ -137,8 +186,13 @@ export const fetchStages = ({ state, dispatch }) => {
dispatch('requestStages');
axios
- .get(state.stagesEndpoint)
- .then(({ data }) => dispatch('receiveStagesSuccess', data))
+ .get(`${state.job.pipeline.path}.json`)
+ .then(({ data }) => {
+ // Set selected stage
+ dispatch('receiveStagesSuccess', data.details.stages);
+ const selectedStage = data.details.stages.find(stage => stage.name === state.selectedStage);
+ dispatch('fetchJobsForStage', selectedStage);
+ })
.catch(() => dispatch('receiveStagesError'));
};
export const receiveStagesSuccess = ({ commit }, data) =>
@@ -151,17 +205,25 @@ export const receiveStagesError = ({ commit }) => {
/**
* Jobs list on sidebar - depend on stages dropdown
*/
-export const requestJobsForStage = ({ commit }) => commit(types.REQUEST_JOBS_FOR_STAGE);
-export const setSelectedStage = ({ commit }, stage) => commit(types.SET_SELECTED_STAGE, stage);
+export const requestJobsForStage = ({ commit }, stage) =>
+ commit(types.REQUEST_JOBS_FOR_STAGE, stage);
// On stage click, set selected stage + fetch job
-export const fetchJobsForStage = ({ state, dispatch }, stage) => {
- dispatch('setSelectedStage', stage);
- dispatch('requestJobsForStage');
+export const fetchJobsForStage = ({ dispatch }, stage) => {
+ dispatch('requestJobsForStage', stage);
axios
- .get(state.stageJobsEndpoint)
- .then(({ data }) => dispatch('receiveJobsForStageSuccess', data))
+ .get(stage.dropdown_path, {
+ params: {
+ retried: 1,
+ },
+ })
+ .then(({ data }) => {
+ const retriedJobs = data.retried.map(job => Object.assign({}, job, { retried: true }));
+ const jobs = data.latest_statuses.concat(retriedJobs);
+
+ dispatch('receiveJobsForStageSuccess', jobs);
+ })
.catch(() => dispatch('receiveJobsForStageError'));
};
export const receiveJobsForStageSuccess = ({ commit }, data) =>
diff --git a/app/assets/javascripts/jobs/store/getters.js b/app/assets/javascripts/jobs/store/getters.js
new file mode 100644
index 00000000000..35e92b0b5d9
--- /dev/null
+++ b/app/assets/javascripts/jobs/store/getters.js
@@ -0,0 +1,53 @@
+import _ from 'underscore';
+import { __ } from '~/locale';
+import { isScrolledToBottom } from '~/lib/utils/scroll_utils';
+
+export const headerActions = state => {
+ if (state.job.new_issue_path) {
+ return [
+ {
+ label: __('New issue'),
+ path: state.job.new_issue_path,
+ cssClass:
+ 'js-new-issue btn btn-success btn-inverted d-none d-md-block d-lg-block d-xl-block',
+ type: 'link',
+ },
+ ];
+ }
+ return [];
+};
+
+export const headerTime = state => (state.job.started ? state.job.started : state.job.created_at);
+
+export const shouldRenderCalloutMessage = state =>
+ !_.isEmpty(state.job.status) && !_.isEmpty(state.job.callout_message);
+
+/**
+ * When job has not started the key will be null
+ * When job started the key will be a string with a date.
+ */
+export const shouldRenderTriggeredLabel = state => _.isString(state.job.started);
+
+export const hasEnvironment = state => !_.isEmpty(state.job.deployment_status);
+
+/**
+ * Checks if it the job has trace.
+ * Used to check if it should render the job log or the empty state
+ * @returns {Boolean}
+ */
+export const hasTrace = state =>
+ state.job.has_trace || (!_.isEmpty(state.job.status) && state.job.status.group === 'running');
+
+export const emptyStateIllustration = state =>
+ (state.job && state.job.status && state.job.status.illustration) || {};
+
+export const emptyStateAction = state =>
+ (state.job && state.job.status && state.job.status.action) || null;
+
+export const isScrollingDown = state => isScrolledToBottom() && !state.isTraceComplete;
+
+export const hasRunnersForProject = state =>
+ state.job.runners.available && !state.job.runners.online;
+
+// prevent babel-plugin-rewire from generating an invalid default during karma tests
+export default () => {};
diff --git a/app/assets/javascripts/jobs/store/index.js b/app/assets/javascripts/jobs/store/index.js
index d8f6f56ce61..bba01426af7 100644
--- a/app/assets/javascripts/jobs/store/index.js
+++ b/app/assets/javascripts/jobs/store/index.js
@@ -2,12 +2,15 @@ import Vue from 'vue';
import Vuex from 'vuex';
import state from './state';
import * as actions from './actions';
+import * as getters from './getters';
import mutations from './mutations';
Vue.use(Vuex);
-export default () => new Vuex.Store({
- actions,
- mutations,
- state: state(),
-});
+export default () =>
+ new Vuex.Store({
+ actions,
+ mutations,
+ getters,
+ state: state(),
+ });
diff --git a/app/assets/javascripts/jobs/store/mutation_types.js b/app/assets/javascripts/jobs/store/mutation_types.js
index e66e1d4f116..fd098f13e90 100644
--- a/app/assets/javascripts/jobs/store/mutation_types.js
+++ b/app/assets/javascripts/jobs/store/mutation_types.js
@@ -1,10 +1,19 @@
export const SET_JOB_ENDPOINT = 'SET_JOB_ENDPOINT';
-export const SET_TRACE_ENDPOINT = 'SET_TRACE_ENDPOINT';
-export const SET_STAGES_ENDPOINT = 'SET_STAGES_ENDPOINT';
-export const SET_JOBS_ENDPOINT = 'SET_JOBS_ENDPOINT';
+export const SET_TRACE_OPTIONS = 'SET_TRACE_OPTIONS';
+
+export const HIDE_SIDEBAR = 'HIDE_SIDEBAR';
+export const SHOW_SIDEBAR = 'SHOW_SIDEBAR';
export const SCROLL_TO_TOP = 'SCROLL_TO_TOP';
export const SCROLL_TO_BOTTOM = 'SCROLL_TO_BOTTOM';
+export const DISABLE_SCROLL_BOTTOM = 'DISABLE_SCROLL_BOTTOM';
+export const DISABLE_SCROLL_TOP = 'DISABLE_SCROLL_TOP';
+export const ENABLE_SCROLL_BOTTOM = 'ENABLE_SCROLL_BOTTOM';
+export const ENABLE_SCROLL_TOP = 'ENABLE_SCROLL_TOP';
+// TODO
+export const TOGGLE_SCROLL_ANIMATION = 'TOGGLE_SCROLL_ANIMATION';
+
+export const TOGGLE_IS_SCROLL_IN_BOTTOM_BEFORE_UPDATING_TRACE = 'TOGGLE_IS_SCROLL_IN_BOTTOM';
export const REQUEST_JOB = 'REQUEST_JOB';
export const RECEIVE_JOB_SUCCESS = 'RECEIVE_JOB_SUCCESS';
@@ -15,10 +24,6 @@ export const STOP_POLLING_TRACE = 'STOP_POLLING_TRACE';
export const RECEIVE_TRACE_SUCCESS = 'RECEIVE_TRACE_SUCCESS';
export const RECEIVE_TRACE_ERROR = 'RECEIVE_TRACE_ERROR';
-export const REQUEST_STATUS_FAVICON = 'REQUEST_STATUS_FAVICON';
-export const RECEIVE_STATUS_FAVICON_SUCCESS = 'RECEIVE_STATUS_FAVICON_SUCCESS';
-export const RECEIVE_STATUS_FAVICON_ERROR = 'RECEIVE_STATUS_FAVICON_ERROR';
-
export const REQUEST_STAGES = 'REQUEST_STAGES';
export const RECEIVE_STAGES_SUCCESS = 'RECEIVE_STAGES_SUCCESS';
export const RECEIVE_STAGES_ERROR = 'RECEIVE_STAGES_ERROR';
diff --git a/app/assets/javascripts/jobs/store/mutations.js b/app/assets/javascripts/jobs/store/mutations.js
index cd12ef87d40..cd440d21c1f 100644
--- a/app/assets/javascripts/jobs/store/mutations.js
+++ b/app/assets/javascripts/jobs/store/mutations.js
@@ -1,14 +1,20 @@
import * as types from './mutation_types';
export default {
- [types.REQUEST_STATUS_FAVICON](state) {
- state.fetchingStatusFavicon = true;
+ [types.SET_JOB_ENDPOINT](state, endpoint) {
+ state.jobEndpoint = endpoint;
},
- [types.RECEIVE_STATUS_FAVICON_SUCCESS](state) {
- state.fetchingStatusFavicon = false;
+
+ [types.SET_TRACE_OPTIONS](state, options = {}) {
+ state.traceEndpoint = options.pagePath;
+ state.traceState = options.logState;
+ },
+
+ [types.HIDE_SIDEBAR](state) {
+ state.isSidebarOpen = false;
},
- [types.RECEIVE_STATUS_FAVICON_ERROR](state) {
- state.fetchingStatusFavicon = false;
+ [types.SHOW_SIDEBAR](state) {
+ state.isSidebarOpen = true;
},
[types.RECEIVE_TRACE_SUCCESS](state, log) {
@@ -20,8 +26,12 @@ export default {
state.trace += log.html;
state.traceSize += log.size;
} else {
- state.trace = log.html;
- state.traceSize = log.size;
+ // When the job still does not have a trace
+ // the trace response will not have a defined
+ // html or size. We keep the old value otherwise these
+ // will be set to `undefined`
+ state.trace = log.html || state.trace;
+ state.traceSize = log.size || state.traceSize;
}
if (state.traceSize < log.total) {
@@ -30,40 +40,65 @@ export default {
state.isTraceSizeVisible = false;
}
- state.isTraceComplete = log.complete;
- state.hasTraceError = false;
+ state.isTraceComplete = log.complete || state.isTraceComplete;
},
+
+ /**
+ * Will remove loading animation
+ */
[types.STOP_POLLING_TRACE](state) {
state.isTraceComplete = true;
},
- // todo_fl: check this.
+
+ /**
+ * Will remove loading animation
+ */
[types.RECEIVE_TRACE_ERROR](state) {
- state.isLoadingTrace = false;
state.isTraceComplete = true;
- state.hasTraceError = true;
},
[types.REQUEST_JOB](state) {
state.isLoading = true;
},
[types.RECEIVE_JOB_SUCCESS](state, job) {
- state.isLoading = false;
state.hasError = false;
+ state.isLoading = false;
state.job = job;
+
+ /**
+ * We only update it on the first request
+ * The dropdown can be changed by the user
+ * after the first request,
+ * and we do not want to hijack that
+ */
+ if (state.selectedStage === '' && job.stage) {
+ state.selectedStage = job.stage;
+ }
},
[types.RECEIVE_JOB_ERROR](state) {
state.isLoading = false;
- state.hasError = true;
state.job = {};
+ state.hasError = true;
},
- [types.SCROLL_TO_TOP](state) {
- state.isTraceScrolledToBottom = false;
- state.hasBeenScrolled = true;
+ [types.ENABLE_SCROLL_TOP](state) {
+ state.isScrollTopDisabled = false;
+ },
+ [types.DISABLE_SCROLL_TOP](state) {
+ state.isScrollTopDisabled = true;
},
- [types.SCROLL_TO_BOTTOM](state) {
- state.isTraceScrolledToBottom = true;
- state.hasBeenScrolled = true;
+ [types.ENABLE_SCROLL_BOTTOM](state) {
+ state.isScrollBottomDisabled = false;
+ },
+ [types.DISABLE_SCROLL_BOTTOM](state) {
+ state.isScrollBottomDisabled = true;
+ },
+ [types.TOGGLE_SCROLL_ANIMATION](state, toggle) {
+ state.isScrollingDown = toggle;
+ },
+
+ [types.TOGGLE_IS_SCROLL_IN_BOTTOM_BEFORE_UPDATING_TRACE](state, toggle) {
+ state.isScrolledToBottomBeforeReceivingTrace = toggle;
},
[types.REQUEST_STAGES](state) {
@@ -78,8 +113,9 @@ export default {
state.stages = [];
},
- [types.REQUEST_JOBS_FOR_STAGE](state) {
+ [types.REQUEST_JOBS_FOR_STAGE](state, stage) {
state.isLoadingJobs = true;
+ state.selectedStage = stage.name;
},
[types.RECEIVE_JOBS_FOR_STAGE_SUCCESS](state, jobs) {
state.isLoadingJobs = false;
diff --git a/app/assets/javascripts/jobs/store/state.js b/app/assets/javascripts/jobs/store/state.js
index 509cb69a5d3..04825187c99 100644
--- a/app/assets/javascripts/jobs/store/state.js
+++ b/app/assets/javascripts/jobs/store/state.js
@@ -2,39 +2,32 @@ export default () => ({
jobEndpoint: null,
traceEndpoint: null,
- // dropdown options
- stagesEndpoint: null,
- // list of jobs on sidebard
- stageJobsEndpoint: null,
+ // sidebar
+ isSidebarOpen: true,
- // job log
isLoading: false,
hasError: false,
job: {},
- // trace
- isLoadingTrace: false,
- hasTraceError: false,
+ // scroll buttons state
+ isScrollBottomDisabled: true,
+ isScrollTopDisabled: true,
- trace: '',
-
- isTraceScrolledToBottom: false,
- hasBeenScrolled: false,
+ // Used to check if we should keep the automatic scroll
+ isScrolledToBottomBeforeReceivingTrace: true,
+ trace: '',
isTraceComplete: false,
- traceSize: 0, // todo_fl: needs to be converted into human readable format in components
+ traceSize: 0,
isTraceSizeVisible: false,
- fetchingStatusFavicon: false,
- // used as a query parameter
+ // used as a query parameter to fetch the trace
traceState: null,
- // used to check if we need to redirect the user - todo_fl: check if actually needed
- traceStatus: null,
- // sidebar dropdown
+ // sidebar dropdown & list of jobs
isLoadingStages: false,
isLoadingJobs: false,
- selectedStage: null,
+ selectedStage: '',
stages: [],
jobs: [],
});
diff --git a/app/assets/javascripts/jobs/stores/job_store.js b/app/assets/javascripts/jobs/stores/job_store.js
deleted file mode 100644
index 766194b8387..00000000000
--- a/app/assets/javascripts/jobs/stores/job_store.js
+++ /dev/null
@@ -1,11 +0,0 @@
-export default class JobStore {
- constructor() {
- this.state = {
- job: {},
- };
- }
-
- storeJob(job = {}) {
- this.state.job = job;
- }
-}
diff --git a/app/assets/javascripts/jobs/svg/scroll_down.svg b/app/assets/javascripts/jobs/svg/scroll_down.svg
new file mode 100644
index 00000000000..1d22870ec09
--- /dev/null
+++ b/app/assets/javascripts/jobs/svg/scroll_down.svg
@@ -0,0 +1,5 @@
+<svg width="12" height="16" viewBox="0 0 12 16" xmlns="http://www.w3.org/2000/svg">
+ <path class="first-triangle" d="M1.048 14.155a.508.508 0 0 0-.32.105c-.091.07-.136.154-.136.25v.71c0 .095.045.178.135.249.09.07.197.105.321.105h10.043c.124 0 .23-.035.321-.105.09-.07.136-.154.136-.25v-.71c0-.095-.045-.178-.136-.249a.508.508 0 0 0-.32-.105"/>
+ <path class="second-triangle" d="M.687 8.027c-.09-.087-.122-.16-.093-.22.028-.06.104-.09.228-.09h10.5c.123 0 .2.03.228.09.029.06-.002.133-.093.22L6.393 12.91a.458.458 0 0 1-.136.089h-.37a.626.626 0 0 1-.136-.09"/>
+ <path class="third-triangle" d="M.687 1.027C.597.94.565.867.594.807c.028-.06.104-.09.228-.09h10.5c.123 0 .2.03.228.09.029.06-.002.133-.093.22L6.393 5.91A.458.458 0 0 1 6.257 6h-.37a.626.626 0 0 1-.136-.09"/>
+</svg>
diff --git a/app/assets/javascripts/label_manager.js b/app/assets/javascripts/label_manager.js
index c10b1a2b233..062501d1d04 100644
--- a/app/assets/javascripts/label_manager.js
+++ b/app/assets/javascripts/label_manager.js
@@ -1,4 +1,4 @@
-/* eslint-disable class-methods-use-this, no-underscore-dangle, no-param-reassign, no-unused-vars, func-names, max-len */
+/* eslint-disable class-methods-use-this, no-underscore-dangle, no-param-reassign, no-unused-vars, func-names */
import $ from 'jquery';
import Sortable from 'sortablejs';
@@ -47,7 +47,10 @@ export default class LabelManager {
}
toggleEmptyState($label, $btn, action) {
- this.emptyState.classList.toggle('hidden', !!this.prioritizedLabels[0].querySelector(':scope > li'));
+ this.emptyState.classList.toggle(
+ 'hidden',
+ !!this.prioritizedLabels[0].querySelector(':scope > li'),
+ );
}
toggleLabelPriority($label, action, persistState) {
@@ -80,16 +83,14 @@ export default class LabelManager {
return;
}
if (action === 'remove') {
- axios.delete(url)
- .catch(rollbackLabelPosition);
+ axios.delete(url).catch(rollbackLabelPosition);
// Restore empty message
if (!$from.find('li').length) {
$from.find('.empty-message').removeClass('hidden');
}
} else {
- this.savePrioritySort($label, action)
- .catch(rollbackLabelPosition);
+ this.savePrioritySort($label, action).catch(rollbackLabelPosition);
}
}
@@ -102,8 +103,7 @@ export default class LabelManager {
}
onPrioritySortUpdate() {
- this.savePrioritySort()
- .catch(() => flash(this.errorMessage));
+ this.savePrioritySort().catch(() => flash(this.errorMessage));
}
savePrioritySort() {
diff --git a/app/assets/javascripts/labels.js b/app/assets/javascripts/labels.js
index d85ae851706..cd8cf0d354c 100644
--- a/app/assets/javascripts/labels.js
+++ b/app/assets/javascripts/labels.js
@@ -22,7 +22,7 @@ export default class Labels {
updateColorPreview() {
const previewColor = $('input#label_color').val();
return $('div.label-color-preview').css('background-color', previewColor);
- // Updates the the preview color with the hex-color input
+ // Updates the preview color with the hex-color input
}
// Updates the preview color with a click on a suggested color
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
index 1c7bca78df3..c0a76814102 100644
--- a/app/assets/javascripts/labels_select.js
+++ b/app/assets/javascripts/labels_select.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-useless-return, func-names, no-var, no-underscore-dangle, prefer-arrow-callback, max-len, one-var, no-unused-vars, one-var-declaration-per-line, prefer-template, no-new, consistent-return, object-shorthand, comma-dangle, no-shadow, no-param-reassign, brace-style, vars-on-top, quotes, no-lonely-if, no-else-return, dot-notation, no-empty */
+/* eslint-disable no-useless-return, func-names, no-var, no-underscore-dangle, prefer-arrow-callback, one-var, no-unused-vars, prefer-template, no-new, consistent-return, object-shorthand, no-shadow, no-param-reassign, vars-on-top, no-lonely-if, no-else-return, dot-notation, no-empty */
/* global Issuable */
/* global ListLabel */
@@ -11,6 +11,7 @@ import DropdownUtils from './filtered_search/dropdown_utils';
import CreateLabelDropdown from './create_label';
import flash from './flash';
import ModalStore from './boards/stores/modal_store';
+import boardsStore from './boards/stores/boards_store';
export default class LabelsSelect {
constructor(els, options = {}) {
@@ -24,16 +25,43 @@ export default class LabelsSelect {
}
$els.each(function(i, dropdown) {
- var $block, $colorPreview, $dropdown, $form, $loading, $selectbox, $sidebarCollapsedValue, $value, abilityName, defaultLabel, enableLabelCreateButton, issueURLSplit, issueUpdateURL, labelUrl, namespacePath, projectPath, saveLabelData, selectedLabel, showAny, showNo, $sidebarLabelTooltip, initialSelected, $toggleText, fieldName, useId, propertyName, showMenuAbove, $container, $dropdownContainer;
+ var $block,
+ $colorPreview,
+ $dropdown,
+ $form,
+ $loading,
+ $selectbox,
+ $sidebarCollapsedValue,
+ $value,
+ abilityName,
+ defaultLabel,
+ enableLabelCreateButton,
+ issueURLSplit,
+ issueUpdateURL,
+ labelUrl,
+ namespacePath,
+ projectPath,
+ saveLabelData,
+ selectedLabel,
+ showAny,
+ showNo,
+ $sidebarLabelTooltip,
+ initialSelected,
+ $toggleText,
+ fieldName,
+ useId,
+ propertyName,
+ showMenuAbove,
+ $container,
+ $dropdownContainer;
$dropdown = $(dropdown);
$dropdownContainer = $dropdown.closest('.labels-filter');
$toggleText = $dropdown.find('.dropdown-toggle-text');
namespacePath = $dropdown.data('namespacePath');
projectPath = $dropdown.data('projectPath');
- labelUrl = $dropdown.data('labels');
issueUpdateURL = $dropdown.data('issueUpdate');
selectedLabel = $dropdown.data('selected');
- if ((selectedLabel != null) && !$dropdown.hasClass('js-multiselect')) {
+ if (selectedLabel != null && !$dropdown.hasClass('js-multiselect')) {
selectedLabel = selectedLabel.split(',');
}
showNo = $dropdown.data('showNo');
@@ -49,26 +77,37 @@ export default class LabelsSelect {
$value = $block.find('.value');
$loading = $block.find('.block-loading').fadeOut();
fieldName = $dropdown.data('fieldName');
- useId = $dropdown.is('.js-issuable-form-dropdown, .js-filter-bulk-update, .js-label-sidebar-dropdown');
+ useId = $dropdown.is(
+ '.js-issuable-form-dropdown, .js-filter-bulk-update, .js-label-sidebar-dropdown',
+ );
propertyName = useId ? 'id' : 'title';
initialSelected = $selectbox
.find('input[name="' + $dropdown.data('fieldName') + '"]')
- .map(function () {
+ .map(function() {
return this.value;
- }).get();
+ })
+ .get();
const { handleClick } = options;
$sidebarLabelTooltip.tooltip();
if ($dropdown.closest('.dropdown').find('.dropdown-new-label').length) {
- new CreateLabelDropdown($dropdown.closest('.dropdown').find('.dropdown-new-label'), namespacePath, projectPath);
+ new CreateLabelDropdown(
+ $dropdown.closest('.dropdown').find('.dropdown-new-label'),
+ namespacePath,
+ projectPath,
+ );
}
saveLabelData = function() {
var data, selected;
- selected = $dropdown.closest('.selectbox').find("input[name='" + fieldName + "']").map(function() {
- return this.value;
- }).get();
+ selected = $dropdown
+ .closest('.selectbox')
+ .find("input[name='" + fieldName + "']")
+ .map(function() {
+ return this.value;
+ })
+ .get();
if (_.isEqual(initialSelected, selected)) return;
initialSelected = selected;
@@ -81,7 +120,8 @@ export default class LabelsSelect {
}
$loading.removeClass('hidden').fadeIn();
$dropdown.trigger('loading.gl.dropdown');
- axios.put(issueUpdateURL, data)
+ axios
+ .put(issueUpdateURL, data)
.then(({ data }) => {
var labelCount, template, labelTooltipTitle, labelTitles, formattedLabels;
$loading.fadeOut();
@@ -95,8 +135,7 @@ export default class LabelsSelect {
issueUpdateURL,
});
labelCount = data.labels.length;
- }
- else {
+ } else {
template = '<span class="no-value">None</span>';
}
$value.removeAttr('style').html(template);
@@ -113,17 +152,14 @@ export default class LabelsSelect {
}
labelTooltipTitle = labelTitles.join(', ');
- }
- else {
+ } else {
labelTooltipTitle = __('Labels');
}
- $sidebarLabelTooltip
- .attr('title', labelTooltipTitle)
- .tooltip('_fixTitle');
+ $sidebarLabelTooltip.attr('title', labelTooltipTitle).tooltip('_fixTitle');
$('.has-tooltip', $value).tooltip({
- container: 'body'
+ container: 'body',
});
})
.catch(() => flash(__('Error saving label update.')));
@@ -131,34 +167,39 @@ export default class LabelsSelect {
$dropdown.glDropdown({
showMenuAbove: showMenuAbove,
data: function(term, callback) {
- axios.get(labelUrl)
- .then((res) => {
- let data = _.chain(res.data).groupBy(function(label) {
- return label.title;
- }).map(function(label) {
- var color;
- color = _.map(label, function(dup) {
- return dup.color;
- });
- return {
- id: label[0].id,
- title: label[0].title,
- color: color,
- duplicate: color.length > 1
- };
- }).value();
+ labelUrl = $dropdown.attr('data-labels');
+ axios
+ .get(labelUrl)
+ .then(res => {
+ let data = _.chain(res.data)
+ .groupBy(function(label) {
+ return label.title;
+ })
+ .map(function(label) {
+ var color;
+ color = _.map(label, function(dup) {
+ return dup.color;
+ });
+ return {
+ id: label[0].id,
+ title: label[0].title,
+ color: color,
+ duplicate: color.length > 1,
+ };
+ })
+ .value();
if ($dropdown.hasClass('js-extra-options')) {
var extraData = [];
if (showNo) {
extraData.unshift({
id: 0,
- title: 'No Label'
+ title: 'No Label',
});
}
if (showAny) {
extraData.unshift({
isAny: true,
- title: 'Any Label'
+ title: 'Any Label',
});
}
if (extraData.length) {
@@ -175,11 +216,22 @@ export default class LabelsSelect {
.catch(() => flash(__('Error fetching labels.')));
},
renderRow: function(label, instance) {
- var $a, $li, color, colorEl, indeterminate, removesAll, selectedClass, spacing, i, marked, dropdownName, dropdownValue;
+ var $a,
+ $li,
+ color,
+ colorEl,
+ indeterminate,
+ removesAll,
+ selectedClass,
+ spacing,
+ i,
+ marked,
+ dropdownName,
+ dropdownValue;
$li = $('<li>');
$a = $('<a href="#">');
selectedClass = [];
- removesAll = label.id <= 0 || (label.id == null);
+ removesAll = label.id <= 0 || label.id == null;
if ($dropdown.hasClass('js-filter-bulk-update')) {
indeterminate = $dropdown.data('indeterminate') || [];
marked = $dropdown.data('marked') || [];
@@ -199,9 +251,19 @@ export default class LabelsSelect {
} else {
if (this.id(label)) {
dropdownName = $dropdown.data('fieldName');
- dropdownValue = this.id(label).toString().replace(/'/g, '\\\'');
-
- if ($form.find("input[type='hidden'][name='" + dropdownName + "'][value='" + dropdownValue + "']").length) {
+ dropdownValue = this.id(label)
+ .toString()
+ .replace(/'/g, "\\'");
+
+ if (
+ $form.find(
+ "input[type='hidden'][name='" +
+ dropdownName +
+ "'][value='" +
+ dropdownValue +
+ "']",
+ ).length
+ ) {
selectedClass.push('is-active');
}
}
@@ -212,16 +274,14 @@ export default class LabelsSelect {
}
if (label.duplicate) {
color = DropdownUtils.duplicateLabelColor(label.color);
- }
- else {
+ } else {
if (label.color != null) {
[color] = label.color;
}
}
if (color) {
colorEl = "<span class='dropdown-label-box' style='background: " + color + "'></span>";
- }
- else {
+ } else {
colorEl = '';
}
// We need to identify which items are actually labels
@@ -234,7 +294,7 @@ export default class LabelsSelect {
return $li.html($a).prop('outerHTML');
},
search: {
- fields: ['title']
+ fields: ['title'],
},
selectable: true,
filterable: true,
@@ -254,25 +314,21 @@ export default class LabelsSelect {
if (selected && selected.id === 0) {
this.selected = [];
return 'No Label';
- }
- else if (isSelected) {
+ } else if (isSelected) {
this.selected.push(title);
- }
- else if (!isSelected && title) {
+ } else if (!isSelected && title) {
var index = this.selected.indexOf(title);
this.selected.splice(index, 1);
}
if (selectedLabels.length === 1) {
return selectedLabels;
- }
- else if (selectedLabels.length) {
+ } else if (selectedLabels.length) {
return sprintf(__('%{firstLabel} +%{labelCount} more'), {
firstLabel: selectedLabels[0],
- labelCount: selectedLabels.length - 1
+ labelCount: selectedLabels.length - 1,
});
- }
- else {
+ } else {
return defaultLabel;
}
},
@@ -284,10 +340,9 @@ export default class LabelsSelect {
return label.id;
}
- if ($dropdown.hasClass("js-filter-submit") && (label.isAny == null)) {
+ if ($dropdown.hasClass('js-filter-submit') && label.isAny == null) {
return label.title;
- }
- else {
+ } else {
return label.id;
}
},
@@ -309,13 +364,13 @@ export default class LabelsSelect {
}
if ($dropdown.hasClass('js-multiselect')) {
if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
- selectedLabels = $dropdown.closest('form').find("input:hidden[name='" + ($dropdown.data('fieldName')) + "']");
+ selectedLabels = $dropdown
+ .closest('form')
+ .find("input:hidden[name='" + $dropdown.data('fieldName') + "']");
Issuable.filterResults($dropdown.closest('form'));
- }
- else if ($dropdown.hasClass('js-filter-submit')) {
+ } else if ($dropdown.hasClass('js-filter-submit')) {
$dropdown.closest('form').submit();
- }
- else {
+ } else {
if (!$dropdown.hasClass('js-filter-bulk-update')) {
saveLabelData();
}
@@ -324,7 +379,7 @@ export default class LabelsSelect {
},
multiSelect: $dropdown.hasClass('js-multiselect'),
vue: $dropdown.hasClass('js-issue-board-sidebar'),
- clicked: function (clickEvent) {
+ clicked: function(clickEvent) {
const { $el, e, isMarking } = clickEvent;
const label = clickEvent.selectedObj;
@@ -338,7 +393,8 @@ export default class LabelsSelect {
isMRIndex = page === 'projects:merge_requests:index';
if ($dropdown.parent().find('.is-active:not(.dropdown-clear-active)').length) {
- $dropdown.parent()
+ $dropdown
+ .parent()
.find('.dropdown-clear-active')
.removeClass('is-active');
}
@@ -366,48 +422,43 @@ export default class LabelsSelect {
e.preventDefault();
return;
- }
- else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
+ } else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
if (!$dropdown.hasClass('js-multiselect')) {
selectedLabel = label.title;
return Issuable.filterResults($dropdown.closest('form'));
}
- }
- else if ($dropdown.hasClass('js-filter-submit')) {
+ } else if ($dropdown.hasClass('js-filter-submit')) {
return $dropdown.closest('form').submit();
- }
- else if ($dropdown.hasClass('js-issue-board-sidebar')) {
+ } else if ($dropdown.hasClass('js-issue-board-sidebar')) {
if ($el.hasClass('is-active')) {
- gl.issueBoards.BoardsStore.detail.issue.labels.push(new ListLabel({
- id: label.id,
- title: label.title,
- color: label.color[0],
- textColor: '#fff'
- }));
- }
- else {
- var { labels } = gl.issueBoards.BoardsStore.detail.issue;
- labels = labels.filter(function (selectedLabel) {
+ boardsStore.detail.issue.labels.push(
+ new ListLabel({
+ id: label.id,
+ title: label.title,
+ color: label.color[0],
+ textColor: '#fff',
+ }),
+ );
+ } else {
+ var { labels } = boardsStore.detail.issue;
+ labels = labels.filter(function(selectedLabel) {
return selectedLabel.id !== label.id;
});
- gl.issueBoards.BoardsStore.detail.issue.labels = labels;
+ boardsStore.detail.issue.labels = labels;
}
$loading.fadeIn();
- gl.issueBoards.BoardsStore.detail.issue.update($dropdown.attr('data-issue-update'))
+ boardsStore.detail.issue
+ .update($dropdown.attr('data-issue-update'))
.then(fadeOutLoader)
.catch(fadeOutLoader);
- }
- else if (handleClick) {
+ } else if (handleClick) {
e.preventDefault();
handleClick(label);
- }
- else {
+ } else {
if ($dropdown.hasClass('js-multiselect')) {
-
- }
- else {
+ } else {
return saveLabelData();
}
}
@@ -435,15 +486,17 @@ export default class LabelsSelect {
// so best approach is to use traditional way of
// concatenation
// see: http://2ality.com/2016/05/template-literal-whitespace.html#joining-arrays
- const tpl = _.template([
- '<% _.each(labels, function(label){ %>',
- '<a href="<%- issueUpdateURL.slice(0, issueUpdateURL.lastIndexOf("/")) %>?label_name[]=<%- encodeURIComponent(label.title) %>">',
- '<span class="badge label has-tooltip color-label" title="<%- label.description %>" style="background-color: <%- label.color %>; color: <%- label.text_color %>;">',
- '<%- label.title %>',
- '</span>',
- '</a>',
- '<% }); %>',
- ].join(''));
+ const tpl = _.template(
+ [
+ '<% _.each(labels, function(label){ %>',
+ '<a href="<%- issueUpdateURL.slice(0, issueUpdateURL.lastIndexOf("/")) %>?label_name[]=<%- encodeURIComponent(label.title) %>">',
+ '<span class="badge label has-tooltip color-label" title="<%- label.description %>" style="background-color: <%- label.color %>; color: <%- label.text_color %>;">',
+ '<%- label.title %>',
+ '</span>',
+ '</a>',
+ '<% }); %>',
+ ].join(''),
+ );
return tpl(tplData);
}
diff --git a/app/assets/javascripts/landing.js b/app/assets/javascripts/landing.js
index 8c0950ad5d5..bfb4d9ce67b 100644
--- a/app/assets/javascripts/landing.js
+++ b/app/assets/javascripts/landing.js
@@ -1,4 +1,5 @@
import Cookies from 'js-cookie';
+import { parseBoolean } from '~/lib/utils/common_utils';
class Landing {
constructor(landingElement, dismissButton, cookieName) {
@@ -30,7 +31,7 @@ class Landing {
}
isDismissed() {
- return Cookies.get(this.cookieName) === 'true';
+ return parseBoolean(Cookies.get(this.cookieName));
}
}
diff --git a/app/assets/javascripts/layout_nav.js b/app/assets/javascripts/layout_nav.js
index e3177188772..b8c3c237eb3 100644
--- a/app/assets/javascripts/layout_nav.js
+++ b/app/assets/javascripts/layout_nav.js
@@ -5,7 +5,9 @@ import initFlyOutNav from './fly_out_nav';
function hideEndFade($scrollingTabs) {
$scrollingTabs.each(function scrollTabsLoop() {
const $this = $(this);
- $this.siblings('.fade-right').toggleClass('scrolling', Math.round($this.width()) < $this.prop('scrollWidth'));
+ $this
+ .siblings('.fade-right')
+ .toggleClass('scrolling', Math.round($this.width()) < $this.prop('scrollWidth'));
});
}
@@ -15,38 +17,42 @@ export default function initLayoutNav() {
initFlyOutNav();
- $(document).on('init.scrolling-tabs', () => {
- const $scrollingTabs = $('.scrolling-tabs').not('.is-initialized');
- $scrollingTabs.addClass('is-initialized');
+ $(document)
+ .on('init.scrolling-tabs', () => {
+ const $scrollingTabs = $('.scrolling-tabs').not('.is-initialized');
+ $scrollingTabs.addClass('is-initialized');
- $(window).on('resize.nav', () => {
- hideEndFade($scrollingTabs);
- }).trigger('resize.nav');
+ $(window)
+ .on('resize.nav', () => {
+ hideEndFade($scrollingTabs);
+ })
+ .trigger('resize.nav');
- $scrollingTabs.on('scroll', function tabsScrollEvent() {
- const $this = $(this);
- const currentPosition = $this.scrollLeft();
- const maxPosition = $this.prop('scrollWidth') - $this.outerWidth();
+ $scrollingTabs.on('scroll', function tabsScrollEvent() {
+ const $this = $(this);
+ const currentPosition = $this.scrollLeft();
+ const maxPosition = $this.prop('scrollWidth') - $this.outerWidth();
- $this.siblings('.fade-left').toggleClass('scrolling', currentPosition > 0);
- $this.siblings('.fade-right').toggleClass('scrolling', currentPosition < maxPosition - 1);
- });
+ $this.siblings('.fade-left').toggleClass('scrolling', currentPosition > 0);
+ $this.siblings('.fade-right').toggleClass('scrolling', currentPosition < maxPosition - 1);
+ });
- $scrollingTabs.each(function scrollTabsEachLoop() {
- const $this = $(this);
- const scrollingTabWidth = $this.width();
- const $active = $this.find('.active');
- const activeWidth = $active.width();
+ $scrollingTabs.each(function scrollTabsEachLoop() {
+ const $this = $(this);
+ const scrollingTabWidth = $this.width();
+ const $active = $this.find('.active');
+ const activeWidth = $active.width();
- if ($active.length) {
- const offset = $active.offset().left + activeWidth;
+ if ($active.length) {
+ const offset = $active.offset().left + activeWidth;
- if (offset > scrollingTabWidth - 30) {
- const scrollLeft = (offset - (scrollingTabWidth / 2)) - (activeWidth / 2);
+ if (offset > scrollingTabWidth - 30) {
+ const scrollLeft = offset - scrollingTabWidth / 2 - activeWidth / 2;
- $this.scrollLeft(scrollLeft);
+ $this.scrollLeft(scrollLeft);
+ }
}
- }
- });
- }).trigger('init.scrolling-tabs');
+ });
+ })
+ .trigger('init.scrolling-tabs');
}
diff --git a/app/assets/javascripts/lazy_loader.js b/app/assets/javascripts/lazy_loader.js
index bd2212edec7..ee01a73a6e8 100644
--- a/app/assets/javascripts/lazy_loader.js
+++ b/app/assets/javascripts/lazy_loader.js
@@ -2,54 +2,116 @@ import _ from 'underscore';
export const placeholderImage =
'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
-const SCROLL_THRESHOLD = 300;
+const SCROLL_THRESHOLD = 500;
export default class LazyLoader {
constructor(options = {}) {
+ this.intersectionObserver = null;
this.lazyImages = [];
this.observerNode = options.observerNode || '#content-body';
- const throttledScrollCheck = _.throttle(() => this.scrollCheck(), 300);
- const debouncedElementsInView = _.debounce(() => this.checkElementsInView(), 300);
-
- window.addEventListener('scroll', throttledScrollCheck);
- window.addEventListener('resize', debouncedElementsInView);
-
const scrollContainer = options.scrollContainer || window;
- scrollContainer.addEventListener('load', () => this.loadCheck());
+ scrollContainer.addEventListener('load', () => this.register());
+ }
+
+ static supportsIntersectionObserver() {
+ return 'IntersectionObserver' in window;
}
+
searchLazyImages() {
- const that = this;
- requestIdleCallback(
+ window.requestIdleCallback(
() => {
- that.lazyImages = [].slice.call(document.querySelectorAll('.lazy'));
+ const lazyImages = [].slice.call(document.querySelectorAll('.lazy'));
- if (that.lazyImages.length) {
- that.checkElementsInView();
+ if (LazyLoader.supportsIntersectionObserver()) {
+ if (this.intersectionObserver) {
+ lazyImages.forEach(img => this.intersectionObserver.observe(img));
+ }
+ } else if (lazyImages.length) {
+ this.lazyImages = lazyImages;
+ this.checkElementsInView();
}
},
{ timeout: 500 },
);
}
+
startContentObserver() {
const contentNode = document.querySelector(this.observerNode) || document.querySelector('body');
-
if (contentNode) {
- const observer = new MutationObserver(() => this.searchLazyImages());
+ this.mutationObserver = new MutationObserver(() => this.searchLazyImages());
- observer.observe(contentNode, {
+ this.mutationObserver.observe(contentNode, {
childList: true,
subtree: true,
});
}
}
- loadCheck() {
- this.searchLazyImages();
+
+ stopContentObserver() {
+ if (this.mutationObserver) {
+ this.mutationObserver.takeRecords();
+ this.mutationObserver.disconnect();
+ this.mutationObserver = null;
+ }
+ }
+
+ unregister() {
+ this.stopContentObserver();
+ if (this.intersectionObserver) {
+ this.intersectionObserver.takeRecords();
+ this.intersectionObserver.disconnect();
+ this.intersectionObserver = null;
+ }
+ if (this.throttledScrollCheck) {
+ window.removeEventListener('scroll', this.throttledScrollCheck);
+ }
+ if (this.debouncedElementsInView) {
+ window.removeEventListener('resize', this.debouncedElementsInView);
+ }
+ }
+
+ register() {
+ if (LazyLoader.supportsIntersectionObserver()) {
+ this.startIntersectionObserver();
+ } else {
+ this.startLegacyObserver();
+ }
this.startContentObserver();
+ this.searchLazyImages();
}
+
+ startIntersectionObserver = () => {
+ this.throttledElementsInView = _.throttle(() => this.checkElementsInView(), 300);
+ this.intersectionObserver = new IntersectionObserver(this.onIntersection, {
+ rootMargin: `${SCROLL_THRESHOLD}px 0px`,
+ thresholds: 0.1,
+ });
+ };
+
+ onIntersection = entries => {
+ entries.forEach(entry => {
+ // We are using `intersectionRatio > 0` over `isIntersecting`, as some browsers did not ship the latter
+ // See: https://gitlab.com/gitlab-org/gitlab-ce/issues/54407
+ if (entry.intersectionRatio > 0) {
+ this.intersectionObserver.unobserve(entry.target);
+ this.lazyImages.push(entry.target);
+ }
+ });
+ this.throttledElementsInView();
+ };
+
+ startLegacyObserver() {
+ this.throttledScrollCheck = _.throttle(() => this.scrollCheck(), 300);
+ this.debouncedElementsInView = _.debounce(() => this.checkElementsInView(), 300);
+ window.addEventListener('scroll', this.throttledScrollCheck);
+ window.addEventListener('resize', this.debouncedElementsInView);
+ }
+
scrollCheck() {
- requestAnimationFrame(() => this.checkElementsInView());
+ window.requestAnimationFrame(() => this.checkElementsInView());
}
+
checkElementsInView() {
const scrollTop = window.pageYOffset;
const visHeight = scrollTop + window.innerHeight + SCROLL_THRESHOLD;
@@ -61,18 +123,29 @@ export default class LazyLoader {
const imgTop = scrollTop + imgBoundRect.top;
const imgBound = imgTop + imgBoundRect.height;
- if (scrollTop < imgBound && visHeight > imgTop) {
- requestAnimationFrame(() => {
+ if (scrollTop <= imgBound && visHeight >= imgTop) {
+ window.requestAnimationFrame(() => {
LazyLoader.loadImage(selectedImage);
});
return false;
}
+ /*
+ If we are scrolling fast, the img we watched intersecting could have left the view port.
+ So we are going watch for new intersections.
+ */
+ if (LazyLoader.supportsIntersectionObserver()) {
+ if (this.intersectionObserver) {
+ this.intersectionObserver.observe(selectedImage);
+ }
+ return false;
+ }
return true;
}
return false;
});
}
+
static loadImage(img) {
if (img.getAttribute('data-src')) {
let imgUrl = img.getAttribute('data-src');
diff --git a/app/assets/javascripts/lib/ace.js b/app/assets/javascripts/lib/ace.js
index 9cdc0309503..e90b3d2eec7 100644
--- a/app/assets/javascripts/lib/ace.js
+++ b/app/assets/javascripts/lib/ace.js
@@ -1,3 +1,4 @@
/*= require ace/ace */
+/*= require ace/ext-modelist */
/*= require ace/ext-searchbox */
/*= require ./ace/ace_config_paths */
diff --git a/app/assets/javascripts/lib/graphql.js b/app/assets/javascripts/lib/graphql.js
new file mode 100644
index 00000000000..20a0f142d9e
--- /dev/null
+++ b/app/assets/javascripts/lib/graphql.js
@@ -0,0 +1,9 @@
+import ApolloClient from 'apollo-boost';
+import csrf from '~/lib/utils/csrf';
+
+export default new ApolloClient({
+ uri: `${gon.relative_url_root}/api/graphql`,
+ headers: {
+ [csrf.headerKey]: csrf.token,
+ },
+});
diff --git a/app/assets/javascripts/lib/utils/ace_utils.js b/app/assets/javascripts/lib/utils/ace_utils.js
new file mode 100644
index 00000000000..ee71ae0e61a
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/ace_utils.js
@@ -0,0 +1,6 @@
+/* global ace */
+
+export default function getModeByFileExtension(path) {
+ const modelist = ace.require('ace/ext/modelist');
+ return modelist.getModeForPath(path).mode;
+}
diff --git a/app/assets/javascripts/lib/utils/ajax_cache.js b/app/assets/javascripts/lib/utils/ajax_cache.js
index 616d8952ada..2d976dbdbbe 100644
--- a/app/assets/javascripts/lib/utils/ajax_cache.js
+++ b/app/assets/javascripts/lib/utils/ajax_cache.js
@@ -4,7 +4,7 @@ import Cache from './cache';
class AjaxCache extends Cache {
constructor() {
super();
- this.pendingRequests = { };
+ this.pendingRequests = {};
}
override(endpoint, data) {
@@ -19,12 +19,13 @@ class AjaxCache extends Cache {
let pendingRequest = this.pendingRequests[endpoint];
if (!pendingRequest) {
- pendingRequest = axios.get(endpoint)
+ pendingRequest = axios
+ .get(endpoint)
.then(({ data }) => {
this.internalStorage[endpoint] = data;
delete this.pendingRequests[endpoint];
})
- .catch((e) => {
+ .catch(e => {
const error = new Error(`${endpoint}: ${e.message}`);
error.textStatus = e.message;
diff --git a/app/assets/javascripts/lib/utils/axios_utils.js b/app/assets/javascripts/lib/utils/axios_utils.js
index 792871e2ecf..69159e2d741 100644
--- a/app/assets/javascripts/lib/utils/axios_utils.js
+++ b/app/assets/javascripts/lib/utils/axios_utils.js
@@ -7,7 +7,7 @@ axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
// Maintain a global counter for active requests
// see: spec/support/wait_for_requests.rb
-axios.interceptors.request.use((config) => {
+axios.interceptors.request.use(config => {
window.activeVueResources = window.activeVueResources || 0;
window.activeVueResources += 1;
@@ -15,15 +15,18 @@ axios.interceptors.request.use((config) => {
});
// Remove the global counter
-axios.interceptors.response.use((config) => {
- window.activeVueResources -= 1;
-
- return config;
-}, (e) => {
- window.activeVueResources -= 1;
-
- return Promise.reject(e);
-});
+axios.interceptors.response.use(
+ config => {
+ window.activeVueResources -= 1;
+
+ return config;
+ },
+ e => {
+ window.activeVueResources -= 1;
+
+ return Promise.reject(e);
+ },
+);
export default axios;
diff --git a/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js b/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
index c28ed04f94f..a24c71aeab1 100644
--- a/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
+++ b/app/assets/javascripts/lib/utils/bootstrap_linked_tabs.js
@@ -93,9 +93,13 @@ export default class LinkedTabs {
const newState = `${copySource}${this.currentLocation.search}${this.currentLocation.hash}`;
- window.history.replaceState({
- url: newState,
- }, document.title, newState);
+ window.history.replaceState(
+ {
+ url: newState,
+ },
+ document.title,
+ newState,
+ );
return newState;
}
diff --git a/app/assets/javascripts/lib/utils/cache.js b/app/assets/javascripts/lib/utils/cache.js
index 596bd1e388a..45048145139 100644
--- a/app/assets/javascripts/lib/utils/cache.js
+++ b/app/assets/javascripts/lib/utils/cache.js
@@ -1,6 +1,6 @@
export default class Cache {
constructor() {
- this.internalStorage = { };
+ this.internalStorage = {};
}
get(key) {
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index 30925940807..040d0bc659e 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -88,6 +88,7 @@ export const handleLocationHash = () => {
const fixedDiffStats = document.querySelector('.js-diff-files-changed');
const fixedNav = document.querySelector('.navbar-gitlab');
const performanceBar = document.querySelector('#js-peek');
+ const topPadding = 8;
let adjustment = 0;
if (fixedNav) adjustment -= fixedNav.offsetHeight;
@@ -108,6 +109,10 @@ export const handleLocationHash = () => {
adjustment -= performanceBar.offsetHeight;
}
+ if (isInMRPage()) {
+ adjustment -= topPadding;
+ }
+
window.scrollBy(0, adjustment);
};
@@ -221,7 +226,17 @@ export const getParameterByName = (name, urlToParse) => {
return decodeURIComponent(results[2].replace(/\+/g, ' '));
};
-const handleSelectedRange = range => {
+const handleSelectedRange = (range, restrictToNode) => {
+ // Make sure this range is within the restricting container
+ if (restrictToNode && !range.intersectsNode(restrictToNode)) return null;
+
+ // If only a part of the range is within the wanted container, we need to restrict the range to it
+ if (restrictToNode && !restrictToNode.contains(range.commonAncestorContainer)) {
+ if (!restrictToNode.contains(range.startContainer)) range.setStart(restrictToNode, 0);
+ if (!restrictToNode.contains(range.endContainer))
+ range.setEnd(restrictToNode, restrictToNode.childNodes.length);
+ }
+
const container = range.commonAncestorContainer;
// add context to fragment if needed
if (container.tagName === 'OL') {
@@ -232,14 +247,22 @@ const handleSelectedRange = range => {
return range.cloneContents();
};
-export const getSelectedFragment = () => {
+export const getSelectedFragment = restrictToNode => {
const selection = window.getSelection();
if (selection.rangeCount === 0) return null;
+ // Most usages of the selection only want text from a part of the page (e.g. discussion)
+ if (restrictToNode && !selection.containsNode(restrictToNode, true)) return null;
+
const documentFragment = document.createDocumentFragment();
+ documentFragment.originalNodes = [];
for (let i = 0; i < selection.rangeCount; i += 1) {
const range = selection.getRangeAt(i);
- documentFragment.appendChild(handleSelectedRange(range));
+ const handledRange = handleSelectedRange(range, restrictToNode);
+ if (handledRange) {
+ documentFragment.appendChild(handledRange);
+ documentFragment.originalNodes.push(range.commonAncestorContainer);
+ }
}
if (documentFragment.textContent.length === 0) return null;
@@ -381,8 +404,11 @@ export const objectToQueryString = (params = {}) =>
.map(param => `${param}=${params[param]}`)
.join('&');
-export const buildUrlWithCurrentLocation = param =>
- (param ? `${window.location.pathname}${param}` : window.location.pathname);
+export const buildUrlWithCurrentLocation = param => {
+ if (param) return `${window.location.pathname}${param}`;
+
+ return window.location.pathname;
+};
/**
* Based on the current location and the string parameters provided
@@ -395,12 +421,28 @@ export const historyPushState = newUrl => {
};
/**
+ * Returns true for a String "true" and false otherwise.
+ * This is the opposite of Boolean(...).toString()
+ *
+ * @param {String} value
+ * @returns {Boolean}
+ */
+export const parseBoolean = value => value === 'true';
+
+/**
* Converts permission provided as strings to booleans.
*
* @param {String} string
* @returns {Boolean}
*/
-export const convertPermissionToBoolean = permission => permission === 'true';
+export const convertPermissionToBoolean = permission => {
+ if (process.env.NODE_ENV !== 'production') {
+ // eslint-disable-next-line no-console
+ console.warn('convertPermissionToBoolean is deprecated! Please use parseBoolean instead.');
+ }
+
+ return parseBoolean(permission);
+};
/**
* Back Off exponential algorithm
@@ -616,6 +658,17 @@ export const roundOffFloat = (number, precision = 0) => {
return Math.round(number * multiplier) / multiplier;
};
+/**
+ * Represents navigation type constants of the Performance Navigation API.
+ * Detailed explanation see https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigation.
+ */
+export const NavigationType = {
+ TYPE_NAVIGATE: 0,
+ TYPE_RELOAD: 1,
+ TYPE_BACK_FORWARD: 2,
+ TYPE_RESERVED: 255,
+};
+
window.gl = window.gl || {};
window.gl.utils = {
...(window.gl.utils || {}),
diff --git a/app/assets/javascripts/lib/utils/datefix.js b/app/assets/javascripts/lib/utils/datefix.js
deleted file mode 100644
index e98c9068367..00000000000
--- a/app/assets/javascripts/lib/utils/datefix.js
+++ /dev/null
@@ -1,29 +0,0 @@
-
-export const pad = (val, len = 2) => (`0${val}`).slice(-len);
-
-/**
- * Formats dates in Pickaday
- * @param {String} dateString Date in yyyy-mm-dd format
- * @return {Date} UTC format
- */
-export const parsePikadayDate = (dateString) => {
- const parts = dateString.split('-');
- const year = parseInt(parts[0], 10);
- const month = parseInt(parts[1] - 1, 10);
- const day = parseInt(parts[2], 10);
-
- return new Date(year, month, day);
-};
-
-/**
- * Used `onSelect` method in pickaday
- * @param {Date} date UTC format
- * @return {String} Date formated in yyyy-mm-dd
- */
-export const pikadayToString = (date) => {
- const day = pad(date.getDate());
- const month = pad(date.getMonth() + 1);
- const year = date.getFullYear();
-
- return `${year}-${month}-${day}`;
-};
diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js
index 1f66fa811ea..59007d5950e 100644
--- a/app/assets/javascripts/lib/utils/datetime_utility.js
+++ b/app/assets/javascripts/lib/utils/datetime_utility.js
@@ -1,4 +1,5 @@
import $ from 'jquery';
+import _ from 'underscore';
import timeago from 'timeago.js';
import dateFormat from 'dateformat';
import { pluralize } from './text_utility';
@@ -13,7 +14,7 @@ window.timeago = timeago;
*
* @param {Boolean} abbreviated
*/
-const getMonthNames = abbreviated => {
+export const getMonthNames = abbreviated => {
if (abbreviated) {
return [
s__('Jan'),
@@ -46,6 +47,8 @@ const getMonthNames = abbreviated => {
];
};
+export const pad = (val, len = 2) => `0${val}`.slice(-len);
+
/**
* Given a date object returns the day of the week in English
* @param {date} date
@@ -74,10 +77,10 @@ let timeagoInstance;
/**
* Sets a timeago Instance
*/
-export function getTimeago() {
+export const getTimeago = () => {
if (!timeagoInstance) {
- const localeRemaining = function getLocaleRemaining(number, index) {
- return [
+ const localeRemaining = (number, index) =>
+ [
[s__('Timeago|just now'), s__('Timeago|right now')],
[s__('Timeago|%s seconds ago'), s__('Timeago|%s seconds remaining')],
[s__('Timeago|1 minute ago'), s__('Timeago|1 minute remaining')],
@@ -93,9 +96,9 @@ export function getTimeago() {
[s__('Timeago|1 year ago'), s__('Timeago|1 year remaining')],
[s__('Timeago|%s years ago'), s__('Timeago|%s years remaining')],
][index];
- };
- const locale = function getLocale(number, index) {
- return [
+
+ const locale = (number, index) =>
+ [
[s__('Timeago|just now'), s__('Timeago|right now')],
[s__('Timeago|%s seconds ago'), s__('Timeago|in %s seconds')],
[s__('Timeago|1 minute ago'), s__('Timeago|in 1 minute')],
@@ -111,7 +114,6 @@ export function getTimeago() {
[s__('Timeago|1 year ago'), s__('Timeago|in 1 year')],
[s__('Timeago|%s years ago'), s__('Timeago|in %s years')],
][index];
- };
timeago.register(timeagoLanguageCode, locale);
timeago.register(`${timeagoLanguageCode}-remaining`, localeRemaining);
@@ -119,7 +121,7 @@ export function getTimeago() {
}
return timeagoInstance;
-}
+};
/**
* For the given element, renders a timeago instance.
@@ -184,7 +186,7 @@ export const getDayDifference = (a, b) => {
* @param {Number} seconds
* @return {String}
*/
-export function timeIntervalInWords(intervalInSeconds) {
+export const timeIntervalInWords = intervalInSeconds => {
const secondsInteger = parseInt(intervalInSeconds, 10);
const minutes = Math.floor(secondsInteger / 60);
const seconds = secondsInteger - minutes * 60;
@@ -196,9 +198,9 @@ export function timeIntervalInWords(intervalInSeconds) {
text = `${seconds} ${pluralize('second', seconds)}`;
}
return text;
-}
+};
-export function dateInWords(date, abbreviated = false, hideYear = false) {
+export const dateInWords = (date, abbreviated = false, hideYear = false) => {
if (!date) return date;
const month = date.getMonth();
@@ -240,7 +242,7 @@ export function dateInWords(date, abbreviated = false, hideYear = false) {
}
return `${monthName} ${date.getDate()}, ${year}`;
-}
+};
/**
* Returns month name based on provided date.
@@ -370,3 +372,124 @@ window.gl.utils = {
getTimeago,
localTimeAgo,
};
+
+/**
+ * Formats milliseconds as timestamp (e.g. 01:02:03).
+ * This takes durations longer than a day into account (e.g. two days would be 48:00:00).
+ *
+ * @param milliseconds
+ * @returns {string}
+ */
+export const formatTime = milliseconds => {
+ const remainingSeconds = Math.floor(milliseconds / 1000) % 60;
+ const remainingMinutes = Math.floor(milliseconds / 1000 / 60) % 60;
+ const remainingHours = Math.floor(milliseconds / 1000 / 60 / 60);
+ let formattedTime = '';
+ if (remainingHours < 10) formattedTime += '0';
+ formattedTime += `${remainingHours}:`;
+ if (remainingMinutes < 10) formattedTime += '0';
+ formattedTime += `${remainingMinutes}:`;
+ if (remainingSeconds < 10) formattedTime += '0';
+ formattedTime += remainingSeconds;
+ return formattedTime;
+};
+
+/**
+ * Formats dates in Pickaday
+ * @param {String} dateString Date in yyyy-mm-dd format
+ * @return {Date} UTC format
+ */
+export const parsePikadayDate = dateString => {
+ const parts = dateString.split('-');
+ const year = parseInt(parts[0], 10);
+ const month = parseInt(parts[1] - 1, 10);
+ const day = parseInt(parts[2], 10);
+
+ return new Date(year, month, day);
+};
+
+/**
+ * Used `onSelect` method in pickaday
+ * @param {Date} date UTC format
+ * @return {String} Date formated in yyyy-mm-dd
+ */
+export const pikadayToString = date => {
+ const day = pad(date.getDate());
+ const month = pad(date.getMonth() + 1);
+ const year = date.getFullYear();
+
+ return `${year}-${month}-${day}`;
+};
+
+/**
+ * Accepts seconds and returns a timeObject { weeks: #, days: #, hours: #, minutes: # }
+ * Seconds can be negative or positive, zero or non-zero. Can be configured for any day
+ * or week length.
+ */
+export const parseSeconds = (seconds, { daysPerWeek = 5, hoursPerDay = 8 } = {}) => {
+ const DAYS_PER_WEEK = daysPerWeek;
+ const HOURS_PER_DAY = hoursPerDay;
+ const MINUTES_PER_HOUR = 60;
+ const MINUTES_PER_WEEK = DAYS_PER_WEEK * HOURS_PER_DAY * MINUTES_PER_HOUR;
+ const MINUTES_PER_DAY = HOURS_PER_DAY * MINUTES_PER_HOUR;
+
+ const timePeriodConstraints = {
+ weeks: MINUTES_PER_WEEK,
+ days: MINUTES_PER_DAY,
+ hours: MINUTES_PER_HOUR,
+ minutes: 1,
+ };
+
+ let unorderedMinutes = Math.abs(seconds / MINUTES_PER_HOUR);
+
+ return _.mapObject(timePeriodConstraints, minutesPerPeriod => {
+ const periodCount = Math.floor(unorderedMinutes / minutesPerPeriod);
+
+ unorderedMinutes -= periodCount * minutesPerPeriod;
+
+ return periodCount;
+ });
+};
+
+/**
+ * Accepts a timeObject (see parseSeconds) and returns a condensed string representation of it
+ * (e.g. '1w 2d 3h 1m' or '1h 30m'). Zero value units are not included.
+ * If the 'fullNameFormat' param is passed it returns a non condensed string eg '1 week 3 days'
+ */
+export const stringifyTime = (timeObject, fullNameFormat = false) => {
+ const reducedTime = _.reduce(
+ timeObject,
+ (memo, unitValue, unitName) => {
+ const isNonZero = !!unitValue;
+
+ if (fullNameFormat && isNonZero) {
+ // Remove traling 's' if unit value is singular
+ const formatedUnitName = unitValue > 1 ? unitName : unitName.replace(/s$/, '');
+ return `${memo} ${unitValue} ${formatedUnitName}`;
+ }
+
+ return isNonZero ? `${memo} ${unitValue}${unitName.charAt(0)}` : memo;
+ },
+ '',
+ ).trim();
+ return reducedTime.length ? reducedTime : '0m';
+};
+
+/**
+ * Accepts a time string of any size (e.g. '1w 2d 3h 5m' or '1w 2d') and returns
+ * the first non-zero unit/value pair.
+ */
+export const abbreviateTime = timeStr =>
+ timeStr.split(' ').filter(unitStr => unitStr.charAt(0) !== '0')[0];
+
+/**
+ * Calculates the milliseconds between now and a given date string.
+ * The result cannot become negative.
+ *
+ * @param endDate date string that the time difference is calculated for
+ * @return {number} number of milliseconds remaining until the given date
+ */
+export const calculateRemainingMilliseconds = endDate => {
+ const remainingMilliseconds = new Date(endDate).getTime() - Date.now();
+ return Math.max(remainingMilliseconds, 0);
+};
diff --git a/app/assets/javascripts/lib/utils/logoutput_behaviours.js b/app/assets/javascripts/lib/utils/logoutput_behaviours.js
index 1bf99d935ef..41b57025cc9 100644
--- a/app/assets/javascripts/lib/utils/logoutput_behaviours.js
+++ b/app/assets/javascripts/lib/utils/logoutput_behaviours.js
@@ -1,5 +1,11 @@
import $ from 'jquery';
-import { canScroll, isScrolledToBottom, toggleDisableButton } from './scroll_utils';
+import {
+ canScroll,
+ isScrolledToBottom,
+ isScrolledToTop,
+ isScrolledToMiddle,
+ toggleDisableButton,
+} from './scroll_utils';
export default class LogOutputBehaviours {
constructor() {
@@ -12,18 +18,13 @@ export default class LogOutputBehaviours {
}
toggleScroll() {
- const $document = $(document);
- const currentPosition = $document.scrollTop();
- const scrollHeight = $document.height();
-
- const windowHeight = $(window).height();
if (canScroll()) {
- if (currentPosition > 0 && scrollHeight - currentPosition !== windowHeight) {
+ if (isScrolledToMiddle()) {
// User is in the middle of the log
toggleDisableButton(this.$scrollTopBtn, false);
toggleDisableButton(this.$scrollBottomBtn, false);
- } else if (currentPosition === 0) {
+ } else if (isScrolledToTop()) {
// User is at Top of Log
toggleDisableButton(this.$scrollTopBtn, true);
diff --git a/app/assets/javascripts/lib/utils/notify.js b/app/assets/javascripts/lib/utils/notify.js
index 305ad3e5e26..d93873e0214 100644
--- a/app/assets/javascripts/lib/utils/notify.js
+++ b/app/assets/javascripts/lib/utils/notify.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, no-var, consistent-return, prefer-arrow-callback, no-return-assign, object-shorthand, comma-dangle, max-len */
+/* eslint-disable func-names, no-var, consistent-return, prefer-arrow-callback, no-return-assign, object-shorthand */
function notificationGranted(message, opts, onclick) {
var notification;
@@ -8,7 +8,7 @@ function notificationGranted(message, opts, onclick) {
return notification.close();
}, 8000);
- return notification.onclick = onclick || notification.close;
+ return (notification.onclick = onclick || notification.close);
}
function notifyPermissions() {
@@ -21,7 +21,7 @@ function notifyMe(message, body, icon, onclick) {
var opts;
opts = {
body: body,
- icon: icon
+ icon: icon,
};
// Let's check if the browser supports notifications
if (!('Notification' in window)) {
diff --git a/app/assets/javascripts/lib/utils/number_utils.js b/app/assets/javascripts/lib/utils/number_utils.js
index afbab59055b..2ccc51c35f7 100644
--- a/app/assets/javascripts/lib/utils/number_utils.js
+++ b/app/assets/javascripts/lib/utils/number_utils.js
@@ -7,7 +7,7 @@ import { BYTES_IN_KIB } from './constants';
* * * Show 3 digits to the right
* * For 2 digits to the left of the decimal point and X digits to the right of it
* * * Show 2 digits to the right
-*/
+ */
export function formatRelevantDigits(number) {
let digitsLeft = '';
let relevantDigits = 0;
diff --git a/app/assets/javascripts/lib/utils/pretty_time.js b/app/assets/javascripts/lib/utils/pretty_time.js
deleted file mode 100644
index b1ffd797f7e..00000000000
--- a/app/assets/javascripts/lib/utils/pretty_time.js
+++ /dev/null
@@ -1,61 +0,0 @@
-import _ from 'underscore';
-
-/*
- * TODO: Make these methods more configurable (e.g. stringifyTime condensed or
- * non-condensed, abbreviateTimelengths)
- * */
-
-/*
- * Accepts seconds and returns a timeObject { weeks: #, days: #, hours: #, minutes: # }
- * Seconds can be negative or positive, zero or non-zero. Can be configured for any day
- * or week length.
-*/
-
-export function parseSeconds(seconds, { daysPerWeek = 5, hoursPerDay = 8 } = {}) {
- const DAYS_PER_WEEK = daysPerWeek;
- const HOURS_PER_DAY = hoursPerDay;
- const MINUTES_PER_HOUR = 60;
- const MINUTES_PER_WEEK = DAYS_PER_WEEK * HOURS_PER_DAY * MINUTES_PER_HOUR;
- const MINUTES_PER_DAY = HOURS_PER_DAY * MINUTES_PER_HOUR;
-
- const timePeriodConstraints = {
- weeks: MINUTES_PER_WEEK,
- days: MINUTES_PER_DAY,
- hours: MINUTES_PER_HOUR,
- minutes: 1,
- };
-
- let unorderedMinutes = Math.abs(seconds / MINUTES_PER_HOUR);
-
- return _.mapObject(timePeriodConstraints, (minutesPerPeriod) => {
- const periodCount = Math.floor(unorderedMinutes / minutesPerPeriod);
-
- unorderedMinutes -= (periodCount * minutesPerPeriod);
-
- return periodCount;
- });
-}
-
-/*
-* Accepts a timeObject (see parseSeconds) and returns a condensed string representation of it
-* (e.g. '1w 2d 3h 1m' or '1h 30m'). Zero value units are not included.
-*/
-
-export function stringifyTime(timeObject) {
- const reducedTime = _.reduce(timeObject, (memo, unitValue, unitName) => {
- const isNonZero = !!unitValue;
- return isNonZero ? `${memo} ${unitValue}${unitName.charAt(0)}` : memo;
- }, '').trim();
- return reducedTime.length ? reducedTime : '0m';
-}
-
-/*
-* Accepts a time string of any size (e.g. '1w 2d 3h 5m' or '1w 2d') and returns
-* the first non-zero unit/value pair.
-*/
-
-export function abbreviateTime(timeStr) {
- return timeStr.split(' ')
- .filter(unitStr => unitStr.charAt(0) !== '0')[0];
-}
-
diff --git a/app/assets/javascripts/lib/utils/regexp.js b/app/assets/javascripts/lib/utils/regexp.js
index baa0b51d59b..25b60dcd14a 100644
--- a/app/assets/javascripts/lib/utils/regexp.js
+++ b/app/assets/javascripts/lib/utils/regexp.js
@@ -5,6 +5,7 @@
// Inspired by https://github.com/mishoo/UglifyJS/blob/2bc1d02363db3798d5df41fb5059a19edca9b7eb/lib/parse-js.js#L203
// Unicode 6.1
-const unicodeLetters = '\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0\\u08A2-\\u08AC\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F0\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA697\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA793\\uA7A0-\\uA7AA\\uA7F8-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA80-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC';
+const unicodeLetters =
+ '\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0\\u08A2-\\u08AC\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F0\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA697\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA793\\uA7A0-\\uA7AA\\uA7F8-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA80-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC';
export default { unicodeLetters };
diff --git a/app/assets/javascripts/lib/utils/scroll_utils.js b/app/assets/javascripts/lib/utils/scroll_utils.js
index 9313b570863..b4da1e16f08 100644
--- a/app/assets/javascripts/lib/utils/scroll_utils.js
+++ b/app/assets/javascripts/lib/utils/scroll_utils.js
@@ -4,6 +4,7 @@ export const canScroll = () => $(document).height() > $(window).height();
/**
* Checks if the entire page is scrolled down all the way to the bottom
+ * @returns {Boolean}
*/
export const isScrolledToBottom = () => {
const $document = $(document);
@@ -16,11 +17,34 @@ export const isScrolledToBottom = () => {
return scrollHeight - currentPosition === windowHeight;
};
+/**
+ * Checks if page is scrolled to the top
+ * @returns {Boolean}
+ */
+export const isScrolledToTop = () => $(document).scrollTop() === 0;
+
export const scrollDown = () => {
const $document = $(document);
$document.scrollTop($document.height());
};
+export const scrollUp = () => {
+ $(document).scrollTop(0);
+};
+
+/**
+ * Checks if scroll position is in the middle of the page
+ * @returns {Boolean}
+ */
+export const isScrolledToMiddle = () => {
+ const $document = $(document);
+ const currentPosition = $document.scrollTop();
+ const scrollHeight = $document.height();
+ const windowHeight = $(window).height();
+
+ return currentPosition > 0 && scrollHeight - currentPosition !== windowHeight;
+};
+
export const toggleDisableButton = ($button, disable) => {
if (disable && $button.prop('disabled')) return;
$button.prop('disabled', disable);
diff --git a/app/assets/javascripts/lib/utils/simple_poll.js b/app/assets/javascripts/lib/utils/simple_poll.js
index 25ca98afbe7..473f179ad86 100644
--- a/app/assets/javascripts/lib/utils/simple_poll.js
+++ b/app/assets/javascripts/lib/utils/simple_poll.js
@@ -2,7 +2,7 @@ export default (fn, interval = 2000, timeout = 60000) => {
const startTime = Date.now();
return new Promise((resolve, reject) => {
- const stop = arg => ((arg instanceof Error) ? reject(arg) : resolve(arg));
+ const stop = arg => (arg instanceof Error ? reject(arg) : resolve(arg));
const next = () => {
if (Date.now() - startTime < timeout) {
setTimeout(fn.bind(null, next, stop), interval);
diff --git a/app/assets/javascripts/lib/utils/sticky.js b/app/assets/javascripts/lib/utils/sticky.js
index 15a4dd62012..f3244301350 100644
--- a/app/assets/javascripts/lib/utils/sticky.js
+++ b/app/assets/javascripts/lib/utils/sticky.js
@@ -24,7 +24,11 @@ export const isSticky = (el, scrollY, stickyTop, insertPlaceholder) => {
} else if (top > stickyTop && el.classList.contains('is-stuck')) {
el.classList.remove('is-stuck');
- if (insertPlaceholder && el.nextElementSibling && el.nextElementSibling.classList.contains('sticky-placeholder')) {
+ if (
+ insertPlaceholder &&
+ el.nextElementSibling &&
+ el.nextElementSibling.classList.contains('sticky-placeholder')
+ ) {
el.nextElementSibling.remove();
}
}
@@ -42,11 +46,19 @@ export const isSticky = (el, scrollY, stickyTop, insertPlaceholder) => {
export const stickyMonitor = (el, stickyTop, insertPlaceholder = true) => {
if (!el) return;
- if (typeof CSS === 'undefined' || !(CSS.supports('(position: -webkit-sticky) or (position: sticky)'))) return;
+ if (
+ typeof CSS === 'undefined' ||
+ !CSS.supports('(position: -webkit-sticky) or (position: sticky)')
+ )
+ return;
- document.addEventListener('scroll', () => isSticky(el, window.scrollY, stickyTop, insertPlaceholder), {
- passive: true,
- });
+ document.addEventListener(
+ 'scroll',
+ () => isSticky(el, window.scrollY, stickyTop, insertPlaceholder),
+ {
+ passive: true,
+ },
+ );
};
/**
@@ -55,6 +67,6 @@ export const stickyMonitor = (el, stickyTop, insertPlaceholder = true) => {
* - If the current environment supports `position: sticky`, do nothing.
* - Can receive an iterable element list (NodeList, jQuery collection, etc.) or single HTMLElement.
*/
-export const polyfillSticky = (el) => {
+export const polyfillSticky = el => {
StickyFill.add(el);
};
diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js
index ce0bc4d40e9..3618c6af7e2 100644
--- a/app/assets/javascripts/lib/utils/text_markdown.js
+++ b/app/assets/javascripts/lib/utils/text_markdown.js
@@ -1,19 +1,27 @@
-/* eslint-disable func-names, no-var, no-param-reassign, quotes, one-var, one-var-declaration-per-line, operator-assignment, no-else-return, prefer-template, prefer-arrow-callback, max-len, consistent-return, no-unused-vars, max-len */
+/* eslint-disable func-names, no-var, no-param-reassign, one-var, operator-assignment, no-else-return, prefer-template, prefer-arrow-callback, consistent-return, no-unused-vars */
import $ from 'jquery';
import { insertText } from '~/lib/utils/common_utils';
+const LINK_TAG_PATTERN = '[{text}](url)';
+
function selectedText(text, textarea) {
return text.substring(textarea.selectionStart, textarea.selectionEnd);
}
function lineBefore(text, textarea) {
var split;
- split = text.substring(0, textarea.selectionStart).trim().split('\n');
+ split = text
+ .substring(0, textarea.selectionStart)
+ .trim()
+ .split('\n');
return split[split.length - 1];
}
function lineAfter(text, textarea) {
- return text.substring(textarea.selectionEnd).trim().split('\n')[0];
+ return text
+ .substring(textarea.selectionEnd)
+ .trim()
+ .split('\n')[0];
}
function blockTagText(text, textArea, blockTag, selected) {
@@ -27,17 +35,23 @@ function blockTagText(text, textArea, blockTag, selected) {
}
return selected;
} else {
- return blockTag + "\n" + selected + "\n" + blockTag;
+ return blockTag + '\n' + selected + '\n' + blockTag;
}
}
-function moveCursor(textArea, tag, wrapped, removedLastNewLine) {
+function moveCursor({ textArea, tag, positionBetweenTags, removedLastNewLine, select }) {
var pos;
if (!textArea.setSelectionRange) {
return;
}
+ if (select && select.length > 0) {
+ // calculate the part of the text to be selected
+ const startPosition = textArea.selectionStart - (tag.length - tag.indexOf(select));
+ const endPosition = startPosition + select.length;
+ return textArea.setSelectionRange(startPosition, endPosition);
+ }
if (textArea.selectionStart === textArea.selectionEnd) {
- if (wrapped) {
+ if (positionBetweenTags) {
pos = textArea.selectionStart - tag.length;
} else {
pos = textArea.selectionStart;
@@ -51,12 +65,33 @@ function moveCursor(textArea, tag, wrapped, removedLastNewLine) {
}
}
-export function insertMarkdownText(textArea, text, tag, blockTag, selected, wrap) {
- var textToInsert, inserted, selectedSplit, startChar, removedLastNewLine, removedFirstNewLine, currentLineEmpty, lastNewLine;
+export function insertMarkdownText({ textArea, text, tag, blockTag, selected, wrap, select }) {
+ var textToInsert,
+ selectedSplit,
+ startChar,
+ removedLastNewLine,
+ removedFirstNewLine,
+ currentLineEmpty,
+ lastNewLine;
removedLastNewLine = false;
removedFirstNewLine = false;
currentLineEmpty = false;
+ // check for link pattern and selected text is an URL
+ // if so fill in the url part instead of the text part of the pattern.
+ if (tag === LINK_TAG_PATTERN) {
+ if (URL) {
+ try {
+ const ignoredUrl = new URL(selected);
+ // valid url
+ tag = '[text]({text})';
+ select = 'text';
+ } catch (e) {
+ // ignore - no valid url
+ }
+ }
+ }
+
// Remove the first newline
if (selected.indexOf('\n') === 0) {
removedFirstNewLine = true;
@@ -82,20 +117,29 @@ export function insertMarkdownText(textArea, text, tag, blockTag, selected, wrap
startChar = !wrap && !currentLineEmpty && textArea.selectionStart > 0 ? '\n' : '';
+ const textPlaceholder = '{text}';
+
if (selectedSplit.length > 1 && (!wrap || (blockTag != null && blockTag !== ''))) {
if (blockTag != null && blockTag !== '') {
textToInsert = blockTagText(text, textArea, blockTag, selected);
} else {
- textToInsert = selectedSplit.map(function(val) {
- if (val.indexOf(tag) === 0) {
- return "" + (val.replace(tag, ''));
- } else {
- return "" + tag + val;
- }
- }).join('\n');
+ textToInsert = selectedSplit
+ .map(function(val) {
+ if (tag.indexOf(textPlaceholder) > -1) {
+ return tag.replace(textPlaceholder, val);
+ }
+ if (val.indexOf(tag) === 0) {
+ return '' + val.replace(tag, '');
+ } else {
+ return '' + tag + val;
+ }
+ })
+ .join('\n');
}
+ } else if (tag.indexOf(textPlaceholder) > -1) {
+ textToInsert = tag.replace(textPlaceholder, selected);
} else {
- textToInsert = "" + startChar + tag + selected + (wrap ? tag : ' ');
+ textToInsert = '' + startChar + tag + selected + (wrap ? tag : ' ');
}
if (removedFirstNewLine) {
@@ -107,28 +151,38 @@ export function insertMarkdownText(textArea, text, tag, blockTag, selected, wrap
}
insertText(textArea, textToInsert);
- return moveCursor(textArea, tag, wrap, removedLastNewLine);
+ return moveCursor({
+ textArea,
+ tag: tag.replace(textPlaceholder, selected),
+ positionBetweenTags: wrap && selected.length === 0,
+ removedLastNewLine,
+ select,
+ });
}
-function updateText(textArea, tag, blockTag, wrap) {
+function updateText({ textArea, tag, blockTag, wrap, select }) {
var $textArea, selected, text;
$textArea = $(textArea);
textArea = $textArea.get(0);
text = $textArea.val();
selected = selectedText(text, textArea);
$textArea.focus();
- return insertMarkdownText(textArea, text, tag, blockTag, selected, wrap);
-}
-
-function replaceRange(s, start, end, substitute) {
- return s.substring(0, start) + substitute + s.substring(end);
+ return insertMarkdownText({ textArea, text, tag, blockTag, selected, wrap, select });
}
export function addMarkdownListeners(form) {
- return $('.js-md', form).off('click').on('click', function() {
- const $this = $(this);
- return updateText($this.closest('.md-area').find('textarea'), $this.data('mdTag'), $this.data('mdBlock'), !$this.data('mdPrepend'));
- });
+ return $('.js-md', form)
+ .off('click')
+ .on('click', function() {
+ const $this = $(this);
+ return updateText({
+ textArea: $this.closest('.md-area').find('textarea'),
+ tag: $this.data('mdTag'),
+ blockTag: $this.data('mdBlock'),
+ wrap: !$this.data('mdPrepend'),
+ select: $this.data('mdSelect'),
+ });
+ });
}
export function removeMarkdownListeners(form) {
diff --git a/app/assets/javascripts/lib/utils/text_utility.js b/app/assets/javascripts/lib/utils/text_utility.js
index 879f94a26ec..7cc7cd6d20e 100644
--- a/app/assets/javascripts/lib/utils/text_utility.js
+++ b/app/assets/javascripts/lib/utils/text_utility.js
@@ -8,7 +8,7 @@
* @returns {String}
*/
export const addDelimiter = text =>
- (text ? text.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') : text);
+ text ? text.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') : text;
/**
* Returns '99+' for numbers bigger than 99.
@@ -53,10 +53,7 @@ export const slugify = str => str.trim().toLowerCase();
* @param {String} str
* @returns {String}
*/
-export const slugifyWithHyphens = str => {
- const regex = new RegExp(/\s+/, 'g');
- return str.toLowerCase().replace(regex, '-');
-};
+export const slugifyWithHyphens = str => str.toLowerCase().replace(/\s+/g, '-');
/**
* Truncates given text
@@ -94,9 +91,7 @@ export function capitalizeFirstCharacter(text) {
* @return {String}
*/
export function getFirstCharacterCapitalized(text) {
- return text
- ? text.charAt(0).toUpperCase()
- : '';
+ return text ? text.charAt(0).toUpperCase() : '';
}
/**
@@ -136,10 +131,9 @@ export const convertToSentenceCase = string => {
* e.g. HelloWorld => Hello World
*
* @param {*} string
-*/
-export const splitCamelCase = string => (
+ */
+export const splitCamelCase = string =>
string
- .replace(/([A-Z]+)([A-Z][a-z])/g, ' $1 $2')
- .replace(/([a-z\d])([A-Z])/g, '$1 $2')
- .trim()
-);
+ .replace(/([A-Z]+)([A-Z][a-z])/g, ' $1 $2')
+ .replace(/([a-z\d])([A-Z])/g, '$1 $2')
+ .trim();
diff --git a/app/assets/javascripts/lib/utils/tick_formats.js b/app/assets/javascripts/lib/utils/tick_formats.js
index 0c10a85e336..af3ca714400 100644
--- a/app/assets/javascripts/lib/utils/tick_formats.js
+++ b/app/assets/javascripts/lib/utils/tick_formats.js
@@ -26,7 +26,7 @@ initDateFormats();
see also https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Axes.md#tickFormat
*/
-export const dateTickFormat = (date) => {
+export const dateTickFormat = date => {
if (date.getDate() !== 1) {
return dateTimeFormats.dayFormat.format(date);
}
diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js
index a282c2df441..9850f7ce782 100644
--- a/app/assets/javascripts/lib/utils/url_utility.js
+++ b/app/assets/javascripts/lib/utils/url_utility.js
@@ -17,27 +17,29 @@ export function getParameterValues(sParam) {
// @param {Object} params - url keys and value to merge
// @param {String} url
export function mergeUrlParams(params, url) {
- let newUrl = Object.keys(params).reduce((acc, paramName) => {
- const paramValue = encodeURIComponent(params[paramName]);
- const pattern = new RegExp(`\\b(${paramName}=).*?(&|$)`);
-
- if (paramValue === null) {
- return acc.replace(pattern, '');
- } else if (url.search(pattern) !== -1) {
- return acc.replace(pattern, `$1${paramValue}$2`);
- }
-
- return `${acc}${acc.indexOf('?') > 0 ? '&' : '?'}${paramName}=${paramValue}`;
- }, decodeURIComponent(url));
+ const re = /^([^?#]*)(\?[^#]*)?(.*)/;
+ const merged = {};
+ const urlparts = url.match(re);
+
+ if (urlparts[2]) {
+ urlparts[2]
+ .substr(1)
+ .split('&')
+ .forEach(part => {
+ if (part.length) {
+ const kv = part.split('=');
+ merged[decodeURIComponent(kv[0])] = decodeURIComponent(kv.slice(1).join('='));
+ }
+ });
+ }
- // Remove a trailing ampersand
- const lastChar = newUrl[newUrl.length - 1];
+ Object.assign(merged, params);
- if (lastChar === '&') {
- newUrl = newUrl.slice(0, -1);
- }
+ const query = Object.keys(merged)
+ .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(merged[key])}`)
+ .join('&');
- return newUrl;
+ return `${urlparts[1]}?${query}${urlparts[3]}`;
}
export function removeParamQueryString(url, param) {
diff --git a/app/assets/javascripts/lib/utils/users_cache.js b/app/assets/javascripts/lib/utils/users_cache.js
index b01ec6b81a3..c0d45e017b4 100644
--- a/app/assets/javascripts/lib/utils/users_cache.js
+++ b/app/assets/javascripts/lib/utils/users_cache.js
@@ -7,21 +7,20 @@ class UsersCache extends Cache {
return Promise.resolve(this.get(username));
}
- return Api.users('', { username })
- .then(({ data }) => {
- if (!data.length) {
- throw new Error(`User "${username}" could not be found!`);
- }
+ return Api.users('', { username }).then(({ data }) => {
+ if (!data.length) {
+ throw new Error(`User "${username}" could not be found!`);
+ }
- if (data.length > 1) {
- throw new Error(`Expected username "${username}" to be unique!`);
- }
+ if (data.length > 1) {
+ throw new Error(`Expected username "${username}" to be unique!`);
+ }
- const user = data[0];
- this.internalStorage[username] = user;
- return user;
- });
- // missing catch is intentional, error handling depends on use case
+ const user = data[0];
+ this.internalStorage[username] = user;
+ return user;
+ });
+ // missing catch is intentional, error handling depends on use case
}
}
diff --git a/app/assets/javascripts/line_highlighter.js b/app/assets/javascripts/line_highlighter.js
index 291655235d5..4db63c841a9 100644
--- a/app/assets/javascripts/line_highlighter.js
+++ b/app/assets/javascripts/line_highlighter.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, no-var, no-underscore-dangle, no-param-reassign, prefer-template, quotes, comma-dangle, consistent-return, one-var, one-var-declaration-per-line, no-else-return, max-len */
+/* eslint-disable func-names, no-var, no-underscore-dangle, no-param-reassign, prefer-template, consistent-return, one-var, no-else-return */
import $ from 'jquery';
@@ -70,7 +70,7 @@ LineHighlighter.prototype.highlightHash = function(newHash) {
const scrollOptions = {
// Scroll to the first highlighted line on initial load
// Offset -50 for the sticky top bar, and another -100 for some context
- offset: -150
+ offset: -150,
};
if (this.options.scrollFileHolder) {
$(this.options.fileHolderSelector).scrollTo(lineSelector, scrollOptions);
@@ -85,7 +85,9 @@ LineHighlighter.prototype.clickHandler = function(event) {
var current, lineNumber, range;
event.preventDefault();
this.clearHighlight();
- lineNumber = $(event.target).closest('a').data('lineNumber');
+ lineNumber = $(event.target)
+ .closest('a')
+ .data('lineNumber');
current = this.hashToRange(this._hash);
if (!(current[0] && event.shiftKey)) {
// If there's no current selection, or there is but Shift wasn't held,
@@ -104,7 +106,7 @@ LineHighlighter.prototype.clickHandler = function(event) {
};
LineHighlighter.prototype.clearHighlight = function() {
- return $("." + this.highlightLineClass).removeClass(this.highlightLineClass);
+ return $('.' + this.highlightLineClass).removeClass(this.highlightLineClass);
};
// Convert a URL hash String into line numbers
@@ -135,7 +137,7 @@ LineHighlighter.prototype.hashToRange = function(hash) {
//
// lineNumber - Line number to highlight
LineHighlighter.prototype.highlightLine = function(lineNumber) {
- return $("#LC" + lineNumber).addClass(this.highlightLineClass);
+ return $('#LC' + lineNumber).addClass(this.highlightLineClass);
};
// Highlight all lines within a range
@@ -160,9 +162,9 @@ LineHighlighter.prototype.highlightRange = function(range) {
LineHighlighter.prototype.setHash = function(firstLineNumber, lastLineNumber) {
var hash;
if (lastLineNumber) {
- hash = "#L" + firstLineNumber + "-" + lastLineNumber;
+ hash = '#L' + firstLineNumber + '-' + lastLineNumber;
} else {
- hash = "#L" + firstLineNumber;
+ hash = '#L' + firstLineNumber;
}
this._hash = hash;
return this.__setLocationHash__(hash);
@@ -172,11 +174,15 @@ LineHighlighter.prototype.setHash = function(firstLineNumber, lastLineNumber) {
//
// This method is stubbed in tests.
LineHighlighter.prototype.__setLocationHash__ = function(value) {
- return window.history.pushState({
- url: value
- // We're using pushState instead of assigning location.hash directly to
- // prevent the page from scrolling on the hashchange event
- }, document.title, value);
+ return window.history.pushState(
+ {
+ url: value,
+ // We're using pushState instead of assigning location.hash directly to
+ // prevent the page from scrolling on the hashchange event
+ },
+ document.title,
+ value,
+ );
};
export default LineHighlighter;
diff --git a/app/assets/javascripts/locale/sprintf.js b/app/assets/javascripts/locale/sprintf.js
index 599104dcfa0..5246c49842e 100644
--- a/app/assets/javascripts/locale/sprintf.js
+++ b/app/assets/javascripts/locale/sprintf.js
@@ -15,7 +15,7 @@ export default (input, parameters, escapeParameters = true) => {
let output = input;
if (parameters) {
- Object.keys(parameters).forEach((parameterName) => {
+ Object.keys(parameters).forEach(parameterName => {
const parameterValue = parameters[parameterName];
const escapedParameterValue = escapeParameters ? _.escape(parameterValue) : parameterValue;
output = output.replace(new RegExp(`%{${parameterName}}`, 'g'), escapedParameterValue);
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index e8aac51a299..a88b575ad99 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -202,7 +202,6 @@ document.addEventListener('DOMContentLoaded', () => {
$('.navbar-toggler').on('click', () => {
$('.header-content').toggleClass('menu-expanded');
- gl.lazyLoader.loadCheck();
});
// Show/hide comments on diff
diff --git a/app/assets/javascripts/member_expiration_date.js b/app/assets/javascripts/member_expiration_date.js
index d27922a2099..0beedcacf33 100644
--- a/app/assets/javascripts/member_expiration_date.js
+++ b/app/assets/javascripts/member_expiration_date.js
@@ -1,6 +1,6 @@
import $ from 'jquery';
import Pikaday from 'pikaday';
-import { parsePikadayDate, pikadayToString } from './lib/utils/datefix';
+import { parsePikadayDate, pikadayToString } from './lib/utils/datetime_utility';
// Add datepickers to all `js-access-expiration-date` elements. If those elements are
// children of an element with the `clearable-input` class, and have a sibling
@@ -9,7 +9,9 @@ import { parsePikadayDate, pikadayToString } from './lib/utils/datefix';
//
export default function memberExpirationDate(selector = '.js-access-expiration-date') {
function toggleClearInput() {
- $(this).closest('.clearable-input').toggleClass('has-value', $(this).val() !== '');
+ $(this)
+ .closest('.clearable-input')
+ .toggleClass('has-value', $(this).val() !== '');
}
const inputs = $(selector);
@@ -40,7 +42,9 @@ export default function memberExpirationDate(selector = '.js-access-expiration-d
inputs.next('.js-clear-input').on('click', function clicked(event) {
event.preventDefault();
- const input = $(this).closest('.clearable-input').find(selector);
+ const input = $(this)
+ .closest('.clearable-input')
+ .find(selector);
const calendar = input.data('pikaday');
calendar.setDate(null);
diff --git a/app/assets/javascripts/members.js b/app/assets/javascripts/members.js
index 7d0c701fd70..bd263c75a3d 100644
--- a/app/assets/javascripts/members.js
+++ b/app/assets/javascripts/members.js
@@ -7,8 +7,12 @@ export default class Members {
}
addListeners() {
- $('.js-member-update-control').off('change').on('change', this.formSubmit.bind(this));
- $('.js-edit-member-form').off('ajax:success').on('ajax:success', this.formSuccess.bind(this));
+ $('.js-member-update-control')
+ .off('change')
+ .on('change', this.formSubmit.bind(this));
+ $('.js-edit-member-form')
+ .off('ajax:success')
+ .on('ajax:success', this.formSuccess.bind(this));
gl.utils.disableButtonIfEmptyField('#user_ids', 'input[name=commit]', 'change');
}
@@ -28,7 +32,7 @@ export default class Members {
toggleLabel(selected, $el) {
return $el.text();
},
- clicked: (options) => {
+ clicked: options => {
this.formSubmit(null, options.$el);
},
});
diff --git a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js
index 81950515ab4..a62ebe23646 100644
--- a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js
+++ b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js
@@ -1,12 +1,13 @@
-/* eslint-disable comma-dangle, quote-props, no-useless-computed-key, object-shorthand, no-param-reassign, max-len */
+/* eslint-disable no-useless-computed-key, object-shorthand, no-param-reassign */
/* global ace */
import Vue from 'vue';
import axios from '~/lib/utils/axios_utils';
import flash from '~/flash';
import { __ } from '~/locale';
+import getModeByFileExtension from '~/lib/utils/ace_utils';
-((global) => {
+(global => {
global.mergeConflicts = global.mergeConflicts || {};
global.mergeConflicts.diffFileEditor = Vue.extend({
@@ -35,10 +36,10 @@ import { __ } from '~/locale';
computed: {
classObject() {
return {
- 'saved': this.saved,
- 'is-loading': this.loading
+ saved: this.saved,
+ 'is-loading': this.loading,
};
- }
+ },
},
watch: {
['file.showEditor'](val) {
@@ -49,7 +50,7 @@ import { __ } from '~/locale';
}
this.loadEditor();
- }
+ },
},
mounted() {
if (this.file.loadEditor) {
@@ -60,7 +61,8 @@ import { __ } from '~/locale';
loadEditor() {
this.loading = true;
- axios.get(this.file.content_path)
+ axios
+ .get(this.file.content_path)
.then(({ data }) => {
const content = this.$el.querySelector('pre');
const fileContent = document.createTextNode(data.content);
@@ -71,7 +73,7 @@ import { __ } from '~/locale';
this.fileLoaded = true;
this.editor = ace.edit(content);
this.editor.$blockScrolling = Infinity; // Turn off annoying warning
- this.editor.getSession().setMode(`ace/mode/${data.blob_ace_mode}`);
+ this.editor.getSession().setMode(getModeByFileExtension(data.new_path));
this.editor.on('change', () => {
this.saveDiffResolution();
});
@@ -101,7 +103,7 @@ import { __ } from '~/locale';
},
acceptDiscardConfirmation(file) {
this.onAcceptDiscardConfirmation(file);
- }
- }
+ },
+ },
});
})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js b/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js
index 69208ac2d36..c2de0379d23 100644
--- a/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js
+++ b/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js
@@ -4,7 +4,7 @@ import Vue from 'vue';
import actionsMixin from '../mixins/line_conflict_actions';
import utilsMixin from '../mixins/line_conflict_utils';
-((global) => {
+(global => {
global.mergeConflicts = global.mergeConflicts || {};
global.mergeConflicts.parallelConflictLines = Vue.extend({
diff --git a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
index 1501296ac4f..0333335de06 100644
--- a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
+++ b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js
@@ -1,10 +1,10 @@
-/* eslint-disable comma-dangle, object-shorthand, no-param-reassign, camelcase, no-nested-ternary, no-continue, max-len */
+/* eslint-disable object-shorthand, no-param-reassign, camelcase, no-nested-ternary, no-continue */
import $ from 'jquery';
import Vue from 'vue';
import Cookies from 'js-cookie';
-((global) => {
+(global => {
global.mergeConflicts = global.mergeConflicts || {};
const diffViewType = Cookies.get('diff_view');
@@ -17,11 +17,11 @@ import Cookies from 'js-cookie';
const DEFAULT_RESOLVE_MODE = INTERACTIVE_RESOLVE_MODE;
const VIEW_TYPES = {
INLINE: 'inline',
- PARALLEL: 'parallel'
+ PARALLEL: 'parallel',
};
const CONFLICT_TYPES = {
TEXT: 'text',
- TEXT_EDITOR: 'text-editor'
+ TEXT_EDITOR: 'text-editor',
};
global.mergeConflicts.mergeConflictsStore = {
@@ -31,7 +31,7 @@ import Cookies from 'js-cookie';
isSubmitting: false,
isParallel: diffViewType === VIEW_TYPES.PARALLEL,
diffViewType: diffViewType,
- conflictsData: {}
+ conflictsData: {},
},
setConflictsData(data) {
@@ -47,7 +47,7 @@ import Cookies from 'js-cookie';
},
decorateFiles(files) {
- files.forEach((file) => {
+ files.forEach(file => {
file.content = '';
file.resolutionData = {};
file.promptDiscardConfirmation = false;
@@ -72,7 +72,7 @@ import Cookies from 'js-cookie';
setInlineLine(file) {
file.inlineLines = [];
- file.sections.forEach((section) => {
+ file.sections.forEach(section => {
let currentLineType = 'new';
const { conflict, lines, id } = section;
@@ -80,7 +80,7 @@ import Cookies from 'js-cookie';
file.inlineLines.push(this.getHeadHeaderLine(id));
}
- lines.forEach((line) => {
+ lines.forEach(line => {
const { type } = line;
if ((type === 'new' || type === 'old') && currentLineType !== type) {
@@ -102,7 +102,7 @@ import Cookies from 'js-cookie';
file.parallelLines = [];
const linesObj = { left: [], right: [] };
- file.sections.forEach((section) => {
+ file.sections.forEach(section => {
const { conflict, lines, id } = section;
if (conflict) {
@@ -110,7 +110,7 @@ import Cookies from 'js-cookie';
linesObj.right.push(this.getHeadHeaderLine(id));
}
- lines.forEach((line) => {
+ lines.forEach(line => {
const { type } = line;
if (conflict) {
@@ -131,10 +131,7 @@ import Cookies from 'js-cookie';
});
for (let i = 0, len = linesObj.left.length; i < len; i += 1) {
- file.parallelLines.push([
- linesObj.right[i],
- linesObj.left[i]
- ]);
+ file.parallelLines.push([linesObj.right[i], linesObj.left[i]]);
}
},
@@ -159,9 +156,9 @@ import Cookies from 'js-cookie';
const { files } = this.state.conflictsData;
let count = 0;
- files.forEach((file) => {
+ files.forEach(file => {
if (file.type === CONFLICT_TYPES.TEXT) {
- file.sections.forEach((section) => {
+ file.sections.forEach(section => {
if (section.conflict) {
count += 1;
}
@@ -198,7 +195,7 @@ import Cookies from 'js-cookie';
isHeader: true,
isHead: true,
isSelected: false,
- isUnselected: false
+ isUnselected: false,
};
},
@@ -229,7 +226,7 @@ import Cookies from 'js-cookie';
section: isHead ? 'head' : 'origin',
richText: rich_text,
isSelected: false,
- isUnselected: false
+ isUnselected: false,
};
},
@@ -243,7 +240,7 @@ import Cookies from 'js-cookie';
isHeader: true,
isOrigin: true,
isSelected: false,
- isUnselected: false
+ isUnselected: false,
};
},
@@ -290,14 +287,14 @@ import Cookies from 'js-cookie';
},
restoreFileLinesState(file) {
- file.inlineLines.forEach((line) => {
+ file.inlineLines.forEach(line => {
if (line.hasConflict || line.isHeader) {
line.isSelected = false;
line.isUnselected = false;
}
});
- file.parallelLines.forEach((lines) => {
+ file.parallelLines.forEach(lines => {
const left = lines[0];
const right = lines[1];
const isLeftMatch = left.hasConflict || left.isHeader;
@@ -354,7 +351,7 @@ import Cookies from 'js-cookie';
const initial = 'Commit to source branch';
const inProgress = 'Committing...';
- return this.state ? this.state.isSubmitting ? inProgress : initial : initial;
+ return this.state ? (this.state.isSubmitting ? inProgress : initial) : initial;
},
getCommitData() {
@@ -362,13 +359,13 @@ import Cookies from 'js-cookie';
commitData = {
commit_message: this.state.conflictsData.commitMessage,
- files: []
+ files: [],
};
- this.state.conflictsData.files.forEach((file) => {
+ this.state.conflictsData.files.forEach(file => {
const addFile = {
old_path: file.old_path,
- new_path: file.new_path
+ new_path: file.new_path,
};
if (file.type === CONFLICT_TYPES.TEXT) {
@@ -391,13 +388,13 @@ import Cookies from 'js-cookie';
handleSelected(file, sectionId, selection) {
Vue.set(file.resolutionData, sectionId, selection);
- file.inlineLines.forEach((line) => {
+ file.inlineLines.forEach(line => {
if (line.id === sectionId && (line.hasConflict || line.isHeader)) {
this.markLine(line, selection);
}
});
- file.parallelLines.forEach((lines) => {
+ file.parallelLines.forEach(lines => {
const left = lines[0];
const right = lines[1];
const hasSameId = right.id === sectionId || left.id === sectionId;
@@ -430,6 +427,6 @@ import Cookies from 'js-cookie';
fileTextTypePresent() {
return this.state.conflictsData.files.some(f => f.type === CONFLICT_TYPES.TEXT);
- }
+ },
};
})(window.gl || (window.gl = {}));
diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js
index 7bf2c56dd5d..0deae478deb 100644
--- a/app/assets/javascripts/merge_request.js
+++ b/app/assets/javascripts/merge_request.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, no-var, wrap-iife, quotes, no-underscore-dangle, one-var, one-var-declaration-per-line, consistent-return, comma-dangle, max-len, prefer-arrow-callback */
+/* eslint-disable func-names, no-var, no-underscore-dangle, one-var, consistent-return, prefer-arrow-callback */
import $ from 'jquery';
import { __ } from '~/locale';
@@ -16,26 +16,29 @@ function MergeRequest(opts) {
this.opts = opts != null ? opts : {};
this.submitNoteForm = this.submitNoteForm.bind(this);
this.$el = $('.merge-request');
- this.$('.show-all-commits').on('click', (function(_this) {
- return function() {
- return _this.showAllCommits();
- };
- })(this));
+ this.$('.show-all-commits').on(
+ 'click',
+ (function(_this) {
+ return function() {
+ return _this.showAllCommits();
+ };
+ })(this),
+ );
this.initTabs();
this.initMRBtnListeners();
this.initCommitMessageListeners();
this.closeReopenReportToggle = IssuablesHelper.initCloseReopenReport();
- if ($("a.btn-close").length) {
+ if ($('a.btn-close').length) {
this.taskList = new TaskList({
dataType: 'merge_request',
fieldName: 'description',
selector: '.detail-page-description',
- onSuccess: (result) => {
+ onSuccess: result => {
document.querySelector('#task_status').innerText = result.task_status;
document.querySelector('#task_status_short').innerText = result.task_status_short;
- }
+ },
});
}
}
@@ -84,7 +87,7 @@ MergeRequest.prototype.initMRBtnListeners = function() {
MergeRequest.prototype.submitNoteForm = function(form, $button) {
var noteText;
- noteText = form.find("textarea.js-note-text").val();
+ noteText = form.find('textarea.js-note-text').val();
if (noteText.trim().length > 0) {
form.submit();
$button.data('submitted', true);
@@ -122,7 +125,7 @@ MergeRequest.setStatusBoxToMerged = function() {
MergeRequest.decreaseCounter = function(by = 1) {
const $el = $('.js-merge-counter');
- const count = Math.max((parseInt($el.text().replace(/[^\d]/, ''), 10) - by), 0);
+ const count = Math.max(parseInt($el.text().replace(/[^\d]/, ''), 10) - by, 0);
$el.text(addDelimiter(count));
};
diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 53d7504de35..b0dc5697018 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -8,17 +8,20 @@ import flash from './flash';
import BlobForkSuggestion from './blob/blob_fork_suggestion';
import initChangesDropdown from './init_changes_dropdown';
import bp from './breakpoints';
-import { parseUrlPathname, handleLocationHash, isMetaClick } from './lib/utils/common_utils';
+import {
+ parseUrlPathname,
+ handleLocationHash,
+ isMetaClick,
+ parseBoolean,
+} from './lib/utils/common_utils';
import { isInVueNoteablePage } from './lib/utils/dom_utils';
import { getLocationHash } from './lib/utils/url_utility';
-import initDiscussionTab from './image_diff/init_discussion_tab';
import Diff from './diff';
import { localTimeAgo } from './lib/utils/datetime_utility';
import syntaxHighlight from './syntax_highlight';
import Notes from './notes';
import { polyfillSticky } from './lib/utils/sticky';
-/* eslint-disable max-len */
// MergeRequestTabs
//
// Handles persisting and restoring the current tab selection and lazily-loading
@@ -62,7 +65,6 @@ import { polyfillSticky } from './lib/utils/sticky';
// </div>
// </div>
//
-/* eslint-enable max-len */
// Store the `location` object, allowing for easier stubbing in tests
let { location } = window;
@@ -115,8 +117,9 @@ export default class MergeRequestTabs {
this.mergeRequestTabs &&
this.mergeRequestTabs.querySelector(`a[data-action='${action}']`) &&
this.mergeRequestTabs.querySelector(`a[data-action='${action}']`).click
- )
+ ) {
this.mergeRequestTabs.querySelector(`a[data-action='${action}']`).click();
+ }
this.initAffix();
}
@@ -193,9 +196,7 @@ export default class MergeRequestTabs {
if (bp.getBreakpointSize() !== 'lg') {
this.shrinkView();
}
- if (this.diffViewType() === 'parallel') {
- this.expandViewContainer();
- }
+ this.expandViewContainer();
this.destroyPipelinesView();
this.commitsTab.classList.remove('active');
} else if (action === 'pipelines') {
@@ -210,14 +211,34 @@ export default class MergeRequestTabs {
}
this.resetViewContainer();
this.destroyPipelinesView();
-
- initDiscussionTab();
}
if (this.setUrl) {
this.setCurrentAction(action);
}
this.eventHub.$emit('MergeRequestTabChange', this.getCurrentAction());
+ } else if (action === this.currentAction) {
+ // ContentTop is used to handle anything at the top of the page before the main content
+ const mainContentContainer = document.querySelector('.content-wrapper');
+ const tabContentContainer = document.querySelector('.tab-content');
+
+ if (mainContentContainer && tabContentContainer) {
+ const mainContentTop = mainContentContainer.getBoundingClientRect().top;
+ const tabContentTop = tabContentContainer.getBoundingClientRect().top;
+
+ // 51px is the height of the navbar buttons, e.g. `Discussion | Commits | Changes`
+ const scrollDestination = tabContentTop - mainContentTop - 51;
+
+ // scrollBehavior is only available in browsers that support scrollToOptions
+ if ('scrollBehavior' in document.documentElement.style) {
+ window.scrollTo({
+ top: scrollDestination,
+ behavior: 'smooth',
+ });
+ } else {
+ window.scrollTo(0, scrollDestination);
+ }
+ }
}
}
@@ -354,7 +375,7 @@ export default class MergeRequestTabs {
localTimeAgo($('.js-timeago', 'div#diffs'));
syntaxHighlight($('#diffs .js-syntax-highlight'));
- if (this.diffViewType() === 'parallel' && this.isDiffAction(this.currentAction)) {
+ if (this.isDiffAction(this.currentAction)) {
this.expandViewContainer();
}
this.diffsLoaded = true;
@@ -407,19 +428,23 @@ export default class MergeRequestTabs {
}
diffViewType() {
- return $('.inline-parallel-buttons a.active').data('viewType');
+ return $('.inline-parallel-buttons button.active').data('viewType');
}
isDiffAction(action) {
return action === 'diffs' || action === 'new/diffs';
}
- expandViewContainer() {
+ expandViewContainer(removeLimited = true) {
const $wrapper = $('.content-wrapper .container-fluid').not('.breadcrumbs');
if (this.fixedLayoutPref === null) {
this.fixedLayoutPref = $wrapper.hasClass('container-limited');
}
- $wrapper.removeClass('container-limited');
+ if (this.diffViewType() === 'parallel' || removeLimited) {
+ $wrapper.removeClass('container-limited');
+ } else {
+ $wrapper.toggleClass('container-limited', this.fixedLayoutPref);
+ }
}
resetViewContainer() {
@@ -442,7 +467,7 @@ export default class MergeRequestTabs {
// Expand the issuable sidebar unless the user explicitly collapsed it
expandView() {
- if (Cookies.get('collapsed_gutter') === 'true') {
+ if (parseBoolean(Cookies.get('collapsed_gutter'))) {
return;
}
const $gutterIcon = $('.js-sidebar-toggle i:visible');
diff --git a/app/assets/javascripts/milestone.js b/app/assets/javascripts/milestone.js
index 6da04020881..f211632cf24 100644
--- a/app/assets/javascripts/milestone.js
+++ b/app/assets/javascripts/milestone.js
@@ -15,7 +15,7 @@ export default class Milestone {
}
bindTabsSwitching() {
- return $('a[data-toggle="tab"]').on('show.bs.tab', (e) => {
+ return $('a[data-toggle="tab"]').on('show.bs.tab', e => {
const $target = $(e.target);
window.location.hash = $target.attr('href');
@@ -36,7 +36,8 @@ export default class Milestone {
const tabElId = $target.attr('href');
if (endpoint && !$target.hasClass('is-loaded')) {
- axios.get(endpoint)
+ axios
+ .get(endpoint)
.then(({ data }) => {
$(tabElId).html(data.html);
$target.addClass('is-loaded');
@@ -46,23 +47,28 @@ export default class Milestone {
}
static initDeprecationMessage() {
- const deprecationMesssageContainer = document.querySelector('.js-milestone-deprecation-message');
+ const deprecationMesssageContainer = document.querySelector(
+ '.js-milestone-deprecation-message',
+ );
if (!deprecationMesssageContainer) return;
- const deprecationMessage = deprecationMesssageContainer.querySelector('.js-milestone-deprecation-message-template').innerHTML;
+ const deprecationMessage = deprecationMesssageContainer.querySelector(
+ '.js-milestone-deprecation-message-template',
+ ).innerHTML;
const $popover = $('.js-popover-link', deprecationMesssageContainer);
const hideOnScroll = togglePopover.bind($popover, false);
- $popover.popover({
- content: deprecationMessage,
- html: true,
- placement: 'bottom',
- })
- .on('mouseenter', mouseenter)
- .on('mouseleave', debouncedMouseleave())
- .on('show.bs.popover', () => {
- window.addEventListener('scroll', hideOnScroll, { once: true });
- });
+ $popover
+ .popover({
+ content: deprecationMessage,
+ html: true,
+ placement: 'bottom',
+ })
+ .on('mouseenter', mouseenter)
+ .on('mouseleave', debouncedMouseleave())
+ .on('show.bs.popover', () => {
+ window.addEventListener('scroll', hideOnScroll, { once: true });
+ });
}
}
diff --git a/app/assets/javascripts/milestone_select.js b/app/assets/javascripts/milestone_select.js
index 640a4c8260f..d32f39881dd 100644
--- a/app/assets/javascripts/milestone_select.js
+++ b/app/assets/javascripts/milestone_select.js
@@ -1,4 +1,4 @@
-/* eslint-disable max-len, one-var, one-var-declaration-per-line, no-unused-vars, object-shorthand, no-else-return, no-self-compare, consistent-return, no-param-reassign, no-shadow */
+/* eslint-disable one-var, no-unused-vars, object-shorthand, no-else-return, no-self-compare, consistent-return, no-param-reassign, no-shadow */
/* global Issuable */
/* global ListMilestone */
@@ -9,6 +9,10 @@ import '~/gl_dropdown';
import axios from './lib/utils/axios_utils';
import { timeFor } from './lib/utils/datetime_utility';
import ModalStore from './boards/stores/modal_store';
+import boardsStore, {
+ boardStoreIssueSet,
+ boardStoreIssueDelete,
+} from './boards/stores/boards_store';
export default class MilestoneSelect {
constructor(currentProject, els, options = {}) {
@@ -187,7 +191,7 @@ export default class MilestoneSelect {
return $dropdown.closest('form').submit();
} else if ($dropdown.hasClass('js-issue-board-sidebar')) {
if (selected.id !== -1 && isSelecting) {
- gl.issueBoards.boardStoreIssueSet(
+ boardStoreIssueSet(
'milestone',
new ListMilestone({
id: selected.id,
@@ -195,13 +199,13 @@ export default class MilestoneSelect {
}),
);
} else {
- gl.issueBoards.boardStoreIssueDelete('milestone');
+ boardStoreIssueDelete('milestone');
}
$dropdown.trigger('loading.gl.dropdown');
$loading.removeClass('hidden').fadeIn();
- gl.issueBoards.BoardsStore.detail.issue
+ boardsStore.detail.issue
.update($dropdown.attr('data-issue-update'))
.then(() => {
$dropdown.trigger('loaded.gl.dropdown');
diff --git a/app/assets/javascripts/mini_pipeline_graph_dropdown.js b/app/assets/javascripts/mini_pipeline_graph_dropdown.js
index f8257b6abab..81ab9d8be4b 100644
--- a/app/assets/javascripts/mini_pipeline_graph_dropdown.js
+++ b/app/assets/javascripts/mini_pipeline_graph_dropdown.js
@@ -46,7 +46,7 @@ export default class MiniPipelineGraph {
$(document).on(
'click',
`${this.container} .js-builds-dropdown-list a.mini-pipeline-graph-dropdown-item`,
- (e) => {
+ e => {
e.stopPropagation();
},
);
@@ -82,7 +82,8 @@ export default class MiniPipelineGraph {
this.renderBuildsList(button, '');
this.toggleLoading(button);
- axios.get(endpoint)
+ axios
+ .get(endpoint)
.then(({ data }) => {
this.toggleLoading(button);
this.renderBuildsList(button, data.html);
@@ -90,7 +91,11 @@ export default class MiniPipelineGraph {
})
.catch(() => {
this.toggleLoading(button);
- if ($(button).parent().hasClass('open')) {
+ if (
+ $(button)
+ .parent()
+ .hasClass('open')
+ ) {
$(button).dropdown('toggle');
}
flash('An error occurred while fetching the builds.', 'alert');
@@ -104,8 +109,8 @@ export default class MiniPipelineGraph {
* @return {type}
*/
toggleLoading(stageContainer) {
- stageContainer.parentElement.querySelector(
- `${this.dropdownListSelector} .js-builds-dropdown-loading`,
- ).classList.toggle('hidden');
+ stageContainer.parentElement
+ .querySelector(`${this.dropdownListSelector} .js-builds-dropdown-loading`)
+ .classList.toggle('hidden');
}
}
diff --git a/app/assets/javascripts/mirrors/constants.js b/app/assets/javascripts/mirrors/constants.js
new file mode 100644
index 00000000000..8dd6a726425
--- /dev/null
+++ b/app/assets/javascripts/mirrors/constants.js
@@ -0,0 +1,4 @@
+export default {
+ PASSWORD: 'password',
+ SSH: 'ssh_public_key',
+};
diff --git a/app/assets/javascripts/mirrors/mirror_repos.js b/app/assets/javascripts/mirrors/mirror_repos.js
new file mode 100644
index 00000000000..196b84621b6
--- /dev/null
+++ b/app/assets/javascripts/mirrors/mirror_repos.js
@@ -0,0 +1,109 @@
+import $ from 'jquery';
+import _ from 'underscore';
+import { __ } from '~/locale';
+import Flash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import SSHMirror from './ssh_mirror';
+
+export default class MirrorRepos {
+ constructor(container) {
+ this.$container = $(container);
+ this.$password = null;
+ this.$form = $('.js-mirror-form', this.$container);
+ this.$urlInput = $('.js-mirror-url', this.$form);
+ this.$protectedBranchesInput = $('.js-mirror-protected', this.$form);
+ this.$table = $('.js-mirrors-table-body', this.$container);
+ this.mirrorEndpoint = this.$form.data('projectMirrorEndpoint');
+ }
+
+ init() {
+ this.initMirrorPush();
+ this.registerUpdateListeners();
+ }
+
+ initMirrorPush() {
+ this.$passwordGroup = $('.js-password-group', this.$container);
+ this.$password = $('.js-password', this.$passwordGroup);
+ this.$authMethod = $('.js-auth-method', this.$form);
+
+ this.$authMethod.on('change', () => this.togglePassword());
+ this.$password.on('input.updateUrl', () => this.debouncedUpdateUrl());
+
+ this.initMirrorSSH();
+ this.updateProtectedBranches();
+ }
+
+ initMirrorSSH() {
+ if (this.$password) {
+ this.$password.off('input.updateUrl');
+ }
+ this.$password = undefined;
+
+ this.sshMirror = new SSHMirror('.js-mirror-form');
+ this.sshMirror.init();
+ }
+
+ updateUrl() {
+ let val = this.$urlInput.val();
+
+ if (this.$password) {
+ const password = this.$password.val();
+ if (password) val = val.replace('@', `:${password}@`);
+ }
+
+ $('.js-mirror-url-hidden', this.$form).val(val);
+ }
+
+ updateProtectedBranches() {
+ const val = this.$protectedBranchesInput.get(0).checked
+ ? this.$protectedBranchesInput.val()
+ : '0';
+ $('.js-mirror-protected-hidden', this.$form).val(val);
+ }
+
+ registerUpdateListeners() {
+ this.debouncedUpdateUrl = _.debounce(() => this.updateUrl(), 200);
+ this.$urlInput.on('input', () => this.debouncedUpdateUrl());
+ this.$protectedBranchesInput.on('change', () => this.updateProtectedBranches());
+ this.$table.on('click', '.js-delete-mirror', event => this.deleteMirror(event));
+ }
+
+ togglePassword() {
+ const isPassword = this.$authMethod.val() === 'password';
+
+ if (!isPassword) {
+ this.$password.val('');
+ this.updateUrl();
+ }
+ this.$passwordGroup.collapse(isPassword ? 'show' : 'hide');
+ }
+
+ deleteMirror(event, existingPayload) {
+ const $target = $(event.currentTarget);
+ let payload = existingPayload;
+
+ if (!payload) {
+ payload = {
+ project: {
+ remote_mirrors_attributes: {
+ id: $target.data('mirrorId'),
+ enabled: 0,
+ },
+ },
+ };
+ }
+
+ return axios
+ .put(this.mirrorEndpoint, payload)
+ .then(() => this.removeRow($target))
+ .catch(() => Flash(__('Failed to remove mirror.')));
+ }
+
+ /* eslint-disable class-methods-use-this */
+ removeRow($target) {
+ const row = $target.closest('tr');
+ $('.js-delete-mirror', row).tooltip('hide');
+ row.remove();
+ }
+ /* eslint-enable class-methods-use-this */
+}
diff --git a/app/assets/javascripts/mirrors/ssh_mirror.js b/app/assets/javascripts/mirrors/ssh_mirror.js
new file mode 100644
index 00000000000..5bdf5d6277a
--- /dev/null
+++ b/app/assets/javascripts/mirrors/ssh_mirror.js
@@ -0,0 +1,299 @@
+import $ from 'jquery';
+import _ from 'underscore';
+import { __ } from '~/locale';
+import axios from '~/lib/utils/axios_utils';
+import Flash from '~/flash';
+import { backOff } from '~/lib/utils/common_utils';
+import AUTH_METHOD from './constants';
+
+export default class SSHMirror {
+ constructor(formSelector) {
+ this.backOffRequestCounter = 0;
+
+ this.$form = $(formSelector);
+
+ this.$repositoryUrl = this.$form.find('.js-repo-url');
+ this.$knownHosts = this.$form.find('.js-known-hosts');
+
+ this.$sectionSSHHostKeys = this.$form.find('.js-ssh-host-keys-section');
+ this.$hostKeysInformation = this.$form.find('.js-fingerprint-ssh-info');
+ this.$btnDetectHostKeys = this.$form.find('.js-detect-host-keys');
+ this.$btnSSHHostsShowAdvanced = this.$form.find('.btn-show-advanced');
+ this.$dropdownAuthType = this.$form.find('.js-mirror-auth-type');
+
+ this.$wellAuthTypeChanging = this.$form.find('.js-well-changing-auth');
+ this.$wellPasswordAuth = this.$form.find('.js-well-password-auth');
+ this.$wellSSHAuth = this.$form.find('.js-well-ssh-auth');
+ this.$sshPublicKeyWrap = this.$form.find('.js-ssh-public-key-wrap');
+ this.$regeneratePublicSshKeyButton = this.$wellSSHAuth.find('.js-btn-regenerate-ssh-key');
+ this.$regeneratePublicSshKeyModal = this.$wellSSHAuth.find(
+ '.js-regenerate-public-ssh-key-confirm-modal',
+ );
+ }
+
+ init() {
+ this.handleRepositoryUrlInput(true);
+
+ this.$repositoryUrl.on('keyup', () => this.handleRepositoryUrlInput());
+ this.$knownHosts.on('keyup', e => this.handleSSHKnownHostsInput(e));
+ this.$dropdownAuthType.on('change', e => this.handleAuthTypeChange(e));
+ this.$btnDetectHostKeys.on('click', e => this.handleDetectHostKeys(e));
+ this.$btnSSHHostsShowAdvanced.on('click', e => this.handleSSHHostsAdvanced(e));
+ this.$regeneratePublicSshKeyButton.on('click', () =>
+ this.$regeneratePublicSshKeyModal.toggle(true),
+ );
+ $('.js-confirm', this.$regeneratePublicSshKeyModal).on('click', e =>
+ this.regeneratePublicSshKey(e),
+ );
+ $('.js-cancel', this.$regeneratePublicSshKeyModal).on('click', () =>
+ this.$regeneratePublicSshKeyModal.toggle(false),
+ );
+ }
+
+ /**
+ * Method to monitor Git Repository URL input
+ */
+ handleRepositoryUrlInput(forceMatch) {
+ const protocol = this.$repositoryUrl.val().split('://')[0];
+ const protRegEx = /http|git/;
+
+ // Validate URL and verify if it consists only supported protocols
+ if (forceMatch || this.$form.get(0).checkValidity()) {
+ const isSsh = protocol === 'ssh';
+ // Hide/Show SSH Host keys section only for SSH URLs
+ this.$sectionSSHHostKeys.collapse(isSsh ? 'show' : 'hide');
+ this.$btnDetectHostKeys.enable();
+
+ // Verify if URL is http, https or git and hide/show Auth type dropdown
+ // as we don't support auth type SSH for non-SSH URLs
+ const matchesProtocol = protRegEx.test(protocol);
+ this.$dropdownAuthType.attr('disabled', matchesProtocol);
+
+ if (forceMatch && isSsh) {
+ this.$dropdownAuthType.val(AUTH_METHOD.SSH);
+ this.toggleAuthWell(AUTH_METHOD.SSH);
+ } else {
+ this.$dropdownAuthType.val(AUTH_METHOD.PASSWORD);
+ this.toggleAuthWell(AUTH_METHOD.PASSWORD);
+ }
+ }
+ }
+
+ /**
+ * Click event handler to detect SSH Host key and fingerprints from
+ * provided Git Repository URL.
+ */
+ handleDetectHostKeys() {
+ const projectMirrorSSHEndpoint = this.$form.data('project-mirror-ssh-endpoint');
+ const repositoryUrl = this.$repositoryUrl.val();
+ const currentKnownHosts = this.$knownHosts.val();
+ const $btnLoadSpinner = this.$btnDetectHostKeys.find('.js-spinner');
+
+ // Disable button while we make request
+ this.$btnDetectHostKeys.disable();
+ $btnLoadSpinner.removeClass('d-none');
+
+ // Make backOff polling to get data
+ backOff((next, stop) => {
+ axios
+ .get(
+ `${projectMirrorSSHEndpoint}?ssh_url=${repositoryUrl}&compare_host_keys=${encodeURIComponent(
+ currentKnownHosts,
+ )}`,
+ )
+ .then(({ data, status }) => {
+ if (status === 204) {
+ this.backOffRequestCounter += 1;
+ if (this.backOffRequestCounter < 3) {
+ next();
+ } else {
+ stop(data);
+ }
+ } else {
+ stop(data);
+ }
+ })
+ .catch(stop);
+ })
+ .then(res => {
+ $btnLoadSpinner.addClass('d-none');
+ // Once data is received, we show verification info along with Host keys and fingerprints
+ this.$hostKeysInformation
+ .find('.js-fingerprint-verification')
+ .collapse(res.host_keys_changed ? 'hide' : 'show');
+ if (res.known_hosts && res.fingerprints) {
+ this.showSSHInformation(res);
+ }
+ })
+ .catch(({ response }) => {
+ // Show failure message when there's an error and re-enable Detect host keys button
+ const failureMessage = response.data
+ ? response.data.message
+ : __('An error occurred while detecting host keys');
+ Flash(failureMessage);
+
+ $btnLoadSpinner.addClass('hidden');
+ this.$btnDetectHostKeys.enable();
+ });
+ }
+
+ /**
+ * Method to monitor known hosts textarea input
+ */
+ handleSSHKnownHostsInput() {
+ // Strike-out fingerprints and remove verification info if `known hosts` value is altered
+ this.$hostKeysInformation.find('.js-fingerprints-list').addClass('invalidate');
+ this.$hostKeysInformation.find('.js-fingerprint-verification').collapse('hide');
+ }
+
+ /**
+ * Click event handler for `Show advanced` button under SSH Host keys section
+ */
+ handleSSHHostsAdvanced() {
+ const $knownHost = this.$sectionSSHHostKeys.find('.js-ssh-known-hosts');
+ const toggleShowAdvanced = $knownHost.hasClass('show');
+
+ $knownHost.collapse('toggle');
+ this.$btnSSHHostsShowAdvanced.toggleClass('show-advanced', toggleShowAdvanced);
+ }
+
+ /**
+ * Authentication method dropdown change event listener
+ */
+ handleAuthTypeChange() {
+ const projectMirrorAuthTypeEndpoint = `${this.$form.attr('action')}.json`;
+ const $sshPublicKey = this.$sshPublicKeyWrap.find('.ssh-public-key');
+ const selectedAuthType = this.$dropdownAuthType.val();
+
+ this.$wellPasswordAuth.collapse('hide');
+ this.$wellSSHAuth.collapse('hide');
+
+ // This request should happen only if selected Auth type was SSH
+ // and SSH Public key was not present on page load
+ if (selectedAuthType === AUTH_METHOD.SSH && !$sshPublicKey.text().trim()) {
+ if (!this.$wellSSHAuth.length) return;
+
+ // Construct request body
+ const authTypeData = {
+ project: {
+ ...this.$regeneratePublicSshKeyButton.data().projectData,
+ },
+ };
+
+ this.$wellAuthTypeChanging.collapse('show');
+ this.$dropdownAuthType.disable();
+
+ axios
+ .put(projectMirrorAuthTypeEndpoint, JSON.stringify(authTypeData), {
+ headers: {
+ 'Content-Type': 'application/json; charset=utf-8',
+ },
+ })
+ .then(({ data }) => {
+ // Show SSH public key container and fill in public key
+ this.toggleAuthWell(selectedAuthType);
+ this.toggleSSHAuthWellMessage(true);
+ this.setSSHPublicKey(data.import_data_attributes.ssh_public_key);
+
+ this.$wellAuthTypeChanging.collapse('hide');
+ this.$dropdownAuthType.enable();
+ })
+ .catch(() => {
+ Flash(__('Something went wrong on our end.'));
+
+ this.$wellAuthTypeChanging.collapse('hide');
+ this.$dropdownAuthType.enable();
+ });
+ } else {
+ this.toggleAuthWell(selectedAuthType);
+ this.$wellSSHAuth.find('.js-ssh-public-key-present').collapse('show');
+ }
+ }
+
+ /**
+ * Method to parse SSH Host keys data and render it
+ * under SSH host keys section
+ */
+ showSSHInformation(sshHostKeys) {
+ const $fingerprintsList = this.$hostKeysInformation.find('.js-fingerprints-list');
+ let fingerprints = '';
+ sshHostKeys.fingerprints.forEach(fingerprint => {
+ const escFingerprints = _.escape(fingerprint.fingerprint);
+ fingerprints += `<code>${escFingerprints}</code>`;
+ });
+
+ this.$hostKeysInformation.collapse('show');
+ $fingerprintsList.removeClass('invalidate');
+ $fingerprintsList.html(fingerprints);
+ this.$sectionSSHHostKeys.find('.js-known-hosts').val(sshHostKeys.known_hosts);
+ }
+
+ /**
+ * Toggle Auth type information container based on provided `authType`
+ */
+ toggleAuthWell(authType) {
+ this.$wellPasswordAuth.collapse(authType === AUTH_METHOD.PASSWORD ? 'show' : 'hide');
+ this.$wellSSHAuth.collapse(authType === AUTH_METHOD.SSH ? 'show' : 'hide');
+ }
+
+ /**
+ * Toggle SSH auth information message
+ */
+ toggleSSHAuthWellMessage(sshKeyPresent) {
+ this.$sshPublicKeyWrap.collapse(sshKeyPresent ? 'show' : 'hide');
+ this.$wellSSHAuth.find('.js-ssh-public-key-present').collapse(sshKeyPresent ? 'show' : 'hide');
+ this.$regeneratePublicSshKeyButton.collapse(sshKeyPresent ? 'show' : 'hide');
+ this.$wellSSHAuth.find('.js-ssh-public-key-pending').collapse(sshKeyPresent ? 'hide' : 'show');
+ }
+
+ /**
+ * Sets SSH Public key to Clipboard button and shows it on UI.
+ */
+ setSSHPublicKey(sshPublicKey) {
+ this.$sshPublicKeyWrap.find('.ssh-public-key').text(sshPublicKey);
+ this.$sshPublicKeyWrap
+ .find('.btn-copy-ssh-public-key')
+ .attr('data-clipboard-text', sshPublicKey);
+ }
+
+ regeneratePublicSshKey(event) {
+ event.preventDefault();
+
+ this.$regeneratePublicSshKeyModal.toggle(false);
+
+ const button = this.$regeneratePublicSshKeyButton;
+ const spinner = $('.js-spinner', button);
+ const endpoint = button.data('endpoint');
+ const authTypeData = {
+ project: {
+ ...this.$regeneratePublicSshKeyButton.data().projectData,
+ },
+ };
+
+ button.attr('disabled', 'disabled');
+ spinner.removeClass('d-none');
+
+ axios
+ .patch(endpoint, authTypeData)
+ .then(({ data }) => {
+ button.removeAttr('disabled');
+ spinner.addClass('d-none');
+
+ this.setSSHPublicKey(data.import_data_attributes.ssh_public_key);
+ })
+ .catch(() => {
+ Flash(_('Unable to regenerate public ssh key.'));
+ });
+ }
+
+ destroy() {
+ this.$repositoryUrl.off('keyup');
+ this.$form.find('.js-known-hosts').off('keyup');
+ this.$dropdownAuthType.off('change');
+ this.$btnDetectHostKeys.off('click');
+ this.$btnSSHHostsShowAdvanced.off('click');
+ this.$regeneratePublicSshKeyButton.off('click');
+ $('.js-confirm', this.$regeneratePublicSshKeyModal).off('click');
+ $('.js-cancel', this.$regeneratePublicSshKeyModal).off('click');
+ }
+}
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index ae96ac3b80c..218c508a608 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -97,33 +97,45 @@ export default {
store: new MonitoringStore(),
state: 'gettingStarted',
showEmptyState: true,
- updateAspectRatio: false,
- updatedAspectRatios: 0,
hoverData: {},
- resizeThrottled: {},
+ elWidth: 0,
};
},
+ computed: {
+ forceRedraw() {
+ return this.elWidth;
+ },
+ },
created() {
this.service = new MonitoringService({
metricsEndpoint: this.metricsEndpoint,
deploymentEndpoint: this.deploymentEndpoint,
environmentsEndpoint: this.environmentsEndpoint,
});
- eventHub.$on('toggleAspectRatio', this.toggleAspectRatio);
+ this.mutationObserverConfig = {
+ attributes: true,
+ childList: false,
+ subtree: false,
+ };
eventHub.$on('hoverChanged', this.hoverChanged);
},
beforeDestroy() {
- eventHub.$off('toggleAspectRatio', this.toggleAspectRatio);
eventHub.$off('hoverChanged', this.hoverChanged);
window.removeEventListener('resize', this.resizeThrottled, false);
+ this.sidebarMutationObserver.disconnect();
},
mounted() {
- this.resizeThrottled = _.throttle(this.resize, 600);
+ this.resizeThrottled = _.debounce(this.resize, 100);
if (!this.hasMetrics) {
this.state = 'gettingStarted';
} else {
this.getGraphsData();
window.addEventListener('resize', this.resizeThrottled, false);
+
+ const sidebarEl = document.querySelector('.nav-sidebar');
+ // The sidebar listener
+ this.sidebarMutationObserver = new MutationObserver(this.resizeThrottled);
+ this.sidebarMutationObserver.observe(sidebarEl, this.mutationObserverConfig);
}
},
methods: {
@@ -137,7 +149,7 @@ export default {
.catch(() => Flash(s__('Metrics|There was an error getting deployment information.'))),
this.service
.getEnvironmentsData()
- .then((data) => this.store.storeEnvironmentsData(data))
+ .then(data => this.store.storeEnvironmentsData(data))
.catch(() => Flash(s__('Metrics|There was an error getting environments information.'))),
])
.then(() => {
@@ -145,6 +157,7 @@ export default {
this.state = 'noData';
return;
}
+
this.showEmptyState = false;
})
.then(this.resize)
@@ -153,14 +166,7 @@ export default {
});
},
resize() {
- this.updateAspectRatio = true;
- },
- toggleAspectRatio() {
- this.updatedAspectRatios += 1;
- if (this.store.getMetricsCount() === this.updatedAspectRatios) {
- this.updateAspectRatio = !this.updateAspectRatio;
- this.updatedAspectRatios = 0;
- }
+ this.elWidth = this.$el.clientWidth;
},
hoverChanged(data) {
this.hoverData = data;
@@ -170,31 +176,19 @@ export default {
</script>
<template>
- <div
- v-if="!showEmptyState"
- class="prometheus-graphs prepend-top-default"
- >
+ <div v-if="!showEmptyState" :key="forceRedraw" class="prometheus-graphs prepend-top-default">
<div class="environments d-flex align-items-center">
{{ s__('Metrics|Environment') }}
<div class="dropdown prepend-left-10">
- <button
- class="dropdown-menu-toggle"
- data-toggle="dropdown"
- type="button"
- >
- <span>
- {{ currentEnvironmentName }}
- </span>
- <icon
- name="chevron-down"
- />
+ <button class="dropdown-menu-toggle" data-toggle="dropdown" type="button">
+ <span> {{ currentEnvironmentName }} </span> <icon name="chevron-down" />
</button>
- <div class="dropdown-menu dropdown-menu-selectable dropdown-menu-drop-up">
+ <div
+ v-if="store.environmentsData.length > 0"
+ class="dropdown-menu dropdown-menu-selectable dropdown-menu-drop-up"
+ >
<ul>
- <li
- v-for="environment in store.environmentsData"
- :key="environment.latest.id"
- >
+ <li v-for="environment in store.environmentsData" :key="environment.latest.id">
<a
:href="environment.latest.metrics_path"
:class="{ 'is-active': environment.latest.name == currentEnvironmentName }"
@@ -214,11 +208,10 @@ export default {
:show-panels="showPanels"
>
<graph
- v-for="(graphData, index) in groupData.metrics"
- :key="index"
+ v-for="(graphData, graphIndex) in groupData.metrics"
+ :key="graphIndex"
:graph-data="graphData"
:hover-data="hoverData"
- :update-aspect-ratio="updateAspectRatio"
:deployment-data="store.deploymentData"
:project-path="projectPath"
:tags-path="tagsPath"
diff --git a/app/assets/javascripts/monitoring/components/empty_state.vue b/app/assets/javascripts/monitoring/components/empty_state.vue
index 82b9a4b1adb..0e141d02ead 100644
--- a/app/assets/javascripts/monitoring/components/empty_state.vue
+++ b/app/assets/javascripts/monitoring/components/empty_state.vue
@@ -44,9 +44,9 @@ export default {
title: 'Get started with performance monitoring',
description: `Stay updated about the performance and health
of your environment by configuring Prometheus to monitor your deployments.`,
- buttonText: 'Install Prometheus on clusters',
+ buttonText: 'Install on clusters',
buttonPath: this.clustersPath,
- secondaryButtonText: 'Configure existing Prometheus',
+ secondaryButtonText: 'Configure existing installation',
secondaryButtonPath: this.settingsPath,
},
loading: {
@@ -88,39 +88,32 @@ export default {
</script>
<template>
- <div class="prometheus-state">
- <div class="state-svg svg-content">
- <img :src="currentState.svgUrl" />
+ <div class="row empty-state js-empty-state">
+ <div class="col-12">
+ <div class="state-svg svg-content"><img :src="currentState.svgUrl" /></div>
</div>
- <h4 class="state-title">
- {{ currentState.title }}
- </h4>
- <p class="state-description">
- {{ currentState.description }}
- <a
- v-if="showButtonDescription"
- :href="settingsPath"
- >
- Prometheus server
- </a>
- </p>
- <div class="state-button">
- <a
- v-if="currentState.buttonPath"
- :href="currentState.buttonPath"
- class="btn btn-success"
- >
- {{ currentState.buttonText }}
- </a>
- </div>
- <div class="state-button">
- <a
- v-if="currentState.secondaryButtonPath"
- :href="currentState.secondaryButtonPath"
- class="btn"
- >
- {{ currentState.secondaryButtonText }}
- </a>
+
+ <div class="col-12">
+ <div class="text-content">
+ <h4 class="state-title text-center">{{ currentState.title }}</h4>
+ <p class="state-description">
+ {{ currentState.description }}
+ <a v-if="showButtonDescription" :href="settingsPath"> Prometheus server </a>
+ </p>
+
+ <div class="text-center">
+ <a v-if="currentState.buttonPath" :href="currentState.buttonPath" class="btn btn-success">
+ {{ currentState.buttonText }}
+ </a>
+ <a
+ v-if="currentState.secondaryButtonPath"
+ :href="currentState.secondaryButtonPath"
+ class="btn"
+ >
+ {{ currentState.secondaryButtonText }}
+ </a>
+ </div>
+ </div>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/monitoring/components/graph.vue b/app/assets/javascripts/monitoring/components/graph.vue
index a13f30e6079..64a1df80a8e 100644
--- a/app/assets/javascripts/monitoring/components/graph.vue
+++ b/app/assets/javascripts/monitoring/components/graph.vue
@@ -32,10 +32,6 @@ export default {
type: Object,
required: true,
},
- updateAspectRatio: {
- type: Boolean,
- required: true,
- },
deploymentData: {
type: Array,
required: true,
@@ -86,6 +82,7 @@ export default {
showFlag: false,
showFlagContent: false,
timeSeries: [],
+ graphDrawData: {},
realPixelRatio: 1,
seriesUnderMouse: [],
};
@@ -108,17 +105,11 @@ export default {
deploymentFlagData() {
return this.reducedDeploymentData.find(deployment => deployment.showDeploymentFlag);
},
+ shouldRenderData() {
+ return this.graphData.queries.filter(s => s.result.length > 0).length > 0;
+ },
},
watch: {
- updateAspectRatio() {
- if (this.updateAspectRatio) {
- this.graphHeight = 450;
- this.graphWidth = 600;
- this.measurements = measurements.large;
- this.draw();
- eventHub.$emit('toggleAspectRatio');
- }
- },
hoverData() {
this.positionFlag();
},
@@ -132,26 +123,34 @@ export default {
},
draw() {
const breakpointSize = bp.getBreakpointSize();
- const query = this.graphData.queries[0];
+ const svgWidth = this.$refs.baseSvg.getBoundingClientRect().width;
+
this.margin = measurements.large.margin;
+
if (this.smallGraph || breakpointSize === 'xs' || breakpointSize === 'sm') {
this.graphHeight = 300;
this.margin = measurements.small.margin;
this.measurements = measurements.small;
}
- this.unitOfDisplay = query.unit || '';
+
this.yAxisLabel = this.graphData.y_label || 'Values';
- this.legendTitle = query.label || 'Average';
- this.graphWidth = this.$refs.baseSvg.clientWidth - this.margin.left - this.margin.right;
+ this.graphWidth = svgWidth - this.margin.left - this.margin.right;
this.graphHeight = this.graphHeight - this.margin.top - this.margin.bottom;
this.baseGraphHeight = this.graphHeight - 50;
this.baseGraphWidth = this.graphWidth;
// pixel offsets inside the svg and outside are not 1:1
- this.realPixelRatio = this.$refs.baseSvg.clientWidth / this.baseGraphWidth;
+ this.realPixelRatio = svgWidth / this.baseGraphWidth;
- this.renderAxesPaths();
- this.formatDeployments();
+ // set the legends on the axes
+ const [query] = this.graphData.queries;
+ this.legendTitle = query ? query.label : 'Average';
+ this.unitOfDisplay = query ? query.unit : '';
+
+ if (this.shouldRenderData) {
+ this.renderAxesPaths();
+ this.formatDeployments();
+ }
},
handleMouseOverGraph(e) {
let point = this.$refs.graphData.createSVGPoint();
@@ -160,7 +159,7 @@ export default {
point = point.matrixTransform(this.$refs.graphData.getScreenCTM().inverse());
point.x += 7;
- this.seriesUnderMouse = this.timeSeries.filter((series) => {
+ this.seriesUnderMouse = this.timeSeries.filter(series => {
const mouseX = series.timeSeriesScaleX.invert(point.x);
let minDistance = Infinity;
@@ -193,12 +192,12 @@ export default {
});
},
renderAxesPaths() {
- this.timeSeries = createTimeSeries(
+ ({ timeSeries: this.timeSeries, graphDrawData: this.graphDrawData } = createTimeSeries(
this.graphData.queries,
this.graphWidth,
this.graphHeight,
this.graphHeightOffset,
- );
+ ));
if (_.findWhere(this.timeSeries, { renderCanary: true })) {
this.timeSeries = this.timeSeries.map(series => ({ ...series, renderCanary: true }));
@@ -233,21 +232,18 @@ export default {
.scale(axisYScale)
.ticks(measurements.yTicks);
- d3
- .select(this.$refs.baseSvg)
+ d3.select(this.$refs.baseSvg)
.select('.x-axis')
.call(xAxis);
const width = this.graphWidth;
- d3
- .select(this.$refs.baseSvg)
+ d3.select(this.$refs.baseSvg)
.select('.y-axis')
.call(yAxis)
.selectAll('.tick')
.each(function createTickLines(d, i) {
if (i > 0) {
- d3
- .select(this)
+ d3.select(this)
.select('line')
.attr('x2', width)
.attr('class', 'axis-tick');
@@ -261,33 +257,17 @@ export default {
<template>
<div
class="prometheus-graph"
- @mouseover="showFlagContent = true"
- @mouseleave="showFlagContent = false"
+ @mouseover="showFlagContent = true;"
+ @mouseleave="showFlagContent = false;"
>
<div class="prometheus-graph-header">
- <h5 class="prometheus-graph-title">
- {{ graphData.title }}
- </h5>
- <div class="prometheus-graph-widgets">
- <slot></slot>
- </div>
+ <h5 class="prometheus-graph-title">{{ graphData.title }}</h5>
+ <div class="prometheus-graph-widgets"><slot></slot></div>
</div>
- <div
- :style="paddingBottomRootSvg"
- class="prometheus-svg-container"
- >
- <svg
- ref="baseSvg"
- :viewBox="outerViewBox"
- >
- <g
- :transform="axisTransform"
- class="x-axis"
- />
- <g
- class="y-axis"
- transform="translate(70, 20)"
- />
+ <div :style="paddingBottomRootSvg" class="prometheus-svg-container">
+ <svg ref="baseSvg" :viewBox="outerViewBox">
+ <g :transform="axisTransform" class="x-axis" />
+ <g class="y-axis" transform="translate(70, 20)" />
<graph-axis
:graph-width="graphWidth"
:graph-height="graphHeight"
@@ -296,11 +276,8 @@ export default {
:y-axis-label="yAxisLabel"
:unit-of-display="unitOfDisplay"
/>
- <svg
- ref="graphData"
- :viewBox="innerViewBox"
- class="graph-data"
- >
+ <svg v-if="shouldRenderData" ref="graphData" :viewBox="innerViewBox" class="graph-data">
+ <slot name="additionalSvgContent" :graphDrawData="graphDrawData" />
<graph-path
v-for="(path, index) in timeSeries"
:key="index"
@@ -319,15 +296,21 @@ export default {
/>
<rect
ref="graphOverlay"
- :width="(graphWidth - 70)"
- :height="(graphHeight - 100)"
+ :width="graphWidth - 70"
+ :height="graphHeight - 100"
class="prometheus-graph-overlay"
transform="translate(-5, 20)"
- @mousemove="handleMouseOverGraph($event)"
+ @mousemove="handleMouseOverGraph($event);"
/>
</svg>
+ <svg v-else :viewBox="innerViewBox" class="js-no-data-to-display">
+ <text x="50%" y="50%" alignment-baseline="middle" text-anchor="middle">
+ {{ s__('Metrics|No data to display') }}
+ </text>
+ </svg>
</svg>
<graph-flag
+ v-if="shouldRenderData"
:real-pixel-ratio="realPixelRatio"
:current-x-coordinate="currentXCoordinate"
:current-data="currentData"
@@ -341,10 +324,6 @@ export default {
:current-coordinates="currentCoordinates"
/>
</div>
- <graph-legend
- v-if="showLegend"
- :legend-title="legendTitle"
- :time-series="timeSeries"
- />
+ <graph-legend v-if="showLegend" :legend-title="legendTitle" :time-series="timeSeries" />
</div>
</template>
diff --git a/app/assets/javascripts/monitoring/components/graph/axis.vue b/app/assets/javascripts/monitoring/components/graph/axis.vue
index 8a604a51eb2..8f046857a20 100644
--- a/app/assets/javascripts/monitoring/components/graph/axis.vue
+++ b/app/assets/javascripts/monitoring/components/graph/axis.vue
@@ -38,38 +38,25 @@ export default {
computed: {
textTransform() {
const yCoordinate =
- (this.graphHeight -
- this.margin.top +
- this.measurements.axisLabelLineOffset) /
- 2 || 0;
+ (this.graphHeight - this.margin.top + this.measurements.axisLabelLineOffset) / 2 || 0;
return `translate(15, ${yCoordinate}) rotate(-90)`;
},
rectTransform() {
const yCoordinate =
- (this.graphHeight -
- this.margin.top +
- this.measurements.axisLabelLineOffset) /
- 2 +
+ (this.graphHeight - this.margin.top + this.measurements.axisLabelLineOffset) / 2 +
this.yLabelWidth / 2 || 0;
return `translate(0, ${yCoordinate}) rotate(-90)`;
},
xPosition() {
- return (
- (this.graphWidth + this.measurements.axisLabelLineOffset) / 2 -
- this.margin.right || 0
- );
+ return (this.graphWidth + this.measurements.axisLabelLineOffset) / 2 - this.margin.right || 0;
},
yPosition() {
- return (
- this.graphHeight -
- this.margin.top +
- this.measurements.axisLabelLineOffset || 0
- );
+ return this.graphHeight - this.margin.top + this.measurements.axisLabelLineOffset || 0;
},
yAxisLabelSentenceCase() {
@@ -123,19 +110,8 @@ export default {
>
{{ yAxisLabelSentenceCase }}
</text>
- <rect
- :x="xPosition + 60"
- :y="graphHeight - 80"
- class="rect-axis-text"
- width="35"
- height="50"
- />
- <text
- :x="xPosition + 60"
- :y="yPosition"
- class="label-axis-text x-label-text"
- dy=".35em"
- >
+ <rect :x="xPosition + 60" :y="graphHeight - 80" class="rect-axis-text" width="35" height="50" />
+ <text :x="xPosition + 60" :y="yPosition" class="label-axis-text x-label-text" dy=".35em">
{{ timeString }}
</text>
</g>
diff --git a/app/assets/javascripts/monitoring/components/graph/deployment.vue b/app/assets/javascripts/monitoring/components/graph/deployment.vue
index a7289ed53e8..bee9784692c 100644
--- a/app/assets/javascripts/monitoring/components/graph/deployment.vue
+++ b/app/assets/javascripts/monitoring/components/graph/deployment.vue
@@ -31,41 +31,16 @@ export default {
<g
v-for="(deployment, index) in deploymentData"
:key="index"
- :transform="transformDeploymentGroup(deployment)">
- <rect
- :height="calculatedHeight"
- x="0"
- y="0"
- width="3"
- fill="url(#shadow-gradient)"
- />
- <line
- :y2="calculatedHeight"
- class="deployment-line"
- x1="0"
- y1="0"
- x2="0"
- stroke="#000"
- />
- </g>
- <svg
- height="0"
- width="0"
+ :transform="transformDeploymentGroup(deployment)"
>
+ <rect :height="calculatedHeight" x="0" y="0" width="3" fill="url(#shadow-gradient)" />
+ <line :y2="calculatedHeight" class="deployment-line" x1="0" y1="0" x2="0" stroke="#000" />
+ </g>
+ <svg height="0" width="0">
<defs>
- <linearGradient
- id="shadow-gradient"
- >
- <stop
- offset="0%"
- stop-color="#000"
- stop-opacity="0.4"
- />
- <stop
- offset="100%"
- stop-color="#000"
- stop-opacity="0"
- />
+ <linearGradient id="shadow-gradient">
+ <stop offset="0%" stop-color="#000" stop-opacity="0.4" />
+ <stop offset="100%" stop-color="#000" stop-opacity="0" />
</linearGradient>
</defs>
</svg>
diff --git a/app/assets/javascripts/monitoring/components/graph/flag.vue b/app/assets/javascripts/monitoring/components/graph/flag.vue
index 5f00d20ca3f..9d6d1caef80 100644
--- a/app/assets/javascripts/monitoring/components/graph/flag.vue
+++ b/app/assets/javascripts/monitoring/components/graph/flag.vue
@@ -92,7 +92,8 @@ export default {
methods: {
seriesMetricValue(seriesIndex, series) {
const indexFromCoordinates = this.currentCoordinates[series.metricTag]
- ? this.currentCoordinates[series.metricTag].currentDataIndex : 0;
+ ? this.currentCoordinates[series.metricTag].currentDataIndex
+ : 0;
const index = this.deploymentFlagData
? this.deploymentFlagData.seriesIndex
: indexFromCoordinates;
@@ -116,59 +117,29 @@ export default {
</script>
<template>
- <div
- :style="cursorStyle"
- class="prometheus-graph-cursor"
- >
- <div
- v-if="showFlagContent"
- :class="flagOrientation"
- class="prometheus-graph-flag popover"
- >
+ <div :style="cursorStyle" class="prometheus-graph-cursor">
+ <div v-if="showFlagContent" :class="flagOrientation" class="prometheus-graph-flag popover">
<div class="arrow-shadow"></div>
<div class="arrow"></div>
<div class="popover-title">
- <h5 v-if="deploymentFlagData">
- Deployed
- </h5>
- {{ formatDate }}
- <strong>{{ formatTime }}</strong>
+ <h5 v-if="deploymentFlagData">Deployed</h5>
+ {{ formatDate }} <strong>{{ formatTime }}</strong>
</div>
- <div
- v-if="deploymentFlagData"
- class="popover-content deploy-meta-content"
- >
+ <div v-if="deploymentFlagData" class="popover-content deploy-meta-content">
<div>
- <icon
- :size="12"
- name="commit"
- />
- <a :href="deploymentFlagData.commitUrl">
- {{ deploymentFlagData.sha.slice(0, 8) }}
- </a>
+ <icon :size="12" name="commit" />
+ <a :href="deploymentFlagData.commitUrl"> {{ deploymentFlagData.sha.slice(0, 8) }} </a>
</div>
- <div
- v-if="deploymentFlagData.tag"
- >
- <icon
- :size="12"
- name="label"
- />
- <a :href="deploymentFlagData.tagUrl">
- {{ deploymentFlagData.ref }}
- </a>
+ <div v-if="deploymentFlagData.tag">
+ <icon :size="12" name="label" />
+ <a :href="deploymentFlagData.tagUrl"> {{ deploymentFlagData.ref }} </a>
</div>
</div>
<div class="popover-content">
<table class="prometheus-table">
- <tr
- v-for="(series, index) in timeSeries"
- :key="index"
- >
- <track-line :track="series"/>
- <td>
- {{ series.track }} {{ seriesMetricLabel(index, series) }}
- </td>
+ <tr v-for="(series, index) in timeSeries" :key="index">
+ <track-line :track="series" />
+ <td>{{ series.track }} {{ seriesMetricLabel(index, series) }}</td>
<td>
<strong>{{ seriesMetricValue(index, series) }}</strong>
</td>
diff --git a/app/assets/javascripts/monitoring/components/graph/legend.vue b/app/assets/javascripts/monitoring/components/graph/legend.vue
index 3276f3a1ceb..b5211c306a3 100644
--- a/app/assets/javascripts/monitoring/components/graph/legend.vue
+++ b/app/assets/javascripts/monitoring/components/graph/legend.vue
@@ -39,15 +39,9 @@ export default {
<strong v-if="series.renderCanary">{{ series.trackName }}</strong>
</td>
<track-line :track="series" />
- <td
- v-if="timeSeries.length > 1"
- class="legend-metric-title">
- <track-info
- v-if="series.metricTag"
- :track="series" />
- <track-info
- v-else
- :track="series">
+ <td v-if="timeSeries.length > 1" class="legend-metric-title">
+ <track-info v-if="series.metricTag" :track="series" />
+ <track-info v-else :track="series">
<strong>{{ legendTitle }}</strong> series {{ index + 1 }}
</track-info>
</td>
@@ -57,13 +51,9 @@ export default {
</track-info>
</td>
<template v-for="(track, trackIndex) in series.tracksLegend">
- <track-line
- :track="track"
- :key="`track-line-${trackIndex}`"/>
+ <track-line :key="`track-line-${trackIndex}`" :track="track" />
<td :key="`track-info-${trackIndex}`">
- <track-info
- :track="track"
- class="legend-metric-title" />
+ <track-info :track="track" class="legend-metric-title" />
</td>
</template>
</tr>
diff --git a/app/assets/javascripts/monitoring/components/graph/path.vue b/app/assets/javascripts/monitoring/components/graph/path.vue
index a9b7ce586ce..f2c237ec391 100644
--- a/app/assets/javascripts/monitoring/components/graph/path.vue
+++ b/app/assets/javascripts/monitoring/components/graph/path.vue
@@ -52,11 +52,7 @@ export default {
class="circle-path"
r="3"
/>
- <path
- :d="generatedAreaPath"
- :fill="areaColor"
- class="metric-area"
- />
+ <path :d="generatedAreaPath" :fill="areaColor" class="metric-area" />
<path
:d="generatedLinePath"
:stroke="lineColor"
diff --git a/app/assets/javascripts/monitoring/components/graph/track_info.vue b/app/assets/javascripts/monitoring/components/graph/track_info.vue
index ec1c2222af9..3464067834f 100644
--- a/app/assets/javascripts/monitoring/components/graph/track_info.vue
+++ b/app/assets/javascripts/monitoring/components/graph/track_info.vue
@@ -26,4 +26,3 @@ export default {
{{ summaryMetrics }}
</span>
</template>
-
diff --git a/app/assets/javascripts/monitoring/components/graph/track_line.vue b/app/assets/javascripts/monitoring/components/graph/track_line.vue
index ba3f93b39ff..d2ed1ba113e 100644
--- a/app/assets/javascripts/monitoring/components/graph/track_line.vue
+++ b/app/assets/javascripts/monitoring/components/graph/track_line.vue
@@ -18,9 +18,7 @@ export default {
</script>
<template>
<td>
- <svg
- width="16"
- height="8">
+ <svg width="16" height="8">
<line
:stroke-dasharray="stylizedLine"
:stroke="track.lineColor"
@@ -33,4 +31,3 @@ export default {
</svg>
</td>
</template>
-
diff --git a/app/assets/javascripts/monitoring/components/graph_group.vue b/app/assets/javascripts/monitoring/components/graph_group.vue
index 241627f9790..b20ad1802f3 100644
--- a/app/assets/javascripts/monitoring/components/graph_group.vue
+++ b/app/assets/javascripts/monitoring/components/graph_group.vue
@@ -15,21 +15,11 @@ export default {
</script>
<template>
- <div
- v-if="showPanels"
- class="card prometheus-panel"
- >
+ <div v-if="showPanels" class="card prometheus-panel">
<div class="card-header">
<h4>{{ name }}</h4>
</div>
- <div class="card-body prometheus-graph-group">
- <slot></slot>
- </div>
- </div>
- <div
- v-else
- class="prometheus-graph-group"
- >
- <slot></slot>
+ <div class="card-body prometheus-graph-group"><slot></slot></div>
</div>
+ <div v-else class="prometheus-graph-group"><slot></slot></div>
</template>
diff --git a/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js b/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js
index 007451d5c7a..87c3d969de4 100644
--- a/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js
+++ b/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js
@@ -6,7 +6,7 @@ const mixins = {
if (!this.reducedDeploymentData) return false;
let dataFound = false;
- this.reducedDeploymentData = this.reducedDeploymentData.map((d) => {
+ this.reducedDeploymentData = this.reducedDeploymentData.map(d => {
const deployment = d;
if (d.xPos >= mouseXPos - 10 && d.xPos <= mouseXPos + 10 && !dataFound) {
dataFound = d.xPos + 1;
@@ -61,7 +61,7 @@ const mixins = {
this.currentCoordinates = {};
- this.seriesUnderMouse.forEach((series) => {
+ this.seriesUnderMouse.forEach(series => {
const currentDataIndex = bisectDate(series.values, this.hoverData.hoveredDate);
const currentData = series.values[currentDataIndex];
const currentX = Math.floor(series.timeSeriesScaleX(currentData.time));
diff --git a/app/assets/javascripts/monitoring/monitoring_bundle.js b/app/assets/javascripts/monitoring/monitoring_bundle.js
index 41270e015d4..9d78b5ea110 100644
--- a/app/assets/javascripts/monitoring/monitoring_bundle.js
+++ b/app/assets/javascripts/monitoring/monitoring_bundle.js
@@ -1,5 +1,5 @@
import Vue from 'vue';
-import { convertPermissionToBoolean } from '~/lib/utils/common_utils';
+import { parseBoolean } from '~/lib/utils/common_utils';
import Dashboard from './components/dashboard.vue';
export default () => {
@@ -13,7 +13,7 @@ export default () => {
return createElement(Dashboard, {
props: {
...el.dataset,
- hasMetrics: convertPermissionToBoolean(el.dataset.hasMetrics),
+ hasMetrics: parseBoolean(el.dataset.hasMetrics),
},
});
},
diff --git a/app/assets/javascripts/monitoring/services/monitoring_service.js b/app/assets/javascripts/monitoring/services/monitoring_service.js
index 260d424378e..24b4acaf6da 100644
--- a/app/assets/javascripts/monitoring/services/monitoring_service.js
+++ b/app/assets/javascripts/monitoring/services/monitoring_service.js
@@ -8,18 +8,20 @@ const MAX_REQUESTS = 3;
function backOffRequest(makeRequestCallback) {
let requestCounter = 0;
return backOff((next, stop) => {
- makeRequestCallback().then((resp) => {
- if (resp.status === statusCodes.NO_CONTENT) {
- requestCounter += 1;
- if (requestCounter < MAX_REQUESTS) {
- next();
+ makeRequestCallback()
+ .then(resp => {
+ if (resp.status === statusCodes.NO_CONTENT) {
+ requestCounter += 1;
+ if (requestCounter < MAX_REQUESTS) {
+ next();
+ } else {
+ stop(new Error('Failed to connect to the prometheus server'));
+ }
} else {
- stop(new Error('Failed to connect to the prometheus server'));
+ stop(resp);
}
- } else {
- stop(resp);
- }
- }).catch(stop);
+ })
+ .catch(stop);
});
}
@@ -33,7 +35,7 @@ export default class MonitoringService {
getGraphsData() {
return backOffRequest(() => axios.get(this.metricsEndpoint))
.then(resp => resp.data)
- .then((response) => {
+ .then(response => {
if (!response || !response.data) {
throw new Error(s__('Metrics|Unexpected metrics data response from prometheus endpoint'));
}
@@ -47,22 +49,27 @@ export default class MonitoringService {
}
return backOffRequest(() => axios.get(this.deploymentEndpoint))
.then(resp => resp.data)
- .then((response) => {
+ .then(response => {
if (!response || !response.deployments) {
- throw new Error(s__('Metrics|Unexpected deployment data response from prometheus endpoint'));
+ throw new Error(
+ s__('Metrics|Unexpected deployment data response from prometheus endpoint'),
+ );
}
return response.deployments;
});
}
getEnvironmentsData() {
- return axios.get(this.environmentsEndpoint)
- .then(resp => resp.data)
- .then((response) => {
- if (!response || !response.environments) {
- throw new Error(s__('Metrics|There was an error fetching the environments data, please try again'));
- }
- return response.environments;
- });
+ return axios
+ .get(this.environmentsEndpoint)
+ .then(resp => resp.data)
+ .then(response => {
+ if (!response || !response.environments) {
+ throw new Error(
+ s__('Metrics|There was an error fetching the environments data, please try again'),
+ );
+ }
+ return response.environments;
+ });
}
}
diff --git a/app/assets/javascripts/monitoring/stores/monitoring_store.js b/app/assets/javascripts/monitoring/stores/monitoring_store.js
index 176f7d9eef2..8692c873a41 100644
--- a/app/assets/javascripts/monitoring/stores/monitoring_store.js
+++ b/app/assets/javascripts/monitoring/stores/monitoring_store.js
@@ -7,10 +7,29 @@ function sortMetrics(metrics) {
.value();
}
+function checkQueryEmptyData(query) {
+ return {
+ ...query,
+ result: query.result.filter(timeSeries => {
+ const newTimeSeries = timeSeries;
+ const hasValue = series =>
+ !Number.isNaN(series.value) && (series.value !== null || series.value !== undefined);
+ const hasNonNullValue = timeSeries.values.find(hasValue);
+
+ newTimeSeries.values = hasNonNullValue ? newTimeSeries.values : [];
+
+ return newTimeSeries.values.length > 0;
+ }),
+ };
+}
+
+function removeTimeSeriesNoData(queries) {
+ return queries.reduce((series, query) => series.concat(checkQueryEmptyData(query)), []);
+}
+
function normalizeMetrics(metrics) {
- return metrics.map(metric => ({
- ...metric,
- queries: metric.queries.map(query => ({
+ return metrics.map(metric => {
+ const queries = metric.queries.map(query => ({
...query,
result: query.result.map(result => ({
...result,
@@ -19,8 +38,13 @@ function normalizeMetrics(metrics) {
value: Number(value),
})),
})),
- })),
- }));
+ }));
+
+ return {
+ ...metric,
+ queries: removeTimeSeriesNoData(queries),
+ };
+ });
}
export default class MonitoringStore {
diff --git a/app/assets/javascripts/monitoring/utils/measurements.js b/app/assets/javascripts/monitoring/utils/measurements.js
index ee866850e13..7c771f43eee 100644
--- a/app/assets/javascripts/monitoring/utils/measurements.js
+++ b/app/assets/javascripts/monitoring/utils/measurements.js
@@ -1,5 +1,6 @@
export default {
- small: { // Covers both xs and sm screen sizes
+ small: {
+ // Covers both xs and sm screen sizes
margin: {
top: 40,
right: 40,
@@ -18,7 +19,8 @@ export default {
},
axisLabelLineOffset: -20,
},
- large: { // This covers both md and lg screen sizes
+ large: {
+ // This covers both md and lg screen sizes
margin: {
top: 80,
right: 80,
diff --git a/app/assets/javascripts/monitoring/utils/multiple_time_series.js b/app/assets/javascripts/monitoring/utils/multiple_time_series.js
index eff0d7325cd..bb24a1acdb3 100644
--- a/app/assets/javascripts/monitoring/utils/multiple_time_series.js
+++ b/app/assets/javascripts/monitoring/utils/multiple_time_series.js
@@ -30,7 +30,7 @@ const defaultColorOrder = ['blue', 'orange', 'red', 'green', 'purple'];
const defaultStyleOrder = ['solid', 'dashed', 'dotted'];
-function queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom, yDom, lineStyle) {
+function queryTimeSeries(query, graphDrawData, lineStyle) {
let usedColors = [];
let renderCanary = false;
const timeSeriesParsed = [];
@@ -64,9 +64,10 @@ function queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom
// but we need a regularly-spaced set of time/value pairs
// this gives us a complete range of one minute intervals
// offset the same amount as the original data
- const [minX, maxX] = xDom;
+ const [minX, maxX] = graphDrawData.xDom;
const offset = d3.timeMinute(minX) - Number(minX);
- const datesWithoutGaps = d3.timeSecond.every(60)
+ const datesWithoutGaps = d3.timeSecond
+ .every(60)
.range(d3.timeMinute.offset(minX, -1), maxX)
.map(d => d - offset);
@@ -84,31 +85,6 @@ function queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom
renderCanary = true;
}
- const timeSeriesScaleX = d3.scaleTime().range([0, graphWidth - 70]);
-
- const timeSeriesScaleY = d3.scaleLinear().range([graphHeight - graphHeightOffset, 0]);
-
- timeSeriesScaleX.domain(xDom);
- timeSeriesScaleX.ticks(d3.timeMinute, 60);
- timeSeriesScaleY.domain(yDom);
-
- const defined = d => !Number.isNaN(d.value) && d.value != null;
-
- const lineFunction = d3
- .line()
- .defined(defined)
- .curve(d3.curveLinear) // d3 v4 uses curbe instead of interpolate
- .x(d => timeSeriesScaleX(d.time))
- .y(d => timeSeriesScaleY(d.value));
-
- const areaFunction = d3
- .area()
- .defined(defined)
- .curve(d3.curveLinear)
- .x(d => timeSeriesScaleX(d.time))
- .y0(graphHeight - graphHeightOffset)
- .y1(d => timeSeriesScaleY(d.value));
-
const timeSeriesMetricLabel = timeSeries.metric[Object.keys(timeSeries.metric)[0]];
const seriesCustomizationData =
query.series != null && _.findWhere(query.series[0].when, { value: timeSeriesMetricLabel });
@@ -144,10 +120,10 @@ function queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom
}));
timeSeriesParsed.push({
- linePath: lineFunction(values),
- areaPath: areaFunction(values),
- timeSeriesScaleX,
- timeSeriesScaleY,
+ linePath: graphDrawData.lineFunction(values),
+ areaPath: graphDrawData.areaBelowLine(values),
+ timeSeriesScaleX: graphDrawData.timeSeriesScaleX,
+ timeSeriesScaleY: graphDrawData.timeSeriesScaleY,
values: timeSeries.values,
max: maximumValue,
average: accum / timeSeries.values.length,
@@ -164,7 +140,7 @@ function queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom
return timeSeriesParsed;
}
-export default function createTimeSeries(queries, graphWidth, graphHeight, graphHeightOffset) {
+function xyDomain(queries) {
const allValues = queries.reduce(
(allQueryResults, query) =>
allQueryResults.concat(
@@ -176,10 +152,68 @@ export default function createTimeSeries(queries, graphWidth, graphHeight, graph
const xDom = d3.extent(allValues, d => d.time);
const yDom = [0, d3.max(allValues.map(d => d.value))];
- return queries.reduce((series, query, index) => {
+ return {
+ xDom,
+ yDom,
+ };
+}
+
+export function generateGraphDrawData(queries, graphWidth, graphHeight, graphHeightOffset) {
+ const { xDom, yDom } = xyDomain(queries);
+
+ const timeSeriesScaleX = d3.scaleTime().range([0, graphWidth - 70]);
+ const timeSeriesScaleY = d3.scaleLinear().range([graphHeight - graphHeightOffset, 0]);
+
+ timeSeriesScaleX.domain(xDom);
+ timeSeriesScaleX.ticks(d3.timeMinute, 60);
+ timeSeriesScaleY.domain(yDom);
+
+ const defined = d => !Number.isNaN(d.value) && d.value != null;
+
+ const lineFunction = d3
+ .line()
+ .defined(defined)
+ .curve(d3.curveLinear) // d3 v4 uses curbe instead of interpolate
+ .x(d => timeSeriesScaleX(d.time))
+ .y(d => timeSeriesScaleY(d.value));
+
+ const areaBelowLine = d3
+ .area()
+ .defined(defined)
+ .curve(d3.curveLinear)
+ .x(d => timeSeriesScaleX(d.time))
+ .y0(graphHeight - graphHeightOffset)
+ .y1(d => timeSeriesScaleY(d.value));
+
+ const areaAboveLine = d3
+ .area()
+ .defined(defined)
+ .curve(d3.curveLinear)
+ .x(d => timeSeriesScaleX(d.time))
+ .y0(0)
+ .y1(d => timeSeriesScaleY(d.value));
+
+ return {
+ lineFunction,
+ areaBelowLine,
+ areaAboveLine,
+ xDom,
+ yDom,
+ timeSeriesScaleX,
+ timeSeriesScaleY,
+ };
+}
+
+export default function createTimeSeries(queries, graphWidth, graphHeight, graphHeightOffset) {
+ const graphDrawData = generateGraphDrawData(queries, graphWidth, graphHeight, graphHeightOffset);
+
+ const timeSeries = queries.reduce((series, query, index) => {
const lineStyle = defaultStyleOrder[index % defaultStyleOrder.length];
- return series.concat(
- queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom, yDom, lineStyle),
- );
+ return series.concat(queryTimeSeries(query, graphDrawData, lineStyle));
}, []);
+
+ return {
+ timeSeries,
+ graphDrawData,
+ };
}
diff --git a/app/assets/javascripts/mr_notes/index.js b/app/assets/javascripts/mr_notes/index.js
index 8aabb840847..1c98683c597 100644
--- a/app/assets/javascripts/mr_notes/index.js
+++ b/app/assets/javascripts/mr_notes/index.js
@@ -4,6 +4,7 @@ import { mapActions, mapState, mapGetters } from 'vuex';
import initDiffsApp from '../diffs';
import notesApp from '../notes/components/notes_app.vue';
import discussionCounter from '../notes/components/discussion_counter.vue';
+import initDiscussionFilters from '../notes/discussion_filters';
import store from './stores';
import MergeRequest from '../merge_request';
@@ -88,5 +89,6 @@ export default function initMrNotes() {
},
});
+ initDiscussionFilters(store);
initDiffsApp(store);
}
diff --git a/app/assets/javascripts/mr_notes/stores/index.js b/app/assets/javascripts/mr_notes/stores/index.js
index 446eb477efc..c4225c8ec08 100644
--- a/app/assets/javascripts/mr_notes/stores/index.js
+++ b/app/assets/javascripts/mr_notes/stores/index.js
@@ -6,10 +6,13 @@ import mrPageModule from './modules';
Vue.use(Vuex);
-export default new Vuex.Store({
- modules: {
- page: mrPageModule,
- notes: notesModule(),
- diffs: diffsModule(),
- },
-});
+export const createStore = () =>
+ new Vuex.Store({
+ modules: {
+ page: mrPageModule,
+ notes: notesModule(),
+ diffs: diffsModule(),
+ },
+ });
+
+export default createStore();
diff --git a/app/assets/javascripts/namespace_select.js b/app/assets/javascripts/namespace_select.js
index 17370edeb0c..ee1a5274ff7 100644
--- a/app/assets/javascripts/namespace_select.js
+++ b/app/assets/javascripts/namespace_select.js
@@ -1,12 +1,13 @@
-/* eslint-disable func-names, comma-dangle, object-shorthand, no-else-return, prefer-template, quotes, prefer-arrow-callback, max-len */
+/* eslint-disable func-names, object-shorthand, no-else-return, prefer-template, prefer-arrow-callback */
import $ from 'jquery';
import Api from './api';
import { mergeUrlParams } from './lib/utils/url_utility';
+import { parseBoolean } from '~/lib/utils/common_utils';
export default class NamespaceSelect {
constructor(opts) {
- const isFilter = opts.dropdown.dataset.isFilter === 'true';
+ const isFilter = parseBoolean(opts.dropdown.dataset.isFilter);
const fieldName = opts.dropdown.dataset.fieldName || 'namespace_id';
$(opts.dropdown).glDropdown({
@@ -14,14 +15,14 @@ export default class NamespaceSelect {
selectable: true,
filterRemote: true,
search: {
- fields: ['path']
+ fields: ['path'],
},
fieldName: fieldName,
toggleLabel: function(selected) {
if (selected.id == null) {
return selected.text;
} else {
- return selected.kind + ": " + selected.full_path;
+ return selected.kind + ': ' + selected.full_path;
}
},
data: function(term, dataCallback) {
@@ -29,7 +30,7 @@ export default class NamespaceSelect {
if (isFilter) {
const anyNamespace = {
text: 'Any namespace',
- id: null
+ id: null,
};
namespaces.unshift(anyNamespace);
namespaces.splice(1, 0, 'divider');
@@ -41,7 +42,7 @@ export default class NamespaceSelect {
if (namespace.id == null) {
return namespace.text;
} else {
- return namespace.kind + ": " + namespace.full_path;
+ return namespace.kind + ': ' + namespace.full_path;
}
},
renderRow: this.renderRow,
diff --git a/app/assets/javascripts/network/branch_graph.js b/app/assets/javascripts/network/branch_graph.js
index 94da1be4066..d1fa9f5e2a2 100644
--- a/app/assets/javascripts/network/branch_graph.js
+++ b/app/assets/javascripts/network/branch_graph.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, no-var, wrap-iife, quotes, comma-dangle, one-var, one-var-declaration-per-line, no-loop-func, no-floating-decimal, consistent-return, no-unused-vars, prefer-template, prefer-arrow-callback, camelcase, max-len */
+/* eslint-disable func-names, no-var, one-var, no-loop-func, consistent-return, no-unused-vars, prefer-template, prefer-arrow-callback, camelcase */
import $ from 'jquery';
import { __ } from '../locale';
@@ -20,7 +20,7 @@ export default (function() {
this.mtime = 0;
this.mspace = 0;
this.parents = {};
- this.colors = ["#000"];
+ this.colors = ['#000'];
this.offsetX = 150;
this.offsetY = 20;
this.unitTime = 30;
@@ -30,9 +30,10 @@ export default (function() {
}
BranchGraph.prototype.load = function() {
- axios.get(this.options.url)
+ axios
+ .get(this.options.url)
.then(({ data }) => {
- $(".loading", this.element).hide();
+ $('.loading', this.element).hide();
this.prepareData(data.days, data.commits);
this.buildGraph();
})
@@ -71,17 +72,19 @@ export default (function() {
c = ref[j];
this.mtime = Math.max(this.mtime, c.time);
this.mspace = Math.max(this.mspace, c.space);
- results.push((function() {
- var l, len1, ref1, results1;
- ref1 = c.parents;
- results1 = [];
- for (l = 0, len1 = ref1.length; l < len1; l += 1) {
- p = ref1[l];
- this.parents[p[0]] = true;
- results1.push(this.mspace = Math.max(this.mspace, p[1]));
- }
- return results1;
- }).call(this));
+ results.push(
+ function() {
+ var l, len1, ref1, results1;
+ ref1 = c.parents;
+ results1 = [];
+ for (l = 0, len1 = ref1.length; l < len1; l += 1) {
+ p = ref1[l];
+ this.parents[p[0]] = true;
+ results1.push((this.mspace = Math.max(this.mspace, p[1])));
+ }
+ return results1;
+ }.call(this),
+ );
}
return results;
};
@@ -91,11 +94,11 @@ export default (function() {
k = 0;
results = [];
while (k < this.mspace) {
- this.colors.push(Raphael.getColor(.8));
+ this.colors.push(Raphael.getColor(0.8));
// Skipping a few colors in the spectrum to get more contrast between colors
Raphael.getColor();
Raphael.getColor();
- results.push(k += 1);
+ results.push((k += 1));
}
return results;
};
@@ -104,12 +107,12 @@ export default (function() {
var cuday, cumonth, day, j, len, mm, ref;
const { r } = this;
cuday = 0;
- cumonth = "";
+ cumonth = '';
r.rect(0, 0, 40, this.barHeight).attr({
- fill: "#222"
+ fill: '#222',
});
r.rect(40, 0, 30, this.barHeight).attr({
- fill: "#444"
+ fill: '#444',
});
ref = this.days;
@@ -118,16 +121,16 @@ export default (function() {
if (cuday !== day[0] || cumonth !== day[1]) {
// Dates
r.text(55, this.offsetY + this.unitTime * mm, day[0]).attr({
- font: "12px Monaco, monospace",
- fill: "#BBB"
+ font: '12px Monaco, monospace',
+ fill: '#BBB',
});
[cuday] = day;
}
if (cumonth !== day[1]) {
// Months
r.text(20, this.offsetY + this.unitTime * mm, day[1]).attr({
- font: "12px Monaco, monospace",
- fill: "#EEE"
+ font: '12px Monaco, monospace',
+ fill: '#EEE',
});
// eslint-disable-next-line prefer-destructuring
@@ -173,11 +176,13 @@ export default (function() {
BranchGraph.prototype.bindEvents = function() {
const { element } = this;
- return $(element).scroll((function(_this) {
- return function(event) {
- return _this.renderPartialGraph();
- };
- })(this));
+ return $(element).scroll(
+ (function(_this) {
+ return function(event) {
+ return _this.renderPartialGraph();
+ };
+ })(this),
+ );
};
BranchGraph.prototype.scrollDown = function() {
@@ -219,46 +224,53 @@ export default (function() {
shortrefs = commit.refs;
// Truncate if longer than 15 chars
if (shortrefs.length > 17) {
- shortrefs = shortrefs.substr(0, 15) + "…";
+ shortrefs = shortrefs.substr(0, 15) + '…';
}
text = r.text(x + 4, y, shortrefs).attr({
- "text-anchor": "start",
- font: "10px Monaco, monospace",
- fill: "#FFF",
- title: commit.refs
+ 'text-anchor': 'start',
+ font: '10px Monaco, monospace',
+ fill: '#FFF',
+ title: commit.refs,
});
textbox = text.getBBox();
// Create rectangle based on the size of the textbox
rect = r.rect(x, y - 7, textbox.width + 5, textbox.height + 5, 4).attr({
- fill: "#000",
- "fill-opacity": .5,
- stroke: "none"
+ fill: '#000',
+ 'fill-opacity': 0.5,
+ stroke: 'none',
});
- triangle = r.path(["M", x - 5, y, "L", x - 15, y - 4, "L", x - 15, y + 4, "Z"]).attr({
- fill: "#000",
- "fill-opacity": .5,
- stroke: "none"
+ triangle = r.path(['M', x - 5, y, 'L', x - 15, y - 4, 'L', x - 15, y + 4, 'Z']).attr({
+ fill: '#000',
+ 'fill-opacity': 0.5,
+ stroke: 'none',
});
label = r.set(rect, text);
- label.transform(["t", -rect.getBBox().width - 15, 0]);
+ label.transform(['t', -rect.getBBox().width - 15, 0]);
// Set text to front
return text.toFront();
};
BranchGraph.prototype.appendAnchor = function(x, y, commit) {
const { r, top, options } = this;
- const anchor = r.circle(x, y, 10).attr({
- fill: "#000",
- opacity: 0,
- cursor: "pointer"
- }).click(function() {
- return window.open(options.commit_url.replace("%s", commit.id), "_blank");
- }).hover(function() {
- this.tooltip = r.commitTooltip(x + 5, y, commit);
- return top.push(this.tooltip.insertBefore(this));
- }, function() {
- return this.tooltip && this.tooltip.remove() && delete this.tooltip;
- });
+ const anchor = r
+ .circle(x, y, 10)
+ .attr({
+ fill: '#000',
+ opacity: 0,
+ cursor: 'pointer',
+ })
+ .click(function() {
+ return window.open(options.commit_url.replace('%s', commit.id), '_blank');
+ })
+ .hover(
+ function() {
+ this.tooltip = r.commitTooltip(x + 5, y, commit);
+ return top.push(this.tooltip.insertBefore(this));
+ },
+ function() {
+ return this.tooltip && this.tooltip.remove() && delete this.tooltip;
+ },
+ );
return top.push(anchor);
};
@@ -266,7 +278,7 @@ export default (function() {
const { r } = this;
r.circle(x, y, 3).attr({
fill: this.colors[commit.space],
- stroke: "none"
+ stroke: 'none',
});
const avatar_box_x = this.offsetX + this.unitSpace * this.mspace + 10;
@@ -274,13 +286,15 @@ export default (function() {
r.rect(avatar_box_x, avatar_box_y, 20, 20).attr({
stroke: this.colors[commit.space],
- "stroke-width": 2
+ 'stroke-width': 2,
});
r.image(commit.author.icon, avatar_box_x, avatar_box_y, 20, 20);
- return r.text(this.offsetX + this.unitSpace * this.mspace + 35, y, commit.message.split("\n")[0]).attr({
- "text-anchor": "start",
- font: "14px Monaco, monospace"
- });
+ return r
+ .text(this.offsetX + this.unitSpace * this.mspace + 35, y, commit.message.split('\n')[0])
+ .attr({
+ 'text-anchor': 'start',
+ font: '14px Monaco, monospace',
+ });
};
BranchGraph.prototype.drawLines = function(x, y, commit) {
@@ -304,30 +318,32 @@ export default (function() {
// Build line shape
if (parent[1] === commit.space) {
offset = [0, 5];
- arrow = "l-2,5,4,0,-2,-5,0,5";
+ arrow = 'l-2,5,4,0,-2,-5,0,5';
} else if (parent[1] < commit.space) {
offset = [3, 3];
- arrow = "l5,0,-2,4,-3,-4,4,2";
+ arrow = 'l5,0,-2,4,-3,-4,4,2';
} else {
offset = [-3, 3];
- arrow = "l-5,0,2,4,3,-4,-4,2";
+ arrow = 'l-5,0,2,4,3,-4,-4,2';
}
// Start point
- route = ["M", x + offset[0], y + offset[1]];
+ route = ['M', x + offset[0], y + offset[1]];
// Add arrow if not first parent
if (i > 0) {
route.push(arrow);
}
// Circumvent if overlap
if (commit.space !== parentCommit.space || commit.space !== parent[1]) {
- route.push("L", parentX2, y + 10, "L", parentX2, parentY - 5);
+ route.push('L', parentX2, y + 10, 'L', parentX2, parentY - 5);
}
// End point
- route.push("L", parentX1, parentY);
- results.push(r.path(route).attr({
- stroke: color,
- "stroke-width": 2
- }));
+ route.push('L', parentX1, parentY);
+ results.push(
+ r.path(route).attr({
+ stroke: color,
+ 'stroke-width': 2,
+ }),
+ );
}
return results;
};
@@ -337,10 +353,10 @@ export default (function() {
const { r } = this;
const x = this.offsetX + this.unitSpace * (this.mspace - commit.space);
const y = this.offsetY + this.unitTime * commit.time;
- r.path(["M", x + 5, y, "L", x + 15, y + 4, "L", x + 15, y - 4, "Z"]).attr({
- fill: "#000",
- "fill-opacity": .5,
- stroke: "none"
+ r.path(['M', x + 5, y, 'L', x + 15, y + 4, 'L', x + 15, y - 4, 'Z']).attr({
+ fill: '#000',
+ 'fill-opacity': 0.5,
+ stroke: 'none',
});
// Displayed in the center
return this.element.scrollTop(y - this.graphHeight / 2);
diff --git a/app/assets/javascripts/network/raphael.js b/app/assets/javascripts/network/raphael.js
index 09dcf716148..22e06a35d91 100644
--- a/app/assets/javascripts/network/raphael.js
+++ b/app/assets/javascripts/network/raphael.js
@@ -49,7 +49,7 @@ Raphael.prototype.textWrap = function testWrap(t, width) {
const s = [];
for (let j = 0, len = words.length; j < len; j += 1) {
const word = words[j];
- if (x + (word.length * letterWidth) > width) {
+ if (x + word.length * letterWidth > width) {
s.push('\n');
x = 0;
}
diff --git a/app/assets/javascripts/new_branch_form.js b/app/assets/javascripts/new_branch_form.js
index 205d9766656..f338dbbb0a6 100644
--- a/app/assets/javascripts/new_branch_form.js
+++ b/app/assets/javascripts/new_branch_form.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, no-var, one-var, max-len, wrap-iife, consistent-return, comma-dangle, one-var-declaration-per-line, quotes, no-return-assign, prefer-arrow-callback, prefer-template, no-shadow, no-else-return, max-len */
+/* eslint-disable func-names, no-var, one-var, consistent-return, no-return-assign, prefer-arrow-callback, prefer-template, no-shadow, no-else-return */
import $ from 'jquery';
import RefSelectDropdown from './ref_select_dropdown';
@@ -30,24 +30,24 @@ export default class NewBranchForm {
startsWith = {
pattern: /^(\/|\.)/g,
prefix: "can't start with",
- conjunction: "or"
+ conjunction: 'or',
};
endsWith = {
pattern: /(\/|\.|\.lock)$/g,
prefix: "can't end in",
- conjunction: "or"
+ conjunction: 'or',
};
invalid = {
pattern: /(\s|~|\^|:|\?|\*|\[|\\|\.\.|@\{|\/{2,}){1}/g,
prefix: "can't contain",
- conjunction: ", "
+ conjunction: ', ',
};
single = {
pattern: /^@+$/g,
prefix: "can't be",
- conjunction: "or"
+ conjunction: 'or',
};
- return this.restrictions = [startsWith, invalid, endsWith, single];
+ return (this.restrictions = [startsWith, invalid, endsWith, single]);
}
validate() {
@@ -73,7 +73,7 @@ export default class NewBranchForm {
return "'" + value + "'";
}
});
- return restriction.prefix + " " + (formatted.join(restriction.conjunction));
+ return restriction.prefix + ' ' + formatted.join(restriction.conjunction);
};
validator = (function(_this) {
return function(errors, restriction) {
@@ -88,7 +88,7 @@ export default class NewBranchForm {
})(this);
errors = this.restrictions.reduce(validator, []);
if (errors.length > 0) {
- errorMessage = $("<span/>").text(errors.join(', '));
+ errorMessage = $('<span/>').text(errors.join(', '));
return this.branchNameError.append(errorMessage);
}
}
diff --git a/app/assets/javascripts/new_commit_form.js b/app/assets/javascripts/new_commit_form.js
index 17ec20f1cc1..b142f212eb0 100644
--- a/app/assets/javascripts/new_commit_form.js
+++ b/app/assets/javascripts/new_commit_form.js
@@ -6,9 +6,7 @@ export default class NewCommitForm {
this.branchName = form.find('.js-branch-name');
this.originalBranch = form.find('.js-original-branch');
this.createMergeRequest = form.find('.js-create-merge-request');
- this.createMergeRequestContainer = form.find(
- '.js-create-merge-request-container',
- );
+ this.createMergeRequestContainer = form.find('.js-create-merge-request-container');
this.branchName.keyup(this.renderDestination);
this.renderDestination();
}
diff --git a/app/assets/javascripts/notebook/cells/code.vue b/app/assets/javascripts/notebook/cells/code.vue
index 18cef82cec0..bd6736152f5 100644
--- a/app/assets/javascripts/notebook/cells/code.vue
+++ b/app/assets/javascripts/notebook/cells/code.vue
@@ -42,12 +42,14 @@ export default {
:raw-code="rawInputCode"
:count="cell.execution_count"
:code-css-class="codeCssClass"
- type="input" />
+ type="input"
+ />
<output-cell
v-if="hasOutput"
:count="cell.execution_count"
:output="output"
- :code-css-class="codeCssClass" />
+ :code-css-class="codeCssClass"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/notebook/cells/code/index.vue b/app/assets/javascripts/notebook/cells/code/index.vue
index 7d2a1a33b98..8bf2431c4c6 100644
--- a/app/assets/javascripts/notebook/cells/code/index.vue
+++ b/app/assets/javascripts/notebook/cells/code/index.vue
@@ -1,57 +1,50 @@
<script>
- import Prism from '../../lib/highlight';
- import Prompt from '../prompt.vue';
+import Prism from '../../lib/highlight';
+import Prompt from '../prompt.vue';
- export default {
- components: {
- prompt: Prompt,
+export default {
+ components: {
+ prompt: Prompt,
+ },
+ props: {
+ count: {
+ type: Number,
+ required: false,
+ default: 0,
},
- props: {
- count: {
- type: Number,
- required: false,
- default: 0,
- },
- codeCssClass: {
- type: String,
- required: false,
- default: '',
- },
- type: {
- type: String,
- required: true,
- },
- rawCode: {
- type: String,
- required: true,
- },
+ codeCssClass: {
+ type: String,
+ required: false,
+ default: '',
},
- computed: {
- code() {
- return this.rawCode;
- },
- promptType() {
- const type = this.type.split('put')[0];
-
- return type.charAt(0).toUpperCase() + type.slice(1);
- },
+ type: {
+ type: String,
+ required: true,
+ },
+ rawCode: {
+ type: String,
+ required: true,
},
- mounted() {
- Prism.highlightElement(this.$refs.code);
+ },
+ computed: {
+ code() {
+ return this.rawCode;
+ },
+ promptType() {
+ const type = this.type.split('put')[0];
+
+ return type.charAt(0).toUpperCase() + type.slice(1);
},
- };
+ },
+ mounted() {
+ Prism.highlightElement(this.$refs.code);
+ },
+};
</script>
<template>
<div :class="type">
- <prompt
- :type="promptType"
- :count="count" />
- <pre
- ref="code"
- :class="codeCssClass"
- class="language-python"
- v-text="code">
- </pre>
+ <prompt :type="promptType" :count="count" />
+ <pre ref="code" :class="codeCssClass" class="language-python" v-text="code"></pre>
</div>
</template>
diff --git a/app/assets/javascripts/notebook/cells/markdown.vue b/app/assets/javascripts/notebook/cells/markdown.vue
index 3d09d24b6ab..61eabbcb8b2 100644
--- a/app/assets/javascripts/notebook/cells/markdown.vue
+++ b/app/assets/javascripts/notebook/cells/markdown.vue
@@ -1,12 +1,12 @@
<script>
- /* global katex */
- import marked from 'marked';
- import sanitize from 'sanitize-html';
- import Prompt from './prompt.vue';
+/* global katex */
+import marked from 'marked';
+import sanitize from 'sanitize-html';
+import Prompt from './prompt.vue';
- const renderer = new marked.Renderer();
+const renderer = new marked.Renderer();
- /*
+/*
Regex to match KaTex blocks.
Supports the following:
@@ -17,7 +17,7 @@
The matched text then goes through the KaTex renderer & then outputs the HTML
*/
- const katexRegexString = `(
+const katexRegexString = `(
^\\\\begin{[a-zA-Z]+}\\s
|
^\\$\\$
@@ -32,86 +32,86 @@
|
\\$
)
- `.replace(/\s/g, '').trim();
+ `
+ .replace(/\s/g, '')
+ .trim();
- renderer.paragraph = (t) => {
- let text = t;
- let inline = false;
+renderer.paragraph = t => {
+ let text = t;
+ let inline = false;
- if (typeof katex !== 'undefined') {
- const katexString = text.replace(/&amp;/g, '&')
- .replace(/&=&/g, '\\space=\\space')
- .replace(/<(\/?)em>/g, '_');
- const regex = new RegExp(katexRegexString, 'gi');
- const matchLocation = katexString.search(regex);
- const numberOfMatches = katexString.match(regex);
+ if (typeof katex !== 'undefined') {
+ const katexString = text
+ .replace(/&amp;/g, '&')
+ .replace(/&=&/g, '\\space=\\space')
+ .replace(/<(\/?)em>/g, '_');
+ const regex = new RegExp(katexRegexString, 'gi');
+ const matchLocation = katexString.search(regex);
+ const numberOfMatches = katexString.match(regex);
- if (numberOfMatches && numberOfMatches.length !== 0) {
- if (matchLocation > 0) {
- let matches = regex.exec(katexString);
- inline = true;
+ if (numberOfMatches && numberOfMatches.length !== 0) {
+ if (matchLocation > 0) {
+ let matches = regex.exec(katexString);
+ inline = true;
- while (matches !== null) {
- const renderedKatex = katex.renderToString(matches[0].replace(/\$/g, ''));
- text = `${text.replace(matches[0], ` ${renderedKatex}`)}`;
- matches = regex.exec(katexString);
- }
- } else {
- const matches = regex.exec(katexString);
- text = katex.renderToString(matches[2]);
+ while (matches !== null) {
+ const renderedKatex = katex.renderToString(matches[0].replace(/\$/g, ''));
+ text = `${text.replace(matches[0], ` ${renderedKatex}`)}`;
+ matches = regex.exec(katexString);
}
+ } else {
+ const matches = regex.exec(katexString);
+ text = katex.renderToString(matches[2]);
}
}
+ }
- return `<p class="${inline ? 'inline-katex' : ''}">${text}</p>`;
- };
+ return `<p class="${inline ? 'inline-katex' : ''}">${text}</p>`;
+};
- marked.setOptions({
- sanitize: true,
- renderer,
- });
+marked.setOptions({
+ sanitize: true,
+ renderer,
+});
- export default {
- components: {
- prompt: Prompt,
- },
- props: {
- cell: {
- type: Object,
- required: true,
- },
+export default {
+ components: {
+ prompt: Prompt,
+ },
+ props: {
+ cell: {
+ type: Object,
+ required: true,
},
- computed: {
- markdown() {
- return sanitize(marked(this.cell.source.join('').replace(/\\/g, '\\\\')), {
- allowedTags: false,
- allowedAttributes: {
- '*': ['class'],
- },
- });
- },
+ },
+ computed: {
+ markdown() {
+ return sanitize(marked(this.cell.source.join('').replace(/\\/g, '\\\\')), {
+ allowedTags: false,
+ allowedAttributes: {
+ '*': ['class'],
+ },
+ });
},
- };
+ },
+};
</script>
<template>
<div class="cell text-cell">
<prompt />
- <div
- class="markdown"
- v-html="markdown">
- </div>
+ <div class="markdown" v-html="markdown"></div>
</div>
</template>
<style>
- .markdown .katex {
- display: block;
- text-align: center;
- }
+.markdown .katex {
+ display: block;
+ text-align: center;
+}
- .markdown .inline-katex .katex {
- display: inline;
- text-align: initial;
- }
+.markdown .inline-katex .katex {
+ display: inline;
+ text-align: initial;
+}
</style>
diff --git a/app/assets/javascripts/notebook/cells/output/html.vue b/app/assets/javascripts/notebook/cells/output/html.vue
index 0535ee7afa8..c6fc786fa76 100644
--- a/app/assets/javascripts/notebook/cells/output/html.vue
+++ b/app/assets/javascripts/notebook/cells/output/html.vue
@@ -1,30 +1,28 @@
<script>
- import sanitize from 'sanitize-html';
- import Prompt from '../prompt.vue';
+import sanitize from 'sanitize-html';
+import Prompt from '../prompt.vue';
- export default {
- components: {
- prompt: Prompt,
+export default {
+ components: {
+ prompt: Prompt,
+ },
+ props: {
+ rawCode: {
+ type: String,
+ required: true,
},
- props: {
- rawCode: {
- type: String,
- required: true,
- },
+ },
+ computed: {
+ sanitizedOutput() {
+ return sanitize(this.rawCode, {
+ allowedTags: sanitize.defaults.allowedTags.concat(['img', 'svg']),
+ allowedAttributes: {
+ img: ['src'],
+ },
+ });
},
- computed: {
- sanitizedOutput() {
- return sanitize(this.rawCode, {
- allowedTags: sanitize.defaults.allowedTags.concat([
- 'img', 'svg',
- ]),
- allowedAttributes: {
- img: ['src'],
- },
- });
- },
- },
- };
+ },
+};
</script>
<template>
diff --git a/app/assets/javascripts/notebook/cells/output/image.vue b/app/assets/javascripts/notebook/cells/output/image.vue
index 67d6c5ad12b..fe8c81398fb 100644
--- a/app/assets/javascripts/notebook/cells/output/image.vue
+++ b/app/assets/javascripts/notebook/cells/output/image.vue
@@ -1,26 +1,23 @@
<script>
- import Prompt from '../prompt.vue';
+import Prompt from '../prompt.vue';
- export default {
- components: {
- prompt: Prompt,
+export default {
+ components: {
+ prompt: Prompt,
+ },
+ props: {
+ outputType: {
+ type: String,
+ required: true,
},
- props: {
- outputType: {
- type: String,
- required: true,
- },
- rawCode: {
- type: String,
- required: true,
- },
+ rawCode: {
+ type: String,
+ required: true,
},
- };
+ },
+};
</script>
<template>
- <div class="output">
- <prompt />
- <img :src="'data:' + outputType + ';base64,' + rawCode" />
- </div>
+ <div class="output"><prompt /> <img :src="'data:' + outputType + ';base64,' + rawCode" /></div>
</template>
diff --git a/app/assets/javascripts/notebook/cells/output/index.vue b/app/assets/javascripts/notebook/cells/output/index.vue
index 4183b976814..bd0bcc0d819 100644
--- a/app/assets/javascripts/notebook/cells/output/index.vue
+++ b/app/assets/javascripts/notebook/cells/output/index.vue
@@ -1,78 +1,78 @@
<script>
- import CodeCell from '../code/index.vue';
- import Html from './html.vue';
- import Image from './image.vue';
+import CodeCell from '../code/index.vue';
+import Html from './html.vue';
+import Image from './image.vue';
- export default {
- components: {
- 'code-cell': CodeCell,
- 'html-output': Html,
- 'image-output': Image,
+export default {
+ components: {
+ 'code-cell': CodeCell,
+ 'html-output': Html,
+ 'image-output': Image,
+ },
+ props: {
+ codeCssClass: {
+ type: String,
+ required: false,
+ default: '',
},
- props: {
- codeCssClass: {
- type: String,
- required: false,
- default: '',
- },
- count: {
- type: Number,
- required: false,
- default: 0,
- },
- output: {
- type: Object,
- requred: true,
- default: () => ({}),
- },
+ count: {
+ type: Number,
+ required: false,
+ default: 0,
},
- computed: {
- componentName() {
- if (this.output.text) {
- return 'code-cell';
- } else if (this.output.data['image/png']) {
- return 'image-output';
- } else if (this.output.data['text/html']) {
- return 'html-output';
- } else if (this.output.data['image/svg+xml']) {
- return 'html-output';
- }
-
+ output: {
+ type: Object,
+ required: true,
+ default: () => ({}),
+ },
+ },
+ computed: {
+ componentName() {
+ if (this.output.text) {
return 'code-cell';
- },
- rawCode() {
- if (this.output.text) {
- return this.output.text.join('');
- }
+ } else if (this.output.data['image/png']) {
+ return 'image-output';
+ } else if (this.output.data['text/html']) {
+ return 'html-output';
+ } else if (this.output.data['image/svg+xml']) {
+ return 'html-output';
+ }
- return this.dataForType(this.outputType);
- },
- outputType() {
- if (this.output.text) {
- return '';
- } else if (this.output.data['image/png']) {
- return 'image/png';
- } else if (this.output.data['text/html']) {
- return 'text/html';
- } else if (this.output.data['image/svg+xml']) {
- return 'image/svg+xml';
- }
+ return 'code-cell';
+ },
+ rawCode() {
+ if (this.output.text) {
+ return this.output.text.join('');
+ }
+
+ return this.dataForType(this.outputType);
+ },
+ outputType() {
+ if (this.output.text) {
+ return '';
+ } else if (this.output.data['image/png']) {
+ return 'image/png';
+ } else if (this.output.data['text/html']) {
+ return 'text/html';
+ } else if (this.output.data['image/svg+xml']) {
+ return 'image/svg+xml';
+ }
- return 'text/plain';
- },
+ return 'text/plain';
},
- methods: {
- dataForType(type) {
- let data = this.output.data[type];
+ },
+ methods: {
+ dataForType(type) {
+ let data = this.output.data[type];
- if (typeof data === 'object') {
- data = data.join('');
- }
+ if (typeof data === 'object') {
+ data = data.join('');
+ }
- return data;
- },
+ return data;
},
- };
+ },
+};
</script>
<template>
diff --git a/app/assets/javascripts/notebook/cells/prompt.vue b/app/assets/javascripts/notebook/cells/prompt.vue
index fe1fc37e1dc..3f1f239a806 100644
--- a/app/assets/javascripts/notebook/cells/prompt.vue
+++ b/app/assets/javascripts/notebook/cells/prompt.vue
@@ -1,37 +1,35 @@
<script>
- export default {
- props: {
- type: {
- type: String,
- required: false,
- default: '',
- },
- count: {
- type: Number,
- required: false,
- default: 0,
- },
+export default {
+ props: {
+ type: {
+ type: String,
+ required: false,
+ default: '',
},
- computed: {
- hasKeys() {
- return this.type !== '' && this.count;
- },
+ count: {
+ type: Number,
+ required: false,
+ default: 0,
},
- };
+ },
+ computed: {
+ hasKeys() {
+ return this.type !== '' && this.count;
+ },
+ },
+};
</script>
<template>
<div class="prompt">
- <span v-if="hasKeys">
- {{ type }} [{{ count }}]:
- </span>
+ <span v-if="hasKeys"> {{ type }} [{{ count }}]: </span>
</div>
</template>
<style scoped>
- .prompt {
- padding: 0 10px;
- min-width: 7em;
- font-family: monospace;
- }
+.prompt {
+ padding: 0 10px;
+ min-width: 7em;
+ font-family: monospace;
+}
</style>
diff --git a/app/assets/javascripts/notebook/index.vue b/app/assets/javascripts/notebook/index.vue
index e2e3b08c77f..6a54d0b3823 100644
--- a/app/assets/javascripts/notebook/index.vue
+++ b/app/assets/javascripts/notebook/index.vue
@@ -1,61 +1,59 @@
<script>
- import {
- MarkdownCell,
- CodeCell,
- } from './cells';
+import { MarkdownCell, CodeCell } from './cells';
- export default {
- components: {
- 'code-cell': CodeCell,
- 'markdown-cell': MarkdownCell,
+export default {
+ components: {
+ 'code-cell': CodeCell,
+ 'markdown-cell': MarkdownCell,
+ },
+ props: {
+ notebook: {
+ type: Object,
+ required: true,
},
- props: {
- notebook: {
- type: Object,
- required: true,
- },
- codeCssClass: {
- type: String,
- required: false,
- default: '',
- },
+ codeCssClass: {
+ type: String,
+ required: false,
+ default: '',
},
- computed: {
- cells() {
- if (this.notebook.worksheets) {
- const data = {
- cells: [],
- };
+ },
+ computed: {
+ cells() {
+ if (this.notebook.worksheets) {
+ const data = {
+ cells: [],
+ };
- return this.notebook.worksheets.reduce((cellData, sheet) => {
- const cellDataCopy = cellData;
- cellDataCopy.cells = cellDataCopy.cells.concat(sheet.cells);
- return cellDataCopy;
- }, data).cells;
- }
+ return this.notebook.worksheets.reduce((cellData, sheet) => {
+ const cellDataCopy = cellData;
+ cellDataCopy.cells = cellDataCopy.cells.concat(sheet.cells);
+ return cellDataCopy;
+ }, data).cells;
+ }
- return this.notebook.cells;
- },
- hasNotebook() {
- return Object.keys(this.notebook).length;
- },
+ return this.notebook.cells;
},
- methods: {
- cellType(type) {
- return `${type}-cell`;
- },
+ hasNotebook() {
+ return Object.keys(this.notebook).length;
},
- };
+ },
+ methods: {
+ cellType(type) {
+ return `${type}-cell`;
+ },
+ },
+};
</script>
<template>
<div v-if="hasNotebook">
<component
- v-for="(cell, index) in cells"
:is="cellType(cell.cell_type)"
- :cell="cell"
+ v-for="(cell, index) in cells"
:key="index"
- :code-css-class="codeCssClass" />
+ :cell="cell"
+ :code-css-class="codeCssClass"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 0c966e0808a..dfb53c986fc 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -1,5 +1,5 @@
-/* eslint-disable no-restricted-properties, func-names, no-var, wrap-iife, camelcase,
-no-unused-expressions, max-len, one-var, one-var-declaration-per-line, default-case,
+/* eslint-disable no-restricted-properties, func-names, no-var, camelcase,
+no-unused-expressions, one-var, default-case,
prefer-template, consistent-return, no-alert, no-return-assign,
no-param-reassign, prefer-arrow-callback, no-else-return, vars-on-top,
no-unused-vars, no-shadow, no-useless-escape, class-methods-use-this */
@@ -16,7 +16,7 @@ import 'vendor/jquery.atwho';
import AjaxCache from '~/lib/utils/ajax_cache';
import Vue from 'vue';
import syntaxHighlight from '~/syntax_highlight';
-import SkeletonLoadingContainer from '~/vue_shared/components/skeleton_loading_container.vue';
+import { GlSkeletonLoading } from '@gitlab/ui';
import axios from './lib/utils/axios_utils';
import { getLocationHash } from './lib/utils/url_utility';
import Flash from './flash';
@@ -1293,10 +1293,10 @@ export default class Notes {
new Vue({
el,
components: {
- SkeletonLoadingContainer,
+ GlSkeletonLoading,
},
render(createElement) {
- return createElement('skeleton-loading-container');
+ return createElement('gl-skeleton-loading');
},
});
}
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index 7735133c470..841fcec96e8 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -4,10 +4,14 @@ import { mapActions, mapGetters, mapState } from 'vuex';
import _ from 'underscore';
import Autosize from 'autosize';
import { __, sprintf } from '~/locale';
+import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import Flash from '../../flash';
import Autosave from '../../autosave';
-import TaskList from '../../task_list';
-import { capitalizeFirstCharacter, convertToCamelCase, splitCamelCase } from '../../lib/utils/text_utility';
+import {
+ capitalizeFirstCharacter,
+ convertToCamelCase,
+ splitCamelCase,
+} from '../../lib/utils/text_utility';
import * as constants from '../constants';
import eventHub from '../event_hub';
import issueWarning from '../../vue_shared/components/issue/issue_warning.vue';
@@ -27,6 +31,7 @@ export default {
markdownField,
userAvatarLink,
loadingButton,
+ TimelineEntryItem,
},
mixins: [issuableStateMixin],
props: {
@@ -122,7 +127,9 @@ export default {
return this.getNoteableData.create_note_path;
},
issuableTypeTitle() {
- return this.noteableType === constants.MERGE_REQUEST_NOTEABLE_TYPE ? 'merge request' : 'issue';
+ return this.noteableType === constants.MERGE_REQUEST_NOTEABLE_TYPE
+ ? 'merge request'
+ : 'issue';
},
},
watch: {
@@ -140,7 +147,6 @@ export default {
});
this.initAutoSave();
- this.initTaskList();
},
methods: {
...mapActions([
@@ -292,13 +298,6 @@ Please check your network connection and try again.`;
]);
}
},
- initTaskList() {
- return new TaskList({
- dataType: 'note',
- fieldName: 'note',
- selector: '.notes',
- });
- },
resizeTextarea() {
this.$nextTick(() => {
Autosize.update(this.$refs.textarea);
@@ -311,151 +310,136 @@ Please check your network connection and try again.`;
<template>
<div>
<note-signed-out-widget v-if="!isLoggedIn" />
- <discussion-locked-widget
- v-else-if="!canCreateNote"
- :issuable-type="issuableTypeTitle"
- />
- <ul
- v-else-if="canCreateNote"
- class="notes notes-form timeline">
- <li class="timeline-entry">
- <div class="timeline-entry-inner">
- <div class="flash-container error-alert timeline-content"></div>
- <div class="timeline-icon d-none d-sm-none d-md-block">
- <user-avatar-link
- v-if="author"
- :link-href="author.path"
- :img-src="author.avatar_url"
- :img-alt="author.name"
- :img-size="40"
- />
- </div>
- <div class="timeline-content timeline-content-form">
- <form
- ref="commentForm"
- class="new-note common-note-form gfm-form js-main-target-form"
- >
-
- <div class="error-alert"></div>
-
- <issue-warning
- v-if="hasWarning(getNoteableData)"
- :is-locked="isLocked(getNoteableData)"
- :is-confidential="isConfidential(getNoteableData)"
- />
-
- <markdown-field
- ref="markdownField"
- :markdown-preview-path="markdownPreviewPath"
- :markdown-docs-path="markdownDocsPath"
- :quick-actions-docs-path="quickActionsDocsPath"
- :markdown-version="markdownVersion"
- :add-spacing-classes="false">
- <textarea
- id="note-body"
- ref="textarea"
- slot="textarea"
- v-model="note"
- :disabled="isSubmitting"
- name="note[note]"
- class="note-textarea js-vue-comment-form js-note-text
-js-gfm-input js-autosize markdown-area js-vue-textarea"
- data-supports-quick-actions="true"
- aria-label="Description"
- placeholder="Write a comment or drag your files here…"
- @keydown.up="editCurrentUserLastNote()"
- @keydown.meta.enter="handleSave()"
- @keydown.ctrl.enter="handleSave()">
- </textarea>
- </markdown-field>
- <div class="note-form-actions">
- <div
- class="float-left btn-group
-append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown">
- <button
- :disabled="isSubmitButtonDisabled"
- class="btn btn-success comment-btn js-comment-button js-comment-submit-button"
- type="submit"
- @click.prevent="handleSave()">
- {{ __(commentButtonTitle) }}
- </button>
- <button
- :disabled="isSubmitButtonDisabled"
- name="button"
- type="button"
- class="btn comment-btn note-type-toggle js-note-new-discussion dropdown-toggle"
- data-display="static"
- data-toggle="dropdown"
- aria-label="Open comment type dropdown">
- <i
- aria-hidden="true"
- class="fa fa-caret-down toggle-icon">
- </i>
- </button>
-
- <ul class="note-type-dropdown dropdown-open-top dropdown-menu">
- <li :class="{ 'droplab-item-selected': noteType === 'comment' }">
- <button
- type="button"
- class="btn btn-transparent"
- @click.prevent="setNoteType('comment')">
- <i
- aria-hidden="true"
- class="fa fa-check icon">
- </i>
- <div class="description">
- <strong>Comment</strong>
- <p>
- Add a general comment to this {{ noteableDisplayName }}.
- </p>
- </div>
- </button>
- </li>
- <li class="divider droplab-item-ignore"></li>
- <li :class="{ 'droplab-item-selected': noteType === 'discussion' }">
- <button
- type="button"
- class="btn btn-transparent"
- @click.prevent="setNoteType('discussion')">
- <i
- aria-hidden="true"
- class="fa fa-check icon">
- </i>
- <div class="description">
- <strong>Start discussion</strong>
- <p>
- {{ startDiscussionDescription }}
- </p>
- </div>
- </button>
- </li>
- </ul>
- </div>
+ <discussion-locked-widget v-else-if="!canCreateNote" :issuable-type="issuableTypeTitle" />
+ <ul v-else-if="canCreateNote" class="notes notes-form timeline">
+ <timeline-entry-item class="note-form">
+ <div class="flash-container error-alert timeline-content"></div>
+ <div class="timeline-icon d-none d-sm-none d-md-block">
+ <user-avatar-link
+ v-if="author"
+ :link-href="author.path"
+ :img-src="author.avatar_url"
+ :img-alt="author.name"
+ :img-size="40"
+ />
+ </div>
+ <div class="timeline-content timeline-content-form">
+ <form ref="commentForm" class="new-note common-note-form gfm-form js-main-target-form">
+ <div class="error-alert"></div>
- <loading-button
- v-if="canUpdateIssue"
- :loading="isToggleStateButtonLoading"
- :container-class="[
- actionButtonClassNames,
- 'btn btn-comment btn-comment-and-close js-action-button'
- ]"
- :disabled="isToggleStateButtonLoading || isSubmitting"
- :label="issueActionButtonTitle"
- @click="handleSave(true)"
- />
+ <issue-warning
+ v-if="hasWarning(getNoteableData)"
+ :is-locked="isLocked(getNoteableData)"
+ :is-confidential="isConfidential(getNoteableData)"
+ />
+ <markdown-field
+ ref="markdownField"
+ :markdown-preview-path="markdownPreviewPath"
+ :markdown-docs-path="markdownDocsPath"
+ :quick-actions-docs-path="quickActionsDocsPath"
+ :markdown-version="markdownVersion"
+ :add-spacing-classes="false"
+ >
+ <textarea
+ id="note-body"
+ ref="textarea"
+ slot="textarea"
+ v-model="note"
+ :disabled="isSubmitting"
+ name="note[note]"
+ class="note-textarea js-vue-comment-form js-note-text
+js-gfm-input js-autosize markdown-area js-vue-textarea qa-comment-input"
+ data-supports-quick-actions="true"
+ aria-label="Description"
+ placeholder="Write a comment or drag your files here…"
+ @keydown.up="editCurrentUserLastNote();"
+ @keydown.meta.enter="handleSave();"
+ @keydown.ctrl.enter="handleSave();"
+ >
+ </textarea>
+ </markdown-field>
+ <div class="note-form-actions">
+ <div
+ class="float-left btn-group
+append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"
+ >
+ <button
+ :disabled="isSubmitButtonDisabled"
+ class="btn btn-create comment-btn js-comment-button js-comment-submit-button
+ qa-comment-button"
+ type="submit"
+ @click.prevent="handleSave();"
+ >
+ {{ __(commentButtonTitle) }}
+ </button>
<button
- v-if="note.length"
+ :disabled="isSubmitButtonDisabled"
+ name="button"
type="button"
- class="btn btn-cancel js-note-discard"
- @click="discard">
- Discard draft
+ class="btn comment-btn note-type-toggle js-note-new-discussion dropdown-toggle qa-note-dropdown"
+ data-display="static"
+ data-toggle="dropdown"
+ aria-label="Open comment type dropdown"
+ >
+ <i aria-hidden="true" class="fa fa-caret-down toggle-icon"> </i>
</button>
+
+ <ul class="note-type-dropdown dropdown-open-top dropdown-menu">
+ <li :class="{ 'droplab-item-selected': noteType === 'comment' }">
+ <button
+ type="button"
+ class="btn btn-transparent"
+ @click.prevent="setNoteType('comment');"
+ >
+ <i aria-hidden="true" class="fa fa-check icon"> </i>
+ <div class="description">
+ <strong>Comment</strong>
+ <p>Add a general comment to this {{ noteableDisplayName }}.</p>
+ </div>
+ </button>
+ </li>
+ <li class="divider droplab-item-ignore"></li>
+ <li :class="{ 'droplab-item-selected': noteType === 'discussion' }">
+ <button
+ type="button"
+ class="btn btn-transparent qa-discussion-option"
+ @click.prevent="setNoteType('discussion');"
+ >
+ <i aria-hidden="true" class="fa fa-check icon"> </i>
+ <div class="description">
+ <strong>Start discussion</strong>
+ <p>{{ startDiscussionDescription }}</p>
+ </div>
+ </button>
+ </li>
+ </ul>
</div>
- </form>
- </div>
+
+ <loading-button
+ v-if="canUpdateIssue"
+ :loading="isToggleStateButtonLoading"
+ :container-class="[
+ actionButtonClassNames,
+ 'btn btn-comment btn-comment-and-close js-action-button',
+ ]"
+ :disabled="isToggleStateButtonLoading || isSubmitting"
+ :label="issueActionButtonTitle"
+ @click="handleSave(true);"
+ />
+
+ <button
+ v-if="note.length"
+ type="button"
+ class="btn btn-cancel js-note-discard"
+ @click="discard"
+ >
+ Discard draft
+ </button>
+ </div>
+ </form>
</div>
- </li>
+ </timeline-entry-item>
</ul>
</div>
</template>
diff --git a/app/assets/javascripts/notes/components/diff_file_header.vue b/app/assets/javascripts/notes/components/diff_file_header.vue
deleted file mode 100644
index fc7b52be241..00000000000
--- a/app/assets/javascripts/notes/components/diff_file_header.vue
+++ /dev/null
@@ -1,94 +0,0 @@
-<script>
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import Icon from '~/vue_shared/components/icon.vue';
-
-export default {
- components: {
- ClipboardButton,
- Icon,
- },
- props: {
- diffFile: {
- type: Object,
- required: true,
- },
- },
- computed: {
- titleTag() {
- return this.diffFile.discussionPath ? 'a' : 'span';
- },
- },
-};
-</script>
-
-<template>
- <div class="file-header-content">
- <div
- v-if="diffFile.submodule"
- >
- <span>
- <icon name="archive" />
- <strong
- class="file-title-name"
- v-html="diffFile.submoduleLink"
- ></strong>
- <clipboard-button
- :text="diffFile.submoduleLink"
- title="Copy file path to clipboard"
- css-class="btn-default btn-transparent btn-clipboard"
- />
- </span>
- </div>
- <template v-else>
- <component
- ref="titleWrapper"
- :is="titleTag"
- :href="diffFile.discussionPath"
- >
- <span v-html="diffFile.blobIcon"></span>
- <span v-if="diffFile.renamedFile">
- <strong
- :title="diffFile.oldPath"
- class="file-title-name has-tooltip"
- data-container="body"
- >
- {{ diffFile.oldPath }}
- </strong>
- &rarr;
- <strong
- :title="diffFile.newPath"
- class="file-title-name has-tooltip"
- data-container="body"
- >
- {{ diffFile.newPath }}
- </strong>
- </span>
-
- <strong
- v-else
- :title="diffFile.oldPath"
- class="file-title-name has-tooltip"
- data-container="body"
- >
- {{ diffFile.filePath }}
- <span v-if="diffFile.deletedFile">
- deleted
- </span>
- </strong>
- </component>
-
- <clipboard-button
- :text="diffFile.filePath"
- title="Copy file path to clipboard"
- css-class="btn-default btn-transparent btn-clipboard"
- />
-
- <small
- v-if="diffFile.modeChanged"
- ref="fileMode"
- >
- {{ diffFile.aMode }} → {{ diffFile.bMode }}
- </small>
- </template>
- </div>
-</template>
diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue
index 802be022ba6..af821df0fd2 100644
--- a/app/assets/javascripts/notes/components/diff_with_note.vue
+++ b/app/assets/javascripts/notes/components/diff_with_note.vue
@@ -1,15 +1,19 @@
<script>
import { mapState, mapActions } from 'vuex';
-import imageDiffHelper from '~/image_diff/helpers/index';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import DiffFileHeader from '~/diffs/components/diff_file_header.vue';
-import SkeletonLoadingContainer from '~/vue_shared/components/skeleton_loading_container.vue';
-import { trimFirstCharOfLineContent } from '~/diffs/store/utils';
+import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
+import ImageDiffOverlay from '~/diffs/components/image_diff_overlay.vue';
+import { GlSkeletonLoading } from '@gitlab/ui';
+import { getDiffMode } from '~/diffs/store/utils';
+
+const FIRST_CHAR_REGEX = /^(\+|-| )/;
export default {
components: {
DiffFileHeader,
- SkeletonLoadingContainer,
+ GlSkeletonLoading,
+ DiffViewer,
+ ImageDiffOverlay,
},
props: {
discussion: {
@@ -24,57 +28,24 @@ export default {
},
computed: {
...mapState({
- noteableData: state => state.notes.noteableData,
+ projectPath: state => state.diffs.projectPath,
}),
- hasTruncatedDiffLines() {
- return this.discussion.truncatedDiffLines && this.discussion.truncatedDiffLines.length !== 0;
- },
- isDiscussionsExpanded() {
- return true; // TODO: @fatihacet - Fix this.
- },
- isCollapsed() {
- return this.diffFile.collapsed || false;
- },
- isImageDiff() {
- return !this.diffFile.text;
- },
- diffFileClass() {
- const { text } = this.diffFile;
- return text ? 'text-file' : 'js-image-file';
+ diffMode() {
+ return getDiffMode(this.discussion.diff_file);
},
- diffFile() {
- return convertObjectPropsToCamelCase(this.discussion.diffFile, { deep: true });
- },
- imageDiffHtml() {
- return this.discussion.imageDiffHtml;
- },
- userColorScheme() {
- return window.gon.user_color_scheme;
- },
- normalizedDiffLines() {
- if (this.discussion.truncatedDiffLines) {
- return this.discussion.truncatedDiffLines.map(line =>
- trimFirstCharOfLineContent(convertObjectPropsToCamelCase(line)),
- );
- }
-
- return [];
+ hasTruncatedDiffLines() {
+ return (
+ this.discussion.truncated_diff_lines && this.discussion.truncated_diff_lines.length !== 0
+ );
},
},
mounted() {
- if (this.isImageDiff) {
- const canCreateNote = false;
- const renderCommentBadge = true;
- imageDiffHelper.initImageDiff(this.$refs.fileHolder, canCreateNote, renderCommentBadge);
- } else if (!this.hasTruncatedDiffLines) {
+ if (!this.hasTruncatedDiffLines) {
this.fetchDiff();
}
},
methods: {
...mapActions(['fetchDiscussionDiffLines']),
- rowTag(html) {
- return html.outerHTML ? 'tr' : 'template';
- },
fetchDiff() {
this.error = false;
this.fetchDiscussionDiffLines(this.discussion)
@@ -83,53 +54,45 @@ export default {
this.error = true;
});
},
+ trimChar(line) {
+ return line.replace(FIRST_CHAR_REGEX, '');
+ },
},
+ userColorSchemeClass: window.gon.user_color_scheme,
};
</script>
<template>
- <div
- ref="fileHolder"
- :class="diffFileClass"
- class="diff-file file-holder"
- >
+ <div :class="{ 'text-file': discussion.diff_file.text }" class="diff-file file-holder">
<diff-file-header
- :diff-file="diffFile"
+ :discussion-path="discussion.discussion_path"
+ :diff-file="discussion.diff_file"
:can-current-user-fork="false"
- :discussions-expanded="isDiscussionsExpanded"
- :expanded="!isCollapsed"
+ :expanded="!discussion.diff_file.collapsed"
/>
<div
- v-if="diffFile.text"
- :class="userColorScheme"
+ v-if="discussion.diff_file.text"
+ :class="$options.userColorSchemeClass"
class="diff-content code"
>
<table>
- <tr
- v-for="line in normalizedDiffLines"
- :key="line.lineCode"
- class="line_holder"
- >
- <td class="diff-line-num old_line">{{ line.oldLine }}</td>
- <td class="diff-line-num new_line">{{ line.newLine }}</td>
- <td
- :class="line.type"
- class="line_content"
- v-html="line.richText"
+ <template v-if="hasTruncatedDiffLines">
+ <tr
+ v-for="line in discussion.truncated_diff_lines"
+ v-once
+ :key="line.line_code"
+ class="line_holder"
>
- </td>
- </tr>
- <tr
- v-if="!hasTruncatedDiffLines"
- class="line_holder line-holder-placeholder"
- >
+ <td class="diff-line-num old_line">{{ line.old_line }}</td>
+ <td class="diff-line-num new_line">{{ line.new_line }}</td>
+ <td :class="line.type" class="line_content" v-html="trimChar(line.rich_text)"></td>
+ </tr>
+ </template>
+ <tr v-if="!hasTruncatedDiffLines" class="line_holder line-holder-placeholder">
<td class="old_line diff-line-num"></td>
<td class="new_line diff-line-num"></td>
- <td
- v-if="error"
- class="js-error-lazy-load-diff diff-loading-error-block"
- >
- Unable to load the diff
+ <td v-if="error" class="js-error-lazy-load-diff diff-loading-error-block">
+ {{ error }} Unable to load the diff
<button
class="btn-link btn-link-retry btn-no-padding js-toggle-lazy-diff-retry-button"
@click="fetchDiff"
@@ -137,29 +100,36 @@ export default {
Try again
</button>
</td>
- <td
- v-else
- class="line_content js-success-lazy-load"
- >
+ <td v-else class="line_content js-success-lazy-load">
<span></span>
- <skeleton-loading-container />
+ <gl-skeleton-loading />
<span></span>
</td>
</tr>
<tr class="notes_holder">
- <td
- class="notes_content"
- colspan="3"
- >
- <slot></slot>
- </td>
+ <td class="notes_content" colspan="3"><slot></slot></td>
</tr>
</table>
</div>
- <div
- v-else
- >
- <div v-html="imageDiffHtml"></div>
+ <div v-else>
+ <diff-viewer
+ :diff-mode="diffMode"
+ :new-path="discussion.diff_file.new_path"
+ :new-sha="discussion.diff_file.diff_refs.head_sha"
+ :old-path="discussion.diff_file.old_path"
+ :old-sha="discussion.diff_file.diff_refs.base_sha"
+ :file-hash="discussion.diff_file.file_hash"
+ :project-path="projectPath"
+ >
+ <image-diff-overlay
+ slot="image-overlay"
+ :discussions="discussion"
+ :file-hash="discussion.diff_file.file_hash"
+ :show-comment-icon="true"
+ :should-toggle-discussion="false"
+ badge-class="image-comment-badge"
+ />
+ </diff-viewer>
<slot></slot>
</div>
</div>
diff --git a/app/assets/javascripts/notes/components/discussion_counter.vue b/app/assets/javascripts/notes/components/discussion_counter.vue
index ad6e7cf501d..c7cfc0f0f3b 100644
--- a/app/assets/javascripts/notes/components/discussion_counter.vue
+++ b/app/assets/javascripts/notes/components/discussion_counter.vue
@@ -1,25 +1,24 @@
<script>
import { mapActions, mapGetters } from 'vuex';
-import resolveSvg from 'icons/_icon_resolve_discussion.svg';
-import resolvedSvg from 'icons/_icon_status_success_solid.svg';
-import mrIssueSvg from 'icons/_icon_mr_issue.svg';
-import nextDiscussionSvg from 'icons/_next_discussion.svg';
-import { pluralize } from '../../lib/utils/text_utility';
+import { GlTooltipDirective } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
import discussionNavigation from '../mixins/discussion_navigation';
-import tooltip from '../../vue_shared/directives/tooltip';
export default {
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
+ },
+ components: {
+ Icon,
},
mixins: [discussionNavigation],
computed: {
...mapGetters([
'getUserData',
'getNoteableData',
- 'discussionCount',
+ 'resolvableDiscussionsCount',
'firstUnresolvedDiscussionId',
- 'resolvedDiscussionCount',
+ 'unresolvedDiscussionsCount',
]),
isLoggedIn() {
return this.getUserData.id;
@@ -27,21 +26,15 @@ export default {
hasNextButton() {
return this.isLoggedIn && !this.allResolved;
},
- countText() {
- return pluralize('discussion', this.discussionCount);
- },
allResolved() {
- return this.resolvedDiscussionCount === this.discussionCount;
+ return this.unresolvedDiscussionsCount === 0;
},
resolveAllDiscussionsIssuePath() {
return this.getNoteableData.create_issue_to_resolve_discussions_path;
},
- },
- created() {
- this.resolveSvg = resolveSvg;
- this.resolvedSvg = resolvedSvg;
- this.mrIssueSvg = mrIssueSvg;
- this.nextDiscussionSvg = nextDiscussionSvg;
+ resolvedDiscussionsCount() {
+ return this.resolvableDiscussionsCount - this.unresolvedDiscussionsCount;
+ },
},
methods: {
...mapActions(['expandDiscussion']),
@@ -56,53 +49,39 @@ export default {
</script>
<template>
- <div class="line-resolve-all-container prepend-top-10">
+ <div v-if="resolvableDiscussionsCount > 0" class="line-resolve-all-container prepend-top-8">
<div>
- <div
- v-if="discussionCount > 0"
- :class="{ 'has-next-btn': hasNextButton }"
- class="line-resolve-all">
+ <div :class="{ 'has-next-btn': hasNextButton }" class="line-resolve-all">
<span
:class="{ 'is-active': allResolved }"
class="line-resolve-btn is-disabled"
- type="button">
- <span
- v-if="allResolved"
- v-html="resolvedSvg"
- ></span>
- <span
- v-else
- v-html="resolveSvg"
- ></span>
+ type="button"
+ >
+ <icon name="check-circle" />
</span>
<span class="line-resolve-text">
- {{ resolvedDiscussionCount }}/{{ discussionCount }} {{ countText }} resolved
+ {{ resolvedDiscussionsCount }}/{{ resolvableDiscussionsCount }}
+ {{ n__('discussion resolved', 'discussions resolved', resolvableDiscussionsCount) }}
</span>
</div>
- <div
- v-if="resolveAllDiscussionsIssuePath && !allResolved"
- class="btn-group"
- role="group">
+ <div v-if="resolveAllDiscussionsIssuePath && !allResolved" class="btn-group" role="group">
<a
- v-tooltip
+ v-gl-tooltip
:href="resolveAllDiscussionsIssuePath"
:title="s__('Resolve all discussions in new issue')"
- data-container="body"
- class="new-issue-for-discussion btn btn-default discussion-create-issue-btn">
- <span v-html="mrIssueSvg"></span>
+ class="new-issue-for-discussion btn btn-default discussion-create-issue-btn"
+ >
+ <icon name="issue-new" />
</a>
</div>
- <div
- v-if="isLoggedIn && !allResolved"
- class="btn-group"
- role="group">
+ <div v-if="isLoggedIn && !allResolved" class="btn-group" role="group">
<button
- v-tooltip
+ v-gl-tooltip
title="Jump to first unresolved discussion"
- data-container="body"
class="btn btn-default discussion-next-btn"
- @click="jumpToFirstUnresolvedDiscussion">
- <span v-html="nextDiscussionSvg"></span>
+ @click="jumpToFirstUnresolvedDiscussion"
+ >
+ <icon name="comment-next" />
</button>
</div>
</div>
diff --git a/app/assets/javascripts/notes/components/discussion_filter.vue b/app/assets/javascripts/notes/components/discussion_filter.vue
new file mode 100644
index 00000000000..86c114a761a
--- /dev/null
+++ b/app/assets/javascripts/notes/components/discussion_filter.vue
@@ -0,0 +1,90 @@
+<script>
+import $ from 'jquery';
+import { mapGetters, mapActions } from 'vuex';
+import Icon from '~/vue_shared/components/icon.vue';
+import { DISCUSSION_FILTERS_DEFAULT_VALUE, HISTORY_ONLY_FILTER_VALUE } from '../constants';
+
+export default {
+ components: {
+ Icon,
+ },
+ props: {
+ filters: {
+ type: Array,
+ required: true,
+ },
+ selectedValue: {
+ type: Number,
+ default: null,
+ required: false,
+ },
+ },
+ data() {
+ return {
+ currentValue: this.selectedValue,
+ defaultValue: DISCUSSION_FILTERS_DEFAULT_VALUE,
+ };
+ },
+ computed: {
+ ...mapGetters(['getNotesDataByProp']),
+ currentFilter() {
+ if (!this.currentValue) return this.filters[0];
+ return this.filters.find(filter => filter.value === this.currentValue);
+ },
+ },
+ mounted() {
+ this.toggleCommentsForm();
+ },
+ methods: {
+ ...mapActions(['filterDiscussion', 'setCommentsDisabled']),
+ selectFilter(value) {
+ const filter = parseInt(value, 10);
+
+ // close dropdown
+ $(this.$refs.dropdownToggle).dropdown('toggle');
+
+ if (filter === this.currentValue) return;
+ this.currentValue = filter;
+ this.filterDiscussion({ path: this.getNotesDataByProp('discussionsPath'), filter });
+ this.toggleCommentsForm();
+ },
+ toggleCommentsForm() {
+ this.setCommentsDisabled(this.currentValue === HISTORY_ONLY_FILTER_VALUE);
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="discussion-filter-container d-inline-block align-bottom">
+ <button
+ id="discussion-filter-dropdown"
+ ref="dropdownToggle"
+ class="btn btn-default qa-discussion-filter"
+ data-toggle="dropdown"
+ aria-expanded="false"
+ >
+ {{ currentFilter.title }} <icon name="chevron-down" />
+ </button>
+ <div
+ class="dropdown-menu dropdown-menu-selectable dropdown-menu-right"
+ aria-labelledby="discussion-filter-dropdown"
+ >
+ <div class="dropdown-content">
+ <ul>
+ <li v-for="filter in filters" :key="filter.value">
+ <button
+ :class="{ 'is-active': filter.value === currentValue }"
+ class="qa-filter-options"
+ type="button"
+ @click="selectFilter(filter.value);"
+ >
+ {{ filter.title }}
+ </button>
+ <div v-if="filter.value === defaultValue" class="dropdown-divider"></div>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/notes/components/discussion_locked_widget.vue b/app/assets/javascripts/notes/components/discussion_locked_widget.vue
index de0a5f8489b..c469a6b7bcd 100644
--- a/app/assets/javascripts/notes/components/discussion_locked_widget.vue
+++ b/app/assets/javascripts/notes/components/discussion_locked_widget.vue
@@ -13,11 +13,7 @@ export default {
<template>
<div class="disabled-comment text-center">
<span class="issuable-note-warning inline">
- <icon
- :size="16"
- name="lock"
- class="icon"
- />
+ <icon :size="16" name="lock" class="icon" />
<span>
This {{ issuableDisplayName }} is locked. Only <b>project members</b> can comment.
</span>
diff --git a/app/assets/javascripts/notes/components/note_actions.vue b/app/assets/javascripts/notes/components/note_actions.vue
index beb53da0e6d..d99694b06e9 100644
--- a/app/assets/javascripts/notes/components/note_actions.vue
+++ b/app/assets/javascripts/notes/components/note_actions.vue
@@ -1,18 +1,16 @@
<script>
import { mapGetters } from 'vuex';
-import emojiSmiling from 'icons/_emoji_slightly_smiling_face.svg';
-import emojiSmile from 'icons/_emoji_smile.svg';
-import emojiSmiley from 'icons/_emoji_smiley.svg';
-import editSvg from 'icons/_icon_pencil.svg';
-import resolveDiscussionSvg from 'icons/_icon_resolve_discussion.svg';
-import resolvedDiscussionSvg from 'icons/_icon_status_success_solid.svg';
-import ellipsisSvg from 'icons/_ellipsis_v.svg';
-import tooltip from '~/vue_shared/directives/tooltip';
+import Icon from '~/vue_shared/components/icon.vue';
+import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
export default {
name: 'NoteActions',
+ components: {
+ Icon,
+ GlLoadingIcon,
+ },
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
authorId: {
@@ -20,7 +18,7 @@ export default {
required: true,
},
noteId: {
- type: String,
+ type: [String, Number],
required: true,
},
noteUrl: {
@@ -35,7 +33,8 @@ export default {
},
reportAbusePath: {
type: String,
- required: true,
+ required: false,
+ default: null,
},
canEdit: {
type: Boolean,
@@ -84,6 +83,9 @@ export default {
shouldShowActionsDropdown() {
return this.currentUserId && (this.canEdit || this.canReportAsAbuse);
},
+ showDeleteAction() {
+ return this.canDelete && !this.canReportAsAbuse && !this.noteUrl;
+ },
isAuthoredByCurrentUser() {
return this.authorId === this.currentUserId;
},
@@ -100,15 +102,6 @@ export default {
return title;
},
},
- created() {
- this.emojiSmiling = emojiSmiling;
- this.emojiSmile = emojiSmile;
- this.emojiSmiley = emojiSmiley;
- this.editSvg = editSvg;
- this.ellipsisSvg = ellipsisSvg;
- this.resolveDiscussionSvg = resolveDiscussionSvg;
- this.resolvedDiscussionSvg = resolvedDiscussionSvg;
- },
methods: {
onEdit() {
this.$emit('handleEdit');
@@ -125,102 +118,76 @@ export default {
<template>
<div class="note-actions">
- <span
- v-if="accessLevel"
- class="note-role user-access-role">
- {{ accessLevel }}
- </span>
- <div
- v-if="canResolve"
- class="note-actions-item">
+ <span v-if="accessLevel" class="note-role user-access-role">{{ accessLevel }}</span>
+ <div v-if="canResolve" class="note-actions-item">
<button
- v-tooltip
+ v-gl-tooltip
:class="{ 'is-disabled': !resolvable, 'is-active': isResolved }"
:title="resolveButtonTitle"
:aria-label="resolveButtonTitle"
type="button"
class="line-resolve-btn note-action-button"
- @click="onResolve">
+ @click="onResolve"
+ >
<template v-if="!isResolving">
- <div
- v-if="isResolved"
- v-html="resolvedDiscussionSvg"></div>
- <div
- v-else
- v-html="resolveDiscussionSvg"></div>
+ <icon name="check-circle" />
</template>
- <gl-loading-icon
- v-else
- inline
- />
+ <gl-loading-icon v-else inline />
</button>
</div>
- <div
- v-if="canAwardEmoji"
- class="note-actions-item">
+ <div v-if="canAwardEmoji" class="note-actions-item">
<a
- v-tooltip
+ v-gl-tooltip.bottom
:class="{ 'js-user-authored': isAuthoredByCurrentUser }"
class="note-action-button note-emoji-button js-add-award js-note-emoji"
data-position="right"
- data-placement="bottom"
- data-container="body"
href="#"
title="Add reaction"
>
- <gl-loading-icon inline/>
- <span
- class="link-highlight award-control-icon-neutral"
- v-html="emojiSmiling">
- </span>
- <span
- class="link-highlight award-control-icon-positive"
- v-html="emojiSmiley">
- </span>
- <span
- class="link-highlight award-control-icon-super-positive"
- v-html="emojiSmile">
- </span>
+ <gl-loading-icon inline />
+ <icon
+ css-classes="link-highlight award-control-icon-neutral"
+ name="emoji_slightly_smiling_face"
+ />
+ <icon css-classes="link-highlight award-control-icon-positive" name="emoji_smiley" />
+ <icon css-classes="link-highlight award-control-icon-super-positive" name="emoji_smiley" />
</a>
</div>
- <div
- v-if="canEdit"
- class="note-actions-item">
+ <div v-if="canEdit" class="note-actions-item">
<button
- v-tooltip
+ v-gl-tooltip.bottom
type="button"
title="Edit comment"
class="note-action-button js-note-edit btn btn-transparent"
- data-container="body"
- data-placement="bottom"
- @click="onEdit">
- <span
- class="link-highlight"
- v-html="editSvg">
- </span>
+ @click="onEdit"
+ >
+ <icon name="pencil" css-classes="link-highlight" />
+ </button>
+ </div>
+ <div v-if="showDeleteAction" class="note-actions-item">
+ <button
+ v-gl-tooltip.bottom
+ type="button"
+ title="Delete comment"
+ class="note-action-button js-note-delete btn btn-transparent"
+ @click="onDelete"
+ >
+ <icon name="remove" class="link-highlight" />
</button>
</div>
- <div
- v-if="shouldShowActionsDropdown"
- class="dropdown more-actions note-actions-item">
+ <div v-else-if="shouldShowActionsDropdown" class="dropdown more-actions note-actions-item">
<button
- v-tooltip
+ v-gl-tooltip.bottom
type="button"
title="More actions"
class="note-action-button more-actions-toggle btn btn-transparent"
data-toggle="dropdown"
- data-container="body"
- data-placement="bottom">
- <span
- class="icon"
- v-html="ellipsisSvg">
- </span>
+ >
+ <icon css-classes="icon" name="ellipsis_v" />
</button>
<ul class="dropdown-menu more-actions-dropdown dropdown-open-left">
<li v-if="canReportAsAbuse">
- <a :href="reportAbusePath">
- Report as abuse
- </a>
+ <a :href="reportAbusePath">{{ __('Report abuse to GitLab') }}</a>
</li>
<li v-if="noteUrl">
<button
@@ -228,17 +195,16 @@ export default {
type="button"
class="btn-default btn-transparent js-btn-copy-note-link"
>
- Copy link
+ {{ __('Copy link') }}
</button>
</li>
<li v-if="canEdit">
<button
class="btn btn-transparent js-note-delete js-note-delete"
type="button"
- @click.prevent="onDelete">
- <span class="text-danger">
- Delete comment
- </span>
+ @click.prevent="onDelete"
+ >
+ <span class="text-danger">{{ __('Delete comment') }}</span>
</button>
</li>
</ul>
diff --git a/app/assets/javascripts/notes/components/note_attachment.vue b/app/assets/javascripts/notes/components/note_attachment.vue
index 34ecbd00c63..b6d8c831e2e 100644
--- a/app/assets/javascripts/notes/components/note_attachment.vue
+++ b/app/assets/javascripts/notes/components/note_attachment.vue
@@ -12,27 +12,12 @@ export default {
<template>
<div class="note-attachment">
- <a
- v-if="attachment.image"
- :href="attachment.url"
- target="_blank"
- rel="noopener noreferrer">
- <img
- :src="attachment.url"
- class="note-image-attach"
- />
+ <a v-if="attachment.image" :href="attachment.url" target="_blank" rel="noopener noreferrer">
+ <img :src="attachment.url" class="note-image-attach" />
</a>
<div class="attachment">
- <a
- v-if="attachment.url"
- :href="attachment.url"
- target="_blank"
- rel="noopener noreferrer">
- <i
- class="fa fa-paperclip"
- aria-hidden="true">
- </i>
- {{ attachment.filename }}
+ <a v-if="attachment.url" :href="attachment.url" target="_blank" rel="noopener noreferrer">
+ <i class="fa fa-paperclip" aria-hidden="true"> </i> {{ attachment.filename }}
</a>
</div>
</div>
diff --git a/app/assets/javascripts/notes/components/note_awards_list.vue b/app/assets/javascripts/notes/components/note_awards_list.vue
index 051b17e9aa9..3d60eb02db8 100644
--- a/app/assets/javascripts/notes/components/note_awards_list.vue
+++ b/app/assets/javascripts/notes/components/note_awards_list.vue
@@ -1,15 +1,16 @@
<script>
import { mapActions, mapGetters } from 'vuex';
-import emojiSmiling from 'icons/_emoji_slightly_smiling_face.svg';
-import emojiSmile from 'icons/_emoji_smile.svg';
-import emojiSmiley from 'icons/_emoji_smiley.svg';
+import { GlTooltipDirective } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
import Flash from '../../flash';
import { glEmojiTag } from '../../emoji';
-import tooltip from '../../vue_shared/directives/tooltip';
export default {
+ components: {
+ Icon,
+ },
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
awards: {
@@ -72,11 +73,6 @@ export default {
return this.noteAuthorId === this.getUserData.id;
},
},
- created() {
- this.emojiSmiling = emojiSmiling;
- this.emojiSmile = emojiSmile;
- this.emojiSmiley = emojiSmiley;
- },
methods: {
...mapActions(['toggleAwardRequest']),
getAwardHTML(name) {
@@ -95,31 +91,22 @@ export default {
return awardList.filter(award => award.user.id === this.getUserData.id).length;
},
awardTitle(awardsList) {
- const hasReactionByCurrentUser = this.hasReactionByCurrentUser(
- awardsList,
- );
+ const hasReactionByCurrentUser = this.hasReactionByCurrentUser(awardsList);
const TOOLTIP_NAME_COUNT = hasReactionByCurrentUser ? 9 : 10;
let awardList = awardsList;
// Filter myself from list if I am awarded.
if (hasReactionByCurrentUser) {
- awardList = awardList.filter(
- award => award.user.id !== this.getUserData.id,
- );
+ awardList = awardList.filter(award => award.user.id !== this.getUserData.id);
}
// Get only 9-10 usernames to show in tooltip text.
- const namesToShow = awardList
- .slice(0, TOOLTIP_NAME_COUNT)
- .map(award => award.user.name);
+ const namesToShow = awardList.slice(0, TOOLTIP_NAME_COUNT).map(award => award.user.name);
// Get the remaining list to use in `and x more` text.
- const remainingAwardList = awardList.slice(
- TOOLTIP_NAME_COUNT,
- awardList.length,
- );
+ const remainingAwardList = awardList.slice(TOOLTIP_NAME_COUNT, awardList.length);
- // Add myself to the begining of the list so title will start with You.
+ // Add myself to the beginning of the list so title will start with You.
if (hasReactionByCurrentUser) {
namesToShow.unshift('You');
}
@@ -128,9 +115,7 @@ export default {
// We have 10+ awarded user, join them with comma and add `and x more`.
if (remainingAwardList.length) {
- title = `${namesToShow.join(', ')}, and ${
- remainingAwardList.length
- } more.`;
+ title = `${namesToShow.join(', ')}, and ${remainingAwardList.length} more.`;
} else if (namesToShow.length > 1) {
// Join all names with comma but not the last one, it will be added with and text.
title = namesToShow.slice(0, namesToShow.length - 1).join(', ');
@@ -170,9 +155,7 @@ export default {
awardName: parsedName,
};
- this.toggleAwardRequest(data).catch(() =>
- Flash('Something went wrong on our end.'),
- );
+ this.toggleAwardRequest(data).catch(() => Flash('Something went wrong on our end.'));
},
},
};
@@ -182,48 +165,42 @@ export default {
<div class="note-awards">
<div class="awards js-awards-block">
<button
- v-tooltip
v-for="(awardList, awardName, index) in groupedAwards"
:key="index"
+ v-gl-tooltip.bottom="{ boundary: 'viewport' }"
:class="getAwardClassBindings(awardList)"
:title="awardTitle(awardList)"
class="btn award-control"
- data-boundary="viewport"
- data-placement="bottom"
type="button"
- @click="handleAward(awardName)">
+ @click="handleAward(awardName);"
+ >
<span v-html="getAwardHTML(awardName)"></span>
- <span class="award-control-text js-counter">
- {{ awardList.length }}
- </span>
+ <span class="award-control-text js-counter">{{ awardList.length }}</span>
</button>
- <div
- v-if="canAwardEmoji"
- class="award-menu-holder">
+ <div v-if="canAwardEmoji" class="award-menu-holder">
<button
- v-tooltip
+ v-gl-tooltip
:class="{ 'js-user-authored': isAuthoredByMe }"
class="award-control btn js-add-award"
title="Add reaction"
aria-label="Add reaction"
data-boundary="viewport"
data-placement="bottom"
- type="button">
- <span
- class="award-control-icon award-control-icon-neutral"
- v-html="emojiSmiling">
+ type="button"
+ >
+ <span class="award-control-icon award-control-icon-neutral">
+ <icon name="emoji_slightly_smiling_face" />
</span>
- <span
- class="award-control-icon award-control-icon-positive"
- v-html="emojiSmiley">
+ <span class="award-control-icon award-control-icon-positive">
+ <icon name="emoji_smiley" />
</span>
- <span
- class="award-control-icon award-control-icon-super-positive"
- v-html="emojiSmile">
+ <span class="award-control-icon award-control-icon-super-positive">
+ <icon name="emoji_smiley" />
</span>
<i
aria-hidden="true"
- class="fa fa-spinner fa-spin award-control-icon award-control-icon-loading"></i>
+ class="fa fa-spinner fa-spin award-control-icon award-control-icon-loading"
+ ></i>
</button>
</div>
</div>
diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue
index 6f4a0709825..c0bee600181 100644
--- a/app/assets/javascripts/notes/components/note_body.vue
+++ b/app/assets/javascripts/notes/components/note_body.vue
@@ -4,7 +4,6 @@ import noteEditedText from './note_edited_text.vue';
import noteAwardsList from './note_awards_list.vue';
import noteAttachment from './note_attachment.vue';
import noteForm from './note_form.vue';
-import TaskList from '../../task_list';
import autosave from '../mixins/autosave';
export default {
@@ -37,14 +36,12 @@ export default {
},
mounted() {
this.renderGFM();
- this.initTaskList();
if (this.isEditing) {
this.initAutoSave(this.note);
}
},
updated() {
- this.initTaskList();
this.renderGFM();
if (this.isEditing) {
@@ -59,15 +56,6 @@ export default {
renderGFM() {
$(this.$refs['note-body']).renderGFM();
},
- initTaskList() {
- if (this.canEdit) {
- this.taskList = new TaskList({
- dataType: 'note',
- fieldName: 'note',
- selector: '.notes',
- });
- }
- },
handleFormUpdate(note, parentElement, callback) {
this.$emit('handleFormUpdate', note, parentElement, callback);
},
@@ -79,13 +67,8 @@ export default {
</script>
<template>
- <div
- ref="note-body"
- :class="{ 'js-task-list-container': canEdit }"
- class="note-body">
- <div
- class="note-text md"
- v-html="note.note_html"></div>
+ <div ref="note-body" :class="{ 'js-task-list-container': canEdit }" class="note-body">
+ <div class="note-text md" v-html="note.note_html"></div>
<note-form
v-if="isEditing"
ref="noteForm"
@@ -100,7 +83,8 @@ export default {
v-if="canEdit"
v-model="note.note"
:data-update-url="note.path"
- class="hidden js-task-list-field"></textarea>
+ class="hidden js-task-list-field"
+ ></textarea>
<note-edited-text
v-if="note.last_edited_at"
:edited-at="note.last_edited_at"
@@ -109,16 +93,13 @@ export default {
class="note_edited_ago"
/>
<note-awards-list
- v-if="note.award_emoji.length"
+ v-if="note.award_emoji && note.award_emoji.length"
:note-id="note.id"
:note-author-id="note.author.id"
:awards="note.award_emoji"
:toggle-award-path="note.toggle_award_path"
:can-award-emoji="note.current_user.can_award_emoji"
/>
- <note-attachment
- v-if="note.attachment"
- :attachment="note.attachment"
- />
+ <note-attachment v-if="note.attachment" :attachment="note.attachment" />
</div>
</template>
diff --git a/app/assets/javascripts/notes/components/note_edited_text.vue b/app/assets/javascripts/notes/components/note_edited_text.vue
index d848335022f..3d3dbbd7fe1 100644
--- a/app/assets/javascripts/notes/components/note_edited_text.vue
+++ b/app/assets/javascripts/notes/components/note_edited_text.vue
@@ -39,17 +39,9 @@ export default {
<div :class="className">
{{ actionText }}
<template v-if="editedBy">
- by
- <a
- :href="editedBy.path"
- class="js-vue-author author-link">
- {{ editedBy.name }}
- </a>
+ by <a :href="editedBy.path" class="js-vue-author author-link"> {{ editedBy.name }} </a>
</template>
{{ actionDetailText }}
- <time-ago-tooltip
- :time="editedAt"
- tooltip-placement="bottom"
- />
+ <time-ago-tooltip :time="editedAt" tooltip-placement="bottom" />
</div>
</template>
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index 29595a2ba73..95164183ccb 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -20,7 +20,7 @@ export default {
default: '',
},
noteId: {
- type: String,
+ type: [String, Number],
required: false,
default: '',
},
@@ -48,13 +48,19 @@ export default {
required: false,
default: '',
},
+ resolveDiscussion: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
updatedNoteBody: this.noteBody,
conflictWhileEditing: false,
isSubmitting: false,
- isResolving: false,
+ isResolving: this.resolveDiscussion,
+ isUnresolving: !this.resolveDiscussion,
resolveAsThread: true,
};
},
@@ -102,6 +108,18 @@ export default {
},
methods: {
...mapActions(['toggleResolveNote']),
+ shouldToggleResolved(shouldResolve, beforeSubmitDiscussionState) {
+ // shouldBeResolved() checks the actual resolution state,
+ // considering batchComments (EEP), if applicable/enabled.
+ const newResolvedStateAfterUpdate =
+ this.shouldBeResolved && this.shouldBeResolved(shouldResolve);
+
+ const shouldToggleState =
+ newResolvedStateAfterUpdate !== undefined &&
+ beforeSubmitDiscussionState !== newResolvedStateAfterUpdate;
+
+ return shouldResolve || shouldToggleState;
+ },
handleUpdate(shouldResolve) {
const beforeSubmitDiscussionState = this.discussionResolved;
this.isSubmitting = true;
@@ -109,7 +127,7 @@ export default {
this.$emit('handleFormUpdate', this.updatedNoteBody, this.$refs.editNoteForm, () => {
this.isSubmitting = false;
- if (shouldResolve) {
+ if (this.shouldToggleResolved(shouldResolve, beforeSubmitDiscussionState)) {
this.resolveHandler(beforeSubmitDiscussionState);
}
});
@@ -134,27 +152,14 @@ export default {
</script>
<template>
- <div
- ref="editNoteForm"
- class="note-edit-form current-note-edit-form js-discussion-note-form">
- <div
- v-if="conflictWhileEditing"
- class="js-conflict-edit-warning alert alert-danger">
+ <div ref="editNoteForm" class="note-edit-form current-note-edit-form js-discussion-note-form">
+ <div v-if="conflictWhileEditing" class="js-conflict-edit-warning alert alert-danger">
This comment has changed since you started editing, please review the
- <a
- :href="noteHash"
- target="_blank"
- rel="noopener noreferrer">
- updated comment
- </a>
- to ensure information is not lost.
+ <a :href="noteHash" target="_blank" rel="noopener noreferrer">updated comment</a> to ensure
+ information is not lost.
</div>
<div class="flash-container timeline-content"></div>
- <form
- :data-line-code="lineCode"
- class="edit-note common-note-form js-quick-submit gfm-form"
- >
-
+ <form :data-line-code="lineCode" class="edit-note common-note-form js-quick-submit gfm-form">
<issue-warning
v-if="hasWarning(getNoteableData)"
:is-locked="isLocked(getNoteableData)"
@@ -166,43 +171,45 @@ export default {
:markdown-docs-path="markdownDocsPath"
:markdown-version="markdownVersion"
:quick-actions-docs-path="quickActionsDocsPath"
- :add-spacing-classes="false">
+ :add-spacing-classes="false"
+ >
<textarea
id="note_note"
ref="textarea"
slot="textarea"
- :data-supports-quick-actions="!isEditing"
v-model="updatedNoteBody"
+ :data-supports-quick-actions="!isEditing"
name="note[note]"
- class="note-textarea js-gfm-input js-note-text
-js-autosize markdown-area js-vue-issue-note-form js-vue-textarea"
+ class="note-textarea js-gfm-input js-note-text js-autosize markdown-area js-vue-issue-note-form js-vue-textarea qa-reply-input"
aria-label="Description"
placeholder="Write a comment or drag your files here…"
- @keydown.meta.enter="handleUpdate()"
- @keydown.ctrl.enter="handleUpdate()"
- @keydown.up="editMyLastNote()"
- @keydown.esc="cancelHandler(true)">
- </textarea>
+ @keydown.meta.enter="handleUpdate();"
+ @keydown.ctrl.enter="handleUpdate();"
+ @keydown.up="editMyLastNote();"
+ @keydown.esc="cancelHandler(true);"
+ ></textarea>
</markdown-field>
<div class="note-form-actions clearfix">
<button
:disabled="isDisabled"
type="button"
- class="js-vue-issue-save btn btn-success js-comment-button "
- @click="handleUpdate()">
+ class="js-vue-issue-save btn btn-success js-comment-button"
+ @click="handleUpdate();"
+ >
{{ saveButtonTitle }}
</button>
<button
v-if="discussion.resolvable"
class="btn btn-nr btn-default append-right-10 js-comment-resolve-button"
- @click.prevent="handleUpdate(true)"
+ @click.prevent="handleUpdate(true);"
>
{{ resolveButtonTitle }}
</button>
<button
class="btn btn-cancel note-edit-cancel js-close-discussion-note-form"
type="button"
- @click="cancelHandler()">
+ @click="cancelHandler();"
+ >
Cancel
</button>
</div>
diff --git a/app/assets/javascripts/notes/components/note_header.vue b/app/assets/javascripts/notes/components/note_header.vue
index d669d12a39b..e1a58e7cb26 100644
--- a/app/assets/javascripts/notes/components/note_header.vue
+++ b/app/assets/javascripts/notes/components/note_header.vue
@@ -14,7 +14,8 @@ export default {
},
createdAt: {
type: String,
- required: true,
+ required: false,
+ default: null,
},
actionText: {
type: String,
@@ -22,8 +23,9 @@ export default {
default: '',
},
noteId: {
- type: String,
- required: true,
+ type: [String, Number],
+ required: false,
+ default: null,
},
includeToggle: {
type: Boolean,
@@ -43,6 +45,9 @@ export default {
noteTimestampLink() {
return `#note_${this.noteId}`;
},
+ hasAuthor() {
+ return this.author && Object.keys(this.author).length;
+ },
},
methods: {
...mapActions(['setTargetNoteHash']),
@@ -58,56 +63,39 @@ export default {
<template>
<div class="note-header-info">
- <div
- v-if="includeToggle"
- class="discussion-actions">
+ <div v-if="includeToggle" class="discussion-actions">
<button
class="note-action-button discussion-toggle-button js-vue-toggle-button"
type="button"
- @click="handleToggle">
- <i
- :class="toggleChevronClass"
- class="fa"
- aria-hidden="true">
- </i>
+ @click="handleToggle"
+ >
+ <i :class="toggleChevronClass" class="fa" aria-hidden="true"> </i>
{{ __('Toggle discussion') }}
</button>
</div>
- <a
- v-if="Object.keys(author).length"
- :href="author.path"
- >
+ <a v-if="hasAuthor" v-once :href="author.path">
<span class="note-header-author-name">{{ author.name }}</span>
- <span
- v-if="author.status_tooltip_html"
- v-html="author.status_tooltip_html"></span>
- <span class="note-headline-light">
- @{{ author.username }}
- </span>
+ <span v-if="author.status_tooltip_html" v-html="author.status_tooltip_html"></span>
+ <span class="note-headline-light"> @{{ author.username }} </span>
</a>
- <span v-else>
- {{ __('A deleted user') }}
- </span>
+ <span v-else> {{ __('A deleted user') }} </span>
<span class="note-headline-light">
<span class="note-headline-meta">
- <template v-if="actionText">
- {{ actionText }}
+ <span class="system-note-message"> <slot></slot> </span>
+ <template v-if="createdAt">
+ <span class="system-note-separator">
+ <template v-if="actionText">
+ {{ actionText }}
+ </template>
+ </span>
+ <a
+ :href="noteTimestampLink"
+ class="note-timestamp system-note-separator"
+ @click="updateTargetNoteHash"
+ >
+ <time-ago-tooltip :time="createdAt" tooltip-placement="bottom" />
+ </a>
</template>
- <span class="system-note-message">
- <slot></slot>
- </span>
- <span class="system-note-separator">
- &middot;
- </span>
- <a
- :href="noteTimestampLink"
- class="note-timestamp system-note-separator"
- @click="updateTargetNoteHash">
- <time-ago-tooltip
- :time="createdAt"
- tooltip-placement="bottom"
- />
- </a>
<i
class="fa fa-spinner fa-spin editing-spinner"
aria-label="Comment is being updated"
diff --git a/app/assets/javascripts/notes/components/note_signed_out_widget.vue b/app/assets/javascripts/notes/components/note_signed_out_widget.vue
index 91f7c269757..e3eb92956b1 100644
--- a/app/assets/javascripts/notes/components/note_signed_out_widget.vue
+++ b/app/assets/javascripts/notes/components/note_signed_out_widget.vue
@@ -16,10 +16,6 @@ export default {
<template>
<div class="disabled-comment text-center">
- Please
- <a :href="registerLink">register</a>
- or
- <a :href="signInLink">sign in</a>
- to reply
+ Please <a :href="registerLink">register</a> or <a :href="signInLink">sign in</a> to reply
</div>
</template>
diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue
index afe86911230..f4991a41325 100644
--- a/app/assets/javascripts/notes/components/noteable_discussion.vue
+++ b/app/assets/javascripts/notes/components/noteable_discussion.vue
@@ -1,16 +1,18 @@
<script>
+import _ from 'underscore';
import { mapActions, mapGetters } from 'vuex';
-import resolveDiscussionsSvg from 'icons/_icon_mr_issue.svg';
-import nextDiscussionsSvg from 'icons/_next_discussion.svg';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { GlTooltipDirective } from '@gitlab/ui';
import { truncateSha } from '~/lib/utils/text_utility';
+import { s__, __, sprintf } from '~/locale';
import systemNote from '~/vue_shared/components/notes/system_note.vue';
-import { s__ } from '~/locale';
+import icon from '~/vue_shared/components/icon.vue';
+import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import Flash from '../../flash';
import { SYSTEM_NOTE } from '../constants';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import noteableNote from './noteable_note.vue';
import noteHeader from './note_header.vue';
+import toggleRepliesWidget from './toggle_replies_widget.vue';
import noteSignedOutWidget from './note_signed_out_widget.vue';
import noteEditedText from './note_edited_text.vue';
import noteForm from './note_form.vue';
@@ -21,24 +23,25 @@ import autosave from '../mixins/autosave';
import noteable from '../mixins/noteable';
import resolvable from '../mixins/resolvable';
import discussionNavigation from '../mixins/discussion_navigation';
-import tooltip from '../../vue_shared/directives/tooltip';
export default {
name: 'NoteableDiscussion',
components: {
+ icon,
noteableNote,
- diffWithNote,
userAvatarLink,
noteHeader,
noteSignedOutWidget,
noteEditedText,
noteForm,
+ toggleRepliesWidget,
placeholderNote,
placeholderSystemNote,
systemNote,
+ TimelineEntryItem,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
mixins: [autosave, noteable, resolvable, discussionNavigation],
props: {
@@ -46,11 +49,6 @@ export default {
type: Object,
required: true,
},
- renderHeader: {
- type: Boolean,
- required: false,
- default: true,
- },
renderDiffFile: {
type: Boolean,
required: false,
@@ -68,43 +66,24 @@ export default {
},
},
data() {
+ const { diff_discussion: isDiffDiscussion, resolved } = this.discussion;
+
return {
isReplying: false,
isResolving: false,
resolveAsThread: true,
+ isRepliesCollapsed: Boolean(!isDiffDiscussion && resolved),
};
},
computed: {
...mapGetters([
'getNoteableData',
- 'discussionCount',
- 'resolvedDiscussionCount',
- 'allDiscussions',
- 'unresolvedDiscussionsIdsByDiff',
- 'unresolvedDiscussionsIdsByDate',
- 'unresolvedDiscussions',
- 'unresolvedDiscussionsIdsOrdered',
'nextUnresolvedDiscussionId',
- 'isLastUnresolvedDiscussion',
+ 'unresolvedDiscussionsCount',
+ 'hasUnresolvedDiscussions',
]),
- transformedDiscussion() {
- return {
- ...this.discussion.notes[0],
- truncatedDiffLines: this.discussion.truncated_diff_lines || [],
- truncatedDiffLinesPath: this.discussion.truncated_diff_lines_path,
- diffFile: this.discussion.diff_file,
- diffDiscussion: this.discussion.diff_discussion,
- imageDiffHtml: this.discussion.image_diff_html,
- active: this.discussion.active,
- discussionPath: this.discussion.discussion_path,
- resolved: this.discussion.resolved,
- resolvedBy: this.discussion.resolved_by,
- resolvedByPush: this.discussion.resolved_by_push,
- resolvedAt: this.discussion.resolved_at,
- };
- },
author() {
- return this.transformedDiscussion.author;
+ return this.initialDiscussion.author;
},
canReply() {
return this.getNoteableData.current_user.can_create_note;
@@ -112,6 +91,15 @@ export default {
newNotePath() {
return this.getNoteableData.create_note_path;
},
+ hasReplies() {
+ return this.discussion.notes.length > 1;
+ },
+ initialDiscussion() {
+ return this.discussion.notes.slice(0, 1)[0];
+ },
+ replies() {
+ return this.discussion.notes.slice(1);
+ },
lastUpdatedBy() {
const { notes } = this.discussion;
@@ -131,34 +119,69 @@ export default {
return null;
},
resolvedText() {
- return this.transformedDiscussion.resolvedByPush ? 'Automatically resolved' : 'Resolved';
- },
- hasMultipleUnresolvedDiscussions() {
- return this.unresolvedDiscussions.length > 1;
- },
- showJumpToNextDiscussion() {
- return (
- this.hasMultipleUnresolvedDiscussions &&
- !this.isLastUnresolvedDiscussion(this.discussion.id, this.discussionsByDiffOrder)
- );
+ return this.discussion.resolved_by_push ? __('Automatically resolved') : __('Resolved');
},
shouldRenderDiffs() {
- const { diffDiscussion, diffFile } = this.transformedDiscussion;
-
- return diffDiscussion && diffFile && this.renderDiffFile;
+ return this.discussion.diff_discussion && this.renderDiffFile;
+ },
+ shouldGroupReplies() {
+ return !this.shouldRenderDiffs && !this.discussion.diff_discussion;
},
wrapperComponent() {
return this.shouldRenderDiffs ? diffWithNote : 'div';
},
wrapperComponentProps() {
if (this.shouldRenderDiffs) {
- return { discussion: convertObjectPropsToCamelCase(this.discussion) };
+ return { discussion: this.discussion };
}
return {};
},
- wrapperClass() {
- return this.isDiffDiscussion ? '' : 'card discussion-wrapper';
+ componentClassName() {
+ if (this.shouldRenderDiffs) {
+ if (!this.lastUpdatedAt && !this.discussion.resolved) {
+ return 'unresolved';
+ }
+ }
+
+ return '';
+ },
+ shouldShowDiscussions() {
+ const { expanded, resolved } = this.discussion;
+ const isResolvedNonDiffDiscussion = !this.discussion.diff_discussion && resolved;
+
+ return expanded || this.alwaysExpanded || isResolvedNonDiffDiscussion;
+ },
+ actionText() {
+ const commitId = this.discussion.commit_id ? truncateSha(this.discussion.commit_id) : '';
+ const linkStart = `<a href="${_.escape(this.discussion.discussion_path)}">`;
+ const linkEnd = '</a>';
+
+ let text = s__('MergeRequests|started a discussion');
+
+ if (this.discussion.for_commit) {
+ text = s__(
+ 'MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}',
+ );
+ } else if (this.discussion.diff_discussion) {
+ if (this.discussion.active) {
+ text = s__('MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}');
+ } else {
+ text = s__(
+ 'MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}',
+ );
+ }
+ }
+
+ return sprintf(
+ text,
+ {
+ commitId,
+ linkStart,
+ linkEnd,
+ },
+ false,
+ );
},
},
watch: {
@@ -166,17 +189,13 @@ export default {
if (this.isReplying) {
this.$nextTick(() => {
// Pass an extra key to separate reply and note edit forms
- this.initAutoSave(this.transformedDiscussion, ['Reply']);
+ this.initAutoSave({ ...this.initialDiscussion, ...this.discussion }, ['Reply']);
});
} else {
this.disposeAutoSave();
}
},
},
- created() {
- this.resolveDiscussionsSvg = resolveDiscussionsSvg;
- this.nextDiscussionsSvg = nextDiscussionsSvg;
- },
methods: {
...mapActions([
'saveNote',
@@ -191,6 +210,7 @@ export default {
if (note.placeholderType === SYSTEM_NOTE) {
return placeholderSystemNote;
}
+
return placeholderNote;
}
@@ -201,11 +221,14 @@ export default {
return noteableNote;
},
componentData(note) {
- return note.isPlaceholderNote ? this.discussion.notes[0] : note;
+ return note.isPlaceholderNote ? note.notes[0] : note;
},
toggleDiscussionHandler() {
this.toggleDiscussion({ discussionId: this.discussion.id });
},
+ toggleReplies() {
+ this.isRepliesCollapsed = !this.isRepliesCollapsed;
+ },
showReplyForm() {
this.isReplying = true;
},
@@ -273,175 +296,156 @@ Please check your network connection and try again.`;
</script>
<template>
- <li class="note note-discussion timeline-entry">
- <div class="timeline-entry-inner">
- <div class="timeline-icon">
- <user-avatar-link
- v-if="author"
- :link-href="author.path"
- :img-src="author.avatar_url"
- :img-alt="author.name"
- :img-size="40"
- />
- </div>
- <div class="timeline-content">
- <div
- :data-discussion-id="transformedDiscussion.discussion_id"
- class="discussion js-discussion-container"
- >
- <div
- v-if="renderHeader"
- class="discussion-header"
- >
- <note-header
- :author="author"
- :created-at="transformedDiscussion.created_at"
- :note-id="transformedDiscussion.id"
- :include-toggle="true"
- :expanded="discussion.expanded"
- @toggleHandler="toggleDiscussionHandler"
- >
- <template v-if="transformedDiscussion.diffDiscussion">
- started a discussion on
- <a :href="transformedDiscussion.discussionPath">
- <template v-if="transformedDiscussion.active">
- the diff
- </template>
- <template v-else>
- an old version of the diff
- </template>
- </a>
- </template>
- <template v-else-if="discussion.for_commit">
- started a discussion on commit
- <a :href="discussion.discussion_path">
- {{ truncateSha(discussion.commit_id) }}
- </a>
- </template>
- <template v-else>
- started a discussion
- </template>
- </note-header>
- <note-edited-text
- v-if="transformedDiscussion.resolved"
- :edited-at="transformedDiscussion.resolvedAt"
- :edited-by="transformedDiscussion.resolvedBy"
- :action-text="resolvedText"
- class-name="discussion-headline-light js-discussion-headline"
- />
- <note-edited-text
- v-else-if="lastUpdatedAt"
- :edited-at="lastUpdatedAt"
- :edited-by="lastUpdatedBy"
- action-text="Last updated"
- class-name="discussion-headline-light js-discussion-headline"
+ <timeline-entry-item class="note note-discussion" :class="componentClassName">
+ <div class="timeline-content">
+ <div :data-discussion-id="discussion.id" class="discussion js-discussion-container">
+ <div v-if="shouldRenderDiffs" class="discussion-header note-wrapper">
+ <div v-once class="timeline-icon">
+ <user-avatar-link
+ v-if="author"
+ :link-href="author.path"
+ :img-src="author.avatar_url"
+ :img-alt="author.name"
+ :img-size="40"
/>
</div>
- <div
- v-if="discussion.expanded || alwaysExpanded"
- class="discussion-body">
- <component
- :is="wrapperComponent"
- v-bind="wrapperComponentProps"
- :class="wrapperClass"
- >
- <div class="discussion-notes">
- <ul class="notes">
+ <note-header
+ :author="author"
+ :created-at="initialDiscussion.created_at"
+ :note-id="initialDiscussion.id"
+ :include-toggle="true"
+ :expanded="discussion.expanded"
+ @toggleHandler="toggleDiscussionHandler"
+ >
+ <span v-html="actionText"></span>
+ </note-header>
+ <note-edited-text
+ v-if="discussion.resolved"
+ :edited-at="discussion.resolved_at"
+ :edited-by="discussion.resolved_by"
+ :action-text="resolvedText"
+ class-name="discussion-headline-light js-discussion-headline"
+ />
+ <note-edited-text
+ v-else-if="lastUpdatedAt"
+ :edited-at="lastUpdatedAt"
+ :edited-by="lastUpdatedBy"
+ action-text="Last updated"
+ class-name="discussion-headline-light js-discussion-headline"
+ />
+ </div>
+ <div v-if="shouldShowDiscussions" class="discussion-body">
+ <component
+ :is="wrapperComponent"
+ v-bind="wrapperComponentProps"
+ class="card discussion-wrapper"
+ >
+ <div class="discussion-notes">
+ <ul class="notes">
+ <template v-if="shouldGroupReplies">
+ <component
+ :is="componentName(initialDiscussion)"
+ :note="componentData(initialDiscussion)"
+ @handleDeleteNote="deleteNoteHandler"
+ >
+ <slot slot="avatar-badge" name="avatar-badge"></slot>
+ </component>
+ <toggle-replies-widget
+ v-if="hasReplies"
+ :collapsed="isRepliesCollapsed"
+ :replies="replies"
+ @toggle="toggleReplies"
+ />
+ <template v-if="!isRepliesCollapsed">
+ <component
+ :is="componentName(note)"
+ v-for="note in replies"
+ :key="note.id"
+ :note="componentData(note)"
+ @handleDeleteNote="deleteNoteHandler"
+ />
+ </template>
+ </template>
+ <template v-else>
<component
- v-for="note in discussion.notes"
:is="componentName(note)"
- :note="componentData(note)"
+ v-for="(note, index) in discussion.notes"
:key="note.id"
+ :note="componentData(note)"
@handleDeleteNote="deleteNoteHandler"
- />
- </ul>
- <div
- :class="{ 'is-replying': isReplying }"
- class="discussion-reply-holder"
- >
- <template v-if="!isReplying && canReply">
+ >
+ <slot v-if="index === 0" slot="avatar-badge" name="avatar-badge"></slot>
+ </component>
+ </template>
+ </ul>
+ <div
+ v-if="!isRepliesCollapsed"
+ :class="{ 'is-replying': isReplying }"
+ class="discussion-reply-holder"
+ >
+ <template v-if="!isReplying && canReply">
+ <div class="discussion-with-resolve-btn">
+ <button
+ type="button"
+ class="js-vue-discussion-reply btn btn-text-field mr-sm-2 qa-discussion-reply"
+ title="Add a reply"
+ @click="showReplyForm"
+ >
+ Reply...
+ </button>
+ <div v-if="discussion.resolvable">
+ <button
+ type="button"
+ class="btn btn-default mr-sm-2"
+ @click="resolveHandler();"
+ >
+ <i v-if="isResolving" aria-hidden="true" class="fa fa-spinner fa-spin"></i>
+ {{ resolveButtonTitle }}
+ </button>
+ </div>
<div
- class="btn-group d-flex discussion-with-resolve-btn"
- role="group">
- <div
- class="btn-group w-100"
- role="group">
- <button
- type="button"
- class="js-vue-discussion-reply btn btn-text-field mr-2"
- title="Add a reply"
- @click="showReplyForm">Reply...</button>
+ v-if="discussion.resolvable"
+ class="btn-group discussion-actions ml-sm-2"
+ role="group"
+ >
+ <div v-if="!discussionResolved" class="btn-group" role="group">
+ <a
+ v-gl-tooltip
+ :href="discussion.resolve_with_issue_path"
+ :title="s__('MergeRequests|Resolve this discussion in a new issue')"
+ class="new-issue-for-discussion btn btn-default discussion-create-issue-btn"
+ >
+ <icon name="issue-new" />
+ </a>
</div>
- <div
- v-if="discussion.resolvable"
- class="btn-group"
- role="group">
+ <div v-if="hasUnresolvedDiscussions" class="btn-group" role="group">
<button
- type="button"
- class="btn btn-default mr-2"
- @click="resolveHandler()"
+ v-gl-tooltip
+ class="btn btn-default discussion-next-btn"
+ title="Jump to next unresolved discussion"
+ @click="jumpToNextDiscussion"
>
- <i
- v-if="isResolving"
- aria-hidden="true"
- class="fa fa-spinner fa-spin"
- ></i>
- {{ resolveButtonTitle }}
+ <icon name="comment-next" />
</button>
</div>
- <div
- v-if="discussion.resolvable"
- class="btn-group discussion-actions"
- role="group"
- >
- <div
- v-if="!discussionResolved"
- class="btn-group"
- role="group">
- <a
- v-tooltip
- :href="discussion.resolve_with_issue_path"
- :title="s__('MergeRequests|Resolve this discussion in a new issue')"
- class="new-issue-for-discussion btn
- btn-default discussion-create-issue-btn"
- data-container="body"
- >
- <span v-html="resolveDiscussionsSvg"></span>
- </a>
- </div>
- <div
- v-if="showJumpToNextDiscussion"
- class="btn-group"
- role="group">
- <button
- v-tooltip
- class="btn btn-default discussion-next-btn"
- title="Jump to next unresolved discussion"
- data-container="body"
- @click="jumpToNextDiscussion"
- >
- <span v-html="nextDiscussionsSvg"></span>
- </button>
- </div>
- </div>
</div>
- </template>
- <note-form
- v-if="isReplying"
- ref="noteForm"
- :discussion="discussion"
- :is-editing="false"
- save-button-title="Comment"
- @handleFormUpdate="saveReply"
- @cancelForm="cancelReplyForm"
- />
- <note-signed-out-widget v-if="!canReply" />
- </div>
+ </div>
+ </template>
+ <note-form
+ v-if="isReplying"
+ ref="noteForm"
+ :discussion="discussion"
+ :is-editing="false"
+ save-button-title="Comment"
+ @handleFormUpdate="saveReply"
+ @cancelForm="cancelReplyForm"
+ />
+ <note-signed-out-widget v-if="!canReply" />
</div>
- </component>
- </div>
+ </div>
+ </component>
</div>
</div>
</div>
- </li>
+ </timeline-entry-item>
</template>
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index 7579fc852c6..a17be51353e 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -2,6 +2,7 @@
import $ from 'jquery';
import { mapGetters, mapActions } from 'vuex';
import { escape } from 'underscore';
+import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import Flash from '../../flash';
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import noteHeader from './note_header.vue';
@@ -18,6 +19,7 @@ export default {
noteHeader,
noteActions,
noteBody,
+ TimelineEntryItem,
},
mixins: [noteable, resolvable],
props: {
@@ -46,13 +48,14 @@ export default {
'is-requesting being-posted': this.isRequesting,
'disabled-content': this.isDeleting,
target: this.isTarget,
+ 'is-editable': this.note.current_user.can_edit,
};
},
canResolve() {
return this.note.resolvable && !!this.getUserData.id;
},
canReportAsAbuse() {
- return this.note.report_abuse_path && this.author.id !== this.getUserData.id;
+ return !!this.note.report_abuse_path && this.author.id !== this.getUserData.id;
},
noteAnchorId() {
return `note_${this.note.id}`;
@@ -81,13 +84,17 @@ export default {
...mapActions(['deleteNote', 'updateNote', 'toggleResolveNote', 'scrollToNoteIfNeeded']),
editHandler() {
this.isEditing = true;
+ this.$emit('handleEdit');
},
deleteHandler() {
+ const typeOfComment = this.note.isDraft ? 'pending comment' : 'comment';
// eslint-disable-next-line no-alert
- if (window.confirm('Are you sure you want to delete this comment?')) {
+ if (window.confirm(`Are you sure you want to delete this ${typeOfComment}?`)) {
this.isDeleting = true;
this.$emit('handleDeleteNote', this.note);
+ if (this.note.isDraft) return;
+
this.deleteNote(this.note)
.then(() => {
this.isDeleting = false;
@@ -98,7 +105,20 @@ export default {
});
}
},
+ updateSuccess() {
+ this.isEditing = false;
+ this.isRequesting = false;
+ this.oldContent = null;
+ $(this.$refs.noteBody.$el).renderGFM();
+ this.$refs.noteBody.resetAutoSave();
+ this.$emit('updateSuccess');
+ },
formUpdateHandler(noteText, parentElement, callback) {
+ this.$emit('handleUpdateNote', {
+ note: this.note,
+ noteText,
+ callback: () => this.updateSuccess(),
+ });
const data = {
endpoint: this.note.path,
note: {
@@ -113,11 +133,7 @@ export default {
this.updateNote(data)
.then(() => {
- this.isEditing = false;
- this.isRequesting = false;
- this.oldContent = null;
- $(this.$refs.noteBody.$el).renderGFM();
- this.$refs.noteBody.resetAutoSave();
+ this.updateSuccess();
callback();
})
.catch(() => {
@@ -142,6 +158,7 @@ export default {
this.oldContent = null;
}
this.isEditing = false;
+ this.$emit('cancelForm');
},
recoverNoteContent(noteText) {
// we need to do this to prevent noteForm inconsistent content warning
@@ -154,58 +171,60 @@ export default {
</script>
<template>
- <li
+ <timeline-entry-item
:id="noteAnchorId"
:class="classNameBindings"
:data-award-url="note.toggle_award_path"
:data-note-id="note.id"
- class="note timeline-entry"
+ class="note note-wrapper"
>
- <div class="timeline-entry-inner">
- <div class="timeline-icon">
- <user-avatar-link
- :link-href="author.path"
- :img-src="author.avatar_url"
- :img-alt="author.name"
- :img-size="40"
+ <div v-once class="timeline-icon">
+ <user-avatar-link
+ :link-href="author.path"
+ :img-src="author.avatar_url"
+ :img-alt="author.name"
+ :img-size="40"
+ >
+ <slot slot="avatar-badge" name="avatar-badge"> </slot>
+ </user-avatar-link>
+ </div>
+ <div class="timeline-content">
+ <div class="note-header">
+ <note-header
+ v-once
+ :author="author"
+ :created-at="note.created_at"
+ :note-id="note.id"
+ action-text="commented"
/>
- </div>
- <div class="timeline-content">
- <div class="note-header">
- <note-header
- :author="author"
- :created-at="note.created_at"
- :note-id="note.id"
- />
- <note-actions
- :author-id="author.id"
- :note-id="note.id"
- :note-url="note.noteable_note_url"
- :access-level="note.human_access"
- :can-edit="note.current_user.can_edit"
- :can-award-emoji="note.current_user.can_award_emoji"
- :can-delete="note.current_user.can_edit"
- :can-report-as-abuse="canReportAsAbuse"
- :can-resolve="note.current_user.can_resolve"
- :report-abuse-path="note.report_abuse_path"
- :resolvable="note.resolvable"
- :is-resolved="note.resolved"
- :is-resolving="isResolving"
- :resolved-by="note.resolved_by"
- @handleEdit="editHandler"
- @handleDelete="deleteHandler"
- @handleResolve="resolveHandler"
- />
- </div>
- <note-body
- ref="noteBody"
- :note="note"
+ <note-actions
+ :author-id="author.id"
+ :note-id="note.id"
+ :note-url="note.noteable_note_url"
+ :access-level="note.human_access"
:can-edit="note.current_user.can_edit"
- :is-editing="isEditing"
- @handleFormUpdate="formUpdateHandler"
- @cancelForm="formCancelHandler"
+ :can-award-emoji="note.current_user.can_award_emoji"
+ :can-delete="note.current_user.can_edit"
+ :can-report-as-abuse="canReportAsAbuse"
+ :can-resolve="note.current_user.can_resolve"
+ :report-abuse-path="note.report_abuse_path"
+ :resolvable="note.resolvable"
+ :is-resolved="note.resolved"
+ :is-resolving="isResolving"
+ :resolved-by="note.resolved_by"
+ @handleEdit="editHandler"
+ @handleDelete="deleteHandler"
+ @handleResolve="resolveHandler"
/>
</div>
+ <note-body
+ ref="noteBody"
+ :note="note"
+ :can-edit="note.current_user.can_edit"
+ :is-editing="isEditing"
+ @handleFormUpdate="formUpdateHandler"
+ @cancelForm="formCancelHandler"
+ />
</div>
- </li>
+ </timeline-entry-item>
</template>
diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue
index 42c87fdf54a..6e6efb04753 100644
--- a/app/assets/javascripts/notes/components/notes_app.vue
+++ b/app/assets/javascripts/notes/components/notes_app.vue
@@ -11,6 +11,7 @@ import commentForm from './comment_form.vue';
import placeholderNote from '../../vue_shared/components/notes/placeholder_note.vue';
import placeholderSystemNote from '../../vue_shared/components/notes/placeholder_system_note.vue';
import skeletonLoadingContainer from '../../vue_shared/components/notes/skeleton_note.vue';
+import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user';
export default {
name: 'NotesApp',
@@ -21,6 +22,7 @@ export default {
commentForm,
placeholderNote,
placeholderSystemNote,
+ skeletonLoadingContainer,
},
props: {
noteableData: {
@@ -49,11 +51,18 @@ export default {
},
data() {
return {
- isLoading: true,
+ isFetching: false,
+ currentFilter: null,
};
},
computed: {
- ...mapGetters(['isNotesFetched', 'discussions', 'getNotesDataByProp', 'discussionCount']),
+ ...mapGetters([
+ 'isNotesFetched',
+ 'discussions',
+ 'getNotesDataByProp',
+ 'isLoading',
+ 'commentsDisabled',
+ ]),
noteableType() {
return this.noteableData.noteableType;
},
@@ -96,52 +105,46 @@ export default {
});
}
},
+ updated() {
+ this.$nextTick(() => highlightCurrentUser(this.$el.querySelectorAll('.gfm-project_member')));
+ },
methods: {
- ...mapActions({
- fetchDiscussions: 'fetchDiscussions',
- poll: 'poll',
- actionToggleAward: 'toggleAward',
- scrollToNoteIfNeeded: 'scrollToNoteIfNeeded',
- setNotesData: 'setNotesData',
- setNoteableData: 'setNoteableData',
- setUserData: 'setUserData',
- setLastFetchedAt: 'setLastFetchedAt',
- setTargetNoteHash: 'setTargetNoteHash',
- toggleDiscussion: 'toggleDiscussion',
- setNotesFetchedState: 'setNotesFetchedState',
- }),
- getComponentName(discussion) {
- if (discussion.isSkeletonNote) {
- return skeletonLoadingContainer;
- }
- if (discussion.isPlaceholderNote) {
- if (discussion.placeholderType === constants.SYSTEM_NOTE) {
- return placeholderSystemNote;
- }
- return placeholderNote;
- } else if (discussion.individual_note) {
- return discussion.notes[0].system ? systemNote : noteableNote;
- }
-
- return noteableDiscussion;
- },
- getComponentData(discussion) {
- return discussion.individual_note ? { note: discussion.notes[0] } : { discussion };
- },
+ ...mapActions([
+ 'setLoadingState',
+ 'fetchDiscussions',
+ 'poll',
+ 'toggleAward',
+ 'scrollToNoteIfNeeded',
+ 'setNotesData',
+ 'setNoteableData',
+ 'setUserData',
+ 'setLastFetchedAt',
+ 'setTargetNoteHash',
+ 'toggleDiscussion',
+ 'setNotesFetchedState',
+ 'expandDiscussion',
+ 'startTaskList',
+ ]),
fetchNotes() {
- return this.fetchDiscussions(this.getNotesDataByProp('discussionsPath'))
+ if (this.isFetching) return null;
+
+ this.isFetching = true;
+
+ return this.fetchDiscussions({ path: this.getNotesDataByProp('discussionsPath') })
.then(() => {
this.initPolling();
})
.then(() => {
- this.isLoading = false;
+ this.setLoadingState(false);
this.setNotesFetchedState(true);
eventHub.$emit('fetchedNotesData');
+ this.isFetching = false;
})
.then(() => this.$nextTick())
+ .then(() => this.startTaskList())
.then(() => this.checkLocationHash())
.catch(() => {
- this.isLoading = false;
+ this.setLoadingState(false);
this.setNotesFetchedState(true);
Flash('Something went wrong while fetching comments. Please try again.');
});
@@ -161,40 +164,50 @@ export default {
const noteId = hash && hash.replace(/^note_/, '');
if (noteId) {
- this.discussions.forEach(discussion => {
- if (discussion.notes) {
- discussion.notes.forEach(note => {
- if (`${note.id}` === `${noteId}`) {
- // FIXME: this modifies the store state without using a mutation/action
- Object.assign(discussion, { expanded: true });
- }
- });
- }
- });
+ const discussion = this.discussions.find(d => d.notes.some(({ id }) => id === noteId));
+
+ if (discussion) {
+ this.expandDiscussion({ discussionId: discussion.id });
+ }
}
},
},
+ systemNote: constants.SYSTEM_NOTE,
};
</script>
<template>
- <div
- v-show="shouldShow"
- id="notes"
- >
- <ul
- id="notes-list"
- class="notes main-notes-list timeline"
- >
- <component
- v-for="discussion in allDiscussions"
- :is="getComponentName(discussion)"
- v-bind="getComponentData(discussion)"
- :key="discussion.id"
- />
+ <div v-show="shouldShow" id="notes">
+ <ul id="notes-list" class="notes main-notes-list timeline">
+ <template v-for="discussion in allDiscussions">
+ <skeleton-loading-container v-if="discussion.isSkeletonNote" :key="discussion.id" />
+ <template v-else-if="discussion.isPlaceholderNote">
+ <placeholder-system-note
+ v-if="discussion.placeholderType === $options.systemNote"
+ :key="discussion.id"
+ :note="discussion.notes[0]"
+ />
+ <placeholder-note v-else :key="discussion.id" :note="discussion.notes[0]" />
+ </template>
+ <template v-else-if="discussion.individual_note">
+ <system-note
+ v-if="discussion.notes[0].system"
+ :key="discussion.id"
+ :note="discussion.notes[0]"
+ />
+ <noteable-note v-else :key="discussion.id" :note="discussion.notes[0]" />
+ </template>
+ <noteable-discussion
+ v-else
+ :key="discussion.id"
+ :discussion="discussion"
+ :render-diff-file="true"
+ />
+ </template>
</ul>
<comment-form
+ v-if="!commentsDisabled"
:noteable-type="noteableType"
:markdown-version="markdownVersion"
/>
diff --git a/app/assets/javascripts/notes/components/toggle_replies_widget.vue b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
new file mode 100644
index 00000000000..72a8ff28466
--- /dev/null
+++ b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
@@ -0,0 +1,73 @@
+<script>
+import _ from 'underscore';
+import Icon from '~/vue_shared/components/icon.vue';
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+
+export default {
+ components: {
+ Icon,
+ UserAvatarLink,
+ TimeAgoTooltip,
+ },
+ props: {
+ collapsed: {
+ type: Boolean,
+ required: true,
+ },
+ replies: {
+ type: Array,
+ required: true,
+ },
+ },
+ computed: {
+ lastReply() {
+ return this.replies[this.replies.length - 1];
+ },
+ uniqueAuthors() {
+ const authors = this.replies.map(reply => reply.author || {});
+
+ return _.uniq(authors, author => author.username);
+ },
+ className() {
+ return this.collapsed ? 'collapsed' : 'expanded';
+ },
+ },
+ methods: {
+ toggle() {
+ this.$emit('toggle');
+ },
+ },
+};
+</script>
+
+<template>
+ <li :class="className" class="replies-toggle js-toggle-replies">
+ <template v-if="collapsed">
+ <icon name="chevron-right" @click.native="toggle" />
+ <div>
+ <user-avatar-link
+ v-for="author in uniqueAuthors"
+ :key="author.username"
+ :link-href="author.path"
+ :img-alt="author.name"
+ :img-src="author.avatar_url"
+ :img-size="26"
+ :tooltip-text="author.name"
+ tooltip-placement="bottom"
+ />
+ </div>
+ <button class="btn btn-link js-replies-text" type="button" @click="toggle">
+ {{ replies.length }} {{ n__('reply', 'replies', replies.length) }}
+ </button>
+ {{ __('Last reply by') }}
+ <a :href="lastReply.author.path" class="btn btn-link author-link">
+ {{ lastReply.author.name }}
+ </a>
+ <time-ago-tooltip :time="lastReply.created_at" tooltip-placement="bottom" />
+ </template>
+ <span v-else class="collapse-replies-btn js-collapse-replies" @click="toggle">
+ <icon name="chevron-down" /> {{ s__('Notes|Collapse replies') }}
+ </span>
+ </li>
+</template>
diff --git a/app/assets/javascripts/notes/constants.js b/app/assets/javascripts/notes/constants.js
index 2c3e07c0506..3147dc64c27 100644
--- a/app/assets/javascripts/notes/constants.js
+++ b/app/assets/javascripts/notes/constants.js
@@ -15,6 +15,8 @@ export const MERGE_REQUEST_NOTEABLE_TYPE = 'MergeRequest';
export const UNRESOLVE_NOTE_METHOD_NAME = 'delete';
export const RESOLVE_NOTE_METHOD_NAME = 'post';
export const DESCRIPTION_TYPE = 'changed the description';
+export const HISTORY_ONLY_FILTER_VALUE = 2;
+export const DISCUSSION_FILTERS_DEFAULT_VALUE = 0;
export const NOTEABLE_TYPE_MAPPING = {
Issue: ISSUE_NOTEABLE_TYPE,
diff --git a/app/assets/javascripts/notes/discussion_filters.js b/app/assets/javascripts/notes/discussion_filters.js
new file mode 100644
index 00000000000..5c5f38a3fb0
--- /dev/null
+++ b/app/assets/javascripts/notes/discussion_filters.js
@@ -0,0 +1,35 @@
+import Vue from 'vue';
+import DiscussionFilter from './components/discussion_filter.vue';
+
+export default store => {
+ const discussionFilterEl = document.getElementById('js-vue-discussion-filter');
+
+ if (discussionFilterEl) {
+ const { defaultFilter, notesFilters } = discussionFilterEl.dataset;
+ const selectedValue = defaultFilter ? parseInt(defaultFilter, 10) : null;
+ const filterValues = notesFilters ? JSON.parse(notesFilters) : {};
+ const filters = Object.keys(filterValues).map(entry => ({
+ title: entry,
+ value: filterValues[entry],
+ }));
+
+ return new Vue({
+ el: discussionFilterEl,
+ name: 'DiscussionFilter',
+ components: {
+ DiscussionFilter,
+ },
+ store,
+ render(createElement) {
+ return createElement('discussion-filter', {
+ props: {
+ filters,
+ selectedValue,
+ },
+ });
+ },
+ });
+ }
+
+ return null;
+};
diff --git a/app/assets/javascripts/notes/index.js b/app/assets/javascripts/notes/index.js
index 3aef30c608c..2f715c85fa6 100644
--- a/app/assets/javascripts/notes/index.js
+++ b/app/assets/javascripts/notes/index.js
@@ -1,10 +1,13 @@
import Vue from 'vue';
import notesApp from './components/notes_app.vue';
+import initDiscussionFilters from './discussion_filters';
import createStore from './stores';
document.addEventListener('DOMContentLoaded', () => {
const store = createStore();
+ initDiscussionFilters(store);
+
return new Vue({
el: '#js-vue-notes',
components: {
diff --git a/app/assets/javascripts/notes/mixins/resolvable.js b/app/assets/javascripts/notes/mixins/resolvable.js
index cd8394e0619..8edf3d088bb 100644
--- a/app/assets/javascripts/notes/mixins/resolvable.js
+++ b/app/assets/javascripts/notes/mixins/resolvable.js
@@ -36,7 +36,7 @@ export default {
const discussion = this.resolveAsThread;
const endpoint = discussion ? this.discussion.resolve_path : `${this.note.path}/resolve`;
- this.toggleResolveNote({ endpoint, isResolved, discussion })
+ return this.toggleResolveNote({ endpoint, isResolved, discussion })
.then(() => {
this.isResolving = false;
})
diff --git a/app/assets/javascripts/notes/services/notes_service.js b/app/assets/javascripts/notes/services/notes_service.js
index f5dce94caad..47a6f07cce2 100644
--- a/app/assets/javascripts/notes/services/notes_service.js
+++ b/app/assets/javascripts/notes/services/notes_service.js
@@ -5,8 +5,9 @@ import * as constants from '../constants';
Vue.use(VueResource);
export default {
- fetchDiscussions(endpoint) {
- return Vue.http.get(endpoint);
+ fetchDiscussions(endpoint, filter) {
+ const config = filter !== undefined ? { params: { notes_filter: filter } } : null;
+ return Vue.http.get(endpoint, config);
},
deleteNote(endpoint) {
return Vue.http.delete(endpoint);
diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js
index 68df63b8539..b4befdd6e4a 100644
--- a/app/assets/javascripts/notes/stores/actions.js
+++ b/app/assets/javascripts/notes/stores/actions.js
@@ -1,6 +1,8 @@
+import Vue from 'vue';
import $ from 'jquery';
import axios from '~/lib/utils/axios_utils';
import Visibility from 'visibilityjs';
+import TaskList from '../../task_list';
import Flash from '../../flash';
import Poll from '../../lib/utils/poll';
import * as types from './mutation_types';
@@ -9,8 +11,9 @@ import * as constants from '../constants';
import service from '../services/notes_service';
import loadAwardsHandler from '../../awards_handler';
import sidebarTimeTrackingEventHub from '../../sidebar/event_hub';
-import { isInViewport, scrollToElement } from '../../lib/utils/common_utils';
+import { isInViewport, scrollToElement, isInMRPage } from '../../lib/utils/common_utils';
import mrWidgetEventHub from '../../vue_merge_request_widget/event_hub';
+import { __ } from '~/locale';
let eTagPoll;
@@ -36,45 +39,42 @@ export const setNotesFetchedState = ({ commit }, state) =>
export const toggleDiscussion = ({ commit }, data) => commit(types.TOGGLE_DISCUSSION, data);
-export const fetchDiscussions = ({ commit }, path) =>
+export const fetchDiscussions = ({ commit, dispatch }, { path, filter }) =>
service
- .fetchDiscussions(path)
+ .fetchDiscussions(path, filter)
.then(res => res.json())
.then(discussions => {
commit(types.SET_INITIAL_DISCUSSIONS, discussions);
+ dispatch('updateResolvableDiscussonsCounts');
});
-export const refetchDiscussionById = ({ commit, state }, { path, discussionId }) =>
- new Promise(resolve => {
- service
- .fetchDiscussions(path)
- .then(res => res.json())
- .then(discussions => {
- const selectedDiscussion = discussions.find(discussion => discussion.id === discussionId);
- if (selectedDiscussion) {
- commit(types.UPDATE_DISCUSSION, selectedDiscussion);
- // We need to refetch as it is now the transformed one in state
- const discussion = utils.findNoteObjectById(state.discussions, discussionId);
-
- resolve(discussion);
- }
- })
- .catch(() => {});
- });
+export const updateDiscussion = ({ commit, state }, discussion) => {
+ commit(types.UPDATE_DISCUSSION, discussion);
+
+ return utils.findNoteObjectById(state.discussions, discussion.id);
+};
-export const deleteNote = ({ commit, dispatch }, note) =>
+export const deleteNote = ({ commit, dispatch, state }, note) =>
service.deleteNote(note.path).then(() => {
+ const discussion = state.discussions.find(({ id }) => id === note.discussion_id);
+
commit(types.DELETE_NOTE, note);
dispatch('updateMergeRequestWidget');
+ dispatch('updateResolvableDiscussonsCounts');
+
+ if (isInMRPage()) {
+ dispatch('diffs/removeDiscussionsFromDiff', discussion);
+ }
});
-export const updateNote = ({ commit }, { endpoint, note }) =>
+export const updateNote = ({ commit, dispatch }, { endpoint, note }) =>
service
.updateNote(endpoint, note)
.then(res => res.json())
.then(res => {
commit(types.UPDATE_NOTE, res);
+ dispatch('startTaskList');
});
export const replyToDiscussion = ({ commit }, { endpoint, data }) =>
@@ -96,6 +96,8 @@ export const createNewNote = ({ commit, dispatch }, { endpoint, data }) =>
commit(types.ADD_NEW_NOTE, res);
dispatch('updateMergeRequestWidget');
+ dispatch('startTaskList');
+ dispatch('updateResolvableDiscussonsCounts');
}
return res;
});
@@ -111,6 +113,8 @@ export const toggleResolveNote = ({ commit, dispatch }, { endpoint, isResolved,
commit(mutationType, res);
+ dispatch('updateResolvableDiscussonsCounts');
+
dispatch('updateMergeRequestWidget');
});
@@ -162,11 +166,24 @@ export const toggleIssueLocalState = ({ commit }, newState) => {
export const saveNote = ({ commit, dispatch }, noteData) => {
// For MR discussuions we need to post as `note[note]` and issue we use `note.note`.
- const note = noteData.data['note[note]'] || noteData.data.note.note;
+ // For batch comments, we use draft_note
+ const note = noteData.data.draft_note || noteData.data['note[note]'] || noteData.data.note.note;
let placeholderText = note;
const hasQuickActions = utils.hasQuickActions(placeholderText);
const replyId = noteData.data.in_reply_to_discussion_id;
- const methodToDispatch = replyId ? 'replyToDiscussion' : 'createNewNote';
+ let methodToDispatch;
+ const postData = Object.assign({}, noteData);
+ if (postData.isDraft === true) {
+ methodToDispatch = replyId
+ ? 'batchComments/addDraftToDiscussion'
+ : 'batchComments/createNewDraft';
+ if (!postData.draft_note && noteData.note) {
+ postData.draft_note = postData.note;
+ delete postData.note;
+ }
+ } else {
+ methodToDispatch = replyId ? 'replyToDiscussion' : 'createNewNote';
+ }
$('.notes-form .flash-container').hide(); // hide previous flash notification
commit(types.REMOVE_PLACEHOLDER_NOTES); // remove previous placeholders
@@ -192,7 +209,7 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
}
}
- return dispatch(methodToDispatch, noteData).then(res => {
+ return dispatch(methodToDispatch, postData, { root: true }).then(res => {
const { errors } = res;
const commandsChanges = res.commands_changes;
@@ -250,7 +267,7 @@ const pollSuccessCallBack = (resp, commit, state, getters, dispatch) => {
if (discussion) {
commit(types.ADD_NEW_REPLY_TO_DISCUSSION, note);
} else if (note.type === constants.DIFF_NOTE) {
- dispatch('fetchDiscussions', state.notesData.discussionsPath);
+ dispatch('fetchDiscussions', { path: state.notesData.discussionsPath });
} else {
commit(types.ADD_NEW_NOTE, note);
}
@@ -258,6 +275,8 @@ const pollSuccessCallBack = (resp, commit, state, getters, dispatch) => {
commit(types.ADD_NEW_NOTE, note);
}
});
+
+ dispatch('startTaskList');
}
commit(types.SET_LAST_FETCHED_AT, resp.last_fetched_at);
@@ -333,7 +352,7 @@ export const scrollToNoteIfNeeded = (context, el) => {
};
export const fetchDiscussionDiffLines = ({ commit }, discussion) =>
- axios.get(discussion.truncatedDiffLinesPath).then(({ data }) => {
+ axios.get(discussion.truncated_diff_lines_path).then(({ data }) => {
commit(types.SET_DISCUSSION_DIFF_LINES, {
discussionId: discussion.id,
diffLines: data.truncated_diff_lines,
@@ -344,5 +363,41 @@ export const updateMergeRequestWidget = () => {
mrWidgetEventHub.$emit('mr.discussion.updated');
};
+export const setLoadingState = ({ commit }, data) => {
+ commit(types.SET_NOTES_LOADING_STATE, data);
+};
+
+export const filterDiscussion = ({ dispatch }, { path, filter }) => {
+ dispatch('setLoadingState', true);
+ dispatch('fetchDiscussions', { path, filter })
+ .then(() => {
+ dispatch('setLoadingState', false);
+ dispatch('setNotesFetchedState', true);
+ })
+ .catch(() => {
+ dispatch('setLoadingState', false);
+ dispatch('setNotesFetchedState', true);
+ Flash(__('Something went wrong while fetching comments. Please try again.'));
+ });
+};
+
+export const setCommentsDisabled = ({ commit }, data) => {
+ commit(types.DISABLE_COMMENTS, data);
+};
+
+export const startTaskList = ({ dispatch }) =>
+ Vue.nextTick(
+ () =>
+ new TaskList({
+ dataType: 'note',
+ fieldName: 'note',
+ selector: '.notes .is-editable',
+ onSuccess: () => dispatch('startTaskList'),
+ }),
+ );
+
+export const updateResolvableDiscussonsCounts = ({ commit }) =>
+ commit(types.UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS);
+
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/assets/javascripts/notes/stores/collapse_utils.js b/app/assets/javascripts/notes/stores/collapse_utils.js
index fa4a1c56b20..bee6d4f0329 100644
--- a/app/assets/javascripts/notes/stores/collapse_utils.js
+++ b/app/assets/javascripts/notes/stores/collapse_utils.js
@@ -68,12 +68,9 @@ export const collapseSystemNotes = notes => {
lastDescriptionSystemNote = note;
lastDescriptionSystemNoteIndex = acc.length;
} else if (lastDescriptionSystemNote) {
- const timeDifferenceMinutes = getTimeDifferenceMinutes(
- lastDescriptionSystemNote,
- note,
- );
+ const timeDifferenceMinutes = getTimeDifferenceMinutes(lastDescriptionSystemNote, note);
- // are they less than 10 minutes appart?
+ // are they less than 10 minutes apart?
if (timeDifferenceMinutes > 10) {
// reset counter
descriptionChangedTimes = 1;
diff --git a/app/assets/javascripts/notes/stores/getters.js b/app/assets/javascripts/notes/stores/getters.js
index d4babf1fab2..2ed8aac059a 100644
--- a/app/assets/javascripts/notes/stores/getters.js
+++ b/app/assets/javascripts/notes/stores/getters.js
@@ -1,6 +1,5 @@
import _ from 'underscore';
import * as constants from '../constants';
-import { reduceDiscussionsToLineCodes } from './utils';
import { collapseSystemNotes } from './collapse_utils';
export const discussions = state => collapseSystemNotes(state.discussions);
@@ -11,6 +10,8 @@ export const getNotesData = state => state.notesData;
export const isNotesFetched = state => state.isNotesFetched;
+export const isLoading = state => state.isLoading;
+
export const getNotesDataByProp = state => prop => state.notesData[prop];
export const getNoteableData = state => state.noteableData;
@@ -29,9 +30,6 @@ export const notesById = state =>
return acc;
}, {});
-export const discussionsStructuredByLineCode = state =>
- reduceDiscussionsToLineCodes(state.discussions);
-
export const noteableType = state => {
const { ISSUE_NOTEABLE_TYPE, MERGE_REQUEST_NOTEABLE_TYPE, EPIC_NOTEABLE_TYPE } = constants;
@@ -55,40 +53,30 @@ export const getCurrentUserLastNote = state =>
export const getDiscussionLastNote = state => discussion =>
reverseNotes(discussion.notes).find(el => isLastNote(el, state));
-export const discussionCount = state => {
- const filteredDiscussions = state.discussions.filter(n => !n.individual_note && n.resolvable);
-
- return filteredDiscussions.length;
-};
-
-export const unresolvedDiscussions = (state, getters) => {
- const resolvedMap = getters.resolvedDiscussionsById;
+export const unresolvedDiscussionsCount = state => state.unresolvedDiscussionsCount;
+export const resolvableDiscussionsCount = state => state.resolvableDiscussionsCount;
+export const hasUnresolvedDiscussions = state => state.hasUnresolvedDiscussions;
- return state.discussions.filter(n => !n.individual_note && !resolvedMap[n.id]);
-};
+export const isDiscussionResolved = (state, getters) => discussionId =>
+ getters.resolvedDiscussionsById[discussionId] !== undefined;
-export const allDiscussions = (state, getters) => {
- const resolved = getters.resolvedDiscussionsById;
- const unresolved = getters.unresolvedDiscussions;
-
- return Object.values(resolved).concat(unresolved);
-};
-
-export const allResolvableDiscussions = (state, getters) =>
- getters.allDiscussions.filter(d => !d.individual_note && d.resolvable);
+export const allResolvableDiscussions = state =>
+ state.discussions.filter(d => !d.individual_note && d.resolvable);
export const resolvedDiscussionsById = state => {
const map = {};
- state.discussions.filter(d => d.resolvable).forEach(n => {
- if (n.notes) {
- const resolved = n.notes.filter(note => note.resolvable).every(note => note.resolved);
+ state.discussions
+ .filter(d => d.resolvable)
+ .forEach(n => {
+ if (n.notes) {
+ const resolved = n.notes.filter(note => note.resolvable).every(note => note.resolved);
- if (resolved) {
- map[n.id] = n;
+ if (resolved) {
+ map[n.id] = n;
+ }
}
- }
- });
+ });
return map;
};
@@ -126,8 +114,8 @@ export const unresolvedDiscussionsIdsByDiff = (state, getters) =>
const filenameComparison = a.diff_file.file_path.localeCompare(b.diff_file.file_path);
// Get the line numbers, to compare within the same file
- const aLines = [a.position.formatter.new_line, a.position.formatter.old_line];
- const bLines = [b.position.formatter.new_line, b.position.formatter.old_line];
+ const aLines = [a.position.new_line, a.position.old_line];
+ const bLines = [b.position.new_line, b.position.old_line];
return filenameComparison < 0 ||
(filenameComparison === 0 &&
@@ -144,15 +132,12 @@ export const resolvedDiscussionCount = (state, getters) => {
return Object.keys(resolvedMap).length;
};
-export const discussionTabCounter = state => {
- let all = [];
-
- state.discussions.forEach(discussion => {
- all = all.concat(discussion.notes.filter(note => !note.system && !note.placeholder));
- });
-
- return all.length;
-};
+export const discussionTabCounter = state =>
+ state.discussions.reduce(
+ (acc, discussion) =>
+ acc + discussion.notes.filter(note => !note.system && !note.placeholder).length,
+ 0,
+ );
// Returns the list of discussion IDs ordered according to given parameter
// @param {Boolean} diffOrder - is ordered by diff?
@@ -179,8 +164,10 @@ export const isLastUnresolvedDiscussion = (state, getters) => (discussionId, dif
export const nextUnresolvedDiscussionId = (state, getters) => (discussionId, diffOrder) => {
const idsOrdered = getters.unresolvedDiscussionsIdsOrdered(diffOrder);
const currentIndex = idsOrdered.indexOf(discussionId);
+ const slicedIds = idsOrdered.slice(currentIndex + 1, currentIndex + 2);
- return idsOrdered.slice(currentIndex + 1, currentIndex + 2)[0];
+ // Get the first ID if there is none after the currentIndex
+ return slicedIds.length ? idsOrdered.slice(currentIndex + 1, currentIndex + 2)[0] : idsOrdered[0];
};
// @param {Boolean} diffOrder - is ordered by diff?
@@ -191,5 +178,7 @@ export const firstUnresolvedDiscussionId = (state, getters) => diffOrder => {
return getters.unresolvedDiscussionsIdsByDate[0];
};
+export const commentsDisabled = state => state.commentsDisabled;
+
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/assets/javascripts/notes/stores/index.js b/app/assets/javascripts/notes/stores/index.js
index f105b7d0d11..d41b02b4a4b 100644
--- a/app/assets/javascripts/notes/stores/index.js
+++ b/app/assets/javascripts/notes/stores/index.js
@@ -4,5 +4,4 @@ import notesModule from './modules';
Vue.use(Vuex);
-export default () =>
- new Vuex.Store(notesModule());
+export default () => new Vuex.Store(notesModule());
diff --git a/app/assets/javascripts/notes/stores/modules/index.js b/app/assets/javascripts/notes/stores/modules/index.js
index 61dbb075586..b5fe8bdb1d3 100644
--- a/app/assets/javascripts/notes/stores/modules/index.js
+++ b/app/assets/javascripts/notes/stores/modules/index.js
@@ -11,6 +11,7 @@ export default () => ({
// View layer
isToggleStateButtonLoading: false,
isNotesFetched: false,
+ isLoading: true,
// holds endpoints and permissions provided through haml
notesData: {
@@ -20,6 +21,10 @@ export default () => ({
noteableData: {
current_user: {},
},
+ commentsDisabled: false,
+ resolvableDiscussionsCount: 0,
+ unresolvedDiscussionsCount: 0,
+ hasUnresolvedDiscussions: false,
},
actions,
getters,
diff --git a/app/assets/javascripts/notes/stores/mutation_types.js b/app/assets/javascripts/notes/stores/mutation_types.js
index 6f374f78691..9c68ab67a8c 100644
--- a/app/assets/javascripts/notes/stores/mutation_types.js
+++ b/app/assets/javascripts/notes/stores/mutation_types.js
@@ -14,11 +14,14 @@ export const UPDATE_NOTE = 'UPDATE_NOTE';
export const UPDATE_DISCUSSION = 'UPDATE_DISCUSSION';
export const SET_DISCUSSION_DIFF_LINES = 'SET_DISCUSSION_DIFF_LINES';
export const SET_NOTES_FETCHED_STATE = 'SET_NOTES_FETCHED_STATE';
+export const SET_NOTES_LOADING_STATE = 'SET_NOTES_LOADING_STATE';
+export const DISABLE_COMMENTS = 'DISABLE_COMMENTS';
// DISCUSSION
export const COLLAPSE_DISCUSSION = 'COLLAPSE_DISCUSSION';
export const EXPAND_DISCUSSION = 'EXPAND_DISCUSSION';
export const TOGGLE_DISCUSSION = 'TOGGLE_DISCUSSION';
+export const UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS = 'UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS';
// Issue
export const CLOSE_ISSUE = 'CLOSE_ISSUE';
diff --git a/app/assets/javascripts/notes/stores/mutations.js b/app/assets/javascripts/notes/stores/mutations.js
index f1242a0d8be..667c8a97cf3 100644
--- a/app/assets/javascripts/notes/stores/mutations.js
+++ b/app/assets/javascripts/notes/stores/mutations.js
@@ -4,7 +4,8 @@ import * as constants from '../constants';
import { isInMRPage } from '../../lib/utils/common_utils';
export default {
- [types.ADD_NEW_NOTE](state, note) {
+ [types.ADD_NEW_NOTE](state, data) {
+ const note = data.discussion ? data.discussion.notes[0] : data;
const { discussion_id, type } = note;
const [exists] = state.discussions.filter(n => n.id === note.discussion_id);
const isDiscussion = type === constants.DISCUSSION_NOTE || type === constants.DIFF_NOTE;
@@ -23,6 +24,7 @@ export default {
noteData.resolved = false;
noteData.resolve_path = note.resolve_path;
noteData.resolve_with_issue_path = note.resolve_with_issue_path;
+ noteData.diff_discussion = false;
}
state.discussions.push(noteData);
@@ -96,33 +98,36 @@ export default {
},
[types.SET_INITIAL_DISCUSSIONS](state, discussionsData) {
- const discussions = [];
+ const discussions = discussionsData.reduce((acc, d) => {
+ const discussion = { ...d };
+ const diffData = {};
- discussionsData.forEach(discussion => {
if (discussion.diff_file) {
- Object.assign(discussion, {
- fileHash: discussion.diff_file.file_hash,
- truncated_diff_lines: discussion.truncated_diff_lines || [],
- });
+ diffData.file_hash = discussion.diff_file.file_hash;
+ diffData.truncated_diff_lines = discussion.truncated_diff_lines || [];
}
// To support legacy notes, should be very rare case.
if (discussion.individual_note && discussion.notes.length > 1) {
discussion.notes.forEach(n => {
- discussions.push({
+ acc.push({
...discussion,
+ ...diffData,
notes: [n], // override notes array to only have one item to mimick individual_note
});
});
} else {
const oldNote = utils.findNoteObjectById(state.discussions, discussion.id);
- discussions.push({
+ acc.push({
...discussion,
+ ...diffData,
expanded: oldNote ? oldNote.expanded : discussion.expanded,
});
}
- });
+
+ return acc;
+ }, []);
Object.assign(state, { discussions });
},
@@ -194,7 +199,9 @@ export default {
const selectedDiscussion = state.discussions.find(disc => disc.id === note.id);
note.expanded = true; // override expand flag to prevent collapse
if (note.diff_file) {
- Object.assign(note, { fileHash: note.diff_file.file_hash });
+ Object.assign(note, {
+ file_hash: note.diff_file.file_hash,
+ });
}
Object.assign(selectedDiscussion, { ...note });
},
@@ -215,9 +222,29 @@ export default {
Object.assign(state, { isNotesFetched: value });
},
+ [types.SET_NOTES_LOADING_STATE](state, value) {
+ state.isLoading = value;
+ },
+
[types.SET_DISCUSSION_DIFF_LINES](state, { discussionId, diffLines }) {
const discussion = utils.findNoteObjectById(state.discussions, discussionId);
discussion.truncated_diff_lines = diffLines;
},
+
+ [types.DISABLE_COMMENTS](state, value) {
+ state.commentsDisabled = value;
+ },
+ [types.UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS](state) {
+ state.resolvableDiscussionsCount = state.discussions.filter(
+ discussion => !discussion.individual_note && discussion.resolvable,
+ ).length;
+ state.unresolvedDiscussionsCount = state.discussions.filter(
+ discussion =>
+ !discussion.individual_note &&
+ discussion.resolvable &&
+ discussion.notes.some(note => !note.resolved),
+ ).length;
+ state.hasUnresolvedDiscussions = state.unresolvedDiscussionsCount > 1;
+ },
};
diff --git a/app/assets/javascripts/notes/stores/utils.js b/app/assets/javascripts/notes/stores/utils.js
index 0e41ff03d67..dd57539e4d8 100644
--- a/app/assets/javascripts/notes/stores/utils.js
+++ b/app/assets/javascripts/notes/stores/utils.js
@@ -25,18 +25,6 @@ export const getQuickActionText = note => {
return text;
};
-export const reduceDiscussionsToLineCodes = selectedDiscussions =>
- selectedDiscussions.reduce((acc, note) => {
- if (note.diff_discussion && note.line_code) {
- // For context about line notes: there might be multiple notes with the same line code
- const items = acc[note.line_code] || [];
- items.push(note);
-
- Object.assign(acc, { [note.line_code]: items });
- }
- return acc;
- }, {});
-
export const hasQuickActions = note => REGEX_QUICK_ACTIONS.test(note);
export const stripQuickActions = note => note.replace(REGEX_QUICK_ACTIONS, '').trim();
diff --git a/app/assets/javascripts/notifications_dropdown.js b/app/assets/javascripts/notifications_dropdown.js
index 8ff8bb446ad..c4c8cf86cb0 100644
--- a/app/assets/javascripts/notifications_dropdown.js
+++ b/app/assets/javascripts/notifications_dropdown.js
@@ -18,7 +18,9 @@ export default function notificationsDropdown() {
$(document).on('ajax:success', '.notification-form', (e, data) => {
if (data.saved) {
- $(e.currentTarget).closest('.js-notification-dropdown').replaceWith(data.html);
+ $(e.currentTarget)
+ .closest('.js-notification-dropdown')
+ .replaceWith(data.html);
} else {
Flash('Failed to save new settings', 'alert');
}
diff --git a/app/assets/javascripts/notifications_form.js b/app/assets/javascripts/notifications_form.js
index 00e27ca0e70..45f033f2822 100644
--- a/app/assets/javascripts/notifications_form.js
+++ b/app/assets/javascripts/notifications_form.js
@@ -22,7 +22,8 @@ export default class NotificationsForm {
// eslint-disable-next-line class-methods-use-this
showCheckboxLoadingSpinner($parent) {
- $parent.addClass('is-loading')
+ $parent
+ .addClass('is-loading')
.find('.custom-notification-event-loading')
.removeClass('fa-check')
.addClass('fa-spin fa-spinner')
@@ -38,9 +39,12 @@ export default class NotificationsForm {
.then(({ data }) => {
$checkbox.enable();
if (data.saved) {
- $parent.find('.custom-notification-event-loading').toggleClass('fa-spin fa-spinner fa-check is-done');
+ $parent
+ .find('.custom-notification-event-loading')
+ .toggleClass('fa-spin fa-spinner fa-check is-done');
setTimeout(() => {
- $parent.removeClass('is-loading')
+ $parent
+ .removeClass('is-loading')
.find('.custom-notification-event-loading')
.toggleClass('fa-spin fa-spinner fa-check is-done');
}, 2000);
diff --git a/app/assets/javascripts/pager.js b/app/assets/javascripts/pager.js
index 86a43b66cc8..386a9b2c740 100644
--- a/app/assets/javascripts/pager.js
+++ b/app/assets/javascripts/pager.js
@@ -7,14 +7,21 @@ const ENDLESS_SCROLL_BOTTOM_PX = 400;
const ENDLESS_SCROLL_FIRE_DELAY_MS = 1000;
export default {
- init(limit = 0, preload = false, disable = false, prepareData = $.noop, callback = $.noop) {
+ init(
+ limit = 0,
+ preload = false,
+ disable = false,
+ prepareData = $.noop,
+ callback = $.noop,
+ container = '',
+ ) {
this.url = $('.content_list').data('href') || removeParams(['limit', 'offset']);
this.limit = limit;
this.offset = parseInt(getParameterByName('offset'), 10) || this.limit;
this.disable = disable;
this.prepareData = prepareData;
this.callback = callback;
- this.loading = $('.loading').first();
+ this.loading = $(`${container} .loading`).first();
if (preload) {
this.offset = 0;
this.getOld();
@@ -24,22 +31,25 @@ export default {
getOld() {
this.loading.show();
- axios.get(this.url, {
- params: {
- limit: this.limit,
- offset: this.offset,
- },
- }).then(({ data }) => {
- this.append(data.count, this.prepareData(data.html));
- this.callback();
+ axios
+ .get(this.url, {
+ params: {
+ limit: this.limit,
+ offset: this.offset,
+ },
+ })
+ .then(({ data }) => {
+ this.append(data.count, this.prepareData(data.html));
+ this.callback();
- // keep loading until we've filled the viewport height
- if (!this.disable && !this.isScrollable()) {
- this.getOld();
- } else {
- this.loading.hide();
- }
- }).catch(() => this.loading.hide());
+ // keep loading until we've filled the viewport height
+ if (!this.disable && !this.isScrollable()) {
+ this.getOld();
+ } else {
+ this.loading.hide();
+ }
+ })
+ .catch(() => this.loading.hide());
},
append(count, html) {
diff --git a/app/assets/javascripts/pages/admin/abuse_reports/abuse_reports.js b/app/assets/javascripts/pages/admin/abuse_reports/abuse_reports.js
index 15e737fff05..674b807edbe 100644
--- a/app/assets/javascripts/pages/admin/abuse_reports/abuse_reports.js
+++ b/app/assets/javascripts/pages/admin/abuse_reports/abuse_reports.js
@@ -1,5 +1,6 @@
import $ from 'jquery';
import { truncate } from '../../../lib/utils/text_utility';
+import { parseBoolean } from '~/lib/utils/common_utils';
const MAX_MESSAGE_LENGTH = 500;
const MESSAGE_CELL_SELECTOR = '.abuse-reports .message';
@@ -26,12 +27,12 @@ export default class AbuseReports {
const $messageCellElement = $(this);
const originalMessage = $messageCellElement.data('originalMessage');
if (!originalMessage) return;
- if ($messageCellElement.data('messageTruncated') === 'true') {
+ if (parseBoolean($messageCellElement.data('messageTruncated'))) {
$messageCellElement.data('messageTruncated', 'false');
$messageCellElement.text(originalMessage);
} else {
$messageCellElement.data('messageTruncated', 'true');
- $messageCellElement.text(`${originalMessage.substr(0, (MAX_MESSAGE_LENGTH - 3))}...`);
+ $messageCellElement.text(`${originalMessage.substr(0, MAX_MESSAGE_LENGTH - 3)}...`);
}
}
}
diff --git a/app/assets/javascripts/pages/admin/admin.js b/app/assets/javascripts/pages/admin/admin.js
index ff4d6ab15f9..4616a075729 100644
--- a/app/assets/javascripts/pages/admin/admin.js
+++ b/app/assets/javascripts/pages/admin/admin.js
@@ -23,7 +23,7 @@ export default function adminInit() {
}
});
- $('body').on('click', '.js-toggle-colors-link', (e) => {
+ $('body').on('click', '.js-toggle-colors-link', e => {
e.preventDefault();
$('.js-toggle-colors-container').toggleClass('hide');
});
@@ -33,12 +33,15 @@ export default function adminInit() {
$(this).tab('show');
});
- $('.log-bottom').on('click', (e) => {
+ $('.log-bottom').on('click', e => {
e.preventDefault();
const $visibleLog = $('.file-content:visible');
- $visibleLog.animate({
- scrollTop: $visibleLog.find('ol').height(),
- }, 'fast');
+ $visibleLog.animate(
+ {
+ scrollTop: $visibleLog.find('ol').height(),
+ },
+ 'fast',
+ );
});
$('.change-owner-link').on('click', function changeOwnerLinkClick(e) {
@@ -47,7 +50,7 @@ export default function adminInit() {
modal.show();
});
- $('.change-owner-cancel-link').on('click', (e) => {
+ $('.change-owner-cancel-link').on('click', e => {
e.preventDefault();
modal.hide();
$('.change-owner-link').show();
diff --git a/app/assets/javascripts/pages/admin/application_settings/account_and_limits.js b/app/assets/javascripts/pages/admin/application_settings/account_and_limits.js
index 7281f907ec7..455c637a6b3 100644
--- a/app/assets/javascripts/pages/admin/application_settings/account_and_limits.js
+++ b/app/assets/javascripts/pages/admin/application_settings/account_and_limits.js
@@ -1,10 +1,14 @@
import { __ } from '~/locale';
export const PLACEHOLDER_USER_EXTERNAL_DEFAULT_TRUE = __('Regex pattern');
-export const PLACEHOLDER_USER_EXTERNAL_DEFAULT_FALSE = __('To define internal users, first enable new users set to external');
+export const PLACEHOLDER_USER_EXTERNAL_DEFAULT_FALSE = __(
+ 'To define internal users, first enable new users set to external',
+);
function setUserInternalRegexPlaceholder(checkbox) {
- const userInternalRegex = document.getElementById('application_setting_user_default_internal_regex');
+ const userInternalRegex = document.getElementById(
+ 'application_setting_user_default_internal_regex',
+ );
if (checkbox && userInternalRegex) {
if (checkbox.checked) {
userInternalRegex.readOnly = false;
diff --git a/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js b/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
index e7ceccb6f47..d5ded3f9a79 100644
--- a/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
+++ b/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
@@ -17,20 +17,24 @@ export default () => {
const previewPath = $('textarea#broadcast_message_message').data('previewPath');
- $('textarea#broadcast_message_message').on('input', _.debounce(function onMessageInput() {
- const message = $(this).val();
- if (message === '') {
- $('.js-broadcast-message-preview').text('Your message here');
- } else {
- axios.post(previewPath, {
- broadcast_message: {
- message,
- },
- })
- .then(({ data }) => {
- $('.js-broadcast-message-preview').html(data.message);
- })
- .catch(() => flash(__('An error occurred while rendering preview broadcast message')));
- }
- }, 250));
+ $('textarea#broadcast_message_message').on(
+ 'input',
+ _.debounce(function onMessageInput() {
+ const message = $(this).val();
+ if (message === '') {
+ $('.js-broadcast-message-preview').text('Your message here');
+ } else {
+ axios
+ .post(previewPath, {
+ broadcast_message: {
+ message,
+ },
+ })
+ .then(({ data }) => {
+ $('.js-broadcast-message-preview').html(data.message);
+ })
+ .catch(() => flash(__('An error occurred while rendering preview broadcast message')));
+ }
+ }, 250),
+ );
};
diff --git a/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue b/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue
index bc84666779e..e2fec3c7172 100644
--- a/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue
+++ b/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue
@@ -1,39 +1,42 @@
<script>
- import axios from '~/lib/utils/axios_utils';
- import createFlash from '~/flash';
- import GlModal from '~/vue_shared/components/gl_modal.vue';
- import { redirectTo } from '~/lib/utils/url_utility';
- import { s__ } from '~/locale';
+import axios from '~/lib/utils/axios_utils';
+import createFlash from '~/flash';
+import GlModal from '~/vue_shared/components/gl_modal.vue';
+import { redirectTo } from '~/lib/utils/url_utility';
+import { s__ } from '~/locale';
- export default {
- components: {
- GlModal,
+export default {
+ components: {
+ GlModal,
+ },
+ props: {
+ url: {
+ type: String,
+ required: true,
},
- props: {
- url: {
- type: String,
- required: true,
- },
+ },
+ computed: {
+ text() {
+ return s__(
+ 'AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running.',
+ );
},
- computed: {
- text() {
- return s__('AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running.');
- },
+ },
+ methods: {
+ onSubmit() {
+ return axios
+ .post(this.url)
+ .then(response => {
+ // follow the rediect to refresh the page
+ redirectTo(response.request.responseURL);
+ })
+ .catch(error => {
+ createFlash(s__('AdminArea|Stopping jobs failed'));
+ throw error;
+ });
},
- methods: {
- onSubmit() {
- return axios.post(this.url)
- .then((response) => {
- // follow the rediect to refresh the page
- redirectTo(response.request.responseURL);
- })
- .catch((error) => {
- createFlash(s__('AdminArea|Stopping jobs failed'));
- throw error;
- });
- },
- },
- };
+ },
+};
</script>
<template>
diff --git a/app/assets/javascripts/pages/admin/projects/index.js b/app/assets/javascripts/pages/admin/projects/index.js
index 31c96eb87af..d6b1e747aec 100644
--- a/app/assets/javascripts/pages/admin/projects/index.js
+++ b/app/assets/javascripts/pages/admin/projects/index.js
@@ -4,6 +4,7 @@ import NamespaceSelect from '../../../namespace_select';
document.addEventListener('DOMContentLoaded', () => {
new ProjectsList(); // eslint-disable-line no-new
- document.querySelectorAll('.js-namespace-select')
+ document
+ .querySelectorAll('.js-namespace-select')
.forEach(dropdown => new NamespaceSelect({ dropdown }));
});
diff --git a/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue b/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
index ff66d3a8ac4..527c16860c0 100644
--- a/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
+++ b/app/assets/javascripts/pages/admin/projects/index/components/delete_project_modal.vue
@@ -1,81 +1,84 @@
<script>
- import _ from 'underscore';
- import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
- import { s__, sprintf } from '~/locale';
+import _ from 'underscore';
+import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
+import { s__, sprintf } from '~/locale';
- export default {
- components: {
- DeprecatedModal,
+export default {
+ components: {
+ DeprecatedModal,
+ },
+ props: {
+ deleteProjectUrl: {
+ type: String,
+ required: false,
+ default: '',
},
- props: {
- deleteProjectUrl: {
- type: String,
- required: false,
- default: '',
- },
- projectName: {
- type: String,
- required: false,
- default: '',
- },
- csrfToken: {
- type: String,
- required: false,
- default: '',
- },
+ projectName: {
+ type: String,
+ required: false,
+ default: '',
},
- data() {
- return {
- enteredProjectName: '',
- };
+ csrfToken: {
+ type: String,
+ required: false,
+ default: '',
},
- computed: {
- title() {
- return sprintf(s__('AdminProjects|Delete Project %{projectName}?'),
- {
- projectName: `'${_.escape(this.projectName)}'`,
- },
- false,
- );
- },
- text() {
- return sprintf(s__(`AdminProjects|
+ },
+ data() {
+ return {
+ enteredProjectName: '',
+ };
+ },
+ computed: {
+ title() {
+ return sprintf(
+ s__('AdminProjects|Delete Project %{projectName}?'),
+ {
+ projectName: `'${_.escape(this.projectName)}'`,
+ },
+ false,
+ );
+ },
+ text() {
+ return sprintf(
+ s__(`AdminProjects|
You’re about to permanently delete the project %{projectName}, its repository,
and all related resources including issues, merge requests, etc.. Once you confirm and press
%{strong_start}Delete project%{strong_end}, it cannot be undone or recovered.`),
- {
- projectName: `<strong>${_.escape(this.projectName)}</strong>`,
- strong_start: '<strong>',
- strong_end: '</strong>',
- },
- false,
- );
- },
- confirmationTextLabel() {
- return sprintf(s__('AdminUsers|To confirm, type %{projectName}'),
- {
- projectName: `<code>${_.escape(this.projectName)}</code>`,
- },
- false,
- );
- },
- primaryButtonLabel() {
- return s__('AdminProjects|Delete project');
- },
- canSubmit() {
- return this.enteredProjectName === this.projectName;
- },
+ {
+ projectName: `<strong>${_.escape(this.projectName)}</strong>`,
+ strong_start: '<strong>',
+ strong_end: '</strong>',
+ },
+ false,
+ );
+ },
+ confirmationTextLabel() {
+ return sprintf(
+ s__('AdminUsers|To confirm, type %{projectName}'),
+ {
+ projectName: `<code>${_.escape(this.projectName)}</code>`,
+ },
+ false,
+ );
+ },
+ primaryButtonLabel() {
+ return s__('AdminProjects|Delete project');
+ },
+ canSubmit() {
+ return this.enteredProjectName === this.projectName;
+ },
+ },
+ methods: {
+ onCancel() {
+ this.enteredProjectName = '';
},
- methods: {
- onCancel() {
- this.enteredProjectName = '';
- },
- onSubmit() {
- this.$refs.form.submit();
- this.enteredProjectName = '';
- },
+ onSubmit() {
+ this.$refs.form.submit();
+ this.enteredProjectName = '';
},
- };
+ },
+};
</script>
<template>
@@ -89,28 +92,12 @@
@submit="onSubmit"
@cancel="onCancel"
>
- <template
- slot="body"
- slot-scope="props"
- >
+ <template slot="body" slot-scope="props">
<p v-html="props.text"></p>
<p v-html="confirmationTextLabel"></p>
- <form
- ref="form"
- :action="deleteProjectUrl"
- method="post"
- >
- <input
- ref="method"
- type="hidden"
- name="_method"
- value="delete"
- />
- <input
- :value="csrfToken"
- type="hidden"
- name="authenticity_token"
- />
+ <form ref="form" :action="deleteProjectUrl" method="post">
+ <input ref="method" type="hidden" name="_method" value="delete" />
+ <input :value="csrfToken" type="hidden" name="authenticity_token" />
<input
v-model="enteredProjectName"
name="projectName"
diff --git a/app/assets/javascripts/pages/admin/projects/index/index.js b/app/assets/javascripts/pages/admin/projects/index/index.js
index ddbefec87b6..6fa8760545d 100644
--- a/app/assets/javascripts/pages/admin/projects/index/index.js
+++ b/app/assets/javascripts/pages/admin/projects/index/index.js
@@ -28,7 +28,7 @@ document.addEventListener('DOMContentLoaded', () => {
},
});
- $(document).on('shown.bs.modal', (event) => {
+ $(document).on('shown.bs.modal', event => {
if (event.relatedTarget.classList.contains('delete-project-button')) {
const buttonProps = event.relatedTarget.dataset;
deleteModal.deleteProjectUrl = buttonProps.deleteProjectUrl;
diff --git a/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
index d6aa4bb95d2..e8905b479ee 100644
--- a/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
+++ b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
@@ -1,114 +1,119 @@
<script>
- import _ from 'underscore';
- import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
- import { s__, sprintf } from '~/locale';
+import _ from 'underscore';
+import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
+import { s__, sprintf } from '~/locale';
- export default {
- components: {
- DeprecatedModal,
+export default {
+ components: {
+ DeprecatedModal,
+ },
+ props: {
+ deleteUserUrl: {
+ type: String,
+ required: false,
+ default: '',
},
- props: {
- deleteUserUrl: {
- type: String,
- required: false,
- default: '',
- },
- blockUserUrl: {
- type: String,
- required: false,
- default: '',
- },
- deleteContributions: {
- type: Boolean,
- required: false,
- default: false,
- },
- username: {
- type: String,
- required: false,
- default: '',
- },
- csrfToken: {
- type: String,
- required: false,
- default: '',
- },
+ blockUserUrl: {
+ type: String,
+ required: false,
+ default: '',
},
- data() {
- return {
- enteredUsername: '',
- };
+ deleteContributions: {
+ type: Boolean,
+ required: false,
+ default: false,
},
- computed: {
- title() {
- const keepContributionsTitle = s__('AdminUsers|Delete User %{username}?');
- const deleteContributionsTitle = s__('AdminUsers|Delete User %{username} and contributions?');
+ username: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ csrfToken: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ data() {
+ return {
+ enteredUsername: '',
+ };
+ },
+ computed: {
+ title() {
+ const keepContributionsTitle = s__('AdminUsers|Delete User %{username}?');
+ const deleteContributionsTitle = s__('AdminUsers|Delete User %{username} and contributions?');
- return sprintf(
- this.deleteContributions ? deleteContributionsTitle : keepContributionsTitle, {
- username: `'${_.escape(this.username)}'`,
- }, false);
- },
- text() {
- const keepContributionsText = s__(`AdminArea|
+ return sprintf(
+ this.deleteContributions ? deleteContributionsTitle : keepContributionsTitle,
+ {
+ username: `'${_.escape(this.username)}'`,
+ },
+ false,
+ );
+ },
+ text() {
+ const keepContributionsText = s__(`AdminArea|
You are about to permanently delete the user %{username}.
Issues, merge requests, and groups linked to them will be transferred to a system-wide "Ghost-user".
To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead.
Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered.`);
- const deleteContributionsText = s__(`AdminArea|
+ const deleteContributionsText = s__(`AdminArea|
You are about to permanently delete the user %{username}.
This will delete all of the issues, merge requests, and groups linked to them.
To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead.
Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered.`);
- return sprintf(this.deleteContributions ? deleteContributionsText : keepContributionsText,
- {
- username: `<strong>${_.escape(this.username)}</strong>`,
- strong_start: '<strong>',
- strong_end: '</strong>',
- },
- false,
- );
- },
- confirmationTextLabel() {
- return sprintf(s__('AdminUsers|To confirm, type %{username}'),
- {
- username: `<code>${_.escape(this.username)}</code>`,
- },
- false,
- );
- },
- primaryButtonLabel() {
- const keepContributionsLabel = s__('AdminUsers|Delete user');
- const deleteContributionsLabel = s__('AdminUsers|Delete user and contributions');
+ return sprintf(
+ this.deleteContributions ? deleteContributionsText : keepContributionsText,
+ {
+ username: `<strong>${_.escape(this.username)}</strong>`,
+ strong_start: '<strong>',
+ strong_end: '</strong>',
+ },
+ false,
+ );
+ },
+ confirmationTextLabel() {
+ return sprintf(
+ s__('AdminUsers|To confirm, type %{username}'),
+ {
+ username: `<code>${_.escape(this.username)}</code>`,
+ },
+ false,
+ );
+ },
+ primaryButtonLabel() {
+ const keepContributionsLabel = s__('AdminUsers|Delete user');
+ const deleteContributionsLabel = s__('AdminUsers|Delete user and contributions');
- return this.deleteContributions ? deleteContributionsLabel : keepContributionsLabel;
- },
- secondaryButtonLabel() {
- return s__('AdminUsers|Block user');
- },
- canSubmit() {
- return this.enteredUsername === this.username;
- },
+ return this.deleteContributions ? deleteContributionsLabel : keepContributionsLabel;
+ },
+ secondaryButtonLabel() {
+ return s__('AdminUsers|Block user');
+ },
+ canSubmit() {
+ return this.enteredUsername === this.username;
},
- methods: {
- onCancel() {
- this.enteredUsername = '';
- },
- onSecondaryAction() {
- const { form } = this.$refs;
+ },
+ methods: {
+ onCancel() {
+ this.enteredUsername = '';
+ },
+ onSecondaryAction() {
+ const { form } = this.$refs;
- form.action = this.blockUserUrl;
- this.$refs.method.value = 'put';
+ form.action = this.blockUserUrl;
+ this.$refs.method.value = 'put';
- form.submit();
- },
- onSubmit() {
- this.$refs.form.submit();
- this.enteredUsername = '';
- },
+ form.submit();
+ },
+ onSubmit() {
+ this.$refs.form.submit();
+ this.enteredUsername = '';
},
- };
+ },
+};
</script>
<template>
@@ -123,28 +128,12 @@
@submit="onSubmit"
@cancel="onCancel"
>
- <template
- slot="body"
- slot-scope="props"
- >
+ <template slot="body" slot-scope="props">
<p v-html="props.text"></p>
<p v-html="confirmationTextLabel"></p>
- <form
- ref="form"
- :action="deleteUserUrl"
- method="post"
- >
- <input
- ref="method"
- type="hidden"
- name="_method"
- value="delete"
- />
- <input
- :value="csrfToken"
- type="hidden"
- name="authenticity_token"
- />
+ <form ref="form" :action="deleteUserUrl" method="post">
+ <input ref="method" type="hidden" name="_method" value="delete" />
+ <input :value="csrfToken" type="hidden" name="authenticity_token" />
<input
v-model="enteredUsername"
type="text"
@@ -155,10 +144,7 @@
/>
</form>
</template>
- <template
- slot="secondary-button"
- slot-scope="props"
- >
+ <template slot="secondary-button">
<button
:disabled="!canSubmit"
type="button"
diff --git a/app/assets/javascripts/pages/admin/users/index.js b/app/assets/javascripts/pages/admin/users/index.js
index 06599c3fd5f..45046688b57 100644
--- a/app/assets/javascripts/pages/admin/users/index.js
+++ b/app/assets/javascripts/pages/admin/users/index.js
@@ -32,12 +32,14 @@ document.addEventListener('DOMContentLoaded', () => {
},
});
- $(document).on('shown.bs.modal', (event) => {
+ $(document).on('shown.bs.modal', event => {
if (event.relatedTarget.classList.contains('delete-user-button')) {
const buttonProps = event.relatedTarget.dataset;
deleteModal.deleteUserUrl = buttonProps.deleteUserUrl;
deleteModal.blockUserUrl = buttonProps.blockUserUrl;
- deleteModal.deleteContributions = event.relatedTarget.hasAttribute('data-delete-contributions');
+ deleteModal.deleteContributions = event.relatedTarget.hasAttribute(
+ 'data-delete-contributions',
+ );
deleteModal.username = buttonProps.username;
}
});
diff --git a/app/assets/javascripts/pages/admin/users/new/index.js b/app/assets/javascripts/pages/admin/users/new/index.js
index 58bfa8d64e7..3e6a090cb0e 100644
--- a/app/assets/javascripts/pages/admin/users/new/index.js
+++ b/app/assets/javascripts/pages/admin/users/new/index.js
@@ -4,7 +4,9 @@ export default class UserInternalRegexHandler {
constructor() {
this.regexPattern = $('[data-user-internal-regex-pattern]').data('user-internal-regex-pattern');
if (this.regexPattern && this.regexPattern !== '') {
- this.regexOptions = $('[data-user-internal-regex-options]').data('user-internal-regex-options');
+ this.regexOptions = $('[data-user-internal-regex-options]').data(
+ 'user-internal-regex-options',
+ );
this.external = $('#user_external');
this.warningMessage = $('#warning_external_automatically_set');
this.addListenerToEmailField();
@@ -13,7 +15,7 @@ export default class UserInternalRegexHandler {
}
addListenerToEmailField() {
- $('#user_email').on('input', (event) => {
+ $('#user_email').on('input', event => {
this.setExternalCheckbox(event.currentTarget.value);
});
}
diff --git a/app/assets/javascripts/pages/dashboard/issues/index.js b/app/assets/javascripts/pages/dashboard/issues/index.js
index c4901dd1cb6..9055738f86e 100644
--- a/app/assets/javascripts/pages/dashboard/issues/index.js
+++ b/app/assets/javascripts/pages/dashboard/issues/index.js
@@ -1,7 +1,13 @@
import projectSelect from '~/project_select';
-import initLegacyFilters from '~/init_legacy_filters';
+import initFilteredSearch from '~/pages/search/init_filtered_search';
+import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
+import { FILTERED_SEARCH } from '~/pages/constants';
document.addEventListener('DOMContentLoaded', () => {
+ initFilteredSearch({
+ page: FILTERED_SEARCH.ISSUES,
+ filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
+ });
+
projectSelect();
- initLegacyFilters();
});
diff --git a/app/assets/javascripts/pages/dashboard/merge_requests/index.js b/app/assets/javascripts/pages/dashboard/merge_requests/index.js
index c4901dd1cb6..260484726f3 100644
--- a/app/assets/javascripts/pages/dashboard/merge_requests/index.js
+++ b/app/assets/javascripts/pages/dashboard/merge_requests/index.js
@@ -1,7 +1,15 @@
import projectSelect from '~/project_select';
-import initLegacyFilters from '~/init_legacy_filters';
+import initFilteredSearch from '~/pages/search/init_filtered_search';
+import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
+import { FILTERED_SEARCH } from '~/pages/constants';
document.addEventListener('DOMContentLoaded', () => {
+ IssuableFilteredSearchTokenKeys.addExtraTokensForMergeRequests();
+
+ initFilteredSearch({
+ page: FILTERED_SEARCH.MERGE_REQUESTS,
+ filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
+ });
+
projectSelect();
- initLegacyFilters();
});
diff --git a/app/assets/javascripts/pages/dashboard/todos/index/todos.js b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
index 9aa83ce6269..1b56b97f751 100644
--- a/app/assets/javascripts/pages/dashboard/todos/index/todos.js
+++ b/app/assets/javascripts/pages/dashboard/todos/index/todos.js
@@ -79,10 +79,14 @@ export default class Todos {
.then(({ data }) => {
this.updateRowState(target);
this.updateBadges(data);
- }).catch(() => flash(__('Error updating todo status.')));
+ })
+ .catch(() => {
+ this.updateRowState(target, true);
+ return flash(__('Error updating todo status.'));
+ });
}
- updateRowState(target) {
+ updateRowState(target, isInactive = false) {
const row = target.closest('li');
const restoreBtn = row.querySelector('.js-undo-todo');
const doneBtn = row.querySelector('.js-done-todo');
@@ -91,7 +95,10 @@ export default class Todos {
target.removeAttribute('disabled');
target.classList.remove('disabled');
- if (target === doneBtn) {
+ if (isInactive === true) {
+ restoreBtn.classList.add('hidden');
+ doneBtn.classList.remove('hidden');
+ } else if (target === doneBtn) {
row.classList.add('done-reversible');
restoreBtn.classList.remove('hidden');
} else if (target === restoreBtn) {
@@ -112,10 +119,12 @@ export default class Todos {
axios[target.dataset.method](target.dataset.href, {
ids: this.todo_ids,
- }).then(({ data }) => {
- this.updateAllState(target, data);
- this.updateBadges(data);
- }).catch(() => flash(__('Error updating status for all todos.')));
+ })
+ .then(({ data }) => {
+ this.updateAllState(target, data);
+ this.updateBadges(data);
+ })
+ .catch(() => flash(__('Error updating status for all todos.')));
}
updateAllState(target, data) {
@@ -127,7 +136,7 @@ export default class Todos {
target.removeAttribute('disabled');
target.classList.remove('disabled');
- this.todo_ids = (target === markAllDoneBtn) ? data.updated_ids : [];
+ this.todo_ids = target === markAllDoneBtn ? data.updated_ids : [];
undoAllBtn.classList.toggle('hidden');
markAllDoneBtn.classList.toggle('hidden');
todoListContainer.classList.toggle('hidden');
diff --git a/app/assets/javascripts/pages/groups/clusters/destroy/index.js b/app/assets/javascripts/pages/groups/clusters/destroy/index.js
new file mode 100644
index 00000000000..8001d2dd1da
--- /dev/null
+++ b/app/assets/javascripts/pages/groups/clusters/destroy/index.js
@@ -0,0 +1,5 @@
+import ClustersBundle from '~/clusters/clusters_bundle';
+
+document.addEventListener('DOMContentLoaded', () => {
+ new ClustersBundle(); // eslint-disable-line no-new
+});
diff --git a/app/assets/javascripts/pages/groups/clusters/index/index.js b/app/assets/javascripts/pages/groups/clusters/index/index.js
new file mode 100644
index 00000000000..21efc4f6d00
--- /dev/null
+++ b/app/assets/javascripts/pages/groups/clusters/index/index.js
@@ -0,0 +1,7 @@
+import PersistentUserCallout from '~/persistent_user_callout';
+
+document.addEventListener('DOMContentLoaded', () => {
+ const callout = document.querySelector('.gcp-signup-offer');
+
+ if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new
+});
diff --git a/app/assets/javascripts/pages/groups/clusters/show/index.js b/app/assets/javascripts/pages/groups/clusters/show/index.js
new file mode 100644
index 00000000000..8001d2dd1da
--- /dev/null
+++ b/app/assets/javascripts/pages/groups/clusters/show/index.js
@@ -0,0 +1,5 @@
+import ClustersBundle from '~/clusters/clusters_bundle';
+
+document.addEventListener('DOMContentLoaded', () => {
+ new ClustersBundle(); // eslint-disable-line no-new
+});
diff --git a/app/assets/javascripts/pages/groups/clusters/update/index.js b/app/assets/javascripts/pages/groups/clusters/update/index.js
new file mode 100644
index 00000000000..8001d2dd1da
--- /dev/null
+++ b/app/assets/javascripts/pages/groups/clusters/update/index.js
@@ -0,0 +1,5 @@
+import ClustersBundle from '~/clusters/clusters_bundle';
+
+document.addEventListener('DOMContentLoaded', () => {
+ new ClustersBundle(); // eslint-disable-line no-new
+});
diff --git a/app/assets/javascripts/pages/groups/edit/index.js b/app/assets/javascripts/pages/groups/edit/index.js
index 002b2279fcc..01ef445c901 100644
--- a/app/assets/javascripts/pages/groups/edit/index.js
+++ b/app/assets/javascripts/pages/groups/edit/index.js
@@ -2,13 +2,24 @@ import groupAvatar from '~/group_avatar';
import TransferDropdown from '~/groups/transfer_dropdown';
import initConfirmDangerModal from '~/confirm_danger_modal';
import initSettingsPanels from '~/settings_panels';
+import dirtySubmitFactory from '~/dirty_submit/dirty_submit_factory';
import mountBadgeSettings from '~/pages/shared/mount_badge_settings';
import { GROUP_BADGE } from '~/badges/constants';
+import groupsSelect from '~/groups_select';
+import projectSelect from '~/project_select';
document.addEventListener('DOMContentLoaded', () => {
groupAvatar();
new TransferDropdown(); // eslint-disable-line no-new
initConfirmDangerModal();
initSettingsPanels();
+ dirtySubmitFactory(
+ document.querySelectorAll('.js-general-settings-form, .js-general-permissions-form'),
+ );
mountBadgeSettings(GROUP_BADGE);
+
+ // Initialize Subgroups selector
+ groupsSelect();
+
+ projectSelect();
});
diff --git a/app/assets/javascripts/pages/groups/index.js b/app/assets/javascripts/pages/groups/index.js
new file mode 100644
index 00000000000..00e2d7fc998
--- /dev/null
+++ b/app/assets/javascripts/pages/groups/index.js
@@ -0,0 +1,22 @@
+import PersistentUserCallout from '~/persistent_user_callout';
+import initGkeDropdowns from '~/projects/gke_cluster_dropdowns';
+
+function initCallout() {
+ const callout = document.querySelector('.gcp-signup-offer');
+
+ if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+ const { page } = document.body.dataset;
+ const newClusterViews = [
+ 'groups:clusters:new',
+ 'groups:clusters:create_gcp',
+ 'groups:clusters:create_user',
+ ];
+
+ if (newClusterViews.indexOf(page) > -1) {
+ initCallout();
+ initGkeDropdowns();
+ }
+});
diff --git a/app/assets/javascripts/pages/groups/merge_requests/index.js b/app/assets/javascripts/pages/groups/merge_requests/index.js
index b798a254459..339ce67438a 100644
--- a/app/assets/javascripts/pages/groups/merge_requests/index.js
+++ b/app/assets/javascripts/pages/groups/merge_requests/index.js
@@ -4,6 +4,8 @@ import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered
import { FILTERED_SEARCH } from '~/pages/constants';
document.addEventListener('DOMContentLoaded', () => {
+ IssuableFilteredSearchTokenKeys.addExtraTokensForMergeRequests();
+
initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS,
isGroupDecendent: true,
diff --git a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
index d3b2656743d..ae0a8c74964 100644
--- a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
+++ b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
@@ -9,7 +9,7 @@ document.addEventListener('DOMContentLoaded', () => {
// eslint-disable-next-line no-new
new AjaxVariableList({
container: variableListEl,
- saveButton: variableListEl.querySelector('.js-secret-variables-save-button'),
+ saveButton: variableListEl.querySelector('.js-ci-variables-save-button'),
errorBox: variableListEl.querySelector('.js-ci-variable-error-box'),
saveEndpoint: variableListEl.dataset.saveEndpoint,
});
diff --git a/app/assets/javascripts/pages/ide/index.js b/app/assets/javascripts/pages/ide/index.js
index efadf6967aa..d192df3561e 100644
--- a/app/assets/javascripts/pages/ide/index.js
+++ b/app/assets/javascripts/pages/ide/index.js
@@ -1,9 +1,3 @@
-import { initIde, resetServiceWorkersPublicPath } from '~/ide/index';
+import { startIde } from '~/ide/index';
-document.addEventListener('DOMContentLoaded', () => {
- const ideElement = document.getElementById('ide');
- if (ideElement) {
- resetServiceWorkersPublicPath();
- initIde(ideElement);
- }
-});
+startIde();
diff --git a/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue b/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue
index 48668562f09..061044eba84 100644
--- a/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue
+++ b/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue
@@ -1,94 +1,117 @@
<script>
- import axios from '~/lib/utils/axios_utils';
+import axios from '~/lib/utils/axios_utils';
- import Flash from '~/flash';
- import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
- import { n__, s__, sprintf } from '~/locale';
- import { redirectTo } from '~/lib/utils/url_utility';
- import eventHub from '../event_hub';
+import Flash from '~/flash';
+import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
+import { n__, s__, sprintf } from '~/locale';
+import { redirectTo } from '~/lib/utils/url_utility';
+import eventHub from '../event_hub';
- export default {
- components: {
- DeprecatedModal,
+export default {
+ components: {
+ DeprecatedModal,
+ },
+ props: {
+ issueCount: {
+ type: Number,
+ required: true,
},
- props: {
- issueCount: {
- type: Number,
- required: true,
- },
- mergeRequestCount: {
- type: Number,
- required: true,
- },
- milestoneId: {
- type: Number,
- required: true,
- },
- milestoneTitle: {
- type: String,
- required: true,
- },
- milestoneUrl: {
- type: String,
- required: true,
- },
+ mergeRequestCount: {
+ type: Number,
+ required: true,
},
- computed: {
- text() {
- const milestoneTitle = sprintf('<strong>%{milestoneTitle}</strong>', { milestoneTitle: this.milestoneTitle });
-
- if (this.issueCount === 0 && this.mergeRequestCount === 0) {
- return sprintf(
- s__(`Milestones|
-You’re about to permanently delete the milestone %{milestoneTitle}.
-This milestone is not currently used in any issues or merge requests.`),
- {
- milestoneTitle,
- },
- false,
- );
- }
+ milestoneId: {
+ type: Number,
+ required: true,
+ },
+ milestoneTitle: {
+ type: String,
+ required: true,
+ },
+ milestoneUrl: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ text() {
+ const milestoneTitle = sprintf('<strong>%{milestoneTitle}</strong>', {
+ milestoneTitle: this.milestoneTitle,
+ });
+ if (this.issueCount === 0 && this.mergeRequestCount === 0) {
return sprintf(
s__(`Milestones|
-You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}.
-Once deleted, it cannot be undone or recovered.`),
+You’re about to permanently delete the milestone %{milestoneTitle}.
+This milestone is not currently used in any issues or merge requests.`),
{
milestoneTitle,
- issuesWithCount: n__('%d issue', '%d issues', this.issueCount),
- mergeRequestsWithCount: n__('%d merge request', '%d merge requests', this.mergeRequestCount),
},
false,
);
- },
- title() {
- return sprintf(s__('Milestones|Delete milestone %{milestoneTitle}?'), { milestoneTitle: this.milestoneTitle });
- },
- },
- methods: {
- onSubmit() {
- eventHub.$emit('deleteMilestoneModal.requestStarted', this.milestoneUrl);
+ }
- return axios.delete(this.milestoneUrl)
- .then((response) => {
- eventHub.$emit('deleteMilestoneModal.requestFinished', { milestoneUrl: this.milestoneUrl, successful: true });
+ return sprintf(
+ s__(`Milestones|
+You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}.
+Once deleted, it cannot be undone or recovered.`),
+ {
+ milestoneTitle,
+ issuesWithCount: n__('%d issue', '%d issues', this.issueCount),
+ mergeRequestsWithCount: n__(
+ '%d merge request',
+ '%d merge requests',
+ this.mergeRequestCount,
+ ),
+ },
+ false,
+ );
+ },
+ title() {
+ return sprintf(s__('Milestones|Delete milestone %{milestoneTitle}?'), {
+ milestoneTitle: this.milestoneTitle,
+ });
+ },
+ },
+ methods: {
+ onSubmit() {
+ eventHub.$emit('deleteMilestoneModal.requestStarted', this.milestoneUrl);
- // follow the rediect to milestones overview page
- redirectTo(response.request.responseURL);
- })
- .catch((error) => {
- eventHub.$emit('deleteMilestoneModal.requestFinished', { milestoneUrl: this.milestoneUrl, successful: false });
+ return axios
+ .delete(this.milestoneUrl)
+ .then(response => {
+ eventHub.$emit('deleteMilestoneModal.requestFinished', {
+ milestoneUrl: this.milestoneUrl,
+ successful: true,
+ });
- if (error.response && error.response.status === 404) {
- Flash(sprintf(s__('Milestones|Milestone %{milestoneTitle} was not found'), { milestoneTitle: this.milestoneTitle }));
- } else {
- Flash(sprintf(s__('Milestones|Failed to delete milestone %{milestoneTitle}'), { milestoneTitle: this.milestoneTitle }));
- }
- throw error;
+ // follow the rediect to milestones overview page
+ redirectTo(response.request.responseURL);
+ })
+ .catch(error => {
+ eventHub.$emit('deleteMilestoneModal.requestFinished', {
+ milestoneUrl: this.milestoneUrl,
+ successful: false,
});
- },
+
+ if (error.response && error.response.status === 404) {
+ Flash(
+ sprintf(s__('Milestones|Milestone %{milestoneTitle} was not found'), {
+ milestoneTitle: this.milestoneTitle,
+ }),
+ );
+ } else {
+ Flash(
+ sprintf(s__('Milestones|Failed to delete milestone %{milestoneTitle}'), {
+ milestoneTitle: this.milestoneTitle,
+ }),
+ );
+ }
+ throw error;
+ });
},
- };
+ },
+};
</script>
<template>
@@ -98,13 +121,10 @@ Once deleted, it cannot be undone or recovered.`),
:text="text"
:primary-button-label="s__('Milestones|Delete milestone')"
kind="danger"
- @submit="onSubmit">
-
- <template
- slot="body"
- slot-scope="props">
+ @submit="onSubmit"
+ >
+ <template slot="body" slot-scope="props">
<p v-html="props.text"></p>
</template>
-
</deprecated-modal>
</template>
diff --git a/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue b/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
index 2c683a39f42..a79ef07f1c5 100644
--- a/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
+++ b/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
@@ -1,54 +1,66 @@
<script>
- import axios from '~/lib/utils/axios_utils';
- import createFlash from '~/flash';
- import GlModal from '~/vue_shared/components/gl_modal.vue';
- import { s__, sprintf } from '~/locale';
- import { visitUrl } from '~/lib/utils/url_utility';
- import eventHub from '../event_hub';
+import axios from '~/lib/utils/axios_utils';
+import createFlash from '~/flash';
+import GlModal from '~/vue_shared/components/gl_modal.vue';
+import { s__, sprintf } from '~/locale';
+import { visitUrl } from '~/lib/utils/url_utility';
+import eventHub from '../event_hub';
- export default {
- components: {
- GlModal,
+export default {
+ components: {
+ GlModal,
+ },
+ props: {
+ milestoneTitle: {
+ type: String,
+ required: true,
},
- props: {
- milestoneTitle: {
- type: String,
- required: true,
- },
- url: {
- type: String,
- required: true,
- },
- groupName: {
- type: String,
- required: true,
- },
+ url: {
+ type: String,
+ required: true,
},
- computed: {
- title() {
- return sprintf(s__('Milestones|Promote %{milestoneTitle} to group milestone?'), { milestoneTitle: this.milestoneTitle });
- },
- text() {
- return sprintf(s__(`Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}.
+ groupName: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ title() {
+ return sprintf(s__('Milestones|Promote %{milestoneTitle} to group milestone?'), {
+ milestoneTitle: this.milestoneTitle,
+ });
+ },
+ text() {
+ return sprintf(
+ s__(`Milestones|Promoting %{milestoneTitle} will make it available for all projects inside %{groupName}.
Existing project milestones with the same title will be merged.
- This action cannot be reversed.`), { milestoneTitle: this.milestoneTitle, groupName: this.groupName });
- },
+ This action cannot be reversed.`),
+ { milestoneTitle: this.milestoneTitle, groupName: this.groupName },
+ );
},
- methods: {
- onSubmit() {
- eventHub.$emit('promoteMilestoneModal.requestStarted', this.url);
- return axios.post(this.url, { params: { format: 'json' } })
- .then((response) => {
- eventHub.$emit('promoteMilestoneModal.requestFinished', { milestoneUrl: this.url, successful: true });
- visitUrl(response.data.url);
- })
- .catch((error) => {
- eventHub.$emit('promoteMilestoneModal.requestFinished', { milestoneUrl: this.url, successful: false });
- createFlash(error);
+ },
+ methods: {
+ onSubmit() {
+ eventHub.$emit('promoteMilestoneModal.requestStarted', this.url);
+ return axios
+ .post(this.url, { params: { format: 'json' } })
+ .then(response => {
+ eventHub.$emit('promoteMilestoneModal.requestFinished', {
+ milestoneUrl: this.url,
+ successful: true,
});
- },
+ visitUrl(response.data.url);
+ })
+ .catch(error => {
+ eventHub.$emit('promoteMilestoneModal.requestFinished', {
+ milestoneUrl: this.url,
+ successful: false,
+ });
+ createFlash(error);
+ });
},
- };
+ },
+};
</script>
<template>
<gl-modal
@@ -57,12 +69,9 @@
footer-primary-button-variant="warning"
@submit="onSubmit"
>
- <template
- slot="title"
- >
+ <template slot="title">
{{ title }}
</template>
{{ text }}
</gl-modal>
</template>
-
diff --git a/app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js b/app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js
index d51b5c221e3..1d559dc6e41 100644
--- a/app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js
+++ b/app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js
@@ -7,7 +7,9 @@ export default () => {
Vue.use(Translate);
const onRequestFinished = ({ milestoneUrl, successful }) => {
- const button = document.querySelector(`.js-delete-milestone-button[data-milestone-url="${milestoneUrl}"]`);
+ const button = document.querySelector(
+ `.js-delete-milestone-button[data-milestone-url="${milestoneUrl}"]`,
+ );
if (!successful) {
button.removeAttribute('disabled');
@@ -16,14 +18,16 @@ export default () => {
button.querySelector('.js-loading-icon').classList.add('hidden');
};
- const onRequestStarted = (milestoneUrl) => {
- const button = document.querySelector(`.js-delete-milestone-button[data-milestone-url="${milestoneUrl}"]`);
+ const onRequestStarted = milestoneUrl => {
+ const button = document.querySelector(
+ `.js-delete-milestone-button[data-milestone-url="${milestoneUrl}"]`,
+ );
button.setAttribute('disabled', '');
button.querySelector('.js-loading-icon').classList.remove('hidden');
eventHub.$once('deleteMilestoneModal.requestFinished', onRequestFinished);
};
- const onDeleteButtonClick = (event) => {
+ const onDeleteButtonClick = event => {
const button = event.currentTarget;
const modalProps = {
milestoneId: parseInt(button.dataset.milestoneId, 10),
@@ -37,12 +41,12 @@ export default () => {
};
const deleteMilestoneButtons = document.querySelectorAll('.js-delete-milestone-button');
- deleteMilestoneButtons.forEach((button) => {
+ deleteMilestoneButtons.forEach(button => {
button.addEventListener('click', onDeleteButtonClick);
});
eventHub.$once('deleteMilestoneModal.mounted', () => {
- deleteMilestoneButtons.forEach((button) => {
+ deleteMilestoneButtons.forEach(button => {
button.removeAttribute('disabled');
});
});
diff --git a/app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js b/app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js
index 8e79341e96a..fcc62a2b2af 100644
--- a/app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js
+++ b/app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js
@@ -7,20 +7,24 @@ Vue.use(Translate);
export default () => {
const onRequestFinished = ({ milestoneUrl, successful }) => {
- const button = document.querySelector(`.js-promote-project-milestone-button[data-url="${milestoneUrl}"]`);
+ const button = document.querySelector(
+ `.js-promote-project-milestone-button[data-url="${milestoneUrl}"]`,
+ );
if (!successful) {
button.removeAttribute('disabled');
}
};
- const onRequestStarted = (milestoneUrl) => {
- const button = document.querySelector(`.js-promote-project-milestone-button[data-url="${milestoneUrl}"]`);
+ const onRequestStarted = milestoneUrl => {
+ const button = document.querySelector(
+ `.js-promote-project-milestone-button[data-url="${milestoneUrl}"]`,
+ );
button.setAttribute('disabled', '');
eventHub.$once('promoteMilestoneModal.requestFinished', onRequestFinished);
};
- const onDeleteButtonClick = (event) => {
+ const onDeleteButtonClick = event => {
const button = event.currentTarget;
const modalProps = {
milestoneTitle: button.dataset.milestoneTitle,
@@ -32,12 +36,12 @@ export default () => {
};
const promoteMilestoneButtons = document.querySelectorAll('.js-promote-project-milestone-button');
- promoteMilestoneButtons.forEach((button) => {
+ promoteMilestoneButtons.forEach(button => {
button.addEventListener('click', onDeleteButtonClick);
});
eventHub.$once('promoteMilestoneModal.mounted', () => {
- promoteMilestoneButtons.forEach((button) => {
+ promoteMilestoneButtons.forEach(button => {
button.removeAttribute('disabled');
});
});
diff --git a/app/assets/javascripts/pages/profiles/index.js b/app/assets/javascripts/pages/profiles/index.js
index 04e50963699..883be18b336 100644
--- a/app/assets/javascripts/pages/profiles/index.js
+++ b/app/assets/javascripts/pages/profiles/index.js
@@ -3,9 +3,12 @@ import '~/profile/gl_crop';
import Profile from '~/profile/profile';
document.addEventListener('DOMContentLoaded', () => {
- $(document).on('input.ssh_key', '#key_key', function () { // eslint-disable-line func-names
+ // eslint-disable-next-line func-names
+ $(document).on('input.ssh_key', '#key_key', function() {
const $title = $('#key_title');
- const comment = $(this).val().match(/^\S+ \S+ (.+)\n?$/);
+ const comment = $(this)
+ .val()
+ .match(/^\S+ \S+ (.+)\n?$/);
// Extract the SSH Key title from its comment
if (comment && comment.length > 1) {
diff --git a/app/assets/javascripts/pages/profiles/show/index.js b/app/assets/javascripts/pages/profiles/show/index.js
index aea7b649c20..c7ce4675573 100644
--- a/app/assets/javascripts/pages/profiles/show/index.js
+++ b/app/assets/javascripts/pages/profiles/show/index.js
@@ -11,7 +11,7 @@ document.addEventListener('DOMContentLoaded', () => {
const statusEmojiField = document.getElementById('js-status-emoji-field');
const statusMessageField = document.getElementById('js-status-message-field');
- const toggleNoEmojiPlaceholder = (isVisible) => {
+ const toggleNoEmojiPlaceholder = isVisible => {
const placeholderElement = document.getElementById('js-no-emoji-placeholder');
placeholderElement.classList.toggle('hidden', !isVisible);
};
@@ -69,5 +69,5 @@ document.addEventListener('DOMContentLoaded', () => {
}
});
})
- .catch(() => createFlash('Failed to load emoji list!'));
+ .catch(() => createFlash('Failed to load emoji list.'));
});
diff --git a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
index 8e8f47c21d8..10cd8ecfbc9 100644
--- a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
+++ b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js
@@ -1,11 +1,14 @@
import $ from 'jquery';
import U2FRegister from '~/u2f/register';
+import { parseBoolean } from '~/lib/utils/common_utils';
document.addEventListener('DOMContentLoaded', () => {
const twoFactorNode = document.querySelector('.js-two-factor-auth');
- const skippable = twoFactorNode.dataset.twoFactorSkippable === 'true';
+ const skippable = parseBoolean(twoFactorNode.dataset.twoFactorSkippable);
if (skippable) {
- const button = `<a class="btn btn-sm btn-warning float-right" data-method="patch" href="${twoFactorNode.dataset.two_factor_skip_url}">Configure it later</a>`;
+ const button = `<a class="btn btn-sm btn-warning float-right" data-method="patch" href="${
+ twoFactorNode.dataset.two_factor_skip_url
+ }">Configure it later</a>`;
const flashAlert = document.querySelector('.flash-alert .container-fluid');
if (flashAlert) flashAlert.insertAdjacentHTML('beforeend', button);
}
diff --git a/app/assets/javascripts/pages/projects/branches/new/index.js b/app/assets/javascripts/pages/projects/branches/new/index.js
index a9658fd1eb4..13ff47d53c2 100644
--- a/app/assets/javascripts/pages/projects/branches/new/index.js
+++ b/app/assets/javascripts/pages/projects/branches/new/index.js
@@ -1,6 +1,11 @@
import $ from 'jquery';
import NewBranchForm from '~/new_branch_form';
-document.addEventListener('DOMContentLoaded', () => (
- new NewBranchForm($('.js-create-branch-form'), JSON.parse(document.getElementById('availableRefs').innerHTML))
-));
+document.addEventListener(
+ 'DOMContentLoaded',
+ () =>
+ new NewBranchForm(
+ $('.js-create-branch-form'),
+ JSON.parse(document.getElementById('availableRefs').innerHTML),
+ ),
+);
diff --git a/app/assets/javascripts/pages/projects/clusters/gcp/new/index.js b/app/assets/javascripts/pages/projects/clusters/gcp/new/index.js
deleted file mode 100644
index d4f34e32a48..00000000000
--- a/app/assets/javascripts/pages/projects/clusters/gcp/new/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import initGkeDropdowns from '~/projects/gke_cluster_dropdowns';
-
-document.addEventListener('DOMContentLoaded', () => {
- initGkeDropdowns();
-});
diff --git a/app/assets/javascripts/pages/projects/clusters/index/index.js b/app/assets/javascripts/pages/projects/clusters/index/index.js
index e4b8baede58..21efc4f6d00 100644
--- a/app/assets/javascripts/pages/projects/clusters/index/index.js
+++ b/app/assets/javascripts/pages/projects/clusters/index/index.js
@@ -1,5 +1,7 @@
-import ClustersIndex from '~/clusters/clusters_index';
+import PersistentUserCallout from '~/persistent_user_callout';
document.addEventListener('DOMContentLoaded', () => {
- new ClustersIndex(); // eslint-disable-line no-new
+ const callout = document.querySelector('.gcp-signup-offer');
+
+ if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new
});
diff --git a/app/assets/javascripts/pages/projects/commit/show/index.js b/app/assets/javascripts/pages/projects/commit/show/index.js
index f477424811d..6fc982967eb 100644
--- a/app/assets/javascripts/pages/projects/commit/show/index.js
+++ b/app/assets/javascripts/pages/projects/commit/show/index.js
@@ -11,6 +11,8 @@ import initDiffNotes from '~/diff_notes/diff_notes_bundle';
import { fetchCommitMergeRequests } from '~/commit_merge_requests';
document.addEventListener('DOMContentLoaded', () => {
+ const hasPerfBar = document.querySelector('.with-performance-bar');
+ const performanceHeight = hasPerfBar ? 35 : 0;
new Diff();
new ZenMode();
new ShortcutsNavigation();
@@ -18,8 +20,7 @@ document.addEventListener('DOMContentLoaded', () => {
container: '.js-commit-pipeline-graph',
}).bindEvents();
initNotes();
- const stickyBarPaddingTop = 16;
- initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight - stickyBarPaddingTop);
+ initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight + performanceHeight);
$('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath);
fetchCommitMergeRequests();
initDiffNotes();
diff --git a/app/assets/javascripts/pages/projects/graphs/charts/index.js b/app/assets/javascripts/pages/projects/graphs/charts/index.js
index 80159a82bd4..3ccad513c05 100644
--- a/app/assets/javascripts/pages/projects/graphs/charts/index.js
+++ b/app/assets/javascripts/pages/projects/graphs/charts/index.js
@@ -31,14 +31,16 @@ document.addEventListener('DOMContentLoaded', () => {
const chartData = data => ({
labels: Object.keys(data),
- datasets: [{
- fillColor: 'rgba(220,220,220,0.5)',
- strokeColor: 'rgba(220,220,220,1)',
- barStrokeWidth: 1,
- barValueSpacing: 1,
- barDatasetSpacing: 1,
- data: _.values(data),
- }],
+ datasets: [
+ {
+ fillColor: 'rgba(220,220,220,0.5)',
+ strokeColor: 'rgba(220,220,220,1)',
+ barStrokeWidth: 1,
+ barValueSpacing: 1,
+ barDatasetSpacing: 1,
+ data: _.values(data),
+ },
+ ],
});
const hourData = chartData(projectChartData.hour);
@@ -51,7 +53,9 @@ document.addEventListener('DOMContentLoaded', () => {
responsiveChart($('#month-chart'), monthData);
const data = projectChartData.languages;
- const ctx = $('#languages-chart').get(0).getContext('2d');
+ const ctx = $('#languages-chart')
+ .get(0)
+ .getContext('2d');
const options = {
scaleOverlay: true,
responsive: true,
diff --git a/app/assets/javascripts/pages/projects/graphs/show/index.js b/app/assets/javascripts/pages/projects/graphs/show/index.js
index 71f629fbc13..f79c386b59e 100644
--- a/app/assets/javascripts/pages/projects/graphs/show/index.js
+++ b/app/assets/javascripts/pages/projects/graphs/show/index.js
@@ -7,7 +7,8 @@ import ContributorsStatGraph from './stat_graph_contributors';
document.addEventListener('DOMContentLoaded', () => {
const url = document.querySelector('.js-graphs-show').dataset.projectGraphPath;
- axios.get(url)
+ axios
+ .get(url)
.then(({ data }) => {
const graph = new ContributorsStatGraph();
graph.init(data);
diff --git a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors.js b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors.js
index 6c1788dc160..76613394af6 100644
--- a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors.js
+++ b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors.js
@@ -1,9 +1,13 @@
-/* eslint-disable func-names, wrap-iife, no-var, one-var, camelcase, one-var-declaration-per-line, quotes, no-param-reassign, quote-props, comma-dangle, prefer-template, max-len, no-return-assign */
+/* eslint-disable func-names, no-var, one-var, camelcase, no-param-reassign, prefer-template, no-return-assign */
import $ from 'jquery';
import _ from 'underscore';
import { n__, s__, createDateTimeFormat, sprintf } from '~/locale';
-import { ContributorsGraph, ContributorsAuthorGraph, ContributorsMasterGraph } from './stat_graph_contributors_graph';
+import {
+ ContributorsGraph,
+ ContributorsAuthorGraph,
+ ContributorsMasterGraph,
+} from './stat_graph_contributors_graph';
import ContributorsStatGraphUtil from './stat_graph_contributors_util';
export default (function() {
@@ -14,7 +18,7 @@ export default (function() {
ContributorsStatGraph.prototype.init = function(log) {
var author_commits, total_commits;
this.parsed_log = ContributorsStatGraphUtil.parse_log(log);
- this.set_current_field("commits");
+ this.set_current_field('commits');
total_commits = ContributorsStatGraphUtil.get_total_data(this.parsed_log, this.field);
author_commits = ContributorsStatGraphUtil.get_author_data(this.parsed_log, this.field);
this.add_master_graph(total_commits);
@@ -31,23 +35,26 @@ export default (function() {
var limited_author_data;
this.authors = [];
limited_author_data = author_data.slice(0, 100);
- return _.each(limited_author_data, (function(_this) {
- return function(d) {
- var author_graph, author_header;
- author_header = _this.create_author_header(d);
- $(".contributors-list").append(author_header);
-
- author_graph = new ContributorsAuthorGraph(d.dates);
- _this.authors[d.author_name] = author_graph;
- return author_graph.draw();
- };
- })(this));
+ return _.each(
+ limited_author_data,
+ (function(_this) {
+ return function(d) {
+ var author_graph, author_header;
+ author_header = _this.create_author_header(d);
+ $('.contributors-list').append(author_header);
+
+ author_graph = new ContributorsAuthorGraph(d.dates);
+ _this.authors[d.author_name] = author_graph;
+ return author_graph.draw();
+ };
+ })(this),
+ );
};
ContributorsStatGraph.prototype.format_author_commit_info = function(author) {
var commits;
commits = $('<span/>', {
- "class": 'graph-author-commits-count'
+ class: 'graph-author-commits-count',
});
commits.text(n__('%d commit', '%d commits', author.commits));
return $('<span/>').append(commits);
@@ -56,13 +63,13 @@ export default (function() {
ContributorsStatGraph.prototype.create_author_header = function(author) {
var author_commit_info, author_commit_info_span, author_email, author_name, list_item;
list_item = $('<li/>', {
- "class": 'person',
- style: 'display: block;'
+ class: 'person',
+ style: 'display: block;',
});
author_name = $('<h4>' + author.author_name + '</h4>');
author_email = $('<p class="graph-author-email">' + author.author_email + '</p>');
author_commit_info_span = $('<span/>', {
- "class": 'commits'
+ class: 'commits',
});
author_commit_info = this.format_author_commit_info(author);
author_commit_info_span.html(author_commit_info);
@@ -80,37 +87,41 @@ export default (function() {
};
ContributorsStatGraph.prototype.redraw_authors = function() {
- $("ol").html("");
+ $('ol').html('');
const { x_domain } = ContributorsGraph.prototype;
- const author_commits = ContributorsStatGraphUtil.get_author_data(this.parsed_log, this.field, x_domain);
-
- return _.each(author_commits, (function(_this) {
- return function(d) {
- _this.redraw_author_commit_info(d);
- if (_this.authors[d.author_name] != null) {
- $(_this.authors[d.author_name].list_item).appendTo("ol");
- _this.authors[d.author_name].set_data(d.dates);
- return _this.authors[d.author_name].redraw();
- }
- return '';
- };
- })(this));
+ const author_commits = ContributorsStatGraphUtil.get_author_data(
+ this.parsed_log,
+ this.field,
+ x_domain,
+ );
+
+ return _.each(
+ author_commits,
+ (function(_this) {
+ return function(d) {
+ _this.redraw_author_commit_info(d);
+ if (_this.authors[d.author_name] != null) {
+ $(_this.authors[d.author_name].list_item).appendTo('ol');
+ _this.authors[d.author_name].set_data(d.dates);
+ return _this.authors[d.author_name].redraw();
+ }
+ return '';
+ };
+ })(this),
+ );
};
ContributorsStatGraph.prototype.set_current_field = function(field) {
- return this.field = field;
+ return (this.field = field);
};
ContributorsStatGraph.prototype.change_date_header = function() {
const { x_domain } = ContributorsGraph.prototype;
- const formattedDateRange = sprintf(
- s__('ContributorsPage|%{startDate} – %{endDate}'),
- {
- startDate: this.dateFormat.format(new Date(x_domain[0])),
- endDate: this.dateFormat.format(new Date(x_domain[1])),
- },
- );
+ const formattedDateRange = sprintf(s__('ContributorsPage|%{startDate} – %{endDate}'), {
+ startDate: this.dateFormat.format(new Date(x_domain[0])),
+ endDate: this.dateFormat.format(new Date(x_domain[1])),
+ });
return $('#date_header').text(formattedDateRange);
};
@@ -120,7 +131,7 @@ export default (function() {
if ($author != null) {
author_list_item = $(this.authors[author.author_name].list_item);
author_commit_info = this.format_author_commit_info(author);
- return author_list_item.find("span").html(author_commit_info);
+ return author_list_item.find('span').html(author_commit_info);
}
return '';
};
diff --git a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js
index a02ec9e5f00..377dce6c746 100644
--- a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js
+++ b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, max-len, no-restricted-syntax, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, comma-dangle, no-return-assign, prefer-arrow-callback, quotes, prefer-template, newline-per-chained-call, no-else-return, no-shadow */
+/* eslint-disable func-names, no-restricted-syntax, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, no-return-assign, prefer-arrow-callback, prefer-template, no-else-return, no-shadow */
import $ from 'jquery';
import _ from 'underscore';
@@ -11,10 +11,32 @@ import { brushX } from 'd3-brush';
import { timeParse } from 'd3-time-format';
import { dateTickFormat } from '~/lib/utils/tick_formats';
-const d3 = { extent, max, select, scaleTime, scaleLinear, axisLeft, axisBottom, area, brushX, timeParse };
+const d3 = {
+ extent,
+ max,
+ select,
+ scaleTime,
+ scaleLinear,
+ axisLeft,
+ axisBottom,
+ area,
+ brushX,
+ timeParse,
+};
const hasProp = {}.hasOwnProperty;
-const extend = function(child, parent) { for (const key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
+const extend = function(child, parent) {
+ for (const key in parent) {
+ if (hasProp.call(parent, key)) child[key] = parent[key];
+ }
+ function ctor() {
+ this.constructor = child;
+ }
+ ctor.prototype = parent.prototype;
+ child.prototype = new ctor();
+ child.__super__ = parent.prototype;
+ return child;
+};
export const ContributorsGraph = (function() {
function ContributorsGraph() {}
@@ -23,7 +45,7 @@ export const ContributorsGraph = (function() {
top: 20,
right: 10,
bottom: 30,
- left: 40
+ left: 40,
};
ContributorsGraph.prototype.x_domain = null;
@@ -33,35 +55,39 @@ export const ContributorsGraph = (function() {
ContributorsGraph.prototype.dates = [];
ContributorsGraph.prototype.determine_width = function(baseWidth, $parentElement) {
- const parentPaddingWidth = parseFloat($parentElement.css('padding-left')) + parseFloat($parentElement.css('padding-right'));
+ const parentPaddingWidth =
+ parseFloat($parentElement.css('padding-left')) +
+ parseFloat($parentElement.css('padding-right'));
const marginWidth = this.MARGIN.left + this.MARGIN.right;
return baseWidth - parentPaddingWidth - marginWidth;
};
ContributorsGraph.set_x_domain = function(data) {
- return ContributorsGraph.prototype.x_domain = data;
+ return (ContributorsGraph.prototype.x_domain = data);
};
ContributorsGraph.set_y_domain = function(data) {
- return ContributorsGraph.prototype.y_domain = [
- 0, d3.max(data, function(d) {
- return d.commits = d.commits || d.additions || d.deletions;
- })
- ];
+ return (ContributorsGraph.prototype.y_domain = [
+ 0,
+ d3.max(data, function(d) {
+ return (d.commits = d.commits || d.additions || d.deletions);
+ }),
+ ]);
};
ContributorsGraph.init_x_domain = function(data) {
- return ContributorsGraph.prototype.x_domain = d3.extent(data, function(d) {
+ return (ContributorsGraph.prototype.x_domain = d3.extent(data, function(d) {
return d.date;
- });
+ }));
};
ContributorsGraph.init_y_domain = function(data) {
- return ContributorsGraph.prototype.y_domain = [
- 0, d3.max(data, function(d) {
- return d.commits = d.commits || d.additions || d.deletions;
- })
- ];
+ return (ContributorsGraph.prototype.y_domain = [
+ 0,
+ d3.max(data, function(d) {
+ return (d.commits = d.commits || d.additions || d.deletions);
+ }),
+ ]);
};
ContributorsGraph.init_domain = function(data) {
@@ -70,7 +96,7 @@ export const ContributorsGraph = (function() {
};
ContributorsGraph.set_dates = function(data) {
- return ContributorsGraph.prototype.dates = data;
+ return (ContributorsGraph.prototype.dates = data);
};
ContributorsGraph.prototype.set_x_domain = function() {
@@ -87,20 +113,33 @@ export const ContributorsGraph = (function() {
};
ContributorsGraph.prototype.create_scale = function(width, height) {
- this.x = d3.scaleTime().range([0, width]).clamp(true);
- return this.y = d3.scaleLinear().range([height, 0]).nice();
+ this.x = d3
+ .scaleTime()
+ .range([0, width])
+ .clamp(true);
+ return (this.y = d3
+ .scaleLinear()
+ .range([height, 0])
+ .nice());
};
ContributorsGraph.prototype.draw_x_axis = function() {
- return this.svg.append("g").attr("class", "x axis").attr("transform", "translate(0, " + this.height + ")").call(this.x_axis);
+ return this.svg
+ .append('g')
+ .attr('class', 'x axis')
+ .attr('transform', 'translate(0, ' + this.height + ')')
+ .call(this.x_axis);
};
ContributorsGraph.prototype.draw_y_axis = function() {
- return this.svg.append("g").attr("class", "y axis").call(this.y_axis);
+ return this.svg
+ .append('g')
+ .attr('class', 'y axis')
+ .call(this.y_axis);
};
ContributorsGraph.prototype.set_data = function(data) {
- return this.data = data;
+ return (this.data = data);
};
return ContributorsGraph;
@@ -137,9 +176,9 @@ export const ContributorsMasterGraph = (function(superClass) {
};
ContributorsMasterGraph.prototype.parse_dates = function(data) {
- const parseDate = d3.timeParse("%Y-%m-%d");
+ const parseDate = d3.timeParse('%Y-%m-%d');
return data.forEach(function(d) {
- return d.date = parseDate(d.date);
+ return (d.date = parseDate(d.date));
});
};
@@ -148,42 +187,63 @@ export const ContributorsMasterGraph = (function(superClass) {
};
ContributorsMasterGraph.prototype.create_axes = function() {
- this.x_axis = d3.axisBottom()
+ this.x_axis = d3
+ .axisBottom()
.scale(this.x)
.tickFormat(dateTickFormat);
- return this.y_axis = d3.axisLeft().scale(this.y).ticks(5);
+ return (this.y_axis = d3
+ .axisLeft()
+ .scale(this.y)
+ .ticks(5));
};
ContributorsMasterGraph.prototype.create_svg = function() {
- this.svg = d3.select("#contributors-master")
- .append("svg")
- .attr("width", this.width + this.MARGIN.left + this.MARGIN.right)
- .attr("height", this.height + this.MARGIN.top + this.MARGIN.bottom)
- .attr("class", "tint-box")
- .append("g")
- .attr("transform", "translate(" + this.MARGIN.left + "," + this.MARGIN.top + ")");
+ this.svg = d3
+ .select('#contributors-master')
+ .append('svg')
+ .attr('width', this.width + this.MARGIN.left + this.MARGIN.right)
+ .attr('height', this.height + this.MARGIN.top + this.MARGIN.bottom)
+ .attr('class', 'tint-box')
+ .append('g')
+ .attr('transform', 'translate(' + this.MARGIN.left + ',' + this.MARGIN.top + ')');
return this.svg;
};
ContributorsMasterGraph.prototype.create_area = function(x, y) {
- return this.area = d3.area().x(function(d) {
- return x(d.date);
- }).y0(this.height).y1(function(d) {
- d.commits = d.commits || d.additions || d.deletions;
- return y(d.commits);
- });
+ return (this.area = d3
+ .area()
+ .x(function(d) {
+ return x(d.date);
+ })
+ .y0(this.height)
+ .y1(function(d) {
+ d.commits = d.commits || d.additions || d.deletions;
+ return y(d.commits);
+ }));
};
ContributorsMasterGraph.prototype.create_brush = function() {
- return this.brush = d3.brushX(this.x).extent([[this.x.range()[0], 0], [this.x.range()[1], this.height]]).on("end", this.update_content);
+ return (this.brush = d3
+ .brushX(this.x)
+ .extent([[this.x.range()[0], 0], [this.x.range()[1], this.height]])
+ .on('end', this.update_content));
};
ContributorsMasterGraph.prototype.draw_path = function(data) {
- return this.svg.append("path").datum(data).attr("class", "area").attr("d", this.area);
+ return this.svg
+ .append('path')
+ .datum(data)
+ .attr('class', 'area')
+ .attr('d', this.area);
};
ContributorsMasterGraph.prototype.add_brush = function() {
- return this.svg.append("g").attr("class", "selection").call(this.brush).selectAll("rect").attr("height", this.height);
+ return this.svg
+ .append('g')
+ .attr('class', 'selection')
+ .call(this.brush)
+ .selectAll('rect')
+ .attr('height', this.height);
};
ContributorsMasterGraph.prototype.update_content = function() {
@@ -193,7 +253,7 @@ export const ContributorsMasterGraph = (function(superClass) {
} else {
ContributorsGraph.set_x_domain(this.x_max_domain);
}
- return $("#brush_change").trigger('change');
+ return $('#brush_change').trigger('change');
};
ContributorsMasterGraph.prototype.draw = function() {
@@ -216,9 +276,9 @@ export const ContributorsMasterGraph = (function(superClass) {
this.process_dates(this.data);
ContributorsGraph.set_y_domain(this.data);
this.set_y_domain();
- this.svg.select("path").datum(this.data);
- this.svg.select("path").attr("d", this.area);
- return this.svg.select(".y.axis").call(this.y_axis);
+ this.svg.select('path').datum(this.data);
+ this.svg.select('path').attr('d', this.area);
+ return this.svg.select('.y.axis').call(this.y_axis);
};
return ContributorsMasterGraph;
@@ -252,43 +312,58 @@ export const ContributorsAuthorGraph = (function(superClass) {
};
ContributorsAuthorGraph.prototype.create_axes = function() {
- this.x_axis = d3.axisBottom()
+ this.x_axis = d3
+ .axisBottom()
.scale(this.x)
.ticks(8)
.tickFormat(dateTickFormat);
- return this.y_axis = d3.axisLeft().scale(this.y).ticks(5);
+ return (this.y_axis = d3
+ .axisLeft()
+ .scale(this.y)
+ .ticks(5));
};
ContributorsAuthorGraph.prototype.create_area = function(x, y) {
- return this.area = d3.area().x(function(d) {
- const parseDate = d3.timeParse("%Y-%m-%d");
- return x(parseDate(d));
- }).y0(this.height).y1((function(_this) {
- return function(d) {
- if (_this.data[d] != null) {
- return y(_this.data[d]);
- } else {
- return y(0);
- }
- };
- })(this));
+ return (this.area = d3
+ .area()
+ .x(function(d) {
+ const parseDate = d3.timeParse('%Y-%m-%d');
+ return x(parseDate(d));
+ })
+ .y0(this.height)
+ .y1(
+ (function(_this) {
+ return function(d) {
+ if (_this.data[d] != null) {
+ return y(_this.data[d]);
+ } else {
+ return y(0);
+ }
+ };
+ })(this),
+ ));
};
ContributorsAuthorGraph.prototype.create_svg = function() {
const persons = document.querySelectorAll('.person');
this.list_item = persons[persons.length - 1];
- this.svg = d3.select(this.list_item)
- .append("svg")
- .attr("width", this.width + this.MARGIN.left + this.MARGIN.right)
- .attr("height", this.height + this.MARGIN.top + this.MARGIN.bottom)
- .attr("class", "spark")
- .append("g")
- .attr("transform", "translate(" + this.MARGIN.left + "," + this.MARGIN.top + ")");
+ this.svg = d3
+ .select(this.list_item)
+ .append('svg')
+ .attr('width', this.width + this.MARGIN.left + this.MARGIN.right)
+ .attr('height', this.height + this.MARGIN.top + this.MARGIN.bottom)
+ .attr('class', 'spark')
+ .append('g')
+ .attr('transform', 'translate(' + this.MARGIN.left + ',' + this.MARGIN.top + ')');
return this.svg;
};
ContributorsAuthorGraph.prototype.draw_path = function(data) {
- return this.svg.append("path").datum(data).attr("class", "area-contributor").attr("d", this.area);
+ return this.svg
+ .append('path')
+ .datum(data)
+ .attr('class', 'area-contributor')
+ .attr('d', this.area);
};
ContributorsAuthorGraph.prototype.draw = function() {
@@ -304,10 +379,10 @@ export const ContributorsAuthorGraph = (function(superClass) {
ContributorsAuthorGraph.prototype.redraw = function() {
this.set_domain();
- this.svg.select("path").datum(this.dates);
- this.svg.select("path").attr("d", this.area);
- this.svg.select(".x.axis").call(this.x_axis);
- return this.svg.select(".y.axis").call(this.y_axis);
+ this.svg.select('path').datum(this.dates);
+ this.svg.select('path').attr('d', this.area);
+ this.svg.select('.x.axis').call(this.x_axis);
+ return this.svg.select('.y.axis').call(this.y_axis);
};
return ContributorsAuthorGraph;
diff --git a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js
index d12249bf612..988ae164955 100644
--- a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js
+++ b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, object-shorthand, no-var, one-var, camelcase, one-var-declaration-per-line, comma-dangle, no-param-reassign, no-return-assign, quotes, prefer-arrow-callback, wrap-iife, consistent-return, no-unused-vars, max-len, no-cond-assign, no-else-return, max-len */
+/* eslint-disable func-names, object-shorthand, no-var, one-var, camelcase, no-param-reassign, no-return-assign, prefer-arrow-callback, consistent-return, no-unused-vars, no-cond-assign, no-else-return */
import _ from 'underscore';
export default {
@@ -26,12 +26,12 @@ export default {
by_author = _.toArray(by_author);
return {
total: total,
- by_author: by_author
+ by_author: by_author,
};
},
add_date: function(date, collection) {
collection[date] = {};
- return collection[date].date = date;
+ return (collection[date].date = date);
},
add_author: function(author, by_author, by_email) {
var data, normalized_email;
@@ -49,28 +49,28 @@ export default {
return this.store_deletions(entry, total, by_author);
},
store_commits: function(total, by_author) {
- this.add(total, "commits", 1);
- return this.add(by_author, "commits", 1);
+ this.add(total, 'commits', 1);
+ return this.add(by_author, 'commits', 1);
},
add: function(collection, field, value) {
if (collection[field] == null) {
collection[field] = 0;
}
- return collection[field] += value;
+ return (collection[field] += value);
},
store_additions: function(entry, total, by_author) {
if (entry.additions == null) {
entry.additions = 0;
}
- this.add(total, "additions", entry.additions);
- return this.add(by_author, "additions", entry.additions);
+ this.add(total, 'additions', entry.additions);
+ return this.add(by_author, 'additions', entry.additions);
},
store_deletions: function(entry, total, by_author) {
if (entry.deletions == null) {
entry.deletions = 0;
}
- this.add(total, "deletions", entry.deletions);
- return this.add(by_author, "deletions", entry.deletions);
+ this.add(total, 'deletions', entry.deletions);
+ return this.add(by_author, 'deletions', entry.deletions);
},
get_total_data: function(parsed_log, field) {
var log, total_data;
@@ -95,15 +95,18 @@ export default {
}
log = parsed_log.by_author;
author_data = [];
- _.each(log, (function(_this) {
- return function(log_entry) {
- var parsed_log_entry;
- parsed_log_entry = _this.parse_log_entry(log_entry, field, date_range);
- if (!_.isEmpty(parsed_log_entry.dates)) {
- return author_data.push(parsed_log_entry);
- }
- };
- })(this));
+ _.each(
+ log,
+ (function(_this) {
+ return function(log_entry) {
+ var parsed_log_entry;
+ parsed_log_entry = _this.parse_log_entry(log_entry, field, date_range);
+ if (!_.isEmpty(parsed_log_entry.dates)) {
+ return author_data.push(parsed_log_entry);
+ }
+ };
+ })(this),
+ );
return _.sortBy(author_data, function(d) {
return d[field];
}).reverse();
@@ -120,16 +123,19 @@ export default {
parsed_entry.additions = 0;
parsed_entry.deletions = 0;
- _.each(_.omit(log_entry, 'author_name', 'author_email'), (function(_this) {
- return function(value, key) {
- if (_this.in_range(value.date, date_range)) {
- parsed_entry.dates[value.date] = value[field];
- parsed_entry.commits += value.commits;
- parsed_entry.additions += value.additions;
- return parsed_entry.deletions += value.deletions;
- }
- };
- })(this));
+ _.each(
+ _.omit(log_entry, 'author_name', 'author_email'),
+ (function(_this) {
+ return function(value, key) {
+ if (_this.in_range(value.date, date_range)) {
+ parsed_entry.dates[value.date] = value[field];
+ parsed_entry.commits += value.commits;
+ parsed_entry.additions += value.additions;
+ return (parsed_entry.deletions += value.deletions);
+ }
+ };
+ })(this),
+ );
return parsed_entry;
},
in_range: function(date, date_range) {
@@ -139,5 +145,5 @@ export default {
} else {
return false;
}
- }
+ },
};
diff --git a/app/assets/javascripts/pages/projects/index.js b/app/assets/javascripts/pages/projects/index.js
index 5659e13981a..b0345b4e50d 100644
--- a/app/assets/javascripts/pages/projects/index.js
+++ b/app/assets/javascripts/pages/projects/index.js
@@ -1,5 +1,5 @@
-import initDismissableCallout from '~/dismissable_callout';
import initGkeDropdowns from '~/projects/gke_cluster_dropdowns';
+import PersistentUserCallout from '../../persistent_user_callout';
import Project from './project';
import ShortcutsNavigation from '../../behaviors/shortcuts/shortcuts_navigation';
@@ -12,7 +12,9 @@ document.addEventListener('DOMContentLoaded', () => {
];
if (newClusterViews.indexOf(page) > -1) {
- initDismissableCallout('.gcp-signup-offer');
+ const callout = document.querySelector('.gcp-signup-offer');
+ if (callout) new PersistentUserCallout(callout); // eslint-disable-line no-new
+
initGkeDropdowns();
}
diff --git a/app/assets/javascripts/pages/projects/init_blob.js b/app/assets/javascripts/pages/projects/init_blob.js
index bc08ccf3584..bd8afa2d5ba 100644
--- a/app/assets/javascripts/pages/projects/init_blob.js
+++ b/app/assets/javascripts/pages/projects/init_blob.js
@@ -16,7 +16,8 @@ export default () => {
);
const fileBlobPermalinkUrlElement = document.querySelector('.js-data-file-blob-permalink-url');
- const fileBlobPermalinkUrl = fileBlobPermalinkUrlElement && fileBlobPermalinkUrlElement.getAttribute('href');
+ const fileBlobPermalinkUrl =
+ fileBlobPermalinkUrlElement && fileBlobPermalinkUrlElement.getAttribute('href');
new ShortcutsNavigation(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/init_form.js b/app/assets/javascripts/pages/projects/init_form.js
index 9f20a3e4e46..019efe077f7 100644
--- a/app/assets/javascripts/pages/projects/init_form.js
+++ b/app/assets/javascripts/pages/projects/init_form.js
@@ -1,7 +1,7 @@
import ZenMode from '~/zen_mode';
import GLForm from '~/gl_form';
-export default function ($formEl) {
+export default function($formEl) {
new ZenMode(); // eslint-disable-line no-new
new GLForm($formEl); // eslint-disable-line no-new
}
diff --git a/app/assets/javascripts/pages/projects/issues/form.js b/app/assets/javascripts/pages/projects/issues/form.js
index 197bfa8a394..02a56685a35 100644
--- a/app/assets/javascripts/pages/projects/issues/form.js
+++ b/app/assets/javascripts/pages/projects/issues/form.js
@@ -7,6 +7,7 @@ import LabelsSelect from '~/labels_select';
import MilestoneSelect from '~/milestone_select';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import IssuableTemplateSelectors from '~/templates/issuable_template_selectors';
+import initSuggestions from '~/issuable_suggestions';
export default () => {
new ShortcutsNavigation();
@@ -15,4 +16,8 @@ export default () => {
new LabelsSelect();
new MilestoneSelect();
new IssuableTemplateSelectors();
+
+ if (gon.features.issueSuggestions && gon.features.graphql) {
+ initSuggestions();
+ }
};
diff --git a/app/assets/javascripts/pages/projects/issues/show.js b/app/assets/javascripts/pages/projects/issues/show.js
index 74b3a515e84..8987c8e3f47 100644
--- a/app/assets/javascripts/pages/projects/issues/show.js
+++ b/app/assets/javascripts/pages/projects/issues/show.js
@@ -3,9 +3,10 @@ import Issue from '~/issue';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import ZenMode from '~/zen_mode';
import '~/notes/index';
-import '~/issue_show/index';
+import initIssueableApp from '~/issue_show';
-export default function () {
+export default function() {
+ initIssueableApp();
new Issue(); // eslint-disable-line no-new
new ShortcutsIssuable(); // eslint-disable-line no-new
new ZenMode(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/jobs/index/index.js b/app/assets/javascripts/pages/projects/jobs/index/index.js
new file mode 100644
index 00000000000..1b57c67f16b
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/jobs/index/index.js
@@ -0,0 +1,16 @@
+import Vue from 'vue';
+import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
+
+document.addEventListener('DOMContentLoaded', () => {
+ const remainingTimeElements = document.querySelectorAll('.js-remaining-time');
+ remainingTimeElements.forEach(
+ el =>
+ new Vue({
+ ...GlCountdown,
+ el,
+ propsData: {
+ endDateString: el.dateTime,
+ },
+ }),
+ );
+});
diff --git a/app/assets/javascripts/pages/projects/jobs/show/index.js b/app/assets/javascripts/pages/projects/jobs/show/index.js
index 3626f3ffec6..d57dbeb1242 100644
--- a/app/assets/javascripts/pages/projects/jobs/show/index.js
+++ b/app/assets/javascripts/pages/projects/jobs/show/index.js
@@ -1,3 +1,3 @@
-import initJobDetails from '~/jobs/job_details_bundle';
+import initJobDetails from '~/jobs';
document.addEventListener('DOMContentLoaded', initJobDetails);
diff --git a/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue b/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
index 5d2247f6c6d..e723cd3fea9 100644
--- a/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
+++ b/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
@@ -1,72 +1,86 @@
<script>
- import _ from 'underscore';
- import axios from '~/lib/utils/axios_utils';
- import createFlash from '~/flash';
- import GlModal from '~/vue_shared/components/gl_modal.vue';
- import { s__, sprintf } from '~/locale';
- import { visitUrl } from '~/lib/utils/url_utility';
- import eventHub from '../event_hub';
+import _ from 'underscore';
+import axios from '~/lib/utils/axios_utils';
+import createFlash from '~/flash';
+import GlModal from '~/vue_shared/components/gl_modal.vue';
+import { s__, sprintf } from '~/locale';
+import { visitUrl } from '~/lib/utils/url_utility';
+import eventHub from '../event_hub';
- export default {
- components: {
- GlModal,
+export default {
+ components: {
+ GlModal,
+ },
+ props: {
+ url: {
+ type: String,
+ required: true,
},
- props: {
- url: {
- type: String,
- required: true,
- },
- labelTitle: {
- type: String,
- required: true,
- },
- labelColor: {
- type: String,
- required: true,
- },
- labelTextColor: {
- type: String,
- required: true,
- },
- groupName: {
- type: String,
- required: true,
- },
+ labelTitle: {
+ type: String,
+ required: true,
},
- computed: {
- text() {
- return sprintf(s__(`Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}.
- Existing project labels with the same title will be merged. This action cannot be reversed.`), {
+ labelColor: {
+ type: String,
+ required: true,
+ },
+ labelTextColor: {
+ type: String,
+ required: true,
+ },
+ groupName: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ text() {
+ return sprintf(
+ s__(`Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}.
+ Existing project labels with the same title will be merged. This action cannot be reversed.`),
+ {
labelTitle: this.labelTitle,
groupName: this.groupName,
- });
- },
- title() {
- const label = `<span
+ },
+ );
+ },
+ title() {
+ const label = `<span
class="label color-label"
style="background-color: ${this.labelColor}; color: ${this.labelTextColor};"
>${_.escape(this.labelTitle)}</span>`;
- return sprintf(s__('Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>'), {
+ return sprintf(
+ s__('Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>'),
+ {
labelTitle: label,
- }, false);
- },
+ },
+ false,
+ );
},
- methods: {
- onSubmit() {
- eventHub.$emit('promoteLabelModal.requestStarted', this.url);
- return axios.post(this.url, { params: { format: 'json' } })
- .then((response) => {
- eventHub.$emit('promoteLabelModal.requestFinished', { labelUrl: this.url, successful: true });
- visitUrl(response.data.url);
- })
- .catch((error) => {
- eventHub.$emit('promoteLabelModal.requestFinished', { labelUrl: this.url, successful: false });
- createFlash(error);
+ },
+ methods: {
+ onSubmit() {
+ eventHub.$emit('promoteLabelModal.requestStarted', this.url);
+ return axios
+ .post(this.url, { params: { format: 'json' } })
+ .then(response => {
+ eventHub.$emit('promoteLabelModal.requestFinished', {
+ labelUrl: this.url,
+ successful: true,
+ });
+ visitUrl(response.data.url);
+ })
+ .catch(error => {
+ eventHub.$emit('promoteLabelModal.requestFinished', {
+ labelUrl: this.url,
+ successful: false,
});
- },
+ createFlash(error);
+ });
},
- };
+ },
+};
</script>
<template>
<gl-modal
@@ -75,13 +89,7 @@
footer-primary-button-variant="warning"
@submit="onSubmit"
>
- <div
- slot="title"
- class="modal-title-with-label"
- v-html="title"
- >
- {{ title }}
- </div>
+ <div slot="title" class="modal-title-with-label" v-html="title">{{ title }}</div>
{{ text }}
</gl-modal>
diff --git a/app/assets/javascripts/pages/projects/labels/index/index.js b/app/assets/javascripts/pages/projects/labels/index/index.js
index 03cfef61311..36cf485f33d 100644
--- a/app/assets/javascripts/pages/projects/labels/index/index.js
+++ b/app/assets/javascripts/pages/projects/labels/index/index.js
@@ -10,20 +10,24 @@ const initLabelIndex = () => {
initLabels();
const onRequestFinished = ({ labelUrl, successful }) => {
- const button = document.querySelector(`.js-promote-project-label-button[data-url="${labelUrl}"]`);
+ const button = document.querySelector(
+ `.js-promote-project-label-button[data-url="${labelUrl}"]`,
+ );
if (!successful) {
button.removeAttribute('disabled');
}
};
- const onRequestStarted = (labelUrl) => {
- const button = document.querySelector(`.js-promote-project-label-button[data-url="${labelUrl}"]`);
+ const onRequestStarted = labelUrl => {
+ const button = document.querySelector(
+ `.js-promote-project-label-button[data-url="${labelUrl}"]`,
+ );
button.setAttribute('disabled', '');
eventHub.$once('promoteLabelModal.requestFinished', onRequestFinished);
};
- const onDeleteButtonClick = (event) => {
+ const onDeleteButtonClick = event => {
const button = event.currentTarget;
const modalProps = {
labelTitle: button.dataset.labelTitle,
@@ -37,12 +41,12 @@ const initLabelIndex = () => {
};
const promoteLabelButtons = document.querySelectorAll('.js-promote-project-label-button');
- promoteLabelButtons.forEach((button) => {
+ promoteLabelButtons.forEach(button => {
button.addEventListener('click', onDeleteButtonClick);
});
eventHub.$once('promoteLabelModal.mounted', () => {
- promoteLabelButtons.forEach((button) => {
+ promoteLabelButtons.forEach(button => {
button.removeAttribute('disabled');
});
});
diff --git a/app/assets/javascripts/pages/projects/merge_requests/index/index.js b/app/assets/javascripts/pages/projects/merge_requests/index/index.js
index 3647048a872..ec39db12e74 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/index/index.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/index/index.js
@@ -7,10 +7,13 @@ import { FILTERED_SEARCH } from '~/pages/constants';
import { ISSUABLE_INDEX } from '~/pages/projects/constants';
document.addEventListener('DOMContentLoaded', () => {
+ IssuableFilteredSearchTokenKeys.addExtraTokensForMergeRequests();
+
initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS,
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
});
+
new IssuableIndex(ISSUABLE_INDEX.MERGE_REQUEST); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new
new UsersSelect(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/network/network.js b/app/assets/javascripts/pages/projects/network/network.js
index 77368c47451..226d63f05c4 100644
--- a/app/assets/javascripts/pages/projects/network/network.js
+++ b/app/assets/javascripts/pages/projects/network/network.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, wrap-iife, no-var, quotes, quote-props, prefer-template, comma-dangle, max-len */
+/* eslint-disable func-names, no-var, prefer-template */
import $ from 'jquery';
import BranchGraph from '../../../network/branch_graph';
@@ -6,13 +6,15 @@ import BranchGraph from '../../../network/branch_graph';
export default (function() {
function Network(opts) {
var vph;
- $("#filter_ref").click(function() {
- return $(this).closest('form').submit();
+ $('#filter_ref').click(function() {
+ return $(this)
+ .closest('form')
+ .submit();
});
- this.branch_graph = new BranchGraph($(".network-graph"), opts);
+ this.branch_graph = new BranchGraph($('.network-graph'), opts);
vph = $(window).height() - 250;
$('.network-graph').css({
- 'height': vph + 'px'
+ height: vph + 'px',
});
}
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
index 544360dcd51..6197dc8a9db 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
@@ -1,12 +1,16 @@
import Vue from 'vue';
import PipelineSchedulesCallout from '../shared/components/pipeline_schedules_callout.vue';
-document.addEventListener('DOMContentLoaded', () => new Vue({
- el: '#pipeline-schedules-callout',
- components: {
- 'pipeline-schedules-callout': PipelineSchedulesCallout,
- },
- render(createElement) {
- return createElement('pipeline-schedules-callout');
- },
-}));
+document.addEventListener(
+ 'DOMContentLoaded',
+ () =>
+ new Vue({
+ el: '#pipeline-schedules-callout',
+ components: {
+ 'pipeline-schedules-callout': PipelineSchedulesCallout,
+ },
+ render(createElement) {
+ return createElement('pipeline-schedules-callout');
+ },
+ }),
+);
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
index 0d05668b285..db2a4041ec0 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
@@ -1,63 +1,63 @@
<script>
- import _ from 'underscore';
+import _ from 'underscore';
- export default {
- props: {
- initialCronInterval: {
- type: String,
- required: false,
- default: '',
- },
- },
- data() {
- return {
- inputNameAttribute: 'schedule[cron]',
- cronInterval: this.initialCronInterval,
- cronIntervalPresets: {
- everyDay: '0 4 * * *',
- everyWeek: '0 4 * * 0',
- everyMonth: '0 4 1 * *',
- },
- cronSyntaxUrl: 'https://en.wikipedia.org/wiki/Cron',
- customInputEnabled: false,
- };
+export default {
+ props: {
+ initialCronInterval: {
+ type: String,
+ required: false,
+ default: '',
},
- computed: {
- intervalIsPreset() {
- return _.contains(this.cronIntervalPresets, this.cronInterval);
- },
- // The text input is editable when there's a custom interval, or when it's
- // a preset interval and the user clicks the 'custom' radio button
- isEditable() {
- return !!(this.customInputEnabled || !this.intervalIsPreset);
+ },
+ data() {
+ return {
+ inputNameAttribute: 'schedule[cron]',
+ cronInterval: this.initialCronInterval,
+ cronIntervalPresets: {
+ everyDay: '0 4 * * *',
+ everyWeek: '0 4 * * 0',
+ everyMonth: '0 4 1 * *',
},
+ cronSyntaxUrl: 'https://en.wikipedia.org/wiki/Cron',
+ customInputEnabled: false,
+ };
+ },
+ computed: {
+ intervalIsPreset() {
+ return _.contains(this.cronIntervalPresets, this.cronInterval);
},
- watch: {
- cronInterval() {
- // updates field validation state when model changes, as
- // glFieldError only updates on input.
- this.$nextTick(() => {
- gl.pipelineScheduleFieldErrors.updateFormValidityState();
- });
- },
+ // The text input is editable when there's a custom interval, or when it's
+ // a preset interval and the user clicks the 'custom' radio button
+ isEditable() {
+ return !!(this.customInputEnabled || !this.intervalIsPreset);
},
- created() {
- if (this.intervalIsPreset) {
- this.enableCustomInput = false;
- }
+ },
+ watch: {
+ cronInterval() {
+ // updates field validation state when model changes, as
+ // glFieldError only updates on input.
+ this.$nextTick(() => {
+ gl.pipelineScheduleFieldErrors.updateFormValidityState();
+ });
},
- methods: {
- toggleCustomInput(shouldEnable) {
- this.customInputEnabled = shouldEnable;
+ },
+ created() {
+ if (this.intervalIsPreset) {
+ this.enableCustomInput = false;
+ }
+ },
+ methods: {
+ toggleCustomInput(shouldEnable) {
+ this.customInputEnabled = shouldEnable;
- if (shouldEnable) {
- // We need to change the value so other radios don't remain selected
- // because the model (cronInterval) hasn't changed. The server trims it.
- this.cronInterval = `${this.cronInterval} `;
- }
- },
+ if (shouldEnable) {
+ // We need to change the value so other radios don't remain selected
+ // because the model (cronInterval) hasn't changed. The server trims it.
+ this.cronInterval = `${this.cronInterval} `;
+ }
},
- };
+ },
+};
</script>
<template>
@@ -70,20 +70,13 @@
:checked="isEditable"
class="label-bold"
type="radio"
- @click="toggleCustomInput(true)"
+ @click="toggleCustomInput(true);"
/>
- <label for="custom">
- {{ s__('PipelineSheduleIntervalPattern|Custom') }}
- </label>
+ <label for="custom"> {{ s__('PipelineSheduleIntervalPattern|Custom') }} </label>
<span class="cron-syntax-link-wrap">
- (<a
- :href="cronSyntaxUrl"
- target="_blank"
- >
- {{ __('Cron syntax') }}
- </a>)
+ (<a :href="cronSyntaxUrl" target="_blank"> {{ __('Cron syntax') }} </a>)
</span>
</div>
@@ -95,15 +88,10 @@
:value="cronIntervalPresets.everyDay"
class="label-bold"
type="radio"
- @click="toggleCustomInput(false)"
+ @click="toggleCustomInput(false);"
/>
- <label
- class="label-bold"
- for="every-day"
- >
- {{ __('Every day (at 4:00am)') }}
- </label>
+ <label class="label-bold" for="every-day"> {{ __('Every day (at 4:00am)') }} </label>
</div>
<div class="cron-preset-radio-input">
@@ -114,13 +102,10 @@
:value="cronIntervalPresets.everyWeek"
class="label-bold"
type="radio"
- @click="toggleCustomInput(false)"
+ @click="toggleCustomInput(false);"
/>
- <label
- class="label-bold"
- for="every-week"
- >
+ <label class="label-bold" for="every-week">
{{ __('Every week (Sundays at 4:00am)') }}
</label>
</div>
@@ -133,13 +118,10 @@
:value="cronIntervalPresets.everyMonth"
class="label-bold"
type="radio"
- @click="toggleCustomInput(false)"
+ @click="toggleCustomInput(false);"
/>
- <label
- class="label-bold"
- for="every-month"
- >
+ <label class="label-bold" for="every-month">
{{ __('Every month (on the 1st at 4:00am)') }}
</label>
</div>
@@ -147,8 +129,8 @@
<div class="cron-interval-input-wrapper">
<input
id="schedule_cron"
- :placeholder="__('Define a custom pattern with cron syntax')"
v-model="cronInterval"
+ :placeholder="__('Define a custom pattern with cron syntax')"
:name="inputNameAttribute"
:disabled="!isEditable"
class="form-control inline cron-interval-input"
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue
index 77508e62cef..22512a6f12a 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue
@@ -1,64 +1,54 @@
<script>
- import Vue from 'vue';
- import Cookies from 'js-cookie';
- import Translate from '../../../../../vue_shared/translate';
- import illustrationSvg from '../icons/intro_illustration.svg';
+import Vue from 'vue';
+import Cookies from 'js-cookie';
+import Translate from '../../../../../vue_shared/translate';
+import illustrationSvg from '../icons/intro_illustration.svg';
+import { parseBoolean } from '~/lib/utils/common_utils';
- Vue.use(Translate);
+Vue.use(Translate);
- const cookieKey = 'pipeline_schedules_callout_dismissed';
+const cookieKey = 'pipeline_schedules_callout_dismissed';
- export default {
- name: 'PipelineSchedulesCallout',
- data() {
- return {
- docsUrl: document.getElementById('pipeline-schedules-callout').dataset.docsUrl,
- calloutDismissed: Cookies.get(cookieKey) === 'true',
- };
+export default {
+ name: 'PipelineSchedulesCallout',
+ data() {
+ return {
+ docsUrl: document.getElementById('pipeline-schedules-callout').dataset.docsUrl,
+ calloutDismissed: parseBoolean(Cookies.get(cookieKey)),
+ };
+ },
+ created() {
+ this.illustrationSvg = illustrationSvg;
+ },
+ methods: {
+ dismissCallout() {
+ this.calloutDismissed = true;
+ Cookies.set(cookieKey, this.calloutDismissed, { expires: 365 });
},
- created() {
- this.illustrationSvg = illustrationSvg;
- },
- methods: {
- dismissCallout() {
- this.calloutDismissed = true;
- Cookies.set(cookieKey, this.calloutDismissed, { expires: 365 });
- },
- },
- };
+ },
+};
</script>
<template>
- <div
- v-if="!calloutDismissed"
- class="pipeline-schedules-user-callout user-callout">
+ <div v-if="!calloutDismissed" class="pipeline-schedules-user-callout user-callout">
<div class="bordered-box landing content-block">
- <button
- id="dismiss-callout-btn"
- class="btn btn-default close"
- @click="dismissCallout">
- <i
- aria-hidden="true"
- class="fa fa-times">
- </i>
+ <button id="dismiss-callout-btn" class="btn btn-default close" @click="dismissCallout">
+ <i aria-hidden="true" class="fa fa-times"> </i>
</button>
- <div
- class="svg-container"
- v-html="illustrationSvg">
- </div>
+ <div class="svg-container" v-html="illustrationSvg"></div>
<div class="user-callout-copy">
<h4>{{ __('Scheduling Pipelines') }}</h4>
<p>
- {{ __(`The pipelines schedule runs pipelines in the future,
+ {{
+ __(`The pipelines schedule runs pipelines in the future,
repeatedly, for specific branches or tags.
-Those scheduled pipelines will inherit limited project access based on their associated user.`) }}
+Those scheduled pipelines will inherit limited project access based on their associated user.`)
+ }}
</p>
- <p> {{ __('Learn more in the') }}
- <a
- :href="docsUrl"
- target="_blank"
- rel="nofollow"
- >
- {{ s__('Learn more in the|pipeline schedules documentation') }}</a>.
+ <p>
+ {{ __('Learn more in the') }}
+ <a :href="docsUrl" target="_blank" rel="nofollow">
+ {{ s__('Learn more in the|pipeline schedules documentation') }}</a
+ >.
<!-- oneline to prevent extra space before period -->
</p>
</div>
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js
index 4ef0d11dd36..0057700c1b3 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js
@@ -26,8 +26,7 @@ export default class TargetBranchDropdown {
}
formatBranchesList() {
- return this.$dropdown.data('data')
- .map(val => ({ name: val }));
+ return this.$dropdown.data('data').map(val => ({ name: val }));
}
setDropdownToggle() {
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
index c3ac54733a3..4d494efef6c 100644
--- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
@@ -11,7 +11,9 @@ Vue.use(Translate);
function initIntervalPatternInput() {
const intervalPatternMount = document.getElementById('interval-pattern-input');
- const initialCronInterval = intervalPatternMount ? intervalPatternMount.dataset.initialInterval : '';
+ const initialCronInterval = intervalPatternMount
+ ? intervalPatternMount.dataset.initialInterval
+ : '';
return new Vue({
el: intervalPatternMount,
diff --git a/app/assets/javascripts/pages/projects/pipelines/charts/index.js b/app/assets/javascripts/pages/projects/pipelines/charts/index.js
index 07b6992eba1..48353f3b4ef 100644
--- a/app/assets/javascripts/pages/projects/pipelines/charts/index.js
+++ b/app/assets/javascripts/pages/projects/pipelines/charts/index.js
@@ -7,26 +7,29 @@ const options = {
maintainAspectRatio: false,
};
-const buildChart = (chartScope) => {
+const buildChart = chartScope => {
const data = {
labels: chartScope.labels,
- datasets: [{
- fillColor: '#707070',
- strokeColor: '#707070',
- pointColor: '#707070',
- pointStrokeColor: '#EEE',
- data: chartScope.totalValues,
- },
- {
- fillColor: '#1aaa55',
- strokeColor: '#1aaa55',
- pointColor: '#1aaa55',
- pointStrokeColor: '#fff',
- data: chartScope.successValues,
- },
+ datasets: [
+ {
+ fillColor: '#707070',
+ strokeColor: '#707070',
+ pointColor: '#707070',
+ pointStrokeColor: '#EEE',
+ data: chartScope.totalValues,
+ },
+ {
+ fillColor: '#1aaa55',
+ strokeColor: '#1aaa55',
+ pointColor: '#1aaa55',
+ pointStrokeColor: '#fff',
+ data: chartScope.successValues,
+ },
],
};
- const ctx = $(`#${chartScope.scope}Chart`).get(0).getContext('2d');
+ const ctx = $(`#${chartScope.scope}Chart`)
+ .get(0)
+ .getContext('2d');
new Chart(ctx).Line(data, options);
};
@@ -36,14 +39,16 @@ document.addEventListener('DOMContentLoaded', () => {
const chartsData = JSON.parse(document.getElementById('pipelinesChartsData').innerHTML);
const data = {
labels: chartTimesData.labels,
- datasets: [{
- fillColor: 'rgba(220,220,220,0.5)',
- strokeColor: 'rgba(220,220,220,1)',
- barStrokeWidth: 1,
- barValueSpacing: 1,
- barDatasetSpacing: 1,
- data: chartTimesData.values,
- }],
+ datasets: [
+ {
+ fillColor: 'rgba(220,220,220,0.5)',
+ strokeColor: 'rgba(220,220,220,1)',
+ barStrokeWidth: 1,
+ barValueSpacing: 1,
+ barDatasetSpacing: 1,
+ data: chartTimesData.values,
+ },
+ ],
};
if (window.innerWidth < 768) {
@@ -51,7 +56,11 @@ document.addEventListener('DOMContentLoaded', () => {
options.scaleFontSize = 8;
}
- new Chart($('#build_timesChart').get(0).getContext('2d')).Bar(data, options);
+ new Chart(
+ $('#build_timesChart')
+ .get(0)
+ .getContext('2d'),
+ ).Bar(data, options);
chartsData.forEach(scope => buildChart(scope));
});
diff --git a/app/assets/javascripts/pages/projects/pipelines/index/index.js b/app/assets/javascripts/pages/projects/pipelines/index/index.js
index a84e2790680..fd72d2ddbe0 100644
--- a/app/assets/javascripts/pages/projects/pipelines/index/index.js
+++ b/app/assets/javascripts/pages/projects/pipelines/index/index.js
@@ -2,39 +2,43 @@ import Vue from 'vue';
import PipelinesStore from '../../../../pipelines/stores/pipelines_store';
import pipelinesComponent from '../../../../pipelines/components/pipelines.vue';
import Translate from '../../../../vue_shared/translate';
-import { convertPermissionToBoolean } from '../../../../lib/utils/common_utils';
+import { parseBoolean } from '../../../../lib/utils/common_utils';
Vue.use(Translate);
-document.addEventListener('DOMContentLoaded', () => new Vue({
- el: '#pipelines-list-vue',
- components: {
- pipelinesComponent,
- },
- data() {
- return {
- store: new PipelinesStore(),
- };
- },
- created() {
- this.dataset = document.querySelector(this.$options.el).dataset;
- },
- render(createElement) {
- return createElement('pipelines-component', {
- props: {
- store: this.store,
- endpoint: this.dataset.endpoint,
- helpPagePath: this.dataset.helpPagePath,
- emptyStateSvgPath: this.dataset.emptyStateSvgPath,
- errorStateSvgPath: this.dataset.errorStateSvgPath,
- noPipelinesSvgPath: this.dataset.noPipelinesSvgPath,
- autoDevopsPath: this.dataset.helpAutoDevopsPath,
- newPipelinePath: this.dataset.newPipelinePath,
- canCreatePipeline: convertPermissionToBoolean(this.dataset.canCreatePipeline),
- hasGitlabCi: convertPermissionToBoolean(this.dataset.hasGitlabCi),
- ciLintPath: this.dataset.ciLintPath,
- resetCachePath: this.dataset.resetCachePath,
+document.addEventListener(
+ 'DOMContentLoaded',
+ () =>
+ new Vue({
+ el: '#pipelines-list-vue',
+ components: {
+ pipelinesComponent,
},
- });
- },
-}));
+ data() {
+ return {
+ store: new PipelinesStore(),
+ };
+ },
+ created() {
+ this.dataset = document.querySelector(this.$options.el).dataset;
+ },
+ render(createElement) {
+ return createElement('pipelines-component', {
+ props: {
+ store: this.store,
+ endpoint: this.dataset.endpoint,
+ helpPagePath: this.dataset.helpPagePath,
+ emptyStateSvgPath: this.dataset.emptyStateSvgPath,
+ errorStateSvgPath: this.dataset.errorStateSvgPath,
+ noPipelinesSvgPath: this.dataset.noPipelinesSvgPath,
+ autoDevopsPath: this.dataset.helpAutoDevopsPath,
+ newPipelinePath: this.dataset.newPipelinePath,
+ canCreatePipeline: parseBoolean(this.dataset.canCreatePipeline),
+ hasGitlabCi: parseBoolean(this.dataset.hasGitlabCi),
+ ciLintPath: this.dataset.ciLintPath,
+ resetCachePath: this.dataset.resetCachePath,
+ },
+ });
+ },
+ }),
+);
diff --git a/app/assets/javascripts/pages/projects/pipelines/init_pipelines.js b/app/assets/javascripts/pages/projects/pipelines/init_pipelines.js
index 94dfeb96e8c..ba4ae04ab3d 100644
--- a/app/assets/javascripts/pages/projects/pipelines/init_pipelines.js
+++ b/app/assets/javascripts/pages/projects/pipelines/init_pipelines.js
@@ -2,9 +2,12 @@ import Pipelines from '~/pipelines';
export default () => {
const { controllerAction } = document.querySelector('.js-pipeline-container').dataset;
- const pipelineStatusUrl = `${document.querySelector('.js-pipeline-tab-link a').getAttribute('href')}/status.json`;
+ const pipelineStatusUrl = `${document
+ .querySelector('.js-pipeline-tab-link a')
+ .getAttribute('href')}/status.json`;
- new Pipelines({ // eslint-disable-line no-new
+ // eslint-disable-next-line no-new
+ new Pipelines({
initTabs: true,
pipelineStatusUrl,
tabsOptions: {
diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js
index 34a13eb3251..a6bee49a6b1 100644
--- a/app/assets/javascripts/pages/projects/project.js
+++ b/app/assets/javascripts/pages/projects/project.js
@@ -1,5 +1,4 @@
-/* eslint-disable func-names, no-var, no-return-assign, one-var,
- one-var-declaration-per-line, object-shorthand, vars-on-top */
+/* eslint-disable func-names, no-var, no-return-assign, one-var, object-shorthand, vars-on-top */
import $ from 'jquery';
import Cookies from 'js-cookie';
@@ -65,7 +64,9 @@ export default class Project {
const projectId = $(this).data('project-id');
const cookieKey = `hide_auto_devops_implicitly_enabled_banner_${projectId}`;
Cookies.set(cookieKey, 'false');
- $(this).parents('.auto-devops-implicitly-enabled-banner').remove();
+ $(this)
+ .parents('.auto-devops-implicitly-enabled-banner')
+ .remove();
return e.preventDefault();
});
Project.projectSelectDropdown();
diff --git a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
index 8f5ac3d8082..15c6fb550c1 100644
--- a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js
@@ -18,7 +18,7 @@ document.addEventListener('DOMContentLoaded', () => {
// eslint-disable-next-line no-new
new AjaxVariableList({
container: variableListEl,
- saveButton: variableListEl.querySelector('.js-secret-variables-save-button'),
+ saveButton: variableListEl.querySelector('.js-ci-variables-save-button'),
errorBox: variableListEl.querySelector('.js-ci-variable-error-box'),
saveEndpoint: variableListEl.dataset.saveEndpoint,
});
diff --git a/app/assets/javascripts/pages/projects/settings/repository/show/index.js b/app/assets/javascripts/pages/projects/settings/repository/show/index.js
index 78cf5406e43..1ef4b460263 100644
--- a/app/assets/javascripts/pages/projects/settings/repository/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/repository/show/index.js
@@ -1,5 +1,5 @@
import initForm from '../form';
-import MirrorRepos from './mirror_repos';
+import MirrorRepos from '~/mirrors/mirror_repos';
document.addEventListener('DOMContentLoaded', () => {
initForm();
diff --git a/app/assets/javascripts/pages/projects/settings/repository/show/mirror_repos.js b/app/assets/javascripts/pages/projects/settings/repository/show/mirror_repos.js
deleted file mode 100644
index 4c56af20cc3..00000000000
--- a/app/assets/javascripts/pages/projects/settings/repository/show/mirror_repos.js
+++ /dev/null
@@ -1,94 +0,0 @@
-import $ from 'jquery';
-import _ from 'underscore';
-import { __ } from '~/locale';
-import Flash from '~/flash';
-import axios from '~/lib/utils/axios_utils';
-
-export default class MirrorRepos {
- constructor(container) {
- this.$container = $(container);
- this.$form = $('.js-mirror-form', this.$container);
- this.$urlInput = $('.js-mirror-url', this.$form);
- this.$protectedBranchesInput = $('.js-mirror-protected', this.$form);
- this.$table = $('.js-mirrors-table-body', this.$container);
- this.mirrorEndpoint = this.$form.data('projectMirrorEndpoint');
- }
-
- init() {
- this.initMirrorPush();
- this.registerUpdateListeners();
- }
-
- initMirrorPush() {
- this.$passwordGroup = $('.js-password-group', this.$container);
- this.$password = $('.js-password', this.$passwordGroup);
- this.$authMethod = $('.js-auth-method', this.$form);
-
- this.$authMethod.on('change', () => this.togglePassword());
- this.$password.on('input.updateUrl', () => this.debouncedUpdateUrl());
- }
-
- updateUrl() {
- let val = this.$urlInput.val();
-
- if (this.$password) {
- const password = this.$password.val();
- if (password) val = val.replace('@', `:${password}@`);
- }
-
- $('.js-mirror-url-hidden', this.$form).val(val);
- }
-
- updateProtectedBranches() {
- const val = this.$protectedBranchesInput.get(0).checked
- ? this.$protectedBranchesInput.val()
- : '0';
- $('.js-mirror-protected-hidden', this.$form).val(val);
- }
-
- registerUpdateListeners() {
- this.debouncedUpdateUrl = _.debounce(() => this.updateUrl(), 200);
- this.$urlInput.on('input', () => this.debouncedUpdateUrl());
- this.$protectedBranchesInput.on('change', () => this.updateProtectedBranches());
- this.$table.on('click', '.js-delete-mirror', event => this.deleteMirror(event));
- }
-
- togglePassword() {
- const isPassword = this.$authMethod.val() === 'password';
-
- if (!isPassword) {
- this.$password.val('');
- this.updateUrl();
- }
- this.$passwordGroup.collapse(isPassword ? 'show' : 'hide');
- }
-
- deleteMirror(event, existingPayload) {
- const $target = $(event.currentTarget);
- let payload = existingPayload;
-
- if (!payload) {
- payload = {
- project: {
- remote_mirrors_attributes: {
- id: $target.data('mirrorId'),
- enabled: 0,
- },
- },
- };
- }
-
- return axios
- .put(this.mirrorEndpoint, payload)
- .then(() => this.removeRow($target))
- .catch(() => Flash(__('Failed to remove mirror.')));
- }
-
- /* eslint-disable class-methods-use-this */
- removeRow($target) {
- const row = $target.closest('tr');
- $('.js-delete-mirror', row).tooltip('hide');
- row.remove();
- }
- /* eslint-enable class-methods-use-this */
-}
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue
index 06101290f6c..ff6dadeff7d 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/project_feature_setting.vue
@@ -1,86 +1,76 @@
<script>
- import projectFeatureToggle from '../../../../../vue_shared/components/toggle_button.vue';
+import projectFeatureToggle from '../../../../../vue_shared/components/toggle_button.vue';
- export default {
- components: {
- projectFeatureToggle,
- },
+export default {
+ components: {
+ projectFeatureToggle,
+ },
- model: {
- prop: 'value',
- event: 'change',
- },
+ model: {
+ prop: 'value',
+ event: 'change',
+ },
- props: {
- name: {
- type: String,
- required: false,
- default: '',
- },
- options: {
- type: Array,
- required: false,
- default: () => [],
- },
- value: {
- type: Number,
- required: false,
- default: 0,
- },
- disabledInput: {
- type: Boolean,
- required: false,
- default: false,
- },
+ props: {
+ name: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ options: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ value: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
+ disabledInput: {
+ type: Boolean,
+ required: false,
+ default: false,
},
+ },
- computed: {
- featureEnabled() {
- return this.value !== 0;
- },
+ computed: {
+ featureEnabled() {
+ return this.value !== 0;
+ },
- displayOptions() {
- if (this.featureEnabled) {
- return this.options;
- }
- return [
- [0, 'Enable feature to choose access level'],
- ];
- },
+ displayOptions() {
+ if (this.featureEnabled) {
+ return this.options;
+ }
+ return [[0, 'Enable feature to choose access level']];
+ },
- displaySelectInput() {
- return this.disabledInput || !this.featureEnabled || this.displayOptions.length < 2;
- },
+ displaySelectInput() {
+ return this.disabledInput || !this.featureEnabled || this.displayOptions.length < 2;
},
+ },
- methods: {
- toggleFeature(featureEnabled) {
- if (featureEnabled === false || this.options.length < 1) {
- this.$emit('change', 0);
- } else {
- const [firstOptionValue] = this.options[this.options.length - 1];
- this.$emit('change', firstOptionValue);
- }
- },
+ methods: {
+ toggleFeature(featureEnabled) {
+ if (featureEnabled === false || this.options.length < 1) {
+ this.$emit('change', 0);
+ } else {
+ const [firstOptionValue] = this.options[this.options.length - 1];
+ this.$emit('change', firstOptionValue);
+ }
+ },
- selectOption(e) {
- this.$emit('change', Number(e.target.value));
- },
+ selectOption(e) {
+ this.$emit('change', Number(e.target.value));
},
- };
+ },
+};
</script>
<template>
- <div
- :data-for="name"
- class="project-feature-controls"
- >
- <input
- v-if="name"
- :name="name"
- :value="value"
- type="hidden"
- />
+ <div :data-for="name" class="project-feature-controls">
+ <input v-if="name" :name="name" :value="value" type="hidden" />
<project-feature-toggle
:value="featureEnabled"
:disabled-input="disabledInput"
@@ -101,11 +91,7 @@
{{ optionName }}
</option>
</select>
- <i
- aria-hidden="true"
- class="fa fa-chevron-down"
- >
- </i>
+ <i aria-hidden="true" class="fa fa-chevron-down"> </i>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue
index 83437363af5..92d23772565 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue
@@ -1,51 +1,33 @@
<script>
- export default {
- props: {
- label: {
- type: String,
- required: false,
- default: null,
- },
- helpPath: {
- type: String,
- required: false,
- default: null,
- },
- helpText: {
- type: String,
- required: false,
- default: null,
- },
+export default {
+ props: {
+ label: {
+ type: String,
+ required: false,
+ default: null,
},
- };
+ helpPath: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ helpText: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+};
</script>
<template>
<div class="project-feature-row">
- <label
- v-if="label"
- class="label-bold"
- >
+ <label v-if="label" class="label-bold">
{{ label }}
- <a
- v-if="helpPath"
- :href="helpPath"
- target="_blank"
- >
- <i
- aria-hidden="true"
- data-hidden="true"
- class="fa fa-question-circle"
- >
- </i>
+ <a v-if="helpPath" :href="helpPath" target="_blank">
+ <i aria-hidden="true" data-hidden="true" class="fa fa-question-circle"> </i>
</a>
</label>
- <span
- v-if="helpText"
- class="form-text text-muted"
- >
- {{ helpText }}
- </span>
- <slot></slot>
+ <span v-if="helpText" class="form-text text-muted"> {{ helpText }} </span> <slot></slot>
</div>
</template>
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
index ae88b765abf..08c7719dcf2 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
+++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
@@ -1,183 +1,206 @@
<script>
- import projectFeatureSetting from './project_feature_setting.vue';
- import projectFeatureToggle from '../../../../../vue_shared/components/toggle_button.vue';
- import projectSettingRow from './project_setting_row.vue';
- import { visibilityOptions, visibilityLevelDescriptions } from '../constants';
- import { toggleHiddenClassBySelector } from '../external';
+import projectFeatureSetting from './project_feature_setting.vue';
+import projectFeatureToggle from '../../../../../vue_shared/components/toggle_button.vue';
+import projectSettingRow from './project_setting_row.vue';
+import { visibilityOptions, visibilityLevelDescriptions } from '../constants';
+import { toggleHiddenClassBySelector } from '../external';
- export default {
- components: {
- projectFeatureSetting,
- projectFeatureToggle,
- projectSettingRow,
- },
+export default {
+ components: {
+ projectFeatureSetting,
+ projectFeatureToggle,
+ projectSettingRow,
+ },
- props: {
- currentSettings: {
- type: Object,
- required: true,
- },
- canChangeVisibilityLevel: {
- type: Boolean,
- required: false,
- default: false,
- },
- allowedVisibilityOptions: {
- type: Array,
- required: false,
- default: () => [0, 10, 20],
- },
- lfsAvailable: {
- type: Boolean,
- required: false,
- default: false,
- },
- registryAvailable: {
- type: Boolean,
- required: false,
- default: false,
- },
- visibilityHelpPath: {
- type: String,
- required: false,
- default: '',
- },
- lfsHelpPath: {
- type: String,
- required: false,
- default: '',
- },
- registryHelpPath: {
- type: String,
- required: false,
- default: '',
- },
+ props: {
+ currentSettings: {
+ type: Object,
+ required: true,
+ },
+ canChangeVisibilityLevel: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ allowedVisibilityOptions: {
+ type: Array,
+ required: false,
+ default: () => [0, 10, 20],
+ },
+ lfsAvailable: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ registryAvailable: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ visibilityHelpPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ lfsHelpPath: {
+ type: String,
+ required: false,
+ default: '',
},
+ registryHelpPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ pagesAvailable: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ pagesAccessControlEnabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ pagesHelpPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+
+ data() {
+ const defaults = {
+ visibilityOptions,
+ visibilityLevel: visibilityOptions.PUBLIC,
+ issuesAccessLevel: 20,
+ repositoryAccessLevel: 20,
+ mergeRequestsAccessLevel: 20,
+ buildsAccessLevel: 20,
+ wikiAccessLevel: 20,
+ snippetsAccessLevel: 20,
+ pagesAccessLevel: 20,
+ containerRegistryEnabled: true,
+ lfsEnabled: true,
+ requestAccessEnabled: true,
+ highlightChangesClass: false,
+ };
- data() {
- const defaults = {
- visibilityOptions,
- visibilityLevel: visibilityOptions.PUBLIC,
- issuesAccessLevel: 20,
- repositoryAccessLevel: 20,
- mergeRequestsAccessLevel: 20,
- buildsAccessLevel: 20,
- wikiAccessLevel: 20,
- snippetsAccessLevel: 20,
- containerRegistryEnabled: true,
- lfsEnabled: true,
- requestAccessEnabled: true,
- highlightChangesClass: false,
- };
+ return { ...defaults, ...this.currentSettings };
+ },
- return { ...defaults, ...this.currentSettings };
+ computed: {
+ featureAccessLevelOptions() {
+ const options = [[10, 'Only Project Members']];
+ if (this.visibilityLevel !== visibilityOptions.PRIVATE) {
+ options.push([20, 'Everyone With Access']);
+ }
+ return options;
},
- computed: {
- featureAccessLevelOptions() {
- const options = [
- [10, 'Only Project Members'],
- ];
- if (this.visibilityLevel !== visibilityOptions.PRIVATE) {
- options.push([20, 'Everyone With Access']);
- }
- return options;
- },
+ repoFeatureAccessLevelOptions() {
+ return this.featureAccessLevelOptions.filter(
+ ([value]) => value <= this.repositoryAccessLevel,
+ );
+ },
- repoFeatureAccessLevelOptions() {
- return this.featureAccessLevelOptions.filter(
- ([value]) => value <= this.repositoryAccessLevel,
- );
- },
+ pagesFeatureAccessLevelOptions() {
+ if (this.visibilityLevel !== visibilityOptions.PUBLIC) {
+ return this.featureAccessLevelOptions.concat([[30, 'Everyone']]);
+ }
+ return this.featureAccessLevelOptions;
+ },
- repositoryEnabled() {
- return this.repositoryAccessLevel > 0;
- },
+ repositoryEnabled() {
+ return this.repositoryAccessLevel > 0;
+ },
- visibilityLevelDescription() {
- return visibilityLevelDescriptions[this.visibilityLevel];
- },
+ visibilityLevelDescription() {
+ return visibilityLevelDescriptions[this.visibilityLevel];
},
+ },
- watch: {
- visibilityLevel(value, oldValue) {
- if (value === visibilityOptions.PRIVATE) {
- // when private, features are restricted to "only team members"
- this.issuesAccessLevel = Math.min(10, this.issuesAccessLevel);
- this.repositoryAccessLevel = Math.min(10, this.repositoryAccessLevel);
- this.mergeRequestsAccessLevel = Math.min(10, this.mergeRequestsAccessLevel);
- this.buildsAccessLevel = Math.min(10, this.buildsAccessLevel);
- this.wikiAccessLevel = Math.min(10, this.wikiAccessLevel);
- this.snippetsAccessLevel = Math.min(10, this.snippetsAccessLevel);
- this.highlightChanges();
- } else if (oldValue === visibilityOptions.PRIVATE) {
- // if changing away from private, make enabled features more permissive
- if (this.issuesAccessLevel > 0) this.issuesAccessLevel = 20;
- if (this.repositoryAccessLevel > 0) this.repositoryAccessLevel = 20;
- if (this.mergeRequestsAccessLevel > 0) this.mergeRequestsAccessLevel = 20;
- if (this.buildsAccessLevel > 0) this.buildsAccessLevel = 20;
- if (this.wikiAccessLevel > 0) this.wikiAccessLevel = 20;
- if (this.snippetsAccessLevel > 0) this.snippetsAccessLevel = 20;
- this.highlightChanges();
+ watch: {
+ visibilityLevel(value, oldValue) {
+ if (value === visibilityOptions.PRIVATE) {
+ // when private, features are restricted to "only team members"
+ this.issuesAccessLevel = Math.min(10, this.issuesAccessLevel);
+ this.repositoryAccessLevel = Math.min(10, this.repositoryAccessLevel);
+ this.mergeRequestsAccessLevel = Math.min(10, this.mergeRequestsAccessLevel);
+ this.buildsAccessLevel = Math.min(10, this.buildsAccessLevel);
+ this.wikiAccessLevel = Math.min(10, this.wikiAccessLevel);
+ this.snippetsAccessLevel = Math.min(10, this.snippetsAccessLevel);
+ if (this.pagesAccessLevel === 20) {
+ // When from Internal->Private narrow access for only members
+ this.pagesAccessLevel = 10;
}
- },
+ this.highlightChanges();
+ } else if (oldValue === visibilityOptions.PRIVATE) {
+ // if changing away from private, make enabled features more permissive
+ if (this.issuesAccessLevel > 0) this.issuesAccessLevel = 20;
+ if (this.repositoryAccessLevel > 0) this.repositoryAccessLevel = 20;
+ if (this.mergeRequestsAccessLevel > 0) this.mergeRequestsAccessLevel = 20;
+ if (this.buildsAccessLevel > 0) this.buildsAccessLevel = 20;
+ if (this.wikiAccessLevel > 0) this.wikiAccessLevel = 20;
+ if (this.snippetsAccessLevel > 0) this.snippetsAccessLevel = 20;
+ if (this.pagesAccessLevel === 10) this.pagesAccessLevel = 20;
+ this.highlightChanges();
+ }
+ },
- repositoryAccessLevel(value, oldValue) {
- if (value < oldValue) {
- // sub-features cannot have more premissive access level
- this.mergeRequestsAccessLevel = Math.min(this.mergeRequestsAccessLevel, value);
- this.buildsAccessLevel = Math.min(this.buildsAccessLevel, value);
+ repositoryAccessLevel(value, oldValue) {
+ if (value < oldValue) {
+ // sub-features cannot have more premissive access level
+ this.mergeRequestsAccessLevel = Math.min(this.mergeRequestsAccessLevel, value);
+ this.buildsAccessLevel = Math.min(this.buildsAccessLevel, value);
- if (value === 0) {
- this.containerRegistryEnabled = false;
- this.lfsEnabled = false;
- }
- } else if (oldValue === 0) {
- this.mergeRequestsAccessLevel = value;
- this.buildsAccessLevel = value;
- this.containerRegistryEnabled = true;
- this.lfsEnabled = true;
+ if (value === 0) {
+ this.containerRegistryEnabled = false;
+ this.lfsEnabled = false;
}
- },
+ } else if (oldValue === 0) {
+ this.mergeRequestsAccessLevel = value;
+ this.buildsAccessLevel = value;
+ this.containerRegistryEnabled = true;
+ this.lfsEnabled = true;
+ }
+ },
- issuesAccessLevel(value, oldValue) {
- if (value === 0) toggleHiddenClassBySelector('.issues-feature', true);
- else if (oldValue === 0) toggleHiddenClassBySelector('.issues-feature', false);
- },
+ issuesAccessLevel(value, oldValue) {
+ if (value === 0) toggleHiddenClassBySelector('.issues-feature', true);
+ else if (oldValue === 0) toggleHiddenClassBySelector('.issues-feature', false);
+ },
- mergeRequestsAccessLevel(value, oldValue) {
- if (value === 0) toggleHiddenClassBySelector('.merge-requests-feature', true);
- else if (oldValue === 0) toggleHiddenClassBySelector('.merge-requests-feature', false);
- },
+ mergeRequestsAccessLevel(value, oldValue) {
+ if (value === 0) toggleHiddenClassBySelector('.merge-requests-feature', true);
+ else if (oldValue === 0) toggleHiddenClassBySelector('.merge-requests-feature', false);
+ },
- buildsAccessLevel(value, oldValue) {
- if (value === 0) toggleHiddenClassBySelector('.builds-feature', true);
- else if (oldValue === 0) toggleHiddenClassBySelector('.builds-feature', false);
- },
+ buildsAccessLevel(value, oldValue) {
+ if (value === 0) toggleHiddenClassBySelector('.builds-feature', true);
+ else if (oldValue === 0) toggleHiddenClassBySelector('.builds-feature', false);
},
+ },
- methods: {
- highlightChanges() {
- this.highlightChangesClass = true;
- this.$nextTick(() => {
- this.highlightChangesClass = false;
- });
- },
+ methods: {
+ highlightChanges() {
+ this.highlightChangesClass = true;
+ this.$nextTick(() => {
+ this.highlightChangesClass = false;
+ });
+ },
- visibilityAllowed(option) {
- return this.allowedVisibilityOptions.includes(option);
- },
+ visibilityAllowed(option) {
+ return this.allowedVisibilityOptions.includes(option);
},
- };
+ },
+};
</script>
<template>
<div>
<div class="project-visibility-setting">
- <project-setting-row
- :help-path="visibilityHelpPath"
- label="Project visibility"
- >
+ <project-setting-row :help-path="visibilityHelpPath" label="Project visibility">
<div class="project-feature-controls">
<div class="select-wrapper">
<select
@@ -205,53 +228,35 @@
Public
</option>
</select>
- <i
- aria-hidden="true"
- data-hidden="true"
- class="fa fa-chevron-down"
- >
- </i>
+ <i aria-hidden="true" data-hidden="true" class="fa fa-chevron-down"> </i>
</div>
</div>
<span class="form-text text-muted">{{ visibilityLevelDescription }}</span>
- <label
- v-if="visibilityLevel !== visibilityOptions.PRIVATE"
- class="request-access"
- >
+ <label v-if="visibilityLevel !== visibilityOptions.PRIVATE" class="request-access">
<input
:value="requestAccessEnabled"
type="hidden"
name="project[request_access_enabled]"
/>
- <input
- v-model="requestAccessEnabled"
- type="checkbox"
- />
- Allow users to request access
+ <input v-model="requestAccessEnabled" type="checkbox" /> Allow users to request access
</label>
</project-setting-row>
</div>
- <div
- :class="{ 'highlight-changes': highlightChangesClass }"
- class="project-feature-settings"
- >
+ <div :class="{ 'highlight-changes': highlightChangesClass }" class="project-feature-settings">
<project-setting-row
label="Issues"
help-text="Lightweight issue tracking system for this project"
>
<project-feature-setting
- :options="featureAccessLevelOptions"
v-model="issuesAccessLevel"
+ :options="featureAccessLevelOptions"
name="project[project_feature_attributes][issues_access_level]"
/>
</project-setting-row>
- <project-setting-row
- label="Repository"
- help-text="View and edit files in this project"
- >
+ <project-setting-row label="Repository" help-text="View and edit files in this project">
<project-feature-setting
- :options="featureAccessLevelOptions"
v-model="repositoryAccessLevel"
+ :options="featureAccessLevelOptions"
name="project[project_feature_attributes][repository_access_level]"
/>
</project-setting-row>
@@ -261,19 +266,16 @@
help-text="Submit changes to be merged upstream"
>
<project-feature-setting
- :options="repoFeatureAccessLevelOptions"
v-model="mergeRequestsAccessLevel"
+ :options="repoFeatureAccessLevelOptions"
:disabled-input="!repositoryEnabled"
name="project[project_feature_attributes][merge_requests_access_level]"
/>
</project-setting-row>
- <project-setting-row
- label="Pipelines"
- help-text="Build, test, and deploy your changes"
- >
+ <project-setting-row label="Pipelines" help-text="Build, test, and deploy your changes">
<project-feature-setting
- :options="repoFeatureAccessLevelOptions"
v-model="buildsAccessLevel"
+ :options="repoFeatureAccessLevelOptions"
:disabled-input="!repositoryEnabled"
name="project[project_feature_attributes][builds_access_level]"
/>
@@ -303,13 +305,10 @@
/>
</project-setting-row>
</div>
- <project-setting-row
- label="Wiki"
- help-text="Pages for project documentation"
- >
+ <project-setting-row label="Wiki" help-text="Pages for project documentation">
<project-feature-setting
- :options="featureAccessLevelOptions"
v-model="wikiAccessLevel"
+ :options="featureAccessLevelOptions"
name="project[project_feature_attributes][wiki_access_level]"
/>
</project-setting-row>
@@ -318,11 +317,23 @@
help-text="Share code pastes with others out of Git repository"
>
<project-feature-setting
- :options="featureAccessLevelOptions"
v-model="snippetsAccessLevel"
+ :options="featureAccessLevelOptions"
name="project[project_feature_attributes][snippets_access_level]"
/>
</project-setting-row>
+ <project-setting-row
+ v-if="pagesAvailable && pagesAccessControlEnabled"
+ :help-path="pagesHelpPath"
+ label="Pages"
+ help-text="Static website for the project."
+ >
+ <project-feature-setting
+ v-model="pagesAccessLevel"
+ :options="pagesFeatureAccessLevelOptions"
+ name="project[project_feature_attributes][pages_access_level]"
+ />
+ </project-setting-row>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/pages/projects/shared/permissions/constants.js b/app/assets/javascripts/pages/projects/shared/permissions/constants.js
index ce47562f259..bc5c29d12b5 100644
--- a/app/assets/javascripts/pages/projects/shared/permissions/constants.js
+++ b/app/assets/javascripts/pages/projects/shared/permissions/constants.js
@@ -5,7 +5,9 @@ export const visibilityOptions = {
};
export const visibilityLevelDescriptions = {
- [visibilityOptions.PRIVATE]: 'The project is accessible only by members of the project. Access must be granted explicitly to each user.',
+ [visibilityOptions.PRIVATE]:
+ 'The project is accessible only by members of the project. Access must be granted explicitly to each user.',
[visibilityOptions.INTERNAL]: 'The project can be accessed by any user who is logged in.',
- [visibilityOptions.PUBLIC]: 'The project can be accessed by anyone, regardless of authentication.',
+ [visibilityOptions.PUBLIC]:
+ 'The project can be accessed by anyone, regardless of authentication.',
};
diff --git a/app/assets/javascripts/pages/projects/shared/project_avatar.js b/app/assets/javascripts/pages/projects/shared/project_avatar.js
index 447877752fe..1e69ecb481d 100644
--- a/app/assets/javascripts/pages/projects/shared/project_avatar.js
+++ b/app/assets/javascripts/pages/projects/shared/project_avatar.js
@@ -8,8 +8,9 @@ export default function projectAvatar() {
$('.js-project-avatar-input').bind('change', function onClickAvatarInput() {
const form = $(this).closest('form');
- // eslint-disable-next-line no-useless-escape
- const filename = $(this).val().replace(/^.*[\\\/]/, '');
+ const filename = $(this)
+ .val()
+ .replace(/^.*[\\\/]/, ''); // eslint-disable-line no-useless-escape
return form.find('.js-avatar-filename').text(filename);
});
}
diff --git a/app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue b/app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue
index 75cb6374ad5..b0c9ca3ec0d 100644
--- a/app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue
+++ b/app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue
@@ -1,8 +1,15 @@
<script>
import _ from 'underscore';
import { s__, sprintf } from '~/locale';
+import { GlModal, GlModalDirective } from '@gitlab/ui';
export default {
+ components: {
+ GlModal,
+ },
+ directives: {
+ 'gl-modal': GlModalDirective,
+ },
props: {
deleteWikiUrl: {
type: String,
@@ -47,14 +54,8 @@ export default {
<template>
<div class="d-inline-block">
- <button
- v-gl-modal="modalId"
- type="button"
- class="btn btn-danger"
- >
- {{ __('Delete') }}
- </button>
- <gl-ui-modal
+ <button v-gl-modal="modalId" type="button" class="btn btn-danger">{{ __('Delete') }}</button>
+ <gl-modal
:title="title"
:ok-title="s__('WikiPageConfirmDelete|Delete page')"
:modal-id="modalId"
@@ -63,24 +64,10 @@ export default {
@ok="onSubmit"
>
{{ message }}
- <form
- ref="form"
- :action="deleteWikiUrl"
- method="post"
- class="js-requires-input"
- >
- <input
- ref="method"
- type="hidden"
- name="_method"
- value="delete"
- />
- <input
- :value="csrfToken"
- type="hidden"
- name="authenticity_token"
- />
+ <form ref="form" :action="deleteWikiUrl" method="post" class="js-requires-input">
+ <input ref="method" type="hidden" name="_method" value="delete" />
+ <input :value="csrfToken" type="hidden" name="authenticity_token" />
</form>
- </gl-ui-modal>
+ </gl-modal>
</div>
</template>
diff --git a/app/assets/javascripts/pages/projects/wikis/index.js b/app/assets/javascripts/pages/projects/wikis/index.js
index c2629090f01..f5fd84d69ac 100644
--- a/app/assets/javascripts/pages/projects/wikis/index.js
+++ b/app/assets/javascripts/pages/projects/wikis/index.js
@@ -21,7 +21,8 @@ document.addEventListener('DOMContentLoaded', () => {
const { deleteWikiUrl, pageTitle } = deleteWikiModalWrapperEl.dataset;
- new Vue({ // eslint-disable-line no-new
+ // eslint-disable-next-line no-new
+ new Vue({
el: deleteWikiModalWrapperEl,
data: {
deleteWikiUrl: '',
diff --git a/app/assets/javascripts/pages/projects/wikis/wikis.js b/app/assets/javascripts/pages/projects/wikis/wikis.js
index d3e8dbf4000..9b58d42b47d 100644
--- a/app/assets/javascripts/pages/projects/wikis/wikis.js
+++ b/app/assets/javascripts/pages/projects/wikis/wikis.js
@@ -1,5 +1,4 @@
import bp from '../../../breakpoints';
-import { slugify } from '../../../lib/utils/text_utility';
import { parseQueryStringIntoObject } from '../../../lib/utils/common_utils';
import { mergeUrlParams, redirectTo } from '../../../lib/utils/url_utility';
@@ -26,7 +25,8 @@ export default class Wikis {
if (!this.newWikiForm) return;
const slugInput = this.newWikiForm.querySelector('#new_wiki_path');
- const slug = slugify(slugInput.value);
+
+ const slug = slugInput.value;
if (slug.length > 0) {
const wikisPath = slugInput.getAttribute('data-wikis-path');
diff --git a/app/assets/javascripts/pages/root/index.js b/app/assets/javascripts/pages/root/index.js
new file mode 100644
index 00000000000..09f8185d3b5
--- /dev/null
+++ b/app/assets/javascripts/pages/root/index.js
@@ -0,0 +1,5 @@
+// if the "projects dashboard" is a user's default dashboard, when they visit the
+// instance root index, the dashboard will be served by the root controller instead
+// of a dashboard controller. The root index redirects for all other default dashboards.
+
+import '../dashboard/projects/index';
diff --git a/app/assets/javascripts/pages/search/show/search.js b/app/assets/javascripts/pages/search/show/search.js
index e3e0ab91993..0c896c8599e 100644
--- a/app/assets/javascripts/pages/search/show/search.js
+++ b/app/assets/javascripts/pages/search/show/search.js
@@ -22,7 +22,7 @@ export default class Search {
fields: ['full_name'],
},
data(term, callback) {
- return Api.groups(term, {}, (data) => {
+ return Api.groups(term, {}, data => {
data.unshift({
full_name: 'Any',
});
@@ -37,7 +37,7 @@ export default class Search {
return obj.full_name;
},
toggleLabel(obj) {
- return `${($groupDropdown.data('defaultLabel'))} ${obj.full_name}`;
+ return `${$groupDropdown.data('defaultLabel')} ${obj.full_name}`;
},
clicked: () => Search.submitSearch(),
});
@@ -52,7 +52,7 @@ export default class Search {
},
data: (term, callback) => {
this.getProjectsData(term)
- .then((data) => {
+ .then(data => {
data.unshift({
name_with_namespace: 'Any',
});
@@ -70,7 +70,7 @@ export default class Search {
return obj.name_with_namespace;
},
toggleLabel(obj) {
- return `${($projectDropdown.data('defaultLabel'))} ${obj.name_with_namespace}`;
+ return `${$projectDropdown.data('defaultLabel')} ${obj.name_with_namespace}`;
},
clicked: () => Search.submitSearch(),
});
@@ -99,17 +99,24 @@ export default class Search {
}
clearSearchField() {
- return $(this.searchInput).val('').trigger('keyup').focus();
+ return $(this.searchInput)
+ .val('')
+ .trigger('keyup')
+ .focus();
}
getProjectsData(term) {
- return new Promise((resolve) => {
+ return new Promise(resolve => {
if (this.groupId) {
Api.groupProjects(this.groupId, term, {}, resolve);
} else {
- Api.projects(term, {
- order_by: 'id',
- }, resolve);
+ Api.projects(
+ term,
+ {
+ order_by: 'id',
+ },
+ resolve,
+ );
}
});
}
diff --git a/app/assets/javascripts/pages/sessions/new/signin_tabs_memoizer.js b/app/assets/javascripts/pages/sessions/new/signin_tabs_memoizer.js
index 1e7c29aefaa..2b8f1e8b0ef 100644
--- a/app/assets/javascripts/pages/sessions/new/signin_tabs_memoizer.js
+++ b/app/assets/javascripts/pages/sessions/new/signin_tabs_memoizer.js
@@ -20,7 +20,7 @@ export default class SigninTabsMemoizer {
bootstrap() {
const tabs = document.querySelectorAll(this.tabSelector);
if (tabs.length > 0) {
- tabs[0].addEventListener('click', (e) => {
+ tabs[0].addEventListener('click', e => {
if (e.target && e.target.nodeName === 'A') {
const anchorName = e.target.getAttribute('href');
this.saveData(anchorName);
diff --git a/app/assets/javascripts/pages/sessions/new/username_validator.js b/app/assets/javascripts/pages/sessions/new/username_validator.js
index 97cf1aeaadc..7a41805bada 100644
--- a/app/assets/javascripts/pages/sessions/new/username_validator.js
+++ b/app/assets/javascripts/pages/sessions/new/username_validator.js
@@ -1,4 +1,4 @@
-/* eslint-disable comma-dangle, consistent-return, class-methods-use-this */
+/* eslint-disable consistent-return, class-methods-use-this */
import $ from 'jquery';
import _ from 'underscore';
@@ -22,10 +22,10 @@ export default class UsernameValidator {
available: false,
valid: false,
pending: false,
- empty: true
+ empty: true,
};
- const debounceTimeout = _.debounce((username) => {
+ const debounceTimeout = _.debounce(username => {
this.validateUsername(username);
}, debounceTimeoutDuration);
@@ -81,7 +81,8 @@ export default class UsernameValidator {
this.state.pending = true;
this.state.available = false;
this.renderState();
- axios.get(`${gon.relative_url_root}/users/${username}/exists`)
+ axios
+ .get(`${gon.relative_url_root}/users/${username}/exists`)
.then(({ data }) => this.setAvailabilityState(data.exists))
.catch(() => flash(__('An error occurred while validating username')));
}
@@ -100,8 +101,7 @@ export default class UsernameValidator {
clearFieldValidationState() {
this.inputElement.siblings('p').hide();
- this.inputElement.removeClass(invalidInputClass)
- .removeClass(successInputClass);
+ this.inputElement.removeClass(invalidInputClass).removeClass(successInputClass);
}
setUnavailableState() {
diff --git a/app/assets/javascripts/pages/snippets/form.js b/app/assets/javascripts/pages/snippets/form.js
index f369c7ef9a6..8859557e62d 100644
--- a/app/assets/javascripts/pages/snippets/form.js
+++ b/app/assets/javascripts/pages/snippets/form.js
@@ -11,6 +11,7 @@ export default () => {
epics: false,
milestones: false,
labels: false,
+ snippets: false,
});
new ZenMode(); // eslint-disable-line no-new
};
diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js
index 9892a039941..8a84ac37dab 100644
--- a/app/assets/javascripts/pages/users/activity_calendar.js
+++ b/app/assets/javascripts/pages/users/activity_calendar.js
@@ -43,7 +43,15 @@ const initColorKey = () =>
.domain([0, 3]);
export default class ActivityCalendar {
- constructor(container, timestamps, calendarActivitiesPath, utcOffset = 0, firstDayOfWeek = 0) {
+ constructor(
+ container,
+ activitiesContainer,
+ timestamps,
+ calendarActivitiesPath,
+ utcOffset = 0,
+ firstDayOfWeek = 0,
+ monthsAgo = 12,
+ ) {
this.calendarActivitiesPath = calendarActivitiesPath;
this.clickDay = this.clickDay.bind(this);
this.currentSelectedDate = '';
@@ -66,6 +74,8 @@ export default class ActivityCalendar {
];
this.months = [];
this.firstDayOfWeek = firstDayOfWeek;
+ this.activitiesContainer = activitiesContainer;
+ this.container = container;
// Loop through the timestamps to create a group of objects
// The group of objects will be grouped based on the day of the week they are
@@ -75,13 +85,13 @@ export default class ActivityCalendar {
const today = getSystemDate(utcOffset);
today.setHours(0, 0, 0, 0, 0);
- const oneYearAgo = new Date(today);
- oneYearAgo.setFullYear(today.getFullYear() - 1);
+ const timeAgo = new Date(today);
+ timeAgo.setMonth(today.getMonth() - monthsAgo);
- const days = getDayDifference(oneYearAgo, today);
+ const days = getDayDifference(timeAgo, today);
for (let i = 0; i <= days; i += 1) {
- const date = new Date(oneYearAgo);
+ const date = new Date(timeAgo);
date.setDate(date.getDate() + i);
const day = date.getDay();
@@ -171,9 +181,8 @@ export default class ActivityCalendar {
.attr('y', stamp => this.dayYPos(stamp.day))
.attr('width', this.daySize)
.attr('height', this.daySize)
- .attr(
- 'fill',
- stamp => (stamp.count !== 0 ? this.color(Math.min(stamp.count, 40)) : '#ededed'),
+ .attr('fill', stamp =>
+ stamp.count !== 0 ? this.color(Math.min(stamp.count, 40)) : '#ededed',
)
.attr('title', stamp => formatTooltipText(stamp))
.attr('class', 'user-contrib-cell js-tooltip')
@@ -280,7 +289,7 @@ export default class ActivityCalendar {
this.currentSelectedDate.getDate(),
].join('-');
- $('.user-calendar-activities').html(LOADING_HTML);
+ $(this.activitiesContainer).html(LOADING_HTML);
axios
.get(this.calendarActivitiesPath, {
@@ -289,11 +298,11 @@ export default class ActivityCalendar {
},
responseType: 'text',
})
- .then(({ data }) => $('.user-calendar-activities').html(data))
+ .then(({ data }) => $(this.activitiesContainer).html(data))
.catch(() => flash(__('An error occurred while retrieving calendar activity')));
} else {
this.currentSelectedDate = '';
- $('.user-calendar-activities').html('');
+ $(this.activitiesContainer).html('');
}
}
}
diff --git a/app/assets/javascripts/pages/users/index.js b/app/assets/javascripts/pages/users/index.js
index 6b1626b0161..a191df00dfa 100644
--- a/app/assets/javascripts/pages/users/index.js
+++ b/app/assets/javascripts/pages/users/index.js
@@ -13,10 +13,12 @@ function initUserProfile(action) {
new UserTabs({ parentEl: '.user-profile', action });
// hide project limit message
- $('.hide-project-limit-message').on('click', (e) => {
+ $('.hide-project-limit-message').on('click', e => {
e.preventDefault();
Cookies.set('hide_project_limit_message', 'false');
- $(this).parents('.project-limit-message').remove();
+ $(this)
+ .parents('.project-limit-message')
+ .remove();
});
}
diff --git a/app/assets/javascripts/pages/users/user_overview_block.js b/app/assets/javascripts/pages/users/user_overview_block.js
new file mode 100644
index 00000000000..eec2b5ca8e5
--- /dev/null
+++ b/app/assets/javascripts/pages/users/user_overview_block.js
@@ -0,0 +1,52 @@
+import axios from '~/lib/utils/axios_utils';
+
+const DEFAULT_LIMIT = 20;
+
+export default class UserOverviewBlock {
+ constructor(options = {}) {
+ this.container = options.container;
+ this.url = options.url;
+ this.requestParams = {
+ limit: DEFAULT_LIMIT,
+ ...options.requestParams,
+ };
+ this.postRenderCallback = options.postRenderCallback;
+ this.loadData();
+ }
+
+ loadData() {
+ const loadingEl = document.querySelector(`${this.container} .loading`);
+
+ loadingEl.classList.remove('hide');
+
+ axios
+ .get(this.url, {
+ params: this.requestParams,
+ })
+ .then(({ data }) => this.render(data))
+ .catch(() => loadingEl.classList.add('hide'));
+ }
+
+ render(data) {
+ const { html, count } = data;
+ const contentList = document.querySelector(`${this.container} .overview-content-list`);
+
+ contentList.innerHTML += html;
+
+ const loadingEl = document.querySelector(`${this.container} .loading`);
+
+ if (count && count > 0) {
+ document.querySelector(`${this.container} .js-view-all`).classList.remove('hide');
+ } else {
+ document
+ .querySelector(`${this.container} .nothing-here-block`)
+ .classList.add('text-left', 'p-0');
+ }
+
+ loadingEl.classList.add('hide');
+
+ if (this.postRenderCallback) {
+ this.postRenderCallback.call(this);
+ }
+ }
+}
diff --git a/app/assets/javascripts/pages/users/user_tabs.js b/app/assets/javascripts/pages/users/user_tabs.js
index a2ca03536f2..aa537d4a43e 100644
--- a/app/assets/javascripts/pages/users/user_tabs.js
+++ b/app/assets/javascripts/pages/users/user_tabs.js
@@ -2,9 +2,11 @@ import $ from 'jquery';
import axios from '~/lib/utils/axios_utils';
import Activities from '~/activities';
import { localTimeAgo } from '~/lib/utils/datetime_utility';
+import AjaxCache from '~/lib/utils/ajax_cache';
import { __ } from '~/locale';
import flash from '~/flash';
import ActivityCalendar from './activity_calendar';
+import UserOverviewBlock from './user_overview_block';
/**
* UserTabs
@@ -64,16 +66,22 @@ import ActivityCalendar from './activity_calendar';
const CALENDAR_TEMPLATE = `
<div class="clearfix calendar">
<div class="js-contrib-calendar"></div>
- <div class="calendar-hint">
- Summary of issues, merge requests, push events, and comments
- </div>
+ <div class="calendar-hint bottom-right"></div>
</div>
`;
+const CALENDAR_PERIOD_6_MONTHS = 6;
+const CALENDAR_PERIOD_12_MONTHS = 12;
+/* computation based on
+ * width = (group + 1) * this.daySizeWithSpace + this.getExtraWidthPadding(group);
+ * (see activity_calendar.js)
+ */
+const OVERVIEW_CALENDAR_BREAKPOINT = 918;
+
export default class UserTabs {
constructor({ defaultAction, action, parentEl }) {
this.loaded = {};
- this.defaultAction = defaultAction || 'activity';
+ this.defaultAction = defaultAction || 'overview';
this.action = action || this.defaultAction;
this.$parentEl = $(parentEl) || $(document);
this.windowLocation = window.location;
@@ -95,6 +103,12 @@ export default class UserTabs {
.off('shown.bs.tab', '.nav-links a[data-toggle="tab"]')
.on('shown.bs.tab', '.nav-links a[data-toggle="tab"]', event => this.tabShown(event))
.on('click', '.gl-pagination a', event => this.changeProjectsPage(event));
+
+ window.addEventListener('resize', () => this.onResize());
+ }
+
+ onResize() {
+ this.loadActivityCalendar();
}
changeProjectsPage(e) {
@@ -124,6 +138,8 @@ export default class UserTabs {
}
if (action === 'activity') {
this.loadActivities();
+ } else if (action === 'overview') {
+ this.loadOverviewTab();
}
const loadableActions = ['groups', 'contributed', 'projects', 'snippets'];
@@ -154,29 +170,69 @@ export default class UserTabs {
if (this.loaded.activity) {
return;
}
- const $calendarWrap = this.$parentEl.find('.user-calendar');
+
+ // eslint-disable-next-line no-new
+ new Activities('#activity');
+
+ this.loaded.activity = true;
+ }
+
+ loadOverviewTab() {
+ if (this.loaded.overview) {
+ return;
+ }
+
+ this.loadActivityCalendar();
+
+ UserTabs.renderMostRecentBlocks('#js-overview .activities-block', {
+ requestParams: { limit: 10 },
+ });
+ UserTabs.renderMostRecentBlocks('#js-overview .projects-block', {
+ requestParams: { limit: 10, skip_pagination: true },
+ });
+
+ this.loaded.overview = true;
+ }
+
+ static renderMostRecentBlocks(container, options) {
+ // eslint-disable-next-line no-new
+ new UserOverviewBlock({
+ container,
+ url: $(`${container} .overview-content-list`).data('href'),
+ ...options,
+ postRenderCallback: () => localTimeAgo($('.js-timeago', container)),
+ });
+ }
+
+ loadActivityCalendar() {
+ const $calendarWrap = this.$parentEl.find('.tab-pane.active .user-calendar');
const calendarPath = $calendarWrap.data('calendarPath');
+
+ AjaxCache.retrieve(calendarPath)
+ .then(data => UserTabs.renderActivityCalendar(data, $calendarWrap))
+ .catch(() => flash(__('There was an error loading users activity calendar.')));
+ }
+
+ static renderActivityCalendar(data, $calendarWrap) {
+ const monthsAgo = UserTabs.getVisibleCalendarPeriod($calendarWrap);
const calendarActivitiesPath = $calendarWrap.data('calendarActivitiesPath');
const utcOffset = $calendarWrap.data('utcOffset');
- let utcFormatted = 'UTC';
- if (utcOffset !== 0) {
- utcFormatted = `UTC${utcOffset > 0 ? '+' : ''}${utcOffset / 3600}`;
- }
+ const calendarHint = __('Issues, merge requests, pushes and comments.');
- axios
- .get(calendarPath)
- .then(({ data }) => {
- $calendarWrap.html(CALENDAR_TEMPLATE);
- $calendarWrap.find('.calendar-hint').append(`(Timezone: ${utcFormatted})`);
+ $calendarWrap.html(CALENDAR_TEMPLATE);
- // eslint-disable-next-line no-new
- new ActivityCalendar('.js-contrib-calendar', data, calendarActivitiesPath, utcOffset);
- })
- .catch(() => flash(__('There was an error loading users activity calendar.')));
+ $calendarWrap.find('.calendar-hint').text(calendarHint);
// eslint-disable-next-line no-new
- new Activities();
- this.loaded.activity = true;
+ new ActivityCalendar(
+ '.tab-pane.active .js-contrib-calendar',
+ '.tab-pane.active .user-calendar-activities',
+ data,
+ calendarActivitiesPath,
+ utcOffset,
+ 0,
+ monthsAgo,
+ );
}
toggleLoading(status) {
@@ -200,4 +256,11 @@ export default class UserTabs {
getCurrentAction() {
return this.$parentEl.find('.nav-links a.active').data('action');
}
+
+ static getVisibleCalendarPeriod($calendarWrap) {
+ const width = $calendarWrap.width();
+ return width < OVERVIEW_CALENDAR_BREAKPOINT
+ ? CALENDAR_PERIOD_6_MONTHS
+ : CALENDAR_PERIOD_12_MONTHS;
+ }
}
diff --git a/app/assets/javascripts/pdf/index.vue b/app/assets/javascripts/pdf/index.vue
index 2f480ecdc69..cdf1257b4e3 100644
--- a/app/assets/javascripts/pdf/index.vue
+++ b/app/assets/javascripts/pdf/index.vue
@@ -1,63 +1,62 @@
<script>
- import pdfjsLib from 'vendor/pdf';
- import workerSrc from 'vendor/pdf.worker.min';
+import pdfjsLib from 'vendor/pdf';
+import workerSrc from 'vendor/pdf.worker.min';
- import page from './page/index.vue';
+import page from './page/index.vue';
- export default {
- components: { page },
- props: {
- pdf: {
- type: [String, Uint8Array],
- required: true,
- },
+export default {
+ components: { page },
+ props: {
+ pdf: {
+ type: [String, Uint8Array],
+ required: true,
},
- data() {
- return {
- loading: false,
- pages: [],
- };
+ },
+ data() {
+ return {
+ loading: false,
+ pages: [],
+ };
+ },
+ computed: {
+ document() {
+ return typeof this.pdf === 'string' ? this.pdf : { data: this.pdf };
},
- computed: {
- document() {
- return typeof this.pdf === 'string' ? this.pdf : { data: this.pdf };
- },
- hasPDF() {
- return this.pdf && this.pdf.length > 0;
- },
+ hasPDF() {
+ return this.pdf && this.pdf.length > 0;
},
- watch: { pdf: 'load' },
- mounted() {
- pdfjsLib.PDFJS.workerSrc = workerSrc;
- if (this.hasPDF) this.load();
+ },
+ watch: { pdf: 'load' },
+ mounted() {
+ pdfjsLib.PDFJS.workerSrc = workerSrc;
+ if (this.hasPDF) this.load();
+ },
+ methods: {
+ load() {
+ this.pages = [];
+ return pdfjsLib
+ .getDocument(this.document)
+ .then(this.renderPages)
+ .then(() => this.$emit('pdflabload'))
+ .catch(error => this.$emit('pdflaberror', error))
+ .then(() => {
+ this.loading = false;
+ });
},
- methods: {
- load() {
- this.pages = [];
- return pdfjsLib.getDocument(this.document)
- .then(this.renderPages)
- .then(() => this.$emit('pdflabload'))
- .catch(error => this.$emit('pdflaberror', error))
- .then(() => { this.loading = false; });
- },
- renderPages(pdf) {
- const pagePromises = [];
- this.loading = true;
- for (let num = 1; num <= pdf.numPages; num += 1) {
- pagePromises.push(
- pdf.getPage(num).then(p => this.pages.push(p)),
- );
- }
- return Promise.all(pagePromises);
- },
+ renderPages(pdf) {
+ const pagePromises = [];
+ this.loading = true;
+ for (let num = 1; num <= pdf.numPages; num += 1) {
+ pagePromises.push(pdf.getPage(num).then(p => this.pages.push(p)));
+ }
+ return Promise.all(pagePromises);
},
- };
+ },
+};
</script>
<template>
- <div
- v-if="hasPDF"
- class="pdf-viewer">
+ <div v-if="hasPDF" class="pdf-viewer">
<page
v-for="(page, index) in pages"
:key="index"
@@ -69,9 +68,9 @@
</template>
<style>
- .pdf-viewer {
- background: url('./assets/img/bg.gif');
- display: flex;
- flex-flow: column nowrap;
- }
+.pdf-viewer {
+ background: url('./assets/img/bg.gif');
+ display: flex;
+ flex-flow: column nowrap;
+}
</style>
diff --git a/app/assets/javascripts/pdf/page/index.vue b/app/assets/javascripts/pdf/page/index.vue
index 9f06833d560..f16aaca6cd7 100644
--- a/app/assets/javascripts/pdf/page/index.vue
+++ b/app/assets/javascripts/pdf/page/index.vue
@@ -1,70 +1,68 @@
<script>
- export default {
- props: {
- page: {
- type: Object,
- required: true,
- },
- number: {
- type: Number,
- required: true,
- },
+export default {
+ props: {
+ page: {
+ type: Object,
+ required: true,
},
- data() {
- return {
- scale: 4,
- rendering: false,
- };
+ number: {
+ type: Number,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ scale: 4,
+ rendering: false,
+ };
+ },
+ computed: {
+ viewport() {
+ return this.page.getViewport(this.scale);
},
- computed: {
- viewport() {
- return this.page.getViewport(this.scale);
- },
- context() {
- return this.$refs.canvas.getContext('2d');
- },
- renderContext() {
- return {
- canvasContext: this.context,
- viewport: this.viewport,
- };
- },
+ context() {
+ return this.$refs.canvas.getContext('2d');
},
- mounted() {
- this.$refs.canvas.height = this.viewport.height;
- this.$refs.canvas.width = this.viewport.width;
- this.rendering = true;
- this.page.render(this.renderContext)
- .then(() => { this.rendering = false; })
- .catch(error => this.$emit('pdflaberror', error));
+ renderContext() {
+ return {
+ canvasContext: this.context,
+ viewport: this.viewport,
+ };
},
- };
+ },
+ mounted() {
+ this.$refs.canvas.height = this.viewport.height;
+ this.$refs.canvas.width = this.viewport.width;
+ this.rendering = true;
+ this.page
+ .render(this.renderContext)
+ .then(() => {
+ this.rendering = false;
+ })
+ .catch(error => this.$emit('pdflaberror', error));
+ },
+};
</script>
<template>
- <canvas
- ref="canvas"
- :data-page="number"
- class="pdf-page"
- >
- </canvas>
+ <canvas ref="canvas" :data-page="number" class="pdf-page"> </canvas>
</template>
<style>
- .pdf-page {
- margin: 8px auto 0 auto;
- border-top: 1px #ddd solid;
- border-bottom: 1px #ddd solid;
- width: 100%;
- }
+.pdf-page {
+ margin: 8px auto 0 auto;
+ border-top: 1px #ddd solid;
+ border-bottom: 1px #ddd solid;
+ width: 100%;
+}
- .pdf-page:first-child {
- margin-top: 0px;
- border-top: 0px;
- }
+.pdf-page:first-child {
+ margin-top: 0px;
+ border-top: 0px;
+}
- .pdf-page:last-child {
- margin-bottom: 0px;
- border-bottom: 0px;
- }
+.pdf-page:last-child {
+ margin-bottom: 0px;
+ border-bottom: 0px;
+}
</style>
diff --git a/app/assets/javascripts/performance_bar/components/detailed_metric.vue b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
index dc7d6d29b8f..c729198c1d3 100644
--- a/app/assets/javascripts/performance_bar/components/detailed_metric.vue
+++ b/app/assets/javascripts/performance_bar/components/detailed_metric.vue
@@ -38,20 +38,14 @@ export default {
};
</script>
<template>
- <div
- v-if="currentRequest.details"
- :id="`peek-view-${metric}`"
- class="view"
- >
+ <div v-if="currentRequest.details" :id="`peek-view-${metric}`" class="view">
<button
:data-target="`#modal-peek-${metric}-details`"
class="btn-blank btn-link bold"
type="button"
data-toggle="modal"
>
- {{ metricDetails.duration }}
- /
- {{ metricDetails.calls }}
+ {{ metricDetails.duration }} / {{ metricDetails.calls }}
</button>
<gl-modal
:id="`modal-peek-${metric}-details`"
@@ -59,35 +53,23 @@ export default {
modal-size="xl"
class="performance-bar-modal"
>
- <table
- class="table"
- >
+ <table class="table">
<template v-if="detailsList.length">
- <tr
- v-for="(item, index) in detailsList"
- :key="index"
- >
- <td><strong>{{ item.duration }}ms</strong></td>
- <td
- v-for="key in keys"
- :key="key"
- class="break-word"
- >
- {{ item[key] }}
+ <tr v-for="(item, index) in detailsList" :key="index">
+ <td>
+ <strong>{{ item.duration }}ms</strong>
</td>
+ <td v-for="key in keys" :key="key" class="break-word">{{ item[key] }}</td>
</tr>
</template>
<template v-else>
<tr>
- <td>
- No {{ header.toLowerCase() }} for this request.
- </td>
+ <td>No {{ header.toLowerCase() }} for this request.</td>
</tr>
</template>
</table>
- <div slot="footer">
- </div>
+ <div slot="footer"></div>
</gl-modal>
{{ metric }}
</div>
diff --git a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
index 0fdb0a080cf..74faa35358d 100644
--- a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
+++ b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue
@@ -1,5 +1,6 @@
<script>
import $ from 'jquery';
+import { glEmojiTag } from '~/emoji';
import detailedMetric from './detailed_metric.vue';
import requestSelector from './request_selector.vue';
@@ -42,7 +43,7 @@ export default {
keys: ['feature', 'request'],
},
],
- simpleMetrics: ['redis', 'sidekiq'],
+ simpleMetrics: ['redis'],
data() {
return { currentRequestId: '' };
},
@@ -64,6 +65,16 @@ export default {
lineProfileModal() {
return $('#modal-peek-line-profile');
},
+ hasHost() {
+ return this.currentRequest && this.currentRequest.details && this.currentRequest.details.host;
+ },
+ birdEmoji() {
+ if (this.hasHost && this.currentRequest.details.host.canary) {
+ return glEmojiTag('baby_chick');
+ }
+
+ return '';
+ },
},
mounted() {
this.currentRequest = this.requestId;
@@ -80,23 +91,15 @@ export default {
};
</script>
<template>
- <div
- id="js-peek"
- :class="env"
- >
- <div
- v-if="currentRequest"
- class="d-flex container-fluid container-limited"
- >
- <div
- id="peek-view-host"
- class="view"
- >
+ <div id="js-peek" :class="env">
+ <div v-if="currentRequest" class="d-flex container-fluid container-limited">
+ <div id="peek-view-host" class="view">
<span
- v-if="currentRequest.details"
+ v-if="hasHost"
class="current-host"
+ :class="{ canary: currentRequest.details.host.canary }"
>
- {{ currentRequest.details.host.hostname }}
+ <span v-html="birdEmoji"></span> {{ currentRequest.details.host.hostname }}
</span>
</div>
<detailed-metric
@@ -108,11 +111,7 @@ export default {
:details="metric.details"
:keys="metric.keys"
/>
- <div
- v-if="initialRequest"
- id="peek-view-rblineprof"
- class="view"
- >
+ <div v-if="initialRequest" id="peek-view-rblineprof" class="view">
<button
v-if="lineProfileModal.length"
class="btn-link btn-blank"
@@ -121,31 +120,18 @@ export default {
>
profile
</button>
- <a
- v-else
- :href="profileUrl"
- >
- profile
- </a>
+ <a v-else :href="profileUrl"> profile </a>
</div>
<simple-metric
v-for="metric in $options.simpleMetrics"
- :current-request="currentRequest"
:key="metric"
+ :current-request="currentRequest"
:metric="metric"
/>
- <div
- id="peek-view-gc"
- class="view"
- >
- <span
- v-if="currentRequest.details"
- class="bold"
- >
- <span title="Invoke Time">{{ currentRequest.details.gc.gc_time }}</span>ms
- /
- <span title="Invoke Count">{{ currentRequest.details.gc.invokes }}</span>
- gc
+ <div id="peek-view-gc" class="view">
+ <span v-if="currentRequest.details" class="bold">
+ <span title="Invoke Time">{{ currentRequest.details.gc.gc_time }}</span
+ >ms / <span title="Invoke Count">{{ currentRequest.details.gc.invokes }}</span> gc
</span>
</div>
<request-selector
diff --git a/app/assets/javascripts/performance_bar/components/request_selector.vue b/app/assets/javascripts/performance_bar/components/request_selector.vue
index ad74f7b38f9..fdb5c0d6939 100644
--- a/app/assets/javascripts/performance_bar/components/request_selector.vue
+++ b/app/assets/javascripts/performance_bar/components/request_selector.vue
@@ -37,11 +37,7 @@ export default {
<template>
<div id="peek-request-selector">
<select v-model="currentRequestId">
- <option
- v-for="request in requests"
- :key="request.id"
- :value="request.id"
- >
+ <option v-for="request in requests" :key="request.id" :value="request.id">
{{ truncatedUrl(request.url) }}
</option>
</select>
diff --git a/app/assets/javascripts/performance_bar/components/simple_metric.vue b/app/assets/javascripts/performance_bar/components/simple_metric.vue
index b654bc66249..358a57d5bc5 100644
--- a/app/assets/javascripts/performance_bar/components/simple_metric.vue
+++ b/app/assets/javascripts/performance_bar/components/simple_metric.vue
@@ -10,21 +10,24 @@ export default {
required: true,
},
},
+ computed: {
+ duration() {
+ return (
+ this.currentRequest.details[this.metric] &&
+ this.currentRequest.details[this.metric].duration
+ );
+ },
+ calls() {
+ return (
+ this.currentRequest.details[this.metric] && this.currentRequest.details[this.metric].calls
+ );
+ },
+ },
};
</script>
<template>
- <div
- :id="`peek-view-${metric}`"
- class="view"
- >
- <span
- v-if="currentRequest.details"
- class="bold"
- >
- {{ currentRequest.details[metric].duration }}
- /
- {{ currentRequest.details[metric].calls }}
- </span>
+ <div :id="`peek-view-${metric}`" class="view">
+ <span v-if="currentRequest.details" class="bold"> {{ duration }} / {{ calls }} </span>
{{ metric }}
</div>
</template>
diff --git a/app/assets/javascripts/performance_bar/index.js b/app/assets/javascripts/performance_bar/index.js
index 6e5ef0ac0b2..29bfb7ee5df 100644
--- a/app/assets/javascripts/performance_bar/index.js
+++ b/app/assets/javascripts/performance_bar/index.js
@@ -9,8 +9,7 @@ export default ({ container }) =>
performanceBarApp: () => import('./components/performance_bar_app.vue'),
},
data() {
- const performanceBarData = document.querySelector(this.$options.el)
- .dataset;
+ const performanceBarData = document.querySelector(this.$options.el).dataset;
const store = new PerformanceBarStore();
return {
diff --git a/app/assets/javascripts/performance_bar/services/performance_bar_service.js b/app/assets/javascripts/performance_bar/services/performance_bar_service.js
index 60d9ba62570..d8c23c82f7f 100644
--- a/app/assets/javascripts/performance_bar/services/performance_bar_service.js
+++ b/app/assets/javascripts/performance_bar/services/performance_bar_service.js
@@ -1,6 +1,7 @@
import Vue from 'vue';
import _ from 'underscore';
import axios from '../../lib/utils/axios_utils';
+import { parseBoolean } from '~/lib/utils/common_utils';
let vueResourceInterceptor;
@@ -11,8 +12,10 @@ export default class PerformanceBarService {
static registerInterceptor(peekUrl, callback) {
const interceptor = response => {
- const [fireCallback, requestId, requestUrl] =
- PerformanceBarService.callbackParams(response, peekUrl);
+ const [fireCallback, requestId, requestUrl] = PerformanceBarService.callbackParams(
+ response,
+ peekUrl,
+ );
if (fireCallback) {
callback(requestId, requestUrl);
@@ -30,10 +33,7 @@ export default class PerformanceBarService {
static removeInterceptor(interceptor) {
axios.interceptors.response.eject(interceptor);
- Vue.http.interceptors = _.without(
- Vue.http.interceptors,
- vueResourceInterceptor,
- );
+ Vue.http.interceptors = _.without(Vue.http.interceptors, vueResourceInterceptor);
}
static callbackParams(response, peekUrl) {
@@ -42,7 +42,8 @@ export default class PerformanceBarService {
// Vue Resource.
const requestUrl = (response.config || response).url;
const apiRequest = requestUrl && requestUrl.match(/^\/api\//);
- const cachedResponse = response.headers && response.headers['x-gitlab-from-cache'] === 'true';
+ const cachedResponse =
+ response.headers && parseBoolean(response.headers['x-gitlab-from-cache']);
const fireCallback = requestUrl !== peekUrl && requestId && !apiRequest && !cachedResponse;
return [fireCallback, requestId, requestUrl];
diff --git a/app/assets/javascripts/performance_bar/stores/performance_bar_store.js b/app/assets/javascripts/performance_bar/stores/performance_bar_store.js
index c6b2f55243c..031e774d533 100644
--- a/app/assets/javascripts/performance_bar/stores/performance_bar_store.js
+++ b/app/assets/javascripts/performance_bar/stores/performance_bar_store.js
@@ -32,8 +32,6 @@ export default class PerformanceBarStore {
}
canTrackRequest(requestUrl) {
- return (
- this.requests.filter(request => request.url === requestUrl).length < 2
- );
+ return this.requests.filter(request => request.url === requestUrl).length < 2;
}
}
diff --git a/app/assets/javascripts/persistent_user_callout.js b/app/assets/javascripts/persistent_user_callout.js
new file mode 100644
index 00000000000..1e34e74a152
--- /dev/null
+++ b/app/assets/javascripts/persistent_user_callout.js
@@ -0,0 +1,34 @@
+import axios from './lib/utils/axios_utils';
+import { __ } from './locale';
+import Flash from './flash';
+
+export default class PersistentUserCallout {
+ constructor(container) {
+ const { dismissEndpoint, featureId } = container.dataset;
+ this.container = container;
+ this.dismissEndpoint = dismissEndpoint;
+ this.featureId = featureId;
+
+ this.init();
+ }
+
+ init() {
+ const closeButton = this.container.querySelector('.js-close');
+ closeButton.addEventListener('click', event => this.dismiss(event));
+ }
+
+ dismiss(event) {
+ event.preventDefault();
+
+ axios
+ .post(this.dismissEndpoint, {
+ feature_name: this.featureId,
+ })
+ .then(() => {
+ this.container.remove();
+ })
+ .catch(() => {
+ Flash(__('An error occurred while dismissing the alert. Refresh the page and try again.'));
+ });
+ }
+}
diff --git a/app/assets/javascripts/pipelines/components/blank_state.vue b/app/assets/javascripts/pipelines/components/blank_state.vue
index 34360105176..6c3a4a27606 100644
--- a/app/assets/javascripts/pipelines/components/blank_state.vue
+++ b/app/assets/javascripts/pipelines/components/blank_state.vue
@@ -18,9 +18,7 @@ export default {
<template>
<div class="row empty-state">
<div class="col-12">
- <div class="svg-content">
- <img :src="svgPath" />
- </div>
+ <div class="svg-content"><img :src="svgPath" /></div>
</div>
<div class="col-12 text-center">
diff --git a/app/assets/javascripts/pipelines/components/empty_state.vue b/app/assets/javascripts/pipelines/components/empty_state.vue
index c5a45afc634..d16f49f981c 100644
--- a/app/assets/javascripts/pipelines/components/empty_state.vue
+++ b/app/assets/javascripts/pipelines/components/empty_state.vue
@@ -1,6 +1,11 @@
<script>
+import { GlButton } from '@gitlab/ui';
+
export default {
name: 'PipelinesEmptyState',
+ components: {
+ GlButton,
+ },
props: {
helpPagePath: {
type: String,
@@ -20,43 +25,33 @@ export default {
<template>
<div class="row empty-state js-empty-state">
<div class="col-12">
- <div class="svg-content svg-250">
- <img :src="emptyStateSvgPath" />
- </div>
+ <div class="svg-content svg-250"><img :src="emptyStateSvgPath" /></div>
</div>
<div class="col-12">
<div class="text-content">
-
<template v-if="canSetCi">
- <h4 class="text-center">
- {{ s__('Pipelines|Build with confidence') }}
- </h4>
+ <h4 class="text-center">{{ s__('Pipelines|Build with confidence') }}</h4>
<p>
- {{ s__(`Pipelines|Continuous Integration can help
+ {{
+ s__(`Pipelines|Continuous Integration can help
catch bugs by running your tests automatically,
while Continuous Deployment can help you deliver
- code to your product environment.`) }}
+ code to your product environment.`)
+ }}
</p>
<div class="text-center">
- <a
- :href="helpPagePath"
- class="btn btn-primary js-get-started-pipelines"
- >
+ <gl-button :href="helpPagePath" variant="primary" class="js-get-started-pipelines">
{{ s__('Pipelines|Get started with Pipelines') }}
- </a>
+ </gl-button>
</div>
</template>
- <p
- v-else
- class="text-center"
- >
+ <p v-else class="text-center">
{{ s__('Pipelines|This project is not currently set up to run pipelines.') }}
</p>
-
</div>
</div>
</div>
diff --git a/app/assets/javascripts/pipelines/components/graph/action_component.vue b/app/assets/javascripts/pipelines/components/graph/action_component.vue
index b82e28a0735..8ca539351a7 100644
--- a/app/assets/javascripts/pipelines/components/graph/action_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/action_component.vue
@@ -1,10 +1,9 @@
<script>
-import $ from 'jquery';
+import { GlTooltipDirective, GlButton } from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
import { dasherize } from '~/lib/utils/text_utility';
import { __ } from '~/locale';
import createFlash from '~/flash';
-import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
/**
@@ -20,23 +19,20 @@ import Icon from '~/vue_shared/components/icon.vue';
export default {
components: {
Icon,
+ GlButton,
},
-
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
-
props: {
tooltipText: {
type: String,
required: true,
},
-
link: {
type: String,
required: true,
},
-
actionIcon: {
type: String,
required: true,
@@ -47,7 +43,6 @@ export default {
isDisabled: false,
};
},
-
computed: {
cssClass() {
const actionIconDash = dasherize(this.actionIcon);
@@ -62,8 +57,7 @@ export default {
*
*/
onClickAction() {
- $(this.$el).tooltip('hide');
-
+ this.$root.$emit('bv::hide::tooltip', `js-ci-action-${this.link}`);
this.isDisabled = true;
axios
@@ -82,18 +76,16 @@ export default {
};
</script>
<template>
- <button
- v-tooltip
+ <gl-button
+ :id="`js-ci-action-${link}`"
+ v-gl-tooltip="{ boundary: 'viewport' }"
:title="tooltipText"
:class="cssClass"
:disabled="isDisabled"
- type="button"
class="js-ci-action btn btn-blank
btn-transparent ci-action-icon-container ci-action-icon-wrapper"
- data-container="body"
- data-boundary="viewport"
@click="onClickAction"
>
- <icon :name="actionIcon"/>
- </button>
+ <icon :name="actionIcon" />
+ </gl-button>
</template>
diff --git a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue b/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue
deleted file mode 100644
index 2ad66f4fe86..00000000000
--- a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue
+++ /dev/null
@@ -1,122 +0,0 @@
-<script>
-import $ from 'jquery';
-import JobNameComponent from './job_name_component.vue';
-import JobComponent from './job_component.vue';
-import tooltip from '../../../vue_shared/directives/tooltip';
-
-/**
- * Renders the dropdown for the pipeline graph.
- *
- * The following object should be provided as `job`:
- *
- * {
- * "id": 4256,
- * "name": "test",
- * "status": {
- * "icon": "status_success",
- * "text": "passed",
- * "label": "passed",
- * "group": "success",
- * "details_path": "/root/ci-mock/builds/4256",
- * "action": {
- * "icon": "retry",
- * "title": "Retry",
- * "path": "/root/ci-mock/builds/4256/retry",
- * "method": "post"
- * }
- * }
- * }
- */
-export default {
- directives: {
- tooltip,
- },
-
- components: {
- JobComponent,
- JobNameComponent,
- },
-
- props: {
- job: {
- type: Object,
- required: true,
- },
- },
-
- computed: {
- tooltipText() {
- return `${this.job.name} - ${this.job.status.label}`;
- },
- },
-
- mounted() {
- this.stopDropdownClickPropagation();
- },
-
- methods: {
- /**
- * When the user right clicks or cmd/ctrl + click in the job name or the action icon
- * the dropdown should not be closed so we stop propagation
- * of the click event inside the dropdown.
- *
- * Since this component is rendered multiple times per page we need to guarantee we only
- * target the click event of this component.
- */
- stopDropdownClickPropagation() {
- $(
- '.js-grouped-pipeline-dropdown button, .js-grouped-pipeline-dropdown a.mini-pipeline-graph-dropdown-item',
- this.$el,
- ).on('click', e => {
- e.stopPropagation();
- });
- },
-
- pipelineActionRequestComplete() {
- this.$emit('pipelineActionRequestComplete');
- },
- },
-};
-</script>
-<template>
- <div class="ci-job-dropdown-container dropdown dropright">
- <button
- v-tooltip
- :title="tooltipText"
- type="button"
- data-toggle="dropdown"
- data-container="body"
- data-boundary="viewport"
- data-display="static"
- class="dropdown-menu-toggle build-content"
- >
-
- <job-name-component
- :name="job.name"
- :status="job.status"
- />
-
- <span class="dropdown-counter-badge">
- {{ job.size }}
- </span>
- </button>
-
- <ul class="dropdown-menu big-pipeline-graph-dropdown-menu js-grouped-pipeline-dropdown">
- <li class="scrollable-menu">
- <ul>
- <li
- v-for="(item, i) in job.jobs"
- :key="i"
- >
- <job-component
- :dropdown-length="job.size"
- :job="item"
- css-class-job-name="mini-pipeline-graph-dropdown-item"
- @pipelineActionRequestComplete="pipelineActionRequestComplete"
- />
- </li>
- </ul>
- </li>
- </ul>
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
index e27f195c9b0..59cebaba717 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
@@ -1,10 +1,12 @@
<script>
import _ from 'underscore';
+import { GlLoadingIcon } from '@gitlab/ui';
import StageColumnComponent from './stage_column_component.vue';
export default {
components: {
StageColumnComponent,
+ GlLoadingIcon,
},
props: {
isLoading: {
@@ -16,23 +18,19 @@ export default {
required: true,
},
},
-
computed: {
graph() {
return this.pipeline.details && this.pipeline.details.stages;
},
},
-
methods: {
capitalizeStageName(name) {
const escapedName = _.escape(name);
return escapedName.charAt(0).toUpperCase() + escapedName.slice(1);
},
-
isFirstColumn(index) {
return index === 0;
},
-
stageConnectorClass(index, stage) {
let className;
@@ -46,7 +44,6 @@ export default {
return className;
},
-
refreshPipelineGraph() {
this.$emit('refreshPipelineGraph');
},
@@ -56,21 +53,14 @@ export default {
<template>
<div class="build-content middle-block js-pipeline-graph">
<div class="pipeline-visualization pipeline-graph pipeline-tab-content">
- <div class="text-center">
- <gl-loading-icon
- v-if="isLoading"
- :size="3"
- />
- </div>
+ <div class="text-center"><gl-loading-icon v-if="isLoading" :size="3" /></div>
- <ul
- v-if="!isLoading"
- class="stage-column-list">
+ <ul v-if="!isLoading" class="stage-column-list">
<stage-column-component
v-for="(stage, index) in graph"
- :title="capitalizeStageName(stage.name)"
- :jobs="stage.groups"
:key="stage.name"
+ :title="capitalizeStageName(stage.name)"
+ :groups="stage.groups"
:stage-connector-class="stageConnectorClass(index, stage)"
:is-first-column="isFirstColumn(index)"
@refreshPipelineGraph="refreshPipelineGraph"
diff --git a/app/assets/javascripts/pipelines/components/graph/job_component.vue b/app/assets/javascripts/pipelines/components/graph/job_component.vue
deleted file mode 100644
index 9ac16b7e541..00000000000
--- a/app/assets/javascripts/pipelines/components/graph/job_component.vue
+++ /dev/null
@@ -1,140 +0,0 @@
-<script>
-import ActionComponent from './action_component.vue';
-import JobNameComponent from './job_name_component.vue';
-import tooltip from '../../../vue_shared/directives/tooltip';
-
-/**
- * Renders the badge for the pipeline graph and the job's dropdown.
- *
- * The following object should be provided as `job`:
- *
- * {
- * "id": 4256,
- * "name": "test",
- * "status": {
- * "icon": "status_success",
- * "text": "passed",
- * "label": "passed",
- * "group": "success",
- * "tooltip": "passed",
- * "details_path": "/root/ci-mock/builds/4256",
- * "action": {
- * "icon": "retry",
- * "title": "Retry",
- * "path": "/root/ci-mock/builds/4256/retry",
- * "method": "post"
- * }
- * }
- * }
- */
-
-export default {
- components: {
- ActionComponent,
- JobNameComponent,
- },
- directives: {
- tooltip,
- },
- props: {
- job: {
- type: Object,
- required: true,
- },
- cssClassJobName: {
- type: String,
- required: false,
- default: '',
- },
- dropdownLength: {
- type: Number,
- required: false,
- default: Infinity,
- },
- },
- computed: {
- status() {
- return this.job && this.job.status ? this.job.status : {};
- },
-
- tooltipText() {
- const textBuilder = [];
-
- if (this.job.name) {
- textBuilder.push(this.job.name);
- }
-
- if (this.job.name && this.status.tooltip) {
- textBuilder.push('-');
- }
-
- if (this.status.tooltip) {
- textBuilder.push(this.job.status.tooltip);
- }
-
- return textBuilder.join(' ');
- },
-
- tooltipBoundary() {
- return this.dropdownLength < 5 ? 'viewport' : null;
- },
-
- /**
- * Verifies if the provided job has an action path
- *
- * @return {Boolean}
- */
- hasAction() {
- return this.job.status && this.job.status.action && this.job.status.action.path;
- },
- },
- methods: {
- pipelineActionRequestComplete() {
- this.$emit('pipelineActionRequestComplete');
- },
- },
-};
-</script>
-<template>
- <div class="ci-job-component">
- <a
- v-tooltip
- v-if="status.has_details"
- :href="status.details_path"
- :title="tooltipText"
- :class="cssClassJobName"
- :data-boundary="tooltipBoundary"
- data-container="body"
- class="js-pipeline-graph-job-link"
- >
-
- <job-name-component
- :name="job.name"
- :status="job.status"
- />
- </a>
-
- <div
- v-tooltip
- v-else
- :title="tooltipText"
- :class="cssClassJobName"
- class="js-job-component-tooltip non-details-job-component"
- data-container="body"
- >
-
- <job-name-component
- :name="job.name"
- :status="job.status"
- />
- </div>
-
- <action-component
- v-if="hasAction"
- :tooltip-text="status.action.title"
- :link="status.action.path"
- :action-icon="status.action.icon"
- @pipelineActionRequestComplete="pipelineActionRequestComplete"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
new file mode 100644
index 00000000000..482898b80c4
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
@@ -0,0 +1,92 @@
+<script>
+import $ from 'jquery';
+import { GlTooltipDirective } from '@gitlab/ui';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import JobItem from './job_item.vue';
+
+/**
+ * Renders the dropdown for the pipeline graph.
+ *
+ * The object provided as `group` corresponds to app/serializers/job_group_entity.rb.
+ *
+ */
+export default {
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ components: {
+ JobItem,
+ CiIcon,
+ },
+ props: {
+ group: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ tooltipText() {
+ const { name, status } = this.group;
+ return `${name} - ${status.label}`;
+ },
+ },
+ mounted() {
+ this.stopDropdownClickPropagation();
+ },
+ methods: {
+ /**
+ * When the user right clicks or cmd/ctrl + click in the group name or the action icon
+ * the dropdown should not be closed so we stop propagation
+ * of the click event inside the dropdown.
+ *
+ * Since this component is rendered multiple times per page we need to guarantee we only
+ * target the click event of this component.
+ */
+ stopDropdownClickPropagation() {
+ $(
+ '.js-grouped-pipeline-dropdown button, .js-grouped-pipeline-dropdown a.mini-pipeline-graph-dropdown-item',
+ this.$el,
+ ).on('click', e => {
+ e.stopPropagation();
+ });
+ },
+
+ pipelineActionRequestComplete() {
+ this.$emit('pipelineActionRequestComplete');
+ },
+ },
+};
+</script>
+<template>
+ <div class="ci-job-dropdown-container dropdown dropright">
+ <button
+ v-gl-tooltip.hover="{ boundary: 'viewport' }"
+ :title="tooltipText"
+ type="button"
+ data-toggle="dropdown"
+ data-display="static"
+ class="dropdown-menu-toggle build-content"
+ >
+ <ci-icon :status="group.status" />
+
+ <span class="ci-status-text"> {{ group.name }} </span>
+
+ <span class="dropdown-counter-badge"> {{ group.size }} </span>
+ </button>
+
+ <ul class="dropdown-menu big-pipeline-graph-dropdown-menu js-grouped-pipeline-dropdown">
+ <li class="scrollable-menu">
+ <ul>
+ <li v-for="job in group.jobs" :key="job.id">
+ <job-item
+ :dropdown-length="group.size"
+ :job="job"
+ css-class-job-name="mini-pipeline-graph-dropdown-item"
+ @pipelineActionRequestComplete="pipelineActionRequestComplete"
+ />
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/graph/job_item.vue b/app/assets/javascripts/pipelines/components/graph/job_item.vue
new file mode 100644
index 00000000000..cf9db89e32b
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/graph/job_item.vue
@@ -0,0 +1,134 @@
+<script>
+import ActionComponent from './action_component.vue';
+import JobNameComponent from './job_name_component.vue';
+import { GlTooltipDirective, GlLink } from '@gitlab/ui';
+import { sprintf } from '~/locale';
+import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
+
+/**
+ * Renders the badge for the pipeline graph and the job's dropdown.
+ *
+ * The following object should be provided as `job`:
+ *
+ * {
+ * "id": 4256,
+ * "name": "test",
+ * "status": {
+ * "icon": "status_success",
+ * "text": "passed",
+ * "label": "passed",
+ * "group": "success",
+ * "tooltip": "passed",
+ * "details_path": "/root/ci-mock/builds/4256",
+ * "action": {
+ * "icon": "retry",
+ * "title": "Retry",
+ * "path": "/root/ci-mock/builds/4256/retry",
+ * "method": "post"
+ * }
+ * }
+ * }
+ */
+
+export default {
+ components: {
+ ActionComponent,
+ JobNameComponent,
+ GlLink,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ mixins: [delayedJobMixin],
+ props: {
+ job: {
+ type: Object,
+ required: true,
+ },
+ cssClassJobName: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ dropdownLength: {
+ type: Number,
+ required: false,
+ default: Infinity,
+ },
+ },
+ computed: {
+ status() {
+ return this.job && this.job.status ? this.job.status : {};
+ },
+
+ tooltipText() {
+ const textBuilder = [];
+ const { name: jobName } = this.job;
+
+ if (jobName) {
+ textBuilder.push(jobName);
+ }
+
+ const { tooltip: statusTooltip } = this.status;
+ if (jobName && statusTooltip) {
+ textBuilder.push('-');
+ }
+
+ if (statusTooltip) {
+ if (this.isDelayedJob) {
+ textBuilder.push(sprintf(statusTooltip, { remainingTime: this.remainingTime }));
+ } else {
+ textBuilder.push(statusTooltip);
+ }
+ }
+
+ return textBuilder.join(' ');
+ },
+ /**
+ * Verifies if the provided job has an action path
+ *
+ * @return {Boolean}
+ */
+ hasAction() {
+ return this.job.status && this.job.status.action && this.job.status.action.path;
+ },
+ },
+ methods: {
+ pipelineActionRequestComplete() {
+ this.$emit('pipelineActionRequestComplete');
+ },
+ },
+};
+</script>
+<template>
+ <div class="ci-job-component">
+ <gl-link
+ v-if="status.has_details"
+ v-gl-tooltip
+ :href="status.details_path"
+ :title="tooltipText"
+ :class="cssClassJobName"
+ class="js-pipeline-graph-job-link"
+ >
+ <job-name-component :name="job.name" :status="job.status" />
+ </gl-link>
+
+ <div
+ v-else
+ v-gl-tooltip
+ :title="tooltipText"
+ :class="cssClassJobName"
+ class="js-job-component-tooltip non-details-job-component"
+ >
+ <job-name-component :name="job.name" :status="job.status" />
+ </div>
+
+ <action-component
+ v-if="hasAction"
+ :tooltip-text="status.action.title"
+ :link="status.action.path"
+ :action-icon="status.action.icon"
+ @pipelineActionRequestComplete="pipelineActionRequestComplete"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/graph/job_name_component.vue b/app/assets/javascripts/pipelines/components/graph/job_name_component.vue
index 6fdbcc1e049..1bfab2a7fc0 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_name_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_name_component.vue
@@ -28,8 +28,6 @@ export default {
<span class="ci-job-name-component">
<ci-icon :status="status" />
- <span class="ci-status-text">
- {{ name }}
- </span>
+ <span class="ci-status-text"> {{ name }} </span>
</span>
</template>
diff --git a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
index e7b2de52f76..09a50d25020 100644
--- a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
@@ -1,50 +1,40 @@
<script>
import _ from 'underscore';
-import JobComponent from './job_component.vue';
-import DropdownJobComponent from './dropdown_job_component.vue';
+import JobItem from './job_item.vue';
+import JobGroupDropdown from './job_group_dropdown.vue';
export default {
components: {
- JobComponent,
- DropdownJobComponent,
+ JobItem,
+ JobGroupDropdown,
},
props: {
title: {
type: String,
required: true,
},
-
- jobs: {
+ groups: {
type: Array,
required: true,
},
-
isFirstColumn: {
type: Boolean,
required: false,
default: false,
},
-
stageConnectorClass: {
type: String,
required: false,
default: '',
},
},
-
methods: {
- firstJob(list) {
- return list[0];
- },
-
- jobId(job) {
- return `ci-badge-${_.escape(job.name)}`;
+ groupId(group) {
+ return `ci-badge-${_.escape(group.name)}`;
},
-
buildConnnectorClass(index) {
return index === 0 && !this.isFirstColumn ? 'left-connector' : '';
},
-
pipelineActionRequestComplete() {
this.$emit('refreshPipelineGraph');
},
@@ -52,37 +42,31 @@ export default {
};
</script>
<template>
- <li
- :class="stageConnectorClass"
- class="stage-column">
- <div class="stage-name">
- {{ title }}
- </div>
+ <li :class="stageConnectorClass" class="stage-column">
+ <div class="stage-name">{{ title }}</div>
<div class="builds-container">
<ul>
<li
- v-for="(job, index) in jobs"
- :key="job.id"
+ v-for="(group, index) in groups"
+ :id="groupId(group)"
+ :key="group.id"
:class="buildConnnectorClass(index)"
- :id="jobId(job)"
class="build"
>
-
<div class="curve"></div>
- <job-component
- v-if="job.size === 1"
- :job="job"
+ <job-item
+ v-if="group.size === 1"
+ :job="group.jobs[0]"
css-class-job-name="build-content"
@pipelineActionRequestComplete="pipelineActionRequestComplete"
/>
- <dropdown-job-component
- v-if="job.size > 1"
- :job="job"
+ <job-group-dropdown
+ v-if="group.size > 1"
+ :group="group"
@pipelineActionRequestComplete="pipelineActionRequestComplete"
/>
-
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/pipelines/components/header_component.vue b/app/assets/javascripts/pipelines/components/header_component.vue
index 1f9187c3d65..b2e365e5cde 100644
--- a/app/assets/javascripts/pipelines/components/header_component.vue
+++ b/app/assets/javascripts/pipelines/components/header_component.vue
@@ -1,4 +1,5 @@
<script>
+import { GlLoadingIcon } from '@gitlab/ui';
import ciHeader from '../../vue_shared/components/header_ci_component.vue';
import eventHub from '../event_hub';
@@ -6,6 +7,7 @@ export default {
name: 'PipelineHeaderSection',
components: {
ciHeader,
+ GlLoadingIcon,
},
props: {
pipeline: {
@@ -87,10 +89,6 @@ export default {
item-name="Pipeline"
@actionClicked="postAction"
/>
- <gl-loading-icon
- v-if="isLoading"
- :size="2"
- class="prepend-top-default append-bottom-default"
- />
+ <gl-loading-icon v-if="isLoading" :size="2" class="prepend-top-default append-bottom-default" />
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/nav_controls.vue b/app/assets/javascripts/pipelines/components/nav_controls.vue
index efb80d3a3c0..c6990683ec7 100644
--- a/app/assets/javascripts/pipelines/components/nav_controls.vue
+++ b/app/assets/javascripts/pipelines/components/nav_controls.vue
@@ -1,10 +1,13 @@
<script>
+import { GlLink, GlButton } from '@gitlab/ui';
import LoadingButton from '../../vue_shared/components/loading_button.vue';
export default {
name: 'PipelineNavControls',
components: {
LoadingButton,
+ GlLink,
+ GlButton,
},
props: {
newPipelinePath: {
@@ -40,28 +43,25 @@ export default {
</script>
<template>
<div class="nav-controls">
- <a
+ <gl-button
v-if="newPipelinePath"
:href="newPipelinePath"
- class="btn btn-success js-run-pipeline"
+ variant="success"
+ class="js-run-pipeline"
>
{{ s__('Pipelines|Run Pipeline') }}
- </a>
+ </gl-button>
<loading-button
v-if="resetCachePath"
:loading="isResetCacheButtonLoading"
:label="s__('Pipelines|Clear Runner Caches')"
- class="btn btn-default js-clear-cache"
+ class="js-clear-cache"
@click="onClickResetCache"
/>
- <a
- v-if="ciLintPath"
- :href="ciLintPath"
- class="btn btn-default js-ci-lint"
- >
+ <gl-button v-if="ciLintPath" :href="ciLintPath" class="js-ci-lint">
{{ s__('Pipelines|CI Lint') }}
- </a>
+ </gl-button>
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_url.vue b/app/assets/javascripts/pipelines/components/pipeline_url.vue
index 75db1e9ae7c..e5924d3a77e 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_url.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_url.vue
@@ -1,14 +1,15 @@
<script>
-import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
-import tooltip from '../../vue_shared/directives/tooltip';
-import popover from '../../vue_shared/directives/popover';
+import { GlLink, GlTooltipDirective } from '@gitlab/ui';
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+import popover from '~/vue_shared/directives/popover';
export default {
components: {
- userAvatarLink,
+ UserAvatarLink,
+ GlLink,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
popover,
},
props: {
@@ -47,11 +48,9 @@ export default {
</script>
<template>
<div class="table-section section-15 d-none d-sm-none d-md-block pipeline-tags">
- <a
- :href="pipeline.path"
- class="js-pipeline-url-link">
+ <gl-link :href="pipeline.path" class="js-pipeline-url-link">
<span class="pipeline-id">#{{ pipeline.id }}</span>
- </a>
+ </gl-link>
<span>by</span>
<user-avatar-link
v-if="user"
@@ -60,44 +59,42 @@ export default {
:tooltip-text="pipeline.user.name"
class="js-pipeline-url-user"
/>
- <span
- v-if="!user"
- class="js-pipeline-url-api api">
- API
- </span>
+ <span v-if="!user" class="js-pipeline-url-api api"> API </span>
<div class="label-container">
<span
- v-tooltip
v-if="pipeline.flags.latest"
+ v-gl-tooltip
class="js-pipeline-url-latest badge badge-success"
- title="Latest pipeline for this branch">
+ title="Latest pipeline for this branch"
+ >
latest
</span>
<span
- v-tooltip
v-if="pipeline.flags.yaml_errors"
+ v-gl-tooltip
:title="pipeline.yaml_errors"
- class="js-pipeline-url-yaml badge badge-danger">
+ class="js-pipeline-url-yaml badge badge-danger"
+ >
yaml invalid
</span>
<span
- v-tooltip
v-if="pipeline.flags.failure_reason"
+ v-gl-tooltip
:title="pipeline.failure_reason"
- class="js-pipeline-url-failure badge badge-danger">
+ class="js-pipeline-url-failure badge badge-danger"
+ >
error
</span>
- <a
- v-popover="popoverOptions"
+ <gl-link
v-if="pipeline.flags.auto_devops"
+ v-popover="popoverOptions"
tabindex="0"
class="js-pipeline-url-autodevops badge badge-info autodevops-badge"
- role="button">
+ role="button"
+ >
Auto DevOps
- </a>
- <span
- v-if="pipeline.flags.stuck"
- class="js-pipeline-url-stuck badge badge-warning">
+ </gl-link>
+ <span v-if="pipeline.flags.stuck" class="js-pipeline-url-stuck badge badge-warning">
stuck
</span>
</div>
diff --git a/app/assets/javascripts/pipelines/components/pipelines.vue b/app/assets/javascripts/pipelines/components/pipelines.vue
index ea526cf1309..9dcea557b32 100644
--- a/app/assets/javascripts/pipelines/components/pipelines.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines.vue
@@ -155,14 +155,6 @@ export default {
);
},
- shouldRenderPagination() {
- return (
- !this.isLoading &&
- this.state.pipelines.length &&
- this.state.pageInfo.total > this.state.pageInfo.perPage
- );
- },
-
emptyTabMessage() {
const { scopes } = this.$options;
const possibleScopes = [scopes.pending, scopes.running, scopes.finished];
@@ -232,36 +224,6 @@ export default {
this.setCommonData(resp.data.pipelines);
}
},
- /**
- * Handles URL and query parameter changes.
- * When the user uses the pagination or the tabs,
- * - update URL
- * - Make API request to the server with new parameters
- * - Update the polling function
- * - Update the internal state
- */
- updateContent(parameters) {
- this.updateInternalState(parameters);
-
- // fetch new data
- return this.service
- .getPipelines(this.requestData)
- .then(response => {
- this.isLoading = false;
- this.successCallback(response);
-
- // restart polling
- this.poll.restart({ data: this.requestData });
- })
- .catch(() => {
- this.isLoading = false;
- this.errorCallback();
-
- // restart polling
- this.poll.restart({ data: this.requestData });
- });
- },
-
handleResetRunnersCache(endpoint) {
this.isResetCacheButtonLoading = true;
@@ -285,20 +247,8 @@ export default {
v-if="shouldRenderTabs || shouldRenderButtons"
class="top-area scrolling-tabs-container inner-page-scroll-tabs"
>
- <div class="fade-left">
- <i
- class="fa fa-angle-left"
- aria-hidden="true"
- >
- </i>
- </div>
- <div class="fade-right">
- <i
- class="fa fa-angle-right"
- aria-hidden="true"
- >
- </i>
- </div>
+ <div class="fade-left"><i class="fa fa-angle-left" aria-hidden="true"> </i></div>
+ <div class="fade-right"><i class="fa fa-angle-right" aria-hidden="true"> </i></div>
<navigation-tabs
v-if="shouldRenderTabs"
@@ -318,7 +268,6 @@ export default {
</div>
<div class="content-list pipelines">
-
<gl-loading-icon
v-if="stateToRender === $options.stateMap.loading"
:label="s__('Pipelines|Loading Pipelines')"
@@ -336,8 +285,10 @@ export default {
<svg-blank-state
v-else-if="stateToRender === $options.stateMap.error"
:svg-path="errorStateSvgPath"
- :message="s__(`Pipelines|There was an error fetching the pipelines.
- Try again in a few moments or contact your support team.`)"
+ :message="
+ s__(`Pipelines|There was an error fetching the pipelines.
+ Try again in a few moments or contact your support team.`)
+ "
/>
<svg-blank-state
@@ -346,11 +297,7 @@ export default {
:message="emptyTabMessage"
/>
- <div
- v-else-if="stateToRender === $options.stateMap.tableList"
- class="table-holder"
- >
-
+ <div v-else-if="stateToRender === $options.stateMap.tableList" class="table-holder">
<pipelines-table-component
:pipelines="state.pipelines"
:update-graph-dropdown="updateGraphDropdown"
diff --git a/app/assets/javascripts/pipelines/components/pipelines_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_actions.vue
index 017dd560621..2e9f2519fcb 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_actions.vue
@@ -1,14 +1,19 @@
<script>
+import { GlButton, GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui';
+import { s__, sprintf } from '~/locale';
+import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
import eventHub from '../event_hub';
-import icon from '../../vue_shared/components/icon.vue';
-import tooltip from '../../vue_shared/directives/tooltip';
+import Icon from '../../vue_shared/components/icon.vue';
export default {
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
components: {
- icon,
+ Icon,
+ GlCountdown,
+ GlButton,
+ GlLoadingIcon,
},
props: {
actions: {
@@ -22,10 +27,24 @@ export default {
};
},
methods: {
- onClickAction(endpoint) {
+ onClickAction(action) {
+ if (action.scheduled_at) {
+ const confirmationMessage = sprintf(
+ s__(
+ "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes.",
+ ),
+ { jobName: action.name },
+ );
+ // https://gitlab.com/gitlab-org/gitlab-ce/issues/52156
+ // eslint-disable-next-line no-alert
+ if (!window.confirm(confirmationMessage)) {
+ return;
+ }
+ }
+
this.isLoading = true;
- eventHub.$emit('postAction', endpoint);
+ eventHub.$emit('postAction', action.path);
},
isActionDisabled(action) {
@@ -40,41 +59,32 @@ export default {
</script>
<template>
<div class="btn-group">
- <button
- v-tooltip
+ <gl-button
+ v-gl-tooltip
:disabled="isLoading"
- type="button"
class="dropdown-new btn btn-default js-pipeline-dropdown-manual-actions"
title="Manual job"
data-toggle="dropdown"
- data-placement="top"
aria-label="Manual job"
>
- <icon
- name="play"
- class="icon-play"
- />
- <i
- class="fa fa-caret-down"
- aria-hidden="true">
- </i>
+ <icon name="play" class="icon-play" /> <i class="fa fa-caret-down" aria-hidden="true"> </i>
<gl-loading-icon v-if="isLoading" />
- </button>
+ </gl-button>
<ul class="dropdown-menu dropdown-menu-right">
- <li
- v-for="(action, i) in actions"
- :key="i"
- >
- <button
+ <li v-for="action in actions" :key="action.path">
+ <gl-button
:class="{ disabled: isActionDisabled(action) }"
:disabled="isActionDisabled(action)"
- type="button"
class="js-pipeline-action-link no-btn btn"
- @click="onClickAction(action.path)"
+ @click="onClickAction(action);"
>
{{ action.name }}
- </button>
+ <span v-if="action.scheduled_at" class="pull-right">
+ <icon name="clock" />
+ <gl-countdown :end-date-string="action.scheduled_at" />
+ </span>
+ </gl-button>
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue b/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue
index d40de95e051..908b10afee6 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue
@@ -1,13 +1,15 @@
<script>
-import tooltip from '../../vue_shared/directives/tooltip';
-import icon from '../../vue_shared/components/icon.vue';
+import { GlLink, GlButton, GlTooltipDirective } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
export default {
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
components: {
- icon,
+ Icon,
+ GlLink,
+ GlButton,
},
props: {
artifacts: {
@@ -18,36 +20,21 @@ export default {
};
</script>
<template>
- <div
- class="btn-group"
- role="group"
- >
- <button
- v-tooltip
- class="dropdown-toggle btn btn-default build-artifacts js-pipeline-dropdown-download"
+ <div class="btn-group" role="group">
+ <gl-button
+ v-gl-tooltip
+ class="dropdown-toggle build-artifacts js-pipeline-dropdown-download"
title="Artifacts"
- data-placement="top"
data-toggle="dropdown"
aria-label="Artifacts"
>
- <icon name="download" />
- <i
- class="fa fa-caret-down"
- aria-hidden="true"
- >
- </i>
- </button>
+ <icon name="download" /> <i class="fa fa-caret-down" aria-hidden="true"> </i>
+ </gl-button>
<ul class="dropdown-menu dropdown-menu-right">
- <li
- v-for="(artifact, i) in artifacts"
- :key="i">
- <a
- :href="artifact.path"
- rel="nofollow"
- download
- >
+ <li v-for="(artifact, i) in artifacts" :key="i">
+ <gl-link :href="artifact.path" rel="nofollow" download>
Download {{ artifact.name }} artifacts
- </a>
+ </gl-link>
</li>
</ul>
</div>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_table.vue b/app/assets/javascripts/pipelines/components/pipelines_table.vue
index 0d7324f3fb5..1c60ae6a152 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_table.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_table.vue
@@ -35,7 +35,7 @@ export default {
},
data() {
return {
- pipelineId: '',
+ pipelineId: 0,
endpoint: '',
cancelingPipeline: null,
};
@@ -80,33 +80,18 @@ export default {
</script>
<template>
<div class="ci-table">
- <div
- class="gl-responsive-table-row table-row-header"
- role="row"
- >
- <div
- class="table-section section-10 js-pipeline-status pipeline-status"
- role="rowheader"
- >
- Status
+ <div class="gl-responsive-table-row table-row-header" role="row">
+ <div class="table-section section-10 js-pipeline-status pipeline-status" role="rowheader">
+ {{ s__('Pipeline|Status') }}
</div>
- <div
- class="table-section section-15 js-pipeline-info pipeline-info"
- role="rowheader"
- >
- Pipeline
+ <div class="table-section section-15 js-pipeline-info pipeline-info" role="rowheader">
+ {{ s__('Pipeline|Pipeline') }}
</div>
- <div
- class="table-section section-20 js-pipeline-commit pipeline-commit"
- role="rowheader"
- >
- Commit
+ <div class="table-section section-20 js-pipeline-commit pipeline-commit" role="rowheader">
+ {{ s__('Pipeline|Commit') }}
</div>
- <div
- class="table-section section-20 js-pipeline-stages pipeline-stages"
- role="rowheader"
- >
- Stages
+ <div class="table-section section-20 js-pipeline-stages pipeline-stages" role="rowheader">
+ {{ s__('Pipeline|Stages') }}
</div>
</div>
<pipelines-table-row-component
@@ -128,6 +113,5 @@ export default {
>
<span v-html="modalText"></span>
</modal>
-
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_table_row.vue b/app/assets/javascripts/pipelines/components/pipelines_table_row.vue
index a39cc265601..da42698c255 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_table_row.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_table_row.vue
@@ -47,7 +47,7 @@ export default {
required: true,
},
cancelingPipeline: {
- type: String,
+ type: Number,
required: false,
default: null,
},
@@ -59,6 +59,13 @@ export default {
};
},
computed: {
+ actions() {
+ if (!this.pipeline || !this.pipeline.details) {
+ return [];
+ }
+ const { details } = this.pipeline;
+ return [...(details.manual_actions || []), ...(details.scheduled_actions || [])];
+ },
/**
* If provided, returns the commit tag.
* Needed to render the commit component column.
@@ -250,31 +257,16 @@ export default {
<template>
<div class="commit gl-responsive-table-row">
<div class="table-section section-10 commit-link">
- <div
- class="table-mobile-header"
- role="rowheader"
- >
- Status
- </div>
+ <div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Status') }}</div>
<div class="table-mobile-content">
- <ci-badge
- :status="pipelineStatus"
- :show-text="!isChildView"
- />
+ <ci-badge :status="pipelineStatus" :show-text="!isChildView" />
</div>
</div>
- <pipeline-url
- :pipeline="pipeline"
- :auto-devops-help-path="autoDevopsHelpPath"
- />
+ <pipeline-url :pipeline="pipeline" :auto-devops-help-path="autoDevopsHelpPath" />
<div class="table-section section-20">
- <div
- class="table-mobile-header"
- role="rowheader">
- Commit
- </div>
+ <div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Commit') }}</div>
<div class="table-mobile-content">
<commit-component
:tag="commitTag"
@@ -289,17 +281,14 @@ export default {
</div>
<div class="table-section section-wrap section-20 stage-cell">
- <div
- class="table-mobile-header"
- role="rowheader">
- Stages
- </div>
+ <div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Stages') }}</div>
<div class="table-mobile-content">
<template v-if="pipeline.details.stages.length > 0">
<div
v-for="(stage, index) in pipeline.details.stages"
:key="index"
- class="stage-container dropdown js-mini-pipeline-graph">
+ class="stage-container dropdown js-mini-pipeline-graph"
+ >
<pipeline-stage
:type="$options.pipelinesTable"
:stage="stage"
@@ -310,20 +299,14 @@ export default {
</div>
</div>
- <pipelines-timeago
- :duration="pipelineDuration"
- :finished-time="pipelineFinishedAt"
- />
+ <pipelines-timeago :duration="pipelineDuration" :finished-time="pipelineFinishedAt" />
<div
v-if="displayPipelineActions"
class="table-section section-20 table-button-footer pipeline-actions"
>
<div class="btn-group table-action-buttons">
- <pipelines-actions-component
- v-if="pipeline.details.manual_actions.length"
- :actions="pipeline.details.manual_actions"
- />
+ <pipelines-actions-component v-if="actions.length > 0" :actions="actions" />
<pipelines-artifacts-component
v-if="pipeline.details.artifacts.length"
diff --git a/app/assets/javascripts/pipelines/components/stage.vue b/app/assets/javascripts/pipelines/components/stage.vue
index 3e13bad9a0b..2d3f667e73e 100644
--- a/app/assets/javascripts/pipelines/components/stage.vue
+++ b/app/assets/javascripts/pipelines/components/stage.vue
@@ -13,23 +13,24 @@
*/
import $ from 'jquery';
+import { GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
import { __ } from '../../locale';
import Flash from '../../flash';
import axios from '../../lib/utils/axios_utils';
import eventHub from '../event_hub';
import Icon from '../../vue_shared/components/icon.vue';
-import JobComponent from './graph/job_component.vue';
-import tooltip from '../../vue_shared/directives/tooltip';
+import JobItem from './graph/job_item.vue';
import { PIPELINES_TABLE } from '../constants';
export default {
components: {
Icon,
- JobComponent,
+ JobItem,
+ GlLoadingIcon,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
@@ -155,13 +156,12 @@ export default {
<template>
<div class="dropdown">
<button
- v-tooltip
id="stageDropdown"
ref="dropdown"
+ v-gl-tooltip.hover
:class="triggerButtonClass"
:title="stage.title"
class="mini-pipeline-graph-dropdown-toggle js-builds-dropdown-button"
- data-placement="top"
data-toggle="dropdown"
data-display="static"
type="button"
@@ -169,36 +169,21 @@ export default {
aria-expanded="false"
@click="onClickStage"
>
-
- <span
- :aria-label="stage.title"
- aria-hidden="true"
- class="no-pointer-events"
- >
+ <span :aria-label="stage.title" aria-hidden="true" class="no-pointer-events">
<icon :name="borderlessIcon" />
</span>
- <i
- class="fa fa-caret-down"
- aria-hidden="true"
- >
- </i>
+ <i class="fa fa-caret-down" aria-hidden="true"> </i>
</button>
<div
class="dropdown-menu mini-pipeline-graph-dropdown-menu js-builds-dropdown-container"
aria-labelledby="stageDropdown"
>
- <gl-loading-icon v-if="isLoading"/>
- <ul
- v-else
- class="js-builds-dropdown-list scrollable-menu"
- >
- <li
- v-for="job in dropdownContent"
- :key="job.id"
- >
- <job-component
+ <gl-loading-icon v-if="isLoading" />
+ <ul v-else class="js-builds-dropdown-list scrollable-menu">
+ <li v-for="job in dropdownContent" :key="job.id">
+ <job-item
:dropdown-length="dropdownContent.length"
:job="job"
css-class-job-name="mini-pipeline-graph-dropdown-item"
diff --git a/app/assets/javascripts/pipelines/components/time_ago.vue b/app/assets/javascripts/pipelines/components/time_ago.vue
index cd43d78de40..2ed0c24825c 100644
--- a/app/assets/javascripts/pipelines/components/time_ago.vue
+++ b/app/assets/javascripts/pipelines/components/time_ago.vue
@@ -56,38 +56,21 @@ export default {
</script>
<template>
<div class="table-section section-15 pipelines-time-ago">
- <div
- class="table-mobile-header"
- role="rowheader"
- >
- Duration
- </div>
+ <div class="table-mobile-header" role="rowheader">{{ s__('Pipeline|Duration') }}</div>
<div class="table-mobile-content">
- <p
- v-if="hasDuration"
- class="duration"
- >
- <span v-html="iconTimerSvg">
- </span>
- {{ durationFormated }}
+ <p v-if="hasDuration" class="duration">
+ <span v-html="iconTimerSvg"> </span> {{ durationFormated }}
</p>
- <p
- v-if="hasFinishedTime"
- class="finished-at d-none d-sm-none d-md-block"
- >
-
- <i
- class="fa fa-calendar"
- aria-hidden="true"
- >
- </i>
+ <p v-if="hasFinishedTime" class="finished-at d-none d-sm-none d-md-block">
+ <i class="fa fa-calendar" aria-hidden="true"> </i>
<time
v-tooltip
:title="tooltipTitle(finishedTime)"
data-placement="top"
- data-container="body">
+ data-container="body"
+ >
{{ timeFormated(finishedTime) }}
</time>
</p>
diff --git a/app/assets/javascripts/pipelines/mixins/pipelines.js b/app/assets/javascripts/pipelines/mixins/pipelines.js
index 8929b397f6c..32bfa47e5f2 100644
--- a/app/assets/javascripts/pipelines/mixins/pipelines.js
+++ b/app/assets/javascripts/pipelines/mixins/pipelines.js
@@ -1,4 +1,5 @@
import Visibility from 'visibilityjs';
+import { GlLoadingIcon } from '@gitlab/ui';
import { __ } from '../../locale';
import Flash from '../../flash';
import Poll from '../../lib/utils/poll';
@@ -13,6 +14,7 @@ export default {
PipelinesTableComponent,
SvgBlankState,
EmptyState,
+ GlLoadingIcon,
},
data() {
return {
@@ -23,6 +25,15 @@ export default {
hasMadeRequest: false,
};
},
+ computed: {
+ shouldRenderPagination() {
+ return (
+ !this.isLoading &&
+ this.state.pipelines.length &&
+ this.state.pageInfo.total > this.state.pageInfo.perPage
+ );
+ },
+ },
beforeMount() {
this.poll = new Poll({
resource: this.service,
@@ -65,6 +76,35 @@ export default {
this.poll.stop();
},
methods: {
+ /**
+ * Handles URL and query parameter changes.
+ * When the user uses the pagination or the tabs,
+ * - update URL
+ * - Make API request to the server with new parameters
+ * - Update the polling function
+ * - Update the internal state
+ */
+ updateContent(parameters) {
+ this.updateInternalState(parameters);
+
+ // fetch new data
+ return this.service
+ .getPipelines(this.requestData)
+ .then(response => {
+ this.isLoading = false;
+ this.successCallback(response);
+
+ // restart polling
+ this.poll.restart({ data: this.requestData });
+ })
+ .catch(() => {
+ this.isLoading = false;
+ this.errorCallback();
+
+ // restart polling
+ this.poll.restart({ data: this.requestData });
+ });
+ },
updateTable() {
// Cancel ongoing request
if (this.isMakingRequest) {
diff --git a/app/assets/javascripts/profile/account/components/delete_account_modal.vue b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
index 974629fa2af..85c5c073a74 100644
--- a/app/assets/javascripts/profile/account/components/delete_account_modal.vue
+++ b/app/assets/javascripts/profile/account/components/delete_account_modal.vue
@@ -1,78 +1,78 @@
<script>
- import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
- import { __, s__, sprintf } from '~/locale';
- import csrf from '~/lib/utils/csrf';
+import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
+import { __, s__, sprintf } from '~/locale';
+import csrf from '~/lib/utils/csrf';
- export default {
- components: {
- DeprecatedModal,
+export default {
+ components: {
+ DeprecatedModal,
+ },
+ props: {
+ actionUrl: {
+ type: String,
+ required: true,
},
- props: {
- actionUrl: {
- type: String,
- required: true,
- },
- confirmWithPassword: {
- type: Boolean,
- required: true,
- },
- username: {
- type: String,
- required: true,
- },
+ confirmWithPassword: {
+ type: Boolean,
+ required: true,
},
- data() {
- return {
- enteredPassword: '',
- enteredUsername: '',
- };
+ username: {
+ type: String,
+ required: true,
},
- computed: {
- csrfToken() {
- return csrf.token;
- },
- inputLabel() {
- let confirmationValue;
- if (this.confirmWithPassword) {
- confirmationValue = __('password');
- } else {
- confirmationValue = __('username');
- }
+ },
+ data() {
+ return {
+ enteredPassword: '',
+ enteredUsername: '',
+ };
+ },
+ computed: {
+ csrfToken() {
+ return csrf.token;
+ },
+ inputLabel() {
+ let confirmationValue;
+ if (this.confirmWithPassword) {
+ confirmationValue = __('password');
+ } else {
+ confirmationValue = __('username');
+ }
- confirmationValue = `<code>${confirmationValue}</code>`;
+ confirmationValue = `<code>${confirmationValue}</code>`;
- return sprintf(
- s__('Profiles|Type your %{confirmationValue} to confirm:'),
- { confirmationValue },
- false,
- );
- },
- text() {
- return sprintf(
- s__(`Profiles|
+ return sprintf(
+ s__('Profiles|Type your %{confirmationValue} to confirm:'),
+ { confirmationValue },
+ false,
+ );
+ },
+ text() {
+ return sprintf(
+ s__(`Profiles|
You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account.
Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
- {
- yourAccount: `<strong>${s__('Profiles|your account')}</strong>`,
- deleteAccount: `<strong>${s__('Profiles|Delete Account')}</strong>`,
- },
- false,
- );
- },
+ {
+ yourAccount: `<strong>${s__('Profiles|your account')}</strong>`,
+ deleteAccount: `<strong>${s__('Profiles|Delete Account')}</strong>`,
+ },
+ false,
+ );
},
- methods: {
- canSubmit() {
- if (this.confirmWithPassword) {
- return this.enteredPassword !== '';
- }
+ },
+ methods: {
+ canSubmit() {
+ if (this.confirmWithPassword) {
+ return this.enteredPassword !== '';
+ }
- return this.enteredUsername === this.username;
- },
- onSubmit() {
- this.$refs.form.submit();
- },
+ return this.enteredUsername === this.username;
+ },
+ onSubmit() {
+ this.$refs.form.submit();
},
- };
+ },
+};
</script>
<template>
@@ -83,34 +83,16 @@ Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
:primary-button-label="s__('Profiles|Delete account')"
:submit-disabled="!canSubmit()"
kind="danger"
- @submit="onSubmit">
-
- <template
- slot="body"
- slot-scope="props">
+ @submit="onSubmit"
+ >
+ <template slot="body" slot-scope="props">
<p v-html="props.text"></p>
- <form
- ref="form"
- :action="actionUrl"
- method="post">
-
- <input
- type="hidden"
- name="_method"
- value="delete"
- />
- <input
- :value="csrfToken"
- type="hidden"
- name="authenticity_token"
- />
+ <form ref="form" :action="actionUrl" method="post">
+ <input type="hidden" name="_method" value="delete" />
+ <input :value="csrfToken" type="hidden" name="authenticity_token" />
- <p
- id="input-label"
- v-html="inputLabel"
- >
- </p>
+ <p id="input-label" v-html="inputLabel"></p>
<input
v-if="confirmWithPassword"
@@ -130,6 +112,5 @@ Once you confirm %{deleteAccount}, it cannot be undone or recovered.`),
/>
</form>
</template>
-
</deprecated-modal>
</template>
diff --git a/app/assets/javascripts/profile/account/components/update_username.vue b/app/assets/javascripts/profile/account/components/update_username.vue
index ef484ddfd61..e1085c0a44d 100644
--- a/app/assets/javascripts/profile/account/components/update_username.vue
+++ b/app/assets/javascripts/profile/account/components/update_username.vue
@@ -87,9 +87,7 @@ Please update your Git repository remotes as soon as possible.`),
<label :for="$options.inputId">{{ s__('Profiles|Path') }}</label>
<div class="input-group">
<div class="input-group-prepend">
- <div class="input-group-text">
- {{ rootUrl }}
- </div>
+ <div class="input-group-text">{{ rootUrl }}</div>
</div>
<input
:id="$options.inputId"
@@ -99,9 +97,7 @@ Please update your Git repository remotes as soon as possible.`),
required="required"
/>
</div>
- <p class="form-text text-muted">
- {{ path }}
- </p>
+ <p class="form-text text-muted">{{ path }}</p>
</div>
<button
:data-target="`#${$options.modalId}`"
diff --git a/app/assets/javascripts/profile/gl_crop.js b/app/assets/javascripts/profile/gl_crop.js
index f641b23e519..befe91c332f 100644
--- a/app/assets/javascripts/profile/gl_crop.js
+++ b/app/assets/javascripts/profile/gl_crop.js
@@ -1,23 +1,38 @@
-/* eslint-disable no-useless-escape, max-len, no-var, no-underscore-dangle, func-names, no-unused-vars, no-return-assign, object-shorthand, one-var, one-var-declaration-per-line, comma-dangle, consistent-return, class-methods-use-this, new-parens */
+/* eslint-disable no-useless-escape, no-var, no-underscore-dangle, func-names, no-unused-vars, no-return-assign, object-shorthand, one-var, consistent-return, class-methods-use-this */
import $ from 'jquery';
import 'cropper';
import _ from 'underscore';
-((global) => {
+(global => {
// Matches everything but the file name
const FILENAMEREGEX = /^.*[\\\/]/;
class GitLabCrop {
- constructor(input, { filename, previewImage, modalCrop, pickImageEl, uploadImageBtn, modalCropImg,
- exportWidth = 200, exportHeight = 200, cropBoxWidth = 200, cropBoxHeight = 200 } = {}) {
+ constructor(
+ input,
+ {
+ filename,
+ previewImage,
+ modalCrop,
+ pickImageEl,
+ uploadImageBtn,
+ modalCropImg,
+ exportWidth = 200,
+ exportHeight = 200,
+ cropBoxWidth = 200,
+ cropBoxHeight = 200,
+ } = {},
+ ) {
this.onUploadImageBtnClick = this.onUploadImageBtnClick.bind(this);
this.onModalHide = this.onModalHide.bind(this);
this.onModalShow = this.onModalShow.bind(this);
this.onPickImageClick = this.onPickImageClick.bind(this);
this.fileInput = $(input);
this.modalCropImg = _.isString(this.modalCropImg) ? $(this.modalCropImg) : this.modalCropImg;
- this.fileInput.attr('name', `${this.fileInput.attr('name')}-trigger`).attr('id', `${this.fileInput.attr('id')}-trigger`);
+ this.fileInput
+ .attr('name', `${this.fileInput.attr('name')}-trigger`)
+ .attr('id', `${this.fileInput.attr('id')}-trigger`);
this.exportWidth = exportWidth;
this.exportHeight = exportHeight;
this.cropBoxWidth = cropBoxWidth;
@@ -59,7 +74,7 @@ import _ from 'underscore';
btn = this;
return _this.onActionBtnClick(btn);
});
- return this.croppedImageBlob = null;
+ return (this.croppedImageBlob = null);
}
onPickImageClick() {
@@ -94,9 +109,9 @@ import _ from 'underscore';
width: cropBoxWidth,
height: cropBoxHeight,
left: (container.width - cropBoxWidth) / 2,
- top: (container.height - cropBoxHeight) / 2
+ top: (container.height - cropBoxHeight) / 2,
});
- }
+ },
});
}
@@ -116,7 +131,7 @@ import _ from 'underscore';
var data, result;
data = $(btn).data();
if (this.modalCropImg.data('cropper') && data.method) {
- return result = this.modalCropImg.cropper(data.method, data.option);
+ return (result = this.modalCropImg.cropper(data.method, data.option));
}
}
@@ -127,7 +142,7 @@ import _ from 'underscore';
readFile(input) {
var _this, reader;
_this = this;
- reader = new FileReader;
+ reader = new FileReader();
reader.onload = () => {
_this.modalCropImg.attr('src', reader.result);
return _this.modalCrop.modal('show');
@@ -145,7 +160,7 @@ import _ from 'underscore';
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], {
- type: 'image/png'
+ type: 'image/png',
});
}
@@ -157,11 +172,13 @@ import _ from 'underscore';
}
setBlob() {
- this.dataURL = this.modalCropImg.cropper('getCroppedCanvas', {
- width: 200,
- height: 200
- }).toDataURL('image/png');
- return this.croppedImageBlob = this.dataURLtoBlob(this.dataURL);
+ this.dataURL = this.modalCropImg
+ .cropper('getCroppedCanvas', {
+ width: 200,
+ height: 200,
+ })
+ .toDataURL('image/png');
+ return (this.croppedImageBlob = this.dataURLtoBlob(this.dataURL));
}
getBlob() {
diff --git a/app/assets/javascripts/profile/profile.js b/app/assets/javascripts/profile/profile.js
index e49c67ffb5c..deacff5abe7 100644
--- a/app/assets/javascripts/profile/profile.js
+++ b/app/assets/javascripts/profile/profile.js
@@ -1,6 +1,7 @@
import $ from 'jquery';
import axios from '~/lib/utils/axios_utils';
import flash from '../flash';
+import { parseBoolean } from '~/lib/utils/common_utils';
export default class Profile {
constructor({ form } = {}) {
@@ -26,11 +27,7 @@ export default class Profile {
}
bindEvents() {
- $('.js-preferences-form').on(
- 'change.preference',
- 'input[type=radio]',
- this.submitForm,
- );
+ $('.js-preferences-form').on('change.preference', 'input[type=radio]', this.submitForm);
$('#user_notification_email').on('change', this.submitForm);
$('#user_notified_of_own_activity').on('change', this.submitForm);
this.form.on('submit', this.onSubmitForm);
@@ -84,7 +81,7 @@ export default class Profile {
setRepoRadio() {
const multiEditRadios = $('input[name="user[multi_file]"]');
- if (this.newRepoActivated || this.newRepoActivated === 'true') {
+ if (parseBoolean(this.newRepoActivated)) {
multiEditRadios.filter('[value=on]').prop('checked', true);
} else {
multiEditRadios.filter('[value=off]').prop('checked', true);
diff --git a/app/assets/javascripts/project_find_file.js b/app/assets/javascripts/project_find_file.js
index 05485e352dc..60d3d83a4b2 100644
--- a/app/assets/javascripts/project_find_file.js
+++ b/app/assets/javascripts/project_find_file.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, no-var, wrap-iife, quotes, consistent-return, one-var, one-var-declaration-per-line, no-cond-assign, max-len, prefer-template, no-unused-vars, no-return-assign */
+/* eslint-disable func-names, no-var, consistent-return, one-var, no-cond-assign, prefer-template, no-unused-vars, no-return-assign */
import $ from 'jquery';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
@@ -10,14 +10,14 @@ import { __ } from '~/locale';
const highlighter = function(element, text, matches) {
var highlightText, j, lastIndex, len, matchIndex, matchedChars, unmatched;
lastIndex = 0;
- highlightText = "";
+ highlightText = '';
matchedChars = [];
for (j = 0, len = matches.length; j < len; j += 1) {
matchIndex = matches[j];
unmatched = text.substring(lastIndex, matchIndex);
if (unmatched) {
if (matchedChars.length) {
- element.append(matchedChars.join("").bold());
+ element.append(matchedChars.join('').bold());
}
matchedChars = [];
element.append(document.createTextNode(unmatched));
@@ -26,7 +26,7 @@ const highlighter = function(element, text, matches) {
lastIndex = matchIndex + 1;
}
if (matchedChars.length) {
- element.append(matchedChars.join("").bold());
+ element.append(matchedChars.join('').bold());
}
return element.append(document.createTextNode(text.substring(lastIndex)));
};
@@ -40,7 +40,7 @@ export default class ProjectFindFile {
this.selectRowDown = this.selectRowDown.bind(this);
this.selectRowUp = this.selectRowUp.bind(this);
this.filePaths = {};
- this.inputElement = this.element.find(".file-finder-input");
+ this.inputElement = this.element.find('.file-finder-input');
// init event
this.initEvent();
// focus text input box
@@ -50,38 +50,51 @@ export default class ProjectFindFile {
}
initEvent() {
- this.inputElement.off("keyup");
- this.inputElement.on("keyup", (function(_this) {
- return function(event) {
- var oldValue, ref, target, value;
- target = $(event.target);
- value = target.val();
- oldValue = (ref = target.data("oldValue")) != null ? ref : "";
- if (value !== oldValue) {
- target.data("oldValue", value);
- _this.findFile();
- return _this.element.find("tr.tree-item").eq(0).addClass("selected").focus();
- }
- };
- })(this));
+ this.inputElement.off('keyup');
+ this.inputElement.on(
+ 'keyup',
+ (function(_this) {
+ return function(event) {
+ var oldValue, ref, target, value;
+ target = $(event.target);
+ value = target.val();
+ oldValue = (ref = target.data('oldValue')) != null ? ref : '';
+ if (value !== oldValue) {
+ target.data('oldValue', value);
+ _this.findFile();
+ return _this.element
+ .find('tr.tree-item')
+ .eq(0)
+ .addClass('selected')
+ .focus();
+ }
+ };
+ })(this),
+ );
}
findFile() {
var result, searchText;
searchText = this.inputElement.val();
- result = searchText.length > 0 ? fuzzaldrinPlus.filter(this.filePaths, searchText) : this.filePaths;
+ result =
+ searchText.length > 0 ? fuzzaldrinPlus.filter(this.filePaths, searchText) : this.filePaths;
return this.renderList(result, searchText);
- // find file
+ // find file
}
// files pathes load
load(url) {
- axios.get(url)
+ axios
+ .get(url)
.then(({ data }) => {
this.element.find('.loading').hide();
this.filePaths = data;
this.findFile();
- this.element.find('.files-slider tr.tree-item').eq(0).addClass('selected').focus();
+ this.element
+ .find('.files-slider tr.tree-item')
+ .eq(0)
+ .addClass('selected')
+ .focus();
})
.catch(() => flash(__('An error occurred while loading filenames')));
}
@@ -89,7 +102,7 @@ export default class ProjectFindFile {
// render result
renderList(filePaths, searchText) {
var blobItemUrl, filePath, html, i, len, matches, results;
- this.element.find(".tree-table > tbody").empty();
+ this.element.find('.tree-table > tbody').empty();
results = [];
for (i = 0, len = filePaths.length; i < len; i += 1) {
@@ -100,9 +113,9 @@ export default class ProjectFindFile {
if (searchText) {
matches = fuzzaldrinPlus.match(filePath, searchText);
}
- blobItemUrl = this.options.blobUrlTemplate + "/" + filePath;
+ blobItemUrl = this.options.blobUrlTemplate + '/' + filePath;
html = ProjectFindFile.makeHtml(filePath, matches, blobItemUrl);
- results.push(this.element.find(".tree-table > tbody").append(html));
+ results.push(this.element.find('.tree-table > tbody').append(html));
}
return results;
}
@@ -110,52 +123,56 @@ export default class ProjectFindFile {
// make tbody row html
static makeHtml(filePath, matches, blobItemUrl) {
var $tr;
- $tr = $("<tr class='tree-item'><td class='tree-item-file-name link-container'><a><i class='fa fa-file-text-o fa-fw'></i><span class='str-truncated'></span></a></td></tr>");
+ $tr = $(
+ "<tr class='tree-item'><td class='tree-item-file-name link-container'><a><i class='fa fa-file-text-o fa-fw'></i><span class='str-truncated'></span></a></td></tr>",
+ );
if (matches) {
- $tr.find("a").replaceWith(highlighter($tr.find("a"), filePath, matches).attr("href", blobItemUrl));
+ $tr
+ .find('a')
+ .replaceWith(highlighter($tr.find('a'), filePath, matches).attr('href', blobItemUrl));
} else {
- $tr.find("a").attr("href", blobItemUrl);
- $tr.find(".str-truncated").text(filePath);
+ $tr.find('a').attr('href', blobItemUrl);
+ $tr.find('.str-truncated').text(filePath);
}
return $tr;
}
selectRow(type) {
var next, rows, selectedRow;
- rows = this.element.find(".files-slider tr.tree-item");
- selectedRow = this.element.find(".files-slider tr.tree-item.selected");
+ rows = this.element.find('.files-slider tr.tree-item');
+ selectedRow = this.element.find('.files-slider tr.tree-item.selected');
if (rows && rows.length > 0) {
if (selectedRow && selectedRow.length > 0) {
- if (type === "UP") {
+ if (type === 'UP') {
next = selectedRow.prev();
- } else if (type === "DOWN") {
+ } else if (type === 'DOWN') {
next = selectedRow.next();
}
if (next.length > 0) {
- selectedRow.removeClass("selected");
+ selectedRow.removeClass('selected');
selectedRow = next;
}
} else {
selectedRow = rows.eq(0);
}
- return selectedRow.addClass("selected").focus();
+ return selectedRow.addClass('selected').focus();
}
}
selectRowUp() {
- return this.selectRow("UP");
+ return this.selectRow('UP');
}
selectRowDown() {
- return this.selectRow("DOWN");
+ return this.selectRow('DOWN');
}
goToTree() {
- return window.location.href = this.options.treeUrl;
+ return (window.location.href = this.options.treeUrl);
}
goToBlob() {
- var $link = this.element.find(".tree-item.selected .tree-item-file-name a");
+ var $link = this.element.find('.tree-item.selected .tree-item-file-name a');
if ($link.length) {
$link.get(0).click();
diff --git a/app/assets/javascripts/project_import.js b/app/assets/javascripts/project_import.js
index 5a0d2b642eb..a51a2a2242f 100644
--- a/app/assets/javascripts/project_import.js
+++ b/app/assets/javascripts/project_import.js
@@ -5,4 +5,3 @@ export default function projectImport() {
visitUrl(window.location.href);
}, 5000);
}
-
diff --git a/app/assets/javascripts/project_label_subscription.js b/app/assets/javascripts/project_label_subscription.js
index 9049f87e037..d3c604dcee1 100644
--- a/app/assets/javascripts/project_label_subscription.js
+++ b/app/assets/javascripts/project_label_subscription.js
@@ -31,32 +31,35 @@ export default class ProjectLabelSubscription {
$btn.addClass('disabled');
- axios.post(url).then(() => {
- let newStatus;
- let newAction;
+ axios
+ .post(url)
+ .then(() => {
+ let newStatus;
+ let newAction;
- if (oldStatus === 'unsubscribed') {
- [newStatus, newAction] = ['subscribed', 'Unsubscribe'];
- } else {
- [newStatus, newAction] = ['unsubscribed', 'Subscribe'];
- }
+ if (oldStatus === 'unsubscribed') {
+ [newStatus, newAction] = ['subscribed', 'Unsubscribe'];
+ } else {
+ [newStatus, newAction] = ['unsubscribed', 'Subscribe'];
+ }
- $btn.removeClass('disabled');
+ $btn.removeClass('disabled');
- this.$buttons.attr('data-status', newStatus);
- this.$buttons.find('> span').text(newAction);
+ this.$buttons.attr('data-status', newStatus);
+ this.$buttons.find('> span').text(newAction);
- this.$buttons.map((i, button) => {
- const $button = $(button);
- const originalTitle = $button.attr('data-original-title');
+ this.$buttons.map((i, button) => {
+ const $button = $(button);
+ const originalTitle = $button.attr('data-original-title');
- if (originalTitle) {
- ProjectLabelSubscription.setNewTitle($button, originalTitle, newStatus, newAction);
- }
+ if (originalTitle) {
+ ProjectLabelSubscription.setNewTitle($button, originalTitle, newStatus, newAction);
+ }
- return button;
- });
- }).catch(() => flash(__('There was an error subscribing to this label.')));
+ return button;
+ });
+ })
+ .catch(() => flash(__('There was an error subscribing to this label.')));
}
static setNewTitle($button, originalTitle, newStatus) {
diff --git a/app/assets/javascripts/project_select.js b/app/assets/javascripts/project_select.js
index 6f3b32f8eea..a33835472bb 100644
--- a/app/assets/javascripts/project_select.js
+++ b/app/assets/javascripts/project_select.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, wrap-iife, no-var, comma-dangle, object-shorthand, one-var, one-var-declaration-per-line, no-else-return, quotes, max-len */
+/* eslint-disable func-names, no-var, object-shorthand, one-var, no-else-return */
import $ from 'jquery';
import Api from './api';
@@ -14,30 +14,33 @@ export default function projectSelect() {
this.orderBy = $(select).data('orderBy') || 'id';
this.withIssuesEnabled = $(select).data('withIssuesEnabled');
this.withMergeRequestsEnabled = $(select).data('withMergeRequestsEnabled');
+ this.withShared =
+ $(select).data('withShared') === undefined ? true : $(select).data('withShared');
+ this.includeProjectsInSubgroups = $(select).data('includeProjectsInSubgroups') || false;
this.allowClear = $(select).data('allowClear') || false;
- placeholder = "Search for project";
+ placeholder = 'Search for project';
if (this.includeGroups) {
- placeholder += " or group";
+ placeholder += ' or group';
}
$(select).select2({
placeholder: placeholder,
minimumInputLength: 0,
- query: (function (_this) {
- return function (query) {
+ query: (function(_this) {
+ return function(query) {
var finalCallback, projectsCallback;
- finalCallback = function (projects) {
+ finalCallback = function(projects) {
var data;
data = {
- results: projects
+ results: projects,
};
return query.callback(data);
};
if (_this.includeGroups) {
- projectsCallback = function (projects) {
+ projectsCallback = function(projects) {
var groupsCallback;
- groupsCallback = function (groups) {
+ groupsCallback = function(groups) {
var data;
data = groups.concat(projects);
return finalCallback(data);
@@ -48,17 +51,28 @@ export default function projectSelect() {
projectsCallback = finalCallback;
}
if (_this.groupId) {
- return Api.groupProjects(_this.groupId, query.term, {
- with_issues_enabled: _this.withIssuesEnabled,
- with_merge_requests_enabled: _this.withMergeRequestsEnabled,
- }, projectsCallback);
+ return Api.groupProjects(
+ _this.groupId,
+ query.term,
+ {
+ with_issues_enabled: _this.withIssuesEnabled,
+ with_merge_requests_enabled: _this.withMergeRequestsEnabled,
+ with_shared: _this.withShared,
+ include_subgroups: _this.includeProjectsInSubgroups,
+ },
+ projectsCallback,
+ );
} else {
- return Api.projects(query.term, {
- order_by: _this.orderBy,
- with_issues_enabled: _this.withIssuesEnabled,
- with_merge_requests_enabled: _this.withMergeRequestsEnabled,
- membership: !_this.allProjects,
- }, projectsCallback);
+ return Api.projects(
+ query.term,
+ {
+ order_by: _this.orderBy,
+ with_issues_enabled: _this.withIssuesEnabled,
+ with_merge_requests_enabled: _this.withMergeRequestsEnabled,
+ membership: !_this.allProjects,
+ },
+ projectsCallback,
+ );
}
};
})(this),
@@ -69,7 +83,7 @@ export default function projectSelect() {
url: project.web_url,
});
},
- text: function (project) {
+ text: function(project) {
return project.name_with_namespace || project.name;
},
@@ -79,7 +93,7 @@ export default function projectSelect() {
allowClear: this.allowClear,
- dropdownCssClass: "ajax-project-dropdown"
+ dropdownCssClass: 'ajax-project-dropdown',
});
if (simpleFilter) return select;
return new ProjectSelectComboButton(select);
diff --git a/app/assets/javascripts/project_select_combo_button.js b/app/assets/javascripts/project_select_combo_button.js
index 9b404896e86..3dbac3ff942 100644
--- a/app/assets/javascripts/project_select_combo_button.js
+++ b/app/assets/javascripts/project_select_combo_button.js
@@ -14,10 +14,11 @@ export default class ProjectSelectComboButton {
}
bindEvents() {
- this.projectSelectInput.siblings('.new-project-item-select-button')
+ this.projectSelectInput
+ .siblings('.new-project-item-select-button')
.on('click', e => this.openDropdown(e));
- this.newItemBtn.on('click', (e) => {
+ this.newItemBtn.on('click', e => {
if (!this.getProjectFromLocalStorage()) {
e.preventDefault();
this.openDropdown(e);
@@ -31,14 +32,21 @@ export default class ProjectSelectComboButton {
const localStorageIsSafe = AccessorUtilities.isLocalStorageAccessSafe();
if (localStorageIsSafe) {
- this.localStorageKey = ['group', this.groupId, this.formattedText.localStorageItemType, 'recent-project'].join('-');
+ this.localStorageKey = [
+ 'group',
+ this.groupId,
+ this.formattedText.localStorageItemType,
+ 'recent-project',
+ ].join('-');
this.setBtnTextFromLocalStorage();
}
}
// eslint-disable-next-line class-methods-use-this
openDropdown(event) {
- $(event.currentTarget).siblings('.project-item-select').select2('open');
+ $(event.currentTarget)
+ .siblings('.project-item-select')
+ .select2('open');
}
selectProject() {
@@ -86,8 +94,14 @@ export default class ProjectSelectComboButton {
const defaultTextPrefix = this.resourceLabel;
// the trailing slice call depluralizes each of these strings (e.g. new-issues -> new-issue)
- const localStorageItemType = `new-${this.resourceType.split('_').join('-').slice(0, -1)}`;
- const presetTextSuffix = this.resourceType.split('_').join(' ').slice(0, -1);
+ const localStorageItemType = `new-${this.resourceType
+ .split('_')
+ .join('-')
+ .slice(0, -1)}`;
+ const presetTextSuffix = this.resourceType
+ .split('_')
+ .join(' ')
+ .slice(0, -1);
return {
localStorageItemType, // new-issue / new-merge-request
@@ -96,4 +110,3 @@ export default class ProjectSelectComboButton {
};
}
}
-
diff --git a/app/assets/javascripts/project_visibility.js b/app/assets/javascripts/project_visibility.js
index a52ac768e57..aaf6723c85c 100644
--- a/app/assets/javascripts/project_visibility.js
+++ b/app/assets/javascripts/project_visibility.js
@@ -7,7 +7,7 @@ function setVisibilityOptions(namespaceSelector) {
const selectedNamespace = namespaceSelector.options[namespaceSelector.selectedIndex];
const { name, visibility, visibilityLevel, showPath, editPath } = selectedNamespace.dataset;
- document.querySelectorAll('.visibility-level-setting .form-check').forEach((option) => {
+ document.querySelectorAll('.visibility-level-setting .form-check').forEach(option => {
const optionInput = option.querySelector('input[type=radio]');
const optionValue = optionInput ? optionInput.value : 0;
const optionTitle = option.querySelector('.option-title');
@@ -20,8 +20,7 @@ function setVisibilityOptions(namespaceSelector) {
optionInput.disabled = true;
const reason = option.querySelector('.option-disabled-reason');
if (reason) {
- reason.innerHTML =
- `This project cannot be ${optionName} because the visibility of
+ reason.innerHTML = `This project cannot be ${optionName} because the visibility of
<a href="${showPath}">${name}</a> is ${visibility}. To make this project
${optionName}, you must first <a href="${editPath}">change the visibility</a>
of the parent group.`;
diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_dropdown_mixin.js b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_dropdown_mixin.js
index d5266544307..5a3407693e5 100644
--- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_dropdown_mixin.js
+++ b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_dropdown_mixin.js
@@ -2,6 +2,7 @@ import _ from 'underscore';
import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_search_input.vue';
import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
import store from '../store';
@@ -11,6 +12,7 @@ export default {
DropdownButton,
DropdownSearchInput,
DropdownHiddenInput,
+ GlLoadingIcon,
},
props: {
fieldId: {
diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue
index 2c02f436b69..21095fcba16 100644
--- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue
+++ b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue
@@ -47,7 +47,7 @@ export default {
errorMessage() {
return sprintf(
s__(
- 'ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}',
+ 'ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}',
),
{ error: this.gapiError },
);
@@ -87,13 +87,8 @@ export default {
<template>
<div>
- <div
- class="js-gcp-machine-type-dropdown dropdown"
- >
- <dropdown-hidden-input
- :name="fieldName"
- :value="selectedMachineType"
- />
+ <div class="js-gcp-machine-type-dropdown dropdown">
+ <dropdown-hidden-input :name="fieldName" :value="selectedMachineType" />
<dropdown-button
:class="{ 'border-danger': hasErrors }"
:is-disabled="isDisabled"
@@ -112,29 +107,21 @@ export default {
{{ s__('ClusterIntegration|No machine types matched your search') }}
</span>
</li>
- <li
- v-for="result in results"
- :key="result.id"
- >
- <button
- type="button"
- @click.prevent="setItem(result.name)"
- >
+ <li v-for="result in results" :key="result.id">
+ <button type="button" @click.prevent="setItem(result.name);">
{{ result.name }}
</button>
</li>
</ul>
</div>
- <div class="dropdown-loading">
- <gl-loading-icon />
- </div>
+ <div class="dropdown-loading"><gl-loading-icon /></div>
</div>
</div>
<span
v-if="hasErrors"
:class="{
'text-danger': hasErrors,
- 'text-muted': !hasErrors
+ 'text-muted': !hasErrors,
}"
class="form-text"
>
diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue
index fc17e2fab49..056584c8865 100644
--- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue
+++ b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue
@@ -93,7 +93,7 @@ export default {
}
return sprintf(
- s__('ClusterIntegration|An error occured while trying to fetch your projects: %{error}'),
+ s__('ClusterIntegration|An error occurred while trying to fetch your projects: %{error}'),
{ error: this.gapiError },
);
},
@@ -145,17 +145,12 @@ export default {
<template>
<div>
- <div
- class="js-gcp-project-id-dropdown dropdown"
- >
- <dropdown-hidden-input
- :name="fieldName"
- :value="selectedProject.projectId"
- />
+ <div class="js-gcp-project-id-dropdown dropdown">
+ <dropdown-hidden-input :name="fieldName" :value="selectedProject.projectId" />
<dropdown-button
:class="{
'border-danger': hasErrors,
- 'read-only': hasOneProject
+ 'read-only': hasOneProject,
}"
:is-disabled="isDisabled"
:is-loading="isLoading"
@@ -173,28 +168,18 @@ export default {
{{ s__('ClusterIntegration|No projects matched your search') }}
</span>
</li>
- <li
- v-for="result in results"
- :key="result.project_number"
- >
- <button
- type="button"
- @click.prevent="setItem(result)"
- >
- {{ result.name }}
- </button>
+ <li v-for="result in results" :key="result.project_number">
+ <button type="button" @click.prevent="setItem(result);">{{ result.name }}</button>
</li>
</ul>
</div>
- <div class="dropdown-loading">
- <gl-loading-icon />
- </div>
+ <div class="dropdown-loading"><gl-loading-icon /></div>
</div>
</div>
<span
:class="{
'text-danger': hasErrors,
- 'text-muted': !hasErrors
+ 'text-muted': !hasErrors,
}"
class="form-text"
v-html="helpText"
diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown.vue b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown.vue
index ca7c79f75f0..728616a441f 100644
--- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown.vue
+++ b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown.vue
@@ -61,13 +61,8 @@ export default {
<template>
<div>
- <div
- class="js-gcp-zone-dropdown dropdown"
- >
- <dropdown-hidden-input
- :name="fieldName"
- :value="selectedZone"
- />
+ <div class="js-gcp-zone-dropdown dropdown">
+ <dropdown-hidden-input :name="fieldName" :value="selectedZone" />
<dropdown-button
:class="{ 'border-danger': hasErrors }"
:is-disabled="isDisabled"
@@ -86,29 +81,21 @@ export default {
{{ s__('ClusterIntegration|No zones matched your search') }}
</span>
</li>
- <li
- v-for="result in results"
- :key="result.id"
- >
- <button
- type="button"
- @click.prevent="setItem(result.name)"
- >
+ <li v-for="result in results" :key="result.id">
+ <button type="button" @click.prevent="setItem(result.name);">
{{ result.name }}
</button>
</li>
</ul>
</div>
- <div class="dropdown-loading">
- <gl-loading-icon />
- </div>
+ <div class="dropdown-loading"><gl-loading-icon /></div>
</div>
</div>
<span
v-if="hasErrors"
:class="{
'text-danger': hasErrors,
- 'text-muted': !hasErrors
+ 'text-muted': !hasErrors,
}"
class="form-text"
>
diff --git a/app/assets/javascripts/projects/project_new.js b/app/assets/javascripts/projects/project_new.js
index 8a079b4b38a..998554d1be5 100644
--- a/app/assets/javascripts/projects/project_new.js
+++ b/app/assets/javascripts/projects/project_new.js
@@ -4,8 +4,10 @@ import { slugifyWithHyphens } from '../lib/utils/text_utility';
let hasUserDefinedProjectPath = false;
-const deriveProjectPathFromUrl = ($projectImportUrl) => {
- const $currentProjectPath = $projectImportUrl.parents('.toggle-import-form').find('#project_path');
+const deriveProjectPathFromUrl = $projectImportUrl => {
+ const $currentProjectPath = $projectImportUrl
+ .parents('.toggle-import-form')
+ .find('#project_path');
if (hasUserDefinedProjectPath) {
return;
}
@@ -52,9 +54,11 @@ const bindEvents = () => {
return;
}
- $('.how_to_import_link').on('click', (e) => {
+ $('.how_to_import_link').on('click', e => {
e.preventDefault();
- $(e.currentTarget).next('.modal').show();
+ $(e.currentTarget)
+ .next('.modal')
+ .show();
});
$('.modal-header .close').on('click', () => {
@@ -63,15 +67,21 @@ const bindEvents = () => {
$('.btn_import_gitlab_project').on('click', () => {
const importHref = $('a.btn_import_gitlab_project').attr('href');
- $('.btn_import_gitlab_project')
- .attr('href', `${importHref}?namespace_id=${$('#project_namespace_id').val()}&name=${$projectName.val()}&path=${$projectPath.val()}`);
+ $('.btn_import_gitlab_project').attr(
+ 'href',
+ `${importHref}?namespace_id=${$(
+ '#project_namespace_id',
+ ).val()}&name=${$projectName.val()}&path=${$projectPath.val()}`,
+ );
});
if ($pushNewProjectTipTrigger) {
$pushNewProjectTipTrigger
.removeAttr('rel')
.removeAttr('target')
- .on('click', (e) => { e.preventDefault(); })
+ .on('click', e => {
+ e.preventDefault();
+ })
.popover({
title: $pushNewProjectTipTrigger.data('title'),
placement: 'bottom',
@@ -79,13 +89,15 @@ const bindEvents = () => {
content: $('.push-new-project-tip-template').html(),
})
.on('shown.bs.popover', () => {
- $(document).on('click.popover touchstart.popover', (event) => {
+ $(document).on('click.popover touchstart.popover', event => {
if ($(event.target).closest('.popover').length === 0) {
$pushNewProjectTipTrigger.trigger('click');
}
});
- const target = $(`#${$pushNewProjectTipTrigger.attr('aria-describedby')}`).find('.js-select-on-focus');
+ const target = $(`#${$pushNewProjectTipTrigger.attr('aria-describedby')}`).find(
+ '.js-select-on-focus',
+ );
addSelectOnFocusBehaviour(target);
target.focus();
@@ -117,16 +129,18 @@ const bindEvents = () => {
const selectedTemplate = templates[value];
$selectedTemplateText.text(selectedTemplate.text);
- $(selectedTemplate.icon).clone().addClass('d-block').appendTo($selectedIcon);
+ $(selectedTemplate.icon)
+ .clone()
+ .addClass('d-block')
+ .appendTo($selectedIcon);
const $activeTabProjectName = $('.tab-pane.active #project_name');
const $activeTabProjectPath = $('.tab-pane.active #project_path');
$activeTabProjectName.focus();
- $activeTabProjectName
- .keyup(() => {
- onProjectNameChange($activeTabProjectName, $activeTabProjectPath);
- hasUserDefinedProjectPath = $activeTabProjectPath.val().trim().length > 0;
- });
+ $activeTabProjectName.keyup(() => {
+ onProjectNameChange($activeTabProjectName, $activeTabProjectPath);
+ hasUserDefinedProjectPath = $activeTabProjectPath.val().trim().length > 0;
+ });
}
$useTemplateBtn.on('change', chooseTemplate);
@@ -147,7 +161,7 @@ const bindEvents = () => {
$projectImportUrl.keyup(() => deriveProjectPathFromUrl($projectImportUrl));
- $projectName.keyup(() => {
+ $projectName.on('keyup change', () => {
onProjectNameChange($projectName, $projectPath);
hasUserDefinedProjectPath = $projectPath.val().trim().length > 0;
});
diff --git a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
index 120b4fc2f2b..bfc55013a71 100644
--- a/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
+++ b/app/assets/javascripts/projects/tree/components/commit_pipeline_status_component.vue
@@ -5,6 +5,7 @@ import Poll from '~/lib/utils/poll';
import Flash from '~/flash';
import { s__, sprintf } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
+import { GlLoadingIcon } from '@gitlab/ui';
import CommitPipelineService from '../services/commit_pipeline_service';
export default {
@@ -13,6 +14,7 @@ export default {
},
components: {
ciIcon,
+ GlLoadingIcon,
},
props: {
endpoint: {
@@ -98,15 +100,8 @@ export default {
</script>
<template>
<div class="ci-status-link">
- <gl-loading-icon
- v-if="isLoading"
- :size="3"
- label="Loading pipeline status"
- />
- <a
- v-else
- :href="ciStatus.details_path"
- >
+ <gl-loading-icon v-if="isLoading" :size="3" label="Loading pipeline status" />
+ <a v-else :href="ciStatus.details_path">
<ci-icon
v-tooltip
:title="statusTitle"
diff --git a/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js b/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js
index 078ccbbbac2..8380cfb6c59 100644
--- a/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js
+++ b/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js
@@ -65,10 +65,14 @@ export default class PrometheusMetrics {
let totalMissingEnvVarMetrics = 0;
let totalExporters = 0;
- metrics.forEach((metric) => {
+ metrics.forEach(metric => {
if (metric.active_metrics > 0) {
totalExporters += 1;
- this.$monitoredMetricsList.append(`<li>${_.escape(metric.group)}<span class="badge">${_.escape(metric.active_metrics)}</span></li>`);
+ this.$monitoredMetricsList.append(
+ `<li>${_.escape(metric.group)}<span class="badge">${_.escape(
+ metric.active_metrics,
+ )}</span></li>`,
+ );
totalMonitoredMetrics += metric.active_metrics;
if (metric.metrics_missing_requirements > 0) {
this.$missingEnvVarMetricsList.append(`<li>${_.escape(metric.group)}</li>`);
@@ -78,17 +82,26 @@ export default class PrometheusMetrics {
});
if (totalMonitoredMetrics === 0) {
- const emptyCommonMetricsText = sprintf(s__('PrometheusService|<p class="text-tertiary">No <a href="%{docsUrl}">common metrics</a> were found</p>'), {
- docsUrl: this.helpMetricsPath,
- }, false);
+ const emptyCommonMetricsText = sprintf(
+ s__(
+ 'PrometheusService|<p class="text-tertiary">No <a href="%{docsUrl}">common metrics</a> were found</p>',
+ ),
+ {
+ docsUrl: this.helpMetricsPath,
+ },
+ false,
+ );
this.$monitoredMetricsEmpty.empty();
this.$monitoredMetricsEmpty.append(emptyCommonMetricsText);
this.showMonitoringMetricsPanelState(PANEL_STATE.EMPTY);
} else {
- const metricsCountText = sprintf(s__('PrometheusService|%{exporters} with %{metrics} were found'), {
- exporters: n__('%d exporter', '%d exporters', totalExporters),
- metrics: n__('%d metric', '%d metrics', totalMonitoredMetrics),
- });
+ const metricsCountText = sprintf(
+ s__('PrometheusService|%{exporters} with %{metrics} were found'),
+ {
+ exporters: n__('%d exporter', '%d exporters', totalExporters),
+ metrics: n__('%d metric', '%d metrics', totalMonitoredMetrics),
+ },
+ );
this.$monitoredMetricsCount.text(metricsCountText);
this.showMonitoringMetricsPanelState(PANEL_STATE.LIST);
@@ -102,7 +115,8 @@ export default class PrometheusMetrics {
loadActiveMetrics() {
this.showMonitoringMetricsPanelState(PANEL_STATE.LOADING);
backOff((next, stop) => {
- axios.get(this.activeMetricsEndpoint)
+ axios
+ .get(this.activeMetricsEndpoint)
.then(({ data }) => {
if (data && data.success) {
stop(data);
@@ -117,7 +131,7 @@ export default class PrometheusMetrics {
})
.catch(stop);
})
- .then((res) => {
+ .then(res => {
if (res && res.data && res.data.length) {
this.populateActiveMetrics(res.data);
} else {
diff --git a/app/assets/javascripts/protected_branches/protected_branch_create.js b/app/assets/javascripts/protected_branches/protected_branch_create.js
index b601b19e7be..48343c8ba0a 100644
--- a/app/assets/javascripts/protected_branches/protected_branch_create.js
+++ b/app/assets/javascripts/protected_branches/protected_branch_create.js
@@ -46,8 +46,12 @@ export default class ProtectedBranchCreate {
onSelect() {
// Enable submit button
const $branchInput = this.$form.find('input[name="protected_branch[name]"]');
- const $allowedToMergeInput = this.$form.find('input[name="protected_branch[merge_access_levels_attributes][0][access_level]"]');
- const $allowedToPushInput = this.$form.find('input[name="protected_branch[push_access_levels_attributes][0][access_level]"]');
+ const $allowedToMergeInput = this.$form.find(
+ 'input[name="protected_branch[merge_access_levels_attributes][0][access_level]"]',
+ );
+ const $allowedToPushInput = this.$form.find(
+ 'input[name="protected_branch[push_access_levels_attributes][0][access_level]"]',
+ );
const completedForm = !(
$branchInput.val() &&
$allowedToMergeInput.length &&
diff --git a/app/assets/javascripts/protected_branches/protected_branch_edit.js b/app/assets/javascripts/protected_branches/protected_branch_edit.js
index 54560d08ad7..5bc08f60d16 100644
--- a/app/assets/javascripts/protected_branches/protected_branch_edit.js
+++ b/app/assets/javascripts/protected_branches/protected_branch_edit.js
@@ -29,8 +29,12 @@ export default class ProtectedBranchEdit {
}
onSelect() {
- const $allowedToMergeInput = this.$wrap.find(`input[name="${this.$allowedToMergeDropdown.data('fieldName')}"]`);
- const $allowedToPushInput = this.$wrap.find(`input[name="${this.$allowedToPushDropdown.data('fieldName')}"]`);
+ const $allowedToMergeInput = this.$wrap.find(
+ `input[name="${this.$allowedToMergeDropdown.data('fieldName')}"]`,
+ );
+ const $allowedToPushInput = this.$wrap.find(
+ `input[name="${this.$allowedToPushDropdown.data('fieldName')}"]`,
+ );
// Do not update if one dropdown has not selected any option
if (!($allowedToMergeInput.length && $allowedToPushInput.length)) return;
@@ -38,25 +42,36 @@ export default class ProtectedBranchEdit {
this.$allowedToMergeDropdown.disable();
this.$allowedToPushDropdown.disable();
- axios.patch(this.$wrap.data('url'), {
- protected_branch: {
- merge_access_levels_attributes: [{
- id: this.$allowedToMergeDropdown.data('accessLevelId'),
- access_level: $allowedToMergeInput.val(),
- }],
- push_access_levels_attributes: [{
- id: this.$allowedToPushDropdown.data('accessLevelId'),
- access_level: $allowedToPushInput.val(),
- }],
- },
- }).then(() => {
- this.$allowedToMergeDropdown.enable();
- this.$allowedToPushDropdown.enable();
- }).catch(() => {
- this.$allowedToMergeDropdown.enable();
- this.$allowedToPushDropdown.enable();
-
- flash('Failed to update branch!', 'alert', document.querySelector('.js-protected-branches-list'));
- });
+ axios
+ .patch(this.$wrap.data('url'), {
+ protected_branch: {
+ merge_access_levels_attributes: [
+ {
+ id: this.$allowedToMergeDropdown.data('accessLevelId'),
+ access_level: $allowedToMergeInput.val(),
+ },
+ ],
+ push_access_levels_attributes: [
+ {
+ id: this.$allowedToPushDropdown.data('accessLevelId'),
+ access_level: $allowedToPushInput.val(),
+ },
+ ],
+ },
+ })
+ .then(() => {
+ this.$allowedToMergeDropdown.enable();
+ this.$allowedToPushDropdown.enable();
+ })
+ .catch(() => {
+ this.$allowedToMergeDropdown.enable();
+ this.$allowedToPushDropdown.enable();
+
+ flash(
+ 'Failed to update branch!',
+ 'alert',
+ document.querySelector('.js-protected-branches-list'),
+ );
+ });
}
}
diff --git a/app/assets/javascripts/protected_tags/protected_tag_create.js b/app/assets/javascripts/protected_tags/protected_tag_create.js
index 2f8116df0d2..fddf2674cbb 100644
--- a/app/assets/javascripts/protected_tags/protected_tag_create.js
+++ b/app/assets/javascripts/protected_tags/protected_tag_create.js
@@ -40,7 +40,9 @@ export default class ProtectedTagCreate {
const $tagInput = this.$form.find('input[name="protected_tag[name]"]');
const $allowedToCreateInput = this.$form.find('#create_access_levels_attributes');
- this.$form.find('input[type="submit"]').prop('disabled', !($tagInput.val() && $allowedToCreateInput.length));
+ this.$form
+ .find('input[type="submit"]')
+ .prop('disabled', !($tagInput.val() && $allowedToCreateInput.length));
}
static getProtectedTags(term, callback) {
diff --git a/app/assets/javascripts/protected_tags/protected_tag_edit.js b/app/assets/javascripts/protected_tags/protected_tag_edit.js
index 8687b2a4044..c52497e62f2 100644
--- a/app/assets/javascripts/protected_tags/protected_tag_edit.js
+++ b/app/assets/javascripts/protected_tags/protected_tag_edit.js
@@ -21,26 +21,33 @@ export default class ProtectedTagEdit {
}
onSelect() {
- const $allowedToCreateInput = this.$wrap.find(`input[name="${this.$allowedToCreateDropdownButton.data('fieldName')}"]`);
+ const $allowedToCreateInput = this.$wrap.find(
+ `input[name="${this.$allowedToCreateDropdownButton.data('fieldName')}"]`,
+ );
// Do not update if one dropdown has not selected any option
if (!$allowedToCreateInput.length) return;
this.$allowedToCreateDropdownButton.disable();
- axios.patch(this.$wrap.data('url'), {
- protected_tag: {
- create_access_levels_attributes: [{
- id: this.$allowedToCreateDropdownButton.data('accessLevelId'),
- access_level: $allowedToCreateInput.val(),
- }],
- },
- }).then(() => {
- this.$allowedToCreateDropdownButton.enable();
- }).catch(() => {
- this.$allowedToCreateDropdownButton.enable();
-
- flash('Failed to update tag!', 'alert', document.querySelector('.js-protected-tags-list'));
- });
+ axios
+ .patch(this.$wrap.data('url'), {
+ protected_tag: {
+ create_access_levels_attributes: [
+ {
+ id: this.$allowedToCreateDropdownButton.data('accessLevelId'),
+ access_level: $allowedToCreateInput.val(),
+ },
+ ],
+ },
+ })
+ .then(() => {
+ this.$allowedToCreateDropdownButton.enable();
+ })
+ .catch(() => {
+ this.$allowedToCreateDropdownButton.enable();
+
+ flash('Failed to update tag!', 'alert', document.querySelector('.js-protected-tags-list'));
+ });
}
}
diff --git a/app/assets/javascripts/raven/raven_config.js b/app/assets/javascripts/raven/raven_config.js
index 658caeecde1..338006ce2b9 100644
--- a/app/assets/javascripts/raven/raven_config.js
+++ b/app/assets/javascripts/raven/raven_config.js
@@ -9,7 +9,7 @@ const IGNORE_ERRORS = [
'canvas.contentDocument',
'MyApp_RemoveAllHighlights',
'http://tt.epicplay.com',
- 'Can\'t find variable: ZiteReader',
+ "Can't find variable: ZiteReader",
'jigsaw is not defined',
'ComboSearch is not defined',
'http://loading.retry.widdit.com/',
diff --git a/app/assets/javascripts/ref_select_dropdown.js b/app/assets/javascripts/ref_select_dropdown.js
index 95c5cf7b345..75bac035aca 100644
--- a/app/assets/javascripts/ref_select_dropdown.js
+++ b/app/assets/javascripts/ref_select_dropdown.js
@@ -2,7 +2,8 @@ import $ from 'jquery';
class RefSelectDropdown {
constructor($dropdownButton, availableRefs) {
- const availableRefsValue = availableRefs || JSON.parse(document.getElementById('availableRefs').innerHTML);
+ const availableRefsValue =
+ availableRefs || JSON.parse(document.getElementById('availableRefs').innerHTML);
$dropdownButton.glDropdown({
data: availableRefsValue,
filterable: true,
@@ -29,7 +30,7 @@ class RefSelectDropdown {
const $fieldInput = $(`input[name="${$dropdownButton.data('fieldName')}"]`, $dropdownContainer);
const $filterInput = $('input[type="search"]', $dropdownContainer);
- $filterInput.on('keyup', (e) => {
+ $filterInput.on('keyup', e => {
const keyCode = e.keyCode || e.which;
if (keyCode !== 13) return;
diff --git a/app/assets/javascripts/registry/components/app.vue b/app/assets/javascripts/registry/components/app.vue
index 7e2287ac4db..6233fb169e9 100644
--- a/app/assets/javascripts/registry/components/app.vue
+++ b/app/assets/javascripts/registry/components/app.vue
@@ -1,49 +1,41 @@
<script>
- import { mapGetters, mapActions } from 'vuex';
- import Flash from '../../flash';
- import store from '../stores';
- import collapsibleContainer from './collapsible_container.vue';
- import { errorMessages, errorMessagesTypes } from '../constants';
+import { mapGetters, mapActions } from 'vuex';
+import { GlLoadingIcon } from '@gitlab/ui';
+import Flash from '../../flash';
+import store from '../stores';
+import collapsibleContainer from './collapsible_container.vue';
+import { errorMessages, errorMessagesTypes } from '../constants';
- export default {
- name: 'RegistryListApp',
- components: {
- collapsibleContainer,
+export default {
+ name: 'RegistryListApp',
+ components: {
+ collapsibleContainer,
+ GlLoadingIcon,
+ },
+ props: {
+ endpoint: {
+ type: String,
+ required: true,
},
- props: {
- endpoint: {
- type: String,
- required: true,
- },
- },
- store,
- computed: {
- ...mapGetters([
- 'isLoading',
- 'repos',
- ]),
- },
- created() {
- this.setMainEndpoint(this.endpoint);
- },
- mounted() {
- this.fetchRepos()
- .catch(() => Flash(errorMessages[errorMessagesTypes.FETCH_REPOS]));
- },
- methods: {
- ...mapActions([
- 'setMainEndpoint',
- 'fetchRepos',
- ]),
- },
- };
+ },
+ store,
+ computed: {
+ ...mapGetters(['isLoading', 'repos']),
+ },
+ created() {
+ this.setMainEndpoint(this.endpoint);
+ },
+ mounted() {
+ this.fetchRepos().catch(() => Flash(errorMessages[errorMessagesTypes.FETCH_REPOS]));
+ },
+ methods: {
+ ...mapActions(['setMainEndpoint', 'fetchRepos']),
+ },
+};
</script>
<template>
<div>
- <gl-loading-icon
- v-if="isLoading"
- :size="3"
- />
+ <gl-loading-icon v-if="isLoading" :size="3" />
<collapsible-container
v-for="(item, index) in repos"
@@ -53,8 +45,10 @@
/>
<p v-else-if="!isLoading && !repos.length">
- {{ __(`No container images stored for this project.
-Add one by following the instructions above.`) }}
+ {{
+ __(`No container images stored for this project.
+Add one by following the instructions above.`)
+ }}
</p>
</div>
</template>
diff --git a/app/assets/javascripts/registry/components/collapsible_container.vue b/app/assets/javascripts/registry/components/collapsible_container.vue
index d4c4d779d44..6514c05a9c7 100644
--- a/app/assets/javascripts/registry/components/collapsible_container.vue
+++ b/app/assets/javascripts/registry/components/collapsible_container.vue
@@ -1,72 +1,67 @@
<script>
- import { mapActions } from 'vuex';
- import Flash from '../../flash';
- import clipboardButton from '../../vue_shared/components/clipboard_button.vue';
- import tooltip from '../../vue_shared/directives/tooltip';
- import tableRegistry from './table_registry.vue';
- import { errorMessages, errorMessagesTypes } from '../constants';
- import { __ } from '../../locale';
+import { mapActions } from 'vuex';
+import { GlLoadingIcon } from '@gitlab/ui';
+import Flash from '../../flash';
+import clipboardButton from '../../vue_shared/components/clipboard_button.vue';
+import tooltip from '../../vue_shared/directives/tooltip';
+import tableRegistry from './table_registry.vue';
+import { errorMessages, errorMessagesTypes } from '../constants';
+import { __ } from '../../locale';
- export default {
- name: 'CollapsibeContainerRegisty',
- components: {
- clipboardButton,
- tableRegistry,
+export default {
+ name: 'CollapsibeContainerRegisty',
+ components: {
+ clipboardButton,
+ tableRegistry,
+ GlLoadingIcon,
+ },
+ directives: {
+ tooltip,
+ },
+ props: {
+ repo: {
+ type: Object,
+ required: true,
},
- directives: {
- tooltip,
- },
- props: {
- repo: {
- type: Object,
- required: true,
- },
- },
- data() {
- return {
- isOpen: false,
- };
- },
- methods: {
- ...mapActions([
- 'fetchRepos',
- 'fetchList',
- 'deleteRepo',
- ]),
+ },
+ data() {
+ return {
+ isOpen: false,
+ };
+ },
+ methods: {
+ ...mapActions(['fetchRepos', 'fetchList', 'deleteRepo']),
- toggleRepo() {
- this.isOpen = !this.isOpen;
+ toggleRepo() {
+ this.isOpen = !this.isOpen;
- if (this.isOpen) {
- this.fetchList({ repo: this.repo })
- .catch(() => this.showError(errorMessagesTypes.FETCH_REGISTRY));
- }
- },
+ if (this.isOpen) {
+ this.fetchList({ repo: this.repo }).catch(() =>
+ this.showError(errorMessagesTypes.FETCH_REGISTRY),
+ );
+ }
+ },
- handleDeleteRepository() {
- this.deleteRepo(this.repo)
- .then(() => {
- Flash(__('This container registry has been scheduled for deletion.'), 'notice');
- this.fetchRepos();
- })
- .catch(() => this.showError(errorMessagesTypes.DELETE_REPO));
- },
+ handleDeleteRepository() {
+ this.deleteRepo(this.repo)
+ .then(() => {
+ Flash(__('This container registry has been scheduled for deletion.'), 'notice');
+ this.fetchRepos();
+ })
+ .catch(() => this.showError(errorMessagesTypes.DELETE_REPO));
+ },
- showError(message) {
- Flash(errorMessages[message]);
- },
+ showError(message) {
+ Flash(errorMessages[message]);
},
- };
+ },
+};
</script>
<template>
<div class="container-image">
<div class="container-image-head">
- <button
- type="button"
- class="js-toggle-repo btn-link"
- @click="toggleRepo"
- >
+ <button type="button" class="js-toggle-repo btn-link" @click="toggleRepo">
<i
:class="{
'fa-chevron-right': !isOpen,
@@ -88,44 +83,26 @@
<div class="controls d-none d-sm-block float-right">
<button
- v-tooltip
v-if="repo.canDelete"
+ v-tooltip
:title="s__('ContainerRegistry|Remove repository')"
:aria-label="s__('ContainerRegistry|Remove repository')"
type="button"
class="js-remove-repo btn btn-danger"
@click="handleDeleteRepository"
>
- <i
- class="fa fa-trash"
- aria-hidden="true"
- >
- </i>
+ <i class="fa fa-trash" aria-hidden="true"> </i>
</button>
</div>
</div>
- <gl-loading-icon
- v-if="repo.isLoading"
- :size="2"
- class="append-bottom-20"
- />
+ <gl-loading-icon v-if="repo.isLoading" :size="2" class="append-bottom-20" />
- <div
- v-else-if="!repo.isLoading && isOpen"
- class="container-image-tags"
- >
-
- <table-registry
- v-if="repo.list.length"
- :repo="repo"
- />
+ <div v-else-if="!repo.isLoading && isOpen" class="container-image-tags">
+ <table-registry v-if="repo.list.length" :repo="repo" />
- <div
- v-else
- class="nothing-here-block"
- >
- {{ s__("ContainerRegistry|No tags in Container Registry for this container image.") }}
+ <div v-else class="nothing-here-block">
+ {{ s__('ContainerRegistry|No tags in Container Registry for this container image.') }}
</div>
</div>
</div>
diff --git a/app/assets/javascripts/registry/components/table_registry.vue b/app/assets/javascripts/registry/components/table_registry.vue
index 9f4973c3490..6735c3ff7cf 100644
--- a/app/assets/javascripts/registry/components/table_registry.vue
+++ b/app/assets/javascripts/registry/components/table_registry.vue
@@ -1,66 +1,62 @@
<script>
- import { mapActions } from 'vuex';
- import { n__ } from '../../locale';
- import Flash from '../../flash';
- import clipboardButton from '../../vue_shared/components/clipboard_button.vue';
- import tablePagination from '../../vue_shared/components/table_pagination.vue';
- import tooltip from '../../vue_shared/directives/tooltip';
- import timeagoMixin from '../../vue_shared/mixins/timeago';
- import { errorMessages, errorMessagesTypes } from '../constants';
- import { numberToHumanSize } from '../../lib/utils/number_utils';
+import { mapActions } from 'vuex';
+import { n__ } from '../../locale';
+import Flash from '../../flash';
+import clipboardButton from '../../vue_shared/components/clipboard_button.vue';
+import tablePagination from '../../vue_shared/components/table_pagination.vue';
+import tooltip from '../../vue_shared/directives/tooltip';
+import timeagoMixin from '../../vue_shared/mixins/timeago';
+import { errorMessages, errorMessagesTypes } from '../constants';
+import { numberToHumanSize } from '../../lib/utils/number_utils';
- export default {
- components: {
- clipboardButton,
- tablePagination,
+export default {
+ components: {
+ clipboardButton,
+ tablePagination,
+ },
+ directives: {
+ tooltip,
+ },
+ mixins: [timeagoMixin],
+ props: {
+ repo: {
+ type: Object,
+ required: true,
},
- directives: {
- tooltip,
+ },
+ computed: {
+ shouldRenderPagination() {
+ return this.repo.pagination.total > this.repo.pagination.perPage;
},
- mixins: [
- timeagoMixin,
- ],
- props: {
- repo: {
- type: Object,
- required: true,
- },
- },
- computed: {
- shouldRenderPagination() {
- return this.repo.pagination.total > this.repo.pagination.perPage;
- },
- },
- methods: {
- ...mapActions([
- 'fetchList',
- 'deleteRegistry',
- ]),
+ },
+ methods: {
+ ...mapActions(['fetchList', 'deleteRegistry']),
- layers(item) {
- return item.layers ? n__('%d layer', '%d layers', item.layers) : '';
- },
+ layers(item) {
+ return item.layers ? n__('%d layer', '%d layers', item.layers) : '';
+ },
- formatSize(size) {
- return numberToHumanSize(size);
- },
+ formatSize(size) {
+ return numberToHumanSize(size);
+ },
- handleDeleteRegistry(registry) {
- this.deleteRegistry(registry)
- .then(() => this.fetchList({ repo: this.repo }))
- .catch(() => this.showError(errorMessagesTypes.DELETE_REGISTRY));
- },
+ handleDeleteRegistry(registry) {
+ this.deleteRegistry(registry)
+ .then(() => this.fetchList({ repo: this.repo }))
+ .catch(() => this.showError(errorMessagesTypes.DELETE_REGISTRY));
+ },
- onPageChange(pageNumber) {
- this.fetchList({ repo: this.repo, page: pageNumber })
- .catch(() => this.showError(errorMessagesTypes.FETCH_REGISTRY));
- },
+ onPageChange(pageNumber) {
+ this.fetchList({ repo: this.repo, page: pageNumber }).catch(() =>
+ this.showError(errorMessagesTypes.FETCH_REGISTRY),
+ );
+ },
- showError(message) {
- Flash(errorMessages[message]);
- },
+ showError(message) {
+ Flash(errorMessages[message]);
},
- };
+ },
+};
</script>
<template>
<div>
@@ -69,17 +65,14 @@
<tr>
<th>{{ s__('ContainerRegistry|Tag') }}</th>
<th>{{ s__('ContainerRegistry|Tag ID') }}</th>
- <th>{{ s__("ContainerRegistry|Size") }}</th>
- <th>{{ s__("ContainerRegistry|Created") }}</th>
+ <th>{{ s__('ContainerRegistry|Size') }}</th>
+ <th>{{ s__('ContainerRegistry|Created') }}</th>
<th></th>
</tr>
</thead>
<tbody>
- <tr
- v-for="(item, i) in repo.list"
- :key="i">
+ <tr v-for="(item, i) in repo.list" :key="i">
<td>
-
{{ item.tag }}
<clipboard-button
@@ -90,11 +83,7 @@
/>
</td>
<td>
- <span
- v-tooltip
- :title="item.revision"
- data-placement="bottom"
- >
+ <span v-tooltip :title="item.revision" data-placement="bottom">
{{ item.shortRevision }}
</span>
</td>
@@ -107,31 +96,23 @@
</td>
<td>
- <span
- v-tooltip
- :title="tooltipTitle(item.createdAt)"
- data-placement="bottom"
- >
+ <span v-tooltip :title="tooltipTitle(item.createdAt)" data-placement="bottom">
{{ timeFormated(item.createdAt) }}
</span>
</td>
<td class="content">
<button
- v-tooltip
v-if="item.canDelete"
+ v-tooltip
:title="s__('ContainerRegistry|Remove tag')"
:aria-label="s__('ContainerRegistry|Remove tag')"
type="button"
class="js-delete-registry btn btn-danger d-none d-sm-block float-right"
data-container="body"
- @click="handleDeleteRegistry(item)"
+ @click="handleDeleteRegistry(item);"
>
- <i
- class="fa fa-trash"
- aria-hidden="true"
- >
- </i>
+ <i class="fa fa-trash" aria-hidden="true"> </i>
</button>
</td>
</tr>
diff --git a/app/assets/javascripts/registry/index.js b/app/assets/javascripts/registry/index.js
index e15cd94a915..025afefe7f0 100644
--- a/app/assets/javascripts/registry/index.js
+++ b/app/assets/javascripts/registry/index.js
@@ -4,22 +4,23 @@ import Translate from '../vue_shared/translate';
Vue.use(Translate);
-export default () => new Vue({
- el: '#js-vue-registry-images',
- components: {
- registryApp,
- },
- data() {
- const { dataset } = document.querySelector(this.$options.el);
- return {
- endpoint: dataset.endpoint,
- };
- },
- render(createElement) {
- return createElement('registry-app', {
- props: {
- endpoint: this.endpoint,
- },
- });
- },
-});
+export default () =>
+ new Vue({
+ el: '#js-vue-registry-images',
+ components: {
+ registryApp,
+ },
+ data() {
+ const { dataset } = document.querySelector(this.$options.el);
+ return {
+ endpoint: dataset.endpoint,
+ };
+ },
+ render(createElement) {
+ return createElement('registry-app', {
+ props: {
+ endpoint: this.endpoint,
+ },
+ });
+ },
+ });
diff --git a/app/assets/javascripts/registry/stores/mutations.js b/app/assets/javascripts/registry/stores/mutations.js
index 208c3c39866..69c051cd2d6 100644
--- a/app/assets/javascripts/registry/stores/mutations.js
+++ b/app/assets/javascripts/registry/stores/mutations.js
@@ -2,7 +2,6 @@ import * as types from './mutation_types';
import { parseIntPagination, normalizeHeaders } from '../../lib/utils/common_utils';
export default {
-
[types.SET_MAIN_ENDPOINT](state, endpoint) {
Object.assign(state, { endpoint });
},
diff --git a/app/assets/javascripts/reports/components/grouped_test_reports_app.vue b/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
index 7b37f4e9a97..82601363aa4 100644
--- a/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
+++ b/app/assets/javascripts/reports/components/grouped_test_reports_app.vue
@@ -1,79 +1,72 @@
<script>
- import { mapActions, mapGetters, mapState } from 'vuex';
- import { s__ } from '~/locale';
- import { componentNames } from './issue_body';
- import ReportSection from './report_section.vue';
- import SummaryRow from './summary_row.vue';
- import IssuesList from './issues_list.vue';
- import Modal from './modal.vue';
- import createStore from '../store';
- import { summaryTextBuilder, reportTextBuilder, statusIcon } from '../store/utils';
+import { mapActions, mapGetters, mapState } from 'vuex';
+import { s__ } from '~/locale';
+import { componentNames } from './issue_body';
+import ReportSection from './report_section.vue';
+import SummaryRow from './summary_row.vue';
+import IssuesList from './issues_list.vue';
+import Modal from './modal.vue';
+import createStore from '../store';
+import { summaryTextBuilder, reportTextBuilder, statusIcon } from '../store/utils';
- export default {
- name: 'GroupedTestReportsApp',
- store: createStore(),
- components: {
- ReportSection,
- SummaryRow,
- IssuesList,
- Modal,
+export default {
+ name: 'GroupedTestReportsApp',
+ store: createStore(),
+ components: {
+ ReportSection,
+ SummaryRow,
+ IssuesList,
+ Modal,
+ },
+ props: {
+ endpoint: {
+ type: String,
+ required: true,
},
- props: {
- endpoint: {
- type: String,
- required: true,
- },
- },
- componentNames,
- computed: {
- ...mapState([
- 'reports',
- 'isLoading',
- 'hasError',
- 'summary',
- ]),
- ...mapState({
- modalTitle: state => state.modal.title || '',
- modalData: state => state.modal.data || {},
- }),
- ...mapGetters([
- 'summaryStatus',
- ]),
- groupedSummaryText() {
- if (this.isLoading) {
- return s__('Reports|Test summary results are being parsed');
- }
+ },
+ componentNames,
+ computed: {
+ ...mapState(['reports', 'isLoading', 'hasError', 'summary']),
+ ...mapState({
+ modalTitle: state => state.modal.title || '',
+ modalData: state => state.modal.data || {},
+ }),
+ ...mapGetters(['summaryStatus']),
+ groupedSummaryText() {
+ if (this.isLoading) {
+ return s__('Reports|Test summary results are being parsed');
+ }
- if (this.hasError) {
- return s__('Reports|Test summary failed loading results');
- }
+ if (this.hasError) {
+ return s__('Reports|Test summary failed loading results');
+ }
- return summaryTextBuilder(s__('Reports|Test summary'), this.summary);
- },
+ return summaryTextBuilder(s__('Reports|Test summary'), this.summary);
},
- created() {
- this.setEndpoint(this.endpoint);
+ },
+ created() {
+ this.setEndpoint(this.endpoint);
- this.fetchReports();
+ this.fetchReports();
+ },
+ methods: {
+ ...mapActions(['setEndpoint', 'fetchReports']),
+ reportText(report) {
+ const summary = report.summary || {};
+ return reportTextBuilder(report.name, summary);
+ },
+ getReportIcon(report) {
+ return statusIcon(report.status);
},
- methods: {
- ...mapActions(['setEndpoint', 'fetchReports']),
- reportText(report) {
- const summary = report.summary || {};
- return reportTextBuilder(report.name, summary);
- },
- getReportIcon(report) {
- return statusIcon(report.status);
- },
- shouldRenderIssuesList(report) {
- return (
- report.existing_failures.length > 0 ||
- report.new_failures.length > 0 ||
- report.resolved_failures.length > 0
- );
- },
+ shouldRenderIssuesList(report) {
+ return (
+ report.existing_failures.length > 0 ||
+ report.new_failures.length > 0 ||
+ report.resolved_failures.length > 0
+ );
},
- };
+ },
+};
</script>
<template>
<report-section
@@ -82,35 +75,27 @@
:loading-text="groupedSummaryText"
:error-text="groupedSummaryText"
:has-issues="reports.length > 0"
- class="mr-widget-border-top grouped-security-reports mr-report"
+ class="mr-widget-section grouped-security-reports mr-report"
>
- <div
- slot="body"
- class="mr-widget-grouped-section report-block"
- >
- <template
- v-for="(report, i) in reports"
- >
+ <div slot="body" class="mr-widget-grouped-section report-block">
+ <template v-for="(report, i) in reports">
<summary-row
+ :key="`summary-row-${i}`"
:summary="reportText(report)"
:status-icon="getReportIcon(report)"
- :key="`summary-row-${i}`"
/>
<issues-list
v-if="shouldRenderIssuesList(report)"
+ :key="`issues-list-${i}`"
:unresolved-issues="report.existing_failures"
:new-issues="report.new_failures"
:resolved-issues="report.resolved_failures"
- :key="`issues-list-${i}`"
:component="$options.componentNames.TestIssueBody"
class="report-block-group-list"
/>
</template>
- <modal
- :title="modalTitle"
- :modal-data="modalData"
- />
+ <modal :title="modalTitle" :modal-data="modalData" />
</div>
</report-section>
</template>
diff --git a/app/assets/javascripts/reports/components/issue_status_icon.vue b/app/assets/javascripts/reports/components/issue_status_icon.vue
index 85811698a37..2946fbc6a1f 100644
--- a/app/assets/javascripts/reports/components/issue_status_icon.vue
+++ b/app/assets/javascripts/reports/components/issue_status_icon.vue
@@ -1,10 +1,6 @@
<script>
import Icon from '~/vue_shared/components/icon.vue';
-import {
- STATUS_FAILED,
- STATUS_NEUTRAL,
- STATUS_SUCCESS,
-} from '../constants';
+import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '../constants';
export default {
name: 'IssueStatusIcon',
@@ -49,9 +45,6 @@ export default {
}"
class="report-block-list-icon"
>
- <icon
- :name="iconName"
- :size="32"
- />
+ <icon :name="iconName" :size="32" />
</div>
</template>
diff --git a/app/assets/javascripts/reports/components/issues_list.vue b/app/assets/javascripts/reports/components/issues_list.vue
index df42201b5de..f4243522ef8 100644
--- a/app/assets/javascripts/reports/components/issues_list.vue
+++ b/app/assets/javascripts/reports/components/issues_list.vue
@@ -1,22 +1,31 @@
<script>
-import IssuesBlock from '~/reports/components/report_issues.vue';
-import {
- STATUS_SUCCESS,
- STATUS_FAILED,
- STATUS_NEUTRAL,
-} from '~/reports/constants';
+import ReportItem from '~/reports/components/report_item.vue';
+import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/reports/constants';
+import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
+
+const wrapIssueWithState = (status, isNew = false) => issue => ({
+ status: issue.status || status,
+ isNew,
+ issue,
+});
/**
* Renders block of issues
*/
-
export default {
components: {
- IssuesBlock,
+ SmartVirtualList,
+ ReportItem,
},
- success: STATUS_SUCCESS,
- failed: STATUS_FAILED,
- neutral: STATUS_NEUTRAL,
+ // Typical height of a report item in px
+ typicalReportItemHeight: 32,
+ /*
+ The maximum amount of shown issues. This is calculated by
+ ( max-height of report-block-list / typicalReportItemHeight ) + some safety margin
+ We will use VirtualList if we have more items than this number.
+ For entries lower than this number, the virtual scroll list calculates the total height of the element wrongly.
+ */
+ maxShownReportItems: 20,
props: {
newIssues: {
type: Array,
@@ -44,42 +53,34 @@ export default {
default: '',
},
},
+ computed: {
+ issuesWithState() {
+ return [
+ ...this.newIssues.map(wrapIssueWithState(STATUS_FAILED, true)),
+ ...this.unresolvedIssues.map(wrapIssueWithState(STATUS_FAILED)),
+ ...this.neutralIssues.map(wrapIssueWithState(STATUS_NEUTRAL)),
+ ...this.resolvedIssues.map(wrapIssueWithState(STATUS_SUCCESS)),
+ ];
+ },
+ },
};
</script>
<template>
- <div class="report-block-container">
-
- <issues-block
- v-if="newIssues.length"
- :component="component"
- :issues="newIssues"
- class="js-mr-code-new-issues"
- status="failed"
- is-new
- />
-
- <issues-block
- v-if="unresolvedIssues.length"
- :component="component"
- :issues="unresolvedIssues"
- :status="$options.failed"
- class="js-mr-code-new-issues"
- />
-
- <issues-block
- v-if="neutralIssues.length"
- :component="component"
- :issues="neutralIssues"
- :status="$options.neutral"
- class="js-mr-code-non-issues"
- />
-
- <issues-block
- v-if="resolvedIssues.length"
+ <smart-virtual-list
+ :length="issuesWithState.length"
+ :remain="$options.maxShownReportItems"
+ :size="$options.typicalReportItemHeight"
+ class="report-block-container"
+ wtag="ul"
+ wclass="report-block-list"
+ >
+ <report-item
+ v-for="(wrapped, index) in issuesWithState"
+ :key="index"
+ :issue="wrapped.issue"
+ :status="wrapped.status"
:component="component"
- :issues="resolvedIssues"
- :status="$options.success"
- class="js-mr-code-resolved-issues"
+ :is-new="wrapped.isNew"
/>
- </div>
+ </smart-virtual-list>
</template>
diff --git a/app/assets/javascripts/reports/components/modal.vue b/app/assets/javascripts/reports/components/modal.vue
index acc5c6d85e2..162421b037f 100644
--- a/app/assets/javascripts/reports/components/modal.vue
+++ b/app/assets/javascripts/reports/components/modal.vue
@@ -1,27 +1,27 @@
<script>
- import Modal from '~/vue_shared/components/gl_modal.vue';
- import LoadingButton from '~/vue_shared/components/loading_button.vue';
- import CodeBlock from '~/vue_shared/components/code_block.vue';
- import { fieldTypes } from '../constants';
+import Modal from '~/vue_shared/components/gl_modal.vue';
+import LoadingButton from '~/vue_shared/components/loading_button.vue';
+import CodeBlock from '~/vue_shared/components/code_block.vue';
+import { fieldTypes } from '../constants';
- export default {
- components: {
- Modal,
- LoadingButton,
- CodeBlock,
+export default {
+ components: {
+ Modal,
+ LoadingButton,
+ CodeBlock,
+ },
+ props: {
+ title: {
+ type: String,
+ required: true,
},
- props: {
- title: {
- type: String,
- required: true,
- },
- modalData: {
- type: Object,
- required: true,
- },
+ modalData: {
+ type: Object,
+ required: true,
},
- fieldTypes,
- };
+ },
+ fieldTypes,
+};
</script>
<template>
<modal
@@ -36,23 +36,13 @@
:key="index"
class="row prepend-top-10 append-bottom-10"
>
- <strong class="col-sm-3 text-right">
- {{ field.text }}:
- </strong>
+ <strong class="col-sm-3 text-right"> {{ field.text }}: </strong>
<div class="col-sm-9 text-secondary">
- <code-block
- v-if="field.type === $options.fieldTypes.codeBock"
- :code="field.value"
- />
+ <code-block v-if="field.type === $options.fieldTypes.codeBock" :code="field.value" />
<template v-else-if="field.type === $options.fieldTypes.link">
- <a
- :href="field.value"
- target="_blank"
- rel="noopener noreferrer"
- class="js-modal-link"
- >
+ <a :href="field.value" target="_blank" rel="noopener noreferrer" class="js-modal-link">
{{ field.value }}
</a>
</template>
@@ -67,7 +57,6 @@
</div>
</div>
</slot>
- <div slot="footer">
- </div>
+ <div slot="footer"></div>
</modal>
</template>
diff --git a/app/assets/javascripts/reports/components/modal_open_name.vue b/app/assets/javascripts/reports/components/modal_open_name.vue
index 4f81cee2a38..118e4b02c46 100644
--- a/app/assets/javascripts/reports/components/modal_open_name.vue
+++ b/app/assets/javascripts/reports/components/modal_open_name.vue
@@ -26,7 +26,7 @@ export default {
<button
type="button"
class="btn-link btn-blank text-left break-link vulnerability-name-button"
- @click="handleIssueClick()"
+ @click="handleIssueClick();"
>
{{ issue.title }}
</button>
diff --git a/app/assets/javascripts/reports/components/report_issues.vue b/app/assets/javascripts/reports/components/report_issues.vue
deleted file mode 100644
index c553a374f66..00000000000
--- a/app/assets/javascripts/reports/components/report_issues.vue
+++ /dev/null
@@ -1,59 +0,0 @@
-<script>
-import IssueStatusIcon from '~/reports/components/issue_status_icon.vue';
-import { components, componentNames } from '~/reports/components/issue_body';
-
-export default {
- name: 'ReportIssues',
- components: {
- IssueStatusIcon,
- ...components,
- },
- props: {
- issues: {
- type: Array,
- required: true,
- },
- component: {
- type: String,
- required: false,
- default: '',
- validator: value => value === '' || Object.values(componentNames).includes(value),
- },
- // failed || success
- status: {
- type: String,
- required: true,
- },
- isNew: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
-};
-</script>
-<template>
- <div>
- <ul class="report-block-list">
- <li
- v-for="(issue, index) in issues"
- :class="{ 'is-dismissed': issue.isDismissed }"
- :key="index"
- class="report-block-list-issue"
- >
- <issue-status-icon
- :status="issue.status || status"
- class="append-right-5"
- />
-
- <component
- v-if="component"
- :is="component"
- :issue="issue"
- :status="issue.status || status"
- :is-new="isNew"
- />
- </li>
- </ul>
- </div>
-</template>
diff --git a/app/assets/javascripts/reports/components/report_item.vue b/app/assets/javascripts/reports/components/report_item.vue
new file mode 100644
index 00000000000..839e86bdf17
--- /dev/null
+++ b/app/assets/javascripts/reports/components/report_item.vue
@@ -0,0 +1,41 @@
+<script>
+import IssueStatusIcon from '~/reports/components/issue_status_icon.vue';
+import { components, componentNames } from '~/reports/components/issue_body';
+
+export default {
+ name: 'ReportItem',
+ components: {
+ IssueStatusIcon,
+ ...components,
+ },
+ props: {
+ issue: {
+ type: Object,
+ required: true,
+ },
+ component: {
+ type: String,
+ required: false,
+ default: '',
+ validator: value => value === '' || Object.values(componentNames).includes(value),
+ },
+ // failed || success
+ status: {
+ type: String,
+ required: true,
+ },
+ isNew: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+};
+</script>
+<template>
+ <li :class="{ 'is-dismissed': issue.isDismissed }" class="report-block-list-issue">
+ <issue-status-icon :status="status" class="append-right-5" />
+
+ <component :is="component" v-if="component" :issue="issue" :status="status" :is-new="isNew" />
+ </li>
+</template>
diff --git a/app/assets/javascripts/reports/components/report_link.vue b/app/assets/javascripts/reports/components/report_link.vue
index 74d68f9f439..052bc53d610 100644
--- a/app/assets/javascripts/reports/components/report_link.vue
+++ b/app/assets/javascripts/reports/components/report_link.vue
@@ -20,10 +20,16 @@ export default {
rel="noopener noreferrer nofollow"
class="break-link"
>
- {{ issue.path }}<template v-if="issue.line">:{{ issue.line }}</template>
+ {{ issue.path
+ }}<template v-if="issue.line"
+ >:{{ issue.line }}</template
+ >
</a>
<template v-else>
- {{ issue.path }}<template v-if="issue.line">:{{ issue.line }}</template>
+ {{ issue.path
+ }}<template v-if="issue.line"
+ >:{{ issue.line }}</template
+ >
</template>
</div>
</template>
diff --git a/app/assets/javascripts/reports/components/report_section.vue b/app/assets/javascripts/reports/components/report_section.vue
index dc609d6f90e..d6483e95278 100644
--- a/app/assets/javascripts/reports/components/report_section.vue
+++ b/app/assets/javascripts/reports/components/report_section.vue
@@ -139,15 +139,11 @@ export default {
<section class="media-section">
<div class="media">
<status-icon :status="statusIconName" />
- <div class="media-body space-children d-flex flex-align-self-center">
+ <div class="media-body d-flex flex-align-self-center">
<span class="js-code-text code-text">
{{ headerText }}
- <popover
- v-if="hasPopover"
- :options="popoverOptions"
- class="prepend-left-5"
- />
+ <popover v-if="hasPopover" :options="popoverOptions" class="prepend-left-5" />
</span>
<slot name="actionButtons"></slot>
@@ -163,11 +159,7 @@ export default {
</div>
</div>
- <div
- v-if="hasIssues"
- v-show="isExpanded"
- class="js-report-section-container"
- >
+ <div v-if="hasIssues" v-show="isExpanded" class="js-report-section-container">
<slot name="body">
<issues-list
:unresolved-issues="unresolvedIssues"
diff --git a/app/assets/javascripts/reports/components/summary_row.vue b/app/assets/javascripts/reports/components/summary_row.vue
index 51188981bed..97a68531d29 100644
--- a/app/assets/javascripts/reports/components/summary_row.vue
+++ b/app/assets/javascripts/reports/components/summary_row.vue
@@ -1,6 +1,7 @@
<script>
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import Popover from '~/vue_shared/components/help_popover.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
/**
* Renders the summary row for each report
@@ -15,6 +16,7 @@ export default {
components: {
CiIcon,
Popover,
+ GlLoadingIcon,
},
props: {
summary: {
@@ -44,26 +46,14 @@ export default {
<template>
<div class="report-block-list-issue report-block-list-issue-parent">
<div class="report-block-list-icon append-right-10 prepend-left-5">
- <gl-loading-icon
- v-if="statusIcon === 'loading'"
- css-class="report-block-list-loading-icon"
- />
- <ci-icon
- v-else
- :status="iconStatus"
- />
+ <gl-loading-icon v-if="statusIcon === 'loading'" css-class="report-block-list-loading-icon" />
+ <ci-icon v-else :status="iconStatus" />
</div>
<div class="report-block-list-issue-description">
- <div class="report-block-list-issue-description-text">
- {{ summary }}
- </div>
-
- <popover
- v-if="popoverOptions"
- :options="popoverOptions"
- />
+ <div class="report-block-list-issue-description-text">{{ summary }}</div>
+ <popover v-if="popoverOptions" :options="popoverOptions" />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/reports/components/test_issue_body.vue b/app/assets/javascripts/reports/components/test_issue_body.vue
index cd443a49b52..938e83de546 100644
--- a/app/assets/javascripts/reports/components/test_issue_body.vue
+++ b/app/assets/javascripts/reports/components/test_issue_body.vue
@@ -1,28 +1,28 @@
<script>
- import { mapActions } from 'vuex';
+import { mapActions } from 'vuex';
- export default {
- name: 'TestIssueBody',
- props: {
- issue: {
- type: Object,
- required: true,
- },
- // failed || success
- status: {
- type: String,
- required: true,
- },
- isNew: {
- type: Boolean,
- required: false,
- default: false,
- },
+export default {
+ name: 'TestIssueBody',
+ props: {
+ issue: {
+ type: Object,
+ required: true,
},
- methods: {
- ...mapActions(['openModal']),
+ // failed || success
+ status: {
+ type: String,
+ required: true,
},
- };
+ isNew: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ methods: {
+ ...mapActions(['openModal']),
+ },
+};
</script>
<template>
<div class="report-block-list-issue-description prepend-top-5 append-bottom-5">
@@ -30,14 +30,10 @@
<button
type="button"
class="btn-link btn-blank text-left break-link vulnerability-name-button"
- @click="openModal({ issue })"
+ @click="openModal({ issue });"
>
- <div
- v-if="isNew"
- class="badge badge-danger append-right-5"
- >
- {{ s__('New') }}
- </div>{{ issue.name }}
+ <div v-if="isNew" class="badge badge-danger append-right-5">{{ s__('New') }}</div>
+ {{ issue.name }}
</button>
</div>
</div>
diff --git a/app/assets/javascripts/reports/store/actions.js b/app/assets/javascripts/reports/store/actions.js
index acabcc1d193..db8ab5ccb80 100644
--- a/app/assets/javascripts/reports/store/actions.js
+++ b/app/assets/javascripts/reports/store/actions.js
@@ -43,9 +43,11 @@ export const fetchReports = ({ state, dispatch }) => {
},
data: state.endpoint,
method: 'getReports',
- successCallback: ({ data, status }) => dispatch('receiveReportsSuccess', {
- data, status,
- }),
+ successCallback: ({ data, status }) =>
+ dispatch('receiveReportsSuccess', {
+ data,
+ status,
+ }),
errorCallback: () => dispatch('receiveReportsError'),
});
diff --git a/app/assets/javascripts/reports/store/index.js b/app/assets/javascripts/reports/store/index.js
index 9d8f7dc3b74..467c692b438 100644
--- a/app/assets/javascripts/reports/store/index.js
+++ b/app/assets/javascripts/reports/store/index.js
@@ -7,9 +7,10 @@ import state from './state';
Vue.use(Vuex);
-export default () => new Vuex.Store({
- actions,
- mutations,
- getters,
- state: state(),
-});
+export default () =>
+ new Vuex.Store({
+ actions,
+ mutations,
+ getters,
+ state: state(),
+ });
diff --git a/app/assets/javascripts/reports/store/mutation_types.js b/app/assets/javascripts/reports/store/mutation_types.js
index 82bda31df5d..599d4862dfe 100644
--- a/app/assets/javascripts/reports/store/mutation_types.js
+++ b/app/assets/javascripts/reports/store/mutation_types.js
@@ -4,4 +4,3 @@ export const REQUEST_REPORTS = 'REQUEST_REPORTS';
export const RECEIVE_REPORTS_SUCCESS = 'RECEIVE_REPORTS_SUCCESS';
export const RECEIVE_REPORTS_ERROR = 'RECEIVE_REPORTS_ERROR';
export const SET_ISSUE_MODAL_DATA = 'SET_ISSUE_MODAL_DATA';
-
diff --git a/app/assets/javascripts/reports/store/mutations.js b/app/assets/javascripts/reports/store/mutations.js
index b88bff97075..2a37f5b74fa 100644
--- a/app/assets/javascripts/reports/store/mutations.js
+++ b/app/assets/javascripts/reports/store/mutations.js
@@ -19,7 +19,6 @@ export default {
state.status = response.status;
state.reports = response.suites;
-
},
[types.RECEIVE_REPORTS_ERROR](state) {
state.isLoading = false;
@@ -36,7 +35,7 @@ export default {
[types.SET_ISSUE_MODAL_DATA](state, payload) {
state.modal.title = payload.issue.name;
- Object.keys(payload.issue).forEach((key) => {
+ Object.keys(payload.issue).forEach(key => {
if (Object.prototype.hasOwnProperty.call(state.modal.data, key)) {
state.modal.data[key] = {
...state.modal.data[key],
diff --git a/app/assets/javascripts/reports/store/state.js b/app/assets/javascripts/reports/store/state.js
index 4cab2e27a16..5484900276c 100644
--- a/app/assets/javascripts/reports/store/state.js
+++ b/app/assets/javascripts/reports/store/state.js
@@ -57,5 +57,4 @@ export default () => ({
},
},
},
-
});
diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js
index b27d635c6ac..225e21ad322 100644
--- a/app/assets/javascripts/right_sidebar.js
+++ b/app/assets/javascripts/right_sidebar.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, no-var, no-unused-vars, consistent-return, one-var, one-var-declaration-per-line, quotes, prefer-template, no-else-return, no-param-reassign, max-len */
+/* eslint-disable func-names, no-var, no-unused-vars, consistent-return, one-var, prefer-template, no-else-return, no-param-reassign */
import $ from 'jquery';
import _ from 'underscore';
@@ -21,7 +21,7 @@ Sidebar.initialize = function(currentUser) {
}
};
-Sidebar.prototype.removeListeners = function () {
+Sidebar.prototype.removeListeners = function() {
this.sidebar.off('click', '.sidebar-collapsed-icon');
this.sidebar.off('hidden.gl.dropdown');
$('.dropdown').off('loading.gl.dropdown');
@@ -38,10 +38,12 @@ Sidebar.prototype.addEventListeners = function() {
$('.dropdown').on('loaded.gl.dropdown', this.sidebarDropdownLoaded);
$document.on('click', '.js-sidebar-toggle', this.sidebarToggleClicked);
- return $(document).off('click', '.js-issuable-todo').on('click', '.js-issuable-todo', this.toggleTodo);
+ return $(document)
+ .off('click', '.js-issuable-todo')
+ .on('click', '.js-issuable-todo', this.toggleTodo);
};
-Sidebar.prototype.sidebarToggleClicked = function (e, triggered) {
+Sidebar.prototype.sidebarToggleClicked = function(e, triggered) {
var $allGutterToggleIcons, $this, isExpanded, tooltipLabel;
e.preventDefault();
$this = $(this);
@@ -51,20 +53,26 @@ Sidebar.prototype.sidebarToggleClicked = function (e, triggered) {
if (isExpanded) {
$allGutterToggleIcons.removeClass('fa-angle-double-right').addClass('fa-angle-double-left');
- $('aside.right-sidebar').removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed');
- $('.layout-page').removeClass('right-sidebar-expanded').addClass('right-sidebar-collapsed');
+ $('aside.right-sidebar')
+ .removeClass('right-sidebar-expanded')
+ .addClass('right-sidebar-collapsed');
+ $('.layout-page')
+ .removeClass('right-sidebar-expanded')
+ .addClass('right-sidebar-collapsed');
} else {
$allGutterToggleIcons.removeClass('fa-angle-double-left').addClass('fa-angle-double-right');
- $('aside.right-sidebar').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded');
- $('.layout-page').removeClass('right-sidebar-collapsed').addClass('right-sidebar-expanded');
-
- if (gl.lazyLoader) gl.lazyLoader.loadCheck();
+ $('aside.right-sidebar')
+ .removeClass('right-sidebar-collapsed')
+ .addClass('right-sidebar-expanded');
+ $('.layout-page')
+ .removeClass('right-sidebar-collapsed')
+ .addClass('right-sidebar-expanded');
}
$this.attr('data-original-title', tooltipLabel);
if (!triggered) {
- Cookies.set("collapsed_gutter", $('.right-sidebar').hasClass('right-sidebar-collapsed'));
+ Cookies.set('collapsed_gutter', $('.right-sidebar').hasClass('right-sidebar-collapsed'));
}
};
@@ -73,21 +81,27 @@ Sidebar.prototype.toggleTodo = function(e) {
$this = $(e.currentTarget);
ajaxType = $this.attr('data-delete-path') ? 'delete' : 'post';
if ($this.attr('data-delete-path')) {
- url = "" + ($this.attr('data-delete-path'));
+ url = '' + $this.attr('data-delete-path');
} else {
- url = "" + ($this.data('url'));
+ url = '' + $this.data('url');
}
$this.tooltip('hide');
- $('.js-issuable-todo').disable().addClass('is-loading');
+ $('.js-issuable-todo')
+ .disable()
+ .addClass('is-loading');
axios[ajaxType](url, {
issuable_id: $this.data('issuableId'),
issuable_type: $this.data('issuableType'),
- }).then(({ data }) => {
- this.todoUpdateDone(data);
- }).catch(() => flash(`There was an error ${ajaxType === 'post' ? 'adding a' : 'deleting the'} todo.`));
+ })
+ .then(({ data }) => {
+ this.todoUpdateDone(data);
+ })
+ .catch(() =>
+ flash(`There was an error ${ajaxType === 'post' ? 'adding a' : 'deleting the'} todo.`),
+ );
};
Sidebar.prototype.todoUpdateDone = function(data) {
@@ -101,7 +115,8 @@ Sidebar.prototype.todoUpdateDone = function(data) {
const $el = $(el);
const $elText = $el.find('.js-issuable-todo-inner');
- $el.removeClass('is-loading')
+ $el
+ .removeClass('is-loading')
.enable()
.attr('aria-label', $el.data(`${attrPrefix}Text`))
.attr('data-delete-path', deletePath)
@@ -121,7 +136,9 @@ Sidebar.prototype.todoUpdateDone = function(data) {
Sidebar.prototype.sidebarDropdownLoading = function(e) {
var $loading, $sidebarCollapsedIcon, i, img;
- $sidebarCollapsedIcon = $(this).closest('.block').find('.sidebar-collapsed-icon');
+ $sidebarCollapsedIcon = $(this)
+ .closest('.block')
+ .find('.sidebar-collapsed-icon');
img = $sidebarCollapsedIcon.find('img');
i = $sidebarCollapsedIcon.find('i');
$loading = $('<i class="fa fa-spinner fa-spin"></i>');
@@ -136,7 +153,9 @@ Sidebar.prototype.sidebarDropdownLoading = function(e) {
Sidebar.prototype.sidebarDropdownLoaded = function(e) {
var $sidebarCollapsedIcon, i, img;
- $sidebarCollapsedIcon = $(this).closest('.block').find('.sidebar-collapsed-icon');
+ $sidebarCollapsedIcon = $(this)
+ .closest('.block')
+ .find('.sidebar-collapsed-icon');
img = $sidebarCollapsedIcon.find('img');
$sidebarCollapsedIcon.find('i.fa-spin').remove();
i = $sidebarCollapsedIcon.find('i');
@@ -222,7 +241,7 @@ Sidebar.prototype.isOpen = function() {
};
Sidebar.prototype.getBlock = function(name) {
- return this.sidebar.find(".block." + name);
+ return this.sidebar.find('.block.' + name);
};
export default Sidebar;
diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js
index 50dd3c12382..0a4583b5861 100644
--- a/app/assets/javascripts/search_autocomplete.js
+++ b/app/assets/javascripts/search_autocomplete.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-return-assign, one-var, no-var, one-var-declaration-per-line, no-unused-vars, consistent-return, object-shorthand, prefer-template, class-methods-use-this, no-lonely-if, vars-on-top, max-len */
+/* eslint-disable no-return-assign, one-var, no-var, no-unused-vars, consistent-return, object-shorthand, prefer-template, class-methods-use-this, no-lonely-if, vars-on-top */
import $ from 'jquery';
import { escape, throttle } from 'underscore';
@@ -226,7 +226,7 @@ export class SearchAutocomplete {
icon,
text: term,
template: s__('SearchAutocomplete|in all GitLab'),
- url: `/search?search=${term}`,
+ url: `${gon.relative_url_root}/search?search=${term}`,
});
if (template) {
@@ -234,7 +234,9 @@ export class SearchAutocomplete {
icon,
text: term,
template,
- url: `/search?search=${term}&project_id=${this.projectInputEl.val()}&group_id=${this.groupInputEl.val()}`,
+ url: `${
+ gon.relative_url_root
+ }/search?search=${term}&project_id=${this.projectInputEl.val()}&group_id=${this.groupInputEl.val()}`,
});
}
}
@@ -251,7 +253,6 @@ export class SearchAutocomplete {
}
getCategoryContents() {
- const userId = gon.current_user_id;
const userName = gon.current_username;
const { projectOptions, groupOptions, dashboardOptions } = gl;
@@ -277,21 +278,21 @@ export class SearchAutocomplete {
const issueItems = [
{
text: s__('SearchAutocomplete|Issues assigned to me'),
- url: `${issuesPath}/?assignee_id=${userId}`,
+ url: `${issuesPath}/?assignee_username=${userName}`,
},
{
text: s__("SearchAutocomplete|Issues I've created"),
- url: `${issuesPath}/?author_id=${userId}`,
+ url: `${issuesPath}/?author_username=${userName}`,
},
];
const mergeRequestItems = [
{
text: s__('SearchAutocomplete|Merge requests assigned to me'),
- url: `${mrPath}/?assignee_id=${userId}`,
+ url: `${mrPath}/?assignee_username=${userName}`,
},
{
text: s__("SearchAutocomplete|Merge requests I've created"),
- url: `${mrPath}/?author_id=${userId}`,
+ url: `${mrPath}/?author_username=${userName}`,
},
];
diff --git a/app/assets/javascripts/set_status_modal/emoji_menu_in_modal.js b/app/assets/javascripts/set_status_modal/emoji_menu_in_modal.js
new file mode 100644
index 00000000000..14a89ef9293
--- /dev/null
+++ b/app/assets/javascripts/set_status_modal/emoji_menu_in_modal.js
@@ -0,0 +1,21 @@
+import { AwardsHandler } from '~/awards_handler';
+
+class EmojiMenuInModal extends AwardsHandler {
+ constructor(emoji, toggleButtonSelector, menuClass, selectEmojiCallback, targetContainerEl) {
+ super(emoji);
+
+ this.selectEmojiCallback = selectEmojiCallback;
+ this.toggleButtonSelector = toggleButtonSelector;
+ this.menuClass = menuClass;
+ this.targetContainerEl = targetContainerEl;
+
+ this.bindEvents();
+ }
+
+ postEmoji($emojiButton, awardUrl, selectedEmoji, callback) {
+ this.selectEmojiCallback(selectedEmoji, this.emoji.glEmojiTag(selectedEmoji));
+ callback();
+ }
+}
+
+export default EmojiMenuInModal;
diff --git a/app/assets/javascripts/set_status_modal/event_hub.js b/app/assets/javascripts/set_status_modal/event_hub.js
new file mode 100644
index 00000000000..0948c2e5352
--- /dev/null
+++ b/app/assets/javascripts/set_status_modal/event_hub.js
@@ -0,0 +1,3 @@
+import Vue from 'vue';
+
+export default new Vue();
diff --git a/app/assets/javascripts/set_status_modal/set_status_modal_trigger.vue b/app/assets/javascripts/set_status_modal/set_status_modal_trigger.vue
new file mode 100644
index 00000000000..0e8b6d93f42
--- /dev/null
+++ b/app/assets/javascripts/set_status_modal/set_status_modal_trigger.vue
@@ -0,0 +1,27 @@
+<script>
+import { s__ } from '~/locale';
+import eventHub from './event_hub';
+
+export default {
+ props: {
+ hasStatus: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ computed: {
+ buttonText() {
+ return this.hasStatus ? s__('SetStatusModal|Edit status') : s__('SetStatusModal|Set status');
+ },
+ },
+ methods: {
+ openModal() {
+ eventHub.$emit('openModal');
+ },
+ },
+};
+</script>
+
+<template>
+ <button type="button" class="btn menu-item" @click="openModal">{{ buttonText }}</button>
+</template>
diff --git a/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
new file mode 100644
index 00000000000..f04f7606976
--- /dev/null
+++ b/app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue
@@ -0,0 +1,231 @@
+<script>
+import $ from 'jquery';
+import createFlash from '~/flash';
+import Icon from '~/vue_shared/components/icon.vue';
+import GfmAutoComplete from '~/gfm_auto_complete';
+import { __, s__ } from '~/locale';
+import Api from '~/api';
+import { GlModal, GlTooltipDirective } from '@gitlab/ui';
+import eventHub from './event_hub';
+import EmojiMenuInModal from './emoji_menu_in_modal';
+
+const emojiMenuClass = 'js-modal-status-emoji-menu';
+
+export default {
+ components: {
+ Icon,
+ GlModal,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ currentEmoji: {
+ type: String,
+ required: true,
+ },
+ currentMessage: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ defaultEmojiTag: '',
+ emoji: this.currentEmoji,
+ emojiMenu: null,
+ emojiTag: '',
+ isEmojiMenuVisible: false,
+ message: this.currentMessage,
+ modalId: 'set-user-status-modal',
+ noEmoji: true,
+ };
+ },
+ computed: {
+ isDirty() {
+ return this.message.length || this.emoji.length;
+ },
+ },
+ mounted() {
+ eventHub.$on('openModal', this.openModal);
+ },
+ beforeDestroy() {
+ this.emojiMenu.destroy();
+ },
+ methods: {
+ openModal() {
+ this.$root.$emit('bv::show::modal', this.modalId);
+ },
+ closeModal() {
+ this.$root.$emit('bv::hide::modal', this.modalId);
+ },
+ setupEmojiListAndAutocomplete() {
+ const toggleEmojiMenuButtonSelector = '#set-user-status-modal .js-toggle-emoji-menu';
+ const emojiAutocomplete = new GfmAutoComplete();
+ emojiAutocomplete.setup($(this.$refs.statusMessageField), { emojis: true });
+
+ import(/* webpackChunkName: 'emoji' */ '~/emoji')
+ .then(Emoji => {
+ if (this.emoji) {
+ this.emojiTag = Emoji.glEmojiTag(this.emoji);
+ }
+ this.noEmoji = this.emoji === '';
+ this.defaultEmojiTag = Emoji.glEmojiTag('speech_balloon');
+
+ this.emojiMenu = new EmojiMenuInModal(
+ Emoji,
+ toggleEmojiMenuButtonSelector,
+ emojiMenuClass,
+ this.setEmoji,
+ this.$refs.userStatusForm,
+ );
+ })
+ .catch(() => createFlash(__('Failed to load emoji list.')));
+ },
+ showEmojiMenu() {
+ this.isEmojiMenuVisible = true;
+ this.emojiMenu.showEmojiMenu($(this.$refs.toggleEmojiMenuButton));
+ },
+ hideEmojiMenu() {
+ if (!this.isEmojiMenuVisible) {
+ return;
+ }
+
+ this.isEmojiMenuVisible = false;
+ this.emojiMenu.hideMenuElement($(`.${emojiMenuClass}`));
+ },
+ setDefaultEmoji() {
+ const { emojiTag } = this;
+ const hasStatusMessage = this.message;
+ if (hasStatusMessage && emojiTag) {
+ return;
+ }
+
+ if (hasStatusMessage) {
+ this.noEmoji = false;
+ this.emojiTag = this.defaultEmojiTag;
+ } else if (emojiTag === this.defaultEmojiTag) {
+ this.noEmoji = true;
+ this.clearEmoji();
+ }
+ },
+ setEmoji(emoji, emojiTag) {
+ this.emoji = emoji;
+ this.noEmoji = false;
+ this.clearEmoji();
+ this.emojiTag = emojiTag;
+ },
+ clearEmoji() {
+ if (this.emojiTag) {
+ this.emojiTag = '';
+ }
+ },
+ clearStatusInputs() {
+ this.emoji = '';
+ this.message = '';
+ this.noEmoji = true;
+ this.clearEmoji();
+ this.hideEmojiMenu();
+ },
+ removeStatus() {
+ this.clearStatusInputs();
+ this.setStatus();
+ },
+ setStatus() {
+ const { emoji, message } = this;
+
+ Api.postUserStatus({
+ emoji,
+ message,
+ })
+ .then(this.onUpdateSuccess)
+ .catch(this.onUpdateFail);
+ },
+ onUpdateSuccess() {
+ this.closeModal();
+ window.location.reload();
+ },
+ onUpdateFail() {
+ createFlash(
+ s__("SetStatusModal|Sorry, we weren't able to set your status. Please try again later."),
+ );
+
+ this.closeModal();
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-modal
+ :title="s__('SetStatusModal|Set a status')"
+ :modal-id="modalId"
+ :ok-title="s__('SetStatusModal|Set status')"
+ :cancel-title="s__('SetStatusModal|Remove status')"
+ ok-variant="success"
+ class="set-user-status-modal"
+ @shown="setupEmojiListAndAutocomplete"
+ @hide="hideEmojiMenu"
+ @ok="setStatus"
+ @cancel="removeStatus"
+ >
+ <div>
+ <input
+ v-model="emoji"
+ class="js-status-emoji-field"
+ type="hidden"
+ name="user[status][emoji]"
+ />
+ <div ref="userStatusForm" class="form-group position-relative m-0">
+ <div class="input-group">
+ <span class="input-group-btn">
+ <button
+ ref="toggleEmojiMenuButton"
+ v-gl-tooltip.bottom
+ :title="s__('SetStatusModal|Add status emoji')"
+ :aria-label="s__('SetStatusModal|Add status emoji')"
+ name="button"
+ type="button"
+ class="js-toggle-emoji-menu emoji-menu-toggle-button btn"
+ @click="showEmojiMenu"
+ >
+ <span v-html="emojiTag"></span>
+ <span
+ v-show="noEmoji"
+ class="js-no-emoji-placeholder no-emoji-placeholder position-relative"
+ >
+ <icon name="emoji_slightly_smiling_face" css-classes="award-control-icon-neutral" />
+ <icon name="emoji_smiley" css-classes="award-control-icon-positive" />
+ <icon name="emoji_smile" css-classes="award-control-icon-super-positive" />
+ </span>
+ </button>
+ </span>
+ <input
+ ref="statusMessageField"
+ v-model="message"
+ :placeholder="s__('SetStatusModal|What\'s your status?')"
+ type="text"
+ class="form-control form-control input-lg js-status-message-field"
+ name="user[status][message]"
+ @keyup="setDefaultEmoji"
+ @keyup.enter.prevent
+ @click="hideEmojiMenu"
+ />
+ <span v-show="isDirty" class="input-group-btn">
+ <button
+ v-gl-tooltip.bottom
+ :title="s__('SetStatusModal|Clear status')"
+ :aria-label="s__('SetStatusModal|Clear status')"
+ name="button"
+ type="button"
+ class="js-clear-user-status-button clear-user-status btn"
+ @click="clearStatusInputs();"
+ >
+ <icon name="close" />
+ </button>
+ </span>
+ </div>
+ </div>
+ </div>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/settings_panels.js b/app/assets/javascripts/settings_panels.js
index 37b4a2a4c63..d22aca35e09 100644
--- a/app/assets/javascripts/settings_panels.js
+++ b/app/assets/javascripts/settings_panels.js
@@ -1,21 +1,27 @@
import $ from 'jquery';
+import { __ } from './locale';
function expandSection($section) {
- $section.find('.js-settings-toggle').text('Collapse');
- $section.find('.settings-content').off('scroll.expandSection').scrollTop(0);
+ $section.find('.js-settings-toggle:not(.js-settings-toggle-trigger-only)').text(__('Collapse'));
+ $section
+ .find('.settings-content')
+ .off('scroll.expandSection')
+ .scrollTop(0);
$section.addClass('expanded');
if (!$section.hasClass('no-animate')) {
- $section.addClass('animating')
+ $section
+ .addClass('animating')
.one('animationend.animateSection', () => $section.removeClass('animating'));
}
}
function closeSection($section) {
- $section.find('.js-settings-toggle').text('Expand');
+ $section.find('.js-settings-toggle:not(.js-settings-toggle-trigger-only)').text(__('Expand'));
$section.find('.settings-content').on('scroll.expandSection', () => expandSection($section));
$section.removeClass('expanded');
if (!$section.hasClass('no-animate')) {
- $section.addClass('animating')
+ $section
+ .addClass('animating')
.one('animationend.animateSection', () => $section.removeClass('animating'));
}
}
diff --git a/app/assets/javascripts/shared/milestones/form.js b/app/assets/javascripts/shared/milestones/form.js
index 8681a1776c6..0ff84dc4667 100644
--- a/app/assets/javascripts/shared/milestones/form.js
+++ b/app/assets/javascripts/shared/milestones/form.js
@@ -15,5 +15,6 @@ export default (initGFM = true) => {
epics: initGFM,
milestones: initGFM,
labels: initGFM,
+ snippets: initGFM,
});
};
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue b/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue
index 284a258d3c9..0ad2b3a73a2 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue
@@ -32,18 +32,8 @@ export default {
<template>
<div class="title hide-collapsed">
{{ assigneeTitle }}
- <i
- v-if="loading"
- aria-hidden="true"
- class="fa fa-spinner fa-spin block-loading"
- >
-
- </i>
- <a
- v-if="editable"
- class="js-sidebar-dropdown-toggle edit-link float-right"
- href="#"
- >
+ <i v-if="loading" aria-hidden="true" class="fa fa-spinner fa-spin block-loading"> </i>
+ <a v-if="editable" class="js-sidebar-dropdown-toggle edit-link float-right" href="#">
{{ __('Edit') }}
</a>
<a
@@ -53,12 +43,7 @@ export default {
href="#"
role="button"
>
- <i
- aria-hidden="true"
- data-hidden="true"
- class="fa fa-angle-double-right"
- >
- </i>
+ <i aria-hidden="true" data-hidden="true" class="fa fa-angle-double-right"> </i>
</a>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignees.vue b/app/assets/javascripts/sidebar/components/assignees/assignees.vue
index dd155c133ce..d1a396182b3 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignees.vue
@@ -74,8 +74,8 @@ export default {
}
if (!this.users.length) {
- const emptyTooltipLabel = this.issuableType === 'issue' ?
- __('Assignee(s)') : __('Assignee');
+ const emptyTooltipLabel =
+ this.issuableType === 'issue' ? __('Assignee(s)') : __('Assignee');
names.push(emptyTooltipLabel);
}
@@ -133,12 +133,7 @@ export default {
data-placement="left"
data-boundary="viewport"
>
- <i
- v-if="hasNoUsers"
- aria-label="No Assignee"
- class="fa fa-user"
- >
- </i>
+ <i v-if="hasNoUsers" aria-label="No Assignee" class="fa fa-user"> </i>
<button
v-for="(user, index) in users"
v-if="shouldRenderCollapsedAssignee(index)"
@@ -152,20 +147,10 @@ export default {
width="24"
class="avatar avatar-inline s24"
/>
- <span class="author">
- {{ user.name }}
- </span>
+ <span class="author"> {{ user.name }} </span>
</button>
- <button
- v-if="hasMoreThanTwoAssignees"
- class="btn-link"
- type="button"
- >
- <span
- class="avatar-counter sidebar-avatar-counter"
- >
- {{ sidebarAvatarCounter }}
- </span>
+ <button v-if="hasMoreThanTwoAssignees" class="btn-link" type="button">
+ <span class="avatar-counter sidebar-avatar-counter"> {{ sidebarAvatarCounter }} </span>
</button>
</div>
<div class="value hide-collapsed">
@@ -173,34 +158,20 @@ export default {
<span class="assign-yourself no-value">
No assignee
<template v-if="editable">
- -
- <button
- type="button"
- class="btn-link"
- @click="assignSelf"
- >
- assign yourself
- </button>
+ - <button type="button" class="btn-link" @click="assignSelf">assign yourself</button>
</template>
</span>
</template>
<template v-else-if="hasOneUser">
- <a
- :href="assigneeUrl(firstUser)"
- class="author-link bold"
- >
+ <a :href="assigneeUrl(firstUser)" class="author-link bold">
<img
:alt="assigneeAlt(firstUser)"
:src="avatarUrl(firstUser)"
width="32"
class="avatar avatar-inline s32"
/>
- <span class="author">
- {{ firstUser.name }}
- </span>
- <span class="username">
- {{ assigneeUsername(firstUser) }}
- </span>
+ <span class="author"> {{ firstUser.name }} </span>
+ <span class="username"> {{ assigneeUsername(firstUser) }} </span>
</a>
</template>
<template v-else>
@@ -227,15 +198,8 @@ export default {
</a>
</div>
</div>
- <div
- v-if="renderShowMoreSection"
- class="user-list-more"
- >
- <button
- type="button"
- class="btn-link"
- @click="toggleShowLess"
- >
+ <div v-if="renderShowMoreSection" class="user-list-more">
+ <button type="button" class="btn-link" @click="toggleShowLess">
<template v-if="showLess">
{{ hiddenAssigneesLabel }}
</template>
@@ -248,4 +212,3 @@ export default {
</div>
</div>
</template>
-
diff --git a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
index 123c92aff64..cfa7029b388 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees.vue
@@ -69,7 +69,8 @@ export default {
this.loading = false;
}
- this.mediator.saveAssignees(this.field)
+ this.mediator
+ .saveAssignees(this.field)
.then(setLoadingFalse.bind(this))
.catch(() => {
setLoadingFalse();
diff --git a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
index 2b8d6207dea..597b723a9d9 100644
--- a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
@@ -56,11 +56,7 @@ export default {
.update('issue', { confidential })
.then(() => window.location.reload())
.catch(() => {
- Flash(
- __(
- 'Something went wrong trying to change the confidentiality of this issue',
- ),
- );
+ Flash(__('Something went wrong trying to change the confidentiality of this issue'));
});
},
},
@@ -78,10 +74,7 @@ export default {
data-boundary="viewport"
@click="toggleForm"
>
- <icon
- :name="confidentialityIcon"
- aria-hidden="true"
- />
+ <icon :name="confidentialityIcon" aria-hidden="true" />
</div>
<div class="title hide-collapsed">
{{ __('Confidentiality') }}
@@ -100,20 +93,11 @@ export default {
:is-confidential="isConfidential"
:update-confidential-attribute="updateConfidentialAttribute"
/>
- <div
- v-if="!isConfidential"
- class="no-value sidebar-item-value">
- <icon
- :size="16"
- name="eye"
- aria-hidden="true"
- class="sidebar-item-icon inline"
- />
+ <div v-if="!isConfidential" class="no-value sidebar-item-value">
+ <icon :size="16" name="eye" aria-hidden="true" class="sidebar-item-icon inline" />
{{ __('Not confidential') }}
</div>
- <div
- v-else
- class="value sidebar-item-value hide-collapsed">
+ <div v-else class="value sidebar-item-value hide-collapsed">
<icon
:size="16"
name="eye-slash"
diff --git a/app/assets/javascripts/sidebar/components/confidential/edit_form.vue b/app/assets/javascripts/sidebar/components/confidential/edit_form.vue
index 4165aa19acf..0ecbf934c25 100644
--- a/app/assets/javascripts/sidebar/components/confidential/edit_form.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/edit_form.vue
@@ -35,14 +35,8 @@ export default {
<div class="dropdown show">
<div class="dropdown-menu sidebar-item-warning-message">
<div>
- <p
- v-if="!isConfidential"
- v-html="confidentialityOnWarning">
- </p>
- <p
- v-else
- v-html="confidentialityOffWarning">
- </p>
+ <p v-if="!isConfidential" v-html="confidentialityOnWarning"></p>
+ <p v-else v-html="confidentialityOffWarning"></p>
<edit-form-buttons
:is-confidential="isConfidential"
:update-confidential-attribute="updateConfidentialAttribute"
diff --git a/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue b/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
index 38b1ddbfd5b..4b9bb5c7b0e 100644
--- a/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue
@@ -36,18 +36,10 @@ export default {
<template>
<div class="sidebar-item-warning-message-actions">
- <button
- type="button"
- class="btn btn-default append-right-10"
- @click="closeForm"
- >
+ <button type="button" class="btn btn-default append-right-10" @click="closeForm">
{{ __('Cancel') }}
</button>
- <button
- type="button"
- class="btn btn-close"
- @click.prevent="submitForm"
- >
+ <button type="button" class="btn btn-close" @click.prevent="submitForm">
{{ toggleButtonText }}
</button>
</div>
diff --git a/app/assets/javascripts/sidebar/components/lock/edit_form.vue b/app/assets/javascripts/sidebar/components/lock/edit_form.vue
index 4906dad22e1..630da751704 100644
--- a/app/assets/javascripts/sidebar/components/lock/edit_form.vue
+++ b/app/assets/javascripts/sidebar/components/lock/edit_form.vue
@@ -43,22 +43,11 @@ export default {
<template>
<div class="dropdown show">
<div class="dropdown-menu sidebar-item-warning-message">
- <p
- v-if="isLocked"
- class="text"
- v-html="unlockWarning">
- </p>
+ <p v-if="isLocked" class="text" v-html="unlockWarning"></p>
- <p
- v-else
- class="text"
- v-html="lockWarning">
- </p>
+ <p v-else class="text" v-html="lockWarning"></p>
- <edit-form-buttons
- :is-locked="isLocked"
- :update-locked-attribute="updateLockedAttribute"
- />
+ <edit-form-buttons :is-locked="isLocked" :update-locked-attribute="updateLockedAttribute" />
</div>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue b/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue
index 63082654101..902aeb9b8e4 100644
--- a/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue
+++ b/app/assets/javascripts/sidebar/components/lock/edit_form_buttons.vue
@@ -41,19 +41,11 @@ export default {
<template>
<div class="sidebar-item-warning-message-actions">
- <button
- type="button"
- class="btn btn-default append-right-10"
- @click="closeForm"
- >
+ <button type="button" class="btn btn-default append-right-10" @click="closeForm">
{{ __('Cancel') }}
</button>
- <button
- type="button"
- class="btn btn-close"
- @click.prevent="submitForm"
- >
+ <button type="button" class="btn btn-close" @click.prevent="submitForm">
{{ buttonText }}
</button>
</div>
diff --git a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
index ab7fab7e5ca..faea64c9841 100644
--- a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
+++ b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
@@ -34,11 +34,7 @@ export default {
required: true,
type: Object,
validator(mediatorObject) {
- return (
- mediatorObject.service &&
- mediatorObject.service.update &&
- mediatorObject.store
- );
+ return mediatorObject.service && mediatorObject.service.update && mediatorObject.store;
},
},
},
@@ -67,8 +63,7 @@ export default {
methods: {
toggleForm() {
- this.mediator.store.isLockDialogOpen = !this.mediator.store
- .isLockDialogOpen;
+ this.mediator.store.isLockDialogOpen = !this.mediator.store.isLockDialogOpen;
},
updateLockedAttribute(locked) {
@@ -79,9 +74,14 @@ export default {
.then(() => window.location.reload())
.catch(() =>
Flash(
- sprintf(__('Something went wrong trying to change the locked state of this %{issuableDisplayName}'), {
- issuableDisplayName: this.issuableDisplayName,
- }),
+ sprintf(
+ __(
+ 'Something went wrong trying to change the locked state of this %{issuableDisplayName}',
+ ),
+ {
+ issuableDisplayName: this.issuableDisplayName,
+ },
+ ),
),
);
},
@@ -100,15 +100,13 @@ export default {
data-boundary="viewport"
@click="toggleForm"
>
- <icon
- :name="lockIcon"
- aria-hidden="true"
- class="sidebar-item-icon is-active"
- />
+ <icon :name="lockIcon" class="sidebar-item-icon is-active" />
</div>
<div class="title hide-collapsed">
- {{ sprintf(__('Lock %{issuableDisplayName}'), { issuableDisplayName: issuableDisplayName }) }}
+ {{
+ sprintf(__('Lock %{issuableDisplayName}'), { issuableDisplayName: issuableDisplayName })
+ }}
<button
v-if="isEditable"
class="float-right lock-edit"
@@ -127,30 +125,13 @@ export default {
:issuable-type="issuableType"
/>
- <div
- v-if="isLocked"
- class="value sidebar-item-value"
- >
- <icon
- :size="16"
- name="lock"
- aria-hidden="true"
- class="sidebar-item-icon inline is-active"
- />
+ <div v-if="isLocked" class="value sidebar-item-value">
+ <icon :size="16" name="lock" class="sidebar-item-icon inline is-active" />
{{ __('Locked') }}
</div>
- <div
- v-else
- class="no-value sidebar-item-value hide-collapsed"
- >
- <icon
- :size="16"
- name="lock-open"
- aria-hidden="true"
- class="sidebar-item-icon inline"
- />
- {{ __('Unlocked') }}
+ <div v-else class="no-value sidebar-item-value hide-collapsed">
+ <icon :size="16" name="lock-open" class="sidebar-item-icon inline" /> {{ __('Unlocked') }}
</div>
</div>
</div>
diff --git a/app/assets/javascripts/sidebar/components/participants/participants.vue b/app/assets/javascripts/sidebar/components/participants/participants.vue
index 286a16f7bbf..4bfc8fa7eec 100644
--- a/app/assets/javascripts/sidebar/components/participants/participants.vue
+++ b/app/assets/javascripts/sidebar/components/participants/participants.vue
@@ -1,78 +1,80 @@
<script>
- import { __, n__, sprintf } from '~/locale';
- import tooltip from '~/vue_shared/directives/tooltip';
- import userAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
+import { __, n__, sprintf } from '~/locale';
+import tooltip from '~/vue_shared/directives/tooltip';
+import userAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
- export default {
- directives: {
- tooltip,
+export default {
+ directives: {
+ tooltip,
+ },
+ components: {
+ userAvatarImage,
+ GlLoadingIcon,
+ },
+ props: {
+ loading: {
+ type: Boolean,
+ required: false,
+ default: false,
},
- components: {
- userAvatarImage,
+ participants: {
+ type: Array,
+ required: false,
+ default: () => [],
},
- props: {
- loading: {
- type: Boolean,
- required: false,
- default: false,
- },
- participants: {
- type: Array,
- required: false,
- default: () => [],
- },
- numberOfLessParticipants: {
- type: Number,
- required: false,
- default: 7,
- },
+ numberOfLessParticipants: {
+ type: Number,
+ required: false,
+ default: 7,
},
- data() {
- return {
- isShowingMoreParticipants: false,
- };
+ },
+ data() {
+ return {
+ isShowingMoreParticipants: false,
+ };
+ },
+ computed: {
+ lessParticipants() {
+ return this.participants.slice(0, this.numberOfLessParticipants);
},
- computed: {
- lessParticipants() {
- return this.participants.slice(0, this.numberOfLessParticipants);
- },
- visibleParticipants() {
- return this.isShowingMoreParticipants ? this.participants : this.lessParticipants;
- },
- hasMoreParticipants() {
- return this.participants.length > this.numberOfLessParticipants;
- },
- toggleLabel() {
- let label = '';
- if (this.isShowingMoreParticipants) {
- label = __('- show less');
- } else {
- label = sprintf(__('+ %{moreCount} more'), {
- moreCount: this.participants.length - this.numberOfLessParticipants,
- });
- }
+ visibleParticipants() {
+ return this.isShowingMoreParticipants ? this.participants : this.lessParticipants;
+ },
+ hasMoreParticipants() {
+ return this.participants.length > this.numberOfLessParticipants;
+ },
+ toggleLabel() {
+ let label = '';
+ if (this.isShowingMoreParticipants) {
+ label = __('- show less');
+ } else {
+ label = sprintf(__('+ %{moreCount} more'), {
+ moreCount: this.participants.length - this.numberOfLessParticipants,
+ });
+ }
- return label;
- },
- participantLabel() {
- return sprintf(
- n__('%{count} participant', '%{count} participants', this.participants.length),
- { count: this.loading ? '' : this.participantCount },
- );
- },
- participantCount() {
- return this.participants.length;
- },
+ return label;
+ },
+ participantLabel() {
+ return sprintf(
+ n__('%{count} participant', '%{count} participants', this.participants.length),
+ { count: this.loading ? '' : this.participantCount },
+ );
},
- methods: {
- toggleMoreParticipants() {
- this.isShowingMoreParticipants = !this.isShowingMoreParticipants;
- },
- onClickCollapsedIcon() {
- this.$emit('toggleSidebar');
- },
+ participantCount() {
+ return this.participants.length;
},
- };
+ },
+ methods: {
+ toggleMoreParticipants() {
+ this.isShowingMoreParticipants = !this.isShowingMoreParticipants;
+ },
+ onClickCollapsedIcon() {
+ this.$emit('toggleSidebar');
+ },
+ },
+};
</script>
<template>
@@ -86,21 +88,9 @@
data-boundary="viewport"
@click="onClickCollapsedIcon"
>
- <i
- class="fa fa-users"
- aria-hidden="true"
- >
- </i>
- <gl-loading-icon
- v-if="loading"
- class="js-participants-collapsed-loading-icon"
- />
- <span
- v-else
- class="js-participants-collapsed-count"
- >
- {{ participantCount }}
- </span>
+ <i class="fa fa-users" aria-hidden="true"> </i>
+ <gl-loading-icon v-if="loading" class="js-participants-collapsed-loading-icon" />
+ <span v-else class="js-participants-collapsed-count"> {{ participantCount }} </span>
</div>
<div class="title hide-collapsed">
<gl-loading-icon
@@ -116,10 +106,7 @@
:key="participant.id"
class="participants-author js-participants-author"
>
- <a
- :href="participant.web_url"
- class="author-link"
- >
+ <a :href="participant.web_url" class="author-link">
<user-avatar-image
:lazy="true"
:img-src="participant.avatar_url"
@@ -131,10 +118,7 @@
</a>
</div>
</div>
- <div
- v-if="hasMoreParticipants"
- class="participants-more hide-collapsed"
- >
+ <div v-if="hasMoreParticipants" class="participants-more hide-collapsed">
<button
type="button"
class="btn-transparent btn-blank js-toggle-participants-button"
diff --git a/app/assets/javascripts/sidebar/components/participants/sidebar_participants.vue b/app/assets/javascripts/sidebar/components/participants/sidebar_participants.vue
index 5c1ead1a8ac..4ac515e552a 100644
--- a/app/assets/javascripts/sidebar/components/participants/sidebar_participants.vue
+++ b/app/assets/javascripts/sidebar/components/participants/sidebar_participants.vue
@@ -1,23 +1,23 @@
<script>
- import Store from '../../stores/sidebar_store';
- import participants from './participants.vue';
+import Store from '../../stores/sidebar_store';
+import participants from './participants.vue';
- export default {
- components: {
- participants,
+export default {
+ components: {
+ participants,
+ },
+ props: {
+ mediator: {
+ type: Object,
+ required: true,
},
- props: {
- mediator: {
- type: Object,
- required: true,
- },
- },
- data() {
- return {
- store: new Store(),
- };
- },
- };
+ },
+ data() {
+ return {
+ store: new Store(),
+ };
+ },
+};
</script>
<template>
diff --git a/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue
index 385717e7c1e..95a2c8cce6e 100644
--- a/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue
+++ b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions.vue
@@ -21,10 +21,9 @@ export default {
},
methods: {
onToggleSubscription() {
- this.mediator.toggleSubscription()
- .catch(() => {
- Flash(__('Error occurred when toggling the notification subscription'));
- });
+ this.mediator.toggleSubscription().catch(() => {
+ Flash(__('Error occurred when toggling the notification subscription'));
+ });
},
},
};
diff --git a/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue b/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
index 448c8fc3602..a75daca156c 100644
--- a/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
+++ b/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
@@ -1,82 +1,79 @@
<script>
- import { __ } from '~/locale';
- import icon from '~/vue_shared/components/icon.vue';
- import toggleButton from '~/vue_shared/components/toggle_button.vue';
- import tooltip from '~/vue_shared/directives/tooltip';
- import eventHub from '../../event_hub';
+import { __ } from '~/locale';
+import icon from '~/vue_shared/components/icon.vue';
+import toggleButton from '~/vue_shared/components/toggle_button.vue';
+import tooltip from '~/vue_shared/directives/tooltip';
+import eventHub from '../../event_hub';
- const ICON_ON = 'notifications';
- const ICON_OFF = 'notifications-off';
- const LABEL_ON = __('Notifications on');
- const LABEL_OFF = __('Notifications off');
+const ICON_ON = 'notifications';
+const ICON_OFF = 'notifications-off';
+const LABEL_ON = __('Notifications on');
+const LABEL_OFF = __('Notifications off');
- export default {
- directives: {
- tooltip,
+export default {
+ directives: {
+ tooltip,
+ },
+ components: {
+ icon,
+ toggleButton,
+ },
+ props: {
+ loading: {
+ type: Boolean,
+ required: false,
+ default: false,
},
- components: {
- icon,
- toggleButton,
+ subscribed: {
+ type: Boolean,
+ required: false,
+ default: null,
},
- props: {
- loading: {
- type: Boolean,
- required: false,
- default: false,
- },
- subscribed: {
- type: Boolean,
- required: false,
- default: null,
- },
- id: {
- type: Number,
- required: false,
- default: null,
- },
+ id: {
+ type: Number,
+ required: false,
+ default: null,
},
- computed: {
- showLoadingState() {
- return this.subscribed === null;
- },
- notificationIcon() {
- return this.subscribed ? ICON_ON : ICON_OFF;
- },
- notificationTooltip() {
- return this.subscribed ? LABEL_ON : LABEL_OFF;
- },
+ },
+ computed: {
+ showLoadingState() {
+ return this.subscribed === null;
},
- methods: {
- /**
- * We need to emit this event on both component & eventHub
- * for 2 dependencies;
- *
- * 1. eventHub: This component is used in Issue Boards sidebar
- * where component template is part of HAML
- * and event listeners are tied to app's eventHub.
- * 2. Component: This compone is also used in Epics in EE
- * where listeners are tied to component event.
- */
- toggleSubscription() {
- // App's eventHub event emission.
- eventHub.$emit('toggleSubscription', this.id);
+ notificationIcon() {
+ return this.subscribed ? ICON_ON : ICON_OFF;
+ },
+ notificationTooltip() {
+ return this.subscribed ? LABEL_ON : LABEL_OFF;
+ },
+ },
+ methods: {
+ /**
+ * We need to emit this event on both component & eventHub
+ * for 2 dependencies;
+ *
+ * 1. eventHub: This component is used in Issue Boards sidebar
+ * where component template is part of HAML
+ * and event listeners are tied to app's eventHub.
+ * 2. Component: This compone is also used in Epics in EE
+ * where listeners are tied to component event.
+ */
+ toggleSubscription() {
+ // App's eventHub event emission.
+ eventHub.$emit('toggleSubscription', this.id);
- // Component event emission.
- this.$emit('toggleSubscription', this.id);
- },
- onClickCollapsedIcon() {
- this.$emit('toggleSidebar');
- },
+ // Component event emission.
+ this.$emit('toggleSubscription', this.id);
+ },
+ onClickCollapsedIcon() {
+ this.$emit('toggleSidebar');
},
- };
+ },
+};
</script>
<template>
<div>
- <div
- class="sidebar-collapsed-icon"
- @click="onClickCollapsedIcon"
- >
+ <div class="sidebar-collapsed-icon" @click="onClickCollapsedIcon">
<span
v-tooltip
:title="notificationTooltip"
@@ -92,9 +89,7 @@
/>
</span>
</div>
- <span class="issuable-header-text hide-collapsed float-left">
- {{ __('Notifications') }}
- </span>
+ <span class="issuable-header-text hide-collapsed float-left"> {{ __('Notifications') }} </span>
<toggle-button
ref="toggleButton"
:is-loading="showLoadingState"
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue b/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue
index 1d030c4f67f..657ac837baf 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue
@@ -1,111 +1,111 @@
<script>
- import { __, sprintf } from '~/locale';
- import { abbreviateTime } from '~/lib/utils/pretty_time';
- import icon from '~/vue_shared/components/icon.vue';
- import tooltip from '~/vue_shared/directives/tooltip';
+import { __, sprintf } from '~/locale';
+import { abbreviateTime } from '~/lib/utils/datetime_utility';
+import icon from '~/vue_shared/components/icon.vue';
+import tooltip from '~/vue_shared/directives/tooltip';
- export default {
- name: 'TimeTrackingCollapsedState',
- components: {
- icon,
+export default {
+ name: 'TimeTrackingCollapsedState',
+ components: {
+ icon,
+ },
+ directives: {
+ tooltip,
+ },
+ props: {
+ showComparisonState: {
+ type: Boolean,
+ required: true,
},
- directives: {
- tooltip,
+ showSpentOnlyState: {
+ type: Boolean,
+ required: true,
},
- props: {
- showComparisonState: {
- type: Boolean,
- required: true,
- },
- showSpentOnlyState: {
- type: Boolean,
- required: true,
- },
- showEstimateOnlyState: {
- type: Boolean,
- required: true,
- },
- showNoTimeTrackingState: {
- type: Boolean,
- required: true,
- },
- timeSpentHumanReadable: {
- type: String,
- required: false,
- default: '',
- },
- timeEstimateHumanReadable: {
- type: String,
- required: false,
- default: '',
- },
+ showEstimateOnlyState: {
+ type: Boolean,
+ required: true,
},
- computed: {
- timeSpent() {
- return this.abbreviateTime(this.timeSpentHumanReadable);
- },
- timeEstimate() {
- return this.abbreviateTime(this.timeEstimateHumanReadable);
- },
- divClass() {
- if (this.showComparisonState) {
- return 'compare';
- } else if (this.showEstimateOnlyState) {
- return 'estimate-only';
- } else if (this.showSpentOnlyState) {
- return 'spend-only';
- } else if (this.showNoTimeTrackingState) {
- return 'no-tracking';
- }
+ showNoTimeTrackingState: {
+ type: Boolean,
+ required: true,
+ },
+ timeSpentHumanReadable: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ timeEstimateHumanReadable: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ timeSpent() {
+ return this.abbreviateTime(this.timeSpentHumanReadable);
+ },
+ timeEstimate() {
+ return this.abbreviateTime(this.timeEstimateHumanReadable);
+ },
+ divClass() {
+ if (this.showComparisonState) {
+ return 'compare';
+ } else if (this.showEstimateOnlyState) {
+ return 'estimate-only';
+ } else if (this.showSpentOnlyState) {
+ return 'spend-only';
+ } else if (this.showNoTimeTrackingState) {
+ return 'no-tracking';
+ }
+ return '';
+ },
+ spanClass() {
+ if (this.showComparisonState) {
return '';
- },
- spanClass() {
- if (this.showComparisonState) {
- return '';
- } else if (this.showEstimateOnlyState || this.showSpentOnlyState) {
- return 'bold';
- } else if (this.showNoTimeTrackingState) {
- return 'no-value';
- }
+ } else if (this.showEstimateOnlyState || this.showSpentOnlyState) {
+ return 'bold';
+ } else if (this.showNoTimeTrackingState) {
+ return 'no-value';
+ }
- return '';
- },
- text() {
- if (this.showComparisonState) {
- return `${this.timeSpent} / ${this.timeEstimate}`;
- } else if (this.showEstimateOnlyState) {
- return `-- / ${this.timeEstimate}`;
- } else if (this.showSpentOnlyState) {
- return `${this.timeSpent} / --`;
- } else if (this.showNoTimeTrackingState) {
- return 'None';
- }
+ return '';
+ },
+ text() {
+ if (this.showComparisonState) {
+ return `${this.timeSpent} / ${this.timeEstimate}`;
+ } else if (this.showEstimateOnlyState) {
+ return `-- / ${this.timeEstimate}`;
+ } else if (this.showSpentOnlyState) {
+ return `${this.timeSpent} / --`;
+ } else if (this.showNoTimeTrackingState) {
+ return 'None';
+ }
- return '';
- },
- timeTrackedTooltipText() {
- let title;
- if (this.showComparisonState) {
- title = __('Time remaining');
- } else if (this.showEstimateOnlyState) {
- title = __('Estimated');
- } else if (this.showSpentOnlyState) {
- title = __('Time spent');
- }
+ return '';
+ },
+ timeTrackedTooltipText() {
+ let title;
+ if (this.showComparisonState) {
+ title = __('Time remaining');
+ } else if (this.showEstimateOnlyState) {
+ title = __('Estimated');
+ } else if (this.showSpentOnlyState) {
+ title = __('Time spent');
+ }
- return sprintf('%{title}: %{text}', ({ title, text: this.text }));
- },
- tooltipText() {
- return this.showNoTimeTrackingState ? __('Time tracking') : this.timeTrackedTooltipText;
- },
+ return sprintf('%{title}: %{text}', { title, text: this.text });
+ },
+ tooltipText() {
+ return this.showNoTimeTrackingState ? __('Time tracking') : this.timeTrackedTooltipText;
},
- methods: {
- abbreviateTime(timeStr) {
- return abbreviateTime(timeStr);
- },
+ },
+ methods: {
+ abbreviateTime(timeStr) {
+ return abbreviateTime(timeStr);
},
- };
+ },
+};
</script>
<template>
@@ -120,9 +120,7 @@
<icon name="timer" />
<div class="time-tracking-collapsed-summary">
<div :class="divClass">
- <span :class="spanClass">
- {{ text }}
- </span>
+ <span :class="spanClass"> {{ text }} </span>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue b/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue
index dc599e1b9fc..f4d926cd3ec 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue
@@ -1,9 +1,13 @@
<script>
-import { parseSeconds, stringifyTime } from '../../../lib/utils/pretty_time';
+import { parseSeconds, stringifyTime } from '~/lib/utils/datetime_utility';
import tooltip from '../../../vue_shared/directives/tooltip';
+import { GlProgressBar } from '@gitlab/ui';
export default {
name: 'TimeTrackingComparisonPane',
+ components: {
+ GlProgressBar,
+ },
directives: {
tooltip,
},
@@ -65,26 +69,15 @@ export default {
data-placement="top"
role="timeRemainingDisplay"
>
- <gl-progress-bar
- :value="timeRemainingPercent"
- :variant="progressBarVariant"
- />
+ <gl-progress-bar :value="timeRemainingPercent" :variant="progressBarVariant" />
<div class="compare-display-container">
<div class="compare-display float-left">
- <span class="compare-label">
- {{ s__('TimeTracking|Spent') }}
- </span>
- <span class="compare-value spent">
- {{ timeSpentHumanReadable }}
- </span>
+ <span class="compare-label"> {{ s__('TimeTracking|Spent') }} </span>
+ <span class="compare-value spent"> {{ timeSpentHumanReadable }} </span>
</div>
<div class="compare-display estimated float-right">
- <span class="compare-label">
- {{ s__('TimeTrackingEstimated|Est') }}
- </span>
- <span class="compare-value">
- {{ timeEstimateHumanReadable }}
- </span>
+ <span class="compare-label"> {{ s__('TimeTrackingEstimated|Est') }} </span>
+ <span class="compare-value"> {{ timeEstimateHumanReadable }} </span>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/estimate_only_pane.vue b/app/assets/javascripts/sidebar/components/time_tracking/estimate_only_pane.vue
index 08fce597e50..305726d9725 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/estimate_only_pane.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/estimate_only_pane.vue
@@ -12,9 +12,6 @@ export default {
<template>
<div class="time-tracking-estimate-only-pane">
- <span class="bold">
- {{ s__('TimeTracking|Estimated:') }}
- </span>
- {{ timeEstimateHumanReadable }}
+ <span class="bold"> {{ s__('TimeTracking|Estimated:') }} </span> {{ timeEstimateHumanReadable }}
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue b/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue
index 19ec0f05a26..51cd5810ac0 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue
@@ -15,16 +15,22 @@ export default {
},
estimateText() {
return sprintf(
- s__('estimateCommand|%{slash_command} will update the estimated time with the latest command.'), {
+ s__(
+ 'estimateCommand|%{slash_command} will update the estimated time with the latest command.',
+ ),
+ {
slash_command: '<code>/estimate</code>',
- }, false,
+ },
+ false,
);
},
spendText() {
return sprintf(
- s__('spendCommand|%{slash_command} will update the sum of the time spent.'), {
+ s__('spendCommand|%{slash_command} will update the sum of the time spent.'),
+ {
slash_command: '<code>/spend</code>',
- }, false,
+ },
+ false,
);
},
},
@@ -34,22 +40,11 @@ export default {
<template>
<div class="time-tracking-help-state">
<div class="time-tracking-info">
- <h4>
- {{ __('Track time with quick actions') }}
- </h4>
- <p>
- {{ __('Quick actions can be used in the issues description and comment boxes.') }}
- </p>
- <p v-html="estimateText">
- </p>
- <p v-html="spendText">
- </p>
- <a
- :href="href"
- class="btn btn-default learn-more-button"
- >
- {{ __('Learn more') }}
- </a>
+ <h4>{{ __('Track time with quick actions') }}</h4>
+ <p>{{ __('Quick actions can be used in the issues description and comment boxes.') }}</p>
+ <p v-html="estimateText"></p>
+ <p v-html="spendText"></p>
+ <a :href="href" class="btn btn-default learn-more-button"> {{ __('Learn more') }} </a>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/no_tracking_pane.vue b/app/assets/javascripts/sidebar/components/time_tracking/no_tracking_pane.vue
index 9228184df5b..45552589e50 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/no_tracking_pane.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/no_tracking_pane.vue
@@ -6,8 +6,6 @@ export default {
<template>
<div class="time-tracking-no-tracking-pane">
- <span class="no-value">
- {{ __('No estimate or time spent') }}
- </span>
+ <span class="no-value"> {{ __('No estimate or time spent') }} </span>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue b/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
index 2e1d6e9643a..8e8b9f19b6e 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/sidebar_time_tracking.vue
@@ -26,7 +26,7 @@ export default {
methods: {
listenForQuickActions() {
$(document).on('ajax:success', '.gfm-form', this.quickActionListened);
- eventHub.$on('timeTrackingUpdated', (data) => {
+ eventHub.$on('timeTrackingUpdated', data => {
this.quickActionListened(null, data);
});
},
@@ -34,9 +34,7 @@ export default {
const subscribedCommands = ['spend_time', 'time_estimate'];
let changedCommands;
if (data !== undefined) {
- changedCommands = data.commands_changes
- ? Object.keys(data.commands_changes)
- : [];
+ changedCommands = data.commands_changes ? Object.keys(data.commands_changes) : [];
} else {
changedCommands = [];
}
@@ -51,10 +49,10 @@ export default {
<template>
<div class="block">
<issuable-time-tracker
- :time_estimate="store.timeEstimate"
- :time_spent="store.totalTimeSpent"
- :human_time_estimate="store.humanTimeEstimate"
- :human_time_spent="store.humanTotalTimeSpent"
+ :time-estimate="store.timeEstimate"
+ :time-spent="store.totalTimeSpent"
+ :human-time-estimate="store.humanTimeEstimate"
+ :human-time-spent="store.humanTotalTimeSpent"
:root-path="store.rootPath"
/>
</div>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/spent_only_pane.vue b/app/assets/javascripts/sidebar/components/time_tracking/spent_only_pane.vue
index 59cd99f8f14..7c7356e2afa 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/spent_only_pane.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/spent_only_pane.vue
@@ -12,7 +12,6 @@ export default {
<template>
<div class="time-tracking-spend-only-pane">
- <span class="bold">Spent:</span>
- {{ timeSpentHumanReadable }}
+ <span class="bold">Spent:</span> {{ timeSpentHumanReadable }}
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
index ca3b9338c29..d3a4f9c81e0 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
@@ -19,20 +19,20 @@ export default {
TimeTrackingHelpState,
},
props: {
- time_estimate: {
+ timeEstimate: {
type: Number,
required: true,
},
- time_spent: {
+ timeSpent: {
type: Number,
required: true,
},
- human_time_estimate: {
+ humanTimeEstimate: {
type: String,
required: false,
default: '',
},
- human_time_spent: {
+ humanTimeSpent: {
type: String,
required: false,
default: '',
@@ -48,18 +48,6 @@ export default {
};
},
computed: {
- timeSpent() {
- return this.time_spent;
- },
- timeEstimate() {
- return this.time_estimate;
- },
- timeEstimateHumanReadable() {
- return this.human_time_estimate;
- },
- timeSpentHumanReadable() {
- return this.human_time_spent;
- },
hasTimeSpent() {
return !!this.timeSpent;
},
@@ -90,78 +78,60 @@ export default {
this.showHelp = show;
},
update(data) {
- this.time_estimate = data.time_estimate;
- this.time_spent = data.time_spent;
- this.human_time_estimate = data.human_time_estimate;
- this.human_time_spent = data.human_time_spent;
+ const { timeEstimate, timeSpent, humanTimeEstimate, humanTimeSpent } = data;
+
+ this.timeEstimate = timeEstimate;
+ this.timeSpent = timeSpent;
+ this.humanTimeEstimate = humanTimeEstimate;
+ this.humanTimeSpent = humanTimeSpent;
},
},
};
</script>
<template>
- <div
- v-cloak
- class="time_tracker time-tracking-component-wrap"
- >
+ <div v-cloak class="time_tracker time-tracking-component-wrap">
<time-tracking-collapsed-state
:show-comparison-state="showComparisonState"
:show-no-time-tracking-state="showNoTimeTrackingState"
:show-help-state="showHelpState"
:show-spent-only-state="showSpentOnlyState"
:show-estimate-only-state="showEstimateOnlyState"
- :time-spent-human-readable="timeSpentHumanReadable"
- :time-estimate-human-readable="timeEstimateHumanReadable"
+ :time-spent-human-readable="humanTimeSpent"
+ :time-estimate-human-readable="humanTimeEstimate"
/>
<div class="title hide-collapsed">
{{ __('Time tracking') }}
- <div
- v-if="!showHelpState"
- class="help-button float-right"
- @click="toggleHelpState(true)"
- >
- <i
- class="fa fa-question-circle"
- aria-hidden="true"
- >
- </i>
+ <div v-if="!showHelpState" class="help-button float-right" @click="toggleHelpState(true);">
+ <i class="fa fa-question-circle" aria-hidden="true"> </i>
</div>
<div
v-if="showHelpState"
class="close-help-button float-right"
- @click="toggleHelpState(false)"
+ @click="toggleHelpState(false);"
>
- <i
- class="fa fa-close"
- aria-hidden="true"
- >
- </i>
+ <i class="fa fa-close" aria-hidden="true"> </i>
</div>
</div>
<div class="time-tracking-content hide-collapsed">
<time-tracking-estimate-only-pane
v-if="showEstimateOnlyState"
- :time-estimate-human-readable="timeEstimateHumanReadable"
+ :time-estimate-human-readable="humanTimeEstimate"
/>
<time-tracking-spent-only-pane
v-if="showSpentOnlyState"
- :time-spent-human-readable="timeSpentHumanReadable"
- />
- <time-tracking-no-tracking-pane
- v-if="showNoTimeTrackingState"
+ :time-spent-human-readable="humanTimeSpent"
/>
+ <time-tracking-no-tracking-pane v-if="showNoTimeTrackingState" />
<time-tracking-comparison-pane
v-if="showComparisonState"
:time-estimate="timeEstimate"
:time-spent="timeSpent"
- :time-spent-human-readable="timeSpentHumanReadable"
- :time-estimate-human-readable="timeEstimateHumanReadable"
+ :time-spent-human-readable="humanTimeSpent"
+ :time-estimate-human-readable="humanTimeEstimate"
/>
<transition name="help-state-toggle">
- <time-tracking-help-state
- v-if="showHelpState"
- :root-path="rootPath"
- />
+ <time-tracking-help-state v-if="showHelpState" :root-path="rootPath" />
</transition>
</div>
</div>
diff --git a/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue b/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue
index a6b3a674952..706e6ca19c3 100644
--- a/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue
+++ b/app/assets/javascripts/sidebar/components/todo_toggle/todo.vue
@@ -1,6 +1,7 @@
<script>
import { __ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
+import { GlLoadingIcon } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
@@ -13,6 +14,7 @@ export default {
},
components: {
Icon,
+ GlLoadingIcon,
},
props: {
issuableId: {
@@ -41,9 +43,9 @@ export default {
},
computed: {
buttonClasses() {
- return this.collapsed ?
- 'btn-blank btn-todo sidebar-collapsed-icon dont-change-state' :
- 'btn btn-default btn-todo issuable-header-btn float-right';
+ return this.collapsed
+ ? 'btn-blank btn-todo sidebar-collapsed-icon dont-change-state'
+ : 'btn btn-default btn-todo issuable-header-btn float-right';
},
buttonLabel() {
return this.isTodo ? MARK_TEXT : TODO_TEXT;
@@ -82,15 +84,7 @@ export default {
:css-classes="collapsedButtonIconClasses"
:name="collapsedButtonIcon"
/>
- <span
- v-show="!collapsed"
- class="issuable-todo-inner"
- >
- {{ buttonLabel }}
- </span>
- <gl-loading-icon
- v-show="isActionActive"
- :inline="true"
- />
+ <span v-show="!collapsed" class="issuable-todo-inner"> {{ buttonLabel }} </span>
+ <gl-loading-icon v-show="isActionActive" :inline="true" />
</button>
</template>
diff --git a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
index b267422cd97..225ebb61195 100644
--- a/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
+++ b/app/assets/javascripts/sidebar/lib/sidebar_move_issue.js
@@ -37,7 +37,8 @@ class SidebarMoveIssue {
// Keep the dropdown open after selecting an option
shouldPropagate: false,
data: (searchTerm, callback) => {
- this.mediator.fetchAutocompleteProjects(searchTerm)
+ this.mediator
+ .fetchAutocompleteProjects(searchTerm)
.then(callback)
.catch(() => new window.Flash('An error occurred while fetching projects autocomplete.'));
},
@@ -48,7 +49,7 @@ class SidebarMoveIssue {
</a>
</li>
`,
- clicked: (options) => {
+ clicked: options => {
const project = options.selectedObj;
const selectedProjectId = options.isMarking ? project.id : 0;
this.mediator.setMoveToProjectId(selectedProjectId);
@@ -68,17 +69,12 @@ class SidebarMoveIssue {
onConfirmClicked() {
if (isValidProjectId(this.mediator.store.moveToProjectId)) {
- this.$confirmButton
- .disable()
- .addClass('is-loading');
+ this.$confirmButton.disable().addClass('is-loading');
- this.mediator.moveIssue()
- .catch(() => {
- window.Flash('An error occurred while moving the issue.');
- this.$confirmButton
- .enable()
- .removeClass('is-loading');
- });
+ this.mediator.moveIssue().catch(() => {
+ window.Flash('An error occurred while moving the issue.');
+ this.$confirmButton.enable().removeClass('is-loading');
+ });
}
}
}
diff --git a/app/assets/javascripts/sidebar/mount_milestone_sidebar.js b/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
index b15ad0e5586..1ebdbec7bc9 100644
--- a/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
@@ -7,21 +7,24 @@ export default class SidebarMilestone {
if (!el) return;
+ const { timeEstimate, timeSpent, humanTimeEstimate, humanTimeSpent } = el.dataset;
+
// eslint-disable-next-line no-new
new Vue({
el,
components: {
timeTracker,
},
- render: createElement => createElement('timeTracker', {
- props: {
- time_estimate: parseInt(el.dataset.timeEstimate, 10),
- time_spent: parseInt(el.dataset.timeSpent, 10),
- human_time_estimate: el.dataset.humanTimeEstimate,
- human_time_spent: el.dataset.humanTimeSpent,
- rootPath: '/',
- },
- }),
+ render: createElement =>
+ createElement('timeTracker', {
+ props: {
+ timeEstimate: parseInt(timeEstimate, 10),
+ timeSpent: parseInt(timeSpent, 10),
+ humanTimeEstimate,
+ humanTimeSpent,
+ rootPath: '/',
+ },
+ }),
});
}
}
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 655bf9198b7..6f8214b18ee 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -22,14 +22,15 @@ function mountAssigneesComponent(mediator) {
components: {
SidebarAssignees,
},
- render: createElement => createElement('sidebar-assignees', {
- props: {
- mediator,
- field: el.dataset.field,
- signedIn: el.hasAttribute('data-signed-in'),
- issuableType: gl.utils.isInIssuePage() ? 'issue' : 'merge_request',
- },
- }),
+ render: createElement =>
+ createElement('sidebar-assignees', {
+ props: {
+ mediator,
+ field: el.dataset.field,
+ signedIn: el.hasAttribute('data-signed-in'),
+ issuableType: gl.utils.isInIssuePage() ? 'issue' : 'merge_request',
+ },
+ }),
});
}
@@ -83,11 +84,12 @@ function mountParticipantsComponent(mediator) {
components: {
sidebarParticipants,
},
- render: createElement => createElement('sidebar-participants', {
- props: {
- mediator,
- },
- }),
+ render: createElement =>
+ createElement('sidebar-participants', {
+ props: {
+ mediator,
+ },
+ }),
});
}
@@ -102,11 +104,12 @@ function mountSubscriptionsComponent(mediator) {
components: {
sidebarSubscriptions,
},
- render: createElement => createElement('sidebar-subscriptions', {
- props: {
- mediator,
- },
- }),
+ render: createElement =>
+ createElement('sidebar-subscriptions', {
+ props: {
+ mediator,
+ },
+ }),
});
}
diff --git a/app/assets/javascripts/sidebar/services/sidebar_service.js b/app/assets/javascripts/sidebar/services/sidebar_service.js
index 37c97225bfd..cbe20f761ff 100644
--- a/app/assets/javascripts/sidebar/services/sidebar_service.js
+++ b/app/assets/javascripts/sidebar/services/sidebar_service.js
@@ -22,11 +22,15 @@ export default class SidebarService {
}
update(key, data) {
- return Vue.http.put(this.endpoint, {
- [key]: data,
- }, {
- emulateJSON: true,
- });
+ return Vue.http.put(
+ this.endpoint,
+ {
+ [key]: data,
+ },
+ {
+ emulateJSON: true,
+ },
+ );
}
getProjectsAutocomplete(searchTerm) {
diff --git a/app/assets/javascripts/sidebar/sidebar_mediator.js b/app/assets/javascripts/sidebar/sidebar_mediator.js
index d9ca5e46770..3e040ec8428 100644
--- a/app/assets/javascripts/sidebar/sidebar_mediator.js
+++ b/app/assets/javascripts/sidebar/sidebar_mediator.js
@@ -39,9 +39,10 @@ export default class SidebarMediator {
}
fetch() {
- return this.service.get()
+ return this.service
+ .get()
.then(response => response.json())
- .then((data) => {
+ .then(data => {
this.processFetchedData(data);
})
.catch(() => new Flash('Error occurred when fetching sidebar data'));
@@ -56,30 +57,33 @@ export default class SidebarMediator {
toggleSubscription() {
this.store.setFetchingState('subscriptions', true);
- return this.service.toggleSubscription()
+ return this.service
+ .toggleSubscription()
.then(() => {
this.store.setSubscribedState(!this.store.subscribed);
this.store.setFetchingState('subscriptions', false);
})
- .catch((err) => {
+ .catch(err => {
this.store.setFetchingState('subscriptions', false);
throw err;
});
}
fetchAutocompleteProjects(searchTerm) {
- return this.service.getProjectsAutocomplete(searchTerm)
+ return this.service
+ .getProjectsAutocomplete(searchTerm)
.then(response => response.json())
- .then((data) => {
+ .then(data => {
this.store.setAutocompleteProjects(data);
return this.store.autocompleteProjects;
});
}
moveIssue() {
- return this.service.moveIssue(this.store.moveToProjectId)
+ return this.service
+ .moveIssue(this.store.moveToProjectId)
.then(response => response.json())
- .then((data) => {
+ .then(data => {
if (window.location.pathname !== data.web_url) {
visitUrl(data.web_url);
}
diff --git a/app/assets/javascripts/single_file_diff.js b/app/assets/javascripts/single_file_diff.js
index 99c93952e2a..f2b9d75dd00 100644
--- a/app/assets/javascripts/single_file_diff.js
+++ b/app/assets/javascripts/single_file_diff.js
@@ -10,8 +10,10 @@ import syntaxHighlight from './syntax_highlight';
const WRAPPER = '<div class="diff-content"></div>';
const LOADING_HTML = '<i class="fa fa-spinner fa-spin"></i>';
-const ERROR_HTML = '<div class="nothing-here-block"><i class="fa fa-warning"></i> Could not load diff</div>';
-const COLLAPSED_HTML = '<div class="nothing-here-block diff-collapsed">This diff is collapsed. <button class="click-to-expand btn btn-link">Click to expand it.</button></div>';
+const ERROR_HTML =
+ '<div class="nothing-here-block"><i class="fa fa-warning"></i> Could not load diff</div>';
+const COLLAPSED_HTML =
+ '<div class="nothing-here-block diff-collapsed">This diff is collapsed. <button class="click-to-expand btn btn-link">Click to expand it.</button></div>';
export default class SingleFileDiff {
constructor(file) {
@@ -23,23 +25,36 @@ export default class SingleFileDiff {
this.isOpen = !this.diffForPath;
if (this.diffForPath) {
this.collapsedContent = this.content;
- this.loadingContent = $(WRAPPER).addClass('loading').html(LOADING_HTML).hide();
+ this.loadingContent = $(WRAPPER)
+ .addClass('loading')
+ .html(LOADING_HTML)
+ .hide();
this.content = null;
this.collapsedContent.after(this.loadingContent);
this.$toggleIcon.addClass('fa-caret-right');
} else {
- this.collapsedContent = $(WRAPPER).html(COLLAPSED_HTML).hide();
+ this.collapsedContent = $(WRAPPER)
+ .html(COLLAPSED_HTML)
+ .hide();
this.content.after(this.collapsedContent);
this.$toggleIcon.addClass('fa-caret-down');
}
- $('.js-file-title, .click-to-expand', this.file).on('click', (function (e) {
- this.toggleDiff($(e.target));
- }).bind(this));
+ $('.js-file-title, .click-to-expand', this.file).on(
+ 'click',
+ function(e) {
+ this.toggleDiff($(e.target));
+ }.bind(this),
+ );
}
toggleDiff($target, cb) {
- if (!$target.hasClass('js-file-title') && !$target.hasClass('click-to-expand') && !$target.hasClass('diff-toggle-caret')) return;
+ if (
+ !$target.hasClass('js-file-title') &&
+ !$target.hasClass('click-to-expand') &&
+ !$target.hasClass('diff-toggle-caret')
+ )
+ return;
this.isOpen = !this.isOpen;
if (!this.isOpen && !this.hasError) {
this.content.hide();
@@ -65,7 +80,8 @@ export default class SingleFileDiff {
this.collapsedContent.hide();
this.loadingContent.show();
- axios.get(this.diffForPath)
+ axios
+ .get(this.diffForPath)
.then(({ data }) => {
this.loadingContent.hide();
if (data.html) {
diff --git a/app/assets/javascripts/smart_interval.js b/app/assets/javascripts/smart_interval.js
index 5e385400747..8ca590123ae 100644
--- a/app/assets/javascripts/smart_interval.js
+++ b/app/assets/javascripts/smart_interval.js
@@ -93,7 +93,9 @@ export default class SmartInterval {
destroy() {
this.cancel();
document.removeEventListener('visibilitychange', this.handleVisibilityChange);
- $(document).off('visibilitychange').off('beforeunload');
+ $(document)
+ .off('visibilitychange')
+ .off('beforeunload');
}
/* private */
@@ -111,11 +113,12 @@ export default class SmartInterval {
triggerCallback() {
this.isLoading = true;
- this.cfg.callback()
+ this.cfg
+ .callback()
.then(() => {
this.isLoading = false;
})
- .catch((err) => {
+ .catch(err => {
this.isLoading = false;
throw err;
});
@@ -134,9 +137,9 @@ export default class SmartInterval {
handleVisibilityChange(e) {
this.state.pageVisibility = e.target.visibilityState;
- const intervalAction = this.isPageVisible() ?
- this.onVisibilityVisible :
- this.onVisibilityHidden;
+ const intervalAction = this.isPageVisible()
+ ? this.onVisibilityVisible
+ : this.onVisibilityHidden;
intervalAction.apply(this);
}
@@ -162,7 +165,9 @@ export default class SmartInterval {
this.setCurrentInterval(nextInterval);
}
- isPageVisible() { return this.state.pageVisibility === 'visible'; }
+ isPageVisible() {
+ return this.state.pageVisibility === 'visible';
+ }
stopTimer() {
const { state } = this;
@@ -170,4 +175,3 @@ export default class SmartInterval {
state.intervalId = window.clearInterval(state.intervalId);
}
}
-
diff --git a/app/assets/javascripts/star.js b/app/assets/javascripts/star.js
index f5a7fdae5d7..9af5d5b23cb 100644
--- a/app/assets/javascripts/star.js
+++ b/app/assets/javascripts/star.js
@@ -11,19 +11,23 @@ export default class Star {
const $starSpan = $this.find('span');
const $startIcon = $this.find('svg');
- axios.post($this.data('endpoint'))
+ axios
+ .post($this.data('endpoint'))
.then(({ data }) => {
const isStarred = $starSpan.hasClass('starred');
- $this.parent().find('.star-count').text(data.star_count);
+ $this
+ .parent()
+ .find('.star-count')
+ .text(data.star_count);
if (isStarred) {
$starSpan.removeClass('starred').text(s__('StarProject|Star'));
$startIcon.remove();
- $this.prepend(spriteIcon('star-o'));
+ $this.prepend(spriteIcon('star-o', 'icon'));
} else {
$starSpan.addClass('starred').text(__('Unstar'));
$startIcon.remove();
- $this.prepend(spriteIcon('star'));
+ $this.prepend(spriteIcon('star', 'icon'));
}
})
.catch(() => Flash('Star toggle failed. Try again later.'));
diff --git a/app/assets/javascripts/task_list.js b/app/assets/javascripts/task_list.js
index 48782e63b9b..edefb3735d7 100644
--- a/app/assets/javascripts/task_list.js
+++ b/app/assets/javascripts/task_list.js
@@ -26,7 +26,11 @@ export default class TaskList {
// Prevent duplicate event bindings
this.disable();
$(`${this.selector} .js-task-list-container`).taskList('enable');
- $(document).on('tasklist:changed', `${this.selector} .js-task-list-container`, this.update.bind(this));
+ $(document).on(
+ 'tasklist:changed',
+ `${this.selector} .js-task-list-container`,
+ this.update.bind(this),
+ );
}
disable() {
@@ -41,7 +45,8 @@ export default class TaskList {
[this.fieldName]: $target.val(),
};
- return axios.patch($target.data('updateUrl') || $('form.js-issuable-update').attr('action'), patchData)
+ return axios
+ .patch($target.data('updateUrl') || $('form.js-issuable-update').attr('action'), patchData)
.then(({ data }) => this.onSuccess(data))
.catch(err => this.onError(err));
}
diff --git a/app/assets/javascripts/templates/issuable_template_selector.js b/app/assets/javascripts/templates/issuable_template_selector.js
index 6fea03af46a..6065770e68d 100644
--- a/app/assets/javascripts/templates/issuable_template_selector.js
+++ b/app/assets/javascripts/templates/issuable_template_selector.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-useless-return, max-len */
+/* eslint-disable no-useless-return */
import $ from 'jquery';
import Api from '../api';
@@ -31,12 +31,18 @@ export default class IssuableTemplateSelector extends TemplateSelector {
requestFile(query) {
this.startLoadingSpinner();
- Api.issueTemplate(this.namespacePath, this.projectPath, query.name, this.issuableType, (err, currentTemplate) => {
- this.currentTemplate = currentTemplate;
- this.stopLoadingSpinner();
- if (err) return; // Error handled by global AJAX error handler
- this.setInputValueToTemplateContent();
- });
+ Api.issueTemplate(
+ this.namespacePath,
+ this.projectPath,
+ query.name,
+ this.issuableType,
+ (err, currentTemplate) => {
+ this.currentTemplate = currentTemplate;
+ this.stopLoadingSpinner();
+ if (err) return; // Error handled by global AJAX error handler
+ this.setInputValueToTemplateContent();
+ },
+ );
return;
}
diff --git a/app/assets/javascripts/terminal/terminal.js b/app/assets/javascripts/terminal/terminal.js
index 74c5bbe45a4..b24aa8a3a34 100644
--- a/app/assets/javascripts/terminal/terminal.js
+++ b/app/assets/javascripts/terminal/terminal.js
@@ -4,10 +4,14 @@ import * as fit from 'xterm/lib/addons/fit/fit';
export default class GLTerminal {
constructor(options = {}) {
- this.options = Object.assign({}, {
- cursorBlink: true,
- screenKeys: true,
- }, options);
+ this.options = Object.assign(
+ {},
+ {
+ cursorBlink: true,
+ screenKeys: true,
+ },
+ options,
+ );
this.container = document.querySelector(options.selector);
diff --git a/app/assets/javascripts/test_utils/simulate_drag.js b/app/assets/javascripts/test_utils/simulate_drag.js
index a5c18042ce7..be9ebc81c6b 100644
--- a/app/assets/javascripts/test_utils/simulate_drag.js
+++ b/app/assets/javascripts/test_utils/simulate_drag.js
@@ -4,15 +4,43 @@ function simulateEvent(el, type, options = {}) {
if (/^mouse/.test(type)) {
event = el.ownerDocument.createEvent('MouseEvents');
- event.initMouseEvent(type, true, true, el.ownerDocument.defaultView,
- options.button, options.screenX, options.screenY, options.clientX, options.clientY,
- options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.button, el);
+ event.initMouseEvent(
+ type,
+ true,
+ true,
+ el.ownerDocument.defaultView,
+ options.button,
+ options.screenX,
+ options.screenY,
+ options.clientX,
+ options.clientY,
+ options.ctrlKey,
+ options.altKey,
+ options.shiftKey,
+ options.metaKey,
+ options.button,
+ el,
+ );
} else {
event = el.ownerDocument.createEvent('CustomEvent');
- event.initCustomEvent(type, true, true, el.ownerDocument.defaultView,
- options.button, options.screenX, options.screenY, options.clientX, options.clientY,
- options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, options.button, el);
+ event.initCustomEvent(
+ type,
+ true,
+ true,
+ el.ownerDocument.defaultView,
+ options.button,
+ options.screenX,
+ options.screenY,
+ options.clientX,
+ options.clientY,
+ options.ctrlKey,
+ options.altKey,
+ options.shiftKey,
+ options.metaKey,
+ options.button,
+ el,
+ );
event.dataTransfer = {
data: {},
@@ -37,14 +65,16 @@ function simulateEvent(el, type, options = {}) {
}
function isLast(target) {
- const el = typeof target.el === 'string' ? document.getElementById(target.el.substr(1)) : target.el;
+ const el =
+ typeof target.el === 'string' ? document.getElementById(target.el.substr(1)) : target.el;
const { children } = el;
return children.length - 1 === target.index;
}
function getTarget(target) {
- const el = typeof target.el === 'string' ? document.getElementById(target.el.substr(1)) : target.el;
+ const el =
+ typeof target.el === 'string' ? document.getElementById(target.el.substr(1)) : target.el;
const { children } = el;
return (
@@ -58,13 +88,13 @@ function getTarget(target) {
function getRect(el) {
const rect = el.getBoundingClientRect();
const width = rect.right - rect.left;
- const height = (rect.bottom - rect.top) + 10;
+ const height = rect.bottom - rect.top + 10;
return {
x: rect.left,
y: rect.top,
- cx: rect.left + (width / 2),
- cy: rect.top + (height / 2),
+ cx: rect.left + width / 2,
+ cy: rect.top + height / 2,
w: width,
h: height,
hw: width / 2,
@@ -112,8 +142,8 @@ export default function simulateDrag(options) {
const dragInterval = setInterval(() => {
const progress = (new Date().getTime() - startTime) / duration;
- const x = (fromRect.cx + ((toRect.cx - fromRect.cx) * progress));
- const y = (fromRect.cy + ((toRect.cy - fromRect.cy) * progress));
+ const x = fromRect.cx + (toRect.cx - fromRect.cx) * progress;
+ const y = fromRect.cy + (toRect.cy - fromRect.cy) * progress;
const overEl = fromEl.ownerDocument.elementFromPoint(x, y);
simulateEvent(overEl, 'mousemove', {
diff --git a/app/assets/javascripts/test_utils/simulate_input.js b/app/assets/javascripts/test_utils/simulate_input.js
index 90c1b7cb57e..c300c806e6d 100644
--- a/app/assets/javascripts/test_utils/simulate_input.js
+++ b/app/assets/javascripts/test_utils/simulate_input.js
@@ -12,7 +12,7 @@ export default function simulateInput(target, text) {
}
if (text.length > 0) {
- Array.prototype.forEach.call(text, (char) => {
+ Array.prototype.forEach.call(text, char => {
input.value += char;
triggerEvents(input);
});
diff --git a/app/assets/javascripts/toggle_buttons.js b/app/assets/javascripts/toggle_buttons.js
index 199b14458ed..bcb44bf7acf 100644
--- a/app/assets/javascripts/toggle_buttons.js
+++ b/app/assets/javascripts/toggle_buttons.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import Flash from './flash';
import { __ } from './locale';
-import { convertPermissionToBoolean } from './lib/utils/common_utils';
+import { parseBoolean } from './lib/utils/common_utils';
/*
example HAML:
@@ -18,7 +18,7 @@ function updateToggle(toggle, isOn) {
}
function onToggleClicked(toggle, input, clickCallback) {
- const previousIsOn = convertPermissionToBoolean(input.value);
+ const previousIsOn = parseBoolean(input.value);
// Visually change the toggle and start loading
updateToggle(toggle, !previousIsOn);
@@ -49,9 +49,9 @@ function onToggleClicked(toggle, input, clickCallback) {
export default function setupToggleButtons(container, clickCallback = () => {}) {
const toggles = container.querySelectorAll('.js-project-feature-toggle');
- toggles.forEach((toggle) => {
+ toggles.forEach(toggle => {
const input = toggle.querySelector('.js-project-feature-toggle-input');
- const isOn = convertPermissionToBoolean(input.value);
+ const isOn = parseBoolean(input.value);
// Get the visible toggle in sync with the hidden input
updateToggle(toggle, isOn);
diff --git a/app/assets/javascripts/tree.js b/app/assets/javascripts/tree.js
index 85123a63a45..3e659c9e7ea 100644
--- a/app/assets/javascripts/tree.js
+++ b/app/assets/javascripts/tree.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, max-len, quotes, consistent-return, no-var, one-var, one-var-declaration-per-line, no-else-return, prefer-arrow-callback, class-methods-use-this */
+/* eslint-disable func-names, consistent-return, no-var, one-var, no-else-return, prefer-arrow-callback, class-methods-use-this */
import $ from 'jquery';
import { visitUrl } from './lib/utils/url_utility';
@@ -8,7 +8,7 @@ export default class TreeView {
this.initKeyNav();
// Code browser tree slider
// Make the entire tree-item row clickable, but not if clicking another link (like a commit message)
- $(".tree-content-holder .tree-item").on('click', function(e) {
+ $('.tree-content-holder .tree-item').on('click', function(e) {
var $clickedEl, path;
$clickedEl = $(e.target);
path = $('.tree-item-file-name a', this).attr('href');
@@ -27,33 +27,33 @@ export default class TreeView {
initKeyNav() {
var li, liSelected;
- li = $("tr.tree-item");
+ li = $('tr.tree-item');
liSelected = null;
return $('body').keydown(function(e) {
var next, path;
- if ($("input:focus").length > 0 && (e.which === 38 || e.which === 40)) {
+ if ($('input:focus').length > 0 && (e.which === 38 || e.which === 40)) {
return false;
}
if (e.which === 40) {
if (liSelected) {
next = liSelected.next();
if (next.length > 0) {
- liSelected.removeClass("selected");
- liSelected = next.addClass("selected");
+ liSelected.removeClass('selected');
+ liSelected = next.addClass('selected');
}
} else {
- liSelected = li.eq(0).addClass("selected");
+ liSelected = li.eq(0).addClass('selected');
}
return $(liSelected).focus();
} else if (e.which === 38) {
if (liSelected) {
next = liSelected.prev();
if (next.length > 0) {
- liSelected.removeClass("selected");
- liSelected = next.addClass("selected");
+ liSelected.removeClass('selected');
+ liSelected = next.addClass('selected');
}
} else {
- liSelected = li.last().addClass("selected");
+ liSelected = li.last().addClass('selected');
}
return $(liSelected).focus();
} else if (e.which === 13) {
diff --git a/app/assets/javascripts/u2f/authenticate.js b/app/assets/javascripts/u2f/authenticate.js
index 78fd7ad441f..abfc81e681e 100644
--- a/app/assets/javascripts/u2f/authenticate.js
+++ b/app/assets/javascripts/u2f/authenticate.js
@@ -49,7 +49,7 @@ export default class U2FAuthenticate {
start() {
return importU2FLibrary()
- .then((utils) => {
+ .then(utils => {
this.u2fUtils = utils;
this.renderInProgress();
})
@@ -57,14 +57,19 @@ export default class U2FAuthenticate {
}
authenticate() {
- return this.u2fUtils.sign(this.appId, this.challenge, this.signRequests,
- (response) => {
+ return this.u2fUtils.sign(
+ this.appId,
+ this.challenge,
+ this.signRequests,
+ response => {
if (response.errorCode) {
const error = new U2FError(response.errorCode, 'authenticate');
return this.renderError(error);
}
return this.renderAuthenticated(JSON.stringify(response));
- }, 10);
+ },
+ 10,
+ );
}
renderTemplate(name, params) {
@@ -99,5 +104,4 @@ export default class U2FAuthenticate {
this.container[0].classList.add('hidden');
this.fallbackUI.classList.remove('hidden');
}
-
}
diff --git a/app/assets/javascripts/u2f/register.js b/app/assets/javascripts/u2f/register.js
index 01e259a741d..43c814c8070 100644
--- a/app/assets/javascripts/u2f/register.js
+++ b/app/assets/javascripts/u2f/register.js
@@ -34,7 +34,7 @@ export default class U2FRegister {
start() {
return importU2FLibrary()
- .then((utils) => {
+ .then(utils => {
this.u2fUtils = utils;
this.renderSetup();
})
@@ -42,14 +42,19 @@ export default class U2FRegister {
}
register() {
- return this.u2fUtils.register(this.appId, this.registerRequests, this.signRequests,
- (response) => {
+ return this.u2fUtils.register(
+ this.appId,
+ this.registerRequests,
+ this.signRequests,
+ response => {
if (response.errorCode) {
const error = new U2FError(response.errorCode, 'register');
return this.renderError(error);
}
return this.renderRegistered(JSON.stringify(response));
- }, 10);
+ },
+ 10,
+ );
}
renderTemplate(name, params) {
diff --git a/app/assets/javascripts/u2f/util.js b/app/assets/javascripts/u2f/util.js
index 5778f00332d..b706481c02f 100644
--- a/app/assets/javascripts/u2f/util.js
+++ b/app/assets/javascripts/u2f/util.js
@@ -19,11 +19,10 @@ function getChromeVersion(userAgent) {
export function canInjectU2fApi(userAgent) {
const isSupportedChrome = isChrome(userAgent) && getChromeVersion(userAgent) >= 41;
const isSupportedOpera = isOpera(userAgent) && getOperaVersion(userAgent) >= 40;
- const isMobile = (
+ const isMobile =
userAgent.indexOf('droid') >= 0 ||
userAgent.indexOf('CriOS') >= 0 ||
- /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent)
- );
+ /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent);
return (isSupportedChrome || isSupportedOpera) && !isMobile;
}
diff --git a/app/assets/javascripts/ui_development_kit.js b/app/assets/javascripts/ui_development_kit.js
index 9b242ea779d..be18ac5da24 100644
--- a/app/assets/javascripts/ui_development_kit.js
+++ b/app/assets/javascripts/ui_development_kit.js
@@ -4,13 +4,17 @@ import Api from './api';
export default () => {
$('#js-project-dropdown').glDropdown({
data: (term, callback) => {
- Api.projects(term, {
- order_by: 'last_activity_at',
- }, (data) => {
- callback(data);
- });
+ Api.projects(
+ term,
+ {
+ order_by: 'last_activity_at',
+ },
+ data => {
+ callback(data);
+ },
+ );
},
- text: project => (project.name_with_namespace || project.name),
+ text: project => project.name_with_namespace || project.name,
selectable: true,
fieldName: 'author_id',
filterable: true,
@@ -18,6 +22,6 @@ export default () => {
fields: ['name_with_namespace'],
},
id: data => data.id,
- isSelected: data => (data.id === 2),
+ isSelected: data => data.id === 2,
});
};
diff --git a/app/assets/javascripts/usage_ping_consent.js b/app/assets/javascripts/usage_ping_consent.js
index ae3fde190e3..d3d745a3c11 100644
--- a/app/assets/javascripts/usage_ping_consent.js
+++ b/app/assets/javascripts/usage_ping_consent.js
@@ -1,24 +1,25 @@
import $ from 'jquery';
import axios from './lib/utils/axios_utils';
import Flash, { hideFlash } from './flash';
-import { convertPermissionToBoolean } from './lib/utils/common_utils';
+import { parseBoolean } from './lib/utils/common_utils';
export default () => {
- $('body').on('click', '.js-usage-consent-action', (e) => {
+ $('body').on('click', '.js-usage-consent-action', e => {
e.preventDefault();
e.stopImmediatePropagation(); // overwrite rails listener
const { url, checkEnabled, pingEnabled } = e.target.dataset;
const data = {
application_setting: {
- version_check_enabled: convertPermissionToBoolean(checkEnabled),
- usage_ping_enabled: convertPermissionToBoolean(pingEnabled),
+ version_check_enabled: parseBoolean(checkEnabled),
+ usage_ping_enabled: parseBoolean(pingEnabled),
},
};
const hideConsentMessage = () => hideFlash(document.querySelector('.ping-consent-message'));
- axios.put(url, data)
+ axios
+ .put(url, data)
.then(() => {
hideConsentMessage();
})
diff --git a/app/assets/javascripts/users_select.js b/app/assets/javascripts/users_select.js
index e19bbbacf4d..ce051582299 100644
--- a/app/assets/javascripts/users_select.js
+++ b/app/assets/javascripts/users_select.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, one-var, no-var, prefer-rest-params, quotes, max-len, one-var-declaration-per-line, vars-on-top, prefer-arrow-callback, consistent-return, comma-dangle, object-shorthand, no-shadow, no-unused-vars, no-else-return, no-self-compare, prefer-template, no-unused-expressions, yoda, prefer-spread, no-void, camelcase, no-param-reassign */
+/* eslint-disable func-names, one-var, no-var, prefer-rest-params, vars-on-top, prefer-arrow-callback, consistent-return, object-shorthand, no-shadow, no-unused-vars, no-else-return, no-self-compare, prefer-template, no-unused-expressions, yoda, prefer-spread, camelcase, no-param-reassign */
/* global Issuable */
/* global emitSidebarEvent */
@@ -15,8 +15,8 @@ function UsersSelect(currentUser, els, options = {}) {
var $els;
this.users = this.users.bind(this);
this.user = this.user.bind(this);
- this.usersPath = "/autocomplete/users.json";
- this.userPath = "/autocomplete/users/:id.json";
+ this.usersPath = '/autocomplete/users.json';
+ this.userPath = '/autocomplete/users/:id.json';
if (currentUser != null) {
if (typeof currentUser === 'object') {
this.currentUser = currentUser;
@@ -33,156 +33,180 @@ function UsersSelect(currentUser, els, options = {}) {
$els = $('.js-user-search');
}
- $els.each((function(_this) {
- return function(i, dropdown) {
- var options = {};
- var $block, $collapsedSidebar, $dropdown, $loading, $selectbox, $value, abilityName, assignTo, assigneeTemplate, collapsedAssigneeTemplate, defaultLabel, defaultNullUser, firstUser, issueURL, selectedId, selectedIdDefault, showAnyUser, showNullUser, showMenuAbove;
- $dropdown = $(dropdown);
- options.projectId = $dropdown.data('projectId');
- options.groupId = $dropdown.data('groupId');
- options.showCurrentUser = $dropdown.data('currentUser');
- options.todoFilter = $dropdown.data('todoFilter');
- options.todoStateFilter = $dropdown.data('todoStateFilter');
- showNullUser = $dropdown.data('nullUser');
- defaultNullUser = $dropdown.data('nullUserDefault');
- showMenuAbove = $dropdown.data('showMenuAbove');
- showAnyUser = $dropdown.data('anyUser');
- firstUser = $dropdown.data('firstUser');
- options.authorId = $dropdown.data('authorId');
- defaultLabel = $dropdown.data('defaultLabel');
- issueURL = $dropdown.data('issueUpdate');
- $selectbox = $dropdown.closest('.selectbox');
- $block = $selectbox.closest('.block');
- abilityName = $dropdown.data('abilityName');
- $value = $block.find('.value');
- $collapsedSidebar = $block.find('.sidebar-collapsed-user');
- $loading = $block.find('.block-loading').fadeOut();
- selectedIdDefault = (defaultNullUser && showNullUser) ? 0 : null;
- selectedId = $dropdown.data('selected');
-
- if (selectedId === undefined) {
- selectedId = selectedIdDefault;
- }
-
- const assignYourself = function () {
- const unassignedSelected = $dropdown.closest('.selectbox')
- .find(`input[name='${$dropdown.data('fieldName')}'][value=0]`);
-
- if (unassignedSelected) {
- unassignedSelected.remove();
+ $els.each(
+ (function(_this) {
+ return function(i, dropdown) {
+ var options = {};
+ var $block,
+ $collapsedSidebar,
+ $dropdown,
+ $loading,
+ $selectbox,
+ $value,
+ abilityName,
+ assignTo,
+ assigneeTemplate,
+ collapsedAssigneeTemplate,
+ defaultLabel,
+ defaultNullUser,
+ firstUser,
+ issueURL,
+ selectedId,
+ selectedIdDefault,
+ showAnyUser,
+ showNullUser,
+ showMenuAbove;
+ $dropdown = $(dropdown);
+ options.projectId = $dropdown.data('projectId');
+ options.groupId = $dropdown.data('groupId');
+ options.showCurrentUser = $dropdown.data('currentUser');
+ options.todoFilter = $dropdown.data('todoFilter');
+ options.todoStateFilter = $dropdown.data('todoStateFilter');
+ showNullUser = $dropdown.data('nullUser');
+ defaultNullUser = $dropdown.data('nullUserDefault');
+ showMenuAbove = $dropdown.data('showMenuAbove');
+ showAnyUser = $dropdown.data('anyUser');
+ firstUser = $dropdown.data('firstUser');
+ options.authorId = $dropdown.data('authorId');
+ defaultLabel = $dropdown.data('defaultLabel');
+ issueURL = $dropdown.data('issueUpdate');
+ $selectbox = $dropdown.closest('.selectbox');
+ $block = $selectbox.closest('.block');
+ abilityName = $dropdown.data('abilityName');
+ $value = $block.find('.value');
+ $collapsedSidebar = $block.find('.sidebar-collapsed-user');
+ $loading = $block.find('.block-loading').fadeOut();
+ selectedIdDefault = defaultNullUser && showNullUser ? 0 : null;
+ selectedId = $dropdown.data('selected');
+
+ if (selectedId === undefined) {
+ selectedId = selectedIdDefault;
}
- // Save current selected user to the DOM
- const input = document.createElement('input');
- input.type = 'hidden';
- input.name = $dropdown.data('fieldName');
+ const assignYourself = function() {
+ const unassignedSelected = $dropdown
+ .closest('.selectbox')
+ .find(`input[name='${$dropdown.data('fieldName')}'][value=0]`);
- const currentUserInfo = $dropdown.data('currentUserInfo');
-
- if (currentUserInfo) {
- input.value = currentUserInfo.id;
- input.dataset.meta = _.escape(currentUserInfo.name);
- } else if (_this.currentUser) {
- input.value = _this.currentUser.id;
- }
-
- if ($selectbox) {
- $dropdown.parent().before(input);
- } else {
- $dropdown.after(input);
- }
- };
-
- if ($block[0]) {
- $block[0].addEventListener('assignYourself', assignYourself);
- }
-
- const getSelectedUserInputs = function() {
- return $selectbox
- .find(`input[name="${$dropdown.data('fieldName')}"]`);
- };
+ if (unassignedSelected) {
+ unassignedSelected.remove();
+ }
- const getSelected = function() {
- return getSelectedUserInputs()
- .map((index, input) => parseInt(input.value, 10))
- .get();
- };
+ // Save current selected user to the DOM
+ const input = document.createElement('input');
+ input.type = 'hidden';
+ input.name = $dropdown.data('fieldName');
- const checkMaxSelect = function() {
- const maxSelect = $dropdown.data('maxSelect');
- if (maxSelect) {
- const selected = getSelected();
+ const currentUserInfo = $dropdown.data('currentUserInfo');
- if (selected.length > maxSelect) {
- const firstSelectedId = selected[0];
- const firstSelected = $dropdown.closest('.selectbox')
- .find(`input[name='${$dropdown.data('fieldName')}'][value=${firstSelectedId}]`);
+ if (currentUserInfo) {
+ input.value = currentUserInfo.id;
+ input.dataset.meta = _.escape(currentUserInfo.name);
+ } else if (_this.currentUser) {
+ input.value = _this.currentUser.id;
+ }
- firstSelected.remove();
- emitSidebarEvent('sidebar.removeAssignee', {
- id: firstSelectedId,
- });
+ if ($selectbox) {
+ $dropdown.parent().before(input);
+ } else {
+ $dropdown.after(input);
}
- }
- };
+ };
- const getMultiSelectDropdownTitle = function(selectedUser, isSelected) {
- const selectedUsers = getSelected()
- .filter(u => u !== 0);
-
- const firstUser = getSelectedUserInputs()
- .map((index, input) => ({
- name: input.dataset.meta,
- value: parseInt(input.value, 10),
- }))
- .filter(u => u.id !== 0)
- .get(0);
-
- if (selectedUsers.length === 0) {
- return 'Unassigned';
- } else if (selectedUsers.length === 1) {
- return firstUser.name;
- } else if (isSelected) {
- const otherSelected = selectedUsers.filter(s => s !== selectedUser.id);
- return `${selectedUser.name} + ${otherSelected.length} more`;
- } else {
- return `${firstUser.name} + ${selectedUsers.length - 1} more`;
+ if ($block[0]) {
+ $block[0].addEventListener('assignYourself', assignYourself);
}
- };
- $('.assign-to-me-link').on('click', (e) => {
- e.preventDefault();
- $(e.currentTarget).hide();
+ const getSelectedUserInputs = function() {
+ return $selectbox.find(`input[name="${$dropdown.data('fieldName')}"]`);
+ };
+
+ const getSelected = function() {
+ return getSelectedUserInputs()
+ .map((index, input) => parseInt(input.value, 10))
+ .get();
+ };
+
+ const checkMaxSelect = function() {
+ const maxSelect = $dropdown.data('maxSelect');
+ if (maxSelect) {
+ const selected = getSelected();
+
+ if (selected.length > maxSelect) {
+ const firstSelectedId = selected[0];
+ const firstSelected = $dropdown
+ .closest('.selectbox')
+ .find(`input[name='${$dropdown.data('fieldName')}'][value=${firstSelectedId}]`);
+
+ firstSelected.remove();
+ emitSidebarEvent('sidebar.removeAssignee', {
+ id: firstSelectedId,
+ });
+ }
+ }
+ };
+
+ const getMultiSelectDropdownTitle = function(selectedUser, isSelected) {
+ const selectedUsers = getSelected().filter(u => u !== 0);
+
+ const firstUser = getSelectedUserInputs()
+ .map((index, input) => ({
+ name: input.dataset.meta,
+ value: parseInt(input.value, 10),
+ }))
+ .filter(u => u.id !== 0)
+ .get(0);
+
+ if (selectedUsers.length === 0) {
+ return 'Unassigned';
+ } else if (selectedUsers.length === 1) {
+ return firstUser.name;
+ } else if (isSelected) {
+ const otherSelected = selectedUsers.filter(s => s !== selectedUser.id);
+ return `${selectedUser.name} + ${otherSelected.length} more`;
+ } else {
+ return `${firstUser.name} + ${selectedUsers.length - 1} more`;
+ }
+ };
- if ($dropdown.data('multiSelect')) {
- assignYourself();
- checkMaxSelect();
+ $('.assign-to-me-link').on('click', e => {
+ e.preventDefault();
+ $(e.currentTarget).hide();
- const currentUserInfo = $dropdown.data('currentUserInfo');
- $dropdown.find('.dropdown-toggle-text').text(getMultiSelectDropdownTitle(currentUserInfo)).removeClass('is-default');
- } else {
- const $input = $(`input[name="${$dropdown.data('fieldName')}"]`);
- $input.val(gon.current_user_id);
- selectedId = $input.val();
- $dropdown.find('.dropdown-toggle-text').text(gon.current_user_fullname).removeClass('is-default');
- }
- });
-
- $block.on('click', '.js-assign-yourself', (e) => {
- e.preventDefault();
- return assignTo(_this.currentUser.id);
- });
-
- assignTo = function(selected) {
- var data;
- data = {};
- data[abilityName] = {};
- data[abilityName].assignee_id = selected != null ? selected : null;
- $loading.removeClass('hidden').fadeIn();
- $dropdown.trigger('loading.gl.dropdown');
-
- return axios.put(issueURL, data)
- .then(({ data }) => {
+ if ($dropdown.data('multiSelect')) {
+ assignYourself();
+ checkMaxSelect();
+
+ const currentUserInfo = $dropdown.data('currentUserInfo');
+ $dropdown
+ .find('.dropdown-toggle-text')
+ .text(getMultiSelectDropdownTitle(currentUserInfo))
+ .removeClass('is-default');
+ } else {
+ const $input = $(`input[name="${$dropdown.data('fieldName')}"]`);
+ $input.val(gon.current_user_id);
+ selectedId = $input.val();
+ $dropdown
+ .find('.dropdown-toggle-text')
+ .text(gon.current_user_fullname)
+ .removeClass('is-default');
+ }
+ });
+
+ $block.on('click', '.js-assign-yourself', e => {
+ e.preventDefault();
+ return assignTo(_this.currentUser.id);
+ });
+
+ assignTo = function(selected) {
+ var data;
+ data = {};
+ data[abilityName] = {};
+ data[abilityName].assignee_id = selected != null ? selected : null;
+ $loading.removeClass('hidden').fadeIn();
+ $dropdown.trigger('loading.gl.dropdown');
+
+ return axios.put(issueURL, data).then(({ data }) => {
var user, tooltipTitle;
$dropdown.trigger('loaded.gl.dropdown');
$loading.fadeOut();
@@ -190,14 +214,14 @@ function UsersSelect(currentUser, els, options = {}) {
user = {
name: data.assignee.name,
username: data.assignee.username,
- avatar: data.assignee.avatar_url
+ avatar: data.assignee.avatar_url,
};
tooltipTitle = _.escape(user.name);
} else {
user = {
name: 'Unassigned',
username: '',
- avatar: ''
+ avatar: '',
};
tooltipTitle = __('Assignee');
}
@@ -205,319 +229,341 @@ function UsersSelect(currentUser, els, options = {}) {
$collapsedSidebar.attr('title', tooltipTitle).tooltip('_fixTitle');
return $collapsedSidebar.html(collapsedAssigneeTemplate(user));
});
- };
- collapsedAssigneeTemplate = _.template('<% if( avatar ) { %> <a class="author-link" href="/<%- username %>"> <img width="24" class="avatar avatar-inline s24" alt="" src="<%- avatar %>"> </a> <% } else { %> <i class="fa fa-user"></i> <% } %>');
- assigneeTemplate = _.template('<% if (username) { %> <a class="author-link bold" href="/<%- username %>"> <% if( avatar ) { %> <img width="32" class="avatar avatar-inline s32" alt="" src="<%- avatar %>"> <% } %> <span class="author"><%- name %></span> <span class="username"> @<%- username %> </span> </a> <% } else { %> <span class="no-value assign-yourself"> No assignee - <a href="#" class="js-assign-yourself"> assign yourself </a> </span> <% } %>');
- return $dropdown.glDropdown({
- showMenuAbove: showMenuAbove,
- data: function(term, callback) {
- return _this.users(term, options, function(users) {
- // GitLabDropdownFilter returns this.instance
- // GitLabDropdownRemote returns this.options.instance
- const glDropdown = this.instance || this.options.instance;
- glDropdown.options.processData(term, users, callback);
- }.bind(this));
- },
- processData: function(term, data, callback) {
- let users = data;
-
- // Only show assigned user list when there is no search term
- if ($dropdown.hasClass('js-multiselect') && term.length === 0) {
- const selectedInputs = getSelectedUserInputs();
-
- // Potential duplicate entries when dealing with issue board
- // because issue board is also managed by vue
- const selectedUsers = _.uniq(selectedInputs, false, a => a.value)
- .filter((input) => {
- const userId = parseInt(input.value, 10);
- const inUsersArray = users.find(u => u.id === userId);
-
- return !inUsersArray && userId !== 0;
- })
- .map((input) => {
- const userId = parseInt(input.value, 10);
- const { avatarUrl, avatar_url, name, username } = input.dataset;
- return {
- avatar_url: avatarUrl || avatar_url,
- id: userId,
- name,
- username,
- };
- });
+ };
+ collapsedAssigneeTemplate = _.template(
+ '<% if( avatar ) { %> <a class="author-link" href="/<%- username %>"> <img width="24" class="avatar avatar-inline s24" alt="" src="<%- avatar %>"> </a> <% } else { %> <i class="fa fa-user"></i> <% } %>',
+ );
+ assigneeTemplate = _.template(
+ '<% if (username) { %> <a class="author-link bold" href="/<%- username %>"> <% if( avatar ) { %> <img width="32" class="avatar avatar-inline s32" alt="" src="<%- avatar %>"> <% } %> <span class="author"><%- name %></span> <span class="username"> @<%- username %> </span> </a> <% } else { %> <span class="no-value assign-yourself"> No assignee - <a href="#" class="js-assign-yourself"> assign yourself </a> </span> <% } %>',
+ );
+ return $dropdown.glDropdown({
+ showMenuAbove: showMenuAbove,
+ data: function(term, callback) {
+ return _this.users(
+ term,
+ options,
+ function(users) {
+ // GitLabDropdownFilter returns this.instance
+ // GitLabDropdownRemote returns this.options.instance
+ const glDropdown = this.instance || this.options.instance;
+ glDropdown.options.processData(term, users, callback);
+ }.bind(this),
+ );
+ },
+ processData: function(term, data, callback) {
+ let users = data;
+
+ // Only show assigned user list when there is no search term
+ if ($dropdown.hasClass('js-multiselect') && term.length === 0) {
+ const selectedInputs = getSelectedUserInputs();
+
+ // Potential duplicate entries when dealing with issue board
+ // because issue board is also managed by vue
+ const selectedUsers = _.uniq(selectedInputs, false, a => a.value)
+ .filter(input => {
+ const userId = parseInt(input.value, 10);
+ const inUsersArray = users.find(u => u.id === userId);
+
+ return !inUsersArray && userId !== 0;
+ })
+ .map(input => {
+ const userId = parseInt(input.value, 10);
+ const { avatarUrl, avatar_url, name, username } = input.dataset;
+ return {
+ avatar_url: avatarUrl || avatar_url,
+ id: userId,
+ name,
+ username,
+ };
+ });
- users = data.concat(selectedUsers);
- }
+ users = data.concat(selectedUsers);
+ }
- let anyUser;
- let index;
- let len;
- let name;
- let obj;
- let showDivider;
- if (term.length === 0) {
- showDivider = 0;
- if (firstUser) {
- // Move current user to the front of the list
- for (index = 0, len = users.length; index < len; index += 1) {
- obj = users[index];
- if (obj.username === firstUser) {
- users.splice(index, 1);
- users.unshift(obj);
- break;
+ let anyUser;
+ let index;
+ let len;
+ let name;
+ let obj;
+ let showDivider;
+ if (term.length === 0) {
+ showDivider = 0;
+ if (firstUser) {
+ // Move current user to the front of the list
+ for (index = 0, len = users.length; index < len; index += 1) {
+ obj = users[index];
+ if (obj.username === firstUser) {
+ users.splice(index, 1);
+ users.unshift(obj);
+ break;
+ }
}
}
- }
- if (showNullUser) {
- showDivider += 1;
- users.unshift({
- beforeDivider: true,
- name: 'Unassigned',
- id: 0
- });
- }
- if (showAnyUser) {
- showDivider += 1;
- name = showAnyUser;
- if (name === true) {
- name = 'Any User';
+ if (showNullUser) {
+ showDivider += 1;
+ users.unshift({
+ beforeDivider: true,
+ name: 'Unassigned',
+ id: 0,
+ });
+ }
+ if (showAnyUser) {
+ showDivider += 1;
+ name = showAnyUser;
+ if (name === true) {
+ name = 'Any User';
+ }
+ anyUser = {
+ beforeDivider: true,
+ name: name,
+ id: null,
+ };
+ users.unshift(anyUser);
}
- anyUser = {
- beforeDivider: true,
- name: name,
- id: null
- };
- users.unshift(anyUser);
- }
- if (showDivider) {
- users.splice(showDivider, 0, 'divider');
- }
+ if (showDivider) {
+ users.splice(showDivider, 0, 'divider');
+ }
- if ($dropdown.hasClass('js-multiselect')) {
- const selected = getSelected().filter(i => i !== 0);
+ if ($dropdown.hasClass('js-multiselect')) {
+ const selected = getSelected().filter(i => i !== 0);
- if (selected.length > 0) {
- if ($dropdown.data('dropdownHeader')) {
- showDivider += 1;
- users.splice(showDivider, 0, {
- header: $dropdown.data('dropdownHeader'),
- });
- }
+ if (selected.length > 0) {
+ if ($dropdown.data('dropdownHeader')) {
+ showDivider += 1;
+ users.splice(showDivider, 0, {
+ header: $dropdown.data('dropdownHeader'),
+ });
+ }
- const selectedUsers = users
- .filter(u => selected.indexOf(u.id) !== -1)
- .sort((a, b) => a.name > b.name);
+ const selectedUsers = users
+ .filter(u => selected.indexOf(u.id) !== -1)
+ .sort((a, b) => a.name > b.name);
- users = users.filter(u => selected.indexOf(u.id) === -1);
+ users = users.filter(u => selected.indexOf(u.id) === -1);
- selectedUsers.forEach((selectedUser) => {
- showDivider += 1;
- users.splice(showDivider, 0, selectedUser);
- });
+ selectedUsers.forEach(selectedUser => {
+ showDivider += 1;
+ users.splice(showDivider, 0, selectedUser);
+ });
- users.splice(showDivider + 1, 0, 'divider');
+ users.splice(showDivider + 1, 0, 'divider');
+ }
}
}
- }
- callback(users);
- if (showMenuAbove) {
- $dropdown.data('glDropdown').positionMenuAbove();
- }
- },
- filterable: true,
- filterRemote: true,
- search: {
- fields: ['name', 'username']
- },
- selectable: true,
- fieldName: $dropdown.data('fieldName'),
- toggleLabel: function(selected, el, glDropdown) {
- const inputValue = glDropdown.filterInput.val();
-
- if (this.multiSelect && inputValue === '') {
- // Remove non-users from the fullData array
- const users = glDropdown.filteredFullData();
- const callback = glDropdown.parseData.bind(glDropdown);
-
- // Update the data model
- this.processData(inputValue, users, callback);
- }
+ callback(users);
+ if (showMenuAbove) {
+ $dropdown.data('glDropdown').positionMenuAbove();
+ }
+ },
+ filterable: true,
+ filterRemote: true,
+ search: {
+ fields: ['name', 'username'],
+ },
+ selectable: true,
+ fieldName: $dropdown.data('fieldName'),
+ toggleLabel: function(selected, el, glDropdown) {
+ const inputValue = glDropdown.filterInput.val();
+
+ if (this.multiSelect && inputValue === '') {
+ // Remove non-users from the fullData array
+ const users = glDropdown.filteredFullData();
+ const callback = glDropdown.parseData.bind(glDropdown);
+
+ // Update the data model
+ this.processData(inputValue, users, callback);
+ }
- if (this.multiSelect) {
- return getMultiSelectDropdownTitle(selected, $(el).hasClass('is-active'));
- }
+ if (this.multiSelect) {
+ return getMultiSelectDropdownTitle(selected, $(el).hasClass('is-active'));
+ }
- if (selected && 'id' in selected && $(el).hasClass('is-active')) {
- $dropdown.find('.dropdown-toggle-text').removeClass('is-default');
- if (selected.text) {
- return selected.text;
+ if (selected && 'id' in selected && $(el).hasClass('is-active')) {
+ $dropdown.find('.dropdown-toggle-text').removeClass('is-default');
+ if (selected.text) {
+ return selected.text;
+ } else {
+ return selected.name;
+ }
} else {
- return selected.name;
+ $dropdown.find('.dropdown-toggle-text').addClass('is-default');
+ return defaultLabel;
+ }
+ },
+ defaultLabel: defaultLabel,
+ hidden: function(e) {
+ if ($dropdown.hasClass('js-multiselect')) {
+ emitSidebarEvent('sidebar.saveAssignees');
}
- } else {
- $dropdown.find('.dropdown-toggle-text').addClass('is-default');
- return defaultLabel;
- }
- },
- defaultLabel: defaultLabel,
- hidden: function(e) {
- if ($dropdown.hasClass('js-multiselect')) {
- emitSidebarEvent('sidebar.saveAssignees');
- }
-
- if (!$dropdown.data('alwaysShowSelectbox')) {
- $selectbox.hide();
- // Recalculate where .value is because vue might have changed it
- $block = $selectbox.closest('.block');
- $value = $block.find('.value');
- // display:block overrides the hide-collapse rule
- $value.css('display', '');
- }
- },
- multiSelect: $dropdown.hasClass('js-multiselect'),
- inputMeta: $dropdown.data('inputMeta'),
- clicked: function(options) {
- const { $el, e, isMarking } = options;
- const user = options.selectedObj;
-
- if ($dropdown.hasClass('js-multiselect')) {
- const isActive = $el.hasClass('is-active');
- const previouslySelected = $dropdown.closest('.selectbox')
- .find("input[name='" + ($dropdown.data('fieldName')) + "'][value!=0]");
-
- // Enables support for limiting the number of users selected
- // Automatically removes the first on the list if more users are selected
- checkMaxSelect();
+ if (!$dropdown.data('alwaysShowSelectbox')) {
+ $selectbox.hide();
- if (user.beforeDivider && user.name.toLowerCase() === 'unassigned') {
- // Unassigned selected
- previouslySelected.each((index, element) => {
- const id = parseInt(element.value, 10);
- element.remove();
- });
- emitSidebarEvent('sidebar.removeAllAssignees');
- } else if (isActive) {
- // user selected
- emitSidebarEvent('sidebar.addAssignee', user);
+ // Recalculate where .value is because vue might have changed it
+ $block = $selectbox.closest('.block');
+ $value = $block.find('.value');
+ // display:block overrides the hide-collapse rule
+ $value.css('display', '');
+ }
+ },
+ multiSelect: $dropdown.hasClass('js-multiselect'),
+ inputMeta: $dropdown.data('inputMeta'),
+ clicked: function(options) {
+ const { $el, e, isMarking } = options;
+ const user = options.selectedObj;
- // Remove unassigned selection (if it was previously selected)
- const unassignedSelected = $dropdown.closest('.selectbox')
- .find("input[name='" + ($dropdown.data('fieldName')) + "'][value=0]");
+ if ($dropdown.hasClass('js-multiselect')) {
+ const isActive = $el.hasClass('is-active');
+ const previouslySelected = $dropdown
+ .closest('.selectbox')
+ .find("input[name='" + $dropdown.data('fieldName') + "'][value!=0]");
+
+ // Enables support for limiting the number of users selected
+ // Automatically removes the first on the list if more users are selected
+ checkMaxSelect();
+
+ if (user.beforeDivider && user.name.toLowerCase() === 'unassigned') {
+ // Unassigned selected
+ previouslySelected.each((index, element) => {
+ const id = parseInt(element.value, 10);
+ element.remove();
+ });
+ emitSidebarEvent('sidebar.removeAllAssignees');
+ } else if (isActive) {
+ // user selected
+ emitSidebarEvent('sidebar.addAssignee', user);
+
+ // Remove unassigned selection (if it was previously selected)
+ const unassignedSelected = $dropdown
+ .closest('.selectbox')
+ .find("input[name='" + $dropdown.data('fieldName') + "'][value=0]");
+
+ if (unassignedSelected) {
+ unassignedSelected.remove();
+ }
+ } else {
+ if (previouslySelected.length === 0) {
+ // Select unassigned because there is no more selected users
+ this.addInput($dropdown.data('fieldName'), 0, {});
+ }
- if (unassignedSelected) {
- unassignedSelected.remove();
- }
- } else {
- if (previouslySelected.length === 0) {
- // Select unassigned because there is no more selected users
- this.addInput($dropdown.data('fieldName'), 0, {});
+ // User unselected
+ emitSidebarEvent('sidebar.removeAssignee', user);
}
- // User unselected
- emitSidebarEvent('sidebar.removeAssignee', user);
+ if (getSelected().find(u => u === gon.current_user_id)) {
+ $('.assign-to-me-link').hide();
+ } else {
+ $('.assign-to-me-link').show();
+ }
}
- if (getSelected().find(u => u === gon.current_user_id)) {
- $('.assign-to-me-link').hide();
- } else {
- $('.assign-to-me-link').show();
+ var isIssueIndex, isMRIndex, page, selected;
+ page = $('body').attr('data-page');
+ isIssueIndex = page === 'projects:issues:index';
+ isMRIndex = page === page && page === 'projects:merge_requests:index';
+ if (
+ $dropdown.hasClass('js-filter-bulk-update') ||
+ $dropdown.hasClass('js-issuable-form-dropdown')
+ ) {
+ e.preventDefault();
+
+ const isSelecting = user.id !== selectedId;
+ selectedId = isSelecting ? user.id : selectedIdDefault;
+
+ if (selectedId === gon.current_user_id) {
+ $('.assign-to-me-link').hide();
+ } else {
+ $('.assign-to-me-link').show();
+ }
+ return;
+ }
+ if ($el.closest('.add-issues-modal').length) {
+ ModalStore.store.filter[$dropdown.data('fieldName')] = user.id;
+ } else if (handleClick) {
+ e.preventDefault();
+ handleClick(user, isMarking);
+ } else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
+ return Issuable.filterResults($dropdown.closest('form'));
+ } else if ($dropdown.hasClass('js-filter-submit')) {
+ return $dropdown.closest('form').submit();
+ } else if (!$dropdown.hasClass('js-multiselect')) {
+ selected = $dropdown
+ .closest('.selectbox')
+ .find("input[name='" + $dropdown.data('fieldName') + "']")
+ .val();
+ return assignTo(selected);
}
- }
- var isIssueIndex, isMRIndex, page, selected;
- page = $('body').attr('data-page');
- isIssueIndex = page === 'projects:issues:index';
- isMRIndex = (page === page && page === 'projects:merge_requests:index');
- if ($dropdown.hasClass('js-filter-bulk-update') || $dropdown.hasClass('js-issuable-form-dropdown')) {
- e.preventDefault();
+ // Automatically close dropdown after assignee is selected
+ // since CE has no multiple assignees
+ // EE does not have a max-select
+ if (
+ $dropdown.data('maxSelect') &&
+ getSelected().length === $dropdown.data('maxSelect')
+ ) {
+ // Close the dropdown
+ $dropdown.dropdown('toggle');
+ }
+ },
+ id: function(user) {
+ return user.id;
+ },
+ opened: function(e) {
+ const $el = $(e.currentTarget);
+ const selected = getSelected();
+ if ($dropdown.hasClass('js-issue-board-sidebar') && selected.length === 0) {
+ this.addInput($dropdown.data('fieldName'), 0, {});
+ }
+ $el.find('.is-active').removeClass('is-active');
- const isSelecting = (user.id !== selectedId);
- selectedId = isSelecting ? user.id : selectedIdDefault;
+ function highlightSelected(id) {
+ $el.find(`li[data-user-id="${id}"] .dropdown-menu-user-link`).addClass('is-active');
+ }
- if (selectedId === gon.current_user_id) {
- $('.assign-to-me-link').hide();
+ if (selected.length > 0) {
+ getSelected().forEach(selectedId => highlightSelected(selectedId));
+ } else if ($dropdown.hasClass('js-issue-board-sidebar')) {
+ highlightSelected(0);
} else {
- $('.assign-to-me-link').show();
+ highlightSelected(selectedId);
}
- return;
- }
- if ($el.closest('.add-issues-modal').length) {
- ModalStore.store.filter[$dropdown.data('fieldName')] = user.id;
- } else if (handleClick) {
- e.preventDefault();
- handleClick(user, isMarking);
- } else if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
- return Issuable.filterResults($dropdown.closest('form'));
- } else if ($dropdown.hasClass('js-filter-submit')) {
- return $dropdown.closest('form').submit();
- } else if (!$dropdown.hasClass('js-multiselect')) {
- selected = $dropdown.closest('.selectbox').find("input[name='" + ($dropdown.data('fieldName')) + "']").val();
- return assignTo(selected);
- }
-
- // Automatically close dropdown after assignee is selected
- // since CE has no multiple assignees
- // EE does not have a max-select
- if ($dropdown.data('maxSelect') &&
- getSelected().length === $dropdown.data('maxSelect')) {
- // Close the dropdown
- $dropdown.dropdown('toggle');
- }
- },
- id: function (user) {
- return user.id;
- },
- opened: function(e) {
- const $el = $(e.currentTarget);
- const selected = getSelected();
- if ($dropdown.hasClass('js-issue-board-sidebar') && selected.length === 0) {
- this.addInput($dropdown.data('fieldName'), 0, {});
- }
- $el.find('.is-active').removeClass('is-active');
-
- function highlightSelected(id) {
- $el.find(`li[data-user-id="${id}"] .dropdown-menu-user-link`).addClass('is-active');
- }
+ },
+ updateLabel: $dropdown.data('dropdownTitle'),
+ renderRow: function(user) {
+ var avatar, img, listClosingTags, listWithName, listWithUserName, username;
+ username = user.username ? '@' + user.username : '';
+ avatar = user.avatar_url ? user.avatar_url : gon.default_avatar_url;
- if (selected.length > 0) {
- getSelected().forEach(selectedId => highlightSelected(selectedId));
- } else if ($dropdown.hasClass('js-issue-board-sidebar')) {
- highlightSelected(0);
- } else {
- highlightSelected(selectedId);
- }
- },
- updateLabel: $dropdown.data('dropdownTitle'),
- renderRow: function(user) {
- var avatar, img, listClosingTags, listWithName, listWithUserName, username;
- username = user.username ? "@" + user.username : "";
- avatar = user.avatar_url ? user.avatar_url : gon.default_avatar_url;
+ let selected = false;
- let selected = false;
+ if (this.multiSelect) {
+ selected = getSelected().find(u => user.id === u);
- if (this.multiSelect) {
- selected = getSelected().find(u => user.id === u);
+ const { fieldName } = this;
+ const field = $dropdown
+ .closest('.selectbox')
+ .find("input[name='" + fieldName + "'][value='" + user.id + "']");
- const { fieldName } = this;
- const field = $dropdown.closest('.selectbox').find("input[name='" + fieldName + "'][value='" + user.id + "']");
-
- if (field.length) {
- selected = true;
+ if (field.length) {
+ selected = true;
+ }
+ } else {
+ selected = user.id === selectedId;
}
- } else {
- selected = user.id === selectedId;
- }
- img = "";
- if (user.beforeDivider != null) {
- `<li><a href='#' class='${selected === true ? 'is-active' : ''}'>${_.escape(user.name)}</a></li>`;
- } else {
- img = "<img src='" + avatar + "' class='avatar avatar-inline' width='32' />";
- }
+ img = '';
+ if (user.beforeDivider != null) {
+ `<li><a href='#' class='${selected === true ? 'is-active' : ''}'>${_.escape(
+ user.name,
+ )}</a></li>`;
+ } else {
+ img = "<img src='" + avatar + "' class='avatar avatar-inline' width='32' />";
+ }
- return `
+ return `
<li data-user-id=${user.id}>
<a href='#' class='dropdown-menu-user-link ${selected === true ? 'is-active' : ''}'>
${img}
@@ -528,114 +574,117 @@ function UsersSelect(currentUser, els, options = {}) {
</a>
</li>
`;
- }
- });
- };
- })(this));
- $('.ajax-users-select').each((function(_this) {
- return function(i, select) {
- var firstUser, showAnyUser, showEmailUser, showNullUser;
- var options = {};
- options.skipLdap = $(select).hasClass('skip_ldap');
- options.projectId = $(select).data('projectId');
- options.groupId = $(select).data('groupId');
- options.showCurrentUser = $(select).data('currentUser');
- options.authorId = $(select).data('authorId');
- options.skipUsers = $(select).data('skipUsers');
- showNullUser = $(select).data('nullUser');
- showAnyUser = $(select).data('anyUser');
- showEmailUser = $(select).data('emailUser');
- firstUser = $(select).data('firstUser');
- return $(select).select2({
- placeholder: "Search for a user",
- multiple: $(select).hasClass('multiselect'),
- minimumInputLength: 0,
- query: function(query) {
- return _this.users(query.term, options, function(users) {
- var anyUser, data, emailUser, index, len, name, nullUser, obj, ref;
- data = {
- results: users
- };
- if (query.term.length === 0) {
- if (firstUser) {
- // Move current user to the front of the list
- ref = data.results;
-
- for (index = 0, len = ref.length; index < len; index += 1) {
- obj = ref[index];
- if (obj.username === firstUser) {
- data.results.splice(index, 1);
- data.results.unshift(obj);
- break;
+ },
+ });
+ };
+ })(this),
+ );
+ $('.ajax-users-select').each(
+ (function(_this) {
+ return function(i, select) {
+ var firstUser, showAnyUser, showEmailUser, showNullUser;
+ var options = {};
+ options.skipLdap = $(select).hasClass('skip_ldap');
+ options.projectId = $(select).data('projectId');
+ options.groupId = $(select).data('groupId');
+ options.showCurrentUser = $(select).data('currentUser');
+ options.authorId = $(select).data('authorId');
+ options.skipUsers = $(select).data('skipUsers');
+ showNullUser = $(select).data('nullUser');
+ showAnyUser = $(select).data('anyUser');
+ showEmailUser = $(select).data('emailUser');
+ firstUser = $(select).data('firstUser');
+ return $(select).select2({
+ placeholder: 'Search for a user',
+ multiple: $(select).hasClass('multiselect'),
+ minimumInputLength: 0,
+ query: function(query) {
+ return _this.users(query.term, options, function(users) {
+ var anyUser, data, emailUser, index, len, name, nullUser, obj, ref;
+ data = {
+ results: users,
+ };
+ if (query.term.length === 0) {
+ if (firstUser) {
+ // Move current user to the front of the list
+ ref = data.results;
+
+ for (index = 0, len = ref.length; index < len; index += 1) {
+ obj = ref[index];
+ if (obj.username === firstUser) {
+ data.results.splice(index, 1);
+ data.results.unshift(obj);
+ break;
+ }
}
}
- }
- if (showNullUser) {
- nullUser = {
- name: 'Unassigned',
- id: 0
- };
- data.results.unshift(nullUser);
- }
- if (showAnyUser) {
- name = showAnyUser;
- if (name === true) {
- name = 'Any User';
+ if (showNullUser) {
+ nullUser = {
+ name: 'Unassigned',
+ id: 0,
+ };
+ data.results.unshift(nullUser);
}
- anyUser = {
- name: name,
- id: null
+ if (showAnyUser) {
+ name = showAnyUser;
+ if (name === true) {
+ name = 'Any User';
+ }
+ anyUser = {
+ name: name,
+ id: null,
+ };
+ data.results.unshift(anyUser);
+ }
+ }
+ if (showEmailUser && data.results.length === 0 && query.term.match(/^[^@]+@[^@]+$/)) {
+ var trimmed = query.term.trim();
+ emailUser = {
+ name: 'Invite "' + trimmed + '" by email',
+ username: trimmed,
+ id: trimmed,
+ invite: true,
};
- data.results.unshift(anyUser);
+ data.results.unshift(emailUser);
}
- }
- if (showEmailUser && data.results.length === 0 && query.term.match(/^[^@]+@[^@]+$/)) {
- var trimmed = query.term.trim();
- emailUser = {
- name: "Invite \"" + query.term + "\" by email",
- username: trimmed,
- id: trimmed,
- invite: true
- };
- data.results.unshift(emailUser);
- }
- return query.callback(data);
- });
- },
- initSelection: function() {
- var args;
- args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
- return _this.initSelection.apply(_this, args);
- },
- formatResult: function() {
- var args;
- args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
- return _this.formatResult.apply(_this, args);
- },
- formatSelection: function() {
- var args;
- args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
- return _this.formatSelection.apply(_this, args);
- },
- dropdownCssClass: "ajax-users-dropdown",
- // we do not want to escape markup since we are displaying html in results
- escapeMarkup: function(m) {
- return m;
- }
- });
- };
- })(this));
+ return query.callback(data);
+ });
+ },
+ initSelection: function() {
+ var args;
+ args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
+ return _this.initSelection.apply(_this, args);
+ },
+ formatResult: function() {
+ var args;
+ args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
+ return _this.formatResult.apply(_this, args);
+ },
+ formatSelection: function() {
+ var args;
+ args = 1 <= arguments.length ? [].slice.call(arguments, 0) : [];
+ return _this.formatSelection.apply(_this, args);
+ },
+ dropdownCssClass: 'ajax-users-dropdown',
+ // we do not want to escape markup since we are displaying html in results
+ escapeMarkup: function(m) {
+ return m;
+ },
+ });
+ };
+ })(this),
+ );
}
UsersSelect.prototype.initSelection = function(element, callback) {
var id, nullUser;
id = $(element).val();
- if (id === "0") {
+ if (id === '0') {
nullUser = {
- name: 'Unassigned'
+ name: 'Unassigned',
};
return callback(nullUser);
- } else if (id !== "") {
+ } else if (id !== '') {
return this.user(id, callback);
}
};
@@ -647,7 +696,21 @@ UsersSelect.prototype.formatResult = function(user) {
} else {
avatar = gon.default_avatar_url;
}
- return "<div class='user-result " + (!user.username ? 'no-username' : void 0) + "'> <div class='user-image'><img class='avatar avatar-inline s32' src='" + avatar + "'></div> <div class='user-name dropdown-menu-user-full-name'>" + _.escape(user.name) + "</div> <div class='user-username dropdown-menu-user-username'>" + (!user.invite ? "@" + _.escape(user.username) : "") + "</div> </div>";
+ return `
+ <div class='user-result'>
+ <div class='user-image'>
+ <img class='avatar avatar-inline s32' src='${avatar}'>
+ </div>
+ <div class='user-info'>
+ <div class='user-name dropdown-menu-user-full-name'>
+ ${_.escape(user.name)}
+ </div>
+ <div class='user-username dropdown-menu-user-username text-secondary'>
+ ${!user.invite ? '@' + _.escape(user.username) : ''}
+ </div>
+ </div>
+ </div>
+ `;
};
UsersSelect.prototype.formatSelection = function(user) {
@@ -662,10 +725,9 @@ UsersSelect.prototype.user = function(user_id, callback) {
var url;
url = this.buildUrl(this.userPath);
url = url.replace(':id', user_id);
- return axios.get(url)
- .then(({ data }) => {
- callback(data);
- });
+ return axios.get(url).then(({ data }) => {
+ callback(data);
+ });
};
// Return users list. Filtered by query
@@ -682,12 +744,11 @@ UsersSelect.prototype.users = function(query, options, callback) {
todo_state_filter: options.todoStateFilter || null,
current_user: options.showCurrentUser || null,
author_id: options.authorId || null,
- skip_users: options.skipUsers || null
+ skip_users: options.skipUsers || null,
};
- return axios.get(url, { params })
- .then(({ data }) => {
- callback(data);
- });
+ return axios.get(url, { params }).then(({ data }) => {
+ callback(data);
+ });
};
UsersSelect.prototype.buildUrl = function(url) {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
index d530ab2767b..2f2a37347af 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue
@@ -1,13 +1,16 @@
<script>
+import { GlTooltipDirective } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import FilteredSearchDropdown from '~/vue_shared/components/filtered_search_dropdown.vue';
+import { __ } from '~/locale';
import timeagoMixin from '../../vue_shared/mixins/timeago';
-import tooltip from '../../vue_shared/directives/tooltip';
import LoadingButton from '../../vue_shared/components/loading_button.vue';
import { visitUrl } from '../../lib/utils/url_utility';
import createFlash from '../../flash';
import MemoryUsage from './memory_usage.vue';
import StatusIcon from './mr_widget_status_icon.vue';
+import ReviewAppLink from './review_app_link.vue';
import MRWidgetService from '../services/mr_widget_service';
export default {
@@ -18,18 +21,29 @@ export default {
StatusIcon,
Icon,
TooltipOnTruncate,
+ FilteredSearchDropdown,
+ ReviewAppLink,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
- mixins: [
- timeagoMixin,
- ],
+ mixins: [timeagoMixin],
props: {
deployment: {
type: Object,
required: true,
},
+ showMetrics: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ deployedTextMap: {
+ running: __('Deploying to'),
+ success: __('Deployed to'),
+ failed: __('Failed to deploy to'),
+ created: __('Will deploy to'),
+ canceled: __('Failed to deploy to'),
},
data() {
return {
@@ -50,12 +64,29 @@ export default {
return !!(this.deployment.url && this.deployment.name);
},
hasMetrics() {
- return !!(this.deployment.metrics_url);
+ return !!this.deployment.metrics_url;
+ },
+ deployedText() {
+ return this.$options.deployedTextMap[this.deployment.status];
+ },
+ isDeployInProgress() {
+ return this.deployment.status === 'running';
+ },
+ deployInProgressTooltip() {
+ return this.isDeployInProgress
+ ? __('Stopping this environment is currently not possible as a deployment is in progress')
+ : '';
+ },
+ shouldRenderDropdown() {
+ return this.deployment.changes && this.deployment.changes.length > 0;
+ },
+ showMemoryUsage() {
+ return this.hasMetrics && this.showMetrics;
},
},
methods: {
stopEnvironment() {
- const msg = 'Are you sure you want to stop this environment?';
+ const msg = __('Are you sure you want to stop this environment?');
const isConfirmed = confirm(msg); // eslint-disable-line
if (isConfirmed) {
@@ -63,7 +94,7 @@ export default {
MRWidgetService.stopEnvironment(this.deployment.stop_url)
.then(res => res.data)
- .then((data) => {
+ .then(data => {
if (data.redirect_url) {
visitUrl(data.redirect_url);
}
@@ -81,15 +112,13 @@ export default {
</script>
<template>
- <div class="mr-widget-heading deploy-heading append-bottom-default">
+ <div class="deploy-heading">
<div class="ci-widget media">
<div class="media-body">
<div class="deploy-body">
- <div class="deployment-info">
+ <div class="js-deployment-info deployment-info">
<template v-if="hasDeploymentMeta">
- <span>
- Deployed to
- </span>
+ <span> {{ deployedText }} </span>
<tooltip-on-truncate
:title="deployment.name"
truncate-target="child"
@@ -106,41 +135,75 @@ export default {
</tooltip-on-truncate>
</template>
<span
- v-tooltip
v-if="hasDeploymentTime"
+ v-gl-tooltip
:title="deployment.deployed_at_formatted"
class="js-deploy-time"
>
{{ deployTimeago }}
</span>
<memory-usage
- v-if="hasMetrics"
+ v-if="showMemoryUsage"
:metrics-url="deployment.metrics_url"
:metrics-monitoring-url="deployment.metrics_monitoring_url"
/>
</div>
<div>
- <a
- v-if="hasExternalUrls"
- :href="deployment.external_url"
- target="_blank"
- rel="noopener noreferrer nofollow"
- class="deploy-link js-deploy-url btn btn-default btn-sm inline"
- >
- <span>
- View app
- <icon name="external-link" />
- </span>
- </a>
- <loading-button
+ <template v-if="hasExternalUrls">
+ <filtered-search-dropdown
+ v-if="shouldRenderDropdown"
+ class="js-mr-wigdet-deployment-dropdown inline"
+ :items="deployment.changes"
+ :main-action-link="deployment.external_url"
+ filter-key="path"
+ >
+ <template slot="mainAction" slot-scope="slotProps">
+ <review-app-link
+ :link="deployment.external_url"
+ :css-class="`deploy-link js-deploy-url inline ${slotProps.className}`"
+ />
+ </template>
+
+ <template slot="result" slot-scope="slotProps">
+ <a
+ :href="slotProps.result.external_url"
+ target="_blank"
+ rel="noopener noreferrer nofollow"
+ class="menu-item"
+ >
+ <strong class="str-truncated-100 append-bottom-0 d-block">
+ {{ slotProps.result.path }}
+ </strong>
+
+ <p class="text-secondary str-truncated-100 append-bottom-0 d-block">
+ {{ slotProps.result.external_url }}
+ </p>
+ </a>
+ </template>
+ </filtered-search-dropdown>
+ <review-app-link
+ v-else
+ :link="deployment.external_url"
+ css-class="js-deploy-url js-deploy-url-feature-flag deploy-link btn btn-default btn-sm inlin"
+ />
+ </template>
+ <span
v-if="deployment.stop_url"
- :loading="isStopping"
- container-class="btn btn-default btn-sm inline prepend-left-4"
- title="Stop environment"
- @click="stopEnvironment"
+ v-gl-tooltip
+ :title="deployInProgressTooltip"
+ class="d-inline-block"
+ tabindex="0"
>
- <icon name="stop" />
- </loading-button>
+ <loading-button
+ :loading="isStopping"
+ :disabled="isDeployInProgress"
+ :title="__('Stop environment')"
+ container-class="js-stop-env btn btn-default btn-sm inline prepend-left-4"
+ @click="stopEnvironment"
+ >
+ <icon name="stop" />
+ </loading-button>
+ </span>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/memory_usage.vue b/app/assets/javascripts/vue_merge_request_widget/components/memory_usage.vue
index 5e76f6b1cac..7ce454b7338 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/memory_usage.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/memory_usage.vue
@@ -60,11 +60,29 @@ export default {
let memoryUsageMsg = '';
if (memoryTo > memoryFrom) {
- memoryUsageMsg = sprintf(s__('mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB'), messageProps, false);
+ memoryUsageMsg = sprintf(
+ s__(
+ 'mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB',
+ ),
+ messageProps,
+ false,
+ );
} else if (memoryTo < memoryFrom) {
- memoryUsageMsg = sprintf(s__('mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB'), messageProps, false);
+ memoryUsageMsg = sprintf(
+ s__(
+ 'mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB',
+ ),
+ messageProps,
+ false,
+ );
} else {
- memoryUsageMsg = sprintf(s__('mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB'), messageProps, false);
+ memoryUsageMsg = sprintf(
+ s__(
+ 'mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB',
+ ),
+ messageProps,
+ false,
+ );
}
return memoryUsageMsg;
@@ -77,7 +95,7 @@ export default {
methods: {
getMegabytes(bytesString) {
const valueInBytes = Number(bytesString).toFixed(2);
- return (bytesToMiB(valueInBytes)).toFixed(2);
+ return bytesToMiB(valueInBytes).toFixed(2);
},
computeGraphData(metrics, deploymentTime) {
this.loadingMetrics = false;
@@ -103,7 +121,7 @@ export default {
loadMetrics() {
backOff((next, stop) => {
MRWidgetService.fetchMetrics(this.metricsUrl)
- .then((res) => {
+ .then(res => {
if (res.status === statusCodes.NO_CONTENT) {
this.backOffRequestCounter += 1;
/* eslint-disable no-unused-expressions */
@@ -114,14 +132,14 @@ export default {
})
.catch(stop);
})
- .then((res) => {
+ .then(res => {
if (res.status === statusCodes.NO_CONTENT) {
return res;
}
return res.data;
})
- .then((data) => {
+ .then(data => {
this.computeGraphData(data.metrics, data.deployment_time);
return data;
})
@@ -136,27 +154,19 @@ export default {
<template>
<div class="mr-info-list clearfix mr-memory-usage js-mr-memory-usage">
- <p
- v-if="shouldShowLoading"
- class="usage-info js-usage-info usage-info-loading">
- <i
- class="fa fa-spinner fa-spin usage-info-load-spinner"
- aria-hidden="true">
- </i>{{ s__('mrWidget|Loading deployment statistics') }}
+ <p v-if="shouldShowLoading" class="usage-info js-usage-info usage-info-loading">
+ <i class="fa fa-spinner fa-spin usage-info-load-spinner" aria-hidden="true"> </i
+ >{{ s__('mrWidget|Loading deployment statistics') }}
</p>
<p
v-if="shouldShowMemoryGraph"
class="usage-info js-usage-info"
- v-html="memoryChangeMessage">
- </p>
- <p
- v-if="shouldShowLoadFailure"
- class="usage-info js-usage-info usage-info-failed">
+ v-html="memoryChangeMessage"
+ ></p>
+ <p v-if="shouldShowLoadFailure" class="usage-info js-usage-info usage-info-failed">
{{ s__('mrWidget|Failed to load deployment statistics') }}
</p>
- <p
- v-if="shouldShowMetricsUnavailable"
- class="usage-info js-usage-info usage-info-unavailable">
+ <p v-if="shouldShowMetricsUnavailable" class="usage-info js-usage-info usage-info-unavailable">
{{ s__('mrWidget|Deployment statistics are not available currently') }}
</p>
<memory-graph
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue
index 22c2f74f900..84937aa9510 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue
@@ -1,36 +1,36 @@
<script>
- import tooltip from '../../vue_shared/directives/tooltip';
+import tooltip from '../../vue_shared/directives/tooltip';
- export default {
- name: 'MrWidgetAuthor',
- directives: {
- tooltip,
+export default {
+ name: 'MrWidgetAuthor',
+ directives: {
+ tooltip,
+ },
+ props: {
+ author: {
+ type: Object,
+ required: true,
},
- props: {
- author: {
- type: Object,
- required: true,
- },
- showAuthorName: {
- type: Boolean,
- required: false,
- default: true,
- },
- showAuthorTooltip: {
- type: Boolean,
- required: false,
- default: false,
- },
+ showAuthorName: {
+ type: Boolean,
+ required: false,
+ default: true,
},
- computed: {
- authorUrl() {
- return this.author.webUrl || this.author.web_url;
- },
- avatarUrl() {
- return this.author.avatarUrl || this.author.avatar_url;
- },
+ showAuthorTooltip: {
+ type: Boolean,
+ required: false,
+ default: false,
},
- };
+ },
+ computed: {
+ authorUrl() {
+ return this.author.webUrl || this.author.web_url;
+ },
+ avatarUrl() {
+ return this.author.avatarUrl || this.author.avatar_url;
+ },
+ },
+};
</script>
<template>
<a
@@ -39,15 +39,7 @@
:title="author.name"
class="author-link inline"
>
- <img
- :src="avatarUrl"
- class="avatar avatar-inline s16"
- />
- <span
- v-if="showAuthorName"
- class="author"
- >
- {{ author.name }}
- </span>
+ <img :src="avatarUrl" class="avatar avatar-inline s16" />
+ <span v-if="showAuthorName" class="author"> {{ author.name }} </span>
</a>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author_time.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author_time.vue
index ba16cb9e2c8..6b3007fce51 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author_time.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author_time.vue
@@ -1,45 +1,39 @@
<script>
- import tooltip from '~/vue_shared/directives/tooltip';
- import MrWidgetAuthor from './mr_widget_author.vue';
+import tooltip from '~/vue_shared/directives/tooltip';
+import MrWidgetAuthor from './mr_widget_author.vue';
- export default {
- name: 'MrWidgetAuthorTime',
- components: {
- MrWidgetAuthor,
+export default {
+ name: 'MrWidgetAuthorTime',
+ components: {
+ MrWidgetAuthor,
+ },
+ directives: {
+ tooltip,
+ },
+ props: {
+ actionText: {
+ type: String,
+ required: true,
},
- directives: {
- tooltip,
+ author: {
+ type: Object,
+ required: true,
},
- props: {
- actionText: {
- type: String,
- required: true,
- },
- author: {
- type: Object,
- required: true,
- },
- dateTitle: {
- type: String,
- required: true,
- },
- dateReadable: {
- type: String,
- required: true,
- },
+ dateTitle: {
+ type: String,
+ required: true,
},
- };
+ dateReadable: {
+ type: String,
+ required: true,
+ },
+ },
+};
</script>
<template>
<h4 class="js-mr-widget-author">
{{ actionText }}
<mr-widget-author :author="author" />
- <time
- v-tooltip
- :title="dateTitle"
- data-container="body"
- >
- {{ dateReadable }}
- </time>
+ <time v-tooltip :title="dateTitle" data-container="body"> {{ dateReadable }} </time>
</h4>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_container.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_container.vue
new file mode 100644
index 00000000000..5967ca026e5
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_container.vue
@@ -0,0 +1,6 @@
+<template>
+ <div class="mr-widget-heading">
+ <div class="mr-widget-content"><slot name="default"></slot></div>
+ <slot name="footer"></slot>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
index 4c3f8dff3c4..3b9fc2661ef 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
@@ -6,6 +6,7 @@ import Icon from '~/vue_shared/components/icon.vue';
import clipboardButton from '~/vue_shared/components/clipboard_button.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import MrWidgetIcon from './mr_widget_icon.vue';
export default {
name: 'MRWidgetHeader',
@@ -13,6 +14,7 @@ export default {
Icon,
clipboardButton,
TooltipOnTruncate,
+ MrWidgetIcon,
},
directives: {
tooltip,
@@ -28,11 +30,17 @@ export default {
return this.mr.divergedCommitsCount > 0;
},
commitsBehindText() {
- return sprintf(s__('mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch'), {
- commitsBehindLinkStart: `<a href="${_.escape(this.mr.targetBranchPath)}">`,
- commitsBehind: n__('%d commit behind', '%d commits behind', this.mr.divergedCommitsCount),
- commitsBehindLinkEnd: '</a>',
- }, false);
+ return sprintf(
+ s__(
+ 'mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch',
+ ),
+ {
+ commitsBehindLinkStart: `<a href="${_.escape(this.mr.targetBranchPath)}">`,
+ commitsBehind: n__('%d commit behind', '%d commits behind', this.mr.divergedCommitsCount),
+ commitsBehindLinkEnd: '</a>',
+ },
+ false,
+ );
},
branchNameClipboardData() {
// This supports code in app/assets/javascripts/copy_to_clipboard.js that
@@ -45,17 +53,24 @@ export default {
},
webIdePath() {
if (this.mr.canPushToSourceBranch) {
- return mergeUrlParams({
- target_project: this.mr.sourceProjectFullPath !== this.mr.targetProjectFullPath ?
- this.mr.targetProjectFullPath : '',
- }, webIDEUrl(`/${this.mr.sourceProjectFullPath}/merge_requests/${this.mr.iid}`));
+ return mergeUrlParams(
+ {
+ target_project:
+ this.mr.sourceProjectFullPath !== this.mr.targetProjectFullPath
+ ? this.mr.targetProjectFullPath
+ : '',
+ },
+ webIDEUrl(`/${this.mr.sourceProjectFullPath}/merge_requests/${this.mr.iid}`),
+ );
}
return null;
},
ideButtonTitle() {
return !this.mr.canPushToSourceBranch
- ? s__('mrWidget|You are not allowed to edit this project directly. Please fork to make changes.')
+ ? s__(
+ 'mrWidget|You are not allowed to edit this project directly. Please fork to make changes.',
+ )
: '';
},
},
@@ -63,13 +78,11 @@ export default {
</script>
<template>
<div class="mr-source-target append-bottom-default">
- <div class="git-merge-icon-container append-right-default">
- <icon name="git-merge" />
- </div>
+ <mr-widget-icon name="git-merge" />
<div class="git-merge-container d-flex">
<div class="normal">
<strong>
- {{ s__("mrWidget|Request to merge") }}
+ {{ s__('mrWidget|Request to merge') }}
<tooltip-on-truncate
:title="mr.sourceBranch"
truncate-target="child"
@@ -80,89 +93,65 @@ export default {
:title="__('Copy branch name to clipboard')"
css-class="btn-default btn-transparent btn-clipboard"
/>
- {{ s__("mrWidget|into") }}
+ {{ s__('mrWidget|into') }}
<tooltip-on-truncate
:title="mr.targetBranch"
truncate-target="child"
class="label-branch label-truncate"
>
- <a
- :href="mr.targetBranchTreePath"
- class="js-target-branch"
- >
- {{ mr.targetBranch }}
- </a>
+ <a :href="mr.targetBranchTreePath" class="js-target-branch"> {{ mr.targetBranch }} </a>
</tooltip-on-truncate>
</strong>
<div
v-if="shouldShowCommitsBehindText"
class="diverged-commits-count"
v-html="commitsBehindText"
- >
- </div>
+ ></div>
</div>
- <div
- v-if="mr.isOpen"
- class="branch-actions"
- >
- <span
+ <div v-if="mr.isOpen" class="branch-actions d-flex">
+ <a
+ v-if="!mr.sourceBranchRemoved"
v-tooltip
+ :href="webIdePath"
:title="ideButtonTitle"
+ :class="{ disabled: !mr.canPushToSourceBranch }"
+ class="btn btn-default js-web-ide d-none d-md-inline-block append-right-8"
data-placement="bottom"
tabindex="0"
+ role="button"
>
- <a
- v-if="!mr.sourceBranchRemoved"
- :href="webIdePath"
- :class="{ disabled: !mr.canPushToSourceBranch }"
- class="btn btn-default inline js-web-ide d-none d-md-inline-block"
- role="button"
- >
- {{ s__("mrWidget|Open in Web IDE") }}
- </a>
- </span>
+ {{ s__('mrWidget|Open in Web IDE') }}
+ </a>
<button
:disabled="mr.sourceBranchRemoved"
data-target="#modal_merge_info"
data-toggle="modal"
- class="btn btn-default inline js-check-out-branch"
+ class="btn btn-default js-check-out-branch append-right-default"
type="button"
>
- {{ s__("mrWidget|Check out branch") }}
+ {{ s__('mrWidget|Check out branch') }}
</button>
- <span class="dropdown prepend-left-10">
+ <span class="dropdown">
<button
type="button"
- class="btn inline dropdown-toggle"
+ class="btn dropdown-toggle"
data-toggle="dropdown"
aria-label="Download as"
aria-haspopup="true"
aria-expanded="false"
>
- <icon name="download" />
- <i
- class="fa fa-caret-down"
- aria-hidden="true">
- </i>
+ <icon name="download" /> <i class="fa fa-caret-down" aria-hidden="true"> </i>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li>
- <a
- :href="mr.emailPatchesPath"
- class="js-download-email-patches"
- download
- >
- {{ s__("mrWidget|Email patches") }}
+ <a :href="mr.emailPatchesPath" class="js-download-email-patches" download>
+ {{ s__('mrWidget|Email patches') }}
</a>
</li>
<li>
- <a
- :href="mr.plainDiffPath"
- class="js-download-plain-diff"
- download
- >
- {{ s__("mrWidget|Plain diff") }}
+ <a :href="mr.plainDiffPath" class="js-download-plain-diff" download>
+ {{ s__('mrWidget|Plain diff') }}
</a>
</li>
</ul>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_icon.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_icon.vue
new file mode 100644
index 00000000000..e3adc7f7af5
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_icon.vue
@@ -0,0 +1,17 @@
+<script>
+import Icon from '~/vue_shared/components/icon.vue';
+
+export default {
+ components: { Icon },
+ props: {
+ name: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="circle-icon-container append-right-default"><icon :name="name" /></div>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.vue
index 62b61e1f41f..a347269c916 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_merge_help.vue
@@ -1,24 +1,26 @@
<script>
- import { sprintf, s__ } from '~/locale';
+import { sprintf, s__ } from '~/locale';
- export default {
- name: 'MRWidgetMergeHelp',
- props: {
- missingBranch: {
- type: String,
- required: false,
- default: '',
- },
+export default {
+ name: 'MRWidgetMergeHelp',
+ props: {
+ missingBranch: {
+ type: String,
+ required: false,
+ default: '',
},
- computed: {
- missingBranchInfo() {
- return sprintf(
- s__('mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the'),
- { branch: this.missingBranch },
- );
- },
+ },
+ computed: {
+ missingBranchInfo() {
+ return sprintf(
+ s__(
+ 'mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the',
+ ),
+ { branch: this.missingBranch },
+ );
},
- };
+ },
+};
</script>
<template>
<section class="mr-widget-help">
@@ -26,7 +28,7 @@
{{ missingBranchInfo }}
</template>
<template v-else>
- {{ s__("mrWidget|You can merge this merge request manually using the") }}
+ {{ s__('mrWidget|You can merge this merge request manually using the') }}
</template>
<button
@@ -35,7 +37,7 @@
data-toggle="modal"
data-target="#modal_merge_info"
>
- {{ s__("mrWidget|command line") }}
+ {{ s__('mrWidget|command line') }}
</button>
</section>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
index fee41b239e8..f11cf21b0ca 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
@@ -1,5 +1,6 @@
<script>
/* eslint-disable vue/require-default-prop */
+import { sprintf, __ } from '~/locale';
import PipelineStage from '~/pipelines/components/stage.vue';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import Icon from '~/vue_shared/components/icon.vue';
@@ -36,6 +37,10 @@ export default {
type: String,
required: false,
},
+ troubleshootingDocsPath: {
+ type: String,
+ required: true,
+ },
},
computed: {
hasPipeline() {
@@ -57,96 +62,82 @@ export default {
hasCommitInfo() {
return this.pipeline.commit && Object.keys(this.pipeline.commit).length > 0;
},
+ errorText() {
+ return sprintf(
+ __(
+ 'Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}',
+ ),
+ {
+ linkStart: `<a href="${this.troubleshootingDocsPath}">`,
+ linkEnd: '</a>',
+ },
+ false,
+ );
+ },
},
};
</script>
<template>
- <div
- v-if="hasPipeline || hasCIError"
- class="mr-widget-heading append-bottom-default"
- >
- <div class="ci-widget media">
- <template v-if="hasCIError">
- <div
- class="add-border ci-status-icon ci-status-icon-failed ci-error
- js-ci-error append-right-default"
- >
- <icon
- :size="32"
- name="status_failed_borderless"
- />
- </div>
- <div class="media-body">
- Could not connect to the CI server. Please check your settings and try again
- </div>
- </template>
- <template v-else-if="hasPipeline">
- <a
- :href="status.details_path"
- class="align-self-start append-right-default"
- >
- <ci-icon
- :status="status"
- :size="32"
- :borderless="true"
- class="add-border"
- />
- </a>
- <div class="ci-widget-container d-flex">
- <div class="ci-widget-content">
- <div class="media-body">
- <div class="font-weight-bold">
- Pipeline
- <a
- :href="pipeline.path"
- class="pipeline-id font-weight-normal pipeline-number"
- >#{{ pipeline.id }}</a>
+ <div v-if="hasPipeline || hasCIError" class="ci-widget media">
+ <template v-if="hasCIError">
+ <div
+ class="add-border ci-status-icon ci-status-icon-failed ci-error
+ js-ci-error append-right-default"
+ >
+ <icon :size="32" name="status_failed_borderless" />
+ </div>
+ <div class="media-body" v-html="errorText"></div>
+ </template>
+ <template v-else-if="hasPipeline">
+ <a :href="status.details_path" class="align-self-start append-right-default">
+ <ci-icon :status="status" :size="32" :borderless="true" class="add-border" />
+ </a>
+ <div class="ci-widget-container d-flex">
+ <div class="ci-widget-content">
+ <div class="media-body">
+ <div class="font-weight-bold">
+ Pipeline
+ <a :href="pipeline.path" class="pipeline-id font-weight-normal pipeline-number"
+ >#{{ pipeline.id }}</a
+ >
- {{ pipeline.details.status.label }}
+ {{ pipeline.details.status.label }}
- <template v-if="hasCommitInfo">
- for
- <a
- :href="pipeline.commit.commit_path"
- class="commit-sha js-commit-link font-weight-normal"
- >
- {{ pipeline.commit.short_id }}</a>
- on
- <tooltip-on-truncate
- :title="sourceBranch"
- truncate-target="child"
- class="label-branch label-truncate"
- v-html="sourceBranchLink"
- />
- </template>
- </div>
- <div
- v-if="pipeline.coverage"
- class="coverage"
- >
- Coverage {{ pipeline.coverage }}%
- </div>
+ <template v-if="hasCommitInfo">
+ for
+ <a
+ :href="pipeline.commit.commit_path"
+ class="commit-sha js-commit-link font-weight-normal"
+ >
+ {{ pipeline.commit.short_id }}</a
+ >
+ on
+ <tooltip-on-truncate
+ :title="sourceBranch"
+ truncate-target="child"
+ class="label-branch label-truncate"
+ v-html="sourceBranchLink"
+ />
+ </template>
</div>
+ <div v-if="pipeline.coverage" class="coverage">Coverage {{ pipeline.coverage }}%</div>
</div>
- <div>
- <span class="mr-widget-pipeline-graph">
- <span
- v-if="hasStages"
- class="stage-cell"
+ </div>
+ <div>
+ <span class="mr-widget-pipeline-graph">
+ <span v-if="hasStages" class="stage-cell">
+ <div
+ v-for="(stage, i) in pipeline.details.stages"
+ :key="i"
+ class="stage-container dropdown js-mini-pipeline-graph mr-widget-pipeline-stages"
>
- <div
- v-for="(stage, i) in pipeline.details.stages"
- :key="i"
- class="stage-container dropdown js-mini-pipeline-graph mr-widget-pipeline-stages"
- >
- <pipeline-stage :stage="stage" />
- </div>
- </span>
+ <pipeline-stage :stage="stage" />
+ </div>
</span>
- </div>
+ </span>
</div>
- </template>
- </div>
+ </div>
+ </template>
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue
new file mode 100644
index 00000000000..5f5fe67b3c1
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline_container.vue
@@ -0,0 +1,74 @@
+<script>
+import Deployment from './deployment.vue';
+import MrWidgetContainer from './mr_widget_container.vue';
+import MrWidgetPipeline from './mr_widget_pipeline.vue';
+
+/**
+ * Renders the pipeline and related deployments from the store.
+ *
+ * | Props | Description
+ * |---------------|-------------
+ * | `mr` | This is the mr_widget store
+ * | `isPostMerge` | If true, show the "post merge" pipeline and deployments
+ */
+export default {
+ name: 'MrWidgetPipelineContainer',
+ components: {
+ Deployment,
+ MrWidgetContainer,
+ MrWidgetPipeline,
+ },
+ props: {
+ mr: {
+ type: Object,
+ required: true,
+ },
+ isPostMerge: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ pipeline() {
+ return this.isPostMerge ? this.mr.mergePipeline : this.mr.pipeline;
+ },
+ branch() {
+ return this.isPostMerge ? this.mr.targetBranch : this.mr.sourceBranch;
+ },
+ branchLink() {
+ return this.isPostMerge ? this.mr.targetBranch : this.mr.sourceBranchLink;
+ },
+ deployments() {
+ return this.isPostMerge ? this.mr.postMergeDeployments : this.mr.deployments;
+ },
+ deploymentClass() {
+ return this.isPostMerge ? 'js-post-deployment' : 'js-pre-deployment';
+ },
+ hasDeploymentMetrics() {
+ return this.isPostMerge;
+ },
+ },
+};
+</script>
+<template>
+ <mr-widget-container>
+ <mr-widget-pipeline
+ :pipeline="pipeline"
+ :ci-status="mr.ciStatus"
+ :has-ci="mr.hasCI"
+ :source-branch="branch"
+ :source-branch-link="branchLink"
+ :troubleshooting-docs-path="mr.troubleshootingDocsPath"
+ />
+ <div v-if="deployments.length" slot="footer" class="mr-widget-extension">
+ <deployment
+ v-for="deployment in deployments"
+ :key="deployment.id"
+ :class="deploymentClass"
+ :deployment="deployment"
+ :show-metrics="hasDeploymentMetrics"
+ />
+ </div>
+ </mr-widget-container>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
index 88d0fcd70f5..1b3b589c32f 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
@@ -1,43 +1,39 @@
<script>
- import { s__ } from '~/locale';
+import { s__ } from '~/locale';
- export default {
- name: 'MRWidgetRelatedLinks',
- props: {
- relatedLinks: {
- type: Object,
- required: true,
- default: () => ({}),
- },
- state: {
- type: String,
- required: false,
- default: '',
- },
+export default {
+ name: 'MRWidgetRelatedLinks',
+ props: {
+ relatedLinks: {
+ type: Object,
+ required: true,
+ default: () => ({}),
},
- computed: {
- closesText() {
- if (this.state === 'merged') {
- return s__('mrWidget|Closed');
- }
- if (this.state === 'closed') {
- return s__('mrWidget|Did not close');
- }
- return s__('mrWidget|Closes');
- },
+ state: {
+ type: String,
+ required: false,
+ default: '',
},
- };
+ },
+ computed: {
+ closesText() {
+ if (this.state === 'merged') {
+ return s__('mrWidget|Closed');
+ }
+ if (this.state === 'closed') {
+ return s__('mrWidget|Did not close');
+ }
+ return s__('mrWidget|Closes');
+ },
+ },
+};
</script>
<template>
<section class="mr-info-list mr-links">
- <p v-if="relatedLinks.closing">
- {{ closesText }} <span v-html="relatedLinks.closing"></span>
- </p>
+ <p v-if="relatedLinks.closing">{{ closesText }} <span v-html="relatedLinks.closing"></span></p>
<p v-if="relatedLinks.mentioned">
- {{ s__("mrWidget|Mentions") }} <span v-html="relatedLinks.mentioned"></span>
- </p>
- <p v-if="relatedLinks.assignToMe">
- <span v-html="relatedLinks.assignToMe"></span>
+ {{ s__('mrWidget|Mentions') }} <span v-html="relatedLinks.mentioned"></span>
</p>
+ <p v-if="relatedLinks.assignToMe"><span v-html="relatedLinks.assignToMe"></span></p>
</section>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue
index 035ae791a1d..780ced4d382 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_status_icon.vue
@@ -1,48 +1,41 @@
<script>
- import ciIcon from '../../vue_shared/components/ci_icon.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
+import ciIcon from '../../vue_shared/components/ci_icon.vue';
- export default {
- components: {
- ciIcon,
+export default {
+ components: {
+ ciIcon,
+ GlLoadingIcon,
+ },
+ props: {
+ status: {
+ type: String,
+ required: true,
},
- props: {
- status: {
- type: String,
- required: true,
- },
- showDisabledButton: {
- type: Boolean,
- required: false,
- default: false,
- },
+ showDisabledButton: {
+ type: Boolean,
+ required: false,
+ default: false,
},
- computed: {
- isLoading() {
- return this.status === 'loading';
- },
- statusObj() {
- return {
- group: this.status,
- icon: `status_${this.status}`,
- };
- },
+ },
+ computed: {
+ isLoading() {
+ return this.status === 'loading';
},
- };
+ statusObj() {
+ return {
+ group: this.status,
+ icon: `status_${this.status}`,
+ };
+ },
+ },
+};
</script>
<template>
<div class="space-children d-flex append-right-10 widget-status-icon">
- <div
- v-if="isLoading"
- class="mr-widget-icon"
- >
- <gl-loading-icon />
- </div>
+ <div v-if="isLoading" class="mr-widget-icon"><gl-loading-icon /></div>
- <ci-icon
- v-else
- :status="statusObj"
- :size="24"
- />
+ <ci-icon v-else :status="statusObj" :size="24" />
<button
v-if="showDisabledButton"
@@ -50,7 +43,7 @@
class="js-disabled-merge-button btn btn-success btn-sm"
disabled="true"
>
- {{ s__("mrWidget|Merge") }}
+ {{ s__('mrWidget|Merge') }}
</button>
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/review_app_link.vue b/app/assets/javascripts/vue_merge_request_widget/components/review_app_link.vue
new file mode 100644
index 00000000000..de9c122f268
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/review_app_link.vue
@@ -0,0 +1,24 @@
+<script>
+import Icon from '~/vue_shared/components/icon.vue';
+
+export default {
+ components: {
+ Icon,
+ },
+ props: {
+ link: {
+ type: String,
+ required: true,
+ },
+ cssClass: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+<template>
+ <a :href="link" target="_blank" rel="noopener noreferrer nofollow" :class="cssClass">
+ {{ __('View app') }} <icon name="external-link" />
+ </a>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue b/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
index 56879c04d16..dd940548e30 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/source_branch_removal_status.vue
@@ -1,34 +1,22 @@
<script>
- import tooltip from '../../vue_shared/directives/tooltip';
- import { __ } from '../../locale';
+import tooltip from '../../vue_shared/directives/tooltip';
+import { __ } from '../../locale';
- export default {
- directives: {
- tooltip,
- },
- created() {
- this.removesBranchText = __('<strong>Removes</strong> source branch');
- this.tooltipTitle = __('A user with write access to the source branch selected this option');
- },
- };
+export default {
+ directives: {
+ tooltip,
+ },
+ created() {
+ this.removesBranchText = __('<strong>Removes</strong> source branch');
+ this.tooltipTitle = __('A user with write access to the source branch selected this option');
+ },
+};
</script>
<template>
- <p
- v-once
- class="mr-info-list mr-links source-branch-removal-status append-bottom-0"
- >
- <span
- class="status-text"
- v-html="removesBranchText"
- >
- </span>
- <i
- v-tooltip
- :title="tooltipTitle"
- :aria-label="tooltipTitle"
- class="fa fa-question-circle"
- >
+ <p v-once class="mr-info-list mr-links source-branch-removal-status append-bottom-0">
+ <span class="status-text" v-html="removesBranchText"> </span>
+ <i v-tooltip :title="tooltipTitle" :aria-label="tooltipTitle" class="fa fa-question-circle">
</i>
</p>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue
index cfbd44d41b2..7ddcdd49df5 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue
@@ -1,30 +1,24 @@
<script>
- import statusIcon from '../mr_widget_status_icon.vue';
+import statusIcon from '../mr_widget_status_icon.vue';
- export default {
- name: 'MRWidgetArchived',
- components: {
- statusIcon,
- },
- };
+export default {
+ name: 'MRWidgetArchived',
+ components: {
+ statusIcon,
+ },
+};
</script>
<template>
<div class="mr-widget-body media">
<div class="space-children">
- <status-icon
- status="warning"
- />
- <button
- type="button"
- class="btn btn-success btn-sm"
- disabled="true"
- >
- {{ s__("mrWidget|Merge") }}
+ <status-icon status="warning" />
+ <button type="button" class="btn btn-success btn-sm" disabled="true">
+ {{ s__('mrWidget|Merge') }}
</button>
</div>
<div class="media-body">
<span class="bold">
- {{ s__("mrWidget|This project is archived, write access has been disabled") }}
+ {{ s__('mrWidget|This project is archived, write access has been disabled') }}
</span>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue
index 01294d5b40c..a3a44dd8e99 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue
@@ -1,40 +1,44 @@
<script>
- import eventHub from '../../event_hub';
- import statusIcon from '../mr_widget_status_icon.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
+import eventHub from '../../event_hub';
+import statusIcon from '../mr_widget_status_icon.vue';
- export default {
- name: 'MRWidgetAutoMergeFailed',
- components: {
- statusIcon,
+export default {
+ name: 'MRWidgetAutoMergeFailed',
+ components: {
+ statusIcon,
+ GlLoadingIcon,
+ },
+ props: {
+ mr: {
+ type: Object,
+ required: true,
},
- props: {
- mr: {
- type: Object,
- required: true,
- },
+ },
+ data() {
+ return {
+ isRefreshing: false,
+ };
+ },
+ methods: {
+ refreshWidget() {
+ this.isRefreshing = true;
+ eventHub.$emit('MRWidgetUpdateRequested', () => {
+ this.isRefreshing = false;
+ });
},
- data() {
- return {
- isRefreshing: false,
- };
- },
- methods: {
- refreshWidget() {
- this.isRefreshing = true;
- eventHub.$emit('MRWidgetUpdateRequested', () => {
- this.isRefreshing = false;
- });
- },
- },
- };
+ },
+};
</script>
<template>
<div class="mr-widget-body media">
<status-icon status="warning" />
<div class="media-body space-children">
<span class="bold">
- <template v-if="mr.mergeError">{{ mr.mergeError }}.</template>
- {{ s__("mrWidget|This merge request failed to be merged automatically") }}
+ <template v-if="mr.mergeError"
+ >{{ mr.mergeError }}.</template
+ >
+ {{ s__('mrWidget|This merge request failed to be merged automatically') }}
</span>
<button
:disabled="isRefreshing"
@@ -42,11 +46,8 @@
class="btn btn-sm btn-default"
@click="refreshWidget"
>
- <gl-loading-icon
- v-if="isRefreshing"
- :inline="true"
- />
- {{ s__("mrWidget|Refresh") }}
+ <gl-loading-icon v-if="isRefreshing" :inline="true" />
+ {{ s__('mrWidget|Refresh') }}
</button>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue
index ae6630dcd6f..cf26003d038 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vue
@@ -1,23 +1,18 @@
<script>
- import statusIcon from '../mr_widget_status_icon.vue';
+import statusIcon from '../mr_widget_status_icon.vue';
- export default {
- name: 'MRWidgetChecking',
- components: {
- statusIcon,
- },
- };
+export default {
+ name: 'MRWidgetChecking',
+ components: {
+ statusIcon,
+ },
+};
</script>
<template>
<div class="mr-widget-body media">
- <status-icon
- :show-disabled-button="true"
- status="loading"
- />
+ <status-icon :show-disabled-button="true" status="loading" />
<div class="media-body space-children">
- <span class="bold">
- {{ s__("mrWidget|Checking ability to merge automatically") }}
- </span>
+ <span class="bold"> {{ s__('mrWidget|Checking ability to merge automatically') }} </span>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue
index 25a57e520ee..a5c75369fa1 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue
@@ -1,29 +1,27 @@
<script>
- import MrWidgetAuthorTime from '../../components/mr_widget_author_time.vue';
- import statusIcon from '../mr_widget_status_icon.vue';
+import MrWidgetAuthorTime from '../../components/mr_widget_author_time.vue';
+import statusIcon from '../mr_widget_status_icon.vue';
- export default {
- name: 'MRWidgetClosed',
- components: {
- MrWidgetAuthorTime,
- statusIcon,
- },
- props: {
- /* TODO: This is providing all store and service down when it
+export default {
+ name: 'MRWidgetClosed',
+ components: {
+ MrWidgetAuthorTime,
+ statusIcon,
+ },
+ props: {
+ /* TODO: This is providing all store and service down when it
only needs metrics and targetBranch */
- mr: {
- type: Object,
- required: true,
- default: () => ({}),
- },
+ mr: {
+ type: Object,
+ required: true,
+ default: () => ({}),
},
- };
+ },
+};
</script>
<template>
<div class="mr-widget-body media">
- <status-icon
- status="warning"
- />
+ <status-icon status="warning" />
<div class="media-body">
<mr-widget-author-time
:action-text="s__('mrWidget|Closed by')"
@@ -34,13 +32,8 @@
<section class="mr-info-list">
<p>
- {{ s__("mrWidget|The changes were not merged into") }}
- <a
- :href="mr.targetBranchPath"
- class="label-branch"
- >
- {{ mr.targetBranch }}
- </a>
+ {{ s__('mrWidget|The changes were not merged into') }}
+ <a :href="mr.targetBranchPath" class="label-branch"> {{ mr.targetBranch }} </a>
</p>
</section>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
index dff9ec657b9..27352e0b2b1 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue
@@ -1,43 +1,41 @@
<script>
- import statusIcon from '../mr_widget_status_icon.vue';
+import statusIcon from '../mr_widget_status_icon.vue';
- export default {
- name: 'MRWidgetConflicts',
- components: {
- statusIcon,
- },
- props: {
- /* TODO: This is providing all store and service down when it
+export default {
+ name: 'MRWidgetConflicts',
+ components: {
+ statusIcon,
+ },
+ props: {
+ /* TODO: This is providing all store and service down when it
only needs a few props */
- mr: {
- type: Object,
- required: true,
- default: () => ({}),
- },
+ mr: {
+ type: Object,
+ required: true,
+ default: () => ({}),
},
- };
+ },
+};
</script>
<template>
<div class="mr-widget-body media">
- <status-icon
- :show-disabled-button="true"
- status="warning"
- />
+ <status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children">
- <span
- v-if="mr.shouldBeRebased"
- class="bold"
- >
- {{ s__(`mrWidget|Fast-forward merge is not possible.
-To merge this request, first rebase locally.`) }}
+ <span v-if="mr.shouldBeRebased" class="bold">
+ {{
+ s__(`mrWidget|Fast-forward merge is not possible.
+To merge this request, first rebase locally.`)
+ }}
</span>
<template v-else>
<span class="bold">
- {{ s__("mrWidget|There are merge conflicts") }}<span v-if="!mr.canMerge">.</span>
+ {{ s__('mrWidget|There are merge conflicts') }}<span v-if="!mr.canMerge">.</span>
<span v-if="!mr.canMerge">
- {{ s__(`mrWidget|Resolve these conflicts or ask someone
- with write access to this repository to merge it locally`) }}
+ {{
+ s__(`mrWidget|Resolve these conflicts or ask someone
+ with write access to this repository to merge it locally`)
+ }}
</span>
</span>
<a
@@ -45,7 +43,7 @@ To merge this request, first rebase locally.`) }}
:href="mr.conflictResolutionPath"
class="js-resolve-conflicts-button btn btn-default btn-sm"
>
- {{ s__("mrWidget|Resolve conflicts") }}
+ {{ s__('mrWidget|Resolve conflicts') }}
</a>
<button
v-if="mr.canMerge"
@@ -53,7 +51,7 @@ To merge this request, first rebase locally.`) }}
data-toggle="modal"
data-target="#modal_merge_info"
>
- {{ s__("mrWidget|Merge locally") }}
+ {{ s__('mrWidget|Merge locally') }}
</button>
</template>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
index c302960f16e..2a4dff71d9b 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue
@@ -74,38 +74,18 @@ export default {
<div class="mr-widget-body media">
<template v-if="isRefreshing">
<status-icon status="loading" />
- <span class="media-body bold js-refresh-label">
- {{ s__("mrWidget|Refreshing now") }}
- </span>
+ <span class="media-body bold js-refresh-label"> {{ s__('mrWidget|Refreshing now') }} </span>
</template>
<template v-else>
- <status-icon
- :show-disabled-button="true"
- status="warning"
- />
+ <status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children">
<span class="bold">
- <span
- v-if="mr.mergeError"
- class="has-error-message"
- >
- {{ mergeError }}.
- </span>
- <span v-else>
- {{ s__("mrWidget|Merge failed.") }}
- </span>
- <span
- :class="{ 'has-custom-error': mr.mergeError }"
- >
- {{ timerText }}
- </span>
+ <span v-if="mr.mergeError" class="has-error-message"> {{ mergeError }}. </span>
+ <span v-else> {{ s__('mrWidget|Merge failed.') }} </span>
+ <span :class="{ 'has-custom-error': mr.mergeError }"> {{ timerText }} </span>
</span>
- <button
- class="btn btn-default btn-sm js-refresh-button"
- type="button"
- @click="refresh"
- >
- {{ s__("mrWidget|Refresh now") }}
+ <button class="btn btn-default btn-sm js-refresh-button" type="button" @click="refresh">
+ {{ s__('mrWidget|Refresh now') }}
</button>
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue
index 97f4196b94d..02c76db4a50 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue
@@ -1,82 +1,82 @@
<script>
- import Flash from '../../../flash';
- import statusIcon from '../mr_widget_status_icon.vue';
- import MrWidgetAuthor from '../../components/mr_widget_author.vue';
- import eventHub from '../../event_hub';
+import Flash from '../../../flash';
+import statusIcon from '../mr_widget_status_icon.vue';
+import MrWidgetAuthor from '../../components/mr_widget_author.vue';
+import eventHub from '../../event_hub';
- export default {
- name: 'MRWidgetMergeWhenPipelineSucceeds',
- components: {
- MrWidgetAuthor,
- statusIcon,
+export default {
+ name: 'MRWidgetMergeWhenPipelineSucceeds',
+ components: {
+ MrWidgetAuthor,
+ statusIcon,
+ },
+ props: {
+ mr: {
+ type: Object,
+ required: true,
+ default: () => ({}),
},
- props: {
- mr: {
- type: Object,
- required: true,
- default: () => ({}),
- },
- service: {
- type: Object,
- required: true,
- default: () => ({}),
- },
+ service: {
+ type: Object,
+ required: true,
+ default: () => ({}),
},
- data() {
- return {
- isCancellingAutoMerge: false,
- isRemovingSourceBranch: false,
- };
- },
- computed: {
- canRemoveSourceBranch() {
- const {
- shouldRemoveSourceBranch,
- canRemoveSourceBranch,
- mergeUserId,
- currentUserId,
- } = this.mr;
+ },
+ data() {
+ return {
+ isCancellingAutoMerge: false,
+ isRemovingSourceBranch: false,
+ };
+ },
+ computed: {
+ canRemoveSourceBranch() {
+ const {
+ shouldRemoveSourceBranch,
+ canRemoveSourceBranch,
+ mergeUserId,
+ currentUserId,
+ } = this.mr;
- return !shouldRemoveSourceBranch &&
- canRemoveSourceBranch &&
- mergeUserId === currentUserId;
- },
+ return !shouldRemoveSourceBranch && canRemoveSourceBranch && mergeUserId === currentUserId;
+ },
+ },
+ methods: {
+ cancelAutomaticMerge() {
+ this.isCancellingAutoMerge = true;
+ this.service
+ .cancelAutomaticMerge()
+ .then(res => res.data)
+ .then(data => {
+ eventHub.$emit('UpdateWidgetData', data);
+ })
+ .catch(() => {
+ this.isCancellingAutoMerge = false;
+ Flash('Something went wrong. Please try again.');
+ });
},
- methods: {
- cancelAutomaticMerge() {
- this.isCancellingAutoMerge = true;
- this.service.cancelAutomaticMerge()
- .then(res => res.data)
- .then((data) => {
- eventHub.$emit('UpdateWidgetData', data);
- })
- .catch(() => {
- this.isCancellingAutoMerge = false;
- Flash('Something went wrong. Please try again.');
- });
- },
- removeSourceBranch() {
- const options = {
- sha: this.mr.sha,
- merge_when_pipeline_succeeds: true,
- should_remove_source_branch: true,
- };
+ removeSourceBranch() {
+ const options = {
+ sha: this.mr.sha,
+ merge_when_pipeline_succeeds: true,
+ should_remove_source_branch: true,
+ };
- this.isRemovingSourceBranch = true;
- this.service.merge(options)
- .then(res => res.data)
- .then((data) => {
- if (data.status === 'merge_when_pipeline_succeeds') {
- eventHub.$emit('MRWidgetUpdateRequested');
- }
- })
- .catch(() => {
- this.isRemovingSourceBranch = false;
- Flash('Something went wrong. Please try again.');
- });
- },
+ this.isRemovingSourceBranch = true;
+ this.service
+ .merge(options)
+ .then(res => res.data)
+ .then(data => {
+ if (data.status === 'merge_when_pipeline_succeeds') {
+ eventHub.$emit('MRWidgetUpdateRequested');
+ }
+ })
+ .catch(() => {
+ this.isRemovingSourceBranch = false;
+ Flash('Something went wrong. Please try again.');
+ });
},
- };
+ },
+};
</script>
<template>
<div class="mr-widget-body media">
@@ -84,9 +84,9 @@
<div class="media-body">
<h4 class="d-flex align-items-start">
<span class="append-right-10">
- {{ s__("mrWidget|Set by") }}
+ {{ s__('mrWidget|Set by') }}
<mr-widget-author :author="mr.setToMWPSBy" />
- {{ s__("mrWidget|to be merged automatically when the pipeline succeeds") }}
+ {{ s__('mrWidget|to be merged automatically when the pipeline succeeds') }}
</span>
<a
v-if="mr.canCancelAutomaticMerge"
@@ -94,35 +94,23 @@
role="button"
href="#"
class="btn btn-sm btn-default js-cancel-auto-merge"
- @click.prevent="cancelAutomaticMerge">
- <i
- v-if="isCancellingAutoMerge"
- class="fa fa-spinner fa-spin"
- aria-hidden="true"
- >
- </i>
- {{ s__("mrWidget|Cancel automatic merge") }}
+ @click.prevent="cancelAutomaticMerge"
+ >
+ <i v-if="isCancellingAutoMerge" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
+ {{ s__('mrWidget|Cancel automatic merge') }}
</a>
</h4>
<section class="mr-info-list">
<p>
- {{ s__("mrWidget|The changes will be merged into") }}
- <a
- :href="mr.targetBranchPath"
- class="label-branch"
- >
- {{ mr.targetBranch }}
- </a>
+ {{ s__('mrWidget|The changes will be merged into') }}
+ <a :href="mr.targetBranchPath" class="label-branch"> {{ mr.targetBranch }} </a>
</p>
<p v-if="mr.shouldRemoveSourceBranch">
- {{ s__("mrWidget|The source branch will be removed") }}
+ {{ s__('mrWidget|The source branch will be removed') }}
</p>
- <p
- v-else
- class="d-flex align-items-start"
- >
+ <p v-else class="d-flex align-items-start">
<span class="append-right-10">
- {{ s__("mrWidget|The source branch will not be removed") }}
+ {{ s__('mrWidget|The source branch will not be removed') }}
</span>
<a
v-if="canRemoveSourceBranch"
@@ -132,13 +120,8 @@
href="#"
@click.prevent="removeSourceBranch"
>
- <i
- v-if="isRemovingSourceBranch"
- class="fa fa-spinner fa-spin"
- aria-hidden="true"
- >
- </i>
- {{ s__("mrWidget|Remove source branch") }}
+ <i v-if="isRemovingSourceBranch" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
+ {{ s__('mrWidget|Remove source branch') }}
</a>
</p>
</section>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
index 2f2394371ef..fe83fe58b67 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue
@@ -1,106 +1,102 @@
<script>
- import Flash from '~/flash';
- import tooltip from '~/vue_shared/directives/tooltip';
- import { s__, __ } from '~/locale';
- import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
- import MrWidgetAuthorTime from '../../components/mr_widget_author_time.vue';
- import statusIcon from '../mr_widget_status_icon.vue';
- import eventHub from '../../event_hub';
+import Flash from '~/flash';
+import tooltip from '~/vue_shared/directives/tooltip';
+import { s__, __ } from '~/locale';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import MrWidgetAuthorTime from '../../components/mr_widget_author_time.vue';
+import statusIcon from '../mr_widget_status_icon.vue';
+import eventHub from '../../event_hub';
+import { GlLoadingIcon } from '@gitlab/ui';
- export default {
- name: 'MRWidgetMerged',
- directives: {
- tooltip,
+export default {
+ name: 'MRWidgetMerged',
+ directives: {
+ tooltip,
+ },
+ components: {
+ MrWidgetAuthorTime,
+ statusIcon,
+ ClipboardButton,
+ GlLoadingIcon,
+ },
+ props: {
+ mr: {
+ type: Object,
+ required: true,
+ default: () => ({}),
},
- components: {
- MrWidgetAuthorTime,
- statusIcon,
- ClipboardButton,
+ service: {
+ type: Object,
+ required: true,
+ default: () => ({}),
},
- props: {
- mr: {
- type: Object,
- required: true,
- default: () => ({}),
- },
- service: {
- type: Object,
- required: true,
- default: () => ({}),
- },
+ },
+ data() {
+ return {
+ isMakingRequest: false,
+ };
+ },
+ computed: {
+ shouldShowRemoveSourceBranch() {
+ const { sourceBranchRemoved, isRemovingSourceBranch, canRemoveSourceBranch } = this.mr;
+
+ return (
+ !sourceBranchRemoved &&
+ canRemoveSourceBranch &&
+ !this.isMakingRequest &&
+ !isRemovingSourceBranch
+ );
},
- data() {
- return {
- isMakingRequest: false,
- };
+ shouldShowSourceBranchRemoving() {
+ const { sourceBranchRemoved, isRemovingSourceBranch } = this.mr;
+ return !sourceBranchRemoved && (isRemovingSourceBranch || this.isMakingRequest);
},
- computed: {
- shouldShowRemoveSourceBranch() {
- const {
- sourceBranchRemoved,
- isRemovingSourceBranch,
- canRemoveSourceBranch,
- } = this.mr;
-
- return !sourceBranchRemoved &&
- canRemoveSourceBranch &&
- !this.isMakingRequest &&
- !isRemovingSourceBranch;
- },
- shouldShowSourceBranchRemoving() {
- const {
- sourceBranchRemoved,
- isRemovingSourceBranch,
- } = this.mr;
- return !sourceBranchRemoved &&
- (isRemovingSourceBranch || this.isMakingRequest);
- },
- shouldShowMergedButtons() {
- const {
- canRevertInCurrentMR,
- canCherryPickInCurrentMR,
- revertInForkPath,
- cherryPickInForkPath,
- } = this.mr;
+ shouldShowMergedButtons() {
+ const {
+ canRevertInCurrentMR,
+ canCherryPickInCurrentMR,
+ revertInForkPath,
+ cherryPickInForkPath,
+ } = this.mr;
- return canRevertInCurrentMR ||
- canCherryPickInCurrentMR ||
- revertInForkPath ||
- cherryPickInForkPath;
- },
- revertTitle() {
- return s__('mrWidget|Revert this merge request in a new merge request');
- },
- cherryPickTitle() {
- return s__('mrWidget|Cherry-pick this merge request in a new merge request');
- },
- revertLabel() {
- return s__('mrWidget|Revert');
- },
- cherryPickLabel() {
- return s__('mrWidget|Cherry-pick');
- },
+ return (
+ canRevertInCurrentMR || canCherryPickInCurrentMR || revertInForkPath || cherryPickInForkPath
+ );
+ },
+ revertTitle() {
+ return s__('mrWidget|Revert this merge request in a new merge request');
+ },
+ cherryPickTitle() {
+ return s__('mrWidget|Cherry-pick this merge request in a new merge request');
+ },
+ revertLabel() {
+ return s__('mrWidget|Revert');
},
- methods: {
- removeSourceBranch() {
- this.isMakingRequest = true;
+ cherryPickLabel() {
+ return s__('mrWidget|Cherry-pick');
+ },
+ },
+ methods: {
+ removeSourceBranch() {
+ this.isMakingRequest = true;
- this.service.removeSourceBranch()
- .then(res => res.data)
- .then((data) => {
- if (data.message === 'Branch was removed') {
- eventHub.$emit('MRWidgetUpdateRequested', () => {
- this.isMakingRequest = false;
- });
- }
- })
- .catch(() => {
- this.isMakingRequest = false;
- Flash(__('Something went wrong. Please try again.'));
- });
- },
+ this.service
+ .removeSourceBranch()
+ .then(res => res.data)
+ .then(data => {
+ if (data.message === 'Branch was removed') {
+ eventHub.$emit('MRWidgetUpdateRequested', () => {
+ this.isMakingRequest = false;
+ });
+ }
+ })
+ .catch(() => {
+ this.isMakingRequest = false;
+ Flash(__('Something went wrong. Please try again.'));
+ });
},
- };
+ },
+};
</script>
<template>
<div class="mr-widget-body media">
@@ -114,8 +110,8 @@
:date-readable="mr.metrics.readableMergedAt"
/>
<a
- v-tooltip
v-if="mr.canRevertInCurrentMR"
+ v-tooltip
:title="revertTitle"
class="btn btn-close btn-sm"
href="#modal-revert-commit"
@@ -125,8 +121,8 @@
{{ revertLabel }}
</a>
<a
- v-tooltip
v-else-if="mr.revertInForkPath"
+ v-tooltip
:href="mr.revertInForkPath"
:title="revertTitle"
class="btn btn-close btn-sm"
@@ -135,8 +131,8 @@
{{ revertLabel }}
</a>
<a
- v-tooltip
v-if="mr.canCherryPickInCurrentMR"
+ v-tooltip
:title="cherryPickTitle"
class="btn btn-default btn-sm"
href="#modal-cherry-pick-commit"
@@ -146,8 +142,8 @@
{{ cherryPickLabel }}
</a>
<a
- v-tooltip
v-else-if="mr.cherryPickInForkPath"
+ v-tooltip
:href="mr.cherryPickInForkPath"
:title="cherryPickTitle"
class="btn btn-default btn-sm"
@@ -158,45 +154,42 @@
</div>
<section class="mr-info-list">
<p>
- {{ s__("mrWidget|The changes were merged into") }}
+ {{ s__('mrWidget|The changes were merged into') }}
<span class="label-branch">
<a :href="mr.targetBranchPath">{{ mr.targetBranch }}</a>
</span>
- with
- <a
- :href="mr.mergeCommitPath"
- class="commit-sha js-mr-merged-commit-sha"
- v-text="mr.shortMergeCommitSha"
- >
- </a>
- <clipboard-button
- :title="__('Copy commit SHA to clipboard')"
- :text="mr.mergeCommitSha"
- css-class="btn-default btn-transparent btn-clipboard js-mr-merged-copy-sha"
- />
+ <template v-if="mr.mergeCommitSha">
+ with
+ <a
+ :href="mr.mergeCommitPath"
+ class="commit-sha js-mr-merged-commit-sha"
+ v-text="mr.shortMergeCommitSha"
+ >
+ </a>
+ <clipboard-button
+ :title="__('Copy commit SHA to clipboard')"
+ :text="mr.mergeCommitSha"
+ css-class="btn-default btn-transparent btn-clipboard js-mr-merged-copy-sha"
+ />
+ </template>
</p>
<p v-if="mr.sourceBranchRemoved">
- {{ s__("mrWidget|The source branch has been removed") }}
+ {{ s__('mrWidget|The source branch has been removed') }}
</p>
- <p
- v-if="shouldShowRemoveSourceBranch"
- class="space-children"
- >
- <span>{{ s__("mrWidget|You can remove source branch now") }}</span>
+ <p v-if="shouldShowRemoveSourceBranch" class="space-children">
+ <span>{{ s__('mrWidget|You can remove source branch now') }}</span>
<button
:disabled="isMakingRequest"
type="button"
class="btn btn-sm btn-default js-remove-branch-button"
@click="removeSourceBranch"
>
- {{ s__("mrWidget|Remove Source Branch") }}
+ {{ s__('mrWidget|Remove Source Branch') }}
</button>
</p>
<p v-if="shouldShowSourceBranchRemoving">
<gl-loading-icon :inline="true" />
- <span>
- {{ s__("mrWidget|The source branch is being removed") }}
- </span>
+ <span> {{ s__('mrWidget|The source branch is being removed') }} </span>
</p>
</section>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue
index 953ddf40a51..0655eef6504 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merging.vue
@@ -1,30 +1,28 @@
<script>
- import statusIcon from '../mr_widget_status_icon.vue';
+import statusIcon from '../mr_widget_status_icon.vue';
- export default {
- name: 'MRWidgetMerging',
- components: {
- statusIcon,
+export default {
+ name: 'MRWidgetMerging',
+ components: {
+ statusIcon,
+ },
+ props: {
+ mr: {
+ type: Object,
+ required: true,
+ default: () => ({}),
},
- props: {
- mr: {
- type: Object,
- required: true,
- default: () => ({}),
- },
- },
- };
+ },
+};
</script>
<template>
<div class="mr-widget-body mr-state-locked media">
<status-icon status="loading" />
<div class="media-body">
- <h4>
- {{ s__("mrWidget|This merge request is in the process of being merged") }}
- </h4>
+ <h4>{{ s__('mrWidget|This merge request is in the process of being merged') }}</h4>
<section class="mr-info-list">
<p>
- {{ s__("mrWidget|The changes will be merged into") }}
+ {{ s__('mrWidget|The changes will be merged into') }}
<span class="label-branch">
<a :href="mr.targetBranchPath">{{ mr.targetBranch }}</a>
</span>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue
index b0e96f74626..e9aac8b385c 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_missing_branch.vue
@@ -1,61 +1,58 @@
<script>
- import { sprintf, s__ } from '~/locale';
- import tooltip from '~/vue_shared/directives/tooltip';
- import statusIcon from '../mr_widget_status_icon.vue';
- import mrWidgetMergeHelp from '../../components/mr_widget_merge_help.vue';
+import { sprintf, s__ } from '~/locale';
+import tooltip from '~/vue_shared/directives/tooltip';
+import statusIcon from '../mr_widget_status_icon.vue';
+import mrWidgetMergeHelp from '../../components/mr_widget_merge_help.vue';
- export default {
- name: 'MRWidgetMissingBranch',
- directives: {
- tooltip,
+export default {
+ name: 'MRWidgetMissingBranch',
+ directives: {
+ tooltip,
+ },
+ components: {
+ mrWidgetMergeHelp,
+ statusIcon,
+ },
+ props: {
+ mr: {
+ type: Object,
+ required: true,
},
- components: {
- mrWidgetMergeHelp,
- statusIcon,
+ },
+ computed: {
+ missingBranchName() {
+ return this.mr.sourceBranchRemoved ? 'source' : 'target';
},
- props: {
- mr: {
- type: Object,
- required: true,
- },
- },
- computed: {
- missingBranchName() {
- return this.mr.sourceBranchRemoved ? 'source' : 'target';
- },
- missingBranchNameMessage() {
- return sprintf(s__('mrWidget| Please restore it or use a different %{missingBranchName} branch'), {
+ missingBranchNameMessage() {
+ return sprintf(
+ s__('mrWidget| Please restore it or use a different %{missingBranchName} branch'),
+ {
missingBranchName: this.missingBranchName,
- });
- },
- message() {
- return sprintf(s__('mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line'), {
+ },
+ );
+ },
+ message() {
+ return sprintf(
+ s__(
+ 'mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line',
+ ),
+ {
missingBranchName: this.missingBranchName,
- });
- },
+ },
+ );
},
- };
+ },
+};
</script>
<template>
<div class="mr-widget-body media">
- <status-icon
- :show-disabled-button="true"
- status="warning"
- />
+ <status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children">
<span class="bold js-branch-text">
- <span class="capitalize">
- {{ missingBranchName }}
- </span> {{ s__("mrWidget|branch does not exist.") }}
- {{ missingBranchNameMessage }}
- <i
- v-tooltip
- :title="message"
- :aria-label="message"
- class="fa fa-question-circle"
- >
- </i>
+ <span class="capitalize"> {{ missingBranchName }} </span>
+ {{ s__('mrWidget|branch does not exist.') }} {{ missingBranchNameMessage }}
+ <i v-tooltip :title="message" :aria-label="message" class="fa fa-question-circle"> </i>
</span>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.vue
index 92eee2cf5dd..c203d2824fa 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_not_allowed.vue
@@ -1,24 +1,23 @@
<script>
- import StatusIcon from '../mr_widget_status_icon.vue';
+import StatusIcon from '../mr_widget_status_icon.vue';
- export default {
- name: 'MRWidgetNotAllowed',
- components: {
- StatusIcon,
- },
- };
+export default {
+ name: 'MRWidgetNotAllowed',
+ components: {
+ StatusIcon,
+ },
+};
</script>
<template>
<div class="mr-widget-body media">
- <status-icon
- :show-disabled-button="true"
- status="success"
- />
+ <status-icon :show-disabled-button="true" status="success" />
<div class="media-body space-children">
<span class="bold">
- {{ s__(`mrWidget|Ready to be merged automatically.
-Ask someone with write access to this repository to merge this request`) }}
+ {{
+ s__(`mrWidget|Ready to be merged automatically.
+Ask someone with write access to this repository to merge this request`)
+ }}
</span>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue
index 37ee5215cea..6331a7d8388 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_pipeline_blocked.vue
@@ -1,23 +1,22 @@
<script>
- import StatusIcon from '../mr_widget_status_icon.vue';
+import StatusIcon from '../mr_widget_status_icon.vue';
- export default {
- name: 'MRWidgetPipelineBlocked',
- components: {
- StatusIcon,
- },
- };
+export default {
+ name: 'MRWidgetPipelineBlocked',
+ components: {
+ StatusIcon,
+ },
+};
</script>
<template>
<div class="mr-widget-body media">
- <status-icon
- :show-disabled-button="true"
- status="warning"
- />
+ <status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children">
<span class="bold">
- {{ s__(`mrWidget|Pipeline blocked.
-The pipeline for this merge request requires a manual action to proceed`) }}
+ {{
+ s__(`mrWidget|Pipeline blocked.
+The pipeline for this merge request requires a manual action to proceed`)
+ }}
</span>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
index f31c7a3edb8..adfbcd18588 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
@@ -1,105 +1,103 @@
<script>
- import simplePoll from '../../../lib/utils/simple_poll';
- import eventHub from '../../event_hub';
- import statusIcon from '../mr_widget_status_icon.vue';
- import Flash from '../../../flash';
+import { GlLoadingIcon } from '@gitlab/ui';
+import simplePoll from '../../../lib/utils/simple_poll';
+import eventHub from '../../event_hub';
+import statusIcon from '../mr_widget_status_icon.vue';
+import Flash from '../../../flash';
- export default {
- name: 'MRWidgetRebase',
- components: {
- statusIcon,
+export default {
+ name: 'MRWidgetRebase',
+ components: {
+ statusIcon,
+ GlLoadingIcon,
+ },
+ props: {
+ mr: {
+ type: Object,
+ required: true,
},
- props: {
- mr: {
- type: Object,
- required: true,
- },
- service: {
- type: Object,
- required: true,
- },
+ service: {
+ type: Object,
+ required: true,
},
- data() {
- return {
- isMakingRequest: false,
- rebasingError: null,
- };
+ },
+ data() {
+ return {
+ isMakingRequest: false,
+ rebasingError: null,
+ };
+ },
+ computed: {
+ status() {
+ if (this.mr.rebaseInProgress || this.isMakingRequest) {
+ return 'loading';
+ }
+ if (!this.mr.canPushToSourceBranch && !this.mr.rebaseInProgress) {
+ return 'warning';
+ }
+ return 'success';
},
- computed: {
- status() {
- if (this.mr.rebaseInProgress || this.isMakingRequest) {
- return 'loading';
- }
- if (!this.mr.canPushToSourceBranch && !this.mr.rebaseInProgress) {
- return 'warning';
- }
- return 'success';
- },
- showDisabledButton() {
- return ['failed', 'loading'].includes(this.status);
- },
+ showDisabledButton() {
+ return ['failed', 'loading'].includes(this.status);
},
- methods: {
- rebase() {
- this.isMakingRequest = true;
- this.rebasingError = null;
+ },
+ methods: {
+ rebase() {
+ this.isMakingRequest = true;
+ this.rebasingError = null;
- this.service.rebase()
- .then(() => {
- simplePoll(this.checkRebaseStatus);
- })
- .catch((error) => {
- this.rebasingError = error.merge_error;
+ this.service
+ .rebase()
+ .then(() => {
+ simplePoll(this.checkRebaseStatus);
+ })
+ .catch(error => {
+ this.rebasingError = error.merge_error;
+ this.isMakingRequest = false;
+ Flash('Something went wrong. Please try again.');
+ });
+ },
+ checkRebaseStatus(continuePolling, stopPolling) {
+ this.service
+ .poll()
+ .then(res => res.data)
+ .then(res => {
+ if (res.rebase_in_progress) {
+ continuePolling();
+ } else {
this.isMakingRequest = false;
- Flash('Something went wrong. Please try again.');
- });
- },
- checkRebaseStatus(continuePolling, stopPolling) {
- this.service.poll()
- .then(res => res.data)
- .then((res) => {
- if (res.rebase_in_progress) {
- continuePolling();
- } else {
- this.isMakingRequest = false;
-
- if (res.merge_error && res.merge_error.length) {
- this.rebasingError = res.merge_error;
- Flash('Something went wrong. Please try again.');
- }
- eventHub.$emit('MRWidgetUpdateRequested');
- stopPolling();
+ if (res.merge_error && res.merge_error.length) {
+ this.rebasingError = res.merge_error;
+ Flash('Something went wrong. Please try again.');
}
- })
- .catch(() => {
- this.isMakingRequest = false;
- Flash('Something went wrong. Please try again.');
+
+ eventHub.$emit('MRWidgetUpdateRequested');
stopPolling();
- });
- },
+ }
+ })
+ .catch(() => {
+ this.isMakingRequest = false;
+ Flash('Something went wrong. Please try again.');
+ stopPolling();
+ });
},
- };
+ },
+};
</script>
<template>
<div class="mr-widget-body media">
- <status-icon
- :status="status"
- :show-disabled-button="showDisabledButton"
- />
+ <status-icon :status="status" :show-disabled-button="showDisabledButton" />
<div class="rebase-state-find-class-convention media media-body space-children">
<template v-if="mr.rebaseInProgress || isMakingRequest">
- <span class="bold">
- Rebase in progress
- </span>
+ <span class="bold"> Rebase in progress </span>
</template>
<template v-if="!mr.rebaseInProgress && !mr.canPushToSourceBranch">
<span class="bold">
- Fast-forward merge is not possible.
- Rebase the source branch onto
- <span class="label-branch">{{ mr.targetBranch }}</span>
- to allow this merge request to be merged.
+ Fast-forward merge is not possible. Rebase the source branch onto
+ <span class="label-branch">{{ mr.targetBranch }}</span> to allow this merge request to be
+ merged.
</span>
</template>
<template v-if="!mr.rebaseInProgress && mr.canPushToSourceBranch && !isMakingRequest">
@@ -116,19 +114,11 @@ js-toggle-container accept-action media space-children"
<gl-loading-icon v-if="isMakingRequest" />
Rebase
</button>
- <span
- v-if="!rebasingError"
- class="bold"
- >
- Fast-forward merge is not possible.
- Rebase the source branch onto the target branch or merge target
- branch into source branch to allow this merge request to be merged.
- </span>
- <span
- v-else
- class="bold danger">
- {{ rebasingError }}
+ <span v-if="!rebasingError" class="bold">
+ Fast-forward merge is not possible. Rebase the source branch onto the target branch or
+ merge target branch into source branch to allow this merge request to be merged.
</span>
+ <span v-else class="bold danger"> {{ rebasingError }} </span>
</div>
</template>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_squash_before_merge.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_squash_before_merge.js
deleted file mode 100644
index bf8628d18a6..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_squash_before_merge.js
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
-The squash-before-merge button is EE only, but it's located right in the middle
-of the readyToMerge state component template.
-
-If we didn't declare this component in CE, we'd need to maintain a separate copy
-of the readyToMergeState template in EE, which is pretty big and likely to change.
-
-Instead, in CE, we declare the component, but it's hidden and is configured to do nothing.
-In EE, the configuration extends this object to add a functioning squash-before-merge
-button.
-*/
-
-export default {
- template: '',
-};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_squash_before_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_squash_before_merge.vue
deleted file mode 100644
index 25c1044fe2b..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_squash_before_merge.vue
+++ /dev/null
@@ -1,63 +0,0 @@
-<script>
-import Icon from '~/vue_shared/components/icon.vue';
-import eventHub from '~/vue_merge_request_widget/event_hub';
-import tooltip from '~/vue_shared/directives/tooltip';
-
-export default {
- components: {
- Icon,
- },
- directives: {
- tooltip,
- },
- props: {
- mr: {
- type: Object,
- required: true,
- },
- isMergeButtonDisabled: {
- type: Boolean,
- required: true,
- },
- },
- data() {
- return {
- squashBeforeMerge: this.mr.squash,
- };
- },
- methods: {
- updateSquashModel() {
- eventHub.$emit('MRWidgetUpdateSquash', this.squashBeforeMerge);
- },
- },
-};
-</script>
-
-<template>
- <div class="accept-control inline">
- <label class="merge-param-checkbox">
- <input
- :disabled="isMergeButtonDisabled"
- v-model="squashBeforeMerge"
- type="checkbox"
- name="squash"
- class="qa-squash-checkbox"
- @change="updateSquashModel"
- />
- {{ __('Squash commits') }}
- </label>
- <a
- v-tooltip
- :href="mr.squashBeforeMergeHelpPath"
- data-title="About this feature"
- data-placement="bottom"
- target="_blank"
- rel="noopener noreferrer nofollow"
- data-container="body"
- >
- <icon
- name="question-o"
- />
- </a>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue
index e73b7e410d5..a38495bb4cc 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue
@@ -23,21 +23,16 @@ export default {
</div>
<div class="text col-md-7 order-md-first col-12">
<span>
- Merge requests are a place to propose changes you have made to a project
- and discuss those changes with others.
+ Merge requests are a place to propose changes you have made to a project and discuss those
+ changes with others.
</span>
+ <p>Interested parties can even contribute by pushing commits if they want to.</p>
<p>
- Interested parties can even contribute by pushing commits if they want to.
- </p>
- <p>
- Currently there are no changes in this merge request's source branch.
- Please push new commits or use a different branch.
+ Currently there are no changes in this merge request's source branch. Please push new
+ commits or use a different branch.
</p>
<div>
- <a
- v-if="mr.newBlobPath"
- :href="mr.newBlobPath"
- class="btn btn-inverted btn-success">
+ <a v-if="mr.newBlobPath" :href="mr.newBlobPath" class="btn btn-inverted btn-success">
Create file
</a>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue
index 2bb1a34412e..5f56157cb89 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/pipeline_failed.vue
@@ -11,14 +11,13 @@ export default {
<template>
<div class="mr-widget-body media">
- <status-icon
- :show-disabled-button="true"
- status="warning"
- />
+ <status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children">
<span class="bold">
- {{ s__(`mrWidget|The pipeline for this merge request failed.
-Please retry the job or push a new commit to fix the failure`) }}
+ {{
+ s__(`mrWidget|The pipeline for this merge request failed.
+Please retry the job or push a new commit to fix the failure`)
+ }}
</span>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
index 23c3284cd21..84c8a3464a5 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
@@ -6,7 +6,7 @@ import MergeRequest from '../../../merge_request';
import Flash from '../../../flash';
import statusIcon from '../mr_widget_status_icon.vue';
import eventHub from '../../event_hub';
-import SquashBeforeMerge from './mr_widget_squash_before_merge.vue';
+import SquashBeforeMerge from './squash_before_merge.vue';
export default {
name: 'ReadyToMerge',
@@ -71,7 +71,12 @@ export default {
return defaultClass;
},
iconClass() {
- if (this.status === 'failed' || !this.commitMessage.length || !this.mr.isMergeAllowed || this.mr.preventMerge) {
+ if (
+ this.status === 'failed' ||
+ !this.commitMessage.length ||
+ !this.mr.isMergeAllowed ||
+ this.mr.preventMerge
+ ) {
return 'warning';
}
return 'success';
@@ -90,10 +95,12 @@ export default {
},
isMergeButtonDisabled() {
const { commitMessage } = this;
- return Boolean(!commitMessage.length
- || !this.shouldShowMergeControls()
- || this.isMakingRequest
- || this.mr.preventMerge);
+ return Boolean(
+ !commitMessage.length ||
+ !this.shouldShowMergeControls() ||
+ this.isMakingRequest ||
+ this.mr.preventMerge,
+ );
},
isRemoveSourceBranchButtonDisabled() {
return this.isMergeButtonDisabled;
@@ -140,9 +147,10 @@ export default {
};
this.isMakingRequest = true;
- this.service.merge(options)
+ this.service
+ .merge(options)
.then(res => res.data)
- .then((data) => {
+ .then(data => {
const hasError = data.status === 'failed' || data.status === 'hook_validation_error';
if (data.status === 'merge_when_pipeline_succeeds') {
@@ -167,9 +175,10 @@ export default {
});
},
handleMergePolling(continuePolling, stopPolling) {
- this.service.poll()
+ this.service
+ .poll()
.then(res => res.data)
- .then((data) => {
+ .then(data => {
if (data.state === 'merged') {
// If state is merged we should update the widget and stop the polling
eventHub.$emit('MRWidgetUpdateRequested');
@@ -205,9 +214,10 @@ export default {
});
},
handleRemoveBranchPolling(continuePolling, stopPolling) {
- this.service.poll()
+ this.service
+ .poll()
.then(res => res.data)
- .then((data) => {
+ .then(data => {
// If source branch exists then we should continue polling
// because removing a source branch is a background task and takes time
if (data.source_branch_exists) {
@@ -239,12 +249,9 @@ export default {
:class="mergeButtonClass"
type="button"
class="qa-merge-button"
- @click="handleMergeButtonClick()">
- <i
- v-if="isMakingRequest"
- class="fa fa-spinner fa-spin"
- aria-hidden="true"
- ></i>
+ @click="handleMergeButtonClick();"
+ >
+ <i v-if="isMakingRequest" class="fa fa-spinner fa-spin" aria-hidden="true"></i>
{{ mergeButtonText }}
</button>
<button
@@ -253,26 +260,23 @@ export default {
type="button"
class="btn btn-sm btn-info dropdown-toggle js-merge-moment"
data-toggle="dropdown"
- aria-label="Select merge moment">
- <i
- class="fa fa-chevron-down qa-merge-moment-dropdown"
- aria-hidden="true"
- ></i>
+ aria-label="Select merge moment"
+ >
+ <i class="fa fa-chevron-down qa-merge-moment-dropdown" aria-hidden="true"></i>
</button>
<ul
v-if="shouldShowMergeOptionsDropdown"
class="dropdown-menu dropdown-menu-right"
- role="menu">
+ role="menu"
+ >
<li>
<a
class="merge_when_pipeline_succeeds qa-merge-when-pipeline-succeeds-option"
href="#"
- @click.prevent="handleMergeButtonClick(true)">
+ @click.prevent="handleMergeButtonClick(true);"
+ >
<span class="media">
- <span
- class="merge-opt-icon"
- aria-hidden="true"
- v-html="successSvg"></span>
+ <span class="merge-opt-icon" aria-hidden="true" v-html="successSvg"></span>
<span class="media-body merge-opt-title">Merge when pipeline succeeds</span>
</span>
</a>
@@ -281,12 +285,10 @@ export default {
<a
class="accept-merge-request qa-merge-immediately-option"
href="#"
- @click.prevent="handleMergeButtonClick(false, true)">
+ @click.prevent="handleMergeButtonClick(false, true);"
+ >
<span class="media">
- <span
- class="merge-opt-icon"
- aria-hidden="true"
- v-html="warningSvg"></span>
+ <span class="merge-opt-icon" aria-hidden="true" v-html="warningSvg"></span>
<span class="media-body merge-opt-title">Merge immediately</span>
</span>
</a>
@@ -301,18 +303,19 @@ export default {
v-model="removeSourceBranch"
:disabled="isRemoveSourceBranchButtonDisabled"
class="js-remove-source-branch-checkbox"
- type="checkbox"/> Remove source branch
+ type="checkbox"
+ />
+ Remove source branch
</label>
<!-- Placeholder for EE extension of this component -->
<squash-before-merge
v-if="shouldShowSquashBeforeMerge"
:mr="mr"
- :is-merge-button-disabled="isMergeButtonDisabled" />
+ :is-merge-button-disabled="isMergeButtonDisabled"
+ />
- <span
- v-if="mr.ffOnlyEnabled"
- class="js-fast-forward-message">
+ <span v-if="mr.ffOnlyEnabled" class="js-fast-forward-message">
Fast-forward merge without a merge commit
</span>
<button
@@ -320,7 +323,8 @@ export default {
:disabled="isMergeButtonDisabled"
class="js-modify-commit-message-button btn btn-default btn-sm"
type="button"
- @click="toggleCommitMessageEditor">
+ @click="toggleCommitMessageEditor"
+ >
Modify commit message
</button>
</template>
@@ -331,15 +335,9 @@ export default {
</template>
</div>
</div>
- <div
- v-if="showCommitMessageEditor"
- class="prepend-top-default commit-message-editor">
+ <div v-if="showCommitMessageEditor" class="prepend-top-default commit-message-editor">
<div class="form-group clearfix">
- <label
- class="col-form-label"
- for="commit-message">
- Commit message
- </label>
+ <label class="col-form-label" for="commit-message"> Commit message </label>
<div class="col-sm-10">
<div class="commit-message-container">
<div class="max-width-marker"></div>
@@ -349,18 +347,14 @@ export default {
class="form-control js-commit-message"
required="required"
rows="14"
- name="Commit message"></textarea>
+ name="Commit message"
+ ></textarea>
</div>
<p class="hint">
Try to keep the first line under 52 characters and the others under 72
</p>
<div class="hint">
- <a
- href="#"
- @click.prevent="updateCommitMessage"
- >
- {{ commitMessageLinkTitle }}
- </a>
+ <a href="#" @click.prevent="updateCommitMessage"> {{ commitMessageLinkTitle }} </a>
</div>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue
index 16c903c923f..8acca0d6481 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/sha_mismatch.vue
@@ -11,14 +11,13 @@ export default {
<template>
<div class="mr-widget-body media">
- <status-icon
- :show-disabled-button="true"
- status="warning"
- />
+ <status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children">
<span class="bold">
- {{ s__(`mrWidget|The source branch HEAD has recently changed.
-Please reload the page and review the changes before merging`) }}
+ {{
+ s__(`mrWidget|The source branch HEAD has recently changed.
+Please reload the page and review the changes before merging`)
+ }}
</span>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
new file mode 100644
index 00000000000..e71acf0d7dd
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue
@@ -0,0 +1,61 @@
+<script>
+import Icon from '~/vue_shared/components/icon.vue';
+import eventHub from '~/vue_merge_request_widget/event_hub';
+import tooltip from '~/vue_shared/directives/tooltip';
+
+export default {
+ components: {
+ Icon,
+ },
+ directives: {
+ tooltip,
+ },
+ props: {
+ mr: {
+ type: Object,
+ required: true,
+ },
+ isMergeButtonDisabled: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ squashBeforeMerge: this.mr.squash,
+ };
+ },
+ methods: {
+ updateSquashModel() {
+ eventHub.$emit('MRWidgetUpdateSquash', this.squashBeforeMerge);
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="accept-control inline">
+ <label class="merge-param-checkbox">
+ <input
+ v-model="squashBeforeMerge"
+ :disabled="isMergeButtonDisabled"
+ type="checkbox"
+ name="squash"
+ class="qa-squash-checkbox"
+ @change="updateSquashModel"
+ />
+ {{ __('Squash commits') }}
+ </label>
+ <a
+ v-tooltip
+ :href="mr.squashBeforeMergeHelpPath"
+ data-title="About this feature"
+ data-placement="bottom"
+ target="_blank"
+ rel="noopener noreferrer nofollow"
+ data-container="body"
+ >
+ <icon name="question-o" />
+ </a>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue
index 5eb2058a03b..a9fb40a4949 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue
@@ -17,20 +17,17 @@ export default {
<template>
<div class="mr-widget-body media">
- <status-icon
- :show-disabled-button="true"
- status="warning"
- />
+ <status-icon :show-disabled-button="true" status="warning" />
<div class="media-body space-children">
<span class="bold">
- {{ s__("mrWidget|There are unresolved discussions. Please resolve these discussions") }}
+ {{ s__('mrWidget|There are unresolved discussions. Please resolve these discussions') }}
</span>
<a
v-if="mr.createIssueToResolveDiscussionsPath"
:href="mr.createIssueToResolveDiscussionsPath"
class="btn btn-default btn-sm js-create-issue"
>
- {{ s__("mrWidget|Create an issue to resolve them later") }}
+ {{ s__('mrWidget|Create an issue to resolve them later') }}
</a>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
index 89c9a41f316..7c322388d30 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
@@ -24,9 +24,10 @@ export default {
methods: {
removeWIP() {
this.isMakingRequest = true;
- this.service.removeWIP()
+ this.service
+ .removeWIP()
.then(res => res.data)
- .then((data) => {
+ .then(data => {
eventHub.$emit('UpdateWidgetData', data);
new window.Flash('The merge request can now be merged.', 'notice'); // eslint-disable-line
$('.merge-request .detail-page-description .title').text(this.mr.title);
@@ -42,10 +43,7 @@ export default {
<template>
<div class="mr-widget-body media">
- <status-icon
- :show-disabled-button="Boolean(mr.removeWIPPath)"
- status="warning"
- />
+ <status-icon :show-disabled-button="Boolean(mr.removeWIPPath)" status="warning" />
<div class="media-body space-children">
<span class="bold">
This is a Work in Progress
@@ -55,7 +53,8 @@ export default {
title="When this merge request is ready,
remove the WIP: prefix from the title to allow it to be merged"
aria-label="When this merge request is ready,
- remove the WIP: prefix from the title to allow it to be merged">
+ remove the WIP: prefix from the title to allow it to be merged"
+ >
</i>
</span>
<button
@@ -63,13 +62,10 @@ export default {
:disabled="isMakingRequest"
type="button"
class="btn btn-default btn-sm js-remove-wip"
- @click="removeWIP">
- <i
- v-if="isMakingRequest"
- class="fa fa-spinner fa-spin"
- aria-hidden="true">
- </i>
- Resolve WIP status
+ @click="removeWIP"
+ >
+ <i v-if="isMakingRequest" class="fa fa-spinner fa-spin" aria-hidden="true"> </i> Resolve WIP
+ status
</button>
</div>
</div>
diff --git a/app/assets/javascripts/vue_merge_request_widget/dependencies.js b/app/assets/javascripts/vue_merge_request_widget/dependencies.js
deleted file mode 100644
index 15097fa2a3f..00000000000
--- a/app/assets/javascripts/vue_merge_request_widget/dependencies.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * This file is the centerpiece of an attempt to reduce potential conflicts
- * between the CE and EE versions of the MR widget. EE additions to the MR widget should
- * be contained in the ee/vue_merge_request_widget directory, and should **extend**
- * rather than mutate CE MR Widget code.
- *
- * This file should be the only source of conflicts between EE and CE. EE-only components should
- * imported directly where they are needed, and import paths for EE extensions of CE components
- * should overwrite import paths **without** changing the order of dependencies listed here.
- */
-
-export { default as Vue } from 'vue';
-export { default as SmartInterval } from '~/smart_interval';
-export { default as WidgetHeader } from './components/mr_widget_header.vue';
-export { default as WidgetMergeHelp } from './components/mr_widget_merge_help.vue';
-export { default as WidgetPipeline } from './components/mr_widget_pipeline.vue';
-export { default as Deployment } from './components/deployment.vue';
-export { default as WidgetRelatedLinks } from './components/mr_widget_related_links.vue';
-export { default as MergedState } from './components/states/mr_widget_merged.vue';
-export { default as FailedToMerge } from './components/states/mr_widget_failed_to_merge.vue';
-export { default as ClosedState } from './components/states/mr_widget_closed.vue';
-export { default as MergingState } from './components/states/mr_widget_merging.vue';
-export { default as WorkInProgressState } from './components/states/work_in_progress.vue';
-export { default as ArchivedState } from './components/states/mr_widget_archived.vue';
-export { default as ConflictsState } from './components/states/mr_widget_conflicts.vue';
-export { default as NothingToMergeState } from './components/states/nothing_to_merge.vue';
-export { default as MissingBranchState } from './components/states/mr_widget_missing_branch.vue';
-export { default as NotAllowedState } from './components/states/mr_widget_not_allowed.vue';
-export { default as ReadyToMergeState } from './components/states/ready_to_merge.vue';
-export { default as ShaMismatchState } from './components/states/sha_mismatch.vue';
-export { default as UnresolvedDiscussionsState } from './components/states/unresolved_discussions.vue';
-export { default as PipelineBlockedState } from './components/states/mr_widget_pipeline_blocked.vue';
-export { default as PipelineFailedState } from './components/states/pipeline_failed.vue';
-export { default as MergeWhenPipelineSucceedsState } from './components/states/mr_widget_merge_when_pipeline_succeeds.vue';
-export { default as RebaseState } from './components/states/mr_widget_rebase.vue';
-export { default as AutoMergeFailed } from './components/states/mr_widget_auto_merge_failed.vue';
-export { default as CheckingState } from './components/states/mr_widget_checking.vue';
-export { default as MRWidgetStore } from './stores/mr_widget_store';
-export { default as MRWidgetService } from './services/mr_widget_service';
-export { default as eventHub } from './event_hub';
-export { default as getStateKey } from './stores/get_state_key';
-export { default as stateMaps } from './stores/state_maps';
-export { default as SquashBeforeMerge } from './components/states/mr_widget_squash_before_merge.vue';
-export { default as notify } from '../lib/utils/notify';
-export { default as SourceBranchRemovalStatus } from './components/source_branch_removal_status.vue';
-
-export { default as mrWidgetOptions } from './mr_widget_options.vue';
diff --git a/app/assets/javascripts/vue_merge_request_widget/ee_switch_mr_widget_options.js b/app/assets/javascripts/vue_merge_request_widget/ee_switch_mr_widget_options.js
new file mode 100644
index 00000000000..8780aa4bd1c
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/ee_switch_mr_widget_options.js
@@ -0,0 +1,3 @@
+import MRWidgetOptions from './mr_widget_options.vue';
+
+export default MRWidgetOptions;
diff --git a/app/assets/javascripts/vue_merge_request_widget/index.js b/app/assets/javascripts/vue_merge_request_widget/index.js
index cc6e620f365..60cebbfc2b2 100644
--- a/app/assets/javascripts/vue_merge_request_widget/index.js
+++ b/app/assets/javascripts/vue_merge_request_widget/index.js
@@ -1,4 +1,5 @@
-import { Vue, mrWidgetOptions } from './dependencies';
+import Vue from 'vue';
+import MrWidgetOptions from './ee_switch_mr_widget_options';
import Translate from '../vue_shared/translate';
Vue.use(Translate);
@@ -6,7 +7,7 @@ Vue.use(Translate);
export default () => {
gl.mrWidgetData.gitlabLogo = gon.gitlab_logo;
- const vm = new Vue(mrWidgetOptions);
+ const vm = new Vue(MrWidgetOptions);
window.gl.mrWidget = {
checkStatus: vm.checkStatus,
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index b5eaaf054e7..3c3e3efcc36 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -1,41 +1,40 @@
<script>
-
+import _ from 'underscore';
+import { __ } from '~/locale';
import Project from '~/pages/projects/project';
import SmartInterval from '~/smart_interval';
import createFlash from '../flash';
-import {
- WidgetHeader,
- WidgetMergeHelp,
- WidgetPipeline,
- Deployment,
- WidgetRelatedLinks,
- MergedState,
- ClosedState,
- MergingState,
- RebaseState,
- WorkInProgressState,
- ArchivedState,
- ConflictsState,
- NothingToMergeState,
- MissingBranchState,
- NotAllowedState,
- ReadyToMergeState,
- ShaMismatchState,
- UnresolvedDiscussionsState,
- PipelineBlockedState,
- PipelineFailedState,
- FailedToMerge,
- MergeWhenPipelineSucceedsState,
- AutoMergeFailed,
- CheckingState,
- MRWidgetStore,
- MRWidgetService,
- eventHub,
- stateMaps,
- SquashBeforeMerge,
- notify,
- SourceBranchRemovalStatus,
-} from './dependencies';
+import WidgetHeader from './components/mr_widget_header.vue';
+import WidgetMergeHelp from './components/mr_widget_merge_help.vue';
+import MrWidgetPipelineContainer from './components/mr_widget_pipeline_container.vue';
+import Deployment from './components/deployment.vue';
+import WidgetRelatedLinks from './components/mr_widget_related_links.vue';
+import MergedState from './components/states/mr_widget_merged.vue';
+import ClosedState from './components/states/mr_widget_closed.vue';
+import MergingState from './components/states/mr_widget_merging.vue';
+import RebaseState from './components/states/mr_widget_rebase.vue';
+import WorkInProgressState from './components/states/work_in_progress.vue';
+import ArchivedState from './components/states/mr_widget_archived.vue';
+import ConflictsState from './components/states/mr_widget_conflicts.vue';
+import NothingToMergeState from './components/states/nothing_to_merge.vue';
+import MissingBranchState from './components/states/mr_widget_missing_branch.vue';
+import NotAllowedState from './components/states/mr_widget_not_allowed.vue';
+import ReadyToMergeState from './components/states/ready_to_merge.vue';
+import ShaMismatchState from './components/states/sha_mismatch.vue';
+import UnresolvedDiscussionsState from './components/states/unresolved_discussions.vue';
+import PipelineBlockedState from './components/states/mr_widget_pipeline_blocked.vue';
+import PipelineFailedState from './components/states/pipeline_failed.vue';
+import FailedToMerge from './components/states/mr_widget_failed_to_merge.vue';
+import MergeWhenPipelineSucceedsState from './components/states/mr_widget_merge_when_pipeline_succeeds.vue';
+import AutoMergeFailed from './components/states/mr_widget_auto_merge_failed.vue';
+import CheckingState from './components/states/mr_widget_checking.vue';
+import MRWidgetStore from './stores/ee_switch_mr_widget_store';
+import MRWidgetService from './services/ee_switch_mr_widget_service';
+import eventHub from './event_hub';
+import stateMaps from './stores/ee_switch_state_maps';
+import SquashBeforeMerge from './components/states/squash_before_merge.vue';
+import notify from '~/lib/utils/notify';
+import SourceBranchRemovalStatus from './components/source_branch_removal_status.vue';
import GroupedTestReportsApp from '../reports/components/grouped_test_reports_app.vue';
import { setFaviconOverlay } from '../lib/utils/common_utils';
@@ -45,7 +44,7 @@ export default {
components: {
'mr-widget-header': WidgetHeader,
'mr-widget-merge-help': WidgetMergeHelp,
- 'mr-widget-pipeline': WidgetPipeline,
+ MrWidgetPipelineContainer,
Deployment,
'mr-widget-related-links': WidgetRelatedLinks,
'mr-widget-merged': MergedState,
@@ -83,6 +82,7 @@ export default {
const service = this.createService(store);
return {
mr: store,
+ state: store.state,
service,
};
},
@@ -100,8 +100,22 @@ export default {
return !!this.mr.relatedLinks && !this.mr.isNothingToMergeState;
},
shouldRenderSourceBranchRemovalStatus() {
- return !this.mr.canRemoveSourceBranch && this.mr.shouldRemoveSourceBranch &&
- (!this.mr.isNothingToMergeState && !this.mr.isMergedState);
+ return (
+ !this.mr.canRemoveSourceBranch &&
+ this.mr.shouldRemoveSourceBranch &&
+ (!this.mr.isNothingToMergeState && !this.mr.isMergedState)
+ );
+ },
+ shouldRenderMergedPipeline() {
+ return this.mr.state === 'merged' && !_.isEmpty(this.mr.mergePipeline);
+ },
+ },
+ watch: {
+ state(newVal, oldVal) {
+ if (newVal !== oldVal && this.shouldRenderMergedPipeline) {
+ // init polling
+ this.initPostMergeDeploymentsPolling();
+ }
},
},
created() {
@@ -110,10 +124,21 @@ export default {
eventHub.$on('mr.discussion.updated', this.checkStatus);
},
mounted() {
- this.handleMounted();
+ this.setFaviconHelper();
+ this.initDeploymentsPolling();
+
+ if (this.shouldRenderMergedPipeline) {
+ this.initPostMergeDeploymentsPolling();
+ }
},
beforeDestroy() {
eventHub.$off('mr.discussion.updated', this.checkStatus);
+ this.pollingInterval.destroy();
+ this.deploymentsInterval.destroy();
+
+ if (this.postMergeDeploymentsInterval) {
+ this.postMergeDeploymentsInterval.destroy();
+ }
},
methods: {
createService(store) {
@@ -131,9 +156,10 @@ export default {
return new MRWidgetService(endpoints);
},
checkStatus(cb) {
- return this.service.checkStatus()
+ return this.service
+ .checkStatus()
.then(res => res.data)
- .then((data) => {
+ .then(data => {
this.handleNotification(data);
this.mr.setData(data);
this.setFaviconHelper();
@@ -142,7 +168,13 @@ export default {
cb.call(null, data);
}
})
- .catch(() => createFlash('Something went wrong. Please try again.'));
+ .catch(() => createFlash(__('Something went wrong. Please try again.')));
+ },
+ setFaviconHelper() {
+ if (this.mr.ciStatusFaviconPath) {
+ return setFaviconOverlay(this.mr.ciStatusFaviconPath);
+ }
+ return Promise.resolve();
},
initPolling() {
this.pollingInterval = new SmartInterval({
@@ -154,8 +186,14 @@ export default {
});
},
initDeploymentsPolling() {
- this.deploymentsInterval = new SmartInterval({
- callback: this.fetchDeployments,
+ this.deploymentsInterval = this.deploymentsPoll(this.fetchPreMergeDeployments);
+ },
+ initPostMergeDeploymentsPolling() {
+ this.postMergeDeploymentsInterval = this.deploymentsPoll(this.fetchPostMergeDeployments);
+ },
+ deploymentsPoll(callback) {
+ return new SmartInterval({
+ callback,
startingInterval: 30000,
maxInterval: 120000,
hiddenInterval: 240000,
@@ -163,27 +201,38 @@ export default {
immediateExecution: true,
});
},
- setFaviconHelper() {
- if (this.mr.ciStatusFaviconPath) {
- return setFaviconOverlay(this.mr.ciStatusFaviconPath);
- }
- return Promise.resolve();
+ fetchDeployments(target) {
+ return this.service.fetchDeployments(target);
},
- fetchDeployments() {
- return this.service.fetchDeployments()
- .then(res => res.data)
- .then((data) => {
+ fetchPreMergeDeployments() {
+ return this.fetchDeployments()
+ .then(({ data }) => {
if (data.length) {
this.mr.deployments = data;
}
})
- .catch(() => {
- createFlash('Something went wrong while fetching the environments for this merge request. Please try again.');
- });
+ .catch(() => this.throwDeploymentsError());
+ },
+ fetchPostMergeDeployments() {
+ return this.fetchDeployments('merge_commit')
+ .then(({ data }) => {
+ if (data.length) {
+ this.mr.postMergeDeployments = data;
+ }
+ })
+ .catch(() => this.throwDeploymentsError());
+ },
+ throwDeploymentsError() {
+ createFlash(
+ __(
+ 'Something went wrong while fetching the environments for this merge request. Please try again.',
+ ),
+ );
},
fetchActionsContent() {
- this.service.fetchMergeActionsContent()
- .then((res) => {
+ this.service
+ .fetchMergeActionsContent()
+ .then(res => {
if (res.data) {
const el = document.createElement('div');
el.innerHTML = res.data;
@@ -191,7 +240,7 @@ export default {
Project.initRefSwitcher();
}
})
- .catch(() => createFlash('Something went wrong. Please try again.'));
+ .catch(() => createFlash(__('Something went wrong. Please try again.')));
},
handleNotification(data) {
if (data.ci_status === this.mr.ciStatus) return;
@@ -210,22 +259,22 @@ export default {
this.pollingInterval.stopTimer();
},
bindEventHubListeners() {
- eventHub.$on('MRWidgetUpdateRequested', (cb) => {
+ eventHub.$on('MRWidgetUpdateRequested', cb => {
this.checkStatus(cb);
});
// `params` should be an Array contains a Boolean, like `[true]`
// Passing parameter as Boolean didn't work.
- eventHub.$on('SetBranchRemoveFlag', (params) => {
+ eventHub.$on('SetBranchRemoveFlag', params => {
[this.mr.isRemovingSourceBranch] = params;
});
- eventHub.$on('FailedToMerge', (mergeError) => {
+ eventHub.$on('FailedToMerge', mergeError => {
this.mr.state = 'failedToMerge';
this.mr.mergeError = mergeError;
});
- eventHub.$on('UpdateWidgetData', (data) => {
+ eventHub.$on('UpdateWidgetData', data => {
this.mr.setData(data);
});
@@ -241,48 +290,29 @@ export default {
this.stopPolling();
});
},
- handleMounted() {
- this.setFaviconHelper();
- this.initDeploymentsPolling();
- },
},
};
</script>
<template>
<div class="mr-state-widget prepend-top-default">
- <mr-widget-header
- :mr="mr"
- />
- <mr-widget-pipeline
+ <mr-widget-header :mr="mr" />
+ <mr-widget-pipeline-container
v-if="shouldRenderPipelines"
- :pipeline="mr.pipeline"
- :ci-status="mr.ciStatus"
- :has-ci="mr.hasCI"
- :source-branch="mr.sourceBranch"
- :source-branch-link="mr.sourceBranchLink"
- />
- <deployment
- v-for="deployment in mr.deployments"
- :key="deployment.id"
- :deployment="deployment"
+ class="mr-widget-workflow"
+ :mr="mr"
/>
- <div class="mr-section-container">
+ <div class="mr-section-container mr-widget-workflow">
<grouped-test-reports-app
v-if="mr.testResultsPath"
+ class="js-reports-container"
:endpoint="mr.testResultsPath"
/>
+
<div class="mr-widget-section">
- <component
- :is="componentName"
- :mr="mr"
- :service="service"
- />
+ <component :is="componentName" :mr="mr" :service="service" />
- <section
- v-if="mr.allowCollaboration"
- class="mr-info-list mr-links"
- >
- {{ s__("mrWidget|Allows commits from members who can merge to the target branch") }}
+ <section v-if="mr.allowCollaboration" class="mr-info-list mr-links">
+ {{ s__('mrWidget|Allows commits from members who can merge to the target branch') }}
</section>
<mr-widget-related-links
@@ -291,16 +321,15 @@ export default {
:related-links="mr.relatedLinks"
/>
- <source-branch-removal-status
- v-if="shouldRenderSourceBranchRemovalStatus"
- />
- </div>
- <div
- v-if="shouldRenderMergeHelp"
- class="mr-widget-footer"
- >
- <mr-widget-merge-help />
+ <source-branch-removal-status v-if="shouldRenderSourceBranchRemovalStatus" />
</div>
+ <div v-if="shouldRenderMergeHelp" class="mr-widget-footer"><mr-widget-merge-help /></div>
</div>
+ <mr-widget-pipeline-container
+ v-if="shouldRenderMergedPipeline"
+ class="js-post-merge-pipeline mr-widget-workflow"
+ :mr="mr"
+ :is-post-merge="true"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/services/ee_switch_mr_widget_service.js b/app/assets/javascripts/vue_merge_request_widget/services/ee_switch_mr_widget_service.js
new file mode 100644
index 00000000000..ea2aabb78fe
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/services/ee_switch_mr_widget_service.js
@@ -0,0 +1,3 @@
+import MRWidgetService from './mr_widget_service';
+
+export default MRWidgetService;
diff --git a/app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js b/app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js
index fecbfec2214..0bb70bfd658 100644
--- a/app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js
+++ b/app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js
@@ -21,8 +21,12 @@ export default class MRWidgetService {
return axios.delete(this.endpoints.sourceBranchPath);
}
- fetchDeployments() {
- return axios.get(this.endpoints.ciEnvironmentsStatusPath);
+ fetchDeployments(targetParam) {
+ return axios.get(this.endpoints.ciEnvironmentsStatusPath, {
+ params: {
+ environment_target: targetParam,
+ },
+ });
}
poll() {
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_get_state_key.js b/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_get_state_key.js
new file mode 100644
index 00000000000..ebef30e3eab
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_get_state_key.js
@@ -0,0 +1,3 @@
+import getStateKey from './get_state_key';
+
+export default getStateKey;
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_mr_widget_store.js
new file mode 100644
index 00000000000..92a07c53f2d
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_mr_widget_store.js
@@ -0,0 +1,3 @@
+import MergeRequestStore from './mr_widget_store';
+
+export default MergeRequestStore;
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_state_maps.js b/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_state_maps.js
new file mode 100644
index 00000000000..50cf9503ea7
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/ee_switch_state_maps.js
@@ -0,0 +1,3 @@
+import stateMaps from './state_maps';
+
+export default stateMaps;
diff --git a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
index 672e5280b5e..5c9a7133a6e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
+++ b/app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
@@ -1,5 +1,5 @@
import Timeago from 'timeago.js';
-import { getStateKey } from '../dependencies';
+import getStateKey from './ee_switch_get_state_key';
import { stateKey } from './state_maps';
import { formatDate } from '../../lib/utils/datetime_utility';
@@ -18,6 +18,7 @@ export default class MergeRequestStore {
this.squash = data.squash;
this.squashBeforeMergeHelpPath =
this.squashBeforeMergeHelpPath || data.squash_before_merge_help_path;
+ this.troubleshootingDocsPath = this.troubleshootingDocsPath || data.troubleshooting_docs_path;
this.enableSquashBeforeMerge = this.enableSquashBeforeMerge || true;
this.iid = data.iid;
@@ -32,7 +33,9 @@ export default class MergeRequestStore {
this.commitsCount = data.commits_count;
this.divergedCommitsCount = data.diverged_commits_count;
this.pipeline = data.pipeline || {};
+ this.mergePipeline = data.merge_pipeline || {};
this.deployments = this.deployments || data.deployments || [];
+ this.postMergeDeployments = this.postMergeDeployments || [];
this.initRebase(data);
if (data.issues_links) {
diff --git a/app/assets/javascripts/vue_shared/components/bar_chart.vue b/app/assets/javascripts/vue_shared/components/bar_chart.vue
index 3ced4eb691a..4abf795f7bd 100644
--- a/app/assets/javascripts/vue_shared/components/bar_chart.vue
+++ b/app/assets/javascripts/vue_shared/components/bar_chart.vue
@@ -118,7 +118,9 @@ export default {
this.rectYAxisLabelDims.height != null ? this.rectYAxisLabelDims.height / 2 : 0;
const yCoord = this.vbHeight / 2 + rectWidth - 5;
- return `translate(${this.minX + this.yAxisTextTransformPadding}, ${yCoord}) rotate(-${this.yAxisTextRotation})`;
+ return `translate(${this.minX + this.yAxisTextTransformPadding}, ${yCoord}) rotate(-${
+ this.yAxisTextRotation
+ })`;
},
},
mounted() {
@@ -207,8 +209,7 @@ export default {
renderedYAxis.selectAll('.tick').each(function createTickLines(d, i) {
if (i > 0) {
- d3
- .select(this)
+ d3.select(this)
.select('line')
.attr('x2', width)
.attr('class', 'axis-tick');
@@ -217,8 +218,7 @@ export default {
// Add the panning capabilities
if (this.isPanAvailable) {
- d3
- .select(this.$refs.baseSvg)
+ d3.select(this.$refs.baseSvg)
.call(this.zoom)
.on('wheel.zoom', null); // This disables the pan of the graph with the scroll of the mouse wheel
}
@@ -271,28 +271,20 @@ export default {
};
</script>
<template>
- <div
- ref="svgContainer"
- :class="activateGrabCursor"
- class="svg-graph-container"
- >
+ <div ref="svgContainer" :class="activateGrabCursor" class="svg-graph-container">
<svg
ref="baseSvg"
:width="vpWidth"
:height="vpHeight"
:viewBox="svgViewBox"
- :preserveAspectRatio="preserveAspectRatioType">
- <g
- ref="xAxis"
- :transform="xAxisLocation"
- class="x-axis"
- />
+ :preserveAspectRatio="preserveAspectRatioType"
+ >
+ <g ref="xAxis" :transform="xAxisLocation" class="x-axis" />
<g v-if="!isLoading">
- <template
- v-for="(data, index) in graphData">
+ <template v-for="(data, index) in graphData">
<rect
- v-tooltip
:key="index"
+ v-tooltip
:width="xScale.bandwidth()"
:x="xScale(data.name)"
:y="yScale(data.value)"
@@ -301,43 +293,24 @@ export default {
:title="setTooltipTitle(data)"
class="bar-rect"
data-placement="top"
- @mouseover="barHoveredIn(index)"
- @mouseout="barHoveredOut(index)"
+ @mouseover="barHoveredIn(index);"
+ @mouseout="barHoveredOut(index);"
/>
</template>
</g>
- <rect
- :height="vbHeight + 100"
- transform="translate(-100, -5)"
- width="100"
- fill="#fff"
- />
+ <rect :height="vbHeight + 100" transform="translate(-100, -5)" width="100" fill="#fff" />
<g class="y-axis-label">
- <line
- :x1="0"
- :x2="0"
- :y1="0"
- :y2="vbHeight"
- transform="translate(-35, 0)"
- stroke="black"
- />
- <!--Get text length and change the height of this rect accordingly-->
+ <line :x1="0" :x2="0" :y1="0" :y2="vbHeight" transform="translate(-35, 0)" stroke="black" />
+ <!-- Get text length and change the height of this rect accordingly -->
<rect
:height="rectYAxisLabelDims.height"
:transform="yAxisLabelRectTransform"
:width="30"
fill="#fff"
/>
- <text
- ref="yAxisLabel"
- :transform="yAxisLabelTextTransform"
- >
- {{ yAxisLabel }}
- </text>
+ <text ref="yAxisLabel" :transform="yAxisLabelTextTransform">{{ yAxisLabel }}</text>
</g>
- <g
- class="y-axis"
- />
+ <g class="y-axis" />
<g v-if="showScrollIndicator">
<rect
:height="vbHeight + 100"
@@ -354,38 +327,24 @@ export default {
class="animate-flicker"
/>
</g>
- <!--The line that shows up when the data elements surpass the available width -->
- <g
- v-if="showScrollIndicator"
- :transform="scrollIndicatorTransform">
- <rect
- :height="vbHeight"
- x="0"
- y="0"
- width="20"
- fill="url(#shadow-gradient)"
- />
+ <!-- The line that shows up when the data elements surpass the available width -->
+ <g v-if="showScrollIndicator" :transform="scrollIndicatorTransform">
+ <rect :height="vbHeight" x="0" y="0" width="20" fill="url(#shadow-gradient)" />
</g>
- <!--Left scroll indicator-->
- <g
- v-if="showLeftScrollIndicator"
- transform="translate(0, 0)">
- <rect
- :height="vbHeight"
- x="0"
- y="0"
- width="20"
- fill="url(#left-shadow-gradient)"
- />
+ <!-- Left scroll indicator -->
+ <g v-if="showLeftScrollIndicator" transform="translate(0, 0)">
+ <rect :height="vbHeight" x="0" y="0" width="20" fill="url(#left-shadow-gradient)" />
</g>
<svg-gradient
:colors="gradientColors"
:opacity="gradientOpacity"
- identifier-name="shadow-gradient"/>
+ identifier-name="shadow-gradient"
+ />
<svg-gradient
:colors="inverseGradientColors"
:opacity="inverseGradientOpacity"
- identifier-name="left-shadow-gradient"/>
+ identifier-name="left-shadow-gradient"
+ />
</svg>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/callout.vue b/app/assets/javascripts/vue_shared/components/callout.vue
index ccf802c456c..ddbb14ae812 100644
--- a/app/assets/javascripts/vue_shared/components/callout.vue
+++ b/app/assets/javascripts/vue_shared/components/callout.vue
@@ -17,11 +17,7 @@ export default {
};
</script>
<template>
- <div
- :class="`bs-callout bs-callout-${category}`"
- role="alert"
- aria-live="assertive"
- >
+ <div :class="`bs-callout bs-callout-${category}`" role="alert" aria-live="assertive">
{{ message }}
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/changed_file_icon.vue b/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
new file mode 100644
index 00000000000..bb7710f708e
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/changed_file_icon.vue
@@ -0,0 +1,101 @@
+<script>
+import { GlTooltipDirective } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
+import { pluralize } from '~/lib/utils/text_utility';
+import { __, sprintf } from '~/locale';
+import { getCommitIconMap } from '~/ide/utils';
+
+export default {
+ components: {
+ Icon,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ file: {
+ type: Object,
+ required: true,
+ },
+ showTooltip: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ showStagedIcon: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ forceModifiedIcon: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ size: {
+ type: Number,
+ required: false,
+ default: 12,
+ },
+ },
+ computed: {
+ changedIcon() {
+ const suffix = !this.file.changed && this.file.staged && !this.showStagedIcon ? '-solid' : '';
+
+ if (this.forceModifiedIcon) return `file-modified${suffix}`;
+
+ return `${getCommitIconMap(this.file).icon}${suffix}`;
+ },
+ changedIconClass() {
+ return `${this.changedIcon} float-left d-block`;
+ },
+ tooltipTitle() {
+ if (!this.showTooltip) return undefined;
+
+ const type = this.file.tempFile ? 'addition' : 'modification';
+
+ if (this.file.changed && !this.file.staged) {
+ return sprintf(__('Unstaged %{type}'), {
+ type,
+ });
+ } else if (!this.file.changed && this.file.staged) {
+ return sprintf(__('Staged %{type}'), {
+ type,
+ });
+ } else if (this.file.changed && this.file.staged) {
+ return sprintf(__('Unstaged and staged %{type}'), {
+ type: pluralize(type),
+ });
+ }
+
+ return undefined;
+ },
+ showIcon() {
+ return this.file.changed || this.file.tempFile || this.file.staged || this.file.deleted;
+ },
+ },
+};
+</script>
+
+<template>
+ <span v-gl-tooltip.right :title="tooltipTitle" class="file-changed-icon ml-auto">
+ <icon v-if="showIcon" :name="changedIcon" :size="size" :css-classes="changedIconClass" />
+ </span>
+</template>
+
+<style>
+.file-addition,
+.file-addition-solid {
+ color: #1aaa55;
+}
+
+.file-modified,
+.file-modified-solid {
+ color: #fc9403;
+}
+
+.file-deletion,
+.file-deletion-solid {
+ color: #db3b21;
+}
+</style>
diff --git a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
index a2518e2a611..b0962684430 100644
--- a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
@@ -1,6 +1,6 @@
<script>
+import { GlTooltipDirective } from '@gitlab/ui';
import CiIcon from './ci_icon.vue';
-import tooltip from '../directives/tooltip';
/**
* Renders CI Badge link with CI icon and status text based on
* API response shared between all places where it is used.
@@ -27,7 +27,7 @@ export default {
CiIcon,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
status: {
@@ -43,14 +43,14 @@ export default {
computed: {
cssClass() {
const className = this.status.group;
- return className ? `ci-status ci-${className}` : 'ci-status';
+ return className ? `ci-status ci-${className} qa-status-badge` : 'ci-status qa-status-badge';
},
},
};
</script>
<template>
<a
- v-tooltip
+ v-gl-tooltip
:href="status.details_path"
:class="cssClass"
:title="!showText ? status.text : ''"
diff --git a/app/assets/javascripts/vue_shared/components/ci_icon.vue b/app/assets/javascripts/vue_shared/components/ci_icon.vue
index 03f924ba99d..b8eb555106f 100644
--- a/app/assets/javascripts/vue_shared/components/ci_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_icon.vue
@@ -59,10 +59,5 @@ export default {
};
</script>
<template>
- <span :class="cssClass">
- <icon
- :name="icon"
- :size="size"
- />
- </span>
+ <span :class="cssClass"> <icon :name="icon" :size="size" /> </span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/clipboard_button.vue b/app/assets/javascripts/vue_shared/components/clipboard_button.vue
index 945a33d9622..671b4909839 100644
--- a/app/assets/javascripts/vue_shared/components/clipboard_button.vue
+++ b/app/assets/javascripts/vue_shared/components/clipboard_button.vue
@@ -12,20 +12,18 @@
* css-class="btn-transparent"
* />
*/
-import tooltip from '../directives/tooltip';
+import { GlButton, GlTooltipDirective } from '@gitlab/ui';
import Icon from '../components/icon.vue';
export default {
name: 'ClipboardButton',
-
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
-
components: {
+ GlButton,
Icon,
},
-
props: {
text: {
type: String,
@@ -68,16 +66,12 @@ export default {
</script>
<template>
- <button
- v-tooltip
+ <gl-button
+ v-gl-tooltip="{ placement: tooltipPlacement, container: tooltipContainer }"
:class="cssClass"
:title="title"
:data-clipboard-text="clipboardText"
- :data-container="tooltipContainer"
- :data-placement="tooltipPlacement"
- type="button"
- class="btn"
>
<icon name="duplicate" />
- </button>
+ </gl-button>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/commit.vue b/app/assets/javascripts/vue_shared/components/commit.vue
index 13bca99dcb3..ee685a4b8cd 100644
--- a/app/assets/javascripts/vue_shared/components/commit.vue
+++ b/app/assets/javascripts/vue_shared/components/commit.vue
@@ -1,11 +1,11 @@
<script>
+import { GlTooltipDirective } from '@gitlab/ui';
import UserAvatarLink from './user_avatar/user_avatar_link.vue';
-import tooltip from '../directives/tooltip';
import Icon from '../../vue_shared/components/icon.vue';
export default {
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
components: {
UserAvatarLink,
@@ -13,7 +13,7 @@ export default {
},
props: {
/**
- * Indicates the existance of a tag.
+ * Indicates the existence of a tag.
* Used to render the correct icon, if true will render `fa-tag` icon,
* if false will render a svg sprite fork icon
*/
@@ -111,45 +111,19 @@ export default {
<div class="branch-commit">
<template v-if="hasCommitRef && showBranch">
<div class="icon-container">
- <i
- v-if="tag"
- class="fa fa-tag"
- aria-hidden="true"
- >
- </i>
- <icon
- v-if="!tag"
- name="fork"
- />
+ <i v-if="tag" class="fa fa-tag" aria-hidden="true"> </i> <icon v-if="!tag" name="fork" />
</div>
- <a
- v-tooltip
- :href="commitRef.ref_url"
- :title="commitRef.name"
- class="ref-name"
- data-container="body"
- >
+ <a v-gl-tooltip :href="commitRef.ref_url" :title="commitRef.name" class="ref-name">
{{ commitRef.name }}
</a>
</template>
- <icon
- name="commit"
- class="commit-icon js-commit-icon"
- />
+ <icon name="commit" class="commit-icon js-commit-icon" />
- <a
- :href="commitUrl"
- class="commit-sha"
- >
- {{ shortSha }}
- </a>
+ <a :href="commitUrl" class="commit-sha"> {{ shortSha }} </a>
<div class="commit-title flex-truncate-parent">
- <span
- v-if="title"
- class="flex-truncate-child"
- >
+ <span v-if="title" class="flex-truncate-child">
<user-avatar-link
v-if="hasAuthor"
:link-href="author.path"
@@ -158,16 +132,9 @@ export default {
:tooltip-text="author.username"
class="avatar-image-container"
/>
- <a
- :href="commitUrl"
- class="commit-row-message"
- >
- {{ title }}
- </a>
- </span>
- <span v-else>
- Can't find HEAD commit for this branch
+ <a :href="commitUrl" class="commit-row-message"> {{ title }} </a>
</span>
+ <span v-else> Can't find HEAD commit for this branch </span>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue
index f1ef50d0e3d..c6d61d6ee62 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue
@@ -1,9 +1,11 @@
<script>
+import { GlLink } from '@gitlab/ui';
import Icon from '../../icon.vue';
import { numberToHumanSize } from '../../../../lib/utils/number_utils';
export default {
components: {
+ GlLink,
Icon,
},
props: {
@@ -37,19 +39,10 @@ export default {
({{ fileSizeReadable }})
</template>
</p>
- <a
- :href="path"
- class="btn btn-default"
- rel="nofollow"
- download
- target="_blank">
- <icon
- :size="16"
- name="download"
- css-classes="float-left append-right-8"
- />
+ <gl-link :href="path" class="btn btn-default" rel="nofollow" download target="_blank">
+ <icon :size="16" name="download" css-classes="float-left append-right-8" />
{{ __('Download') }}
- </a>
+ </gl-link>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue
index 8163947cd0c..2ca933a37d2 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue
@@ -17,19 +17,30 @@ export default {
type: Boolean,
default: true,
},
+ innerCssClasses: {
+ type: [Array, Object, String],
+ required: false,
+ default: '',
+ },
},
data() {
return {
width: 0,
height: 0,
- isZoomable: false,
- isZoomed: false,
+ isLoaded: false,
};
},
computed: {
fileSizeReadable() {
return numberToHumanSize(this.fileSize);
},
+
+ hasFileSize() {
+ return this.fileSize > 0;
+ },
+ hasDimensions() {
+ return this.width && this.height;
+ },
},
beforeDestroy() {
window.removeEventListener('resize', this.resizeThrottled, false);
@@ -48,51 +59,40 @@ export default {
const { contentImg } = this.$refs;
if (contentImg) {
- this.isZoomable =
- contentImg.naturalWidth > contentImg.width ||
- contentImg.naturalHeight > contentImg.height;
-
this.width = contentImg.naturalWidth;
this.height = contentImg.naturalHeight;
- this.$emit('imgLoaded', {
- width: this.width,
- height: this.height,
- renderedWidth: contentImg.clientWidth,
- renderedHeight: contentImg.clientHeight,
+ this.$nextTick(() => {
+ this.isLoaded = true;
+
+ this.$emit('imgLoaded', {
+ width: this.width,
+ height: this.height,
+ renderedWidth: contentImg.clientWidth,
+ renderedHeight: contentImg.clientHeight,
+ });
});
}
},
- onImgClick() {
- if (this.isZoomable) this.isZoomed = !this.isZoomed;
- },
},
};
</script>
<template>
- <div class="file-container">
- <div class="file-content image_file">
- <img
- ref="contentImg"
- :class="{ 'is-zoomable': isZoomable, 'is-zoomed': isZoomed }"
- :src="path"
- :alt="path"
- @load="onImgLoad"
- @click="onImgClick"/>
- <p
- v-if="renderInfo"
- class="file-info prepend-top-10">
- <template v-if="fileSize>0">
- {{ fileSizeReadable }}
- </template>
- <template v-if="fileSize>0 && width && height">
- |
- </template>
- <template v-if="width && height">
- W: {{ width }} | H: {{ height }}
- </template>
- </p>
+ <div>
+ <div :class="innerCssClasses" class="position-relative">
+ <img ref="contentImg" :src="path" @load="onImgLoad" /> <slot name="image-overlay"></slot>
</div>
+ <p v-if="renderInfo" class="image-info">
+ <template v-if="hasFileSize">
+ {{ fileSizeReadable }}
+ </template>
+ <template v-if="hasFileSize && hasDimensions">
+ |
+ </template>
+ <template v-if="hasDimensions">
+ <strong>W</strong>: {{ width }} | <strong>H</strong>: {{ height }}
+ </template>
+ </p>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
index a10deb93f0f..c9915f7d685 100644
--- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/markdown_viewer.vue
@@ -2,14 +2,14 @@
import axios from '~/lib/utils/axios_utils';
import { __ } from '~/locale';
import $ from 'jquery';
-import SkeletonLoadingContainer from '~/vue_shared/components/skeleton_loading_container.vue';
+import { GlSkeletonLoading } from '@gitlab/ui';
const { CancelToken } = axios;
let axiosSource;
export default {
components: {
- SkeletonLoadingContainer,
+ GlSkeletonLoading,
},
props: {
content: {
@@ -78,13 +78,8 @@ export default {
</script>
<template>
- <div
- ref="markdown-preview"
- class="md md-previewer">
- <skeleton-loading-container v-if="isLoading" />
- <div
- v-else
- v-html="previewContent">
- </div>
+ <div ref="markdown-preview" class="md md-previewer">
+ <gl-skeleton-loading v-if="isLoading" />
+ <div v-else v-html="previewContent"></div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/deprecated_modal.vue b/app/assets/javascripts/vue_shared/components/deprecated_modal.vue
index 9c1e5c68649..2129f90d497 100644
--- a/app/assets/javascripts/vue_shared/components/deprecated_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/deprecated_modal.vue
@@ -1,150 +1,124 @@
<script>
- /* eslint-disable vue/require-default-prop */
- export default {
- name: 'DeprecatedModal', // use GlModal instead
+/* eslint-disable vue/require-default-prop */
+export default {
+ name: 'DeprecatedModal', // use GlModal instead
- props: {
- id: {
- type: String,
- required: false,
- },
- title: {
- type: String,
- required: false,
- },
- text: {
- type: String,
- required: false,
- },
- hideFooter: {
- type: Boolean,
- required: false,
- default: false,
- },
- kind: {
- type: String,
- required: false,
- default: 'primary',
- },
- modalDialogClass: {
- type: String,
- required: false,
- default: '',
- },
- closeKind: {
- type: String,
- required: false,
- default: 'default',
- },
- closeButtonLabel: {
- type: String,
- required: false,
- default: 'Cancel',
- },
- primaryButtonLabel: {
- type: String,
- required: false,
- default: '',
- },
- secondaryButtonLabel: {
- type: String,
- required: false,
- default: '',
- },
- submitDisabled: {
- type: Boolean,
- required: false,
- default: false,
- },
+ props: {
+ id: {
+ type: String,
+ required: false,
},
+ title: {
+ type: String,
+ required: false,
+ },
+ text: {
+ type: String,
+ required: false,
+ },
+ hideFooter: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ kind: {
+ type: String,
+ required: false,
+ default: 'primary',
+ },
+ modalDialogClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ closeKind: {
+ type: String,
+ required: false,
+ default: 'default',
+ },
+ closeButtonLabel: {
+ type: String,
+ required: false,
+ default: 'Cancel',
+ },
+ primaryButtonLabel: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ secondaryButtonLabel: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ submitDisabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
- computed: {
- btnKindClass() {
- return {
- [`btn-${this.kind}`]: true,
- };
- },
- btnCancelKindClass() {
- return {
- [`btn-${this.closeKind}`]: true,
- };
- },
+ computed: {
+ btnKindClass() {
+ return {
+ [`btn-${this.kind}`]: true,
+ };
},
+ btnCancelKindClass() {
+ return {
+ [`btn-${this.closeKind}`]: true,
+ };
+ },
+ },
- methods: {
- emitCancel(event) {
- this.$emit('cancel', event);
- },
- emitSubmit(event) {
- this.$emit('submit', event);
- },
+ methods: {
+ emitCancel(event) {
+ this.$emit('cancel', event);
+ },
+ emitSubmit(event) {
+ this.$emit('submit', event);
},
- };
+ },
+};
</script>
<template>
<div class="modal-open">
- <div
- :id="id"
- :class="id ? '' : 'd-block'"
- class="modal"
- role="dialog"
- tabindex="-1"
- >
- <div
- :class="modalDialogClass"
- class="modal-dialog"
- role="document"
- >
+ <div :id="id" :class="id ? '' : 'd-block'" class="modal" role="dialog" tabindex="-1">
+ <div :class="modalDialogClass" class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<slot name="header">
- <h4 class="modal-title float-left">
- {{ title }}
- </h4>
+ <h4 class="modal-title float-left">{{ title }}</h4>
<button
type="button"
class="close float-right"
data-dismiss="modal"
aria-label="Close"
- @click="emitCancel($event)"
+ @click="emitCancel($event);"
>
<span aria-hidden="true">&times;</span>
</button>
</slot>
</div>
<div class="modal-body">
- <slot
- :text="text"
- name="body"
- >
+ <slot :text="text" name="body">
<p>{{ text }}</p>
</slot>
</div>
- <div
- v-if="!hideFooter"
- class="modal-footer"
- >
+ <div v-if="!hideFooter" class="modal-footer">
<button
:class="btnCancelKindClass"
type="button"
class="btn"
data-dismiss="modal"
- @click="emitCancel($event)"
+ @click="emitCancel($event);"
>
{{ closeButtonLabel }}
</button>
- <slot
- v-if="secondaryButtonLabel"
- name="secondary-button"
- >
- <button
- v-if="secondaryButtonLabel"
- type="button"
- class="btn"
- data-dismiss="modal"
- >
+ <slot v-if="secondaryButtonLabel" name="secondary-button">
+ <button v-if="secondaryButtonLabel" type="button" class="btn" data-dismiss="modal">
{{ secondaryButtonLabel }}
</button>
</slot>
@@ -156,7 +130,7 @@
type="button"
class="btn js-primary-button"
data-dismiss="modal"
- @click="emitSubmit($event)"
+ @click="emitSubmit($event);"
>
{{ primaryButtonLabel }}
</button>
@@ -164,10 +138,6 @@
</div>
</div>
</div>
- <div
- v-if="!id"
- class="modal-backdrop fade show"
- >
- </div>
+ <div v-if="!id" class="modal-backdrop fade show"></div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue
index cfc5343217c..bb2e0e12c11 100644
--- a/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/diff_viewer/diff_viewer.vue
@@ -60,15 +60,16 @@ export default {
</script>
<template>
- <div
- v-if="viewer"
- class="diff-file preview-container">
+ <div v-if="viewer" class="diff-file preview-container">
<component
:is="viewer"
:diff-mode="diffMode"
:new-path="fullNewPath"
:old-path="fullOldPath"
:project-path="projectPath"
- />
+ >
+ <slot slot="image-overlay" name="image-overlay"> </slot>
+ </component>
+ <slot></slot>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/download_diff_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/download_diff_viewer.vue
index 50389b6ae63..40ae9ed6c02 100644
--- a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/download_diff_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/download_diff_viewer.vue
@@ -32,37 +32,19 @@ export default {
<template>
<div class="diff-file-container">
<div class="diff-viewer">
- <div
- v-if="diffMode === $options.diffModes.replaced"
- class="two-up view row">
+ <div v-if="diffMode === $options.diffModes.replaced" class="two-up view row">
<div class="col-sm-6 deleted">
- <download-viewer
- :path="oldPath"
- :project-path="projectPath"
- />
+ <download-viewer :path="oldPath" :project-path="projectPath" />
</div>
<div class="col-sm-6 added">
- <download-viewer
- :path="newPath"
- :project-path="projectPath"
- />
+ <download-viewer :path="newPath" :project-path="projectPath" />
</div>
</div>
- <div
- v-else-if="diffMode === $options.diffModes.new"
- class="added">
- <download-viewer
- :path="newPath"
- :project-path="projectPath"
- />
+ <div v-else-if="diffMode === $options.diffModes.new" class="added">
+ <download-viewer :path="newPath" :project-path="projectPath" />
</div>
- <div
- v-else
- class="deleted">
- <download-viewer
- :path="oldPath"
- :project-path="projectPath"
- />
+ <div v-else class="deleted">
+ <download-viewer :path="oldPath" :project-path="projectPath" />
</div>
</div>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/onion_skin_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/onion_skin_viewer.vue
index 38e881d17a2..f085ef35ccc 100644
--- a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/onion_skin_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/onion_skin_viewer.vue
@@ -15,11 +15,6 @@ export default {
type: String,
required: true,
},
- projectPath: {
- type: String,
- required: false,
- default: '',
- },
},
data() {
return {
@@ -105,53 +100,48 @@ export default {
<div class="onion-skin view">
<div
:style="{
- 'width': onionMaxPixelWidth,
- 'height': onionMaxPixelHeight,
+ width: onionMaxPixelWidth,
+ height: onionMaxPixelHeight,
'user-select': dragging === true ? 'none' : '',
}"
- class="onion-skin-frame">
+ class="onion-skin-frame"
+ >
<div
:style="{
- 'width': onionMaxPixelWidth,
- 'height': onionMaxPixelHeight,
+ width: onionMaxPixelWidth,
+ height: onionMaxPixelHeight,
}"
- class="frame deleted">
+ class="frame deleted"
+ >
<image-viewer
key="onionOldImg"
:render-info="false"
:path="oldPath"
- :project-path="projectPath"
@imgLoaded="onionOldImgLoaded"
/>
</div>
<div
ref="addedFrame"
:style="{
- 'opacity': onionOpacity,
- 'width': onionMaxPixelWidth,
- 'height': onionMaxPixelHeight,
+ opacity: onionOpacity,
+ width: onionMaxPixelWidth,
+ height: onionMaxPixelHeight,
}"
- class="added frame">
+ class="added frame"
+ >
<image-viewer
key="onionNewImg"
:render-info="false"
:path="newPath"
- :project-path="projectPath"
@imgLoaded="onionNewImgLoaded"
- />
+ >
+ <slot slot="image-overlay" name="image-overlay"> </slot>
+ </image-viewer>
</div>
<div class="controls">
<div class="transparent"></div>
- <div
- ref="dragTrack"
- class="drag-track"
- @mousedown="startDrag"
- @mouseup="stopDrag">
- <div
- ref="dragger"
- :style="{ 'left': onionDraggerPixelPos }"
- class="dragger">
- </div>
+ <div ref="dragTrack" class="drag-track" @mousedown="startDrag" @mouseup="stopDrag">
+ <div ref="dragger" :style="{ left: onionDraggerPixelPos }" class="dragger"></div>
</div>
<div class="opaque"></div>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue
index 86366c799a2..1c970b72a66 100644
--- a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/swipe_viewer.vue
@@ -16,11 +16,6 @@ export default {
type: String,
required: true,
},
- projectPath: {
- type: String,
- required: false,
- default: '',
- },
},
data() {
return {
@@ -30,7 +25,7 @@ export default {
swipeMaxWidth: undefined,
swipeMaxHeight: undefined,
swipeBarPos: 1,
- swipeWrapWidth: undefined,
+ swipeWrapWidth: 0,
};
},
computed: {
@@ -68,7 +63,7 @@ export default {
leftValue = clientWidth - spaceLeft;
}
- this.swipeWrapWidth = this.swipeMaxWidth - leftValue;
+ this.swipeWrapWidth = (leftValue / clientWidth) * 100;
this.swipeBarPos = leftValue;
},
startDrag() {
@@ -86,7 +81,6 @@ export default {
// Add 2 for border width
this.swipeMaxWidth =
Math.max(this.swipeOldImgInfo.renderedWidth, this.swipeNewImgInfo.renderedWidth) + 2;
- this.swipeWrapWidth = this.swipeMaxWidth;
this.swipeMaxHeight =
Math.max(this.swipeOldImgInfo.renderedHeight, this.swipeNewImgInfo.renderedHeight) + 2;
@@ -110,48 +104,43 @@ export default {
<template>
<div class="swipe view">
- <div
- ref="swipeFrame"
- :style="{
- 'width': swipeMaxPixelWidth,
- 'height': swipeMaxPixelHeight,
- }"
- class="swipe-frame">
- <div class="frame deleted">
- <image-viewer
- key="swipeOldImg"
- ref="swipeOldImg"
- :render-info="false"
- :path="oldPath"
- :project-path="projectPath"
- @imgLoaded="swipeOldImgLoaded"
- />
- </div>
+ <div ref="swipeFrame" class="swipe-frame">
+ <image-viewer
+ key="swipeOldImg"
+ ref="swipeOldImg"
+ :render-info="false"
+ :path="oldPath"
+ class="frame deleted"
+ @imgLoaded="swipeOldImgLoaded"
+ />
<div
ref="swipeWrap"
:style="{
- 'width': swipeWrapPixelWidth,
- 'height': swipeMaxPixelHeight,
+ width: `${swipeWrapWidth}%`,
}"
- class="swipe-wrap">
- <div class="frame added">
- <image-viewer
- key="swipeNewImg"
- :render-info="false"
- :path="newPath"
- :project-path="projectPath"
- @imgLoaded="swipeNewImgLoaded"
- />
- </div>
+ class="swipe-wrap"
+ >
+ <image-viewer
+ key="swipeNewImg"
+ :render-info="false"
+ :path="newPath"
+ :style="{
+ width: swipeMaxPixelWidth,
+ }"
+ class="frame added"
+ @imgLoaded="swipeNewImgLoaded"
+ >
+ <slot slot="image-overlay" name="image-overlay"> </slot>
+ </image-viewer>
</div>
<span
ref="swipeBar"
- :style="{ 'left': swipeBarPixelPos }"
+ :style="{ left: swipeBarPixelPos }"
class="swipe-bar"
@mousedown="startDrag"
- @mouseup="stopDrag">
- <span class="top-handle"></span>
- <span class="bottom-handle"></span>
+ @mouseup="stopDrag"
+ >
+ <span class="top-handle"></span> <span class="bottom-handle"></span>
</span>
</div>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/two_up_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/two_up_viewer.vue
index 9c19266ecdf..a17fc022195 100644
--- a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/two_up_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff/two_up_viewer.vue
@@ -14,28 +14,25 @@ export default {
type: String,
required: true,
},
- projectPath: {
- type: String,
- required: false,
- default: '',
- },
},
};
</script>
<template>
- <div class="two-up view row">
- <div class="col-sm-6 frame deleted">
- <image-viewer
- :path="oldPath"
- :project-path="projectPath"
- />
- </div>
- <div class="col-sm-6 frame added">
- <image-viewer
- :path="newPath"
- :project-path="projectPath"
- />
- </div>
+ <div class="two-up view d-flex">
+ <image-viewer
+ :path="oldPath"
+ :render-info="true"
+ inner-css-classes="frame deleted"
+ class="wrap w-50"
+ />
+ <image-viewer
+ :path="newPath"
+ :render-info="true"
+ :inner-css-classes="['frame', 'added']"
+ class="wrap w-50"
+ >
+ <slot slot="image-overlay" name="image-overlay"> </slot>
+ </image-viewer>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue
index 1af85283277..d5fda7e4ed3 100644
--- a/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer.vue
@@ -8,9 +8,6 @@ import { diffModes, imageViewMode } from '../constants';
export default {
components: {
ImageViewer,
- TwoUpViewer,
- SwipeViewer,
- OnionSkinViewer,
},
props: {
diffMode: {
@@ -25,17 +22,35 @@ export default {
type: String,
required: true,
},
- projectPath: {
- type: String,
- required: false,
- default: '',
- },
},
data() {
return {
mode: imageViewMode.twoup,
};
},
+ computed: {
+ imageViewComponent() {
+ switch (this.mode) {
+ case imageViewMode.twoup:
+ return TwoUpViewer;
+ case imageViewMode.swipe:
+ return SwipeViewer;
+ case imageViewMode.onion:
+ return OnionSkinViewer;
+ default:
+ return undefined;
+ }
+ },
+ isNew() {
+ return this.diffMode === diffModes.new;
+ },
+ isRenamed() {
+ return this.diffMode === diffModes.renamed;
+ },
+ imagePath() {
+ return this.isNew || this.isRenamed ? this.newPath : this.oldPath;
+ },
+ },
methods: {
changeMode(newMode) {
this.mode = newMode;
@@ -48,62 +63,56 @@ export default {
<template>
<div class="diff-file-container">
- <div
- v-if="diffMode === $options.diffModes.replaced"
- class="diff-viewer">
+ <div v-if="diffMode === $options.diffModes.replaced" class="diff-viewer">
<div class="image js-replaced-image">
- <two-up-viewer
- v-if="mode === $options.imageViewMode.twoup"
- v-bind="$props"/>
- <swipe-viewer
- v-else-if="mode === $options.imageViewMode.swipe"
- v-bind="$props"/>
- <onion-skin-viewer
- v-else-if="mode === $options.imageViewMode.onion"
- v-bind="$props"/>
+ <component :is="imageViewComponent" v-bind="$props">
+ <slot slot="image-overlay" name="image-overlay"> </slot>
+ </component>
</div>
<div class="view-modes">
<ul class="view-modes-menu">
<li
:class="{
- active: mode === $options.imageViewMode.twoup
+ active: mode === $options.imageViewMode.twoup,
}"
- @click="changeMode($options.imageViewMode.twoup)">
+ @click="changeMode($options.imageViewMode.twoup);"
+ >
{{ s__('ImageDiffViewer|2-up') }}
</li>
<li
:class="{
- active: mode === $options.imageViewMode.swipe
+ active: mode === $options.imageViewMode.swipe,
}"
- @click="changeMode($options.imageViewMode.swipe)">
+ @click="changeMode($options.imageViewMode.swipe);"
+ >
{{ s__('ImageDiffViewer|Swipe') }}
</li>
<li
:class="{
- active: mode === $options.imageViewMode.onion
+ active: mode === $options.imageViewMode.onion,
}"
- @click="changeMode($options.imageViewMode.onion)">
+ @click="changeMode($options.imageViewMode.onion);"
+ >
{{ s__('ImageDiffViewer|Onion skin') }}
</li>
</ul>
</div>
- <div class="note-container"></div>
</div>
- <div
- v-else-if="diffMode === $options.diffModes.new"
- class="diff-viewer added">
- <image-viewer
- :path="newPath"
- :project-path="projectPath"
- />
- </div>
- <div
- v-else
- class="diff-viewer deleted">
- <image-viewer
- :path="oldPath"
- :project-path="projectPath"
- />
+ <div v-else class="diff-viewer">
+ <div class="image">
+ <image-viewer
+ :path="imagePath"
+ :inner-css-classes="[
+ 'frame',
+ {
+ added: isNew,
+ deleted: diffMode === $options.diffModes.deleted,
+ },
+ ]"
+ >
+ <slot v-if="isNew || isRenamed" slot="image-overlay" name="image-overlay"> </slot>
+ </image-viewer>
+ </div>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue
index 31087017968..22f370c4bca 100644
--- a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue
+++ b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_button.vue
@@ -1,7 +1,11 @@
<script>
import { __ } from '~/locale';
+import { GlLoadingIcon } from '@gitlab/ui';
export default {
+ components: {
+ GlLoadingIcon,
+ },
props: {
isDisabled: {
type: Boolean,
@@ -30,30 +34,13 @@ export default {
data-toggle="dropdown"
aria-expanded="false"
>
- <gl-loading-icon
- v-show="isLoading"
- :inline="true"
- />
+ <gl-loading-icon v-show="isLoading" :inline="true" />
<template>
- <slot
- v-if="$slots.default"
- ></slot>
- <span
- v-else
- class="dropdown-toggle-text"
- >
- {{ toggleText }}
- </span>
+ <slot v-if="$slots.default"></slot>
+ <span v-else class="dropdown-toggle-text"> {{ toggleText }} </span>
</template>
- <span
- v-show="!isLoading"
- class="dropdown-toggle-icon"
- >
- <i
- class="fa fa-chevron-down"
- aria-hidden="true"
- data-hidden="true"
- ></i>
+ <span v-show="!isLoading" class="dropdown-toggle-icon">
+ <i class="fa fa-chevron-down" aria-hidden="true" data-hidden="true"></i>
</span>
</button>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_hidden_input.vue b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_hidden_input.vue
index b7a4613bdd2..afde0c81580 100644
--- a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_hidden_input.vue
+++ b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_hidden_input.vue
@@ -14,9 +14,5 @@ export default {
</script>
<template>
- <input
- :name="name"
- :value="value"
- type="hidden"
- />
+ <input :name="name" :value="value" type="hidden" />
</template>
diff --git a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_search_input.vue b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_search_input.vue
index 7f1912f6405..c01c7cc4ccc 100644
--- a/app/assets/javascripts/vue_shared/components/dropdown/dropdown_search_input.vue
+++ b/app/assets/javascripts/vue_shared/components/dropdown/dropdown_search_input.vue
@@ -29,12 +29,7 @@ export default {
type="search"
autocomplete="off"
/>
- <i
- class="fa fa-search dropdown-input-search"
- aria-hidden="true"
- data-hidden="true"
- >
- </i>
+ <i class="fa fa-search dropdown-input-search" aria-hidden="true" data-hidden="true"> </i>
<i
class="fa fa-times dropdown-input-clear js-dropdown-input-clear"
aria-hidden="true"
diff --git a/app/assets/javascripts/vue_shared/components/expand_button.vue b/app/assets/javascripts/vue_shared/components/expand_button.vue
index e6e92594b65..d64ab774431 100644
--- a/app/assets/javascripts/vue_shared/components/expand_button.vue
+++ b/app/assets/javascripts/vue_shared/components/expand_button.vue
@@ -44,14 +44,10 @@ export default {
:aria-label="ariaLabel"
type="button"
class="text-expander btn-blank"
- @click="onClick">
- <icon
- :size="12"
- name="ellipsis_h"
- />
+ @click="onClick"
+ >
+ <icon :size="12" name="ellipsis_h" />
</button>
- <span v-if="!isCollapsed">
- <slot name="expanded"></slot>
- </span>
+ <span v-if="!isCollapsed"> <slot name="expanded"></slot> </span>
</span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/file_icon.vue b/app/assets/javascripts/vue_shared/components/file_icon.vue
index 408f7d7965f..b69ecc1dce6 100644
--- a/app/assets/javascripts/vue_shared/components/file_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/file_icon.vue
@@ -1,4 +1,5 @@
<script>
+import { GlLoadingIcon } from '@gitlab/ui';
import getIconForFile from './file_icon/file_icon_map';
import icon from '../../vue_shared/components/icon.vue';
@@ -17,6 +18,7 @@ import icon from '../../vue_shared/components/icon.vue';
export default {
components: {
icon,
+ GlLoadingIcon,
},
props: {
fileName: {
@@ -70,21 +72,10 @@ export default {
</script>
<template>
<span>
- <svg
- v-if="!loading && !folder"
- :class="[iconSizeClass, cssClasses]"
- >
- <use v-bind="{ 'xlink:href':spriteHref }" />
+ <svg v-if="!loading && !folder" :class="[iconSizeClass, cssClasses]">
+ <use v-bind="{ 'xlink:href': spriteHref }" />
</svg>
- <icon
- v-if="!loading && folder"
- :name="folderIconName"
- :size="size"
- css-classes="folder-icon"
- />
- <gl-loading-icon
- v-if="loading"
- :inline="true"
- />
+ <icon v-if="!loading && folder" :name="folderIconName" :size="size" css-classes="folder-icon" />
+ <gl-loading-icon v-if="loading" :inline="true" />
</span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js b/app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js
index 9bca1993ccc..bffaa096210 100644
--- a/app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js
+++ b/app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js
@@ -549,6 +549,7 @@ const fileNameIcons = {
jenkinsfile: 'jenkins',
'firebase.json': 'firebase',
'.firebaserc': 'firebase',
+ Rakefile: 'ruby',
'rollup.config.js': 'rollup',
'rollup.config.ts': 'rollup',
'rollup-config.js': 'rollup',
@@ -583,7 +584,5 @@ const fileNameIcons = {
};
export default function getIconForFile(name) {
- return fileNameIcons[name] ||
- fileExtensionIcons[name ? name.split('.').pop() : ''] ||
- '';
+ return fileNameIcons[name] || fileExtensionIcons[name ? name.split('.').pop() : ''] || '';
}
diff --git a/app/assets/javascripts/vue_shared/components/file_row.vue b/app/assets/javascripts/vue_shared/components/file_row.vue
index 6f7bdbc2c4d..9e713673678 100644
--- a/app/assets/javascripts/vue_shared/components/file_row.vue
+++ b/app/assets/javascripts/vue_shared/components/file_row.vue
@@ -1,12 +1,14 @@
<script>
import Icon from '~/vue_shared/components/icon.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
+import ChangedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
export default {
name: 'FileRow',
components: {
FileIcon,
Icon,
+ ChangedFileIcon,
},
props: {
file: {
@@ -22,10 +24,31 @@ export default {
required: false,
default: null,
},
+ hideExtraOnTree: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ showChangedIcon: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ displayTextKey: {
+ type: String,
+ required: false,
+ default: 'name',
+ },
+ shouldTruncateStart: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
mouseOver: false,
+ truncateStart: 0,
};
},
computed: {
@@ -48,6 +71,15 @@ export default {
'is-open': this.file.opened,
};
},
+ outputText() {
+ const text = this.file[this.displayTextKey];
+
+ if (this.truncateStart === 0) {
+ return text;
+ }
+
+ return `...${text.substring(this.truncateStart, text.length)}`;
+ },
},
watch: {
'file.active': function fileActiveWatch(active) {
@@ -60,11 +92,23 @@ export default {
if (this.hasPathAtCurrentRoute()) {
this.scrollIntoView(true);
}
+
+ if (this.shouldTruncateStart) {
+ const { scrollWidth, offsetWidth } = this.$refs.textOutput;
+ const textOverflow = scrollWidth - offsetWidth;
+
+ if (textOverflow > 0) {
+ this.truncateStart = Math.ceil(textOverflow / 5) + 3;
+ }
+ }
},
methods: {
toggleTreeOpen(path) {
this.$emit('toggleTreeOpen', path);
},
+ clickedFile(path) {
+ this.$emit('clickFile', path);
+ },
clickFile() {
// Manual Action if a tree is selected/opened
if (this.isTree && this.hasUrlAtCurrentRoute()) {
@@ -72,6 +116,8 @@ export default {
}
if (this.$router) this.$router.push(`/project${this.file.url}`);
+
+ if (this.isBlob) this.clickedFile(this.file.path);
},
scrollIntoView(isInit = false) {
const block = isInit && this.isTree ? 'center' : 'nearest';
@@ -115,28 +161,25 @@ export default {
class="file-row"
role="button"
@click="clickFile"
- @mouseover="toggleHover(true)"
- @mouseout="toggleHover(false)"
+ @mouseover="toggleHover(true);"
+ @mouseout="toggleHover(false);"
>
- <div
- class="file-row-name-container"
- >
- <span
- :style="levelIndentation"
- class="file-row-name str-truncated"
- >
+ <div class="file-row-name-container">
+ <span ref="textOutput" :style="levelIndentation" class="file-row-name str-truncated">
<file-icon
+ v-if="!showChangedIcon || file.type === 'tree'"
:file-name="file.name"
:loading="file.loading"
:folder="isTree"
:opened="file.opened"
:size="16"
/>
- {{ file.name }}
+ <changed-file-icon v-else :file="file" :size="16" class="append-right-5" />
+ {{ outputText }}
</span>
<component
- v-if="extraComponent"
:is="extraComponent"
+ v-if="extraComponent && !(hideExtraOnTree && file.type === 'tree')"
:file="file"
:mouse-over="mouseOver"
/>
@@ -148,8 +191,13 @@ export default {
:key="childFile.key"
:file="childFile"
:level="level + 1"
+ :hide-extra-on-tree="hideExtraOnTree"
:extra-component="extraComponent"
+ :show-changed-icon="showChangedIcon"
+ :display-text-key="displayTextKey"
+ :should-truncate-start="shouldTruncateStart"
@toggleTreeOpen="toggleTreeOpen"
+ @clickFile="clickedFile"
/>
</template>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue b/app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue
new file mode 100644
index 00000000000..834c39a5ee0
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue
@@ -0,0 +1,122 @@
+<script>
+import $ from 'jquery';
+import Icon from '~/vue_shared/components/icon.vue';
+/**
+ * Renders a split dropdown with
+ * an input that allows to search through the given
+ * array of options.
+ */
+export default {
+ name: 'FilteredSearchDropdown',
+ components: {
+ Icon,
+ },
+ props: {
+ title: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ buttonType: {
+ required: false,
+ validator: value =>
+ ['primary', 'default', 'secondary', 'success', 'info', 'warning', 'danger'].indexOf(
+ value,
+ ) !== -1,
+ default: 'default',
+ },
+ size: {
+ required: false,
+ type: String,
+ default: 'sm',
+ },
+ items: {
+ type: Array,
+ required: true,
+ },
+ visibleItems: {
+ type: Number,
+ required: false,
+ default: 5,
+ },
+ filterKey: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ filter: '',
+ };
+ },
+ computed: {
+ className() {
+ return `btn btn-${this.buttonType} btn-${this.size}`;
+ },
+ filteredResults() {
+ if (this.filter !== '') {
+ return this.items.filter(
+ item =>
+ item[this.filterKey] &&
+ item[this.filterKey].toLowerCase().includes(this.filter.toLowerCase()),
+ );
+ }
+
+ return this.items.slice(0, this.visibleItems);
+ },
+ },
+ mounted() {
+ /**
+ * Resets the filter every time the user closes the dropdown
+ */
+ $(this.$el)
+ .on('shown.bs.dropdown', () => {
+ this.$nextTick(() => this.$refs.searchInput.focus());
+ })
+ .on('hidden.bs.dropdown', () => {
+ this.filter = '';
+ });
+ },
+};
+</script>
+<template>
+ <div class="dropdown">
+ <div class="btn-group">
+ <slot name="mainAction" :class-name="className">
+ <button type="button" :class="className">{{ title }}</button>
+ </slot>
+
+ <button
+ type="button"
+ :class="className"
+ class="dropdown-toggle dropdown-toggle-split"
+ data-toggle="dropdown"
+ aria-haspopup="true"
+ aria-expanded="false"
+ aria-label="Expand dropdown"
+ >
+ <icon name="angle-down" :size="12" />
+ </button>
+ <div class="dropdown-menu dropdown-menu-right">
+ <div class="dropdown-input">
+ <input
+ ref="searchInput"
+ v-model="filter"
+ type="search"
+ placeholder="Filter"
+ class="js-filtered-dropdown-input dropdown-input-field"
+ />
+ <icon class="dropdown-input-search" name="search" />
+ </div>
+
+ <div class="dropdown-content">
+ <ul>
+ <li v-for="(result, i) in filteredResults" :key="i" class="js-filtered-dropdown-result">
+ <slot name="result" :result="result"> {{ result[filterKey] }} </slot>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/gl_countdown.vue b/app/assets/javascripts/vue_shared/components/gl_countdown.vue
new file mode 100644
index 00000000000..c1aace31fb2
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/gl_countdown.vue
@@ -0,0 +1,47 @@
+<script>
+import { calculateRemainingMilliseconds, formatTime } from '~/lib/utils/datetime_utility';
+import { GlTooltipDirective } from '@gitlab/ui';
+
+/**
+ * Counts down to a given end date.
+ */
+export default {
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ endDateString: {
+ type: String,
+ required: true,
+ validator(value) {
+ return !Number.isNaN(new Date(value).getTime());
+ },
+ },
+ },
+
+ data() {
+ return {
+ remainingTime: formatTime(0),
+ countdownUpdateIntervalId: null,
+ };
+ },
+
+ mounted() {
+ const updateRemainingTime = () => {
+ const remainingMilliseconds = calculateRemainingMilliseconds(this.endDateString);
+ this.remainingTime = formatTime(remainingMilliseconds);
+ };
+
+ updateRemainingTime();
+ this.countdownUpdateIntervalId = window.setInterval(updateRemainingTime, 1000);
+ },
+
+ beforeDestroy() {
+ window.clearInterval(this.countdownUpdateIntervalId);
+ },
+};
+</script>
+
+<template>
+ <time v-gl-tooltip :datetime="endDateString" :title="endDateString"> {{ remainingTime }} </time>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/gl_modal.vue b/app/assets/javascripts/vue_shared/components/gl_modal.vue
index b023c5cfeb1..faf4181bbaf 100644
--- a/app/assets/javascripts/vue_shared/components/gl_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/gl_modal.vue
@@ -41,10 +41,14 @@ export default {
},
},
mounted() {
- $(this.$el).on('shown.bs.modal', this.opened).on('hidden.bs.modal', this.closed);
+ $(this.$el)
+ .on('shown.bs.modal', this.opened)
+ .on('hidden.bs.modal', this.closed);
},
beforeDestroy() {
- $(this.$el).off('shown.bs.modal', this.opened).off('hidden.bs.modal', this.closed);
+ $(this.$el)
+ .off('shown.bs.modal', this.opened)
+ .off('hidden.bs.modal', this.closed);
},
methods: {
emitCancel(event) {
@@ -64,57 +68,44 @@ export default {
</script>
<template>
- <div
- :id="id"
- class="modal fade"
- tabindex="-1"
- role="dialog"
- >
- <div
- :class="modalSizeClass"
- class="modal-dialog"
- role="document"
- >
+ <div :id="id" class="modal fade" tabindex="-1" role="dialog">
+ <div :class="modalSizeClass" class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<slot name="header">
<h4 class="modal-title">
- <slot name="title">
- {{ headerTitleText }}
- </slot>
+ <slot name="title"> {{ headerTitleText }} </slot>
</h4>
<button
:aria-label="s__('Modal|Close')"
type="button"
class="close js-modal-close-action"
data-dismiss="modal"
- @click="emitCancel($event)"
+ @click="emitCancel($event);"
>
<span aria-hidden="true">&times;</span>
</button>
</slot>
</div>
- <div class="modal-body">
- <slot></slot>
- </div>
+ <div class="modal-body"><slot></slot></div>
<div class="modal-footer">
<slot name="footer">
<button
type="button"
- class="btn js-modal-cancel-action"
+ class="btn js-modal-cancel-action qa-modal-cancel-button"
data-dismiss="modal"
- @click="emitCancel($event)"
+ @click="emitCancel($event);"
>
{{ s__('Modal|Cancel') }}
</button>
<button
:class="`btn-${footerPrimaryButtonVariant}`"
type="button"
- class="btn js-modal-primary-action"
+ class="btn js-modal-primary-action qa-modal-primary-button"
data-dismiss="modal"
- @click="emitSubmit($event)"
+ @click="emitSubmit($event);"
>
{{ footerPrimaryButtonText }}
</button>
diff --git a/app/assets/javascripts/vue_shared/components/header_ci_component.vue b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
index 18f5ce53bb1..c830f5b49b6 100644
--- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue
+++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
@@ -1,8 +1,9 @@
<script>
+import { GlTooltipDirective, GlLink, GlButton } from '@gitlab/ui';
import CiIconBadge from './ci_badge_link.vue';
import TimeagoTooltip from './time_ago_tooltip.vue';
-import tooltip from '../directives/tooltip';
import UserAvatarImage from './user_avatar/user_avatar_image.vue';
+import LoadingButton from '~/vue_shared/components/loading_button.vue';
/**
* Renders header component for job and pipeline page based on UI mockups
@@ -16,9 +17,12 @@ export default {
CiIconBadge,
TimeagoTooltip,
UserAvatarImage,
+ GlLink,
+ GlButton,
+ LoadingButton,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
status: {
@@ -69,6 +73,9 @@ export default {
onClickAction(action) {
this.$emit('actionClicked', action);
},
+ onClickSidebarButton() {
+ this.$emit('clickedSidebarButton');
+ },
},
};
</script>
@@ -76,12 +83,9 @@ export default {
<template>
<header class="page-content-header ci-header-container">
<section class="header-main-content">
-
<ci-icon-badge :status="status" />
- <strong>
- {{ itemName }} #{{ itemId }}
- </strong>
+ <strong> {{ itemName }} #{{ itemId }} </strong>
<template v-if="shouldRenderTriggeredLabel">
triggered
@@ -95,13 +99,12 @@ export default {
by
<template v-if="user">
- <a
- v-tooltip
+ <gl-link
+ v-gl-tooltip
:href="user.path"
:title="user.email"
class="js-user-link commit-committer-link"
>
-
<user-avatar-image
:img-src="user.avatar_url"
:img-alt="userAvatarAltText"
@@ -110,72 +113,53 @@ export default {
/>
{{ user.name }}
- </a>
- <span
- v-if="user.status_tooltip_html"
- v-html="user.status_tooltip_html"></span>
+ </gl-link>
+ <span v-if="user.status_tooltip_html" v-html="user.status_tooltip_html"></span>
</template>
</section>
- <section
- v-if="actions.length"
- class="header-action-buttons"
- >
- <template
- v-for="(action, i) in actions"
- >
- <a
+ <section v-if="actions.length" class="header-action-buttons">
+ <template v-for="(action, i) in actions">
+ <gl-link
v-if="action.type === 'link'"
+ :key="i"
:href="action.path"
:class="action.cssClass"
- :key="i"
>
{{ action.label }}
- </a>
+ </gl-link>
- <a
+ <gl-link
v-else-if="action.type === 'ujs-link'"
+ :key="i"
:href="action.path"
:class="action.cssClass"
- :key="i"
data-method="post"
rel="nofollow"
>
{{ action.label }}
- </a>
+ </gl-link>
- <button
+ <loading-button
v-else-if="action.type === 'button'"
+ :key="i"
+ :loading="action.isLoading"
:disabled="action.isLoading"
:class="action.cssClass"
- :key="i"
- type="button"
- @click="onClickAction(action)"
- >
- {{ action.label }}
- <i
- v-show="action.isLoading"
- class="fa fa-spin fa-spinner"
- aria-hidden="true"
- >
- </i>
- </button>
+ container-class="d-inline"
+ :label="action.label"
+ @click="onClickAction(action);"
+ />
</template>
- <button
- v-if="hasSidebarButton"
- id="toggleSidebar"
- type="button"
- class="btn btn-default d-block d-sm-none d-md-none
-sidebar-toggle-btn js-sidebar-build-toggle js-sidebar-build-toggle-header"
- aria-label="Toggle Sidebar"
- >
- <i
- class="fa fa-angle-double-left"
- aria-hidden="true"
- aria-labelledby="toggleSidebar"
- >
- </i>
- </button>
</section>
+ <gl-button
+ v-if="hasSidebarButton"
+ id="toggleSidebar"
+ class="d-block d-sm-none
+sidebar-toggle-btn js-sidebar-build-toggle js-sidebar-build-toggle-header"
+ @click="onClickSidebarButton"
+ >
+ <i class="fa fa-angle-double-left" aria-hidden="true" aria-labelledby="toggleSidebar"> </i>
+ </gl-button>
</header>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/help_popover.vue b/app/assets/javascripts/vue_shared/components/help_popover.vue
index 540df392e4e..a57fa09f753 100644
--- a/app/assets/javascripts/vue_shared/components/help_popover.vue
+++ b/app/assets/javascripts/vue_shared/components/help_popover.vue
@@ -43,11 +43,7 @@ export default {
};
</script>
<template>
- <button
- type="button"
- class="btn btn-blank btn-transparent btn-help"
- tabindex="0"
- >
+ <button type="button" class="btn btn-blank btn-transparent btn-help" tabindex="0">
<icon name="question" />
</button>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/icon.vue b/app/assets/javascripts/vue_shared/components/icon.vue
index 5e0e7315e99..41c4c861566 100644
--- a/app/assets/javascripts/vue_shared/components/icon.vue
+++ b/app/assets/javascripts/vue_shared/components/icon.vue
@@ -1,7 +1,6 @@
<script>
-
// only allow classes in images.scss e.g. s12
-const validSizes = [8, 10, 12, 16, 18, 24, 32, 48, 72];
+const validSizes = [8, 10, 12, 14, 16, 18, 24, 32, 48, 72];
let iconValidator = () => true;
/*
@@ -9,7 +8,7 @@ let iconValidator = () => true;
*/
if (process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line global-require
- const data = require('@gitlab-org/gitlab-svgs/dist/icons.json');
+ const data = require('@gitlab/svgs/dist/icons.json');
const { icons } = data;
iconValidator = value => {
if (icons.includes(value)) {
@@ -105,7 +104,8 @@ export default {
:x="x"
:y="y"
:tabindex="tabIndex"
+ aria-hidden="true"
>
- <use v-bind="{ 'xlink:href':spriteHref }"/>
+ <use v-bind="{ 'xlink:href': spriteHref }" />
</svg>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/identicon.vue b/app/assets/javascripts/vue_shared/components/identicon.vue
index 0862f2c0cff..d42f0d8192c 100644
--- a/app/assets/javascripts/vue_shared/components/identicon.vue
+++ b/app/assets/javascripts/vue_shared/components/identicon.vue
@@ -29,9 +29,7 @@ export default {
</script>
<template>
- <div
- :class="[sizeClass, identiconBackgroundClass]"
- class="avatar identicon">
+ <div :class="[sizeClass, identiconBackgroundClass]" class="avatar identicon">
{{ identiconTitle }}
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/issue/issue_warning.vue b/app/assets/javascripts/vue_shared/components/issue/issue_warning.vue
index ca8ce554588..e92babc499b 100644
--- a/app/assets/javascripts/vue_shared/components/issue/issue_warning.vue
+++ b/app/assets/javascripts/vue_shared/components/issue/issue_warning.vue
@@ -1,49 +1,45 @@
<script>
- import icon from '../../../vue_shared/components/icon.vue';
+import icon from '../../../vue_shared/components/icon.vue';
- export default {
- components: {
- icon,
+export default {
+ components: {
+ icon,
+ },
+ props: {
+ isLocked: {
+ type: Boolean,
+ default: false,
+ required: false,
},
- props: {
- isLocked: {
- type: Boolean,
- default: false,
- required: false,
- },
- isConfidential: {
- type: Boolean,
- default: false,
- required: false,
- },
+ isConfidential: {
+ type: Boolean,
+ default: false,
+ required: false,
},
- computed: {
- warningIcon() {
- if (this.isConfidential) return 'eye-slash';
- if (this.isLocked) return 'lock';
+ },
+ computed: {
+ warningIcon() {
+ if (this.isConfidential) return 'eye-slash';
+ if (this.isLocked) return 'lock';
- return '';
- },
- isLockedAndConfidential() {
- return this.isConfidential && this.isLocked;
- },
+ return '';
},
- };
+ isLockedAndConfidential() {
+ return this.isConfidential && this.isLocked;
+ },
+ },
+};
</script>
<template>
<div class="issuable-note-warning">
- <icon
- v-if="!isLockedAndConfidential"
- :name="warningIcon"
- :size="16"
- class="icon inline"
- aria-hidden="true"
- />
+ <icon v-if="!isLockedAndConfidential" :name="warningIcon" :size="16" class="icon inline" />
<span v-if="isLockedAndConfidential">
{{ __('This issue is confidential and locked.') }}
- {{ __(`People without permission will never
-get a notification and won't be able to comment.`) }}
+ {{
+ __(`People without permission will never
+get a notification and won't be able to comment.`)
+ }}
</span>
<span v-else-if="isConfidential">
@@ -52,8 +48,7 @@ get a notification and won't be able to comment.`) }}
</span>
<span v-else-if="isLocked">
- {{ __('This issue is locked.') }}
- {{ __('Only project members can comment.') }}
+ {{ __('This issue is locked.') }} {{ __('Only project members can comment.') }}
</span>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/loading_button.vue b/app/assets/javascripts/vue_shared/components/loading_button.vue
index 4cbd3e6429d..7a53d053eec 100644
--- a/app/assets/javascripts/vue_shared/components/loading_button.vue
+++ b/app/assets/javascripts/vue_shared/components/loading_button.vue
@@ -1,6 +1,7 @@
<script>
- /* eslint-disable vue/require-default-prop */
- /* This is a re-usable vue component for rendering a button
+import { GlLoadingIcon } from '@gitlab/ui';
+/* eslint-disable vue/require-default-prop */
+/* This is a re-usable vue component for rendering a button
that will probably be sending off ajax requests and need
to show the loading status by setting the `loading` option.
This can also be used for initial page load when you don't
@@ -17,61 +18,54 @@
*/
- export default {
- props: {
- loading: {
- type: Boolean,
- required: false,
- default: false,
- },
- disabled: {
- type: Boolean,
- required: false,
- default: false,
- },
- label: {
- type: String,
- required: false,
- },
- containerClass: {
- type: [String, Array, Object],
- required: false,
- default: 'btn btn-align-content',
- },
+export default {
+ components: {
+ GlLoadingIcon,
+ },
+ props: {
+ loading: {
+ type: Boolean,
+ required: false,
+ default: false,
},
- methods: {
- onClick(e) {
- this.$emit('click', e);
- },
+ disabled: {
+ type: Boolean,
+ required: false,
+ default: false,
},
- };
+ label: {
+ type: String,
+ required: false,
+ },
+ containerClass: {
+ type: [String, Array, Object],
+ required: false,
+ default: 'btn btn-align-content',
+ },
+ },
+ methods: {
+ onClick(e) {
+ this.$emit('click', e);
+ },
+ },
+};
</script>
<template>
- <button
- :class="containerClass"
- :disabled="loading || disabled"
- type="button"
- @click="onClick"
- >
+ <button :class="containerClass" :disabled="loading || disabled" type="button" @click="onClick">
<transition name="fade">
<gl-loading-icon
v-if="loading"
:inline="true"
:class="{
- 'append-right-5': label
+ 'append-right-5': label,
}"
class="js-loading-button-icon"
/>
</transition>
<transition name="fade">
<slot>
- <span
- v-if="label"
- class="js-loading-button-label"
- >
- {{ label }}
- </span>
+ <span v-if="label" class="js-loading-button-label"> {{ label }} </span>
</slot>
</transition>
</button>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/field.vue b/app/assets/javascripts/vue_shared/components/markdown/field.vue
index d62537021ca..21d6519191f 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/field.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/field.vue
@@ -1,167 +1,159 @@
<script>
- import $ from 'jquery';
- import { s__ } from '~/locale';
- import Flash from '../../../flash';
- import GLForm from '../../../gl_form';
- import markdownHeader from './header.vue';
- import markdownToolbar from './toolbar.vue';
- import icon from '../icon.vue';
+import $ from 'jquery';
+import { s__ } from '~/locale';
+import Flash from '../../../flash';
+import GLForm from '../../../gl_form';
+import markdownHeader from './header.vue';
+import markdownToolbar from './toolbar.vue';
+import icon from '../icon.vue';
- export default {
- components: {
- markdownHeader,
- markdownToolbar,
- icon,
+export default {
+ components: {
+ markdownHeader,
+ markdownToolbar,
+ icon,
+ },
+ props: {
+ markdownPreviewPath: {
+ type: String,
+ required: false,
+ default: '',
},
- props: {
- markdownPreviewPath: {
- type: String,
- required: false,
- default: '',
- },
- markdownDocsPath: {
- type: String,
- required: true,
- },
- markdownVersion: {
- type: Number,
- required: false,
- default: 0,
- },
- addSpacingClasses: {
- type: Boolean,
- required: false,
- default: true,
- },
- quickActionsDocsPath: {
- type: String,
- required: false,
- default: '',
- },
- canAttachFile: {
- type: Boolean,
- required: false,
- default: true,
- },
- enableAutocomplete: {
- type: Boolean,
- required: false,
- default: true,
- },
+ markdownDocsPath: {
+ type: String,
+ required: true,
},
- data() {
- return {
- markdownPreview: '',
- referencedCommands: '',
- referencedUsers: '',
- markdownPreviewLoading: false,
- previewMarkdown: false,
- };
+ markdownVersion: {
+ type: Number,
+ required: false,
+ default: 0,
},
- computed: {
- shouldShowReferencedUsers() {
- const referencedUsersThreshold = 10;
- return this.referencedUsers.length >= referencedUsersThreshold;
- },
+ addSpacingClasses: {
+ type: Boolean,
+ required: false,
+ default: true,
},
- mounted() {
- /*
- GLForm class handles all the toolbar buttons
- */
- return new GLForm($(this.$refs['gl-form']), {
- emojis: this.enableAutocomplete,
- members: this.enableAutocomplete,
- issues: this.enableAutocomplete,
- mergeRequests: this.enableAutocomplete,
- epics: this.enableAutocomplete,
- milestones: this.enableAutocomplete,
- labels: this.enableAutocomplete,
- });
+ quickActionsDocsPath: {
+ type: String,
+ required: false,
+ default: '',
},
- beforeDestroy() {
- const glForm = $(this.$refs['gl-form']).data('glForm');
- if (glForm) {
- glForm.destroy();
- }
+ canAttachFile: {
+ type: Boolean,
+ required: false,
+ default: true,
},
- methods: {
- showPreviewTab() {
- if (this.previewMarkdown) return;
+ enableAutocomplete: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+ data() {
+ return {
+ markdownPreview: '',
+ referencedCommands: '',
+ referencedUsers: '',
+ markdownPreviewLoading: false,
+ previewMarkdown: false,
+ };
+ },
+ computed: {
+ shouldShowReferencedUsers() {
+ const referencedUsersThreshold = 10;
+ return this.referencedUsers.length >= referencedUsersThreshold;
+ },
+ },
+ mounted() {
+ /*
+ GLForm class handles all the toolbar buttons
+ */
+ return new GLForm($(this.$refs['gl-form']), {
+ emojis: this.enableAutocomplete,
+ members: this.enableAutocomplete,
+ issues: this.enableAutocomplete,
+ mergeRequests: this.enableAutocomplete,
+ epics: this.enableAutocomplete,
+ milestones: this.enableAutocomplete,
+ labels: this.enableAutocomplete,
+ snippets: this.enableAutocomplete,
+ });
+ },
+ beforeDestroy() {
+ const glForm = $(this.$refs['gl-form']).data('glForm');
+ if (glForm) {
+ glForm.destroy();
+ }
+ },
+ methods: {
+ showPreviewTab() {
+ if (this.previewMarkdown) return;
- this.previewMarkdown = true;
+ this.previewMarkdown = true;
- /*
+ /*
Can't use `$refs` as the component is technically in the parent component
so we access the VNode & then get the element
*/
- const text = this.$slots.textarea[0].elm.value;
+ const text = this.$slots.textarea[0].elm.value;
- if (text) {
- this.markdownPreviewLoading = true;
- this.$http
- .post(this.versionedPreviewPath(), { text })
- .then(resp => resp.json())
- .then(data => this.renderMarkdown(data))
- .catch(() => new Flash(s__('Error loading markdown preview')));
- } else {
- this.renderMarkdown();
- }
- },
+ if (text) {
+ this.markdownPreviewLoading = true;
+ this.$http
+ .post(this.versionedPreviewPath(), { text })
+ .then(resp => resp.json())
+ .then(data => this.renderMarkdown(data))
+ .catch(() => new Flash(s__('Error loading markdown preview')));
+ } else {
+ this.renderMarkdown();
+ }
+ },
- showWriteTab() {
- this.markdownPreview = '';
- this.previewMarkdown = false;
- },
+ showWriteTab() {
+ this.markdownPreview = '';
+ this.previewMarkdown = false;
+ },
- renderMarkdown(data = {}) {
- this.markdownPreviewLoading = false;
- this.markdownPreview = data.body || 'Nothing to preview.';
+ renderMarkdown(data = {}) {
+ this.markdownPreviewLoading = false;
+ this.markdownPreview = data.body || 'Nothing to preview.';
- if (data.references) {
- this.referencedCommands = data.references.commands;
- this.referencedUsers = data.references.users;
- }
+ if (data.references) {
+ this.referencedCommands = data.references.commands;
+ this.referencedUsers = data.references.users;
+ }
- this.$nextTick(() => {
- $(this.$refs['markdown-preview']).renderGFM();
- });
- },
+ this.$nextTick(() => {
+ $(this.$refs['markdown-preview']).renderGFM();
+ });
+ },
- versionedPreviewPath() {
- const { markdownPreviewPath, markdownVersion } = this;
- return `${markdownPreviewPath}${
- markdownPreviewPath.indexOf('?') === -1 ? '?' : '&'
- }markdown_version=${markdownVersion}`;
- },
+ versionedPreviewPath() {
+ const { markdownPreviewPath, markdownVersion } = this;
+ return `${markdownPreviewPath}${
+ markdownPreviewPath.indexOf('?') === -1 ? '?' : '&'
+ }markdown_version=${markdownVersion}`;
},
- };
+ },
+};
</script>
<template>
<div
ref="gl-form"
:class="{ 'prepend-top-default append-bottom-default': addSpacingClasses }"
- class="md-area js-vue-markdown-field">
+ class="md-area js-vue-markdown-field"
+ >
<markdown-header
:preview-markdown="previewMarkdown"
@preview-markdown="showPreviewTab"
@write-markdown="showWriteTab"
/>
- <div
- v-show="!previewMarkdown"
- class="md-write-holder"
- >
+ <div v-show="!previewMarkdown" class="md-write-holder">
<div class="zen-backdrop">
<slot name="textarea"></slot>
- <a
- class="zen-control zen-control-leave js-zen-leave"
- href="#"
- aria-label="Enter zen mode"
- >
- <icon
- :size="32"
- name="screen-normal"
- />
+ <a class="zen-control zen-control-leave js-zen-leave" href="#" aria-label="Enter zen mode">
+ <icon :size="32" name="screen-normal" />
</a>
<markdown-toolbar
:markdown-docs-path="markdownDocsPath"
@@ -170,42 +162,19 @@
/>
</div>
</div>
- <div
- v-show="previewMarkdown"
- class="md md-preview-holder md-preview js-vue-md-preview"
- >
- <div
- ref="markdown-preview"
- v-html="markdownPreview"
- >
- </div>
- <span v-if="markdownPreviewLoading">
- Loading...
- </span>
+ <div v-show="previewMarkdown" class="md md-preview-holder md-preview js-vue-md-preview">
+ <div ref="markdown-preview" v-html="markdownPreview"></div>
+ <span v-if="markdownPreviewLoading"> Loading... </span>
</div>
<template v-if="previewMarkdown && !markdownPreviewLoading">
- <div
- v-if="referencedCommands"
- class="referenced-commands"
- v-html="referencedCommands"
- >
- </div>
- <div
- v-if="shouldShowReferencedUsers"
- class="referenced-users"
- >
+ <div v-if="referencedCommands" class="referenced-commands" v-html="referencedCommands"></div>
+ <div v-if="shouldShowReferencedUsers" class="referenced-users">
<span>
- <i
- class="fa fa-exclamation-triangle"
- aria-hidden="true"
- >
- </i>
- You are about to add
+ <i class="fa fa-exclamation-triangle" aria-hidden="true"> </i> You are about to add
<strong>
- <span class="js-referenced-users-count">
- {{ referencedUsers.length }}
- </span>
- </strong> people to the discussion. Proceed with caution.
+ <span class="js-referenced-users-count"> {{ referencedUsers.length }} </span>
+ </strong>
+ people to the discussion. Proceed with caution.
</span>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/header.vue b/app/assets/javascripts/vue_shared/components/markdown/header.vue
index 8c22f3f6536..4c4ba537065 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/header.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/header.vue
@@ -1,109 +1,99 @@
<script>
- import $ from 'jquery';
- import tooltip from '../../directives/tooltip';
- import toolbarButton from './toolbar_button.vue';
- import icon from '../icon.vue';
+import $ from 'jquery';
+import { GlTooltipDirective } from '@gitlab/ui';
+import ToolbarButton from './toolbar_button.vue';
+import Icon from '../icon.vue';
- export default {
- directives: {
- tooltip,
+export default {
+ components: {
+ ToolbarButton,
+ Icon,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ previewMarkdown: {
+ type: Boolean,
+ required: true,
},
- components: {
- toolbarButton,
- icon,
+ },
+ computed: {
+ mdTable() {
+ return [
+ '| header | header |',
+ '| ------ | ------ |',
+ '| cell | cell |',
+ '| cell | cell |',
+ ].join('\n');
},
- props: {
- previewMarkdown: {
- type: Boolean,
- required: true,
- },
+ },
+ mounted() {
+ $(document).on('markdown-preview:show.vue', this.previewMarkdownTab);
+ $(document).on('markdown-preview:hide.vue', this.writeMarkdownTab);
+ },
+ beforeDestroy() {
+ $(document).off('markdown-preview:show.vue', this.previewMarkdownTab);
+ $(document).off('markdown-preview:hide.vue', this.writeMarkdownTab);
+ },
+ methods: {
+ isValid(form) {
+ return (
+ !form ||
+ (form.find('.js-vue-markdown-field').length && $(this.$el).closest('form')[0] === form[0])
+ );
},
- mounted() {
- $(document).on('markdown-preview:show.vue', this.previewMarkdownTab);
- $(document).on('markdown-preview:hide.vue', this.writeMarkdownTab);
- },
- beforeDestroy() {
- $(document).off('markdown-preview:show.vue', this.previewMarkdownTab);
- $(document).off('markdown-preview:hide.vue', this.writeMarkdownTab);
- },
- methods: {
- isValid(form) {
- return !form ||
- form.find('.js-vue-markdown-field').length &&
- $(this.$el).closest('form')[0] === form[0];
- },
- previewMarkdownTab(event, form) {
- if (event.target.blur) event.target.blur();
- if (!this.isValid(form)) return;
+ previewMarkdownTab(event, form) {
+ if (event.target.blur) event.target.blur();
+ if (!this.isValid(form)) return;
- this.$emit('preview-markdown');
- },
+ this.$emit('preview-markdown');
+ },
- writeMarkdownTab(event, form) {
- if (event.target.blur) event.target.blur();
- if (!this.isValid(form)) return;
+ writeMarkdownTab(event, form) {
+ if (event.target.blur) event.target.blur();
+ if (!this.isValid(form)) return;
- this.$emit('write-markdown');
- },
+ this.$emit('write-markdown');
},
- };
+ },
+};
</script>
<template>
<div class="md-header">
<ul class="nav-links clearfix">
- <li
- :class="{ active: !previewMarkdown }"
- class="md-header-tab"
- >
- <a
+ <li :class="{ active: !previewMarkdown }" class="md-header-tab">
+ <button
class="js-write-link"
- href="#md-write-holder"
tabindex="-1"
- @click.prevent="writeMarkdownTab($event)"
+ type="button"
+ @click="writeMarkdownTab($event);"
>
Write
- </a>
+ </button>
</li>
- <li
- :class="{ active: previewMarkdown }"
- class="md-header-tab"
- >
- <a
+ <li :class="{ active: previewMarkdown }" class="md-header-tab">
+ <button
class="js-preview-link js-md-preview-button"
- href="#md-preview-holder"
tabindex="-1"
- @click.prevent="previewMarkdownTab($event)"
+ type="button"
+ @click="previewMarkdownTab($event);"
>
Preview
- </a>
+ </button>
</li>
- <li
- :class="{ active: !previewMarkdown }"
- class="md-header-toolbar"
- >
+ <li :class="{ active: !previewMarkdown }" class="md-header-toolbar">
+ <toolbar-button tag="**" button-title="Add bold text" icon="bold" />
+ <toolbar-button tag="*" button-title="Add italic text" icon="italic" />
+ <toolbar-button :prepend="true" tag="> " button-title="Insert a quote" icon="quote" />
+ <toolbar-button tag="`" tag-block="```" button-title="Insert code" icon="code" />
<toolbar-button
- tag="**"
- button-title="Add bold text"
- icon="bold"
- />
- <toolbar-button
- tag="*"
- button-title="Add italic text"
- icon="italic"
- />
- <toolbar-button
- :prepend="true"
- tag="> "
- button-title="Insert a quote"
- icon="quote"
- />
- <toolbar-button
- tag="`"
- tag-block="```"
- button-title="Insert code"
- icon="code"
+ tag="[{text}](url)"
+ tag-select="url"
+ button-title="Add a link"
+ icon="link"
/>
<toolbar-button
:prepend="true"
@@ -123,8 +113,14 @@
button-title="Add a task list"
icon="task-done"
/>
+ <toolbar-button
+ :tag="mdTable"
+ :prepend="true"
+ :button-title="__('Add a table')"
+ icon="table"
+ />
<button
- v-tooltip
+ v-gl-tooltip
aria-label="Go full screen"
class="toolbar-btn toolbar-fullscreen-btn js-zen-enter"
data-container="body"
@@ -132,9 +128,7 @@
title="Go full screen"
type="button"
>
- <icon
- name="screen-full"
- />
+ <icon name="screen-full" />
</button>
</li>
</ul>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
index d63318f3da6..3b57b5e8da4 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
@@ -1,119 +1,71 @@
<script>
- export default {
- props: {
- markdownDocsPath: {
- type: String,
- required: true,
- },
- quickActionsDocsPath: {
- type: String,
- required: false,
- default: '',
- },
- canAttachFile: {
- type: Boolean,
- required: false,
- default: true,
- },
+import { GlLink } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlLink,
+ },
+ props: {
+ markdownDocsPath: {
+ type: String,
+ required: true,
+ },
+ quickActionsDocsPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ canAttachFile: {
+ type: Boolean,
+ required: false,
+ default: true,
},
- computed: {
- hasQuickActionsDocsPath() {
- return this.quickActionsDocsPath !== '';
- },
+ },
+ computed: {
+ hasQuickActionsDocsPath() {
+ return this.quickActionsDocsPath !== '';
},
- };
+ },
+};
</script>
<template>
<div class="comment-toolbar clearfix">
<div class="toolbar-text">
<template v-if="!hasQuickActionsDocsPath && markdownDocsPath">
- <a
- :href="markdownDocsPath"
- target="_blank"
- tabindex="-1"
- >
+ <gl-link :href="markdownDocsPath" target="_blank" tabindex="-1">
Markdown is supported
- </a>
+ </gl-link>
</template>
<template v-if="hasQuickActionsDocsPath && markdownDocsPath">
- <a
- :href="markdownDocsPath"
- target="_blank"
- tabindex="-1"
- >
- Markdown
- </a>
+ <gl-link :href="markdownDocsPath" target="_blank" tabindex="-1"> Markdown </gl-link>
and
- <a
- :href="quickActionsDocsPath"
- target="_blank"
- tabindex="-1"
- >
+ <gl-link :href="quickActionsDocsPath" target="_blank" tabindex="-1">
quick actions
- </a>
+ </gl-link>
are supported
</template>
</div>
- <span
- v-if="canAttachFile"
- class="uploading-container"
- >
+ <span v-if="canAttachFile" class="uploading-container">
<span class="uploading-progress-container hide">
- <i
- class="fa fa-file-image-o toolbar-button-icon"
- aria-hidden="true"
- >
- </i>
- <span class="attaching-file-message"></span>
- <span class="uploading-progress">0%</span>
+ <i class="fa fa-file-image-o toolbar-button-icon" aria-hidden="true"> </i>
+ <span class="attaching-file-message"></span> <span class="uploading-progress">0%</span>
<span class="uploading-spinner">
- <i
- class="fa fa-spinner fa-spin toolbar-button-icon"
- aria-hidden="true"
- >
- </i>
+ <i class="fa fa-spinner fa-spin toolbar-button-icon" aria-hidden="true"> </i>
</span>
</span>
<span class="uploading-error-container hide">
<span class="uploading-error-icon">
- <i
- class="fa fa-file-image-o toolbar-button-icon"
- aria-hidden="true"
- >
- </i>
+ <i class="fa fa-file-image-o toolbar-button-icon" aria-hidden="true"> </i>
</span>
<span class="uploading-error-message"></span>
- <button
- class="retry-uploading-link"
- type="button"
- >
- Try again
- </button>
- or
- <button
- class="attach-new-file markdown-selector"
- type="button"
- >
- attach a new file
- </button>
+ <button class="retry-uploading-link" type="button">Try again</button> or
+ <button class="attach-new-file markdown-selector" type="button">attach a new file</button>
</span>
- <button
- class="markdown-selector button-attach-file"
- tabindex="-1"
- type="button"
- >
- <i
- class="fa fa-file-image-o toolbar-button-icon"
- aria-hidden="true"
- >
- </i>
- Attach a file
+ <button class="markdown-selector button-attach-file" tabindex="-1" type="button">
+ <i class="fa fa-file-image-o toolbar-button-icon" aria-hidden="true"> </i> Attach a file
</button>
- <button
- class="btn btn-default btn-sm hide button-cancel-uploading-files"
- type="button"
- >
+ <button class="btn btn-default btn-sm hide button-cancel-uploading-files" type="button">
Cancel
</button>
</span>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
index 9f1e009efdd..a6d2cecdf7e 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar_button.vue
@@ -1,45 +1,51 @@
<script>
- import tooltip from '../../directives/tooltip';
- import icon from '../icon.vue';
+import { GlTooltipDirective } from '@gitlab/ui';
+import Icon from '../icon.vue';
- export default {
- components: {
- icon,
+export default {
+ components: {
+ Icon,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ buttonTitle: {
+ type: String,
+ required: true,
},
- directives: {
- tooltip,
+ icon: {
+ type: String,
+ required: true,
},
- props: {
- buttonTitle: {
- type: String,
- required: true,
- },
- icon: {
- type: String,
- required: true,
- },
- tag: {
- type: String,
- required: true,
- },
- tagBlock: {
- type: String,
- required: false,
- default: '',
- },
- prepend: {
- type: Boolean,
- required: false,
- default: false,
- },
+ tag: {
+ type: String,
+ required: true,
},
- };
+ tagBlock: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ tagSelect: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ prepend: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+};
</script>
<template>
<button
- v-tooltip
+ v-gl-tooltip
:data-md-tag="tag"
+ :data-md-select="tagSelect"
:data-md-block="tagBlock"
:data-md-prepend="prepend"
:title="buttonTitle"
@@ -49,8 +55,6 @@
tabindex="-1"
data-container="body"
>
- <icon
- :name="icon"
- />
+ <icon :name="icon" />
</button>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/memory_graph.vue b/app/assets/javascripts/vue_shared/components/memory_graph.vue
index 552a92541be..16f4ff068f6 100644
--- a/app/assets/javascripts/vue_shared/components/memory_graph.vue
+++ b/app/assets/javascripts/vue_shared/components/memory_graph.vue
@@ -41,7 +41,8 @@ export default {
// Find metric timestamp which is closest to deploymentTime
timestampDiff = Math.abs(metricTimestamps[0] - median);
metricTimestamps.forEach((timestamp, index) => {
- if (index === 0) { // Skip first element
+ if (index === 0) {
+ // Skip first element
return;
}
@@ -117,17 +118,10 @@ export default {
:width="width"
:height="height"
class="has-tooltip"
- xmlns="http://www.w3.org/2000/svg">
- <path
- :d="pathD"
- :viewBox="pathViewBox"
- />
- <circle
- :cx="dotX"
- :cy="dotY"
- r="1.5"
- transform="translate(0 -1)"
- />
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <path :d="pathD" :viewBox="pathViewBox" />
+ <circle :cx="dotX" :cy="dotY" r="1.5" transform="translate(0 -1)" />
</svg>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/navigation_tabs.vue b/app/assets/javascripts/vue_shared/components/navigation_tabs.vue
index 99d61b5639d..09a64502819 100644
--- a/app/assets/javascripts/vue_shared/components/navigation_tabs.vue
+++ b/app/assets/javascripts/vue_shared/components/navigation_tabs.vue
@@ -58,19 +58,10 @@ export default {
active: tab.isActive,
}"
>
- <a
- :class="`js-${scope}-tab-${tab.scope}`"
- role="button"
- @click="onTabClick(tab)"
- >
+ <a :class="`js-${scope}-tab-${tab.scope}`" role="button" @click="onTabClick(tab);">
{{ tab.name }}
- <span
- v-if="shouldRenderBadge(tab.count)"
- class="badge badge-pill"
- >
- {{ tab.count }}
- </span>
+ <span v-if="shouldRenderBadge(tab.count)" class="badge badge-pill"> {{ tab.count }} </span>
</a>
</li>
</ul>
diff --git a/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue b/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue
index 38115f268bb..8d3a3009c55 100644
--- a/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue
@@ -1,70 +1,66 @@
<script>
- /**
- * Common component to render a placeholder note and user information.
- *
- * This component needs to be used with a vuex store.
- * That vuex store needs to have a `getUserData` getter that contains
- * {
- * path: String,
- * avatar_url: String,
- * name: String,
- * username: String,
- * }
- *
- * @example
- * <placeholder-note
- * :note="{body: 'This is a note'}"
- * />
- */
- import { mapGetters } from 'vuex';
- import userAvatarLink from '../user_avatar/user_avatar_link.vue';
+/**
+ * Common component to render a placeholder note and user information.
+ *
+ * This component needs to be used with a vuex store.
+ * That vuex store needs to have a `getUserData` getter that contains
+ * {
+ * path: String,
+ * avatar_url: String,
+ * name: String,
+ * username: String,
+ * }
+ *
+ * @example
+ * <placeholder-note
+ * :note="{body: 'This is a note'}"
+ * />
+ */
+import { mapGetters } from 'vuex';
+import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
+import userAvatarLink from '../user_avatar/user_avatar_link.vue';
- export default {
- name: 'PlaceholderNote',
- components: {
- userAvatarLink,
+export default {
+ name: 'PlaceholderNote',
+ components: {
+ userAvatarLink,
+ TimelineEntryItem,
+ },
+ props: {
+ note: {
+ type: Object,
+ required: true,
},
- props: {
- note: {
- type: Object,
- required: true,
- },
- },
- computed: {
- ...mapGetters([
- 'getUserData',
- ]),
- },
- };
+ },
+ computed: {
+ ...mapGetters(['getUserData']),
+ },
+};
</script>
<template>
- <li class="note being-posted fade-in-half timeline-entry">
- <div class="timeline-entry-inner">
- <div class="timeline-icon">
- <user-avatar-link
- :link-href="getUserData.path"
- :img-src="getUserData.avatar_url"
- :img-size="40"
- />
- </div>
- <div
- :class="{ discussion: !note.individual_note }"
- class="timeline-content">
- <div class="note-header">
- <div class="note-header-info">
- <a :href="getUserData.path">
- <span class="d-none d-sm-inline-block">{{ getUserData.name }}</span>
- <span class="note-headline-light">@{{ getUserData.username }}</span>
- </a>
- </div>
+ <timeline-entry-item class="note being-posted fade-in-half">
+ <div class="timeline-icon">
+ <user-avatar-link
+ :link-href="getUserData.path"
+ :img-src="getUserData.avatar_url"
+ :img-size="40"
+ />
+ </div>
+ <div :class="{ discussion: !note.individual_note }" class="timeline-content">
+ <div class="note-header">
+ <div class="note-header-info">
+ <a :href="getUserData.path">
+ <span class="d-none d-sm-inline-block">{{ getUserData.name }}</span>
+ <span class="note-headline-light">@{{ getUserData.username }}</span>
+ </a>
</div>
- <div class="note-body">
- <div class="note-text">
- <p>{{ note.body }}</p>
- </div>
+ </div>
+ <div class="note-body">
+ <div class="note-text">
+ <p>{{ note.body }}</p>
</div>
</div>
</div>
- </li>
+ </timeline-entry-item>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/notes/placeholder_system_note.vue b/app/assets/javascripts/vue_shared/components/notes/placeholder_system_note.vue
index 95e2b38e292..7689425eb52 100644
--- a/app/assets/javascripts/vue_shared/components/notes/placeholder_system_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/placeholder_system_note.vue
@@ -1,29 +1,32 @@
<script>
- /**
- * Common component to render a placeholder system note.
- *
- * @example
- * <placeholder-system-note
- * :note="{ body: 'Commands are being applied'}"
- * />
- */
- export default {
- name: 'PlaceholderSystemNote',
- props: {
- note: {
- type: Object,
- required: true,
- },
+import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
+
+/**
+ * Common component to render a placeholder system note.
+ *
+ * @example
+ * <placeholder-system-note
+ * :note="{ body: 'Commands are being applied'}"
+ * />
+ */
+export default {
+ name: 'PlaceholderSystemNote',
+ components: {
+ TimelineEntryItem,
+ },
+ props: {
+ note: {
+ type: Object,
+ required: true,
},
- };
+ },
+};
</script>
<template>
- <li class="note system-note timeline-entry being-posted fade-in-half">
- <div class="timeline-entry-inner">
- <div class="timeline-content">
- <em>{{ note.body }}</em>
- </div>
+ <timeline-entry-item class="note system-note being-posted fade-in-half">
+ <div class="timeline-content">
+ <em>{{ note.body }}</em>
</div>
- </li>
+ </timeline-entry-item>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue b/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue
index 2eb6c20b2c0..e61d1fd2031 100644
--- a/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue
@@ -1,25 +1,22 @@
-<template>
- <li class="timeline-entry note">
- <div class="timeline-entry-inner">
- <div class="timeline-icon">
- </div>
- <div class="timeline-content">
- <div class="note-header"></div>
- <div class="note-body">
- <skeleton-loading-container />
- </div>
- </div>
- </div>
- </li>
-</template>
-
<script>
-import skeletonLoadingContainer from '~/vue_shared/components/skeleton_loading_container.vue';
+import { GlSkeletonLoading } from '@gitlab/ui';
+import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
export default {
name: 'SkeletonNote',
components: {
- skeletonLoadingContainer,
+ GlSkeletonLoading,
+ TimelineEntryItem,
},
};
</script>
+
+<template>
+ <timeline-entry-item class="note note-wrapper">
+ <div class="timeline-icon"></div>
+ <div class="timeline-content">
+ <div class="note-header"></div>
+ <div class="note-body"><gl-skeleton-loading /></div>
+ </div>
+ </timeline-entry-item>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/notes/system_note.vue b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
index 2122d0a508e..31df26f7b05 100644
--- a/app/assets/javascripts/vue_shared/components/notes/system_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
@@ -20,6 +20,7 @@ import $ from 'jquery';
import { mapGetters } from 'vuex';
import noteHeader from '~/notes/components/note_header.vue';
import Icon from '~/vue_shared/components/icon.vue';
+import TimelineEntryItem from './timeline_entry_item.vue';
import { spriteIcon } from '../../../lib/utils/common_utils';
const MAX_VISIBLE_COMMIT_LIST_COUNT = 3;
@@ -29,6 +30,7 @@ export default {
components: {
Icon,
noteHeader,
+ TimelineEntryItem,
},
props: {
note: {
@@ -73,52 +75,34 @@ export default {
</script>
<template>
- <li
+ <timeline-entry-item
:id="noteAnchorId"
:class="{ target: isTargetNote }"
- class="note system-note timeline-entry">
- <div class="timeline-entry-inner">
- <div
- class="timeline-icon"
- v-html="iconHtml">
+ class="note system-note note-wrapper"
+ >
+ <div class="timeline-icon" v-html="iconHtml"></div>
+ <div class="timeline-content">
+ <div class="note-header">
+ <note-header :author="note.author" :created-at="note.created_at" :note-id="note.id">
+ <span v-html="actionTextHtml"></span>
+ </note-header>
</div>
- <div class="timeline-content">
- <div class="note-header">
- <note-header
- :author="note.author"
- :created-at="note.created_at"
- :note-id="note.id"
- >
- <span v-html="actionTextHtml"></span>
- </note-header>
- </div>
- <div class="note-body">
- <div
- :class="{
- 'system-note-commit-list': hasMoreCommits,
- 'hide-shade': expanded
- }"
- class="note-text"
- v-html="note.note_html"
- ></div>
- <div
- v-if="hasMoreCommits"
- class="flex-list"
- >
- <div
- class="system-note-commit-list-toggler flex-row"
- @click="expanded = !expanded"
- >
- <Icon
- :name="toggleIcon"
- :size="8"
- class="append-right-5"
- />
- <span>Toggle commit list</span>
- </div>
+ <div class="note-body">
+ <div
+ :class="{
+ 'system-note-commit-list': hasMoreCommits,
+ 'hide-shade': expanded,
+ }"
+ class="note-text"
+ v-html="note.note_html"
+ ></div>
+ <div v-if="hasMoreCommits" class="flex-list">
+ <div class="system-note-commit-list-toggler flex-row" @click="expanded = !expanded;">
+ <icon :name="toggleIcon" :size="8" class="append-right-5" />
+ <span>Toggle commit list</span>
</div>
</div>
</div>
</div>
- </li>
+ </timeline-entry-item>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/notes/timeline_entry_item.vue b/app/assets/javascripts/vue_shared/components/notes/timeline_entry_item.vue
new file mode 100644
index 00000000000..06974a12aed
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/notes/timeline_entry_item.vue
@@ -0,0 +1,11 @@
+<script>
+export default {
+ name: 'TimelineEntryItem',
+};
+</script>
+
+<template>
+ <li class="timeline-entry">
+ <div class="timeline-entry-inner"><slot></slot></div>
+ </li>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/pagination_links.vue b/app/assets/javascripts/vue_shared/components/pagination_links.vue
index 1f2a679c145..0b44f8578cb 100644
--- a/app/assets/javascripts/vue_shared/components/pagination_links.vue
+++ b/app/assets/javascripts/vue_shared/components/pagination_links.vue
@@ -1,7 +1,11 @@
<script>
+import { GlPagination } from '@gitlab/ui';
import { s__ } from '../../locale';
export default {
+ components: {
+ GlPagination,
+ },
props: {
change: {
type: Function,
diff --git a/app/assets/javascripts/vue_shared/components/panel_resizer.vue b/app/assets/javascripts/vue_shared/components/panel_resizer.vue
index 7947ae1e4da..bf736a378dd 100644
--- a/app/assets/javascripts/vue_shared/components/panel_resizer.vue
+++ b/app/assets/javascripts/vue_shared/components/panel_resizer.vue
@@ -1,90 +1,90 @@
<script>
- export default {
- props: {
- startSize: {
- type: Number,
- required: true,
- },
- side: {
- type: String,
- required: true,
- },
- minSize: {
- type: Number,
- required: false,
- default: 0,
- },
- maxSize: {
- type: Number,
- required: false,
- default: Number.MAX_VALUE,
- },
- enabled: {
- type: Boolean,
- required: false,
- default: true,
- },
+export default {
+ props: {
+ startSize: {
+ type: Number,
+ required: true,
},
- data() {
- return {
- size: this.startSize,
- };
+ side: {
+ type: String,
+ required: true,
},
- computed: {
- className() {
- return `drag-${this.side}`;
- },
- cursorStyle() {
- if (this.enabled) {
- return { cursor: 'ew-resize' };
- }
- return {};
- },
+ minSize: {
+ type: Number,
+ required: false,
+ default: 0,
},
- methods: {
- resetSize(e) {
- e.preventDefault();
- this.$emit('resize-start', this.size);
+ maxSize: {
+ type: Number,
+ required: false,
+ default: Number.MAX_VALUE,
+ },
+ enabled: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+ data() {
+ return {
+ size: this.startSize,
+ };
+ },
+ computed: {
+ className() {
+ return `drag-${this.side}`;
+ },
+ cursorStyle() {
+ if (this.enabled) {
+ return { cursor: 'ew-resize' };
+ }
+ return {};
+ },
+ },
+ methods: {
+ resetSize(e) {
+ e.preventDefault();
+ this.$emit('resize-start', this.size);
- this.size = this.startSize;
- this.$emit('update:size', this.size);
+ this.size = this.startSize;
+ this.$emit('update:size', this.size);
- // End resizing on next tick so that listeners can react to DOM changes
- this.$nextTick(() => {
- this.$emit('resize-end', this.size);
- });
- },
- startDrag(e) {
- if (this.enabled) {
- e.preventDefault();
- this.startPos = e.clientX;
- this.currentStartSize = this.size;
- document.addEventListener('mousemove', this.drag);
- document.addEventListener('mouseup', this.endDrag, { once: true });
- this.$emit('resize-start', this.size);
- }
- },
- drag(e) {
+ // End resizing on next tick so that listeners can react to DOM changes
+ this.$nextTick(() => {
+ this.$emit('resize-end', this.size);
+ });
+ },
+ startDrag(e) {
+ if (this.enabled) {
e.preventDefault();
- let moved = e.clientX - this.startPos;
- if (this.side === 'left') moved = -moved;
- let newSize = this.currentStartSize + moved;
- if (newSize < this.minSize) {
- newSize = this.minSize;
- } else if (newSize > this.maxSize) {
- newSize = this.maxSize;
- }
- this.size = newSize;
+ this.startPos = e.clientX;
+ this.currentStartSize = this.size;
+ document.addEventListener('mousemove', this.drag);
+ document.addEventListener('mouseup', this.endDrag, { once: true });
+ this.$emit('resize-start', this.size);
+ }
+ },
+ drag(e) {
+ e.preventDefault();
+ let moved = e.clientX - this.startPos;
+ if (this.side === 'left') moved = -moved;
+ let newSize = this.currentStartSize + moved;
+ if (newSize < this.minSize) {
+ newSize = this.minSize;
+ } else if (newSize > this.maxSize) {
+ newSize = this.maxSize;
+ }
+ this.size = newSize;
- this.$emit('update:size', newSize);
- },
- endDrag(e) {
- e.preventDefault();
- document.removeEventListener('mousemove', this.drag);
- this.$emit('resize-end', this.size);
- },
+ this.$emit('update:size', newSize);
+ },
+ endDrag(e) {
+ e.preventDefault();
+ document.removeEventListener('mousemove', this.drag);
+ this.$emit('resize-end', this.size);
},
- };
+ },
+};
</script>
<template>
diff --git a/app/assets/javascripts/vue_shared/components/pikaday.vue b/app/assets/javascripts/vue_shared/components/pikaday.vue
index bfeece12077..8bdb5bf22c2 100644
--- a/app/assets/javascripts/vue_shared/components/pikaday.vue
+++ b/app/assets/javascripts/vue_shared/components/pikaday.vue
@@ -1,81 +1,70 @@
<script>
- import Pikaday from 'pikaday';
- import { parsePikadayDate, pikadayToString } from '../../lib/utils/datefix';
+import Pikaday from 'pikaday';
+import { parsePikadayDate, pikadayToString } from '~/lib/utils/datetime_utility';
- export default {
- name: 'DatePicker',
- props: {
- label: {
- type: String,
- required: false,
- default: 'Date picker',
- },
- selectedDate: {
- type: Date,
- required: false,
- default: null,
- },
- minDate: {
- type: Date,
- required: false,
- default: null,
- },
- maxDate: {
- type: Date,
- required: false,
- default: null,
- },
+export default {
+ name: 'DatePicker',
+ props: {
+ label: {
+ type: String,
+ required: false,
+ default: 'Date picker',
},
- mounted() {
- this.calendar = new Pikaday({
- field: this.$el.querySelector('.dropdown-menu-toggle'),
- theme: 'gitlab-theme animate-picker',
- format: 'yyyy-mm-dd',
- container: this.$el,
- defaultDate: this.selectedDate,
- setDefaultDate: !!this.selectedDate,
- minDate: this.minDate,
- maxDate: this.maxDate,
- parse: dateString => parsePikadayDate(dateString),
- toString: date => pikadayToString(date),
- onSelect: this.selected.bind(this),
- onClose: this.toggled.bind(this),
- });
-
- this.$el.append(this.calendar.el);
- this.calendar.show();
+ selectedDate: {
+ type: Date,
+ required: false,
+ default: null,
+ },
+ minDate: {
+ type: Date,
+ required: false,
+ default: null,
},
- beforeDestroy() {
- this.calendar.destroy();
+ maxDate: {
+ type: Date,
+ required: false,
+ default: null,
+ },
+ },
+ mounted() {
+ this.calendar = new Pikaday({
+ field: this.$el.querySelector('.dropdown-menu-toggle'),
+ theme: 'gitlab-theme animate-picker',
+ format: 'yyyy-mm-dd',
+ container: this.$el,
+ defaultDate: this.selectedDate,
+ setDefaultDate: !!this.selectedDate,
+ minDate: this.minDate,
+ maxDate: this.maxDate,
+ parse: dateString => parsePikadayDate(dateString),
+ toString: date => pikadayToString(date),
+ onSelect: this.selected.bind(this),
+ onClose: this.toggled.bind(this),
+ });
+
+ this.$el.append(this.calendar.el);
+ this.calendar.show();
+ },
+ beforeDestroy() {
+ this.calendar.destroy();
+ },
+ methods: {
+ selected(dateText) {
+ this.$emit('newDateSelected', this.calendar.toString(dateText));
},
- methods: {
- selected(dateText) {
- this.$emit('newDateSelected', this.calendar.toString(dateText));
- },
- toggled() {
- this.$emit('hidePicker');
- },
+ toggled() {
+ this.$emit('hidePicker');
},
- };
+ },
+};
</script>
<template>
<div class="pikaday-container">
<div class="dropdown open">
- <button
- type="button"
- class="dropdown-menu-toggle"
- data-toggle="dropdown"
- @click="toggled"
- >
- <span class="dropdown-toggle-text">
- {{ label }}
- </span>
- <i
- class="fa fa-chevron-down"
- aria-hidden="true"
- >
- </i>
+ <button type="button" class="dropdown-menu-toggle" data-toggle="dropdown" @click="toggled">
+ <span class="dropdown-toggle-text"> {{ label }} </span>
+ <i class="fa fa-chevron-down" aria-hidden="true"> </i>
</button>
</div>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/project_avatar/default.vue b/app/assets/javascripts/vue_shared/components/project_avatar/default.vue
index 17927fabbcc..b399c232937 100644
--- a/app/assets/javascripts/vue_shared/components/project_avatar/default.vue
+++ b/app/assets/javascripts/vue_shared/components/project_avatar/default.vue
@@ -26,10 +26,7 @@ export default {
</script>
<template>
- <span
- :class="sizeClass"
- class="avatar-container project-avatar"
- >
+ <span :class="sizeClass" class="avatar-container project-avatar">
<project-avatar-image
v-if="project.avatar_url"
:link-href="project.path"
@@ -37,11 +34,6 @@ export default {
:img-alt="project.name"
:img-size="size"
/>
- <identicon
- v-else
- :entity-id="project.id"
- :entity-name="project.name"
- :size-class="sizeClass"
- />
+ <identicon v-else :entity-id="project.id" :entity-name="project.name" :size-class="sizeClass" />
</span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/project_avatar/image.vue b/app/assets/javascripts/vue_shared/components/project_avatar/image.vue
index 97ca4d93bd7..e77b9ddc7ba 100644
--- a/app/assets/javascripts/vue_shared/components/project_avatar/image.vue
+++ b/app/assets/javascripts/vue_shared/components/project_avatar/image.vue
@@ -1,6 +1,5 @@
<script>
-
- /* This is a re-usable vue component for rendering a project avatar that
+/* This is a re-usable vue component for rendering a project avatar that
does not need to link to the project's profile. The image and an optional
tooltip can be configured by props passed to this component.
@@ -16,70 +15,70 @@
*/
- import defaultAvatarUrl from 'images/no_avatar.png';
- import { placeholderImage } from '../../../lazy_loader';
- import tooltip from '../../directives/tooltip';
+import defaultAvatarUrl from 'images/no_avatar.png';
+import { placeholderImage } from '../../../lazy_loader';
+import tooltip from '../../directives/tooltip';
- export default {
- name: 'ProjectAvatarImage',
- directives: {
- tooltip,
+export default {
+ name: 'ProjectAvatarImage',
+ directives: {
+ tooltip,
+ },
+ props: {
+ lazy: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ imgSrc: {
+ type: String,
+ required: false,
+ default: defaultAvatarUrl,
+ },
+ cssClasses: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ imgAlt: {
+ type: String,
+ required: false,
+ default: 'project avatar',
+ },
+ size: {
+ type: Number,
+ required: false,
+ default: 20,
+ },
+ tooltipText: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ tooltipPlacement: {
+ type: String,
+ required: false,
+ default: 'top',
+ },
+ },
+ computed: {
+ // API response sends null when gravatar is disabled and
+ // we provide an empty string when we use it inside project avatar link.
+ // In both cases we should render the defaultAvatarUrl
+ sanitizedSource() {
+ return this.imgSrc === '' || this.imgSrc === null ? defaultAvatarUrl : this.imgSrc;
+ },
+ resultantSrcAttribute() {
+ return this.lazy ? placeholderImage : this.sanitizedSource;
},
- props: {
- lazy: {
- type: Boolean,
- required: false,
- default: false,
- },
- imgSrc: {
- type: String,
- required: false,
- default: defaultAvatarUrl,
- },
- cssClasses: {
- type: String,
- required: false,
- default: '',
- },
- imgAlt: {
- type: String,
- required: false,
- default: 'project avatar',
- },
- size: {
- type: Number,
- required: false,
- default: 20,
- },
- tooltipText: {
- type: String,
- required: false,
- default: '',
- },
- tooltipPlacement: {
- type: String,
- required: false,
- default: 'top',
- },
+ tooltipContainer() {
+ return this.tooltipText ? 'body' : null;
},
- computed: {
- // API response sends null when gravatar is disabled and
- // we provide an empty string when we use it inside project avatar link.
- // In both cases we should render the defaultAvatarUrl
- sanitizedSource() {
- return this.imgSrc === '' || this.imgSrc === null ? defaultAvatarUrl : this.imgSrc;
- },
- resultantSrcAttribute() {
- return this.lazy ? placeholderImage : this.sanitizedSource;
- },
- tooltipContainer() {
- return this.tooltipText ? 'body' : null;
- },
- avatarSizeClass() {
- return `s${this.size}`;
- },
+ avatarSizeClass() {
+ return `s${this.size}`;
},
- };
+ },
+};
</script>
<template>
@@ -88,7 +87,7 @@
:class="{
lazy: lazy,
[avatarSizeClass]: true,
- [cssClasses]: true
+ [cssClasses]: true,
}"
:src="resultantSrcAttribute"
:width="size"
diff --git a/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue b/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
index a2a9a5e6987..1c6c3fc4734 100644
--- a/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/recaptcha_modal.vue
@@ -1,67 +1,67 @@
<script>
- import DeprecatedModal from './deprecated_modal.vue';
+import DeprecatedModal from './deprecated_modal.vue';
- export default {
- name: 'RecaptchaModal',
+export default {
+ name: 'RecaptchaModal',
- components: {
- DeprecatedModal,
- },
+ components: {
+ DeprecatedModal,
+ },
- props: {
- html: {
- type: String,
- required: false,
- default: '',
- },
+ props: {
+ html: {
+ type: String,
+ required: false,
+ default: '',
},
+ },
- data() {
- return {
- script: {},
- scriptSrc: 'https://www.google.com/recaptcha/api.js',
- };
- },
+ data() {
+ return {
+ script: {},
+ scriptSrc: 'https://www.google.com/recaptcha/api.js',
+ };
+ },
- watch: {
- html() {
- this.appendRecaptchaScript();
- },
+ watch: {
+ html() {
+ this.appendRecaptchaScript();
},
+ },
- mounted() {
- window.recaptchaDialogCallback = this.submit.bind(this);
- },
+ mounted() {
+ window.recaptchaDialogCallback = this.submit.bind(this);
+ },
- methods: {
- appendRecaptchaScript() {
- this.removeRecaptchaScript();
+ methods: {
+ appendRecaptchaScript() {
+ this.removeRecaptchaScript();
- const script = document.createElement('script');
- script.src = this.scriptSrc;
- script.classList.add('js-recaptcha-script');
- script.async = true;
- script.defer = true;
+ const script = document.createElement('script');
+ script.src = this.scriptSrc;
+ script.classList.add('js-recaptcha-script');
+ script.async = true;
+ script.defer = true;
- this.script = script;
+ this.script = script;
- document.body.appendChild(script);
- },
+ document.body.appendChild(script);
+ },
- removeRecaptchaScript() {
- if (this.script instanceof Element) this.script.remove();
- },
+ removeRecaptchaScript() {
+ if (this.script instanceof Element) this.script.remove();
+ },
- close() {
- this.removeRecaptchaScript();
- this.$emit('close');
- },
+ close() {
+ this.removeRecaptchaScript();
+ this.$emit('close');
+ },
- submit() {
- this.$el.querySelector('form').submit();
- },
+ submit() {
+ this.$el.querySelector('form').submit();
},
- };
+ },
+};
</script>
<template>
@@ -73,14 +73,8 @@
@cancel="close"
>
<div slot="body">
- <p>
- {{ __('We want to be sure it is you, please confirm you are not a robot.') }}
- </p>
- <div
- ref="recaptcha"
- v-html="html"
- >
- </div>
+ <p>{{ __('We want to be sure it is you, please confirm you are not a robot.') }}</p>
+ <div ref="recaptcha" v-html="html"></div>
</div>
</deprecated-modal>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue b/app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue
index 7f1eb6bcec4..cc24fedceed 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue
@@ -1,46 +1,55 @@
<script>
- export default {
- name: 'CollapsedCalendarIcon',
- props: {
- containerClass: {
- type: String,
- required: false,
- default: '',
- },
- text: {
- type: String,
- required: false,
- default: '',
- },
- showIcon: {
- type: Boolean,
- required: false,
- default: true,
- },
+import tooltip from '~/vue_shared/directives/tooltip';
+
+export default {
+ name: 'CollapsedCalendarIcon',
+ directives: {
+ tooltip,
+ },
+ props: {
+ containerClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ text: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ showIcon: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ tooltipText: {
+ type: String,
+ required: false,
+ default: '',
},
- methods: {
- click() {
- this.$emit('click');
- },
+ },
+ methods: {
+ click() {
+ this.$emit('click');
},
- };
+ },
+};
</script>
<template>
<div
+ v-tooltip
:class="containerClass"
+ :title="tooltipText"
+ data-container="body"
+ data-placement="left"
+ data-html="true"
+ data-boundary="viewport"
@click="click"
>
- <i
- v-if="showIcon"
- class="fa fa-calendar"
- aria-hidden="true"
- >
- </i>
+ <i v-if="showIcon" class="fa fa-calendar" aria-hidden="true"> </i>
<slot>
- <span>
- {{ text }}
- </span>
+ <span> {{ text }} </span>
</slot>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue b/app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue
index dac438a702d..b5e43da401e 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue
@@ -1,110 +1,102 @@
<script>
- import { dateInWords } from '../../../lib/utils/datetime_utility';
- import toggleSidebar from './toggle_sidebar.vue';
- import collapsedCalendarIcon from './collapsed_calendar_icon.vue';
+import { __ } from '~/locale';
+import timeagoMixin from '~/vue_shared/mixins/timeago';
+import { dateInWords, timeFor } from '~/lib/utils/datetime_utility';
+import collapsedCalendarIcon from './collapsed_calendar_icon.vue';
- export default {
- name: 'SidebarCollapsedGroupedDatePicker',
- components: {
- toggleSidebar,
- collapsedCalendarIcon,
+export default {
+ name: 'SidebarCollapsedGroupedDatePicker',
+ components: {
+ collapsedCalendarIcon,
+ },
+ mixins: [timeagoMixin],
+ props: {
+ collapsed: {
+ type: Boolean,
+ required: false,
+ default: true,
},
- props: {
- collapsed: {
- type: Boolean,
- required: false,
- default: true,
- },
- showToggleSidebar: {
- type: Boolean,
- required: false,
- default: false,
- },
- minDate: {
- type: Date,
- required: false,
- default: null,
- },
- maxDate: {
- type: Date,
- required: false,
- default: null,
- },
- disableClickableIcons: {
- type: Boolean,
- required: false,
- default: false,
- },
+ minDate: {
+ type: Date,
+ required: false,
+ default: null,
},
- computed: {
- hasMinAndMaxDates() {
- return this.minDate && this.maxDate;
- },
- hasNoMinAndMaxDates() {
- return !this.minDate && !this.maxDate;
- },
- showMinDateBlock() {
- return this.minDate || this.hasNoMinAndMaxDates;
- },
- showFromText() {
- return !this.maxDate && this.minDate;
- },
- iconClass() {
- const disabledClass = this.disableClickableIcons ? 'disabled' : '';
- return `block sidebar-collapsed-icon calendar-icon ${disabledClass}`;
- },
+ maxDate: {
+ type: Date,
+ required: false,
+ default: null,
},
- methods: {
- toggleSidebar() {
- this.$emit('toggleCollapse');
- },
- dateText(dateType = 'min') {
- const date = this[`${dateType}Date`];
- const dateWords = dateInWords(date, true);
- const parsedDateWords = dateWords ? dateWords.replace(',', '') : dateWords;
+ disableClickableIcons: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ hasMinAndMaxDates() {
+ return this.minDate && this.maxDate;
+ },
+ hasNoMinAndMaxDates() {
+ return !this.minDate && !this.maxDate;
+ },
+ showMinDateBlock() {
+ return this.minDate || this.hasNoMinAndMaxDates;
+ },
+ showFromText() {
+ return !this.maxDate && this.minDate;
+ },
+ iconClass() {
+ const disabledClass = this.disableClickableIcons ? 'disabled' : '';
+ return `sidebar-collapsed-icon calendar-icon ${disabledClass}`;
+ },
+ },
+ methods: {
+ toggleSidebar() {
+ this.$emit('toggleCollapse');
+ },
+ dateText(dateType = 'min') {
+ const date = this[`${dateType}Date`];
+ const dateWords = dateInWords(date, true);
+ const parsedDateWords = dateWords ? dateWords.replace(',', '') : dateWords;
+
+ return date ? parsedDateWords : __('None');
+ },
+ tooltipText(dateType = 'min') {
+ const defaultText = dateType === 'min' ? __('Start date') : __('Due date');
+ const date = this[`${dateType}Date`];
+ const timeAgo = dateType === 'min' ? this.timeFormated(date) : timeFor(date);
+ const dateText = date ? [this.dateText(dateType), `(${timeAgo})`].join(' ') : '';
- return date ? parsedDateWords : 'None';
- },
+ if (date) {
+ return [defaultText, dateText].join('<br />');
+ }
+ return __('Start and due date');
},
- };
+ },
+};
</script>
<template>
<div class="block sidebar-grouped-item">
- <div
- v-if="showToggleSidebar"
- class="issuable-sidebar-header"
- >
- <toggle-sidebar
- :collapsed="collapsed"
- @toggle="toggleSidebar"
- />
- </div>
<collapsed-calendar-icon
v-if="showMinDateBlock"
:container-class="iconClass"
+ :tooltip-text="tooltipText('min')"
@click="toggleSidebar"
>
<span class="sidebar-collapsed-value">
- <span v-if="showFromText">From</span>
- <span>{{ dateText('min') }}</span>
+ <span v-if="showFromText">From</span> <span>{{ dateText('min') }}</span>
</span>
</collapsed-calendar-icon>
- <div
- v-if="hasMinAndMaxDates"
- class="text-center sidebar-collapsed-divider"
- >
- -
- </div>
+ <div v-if="hasMinAndMaxDates" class="text-center sidebar-collapsed-divider">-</div>
<collapsed-calendar-icon
v-if="maxDate"
:container-class="iconClass"
- :show-icon="!minDate"
+ :tooltip-text="tooltipText('max')"
@click="toggleSidebar"
>
<span class="sidebar-collapsed-value">
- <span v-if="!minDate">Until</span>
- <span>{{ dateText('max') }}</span>
+ <span v-if="!minDate">Until</span> <span>{{ dateText('max') }}</span>
</span>
</collapsed-calendar-icon>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue b/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue
index 9d757b27edc..82067129c57 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue
@@ -1,119 +1,109 @@
<script>
- import datePicker from '../pikaday.vue';
- import toggleSidebar from './toggle_sidebar.vue';
- import collapsedCalendarIcon from './collapsed_calendar_icon.vue';
- import { dateInWords } from '../../../lib/utils/datetime_utility';
+import { GlLoadingIcon } from '@gitlab/ui';
+import datePicker from '../pikaday.vue';
+import toggleSidebar from './toggle_sidebar.vue';
+import collapsedCalendarIcon from './collapsed_calendar_icon.vue';
+import { dateInWords } from '../../../lib/utils/datetime_utility';
- export default {
- name: 'SidebarDatePicker',
- components: {
- datePicker,
- toggleSidebar,
- collapsedCalendarIcon,
- },
- props: {
- blockClass: {
- type: String,
- required: false,
- default: '',
- },
- collapsed: {
- type: Boolean,
- required: false,
- default: true,
- },
- showToggleSidebar: {
- type: Boolean,
- required: false,
- default: false,
- },
- isLoading: {
- type: Boolean,
- required: false,
- default: false,
- },
- editable: {
- type: Boolean,
- required: false,
- default: false,
- },
- label: {
- type: String,
- required: false,
- default: 'Date picker',
- },
- selectedDate: {
- type: Date,
- required: false,
- default: null,
- },
- minDate: {
- type: Date,
- required: false,
- default: null,
- },
- maxDate: {
- type: Date,
- required: false,
- default: null,
- },
- },
- data() {
- return {
- editing: false,
- };
- },
- computed: {
- selectedAndEditable() {
- return this.selectedDate && this.editable;
- },
- selectedDateWords() {
- return dateInWords(this.selectedDate, true);
- },
- collapsedText() {
- return this.selectedDateWords ? this.selectedDateWords : 'None';
- },
- },
- methods: {
- stopEditing() {
- this.editing = false;
- },
- toggleDatePicker() {
- this.editing = !this.editing;
- },
- newDateSelected(date = null) {
- this.date = date;
- this.editing = false;
- this.$emit('saveDate', date);
- },
- toggleSidebar() {
- this.$emit('toggleCollapse');
- },
- },
- };
+export default {
+ name: 'SidebarDatePicker',
+ components: {
+ datePicker,
+ toggleSidebar,
+ collapsedCalendarIcon,
+ GlLoadingIcon,
+ },
+ props: {
+ blockClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ collapsed: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ showToggleSidebar: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ editable: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ label: {
+ type: String,
+ required: false,
+ default: 'Date picker',
+ },
+ selectedDate: {
+ type: Date,
+ required: false,
+ default: null,
+ },
+ minDate: {
+ type: Date,
+ required: false,
+ default: null,
+ },
+ maxDate: {
+ type: Date,
+ required: false,
+ default: null,
+ },
+ },
+ data() {
+ return {
+ editing: false,
+ };
+ },
+ computed: {
+ selectedAndEditable() {
+ return this.selectedDate && this.editable;
+ },
+ selectedDateWords() {
+ return dateInWords(this.selectedDate, true);
+ },
+ collapsedText() {
+ return this.selectedDateWords ? this.selectedDateWords : 'None';
+ },
+ },
+ methods: {
+ stopEditing() {
+ this.editing = false;
+ },
+ toggleDatePicker() {
+ this.editing = !this.editing;
+ },
+ newDateSelected(date = null) {
+ this.date = date;
+ this.editing = false;
+ this.$emit('saveDate', date);
+ },
+ toggleSidebar() {
+ this.$emit('toggleCollapse');
+ },
+ },
+};
</script>
<template>
- <div
- :class="blockClass"
- class="block"
- >
+ <div :class="blockClass" class="block">
<div class="issuable-sidebar-header">
- <toggle-sidebar
- :collapsed="collapsed"
- @toggle="toggleSidebar"
- />
+ <toggle-sidebar :collapsed="collapsed" @toggle="toggleSidebar" />
</div>
- <collapsed-calendar-icon
- :text="collapsedText"
- class="sidebar-collapsed-icon"
- />
+ <collapsed-calendar-icon :text="collapsedText" class="sidebar-collapsed-icon" />
<div class="title">
{{ label }}
- <gl-loading-icon
- v-if="isLoading"
- :inline="true"
- />
+ <gl-loading-icon v-if="isLoading" :inline="true" />
<div class="float-right">
<button
v-if="editable && !editing"
@@ -123,11 +113,7 @@
>
Edit
</button>
- <toggle-sidebar
- v-if="showToggleSidebar"
- :collapsed="collapsed"
- @toggle="toggleSidebar"
- />
+ <toggle-sidebar v-if="showToggleSidebar" :collapsed="collapsed" @toggle="toggleSidebar" />
</div>
</div>
<div class="value">
@@ -140,32 +126,21 @@
@newDateSelected="newDateSelected"
@hidePicker="stopEditing"
/>
- <span
- v-else
- class="value-content"
- >
+ <span v-else class="value-content">
<template v-if="selectedDate">
<strong>{{ selectedDateWords }}</strong>
- <span
- v-if="selectedAndEditable"
- class="no-value"
- >
+ <span v-if="selectedAndEditable" class="no-value">
-
<button
type="button"
class="btn-blank btn-link btn-secondary-hover-link"
- @click="newDateSelected(null)"
+ @click="newDateSelected(null);"
>
remove
</button>
</span>
</template>
- <span
- v-else
- class="no-value"
- >
- None
- </span>
+ <span v-else class="no-value"> None </span>
</span>
</div>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
index 3df286de129..f66e81b1e08 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
@@ -4,6 +4,7 @@ import { __ } from '~/locale';
import LabelsSelect from '~/labels_select';
import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
import DropdownTitle from './dropdown_title.vue';
import DropdownValue from './dropdown_value.vue';
import DropdownValueCollapsed from './dropdown_value_collapsed.vue';
@@ -24,6 +25,7 @@ export default {
DropdownSearchInput,
DropdownFooter,
DropdownCreateLabel,
+ GlLoadingIcon,
},
props: {
showCreate: {
@@ -120,30 +122,18 @@ export default {
:labels="context.labels"
@onValueClick="handleCollapsedValueClick"
/>
- <dropdown-title
- :can-edit="canEdit"
- />
- <dropdown-value
- :labels="context.labels"
- :label-filter-base-path="labelFilterBasePath"
- >
+ <dropdown-title :can-edit="canEdit" />
+ <dropdown-value :labels="context.labels" :label-filter-base-path="labelFilterBasePath">
<slot></slot>
</dropdown-value>
- <div
- v-if="canEdit"
- class="selectbox js-selectbox"
- style="display: none;"
- >
+ <div v-if="canEdit" class="selectbox js-selectbox" style="display: none;">
<dropdown-hidden-input
v-for="label in context.labels"
:key="label.id"
:name="hiddenInputName"
:value="label.id"
/>
- <div
- ref="dropdown"
- class="dropdown"
- >
+ <div ref="dropdown" class="dropdown">
<dropdown-button
:ability-name="abilityName"
:field-name="hiddenInputName"
@@ -159,11 +149,9 @@ dropdown-menu-labels dropdown-menu-selectable"
>
<div class="dropdown-page-one">
<dropdown-header v-if="showCreate" />
- <dropdown-search-input/>
+ <dropdown-search-input />
<div class="dropdown-content"></div>
- <div class="dropdown-loading">
- <gl-loading-icon />
- </div>
+ <div class="dropdown-loading"><gl-loading-icon /></div>
<dropdown-footer
v-if="showCreate"
:labels-web-url="labelsWebUrl"
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button.vue
index 48d2f16f554..498b507d11d 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button.vue
@@ -65,14 +65,7 @@ export default {
class="dropdown-menu-toggle wide js-label-select js-multiselect js-context-config-modal"
data-toggle="dropdown"
>
- <span class="dropdown-toggle-text">
- {{ dropdownToggleText }}
- </span>
- <i
- aria-hidden="true"
- class="fa fa-chevron-down"
- data-hidden="true"
- >
- </i>
+ <span class="dropdown-toggle-text"> {{ dropdownToggleText }} </span>
+ <i aria-hidden="true" class="fa fa-chevron-down" data-hidden="true"> </i>
</button>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue
index fe895136ccc..74c5e063c3d 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue
@@ -23,12 +23,7 @@ export default {
type="button"
class="dropdown-title-button dropdown-menu-back"
>
- <i
- aria-hidden="true"
- class="fa fa-arrow-left"
- data-hidden="true"
- >
- </i>
+ <i aria-hidden="true" class="fa fa-arrow-left" data-hidden="true"> </i>
</button>
{{ headerTitle }}
<button
@@ -36,12 +31,7 @@ export default {
type="button"
class="dropdown-title-button dropdown-menu-close"
>
- <i
- aria-hidden="true"
- class="fa fa-times dropdown-menu-close-icon"
- data-hidden="true"
- >
- </i>
+ <i aria-hidden="true" class="fa fa-times dropdown-menu-close-icon" data-hidden="true"> </i>
</button>
</div>
<div class="dropdown-content">
@@ -75,16 +65,10 @@ export default {
/>
</div>
<div class="clearfix">
- <button
- type="button"
- class="btn btn-primary float-left js-new-label-btn disabled"
- >
+ <button type="button" class="btn btn-primary float-left js-new-label-btn disabled">
{{ __('Create') }}
</button>
- <button
- type="button"
- class="btn btn-default float-right js-cancel-label-btn"
- >
+ <button type="button" class="btn btn-default float-right js-cancel-label-btn">
{{ __('Cancel') }}
</button>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer.vue
index d64ad016f9b..ebbd8d119b5 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer.vue
@@ -25,19 +25,10 @@ export default {
<div class="dropdown-footer">
<ul class="dropdown-footer-list">
<li>
- <a
- href="#"
- class="dropdown-toggle-page"
- >
- {{ createLabelTitle }}
- </a>
+ <a href="#" class="dropdown-toggle-page"> {{ createLabelTitle }} </a>
</li>
<li>
- <a
- :href="labelsWebUrl"
- data-is-link="true"
- class="dropdown-external-link"
- >
+ <a :href="labelsWebUrl" data-is-link="true" class="dropdown-external-link">
{{ manageLabelsTitle }}
</a>
</li>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header.vue
index e98b6392827..eb837be165b 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header.vue
@@ -10,12 +10,7 @@ export default {};
type="button"
class="dropdown-title-button dropdown-menu-close"
>
- <i
- aria-hidden="true"
- class="fa fa-times dropdown-menu-close-icon"
- data-hidden="true"
- >
- </i>
+ <i aria-hidden="true" class="fa fa-times dropdown-menu-close-icon" data-hidden="true"> </i>
</button>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input.vue
index 80d65a2a534..bf51fa3dc38 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input.vue
@@ -10,12 +10,7 @@ export default {};
class="dropdown-input-field"
type="search"
/>
- <i
- aria-hidden="true"
- class="fa fa-search dropdown-input-search"
- data-hidden="true"
- >
- </i>
+ <i aria-hidden="true" class="fa fa-search dropdown-input-search" data-hidden="true"> </i>
<i
aria-hidden="true"
class="fa fa-times dropdown-input-clear js-dropdown-input-clear"
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue
index 9ac32ff13c6..cb53273c786 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue
@@ -13,16 +13,8 @@ export default {
<div class="title hide-collapsed append-bottom-10">
{{ __('Labels') }}
<template v-if="canEdit">
- <i
- aria-hidden="true"
- class="fa fa-spinner fa-spin block-loading"
- data-hidden="true"
- >
- </i>
- <button
- type="button"
- class="edit-link btn btn-blank float-right js-sidebar-dropdown-toggle"
- >
+ <i aria-hidden="true" class="fa fa-spinner fa-spin block-loading" data-hidden="true"> </i>
+ <button type="button" class="edit-link btn btn-blank float-right js-sidebar-dropdown-toggle">
{{ __('Edit') }}
</button>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue
index 10e990f8a80..6faf3fafad1 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value.vue
@@ -37,22 +37,14 @@ export default {
<template>
<div
:class="{
- 'has-labels':!isEmpty,
+ 'has-labels': !isEmpty,
}"
class="hide-collapsed value issuable-show-labels js-value"
>
- <span
- v-if="isEmpty"
- class="text-secondary"
- >
+ <span v-if="isEmpty" class="text-secondary">
<slot>{{ __('None') }}</slot>
</span>
- <a
- v-for="label in labels"
- v-else
- :key="label.id"
- :href="labelFilterUrl(label)"
- >
+ <a v-for="label in labels" v-else :key="label.id" :href="labelFilterUrl(label)">
<span
v-tooltip
:style="labelStyle(label)"
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
index af297f3c408..e742900dbcb 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
@@ -14,7 +14,10 @@ export default {
},
computed: {
labelsList() {
- const labelsString = this.labels.slice(0, 5).map(label => label.title).join(', ');
+ const labelsString = this.labels
+ .slice(0, 5)
+ .map(label => label.title)
+ .join(', ');
if (this.labels.length > 5) {
return sprintf(s__('LabelSelect|%{labelsString}, and %{remainingLabelCount} more'), {
@@ -43,12 +46,7 @@ export default {
data-container="body"
@click="handleClick"
>
- <i
- aria-hidden="true"
- data-hidden="true"
- class="fa fa-tags"
- >
- </i>
+ <i aria-hidden="true" data-hidden="true" class="fa fa-tags"> </i>
<span>{{ labels.length }}</span>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/toggle_sidebar.vue b/app/assets/javascripts/vue_shared/components/sidebar/toggle_sidebar.vue
index 80dc7d3557c..3b5ce0e9910 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/toggle_sidebar.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/toggle_sidebar.vue
@@ -46,7 +46,7 @@ export default {
<i
:class="{
'fa-angle-double-right': !collapsed,
- 'fa-angle-double-left': collapsed
+ 'fa-angle-double-left': collapsed,
}"
aria-label="toggle collapse"
class="fa"
diff --git a/app/assets/javascripts/vue_shared/components/skeleton_loading_container.vue b/app/assets/javascripts/vue_shared/components/skeleton_loading_container.vue
deleted file mode 100644
index 4a5ffbe5d5a..00000000000
--- a/app/assets/javascripts/vue_shared/components/skeleton_loading_container.vue
+++ /dev/null
@@ -1,37 +0,0 @@
-<script>
- export default {
- props: {
- small: {
- type: Boolean,
- required: false,
- default: false,
- },
- lines: {
- type: Number,
- required: false,
- default: 3,
- },
- },
- computed: {
- lineClasses() {
- return new Array(this.lines).fill().map((_, i) => `skeleton-line-${i + 1}`);
- },
- },
- };
-</script>
-
-<template>
- <div
- :class="{
- 'animation-container-small': small,
- }"
- class="animation-container"
- >
- <div
- v-for="(css, index) in lineClasses"
- :key="index"
- :class="css"
- >
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/smart_virtual_list.vue b/app/assets/javascripts/vue_shared/components/smart_virtual_list.vue
new file mode 100644
index 00000000000..49f987bb619
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/smart_virtual_list.vue
@@ -0,0 +1,33 @@
+<script>
+import VirtualList from 'vue-virtual-scroll-list';
+
+export default {
+ name: 'SmartVirtualList',
+ components: { VirtualList },
+ props: {
+ size: { type: Number, required: true },
+ length: { type: Number, required: true },
+ remain: { type: Number, required: true },
+ rtag: { type: String, default: 'div' },
+ wtag: { type: String, default: 'div' },
+ wclass: { type: String, default: null },
+ },
+};
+</script>
+<template>
+ <virtual-list
+ v-if="length > remain"
+ v-bind="$attrs"
+ :size="remain"
+ :remain="remain"
+ :rtag="rtag"
+ :wtag="wtag"
+ :wclass="wclass"
+ class="js-virtual-list"
+ >
+ <slot></slot>
+ </virtual-list>
+ <component :is="rtag" v-else class="js-plain-element">
+ <component :is="wtag" :class="wclass"> <slot></slot> </component>
+ </component>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue b/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue
index 78fde463507..8ba6b73f928 100644
--- a/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue
+++ b/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue
@@ -88,19 +88,11 @@ export default {
</script>
<template>
- <div
- :class="cssClass"
- class="stacked-progress-bar"
- >
+ <div :class="cssClass" class="stacked-progress-bar">
+ <span v-if="!totalCount" class="status-unavailable"> {{ __('Not available') }} </span>
<span
- v-if="!totalCount"
- class="status-unavailable"
- >
- {{ __("Not available") }}
- </span>
- <span
- v-tooltip
v-if="successPercent"
+ v-tooltip
:title="successTooltip"
:style="successBarStyle"
class="status-green"
@@ -109,8 +101,8 @@ export default {
{{ successPercent }}%
</span>
<span
- v-tooltip
v-if="neutralPercent"
+ v-tooltip
:title="neutralTooltip"
:style="neutralBarStyle"
class="status-neutral"
@@ -119,8 +111,8 @@ export default {
{{ neutralPercent }}%
</span>
<span
- v-tooltip
v-if="failurePercent"
+ v-tooltip
:title="failureTooltip"
:style="failureBarStyle"
class="status-red"
diff --git a/app/assets/javascripts/vue_shared/components/svg_gradient.vue b/app/assets/javascripts/vue_shared/components/svg_gradient.vue
index b61a1befcd6..cca90af275e 100644
--- a/app/assets/javascripts/vue_shared/components/svg_gradient.vue
+++ b/app/assets/javascripts/vue_shared/components/svg_gradient.vue
@@ -17,20 +17,11 @@ export default {
};
</script>
<template>
- <svg
- height="0"
- width="0">
+ <svg height="0" width="0">
<defs>
- <linearGradient
- :id="identifierName">
- <stop
- :stop-color="colors[0]"
- :stop-opacity="opacity[0]"
- offset="0%" />
- <stop
- :stop-color="colors[1]"
- :stop-opacity="opacity[1]"
- offset="100%" />
+ <linearGradient :id="identifierName">
+ <stop :stop-color="colors[0]" :stop-opacity="opacity[0]" offset="0%" />
+ <stop :stop-color="colors[1]" :stop-opacity="opacity[1]" offset="100%" />
</linearGradient>
</defs>
</svg>
diff --git a/app/assets/javascripts/vue_shared/components/table_pagination.vue b/app/assets/javascripts/vue_shared/components/table_pagination.vue
index 8e9621c956f..01e655d27e5 100644
--- a/app/assets/javascripts/vue_shared/components/table_pagination.vue
+++ b/app/assets/javascripts/vue_shared/components/table_pagination.vue
@@ -1,17 +1,17 @@
<script>
- import { s__ } from '../../locale';
-
- const PAGINATION_UI_BUTTON_LIMIT = 4;
- const UI_LIMIT = 6;
- const SPREAD = '...';
- const PREV = s__('Pagination|Prev');
- const NEXT = s__('Pagination|Next');
- const FIRST = s__('Pagination|« First');
- const LAST = s__('Pagination|Last »');
-
- export default {
- props: {
- /**
+import { s__ } from '../../locale';
+
+const PAGINATION_UI_BUTTON_LIMIT = 4;
+const UI_LIMIT = 6;
+const SPREAD = '...';
+const PREV = s__('Pagination|Prev');
+const NEXT = s__('Pagination|Next');
+const FIRST = s__('Pagination|« First');
+const LAST = s__('Pagination|Last »');
+
+export default {
+ props: {
+ /**
This function will take the information given by the pagination component
Here is an example `change` method:
@@ -20,12 +20,12 @@
gl.utils.visitUrl(`?page=${pagenum}`);
},
*/
- change: {
- type: Function,
- required: true,
- },
+ change: {
+ type: Function,
+ required: true,
+ },
- /**
+ /**
pageInfo will come from the headers of the API call
in the `.then` clause of the VueResource API call
there should be a function that contructs the pageInfo for this component
@@ -41,100 +41,97 @@
previousPage: +headers['X-Prev-Page'],
});
*/
- pageInfo: {
- type: Object,
- required: true,
- },
+ pageInfo: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ prev() {
+ return this.pageInfo.previousPage;
+ },
+ next() {
+ return this.pageInfo.nextPage;
+ },
+ getItems() {
+ const total = this.pageInfo.totalPages;
+ const { page } = this.pageInfo;
+ const items = [];
+
+ if (page > 1) {
+ items.push({ title: FIRST, first: true });
+ }
+
+ if (page > 1) {
+ items.push({ title: PREV, prev: true });
+ } else {
+ items.push({ title: PREV, disabled: true, prev: true });
+ }
+
+ if (page > UI_LIMIT) items.push({ title: SPREAD, separator: true });
+
+ const start = Math.max(page - PAGINATION_UI_BUTTON_LIMIT, 1);
+ const end = Math.min(page + PAGINATION_UI_BUTTON_LIMIT, total);
+
+ for (let i = start; i <= end; i += 1) {
+ const isActive = i === page;
+ items.push({ title: i, active: isActive, page: true });
+ }
+
+ if (total - page > PAGINATION_UI_BUTTON_LIMIT) {
+ items.push({ title: SPREAD, separator: true, page: true });
+ }
+
+ if (page === total) {
+ items.push({ title: NEXT, disabled: true, next: true });
+ } else if (total - page >= 1) {
+ items.push({ title: NEXT, next: true });
+ }
+
+ if (total - page >= 1) {
+ items.push({ title: LAST, last: true });
+ }
+
+ return items;
+ },
+ showPagination() {
+ return this.pageInfo.totalPages > 1;
},
- computed: {
- prev() {
- return this.pageInfo.previousPage;
- },
- next() {
- return this.pageInfo.nextPage;
- },
- getItems() {
- const total = this.pageInfo.totalPages;
- const { page } = this.pageInfo;
- const items = [];
-
- if (page > 1) {
- items.push({ title: FIRST, first: true });
- }
-
- if (page > 1) {
- items.push({ title: PREV, prev: true });
- } else {
- items.push({ title: PREV, disabled: true, prev: true });
- }
-
- if (page > UI_LIMIT) items.push({ title: SPREAD, separator: true });
-
- const start = Math.max(page - PAGINATION_UI_BUTTON_LIMIT, 1);
- const end = Math.min(page + PAGINATION_UI_BUTTON_LIMIT, total);
-
- for (let i = start; i <= end; i += 1) {
- const isActive = i === page;
- items.push({ title: i, active: isActive, page: true });
- }
-
- if (total - page > PAGINATION_UI_BUTTON_LIMIT) {
- items.push({ title: SPREAD, separator: true, page: true });
- }
-
- if (page === total) {
- items.push({ title: NEXT, disabled: true, next: true });
- } else if (total - page >= 1) {
- items.push({ title: NEXT, next: true });
- }
-
- if (total - page >= 1) {
- items.push({ title: LAST, last: true });
- }
-
- return items;
- },
- showPagination() {
- return this.pageInfo.totalPages > 1;
- },
+ },
+ methods: {
+ changePage(text, isDisabled) {
+ if (isDisabled) return;
+
+ const { totalPages, nextPage, previousPage } = this.pageInfo;
+
+ switch (text) {
+ case SPREAD:
+ break;
+ case LAST:
+ this.change(totalPages);
+ break;
+ case NEXT:
+ this.change(nextPage);
+ break;
+ case PREV:
+ this.change(previousPage);
+ break;
+ case FIRST:
+ this.change(1);
+ break;
+ default:
+ this.change(+text);
+ break;
+ }
},
- methods: {
- changePage(text, isDisabled) {
- if (isDisabled) return;
-
- const { totalPages, nextPage, previousPage } = this.pageInfo;
-
- switch (text) {
- case SPREAD:
- break;
- case LAST:
- this.change(totalPages);
- break;
- case NEXT:
- this.change(nextPage);
- break;
- case PREV:
- this.change(previousPage);
- break;
- case FIRST:
- this.change(1);
- break;
- default:
- this.change(+text);
- break;
- }
- },
- hideOnSmallScreen(item) {
- return !item.first && !item.last && !item.next && !item.prev && !item.active;
- },
+ hideOnSmallScreen(item) {
+ return !item.first && !item.last && !item.next && !item.prev && !item.active;
},
- };
+ },
+};
</script>
<template>
- <div
- v-if="showPagination"
- class="gl-pagination prepend-top-default"
- >
+ <div v-if="showPagination" class="gl-pagination prepend-top-default">
<ul class="pagination justify-content-center">
<li
v-for="(item, index) in getItems"
@@ -148,14 +145,11 @@
'd-none d-md-block': hideOnSmallScreen(item),
separator: item.separator,
active: item.active,
- disabled: item.disabled || item.separator
+ disabled: item.disabled || item.separator,
}"
class="page-item"
>
- <a
- class="page-link"
- @click.prevent="changePage(item.title, item.disabled)"
- >
+ <a class="page-link" @click.prevent="changePage(item.title, item.disabled);">
{{ item.title }}
</a>
</li>
diff --git a/app/assets/javascripts/vue_shared/components/tabs/tab.vue b/app/assets/javascripts/vue_shared/components/tabs/tab.vue
index 1c6011dcfd0..d24c27cfcc3 100644
--- a/app/assets/javascripts/vue_shared/components/tabs/tab.vue
+++ b/app/assets/javascripts/vue_shared/components/tabs/tab.vue
@@ -37,7 +37,7 @@ export default {
<template>
<div
:class="{
- active: localActive
+ active: localActive,
}"
class="tab-pane"
role="tabpanel"
diff --git a/app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue b/app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue
index 368eeb6c453..8bcad7ac765 100644
--- a/app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue
+++ b/app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue
@@ -1,5 +1,5 @@
<script>
-import tooltip from '../directives/tooltip';
+import { GlTooltipDirective } from '@gitlab/ui';
import timeagoMixin from '../mixins/timeago';
import '../../lib/utils/datetime_utility';
@@ -9,23 +9,19 @@ import '../../lib/utils/datetime_utility';
export default {
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
- mixins: [
- timeagoMixin,
- ],
+ mixins: [timeagoMixin],
props: {
time: {
type: String,
required: true,
},
-
tooltipPlacement: {
type: String,
required: false,
default: 'top',
},
-
cssClass: {
type: String,
required: false,
@@ -36,11 +32,10 @@ export default {
</script>
<template>
<time
- v-tooltip
+ v-gl-tooltip="{ placement: tooltipPlacement }"
:class="cssClass"
:title="tooltipTitle(time)"
- :data-placement="tooltipPlacement"
- data-container="body"
- v-text="timeFormated(time)">
+ v-text="timeFormated(time)"
+ >
</time>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/toggle_button.vue b/app/assets/javascripts/vue_shared/components/toggle_button.vue
index 5b9c51786d6..de70fa2182b 100644
--- a/app/assets/javascripts/vue_shared/components/toggle_button.vue
+++ b/app/assets/javascripts/vue_shared/components/toggle_button.vue
@@ -1,87 +1,80 @@
<script>
- import { s__ } from '../../locale';
- import icon from './icon.vue';
+import { GlLoadingIcon } from '@gitlab/ui';
+import { s__ } from '../../locale';
+import icon from './icon.vue';
- const ICON_ON = 'status_success_borderless';
- const ICON_OFF = 'status_failed_borderless';
- const LABEL_ON = s__('ToggleButton|Toggle Status: ON');
- const LABEL_OFF = s__('ToggleButton|Toggle Status: OFF');
+const ICON_ON = 'status_success_borderless';
+const ICON_OFF = 'status_failed_borderless';
+const LABEL_ON = s__('ToggleButton|Toggle Status: ON');
+const LABEL_OFF = s__('ToggleButton|Toggle Status: OFF');
- export default {
- components: {
- icon,
- },
+export default {
+ components: {
+ icon,
+ GlLoadingIcon,
+ },
- model: {
- prop: 'value',
- event: 'change',
- },
+ model: {
+ prop: 'value',
+ event: 'change',
+ },
- props: {
- name: {
- type: String,
- required: false,
- default: null,
- },
- value: {
- type: Boolean,
- required: false,
- default: null,
- },
- disabledInput: {
- type: Boolean,
- required: false,
- default: false,
- },
- isLoading: {
- type: Boolean,
- required: false,
- default: false,
- },
+ props: {
+ name: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ value: {
+ type: Boolean,
+ required: false,
+ default: null,
},
+ disabledInput: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
- computed: {
- toggleIcon() {
- return this.value ? ICON_ON : ICON_OFF;
- },
- ariaLabel() {
- return this.value ? LABEL_ON : LABEL_OFF;
- },
+ computed: {
+ toggleIcon() {
+ return this.value ? ICON_ON : ICON_OFF;
+ },
+ ariaLabel() {
+ return this.value ? LABEL_ON : LABEL_OFF;
},
+ },
- methods: {
- toggleFeature() {
- if (!this.disabledInput) this.$emit('change', !this.value);
- },
+ methods: {
+ toggleFeature() {
+ if (!this.disabledInput) this.$emit('change', !this.value);
},
- };
+ },
+};
</script>
<template>
<label class="toggle-wrapper">
- <input
- v-if="name"
- :name="name"
- :value="value"
- type="hidden"
- />
+ <input v-if="name" :name="name" :value="value" type="hidden" />
<button
:aria-label="ariaLabel"
:class="{
'is-checked': value,
'is-disabled': disabledInput,
- 'is-loading': isLoading
+ 'is-loading': isLoading,
}"
type="button"
class="project-feature-toggle"
@click="toggleFeature"
>
<gl-loading-icon class="loading-icon" />
- <span class="toggle-icon">
- <icon
- :name="toggleIcon"
- css-classes="toggle-icon-svg"/>
- </span>
+ <span class="toggle-icon"> <icon :name="toggleIcon" css-classes="toggle-icon-svg" /> </span>
</button>
</label>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue b/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue
index 125826da6c3..69eb791d195 100644
--- a/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue
+++ b/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue
@@ -51,17 +51,13 @@ export default {
<template>
<span
- v-tooltip
v-if="showTooltip"
+ v-tooltip
:title="title"
:data-placement="placement"
class="js-show-tooltip"
>
<slot></slot>
</span>
- <span
- v-else
- >
- <slot></slot>
- </span>
+ <span v-else> <slot></slot> </span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue
index 7737b9f2697..01b8b94f9e3 100644
--- a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue
+++ b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_image.vue
@@ -15,14 +15,14 @@
*/
+import { GlTooltip } from '@gitlab/ui';
import defaultAvatarUrl from 'images/no_avatar.png';
import { placeholderImage } from '../../../lazy_loader';
-import tooltip from '../../directives/tooltip';
export default {
name: 'UserAvatarImage',
- directives: {
- tooltip,
+ components: {
+ GlTooltip,
},
props: {
lazy: {
@@ -73,9 +73,6 @@ export default {
resultantSrcAttribute() {
return this.lazy ? placeholderImage : this.sanitizedSource;
},
- tooltipContainer() {
- return this.tooltipText ? 'body' : null;
- },
avatarSizeClass() {
return `s${this.size}`;
},
@@ -84,22 +81,28 @@ export default {
</script>
<template>
- <img
- v-tooltip
- :class="{
- lazy: lazy,
- [avatarSizeClass]: true,
- [cssClasses]: true
- }"
- :src="resultantSrcAttribute"
- :width="size"
- :height="size"
- :alt="imgAlt"
- :data-src="sanitizedSource"
- :data-container="tooltipContainer"
- :data-placement="tooltipPlacement"
- :title="tooltipText"
- class="avatar"
- data-boundary="window"
- />
+ <span>
+ <img
+ ref="userAvatarImage"
+ :class="{
+ lazy: lazy,
+ [avatarSizeClass]: true,
+ [cssClasses]: true,
+ }"
+ :src="resultantSrcAttribute"
+ :width="size"
+ :height="size"
+ :alt="imgAlt"
+ :data-src="sanitizedSource"
+ class="avatar"
+ />
+ <gl-tooltip
+ :target="() => $refs.userAvatarImage"
+ :placement="tooltipPlacement"
+ boundary="window"
+ class="js-user-avatar-image-toolip"
+ >
+ <slot> {{ tooltipText }} </slot>
+ </gl-tooltip>
+ </span>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue
index 01c36fec41a..55e2a786c8f 100644
--- a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue
+++ b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_link.vue
@@ -1,5 +1,4 @@
<script>
-
/* This is a re-usable vue component for rendering a user avatar wrapped in
a clickable link (likely to the user's profile). The link, image, and
tooltip can be configured by props passed to this component.
@@ -18,16 +17,17 @@
*/
+import { GlLink, GlTooltipDirective } from '@gitlab/ui';
import userAvatarImage from './user_avatar_image.vue';
-import tooltip from '../../directives/tooltip';
export default {
name: 'UserAvatarLink',
components: {
+ GlLink,
userAvatarImage,
},
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
},
props: {
linkHref: {
@@ -83,9 +83,7 @@ export default {
</script>
<template>
- <a
- :href="linkHref"
- class="user-avatar-link">
+ <gl-link :href="linkHref" class="user-avatar-link">
<user-avatar-image
:img-src="imgSrc"
:img-alt="imgAlt"
@@ -93,11 +91,15 @@ export default {
:size="imgSize"
:tooltip-text="avatarTooltipText"
:tooltip-placement="tooltipPlacement"
- /><span
- v-tooltip
+ >
+ <slot></slot> </user-avatar-image
+ ><span
v-if="shouldShowUsername"
+ v-gl-tooltip
:title="tooltipText"
:tooltip-placement="tooltipPlacement"
- >{{ username }}</span>
- </a>
+ class="js-user-avatar-link-username"
+ >{{ username }}</span
+ ><slot name="avatar-badge"></slot>
+ </gl-link>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_svg.vue b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_svg.vue
index ef3b16edf5f..7ed4da84120 100644
--- a/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_svg.vue
+++ b/app/assets/javascripts/vue_shared/components/user_avatar/user_avatar_svg.vue
@@ -1,5 +1,4 @@
<script>
-
/* This is a re-usable vue component for rendering a user avatar svg (typically
for a blank state). It will receive styles comparable to the user avatar,
but no image is loaded, it isn't wrapped in a link, and tooltips aren't supported.
@@ -35,11 +34,5 @@ export default {
</script>
<template>
- <svg
- :class="avatarSizeClass"
- :height="size"
- :width="size"
- v-html="svg"
- />
+ <svg :class="avatarSizeClass" :height="size" :width="size" v-html="svg" />
</template>
-
diff --git a/app/assets/javascripts/vue_shared/directives/tooltip.js b/app/assets/javascripts/vue_shared/directives/tooltip.js
index 4f2412ce520..549d27e96d9 100644
--- a/app/assets/javascripts/vue_shared/directives/tooltip.js
+++ b/app/assets/javascripts/vue_shared/directives/tooltip.js
@@ -9,6 +9,14 @@ export default {
componentUpdated(el) {
$(el).tooltip('_fixTitle');
+
+ // update visible tooltips
+ const tooltipInstance = $(el).data('bs.tooltip');
+ const tip = tooltipInstance.getTipElement();
+ tooltipInstance.setElementContent(
+ $(tip.querySelectorAll('.tooltip-inner')),
+ tooltipInstance.getTitle(),
+ );
},
unbind(el) {
diff --git a/app/assets/javascripts/vue_shared/mixins/ci_pagination_api_mixin.js b/app/assets/javascripts/vue_shared/mixins/ci_pagination_api_mixin.js
index f94cc670edf..f9e3f3df0cc 100644
--- a/app/assets/javascripts/vue_shared/mixins/ci_pagination_api_mixin.js
+++ b/app/assets/javascripts/vue_shared/mixins/ci_pagination_api_mixin.js
@@ -4,10 +4,7 @@
*
* Components need to have `scope`, `page` and `requestData`
*/
-import {
- historyPushState,
- buildUrlWithCurrentLocation,
-} from '../../lib/utils/common_utils';
+import { historyPushState, buildUrlWithCurrentLocation } from '../../lib/utils/common_utils';
export default {
methods: {
@@ -17,19 +14,28 @@ export default {
onChangePage(page) {
/* URLS parameters are strings, we need to parse to match types */
- this.updateContent({ scope: this.scope, page: Number(page).toString() });
+ const params = {
+ page: Number(page).toString(),
+ };
+
+ if (this.scope) {
+ params.scope = this.scope;
+ }
+ this.updateContent(params);
},
updateInternalState(parameters) {
// stop polling
this.poll.stop();
- const queryString = Object.keys(parameters).map((parameter) => {
- const value = parameters[parameter];
- // update internal state for UI
- this[parameter] = value;
- return `${parameter}=${encodeURIComponent(value)}`;
- }).join('&');
+ const queryString = Object.keys(parameters)
+ .map(parameter => {
+ const value = parameters[parameter];
+ // update internal state for UI
+ this[parameter] = value;
+ return `${parameter}=${encodeURIComponent(value)}`;
+ })
+ .join('&');
// update polling parameters
this.requestData = parameters;
diff --git a/app/assets/javascripts/vue_shared/models/label.js b/app/assets/javascripts/vue_shared/models/label.js
index d29c7fe973a..2d2732d0661 100644
--- a/app/assets/javascripts/vue_shared/models/label.js
+++ b/app/assets/javascripts/vue_shared/models/label.js
@@ -6,7 +6,7 @@ export default class ListLabel {
this.color = obj.color;
this.textColor = obj.text_color;
this.description = obj.description;
- this.priority = (obj.priority !== null) ? obj.priority : Infinity;
+ this.priority = obj.priority !== null ? obj.priority : Infinity;
}
}
diff --git a/app/assets/javascripts/vue_shared/translate.js b/app/assets/javascripts/vue_shared/translate.js
index 48c63373b77..e0baf03acc3 100644
--- a/app/assets/javascripts/vue_shared/translate.js
+++ b/app/assets/javascripts/vue_shared/translate.js
@@ -1,11 +1,6 @@
-import {
- __,
- n__,
- s__,
- sprintf,
-} from '../locale';
+import { __, n__, s__, sprintf } from '../locale';
-export default (Vue) => {
+export default Vue => {
Vue.mixin({
methods: {
/**
diff --git a/app/assets/javascripts/vue_shared/vue_resource_interceptor.js b/app/assets/javascripts/vue_shared/vue_resource_interceptor.js
index b9693892f45..754025207c8 100644
--- a/app/assets/javascripts/vue_shared/vue_resource_interceptor.js
+++ b/app/assets/javascripts/vue_shared/vue_resource_interceptor.js
@@ -21,7 +21,7 @@ Vue.http.interceptors.push((request, next) => {
Vue.http.interceptors.push((request, next) => {
request.headers.set(csrf.headerKey, csrf.token);
- next((response) => {
+ next(response => {
// Headers object has a `forEach` property that iterates through all values.
const headers = {};
diff --git a/app/assets/javascripts/zen_mode.js b/app/assets/javascripts/zen_mode.js
index 0138c9be803..e98c4d7bf7a 100644
--- a/app/assets/javascripts/zen_mode.js
+++ b/app/assets/javascripts/zen_mode.js
@@ -1,4 +1,4 @@
-/* eslint-disable func-names, wrap-iife, prefer-arrow-callback, no-unused-vars, consistent-return, camelcase, comma-dangle, max-len, class-methods-use-this */
+/* eslint-disable func-names, prefer-arrow-callback, no-unused-vars, consistent-return, camelcase, class-methods-use-this */
// Zen Mode (full screen) textarea
//
@@ -47,16 +47,26 @@ export default class ZenMode {
e.preventDefault();
return $(e.currentTarget).trigger('zen_mode:leave');
});
- $(document).on('zen_mode:enter', (function(_this) {
- return function(e) {
- return _this.enter($(e.target).closest('.md-area').find('.zen-backdrop'));
- };
- })(this));
- $(document).on('zen_mode:leave', (function(_this) {
- return function(e) {
- return _this.exit();
- };
- })(this));
+ $(document).on(
+ 'zen_mode:enter',
+ (function(_this) {
+ return function(e) {
+ return _this.enter(
+ $(e.target)
+ .closest('.md-area')
+ .find('.zen-backdrop'),
+ );
+ };
+ })(this),
+ );
+ $(document).on(
+ 'zen_mode:leave',
+ (function(_this) {
+ return function(e) {
+ return _this.exit();
+ };
+ })(this),
+ );
$(document).on('keydown', function(e) {
// Esc
if (e.keyCode === 27) {
@@ -93,7 +103,7 @@ export default class ZenMode {
scrollTo(zen_area) {
return $.scrollTo(zen_area, 0, {
- offset: -150
+ offset: -150,
});
}
}
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index f2950308019..bd1cca69c03 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -5,7 +5,6 @@
*= require jquery.atwho
*= require select2
*= require_self
- *= require dropzone/basic
*= require cropper.css
*/
@@ -18,6 +17,7 @@
*/
@import "../../../node_modules/pikaday/scss/pikaday";
+@import "../../../node_modules/dropzone/dist/basic";
/*
* GitLab UI framework
diff --git a/app/assets/stylesheets/bootstrap.scss b/app/assets/stylesheets/bootstrap.scss
index a040c2f8c20..4a09da3d580 100644
--- a/app/assets/stylesheets/bootstrap.scss
+++ b/app/assets/stylesheets/bootstrap.scss
@@ -1,5 +1,5 @@
/*
- * Includes specific styles from the bootstrap4 foler in node_modules
+ * Includes specific styles from the bootstrap4 folder in node_modules
*/
@import "../../../node_modules/bootstrap/scss/functions";
diff --git a/app/assets/stylesheets/bootstrap_migration.scss b/app/assets/stylesheets/bootstrap_migration.scss
index c91f5e279ea..62024b8c555 100644
--- a/app/assets/stylesheets/bootstrap_migration.scss
+++ b/app/assets/stylesheets/bootstrap_migration.scss
@@ -93,7 +93,6 @@ hr {
}
.form-group.row .col-form-label {
- padding-top: 0;
// Bootstrap 4 aligns labels to the left
// for horizontal forms
@include media-breakpoint-up(md) {
@@ -239,10 +238,6 @@ h3.popover-header {
}
.card {
- .card-title {
- margin-bottom: 0;
- }
-
&.card-without-border {
@extend .border-0;
}
@@ -256,13 +251,6 @@ h3.popover-header {
}
}
-.card-header {
- h3.card-title,
- h4.card-title {
- margin-top: 0;
- }
-}
-
.nav-tabs {
// Override bootstrap's default border
border-bottom: 0;
@@ -348,3 +336,12 @@ input[type=color].form-control {
.input-group-btn:last-child {
@extend .input-group-append;
}
+
+/*
+ Bootstrap 4.1.2 introduced a new default vertical alignment which breaks our icons,
+ so we need to reset the vertical alignment to the default value. See:
+ - https://gitlab.com/gitlab-org/gitlab-ce/issues/51362
+ */
+svg {
+ vertical-align: baseline;
+}
diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss
index 4ffb3e9ab42..4041f2b4479 100644
--- a/app/assets/stylesheets/framework.scss
+++ b/app/assets/stylesheets/framework.scss
@@ -51,6 +51,7 @@
@import 'framework/blank';
@import 'framework/wells';
@import 'framework/page_header';
+@import 'framework/page_title';
@import 'framework/awards';
@import 'framework/images';
@import 'framework/broadcast_messages';
diff --git a/app/assets/stylesheets/framework/awards.scss b/app/assets/stylesheets/framework/awards.scss
index 702276780e9..7a95db5976d 100644
--- a/app/assets/stylesheets/framework/awards.scss
+++ b/app/assets/stylesheets/framework/awards.scss
@@ -148,10 +148,7 @@
.award-control-icon svg {
background: $award-emoji-positive-add-bg;
-
- path {
- fill: $award-emoji-positive-add-lines;
- }
+ fill: $award-emoji-positive-add-lines;
}
.award-control-icon-neutral {
diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
index 7145a76db6d..43b7c26b272 100644
--- a/app/assets/stylesheets/framework/blocks.scss
+++ b/app/assets/stylesheets/framework/blocks.scss
@@ -283,18 +283,20 @@
.dismiss-button {
position: absolute;
- right: 6px;
- top: 6px;
+ right: $gl-padding-8;
+ top: $gl-padding-8;
cursor: pointer;
- color: $blue-300;
+ color: $blue-500;
z-index: 1;
border: 0;
background-color: transparent;
+ padding: $gl-padding-8;
+ line-height: 0;
&:hover,
&:focus {
border: 0;
- color: $blue-400;
+ color: $blue-700;
}
}
@@ -346,6 +348,7 @@
@include media-breakpoint-down(xs) {
width: 100%;
+ margin: $btn-side-margin 0;
}
}
}
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index 686ce0c63a4..219fd99b097 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -207,6 +207,10 @@
@include btn-with-margin;
}
+ &.btn-icon {
+ color: $gl-gray-700;
+ }
+
.fa-caret-down,
.fa-chevron-down {
margin-left: 5px;
@@ -218,6 +222,25 @@
}
}
+ &.btn-text-field {
+ width: 100%;
+ text-align: left;
+ padding: 6px 16px;
+ border-color: $border-color;
+ color: $gray-darkest;
+ background-color: $gray-light;
+
+ &:hover,
+ &:active,
+ &:focus {
+ cursor: text;
+ box-shadow: none;
+ border-color: lighten($blue-300, 20%);
+ color: $gray-darkest;
+ background-color: $gray-light;
+ }
+ }
+
&.dot-highlight::after {
content: '';
background-color: $blue-500;
@@ -335,31 +358,16 @@
}
}
-.btn-text-field {
- width: 100%;
- text-align: left;
- padding: 6px 16px;
- border-color: $border-color;
- color: $gray-darkest;
- background-color: $gray-light;
-
- &:hover,
- &:active,
- &:focus {
- cursor: text;
- box-shadow: none;
- border-color: lighten($blue-300, 20%);
- color: $gray-darkest;
- background-color: $gray-light;
- }
-}
-
.btn-build {
margin-left: 10px;
i {
color: $gl-text-color-secondary;
}
+
+ svg {
+ fill: $gl-text-color-secondary;
+ }
}
.clone-dropdown-btn a {
diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss
index 0b9dff64b0b..9638fee6078 100644
--- a/app/assets/stylesheets/framework/calendar.scss
+++ b/app/assets/stylesheets/framework/calendar.scss
@@ -1,8 +1,7 @@
-.calender-block {
+.calendar-block {
padding-left: 0;
padding-right: 0;
border-top: 0;
- direction: rtl;
@media (min-width: map-get($grid-breakpoints, sm)) and (max-width: map-get($grid-breakpoints, sm)) {
overflow-x: auto;
@@ -42,10 +41,13 @@
}
.calendar-hint {
- margin-top: -23px;
- float: right;
font-size: 12px;
- direction: ltr;
+
+ &.bottom-right {
+ direction: ltr;
+ margin-top: -23px;
+ float: right;
+ }
}
.pika-single.gitlab-theme {
diff --git a/app/assets/stylesheets/framework/callout.scss b/app/assets/stylesheets/framework/callout.scss
index bdd7f09d926..0d8e4afa76f 100644
--- a/app/assets/stylesheets/framework/callout.scss
+++ b/app/assets/stylesheets/framework/callout.scss
@@ -33,7 +33,11 @@
.bs-callout-warning {
background-color: $orange-100;
border-color: $orange-200;
- color: $orange-700;
+ color: $orange-900;
+
+ a {
+ color: $orange-900;
+ }
}
.bs-callout-info {
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 28dda65091d..626c8f92d1d 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -33,6 +33,11 @@
color: $brand-danger;
}
+.text-danger-muted,
+.text-danger-muted:hover {
+ color: $red-300;
+}
+
.text-warning,
.text-warning:hover {
color: $brand-warning;
@@ -324,9 +329,28 @@ img.emoji {
word-wrap: break-word;
}
+.checkbox-icon-inline-wrapper {
+ .checkbox {
+ display: inline;
+
+ label {
+ display: inline;
+ }
+ }
+}
+
+.outline-0 {
+ outline: 0;
+
+ &:focus {
+ outline: 0;
+ }
+}
+
/** COMMON CLASSES **/
.prepend-top-0 { margin-top: 0; }
.prepend-top-2 { margin-top: 2px; }
+.prepend-top-4 { margin-top: $gl-padding-4; }
.prepend-top-5 { margin-top: 5px; }
.prepend-top-8 { margin-top: $grid-size; }
.prepend-top-10 { margin-top: 10px; }
@@ -347,6 +371,7 @@ img.emoji {
.append-right-default { margin-right: $gl-padding; }
.append-right-20 { margin-right: 20px; }
.append-bottom-0 { margin-bottom: 0; }
+.append-bottom-4 { margin-bottom: $gl-padding-4; }
.append-bottom-5 { margin-bottom: 5px; }
.append-bottom-8 { margin-bottom: $grid-size; }
.append-bottom-10 { margin-bottom: 10px; }
@@ -359,3 +384,5 @@ img.emoji {
.flex-align-self-center { align-self: center; }
.flex-grow { flex-grow: 1; }
.flex-no-shrink { flex-shrink: 0; }
+.mw-460 { max-width: 460px; }
+.ws-initial { white-space: initial; }
diff --git a/app/assets/stylesheets/framework/contextual_sidebar.scss b/app/assets/stylesheets/framework/contextual_sidebar.scss
index e2bbcc67a67..6f103e4e89a 100644
--- a/app/assets/stylesheets/framework/contextual_sidebar.scss
+++ b/app/assets/stylesheets/framework/contextual_sidebar.scss
@@ -9,8 +9,7 @@
padding-left: $contextual-sidebar-width;
}
- .issues-bulk-update.right-sidebar.right-sidebar-expanded
- .issuable-sidebar-header {
+ .issues-bulk-update.right-sidebar.right-sidebar-expanded .issuable-sidebar-header {
padding: 10px 0 15px;
}
}
@@ -75,7 +74,7 @@
.nav-sidebar {
transition: width $sidebar-transition-duration, left $sidebar-transition-duration;
position: fixed;
- z-index: 400;
+ z-index: 600;
width: $contextual-sidebar-width;
top: $header-height;
bottom: 0;
@@ -86,8 +85,7 @@
&:not(.sidebar-collapsed-desktop) {
@media (min-width: map-get($grid-breakpoints, sm)) and (max-width: map-get($grid-breakpoints, sm)) {
- box-shadow: inset -1px 0 0 $border-color,
- 2px 1px 3px $dropdown-shadow-color;
+ box-shadow: inset -1px 0 0 $border-color, 2px 1px 3px $dropdown-shadow-color;
}
}
@@ -113,7 +111,7 @@
}
.avatar-container {
- margin-right: 0;
+ margin: 0 auto;
}
}
@@ -324,15 +322,15 @@
width: $contextual-sidebar-width - 1px;
transition: width $sidebar-transition-duration;
position: fixed;
+ height: $toggle-sidebar-height;
bottom: 0;
- padding: $gl-padding;
+ padding: 0 $gl-padding;
background-color: $gray-light;
border: 0;
border-top: 1px solid $border-color;
color: $gl-text-color-secondary;
display: flex;
align-items: center;
- line-height: 1;
svg {
margin-right: 8px;
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 8603714f709..ce5d36a340f 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -144,6 +144,13 @@
top: 11px;
right: 8px;
}
+
+ .ic-chevron-down {
+ position: absolute;
+ top: $gl-padding-8;
+ right: $gl-padding-8;
+ color: $gray-darkest;
+ }
}
@mixin dropdown-item-hover {
@@ -151,7 +158,7 @@
color: $gl-text-color;
outline: 0;
- // make sure the text color is not overriden
+ // make sure the text color is not overridden
&.text-danger {
color: $brand-danger;
}
@@ -177,7 +184,7 @@
text-align: left;
width: 100%;
- // make sure the text color is not overriden
+ // make sure the text color is not overridden
&.text-danger {
color: $brand-danger;
}
@@ -561,6 +568,10 @@
top: -1px;
}
+.dropdown-menu-close-icon {
+ vertical-align: middle;
+}
+
.dropdown-menu-back {
left: 7px;
top: 2px;
@@ -572,9 +583,10 @@
padding: 0 10px;
.fa,
- .input-icon {
+ .input-icon,
+ .ic-search {
position: absolute;
- top: 10px;
+ top: $gl-padding-8;
right: 20px;
color: $dropdown-input-fa-color;
font-size: 12px;
@@ -790,11 +802,7 @@
@include media-breakpoint-down(xs) {
.navbar-gitlab {
- li.header-projects,
- li.header-groups,
- li.header-more,
- li.header-new,
- li.header-user {
+ li.dropdown {
position: static;
}
}
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index 53f198b47c6..037a5adfb7e 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -36,7 +36,6 @@
text-align: left;
padding: 10px $gl-padding;
word-wrap: break-word;
- border-radius: $border-radius-default $border-radius-default 0 0;
&.file-title-clear {
padding-left: 0;
@@ -416,7 +415,6 @@ span.idiff {
}
.preview-container {
- height: 100%;
overflow: auto;
.file-container {
diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss
index d5693a5d1a1..f48b3ddc912 100644
--- a/app/assets/stylesheets/framework/filters.scss
+++ b/app/assets/stylesheets/framework/filters.scss
@@ -363,6 +363,12 @@
background-color: $white-light;
border-top: 0;
}
+
+ .filter-dropdown-container {
+ .dropdown {
+ margin-left: 0;
+ }
+ }
}
@include media-breakpoint-down(sm) {
@@ -372,16 +378,6 @@
.dropdown-menu {
width: 100%;
}
-
- .dropdown {
- margin-left: 0;
- }
-
- .fa-chevron-down {
- position: absolute;
- right: 10px;
- top: 10px;
- }
}
}
diff --git a/app/assets/stylesheets/framework/flash.scss b/app/assets/stylesheets/framework/flash.scss
index 7a4c3914fb0..afa85f0e4ae 100644
--- a/app/assets/stylesheets/framework/flash.scss
+++ b/app/assets/stylesheets/framework/flash.scss
@@ -32,16 +32,16 @@
margin: 0;
}
+ .flash-text,
+ .flash-action {
+ display: inline-block;
+ }
+
.flash-alert {
@extend .alert;
background-color: $red-500;
margin: 0;
- .flash-text,
- .flash-action {
- display: inline-block;
- }
-
.flash-action {
margin-left: 5px;
text-decoration: none;
diff --git a/app/assets/stylesheets/framework/gfm.scss b/app/assets/stylesheets/framework/gfm.scss
index d2ba76f5160..50d4298d418 100644
--- a/app/assets/stylesheets/framework/gfm.scss
+++ b/app/assets/stylesheets/framework/gfm.scss
@@ -11,6 +11,10 @@
padding: 0 2px;
background-color: $blue-100;
border-radius: $border-radius-default;
+
+ &.current-user {
+ background-color: $orange-100;
+ }
}
.gfm-color_chip {
diff --git a/app/assets/stylesheets/framework/gitlab_theme.scss b/app/assets/stylesheets/framework/gitlab_theme.scss
index 50ebc6d0dd1..b8bb9e1e07b 100644
--- a/app/assets/stylesheets/framework/gitlab_theme.scss
+++ b/app/assets/stylesheets/framework/gitlab_theme.scss
@@ -161,6 +161,7 @@
.nav-links li {
&.active a,
+ &.md-header-tab.active button,
a.active {
border-bottom: 2px solid $active-tab-border;
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 11a30d83f03..39410ac56af 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -110,6 +110,10 @@
}
}
+ .navbar-collapse > ul.nav > li:not(.d-none) {
+ margin: 0 2px;
+ }
+
&.menu-expanded {
@include media-breakpoint-down(xs) {
.title-container {
@@ -117,7 +121,7 @@
}
.navbar-collapse {
- display: block;
+ display: flex;
}
}
}
@@ -209,7 +213,7 @@
> a {
will-change: color;
- margin: 4px 2px;
+ margin: 4px 0;
padding: 6px 8px;
height: 32px;
@@ -455,14 +459,11 @@
color: $indigo-900;
font-weight: $gl-font-weight-bold;
line-height: 18px;
+ margin: 4px 0 4px 2px;
&:hover {
background-color: $white-light;
}
-
- @include media-breakpoint-down(xs) {
- margin-top: $gl-padding-4;
- }
}
.navbar-nav {
@@ -509,12 +510,7 @@
margin-right: -10px;
.nav > li:not(.d-none) {
- display: table-cell !important;
- width: 25%;
-
- a {
- margin-right: 8px;
- }
+ flex: 1;
}
}
}
@@ -529,9 +525,7 @@
}
.header-user {
- .dropdown-menu {
- width: auto;
- min-width: unset;
+ &.show .dropdown-menu {
margin-top: 4px;
color: $gl-text-color;
left: auto;
@@ -542,6 +536,22 @@
.user-name {
display: block;
}
+
+ .user-status {
+ margin-right: 0;
+ max-width: 240px;
+ font-size: $gl-font-size-small;
+
+ gl-emoji {
+ font-size: $gl-font-size-small;
+ }
+
+ .user-status-emoji {
+ gl-emoji {
+ font-size: $gl-font-size;
+ }
+ }
+ }
}
svg {
@@ -573,3 +583,24 @@
}
}
}
+
+.set-user-status-modal {
+ .modal-body {
+ min-height: unset;
+ }
+
+ .input-lg {
+ max-width: unset;
+ }
+
+ .no-emoji-placeholder,
+ .clear-user-status {
+ svg {
+ fill: $gl-text-color-secondary;
+ }
+ }
+
+ .emoji-menu-toggle-button {
+ @include emoji-menu-toggle-button;
+ }
+}
diff --git a/app/assets/stylesheets/framework/highlight.scss b/app/assets/stylesheets/framework/highlight.scss
index 452e946f95f..73533571a2f 100644
--- a/app/assets/stylesheets/framework/highlight.scss
+++ b/app/assets/stylesheets/framework/highlight.scss
@@ -42,11 +42,12 @@
padding: 10px;
text-align: right;
float: left;
+ line-height: 1;
a {
font-family: $monospace-font;
display: block;
- font-size: $code_font_size !important;
+ font-size: $code-font-size !important;
min-height: 19px;
white-space: nowrap;
diff --git a/app/assets/stylesheets/framework/icons.scss b/app/assets/stylesheets/framework/icons.scss
index f002edced8a..8db7d63266e 100644
--- a/app/assets/stylesheets/framework/icons.scss
+++ b/app/assets/stylesheets/framework/icons.scss
@@ -64,6 +64,7 @@
}
}
+.ci-status-icon-scheduled,
.ci-status-icon-manual {
svg {
fill: $gl-text-color;
@@ -79,3 +80,15 @@
.user-avatar-link {
text-decoration: none;
}
+
+.circle-icon-container {
+ $border-size: 1px;
+
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border: $border-size solid $theme-gray-400;
+ border-radius: 50%;
+ padding: $gl-padding-8 - $border-size;
+ color: $theme-gray-700;
+}
diff --git a/app/assets/stylesheets/framework/images.scss b/app/assets/stylesheets/framework/images.scss
index 1e93bf2b751..a20920e2503 100644
--- a/app/assets/stylesheets/framework/images.scss
+++ b/app/assets/stylesheets/framework/images.scss
@@ -39,7 +39,7 @@
svg {
fill: currentColor;
- $svg-sizes: 8 10 12 16 18 24 32 48 72;
+ $svg-sizes: 8 10 12 14 16 18 24 32 48 72;
@each $svg-size in $svg-sizes {
&.s#{$svg-size} {
@include svg-size(#{$svg-size}px);
diff --git a/app/assets/stylesheets/framework/issue_box.scss b/app/assets/stylesheets/framework/issue_box.scss
index 2d672e62e08..a66604e56ff 100644
--- a/app/assets/stylesheets/framework/issue_box.scss
+++ b/app/assets/stylesheets/framework/issue_box.scss
@@ -22,7 +22,7 @@
margin-right: 10px;
color: $white-light;
font-size: $gl-font-size;
- line-height: 25px;
+ line-height: $gl-line-height-24;
&.status-box-closed,
&.status-box-mr-closed {
diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss
index 554e2b6720a..0f6fb16774c 100644
--- a/app/assets/stylesheets/framework/markdown_area.scss
+++ b/app/assets/stylesheets/framework/markdown_area.scss
@@ -72,6 +72,7 @@
.md-header-tab {
@include media-breakpoint-down(xs) {
flex: 1;
+ flex-direction: column;
width: 100%;
border-bottom: 1px solid $border-color;
text-align: center;
@@ -218,6 +219,13 @@
margin-bottom: 0;
}
+ .has-warning {
+ .name,
+ .description {
+ color: $orange-700;
+ }
+ }
+
.cur {
.avatar {
@include disableAllAnimation;
@@ -245,6 +253,11 @@
small {
color: inherit;
}
+
+ &.has-warning {
+ color: $orange-700;
+ background-color: $orange-100;
+ }
}
div.avatar {
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index 7f37dd3de91..9837b1a6bd0 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -12,6 +12,15 @@
max-width: $max-width;
}
+/**
+ * Mixin for fixed width container
+ */
+@mixin fixed-width-container {
+ max-width: $limited-layout-width - ($gl-padding * 2);
+ margin-left: auto;
+ margin-right: auto;
+}
+
/*
* Mixin for markdown tables
*/
@@ -20,20 +29,24 @@
display: inline-block;
overflow-x: auto;
border: 0;
- border-color: $gray-100;
+ border-color: $gl-gray-100;
@supports (width: fit-content) {
display: block;
width: fit-content;
}
+ tbody {
+ background-color: $white-light;
+ }
+
tr {
th {
- border-bottom: solid 2px $gray-100;
+ border-bottom: solid 2px $gl-gray-100;
}
td {
- border-color: $gray-100;
+ border-color: $gl-gray-100;
}
}
}
@@ -237,6 +250,101 @@
max-width: 100%;
}
+/*
+* Mixin that handles the container for the job logs (CI/CD and kubernetes pod logs)
+*/
+@mixin build-trace {
+ background: $black;
+ color: $gray-darkest;
+ white-space: pre;
+ overflow-x: auto;
+ font-size: 12px;
+ border-radius: 0;
+ border: 0;
+ padding: $grid-size;
+
+ .bash {
+ display: block;
+ }
+
+ &.build-trace-rounded {
+ border-radius: $border-radius-base;
+ }
+}
+
+@mixin build-trace-top-bar($height) {
+ height: $height;
+ min-height: $height;
+ background: $gray-light;
+ border: 1px solid $border-color;
+ color: $gl-text-color;
+ position: sticky;
+ position: -webkit-sticky;
+ top: $header-height;
+ padding: $grid-size;
+
+ .with-performance-bar & {
+ top: $header-height + $performance-bar-height;
+ }
+}
+
+/*
+* Mixin that handles the position of the controls placed on the top bar
+*/
+@mixin build-controllers($control-font-size, $flex-direction, $with-grow, $flex-grow-size, $svg-display: 'block', $svg-top: '2px') {
+ display: flex;
+ font-size: $control-font-size;
+ justify-content: $flex-direction;
+ align-items: center;
+ align-self: baseline;
+ @if $with-grow {
+ flex-grow: $flex-grow-size;
+ }
+
+ svg {
+ width: 15px;
+ height: 15px;
+ display: $svg-display;
+ fill: $gl-text-color;
+ top: $svg-top;
+ }
+
+ .controllers-buttons {
+ color: $gl-text-color;
+ margin: 0 $grid-size;
+
+ &:last-child {
+ margin-right: 0;
+ }
+ }
+
+ .btn-scroll.animate {
+ .first-triangle {
+ animation: blinking-scroll-button 1s ease infinite;
+ animation-delay: 0.3s;
+ }
+
+ .second-triangle {
+ animation: blinking-scroll-button 1s ease infinite;
+ animation-delay: 0.2s;
+ }
+
+ .third-triangle {
+ animation: blinking-scroll-button 1s ease infinite;
+ }
+
+ &:disabled {
+ opacity: 1;
+ }
+ }
+
+ .btn-scroll:disabled,
+ .btn-refresh:disabled {
+ opacity: 0.35;
+ cursor: not-allowed;
+ }
+}
+
@mixin build-loader-animation {
position: relative;
white-space: initial;
@@ -266,3 +374,59 @@
border-radius: 50%;
}
}
+
+@mixin emoji-menu-toggle-button {
+ line-height: 1;
+ padding: 0;
+ min-width: 16px;
+ color: $gray-darkest;
+ fill: $gray-darkest;
+
+ .fa {
+ position: relative;
+ font-size: 16px;
+ }
+
+ svg {
+ @include btn-svg;
+ margin: 0;
+ }
+
+ .award-control-icon-positive,
+ .award-control-icon-super-positive {
+ position: absolute;
+ top: 0;
+ left: 0;
+ opacity: 0;
+ }
+
+ &:hover,
+ &.is-active {
+ .danger-highlight {
+ color: $red-500;
+ }
+
+ .link-highlight {
+ color: $blue-600;
+ fill: $blue-600;
+ }
+
+ .award-control-icon-neutral {
+ opacity: 0;
+ }
+
+ .award-control-icon-positive {
+ opacity: 1;
+ }
+ }
+
+ &.is-active {
+ .award-control-icon-positive {
+ opacity: 0;
+ }
+
+ .award-control-icon-super-positive {
+ opacity: 1;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/framework/modal.scss b/app/assets/stylesheets/framework/modal.scss
index 7d53a631cdf..7e30747963a 100644
--- a/app/assets/stylesheets/framework/modal.scss
+++ b/app/assets/stylesheets/framework/modal.scss
@@ -19,6 +19,17 @@
}
}
+ // leave enough space for the close icon
+ .modal-title {
+ &.mw-100,
+ &.w-100 {
+ // after upgrading to Bootstrap 4.2 we can use $modal-header-padding-x here
+ // https://github.com/twbs/bootstrap/pull/26976
+ margin-right: -2rem;
+ padding-right: 2rem;
+ }
+ }
+
.page-title {
margin-top: 0;
}
@@ -59,7 +70,7 @@
}
@include media-breakpoint-up(sm) {
- .btn:first-of-type {
+ .btn:nth-child(1) {
margin-left: auto;
}
}
diff --git a/app/assets/stylesheets/framework/page_title.scss b/app/assets/stylesheets/framework/page_title.scss
new file mode 100644
index 00000000000..e8302953a63
--- /dev/null
+++ b/app/assets/stylesheets/framework/page_title.scss
@@ -0,0 +1,18 @@
+.page-title-holder {
+ @extend .d-flex;
+ @extend .align-items-center;
+
+ padding-top: $gl-padding-top;
+ border-bottom: 1px solid $border-color;
+
+ .page-title {
+ margin: $gl-padding 0;
+ font-size: 1.75em;
+ font-weight: $gl-font-weight-bold;
+ color: $gl-text-color;
+ }
+
+ .page-title-controls {
+ margin-left: auto;
+ }
+}
diff --git a/app/assets/stylesheets/framework/panels.scss b/app/assets/stylesheets/framework/panels.scss
index 5ca4d944d73..3a117106cff 100644
--- a/app/assets/stylesheets/framework/panels.scss
+++ b/app/assets/stylesheets/framework/panels.scss
@@ -53,8 +53,3 @@
margin-top: $gl-padding;
}
}
-
-.card-title {
- font-size: inherit;
- line-height: inherit;
-}
diff --git a/app/assets/stylesheets/framework/responsive_tables.scss b/app/assets/stylesheets/framework/responsive_tables.scss
index fc185ccfaad..29a9c076cdf 100644
--- a/app/assets/stylesheets/framework/responsive_tables.scss
+++ b/app/assets/stylesheets/framework/responsive_tables.scss
@@ -39,7 +39,7 @@
.table-section {
white-space: nowrap;
- $section-widths: 5 10 15 20 25 30 40 50 100;
+ $section-widths: 5 10 15 20 25 30 40 50 60 100;
@each $width in $section-widths {
&.section-#{$width} {
flex: 0 0 #{$width + '%'};
diff --git a/app/assets/stylesheets/framework/secondary_navigation_elements.scss b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
index 8bab8cf36b1..19640ab5986 100644
--- a/app/assets/stylesheets/framework/secondary_navigation_elements.scss
+++ b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
@@ -1,6 +1,6 @@
// For tabbed navigation links, scrolling tabs, etc. For all top/main navigation,
// please check nav.scss
-.nav-links {
+.nav-links:not(.quick-links) {
display: flex;
padding: 0;
margin: 0;
@@ -8,15 +8,17 @@
height: auto;
border-bottom: 1px solid $border-color;
- li {
+ li:not(.md-header-toolbar) {
display: flex;
- a {
+ a,
+ button {
padding: $gl-btn-padding;
padding-bottom: 11px;
font-size: 14px;
line-height: 28px;
color: $gl-text-color-secondary;
+ border: 0;
border-bottom: 2px solid transparent;
white-space: nowrap;
@@ -33,7 +35,13 @@
}
}
+ button {
+ padding-top: 0;
+ background-color: transparent;
+ }
+
&.active a,
+ &.active button,
a.active {
color: $black;
font-weight: $gl-font-weight-bold;
@@ -42,6 +50,10 @@
color: $black;
}
}
+
+ &.md-header-tab button {
+ line-height: 19px;
+ }
}
}
@@ -94,7 +106,7 @@
display: inline-block;
float: right;
text-align: right;
- padding: 11px 0;
+ padding: $gl-padding-8 0;
margin-bottom: 0;
> .btn,
@@ -146,6 +158,10 @@
width: 100%;
}
+ .dropdown-menu-toggle {
+ margin-bottom: 0;
+ }
+
form {
display: block;
height: auto;
diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss
index 381c0290d32..7f0edd88dfb 100644
--- a/app/assets/stylesheets/framework/selects.scss
+++ b/app/assets/stylesheets/framework/selects.scss
@@ -243,6 +243,8 @@
.user-result {
min-height: 24px;
+ display: flex;
+ align-items: center;
.user-image {
float: left;
diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss
index 339388392df..6954e6599b1 100644
--- a/app/assets/stylesheets/framework/tables.scss
+++ b/app/assets/stylesheets/framework/tables.scss
@@ -147,3 +147,9 @@ table {
}
}
}
+
+.top-area + .content-list {
+ th {
+ border-top: 0;
+ }
+}
diff --git a/app/assets/stylesheets/framework/terms.scss b/app/assets/stylesheets/framework/terms.scss
index 7cda674e5c8..3f4be8829d7 100644
--- a/app/assets/stylesheets/framework/terms.scss
+++ b/app/assets/stylesheets/framework/terms.scss
@@ -19,17 +19,12 @@
justify-content: space-between;
line-height: $line-height-base;
- .card-title {
+ .logo-text {
+ width: 55px;
+ height: 24px;
display: flex;
- align-items: center;
-
- .logo-text {
- width: 55px;
- height: 24px;
- display: flex;
- flex-direction: column;
- justify-content: center;
- }
+ flex-direction: column;
+ justify-content: center;
}
.navbar-collapse {
diff --git a/app/assets/stylesheets/framework/timeline.scss b/app/assets/stylesheets/framework/timeline.scss
index dfb145debe7..3d5208c3db5 100644
--- a/app/assets/stylesheets/framework/timeline.scss
+++ b/app/assets/stylesheets/framework/timeline.scss
@@ -1,7 +1,7 @@
.timeline {
- @include basic-list;
margin: 0;
padding: 0;
+ list-style: none;
&::before {
@include notes-media('max', map-get($grid-breakpoints, sm)) {
@@ -26,23 +26,11 @@
}
.timeline-entry {
- border-color: $white-normal;
color: $gl-text-color;
- border-bottom: 1px solid $border-white-light;
- background: $white-light;
+ background-color: $white-light;
.timeline-entry-inner {
position: relative;
-
- @include notes-media('max', map-get($grid-breakpoints, sm)) {
- .timeline-icon {
- display: none;
- }
-
- .timeline-content {
- margin-left: 0;
- }
- }
}
&:target,
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index 0c1b8b92de3..b3b99df5790 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -34,7 +34,7 @@
margin-bottom: 0;
}
- *:first-child:not(.katex-display) {
+ *:first-child {
margin-top: 0;
}
@@ -286,7 +286,7 @@ body {
}
.page-title {
- margin-top: $gl-padding;
+ margin: #{2 * $grid-size} 0;
line-height: 1.3;
font-size: 1.25em;
font-weight: $gl-font-weight-bold;
@@ -360,10 +360,6 @@ code {
font-size: 95%;
}
-.git-revision-dropdown-toggle {
- @extend .monospace;
-}
-
.git-revision-dropdown .dropdown-content ul li a {
@extend .ref-name;
}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index f66782ab882..bf2868710eb 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -10,6 +10,7 @@ $sidebar-breakpoint: 1024px;
$default-transition-duration: 0.15s;
$contextual-sidebar-width: 220px;
$contextual-sidebar-collapsed-width: 50px;
+$toggle-sidebar-height: 48px;
/*
* Color schema
@@ -55,7 +56,7 @@ $blue-50: #f6fafe;
$blue-100: #e4f0fb;
$blue-200: #b8d6f4;
$blue-300: #73afea;
-$blue-400: #2e87e0;
+$blue-400: #418cd8;
$blue-500: #1f78d1;
$blue-600: #1b69b6;
$blue-700: #17599c;
@@ -67,7 +68,7 @@ $orange-50: #fffaf4;
$orange-100: #fff1de;
$orange-200: #fed69f;
$orange-300: #fdbc60;
-$orange-400: #fca121;
+$orange-400: #fca429;
$orange-500: #fc9403;
$orange-600: #de7e00;
$orange-700: #c26700;
@@ -78,7 +79,7 @@ $orange-950: #592800;
$red-50: #fef6f5;
$red-100: #fbe5e1;
$red-200: #f2b4a9;
-$red-300: #e67664;
+$red-300: #ea8271;
$red-400: #e05842;
$red-500: #db3b21;
$red-600: #c0341d;
@@ -194,6 +195,8 @@ $well-light-text-color: #5b6169;
* Text
*/
$gl-font-size: 14px;
+$gl-font-size-xs: 11px;
+$gl-font-size-small: 12px;
$gl-font-weight-normal: 400;
$gl-font-weight-bold: 600;
$gl-text-color: #2e2e2e;
@@ -240,6 +243,7 @@ $gl-padding-top: 10px;
$gl-sidebar-padding: 22px;
$gl-bar-padding: 3px;
$input-horizontal-padding: 12px;
+$browserScrollbarSize: 10px;
/*
* Misc
@@ -267,6 +271,8 @@ $flash-height: 52px;
$context-header-height: 60px;
$breadcrumb-min-height: 48px;
$project-title-row-height: 24px;
+$gl-line-height: 16px;
+$gl-line-height-24: 24px;
/*
* Common component specific colors
@@ -314,7 +320,8 @@ $diff-jagged-border-gradient-color: darken($white-normal, 8%);
$monospace-font: 'Menlo', 'DejaVu Sans Mono', 'Liberation Mono', 'Consolas', 'Ubuntu Mono',
'Courier New', 'andale mono', 'lucida console', monospace;
$regular-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell,
- 'Helvetica Neue', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
+ 'Helvetica Neue', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
+ 'Noto Color Emoji';
/*
* Dropdowns
@@ -436,7 +443,7 @@ $ci-skipped-color: #888;
* Boards
*/
$issue-boards-font-size: 14px;
-$issue-boards-card-shadow: rgba(186, 186, 186, 0.5);
+$issue-boards-card-shadow: rgba(0, 0, 0, 0.1);
/*
The following heights are used in boards.scss and are used for calculation of the board height.
They probably should be derived in a smarter way.
@@ -604,6 +611,7 @@ $perf-bar-development: #4c1210;
$perf-bar-bucket-bg: #111;
$perf-bar-bucket-box-shadow-from: rgba($white-light, 0.2);
$perf-bar-bucket-box-shadow-to: rgba($black, 0.25);
+$perf-bar-canary-text: $orange-400;
/*
Issuable warning
@@ -634,5 +642,9 @@ Modals
*/
$modal-body-height: 134px;
-
$priority-label-empty-state-width: 114px;
+
+/*
+Issues Analytics
+*/
+$issues-analytics-popover-boarder-color: rgba(0, 0, 0, 0.15);
diff --git a/app/assets/stylesheets/framework/variables_overrides.scss b/app/assets/stylesheets/framework/variables_overrides.scss
index 7d90452e1f4..759b4f333ca 100644
--- a/app/assets/stylesheets/framework/variables_overrides.scss
+++ b/app/assets/stylesheets/framework/variables_overrides.scss
@@ -18,3 +18,4 @@ $success: $green-500;
$info: $blue-500;
$warning: $orange-500;
$danger: $red-500;
+$zindex-modal-backdrop: 1040;
diff --git a/app/assets/stylesheets/page_bundles/ide.scss b/app/assets/stylesheets/page_bundles/ide.scss
index 65f0a0d18e2..07d82e984ba 100644
--- a/app/assets/stylesheets/page_bundles/ide.scss
+++ b/app/assets/stylesheets/page_bundles/ide.scss
@@ -517,21 +517,6 @@ $ide-commit-header-height: 48px;
}
}
-.ide-file-addition,
-.ide-file-addition-solid {
- color: $green-500;
-}
-
-.ide-file-modified,
-.ide-file-modified-solid {
- color: $orange-500;
-}
-
-.ide-file-deletion,
-.ide-file-deletion-solid {
- color: $red-500;
-}
-
.multi-file-commit-list-collapsed {
display: flex;
flex-direction: column;
@@ -1399,14 +1384,6 @@ $ide-commit-header-height: 48px;
color: $theme-gray-700;
}
-.ide-file-changed-icon {
- margin-left: auto;
-
- > svg {
- display: block;
- }
-}
-
.file-row:hover,
.file-row:focus {
.ide-new-btn {
diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss
index 69d7de886b4..c6074eb9df4 100644
--- a/app/assets/stylesheets/pages/boards.scss
+++ b/app/assets/stylesheets/pages/boards.scss
@@ -90,20 +90,14 @@
}
.with-performance-bar & {
- height: calc(
- 100vh - #{$issue-board-list-difference-xs} - #{$performance-bar-height}
- );
+ height: calc(100vh - #{$issue-board-list-difference-xs} - #{$performance-bar-height});
@include media-breakpoint-only(sm) {
- height: calc(
- 100vh - #{$issue-board-list-difference-sm} - #{$performance-bar-height}
- );
+ height: calc(100vh - #{$issue-board-list-difference-sm} - #{$performance-bar-height});
}
@include media-breakpoint-up(md) {
- height: calc(
- 100vh - #{$issue-board-list-difference-md} - #{$performance-bar-height}
- );
+ height: calc(100vh - #{$issue-board-list-difference-md} - #{$performance-bar-height});
}
}
}
@@ -136,15 +130,23 @@
right: 0;
bottom: 0;
left: 0;
+
+ button {
+ display: none;
+ }
}
.board-title {
padding: 0;
border-bottom: 0;
+ justify-content: center;
> span {
+ width: 100%;
+ margin-top: -12px;
display: block;
- transform: rotate(90deg) translate(35px, 10px);
+ transform: rotate(90deg) translate(35px, 0);
+ overflow: initial;
}
}
@@ -263,9 +265,9 @@
height: 100%;
width: 100%;
margin-bottom: 0;
- padding: 5px;
+ padding: $gl-padding-4;
list-style: none;
- overflow-y: scroll;
+ overflow-y: auto;
overflow-x: hidden;
}
@@ -276,14 +278,16 @@
.board-card {
position: relative;
- padding: 11px 10px 11px $gl-padding;
+ padding: $gl-padding;
background: $white-light;
border-radius: $border-radius-default;
+ border: 1px solid $theme-gray-200;
box-shadow: 0 1px 2px $issue-boards-card-shadow;
list-style: none;
+ line-height: $gl-padding;
&:not(:last-child) {
- margin-bottom: 5px;
+ margin-bottom: $gl-padding-8;
}
&.is-active,
@@ -294,114 +298,120 @@
.badge {
border: 0;
outline: 0;
+
+ &:hover {
+ text-decoration: underline;
+ }
+
+ @include media-breakpoint-down(lg) {
+ font-size: $gl-font-size-xs;
+ padding-left: $gl-padding-4;
+ padding-right: $gl-padding-4;
+ font-weight: $gl-font-weight-bold;
+ }
+ }
+
+ svg {
+ vertical-align: top;
}
.confidential-icon {
- position: relative;
- top: 1px;
- margin-right: 5px;
+ color: $orange-600;
+ cursor: help;
+ }
+
+ @include media-breakpoint-down(md) {
+ padding: $gl-padding-8;
}
}
.board-card-title {
@include overflow-break-word();
- margin: 0 30px 0 0;
font-size: 1em;
- line-height: inherit;
a {
color: $gl-text-color;
- margin-right: 2px;
+ }
+
+ @include media-breakpoint-down(md) {
+ font-size: $label-font-size;
}
}
.board-card-header {
display: flex;
- min-height: 20px;
-
- .board-card-assignee {
- display: flex;
- justify-content: flex-end;
- position: absolute;
- right: 15px;
- height: 20px;
- width: 20px;
+}
- .avatar-counter {
- display: none;
- vertical-align: middle;
- min-width: 20px;
- line-height: 19px;
- height: 20px;
- padding-left: 2px;
- padding-right: 2px;
- border-radius: 2em;
- }
+.board-card-assignee {
+ display: flex;
+ margin-top: -$gl-padding-4;
+ margin-bottom: -$gl-padding-4;
+
+ .avatar-counter {
+ vertical-align: middle;
+ line-height: $gl-padding-24;
+ min-width: $gl-padding-24;
+ height: $gl-padding-24;
+ border-radius: $gl-padding-24;
+ background-color: $gl-text-color-tertiary;
+ font-size: $gl-font-size-xs;
+ cursor: help;
+ font-weight: $gl-font-weight-bold;
+ margin-left: -$gl-padding-4;
+ border: 0;
+ padding: 0 $gl-padding-4;
- img {
- vertical-align: top;
+ @include media-breakpoint-down(md) {
+ min-width: auto;
+ height: $gl-padding;
+ border-radius: $gl-padding;
+ line-height: $gl-padding;
}
+ }
- a {
- position: relative;
- margin-left: -15px;
- }
+ img {
+ vertical-align: top;
+ }
- a:nth-child(1) {
- z-index: 3;
- }
+ .user-avatar-link:not(:only-child) {
+ margin-left: -$gl-padding-4;
- a:nth-child(2) {
+ &:nth-of-type(1) {
z-index: 2;
}
- a:nth-child(3) {
+ &:nth-of-type(2) {
z-index: 1;
}
+ }
- a:nth-child(4) {
- display: none;
- }
-
- &:hover {
- .avatar-counter {
- display: inline-block;
- }
-
- a {
- position: static;
- background-color: $white-light;
- transition: background-color 0s;
- margin-left: auto;
-
- &:nth-child(4) {
- display: block;
- }
+ .avatar {
+ margin: 0;
- &:first-child:not(:only-child) {
- box-shadow: -10px 0 10px 1px $white-light;
- }
- }
+ @include media-breakpoint-down(md) {
+ width: $gl-padding;
+ height: $gl-padding;
}
}
- .avatar {
- margin: 0;
+ @include media-breakpoint-down(md) {
+ margin-top: 0;
+ margin-bottom: 0;
}
}
-.board-card-footer {
- margin: 0 0 5px;
+.board-card-number {
+ font-size: $gl-font-size-xs;
+ color: $gl-text-color-secondary;
+ overflow: hidden;
- .badge {
- margin-top: 5px;
- margin-right: 6px;
+ @include media-breakpoint-up(md) {
+ font-size: $label-font-size;
}
}
-.board-card-number {
- font-size: 12px;
- color: $gl-text-color-secondary;
+.board-card-number-container {
+ overflow: hidden;
}
.issue-boards-search {
@@ -467,8 +477,7 @@
.right-sidebar.right-sidebar-expanded {
&.boards-sidebar-slide-enter-active,
&.boards-sidebar-slide-leave-active {
- transition: width $sidebar-transition-duration,
- padding $sidebar-transition-duration;
+ transition: width $sidebar-transition-duration, padding $sidebar-transition-duration;
}
&.boards-sidebar-slide-enter,
@@ -643,3 +652,36 @@
}
}
}
+
+.board-card-info {
+ color: $gl-text-color-secondary;
+ white-space: nowrap;
+ margin-right: $gl-padding-8;
+
+ &:not(.board-card-weight) {
+ cursor: help;
+ }
+
+ &.board-card-weight {
+ color: $gl-text-color;
+ cursor: pointer;
+
+ &:hover {
+ color: initial;
+ text-decoration: underline;
+ }
+ }
+
+ .board-card-info-icon {
+ color: $theme-gray-600;
+ margin-right: $gl-padding-4;
+ }
+
+ @include media-breakpoint-down(md) {
+ font-size: $label-font-size;
+ }
+}
+
+.board-issue-path.js-show-tooltip {
+ cursor: help;
+}
diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss
index 14ba8b1df83..81cb519883b 100644
--- a/app/assets/stylesheets/pages/builds.scss
+++ b/app/assets/stylesheets/pages/builds.scss
@@ -50,35 +50,33 @@
position: relative;
}
- .build-trace {
- background: $black;
- color: $gray-darkest;
- white-space: pre;
- overflow-x: auto;
- font-size: 12px;
- border-radius: 0;
- border: 0;
- padding: $grid-size;
- .bash {
- display: block;
- }
+ .build-trace {
+ @include build-trace();
+ }
- &.build-trace-rounded {
- border-radius: $border-radius-base;
+ .archived-sticky {
+ top: $header-height;
+ border-radius: 2px 2px 0 0;
+ color: $orange-600;
+ background-color: $orange-100;
+ border: 1px solid $border-gray-normal;
+ border-bottom: 0;
+ padding: 3px 12px;
+ margin: auto;
+ align-items: center;
+
+ .with-performance-bar & {
+ top: $header-height + $performance-bar-height;
}
}
.top-bar {
- height: 35px;
- min-height: 35px;
- background: $gray-light;
- border: 1px solid $border-color;
- color: $gl-text-color;
- position: sticky;
- position: -webkit-sticky;
- top: $header-height;
- padding: $grid-size;
+ @include build-trace-top-bar(35px);
+
+ &.has-archived-block {
+ top: $header-height + $performance-bar-height + 28px;
+ }
&.affix {
top: $header-height;
@@ -116,50 +114,7 @@
}
.controllers {
- display: flex;
- font-size: 15px;
- justify-content: center;
- align-items: center;
-
- svg {
- height: 15px;
- display: block;
- fill: $gl-text-color;
- }
-
- .controllers-buttons {
- color: $gl-text-color;
- margin: 0 $grid-size;
-
- &:last-child {
- margin-right: 0;
- }
- }
-
- .btn-scroll.animate {
- .first-triangle {
- animation: blinking-scroll-button 1s ease infinite;
- animation-delay: 0.3s;
- }
-
- .second-triangle {
- animation: blinking-scroll-button 1s ease infinite;
- animation-delay: 0.2s;
- }
-
- .third-triangle {
- animation: blinking-scroll-button 1s ease infinite;
- }
-
- &:disabled {
- opacity: 1;
- }
- }
-
- .btn-scroll:disabled {
- opacity: 0.35;
- cursor: not-allowed;
- }
+ @include build-controllers(15px, center, false, 0, inline, 0);
}
}
@@ -179,16 +134,13 @@
.build-loader-animation {
@include build-loader-animation;
+ float: left;
}
}
.with-performance-bar .build-page {
- .top-bar {
+ .top-bar.affix {
top: $header-height + $performance-bar-height;
-
- &.affix {
- top: $header-height + $performance-bar-height;
- }
}
}
@@ -328,23 +280,6 @@
}
}
- .build-dropdown {
- margin: $gl-padding 0;
- padding: 0;
-
- .dropdown-menu-toggle {
- margin-top: #{$gl-padding / 2};
- }
-
- svg {
- position: relative;
- top: 3px;
- margin-right: 3px;
- width: 14px;
- height: 14px;
- }
- }
-
.builds-container {
background-color: $white-light;
border-top: 1px solid $border-color;
@@ -381,15 +316,11 @@
position: absolute;
left: 15px;
top: 20px;
- display: none;
+ display: block;
}
&.active {
font-weight: $gl-font-weight-bold;
-
- .icon-arrow-right {
- display: block;
- }
}
&.retried {
diff --git a/app/assets/stylesheets/pages/clusters.scss b/app/assets/stylesheets/pages/clusters.scss
index 71a3fd544f2..ad12cd101b6 100644
--- a/app/assets/stylesheets/pages/clusters.scss
+++ b/app/assets/stylesheets/pages/clusters.scss
@@ -25,6 +25,12 @@
.cluster-application-row {
border-bottom: 1px solid $border-color;
padding: $gl-padding;
+
+ &:last-child {
+ border-bottom: 0;
+ border-bottom-left-radius: calc(#{$border-radius-default} - 1px);
+ border-bottom-right-radius: calc(#{$border-radius-default} - 1px);
+ }
}
}
@@ -73,6 +79,10 @@
padding: $gl-padding-top $gl-padding;
}
+ .card {
+ margin-bottom: $gl-vert-padding;
+ }
+
.empty-state .svg-content img {
width: 145px;
}
@@ -80,6 +90,31 @@
.top-area .nav-controls > .btn.btn-add-cluster {
margin-right: 0;
}
+
+ .clusters-table {
+ background-color: $gray-light;
+ padding: $gl-padding-8;
+ }
+
+ .badge-light {
+ background-color: $white-normal;
+ }
+
+ .gl-responsive-table-row {
+ padding: $gl-padding;
+ border: 0;
+
+ &.table-row-header {
+ background-color: none;
+ border: 0;
+ font-weight: bold;
+ color: $gl-gray-500;
+ }
+ }
+}
+
+.cluster-warning {
+ @include alert-variant(theme-color-level('warning', $alert-bg-level), theme-color-level('warning', $alert-border-level), theme-color-level('warning', $alert-color-level));
}
.gcp-signup-offer {
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index 10764e0f3df..11966931a6c 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -59,7 +59,7 @@
vertical-align: middle;
.stage-cell .stage-container {
- margin: 3px 3px 3px 0;
+ margin: 0 3px 3px 0;
}
.stage-container:last-child {
@@ -223,6 +223,7 @@
}
}
+.clipboard-group,
.commit-sha-group {
display: inline-flex;
diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss
index f0228768b5a..ec2108b15be 100644
--- a/app/assets/stylesheets/pages/cycle_analytics.scss
+++ b/app/assets/stylesheets/pages/cycle_analytics.scss
@@ -21,7 +21,7 @@
}
}
- svg {
+ .svg-container svg {
width: 136px;
height: 136px;
}
diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss
index 987dcd32e3a..5405f20a760 100644
--- a/app/assets/stylesheets/pages/diff.scss
+++ b/app/assets/stylesheets/pages/diff.scss
@@ -6,6 +6,38 @@
.file-title-flex-parent {
cursor: pointer;
+ @media (min-width: map-get($grid-breakpoints, md)) {
+ position: -webkit-sticky;
+ position: sticky;
+ top: 92px;
+ margin-left: -1px;
+ border-left: 1px solid $border-color;
+ z-index: 102;
+
+ &.is-commit {
+ top: $header-height + 36px;
+
+ .with-performance-bar & {
+ top: $header-height + 36px + $performance-bar-height;
+ }
+ }
+
+ &::before {
+ content: '';
+ position: absolute;
+ top: -1px;
+ left: -11px;
+ width: 10px;
+ height: calc(100% + 1px);
+ background: $white-light;
+ pointer-events: none;
+ }
+
+ .with-performance-bar & {
+ top: 127px;
+ }
+ }
+
a:hover {
text-decoration: none;
}
@@ -59,6 +91,7 @@
margin: 0;
padding: 0;
table-layout: fixed;
+ border-radius: 0 0 $border-radius-default $border-radius-default;
.diff-line-num {
width: 50px;
@@ -252,19 +285,6 @@
right: 7px;
}
- .frame {
- top: 0;
- right: 0;
- position: absolute;
-
- &.deleted {
- margin: 0;
- display: block;
- top: 13px;
- right: 7px;
- }
- }
-
.swipe-bar {
display: block;
height: 100%;
@@ -421,28 +441,20 @@
.diff-file-container {
.frame.deleted {
- border: 0;
+ border: 1px solid $deleted;
background-color: inherit;
-
- .image_file img {
- border: 1px solid $deleted;
- }
}
.frame.added {
- border: 0;
+ border: 1px solid $added;
background-color: inherit;
-
- .image_file img {
- border: 1px solid $added;
- }
}
.swipe.view,
.onion-skin.view {
.swipe-wrap {
top: 0;
- right: 0;
+ left: 0;
}
.frame.deleted {
@@ -481,6 +493,11 @@
bottom: -25px;
}
}
+
+ .discussion-notes .discussion-notes {
+ margin-left: 0;
+ border-left: 0;
+ }
}
.file-content .diff-file {
@@ -571,8 +588,6 @@
}
.files {
- margin-top: 1px;
-
.diff-file:last-child {
margin-bottom: 0;
}
@@ -696,15 +711,14 @@
}
@include media-breakpoint-up(sm) {
- top: 24px;
+ position: -webkit-sticky;
+ position: sticky;
+ top: $header-height;
background-color: $white-light;
+ z-index: 200;
- &.diff-files-changed-merge-request {
- position: sticky;
- top: 90px;
- z-index: 200;
- margin: $gl-padding 0;
- padding: 0;
+ .with-performance-bar & {
+ top: $header-height + $performance-bar-height;
}
&.is-stuck {
@@ -729,14 +743,6 @@
}
}
-@include media-breakpoint-up(sm) {
- .with-performance-bar {
- .diff-files-changed.diff-files-changed-merge-request {
- top: 76px + $performance-bar-height;
- }
- }
-}
-
.diff-file-changes {
max-width: 560px;
width: 100%;
@@ -806,7 +812,7 @@
// double jagged line divider
.discussion-notes + .discussion-notes::before,
- .discussion-notes + .discussion-form::before {
+ .diff-file-discussions + .discussion-form::before {
content: '';
position: relative;
display: block;
@@ -846,6 +852,17 @@
background-repeat: repeat;
}
+ .diff-file-discussions + .discussion-form {
+ padding: $gl-padding;
+
+ &::before {
+ width: auto;
+ margin-left: -$gl-padding;
+ margin-right: -$gl-padding;
+ margin-bottom: $gl-padding;
+ }
+ }
+
.notes {
position: relative;
}
@@ -857,7 +874,7 @@
}
.diff-file .note-container > .new-note,
-.note-container .discussion-notes {
+.note-container .discussion-notes.diff-discussions {
margin-left: 100px;
border-left: 1px solid $white-normal;
}
@@ -872,11 +889,13 @@
}
}
-.files:not([data-can-create-note]) .frame {
+.files:not([data-can-create-note="true"]) .frame {
cursor: auto;
}
-.frame.click-to-comment {
+.frame,
+.frame.click-to-comment,
+.btn-transparent.image-diff-overlay-add-comment {
position: relative;
cursor: image-url('illustrations/image_comment_light_cursor.svg')
$image-comment-cursor-left-offset $image-comment-cursor-top-offset,
@@ -912,6 +931,7 @@
.frame .badge.badge-pill,
.image-diff-avatar-link .badge.badge-pill,
+.user-avatar-link .badge.badge-pill,
.notes > .badge.badge-pill {
position: absolute;
background-color: $blue-400;
@@ -946,7 +966,8 @@
}
}
-.image-diff-avatar-link {
+.image-diff-avatar-link,
+.user-avatar-link {
position: relative;
.badge.badge-pill,
@@ -987,3 +1008,102 @@
.discussion-body .image .frame {
position: relative;
}
+
+.diff-tree-list {
+ width: 320px;
+}
+
+.diff-files-holder {
+ flex: 1;
+ min-width: 0;
+}
+
+.compare-versions-container {
+ min-width: 0;
+}
+
+.tree-list-holder {
+ position: -webkit-sticky;
+ position: sticky;
+ top: 100px;
+ max-height: calc(100vh - 100px);
+ padding-right: $gl-padding;
+
+ .file-row {
+ margin-left: 0;
+ margin-right: 0;
+ }
+
+ .with-performance-bar & {
+ top: 135px;
+ max-height: calc(100vh - 135px);
+ }
+}
+
+.tree-list-scroll {
+ max-height: 100%;
+ padding-top: $grid-size;
+ padding-bottom: $grid-size;
+ border-top: 1px solid $border-color;
+ border-bottom: 1px solid $border-color;
+ overflow-y: scroll;
+ overflow-x: auto;
+}
+
+.tree-list-search {
+ flex: 0 0 34px;
+
+ .form-control {
+ padding-left: 30px;
+ }
+}
+
+.tree-list-icon {
+ top: 50%;
+ left: 10px;
+ transform: translateY(-50%);
+
+ &,
+ svg {
+ fill: $gl-text-color-tertiary;
+ }
+}
+
+.tree-list-clear-icon {
+ right: 10px;
+ left: auto;
+ line-height: 0;
+}
+
+@media (max-width: map-get($grid-breakpoints, md)-1) {
+ .diffs .files {
+ @include fixed-width-container;
+ flex-direction: column;
+
+ .diff-tree-list {
+ width: 100%;
+ }
+
+ .tree-list-holder {
+ max-height: calc(50px + 50vh);
+ padding-right: 0;
+ }
+ }
+}
+
+.tree-list-view-toggle {
+ svg {
+ top: 0;
+ }
+}
+
+.image-diff-overlay,
+.image-diff-overlay-add-comment {
+ top: 0;
+ left: 0;
+
+ &:active,
+ &:focus {
+ outline: 0;
+ }
+}
diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss
index 04570c057d1..f46ff360496 100644
--- a/app/assets/stylesheets/pages/editor.scss
+++ b/app/assets/stylesheets/pages/editor.scss
@@ -32,7 +32,6 @@
.file-title {
@extend .monospace;
-
line-height: 35px;
padding-top: 7px;
padding-bottom: 7px;
@@ -48,13 +47,6 @@
margin-right: 10px;
}
- .editor-file-name {
- @extend .monospace;
-
- float: left;
- margin-right: 10px;
- }
-
.new-file-name {
display: inline-block;
max-width: 420px;
diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss
index 79984c1a546..75166ffcada 100644
--- a/app/assets/stylesheets/pages/environments.scss
+++ b/app/assets/stylesheets/pages/environments.scss
@@ -44,11 +44,6 @@
margin: 0;
}
- .icon-play {
- height: 13px;
- width: 12px;
- }
-
.external-url,
.dropdown-new {
color: $gl-text-color-secondary;
@@ -90,6 +85,7 @@
margin-right: 3px;
color: $gl-text-color-secondary;
display: inline-block;
+ vertical-align: text-top;
.fa:nth-child(1) {
margin-right: 3px;
@@ -207,21 +203,6 @@
stroke: $gray-darkest;
}
-.prometheus-state {
- max-width: 460px;
- margin: 10px auto;
- text-align: center;
-
- .state-svg {
- max-width: 80vw;
- margin: 0 auto;
- }
-
- .state-button {
- padding: $gl-padding / 2;
- }
-}
-
.prometheus-graphs {
.environments {
.dropdown-menu-toggle {
@@ -365,7 +346,7 @@
}
.arrow-shadow {
- content: "";
+ content: '';
position: absolute;
width: 7px;
height: 7px;
diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss
index a91d44805ee..618f23d81b1 100644
--- a/app/assets/stylesheets/pages/events.scss
+++ b/app/assets/stylesheets/pages/events.scss
@@ -4,41 +4,29 @@
*/
.event-item {
font-size: $gl-font-size;
- padding: $gl-padding-top 0 $gl-padding-top 40px;
+ padding: $gl-padding 0 $gl-padding 56px;
border-bottom: 1px solid $white-normal;
- color: $gl-text-color;
+ color: $gl-text-color-secondary;
position: relative;
-
- &.event-inline {
- .system-note-image {
- top: 20px;
- }
-
- .user-avatar {
- top: 14px;
- }
-
- .event-title,
- .event-item-timestamp {
- line-height: 40px;
- }
- }
-
- a {
- color: $gl-text-color;
- }
+ line-height: $gl-line-height;
.system-note-image {
position: absolute;
left: 0;
- top: 14px;
svg {
- width: 20px;
- height: 20px;
fill: $gl-text-color-secondary;
}
+ }
+
+ .system-note-image-inline {
+ svg {
+ fill: $gl-text-color-secondary;
+ }
+ }
+ .system-note-image,
+ .system-note-image-inline {
&.opened-icon,
&.created-icon {
svg {
@@ -53,16 +41,35 @@
&.accepted-icon svg {
fill: $blue-300;
}
+
+ &.commented-on-icon svg {
+ fill: $blue-600;
+ }
+ }
+
+ .event-user-info {
+ margin-bottom: $gl-padding-8;
+
+ .author_name {
+ a {
+ color: $gl-text-color;
+ font-weight: $gl-font-weight-bold;
+ }
+ }
}
.event-title {
- @include str-truncated(calc(100% - 174px));
- font-weight: $gl-font-weight-bold;
- color: $gl-text-color;
+ .event-type {
+ &::first-letter {
+ text-transform: capitalize;
+ }
+ }
}
.event-body {
+ margin-top: $gl-padding-8;
margin-right: 174px;
+ color: $gl-text-color;
.event-note {
word-wrap: break-word;
@@ -92,7 +99,7 @@
}
.note-image-attach {
- margin-top: 4px;
+ margin-top: $gl-padding-4;
margin-left: 0;
max-width: 200px;
float: none;
@@ -107,7 +114,6 @@
color: $gl-gray-500;
float: left;
font-size: $gl-font-size;
- line-height: 16px;
margin-right: 5px;
}
}
@@ -127,7 +133,9 @@
}
}
- &:last-child { border: 0; }
+ &:last-child {
+ border: 0;
+ }
.event_commits {
li {
@@ -154,7 +162,6 @@
.event-item-timestamp {
float: right;
- line-height: 22px;
}
}
@@ -177,10 +184,8 @@
.event-item {
padding-left: 0;
- &.event-inline {
- .event-title {
- line-height: 20px;
- }
+ .event-user-info {
+ margin-bottom: $gl-padding-4;
}
.event-title {
@@ -194,7 +199,8 @@
}
.event-body {
- margin: 0;
+ margin-top: $gl-padding-4;
+ margin-right: 0;
padding-left: 0;
}
diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss
index fe792a53b44..f0cb81e0bc3 100644
--- a/app/assets/stylesheets/pages/groups.scss
+++ b/app/assets/stylesheets/pages/groups.scss
@@ -191,7 +191,7 @@
}
}
- svg {
+ .svg-container svg {
width: 62px;
height: 50px;
}
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index 62a9f97caa9..5b5f486ea63 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -1,33 +1,27 @@
// Limit MR description for side-by-side diff view
.fixed-width-container {
- max-width: $limited-layout-width - ($gl-padding * 2);
- margin-left: auto;
- margin-right: auto;
+ @include fixed-width-container;
}
.issuable-warning-icon {
background-color: $orange-100;
border-radius: $border-radius-default;
- margin: 0 $btn-side-margin 0 0;
width: $issuable-warning-size;
height: $issuable-warning-size;
text-align: center;
+ margin-right: $issuable-warning-icon-margin;
+ line-height: $gl-line-height-24;
.icon {
fill: $orange-600;
vertical-align: text-bottom;
}
-
- &:first-of-type {
- margin-right: $issuable-warning-icon-margin;
- }
}
.limit-container-width {
.detail-page-header,
.page-content-header,
.commit-box,
- .info-well,
.commit-ci-menu,
.files-changed-inner,
.limited-header-width,
@@ -49,12 +43,6 @@
@extend .fixed-width-container;
}
}
-
- .diffs {
- .mr-version-controls {
- @extend .fixed-width-container;
- }
- }
}
.issuable-details {
@@ -697,7 +685,6 @@
flex: 1;
display: inline-block;
font-size: 14px;
- line-height: 24px;
align-self: center;
overflow: hidden;
text-overflow: ellipsis;
@@ -735,6 +722,10 @@
.issuable-main-info {
flex: 1 auto;
margin-right: 10px;
+
+ .issue-weight-icon {
+ vertical-align: sub;
+ }
}
.issuable-meta {
@@ -947,3 +938,37 @@
}
}
}
+
+.issuable-suggestions svg {
+ vertical-align: sub;
+}
+
+.suggestion-item a {
+ color: initial;
+}
+
+.suggestion-confidential {
+ color: $orange-600;
+}
+
+.suggestion-state-open {
+ color: $green-500;
+}
+
+.suggestion-state-closed {
+ color: $blue-500;
+}
+
+.suggestion-help-hover {
+ cursor: help;
+}
+
+.suggestion-footer {
+ font-size: 12px;
+ line-height: 15px;
+
+ .avatar {
+ margin-top: -3px;
+ border: 0;
+ }
+}
diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss
index 0f95fb911e1..8ea34f5d19d 100644
--- a/app/assets/stylesheets/pages/issues.scss
+++ b/app/assets/stylesheets/pages/issues.scss
@@ -185,7 +185,17 @@ ul.related-merge-requests > li {
}
.new-branch-col {
- padding-top: 10px;
+ font-size: 0;
+
+ .discussion-filter-container {
+ &:not(:only-child) {
+ margin-right: $gl-padding-8;
+ }
+
+ @include media-breakpoint-down(md) {
+ margin-top: $gl-padding-8;
+ }
+ }
}
.create-mr-dropdown-wrap {
@@ -205,6 +215,10 @@ ul.related-merge-requests > li {
.btn-group:not(.hidden) {
display: flex;
+
+ @include media-breakpoint-down(md) {
+ margin-top: $gl-padding-8;
+ }
}
.js-create-merge-request {
@@ -251,7 +265,6 @@ ul.related-merge-requests > li {
.new-branch-col {
padding-top: 0;
- text-align: right;
align-self: center;
}
@@ -262,3 +275,9 @@ ul.related-merge-requests > li {
}
}
}
+
+@include media-breakpoint-up(lg) {
+ .new-branch-col {
+ text-align: right;
+ }
+}
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 97b131687d3..221b4e934ff 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -47,13 +47,22 @@
}
}
-
.mr-widget-heading {
position: relative;
border: 1px solid $border-color;
- border-radius: 4px;
+ border-radius: $border-radius-default;
+}
+
+.mr-widget-extension {
+ border-top: 1px solid $border-color;
+ background-color: $gray-light;
+}
+
+.mr-widget-workflow {
+ margin-top: $gl-padding;
+ position: relative;
- &:not(.deploy-heading)::before {
+ &::before {
content: '';
border-left: 1px solid $theme-gray-200;
position: absolute;
@@ -69,8 +78,8 @@
border-top: 0;
}
-.mr-widget-heading,
.mr-widget-section,
+.mr-widget-content,
.mr-widget-footer {
padding: $gl-padding;
}
@@ -201,7 +210,6 @@
.mr-widget-icon {
font-size: 22px;
- margin-right: $gl-btn-padding;
}
.ci-status-icon svg {
@@ -455,7 +463,7 @@
.mr-list {
.merge-request {
- padding: 10px 0 10px 15px;
+ padding: 10px 0 10px 15px;
position: relative;
display: -webkit-flex;
display: flex;
@@ -469,7 +477,6 @@
margin-bottom: 2px;
.ci-status-link {
-
svg {
height: 16px;
width: 16px;
@@ -563,19 +570,6 @@
color: $gl-text-color;
}
- .git-merge-icon-container {
- border: 1px solid $theme-gray-400;
- border-radius: 50%;
- height: 32px;
- width: 32px;
- color: $theme-gray-700;
- line-height: 28px;
-
- .ic-git-merge {
- vertical-align: middle;
- width: 31px;
- }
- }
.git-merge-container {
justify-content: space-between;
@@ -699,7 +693,6 @@
.table-holder {
.ci-table {
-
th {
background-color: $white-light;
color: $gl-text-color-secondary;
@@ -721,8 +714,20 @@
.mr-version-menus-container {
display: flex;
align-items: center;
+ flex-wrap: wrap;
padding: 16px;
z-index: 199;
+ white-space: nowrap;
+
+ .dropdown-menu-toggle {
+ width: auto;
+ max-width: 170px;
+
+ svg {
+ top: 10px;
+ right: 8px;
+ }
+ }
}
.content-block {
@@ -765,7 +770,7 @@
&.affix {
left: 0;
- transition: right .15s;
+ transition: right 0.15s;
@include media-breakpoint-down(xs) {
right: 0;
@@ -811,9 +816,17 @@
display: flex;
justify-content: space-between;
- @include media-breakpoint-down(xs) {
+ @include media-breakpoint-down(md) {
flex-direction: column-reverse;
}
+
+ .discussion-filter-container {
+ margin-top: $gl-padding-8;
+
+ &:not(:only-child) {
+ padding-right: $gl-padding-8;
+ }
+ }
}
.limit-container-width:not(.container-limited) {
@@ -838,11 +851,6 @@
}
.deploy-heading {
- margin-top: -19px;
- border-top-left-radius: 0;
- border-top-right-radius: 0;
- background-color: $gray-light;
-
@include media-breakpoint-up(md) {
padding: $gl-padding-8 $gl-padding;
}
@@ -852,6 +860,10 @@
font-size: 12px;
margin-left: 48px;
}
+
+ &:not(:last-child) {
+ border-bottom: 1px solid $border-color;
+ }
}
.deploy-body {
@@ -874,7 +886,7 @@
}
> *:not(:last-child) {
- margin-right: .3em;
+ margin-right: 0.3em;
}
svg {
@@ -897,6 +909,10 @@
.btn svg {
fill: $theme-gray-700;
}
+
+ .dropdown-menu {
+ width: 400px;
+ }
}
// Hack alert: we've rewritten `btn` class in a way that
@@ -907,7 +923,7 @@
&[disabled] {
cursor: not-allowed;
box-shadow: none;
- opacity: .65;
+ opacity: 0.65;
&:hover {
color: $gl-gray-500;
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index 4268e194ed7..97b3f696139 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -176,8 +176,10 @@
background-color: $white-light;
}
-.discussion-form-container {
- padding: $gl-padding-top $gl-padding $gl-padding;
+table {
+ .discussion-form-container {
+ padding: $gl-padding-top $gl-padding $gl-padding;
+ }
}
.discussion-notes .disabled-comment {
@@ -239,6 +241,7 @@
.discussion-reply-holder {
background-color: $white-light;
padding: 10px 16px;
+ border-radius: 0 0 3px 3px;
&.is-replying {
padding-bottom: $gl-padding;
@@ -247,10 +250,15 @@
}
.discussion-with-resolve-btn {
+ @include media-breakpoint-up(sm) {
+ display: flex;
+ }
+
+
.discussion-actions {
display: table;
- .btn-default path {
+ svg {
fill: $gray-darkest;
}
@@ -270,6 +278,12 @@
.btn {
width: 100%;
}
+
+ .btn-text-field {
+ @include media-breakpoint-down(xs) {
+ margin-bottom: $gl-padding-8;
+ }
+ }
}
.discussion-notes-count {
@@ -340,6 +354,8 @@
}
.note-form-actions {
+ color: $gl-text-color;
+
@include media-breakpoint-down(xs) {
.btn {
float: none;
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index c9e0899425f..0d1d0b4d2d6 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -1,26 +1,139 @@
-/**
- * Notes
- */
-
-@-webkit-keyframes targe3-note {
- from {
- background: $note-targe3-outside;
+$system-note-icon-size: 32px;
+$system-note-svg-size: 16px;
+$note-form-margin-left: 72px;
+
+@mixin vertical-line($left) {
+ &::before {
+ content: '';
+ border-left: 2px solid $theme-gray-100;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: $left;
}
+}
- 50% {
- background: $note-targe3-inside;
- }
+@mixin outline-comment() {
+ margin: $gl-padding;
+ border: 1px solid $border-color;
+ border-radius: $border-radius-default;
+}
+
+.note-wrapper {
+ padding: $gl-padding;
- to {
- background: $note-targe3-outside;
+ &.outlined {
+ @include outline-comment();
}
}
-ul.notes {
+.main-notes-list {
+ @include vertical-line(36px);
+}
+
+.notes {
display: block;
list-style: none;
margin: 0;
padding: 0;
+ position: relative;
+
+ &.timeline > .timeline-entry {
+ border: 1px solid $border-color;
+ border-radius: $border-radius-default;
+ margin: $gl-padding 0;
+
+ &.system-note,
+ &.note-form {
+ border: 0;
+ }
+
+ &.note-form {
+ margin-left: 0;
+
+ @include notes-media('min', map-get($grid-breakpoints, md)) {
+ margin-left: $note-form-margin-left;
+ }
+
+ .timeline-icon {
+ @include notes-media('min', map-get($grid-breakpoints, sm)) {
+ margin-left: -$note-icon-gutter-width;
+ }
+ }
+
+ .timeline-content {
+ margin-left: 0;
+ }
+ }
+
+ .notes_content {
+ border: 0;
+ border-top: 1px solid $border-color;
+ }
+ }
+
+ > .note-discussion {
+ .card {
+ border: 0;
+ }
+
+ li.note {
+ border-bottom: 1px solid $border-color;
+ }
+ }
+
+ .replies-toggle {
+ background-color: $gray-light;
+ padding: $gl-padding-8 $gl-padding;
+
+ .collapse-replies-btn:hover {
+ color: $blue-600;
+ }
+
+ &.expanded {
+ border-bottom: 1px solid $border-color;
+
+ span {
+ cursor: pointer;
+ }
+
+ svg {
+ position: relative;
+ top: 3px;
+ }
+ }
+
+ &.collapsed {
+ color: $gl-text-color-secondary;
+
+ svg {
+ float: left;
+ position: relative;
+ top: $gl-padding-4;
+ margin-right: $gl-padding-8;
+ cursor: pointer;
+ }
+
+ img {
+ margin: -2px 4px 0 0;
+ }
+
+ .author-link {
+ color: $gl-text-color;
+ }
+ }
+
+ .user-avatar-link {
+ &:last-child img {
+ margin-right: $gl-padding-8;
+ }
+ }
+
+ .btn-link {
+ border: 0;
+ vertical-align: baseline;
+ }
+ }
.note-created-ago,
.note-updated-at {
@@ -28,8 +141,6 @@ ul.notes {
}
.discussion-body {
- padding-top: 8px;
-
.card {
margin-bottom: 0;
}
@@ -46,21 +157,10 @@ ul.notes {
}
> li {
- // .timeline-entry
- padding: 0;
display: block;
position: relative;
border-bottom: 0;
- @include notes-media('min', map-get($grid-breakpoints, sm)) {
- padding-left: $note-icon-gutter-width;
- }
-
- .timeline-entry-inner {
- padding: $gl-padding $gl-btn-padding;
- border-bottom: 1px solid $white-normal;
- }
-
&:target,
&.target {
border-bottom: 1px solid $white-normal;
@@ -75,23 +175,10 @@ ul.notes {
}
}
- .timeline-icon {
- @include notes-media('min', map-get($grid-breakpoints, sm)) {
- margin-left: -$note-icon-gutter-width;
- }
- }
-
- .timeline-content {
- margin-left: $note-icon-gutter-width;
-
- @include notes-media('min', map-get($grid-breakpoints, sm)) {
- margin-left: 0;
- }
- }
-
&.being-posted {
pointer-events: none;
opacity: 0.5;
+ padding: $gl-padding;
.dummy-avatar {
background-color: $gl-gray-200;
@@ -104,12 +191,6 @@ ul.notes {
}
}
- &.note-discussion {
- .timeline-entry-inner {
- padding: $gl-padding 10px;
- }
- }
-
.editing-spinner {
display: none;
}
@@ -191,8 +272,9 @@ ul.notes {
}
.system-note {
- font-size: 14px;
- clear: both;
+ padding: 6px 21px;
+ margin: $gl-padding-24 0;
+ background-color: transparent;
.note-header-info {
padding-bottom: 0;
@@ -225,17 +307,21 @@ ul.notes {
.timeline-icon {
float: left;
-
- @include notes-media('min', map-get($grid-breakpoints, sm)) {
- margin-left: 0;
- width: auto;
- }
+ display: flex;
+ align-items: center;
+ background-color: $white-light;
+ width: $system-note-icon-size;
+ height: $system-note-icon-size;
+ border: 1px solid $border-color;
+ border-radius: $system-note-icon-size;
+ margin: -6px $gl-padding 0 0;
svg {
- width: 16px;
- height: 16px;
+ width: $system-note-svg-size;
+ height: $system-note-svg-size;
fill: $gray-darkest;
- margin-top: 2px;
+ display: block;
+ margin: 0 auto;
}
}
@@ -302,10 +388,26 @@ ul.notes {
.discussion-body .diff-file {
.file-title {
cursor: default;
+ line-height: 42px;
+ padding: 0 $gl-padding;
+ border-top: 1px solid $border-color;
+ border-radius: 0;
+
+ @media (min-width: map-get($grid-breakpoints, md)) {
+ top: 91px;
+
+ .with-performance-bar & {
+ top: 126px;
+ }
+ }
&:hover {
background-color: $gray-light;
}
+
+ .btn-clipboard {
+ top: 10px;
+ }
}
.line_content {
@@ -313,6 +415,24 @@ ul.notes {
}
}
+.tab-pane.notes {
+ .diff-file .notes .system-note {
+ margin: 0;
+ }
+}
+
+.tab-pane.diffs {
+ .system-note {
+ padding: 0 $gl-padding;
+ margin-left: 20px;
+ }
+
+ .notes > .note-discussion li.note.system-note {
+ border-bottom: 0;
+ padding: 0 $gl-padding;
+ }
+}
+
.diff-file {
.is-over {
.add-diff-note {
@@ -320,6 +440,17 @@ ul.notes {
}
}
+ .discussion-notes {
+ &:not(:last-child) {
+ margin-bottom: 0;
+ }
+
+ .system-note {
+ background-color: $white-light;
+ padding: $gl-padding;
+ }
+ }
+
// Merge request notes in diffs
// Diff is inline
.notes_content .note-header .note-headline-light {
@@ -335,7 +466,6 @@ ul.notes {
border-left: 0;
&.notes_content {
- background-color: $gray-light;
border-width: 1px 0;
padding: 0;
vertical-align: top;
@@ -343,17 +473,9 @@ ul.notes {
&.parallel {
border-width: 1px;
- }
-
- .discussion-notes {
- &:not(:first-child) {
- border-top: 1px solid $white-normal;
- margin-top: 20px;
- }
- &:not(:last-child) {
- border-bottom: 1px solid $white-normal;
- margin-bottom: 20px;
+ &.new {
+ border-right-width: 0;
}
}
@@ -370,6 +492,47 @@ ul.notes {
}
}
+.diffs {
+ .discussion-notes {
+ margin-left: 0;
+ border-left: 0;
+
+ .notes {
+ position: relative;
+ @include vertical-line(52px);
+ }
+ }
+
+ .note-wrapper {
+ @include outline-comment();
+
+ &.system-note {
+ border: 0;
+ margin-left: 20px;
+ }
+ }
+
+ .discussion-reply-holder {
+ border-radius: 0 0 $border-radius-default $border-radius-default;
+ border-top: 1px solid $border-color;
+ position: relative;
+ }
+}
+
+.commit-diff {
+ .notes {
+ @include vertical-line(52px);
+ }
+
+ .notes_content {
+ background-color: $white-light;
+ }
+
+ .discussion-reply-holder {
+ border-top: 1px solid $border-color;
+ }
+}
+
.discussion-header,
.note-header-info {
a {
@@ -395,7 +558,17 @@ ul.notes {
}
.discussion-header {
- font-size: 14px;
+ min-height: 72px;
+
+ .note-header-info {
+ padding-bottom: 0;
+ }
+}
+
+.unresolved {
+ .note-header-info {
+ margin-top: $gl-padding-8;
+ }
}
.note-header {
@@ -405,7 +578,7 @@ ul.notes {
.note-header-info {
min-width: 0;
- padding-bottom: 8px;
+ padding-bottom: $gl-padding-8;
&.discussion {
padding-bottom: 0;
@@ -416,12 +589,6 @@ ul.notes {
padding-bottom: 0;
}
-.note-header-author-name {
- @include notes-media('max', map-get($grid-breakpoints, sm) - 1) {
- display: none;
- }
-}
-
.note-headline-light {
display: inline;
@@ -464,12 +631,20 @@ ul.notes {
.discussion-actions {
float: right;
- margin-left: 10px;
color: $gray-darkest;
+ @include media-breakpoint-down(xs) {
+ width: 100%;
+ margin: $gl-padding-8 0;
+ }
+
.btn-group > .discussion-next-btn {
margin-left: -1px;
}
+
+ svg {
+ height: 15px;
+ }
}
.note-actions {
@@ -519,59 +694,7 @@ ul.notes {
}
.note-action-button {
- line-height: 1;
- padding: 0;
- min-width: 16px;
- color: $gray-darkest;
- fill: $gray-darkest;
-
- .fa {
- position: relative;
- font-size: 16px;
- }
-
- svg {
- @include btn-svg;
- margin: 0;
- }
-
- .award-control-icon-positive,
- .award-control-icon-super-positive {
- position: absolute;
- top: 0;
- left: 0;
- opacity: 0;
- }
-
- &:hover,
- &.is-active {
- .danger-highlight {
- color: $red-500;
- }
-
- .link-highlight {
- color: $blue-600;
- fill: $blue-600;
- }
-
- .award-control-icon-neutral {
- opacity: 0;
- }
-
- .award-control-icon-positive {
- opacity: 1;
- }
- }
-
- &.is-active {
- .award-control-icon-positive {
- opacity: 0;
- }
-
- .award-control-icon-super-positive {
- opacity: 1;
- }
- }
+ @include emoji-menu-toggle-button;
}
.discussion-toggle-button {
@@ -633,19 +756,6 @@ ul.notes {
z-index: 10;
}
-.discussion-body,
-.diff-file {
- .notes .note {
- border-bottom: 1px solid $white-normal;
-
- .timeline-entry-inner {
- padding-left: $gl-padding;
- padding-right: $gl-padding;
- border-bottom: 0;
- }
- }
-}
-
.disabled-comment {
background-color: $gray-light;
border-radius: $border-radius-base;
@@ -666,7 +776,6 @@ ul.notes {
.line-resolve-all-container {
@include notes-media('min', map-get($grid-breakpoints, sm)) {
margin-right: 0;
- padding-left: $gl-padding;
}
> div {
@@ -683,7 +792,7 @@ ul.notes {
}
.btn {
- svg path {
+ svg {
fill: $gray-darkest;
}
@@ -708,7 +817,7 @@ ul.notes {
.line-resolve-all {
vertical-align: middle;
display: inline-block;
- padding: 5px 10px 6px;
+ padding: 6px 10px;
background-color: $gray-light;
border: 1px solid $border-color;
border-radius: $border-radius-default;
@@ -790,7 +899,7 @@ ul.notes {
padding-top: 0;
.discussion-wrapper {
- border-color: transparent;
+ border: 0;
}
}
}
@@ -804,3 +913,43 @@ ul.notes {
margin-top: 4px;
}
}
+
+.discussion-filter-container {
+
+ .btn > svg {
+ width: $gl-col-padding;
+ height: $gl-col-padding;
+ }
+
+ .dropdown-menu {
+ margin-bottom: $gl-padding-4;
+
+ @include media-breakpoint-down(md) {
+ margin-left: $btn-side-margin + $contextual-sidebar-collapsed-width;
+ }
+
+ @include media-breakpoint-down(xs) {
+ margin-left: $btn-side-margin;
+ }
+ }
+}
+
+//This needs to be deleted when Snippet/Commit comments are convered to Vue
+// See https://gitlab.com/gitlab-org/gitlab-ce/issues/53918#note_117038785
+.unstyled-comments {
+
+ .discussion-header {
+ padding: $gl-padding;
+ border-bottom: 1px solid $border-color;
+ }
+
+ .note-wrapper.outlined {
+ margin: 0;
+ border: 0;
+ border-radius: 0;
+ }
+
+ .discussion-form-container {
+ padding: $gl-padding;
+ }
+}
diff --git a/app/assets/stylesheets/pages/pages.scss b/app/assets/stylesheets/pages/pages.scss
index fb42dee66d2..374227fe16a 100644
--- a/app/assets/stylesheets/pages/pages.scss
+++ b/app/assets/stylesheets/pages/pages.scss
@@ -1,7 +1,5 @@
.pages-domain-list {
&-item {
- position: relative;
- display: flex;
align-items: center;
.domain-status {
@@ -44,8 +42,9 @@
}
:first-child {
- border-bottom-left-radius: $border-radius-default;
- border-top-left-radius: $border-radius-default;
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0;
+ line-height: $gl-line-height;
}
:not(:first-child) {
diff --git a/app/assets/stylesheets/pages/pipeline_schedules.scss b/app/assets/stylesheets/pages/pipeline_schedules.scss
index 86e70955389..617b3db2fae 100644
--- a/app/assets/stylesheets/pages/pipeline_schedules.scss
+++ b/app/assets/stylesheets/pages/pipeline_schedules.scss
@@ -39,10 +39,6 @@
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
-
- svg {
- vertical-align: middle;
- }
}
.next-run-cell {
@@ -52,6 +48,10 @@
a {
color: $text-color;
}
+
+ svg {
+ vertical-align: middle;
+ }
}
.pipeline-schedules-user-callout {
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index 8bb8b83dc5e..fdd17af35fb 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -141,10 +141,6 @@
float: none;
}
- .api {
- @extend .monospace;
- }
-
.branch-commit {
.ref-name {
font-weight: $gl-font-weight-bold;
@@ -760,6 +756,7 @@
}
&.ci-status-icon-canceled,
+ &.ci-status-icon-scheduled,
&.ci-status-icon-disabled,
&.ci-status-icon-not-found,
&.ci-status-icon-manual {
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index caa839c32a5..1d691d1d8b8 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -81,14 +81,14 @@
// Middle dot divider between each element in a list of items.
.middle-dot-divider {
&::after {
- content: "\00B7"; // Middle Dot
+ content: '\00B7'; // Middle Dot
padding: 0 6px;
font-weight: $gl-font-weight-bold;
}
&:last-child {
&::after {
- content: "";
+ content: '';
padding: 0;
}
}
@@ -191,7 +191,6 @@
@include media-breakpoint-down(xs) {
width: auto;
}
-
}
.profile-crop-image-container {
@@ -215,7 +214,6 @@
}
}
-
.user-profile {
.cover-controls a {
margin-left: 5px;
@@ -242,6 +240,12 @@
left: 0;
}
+ .activities-block {
+ .event-item {
+ padding-left: 40px;
+ }
+ }
+
@include media-breakpoint-down(xs) {
.cover-block {
padding-top: 20px;
@@ -269,6 +273,12 @@
margin-right: 0;
}
}
+
+ .activities-block {
+ .event-item {
+ padding-left: 0;
+ }
+ }
}
}
@@ -418,7 +428,7 @@ table.u2f-registrations {
}
&.unverified {
- @include status-color($gray-dark, color("gray"), $common-gray-dark);
+ @include status-color($gray-dark, color('gray'), $common-gray-dark);
}
}
}
@@ -431,7 +441,7 @@ table.u2f-registrations {
}
.emoji-menu-toggle-button {
- @extend .note-action-button;
+ @include emoji-menu-toggle-button;
.no-emoji-placeholder {
position: relative;
diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss
index 7c42dcad959..6cc21072acd 100644
--- a/app/assets/stylesheets/pages/projects.scss
+++ b/app/assets/stylesheets/pages/projects.scss
@@ -352,10 +352,6 @@
.mobile-git-clone {
margin-top: $gl-padding-8;
-
- .dropdown-menu-inner-content {
- @extend .monospace;
- }
}
}
@@ -727,7 +723,8 @@
.scrolling-tabs-container {
.scrolling-tabs {
margin-top: $gl-padding-8;
- margin-bottom: $gl-padding-8;
+ margin-bottom: $gl-padding-8 - $browserScrollbarSize;
+ padding-bottom: $browserScrollbarSize;
flex-wrap: wrap;
border-bottom: 0;
}
@@ -735,7 +732,7 @@
.fade-left,
.fade-right {
top: 0;
- height: 100%;
+ height: calc(100% - #{$browserScrollbarSize});
.fa {
top: 50%;
@@ -830,6 +827,14 @@
}
}
+.repository-language-bar-tooltip-language {
+ font-weight: $gl-font-weight-bold;
+}
+
+.repository-language-bar-tooltip-share {
+ color: $theme-gray-400;
+}
+
pre.light-well {
border-color: $well-light-border;
}
@@ -1215,3 +1220,27 @@ pre.light-well {
opacity: 1;
}
}
+
+.project-mirror-settings {
+ .btn-show-advanced {
+ min-width: 135px;
+
+ .label-show {
+ display: none;
+ }
+
+ .label-hide {
+ display: inline;
+ }
+
+ &.show-advanced {
+ .label-show {
+ display: inline;
+ }
+
+ .label-hide {
+ display: none;
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss
index dbf8692d69b..ccfa4e00a5b 100644
--- a/app/assets/stylesheets/pages/settings.scss
+++ b/app/assets/stylesheets/pages/settings.scss
@@ -42,6 +42,10 @@
margin-top: 0;
}
+ .settings-title {
+ cursor: pointer;
+ }
+
button {
position: absolute;
top: 20px;
diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss
index 620297e589d..7d59dd3b5d1 100644
--- a/app/assets/stylesheets/pages/status.scss
+++ b/app/assets/stylesheets/pages/status.scss
@@ -27,6 +27,7 @@
&.ci-canceled,
&.ci-disabled,
+ &.ci-scheduled,
&.ci-manual {
color: $gl-text-color;
border-color: $gl-text-color;
diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss
index dc5ca78ff58..a46b8679a42 100644
--- a/app/assets/stylesheets/pages/tree.scss
+++ b/app/assets/stylesheets/pages/tree.scss
@@ -104,11 +104,23 @@
border-bottom: 1px solid $white-normal;
border-top: 1px solid $white-normal;
+ &:last-of-type {
+ border-bottom-color: $white-light;
+ }
+
td,
th {
line-height: 21px;
}
+ th {
+ border-top-color: $gray-light;
+ }
+
+ td {
+ border-color: $border-color;
+ }
+
&:hover:not(.tree-truncated-warning) {
td {
background-color: $blue-50;
diff --git a/app/assets/stylesheets/performance_bar.scss b/app/assets/stylesheets/performance_bar.scss
index 2e2ab8532d2..9c01a2f8bda 100644
--- a/app/assets/stylesheets/performance_bar.scss
+++ b/app/assets/stylesheets/performance_bar.scss
@@ -1,4 +1,5 @@
@import 'framework/variables';
+@import 'framework/variables_overrides';
@import 'peek/views/rblineprof';
#js-peek {
@@ -6,7 +7,7 @@
left: 0;
top: 0;
width: 100%;
- z-index: 1039;
+ z-index: #{$zindex-modal-backdrop + 1};
height: $performance-bar-height;
background: $black;
@@ -67,6 +68,10 @@
}
}
+ .current-host.canary {
+ color: $perf-bar-canary-text;
+ }
+
strong {
color: $white-light;
}
diff --git a/app/controllers/admin/appearances_controller.rb b/app/controllers/admin/appearances_controller.rb
index fdd3b4126ff..e3226c86b0b 100644
--- a/app/controllers/admin/appearances_controller.rb
+++ b/app/controllers/admin/appearances_controller.rb
@@ -33,21 +33,21 @@ class Admin::AppearancesController < Admin::ApplicationController
@appearance.save
- redirect_to admin_appearances_path, notice: 'Logo was succesfully removed.'
+ redirect_to admin_appearances_path, notice: 'Logo was successfully removed.'
end
def header_logos
@appearance.remove_header_logo!
@appearance.save
- redirect_to admin_appearances_path, notice: 'Header logo was succesfully removed.'
+ redirect_to admin_appearances_path, notice: 'Header logo was successfully removed.'
end
def favicon
@appearance.remove_favicon!
@appearance.save
- redirect_to admin_appearances_path, notice: 'Favicon was succesfully removed.'
+ redirect_to admin_appearances_path, notice: 'Favicon was successfully removed.'
end
private
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 875e46969fe..8f683ca06ad 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -61,14 +61,15 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
format.html do
usage_data_json = JSON.pretty_generate(Gitlab::UsageData.data)
- render html: Gitlab::Highlight.highlight('payload.json', usage_data_json)
+ render html: Gitlab::Highlight.highlight('payload.json', usage_data_json, language: 'json')
end
format.json { render json: Gitlab::UsageData.to_json }
end
end
- def reset_runners_token
+ def reset_registration_token
@application_setting.reset_runners_registration_token!
+
flash[:notice] = 'New runners registration token has been generated!'
redirect_to admin_runners_path
end
@@ -128,8 +129,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
disabled_oauth_sign_in_sources: [],
import_sources: [],
repository_storages: [],
- restricted_visibility_levels: [],
- sidekiq_throttling_queues: []
+ restricted_visibility_levels: []
]
end
end
diff --git a/app/controllers/admin/applications_controller.rb b/app/controllers/admin/applications_controller.rb
index 00d2cc01192..6fc336714b6 100644
--- a/app/controllers/admin/applications_controller.rb
+++ b/app/controllers/admin/applications_controller.rb
@@ -6,11 +6,9 @@ class Admin::ApplicationsController < Admin::ApplicationController
before_action :set_application, only: [:show, :edit, :update, :destroy]
before_action :load_scopes, only: [:new, :create, :edit, :update]
- # rubocop: disable CodeReuse/ActiveRecord
def index
- @applications = Doorkeeper::Application.where("owner_id IS NULL")
+ @applications = ApplicationsFinder.new.execute
end
- # rubocop: enable CodeReuse/ActiveRecord
def show
end
@@ -49,11 +47,9 @@ class Admin::ApplicationsController < Admin::ApplicationController
private
- # rubocop: disable CodeReuse/ActiveRecord
def set_application
- @application = Doorkeeper::Application.where("owner_id IS NULL").find(params[:id])
+ @application = ApplicationsFinder.new(id: params[:id]).execute
end
- # rubocop: enable CodeReuse/ActiveRecord
# Only allow a trusted parameter "white list" through.
def application_params
diff --git a/app/controllers/admin/background_jobs_controller.rb b/app/controllers/admin/background_jobs_controller.rb
index 7701f2e645b..fc877142418 100644
--- a/app/controllers/admin/background_jobs_controller.rb
+++ b/app/controllers/admin/background_jobs_controller.rb
@@ -1,9 +1,4 @@
# frozen_string_literal: true
class Admin::BackgroundJobsController < Admin::ApplicationController
- def show
- ps_output, _ = Gitlab::Popen.popen(%W(ps ww -U #{Gitlab.config.gitlab.user} -o pid,pcpu,pmem,stat,start,command))
- @sidekiq_processes = ps_output.split("\n").grep(/sidekiq \d+\.\d+\.\d+/)
- @concurrency = Sidekiq.options[:concurrency]
- end
end
diff --git a/app/controllers/admin/dashboard_controller.rb b/app/controllers/admin/dashboard_controller.rb
index b5fb5511638..23cc9ee247a 100644
--- a/app/controllers/admin/dashboard_controller.rb
+++ b/app/controllers/admin/dashboard_controller.rb
@@ -3,8 +3,8 @@
class Admin::DashboardController < Admin::ApplicationController
include CountHelper
- COUNTED_ITEMS = [Project, User, Group, ForkedProjectLink, Issue, MergeRequest,
- Note, Snippet, Key, Milestone].freeze
+ COUNTED_ITEMS = [Project, User, Group, ForkNetworkMember, ForkNetwork, Issue,
+ MergeRequest, Note, Snippet, Key, Milestone].freeze
# rubocop: disable CodeReuse/ActiveRecord
def index
diff --git a/app/controllers/admin/health_check_controller.rb b/app/controllers/admin/health_check_controller.rb
index 44864f9c7d0..25cc241e5b0 100644
--- a/app/controllers/admin/health_check_controller.rb
+++ b/app/controllers/admin/health_check_controller.rb
@@ -3,12 +3,5 @@
class Admin::HealthCheckController < Admin::ApplicationController
def show
@errors = HealthCheck::Utils.process_checks(['standard'])
- @failing_storage_statuses = Gitlab::Git::Storage::Health.for_failing_storages
- end
-
- def reset_storage_health
- Gitlab::Git::Storage::FailureInfo.reset_all!
- redirect_to admin_health_check_path,
- notice: _('Git storage health information has been reset')
end
end
diff --git a/app/controllers/admin/impersonation_tokens_controller.rb b/app/controllers/admin/impersonation_tokens_controller.rb
index f5825ecb19a..706bcc1e549 100644
--- a/app/controllers/admin/impersonation_tokens_controller.rb
+++ b/app/controllers/admin/impersonation_tokens_controller.rb
@@ -11,6 +11,7 @@ class Admin::ImpersonationTokensController < Admin::ApplicationController
@impersonation_token = finder.build(impersonation_token_params)
if @impersonation_token.save
+ PersonalAccessToken.redis_store!(current_user.id, @impersonation_token.token)
redirect_to admin_user_impersonation_tokens_path, notice: "A new impersonation token has been created."
else
set_index_vars
@@ -53,6 +54,8 @@ class Admin::ImpersonationTokensController < Admin::ApplicationController
@impersonation_token ||= finder.build
@inactive_impersonation_tokens = finder(state: 'inactive').execute
@active_impersonation_tokens = finder(state: 'active').execute.order(:expires_at)
+
+ @new_impersonation_token = PersonalAccessToken.redis_getdel(current_user.id)
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/controllers/admin/impersonations_controller.rb b/app/controllers/admin/impersonations_controller.rb
index 08d7e3b4fa2..65fe22bd8f4 100644
--- a/app/controllers/admin/impersonations_controller.rb
+++ b/app/controllers/admin/impersonations_controller.rb
@@ -5,23 +5,12 @@ class Admin::ImpersonationsController < Admin::ApplicationController
before_action :authenticate_impersonator!
def destroy
- original_user = current_user
-
- warden.set_user(impersonator, scope: :user)
-
- Gitlab::AppLogger.info("User #{impersonator.username} has stopped impersonating #{original_user.username}")
-
- session[:impersonator_id] = nil
-
+ original_user = stop_impersonation
redirect_to admin_user_path(original_user), status: :found
end
private
- def impersonator
- @impersonator ||= User.find(session[:impersonator_id]) if session[:impersonator_id]
- end
-
def authenticate_impersonator!
render_404 unless impersonator && impersonator.admin? && !impersonator.blocked?
end
diff --git a/app/controllers/admin/requests_profiles_controller.rb b/app/controllers/admin/requests_profiles_controller.rb
index 64d74ae4231..57f7d3e3951 100644
--- a/app/controllers/admin/requests_profiles_controller.rb
+++ b/app/controllers/admin/requests_profiles_controller.rb
@@ -11,7 +11,7 @@ class Admin::RequestsProfilesController < Admin::ApplicationController
profile = Gitlab::RequestProfiler::Profile.find(clean_name)
if profile
- render text: profile.content
+ render html: profile.content
else
redirect_to admin_requests_profiles_path, alert: 'Profile not found'
end
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index b783c0e2a6f..e93be1c1ba2 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -2,6 +2,7 @@
class Admin::UsersController < Admin::ApplicationController
before_action :user, except: [:index, :new, :create]
+ before_action :check_impersonation_availability, only: :impersonate
def index
@users = User.order_name_asc.filter(params[:filter])
@@ -227,4 +228,8 @@ class Admin::UsersController < Admin::ApplicationController
result[:status] == :success
end
+
+ def check_impersonation_availability
+ access_denied! unless Gitlab.config.gitlab.impersonation_enabled
+ end
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 838527aaa41..65c1576d9d2 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -12,8 +12,11 @@ class ApplicationController < ActionController::Base
include WorkhorseHelper
include EnforcesTwoFactorAuthentication
include WithPerformanceBar
+ include SessionlessAuthentication
+ # this can be removed after switching to rails 5
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/51908
+ include InvalidUTF8ErrorHandler unless Gitlab.rails5?
- before_action :authenticate_sessionless_user!
before_action :authenticate_user!
before_action :enforce_terms!, if: :should_enforce_terms?
before_action :validate_user_service_ticket!
@@ -25,6 +28,7 @@ class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
before_action :require_email, unless: :devise_controller?
before_action :set_usage_stats_consent_flag
+ before_action :check_impersonation_availability
around_action :set_locale
@@ -43,6 +47,8 @@ class ApplicationController < ActionController::Base
:git_import_enabled?, :gitlab_project_import_enabled?,
:manifest_import_enabled?
+ DEFAULT_GITLAB_CACHE_CONTROL = "#{ActionDispatch::Http::Cache::Response::DEFAULT_CACHE_CONTROL}, no-store".freeze
+
rescue_from Encoding::CompatibilityError do |exception|
log_exception(exception)
render "errors/encoding", layout: "errors", status: 500
@@ -65,8 +71,7 @@ class ApplicationController < ActionController::Base
head :forbidden, retry_after: Gitlab::Auth::UniqueIpsLimiter.config.unique_ips_limit_time_window
end
- rescue_from Gitlab::Git::Storage::Inaccessible, GRPC::Unavailable, Gitlab::Git::CommandError do |exception|
- Raven.capture_exception(exception) if sentry_enabled?
+ rescue_from GRPC::Unavailable, Gitlab::Git::CommandError do |exception|
log_exception(exception)
headers['Retry-After'] = exception.retry_after if exception.respond_to?(:retry_after)
@@ -108,6 +113,15 @@ class ApplicationController < ActionController::Base
request.env['rack.session.options'][:expire_after] = Settings.gitlab['unauthenticated_session_expire_delay']
end
+ def render(*args)
+ super.tap do
+ # Set a header for custom error pages to prevent them from being intercepted by gitlab-workhorse
+ if response.content_type == 'text/html' && (400..599).cover?(response.status)
+ response.headers['X-GitLab-Custom-Error'] = '1'
+ end
+ end
+ end
+
protected
def append_info_to_payload(payload)
@@ -140,17 +154,10 @@ class ApplicationController < ActionController::Base
end
end
- # This filter handles personal access tokens, and atom requests with rss tokens
- def authenticate_sessionless_user!
- user = Gitlab::Auth::RequestAuthenticator.new(request).find_sessionless_user
-
- sessionless_sign_in(user) if user
- end
-
def log_exception(exception)
Raven.capture_exception(exception) if sentry_enabled?
- backtrace_cleaner = Gitlab.rails5? ? env["action_dispatch.backtrace_cleaner"] : env
+ backtrace_cleaner = Gitlab.rails5? ? request.env["action_dispatch.backtrace_cleaner"] : env
application_trace = ActionDispatch::ExceptionWrapper.new(backtrace_cleaner, exception).application_trace
application_trace.map! { |t| " #{t}\n" }
logger.error "\n#{exception.class.name} (#{exception.message}):\n#{application_trace.join}"
@@ -168,11 +175,11 @@ class ApplicationController < ActionController::Base
Ability.allowed?(object, action, subject)
end
- def access_denied!(message = nil)
+ def access_denied!(message = nil, status = nil)
# If we display a custom access denied message to the user, we don't want to
# hide existence of the resource, rather tell them they cannot access it using
# the provided message
- status = message.present? ? :forbidden : :not_found
+ status ||= message.present? ? :forbidden : :not_found
respond_to do |format|
format.any { head status }
@@ -233,6 +240,13 @@ class ApplicationController < ActionController::Base
headers['X-XSS-Protection'] = '1; mode=block'
headers['X-UA-Compatible'] = 'IE=edge'
headers['X-Content-Type-Options'] = 'nosniff'
+
+ if current_user
+ # Adds `no-store` to the DEFAULT_CACHE_CONTROL, to prevent security
+ # concerns due to caching private data.
+ headers['Cache-Control'] = DEFAULT_GITLAB_CACHE_CONTROL
+ headers["Pragma"] = "no-cache" # HTTP 1.0 compatibility
+ end
end
def validate_user_service_ticket!
@@ -272,9 +286,10 @@ class ApplicationController < ActionController::Base
end
def event_filter
- # Split using comma to maintain backward compatibility Ex/ "filter1,filter2"
- filters = cookies['event_filter'].split(',')[0] if cookies['event_filter'].present?
- @event_filter ||= EventFilter.new(filters)
+ @event_filter ||=
+ EventFilter.new(params[:event_filter].presence || cookies[:event_filter]).tap do |new_event_filter|
+ cookies[:event_filter] = new_event_filter.filter
+ end
end
# JSON for infinite scroll via Pager object
@@ -405,25 +420,11 @@ class ApplicationController < ActionController::Base
Gitlab::I18n.with_user_locale(current_user, &block)
end
- def sessionless_sign_in(user)
- if user && can?(user, :log_in)
- # Notice we are passing store false, so the user is not
- # actually stored in the session and a token is needed
- # for every request. If you want the token to work as a
- # sign in token, you can simply remove store: false.
- sign_in(user, store: false, message: :sessionless_sign_in)
- end
- end
-
def set_page_title_header
# Per https://tools.ietf.org/html/rfc5987, headers need to be ISO-8859-1, not UTF-8
response.headers['Page-Title'] = URI.escape(page_title('GitLab'))
end
- def sessionless_user?
- current_user && !session.keys.include?('warden.user.user.key')
- end
-
def peek_request?
request.path.start_with?('/-/peek')
end
@@ -462,4 +463,28 @@ class ApplicationController < ActionController::Base
.new(settings, current_user, application_setting_params)
.execute
end
+
+ def check_impersonation_availability
+ return unless session[:impersonator_id]
+
+ unless Gitlab.config.gitlab.impersonation_enabled
+ stop_impersonation
+ access_denied! _('Impersonation has been disabled')
+ end
+ end
+
+ def stop_impersonation
+ impersonated_user = current_user
+
+ Gitlab::AppLogger.info("User #{impersonator.username} has stopped impersonating #{impersonated_user.username}")
+
+ warden.set_user(impersonator, scope: :user)
+ session[:impersonator_id] = nil
+
+ impersonated_user
+ end
+
+ def impersonator
+ @impersonator ||= User.find(session[:impersonator_id]) if session[:impersonator_id]
+ end
end
diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb
index 3766b64a091..0d5c8657c9e 100644
--- a/app/controllers/autocomplete_controller.rb
+++ b/app/controllers/autocomplete_controller.rb
@@ -20,7 +20,7 @@ class AutocompleteController < ApplicationController
end
def user
- user = UserFinder.new(params).execute!
+ user = UserFinder.new(params[:id]).find_by_id!
render json: UserSerializer.new.represent(user)
end
diff --git a/app/controllers/boards/issues_controller.rb b/app/controllers/boards/issues_controller.rb
index 4f3d737e3ce..7f874687212 100644
--- a/app/controllers/boards/issues_controller.rb
+++ b/app/controllers/boards/issues_controller.rb
@@ -18,10 +18,15 @@ module Boards
list_service = Boards::Issues::ListService.new(board_parent, current_user, filter_params)
issues = list_service.execute
issues = issues.page(params[:page]).per(params[:per] || 20).without_count
- make_sure_position_is_set(issues) if Gitlab::Database.read_write?
- issues = issues.preload(:project,
- :milestone,
+ Issue.move_to_end(issues) if Gitlab::Database.read_write?
+ issues = issues.preload(:milestone,
:assignees,
+ project: [
+ :route,
+ {
+ namespace: [:route]
+ }
+ ],
labels: [:priorities],
notes: [:award_emoji, :author]
)
@@ -60,12 +65,6 @@ module Boards
render json: data
end
- def make_sure_position_is_set(issues)
- issues.each do |issue|
- issue.move_to_end && issue.save unless issue.relative_position
- end
- end
-
def issue
@issue ||= issues_finder.find(params[:id])
end
diff --git a/app/controllers/chaos_controller.rb b/app/controllers/chaos_controller.rb
new file mode 100644
index 00000000000..8d518c14b90
--- /dev/null
+++ b/app/controllers/chaos_controller.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+class ChaosController < ActionController::Base
+ before_action :validate_request
+
+ def leakmem
+ memory_mb = (params[:memory_mb]&.to_i || 100)
+ duration_s = (params[:duration_s]&.to_i || 30).seconds
+
+ start = Time.now
+ retainer = []
+ # Add `n` 1mb chunks of memory to the retainer array
+ memory_mb.times { retainer << "x" * 1.megabyte }
+
+ duration_taken = (Time.now - start).seconds
+ Kernel.sleep duration_s - duration_taken if duration_s > duration_taken
+
+ render plain: "OK"
+ end
+
+ def cpuspin
+ duration_s = (params[:duration_s]&.to_i || 30).seconds
+ end_time = Time.now + duration_s.seconds
+
+ rand while Time.now < end_time
+
+ render plain: "OK"
+ end
+
+ def sleep
+ duration_s = (params[:duration_s]&.to_i || 30).seconds
+ Kernel.sleep duration_s
+
+ render plain: "OK"
+ end
+
+ def kill
+ Process.kill("KILL", Process.pid)
+ end
+
+ private
+
+ def validate_request
+ secret = ENV['GITLAB_CHAOS_SECRET']
+ # GITLAB_CHAOS_SECRET is required unless you're running in Development mode
+ if !secret && !Rails.env.development?
+ render plain: "chaos misconfigured: please configure GITLAB_CHAOS_SECRET when using GITLAB_ENABLE_CHAOS_ENDPOINTS outside of a development environment", status: :internal_server_error
+ end
+
+ return unless secret
+
+ unless request.headers["HTTP_X_CHAOS_SECRET"] == secret
+ render plain: "To experience chaos, please set X-Chaos-Secret header", status: :unauthorized
+ end
+ end
+end
diff --git a/app/controllers/clusters/applications_controller.rb b/app/controllers/clusters/applications_controller.rb
new file mode 100644
index 00000000000..250f42f3096
--- /dev/null
+++ b/app/controllers/clusters/applications_controller.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+class Clusters::ApplicationsController < Clusters::BaseController
+ before_action :cluster
+ before_action :authorize_create_cluster!, only: [:create]
+
+ def create
+ Clusters::Applications::CreateService
+ .new(@cluster, current_user, create_cluster_application_params)
+ .execute(request)
+
+ head :no_content
+ rescue Clusters::Applications::CreateService::InvalidApplicationError
+ render_404
+ rescue StandardError
+ head :bad_request
+ end
+
+ private
+
+ def cluster
+ @cluster ||= clusterable.clusters.find(params[:id]) || render_404
+ end
+
+ def create_cluster_application_params
+ params.permit(:application, :hostname)
+ end
+end
diff --git a/app/controllers/clusters/base_controller.rb b/app/controllers/clusters/base_controller.rb
new file mode 100644
index 00000000000..ef42f7c4074
--- /dev/null
+++ b/app/controllers/clusters/base_controller.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+class Clusters::BaseController < ApplicationController
+ include RoutableActions
+
+ skip_before_action :authenticate_user!
+ before_action :authorize_read_cluster!
+
+ helper_method :clusterable
+
+ private
+
+ def cluster
+ @cluster ||= clusterable.clusters.find(params[:id])
+ .present(current_user: current_user)
+ end
+
+ def authorize_update_cluster!
+ access_denied! unless can?(current_user, :update_cluster, cluster)
+ end
+
+ def authorize_admin_cluster!
+ access_denied! unless can?(current_user, :admin_cluster, cluster)
+ end
+
+ def authorize_read_cluster!
+ access_denied! unless can?(current_user, :read_cluster, clusterable)
+ end
+
+ def authorize_create_cluster!
+ access_denied! unless can?(current_user, :create_cluster, clusterable)
+ end
+
+ def clusterable
+ raise NotImplementedError
+ end
+end
diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb
new file mode 100644
index 00000000000..2e9c77ae55c
--- /dev/null
+++ b/app/controllers/clusters/clusters_controller.rb
@@ -0,0 +1,218 @@
+# frozen_string_literal: true
+
+class Clusters::ClustersController < Clusters::BaseController
+ include RoutableActions
+
+ before_action :cluster, except: [:index, :new, :create_gcp, :create_user]
+ before_action :generate_gcp_authorize_url, only: [:new]
+ before_action :validate_gcp_token, only: [:new]
+ before_action :gcp_cluster, only: [:new]
+ before_action :user_cluster, only: [:new]
+ before_action :authorize_create_cluster!, only: [:new]
+ before_action :authorize_update_cluster!, only: [:update]
+ before_action :authorize_admin_cluster!, only: [:destroy]
+ before_action :update_applications_status, only: [:cluster_status]
+
+ helper_method :token_in_session
+
+ STATUS_POLLING_INTERVAL = 10_000
+
+ def index
+ clusters = ClustersFinder.new(clusterable, current_user, :all).execute
+ @clusters = clusters.page(params[:page]).per(20)
+ end
+
+ def new
+ end
+
+ # Overridding ActionController::Metal#status is NOT a good idea
+ def cluster_status
+ respond_to do |format|
+ format.json do
+ Gitlab::PollingInterval.set_header(response, interval: STATUS_POLLING_INTERVAL)
+
+ render json: ClusterSerializer
+ .new(current_user: @current_user)
+ .represent_status(@cluster)
+ end
+ end
+ end
+
+ def show
+ end
+
+ def update
+ Clusters::UpdateService
+ .new(current_user, update_params)
+ .execute(cluster)
+
+ if cluster.valid?
+ respond_to do |format|
+ format.json do
+ head :no_content
+ end
+ format.html do
+ flash[:notice] = _('Kubernetes cluster was successfully updated.')
+ redirect_to cluster.show_path
+ end
+ end
+ else
+ respond_to do |format|
+ format.json { head :bad_request }
+ format.html { render :show }
+ end
+ end
+ end
+
+ def destroy
+ if cluster.destroy
+ flash[:notice] = _('Kubernetes cluster integration was successfully removed.')
+ redirect_to clusterable.index_path, status: :found
+ else
+ flash[:notice] = _('Kubernetes cluster integration was not removed.')
+ render :show
+ end
+ end
+
+ def create_gcp
+ @gcp_cluster = ::Clusters::CreateService
+ .new(current_user, create_gcp_cluster_params)
+ .execute(access_token: token_in_session)
+ .present(current_user: current_user)
+
+ if @gcp_cluster.persisted?
+ redirect_to @gcp_cluster.show_path
+ else
+ generate_gcp_authorize_url
+ validate_gcp_token
+ user_cluster
+
+ render :new, locals: { active_tab: 'gcp' }
+ end
+ end
+
+ def create_user
+ @user_cluster = ::Clusters::CreateService
+ .new(current_user, create_user_cluster_params)
+ .execute(access_token: token_in_session)
+ .present(current_user: current_user)
+
+ if @user_cluster.persisted?
+ redirect_to @user_cluster.show_path
+ else
+ generate_gcp_authorize_url
+ validate_gcp_token
+ gcp_cluster
+
+ render :new, locals: { active_tab: 'user' }
+ end
+ end
+
+ private
+
+ def update_params
+ if cluster.managed?
+ params.require(:cluster).permit(
+ :enabled,
+ :environment_scope,
+ platform_kubernetes_attributes: [
+ :namespace
+ ]
+ )
+ else
+ params.require(:cluster).permit(
+ :enabled,
+ :name,
+ :environment_scope,
+ platform_kubernetes_attributes: [
+ :api_url,
+ :token,
+ :ca_cert,
+ :namespace
+ ]
+ )
+ end
+ end
+
+ def create_gcp_cluster_params
+ params.require(:cluster).permit(
+ :enabled,
+ :name,
+ :environment_scope,
+ provider_gcp_attributes: [
+ :gcp_project_id,
+ :zone,
+ :num_nodes,
+ :machine_type,
+ :legacy_abac
+ ]).merge(
+ provider_type: :gcp,
+ platform_type: :kubernetes,
+ clusterable: clusterable.subject
+ )
+ end
+
+ def create_user_cluster_params
+ params.require(:cluster).permit(
+ :enabled,
+ :name,
+ :environment_scope,
+ platform_kubernetes_attributes: [
+ :namespace,
+ :api_url,
+ :token,
+ :ca_cert,
+ :authorization_type
+ ]).merge(
+ provider_type: :user,
+ platform_type: :kubernetes,
+ clusterable: clusterable.subject
+ )
+ end
+
+ def generate_gcp_authorize_url
+ state = generate_session_key_redirect(clusterable.new_path.to_s)
+
+ @authorize_url = GoogleApi::CloudPlatform::Client.new(
+ nil, callback_google_api_auth_url,
+ state: state).authorize_url
+ rescue GoogleApi::Auth::ConfigMissingError
+ # no-op
+ end
+
+ def gcp_cluster
+ @gcp_cluster = ::Clusters::Cluster.new.tap do |cluster|
+ cluster.build_provider_gcp
+ end.present(current_user: current_user)
+ end
+
+ def user_cluster
+ @user_cluster = ::Clusters::Cluster.new.tap do |cluster|
+ cluster.build_platform_kubernetes
+ end.present(current_user: current_user)
+ end
+
+ def validate_gcp_token
+ @valid_gcp_token = GoogleApi::CloudPlatform::Client.new(token_in_session, nil)
+ .validate_token(expires_at_in_session)
+ end
+
+ def token_in_session
+ session[GoogleApi::CloudPlatform::Client.session_key_for_token]
+ end
+
+ def expires_at_in_session
+ @expires_at_in_session ||=
+ session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at]
+ end
+
+ def generate_session_key_redirect(uri)
+ GoogleApi::CloudPlatform::Client.new_session_key_for_redirect_uri do |key|
+ session[key] = uri
+ end
+ end
+
+ def update_applications_status
+ @cluster.applications.each(&:schedule_status_update)
+ end
+end
diff --git a/app/controllers/concerns/boards_responses.rb b/app/controllers/concerns/boards_responses.rb
index b7e4f9b81f1..3cdf4ddf8bb 100644
--- a/app/controllers/concerns/boards_responses.rb
+++ b/app/controllers/concerns/boards_responses.rb
@@ -50,7 +50,10 @@ module BoardsResponses
end
def authorize_create_issue
- authorize_action_for!(project, :admin_issue)
+ list = List.find(issue_params[:list_id])
+ action = list.backlog? ? :create_issue : :admin_issue
+
+ authorize_action_for!(project, action)
end
def authorize_admin_list
diff --git a/app/controllers/concerns/invalid_utf8_error_handler.rb b/app/controllers/concerns/invalid_utf8_error_handler.rb
new file mode 100644
index 00000000000..44c6d6b0da0
--- /dev/null
+++ b/app/controllers/concerns/invalid_utf8_error_handler.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module InvalidUTF8ErrorHandler
+ extend ActiveSupport::Concern
+
+ included do
+ rescue_from ArgumentError, with: :handle_invalid_utf8
+ end
+
+ private
+
+ def handle_invalid_utf8(error)
+ if error.message == "invalid byte sequence in UTF-8"
+ render_412
+ else
+ raise(error)
+ end
+ end
+
+ def render_412
+ respond_to do |format|
+ format.html { render "errors/precondition_failed", layout: "errors", status: 412 }
+ format.js { render json: { error: 'Invalid UTF-8' }, status: :precondition_failed, content_type: 'application/json' }
+ format.any { head :precondition_failed }
+ end
+ end
+end
diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb
index 07e01e903ea..ad9cc0925b7 100644
--- a/app/controllers/concerns/issuable_actions.rb
+++ b/app/controllers/concerns/issuable_actions.rb
@@ -2,6 +2,7 @@
module IssuableActions
extend ActiveSupport::Concern
+ include Gitlab::Utils::StrongMemoize
included do
before_action :labels, only: [:show, :new, :edit]
@@ -95,10 +96,14 @@ module IssuableActions
def discussions
notes = issuable.discussion_notes
.inc_relations_for_view
+ .with_notes_filter(notes_filter)
.includes(:noteable)
.fresh
- notes = ResourceEvents::MergeIntoNotesService.new(issuable, current_user).execute(notes)
+ if notes_filter != UserPreference::NOTES_FILTERS[:only_comments]
+ notes = ResourceEvents::MergeIntoNotesService.new(issuable, current_user).execute(notes)
+ end
+
notes = prepare_notes_for_rendering(notes)
notes = notes.reject { |n| n.cross_reference_not_visible_for?(current_user) }
@@ -110,6 +115,32 @@ module IssuableActions
private
+ def notes_filter
+ strong_memoize(:notes_filter) do
+ notes_filter_param = params[:notes_filter]&.to_i
+
+ # GitLab Geo does not expect database UPDATE or INSERT statements to happen
+ # on GET requests.
+ # This is just a fail-safe in case notes_filter is sent via GET request in GitLab Geo.
+ if Gitlab::Database.read_only?
+ notes_filter_param || current_user&.notes_filter_for(issuable)
+ else
+ notes_filter = current_user&.set_notes_filter(notes_filter_param, issuable) || notes_filter_param
+
+ # We need to invalidate the cache for polling notes otherwise it will
+ # ignore the filter.
+ # The ideal would be to invalidate the cache for each user.
+ issuable.expire_note_etag_cache if notes_filter_updated?
+
+ notes_filter
+ end
+ end
+ end
+
+ def notes_filter_updated?
+ current_user&.user_preference&.previous_changes&.any?
+ end
+
def discussion_serializer
DiscussionSerializer.new(project: project, noteable: issuable, current_user: current_user, note_entity: ProjectNoteEntity)
end
diff --git a/app/controllers/concerns/issuable_collections.rb b/app/controllers/concerns/issuable_collections.rb
index 5217b4be928..34a8c50fcbd 100644
--- a/app/controllers/concerns/issuable_collections.rb
+++ b/app/controllers/concerns/issuable_collections.rb
@@ -81,36 +81,36 @@ module IssuableCollections
end
def issuable_finder_for(finder_class)
- finder_class.new(current_user, filter_params)
+ finder_class.new(current_user, finder_options)
end
# rubocop:disable Gitlab/ModuleWithInstanceVariables
- # rubocop: disable CodeReuse/ActiveRecord
- def filter_params
- set_sort_order_from_cookie
- set_default_state
+ def finder_options
+ params[:state] = default_state if params[:state].blank?
- # Skip irrelevant Rails routing params
- @filter_params = params.dup.except(:controller, :action, :namespace_id)
- @filter_params[:sort] ||= default_sort_order
+ options = {
+ scope: params[:scope],
+ state: params[:state],
+ sort: set_sort_order_from_cookie || default_sort_order
+ }
- @sort = @filter_params[:sort]
+ # Used by view to highlight active option
+ @sort = options[:sort]
if @project
- @filter_params[:project_id] = @project.id
+ options[:project_id] = @project.id
elsif @group
- @filter_params[:group_id] = @group.id
- @filter_params[:include_subgroups] = true
- @filter_params[:use_cte_for_search] = true
+ options[:group_id] = @group.id
+ options[:include_subgroups] = true
+ options[:use_cte_for_search] = true
end
- @filter_params.permit(finder_type.valid_params)
+ params.permit(finder_type.valid_params).merge(options)
end
- # rubocop: enable CodeReuse/ActiveRecord
# rubocop:enable Gitlab/ModuleWithInstanceVariables
- def set_default_state
- params[:state] = 'opened' if params[:state].blank?
+ def default_state
+ 'opened'
end
def set_sort_order_from_cookie
@@ -121,7 +121,7 @@ module IssuableCollections
sort_value = update_cookie_value(sort_param)
set_secure_cookie(remember_sorting_key, sort_value)
- params[:sort] = sort_value
+ sort_value
end
def remember_sorting_key
diff --git a/app/controllers/concerns/labels_as_hash.rb b/app/controllers/concerns/labels_as_hash.rb
new file mode 100644
index 00000000000..1171aa9cf44
--- /dev/null
+++ b/app/controllers/concerns/labels_as_hash.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module LabelsAsHash
+ extend ActiveSupport::Concern
+
+ def labels_as_hash(target = nil, params = {})
+ available_labels = LabelsFinder.new(
+ current_user,
+ params
+ ).execute
+
+ label_hashes = available_labels.as_json(only: [:title, :color])
+
+ if target&.respond_to?(:labels)
+ already_set_labels = available_labels & target.labels
+ if already_set_labels.present?
+ titles = already_set_labels.map(&:title)
+ label_hashes.each do |hash|
+ if titles.include?(hash['title'])
+ hash[:set] = true
+ end
+ end
+ end
+ end
+
+ label_hashes
+ end
+end
diff --git a/app/controllers/concerns/members_presentation.rb b/app/controllers/concerns/members_presentation.rb
index c6c3598a976..0a9d3d86245 100644
--- a/app/controllers/concerns/members_presentation.rb
+++ b/app/controllers/concerns/members_presentation.rb
@@ -12,12 +12,7 @@ module MembersPresentation
).fabricate!
end
- # rubocop: disable CodeReuse/ActiveRecord
def preload_associations(members)
- ActiveRecord::Associations::Preloader.new.preload(members, :user)
- ActiveRecord::Associations::Preloader.new.preload(members, :source)
- ActiveRecord::Associations::Preloader.new.preload(members.map(&:user), :status)
- ActiveRecord::Associations::Preloader.new.preload(members.map(&:user), :u2f_registrations)
+ MembersPreloader.new(members).preload_all
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/controllers/concerns/merge_requests_action.rb b/app/controllers/concerns/merge_requests_action.rb
index 285f2c3a8a0..ed10f32512e 100644
--- a/app/controllers/concerns/merge_requests_action.rb
+++ b/app/controllers/concerns/merge_requests_action.rb
@@ -19,7 +19,7 @@ module MergeRequestsAction
(MergeRequestsFinder if action_name == 'merge_requests')
end
- def filter_params
+ def finder_options
super.merge(non_archived: true)
end
end
diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb
index 9422a06387b..0319948a12f 100644
--- a/app/controllers/concerns/notes_actions.rb
+++ b/app/controllers/concerns/notes_actions.rb
@@ -6,6 +6,7 @@ module NotesActions
extend ActiveSupport::Concern
included do
+ prepend_before_action :normalize_create_params, only: [:create]
before_action :set_polling_interval_header, only: [:index]
before_action :require_noteable!, only: [:index, :create]
before_action :authorize_admin_note!, only: [:update, :destroy]
@@ -17,10 +18,17 @@ module NotesActions
notes_json = { notes: [], last_fetched_at: current_fetched_at }
- notes = notes_finder.execute
- .inc_relations_for_view
+ notes = notes_finder
+ .execute
+ .inc_relations_for_view
+
+ if notes_filter != UserPreference::NOTES_FILTERS[:only_comments]
+ notes =
+ ResourceEvents::MergeIntoNotesService
+ .new(noteable, current_user, last_fetched_at: current_fetched_at)
+ .execute(notes)
+ end
- notes = ResourceEvents::MergeIntoNotesService.new(noteable, current_user, last_fetched_at: current_fetched_at).execute(notes)
notes = prepare_notes_for_rendering(notes)
notes = notes.reject { |n| n.cross_reference_not_visible_for?(current_user) }
@@ -43,12 +51,26 @@ module NotesActions
@note = Notes::CreateService.new(note_project, current_user, create_params).execute
- if @note.is_a?(Note)
- prepare_notes_for_rendering([@note], noteable)
- end
-
respond_to do |format|
- format.json { render json: note_json(@note) }
+ format.json do
+ json = {
+ commands_changes: @note.commands_changes
+ }
+
+ if @note.persisted? && return_discussion?
+ json[:valid] = true
+
+ discussion = @note.discussion
+ prepare_notes_for_rendering(discussion.notes)
+ json[:discussion] = discussion_serializer.represent(discussion, context: self)
+ else
+ prepare_notes_for_rendering([@note])
+
+ json.merge!(note_json(@note))
+ end
+
+ render json: json
+ end
format.html { redirect_back_or_default }
end
end
@@ -57,10 +79,7 @@ module NotesActions
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def update
@note = Notes::UpdateService.new(project, current_user, note_params).execute(note)
-
- if @note.is_a?(Note)
- prepare_notes_for_rendering([@note])
- end
+ prepare_notes_for_rendering([@note])
respond_to do |format|
format.json { render json: note_json(@note) }
@@ -91,14 +110,17 @@ module NotesActions
end
def note_json(note)
- attrs = {
- commands_changes: note.commands_changes
- }
+ attrs = {}
if note.persisted?
attrs[:valid] = true
- if use_note_serializer?
+ if return_discussion?
+ discussion = note.discussion
+ prepare_notes_for_rendering(discussion.notes)
+
+ attrs[:discussion] = discussion_serializer.represent(discussion, context: self)
+ elsif use_note_serializer?
attrs.merge!(note_serializer.represent(note))
else
attrs.merge!(
@@ -210,6 +232,10 @@ module NotesActions
request.headers['X-Last-Fetched-At']
end
+ def notes_filter
+ current_user&.notes_filter_for(params[:target_type])
+ end
+
def notes_finder
@notes_finder ||= NotesFinder.new(project, current_user, finder_params)
end
@@ -218,6 +244,19 @@ module NotesActions
ProjectNoteSerializer.new(project: project, noteable: noteable, current_user: current_user)
end
+ def discussion_serializer
+ DiscussionSerializer.new(project: project, noteable: noteable, current_user: current_user, note_entity: ProjectNoteEntity)
+ end
+
+ # Avoids checking permissions in the wrong object - this ensures that the object we checked permissions for
+ # is the object we're actually creating a note in.
+ def normalize_create_params
+ params[:note].try do |note|
+ note[:noteable_id] = params[:target_id]
+ note[:noteable_type] = params[:target_type].classify
+ end
+ end
+
def note_project
strong_memoize(:note_project) do
next nil unless project
@@ -237,6 +276,10 @@ module NotesActions
end
end
+ def return_discussion?
+ Gitlab::Utils.to_boolean(params[:return_discussion])
+ end
+
def use_note_serializer?
return false if params['html']
diff --git a/app/controllers/concerns/project_unauthorized.rb b/app/controllers/concerns/project_unauthorized.rb
new file mode 100644
index 00000000000..f59440dbc59
--- /dev/null
+++ b/app/controllers/concerns/project_unauthorized.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module ProjectUnauthorized
+ extend ActiveSupport::Concern
+
+ # EE would override this
+ def project_unauthorized_proc
+ # no-op
+ end
+end
diff --git a/app/controllers/concerns/routable_actions.rb b/app/controllers/concerns/routable_actions.rb
index 88939b002b2..5624eb3aa45 100644
--- a/app/controllers/concerns/routable_actions.rb
+++ b/app/controllers/concerns/routable_actions.rb
@@ -3,23 +3,25 @@
module RoutableActions
extend ActiveSupport::Concern
- def find_routable!(routable_klass, requested_full_path, extra_authorization_proc: nil)
+ def find_routable!(routable_klass, requested_full_path, extra_authorization_proc: nil, not_found_or_authorized_proc: nil)
routable = routable_klass.find_by_full_path(requested_full_path, follow_redirects: request.get?)
if routable_authorized?(routable, extra_authorization_proc)
ensure_canonical_path(routable, requested_full_path)
routable
else
- handle_not_found_or_authorized(routable)
+ if not_found_or_authorized_proc
+ not_found_or_authorized_proc.call(routable)
+ end
+
+ route_not_found unless performed?
+
nil
end
end
- # This is overridden in gitlab-ee.
- def handle_not_found_or_authorized(_routable)
- route_not_found
- end
-
def routable_authorized?(routable, extra_authorization_proc)
+ return false unless routable
+
action = :"read_#{routable.class.to_s.underscore}"
return false unless can?(current_user, action, routable)
diff --git a/app/controllers/concerns/send_file_upload.rb b/app/controllers/concerns/send_file_upload.rb
index 0bb7b7efed0..515a9eede8e 100644
--- a/app/controllers/concerns/send_file_upload.rb
+++ b/app/controllers/concerns/send_file_upload.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module SendFileUpload
- def send_upload(file_upload, send_params: {}, redirect_params: {}, attachment: nil, disposition: 'attachment')
+ def send_upload(file_upload, send_params: {}, redirect_params: {}, attachment: nil, proxy: false, disposition: 'attachment')
if attachment
# Response-Content-Type will not override an existing Content-Type in
# Google Cloud Storage, so the metadata needs to be cleared on GCS for
@@ -17,7 +17,7 @@ module SendFileUpload
if file_upload.file_storage?
send_file file_upload.path, send_params
- elsif file_upload.class.proxy_download_enabled?
+ elsif file_upload.class.proxy_download_enabled? || proxy
headers.store(*Gitlab::Workhorse.send_url(file_upload.url(**redirect_params)))
head :ok
else
diff --git a/app/controllers/concerns/sends_blob.rb b/app/controllers/concerns/sends_blob.rb
index 971390d9118..8ecdaced9f5 100644
--- a/app/controllers/concerns/sends_blob.rb
+++ b/app/controllers/concerns/sends_blob.rb
@@ -8,7 +8,7 @@ module SendsBlob
include SendFileUpload
end
- def send_blob(blob, params = {})
+ def send_blob(repository, blob, params = {})
if blob
headers['X-Content-Type-Options'] = 'nosniff'
diff --git a/app/controllers/concerns/sessionless_authentication.rb b/app/controllers/concerns/sessionless_authentication.rb
new file mode 100644
index 00000000000..590eefc6dab
--- /dev/null
+++ b/app/controllers/concerns/sessionless_authentication.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+# == SessionlessAuthentication
+#
+# Controller concern to handle PAT and RSS token authentication methods
+#
+module SessionlessAuthentication
+ # This filter handles personal access tokens, and atom requests with rss tokens
+ def authenticate_sessionless_user!(request_format)
+ user = Gitlab::Auth::RequestAuthenticator.new(request).find_sessionless_user(request_format)
+
+ sessionless_sign_in(user) if user
+ end
+
+ def sessionless_user?
+ current_user && !session.keys.include?('warden.user.user.key')
+ end
+
+ def sessionless_sign_in(user)
+ if user && can?(user, :log_in)
+ # Notice we are passing store false, so the user is not
+ # actually stored in the session and a token is needed
+ # for every request. If you want the token to work as a
+ # sign in token, you can simply remove store: false.
+ sign_in(user, store: false, message: :sessionless_sign_in)
+ end
+ end
+end
diff --git a/app/controllers/concerns/uploads_actions.rb b/app/controllers/concerns/uploads_actions.rb
index 7a1c7abfb8f..5912fffc058 100644
--- a/app/controllers/concerns/uploads_actions.rb
+++ b/app/controllers/concerns/uploads_actions.rb
@@ -1,17 +1,11 @@
# frozen_string_literal: true
module UploadsActions
- extend ActiveSupport::Concern
-
include Gitlab::Utils::StrongMemoize
include SendFileUpload
UPLOAD_MOUNTS = %w(avatar attachment file logo header_logo favicon).freeze
- included do
- prepend_before_action :set_html_format, only: :show
- end
-
def create
link_to_file = UploadService.new(model, params[:file], uploader_class).execute
@@ -61,13 +55,6 @@ module UploadsActions
private
- # Explicitly set the format.
- # Otherwise rails 5 will set it from a file extension.
- # See https://github.com/rails/rails/commit/84e8accd6fb83031e4c27e44925d7596655285f7#diff-2b8f2fbb113b55ca8e16001c393da8f1
- def set_html_format
- request.format = :html
- end
-
def uploader_class
raise NotImplementedError
end
diff --git a/app/controllers/concerns/with_performance_bar.rb b/app/controllers/concerns/with_performance_bar.rb
index c12839c7bbd..77c3d476ac6 100644
--- a/app/controllers/concerns/with_performance_bar.rb
+++ b/app/controllers/concerns/with_performance_bar.rb
@@ -10,11 +10,7 @@ module WithPerformanceBar
def peek_enabled?
return false unless Gitlab::PerformanceBar.enabled?(current_user)
- if RequestStore.active?
- RequestStore.fetch(:peek_enabled) { cookie_or_default_value }
- else
- cookie_or_default_value
- end
+ Gitlab::SafeRequestStore.fetch(:peek_enabled) { cookie_or_default_value }
end
private
diff --git a/app/controllers/dashboard/application_controller.rb b/app/controllers/dashboard/application_controller.rb
index 9fb5c525425..cee0753a021 100644
--- a/app/controllers/dashboard/application_controller.rb
+++ b/app/controllers/dashboard/application_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Dashboard::ApplicationController < ApplicationController
include ControllerWithCrossProjectAccessCheck
diff --git a/app/controllers/dashboard/groups_controller.rb b/app/controllers/dashboard/groups_controller.rb
index 79f563bef86..f82cde8e10a 100644
--- a/app/controllers/dashboard/groups_controller.rb
+++ b/app/controllers/dashboard/groups_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Dashboard::GroupsController < Dashboard::ApplicationController
include GroupTree
diff --git a/app/controllers/dashboard/labels_controller.rb b/app/controllers/dashboard/labels_controller.rb
index 9dcb3a0eb6d..89d87c2d5c8 100644
--- a/app/controllers/dashboard/labels_controller.rb
+++ b/app/controllers/dashboard/labels_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Dashboard::LabelsController < Dashboard::ApplicationController
def index
respond_to do |format|
diff --git a/app/controllers/dashboard/milestones_controller.rb b/app/controllers/dashboard/milestones_controller.rb
index 78f7f6d4e23..3802aa5f40f 100644
--- a/app/controllers/dashboard/milestones_controller.rb
+++ b/app/controllers/dashboard/milestones_controller.rb
@@ -1,13 +1,16 @@
+# frozen_string_literal: true
+
class Dashboard::MilestonesController < Dashboard::ApplicationController
include MilestoneActions
before_action :projects
+ before_action :groups, only: :index
before_action :milestone, only: [:show, :merge_requests, :participants, :labels]
def index
respond_to do |format|
format.html do
- @milestone_states = GlobalMilestone.states_count(@projects)
+ @milestone_states = Milestone.states_count(@projects.select(:id), @groups.select(:id))
@milestones = Kaminari.paginate_array(milestones).page(params[:page])
end
format.json do
@@ -40,4 +43,8 @@ class Dashboard::MilestonesController < Dashboard::ApplicationController
@milestone = DashboardMilestone.build(@projects, params[:title])
render_404 unless @milestone
end
+
+ def groups
+ @groups ||= GroupsFinder.new(current_user, state_all: true).execute
+ end
end
diff --git a/app/controllers/dashboard/projects_controller.rb b/app/controllers/dashboard/projects_controller.rb
index e8f796f17ca..57e612d89d3 100644
--- a/app/controllers/dashboard/projects_controller.rb
+++ b/app/controllers/dashboard/projects_controller.rb
@@ -1,7 +1,10 @@
+# frozen_string_literal: true
+
class Dashboard::ProjectsController < Dashboard::ApplicationController
include ParamsBackwardCompatibility
include RendersMemberAccess
+ prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) }
before_action :set_non_archived_param
before_action :default_sorting
skip_cross_project_access_check :index, :starred
diff --git a/app/controllers/dashboard/snippets_controller.rb b/app/controllers/dashboard/snippets_controller.rb
index 0ba97e4fd59..161c22046f9 100644
--- a/app/controllers/dashboard/snippets_controller.rb
+++ b/app/controllers/dashboard/snippets_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Dashboard::SnippetsController < Dashboard::ApplicationController
skip_cross_project_access_check :index
diff --git a/app/controllers/dashboard/todos_controller.rb b/app/controllers/dashboard/todos_controller.rb
index 231a23427f7..3fa582cf25b 100644
--- a/app/controllers/dashboard/todos_controller.rb
+++ b/app/controllers/dashboard/todos_controller.rb
@@ -1,7 +1,10 @@
+# frozen_string_literal: true
+
class Dashboard::TodosController < Dashboard::ApplicationController
include ActionView::Helpers::NumberHelper
before_action :authorize_read_project!, only: :index
+ before_action :authorize_read_group!, only: :index
before_action :find_todos, only: [:index, :destroy_all]
def index
@@ -58,6 +61,15 @@ class Dashboard::TodosController < Dashboard::ApplicationController
end
end
+ def authorize_read_group!
+ group_id = params[:group_id]
+
+ if group_id.present?
+ group = Group.find(group_id)
+ render_404 unless can?(current_user, :read_group, group)
+ end
+ end
+
def find_todos
@todos ||= TodosFinder.new(current_user, todo_params).execute
end
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 241753a505a..be2d9512c01 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -4,12 +4,8 @@ class DashboardController < Dashboard::ApplicationController
include IssuesAction
include MergeRequestsAction
- FILTER_PARAMS = [
- :author_id,
- :assignee_id,
- :milestone_title,
- :label_name
- ].freeze
+ prepend_before_action(only: [:issues]) { authenticate_sessionless_user!(:rss) }
+ prepend_before_action(only: [:issues_calendar]) { authenticate_sessionless_user!(:ics) }
before_action :event_filter, only: :activity
before_action :projects, only: [:issues, :merge_requests]
@@ -40,7 +36,7 @@ class DashboardController < Dashboard::ApplicationController
end
@events = EventCollection
- .new(projects, offset: params[:offset].to_i, filter: @event_filter)
+ .new(projects, offset: params[:offset].to_i, filter: event_filter)
.to_a
Events::RenderService.new(current_user).execute(@events)
@@ -51,10 +47,13 @@ class DashboardController < Dashboard::ApplicationController
end
def check_filters_presence!
- @no_filters_set = FILTER_PARAMS.none? { |k| params.key?(k) }
+ @no_filters_set = finder_type.scalar_params.none? { |k| params.key?(k) }
return unless @no_filters_set
+ # Call to set selected `state` and `sort` options in view
+ finder_options
+
respond_to do |format|
format.html { render }
format.atom { head :bad_request }
diff --git a/app/controllers/explore/application_controller.rb b/app/controllers/explore/application_controller.rb
index baf54520b9c..8eee3742d89 100644
--- a/app/controllers/explore/application_controller.rb
+++ b/app/controllers/explore/application_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Explore::ApplicationController < ApplicationController
skip_before_action :authenticate_user!
diff --git a/app/controllers/explore/groups_controller.rb b/app/controllers/explore/groups_controller.rb
index fa0a0f68fbc..67db797b80a 100644
--- a/app/controllers/explore/groups_controller.rb
+++ b/app/controllers/explore/groups_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Explore::GroupsController < Explore::ApplicationController
include GroupTree
diff --git a/app/controllers/explore/projects_controller.rb b/app/controllers/explore/projects_controller.rb
index 03a2ee07fea..7ecbc32cf4e 100644
--- a/app/controllers/explore/projects_controller.rb
+++ b/app/controllers/explore/projects_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Explore::ProjectsController < Explore::ApplicationController
include ParamsBackwardCompatibility
include RendersMemberAccess
diff --git a/app/controllers/explore/snippets_controller.rb b/app/controllers/explore/snippets_controller.rb
index d3f0e033068..76ed142c939 100644
--- a/app/controllers/explore/snippets_controller.rb
+++ b/app/controllers/explore/snippets_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Explore::SnippetsController < Explore::ApplicationController
def index
@snippets = SnippetsFinder.new(current_user).execute
diff --git a/app/controllers/google_api/authorizations_controller.rb b/app/controllers/google_api/authorizations_controller.rb
index 5551057ff55..dd9f5af61b3 100644
--- a/app/controllers/google_api/authorizations_controller.rb
+++ b/app/controllers/google_api/authorizations_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module GoogleApi
class AuthorizationsController < ApplicationController
def callback
diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb
index a1ec144410b..6ea4758ec32 100644
--- a/app/controllers/graphql_controller.rb
+++ b/app/controllers/graphql_controller.rb
@@ -3,6 +3,7 @@
class GraphqlController < ApplicationController
# Unauthenticated users have access to the API for public data
skip_before_action :authenticate_user!
+ prepend_before_action(only: [:execute]) { authenticate_sessionless_user!(:api) }
before_action :check_graphql_feature_flag!
diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb
index 62213561898..5f92333c2c3 100644
--- a/app/controllers/groups/application_controller.rb
+++ b/app/controllers/groups/application_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Groups::ApplicationController < ApplicationController
include RoutableActions
include ControllerWithCrossProjectAccessCheck
diff --git a/app/controllers/groups/avatars_controller.rb b/app/controllers/groups/avatars_controller.rb
index 35a61b359c8..8e4dc2bb6e9 100644
--- a/app/controllers/groups/avatars_controller.rb
+++ b/app/controllers/groups/avatars_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Groups::AvatarsController < Groups::ApplicationController
before_action :authorize_admin_group!
diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb
index e892d1f8dbf..cdc6f53df8e 100644
--- a/app/controllers/groups/boards_controller.rb
+++ b/app/controllers/groups/boards_controller.rb
@@ -1,8 +1,11 @@
+# frozen_string_literal: true
+
class Groups::BoardsController < Groups::ApplicationController
include BoardsResponses
before_action :assign_endpoint_vars
before_action :boards, only: :index
+ before_action :redirect_to_recent_board, only: :index
def index
respond_with_boards
@@ -11,6 +14,9 @@ class Groups::BoardsController < Groups::ApplicationController
def show
@board = boards.find(params[:id])
+ # add/update the board in the recent visited table
+ Boards::Visits::CreateService.new(@board.group, current_user).execute(@board) if request.format.html?
+
respond_with_board
end
@@ -29,4 +35,18 @@ class Groups::BoardsController < Groups::ApplicationController
def serialize_as_json(resource)
resource.as_json(only: [:id])
end
+
+ def includes_board?(board_id)
+ boards.any? { |board| board.id == board_id }
+ end
+
+ def redirect_to_recent_board
+ return if request.format.json?
+
+ recently_visited = Boards::Visits::LatestService.new(group, current_user).execute
+
+ if recently_visited && includes_board?(recently_visited.board_id)
+ redirect_to(group_board_path(id: recently_visited.board_id), status: :found)
+ end
+ end
end
diff --git a/app/controllers/groups/children_controller.rb b/app/controllers/groups/children_controller.rb
index 0e8125d6113..d549f793ad7 100644
--- a/app/controllers/groups/children_controller.rb
+++ b/app/controllers/groups/children_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Groups
class ChildrenController < Groups::ApplicationController
before_action :group
diff --git a/app/controllers/groups/clusters/applications_controller.rb b/app/controllers/groups/clusters/applications_controller.rb
new file mode 100644
index 00000000000..8dd8a01cf40
--- /dev/null
+++ b/app/controllers/groups/clusters/applications_controller.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class Groups::Clusters::ApplicationsController < Clusters::ApplicationsController
+ include ControllerWithCrossProjectAccessCheck
+
+ prepend_before_action :group
+ requires_cross_project_access
+
+ private
+
+ def clusterable
+ @clusterable ||= ClusterablePresenter.fabricate(group, current_user: current_user)
+ end
+
+ def group
+ @group ||= find_routable!(Group, params[:group_id] || params[:id])
+ end
+end
diff --git a/app/controllers/groups/clusters_controller.rb b/app/controllers/groups/clusters_controller.rb
new file mode 100644
index 00000000000..50c44b7a58b
--- /dev/null
+++ b/app/controllers/groups/clusters_controller.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class Groups::ClustersController < Clusters::ClustersController
+ include ControllerWithCrossProjectAccessCheck
+
+ prepend_before_action :check_group_clusters_feature_flag!
+ prepend_before_action :group
+ requires_cross_project_access
+
+ layout 'group'
+
+ private
+
+ def clusterable
+ @clusterable ||= ClusterablePresenter.fabricate(group, current_user: current_user)
+ end
+
+ def group
+ @group ||= find_routable!(Group, params[:group_id] || params[:id])
+ end
+
+ def check_group_clusters_feature_flag!
+ render_404 unless Feature.enabled?(:group_clusters)
+ end
+end
diff --git a/app/controllers/groups/group_members_controller.rb b/app/controllers/groups/group_members_controller.rb
index 7dc51f4c357..0bc082246a1 100644
--- a/app/controllers/groups/group_members_controller.rb
+++ b/app/controllers/groups/group_members_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Groups::GroupMembersController < Groups::ApplicationController
include MembershipActions
include MembersPresentation
diff --git a/app/controllers/groups/labels_controller.rb b/app/controllers/groups/labels_controller.rb
index 059cf160fa2..26768c628ca 100644
--- a/app/controllers/groups/labels_controller.rb
+++ b/app/controllers/groups/labels_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Groups::LabelsController < Groups::ApplicationController
include ToggleSubscriptionAction
@@ -10,10 +12,8 @@ class Groups::LabelsController < Groups::ApplicationController
def index
respond_to do |format|
format.html do
- @labels = @group.labels
- .optionally_search(params[:search])
- .order_by(sort)
- .page(params[:page])
+ @labels = GroupLabelsFinder
+ .new(current_user, @group, params.merge(sort: sort)).execute
end
format.json do
render json: LabelSerializer.new.represent_appearance(available_labels)
diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb
index 6bdc0f79ef2..b42116b0f36 100644
--- a/app/controllers/groups/milestones_controller.rb
+++ b/app/controllers/groups/milestones_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Groups::MilestonesController < Groups::ApplicationController
include MilestoneActions
@@ -8,7 +10,7 @@ class Groups::MilestonesController < Groups::ApplicationController
def index
respond_to do |format|
format.html do
- @milestone_states = GlobalMilestone.states_count(group_projects, group)
+ @milestone_states = Milestone.states_count(group_projects, [group])
@milestones = Kaminari.paginate_array(milestones).page(params[:page])
end
format.json do
diff --git a/app/controllers/groups/runners_controller.rb b/app/controllers/groups/runners_controller.rb
index 1036b4e6ed3..dd8fbf7a029 100644
--- a/app/controllers/groups/runners_controller.rb
+++ b/app/controllers/groups/runners_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Groups::RunnersController < Groups::ApplicationController
# Proper policies should be implemented per
# https://gitlab.com/gitlab-org/gitlab-ce/issues/45894
diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb
index 4bf6a2a3ad1..c1dcc463de7 100644
--- a/app/controllers/groups/settings/ci_cd_controller.rb
+++ b/app/controllers/groups/settings/ci_cd_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Groups
module Settings
class CiCdController < Groups::ApplicationController
@@ -5,12 +7,19 @@ module Groups
before_action :authorize_admin_pipeline!
def show
- define_secret_variables
+ define_ci_variables
+ end
+
+ def reset_registration_token
+ @group.reset_runners_token!
+
+ flash[:notice] = 'New runners registration token has been generated!'
+ redirect_to group_settings_ci_cd_path
end
private
- def define_secret_variables
+ def define_ci_variables
@variable = Ci::GroupVariable.new(group: group)
.present(current_user: current_user)
@variables = group.variables.order_key_asc
diff --git a/app/controllers/groups/shared_projects_controller.rb b/app/controllers/groups/shared_projects_controller.rb
index 7dec1f5f402..30b7bfc70ae 100644
--- a/app/controllers/groups/shared_projects_controller.rb
+++ b/app/controllers/groups/shared_projects_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Groups
class SharedProjectsController < Groups::ApplicationController
respond_to :json
diff --git a/app/controllers/groups/uploads_controller.rb b/app/controllers/groups/uploads_controller.rb
index 74760194a1f..7e5cdae0ce3 100644
--- a/app/controllers/groups/uploads_controller.rb
+++ b/app/controllers/groups/uploads_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Groups::UploadsController < Groups::ApplicationController
include UploadsActions
include WorkhorseRequest
diff --git a/app/controllers/groups/variables_controller.rb b/app/controllers/groups/variables_controller.rb
index 4d8a20de017..4f641de0357 100644
--- a/app/controllers/groups/variables_controller.rb
+++ b/app/controllers/groups/variables_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Groups
class VariablesController < Groups::ApplicationController
before_action :authorize_admin_build!
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 062c8c4e9e1..c5d8ac2ed77 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -9,6 +9,9 @@ class GroupsController < Groups::ApplicationController
respond_to :html
+ prepend_before_action(only: [:show, :issues]) { authenticate_sessionless_user!(:rss) }
+ prepend_before_action(only: [:issues_calendar]) { authenticate_sessionless_user!(:ics) }
+
before_action :authenticate_user!, only: [:new, :create]
before_action :group, except: [:index, :new, :create]
diff --git a/app/controllers/health_controller.rb b/app/controllers/health_controller.rb
index ab4bc911e17..dc9a52f8da5 100644
--- a/app/controllers/health_controller.rb
+++ b/app/controllers/health_controller.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class HealthController < ActionController::Base
- protect_from_forgery with: :exception, except: :storage_check, prepend: true
+ protect_from_forgery with: :exception, prepend: true
include RequiresWhitelistedMonitoringClient
CHECKS = [
@@ -25,15 +25,6 @@ class HealthController < ActionController::Base
render_check_results(results)
end
- def storage_check
- results = Gitlab::Git::Storage::Checker.check_all
-
- render json: {
- check_interval: Gitlab::CurrentSettings.current_application_settings.circuitbreaker_check_interval,
- results: results
- }
- end
-
private
def render_check_results(results)
diff --git a/app/controllers/import/base_controller.rb b/app/controllers/import/base_controller.rb
index 14b8c6e4137..042b6b1264f 100644
--- a/app/controllers/import/base_controller.rb
+++ b/app/controllers/import/base_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Import::BaseController < ApplicationController
private
diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb
index f885e04b198..1b30b4dda36 100644
--- a/app/controllers/import/bitbucket_controller.rb
+++ b/app/controllers/import/bitbucket_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Import::BitbucketController < Import::BaseController
before_action :verify_bitbucket_import_enabled
before_action :bitbucket_auth, except: :callback
diff --git a/app/controllers/import/bitbucket_server_controller.rb b/app/controllers/import/bitbucket_server_controller.rb
index fdd1078cdf7..575c40d5f6f 100644
--- a/app/controllers/import/bitbucket_server_controller.rb
+++ b/app/controllers/import/bitbucket_server_controller.rb
@@ -54,14 +54,14 @@ class Import::BitbucketServerController < Import::BaseController
# rubocop: disable CodeReuse/ActiveRecord
def status
- repos = bitbucket_client.repos
+ @collection = bitbucket_client.repos(page_offset: page_offset, limit: limit_per_page)
+ @repos, @incompatible_repos = @collection.partition { |repo| repo.valid? }
- @repos, @incompatible_repos = repos.partition { |repo| repo.valid? }
-
- @already_added_projects = find_already_added_projects('bitbucket_server')
+ # Use the import URL to filter beyond what BaseService#find_already_added_projects
+ @already_added_projects = filter_added_projects('bitbucket_server', @repos.map(&:browse_url))
already_added_projects_names = @already_added_projects.pluck(:import_source)
- @repos.to_a.reject! { |repo| already_added_projects_names.include?(repo.browse_url) }
+ @repos.reject! { |repo| already_added_projects_names.include?(repo.browse_url) }
rescue BitbucketServer::Connection::ConnectionError, BitbucketServer::Client::ServerError => e
flash[:alert] = "Unable to connect to server: #{e}"
clear_session_data
@@ -75,6 +75,12 @@ class Import::BitbucketServerController < Import::BaseController
private
+ # rubocop: disable CodeReuse/ActiveRecord
+ def filter_added_projects(import_type, import_sources)
+ current_user.created_projects.where(import_type: import_type, import_source: import_sources).includes(:import_state)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
def bitbucket_client
@bitbucket_client ||= BitbucketServer::Client.new(credentials)
end
@@ -130,4 +136,12 @@ class Import::BitbucketServerController < Import::BaseController
password: session[personal_access_token_key]
}
end
+
+ def page_offset
+ [0, params[:page].to_i].max
+ end
+
+ def limit_per_page
+ BitbucketServer::Paginator::PAGE_LENGTH
+ end
end
diff --git a/app/controllers/import/fogbugz_controller.rb b/app/controllers/import/fogbugz_controller.rb
index df96d181153..5a439e6de78 100644
--- a/app/controllers/import/fogbugz_controller.rb
+++ b/app/controllers/import/fogbugz_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Import::FogbugzController < Import::BaseController
before_action :verify_fogbugz_import_enabled
before_action :user_map, only: [:new_user_map, :create_user_map]
diff --git a/app/controllers/import/gitea_controller.rb b/app/controllers/import/gitea_controller.rb
index fbd851c64a7..f067ef625aa 100644
--- a/app/controllers/import/gitea_controller.rb
+++ b/app/controllers/import/gitea_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Import::GiteaController < Import::GithubController
def new
if session[access_token_key].present? && session[host_key].present?
@@ -21,7 +23,7 @@ class Import::GiteaController < Import::GithubController
:"#{provider}_host_url"
end
- # Overriden methods
+ # Overridden methods
def provider
:gitea
end
diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb
index f8b43b4fde5..58565aaf8c9 100644
--- a/app/controllers/import/github_controller.rb
+++ b/app/controllers/import/github_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Import::GithubController < Import::BaseController
before_action :verify_import_enabled
before_action :provider_auth, only: [:status, :jobs, :create]
@@ -18,7 +20,7 @@ class Import::GithubController < Import::BaseController
end
def personal_access_token
- session[access_token_key] = params[:personal_access_token]
+ session[access_token_key] = params[:personal_access_token]&.strip
redirect_to status_import_url
end
@@ -101,7 +103,7 @@ class Import::GithubController < Import::BaseController
{ github_access_token: session[access_token_key] }
end
- # The following methods are overriden in subclasses
+ # The following methods are overridden in subclasses
def provider
:github
end
diff --git a/app/controllers/import/gitlab_controller.rb b/app/controllers/import/gitlab_controller.rb
index bdc402b0a77..498de0b07b8 100644
--- a/app/controllers/import/gitlab_controller.rb
+++ b/app/controllers/import/gitlab_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Import::GitlabController < Import::BaseController
MAX_PROJECT_PAGES = 15
PER_PAGE_PROJECTS = 100
diff --git a/app/controllers/import/gitlab_projects_controller.rb b/app/controllers/import/gitlab_projects_controller.rb
index f21c38a4c27..354fba5d204 100644
--- a/app/controllers/import/gitlab_projects_controller.rb
+++ b/app/controllers/import/gitlab_projects_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Import::GitlabProjectsController < Import::BaseController
before_action :whitelist_query_limiting, only: [:create]
before_action :verify_gitlab_project_import_enabled
diff --git a/app/controllers/import/google_code_controller.rb b/app/controllers/import/google_code_controller.rb
index e9387d0ad14..331f06c3dd6 100644
--- a/app/controllers/import/google_code_controller.rb
+++ b/app/controllers/import/google_code_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Import::GoogleCodeController < Import::BaseController
before_action :verify_google_code_import_enabled
before_action :user_map, only: [:new_user_map, :create_user_map]
diff --git a/app/controllers/import/manifest_controller.rb b/app/controllers/import/manifest_controller.rb
index 4ed9dca2475..320cd45b925 100644
--- a/app/controllers/import/manifest_controller.rb
+++ b/app/controllers/import/manifest_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Import::ManifestController < Import::BaseController
before_action :whitelist_query_limiting, only: [:create]
before_action :verify_import_enabled
diff --git a/app/controllers/koding_controller.rb b/app/controllers/koding_controller.rb
deleted file mode 100644
index 72aa9d4f17f..00000000000
--- a/app/controllers/koding_controller.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-class KodingController < ApplicationController
- before_action :check_integration!
- layout 'koding'
-
- def index
- path = File.join(Rails.root, 'doc/user/project/koding.md')
- @markdown = File.read(path)
- end
-
- private
-
- def check_integration!
- render_404 unless Gitlab::CurrentSettings.koding_enabled?
- end
-end
diff --git a/app/controllers/ldap/omniauth_callbacks_controller.rb b/app/controllers/ldap/omniauth_callbacks_controller.rb
index fb24edb8602..5e872804448 100644
--- a/app/controllers/ldap/omniauth_callbacks_controller.rb
+++ b/app/controllers/ldap/omniauth_callbacks_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Ldap::OmniauthCallbacksController < OmniauthCallbacksController
extend ::Gitlab::Utils::Override
diff --git a/app/controllers/metrics_controller.rb b/app/controllers/metrics_controller.rb
index 7353be478e1..c2089a0fca3 100644
--- a/app/controllers/metrics_controller.rb
+++ b/app/controllers/metrics_controller.rb
@@ -15,7 +15,7 @@ class MetricsController < ActionController::Base
"# Metrics are disabled, see: #{help_page}\n"
end
- render text: response, content_type: 'text/plain; version=0.0.4'
+ render plain: response, content_type: 'text/plain; version=0.0.4'
end
private
diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb
index 9e700f648f4..ab4ca56bb49 100644
--- a/app/controllers/oauth/applications_controller.rb
+++ b/app/controllers/oauth/applications_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Oauth::ApplicationsController < Doorkeeper::ApplicationsController
include Gitlab::GonHelper
include Gitlab::Allowable
@@ -7,7 +9,7 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController
before_action :verify_user_oauth_applications_enabled, except: :index
before_action :authenticate_user!
before_action :add_gon_variables
- before_action :load_scopes, only: [:index, :create, :edit]
+ before_action :load_scopes, only: [:index, :create, :edit, :update]
helper_method :can?
diff --git a/app/controllers/oauth/authorizations_controller.rb b/app/controllers/oauth/authorizations_controller.rb
index 05190103767..705389749d8 100644
--- a/app/controllers/oauth/authorizations_controller.rb
+++ b/app/controllers/oauth/authorizations_controller.rb
@@ -1,7 +1,9 @@
+# frozen_string_literal: true
+
class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
layout 'profile'
- # Overriden from Doorkeeper::AuthorizationsController to
+ # Overridden from Doorkeeper::AuthorizationsController to
# include the call to session.delete
def new
if pre_auth.authorizable?
diff --git a/app/controllers/oauth/authorized_applications_controller.rb b/app/controllers/oauth/authorized_applications_controller.rb
index 656107d2b26..a59ade559b3 100644
--- a/app/controllers/oauth/authorized_applications_controller.rb
+++ b/app/controllers/oauth/authorized_applications_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Oauth::AuthorizedApplicationsController < Doorkeeper::AuthorizedApplicationsController
include PageLayoutHelper
diff --git a/app/controllers/profiles/accounts_controller.rb b/app/controllers/profiles/accounts_controller.rb
index fd9cb9fca3e..cb3180f4196 100644
--- a/app/controllers/profiles/accounts_controller.rb
+++ b/app/controllers/profiles/accounts_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Profiles::AccountsController < Profiles::ApplicationController
include AuthHelper
diff --git a/app/controllers/profiles/active_sessions_controller.rb b/app/controllers/profiles/active_sessions_controller.rb
index f1e77d68acd..efe7ede5efa 100644
--- a/app/controllers/profiles/active_sessions_controller.rb
+++ b/app/controllers/profiles/active_sessions_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Profiles::ActiveSessionsController < Profiles::ApplicationController
def index
@sessions = ActiveSession.list(current_user)
diff --git a/app/controllers/profiles/application_controller.rb b/app/controllers/profiles/application_controller.rb
index c8be288b9a0..52b046ef64f 100644
--- a/app/controllers/profiles/application_controller.rb
+++ b/app/controllers/profiles/application_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Profiles::ApplicationController < ApplicationController
layout 'profile'
end
diff --git a/app/controllers/profiles/avatars_controller.rb b/app/controllers/profiles/avatars_controller.rb
index 4f030ded80f..3378a09628c 100644
--- a/app/controllers/profiles/avatars_controller.rb
+++ b/app/controllers/profiles/avatars_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Profiles::AvatarsController < Profiles::ApplicationController
def destroy
@user = current_user
diff --git a/app/controllers/profiles/chat_names_controller.rb b/app/controllers/profiles/chat_names_controller.rb
index a186c5f36a8..2e78b9e6dc7 100644
--- a/app/controllers/profiles/chat_names_controller.rb
+++ b/app/controllers/profiles/chat_names_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Profiles::ChatNamesController < Profiles::ApplicationController
before_action :chat_name_token, only: [:new]
before_action :chat_name_params, only: [:new, :create, :deny]
diff --git a/app/controllers/profiles/emails_controller.rb b/app/controllers/profiles/emails_controller.rb
index a39824ec9c8..503eda250b4 100644
--- a/app/controllers/profiles/emails_controller.rb
+++ b/app/controllers/profiles/emails_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Profiles::EmailsController < Profiles::ApplicationController
before_action :find_email, only: [:destroy, :resend_confirmation_instructions]
diff --git a/app/controllers/profiles/gpg_keys_controller.rb b/app/controllers/profiles/gpg_keys_controller.rb
index c32507756e8..8c34a66c374 100644
--- a/app/controllers/profiles/gpg_keys_controller.rb
+++ b/app/controllers/profiles/gpg_keys_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Profiles::GpgKeysController < Profiles::ApplicationController
before_action :set_gpg_key, only: [:destroy, :revoke]
diff --git a/app/controllers/profiles/keys_controller.rb b/app/controllers/profiles/keys_controller.rb
index 6035258667e..dcee8eb7e6e 100644
--- a/app/controllers/profiles/keys_controller.rb
+++ b/app/controllers/profiles/keys_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Profiles::KeysController < Profiles::ApplicationController
skip_before_action :authenticate_user!, only: [:get_keys]
@@ -36,14 +38,15 @@ class Profiles::KeysController < Profiles::ApplicationController
def get_keys
if params[:username].present?
begin
- user = User.find_by_username(params[:username])
+ user = UserFinder.new(params[:username]).find_by_username
if user.present?
- render text: user.all_ssh_keys.join("\n"), content_type: "text/plain"
+ headers['Content-Disposition'] = 'attachment'
+ render plain: user.all_ssh_keys.join("\n")
else
return render_404
end
rescue => e
- render text: e.message
+ render html: e.message
end
else
return render_404
diff --git a/app/controllers/profiles/notifications_controller.rb b/app/controllers/profiles/notifications_controller.rb
index 00bd2040b9a..b719b70c56e 100644
--- a/app/controllers/profiles/notifications_controller.rb
+++ b/app/controllers/profiles/notifications_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Profiles::NotificationsController < Profiles::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def show
diff --git a/app/controllers/profiles/passwords_controller.rb b/app/controllers/profiles/passwords_controller.rb
index b8ccc6e3c99..a0391d677c4 100644
--- a/app/controllers/profiles/passwords_controller.rb
+++ b/app/controllers/profiles/passwords_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Profiles::PasswordsController < Profiles::ApplicationController
skip_before_action :check_password_expiration, only: [:new, :create]
skip_before_action :check_two_factor_requirement, only: [:new, :create]
diff --git a/app/controllers/profiles/personal_access_tokens_controller.rb b/app/controllers/profiles/personal_access_tokens_controller.rb
index b357741e3fb..4b6ec2697b7 100644
--- a/app/controllers/profiles/personal_access_tokens_controller.rb
+++ b/app/controllers/profiles/personal_access_tokens_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Profiles::PersonalAccessTokensController < Profiles::ApplicationController
def index
set_index_vars
diff --git a/app/controllers/profiles/preferences_controller.rb b/app/controllers/profiles/preferences_controller.rb
index ed0f98179eb..37ac11dc6a1 100644
--- a/app/controllers/profiles/preferences_controller.rb
+++ b/app/controllers/profiles/preferences_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Profiles::PreferencesController < Profiles::ApplicationController
before_action :user
diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb
index 29ff18a1219..ba94196b2f9 100644
--- a/app/controllers/profiles/two_factor_auths_controller.rb
+++ b/app/controllers/profiles/two_factor_auths_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
skip_before_action :check_two_factor_requirement
@@ -30,7 +32,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
unless two_factor_grace_period_expired?
grace_period_deadline = current_user.otp_grace_period_started_at + two_factor_grace_period.hours
- flash.now[:alert] << " You need to do this before #{l(grace_period_deadline)}."
+ flash.now[:alert] = flash.now[:alert] + " You need to do this before #{l(grace_period_deadline)}."
end
end
diff --git a/app/controllers/profiles/u2f_registrations_controller.rb b/app/controllers/profiles/u2f_registrations_controller.rb
index e3d7737f44a..e6a154fb6aa 100644
--- a/app/controllers/profiles/u2f_registrations_controller.rb
+++ b/app/controllers/profiles/u2f_registrations_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Profiles::U2fRegistrationsController < Profiles::ApplicationController
def destroy
u2f_registration = current_user.u2f_registrations.find(params[:id])
diff --git a/app/controllers/projects/application_controller.rb b/app/controllers/projects/application_controller.rb
index 695ffd90a85..e0677ce3fbc 100644
--- a/app/controllers/projects/application_controller.rb
+++ b/app/controllers/projects/application_controller.rb
@@ -1,6 +1,9 @@
+# frozen_string_literal: true
+
class Projects::ApplicationController < ApplicationController
include CookiesHelper
include RoutableActions
+ include ProjectUnauthorized
include ChecksCollaboration
skip_before_action :authenticate_user!
@@ -19,7 +22,7 @@ class Projects::ApplicationController < ApplicationController
path = File.join(params[:namespace_id], params[:project_id] || params[:id])
auth_proc = ->(project) { !project.pending_delete? }
- @project = find_routable!(Project, path, extra_authorization_proc: auth_proc)
+ @project = find_routable!(Project, path, extra_authorization_proc: auth_proc, not_found_or_authorized_proc: project_unauthorized_proc)
end
def build_canonical_path(project)
diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb
index 3e8ffa485dd..1a91e07b97f 100644
--- a/app/controllers/projects/artifacts_controller.rb
+++ b/app/controllers/projects/artifacts_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::ArtifactsController < Projects::ApplicationController
include ExtractsPath
include RendersBlob
@@ -7,12 +9,13 @@ class Projects::ArtifactsController < Projects::ApplicationController
before_action :authorize_read_build!
before_action :authorize_update_build!, only: [:keep]
before_action :extract_ref_name_and_path
- before_action :set_request_format, only: [:file]
- before_action :validate_artifacts!
+ before_action :validate_artifacts!, except: [:download]
before_action :entry, only: [:file]
def download
- send_upload(artifacts_file, attachment: artifacts_file.filename)
+ return render_404 unless artifacts_file
+
+ send_upload(artifacts_file, attachment: artifacts_file.filename, proxy: params[:proxy])
end
def browse
@@ -98,7 +101,7 @@ class Projects::ArtifactsController < Projects::ApplicationController
# rubocop: enable CodeReuse/ActiveRecord
def artifacts_file
- @artifacts_file ||= build.artifacts_file
+ @artifacts_file ||= build&.artifacts_file_for_type(params[:file_type] || :archive)
end
def entry
@@ -106,12 +109,4 @@ class Projects::ArtifactsController < Projects::ApplicationController
render_404 unless @entry.exists?
end
-
- def set_request_format
- request.format = :html if set_request_format?
- end
-
- def set_request_format?
- request.format != :json
- end
end
diff --git a/app/controllers/projects/autocomplete_sources_controller.rb b/app/controllers/projects/autocomplete_sources_controller.rb
index a8f73ed5cb0..9c130af8394 100644
--- a/app/controllers/projects/autocomplete_sources_controller.rb
+++ b/app/controllers/projects/autocomplete_sources_controller.rb
@@ -1,34 +1,38 @@
-class Projects::AutocompleteSourcesController < Projects::ApplicationController
- before_action :load_autocomplete_service, except: [:members]
+# frozen_string_literal: true
+class Projects::AutocompleteSourcesController < Projects::ApplicationController
def members
render json: ::Projects::ParticipantsService.new(@project, current_user).execute(target)
end
def issues
- render json: @autocomplete_service.issues
+ render json: autocomplete_service.issues
end
def merge_requests
- render json: @autocomplete_service.merge_requests
+ render json: autocomplete_service.merge_requests
end
def labels
- render json: @autocomplete_service.labels_as_hash(target)
+ render json: autocomplete_service.labels_as_hash(target)
end
def milestones
- render json: @autocomplete_service.milestones
+ render json: autocomplete_service.milestones
end
def commands
- render json: @autocomplete_service.commands(target, params[:type])
+ render json: autocomplete_service.commands(target, params[:type])
+ end
+
+ def snippets
+ render json: autocomplete_service.snippets
end
private
- def load_autocomplete_service
- @autocomplete_service = ::Projects::AutocompleteService.new(@project, current_user)
+ def autocomplete_service
+ @autocomplete_service ||= ::Projects::AutocompleteService.new(@project, current_user)
end
def target
diff --git a/app/controllers/projects/avatars_controller.rb b/app/controllers/projects/avatars_controller.rb
index 878c82cd183..1f4a25f82e9 100644
--- a/app/controllers/projects/avatars_controller.rb
+++ b/app/controllers/projects/avatars_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::AvatarsController < Projects::ApplicationController
include SendsBlob
@@ -6,7 +8,7 @@ class Projects::AvatarsController < Projects::ApplicationController
def show
@blob = @repository.blob_at_branch(@repository.root_ref, @project.avatar_in_git)
- send_blob(@blob)
+ send_blob(@repository, @blob)
end
def destroy
diff --git a/app/controllers/projects/badges_controller.rb b/app/controllers/projects/badges_controller.rb
index 06ba73d8e8d..c24bf211760 100644
--- a/app/controllers/projects/badges_controller.rb
+++ b/app/controllers/projects/badges_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::BadgesController < Projects::ApplicationController
layout 'project_settings'
before_action :authorize_admin_project!, only: [:index]
diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb
index 6461eeac11c..9076bdb9f04 100644
--- a/app/controllers/projects/blame_controller.rb
+++ b/app/controllers/projects/blame_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Controller for viewing a file's blame
class Projects::BlameController < Projects::ApplicationController
include ExtractsPath
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index bfe4e7f934f..60fabd15333 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Controller for viewing a file's blame
class Projects::BlobController < Projects::ApplicationController
include ExtractsPath
@@ -7,7 +9,6 @@ class Projects::BlobController < Projects::ApplicationController
include ActionView::Helpers::SanitizeHelper
prepend_before_action :authenticate_user!, only: [:edit]
- before_action :set_request_format, only: [:edit, :show, :update]
before_action :require_non_empty_project, except: [:new, :create]
before_action :authorize_download_code!
@@ -81,7 +82,7 @@ class Projects::BlobController < Projects::ApplicationController
def destroy
create_commit(Files::DeleteService, success_notice: "The file has been successfully deleted.",
- success_path: -> { project_tree_path(@project, @branch_name) },
+ success_path: -> { after_delete_path },
failure_view: :show,
failure_path: project_blob_path(@project, @id))
end
@@ -90,7 +91,7 @@ class Projects::BlobController < Projects::ApplicationController
apply_diff_view_cookie!
@blob.load_all_data!
- @lines = Gitlab::Highlight.highlight(@blob.path, @blob.data, repository: @repository).lines
+ @lines = @blob.present.highlight.lines
@form = UnfoldForm.new(params)
@@ -120,7 +121,7 @@ class Projects::BlobController < Projects::ApplicationController
@lines.map! do |line|
# These are marked as context lines but are loaded from blobs.
# We also have context lines loaded from diffs in other places.
- diff_line = Gitlab::Diff::Line.new(line, 'context', nil, nil, nil)
+ diff_line = Gitlab::Diff::Line.new(line, nil, nil, nil, nil)
diff_line.rich_text = line
diff_line
end
@@ -189,6 +190,15 @@ class Projects::BlobController < Projects::ApplicationController
end
# rubocop: enable CodeReuse/ActiveRecord
+ def after_delete_path
+ branch = BranchesFinder.new(@repository, search: @ref).execute.first
+ if @repository.tree(branch.target, tree_path).entries.empty?
+ project_tree_path(@project, @ref)
+ else
+ project_tree_path(@project, File.join(@ref, tree_path))
+ end
+ end
+
def editor_variables
@branch_name = params[:branch_name]
@@ -222,7 +232,7 @@ class Projects::BlobController < Projects::ApplicationController
def validate_diff_params
if [:since, :to, :offset].any? { |key| params[key].blank? }
- render nothing: true
+ head :ok
end
end
@@ -231,18 +241,6 @@ class Projects::BlobController < Projects::ApplicationController
.last_for_path(@repository, @ref, @path).sha
end
- # In Rails 4.2 if params[:format] is empty, Rails set it to :html
- # But since Rails 5.0 the framework now looks for an extension.
- # E.g. for `blob/master/CHANGELOG.md` in Rails 4 the format would be `:html`, but in Rails 5 on it'd be `:md`
- # This before_action explicitly sets the `:html` format for all requests unless `:format` is set by a client e.g. by JS for XHR requests.
- def set_request_format
- request.format = :html if set_request_format?
- end
-
- def set_request_format?
- params[:id].present? && params[:format].blank? && request.format != "json"
- end
-
def show_html
environment_params = @repository.branch_exists?(@ref) ? { ref: @ref } : { commit: @commit }
@environment = EnvironmentsFinder.new(@project, current_user, environment_params).execute.last
@@ -253,9 +251,6 @@ class Projects::BlobController < Projects::ApplicationController
def show_json
set_last_commit_sha
- path_segments = @path.split('/')
- path_segments.pop
- tree_path = path_segments.join('/')
json = {
id: @blob.id,
@@ -281,4 +276,8 @@ class Projects::BlobController < Projects::ApplicationController
render json: json
end
+
+ def tree_path
+ @path.rpartition('/').first
+ end
end
diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb
index e7354a9e1f7..8189b5d182a 100644
--- a/app/controllers/projects/boards_controller.rb
+++ b/app/controllers/projects/boards_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::BoardsController < Projects::ApplicationController
include BoardsResponses
include IssuableCollections
@@ -6,6 +8,7 @@ class Projects::BoardsController < Projects::ApplicationController
before_action :authorize_read_board!, only: [:index, :show]
before_action :boards, only: :index
before_action :assign_endpoint_vars
+ before_action :redirect_to_recent_board, only: :index
def index
respond_with_boards
@@ -14,6 +17,9 @@ class Projects::BoardsController < Projects::ApplicationController
def show
@board = boards.find(params[:id])
+ # add/update the board in the recent visited table
+ Boards::Visits::CreateService.new(@board.project, current_user).execute(@board) if request.format.html?
+
respond_with_board
end
@@ -31,10 +37,24 @@ class Projects::BoardsController < Projects::ApplicationController
end
def authorize_read_board!
- return access_denied! unless can?(current_user, :read_board, project)
+ access_denied! unless can?(current_user, :read_board, project)
end
def serialize_as_json(resource)
resource.as_json(only: [:id])
end
+
+ def includes_board?(board_id)
+ boards.any? { |board| board.id == board_id }
+ end
+
+ def redirect_to_recent_board
+ return if request.format.json?
+
+ recently_visited = Boards::Visits::LatestService.new(project, current_user).execute
+
+ if recently_visited && includes_board?(recently_visited.board_id)
+ redirect_to(namespace_project_board_path(id: recently_visited.board_id), status: :found)
+ end
+ end
end
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index d14795e787b..95a014d24da 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::BranchesController < Projects::ApplicationController
include ActionView::Helpers::SanitizeHelper
include SortingHelper
@@ -103,7 +105,7 @@ class Projects::BranchesController < Projects::ApplicationController
redirect_to project_branches_path(@project), status: :see_other
end
- format.js { render nothing: true, status: result[:return_code] }
+ format.js { head result[:return_code] }
format.json { render json: { message: result[:message] }, status: result[:return_code] }
end
end
diff --git a/app/controllers/projects/build_artifacts_controller.rb b/app/controllers/projects/build_artifacts_controller.rb
index 9e99a84fac7..7d4d566499c 100644
--- a/app/controllers/projects/build_artifacts_controller.rb
+++ b/app/controllers/projects/build_artifacts_controller.rb
@@ -1,13 +1,15 @@
+# frozen_string_literal: true
+
class Projects::BuildArtifactsController < Projects::ApplicationController
include ExtractsPath
include RendersBlob
before_action :authorize_read_build!
before_action :extract_ref_name_and_path
- before_action :validate_artifacts!
+ before_action :validate_artifacts!, except: [:download]
def download
- redirect_to download_project_job_artifacts_path(project, job)
+ redirect_to download_project_job_artifacts_path(project, job, params: request.query_parameters)
end
def browse
diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb
index 230b072dcea..6b3d70cb720 100644
--- a/app/controllers/projects/builds_controller.rb
+++ b/app/controllers/projects/builds_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::BuildsController < Projects::ApplicationController
before_action :authorize_read_build!
diff --git a/app/controllers/projects/ci/lints_controller.rb b/app/controllers/projects/ci/lints_controller.rb
index a2185572a20..2090af0a111 100644
--- a/app/controllers/projects/ci/lints_controller.rb
+++ b/app/controllers/projects/ci/lints_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::Ci::LintsController < Projects::ApplicationController
before_action :authorize_create_pipeline!
diff --git a/app/controllers/projects/clusters/applications_controller.rb b/app/controllers/projects/clusters/applications_controller.rb
index 8c9df51981a..c7b6218d007 100644
--- a/app/controllers/projects/clusters/applications_controller.rb
+++ b/app/controllers/projects/clusters/applications_controller.rb
@@ -1,49 +1,17 @@
-class Projects::Clusters::ApplicationsController < Projects::ApplicationController
- before_action :cluster
- before_action :application_class, only: [:create]
- before_action :authorize_read_cluster!
- before_action :authorize_create_cluster!, only: [:create]
+# frozen_string_literal: true
- # rubocop: disable CodeReuse/ActiveRecord
- def create
- application = @application_class.find_or_initialize_by(cluster: @cluster)
+class Projects::Clusters::ApplicationsController < Clusters::ApplicationsController
+ include ProjectUnauthorized
- if application.has_attribute?(:hostname)
- application.hostname = params[:hostname]
- end
-
- if application.respond_to?(:oauth_application)
- application.oauth_application = create_oauth_application(application)
- end
-
- application.save!
-
- Clusters::Applications::ScheduleInstallationService.new(project, current_user).execute(application)
-
- head :no_content
- rescue StandardError
- head :bad_request
- end
- # rubocop: enable CodeReuse/ActiveRecord
+ prepend_before_action :project
private
- def cluster
- @cluster ||= project.clusters.find(params[:id]) || render_404
- end
-
- def application_class
- @application_class ||= Clusters::Cluster::APPLICATIONS[params[:application]] || render_404
+ def clusterable
+ @clusterable ||= ClusterablePresenter.fabricate(project, current_user: current_user)
end
- def create_oauth_application(application)
- oauth_application_params = {
- name: params[:application],
- redirect_uri: application.callback_url,
- scopes: 'api read_user openid',
- owner: current_user
- }
-
- Applications::CreateService.new(current_user, oauth_application_params).execute(request)
+ def project
+ @project ||= find_routable!(Project, File.join(params[:namespace_id], params[:project_id]), not_found_or_authorized_proc: project_unauthorized_proc)
end
end
diff --git a/app/controllers/projects/clusters_controller.rb b/app/controllers/projects/clusters_controller.rb
index eb0fad6cbb2..feda6deeaa6 100644
--- a/app/controllers/projects/clusters_controller.rb
+++ b/app/controllers/projects/clusters_controller.rb
@@ -1,222 +1,24 @@
-class Projects::ClustersController < Projects::ApplicationController
- before_action :cluster, except: [:index, :new, :create_gcp, :create_user]
- before_action :authorize_read_cluster!
- before_action :generate_gcp_authorize_url, only: [:new]
- before_action :validate_gcp_token, only: [:new]
- before_action :gcp_cluster, only: [:new]
- before_action :user_cluster, only: [:new]
- before_action :authorize_create_cluster!, only: [:new]
- before_action :authorize_update_cluster!, only: [:update]
- before_action :authorize_admin_cluster!, only: [:destroy]
- before_action :update_applications_status, only: [:status]
- helper_method :token_in_session
+# frozen_string_literal: true
- STATUS_POLLING_INTERVAL = 10_000
+class Projects::ClustersController < Clusters::ClustersController
+ include ProjectUnauthorized
- def index
- clusters = ClustersFinder.new(project, current_user, :all).execute
- @clusters = clusters.page(params[:page]).per(20)
- end
-
- def new
- end
-
- def status
- respond_to do |format|
- format.json do
- Gitlab::PollingInterval.set_header(response, interval: STATUS_POLLING_INTERVAL)
-
- render json: ClusterSerializer
- .new(project: @project, current_user: @current_user)
- .represent_status(@cluster)
- end
- end
- end
-
- def show
- end
-
- def update
- Clusters::UpdateService
- .new(project, current_user, update_params)
- .execute(cluster)
-
- if cluster.valid?
- respond_to do |format|
- format.json do
- head :no_content
- end
- format.html do
- flash[:notice] = _('Kubernetes cluster was successfully updated.')
- redirect_to project_cluster_path(project, cluster)
- end
- end
- else
- respond_to do |format|
- format.json { head :bad_request }
- format.html { render :show }
- end
- end
- end
+ prepend_before_action :project
+ before_action :repository
- def destroy
- if cluster.destroy
- flash[:notice] = _('Kubernetes cluster integration was successfully removed.')
- redirect_to project_clusters_path(project), status: :found
- else
- flash[:notice] = _('Kubernetes cluster integration was not removed.')
- render :show
- end
- end
-
- def create_gcp
- @gcp_cluster = ::Clusters::CreateService
- .new(project, current_user, create_gcp_cluster_params)
- .execute(token_in_session)
-
- if @gcp_cluster.persisted?
- redirect_to project_cluster_path(project, @gcp_cluster)
- else
- generate_gcp_authorize_url
- validate_gcp_token
- user_cluster
-
- render :new, locals: { active_tab: 'gcp' }
- end
- end
-
- def create_user
- @user_cluster = ::Clusters::CreateService
- .new(project, current_user, create_user_cluster_params)
- .execute(token_in_session)
-
- if @user_cluster.persisted?
- redirect_to project_cluster_path(project, @user_cluster)
- else
- generate_gcp_authorize_url
- validate_gcp_token
- gcp_cluster
-
- render :new, locals: { active_tab: 'user' }
- end
- end
+ layout 'project'
private
- def cluster
- @cluster ||= project.clusters.find(params[:id])
- .present(current_user: current_user)
- end
-
- def update_params
- if cluster.managed?
- params.require(:cluster).permit(
- :enabled,
- :environment_scope,
- platform_kubernetes_attributes: [
- :namespace
- ]
- )
- else
- params.require(:cluster).permit(
- :enabled,
- :name,
- :environment_scope,
- platform_kubernetes_attributes: [
- :api_url,
- :token,
- :ca_cert,
- :namespace
- ]
- )
- end
- end
-
- def create_gcp_cluster_params
- params.require(:cluster).permit(
- :enabled,
- :name,
- :environment_scope,
- provider_gcp_attributes: [
- :gcp_project_id,
- :zone,
- :num_nodes,
- :machine_type,
- :legacy_abac
- ]).merge(
- provider_type: :gcp,
- platform_type: :kubernetes
- )
- end
-
- def create_user_cluster_params
- params.require(:cluster).permit(
- :enabled,
- :name,
- :environment_scope,
- platform_kubernetes_attributes: [
- :namespace,
- :api_url,
- :token,
- :ca_cert,
- :authorization_type
- ]).merge(
- provider_type: :user,
- platform_type: :kubernetes
- )
- end
-
- def generate_gcp_authorize_url
- state = generate_session_key_redirect(new_project_cluster_path(@project).to_s)
-
- @authorize_url = GoogleApi::CloudPlatform::Client.new(
- nil, callback_google_api_auth_url,
- state: state).authorize_url
- rescue GoogleApi::Auth::ConfigMissingError
- # no-op
- end
-
- def gcp_cluster
- @gcp_cluster = ::Clusters::Cluster.new.tap do |cluster|
- cluster.build_provider_gcp
- end
- end
-
- def user_cluster
- @user_cluster = ::Clusters::Cluster.new.tap do |cluster|
- cluster.build_platform_kubernetes
- end
- end
-
- def validate_gcp_token
- @valid_gcp_token = GoogleApi::CloudPlatform::Client.new(token_in_session, nil)
- .validate_token(expires_at_in_session)
- end
-
- def token_in_session
- session[GoogleApi::CloudPlatform::Client.session_key_for_token]
- end
-
- def expires_at_in_session
- @expires_at_in_session ||=
- session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at]
- end
-
- def generate_session_key_redirect(uri)
- GoogleApi::CloudPlatform::Client.new_session_key_for_redirect_uri do |key|
- session[key] = uri
- end
- end
-
- def authorize_update_cluster!
- access_denied! unless can?(current_user, :update_cluster, cluster)
+ def clusterable
+ @clusterable ||= ClusterablePresenter.fabricate(project, current_user: current_user)
end
- def authorize_admin_cluster!
- access_denied! unless can?(current_user, :admin_cluster, cluster)
+ def project
+ @project ||= find_routable!(Project, File.join(params[:namespace_id], params[:project_id]), not_found_or_authorized_proc: project_unauthorized_proc)
end
- def update_applications_status
- @cluster.applications.each(&:schedule_status_update)
+ def repository
+ @repository ||= project.repository
end
end
diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb
index 81f375875b2..32fc5140366 100644
--- a/app/controllers/projects/commit_controller.rb
+++ b/app/controllers/projects/commit_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Controller for a specific Commit
#
# Not to be confused with CommitsController, plural.
@@ -41,7 +43,7 @@ class Projects::CommitController < Projects::ApplicationController
# rubocop: disable CodeReuse/ActiveRecord
def pipelines
@pipelines = @commit.pipelines.order(id: :desc)
- @pipelines = @pipelines.where(ref: params[:ref]) if params[:ref]
+ @pipelines = @pipelines.where(ref: params[:ref]).page(params[:page]).per(30) if params[:ref]
respond_to do |format|
format.html
@@ -51,6 +53,7 @@ class Projects::CommitController < Projects::ApplicationController
render json: {
pipelines: PipelineSerializer
.new(project: @project, current_user: @current_user)
+ .with_pagination(request, response)
.represent(@pipelines),
count: {
all: @pipelines.count
diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb
index cd9c9aa30f1..e40a1a1d744 100644
--- a/app/controllers/projects/commits_controller.rb
+++ b/app/controllers/projects/commits_controller.rb
@@ -1,15 +1,17 @@
+# frozen_string_literal: true
+
require "base64"
class Projects::CommitsController < Projects::ApplicationController
include ExtractsPath
include RendersCommits
+ prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) }
before_action :whitelist_query_limiting, except: :commits_root
before_action :require_non_empty_project
before_action :assign_ref_vars, except: :commits_root
before_action :authorize_download_code!
before_action :set_commits, except: :commits_root
- before_action :set_request_format, only: :show
def commits_root
redirect_to project_commits_path(@project, @project.default_branch)
@@ -68,19 +70,6 @@ class Projects::CommitsController < Projects::ApplicationController
@commits = set_commits_for_rendering(@commits)
end
- # Rails 5 sets request.format from the extension.
- # Explicitly set to :html.
- def set_request_format
- request.format = :html if set_request_format?
- end
-
- # Rails 5 sets request.format from extension.
- # In this case if the ref ends with `.atom`, it's expected to be the html response,
- # not the atom one. So explicitly set request.format as :html to act like rails4.
- def set_request_format?
- request.format.to_s == "text/html" || @commits.ref.ends_with?("atom")
- end
-
def whitelist_query_limiting
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/42330')
end
diff --git a/app/controllers/projects/compare_controller.rb b/app/controllers/projects/compare_controller.rb
index cca77903250..2917925947f 100644
--- a/app/controllers/projects/compare_controller.rb
+++ b/app/controllers/projects/compare_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'addressable/uri'
class Projects::CompareController < Projects::ApplicationController
@@ -14,6 +16,8 @@ class Projects::CompareController < Projects::ApplicationController
before_action :define_diff_notes_disabled, only: [:show, :diff_for_path]
before_action :define_commits, only: [:show, :diff_for_path, :signatures]
before_action :merge_request, only: [:index, :show]
+ # Validation
+ before_action :validate_refs!
def index
end
@@ -61,6 +65,21 @@ class Projects::CompareController < Projects::ApplicationController
private
+ def valid_ref?(ref_name)
+ return true unless ref_name.present?
+
+ Gitlab::GitRefValidator.validate(ref_name)
+ end
+
+ def validate_refs!
+ valid = [head_ref, start_ref].map { |ref| valid_ref?(ref) }
+
+ return if valid.all?
+
+ flash[:alert] = "Invalid branch name"
+ redirect_to project_compare_index_path(@project)
+ end
+
def compare
return @compare if defined?(@compare)
diff --git a/app/controllers/projects/cycle_analytics/events_controller.rb b/app/controllers/projects/cycle_analytics/events_controller.rb
index 26f3c114108..fb43356ff10 100644
--- a/app/controllers/projects/cycle_analytics/events_controller.rb
+++ b/app/controllers/projects/cycle_analytics/events_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Projects
module CycleAnalytics
class EventsController < Projects::ApplicationController
diff --git a/app/controllers/projects/cycle_analytics_controller.rb b/app/controllers/projects/cycle_analytics_controller.rb
index d1b8fd80c4e..8c071496ba9 100644
--- a/app/controllers/projects/cycle_analytics_controller.rb
+++ b/app/controllers/projects/cycle_analytics_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::CycleAnalyticsController < Projects::ApplicationController
include ActionView::Helpers::DateHelper
include ActionView::Helpers::TextHelper
diff --git a/app/controllers/projects/deploy_keys_controller.rb b/app/controllers/projects/deploy_keys_controller.rb
index 2555139cd2c..0a593bd35b6 100644
--- a/app/controllers/projects/deploy_keys_controller.rb
+++ b/app/controllers/projects/deploy_keys_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::DeployKeysController < Projects::ApplicationController
include RepositorySettingsRedirect
respond_to :html
@@ -44,7 +46,9 @@ class Projects::DeployKeysController < Projects::ApplicationController
end
def enable
- Projects::EnableDeployKeyService.new(@project, current_user, params).execute
+ key = Projects::EnableDeployKeyService.new(@project, current_user, params).execute
+
+ return render_404 unless key
respond_to do |format|
format.html { redirect_to_repository_settings(@project, anchor: 'js-deploy-keys-settings') }
@@ -52,19 +56,16 @@ class Projects::DeployKeysController < Projects::ApplicationController
end
end
- # rubocop: disable CodeReuse/ActiveRecord
def disable
- deploy_key_project = @project.deploy_keys_projects.find_by(deploy_key_id: params[:id])
- return render_404 unless deploy_key_project
+ deploy_key_project = Projects::DisableDeployKeyService.new(@project, current_user, params).execute
- deploy_key_project.destroy!
+ return render_404 unless deploy_key_project
respond_to do |format|
format.html { redirect_to_repository_settings(@project, anchor: 'js-deploy-keys-settings') }
format.json { head :ok }
end
end
- # rubocop: enable CodeReuse/ActiveRecord
protected
diff --git a/app/controllers/projects/deploy_tokens_controller.rb b/app/controllers/projects/deploy_tokens_controller.rb
index 83abda64fe0..830b1f4fe4a 100644
--- a/app/controllers/projects/deploy_tokens_controller.rb
+++ b/app/controllers/projects/deploy_tokens_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::DeployTokensController < Projects::ApplicationController
before_action :authorize_admin_project!
diff --git a/app/controllers/projects/deployments_controller.rb b/app/controllers/projects/deployments_controller.rb
index 5a2da7274d1..0a009477d61 100644
--- a/app/controllers/projects/deployments_controller.rb
+++ b/app/controllers/projects/deployments_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::DeploymentsController < Projects::ApplicationController
before_action :authorize_read_environment!
before_action :authorize_read_deployment!
diff --git a/app/controllers/projects/discussions_controller.rb b/app/controllers/projects/discussions_controller.rb
index efdddb24290..b62606067c0 100644
--- a/app/controllers/projects/discussions_controller.rb
+++ b/app/controllers/projects/discussions_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::DiscussionsController < Projects::ApplicationController
include NotesHelper
include RendersNotes
diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb
index be22950286e..e940f382a19 100644
--- a/app/controllers/projects/environments_controller.rb
+++ b/app/controllers/projects/environments_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::EnvironmentsController < Projects::ApplicationController
layout 'project'
before_action :authorize_read_environment!
@@ -120,7 +122,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController
set_workhorse_internal_api_content_type
render json: Gitlab::Workhorse.terminal_websocket(terminal)
else
- render text: 'Not found', status: :not_found
+ render html: 'Not found', status: :not_found
end
end
diff --git a/app/controllers/projects/find_file_controller.rb b/app/controllers/projects/find_file_controller.rb
index cf53ad0a670..c026e9ff332 100644
--- a/app/controllers/projects/find_file_controller.rb
+++ b/app/controllers/projects/find_file_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Controller for viewing a repository's file structure
class Projects::FindFileController < Projects::ApplicationController
include ExtractsPath
diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb
index b709edc8f10..7a1700a206a 100644
--- a/app/controllers/projects/forks_controller.rb
+++ b/app/controllers/projects/forks_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::ForksController < Projects::ApplicationController
include ContinueParams
diff --git a/app/controllers/projects/git_http_client_controller.rb b/app/controllers/projects/git_http_client_controller.rb
index a52814e6e52..d439db97252 100644
--- a/app/controllers/projects/git_http_client_controller.rb
+++ b/app/controllers/projects/git_http_client_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This file should be identical in GitLab Community Edition and Enterprise Edition
class Projects::GitHttpClientController < Projects::ApplicationController
diff --git a/app/controllers/projects/git_http_controller.rb b/app/controllers/projects/git_http_controller.rb
index 1dcf837f78e..c0aa39d87c6 100644
--- a/app/controllers/projects/git_http_controller.rb
+++ b/app/controllers/projects/git_http_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::GitHttpController < Projects::GitHttpClientController
include WorkhorseRequest
@@ -6,6 +8,7 @@ class Projects::GitHttpController < Projects::GitHttpClientController
rescue_from Gitlab::GitAccess::UnauthorizedError, with: :render_403
rescue_from Gitlab::GitAccess::NotFoundError, with: :render_404
rescue_from Gitlab::GitAccess::ProjectCreationError, with: :render_422
+ rescue_from Gitlab::GitAccess::TimeoutError, with: :render_503
# GET /foo/bar.git/info/refs?service=git-upload-pack (git pull)
# GET /foo/bar.git/info/refs?service=git-receive-pack (git push)
@@ -60,6 +63,10 @@ class Projects::GitHttpController < Projects::GitHttpClientController
render plain: exception.message, status: :unprocessable_entity
end
+ def render_503(exception)
+ render plain: exception.message, status: :service_unavailable
+ end
+
def access
@access ||= access_klass.new(access_actor, project,
'http', authentication_abilities: authentication_abilities,
diff --git a/app/controllers/projects/graphs_controller.rb b/app/controllers/projects/graphs_controller.rb
index 475d4c86294..925b6ed9bfd 100644
--- a/app/controllers/projects/graphs_controller.rb
+++ b/app/controllers/projects/graphs_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::GraphsController < Projects::ApplicationController
include ExtractsPath
diff --git a/app/controllers/projects/group_links_controller.rb b/app/controllers/projects/group_links_controller.rb
index bc5f38f3c2b..7c713c19762 100644
--- a/app/controllers/projects/group_links_controller.rb
+++ b/app/controllers/projects/group_links_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::GroupLinksController < Projects::ApplicationController
layout 'project_settings'
before_action :authorize_admin_project!
diff --git a/app/controllers/projects/hook_logs_controller.rb b/app/controllers/projects/hook_logs_controller.rb
index 745e89fc843..a7afc3d77a5 100644
--- a/app/controllers/projects/hook_logs_controller.rb
+++ b/app/controllers/projects/hook_logs_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::HookLogsController < Projects::ApplicationController
include HooksExecution
diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb
index bbf8c7d5cbc..bc84418b79f 100644
--- a/app/controllers/projects/hooks_controller.rb
+++ b/app/controllers/projects/hooks_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::HooksController < Projects::ApplicationController
include HooksExecution
diff --git a/app/controllers/projects/imports_controller.rb b/app/controllers/projects/imports_controller.rb
index 49aa32119ef..a10e159ea1e 100644
--- a/app/controllers/projects/imports_controller.rb
+++ b/app/controllers/projects/imports_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::ImportsController < Projects::ApplicationController
include ContinueParams
@@ -11,10 +13,8 @@ class Projects::ImportsController < Projects::ApplicationController
end
def create
- @project.import_url = params[:project][:import_url]
-
- if @project.save
- @project.reload.import_schedule
+ if @project.update(safe_import_params)
+ @project.import_state.reload.schedule
end
redirect_to project_import_path(@project)
@@ -22,7 +22,7 @@ class Projects::ImportsController < Projects::ApplicationController
def show
if @project.import_finished?
- if continue_params
+ if continue_params&.key?(:to)
redirect_to continue_params[:to], notice: continue_params[:notice]
else
redirect_to project_path(@project), notice: finished_notice
@@ -65,4 +65,12 @@ class Projects::ImportsController < Projects::ApplicationController
redirect_to project_path(@project)
end
end
+
+ def import_params
+ params.require(:project).permit(:import_url)
+ end
+
+ def safe_import_params
+ import_params
+ end
end
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 632e498e4ba..c6ab6b4642e 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::IssuesController < Projects::ApplicationController
include RendersNotes
include ToggleSubscriptionAction
@@ -7,12 +9,24 @@ class Projects::IssuesController < Projects::ApplicationController
include IssuesCalendar
include SpammableActions
- prepend_before_action :authenticate_user!, only: [:new]
+ def self.issue_except_actions
+ %i[index calendar new create bulk_update]
+ end
+
+ def self.set_issuables_index_only_actions
+ %i[index calendar]
+ end
+
+ prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) }
+ prepend_before_action(only: [:calendar]) { authenticate_sessionless_user!(:ics) }
+ prepend_before_action :authenticate_new_issue!, only: [:new]
+ prepend_before_action :store_uri, only: [:new, :show]
before_action :whitelist_query_limiting, only: [:create, :create_merge_request, :move, :bulk_update]
before_action :check_issues_available!
- before_action :issue, except: [:index, :calendar, :new, :create, :bulk_update]
- before_action :set_issuables_index, only: [:index, :calendar]
+ before_action :issue, except: issue_except_actions
+
+ before_action :set_issuables_index, only: set_issuables_index_only_actions
# Allow write(create) issue
before_action :authorize_create_issue!, only: [:new, :create]
@@ -23,6 +37,8 @@ class Projects::IssuesController < Projects::ApplicationController
# Allow create a new branch and empty WIP merge request from current issue
before_action :authorize_create_merge_request_from!, only: [:create_merge_request]
+ before_action :set_suggested_issues_feature_flags, only: [:new]
+
respond_to :html
def index
@@ -125,7 +141,7 @@ class Projects::IssuesController < Projects::ApplicationController
end
def related_branches
- @related_branches = @issue.related_branches(current_user)
+ @related_branches = Issues::RelatedBranchesService.new(project, current_user).execute(issue)
respond_to do |format|
format.json do
@@ -215,16 +231,18 @@ class Projects::IssuesController < Projects::ApplicationController
] + [{ label_ids: [], assignee_ids: [] }]
end
- def authenticate_user!
+ def authenticate_new_issue!
return if current_user
notice = "Please sign in to create the new issue."
+ redirect_to new_user_session_path, notice: notice
+ end
+
+ def store_uri
if request.get? && !request.xhr?
store_location_for :user, request.fullpath
end
-
- redirect_to new_user_session_path, notice: notice
end
def serializer
@@ -248,4 +266,9 @@ class Projects::IssuesController < Projects::ApplicationController
# 3. https://gitlab.com/gitlab-org/gitlab-ce/issues/42426
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/42422')
end
+
+ def set_suggested_issues_feature_flags
+ push_frontend_feature_flag(:graphql)
+ push_frontend_feature_flag(:issue_suggestions)
+ end
end
diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb
index 62b74e84c2c..3ecf94c008e 100644
--- a/app/controllers/projects/jobs_controller.rb
+++ b/app/controllers/projects/jobs_controller.rb
@@ -1,5 +1,8 @@
+# frozen_string_literal: true
+
class Projects::JobsController < Projects::ApplicationController
include SendFileUpload
+ include ContinueParams
before_action :build, except: [:index, :cancel_all]
before_action :authorize_read_build!
@@ -105,6 +108,18 @@ class Projects::JobsController < Projects::ApplicationController
return respond_422 unless @build.cancelable?
@build.cancel
+
+ if continue_params
+ redirect_to continue_params[:to]
+ else
+ redirect_to builds_project_pipeline_path(@project, @build.pipeline.id)
+ end
+ end
+
+ def unschedule
+ return respond_422 unless @build.scheduled?
+
+ @build.unschedule!
redirect_to build_path(@build)
end
diff --git a/app/controllers/projects/labels_controller.rb b/app/controllers/projects/labels_controller.rb
index 1fd4f0721a7..640038818f2 100644
--- a/app/controllers/projects/labels_controller.rb
+++ b/app/controllers/projects/labels_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::LabelsController < Projects::ApplicationController
include ToggleSubscriptionAction
@@ -138,12 +140,7 @@ class Projects::LabelsController < Projects::ApplicationController
end
def flash_notice_for(label, group)
- notice = ''.html_safe
- notice << label.title
- notice << ' promoted to '
- notice << view_context.link_to('<u>group label</u>'.html_safe, group_labels_path(group))
- notice << '.'
- notice
+ ''.html_safe + "#{label.title} promoted to " + view_context.link_to('<u>group label</u>'.html_safe, group_labels_path(group)) + '.'
end
protected
@@ -166,6 +163,7 @@ class Projects::LabelsController < Projects::ApplicationController
project_id: @project.id,
include_ancestor_groups: params[:include_ancestor_groups],
search: params[:search],
+ subscribed: params[:subscribed],
sort: sort).execute
end
diff --git a/app/controllers/projects/lfs_api_controller.rb b/app/controllers/projects/lfs_api_controller.rb
index 6d6f88c1075..be40077d389 100644
--- a/app/controllers/projects/lfs_api_controller.rb
+++ b/app/controllers/projects/lfs_api_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::LfsApiController < Projects::GitHttpClientController
include LfsRequest
diff --git a/app/controllers/projects/lfs_locks_api_controller.rb b/app/controllers/projects/lfs_locks_api_controller.rb
index 3fff0fd69ae..fc67cd72faa 100644
--- a/app/controllers/projects/lfs_locks_api_controller.rb
+++ b/app/controllers/projects/lfs_locks_api_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::LfsLocksApiController < Projects::GitHttpClientController
include LfsRequest
diff --git a/app/controllers/projects/lfs_storage_controller.rb b/app/controllers/projects/lfs_storage_controller.rb
index 930d9a05c50..babeee48ef3 100644
--- a/app/controllers/projects/lfs_storage_controller.rb
+++ b/app/controllers/projects/lfs_storage_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::LfsStorageController < Projects::GitHttpClientController
include LfsRequest
include WorkhorseRequest
diff --git a/app/controllers/projects/mattermosts_controller.rb b/app/controllers/projects/mattermosts_controller.rb
index 0f6add3e287..085b1bc1498 100644
--- a/app/controllers/projects/mattermosts_controller.rb
+++ b/app/controllers/projects/mattermosts_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::MattermostsController < Projects::ApplicationController
include TriggersHelper
include ActionView::Helpers::AssetUrlHelper
diff --git a/app/controllers/projects/merge_requests/application_controller.rb b/app/controllers/projects/merge_requests/application_controller.rb
index aa2008722ec..368ee89ff5c 100644
--- a/app/controllers/projects/merge_requests/application_controller.rb
+++ b/app/controllers/projects/merge_requests/application_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::MergeRequests::ApplicationController < Projects::ApplicationController
before_action :check_merge_requests_available!
before_action :merge_request
diff --git a/app/controllers/projects/merge_requests/conflicts_controller.rb b/app/controllers/projects/merge_requests/conflicts_controller.rb
index 366524b0783..ac1969adc6e 100644
--- a/app/controllers/projects/merge_requests/conflicts_controller.rb
+++ b/app/controllers/projects/merge_requests/conflicts_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::MergeRequests::ConflictsController < Projects::MergeRequests::ApplicationController
include IssuableActions
diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb
index 2ccb3896857..5639402a1e9 100644
--- a/app/controllers/projects/merge_requests/creations_controller.rb
+++ b/app/controllers/projects/merge_requests/creations_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::MergeRequests::CreationsController < Projects::MergeRequests::ApplicationController
include DiffForPath
include DiffHelper
@@ -104,6 +106,10 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
@commits = set_commits_for_rendering(@merge_request.commits)
@commit = @merge_request.diff_head_commit
+ # FIXME: We have to assign a presenter to another instance variable
+ # due to class_name checks being made with issuable classes
+ @mr_presenter = @merge_request.present(current_user: current_user)
+
@labels = LabelsFinder.new(current_user, project_id: @project.id).execute
set_pipeline_variables
diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb
index 666e65b6c5e..b3d77335c2a 100644
--- a/app/controllers/projects/merge_requests/diffs_controller.rb
+++ b/app/controllers/projects/merge_requests/diffs_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::MergeRequests::DiffsController < Projects::MergeRequests::ApplicationController
include DiffForPath
include DiffHelper
@@ -20,10 +22,22 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
def render_diffs
@environment = @merge_request.environments_for(current_user).last
+ notes_grouped_by_path = renderable_notes.group_by { |note| note.position.file_path }
+
+ @diffs.diff_files.each do |diff_file|
+ notes = notes_grouped_by_path.fetch(diff_file.file_path, [])
+ notes.each { |note| diff_file.unfold_diff_lines(note.position) }
+ end
@diffs.write_cache
- render json: DiffsSerializer.new(current_user: current_user).represent(@diffs, additional_attributes)
+ request = {
+ current_user: current_user,
+ project: @merge_request.project,
+ render: ->(partial, locals) { view_to_html_string(partial, locals) }
+ }
+
+ render json: DiffsSerializer.new(request).represent(@diffs, additional_attributes)
end
def define_diff_vars
@@ -100,4 +114,10 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
@grouped_diff_discussions = @merge_request.grouped_diff_discussions(@compare.diff_refs)
@notes = prepare_notes_for_rendering(@grouped_diff_discussions.values.flatten.flat_map(&:notes), @merge_request)
end
+
+ def renderable_notes
+ define_diff_comment_vars unless @notes
+
+ @notes
+ end
end
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 75a85fafa3f..d521db79f85 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationController
include ToggleSubscriptionAction
include IssuableActions
@@ -42,12 +44,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
@noteable = @merge_request
@commits_count = @merge_request.commits_count
- # TODO cleanup- Fatih Simon Create an issue to remove these after the refactoring
- # we no longer render notes here. I see it will require a small frontend refactoring,
- # since we gather some data from this collection.
- @discussions = @merge_request.discussions
- @notes = prepare_notes_for_rendering(@discussions.flat_map(&:notes), @noteable)
-
labels
set_pipeline_variables
@@ -85,13 +81,14 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
def pipelines
- @pipelines = @merge_request.all_pipelines
+ @pipelines = @merge_request.all_pipelines.page(params[:page]).per(30)
Gitlab::PollingInterval.set_header(response, interval: 10_000)
render json: {
pipelines: PipelineSerializer
.new(project: @project, current_user: @current_user)
+ .with_pagination(request, response)
.represent(@pipelines),
count: {
all: @pipelines.count
@@ -169,7 +166,9 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
def merge
- return access_denied! unless @merge_request.can_be_merged_by?(current_user)
+ access_check_result = merge_access_check
+
+ return access_check_result if access_check_result
status = merge!
@@ -202,49 +201,19 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
end
def ci_environments_status
- environments =
- begin
- @merge_request.environments_for(current_user).map do |environment|
- project = environment.project
- deployment = environment.first_deployment_for(@merge_request.diff_head_sha)
-
- stop_url =
- if can?(current_user, :stop_environment, environment)
- stop_project_environment_path(project, environment)
- end
-
- metrics_url =
- if can?(current_user, :read_environment, environment) && environment.has_metrics?
- metrics_project_environment_deployment_path(environment.project, environment, deployment)
- end
-
- metrics_monitoring_url =
- if can?(current_user, :read_environment, environment)
- environment_metrics_path(environment)
- end
-
- {
- id: environment.id,
- name: environment.name,
- url: project_environment_path(project, environment),
- metrics_url: metrics_url,
- metrics_monitoring_url: metrics_monitoring_url,
- stop_url: stop_url,
- external_url: environment.external_url,
- external_url_formatted: environment.formatted_external_url,
- deployed_at: deployment.try(:created_at),
- deployed_at_formatted: deployment.try(:formatted_deployment_time)
- }
- end.compact
- end
+ environments = if ci_environments_status_on_merge_result?
+ EnvironmentStatus.after_merge_request(@merge_request, current_user)
+ else
+ EnvironmentStatus.for_merge_request(@merge_request, current_user)
+ end
- render json: environments
+ render json: EnvironmentStatusSerializer.new(current_user: current_user).represent(environments)
end
def rebase
RebaseWorker.perform_async(@merge_request.id, current_user.id)
- render nothing: true, status: :ok
+ head :ok
end
protected
@@ -274,6 +243,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
private
+ def ci_environments_status_on_merge_result?
+ params[:environment_target] == 'merge_commit'
+ end
+
def target_branch_missing?
@merge_request.has_no_commits? && !@merge_request.target_branch_exists?
end
@@ -289,6 +262,12 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
return :failed
end
+ merge_service = ::MergeRequests::MergeService.new(@project, current_user, merge_params)
+
+ unless merge_service.hooks_validation_pass?(@merge_request)
+ return :hook_validation_error
+ end
+
return :sha_mismatch if params[:sha] != @merge_request.diff_head_sha
@merge_request.update(merge_error: nil, squash: merge_params.fetch(:squash, false))
@@ -331,6 +310,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
@target_project = @merge_request.target_project
@target_branches = @merge_request.target_project.repository.branch_names
@noteable = @merge_request
+
+ # FIXME: We have to assign a presenter to another instance variable
+ # due to class_name checks being made with issuable classes
+ @mr_presenter = @merge_request.present(current_user: current_user)
end
def finder_type
@@ -347,6 +330,10 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
access_denied! unless access_check
end
+ def merge_access_check
+ access_denied! unless @merge_request.can_be_merged_by?(current_user)
+ end
+
def whitelist_query_limiting
# Also see https://gitlab.com/gitlab-org/gitlab-ce/issues/42441
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/42438')
diff --git a/app/controllers/projects/milestones_controller.rb b/app/controllers/projects/milestones_controller.rb
index e2c05171cd6..8e68014a30d 100644
--- a/app/controllers/projects/milestones_controller.rb
+++ b/app/controllers/projects/milestones_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::MilestonesController < Projects::ApplicationController
include Gitlab::Utils::StrongMemoize
include MilestoneActions
@@ -9,7 +11,10 @@ class Projects::MilestonesController < Projects::ApplicationController
before_action :authorize_read_milestone!
# Allow admin milestone
- before_action :authorize_admin_milestone!, except: [:index, :show, :merge_requests, :participants, :labels, :promote]
+ before_action :authorize_admin_milestone!, except: [:index, :show, :merge_requests, :participants, :labels]
+
+ # Allow to promote milestone
+ before_action :authorize_promote_milestone!, only: :promote
respond_to :html
@@ -76,7 +81,7 @@ class Projects::MilestonesController < Projects::ApplicationController
def promote
promoted_milestone = Milestones::PromoteService.new(project, current_user).execute(milestone)
- flash[:notice] = flash_notice_for(promoted_milestone, project.group)
+ flash[:notice] = flash_notice_for(promoted_milestone, project_group)
respond_to do |format|
format.html do
@@ -91,12 +96,7 @@ class Projects::MilestonesController < Projects::ApplicationController
end
def flash_notice_for(milestone, group)
- notice = ''.html_safe
- notice << milestone.title
- notice << ' promoted to '
- notice << view_context.link_to('<u>group milestone</u>'.html_safe, group_milestone_path(group, milestone.iid))
- notice << '.'
- notice
+ ''.html_safe + "#{milestone.title} promoted to " + view_context.link_to('<u>group milestone</u>'.html_safe, group_milestone_path(group, milestone.iid)) + '.'
end
def destroy
@@ -112,6 +112,12 @@ class Projects::MilestonesController < Projects::ApplicationController
protected
+ def project_group
+ strong_memoize(:project_group) do
+ project.group
+ end
+ end
+
def milestones
strong_memoize(:milestones) do
MilestonesFinder.new(search_params).execute
@@ -128,13 +134,17 @@ class Projects::MilestonesController < Projects::ApplicationController
return render_404 unless can?(current_user, :admin_milestone, @project)
end
+ def authorize_promote_milestone!
+ return render_404 unless can?(current_user, :admin_milestone, project_group)
+ end
+
def milestone_params
params.require(:milestone).permit(:title, :description, :start_date, :due_date, :state_event)
end
def search_params
- if request.format.json? && @project.group && can?(current_user, :read_group, @project.group)
- groups = @project.group.self_and_ancestors_ids
+ if request.format.json? && project_group && can?(current_user, :read_group, project_group)
+ groups = project_group.self_and_ancestors_ids
end
params.permit(:state).merge(project_ids: @project.id, group_ids: groups)
diff --git a/app/controllers/projects/mirrors_controller.rb b/app/controllers/projects/mirrors_controller.rb
index 3739608e4c0..ab7ab13657a 100644
--- a/app/controllers/projects/mirrors_controller.rb
+++ b/app/controllers/projects/mirrors_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::MirrorsController < Projects::ApplicationController
include RepositorySettingsRedirect
@@ -42,6 +44,22 @@ class Projects::MirrorsController < Projects::ApplicationController
redirect_to_repository_settings(project, anchor: 'js-push-remote-settings')
end
+ def ssh_host_keys
+ lookup = SshHostKey.new(project: project, url: params[:ssh_url], compare_host_keys: params[:compare_host_keys])
+
+ if lookup.error.present?
+ # Failed to read keys
+ render json: { message: lookup.error }, status: :bad_request
+ elsif lookup.known_hosts.nil?
+ # Still working, come back later
+ render body: nil, status: :no_content
+ else
+ render json: lookup
+ end
+ rescue ArgumentError => err
+ render json: { message: err.message }, status: :bad_request
+ end
+
private
def remote_mirror
@@ -59,6 +77,10 @@ class Projects::MirrorsController < Projects::ApplicationController
id
enabled
only_protected_branches
+ auth_method
+ password
+ ssh_known_hosts
+ regenerate_ssh_private_key
]
]
end
diff --git a/app/controllers/projects/network_controller.rb b/app/controllers/projects/network_controller.rb
index 35fec229db7..6543711ecfa 100644
--- a/app/controllers/projects/network_controller.rb
+++ b/app/controllers/projects/network_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::NetworkController < Projects::ApplicationController
include ExtractsPath
include ApplicationHelper
@@ -6,6 +8,7 @@ class Projects::NetworkController < Projects::ApplicationController
before_action :require_non_empty_project
before_action :assign_ref_vars
before_action :authorize_download_code!
+ before_action :assign_options
before_action :assign_commit
def show
@@ -27,10 +30,13 @@ class Projects::NetworkController < Projects::ApplicationController
render
end
+ def assign_options
+ @options = params.permit(:filter_ref, :extended_sha1)
+ end
+
def assign_commit
- return if params[:extended_sha1].blank?
+ return if @options[:extended_sha1].blank?
- @options[:extended_sha1] = params[:extended_sha1]
@commit = @repo.commit(@options[:extended_sha1])
end
diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb
index 21e2145b73b..3152a38fd8e 100644
--- a/app/controllers/projects/notes_controller.rb
+++ b/app/controllers/projects/notes_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::NotesController < Projects::ApplicationController
include RendersNotes
include NotesActions
@@ -66,7 +68,7 @@ class Projects::NotesController < Projects::ApplicationController
alias_method :awardable, :note
def finder_params
- params.merge(last_fetched_at: last_fetched_at)
+ params.merge(last_fetched_at: last_fetched_at, notes_filter: notes_filter)
end
def authorize_admin_note!
diff --git a/app/controllers/projects/pages_controller.rb b/app/controllers/projects/pages_controller.rb
index e1eba4f8327..c1ad6707c97 100644
--- a/app/controllers/projects/pages_controller.rb
+++ b/app/controllers/projects/pages_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::PagesController < Projects::ApplicationController
layout 'project_settings'
diff --git a/app/controllers/projects/pages_domains_controller.rb b/app/controllers/projects/pages_domains_controller.rb
index c29b3c953a6..439ec9b1731 100644
--- a/app/controllers/projects/pages_domains_controller.rb
+++ b/app/controllers/projects/pages_domains_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::PagesDomainsController < Projects::ApplicationController
layout 'project_settings'
diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb
index d8adeffd0b2..acf56f0eb6a 100644
--- a/app/controllers/projects/pipeline_schedules_controller.rb
+++ b/app/controllers/projects/pipeline_schedules_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::PipelineSchedulesController < Projects::ApplicationController
before_action :schedule, except: [:index, :new, :create]
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index 5b2091d68f8..53b29d4146e 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::PipelinesController < Projects::ApplicationController
before_action :whitelist_query_limiting, only: [:create, :retry]
before_action :pipeline, except: [:index, :new, :create, :charts]
diff --git a/app/controllers/projects/pipelines_settings_controller.rb b/app/controllers/projects/pipelines_settings_controller.rb
index 73c613b26f3..192e6d38f36 100644
--- a/app/controllers/projects/pipelines_settings_controller.rb
+++ b/app/controllers/projects/pipelines_settings_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::PipelinesSettingsController < Projects::ApplicationController
before_action :authorize_admin_pipeline!
diff --git a/app/controllers/projects/project_members_controller.rb b/app/controllers/projects/project_members_controller.rb
index 08d5e377941..8938cfbad54 100644
--- a/app/controllers/projects/project_members_controller.rb
+++ b/app/controllers/projects/project_members_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::ProjectMembersController < Projects::ApplicationController
include MembershipActions
include MembersPresentation
diff --git a/app/controllers/projects/prometheus/metrics_controller.rb b/app/controllers/projects/prometheus/metrics_controller.rb
index c6b6243b553..3a9f9aab4a5 100644
--- a/app/controllers/projects/prometheus/metrics_controller.rb
+++ b/app/controllers/projects/prometheus/metrics_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Projects
module Prometheus
class MetricsController < Projects::ApplicationController
diff --git a/app/controllers/projects/protected_branches_controller.rb b/app/controllers/projects/protected_branches_controller.rb
index 64954ac9a42..a860be83e95 100644
--- a/app/controllers/projects/protected_branches_controller.rb
+++ b/app/controllers/projects/protected_branches_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::ProtectedBranchesController < Projects::ProtectedRefsController
protected
diff --git a/app/controllers/projects/protected_refs_controller.rb b/app/controllers/projects/protected_refs_controller.rb
index cc62ce2f11b..3a3a29ddd0d 100644
--- a/app/controllers/projects/protected_refs_controller.rb
+++ b/app/controllers/projects/protected_refs_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::ProtectedRefsController < Projects::ApplicationController
include RepositorySettingsRedirect
diff --git a/app/controllers/projects/protected_tags_controller.rb b/app/controllers/projects/protected_tags_controller.rb
index 198c938ff35..01cedba95ac 100644
--- a/app/controllers/projects/protected_tags_controller.rb
+++ b/app/controllers/projects/protected_tags_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::ProtectedTagsController < Projects::ProtectedRefsController
protected
diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb
index 91cf35bc70b..42ae5b0ef3c 100644
--- a/app/controllers/projects/raw_controller.rb
+++ b/app/controllers/projects/raw_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Controller for viewing a file's raw
class Projects::RawController < Projects::ApplicationController
include ExtractsPath
@@ -10,6 +12,6 @@ class Projects::RawController < Projects::ApplicationController
def show
@blob = @repository.blob_at(@commit.id, @path)
- send_blob(@blob, inline: (params[:inline] != 'false'))
+ send_blob(@repository, @blob, inline: (params[:inline] != 'false'))
end
end
diff --git a/app/controllers/projects/refs_controller.rb b/app/controllers/projects/refs_controller.rb
index 0fed7f6576c..b97fbe19bbf 100644
--- a/app/controllers/projects/refs_controller.rb
+++ b/app/controllers/projects/refs_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::RefsController < Projects::ApplicationController
include ExtractsPath
include TreeHelper
diff --git a/app/controllers/projects/registry/application_controller.rb b/app/controllers/projects/registry/application_controller.rb
index a56f9c58726..2f891d78c91 100644
--- a/app/controllers/projects/registry/application_controller.rb
+++ b/app/controllers/projects/registry/application_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Projects
module Registry
class ApplicationController < Projects::ApplicationController
diff --git a/app/controllers/projects/registry/repositories_controller.rb b/app/controllers/projects/registry/repositories_controller.rb
index ef0433795f4..6d60117c37d 100644
--- a/app/controllers/projects/registry/repositories_controller.rb
+++ b/app/controllers/projects/registry/repositories_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Projects
module Registry
class RepositoriesController < ::Projects::Registry::ApplicationController
diff --git a/app/controllers/projects/registry/tags_controller.rb b/app/controllers/projects/registry/tags_controller.rb
index e602aa3f393..567d750caae 100644
--- a/app/controllers/projects/registry/tags_controller.rb
+++ b/app/controllers/projects/registry/tags_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Projects
module Registry
class TagsController < ::Projects::Registry::ApplicationController
diff --git a/app/controllers/projects/releases_controller.rb b/app/controllers/projects/releases_controller.rb
index caf400ecd92..55827075896 100644
--- a/app/controllers/projects/releases_controller.rb
+++ b/app/controllers/projects/releases_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::ReleasesController < Projects::ApplicationController
# Authorize
before_action :require_non_empty_project
diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb
index ecb2ece7532..4eeaeb860ee 100644
--- a/app/controllers/projects/repositories_controller.rb
+++ b/app/controllers/projects/repositories_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::RepositoriesController < Projects::ApplicationController
include ExtractsPath
diff --git a/app/controllers/projects/runner_projects_controller.rb b/app/controllers/projects/runner_projects_controller.rb
index c098c82081e..cbeb32fd610 100644
--- a/app/controllers/projects/runner_projects_controller.rb
+++ b/app/controllers/projects/runner_projects_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::RunnerProjectsController < Projects::ApplicationController
before_action :authorize_admin_build!
diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb
index d118cec977c..91f40b90aa8 100644
--- a/app/controllers/projects/runners_controller.rb
+++ b/app/controllers/projects/runners_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::RunnersController < Projects::ApplicationController
before_action :authorize_admin_build!
before_action :runner, only: [:edit, :update, :destroy, :pause, :resume, :show]
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index d55046047ae..f1c9d0d0f77 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::ServicesController < Projects::ApplicationController
include ServiceParams
diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb
index 322ec096ffb..75e590f3f33 100644
--- a/app/controllers/projects/settings/ci_cd_controller.rb
+++ b/app/controllers/projects/settings/ci_cd_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Projects
module Settings
class CiCdController < Projects::ApplicationController
@@ -34,6 +36,13 @@ module Projects
end
end
+ def reset_registration_token
+ @project.reset_runners_token!
+
+ flash[:notice] = 'New runners registration token has been generated!'
+ redirect_to namespace_project_settings_ci_cd_path
+ end
+
private
def update_params
@@ -59,7 +68,7 @@ module Projects
def define_variables
define_runners_variables
- define_secret_variables
+ define_ci_variables
define_triggers_variables
define_badges_variables
define_auto_devops_variables
@@ -81,7 +90,7 @@ module Projects
@group_runners = ::Ci::Runner.belonging_to_parent_group_of_project(@project.id)
end
- def define_secret_variables
+ def define_ci_variables
@variable = ::Ci::Variable.new(project: project)
.present(current_user: current_user)
@variables = project.variables.order_key_asc
diff --git a/app/controllers/projects/settings/integrations_controller.rb b/app/controllers/projects/settings/integrations_controller.rb
index d9fecfecc40..388fcb32c35 100644
--- a/app/controllers/projects/settings/integrations_controller.rb
+++ b/app/controllers/projects/settings/integrations_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Projects
module Settings
class IntegrationsController < Projects::ApplicationController
diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb
index ccd481b4dbd..1d76c90d4eb 100644
--- a/app/controllers/projects/settings/repository_controller.rb
+++ b/app/controllers/projects/settings/repository_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Projects
module Settings
class RepositoryController < Projects::ApplicationController
diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb
index 7c03d8ce827..a44acb12bdf 100644
--- a/app/controllers/projects/snippets_controller.rb
+++ b/app/controllers/projects/snippets_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::SnippetsController < Projects::ApplicationController
include RendersNotes
include ToggleAwardEmoji
diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb
index 74bba97987f..2b28670a49b 100644
--- a/app/controllers/projects/tags_controller.rb
+++ b/app/controllers/projects/tags_controller.rb
@@ -1,6 +1,10 @@
+# frozen_string_literal: true
+
class Projects::TagsController < Projects::ApplicationController
include SortingHelper
+ prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) }
+
# Authorize
before_action :require_non_empty_project
before_action :authorize_download_code!
diff --git a/app/controllers/projects/templates_controller.rb b/app/controllers/projects/templates_controller.rb
index 52d6fb82093..7ceea4e5b96 100644
--- a/app/controllers/projects/templates_controller.rb
+++ b/app/controllers/projects/templates_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::TemplatesController < Projects::ApplicationController
before_action :authenticate_user!, :get_template_class
diff --git a/app/controllers/projects/todos_controller.rb b/app/controllers/projects/todos_controller.rb
index 93fb9da6510..0b11ee9edc0 100644
--- a/app/controllers/projects/todos_controller.rb
+++ b/app/controllers/projects/todos_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::TodosController < Projects::ApplicationController
include Gitlab::Utils::StrongMemoize
include TodosActions
diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb
index ee9b5458282..3fe300dcfc0 100644
--- a/app/controllers/projects/tree_controller.rb
+++ b/app/controllers/projects/tree_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Controller for viewing a repository's file structure
class Projects::TreeController < Projects::ApplicationController
include ExtractsPath
diff --git a/app/controllers/projects/triggers_controller.rb b/app/controllers/projects/triggers_controller.rb
index cb12b707087..f5fdfb8accc 100644
--- a/app/controllers/projects/triggers_controller.rb
+++ b/app/controllers/projects/triggers_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::TriggersController < Projects::ApplicationController
before_action :authorize_admin_build!
before_action :authorize_manage_trigger!, except: [:index, :create]
diff --git a/app/controllers/projects/uploads_controller.rb b/app/controllers/projects/uploads_controller.rb
index 7a85046164c..4ffcc2ac805 100644
--- a/app/controllers/projects/uploads_controller.rb
+++ b/app/controllers/projects/uploads_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::UploadsController < Projects::ApplicationController
include UploadsActions
include WorkhorseRequest
diff --git a/app/controllers/projects/variables_controller.rb b/app/controllers/projects/variables_controller.rb
index bf09ea7e4d8..bb658bfcc19 100644
--- a/app/controllers/projects/variables_controller.rb
+++ b/app/controllers/projects/variables_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Projects::VariablesController < Projects::ApplicationController
before_action :authorize_admin_build!
diff --git a/app/controllers/projects/wikis_controller.rb b/app/controllers/projects/wikis_controller.rb
index da7aeb26a75..88dd111132b 100644
--- a/app/controllers/projects/wikis_controller.rb
+++ b/app/controllers/projects/wikis_controller.rb
@@ -1,5 +1,8 @@
+# frozen_string_literal: true
+
class Projects::WikisController < Projects::ApplicationController
include PreviewMarkdown
+ include SendsBlob
include Gitlab::Utils::StrongMemoize
before_action :authorize_read_wiki!
@@ -24,16 +27,8 @@ class Projects::WikisController < Projects::ApplicationController
set_encoding_error unless valid_encoding?
render 'show'
- elsif file = @project_wiki.find_file(params[:id], params[:version_id])
- response.headers['Content-Security-Policy'] = "default-src 'none'"
- response.headers['X-Content-Security-Policy'] = "default-src 'none'"
-
- send_data(
- file.raw_data,
- type: file.mime_type,
- disposition: 'inline',
- filename: file.name
- )
+ elsif file_blob
+ send_blob(@project_wiki.repository, file_blob)
elsif can?(current_user, :create_wiki, @project) && view_param == 'create'
@page = build_page(title: params[:id])
@@ -162,4 +157,14 @@ class Projects::WikisController < Projects::ApplicationController
def set_encoding_error
flash.now[:notice] = "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
end
+
+ def file_blob
+ strong_memoize(:file_blob) do
+ commit = @project_wiki.repository.commit(@project_wiki.default_branch)
+
+ next unless commit
+
+ @project_wiki.repository.blob_at(commit.id, params[:id])
+ end
+ end
end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 7352c5e9bec..8bf93bfd68d 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -7,6 +7,8 @@ class ProjectsController < Projects::ApplicationController
include PreviewMarkdown
include SendFileUpload
+ prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) }
+
before_action :whitelist_query_limiting, only: [:create]
before_action :authenticate_user!, except: [:index, :show, :activity, :refs]
before_action :redirect_git_extension, only: [:show]
@@ -16,6 +18,7 @@ class ProjectsController < Projects::ApplicationController
before_action :tree, only: [:show], if: [:repo_exists?, :project_view_files?]
before_action :lfs_blob_ids, only: [:show], if: [:repo_exists?, :project_view_files?]
before_action :project_export_enabled, only: [:export, :download_export, :remove_export, :generate_new_export]
+ before_action :present_project, only: [:edit]
# Authorize
before_action :authorize_admin_project!, only: [:edit, :update, :housekeeping, :download_export, :export, :remove_export, :generate_new_export]
@@ -275,7 +278,7 @@ class ProjectsController < Projects::ApplicationController
# rubocop: enable CodeReuse/ActiveRecord
# Render project landing depending of which features are available
- # So if page is not availble in the list it renders the next page
+ # So if page is not available in the list it renders the next page
#
# pages list order: repository readme, wiki home, issues list, customize workflow
def render_landing_page
@@ -365,6 +368,7 @@ class ProjectsController < Projects::ApplicationController
repository_access_level
snippets_access_level
wiki_access_level
+ pages_access_level
]
]
end
@@ -433,4 +437,8 @@ class ProjectsController < Projects::ApplicationController
def whitelist_query_limiting
Gitlab::QueryLimiting.whitelist('https://gitlab.com/gitlab-org/gitlab-ce/issues/42440')
end
+
+ def present_project
+ @project = @project.present(current_user: current_user)
+ end
end
diff --git a/app/controllers/root_controller.rb b/app/controllers/root_controller.rb
index ebf70f25bda..7b6657e1196 100644
--- a/app/controllers/root_controller.rb
+++ b/app/controllers/root_controller.rb
@@ -45,9 +45,9 @@ class RootController < Dashboard::ProjectsController
when 'todos'
redirect_to(dashboard_todos_path)
when 'issues'
- redirect_to(issues_dashboard_path(assignee_id: current_user.id))
+ redirect_to(issues_dashboard_path(assignee_username: current_user.username))
when 'merge_requests'
- redirect_to(merge_requests_dashboard_path(assignee_id: current_user.id))
+ redirect_to(merge_requests_dashboard_path(assignee_username: current_user.username))
end
end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 643eb75c83c..4bd7d71e264 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -104,7 +104,7 @@ class SessionsController < Devise::SessionsController
end
def failed_login?
- (options = env["warden.options"]) && options[:action] == "unauthenticated"
+ (options = request.env["warden.options"]) && options[:action] == "unauthenticated"
end
# Handle an "initial setup" state, where there's only one user, it's an admin,
diff --git a/app/controllers/sherlock/application_controller.rb b/app/controllers/sherlock/application_controller.rb
index 6bdd3568a78..c048254d348 100644
--- a/app/controllers/sherlock/application_controller.rb
+++ b/app/controllers/sherlock/application_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Sherlock
class ApplicationController < ::ApplicationController
before_action :find_transaction
diff --git a/app/controllers/sherlock/file_samples_controller.rb b/app/controllers/sherlock/file_samples_controller.rb
index 0c3bc100106..900446bb75a 100644
--- a/app/controllers/sherlock/file_samples_controller.rb
+++ b/app/controllers/sherlock/file_samples_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Sherlock
class FileSamplesController < Sherlock::ApplicationController
def show
diff --git a/app/controllers/sherlock/queries_controller.rb b/app/controllers/sherlock/queries_controller.rb
index 63b26aab1a4..49a25c682b5 100644
--- a/app/controllers/sherlock/queries_controller.rb
+++ b/app/controllers/sherlock/queries_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Sherlock
class QueriesController < Sherlock::ApplicationController
def show
diff --git a/app/controllers/sherlock/transactions_controller.rb b/app/controllers/sherlock/transactions_controller.rb
index ae4953c3259..46e382e594e 100644
--- a/app/controllers/sherlock/transactions_controller.rb
+++ b/app/controllers/sherlock/transactions_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Sherlock
class TransactionsController < Sherlock::ApplicationController
def index
diff --git a/app/controllers/snippets/notes_controller.rb b/app/controllers/snippets/notes_controller.rb
index e992afc0026..091bcb1253d 100644
--- a/app/controllers/snippets/notes_controller.rb
+++ b/app/controllers/snippets/notes_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Snippets::NotesController < ApplicationController
include NotesActions
include ToggleAwardEmoji
diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb
index 694c3a59e2b..dd9bf17cf0c 100644
--- a/app/controllers/snippets_controller.rb
+++ b/app/controllers/snippets_controller.rb
@@ -26,12 +26,9 @@ class SnippetsController < ApplicationController
layout 'snippets'
respond_to :html
- # rubocop: disable CodeReuse/ActiveRecord
def index
if params[:username].present?
- @user = User.find_by(username: params[:username])
-
- return render_404 unless @user
+ @user = UserFinder.new(params[:username]).find_by_username!
@snippets = SnippetsFinder.new(current_user, author: @user, scope: params[:scope])
.execute.page(params[:page])
@@ -41,7 +38,6 @@ class SnippetsController < ApplicationController
redirect_to(current_user ? dashboard_snippets_path : explore_snippets_path)
end
end
- # rubocop: enable CodeReuse/ActiveRecord
def new
@snippet = PersonalSnippet.new
diff --git a/app/controllers/users/terms_controller.rb b/app/controllers/users/terms_controller.rb
index 1b1560a2a00..3c16d934b4d 100644
--- a/app/controllers/users/terms_controller.rb
+++ b/app/controllers/users/terms_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Users
class TermsController < ApplicationController
include InternalRedirect
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index e509098d778..8b040dc080e 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -14,6 +14,7 @@ class UsersController < ApplicationController
calendar_activities: true
skip_before_action :authenticate_user!
+ prepend_before_action(only: [:show]) { authenticate_sessionless_user!(:rss) }
before_action :user, except: [:exists]
before_action :authorize_read_user_profile!,
only: [:calendar, :calendar_activities, :groups, :projects, :contributed_projects, :snippets]
@@ -29,11 +30,17 @@ class UsersController < ApplicationController
format.json do
load_events
- pager_json("events/_events", @events.count)
+ pager_json("events/_events", @events.count, events: @events)
end
end
end
+ def activity
+ respond_to do |format|
+ format.html { render 'show' }
+ end
+ end
+
def groups
load_groups
@@ -50,12 +57,12 @@ class UsersController < ApplicationController
def projects
load_projects
+ skip_pagination = Gitlab::Utils.to_boolean(params[:skip_pagination])
+
respond_to do |format|
format.html { render 'show' }
format.json do
- render json: {
- html: view_to_html_string("shared/projects/_list", projects: @projects)
- }
+ pager_json("shared/projects/_list", @projects.count, projects: @projects, skip_pagination: skip_pagination)
end
end
end
@@ -125,6 +132,7 @@ class UsersController < ApplicationController
@projects =
PersonalProjectsFinder.new(user).execute(current_user)
.page(params[:page])
+ .per(params[:limit])
prepare_projects_for_rendering(@projects)
end
diff --git a/app/finders/admin/runners_finder.rb b/app/finders/admin/runners_finder.rb
index 3c2d7ee7d76..fbb1cfc5c66 100644
--- a/app/finders/admin/runners_finder.rb
+++ b/app/finders/admin/runners_finder.rb
@@ -10,6 +10,7 @@ class Admin::RunnersFinder < UnionFinder
def execute
search!
filter_by_status!
+ filter_by_runner_type!
sort!
paginate!
@@ -36,10 +37,11 @@ class Admin::RunnersFinder < UnionFinder
end
def filter_by_status!
- status = @params[:status_status]
- if status.present? && Ci::Runner::AVAILABLE_STATUSES.include?(status)
- @runners = @runners.public_send(status) # rubocop:disable GitlabSecurity/PublicSend
- end
+ filter_by!(:status_status, Ci::Runner::AVAILABLE_STATUSES)
+ end
+
+ def filter_by_runner_type!
+ filter_by!(:type_type, Ci::Runner::AVAILABLE_TYPES)
end
def sort!
@@ -49,4 +51,12 @@ class Admin::RunnersFinder < UnionFinder
def paginate!
@runners = @runners.page(@params[:page]).per(NUMBER_OF_RUNNERS_PER_PAGE)
end
+
+ def filter_by!(scope_name, available_scopes)
+ scope = @params[scope_name]
+
+ if scope.present? && available_scopes.include?(scope)
+ @runners = @runners.public_send(scope) # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
end
diff --git a/app/finders/applications_finder.rb b/app/finders/applications_finder.rb
new file mode 100644
index 00000000000..3ded90f3fd5
--- /dev/null
+++ b/app/finders/applications_finder.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class ApplicationsFinder
+ attr_reader :params
+
+ def initialize(params = {})
+ @params = params
+ end
+
+ def execute
+ applications = Doorkeeper::Application.where(owner_id: nil) # rubocop: disable CodeReuse/ActiveRecord
+ by_id(applications)
+ end
+
+ private
+
+ def by_id(applications)
+ return applications unless params[:id]
+
+ Doorkeeper::Application.find_by(id: params[:id]) # rubocop: disable CodeReuse/ActiveRecord
+ end
+end
diff --git a/app/finders/autocomplete/users_finder.rb b/app/finders/autocomplete/users_finder.rb
index e2283f3266e..45955783be9 100644
--- a/app/finders/autocomplete/users_finder.rb
+++ b/app/finders/autocomplete/users_finder.rb
@@ -72,7 +72,6 @@ module Autocomplete
author_id.present? && current_user
end
- # rubocop: disable CodeReuse/ActiveRecord
def find_users
if project
project.authorized_users.union_with_user(author_id)
@@ -84,6 +83,5 @@ module Autocomplete
User.none
end
end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
diff --git a/app/finders/branches_finder.rb b/app/finders/branches_finder.rb
index 970efa79dfb..45d5591e81b 100644
--- a/app/finders/branches_finder.rb
+++ b/app/finders/branches_finder.rb
@@ -7,8 +7,9 @@ class BranchesFinder
end
def execute
- branches = @repository.branches_sorted_by(sort)
- filter_by_name(branches)
+ branches = repository.branches_sorted_by(sort)
+ branches = by_search(branches)
+ branches
end
private
@@ -23,11 +24,39 @@ class BranchesFinder
@params[:sort].presence || 'name'
end
- def filter_by_name(branches)
- if search
- branches.select { |branch| branch.name.upcase.include?(search.upcase) }
+ def by_search(branches)
+ return branches unless search
+
+ case search
+ when ->(v) { v.starts_with?('^') }
+ filter_branches_with_prefix(branches, search.slice(1..-1).upcase)
+ when ->(v) { v.ends_with?('$') }
+ filter_branches_with_suffix(branches, search.chop.upcase)
else
- branches
+ matches = filter_branches_by_name(branches, search.upcase)
+ set_exact_match_as_first_result(matches, search)
end
end
+
+ def filter_branches_with_prefix(branches, prefix)
+ branches.select { |branch| branch.name.upcase.starts_with?(prefix) }
+ end
+
+ def filter_branches_with_suffix(branches, suffix)
+ branches.select { |branch| branch.name.upcase.ends_with?(suffix) }
+ end
+
+ def filter_branches_by_name(branches, term)
+ branches.select { |branch| branch.name.upcase.include?(term) }
+ end
+
+ def set_exact_match_as_first_result(matches, term)
+ exact_match_index = find_exact_match_index(matches, term)
+ matches.insert(0, matches.delete_at(exact_match_index)) if exact_match_index
+ matches
+ end
+
+ def find_exact_match_index(matches, term)
+ matches.index { |branch| branch.name.casecmp(term) == 0 }
+ end
end
diff --git a/app/finders/clusters_finder.rb b/app/finders/clusters_finder.rb
index b40d6c41b71..0cce493b73e 100644
--- a/app/finders/clusters_finder.rb
+++ b/app/finders/clusters_finder.rb
@@ -1,20 +1,20 @@
# frozen_string_literal: true
class ClustersFinder
- def initialize(project, user, scope)
- @project = project
+ def initialize(clusterable, user, scope)
+ @clusterable = clusterable
@user = user
@scope = scope || :active
end
def execute
- clusters = project.clusters
+ clusters = clusterable.clusters
filter_by_scope(clusters)
end
private
- attr_reader :project, :user, :scope
+ attr_reader :clusterable, :user, :scope
def filter_by_scope(clusters)
case scope.to_sym
diff --git a/app/finders/concerns/finder_with_cross_project_access.rb b/app/finders/concerns/finder_with_cross_project_access.rb
index e038636f0c4..220f62bcc7f 100644
--- a/app/finders/concerns/finder_with_cross_project_access.rb
+++ b/app/finders/concerns/finder_with_cross_project_access.rb
@@ -16,7 +16,6 @@ module FinderWithCrossProjectAccess
end
override :execute
- # rubocop: disable CodeReuse/ActiveRecord
def execute(*args)
check = Gitlab::CrossProjectAccess.find_check(self)
original = super
@@ -30,7 +29,6 @@ module FinderWithCrossProjectAccess
original
end
end
- # rubocop: enable CodeReuse/ActiveRecord
# We can skip the cross project check for finding indivitual records.
# this would be handled by the `can?(:read_*, result)` call in `FinderMethods`
diff --git a/app/finders/events_finder.rb b/app/finders/events_finder.rb
index fd7aeca0d8b..8df01f1dad9 100644
--- a/app/finders/events_finder.rb
+++ b/app/finders/events_finder.rb
@@ -12,6 +12,7 @@ class EventsFinder
# Arguments:
# source - which user or project to looks for events on
# current_user - only return events for projects visible to this user
+ # WARNING: does not consider project feature visibility!
# params:
# action: string
# target_type: string
@@ -57,7 +58,7 @@ class EventsFinder
def by_target_type(events)
return events unless Event::TARGET_TYPES[params[:target_type]]
- events.where(target_type: Event::TARGET_TYPES[params[:target_type]])
+ events.where(target_type: Event::TARGET_TYPES[params[:target_type]].name)
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/finders/group_descendants_finder.rb b/app/finders/group_descendants_finder.rb
index 9d57d2d3bc9..a9ce5be13f3 100644
--- a/app/finders/group_descendants_finder.rb
+++ b/app/finders/group_descendants_finder.rb
@@ -131,7 +131,6 @@ class GroupDescendantsFinder
.with_selects_for_list(archived: params[:archived])
end
- # rubocop: disable CodeReuse/ActiveRecord
def subgroups
return Group.none unless Group.supports_nested_groups?
@@ -145,7 +144,6 @@ class GroupDescendantsFinder
groups.with_selects_for_list(archived: params[:archived]).order_by(sort)
end
- # rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/Finder
def direct_child_projects
@@ -180,7 +178,7 @@ class GroupDescendantsFinder
end
def sort
- params.fetch(:sort, 'id_asc')
+ params.fetch(:sort, 'created_desc')
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/finders/group_labels_finder.rb b/app/finders/group_labels_finder.rb
new file mode 100644
index 00000000000..a668a0f0fae
--- /dev/null
+++ b/app/finders/group_labels_finder.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class GroupLabelsFinder
+ attr_reader :current_user, :group, :params
+
+ def initialize(current_user, group, params = {})
+ @current_user = current_user
+ @group = group
+ @params = params
+ end
+
+ def execute
+ group.labels
+ .optionally_subscribed_by(subscriber_id)
+ .optionally_search(params[:search])
+ .order_by(params[:sort])
+ .page(params[:page])
+ end
+
+ private
+
+ def subscriber_id
+ current_user&.id if subscribed?
+ end
+
+ def subscribed?
+ params[:subscribed] == 'true'
+ end
+end
diff --git a/app/finders/groups_finder.rb b/app/finders/groups_finder.rb
index a35a3ed6142..ea954f98220 100644
--- a/app/finders/groups_finder.rb
+++ b/app/finders/groups_finder.rb
@@ -40,7 +40,6 @@ class GroupsFinder < UnionFinder
attr_reader :current_user, :params
- # rubocop: disable CodeReuse/ActiveRecord
def all_groups
return [owned_groups] if params[:owned]
return [groups_with_min_access_level] if min_access_level?
@@ -52,7 +51,6 @@ class GroupsFinder < UnionFinder
groups << Group.none if groups.empty?
groups
end
- # rubocop: enable CodeReuse/ActiveRecord
def groups_for_ancestors
current_user.authorized_groups
@@ -82,11 +80,9 @@ class GroupsFinder < UnionFinder
end
# rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def owned_groups
current_user&.owned_groups || Group.none
end
- # rubocop: enable CodeReuse/ActiveRecord
def include_public_groups?
current_user.nil? || all_available?
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 251a559878a..e04e3a2a7e0 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -14,7 +14,9 @@
# project_id: integer
# milestone_title: string
# author_id: integer
-# assignee_id: integer
+# author_username: string
+# assignee_id: integer or 'None' or 'Any'
+# assignee_username: string
# search: string
# label_name: string
# sort: string
@@ -34,6 +36,11 @@ class IssuableFinder
requires_cross_project_access unless: -> { project? }
+ # This is used as a common filter for None / Any
+ FILTER_NONE = 'none'.freeze
+ FILTER_ANY = 'any'.freeze
+
+ # This is accepted as a deprecated filter and is also used in unassigning users
NONE = '0'.freeze
attr_accessor :current_user, :params
@@ -44,25 +51,15 @@ class IssuableFinder
assignee_username
author_id
author_username
- authorized_only
- group_id
- iids
label_name
milestone_title
my_reaction_emoji
- non_archived
- project_id
- scope
search
- sort
- state
- include_subgroups
- use_cte_for_search
]
end
def self.array_params
- @array_params ||= { label_name: [], iids: [], assignee_username: [] }
+ @array_params ||= { label_name: [], assignee_username: [] }
end
def self.valid_params
@@ -128,7 +125,7 @@ class IssuableFinder
labels_count = 1 if use_cte_for_search?
finder.execute.reorder(nil).group(:state).count.each do |key, value|
- counts[Array(key).last.to_sym] += value / labels_count
+ counts[count_key(key)] += value / labels_count
end
counts[:all] = counts.values.sum
@@ -187,11 +184,6 @@ class IssuableFinder
params[:milestone_title].present?
end
- def filter_by_no_milestone?
- milestones? && params[:milestone_title] == Milestone::None.title
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
def milestones
return @milestones if defined?(@milestones)
@@ -212,17 +204,22 @@ class IssuableFinder
Milestone.none
end
end
- # rubocop: enable CodeReuse/ActiveRecord
def labels?
params[:label_name].present?
end
def filter_by_no_label?
- labels? && params[:label_name].include?(Label::None.title)
+ downcased = label_names.map(&:downcase)
+
+ # Label::NONE is deprecated and should be removed in 12.0
+ downcased.include?(FILTER_NONE) || downcased.include?(Label::NONE)
+ end
+
+ def filter_by_any_label?
+ label_names.map(&:downcase).include?(FILTER_ANY)
end
- # rubocop: disable CodeReuse/ActiveRecord
def labels
return @labels if defined?(@labels)
@@ -233,19 +230,13 @@ class IssuableFinder
Label.none
end
end
- # rubocop: enable CodeReuse/ActiveRecord
def assignee_id?
- params[:assignee_id].present? && params[:assignee_id] != NONE
+ params[:assignee_id].present?
end
def assignee_username?
- params[:assignee_username].present? && params[:assignee_username] != NONE
- end
-
- def no_assignee?
- # Assignee_id takes precedence over assignee_username
- params[:assignee_id] == NONE || params[:assignee_username] == NONE
+ params[:assignee_username].present?
end
# rubocop: disable CodeReuse/ActiveRecord
@@ -256,7 +247,7 @@ class IssuableFinder
if assignee_id?
User.find_by(id: params[:assignee_id])
elsif assignee_username?
- User.find_by(username: params[:assignee_username])
+ User.find_by_username(params[:assignee_username])
else
nil
end
@@ -284,7 +275,7 @@ class IssuableFinder
if author_id?
User.find_by(id: params[:author_id])
elsif author_username?
- User.find_by(username: params[:author_username])
+ User.find_by_username(params[:author_username])
else
nil
end
@@ -297,6 +288,10 @@ class IssuableFinder
klass.all
end
+ def count_key(value)
+ Array(value).last.to_sym
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def by_scope(items)
return items.none if current_user_related? && !current_user
@@ -359,6 +354,7 @@ class IssuableFinder
def use_cte_for_search?
return false unless search
return false unless Gitlab::Database.postgresql?
+ return false unless Feature.enabled?(:use_cte_for_group_issues_search, default_enabled: true)
params[:use_cte_for_search]
end
@@ -394,18 +390,29 @@ class IssuableFinder
# rubocop: disable CodeReuse/ActiveRecord
def by_assignee(items)
- if assignee
- items = items.where(assignee_id: assignee.id)
- elsif no_assignee?
- items = items.where(assignee_id: nil)
+ if filter_by_no_assignee?
+ items.where(assignee_id: nil)
+ elsif filter_by_any_assignee?
+ items.where('assignee_id IS NOT NULL')
+ elsif assignee
+ items.where(assignee_id: assignee.id)
elsif assignee_id? || assignee_username? # assignee not found
- items = items.none
+ items.none
+ else
+ items
end
-
- items
end
# rubocop: enable CodeReuse/ActiveRecord
+ def filter_by_no_assignee?
+ # Assignee_id takes precedence over assignee_username
+ [NONE, FILTER_NONE].include?(params[:assignee_id].to_s.downcase) || params[:assignee_username].to_s == NONE
+ end
+
+ def filter_by_any_assignee?
+ params[:assignee_id].to_s.downcase == FILTER_ANY
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def by_author(items)
if author
@@ -420,19 +427,13 @@ class IssuableFinder
end
# rubocop: enable CodeReuse/ActiveRecord
- def filter_by_upcoming_milestone?
- params[:milestone_title] == Milestone::Upcoming.name
- end
-
- def filter_by_started_milestone?
- params[:milestone_title] == Milestone::Started.name
- end
-
# rubocop: disable CodeReuse/ActiveRecord
def by_milestone(items)
if milestones?
if filter_by_no_milestone?
items = items.left_joins_milestones.where(milestone_id: [-1, nil])
+ elsif filter_by_any_milestone?
+ items = items.any_milestone
elsif filter_by_upcoming_milestone?
upcoming_ids = Milestone.upcoming_ids_by_projects(projects(items))
items = items.left_joins_milestones.where(milestone_id: upcoming_ids)
@@ -447,12 +448,32 @@ class IssuableFinder
end
# rubocop: enable CodeReuse/ActiveRecord
+ def filter_by_no_milestone?
+ # Accepts `No Milestone` for compatibility
+ params[:milestone_title].to_s.downcase == FILTER_NONE || params[:milestone_title] == Milestone::None.title
+ end
+
+ def filter_by_any_milestone?
+ # Accepts `Any Milestone` for compatibility
+ params[:milestone_title].to_s.downcase == FILTER_ANY || params[:milestone_title] == Milestone::Any.title
+ end
+
+ def filter_by_upcoming_milestone?
+ params[:milestone_title] == Milestone::Upcoming.name
+ end
+
+ def filter_by_started_milestone?
+ params[:milestone_title] == Milestone::Started.name
+ end
+
def by_label(items)
return items unless labels?
items =
if filter_by_no_label?
items.without_label
+ elsif filter_by_any_label?
+ items.any_label
else
items.with_label(label_names, params[:sort])
end
@@ -462,12 +483,27 @@ class IssuableFinder
def by_my_reaction_emoji(items)
if params[:my_reaction_emoji].present? && current_user
- items = items.awarded(current_user, params[:my_reaction_emoji])
+ items =
+ if filter_by_no_reaction?
+ items.not_awarded(current_user)
+ elsif filter_by_any_reaction?
+ items.awarded(current_user)
+ else
+ items.awarded(current_user, params[:my_reaction_emoji])
+ end
end
items
end
+ def filter_by_no_reaction?
+ params[:my_reaction_emoji].to_s.downcase == FILTER_NONE
+ end
+
+ def filter_by_any_reaction?
+ params[:my_reaction_emoji].to_s.downcase == FILTER_ANY
+ end
+
def label_names
if labels?
params[:label_name].is_a?(String) ? params[:label_name].split(',') : params[:label_name]
diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb
index 770e0bfe1a3..45e494725d7 100644
--- a/app/finders/issues_finder.rb
+++ b/app/finders/issues_finder.rb
@@ -120,9 +120,13 @@ class IssuesFinder < IssuableFinder
return @user_can_see_all_confidential_issues = true if current_user.full_private_access?
@user_can_see_all_confidential_issues =
- project? &&
- project &&
- project.team.max_member_access(current_user.id) >= CONFIDENTIAL_ACCESS_LEVEL
+ if project? && project
+ project.team.max_member_access(current_user.id) >= CONFIDENTIAL_ACCESS_LEVEL
+ elsif group
+ group.max_member_access_for_user(current_user) >= CONFIDENTIAL_ACCESS_LEVEL
+ else
+ false
+ end
end
def user_cannot_see_confidential_issues?
@@ -131,17 +135,17 @@ class IssuesFinder < IssuableFinder
current_user.blank?
end
- # rubocop: disable CodeReuse/ActiveRecord
def by_assignee(items)
- if assignee
- items.assigned_to(assignee)
- elsif no_assignee?
+ if filter_by_no_assignee?
items.unassigned
+ elsif filter_by_any_assignee?
+ items.assigned
+ elsif assignee
+ items.assigned_to(assignee)
elsif assignee_id? || assignee_username? # assignee not found
items.none
else
items
end
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/finders/joined_groups_finder.rb b/app/finders/joined_groups_finder.rb
index 18cc6891ca4..4d8128dd824 100644
--- a/app/finders/joined_groups_finder.rb
+++ b/app/finders/joined_groups_finder.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class JoinedGroupsFinder < UnionFinder
+class JoinedGroupsFinder
def initialize(user)
@user = user
end
@@ -8,19 +8,8 @@ class JoinedGroupsFinder < UnionFinder
# Finds the groups of the source user, optionally limited to those visible to
# the current user.
def execute(current_user = nil)
- segments = all_groups(current_user)
-
- find_union(segments, Group).order_id_desc
- end
-
- private
-
- def all_groups(current_user)
- groups = []
-
- groups << @user.authorized_groups.visible_to_user(current_user) if current_user
- groups << @user.authorized_groups.public_to_user(current_user)
-
- groups
+ @user.authorized_groups
+ .public_or_visible_to_user(current_user)
+ .order_id_desc
end
end
diff --git a/app/finders/labels_finder.rb b/app/finders/labels_finder.rb
index 08fc2968e77..e523942ea4c 100644
--- a/app/finders/labels_finder.rb
+++ b/app/finders/labels_finder.rb
@@ -12,15 +12,14 @@ class LabelsFinder < UnionFinder
@params = params
end
- # rubocop: disable CodeReuse/ActiveRecord
def execute(skip_authorization: false)
@skip_authorization = skip_authorization
items = find_union(label_ids, Label) || Label.none
items = with_title(items)
+ items = by_subscription(items)
items = by_search(items)
sort(items)
end
- # rubocop: enable CodeReuse/ActiveRecord
private
@@ -84,6 +83,18 @@ class LabelsFinder < UnionFinder
labels.search(params[:search])
end
+ def by_subscription(labels)
+ labels.optionally_subscribed_by(subscriber_id)
+ end
+
+ def subscriber_id
+ current_user&.id if subscribed?
+ end
+
+ def subscribed?
+ params[:subscribed] == 'true'
+ end
+
# Gets redacted array of group ids
# which can include the ancestors and descendants of the requested group.
def group_ids_for(group)
@@ -116,7 +127,7 @@ class LabelsFinder < UnionFinder
end
def project?
- params[:project_id].present?
+ params[:project].present? || params[:project_id].present?
end
def projects?
@@ -139,7 +150,7 @@ class LabelsFinder < UnionFinder
return @project if defined?(@project)
if project?
- @project = Project.find(params[:project_id])
+ @project = params[:project] || Project.find(params[:project_id])
@project = nil unless authorized_to_read_labels?(@project)
else
@project = nil
diff --git a/app/finders/license_template_finder.rb b/app/finders/license_template_finder.rb
index 196922709f7..d735a4c1d69 100644
--- a/app/finders/license_template_finder.rb
+++ b/app/finders/license_template_finder.rb
@@ -5,33 +5,47 @@
# Used to find license templates, which may come from a variety of external
# sources
#
-# Arguments:
+# Params can be any of the following:
# popular: boolean. When set to true, only "popular" licenses are shown. When
# false, all licenses except popular ones are shown. When nil (the
# default), *all* licenses will be shown.
+# name: string. If set, return a single license matching that name (or nil)
class LicenseTemplateFinder
- attr_reader :params
+ include Gitlab::Utils::StrongMemoize
- def initialize(params = {})
+ attr_reader :project, :params
+
+ def initialize(project, params = {})
+ @project = project
@params = params
end
def execute
- Licensee::License.all(featured: popular_only?).map do |license|
- LicenseTemplate.new(
- id: license.key,
- name: license.name,
- nickname: license.nickname,
- category: (license.featured? ? :Popular : :Other),
- content: license.content,
- url: license.url,
- meta: license.meta
- )
+ if params[:name]
+ vendored_licenses.find { |template| template.key == params[:name] }
+ else
+ vendored_licenses
end
end
private
+ def vendored_licenses
+ strong_memoize(:vendored_licenses) do
+ Licensee::License.all(featured: popular_only?).map do |license|
+ LicenseTemplate.new(
+ key: license.key,
+ name: license.name,
+ nickname: license.nickname,
+ category: (license.featured? ? :Popular : :Other),
+ content: license.content,
+ url: license.url,
+ meta: license.meta
+ )
+ end
+ end
+ end
+
def popular_only?
params.fetch(:popular, nil)
end
diff --git a/app/finders/merge_requests_finder.rb b/app/finders/merge_requests_finder.rb
index b698a3c7b09..e190d5d90c9 100644
--- a/app/finders/merge_requests_finder.rb
+++ b/app/finders/merge_requests_finder.rb
@@ -27,13 +27,17 @@
# updated_before: datetime
#
class MergeRequestsFinder < IssuableFinder
+ def self.scalar_params
+ @scalar_params ||= super + [:wip]
+ end
+
def klass
MergeRequest
end
def filter_items(_items)
items = by_source_branch(super)
-
+ items = by_wip(items)
by_target_branch(items)
end
@@ -61,5 +65,20 @@ class MergeRequestsFinder < IssuableFinder
items.where(target_branch: target_branch)
end
- # rubocop: enable CodeReuse/ActiveRecord
+
+ def by_wip(items)
+ if params[:wip] == 'yes'
+ items.where(wip_match(items.arel_table))
+ elsif params[:wip] == 'no'
+ items.where.not(wip_match(items.arel_table))
+ else
+ items
+ end
+ end
+
+ def wip_match(table)
+ table[:title].matches('WIP:%')
+ .or(table[:title].matches('WIP %'))
+ .or(table[:title].matches('[WIP]%'))
+ end
end
diff --git a/app/finders/milestones_finder.rb b/app/finders/milestones_finder.rb
index 47231ea80c7..9c477978f60 100644
--- a/app/finders/milestones_finder.rb
+++ b/app/finders/milestones_finder.rb
@@ -20,7 +20,6 @@ class MilestonesFinder
@params = params
end
- # rubocop: disable CodeReuse/ActiveRecord
def execute
return Milestone.none if project_ids.empty? && group_ids.empty?
@@ -31,7 +30,6 @@ class MilestonesFinder
order(items)
end
- # rubocop: enable CodeReuse/ActiveRecord
private
diff --git a/app/finders/notes_finder.rb b/app/finders/notes_finder.rb
index c67c2065440..817aac8b5d5 100644
--- a/app/finders/notes_finder.rb
+++ b/app/finders/notes_finder.rb
@@ -24,6 +24,8 @@ class NotesFinder
def execute
notes = init_collection
notes = since_fetch_at(notes)
+ notes = notes.with_notes_filter(@params[:notes_filter]) if notes_filter?
+
notes.fresh
end
@@ -134,4 +136,8 @@ class NotesFinder
last_fetched_at = Time.at(@params.fetch(:last_fetched_at, 0).to_i)
notes.updated_after(last_fetched_at - FETCH_OVERLAP)
end
+
+ def notes_filter?
+ @params[:notes_filter].present?
+ end
end
diff --git a/app/finders/pending_todos_finder.rb b/app/finders/pending_todos_finder.rb
new file mode 100644
index 00000000000..c21d90c9182
--- /dev/null
+++ b/app/finders/pending_todos_finder.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+# Finder for retrieving the pending todos of a user, optionally filtered using
+# various fields.
+#
+# While this finder is a bit more verbose compared to use
+# `where(params.slice(...))`, it allows us to decouple the input parameters from
+# the actual column names. For example, if we ever decide to use separate
+# columns for target types (e.g. `issue_id`, `merge_request_id`, etc), we no
+# longer need to change _everything_ that uses this finder. Instead, we just
+# change the various `by_*` methods in this finder, without having to touch
+# everything that uses it.
+class PendingTodosFinder
+ attr_reader :current_user, :params
+
+ # current_user - The user to retrieve the todos for.
+ # params - A Hash containing columns and values to use for filtering todos.
+ def initialize(current_user, params = {})
+ @current_user = current_user
+ @params = params
+ end
+
+ def execute
+ todos = current_user.todos.pending
+ todos = by_project(todos)
+ todos = by_target_id(todos)
+ todos = by_target_type(todos)
+ todos = by_commit_id(todos)
+
+ todos
+ end
+
+ def by_project(todos)
+ if (id = params[:project_id])
+ todos.for_project(id)
+ else
+ todos
+ end
+ end
+
+ def by_target_id(todos)
+ if (id = params[:target_id])
+ todos.for_target(id)
+ else
+ todos
+ end
+ end
+
+ def by_target_type(todos)
+ if (type = params[:target_type])
+ todos.for_type(type)
+ else
+ todos
+ end
+ end
+
+ def by_commit_id(todos)
+ if (id = params[:commit_id])
+ todos.for_commit(id)
+ else
+ todos
+ end
+ end
+end
diff --git a/app/finders/personal_access_tokens_finder.rb b/app/finders/personal_access_tokens_finder.rb
index 5beea92689f..bd95dcd323f 100644
--- a/app/finders/personal_access_tokens_finder.rb
+++ b/app/finders/personal_access_tokens_finder.rb
@@ -3,7 +3,7 @@
class PersonalAccessTokensFinder
attr_accessor :params
- delegate :build, :find, :find_by, to: :execute
+ delegate :build, :find, :find_by_id, :find_by_token, to: :execute
def initialize(params = {})
@params = params
diff --git a/app/finders/pipelines_finder.rb b/app/finders/pipelines_finder.rb
index 3d0d3219a94..35d0e1acce5 100644
--- a/app/finders/pipelines_finder.rb
+++ b/app/finders/pipelines_finder.rb
@@ -12,7 +12,6 @@ class PipelinesFinder
@params = params
end
- # rubocop: disable CodeReuse/ActiveRecord
def execute
unless Ability.allowed?(current_user, :read_pipeline, project)
return Ci::Pipeline.none
@@ -28,7 +27,6 @@ class PipelinesFinder
items = by_yaml_errors(items)
sort_items(items)
end
- # rubocop: enable CodeReuse/ActiveRecord
private
diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb
index c2404412006..93d3c991846 100644
--- a/app/finders/projects_finder.rb
+++ b/app/finders/projects_finder.rb
@@ -42,17 +42,7 @@ class ProjectsFinder < UnionFinder
init_collection
end
- collection = by_ids(collection)
- collection = by_personal(collection)
- collection = by_starred(collection)
- collection = by_trending(collection)
- collection = by_visibilty_level(collection)
- collection = by_tags(collection)
- collection = by_search(collection)
- collection = by_archived(collection)
- collection = by_custom_attributes(collection)
- collection = by_deleted_status(collection)
-
+ collection = filter_projects(collection)
sort(collection)
end
@@ -66,6 +56,21 @@ class ProjectsFinder < UnionFinder
end
end
+ # EE would override this to add more filters
+ def filter_projects(collection)
+ collection = by_ids(collection)
+ collection = by_personal(collection)
+ collection = by_starred(collection)
+ collection = by_trending(collection)
+ collection = by_visibilty_level(collection)
+ collection = by_tags(collection)
+ collection = by_search(collection)
+ collection = by_archived(collection)
+ collection = by_custom_attributes(collection)
+ collection = by_deleted_status(collection)
+ collection
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def collection_with_user
if owned_projects?
@@ -83,7 +88,6 @@ class ProjectsFinder < UnionFinder
# rubocop: enable CodeReuse/ActiveRecord
# Builds a collection for an anonymous user.
- # rubocop: disable CodeReuse/ActiveRecord
def collection_without_user
if private_only? || owned_projects? || min_access_level?
Project.none
@@ -91,7 +95,6 @@ class ProjectsFinder < UnionFinder
Project.public_to_user
end
end
- # rubocop: enable CodeReuse/ActiveRecord
def owned_projects?
params[:owned].present?
diff --git a/app/finders/snippets_finder.rb b/app/finders/snippets_finder.rb
index 3528e4228b2..d3774746cb8 100644
--- a/app/finders/snippets_finder.rb
+++ b/app/finders/snippets_finder.rb
@@ -1,140 +1,149 @@
# frozen_string_literal: true
-# Snippets Finder
+# Finder for retrieving snippets that a user can see, optionally scoped to a
+# project or snippets author.
#
-# Used to filter Snippets collections by a set of params
+# Basic usage:
#
-# Arguments.
+# user = User.find(1)
#
-# current_user - The current user, nil also can be used.
-# params:
-# visibility (integer) - Individual snippet visibility: Public(20), internal(10) or private(0).
-# project (Project) - Project related.
-# author (User) - Author related.
+# SnippetsFinder.new(user).execute
#
-# params are optional
+# To limit the snippets to a specific project, supply the `project:` option:
+#
+# user = User.find(1)
+# project = Project.find(1)
+#
+# SnippetsFinder.new(user, project: project).execute
+#
+# Limiting snippets to an author can be done by supplying the `author:` option:
+#
+# user = User.find(1)
+# project = Project.find(1)
+#
+# SnippetsFinder.new(user, author: user).execute
+#
+# To filter snippets using a specific visibility level, you can provide the
+# `scope:` option:
+#
+# user = User.find(1)
+# project = Project.find(1)
+#
+# SnippetsFinder.new(user, author: user, scope: :are_public).execute
+#
+# Valid `scope:` values are:
+#
+# * `:are_private`
+# * `:are_internal`
+# * `:are_public`
+#
+# Any other value will be ignored.
class SnippetsFinder < UnionFinder
- include Gitlab::Allowable
include FinderMethods
- attr_accessor :current_user, :project, :params
+ attr_accessor :current_user, :project, :author, :scope
- def initialize(current_user, params = {})
+ def initialize(current_user = nil, params = {})
@current_user = current_user
- @params = params
@project = params[:project]
+ @author = params[:author]
+ @scope = params[:scope].to_s
+
+ if project && author
+ raise(
+ ArgumentError,
+ 'Filtering by both an author and a project is not supported, ' \
+ 'as this finder is not optimised for this use case'
+ )
+ end
end
def execute
- items = init_collection
- items = by_author(items)
- items = by_visibility(items)
+ base =
+ if project
+ snippets_for_a_single_project
+ else
+ snippets_for_multiple_projects
+ end
- items.fresh
+ base.with_optional_visibility(visibility_from_scope).fresh
end
- private
-
- def init_collection
- if project.present?
- authorized_snippets_from_project
- else
- authorized_snippets
+ # Produces a query that retrieves snippets from multiple projects.
+ #
+ # The resulting query will, depending on the user's permissions, include the
+ # following collections of snippets:
+ #
+ # 1. Snippets that don't belong to any project.
+ # 2. Snippets of projects that are visible to the current user (e.g. snippets
+ # in public projects).
+ # 3. Snippets of projects that the current user is a member of.
+ #
+ # Each collection is constructed in isolation, allowing for greater control
+ # over the resulting SQL query.
+ def snippets_for_multiple_projects
+ queries = [global_snippets]
+
+ if Ability.allowed?(current_user, :read_cross_project)
+ queries << snippets_of_visible_projects
+ queries << snippets_of_authorized_projects if current_user
end
- end
- # rubocop: disable CodeReuse/ActiveRecord
- def authorized_snippets_from_project
- if can?(current_user, :read_project_snippet, project)
- if project.team.member?(current_user)
- project.snippets
- else
- project.snippets.public_to_user(current_user)
- end
- else
- Snippet.none
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- # rubocop: disable CodeReuse/ActiveRecord
- def authorized_snippets
- # This query was intentionally converted to a raw one to get it work in Rails 5.0.
- # In Rails 5.0 and 5.1 there's a bug: https://github.com/rails/arel/issues/531
- # Please convert it back when on rails 5.2 as it works again as expected since 5.2.
- Snippet.where("#{feature_available_projects} OR #{not_project_related}")
- .public_or_visible_to_user(current_user)
+ find_union(queries, Snippet)
end
- # rubocop: enable CodeReuse/ActiveRecord
- # Returns a collection of projects that is either public or visible to the
- # logged in user.
- #
- # A caller must pass in a block to modify individual parts of
- # the query, e.g. to apply .with_feature_available_for_user on top of it.
- # This is useful for performance as we can stick those additional filters
- # at the bottom of e.g. the UNION.
- # rubocop: disable CodeReuse/ActiveRecord
- def projects_for_user
- return yield(Project.public_to_user) unless current_user
-
- # If the current_user is allowed to see all projects,
- # we can shortcut and just return.
- return yield(Project.all) if current_user.full_private_access?
-
- authorized_projects = yield(Project.where('EXISTS (?)', current_user.authorizations_for_projects))
-
- levels = Gitlab::VisibilityLevel.levels_for_user(current_user)
- visible_projects = yield(Project.where(visibility_level: levels))
-
- # We use a UNION here instead of OR clauses since this results in better
- # performance.
- Project.from_union([authorized_projects, visible_projects])
+ def snippets_for_a_single_project
+ Snippet.for_project_with_user(project, current_user)
end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def feature_available_projects
- # Don't return any project related snippets if the user cannot read cross project
- return table[:id].eq(nil).to_sql unless Ability.allowed?(current_user, :read_cross_project)
- projects = projects_for_user do |part|
- part.with_feature_available_for_user(:snippets, current_user)
- end.select(:id)
-
- # This query was intentionally converted to a raw one to get it work in Rails 5.0.
- # In Rails 5.0 and 5.1 there's a bug: https://github.com/rails/arel/issues/531
- # Please convert it back when on rails 5.2 as it works again as expected since 5.2.
- "snippets.project_id IN (#{projects.to_sql})"
+ def global_snippets
+ snippets_for_author_or_visible_to_user.only_global_snippets
end
- def not_project_related
- table[:project_id].eq(nil).to_sql
+ # Returns the snippets that the current user (logged in or not) can view.
+ def snippets_of_visible_projects
+ snippets_for_author_or_visible_to_user
+ .only_include_projects_visible_to(current_user)
+ .only_include_projects_with_snippets_enabled
end
- def table
- Snippet.arel_table
+ # Returns the snippets that the currently logged in user has access to by
+ # being a member of the project the snippets belong to.
+ #
+ # This method requires that `current_user` returns a `User` instead of `nil`,
+ # and is optimised for this specific scenario.
+ def snippets_of_authorized_projects
+ base = author ? snippets_for_author : Snippet.all
+
+ base
+ .only_include_projects_with_snippets_enabled(include_private: true)
+ .only_include_authorized_projects(current_user)
end
- # rubocop: disable CodeReuse/ActiveRecord
- def by_visibility(items)
- visibility = params[:visibility] || visibility_from_scope
-
- return items unless visibility
-
- items.where(visibility_level: visibility)
+ def snippets_for_author_or_visible_to_user
+ if author
+ snippets_for_author
+ elsif current_user
+ Snippet.visible_to_or_authored_by(current_user)
+ else
+ Snippet.public_to_user
+ end
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
- def by_author(items)
- return items unless params[:author]
+ def snippets_for_author
+ base = author.snippets
- items.where(author_id: params[:author].id)
+ if author == current_user
+ # If the current user is also the author of all snippets, then we can
+ # include private snippets.
+ base
+ else
+ base.public_to_user(current_user)
+ end
end
- # rubocop: enable CodeReuse/ActiveRecord
def visibility_from_scope
- case params[:scope].to_s
+ case scope
when 'are_private'
Snippet::PRIVATE
when 'are_internal'
diff --git a/app/finders/template_finder.rb b/app/finders/template_finder.rb
index c92ee9ca9ac..3e483716064 100644
--- a/app/finders/template_finder.rb
+++ b/app/finders/template_finder.rb
@@ -1,29 +1,32 @@
# frozen_string_literal: true
class TemplateFinder
- VENDORED_TEMPLATES = {
+ include Gitlab::Utils::StrongMemoize
+
+ VENDORED_TEMPLATES = HashWithIndifferentAccess.new(
dockerfiles: ::Gitlab::Template::DockerfileTemplate,
gitignores: ::Gitlab::Template::GitignoreTemplate,
gitlab_ci_ymls: ::Gitlab::Template::GitlabCiYmlTemplate
- }.freeze
+ ).freeze
class << self
- def build(type, params = {})
- if type == :licenses
- LicenseTemplateFinder.new(params) # rubocop: disable CodeReuse/Finder
+ def build(type, project, params = {})
+ if type.to_s == 'licenses'
+ LicenseTemplateFinder.new(project, params) # rubocop: disable CodeReuse/Finder
else
- new(type, params)
+ new(type, project, params)
end
end
end
- attr_reader :type, :params
+ attr_reader :type, :project, :params
attr_reader :vendored_templates
private :vendored_templates
- def initialize(type, params = {})
+ def initialize(type, project, params = {})
@type = type
+ @project = project
@params = params
@vendored_templates = VENDORED_TEMPLATES.fetch(type)
diff --git a/app/finders/todos_finder.rb b/app/finders/todos_finder.rb
index 74baf79e4f2..d001e18fea9 100644
--- a/app/finders/todos_finder.rb
+++ b/app/finders/todos_finder.rb
@@ -23,6 +23,8 @@ class TodosFinder
NONE = '0'.freeze
+ TODO_TYPES = Set.new(%w(Issue MergeRequest Epic)).freeze
+
attr_accessor :current_user, :params
def initialize(current_user, params = {})
@@ -45,6 +47,13 @@ class TodosFinder
sort(items)
end
+ # Returns `true` if the current user has any todos for the given target.
+ #
+ # target - The value of the `target_type` column, such as `Issue`.
+ def any_for_target?(target)
+ current_user.todos.any_for_target?(target)
+ end
+
private
def action_id?
@@ -72,14 +81,11 @@ class TodosFinder
end
def author
- return @author if defined?(@author)
-
- @author =
+ strong_memoize(:author) do
if author? && params[:author_id] != NONE
User.find(params[:author_id])
- else
- nil
end
+ end
end
def project?
@@ -91,17 +97,9 @@ class TodosFinder
end
def project
- return @project if defined?(@project)
-
- if project?
- @project = Project.find(params[:project_id])
-
- @project = nil if @project.pending_delete?
- else
- @project = nil
+ strong_memoize(:project) do
+ Project.find_without_deleted(params[:project_id]) if project?
end
-
- @project
end
def group
@@ -111,7 +109,7 @@ class TodosFinder
end
def type?
- type.present? && %w(Issue MergeRequest Epic).include?(type)
+ type.present? && TODO_TYPES.include?(type)
end
def type
@@ -119,77 +117,66 @@ class TodosFinder
end
def sort(items)
- params[:sort] ? items.sort_by_attribute(params[:sort]) : items.order_id_desc
+ if params[:sort]
+ items.sort_by_attribute(params[:sort])
+ else
+ items.order_id_desc
+ end
end
- # rubocop: disable CodeReuse/ActiveRecord
def by_action(items)
if action?
- items = items.where(action: to_action_id)
+ items.for_action(to_action_id)
+ else
+ items
end
-
- items
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def by_action_id(items)
if action_id?
- items = items.where(action: action_id)
+ items.for_action(action_id)
+ else
+ items
end
-
- items
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def by_author(items)
if author?
- items = items.where(author_id: author.try(:id))
+ items.for_author(author)
+ else
+ items
end
-
- items
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def by_project(items)
if project?
- items = items.where(project: project)
+ items.for_project(project)
+ else
+ items
end
-
- items
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def by_group(items)
- return items unless group?
-
- groups = group.self_and_descendants
- project_todos = items.where(project_id: Project.where(group: groups).select(:id))
- group_todos = items.where(group_id: groups.select(:id))
-
- Todo.from_union([project_todos, group_todos])
+ if group?
+ items.for_group_and_descendants(group)
+ else
+ items
+ end
end
- # rubocop: enable CodeReuse/ActiveRecord
def by_state(items)
- case params[:state].to_s
- when 'done'
+ if params[:state].to_s == 'done'
items.done
else
items.pending
end
end
- # rubocop: disable CodeReuse/ActiveRecord
def by_type(items)
if type?
- items = items.where(target_type: type)
+ items.for_type(type)
+ else
+ items
end
-
- items
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/finders/user_finder.rb b/app/finders/user_finder.rb
index 815388c894e..556be4c4338 100644
--- a/app/finders/user_finder.rb
+++ b/app/finders/user_finder.rb
@@ -7,22 +7,52 @@
# times we may want to exclude blocked user. By using this finder (and extending
# it whenever necessary) we can keep this logic in one place.
class UserFinder
- attr_reader :params
+ def initialize(username_or_id)
+ @username_or_id = username_or_id
+ end
+
+ # Tries to find a User by id, returning nil if none could be found.
+ def find_by_id
+ User.find_by_id(@username_or_id)
+ end
- def initialize(params)
- @params = params
+ # Tries to find a User by id, raising a `ActiveRecord::RecordNotFound` if it could
+ # not be found.
+ def find_by_id!
+ User.find(@username_or_id)
end
- # Tries to find a User, returning nil if none could be found.
- # rubocop: disable CodeReuse/ActiveRecord
- def execute
- User.find_by(id: params[:id])
+ # Tries to find a User by username, returning nil if none could be found.
+ def find_by_username
+ User.find_by_username(@username_or_id)
end
- # rubocop: enable CodeReuse/ActiveRecord
- # Tries to find a User, raising a `ActiveRecord::RecordNotFound` if it could
+ # Tries to find a User by username, raising a `ActiveRecord::RecordNotFound` if it could
# not be found.
- def execute!
- User.find(params[:id])
+ def find_by_username!
+ User.find_by_username!(@username_or_id)
+ end
+
+ # Tries to find a User by username or id, returning nil if none could be found.
+ def find_by_id_or_username
+ if input_is_id?
+ find_by_id
+ else
+ find_by_username
+ end
+ end
+
+ # Tries to find a User by username or id, raising a `ActiveRecord::RecordNotFound` if it could
+ # not be found.
+ def find_by_id_or_username!
+ if input_is_id?
+ find_by_id!
+ else
+ find_by_username!
+ end
+ end
+
+ def input_is_id?
+ @username_or_id.is_a?(Numeric) || @username_or_id =~ /^\d+$/
end
end
diff --git a/app/finders/user_recent_events_finder.rb b/app/finders/user_recent_events_finder.rb
index a4daf5b5841..3f2e813d381 100644
--- a/app/finders/user_recent_events_finder.rb
+++ b/app/finders/user_recent_events_finder.rb
@@ -3,6 +3,7 @@
# Get user activity feed for projects common for a user and a logged in user
#
# - current_user: The user viewing the events
+# WARNING: does not consider project feature visibility!
# - user: The user for which to load the events
# - params:
# - offset: The page of events to return
@@ -30,7 +31,7 @@ class UserRecentEventsFinder
recent_events(params[:offset] || 0)
.joins(:project)
.with_associations
- .limit_recent(LIMIT, params[:offset])
+ .limit_recent(params[:limit].presence || LIMIT, params[:offset])
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/finders/users_finder.rb b/app/finders/users_finder.rb
index f2ad9b4bda5..81ae50c0bd1 100644
--- a/app/finders/users_finder.rb
+++ b/app/finders/users_finder.rb
@@ -43,13 +43,11 @@ class UsersFinder
private
- # rubocop: disable CodeReuse/ActiveRecord
def by_username(users)
return users unless params[:username]
- users.where(username: params[:username])
+ users.by_username(params[:username])
end
- # rubocop: enable CodeReuse/ActiveRecord
def by_search(users)
return users unless params[:search].present?
diff --git a/app/finders/users_with_pending_todos_finder.rb b/app/finders/users_with_pending_todos_finder.rb
new file mode 100644
index 00000000000..461bd92a366
--- /dev/null
+++ b/app/finders/users_with_pending_todos_finder.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+# Finder that given a target (e.g. an issue) finds all the users that have
+# pending todos for said target.
+class UsersWithPendingTodosFinder
+ attr_reader :target
+
+ # target - The target, such as an Issue or MergeRequest.
+ def initialize(target)
+ @target = target
+ end
+
+ def execute
+ User.for_todos(target.todos.pending)
+ end
+end
diff --git a/app/graphql/resolvers/full_path_resolver.rb b/app/graphql/resolvers/full_path_resolver.rb
index 8d3da33e8d2..0f1a64b6c58 100644
--- a/app/graphql/resolvers/full_path_resolver.rb
+++ b/app/graphql/resolvers/full_path_resolver.rb
@@ -11,10 +11,11 @@ module Resolvers
end
def model_by_full_path(model, full_path)
- BatchLoader.for(full_path).batch(key: "#{model.model_name.param_key}:full_path") do |full_paths, loader|
+ BatchLoader.for(full_path).batch(key: model) do |full_paths, loader, args|
# `with_route` avoids an N+1 calculating full_path
- results = model.where_full_path_in(full_paths).with_route
- results.each { |project| loader.call(project.full_path, project) }
+ args[:key].where_full_path_in(full_paths).with_route.each do |project|
+ loader.call(project.full_path, project)
+ end
end
end
end
diff --git a/app/graphql/resolvers/issues_resolver.rb b/app/graphql/resolvers/issues_resolver.rb
new file mode 100644
index 00000000000..4ab3c13787a
--- /dev/null
+++ b/app/graphql/resolvers/issues_resolver.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class IssuesResolver < BaseResolver
+ extend ActiveSupport::Concern
+
+ argument :search, GraphQL::STRING_TYPE,
+ required: false
+ argument :sort, Types::Sort,
+ required: false,
+ default_value: 'created_desc'
+
+ type Types::IssueType, null: true
+
+ alias_method :project, :object
+
+ def resolve(**args)
+ # Will need to be be made group & namespace aware with
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/54520
+ args[:project_id] = project.id
+
+ IssuesFinder.new(context[:current_user], args).execute
+ end
+ end
+end
diff --git a/app/graphql/resolvers/merge_request_resolver.rb b/app/graphql/resolvers/merge_request_resolver.rb
index b87c95217f7..d047ce9e3a1 100644
--- a/app/graphql/resolvers/merge_request_resolver.rb
+++ b/app/graphql/resolvers/merge_request_resolver.rb
@@ -14,9 +14,10 @@ module Resolvers
def resolve(iid:)
return unless project.present?
- BatchLoader.for(iid.to_s).batch(key: project.id) do |iids, loader|
- results = project.merge_requests.where(iid: iids)
- results.each { |mr| loader.call(mr.iid.to_s, mr) }
+ BatchLoader.for(iid.to_s).batch(key: project) do |iids, loader, args|
+ args[:key].merge_requests.where(iid: iids).each do |mr|
+ loader.call(mr.iid.to_s, mr)
+ end
end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb
new file mode 100644
index 00000000000..a8f2f7914a8
--- /dev/null
+++ b/app/graphql/types/issue_type.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module Types
+ class IssueType < BaseObject
+ expose_permissions Types::PermissionTypes::Issue
+
+ graphql_name 'Issue'
+
+ present_using IssuePresenter
+
+ field :iid, GraphQL::ID_TYPE, null: false
+ field :title, GraphQL::STRING_TYPE, null: false
+ field :description, GraphQL::STRING_TYPE, null: true
+ field :state, GraphQL::STRING_TYPE, null: false
+
+ field :author, Types::UserType,
+ null: false,
+ resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchModelLoader.new(User, obj.author_id).find } do
+ authorize :read_user
+ end
+
+ field :assignees, Types::UserType.connection_type, null: true
+
+ field :labels, Types::LabelType.connection_type, null: true
+ field :milestone, Types::MilestoneType,
+ null: true,
+ resolve: -> (obj, _args, _ctx) { Gitlab::Graphql::Loaders::BatchModelLoader.new(Milestone, obj.milestone_id).find } do
+ authorize :read_milestone
+ end
+
+ field :due_date, Types::TimeType, null: true
+ field :confidential, GraphQL::BOOLEAN_TYPE, null: false
+ field :discussion_locked, GraphQL::BOOLEAN_TYPE,
+ null: false,
+ resolve: -> (obj, _args, _ctx) { !!obj.discussion_locked }
+
+ field :upvotes, GraphQL::INT_TYPE, null: false
+ field :downvotes, GraphQL::INT_TYPE, null: false
+ field :user_notes_count, GraphQL::INT_TYPE, null: false
+ field :web_url, GraphQL::STRING_TYPE, null: false
+
+ field :closed_at, Types::TimeType, null: true
+
+ field :created_at, Types::TimeType, null: false
+ field :updated_at, Types::TimeType, null: false
+ end
+end
diff --git a/app/graphql/types/label_type.rb b/app/graphql/types/label_type.rb
new file mode 100644
index 00000000000..ccd466edc1a
--- /dev/null
+++ b/app/graphql/types/label_type.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Types
+ class LabelType < BaseObject
+ graphql_name 'Label'
+
+ field :description, GraphQL::STRING_TYPE, null: true
+ field :title, GraphQL::STRING_TYPE, null: false
+ field :color, GraphQL::STRING_TYPE, null: false
+ field :text_color, GraphQL::STRING_TYPE, null: false
+ end
+end
diff --git a/app/graphql/types/milestone_type.rb b/app/graphql/types/milestone_type.rb
new file mode 100644
index 00000000000..af31b572c9a
--- /dev/null
+++ b/app/graphql/types/milestone_type.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Types
+ class MilestoneType < BaseObject
+ graphql_name 'Milestone'
+
+ field :description, GraphQL::STRING_TYPE, null: true
+ field :title, GraphQL::STRING_TYPE, null: false
+ field :state, GraphQL::STRING_TYPE, null: false
+
+ field :due_date, Types::TimeType, null: true
+ field :start_date, Types::TimeType, null: true
+
+ field :created_at, Types::TimeType, null: false
+ field :updated_at, Types::TimeType, null: false
+ end
+end
diff --git a/app/graphql/types/order.rb b/app/graphql/types/order.rb
new file mode 100644
index 00000000000..c5e1cc406b4
--- /dev/null
+++ b/app/graphql/types/order.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+module Types
+ class Types::Order < Types::BaseEnum
+ value "id", "Created at date"
+ value "updated_at", "Updated at date"
+ end
+end
diff --git a/app/graphql/types/permission_types/issue.rb b/app/graphql/types/permission_types/issue.rb
new file mode 100644
index 00000000000..199540c7d6d
--- /dev/null
+++ b/app/graphql/types/permission_types/issue.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Types
+ module PermissionTypes
+ class Issue < BasePermissionType
+ description 'Check permissions for the current user on a issue'
+ graphql_name 'IssuePermissions'
+
+ abilities :read_issue, :admin_issue,
+ :update_issue, :create_note,
+ :reopen_issue
+ end
+ end
+end
diff --git a/app/graphql/types/permission_types/project.rb b/app/graphql/types/permission_types/project.rb
index 066ce64a254..ab37c282fe5 100644
--- a/app/graphql/types/permission_types/project.rb
+++ b/app/graphql/types/permission_types/project.rb
@@ -16,7 +16,7 @@ module Types
:create_deployment, :push_to_delete_protected_branch,
:admin_wiki, :admin_project, :update_pages,
:admin_remote_mirror, :create_label, :update_wiki, :destroy_wiki,
- :create_pages, :destroy_pages
+ :create_pages, :destroy_pages, :read_pages_content
end
end
end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index 7b879608b34..050706f97be 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -73,6 +73,11 @@ module Types
authorize :read_merge_request
end
+ field :issues,
+ Types::IssueType.connection_type,
+ null: true,
+ resolver: Resolvers::IssuesResolver
+
field :pipelines,
Types::Ci::PipelineType.connection_type,
null: false,
diff --git a/app/graphql/types/sort.rb b/app/graphql/types/sort.rb
new file mode 100644
index 00000000000..1f756fdab69
--- /dev/null
+++ b/app/graphql/types/sort.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module Types
+ class Types::Sort < Types::BaseEnum
+ value "updated_desc", "Updated at descending order"
+ value "updated_asc", "Updated at ascending order"
+ value "created_desc", "Created at descending order"
+ value "created_asc", "Created at ascending order"
+ end
+end
diff --git a/app/graphql/types/user_type.rb b/app/graphql/types/user_type.rb
new file mode 100644
index 00000000000..a13e65207df
--- /dev/null
+++ b/app/graphql/types/user_type.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Types
+ class UserType < BaseObject
+ graphql_name 'User'
+
+ present_using UserPresenter
+
+ field :name, GraphQL::STRING_TYPE, null: false
+ field :username, GraphQL::STRING_TYPE, null: false
+ field :avatar_url, GraphQL::STRING_TYPE, null: false
+ field :web_url, GraphQL::STRING_TYPE, null: false
+ end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 32fc8e5e9ce..74042f0bae8 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -173,17 +173,7 @@ module ApplicationHelper
without = options.delete(:without)
add_label = options.delete(:label)
- exist_opts = {
- state: params[:state],
- scope: params[:scope],
- milestone_title: params[:milestone_title],
- assignee_id: params[:assignee_id],
- author_id: params[:author_id],
- search: params[:search],
- label_name: params[:label_name]
- }
-
- options = exist_opts.merge(options)
+ options = request.query_parameters.merge(options)
if without.present?
without.each do |key|
@@ -292,7 +282,8 @@ module ApplicationHelper
mergeRequests: merge_requests_project_autocomplete_sources_path(object),
labels: labels_project_autocomplete_sources_path(object, type: noteable_type, type_id: params[:id]),
milestones: milestones_project_autocomplete_sources_path(object),
- commands: commands_project_autocomplete_sources_path(object, type: noteable_type, type_id: params[:id])
+ commands: commands_project_autocomplete_sources_path(object, type: noteable_type, type_id: params[:id]),
+ snippets: snippets_project_autocomplete_sources_path(object)
}
end
end
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index dc393968786..086bb38ce9a 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -7,7 +7,6 @@ module ApplicationSettingsHelper
:gravatar_enabled?,
:password_authentication_enabled_for_web?,
:akismet_enabled?,
- :koding_enabled?,
to: :'Gitlab::CurrentSettings.current_application_settings'
def user_oauth_applications?
@@ -108,41 +107,6 @@ module ApplicationSettingsHelper
options_for_select(options, selected)
end
- def sidekiq_queue_options_for_select
- options_for_select(Sidekiq::Queue.all.map(&:name), @application_setting.sidekiq_throttling_queues)
- end
-
- def circuitbreaker_failure_count_help_text
- health_link = link_to(s_('AdminHealthPageLink|health page'), admin_health_check_path)
- api_link = link_to(s_('CircuitBreakerApiLink|circuitbreaker api'), help_page_path("api/repository_storage_health"))
- message = _("The number of failures of after which GitLab will completely "\
- "prevent access to the storage. The number of failures can be "\
- "reset in the admin interface: %{link_to_health_page} or using "\
- "the %{api_documentation_link}.")
- message = message % { link_to_health_page: health_link, api_documentation_link: api_link }
-
- message.html_safe
- end
-
- def circuitbreaker_access_retries_help_text
- _('The number of attempts GitLab will make to access a storage.')
- end
-
- def circuitbreaker_failure_reset_time_help_text
- _("The time in seconds GitLab will keep failure information. When no "\
- "failures occur during this time, information about the mount is reset.")
- end
-
- def circuitbreaker_storage_timeout_help_text
- _("The time in seconds GitLab will try to access storage. After this time a "\
- "timeout error will be raised.")
- end
-
- def circuitbreaker_check_interval_help_text
- _("The time in seconds between storage checks. When a previous check did "\
- "complete yet, GitLab will skip a check.")
- end
-
def visible_attributes
[
:admin_notification_email,
@@ -151,14 +115,10 @@ module ApplicationSettingsHelper
:akismet_api_key,
:akismet_enabled,
:allow_local_requests_from_hooks_and_services,
+ :archive_builds_in_human_readable,
:authorized_keys_enabled,
:auto_devops_enabled,
:auto_devops_domain,
- :circuitbreaker_access_retries,
- :circuitbreaker_check_interval,
- :circuitbreaker_failure_count_threshold,
- :circuitbreaker_failure_reset_time,
- :circuitbreaker_storage_timeout,
:clientside_sentry_dsn,
:clientside_sentry_enabled,
:container_registry_token_expire_delay,
@@ -195,8 +155,6 @@ module ApplicationSettingsHelper
:housekeeping_incremental_repack_period,
:html_emails_enabled,
:import_sources,
- :koding_enabled,
- :koding_url,
:max_artifacts_size,
:max_attachment_size,
:max_pages_size,
@@ -234,9 +192,6 @@ module ApplicationSettingsHelper
:session_expire_delay,
:shared_runners_enabled,
:shared_runners_text,
- :sidekiq_throttling_enabled,
- :sidekiq_throttling_factor,
- :sidekiq_throttling_queues,
:sign_in_text,
:signup_enabled,
:terminal_max_session_time,
@@ -261,7 +216,9 @@ module ApplicationSettingsHelper
:user_default_internal_regex,
:user_oauth_applications,
:version_check_enabled,
- :web_ide_clientside_preview_enabled
+ :web_ide_clientside_preview_enabled,
+ :diff_max_patch_bytes,
+ :commit_email_hostname
]
end
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index c158cf20dd6..44f85e9c0f8 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -24,6 +24,23 @@ module AuthHelper
Gitlab::Auth::OAuth::Provider.label_for(name)
end
+ def form_based_provider_priority
+ ['crowd', /^ldap/, 'kerberos']
+ end
+
+ def form_based_provider_with_highest_priority
+ @form_based_provider_with_highest_priority ||= begin
+ form_based_provider_priority.each do |provider_regexp|
+ highest_priority = form_based_providers.find { |provider| provider.match?(provider_regexp) }
+ break highest_priority unless highest_priority.nil?
+ end
+ end
+ end
+
+ def form_based_auth_provider_has_active_class?(provider)
+ form_based_provider_with_highest_priority == provider
+ end
+
def form_based_provider?(name)
[LDAP_PROVIDER, 'crowd'].any? { |pattern| pattern === name.to_s }
end
diff --git a/app/helpers/avatars_helper.rb b/app/helpers/avatars_helper.rb
index 321811a3ca3..5906ddabee4 100644
--- a/app/helpers/avatars_helper.rb
+++ b/app/helpers/avatars_helper.rb
@@ -1,12 +1,12 @@
# frozen_string_literal: true
module AvatarsHelper
- def project_icon(project_id, options = {})
- source_icon(Project, project_id, options)
+ def project_icon(project, options = {})
+ source_icon(project, options)
end
- def group_icon(group_id, options = {})
- source_icon(Group, group_id, options)
+ def group_icon(group, options = {})
+ source_icon(group, options)
end
# Takes both user and email and returns the avatar_icon by
@@ -22,7 +22,7 @@ module AvatarsHelper
end
def avatar_icon_for_email(email = nil, size = nil, scale = 2, only_path: true)
- user = User.find_by_any_email(email.try(:downcase))
+ user = User.find_by_any_email(email)
if user
avatar_icon_for_user(user, size, scale, only_path: only_path)
else
@@ -110,16 +110,11 @@ module AvatarsHelper
private
- def source_icon(klass, source_id, options = {})
- source =
- if source_id.respond_to?(:avatar_url)
- source_id
- else
- klass.find_by_full_path(source_id)
- end
+ def source_icon(source, options = {})
+ avatar_url = source.try(:avatar_url)
- if source.avatar_url
- image_tag source.avatar_url, options
+ if avatar_url
+ image_tag avatar_url, options
else
source_identicon(source, options)
end
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 9cbd5b5f785..638744a1426 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -1,9 +1,8 @@
# frozen_string_literal: true
module BlobHelper
- def highlight(blob_name, blob_content, repository: nil, plain: false)
- plain ||= blob_content.length > Blob::MAXIMUM_TEXT_HIGHLIGHT_SIZE
- highlighted = Gitlab::Highlight.highlight(blob_name, blob_content, plain: plain, repository: repository)
+ def highlight(file_name, file_content, language: nil, plain: false)
+ highlighted = Gitlab::Highlight.highlight(file_name, file_content, plain: plain, language: language)
raw %(<pre class="code highlight"><code>#{highlighted}</code></pre>)
end
@@ -150,7 +149,9 @@ module BlobHelper
# example of Javascript) we tell the browser of the victim not to
# execute untrusted data.
def safe_content_type(blob)
- if blob.text?
+ if blob.extension == 'svg'
+ blob.mime_type
+ elsif blob.text?
'text/plain; charset=utf-8'
elsif blob.image?
blob.content_type
@@ -159,8 +160,10 @@ module BlobHelper
end
end
- def licenses_for_select
- @licenses_for_select ||= template_dropdown_names(TemplateFinder.build(:licenses).execute)
+ def content_disposition(blob, inline)
+ return 'attachment' if blob.extension == 'svg'
+
+ inline ? 'inline' : 'attachment'
end
def ref_project
@@ -173,29 +176,34 @@ module BlobHelper
categories.each_with_object({}) do |category, hash|
hash[category] = grouped[category].map do |item|
- { name: item.name, id: item.id }
+ { name: item.name, id: item.key }
end
end
end
private :template_dropdown_names
- def gitignore_names
- @gitignore_names ||= template_dropdown_names(TemplateFinder.build(:gitignores).execute)
+ def licenses_for_select(project)
+ @licenses_for_select ||= template_dropdown_names(TemplateFinder.build(:licenses, project).execute)
+ end
+
+ def gitignore_names(project)
+ @gitignore_names ||= template_dropdown_names(TemplateFinder.build(:gitignores, project).execute)
end
- def gitlab_ci_ymls
- @gitlab_ci_ymls ||= template_dropdown_names(TemplateFinder.build(:gitlab_ci_ymls).execute)
+ def gitlab_ci_ymls(project)
+ @gitlab_ci_ymls ||= template_dropdown_names(TemplateFinder.build(:gitlab_ci_ymls, project).execute)
end
- def dockerfile_names
- @dockerfile_names ||= template_dropdown_names(TemplateFinder.build(:dockerfiles).execute)
+ def dockerfile_names(project)
+ @dockerfile_names ||= template_dropdown_names(TemplateFinder.build(:dockerfiles, project).execute)
end
- def blob_editor_paths
+ def blob_editor_paths(project)
{
'relative-url-root' => Rails.application.config.relative_url_root,
'assets-prefix' => Gitlab::Application.config.assets.prefix,
- 'blob-language' => @blob && @blob.language.try(:ace_mode)
+ 'blob-filename' => @blob && @blob.path,
+ 'project-id' => project.id
}
end
diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb
index e3b74f443f7..be1e7016a1e 100644
--- a/app/helpers/boards_helper.rb
+++ b/app/helpers/boards_helper.rb
@@ -59,8 +59,8 @@ module BoardsHelper
{
toggle: "dropdown",
- list_labels_path: labels_filter_path(true, include_ancestor_groups: true),
- labels: labels_filter_path(true, include_descendant_groups: include_descendant_groups),
+ list_labels_path: labels_filter_path_with_defaults(only_group_labels: true, include_ancestor_groups: true),
+ labels: labels_filter_path_with_defaults(only_group_labels: true, include_descendant_groups: include_descendant_groups),
labels_endpoint: @labels_endpoint,
namespace_path: @namespace_path,
project_path: @project&.path,
diff --git a/app/helpers/ci_status_helper.rb b/app/helpers/ci_status_helper.rb
index 136772e1ec3..923a06a0512 100644
--- a/app/helpers/ci_status_helper.rb
+++ b/app/helpers/ci_status_helper.rb
@@ -20,6 +20,8 @@ module CiStatusHelper
'passed with warnings'
when 'manual'
'waiting for manual action'
+ when 'scheduled'
+ 'waiting for delayed job'
else
status
end
@@ -39,6 +41,8 @@ module CiStatusHelper
s_('CiStatusText|passed')
when 'manual'
s_('CiStatusText|blocked')
+ when 'scheduled'
+ s_('CiStatusText|delayed')
else
# All states are already being translated inside the detailed statuses:
# :running => Gitlab::Ci::Status::Running
@@ -83,6 +87,8 @@ module CiStatusHelper
'status_skipped'
when 'manual'
'status_manual'
+ when 'scheduled'
+ 'status_scheduled'
else
'status_canceled'
end
diff --git a/app/helpers/clusters_helper.rb b/app/helpers/clusters_helper.rb
index a67c91b21d7..916dcb1a308 100644
--- a/app/helpers/clusters_helper.rb
+++ b/app/helpers/clusters_helper.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
module ClustersHelper
- def has_multiple_clusters?(project)
+ # EE overrides this
+ def has_multiple_clusters?
false
end
@@ -10,11 +11,7 @@ module ClustersHelper
return unless show_gcp_signup_offer?
content_tag :section, class: 'no-animate expanded' do
- render 'projects/clusters/gcp_signup_offer_banner'
+ render 'clusters/clusters/gcp_signup_offer_banner'
end
end
-
- def rbac_clusters_feature_enabled?
- Feature.enabled?(:rbac_clusters)
- end
end
diff --git a/app/helpers/count_helper.rb b/app/helpers/count_helper.rb
index e16223a82c9..13839474e1f 100644
--- a/app/helpers/count_helper.rb
+++ b/app/helpers/count_helper.rb
@@ -8,4 +8,18 @@ module CountHelper
number_with_delimiter(count)
end
+
+ # This will approximate the fork count by checking all counting all fork network
+ # memberships, and deducting 1 for each root of the fork network.
+ # This might be inacurate as the root of the fork network might have been deleted.
+ #
+ # This makes querying this information a lot more effecient and it should be
+ # accurate enough for the instance wide statistics
+ def approximate_fork_count_with_delimiters(count_data)
+ fork_network_count = count_data[ForkNetwork]
+ fork_network_member_count = count_data[ForkNetworkMember]
+ approximate_fork_count = fork_network_member_count - fork_network_count
+
+ number_with_delimiter(approximate_fork_count)
+ end
end
diff --git a/app/helpers/dashboard_helper.rb b/app/helpers/dashboard_helper.rb
index 463f4145bdd..d90ef8903a7 100644
--- a/app/helpers/dashboard_helper.rb
+++ b/app/helpers/dashboard_helper.rb
@@ -2,11 +2,11 @@
module DashboardHelper
def assigned_issues_dashboard_path
- issues_dashboard_path(assignee_id: current_user.id)
+ issues_dashboard_path(assignee_username: current_user.username)
end
def assigned_mrs_dashboard_path
- merge_requests_dashboard_path(assignee_id: current_user.id)
+ merge_requests_dashboard_path(assignee_username: current_user.username)
end
def dashboard_nav_links
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index c94946a04e7..3ce2398f1de 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -91,7 +91,14 @@ module EventsHelper
words << "##{event.target_iid}" if event.target_iid
words << "in"
elsif event.target
- words << "##{event.target_iid}:"
+ prefix =
+ if event.merge_request?
+ MergeRequest.reference_prefix
+ else
+ Issue.reference_prefix
+ end
+
+ words << "#{prefix}#{event.target_iid}:" if event.target_iid
words << event.target.title if event.target.respond_to?(:title)
words << "at"
end
@@ -163,14 +170,10 @@ module EventsHelper
def event_note_title_html(event)
if event.note_target
- text = raw("#{event.note_target_type} ") +
- if event.commit_note?
- content_tag(:span, event.note_target_reference, class: 'commit-sha')
- else
- event.note_target_reference
- end
-
- link_to(text, event_note_target_url(event), title: event.target_title, class: 'has-tooltip')
+ capture do
+ concat content_tag(:span, event.note_target_type, class: "event-target-type append-right-4")
+ concat link_to(event.note_target_reference, event_note_target_url(event), title: event.target_title, class: 'has-tooltip event-target-link append-right-4')
+ end
else
content_tag(:strong, '(deleted)')
end
@@ -183,17 +186,9 @@ module EventsHelper
"--broken encoding"
end
- def event_row_class(event)
- if event.body?
- "event-block"
- else
- "event-inline"
- end
- end
-
- def icon_for_event(note)
+ def icon_for_event(note, size: 24)
icon_name = ICON_NAMES_BY_EVENT_TYPE[note]
- sprite_icon(icon_name) if icon_name
+ sprite_icon(icon_name, size: size) if icon_name
end
def icon_for_profile_event(event)
@@ -203,8 +198,24 @@ module EventsHelper
end
else
content_tag :div, class: 'system-note-image user-avatar' do
- author_avatar(event, size: 32)
+ author_avatar(event, size: 40)
end
end
end
+
+ def inline_event_icon(event)
+ unless current_path?('users#show')
+ content_tag :span, class: "system-note-image-inline d-none d-sm-flex append-right-4 #{event.action_name.parameterize}-icon align-self-center" do
+ icon_for_event(event.action_name, size: 14)
+ end
+ end
+ end
+
+ def event_user_info(event)
+ content_tag(:div, class: "event-user-info") do
+ concat content_tag(:span, link_to_author(event), class: "author_name")
+ concat "&nbsp;".html_safe
+ concat content_tag(:span, event.author.to_reference, class: "username")
+ end
+ end
end
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index f573fd399a5..e9b9b9b7721 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -1,6 +1,15 @@
# frozen_string_literal: true
module GroupsHelper
+ def group_overview_nav_link_paths
+ %w[
+ groups#show
+ groups#activity
+ groups#subgroups
+ analytics#show
+ ]
+ end
+
def group_nav_link_paths
%w[groups#projects groups#edit badges#index ci_cd#show ldap_group_links#index hooks#index audit_events#index pipeline_quota#index]
end
@@ -131,6 +140,10 @@ module GroupsHelper
can?(current_user, "read_group_#{resource}".to_sym, @group)
end
+ if can?(current_user, :read_cluster, @group) && Feature.enabled?(:group_clusters)
+ links << :kubernetes
+ end
+
if can?(current_user, :admin_group, @group)
links << :settings
end
diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb
index 037004327b9..b0f63de2fb8 100644
--- a/app/helpers/icons_helper.rb
+++ b/app/helpers/icons_helper.rb
@@ -109,6 +109,8 @@ module IconsHelper
def file_type_icon_class(type, mode, name)
if type == 'folder'
icon_class = 'folder'
+ elsif type == 'archive'
+ icon_class = 'archive'
elsif mode == '120000'
icon_class = 'share'
else
@@ -153,6 +155,6 @@ module IconsHelper
private
def known_sprites
- @known_sprites ||= JSON.parse(File.read(Rails.root.join('node_modules/@gitlab-org/gitlab-svgs/dist/icons.json')))['icons']
+ @known_sprites ||= JSON.parse(File.read(Rails.root.join('node_modules/@gitlab/svgs/dist/icons.json')))['icons']
end
end
diff --git a/app/helpers/import_helper.rb b/app/helpers/import_helper.rb
index 3d0eb3d0d51..49171df1433 100644
--- a/app/helpers/import_helper.rb
+++ b/app/helpers/import_helper.rb
@@ -83,7 +83,7 @@ module ImportHelper
private
def github_project_url(full_path)
- URI.join(github_root_url, full_path).to_s
+ Gitlab::Utils.append_path(github_root_url, full_path)
end
def github_root_url
@@ -95,6 +95,6 @@ module ImportHelper
end
def gitea_project_url(full_path)
- URI.join(@gitea_host_url, full_path).to_s
+ Gitlab::Utils.append_path(@gitea_host_url, full_path)
end
end
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 56f6686da57..dfa86f52e40 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -327,11 +327,15 @@ module IssuablesHelper
end
def issuable_button_visibility(issuable, closed)
+ return 'hidden' if issuable_button_hidden?(issuable, closed)
+ end
+
+ def issuable_button_hidden?(issuable, closed)
case issuable
when Issue
- issue_button_visibility(issuable, closed)
+ issue_button_hidden?(issuable, closed)
when MergeRequest
- merge_request_button_visibility(issuable, closed)
+ merge_request_button_hidden?(issuable, closed)
end
end
@@ -358,6 +362,10 @@ module IssuablesHelper
end
end
+ def has_filter_bar_param?
+ finder.class.scalar_params.any? { |p| params[p].present? }
+ end
+
private
def sidebar_gutter_collapsed?
@@ -382,8 +390,8 @@ module IssuablesHelper
{
todo_text: "Add todo",
mark_text: "Mark todo as done",
- todo_icon: (is_collapsed ? icon('plus-square') : nil),
- mark_icon: (is_collapsed ? icon('check-square', class: 'todo-undone') : nil),
+ todo_icon: (is_collapsed ? sprite_icon('todo-add') : nil),
+ mark_icon: (is_collapsed ? sprite_icon('todo-done', css_class: 'todo-undone') : nil),
issuable_id: issuable.id,
issuable_type: issuable.class.name.underscore,
url: project_todos_path(@project),
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index f7d448ea3a7..957ab06b0ca 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -64,7 +64,11 @@ module IssuesHelper
end
def issue_button_visibility(issue, closed)
- return 'hidden' if issue.closed? == closed
+ return 'hidden' if issue_button_hidden?(issue, closed)
+ end
+
+ def issue_button_hidden?(issue, closed)
+ issue.closed? == closed || (!closed && issue.discussion_locked)
end
def confidential_icon(issue)
diff --git a/app/helpers/labels_helper.rb b/app/helpers/labels_helper.rb
index 6c51739ba1a..39f661b5f0c 100644
--- a/app/helpers/labels_helper.rb
+++ b/app/helpers/labels_helper.rb
@@ -131,20 +131,26 @@ module LabelsHelper
end
end
- def labels_filter_path(only_group_labels = false, include_ancestor_groups: true, include_descendant_groups: false)
- project = @target_project || @project
-
+ def labels_filter_path_with_defaults(only_group_labels: false, include_ancestor_groups: true, include_descendant_groups: false)
options = {}
options[:include_ancestor_groups] = include_ancestor_groups if include_ancestor_groups
options[:include_descendant_groups] = include_descendant_groups if include_descendant_groups
+ options[:only_group_labels] = only_group_labels if only_group_labels && @group
+ options[:format] = :json
+
+ labels_filter_path(options)
+ end
+
+ def labels_filter_path(options = {})
+ project = @target_project || @project
+ format = options.delete(:format)
if project
- project_labels_path(project, :json, options)
+ project_labels_path(project, format, options)
elsif @group
- options[:only_group_labels] = only_group_labels if only_group_labels
- group_labels_path(@group, :json, options)
+ group_labels_path(@group, format, options)
else
- dashboard_labels_path(:json)
+ dashboard_labels_path(format, options)
end
end
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index 87af6fb08f0..23d7aa427bb 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -80,7 +80,11 @@ module MergeRequestsHelper
end
def merge_request_button_visibility(merge_request, closed)
- return 'hidden' if merge_request.closed? == closed || (merge_request.merged? == closed && !merge_request.closed?) || merge_request.closed_without_fork?
+ return 'hidden' if merge_request_button_hidden?(merge_request, closed)
+ end
+
+ def merge_request_button_hidden?(merge_request, closed)
+ merge_request.closed? == closed || (merge_request.merged? == closed && !merge_request.closed?) || merge_request.closed_without_fork?
end
def merge_request_version_path(project, merge_request, merge_request_diff, start_sha = nil)
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
index 94a030d9d57..9666080092b 100644
--- a/app/helpers/milestones_helper.rb
+++ b/app/helpers/milestones_helper.rb
@@ -2,6 +2,7 @@
module MilestonesHelper
include EntityDateHelper
+ include Gitlab::Utils::StrongMemoize
def milestones_filter_path(opts = {})
if @project
@@ -243,4 +244,16 @@ module MilestonesHelper
dashboard_milestone_path(milestone.safe_title, title: milestone.title)
end
end
+
+ def can_admin_project_milestones?
+ strong_memoize(:can_admin_project_milestones) do
+ can?(current_user, :admin_milestone, @project)
+ end
+ end
+
+ def can_admin_group_milestones?
+ strong_memoize(:can_admin_group_milestones) do
+ can?(current_user, :admin_milestone, @project.group)
+ end
+ end
end
diff --git a/app/helpers/mirror_helper.rb b/app/helpers/mirror_helper.rb
index a4025730397..65c7cd82832 100644
--- a/app/helpers/mirror_helper.rb
+++ b/app/helpers/mirror_helper.rb
@@ -2,6 +2,9 @@
module MirrorHelper
def mirrors_form_data_attributes
- { project_mirror_endpoint: project_mirror_path(@project) }
+ {
+ project_mirror_ssh_endpoint: ssh_host_keys_project_mirror_path(@project, :json),
+ project_mirror_endpoint: project_mirror_path(@project, :json)
+ }
end
end
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index 761f42f2f0f..a7fe8c3d59c 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -19,10 +19,7 @@ module NavHelper
end
def page_gutter_class
- if current_path?('merge_requests#show') ||
- current_path?('projects/merge_requests/conflicts#show') ||
- current_path?('issues#show') ||
- current_path?('milestones#show')
+ if page_has_markdown?
if cookies[:collapsed_gutter] == 'true'
%w[page-gutter right-sidebar-collapsed]
@@ -50,6 +47,17 @@ module NavHelper
class_names
end
+ def show_separator?
+ Gitlab::Sherlock.enabled? || can?(current_user, :read_instance_statistics)
+ end
+
+ def page_has_markdown?
+ current_path?('merge_requests#show') ||
+ current_path?('projects/merge_requests/conflicts#show') ||
+ current_path?('issues#show') ||
+ current_path?('milestones#show')
+ end
+
private
def get_header_links
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index a80c8f273a8..033686823a2 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -142,7 +142,7 @@ module NotesHelper
def initial_notes_data(autocomplete)
{
notesUrl: notes_url,
- notesIds: @notes.map(&:id),
+ notesIds: @noteable.notes.pluck(:id), # rubocop: disable CodeReuse/ActiveRecord
now: Time.now.to_i,
diffView: diff_view,
enableGFM: {
@@ -178,7 +178,7 @@ module NotesHelper
notesPath: notes_url,
totalNotes: issuable.discussions.length,
lastFetchedAt: Time.now.to_i
- }.to_json
+ }
end
def discussion_resolved_intro(discussion)
diff --git a/app/helpers/page_layout_helper.rb b/app/helpers/page_layout_helper.rb
index b33c074d1af..5038dcf9746 100644
--- a/app/helpers/page_layout_helper.rb
+++ b/app/helpers/page_layout_helper.rb
@@ -10,7 +10,7 @@ module PageLayoutHelper
@breadcrumb_title = @page_title.last
end
- # Segments are seperated by middot
+ # Segments are separated by middot
@page_title.join(" · ")
end
diff --git a/app/helpers/preferences_helper.rb b/app/helpers/preferences_helper.rb
index ff9842d4cd9..f4f46b0fe96 100644
--- a/app/helpers/preferences_helper.rb
+++ b/app/helpers/preferences_helper.rb
@@ -18,22 +18,20 @@ module PreferencesHelper
groups: _("Your Groups"),
todos: _("Your Todos"),
issues: _("Assigned Issues"),
- merge_requests: _("Assigned Merge Requests")
+ merge_requests: _("Assigned Merge Requests"),
+ operations: _("Operations Dashboard")
}.with_indifferent_access.freeze
# Returns an Array usable by a select field for more user-friendly option text
def dashboard_choices
- defined = User.dashboards
+ dashboards = User.dashboards.keys
- if defined.size != DASHBOARD_CHOICES.size
- # Ensure that anyone adding new options updates this method too
- raise "`User` defines #{defined.size} dashboard choices," \
- " but `DASHBOARD_CHOICES` defined #{DASHBOARD_CHOICES.size}."
- else
- defined.map do |key, _|
- # Use `fetch` so `KeyError` gets raised when a key is missing
- [DASHBOARD_CHOICES.fetch(key), key]
- end
+ validate_dashboard_choices!(dashboards)
+ dashboards -= excluded_dashboard_choices
+
+ dashboards.map do |key|
+ # Use `fetch` so `KeyError` gets raised when a key is missing
+ [DASHBOARD_CHOICES.fetch(key), key]
end
end
@@ -52,4 +50,20 @@ module PreferencesHelper
def user_color_scheme
Gitlab::ColorSchemes.for_user(current_user).css_class
end
+
+ private
+
+ # Ensure that anyone adding new options updates `DASHBOARD_CHOICES` too
+ def validate_dashboard_choices!(user_dashboards)
+ if user_dashboards.size != DASHBOARD_CHOICES.size
+ raise "`User` defines #{user_dashboards.size} dashboard choices," \
+ " but `DASHBOARD_CHOICES` defined #{DASHBOARD_CHOICES.size}."
+ end
+ end
+
+ # List of dashboard choice to be excluded from CE.
+ # EE would override this.
+ def excluded_dashboard_choices
+ ['operations']
+ end
end
diff --git a/app/helpers/profiles_helper.rb b/app/helpers/profiles_helper.rb
index 55674e37a34..df318de740a 100644
--- a/app/helpers/profiles_helper.rb
+++ b/app/helpers/profiles_helper.rb
@@ -1,6 +1,20 @@
# frozen_string_literal: true
module ProfilesHelper
+ def commit_email_select_options(user)
+ private_email = user.private_commit_email
+ verified_emails = user.verified_emails - [private_email]
+
+ [
+ [s_("Profiles|Use a private email - %{email}").html_safe % { email: private_email }, Gitlab::PrivateCommitEmail::TOKEN],
+ *verified_emails
+ ]
+ end
+
+ def selected_commit_email(user)
+ user.read_attribute(:commit_email) || user.commit_email
+ end
+
def attribute_provider_label(attribute)
user_synced_attributes_metadata = current_user.user_synced_attributes_metadata
if user_synced_attributes_metadata&.synced?(attribute)
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 8b17e6ef75d..0a7f930110a 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -388,22 +388,6 @@ module ProjectsHelper
end
end
- def koding_project_url(project = nil, branch = nil, sha = nil)
- if project
- import_path = "/Home/Stacks/import"
-
- repo = project.full_path
- branch ||= project.default_branch
- sha ||= project.commit.short_id
-
- path = "#{import_path}?repo=#{repo}&branch=#{branch}&sha=#{sha}"
-
- return URI.join(Gitlab::CurrentSettings.koding_url, path).to_s
- end
-
- Gitlab::CurrentSettings.koding_url
- end
-
def project_wiki_path_with_version(proj, page, version, is_newest)
url_params = is_newest ? {} : { version_id: version }
project_wiki_path(proj, page, url_params)
@@ -454,6 +438,7 @@ module ProjectsHelper
buildsAccessLevel: feature.builds_access_level,
wikiAccessLevel: feature.wiki_access_level,
snippetsAccessLevel: feature.snippets_access_level,
+ pagesAccessLevel: feature.pages_access_level,
containerRegistryEnabled: !!project.container_registry_enabled,
lfsEnabled: !!project.lfs_enabled
}
@@ -468,7 +453,10 @@ module ProjectsHelper
registryAvailable: Gitlab.config.registry.enabled,
registryHelpPath: help_page_path('user/project/container_registry'),
lfsAvailable: Gitlab.config.lfs.enabled,
- lfsHelpPath: help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs')
+ lfsHelpPath: help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs'),
+ pagesAvailable: Gitlab.config.pages.enabled,
+ pagesAccessControlEnabled: Gitlab.config.pages.access_control,
+ pagesHelpPath: help_page_path('user/project/pages/index.md')
}
end
@@ -552,4 +540,13 @@ module ProjectsHelper
network
]
end
+
+ def sidebar_operations_paths
+ %w[
+ environments
+ clusters
+ user
+ gcp
+ ]
+ end
end
diff --git a/app/helpers/repository_languages_helper.rb b/app/helpers/repository_languages_helper.rb
index c1505b52808..cf7eee7fff3 100644
--- a/app/helpers/repository_languages_helper.rb
+++ b/app/helpers/repository_languages_helper.rb
@@ -13,6 +13,7 @@ module RepositoryLanguagesHelper
content_tag :div, nil,
class: "progress-bar has-tooltip",
style: "width: #{lang.share}%; background-color:#{lang.color}",
- title: lang.name
+ data: { html: true },
+ title: "<span class=\"repository-language-bar-tooltip-language\">#{escape_javascript(lang.name)}</span>&nbsp;<span class=\"repository-language-bar-tooltip-share\">#{lang.share.round(1)}%</span>"
end
end
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 4f9e1322b56..80cc568820a 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -163,15 +163,26 @@ module SearchHelper
if @project.present?
opts[:data]['project-id'] = @project.id
opts[:data]['base-endpoint'] = project_path(@project)
- else
- # Group context
+ elsif @group.present?
opts[:data]['group-id'] = @group.id
opts[:data]['base-endpoint'] = group_canonical_path(@group)
+ else
+ opts[:data]['base-endpoint'] = root_dashboard_path
end
opts
end
+ def search_history_storage_prefix
+ if @project.present?
+ @project.full_path
+ elsif @group.present?
+ @group.full_path
+ else
+ 'dashboard'
+ end
+ end
+
# Sanitize a HTML field for search display. Most tags are stripped out and the
# maximum length is set to 200 characters.
def search_md_sanitize(object, field)
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
index 53bd43d4861..8ed2a2ec9f4 100644
--- a/app/helpers/sorting_helper.rb
+++ b/app/helpers/sorting_helper.rb
@@ -48,15 +48,21 @@ module SortingHelper
def groups_sort_options_hash
{
- sort_value_name => sort_title_name,
- sort_value_name_desc => sort_title_name_desc,
+ sort_value_name => sort_title_name,
+ sort_value_name_desc => sort_title_name_desc,
sort_value_recently_created => sort_title_recently_created,
- sort_value_oldest_created => sort_title_oldest_created,
+ sort_value_oldest_created => sort_title_oldest_created,
sort_value_recently_updated => sort_title_recently_updated,
- sort_value_oldest_updated => sort_title_oldest_updated
+ sort_value_oldest_updated => sort_title_oldest_updated
}
end
+ def subgroups_sort_options_hash
+ groups_sort_options_hash.merge(
+ sort_value_most_stars => sort_title_most_stars
+ )
+ end
+
def admin_groups_sort_options_hash
groups_sort_options_hash.merge(
sort_value_largest_group => sort_title_largest_group
diff --git a/app/helpers/storage_health_helper.rb b/app/helpers/storage_health_helper.rb
deleted file mode 100644
index 182e8e6641b..00000000000
--- a/app/helpers/storage_health_helper.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-module StorageHealthHelper
- def failing_storage_health_message(storage_health)
- storage_name = content_tag(:strong, h(storage_health.storage_name))
- host_names = h(storage_health.failing_on_hosts.to_sentence)
- translation_params = { storage_name: storage_name,
- host_names: host_names,
- failed_attempts: storage_health.total_failures }
-
- translation = n_('%{storage_name}: failed storage access attempt on host:',
- '%{storage_name}: %{failed_attempts} failed storage access attempts:',
- storage_health.total_failures) % translation_params
-
- translation.html_safe
- end
-
- def message_for_circuit_breaker(circuit_breaker)
- maximum_failures = circuit_breaker.failure_count_threshold
- current_failures = circuit_breaker.failure_count
-
- translation_params = { number_of_failures: current_failures,
- maximum_failures: maximum_failures }
-
- if circuit_breaker.circuit_broken?
- s_("%{number_of_failures} of %{maximum_failures} failures. GitLab will not "\
- "retry automatically. Reset storage information when the problem is "\
- "resolved.") % translation_params
- else
- _("%{number_of_failures} of %{maximum_failures} failures. GitLab will "\
- "allow access on the next attempt.") % translation_params
- end
- end
-end
diff --git a/app/helpers/time_helper.rb b/app/helpers/time_helper.rb
index 94044d7b85e..719c351242c 100644
--- a/app/helpers/time_helper.rb
+++ b/app/helpers/time_helper.rb
@@ -21,9 +21,15 @@ module TimeHelper
"#{from.to_s(:short)} - #{to.to_s(:short)}"
end
- def duration_in_numbers(duration)
- time_format = duration < 1.hour ? "%M:%S" : "%H:%M:%S"
+ def duration_in_numbers(duration_in_seconds)
+ seconds = duration_in_seconds % 1.minute
+ minutes = (duration_in_seconds / 1.minute) % (1.hour / 1.minute)
+ hours = duration_in_seconds / 1.hour
- Time.at(duration).utc.strftime(time_format)
+ if hours == 0
+ "%02d:%02d" % [minutes, seconds]
+ else
+ "%02d:%02d:%02d" % [hours, minutes, seconds]
+ end
end
end
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index 6d2da5699fb..e2879bfdcf1 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -31,11 +31,21 @@ module TreeHelper
# mode - File unix mode
# name - File name
def tree_icon(type, mode, name)
- icon("#{file_type_icon_class(type, mode, name)} fw")
+ icon([file_type_icon_class(type, mode, name), 'fw'])
end
- def tree_hex_class(content)
- "file_#{hexdigest(content.name)}"
+ # Using Rails `*_path` methods can be slow, especially when generating
+ # many paths, as with a repository tree that has thousands of items.
+ def fast_project_blob_path(project, blob_path)
+ ActionDispatch::Journey::Router::Utils.escape_path(
+ File.join(relative_url_root, project.path_with_namespace, 'blob', blob_path)
+ )
+ end
+
+ def fast_project_tree_path(project, tree_path)
+ ActionDispatch::Journey::Router::Utils.escape_path(
+ File.join(relative_url_root, project.path_with_namespace, 'tree', tree_path)
+ )
end
# Simple shortcut to File.join
@@ -142,4 +152,8 @@ module TreeHelper
def selected_branch
@branch_name || tree_edit_branch
end
+
+ def relative_url_root
+ Gitlab.config.gitlab.relative_url_root.presence || '/'
+ end
end
diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb
index bae01d476df..4aba48061ba 100644
--- a/app/helpers/user_callouts_helper.rb
+++ b/app/helpers/user_callouts_helper.rb
@@ -3,7 +3,6 @@
module UserCalloutsHelper
GKE_CLUSTER_INTEGRATION = 'gke_cluster_integration'.freeze
GCP_SIGNUP_OFFER = 'gcp_signup_offer'.freeze
- CLUSTER_SECURITY_WARNING = 'cluster_security_warning'.freeze
def show_gke_cluster_integration_callout?(project)
can?(current_user, :create_cluster, project) &&
@@ -14,10 +13,6 @@ module UserCalloutsHelper
!user_dismissed?(GCP_SIGNUP_OFFER)
end
- def show_cluster_security_warning?
- !user_dismissed?(CLUSTER_SECURITY_WARNING)
- end
-
private
def user_dismissed?(feature_name)
diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb
index bcd91f619c8..bde9ca0cbf2 100644
--- a/app/helpers/users_helper.rb
+++ b/app/helpers/users_helper.rb
@@ -70,13 +70,17 @@ module UsersHelper
end
end
+ def impersonation_enabled?
+ Gitlab.config.gitlab.impersonation_enabled
+ end
+
private
def get_profile_tabs
tabs = []
if can?(current_user, :read_user_profile, @user)
- tabs += [:activity, :groups, :contributed, :projects, :snippets]
+ tabs += [:overview, :activity, :groups, :contributed, :projects, :snippets]
end
tabs
diff --git a/app/helpers/version_check_helper.rb b/app/helpers/version_check_helper.rb
index 75637eb0676..ab77b149072 100644
--- a/app/helpers/version_check_helper.rb
+++ b/app/helpers/version_check_helper.rb
@@ -9,4 +9,17 @@ module VersionCheckHelper
image_url = VersionCheck.new.url
image_tag image_url, class: 'js-version-status-badge'
end
+
+ def link_to_version
+ if Gitlab.pre_release?
+ commit_link = link_to(Gitlab.revision, Gitlab::COM_URL + namespace_project_commits_path('gitlab-org', source_code_project, Gitlab.revision))
+ [Gitlab::VERSION, content_tag(:small, commit_link)].join(' ').html_safe
+ else
+ link_to Gitlab::VERSION, Gitlab::COM_URL + namespace_project_tag_path('gitlab-org', source_code_project, "v#{Gitlab::VERSION}")
+ end
+ end
+
+ def source_code_project
+ 'gitlab-ce'
+ end
end
diff --git a/app/helpers/workhorse_helper.rb b/app/helpers/workhorse_helper.rb
index f19445fca1a..49c08dce96c 100644
--- a/app/helpers/workhorse_helper.rb
+++ b/app/helpers/workhorse_helper.rb
@@ -6,7 +6,7 @@ module WorkhorseHelper
# Send a Git blob through Workhorse
def send_git_blob(repository, blob, inline: true)
headers.store(*Gitlab::Workhorse.send_git_blob(repository, blob))
- headers['Content-Disposition'] = inline ? 'inline' : 'attachment'
+ headers['Content-Disposition'] = content_disposition(blob, inline)
headers['Content-Type'] = safe_content_type(blob)
render plain: ""
end
diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb
index 602e5afe26b..93b51fb1774 100644
--- a/app/mailers/emails/issues.rb
+++ b/app/mailers/emails/issues.rb
@@ -45,6 +45,20 @@ module Emails
mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id, reason))
end
+ def removed_milestone_issue_email(recipient_id, issue_id, updated_by_user_id, reason = nil)
+ setup_issue_mail(issue_id, recipient_id)
+
+ mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id, reason))
+ end
+
+ def changed_milestone_issue_email(recipient_id, issue_id, milestone, updated_by_user_id, reason = nil)
+ setup_issue_mail(issue_id, recipient_id)
+
+ @milestone = milestone
+ @milestone_url = milestone_url(@milestone)
+ mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id, reason))
+ end
+
def issue_status_changed_email(recipient_id, issue_id, status, updated_by_user_id, reason = nil)
setup_issue_mail(issue_id, recipient_id)
diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb
index 67af0a4eb98..6524d0c2087 100644
--- a/app/mailers/emails/merge_requests.rb
+++ b/app/mailers/emails/merge_requests.rb
@@ -3,13 +3,14 @@
module Emails
module MergeRequests
def new_merge_request_email(recipient_id, merge_request_id, reason = nil)
- setup_merge_request_mail(merge_request_id, recipient_id)
+ setup_merge_request_mail(merge_request_id, recipient_id, present: true)
mail_new_thread(@merge_request, merge_request_thread_options(@merge_request.author_id, recipient_id, reason))
end
def new_mention_in_merge_request_email(recipient_id, merge_request_id, updated_by_user_id, reason = nil)
- setup_merge_request_mail(merge_request_id, recipient_id)
+ setup_merge_request_mail(merge_request_id, recipient_id, present: true)
+
mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
end
@@ -39,6 +40,20 @@ module Emails
mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
end
+ def removed_milestone_merge_request_email(recipient_id, merge_request_id, updated_by_user_id, reason = nil)
+ setup_merge_request_mail(merge_request_id, recipient_id)
+
+ mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
+ end
+
+ def changed_milestone_merge_request_email(recipient_id, merge_request_id, milestone, updated_by_user_id, reason = nil)
+ setup_merge_request_mail(merge_request_id, recipient_id)
+
+ @milestone = milestone
+ @milestone_url = milestone_url(@milestone)
+ mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
+ end
+
def closed_merge_request_email(recipient_id, merge_request_id, updated_by_user_id, reason = nil)
setup_merge_request_mail(merge_request_id, recipient_id)
@@ -75,11 +90,16 @@ module Emails
private
- def setup_merge_request_mail(merge_request_id, recipient_id)
+ def setup_merge_request_mail(merge_request_id, recipient_id, present: false)
@merge_request = MergeRequest.find(merge_request_id)
@project = @merge_request.project
@target_url = project_merge_request_url(@project, @merge_request)
+ if present
+ recipient = User.find(recipient_id)
+ @mr_presenter = @merge_request.present(current_user: recipient)
+ end
+
@sent_notification = SentNotification.record(@merge_request, recipient_id, reply_key)
end
diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb
index d3284e90568..1b3c1f9a8a9 100644
--- a/app/mailers/emails/notes.rb
+++ b/app/mailers/emails/notes.rb
@@ -26,7 +26,7 @@ module Emails
mail_answer_note_thread(@merge_request, @note, note_thread_options(recipient_id))
end
- def note_snippet_email(recipient_id, note_id)
+ def note_project_snippet_email(recipient_id, note_id)
setup_note_mail(note_id, recipient_id)
@snippet = @note.noteable
diff --git a/app/mailers/notify.rb b/app/mailers/notify.rb
index f7347ee61b4..662f3e00047 100644
--- a/app/mailers/notify.rb
+++ b/app/mailers/notify.rb
@@ -118,6 +118,7 @@ class Notify < BaseMailer
add_unsubscription_headers_and_links
headers["X-GitLab-#{model.class.name}-ID"] = model.id
+ headers["X-GitLab-#{model.class.name}-IID"] = model.iid if model.respond_to?(:iid)
headers['X-GitLab-Reply-Key'] = reply_key
@reason = headers['X-GitLab-NotificationReason']
diff --git a/app/mailers/previews/notify_preview.rb b/app/mailers/previews/notify_preview.rb
index 2f5b5483e9d..e7e8d96eca4 100644
--- a/app/mailers/previews/notify_preview.rb
+++ b/app/mailers/previews/notify_preview.rb
@@ -68,6 +68,14 @@ class NotifyPreview < ActionMailer::Preview
Notify.issue_status_changed_email(user.id, issue.id, 'closed', user.id).message
end
+ def removed_milestone_issue_email
+ Notify.removed_milestone_issue_email(user.id, issue.id, user.id)
+ end
+
+ def changed_milestone_issue_email
+ Notify.changed_milestone_issue_email(user.id, issue.id, milestone, user.id)
+ end
+
def closed_merge_request_email
Notify.closed_merge_request_email(user.id, issue.id, user.id).message
end
@@ -80,6 +88,14 @@ class NotifyPreview < ActionMailer::Preview
Notify.merged_merge_request_email(user.id, merge_request.id, user.id).message
end
+ def removed_milestone_merge_request_email
+ Notify.removed_milestone_merge_request_email(user.id, merge_request.id, user.id)
+ end
+
+ def changed_milestone_merge_request_email
+ Notify.changed_milestone_merge_request_email(user.id, merge_request.id, milestone, user.id)
+ end
+
def member_access_denied_email
Notify.member_access_denied_email('project', project.id, user.id).message
end
@@ -143,6 +159,10 @@ class NotifyPreview < ActionMailer::Preview
@merge_request ||= project.merge_requests.first
end
+ def milestone
+ @milestone ||= issue.milestone
+ end
+
def pipeline
@pipeline = Ci::Pipeline.last
end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index a853106e5bd..1466407d0d1 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -74,7 +74,7 @@ class Ability
end
def policy_for(user, subject = :global)
- cache = RequestStore.active? ? RequestStore : {}
+ cache = Gitlab::SafeRequestStore.active? ? Gitlab::SafeRequestStore : {}
DeclarativePolicy.policy_for(user, subject, cache: cache)
end
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
new file mode 100644
index 00000000000..71fbba5b328
--- /dev/null
+++ b/app/models/application_record.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class ApplicationRecord < ActiveRecord::Base
+ self.abstract_class = true
+end
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 645adddb000..207ffae873a 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -4,6 +4,8 @@ class ApplicationSetting < ActiveRecord::Base
include CacheableAttributes
include CacheMarkdownField
include TokenAuthenticatable
+ include IgnorableColumn
+ include ChronicDurationAttribute
add_authentication_token_field :runners_registration_token
add_authentication_token_field :health_check_access_token
@@ -26,7 +28,14 @@ class ApplicationSetting < ActiveRecord::Base
serialize :domain_whitelist, Array # rubocop:disable Cop/ActiveRecordSerialize
serialize :domain_blacklist, Array # rubocop:disable Cop/ActiveRecordSerialize
serialize :repository_storages # rubocop:disable Cop/ActiveRecordSerialize
- serialize :sidekiq_throttling_queues, Array # rubocop:disable Cop/ActiveRecordSerialize
+
+ ignore_column :circuitbreaker_failure_count_threshold
+ ignore_column :circuitbreaker_failure_reset_time
+ ignore_column :circuitbreaker_storage_timeout
+ ignore_column :circuitbreaker_access_retries
+ ignore_column :circuitbreaker_check_interval
+ ignore_column :koding_url
+ ignore_column :koding_enabled
cache_markdown_field :sign_in_text
cache_markdown_field :help_page_text
@@ -37,6 +46,8 @@ class ApplicationSetting < ActiveRecord::Base
default_value_for :id, 1
+ chronic_duration_attr_writer :archive_builds_in_human_readable, :archive_builds_in_seconds
+
validates :uuid, presence: true
validates :session_expire_delay,
@@ -94,10 +105,6 @@ class ApplicationSetting < ActiveRecord::Base
presence: true,
if: :unique_ips_limit_enabled
- validates :koding_url,
- presence: true,
- if: :koding_enabled
-
validates :plantuml_url,
presence: true,
if: :plantuml_enabled
@@ -131,15 +138,6 @@ class ApplicationSetting < ActiveRecord::Base
presence: { message: 'Domain blacklist cannot be empty if Blacklist is enabled.' },
if: :domain_blacklist_enabled?
- validates :sidekiq_throttling_factor,
- numericality: { greater_than: 0, less_than: 1 },
- presence: { message: 'Throttling factor cannot be empty if Sidekiq Throttling is enabled.' },
- if: :sidekiq_throttling_enabled?
-
- validates :sidekiq_throttling_queues,
- presence: { message: 'Queues to throttle cannot be empty if Sidekiq Throttling is enabled.' },
- if: :sidekiq_throttling_enabled?
-
validates :housekeeping_incremental_repack_period,
presence: true,
numericality: { only_integer: true, greater_than: 0 }
@@ -160,17 +158,6 @@ class ApplicationSetting < ActiveRecord::Base
presence: true,
numericality: { greater_than_or_equal_to: 0 }
- validates :circuitbreaker_failure_count_threshold,
- :circuitbreaker_failure_reset_time,
- :circuitbreaker_storage_timeout,
- :circuitbreaker_check_interval,
- presence: true,
- numericality: { only_integer: true, greater_than_or_equal_to: 0 }
-
- validates :circuitbreaker_access_retries,
- presence: true,
- numericality: { only_integer: true, greater_than_or_equal_to: 1 }
-
validates :gitaly_timeout_default,
presence: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
@@ -192,8 +179,20 @@ class ApplicationSetting < ActiveRecord::Base
numericality: { less_than_or_equal_to: :gitaly_timeout_default },
if: :gitaly_timeout_default
+ validates :diff_max_patch_bytes,
+ presence: true,
+ numericality: { only_integer: true,
+ greater_than_or_equal_to: Gitlab::Git::Diff::DEFAULT_MAX_PATCH_BYTES,
+ less_than_or_equal_to: Gitlab::Git::Diff::MAX_PATCH_BYTES_UPPER_BOUND }
+
validates :user_default_internal_regex, js_regex: true, allow_nil: true
+ validates :commit_email_hostname, format: { with: /\A[^@]+\z/ }
+
+ validates :archive_builds_in_seconds,
+ allow_nil: true,
+ numericality: { only_integer: true, greater_than_or_equal_to: 1.day.seconds }
+
SUPPORTED_KEY_TYPES.each do |type|
validates :"#{type}_key_restriction", presence: true, key_restriction: { type: type }
end
@@ -260,8 +259,6 @@ class ApplicationSetting < ActiveRecord::Base
housekeeping_gc_period: 200,
housekeeping_incremental_repack_period: 10,
import_sources: Settings.gitlab['import_sources'],
- koding_enabled: false,
- koding_url: nil,
max_artifacts_size: Settings.artifacts['max_size'],
max_attachment_size: Settings.gitlab['max_attachment_size'],
mirror_available: true,
@@ -282,7 +279,6 @@ class ApplicationSetting < ActiveRecord::Base
send_user_confirmation_email: false,
shared_runners_enabled: Settings.gitlab_ci['shared_runners_enabled'],
shared_runners_text: nil,
- sidekiq_throttling_enabled: false,
sign_in_text: nil,
signup_enabled: Settings.gitlab['signup_enabled'],
terminal_max_session_time: 0,
@@ -304,10 +300,16 @@ class ApplicationSetting < ActiveRecord::Base
user_default_external: false,
user_default_internal_regex: nil,
user_show_add_ssh_key_message: true,
- usage_stats_set_by_user_id: nil
+ usage_stats_set_by_user_id: nil,
+ diff_max_patch_bytes: Gitlab::Git::Diff::DEFAULT_MAX_PATCH_BYTES,
+ commit_email_hostname: default_commit_email_hostname
}
end
+ def self.default_commit_email_hostname
+ "users.noreply.#{Gitlab.config.gitlab.host}"
+ end
+
def self.create_from_defaults
create(defaults)
end
@@ -328,10 +330,6 @@ class ApplicationSetting < ActiveRecord::Base
::Gitlab::Database.cached_column_exists?(:application_settings, :help_page_support_url)
end
- def sidekiq_throttling_column_exists?
- ::Gitlab::Database.cached_column_exists?(:application_settings, :sidekiq_throttling_enabled)
- end
-
def disabled_oauth_sign_in_sources=(sources)
sources = (sources || []).map(&:to_s) & Devise.omniauth_providers.map(&:to_s)
super(sources)
@@ -367,6 +365,10 @@ class ApplicationSetting < ActiveRecord::Base
Array(read_attribute(:repository_storages))
end
+ def commit_email_hostname
+ super.presence || self.class.default_commit_email_hostname
+ end
+
def default_project_visibility=(level)
super(Gitlab::VisibilityLevel.level_value(level))
end
@@ -411,12 +413,6 @@ class ApplicationSetting < ActiveRecord::Base
ensure_health_check_access_token!
end
- def sidekiq_throttling_enabled?
- return false unless sidekiq_throttling_column_exists?
-
- sidekiq_throttling_enabled
- end
-
def usage_ping_can_be_configured?
Settings.gitlab.usage_ping_enabled
end
@@ -463,6 +459,10 @@ class ApplicationSetting < ActiveRecord::Base
latest_terms
end
+ def archive_builds_older_than
+ archive_builds_in_seconds.seconds.ago if archive_builds_in_seconds
+ end
+
private
def ensure_uuid!
diff --git a/app/models/blob.rb b/app/models/blob.rb
index acc64ffca67..66a0925c495 100644
--- a/app/models/blob.rb
+++ b/app/models/blob.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
-# Blob is a Rails-specific wrapper around Gitlab::Git::Blob objects
+# Blob is a Rails-specific wrapper around Gitlab::Git::Blob, SnippetBlob and Ci::ArtifactBlob
class Blob < SimpleDelegator
+ include Presentable
+ include BlobLanguageFromGitAttributes
+
CACHE_TIME = 60 # Cache raw blobs referred to by a (mutable) ref for 1 minute
CACHE_TIME_IMMUTABLE = 3600 # Cache blobs referred to by an immutable reference for 1 hour
- MAXIMUM_TEXT_HIGHLIGHT_SIZE = 1.megabyte
-
# Finding a viewer for a blob happens based only on extension and whether the
# blob is binary or text, which means 1 blob should only be matched by 1 viewer,
# and the order of these viewers doesn't really matter.
@@ -79,15 +80,9 @@ class Blob < SimpleDelegator
end
def self.lazy(project, commit_id, path)
- BatchLoader.for({ project: project, commit_id: commit_id, path: path }).batch do |items, loader|
- items_by_project = items.group_by { |i| i[:project] }
-
- items_by_project.each do |project, items|
- items = items.map { |i| i.values_at(:commit_id, :path) }
-
- project.repository.blobs_at(items).each do |blob|
- loader.call({ project: blob.project, commit_id: blob.commit_id, path: blob.path }, blob) if blob
- end
+ BatchLoader.for([commit_id, path]).batch(key: project.repository) do |items, loader, args|
+ args[:key].blobs_at(items).each do |blob|
+ loader.call([blob.commit_id, blob.path], blob) if blob
end
end
end
@@ -121,10 +116,6 @@ class Blob < SimpleDelegator
end
end
- def no_highlighting?
- raw_size && raw_size > MAXIMUM_TEXT_HIGHLIGHT_SIZE
- end
-
def empty?
raw_size == 0
end
@@ -162,7 +153,7 @@ class Blob < SimpleDelegator
if stored_externally?
if rich_viewer
rich_viewer.binary?
- elsif Linguist::Language.find_by_extension(name).any?
+ elsif known_extension?
false
elsif _mime_type
_mime_type.binary?
diff --git a/app/models/blob_viewer/package_json.rb b/app/models/blob_viewer/package_json.rb
index d12dd93ce2e..7cae60a74d6 100644
--- a/app/models/blob_viewer/package_json.rb
+++ b/app/models/blob_viewer/package_json.rb
@@ -33,7 +33,8 @@ module BlobViewer
end
def homepage
- json_data['homepage']
+ url = json_data['homepage']
+ url if Gitlab::UrlSanitizer.valid?(url)
end
def npm_url
diff --git a/app/models/board_group_recent_visit.rb b/app/models/board_group_recent_visit.rb
new file mode 100644
index 00000000000..92abbb67222
--- /dev/null
+++ b/app/models/board_group_recent_visit.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+# Tracks which boards in a specific group a user has visited
+class BoardGroupRecentVisit < ActiveRecord::Base
+ belongs_to :user
+ belongs_to :group
+ belongs_to :board
+
+ validates :user, presence: true
+ validates :group, presence: true
+ validates :board, presence: true
+
+ scope :by_user_group, -> (user, group) { where(user: user, group: group).order(:updated_at) }
+
+ def self.visited!(user, board)
+ visit = find_or_create_by(user: user, group: board.group, board: board)
+ visit.touch if visit.updated_at < Time.now
+ rescue ActiveRecord::RecordNotUnique
+ retry
+ end
+
+ def self.latest(user, group)
+ by_user_group(user, group).last
+ end
+end
diff --git a/app/models/board_project_recent_visit.rb b/app/models/board_project_recent_visit.rb
new file mode 100644
index 00000000000..7cffff906d8
--- /dev/null
+++ b/app/models/board_project_recent_visit.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+# Tracks which boards in a specific project a user has visited
+class BoardProjectRecentVisit < ActiveRecord::Base
+ belongs_to :user
+ belongs_to :project
+ belongs_to :board
+
+ validates :user, presence: true
+ validates :project, presence: true
+ validates :board, presence: true
+
+ scope :by_user_project, -> (user, project) { where(user: user, project: project).order(:updated_at) }
+
+ def self.visited!(user, board)
+ visit = find_or_create_by(user: user, project: board.project, board: board)
+ visit.touch if visit.updated_at < Time.now
+ rescue ActiveRecord::RecordNotUnique
+ retry
+ end
+
+ def self.latest(user, project)
+ by_user_project(user, project).last
+ end
+end
diff --git a/app/models/ci/artifact_blob.rb b/app/models/ci/artifact_blob.rb
index cd0b31482d2..d87d6a5cb2f 100644
--- a/app/models/ci/artifact_blob.rb
+++ b/app/models/ci/artifact_blob.rb
@@ -4,7 +4,7 @@ module Ci
class ArtifactBlob
include BlobLike
- EXTENSIONS_SERVED_BY_PAGES = %w[.html .htm .txt .json].freeze
+ EXTENSIONS_SERVED_BY_PAGES = %w[.html .htm .txt .json .log].freeze
attr_reader :entry
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 63aaa0f7bcc..d60861dc95f 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -9,19 +9,18 @@ module Ci
include Presentable
include Importable
include Gitlab::Utils::StrongMemoize
+ include Deployable
belongs_to :project, inverse_of: :builds
belongs_to :runner
belongs_to :trigger_request
belongs_to :erased_by, class_name: 'User'
- has_many :deployments, as: :deployable
-
RUNNER_FEATURES = {
upload_multiple_artifacts: -> (build) { build.publishes_artifacts_reports? }
}.freeze
- has_one :last_deployment, -> { order('deployments.id DESC') }, as: :deployable, class_name: 'Deployment'
+ has_one :deployment, as: :deployable, class_name: 'Deployment'
has_many :trace_sections, class_name: 'Ci::BuildTraceSection'
has_many :trace_chunks, class_name: 'Ci::BuildTraceChunk', foreign_key: :build_id
@@ -68,8 +67,12 @@ module Ci
'', Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id').archive)
end
+ scope :with_existing_job_artifacts, ->(query) do
+ where('EXISTS (?)', ::Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id').merge(query))
+ end
+
scope :with_archived_trace, ->() do
- where('EXISTS (?)', Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id').trace)
+ with_existing_job_artifacts(Ci::JobArtifact.trace)
end
scope :without_archived_trace, ->() do
@@ -77,22 +80,25 @@ module Ci
end
scope :with_test_reports, ->() do
- includes(:job_artifacts_junit) # Prevent N+1 problem when iterating each ci_job_artifact row
- .where('EXISTS (?)', Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id').test_reports)
+ with_existing_job_artifacts(Ci::JobArtifact.test_reports)
+ .eager_load_job_artifacts
end
+ scope :eager_load_job_artifacts, -> { includes(:job_artifacts) }
+
scope :with_artifacts_stored_locally, -> { with_artifacts_archive.where(artifacts_file_store: [nil, LegacyArtifactUploader::Store::LOCAL]) }
scope :with_archived_trace_stored_locally, -> { with_archived_trace.where(artifacts_file_store: [nil, LegacyArtifactUploader::Store::LOCAL]) }
scope :with_artifacts_not_expired, ->() { with_artifacts_archive.where('artifacts_expire_at IS NULL OR artifacts_expire_at > ?', Time.now) }
scope :with_expired_artifacts, ->() { with_artifacts_archive.where('artifacts_expire_at < ?', Time.now) }
scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) }
- scope :manual_actions, ->() { where(when: :manual, status: COMPLETED_STATUSES + [:manual]) }
+ scope :manual_actions, ->() { where(when: :manual, status: COMPLETED_STATUSES + %i[manual]) }
+ scope :scheduled_actions, ->() { where(when: :delayed, status: COMPLETED_STATUSES + %i[scheduled]) }
scope :ref_protected, -> { where(protected: true) }
scope :with_live_trace, -> { where('EXISTS (?)', Ci::BuildTraceChunk.where('ci_builds.id = ci_build_trace_chunks.build_id').select(1)) }
scope :matches_tag_ids, -> (tag_ids) do
matcher = ::ActsAsTaggableOn::Tagging
- .where(taggable_type: CommitStatus)
+ .where(taggable_type: CommitStatus.name)
.where(context: 'tags')
.where('taggable_id = ci_builds.id')
.where.not(tag_id: tag_ids).select('1')
@@ -102,7 +108,7 @@ module Ci
scope :with_any_tags, -> do
matcher = ::ActsAsTaggableOn::Tagging
- .where(taggable_type: CommitStatus)
+ .where(taggable_type: CommitStatus.name)
.where(context: 'tags')
.where('taggable_id = ci_builds.id').select('1')
@@ -153,6 +159,34 @@ module Ci
transition created: :manual
end
+ event :schedule do
+ transition created: :scheduled
+ end
+
+ event :unschedule do
+ transition scheduled: :manual
+ end
+
+ event :enqueue_scheduled do
+ transition scheduled: :pending, if: ->(build) do
+ build.scheduled_at && build.scheduled_at < Time.now
+ end
+ end
+
+ before_transition scheduled: any do |build|
+ build.scheduled_at = nil
+ end
+
+ before_transition created: :scheduled do |build|
+ build.scheduled_at = build.options_scheduled_at
+ end
+
+ after_transition created: :scheduled do |build|
+ build.run_after_commit do
+ Ci::BuildScheduleWorker.perform_at(build.scheduled_at, build.id)
+ end
+ end
+
after_transition any => [:pending] do |build|
build.run_after_commit do
BuildQueueWorker.perform_async(id)
@@ -160,6 +194,8 @@ module Ci
end
after_transition pending: :running do |build|
+ build.deployment&.run
+
build.run_after_commit do
BuildHooksWorker.perform_async(id)
end
@@ -172,6 +208,8 @@ module Ci
end
after_transition any => [:success] do |build|
+ build.deployment&.succeed
+
build.run_after_commit do
BuildSuccessWorker.perform_async(id)
PagesWorker.perform_async(:deploy, id) if build.pages_generator?
@@ -180,9 +218,10 @@ module Ci
before_transition any => [:failed] do |build|
next unless build.project
- next if build.retries_max.zero?
- if build.retries_count < build.retries_max
+ build.deployment&.drop
+
+ if build.retry_failure?
begin
Ci::Build.retry(build, build.user)
rescue Gitlab::Access::AccessDeniedError => ex
@@ -198,6 +237,10 @@ module Ci
after_transition running: any do |build|
Ci::BuildRunnerSession.where(build: build).delete_all
end
+
+ after_transition any => [:skipped, :canceled] do |build|
+ build.deployment&.cancel
+ end
end
def ensure_metadata
@@ -210,21 +253,49 @@ module Ci
.fabricate!
end
- def other_actions
+ def other_manual_actions
pipeline.manual_actions.where.not(name: name)
end
+ def other_scheduled_actions
+ pipeline.scheduled_actions.where.not(name: name)
+ end
+
def pages_generator?
Gitlab.config.pages.enabled &&
self.name == 'pages'
end
+ # degenerated build is one that cannot be run by Runner
+ def degenerated?
+ self.options.nil?
+ end
+
+ def degenerate!
+ self.update!(options: nil, yaml_variables: nil, commands: nil)
+ end
+
+ def archived?
+ return true if degenerated?
+
+ archive_builds_older_than = Gitlab::CurrentSettings.current_application_settings.archive_builds_older_than
+ archive_builds_older_than.present? && created_at < archive_builds_older_than
+ end
+
def playable?
- action? && (manual? || retryable?)
+ action? && !archived? && (manual? || scheduled? || retryable?)
+ end
+
+ def schedulable?
+ self.when == 'delayed' && options[:start_in].present?
+ end
+
+ def options_scheduled_at
+ ChronicDuration.parse(options[:start_in])&.seconds&.from_now
end
def action?
- self.when == 'manual'
+ %w[manual delayed].include?(self.when)
end
# rubocop: disable CodeReuse/ServiceClass
@@ -240,7 +311,7 @@ module Ci
end
def retryable?
- success? || failed? || canceled?
+ !archived? && (success? || failed? || canceled?)
end
def retries_count
@@ -248,7 +319,17 @@ module Ci
end
def retries_max
- self.options.fetch(:retry, 0).to_i
+ normalized_retry.fetch(:max, 0)
+ end
+
+ def retry_when
+ normalized_retry.fetch(:when, ['always'])
+ end
+
+ def retry_failure?
+ return false if retries_max.zero? || retries_count >= retries_max
+
+ retry_when.include?('always') || retry_when.include?(failure_reason.to_s)
end
def latest?
@@ -279,8 +360,12 @@ module Ci
self.options.fetch(:environment, {}).fetch(:action, 'start') if self.options
end
+ def has_deployment?
+ !!self.deployment
+ end
+
def outdated_deployment?
- success? && !last_deployment.try(:last?)
+ success? && !deployment.try(:last?)
end
def depends_on_builds
@@ -295,6 +380,10 @@ module Ci
user == current_user
end
+ def on_stop
+ options&.dig(:environment, :on_stop)
+ end
+
# A slugified version of the build ref, suitable for inclusion in URLs and
# domain names. Rules:
#
@@ -375,7 +464,9 @@ module Ci
end
def repo_url
- auth = "gitlab-ci-token:#{ensure_token!}@"
+ return unless token
+
+ auth = "gitlab-ci-token:#{token}@"
project.http_url_to_repo.sub(%r{^https?://}) do |prefix|
prefix + auth
end
@@ -404,8 +495,8 @@ module Ci
trace.exist?
end
- def has_test_reports?
- job_artifacts.test_reports.any?
+ def has_job_artifacts?
+ job_artifacts.any?
end
def has_old_trace?
@@ -469,28 +560,23 @@ module Ci
end
end
- def erase_artifacts!
- remove_artifacts_file!
- remove_artifacts_metadata!
- save
- end
-
- def erase_test_reports!
- # TODO: Use fast_destroy_all in the context of https://gitlab.com/gitlab-org/gitlab-ce/issues/35240
- job_artifacts_junit&.destroy
+ # and use that for `ExpireBuildInstanceArtifactsWorker`?
+ def erase_erasable_artifacts!
+ job_artifacts.erasable.destroy_all # rubocop: disable DestroyAll
+ erase_old_artifacts!
end
def erase(opts = {})
return false unless erasable?
- erase_artifacts!
- erase_test_reports!
+ job_artifacts.destroy_all # rubocop: disable DestroyAll
+ erase_old_artifacts!
erase_trace!
update_erased!(opts[:erased_by])
end
def erasable?
- complete? && (artifacts? || has_test_reports? || has_trace?)
+ complete? && (artifacts? || has_job_artifacts? || has_trace?)
end
def erased?
@@ -521,6 +607,13 @@ module Ci
self.job_artifacts.update_all(expire_at: nil)
end
+ def artifacts_file_for_type(type)
+ file = job_artifacts.find_by(file_type: Ci::JobArtifact.file_types[type])&.file
+ # TODO: to be removed once legacy artifacts is removed
+ file ||= legacy_artifacts_file if type == :archive
+ file
+ end
+
def coverage_regex
super || project.try(:build_coverage_regex)
end
@@ -547,11 +640,11 @@ module Ci
def secret_group_variables
return [] unless project.group
- project.group.secret_variables_for(ref, project)
+ project.group.ci_variables_for(ref, project)
end
def secret_project_variables(environment: persisted_environment)
- project.secret_variables_for(ref: ref, environment: environment)
+ project.ci_variables_for(ref: ref, environment: environment)
end
def steps
@@ -634,7 +727,7 @@ module Ci
trace = trace.dup
Gitlab::Ci::MaskSecret.mask!(trace, project.runners_token) if project
- Gitlab::Ci::MaskSecret.mask!(trace, token)
+ Gitlab::Ci::MaskSecret.mask!(trace, token) if token
trace
end
@@ -648,8 +741,8 @@ module Ci
def collect_test_reports!(test_reports)
test_reports.get_suite(group_name).tap do |test_suite|
- each_test_report do |file_type, blob|
- Gitlab::Ci::Parsers.fabricate!(file_type).parse!(blob, test_suite)
+ each_report(Ci::JobArtifact::TEST_REPORT_FILE_TYPES) do |file_type, blob|
+ Gitlab::Ci::Parsers::Test.fabricate!(file_type).parse!(blob, test_suite)
end
end
end
@@ -660,7 +753,7 @@ module Ci
if success?
return successful_deployment_status
- elsif complete? && !success?
+ elsif failed?
return :failed
end
@@ -669,24 +762,34 @@ module Ci
private
+ def erase_old_artifacts!
+ # TODO: To be removed once we get rid of
+ remove_artifacts_file!
+ remove_artifacts_metadata!
+ save
+ end
+
def successful_deployment_status
- if success? && last_deployment&.last?
- return :last
- elsif success? && last_deployment.present?
- return :out_of_date
+ if deployment&.last?
+ :last
+ else
+ :out_of_date
end
-
- :creating
end
- def each_test_report
- Ci::JobArtifact::TEST_REPORT_FILE_TYPES.each do |file_type|
- public_send("job_artifacts_#{file_type}").each_blob do |blob| # rubocop:disable GitlabSecurity/PublicSend
- yield file_type, blob
+ def each_report(report_types)
+ job_artifacts_for_types(report_types).each do |report_artifact|
+ report_artifact.each_blob do |blob|
+ yield report_artifact.file_type, blob
end
end
end
+ def job_artifacts_for_types(report_types)
+ # Use select to leverage cached associations and avoid N+1 queries
+ job_artifacts.select { |artifact| artifact.file_type.in?(report_types) }
+ end
+
def update_artifacts_size
self.artifacts_size = legacy_artifacts_file&.size
end
@@ -713,23 +816,26 @@ module Ci
.concat(pipeline.persisted_variables)
.append(key: 'CI_JOB_ID', value: id.to_s)
.append(key: 'CI_JOB_URL', value: Gitlab::Routing.url_helpers.project_job_url(project, self))
- .append(key: 'CI_JOB_TOKEN', value: token, public: false)
+ .append(key: 'CI_JOB_TOKEN', value: token.to_s, public: false)
.append(key: 'CI_BUILD_ID', value: id.to_s)
- .append(key: 'CI_BUILD_TOKEN', value: token, public: false)
+ .append(key: 'CI_BUILD_TOKEN', value: token.to_s, public: false)
.append(key: 'CI_REGISTRY_USER', value: CI_REGISTRY_USER)
- .append(key: 'CI_REGISTRY_PASSWORD', value: token, public: false)
- .append(key: 'CI_REPOSITORY_URL', value: repo_url, public: false)
+ .append(key: 'CI_REGISTRY_PASSWORD', value: token.to_s, public: false)
+ .append(key: 'CI_REPOSITORY_URL', value: repo_url.to_s, public: false)
.concat(deploy_token_variables)
end
end
- def predefined_variables
+ def predefined_variables # rubocop:disable Metrics/AbcSize
Gitlab::Ci::Variables::Collection.new.tap do |variables|
variables.append(key: 'CI', value: 'true')
variables.append(key: 'GITLAB_CI', value: 'true')
variables.append(key: 'GITLAB_FEATURES', value: project.licensed_features.join(','))
variables.append(key: 'CI_SERVER_NAME', value: 'GitLab')
variables.append(key: 'CI_SERVER_VERSION', value: Gitlab::VERSION)
+ variables.append(key: 'CI_SERVER_VERSION_MAJOR', value: Gitlab.version_info.major.to_s)
+ variables.append(key: 'CI_SERVER_VERSION_MINOR', value: Gitlab.version_info.minor.to_s)
+ variables.append(key: 'CI_SERVER_VERSION_PATCH', value: Gitlab.version_info.patch.to_s)
variables.append(key: 'CI_SERVER_REVISION', value: Gitlab.revision)
variables.append(key: 'CI_JOB_NAME', value: name)
variables.append(key: 'CI_JOB_STAGE', value: stage)
@@ -740,6 +846,8 @@ module Ci
variables.append(key: "CI_COMMIT_TAG", value: ref) if tag?
variables.append(key: "CI_PIPELINE_TRIGGERED", value: 'true') if trigger_request
variables.append(key: "CI_JOB_MANUAL", value: 'true') if action?
+ variables.append(key: "CI_NODE_INDEX", value: self.options[:instance].to_s) if self.options&.include?(:instance)
+ variables.append(key: "CI_NODE_TOTAL", value: (self.options&.dig(:parallel) || 1).to_s)
variables.concat(legacy_variables)
end
end
@@ -784,6 +892,16 @@ module Ci
options&.dig(:environment, :url) || persisted_environment&.external_url
end
+ # The format of the retry option changed in GitLab 11.5: Before it was
+ # integer only, after it is a hash. New builds are created with the new
+ # format, but builds created before GitLab 11.5 and saved in database still
+ # have the old integer only format. This method returns the retry option
+ # normalized as a hash in 11.5+ format.
+ def normalized_retry
+ value = options&.dig(:retry)
+ value.is_a?(Integer) ? { max: value } : value.to_h
+ end
+
def build_attributes_from_config
return {} unless pipeline.config_processor
diff --git a/app/models/ci/build_trace_chunk.rb b/app/models/ci/build_trace_chunk.rb
index 108874b75a6..da08214963f 100644
--- a/app/models/ci/build_trace_chunk.rb
+++ b/app/models/ci/build_trace_chunk.rb
@@ -15,6 +15,8 @@ module Ci
WRITE_LOCK_SLEEP = 0.01.seconds
WRITE_LOCK_TTL = 1.minute
+ FailedToPersistDataError = Class.new(StandardError)
+
# Note: The ordering of this enum is related to the precedence of persist store.
# The bottom item takes the higest precedence, and the top item takes the lowest precedence.
enum data_store: {
@@ -76,7 +78,7 @@ module Ci
raise ArgumentError, 'Offset is out of range' if offset > size || offset < 0
raise ArgumentError, 'Chunk size overflow' if CHUNK_SIZE < (offset + new_data.bytesize)
- in_lock(*lock_params) do # Write opetation is atomic
+ in_lock(*lock_params) do # Write operation is atomic
unsafe_set_data!(data.byteslice(0, offset) + new_data)
end
@@ -100,7 +102,7 @@ module Ci
end
def persist_data!
- in_lock(*lock_params) do # Write opetation is atomic
+ in_lock(*lock_params) do # Write operation is atomic
unsafe_persist_to!(self.class.persistable_store)
end
end
@@ -109,16 +111,19 @@ module Ci
def unsafe_persist_to!(new_store)
return if data_store == new_store.to_s
- raise ArgumentError, 'Can not persist empty data' unless size > 0
- old_store_class = self.class.get_store_class(data_store)
+ current_data = get_data
- get_data.tap do |the_data|
- self.raw_data = nil
- self.data_store = new_store
- unsafe_set_data!(the_data)
+ unless current_data&.bytesize.to_i == CHUNK_SIZE
+ raise FailedToPersistDataError, 'Data is not fullfilled in a bucket'
end
+ old_store_class = self.class.get_store_class(data_store)
+
+ self.raw_data = nil
+ self.data_store = new_store
+ unsafe_set_data!(current_data)
+
old_store_class.delete_data(self)
end
diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb
index 93fc1b145b2..11c88200c37 100644
--- a/app/models/ci/job_artifact.rb
+++ b/app/models/ci/job_artifact.rb
@@ -9,8 +9,38 @@ module Ci
NotSupportedAdapterError = Class.new(StandardError)
TEST_REPORT_FILE_TYPES = %w[junit].freeze
- DEFAULT_FILE_NAMES = { junit: 'junit.xml' }.freeze
- TYPE_AND_FORMAT_PAIRS = { archive: :zip, metadata: :gzip, trace: :raw, junit: :gzip }.freeze
+ NON_ERASABLE_FILE_TYPES = %w[trace].freeze
+ DEFAULT_FILE_NAMES = {
+ archive: nil,
+ metadata: nil,
+ trace: nil,
+ junit: 'junit.xml',
+ codequality: 'gl-code-quality-report.json',
+ sast: 'gl-sast-report.json',
+ dependency_scanning: 'gl-dependency-scanning-report.json',
+ container_scanning: 'gl-container-scanning-report.json',
+ dast: 'gl-dast-report.json',
+ license_management: 'gl-license-management-report.json',
+ performance: 'performance.json'
+ }.freeze
+
+ TYPE_AND_FORMAT_PAIRS = {
+ archive: :zip,
+ metadata: :gzip,
+ trace: :raw,
+ junit: :gzip,
+
+ # All these file formats use `raw` as we need to store them uncompressed
+ # for Frontend to fetch the files and do analysis
+ # When they will be only used by backend, they can be `gzipped`.
+ codequality: :raw,
+ sast: :raw,
+ dependency_scanning: :raw,
+ container_scanning: :raw,
+ dast: :raw,
+ license_management: :raw,
+ performance: :raw
+ }.freeze
belongs_to :project
belongs_to :job, class_name: "Ci::Build", foreign_key: :job_id
@@ -27,8 +57,18 @@ module Ci
scope :with_files_stored_locally, -> { where(file_store: [nil, ::JobArtifactUploader::Store::LOCAL]) }
+ scope :with_file_types, -> (file_types) do
+ types = self.file_types.select { |file_type| file_types.include?(file_type) }.values
+
+ where(file_type: types)
+ end
+
scope :test_reports, -> do
- types = self.file_types.select { |file_type| TEST_REPORT_FILE_TYPES.include?(file_type) }.values
+ with_file_types(TEST_REPORT_FILE_TYPES)
+ end
+
+ scope :erasable, -> do
+ types = self.file_types.reject { |file_type| NON_ERASABLE_FILE_TYPES.include?(file_type) }.values
where(file_type: types)
end
@@ -39,7 +79,14 @@ module Ci
archive: 1,
metadata: 2,
trace: 3,
- junit: 4
+ junit: 4,
+ sast: 5, ## EE-specific
+ dependency_scanning: 6, ## EE-specific
+ container_scanning: 7, ## EE-specific
+ dast: 8, ## EE-specific
+ codequality: 9, ## EE-specific
+ license_management: 10, ## EE-specific
+ performance: 11 ## EE-specific
}
enum file_format: {
@@ -63,7 +110,8 @@ module Ci
}
FILE_FORMAT_ADAPTERS = {
- gzip: Gitlab::Ci::Build::Artifacts::GzipFileAdapter
+ gzip: Gitlab::Ci::Build::Artifacts::Adapters::GzipStream,
+ raw: Gitlab::Ci::Build::Artifacts::Adapters::RawStream
}.freeze
def valid_file_format?
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 6dac577c514..1487b9d3bca 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -26,6 +26,8 @@ module Ci
has_many :builds, foreign_key: :commit_id, inverse_of: :pipeline
has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id # rubocop:disable Cop/ActiveRecordDependent
has_many :variables, class_name: 'Ci::PipelineVariable'
+ has_many :deployments, through: :builds
+ has_many :environments, -> { distinct }, through: :deployments
# Merge requests for which the current pipeline is running against
# the merge request's latest commit.
@@ -35,6 +37,7 @@ module Ci
has_many :retryable_builds, -> { latest.failed_or_canceled.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build'
has_many :cancelable_statuses, -> { cancelable }, foreign_key: :commit_id, class_name: 'CommitStatus'
has_many :manual_actions, -> { latest.manual_actions.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build'
+ has_many :scheduled_actions, -> { latest.scheduled_actions.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build'
has_many :artifacts, -> { latest.with_artifacts_not_expired.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build'
has_many :auto_canceled_pipelines, class_name: 'Ci::Pipeline', foreign_key: 'auto_canceled_by_id'
@@ -57,15 +60,9 @@ module Ci
after_create :keep_around_commits, unless: :importing?
- enum_with_nil source: {
- unknown: nil,
- push: 1,
- web: 2,
- trigger: 3,
- schedule: 4,
- api: 5,
- external: 6
- }
+ # We use `Ci::PipelineEnums.sources` here so that EE can more easily extend
+ # this `Hash` with new values.
+ enum_with_nil source: ::Ci::PipelineEnums.sources
enum_with_nil config_source: {
unknown_source: nil,
@@ -73,14 +70,13 @@ module Ci
auto_devops_source: 2
}
- enum failure_reason: {
- unknown_failure: 0,
- config_error: 1
- }
+ # We use `Ci::PipelineEnums.failure_reasons` here so that EE can more easily
+ # extend this `Hash` with new values.
+ enum failure_reason: ::Ci::PipelineEnums.failure_reasons
state_machine :status, initial: :created do
event :enqueue do
- transition [:created, :skipped] => :pending
+ transition [:created, :skipped, :scheduled] => :pending
transition [:success, :failed, :canceled] => :running
end
@@ -108,6 +104,10 @@ module Ci
transition any - [:manual] => :manual
end
+ event :delay do
+ transition any - [:scheduled] => :scheduled
+ end
+
# IMPORTANT
# Do not add any operations to this state_machine
# Create a separate worker for each new operation
@@ -176,22 +176,31 @@ module Ci
#
# ref - The name (or names) of the branch(es)/tag(s) to limit the list of
# pipelines to.
- def self.newest_first(ref = nil)
+ # limit - This limits a backlog search, default to 100.
+ def self.newest_first(ref: nil, limit: 100)
relation = order(id: :desc)
+ relation = relation.where(ref: ref) if ref
+
+ if limit
+ ids = relation.limit(limit).select(:id)
+ # MySQL does not support limit in subquery
+ ids = ids.pluck(:id) if Gitlab::Database.mysql?
+ relation = relation.where(id: ids)
+ end
- ref ? relation.where(ref: ref) : relation
+ relation
end
def self.latest_status(ref = nil)
- newest_first(ref).pluck(:status).first
+ newest_first(ref: ref).pluck(:status).first
end
def self.latest_successful_for(ref)
- newest_first(ref).success.take
+ newest_first(ref: ref).success.take
end
def self.latest_successful_for_refs(refs)
- relation = newest_first(refs).success
+ relation = newest_first(ref: refs).success
relation.each_with_object({}) do |pipeline, hash|
hash[pipeline.ref] ||= pipeline
@@ -233,6 +242,10 @@ module Ci
end
end
+ def self.latest_successful_ids_per_project
+ success.group(:project_id).select('max(id) as id')
+ end
+
def self.truncate_sha(sha)
sha[0...8]
end
@@ -263,6 +276,12 @@ module Ci
stage unless stage.statuses_count.zero?
end
+ def ref_exists?
+ project.repository.ref_exists?(git_ref)
+ rescue Gitlab::Git::Repository::NoRepository
+ false
+ end
+
##
# TODO We do not completely switch to persisted stages because of
# race conditions with setting statuses gitlab-ce#23257.
@@ -506,10 +525,6 @@ module Ci
yaml_errors.present?
end
- def environments
- builds.where.not(environment: nil).success.pluck(:environment).uniq
- end
-
# Manually set the notes for a Ci::Pipeline
# There is no ActiveRecord relation between Ci::Pipeline and notes
# as they are related to a commit sha. This method helps importing
@@ -544,6 +559,7 @@ module Ci
when 'canceled' then cancel
when 'skipped' then skip
when 'manual' then block
+ when 'scheduled' then delay
else
raise HasStatus::UnknownStatusError,
"Unknown status `#{latest_builds_status}`"
@@ -627,6 +643,22 @@ module Ci
end
end
+ def branch_updated?
+ strong_memoize(:branch_updated) do
+ push_details.branch_updated?
+ end
+ end
+
+ def modified_paths
+ strong_memoize(:modified_paths) do
+ push_details.modified_paths
+ end
+ end
+
+ def default_branch?
+ ref == project.default_branch
+ end
+
private
def ci_yaml_from_repo
@@ -650,6 +682,22 @@ module Ci
Gitlab::DataBuilder::Pipeline.build(self)
end
+ def push_details
+ strong_memoize(:push_details) do
+ Gitlab::Git::Push.new(project, before_sha, sha, git_ref)
+ end
+ end
+
+ def git_ref
+ if branch?
+ Gitlab::Git::BRANCH_REF_PREFIX + ref.to_s
+ elsif tag?
+ Gitlab::Git::TAG_REF_PREFIX + ref.to_s
+ else
+ raise ArgumentError, 'Invalid pipeline type!'
+ end
+ end
+
def latest_builds_status
return 'failed' unless yaml_errors.blank?
diff --git a/app/models/ci/pipeline_enums.rb b/app/models/ci/pipeline_enums.rb
new file mode 100644
index 00000000000..8d8d16e2ec1
--- /dev/null
+++ b/app/models/ci/pipeline_enums.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Ci
+ module PipelineEnums
+ # Returns the `Hash` to use for creating the `failure_reason` enum for
+ # `Ci::Pipeline`.
+ def self.failure_reasons
+ {
+ unknown_failure: 0,
+ config_error: 1
+ }
+ end
+
+ # Returns the `Hash` to use for creating the `sources` enum for
+ # `Ci::Pipeline`.
+ def self.sources
+ {
+ unknown: nil,
+ push: 1,
+ web: 2,
+ trigger: 3,
+ schedule: 4,
+ api: 5,
+ external: 6
+ }
+ end
+ end
+end
diff --git a/app/models/ci/pipeline_variable.rb b/app/models/ci/pipeline_variable.rb
index 017ec0b145a..08514d6af4e 100644
--- a/app/models/ci/pipeline_variable.rb
+++ b/app/models/ci/pipeline_variable.rb
@@ -10,5 +10,9 @@ module Ci
alias_attribute :secret_value, :value
validates :key, uniqueness: { scope: :pipeline_id }
+
+ def hook_attrs
+ { key: key, value: value }
+ end
end
end
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 3e815937f4b..31330d0682e 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -9,12 +9,24 @@ module Ci
include ChronicDurationAttribute
include FromUnion
+ enum access_level: {
+ not_protected: 0,
+ ref_protected: 1
+ }
+
+ enum runner_type: {
+ instance_type: 1,
+ group_type: 2,
+ project_type: 3
+ }
+
RUNNER_QUEUE_EXPIRY_TIME = 60.minutes
ONLINE_CONTACT_TIMEOUT = 1.hour
UPDATE_DB_RUNNER_INFO_EVERY = 40.minutes
- AVAILABLE_TYPES = %w[specific shared].freeze
+ AVAILABLE_TYPES_LEGACY = %w[specific shared].freeze
+ AVAILABLE_TYPES = runner_types.keys.freeze
AVAILABLE_STATUSES = %w[active paused online offline].freeze
- AVAILABLE_SCOPES = (AVAILABLE_TYPES + AVAILABLE_STATUSES).freeze
+ AVAILABLE_SCOPES = (AVAILABLE_TYPES_LEGACY + AVAILABLE_TYPES + AVAILABLE_STATUSES).freeze
FORM_EDITABLE = %i[description tag_list active run_untagged locked access_level maximum_timeout_human_readable].freeze
ignore_column :is_shared
@@ -97,17 +109,6 @@ module Ci
after_destroy :cleanup_runner_queue
- enum access_level: {
- not_protected: 0,
- ref_protected: 1
- }
-
- enum runner_type: {
- instance_type: 1,
- group_type: 2,
- project_type: 3
- }
-
cached_attr_reader :version, :revision, :platform, :architecture, :ip_address, :contacted_at
chronic_duration_attr :maximum_timeout_human_readable, :maximum_timeout
diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb
index 511ded55dc3..58f3fe2460a 100644
--- a/app/models/ci/stage.rb
+++ b/app/models/ci/stage.rb
@@ -65,6 +65,10 @@ module Ci
event :block do
transition any - [:manual] => :manual
end
+
+ event :delay do
+ transition any - [:scheduled] => :scheduled
+ end
end
def update_status
@@ -77,6 +81,7 @@ module Ci
when 'failed' then drop
when 'canceled' then cancel
when 'manual' then block
+ when 'scheduled' then delay
when 'skipped', nil then skip
else
raise HasStatus::UnknownStatusError,
diff --git a/app/models/clusters/applications/cert_manager.rb b/app/models/clusters/applications/cert_manager.rb
new file mode 100644
index 00000000000..077e2bda143
--- /dev/null
+++ b/app/models/clusters/applications/cert_manager.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Applications
+ class CertManager < ActiveRecord::Base
+ VERSION = 'v0.5.0'.freeze
+
+ self.table_name = 'clusters_applications_cert_managers'
+
+ include ::Clusters::Concerns::ApplicationCore
+ include ::Clusters::Concerns::ApplicationStatus
+ include ::Clusters::Concerns::ApplicationVersion
+ include ::Clusters::Concerns::ApplicationData
+
+ default_value_for :version, VERSION
+
+ validates :email, presence: true
+
+ def chart
+ 'stable/cert-manager'
+ end
+
+ def install_command
+ Gitlab::Kubernetes::Helm::InstallCommand.new(
+ name: 'certmanager',
+ version: VERSION,
+ rbac: cluster.platform_kubernetes_rbac?,
+ chart: chart,
+ files: files.merge(cluster_issuer_file),
+ postinstall: post_install_script
+ )
+ end
+
+ private
+
+ def post_install_script
+ ["/usr/bin/kubectl create -f /data/helm/certmanager/config/cluster_issuer.yaml"]
+ end
+
+ def cluster_issuer_file
+ {
+ 'cluster_issuer.yaml': cluster_issuer_yaml_content
+ }
+ end
+
+ def cluster_issuer_yaml_content
+ YAML.dump(cluster_issuer_content.deep_merge(cluster_issue_overlay))
+ end
+
+ def cluster_issuer_content
+ YAML.safe_load(File.read(cluster_issuer_file_path))
+ end
+
+ def cluster_issue_overlay
+ { "spec" => { "acme" => { "email" => self.email } } }
+ end
+
+ def cluster_issuer_file_path
+ Rails.root.join('vendor', 'cert_manager', 'cluster_issuer.yaml')
+ end
+ end
+ end
+end
diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb
index bd0286ee3f9..8f8790585a3 100644
--- a/app/models/clusters/applications/ingress.rb
+++ b/app/models/clusters/applications/ingress.rb
@@ -51,6 +51,10 @@ module Clusters
ClusterWaitForIngressIpAddressWorker.perform_async(name, id)
end
+
+ def ingress_service
+ cluster.kubeclient.get_service('ingress-nginx-ingress-controller', Gitlab::Kubernetes::Helm::NAMESPACE)
+ end
end
end
end
diff --git a/app/models/clusters/applications/jupyter.rb b/app/models/clusters/applications/jupyter.rb
index 3d84eeed5a8..421a923d386 100644
--- a/app/models/clusters/applications/jupyter.rb
+++ b/app/models/clusters/applications/jupyter.rb
@@ -19,7 +19,7 @@ module Clusters
def set_initial_status
return unless not_installable?
- if cluster&.application_ingress_installed? && cluster.application_ingress.external_ip
+ if cluster&.application_ingress_available? && cluster.application_ingress.external_ip
self.status = 'installable'
end
end
@@ -56,7 +56,11 @@ module Clusters
def specification
{
"ingress" => {
- "hosts" => [hostname]
+ "hosts" => [hostname],
+ "tls" => [{
+ "hosts" => [hostname],
+ "secretName" => "jupyter-cert"
+ }]
},
"hub" => {
"extraEnv" => {
@@ -73,6 +77,11 @@ module Clusters
"clientSecret" => oauth_application.secret,
"callbackUrl" => callback_url
}
+ },
+ "singleuser" => {
+ "extraEnv" => {
+ "GITLAB_CLUSTER_ID" => cluster.id
+ }
}
}
end
diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb
new file mode 100644
index 00000000000..c0aaa8dce20
--- /dev/null
+++ b/app/models/clusters/applications/knative.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Applications
+ class Knative < ActiveRecord::Base
+ VERSION = '0.1.3'.freeze
+ REPOSITORY = 'https://storage.googleapis.com/triggermesh-charts'.freeze
+
+ FETCH_IP_ADDRESS_DELAY = 30.seconds
+
+ self.table_name = 'clusters_applications_knative'
+
+ include ::Clusters::Concerns::ApplicationCore
+ include ::Clusters::Concerns::ApplicationStatus
+ include ::Clusters::Concerns::ApplicationVersion
+ include ::Clusters::Concerns::ApplicationData
+ include AfterCommitQueue
+
+ state_machine :status do
+ before_transition any => [:installed] do |application|
+ application.run_after_commit do
+ ClusterWaitForIngressIpAddressWorker.perform_in(
+ FETCH_IP_ADDRESS_DELAY, application.name, application.id)
+ end
+ end
+ end
+
+ default_value_for :version, VERSION
+
+ validates :hostname, presence: true, hostname: true
+
+ def chart
+ 'knative/knative'
+ end
+
+ def values
+ { "domain" => hostname }.to_yaml
+ end
+
+ def install_command
+ Gitlab::Kubernetes::Helm::InstallCommand.new(
+ name: name,
+ version: VERSION,
+ rbac: cluster.platform_kubernetes_rbac?,
+ chart: chart,
+ files: files,
+ repository: REPOSITORY
+ )
+ end
+
+ def schedule_status_update
+ return unless installed?
+ return if external_ip
+
+ ClusterWaitForIngressIpAddressWorker.perform_async(name, id)
+ end
+
+ def ingress_service
+ cluster.kubeclient.get_service('knative-ingressgateway', 'istio-system')
+ end
+
+ def client
+ cluster.platform_kubernetes.kubeclient.knative_client
+ end
+ end
+ end
+end
diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb
index a4a2e2b79a6..67746e34913 100644
--- a/app/models/clusters/applications/runner.rb
+++ b/app/models/clusters/applications/runner.rb
@@ -3,7 +3,7 @@
module Clusters
module Applications
class Runner < ActiveRecord::Base
- VERSION = '0.1.31'.freeze
+ VERSION = '0.1.38'.freeze
self.table_name = 'clusters_applications_runners'
diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb
index d7011ef447a..13906c903b9 100644
--- a/app/models/clusters/cluster.rb
+++ b/app/models/clusters/cluster.rb
@@ -3,15 +3,18 @@
module Clusters
class Cluster < ActiveRecord::Base
include Presentable
+ include Gitlab::Utils::StrongMemoize
self.table_name = 'clusters'
APPLICATIONS = {
Applications::Helm.application_name => Applications::Helm,
Applications::Ingress.application_name => Applications::Ingress,
+ Applications::CertManager.application_name => Applications::CertManager,
Applications::Prometheus.application_name => Applications::Prometheus,
Applications::Runner.application_name => Applications::Runner,
- Applications::Jupyter.application_name => Applications::Jupyter
+ Applications::Jupyter.application_name => Applications::Jupyter,
+ Applications::Knative.application_name => Applications::Knative
}.freeze
DEFAULT_ENVIRONMENT = '*'.freeze
@@ -19,32 +22,52 @@ module Clusters
has_many :cluster_projects, class_name: 'Clusters::Project'
has_many :projects, through: :cluster_projects, class_name: '::Project'
+ has_one :cluster_project, -> { order(id: :desc) }, class_name: 'Clusters::Project'
+
+ has_many :cluster_groups, class_name: 'Clusters::Group'
+ has_many :groups, through: :cluster_groups, class_name: '::Group'
# we force autosave to happen when we save `Cluster` model
has_one :provider_gcp, class_name: 'Clusters::Providers::Gcp', autosave: true
- has_one :platform_kubernetes, class_name: 'Clusters::Platforms::Kubernetes', autosave: true
+ has_one :platform_kubernetes, class_name: 'Clusters::Platforms::Kubernetes', inverse_of: :cluster, autosave: true
has_one :application_helm, class_name: 'Clusters::Applications::Helm'
has_one :application_ingress, class_name: 'Clusters::Applications::Ingress'
+ has_one :application_cert_manager, class_name: 'Clusters::Applications::CertManager'
has_one :application_prometheus, class_name: 'Clusters::Applications::Prometheus'
has_one :application_runner, class_name: 'Clusters::Applications::Runner'
has_one :application_jupyter, class_name: 'Clusters::Applications::Jupyter'
+ has_one :application_knative, class_name: 'Clusters::Applications::Knative'
+
+ has_many :kubernetes_namespaces
+ has_one :kubernetes_namespace, -> { order(id: :desc) }, class_name: 'Clusters::KubernetesNamespace'
accepts_nested_attributes_for :provider_gcp, update_only: true
accepts_nested_attributes_for :platform_kubernetes, update_only: true
validates :name, cluster_name: true
+ validates :cluster_type, presence: true
validate :restrict_modification, on: :update
+ validate :no_groups, unless: :group_type?
+ validate :no_projects, unless: :project_type?
+
delegate :status, to: :provider, allow_nil: true
delegate :status_reason, to: :provider, allow_nil: true
delegate :on_creation?, to: :provider, allow_nil: true
delegate :active?, to: :platform_kubernetes, prefix: true, allow_nil: true
delegate :rbac?, to: :platform_kubernetes, prefix: true, allow_nil: true
- delegate :installed?, to: :application_helm, prefix: true, allow_nil: true
- delegate :installed?, to: :application_ingress, prefix: true, allow_nil: true
+ delegate :available?, to: :application_helm, prefix: true, allow_nil: true
+ delegate :available?, to: :application_ingress, prefix: true, allow_nil: true
+ delegate :available?, to: :application_prometheus, prefix: true, allow_nil: true
+
+ enum cluster_type: {
+ instance_type: 1,
+ group_type: 2,
+ project_type: 3
+ }
enum platform_type: {
kubernetes: 1
@@ -79,9 +102,11 @@ module Clusters
[
application_helm || build_application_helm,
application_ingress || build_application_ingress,
+ application_cert_manager || build_application_cert_manager,
application_prometheus || build_application_prometheus,
application_runner || build_application_runner,
- application_jupyter || build_application_jupyter
+ application_jupyter || build_application_jupyter,
+ application_knative || build_application_knative
]
end
@@ -98,16 +123,34 @@ module Clusters
end
def first_project
- return @first_project if defined?(@first_project)
-
- @first_project = projects.first
+ strong_memoize(:first_project) do
+ projects.first
+ end
end
alias_method :project, :first_project
+ def first_group
+ strong_memoize(:first_group) do
+ groups.first
+ end
+ end
+ alias_method :group, :first_group
+
def kubeclient
platform_kubernetes.kubeclient if kubernetes?
end
+ def find_or_initialize_kubernetes_namespace(cluster_project)
+ kubernetes_namespaces.find_or_initialize_by(
+ project: cluster_project.project,
+ cluster_project: cluster_project
+ )
+ end
+
+ def allow_user_defined_namespace?
+ project_type?
+ end
+
private
def restrict_modification
@@ -118,5 +161,17 @@ module Clusters
true
end
+
+ def no_groups
+ if groups.any?
+ errors.add(:cluster, 'cannot have groups assigned')
+ end
+ end
+
+ def no_projects
+ if projects.any?
+ errors.add(:cluster, 'cannot have projects assigned')
+ end
+ end
end
end
diff --git a/app/models/clusters/concerns/application_core.rb b/app/models/clusters/concerns/application_core.rb
index e3deedfb036..683b45331f6 100644
--- a/app/models/clusters/concerns/application_core.rb
+++ b/app/models/clusters/concerns/application_core.rb
@@ -15,7 +15,7 @@ module Clusters
def set_initial_status
return unless not_installable?
- self.status = 'installable' if cluster&.application_helm_installed?
+ self.status = 'installable' if cluster&.application_helm_available?
end
def self.application_name
diff --git a/app/models/clusters/concerns/application_status.rb b/app/models/clusters/concerns/application_status.rb
index d4d3859dfd5..0e74cce29b7 100644
--- a/app/models/clusters/concerns/application_status.rb
+++ b/app/models/clusters/concerns/application_status.rb
@@ -15,6 +15,9 @@ module Clusters
state :scheduled, value: 1
state :installing, value: 2
state :installed, value: 3
+ state :updating, value: 4
+ state :updated, value: 5
+ state :update_errored, value: 6
event :make_scheduled do
transition [:installable, :errored] => :scheduled
@@ -32,6 +35,18 @@ module Clusters
transition any => :errored
end
+ event :make_updating do
+ transition [:installed, :updated, :update_errored] => :updating
+ end
+
+ event :make_updated do
+ transition [:updating] => :updated
+ end
+
+ event :make_update_errored do
+ transition any => :update_errored
+ end
+
before_transition any => [:scheduled] do |app_status, _|
app_status.status_reason = nil
end
@@ -40,8 +55,28 @@ module Clusters
status_reason = transition.args.first
app_status.status_reason = status_reason if status_reason
end
+
+ before_transition any => [:updating] do |app_status, _|
+ app_status.status_reason = nil
+ end
+
+ before_transition any => [:update_errored] do |app_status, transition|
+ status_reason = transition.args.first
+ app_status.status_reason = status_reason if status_reason
+ end
+
+ before_transition any => [:installed, :updated] do |app_status, _|
+ # When installing any application we are also performing an update
+ # of tiller (see Gitlab::Kubernetes::Helm::ClientCommand) so
+ # therefore we need to reflect that in the database.
+ app_status.cluster.application_helm.update!(version: Gitlab::Kubernetes::Helm::HELM_VERSION)
+ end
end
end
+
+ def available?
+ installed? || updated?
+ end
end
end
end
diff --git a/app/models/clusters/group.rb b/app/models/clusters/group.rb
new file mode 100644
index 00000000000..2b08a9e47f0
--- /dev/null
+++ b/app/models/clusters/group.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module Clusters
+ class Group < ActiveRecord::Base
+ self.table_name = 'cluster_groups'
+
+ belongs_to :cluster, class_name: 'Clusters::Cluster'
+ belongs_to :group, class_name: '::Group'
+ end
+end
diff --git a/app/models/clusters/kubernetes_namespace.rb b/app/models/clusters/kubernetes_namespace.rb
new file mode 100644
index 00000000000..34f5e38ff79
--- /dev/null
+++ b/app/models/clusters/kubernetes_namespace.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+module Clusters
+ class KubernetesNamespace < ActiveRecord::Base
+ include Gitlab::Kubernetes
+
+ self.table_name = 'clusters_kubernetes_namespaces'
+
+ belongs_to :cluster_project, class_name: 'Clusters::Project'
+ belongs_to :cluster, class_name: 'Clusters::Cluster'
+ belongs_to :project, class_name: '::Project'
+ has_one :platform_kubernetes, through: :cluster
+
+ before_validation :set_defaults
+
+ validates :namespace, presence: true
+ validates :namespace, uniqueness: { scope: :cluster_id }
+
+ validates :service_account_name, presence: true
+
+ delegate :ca_pem, to: :platform_kubernetes, allow_nil: true
+ delegate :api_url, to: :platform_kubernetes, allow_nil: true
+
+ attr_encrypted :service_account_token,
+ mode: :per_attribute_iv,
+ key: Settings.attr_encrypted_db_key_base_truncated,
+ algorithm: 'aes-256-cbc'
+
+ scope :has_service_account_token, -> { where.not(encrypted_service_account_token: nil) }
+
+ def token_name
+ "#{namespace}-token"
+ end
+
+ def predefined_variables
+ config = YAML.dump(kubeconfig)
+
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ variables
+ .append(key: 'KUBE_SERVICE_ACCOUNT', value: service_account_name.to_s)
+ .append(key: 'KUBE_NAMESPACE', value: namespace.to_s)
+ .append(key: 'KUBE_TOKEN', value: service_account_token.to_s, public: false)
+ .append(key: 'KUBECONFIG', value: config, public: false, file: true)
+ end
+ end
+
+ def set_defaults
+ self.namespace ||= default_platform_kubernetes_namespace
+ self.namespace ||= default_project_namespace
+ self.service_account_name ||= default_service_account_name
+ end
+
+ private
+
+ def default_service_account_name
+ return unless namespace
+
+ "#{namespace}-service-account"
+ end
+
+ def default_platform_kubernetes_namespace
+ platform_kubernetes&.namespace.presence
+ end
+
+ def default_project_namespace
+ Gitlab::NamespaceSanitizer.sanitize(project_slug) if project_slug
+ end
+
+ def project_slug
+ return unless project
+
+ "#{project.path}-#{project.id}".downcase
+ end
+
+ def kubeconfig
+ to_kubeconfig(
+ url: api_url,
+ namespace: namespace,
+ token: service_account_token,
+ ca_pem: ca_pem)
+ end
+ end
+end
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index 3a335909101..dc8b52105cc 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -6,6 +6,9 @@ module Clusters
include Gitlab::Kubernetes
include ReactiveCaching
include EnumWithNil
+ include AfterCommitQueue
+
+ RESERVED_NAMESPACES = %w(gitlab-managed-apps).freeze
self.table_name = 'cluster_platforms_kubernetes'
self.reactive_cache_key = ->(kubernetes) { [kubernetes.class.model_name.singular, kubernetes.id] }
@@ -23,6 +26,7 @@ module Clusters
algorithm: 'aes-256-cbc'
before_validation :enforce_namespace_to_lower_case
+ before_validation :enforce_ca_whitespace_trimming
validates :namespace,
allow_blank: true,
@@ -32,6 +36,10 @@ module Clusters
message: Gitlab::Regex.kubernetes_namespace_regex_message
}
+ validates :namespace, exclusion: { in: RESERVED_NAMESPACES }
+
+ validate :no_namespace, unless: :allow_user_defined_namespace?
+
# We expect to be `active?` only when enabled and cluster is created (the api_url is assigned)
validates :api_url, url: true, presence: true
validates :token, presence: true
@@ -39,12 +47,15 @@ module Clusters
validate :prevent_modification, on: :update
after_save :clear_reactive_cache!
+ after_update :update_kubernetes_namespace
alias_attribute :ca_pem, :ca_cert
delegate :project, to: :cluster, allow_nil: true
delegate :enabled?, to: :cluster, allow_nil: true
delegate :managed?, to: :cluster, allow_nil: true
+ delegate :allow_user_defined_namespace?, to: :cluster, allow_nil: true
+ delegate :kubernetes_namespace, to: :cluster
alias_method :active?, :enabled?
@@ -62,21 +73,31 @@ module Clusters
end
end
- def predefined_variables
- config = YAML.dump(kubeconfig)
-
+ def predefined_variables(project:)
Gitlab::Ci::Variables::Collection.new.tap do |variables|
- variables
- .append(key: 'KUBE_URL', value: api_url)
- .append(key: 'KUBE_TOKEN', value: token, public: false)
- .append(key: 'KUBE_NAMESPACE', value: actual_namespace)
- .append(key: 'KUBECONFIG', value: config, public: false, file: true)
+ variables.append(key: 'KUBE_URL', value: api_url)
if ca_pem.present?
variables
.append(key: 'KUBE_CA_PEM', value: ca_pem)
.append(key: 'KUBE_CA_PEM_FILE', value: ca_pem, file: true)
end
+
+ if kubernetes_namespace = cluster.kubernetes_namespaces.has_service_account_token.find_by(project: project)
+ variables.concat(kubernetes_namespace.predefined_variables)
+ elsif cluster.project_type?
+ # From 11.5, every Clusters::Project should have at least one
+ # Clusters::KubernetesNamespace, so once migration has been completed,
+ # this 'else' branch will be removed. For more information, please see
+ # https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22433
+ config = YAML.dump(kubeconfig)
+
+ variables
+ .append(key: 'KUBE_URL', value: api_url)
+ .append(key: 'KUBE_TOKEN', value: token, public: false)
+ .append(key: 'KUBE_NAMESPACE', value: actual_namespace)
+ .append(key: 'KUBECONFIG', value: config, public: false, file: true)
+ end
end
end
@@ -102,7 +123,7 @@ module Clusters
end
def kubeclient
- @kubeclient ||= build_kube_client!(api_groups: ['api', 'apis/rbac.authorization.k8s.io'])
+ @kubeclient ||= build_kube_client!
end
private
@@ -116,14 +137,24 @@ module Clusters
end
def default_namespace
+ kubernetes_namespace&.namespace.presence || fallback_default_namespace
+ end
+
+ # DEPRECATED
+ #
+ # On 11.4 Clusters::KubernetesNamespace was introduced, this model will allow to
+ # have multiple namespaces per project. This method will be removed after migration
+ # has been completed.
+ def fallback_default_namespace
return unless project
slug = "#{project.path}-#{project.id}".downcase
- slug.gsub(/[^-a-z0-9]/, '-').gsub(/^-+/, '')
+ Gitlab::NamespaceSanitizer.sanitize(slug)
end
- def build_kube_client!(api_groups: ['api'], api_version: 'v1')
- raise "Incomplete settings" unless api_url && actual_namespace
+ def build_kube_client!
+ raise "Incomplete settings" unless api_url
+ raise "No namespace" if cluster.project_type? && actual_namespace.empty? # can probably remove this line once we remove #actual_namespace
unless (username && password) || token
raise "Either username/password or token is required to access API"
@@ -131,8 +162,6 @@ module Clusters
Gitlab::Kubernetes::KubeClient.new(
api_url,
- api_groups,
- api_version,
auth_options: kubeclient_auth_options,
ssl_options: kubeclient_ssl_options,
http_proxy_uri: ENV['http_proxy']
@@ -144,9 +173,7 @@ module Clusters
kubeclient = build_kube_client!
kubeclient.get_pods(namespace: actual_namespace).as_json
- rescue Kubeclient::HttpError => err
- raise err unless err.error_code == 404
-
+ rescue Kubeclient::ResourceNotFoundError
[]
end
@@ -177,6 +204,17 @@ module Clusters
self.namespace = self.namespace&.downcase
end
+ def enforce_ca_whitespace_trimming
+ self.ca_pem = self.ca_pem&.strip
+ self.token = self.token&.strip
+ end
+
+ def no_namespace
+ if namespace
+ errors.add(:namespace, 'only allowed for project cluster')
+ end
+ end
+
def prevent_modification
return unless managed?
@@ -187,6 +225,14 @@ module Clusters
true
end
+
+ def update_kubernetes_namespace
+ return unless namespace_changed?
+
+ run_after_commit do
+ ClusterPlatformConfigureWorker.perform_async(cluster_id)
+ end
+ end
end
end
end
diff --git a/app/models/clusters/project.rb b/app/models/clusters/project.rb
index 839ce796081..15092b1c9d2 100644
--- a/app/models/clusters/project.rb
+++ b/app/models/clusters/project.rb
@@ -6,5 +6,8 @@ module Clusters
belongs_to :cluster, class_name: 'Clusters::Cluster'
belongs_to :project, class_name: '::Project'
+
+ has_many :kubernetes_namespaces, class_name: 'Clusters::KubernetesNamespace', foreign_key: :cluster_project_id
+ has_one :kubernetes_namespace, -> { order(id: :desc) }, class_name: 'Clusters::KubernetesNamespace', foreign_key: :cluster_project_id
end
end
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 49c36ad9d3f..546fcc54a15 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -230,24 +230,13 @@ class Commit
def lazy_author
BatchLoader.for(author_email.downcase).batch do |emails, loader|
- # A Hash that maps user Emails to the corresponding User objects. The
- # Emails at this point are the _primary_ Emails of the Users.
- users_for_emails = User
- .by_any_email(emails)
- .each_with_object({}) { |user, hash| hash[user.email] = user }
-
- users_for_ids = users_for_emails
- .values
- .each_with_object({}) { |user, hash| hash[user.id] = user }
-
- # Some commits may have used an alternative Email address. In this case we
- # need to query the "emails" table to map those addresses to User objects.
- Email
- .where(email: emails - users_for_emails.keys)
- .pluck(:email, :user_id)
- .each { |(email, id)| users_for_emails[email] = users_for_ids[id] }
-
- users_for_emails.each { |email, user| loader.call(email, user) }
+ users = User.by_any_email(emails).includes(:emails)
+
+ emails.each do |email|
+ user = users.find { |u| u.any_email?(email) }
+
+ loader.call(email, user)
+ end
end
end
@@ -260,7 +249,7 @@ class Commit
request_cache(:author) { author_email.downcase }
def committer
- @committer ||= User.find_by_any_email(committer_email.downcase)
+ @committer ||= User.find_by_any_email(committer_email)
end
def parents
@@ -319,7 +308,11 @@ class Commit
def status(ref = nil)
return @statuses[ref] if @statuses.key?(ref)
- @statuses[ref] = project.pipelines.latest_status_per_commit(id, ref)[id]
+ @statuses[ref] = status_for_project(ref, project)
+ end
+
+ def status_for_project(ref, pipeline_project)
+ pipeline_project.pipelines.latest_status_per_commit(id, ref)[id]
end
def set_status_for_ref(ref, status)
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index fe2f144ef03..0f50bd39131 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -42,15 +42,9 @@ class CommitStatus < ActiveRecord::Base
scope :retried_ordered, -> { retried.ordered.includes(project: :namespace) }
scope :after_stage, -> (index) { where('stage_idx > ?', index) }
- enum_with_nil failure_reason: {
- unknown_failure: nil,
- script_failure: 1,
- api_failure: 2,
- stuck_or_timeout_failure: 3,
- runner_system_failure: 4,
- missing_dependency_failure: 5,
- runner_unsupported: 6
- }
+ # We use `CommitStatusEnums.failure_reasons` here so that EE can more easily
+ # extend this `Hash` with new values.
+ enum_with_nil failure_reason: ::CommitStatusEnums.failure_reasons
##
# We still create some CommitStatuses outside of CreatePipelineService.
@@ -71,7 +65,7 @@ class CommitStatus < ActiveRecord::Base
end
event :enqueue do
- transition [:created, :skipped, :manual] => :pending
+ transition [:created, :skipped, :manual, :scheduled] => :pending
end
event :run do
@@ -83,7 +77,7 @@ class CommitStatus < ActiveRecord::Base
end
event :drop do
- transition [:created, :pending, :running] => :failed
+ transition [:created, :pending, :running, :scheduled] => :failed
end
event :success do
@@ -91,10 +85,10 @@ class CommitStatus < ActiveRecord::Base
end
event :cancel do
- transition [:created, :pending, :running, :manual] => :canceled
+ transition [:created, :pending, :running, :manual, :scheduled] => :canceled
end
- before_transition [:created, :skipped, :manual] => :pending do |commit_status|
+ before_transition [:created, :skipped, :manual, :scheduled] => :pending do |commit_status|
commit_status.queued_at = Time.now
end
@@ -108,7 +102,7 @@ class CommitStatus < ActiveRecord::Base
before_transition any => :failed do |commit_status, transition|
failure_reason = transition.args.first
- commit_status.failure_reason = failure_reason
+ commit_status.failure_reason = CommitStatus.failure_reasons[failure_reason]
end
after_transition do |commit_status, transition|
@@ -165,16 +159,18 @@ class CommitStatus < ActiveRecord::Base
false
end
- # To be overriden when inherrited from
def retryable?
false
end
- # To be overriden when inherrited from
def cancelable?
false
end
+ def archived?
+ false
+ end
+
def stuck?
false
end
diff --git a/app/models/commit_status_enums.rb b/app/models/commit_status_enums.rb
new file mode 100644
index 00000000000..152105d9429
--- /dev/null
+++ b/app/models/commit_status_enums.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module CommitStatusEnums
+ # Returns the Hash to use for creating the `failure_reason` enum for
+ # `CommitStatus`.
+ def self.failure_reasons
+ {
+ unknown_failure: nil,
+ script_failure: 1,
+ api_failure: 2,
+ stuck_or_timeout_failure: 3,
+ runner_system_failure: 4,
+ missing_dependency_failure: 5,
+ runner_unsupported: 6,
+ stale_schedule: 7,
+ job_execution_timeout: 8,
+ archived_failure: 9
+ }
+ end
+end
diff --git a/app/models/compare.rb b/app/models/compare.rb
index b2d46ada831..f1ed84ab5a5 100644
--- a/app/models/compare.rb
+++ b/app/models/compare.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require 'set'
+
class Compare
include Gitlab::Utils::StrongMemoize
@@ -77,4 +79,13 @@ class Compare
head_sha: head_commit_sha
)
end
+
+ def modified_paths
+ paths = Set.new
+ diffs.diff_files.each do |diff|
+ paths.add diff.old_path
+ paths.add diff.new_path
+ end
+ paths.to_a
+ end
end
diff --git a/app/models/concerns/avatarable.rb b/app/models/concerns/avatarable.rb
index 0d5311a9985..b42236c1fa2 100644
--- a/app/models/concerns/avatarable.rb
+++ b/app/models/concerns/avatarable.rb
@@ -86,7 +86,7 @@ module Avatarable
params[:model].upload_paths(params[:identifier])
end
- Upload.where(uploader: AvatarUploader, path: paths).find_each do |upload|
+ Upload.where(uploader: AvatarUploader.name, path: paths).find_each do |upload|
model = model_class.instantiate('id' => upload.model_id)
loader.call({ model: model, identifier: File.basename(upload.path) }, upload)
diff --git a/app/models/concerns/awardable.rb b/app/models/concerns/awardable.rb
index 6f29c92d176..60b7ec2815c 100644
--- a/app/models/concerns/awardable.rb
+++ b/app/models/concerns/awardable.rb
@@ -13,13 +13,13 @@ module Awardable
end
class_methods do
- def awarded(user, name)
+ def awarded(user, name = nil)
sql = <<~EOL
EXISTS (
SELECT TRUE
FROM award_emoji
WHERE user_id = :user_id AND
- name = :name AND
+ #{"name = :name AND" if name.present?}
awardable_type = :awardable_type AND
awardable_id = #{self.arel_table.name}.id
)
@@ -28,6 +28,20 @@ module Awardable
where(sql, user_id: user.id, name: name, awardable_type: self.name)
end
+ def not_awarded(user)
+ sql = <<~EOL
+ NOT EXISTS (
+ SELECT TRUE
+ FROM award_emoji
+ WHERE user_id = :user_id AND
+ awardable_type = :awardable_type AND
+ awardable_id = #{self.arel_table.name}.id
+ )
+ EOL
+
+ where(sql, user_id: user.id, awardable_type: self.name)
+ end
+
def order_upvotes_desc
order_votes_desc(AwardEmoji::UPVOTE_NAME)
end
diff --git a/app/models/concerns/blob_language_from_git_attributes.rb b/app/models/concerns/blob_language_from_git_attributes.rb
new file mode 100644
index 00000000000..70213d22147
--- /dev/null
+++ b/app/models/concerns/blob_language_from_git_attributes.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+# Applicable for blob classes with project attribute
+module BlobLanguageFromGitAttributes
+ extend ActiveSupport::Concern
+
+ def language_from_gitattributes
+ return nil unless project
+
+ repository = project.repository
+ repository.gitattribute(path, 'gitlab-language')
+ end
+end
diff --git a/app/models/concerns/blob_like.rb b/app/models/concerns/blob_like.rb
index e96fefe81c4..f20f01486a5 100644
--- a/app/models/concerns/blob_like.rb
+++ b/app/models/concerns/blob_like.rb
@@ -2,7 +2,7 @@
module BlobLike
extend ActiveSupport::Concern
- include Linguist::BlobHelper
+ include Gitlab::BlobHelper
def id
raise NotImplementedError
diff --git a/app/models/concerns/blocks_json_serialization.rb b/app/models/concerns/blocks_json_serialization.rb
index d346da1ba4b..18c00532d78 100644
--- a/app/models/concerns/blocks_json_serialization.rb
+++ b/app/models/concerns/blocks_json_serialization.rb
@@ -3,7 +3,7 @@
# Overrides `as_json` and `to_json` to raise an exception when called in order
# to prevent accidentally exposing attributes
#
-# Not that that would ever happen... but just in case.
+# Not that would ever happen... but just in case.
module BlocksJsonSerialization
extend ActiveSupport::Concern
diff --git a/app/models/concerns/bulk_member_access_load.rb b/app/models/concerns/bulk_member_access_load.rb
index c4346d5dd17..041ed3755e0 100644
--- a/app/models/concerns/bulk_member_access_load.rb
+++ b/app/models/concerns/bulk_member_access_load.rb
@@ -16,9 +16,9 @@ module BulkMemberAccessLoad
key = max_member_access_for_resource_key(resource_klass, memoization_index)
access = {}
- if RequestStore.active?
- RequestStore.store[key] ||= {}
- access = RequestStore.store[key]
+ if Gitlab::SafeRequestStore.active?
+ Gitlab::SafeRequestStore[key] ||= {}
+ access = Gitlab::SafeRequestStore[key]
end
# Look up only the IDs we need
diff --git a/app/models/concerns/cache_markdown_field.rb b/app/models/concerns/cache_markdown_field.rb
index 6e2adc76ec6..a8c9e54f00c 100644
--- a/app/models/concerns/cache_markdown_field.rb
+++ b/app/models/concerns/cache_markdown_field.rb
@@ -15,7 +15,7 @@ module CacheMarkdownField
# Increment this number every time the renderer changes its output
CACHE_REDCARPET_VERSION = 3
CACHE_COMMONMARK_VERSION_START = 10
- CACHE_COMMONMARK_VERSION = 11
+ CACHE_COMMONMARK_VERSION = 12
# changes to these attributes cause the cache to be invalidates
INVALIDATED_BY = %w[author project].freeze
diff --git a/app/models/concerns/cacheable_attributes.rb b/app/models/concerns/cacheable_attributes.rb
index 62b78c3611c..75592bb63e2 100644
--- a/app/models/concerns/cacheable_attributes.rb
+++ b/app/models/concerns/cacheable_attributes.rb
@@ -12,12 +12,12 @@ module CacheableAttributes
"#{name}:#{Gitlab::VERSION}:#{Rails.version}".freeze
end
- # Can be overriden
+ # Can be overridden
def current_without_cache
last
end
- # Can be overriden
+ # Can be overridden
def defaults
{}
end
@@ -27,11 +27,7 @@ module CacheableAttributes
end
def cached
- if RequestStore.active?
- RequestStore[:"#{name}_cached_attributes"] ||= retrieve_from_cache
- else
- retrieve_from_cache
- end
+ Gitlab::SafeRequestStore[:"#{name}_cached_attributes"] ||= retrieve_from_cache
end
def retrieve_from_cache
diff --git a/app/models/concerns/deployable.rb b/app/models/concerns/deployable.rb
new file mode 100644
index 00000000000..bc12b06b5af
--- /dev/null
+++ b/app/models/concerns/deployable.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Deployable
+ extend ActiveSupport::Concern
+
+ included do
+ after_create :create_deployment
+
+ def create_deployment
+ return unless starts_environment? && !has_deployment?
+
+ environment = project.environments.find_or_create_by(
+ name: expanded_environment_name
+ )
+
+ # If we failed to persist envirionment record by validation error, such as name with invalid character,
+ # the job will fall back to a non-environment job.
+ return unless environment.persisted?
+
+ create_deployment!(
+ project_id: environment.project_id,
+ environment: environment,
+ ref: ref,
+ tag: tag,
+ sha: sha,
+ user: user,
+ on_stop: on_stop)
+ end
+ end
+end
diff --git a/app/models/concerns/deployment_platform.rb b/app/models/concerns/deployment_platform.rb
index 91052013592..e57a3383544 100644
--- a/app/models/concerns/deployment_platform.rb
+++ b/app/models/concerns/deployment_platform.rb
@@ -42,6 +42,7 @@ module DeploymentPlatform
{
name: 'kubernetes-template',
projects: [self],
+ cluster_type: :project_type,
provider_type: :user,
platform_type: :kubernetes,
platform_kubernetes_attributes: platform_kubernetes_attributes_from_service_template
diff --git a/app/models/concerns/diff_positionable_note.rb b/app/models/concerns/diff_positionable_note.rb
new file mode 100644
index 00000000000..b61bf29e6ad
--- /dev/null
+++ b/app/models/concerns/diff_positionable_note.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+module DiffPositionableNote
+ extend ActiveSupport::Concern
+
+ included do
+ before_validation :set_original_position, on: :create
+ before_validation :update_position, on: :create, if: :on_text?
+
+ serialize :original_position, Gitlab::Diff::Position # rubocop:disable Cop/ActiveRecordSerialize
+ serialize :position, Gitlab::Diff::Position # rubocop:disable Cop/ActiveRecordSerialize
+ serialize :change_position, Gitlab::Diff::Position # rubocop:disable Cop/ActiveRecordSerialize
+ end
+
+ %i(original_position position change_position).each do |meth|
+ define_method "#{meth}=" do |new_position|
+ if new_position.is_a?(String)
+ new_position = JSON.parse(new_position) rescue nil
+ end
+
+ if new_position.is_a?(Hash)
+ new_position = new_position.with_indifferent_access
+ new_position = Gitlab::Diff::Position.new(new_position)
+ end
+
+ return if new_position == read_attribute(meth)
+
+ super(new_position)
+ end
+ end
+
+ def on_text?
+ position&.position_type == "text"
+ end
+
+ def on_image?
+ position&.position_type == "image"
+ end
+
+ def supported?
+ for_commit? || self.noteable.has_complete_diff_refs?
+ end
+
+ def active?(diff_refs = nil)
+ return false unless supported?
+ return true if for_commit?
+
+ diff_refs ||= noteable.diff_refs
+
+ self.position.diff_refs == diff_refs
+ end
+
+ def set_original_position
+ return unless position
+
+ self.original_position = self.position.dup unless self.original_position&.complete?
+ end
+
+ def update_position
+ return unless supported?
+ return if for_commit?
+
+ return if active?
+ return unless position
+
+ tracer = Gitlab::Diff::PositionTracer.new(
+ project: self.project,
+ old_diff_refs: self.position.diff_refs,
+ new_diff_refs: self.noteable.diff_refs,
+ paths: self.position.paths
+ )
+
+ result = tracer.trace(self.position)
+ return unless result
+
+ if result[:outdated]
+ self.change_position = result[:position]
+ else
+ self.position = result[:position]
+ end
+ end
+end
diff --git a/app/models/concerns/each_batch.rb b/app/models/concerns/each_batch.rb
index 8cf0b8b154d..6314b46a7e3 100644
--- a/app/models/concerns/each_batch.rb
+++ b/app/models/concerns/each_batch.rb
@@ -39,7 +39,15 @@ module EachBatch
#
# of - The number of rows to retrieve per batch.
# column - The column to use for ordering the batches.
- def each_batch(of: 1000, column: primary_key)
+ # order_hint - An optional column to append to the `ORDER BY id`
+ # clause to help the query planner. PostgreSQL might perform badly
+ # with a LIMIT 1 because the planner is guessing that scanning the
+ # index in ID order will come across the desired row in less time
+ # it will take the planner than using another index. The
+ # order_hint does not affect the search results. For example,
+ # `ORDER BY id ASC, updated_at ASC` means the same thing as `ORDER
+ # BY id ASC`.
+ def each_batch(of: 1000, column: primary_key, order_hint: nil)
unless column
raise ArgumentError,
'the column: argument must be set to a column name to use for ordering rows'
@@ -48,7 +56,9 @@ module EachBatch
start = except(:select)
.select(column)
.reorder(column => :asc)
- .take
+
+ start = start.order(order_hint) if order_hint
+ start = start.take
return unless start
@@ -60,6 +70,9 @@ module EachBatch
.select(column)
.where(arel_table[column].gteq(start_id))
.reorder(column => :asc)
+
+ stop = stop.order(order_hint) if order_hint
+ stop = stop
.offset(of)
.limit(1)
.take
diff --git a/app/models/concerns/fast_destroy_all.rb b/app/models/concerns/fast_destroy_all.rb
index c342d01243e..2bfa7da6c1c 100644
--- a/app/models/concerns/fast_destroy_all.rb
+++ b/app/models/concerns/fast_destroy_all.rb
@@ -7,7 +7,7 @@
# `delete_all` is efficient as it deletes all rows with a single `DELETE` query.
#
# It's better to use `delete_all` as our best practice, however,
-# if external data (e.g. ObjectStorage, FileStorage or Redis) are assosiated with database records,
+# if external data (e.g. ObjectStorage, FileStorage or Redis) are associated with database records,
# it is difficult to accomplish it.
#
# This module defines a format to use `delete_all` and delete associated external data.
diff --git a/app/models/concerns/has_status.rb b/app/models/concerns/has_status.rb
index b3960cbad1a..b92643f87f8 100644
--- a/app/models/concerns/has_status.rb
+++ b/app/models/concerns/has_status.rb
@@ -4,14 +4,15 @@ module HasStatus
extend ActiveSupport::Concern
DEFAULT_STATUS = 'created'.freeze
- BLOCKED_STATUS = 'manual'.freeze
- AVAILABLE_STATUSES = %w[created pending running success failed canceled skipped manual].freeze
- STARTED_STATUSES = %w[running success failed skipped manual].freeze
+ BLOCKED_STATUS = %w[manual scheduled].freeze
+ AVAILABLE_STATUSES = %w[created pending running success failed canceled skipped manual scheduled].freeze
+ STARTED_STATUSES = %w[running success failed skipped manual scheduled].freeze
ACTIVE_STATUSES = %w[pending running].freeze
COMPLETED_STATUSES = %w[success failed canceled skipped].freeze
- ORDERED_STATUSES = %w[failed pending running manual canceled success skipped created].freeze
+ ORDERED_STATUSES = %w[failed pending running manual scheduled canceled success skipped created].freeze
STATUSES_ENUM = { created: 0, pending: 1, running: 2, success: 3,
- failed: 4, canceled: 5, skipped: 6, manual: 7 }.freeze
+ failed: 4, canceled: 5, skipped: 6, manual: 7,
+ scheduled: 8 }.freeze
UnknownStatusError = Class.new(StandardError)
@@ -24,6 +25,7 @@ module HasStatus
created = scope_relevant.created.select('count(*)').to_sql
success = scope_relevant.success.select('count(*)').to_sql
manual = scope_relevant.manual.select('count(*)').to_sql
+ scheduled = scope_relevant.scheduled.select('count(*)').to_sql
pending = scope_relevant.pending.select('count(*)').to_sql
running = scope_relevant.running.select('count(*)').to_sql
skipped = scope_relevant.skipped.select('count(*)').to_sql
@@ -40,6 +42,7 @@ module HasStatus
WHEN (#{builds})=(#{created})+(#{skipped})+(#{pending}) THEN 'pending'
WHEN (#{running})+(#{pending})>0 THEN 'running'
WHEN (#{manual})>0 THEN 'manual'
+ WHEN (#{scheduled})>0 THEN 'scheduled'
WHEN (#{created})>0 THEN 'running'
ELSE 'failed'
END)"
@@ -74,6 +77,7 @@ module HasStatus
state :canceled, value: 'canceled'
state :skipped, value: 'skipped'
state :manual, value: 'manual'
+ state :scheduled, value: 'scheduled'
end
scope :created, -> { where(status: 'created') }
@@ -85,6 +89,7 @@ module HasStatus
scope :canceled, -> { where(status: 'canceled') }
scope :skipped, -> { where(status: 'skipped') }
scope :manual, -> { where(status: 'manual') }
+ scope :scheduled, -> { where(status: 'scheduled') }
scope :alive, -> { where(status: [:created, :pending, :running]) }
scope :created_or_pending, -> { where(status: [:created, :pending]) }
scope :running_or_pending, -> { where(status: [:running, :pending]) }
@@ -92,7 +97,7 @@ module HasStatus
scope :failed_or_canceled, -> { where(status: [:failed, :canceled]) }
scope :cancelable, -> do
- where(status: [:running, :pending, :created])
+ where(status: [:running, :pending, :created, :scheduled])
end
end
@@ -109,7 +114,7 @@ module HasStatus
end
def blocked?
- BLOCKED_STATUS == status
+ BLOCKED_STATUS.include?(status)
end
private
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index 5f65fceb7af..5080fe03cc8 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -9,6 +9,7 @@
module Issuable
extend ActiveSupport::Concern
include Gitlab::SQL::Pattern
+ include Redactable
include CacheMarkdownField
include Participable
include Mentionable
@@ -32,6 +33,8 @@ module Issuable
cache_markdown_field :title, pipeline: :single_line
cache_markdown_field :description, issuable_state_filter_enabled: true
+ redact_field :description
+
belongs_to :author, class_name: "User"
belongs_to :updated_by, class_name: "User"
belongs_to :last_edited_by, class_name: 'User'
@@ -76,6 +79,7 @@ module Issuable
scope :recent, -> { reorder(id: :desc) }
scope :of_projects, ->(ids) { where(project_id: ids) }
scope :of_milestones, ->(ids) { where(milestone_id: ids) }
+ scope :any_milestone, -> { where('milestone_id IS NOT NULL') }
scope :with_milestone, ->(title) { left_joins_milestones.where(milestones: { title: title }) }
scope :opened, -> { with_state(:opened) }
scope :only_opened, -> { with_state(:opened) }
@@ -86,6 +90,7 @@ module Issuable
scope :order_milestone_due_asc, -> { left_joins_milestones.reorder('milestones.due_date IS NULL, milestones.id IS NULL, milestones.due_date ASC') }
scope :without_label, -> { joins("LEFT OUTER JOIN label_links ON label_links.target_type = '#{name}' AND label_links.target_id = #{table_name}.id").where(label_links: { id: nil }) }
+ scope :any_label, -> { joins(:label_links).group(:id) }
scope :join_project, -> { joins(:project) }
scope :inc_notes_with_associations, -> { includes(notes: [:project, :author, :award_emoji]) }
scope :references_project, -> { references(:project) }
@@ -359,7 +364,7 @@ module Issuable
end
##
- # Overriden in MergeRequest
+ # Overridden in MergeRequest
#
def wipless_title_changed(old_title)
old_title != title
diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb
index 298d0d42d90..0d88b34fb48 100644
--- a/app/models/concerns/mentionable.rb
+++ b/app/models/concerns/mentionable.rb
@@ -97,9 +97,9 @@ module Mentionable
# Allows heavy processing to be skipped
def matches_cross_reference_regex?
reference_pattern = if !project || project.default_issues_tracker?
- ReferenceRegexes::DEFAULT_PATTERN
+ ReferenceRegexes.default_pattern
else
- ReferenceRegexes::EXTERNAL_PATTERN
+ ReferenceRegexes.external_pattern
end
self.class.mentionable_attrs.any? do |attr, _|
diff --git a/app/models/concerns/mentionable/reference_regexes.rb b/app/models/concerns/mentionable/reference_regexes.rb
index fe8fbb71184..b8fb3f71925 100644
--- a/app/models/concerns/mentionable/reference_regexes.rb
+++ b/app/models/concerns/mentionable/reference_regexes.rb
@@ -2,6 +2,8 @@
module Mentionable
module ReferenceRegexes
+ extend Gitlab::Utils::StrongMemoize
+
def self.reference_pattern(link_patterns, issue_pattern)
Regexp.union(link_patterns,
issue_pattern,
@@ -15,16 +17,20 @@ module Mentionable
]
end
- DEFAULT_PATTERN = begin
- issue_pattern = Issue.reference_pattern
- link_patterns = Regexp.union([Issue, Commit, MergeRequest, Epic].map(&:link_reference_pattern).compact)
- reference_pattern(link_patterns, issue_pattern)
+ def self.default_pattern
+ strong_memoize(:default_pattern) do
+ issue_pattern = Issue.reference_pattern
+ link_patterns = Regexp.union([Issue, Commit, MergeRequest, Epic].map(&:link_reference_pattern).compact)
+ reference_pattern(link_patterns, issue_pattern)
+ end
end
- EXTERNAL_PATTERN = begin
- issue_pattern = IssueTrackerService.reference_pattern
- link_patterns = URI.regexp(%w(http https))
- reference_pattern(link_patterns, issue_pattern)
+ def self.external_pattern
+ strong_memoize(:external_pattern) do
+ issue_pattern = IssueTrackerService.reference_pattern
+ link_patterns = URI.regexp(%w(http https))
+ reference_pattern(link_patterns, issue_pattern)
+ end
end
end
end
diff --git a/app/models/concerns/mirror_authentication.rb b/app/models/concerns/mirror_authentication.rb
new file mode 100644
index 00000000000..e3e1a0441f8
--- /dev/null
+++ b/app/models/concerns/mirror_authentication.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+# Mirroring may use password or SSH public-key authentication. This concern
+# implements support for persisting the necessary data in a `credentials`
+# serialized attribute. It also needs an `url` method to be defined
+module MirrorAuthentication
+ SSH_PRIVATE_KEY_OPTS = {
+ type: 'RSA',
+ bits: 4096
+ }.freeze
+
+ extend ActiveSupport::Concern
+
+ included do
+ validates :auth_method, inclusion: { in: %w[password ssh_public_key] }, allow_blank: true
+
+ # We should generate a key even if there's no SSH URL present
+ before_validation :generate_ssh_private_key!, if: -> {
+ regenerate_ssh_private_key || ( auth_method == 'ssh_public_key' && ssh_private_key.blank? )
+ }
+
+ credentials_field :auth_method, reader: false
+ credentials_field :ssh_known_hosts
+ credentials_field :ssh_known_hosts_verified_at
+ credentials_field :ssh_known_hosts_verified_by_id
+ credentials_field :ssh_private_key
+ credentials_field :user
+ credentials_field :password
+ end
+
+ class_methods do
+ def credentials_field(name, reader: true)
+ if reader
+ define_method(name) do
+ credentials[name] if credentials.present?
+ end
+ end
+
+ define_method("#{name}=") do |value|
+ self.credentials ||= {}
+
+ # Removal of the password, username, etc, generally causes an update of
+ # the value to the empty string. Detect and gracefully handle this case.
+ if value.present?
+ self.credentials[name] = value
+ else
+ self.credentials.delete(name)
+ end
+ end
+ end
+ end
+
+ attr_accessor :regenerate_ssh_private_key
+
+ def ssh_key_auth?
+ ssh_mirror_url? && auth_method == 'ssh_public_key'
+ end
+
+ def password_auth?
+ auth_method == 'password'
+ end
+
+ def ssh_mirror_url?
+ url&.start_with?('ssh://')
+ end
+
+ def ssh_known_hosts_verified_by
+ @ssh_known_hosts_verified_by ||= ::User.find_by(id: ssh_known_hosts_verified_by_id)
+ end
+
+ def ssh_known_hosts_fingerprints
+ ::SshHostKey.fingerprint_host_keys(ssh_known_hosts)
+ end
+
+ def auth_method
+ auth_method = credentials.fetch(:auth_method, nil) if credentials.present?
+
+ auth_method.presence || 'password'
+ end
+
+ def ssh_public_key
+ return nil if ssh_private_key.blank?
+
+ comment = "git@#{::Gitlab.config.gitlab.host}"
+ ::SSHKey.new(ssh_private_key, comment: comment).ssh_public_key
+ end
+
+ def generate_ssh_private_key!
+ self.ssh_private_key = ::SSHKey.generate(SSH_PRIVATE_KEY_OPTS).private_key
+ end
+end
diff --git a/app/models/concerns/noteable.rb b/app/models/concerns/noteable.rb
index 098eed137ba..eb315058c3a 100644
--- a/app/models/concerns/noteable.rb
+++ b/app/models/concerns/noteable.rb
@@ -23,7 +23,7 @@ module Noteable
end
def supports_discussions?
- DiscussionNote::NOTEABLE_TYPES.include?(base_class_name)
+ DiscussionNote.noteable_types.include?(base_class_name)
end
def discussions_rendered_on_frontend?
diff --git a/app/models/concerns/redactable.rb b/app/models/concerns/redactable.rb
new file mode 100644
index 00000000000..5ad96d6cc46
--- /dev/null
+++ b/app/models/concerns/redactable.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+# This module searches and redacts sensitive information in
+# redactable fields. Currently only unsubscribe link is redacted.
+# Add following lines into your model:
+#
+# include Redactable
+# redact_field :foo
+#
+module Redactable
+ extend ActiveSupport::Concern
+
+ UNSUBSCRIBE_PATTERN = %r{/sent_notifications/\h{32}/unsubscribe}
+
+ class_methods do
+ def redact_field(field)
+ before_validation do
+ redact_field!(field) if attribute_changed?(field)
+ end
+ end
+ end
+
+ private
+
+ def redact_field!(field)
+ text = public_send(field) # rubocop:disable GitlabSecurity/PublicSend
+ return unless text.present?
+
+ redacted = text.gsub(UNSUBSCRIBE_PATTERN, '/sent_notifications/REDACTED/unsubscribe')
+
+ public_send("#{field}=", redacted) # rubocop:disable GitlabSecurity/PublicSend
+ end
+end
diff --git a/app/models/concerns/relative_positioning.rb b/app/models/concerns/relative_positioning.rb
index 85229cded5d..46d2c345758 100644
--- a/app/models/concerns/relative_positioning.rb
+++ b/app/models/concerns/relative_positioning.rb
@@ -12,22 +12,66 @@ module RelativePositioning
after_save :save_positionable_neighbours
end
- def min_relative_position
- self.class.in_parents(parent_ids).minimum(:relative_position)
+ class_methods do
+ def move_to_end(objects)
+ objects = objects.reject(&:relative_position)
+
+ return if objects.empty?
+
+ max_relative_position = objects.first.max_relative_position
+
+ self.transaction do
+ objects.each do |object|
+ relative_position = position_between(max_relative_position, MAX_POSITION)
+ object.relative_position = relative_position
+ max_relative_position = relative_position
+ object.save
+ end
+ end
+ end
+
+ # This method takes two integer values (positions) and
+ # calculates the position between them. The range is huge as
+ # the maximum integer value is 2147483647. We are incrementing position by IDEAL_DISTANCE * 2 every time
+ # when we have enough space. If distance is less then IDEAL_DISTANCE we are calculating an average number
+ def position_between(pos_before, pos_after)
+ pos_before ||= MIN_POSITION
+ pos_after ||= MAX_POSITION
+
+ pos_before, pos_after = [pos_before, pos_after].sort
+
+ halfway = (pos_after + pos_before) / 2
+ distance_to_halfway = pos_after - halfway
+
+ if distance_to_halfway < IDEAL_DISTANCE
+ halfway
+ else
+ if pos_before == MIN_POSITION
+ pos_after - IDEAL_DISTANCE
+ elsif pos_after == MAX_POSITION
+ pos_before + IDEAL_DISTANCE
+ else
+ halfway
+ end
+ end
+ end
end
- def max_relative_position
- self.class.in_parents(parent_ids).maximum(:relative_position)
+ def min_relative_position(&block)
+ calculate_relative_position('MIN', &block)
+ end
+
+ def max_relative_position(&block)
+ calculate_relative_position('MAX', &block)
end
def prev_relative_position
prev_pos = nil
if self.relative_position
- prev_pos = self.class
- .in_parents(parent_ids)
- .where('relative_position < ?', self.relative_position)
- .maximum(:relative_position)
+ prev_pos = max_relative_position do |relation|
+ relation.where('relative_position < ?', self.relative_position)
+ end
end
prev_pos
@@ -37,10 +81,9 @@ module RelativePositioning
next_pos = nil
if self.relative_position
- next_pos = self.class
- .in_parents(parent_ids)
- .where('relative_position > ?', self.relative_position)
- .minimum(:relative_position)
+ next_pos = min_relative_position do |relation|
+ relation.where('relative_position > ?', self.relative_position)
+ end
end
next_pos
@@ -57,7 +100,7 @@ module RelativePositioning
@positionable_neighbours = [before] # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
- self.relative_position = position_between(before.relative_position, after.relative_position)
+ self.relative_position = self.class.position_between(before.relative_position, after.relative_position)
end
def move_after(before = self)
@@ -72,7 +115,7 @@ module RelativePositioning
pos_after = issue_to_move.relative_position
end
- self.relative_position = position_between(pos_before, pos_after)
+ self.relative_position = self.class.position_between(pos_before, pos_after)
end
def move_before(after = self)
@@ -87,15 +130,15 @@ module RelativePositioning
pos_before = issue_to_move.relative_position
end
- self.relative_position = position_between(pos_before, pos_after)
+ self.relative_position = self.class.position_between(pos_before, pos_after)
end
def move_to_end
- self.relative_position = position_between(max_relative_position || START_POSITION, MAX_POSITION)
+ self.relative_position = self.class.position_between(max_relative_position || START_POSITION, MAX_POSITION)
end
def move_to_start
- self.relative_position = position_between(min_relative_position || START_POSITION, MIN_POSITION)
+ self.relative_position = self.class.position_between(min_relative_position || START_POSITION, MIN_POSITION)
end
# Indicates if there is an issue that should be shifted to free the place
@@ -112,32 +155,6 @@ module RelativePositioning
private
- # This method takes two integer values (positions) and
- # calculates the position between them. The range is huge as
- # the maximum integer value is 2147483647. We are incrementing position by IDEAL_DISTANCE * 2 every time
- # when we have enough space. If distance is less then IDEAL_DISTANCE we are calculating an average number
- def position_between(pos_before, pos_after)
- pos_before ||= MIN_POSITION
- pos_after ||= MAX_POSITION
-
- pos_before, pos_after = [pos_before, pos_after].sort
-
- halfway = (pos_after + pos_before) / 2
- distance_to_halfway = pos_after - halfway
-
- if distance_to_halfway < IDEAL_DISTANCE
- halfway
- else
- if pos_before == MIN_POSITION
- pos_after - IDEAL_DISTANCE
- elsif pos_after == MAX_POSITION
- pos_before + IDEAL_DISTANCE
- else
- halfway
- end
- end
- end
-
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def save_positionable_neighbours
return unless @positionable_neighbours
@@ -148,4 +165,22 @@ module RelativePositioning
status
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
+
+ def calculate_relative_position(calculation)
+ # When calculating across projects, this is much more efficient than
+ # MAX(relative_position) without the GROUP BY, due to index usage:
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/54276#note_119340977
+ relation = self.class
+ .in_parents(parent_ids)
+ .order(Gitlab::Database.nulls_last_order('position', 'DESC'))
+ .limit(1)
+ .group(self.class.parent_column)
+
+ relation = yield relation if block_given?
+
+ relation
+ .pluck(self.class.parent_column, "#{calculation}(relative_position) AS position")
+ .first&.
+ last
+ end
end
diff --git a/app/models/concerns/shardable.rb b/app/models/concerns/shardable.rb
new file mode 100644
index 00000000000..57cd77b44b4
--- /dev/null
+++ b/app/models/concerns/shardable.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Shardable
+ extend ActiveSupport::Concern
+
+ included do
+ belongs_to :shard
+ validates :shard, presence: true
+ end
+
+ def shard_name
+ shard&.name
+ end
+
+ def shard_name=(name)
+ self.shard = Shard.by_name(name)
+ end
+end
diff --git a/app/models/concerns/storage/legacy_namespace.rb b/app/models/concerns/storage/legacy_namespace.rb
index 9785011720a..af699eeebce 100644
--- a/app/models/concerns/storage/legacy_namespace.rb
+++ b/app/models/concerns/storage/legacy_namespace.rb
@@ -5,8 +5,10 @@ module Storage
extend ActiveSupport::Concern
def move_dir
- if any_project_has_container_registry_tags?
- raise Gitlab::UpdatePathError.new('Namespace cannot be moved, because at least one project has tags in container registry')
+ proj_with_tags = first_project_with_container_registry_tags
+
+ if proj_with_tags
+ raise Gitlab::UpdatePathError.new("Namespace #{name} (#{id}) cannot be moved because at least one project (e.g. #{proj_with_tags.name} (#{proj_with_tags.id})) has tags in container registry")
end
parent_was = if parent_changed? && parent_id_was.present?
@@ -92,7 +94,7 @@ module Storage
if gitlab_shell.mv_namespace(repository_storage, full_path, new_path)
Gitlab::AppLogger.info %Q(Namespace directory "#{full_path}" moved to "#{new_path}")
- # Remove namespace directroy async with delay so
+ # Remove namespace directory async with delay so
# GitLab has time to remove all projects first
run_after_commit do
GitlabShellWorker.perform_in(5.minutes, :rm_namespace, repository_storage, new_path)
diff --git a/app/models/concerns/subscribable.rb b/app/models/concerns/subscribable.rb
index 1d0a61364b0..92a5c1112af 100644
--- a/app/models/concerns/subscribable.rb
+++ b/app/models/concerns/subscribable.rb
@@ -31,9 +31,11 @@ module Subscribable
end
def subscribers(project)
- subscriptions_available(project)
- .where(subscribed: true)
- .map(&:user)
+ relation = subscriptions_available(project)
+ .where(subscribed: true)
+ .select(:user_id)
+
+ User.where(id: relation)
end
def toggle_subscription(user, project = nil)
diff --git a/app/models/concerns/token_authenticatable.rb b/app/models/concerns/token_authenticatable.rb
index 522b65e4205..be930b6197a 100644
--- a/app/models/concerns/token_authenticatable.rb
+++ b/app/models/concerns/token_authenticatable.rb
@@ -5,57 +5,58 @@ module TokenAuthenticatable
private
- def write_new_token(token_field)
- new_token = generate_available_token(token_field)
- write_attribute(token_field, new_token)
- end
-
- def generate_available_token(token_field)
- loop do
- token = generate_token(token_field)
- break token unless self.class.unscoped.find_by(token_field => token)
- end
- end
-
- def generate_token(token_field)
- Devise.friendly_token
- end
-
class_methods do
- def authentication_token_fields
- @token_fields || []
- end
-
private # rubocop:disable Lint/UselessAccessModifier
- def add_authentication_token_field(token_field)
+ def add_authentication_token_field(token_field, options = {})
@token_fields = [] unless @token_fields
+ unique = options.fetch(:unique, true)
+
+ if @token_fields.include?(token_field)
+ raise ArgumentError.new("#{token_field} already configured via add_authentication_token_field")
+ end
+
@token_fields << token_field
- define_singleton_method("find_by_#{token_field}") do |token|
- find_by(token_field => token) if token
+ attr_accessor :cleartext_tokens
+
+ strategy = if options[:digest]
+ TokenAuthenticatableStrategies::Digest.new(self, token_field, options)
+ else
+ TokenAuthenticatableStrategies::Insecure.new(self, token_field, options)
+ end
+
+ if unique
+ define_singleton_method("find_by_#{token_field}") do |token|
+ strategy.find_token_authenticatable(token)
+ end
end
- define_method("ensure_#{token_field}") do
- current_token = read_attribute(token_field)
- current_token.blank? ? write_new_token(token_field) : current_token
+ define_method(token_field) do
+ strategy.get_token(self)
end
define_method("set_#{token_field}") do |token|
- write_attribute(token_field, token) if token
+ strategy.set_token(self, token)
+ end
+
+ define_method("ensure_#{token_field}") do
+ strategy.ensure_token(self)
end
# Returns a token, but only saves when the database is in read & write mode
define_method("ensure_#{token_field}!") do
- send("reset_#{token_field}!") if read_attribute(token_field).blank? # rubocop:disable GitlabSecurity/PublicSend
-
- read_attribute(token_field)
+ strategy.ensure_token!(self)
end
# Resets the token, but only saves when the database is in read & write mode
define_method("reset_#{token_field}!") do
- write_new_token(token_field)
- save! if Gitlab::Database.read_write?
+ strategy.reset_token!(self)
+ end
+
+ define_method("#{token_field}_matches?") do |other_token|
+ token = read_attribute(token_field)
+ token.present? && ActiveSupport::SecurityUtils.variable_size_secure_compare(other_token, token)
end
end
end
diff --git a/app/models/concerns/token_authenticatable_strategies/base.rb b/app/models/concerns/token_authenticatable_strategies/base.rb
new file mode 100644
index 00000000000..413721d3e6c
--- /dev/null
+++ b/app/models/concerns/token_authenticatable_strategies/base.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+module TokenAuthenticatableStrategies
+ class Base
+ def initialize(klass, token_field, options)
+ @klass = klass
+ @token_field = token_field
+ @options = options
+ end
+
+ def find_token_authenticatable(instance, unscoped = false)
+ raise NotImplementedError
+ end
+
+ def get_token(instance)
+ raise NotImplementedError
+ end
+
+ def set_token(instance)
+ raise NotImplementedError
+ end
+
+ def ensure_token(instance)
+ write_new_token(instance) unless token_set?(instance)
+ end
+
+ # Returns a token, but only saves when the database is in read & write mode
+ def ensure_token!(instance)
+ reset_token!(instance) unless token_set?(instance)
+ get_token(instance)
+ end
+
+ # Resets the token, but only saves when the database is in read & write mode
+ def reset_token!(instance)
+ write_new_token(instance)
+ instance.save! if Gitlab::Database.read_write?
+ end
+
+ protected
+
+ def write_new_token(instance)
+ new_token = generate_available_token
+ set_token(instance, new_token)
+ end
+
+ def unique
+ @options.fetch(:unique, true)
+ end
+
+ def generate_available_token
+ loop do
+ token = generate_token
+ break token unless unique && find_token_authenticatable(token, true)
+ end
+ end
+
+ def generate_token
+ @options[:token_generator] ? @options[:token_generator].call : Devise.friendly_token
+ end
+
+ def relation(unscoped)
+ unscoped ? @klass.unscoped : @klass
+ end
+
+ def token_set?(instance)
+ raise NotImplementedError
+ end
+
+ def token_field_name
+ @token_field
+ end
+ end
+end
diff --git a/app/models/concerns/token_authenticatable_strategies/digest.rb b/app/models/concerns/token_authenticatable_strategies/digest.rb
new file mode 100644
index 00000000000..9926662ed66
--- /dev/null
+++ b/app/models/concerns/token_authenticatable_strategies/digest.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module TokenAuthenticatableStrategies
+ class Digest < Base
+ def find_token_authenticatable(token, unscoped = false)
+ return unless token
+
+ token_authenticatable = relation(unscoped).find_by(token_field_name => Gitlab::CryptoHelper.sha256(token))
+
+ if @options[:fallback]
+ token_authenticatable ||= fallback_strategy.find_token_authenticatable(token)
+ end
+
+ token_authenticatable
+ end
+
+ def get_token(instance)
+ token = instance.cleartext_tokens&.[](@token_field)
+ token ||= fallback_strategy.get_token(instance) if @options[:fallback]
+
+ token
+ end
+
+ def set_token(instance, token)
+ return unless token
+
+ instance.cleartext_tokens ||= {}
+ instance.cleartext_tokens[@token_field] = token
+ instance[token_field_name] = Gitlab::CryptoHelper.sha256(token)
+ instance[@token_field] = nil if @options[:fallback]
+ end
+
+ protected
+
+ def fallback_strategy
+ @fallback_strategy ||= TokenAuthenticatableStrategies::Insecure.new(@klass, @token_field, @options)
+ end
+
+ def token_set?(instance)
+ token_digest = instance.read_attribute(token_field_name)
+ token_digest ||= instance.read_attribute(@token_field) if @options[:fallback]
+
+ token_digest.present?
+ end
+
+ def token_field_name
+ "#{@token_field}_digest"
+ end
+ end
+end
diff --git a/app/models/concerns/token_authenticatable_strategies/insecure.rb b/app/models/concerns/token_authenticatable_strategies/insecure.rb
new file mode 100644
index 00000000000..5f915259521
--- /dev/null
+++ b/app/models/concerns/token_authenticatable_strategies/insecure.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module TokenAuthenticatableStrategies
+ class Insecure < Base
+ def find_token_authenticatable(token, unscoped = false)
+ relation(unscoped).find_by(@token_field => token) if token
+ end
+
+ def get_token(instance)
+ instance.read_attribute(@token_field)
+ end
+
+ def set_token(instance, token)
+ instance[@token_field] = token if token
+ end
+
+ protected
+
+ def token_set?(instance)
+ instance.read_attribute(@token_field).present?
+ end
+ end
+end
diff --git a/app/models/concerns/with_uploads.rb b/app/models/concerns/with_uploads.rb
index e231af5368d..2bdef2a40e4 100644
--- a/app/models/concerns/with_uploads.rb
+++ b/app/models/concerns/with_uploads.rb
@@ -2,7 +2,7 @@
# Mounted uploaders are destroyed by carrierwave's after_commit
# hook. This hook fetches upload location (local vs remote) from
-# Upload model. So it's neccessary to make sure that during that
+# Upload model. So it's necessary to make sure that during that
# after_commit hook model's associated uploads are not deleted yet.
# IOW we can not use dependent: :destroy :
# has_many :uploads, as: :model, dependent: :destroy
diff --git a/app/models/deploy_token.rb b/app/models/deploy_token.rb
index 0b2eedf3631..e3524305346 100644
--- a/app/models/deploy_token.rb
+++ b/app/models/deploy_token.rb
@@ -4,6 +4,7 @@ class DeployToken < ActiveRecord::Base
include Expirable
include TokenAuthenticatable
include PolicyActor
+ include Gitlab::Utils::StrongMemoize
add_authentication_token_field :token
AVAILABLE_SCOPES = %i(read_repository read_registry).freeze
@@ -49,7 +50,9 @@ class DeployToken < ActiveRecord::Base
# to a single project, later we're going to extend
# that to be for multiple projects and namespaces.
def project
- projects.first
+ strong_memoize(:project) do
+ projects.first
+ end
end
def expires_at
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index 6962b54441b..811e623b7f7 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -3,21 +3,68 @@
class Deployment < ActiveRecord::Base
include AtomicInternalId
include IidRoutes
+ include AfterCommitQueue
belongs_to :project, required: true
belongs_to :environment, required: true
belongs_to :user
belongs_to :deployable, polymorphic: true # rubocop:disable Cop/PolymorphicAssociations
- has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.deployments&.maximum(:iid) }
+ has_internal_id :iid, scope: :project, init: ->(s) do
+ Deployment.where(project: s.project).maximum(:iid) if s&.project
+ end
validates :sha, presence: true
validates :ref, presence: true
delegate :name, to: :environment, prefix: true
- after_create :create_ref
- after_create :invalidate_cache
+ scope :for_environment, -> (environment) { where(environment_id: environment) }
+
+ state_machine :status, initial: :created do
+ event :run do
+ transition created: :running
+ end
+
+ event :succeed do
+ transition any - [:success] => :success
+ end
+
+ event :drop do
+ transition any - [:failed] => :failed
+ end
+
+ event :cancel do
+ transition any - [:canceled] => :canceled
+ end
+
+ before_transition any => [:success, :failed, :canceled] do |deployment|
+ deployment.finished_at = Time.now
+ end
+
+ after_transition any => :success do |deployment|
+ deployment.run_after_commit do
+ Deployments::SuccessWorker.perform_async(id)
+ end
+ end
+ end
+
+ enum status: {
+ created: 0,
+ running: 1,
+ success: 2,
+ failed: 3,
+ canceled: 4
+ }
+
+ def self.last_for_environment(environment)
+ ids = self
+ .for_environment(environment)
+ .select('MAX(id) AS id')
+ .group(:environment_id)
+ .map(&:id)
+ find(ids)
+ end
def commit
project.commit(sha)
@@ -44,7 +91,11 @@ class Deployment < ActiveRecord::Base
end
def manual_actions
- @manual_actions ||= deployable.try(:other_actions)
+ @manual_actions ||= deployable.try(:other_manual_actions)
+ end
+
+ def scheduled_actions
+ @scheduled_actions ||= deployable.try(:other_scheduled_actions)
end
def includes_commit?(commit)
@@ -54,15 +105,15 @@ class Deployment < ActiveRecord::Base
end
def update_merge_request_metrics!
- return unless environment.update_merge_request_metrics?
+ return unless environment.update_merge_request_metrics? && success?
merge_requests = project.merge_requests
.joins(:metrics)
.where(target_branch: self.ref, merge_request_metrics: { first_deployed_to_production_at: nil })
- .where("merge_request_metrics.merged_at <= ?", self.created_at)
+ .where("merge_request_metrics.merged_at <= ?", finished_at)
if previous_deployment
- merge_requests = merge_requests.where("merge_request_metrics.merged_at >= ?", previous_deployment.created_at)
+ merge_requests = merge_requests.where("merge_request_metrics.merged_at >= ?", previous_deployment.finished_at)
end
# Need to use `map` instead of `select` because MySQL doesn't allow `SELECT`ing from the same table
@@ -76,7 +127,7 @@ class Deployment < ActiveRecord::Base
MergeRequest::Metrics
.where(merge_request_id: merge_request_ids, first_deployed_to_production_at: nil)
- .update_all(first_deployed_to_production_at: self.created_at)
+ .update_all(first_deployed_to_production_at: finished_at)
end
def previous_deployment
@@ -94,26 +145,36 @@ class Deployment < ActiveRecord::Base
@stop_action ||= manual_actions.find_by(name: on_stop)
end
+ def finished_at
+ read_attribute(:finished_at) || legacy_finished_at
+ end
+
+ def deployed_at
+ return unless success?
+
+ finished_at
+ end
+
def formatted_deployment_time
- created_at.to_time.in_time_zone.to_s(:medium)
+ deployed_at&.to_time&.in_time_zone&.to_s(:medium)
end
def has_metrics?
- prometheus_adapter&.can_query?
+ prometheus_adapter&.can_query? && success?
end
def metrics
return {} unless has_metrics?
metrics = prometheus_adapter.query(:deployment, self)
- metrics&.merge(deployment_time: created_at.to_i) || {}
+ metrics&.merge(deployment_time: finished_at.to_i) || {}
end
def additional_metrics
return {} unless has_metrics?
metrics = prometheus_adapter.query(:additional_metrics_deployment, self)
- metrics&.merge(deployment_time: created_at.to_i) || {}
+ metrics&.merge(deployment_time: finished_at.to_i) || {}
end
private
@@ -125,4 +186,8 @@ class Deployment < ActiveRecord::Base
def ref_path
File.join(environment.ref_path, 'deployments', iid.to_s)
end
+
+ def legacy_finished_at
+ self.created_at if success? && !read_attribute(:finished_at)
+ end
end
diff --git a/app/models/diff_note.rb b/app/models/diff_note.rb
index 047d353b4b5..c32008aa9c7 100644
--- a/app/models/diff_note.rb
+++ b/app/models/diff_note.rb
@@ -5,24 +5,21 @@
# A note of this type can be resolvable.
class DiffNote < Note
include NoteOnDiff
+ include DiffPositionableNote
include Gitlab::Utils::StrongMemoize
- NOTEABLE_TYPES = %w(MergeRequest Commit).freeze
-
- serialize :original_position, Gitlab::Diff::Position # rubocop:disable Cop/ActiveRecordSerialize
- serialize :position, Gitlab::Diff::Position # rubocop:disable Cop/ActiveRecordSerialize
- serialize :change_position, Gitlab::Diff::Position # rubocop:disable Cop/ActiveRecordSerialize
+ def self.noteable_types
+ %w(MergeRequest Commit)
+ end
validates :original_position, presence: true
validates :position, presence: true
validates :line_code, presence: true, line_code: true, if: :on_text?
- validates :noteable_type, inclusion: { in: NOTEABLE_TYPES }
+ validates :noteable_type, inclusion: { in: noteable_types }
validate :positions_complete
validate :verify_supported
validate :diff_refs_match_commit, if: :for_commit?
- before_validation :set_original_position, on: :create
- before_validation :update_position, on: :create, if: :on_text?
before_validation :set_line_code, if: :on_text?
after_save :keep_around_commits
after_commit :create_diff_file, on: :create
@@ -31,31 +28,6 @@ class DiffNote < Note
DiffDiscussion
end
- %i(original_position position change_position).each do |meth|
- define_method "#{meth}=" do |new_position|
- if new_position.is_a?(String)
- new_position = JSON.parse(new_position) rescue nil
- end
-
- if new_position.is_a?(Hash)
- new_position = new_position.with_indifferent_access
- new_position = Gitlab::Diff::Position.new(new_position)
- end
-
- return if new_position == read_attribute(meth)
-
- super(new_position)
- end
- end
-
- def on_text?
- position.position_type == "text"
- end
-
- def on_image?
- position.position_type == "image"
- end
-
def create_diff_file
return unless should_create_diff_file?
@@ -87,15 +59,6 @@ class DiffNote < Note
self.diff_file.line_code(self.diff_line)
end
- def active?(diff_refs = nil)
- return false unless supported?
- return true if for_commit?
-
- diff_refs ||= noteable.diff_refs
-
- self.position.diff_refs == diff_refs
- end
-
def created_at_diff?(diff_refs)
return false unless supported?
return true if for_commit?
@@ -103,6 +66,10 @@ class DiffNote < Note
self.original_position.diff_refs == diff_refs
end
+ def discussion_first_note?
+ self == discussion.first_note
+ end
+
private
def enqueue_diff_file_creation_job
@@ -115,63 +82,43 @@ class DiffNote < Note
end
def should_create_diff_file?
- on_text? && note_diff_file.nil? && self == discussion.first_note
+ on_text? && note_diff_file.nil? && discussion_first_note?
end
def fetch_diff_file
- if note_diff_file
- diff = Gitlab::Git::Diff.new(note_diff_file.to_hash)
- Gitlab::Diff::File.new(diff,
- repository: project.repository,
- diff_refs: original_position.diff_refs)
- elsif created_at_diff?(noteable.diff_refs)
- # We're able to use the already persisted diffs (Postgres) if we're
- # presenting a "current version" of the MR discussion diff.
- # So no need to make an extra Gitaly diff request for it.
- # As an extra benefit, the returned `diff_file` already
- # has `highlighted_diff_lines` data set from Redis on
- # `Diff::FileCollection::MergeRequestDiff`.
- noteable.diffs(original_position.diff_options).diff_files.first
- else
- original_position.diff_file(self.project.repository)
- end
+ file =
+ if note_diff_file
+ diff = Gitlab::Git::Diff.new(note_diff_file.to_hash)
+ Gitlab::Diff::File.new(diff,
+ repository: project.repository,
+ diff_refs: original_position.diff_refs)
+ elsif created_at_diff?(noteable.diff_refs)
+ # We're able to use the already persisted diffs (Postgres) if we're
+ # presenting a "current version" of the MR discussion diff.
+ # So no need to make an extra Gitaly diff request for it.
+ # As an extra benefit, the returned `diff_file` already
+ # has `highlighted_diff_lines` data set from Redis on
+ # `Diff::FileCollection::MergeRequestDiff`.
+ noteable.diffs(original_position.diff_options).diff_files.first
+ else
+ original_position.diff_file(self.project.repository)
+ end
+
+ # Since persisted diff files already have its content "unfolded"
+ # there's no need to make it pass through the unfolding process.
+ file&.unfold_diff_lines(position) unless note_diff_file
+
+ file
end
def supported?
for_commit? || self.noteable.has_complete_diff_refs?
end
- def set_original_position
- self.original_position = self.position.dup unless self.original_position&.complete?
- end
-
def set_line_code
self.line_code = self.position.line_code(self.project.repository)
end
- def update_position
- return unless supported?
- return if for_commit?
-
- return if active?
-
- tracer = Gitlab::Diff::PositionTracer.new(
- project: self.project,
- old_diff_refs: self.position.diff_refs,
- new_diff_refs: self.noteable.diff_refs,
- paths: self.position.paths
- )
-
- result = tracer.trace(self.position)
- return unless result
-
- if result[:outdated]
- self.change_position = result[:position]
- else
- self.position = result[:position]
- end
- end
-
def verify_supported
return if supported?
diff --git a/app/models/discussion_note.rb b/app/models/discussion_note.rb
index 89d86aaed66..142cbdcdfa6 100644
--- a/app/models/discussion_note.rb
+++ b/app/models/discussion_note.rb
@@ -5,9 +5,11 @@
# A note of this type can be resolvable.
class DiscussionNote < Note
# Names of all implementers of `Noteable` that support discussions.
- NOTEABLE_TYPES = %w(MergeRequest Issue Commit Snippet).freeze
+ def self.noteable_types
+ %w(MergeRequest Issue Commit Snippet)
+ end
- validates :noteable_type, inclusion: { in: NOTEABLE_TYPES }
+ validates :noteable_type, inclusion: { in: noteable_types }
def discussion_class(*)
Discussion
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 309bd4f37c9..934828946b9 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -8,9 +8,9 @@ class Environment < ActiveRecord::Base
belongs_to :project, required: true
- has_many :deployments, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_many :deployments, -> { success }, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
- has_one :last_deployment, -> { order('deployments.id DESC') }, class_name: 'Deployment'
+ has_one :last_deployment, -> { success.order('deployments.id DESC') }, class_name: 'Deployment'
before_validation :nullify_external_url
before_validation :generate_slug, if: ->(env) { env.slug.blank? }
@@ -48,6 +48,9 @@ class Environment < ActiveRecord::Base
order(Gitlab::Database.nulls_first_order("(#{max_deployment_id_sql})", 'ASC'))
end
scope :in_review_folder, -> { where(environment_type: "review") }
+ scope :for_name, -> (name) { where(name: name) }
+ scope :for_project, -> (project) { where(project_id: project) }
+ scope :with_deployment, -> (sha) { where('EXISTS (?)', Deployment.select(1).where('deployments.environment_id = environments.id').where(sha: sha)) }
state_machine :state, initial: :available do
event :start do
@@ -147,7 +150,7 @@ class Environment < ActiveRecord::Base
end
def has_metrics?
- prometheus_adapter&.can_query? && available? && last_deployment.present?
+ prometheus_adapter&.can_query? && available?
end
def metrics
diff --git a/app/models/environment_status.rb b/app/models/environment_status.rb
new file mode 100644
index 00000000000..2fb6cadc8cd
--- /dev/null
+++ b/app/models/environment_status.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+class EnvironmentStatus
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :environment, :merge_request, :sha
+
+ delegate :id, to: :environment
+ delegate :name, to: :environment
+ delegate :project, to: :environment
+ delegate :status, to: :deployment, allow_nil: true
+ delegate :deployed_at, to: :deployment, allow_nil: true
+
+ def self.for_merge_request(mr, user)
+ build_environments_status(mr, user, mr.actual_head_pipeline)
+ end
+
+ def self.after_merge_request(mr, user)
+ return [] unless mr.merged?
+
+ build_environments_status(mr, user, mr.merge_pipeline)
+ end
+
+ def initialize(environment, merge_request, sha)
+ @environment = environment
+ @merge_request = merge_request
+ @sha = sha
+ end
+
+ def deployment
+ strong_memoize(:deployment) do
+ Deployment.where(environment: environment).find_by_sha(sha)
+ end
+ end
+
+ def changes
+ return [] if project.route_map_for(sha).nil?
+
+ changed_files.map { |file| build_change(file) }.compact
+ end
+
+ def changed_files
+ merge_request.merge_request_diff
+ .merge_request_diff_files.where(deleted_file: false)
+ end
+
+ private
+
+ PAGE_EXTENSIONS = /\A\.(s?html?|php|asp|cgi|pl)\z/i.freeze
+
+ def build_change(file)
+ public_path = project.public_path_for_source_path(file.new_path, sha)
+ return if public_path.nil?
+
+ ext = File.extname(public_path)
+ return if ext.present? && ext !~ PAGE_EXTENSIONS
+
+ {
+ path: public_path,
+ external_url: environment.external_url_for(file.new_path, sha)
+ }
+ end
+
+ def self.build_environments_status(mr, user, pipeline)
+ return [] unless pipeline
+
+ pipeline.environments.available.map do |environment|
+ next unless Ability.allowed?(user, :read_environment, environment)
+
+ EnvironmentStatus.new(environment, mr, pipeline.sha)
+ end.compact
+ end
+ private_class_method :build_environments_status
+end
diff --git a/app/models/event.rb b/app/models/event.rb
index 596155a9525..2e690f8c013 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -148,6 +148,8 @@ class Event < ActiveRecord::Base
end
end
+ # rubocop:disable Metrics/CyclomaticComplexity
+ # rubocop:disable Metrics/PerceivedComplexity
def visible_to_user?(user = nil)
if push? || commit_note?
Ability.allowed?(user, :download_code, project)
@@ -159,12 +161,18 @@ class Event < ActiveRecord::Base
Ability.allowed?(user, :read_issue, note? ? note_target : target)
elsif merge_request? || merge_request_note?
Ability.allowed?(user, :read_merge_request, note? ? note_target : target)
+ elsif personal_snippet_note?
+ Ability.allowed?(user, :read_personal_snippet, note_target)
+ elsif project_snippet_note?
+ Ability.allowed?(user, :read_project_snippet, note_target)
elsif milestone?
- Ability.allowed?(user, :read_project, project)
+ Ability.allowed?(user, :read_milestone, project)
else
false # No other event types are visible
end
end
+ # rubocop:enable Metrics/PerceivedComplexity
+ # rubocop:enable Metrics/CyclomaticComplexity
def project_name
if project
@@ -306,6 +314,10 @@ class Event < ActiveRecord::Base
note? && target && target.for_snippet?
end
+ def personal_snippet_note?
+ note? && target && target.for_personal_snippet?
+ end
+
def note_target
target.noteable
end
diff --git a/app/models/forked_project_link.rb b/app/models/forked_project_link.rb
deleted file mode 100644
index 0f7067238cd..00000000000
--- a/app/models/forked_project_link.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# frozen_string_literal: true
-
-class ForkedProjectLink < ActiveRecord::Base
- belongs_to :forked_to_project, -> { where.not(pending_delete: true) }, class_name: 'Project'
- belongs_to :forked_from_project, -> { where.not(pending_delete: true) }, class_name: 'Project'
-end
diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb
index a6cebabe089..085ffd16c6a 100644
--- a/app/models/global_milestone.rb
+++ b/app/models/global_milestone.rb
@@ -34,50 +34,6 @@ class GlobalMilestone
new(title, child_milestones)
end
- def self.states_count(projects, group = nil)
- legacy_group_milestones_count = legacy_group_milestone_states_count(projects)
- group_milestones_count = group_milestones_states_count(group)
-
- legacy_group_milestones_count.merge(group_milestones_count) do |k, legacy_group_milestones_count, group_milestones_count|
- legacy_group_milestones_count + group_milestones_count
- end
- end
-
- def self.group_milestones_states_count(group)
- return STATE_COUNT_HASH unless group
-
- params = { group_ids: [group.id], state: 'all' }
-
- relation = MilestonesFinder.new(params).execute # rubocop: disable CodeReuse/Finder
- grouped_by_state = relation.reorder(nil).group(:state).count
-
- {
- opened: grouped_by_state['active'] || 0,
- closed: grouped_by_state['closed'] || 0,
- all: grouped_by_state.values.sum
- }
- end
-
- # Counts the legacy group milestones which must be grouped by title
- def self.legacy_group_milestone_states_count(projects)
- return STATE_COUNT_HASH unless projects
-
- params = { project_ids: projects.map(&:id), state: 'all' }
-
- relation = MilestonesFinder.new(params).execute # rubocop: disable CodeReuse/Finder
- project_milestones_by_state_and_title = relation.reorder(nil).group(:state, :title).count
-
- opened = count_by_state(project_milestones_by_state_and_title, 'active')
- closed = count_by_state(project_milestones_by_state_and_title, 'closed')
- all = project_milestones_by_state_and_title.map { |(_, title), _| title }.uniq.count
-
- {
- opened: opened,
- closed: closed,
- all: all
- }
- end
-
def self.count_by_state(milestones_by_state_and_title, state)
milestones_by_state_and_title.count do |(milestone_state, _), _|
milestone_state == state
diff --git a/app/models/group.rb b/app/models/group.rb
index 62af20d2142..adb9169cfcd 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -41,6 +41,9 @@ class Group < Namespace
has_many :boards
has_many :badges, class_name: 'GroupBadge'
+ has_many :cluster_groups, class_name: 'Clusters::Group'
+ has_many :clusters, through: :cluster_groups, class_name: 'Clusters::Cluster'
+
has_many :todos
accepts_nested_attributes_for :variables, allow_destroy: true
@@ -82,8 +85,17 @@ class Group < Namespace
User.reference_pattern
end
- def visible_to_user(user)
- where(id: user.authorized_groups.select(:id).reorder(nil))
+ # WARNING: This method should never be used on its own
+ # please do make sure the number of rows you are filtering is small
+ # enough for this query
+ def public_or_visible_to_user(user)
+ return public_to_user unless user
+
+ public_for_user = public_to_user_arel(user)
+ visible_for_user = visible_to_user_arel(user)
+ public_or_visible = public_for_user.or(visible_for_user)
+
+ where(public_or_visible)
end
def select_for_project_authorization
@@ -95,6 +107,23 @@ class Group < Namespace
super
end
end
+
+ private
+
+ def public_to_user_arel(user)
+ self.arel_table[:visibility_level]
+ .in(Gitlab::VisibilityLevel.levels_for_user(user))
+ end
+
+ def visible_to_user_arel(user)
+ groups_table = self.arel_table
+ authorized_groups = user.authorized_groups.as('authorized')
+
+ groups_table.project(1)
+ .from(authorized_groups)
+ .where(authorized_groups[:id].eq(groups_table[:id]))
+ .exists
+ end
end
# Overrides notification_settings has_many association
@@ -340,7 +369,7 @@ class Group < Namespace
}
end
- def secret_variables_for(ref, project)
+ def ci_variables_for(ref, project)
list_of_ids = [self] + ancestors
variables = Ci::GroupVariable.where(group: list_of_ids)
variables = variables.unprotected unless project.protected_for?(ref)
diff --git a/app/models/hooks/service_hook.rb b/app/models/hooks/service_hook.rb
index 7d9f6d89d44..8f305dd7c22 100644
--- a/app/models/hooks/service_hook.rb
+++ b/app/models/hooks/service_hook.rb
@@ -5,8 +5,8 @@ class ServiceHook < WebHook
validates :service, presence: true
# rubocop: disable CodeReuse/ServiceClass
- def execute(data)
- WebHookService.new(self, data, 'service_hook').execute
+ def execute(data, hook_name = 'service_hook')
+ WebHookService.new(self, data, hook_name).execute
end
# rubocop: enable CodeReuse/ServiceClass
end
diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb
index 771a61b090f..b2fb79bc7ed 100644
--- a/app/models/hooks/web_hook.rb
+++ b/app/models/hooks/web_hook.rb
@@ -3,6 +3,16 @@
class WebHook < ActiveRecord::Base
include Sortable
+ attr_encrypted :token,
+ mode: :per_attribute_iv,
+ algorithm: 'aes-256-gcm',
+ key: Settings.attr_encrypted_db_key_base_truncated
+
+ attr_encrypted :url,
+ mode: :per_attribute_iv,
+ algorithm: 'aes-256-gcm',
+ key: Settings.attr_encrypted_db_key_base_truncated
+
has_many :web_hook_logs, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
validates :url, presence: true, public_url: { allow_localhost: lambda(&:allow_local_requests?),
diff --git a/app/models/identity.rb b/app/models/identity.rb
index f5a13dbd6f2..d63dd432426 100644
--- a/app/models/identity.rb
+++ b/app/models/identity.rb
@@ -1,18 +1,14 @@
# frozen_string_literal: true
class Identity < ActiveRecord::Base
- def self.uniqueness_scope
- :provider
- end
-
include Sortable
include CaseSensitivity
belongs_to :user
validates :provider, presence: true
- validates :extern_uid, allow_blank: true, uniqueness: { scope: uniqueness_scope, case_sensitive: false }
- validates :user_id, uniqueness: { scope: uniqueness_scope }
+ validates :extern_uid, allow_blank: true, uniqueness: { scope: UniquenessScopes.scopes, case_sensitive: false }
+ validates :user_id, uniqueness: { scope: UniquenessScopes.scopes }
before_save :ensure_normalized_extern_uid, if: :extern_uid_changed?
after_destroy :clear_user_synced_attributes, if: :user_synced_attributes_metadata_from_provider?
diff --git a/app/models/identity/uniqueness_scopes.rb b/app/models/identity/uniqueness_scopes.rb
new file mode 100644
index 00000000000..674b735903f
--- /dev/null
+++ b/app/models/identity/uniqueness_scopes.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class Identity < ActiveRecord::Base
+ # This module and method are defined in a separate file to allow EE to
+ # redefine the `scopes` method before it is used in the `Identity` model.
+ module UniquenessScopes
+ def self.scopes
+ [:provider]
+ end
+ end
+end
diff --git a/app/models/instance_configuration.rb b/app/models/instance_configuration.rb
index 7d8ce0bbd05..11289887e00 100644
--- a/app/models/instance_configuration.rb
+++ b/app/models/instance_configuration.rb
@@ -64,10 +64,10 @@ class InstanceConfiguration
end
def ssh_algorithm_md5(ssh_file_content)
- OpenSSL::Digest::MD5.hexdigest(ssh_file_content).scan(/../).join(':')
+ Gitlab::SSHPublicKey.new(ssh_file_content).fingerprint
end
def ssh_algorithm_sha256(ssh_file_content)
- OpenSSL::Digest::SHA256.hexdigest(ssh_file_content)
+ Gitlab::SSHPublicKey.new(ssh_file_content).fingerprint('SHA256')
end
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index d13fbcf002c..780035c77e2 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -99,6 +99,10 @@ class Issue < ActiveRecord::Base
alias_method :in_parents, :in_projects
end
+ def self.parent_column
+ :project_id
+ end
+
def self.reference_prefix
'#'
end
@@ -170,24 +174,6 @@ class Issue < ActiveRecord::Base
"#{project.to_reference(from, full: full)}#{reference}"
end
- # All branches containing the current issue's ID, except for
- # those with a merge request open referencing the current issue.
- # rubocop: disable CodeReuse/ServiceClass
- def related_branches(current_user)
- branches_with_iid = project.repository.branch_names.select do |branch|
- branch =~ /\A#{iid}-(?!\d+-stable)/i
- end
-
- branches_with_merge_request =
- Issues::ReferencedMergeRequestsService
- .new(project, current_user)
- .referenced_merge_requests(self)
- .map(&:source_branch)
-
- branches_with_iid - branches_with_merge_request
- end
- # rubocop: enable CodeReuse/ServiceClass
-
def suggested_branch_name
return to_branch_name unless project.repository.branch_exists?(to_branch_name)
@@ -258,7 +244,8 @@ class Issue < ActiveRecord::Base
reference_path: issue_reference,
real_path: url_helper.project_issue_path(project, self),
issue_sidebar_endpoint: url_helper.project_issue_path(project, self, format: :json, serializer: 'sidebar'),
- toggle_subscription_endpoint: url_helper.toggle_subscription_project_issue_path(project, self)
+ toggle_subscription_endpoint: url_helper.toggle_subscription_project_issue_path(project, self),
+ assignable_labels_endpoint: url_helper.project_labels_path(project, format: :json, include_ancestor_groups: true)
)
end
diff --git a/app/models/key.rb b/app/models/key.rb
index bdb83e12793..8f93418b88b 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -34,6 +34,10 @@ class Key < ActiveRecord::Base
after_destroy :post_destroy_hook
after_destroy :refresh_user_cache
+ def self.regular_keys
+ where(type: ['Key', nil])
+ end
+
def key=(value)
write_attribute(:key, value.present? ? Gitlab::SSHPublicKey.sanitize(value) : nil)
diff --git a/app/models/label.rb b/app/models/label.rb
index 9ef57a05b3e..5d2d1afd1d9 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -9,15 +9,10 @@ class Label < ActiveRecord::Base
include Sortable
include FromUnion
- # Represents a "No Label" state used for filtering Issues and Merge
- # Requests that have no label assigned.
- LabelStruct = Struct.new(:title, :name)
- None = LabelStruct.new('No Label', 'No Label')
- Any = LabelStruct.new('Any Label', '')
-
cache_markdown_field :description, pipeline: :single_line
- DEFAULT_COLOR = '#428BCA'.freeze
+ DEFAULT_COLOR = '#428BCA'
+ NONE = 'no label'
default_value_for :color, DEFAULT_COLOR
@@ -41,10 +36,11 @@ class Label < ActiveRecord::Base
scope :templates, -> { where(template: true) }
scope :with_title, ->(title) { where(title: title) }
scope :with_lists_and_board, -> { joins(lists: :board).merge(List.movable) }
- scope :on_group_boards, ->(group_id) { with_lists_and_board.where(boards: { group_id: group_id }) }
scope :on_project_boards, ->(project_id) { with_lists_and_board.where(boards: { project_id: project_id }) }
+ scope :on_board, ->(board_id) { with_lists_and_board.where(boards: { id: board_id }) }
scope :order_name_asc, -> { reorder(title: :asc) }
scope :order_name_desc, -> { reorder(title: :desc) }
+ scope :subscribed_by, ->(user_id) { joins(:subscriptions).where(subscriptions: { user_id: user_id, subscribed: true }) }
def self.prioritized(project)
joins(:priorities)
@@ -74,6 +70,14 @@ class Label < ActiveRecord::Base
joins(label_priorities)
end
+ def self.optionally_subscribed_by(user_id)
+ if user_id
+ subscribed_by(user_id)
+ else
+ all
+ end
+ end
+
alias_attribute :name, :title
def self.reference_prefix
diff --git a/app/models/legacy_diff_note.rb b/app/models/legacy_diff_note.rb
index 20f9b18e4ca..00dec6bb92b 100644
--- a/app/models/legacy_diff_note.rb
+++ b/app/models/legacy_diff_note.rb
@@ -20,11 +20,7 @@ class LegacyDiffNote < Note
end
def project_repository
- if RequestStore.active?
- RequestStore.fetch("project:#{project_id}:repository") { self.project.repository }
- else
- self.project.repository
- end
+ Gitlab::SafeRequestStore.fetch("project:#{project_id}:repository") { self.project.repository }
end
def diff_file_hash
diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb
index 97bf5d611c2..69c563545bb 100644
--- a/app/models/lfs_object.rb
+++ b/app/models/lfs_object.rb
@@ -7,7 +7,7 @@ class LfsObject < ActiveRecord::Base
has_many :lfs_objects_projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :projects, through: :lfs_objects_projects
- scope :with_files_stored_locally, -> { where(file_store: [nil, LfsObjectUploader::Store::LOCAL]) }
+ scope :with_files_stored_locally, -> { where(file_store: LfsObjectUploader::Store::LOCAL) }
validates :oid, presence: true, uniqueness: true
@@ -26,7 +26,7 @@ class LfsObject < ActiveRecord::Base
end
def local_store?
- [nil, LfsObjectUploader::Store::LOCAL].include?(self.file_store)
+ file_store == LfsObjectUploader::Store::LOCAL
end
# rubocop: disable DestroyAll
diff --git a/app/models/license_template.rb b/app/models/license_template.rb
index 693a6a89fd2..73e403f98b4 100644
--- a/app/models/license_template.rb
+++ b/app/models/license_template.rb
@@ -12,12 +12,10 @@ class LicenseTemplate
(fullname|name\sof\s(author|copyright\sowner))
[\>\}\]]}xi.freeze
- attr_reader :id, :name, :category, :nickname, :url, :meta
+ attr_reader :key, :name, :category, :nickname, :url, :meta
- alias_method :key, :id
-
- def initialize(id:, name:, category:, content:, nickname: nil, url: nil, meta: {})
- @id = id
+ def initialize(key:, name:, category:, content:, nickname: nil, url: nil, meta: {})
+ @key = key
@name = name
@category = category
@content = content
diff --git a/app/models/list.rb b/app/models/list.rb
index 1a30acc83cf..029685be927 100644
--- a/app/models/list.rb
+++ b/app/models/list.rb
@@ -15,6 +15,7 @@ class List < ActiveRecord::Base
scope :destroyable, -> { where(list_type: list_types.slice(*destroyable_types).values) }
scope :movable, -> { where(list_type: list_types.slice(*movable_types).values) }
+ scope :preload_associations, -> { preload(:board, :label) }
class << self
def destroyable_types
diff --git a/app/models/member.rb b/app/models/member.rb
index 0696ea46c8b..bc8ac14d148 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -152,11 +152,13 @@ class Member < ActiveRecord::Base
return member unless can_update_member?(current_user, member)
- member.attributes = {
- created_by: member.created_by || current_user,
- access_level: access_level,
- expires_at: expires_at
- }
+ set_member_attributes(
+ member,
+ access_level,
+ current_user: current_user,
+ expires_at: expires_at,
+ ldap: ldap
+ )
if member.request?
::Members::ApproveAccessRequestService.new(
@@ -175,6 +177,18 @@ class Member < ActiveRecord::Base
# rubocop: enable CodeReuse/ServiceClass
end
+ # Populates the attributes of a member.
+ #
+ # This logic resides in a separate method so that EE can extend this logic,
+ # without having to patch the `add_user` method directly.
+ def set_member_attributes(member, access_level, current_user: nil, expires_at: nil, ldap: false)
+ member.attributes = {
+ created_by: member.created_by || current_user,
+ access_level: access_level,
+ expires_at: expires_at
+ }
+ end
+
def add_users(source, users, access_level, current_user: nil, expires_at: nil)
return [] unless users.present?
diff --git a/app/models/members_preloader.rb b/app/models/members_preloader.rb
new file mode 100644
index 00000000000..33855191ca8
--- /dev/null
+++ b/app/models/members_preloader.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class MembersPreloader
+ attr_reader :members
+
+ def initialize(members)
+ @members = members
+ end
+
+ def preload_all
+ ActiveRecord::Associations::Preloader.new.preload(members, :user)
+ ActiveRecord::Associations::Preloader.new.preload(members, :source)
+ ActiveRecord::Associations::Preloader.new.preload(members.map(&:user), :status)
+ ActiveRecord::Associations::Preloader.new.preload(members.map(&:user), :u2f_registrations)
+ end
+end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index dd5d494997d..92add079a02 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -6,6 +6,7 @@ class MergeRequest < ActiveRecord::Base
include Issuable
include Noteable
include Referable
+ include Presentable
include IgnorableColumn
include TimeTrackable
include ManualInverseAssociation
@@ -203,6 +204,12 @@ class MergeRequest < ActiveRecord::Base
head_pipeline&.sha == diff_head_sha ? head_pipeline : nil
end
+ def merge_pipeline
+ return unless merged?
+
+ target_project.pipeline_for(target_branch, merge_commit_sha)
+ end
+
# Pattern used to extract `!123` merge request references from text
#
# This pattern supports cross-project references.
@@ -260,7 +267,7 @@ class MergeRequest < ActiveRecord::Base
end
end
- WIP_REGEX = /\A\s*(\[WIP\]\s*|WIP:\s*|WIP\s+)+\s*/i.freeze
+ WIP_REGEX = /\A*(\[WIP\]\s*|WIP:\s*|WIP\s+)+\s*/i.freeze
def self.work_in_progress?(title)
!!(title =~ WIP_REGEX)
@@ -346,6 +353,15 @@ class MergeRequest < ActiveRecord::Base
end
end
+ # Returns true if there are commits that match at least one commit SHA.
+ def includes_any_commits?(shas)
+ if persisted?
+ merge_request_diff.commits_by_shas(shas).exists?
+ else
+ (commit_shas & shas).present?
+ end
+ end
+
# Calls `MergeWorker` to proceed with the merge process and
# updates `merge_jid` with the MergeWorker#jid.
# This helps tracking enqueued and ongoing merge jobs.
@@ -393,6 +409,18 @@ class MergeRequest < ActiveRecord::Base
merge_request_diff&.real_size || diffs.real_size
end
+ def modified_paths(past_merge_request_diff: nil)
+ diffs = if past_merge_request_diff
+ past_merge_request_diff
+ elsif compare
+ compare
+ else
+ self.merge_request_diff
+ end
+
+ diffs.modified_paths
+ end
+
def diff_base_commit
if persisted?
merge_request_diff.base_commit
@@ -938,7 +966,6 @@ class MergeRequest < ActiveRecord::Base
def mergeable_ci_state?
return true unless project.only_allow_merge_if_pipeline_succeeds?
- return true unless head_pipeline
actual_head_pipeline&.success? || actual_head_pipeline&.skipped?
end
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index 02c6b650f33..a3029a54604 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -6,6 +6,7 @@ class MergeRequestDiff < ActiveRecord::Base
include ManualInverseAssociation
include IgnorableColumn
include EachBatch
+ include Gitlab::Utils::StrongMemoize
# Don't display more than 100 commits at once
COMMITS_SAFE_SIZE = 100
@@ -140,6 +141,12 @@ class MergeRequestDiff < ActiveRecord::Base
merge_request_diff_commits.map(&:sha)
end
+ def commits_by_shas(shas)
+ return MergeRequestDiffCommit.none unless shas.present?
+
+ merge_request_diff_commits.where(sha: shas)
+ end
+
def diff_refs=(new_diff_refs)
self.base_commit_sha = new_diff_refs&.base_sha
self.start_commit_sha = new_diff_refs&.start_sha
@@ -228,6 +235,12 @@ class MergeRequestDiff < ActiveRecord::Base
end
# rubocop: enable CodeReuse/ServiceClass
+ def modified_paths
+ strong_memoize(:modified_paths) do
+ merge_request_diff_files.pluck(:new_path, :old_path).flatten.uniq
+ end
+ end
+
private
def create_merge_request_diff_files(diffs)
@@ -300,7 +313,8 @@ class MergeRequestDiff < ActiveRecord::Base
# merge_request_diff_commits.reload is preferred way to reload associated
# objects but it returns cached result for some reason in this case
- commits = merge_request_diff_commits(true)
+ # we can circumvent that by specifying that we need an uncached reload
+ commits = self.class.uncached { merge_request_diff_commits.reload }
self.commits_count = commits.size
end
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 892a680f221..3cc8e2c44bb 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -145,7 +145,7 @@ class Milestone < ActiveRecord::Base
end
def participants
- User.joins(assigned_issues: :milestone).where("milestones.id = ?", id).uniq
+ User.joins(assigned_issues: :milestone).where("milestones.id = ?", id).distinct
end
def self.sort_by_attribute(method)
@@ -170,6 +170,22 @@ class Milestone < ActiveRecord::Base
sorted.with_order_id_desc
end
+ def self.states_count(projects, groups = nil)
+ return STATE_COUNT_HASH unless projects || groups
+
+ counts = Milestone
+ .for_projects_and_groups(projects&.map(&:id), groups&.map(&:id))
+ .reorder(nil)
+ .group(:state)
+ .count
+
+ {
+ opened: counts['active'] || 0,
+ closed: counts['closed'] || 0,
+ all: counts.values.sum
+ }
+ end
+
##
# Returns the String necessary to reference this Milestone in Markdown. Group
# milestones only support name references, and do not support cross-project
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 0289f29211d..11b03846f0b 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -83,7 +83,7 @@ class Namespace < ActiveRecord::Base
find_by('lower(path) = :value', value: path.downcase)
end
- # Case insensetive search for namespace by path or name
+ # Case insensitive search for namespace by path or name
def find_by_path_or_name(path)
find_by("lower(path) = :path OR lower(name) = :path", path: path.downcase)
end
@@ -135,6 +135,10 @@ class Namespace < ActiveRecord::Base
all_projects.any?(&:has_container_registry_tags?)
end
+ def first_project_with_container_registry_tags
+ all_projects.find(&:has_container_registry_tags?)
+ end
+
def send_update_instructions
projects.each do |project|
project.send_move_instructions("#{full_path_was}/#{project.path}")
@@ -148,8 +152,8 @@ class Namespace < ActiveRecord::Base
def find_fork_of(project)
return nil unless project.fork_network
- if RequestStore.active?
- forks_in_namespace = RequestStore.fetch("namespaces:#{id}:forked_projects") do
+ if Gitlab::SafeRequestStore.active?
+ forks_in_namespace = Gitlab::SafeRequestStore.fetch("namespaces:#{id}:forked_projects") do
Hash.new do |found_forks, project|
found_forks[project] = project.fork_network.find_forks_in(projects).first
end
@@ -186,7 +190,7 @@ class Namespace < ActiveRecord::Base
.base_and_ancestors
end
- # returns all ancestors upto but excluding the the given namespace
+ # returns all ancestors upto but excluding the given namespace
# when no namespace is given, all ancestors upto the top are returned
def ancestors_upto(top = nil)
Gitlab::GroupHierarchy.new(self.class.where(id: id))
@@ -228,6 +232,12 @@ class Namespace < ActiveRecord::Base
Project.inside_path(full_path)
end
+ # Includes pipelines from this namespace and pipelines from all subgroups
+ # that belongs to this namespace
+ def all_pipelines
+ Ci::Pipeline.where(project: all_projects)
+ end
+
def has_parent?
parent.present?
end
diff --git a/app/models/note.rb b/app/models/note.rb
index bea02d69b65..a6ae4f58ac4 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -10,6 +10,7 @@ class Note < ActiveRecord::Base
include Awardable
include Importable
include FasterCacheKeys
+ include Redactable
include CacheMarkdownField
include AfterCommitQueue
include ResolvableNote
@@ -33,6 +34,8 @@ class Note < ActiveRecord::Base
cache_markdown_field :note, pipeline: :note, issuable_state_filter_enabled: true
+ redact_field :note
+
# Aliases to make application_helper#edited_time_ago_with_tooltip helper work properly with notes.
# See https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10392/diffs#note_28719102
alias_attribute :last_edited_at, :updated_at
@@ -42,8 +45,10 @@ class Note < ActiveRecord::Base
# Banzai::ObjectRenderer.
attr_accessor :redacted_note_html
- # An Array containing the number of visible references as generated by
- # Banzai::ObjectRenderer
+ # Total of all references as generated by Banzai::ObjectRenderer
+ attr_accessor :total_reference_count
+
+ # Number of user visible references as generated by Banzai::ObjectRenderer
attr_accessor :user_visible_reference_count
# Attribute used to store the attributes that have been changed by quick actions.
@@ -108,6 +113,17 @@ class Note < ActiveRecord::Base
:system_note_metadata, :note_diff_file)
end
+ scope :with_notes_filter, -> (notes_filter) do
+ case notes_filter
+ when UserPreference::NOTES_FILTERS[:only_comments]
+ user
+ when UserPreference::NOTES_FILTERS[:only_activity]
+ system
+ else
+ all
+ end
+ end
+
scope :diff_notes, -> { where(type: %w(LegacyDiffNote DiffNote)) }
scope :new_diff_notes, -> { where(type: 'DiffNote') }
scope :non_diff_notes, -> { where(type: ['Note', 'DiscussionNote', nil]) }
@@ -288,15 +304,7 @@ class Note < ActiveRecord::Base
end
def cross_reference_not_visible_for?(user)
- cross_reference? && !has_referenced_mentionables?(user)
- end
-
- def has_referenced_mentionables?(user)
- if user_visible_reference_count.present?
- user_visible_reference_count > 0
- else
- referenced_mentionables(user).any?
- end
+ cross_reference? && !all_referenced_mentionables_allowed?(user)
end
def award_emoji?
@@ -316,7 +324,7 @@ class Note < ActiveRecord::Base
end
def to_ability_name
- for_personal_snippet? ? 'personal_snippet' : noteable_type.underscore
+ for_snippet? ? noteable.class.name.underscore : noteable_type.underscore
end
def can_be_discussion_note?
@@ -466,9 +474,18 @@ class Note < ActiveRecord::Base
self.discussion_id ||= discussion_class.discussion_id(self)
end
+ def all_referenced_mentionables_allowed?(user)
+ if user_visible_reference_count.present? && total_reference_count.present?
+ # if they are not equal, then there are private/confidential references as well
+ user_visible_reference_count > 0 && user_visible_reference_count == total_reference_count
+ else
+ referenced_mentionables(user).any?
+ end
+ end
+
def force_cross_reference_regex_check?
return unless system?
- SystemNoteMetadata::TYPES_WITH_CROSS_REFERENCES.include?(system_note_metadata&.action)
+ system_note_metadata&.cross_reference_types&.include?(system_note_metadata&.action)
end
end
diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb
index 1600acfc575..e82eaf4e069 100644
--- a/app/models/notification_setting.rb
+++ b/app/models/notification_setting.rb
@@ -5,7 +5,7 @@ class NotificationSetting < ActiveRecord::Base
ignore_column :events
- enum level: { global: 3, watch: 2, mention: 4, participating: 1, disabled: 0, custom: 5 }
+ enum level: { global: 3, watch: 2, participating: 1, mention: 4, disabled: 0, custom: 5 }
default_value_for :level, NotificationSetting.levels[:global]
diff --git a/app/models/personal_access_token.rb b/app/models/personal_access_token.rb
index 207146479c0..73a58f2420e 100644
--- a/app/models/personal_access_token.rb
+++ b/app/models/personal_access_token.rb
@@ -3,7 +3,7 @@
class PersonalAccessToken < ActiveRecord::Base
include Expirable
include TokenAuthenticatable
- add_authentication_token_field :token
+ add_authentication_token_field :token, digest: true, fallback: true
REDIS_EXPIRY_TIME = 3.minutes
@@ -33,16 +33,22 @@ class PersonalAccessToken < ActiveRecord::Base
def self.redis_getdel(user_id)
Gitlab::Redis::SharedState.with do |redis|
- token = redis.get(redis_shared_state_key(user_id))
+ encrypted_token = redis.get(redis_shared_state_key(user_id))
redis.del(redis_shared_state_key(user_id))
- token
+ begin
+ Gitlab::CryptoHelper.aes256_gcm_decrypt(encrypted_token)
+ rescue => ex
+ logger.warn "Failed to decrypt PersonalAccessToken value stored in Redis for User ##{user_id}: #{ex.class}"
+ encrypted_token
+ end
end
end
def self.redis_store!(user_id, token)
+ encrypted_token = Gitlab::CryptoHelper.aes256_gcm_encrypt(token)
+
Gitlab::Redis::SharedState.with do |redis|
- redis.set(redis_shared_state_key(user_id), token, ex: REDIS_EXPIRY_TIME)
- token
+ redis.set(redis_shared_state_key(user_id), encrypted_token, ex: REDIS_EXPIRY_TIME)
end
end
diff --git a/app/models/pool_repository.rb b/app/models/pool_repository.rb
new file mode 100644
index 00000000000..bad0e30ceb5
--- /dev/null
+++ b/app/models/pool_repository.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class PoolRepository < ActiveRecord::Base
+ include Shardable
+
+ has_many :member_projects, class_name: 'Project'
+
+ after_create :correct_disk_path
+
+ private
+
+ def correct_disk_path
+ update!(disk_path: storage.disk_path)
+ end
+
+ def storage
+ Storage::HashedProject
+ .new(self, prefix: Storage::HashedProject::POOL_PATH_PREFIX)
+ end
+end
diff --git a/app/models/postgresql/replication_slot.rb b/app/models/postgresql/replication_slot.rb
index 70c7432e6b5..e264fe88e47 100644
--- a/app/models/postgresql/replication_slot.rb
+++ b/app/models/postgresql/replication_slot.rb
@@ -4,6 +4,15 @@ module Postgresql
class ReplicationSlot < ActiveRecord::Base
self.table_name = 'pg_replication_slots'
+ # Returns true if there are any replication slots in use.
+ # PostgreSQL-compatible databases such as Aurora don't support
+ # replication slots, so this will return false as well.
+ def self.in_use?
+ transaction { exists? }
+ rescue ActiveRecord::StatementInvalid
+ false
+ end
+
# Returns true if the lag observed across all replication slots exceeds a
# given threshold.
#
@@ -11,6 +20,8 @@ module Postgresql
# statistics it takes between 1 and 5 seconds to replicate around
# 100 MB of data.
def self.lag_too_great?(max = 100.megabytes)
+ return false unless in_use?
+
lag_function = "#{Gitlab::Database.pg_wal_lsn_diff}" \
"(#{Gitlab::Database.pg_current_wal_insert_lsn}(), restart_lsn)::bigint"
diff --git a/app/models/project.rb b/app/models/project.rb
index 3e14064a556..ade20cc8948 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -30,6 +30,7 @@ class Project < ActiveRecord::Base
include FeatureGate
include OptionallySearch
include FromUnion
+ include IgnorableColumn
extend Gitlab::Cache::RequestCache
extend Gitlab::ConfigHelper
@@ -49,17 +50,28 @@ class Project < ActiveRecord::Base
attachments: 2
}.freeze
- # Valids ports to import from
- VALID_IMPORT_PORTS = [22, 80, 443].freeze
+ VALID_IMPORT_PORTS = [80, 443].freeze
+ VALID_IMPORT_PROTOCOLS = %w(http https git).freeze
+
+ VALID_MIRROR_PORTS = [22, 80, 443].freeze
+ VALID_MIRROR_PROTOCOLS = %w(http https ssh git).freeze
+
+ ignore_column :import_status, :import_jid, :import_error
cache_markdown_field :description, pipeline: :description
delegate :feature_available?, :builds_enabled?, :wiki_enabled?,
- :merge_requests_enabled?, :issues_enabled?, to: :project_feature,
- allow_nil: true
+ :merge_requests_enabled?, :issues_enabled?, :pages_enabled?, :public_pages?,
+ to: :project_feature, allow_nil: true
delegate :base_dir, :disk_path, :ensure_storage_path_exists, to: :storage
+ delegate :scheduled?, :started?, :in_progress?,
+ :failed?, :finished?,
+ prefix: :import, to: :import_state, allow_nil: true
+
+ delegate :no_import?, to: :import_state, allow_nil: true
+
default_value_for :archived, false
default_value_for :visibility_level, gitlab_config_features.visibility_level
default_value_for :resolve_outdated_diff_discussions, false
@@ -85,15 +97,11 @@ class Project < ActiveRecord::Base
after_create :create_project_feature, unless: :project_feature
- after_create -> { SiteStatistic.track(STATISTICS_ATTRIBUTE) }
- before_destroy :untrack_site_statistics
-
after_create :create_ci_cd_settings,
unless: :ci_cd_settings,
if: proc { ProjectCiCdSetting.available? }
- after_create :set_last_activity_at
- after_create :set_last_repository_updated_at
+ after_create :set_timestamps_for_create
after_update :update_forks_visibility_level
before_destroy :remove_private_deploy_keys
@@ -111,7 +119,7 @@ class Project < ActiveRecord::Base
after_create :ensure_storage_path_exists
after_save :ensure_storage_path_exists, if: :namespace_id_changed?
- acts_as_taggable
+ acts_as_ordered_taggable
attr_accessor :old_path_with_namespace
attr_accessor :template_name
@@ -121,6 +129,7 @@ class Project < ActiveRecord::Base
alias_attribute :title, :name
# Relations
+ belongs_to :pool_repository
belongs_to :creator, class_name: 'User'
belongs_to :group, -> { where(type: 'Group') }, foreign_key: 'namespace_id'
belongs_to :namespace
@@ -132,6 +141,7 @@ class Project < ActiveRecord::Base
# Project services
has_one :campfire_service
+ has_one :discord_service
has_one :drone_ci_service
has_one :emails_on_push_service
has_one :pipelines_email_service
@@ -164,26 +174,22 @@ class Project < ActiveRecord::Base
has_one :packagist_service
has_one :hangouts_chat_service
- # TODO: replace these relations with the fork network versions
- has_one :forked_project_link, foreign_key: "forked_to_project_id"
- has_one :forked_from_project, through: :forked_project_link
-
- has_many :forked_project_links, foreign_key: "forked_from_project_id"
- has_many :forks, through: :forked_project_links, source: :forked_to_project
- # TODO: replace these relations with the fork network versions
-
has_one :root_of_fork_network,
foreign_key: 'root_project_id',
inverse_of: :root_project,
class_name: 'ForkNetwork'
has_one :fork_network_member
has_one :fork_network, through: :fork_network_member
+ has_one :forked_from_project, through: :fork_network_member
+ has_many :forked_to_members, class_name: 'ForkNetworkMember', foreign_key: 'forked_from_project_id'
+ has_many :forks, through: :forked_to_members, source: :project, inverse_of: :forked_from_project
has_one :import_state, autosave: true, class_name: 'ProjectImportState', inverse_of: :project
has_one :import_export_upload, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_one :project_repository, inverse_of: :project
# Merge Requests for target project should be removed with it
- has_many :merge_requests, foreign_key: 'target_project_id'
+ has_many :merge_requests, foreign_key: 'target_project_id', inverse_of: :target_project
has_many :source_of_merge_requests, foreign_key: 'source_project_id', class_name: 'MergeRequest'
has_many :issues
has_many :labels, class_name: 'ProjectLabel'
@@ -256,7 +262,7 @@ class Project < ActiveRecord::Base
has_many :variables, class_name: 'Ci::Variable'
has_many :triggers, class_name: 'Ci::Trigger'
has_many :environments
- has_many :deployments
+ has_many :deployments, -> { success }
has_many :pipeline_schedules, class_name: 'Ci::PipelineSchedule'
has_many :project_deploy_tokens
has_many :deploy_tokens, through: :project_deploy_tokens
@@ -305,10 +311,10 @@ class Project < ActiveRecord::Base
validates :namespace, presence: true
validates :name, uniqueness: { scope: :namespace_id }
- validates :import_url, url: { protocols: %w(http https ssh git),
+ validates :import_url, url: { protocols: ->(project) { project.persisted? ? VALID_MIRROR_PROTOCOLS : VALID_IMPORT_PROTOCOLS },
+ ports: ->(project) { project.persisted? ? VALID_MIRROR_PORTS : VALID_IMPORT_PORTS },
allow_localhost: false,
- enforce_user: true,
- ports: VALID_IMPORT_PORTS }, if: [:external_import?, :import_url_changed?]
+ enforce_user: true }, if: [:external_import?, :import_url_changed?]
validates :star_count, numericality: { greater_than_or_equal_to: 0 }
validate :check_limit, on: :create
validate :check_repository_path_availability, on: :update, if: ->(project) { project.renamed? }
@@ -356,7 +362,7 @@ class Project < ActiveRecord::Base
# "enabled" here means "not disabled". It includes private features!
scope :with_feature_enabled, ->(feature) {
access_level_attribute = ProjectFeature.access_level_attribute(feature)
- with_project_feature.where(project_features: { access_level_attribute => [nil, ProjectFeature::PRIVATE, ProjectFeature::ENABLED] })
+ with_project_feature.where(project_features: { access_level_attribute => [nil, ProjectFeature::PRIVATE, ProjectFeature::ENABLED, ProjectFeature::PUBLIC] })
}
# Picks a feature where the level is exactly that given.
@@ -386,6 +392,13 @@ class Project < ActiveRecord::Base
only_integer: true,
message: 'needs to be beetween 10 minutes and 1 month' }
+ # Returns a project, if it is not about to be removed.
+ #
+ # id - The ID of the project to retrieve.
+ def self.find_without_deleted(id)
+ without_deleted.find_by_id(id)
+ end
+
# Paginates a collection using a `WHERE id < ?` condition.
#
# before - A project ID to use for filtering out projects with an equal or
@@ -418,15 +431,15 @@ class Project < ActiveRecord::Base
end
end
- # project features may be "disabled", "internal" or "enabled". If "internal",
+ # project features may be "disabled", "internal", "enabled" or "public". If "internal",
# they are only available to team members. This scope returns projects where
- # the feature is either enabled, or internal with permission for the user.
+ # the feature is either public, enabled, or internal with permission for the user.
#
# This method uses an optimised version of `with_feature_access_level` for
# logged in users to more efficiently get private projects with the given
# feature.
def self.with_feature_available_for_user(feature, user)
- visible = [nil, ProjectFeature::ENABLED]
+ visible = [nil, ProjectFeature::ENABLED, ProjectFeature::PUBLIC]
if user&.admin?
with_feature_enabled(feature)
@@ -448,8 +461,9 @@ class Project < ActiveRecord::Base
scope :excluding_project, ->(project) { where.not(id: project) }
- scope :joins_import_state, -> { joins("LEFT JOIN project_mirror_data import_state ON import_state.project_id = projects.id") }
- scope :import_started, -> { joins_import_state.where("import_state.status = 'started' OR projects.import_status = 'started'") }
+ # We require an alias to the project_mirror_data_table in order to use import_state in our queries
+ scope :joins_import_state, -> { joins("INNER JOIN project_mirror_data import_state ON import_state.project_id = projects.id") }
+ scope :for_group, -> (group) { where(group: group) }
class << self
# Searches for a list of projects based on the query given in `query`.
@@ -542,6 +556,8 @@ class Project < ActiveRecord::Base
self[:lfs_enabled] && Gitlab.config.lfs.enabled
end
+ alias_method :lfs_enabled, :lfs_enabled?
+
def auto_devops_enabled?
if auto_devops&.enabled.nil?
has_auto_devops_implicitly_enabled?
@@ -622,6 +638,14 @@ class Project < ActiveRecord::Base
id && persisted?
end
+ def import_status
+ import_state&.status || 'none'
+ end
+
+ def human_import_status_name
+ import_state&.human_status_name || 'none'
+ end
+
def add_import_job
job_id =
if forked?
@@ -653,11 +677,11 @@ class Project < ActiveRecord::Base
ProjectCacheWorker.perform_async(self.id)
end
- update(import_error: nil)
+ import_state.update(last_error: nil)
remove_import_data
end
- # This method is overriden in EE::Project model
+ # This method is overridden in EE::Project model
def remove_import_data
import_data&.destroy
end
@@ -682,6 +706,8 @@ class Project < ActiveRecord::Base
else
super
end
+ rescue
+ super
end
def valid_import_url?
@@ -713,130 +739,6 @@ class Project < ActiveRecord::Base
import_url.present?
end
- def imported?
- import_finished?
- end
-
- def import_in_progress?
- import_started? || import_scheduled?
- end
-
- def import_state_args
- {
- status: self[:import_status],
- jid: self[:import_jid],
- last_error: self[:import_error]
- }
- end
-
- def ensure_import_state(force: false)
- return if !force && (self[:import_status] == 'none' || self[:import_status].nil?)
- return unless import_state.nil?
-
- if persisted?
- create_import_state(import_state_args)
-
- update_column(:import_status, 'none')
- else
- build_import_state(import_state_args)
-
- self[:import_status] = 'none'
- end
- end
-
- def human_import_status_name
- ensure_import_state
-
- import_state.human_status_name
- end
-
- def import_schedule
- ensure_import_state(force: true)
-
- import_state.schedule
- end
-
- def force_import_start
- ensure_import_state(force: true)
-
- import_state.force_start
- end
-
- def import_start
- ensure_import_state(force: true)
-
- import_state.start
- end
-
- def import_fail
- ensure_import_state(force: true)
-
- import_state.fail_op
- end
-
- def import_finish
- ensure_import_state(force: true)
-
- import_state.finish
- end
-
- def import_jid=(new_jid)
- ensure_import_state(force: true)
-
- import_state.jid = new_jid
- end
-
- def import_jid
- ensure_import_state
-
- import_state&.jid
- end
-
- def import_error=(new_error)
- ensure_import_state(force: true)
-
- import_state.last_error = new_error
- end
-
- def import_error
- ensure_import_state
-
- import_state&.last_error
- end
-
- def import_status=(new_status)
- ensure_import_state(force: true)
-
- import_state.status = new_status
- end
-
- def import_status
- ensure_import_state
-
- import_state&.status || 'none'
- end
-
- def no_import?
- import_status == 'none'
- end
-
- def import_started?
- # import? does SQL work so only run it if it looks like there's an import running
- import_status == 'started' && import?
- end
-
- def import_scheduled?
- import_status == 'scheduled'
- end
-
- def import_failed?
- import_status == 'failed'
- end
-
- def import_finished?
- import_status == 'finished'
- end
-
def safe_import_url
Gitlab::UrlSanitizer.new(import_url).masked_url
end
@@ -977,9 +879,9 @@ class Project < ActiveRecord::Base
end
def readme_url
- readme = repository.readme
- if readme
- Gitlab::Routing.url_helpers.project_blob_url(self, File.join(default_branch, readme.path))
+ readme_path = repository.readme_path
+ if readme_path
+ Gitlab::Routing.url_helpers.project_blob_url(self, File.join(default_branch, readme_path))
end
end
@@ -1082,31 +984,13 @@ class Project < ActiveRecord::Base
end
def find_or_initialize_services(exceptions: [])
- services_templates = Service.where(template: true)
-
available_services_names = Service.available_services_names - exceptions
available_services = available_services_names.map do |service_name|
- service = find_service(services, service_name)
-
- if service
- service
- else
- # We should check if template for the service exists
- template = find_service(services_templates, service_name)
-
- if template.nil?
- # If no template, we should create an instance. Ex `build_gitlab_ci_service`
- public_send("build_#{service_name}_service") # rubocop:disable GitlabSecurity/PublicSend
- else
- Service.build_from_template(id, template)
- end
- end
+ find_or_initialize_service(service_name)
end
- available_services.reject do |service|
- disabled_services.include?(service.to_param)
- end
+ available_services.compact
end
def disabled_services
@@ -1114,7 +998,20 @@ class Project < ActiveRecord::Base
end
def find_or_initialize_service(name)
- find_or_initialize_services.find { |service| service.to_param == name }
+ return if disabled_services.include?(name)
+
+ service = find_service(services, name)
+ return service if service
+
+ # We should check if template for the service exists
+ template = find_service(services_templates, name)
+
+ if template
+ Service.build_from_template(id, template)
+ else
+ # If no template, we should create an instance. Ex `build_gitlab_ci_service`
+ public_send("build_#{name}_service") # rubocop:disable GitlabSecurity/PublicSend
+ end
end
# rubocop: disable CodeReuse/ServiceClass
@@ -1244,12 +1141,7 @@ class Project < ActiveRecord::Base
end
def forked?
- return true if fork_network && fork_network.root_project != self
-
- # TODO: Use only the above conditional using the `fork_network`
- # This is the old conditional that looks at the `forked_project_link`, we
- # fall back to this while we're migrating the new models
- !(forked_project_link.nil? || forked_project_link.forked_from_project.nil?)
+ fork_network && fork_network.root_project != self
end
def fork_source
@@ -1315,6 +1207,13 @@ class Project < ActiveRecord::Base
false
end
+ def track_project_repository
+ return unless hashed_storage?(:repository)
+
+ project_repo = project_repository || build_project_repository
+ project_repo.update!(shard_name: repository_storage, disk_path: disk_path)
+ end
+
def create_repository(force: false)
# Forked import is handled asynchronously
return if forked? && !force
@@ -1365,6 +1264,18 @@ class Project < ActiveRecord::Base
end
end
+ # Filters `users` to return only authorized users of the project
+ def members_among(users)
+ if users.is_a?(ActiveRecord::Relation) && !users.loaded?
+ authorized_users.merge(users)
+ else
+ return [] if users.empty?
+
+ user_ids = authorized_users.where(users: { id: users.map(&:id) }).pluck(:id)
+ users.select { |user| user_ids.include?(user.id) }
+ end
+ end
+
def default_branch
@default_branch ||= repository.root_ref if repository.exists?
end
@@ -1381,7 +1292,7 @@ class Project < ActiveRecord::Base
def change_head(branch)
if repository.branch_exists?(branch)
repository.before_change_head
- repository.raw_repository.write_ref('HEAD', "refs/heads/#{branch}", shell: false)
+ repository.raw_repository.write_ref('HEAD', "refs/heads/#{branch}")
repository.copy_gitattributes(branch)
repository.after_change_head
reload_default_branch
@@ -1528,9 +1439,7 @@ class Project < ActiveRecord::Base
def visibility_level_allowed_as_fork?(level = self.visibility_level)
return true unless forked?
- # self.forked_from_project will be nil before the project is saved, so
- # we need to go through the relation
- original_project = forked_project_link&.forked_from_project
+ original_project = fork_source
return true unless original_project
level <= original_project.visibility_level
@@ -1622,34 +1531,6 @@ class Project < ActiveRecord::Base
end
# rubocop: enable CodeReuse/ServiceClass
- def rename_repo
- path_before = previous_changes['path'].first
- full_path_before = full_path_was
- full_path_after = build_full_path
-
- Gitlab::AppLogger.info("Attempting to rename #{full_path_was} -> #{full_path_after}")
-
- if has_container_registry_tags?
- Gitlab::AppLogger.info("Project #{full_path_was} cannot be renamed because container registry tags are present!")
-
- # we currently don't support renaming repository if it contains images in container registry
- raise StandardError.new('Project cannot be renamed, because images are present in its container registry')
- end
-
- expire_caches_before_rename(full_path_before)
-
- if rename_or_migrate_repository!
- Gitlab::AppLogger.info("Project was renamed: #{full_path_before} -> #{full_path_after}")
- after_rename_repository(full_path_before, path_before)
- else
- Gitlab::AppLogger.info("Repository could not be renamed: #{full_path_before} -> #{full_path_after}")
-
- # if we cannot move namespace directory we should rollback
- # db changes in order to prevent out of sync between db and fs
- raise StandardError.new('Repository cannot be renamed')
- end
- end
-
def write_repository_config(gl_full_path: full_path)
# We'd need to keep track of project full path otherwise directory tree
# created with hashed storage enabled cannot be usefully imported using
@@ -1663,8 +1544,8 @@ class Project < ActiveRecord::Base
def after_import
repository.after_import
wiki.repository.after_import
- import_finish
- remove_import_jid
+ import_state.finish
+ import_state.remove_jid
update_project_counter_caches
after_create_default_branch
refresh_markdown_cache!
@@ -1704,32 +1585,11 @@ class Project < ActiveRecord::Base
end
# rubocop: enable CodeReuse/ServiceClass
- def remove_import_jid
- return unless import_jid
-
- Gitlab::SidekiqStatus.unset(import_jid)
-
- import_state.update_column(:jid, nil)
- end
-
# Lazy loading of the `pipeline_status` attribute
def pipeline_status
@pipeline_status ||= Gitlab::Cache::Ci::ProjectPipelineStatus.load_for_project(self)
end
- def mark_import_as_failed(error_message)
- original_errors = errors.dup
- sanitized_message = Gitlab::UrlSanitizer.sanitize(error_message)
-
- import_fail
-
- import_state.update_column(:last_error, sanitized_message)
- rescue ActiveRecord::ActiveRecordError => e
- Rails.logger.error("Error setting import status to failed: #{e.message}. Original error: #{sanitized_message}")
- ensure
- @errors = original_errors
- end
-
def add_export_job(current_user:, after_export_strategy: nil, params: {})
job_id = ProjectExportWorker.perform_async(current_user.id, self.id, after_export_strategy, params)
@@ -1774,7 +1634,7 @@ class Project < ActiveRecord::Base
return unless export_file_exists?
import_export_upload.remove_export_file!
- import_export_upload.save
+ import_export_upload.save unless import_export_upload.destroyed?
end
def export_file_exists?
@@ -1829,7 +1689,7 @@ class Project < ActiveRecord::Base
.first
end
- def secret_variables_for(ref:, environment: nil)
+ def ci_variables_for(ref:, environment: nil)
# EE would use the environment
if protected_for?(ref)
variables
@@ -1847,7 +1707,7 @@ class Project < ActiveRecord::Base
end
def deployment_variables(environment: nil)
- deployment_platform(environment: environment)&.predefined_variables || []
+ deployment_platform(environment: environment)&.predefined_variables(project: self) || []
end
def auto_devops_variables
@@ -1920,10 +1780,6 @@ class Project < ActiveRecord::Base
false
end
- def issue_board_milestone_available?(user = nil)
- feature_available?(:issue_board_milestone, user)
- end
-
def full_path_was
File.join(namespace.full_path, previous_changes['path'].first)
end
@@ -1985,7 +1841,7 @@ class Project < ActiveRecord::Base
end
def migrate_to_hashed_storage!
- return if hashed_storage?(:repository)
+ return unless storage_upgradable?
update!(repository_read_only: true)
@@ -2010,17 +1866,6 @@ class Project < ActiveRecord::Base
Gitlab::ReferenceCounter.new(gl_repository(is_wiki: wiki))
end
- # Refreshes the expiration time of the associated import job ID.
- #
- # This method can be used by asynchronous importers to refresh the status,
- # preventing the StuckImportJobsWorker from marking the import as failed.
- def refresh_import_jid_expiration
- return unless import_jid
-
- Gitlab::SidekiqStatus
- .set(import_jid, StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION)
- end
-
def badges
return project_badges unless group
@@ -2078,62 +1923,6 @@ class Project < ActiveRecord::Base
auto_cancel_pending_pipelines == 'enabled'
end
- # Update the default branch querying the remote to determine its HEAD
- def update_root_ref(remote_name)
- root_ref = repository.find_remote_root_ref(remote_name)
- change_head(root_ref) if root_ref.present? && root_ref != default_branch
- end
-
- private
-
- # rubocop: disable CodeReuse/ServiceClass
- def rename_or_migrate_repository!
- if Gitlab::CurrentSettings.hashed_storage_enabled? &&
- storage_upgradable? &&
- Feature.disabled?(:skip_hashed_storage_upgrade) # kill switch in case we need to disable upgrade behavior
- ::Projects::HashedStorageMigrationService.new(self, full_path_was).execute
- else
- storage.rename_repo
- end
- end
- # rubocop: enable CodeReuse/ServiceClass
-
- def storage_upgradable?
- storage_version != LATEST_STORAGE_VERSION
- end
-
- def after_rename_repository(full_path_before, path_before)
- execute_rename_repository_hooks!(full_path_before)
-
- write_repository_config
-
- # We need to check if project had been rolled out to move resource to hashed storage or not and decide
- # if we need execute any take action or no-op.
- unless hashed_storage?(:attachments)
- Gitlab::UploadsTransfer.new.rename_project(path_before, self.path, namespace.full_path)
- end
-
- Gitlab::PagesTransfer.new.rename_project(path_before, self.path, namespace.full_path)
- end
-
- def untrack_site_statistics
- SiteStatistic.untrack(STATISTICS_ATTRIBUTE)
- self.project_feature.untrack_statistics_for_deletion!
- end
-
- # rubocop: disable CodeReuse/ServiceClass
- def execute_rename_repository_hooks!(full_path_before)
- # When we import a project overwriting the original project, there
- # is a move operation. In that case we don't want to send the instructions.
- send_move_instructions(full_path_before) unless import_started?
-
- self.old_path_with_namespace = full_path_before
- SystemHooksService.new.execute_hooks_for(self, :rename)
-
- reload_repository!
- end
- # rubocop: enable CodeReuse/ServiceClass
-
def storage
@storage ||=
if hashed_storage?(:repository)
@@ -2143,6 +1932,16 @@ class Project < ActiveRecord::Base
end
end
+ def storage_upgradable?
+ storage_version != LATEST_STORAGE_VERSION
+ end
+
+ def snippets_visible?(user = nil)
+ Ability.allowed?(user, :read_project_snippet, self)
+ end
+
+ private
+
def use_hashed_storage
if self.new_record? && Gitlab::CurrentSettings.hashed_storage_enabled
self.storage_version = LATEST_STORAGE_VERSION
@@ -2170,13 +1969,8 @@ class Project < ActiveRecord::Base
gitlab_shell.exists?(repository_storage, "#{disk_path}.git")
end
- # set last_activity_at to the same as created_at
- def set_last_activity_at
- update_column(:last_activity_at, self.created_at)
- end
-
- def set_last_repository_updated_at
- update_column(:last_repository_updated_at, self.created_at)
+ def set_timestamps_for_create
+ update_columns(last_activity_at: self.created_at, last_repository_updated_at: self.created_at)
end
def cross_namespace_reference?(from)
@@ -2272,12 +2066,12 @@ class Project < ActiveRecord::Base
end
end
- if RequestStore.active?
- RequestStore.fetch("project-#{id}:branch-#{branch_name}:user-#{user.id}:branch_allows_collaboration") do
- check_access.call
- end
- else
+ Gitlab::SafeRequestStore.fetch("project-#{id}:branch-#{branch_name}:user-#{user.id}:branch_allows_collaboration") do
check_access.call
end
end
+
+ def services_templates
+ @services_templates ||= Service.where(template: true)
+ end
end
diff --git a/app/models/project_auto_devops.rb b/app/models/project_auto_devops.rb
index dc6736dd9cd..2253ad7b543 100644
--- a/app/models/project_auto_devops.rb
+++ b/app/models/project_auto_devops.rb
@@ -5,7 +5,8 @@ class ProjectAutoDevops < ActiveRecord::Base
enum deploy_strategy: {
continuous: 0,
- manual: 1
+ manual: 1,
+ timed_incremental: 2
}
scope :enabled, -> { where(enabled: true) }
@@ -30,10 +31,7 @@ class ProjectAutoDevops < ActiveRecord::Base
value: domain.presence || instance_domain)
end
- if manual?
- variables.append(key: 'STAGING_ENABLED', value: '1')
- variables.append(key: 'INCREMENTAL_ROLLOUT_ENABLED', value: '1')
- end
+ variables.concat(deployment_strategy_default_variables)
end
end
@@ -51,4 +49,16 @@ class ProjectAutoDevops < ActiveRecord::Base
!project.public? &&
!project.deploy_tokens.find_by(name: DeployToken::GITLAB_DEPLOY_TOKEN_NAME).present?
end
+
+ def deployment_strategy_default_variables
+ Gitlab::Ci::Variables::Collection.new.tap do |variables|
+ if manual?
+ variables.append(key: 'STAGING_ENABLED', value: '1')
+ variables.append(key: 'INCREMENTAL_ROLLOUT_ENABLED', value: '1') # deprecated
+ variables.append(key: 'INCREMENTAL_ROLLOUT_MODE', value: 'manual')
+ elsif timed_incremental?
+ variables.append(key: 'INCREMENTAL_ROLLOUT_MODE', value: 'timed')
+ end
+ end
+ end
end
diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb
index d74cb2506ba..39f2b8fe0de 100644
--- a/app/models/project_feature.rb
+++ b/app/models/project_feature.rb
@@ -13,15 +13,16 @@ class ProjectFeature < ActiveRecord::Base
# Disabled: not enabled for anyone
# Private: enabled only for team members
# Enabled: enabled for everyone able to access the project
+ # Public: enabled for everyone (only allowed for pages)
#
# Permission levels
DISABLED = 0
PRIVATE = 10
ENABLED = 20
+ PUBLIC = 30
- FEATURES = %i(issues merge_requests wiki snippets builds repository).freeze
- STATISTICS_ATTRIBUTE = 'wikis_count'.freeze
+ FEATURES = %i(issues merge_requests wiki snippets builds repository pages).freeze
class << self
def access_level_attribute(feature)
@@ -47,6 +48,7 @@ class ProjectFeature < ActiveRecord::Base
validates :project, presence: true
validate :repository_children_level
+ validate :allowed_access_levels
default_value_for :builds_access_level, value: ENABLED, allows_nil: false
default_value_for :issues_access_level, value: ENABLED, allows_nil: false
@@ -55,10 +57,10 @@ class ProjectFeature < ActiveRecord::Base
default_value_for :wiki_access_level, value: ENABLED, allows_nil: false
default_value_for :repository_access_level, value: ENABLED, allows_nil: false
- after_create ->(model) { SiteStatistic.track(STATISTICS_ATTRIBUTE) if model.wiki_enabled? }
- after_update :update_site_statistics
-
def feature_available?(feature, user)
+ # This feature might not be behind a feature flag at all, so default to true
+ return false unless ::Feature.enabled?(feature, user, default_enabled: true)
+
get_permission(user, access_level(feature))
end
@@ -82,30 +84,18 @@ class ProjectFeature < ActiveRecord::Base
issues_access_level > DISABLED
end
- # This is a workaround for the removal hooks not been triggered when removing a Project.
- #
- # ProjectFeature is removed using database cascade index rule.
- # This method is called by Project model when deletion starts.
- def untrack_statistics_for_deletion!
- return unless wiki_enabled?
-
- SiteStatistic.untrack(STATISTICS_ATTRIBUTE)
+ def pages_enabled?
+ pages_access_level > DISABLED
end
- private
-
- def update_site_statistics
- return unless wiki_access_level_changed?
+ def public_pages?
+ return true unless Gitlab.config.pages.access_control
- if self.wiki_access_level_was == DISABLED
- # possible new states are PRIVATE / ENABLED, both should be tracked
- SiteStatistic.track(STATISTICS_ATTRIBUTE)
- elsif self.wiki_access_level == DISABLED
- # old state was either PRIVATE / ENABLED, only untrack if new state is DISABLED
- SiteStatistic.untrack(STATISTICS_ATTRIBUTE)
- end
+ pages_access_level == PUBLIC || pages_access_level == ENABLED && project.public?
end
+ private
+
# Validates builds and merge requests access level
# which cannot be higher than repository access level
def repository_children_level
@@ -118,6 +108,17 @@ class ProjectFeature < ActiveRecord::Base
%i(merge_requests_access_level builds_access_level).each(&validator)
end
+ # Validates access level for other than pages cannot be PUBLIC
+ def allowed_access_levels
+ validator = lambda do |field|
+ level = public_send(field) || ProjectFeature::ENABLED # rubocop:disable GitlabSecurity/PublicSend
+ not_allowed = level > ProjectFeature::ENABLED
+ self.errors.add(field, "cannot have public visibility level") if not_allowed
+ end
+
+ (FEATURES - %i(pages)).each {|f| validator.call("#{f}_access_level")}
+ end
+
def get_permission(user, level)
case level
when DISABLED
@@ -126,6 +127,8 @@ class ProjectFeature < ActiveRecord::Base
user && (project.team.member?(user) || user.full_private_access?)
when ENABLED
true
+ when PUBLIC
+ true
else
true
end
diff --git a/app/models/project_import_state.rb b/app/models/project_import_state.rb
index d59cb43dea4..488f0cb5971 100644
--- a/app/models/project_import_state.rb
+++ b/app/models/project_import_state.rb
@@ -56,4 +56,46 @@ class ProjectImportState < ActiveRecord::Base
end
end
end
+
+ def mark_as_failed(error_message)
+ original_errors = errors.dup
+ sanitized_message = Gitlab::UrlSanitizer.sanitize(error_message)
+
+ fail_op
+
+ update_column(:last_error, sanitized_message)
+ rescue ActiveRecord::ActiveRecordError => e
+ Rails.logger.error("Error setting import status to failed: #{e.message}. Original error: #{sanitized_message}")
+ ensure
+ @errors = original_errors
+ end
+
+ alias_method :no_import?, :none?
+
+ def in_progress?
+ scheduled? || started?
+ end
+
+ def started?
+ # import? does SQL work so only run it if it looks like there's an import running
+ status == 'started' && project.import?
+ end
+
+ def remove_jid
+ return unless jid
+
+ Gitlab::SidekiqStatus.unset(jid)
+
+ update_column(:jid, nil)
+ end
+
+ # Refreshes the expiration time of the associated import job ID.
+ #
+ # This method can be used by asynchronous importers to refresh the status,
+ # preventing the StuckImportJobsWorker from marking the import as failed.
+ def refresh_jid_expiration
+ return unless jid
+
+ Gitlab::SidekiqStatus.set(jid, StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION)
+ end
end
diff --git a/app/models/project_repository.rb b/app/models/project_repository.rb
new file mode 100644
index 00000000000..38913f3f2f5
--- /dev/null
+++ b/app/models/project_repository.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class ProjectRepository < ActiveRecord::Base
+ include Shardable
+
+ belongs_to :project, inverse_of: :project_repository
+
+ class << self
+ def find_project(disk_path)
+ find_by(disk_path: disk_path)&.project
+ end
+ end
+end
diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb
index d502423726c..a252052200a 100644
--- a/app/models/project_services/bamboo_service.rb
+++ b/app/models/project_services/bamboo_service.rb
@@ -80,24 +80,31 @@ class BambooService < CiService
private
+ def get_build_result_index
+ # When Bamboo returns multiple results for a given changeset, arbitrarily assume the most relevant result to be the last one.
+ -1
+ end
+
def read_build_page(response)
- if response.code != 200 || response['results']['results']['size'] == '0'
- # If actual build link can't be determined, send user to build summary page.
- URI.join("#{bamboo_url}/", "browse/#{build_key}").to_s
- else
- # If actual build link is available, go to build result page.
- result_key = response['results']['results']['result']['planResultKey']['key']
- URI.join("#{bamboo_url}/", "browse/#{result_key}").to_s
- end
+ key =
+ if response.code != 200 || response.dig('results', 'results', 'size') == '0'
+ # If actual build link can't be determined, send user to build summary page.
+ build_key
+ else
+ # If actual build link is available, go to build result page.
+ response.dig('results', 'results', 'result', get_build_result_index, 'planResultKey', 'key')
+ end
+
+ build_url("browse/#{key}")
end
def read_commit_status(response)
return :error unless response.code == 200 || response.code == 404
- status = if response.code == 404 || response['results']['results']['size'] == '0'
+ status = if response.code == 404 || response.dig('results', 'results', 'size') == '0'
'Pending'
else
- response['results']['results']['result']['buildState']
+ response.dig('results', 'results', 'result', get_build_result_index, 'buildState')
end
if status.include?('Success')
@@ -112,7 +119,7 @@ class BambooService < CiService
end
def build_url(path)
- URI.join("#{bamboo_url}/", path).to_s
+ Gitlab::Utils.append_path(bamboo_url, path)
end
def get_path(path, query_params = {})
diff --git a/app/models/project_services/chat_message/push_message.rb b/app/models/project_services/chat_message/push_message.rb
index 82be33a12a1..5dd0414b7e6 100644
--- a/app/models/project_services/chat_message/push_message.rb
+++ b/app/models/project_services/chat_message/push_message.rb
@@ -26,16 +26,8 @@ module ChatMessage
end
def activity
- action = if new_branch?
- "created"
- elsif removed_branch?
- "removed"
- else
- "pushed to"
- end
-
{
- title: "#{user_combined_name} #{action} #{ref_type}",
+ title: humanized_action(short: true),
subtitle: "in #{project_link}",
text: compare_link,
image: user_avatar
@@ -44,32 +36,21 @@ module ChatMessage
private
+ def humanized_action(short: false)
+ action, ref_link, target_link = compose_action_details
+ text = [user_combined_name, action, ref_type, ref_link]
+ text << target_link unless short
+ text.join(' ')
+ end
+
def message
- if new_branch?
- new_branch_message
- elsif removed_branch?
- removed_branch_message
- else
- push_message
- end
+ humanized_action
end
def format(string)
Slack::Notifier::LinkFormatter.format(string)
end
- def new_branch_message
- "#{user_combined_name} pushed new #{ref_type} #{branch_link} to #{project_link}"
- end
-
- def removed_branch_message
- "#{user_combined_name} removed #{ref_type} #{ref} from #{project_link}"
- end
-
- def push_message
- "#{user_combined_name} pushed to #{ref_type} #{branch_link} of #{project_link} (#{compare_link})"
- end
-
def commit_messages
commits.map { |commit| compose_commit_message(commit) }.join("\n\n")
end
@@ -115,6 +96,16 @@ module ChatMessage
"[Compare changes](#{compare_url})"
end
+ def compose_action_details
+ if new_branch?
+ ['pushed new', branch_link, "to #{project_link}"]
+ elsif removed_branch?
+ ['removed', ref, "from #{project_link}"]
+ else
+ ['pushed to', branch_link, "of #{project_link} (#{compare_link})"]
+ end
+ end
+
def attachment_color
'#345'
end
diff --git a/app/models/project_services/discord_service.rb b/app/models/project_services/discord_service.rb
new file mode 100644
index 00000000000..21afd14dbff
--- /dev/null
+++ b/app/models/project_services/discord_service.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require "discordrb/webhooks"
+
+class DiscordService < ChatNotificationService
+ def title
+ "Discord Notifications"
+ end
+
+ def description
+ "Receive event notifications in Discord"
+ end
+
+ def self.to_param
+ "discord"
+ end
+
+ def help
+ "This service sends notifications about project events to Discord channels.<br />
+ To set up this service:
+ <ol>
+ <li><a href='https://support.discordapp.com/hc/en-us/articles/228383668-Intro-to-Webhooks'>Setup a custom Incoming Webhook</a>.</li>
+ <li>Paste the <strong>Webhook URL</strong> into the field below.</li>
+ <li>Select events below to enable notifications.</li>
+ </ol>"
+ end
+
+ def event_field(event)
+ # No-op.
+ end
+
+ def default_channel_placeholder
+ # No-op.
+ end
+
+ def default_fields
+ [
+ { type: "text", name: "webhook", placeholder: "e.g. https://discordapp.com/api/webhooks/…" },
+ { type: "checkbox", name: "notify_only_broken_pipelines" },
+ { type: "checkbox", name: "notify_only_default_branch" }
+ ]
+ end
+
+ private
+
+ def notify(message, opts)
+ client = Discordrb::Webhooks::Client.new(url: webhook)
+
+ client.execute do |builder|
+ builder.content = message.pretext
+ end
+ end
+
+ def custom_data(data)
+ super(data).merge(markdown: true)
+ end
+end
diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb
index 158ae0bf255..5ccc2f019cb 100644
--- a/app/models/project_services/drone_ci_service.rb
+++ b/app/models/project_services/drone_ci_service.rb
@@ -39,11 +39,9 @@ class DroneCiService < CiService
end
def commit_status_path(sha, ref)
- url = [drone_url,
- "gitlab/#{project.full_path}/commits/#{sha}",
- "?branch=#{URI.encode(ref.to_s)}&access_token=#{token}"]
-
- URI.join(*url).to_s
+ Gitlab::Utils.append_path(
+ drone_url,
+ "gitlab/#{project.full_path}/commits/#{sha}?branch=#{URI.encode(ref.to_s)}&access_token=#{token}")
end
def commit_status(sha, ref)
@@ -74,11 +72,9 @@ class DroneCiService < CiService
end
def build_page(sha, ref)
- url = [drone_url,
- "gitlab/#{project.full_path}/redirect/commits/#{sha}",
- "?branch=#{URI.encode(ref.to_s)}"]
-
- URI.join(*url).to_s
+ Gitlab::Utils.append_path(
+ drone_url,
+ "gitlab/#{project.full_path}/redirect/commits/#{sha}?branch=#{URI.encode(ref.to_s)}")
end
def title
diff --git a/app/models/project_services/flowdock_service.rb b/app/models/project_services/flowdock_service.rb
index 2545df06f6b..76624263aab 100644
--- a/app/models/project_services/flowdock_service.rb
+++ b/app/models/project_services/flowdock_service.rb
@@ -1,53 +1,5 @@
# frozen_string_literal: true
-require "flowdock-git-hook"
-
-# Flow dock depends on Grit to compute the number of commits between two given
-# commits. To make this depend on Gitaly, a monkey patch is applied
-module Flowdock
- class Git
- # pass down a Repository all the way down
- def repo
- @options[:repo]
- end
-
- def config
- {}
- end
-
- def messages
- Git::Builder.new(repo: repo,
- ref: @ref,
- before: @from,
- after: @to,
- commit_url: @commit_url,
- branch_url: @branch_url,
- diff_url: @diff_url,
- repo_url: @repo_url,
- repo_name: @repo_name,
- permanent_refs: @permanent_refs,
- tags: tags
- ).to_hashes
- end
-
- class Builder
- def commits
- @repo.commits_between(@before, @after).map do |commit|
- {
- url: @opts[:commit_url] ? @opts[:commit_url] % [commit.sha] : nil,
- id: commit.sha,
- message: commit.message,
- author: {
- name: commit.author_name,
- email: commit.author_email
- }
- }
- end
- end
- end
- end
-end
-
class FlowdockService < Service
prop_accessor :token
validates :token, presence: true, if: :activated?
diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb
index 66012f0da99..a69b7b4c4b6 100644
--- a/app/models/project_services/hipchat_service.rb
+++ b/app/models/project_services/hipchat_service.rb
@@ -149,7 +149,7 @@ class HipchatService < Service
context.merge!(options)
- html = Banzai.post_process(Banzai.render(text, context), context)
+ html = Banzai.render_and_post_process(text, context)
sanitized_html = sanitize(html, tags: HIPCHAT_ALLOWED_TAGS, attributes: %w[href title alt])
sanitized_html.truncate(200, separator: ' ', omission: '...')
diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb
index e1d342be188..f54497fc6d8 100644
--- a/app/models/project_services/issue_tracker_service.rb
+++ b/app/models/project_services/issue_tracker_service.rb
@@ -9,12 +9,12 @@ class IssueTrackerService < Service
# Override this method on services that uses different patterns
# This pattern does not support cross-project references
# The other code assumes that this pattern is a superset of all
- # overriden patterns. See ReferenceRegexes::EXTERNAL_PATTERN
+ # overridden patterns. See ReferenceRegexes.external_pattern
def self.reference_pattern(only_long: false)
if only_long
- /(\b[A-Z][A-Z0-9_]+-)(?<issue>\d+)/
+ /(\b[A-Z][A-Z0-9_]*-)(?<issue>\d+)/
else
- /(\b[A-Z][A-Z0-9_]+-|#{Issue.reference_prefix})(?<issue>\d+)/
+ /(\b[A-Z][A-Z0-9_]*-|#{Issue.reference_prefix})(?<issue>\d+)/
end
end
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index ba7fcb0cf93..9066a0b7f1d 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -14,6 +14,9 @@ class JiraService < IssueTrackerService
format: { with: Gitlab::Regex.jira_transition_id_regex, message: "transition ids can have only numbers which can be split with , or ;" },
allow_blank: true
+ # JIRA cloud version is deprecating authentication via username and password.
+ # We should use username/password for JIRA server and email/api_token for JIRA cloud,
+ # for more information check: https://gitlab.com/gitlab-org/gitlab-ce/issues/49936.
prop_accessor :username, :password, :url, :api_url, :jira_issue_transition_id, :title, :description
before_update :reset_password
@@ -51,7 +54,7 @@ class JiraService < IssueTrackerService
{
username: self.username,
password: self.password,
- site: URI.join(url, '/').to_s,
+ site: URI.join(url, '/').to_s, # Intended to find the root
context_path: url.path.chomp('/'),
auth_type: :basic,
read_timeout: 120,
@@ -95,8 +98,8 @@ class JiraService < IssueTrackerService
[
{ type: 'text', name: 'url', title: 'Web URL', placeholder: 'https://jira.example.com', required: true },
{ type: 'text', name: 'api_url', title: 'JIRA API URL', placeholder: 'If different from Web URL' },
- { type: 'text', name: 'username', placeholder: '', required: true },
- { type: 'password', name: 'password', placeholder: '', required: true },
+ { type: 'text', name: 'username', title: 'Username or Email', placeholder: 'Use a username for server version and an email for cloud version', required: true },
+ { type: 'password', name: 'password', title: 'Password or API token', placeholder: 'Use a password for server version and an API token for cloud version', required: true },
{ type: 'text', name: 'jira_issue_transition_id', title: 'Transition ID(s)', placeholder: 'Use , or ; to separate multiple transition IDs' }
]
end
diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb
index f119555f16b..c52a531e5fe 100644
--- a/app/models/project_services/kubernetes_service.rb
+++ b/app/models/project_services/kubernetes_service.rb
@@ -104,7 +104,12 @@ class KubernetesService < DeploymentService
{ success: false, result: err }
end
- def predefined_variables
+ # Project param was added on
+ # https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22011,
+ # as a way to keep this service compatible with
+ # Clusters::Platforms::Kubernetes, it won't be used on this method
+ # as it's only needed for Clusters::Cluster.
+ def predefined_variables(project:)
config = YAML.dump(kubeconfig)
Gitlab::Ci::Variables::Collection.new.tap do |variables|
@@ -144,7 +149,7 @@ class KubernetesService < DeploymentService
end
def kubeclient
- @kubeclient ||= build_kube_client!(api_groups: ['api', 'apis/rbac.authorization.k8s.io'])
+ @kubeclient ||= build_kube_client!
end
def deprecated?
@@ -182,13 +187,11 @@ class KubernetesService < DeploymentService
slug.gsub(/[^-a-z0-9]/, '-').gsub(/^-+/, '')
end
- def build_kube_client!(api_groups: ['api'], api_version: 'v1')
+ def build_kube_client!
raise "Incomplete settings" unless api_url && actual_namespace && token
Gitlab::Kubernetes::KubeClient.new(
api_url,
- api_groups,
- api_version,
auth_options: kubeclient_auth_options,
ssl_options: kubeclient_ssl_options,
http_proxy_uri: ENV['http_proxy']
@@ -200,9 +203,7 @@ class KubernetesService < DeploymentService
kubeclient = build_kube_client!
kubeclient.get_pods(namespace: actual_namespace).as_json
- rescue Kubeclient::HttpError => err
- raise err unless err.error_code == 404
-
+ rescue Kubeclient::ResourceNotFoundError
[]
end
diff --git a/app/models/project_services/microsoft_teams_service.rb b/app/models/project_services/microsoft_teams_service.rb
index 5b0e5fed092..c34078f13c1 100644
--- a/app/models/project_services/microsoft_teams_service.rb
+++ b/app/models/project_services/microsoft_teams_service.rb
@@ -17,7 +17,7 @@ class MicrosoftTeamsService < ChatNotificationService
'This service sends notifications about projects events to Microsoft Teams channels.<br />
To set up this service:
<ol>
- <li><a href="https://msdn.microsoft.com/en-us/microsoft-teams/connectors">Getting started with 365 Office Connectors For Microsoft Teams</a>.</li>
+ <li><a href="https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/connectors/connectors-using#setting-up-a-custom-incoming-webhook">Setup a custom Incoming Webhook using Office 365 Connectors For Microsoft Teams</a>.</li>
<li>Paste the <strong>Webhook URL</strong> into the field below.</li>
<li>Select events below to enable notifications.</li>
</ol>'
diff --git a/app/models/project_services/mock_ci_service.rb b/app/models/project_services/mock_ci_service.rb
index 6883976f0c8..d8bba58dcbf 100644
--- a/app/models/project_services/mock_ci_service.rb
+++ b/app/models/project_services/mock_ci_service.rb
@@ -34,10 +34,9 @@ class MockCiService < CiService
# http://jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c
#
def build_page(sha, ref)
- url = [mock_service_url,
- "#{project.namespace.path}/#{project.path}/status/#{sha}"]
-
- URI.join(*url).to_s
+ Gitlab::Utils.append_path(
+ mock_service_url,
+ "#{project.namespace.path}/#{project.path}/status/#{sha}")
end
# Return string with build status or :error symbol
@@ -61,10 +60,9 @@ class MockCiService < CiService
end
def commit_status_path(sha)
- url = [mock_service_url,
- "#{project.namespace.path}/#{project.path}/status/#{sha}.json"]
-
- URI.join(*url).to_s
+ Gitlab::Utils.append_path(
+ mock_service_url,
+ "#{project.namespace.path}/#{project.path}/status/#{sha}.json")
end
def read_commit_status(response)
diff --git a/app/models/project_services/prometheus_service.rb b/app/models/project_services/prometheus_service.rb
index 509e5b6089b..60cb2d380d5 100644
--- a/app/models/project_services/prometheus_service.rb
+++ b/app/models/project_services/prometheus_service.rb
@@ -26,7 +26,7 @@ class PrometheusService < MonitoringService
end
def editable?
- manual_configuration? || !prometheus_installed?
+ manual_configuration? || !prometheus_available?
end
def title
@@ -56,7 +56,6 @@ class PrometheusService < MonitoringService
name: 'api_url',
title: 'API URL',
placeholder: s_('PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/'),
- help: s_('PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server.'),
required: true
}
]
@@ -72,20 +71,20 @@ class PrometheusService < MonitoringService
end
def prometheus_client
- RestClient::Resource.new(api_url) if api_url && manual_configuration? && active?
+ RestClient::Resource.new(api_url, max_redirects: 0) if api_url && manual_configuration? && active?
end
- def prometheus_installed?
+ def prometheus_available?
return false if template?
return false unless project
- project.clusters.enabled.any? { |cluster| cluster.application_prometheus&.installed? }
+ project.clusters.enabled.any? { |cluster| cluster.application_prometheus_available? }
end
private
def synchronize_service_state
- self.active = prometheus_installed? || manual_configuration?
+ self.active = prometheus_available? || manual_configuration?
true
end
diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb
index eeeff5e802a..b8e17087db5 100644
--- a/app/models/project_services/teamcity_service.rb
+++ b/app/models/project_services/teamcity_service.rb
@@ -132,7 +132,7 @@ class TeamcityService < CiService
end
def build_url(path)
- URI.join("#{teamcity_url}/", path).to_s
+ Gitlab::Utils.append_path(teamcity_url, path)
end
def get_path(path)
diff --git a/app/models/remote_mirror.rb b/app/models/remote_mirror.rb
index c1f53b5da4f..b7b4d0f1be9 100644
--- a/app/models/remote_mirror.rb
+++ b/app/models/remote_mirror.rb
@@ -2,6 +2,7 @@
class RemoteMirror < ActiveRecord::Base
include AfterCommitQueue
+ include MirrorAuthentication
PROTECTED_BACKOFF_DELAY = 1.minute
UNPROTECTED_BACKOFF_DELAY = 5.minutes
@@ -14,8 +15,6 @@ class RemoteMirror < ActiveRecord::Base
insecure_mode: true,
algorithm: 'aes-256-cbc'
- default_value_for :only_protected_branches, true
-
belongs_to :project, inverse_of: :remote_mirrors
validates :url, presence: true, url: { protocols: %w(ssh git http https), allow_blank: true, enforce_user: true }
@@ -28,6 +27,8 @@ class RemoteMirror < ActiveRecord::Base
after_commit :remove_remote, on: :destroy
+ before_validation :store_credentials
+
scope :enabled, -> { where(enabled: true) }
scope :started, -> { with_update_status(:started) }
scope :stuck, -> { started.where('last_update_at < ? OR (last_update_at IS NULL AND updated_at < ?)', 1.day.ago, 1.day.ago) }
@@ -84,7 +85,21 @@ class RemoteMirror < ActiveRecord::Base
end
def update_repository(options)
- raw.update(options)
+ if ssh_mirror_url?
+ if ssh_key_auth? && ssh_private_key.present?
+ options[:ssh_key] = ssh_private_key
+ end
+
+ if ssh_known_hosts.present?
+ options[:known_hosts] = ssh_known_hosts
+ end
+ end
+
+ Gitlab::Git::RemoteMirror.new(
+ project.repository.raw,
+ remote_name,
+ **options
+ ).update
end
def sync?
@@ -128,7 +143,8 @@ class RemoteMirror < ActiveRecord::Base
super(value) && return unless Gitlab::UrlSanitizer.valid?(value)
mirror_url = Gitlab::UrlSanitizer.new(value)
- self.credentials = mirror_url.credentials
+ self.credentials ||= {}
+ self.credentials = self.credentials.merge(mirror_url.credentials)
super(mirror_url.sanitized_url)
end
@@ -152,17 +168,28 @@ class RemoteMirror < ActiveRecord::Base
def ensure_remote!
return unless project
- return unless remote_name && url
+ return unless remote_name && remote_url
# If this fails or the remote already exists, we won't know due to
# https://gitlab.com/gitlab-org/gitaly/issues/1317
- project.repository.add_remote(remote_name, url)
+ project.repository.add_remote(remote_name, remote_url)
end
private
- def raw
- @raw ||= Gitlab::Git::RemoteMirror.new(project.repository.raw, remote_name)
+ def store_credentials
+ # This is a necessary workaround for attr_encrypted, which doesn't otherwise
+ # notice that the credentials have changed
+ self.credentials = self.credentials
+ end
+
+ # The remote URL omits any password if SSH public-key authentication is in use
+ def remote_url
+ return url unless ssh_key_auth? && password.present?
+
+ Gitlab::UrlSanitizer.new(read_attribute(:url), credentials: { user: user }).full_url
+ rescue
+ super
end
def fallback_remote_name
@@ -214,7 +241,7 @@ class RemoteMirror < ActiveRecord::Base
project.repository.async_remove_remote(prev_remote_name)
end
- project.repository.add_remote(remote_name, url)
+ project.repository.add_remote(remote_name, remote_url)
end
def remove_remote
@@ -224,6 +251,6 @@ class RemoteMirror < ActiveRecord::Base
end
def mirror_url_changed?
- url_changed? || encrypted_credentials_changed?
+ url_changed? || credentials_changed?
end
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index ad65881ff43..35dd120856d 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -24,7 +24,6 @@ class Repository
delegate :ref_name_for_sha, to: :raw_repository
delegate :bundle_to_disk, to: :raw_repository
- delegate :find_remote_root_ref, to: :raw_repository
CreateTreeError = Class.new(StandardError)
@@ -36,8 +35,8 @@ class Repository
#
# For example, for entry `:commit_count` there's a method called `commit_count` which
# stores its data in the `commit_count` cache key.
- CACHED_METHODS = %i(size commit_count rendered_readme contribution_guide
- changelog license_blob license_key gitignore koding_yml
+ CACHED_METHODS = %i(size commit_count rendered_readme readme_path contribution_guide
+ changelog license_blob license_key gitignore
gitlab_ci_yml branch_names tag_names branch_count
tag_count avatar exists? root_ref has_visible_content?
issue_template_names merge_request_template_names xcode_project?).freeze
@@ -49,12 +48,11 @@ class Repository
# changed. This Hash maps file types (as returned by Gitlab::FileDetector) to
# the corresponding methods to call for refreshing caches.
METHOD_CACHES_FOR_FILE_TYPES = {
- readme: :rendered_readme,
+ readme: %i(rendered_readme readme_path),
changelog: :changelog,
license: %i(license_blob license_key license),
contributing: :contribution_guide,
gitignore: :gitignore,
- koding: :koding_yml,
gitlab_ci: :gitlab_ci_yml,
avatar: :avatar,
issue_template: :issue_template_names,
@@ -71,7 +69,13 @@ class Repository
end
def ==(other)
- @disk_path == other.disk_path
+ other.is_a?(self.class) && @disk_path == other.disk_path
+ end
+
+ alias_method :eql?, :==
+
+ def hash
+ [self.class, @disk_path].hash
end
def raw_repository
@@ -255,7 +259,7 @@ class Repository
next if kept_around?(sha)
# This will still fail if the file is corrupted (e.g. 0 bytes)
- raw_repository.write_ref(keep_around_ref_name(sha), sha, shell: false)
+ raw_repository.write_ref(keep_around_ref_name(sha), sha)
rescue Gitlab::Git::CommandError => ex
Rails.logger.error "Unable to create keep-around reference for repository #{disk_path}: #{ex}"
end
@@ -489,7 +493,20 @@ class Repository
end
def blob_at(sha, path)
- Blob.decorate(raw_repository.blob_at(sha, path), project)
+ blob = Blob.decorate(raw_repository.blob_at(sha, path), project)
+
+ # Don't attempt to return a special result if there is no blob at all
+ return unless blob
+
+ # Don't attempt to return a special result unless we're looking at HEAD
+ return blob unless head_commit&.sha == sha
+
+ case path
+ when head_tree&.readme_path
+ ReadmeBlob.new(blob, self)
+ else
+ blob
+ end
rescue Gitlab::Git::Repository::NoRepository
nil
end
@@ -511,7 +528,7 @@ class Repository
raw_repository.exists?
end
- cache_method :exists?
+ cache_method_asymmetrically :exists?
# We don't need to cache the output of this method because both exists? and
# has_visible_content? are already memoized and cached. There's no guarantee
@@ -571,11 +588,14 @@ class Repository
cache_method :merge_request_template_names, fallback: []
def readme
- if readme = tree(:head)&.readme
- ReadmeBlob.new(readme, self)
- end
+ head_tree&.readme
end
+ def readme_path
+ readme&.path
+ end
+ cache_method :readme_path
+
def rendered_readme
return unless readme
@@ -613,18 +633,13 @@ class Repository
Licensee::License.new(license_key)
end
- cache_method :license, memoize_only: true
+ memoize_method :license
def gitignore
file_on_head(:gitignore)
end
cache_method :gitignore
- def koding_yml
- file_on_head(:koding)
- end
- cache_method :koding_yml
-
def gitlab_ci_yml
file_on_head(:gitlab_ci)
end
@@ -669,6 +684,14 @@ class Repository
end
end
+ def list_last_commits_for_tree(sha, path, offset: 0, limit: 25)
+ commits = raw_repository.list_last_commits_for_tree(sha, path, offset: offset, limit: limit)
+
+ commits.each do |path, commit|
+ commits[path] = ::Commit.new(commit, @project)
+ end
+ end
+
def last_commit_for_path(sha, path)
commit = raw_repository.last_commit_for_path(sha, path)
::Commit.new(commit, @project) if commit
@@ -874,10 +897,12 @@ class Repository
delegate :merged_branch_names, to: :raw_repository
- def merge_base(first_commit_id, second_commit_id)
- first_commit_id = commit(first_commit_id).try(:id) || first_commit_id
- second_commit_id = commit(second_commit_id).try(:id) || second_commit_id
- raw_repository.merge_base(first_commit_id, second_commit_id)
+ def merge_base(*commits_or_ids)
+ commit_ids = commits_or_ids.map do |commit_or_id|
+ commit_or_id.is_a?(::Commit) ? commit_or_id.id : commit_or_id
+ end
+
+ raw_repository.merge_base(*commit_ids)
end
def ancestor?(ancestor_id, descendant_id)
@@ -898,10 +923,6 @@ class Repository
async_remove_remote(remote_name) if tmp_remote_name
end
- def fetch_remote(remote, forced: false, ssh_auth: nil, no_tags: false, prune: true)
- gitlab_shell.fetch_remote(raw_repository, remote, ssh_auth: ssh_auth, forced: forced, no_tags: no_tags, prune: prune)
- end
-
def async_remove_remote(remote_name)
return unless remote_name
@@ -1004,6 +1025,18 @@ class Repository
message: merge_request.title)
end
+ def update_submodule(user, submodule, commit_sha, message:, branch:)
+ with_cache_hooks do
+ raw.update_submodule(
+ user: user,
+ submodule: submodule,
+ commit_sha: commit_sha,
+ branch: branch,
+ message: message
+ )
+ end
+ end
+
def blob_data_at(sha, path)
blob = blob_at(sha, path)
return unless blob
@@ -1027,7 +1060,19 @@ class Repository
end
def cache
- @cache ||= Gitlab::RepositoryCache.new(self)
+ @cache ||= if is_wiki
+ Gitlab::RepositoryCache.new(self, extra_namespace: 'wiki')
+ else
+ Gitlab::RepositoryCache.new(self)
+ end
+ end
+
+ def request_store_cache
+ @request_store_cache ||= if is_wiki
+ Gitlab::RepositoryCache.new(self, extra_namespace: 'wiki', backend: Gitlab::SafeRequestStore)
+ else
+ Gitlab::RepositoryCache.new(self, backend: Gitlab::SafeRequestStore)
+ end
end
def tags_sorted_by_committed_date
diff --git a/app/models/service.rb b/app/models/service.rb
index 4dbda7acab6..5b8bf6e7cf0 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -253,6 +253,7 @@ class Service < ActiveRecord::Base
bugzilla
campfire
custom_issue_tracker
+ discord
drone_ci
emails_on_push
external_wiki
diff --git a/app/models/shard.rb b/app/models/shard.rb
new file mode 100644
index 00000000000..2e75bc91df0
--- /dev/null
+++ b/app/models/shard.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class Shard < ActiveRecord::Base
+ # Store shard names from the configuration file in the database. This is not a
+ # list of active shards - we just want to assign an immutable, unique ID to
+ # every shard name for easy indexing / referencing.
+ def self.populate!
+ return unless table_exists?
+
+ # The GitLab config does not change for the lifecycle of the process
+ in_config = Gitlab.config.repositories.storages.keys.map(&:to_s)
+ in_db = all.pluck(:name)
+
+ # This may race with other processes creating shards at the same time, but
+ # `by_name` will handle that correctly
+ missing = in_config - in_db
+ missing.map { |name| by_name(name) }
+ end
+
+ def self.by_name(name)
+ find_or_create_by(name: name)
+ rescue ActiveRecord::RecordNotUnique
+ retry
+ end
+end
diff --git a/app/models/site_statistic.rb b/app/models/site_statistic.rb
deleted file mode 100644
index 48324570f0b..00000000000
--- a/app/models/site_statistic.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-# frozen_string_literal: true
-
-class SiteStatistic < ActiveRecord::Base
- # prevents the creation of multiple rows
- default_value_for :id, 1
-
- COUNTER_ATTRIBUTES = %w(repositories_count wikis_count).freeze
- REQUIRED_SCHEMA_VERSION = 20180629153018
-
- # Tracks specific attribute
- #
- # @param [String] raw_attribute must be one of the values listed in COUNTER_ATTRIBUTES
- def self.track(raw_attribute)
- with_statistics_available(raw_attribute) do |attribute|
- SiteStatistic.update_all(["#{attribute} = #{attribute}+1"])
- end
- end
-
- # Untracks specific attribute
- #
- # @param [String] raw_attribute must be one of the values listed in COUNTER_ATTRIBUTES
- def self.untrack(raw_attribute)
- with_statistics_available(raw_attribute) do |attribute|
- SiteStatistic.update_all(["#{attribute} = #{attribute}-1 WHERE #{attribute} > 0"])
- end
- end
-
- # Wrapper for track/untrack operations with basic validations and enforced requirements
- #
- # @param [String] raw_attribute must be one of the values listed in COUNTER_ATTRIBUTES
- # @yield [String] attribute quoted to be used inside SQL / Arel query
- def self.with_statistics_available(raw_attribute)
- unless raw_attribute.in?(COUNTER_ATTRIBUTES)
- raise ArgumentError, "Invalid attribute: '#{raw_attribute}' to '#{caller_locations(1, 1)[0].label}' method. " \
- "Valid attributes are: #{COUNTER_ATTRIBUTES.join(', ')}"
- end
-
- return unless available?
-
- self.fetch # make sure record exists
-
- attribute = self.connection.quote_column_name(raw_attribute)
-
- # will be running on its own transaction context
- yield(attribute)
- end
-
- # Returns a site statistic record with tracked information
- #
- # @return [SiteStatistic] record with tracked information
- def self.fetch
- transaction(requires_new: true) do
- SiteStatistic.first_or_create!
- end
- rescue ActiveRecord::RecordNotUnique
- retry
- end
-
- # Return whether required schema change is available
- #
- # This is needed in order to degrade gracefully when testing schema migrations
- #
- # @return [Boolean] whether schema is available
- def self.available?
- @available_flag ||= ActiveRecord::Migrator.current_version >= REQUIRED_SCHEMA_VERSION
- end
-
- # Resets cached column information
- #
- # This is called during schema migration specs, in order to reset internal cache state
- def self.reset_column_information
- @available_flag = nil
-
- super
- end
-end
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index e9533ee7c77..11856b55902 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -2,6 +2,7 @@
class Snippet < ActiveRecord::Base
include Gitlab::VisibilityLevel
+ include Redactable
include CacheMarkdownField
include Noteable
include Participable
@@ -18,6 +19,8 @@ class Snippet < ActiveRecord::Base
cache_markdown_field :description
cache_markdown_field :content
+ redact_field :description
+
# Aliases to make application_helper#edited_time_ago_with_tooltip helper work properly with snippets.
# See https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10392/diffs#note_28719102
alias_attribute :last_edited_at, :updated_at
@@ -60,6 +63,62 @@ class Snippet < ActiveRecord::Base
attr_spammable :title, spam_title: true
attr_spammable :content, spam_description: true
+ def self.with_optional_visibility(value = nil)
+ if value
+ where(visibility_level: value)
+ else
+ all
+ end
+ end
+
+ def self.only_global_snippets
+ where(project_id: nil)
+ end
+
+ def self.only_include_projects_visible_to(current_user = nil)
+ levels = Gitlab::VisibilityLevel.levels_for_user(current_user)
+
+ joins(:project).where('projects.visibility_level IN (?)', levels)
+ end
+
+ def self.only_include_projects_with_snippets_enabled(include_private: false)
+ column = ProjectFeature.access_level_attribute(:snippets)
+ levels = [ProjectFeature::ENABLED, ProjectFeature::PUBLIC]
+
+ levels << ProjectFeature::PRIVATE if include_private
+
+ joins(project: :project_feature)
+ .where(project_features: { column => levels })
+ end
+
+ def self.only_include_authorized_projects(current_user)
+ where(
+ 'EXISTS (?)',
+ ProjectAuthorization
+ .select(1)
+ .where('project_id = snippets.project_id')
+ .where(user_id: current_user.id)
+ )
+ end
+
+ def self.for_project_with_user(project, user = nil)
+ return none unless project.snippets_visible?(user)
+
+ if user && project.team.member?(user)
+ project.snippets
+ else
+ project.snippets.public_to_user(user)
+ end
+ end
+
+ def self.visible_to_or_authored_by(user)
+ where(
+ 'snippets.visibility_level IN (?) OR snippets.author_id = ?',
+ Gitlab::VisibilityLevel.levels_for_user(user),
+ user.id
+ )
+ end
+
def self.reference_prefix
'$'
end
@@ -78,27 +137,6 @@ class Snippet < ActiveRecord::Base
@link_reference_pattern ||= super("snippets", /(?<snippet>\d+)/)
end
- # Returns a collection of snippets that are either public or visible to the
- # logged in user.
- #
- # This method does not verify the user actually has the access to the project
- # the snippet is in, so it should be only used on a relation that's already scoped
- # for project access
- def self.public_or_visible_to_user(user = nil)
- if user
- authorized = user
- .project_authorizations
- .select(1)
- .where('project_authorizations.project_id = snippets.project_id')
-
- levels = Gitlab::VisibilityLevel.levels_for_user(user)
-
- where('EXISTS (?) OR snippets.visibility_level IN (?) or snippets.author_id = (?)', authorized, levels, user.id)
- else
- public_to_user
- end
- end
-
def to_reference(from = nil, full: false)
reference = "#{self.class.reference_prefix}#{id}"
diff --git a/app/models/ssh_host_key.rb b/app/models/ssh_host_key.rb
new file mode 100644
index 00000000000..b6844dbe870
--- /dev/null
+++ b/app/models/ssh_host_key.rb
@@ -0,0 +1,130 @@
+# frozen_string_literal: true
+
+# Detected SSH host keys are transiently stored in Redis
+class SshHostKey
+ class Fingerprint < Gitlab::SSHPublicKey
+ attr_reader :index
+
+ def initialize(key, index: nil)
+ super(key)
+
+ @index = index
+ end
+
+ def as_json(*)
+ { bits: bits, fingerprint: fingerprint, type: type, index: index }
+ end
+ end
+
+ include ReactiveCaching
+
+ self.reactive_cache_key = ->(key) { [key.class.to_s, key.id] }
+
+ # Do not refresh the data in the background - it is not expected to change.
+ # This is achieved by making the lifetime shorter than the refresh interval.
+ self.reactive_cache_refresh_interval = 15.minutes
+ self.reactive_cache_lifetime = 10.minutes
+
+ def self.find_by(opts = {})
+ return nil unless opts.key?(:id)
+
+ project_id, url = opts[:id].split(':', 2)
+ project = Project.find_by(id: project_id)
+
+ project.presence && new(project: project, url: url)
+ end
+
+ def self.fingerprint_host_keys(data)
+ return [] unless data.is_a?(String)
+
+ data
+ .each_line
+ .each_with_index
+ .map { |line, index| Fingerprint.new(line, index: index) }
+ .select(&:valid?)
+ end
+
+ attr_reader :project, :url, :compare_host_keys
+
+ def initialize(project:, url:, compare_host_keys: nil)
+ @project = project
+ @url = normalize_url(url)
+ @compare_host_keys = compare_host_keys
+ end
+
+ def id
+ [project.id, url].join(':')
+ end
+
+ def as_json(*)
+ {
+ host_keys_changed: host_keys_changed?,
+ fingerprints: fingerprints,
+ known_hosts: known_hosts
+ }
+ end
+
+ def known_hosts
+ with_reactive_cache { |data| data[:known_hosts] }
+ end
+
+ def fingerprints
+ @fingerprints ||= self.class.fingerprint_host_keys(known_hosts)
+ end
+
+ # Returns true if the known_hosts data differs from the version passed in at
+ # initialization as `compare_host_keys`. Comments, ordering, etc, is ignored
+ def host_keys_changed?
+ cleanup(known_hosts) != cleanup(compare_host_keys)
+ end
+
+ def error
+ with_reactive_cache { |data| data[:error] }
+ end
+
+ def calculate_reactive_cache
+ known_hosts, errors, status =
+ Open3.popen3({}, *%W[ssh-keyscan -T 5 -p #{url.port} -f-]) do |stdin, stdout, stderr, wait_thr|
+ stdin.puts(url.host)
+ stdin.close
+
+ [
+ cleanup(stdout.read),
+ cleanup(stderr.read),
+ wait_thr.value
+ ]
+ end
+
+ # ssh-keyscan returns an exit code 0 in several error conditions, such as an
+ # unknown hostname, so check both STDERR and the exit code
+ if status.success? && !errors.present?
+ { known_hosts: known_hosts }
+ else
+ Rails.logger.debug("Failed to detect SSH host keys for #{id}: #{errors}")
+
+ { error: 'Failed to detect SSH host keys' }
+ end
+ end
+
+ private
+
+ # Remove comments and duplicate entries
+ def cleanup(data)
+ data
+ .to_s
+ .each_line
+ .reject { |line| line.start_with?('#') || line.chomp.empty? }
+ .uniq
+ .sort
+ .join
+ end
+
+ def normalize_url(url)
+ full_url = ::Addressable::URI.parse(url)
+ raise ArgumentError.new("Invalid URL") unless full_url&.scheme == 'ssh'
+
+ Addressable::URI.parse("ssh://#{full_url.host}:#{full_url.inferred_port}")
+ rescue Addressable::URI::InvalidURIError
+ raise ArgumentError.new("Invalid URL")
+ end
+end
diff --git a/app/models/storage/hashed_project.rb b/app/models/storage/hashed_project.rb
index 90710f73fd3..911fb7e9ce9 100644
--- a/app/models/storage/hashed_project.rb
+++ b/app/models/storage/hashed_project.rb
@@ -5,17 +5,19 @@ module Storage
attr_accessor :project
delegate :gitlab_shell, :repository_storage, to: :project
- ROOT_PATH_PREFIX = '@hashed'.freeze
+ REPOSITORY_PATH_PREFIX = '@hashed'
+ POOL_PATH_PREFIX = '@pools'
- def initialize(project)
+ def initialize(project, prefix: REPOSITORY_PATH_PREFIX)
@project = project
+ @prefix = prefix
end
# Base directory
#
# @return [String] directory where repository is stored
def base_dir
- "#{ROOT_PATH_PREFIX}/#{disk_hash[0..1]}/#{disk_hash[2..3]}" if disk_hash
+ "#{@prefix}/#{disk_hash[0..1]}/#{disk_hash[2..3]}" if disk_hash
end
# Disk path is used to build repository and project's wiki path on disk
diff --git a/app/models/system_note_metadata.rb b/app/models/system_note_metadata.rb
index 6fadbcefa53..d555ebe5322 100644
--- a/app/models/system_note_metadata.rb
+++ b/app/models/system_note_metadata.rb
@@ -9,6 +9,7 @@ class SystemNoteMetadata < ActiveRecord::Base
TYPES_WITH_CROSS_REFERENCES = %w[
commit cross_reference
close duplicate
+ moved
].freeze
ICON_TYPES = %w[
@@ -26,4 +27,8 @@ class SystemNoteMetadata < ActiveRecord::Base
def icon_types
ICON_TYPES
end
+
+ def cross_reference_types
+ TYPES_WITH_CROSS_REFERENCES
+ end
end
diff --git a/app/models/todo.rb b/app/models/todo.rb
index 265fb932f7c..7b64615f699 100644
--- a/app/models/todo.rb
+++ b/app/models/todo.rb
@@ -40,6 +40,13 @@ class Todo < ActiveRecord::Base
scope :pending, -> { with_state(:pending) }
scope :done, -> { with_state(:done) }
+ scope :for_action, -> (action) { where(action: action) }
+ scope :for_author, -> (author) { where(author: author) }
+ scope :for_project, -> (project) { where(project: project) }
+ scope :for_group, -> (group) { where(group: group) }
+ scope :for_type, -> (type) { where(target_type: type) }
+ scope :for_target, -> (id) { where(target_id: id) }
+ scope :for_commit, -> (id) { where(commit_id: id) }
state_machine :state, initial: :pending do
event :done do
@@ -53,6 +60,42 @@ class Todo < ActiveRecord::Base
after_save :keep_around_commit, if: :commit_id
class << self
+ # Returns all todos for the given group and its descendants.
+ #
+ # group - A `Group` to retrieve todos for.
+ #
+ # Returns an `ActiveRecord::Relation`.
+ def for_group_and_descendants(group)
+ groups = group.self_and_descendants
+
+ from_union([
+ for_project(Project.for_group(groups)),
+ for_group(groups)
+ ])
+ end
+
+ # Returns `true` if the current user has any todos for the given target.
+ #
+ # target - The value of the `target_type` column, such as `Issue`.
+ def any_for_target?(target)
+ exists?(target: target)
+ end
+
+ # Updates the state of a relation of todos to the new state.
+ #
+ # new_state - The new state of the todos.
+ #
+ # Returns an `Array` containing the IDs of the updated todos.
+ def update_state(new_state)
+ # Only update those that are not really on that state
+ base = where.not(state: new_state).except(:order)
+ ids = base.pluck(:id)
+
+ base.update_all(state: new_state)
+
+ ids
+ end
+
# Priority sorting isn't displayed in the dropdown, because we don't show
# milestones, but still show something if the user has a URL with that
# selected.
diff --git a/app/models/tree.rb b/app/models/tree.rb
index 3641c33254c..cd385872171 100644
--- a/app/models/tree.rb
+++ b/app/models/tree.rb
@@ -2,6 +2,7 @@
class Tree
include Gitlab::MarkupHelper
+ include Gitlab::Utils::StrongMemoize
attr_accessor :repository, :sha, :path, :entries
@@ -16,32 +17,36 @@ class Tree
@entries = Gitlab::Git::Tree.where(git_repo, @sha, @path, recursive)
end
- def readme
- return @readme if defined?(@readme)
-
- available_readmes = blobs.select do |blob|
- Gitlab::FileDetector.type_of(blob.name) == :readme
- end
-
- previewable_readmes = available_readmes.select do |blob|
- previewable?(blob.name)
- end
-
- plain_readmes = available_readmes.select do |blob|
- plain?(blob.name)
+ def readme_path
+ strong_memoize(:readme_path) do
+ available_readmes = blobs.select do |blob|
+ Gitlab::FileDetector.type_of(blob.name) == :readme
+ end
+
+ previewable_readmes = available_readmes.select do |blob|
+ previewable?(blob.name)
+ end
+
+ plain_readmes = available_readmes.select do |blob|
+ plain?(blob.name)
+ end
+
+ # Prioritize previewable over plain readmes
+ entry = previewable_readmes.first || plain_readmes.first
+ next nil unless entry
+
+ if path == '/'
+ entry.name
+ else
+ File.join(path, entry.name)
+ end
end
+ end
- # Prioritize previewable over plain readmes
- readme_tree = previewable_readmes.first || plain_readmes.first
-
- # Return if we can't preview any of them
- if readme_tree.nil?
- return @readme = nil
+ def readme
+ strong_memoize(:readme) do
+ repository.blob_at(sha, readme_path) if readme_path
end
-
- readme_path = path == '/' ? readme_tree.name : File.join(path, readme_tree.name)
-
- @readme = repository.blob_at(sha, readme_path)
end
def trees
diff --git a/app/models/upload.rb b/app/models/upload.rb
index 23bc9ca42fc..e01e9c6a4f0 100644
--- a/app/models/upload.rb
+++ b/app/models/upload.rb
@@ -11,7 +11,8 @@ class Upload < ActiveRecord::Base
validates :model, presence: true
validates :uploader, presence: true
- scope :with_files_stored_locally, -> { where(store: [nil, ObjectStorage::Store::LOCAL]) }
+ scope :with_files_stored_locally, -> { where(store: ObjectStorage::Store::LOCAL) }
+ scope :with_files_stored_remotely, -> { where(store: ObjectStorage::Store::REMOTE) }
before_save :calculate_checksum!, if: :foreground_checksummable?
after_commit :schedule_checksum, if: :checksummable?
@@ -46,7 +47,18 @@ class Upload < ActiveRecord::Base
end
def exist?
- File.exist?(absolute_path)
+ exist = File.exist?(absolute_path)
+
+ # Help sysadmins find missing upload files
+ if persisted? && !exist
+ if Gitlab::Sentry.enabled?
+ Raven.capture_message("Upload file does not exist", extra: self.attributes)
+ end
+
+ Gitlab::Metrics.counter(:upload_file_does_not_exist_total, 'The number of times an upload record could not find its file').increment
+ end
+
+ exist
end
def uploader_context
@@ -57,8 +69,6 @@ class Upload < ActiveRecord::Base
end
def local?
- return true if store.nil?
-
store == ObjectStorage::Store::LOCAL
end
diff --git a/app/models/user.rb b/app/models/user.rb
index eeac87e2e52..dbd754dd25a 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -28,7 +28,7 @@ class User < ActiveRecord::Base
ignore_column :email_provider
ignore_column :authentication_token
- add_authentication_token_field :incoming_email_token
+ add_authentication_token_field :incoming_email_token, token_generator: -> { SecureRandom.hex.to_i(16).to_s(36) }
add_authentication_token_field :feed_token
default_value_for :admin, false
@@ -88,7 +88,7 @@ class User < ActiveRecord::Base
has_one :namespace, -> { where(type: nil) }, dependent: :destroy, foreign_key: :owner_id, inverse_of: :owner, autosave: true # rubocop:disable Cop/ActiveRecordDependent
# Profile
- has_many :keys, -> { where(type: ['Key', nil]) }, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_many :keys, -> { regular_keys }, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :deploy_keys, -> { where(type: 'DeployKey') }, dependent: :nullify # rubocop:disable Cop/ActiveRecordDependent
has_many :gpg_keys
@@ -152,6 +152,7 @@ class User < ActiveRecord::Base
belongs_to :accepted_term, class_name: 'ApplicationSetting::Term'
has_one :status, class_name: 'UserStatus'
+ has_one :user_preference
#
# Validations
@@ -217,13 +218,15 @@ class User < ActiveRecord::Base
# User's Dashboard preference
# Note: When adding an option, it MUST go on the end of the array.
- enum dashboard: [:projects, :stars, :project_activity, :starred_project_activity, :groups, :todos, :issues, :merge_requests]
+ enum dashboard: [:projects, :stars, :project_activity, :starred_project_activity, :groups, :todos, :issues, :merge_requests, :operations]
# User's Project preference
# Note: When adding an option, it MUST go on the end of the array.
enum project_view: [:readme, :activity, :files]
delegate :path, to: :namespace, allow_nil: true, prefix: true
+ delegate :notes_filter_for, to: :user_preference
+ delegate :set_notes_filter, to: :user_preference
state_machine :state, initial: :active do
event :block do
@@ -264,7 +267,8 @@ class User < ActiveRecord::Base
scope :order_recent_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('current_sign_in_at', 'DESC')) }
scope :order_oldest_sign_in, -> { reorder(Gitlab::Database.nulls_last_order('current_sign_in_at', 'ASC')) }
scope :confirmed, -> { where.not(confirmed_at: nil) }
- scope :by_username, -> (usernames) { iwhere(username: usernames) }
+ scope :by_username, -> (usernames) { iwhere(username: Array(usernames).map(&:to_s)) }
+ scope :for_todos, -> (todos) { where(id: todos.select(:user_id)) }
# Limits the users to those that have TODOs, optionally in the given state.
#
@@ -343,18 +347,36 @@ class User < ActiveRecord::Base
# Find a User by their primary email or any associated secondary email
def find_by_any_email(email, confirmed: false)
+ return unless email
+
by_any_email(email, confirmed: confirmed).take
end
- # Returns a relation containing all the users for the given Email address
- def by_any_email(email, confirmed: false)
- users = where(email: email)
- users = users.confirmed if confirmed
+ # Returns a relation containing all the users for the given email addresses
+ #
+ # @param emails [String, Array<String>] email addresses to check
+ # @param confirmed [Boolean] Only return users where the email is confirmed
+ def by_any_email(emails, confirmed: false)
+ emails = Array(emails).map(&:downcase)
+
+ from_users = where(email: emails)
+ from_users = from_users.confirmed if confirmed
+
+ from_emails = joins(:emails).where(emails: { email: emails })
+ from_emails = from_emails.confirmed.merge(Email.confirmed) if confirmed
+
+ items = [from_users, from_emails]
- emails = joins(:emails).where(emails: { email: email })
- emails = emails.confirmed if confirmed
+ user_ids = Gitlab::PrivateCommitEmail.user_ids_for_emails(emails)
+ items << where(id: user_ids) if user_ids.present?
- from_union([users, emails])
+ from_union(items)
+ end
+
+ def find_by_private_commit_email(email)
+ user_id = Gitlab::PrivateCommitEmail.user_id_for_email(email)
+
+ find_by(id: user_id)
end
def filter(filter_name)
@@ -456,12 +478,6 @@ class User < ActiveRecord::Base
by_username(username).take!
end
- def find_by_personal_access_token(token_string)
- return unless token_string
-
- PersonalAccessTokensFinder.new(state: 'active').find_by(token: token_string)&.user # rubocop: disable CodeReuse/Finder
- end
-
# Returns a user for the given SSH key.
def find_by_ssh_key_id(key_id)
Key.find_by(id: key_id)&.user
@@ -635,6 +651,10 @@ class User < ActiveRecord::Base
def commit_email
return self.email unless has_attribute?(:commit_email)
+ if super == Gitlab::PrivateCommitEmail::TOKEN
+ return private_commit_email
+ end
+
# The commit email is the same as the primary email if undefined
super.presence || self.email
end
@@ -647,6 +667,10 @@ class User < ActiveRecord::Base
has_attribute?(:commit_email) && super
end
+ def private_commit_email
+ Gitlab::PrivateCommitEmail.for_user(self)
+ end
+
# see if the new email is already a verified secondary email
def check_for_verified_email
skip_reconfirmation! if emails.confirmed.where(email: self.email).any?
@@ -674,10 +698,12 @@ class User < ActiveRecord::Base
# Returns the groups a user has access to, either through a membership or a project authorization
def authorized_groups
- Group.from_union([
- groups,
- authorized_projects.joins(:namespace).select('namespaces.*')
- ])
+ Group.unscoped do
+ Group.from_union([
+ groups,
+ authorized_projects.joins(:namespace).select('namespaces.*')
+ ])
+ end
end
# Returns the groups a user is a member of, either directly or through a parent group
@@ -935,12 +961,17 @@ class User < ActiveRecord::Base
if !Gitlab.config.ldap.enabled
false
elsif ldap_user?
- !last_credential_check_at || (last_credential_check_at + 1.hour) < Time.now
+ !last_credential_check_at || (last_credential_check_at + ldap_sync_time) < Time.now
else
false
end
end
+ def ldap_sync_time
+ # This number resides in this method so it can be redefined in EE.
+ 1.hour
+ end
+
def try_obtain_ldap_lease
# After obtaining this lease LDAP checks will be blocked for 600 seconds
# (10 minutes) for this user.
@@ -1008,6 +1039,7 @@ class User < ActiveRecord::Base
def all_emails
all_emails = []
all_emails << email unless temp_oauth_email?
+ all_emails << private_commit_email
all_emails.concat(emails.map(&:email))
all_emails
end
@@ -1015,13 +1047,29 @@ class User < ActiveRecord::Base
def verified_emails
verified_emails = []
verified_emails << email if primary_email_verified?
+ verified_emails << private_commit_email
verified_emails.concat(emails.confirmed.pluck(:email))
verified_emails
end
+ def any_email?(check_email)
+ downcased = check_email.downcase
+
+ # handle the outdated private commit email case
+ return true if persisted? &&
+ id == Gitlab::PrivateCommitEmail.user_id_for_email(downcased)
+
+ all_emails.include?(check_email.downcase)
+ end
+
def verified_email?(check_email)
downcased = check_email.downcase
- email == downcased ? primary_email_verified? : emails.confirmed.where(email: downcased).exists?
+
+ # handle the outdated private commit email case
+ return true if persisted? &&
+ id == Gitlab::PrivateCommitEmail.user_id_for_email(downcased)
+
+ verified_emails.include?(check_email.downcase)
end
def hook_attrs
@@ -1132,7 +1180,7 @@ class User < ActiveRecord::Base
events = Event.select(:project_id)
.contributions.where(author_id: self)
.where("created_at > ?", Time.now - 1.year)
- .uniq
+ .distinct
.reorder(nil)
Project.where(id: events)
@@ -1364,6 +1412,15 @@ class User < ActiveRecord::Base
!consented_usage_stats? && 7.days.ago > self.created_at && !has_current_license? && User.single_user?
end
+ # Avoid migrations only building user preference object when needed.
+ def user_preference
+ super.presence || build_user_preference
+ end
+
+ def todos_limited_to(ids)
+ todos.where(id: ids)
+ end
+
# @deprecated
alias_method :owned_or_masters_groups, :owned_or_maintainers_groups
@@ -1449,15 +1506,6 @@ class User < ActiveRecord::Base
end
end
- def generate_token(token_field)
- if token_field == :incoming_email_token
- # Needs to be all lowercase and alphanumeric because it's gonna be used in an email address.
- SecureRandom.hex.to_i(16).to_s(36)
- else
- super
- end
- end
-
def self.unique_internal(scope, username, email_pattern, &block)
scope.first || create_unique_internal(scope, username, email_pattern, &block)
end
diff --git a/app/models/user_callout.rb b/app/models/user_callout.rb
index 1cd05cf3aac..76e7bc06b4e 100644
--- a/app/models/user_callout.rb
+++ b/app/models/user_callout.rb
@@ -3,11 +3,9 @@
class UserCallout < ActiveRecord::Base
belongs_to :user
- enum feature_name: {
- gke_cluster_integration: 1,
- gcp_signup_offer: 2,
- cluster_security_warning: 3
- }
+ # We use `UserCalloutEnums.feature_names` here so that EE can more easily
+ # extend this `Hash` with new values.
+ enum feature_name: ::UserCalloutEnums.feature_names
validates :user, presence: true
validates :feature_name,
diff --git a/app/models/user_callout_enums.rb b/app/models/user_callout_enums.rb
new file mode 100644
index 00000000000..b9373ae6166
--- /dev/null
+++ b/app/models/user_callout_enums.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module UserCalloutEnums
+ # Returns the `Hash` to use for the `feature_name` enum in the `UserCallout`
+ # model.
+ #
+ # This method is separate from the `UserCallout` model so that it can be
+ # extended by EE.
+ def self.feature_names
+ {
+ gke_cluster_integration: 1,
+ gcp_signup_offer: 2,
+ cluster_security_warning: 3
+ }
+ end
+end
diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb
new file mode 100644
index 00000000000..32d0407800f
--- /dev/null
+++ b/app/models/user_preference.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+class UserPreference < ActiveRecord::Base
+ # We could use enums, but Rails 4 doesn't support multiple
+ # enum options with same name for multiple fields, also it creates
+ # extra methods that aren't really needed here.
+ NOTES_FILTERS = { all_notes: 0, only_comments: 1, only_activity: 2 }.freeze
+
+ belongs_to :user
+
+ validates :issue_notes_filter, :merge_request_notes_filter, inclusion: { in: NOTES_FILTERS.values }, presence: true
+
+ class << self
+ def notes_filters
+ {
+ s_('Notes|Show all activity') => NOTES_FILTERS[:all_notes],
+ s_('Notes|Show comments only') => NOTES_FILTERS[:only_comments],
+ s_('Notes|Show history only') => NOTES_FILTERS[:only_activity]
+ }
+ end
+ end
+
+ def set_notes_filter(filter_id, issuable)
+ # No need to update the column if the value is already set.
+ if filter_id && NOTES_FILTERS.values.include?(filter_id)
+ field = notes_filter_field_for(issuable)
+ self[field] = filter_id
+
+ save if attribute_changed?(field)
+ end
+
+ notes_filter_for(issuable)
+ end
+
+ # Returns the current discussion filter for a given issuable
+ # or issuable type.
+ def notes_filter_for(resource)
+ self[notes_filter_field_for(resource)]
+ end
+
+ private
+
+ def notes_filter_field_for(resource)
+ field_key =
+ if resource.is_a?(Issuable)
+ resource.model_name.param_key
+ else
+ resource
+ end
+
+ "#{field_key}_notes_filter"
+ end
+end
diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index 102907a8bd3..b1d6d461928 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -58,7 +58,7 @@ class WikiPage
attr_reader :page
# The attributes Hash used for storing and validating
- # new Page values before writing to the Gollum repository.
+ # new Page values before writing to the raw repository.
attr_accessor :attributes
def hook_attrs
@@ -85,6 +85,12 @@ class WikiPage
alias_method :to_param, :slug
+ def human_title
+ return 'Home' if title == 'home'
+
+ title
+ end
+
# The formatted title of this page.
def title
if @attributes[:title]
@@ -111,10 +117,7 @@ class WikiPage
# The processed/formatted content of this page.
def formatted_content
- # Assuming @page exists, nil formatted_data means we didn't load it
- # before hand (i.e. page was fetched by Gitaly), so we fetch it separately.
- # If the page was fetched by Gollum, formatted_data would've been a String.
- @attributes[:formatted_content] ||= @page&.formatted_data || @wiki.page_formatted_data(@page)
+ @attributes[:formatted_content] ||= @wiki.page_formatted_data(@page)
end
# The markup format for the page.
@@ -154,16 +157,12 @@ class WikiPage
last_version&.sha
end
- # Returns the Date that this latest version was
- # created on.
- def created_at
- @page.version.date
- end
-
# Returns boolean True or False if this instance
# is an old version of the page.
def historical?
- @page.historical? && last_version.sha != version.sha
+ return false unless last_commit_sha && version
+
+ @page.historical? && last_commit_sha != version.sha
end
# Returns boolean True or False if this instance
@@ -196,7 +195,7 @@ class WikiPage
update_attributes(attrs)
save(page_details: title) do
- wiki.create_page(title, content, format, message)
+ wiki.create_page(title, content, format, attrs[:message])
end
end
diff --git a/app/policies/ci/build_policy.rb b/app/policies/ci/build_policy.rb
index 3858b29c82c..0ca3e696f46 100644
--- a/app/policies/ci/build_policy.rb
+++ b/app/policies/ci/build_policy.rb
@@ -20,12 +20,17 @@ module Ci
@subject.project.branch_allows_collaboration?(@user, @subject.ref)
end
+ condition(:archived, scope: :subject) do
+ @subject.archived?
+ end
+
condition(:terminal, scope: :subject) do
@subject.has_terminal?
end
- rule { protected_ref }.policy do
+ rule { protected_ref | archived }.policy do
prevent :update_build
+ prevent :update_commit_status
prevent :erase_build
end
diff --git a/app/policies/ci/pipeline_policy.rb b/app/policies/ci/pipeline_policy.rb
index f9623587957..e42d78f47c5 100644
--- a/app/policies/ci/pipeline_policy.rb
+++ b/app/policies/ci/pipeline_policy.rb
@@ -16,6 +16,10 @@ module Ci
enable :update_pipeline
end
+ rule { can?(:owner_access) }.policy do
+ enable :destroy_pipeline
+ end
+
def ref_protected?(user, project, tag, ref)
access = ::Gitlab::UserAccess.new(user, project: project)
diff --git a/app/policies/clusters/cluster_policy.rb b/app/policies/clusters/cluster_policy.rb
index 147943a3d6c..d6d590687e2 100644
--- a/app/policies/clusters/cluster_policy.rb
+++ b/app/policies/clusters/cluster_policy.rb
@@ -4,11 +4,7 @@ module Clusters
class ClusterPolicy < BasePolicy
alias_method :cluster, :subject
+ delegate { cluster.group }
delegate { cluster.project }
-
- rule { can?(:maintainer_access) }.policy do
- enable :update_cluster
- enable :admin_cluster
- end
end
end
diff --git a/app/policies/commit_policy.rb b/app/policies/commit_policy.rb
index 67e9bc12804..4d4f0ba9267 100644
--- a/app/policies/commit_policy.rb
+++ b/app/policies/commit_policy.rb
@@ -2,4 +2,6 @@
class CommitPolicy < BasePolicy
delegate { @subject.project }
+
+ rule { can?(:download_code) }.enable :read_commit
end
diff --git a/app/policies/deployment_policy.rb b/app/policies/deployment_policy.rb
index 56ac898b6ab..d4f2f3c52b1 100644
--- a/app/policies/deployment_policy.rb
+++ b/app/policies/deployment_policy.rb
@@ -2,4 +2,13 @@
class DeploymentPolicy < BasePolicy
delegate { @subject.project }
+
+ condition(:can_retry_deployable) do
+ can?(:update_build, @subject.deployable)
+ end
+
+ rule { ~can_retry_deployable }.policy do
+ prevent :create_deployment
+ prevent :update_deployment
+ end
end
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index 73c93b22c95..6b4e56ef5e4 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -65,6 +65,10 @@ class GroupPolicy < BasePolicy
enable :create_projects
enable :admin_pipeline
enable :admin_build
+ enable :read_cluster
+ enable :create_cluster
+ enable :update_cluster
+ enable :admin_cluster
end
rule { owner }.policy do
diff --git a/app/policies/milestone_policy.rb b/app/policies/milestone_policy.rb
new file mode 100644
index 00000000000..ac4f5b08504
--- /dev/null
+++ b/app/policies/milestone_policy.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class MilestonePolicy < BasePolicy
+ delegate { @subject.project }
+end
diff --git a/app/policies/note_policy.rb b/app/policies/note_policy.rb
index bbc2b48b856..f22843b6463 100644
--- a/app/policies/note_policy.rb
+++ b/app/policies/note_policy.rb
@@ -9,8 +9,17 @@ class NotePolicy < BasePolicy
condition(:editable, scope: :subject) { @subject.editable? }
+ condition(:can_read_noteable) { can?(:"read_#{@subject.to_ability_name}") }
+
rule { ~editable }.prevent :admin_note
+ # If user can't read the issue/MR/etc then they should not be allowed to do anything to their own notes
+ rule { ~can_read_noteable }.policy do
+ prevent :read_note
+ prevent :admin_note
+ prevent :resolve_note
+ end
+
rule { is_author }.policy do
enable :read_note
enable :admin_note
diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb
index d0e84b1aa38..1c082945299 100644
--- a/app/policies/project_policy.rb
+++ b/app/policies/project_policy.rb
@@ -110,6 +110,7 @@ class ProjectPolicy < BasePolicy
snippets
wiki
builds
+ pages
]
features.each do |f|
@@ -167,6 +168,7 @@ class ProjectPolicy < BasePolicy
enable :upload_file
enable :read_cycle_analytics
enable :award_emoji
+ enable :read_pages_content
end
# These abilities are not allowed to admins that are not members of the project,
@@ -256,6 +258,8 @@ class ProjectPolicy < BasePolicy
enable :update_pages
enable :read_cluster
enable :create_cluster
+ enable :update_cluster
+ enable :admin_cluster
enable :create_environment_terminal
end
@@ -286,6 +290,8 @@ class ProjectPolicy < BasePolicy
prevent(*create_read_update_admin_destroy(:merge_request))
end
+ rule { pages_disabled }.prevent :read_pages_content
+
rule { issues_disabled & merge_requests_disabled }.policy do
prevent(*create_read_update_admin_destroy(:label))
prevent(*create_read_update_admin_destroy(:milestone))
@@ -345,6 +351,7 @@ class ProjectPolicy < BasePolicy
enable :download_code
enable :download_wiki_code
enable :read_cycle_analytics
+ enable :read_pages_content
# NOTE: may be overridden by IssuePolicy
enable :read_issue
@@ -390,7 +397,11 @@ class ProjectPolicy < BasePolicy
greedy_load_subject ||= !@user.persisted?
if greedy_load_subject
- project.team.members.include?(user)
+ # We want to load all the members with one query. Calling #include? on
+ # project.team.members will perform a separate query for each user, unless
+ # project.team.members was loaded before somewhere else. Calling #to_a
+ # ensures it's always loaded before checking for membership.
+ project.team.members.to_a.include?(user)
else
# otherwise we just make a specific query for
# this particular user.
diff --git a/app/presenters/blob_presenter.rb b/app/presenters/blob_presenter.rb
new file mode 100644
index 00000000000..6323c1b3389
--- /dev/null
+++ b/app/presenters/blob_presenter.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class BlobPresenter < Gitlab::View::Presenter::Simple
+ presents :blob
+
+ def highlight(plain: nil)
+ blob.load_all_data! if blob.respond_to?(:load_all_data!)
+
+ Gitlab::Highlight.highlight(
+ blob.path,
+ blob.data,
+ language: blob.language_from_gitattributes,
+ plain: plain
+ )
+ end
+end
diff --git a/app/presenters/ci/build_presenter.rb b/app/presenters/ci/build_presenter.rb
index 5331cdf632b..33056a809b7 100644
--- a/app/presenters/ci/build_presenter.rb
+++ b/app/presenters/ci/build_presenter.rb
@@ -35,6 +35,10 @@ module Ci
"#{subject.name} - #{detailed_status.status_tooltip}"
end
+ def execute_in
+ scheduled? && scheduled_at && [0, scheduled_at - Time.now].max
+ end
+
private
def tooltip_for_badge
diff --git a/app/presenters/ci/build_runner_presenter.rb b/app/presenters/ci/build_runner_presenter.rb
index 880218e2727..300f85e1e9d 100644
--- a/app/presenters/ci/build_runner_presenter.rb
+++ b/app/presenters/ci/build_runner_presenter.rb
@@ -30,12 +30,12 @@ module Ci
def create_reports(reports, expire_in:)
return unless reports&.any?
- reports.map do |k, v|
+ reports.map do |report_type, report_paths|
{
- artifact_type: k.to_sym,
- artifact_format: :gzip,
- name: ::Ci::JobArtifact::DEFAULT_FILE_NAMES[k.to_sym],
- paths: v,
+ artifact_type: report_type.to_sym,
+ artifact_format: ::Ci::JobArtifact::TYPE_AND_FORMAT_PAIRS.fetch(report_type.to_sym),
+ name: ::Ci::JobArtifact::DEFAULT_FILE_NAMES.fetch(report_type.to_sym),
+ paths: report_paths,
when: 'always',
expire_in: expire_in
}
diff --git a/app/presenters/ci/pipeline_presenter.rb b/app/presenters/ci/pipeline_presenter.rb
index 93a38f92073..57daf04efc6 100644
--- a/app/presenters/ci/pipeline_presenter.rb
+++ b/app/presenters/ci/pipeline_presenter.rb
@@ -4,9 +4,11 @@ module Ci
class PipelinePresenter < Gitlab::View::Presenter::Delegated
include Gitlab::Utils::StrongMemoize
- FAILURE_REASONS = {
- config_error: 'CI/CD YAML configuration error!'
- }.freeze
+ # We use a class method here instead of a constant, allowing EE to redefine
+ # the returned `Hash` more easily.
+ def self.failure_reasons
+ { config_error: 'CI/CD YAML configuration error!' }
+ end
presents :pipeline
@@ -21,7 +23,7 @@ module Ci
def failure_reason
return unless pipeline.failure_reason?
- FAILURE_REASONS[pipeline.failure_reason.to_sym] ||
+ self.class.failure_reasons[pipeline.failure_reason.to_sym] ||
pipeline.failure_reason
end
diff --git a/app/presenters/clusterable_presenter.rb b/app/presenters/clusterable_presenter.rb
new file mode 100644
index 00000000000..9cc137aa3bd
--- /dev/null
+++ b/app/presenters/clusterable_presenter.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+class ClusterablePresenter < Gitlab::View::Presenter::Delegated
+ presents :clusterable
+
+ def self.fabricate(clusterable, **attributes)
+ presenter_class = "#{clusterable.class.name}ClusterablePresenter".constantize
+ attributes_with_presenter_class = attributes.merge(presenter_class: presenter_class)
+
+ Gitlab::View::Presenter::Factory
+ .new(clusterable, attributes_with_presenter_class)
+ .fabricate!
+ end
+
+ def can_create_cluster?
+ can?(current_user, :create_cluster, clusterable)
+ end
+
+ def index_path
+ polymorphic_path([clusterable, :clusters])
+ end
+
+ def new_path
+ new_polymorphic_path([clusterable, :cluster])
+ end
+
+ def create_user_clusters_path
+ polymorphic_path([clusterable, :clusters], action: :create_user)
+ end
+
+ def create_gcp_clusters_path
+ polymorphic_path([clusterable, :clusters], action: :create_gcp)
+ end
+
+ def cluster_status_cluster_path(cluster, params = {})
+ raise NotImplementedError
+ end
+
+ def install_applications_cluster_path(cluster, application)
+ raise NotImplementedError
+ end
+
+ def cluster_path(cluster, params = {})
+ raise NotImplementedError
+ end
+
+ def empty_state_help_text
+ nil
+ end
+
+ def sidebar_text
+ raise NotImplementedError
+ end
+
+ def learn_more_link
+ raise NotImplementedError
+ end
+end
diff --git a/app/presenters/clusters/cluster_presenter.rb b/app/presenters/clusters/cluster_presenter.rb
index dfdd8e82f97..7e6eccb648c 100644
--- a/app/presenters/clusters/cluster_presenter.rb
+++ b/app/presenters/clusters/cluster_presenter.rb
@@ -11,5 +11,15 @@ module Clusters
def can_toggle_cluster?
can?(current_user, :update_cluster, cluster) && created?
end
+
+ def show_path
+ if cluster.project_type?
+ project_cluster_path(project, cluster)
+ elsif cluster.group_type?
+ group_cluster_path(group, cluster)
+ else
+ raise NotImplementedError
+ end
+ end
end
end
diff --git a/app/presenters/commit_status_presenter.rb b/app/presenters/commit_status_presenter.rb
index 65e77ea3f92..0cd77da6303 100644
--- a/app/presenters/commit_status_presenter.rb
+++ b/app/presenters/commit_status_presenter.rb
@@ -8,7 +8,10 @@ class CommitStatusPresenter < Gitlab::View::Presenter::Delegated
stuck_or_timeout_failure: 'There has been a timeout failure or the job got stuck. Check your timeout limits or try again',
runner_system_failure: 'There has been a runner system failure, please try again',
missing_dependency_failure: 'There has been a missing dependency failure',
- runner_unsupported: 'Your runner is outdated, please upgrade your runner'
+ runner_unsupported: 'Your runner is outdated, please upgrade your runner',
+ stale_schedule: 'Delayed job could not be executed by some reason, please try again',
+ job_execution_timeout: 'The script exceeded the maximum execution time set for the job',
+ archived_failure: 'The job is archived and cannot be run'
}.freeze
private_constant :CALLOUT_FAILURE_MESSAGES
@@ -28,6 +31,6 @@ class CommitStatusPresenter < Gitlab::View::Presenter::Delegated
end
def unrecoverable?
- script_failure? || missing_dependency_failure?
+ script_failure? || missing_dependency_failure? || archived_failure?
end
end
diff --git a/app/presenters/group_clusterable_presenter.rb b/app/presenters/group_clusterable_presenter.rb
new file mode 100644
index 00000000000..d963c188559
--- /dev/null
+++ b/app/presenters/group_clusterable_presenter.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+class GroupClusterablePresenter < ClusterablePresenter
+ extend ::Gitlab::Utils::Override
+ include ActionView::Helpers::UrlHelper
+
+ override :cluster_status_cluster_path
+ def cluster_status_cluster_path(cluster, params = {})
+ cluster_status_group_cluster_path(clusterable, cluster, params)
+ end
+
+ override :install_applications_cluster_path
+ def install_applications_cluster_path(cluster, application)
+ install_applications_group_cluster_path(clusterable, cluster, application)
+ end
+
+ override :cluster_path
+ def cluster_path(cluster, params = {})
+ group_cluster_path(clusterable, cluster, params)
+ end
+
+ override :empty_state_help_text
+ def empty_state_help_text
+ s_('ClusterIntegration|Adding an integration to your group will share the cluster across all your projects.')
+ end
+
+ override :sidebar_text
+ def sidebar_text
+ s_('ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster.')
+ end
+
+ override :learn_more_link
+ def learn_more_link
+ link_to(s_('ClusterIntegration|Learn more about group Kubernetes clusters'), help_page_path('user/project/clusters/index'), target: '_blank', rel: 'noopener noreferrer')
+ end
+end
diff --git a/app/presenters/issue_presenter.rb b/app/presenters/issue_presenter.rb
new file mode 100644
index 00000000000..c12a202efbc
--- /dev/null
+++ b/app/presenters/issue_presenter.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class IssuePresenter < Gitlab::View::Presenter::Delegated
+ presents :issue
+
+ def web_url
+ Gitlab::UrlBuilder.build(issue)
+ end
+end
diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb
index 3f565b826dd..1db6c9eff36 100644
--- a/app/presenters/merge_request_presenter.rb
+++ b/app/presenters/merge_request_presenter.rb
@@ -108,16 +108,10 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
namespace = source_project_namespace
branch = source_branch
- if source_branch_exists?
- namespace = link_to(namespace, project_path(source_project))
- branch = link_to(branch, project_tree_path(source_project, source_branch))
- end
+ namespace_link = source_branch_exists? ? link_to(namespace, project_path(source_project)) : ERB::Util.html_escape(namespace)
+ branch_link = source_branch_exists? ? link_to(branch, project_tree_path(source_project, source_branch)) : ERB::Util.html_escape(branch)
- if for_fork?
- namespace + ":" + branch
- else
- branch
- end
+ for_fork? ? "#{namespace_link}:#{branch_link}" : branch_link
end
def closing_issues_links
diff --git a/app/presenters/project_clusterable_presenter.rb b/app/presenters/project_clusterable_presenter.rb
new file mode 100644
index 00000000000..63e69b91b11
--- /dev/null
+++ b/app/presenters/project_clusterable_presenter.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class ProjectClusterablePresenter < ClusterablePresenter
+ extend ::Gitlab::Utils::Override
+ include ActionView::Helpers::UrlHelper
+
+ override :cluster_status_cluster_path
+ def cluster_status_cluster_path(cluster, params = {})
+ cluster_status_project_cluster_path(clusterable, cluster, params)
+ end
+
+ override :install_applications_cluster_path
+ def install_applications_cluster_path(cluster, application)
+ install_applications_project_cluster_path(clusterable, cluster, application)
+ end
+
+ override :cluster_path
+ def cluster_path(cluster, params = {})
+ project_cluster_path(clusterable, cluster, params)
+ end
+
+ override :sidebar_text
+ def sidebar_text
+ s_('ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way.')
+ end
+
+ override :learn_more_link
+ def learn_more_link
+ link_to(s_('ClusterIntegration|Learn more about Kubernetes'), help_page_path('user/project/clusters/index'), target: '_blank', rel: 'noopener noreferrer')
+ end
+end
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index d2434d96fd7..d61124fa787 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -36,8 +36,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
contribution_guide_anchor_data,
autodevops_anchor_data(show_auto_devops_callout: show_auto_devops_callout),
kubernetes_cluster_anchor_data,
- gitlab_ci_anchor_data,
- koding_anchor_data
+ gitlab_ci_anchor_data
].compact.reject { |item| item.enabled }
end
@@ -125,43 +124,6 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
add_special_file_path(file_name: 'README.md')
end
- def add_koding_stack_path
- project_new_blob_path(
- project,
- default_branch || 'master',
- file_name: '.koding.yml',
- commit_message: "Add Koding stack script",
- content: <<-CONTENT.strip_heredoc
- provider:
- aws:
- access_key: '${var.aws_access_key}'
- secret_key: '${var.aws_secret_key}'
- resource:
- aws_instance:
- #{project.path}-vm:
- instance_type: t2.nano
- user_data: |-
-
- # Created by GitLab UI for :>
-
- echo _KD_NOTIFY_@Installing Base packages...@
-
- apt-get update -y
- apt-get install git -y
-
- echo _KD_NOTIFY_@Cloning #{project.name}...@
-
- export KODING_USER=${var.koding_user_username}
- export REPO_URL=#{root_url}${var.koding_queryString_repo}.git
- export BRANCH=${var.koding_queryString_branch}
-
- sudo -i -u $KODING_USER git clone $REPO_URL -b $BRANCH
-
- echo _KD_NOTIFY_@#{project.name} cloned.@
- CONTENT
- )
- end
-
def license_short_name
license = repository.license
license&.nickname || license&.name || 'LICENSE'
@@ -214,7 +176,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
AnchorData.new(false,
_('New file'),
project_new_blob_path(project, default_branch || 'master'),
- 'new')
+ 'success')
end
end
@@ -310,14 +272,6 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
end
end
- def koding_anchor_data
- if current_user && can_current_user_push_code? && koding_enabled? && repository.koding_yml.blank?
- AnchorData.new(false,
- _('Set up Koding'),
- add_koding_stack_path)
- end
- end
-
def tags_to_show
project.tag_list.take(MAX_TAGS_TO_SHOW) # rubocop: disable CodeReuse/ActiveRecord
end
@@ -363,8 +317,4 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
branch_name: branch_name
)
end
-
- def koding_enabled?
- Gitlab::CurrentSettings.koding_enabled?
- end
end
diff --git a/app/presenters/user_presenter.rb b/app/presenters/user_presenter.rb
new file mode 100644
index 00000000000..14ef53e9ec8
--- /dev/null
+++ b/app/presenters/user_presenter.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class UserPresenter < Gitlab::View::Presenter::Delegated
+ presents :user
+
+ def web_url
+ Gitlab::Routing.url_helpers.user_url(user)
+ end
+end
diff --git a/app/serializers/build_action_entity.rb b/app/serializers/build_action_entity.rb
index f9da3f63911..95833c3528f 100644
--- a/app/serializers/build_action_entity.rb
+++ b/app/serializers/build_action_entity.rb
@@ -12,6 +12,12 @@ class BuildActionEntity < Grape::Entity
end
expose :playable?, as: :playable
+ expose :scheduled?, as: :scheduled
+ expose :scheduled_at, if: -> (*) { scheduled? }
+
+ expose :unschedule_path, if: -> (build) { build.scheduled? } do |build|
+ unschedule_project_job_path(build.project, build)
+ end
private
@@ -20,4 +26,8 @@ class BuildActionEntity < Grape::Entity
def playable?
build.playable? && can?(request.current_user, :update_build, build)
end
+
+ def scheduled?
+ build.scheduled?
+ end
end
diff --git a/app/serializers/build_details_entity.rb b/app/serializers/build_details_entity.rb
index 00a441a9a1e..9ddce0d2c80 100644
--- a/app/serializers/build_details_entity.rb
+++ b/app/serializers/build_details_entity.rb
@@ -1,23 +1,18 @@
# frozen_string_literal: true
class BuildDetailsEntity < JobEntity
- include EnvironmentHelper
- include RequestAwareEntity
- include CiStatusHelper
-
expose :coverage, :erased_at, :duration
expose :tag_list, as: :tags
+ expose :has_trace?, as: :has_trace
+ expose :stage
+ expose :stuck?, as: :stuck
expose :user, using: UserEntity
expose :runner, using: RunnerEntity
expose :pipeline, using: PipelineEntity
- expose :deployment_status, if: -> (*) { build.has_environment? } do
+ expose :deployment_status, if: -> (*) { build.starts_environment? } do
expose :deployment_status, as: :status
- expose :icon do |build|
- ci_label_for_status(build.status)
- end
-
expose :persisted_environment, as: :environment, with: EnvironmentEntity
end
diff --git a/app/serializers/commit_entity.rb b/app/serializers/commit_entity.rb
index ce76659fa46..a94e32478ce 100644
--- a/app/serializers/commit_entity.rb
+++ b/app/serializers/commit_entity.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
class CommitEntity < API::Entities::Commit
+ include MarkupHelper
include RequestAwareEntity
expose :author, using: UserEntity
@@ -9,11 +10,40 @@ class CommitEntity < API::Entities::Commit
GravatarService.new.execute(commit.author_email) # rubocop: disable CodeReuse/ServiceClass
end
- expose :commit_url do |commit|
- project_commit_url(request.project, commit)
+ expose :commit_url do |commit, options|
+ project_commit_url(request.project, commit, params: options.fetch(:commit_url_params, {}))
end
- expose :commit_path do |commit|
- project_commit_path(request.project, commit)
+ expose :commit_path do |commit, options|
+ project_commit_path(request.project, commit, params: options.fetch(:commit_url_params, {}))
+ end
+
+ expose :description_html, if: { type: :full } do |commit|
+ markdown_field(commit, :description)
+ end
+
+ expose :title_html, if: { type: :full } do |commit|
+ markdown_field(commit, :title)
+ end
+
+ expose :signature_html, if: { type: :full } do |commit|
+ render('projects/commit/_signature', signature: commit.signature) if commit.has_signature?
+ end
+
+ expose :pipeline_status_path, if: { type: :full } do |commit, options|
+ pipeline_ref = options[:pipeline_ref]
+ pipeline_project = options[:pipeline_project] || commit.project
+ next unless pipeline_ref && pipeline_project
+
+ status = commit.status_for_project(pipeline_ref, pipeline_project)
+ next unless status
+
+ pipelines_project_commit_path(pipeline_project, commit.id, ref: pipeline_ref)
+ end
+
+ def render(*args)
+ return unless request.respond_to?(:render) && request.render.respond_to?(:call)
+
+ request.render.call(*args)
end
end
diff --git a/app/serializers/current_user_entity.rb b/app/serializers/current_user_entity.rb
new file mode 100644
index 00000000000..71d14e727dd
--- /dev/null
+++ b/app/serializers/current_user_entity.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+# Always use this entity when rendering data for current user
+# for attributes that does not need to be visible to other users
+# like user preferences.
+class CurrentUserEntity < UserEntity
+ expose :user_preference, using: UserPreferenceEntity
+end
diff --git a/app/serializers/deployment_entity.rb b/app/serializers/deployment_entity.rb
index 344148a1fb7..aa1d9e6292c 100644
--- a/app/serializers/deployment_entity.rb
+++ b/app/serializers/deployment_entity.rb
@@ -25,4 +25,5 @@ class DeploymentEntity < Grape::Entity
expose :commit, using: CommitEntity
expose :deployable, using: JobEntity
expose :manual_actions, using: JobEntity
+ expose :scheduled_actions, using: JobEntity
end
diff --git a/app/serializers/detailed_status_entity.rb b/app/serializers/detailed_status_entity.rb
index c772c807f76..da994d78286 100644
--- a/app/serializers/detailed_status_entity.rb
+++ b/app/serializers/detailed_status_entity.rb
@@ -10,7 +10,12 @@ class DetailedStatusEntity < Grape::Entity
expose :illustration do |status|
begin
- status.illustration
+ illustration = {
+ image: ActionController::Base.helpers.image_path(status.illustration[:image])
+ }
+ illustration = status.illustration.merge(illustration)
+
+ illustration
rescue NotImplementedError
# ignored
end
@@ -25,5 +30,6 @@ class DetailedStatusEntity < Grape::Entity
expose :action_title, as: :title
expose :action_path, as: :path
expose :action_method, as: :method
+ expose :action_button_title, as: :button_title
end
end
diff --git a/app/serializers/diff_file_entity.rb b/app/serializers/diff_file_entity.rb
index cbe6f200b86..63ea8e8f95f 100644
--- a/app/serializers/diff_file_entity.rb
+++ b/app/serializers/diff_file_entity.rb
@@ -84,7 +84,7 @@ class DiffFileEntity < Grape::Entity
end
expose :old_path_html do |diff_file|
- old_path = mark_inline_diffs(diff_file.old_path, diff_file.new_path)
+ old_path, _ = mark_inline_diffs(diff_file.old_path, diff_file.new_path)
old_path
end
@@ -116,6 +116,10 @@ class DiffFileEntity < Grape::Entity
project_blob_path(project, tree_join(diff_file.content_sha, diff_file.new_path))
end
+ expose :viewer, using: DiffViewerEntity do |diff_file|
+ diff_file.rich_viewer || diff_file.simple_viewer
+ end
+
expose :replaced_view_path, if: -> (_, options) { options[:merge_request] } do |diff_file|
image_diff = diff_file.rich_viewer && diff_file.rich_viewer.partial_name == 'image'
image_replaced = diff_file.old_content_sha && diff_file.old_content_sha != diff_file.content_sha
diff --git a/app/serializers/diff_line_entity.rb b/app/serializers/diff_line_entity.rb
index 2119a1017d3..942714b7787 100644
--- a/app/serializers/diff_line_entity.rb
+++ b/app/serializers/diff_line_entity.rb
@@ -9,6 +9,6 @@ class DiffLineEntity < Grape::Entity
expose :meta_positions, as: :meta_data
expose :rich_text do |line|
- line.rich_text || CGI.escapeHTML(line.text)
+ ERB::Util.html_escape(line.rich_text || line.text)
end
end
diff --git a/app/serializers/diff_viewer_entity.rb b/app/serializers/diff_viewer_entity.rb
new file mode 100644
index 00000000000..27fba03cb3f
--- /dev/null
+++ b/app/serializers/diff_viewer_entity.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class DiffViewerEntity < Grape::Entity
+ # Partial name refers directly to a Rails feature, let's avoid
+ # using this on the frontend.
+ expose :partial_name, as: :name
+end
diff --git a/app/serializers/diffs_entity.rb b/app/serializers/diffs_entity.rb
index 878cc5290bd..b51e4a7e6d0 100644
--- a/app/serializers/diffs_entity.rb
+++ b/app/serializers/diffs_entity.rb
@@ -15,8 +15,13 @@ class DiffsEntity < Grape::Entity
merge_request&.target_branch
end
- expose :commit do |diffs|
- options[:commit]
+ expose :commit do |diffs, options|
+ CommitEntity.represent options[:commit], options.merge(
+ type: :full,
+ commit_url_params: { merge_request_iid: merge_request&.iid },
+ pipeline_ref: merge_request&.source_branch,
+ pipeline_project: merge_request&.source_project
+ )
end
expose :merge_request_diff, using: MergeRequestDiffEntity do |diffs|
diff --git a/app/serializers/discussion_entity.rb b/app/serializers/discussion_entity.rb
index ebe76c9fcda..b6786a0d597 100644
--- a/app/serializers/discussion_entity.rb
+++ b/app/serializers/discussion_entity.rb
@@ -27,7 +27,7 @@ class DiscussionEntity < Grape::Entity
expose :resolved?, as: :resolved
expose :resolved_by_push?, as: :resolved_by_push
- expose :resolved_by
+ expose :resolved_by, using: NoteUserEntity
expose :resolved_at
expose :resolve_path, if: -> (d, _) { d.resolvable? } do |discussion|
resolve_project_merge_request_discussion_path(discussion.project, discussion.noteable, discussion.id)
diff --git a/app/serializers/environment_status_entity.rb b/app/serializers/environment_status_entity.rb
new file mode 100644
index 00000000000..f6321b9e520
--- /dev/null
+++ b/app/serializers/environment_status_entity.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+class EnvironmentStatusEntity < Grape::Entity
+ include RequestAwareEntity
+
+ expose :id
+ expose :name
+ expose :status
+
+ expose :url do |es|
+ project_environment_path(es.project, es.environment)
+ end
+
+ expose :metrics_url, if: ->(*) { can_read_environment? && deployment.has_metrics? } do |es|
+ metrics_project_environment_deployment_path(es.project, es.environment, es.deployment)
+ end
+
+ expose :metrics_monitoring_url, if: ->(*) { can_read_environment? } do |es|
+ environment_metrics_path(es.environment)
+ end
+
+ expose :stop_url, if: ->(*) { can_stop_environment? } do |es|
+ stop_project_environment_path(es.project, es.environment)
+ end
+
+ expose :external_url do |es|
+ es.environment.external_url
+ end
+
+ expose :external_url_formatted do |es|
+ es.environment.formatted_external_url
+ end
+
+ expose :deployed_at
+
+ expose :deployed_at_formatted do |es|
+ es.deployment.try(:formatted_deployment_time)
+ end
+
+ expose :changes
+
+ private
+
+ def environment
+ object.environment
+ end
+
+ def deployment
+ object.deployment
+ end
+
+ def project
+ object.environment.project
+ end
+
+ def current_user
+ request.current_user
+ end
+
+ def can_read_environment?
+ can?(current_user, :read_environment, environment)
+ end
+
+ def can_stop_environment?
+ can?(current_user, :stop_environment, environment)
+ end
+end
diff --git a/app/serializers/environment_status_serializer.rb b/app/serializers/environment_status_serializer.rb
new file mode 100644
index 00000000000..f8d37934763
--- /dev/null
+++ b/app/serializers/environment_status_serializer.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class EnvironmentStatusSerializer < BaseSerializer
+ entity EnvironmentStatusEntity
+end
diff --git a/app/serializers/issue_entity.rb b/app/serializers/issue_entity.rb
index 16a477c92fa..c3f7d4651fb 100644
--- a/app/serializers/issue_entity.rb
+++ b/app/serializers/issue_entity.rb
@@ -42,6 +42,6 @@ class IssueEntity < IssuableEntity
end
expose :preview_note_path do |issue|
- preview_markdown_path(issue.project, quick_actions_target_type: 'Issue', quick_actions_target_id: issue.id)
+ preview_markdown_path(issue.project, quick_actions_target_type: 'Issue', quick_actions_target_id: issue.iid)
end
end
diff --git a/app/serializers/job_entity.rb b/app/serializers/job_entity.rb
index 26b29993fec..d0099ae77f2 100644
--- a/app/serializers/job_entity.rb
+++ b/app/serializers/job_entity.rb
@@ -7,9 +7,10 @@ class JobEntity < Grape::Entity
expose :name
expose :started?, as: :started
+ expose :archived?, as: :archived
expose :build_path do |build|
- build.target_url || path_to(:namespace_project_job, build)
+ build_path(build)
end
expose :retry_path, if: -> (*) { retryable? } do |build|
@@ -17,14 +18,24 @@ class JobEntity < Grape::Entity
end
expose :cancel_path, if: -> (*) { cancelable? } do |build|
- path_to(:cancel_namespace_project_job, build)
+ path_to(
+ :cancel_namespace_project_job,
+ build,
+ { continue: { to: build_path(build) } }
+ )
end
expose :play_path, if: -> (*) { playable? } do |build|
path_to(:play_namespace_project_job, build)
end
+ expose :unschedule_path, if: -> (*) { scheduled? } do |build|
+ path_to(:unschedule_namespace_project_job, build)
+ end
+
expose :playable?, as: :playable
+ expose :scheduled?, as: :scheduled
+ expose :scheduled_at, if: -> (*) { scheduled? }
expose :created_at
expose :updated_at
expose :detailed_status, as: :status, with: DetailedStatusEntity
@@ -47,12 +58,20 @@ class JobEntity < Grape::Entity
build.playable? && can?(request.current_user, :update_build, build)
end
+ def scheduled?
+ build.scheduled?
+ end
+
def detailed_status
build.detailed_status(request.current_user)
end
- def path_to(route, build)
- send("#{route}_path", build.project.namespace, build.project, build) # rubocop:disable GitlabSecurity/PublicSend
+ def path_to(route, build, params = {})
+ send("#{route}_path", build.project.namespace, build.project, build, params) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ def build_path(build)
+ build.target_url || path_to(:namespace_project_job, build)
end
def failed?
diff --git a/app/serializers/merge_request_user_entity.rb b/app/serializers/merge_request_user_entity.rb
index fd2d2897113..53257b0602c 100644
--- a/app/serializers/merge_request_user_entity.rb
+++ b/app/serializers/merge_request_user_entity.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class MergeRequestUserEntity < UserEntity
+class MergeRequestUserEntity < CurrentUserEntity
include RequestAwareEntity
include BlobHelper
include TreeHelper
diff --git a/app/serializers/merge_request_widget_entity.rb b/app/serializers/merge_request_widget_entity.rb
index 380e8804f51..f33a1654d5e 100644
--- a/app/serializers/merge_request_widget_entity.rb
+++ b/app/serializers/merge_request_widget_entity.rb
@@ -55,6 +55,7 @@ class MergeRequestWidgetEntity < IssuableEntity
expose :merge_commit_message
expose :actual_head_pipeline, with: PipelineDetailsEntity, as: :pipeline
+ expose :merge_pipeline, with: PipelineDetailsEntity, if: ->(mr, _) { mr.merged? && can?(request.current_user, :read_pipeline, mr.target_project)}
# Booleans
expose :merge_ongoing?, as: :merge_ongoing
@@ -222,7 +223,7 @@ class MergeRequestWidgetEntity < IssuableEntity
end
expose :preview_note_path do |merge_request|
- preview_markdown_path(merge_request.project, quick_actions_target_type: 'MergeRequest', quick_actions_target_id: merge_request.id)
+ preview_markdown_path(merge_request.project, quick_actions_target_type: 'MergeRequest', quick_actions_target_id: merge_request.iid)
end
expose :merge_commit_path do |merge_request|
diff --git a/app/serializers/pipeline_details_entity.rb b/app/serializers/pipeline_details_entity.rb
index 3b56767f774..d78ad4af4dc 100644
--- a/app/serializers/pipeline_details_entity.rb
+++ b/app/serializers/pipeline_details_entity.rb
@@ -5,5 +5,6 @@ class PipelineDetailsEntity < PipelineEntity
expose :ordered_stages, as: :stages, using: StageEntity
expose :artifacts, using: BuildArtifactEntity
expose :manual_actions, using: BuildActionEntity
+ expose :scheduled_actions, using: BuildActionEntity
end
end
diff --git a/app/serializers/pipeline_serializer.rb b/app/serializers/pipeline_serializer.rb
index 4f31af3c46d..7451433a841 100644
--- a/app/serializers/pipeline_serializer.rb
+++ b/app/serializers/pipeline_serializer.rb
@@ -13,6 +13,7 @@ class PipelineSerializer < BaseSerializer
:cancelable_statuses,
:trigger_requests,
:manual_actions,
+ :scheduled_actions,
:artifacts,
{
pending_builds: :project,
diff --git a/app/serializers/project_mirror_entity.rb b/app/serializers/project_mirror_entity.rb
index 8aba244cd11..c13cc3276a7 100644
--- a/app/serializers/project_mirror_entity.rb
+++ b/app/serializers/project_mirror_entity.rb
@@ -3,11 +3,7 @@
class ProjectMirrorEntity < Grape::Entity
expose :id
- expose :remote_mirrors_attributes do |project|
- next [] unless project.remote_mirrors.present?
-
- project.remote_mirrors.map do |remote|
- remote.as_json(only: %i[id url enabled])
- end
+ expose :remote_mirrors_attributes, using: RemoteMirrorEntity do |project|
+ project.remote_mirrors
end
end
diff --git a/app/serializers/remote_mirror_entity.rb b/app/serializers/remote_mirror_entity.rb
new file mode 100644
index 00000000000..8835c6d4647
--- /dev/null
+++ b/app/serializers/remote_mirror_entity.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class RemoteMirrorEntity < Grape::Entity
+ expose :id
+ expose :url
+ expose :enabled
+
+ expose :auth_method
+ expose :ssh_known_hosts
+ expose :ssh_public_key
+
+ expose :ssh_known_hosts_fingerprints do |remote_mirror|
+ remote_mirror.ssh_known_hosts_fingerprints.as_json
+ end
+end
diff --git a/app/serializers/user_preference_entity.rb b/app/serializers/user_preference_entity.rb
new file mode 100644
index 00000000000..b99f80424db
--- /dev/null
+++ b/app/serializers/user_preference_entity.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class UserPreferenceEntity < Grape::Entity
+ expose :issue_notes_filter
+ expose :merge_request_notes_filter
+
+ expose :notes_filters do |user_preference|
+ UserPreference.notes_filters
+ end
+
+ expose :default_notes_filter do |user_preference|
+ UserPreference::NOTES_FILTERS[:all_notes]
+ end
+end
diff --git a/app/services/access_token_validation_service.rb b/app/services/access_token_validation_service.rb
index 2a337918d21..40aa9250885 100644
--- a/app/services/access_token_validation_service.rb
+++ b/app/services/access_token_validation_service.rb
@@ -6,6 +6,7 @@ class AccessTokenValidationService
EXPIRED = :expired
REVOKED = :revoked
INSUFFICIENT_SCOPE = :insufficient_scope
+ IMPERSONATION_DISABLED = :impersonation_disabled
attr_reader :token, :request
@@ -24,6 +25,11 @@ class AccessTokenValidationService
elsif !self.include_any_scope?(scopes)
return INSUFFICIENT_SCOPE
+ elsif token.respond_to?(:impersonation) &&
+ token.impersonation &&
+ !Gitlab.config.gitlab.impersonation_enabled
+ return IMPERSONATION_DISABLED
+
else
return VALID
end
diff --git a/app/services/applications/create_service.rb b/app/services/applications/create_service.rb
index 3d88c4f064e..b6c30da4d3a 100644
--- a/app/services/applications/create_service.rb
+++ b/app/services/applications/create_service.rb
@@ -9,6 +9,7 @@ module Applications
end
# rubocop: enable CodeReuse/ActiveRecord
+ # EE would override and use `request` arg
def execute(request)
Doorkeeper::Application.create(@params)
end
diff --git a/app/services/audit_event_service.rb b/app/services/audit_event_service.rb
index 4c5e22bdd7e..201048aaba5 100644
--- a/app/services/audit_event_service.rb
+++ b/app/services/audit_event_service.rb
@@ -17,11 +17,29 @@ class AuditEventService
end
def security_event
- SecurityEvent.create(
+ log_security_event_to_file
+ log_security_event_to_database
+ end
+
+ private
+
+ def base_payload
+ {
author_id: @author.id,
entity_id: @entity.id,
- entity_type: @entity.class.name,
- details: @details
- )
+ entity_type: @entity.class.name
+ }
+ end
+
+ def file_logger
+ @file_logger ||= Gitlab::AuditJsonLogger.build
+ end
+
+ def log_security_event_to_file
+ file_logger.info(base_payload.merge(@details))
+ end
+
+ def log_security_event_to_database
+ SecurityEvent.create(base_payload.merge(details: @details))
end
end
diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb
index 893b37b831a..f764536e762 100644
--- a/app/services/auth/container_registry_authentication_service.rb
+++ b/app/services/auth/container_registry_authentication_service.rb
@@ -99,7 +99,7 @@ module Auth
##
# Because we do not have two way communication with registry yet,
# we create a container repository image resource when push to the
- # registry is successfuly authorized.
+ # registry is successfully authorized.
#
def ensure_container_repository!(path, actions)
return if path.has_repository?
diff --git a/app/services/boards/issues/move_service.rb b/app/services/boards/issues/move_service.rb
index 7dd87034410..43a26f4264e 100644
--- a/app/services/boards/issues/move_service.rb
+++ b/app/services/boards/issues/move_service.rb
@@ -70,10 +70,8 @@ module Boards
label_ids =
if moving_to_list.movable?
moving_from_list.label_id
- elsif board.group_board?
- ::Label.on_group_boards(parent.id).pluck(:label_id)
else
- ::Label.on_project_boards(parent.id).pluck(:label_id)
+ ::Label.on_board(board.id).pluck(:label_id)
end
Array(label_ids).compact
diff --git a/app/services/boards/lists/list_service.rb b/app/services/boards/lists/list_service.rb
index e10eb52e041..5cf5f14a55b 100644
--- a/app/services/boards/lists/list_service.rb
+++ b/app/services/boards/lists/list_service.rb
@@ -6,7 +6,7 @@ module Boards
def execute(board)
board.lists.create(list_type: :backlog) unless board.lists.backlog.exists?
- board.lists
+ board.lists.preload_associations
end
end
end
diff --git a/app/services/boards/visits/create_service.rb b/app/services/boards/visits/create_service.rb
new file mode 100644
index 00000000000..e2adf755511
--- /dev/null
+++ b/app/services/boards/visits/create_service.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Boards
+ module Visits
+ class CreateService < Boards::BaseService
+ def execute(board)
+ return unless current_user && Gitlab::Database.read_write?
+
+ if parent.is_a?(Group)
+ BoardGroupRecentVisit.visited!(current_user, board)
+ else
+ BoardProjectRecentVisit.visited!(current_user, board)
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/boards/visits/latest_service.rb b/app/services/boards/visits/latest_service.rb
new file mode 100644
index 00000000000..9e4c77a6317
--- /dev/null
+++ b/app/services/boards/visits/latest_service.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Boards
+ module Visits
+ class LatestService < Boards::BaseService
+ def execute
+ return nil unless current_user
+
+ if parent.is_a?(Group)
+ BoardGroupRecentVisit.latest(current_user, parent)
+ else
+ BoardProjectRecentVisit.latest(current_user, parent)
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/ci/archive_trace_service.rb b/app/services/ci/archive_trace_service.rb
new file mode 100644
index 00000000000..a1dd00721b5
--- /dev/null
+++ b/app/services/ci/archive_trace_service.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module Ci
+ class ArchiveTraceService
+ def execute(job)
+ job.trace.archive!
+ rescue ::Gitlab::Ci::Trace::AlreadyArchivedError
+ # It's already archived, thus we can safely ignore this exception.
+ rescue => e
+ # Tracks this error with application logs, Sentry, and Prometheus.
+ # If `archive!` keeps failing for over a week, that could incur data loss.
+ # (See more https://docs.gitlab.com/ee/administration/job_traces.html#new-live-trace-architecture)
+ # In order to avoid interrupting the system, we do not raise an exception here.
+ archive_error(e, job)
+ end
+
+ private
+
+ def failed_archive_counter
+ @failed_archive_counter ||=
+ Gitlab::Metrics.counter(:job_trace_archive_failed_total,
+ "Counter of failed attempts of trace archiving")
+ end
+
+ def archive_error(error, job)
+ failed_archive_counter.increment
+ Rails.logger.error "Failed to archive trace. id: #{job.id} message: #{error.message}"
+
+ Gitlab::Sentry
+ .track_exception(error,
+ issue_url: 'https://gitlab.com/gitlab-org/gitlab-ce/issues/51502',
+ extra: { job_id: job.id })
+ end
+ end
+end
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index 92a8438ab2f..46a82377c10 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -4,6 +4,8 @@ module Ci
class CreatePipelineService < BaseService
attr_reader :pipeline
+ CreateError = Class.new(StandardError)
+
SEQUENCE = [Gitlab::Ci::Pipeline::Chain::Build,
Gitlab::Ci::Pipeline::Chain::Validate::Abilities,
Gitlab::Ci::Pipeline::Chain::Validate::Repository,
@@ -47,6 +49,14 @@ module Ci
pipeline
end
+ def execute!(*args, &block)
+ execute(*args, &block).tap do |pipeline|
+ unless pipeline.persisted?
+ raise CreateError, pipeline.errors.full_messages.join(',')
+ end
+ end
+ end
+
private
def commit
diff --git a/app/services/ci/destroy_pipeline_service.rb b/app/services/ci/destroy_pipeline_service.rb
new file mode 100644
index 00000000000..13f892aabb8
--- /dev/null
+++ b/app/services/ci/destroy_pipeline_service.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Ci
+ class DestroyPipelineService < BaseService
+ def execute(pipeline)
+ raise Gitlab::Access::AccessDeniedError unless can?(current_user, :destroy_pipeline, pipeline)
+
+ AuditEventService.new(current_user, pipeline).security_event
+
+ pipeline.destroy!
+ end
+ end
+end
diff --git a/app/services/ci/enqueue_build_service.rb b/app/services/ci/enqueue_build_service.rb
deleted file mode 100644
index 8140651d980..00000000000
--- a/app/services/ci/enqueue_build_service.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-# frozen_string_literal: true
-module Ci
- class EnqueueBuildService < BaseService
- def execute(build)
- build.enqueue
- end
- end
-end
diff --git a/app/services/ci/process_build_service.rb b/app/services/ci/process_build_service.rb
new file mode 100644
index 00000000000..d9f8e7cb452
--- /dev/null
+++ b/app/services/ci/process_build_service.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module Ci
+ class ProcessBuildService < BaseService
+ def execute(build, current_status)
+ if valid_statuses_for_when(build.when).include?(current_status)
+ if build.schedulable?
+ build.schedule
+ elsif build.action?
+ build.actionize
+ else
+ enqueue(build)
+ end
+
+ true
+ else
+ build.skip
+ false
+ end
+ end
+
+ private
+
+ def enqueue(build)
+ build.enqueue
+ end
+
+ def valid_statuses_for_when(value)
+ case value
+ when 'on_success'
+ %w[success skipped]
+ when 'on_failure'
+ %w[failed]
+ when 'always'
+ %w[success failed skipped]
+ when 'manual'
+ %w[success skipped]
+ when 'delayed'
+ %w[success skipped]
+ else
+ []
+ end
+ end
+ end
+end
diff --git a/app/services/ci/process_pipeline_service.rb b/app/services/ci/process_pipeline_service.rb
index 69341a6c263..446188347df 100644
--- a/app/services/ci/process_pipeline_service.rb
+++ b/app/services/ci/process_pipeline_service.rb
@@ -24,42 +24,18 @@ module Ci
def process_stage(index)
current_status = status_for_prior_stages(index)
- return if HasStatus::BLOCKED_STATUS == current_status
+ return if HasStatus::BLOCKED_STATUS.include?(current_status)
if HasStatus::COMPLETED_STATUSES.include?(current_status)
created_builds_in_stage(index).select do |build|
Gitlab::OptimisticLocking.retry_lock(build) do |subject|
- process_build(subject, current_status)
+ Ci::ProcessBuildService.new(project, @user)
+ .execute(build, current_status)
end
end
end
end
- def process_build(build, current_status)
- if valid_statuses_for_when(build.when).include?(current_status)
- build.action? ? build.actionize : enqueue_build(build)
- true
- else
- build.skip
- false
- end
- end
-
- def valid_statuses_for_when(value)
- case value
- when 'on_success'
- %w[success skipped]
- when 'on_failure'
- %w[failed]
- when 'always'
- %w[success failed skipped]
- when 'manual'
- %w[success skipped]
- else
- []
- end
- end
-
# rubocop: disable CodeReuse/ActiveRecord
def status_for_prior_stages(index)
pipeline.builds.where('stage_idx < ?', index).latest.status || 'success'
@@ -101,9 +77,5 @@ module Ci
.update_all(retried: true) if latest_statuses.any?
end
# rubocop: enable CodeReuse/ActiveRecord
-
- def enqueue_build(build)
- Ci::EnqueueBuildService.new(project, @user).execute(build)
- end
end
end
diff --git a/app/services/ci/register_job_service.rb b/app/services/ci/register_job_service.rb
index 5a7be921389..13321b2682e 100644
--- a/app/services/ci/register_job_service.rb
+++ b/app/services/ci/register_job_service.rb
@@ -36,7 +36,7 @@ module Ci
builds = builds.with_any_tags
end
- builds.find do |build|
+ builds.each do |build|
next unless runner.can_pick?(build)
begin
@@ -45,7 +45,7 @@ module Ci
if assign_runner!(build, params)
register_success(build)
- return Result.new(build, true) # rubocop:disable Cop/AvoidReturnFromBlocks
+ return Result.new(build, true)
end
rescue StateMachines::InvalidTransition, ActiveRecord::StaleObjectError
# We are looping to find another build that is not conflicting
@@ -82,6 +82,11 @@ module Ci
return false
end
+ if build.archived?
+ build.drop!(:archived_failure)
+ return false
+ end
+
build.run!
true
end
diff --git a/app/services/ci/run_scheduled_build_service.rb b/app/services/ci/run_scheduled_build_service.rb
new file mode 100644
index 00000000000..8e4a628296f
--- /dev/null
+++ b/app/services/ci/run_scheduled_build_service.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Ci
+ class RunScheduledBuildService < ::BaseService
+ def execute(build)
+ unless can?(current_user, :update_build, build)
+ raise Gitlab::Access::AccessDeniedError
+ end
+
+ build.enqueue_scheduled!
+ end
+ end
+end
diff --git a/app/services/clusters/applications/base_helm_service.rb b/app/services/clusters/applications/base_helm_service.rb
index 270a8eb24f4..e86ca8cf1d0 100644
--- a/app/services/clusters/applications/base_helm_service.rb
+++ b/app/services/clusters/applications/base_helm_service.rb
@@ -11,6 +11,25 @@ module Clusters
protected
+ def log_error(error)
+ meta = {
+ exception: error.class.name,
+ error_code: error.respond_to?(:error_code) ? error.error_code : nil,
+ service: self.class.name,
+ app_id: app.id,
+ project_ids: app.cluster.project_ids,
+ group_ids: app.cluster.group_ids,
+ message: error.message
+ }
+
+ logger.error(meta)
+ Gitlab::Sentry.track_acceptable_exception(error, extra: meta)
+ end
+
+ def logger
+ @logger ||= Gitlab::Kubernetes::Logger.build
+ end
+
def cluster
app.cluster
end
diff --git a/app/services/clusters/applications/check_ingress_ip_address_service.rb b/app/services/clusters/applications/check_ingress_ip_address_service.rb
index f32e73e8b1c..0ec06e776a7 100644
--- a/app/services/clusters/applications/check_ingress_ip_address_service.rb
+++ b/app/services/clusters/applications/check_ingress_ip_address_service.rb
@@ -30,7 +30,7 @@ module Clusters
def service
strong_memoize(:ingress_service) do
- kubeclient.get_service('ingress-nginx-ingress-controller', Gitlab::Kubernetes::Helm::NAMESPACE)
+ app.ingress_service
end
end
end
diff --git a/app/services/clusters/applications/check_installation_progress_service.rb b/app/services/clusters/applications/check_installation_progress_service.rb
index 35f5cff0e0c..21ec26ea233 100644
--- a/app/services/clusters/applications/check_installation_progress_service.rb
+++ b/app/services/clusters/applications/check_installation_progress_service.rb
@@ -14,8 +14,9 @@ module Clusters
else
check_timeout
end
- rescue Kubeclient::HttpError => ke
- app.make_errored!("Kubernetes error: #{ke.message}") unless app.errored?
+ rescue Kubeclient::HttpError => e
+ log_error(e)
+ app.make_errored!("Kubernetes error: #{e.error_code}") unless app.errored?
end
private
@@ -27,17 +28,13 @@ module Clusters
end
def on_failed
- app.make_errored!(installation_errors || 'Installation silently failed')
- ensure
- remove_installation_pod
+ app.make_errored!("Installation failed. Check pod logs for #{install_command.pod_name} for more details.")
end
def check_timeout
if timeouted?
begin
- app.make_errored!('Installation timed out')
- ensure
- remove_installation_pod
+ app.make_errored!("Installation timed out. Check pod logs for #{install_command.pod_name} for more details.")
end
else
ClusterWaitForAppInstallationWorker.perform_in(
@@ -51,8 +48,6 @@ module Clusters
def remove_installation_pod
helm_api.delete_pod!(install_command.pod_name)
- rescue
- # no-op
end
def installation_phase
diff --git a/app/services/clusters/applications/create_service.rb b/app/services/clusters/applications/create_service.rb
new file mode 100644
index 00000000000..a89772e82dc
--- /dev/null
+++ b/app/services/clusters/applications/create_service.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Applications
+ class CreateService
+ InvalidApplicationError = Class.new(StandardError)
+
+ attr_reader :cluster, :current_user, :params
+
+ def initialize(cluster, user, params = {})
+ @cluster = cluster
+ @current_user = user
+ @params = params.dup
+ end
+
+ def execute(request)
+ create_application.tap do |application|
+ if application.has_attribute?(:hostname)
+ application.hostname = params[:hostname]
+ end
+
+ if application.has_attribute?(:email)
+ application.email = current_user.email
+ end
+
+ if application.respond_to?(:oauth_application)
+ application.oauth_application = create_oauth_application(application, request)
+ end
+
+ application.save!
+
+ Clusters::Applications::ScheduleInstallationService.new(application).execute
+ end
+ end
+
+ private
+
+ def create_application
+ builder.call(@cluster)
+ end
+
+ def builder
+ builders[application_name] || raise(InvalidApplicationError, "invalid application: #{application_name}")
+ end
+
+ def builders
+ {
+ "helm" => -> (cluster) { cluster.application_helm || cluster.build_application_helm },
+ "ingress" => -> (cluster) { cluster.application_ingress || cluster.build_application_ingress },
+ "cert_manager" => -> (cluster) { cluster.application_cert_manager || cluster.build_application_cert_manager }
+ }.tap do |hash|
+ hash.merge!(project_builders) if cluster.project_type?
+ end
+ end
+
+ # These applications will need extra configuration to enable them to work
+ # with groups of projects
+ def project_builders
+ {
+ "prometheus" => -> (cluster) { cluster.application_prometheus || cluster.build_application_prometheus },
+ "runner" => -> (cluster) { cluster.application_runner || cluster.build_application_runner },
+ "jupyter" => -> (cluster) { cluster.application_jupyter || cluster.build_application_jupyter },
+ "knative" => -> (cluster) { cluster.application_knative || cluster.build_application_knative }
+ }
+ end
+
+ def application_name
+ params[:application]
+ end
+
+ def create_oauth_application(application, request)
+ oauth_application_params = {
+ name: params[:application],
+ redirect_uri: application.callback_url,
+ scopes: 'api read_user openid',
+ owner: current_user
+ }
+
+ ::Applications::CreateService.new(current_user, oauth_application_params).execute(request)
+ end
+ end
+ end
+end
diff --git a/app/services/clusters/applications/install_service.rb b/app/services/clusters/applications/install_service.rb
index 7e3c0e77a83..5a65dc4ef59 100644
--- a/app/services/clusters/applications/install_service.rb
+++ b/app/services/clusters/applications/install_service.rb
@@ -12,10 +12,12 @@ module Clusters
ClusterWaitForAppInstallationWorker.perform_in(
ClusterWaitForAppInstallationWorker::INTERVAL, app.name, app.id)
- rescue Kubeclient::HttpError => ke
- app.make_errored!("Kubernetes error: #{ke.message}")
+ rescue Kubeclient::HttpError => e
+ log_error(e)
+ app.make_errored!("Kubernetes error: #{e.error_code}")
rescue StandardError => e
- app.make_errored!("Can't start installation process. #{e.message}")
+ log_error(e)
+ app.make_errored!("Can't start installation process.")
end
end
end
diff --git a/app/services/clusters/applications/schedule_installation_service.rb b/app/services/clusters/applications/schedule_installation_service.rb
index 4ead4f619c8..d75ba70c27e 100644
--- a/app/services/clusters/applications/schedule_installation_service.rb
+++ b/app/services/clusters/applications/schedule_installation_service.rb
@@ -2,8 +2,14 @@
module Clusters
module Applications
- class ScheduleInstallationService < ::BaseService
- def execute(application)
+ class ScheduleInstallationService
+ attr_reader :application
+
+ def initialize(application)
+ @application = application
+ end
+
+ def execute
application.make_scheduled!
ClusterInstallAppWorker.perform_async(application.name, application.id)
diff --git a/app/services/clusters/create_service.rb b/app/services/clusters/create_service.rb
index e3e0cfa462c..5a9da053780 100644
--- a/app/services/clusters/create_service.rb
+++ b/app/services/clusters/create_service.rb
@@ -1,37 +1,51 @@
# frozen_string_literal: true
module Clusters
- class CreateService < BaseService
- attr_reader :access_token
+ class CreateService
+ attr_reader :current_user, :params
- def execute(access_token = nil)
- @access_token = access_token
+ def initialize(user = nil, params = {})
+ @current_user, @params = user, params.dup
+ end
+
+ def execute(access_token: nil)
+ raise ArgumentError, 'Unknown clusterable provided' unless clusterable
+ raise ArgumentError, _('Instance does not support multiple Kubernetes clusters') unless can_create_cluster?
- raise ArgumentError.new(_('Instance does not support multiple Kubernetes clusters')) unless can_create_cluster?
+ cluster_params = params.merge(user: current_user).merge(clusterable_params)
+ cluster_params[:provider_gcp_attributes].try do |provider|
+ provider[:access_token] = access_token
+ end
- create_cluster.tap do |cluster|
+ create_cluster(cluster_params).tap do |cluster|
ClusterProvisionWorker.perform_async(cluster.id) if cluster.persisted?
end
end
private
- def create_cluster
+ def create_cluster(cluster_params)
Clusters::Cluster.create(cluster_params)
end
- def cluster_params
- return @cluster_params if defined?(@cluster_params)
+ def clusterable
+ @clusterable ||= params.delete(:clusterable)
+ end
- params[:provider_gcp_attributes].try do |provider|
- provider[:access_token] = access_token
+ def clusterable_params
+ case clusterable
+ when ::Project
+ { cluster_type: :project_type, projects: [clusterable] }
+ when ::Group
+ { cluster_type: :group_type, groups: [clusterable] }
+ else
+ raise NotImplementedError
end
-
- @cluster_params = params.merge(user: current_user, projects: [project])
end
+ # EE would override this method
def can_create_cluster?
- project.clusters.empty?
+ clusterable.clusters.empty?
end
end
end
diff --git a/app/services/clusters/gcp/finalize_creation_service.rb b/app/services/clusters/gcp/finalize_creation_service.rb
index 3ae0a4a19d0..3df43657fa0 100644
--- a/app/services/clusters/gcp/finalize_creation_service.rb
+++ b/app/services/clusters/gcp/finalize_creation_service.rb
@@ -11,8 +11,9 @@ module Clusters
configure_provider
create_gitlab_service_account!
configure_kubernetes
-
cluster.save!
+ configure_project_service_account
+
rescue Google::Apis::ServerError, Google::Apis::ClientError, Google::Apis::AuthorizationError => e
provider.make_errored!("Failed to request to CloudPlatform; #{e.message}")
rescue Kubeclient::HttpError => e
@@ -24,7 +25,10 @@ module Clusters
private
def create_gitlab_service_account!
- Clusters::Gcp::Kubernetes::CreateServiceAccountService.new(kube_client, rbac: create_rbac_cluster?).execute
+ Clusters::Gcp::Kubernetes::CreateServiceAccountService.gitlab_creator(
+ kube_client,
+ rbac: create_rbac_cluster?
+ ).execute
end
def configure_provider
@@ -44,7 +48,20 @@ module Clusters
end
def request_kubernetes_token
- Clusters::Gcp::Kubernetes::FetchKubernetesTokenService.new(kube_client).execute
+ Clusters::Gcp::Kubernetes::FetchKubernetesTokenService.new(
+ kube_client,
+ Clusters::Gcp::Kubernetes::GITLAB_ADMIN_TOKEN_NAME,
+ Clusters::Gcp::Kubernetes::GITLAB_SERVICE_ACCOUNT_NAMESPACE
+ ).execute
+ end
+
+ def configure_project_service_account
+ kubernetes_namespace = cluster.find_or_initialize_kubernetes_namespace(cluster.cluster_project)
+
+ Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService.new(
+ cluster: cluster,
+ kubernetes_namespace: kubernetes_namespace
+ ).execute
end
def authorization_type
@@ -60,18 +77,15 @@ module Clusters
'https://' + gke_cluster.endpoint,
Base64.decode64(gke_cluster.master_auth.cluster_ca_certificate),
gke_cluster.master_auth.username,
- gke_cluster.master_auth.password,
- api_groups: ['api', 'apis/rbac.authorization.k8s.io']
+ gke_cluster.master_auth.password
)
end
- def build_kube_client!(api_url, ca_pem, username, password, api_groups: ['api'], api_version: 'v1')
+ def build_kube_client!(api_url, ca_pem, username, password)
raise "Incomplete settings" unless api_url && username && password
Gitlab::Kubernetes::KubeClient.new(
api_url,
- api_groups,
- api_version,
auth_options: { username: username, password: password },
ssl_options: kubeclient_ssl_options(ca_pem),
http_proxy_uri: ENV['http_proxy']
diff --git a/app/services/clusters/gcp/kubernetes.rb b/app/services/clusters/gcp/kubernetes.rb
index d014d73b3e8..90ed529670c 100644
--- a/app/services/clusters/gcp/kubernetes.rb
+++ b/app/services/clusters/gcp/kubernetes.rb
@@ -3,11 +3,12 @@
module Clusters
module Gcp
module Kubernetes
- SERVICE_ACCOUNT_NAME = 'gitlab'
- SERVICE_ACCOUNT_NAMESPACE = 'default'
- SERVICE_ACCOUNT_TOKEN_NAME = 'gitlab-token'
- CLUSTER_ROLE_BINDING_NAME = 'gitlab-admin'
- CLUSTER_ROLE_NAME = 'cluster-admin'
+ GITLAB_SERVICE_ACCOUNT_NAME = 'gitlab'
+ GITLAB_SERVICE_ACCOUNT_NAMESPACE = 'default'
+ GITLAB_ADMIN_TOKEN_NAME = 'gitlab-token'
+ GITLAB_CLUSTER_ROLE_BINDING_NAME = 'gitlab-admin'
+ GITLAB_CLUSTER_ROLE_NAME = 'cluster-admin'
+ PROJECT_CLUSTER_ROLE_NAME = 'edit'
end
end
end
diff --git a/app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb b/app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb
new file mode 100644
index 00000000000..b31426556f6
--- /dev/null
+++ b/app/services/clusters/gcp/kubernetes/create_or_update_namespace_service.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Gcp
+ module Kubernetes
+ class CreateOrUpdateNamespaceService
+ def initialize(cluster:, kubernetes_namespace:)
+ @cluster = cluster
+ @kubernetes_namespace = kubernetes_namespace
+ @platform = cluster.platform
+ end
+
+ def execute
+ configure_kubernetes_namespace
+ create_project_service_account
+ configure_kubernetes_token
+
+ kubernetes_namespace.save!
+ end
+
+ private
+
+ attr_reader :cluster, :kubernetes_namespace, :platform
+
+ def configure_kubernetes_namespace
+ kubernetes_namespace.set_defaults
+ end
+
+ def create_project_service_account
+ Clusters::Gcp::Kubernetes::CreateServiceAccountService.namespace_creator(
+ platform.kubeclient,
+ service_account_name: kubernetes_namespace.service_account_name,
+ service_account_namespace: kubernetes_namespace.namespace,
+ rbac: platform.rbac?
+ ).execute
+ end
+
+ def configure_kubernetes_token
+ kubernetes_namespace.service_account_token = fetch_service_account_token
+ end
+
+ def fetch_service_account_token
+ Clusters::Gcp::Kubernetes::FetchKubernetesTokenService.new(
+ platform.kubeclient,
+ kubernetes_namespace.token_name,
+ kubernetes_namespace.namespace
+ ).execute
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/clusters/gcp/kubernetes/create_service_account_service.rb b/app/services/clusters/gcp/kubernetes/create_service_account_service.rb
index d17744591e6..dfc4bf7a358 100644
--- a/app/services/clusters/gcp/kubernetes/create_service_account_service.rb
+++ b/app/services/clusters/gcp/kubernetes/create_service_account_service.rb
@@ -4,46 +4,96 @@ module Clusters
module Gcp
module Kubernetes
class CreateServiceAccountService
- attr_reader :kubeclient, :rbac
-
- def initialize(kubeclient, rbac:)
+ def initialize(kubeclient, service_account_name:, service_account_namespace:, token_name:, rbac:, namespace_creator: false, role_binding_name: nil)
@kubeclient = kubeclient
+ @service_account_name = service_account_name
+ @service_account_namespace = service_account_namespace
+ @token_name = token_name
@rbac = rbac
+ @namespace_creator = namespace_creator
+ @role_binding_name = role_binding_name
+ end
+
+ def self.gitlab_creator(kubeclient, rbac:)
+ self.new(
+ kubeclient,
+ service_account_name: Clusters::Gcp::Kubernetes::GITLAB_SERVICE_ACCOUNT_NAME,
+ service_account_namespace: Clusters::Gcp::Kubernetes::GITLAB_SERVICE_ACCOUNT_NAMESPACE,
+ token_name: Clusters::Gcp::Kubernetes::GITLAB_ADMIN_TOKEN_NAME,
+ rbac: rbac
+ )
+ end
+
+ def self.namespace_creator(kubeclient, service_account_name:, service_account_namespace:, rbac:)
+ self.new(
+ kubeclient,
+ service_account_name: service_account_name,
+ service_account_namespace: service_account_namespace,
+ token_name: "#{service_account_namespace}-token",
+ rbac: rbac,
+ namespace_creator: true,
+ role_binding_name: "gitlab-#{service_account_namespace}"
+ )
end
def execute
+ ensure_project_namespace_exists if namespace_creator
kubeclient.create_service_account(service_account_resource)
kubeclient.create_secret(service_account_token_resource)
- kubeclient.create_cluster_role_binding(cluster_role_binding_resource) if rbac
+ create_role_or_cluster_role_binding if rbac
end
private
+ attr_reader :kubeclient, :service_account_name, :service_account_namespace, :token_name, :rbac, :namespace_creator, :role_binding_name
+
+ def ensure_project_namespace_exists
+ Gitlab::Kubernetes::Namespace.new(
+ service_account_namespace,
+ kubeclient
+ ).ensure_exists!
+ end
+
+ def create_role_or_cluster_role_binding
+ if namespace_creator
+ kubeclient.create_role_binding(role_binding_resource)
+ else
+ kubeclient.create_cluster_role_binding(cluster_role_binding_resource)
+ end
+ end
+
def service_account_resource
- Gitlab::Kubernetes::ServiceAccount.new(service_account_name, service_account_namespace).generate
+ Gitlab::Kubernetes::ServiceAccount.new(
+ service_account_name,
+ service_account_namespace
+ ).generate
end
def service_account_token_resource
Gitlab::Kubernetes::ServiceAccountToken.new(
- SERVICE_ACCOUNT_TOKEN_NAME, service_account_name, service_account_namespace).generate
+ token_name,
+ service_account_name,
+ service_account_namespace
+ ).generate
end
def cluster_role_binding_resource
subjects = [{ kind: 'ServiceAccount', name: service_account_name, namespace: service_account_namespace }]
Gitlab::Kubernetes::ClusterRoleBinding.new(
- CLUSTER_ROLE_BINDING_NAME,
- CLUSTER_ROLE_NAME,
+ Clusters::Gcp::Kubernetes::GITLAB_CLUSTER_ROLE_BINDING_NAME,
+ Clusters::Gcp::Kubernetes::GITLAB_CLUSTER_ROLE_NAME,
subjects
).generate
end
- def service_account_name
- SERVICE_ACCOUNT_NAME
- end
-
- def service_account_namespace
- SERVICE_ACCOUNT_NAMESPACE
+ def role_binding_resource
+ Gitlab::Kubernetes::RoleBinding.new(
+ name: role_binding_name,
+ role_name: Clusters::Gcp::Kubernetes::PROJECT_CLUSTER_ROLE_NAME,
+ namespace: service_account_namespace,
+ service_account_name: service_account_name
+ ).generate
end
end
end
diff --git a/app/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service.rb b/app/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service.rb
index 9e09345c8dc..4ad04ab801e 100644
--- a/app/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service.rb
+++ b/app/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service.rb
@@ -4,10 +4,12 @@ module Clusters
module Gcp
module Kubernetes
class FetchKubernetesTokenService
- attr_reader :kubeclient
+ attr_reader :kubeclient, :service_account_token_name, :namespace
- def initialize(kubeclient)
+ def initialize(kubeclient, service_account_token_name, namespace)
@kubeclient = kubeclient
+ @service_account_token_name = service_account_token_name
+ @namespace = namespace
end
def execute
@@ -18,11 +20,8 @@ module Clusters
private
def get_secret
- kubeclient.get_secret(SERVICE_ACCOUNT_TOKEN_NAME, SERVICE_ACCOUNT_NAMESPACE).as_json
- rescue Kubeclient::HttpError => err
- raise err unless err.error_code == 404
-
- nil
+ kubeclient.get_secret(service_account_token_name, namespace).as_json
+ rescue Kubeclient::ResourceNotFoundError
end
end
end
diff --git a/app/services/clusters/update_service.rb b/app/services/clusters/update_service.rb
index 98fdeec4fb1..25d26e761b1 100644
--- a/app/services/clusters/update_service.rb
+++ b/app/services/clusters/update_service.rb
@@ -1,7 +1,13 @@
# frozen_string_literal: true
module Clusters
- class UpdateService < BaseService
+ class UpdateService
+ attr_reader :current_user, :params
+
+ def initialize(user = nil, params = {})
+ @current_user, @params = user, params.dup
+ end
+
def execute(cluster)
cluster.update(params)
end
diff --git a/app/services/commits/change_service.rb b/app/services/commits/change_service.rb
index 2fbd442fc2e..fbf71f02837 100644
--- a/app/services/commits/change_service.rb
+++ b/app/services/commits/change_service.rb
@@ -24,8 +24,12 @@ module Commits
start_project: @start_project,
start_branch_name: @start_branch)
rescue Gitlab::Git::Repository::CreateTreeError
- error_msg = "Sorry, we cannot #{action.to_s.dasherize} this #{@commit.change_type_title(current_user)} automatically.
- This #{@commit.change_type_title(current_user)} may already have been #{action.to_s.dasherize}ed, or a more recent commit may have updated some of its content."
+ act = action.to_s.dasherize
+ type = @commit.change_type_title(current_user)
+
+ error_msg = "Sorry, we cannot #{act} this #{type} automatically. " \
+ "This #{type} may already have been #{act}ed, or a more recent " \
+ "commit may have updated some of its content."
raise ChangeError, error_msg
end
end
diff --git a/app/services/commits/commit_patch_service.rb b/app/services/commits/commit_patch_service.rb
new file mode 100644
index 00000000000..49113c3c691
--- /dev/null
+++ b/app/services/commits/commit_patch_service.rb
@@ -0,0 +1,61 @@
+# frozen_string_literal: true
+
+module Commits
+ class CommitPatchService < CreateService
+ # Requires:
+ # - project: `Project` to be committed into
+ # - user: `User` that will be the committer
+ # - params:
+ # - branch_name: `String` the branch that will be committed into
+ # - start_branch: `String` the branch that will be started from
+ # - patches: `Gitlab::Git::Patches::Collection` that contains the patches
+ def initialize(*args)
+ super
+
+ @patches = Gitlab::Git::Patches::Collection.new(Array(params[:patches]))
+ end
+
+ private
+
+ def new_branch?
+ !repository.branch_exists?(@branch_name)
+ end
+
+ def create_commit!
+ if @start_branch && new_branch?
+ prepare_branch!
+ end
+
+ Gitlab::Git::Patches::CommitPatches
+ .new(current_user, project.repository, @branch_name, @patches)
+ .commit
+ end
+
+ def prepare_branch!
+ branch_result = CreateBranchService.new(project, current_user)
+ .execute(@branch_name, @start_branch)
+
+ if branch_result[:status] != :success
+ raise ChangeError, branch_result[:message]
+ end
+ end
+
+ # Overridden from the Commits::CreateService, to skip some validations we
+ # don't need:
+ # - validate_on_branch!
+ # Not needed, the patches are applied on top of HEAD if the branch did not
+ # exist
+ # - validate_branch_existence!
+ # Not needed because we continue applying patches on the branch if it
+ # already existed, and create it if it did not exist.
+ def validate!
+ validate_patches!
+ validate_new_branch_name! if new_branch?
+ validate_permissions!
+ end
+
+ def validate_patches!
+ raise_error("Patches are too big") unless @patches.valid_size?
+ end
+ end
+end
diff --git a/app/services/commits/create_service.rb b/app/services/commits/create_service.rb
index 3ce9acc833c..34593e12bd5 100644
--- a/app/services/commits/create_service.rb
+++ b/app/services/commits/create_service.rb
@@ -19,7 +19,12 @@ module Commits
new_commit = create_commit!
success(result: new_commit)
- rescue ValidationError, ChangeError, Gitlab::Git::Index::IndexError, Gitlab::Git::CommitError, Gitlab::Git::PreReceiveError => ex
+ rescue ValidationError,
+ ChangeError,
+ Gitlab::Git::Index::IndexError,
+ Gitlab::Git::CommitError,
+ Gitlab::Git::PreReceiveError,
+ Gitlab::Git::CommandError => ex
error(ex.message)
end
diff --git a/app/services/create_deployment_service.rb b/app/services/create_deployment_service.rb
deleted file mode 100644
index bb3f605da28..00000000000
--- a/app/services/create_deployment_service.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-
-class CreateDeploymentService
- attr_reader :job
-
- delegate :expanded_environment_name,
- :variables,
- :project,
- to: :job
-
- def initialize(job)
- @job = job
- end
-
- def execute
- return unless executable?
-
- ActiveRecord::Base.transaction do
- environment.external_url = expanded_environment_url if
- expanded_environment_url
-
- environment.fire_state_event(action)
-
- break unless environment.save
- break if environment.stopped?
-
- deploy.tap(&:update_merge_request_metrics!)
- end
- end
-
- private
-
- def executable?
- project && job.environment.present? && environment
- end
-
- def deploy
- project.deployments.create(
- environment: environment,
- ref: job.ref,
- tag: job.tag,
- sha: job.sha,
- user: job.user,
- deployable: job,
- on_stop: on_stop)
- end
-
- def environment
- @environment ||= job.persisted_environment
- end
-
- def environment_options
- @environment_options ||= job.options&.dig(:environment) || {}
- end
-
- def expanded_environment_url
- return @expanded_environment_url if defined?(@expanded_environment_url)
-
- @expanded_environment_url =
- ExpandVariables.expand(environment_url, variables) if environment_url
- end
-
- def environment_url
- environment_options[:url]
- end
-
- def on_stop
- environment_options[:on_stop]
- end
-
- def action
- environment_options[:action] || 'start'
- end
-end
diff --git a/app/services/delete_merged_branches_service.rb b/app/services/delete_merged_branches_service.rb
index ced87a1c37a..80de897e94b 100644
--- a/app/services/delete_merged_branches_service.rb
+++ b/app/services/delete_merged_branches_service.rb
@@ -24,8 +24,8 @@ class DeleteMergedBranchesService < BaseService
# rubocop: disable CodeReuse/ActiveRecord
def merge_request_branch_names
# reorder(nil) is necessary for SELECT DISTINCT because default scope adds an ORDER BY
- source_names = project.origin_merge_requests.opened.reorder(nil).uniq.pluck(:source_branch)
- target_names = project.merge_requests.opened.reorder(nil).uniq.pluck(:target_branch)
+ source_names = project.origin_merge_requests.opened.reorder(nil).distinct.pluck(:source_branch)
+ target_names = project.merge_requests.opened.reorder(nil).distinct.pluck(:target_branch)
(source_names + target_names).uniq
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/files/multi_service.rb b/app/services/files/multi_service.rb
index 08088f8c592..927634c2159 100644
--- a/app/services/files/multi_service.rb
+++ b/app/services/files/multi_service.rb
@@ -2,12 +2,13 @@
module Files
class MultiService < Files::BaseService
- UPDATE_FILE_ACTIONS = %w(update move delete).freeze
+ UPDATE_FILE_ACTIONS = %w(update move delete chmod).freeze
def create_commit!
transformer = Lfs::FileTransformer.new(project, @branch_name)
actions = actions_after_lfs_transformation(transformer, params[:actions])
+ actions = transform_move_actions(actions)
commit_actions!(actions)
end
@@ -26,6 +27,16 @@ module Files
end
end
+ # When moving a file, `content: nil` means "use the contents of the previous
+ # file", while `content: ''` means "move the file and set it to empty"
+ def transform_move_actions(actions)
+ actions.map do |action|
+ action[:infer_content] = true if action[:content].nil?
+
+ action
+ end
+ end
+
def commit_actions!(actions)
repository.multi_action(
current_user,
diff --git a/app/services/groups/update_service.rb b/app/services/groups/update_service.rb
index fe47aa2f140..0bf0e967dcc 100644
--- a/app/services/groups/update_service.rb
+++ b/app/services/groups/update_service.rb
@@ -14,9 +14,11 @@ module Groups
group.assign_attributes(params)
begin
- after_update if group.save
+ success = group.save
- true
+ after_update if success
+
+ success
rescue Gitlab::UpdatePathError => e
group.errors.add(:base, e.message)
diff --git a/app/services/issuable/clone/attributes_rewriter.rb b/app/services/issuable/clone/attributes_rewriter.rb
new file mode 100644
index 00000000000..0300cc0d8d3
--- /dev/null
+++ b/app/services/issuable/clone/attributes_rewriter.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+module Issuable
+ module Clone
+ class AttributesRewriter < ::Issuable::Clone::BaseService
+ def initialize(current_user, original_entity, new_entity)
+ @current_user = current_user
+ @original_entity = original_entity
+ @new_entity = new_entity
+ end
+
+ def execute
+ new_entity.update(milestone: cloneable_milestone, labels: cloneable_labels)
+ copy_resource_label_events
+ end
+
+ private
+
+ def cloneable_milestone
+ title = original_entity.milestone&.title
+ return unless title
+
+ params = { title: title, project_ids: new_entity.project&.id, group_ids: group&.id }
+
+ milestones = MilestonesFinder.new(params).execute
+ milestones.first
+ end
+
+ def cloneable_labels
+ params = {
+ project_id: new_entity.project&.id,
+ group_id: group&.id,
+ title: original_entity.labels.select(:title),
+ include_ancestor_groups: true
+ }
+
+ params[:only_group_labels] = true if new_parent.is_a?(Group)
+
+ LabelsFinder.new(current_user, params).execute
+ end
+
+ def copy_resource_label_events
+ original_entity.resource_label_events.find_in_batches do |batch|
+ events = batch.map do |event|
+ entity_key = new_entity.is_a?(Issue) ? 'issue_id' : 'epic_id'
+ # rubocop: disable CodeReuse/ActiveRecord
+ event.attributes
+ .except('id', 'reference', 'reference_html')
+ .merge(entity_key => new_entity.id, 'action' => ResourceLabelEvent.actions[event.action])
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+
+ Gitlab::Database.bulk_insert(ResourceLabelEvent.table_name, events)
+ end
+ end
+
+ def entity_key
+ new_entity.class.name.parameterize('_').foreign_key
+ end
+ end
+ end
+end
diff --git a/app/services/issuable/clone/base_service.rb b/app/services/issuable/clone/base_service.rb
new file mode 100644
index 00000000000..42dd9c666f5
--- /dev/null
+++ b/app/services/issuable/clone/base_service.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module Issuable
+ module Clone
+ class BaseService < IssuableBaseService
+ attr_reader :original_entity, :new_entity
+
+ alias_method :old_project, :project
+
+ def execute(original_entity, new_project = nil)
+ @original_entity = original_entity
+
+ # Using transaction because of a high resources footprint
+ # on rewriting notes (unfolding references)
+ #
+ ActiveRecord::Base.transaction do
+ @new_entity = create_new_entity
+
+ update_new_entity
+ update_old_entity
+ create_notes
+ end
+ end
+
+ private
+
+ def update_new_entity
+ rewriters = [ContentRewriter, AttributesRewriter]
+
+ rewriters.each do |rewriter|
+ rewriter.new(current_user, original_entity, new_entity).execute
+ end
+ end
+
+ def update_old_entity
+ close_issue
+ end
+
+ def create_notes
+ add_note_from
+ add_note_to
+ end
+
+ def close_issue
+ close_service = Issues::CloseService.new(old_project, current_user)
+ close_service.execute(original_entity, notifications: false, system_note: false)
+ end
+
+ def new_parent
+ new_entity.project ? new_entity.project : new_entity.group
+ end
+
+ def group
+ if new_entity.project&.group && current_user.can?(:read_group, new_entity.project.group)
+ new_entity.project.group
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/issuable/clone/content_rewriter.rb b/app/services/issuable/clone/content_rewriter.rb
new file mode 100644
index 00000000000..e1e0b75085d
--- /dev/null
+++ b/app/services/issuable/clone/content_rewriter.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+module Issuable
+ module Clone
+ class ContentRewriter < ::Issuable::Clone::BaseService
+ def initialize(current_user, original_entity, new_entity)
+ @current_user = current_user
+ @original_entity = original_entity
+ @new_entity = new_entity
+ @project = original_entity.project
+ end
+
+ def execute
+ rewrite_description
+ rewrite_award_emoji(original_entity, new_entity)
+ rewrite_notes
+ end
+
+ private
+
+ def rewrite_description
+ new_entity.update(description: rewrite_content(original_entity.description))
+ end
+
+ def rewrite_notes
+ original_entity.notes_with_associations.find_each do |note|
+ new_note = note.dup
+ new_params = {
+ project: new_entity.project, noteable: new_entity,
+ note: rewrite_content(new_note.note),
+ created_at: note.created_at,
+ updated_at: note.updated_at
+ }
+
+ if note.system_note_metadata
+ new_params[:system_note_metadata] = note.system_note_metadata.dup
+ end
+
+ new_note.update(new_params)
+
+ rewrite_award_emoji(note, new_note)
+ end
+ end
+
+ def rewrite_content(content)
+ return unless content
+
+ rewriters = [Gitlab::Gfm::ReferenceRewriter, Gitlab::Gfm::UploadsRewriter]
+
+ rewriters.inject(content) do |text, klass|
+ rewriter = klass.new(text, old_project, current_user)
+ rewriter.rewrite(new_parent)
+ end
+ end
+
+ def rewrite_award_emoji(old_awardable, new_awardable)
+ old_awardable.award_emoji.each do |award|
+ new_award = award.dup
+ new_award.awardable = new_awardable
+ new_award.save
+ end
+ end
+ end
+ end
+end
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index 3e8b9f84042..e32e262ac31 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -3,6 +3,14 @@
class IssuableBaseService < BaseService
private
+ attr_accessor :params, :skip_milestone_email
+
+ def initialize(project, user = nil, params = {})
+ super
+
+ @skip_milestone_email = @params.delete(:skip_milestone_email)
+ end
+
def filter_params(issuable)
ability_name = :"admin_#{issuable.to_ability_name}"
@@ -118,12 +126,12 @@ class IssuableBaseService < BaseService
merge_quick_actions_into_params!(issuable)
end
- def merge_quick_actions_into_params!(issuable)
+ def merge_quick_actions_into_params!(issuable, only: nil)
original_description = params.fetch(:description, issuable.description)
description, command_params =
QuickActions::InterpretService.new(project, current_user)
- .execute(original_description, issuable)
+ .execute(original_description, issuable, only: only)
# Avoid a description already set on an issuable to be overwritten by a nil
params[:description] = description if description
diff --git a/app/services/issues/move_service.rb b/app/services/issues/move_service.rb
index d2bdba1e627..41b6a96b005 100644
--- a/app/services/issues/move_service.rb
+++ b/app/services/issues/move_service.rb
@@ -1,165 +1,66 @@
# frozen_string_literal: true
module Issues
- class MoveService < Issues::BaseService
+ class MoveService < Issuable::Clone::BaseService
MoveError = Class.new(StandardError)
- def execute(issue, new_project)
- @old_issue = issue
- @old_project = @project
- @new_project = new_project
+ def execute(issue, target_project)
+ @target_project = target_project
- unless issue.can_move?(current_user, new_project)
+ unless issue.can_move?(current_user, @target_project)
raise MoveError, 'Cannot move issue due to insufficient permissions!'
end
- if @project == new_project
+ if @project == @target_project
raise MoveError, 'Cannot move issue to project it originates from!'
end
- # Using transaction because of a high resources footprint
- # on rewriting notes (unfolding references)
- #
- ActiveRecord::Base.transaction do
- @new_issue = create_new_issue
-
- update_new_issue
- update_old_issue
- end
+ super
notify_participants
- @new_issue
+ new_entity
end
private
- def update_new_issue
- rewrite_notes
- copy_resource_label_events
- rewrite_issue_award_emoji
- add_note_moved_from
- end
+ def update_old_entity
+ super
- def update_old_issue
- add_note_moved_to
- close_issue
mark_as_moved
end
- def create_new_issue
- new_params = { id: nil, iid: nil, label_ids: cloneable_label_ids,
- milestone_id: cloneable_milestone_id,
- project: @new_project, author: @old_issue.author,
- description: rewrite_content(@old_issue.description),
- assignee_ids: @old_issue.assignee_ids }
-
- new_params = @old_issue.serializable_hash.symbolize_keys.merge(new_params)
- CreateService.new(@new_project, @current_user, new_params).execute
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def cloneable_label_ids
- params = {
- project_id: @new_project.id,
- title: @old_issue.labels.pluck(:title),
- include_ancestor_groups: true
- }
+ def create_new_entity
+ new_params = {
+ id: nil,
+ iid: nil,
+ project: @target_project,
+ author: original_entity.author,
+ assignee_ids: original_entity.assignee_ids
+ }
- LabelsFinder.new(current_user, params).execute.pluck(:id)
+ new_params = original_entity.serializable_hash.symbolize_keys.merge(new_params)
+ CreateService.new(@target_project, @current_user, new_params).execute
end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def cloneable_milestone_id
- title = @old_issue.milestone&.title
- return unless title
-
- if @new_project.group && can?(current_user, :read_group, @new_project.group)
- group_id = @new_project.group.id
- end
-
- params =
- { title: title, project_ids: @new_project.id, group_ids: group_id }
- milestones = MilestonesFinder.new(params).execute
- milestones.first&.id
- end
-
- def rewrite_notes
- @old_issue.notes_with_associations.find_each do |note|
- new_note = note.dup
- new_params = { project: @new_project, noteable: @new_issue,
- note: rewrite_content(new_note.note),
- created_at: note.created_at,
- updated_at: note.updated_at }
-
- new_note.update(new_params)
-
- rewrite_award_emoji(note, new_note)
- end
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def copy_resource_label_events
- @old_issue.resource_label_events.find_in_batches do |batch|
- events = batch.map do |event|
- event.attributes
- .except('id', 'reference', 'reference_html')
- .merge('issue_id' => @new_issue.id, 'action' => ResourceLabelEvent.actions[event.action])
- end
-
- Gitlab::Database.bulk_insert(ResourceLabelEvent.table_name, events)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def rewrite_issue_award_emoji
- rewrite_award_emoji(@old_issue, @new_issue)
- end
-
- def rewrite_award_emoji(old_awardable, new_awardable)
- old_awardable.award_emoji.each do |award|
- new_award = award.dup
- new_award.awardable = new_awardable
- new_award.save
- end
- end
-
- def rewrite_content(content)
- return unless content
-
- rewriters = [Gitlab::Gfm::ReferenceRewriter,
- Gitlab::Gfm::UploadsRewriter]
-
- rewriters.inject(content) do |text, klass|
- rewriter = klass.new(text, @old_project, @current_user)
- rewriter.rewrite(@new_project)
- end
+ def mark_as_moved
+ original_entity.update(moved_to: new_entity)
end
- def close_issue
- close_service = CloseService.new(@old_project, @current_user)
- close_service.execute(@old_issue, notifications: false, system_note: false)
+ def notify_participants
+ notification_service.async.issue_moved(original_entity, new_entity, @current_user)
end
- def add_note_moved_from
- SystemNoteService.noteable_moved(@new_issue, @new_project,
- @old_issue, @current_user,
+ def add_note_from
+ SystemNoteService.noteable_moved(new_entity, @target_project,
+ original_entity, current_user,
direction: :from)
end
- def add_note_moved_to
- SystemNoteService.noteable_moved(@old_issue, @old_project,
- @new_issue, @current_user,
+ def add_note_to
+ SystemNoteService.noteable_moved(original_entity, old_project,
+ new_entity, current_user,
direction: :to)
end
-
- def mark_as_moved
- @old_issue.update(moved_to: @new_issue)
- end
-
- def notify_participants
- notification_service.async.issue_moved(@old_issue, @new_issue, @current_user)
- end
end
end
diff --git a/app/services/issues/related_branches_service.rb b/app/services/issues/related_branches_service.rb
new file mode 100644
index 00000000000..76af482b7ac
--- /dev/null
+++ b/app/services/issues/related_branches_service.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+# This service fetches all branches containing the current issue's ID, except for
+# those with a merge request open referencing the current issue.
+module Issues
+ class RelatedBranchesService < Issues::BaseService
+ def execute(issue)
+ branches_with_iid_of(issue) - branches_with_merge_request_for(issue)
+ end
+
+ private
+
+ def branches_with_merge_request_for(issue)
+ Issues::ReferencedMergeRequestsService
+ .new(project, current_user)
+ .referenced_merge_requests(issue)
+ .map(&:source_branch)
+ end
+
+ def branches_with_iid_of(issue)
+ project.repository.branch_names.select do |branch|
+ branch =~ /\A#{issue.iid}-(?!\d+-stable)/i
+ end
+ end
+ end
+end
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index b54b0bf6ef6..a1d0cc0e568 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -11,6 +11,12 @@ module Issues
move_issue_to_new_project(issue) || update(issue)
end
+ def update(issue)
+ create_merge_request_from_quick_action
+
+ super
+ end
+
def before_update(issue)
spam_check(issue, current_user)
end
@@ -48,6 +54,8 @@ module Issues
notification_service.async.relabeled_issue(issue, added_labels, current_user)
end
+ handle_milestone_change(issue)
+
added_mentions = issue.mentioned_users - old_mentioned_users
if added_mentions.present?
@@ -91,6 +99,25 @@ module Issues
private
+ def create_merge_request_from_quick_action
+ create_merge_request_params = params.delete(:create_merge_request)
+ return unless create_merge_request_params
+
+ MergeRequests::CreateFromIssueService.new(project, current_user, create_merge_request_params).execute
+ end
+
+ def handle_milestone_change(issue)
+ return if skip_milestone_email
+
+ return unless issue.previous_changes.include?('milestone_id')
+
+ if issue.milestone.nil?
+ notification_service.async.removed_milestone_issue(issue, current_user)
+ else
+ notification_service.async.changed_milestone_issue(issue, issue.milestone, current_user)
+ end
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def get_issue_if_allowed(id, board_group_id = nil)
return unless id
diff --git a/app/services/keys/destroy_service.rb b/app/services/keys/destroy_service.rb
index e2ae4047941..159455f80f3 100644
--- a/app/services/keys/destroy_service.rb
+++ b/app/services/keys/destroy_service.rb
@@ -6,7 +6,7 @@ module Keys
key.destroy if destroy_possible?(key)
end
- # overriden in EE::Keys::DestroyService
+ # overridden in EE::Keys::DestroyService
def destroy_possible?(key)
true
end
diff --git a/app/services/labels/transfer_service.rb b/app/services/labels/transfer_service.rb
index 52360f775dc..9cbc9fef529 100644
--- a/app/services/labels/transfer_service.rb
+++ b/app/services/labels/transfer_service.rb
@@ -40,7 +40,7 @@ module Labels
group_labels_applied_to_merge_requests
])
.reorder(nil)
- .uniq
+ .distinct
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/members/base_service.rb b/app/services/members/base_service.rb
index 8248f1441d7..d734571f835 100644
--- a/app/services/members/base_service.rb
+++ b/app/services/members/base_service.rb
@@ -10,7 +10,7 @@ module Members
end
def after_execute(args)
- # overriden in EE::Members modules
+ # overridden in EE::Members modules
end
private
diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb
index aa5d8406d0f..28c3219b37b 100644
--- a/app/services/merge_requests/base_service.rb
+++ b/app/services/merge_requests/base_service.rb
@@ -57,10 +57,10 @@ module MergeRequests
# Returns all origin and fork merge requests from `@project` satisfying passed arguments.
# rubocop: disable CodeReuse/ActiveRecord
def merge_requests_for(source_branch, mr_states: [:opened])
- MergeRequest
+ @project.source_of_merge_requests
.with_state(mr_states)
- .where(source_branch: source_branch, source_project_id: @project.id)
- .preload(:source_project) # we don't need a #includes since we're just preloading for the #select
+ .where(source_branch: source_branch)
+ .preload(:source_project) # we don't need #includes since we're just preloading for the #select
.select(&:source_project)
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb
index 0e76d2cc3ab..36767621d74 100644
--- a/app/services/merge_requests/build_service.rb
+++ b/app/services/merge_requests/build_service.rb
@@ -6,8 +6,13 @@ module MergeRequests
def execute
@params_issue_iid = params.delete(:issue_iid)
+ self.merge_request = MergeRequest.new
+ # TODO: this should handle all quick actions that don't have side effects
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/53658
+ merge_quick_actions_into_params!(merge_request, only: [:target_branch])
+ merge_request.merge_params['force_remove_source_branch'] = params.delete(:force_remove_source_branch) if params.has_key?(:force_remove_source_branch)
+ merge_request.assign_attributes(params)
- self.merge_request = MergeRequest.new(params)
merge_request.author = current_user
merge_request.compare_commits = []
merge_request.source_project = find_source_project
diff --git a/app/services/merge_requests/create_from_issue_service.rb b/app/services/merge_requests/create_from_issue_service.rb
index 020af0bb950..e69791872cc 100644
--- a/app/services/merge_requests/create_from_issue_service.rb
+++ b/app/services/merge_requests/create_from_issue_service.rb
@@ -19,13 +19,15 @@ module MergeRequests
result = CreateBranchService.new(project, current_user).execute(branch_name, ref)
return result if result[:status] == :error
- SystemNoteService.new_issue_branch(issue, project, current_user, branch_name)
-
new_merge_request = create(merge_request)
if new_merge_request.valid?
+ SystemNoteService.new_merge_request(issue, project, current_user, new_merge_request)
+
success(new_merge_request)
else
+ SystemNoteService.new_issue_branch(issue, project, current_user, branch_name)
+
error(new_merge_request.errors)
end
end
diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb
index fb44f809c41..70a67baa01c 100644
--- a/app/services/merge_requests/merge_service.rb
+++ b/app/services/merge_requests/merge_service.rb
@@ -49,6 +49,11 @@ module MergeRequests
end
end
+ # Overridden in EE.
+ def hooks_validation_pass?(_merge_request)
+ true
+ end
+
private
def error_check!
diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb
index bcdd752ddc4..5fe48da1cd6 100644
--- a/app/services/merge_requests/refresh_service.rb
+++ b/app/services/merge_requests/refresh_service.rb
@@ -2,18 +2,18 @@
module MergeRequests
class RefreshService < MergeRequests::BaseService
+ attr_reader :push
+
def execute(oldrev, newrev, ref)
- return true unless Gitlab::Git.branch_ref?(ref)
+ @push = Gitlab::Git::Push.new(@project, oldrev, newrev, ref)
+ return true unless @push.branch_push?
- do_execute(oldrev, newrev, ref)
+ refresh_merge_requests!
end
private
- def do_execute(oldrev, newrev, ref)
- @oldrev, @newrev = oldrev, newrev
- @branch_name = Gitlab::Git.ref_name(ref)
-
+ def refresh_merge_requests!
Gitlab::GitalyClient.allow_n_plus_1_calls(&method(:find_new_commits))
# Be sure to close outstanding MRs before reloading them to avoid generating an
# empty diff during a manual merge
@@ -25,7 +25,7 @@ module MergeRequests
cache_merge_requests_closing_issues
# Leave a system note if a branch was deleted/added
- if branch_added? || branch_removed?
+ if @push.branch_added? || @push.branch_removed?
comment_mr_branch_presence_changed
end
@@ -54,8 +54,10 @@ module MergeRequests
# rubocop: disable CodeReuse/ActiveRecord
def post_merge_manually_merged
commit_ids = @commits.map(&:id)
- merge_requests = @project.merge_requests.preload(:latest_merge_request_diff).opened.where(target_branch: @branch_name).to_a
- merge_requests = merge_requests.select(&:diff_head_commit)
+ merge_requests = @project.merge_requests.opened
+ .preload(:latest_merge_request_diff)
+ .where(target_branch: @push.branch_name).to_a
+ .select(&:diff_head_commit)
merge_requests = merge_requests.select do |merge_request|
commit_ids.include?(merge_request.diff_head_sha) &&
@@ -70,30 +72,23 @@ module MergeRequests
end
# rubocop: enable CodeReuse/ActiveRecord
- def force_push?
- Gitlab::Checks::ForcePush.force_push?(@project, @oldrev, @newrev)
- end
-
# Refresh merge request diff if we push to source or target branch of merge request
# Note: we should update merge requests from forks too
# rubocop: disable CodeReuse/ActiveRecord
def reload_merge_requests
merge_requests = @project.merge_requests.opened
- .by_source_or_target_branch(@branch_name).to_a
+ .by_source_or_target_branch(@push.branch_name).to_a
# Fork merge requests
merge_requests += MergeRequest.opened
- .where(source_branch: @branch_name, source_project: @project)
+ .where(source_branch: @push.branch_name, source_project: @project)
.where.not(target_project: @project).to_a
filter_merge_requests(merge_requests).each do |merge_request|
- if merge_request.source_branch == @branch_name || force_push?
+ if branch_and_project_match?(merge_request) || @push.force_push?
+ merge_request.reload_diff(current_user)
+ elsif merge_request.includes_any_commits?(push_commit_ids)
merge_request.reload_diff(current_user)
- else
- mr_commit_ids = merge_request.commit_shas
- push_commit_ids = @commits.map(&:id)
- matches = mr_commit_ids & push_commit_ids
- merge_request.reload_diff(current_user) if matches.any?
end
merge_request.mark_as_unchecked
@@ -106,6 +101,15 @@ module MergeRequests
end
# rubocop: enable CodeReuse/ActiveRecord
+ def push_commit_ids
+ @push_commit_ids ||= @commits.map(&:id)
+ end
+
+ def branch_and_project_match?(merge_request)
+ merge_request.source_project == @project &&
+ merge_request.source_branch == @push.branch_name
+ end
+
def reset_merge_when_pipeline_succeeds
merge_requests_for_source_branch.each(&:reset_merge_when_pipeline_succeeds)
end
@@ -117,7 +121,7 @@ module MergeRequests
end
def find_new_commits
- if branch_added?
+ if @push.branch_added?
@commits = []
merge_request = merge_requests_for_source_branch.first
@@ -126,28 +130,28 @@ module MergeRequests
begin
# Since any number of commits could have been made to the restored branch,
# find the common root to see what has been added.
- common_ref = @project.repository.merge_base(merge_request.diff_head_sha, @newrev)
+ common_ref = @project.repository.merge_base(merge_request.diff_head_sha, @push.newrev)
# If the a commit no longer exists in this repo, gitlab_git throws
# a Rugged::OdbError. This is fixed in https://gitlab.com/gitlab-org/gitlab_git/merge_requests/52
- @commits = @project.repository.commits_between(common_ref, @newrev) if common_ref
+ @commits = @project.repository.commits_between(common_ref, @push.newrev) if common_ref
rescue
end
- elsif branch_removed?
+ elsif @push.branch_removed?
# No commits for a deleted branch.
@commits = []
else
- @commits = @project.repository.commits_between(@oldrev, @newrev)
+ @commits = @project.repository.commits_between(@push.oldrev, @push.newrev)
end
end
# Add comment about branches being deleted or added to merge requests
def comment_mr_branch_presence_changed
- presence = branch_added? ? :add : :delete
+ presence = @push.branch_added? ? :add : :delete
merge_requests_for_source_branch.each do |merge_request|
SystemNoteService.change_branch_presence(
merge_request, merge_request.project, @current_user,
- :source, @branch_name, presence)
+ :source, @push.branch_name, presence)
end
end
@@ -164,7 +168,7 @@ module MergeRequests
SystemNoteService.add_commits(merge_request, merge_request.project,
@current_user, new_commits,
- existing_commits, @oldrev)
+ existing_commits, @push.oldrev)
notification_service.push_to_merge_request(merge_request, @current_user, new_commits: new_commits, existing_commits: existing_commits)
end
@@ -195,7 +199,7 @@ module MergeRequests
# Call merge request webhook with update branches
def execute_mr_web_hooks
merge_requests_for_source_branch.each do |merge_request|
- execute_hooks(merge_request, 'update', old_rev: @oldrev)
+ execute_hooks(merge_request, 'update', old_rev: @push.oldrev)
end
end
@@ -203,7 +207,7 @@ module MergeRequests
# `MergeRequestsClosingIssues` model (as a performance optimization).
# rubocop: disable CodeReuse/ActiveRecord
def cache_merge_requests_closing_issues
- @project.merge_requests.where(source_branch: @branch_name).each do |merge_request|
+ @project.merge_requests.where(source_branch: @push.branch_name).each do |merge_request|
merge_request.cache_merge_request_closes_issues!(@current_user)
end
end
@@ -215,15 +219,7 @@ module MergeRequests
def merge_requests_for_source_branch(reload: false)
@source_merge_requests = nil if reload
- @source_merge_requests ||= merge_requests_for(@branch_name)
- end
-
- def branch_added?
- Gitlab::Git.blank_ref?(@oldrev)
- end
-
- def branch_removed?
- Gitlab::Git.blank_ref?(@newrev)
+ @source_merge_requests ||= merge_requests_for(@push.branch_name)
end
end
end
diff --git a/app/services/merge_requests/reload_diffs_service.rb b/app/services/merge_requests/reload_diffs_service.rb
index b4d48fe92ad..c64b2e99b52 100644
--- a/app/services/merge_requests/reload_diffs_service.rb
+++ b/app/services/merge_requests/reload_diffs_service.rb
@@ -29,14 +29,13 @@ module MergeRequests
# rubocop: disable CodeReuse/ActiveRecord
def clear_cache(new_diff)
- # Executing the iteration we cache highlighted diffs for each diff file of
- # MergeRequestDiff.
- cacheable_collection(new_diff).write_cache
-
# Remove cache for all diffs on this MR. Do not use the association on the
# model, as that will interfere with other actions happening when
# reloading the diff.
- MergeRequestDiff.where(merge_request: merge_request).each do |merge_request_diff|
+ MergeRequestDiff
+ .where(merge_request: merge_request)
+ .preload(merge_request: :target_project)
+ .find_each do |merge_request_diff|
next if merge_request_diff == new_diff
cacheable_collection(merge_request_diff).clear_cache
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index b112edbce7f..aacaf10d09c 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -58,6 +58,8 @@ module MergeRequests
merge_request.mark_as_unchecked
end
+ handle_milestone_change(merge_request)
+
added_labels = merge_request.labels - old_labels
if added_labels.present?
notification_service.async.relabeled_merge_request(
@@ -105,6 +107,18 @@ module MergeRequests
private
+ def handle_milestone_change(merge_request)
+ return if skip_milestone_email
+
+ return unless merge_request.previous_changes.include?('milestone_id')
+
+ if merge_request.milestone.nil?
+ notification_service.async.removed_milestone_merge_request(merge_request, current_user)
+ else
+ notification_service.async.changed_milestone_merge_request(merge_request, merge_request.milestone, current_user)
+ end
+ end
+
def create_branch_change_note(issuable, branch_type, old_branch, new_branch)
SystemNoteService.change_branch(
issuable, issuable.project, current_user, branch_type,
diff --git a/app/services/milestones/destroy_service.rb b/app/services/milestones/destroy_service.rb
index 7cda802c120..87c7a282081 100644
--- a/app/services/milestones/destroy_service.rb
+++ b/app/services/milestones/destroy_service.rb
@@ -4,7 +4,7 @@ module Milestones
class DestroyService < Milestones::BaseService
def execute(milestone)
Milestone.transaction do
- update_params = { milestone: nil }
+ update_params = { milestone: nil, skip_milestone_email: true }
milestone.issues.each do |issue|
Issues::UpdateService.new(parent, current_user, update_params).execute(issue)
diff --git a/app/services/notes/base_service.rb b/app/services/notes/base_service.rb
new file mode 100644
index 00000000000..c1260837c12
--- /dev/null
+++ b/app/services/notes/base_service.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Notes
+ class BaseService < ::BaseService
+ def clear_noteable_diffs_cache(note)
+ if note.is_a?(DiffNote) &&
+ note.discussion_first_note? &&
+ note.position.unfolded_diff?(project.repository)
+ note.noteable.diffs.clear_cache
+ end
+ end
+ end
+end
diff --git a/app/services/notes/build_service.rb b/app/services/notes/build_service.rb
index df5fe65de3c..7b92fe6fe14 100644
--- a/app/services/notes/build_service.rb
+++ b/app/services/notes/build_service.rb
@@ -3,6 +3,7 @@
module Notes
class BuildService < ::BaseService
def execute
+ should_resolve = false
in_reply_to_discussion_id = params.delete(:in_reply_to_discussion_id)
if in_reply_to_discussion_id.present?
@@ -15,12 +16,17 @@ module Notes
end
params.merge!(discussion.reply_attributes)
+ should_resolve = discussion.resolved?
end
note = Note.new(params)
note.project = project
note.author = current_user
+ if should_resolve
+ note.resolve_without_save(current_user)
+ end
+
note
end
diff --git a/app/services/notes/create_service.rb b/app/services/notes/create_service.rb
index 049e6c5a871..e03789e3ca9 100644
--- a/app/services/notes/create_service.rb
+++ b/app/services/notes/create_service.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Notes
- class CreateService < ::BaseService
+ class CreateService < ::Notes::BaseService
def execute
merge_request_diff_head_sha = params.delete(:merge_request_diff_head_sha)
@@ -35,6 +35,7 @@ module Notes
if !only_commands && note.save
todo_service.new_note(note, current_user)
+ clear_noteable_diffs_cache(note)
end
if command_params.present?
diff --git a/app/services/notes/destroy_service.rb b/app/services/notes/destroy_service.rb
index 64e9accd97f..fa0c2c5c86b 100644
--- a/app/services/notes/destroy_service.rb
+++ b/app/services/notes/destroy_service.rb
@@ -1,11 +1,13 @@
# frozen_string_literal: true
module Notes
- class DestroyService < BaseService
+ class DestroyService < ::Notes::BaseService
def execute(note)
TodoService.new.destroy_target(note) do |note|
note.destroy
end
+
+ clear_noteable_diffs_cache(note)
end
end
end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 50fa373025b..5904bfbf88d 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -50,7 +50,7 @@ class NotificationService
# Always notify the user about gpg key added
#
- # This is a security email so it will be sent even if the user user disabled
+ # This is a security email so it will be sent even if the user disabled
# notifications
def new_gpg_key(gpg_key)
if gpg_key.user&.can?(:receive_notifications)
@@ -129,6 +129,14 @@ class NotificationService
relabeled_resource_email(issue, added_labels, current_user, :relabeled_issue_email)
end
+ def removed_milestone_issue(issue, current_user)
+ removed_milestone_resource_email(issue, current_user, :removed_milestone_issue_email)
+ end
+
+ def changed_milestone_issue(issue, new_milestone, current_user)
+ changed_milestone_resource_email(issue, new_milestone, current_user, :changed_milestone_issue_email)
+ end
+
# When create a merge request we should send an email to:
#
# * mr author
@@ -138,7 +146,6 @@ class NotificationService
# * users with custom level checked with "new merge request"
#
# In EE, approvers of the merge request are also included
- #
def new_merge_request(merge_request, current_user)
new_resource_email(merge_request, :new_merge_request_email)
end
@@ -208,6 +215,14 @@ class NotificationService
relabeled_resource_email(merge_request, added_labels, current_user, :relabeled_merge_request_email)
end
+ def removed_milestone_merge_request(merge_request, current_user)
+ removed_milestone_resource_email(merge_request, current_user, :removed_milestone_merge_request_email)
+ end
+
+ def changed_milestone_merge_request(merge_request, new_milestone, current_user)
+ changed_milestone_resource_email(merge_request, new_milestone, current_user, :changed_milestone_merge_request_email)
+ end
+
def close_mr(merge_request, current_user)
close_resource_email(merge_request, current_user, :closed_merge_request_email)
end
@@ -500,6 +515,30 @@ class NotificationService
end
end
+ def removed_milestone_resource_email(target, current_user, method)
+ recipients = NotificationRecipientService.build_recipients(
+ target,
+ current_user,
+ action: 'removed_milestone'
+ )
+
+ recipients.each do |recipient|
+ mailer.send(method, recipient.user.id, target.id, current_user.id).deliver_later
+ end
+ end
+
+ def changed_milestone_resource_email(target, milestone, current_user, method)
+ recipients = NotificationRecipientService.build_recipients(
+ target,
+ current_user,
+ action: 'changed_milestone'
+ )
+
+ recipients.each do |recipient|
+ mailer.send(method, recipient.user.id, target.id, milestone, current_user.id).deliver_later
+ end
+ end
+
def reopen_resource_email(target, current_user, method, status)
recipients = NotificationRecipientService.build_recipients(target, current_user, action: "reopen")
diff --git a/app/services/projects/after_rename_service.rb b/app/services/projects/after_rename_service.rb
new file mode 100644
index 00000000000..4131da44f5a
--- /dev/null
+++ b/app/services/projects/after_rename_service.rb
@@ -0,0 +1,135 @@
+# frozen_string_literal: true
+
+module Projects
+ # Service class for performing operations that should take place after a
+ # project has been renamed.
+ #
+ # Example usage:
+ #
+ # project = Project.find(42)
+ #
+ # project.update(...)
+ #
+ # Projects::AfterRenameService.new(project).execute
+ class AfterRenameService
+ attr_reader :project, :full_path_before, :full_path_after, :path_before
+
+ RenameFailedError = Class.new(StandardError)
+
+ # @param [Project] project The Project of the repository to rename.
+ def initialize(project)
+ @project = project
+
+ # The full path of the namespace + project, before the rename took place.
+ @full_path_before = project.full_path_was
+
+ # The full path of the namespace + project, after the rename took place.
+ @full_path_after = project.build_full_path
+
+ # The path of just the project, before the rename took place.
+ @path_before = project.path_was
+ end
+
+ def execute
+ first_ensure_no_registry_tags_are_present
+ expire_caches_before_rename
+ rename_or_migrate_repository!
+ send_move_instructions
+ execute_system_hooks
+ update_repository_configuration
+ rename_transferred_documents
+ log_completion
+ end
+
+ def first_ensure_no_registry_tags_are_present
+ return unless project.has_container_registry_tags?
+
+ raise RenameFailedError.new(
+ "Project #{full_path_before} cannot be renamed because images are " \
+ "present in its container registry"
+ )
+ end
+
+ def expire_caches_before_rename
+ project.expire_caches_before_rename(full_path_before)
+ end
+
+ def rename_or_migrate_repository!
+ success =
+ if migrate_to_hashed_storage?
+ ::Projects::HashedStorageMigrationService
+ .new(project, full_path_before)
+ .execute
+ else
+ project.storage.rename_repo
+ end
+
+ rename_failed! unless success
+ end
+
+ def send_move_instructions
+ return unless send_move_instructions?
+
+ project.send_move_instructions(full_path_before)
+ end
+
+ def execute_system_hooks
+ project.old_path_with_namespace = full_path_before
+ SystemHooksService.new.execute_hooks_for(project, :rename)
+ end
+
+ def update_repository_configuration
+ project.reload_repository!
+ project.write_repository_config
+ end
+
+ def rename_transferred_documents
+ if rename_uploads?
+ Gitlab::UploadsTransfer
+ .new
+ .rename_project(path_before, project_path, namespace_full_path)
+ end
+
+ Gitlab::PagesTransfer
+ .new
+ .rename_project(path_before, project_path, namespace_full_path)
+ end
+
+ def log_completion
+ Gitlab::AppLogger.info(
+ "Project #{project.id} has been renamed from " \
+ "#{full_path_before} to #{full_path_after}"
+ )
+ end
+
+ def migrate_to_hashed_storage?
+ Gitlab::CurrentSettings.hashed_storage_enabled? &&
+ project.storage_upgradable? &&
+ Feature.disabled?(:skip_hashed_storage_upgrade)
+ end
+
+ def send_move_instructions?
+ !project.import_started?
+ end
+
+ def rename_uploads?
+ !project.hashed_storage?(:attachments)
+ end
+
+ def project_path
+ project.path
+ end
+
+ def namespace_full_path
+ project.namespace.full_path
+ end
+
+ def rename_failed!
+ error = "Repository #{full_path_before} could not be renamed to #{full_path_after}"
+
+ Gitlab::AppLogger.error(error)
+
+ raise RenameFailedError.new(error)
+ end
+ end
+end
diff --git a/app/services/projects/autocomplete_service.rb b/app/services/projects/autocomplete_service.rb
index 5286b92ab6b..61f6402a810 100644
--- a/app/services/projects/autocomplete_service.rb
+++ b/app/services/projects/autocomplete_service.rb
@@ -2,6 +2,7 @@
module Projects
class AutocompleteService < BaseService
+ include LabelsAsHash
def issues
IssuesFinder.new(current_user, project_id: project.id, state: 'opened').execute.select([:iid, :title])
end
@@ -22,34 +23,18 @@ module Projects
MergeRequestsFinder.new(current_user, project_id: project.id, state: 'opened').execute.select([:iid, :title])
end
- def labels_as_hash(target = nil)
- available_labels = LabelsFinder.new(
- current_user,
- project_id: project.id,
- include_ancestor_groups: true
- ).execute
-
- label_hashes = available_labels.as_json(only: [:title, :color])
-
- if target&.respond_to?(:labels)
- already_set_labels = available_labels & target.labels
- if already_set_labels.present?
- titles = already_set_labels.map(&:title)
- label_hashes.each do |hash|
- if titles.include?(hash['title'])
- hash[:set] = true
- end
- end
- end
- end
-
- label_hashes
- end
-
def commands(noteable, type)
return [] unless noteable
QuickActions::InterpretService.new(project, current_user).available_commands(noteable)
end
+
+ def snippets
+ SnippetsFinder.new(current_user, project: project).execute.select([:id, :title])
+ end
+
+ def labels_as_hash(target)
+ super(target, project_id: project.id, include_ancestor_groups: true)
+ end
end
end
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index 0e6a7e8da54..9e77a3237e3 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -9,12 +9,12 @@ module Projects
end
def execute
- if @params[:template_name]&.present?
+ if @params[:template_name].present?
return ::Projects::CreateFromTemplateService.new(current_user, params).execute
end
- forked_from_project_id = params.delete(:forked_from_project_id)
import_data = params.delete(:import_data)
+ relations_block = params.delete(:relations_block)
@project = Project.new(params)
@@ -24,11 +24,6 @@ module Projects
return @project
end
- unless allowed_fork?(forked_from_project_id)
- @project.errors.add(:forked_from_project_id, 'is forbidden')
- return @project
- end
-
set_project_name_from_path
# get namespace id
@@ -47,6 +42,7 @@ module Projects
@project.namespace_id = current_user.namespace_id
end
+ relations_block&.call(@project)
yield(@project) if block_given?
# If the block added errors, don't try to save the project
@@ -54,10 +50,6 @@ module Projects
@project.creator = current_user
- if forked_from_project_id
- @project.build_forked_project_link(forked_from_project_id: forked_from_project_id)
- end
-
save_project_and_import_data(import_data)
after_create_actions if @project.persisted?
@@ -80,15 +72,6 @@ module Projects
end
# rubocop: disable CodeReuse/ActiveRecord
- def allowed_fork?(source_project_id)
- return true if source_project_id.nil?
-
- source_project = Project.find_by(id: source_project_id)
- current_user.can?(:fork_project, source_project)
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- # rubocop: disable CodeReuse/ActiveRecord
def allowed_namespace?(user, namespace_id)
namespace = Namespace.find_by(id: namespace_id)
current_user.can?(:create_projects, namespace)
@@ -103,6 +86,8 @@ module Projects
@project.create_wiki unless skip_wiki?
end
+ @project.track_project_repository
+
event_service.create_project(@project, current_user)
system_hook_service.execute_hooks_for(@project, :create)
@@ -165,7 +150,7 @@ module Projects
Rails.logger.error(log_message)
if @project
- @project.mark_import_as_failed(message) if @project.persisted? && @project.import?
+ @project.import_state.mark_as_failed(message) if @project.persisted? && @project.import?
end
@project
@@ -198,7 +183,7 @@ module Projects
def import_schedule
if @project.errors.empty?
- @project.import_schedule if @project.import? && !@project.bare_repository_import?
+ @project.import_state.schedule if @project.import? && !@project.bare_repository_import?
else
fail(error: @project.errors.full_messages.join(', '))
end
diff --git a/app/services/projects/disable_deploy_key_service.rb b/app/services/projects/disable_deploy_key_service.rb
new file mode 100644
index 00000000000..e483c0708c4
--- /dev/null
+++ b/app/services/projects/disable_deploy_key_service.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Projects
+ class DisableDeployKeyService < BaseService
+ def execute
+ # rubocop: disable CodeReuse/ActiveRecord
+ deploy_key_project = project.deploy_keys_projects.find_by(deploy_key_id: params[:id])
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ deploy_key_project&.destroy!
+ end
+ end
+end
diff --git a/app/services/projects/enable_deploy_key_service.rb b/app/services/projects/enable_deploy_key_service.rb
index 102088e9557..38219cacee9 100644
--- a/app/services/projects/enable_deploy_key_service.rb
+++ b/app/services/projects/enable_deploy_key_service.rb
@@ -2,9 +2,10 @@
module Projects
class EnableDeployKeyService < BaseService
- # rubocop: disable CodeReuse/ActiveRecord
def execute
- key = accessible_keys.find_by(id: params[:key_id] || params[:id])
+ key_id = params[:key_id] || params[:id]
+ key = find_accessible_key(key_id)
+
return unless key
unless project.deploy_keys.include?(key)
@@ -13,12 +14,15 @@ module Projects
key
end
- # rubocop: enable CodeReuse/ActiveRecord
private
- def accessible_keys
- current_user.accessible_deploy_keys
+ def find_accessible_key(key_id)
+ if current_user.admin?
+ DeployKey.find_by_id(key_id)
+ else
+ current_user.accessible_deploy_keys.find_by_id(key_id)
+ end
end
end
end
diff --git a/app/services/projects/fork_service.rb b/app/services/projects/fork_service.rb
index cbbb88a9410..8dc0e044875 100644
--- a/app/services/projects/fork_service.rb
+++ b/app/services/projects/fork_service.rb
@@ -12,31 +12,42 @@ module Projects
private
+ def allowed_fork?
+ current_user.can?(:fork_project, @project)
+ end
+
def link_existing_project(fork_to_project)
return if fork_to_project.forked?
- link_fork_network(fork_to_project)
+ build_fork_network_member(fork_to_project)
- # A forked project stores its LFS objects in the `forked_from_project`.
- # So the LFS objects become inaccessible, and therefore delete them from
- # the database so they'll get cleaned up.
- #
- # TODO: refactor this to get the correct lfs objects when implementing
- # https://gitlab.com/gitlab-org/gitlab-ce/issues/39769
- fork_to_project.lfs_objects_projects.delete_all
+ if link_fork_network(fork_to_project)
+ # A forked project stores its LFS objects in the `forked_from_project`.
+ # So the LFS objects become inaccessible, and therefore delete them from
+ # the database so they'll get cleaned up.
+ #
+ # TODO: refactor this to get the correct lfs objects when implementing
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/39769
+ fork_to_project.lfs_objects_projects.delete_all
- fork_to_project
+ fork_to_project
+ end
end
def fork_new_project
new_params = {
- forked_from_project_id: @project.id,
visibility_level: allowed_visibility_level,
description: @project.description,
name: @project.name,
path: @project.path,
shared_runners_enabled: @project.shared_runners_enabled,
- namespace_id: target_namespace.id
+ namespace_id: target_namespace.id,
+ fork_network: fork_network,
+ # We need to assign the fork network membership after the project has
+ # been instantiated to avoid ActiveRecord trying to create it when
+ # initializing the project, as that would cause a foreign key constraint
+ # exception.
+ relations_block: -> (project) { build_fork_network_member(project) }
}
if @project.avatar.present? && @project.avatar.image?
@@ -46,38 +57,35 @@ module Projects
new_project = CreateService.new(current_user, new_params).execute
return new_project unless new_project.persisted?
+ # Set the forked_from_project relation after saving to avoid having to
+ # reload the project to reset the association information and cause an
+ # extra query.
+ new_project.forked_from_project = @project
+
builds_access_level = @project.project_feature.builds_access_level
new_project.project_feature.update(builds_access_level: builds_access_level)
- link_fork_network(new_project)
-
new_project
end
def fork_network
- if @project.fork_network
- @project.fork_network
- elsif forked_from_project = @project.forked_from_project
- # TODO: remove this case when all background migrations have completed
- # this only happens when a project had a `forked_project_link` that was
- # not migrated to the `fork_network` relation
- forked_from_project.fork_network || forked_from_project.create_root_of_fork_network
+ @fork_network ||= @project.fork_network || @project.build_root_of_fork_network
+ end
+
+ def build_fork_network_member(fork_to_project)
+ if allowed_fork?
+ fork_to_project.build_fork_network_member(forked_from_project: @project,
+ fork_network: fork_network)
else
- @project.create_root_of_fork_network
+ fork_to_project.errors.add(:forked_from_project_id, 'is forbidden')
end
end
def link_fork_network(fork_to_project)
- fork_network.fork_network_members.create(project: fork_to_project,
- forked_from_project: @project)
-
- # TODO: remove this when ForkedProjectLink model is removed
- unless fork_to_project.forked_project_link
- fork_to_project.create_forked_project_link(forked_to_project: fork_to_project,
- forked_from_project: @project)
- end
+ return if fork_to_project.errors.any?
- refresh_forks_count
+ fork_to_project.fork_network_member.save &&
+ refresh_forks_count
end
def refresh_forks_count
diff --git a/app/services/projects/forks_count_service.rb b/app/services/projects/forks_count_service.rb
index 00e73148358..ca85e2dc281 100644
--- a/app/services/projects/forks_count_service.rb
+++ b/app/services/projects/forks_count_service.rb
@@ -9,10 +9,7 @@ module Projects
# rubocop: disable CodeReuse/ActiveRecord
def self.query(project_ids)
- # We can't directly change ForkedProjectLink to ForkNetworkMember here
- # Nowadays, when a call using v3 to projects/:id/fork is made,
- # the relationship to ForkNetworkMember is not updated
- ForkedProjectLink.where(forked_from_project: project_ids)
+ ForkNetworkMember.where(forked_from_project: project_ids)
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/services/projects/hashed_storage/migrate_repository_service.rb b/app/services/projects/hashed_storage/migrate_repository_service.rb
index 4462d504071..f3e026ba38c 100644
--- a/app/services/projects/hashed_storage/migrate_repository_service.rb
+++ b/app/services/projects/hashed_storage/migrate_repository_service.rb
@@ -30,6 +30,7 @@ module Projects
if result
project.write_repository_config
+ project.track_project_repository
else
rollback_folder_move
project.storage_version = nil
diff --git a/app/services/projects/move_forks_service.rb b/app/services/projects/move_forks_service.rb
index 2948555a17c..33f0bab12c9 100644
--- a/app/services/projects/move_forks_service.rb
+++ b/app/services/projects/move_forks_service.rb
@@ -6,7 +6,6 @@ module Projects
return unless super && source_project.fork_network
Project.transaction(requires_new: true) do
- move_forked_project_links
move_fork_network_members
update_root_project
refresh_forks_count
@@ -18,18 +17,6 @@ module Projects
private
# rubocop: disable CodeReuse/ActiveRecord
- def move_forked_project_links
- # Update ancestor
- ForkedProjectLink.where(forked_to_project: source_project)
- .update_all(forked_to_project_id: @project.id)
-
- # Update the descendants
- ForkedProjectLink.where(forked_from_project: source_project)
- .update_all(forked_from_project_id: @project.id)
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- # rubocop: disable CodeReuse/ActiveRecord
def move_fork_network_members
ForkNetworkMember.where(project: source_project).update_all(project_id: @project.id)
ForkNetworkMember.where(forked_from_project: source_project).update_all(forked_from_project_id: @project.id)
diff --git a/app/services/projects/move_project_authorizations_service.rb b/app/services/projects/move_project_authorizations_service.rb
index 2060a263751..2985ba89014 100644
--- a/app/services/projects/move_project_authorizations_service.rb
+++ b/app/services/projects/move_project_authorizations_service.rb
@@ -3,7 +3,7 @@
# NOTE: This service cannot be used directly because it is part of a
# a bigger process. Instead, use the service MoveAccessService which moves
# project memberships, project group links, authorizations and refreshes
-# the authorizations if neccessary
+# the authorizations if necessary
module Projects
class MoveProjectAuthorizationsService < BaseMoveRelationsService
def execute(source_project, remove_remaining_elements: true)
diff --git a/app/services/projects/move_project_group_links_service.rb b/app/services/projects/move_project_group_links_service.rb
index fb395ecb9a1..36afcd0c503 100644
--- a/app/services/projects/move_project_group_links_service.rb
+++ b/app/services/projects/move_project_group_links_service.rb
@@ -3,7 +3,7 @@
# NOTE: This service cannot be used directly because it is part of a
# a bigger process. Instead, use the service MoveAccessService which moves
# project memberships, project group links, authorizations and refreshes
-# the authorizations if neccessary
+# the authorizations if necessary
module Projects
class MoveProjectGroupLinksService < BaseMoveRelationsService
def execute(source_project, remove_remaining_elements: true)
diff --git a/app/services/projects/move_project_members_service.rb b/app/services/projects/move_project_members_service.rb
index f28f44adc03..faf389241d2 100644
--- a/app/services/projects/move_project_members_service.rb
+++ b/app/services/projects/move_project_members_service.rb
@@ -3,7 +3,7 @@
# NOTE: This service cannot be used directly because it is part of a
# a bigger process. Instead, use the service MoveAccessService which moves
# project memberships, project group links, authorizations and refreshes
-# the authorizations if neccessary
+# the authorizations if necessary
module Projects
class MoveProjectMembersService < BaseMoveRelationsService
def execute(source_project, remove_remaining_elements: true)
diff --git a/app/services/projects/unlink_fork_service.rb b/app/services/projects/unlink_fork_service.rb
index a8b7c7f136a..1b8a920268f 100644
--- a/app/services/projects/unlink_fork_service.rb
+++ b/app/services/projects/unlink_fork_service.rb
@@ -25,7 +25,6 @@ module Projects
end
@project.fork_network_member.destroy
- @project.forked_project_link.destroy
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/projects/update_pages_configuration_service.rb b/app/services/projects/update_pages_configuration_service.rb
index efbd4c7b323..abf40b3ad7a 100644
--- a/app/services/projects/update_pages_configuration_service.rb
+++ b/app/services/projects/update_pages_configuration_service.rb
@@ -21,7 +21,9 @@ module Projects
def pages_config
{
domains: pages_domains_config,
- https_only: project.pages_https_only?
+ https_only: project.pages_https_only?,
+ id: project.project_id,
+ access_control: !project.public_pages?
}
end
@@ -31,7 +33,9 @@ module Projects
domain: domain.domain,
certificate: domain.certificate,
key: domain.key,
- https_only: project.pages_https_only? && domain.https?
+ https_only: project.pages_https_only? && domain.https?,
+ id: project.project_id,
+ access_control: !project.public_pages?
}
end
end
diff --git a/app/services/projects/update_remote_mirror_service.rb b/app/services/projects/update_remote_mirror_service.rb
index 85b9eb02803..1244a0f72a7 100644
--- a/app/services/projects/update_remote_mirror_service.rb
+++ b/app/services/projects/update_remote_mirror_service.rb
@@ -11,8 +11,7 @@ module Projects
begin
remote_mirror.ensure_remote!
- repository.fetch_remote(remote_mirror.remote_name, no_tags: true)
- project.update_root_ref(remote_mirror.remote_name)
+ repository.fetch_remote(remote_mirror.remote_name, ssh_auth: remote_mirror, no_tags: true)
opts = {}
if remote_mirror.only_protected_branches?
diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb
index d6d9bacf232..93e48fc0199 100644
--- a/app/services/projects/update_service.rb
+++ b/app/services/projects/update_service.rb
@@ -67,12 +67,16 @@ module Projects
end
if project.previous_changes.include?('path')
- project.rename_repo
+ AfterRenameService.new(project).execute
else
system_hook_service.execute_hooks_for(project, :update)
end
- update_pages_config if changing_pages_https_only?
+ update_pages_config if changing_pages_related_config?
+ end
+
+ def changing_pages_related_config?
+ changing_pages_https_only? || changing_pages_access_level?
end
def update_failed!
@@ -102,6 +106,10 @@ module Projects
params.dig(:project_feature_attributes, :wiki_access_level).to_i > ProjectFeature::DISABLED
end
+ def changing_pages_access_level?
+ params.dig(:project_feature_attributes, :pages_access_level)
+ end
+
def ensure_wiki_exists
ProjectWiki.new(project, project.owner).wiki
rescue ProjectWiki::CouldNotCreateWikiError
diff --git a/app/services/quick_actions/interpret_service.rb b/app/services/quick_actions/interpret_service.rb
index 02d68c3add3..d248b10f41e 100644
--- a/app/services/quick_actions/interpret_service.rb
+++ b/app/services/quick_actions/interpret_service.rb
@@ -23,13 +23,13 @@ module QuickActions
# Takes a text and interprets the commands that are extracted from it.
# Returns the content without commands, and hash of changes to be applied to a record.
- def execute(content, issuable)
+ def execute(content, issuable, only: nil)
return [content, {}] unless current_user.can?(:use_quick_actions)
@issuable = issuable
@updates = {}
- content, commands = extractor.extract_commands(content)
+ content, commands = extractor.extract_commands(content, only: only)
extract_updates(commands)
[content, @updates]
@@ -126,18 +126,16 @@ module QuickActions
parse_params do |assignee_param|
extract_users(assignee_param)
end
- # rubocop: disable CodeReuse/ActiveRecord
command :assign do |users|
next if users.empty?
- @updates[:assignee_ids] =
- if issuable.allows_multiple_assignees?
- issuable.assignees.pluck(:id) + users.map(&:id)
- else
- [users.first.id]
- end
+ if issuable.allows_multiple_assignees?
+ @updates[:assignee_ids] ||= issuable.assignees.map(&:id)
+ @updates[:assignee_ids] += users.map(&:id)
+ else
+ @updates[:assignee_ids] = [users.first.id]
+ end
end
- # rubocop: enable CodeReuse/ActiveRecord
desc do
if issuable.allows_multiple_assignees?
@@ -164,16 +162,14 @@ module QuickActions
# When multiple users are assigned, all will be unassigned if multiple assignees are no longer allowed
extract_users(unassign_param) if issuable.allows_multiple_assignees?
end
- # rubocop: disable CodeReuse/ActiveRecord
command :unassign do |users = nil|
- @updates[:assignee_ids] =
- if users&.any?
- issuable.assignees.pluck(:id) - users.map(&:id)
- else
- []
- end
+ if issuable.allows_multiple_assignees? && users&.any?
+ @updates[:assignee_ids] ||= issuable.assignees.map(&:id)
+ @updates[:assignee_ids] -= users.map(&:id)
+ else
+ @updates[:assignee_ids] = []
+ end
end
- # rubocop: enable CodeReuse/ActiveRecord
desc 'Set milestone'
explanation do |milestone|
@@ -214,9 +210,14 @@ module QuickActions
end
params '~label1 ~"label 2"'
condition do
- available_labels = LabelsFinder.new(current_user, project_id: project.id, include_ancestor_groups: true).execute
+ if project
+ available_labels = LabelsFinder
+ .new(current_user, project_id: project.id, include_ancestor_groups: true)
+ .execute
+ end
- current_user.can?(:"admin_#{issuable.to_ability_name}", project) &&
+ project &&
+ current_user.can?(:"admin_#{issuable.to_ability_name}", project) &&
available_labels.any?
end
command :label do |labels_param|
@@ -290,7 +291,7 @@ module QuickActions
end
params '#issue | !merge_request'
condition do
- issuable.persisted? &&
+ [MergeRequest, Issue].include?(issuable.class) &&
current_user.can?(:"update_#{issuable.to_ability_name}", issuable)
end
parse_params do |issuable_param|
@@ -432,14 +433,14 @@ module QuickActions
end
end
- desc 'Add or substract spent time'
+ desc 'Add or subtract spent time'
explanation do |time_spent, time_spent_date|
if time_spent
if time_spent > 0
verb = 'Adds'
value = time_spent
else
- verb = 'Substracts'
+ verb = 'Subtracts'
value = -time_spent
end
@@ -448,7 +449,8 @@ module QuickActions
end
params '<time(1h30m | -1h30m)> <date(YYYY-MM-DD)>'
condition do
- current_user.can?(:"admin_#{issuable.to_ability_name}", issuable)
+ issuable.is_a?(TimeTrackable) &&
+ current_user.can?(:"admin_#{issuable.to_ability_name}", issuable)
end
parse_params do |raw_time_date|
Gitlab::QuickActions::SpendTimeAndDateSeparator.new(raw_time_date).execute
@@ -498,7 +500,7 @@ module QuickActions
desc "Lock the discussion"
explanation "Locks the discussion"
condition do
- issuable.is_a?(Issuable) &&
+ [MergeRequest, Issue].include?(issuable.class) &&
issuable.persisted? &&
!issuable.discussion_locked? &&
current_user.can?(:"admin_#{issuable.to_ability_name}", issuable)
@@ -510,7 +512,7 @@ module QuickActions
desc "Unlock the discussion"
explanation "Unlocks the discussion"
condition do
- issuable.is_a?(Issuable) &&
+ [MergeRequest, Issue].include?(issuable.class) &&
issuable.persisted? &&
issuable.discussion_locked? &&
current_user.can?(:"admin_#{issuable.to_ability_name}", issuable)
@@ -633,6 +635,22 @@ module QuickActions
@updates[:tag_message] = message
end
+ desc 'Create a merge request.'
+ explanation do |branch_name = nil|
+ branch_text = branch_name ? "branch '#{branch_name}'" : 'a branch'
+ "Creates #{branch_text} and a merge request to resolve this issue"
+ end
+ params "<branch name>"
+ condition do
+ issuable.is_a?(Issue) && current_user.can?(:create_merge_request_in, project) && current_user.can?(:push_code, project)
+ end
+ command :create_merge_request do |branch_name = nil|
+ @updates[:create_merge_request] = {
+ branch_name: branch_name,
+ issue_iid: issuable.iid
+ }
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
def extract_users(params)
return [] if params.nil?
@@ -641,7 +659,7 @@ module QuickActions
if users.empty?
users =
- if params == 'me'
+ if params.strip == 'me'
[current_user]
else
User.where(username: params.split(' ').map(&:strip))
diff --git a/app/services/resource_events/merge_into_notes_service.rb b/app/services/resource_events/merge_into_notes_service.rb
index 596c0105ea0..7504773a002 100644
--- a/app/services/resource_events/merge_into_notes_service.rb
+++ b/app/services/resource_events/merge_into_notes_service.rb
@@ -34,7 +34,7 @@ module ResourceEvents
def label_events_by_discussion_id
return [] unless resource.respond_to?(:resource_label_events)
- events = resource.resource_label_events.includes(:label, :user)
+ events = resource.resource_label_events.includes(:label, user: :status)
events = since_fetch_at(events)
events.group_by { |event| event.discussion_id }
diff --git a/app/services/search/group_service.rb b/app/services/search/group_service.rb
index 00372887985..34803d005e3 100644
--- a/app/services/search/group_service.rb
+++ b/app/services/search/group_service.rb
@@ -11,13 +11,11 @@ module Search
@group = group
end
- # rubocop: disable CodeReuse/ActiveRecord
def projects
return Project.none unless group
return @projects if defined? @projects
@projects = super.inside_path(group.full_path)
end
- # rubocop: enable CodeReuse/ActiveRecord
end
end
diff --git a/app/services/submodules/update_service.rb b/app/services/submodules/update_service.rb
new file mode 100644
index 00000000000..a6011a920bd
--- /dev/null
+++ b/app/services/submodules/update_service.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Submodules
+ class UpdateService < Commits::CreateService
+ include Gitlab::Utils::StrongMemoize
+
+ def initialize(*args)
+ super
+
+ @start_branch = @branch_name
+ @commit_sha = params[:commit_sha].presence
+ @submodule = params[:submodule].presence
+ @commit_message = params[:commit_message].presence || "Update submodule #{@submodule} with oid #{@commit_sha}"
+ end
+
+ def validate!
+ super
+
+ raise ValidationError, 'The repository is empty' if repository.empty?
+ end
+
+ def execute
+ super
+ rescue StandardError => e
+ error(e.message)
+ end
+
+ def create_commit!
+ repository.update_submodule(current_user,
+ @submodule,
+ @commit_sha,
+ message: @commit_message,
+ branch: @branch_name)
+ rescue ArgumentError, TypeError
+ raise ValidationError, 'Invalid parameters'
+ end
+ end
+end
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index 575678da1fa..ec6c306227b 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -211,7 +211,7 @@ module SystemNoteService
# "closed via bc17db76"
#
# Returns the created Note object
- def change_status(noteable, project, author, status, source)
+ def change_status(noteable, project, author, status, source = nil)
body = status.dup
body << " via #{source.gfm_reference(project)}" if source
@@ -407,11 +407,17 @@ module SystemNoteService
def new_issue_branch(issue, project, author, branch)
link = url_helpers.project_compare_url(project, from: project.default_branch, to: branch)
- body = "created branch [`#{branch}`](#{link})"
+ body = "created branch [`#{branch}`](#{link}) to address this issue"
create_note(NoteSummary.new(issue, project, author, body, action: 'branch'))
end
+ def new_merge_request(issue, project, author, merge_request)
+ body = "created merge request #{merge_request.to_reference} to address this issue"
+
+ create_note(NoteSummary.new(issue, project, author, body, action: 'merge'))
+ end
+
# Called when a Mentionable references a Noteable
#
# noteable - Noteable object being referenced
diff --git a/app/services/todo_service.rb b/app/services/todo_service.rb
index 4fe6c1ec986..f357dc37fe7 100644
--- a/app/services/todo_service.rb
+++ b/app/services/todo_service.rb
@@ -41,15 +41,13 @@ class TodoService
# collects the todo users before the todos themselves are deleted, then
# updates the todo counts for those users.
#
- # rubocop: disable CodeReuse/ActiveRecord
def destroy_target(target)
- todo_users = User.where(id: target.todos.pending.select(:user_id)).to_a
+ todo_users = UsersWithPendingTodosFinder.new(target).execute.to_a
yield target
todo_users.each(&:update_todos_count_cache)
end
- # rubocop: enable CodeReuse/ActiveRecord
# When we reassign an issue we should:
#
@@ -200,30 +198,23 @@ class TodoService
create_todos(current_user, attributes)
end
- # rubocop: disable CodeReuse/ActiveRecord
def todo_exist?(issuable, current_user)
- TodosFinder.new(current_user).execute.exists?(target: issuable)
+ TodosFinder.new(current_user).any_for_target?(issuable)
end
- # rubocop: enable CodeReuse/ActiveRecord
private
- # rubocop: disable CodeReuse/ActiveRecord
def todos_by_ids(ids, current_user)
- current_user.todos.where(id: Array(ids))
+ current_user.todos_limited_to(Array(ids))
end
- # rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def update_todos_state(todos, current_user, state)
- # Only update those that are not really on that state
- todos = todos.where.not(state: state)
- todos_ids = todos.pluck(:id)
- todos.unscope(:order).update_all(state: state)
+ todos_ids = todos.update_state(state)
+
current_user.update_todos_count_cache
+
todos_ids
end
- # rubocop: enable CodeReuse/ActiveRecord
def create_todos(users, attributes)
Array(users).map do |user|
@@ -348,10 +339,7 @@ class TodoService
end
end
- # rubocop: disable CodeReuse/ActiveRecord
def pending_todos(user, criteria = {})
- valid_keys = [:project_id, :target_id, :target_type, :commit_id]
- user.todos.pending.where(criteria.slice(*valid_keys))
+ PendingTodosFinder.new(user, criteria).execute
end
- # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/services/todos/destroy/entity_leave_service.rb b/app/services/todos/destroy/entity_leave_service.rb
index e8d1bcdd142..ebfb20132d0 100644
--- a/app/services/todos/destroy/entity_leave_service.rb
+++ b/app/services/todos/destroy/entity_leave_service.rb
@@ -45,7 +45,7 @@ module Todos
# rubocop: disable CodeReuse/ActiveRecord
def remove_confidential_issue_todos
Todo.where(
- target_id: confidential_issues.select(:id), target_type: Issue, user_id: user.id
+ target_id: confidential_issues.select(:id), target_type: Issue.name, user_id: user.id
).delete_all
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/todos/destroy/private_features_service.rb b/app/services/todos/destroy/private_features_service.rb
index a8c3fe0ef5a..bd49519d694 100644
--- a/app/services/todos/destroy/private_features_service.rb
+++ b/app/services/todos/destroy/private_features_service.rb
@@ -14,9 +14,9 @@ module Todos
def execute
ProjectFeature.where(project_id: project_ids).each do |project_features|
target_types = []
- target_types << Issue if private?(project_features.issues_access_level)
- target_types << MergeRequest if private?(project_features.merge_requests_access_level)
- target_types << Commit if private?(project_features.repository_access_level)
+ target_types << Issue.name if private?(project_features.issues_access_level)
+ target_types << MergeRequest.name if private?(project_features.merge_requests_access_level)
+ target_types << Commit.name if private?(project_features.repository_access_level)
next if target_types.empty?
diff --git a/app/services/update_deployment_service.rb b/app/services/update_deployment_service.rb
new file mode 100644
index 00000000000..aa7fcca1e2a
--- /dev/null
+++ b/app/services/update_deployment_service.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+class UpdateDeploymentService
+ attr_reader :deployment
+ attr_reader :deployable
+
+ delegate :environment, to: :deployment
+ delegate :variables, to: :deployable
+
+ def initialize(deployment)
+ @deployment = deployment
+ @deployable = deployment.deployable
+ end
+
+ def execute
+ deployment.create_ref
+ deployment.invalidate_cache
+
+ ActiveRecord::Base.transaction do
+ environment.external_url = expanded_environment_url if
+ expanded_environment_url
+
+ environment.fire_state_event(action)
+
+ break unless environment.save
+ break if environment.stopped?
+
+ deployment.tap(&:update_merge_request_metrics!)
+ end
+ end
+
+ private
+
+ def environment_options
+ @environment_options ||= deployable.options&.dig(:environment) || {}
+ end
+
+ def expanded_environment_url
+ return @expanded_environment_url if defined?(@expanded_environment_url)
+ return unless environment_url
+
+ @expanded_environment_url =
+ ExpandVariables.expand(environment_url, variables)
+ end
+
+ def environment_url
+ environment_options[:url]
+ end
+
+ def action
+ environment_options[:action] || 'start'
+ end
+end
diff --git a/app/services/users/build_service.rb b/app/services/users/build_service.rb
index 9417c63c43a..3f503f3da28 100644
--- a/app/services/users/build_service.rb
+++ b/app/services/users/build_service.rb
@@ -28,7 +28,7 @@ module Users
identity_attrs = params.slice(:extern_uid, :provider)
- if identity_attrs.any?
+ unless identity_attrs.empty?
user.identities.build(identity_attrs)
end
@@ -55,7 +55,6 @@ module Users
:force_random_password,
:hide_no_password,
:hide_no_ssh_key,
- :key_id,
:linkedin,
:name,
:password,
@@ -69,7 +68,10 @@ module Users
:twitter,
:username,
:website_url,
- :private_profile
+ :private_profile,
+ :organization,
+ :location,
+ :public_email
]
end
@@ -93,10 +95,6 @@ module Users
if params[:reset_password]
user_params.merge!(force_random_password: true, password_expires_at: nil)
end
-
- if user_default_internal_regex_enabled? && !user_params.key?(:external)
- user_params[:external] = user_external?
- end
else
allowed_signup_params = signup_params
allowed_signup_params << :skip_confirmation if skip_authorization
@@ -107,6 +105,10 @@ module Users
end
end
+ if user_default_internal_regex_enabled? && !user_params.key?(:external)
+ user_params[:external] = user_external?
+ end
+
user_params
end
diff --git a/app/services/web_hook_service.rb b/app/services/web_hook_service.rb
index 34724e0250d..1fee8bfcd31 100644
--- a/app/services/web_hook_service.rb
+++ b/app/services/web_hook_service.rb
@@ -22,7 +22,7 @@ class WebHookService
end
def execute
- start_time = Time.now
+ start_time = Gitlab::Metrics::System.monotonic_time
response = if parsed_url.userinfo.blank?
make_request(hook.url)
@@ -35,7 +35,7 @@ class WebHookService
url: hook.url,
request_data: data,
response: response,
- execution_duration: Time.now - start_time
+ execution_duration: Gitlab::Metrics::System.monotonic_time - start_time
)
{
@@ -43,13 +43,13 @@ class WebHookService
http_status: response.code,
message: response.to_s
}
- rescue SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Net::OpenTimeout, Net::ReadTimeout, Gitlab::HTTP::BlockedUrlError => e
+ rescue SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Net::OpenTimeout, Net::ReadTimeout, Gitlab::HTTP::BlockedUrlError, Gitlab::HTTP::RedirectionTooDeep => e
log_execution(
trigger: hook_name,
url: hook.url,
request_data: data,
response: InternalErrorResponse.new,
- execution_duration: Time.now - start_time,
+ execution_duration: Gitlab::Metrics::System.monotonic_time - start_time,
error_message: e.to_s
)
diff --git a/app/uploaders/file_uploader.rb b/app/uploaders/file_uploader.rb
index ffc1e5f75ca..e90599f2505 100644
--- a/app/uploaders/file_uploader.rb
+++ b/app/uploaders/file_uploader.rb
@@ -149,9 +149,9 @@ class FileUploader < GitlabUploader
# return a new uploader with a file copy on another project
def self.copy_to(uploader, to_project)
- moved = uploader.dup.tap do |u|
- u.model = to_project
- end
+ moved = self.new(to_project)
+ moved.object_store = uploader.object_store
+ moved.filename = uploader.filename
moved.copy_file(uploader.file)
moved
diff --git a/app/uploaders/gitlab_uploader.rb b/app/uploaders/gitlab_uploader.rb
index 719bd6ef418..cefcd3d3f5a 100644
--- a/app/uploaders/gitlab_uploader.rb
+++ b/app/uploaders/gitlab_uploader.rb
@@ -63,6 +63,12 @@ class GitlabUploader < CarrierWave::Uploader::Base
super || file&.filename
end
+ def relative_path
+ return path if pathname.relative?
+
+ pathname.relative_path_from(Pathname.new(root))
+ end
+
def model_valid?
!!model
end
@@ -115,4 +121,8 @@ class GitlabUploader < CarrierWave::Uploader::Base
# the cache directory.
File.join(work_dir, cache_id, version_name.to_s, for_file)
end
+
+ def pathname
+ @pathname ||= Pathname.new(path)
+ end
end
diff --git a/app/uploaders/job_artifact_uploader.rb b/app/uploaders/job_artifact_uploader.rb
index 557b13a8bd6..400f0b3dcc6 100644
--- a/app/uploaders/job_artifact_uploader.rb
+++ b/app/uploaders/job_artifact_uploader.rb
@@ -9,6 +9,8 @@ class JobArtifactUploader < GitlabUploader
storage_options Gitlab.config.artifacts
+ alias_method :upload, :model
+
def cached_size
return model.size if model.size.present? && !model.file_changed?
diff --git a/app/uploaders/legacy_artifact_uploader.rb b/app/uploaders/legacy_artifact_uploader.rb
index b4d0d752016..a9afc104ed1 100644
--- a/app/uploaders/legacy_artifact_uploader.rb
+++ b/app/uploaders/legacy_artifact_uploader.rb
@@ -8,6 +8,8 @@ class LegacyArtifactUploader < GitlabUploader
storage_options Gitlab.config.artifacts
+ alias_method :upload, :model
+
def store_dir
dynamic_segment
end
diff --git a/app/uploaders/lfs_object_uploader.rb b/app/uploaders/lfs_object_uploader.rb
index f3d32e6b39d..0a966f3d44f 100644
--- a/app/uploaders/lfs_object_uploader.rb
+++ b/app/uploaders/lfs_object_uploader.rb
@@ -6,6 +6,8 @@ class LfsObjectUploader < GitlabUploader
storage_options Gitlab.config.lfs
+ alias_method :upload, :model
+
def filename
model.oid[4..-1]
end
diff --git a/app/views/abuse_reports/new.html.haml b/app/views/abuse_reports/new.html.haml
index 391115a67b5..92ae40512c5 100644
--- a/app/views/abuse_reports/new.html.haml
+++ b/app/views/abuse_reports/new.html.haml
@@ -1,6 +1,10 @@
-- page_title "Report abuse"
-%h3.page-title Report abuse
-%p Please use this form to report users who create spam issues, comments or behave inappropriately.
+- page_title _("Report abuse to GitLab")
+%h3.page-title
+ = _("Report abuse to GitLab")
+%p
+ = _("Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately.")
+%p
+ = _("A member of GitLab's abuse team will review your report as soon as possible.")
%hr
= form_for @abuse_report, html: { class: 'js-quick-submit js-requires-input'} do |f|
= form_errors(@abuse_report)
@@ -16,7 +20,7 @@
.col-sm-10
= f.text_area :message, class: "form-control", rows: 2, required: true, value: sanitize(@ref_url)
.form-text.text-muted
- Explain the problem with this user. If appropriate, provide a link to the relevant issue or comment.
+ = _("Explain the problem. If appropriate, provide a link to the relevant issue or comment.")
.form-actions
- = f.submit "Send report", class: "btn btn-success"
+ = f.submit _("Send report"), class: "btn btn-success"
diff --git a/app/views/admin/appearances/_form.html.haml b/app/views/admin/appearances/_form.html.haml
index d71dac2574c..cb67079853e 100644
--- a/app/views/admin/appearances/_form.html.haml
+++ b/app/views/admin/appearances/_form.html.haml
@@ -5,7 +5,7 @@
%legend
Navigation bar:
.form-group.row
- = f.label :header_logo, 'Header logo', class: 'col-sm-2 col-form-label'
+ = f.label :header_logo, 'Header logo', class: 'col-sm-2 col-form-label pt-0'
.col-sm-10
- if @appearance.header_logo?
= image_tag @appearance.header_logo_url, class: 'appearance-light-logo-preview'
@@ -22,7 +22,7 @@
%legend
Favicon:
.form-group.row
- = f.label :favicon, 'Favicon', class: 'col-sm-2 col-form-label'
+ = f.label :favicon, 'Favicon', class: 'col-sm-2 col-form-label pt-0'
.col-sm-10
- if @appearance.favicon?
= image_tag @appearance.favicon_url, class: 'appearance-light-logo-preview'
@@ -51,7 +51,7 @@
.hint
Description parsed with #{link_to "GitLab Flavored Markdown", help_page_path('user/markdown'), target: '_blank'}.
.form-group.row
- = f.label :logo, class: 'col-sm-2 col-form-label'
+ = f.label :logo, class: 'col-sm-2 col-form-label pt-0'
.col-sm-10
- if @appearance.logo?
= image_tag @appearance.logo_url, class: 'appearance-logo-preview'
diff --git a/app/views/admin/application_settings/_background_jobs.html.haml b/app/views/admin/application_settings/_background_jobs.html.haml
deleted file mode 100644
index 7d1a64b645a..00000000000
--- a/app/views/admin/application_settings/_background_jobs.html.haml
+++ /dev/null
@@ -1,27 +0,0 @@
-= form_for @application_setting, url: admin_application_settings_path(anchor: 'js-background-settings'), html: { class: 'fieldset-form' } do |f|
- = form_errors(@application_setting)
-
- %fieldset
- %p
- These settings require a
- = link_to 'restart', help_page_path('administration/restart_gitlab')
- to take effect.
- .form-group
- .form-check
- = f.check_box :sidekiq_throttling_enabled, class: 'form-check-input'
- = f.label :sidekiq_throttling_enabled, class: 'form-check-label' do
- Enable Sidekiq Job Throttling
- .form-text.text-muted
- Limit the amount of resources slow running jobs are assigned.
- .form-group
- = f.label :sidekiq_throttling_queues, 'Sidekiq queues to throttle', class: 'label-bold'
- = f.select :sidekiq_throttling_queues, sidekiq_queue_options_for_select, { include_hidden: false }, multiple: true, class: 'select2 select-wide', data: { field: 'sidekiq_throttling_queues' }
- .form-text.text-muted
- Choose which queues you wish to throttle.
- .form-group
- = f.label :sidekiq_throttling_factor, 'Throttling Factor', class: 'label-bold'
- = f.number_field :sidekiq_throttling_factor, class: 'form-control', min: '0.01', max: '0.99', step: '0.01'
- .form-text.text-muted
- The factor by which the queues should be throttled. A value between 0.0 and 1.0, exclusive.
-
- = f.submit 'Save changes', class: "btn btn-success"
diff --git a/app/views/admin/application_settings/_ci_cd.html.haml b/app/views/admin/application_settings/_ci_cd.html.haml
index 97be658cd34..0d42094fc89 100644
--- a/app/views/admin/application_settings/_ci_cd.html.haml
+++ b/app/views/admin/application_settings/_ci_cd.html.haml
@@ -41,5 +41,13 @@
The default unit is in seconds, but you can define an alternative. For example:
<code>4 mins 2 sec</code>, <code>2h42min</code>.
= link_to icon('question-circle'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'default-artifacts-expiration')
+ .form-group
+ = f.label :archive_builds_in_human_readable, 'Archive jobs', class: 'label-bold'
+ = f.text_field :archive_builds_in_human_readable, class: 'form-control', placeholder: 'never'
+ .form-text.text-muted
+ Set the duration for which the jobs will be considered as old and expired.
+ Once that time passes, the jobs will be archived and no longer able to be
+ retried. Make it empty to never expire jobs. It has to be no less than 1 day,
+ for example: <code>15 days</code>, <code>1 month</code>, <code>2 years</code>.
= f.submit 'Save changes', class: "btn btn-success"
diff --git a/app/views/admin/application_settings/_diff_limits.html.haml b/app/views/admin/application_settings/_diff_limits.html.haml
new file mode 100644
index 00000000000..408e569fe07
--- /dev/null
+++ b/app/views/admin/application_settings/_diff_limits.html.haml
@@ -0,0 +1,16 @@
+= form_for @application_setting, url: admin_application_settings_path(anchor: 'js-merge-request-settings'), html: { class: 'fieldset-form' } do |f|
+ = form_errors(@application_setting)
+
+ %fieldset
+ .form-group
+ = f.label :diff_max_patch_bytes, 'Maximum diff patch size (Bytes)', class: 'label-light'
+ = f.number_field :diff_max_patch_bytes, class: 'form-control'
+ %span.form-text.text-muted
+ Diff files surpassing this limit will be presented as 'too large'
+ and won't be expandable.
+
+ = link_to icon('question-circle'),
+ help_page_path('user/admin_area/diff_limits',
+ anchor: 'maximum-diff-patch-size')
+
+ = f.submit _('Save changes'), class: 'btn btn-success'
diff --git a/app/views/admin/application_settings/_email.html.haml b/app/views/admin/application_settings/_email.html.haml
index 86339e61215..60a6be731ea 100644
--- a/app/views/admin/application_settings/_email.html.haml
+++ b/app/views/admin/application_settings/_email.html.haml
@@ -20,5 +20,11 @@
By default GitLab sends emails in HTML and plain text formats so mail
clients can choose what format to use. Disable this option if you only
want to send emails in plain text format.
+ .form-group
+ = f.label :commit_email_hostname, _('Custom hostname (for private commit emails)'), class: 'label-bold'
+ = f.text_field :commit_email_hostname, class: 'form-control'
+ .form-text.text-muted
+ - commit_email_hostname_docs_link = link_to _('Learn more'), help_page_path('user/admin_area/settings/email', anchor: 'custom-private-commit-email-hostname'), target: '_blank'
+ = _("This setting will update the hostname that is used to generate private commit emails. %{learn_more}").html_safe % { learn_more: commit_email_hostname_docs_link }
= f.submit 'Save changes', class: "btn btn-success"
diff --git a/app/views/admin/application_settings/_koding.html.haml b/app/views/admin/application_settings/_koding.html.haml
deleted file mode 100644
index 8b635b08abd..00000000000
--- a/app/views/admin/application_settings/_koding.html.haml
+++ /dev/null
@@ -1,22 +0,0 @@
-= form_for @application_setting, url: admin_application_settings_path(anchor: 'js-koding-settings'), html: { class: 'fieldset-form' } do |f|
- = form_errors(@application_setting)
-
- %fieldset
- .form-group
- .form-check
- = f.check_box :koding_enabled, class: 'form-check-input'
- = f.label :koding_enabled, class: 'form-check-label' do
- Enable Koding
- .form-text.text-muted
- Koding integration has been deprecated since GitLab 10.0. If you disable your Koding integration, you will not be able to enable it again.
- .form-group
- = f.label :koding_url, 'Koding URL', class: 'label-bold'
- = f.text_field :koding_url, class: 'form-control', placeholder: 'http://gitlab.your-koding-instance.com:8090'
- .form-text.text-muted
- Koding has integration enabled out of the box for the
- %strong gitlab
- team, and you need to provide that team's URL here. Learn more in the
- = succeed "." do
- = link_to "Koding administration documentation", help_page_path("administration/integration/koding")
-
- = f.submit 'Save changes', class: "btn btn-success"
diff --git a/app/views/admin/application_settings/_repository_storage.html.haml b/app/views/admin/application_settings/_repository_storage.html.haml
index 4523332493b..c6c29ed1f21 100644
--- a/app/views/admin/application_settings/_repository_storage.html.haml
+++ b/app/views/admin/application_settings/_repository_storage.html.haml
@@ -5,7 +5,7 @@
.sub-section
.form-group
.form-check
- = f.check_box :hashed_storage_enabled, class: 'form-check-input'
+ = f.check_box :hashed_storage_enabled, class: 'form-check-input qa-hashed-storage-checkbox'
= f.label :hashed_storage_enabled, class: 'form-check-label' do
Use hashed storage paths for newly created and renamed projects
.form-text.text-muted
@@ -20,32 +20,5 @@
Manage repository storage paths. Learn more in the
= succeed "." do
= link_to "repository storages documentation", help_page_path("administration/repository_storage_paths")
- .sub-section
- %h4 Circuit breaker
- .form-group
- = f.label :circuitbreaker_check_interval, _('Check interval'), class: 'label-bold'
- = f.number_field :circuitbreaker_check_interval, class: 'form-control'
- .form-text.text-muted
- = circuitbreaker_check_interval_help_text
- .form-group
- = f.label :circuitbreaker_access_retries, _('Number of access attempts'), class: 'label-bold'
- = f.number_field :circuitbreaker_access_retries, class: 'form-control'
- .form-text.text-muted
- = circuitbreaker_access_retries_help_text
- .form-group
- = f.label :circuitbreaker_storage_timeout, _('Seconds to wait for a storage access attempt'), class: 'label-bold'
- = f.number_field :circuitbreaker_storage_timeout, class: 'form-control'
- .form-text.text-muted
- = circuitbreaker_storage_timeout_help_text
- .form-group
- = f.label :circuitbreaker_failure_count_threshold, _('Maximum git storage failures'), class: 'label-bold'
- = f.number_field :circuitbreaker_failure_count_threshold, class: 'form-control'
- .form-text.text-muted
- = circuitbreaker_failure_count_help_text
- .form-group
- = f.label :circuitbreaker_failure_reset_time, _('Seconds before reseting failure information'), class: 'label-bold'
- = f.number_field :circuitbreaker_failure_reset_time, class: 'form-control'
- .form-text.text-muted
- = circuitbreaker_failure_reset_time_help_text
- = f.submit 'Save changes', class: "btn btn-success"
+ = f.submit 'Save changes', class: "btn btn-success qa-save-changes-button"
diff --git a/app/views/admin/application_settings/preferences.html.haml b/app/views/admin/application_settings/preferences.html.haml
index 75f76eea3b4..00000b86ab7 100644
--- a/app/views/admin/application_settings/preferences.html.haml
+++ b/app/views/admin/application_settings/preferences.html.haml
@@ -46,17 +46,6 @@
.settings-content
= render 'realtime'
-%section.settings.as-background.no-animate#js-background-settings{ class: ('expanded' if expanded_by_default?) }
- .settings-header
- %h4
- = _('Background jobs')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
- = expanded_by_default? ? _('Collapse') : _('Expand')
- %p
- = _('Configure Sidekiq job throttling.')
- .settings-content
- = render 'background_jobs'
-
%section.settings.as-gitaly.no-animate#js-gitaly-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
%h4
diff --git a/app/views/admin/application_settings/repository.html.haml b/app/views/admin/application_settings/repository.html.haml
index d8029e0c54a..b50a0dd5a18 100644
--- a/app/views/admin/application_settings/repository.html.haml
+++ b/app/views/admin/application_settings/repository.html.haml
@@ -13,14 +13,14 @@
.settings-content
= render partial: 'repository_mirrors_form'
-%section.settings.as-repository-storage.no-animate#js-repository-storage-settings{ class: ('expanded' if expanded_by_default?) }
+%section.settings.qa-repository-storage-settings.as-repository-storage.no-animate#js-repository-storage-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
%h4
= _('Repository storage')
%button.btn.btn-default.js-settings-toggle{ type: 'button' }
= expanded_by_default? ? _('Collapse') : _('Expand')
%p
- = _('Configure storage path and circuit breaker settings.')
+ = _('Configure storage path settings.')
.settings-content
= render 'repository_storage'
diff --git a/app/views/admin/application_settings/show.html.haml b/app/views/admin/application_settings/show.html.haml
index e2043183a97..65e4723afe6 100644
--- a/app/views/admin/application_settings/show.html.haml
+++ b/app/views/admin/application_settings/show.html.haml
@@ -24,6 +24,17 @@
.settings-content
= render 'account_and_limit'
+%section.settings.as-diff-limits.no-animate#js-merge-request-settings{ class: ('expanded' if expanded_by_default?) }
+ .settings-header
+ %h4
+ = _('Diff limits')
+ %button.btn.js-settings-toggle{ type: 'button' }
+ = expanded_by_default? ? _('Collapse') : _('Expand')
+ %p
+ = _('Diff content limits')
+ .settings-content
+ = render 'diff_limits'
+
%section.settings.as-signup.no-animate#js-signup-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
%h4
@@ -46,7 +57,7 @@
.settings-content
= render 'signin'
-%section.qa-terms-settings.settings.as-terms.no-animate#js-terms-settings{ class: ('expanded' if expanded_by_default?) }
+%section.settings.as-terms.no-animate#js-terms-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
%h4
= _('Terms of Service and Privacy Policy')
@@ -57,18 +68,6 @@
.settings-content
= render 'terms'
-- if koding_enabled?
- %section.settings.as-koding.no-animate#js-koding-settings{ class: ('expanded' if expanded_by_default?) }
- .settings-header
- %h4
- = _('Koding')
- %button.btn.btn-default.js-settings-toggle{ type: 'button' }
- = expanded_by_default? ? _('Collapse') : _('Expand')
- %p
- = _('Online IDE integration settings.')
- .settings-content
- = render 'koding'
-
= render_if_exists 'admin/application_settings/external_authorization_service_form', expanded: expanded_by_default?
%section.settings.as-terminal.no-animate#js-terminal-settings{ class: ('expanded' if expanded_by_default?) }
diff --git a/app/views/admin/applications/_form.html.haml b/app/views/admin/applications/_form.html.haml
index 585576ec799..12690343f6e 100644
--- a/app/views/admin/applications/_form.html.haml
+++ b/app/views/admin/applications/_form.html.haml
@@ -21,14 +21,14 @@
for local tests
= content_tag :div, class: 'form-group row' do
- = f.label :trusted, class: 'col-sm-2 col-form-label'
+ = f.label :trusted, class: 'col-sm-2 col-form-label pt-0'
.col-sm-10
= f.check_box :trusted
%span.form-text.text-muted
Trusted applications are automatically authorized on GitLab OAuth flow.
.form-group.row
- = f.label :scopes, class: 'col-sm-2 col-form-label'
+ = f.label :scopes, class: 'col-sm-2 col-form-label pt-0'
.col-sm-10
= render 'shared/tokens/scopes_form', prefix: 'doorkeeper_application', token: application, scopes: @scopes
diff --git a/app/views/admin/applications/show.html.haml b/app/views/admin/applications/show.html.haml
index 593a6d816e3..df3eeba907c 100644
--- a/app/views/admin/applications/show.html.haml
+++ b/app/views/admin/applications/show.html.haml
@@ -1,4 +1,5 @@
- page_title @application.name, "Applications"
+
%h3.page-title
Application: #{@application.name}
@@ -6,23 +7,29 @@
%table.table
%tr
%td
- Application Id
+ = _('Application ID')
%td
- %code#application_id= @application.uid
+ .clipboard-group
+ .input-group
+ %input.label.label-monospace{ id: "application_id", type: "text", autocomplete: 'off', value: @application.uid, readonly: true }
+ .input-group-append
+ = clipboard_button(target: '#application_id', title: _("Copy ID to clipboard"), class: "btn btn btn-default")
%tr
%td
- Secret:
+ = _('Secret')
%td
- %code#secret= @application.secret
-
+ .clipboard-group
+ .input-group
+ %input.label.label-monospace{ id: "secret", type: "text", autocomplete: 'off', value: @application.secret, readonly: true }
+ .input-group-append
+ = clipboard_button(target: '#secret', title: _("Copy secret to clipboard"), class: "btn btn btn-default")
%tr
%td
- Callback url
+ = _('Callback URL')
%td
- @application.redirect_uri.split.each do |uri|
%div
%span.monospace= uri
-
%tr
%td
Trusted
diff --git a/app/views/admin/background_jobs/show.html.haml b/app/views/admin/background_jobs/show.html.haml
index faa5854bb40..a0a00ac5d96 100644
--- a/app/views/admin/background_jobs/show.html.haml
+++ b/app/views/admin/background_jobs/show.html.haml
@@ -6,40 +6,5 @@
%p.light GitLab uses #{link_to "sidekiq", "http://sidekiq.org/"} library for async job processing
%hr
-
- .card
- .card-header Sidekiq running processes
- .card-body
- - if @sidekiq_processes.empty?
- %h4.cred
- %i.fa.fa-exclamation-triangle
- There are no running sidekiq processes. Please restart GitLab
- - else
- .table-holder
- %table.table
- %thead
- %th USER
- %th PID
- %th CPU
- %th MEM
- %th STATE
- %th START
- %th COMMAND
- %tbody
- - @sidekiq_processes.each do |process|
- %tr
- %td= gitlab_config.user
- - parse_sidekiq_ps(process).each do |value|
- %td= value
- .clearfix
- %p
- %i.fa.fa-exclamation-circle
- If '[#{@concurrency} of #{@concurrency} busy]' is shown, restart GitLab with 'sudo service gitlab reload'.
- %p
- %i.fa.fa-exclamation-circle
- If more than one sidekiq process is listed, stop GitLab, kill the remaining sidekiq processes (sudo pkill -u #{gitlab_config.user} -f sidekiq) and restart GitLab.
-
-
-
.card
%iframe{ src: sidekiq_path, width: '100%', height: 970, style: "border: 0" }
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 85c04f8a01d..7ac79cc77f5 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -42,7 +42,7 @@
%p
Forks
%span.light.float-right
- = approximate_count_with_delimiters(@counts, ForkedProjectLink)
+ = approximate_fork_count_with_delimiters(@counts)
%p
Issues
%span.light.float-right
diff --git a/app/views/admin/groups/_form.html.haml b/app/views/admin/groups/_form.html.haml
index 2a117c1414e..5e05568e384 100644
--- a/app/views/admin/groups/_form.html.haml
+++ b/app/views/admin/groups/_form.html.haml
@@ -10,11 +10,11 @@
.col-sm-10
= render 'shared/choose_group_avatar_button', f: f
- = render 'shared/visibility_level', f: f, visibility_level: visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group
+ = render 'shared/old_visibility_level', f: f, visibility_level: visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group, with_label: false
.form-group.row
.offset-sm-2.col-sm-10
- = render 'shared/allow_request_access', form: f
+ = render 'shared/allow_request_access', form: f, bold_label: true
= render 'groups/group_admin_settings', f: f
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index 0c683f86252..5f205d1bcbc 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -63,10 +63,9 @@
.card
.card-header
- %h3.card-title
- = _('Projects')
- %span.badge.badge-pill
- #{@group.projects.count}
+ = _('Projects')
+ %span.badge.badge-pill
+ #{@group.projects.count}
%ul.content-list
- @projects.each do |project|
%li
@@ -119,7 +118,7 @@
= _("<strong>%{group_name}</strong> group members").html_safe % { group_name: @group.name }
%span.badge.badge-pill= @group.members.size
.float-right
- = link_to icon('pencil-square-o', text: _('Manage access')), polymorphic_url([@group, :members]), class: "btn btn-sm"
+ = link_to icon('pencil-square-o', text: _('Manage access')), group_group_members_path(@group), class: "btn btn-sm"
%ul.content-list.group-users-list.content-list.members-list
= render partial: 'shared/members/member', collection: @members, as: :member, locals: { show_controls: false }
.card-footer
diff --git a/app/views/admin/health_check/_failing_storages.html.haml b/app/views/admin/health_check/_failing_storages.html.haml
deleted file mode 100644
index 6830201538d..00000000000
--- a/app/views/admin/health_check/_failing_storages.html.haml
+++ /dev/null
@@ -1,15 +0,0 @@
-- if failing_storages.any?
- = _('There are problems accessing Git storage: ')
- %ul
- - failing_storages.each do |storage_health|
- %li
- = failing_storage_health_message(storage_health)
- %ul
- - storage_health.failing_circuit_breakers.each do |circuit_breaker|
- %li
- #{circuit_breaker.hostname}: #{message_for_circuit_breaker(circuit_breaker)}
-
- = _("Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again.")
- .prepend-top-10
- = button_to _("Reset git storage health information"), reset_storage_health_admin_health_check_path,
- method: :post, class: 'btn btn-default'
diff --git a/app/views/admin/health_check/show.html.haml b/app/views/admin/health_check/show.html.haml
index d51ac854b04..0f5e97e288a 100644
--- a/app/views/admin/health_check/show.html.haml
+++ b/app/views/admin/health_check/show.html.haml
@@ -1,6 +1,6 @@
- @no_container = true
- page_title _('Health Check')
-- no_errors = @errors.blank? && @failing_storage_statuses.blank?
+- no_errors = @errors.blank?
%div{ class: container_class }
%h3.page-title= page_title
@@ -39,4 +39,3 @@
#{ s_('HealthCheck|No Health Problems Detected') }
- else
= @errors
- = render partial: 'failing_storages', object: @failing_storage_statuses
diff --git a/app/views/admin/impersonation_tokens/index.html.haml b/app/views/admin/impersonation_tokens/index.html.haml
index 9e490713ef3..8e869fb4b71 100644
--- a/app/views/admin/impersonation_tokens/index.html.haml
+++ b/app/views/admin/impersonation_tokens/index.html.haml
@@ -5,6 +5,11 @@
.row.prepend-top-default
.col-lg-12
+ - if @new_impersonation_token
+ = render "shared/personal_access_tokens_created_container", new_token_value: @new_impersonation_token,
+ container_title: 'Your New Impersonation Token',
+ clipboard_button_title: 'Copy impersonation token to clipboard'
+
= render "shared/personal_access_tokens_form", path: admin_user_impersonation_tokens_path, impersonation: true, token: @impersonation_token, scopes: @scopes
= render "shared/personal_access_tokens_table", impersonation: true, active_tokens: @active_impersonation_tokens, inactive_tokens: @inactive_impersonation_tokens
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index ccba1c461fc..03cce4745aa 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -1,6 +1,8 @@
- add_to_breadcrumbs "Projects", admin_projects_path
- breadcrumb_title @project.full_name
- page_title @project.full_name, "Projects"
+- @content_class = "admin-projects"
+
%h3.page-title
Project: #{@project.full_name}
= link_to edit_project_path(@project), class: "btn btn-nr float-right" do
@@ -110,6 +112,8 @@
= visibility_level_icon(@project.visibility_level)
= visibility_level_label(@project.visibility_level)
+ = render_if_exists 'admin/projects/geo_status_widget', locals: { project: @project }
+
.card
.card-header
Transfer project
@@ -179,7 +183,7 @@
project members
%span.badge.badge-pill= @project.users.size
.float-right
- = link_to icon('pencil-square-o', text: 'Manage access'), polymorphic_url([@project, :members]), class: "btn btn-sm"
+ = link_to icon('pencil-square-o', text: 'Manage access'), project_project_members_path(@project), class: "btn btn-sm"
%ul.content-list.project_members.members-list
= render partial: 'shared/members/member', collection: @project_members, as: :member, locals: { show_controls: false }
.card-footer
diff --git a/app/views/admin/runners/_sort_dropdown.html.haml b/app/views/admin/runners/_sort_dropdown.html.haml
index b201e6bf10e..19c2a50ebd9 100644
--- a/app/views/admin/runners/_sort_dropdown.html.haml
+++ b/app/views/admin/runners/_sort_dropdown.html.haml
@@ -1,7 +1,7 @@
- sorted_by = sort_options_hash[@sort]
.dropdown.inline.prepend-left-10
- %button.dropdown-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' } }
+ %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' } }
= sorted_by
= icon('chevron-down')
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable.dropdown-menu-sort
diff --git a/app/views/admin/runners/index.html.haml b/app/views/admin/runners/index.html.haml
index ee2e1703fdb..e9e4e0847d3 100644
--- a/app/views/admin/runners/index.html.haml
+++ b/app/views/admin/runners/index.html.haml
@@ -2,97 +2,103 @@
- @no_container = true
%div{ class: container_class }
- .bs-callout
- %p
- = (_"A 'Runner' is a process which runs a job. You can set up as many Runners as you need.")
- %br
- = _('Runners can be placed on separate users, servers, even on your local machine.')
- %br
+ .row
+ .col-sm-6
+ .bs-callout
+ %p
+ = (_"A 'Runner' is a process which runs a job. You can set up as many Runners as you need.")
+ %br
+ = _('Runners can be placed on separate users, servers, even on your local machine.')
+ %br
- %div
- %span= _('Each Runner can be in one of the following states:')
- %ul
- %li
- %span.badge.badge-success shared
- \-
- = _('Runner runs jobs from all unassigned projects')
- %li
- %span.badge.badge-success group
- \-
- = _('Runner runs jobs from all unassigned projects in its group')
- %li
- %span.badge.badge-info specific
- \-
- = _('Runner runs jobs from assigned projects')
- %li
- %span.badge.badge-warning locked
- \-
- = _('Runner cannot be assigned to other projects')
- %li
- %span.badge.badge-danger paused
- \-
- = _('Runner will not receive any new jobs')
+ %div
+ %span= _('Each Runner can be in one of the following states:')
+ %ul
+ %li
+ %span.badge.badge-success shared
+ \-
+ = _('Runner runs jobs from all unassigned projects')
+ %li
+ %span.badge.badge-success group
+ \-
+ = _('Runner runs jobs from all unassigned projects in its group')
+ %li
+ %span.badge.badge-info specific
+ \-
+ = _('Runner runs jobs from assigned projects')
+ %li
+ %span.badge.badge-warning locked
+ \-
+ = _('Runner cannot be assigned to other projects')
+ %li
+ %span.badge.badge-danger paused
+ \-
+ = _('Runner will not receive any new jobs')
- .bs-callout.clearfix
- .float-left
- %p
- = _('You can reset runners registration token by pressing a button below.')
- .prepend-top-10
- = button_to _('Reset runners registration token'), reset_runners_token_admin_application_settings_path,
- method: :put, class: 'btn btn-default',
- data: { confirm: _('Are you sure you want to reset registration token?') }
+ .col-sm-6
+ .bs-callout
+ = render partial: 'ci/runner/how_to_setup_runner',
+ locals: { registration_token: Gitlab::CurrentSettings.runners_registration_token,
+ type: 'shared',
+ reset_token_url: reset_registration_token_admin_application_settings_path }
- = render partial: 'ci/runner/how_to_setup_shared_runner',
- locals: { registration_token: Gitlab::CurrentSettings.runners_registration_token }
+ .row
+ .col-sm-9
+ = form_tag admin_runners_path, id: 'runners-search', method: :get, class: 'filter-form js-filter-form' do
+ .filtered-search-wrapper
+ .filtered-search-box
+ = dropdown_tag(custom_icon('icon_history'),
+ options: { wrapper_class: 'filtered-search-history-dropdown-wrapper',
+ toggle_class: 'filtered-search-history-dropdown-toggle-button',
+ dropdown_class: 'filtered-search-history-dropdown',
+ content_class: 'filtered-search-history-dropdown-content',
+ title: _('Recent searches') }) do
+ .js-filtered-search-history-dropdown{ data: { full_path: admin_runners_path } }
+ .filtered-search-box-input-container.droplab-dropdown
+ .scroll-container
+ %ul.tokens-container.list-unstyled
+ %li.input-token
+ %input.form-control.filtered-search{ { id: 'filtered-search-runners', placeholder: _('Search or filter results...') } }
+ #js-dropdown-hint.filtered-search-input-dropdown-menu.dropdown-menu.hint-dropdown
+ %ul{ data: { dropdown: true } }
+ %li.filter-dropdown-item{ data: { action: 'submit' } }
+ = button_tag class: %w[btn btn-link] do
+ = sprite_icon('search')
+ %span
+ = _('Press Enter or click to search')
+ %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
+ %li.filter-dropdown-item
+ = button_tag class: %w[btn btn-link] do
+ -# Encapsulate static class name `{{icon}}` inside #{} to bypass
+ -# haml lint's ClassAttributeWithStaticValue
+ %svg
+ %use{ 'xlink:href': "#{'{{icon}}'}" }
+ %span.js-filter-hint
+ {{hint}}
+ %span.js-filter-tag.dropdown-light-content
+ {{tag}}
- .bs-callout
- %p
- = _('Runners currently online: %{active_runners_count}') % { active_runners_count: @active_runners_count }
+ #js-dropdown-admin-runner-status.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul{ data: { dropdown: true } }
+ - Ci::Runner::AVAILABLE_STATUSES.each do |status|
+ %li.filter-dropdown-item{ data: { value: status } }
+ = button_tag class: %w[btn btn-link] do
+ = status.titleize
- .row-content-block.second-block
- = form_tag admin_runners_path, id: 'runners-search', method: :get, class: 'filter-form js-filter-form' do
- .filtered-search-wrapper
- .filtered-search-box
- = dropdown_tag(custom_icon('icon_history'),
- options: { wrapper_class: 'filtered-search-history-dropdown-wrapper',
- toggle_class: 'filtered-search-history-dropdown-toggle-button',
- dropdown_class: 'filtered-search-history-dropdown',
- content_class: 'filtered-search-history-dropdown-content',
- title: _('Recent searches') }) do
- .js-filtered-search-history-dropdown{ data: { full_path: admin_runners_path } }
- .filtered-search-box-input-container.droplab-dropdown
- .scroll-container
- %ul.tokens-container.list-unstyled
- %li.input-token
- %input.form-control.filtered-search{ { id: 'filtered-search-runners', placeholder: _('Search or filter results...') } }
- #js-dropdown-hint.filtered-search-input-dropdown-menu.dropdown-menu.hint-dropdown
- %ul{ data: { dropdown: true } }
- %li.filter-dropdown-item{ data: { action: 'submit' } }
- = button_tag class: %w[btn btn-link] do
- = sprite_icon('search')
- %span
- = _('Press Enter or click to search')
- %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
- %li.filter-dropdown-item
- = button_tag class: %w[btn btn-link] do
- -# Encapsulate static class name `{{icon}}` inside #{} to bypass
- -# haml lint's ClassAttributeWithStaticValue
- %svg
- %use{ 'xlink:href': "#{'{{icon}}'}" }
- %span.js-filter-hint
- {{hint}}
- %span.js-filter-tag.dropdown-light-content
- {{tag}}
- #js-dropdown-admin-runner-status.filtered-search-input-dropdown-menu.dropdown-menu
- %ul{ data: { dropdown: true } }
- - Ci::Runner::AVAILABLE_STATUSES.each do |status|
- %li.filter-dropdown-item{ data: { value: status } }
- = button_tag class: %w[btn btn-link] do
- = status.titleize
- = button_tag class: %w[clear-search hidden] do
- = icon('times')
- .filter-dropdown-container
- = render 'sort_dropdown'
+ #js-dropdown-admin-runner-type.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul{ data: { dropdown: true } }
+ - Ci::Runner::AVAILABLE_TYPES.each do |runner_type|
+ %li.filter-dropdown-item{ data: { value: runner_type } }
+ = button_tag class: %w[btn btn-link] do
+ = runner_type.titleize
+
+ = button_tag class: %w[clear-search hidden] do
+ = icon('times')
+ .filter-dropdown-container
+ = render 'sort_dropdown'
+
+ .col-sm-3.text-right-lg
+ = _('Runners currently online: %{active_runners_count}') % { active_runners_count: @active_runners_count }
- if @runners.any?
.runners-content.content-list
diff --git a/app/views/admin/users/_head.html.haml b/app/views/admin/users/_head.html.haml
index bfbc16d37a0..a733f420d11 100644
--- a/app/views/admin/users/_head.html.haml
+++ b/app/views/admin/users/_head.html.haml
@@ -8,7 +8,7 @@
%span.cred (Admin)
.float-right
- - if @user != current_user && @user.can?(:log_in)
+ - if impersonation_enabled? && @user != current_user && @user.can?(:log_in)
= link_to 'Impersonate', impersonate_admin_user_path(@user), method: :post, class: "btn btn-nr btn-grouped btn-info"
= link_to edit_admin_user_path(@user), class: "btn btn-nr btn-grouped" do
%i.fa.fa-pencil-square-o
diff --git a/app/views/ci/runner/_how_to_setup_runner.html.haml b/app/views/ci/runner/_how_to_setup_runner.html.haml
index b1b142460b0..4307060d748 100644
--- a/app/views/ci/runner/_how_to_setup_runner.html.haml
+++ b/app/views/ci/runner/_how_to_setup_runner.html.haml
@@ -13,5 +13,9 @@
= _("Use the following registration token during setup:")
%code#registration_token= registration_token
= clipboard_button(target: '#registration_token', title: _("Copy token to clipboard"), class: "btn-transparent btn-clipboard")
+ .prepend-top-10.append-bottom-10
+ = button_to _("Reset runners registration token"), reset_token_url,
+ method: :put, class: 'btn btn-default',
+ data: { confirm: _("Are you sure you want to reset registration token?") }
%li
= _("Start the Runner!")
diff --git a/app/views/ci/runner/_how_to_setup_shared_runner.html.haml b/app/views/ci/runner/_how_to_setup_shared_runner.html.haml
deleted file mode 100644
index 2a190cb9250..00000000000
--- a/app/views/ci/runner/_how_to_setup_shared_runner.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-.bs-callout.help-callout
- = render partial: 'ci/runner/how_to_setup_runner',
- locals: { registration_token: registration_token, type: 'shared' }
diff --git a/app/views/ci/runner/_how_to_setup_specific_runner.html.haml b/app/views/ci/runner/_how_to_setup_specific_runner.html.haml
deleted file mode 100644
index afe57bdfa01..00000000000
--- a/app/views/ci/runner/_how_to_setup_specific_runner.html.haml
+++ /dev/null
@@ -1,26 +0,0 @@
-.bs-callout.help-callout
- .append-bottom-10
- %h4= _('Set up a specific Runner automatically')
-
- %p
- - link_to_help_page = link_to(_('Learn more about Kubernetes'),
- help_page_path('user/project/clusters/index'),
- target: '_blank',
- rel: 'noopener noreferrer')
-
- = _('You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}').html_safe % { link_to_help_page: link_to_help_page }
-
- %ol
- %li
- = _('Click the button below to begin the install process by navigating to the Kubernetes page')
- %li
- = _('Select an existing Kubernetes cluster or create a new one')
- %li
- = _('From the Kubernetes cluster details view, install Runner from the applications list')
-
- = link_to _('Install Runner on Kubernetes'),
- project_clusters_path(@project),
- class: 'btn btn-info'
- %hr
- = render partial: 'ci/runner/how_to_setup_runner',
- locals: { registration_token: registration_token, type: 'specific' }
diff --git a/app/views/ci/variables/_index.html.haml b/app/views/ci/variables/_index.html.haml
index e402801a776..f34305e94fa 100644
--- a/app/views/ci/variables/_index.html.haml
+++ b/app/views/ci/variables/_index.html.haml
@@ -9,8 +9,8 @@
= render 'ci/variables/variable_row', form_field: 'variables', variable: variable
= render 'ci/variables/variable_row', form_field: 'variables'
.prepend-top-20
- %button.btn.btn-success.js-secret-variables-save-button{ type: 'button' }
- %span.hide.js-secret-variables-save-loading-icon
+ %button.btn.btn-success.js-ci-variables-save-button{ type: 'button' }
+ %span.hide.js-ci-variables-save-loading-icon
= icon('spinner spin')
= _('Save variables')
%button.btn.btn-info.btn-inverted.prepend-left-10.js-secret-value-reveal-button{ type: 'button', data: { secret_reveal_status: "#{@variables.size == 0}" } }
diff --git a/app/views/clusters/clusters/_advanced_settings.html.haml b/app/views/clusters/clusters/_advanced_settings.html.haml
new file mode 100644
index 00000000000..7037c80aa6b
--- /dev/null
+++ b/app/views/clusters/clusters/_advanced_settings.html.haml
@@ -0,0 +1,15 @@
+- if can?(current_user, :admin_cluster, @cluster)
+ - if @cluster.managed?
+ .append-bottom-20
+ %label.append-bottom-10
+ = s_('ClusterIntegration|Google Kubernetes Engine')
+ %p
+ - link_gke = link_to(s_('ClusterIntegration|Google Kubernetes Engine'), @cluster.gke_cluster_url, target: '_blank', rel: 'noopener noreferrer')
+ = s_('ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}').html_safe % { link_gke: link_gke }
+
+ .sub-section.form-group
+ %h4.text-danger
+ = s_('ClusterIntegration|Remove Kubernetes cluster integration')
+ %p
+ = s_("ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster.")
+ = link_to(s_('ClusterIntegration|Remove integration'), clusterable.cluster_path(@cluster), method: :delete, class: 'btn btn-danger', data: { confirm: s_("ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster.")})
diff --git a/app/views/clusters/clusters/_banner.html.haml b/app/views/clusters/clusters/_banner.html.haml
new file mode 100644
index 00000000000..160c5f009a7
--- /dev/null
+++ b/app/views/clusters/clusters/_banner.html.haml
@@ -0,0 +1,9 @@
+.hidden.js-cluster-error.bs-callout.bs-callout-danger{ role: 'alert' }
+ = s_('ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine')
+ %p.js-error-reason
+
+.hidden.js-cluster-creating.bs-callout.bs-callout-info{ role: 'alert' }
+ = s_('ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine...')
+
+.hidden.js-cluster-success.bs-callout.bs-callout-success{ role: 'alert' }
+ = s_("ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details")
diff --git a/app/views/clusters/clusters/_buttons.html.haml b/app/views/clusters/clusters/_buttons.html.haml
new file mode 100644
index 00000000000..db2e247e341
--- /dev/null
+++ b/app/views/clusters/clusters/_buttons.html.haml
@@ -0,0 +1,4 @@
+-# This partial is overridden in EE
+.nav-controls
+ %span.btn.btn-add-cluster.disabled.js-add-cluster
+ = s_("ClusterIntegration|Add Kubernetes cluster")
diff --git a/app/views/clusters/clusters/_cluster.html.haml b/app/views/clusters/clusters/_cluster.html.haml
new file mode 100644
index 00000000000..adeca013749
--- /dev/null
+++ b/app/views/clusters/clusters/_cluster.html.haml
@@ -0,0 +1,16 @@
+.card
+ .card-body.gl-responsive-table-row
+ .table-section.section-60
+ .table-mobile-header{ role: "rowheader" }= s_("ClusterIntegration|Kubernetes cluster")
+ .table-mobile-content
+ = link_to cluster.name, cluster.show_path
+ - unless cluster.enabled?
+ %span.badge.badge-danger Connection disabled
+ .table-section.section-25
+ .table-mobile-header{ role: "rowheader" }= s_("ClusterIntegration|Environment scope")
+ .table-mobile-content= cluster.environment_scope
+ .table-section.section-15.text-right
+ .table-mobile-header{ role: "rowheader" }
+ .table-mobile-content
+ %span.badge.badge-light
+ = cluster.project_type? ? s_("ClusterIntegration|Project cluster") : s_("ClusterIntegration|Group cluster")
diff --git a/app/views/clusters/clusters/_empty_state.html.haml b/app/views/clusters/clusters/_empty_state.html.haml
new file mode 100644
index 00000000000..c926ec258f0
--- /dev/null
+++ b/app/views/clusters/clusters/_empty_state.html.haml
@@ -0,0 +1,14 @@
+.row.empty-state
+ .col-12
+ .svg-content= image_tag 'illustrations/clusters_empty.svg'
+ .col-12
+ .text-content
+ %h4.text-center= s_('ClusterIntegration|Integrate Kubernetes cluster automation')
+ %p
+ = s_('ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way.')
+ = clusterable.empty_state_help_text
+ = clusterable.learn_more_link
+
+ - if clusterable.can_create_cluster?
+ .text-center
+ = link_to s_('ClusterIntegration|Add Kubernetes cluster'), clusterable.new_path, class: 'btn btn-success'
diff --git a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
new file mode 100644
index 00000000000..85d1002243b
--- /dev/null
+++ b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
@@ -0,0 +1,12 @@
+- link = link_to(s_('ClusterIntegration|sign up'), 'https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral', target: '_blank', rel: 'noopener noreferrer')
+.bs-callout.gcp-signup-offer.alert.alert-block.alert-dismissable.prepend-top-default.append-bottom-default{ role: 'alert', data: { feature_id: UserCalloutsHelper::GCP_SIGNUP_OFFER, dismiss_endpoint: user_callouts_path } }
+ %button.close.js-close{ type: "button" } &times;
+ .gcp-signup-offer--content
+ .gcp-signup-offer--icon.append-right-8
+ = sprite_icon("information", size: 16)
+ .gcp-signup-offer--copy
+ %h4= s_('ClusterIntegration|Did you know?')
+ %p= s_('ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab\'s Google Kubernetes Engine Integration.').html_safe % { sign_up_link: link }
+ %a.btn.btn-default{ href: 'https://goo.gl/AaJzRW', target: '_blank', rel: 'noopener noreferrer' }
+ Apply for credit
+
diff --git a/app/views/clusters/clusters/_integration_form.html.haml b/app/views/clusters/clusters/_integration_form.html.haml
new file mode 100644
index 00000000000..5e451f60c9d
--- /dev/null
+++ b/app/views/clusters/clusters/_integration_form.html.haml
@@ -0,0 +1,31 @@
+= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster do |field|
+ = form_errors(@cluster)
+ .form-group
+ %h5= s_('ClusterIntegration|Integration status')
+ %label.append-bottom-0.js-cluster-enable-toggle-area
+ %button{ type: 'button',
+ class: "js-project-feature-toggle project-feature-toggle #{'is-checked' if @cluster.enabled?} #{'is-disabled' unless can?(current_user, :update_cluster, @cluster)}",
+ "aria-label": s_("ClusterIntegration|Toggle Kubernetes cluster"),
+ disabled: !can?(current_user, :update_cluster, @cluster) }
+ = field.hidden_field :enabled, { class: 'js-project-feature-toggle-input'}
+ %span.toggle-icon
+ = sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
+ = sprite_icon('status_failed_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-unchecked')
+ .form-text.text-muted= s_('ClusterIntegration|Enable or disable GitLab\'s connection to your Kubernetes cluster.')
+
+ - if has_multiple_clusters?
+ .form-group
+ %h5= s_('ClusterIntegration|Environment scope')
+ = field.text_field :environment_scope, class: 'col-md-6 form-control js-select-on-focus', placeholder: s_('ClusterIntegration|Environment scope')
+ .form-text.text-muted= s_("ClusterIntegration|Choose which of your environments will use this cluster.")
+
+ - if can?(current_user, :update_cluster, @cluster)
+ .form-group
+ = field.submit _('Save changes'), class: 'btn btn-success'
+
+ - unless has_multiple_clusters?
+ %h5= s_('ClusterIntegration|Environment scope')
+ %p
+ %code *
+ is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster.
+ = link_to 'More information', ('https://docs.gitlab.com/ee/user/project/clusters/#setting-the-environment-scope')
diff --git a/app/views/clusters/clusters/_sidebar.html.haml b/app/views/clusters/clusters/_sidebar.html.haml
new file mode 100644
index 00000000000..6e4415c21a9
--- /dev/null
+++ b/app/views/clusters/clusters/_sidebar.html.haml
@@ -0,0 +1,6 @@
+%h4.prepend-top-0
+ = s_('ClusterIntegration|Add a Kubernetes cluster integration')
+%p
+ = clusterable.sidebar_text
+%p
+ = clusterable.learn_more_link
diff --git a/app/views/clusters/clusters/gcp/_form.html.haml b/app/views/clusters/clusters/gcp/_form.html.haml
new file mode 100644
index 00000000000..8ed4666e79a
--- /dev/null
+++ b/app/views/clusters/clusters/gcp/_form.html.haml
@@ -0,0 +1,74 @@
+= javascript_include_tag 'https://apis.google.com/js/api.js'
+- external_link_icon = icon('external-link')
+- zones_link_url = 'https://cloud.google.com/compute/docs/regions-zones/regions-zones'
+- machine_type_link_url = 'https://cloud.google.com/compute/docs/machine-types'
+- pricing_link_url = 'https://cloud.google.com/compute/pricing#machinetype'
+- help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe
+- help_link_end = ' %{external_link_icon}</a>'.html_safe % { external_link_icon: external_link_icon }
+
+%p
+ - link_to_help_page = link_to(s_('ClusterIntegration|help page'), help_page_path('user/project/clusters/index'), target: '_blank', rel: 'noopener noreferrer')
+ = s_('ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration.').html_safe % { link_to_help_page: link_to_help_page}
+
+%p= link_to('Select a different Google account', @authorize_url)
+
+= form_for @gcp_cluster, html: { class: 'js-gke-cluster-creation prepend-top-20', data: { token: token_in_session } }, url: clusterable.create_gcp_clusters_path, as: :cluster do |field|
+ = form_errors(@gcp_cluster)
+ .form-group
+ = field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-bold'
+ = field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Kubernetes cluster name')
+ .form-group
+ = field.label :environment_scope, s_('ClusterIntegration|Environment scope'), class: 'label-bold'
+ = field.text_field :environment_scope, class: 'form-control', readonly: !has_multiple_clusters?, placeholder: s_('ClusterIntegration|Environment scope')
+
+ = field.fields_for :provider_gcp, @gcp_cluster.provider_gcp do |provider_gcp_field|
+ .form-group
+ = provider_gcp_field.label :gcp_project_id, s_('ClusterIntegration|Google Cloud Platform project'), class: 'label-bold'
+ .js-gcp-project-id-dropdown-entry-point{ data: { docsUrl: 'https://console.cloud.google.com/home/dashboard' } }
+ = provider_gcp_field.hidden_field :gcp_project_id
+ .dropdown
+ %button.dropdown-menu-toggle.dropdown-menu-full-width{ type: 'button', disabled: true }
+ %span.dropdown-toggle-text
+ = _('Select project')
+ = icon('chevron-down')
+ %span.form-text.text-muted &nbsp;
+
+ .form-group
+ = provider_gcp_field.label :zone, s_('ClusterIntegration|Zone'), class: 'label-bold'
+ .js-gcp-zone-dropdown-entry-point
+ = provider_gcp_field.hidden_field :zone
+ .dropdown
+ %button.dropdown-menu-toggle.dropdown-menu-full-width{ type: 'button', disabled: true }
+ %span.dropdown-toggle-text
+ = _('Select project to choose zone')
+ = icon('chevron-down')
+ %p.form-text.text-muted
+ = s_('ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}.').html_safe % { help_link_start: help_link_start % { url: zones_link_url }, help_link_end: help_link_end }
+
+ .form-group
+ = provider_gcp_field.label :num_nodes, s_('ClusterIntegration|Number of nodes'), class: 'label-bold'
+ = provider_gcp_field.text_field :num_nodes, class: 'form-control', placeholder: '3'
+
+ .form-group
+ = provider_gcp_field.label :machine_type, s_('ClusterIntegration|Machine type'), class: 'label-bold'
+ .js-gcp-machine-type-dropdown-entry-point
+ = provider_gcp_field.hidden_field :machine_type
+ .dropdown
+ %button.dropdown-menu-toggle.dropdown-menu-full-width{ type: 'button', disabled: true }
+ %span.dropdown-toggle-text
+ = _('Select project and zone to choose machine type')
+ = icon('chevron-down')
+ %p.form-text.text-muted
+ = s_('ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}.').html_safe % { help_link_start_machine_type: help_link_start % { url: machine_type_link_url }, help_link_start_pricing: help_link_start % { url: pricing_link_url }, help_link_end: help_link_end }
+
+ .form-group
+ .form-check
+ = provider_gcp_field.check_box :legacy_abac, { class: 'form-check-input' }, false, true
+ = provider_gcp_field.label :legacy_abac, s_('ClusterIntegration|RBAC-enabled cluster'), class: 'form-check-label label-bold'
+ .form-text.text-muted
+ = s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
+ = s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
+ = link_to _('More information'), help_page_path('user/project/clusters/index.md', anchor: 'role-based-access-control-rbac-core-only'), target: '_blank'
+
+ .form-group
+ = field.submit s_('ClusterIntegration|Create Kubernetes cluster'), class: 'js-gke-cluster-creation-submit btn btn-success', disabled: true
diff --git a/app/views/projects/clusters/gcp/_header.html.haml b/app/views/clusters/clusters/gcp/_header.html.haml
index a2ad3cd64df..a2ad3cd64df 100644
--- a/app/views/projects/clusters/gcp/_header.html.haml
+++ b/app/views/clusters/clusters/gcp/_header.html.haml
diff --git a/app/views/clusters/clusters/gcp/_show.html.haml b/app/views/clusters/clusters/gcp/_show.html.haml
new file mode 100644
index 00000000000..e9f05eaf453
--- /dev/null
+++ b/app/views/clusters/clusters/gcp/_show.html.haml
@@ -0,0 +1,50 @@
+.form-group
+ %label.append-bottom-10{ for: 'cluster-name' }
+ = s_('ClusterIntegration|Kubernetes cluster name')
+ .input-group
+ %input.form-control.cluster-name.js-select-on-focus{ value: @cluster.name, readonly: true }
+ %span.input-group-append
+ = clipboard_button(text: @cluster.name, title: s_('ClusterIntegration|Copy Kubernetes cluster name'), class: 'input-group-text btn-default')
+
+= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster do |field|
+ = form_errors(@cluster)
+
+ = field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
+ .form-group
+ = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL')
+ .input-group
+ = platform_kubernetes_field.text_field :api_url, class: 'form-control js-select-on-focus', placeholder: s_('ClusterIntegration|API URL'), readonly: true
+ %span.input-group-append
+ = clipboard_button(text: @cluster.platform_kubernetes.api_url, title: s_('ClusterIntegration|Copy API URL'), class: 'input-group-text btn-default')
+
+ .form-group
+ = platform_kubernetes_field.label :ca_cert, s_('ClusterIntegration|CA Certificate')
+ .input-group
+ = platform_kubernetes_field.text_area :ca_cert, class: 'form-control js-select-on-focus', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)'), readonly: true
+ %span.input-group-append.clipboard-addon
+ = clipboard_button(text: @cluster.platform_kubernetes.ca_cert, title: s_('ClusterIntegration|Copy CA Certificate'), class: 'input-group-text btn-blank')
+
+ .form-group
+ = platform_kubernetes_field.label :token, s_('ClusterIntegration|Token')
+ .input-group
+ = platform_kubernetes_field.text_field :token, class: 'form-control js-cluster-token js-select-on-focus', type: 'password', placeholder: s_('ClusterIntegration|Token'), readonly: true
+ %span.input-group-append
+ %button.btn.btn-default.input-group-text.js-show-cluster-token{ type: 'button' }
+ = s_('ClusterIntegration|Show')
+ = clipboard_button(text: @cluster.platform_kubernetes.token, title: s_('ClusterIntegration|Copy Token'), class: 'btn-default')
+
+ - if @cluster.allow_user_defined_namespace?
+ .form-group
+ = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)')
+ = platform_kubernetes_field.text_field :namespace, class: 'form-control', placeholder: s_('ClusterIntegration|Project namespace')
+
+ .form-group
+ .form-check
+ = platform_kubernetes_field.check_box :authorization_type, { class: 'form-check-input', disabled: true }, 'rbac', 'abac'
+ = platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster'), class: 'form-check-label label-bold'
+ .form-text.text-muted
+ = s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
+ = s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
+
+ .form-group
+ = field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success'
diff --git a/app/views/clusters/clusters/index.html.haml b/app/views/clusters/clusters/index.html.haml
new file mode 100644
index 00000000000..ad6d1d856d6
--- /dev/null
+++ b/app/views/clusters/clusters/index.html.haml
@@ -0,0 +1,23 @@
+- breadcrumb_title 'Kubernetes'
+- page_title "Kubernetes Clusters"
+
+= render_gcp_signup_offer
+
+.clusters-container
+ - if @clusters.empty?
+ = render "empty_state"
+ - else
+ .top-area.adjust
+ .nav-text
+ = s_("ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project")
+ = render 'clusters/clusters/buttons'
+ .clusters-table.js-clusters-list
+ .gl-responsive-table-row.table-row-header{ role: "row" }
+ .table-section.section-60{ role: "rowheader" }
+ = s_("ClusterIntegration|Kubernetes cluster")
+ .table-section.section-30{ role: "rowheader" }
+ = s_("ClusterIntegration|Environment scope")
+ .table-section.section-10{ role: "rowheader" }
+ - @clusters.each do |cluster|
+ = render "cluster", cluster: cluster.present(current_user: current_user)
+ = paginate @clusters, theme: "gitlab"
diff --git a/app/views/clusters/clusters/new.html.haml b/app/views/clusters/clusters/new.html.haml
new file mode 100644
index 00000000000..eeeef6bd824
--- /dev/null
+++ b/app/views/clusters/clusters/new.html.haml
@@ -0,0 +1,36 @@
+- breadcrumb_title 'Kubernetes'
+- page_title _("Kubernetes Cluster")
+- active_tab = local_assigns.fetch(:active_tab, 'gcp')
+= javascript_include_tag 'https://apis.google.com/js/api.js'
+
+= render_gcp_signup_offer
+
+.row.prepend-top-default
+ .col-md-3
+ = render 'sidebar'
+ .col-md-9.js-toggle-container
+ %ul.nav-links.nav-tabs.gitlab-tabs.nav{ role: 'tablist' }
+ %li.nav-item{ role: 'presentation' }
+ %a.nav-link{ href: '#create-gcp-cluster-pane', id: 'create-gcp-cluster-tab', class: active_when(active_tab == 'gcp'), data: { toggle: 'tab' }, role: 'tab' }
+ %span Create new Cluster on GKE
+ %li.nav-item{ role: 'presentation' }
+ %a.nav-link{ href: '#add-user-cluster-pane', id: 'add-user-cluster-tab', class: active_when(active_tab == 'user'), data: { toggle: 'tab' }, role: 'tab' }
+ %span Add existing cluster
+
+ .tab-content.gitlab-tab-content
+ .tab-pane{ id: 'create-gcp-cluster-pane', class: active_when(active_tab == 'gcp'), role: 'tabpanel' }
+ = render 'clusters/clusters/gcp/header'
+ - if @valid_gcp_token
+ = render 'clusters/clusters/gcp/form'
+ - elsif @authorize_url
+ .signin-with-google
+ = link_to(image_tag('auth_buttons/signin_with_google.png', width: '191px'), @authorize_url)
+ = _('or')
+ = link_to('create a new Google account', 'https://accounts.google.com/SignUpWithoutGmail?service=cloudconsole&continue=https%3A%2F%2Fconsole.cloud.google.com%2Ffreetrial%3Futm_campaign%3D2018_cpanel%26utm_source%3Dgitlab%26utm_medium%3Dreferral', target: '_blank', rel: 'noopener noreferrer')
+ - else
+ - link = link_to(s_('ClusterIntegration|properly configured'), help_page_path("integration/google"), target: '_blank', rel: 'noopener noreferrer')
+ = s_('Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service.').html_safe % { link_to_documentation: link }
+
+ .tab-pane{ id: 'add-user-cluster-pane', class: active_when(active_tab == 'user'), role: 'tabpanel' }
+ = render 'clusters/clusters/user/header'
+ = render 'clusters/clusters/user/form'
diff --git a/app/views/clusters/clusters/show.html.haml b/app/views/clusters/clusters/show.html.haml
new file mode 100644
index 00000000000..b1aa8e5d477
--- /dev/null
+++ b/app/views/clusters/clusters/show.html.haml
@@ -0,0 +1,56 @@
+- @content_class = "limit-container-width" unless fluid_layout
+- add_to_breadcrumbs "Kubernetes Clusters", clusterable.index_path
+- breadcrumb_title @cluster.name
+- page_title _("Kubernetes Cluster")
+- manage_prometheus_path = edit_project_service_path(@cluster.project, 'prometheus') if @project
+
+- expanded = Rails.env.test?
+
+- status_path = clusterable.cluster_status_cluster_path(@cluster.id, format: :json) if can?(current_user, :admin_cluster, @cluster)
+.edit-cluster-form.js-edit-cluster-form{ data: { status_path: status_path,
+ install_helm_path: clusterable.install_applications_cluster_path(@cluster, :helm),
+ install_ingress_path: clusterable.install_applications_cluster_path(@cluster, :ingress),
+ install_cert_manager_path: clusterable.install_applications_cluster_path(@cluster, :cert_manager),
+ install_prometheus_path: clusterable.install_applications_cluster_path(@cluster, :prometheus),
+ install_runner_path: clusterable.install_applications_cluster_path(@cluster, :runner),
+ install_jupyter_path: clusterable.install_applications_cluster_path(@cluster, :jupyter),
+ install_knative_path: clusterable.install_applications_cluster_path(@cluster, :knative),
+ toggle_status: @cluster.enabled? ? 'true': 'false',
+ cluster_type: @cluster.cluster_type,
+ cluster_status: @cluster.status_name,
+ cluster_status_reason: @cluster.status_reason,
+ help_path: help_page_path('user/project/clusters/index.md', anchor: 'installing-applications'),
+ ingress_help_path: help_page_path('user/project/clusters/index.md', anchor: 'getting-the-external-ip-address'),
+ ingress_dns_help_path: help_page_path('topics/autodevops/quick_start_guide.md', anchor: 'point-dns-at-cluster-ip'),
+ manage_prometheus_path: manage_prometheus_path } }
+
+ .js-cluster-application-notice
+ .flash-container
+
+ %section#cluster-integration
+ %h4= @cluster.name
+ = render 'banner'
+ = render 'integration_form'
+
+ .cluster-applications-table#js-cluster-applications
+
+ %section.settings#js-cluster-details{ class: ('expanded' if expanded) }
+ .settings-header
+ %h4= s_('ClusterIntegration|Kubernetes cluster details')
+ %button.btn.js-settings-toggle{ type: 'button' }
+ = expanded ? 'Collapse' : 'Expand'
+ %p= s_('ClusterIntegration|See and edit the details for your Kubernetes cluster')
+ .settings-content
+ - if @cluster.managed?
+ = render 'clusters/clusters/gcp/show'
+ - else
+ = render 'clusters/clusters/user/show'
+
+ %section.settings.no-animate#js-cluster-advanced-settings{ class: ('expanded' if expanded) }
+ .settings-header
+ %h4= _('Advanced settings')
+ %button.btn.js-settings-toggle{ type: 'button' }
+ = expanded ? 'Collapse' : 'Expand'
+ %p= s_("ClusterIntegration|Advanced options on this Kubernetes cluster's integration")
+ .settings-content
+ = render 'advanced_settings'
diff --git a/app/views/clusters/clusters/user/_form.html.haml b/app/views/clusters/clusters/user/_form.html.haml
new file mode 100644
index 00000000000..9793c77fc2b
--- /dev/null
+++ b/app/views/clusters/clusters/user/_form.html.haml
@@ -0,0 +1,39 @@
+= form_for @user_cluster, url: clusterable.create_user_clusters_path, as: :cluster do |field|
+ = form_errors(@user_cluster)
+ .form-group
+ = field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-bold'
+ = field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Kubernetes cluster name')
+ - if has_multiple_clusters?
+ .form-group
+ = field.label :environment_scope, s_('ClusterIntegration|Environment scope'), class: 'label-bold'
+ = field.text_field :environment_scope, class: 'form-control', placeholder: s_('ClusterIntegration|Environment scope')
+
+ = field.fields_for :platform_kubernetes, @user_cluster.platform_kubernetes do |platform_kubernetes_field|
+ .form-group
+ = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL'), class: 'label-bold'
+ = platform_kubernetes_field.text_field :api_url, class: 'form-control', placeholder: s_('ClusterIntegration|API URL')
+
+ .form-group
+ = platform_kubernetes_field.label :ca_cert, s_('ClusterIntegration|CA Certificate'), class: 'label-bold'
+ = platform_kubernetes_field.text_area :ca_cert, class: 'form-control', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)')
+
+ .form-group
+ = platform_kubernetes_field.label :token, s_('ClusterIntegration|Token'), class: 'label-bold'
+ = platform_kubernetes_field.text_field :token, class: 'form-control', placeholder: s_('ClusterIntegration|Service token'), autocomplete: 'off'
+
+ - if @user_cluster.allow_user_defined_namespace?
+ .form-group
+ = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)'), class: 'label-bold'
+ = platform_kubernetes_field.text_field :namespace, class: 'form-control', placeholder: s_('ClusterIntegration|Project namespace')
+
+ .form-group
+ .form-check
+ = platform_kubernetes_field.check_box :authorization_type, { class: 'form-check-input qa-rbac-checkbox' }, 'rbac', 'abac'
+ = platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster'), class: 'form-check-label label-bold'
+ .form-text.text-muted
+ = s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
+ = s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
+ = link_to _('More information'), help_page_path('user/project/clusters/index.md', anchor: 'role-based-access-control-rbac-core-only'), target: '_blank'
+
+ .form-group
+ = field.submit s_('ClusterIntegration|Add Kubernetes cluster'), class: 'btn btn-success'
diff --git a/app/views/projects/clusters/user/_header.html.haml b/app/views/clusters/clusters/user/_header.html.haml
index 749177fa6c1..749177fa6c1 100644
--- a/app/views/projects/clusters/user/_header.html.haml
+++ b/app/views/clusters/clusters/user/_header.html.haml
diff --git a/app/views/clusters/clusters/user/_show.html.haml b/app/views/clusters/clusters/user/_show.html.haml
new file mode 100644
index 00000000000..cac8e72edd3
--- /dev/null
+++ b/app/views/clusters/clusters/user/_show.html.haml
@@ -0,0 +1,39 @@
+= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster do |field|
+ = form_errors(@cluster)
+ .form-group
+ = field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-bold'
+ = field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Kubernetes cluster name')
+
+ = field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
+ .form-group
+ = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL'), class: 'label-bold'
+ = platform_kubernetes_field.text_field :api_url, class: 'form-control', placeholder: s_('ClusterIntegration|API URL')
+
+ .form-group
+ = platform_kubernetes_field.label :ca_cert, s_('ClusterIntegration|CA Certificate'), class: 'label-bold'
+ = platform_kubernetes_field.text_area :ca_cert, class: 'form-control', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)')
+
+ .form-group
+ = platform_kubernetes_field.label :token, s_('ClusterIntegration|Token'), class: 'label-bold'
+ .input-group
+ = platform_kubernetes_field.text_field :token, class: 'form-control js-cluster-token', type: 'password', placeholder: s_('ClusterIntegration|Token'), autocomplete: 'off'
+ %span.input-group-append.clipboard-addon
+ .input-group-text
+ %button.js-show-cluster-token.btn-blank{ type: 'button' }
+ = s_('ClusterIntegration|Show')
+
+ - if @cluster.allow_user_defined_namespace?
+ .form-group
+ = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)'), class: 'label-bold'
+ = platform_kubernetes_field.text_field :namespace, class: 'form-control', placeholder: s_('ClusterIntegration|Project namespace')
+
+ .form-group
+ .form-check
+ = platform_kubernetes_field.check_box :authorization_type, { class: 'form-check-input', disabled: true }, 'rbac', 'abac'
+ = platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster'), class: 'form-check-label label-bold'
+ .form-text.text-muted
+ = s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
+ = s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
+
+ .form-group
+ = field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success'
diff --git a/app/views/dashboard/_activity_head.html.haml b/app/views/dashboard/_activity_head.html.haml
index 7503548fa3d..ec1a3fef435 100644
--- a/app/views/dashboard/_activity_head.html.haml
+++ b/app/views/dashboard/_activity_head.html.haml
@@ -1,3 +1,6 @@
+.page-title-holder
+ %h1.page-title= _('Activity')
+
.top-area
%ul.nav-links.nav.nav-tabs
%li{ class: active_when(params[:filter].nil?) }>
diff --git a/app/views/dashboard/_groups_head.html.haml b/app/views/dashboard/_groups_head.html.haml
index 727784141bb..8ab5dc37f34 100644
--- a/app/views/dashboard/_groups_head.html.haml
+++ b/app/views/dashboard/_groups_head.html.haml
@@ -1,3 +1,10 @@
+.page-title-holder
+ %h1.page-title= _('Groups')
+
+ - if current_user.can_create_group?
+ .page-title-controls
+ = link_to _("New group"), new_group_path, class: "btn btn-success"
+
.top-area
%ul.nav-links.mobile-separator.nav.nav-tabs
= nav_link(page: dashboard_groups_path) do
@@ -9,5 +16,3 @@
.nav-controls
= render 'shared/groups/search_form'
= render 'shared/groups/dropdown'
- - if current_user.can_create_group?
- = link_to _("New group"), new_group_path, class: "btn btn-success"
diff --git a/app/views/dashboard/_projects_head.html.haml b/app/views/dashboard/_projects_head.html.haml
index 69a2e408073..1050945b15a 100644
--- a/app/views/dashboard/_projects_head.html.haml
+++ b/app/views/dashboard/_projects_head.html.haml
@@ -1,6 +1,13 @@
= content_for :flash_message do
= render 'shared/project_limit'
+.page-title-holder
+ %h1.page-title= _('Projects')
+
+ - if current_user.can_create_project?
+ .page-title-controls
+ = link_to "New project", new_project_path, class: "btn btn-success"
+
.top-area.scrolling-tabs-container.inner-page-scroll-tabs
.fade-left= icon('angle-left')
.fade-right= icon('angle-right')
@@ -18,5 +25,3 @@
.nav-controls
= render 'shared/projects/search_form'
= render 'shared/projects/dropdown'
- - if current_user.can_create_project?
- = link_to "New project", new_project_path, class: "btn btn-success"
diff --git a/app/views/dashboard/_snippets_head.html.haml b/app/views/dashboard/_snippets_head.html.haml
index 4f38339b87a..8d99f84755a 100644
--- a/app/views/dashboard/_snippets_head.html.haml
+++ b/app/views/dashboard/_snippets_head.html.haml
@@ -1,3 +1,10 @@
+.page-title-holder
+ %h1.page-title= _('Snippets')
+
+ - if current_user
+ .page-title-controls
+ = link_to "New snippet", new_snippet_path, class: "btn btn-success", title: "New snippet"
+
.top-area
%ul.nav-links.nav.nav-tabs
= nav_link(page: dashboard_snippets_path, html_options: {class: 'home'}) do
@@ -6,7 +13,3 @@
= nav_link(page: explore_snippets_path) do
= link_to explore_snippets_path, title: 'Explore snippets', data: {placement: 'right'} do
Explore snippets
-
- - if current_user
- .nav-controls.d-none.d-sm-block
- = link_to "New snippet", new_snippet_path, class: "btn btn-success", title: "New snippet"
diff --git a/app/views/dashboard/activity.html.haml b/app/views/dashboard/activity.html.haml
index 31d4b3da4f1..4dbda5c754b 100644
--- a/app/views/dashboard/activity.html.haml
+++ b/app/views/dashboard/activity.html.haml
@@ -4,6 +4,9 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity")
+
+= render_if_exists "shared/gold_trial_callout"
+
- page_title "Activity"
- header_title "Activity", activity_dashboard_path
diff --git a/app/views/dashboard/groups/index.html.haml b/app/views/dashboard/groups/index.html.haml
index 50f39f93283..2f7add600e4 100644
--- a/app/views/dashboard/groups/index.html.haml
+++ b/app/views/dashboard/groups/index.html.haml
@@ -1,6 +1,8 @@
- @hide_top_links = true
- page_title "Groups"
- header_title "Groups", dashboard_groups_path
+
+= render_if_exists "shared/gold_trial_callout"
= render 'dashboard/groups_head'
- if params[:filter].blank? && @groups.empty?
diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml
index 86a21e24ac9..afd46412fab 100644
--- a/app/views/dashboard/issues.html.haml
+++ b/app/views/dashboard/issues.html.haml
@@ -1,16 +1,24 @@
- @hide_top_links = true
- page_title _("Issues")
-- @breadcrumb_link = issues_dashboard_path(assignee_id: current_user.id)
+- @breadcrumb_link = issues_dashboard_path(assignee_username: current_user.username)
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{current_user.name} issues")
+= render_if_exists "shared/gold_trial_callout"
+
+.page-title-holder
+ %h1.page-title= _('Issues')
+
+ - if current_user
+ .page-title-controls
+ = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues', type: :issues
+
.top-area
= render 'shared/issuable/nav', type: :issues, display_count: !@no_filters_set
.nav-controls
= render 'shared/issuable/feed_buttons'
- = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues', type: :issues
-= render 'shared/issuable/filter', type: :issues
+= render 'shared/issuable/search_bar', type: :issues
- if current_user && @no_filters_set
= render 'shared/dashboard/no_filter_selected'
diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml
index 61aae31be60..3e5f13b92e3 100644
--- a/app/views/dashboard/merge_requests.html.haml
+++ b/app/views/dashboard/merge_requests.html.haml
@@ -1,13 +1,20 @@
- @hide_top_links = true
- page_title _("Merge Requests")
-- @breadcrumb_link = merge_requests_dashboard_path(assignee_id: current_user.id)
+- @breadcrumb_link = merge_requests_dashboard_path(assignee_username: current_user.username)
+
+= render_if_exists "shared/gold_trial_callout"
+
+.page-title-holder
+ %h1.page-title= _('Merge Requests')
+
+ - if current_user
+ .page-title-controls
+ = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests', type: :merge_requests
.top-area
= render 'shared/issuable/nav', type: :merge_requests, display_count: !@no_filters_set
- .nav-controls
- = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests', type: :merge_requests
-= render 'shared/issuable/filter', type: :merge_requests
+= render 'shared/issuable/search_bar', type: :merge_requests
- if current_user && @no_filters_set
= render 'shared/dashboard/no_filter_selected'
diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml
index f66e2b40d76..ae0e38bf0ee 100644
--- a/app/views/dashboard/milestones/index.html.haml
+++ b/app/views/dashboard/milestones/index.html.haml
@@ -2,12 +2,18 @@
- page_title 'Milestones'
- header_title 'Milestones', dashboard_milestones_path
+.page-title-holder
+ %h1.page-title= _('Milestones')
+
+ - if current_user
+ .page-title-controls
+ = render 'shared/new_project_item_select',
+ path: 'milestones/new', label: 'New milestone',
+ include_groups: true, type: :milestones
+
.top-area
= render 'shared/milestones_filter', counts: @milestone_states
- .nav-controls
- = render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true, type: :milestones
-
.milestones
%ul.content-list
- if @milestones.blank?
diff --git a/app/views/dashboard/projects/index.html.haml b/app/views/dashboard/projects/index.html.haml
index deed774a4a5..446b4715b2d 100644
--- a/app/views/dashboard/projects/index.html.haml
+++ b/app/views/dashboard/projects/index.html.haml
@@ -4,6 +4,8 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, dashboard_projects_url(rss_url_options), title: "All activity")
+= render_if_exists "shared/gold_trial_callout"
+
- page_title "Projects"
- header_title "Projects", dashboard_projects_path
diff --git a/app/views/dashboard/projects/starred.html.haml b/app/views/dashboard/projects/starred.html.haml
index 8933d9e31ff..ad08409c8fe 100644
--- a/app/views/dashboard/projects/starred.html.haml
+++ b/app/views/dashboard/projects/starred.html.haml
@@ -4,6 +4,8 @@
- page_title "Starred Projects"
- header_title "Projects", dashboard_projects_path
+= render_if_exists "shared/gold_trial_callout"
+
%div{ class: container_class }
= render "projects/last_push"
= render 'dashboard/projects_head'
diff --git a/app/views/dashboard/snippets/index.html.haml b/app/views/dashboard/snippets/index.html.haml
index b11dc2c8e9b..6eb067da95c 100644
--- a/app/views/dashboard/snippets/index.html.haml
+++ b/app/views/dashboard/snippets/index.html.haml
@@ -5,9 +5,4 @@
= render 'dashboard/snippets_head'
= render partial: 'snippets/snippets_scope_menu', locals: { include_private: true }
-.d-block.d-sm-none
- &nbsp;
- = link_to new_snippet_path, class: "btn btn-success btn-block", title: "New snippet" do
- New snippet
-
= render partial: 'snippets/snippets', locals: { link_project: true }
diff --git a/app/views/dashboard/todos/index.html.haml b/app/views/dashboard/todos/index.html.haml
index 8b3974d97f8..47729321961 100644
--- a/app/views/dashboard/todos/index.html.haml
+++ b/app/views/dashboard/todos/index.html.haml
@@ -2,6 +2,11 @@
- page_title "Todos"
- header_title "Todos", dashboard_todos_path
+= render_if_exists "shared/gold_trial_callout"
+
+.page-title-holder
+ %h1.page-title= _('Todos')
+
- if current_user.todos.any?
.top-area
%ul.nav-links.mobile-separator.nav.nav-tabs
diff --git a/app/views/devise/mailer/email_changed.html.haml b/app/views/devise/mailer/email_changed.html.haml
new file mode 100644
index 00000000000..5398430fdfd
--- /dev/null
+++ b/app/views/devise/mailer/email_changed.html.haml
@@ -0,0 +1,12 @@
+= email_default_heading("Hello, #{@resource.name}!")
+
+- if @resource.try(:unconfirmed_email?)
+ %p
+ We're contacting you to notify you that your email is being changed to #{@resource.reload.unconfirmed_email}.
+- else
+ %p
+ We're contacting you to notify you that your email has been changed to #{@resource.email}.
+
+%p
+ If you did not initiate this change, please contact your administrator
+ immediately.
diff --git a/app/views/devise/mailer/email_changed.text.erb b/app/views/devise/mailer/email_changed.text.erb
new file mode 100644
index 00000000000..18137389e7b
--- /dev/null
+++ b/app/views/devise/mailer/email_changed.text.erb
@@ -0,0 +1,10 @@
+Hello, <%= @resource.name %>!
+
+<% if @resource.try(:unconfirmed_email?) %>
+We're contacting you to notify you that your email is being changed to <%= @resource.reload.unconfirmed_email %>.
+<% else %>
+We're contacting you to notify you that your email has been changed to <%= @resource.email %>.
+<% end %>
+
+If you did not initiate this change, please contact your administrator
+immediately.
diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
index 269a3721e06..12271ee5adb 100644
--- a/app/views/devise/shared/_omniauth_box.html.haml
+++ b/app/views/devise/shared/_omniauth_box.html.haml
@@ -5,7 +5,7 @@
.d-flex.justify-content-between.flex-wrap
- providers.each do |provider|
- has_icon = provider_has_icon?(provider)
- = link_to omniauth_authorize_path(:user, provider), method: :post, class: 'btn d-flex align-items-center omniauth-btn text-left oauth-login', id: "oauth-login-#{provider}" do
+ = link_to omniauth_authorize_path(:user, provider), method: :post, class: 'btn d-flex align-items-center omniauth-btn text-left oauth-login qa-saml-login-button', id: "oauth-login-#{provider}" do
- if has_icon
= provider_image_tag(provider)
%span
diff --git a/app/views/devise/shared/_signin_box.html.haml b/app/views/devise/shared/_signin_box.html.haml
index 5ddb3ece1cb..ec968e435cd 100644
--- a/app/views/devise/shared/_signin_box.html.haml
+++ b/app/views/devise/shared/_signin_box.html.haml
@@ -1,10 +1,10 @@
- if form_based_providers.any?
- if crowd_enabled?
- .login-box.tab-pane.active{ id: "crowd", role: 'tabpanel' }
+ .login-box.tab-pane{ id: "crowd", role: 'tabpanel', class: active_when(form_based_auth_provider_has_active_class?(:crowd)) }
.login-body
= render 'devise/sessions/new_crowd'
- @ldap_servers.each_with_index do |server, i|
- .login-box.tab-pane{ id: "#{server['provider_name']}", role: 'tabpanel', class: active_when(i.zero? && !crowd_enabled?) }
+ .login-box.tab-pane{ id: "#{server['provider_name']}", role: 'tabpanel', class: active_when(i.zero? && form_based_auth_provider_has_active_class?(:ldapmain)) }
.login-body
= render 'devise/sessions/new_ldap', server: server
- if password_authentication_enabled_for_web?
@@ -12,6 +12,8 @@
.login-body
= render 'devise/sessions/new_base'
+ = render_if_exists 'devise/sessions/new_smartcard'
+
- elsif password_authentication_enabled_for_web?
.login-box.tab-pane.active{ id: 'login-pane', role: 'tabpanel' }
.login-body
diff --git a/app/views/devise/shared/_signup_box.html.haml b/app/views/devise/shared/_signup_box.html.haml
index 90ed20404c5..004a3528d4b 100644
--- a/app/views/devise/shared/_signup_box.html.haml
+++ b/app/views/devise/shared/_signup_box.html.haml
@@ -5,26 +5,26 @@
= devise_error_messages!
.form-group
= f.label :name, 'Full name', class: 'label-bold'
- = f.text_field :name, class: "form-control top", required: true, title: "This field is required."
+ = f.text_field :name, class: "form-control top qa-new-user-name", required: true, title: "This field is required."
.username.form-group
= f.label :username, class: 'label-bold'
- = f.text_field :username, class: "form-control middle", pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: 'Please create a username with only alphanumeric characters.'
+ = f.text_field :username, class: "form-control middle qa-new-user-username", pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: 'Please create a username with only alphanumeric characters.'
%p.validation-error.hide Username is already taken.
%p.validation-success.hide Username is available.
%p.validation-pending.hide Checking username availability...
.form-group
= f.label :email, class: 'label-bold'
- = f.email_field :email, class: "form-control middle", required: true, title: "Please provide a valid email address."
+ = f.email_field :email, class: "form-control middle qa-new-user-email", required: true, title: "Please provide a valid email address."
.form-group
= f.label :email_confirmation, class: 'label-bold'
- = f.email_field :email_confirmation, class: "form-control middle", required: true, title: "Please retype the email address."
+ = f.email_field :email_confirmation, class: "form-control middle qa-new-user-email-confirmation", required: true, title: "Please retype the email address."
.form-group.append-bottom-20#password-strength
= f.label :password, class: 'label-bold'
- = f.password_field :password, class: "form-control bottom", required: true, pattern: ".{#{@minimum_password_length},}", title: "Minimum length is #{@minimum_password_length} characters."
+ = f.password_field :password, class: "form-control bottom qa-new-user-password", required: true, pattern: ".{#{@minimum_password_length},}", title: "Minimum length is #{@minimum_password_length} characters."
%p.gl-field-hint.text-secondary Minimum length is #{@minimum_password_length} characters
- if Gitlab::CurrentSettings.current_application_settings.enforce_terms?
.form-group
- = check_box_tag :terms_opt_in, '1', false, required: true
+ = check_box_tag :terms_opt_in, '1', false, required: true, class: 'qa-new-user-accept-terms'
= label_tag :terms_opt_in do
- terms_link = link_to s_("I accept the|Terms of Service and Privacy Policy"), terms_path, target: "_blank"
- accept_terms_label = _("I accept the %{terms_link}") % { terms_link: terms_link }
@@ -33,4 +33,4 @@
- if Gitlab::Recaptcha.enabled?
= recaptcha_tags
.submit-container
- = f.submit "Register", class: "btn-register btn"
+ = f.submit "Register", class: "btn-register btn qa-new-user-register-button"
diff --git a/app/views/devise/shared/_tabs_ldap.html.haml b/app/views/devise/shared/_tabs_ldap.html.haml
index 3764e86dd8b..aee05b6c81c 100644
--- a/app/views/devise/shared/_tabs_ldap.html.haml
+++ b/app/views/devise/shared/_tabs_ldap.html.haml
@@ -1,13 +1,16 @@
%ul.nav-links.new-session-tabs.nav-tabs.nav{ class: ('custom-provider-tabs' if form_based_providers.any?) }
- if crowd_enabled?
%li.nav-item
- = link_to "Crowd", "#crowd", class: 'nav-link active', 'data-toggle' => 'tab'
+ = link_to "Crowd", "#crowd", class: "nav-link #{active_when(form_based_auth_provider_has_active_class?(:crowd))}", 'data-toggle' => 'tab'
- @ldap_servers.each_with_index do |server, i|
%li.nav-item
- = link_to server['label'], "##{server['provider_name']}", class: "nav-link #{active_when(i.zero? && !crowd_enabled?)} qa-ldap-tab", 'data-toggle' => 'tab'
+ = link_to server['label'], "##{server['provider_name']}", class: "nav-link #{active_when(i.zero? && form_based_auth_provider_has_active_class?(:ldapmain))} qa-ldap-tab", 'data-toggle' => 'tab'
+
+ = render_if_exists 'devise/shared/tab_smartcard'
+
- if password_authentication_enabled_for_web?
%li.nav-item
= link_to 'Standard', '#login-pane', class: 'nav-link qa-standard-tab', 'data-toggle' => 'tab'
- if allow_signup?
%li.nav-item
- = link_to 'Register', '#register-pane', class: 'nav-link', 'data-toggle' => 'tab'
+ = link_to 'Register', '#register-pane', class: 'nav-link qa-register-tab', 'data-toggle' => 'tab'
diff --git a/app/views/discussions/_discussion.html.haml b/app/views/discussions/_discussion.html.haml
index 1765251c93d..10187129a33 100644
--- a/app/views/discussions/_discussion.html.haml
+++ b/app/views/discussions/_discussion.html.haml
@@ -1,12 +1,12 @@
- expanded = discussion.expanded?
-%li.note.note-discussion.timeline-entry
+%li.note.note-discussion.timeline-entry.unstyled-comments
.timeline-entry-inner
- .timeline-icon
- = link_to user_path(discussion.author) do
- = image_tag avatar_icon_for_user(discussion.author), class: "avatar s40"
.timeline-content
.discussion.js-toggle-container{ data: { discussion_id: discussion.id } }
.discussion-header
+ .timeline-icon
+ = link_to user_path(discussion.author) do
+ = image_tag avatar_icon_for_user(discussion.author), class: "avatar s40"
.discussion-actions
%button.note-action-button.discussion-toggle-button.js-toggle-button{ type: "button", class: ("js-toggle-lazy-diff" unless expanded) }
- if expanded
diff --git a/app/views/doorkeeper/applications/show.html.haml b/app/views/doorkeeper/applications/show.html.haml
index bb76ac6d5f6..cac00f9c854 100644
--- a/app/views/doorkeeper/applications/show.html.haml
+++ b/app/views/doorkeeper/applications/show.html.haml
@@ -10,18 +10,25 @@
%table.table
%tr
%td
- = _('Application Id')
+ = _('Application ID')
%td
- %code#application_id= @application.uid
+ .clipboard-group
+ .input-group
+ %input.label.label-monospace{ id: "application_id", type: "text", autocomplete: 'off', value: @application.uid, readonly: true }
+ .input-group-append
+ = clipboard_button(target: '#application_id', title: _("Copy ID to clipboard"), class: "btn btn btn-default")
%tr
%td
- = _('Secret:')
+ = _('Secret')
%td
- %code#secret= @application.secret
-
+ .clipboard-group
+ .input-group
+ %input.label.label-monospace{ id: "secret", type: "text", autocomplete: 'off', value: @application.secret, readonly: true }
+ .input-group-append
+ = clipboard_button(target: '#secret', title: _("Copy secret to clipboard"), class: "btn btn btn-default")
%tr
%td
- = _('Callback url')
+ = _('Callback URL')
%td
- @application.redirect_uri.split.each do |uri|
%div
diff --git a/app/views/errors/precondition_failed.html.haml b/app/views/errors/precondition_failed.html.haml
new file mode 100644
index 00000000000..aa3869f33a9
--- /dev/null
+++ b/app/views/errors/precondition_failed.html.haml
@@ -0,0 +1,8 @@
+- content_for(:title, 'Encoding Error')
+%img{ :alt => "GitLab Logo", :src => image_path('logo.svg') }
+ %h1
+ 412
+.container
+ %h3 Precondition failed
+ %hr
+ %p Page can't be loaded because of invalid parameters.
diff --git a/app/views/events/_event.html.haml b/app/views/events/_event.html.haml
index 78a1d1a0553..2fcb1d1fd2b 100644
--- a/app/views/events/_event.html.haml
+++ b/app/views/events/_event.html.haml
@@ -1,5 +1,5 @@
- if event.visible_to_user?(current_user)
- .event-item{ class: event_row_class(event) }
+ .event-item
.event-item-timestamp
#{time_ago_with_tooltip(event.created_at)}
diff --git a/app/views/events/event/_common.html.haml b/app/views/events/event/_common.html.haml
index 829a3da1558..96d6553a2ac 100644
--- a/app/views/events/event/_common.html.haml
+++ b/app/views/events/event/_common.html.haml
@@ -1,20 +1,19 @@
= icon_for_profile_event(event)
-.event-title
- %span.author_name= link_to_author(event)
- %span{ class: event.action_name }
+= event_user_info(event)
+
+.event-title.d-flex.flex-wrap
+ = inline_event_icon(event)
- if event.target
- = event.action_name
- %strong
- = link_to [event.project.namespace.becomes(Namespace), event.project, event.target], class: 'has-tooltip', title: event.target_title do
- = event.target_type.titleize.downcase
- = event.target.reference_link_text
+ %span.event-type.d-inline-block.append-right-4{ class: event.action_name }
+ = event.action_name
+ %span.event-target-type.append-right-4= event.target_type.titleize.downcase
+ = link_to [event.project.namespace.becomes(Namespace), event.project, event.target], class: 'has-tooltip event-target-link append-right-4', title: event.target_title do
+ = event.target.reference_link_text
+ - unless event.milestone?
+ %span.event-target-title.append-right-4= "&quot;".html_safe + event.target.title + "&quot".html_safe
- else
- = event_action_name(event)
+ %span.event-type.d-inline-block.append-right-4{ class: event.action_name }
+ = event_action_name(event)
= render "events/event_scope", event: event
-
-- if event.target.respond_to?(:title)
- .event-body
- .event-note
- = event.target.title
diff --git a/app/views/events/event/_created_project.html.haml b/app/views/events/event/_created_project.html.haml
index 6ad7e157131..2f156603414 100644
--- a/app/views/events/event/_created_project.html.haml
+++ b/app/views/events/event/_created_project.html.haml
@@ -1,8 +1,10 @@
= icon_for_profile_event(event)
-.event-title
- %span.author_name= link_to_author(event)
- %span{ class: event.action_name }
+= event_user_info(event)
+
+.event-title.d-flex.flex-wrap
+ = inline_event_icon(event)
+ %span.event-type.d-inline-block.append-right-4{ class: event.action_name }
= event_action_name(event)
- if event.project
diff --git a/app/views/events/event/_note.html.haml b/app/views/events/event/_note.html.haml
index cdacd998a69..fb0d2c3b8b0 100644
--- a/app/views/events/event/_note.html.haml
+++ b/app/views/events/event/_note.html.haml
@@ -1,9 +1,13 @@
= icon_for_profile_event(event)
-.event-title
- %span.author_name= link_to_author(event)
- = event.action_name
+= event_user_info(event)
+
+.event-title.d-flex.flex-wrap
+ = inline_event_icon(event)
+ %span.event-type.d-inline-block.append-right-4{ class: event.action_name }
+ = event.action_name
= event_note_title_html(event)
+ %span.event-target-title.append-right-4= "&quot;".html_safe + event.target.title + "&quot".html_safe
= render "events/event_scope", event: event
diff --git a/app/views/events/event/_private.html.haml b/app/views/events/event/_private.html.haml
index ccd2aacb4ea..d91f30c07cb 100644
--- a/app/views/events/event/_private.html.haml
+++ b/app/views/events/event/_private.html.haml
@@ -1,10 +1,11 @@
-.event-inline.event-item
+.event-item
.event-item-timestamp
= time_ago_with_tooltip(event.created_at)
- .system-note-image= sprite_icon('eye-slash', size: 16, css_class: 'icon')
+ .system-note-image= sprite_icon('eye-slash', size: 24, css_class: 'icon')
- .event-title
- - author_name = capture do
- %span.author_name= link_to_author(event)
- = s_('Profiles|%{author_name} made a private contribution').html_safe % { author_name: author_name }
+ = event_user_info(event)
+
+ .event-title.d-flex.flex-wrap
+ = inline_event_icon(event)
+ = s_('Profiles|Made a private contribution')
diff --git a/app/views/events/event/_push.html.haml b/app/views/events/event/_push.html.haml
index 5f0ee79cd9b..69914fccc48 100644
--- a/app/views/events/event/_push.html.haml
+++ b/app/views/events/event/_push.html.haml
@@ -2,10 +2,12 @@
= icon_for_profile_event(event)
-.event-title
- %span.author_name= link_to_author(event)
- %span.pushed #{event.action_name} #{event.ref_type}
- %strong
+= event_user_info(event)
+
+.event-title.d-flex.flex-wrap
+ = inline_event_icon(event)
+ %span.event-type.d-inline-block.append-right-4.pushed #{event.action_name} #{event.ref_type}
+ %span.append-right-4
- commits_link = project_commits_path(project, event.ref_name)
- should_link = event.tag? ? project.repository.tag_exists?(event.ref_name) : project.repository.branch_exists?(event.ref_name)
= link_to_if should_link, event.ref_name, commits_link, class: 'ref-name'
diff --git a/app/views/explore/groups/index.html.haml b/app/views/explore/groups/index.html.haml
index 387c37b7a91..869be4e8581 100644
--- a/app/views/explore/groups/index.html.haml
+++ b/app/views/explore/groups/index.html.haml
@@ -2,6 +2,8 @@
- page_title _("Groups")
- header_title _("Groups"), dashboard_groups_path
+= render_if_exists "shared/gold_trial_callout"
+
- if current_user
= render 'dashboard/groups_head'
- else
@@ -10,7 +12,7 @@
- if cookies[:explore_groups_landing_dismissed] != 'true'
.explore-groups.landing.content-block.js-explore-groups-landing.hide
- %button.dismiss-button{ type: 'button', 'aria-label' => _('Dismiss') }= icon('times')
+ %button.dismiss-button{ type: 'button', 'aria-label' => _('Dismiss') }= sprite_icon('close', size: 16)
.svg-container
= custom_icon('icon_explore_groups_splash')
.inner-content
diff --git a/app/views/explore/projects/_filter.html.haml b/app/views/explore/projects/_filter.html.haml
index b694103ccaf..f518205f14c 100644
--- a/app/views/explore/projects/_filter.html.haml
+++ b/app/views/explore/projects/_filter.html.haml
@@ -1,8 +1,8 @@
- if current_user
.dropdown
- %button.dropdown-toggle{ href: '#', "data-toggle" => "dropdown", 'data-display' => 'static' }
- = icon('globe')
- %span.light= _("Visibility:")
+ %button.dropdown-menu-toggle{ href: '#', "data-toggle" => "dropdown", 'data-display' => 'static' }
+ = icon('globe', class: 'mt-1')
+ %span.light.ml-3= _("Visibility:")
- if params[:visibility_level].present?
= visibility_level_label(params[:visibility_level].to_i)
- else
diff --git a/app/views/explore/projects/index.html.haml b/app/views/explore/projects/index.html.haml
index 452f390695c..d18dec7bd8e 100644
--- a/app/views/explore/projects/index.html.haml
+++ b/app/views/explore/projects/index.html.haml
@@ -2,6 +2,8 @@
- page_title _("Projects")
- header_title _("Projects"), dashboard_projects_path
+= render_if_exists "shared/gold_trial_callout"
+
- if current_user
= render 'dashboard/projects_head'
- else
diff --git a/app/views/explore/projects/starred.html.haml b/app/views/explore/projects/starred.html.haml
index 452f390695c..d18dec7bd8e 100644
--- a/app/views/explore/projects/starred.html.haml
+++ b/app/views/explore/projects/starred.html.haml
@@ -2,6 +2,8 @@
- page_title _("Projects")
- header_title _("Projects"), dashboard_projects_path
+= render_if_exists "shared/gold_trial_callout"
+
- if current_user
= render 'dashboard/projects_head'
- else
diff --git a/app/views/explore/projects/trending.html.haml b/app/views/explore/projects/trending.html.haml
index 452f390695c..d18dec7bd8e 100644
--- a/app/views/explore/projects/trending.html.haml
+++ b/app/views/explore/projects/trending.html.haml
@@ -2,6 +2,8 @@
- page_title _("Projects")
- header_title _("Projects"), dashboard_projects_path
+= render_if_exists "shared/gold_trial_callout"
+
- if current_user
= render 'dashboard/projects_head'
- else
diff --git a/app/views/groups/_group_admin_settings.html.haml b/app/views/groups/_group_admin_settings.html.haml
index 935a8889d79..ff59013ed67 100644
--- a/app/views/groups/_group_admin_settings.html.haml
+++ b/app/views/groups/_group_admin_settings.html.haml
@@ -1,5 +1,5 @@
.form-group.row
- = f.label :lfs_enabled, 'Large File Storage', class: 'col-form-label col-sm-2'
+ = f.label :lfs_enabled, 'Large File Storage', class: 'col-form-label col-sm-2 pt-0'
.col-sm-10
.form-check
= f.check_box :lfs_enabled, checked: @group.lfs_enabled?, class: 'form-check-input'
@@ -11,7 +11,7 @@
%span.descr This setting can be overridden in each project.
.form-group.row
- = f.label :require_two_factor_authentication, 'Two-factor authentication', class: 'col-form-label col-sm-2'
+ = f.label :require_two_factor_authentication, 'Two-factor authentication', class: 'col-form-label col-sm-2 pt-0'
.col-sm-10
.form-check
= f.check_box :require_two_factor_authentication, class: 'form-check-input'
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index fc17dd2d310..39d0f620283 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -3,31 +3,31 @@
- expanded = Rails.env.test?
-%section.settings.gs-general.no-animate#js-general-settings{ class: ('expanded' if expanded) }
+%section.settings.gs-general.no-animate#js-general-settings{ class: ('expanded') }
.settings-header
- %h4
- = _('General')
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only{ role: 'button' }
+ = _('Naming, visibility')
%button.btn.js-settings-toggle{ type: 'button' }
- = expanded ? _('Collapse') : _('Expand')
+ = _('Collapse')
%p
- = _('Update your group name, description, avatar, and other general settings.')
+ = _('Update your group name, description, avatar, and visibility.')
.settings-content
= render 'groups/settings/general'
%section.settings.gs-permissions.no-animate#js-permissions-settings{ class: ('expanded' if expanded) }
.settings-header
- %h4
- = _('Permissions')
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only{ role: 'button' }
+ = _('Permissions, LFS, 2FA')
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
- = _('Enable or disable certain group features and choose access levels.')
+ = _('Advanced permissions, Large File Storage and Two-Factor authentication settings.')
.settings-content
= render 'groups/settings/permissions'
-%section.settings.no-animate{ class: ('expanded' if expanded) }
+%section.settings.no-animate#js-badge-settings{ class: ('expanded' if expanded) }
.settings-header
- %h4
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only{ role: 'button' }
= s_('GroupSettings|Badges')
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
@@ -37,10 +37,13 @@
.settings-content
= render 'shared/badges/badge_settings'
+= render_if_exists 'groups/custom_project_templates_setting'
+= render_if_exists 'groups/templates_setting', expanded: expanded
+
%section.settings.gs-advanced.no-animate#js-advanced-settings{ class: ('expanded' if expanded) }
.settings-header
- %h4
- = _('Advanced')
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only{ role: 'button' }
+ = _('Path, transfer, remove')
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml
index 5e1ae1dbe38..91d17cfd745 100644
--- a/app/views/groups/issues.html.haml
+++ b/app/views/groups/issues.html.haml
@@ -9,7 +9,7 @@
= render 'shared/issuable/nav', type: :issues
.nav-controls
= render 'shared/issuable/feed_buttons'
- = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", type: :issues, with_feature_enabled: 'issues'
+ = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", type: :issues, with_feature_enabled: 'issues', with_shared: false, include_projects_in_subgroups: true
= render 'shared/issuable/search_bar', type: :issues
diff --git a/app/views/groups/labels/edit.html.haml b/app/views/groups/labels/edit.html.haml
index 836981fc6fd..586b0f6ebfa 100644
--- a/app/views/groups/labels/edit.html.haml
+++ b/app/views/groups/labels/edit.html.haml
@@ -1,4 +1,6 @@
-- page_title 'Edit', @label.name, 'Labels'
+- add_to_breadcrumbs _("Labels"), group_labels_path(@group)
+- breadcrumb_title _("Edit")
+- page_title "Edit", @label.name, _("Labels")
%h3.page-title
Edit Label
diff --git a/app/views/groups/labels/index.html.haml b/app/views/groups/labels/index.html.haml
index 003bd25dd06..4df3d831942 100644
--- a/app/views/groups/labels/index.html.haml
+++ b/app/views/groups/labels/index.html.haml
@@ -3,29 +3,23 @@
- can_admin_label = can?(current_user, :admin_label, @group)
- issuables = ['issues', 'merge requests']
- search = params[:search]
+- subscribed = params[:subscribed]
+- labels_or_filters = @labels.exists? || search.present? || subscribed.present?
-- if can_admin_label
+- if @labels.present? && can_admin_label
- content_for(:header_content) do
.nav-controls
= link_to _('New label'), new_group_label_path(@group), class: "btn btn-success"
-- if @labels.exists? || search.present?
+- if labels_or_filters
#promote-label-modal
%div{ class: container_class }
- .top-area.adjust
- .nav-text
- = _('Labels can be applied to %{features}. Group labels are available for any project within the group.') % { features: issuables.to_sentence }
- .nav-controls
- = form_tag group_labels_path(@group), method: :get do
- .input-group
- = search_field_tag :search, params[:search], { placeholder: _('Filter'), id: 'label-search', class: 'form-control search-text-input input-short', spellcheck: false }
- %span.input-group-append
- %button.btn.btn-default{ type: "submit", "aria-label" => _('Submit search') }
- = icon("search")
- = render 'shared/labels/sort_dropdown'
+ = render 'shared/labels/nav'
.labels-container.prepend-top-5
- if @labels.any?
+ .text-muted
+ = _('Labels can be applied to %{features}. Group labels are available for any project within the group.') % { features: issuables.to_sentence }
.other-labels
%h5= _('Labels')
%ul.content-list.manage-labels-list.js-other-labels
@@ -34,6 +28,9 @@
- elsif search.present?
.nothing-here-block
= _('No labels with such name or description')
+ - elsif subscribed.present?
+ .nothing-here-block
+ = _('You do not have any subscriptions yet')
- else
= render 'shared/empty_states/labels'
diff --git a/app/views/groups/labels/new.html.haml b/app/views/groups/labels/new.html.haml
index 538c353cf2d..bb0b8d2b94d 100644
--- a/app/views/groups/labels/new.html.haml
+++ b/app/views/groups/labels/new.html.haml
@@ -1,5 +1,6 @@
-- breadcrumb_title "Labels"
-- page_title 'New Label'
+- add_to_breadcrumbs _("Labels"), group_labels_path(@group)
+- breadcrumb_title _("New")
+- page_title _("New Label")
%h3.page-title
New Label
diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml
index e2a317dbf67..a9ce2fe5ab0 100644
--- a/app/views/groups/merge_requests.html.haml
+++ b/app/views/groups/merge_requests.html.haml
@@ -7,7 +7,7 @@
= render 'shared/issuable/nav', type: :merge_requests
- if current_user
.nav-controls
- = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", type: :merge_requests, with_feature_enabled: 'merge_requests'
+ = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", type: :merge_requests, with_feature_enabled: 'merge_requests', with_shared: false, include_projects_in_subgroups: true
= render 'shared/issuable/search_bar', type: :merge_requests
diff --git a/app/views/groups/milestones/edit.html.haml b/app/views/groups/milestones/edit.html.haml
index 5f6d7d209d0..c703d5f7f93 100644
--- a/app/views/groups/milestones/edit.html.haml
+++ b/app/views/groups/milestones/edit.html.haml
@@ -1,7 +1,10 @@
-- page_title "Milestones"
+- breadcrumb_title _("Edit")
+- page_title _("Milestones")
+
- render "header_title"
%h3.page-title
Edit Milestone
+%hr
= render "form"
diff --git a/app/views/groups/milestones/new.html.haml b/app/views/groups/milestones/new.html.haml
index d758e314d41..248cb3b0ba5 100644
--- a/app/views/groups/milestones/new.html.haml
+++ b/app/views/groups/milestones/new.html.haml
@@ -1,7 +1,12 @@
-- breadcrumb_title "Milestones"
-- page_title "Milestones"
+- @no_container = true
+- add_to_breadcrumbs _("Milestones"), group_milestones_path(@group)
+- breadcrumb_title _("New")
+- page_title _("Milestones"), @milestone.name, _("Milestones")
-%h3.page-title
- New Milestone
+%div{ class: container_class }
+ %h3.page-title
+ New Milestone
-= render "form"
+ %hr
+
+ = render "form"
diff --git a/app/views/groups/new.html.haml b/app/views/groups/new.html.haml
index 683129fdf6e..51dcc9d0cda 100644
--- a/app/views/groups/new.html.haml
+++ b/app/views/groups/new.html.haml
@@ -1,13 +1,12 @@
-- @breadcrumb_link = dashboard_groups_path
-- breadcrumb_title "Groups"
+- @hide_breadcrumbs = true
- @hide_top_links = true
-- page_title 'New Group'
-- header_title "Groups", dashboard_groups_path
+- page_title _('New Group')
+- header_title _("Groups"), dashboard_groups_path
+.page-title-holder
+ %h1.page-title= _('New group')
.row.prepend-top-default
.col-lg-3.profile-settings-sidebar
- %h4.prepend-top-0
- = _('New group')
%p
- group_docs_path = help_page_path('user/group/index')
- group_docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: group_docs_path }
@@ -16,24 +15,29 @@
- subgroup_docs_path = help_page_path('user/group/subgroups/index')
- subgroup_docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: subgroup_docs_path }
= s_('Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}.').html_safe % { subgroup_docs_link_start: subgroup_docs_link_start, subgroup_docs_link_end: '</a>'.html_safe }
+ %p
+ = _('Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group.')
.col-lg-9
= form_for @group, html: { class: 'group-form gl-show-field-errors' } do |f|
= form_errors(@group)
= render 'shared/group_form', f: f, autofocus: true
- .form-group.row.group-description-holder
- = f.label :avatar, "Group avatar", class: 'col-form-label col-sm-2'
- .col-sm-10
- = render 'shared/choose_group_avatar_button', f: f
-
- = render 'shared/visibility_level', f: f, visibility_level: default_group_visibility, can_change_visibility_level: true, form_model: @group
+ .row
+ .form-group.group-description-holder.col-sm-12
+ = f.label :avatar, _("Group avatar"), class: 'label-bold'
+ %div
+ = render 'shared/choose_group_avatar_button', f: f
- = render 'create_chat_team', f: f if Gitlab.config.mattermost.enabled
+ .form-group.col-sm-12
+ %label.label-bold
+ = _('Visibility level')
+ %p
+ = _('Who will be able to see this group?')
+ = link_to _('View the documentation'), help_page_path("public_access/public_access"), target: '_blank'
+ = render 'shared/visibility_level', f: f, visibility_level: default_group_visibility, can_change_visibility_level: true, form_model: @group, with_label: false
- .form-group.row
- .offset-sm-2.col-sm-10
- = render 'shared/group_tips'
+ = render 'create_chat_team', f: f if Gitlab.config.mattermost.enabled
.form-actions
= f.submit 'Create group', class: "btn btn-success"
diff --git a/app/views/groups/runners/_group_runners.html.haml b/app/views/groups/runners/_group_runners.html.haml
index e6c089c3494..bcfb6d99716 100644
--- a/app/views/groups/runners/_group_runners.html.haml
+++ b/app/views/groups/runners/_group_runners.html.haml
@@ -11,7 +11,9 @@
-# https://gitlab.com/gitlab-org/gitlab-ce/issues/45894
- if can?(current_user, :admin_pipeline, @group)
= render partial: 'ci/runner/how_to_setup_runner',
- locals: { registration_token: @group.runners_token, type: 'group' }
+ locals: { registration_token: @group.runners_token,
+ type: 'group',
+ reset_token_url: reset_registration_token_group_settings_ci_cd_path }
- if @group.runners.empty?
%h4.underlined-title
diff --git a/app/views/groups/settings/_advanced.html.haml b/app/views/groups/settings/_advanced.html.haml
index b7c673db705..5d211d0e186 100644
--- a/app/views/groups/settings/_advanced.html.haml
+++ b/app/views/groups/settings/_advanced.html.haml
@@ -12,8 +12,8 @@
.group-root-path.input-group-prepend.has-tooltip{ title: group_path(@group), :'data-placement' => 'bottom' }
.input-group-text
%span>= root_url
- - if parent
- %strong= parent.full_path + '/'
+ - if @group.parent
+ %strong= @group.parent.full_path + '/'
= f.hidden_field :parent_id
= f.text_field :path, placeholder: 'open-source', class: 'form-control',
autofocus: local_assigns[:autofocus] || false, required: true,
@@ -23,16 +23,6 @@
= f.submit 'Change group path', class: 'btn btn-warning'
-.sub-section
- %h4.danger-title Remove group
- = form_tag(@group, method: :delete) do
- %p
- Removing group will cause all child projects and resources to be removed.
- %br
- %strong Removed group can not be restored!
-
- = button_to 'Remove group', '#', class: 'btn btn-remove js-confirm-danger', data: { 'confirm-danger-message' => remove_group_message(@group) }
-
- if supports_nested_groups?
.sub-section
%h4.warning-title Transfer group
@@ -47,3 +37,13 @@
%li You will need to update your local repositories to point to the new location.
%li If the parent group's visibility is lower than the group current visibility, visibility levels for subgroups and projects will be changed to match the new parent group's visibility.
= f.submit 'Transfer group', class: 'btn btn-warning'
+
+.sub-section
+ %h4.danger-title= _('Remove group')
+ = form_tag(@group, method: :delete) do
+ %p
+ = _('Removing group will cause all child projects and resources to be removed.')
+ %br
+ %strong= _('Removed group can not be restored!')
+
+ = button_to _('Remove group'), '#', class: 'btn btn-remove js-confirm-danger', data: { 'confirm-danger-message' => remove_group_message(@group) }
diff --git a/app/views/groups/settings/_general.html.haml b/app/views/groups/settings/_general.html.haml
index 0e225fe33a5..0424ece037d 100644
--- a/app/views/groups/settings/_general.html.haml
+++ b/app/views/groups/settings/_general.html.haml
@@ -1,39 +1,33 @@
-= form_for @group, html: { multipart: true, class: 'gl-show-field-errors' }, authenticity_token: true do |f|
+= form_for @group, html: { multipart: true, class: 'gl-show-field-errors js-general-settings-form' }, authenticity_token: true do |f|
%input{ type: 'hidden', name: 'update_section', value: 'js-general-settings' }
= form_errors(@group)
%fieldset
.row
- .form-group.col-md-9
- = f.label :name, class: 'label-bold' do
- Group name
+ .form-group.col-md-5
+ = f.label :name, _('Group name'), class: 'label-bold'
= f.text_field :name, class: 'form-control'
- .form-group.col-md-3
- = f.label :id, class: 'label-bold' do
- Group ID
- = f.text_field :id, class: 'form-control', readonly: true
+ .form-group.col-md-7
+ = f.label :id, _('Group ID'), class: 'label-bold'
+ = f.text_field :id, class: 'form-control w-auto', readonly: true
- .form-group
- = f.label :description, class: 'label-bold' do
- Group description
- %span.light (optional)
- = f.text_area :description, class: 'form-control', rows: 3, maxlength: 250
+ .row.prepend-top-8
+ .form-group.col-md-9.append-bottom-0
+ = f.label :description, _('Group description (optional)'), class: 'label-bold'
+ = f.text_area :description, class: 'form-control', rows: 3, maxlength: 250
= render_if_exists 'shared/repository_size_limit_setting', form: f, type: :group
- .form-group.row
- .col-sm-12
- .avatar-container.s160
- = group_icon(@group, alt: '', class: 'avatar group-avatar s160')
- %p.light
- - if @group.avatar?
- You can change the group avatar here
- - else
- You can upload a group avatar here
- = render 'shared/choose_group_avatar_button', f: f
- - if @group.avatar?
- %hr
- = link_to _('Remove avatar'), group_avatar_path(@group.to_param), data: { confirm: _('Avatar will be removed. Are you sure?')}, method: :delete, class: 'btn btn-danger btn-inverted'
+ .form-group.prepend-top-default.append-bottom-20
+ .avatar-container.s90
+ = group_icon(@group, alt: '', class: 'avatar group-avatar s90')
+ = f.label :avatar, _('Group avatar'), class: 'label-bold d-block'
+ = render 'shared/choose_group_avatar_button', f: f
+ - if @group.avatar?
+ %hr
+ = link_to _('Remove avatar'), group_avatar_path(@group.to_param), data: { confirm: _('Avatar will be removed. Are you sure?')}, method: :delete, class: 'btn btn-danger btn-inverted'
- = f.submit 'Save group', class: 'btn btn-success'
+ = render 'shared/visibility_level', f: f, visibility_level: @group.visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group
+
+ = f.submit _('Save changes'), class: 'btn btn-success mt-4 js-dirty-submit'
diff --git a/app/views/groups/settings/_lfs.html.haml b/app/views/groups/settings/_lfs.html.haml
new file mode 100644
index 00000000000..4674d561c12
--- /dev/null
+++ b/app/views/groups/settings/_lfs.html.haml
@@ -0,0 +1,15 @@
+- docs_link_url = help_page_path('workflow/lfs/manage_large_binaries_with_git_lfs')
+- docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: docs_link_url }
+
+%h5= _('Large File Storage')
+
+%p= s_('Check the %{docs_link_start}documentation%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: '</a>'.html_safe }
+
+.form-group.append-bottom-default
+ .form-check
+ = f.check_box :lfs_enabled, checked: @group.lfs_enabled?, class: 'form-check-input'
+ = f.label :lfs_enabled, class: 'form-check-label' do
+ %span
+ = _('Allow projects within this group to use Git LFS')
+ %br/
+ %span.text-muted= _('This setting can be overridden in each project.')
diff --git a/app/views/groups/settings/_permissions.html.haml b/app/views/groups/settings/_permissions.html.haml
index ffce2d4b14f..6b0a6e7ed99 100644
--- a/app/views/groups/settings/_permissions.html.haml
+++ b/app/views/groups/settings/_permissions.html.haml
@@ -1,29 +1,24 @@
-= form_for @group, html: { multipart: true, class: 'gl-show-field-errors' }, authenticity_token: true do |f|
+= form_for @group, html: { multipart: true, class: 'gl-show-field-errors js-general-permissions-form' }, authenticity_token: true do |f|
%input{ type: 'hidden', name: 'update_section', value: 'js-permissions-settings' }
= form_errors(@group)
%fieldset
- = render 'shared/visibility_level', f: f, visibility_level: @group.visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group
+ %h5= _('Permissions')
+ .form-group
+ = render 'shared/allow_request_access', form: f
- .form-group.row
- .offset-sm-2.col-sm-10
- = render 'shared/allow_request_access', form: f
-
- .form-group.row
- %label.col-form-label.col-sm-2
- = s_('GroupSettings|Share with group lock')
- .col-sm-10
- .form-check
- = f.check_box :share_with_group_lock, disabled: !can_change_share_with_group_lock?(@group), class: 'form-check-input'
- = f.label :share_with_group_lock, class: 'form-check-label' do
- %strong
- - group_link = link_to @group.name, group_path(@group)
- = s_('GroupSettings|Prevent sharing a project within %{group} with other groups').html_safe % { group: group_link }
- %br
- %span.descr= share_with_group_lock_help_text(@group)
-
- = render 'groups/group_admin_settings', f: f
+ .form-group.append-bottom-default
+ .form-check
+ = f.check_box :share_with_group_lock, disabled: !can_change_share_with_group_lock?(@group), class: 'form-check-input'
+ = f.label :share_with_group_lock, class: 'form-check-label' do
+ %span
+ - group_link = link_to @group.name, group_path(@group)
+ = s_('GroupSettings|Prevent sharing a project within %{group} with other groups').html_safe % { group: group_link }
+ %br
+ %span.descr.text-muted= share_with_group_lock_help_text(@group)
+ = render 'groups/settings/lfs', f: f
+ = render 'groups/settings/two_factor_auth', f: f
= render_if_exists 'groups/member_lock_setting', f: f, group: @group
- = f.submit 'Save group', class: 'btn btn-success'
+ = f.submit _('Save changes'), class: 'btn btn-success prepend-top-default js-dirty-submit'
diff --git a/app/views/groups/settings/_two_factor_auth.html.haml b/app/views/groups/settings/_two_factor_auth.html.haml
new file mode 100644
index 00000000000..5d3f1cbb279
--- /dev/null
+++ b/app/views/groups/settings/_two_factor_auth.html.haml
@@ -0,0 +1,16 @@
+- docs_link_url = help_page_path('security/two_factor_authentication', anchor: 'enforcing-2fa-for-all-users-in-a-group')
+- docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: docs_link_url }
+
+%h5= _('Two-factor authentication')
+
+%p= s_('Check the %{docs_link_start}documentation%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: '</a>'.html_safe }
+
+.form-group
+ .form-check
+ = f.check_box :require_two_factor_authentication, class: 'form-check-input'
+ = f.label :require_two_factor_authentication, class: 'form-check-label' do
+ %span= _('Require all users in this group to setup Two-factor authentication')
+.form-group
+ = f.label :two_factor_grace_period, _('Time before enforced'), class: 'label-bold'
+ = f.text_field :two_factor_grace_period, class: 'form-control form-control-sm w-auto'
+ .form-text.text-muted= _('Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication')
diff --git a/app/views/groups/settings/ci_cd/show.html.haml b/app/views/groups/settings/ci_cd/show.html.haml
index 647948c7dff..a5e6abdba52 100644
--- a/app/views/groups/settings/ci_cd/show.html.haml
+++ b/app/views/groups/settings/ci_cd/show.html.haml
@@ -3,7 +3,7 @@
- expanded = Rails.env.test?
-%section.settings#secret-variables.no-animate{ class: ('expanded' if expanded) }
+%section.settings#ci-variables.no-animate{ class: ('expanded' if expanded) }
.settings-header
%h4
= _('Variables')
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index f1bd817f17a..cc294f6a931 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -15,12 +15,12 @@
- new_project_label = _("New project")
- new_subgroup_label = _("New subgroup")
- if can_create_subgroups
- .btn-group.new-project-subgroup.droplab-dropdown.js-new-project-subgroup{ data: { project_path: new_project_path(namespace_id: @group.id), subgroup_path: new_group_path(parent_id: @group.id) } }
- %input.btn.btn-success.dropdown-primary.js-new-group-child{ type: "button", value: new_project_label, data: { action: "new-project" } }
- %button.btn.btn-success.dropdown-toggle.js-dropdown-toggle{ type: "button", data: { "dropdown-trigger" => "#new-project-or-subgroup-dropdown", 'display' => 'static' } }
+ .btn-group.new-project-subgroup.droplab-dropdown.js-new-project-subgroup.qa-new-project-or-subgroup-dropdown{ data: { project_path: new_project_path(namespace_id: @group.id), subgroup_path: new_group_path(parent_id: @group.id) } }
+ %input.btn.btn-success.dropdown-primary.js-new-group-child.qa-new-in-group-button{ type: "button", value: new_project_label, data: { action: "new-project" } }
+ %button.btn.btn-success.dropdown-toggle.js-dropdown-toggle.qa-new-project-or-subgroup-dropdown-toggle{ type: "button", data: { "dropdown-trigger" => "#new-project-or-subgroup-dropdown", 'display' => 'static' } }
= icon("caret-down", class: "dropdown-btn-icon")
%ul#new-project-or-subgroup-dropdown.dropdown-menu.dropdown-menu-right{ data: { dropdown: true } }
- %li.droplab-item-selected{ role: "button", data: { value: "new-project", text: new_project_label } }
+ %li.droplab-item-selected.qa-new-project-option{ role: "button", data: { value: "new-project", text: new_project_label } }
.menu-item
.icon-container
= icon("check", class: "list-item-checkmark")
@@ -28,7 +28,7 @@
%strong= new_project_label
%span= s_("GroupsTree|Create a project in this group.")
%li.divider.droplap-item-ignore
- %li{ role: "button", data: { value: "new-subgroup", text: new_subgroup_label } }
+ %li.qa-new-subgroup-option{ role: "button", data: { value: "new-subgroup", text: new_subgroup_label } }
.menu-item
.icon-container
= icon("check", class: "list-item-checkmark")
@@ -53,7 +53,7 @@
= _("Archived projects")
.nav-controls
- = render "shared/groups/dropdown"
+ = render "shared/groups/dropdown", options_hash: subgroups_sort_options_hash
.tab-content
#subgroups_and_projects.tab-pane
diff --git a/app/views/help/_shortcuts.html.haml b/app/views/help/_shortcuts.html.haml
index 37b56f92030..28ffb2dd63c 100644
--- a/app/views/help/_shortcuts.html.haml
+++ b/app/views/help/_shortcuts.html.haml
@@ -249,6 +249,13 @@
- else
%kbd ctrl p
%td Go to file
+ %tr
+ %td.shortcut
+ - if browser.platform.mac?
+ %kbd &#8984; enter
+ - else
+ %kbd ctrl enter
+ %td Commit (when editing commit message)
.col-lg-4
%table.shortcut-mappings
%tbody.hidden-shortcut{ style: 'display:none' }
diff --git a/app/views/help/index.html.haml b/app/views/help/index.html.haml
index 7a66bac09cb..dfa5d820ce9 100644
--- a/app/views/help/index.html.haml
+++ b/app/views/help/index.html.haml
@@ -7,8 +7,7 @@
GitLab
Community Edition
- if user_signed_in?
- %span= Gitlab::VERSION
- %small= link_to Gitlab.revision, Gitlab::COM_URL + namespace_project_commits_path('gitlab-org', 'gitlab-ce', Gitlab.revision)
+ %span= link_to_version
= version_status_badge
%hr
diff --git a/app/views/import/bitbucket/status.html.haml b/app/views/import/bitbucket/status.html.haml
index 3b1b5e55302..2336e1e83f9 100644
--- a/app/views/import/bitbucket/status.html.haml
+++ b/app/views/import/bitbucket/status.html.haml
@@ -37,11 +37,12 @@
%td
= link_to project.full_path, [project.namespace.becomes(Namespace), project]
%td.job-status
- - if project.import_status == 'finished'
+ - case project.import_status
+ - when 'finished'
%span
%i.fa.fa-check
= _('done')
- - elsif project.import_status == 'started'
+ - when 'started'
%i.fa.fa-spinner.fa-spin
= _('started')
- else
diff --git a/app/views/import/bitbucket_server/status.html.haml b/app/views/import/bitbucket_server/status.html.haml
index ae09e0dfa18..ef69197e453 100644
--- a/app/views/import/bitbucket_server/status.html.haml
+++ b/app/views/import/bitbucket_server/status.html.haml
@@ -38,9 +38,10 @@
%td
= link_to project.full_path, [project.namespace.becomes(Namespace), project]
%td.job-status
- - if project.import_status == 'finished'
+ - case project.import_status
+ - when 'finished'
= icon('check', text: 'Done')
- - elsif project.import_status == 'started'
+ - when 'started'
= icon('spin', text: 'started')
- else
= project.human_import_status_name
@@ -84,4 +85,6 @@
= link_to 'import flow', status_import_bitbucket_server_path
again.
+= paginate_without_count(@collection)
+
.js-importer-status{ data: { jobs_import_path: "#{jobs_import_bitbucket_server_path}", import_path: "#{import_bitbucket_server_path}" } }
diff --git a/app/views/import/fogbugz/status.html.haml b/app/views/import/fogbugz/status.html.haml
index 830d141ebea..eca67582d6f 100644
--- a/app/views/import/fogbugz/status.html.haml
+++ b/app/views/import/fogbugz/status.html.haml
@@ -34,11 +34,12 @@
%td
= link_to project.full_path, [project.namespace.becomes(Namespace), project]
%td.job-status
- - if project.import_status == 'finished'
+ - case project.import_status
+ - when 'finished'
%span
%i.fa.fa-check
= _("done")
- - elsif project.import_status == 'started'
+ - when 'started'
%i.fa.fa-spinner.fa-spin
= _("started")
- else
diff --git a/app/views/import/gitlab/status.html.haml b/app/views/import/gitlab/status.html.haml
index b7bfbae5edf..a5fa12fe7df 100644
--- a/app/views/import/gitlab/status.html.haml
+++ b/app/views/import/gitlab/status.html.haml
@@ -30,11 +30,12 @@
%td
= link_to project.full_path, [project.namespace.becomes(Namespace), project]
%td.job-status
- - if project.import_status == 'finished'
+ - case project.import_status
+ - when 'finished'
%span
%i.fa.fa-check
= _('done')
- - elsif project.import_status == 'started'
+ - when 'started'
%i.fa.fa-spinner.fa-spin
= _('started')
- else
diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml
index 877d945a09b..5e4595d930b 100644
--- a/app/views/import/gitlab_projects/new.html.haml
+++ b/app/views/import/gitlab_projects/new.html.haml
@@ -10,7 +10,7 @@
.row
.form-group.project-name.col-sm-12
= label_tag :name, _('Project name'), class: 'label-bold'
- = text_field_tag :name, @name, placeholder: "My awesome project", class: "js-project-name form-control input-lg", autofocus: true, required: true
+ = text_field_tag :name, @name, placeholder: "My awesome project", class: "js-project-name form-control input-lg", autofocus: true
.form-group.col-12.col-sm-6
= label_tag :namespace_id, _('Project URL'), class: 'label-bold'
.form-group
diff --git a/app/views/import/google_code/status.html.haml b/app/views/import/google_code/status.html.haml
index 347e2820f94..f322b7a956a 100644
--- a/app/views/import/google_code/status.html.haml
+++ b/app/views/import/google_code/status.html.haml
@@ -39,11 +39,12 @@
%td
= link_to project.full_path, [project.namespace.becomes(Namespace), project]
%td.job-status
- - if project.import_status == 'finished'
+ - case project.import_status
+ - when 'finished'
%span
%i.fa.fa-check
= _("done")
- - elsif project.import_status == 'started'
+ - when 'started'
%i.fa.fa-spinner.fa-spin
= _("started")
- else
diff --git a/app/views/instance_statistics/conversational_development_index/_disabled.html.haml b/app/views/instance_statistics/conversational_development_index/_disabled.html.haml
index 0a5717f75e1..b854e15d36f 100644
--- a/app/views/instance_statistics/conversational_development_index/_disabled.html.haml
+++ b/app/views/instance_statistics/conversational_development_index/_disabled.html.haml
@@ -11,4 +11,4 @@
%p
= _('Enable usage ping to get an overview of how you are using GitLab from a feature perspective.')
- if current_user.admin?
- = link_to _('Enable usage ping'), admin_application_settings_path(anchor: 'usage-statistics'), class: 'btn btn-primary'
+ = link_to _('Enable usage ping'), metrics_and_profiling_admin_application_settings_path(anchor: 'js-usage-settings'), class: 'btn btn-primary'
diff --git a/app/views/invites/show.html.haml b/app/views/invites/show.html.haml
index c2bb1216c5f..30ab5781014 100644
--- a/app/views/invites/show.html.haml
+++ b/app/views/invites/show.html.haml
@@ -1,5 +1,5 @@
-- page_title "Invitation"
-%h3.page-title Invitation
+- page_title _("Invitation")
+%h3.page-title= _("Invitation")
%p
You have been invited
@@ -24,14 +24,17 @@
- if is_member
%p
- However, you are already a member of this #{@member.source.is_a?(Group) ? "group" : "project"}.
- Sign in using a different account to accept the invitation.
+ - member_source = @member.source.is_a?(Group) ? _("group") : _("project")
+ = _("However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation.") % { member_source: member_source }
- if @member.invite_email != current_user.email
%p
- Note that this invitation was sent to #{mail_to @member.invite_email}, but you are signed in as #{link_to current_user.to_reference, user_url(current_user)} with email #{mail_to current_user.email}.
+ - mail_to_invite_email = mail_to(@member.invite_email)
+ - mail_to_current_user = mail_to(current_user.email)
+ - link_to_current_user = link_to(current_user.to_reference, user_url(current_user))
+ = _("Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}.").html_safe % { mail_to_invite_email: mail_to_invite_email, mail_to_current_user: mail_to_current_user, link_to_current_user: link_to_current_user }
- unless is_member
.actions
- = link_to "Accept invitation", accept_invite_url(@token), method: :post, class: "btn btn-success"
- = link_to "Decline", decline_invite_url(@token), method: :post, class: "btn btn-danger prepend-left-10"
+ = link_to _("Accept invitation"), accept_invite_url(@token), method: :post, class: "btn btn-success"
+ = link_to _("Decline"), decline_invite_url(@token), method: :post, class: "btn btn-danger prepend-left-10"
diff --git a/app/views/koding/index.html.haml b/app/views/koding/index.html.haml
deleted file mode 100644
index bb7f9ba7ae4..00000000000
--- a/app/views/koding/index.html.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-.row-content-block.second-block.center
- %p
- = icon('circle', class: 'cgreen')
- Integration is active for
- = link_to koding_project_url, target: '_blank', rel: 'noopener noreferrer' do
- #{Gitlab::CurrentSettings.koding_url}
diff --git a/app/views/layouts/_flash.html.haml b/app/views/layouts/_flash.html.haml
index 8bd5708d490..2cdaa85bdaa 100644
--- a/app/views/layouts/_flash.html.haml
+++ b/app/views/layouts/_flash.html.haml
@@ -6,5 +6,5 @@
-# Don't show a flash message if the message is nil
- if value
%div{ class: "flash-#{key}" }
- %div{ class: "#{container_class} #{extra_flash_class}" }
+ %div{ class: "#{(container_class unless fluid_layout)} #{(extra_flash_class unless @no_container)} #{@content_class}" }
%span= value
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index a41d30da450..1b2a4cd6780 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -6,12 +6,13 @@
.mobile-overlay
.alert-wrapper
= render "layouts/broadcast"
- = render 'layouts/header/read_only_banner'
+ = render "layouts/header/read_only_banner"
= yield :flash_message
= render "shared/ping_consent"
- unless @hide_breadcrumbs
= render "layouts/nav/breadcrumbs"
- = render "layouts/flash"
+ = render "layouts/flash", extra_flash_class: 'limit-container-width'
+ .d-flex
%div{ class: "#{(container_class unless @no_container)} #{@content_class}" }
.content{ id: "content-body" }
= yield
diff --git a/app/views/layouts/dashboard.html.haml b/app/views/layouts/dashboard.html.haml
index 489ef245a4d..c10be282952 100644
--- a/app/views/layouts/dashboard.html.haml
+++ b/app/views/layouts/dashboard.html.haml
@@ -1,5 +1,6 @@
- page_title _("Dashboard")
- header_title _("Dashboard"), root_path unless header_title
- sidebar "dashboard"
+- @hide_breadcrumbs = true
= render template: "layouts/application"
diff --git a/app/views/layouts/explore.html.haml b/app/views/layouts/explore.html.haml
index 80bda34a3f5..24751ab4e06 100644
--- a/app/views/layouts/explore.html.haml
+++ b/app/views/layouts/explore.html.haml
@@ -1,4 +1,6 @@
- page_title _("Explore")
+- @hide_breadcrumbs = true
+
- unless current_user
- header_title _("Explore GitLab"), explore_root_path
diff --git a/app/views/layouts/header/_current_user_dropdown.html.haml b/app/views/layouts/header/_current_user_dropdown.html.haml
index 9ed05d6e3d0..4f3e4031fe3 100644
--- a/app/views/layouts/header/_current_user_dropdown.html.haml
+++ b/app/views/layouts/header/_current_user_dropdown.html.haml
@@ -5,19 +5,23 @@
.user-name.bold
= current_user.name
= current_user.to_reference
+ - if current_user.status
+ .user-status.d-flex.align-items-center.prepend-top-2.has-tooltip{ title: current_user.status.message_html, data: { html: 'true', placement: 'bottom' } }
+ %span.user-status-emoji.d-flex.align-items-center
+ = emoji_icon current_user.status.emoji
+ %span.user-status-message.str-truncated
+ = current_user.status.message_html.html_safe
%li.divider
+ - if can?(current_user, :update_user_status, current_user)
+ %li
+ .js-set-status-modal-trigger{ data: { has_status: current_user.status.present? ? 'true' : 'false' } }
- if current_user_menu?(:profile)
%li
= link_to s_("CurrentUser|Profile"), current_user, class: 'profile-link', data: { user: current_user.username }
- if current_user_menu?(:settings)
%li
= link_to s_("CurrentUser|Settings"), profile_path
- - if current_user_menu?(:help)
- %li
- = link_to _("Help"), help_path
- - if current_user_menu?(:help) || current_user_menu?(:settings) || current_user_menu?(:profile)
- %li.divider
- = render 'shared/user_dropdown_contributing_link'
- if current_user_menu?(:sign_out)
+ %li.divider
%li
= link_to _("Sign out"), destroy_user_session_path, class: "sign-out-link"
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index 044b49c12cc..b7d69539eb7 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -5,7 +5,7 @@
- else
- search_path_url = search_path
-%header.navbar.navbar-gitlab.qa-navbar.navbar-expand-sm
+%header.navbar.navbar-gitlab.qa-navbar.navbar-expand-sm.js-navbar
%a.sr-only.gl-accessibility{ href: "#content-body", tabindex: "1" } Skip to content
.container-fluid
.header-content
@@ -53,6 +53,12 @@
= sprite_icon('todo-done', size: 16)
%span.badge.badge-pill.todos-count{ class: ('hidden' if todos_pending_count.zero?) }
= todos_count_format(todos_pending_count)
+ %li.nav-item.header-help.dropdown
+ = link_to help_path, class: 'header-help-dropdown-toggle', data: { toggle: "dropdown" } do
+ = sprite_icon('question', size: 16)
+ = sprite_icon('angle-down', css_class: 'caret-down')
+ .dropdown-menu.dropdown-menu-right
+ = render 'layouts/header/help_dropdown'
- if header_link?(:user_dropdown)
%li.nav-item.header-user.dropdown
= link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown" } do
@@ -74,3 +80,6 @@
%span.sr-only= _('Toggle navigation')
= sprite_icon('ellipsis_h', size: 12, css_class: 'more-icon js-navbar-toggle-right')
= sprite_icon('close', size: 12, css_class: 'close-icon js-navbar-toggle-left')
+
+- if can?(current_user, :update_user_status, current_user)
+ .js-set-status-modal-wrapper{ data: { current_emoji: current_user.status.present? ? current_user.status.emoji : '', current_message: current_user.status.present? ? current_user.status.message : '' } }
diff --git a/app/views/layouts/header/_help_dropdown.html.haml b/app/views/layouts/header/_help_dropdown.html.haml
new file mode 100644
index 00000000000..953c0e7f46c
--- /dev/null
+++ b/app/views/layouts/header/_help_dropdown.html.haml
@@ -0,0 +1,6 @@
+%ul
+ - if current_user_menu?(:help)
+ %li
+ = link_to _("Help"), help_path
+ - if current_user_menu?(:help) || current_user_menu?(:settings) || current_user_menu?(:profile)
+ = render 'shared/user_dropdown_contributing_link'
diff --git a/app/views/layouts/header/_new_dropdown.haml b/app/views/layouts/header/_new_dropdown.haml
index e134f416c70..5cb8aebadb3 100644
--- a/app/views/layouts/header/_new_dropdown.haml
+++ b/app/views/layouts/header/_new_dropdown.haml
@@ -7,15 +7,14 @@
- if @group&.persisted?
- create_group_project = can?(current_user, :create_projects, @group)
- create_group_subgroup = can?(current_user, :create_subgroup, @group)
+
- if create_group_project || create_group_subgroup
%li.dropdown-bold-header
= _('This group')
- if create_group_project
- %li.header-new-group-project
- = link_to _('New project'), new_project_path(namespace_id: @group.id)
+ %li= link_to _('New project'), new_project_path(namespace_id: @group.id)
- if create_group_subgroup
- %li
- = link_to _('New subgroup'), new_group_path(parent_id: @group.id)
+ %li= link_to _('New subgroup'), new_group_path(parent_id: @group.id)
%li.divider
%li.dropdown-bold-header GitLab
@@ -23,25 +22,20 @@
- create_project_issue = show_new_issue_link?(@project)
- merge_project = merge_request_source_project_for_project(@project)
- create_project_snippet = can?(current_user, :create_project_snippet, @project)
+
- if create_project_issue || merge_project || create_project_snippet
%li.dropdown-bold-header
= _('This project')
- if create_project_issue
- %li
- = link_to _('New issue'), new_project_issue_path(@project)
+ %li= link_to _('New issue'), new_project_issue_path(@project)
- if merge_project
- %li
- = link_to _('New merge request'), project_new_merge_request_path(merge_project)
+ %li= link_to _('New merge request'), project_new_merge_request_path(merge_project)
- if create_project_snippet
- %li.header-new-project-snippet
- = link_to _('New snippet'), new_project_snippet_path(@project)
+ %li= link_to _('New snippet'), new_project_snippet_path(@project)
%li.divider
%li.dropdown-bold-header GitLab
- if current_user.can_create_project?
- %li
- = link_to _('New project'), new_project_path, class: 'qa-global-new-project-link'
+ %li= link_to _('New project'), new_project_path, class: 'qa-global-new-project-link'
- if current_user.can_create_group?
- %li
- = link_to _('New group'), new_group_path
- %li
- = link_to _('New snippet'), new_snippet_path
+ %li= link_to _('New group'), new_group_path
+ %li= link_to _('New snippet'), new_snippet_path
diff --git a/app/views/layouts/koding.html.haml b/app/views/layouts/koding.html.haml
deleted file mode 100644
index 45ccd38f687..00000000000
--- a/app/views/layouts/koding.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-- page_title _("Koding")
-- page_description _("Koding Dashboard")
-- header_title _("Koding"), koding_path
-
-= render template: "layouts/application"
diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml
index 5e467c862ab..ea5f2b166b4 100644
--- a/app/views/layouts/nav/_dashboard.html.haml
+++ b/app/views/layouts/nav/_dashboard.html.haml
@@ -64,8 +64,9 @@
= link_to '#', class: 'dashboard-shortcuts-web-ide', title: _('Web IDE') do
= _('Web IDE')
- - if Gitlab::Sherlock.enabled? || can?(current_user, :read_instance_statistics)
+ - if show_separator?
%li.line-separator.d-none.d-sm-block
+ = render_if_exists 'dashboard/operations/nav_link'
- if can?(current_user, :read_instance_statistics)
= nav_link(controller: [:conversational_development_index, :cohorts]) do
= link_to instance_statistics_root_path, title: _('Instance Statistics'), aria: { label: _('Instance Statistics') }, data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
diff --git a/app/views/layouts/nav/sidebar/_admin.html.haml b/app/views/layouts/nav/sidebar/_admin.html.haml
index a2636f8179a..5f15ba87729 100644
--- a/app/views/layouts/nav/sidebar/_admin.html.haml
+++ b/app/views/layouts/nav/sidebar/_admin.html.haml
@@ -1,4 +1,4 @@
-.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?) }
+.nav-sidebar.qa-admin-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?) }
.nav-sidebar-inner-scroll
.context-header
= link_to admin_root_path, title: _('Admin Overview') do
@@ -7,14 +7,14 @@
.sidebar-context-title
= _('Admin Area')
%ul.sidebar-top-level-items
- = nav_link(controller: %w(dashboard admin projects users groups jobs runners gitaly_servers), html_options: {class: 'home'}) do
+ = nav_link(controller: %w(dashboard admin admin/projects users groups jobs runners gitaly_servers), html_options: {class: 'home'}) do
= link_to admin_root_path, class: 'shortcuts-tree' do
.nav-icon-container
= sprite_icon('overview')
%span.nav-item-name
= _('Overview')
%ul.sidebar-sub-level-items
- = nav_link(controller: %w(dashboard admin projects users groups jobs runners gitaly_servers), html_options: { class: "fly-out-top-item" } ) do
+ = nav_link(controller: %w(dashboard admin admin/projects users groups jobs runners gitaly_servers), html_options: { class: "fly-out-top-item" } ) do
= link_to admin_root_path do
%strong.fly-out-top-item-name
= _('Overview')
@@ -23,7 +23,7 @@
= link_to admin_root_path, title: _('Overview') do
%span
= _('Dashboard')
- = nav_link(controller: [:admin, :projects]) do
+ = nav_link(controller: [:admin, 'admin/projects']) do
= link_to admin_projects_path, title: _('Projects') do
%span
= _('Projects')
@@ -197,10 +197,10 @@
= link_to admin_application_settings_path do
.nav-icon-container
= sprite_icon('settings')
- %span.nav-item-name
+ %span.nav-item-name.qa-admin-settings-item
= _('Settings')
- %ul.sidebar-sub-level-items
+ %ul.sidebar-sub-level-items.qa-admin-sidebar-submenu
= nav_link(controller: :application_settings, html_options: { class: "fly-out-top-item" } ) do
= link_to admin_application_settings_path do
%strong.fly-out-top-item-name
@@ -215,7 +215,7 @@
%span
= _('Integrations')
= nav_link(path: 'application_settings#repository') do
- = link_to repository_admin_application_settings_path, title: _('Repository') do
+ = link_to repository_admin_application_settings_path, title: _('Repository'), class: 'qa-admin-settings-repository-item' do
%span
= _('Repository')
- if template_exists?('admin/application_settings/templates')
diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml
index 4158bb69452..477030a20c1 100644
--- a/app/views/layouts/nav/sidebar/_group.html.haml
+++ b/app/views/layouts/nav/sidebar/_group.html.haml
@@ -10,9 +10,9 @@
= group_icon(@group, class: "avatar s40 avatar-tile")
.sidebar-context-title
= @group.name
- %ul.sidebar-top-level-items
+ %ul.sidebar-top-level-items.qa-group-sidebar
- if group_sidebar_link?(:overview)
- = nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups', 'analytics#show'], html_options: { class: 'home' }) do
+ = nav_link(path: group_overview_nav_link_paths, html_options: { class: 'home' }) do
= link_to group_path(@group) do
.nav-icon-container
= sprite_icon('home')
@@ -36,6 +36,16 @@
%span
= _('Activity')
+ = render_if_exists 'groups/sidebar/security_dashboard'
+
+ - if group_sidebar_link?(:contribution_analytics)
+ = nav_link(path: 'analytics#show') do
+ = link_to group_analytics_path(@group), title: 'Contribution Analytics', data: {placement: 'right'} do
+ %span
+ Contribution Analytics
+
+ = render_if_exists "layouts/nav/ee/epic_link", group: @group
+
- if group_sidebar_link?(:issues)
= nav_link(path: issues_sub_menu_items) do
= link_to issues_group_path(@group) do
@@ -64,6 +74,8 @@
%span
= boards_link_text
+ = render_if_exists 'layouts/nav/issues_analytics_link'
+
- if group_sidebar_link?(:labels)
= nav_link(path: 'labels#index') do
= link_to group_labels_path(@group), title: _('Labels') do
@@ -96,7 +108,7 @@
= link_to group_group_members_path(@group) do
.nav-icon-container
= sprite_icon('users')
- %span.nav-item-name
+ %span.nav-item-name.qa-group-members-item
= _('Members')
%ul.sidebar-sub-level-items.is-fly-out-only
= nav_link(path: 'group_members#index', html_options: { class: "fly-out-top-item" } ) do
@@ -104,14 +116,27 @@
%strong.fly-out-top-item-name
= _('Members')
+ - if group_sidebar_link?(:kubernetes)
+ = nav_link(controller: [:clusters]) do
+ = link_to group_clusters_path(@group) do
+ .nav-icon-container
+ = sprite_icon('cloud-gear')
+ %span.nav-item-name
+ = _('Kubernetes')
+ %ul.sidebar-sub-level-items.is-fly-out-only
+ = nav_link(controller: [:clusters], html_options: { class: "fly-out-top-item" } ) do
+ = link_to group_clusters_path(@group), title: _('Kubernetes'), class: 'shortcuts-kubernetes' do
+ %strong.fly-out-top-item-name
+ = _('Kubernetes')
+
- if group_sidebar_link?(:settings)
= nav_link(path: group_nav_link_paths) do
= link_to edit_group_path(@group) do
.nav-icon-container
= sprite_icon('settings')
- %span.nav-item-name
+ %span.nav-item-name.qa-group-settings-item
= _('Settings')
- %ul.sidebar-sub-level-items
+ %ul.sidebar-sub-level-items.qa-group-sidebar-submenu
= nav_link(path: %w[groups#projects groups#edit badges#index ci_cd#show], html_options: { class: "fly-out-top-item" } ) do
= link_to edit_group_path(@group) do
%strong.fly-out-top-item-name
@@ -132,4 +157,6 @@
%span
= _('CI / CD')
+ = render_if_exists "groups/ee/settings_nav"
+
= render 'shared/sidebar_toggle_button'
diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml
index 25cd53b378a..ab15889a465 100644
--- a/app/views/layouts/nav/sidebar/_project.html.haml
+++ b/app/views/layouts/nav/sidebar/_project.html.haml
@@ -86,7 +86,7 @@
- if project_nav_tab? :issues
= nav_link(controller: @project.issues_enabled? ? [:issues, :labels, :milestones, :boards] : :issues) do
- = link_to project_issues_path(@project), class: 'shortcuts-issues' do
+ = link_to project_issues_path(@project), class: 'shortcuts-issues qa-issues-item' do
.nav-icon-container
= sprite_icon('issues')
%span.nav-item-name
@@ -115,7 +115,7 @@
= boards_link_text
= nav_link(controller: :labels) do
- = link_to project_labels_path(@project), title: _('Labels') do
+ = link_to project_labels_path(@project), title: _('Labels'), class: 'qa-labels-link' do
%span
= _('Labels')
@@ -195,7 +195,7 @@
= _('Charts')
- if project_nav_tab? :operations
- = nav_link(controller: [:environments, :clusters, :user, :gcp]) do
+ = nav_link(controller: sidebar_operations_paths) do
= link_to metrics_project_environments_path(@project), class: 'shortcuts-operations' do
.nav-icon-container
= sprite_icon('cloud-gear')
@@ -203,7 +203,7 @@
= _('Operations')
%ul.sidebar-sub-level-items
- = nav_link(controller: [:environments, :clusters, :user, :gcp], html_options: { class: "fly-out-top-item" } ) do
+ = nav_link(controller: sidebar_operations_paths, html_options: { class: "fly-out-top-item" } ) do
= link_to metrics_project_environments_path(@project) do
%strong.fly-out-top-item-name
= _('Operations')
@@ -215,8 +215,10 @@
%span
= _('Metrics')
+ = render_if_exists "layouts/nav/sidebar/tracing_link"
+
= nav_link(controller: :environments, action: [:index, :folder, :show, :new, :edit, :create, :update, :stop, :terminal]) do
- = link_to project_environments_path(@project), title: _('Environments'), class: 'shortcuts-environments' do
+ = link_to project_environments_path(@project), title: _('Environments'), class: 'shortcuts-environments qa-operations-environments-link' do
%span
= _('Environments')
@@ -309,7 +311,7 @@
%span
= _('General')
= nav_link(controller: :project_members) do
- = link_to project_project_members_path(@project), title: _('Members') do
+ = link_to project_project_members_path(@project), title: _('Members'), class: 'qa-link-members-settings' do
%span
= _('Members')
- if can_edit
@@ -326,6 +328,7 @@
= link_to project_settings_ci_cd_path(@project), title: _('CI / CD') do
%span
= _('CI / CD')
+ = render_if_exists 'projects/sidebar/settings_operations'
- if @project.pages_available?
= nav_link(controller: :pages) do
= link_to project_pages_path(@project), title: _('Pages') do
diff --git a/app/views/layouts/terms.html.haml b/app/views/layouts/terms.html.haml
index 977eb350365..cdad617f006 100644
--- a/app/views/layouts/terms.html.haml
+++ b/app/views/layouts/terms.html.haml
@@ -16,19 +16,18 @@
.content{ id: "content-body" }
.card
.card-header
- .card-title
- = brand_header_logo
- - logo_text = brand_header_logo_type
- - if logo_text.present?
- %span.logo-text.prepend-left-8
- = logo_text
- - if header_link?(:user_dropdown)
- .navbar-collapse
- %ul.nav.navbar-nav
- %li.header-user.dropdown
- = link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown" } do
- = image_tag avatar_icon_for_user(current_user, 23), width: 23, height: 23, class: "header-user-avatar qa-user-avatar"
- = sprite_icon('angle-down', css_class: 'caret-down')
- .dropdown-menu.dropdown-menu-right
- = render 'layouts/header/current_user_dropdown'
+ = brand_header_logo
+ - logo_text = brand_header_logo_type
+ - if logo_text.present?
+ %span.logo-text.prepend-left-8
+ = logo_text
+ - if header_link?(:user_dropdown)
+ .navbar-collapse
+ %ul.nav.navbar-nav
+ %li.header-user.dropdown
+ = link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown" } do
+ = image_tag avatar_icon_for_user(current_user, 23), width: 23, height: 23, class: "header-user-avatar qa-user-avatar"
+ = sprite_icon('angle-down', css_class: 'caret-down')
+ .dropdown-menu.dropdown-menu-right
+ = render 'layouts/header/current_user_dropdown'
= yield
diff --git a/app/views/notify/changed_milestone_issue_email.html.haml b/app/views/notify/changed_milestone_issue_email.html.haml
new file mode 100644
index 00000000000..7d5425fc72d
--- /dev/null
+++ b/app/views/notify/changed_milestone_issue_email.html.haml
@@ -0,0 +1,3 @@
+%p
+ Milestone changed to
+ %strong= link_to(@milestone.name, @milestone_url)
diff --git a/app/views/notify/changed_milestone_issue_email.text.erb b/app/views/notify/changed_milestone_issue_email.text.erb
new file mode 100644
index 00000000000..c5fc0b61518
--- /dev/null
+++ b/app/views/notify/changed_milestone_issue_email.text.erb
@@ -0,0 +1 @@
+Milestone changed to <%= @milestone.name %> ( <%= @milestone_url %> )
diff --git a/app/views/notify/changed_milestone_merge_request_email.html.haml b/app/views/notify/changed_milestone_merge_request_email.html.haml
new file mode 100644
index 00000000000..7d5425fc72d
--- /dev/null
+++ b/app/views/notify/changed_milestone_merge_request_email.html.haml
@@ -0,0 +1,3 @@
+%p
+ Milestone changed to
+ %strong= link_to(@milestone.name, @milestone_url)
diff --git a/app/views/notify/changed_milestone_merge_request_email.text.erb b/app/views/notify/changed_milestone_merge_request_email.text.erb
new file mode 100644
index 00000000000..c5fc0b61518
--- /dev/null
+++ b/app/views/notify/changed_milestone_merge_request_email.text.erb
@@ -0,0 +1 @@
+Milestone changed to <%= @milestone.name %> ( <%= @milestone_url %> )
diff --git a/app/views/notify/new_merge_request_email.html.haml b/app/views/notify/new_merge_request_email.html.haml
index dd6a84e503d..5acd45b74a7 100644
--- a/app/views/notify/new_merge_request_email.html.haml
+++ b/app/views/notify/new_merge_request_email.html.haml
@@ -9,7 +9,7 @@
%p
Assignee: #{@merge_request.assignee_name}
-= render_if_exists 'notify/merge_request_approvers', merge_request: @merge_request
+= render_if_exists 'notify/merge_request_approvers', presenter: @mr_presenter
- if @merge_request.description
%div
diff --git a/app/views/notify/new_merge_request_email.text.erb b/app/views/notify/new_merge_request_email.text.erb
index d5b8f8d764f..754f4bca1cd 100644
--- a/app/views/notify/new_merge_request_email.text.erb
+++ b/app/views/notify/new_merge_request_email.text.erb
@@ -5,6 +5,6 @@ New Merge Request <%= @merge_request.to_reference %>
<%= merge_path_description(@merge_request, 'to') %>
Author: <%= @merge_request.author_name %>
Assignee: <%= @merge_request.assignee_name %>
-<%= render_if_exists 'notify/merge_request_approvers', merge_request: @merge_request %>
+<%= render_if_exists 'notify/merge_request_approvers', presenter: @mr_presenter %>
<%= @merge_request.description %>
diff --git a/app/views/notify/note_snippet_email.html.haml b/app/views/notify/note_project_snippet_email.html.haml
index 5e69f01a486..5e69f01a486 100644
--- a/app/views/notify/note_snippet_email.html.haml
+++ b/app/views/notify/note_project_snippet_email.html.haml
diff --git a/app/views/notify/note_snippet_email.text.erb b/app/views/notify/note_project_snippet_email.text.erb
index 413d9e6e9ac..413d9e6e9ac 100644
--- a/app/views/notify/note_snippet_email.text.erb
+++ b/app/views/notify/note_project_snippet_email.text.erb
diff --git a/app/views/notify/removed_milestone_issue_email.html.haml b/app/views/notify/removed_milestone_issue_email.html.haml
new file mode 100644
index 00000000000..7e9205b6491
--- /dev/null
+++ b/app/views/notify/removed_milestone_issue_email.html.haml
@@ -0,0 +1,2 @@
+%p
+ Milestone removed
diff --git a/app/views/notify/removed_milestone_issue_email.text.erb b/app/views/notify/removed_milestone_issue_email.text.erb
new file mode 100644
index 00000000000..0b83ed7a4c5
--- /dev/null
+++ b/app/views/notify/removed_milestone_issue_email.text.erb
@@ -0,0 +1 @@
+Milestone removed
diff --git a/app/views/notify/removed_milestone_merge_request_email.html.haml b/app/views/notify/removed_milestone_merge_request_email.html.haml
new file mode 100644
index 00000000000..7e9205b6491
--- /dev/null
+++ b/app/views/notify/removed_milestone_merge_request_email.html.haml
@@ -0,0 +1,2 @@
+%p
+ Milestone removed
diff --git a/app/views/notify/removed_milestone_merge_request_email.text.erb b/app/views/notify/removed_milestone_merge_request_email.text.erb
new file mode 100644
index 00000000000..0b83ed7a4c5
--- /dev/null
+++ b/app/views/notify/removed_milestone_merge_request_email.text.erb
@@ -0,0 +1 @@
+Milestone removed
diff --git a/app/views/peek/views/_gc.html.haml b/app/views/peek/views/_gc.html.haml
index 9fc83e56ee7..2a586261ce1 100644
--- a/app/views/peek/views/_gc.html.haml
+++ b/app/views/peek/views/_gc.html.haml
@@ -1,7 +1,7 @@
- local_assigns.fetch(:view)
%span.bold
- %span{ title: 'Invoke Time', data: { defer_to: "#{view.defer_key}-gc_time" } }...
+ %span{ title: _('Invoke Time'), data: { defer_to: "#{view.defer_key}-gc_time" } }...
\/
- %span{ title: 'Invoke Count', data: { defer_to: "#{view.defer_key}-invokes" } }...
+ %span{ title: _('Invoke Count'), data: { defer_to: "#{view.defer_key}-invokes" } }...
gc
diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml
index c10d4ea1a4d..4c18398e3dc 100644
--- a/app/views/profiles/personal_access_tokens/index.html.haml
+++ b/app/views/profiles/personal_access_tokens/index.html.haml
@@ -14,17 +14,7 @@
.col-lg-8
- if @new_personal_access_token
- .created-personal-access-token-container
- %h5.prepend-top-0
- Your New Personal Access Token
- .form-group
- .input-group
- = text_field_tag 'created-personal-access-token', @new_personal_access_token, readonly: true, class: "form-control js-select-on-focus", 'aria-describedby' => "created-personal-access-token-help-block"
- %span.input-group-append
- = clipboard_button(text: @new_personal_access_token, title: "Copy personal access token to clipboard", placement: "left", class: "input-group-text btn-default btn-clipboard")
- %span#created-personal-access-token-help-block.form-text.text-muted.text-danger Make sure you save it - you won't be able to access it again.
-
- %hr
+ = render "shared/personal_access_tokens_created_container", new_token_value: @new_personal_access_token
= render "shared/personal_access_tokens_form", path: profile_personal_access_tokens_path, impersonation: false, token: @personal_access_token, scopes: @scopes
@@ -36,7 +26,7 @@
%h4.prepend-top-0
Feed token
%p
- Your feed token is used to authenticate you when your RSS reader loads a personalized RSS feed or when when your calendar application loads a personalized calendar, and is included in those feed URLs.
+ Your feed token is used to authenticate you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar, and is included in those feed URLs.
%p
It cannot be used to access any other data.
.col-lg-8.feed-token-reset
diff --git a/app/views/profiles/preferences/show.html.haml b/app/views/profiles/preferences/show.html.haml
index 156c0d05b02..7c378633667 100644
--- a/app/views/profiles/preferences/show.html.haml
+++ b/app/views/profiles/preferences/show.html.haml
@@ -46,7 +46,7 @@
Layout width
= f.select :layout, layout_choices, {}, class: 'form-control'
.form-text.text-muted
- Choose between fixed (max. 1200px) and fluid (100%) application layout.
+ Choose between fixed (max. 1280px) and fluid (100%) application layout.
.form-group
= f.label :dashboard, class: 'label-bold' do
Default dashboard
@@ -56,6 +56,6 @@
Project overview content
= f.select :project_view, project_view_choices, {}, class: 'form-control'
.form-text.text-muted
- Choose what content you want to see on a project’s overview page
+ Choose what content you want to see on a project’s overview page.
.form-group
= f.submit 'Save changes', class: 'btn btn-success'
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index 51f5ecf2166..2603c558c0f 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -91,8 +91,9 @@
= f.select :public_email, options_for_select(@user.all_emails, selected: @user.public_email),
{ help: s_("Profiles|This email will be displayed on your public profile."), include_blank: s_("Profiles|Do not show on profile") },
control_class: 'select2'
- = f.select :commit_email, options_for_select(@user.verified_emails, selected: @user.commit_email),
- { help: 'This email will be used for web based operations, such as edits and merges.' },
+ - commit_email_docs_link = link_to s_('Profiles|Learn more'), help_page_path('user/profile/index', anchor: 'commit-email', target: '_blank')
+ = f.select :commit_email, options_for_select(commit_email_select_options(@user), selected: selected_commit_email(@user)),
+ { help: s_("Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}").html_safe % { learn_more: commit_email_docs_link } },
control_class: 'select2'
= f.select :preferred_language, Gitlab::I18n::AVAILABLE_LANGUAGES.map { |value, label| [label, value] },
{ help: s_("Profiles|This feature is experimental and translations are not complete yet.") },
@@ -109,10 +110,11 @@
= f.text_area :bio, rows: 4, maxlength: 250, help: s_("Profiles|Tell us about yourself in fewer than 250 characters.")
%hr
%h5= ("Private profile")
- - private_profile_label = capture do
- = s_("Profiles|Don't display activity-related personal information on your profiles")
+ .checkbox-icon-inline-wrapper
+ - private_profile_label = capture do
+ = s_("Profiles|Don't display activity-related personal information on your profiles")
+ = f.check_box :private_profile, label: private_profile_label
= link_to icon('question-circle'), help_page_path('user/profile/index.md', anchor: 'private-profile')
- = f.check_box :private_profile, label: private_profile_label
%h5= s_("Profiles|Private contributions")
= f.check_box :include_private_contributions, label: 'Include private contributions on my profile'
.help-block
diff --git a/app/views/profiles/two_factor_auths/_codes.html.haml b/app/views/profiles/two_factor_auths/_codes.html.haml
index fb4fff12027..759d39cf5f5 100644
--- a/app/views/profiles/two_factor_auths/_codes.html.haml
+++ b/app/views/profiles/two_factor_auths/_codes.html.haml
@@ -1,5 +1,5 @@
%p.slead
- Should you ever lose your phone, each of these recovery codes can be used one
+ Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one
time each to regain access to your account. Please save them in a safe place, or you
%b will
lose access to your account.
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index cd10b8758f6..94ec0cc5db8 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -6,13 +6,13 @@
.row.prepend-top-default
.col-lg-4
%h4.prepend-top-0
- Register Two-Factor Authentication App
+ Register Two-Factor Authenticator
%p
- Use an app on your mobile device to enable two-factor authentication (2FA).
+ Use an one time password authenticator on your mobile device or computer to enable two-factor authentication (2FA).
.col-lg-8
- if current_user.two_factor_otp_enabled?
%p
- You've already enabled two-factor authentication using mobile authenticator applications. In order to register a different device, you must first disable two-factor authentication.
+ You've already enabled two-factor authentication using one time password authenticators. In order to register a different device, you must first disable two-factor authentication.
%p
If you lose your recovery codes you can generate new ones, invalidating all previous codes.
%div
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index ced6a2a0399..dcef4dd5b69 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -5,7 +5,7 @@
.project-header.d-flex.flex-row.flex-wrap.align-items-center.append-bottom-8
.project-title-row.d-flex.align-items-center
.avatar-container.project-avatar.float-none
- = project_icon(@project, alt: @project.name, class: 'avatar avatar-tile')
+ = project_icon(@project, alt: @project.name, class: 'avatar avatar-tile s24', width: 24, height: 24)
%h1.project-title.d-flex.align-items-baseline.qa-project-name
= @project.name
.project-metadata.d-flex.flex-row.flex-wrap.align-items-baseline
@@ -76,8 +76,6 @@
= render 'projects/buttons/download', project: @project, ref: @ref
.d-none.d-sm-inline-flex
= render 'projects/buttons/dropdown'
- .d-none.d-sm-inline-flex
- = render 'projects/buttons/koding'
.d-none.d-sm-inline-flex
= render 'shared/notifications/button', notification_setting: @notification_setting
diff --git a/app/views/projects/_import_project_pane.html.haml b/app/views/projects/_import_project_pane.html.haml
index 32da38f14b9..2b425f18389 100644
--- a/app/views/projects/_import_project_pane.html.haml
+++ b/app/views/projects/_import_project_pane.html.haml
@@ -1,4 +1,5 @@
- active_tab = local_assigns.fetch(:active_tab, 'blank')
+- track_label = local_assigns.fetch(:track_label, 'import_project')
.project-import
.form-group.import-btn-container.clearfix
@@ -7,60 +8,63 @@
.import-buttons
- if gitlab_project_import_enabled?
.import_gitlab_project.has-tooltip{ data: { container: 'body' } }
- = link_to new_import_gitlab_project_path, class: 'btn btn_import_gitlab_project project-submit' do
+ = link_to new_import_gitlab_project_path, class: 'btn btn_import_gitlab_project project-submit', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "gitlab_export" } do
= icon('gitlab', text: 'GitLab export')
- if github_import_enabled?
%div
- = link_to new_import_github_path, class: 'btn js-import-github' do
+ = link_to new_import_github_path, class: 'btn js-import-github', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "github" } do
= icon('github', text: 'GitHub')
- if bitbucket_import_enabled?
%div
- = link_to status_import_bitbucket_path, class: "btn import_bitbucket #{'how_to_import_link' unless bitbucket_import_configured?}" do
+ = link_to status_import_bitbucket_path, class: "btn import_bitbucket #{'how_to_import_link' unless bitbucket_import_configured?}",
+ data: { track_label: "#{track_label}", track_event: "click_button", track_property: "bitbucket_cloud" } do
= icon('bitbucket', text: 'Bitbucket Cloud')
- unless bitbucket_import_configured?
= render 'bitbucket_import_modal'
- if bitbucket_server_import_enabled?
%div
- = link_to status_import_bitbucket_server_path, class: "btn import_bitbucket" do
+ = link_to status_import_bitbucket_server_path, class: "btn import_bitbucket",
+ data: { track_label: "#{track_label}", track_event: "click_button", track_property: "bitbucket_server" } do
= icon('bitbucket-square', text: 'Bitbucket Server')
%div
- if gitlab_import_enabled?
%div
- = link_to status_import_gitlab_path, class: "btn import_gitlab #{'how_to_import_link' unless gitlab_import_configured?}" do
+ = link_to status_import_gitlab_path, class: "btn import_gitlab #{'how_to_import_link' unless gitlab_import_configured?}",
+ data: { track_label: "#{track_label}", track_event: "click_button", track_property: "gitlab_com" } do
= icon('gitlab', text: 'GitLab.com')
- unless gitlab_import_configured?
= render 'gitlab_import_modal'
- if google_code_import_enabled?
%div
- = link_to new_import_google_code_path, class: 'btn import_google_code' do
+ = link_to new_import_google_code_path, class: 'btn import_google_code', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "google_code" } do
= icon('google', text: 'Google Code')
- if fogbugz_import_enabled?
%div
- = link_to new_import_fogbugz_path, class: 'btn import_fogbugz' do
+ = link_to new_import_fogbugz_path, class: 'btn import_fogbugz', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "fogbugz" } do
= icon('bug', text: 'Fogbugz')
- if gitea_import_enabled?
%div
- = link_to new_import_gitea_path, class: 'btn import_gitea' do
+ = link_to new_import_gitea_path, class: 'btn import_gitea', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "gitea" } do
= custom_icon('go_logo')
Gitea
- if git_import_enabled?
%div
- %button.btn.js-toggle-button.js-import-git-toggle-button{ type: "button", data: { toggle_open_class: 'active' } }
+ %button.btn.js-toggle-button.js-import-git-toggle-button{ type: "button", data: { toggle_open_class: 'active', data: { toggle_open_class: 'active', track_label: "#{track_label}" , track_event: "click_button", track_property: "repo_url" } } }
= icon('git', text: 'Repo by URL')
- if manifest_import_enabled?
%div
- = link_to new_import_manifest_path, class: 'btn import_manifest' do
+ = link_to new_import_manifest_path, class: 'btn import_manifest', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "manifest_file" } do
= icon('file-text-o', text: 'Manifest file')
.js-toggle-content.toggle-import-form{ class: ('hide' if active_tab != 'import') }
= form_for @project, html: { class: 'new_project' } do |f|
%hr
= render "shared/import_form", f: f
- = render 'new_project_fields', f: f, project_name_id: "import-url-name", hide_init_with_readme: true
+ = render 'new_project_fields', f: f, project_name_id: "import-url-name", hide_init_with_readme: true, track_label: track_label
diff --git a/app/views/projects/_md_preview.html.haml b/app/views/projects/_md_preview.html.haml
index 8fb6aa55436..0f709c65d0e 100644
--- a/app/views/projects/_md_preview.html.haml
+++ b/app/views/projects/_md_preview.html.haml
@@ -11,21 +11,23 @@
.md-header
%ul.nav.nav-tabs.nav-links.clearfix
%li.md-header-tab.active
- %a.js-md-write-button{ href: "#md-write-holder", tabindex: -1 }
+ %button.js-md-write-button{ tabindex: -1 }
Write
%li.md-header-tab
- %a.js-md-preview-button{ href: "#md-preview-holder", tabindex: -1 }
+ %button.js-md-preview-button{ tabindex: -1 }
Preview
%li.md-header-toolbar.active
- = markdown_toolbar_button({ icon: "bold", data: { "md-tag" => "**" }, title: "Add bold text" })
- = markdown_toolbar_button({ icon: "italic", data: { "md-tag" => "*" }, title: "Add italic text" })
- = markdown_toolbar_button({ icon: "quote", data: { "md-tag" => "> ", "md-prepend" => true }, title: "Insert a quote" })
- = markdown_toolbar_button({ icon: "code", data: { "md-tag" => "`", "md-block" => "```" }, title: "Insert code" })
- = markdown_toolbar_button({ icon: "list-bulleted", data: { "md-tag" => "* ", "md-prepend" => true }, title: "Add a bullet list" })
- = markdown_toolbar_button({ icon: "list-numbered", data: { "md-tag" => "1. ", "md-prepend" => true }, title: "Add a numbered list" })
- = markdown_toolbar_button({ icon: "task-done", data: { "md-tag" => "* [ ] ", "md-prepend" => true }, title: "Add a task list" })
- %button.toolbar-btn.toolbar-fullscreen-btn.js-zen-enter.has-tooltip{ type: "button", tabindex: -1, "aria-label": "Go full screen", title: "Go full screen", data: { container: "body" } }
+ = markdown_toolbar_button({ icon: "bold", data: { "md-tag" => "**" }, title: s_("MarkdownToolbar|Add bold text") })
+ = markdown_toolbar_button({ icon: "italic", data: { "md-tag" => "*" }, title: s_("MarkdownToolbar|Add italic text") })
+ = markdown_toolbar_button({ icon: "quote", data: { "md-tag" => "> ", "md-prepend" => true }, title: s_("MarkdownToolbar|Insert a quote") })
+ = markdown_toolbar_button({ icon: "code", data: { "md-tag" => "`", "md-block" => "```" }, title: s_("MarkdownToolbar|Insert code") })
+ = markdown_toolbar_button({ icon: "link", data: { "md-tag" => "[{text}](url)", "md-select" => "url" }, title: s_("MarkdownToolbar|Add a link") })
+ = markdown_toolbar_button({ icon: "list-bulleted", data: { "md-tag" => "* ", "md-prepend" => true }, title: s_("MarkdownToolbar|Add a bullet list") })
+ = markdown_toolbar_button({ icon: "list-numbered", data: { "md-tag" => "1. ", "md-prepend" => true }, title: s_("MarkdownToolbar|Add a numbered list") })
+ = markdown_toolbar_button({ icon: "task-done", data: { "md-tag" => "* [ ] ", "md-prepend" => true }, title: s_("MarkdownToolbar|Add a task list") })
+ = markdown_toolbar_button({ icon: "table", data: { "md-tag" => "| header | header |\n| ------ | ------ |\n| cell | cell |\n| cell | cell |", "md-prepend" => true }, title: s_("MarkdownToolbar|Add a table") })
+ %button.toolbar-btn.toolbar-fullscreen-btn.js-zen-enter.has-tooltip{ type: "button", tabindex: -1, "aria-label": "Go full screen", title: s_("MarkdownToolbar|Go full screen"), data: { container: "body" } }
= sprite_icon("screen-full")
.md-write-holder
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index db07c475866..ba7d3154326 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -1,13 +1,14 @@
- visibility_level = params.dig(:project, :visibility_level) || default_project_visibility
- ci_cd_only = local_assigns.fetch(:ci_cd_only, false)
- hide_init_with_readme = local_assigns.fetch(:hide_init_with_readme, false)
+- track_label = local_assigns.fetch(:track_label, 'blank_project')
.row{ id: project_name_id }
= f.hidden_field :ci_cd_only, value: ci_cd_only
.form-group.project-name.col-sm-12
= f.label :name, class: 'label-bold' do
%span= _("Project name")
- = f.text_field :name, placeholder: "My awesome project", class: "form-control input-lg", autofocus: true, required: true
+ = f.text_field :name, placeholder: "My awesome project", class: "form-control input-lg", autofocus: true, data: { track_label: "#{track_label}", track_event: "activate_form_input", track_property: "project_name", track_value: "" }
.form-group.project-path.col-sm-6
= f.label :namespace_id, class: 'label-bold' do
%span= s_("Project URL")
@@ -22,7 +23,7 @@
display_path: true,
extra_group: namespace_id),
{},
- { class: 'select2 js-select-namespace qa-project-namespace-select', tabindex: 1})
+ { class: 'select2 js-select-namespace qa-project-namespace-select', tabindex: 1, data: { track_label: "#{track_label}", track_event: "activate_form_input", track_property: "project_path", track_value: "" }})
- else
.input-group-prepend.static-namespace.has-tooltip{ title: user_url(current_user.username) + '/' }
@@ -32,7 +33,7 @@
.form-group.project-path.col-sm-6
= f.label :path, class: 'label-bold' do
%span= _("Project slug")
- = f.text_field :path, placeholder: "my-awesome-project", class: "form-control", tabindex: 2, required: true
+ = f.text_field :path, placeholder: "my-awesome-project", class: "form-control", required: true
- if current_user.can_create_group?
.form-text.text-muted
Want to house several dependent projects under the same namespace?
@@ -42,7 +43,7 @@
= f.label :description, class: 'label-bold' do
Project description
%span (optional)
- = f.text_area :description, placeholder: 'Description format', class: "form-control", rows: 3, maxlength: 250
+ = f.text_area :description, placeholder: 'Description format', class: "form-control", rows: 3, maxlength: 250, data: { track_label: "#{track_label}", track_event: "activate_form_input", track_property: "project_description", track_value: "" }
= f.label :visibility_level, class: 'label-bold' do
Visibility Level
@@ -53,12 +54,12 @@
.form-group.row.initialize-with-readme-setting
%div{ :class => "col-sm-12" }
.form-check
- = check_box_tag 'project[initialize_with_readme]', '1', false, class: 'form-check-input'
+ = check_box_tag 'project[initialize_with_readme]', '1', false, class: 'form-check-input', data: { track_label: "#{track_label}", track_event: "activate_form_input", track_property: "init_with_readme" }
= label_tag 'project[initialize_with_readme]', class: 'form-check-label' do
.option-title
%strong Initialize repository with a README
.option-description
Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository.
-= f.submit 'Create project', class: "btn btn-success project-submit", tabindex: 4
-= link_to 'Cancel', dashboard_projects_path, class: 'btn btn-cancel'
+= f.submit 'Create project', class: "btn btn-success project-submit", data: { track_label: "#{track_label}", track_event: "click_button", track_property: "create_project", track_value: "" }
+= link_to 'Cancel', dashboard_projects_path, class: 'btn btn-cancel', data: { track_label: "#{track_label}", track_event: "click_button", track_property: "cancel" }
diff --git a/app/views/projects/_project_templates.html.haml b/app/views/projects/_project_templates.html.haml
index 0f6f3ad6d5e..98fdb1d7a0b 100644
--- a/app/views/projects/_project_templates.html.haml
+++ b/app/views/projects/_project_templates.html.haml
@@ -5,4 +5,4 @@
.project-fields-form
= render 'projects/project_templates/project_fields_form'
- = render 'projects/new_project_fields', f: f, project_name_id: "template-project-name", hide_init_with_readme: true
+ = render 'projects/new_project_fields', f: f, project_name_id: "template-project-name", hide_init_with_readme: true, track_label: "create_from_template"
diff --git a/app/views/projects/_wiki.html.haml b/app/views/projects/_wiki.html.haml
index 5adca007f7e..45e1d32980c 100644
--- a/app/views/projects/_wiki.html.haml
+++ b/app/views/projects/_wiki.html.haml
@@ -5,14 +5,14 @@
= render_wiki_content(@wiki_home, legacy_render_context(params))
- else
- can_create_wiki = can?(current_user, :create_wiki, @project)
- .project-home-empty{ class: [('row-content-block' if can_create_wiki), ('content-block' unless can_create_wiki)] }
- .text-center{ class: container_class }
+ .landing{ class: [('row-content-block row p-0 align-items-center' if can_create_wiki), ('content-block' unless can_create_wiki)] }
+ .col-12.col-md-3.p-0
+ .svg-content
+ = image_tag 'illustrations/wiki_login_empty.svg'
+ .col-12.col-md-9.text-center.text-md-left.pl-md-0.pl-sm-3.mb-4
%h4
- This project does not have a wiki homepage yet
+ = _("This project does not have a wiki homepage yet")
- if can_create_wiki
%p
- Add a homepage to your wiki that contains information about your project
- %p
- We recommend you
- = link_to "add a homepage", project_wiki_path(@project, :home)
- to your project's wiki and GitLab will show it here instead of this message.
+ = _("Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message.")
+ = link_to _("Create your first page"), project_wiki_path(@project, :home) + '?view=create', class: "btn btn-primary"
diff --git a/app/views/projects/artifacts/browse.html.haml b/app/views/projects/artifacts/browse.html.haml
index 87b165e581a..09295940529 100644
--- a/app/views/projects/artifacts/browse.html.haml
+++ b/app/views/projects/artifacts/browse.html.haml
@@ -1,7 +1,7 @@
- breadcrumb_title _('Artifacts')
- page_title @path.presence, 'Artifacts', "#{@build.name} (##{@build.id})", 'Jobs'
-= render "projects/jobs/header", show_controls: false
+= render "projects/jobs/header"
- add_to_breadcrumbs(s_('CICD|Jobs'), project_jobs_path(@project))
- add_to_breadcrumbs("##{@build.id}", project_jobs_path(@project))
diff --git a/app/views/projects/artifacts/file.html.haml b/app/views/projects/artifacts/file.html.haml
index f7174d6b2c6..808b4acc8f3 100644
--- a/app/views/projects/artifacts/file.html.haml
+++ b/app/views/projects/artifacts/file.html.haml
@@ -1,6 +1,6 @@
- page_title @path, 'Artifacts', "#{@build.name} (##{@build.id})", 'Jobs'
-= render "projects/jobs/header", show_controls: false
+= render "projects/jobs/header"
.tree-holder
.nav-block
diff --git a/app/views/projects/blob/_editor.html.haml b/app/views/projects/blob/_editor.html.haml
index 24f256d083b..3c1f33ea95e 100644
--- a/app/views/projects/blob/_editor.html.haml
+++ b/app/views/projects/blob/_editor.html.haml
@@ -6,12 +6,12 @@
= sprite_icon('fork', size: 12)
= ref
- if current_action?(:edit) || current_action?(:update)
- %span.editor-file-name
+ %span.pull-left.append-right-10
= text_field_tag 'file_path', (params[:file_path] || @path),
class: 'form-control new-file-path js-file-path-name-input'
- if current_action?(:new) || current_action?(:create)
- %span.editor-file-name
+ %span.pull-left.append-right-10
\/
= text_field_tag 'file_name', params[:file_name], placeholder: "File name",
required: true, class: 'form-control new-file-name js-file-path-name-input'
diff --git a/app/views/projects/blob/_template_selectors.html.haml b/app/views/projects/blob/_template_selectors.html.haml
index 5b092427496..bd46f5a4349 100644
--- a/app/views/projects/blob/_template_selectors.html.haml
+++ b/app/views/projects/blob/_template_selectors.html.haml
@@ -3,15 +3,15 @@
Template
.template-selector-dropdowns-wrap
.template-type-selector.js-template-type-selector-wrap.hidden
- = dropdown_tag("Choose type", options: { toggle_class: 'js-template-type-selector', title: "Choose a template type" } )
+ = dropdown_tag("Choose type", options: { toggle_class: 'js-template-type-selector qa-template-type-dropdown', title: "Choose a template type" } )
.license-selector.js-license-selector-wrap.js-template-selector-wrap.hidden
- = dropdown_tag("Apply a license template", options: { toggle_class: 'js-license-selector', title: "Apply a license", filter: true, placeholder: "Filter", data: { data: licenses_for_select, project: @project.name, fullname: @project.namespace.human_name } } )
+ = dropdown_tag("Apply a license template", options: { toggle_class: 'js-license-selector qa-license-dropdown', title: "Apply a license", filter: true, placeholder: "Filter", data: { data: licenses_for_select(@project), project: @project.name, fullname: @project.namespace.human_name } } )
.gitignore-selector.js-gitignore-selector-wrap.js-template-selector-wrap.hidden
- = dropdown_tag("Apply a .gitignore template", options: { toggle_class: 'js-gitignore-selector', title: "Apply a template", filter: true, placeholder: "Filter", data: { data: gitignore_names } } )
+ = dropdown_tag("Apply a .gitignore template", options: { toggle_class: 'js-gitignore-selector qa-gitignore-dropdown', title: "Apply a template", filter: true, placeholder: "Filter", data: { data: gitignore_names(@project) } } )
.gitlab-ci-yml-selector.js-gitlab-ci-yml-selector-wrap.js-template-selector-wrap.hidden
- = dropdown_tag("Apply a GitLab CI Yaml template", options: { toggle_class: 'js-gitlab-ci-yml-selector', title: "Apply a template", filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls } } )
+ = dropdown_tag("Apply a GitLab CI Yaml template", options: { toggle_class: 'js-gitlab-ci-yml-selector qa-gitlab-ci-yml-dropdown', title: "Apply a template", filter: true, placeholder: "Filter", data: { data: gitlab_ci_ymls(@project) } } )
.dockerfile-selector.js-dockerfile-selector-wrap.js-template-selector-wrap.hidden
- = dropdown_tag("Apply a Dockerfile template", options: { toggle_class: 'js-dockerfile-selector', title: "Apply a template", filter: true, placeholder: "Filter", data: { data: dockerfile_names } } )
+ = dropdown_tag("Apply a Dockerfile template", options: { toggle_class: 'js-dockerfile-selector qa-dockerfile-dropdown', title: "Apply a template", filter: true, placeholder: "Filter", data: { data: dockerfile_names(@project) } } )
.template-selectors-undo-menu.hidden
%span.text-info Template applied
%button.btn.btn-sm.btn-info Undo
diff --git a/app/views/projects/blob/edit.html.haml b/app/views/projects/blob/edit.html.haml
index fdab8a53b41..3f2d96b70e5 100644
--- a/app/views/projects/blob/edit.html.haml
+++ b/app/views/projects/blob/edit.html.haml
@@ -24,7 +24,7 @@
= link_to '#preview', 'data-preview-url' => project_preview_blob_path(@project, @id, legacy_render: params[:legacy_render]) do
= editing_preview_title(@blob.name)
- = form_tag(project_update_blob_path(@project, @id), method: :put, class: 'js-quick-submit js-requires-input js-edit-blob-form', data: blob_editor_paths) do
+ = form_tag(project_update_blob_path(@project, @id), method: :put, class: 'js-quick-submit js-requires-input js-edit-blob-form', data: blob_editor_paths(@project)) do
= render 'projects/blob/editor', ref: @ref, path: @path, blob_data: @blob.data
= render 'shared/new_commit_form', placeholder: "Update #{@blob.name}"
= hidden_field_tag 'last_commit_sha', @last_commit_sha
diff --git a/app/views/projects/blob/new.html.haml b/app/views/projects/blob/new.html.haml
index 39442564a2b..4be87b9e074 100644
--- a/app/views/projects/blob/new.html.haml
+++ b/app/views/projects/blob/new.html.haml
@@ -7,7 +7,7 @@
New file
= render 'template_selectors'
.file-editor
- = form_tag(project_create_blob_path(@project, @id), method: :post, class: 'js-edit-blob-form js-new-blob-form js-quick-submit js-requires-input', data: blob_editor_paths) do
+ = form_tag(project_create_blob_path(@project, @id), method: :post, class: 'js-edit-blob-form js-new-blob-form js-quick-submit js-requires-input', data: blob_editor_paths(@project)) do
= render 'projects/blob/editor', ref: @ref
= render 'shared/new_commit_form', placeholder: "Add new file"
diff --git a/app/views/projects/blob/viewers/_highlight_embed.html.haml b/app/views/projects/blob/viewers/_highlight_embed.html.haml
index 9bd4ef6ad0b..6a631fef1a9 100644
--- a/app/views/projects/blob/viewers/_highlight_embed.html.haml
+++ b/app/views/projects/blob/viewers/_highlight_embed.html.haml
@@ -4,4 +4,6 @@
- blob.data.each_line.each_with_index do |_, index|
%span.diff-line-num= index + 1
.blob-content{ data: { blob_id: blob.id } }
- = highlight(blob.path, blob.data, repository: nil, plain: blob.no_highlighting?)
+ %pre.code.highlight
+ %code
+ = blob.present.highlight
diff --git a/app/views/projects/blob/viewers/_text.html.haml b/app/views/projects/blob/viewers/_text.html.haml
index a91df321ca0..26ad23da436 100644
--- a/app/views/projects/blob/viewers/_text.html.haml
+++ b/app/views/projects/blob/viewers/_text.html.haml
@@ -1 +1 @@
-= render 'shared/file_highlight', blob: viewer.blob, repository: @repository
+= render 'shared/file_highlight', blob: viewer.blob
diff --git a/app/views/projects/branches/_panel.html.haml b/app/views/projects/branches/_panel.html.haml
index 398f76d379a..0e4b119bb54 100644
--- a/app/views/projects/branches/_panel.html.haml
+++ b/app/views/projects/branches/_panel.html.haml
@@ -9,8 +9,7 @@
.card.prepend-top-10
.card-header
- %h4.card-title
- = panel_title
+ = panel_title
%ul.content-list.all-branches
- branches.first(overview_max_branches).each do |branch|
= render "projects/branches/branch", branch: branch, merged: project.repository.merged_to_root_ref?(branch)
diff --git a/app/views/projects/branches/new.html.haml b/app/views/projects/branches/new.html.haml
index 500536a5dbc..af8887b0c39 100644
--- a/app/views/projects/branches/new.html.haml
+++ b/app/views/projects/branches/new.html.haml
@@ -13,14 +13,14 @@
.form-group.row
= label_tag :branch_name, nil, class: 'col-form-label col-sm-2'
.col-sm-10
- = text_field_tag :branch_name, params[:branch_name], required: true, autofocus: true, class: 'form-control js-branch-name'
+ = text_field_tag :branch_name, params[:branch_name], required: true, autofocus: true, class: 'form-control js-branch-name monospace'
.form-text.text-muted.text-danger.js-branch-name-error
.form-group.row
= label_tag :ref, 'Create from', class: 'col-form-label col-sm-2'
.col-sm-10.create-from
.dropdown
= hidden_field_tag :ref, default_ref
- = button_tag type: 'button', title: default_ref, class: 'dropdown-menu-toggle wide js-branch-select git-revision-dropdown-toggle', required: true, data: { toggle: 'dropdown', selected: default_ref, field_name: 'ref' } do
+ = button_tag type: 'button', title: default_ref, class: 'dropdown-menu-toggle wide js-branch-select monospace', required: true, data: { toggle: 'dropdown', selected: default_ref, field_name: 'ref' } do
.text-left.dropdown-toggle-text= default_ref
= icon('chevron-down')
= render 'shared/ref_dropdown', dropdown_class: 'wide'
diff --git a/app/views/projects/buttons/_dropdown.html.haml b/app/views/projects/buttons/_dropdown.html.haml
index 8b9c52f0802..45515fb492f 100644
--- a/app/views/projects/buttons/_dropdown.html.haml
+++ b/app/views/projects/buttons/_dropdown.html.haml
@@ -8,7 +8,7 @@
- if show_menu
.project-action-button.dropdown.inline
- %a.btn.dropdown-toggle.has-tooltip{ href: '#', title: _('Create new...'), 'data-toggle' => 'dropdown', 'data-container' => 'body', 'aria-label' => _('Create new...'), 'data-display' => 'static' }
+ %a.btn.dropdown-toggle.has-tooltip.qa-create-new-dropdown{ href: '#', title: _('Create new...'), 'data-toggle' => 'dropdown', 'data-container' => 'body', 'aria-label' => _('Create new...'), 'data-display' => 'static' }
= icon('plus')
= icon("caret-down")
%ul.dropdown-menu.dropdown-menu-right.project-home-dropdown
@@ -28,7 +28,7 @@
%li.dropdown-header= _('This repository')
- if can_push_code
- %li= link_to _('New file'), project_new_blob_path(@project, @project.default_branch || 'master')
+ %li.qa-new-file-option= link_to _('New file'), project_new_blob_path(@project, @project.default_branch || 'master')
- unless @project.empty_repo?
%li= link_to _('New branch'), new_project_branch_path(@project)
%li= link_to _('New tag'), new_project_tag_path(@project)
diff --git a/app/views/projects/buttons/_koding.html.haml b/app/views/projects/buttons/_koding.html.haml
deleted file mode 100644
index e665ca61da8..00000000000
--- a/app/views/projects/buttons/_koding.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-- if koding_enabled? && current_user && @repository.koding_yml && @project.can_current_user_push_code?
- = link_to koding_project_url(@project), class: 'btn project-action-button inline', target: '_blank', rel: 'noopener noreferrer' do
- _('Run in IDE (Koding)')
diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml
index 44c1453e239..44e9cb84341 100644
--- a/app/views/projects/ci/builds/_build.html.haml
+++ b/app/views/projects/ci/builds/_build.html.haml
@@ -47,7 +47,9 @@
%span.badge.badge-info triggered
- if job.try(:allow_failure)
%span.badge.badge-danger allowed to fail
- - if job.action?
+ - if job.schedulable?
+ %span.badge.badge-info= s_('DelayedJobs|delayed')
+ - elsif job.action?
%span.badge.badge-info manual
- if pipeline_link
@@ -58,7 +60,7 @@
- if pipeline.user
= user_avatar(user: pipeline.user, size: 20)
- else
- %span.api API
+ %span.monospace API
- if admin
%td
@@ -99,8 +101,26 @@
= sprite_icon('download')
- if can?(current_user, :update_build, job)
- if job.active?
- = link_to cancel_project_job_path(job.project, job, return_to: request.original_url), method: :post, title: 'Cancel', class: 'btn btn-build' do
+ = link_to cancel_project_job_path(job.project, job, continue: { to: request.fullpath }), method: :post, title: 'Cancel', class: 'btn btn-build' do
= icon('remove', class: 'cred')
+ - elsif job.scheduled?
+ .btn-group
+ .btn.btn-default{ disabled: true }
+ = sprite_icon('planning')
+ %time.js-remaining-time{ datetime: job.scheduled_at.utc.iso8601 }
+ = duration_in_numbers(job.execute_in)
+ - confirmation_message = s_("DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes.") % { job_name: job.name }
+ = link_to play_project_job_path(job.project, job, return_to: request.original_url),
+ method: :post,
+ title: s_('DelayedJobs|Start now'),
+ class: 'btn btn-default btn-build has-tooltip',
+ data: { confirm: confirmation_message } do
+ = sprite_icon('play')
+ = link_to unschedule_project_job_path(job.project, job, return_to: request.original_url),
+ method: :post,
+ title: s_('DelayedJobs|Unschedule'),
+ class: 'btn btn-default btn-build has-tooltip' do
+ = sprite_icon('time-out')
- elsif allow_retry
- if job.playable? && !admin && can?(current_user, :update_build, job)
= link_to play_project_job_path(job.project, job, return_to: request.original_url), method: :post, title: 'Play', class: 'btn btn-build' do
diff --git a/app/views/projects/clusters/_advanced_settings.html.haml b/app/views/projects/clusters/_advanced_settings.html.haml
deleted file mode 100644
index 243e8cd9ba0..00000000000
--- a/app/views/projects/clusters/_advanced_settings.html.haml
+++ /dev/null
@@ -1,15 +0,0 @@
-- if can?(current_user, :admin_cluster, @cluster)
- - if @cluster.managed?
- .append-bottom-20
- %label.append-bottom-10
- = s_('ClusterIntegration|Google Kubernetes Engine')
- %p
- - link_gke = link_to(s_('ClusterIntegration|Google Kubernetes Engine'), @cluster.gke_cluster_url, target: '_blank', rel: 'noopener noreferrer')
- = s_('ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}').html_safe % { link_gke: link_gke }
-
- .sub-section.form-group
- %h4.text-danger
- = s_('ClusterIntegration|Remove Kubernetes cluster integration')
- %p
- = s_("ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster.")
- = link_to(s_('ClusterIntegration|Remove integration'), namespace_project_cluster_path(@project.namespace, @project, @cluster.id), method: :delete, class: 'btn btn-danger', data: { confirm: s_("ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster.")})
diff --git a/app/views/projects/clusters/_banner.html.haml b/app/views/projects/clusters/_banner.html.haml
deleted file mode 100644
index 73cfea0ef92..00000000000
--- a/app/views/projects/clusters/_banner.html.haml
+++ /dev/null
@@ -1,15 +0,0 @@
-.hidden.js-cluster-error.bs-callout.bs-callout-danger{ role: 'alert' }
- = s_('ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine')
- %p.js-error-reason
-
-.hidden.js-cluster-creating.bs-callout.bs-callout-info{ role: 'alert' }
- = s_('ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine...')
-
-.hidden.js-cluster-success.bs-callout.bs-callout-success{ role: 'alert' }
- = s_("ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details")
-
-- if show_cluster_security_warning?
- .js-cluster-security-warning.alert.alert-block.alert-dismissable.bs-callout.bs-callout-warning
- %button.close{ type: "button", data: { feature_id: UserCalloutsHelper::CLUSTER_SECURITY_WARNING, dismiss_endpoint: user_callouts_path } } &times;
- = s_("ClusterIntegration|The default cluster configuration grants access to many functionalities needed to successfully build and deploy a containerised application.")
- = link_to s_("More information"), help_page_path('user/project/clusters/index.md', anchor: 'security-implications')
diff --git a/app/views/projects/clusters/_cluster.html.haml b/app/views/projects/clusters/_cluster.html.haml
deleted file mode 100644
index 2d7f7c6b1fb..00000000000
--- a/app/views/projects/clusters/_cluster.html.haml
+++ /dev/null
@@ -1,24 +0,0 @@
-.gl-responsive-table-row
- .table-section.section-30
- .table-mobile-header{ role: "rowheader" }= s_("ClusterIntegration|Kubernetes cluster")
- .table-mobile-content
- = link_to cluster.name, namespace_project_cluster_path(@project.namespace, @project, cluster)
- .table-section.section-30
- .table-mobile-header{ role: "rowheader" }= s_("ClusterIntegration|Environment scope")
- .table-mobile-content= cluster.environment_scope
- .table-section.section-30
- .table-mobile-header{ role: "rowheader" }= s_("ClusterIntegration|Project namespace")
- .table-mobile-content= cluster.platform_kubernetes&.actual_namespace
- .table-section.section-10
- .table-mobile-header{ role: "rowheader" }
- .table-mobile-content
- %button.js-project-feature-toggle.project-feature-toggle{ type: "button",
- class: "#{'is-checked' if cluster.enabled?} #{'is-disabled' if !cluster.can_toggle_cluster?}",
- "aria-label": s_("ClusterIntegration|Toggle Kubernetes Cluster"),
- disabled: !cluster.can_toggle_cluster?,
- data: { endpoint: namespace_project_cluster_path(@project.namespace, @project, cluster, format: :json) } }
- %input.js-project-feature-toggle-input{ type: "hidden", value: cluster.enabled? }
- = icon("spinner spin", class: "loading-icon")
- %span.toggle-icon
- = sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
- = sprite_icon('status_failed_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-unchecked')
diff --git a/app/views/projects/clusters/_empty_state.html.haml b/app/views/projects/clusters/_empty_state.html.haml
deleted file mode 100644
index b8a3556a206..00000000000
--- a/app/views/projects/clusters/_empty_state.html.haml
+++ /dev/null
@@ -1,12 +0,0 @@
-.row.empty-state
- .col-12
- .svg-content= image_tag 'illustrations/clusters_empty.svg'
- .col-12
- .text-content
- %h4.text-center= s_('ClusterIntegration|Integrate Kubernetes cluster automation')
- - link_to_help_page = link_to(_('Learn more about Kubernetes'), help_page_path('user/project/clusters/index'), target: '_blank', rel: 'noopener noreferrer')
- %p= s_('ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}').html_safe % { link_to_help_page: link_to_help_page}
-
- - if can?(current_user, :create_cluster, @project)
- .text-center
- = link_to s_('ClusterIntegration|Add Kubernetes cluster'), new_project_cluster_path(@project), class: 'btn btn-success'
diff --git a/app/views/projects/clusters/_gcp_signup_offer_banner.html.haml b/app/views/projects/clusters/_gcp_signup_offer_banner.html.haml
deleted file mode 100644
index 73b11d509d3..00000000000
--- a/app/views/projects/clusters/_gcp_signup_offer_banner.html.haml
+++ /dev/null
@@ -1,12 +0,0 @@
-- link = link_to(s_('ClusterIntegration|sign up'), 'https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral', target: '_blank', rel: 'noopener noreferrer')
-.bs-callout.gcp-signup-offer.alert.alert-block.alert-dismissable.prepend-top-default.append-bottom-default{ role: 'alert' }
- %button.close{ type: "button", data: { feature_id: UserCalloutsHelper::GCP_SIGNUP_OFFER, dismiss_endpoint: user_callouts_path } } &times;
- .gcp-signup-offer--content
- .gcp-signup-offer--icon.append-right-8
- = sprite_icon("information", size: 16)
- .gcp-signup-offer--copy
- %h4= s_('ClusterIntegration|Did you know?')
- %p= s_('ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab\'s Google Kubernetes Engine Integration.').html_safe % { sign_up_link: link }
- %a.btn.btn-default{ href: 'https://goo.gl/AaJzRW', target: '_blank', rel: 'noopener noreferrer' }
- Apply for credit
-
diff --git a/app/views/projects/clusters/_integration_form.html.haml b/app/views/projects/clusters/_integration_form.html.haml
deleted file mode 100644
index d0a553e3414..00000000000
--- a/app/views/projects/clusters/_integration_form.html.haml
+++ /dev/null
@@ -1,31 +0,0 @@
-= form_for @cluster, url: namespace_project_cluster_path(@project.namespace, @project, @cluster), as: :cluster do |field|
- = form_errors(@cluster)
- .form-group
- %h5= s_('ClusterIntegration|Integration status')
- %label.append-bottom-0.js-cluster-enable-toggle-area
- %button{ type: 'button',
- class: "js-project-feature-toggle project-feature-toggle #{'is-checked' if @cluster.enabled?} #{'is-disabled' unless can?(current_user, :update_cluster, @cluster)}",
- "aria-label": s_("ClusterIntegration|Toggle Kubernetes cluster"),
- disabled: !can?(current_user, :update_cluster, @cluster) }
- = field.hidden_field :enabled, { class: 'js-project-feature-toggle-input'}
- %span.toggle-icon
- = sprite_icon('status_success_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-checked')
- = sprite_icon('status_failed_borderless', size: 16, css_class: 'toggle-icon-svg toggle-status-unchecked')
- .form-text.text-muted= s_('ClusterIntegration|Enable or disable GitLab\'s connection to your Kubernetes cluster.')
-
- - if has_multiple_clusters?(@project)
- .form-group
- %h5= s_('ClusterIntegration|Environment scope')
- = field.text_field :environment_scope, class: 'col-md-6 form-control js-select-on-focus', placeholder: s_('ClusterIntegration|Environment scope')
- .form-text.text-muted= s_("ClusterIntegration|Choose which of your environments will use this cluster.")
-
- - if can?(current_user, :update_cluster, @cluster)
- .form-group
- = field.submit _('Save changes'), class: 'btn btn-success'
-
- - unless has_multiple_clusters?(@project)
- %h5= s_('ClusterIntegration|Environment scope')
- %p
- %code *
- is the default environment scope for this cluster. This means that all jobs, regardless of their environment, will use this cluster.
- = link_to 'More information', ('https://docs.gitlab.com/ee/user/project/clusters/#setting-the-environment-scope')
diff --git a/app/views/projects/clusters/_sidebar.html.haml b/app/views/projects/clusters/_sidebar.html.haml
deleted file mode 100644
index 3d10348212f..00000000000
--- a/app/views/projects/clusters/_sidebar.html.haml
+++ /dev/null
@@ -1,9 +0,0 @@
-- clusters_help_url = help_page_path('user/project/clusters/index.md')
-- help_link_start = "<a href=\"%{url}\" target=\"_blank\" rel=\"noopener noreferrer\">".html_safe
-- help_link_end = '</a>'.html_safe
-%h4.prepend-top-0
- = s_('ClusterIntegration|Kubernetes cluster integration')
-%p
- = s_('ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way.')
-%p
- = s_('ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}.').html_safe % { help_link_start: help_link_start % { url: clusters_help_url }, help_link_end: help_link_end }
diff --git a/app/views/projects/clusters/gcp/_form.html.haml b/app/views/projects/clusters/gcp/_form.html.haml
deleted file mode 100644
index 0222bbf7338..00000000000
--- a/app/views/projects/clusters/gcp/_form.html.haml
+++ /dev/null
@@ -1,75 +0,0 @@
-= javascript_include_tag 'https://apis.google.com/js/api.js'
-- external_link_icon = icon('external-link')
-- zones_link_url = 'https://cloud.google.com/compute/docs/regions-zones/regions-zones'
-- machine_type_link_url = 'https://cloud.google.com/compute/docs/machine-types'
-- pricing_link_url = 'https://cloud.google.com/compute/pricing#machinetype'
-- help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe
-- help_link_end = ' %{external_link_icon}</a>'.html_safe % { external_link_icon: external_link_icon }
-
-%p
- - link_to_help_page = link_to(s_('ClusterIntegration|help page'), help_page_path('user/project/clusters/index'), target: '_blank', rel: 'noopener noreferrer')
- = s_('ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration.').html_safe % { link_to_help_page: link_to_help_page}
-
-%p= link_to('Select a different Google account', @authorize_url)
-
-= form_for @gcp_cluster, html: { class: 'js-gke-cluster-creation prepend-top-20', data: { token: token_in_session } }, url: create_gcp_namespace_project_clusters_path(@project.namespace, @project), as: :cluster do |field|
- = form_errors(@gcp_cluster)
- .form-group
- = field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-bold'
- = field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Kubernetes cluster name')
- .form-group
- = field.label :environment_scope, s_('ClusterIntegration|Environment scope'), class: 'label-bold'
- = field.text_field :environment_scope, class: 'form-control', readonly: !has_multiple_clusters?(@project), placeholder: s_('ClusterIntegration|Environment scope')
-
- = field.fields_for :provider_gcp, @gcp_cluster.provider_gcp do |provider_gcp_field|
- .form-group
- = provider_gcp_field.label :gcp_project_id, s_('ClusterIntegration|Google Cloud Platform project'), class: 'label-bold'
- .js-gcp-project-id-dropdown-entry-point{ data: { docsUrl: 'https://console.cloud.google.com/home/dashboard' } }
- = provider_gcp_field.hidden_field :gcp_project_id
- .dropdown
- %button.dropdown-menu-toggle.dropdown-menu-full-width{ type: 'button', disabled: true }
- %span.dropdown-toggle-text
- = _('Select project')
- = icon('chevron-down')
- %span.form-text.text-muted &nbsp;
-
- .form-group
- = provider_gcp_field.label :zone, s_('ClusterIntegration|Zone'), class: 'label-bold'
- .js-gcp-zone-dropdown-entry-point
- = provider_gcp_field.hidden_field :zone
- .dropdown
- %button.dropdown-menu-toggle.dropdown-menu-full-width{ type: 'button', disabled: true }
- %span.dropdown-toggle-text
- = _('Select project to choose zone')
- = icon('chevron-down')
- %p.form-text.text-muted
- = s_('ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}.').html_safe % { help_link_start: help_link_start % { url: zones_link_url }, help_link_end: help_link_end }
-
- .form-group
- = provider_gcp_field.label :num_nodes, s_('ClusterIntegration|Number of nodes'), class: 'label-bold'
- = provider_gcp_field.text_field :num_nodes, class: 'form-control', placeholder: '3'
-
- .form-group
- = provider_gcp_field.label :machine_type, s_('ClusterIntegration|Machine type'), class: 'label-bold'
- .js-gcp-machine-type-dropdown-entry-point
- = provider_gcp_field.hidden_field :machine_type
- .dropdown
- %button.dropdown-menu-toggle.dropdown-menu-full-width{ type: 'button', disabled: true }
- %span.dropdown-toggle-text
- = _('Select project and zone to choose machine type')
- = icon('chevron-down')
- %p.form-text.text-muted
- = s_('ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}.').html_safe % { help_link_start_machine_type: help_link_start % { url: machine_type_link_url }, help_link_start_pricing: help_link_start % { url: pricing_link_url }, help_link_end: help_link_end }
-
- - if rbac_clusters_feature_enabled?
- .form-group
- .form-check
- = provider_gcp_field.check_box :legacy_abac, { class: 'form-check-input' }, false, true
- = provider_gcp_field.label :legacy_abac, s_('ClusterIntegration|RBAC-enabled cluster (experimental)'), class: 'form-check-label label-bold'
- .form-text.text-muted
- = s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
- = s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
- = link_to _('More information'), help_page_path('user/project/clusters/index.md', anchor: 'role-based-access-control-rbac-experimental-support'), target: '_blank'
-
- .form-group
- = field.submit s_('ClusterIntegration|Create Kubernetes cluster'), class: 'js-gke-cluster-creation-submit btn btn-success', disabled: true
diff --git a/app/views/projects/clusters/gcp/_show.html.haml b/app/views/projects/clusters/gcp/_show.html.haml
deleted file mode 100644
index be84f2ae67c..00000000000
--- a/app/views/projects/clusters/gcp/_show.html.haml
+++ /dev/null
@@ -1,50 +0,0 @@
-.form-group
- %label.append-bottom-10{ for: 'cluster-name' }
- = s_('ClusterIntegration|Kubernetes cluster name')
- .input-group
- %input.form-control.cluster-name.js-select-on-focus{ value: @cluster.name, readonly: true }
- %span.input-group-append
- = clipboard_button(text: @cluster.name, title: s_('ClusterIntegration|Copy Kubernetes cluster name'), class: 'input-group-text btn-default')
-
-= form_for @cluster, url: namespace_project_cluster_path(@project.namespace, @project, @cluster), as: :cluster do |field|
- = form_errors(@cluster)
-
- = field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
- .form-group
- = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL')
- .input-group
- = platform_kubernetes_field.text_field :api_url, class: 'form-control js-select-on-focus', placeholder: s_('ClusterIntegration|API URL'), readonly: true
- %span.input-group-append
- = clipboard_button(text: @cluster.platform_kubernetes.api_url, title: s_('ClusterIntegration|Copy API URL'), class: 'input-group-text btn-default')
-
- .form-group
- = platform_kubernetes_field.label :ca_cert, s_('ClusterIntegration|CA Certificate')
- .input-group
- = platform_kubernetes_field.text_area :ca_cert, class: 'form-control js-select-on-focus', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)'), readonly: true
- %span.input-group-append.clipboard-addon
- = clipboard_button(text: @cluster.platform_kubernetes.ca_cert, title: s_('ClusterIntegration|Copy CA Certificate'), class: 'input-group-text btn-blank')
-
- .form-group
- = platform_kubernetes_field.label :token, s_('ClusterIntegration|Token')
- .input-group
- = platform_kubernetes_field.text_field :token, class: 'form-control js-cluster-token js-select-on-focus', type: 'password', placeholder: s_('ClusterIntegration|Token'), readonly: true
- %span.input-group-append
- %button.btn.btn-default.input-group-text.js-show-cluster-token{ type: 'button' }
- = s_('ClusterIntegration|Show')
- = clipboard_button(text: @cluster.platform_kubernetes.token, title: s_('ClusterIntegration|Copy Token'), class: 'btn-default')
-
- .form-group
- = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)')
- = platform_kubernetes_field.text_field :namespace, class: 'form-control', placeholder: s_('ClusterIntegration|Project namespace')
-
- - if rbac_clusters_feature_enabled?
- .form-group
- .form-check
- = platform_kubernetes_field.check_box :authorization_type, { class: 'form-check-input', disabled: true }, 'rbac', 'abac'
- = platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster (experimental)'), class: 'form-check-label label-bold'
- .form-text.text-muted
- = s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
- = s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
-
- .form-group
- = field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success'
diff --git a/app/views/projects/clusters/index.html.haml b/app/views/projects/clusters/index.html.haml
deleted file mode 100644
index a55de84b5cd..00000000000
--- a/app/views/projects/clusters/index.html.haml
+++ /dev/null
@@ -1,24 +0,0 @@
-- breadcrumb_title 'Kubernetes'
-- page_title "Kubernetes Clusters"
-
-= render_gcp_signup_offer
-
-.clusters-container
- - if @clusters.empty?
- = render "empty_state"
- - else
- .top-area.adjust
- .nav-text
- = s_("ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project")
- .ci-table.js-clusters-list
- .gl-responsive-table-row.table-row-header{ role: "row" }
- .table-section.section-30{ role: "rowheader" }
- = s_("ClusterIntegration|Kubernetes cluster")
- .table-section.section-30{ role: "rowheader" }
- = s_("ClusterIntegration|Environment scope")
- .table-section.section-30{ role: "rowheader" }
- = s_("ClusterIntegration|Project namespace")
- .table-section.section-10{ role: "rowheader" }
- - @clusters.each do |cluster|
- = render "cluster", cluster: cluster.present(current_user: current_user)
- = paginate @clusters, theme: "gitlab"
diff --git a/app/views/projects/clusters/new.html.haml b/app/views/projects/clusters/new.html.haml
deleted file mode 100644
index a38003f5750..00000000000
--- a/app/views/projects/clusters/new.html.haml
+++ /dev/null
@@ -1,36 +0,0 @@
-- breadcrumb_title 'Kubernetes'
-- page_title _("Kubernetes Cluster")
-- active_tab = local_assigns.fetch(:active_tab, 'gcp')
-= javascript_include_tag 'https://apis.google.com/js/api.js'
-
-= render_gcp_signup_offer
-
-.row.prepend-top-default
- .col-md-3
- = render 'sidebar'
- .col-md-9.js-toggle-container
- %ul.nav-links.nav-tabs.gitlab-tabs.nav{ role: 'tablist' }
- %li.nav-item{ role: 'presentation' }
- %a.nav-link{ href: '#create-gcp-cluster-pane', id: 'create-gcp-cluster-tab', class: active_when(active_tab == 'gcp'), data: { toggle: 'tab' }, role: 'tab' }
- %span Create new Cluster on GKE
- %li.nav-item{ role: 'presentation' }
- %a.nav-link{ href: '#add-user-cluster-pane', id: 'add-user-cluster-tab', class: active_when(active_tab == 'user'), data: { toggle: 'tab' }, role: 'tab' }
- %span Add existing cluster
-
- .tab-content.gitlab-tab-content
- .tab-pane{ id: 'create-gcp-cluster-pane', class: active_when(active_tab == 'gcp'), role: 'tabpanel' }
- = render 'projects/clusters/gcp/header'
- - if @valid_gcp_token
- = render 'projects/clusters/gcp/form'
- - elsif @authorize_url
- .signin-with-google
- = link_to(image_tag('auth_buttons/signin_with_google.png', width: '191px'), @authorize_url)
- = _('or')
- = link_to('create a new Google account', 'https://accounts.google.com/SignUpWithoutGmail?service=cloudconsole&continue=https%3A%2F%2Fconsole.cloud.google.com%2Ffreetrial%3Futm_campaign%3D2018_cpanel%26utm_source%3Dgitlab%26utm_medium%3Dreferral', target: '_blank', rel: 'noopener noreferrer')
- - else
- - link = link_to(s_('ClusterIntegration|properly configured'), help_page_path("integration/google"), target: '_blank', rel: 'noopener noreferrer')
- = s_('Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service.').html_safe % { link_to_documentation: link }
-
- .tab-pane{ id: 'add-user-cluster-pane', class: active_when(active_tab == 'user'), role: 'tabpanel' }
- = render 'projects/clusters/user/header'
- = render 'projects/clusters/user/form'
diff --git a/app/views/projects/clusters/show.html.haml b/app/views/projects/clusters/show.html.haml
deleted file mode 100644
index eddd3613c5f..00000000000
--- a/app/views/projects/clusters/show.html.haml
+++ /dev/null
@@ -1,52 +0,0 @@
-- @content_class = "limit-container-width" unless fluid_layout
-- add_to_breadcrumbs "Kubernetes Clusters", project_clusters_path(@project)
-- breadcrumb_title @cluster.name
-- page_title _("Kubernetes Cluster")
-
-- expanded = Rails.env.test?
-
-- status_path = status_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster.id, format: :json) if can?(current_user, :admin_cluster, @cluster)
-.edit-cluster-form.js-edit-cluster-form{ data: { status_path: status_path,
- install_helm_path: install_applications_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster, :helm),
- install_ingress_path: install_applications_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster, :ingress),
- install_prometheus_path: install_applications_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster, :prometheus),
- install_runner_path: install_applications_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster, :runner),
- install_jupyter_path: install_applications_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster, :jupyter),
- toggle_status: @cluster.enabled? ? 'true': 'false',
- cluster_status: @cluster.status_name,
- cluster_status_reason: @cluster.status_reason,
- help_path: help_page_path('user/project/clusters/index.md', anchor: 'installing-applications'),
- ingress_help_path: help_page_path('user/project/clusters/index.md', anchor: 'getting-the-external-ip-address'),
- ingress_dns_help_path: help_page_path('topics/autodevops/quick_start_guide.md', anchor: 'point-dns-at-cluster-ip'),
- manage_prometheus_path: edit_project_service_path(@cluster.project, 'prometheus') } }
-
- .js-cluster-application-notice
- .flash-container
-
- %section#cluster-integration
- %h4= @cluster.name
- = render 'banner'
- = render 'integration_form'
-
- .cluster-applications-table#js-cluster-applications
-
- %section.settings#js-cluster-details{ class: ('expanded' if expanded) }
- .settings-header
- %h4= s_('ClusterIntegration|Kubernetes cluster details')
- %button.btn.js-settings-toggle{ type: 'button' }
- = expanded ? 'Collapse' : 'Expand'
- %p= s_('ClusterIntegration|See and edit the details for your Kubernetes cluster')
- .settings-content
- - if @cluster.managed?
- = render 'projects/clusters/gcp/show'
- - else
- = render 'projects/clusters/user/show'
-
- %section.settings.no-animate#js-cluster-advanced-settings{ class: ('expanded' if expanded) }
- .settings-header
- %h4= _('Advanced settings')
- %button.btn.js-settings-toggle{ type: 'button' }
- = expanded ? 'Collapse' : 'Expand'
- %p= s_("ClusterIntegration|Advanced options on this Kubernetes cluster's integration")
- .settings-content
- = render 'advanced_settings'
diff --git a/app/views/projects/clusters/user/_form.html.haml b/app/views/projects/clusters/user/_form.html.haml
deleted file mode 100644
index f497f5b606c..00000000000
--- a/app/views/projects/clusters/user/_form.html.haml
+++ /dev/null
@@ -1,39 +0,0 @@
-= form_for @user_cluster, url: create_user_namespace_project_clusters_path(@project.namespace, @project), as: :cluster do |field|
- = form_errors(@user_cluster)
- .form-group
- = field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-bold'
- = field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Kubernetes cluster name')
- - if has_multiple_clusters?(@project)
- .form-group
- = field.label :environment_scope, s_('ClusterIntegration|Environment scope'), class: 'label-bold'
- = field.text_field :environment_scope, class: 'form-control', placeholder: s_('ClusterIntegration|Environment scope')
-
- = field.fields_for :platform_kubernetes, @user_cluster.platform_kubernetes do |platform_kubernetes_field|
- .form-group
- = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL'), class: 'label-bold'
- = platform_kubernetes_field.text_field :api_url, class: 'form-control', placeholder: s_('ClusterIntegration|API URL')
-
- .form-group
- = platform_kubernetes_field.label :ca_cert, s_('ClusterIntegration|CA Certificate'), class: 'label-bold'
- = platform_kubernetes_field.text_area :ca_cert, class: 'form-control', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)')
-
- .form-group
- = platform_kubernetes_field.label :token, s_('ClusterIntegration|Token'), class: 'label-bold'
- = platform_kubernetes_field.text_field :token, class: 'form-control', placeholder: s_('ClusterIntegration|Service token'), autocomplete: 'off'
-
- .form-group
- = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)'), class: 'label-bold'
- = platform_kubernetes_field.text_field :namespace, class: 'form-control', placeholder: s_('ClusterIntegration|Project namespace')
-
- - if rbac_clusters_feature_enabled?
- .form-group
- .form-check
- = platform_kubernetes_field.check_box :authorization_type, { class: 'form-check-input' }, 'rbac', 'abac'
- = platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster (experimental)'), class: 'form-check-label label-bold'
- .form-text.text-muted
- = s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
- = s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
- = link_to _('More information'), help_page_path('user/project/clusters/index.md', anchor: 'role-based-access-control-rbac-experimental-support'), target: '_blank'
-
- .form-group
- = field.submit s_('ClusterIntegration|Add Kubernetes cluster'), class: 'btn btn-success'
diff --git a/app/views/projects/clusters/user/_show.html.haml b/app/views/projects/clusters/user/_show.html.haml
deleted file mode 100644
index 56b597d295a..00000000000
--- a/app/views/projects/clusters/user/_show.html.haml
+++ /dev/null
@@ -1,39 +0,0 @@
-= form_for @cluster, url: namespace_project_cluster_path(@project.namespace, @project, @cluster), as: :cluster do |field|
- = form_errors(@cluster)
- .form-group
- = field.label :name, s_('ClusterIntegration|Kubernetes cluster name'), class: 'label-bold'
- = field.text_field :name, class: 'form-control', placeholder: s_('ClusterIntegration|Kubernetes cluster name')
-
- = field.fields_for :platform_kubernetes, @cluster.platform_kubernetes do |platform_kubernetes_field|
- .form-group
- = platform_kubernetes_field.label :api_url, s_('ClusterIntegration|API URL'), class: 'label-bold'
- = platform_kubernetes_field.text_field :api_url, class: 'form-control', placeholder: s_('ClusterIntegration|API URL')
-
- .form-group
- = platform_kubernetes_field.label :ca_cert, s_('ClusterIntegration|CA Certificate'), class: 'label-bold'
- = platform_kubernetes_field.text_area :ca_cert, class: 'form-control', placeholder: s_('ClusterIntegration|Certificate Authority bundle (PEM format)')
-
- .form-group
- = platform_kubernetes_field.label :token, s_('ClusterIntegration|Token'), class: 'label-bold'
- .input-group
- = platform_kubernetes_field.text_field :token, class: 'form-control js-cluster-token', type: 'password', placeholder: s_('ClusterIntegration|Token'), autocomplete: 'off'
- %span.input-group-append.clipboard-addon
- .input-group-text
- %button.js-show-cluster-token.btn-blank{ type: 'button' }
- = s_('ClusterIntegration|Show')
-
- .form-group
- = platform_kubernetes_field.label :namespace, s_('ClusterIntegration|Project namespace (optional, unique)'), class: 'label-bold'
- = platform_kubernetes_field.text_field :namespace, class: 'form-control', placeholder: s_('ClusterIntegration|Project namespace')
-
- - if rbac_clusters_feature_enabled?
- .form-group
- .form-check
- = platform_kubernetes_field.check_box :authorization_type, { class: 'form-check-input', disabled: true }, 'rbac', 'abac'
- = platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster (experimental)'), class: 'form-check-label label-bold'
- .form-text.text-muted
- = s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
- = s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
-
- .form-group
- = field.submit s_('ClusterIntegration|Save changes'), class: 'btn btn-success'
diff --git a/app/views/projects/commit/show.html.haml b/app/views/projects/commit/show.html.haml
index 541ae905246..79e32949db9 100644
--- a/app/views/projects/commit/show.html.haml
+++ b/app/views/projects/commit/show.html.haml
@@ -13,7 +13,7 @@
= render "ci_menu"
- else
.block-connector
- = render "projects/diffs/diffs", diffs: @diffs, environment: @environment
+ = render "projects/diffs/diffs", diffs: @diffs, environment: @environment, is_commit: true
.limited-width-notes
= render "shared/notes/notes_with_form", :autocomplete => true
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index 7951a5ddc9e..1a74b120c26 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -1,65 +1,57 @@
+-#-----------------------------------------------------------------
+ WARNING: Please keep changes up-to-date with the following files:
+ - `assets/javascripts/diffs/components/commit_item.vue`
+-#-----------------------------------------------------------------
- view_details = local_assigns.fetch(:view_details, false)
- merge_request = local_assigns.fetch(:merge_request, nil)
- project = local_assigns.fetch(:project) { merge_request&.project }
- ref = local_assigns.fetch(:ref) { merge_request&.source_branch }
- link = commit_path(project, commit, merge_request: merge_request)
-- cache_key = [project.full_path,
- ref,
- commit.id,
- Gitlab::CurrentSettings.current_application_settings,
- @path.presence,
- current_controller?(:commits),
- merge_request&.iid,
- view_details,
- commit.status(ref),
- I18n.locale].compact
-
-= cache(cache_key, expires_in: 1.day) do
- %li.commit.flex-row.js-toggle-container{ id: "commit-#{commit.short_id}" }
-
- .avatar-cell.d-none.d-sm-block
- = author_avatar(commit, size: 36, has_tooltip: false)
-
- .commit-detail.flex-list
- .commit-content.qa-commit-content
- - if view_details && merge_request
- = link_to commit.title, project_commit_path(project, commit.id, merge_request_iid: merge_request.iid), class: "commit-row-message item-title"
- - else
- = link_to_markdown_field(commit, :title, link, class: "commit-row-message item-title")
- %span.commit-row-message.d-block.d-sm-none
- &middot;
- = commit.short_id
- - if commit.status(ref)
- .d-block.d-sm-none
- = render_commit_status(commit, ref: ref)
- - if commit.description?
- %button.text-expander.js-toggle-button
- = sprite_icon('ellipsis_h', size: 12)
+%li.commit.flex-row.js-toggle-container{ id: "commit-#{commit.short_id}" }
+
+ .avatar-cell.d-none.d-sm-block
+ = author_avatar(commit, size: 36, has_tooltip: false)
+
+ .commit-detail.flex-list
+ .commit-content.qa-commit-content
+ - if view_details && merge_request
+ = link_to commit.title, project_commit_path(project, commit.id, merge_request_iid: merge_request.iid), class: "commit-row-message item-title"
+ - else
+ = link_to_markdown_field(commit, :title, link, class: "commit-row-message item-title")
+ %span.commit-row-message.d-block.d-sm-none
+ &middot;
+ = commit.short_id
+ - if commit.status(ref)
+ .d-block.d-sm-none
+ = render_commit_status(commit, ref: ref)
+ - if commit.description?
+ %button.text-expander.js-toggle-button
+ = sprite_icon('ellipsis_h', size: 12)
- .commiter
- - commit_author_link = commit_author_link(commit, avatar: false, size: 24)
- - commit_timeago = time_ago_with_tooltip(commit.authored_date, placement: 'bottom')
- - commit_text = _('%{commit_author_link} authored %{commit_timeago}') % { commit_author_link: commit_author_link, commit_timeago: commit_timeago }
- #{ commit_text.html_safe }
+ .committer
+ - commit_author_link = commit_author_link(commit, avatar: false, size: 24)
+ - commit_timeago = time_ago_with_tooltip(commit.authored_date, placement: 'bottom')
+ - commit_text = _('%{commit_author_link} authored %{commit_timeago}') % { commit_author_link: commit_author_link, commit_timeago: commit_timeago }
+ #{ commit_text.html_safe }
- - if commit.description?
- %pre.commit-row-description.js-toggle-content.append-bottom-8
- = preserve(markdown_field(commit, :description))
+ - if commit.description?
+ %pre.commit-row-description.js-toggle-content.append-bottom-8
+ = preserve(markdown_field(commit, :description))
- .commit-actions.flex-row.d-none.d-sm-flex
- - if request.xhr?
- = render partial: 'projects/commit/signature', object: commit.signature
- - else
- = render partial: 'projects/commit/ajax_signature', locals: { commit: commit }
+ .commit-actions.flex-row.d-none.d-sm-flex
+ - if request.xhr?
+ = render partial: 'projects/commit/signature', object: commit.signature
+ - else
+ = render partial: 'projects/commit/ajax_signature', locals: { commit: commit }
- - if commit.status(ref)
- = render_commit_status(commit, ref: ref)
+ - if commit.status(ref)
+ = render_commit_status(commit, ref: ref)
- .js-commit-pipeline-status{ data: { endpoint: pipelines_project_commit_path(project, commit.id, ref: ref) } }
+ .js-commit-pipeline-status{ data: { endpoint: pipelines_project_commit_path(project, commit.id, ref: ref) } }
- .commit-sha-group
- .label.label-monospace
- = commit.short_id
- = clipboard_button(text: commit.id, title: _("Copy commit SHA to clipboard"), class: "btn btn-default", container: "body")
- = link_to_browse_code(project, commit)
+ .commit-sha-group
+ .label.label-monospace
+ = commit.short_id
+ = clipboard_button(text: commit.id, title: _("Copy commit SHA to clipboard"), class: "btn btn-default", container: "body")
+ = link_to_browse_code(project, commit)
diff --git a/app/views/projects/compare/_form.html.haml b/app/views/projects/compare/_form.html.haml
index d24ee4a3251..9744d293c8b 100644
--- a/app/views/projects/compare/_form.html.haml
+++ b/app/views/projects/compare/_form.html.haml
@@ -8,7 +8,7 @@
.input-group-text
= s_("CompareBranches|Source")
= hidden_field_tag :to, params[:to]
- = button_tag type: 'button', title: params[:to], class: "form-control compare-dropdown-toggle js-compare-dropdown has-tooltip git-revision-dropdown-toggle", required: true, data: { refs_url: refs_project_path(@project), toggle: "dropdown", target: ".js-compare-to-dropdown", selected: params[:to], field_name: :to } do
+ = button_tag type: 'button', title: params[:to], class: "form-control compare-dropdown-toggle js-compare-dropdown has-tooltip monospace", required: true, data: { refs_url: refs_project_path(@project), toggle: "dropdown", target: ".js-compare-to-dropdown", selected: params[:to], field_name: :to } do
.dropdown-toggle-text.str-truncated= params[:to] || _("Select branch/tag")
= render 'shared/ref_dropdown'
.compare-ellipsis.inline ...
@@ -18,7 +18,7 @@
.input-group-text
= s_("CompareBranches|Target")
= hidden_field_tag :from, params[:from]
- = button_tag type: 'button', title: params[:from], class: "form-control compare-dropdown-toggle js-compare-dropdown has-tooltip git-revision-dropdown-toggle", required: true, data: { refs_url: refs_project_path(@project), toggle: "dropdown", target: ".js-compare-from-dropdown", selected: params[:from], field_name: :from } do
+ = button_tag type: 'button', title: params[:from], class: "form-control compare-dropdown-toggle js-compare-dropdown has-tooltip monospace", required: true, data: { refs_url: refs_project_path(@project), toggle: "dropdown", target: ".js-compare-from-dropdown", selected: params[:from], field_name: :from } do
.dropdown-toggle-text.str-truncated= params[:from] || _("Select branch/tag")
= render 'shared/ref_dropdown'
&nbsp;
diff --git a/app/views/projects/deploy_tokens/_form.html.haml b/app/views/projects/deploy_tokens/_form.html.haml
index 8b7535397bc..5412fcbc9d8 100644
--- a/app/views/projects/deploy_tokens/_form.html.haml
+++ b/app/views/projects/deploy_tokens/_form.html.haml
@@ -6,24 +6,24 @@
.form-group
= f.label :name, class: 'label-bold'
- = f.text_field :name, class: 'form-control', required: true
+ = f.text_field :name, class: 'form-control qa-deploy-token-name', required: true
.form-group
= f.label :expires_at, class: 'label-bold'
- = f.text_field :expires_at, class: 'datepicker form-control', value: f.object.expires_at
+ = f.text_field :expires_at, class: 'datepicker form-control qa-deploy-token-expires-at', value: f.object.expires_at
.form-group
= f.label :scopes, class: 'label-bold'
%fieldset.form-group.form-check
- = f.check_box :read_repository, class: 'form-check-input'
+ = f.check_box :read_repository, class: 'form-check-input qa-deploy-token-read-repository'
= label_tag ("deploy_token_read_repository"), 'read_repository', class: 'label-bold form-check-label'
.text-secondary= s_('DeployTokens|Allows read-only access to the repository')
- if container_registry_enabled?(project)
%fieldset.form-group.form-check
- = f.check_box :read_registry, class: 'form-check-input'
+ = f.check_box :read_registry, class: 'form-check-input qa-deploy-token-read-registry'
= label_tag ("deploy_token_read_registry"), 'read_registry', class: 'label-bold form-check-label'
.text-secondary= s_('DeployTokens|Allows read-only access to the registry images')
.prepend-top-default
- = f.submit s_('DeployTokens|Create deploy token'), class: 'btn btn-success'
+ = f.submit s_('DeployTokens|Create deploy token'), class: 'btn btn-success qa-create-deploy-token'
diff --git a/app/views/projects/deploy_tokens/_index.html.haml b/app/views/projects/deploy_tokens/_index.html.haml
index 33faab0c510..4619522cfaf 100644
--- a/app/views/projects/deploy_tokens/_index.html.haml
+++ b/app/views/projects/deploy_tokens/_index.html.haml
@@ -1,6 +1,6 @@
- expanded = expand_deploy_tokens_section?(@new_deploy_token)
-%section.settings.no-animate#js-deploy-tokens{ class: ('expanded' if expanded) }
+%section.qa-deploy-tokens-settings.settings.no-animate#js-deploy-tokens{ class: ('expanded' if expanded) }
.settings-header
%h4= s_('DeployTokens|Deploy Tokens')
%button.btn.js-settings-toggle.qa-expand-deploy-keys{ type: 'button' }
diff --git a/app/views/projects/deploy_tokens/_new_deploy_token.html.haml b/app/views/projects/deploy_tokens/_new_deploy_token.html.haml
index 5dd9ffba074..c805ee73acc 100644
--- a/app/views/projects/deploy_tokens/_new_deploy_token.html.haml
+++ b/app/views/projects/deploy_tokens/_new_deploy_token.html.haml
@@ -1,18 +1,18 @@
-.created-deploy-token-container.info-well
+.qa-created-deploy-token-section.created-deploy-token-container.info-well
.well-segment
%h5.prepend-top-0
= s_('DeployTokens|Your New Deploy Token')
.form-group
.input-group
- = text_field_tag 'deploy-token-user', deploy_token.username, readonly: true, class: 'deploy-token-field form-control js-select-on-focus'
+ = text_field_tag 'deploy-token-user', deploy_token.username, readonly: true, class: 'deploy-token-field form-control js-select-on-focus qa-deploy-token-user'
.input-group-append
= clipboard_button(text: deploy_token.username, title: s_('DeployTokens|Copy username to clipboard'), placement: 'left')
%span.deploy-token-help-block.prepend-top-5.text-success= s_("DeployTokens|Use this username as a login.")
.form-group
.input-group
- = text_field_tag 'deploy-token', deploy_token.token, readonly: true, class: 'deploy-token-field form-control js-select-on-focus'
+ = text_field_tag 'deploy-token', deploy_token.token, readonly: true, class: 'deploy-token-field form-control js-select-on-focus qa-deploy-token'
.input-group-append
= clipboard_button(text: deploy_token.token, title: s_('DeployTokens|Copy deploy token to clipboard'), placement: 'left')
%span.deploy-token-help-block.prepend-top-5.text-danger= s_("DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again.")
diff --git a/app/views/projects/deployments/_rollback.haml b/app/views/projects/deployments/_rollback.haml
index 281e042c915..1bd538a08ff 100644
--- a/app/views/projects/deployments/_rollback.haml
+++ b/app/views/projects/deployments/_rollback.haml
@@ -1,4 +1,4 @@
-- if can?(current_user, :create_deployment, deployment) && deployment.deployable
+- if can?(current_user, :create_deployment, deployment)
- tooltip = deployment.last? ? s_('Environments|Re-deploy to environment') : s_('Environments|Rollback environment')
= link_to [:retry, @project.namespace.becomes(Namespace), @project, deployment.deployable], method: :post, class: 'btn btn-build has-tooltip', title: tooltip do
- if deployment.last?
diff --git a/app/views/projects/diffs/_collapsed.html.haml b/app/views/projects/diffs/_collapsed.html.haml
index 9bd1255fe00..94dcda38bd6 100644
--- a/app/views/projects/diffs/_collapsed.html.haml
+++ b/app/views/projects/diffs/_collapsed.html.haml
@@ -1,5 +1,5 @@
- diff_file = viewer.diff_file
- url = url_for(safe_params.merge(action: :diff_for_path, old_path: diff_file.old_path, new_path: diff_file.new_path, file_identifier: diff_file.file_identifier))
.nothing-here-block.diff-collapsed{ data: { diff_for_path: url } }
- This diff is collapsed.
- %button.click-to-expand.btn.btn-link Click to expand it.
+ = _("This diff is collapsed.")
+ %button.click-to-expand.btn.btn-link= _("Click to expand it.")
diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml
index 077c6c68f7e..cc2d0d3b2d8 100644
--- a/app/views/projects/diffs/_diffs.html.haml
+++ b/app/views/projects/diffs/_diffs.html.haml
@@ -2,13 +2,13 @@
- show_whitespace_toggle = local_assigns.fetch(:show_whitespace_toggle, true)
- can_create_note = !@diff_notes_disabled && can?(current_user, :create_note, diffs.project)
- diff_files = diffs.diff_files
-- merge_request = local_assigns.fetch(:merge_request, false)
+- is_commit = local_assigns.fetch(:is_commit, false)
-.content-block.oneline-block.files-changed.diff-files-changed.js-diff-files-changed{ class: ("diff-files-changed-merge-request" if merge_request) }
+.content-block.oneline-block.files-changed.diff-files-changed.js-diff-files-changed
.files-changed-inner
.inline-parallel-buttons.d-none.d-sm-none.d-md-block
- if !diffs_expanded? && diff_files.any? { |diff_file| diff_file.collapsed? }
- = link_to 'Expand all', url_for(safe_params.merge(expanded: 1, format: nil)), class: 'btn btn-default'
+ = link_to _('Expand all'), url_for(safe_params.merge(expanded: 1, format: nil)), class: 'btn btn-default'
- if show_whitespace_toggle
- if current_controller?(:commit)
= commit_diff_whitespace_link(diffs.project, @commit, class: 'd-none d-sm-inline-block')
@@ -25,4 +25,4 @@
= render 'projects/diffs/warning', diff_files: diffs
.files{ data: { can_create_note: can_create_note } }
- = render partial: 'projects/diffs/file', collection: diff_files, as: :diff_file, locals: { project: diffs.project, environment: environment }
+ = render partial: 'projects/diffs/file', collection: diff_files, as: :diff_file, locals: { project: diffs.project, environment: environment, is_commit: is_commit }
diff --git a/app/views/projects/diffs/_file.html.haml b/app/views/projects/diffs/_file.html.haml
index b4df654c839..5565ae1d98b 100644
--- a/app/views/projects/diffs/_file.html.haml
+++ b/app/views/projects/diffs/_file.html.haml
@@ -1,10 +1,11 @@
- environment = local_assigns.fetch(:environment, nil)
+- is_commit = local_assigns.fetch(:is_commit, false)
- file_hash = hexdigest(diff_file.file_path)
- image_diff = diff_file.rich_viewer && diff_file.rich_viewer.partial_name == 'image'
- image_replaced = diff_file.old_content_sha && diff_file.old_content_sha != diff_file.content_sha
.diff-file.file-holder{ id: file_hash, data: diff_file_html_data(project, diff_file.file_path, diff_file.content_sha) }
- .js-file-title.file-title-flex-parent
+ .js-file-title.file-title-flex-parent{ class: is_commit ? "is-commit" : "" }
.file-header-content
= render "projects/diffs/file_header", diff_file: diff_file, url: "##{file_hash}"
@@ -12,7 +13,7 @@
- blob = diff_file.blob
.file-actions.d-none.d-sm-block
- if blob&.readable_text?
- = link_to '#', class: 'js-toggle-diff-comments btn active has-tooltip', title: "Toggle comments for this file", disabled: @diff_notes_disabled do
+ = link_to '#', class: 'js-toggle-diff-comments btn active has-tooltip', title: _("Toggle comments for this file"), disabled: @diff_notes_disabled do
= icon('comment')
\
- if editable_diff?(diff_file)
diff --git a/app/views/projects/diffs/_file_header.html.haml b/app/views/projects/diffs/_file_header.html.haml
index 4cb04d744dc..6a1bff8640c 100644
--- a/app/views/projects/diffs/_file_header.html.haml
+++ b/app/views/projects/diffs/_file_header.html.haml
@@ -28,7 +28,7 @@
= diff_file.file_path
- if diff_file.deleted_file?
- deleted
+ = _("deleted")
= copy_file_path_button(diff_file.file_path)
diff --git a/app/views/projects/diffs/_render_error.html.haml b/app/views/projects/diffs/_render_error.html.haml
index 47a9ac3ee6b..c3dc47a56a7 100644
--- a/app/views/projects/diffs/_render_error.html.haml
+++ b/app/views/projects/diffs/_render_error.html.haml
@@ -1,5 +1,5 @@
.nothing-here-block
- This #{viewer.switcher_title} could not be displayed because #{diff_render_error_reason(viewer)}.
+ = _("This %{viewer} could not be displayed because %{reason}.") % { viewer: viewer.switcher_title, reason: diff_render_error_reason(viewer) }
You can
= diff_render_error_options(viewer).to_sentence(two_words_connector: ' or ', last_word_connector: ', or ').html_safe
diff --git a/app/views/projects/diffs/_stats.html.haml b/app/views/projects/diffs/_stats.html.haml
index 229a4574eeb..c9057f385da 100644
--- a/app/views/projects/diffs/_stats.html.haml
+++ b/app/views/projects/diffs/_stats.html.haml
@@ -38,4 +38,4 @@
\-#{diff_file.removed_lines}
%li.dropdown-menu-empty-item.hidden
%a
- No files found.
+ = _("No files found.")
diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml
index e8a5e63e59e..56427a74d56 100644
--- a/app/views/projects/diffs/_text_file.html.haml
+++ b/app/views/projects/diffs/_text_file.html.haml
@@ -1,9 +1,9 @@
- too_big = diff_file.diff_lines.count > Commit::DIFF_SAFE_LINES
- if too_big
.suppressed-container
- %a.show-suppressed-diff.js-show-suppressed-diff Changes suppressed. Click to show.
+ %a.show-suppressed-diff.js-show-suppressed-diff= _("Changes suppressed. Click to show.")
-%table.text-file.diff-wrap-lines.code.js-syntax-highlight{ data: diff_view_data, class: too_big ? 'hide' : '' }
+%table.text-file.diff-wrap-lines.code.js-syntax-highlight.commit-diff{ data: diff_view_data, class: too_big ? 'hide' : '' }
= render partial: "projects/diffs/line",
collection: diff_file.highlighted_diff_lines,
as: :line,
diff --git a/app/views/projects/diffs/_warning.html.haml b/app/views/projects/diffs/_warning.html.haml
index abe494f2974..2eef599cf84 100644
--- a/app/views/projects/diffs/_warning.html.haml
+++ b/app/views/projects/diffs/_warning.html.haml
@@ -1,14 +1,12 @@
.alert.alert-warning
%h4
- Too many changes to show.
+ = _("Too many changes to show.")
.float-right
- if current_controller?(:commit)
- = link_to "Plain diff", project_commit_path(@project, @commit, format: :diff), class: "btn btn-sm"
- = link_to "Email patch", project_commit_path(@project, @commit, format: :patch), class: "btn btn-sm"
+ = link_to _("Plain diff"), project_commit_path(@project, @commit, format: :diff), class: "btn btn-sm"
+ = link_to _("Email patch"), project_commit_path(@project, @commit, format: :patch), class: "btn btn-sm"
- elsif current_controller?('projects/merge_requests/diffs') && @merge_request&.persisted?
- = link_to "Plain diff", merge_request_path(@merge_request, format: :diff), class: "btn btn-sm"
- = link_to "Email patch", merge_request_path(@merge_request, format: :patch), class: "btn btn-sm"
+ = link_to _("Plain diff"), merge_request_path(@merge_request, format: :diff), class: "btn btn-sm"
+ = link_to _("Email patch"), merge_request_path(@merge_request, format: :patch), class: "btn btn-sm"
%p
- To preserve performance only
- %strong #{diff_files.size} of #{diff_files.real_size}
- files are displayed.
+ = _("To preserve performance only <strong>%{display_size} of ${real_size}</strong> files are displayed.").html_safe % { display_size: diff_files.size, real_size: diff_files.real_size }
diff --git a/app/views/projects/diffs/viewers/_added.html.haml b/app/views/projects/diffs/viewers/_added.html.haml
index 8004fe16688..f4c574a018f 100644
--- a/app/views/projects/diffs/viewers/_added.html.haml
+++ b/app/views/projects/diffs/viewers/_added.html.haml
@@ -1,2 +1,2 @@
.nothing-here-block
- File added
+ = _("File added")
diff --git a/app/views/projects/diffs/viewers/_deleted.html.haml b/app/views/projects/diffs/viewers/_deleted.html.haml
index 0ac7b4ca8f6..b82ca4d0787 100644
--- a/app/views/projects/diffs/viewers/_deleted.html.haml
+++ b/app/views/projects/diffs/viewers/_deleted.html.haml
@@ -1,2 +1,2 @@
.nothing-here-block
- File deleted
+ = _("File deleted")
diff --git a/app/views/projects/diffs/viewers/_mode_changed.html.haml b/app/views/projects/diffs/viewers/_mode_changed.html.haml
index 69bc96bbdad..a8d6f5fe400 100644
--- a/app/views/projects/diffs/viewers/_mode_changed.html.haml
+++ b/app/views/projects/diffs/viewers/_mode_changed.html.haml
@@ -1,3 +1,3 @@
- diff_file = viewer.diff_file
.nothing-here-block
- File mode changed from #{diff_file.a_mode} to #{diff_file.b_mode}
+ = _("File mode changed from %{a_mode} to %{b_mode}") % { a_mode: diff_file.a_mode, b_mode: diff_file.b_mode }
diff --git a/app/views/projects/diffs/viewers/_no_preview.html.haml b/app/views/projects/diffs/viewers/_no_preview.html.haml
index befe070af2b..b763ac34bf8 100644
--- a/app/views/projects/diffs/viewers/_no_preview.html.haml
+++ b/app/views/projects/diffs/viewers/_no_preview.html.haml
@@ -1,2 +1,2 @@
.nothing-here-block
- No preview for this file type
+ = _("No preview for this file type")
diff --git a/app/views/projects/diffs/viewers/_not_diffable.html.haml b/app/views/projects/diffs/viewers/_not_diffable.html.haml
index b2c677ec59c..7c55e272f56 100644
--- a/app/views/projects/diffs/viewers/_not_diffable.html.haml
+++ b/app/views/projects/diffs/viewers/_not_diffable.html.haml
@@ -1,2 +1,2 @@
.nothing-here-block
- This diff was suppressed by a .gitattributes entry.
+ = _("This diff was suppressed by a .gitattributes entry.")
diff --git a/app/views/projects/diffs/viewers/_renamed.html.haml b/app/views/projects/diffs/viewers/_renamed.html.haml
index ef05ee38d8d..b7336c356fe 100644
--- a/app/views/projects/diffs/viewers/_renamed.html.haml
+++ b/app/views/projects/diffs/viewers/_renamed.html.haml
@@ -1,2 +1,2 @@
.nothing-here-block
- File moved
+ = _("File moved")
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 96ab582b050..f376df29878 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -40,14 +40,14 @@
.form-group
= f.label :tag_list, "Tags", class: 'label-bold'
- = f.text_field :tag_list, value: @project.tag_list.sort.join(', '), maxlength: 2000, class: "form-control"
+ = f.text_field :tag_list, value: @project.tag_list.join(', '), maxlength: 2000, class: "form-control"
%p.form-text.text-muted Separate tags with commas.
%fieldset.features
%h5.prepend-top-0= _("Project avatar")
.form-group
- if @project.avatar?
.avatar-container.s160.append-bottom-15
- = project_icon(@project.full_path, alt: '', class: 'avatar project-avatar s160', width: 160, height: 160)
+ = project_icon(@project, alt: '', class: 'avatar project-avatar s160', width: 160, height: 160)
- if @project.avatar_in_git
%p.light
= _("Project avatar in repository: %{link}").html_safe % { link: @project.avatar_in_git }
@@ -95,6 +95,8 @@
= render 'projects/merge_request_settings', form: f
= f.submit 'Save changes', class: "btn btn-success qa-save-merge-request-changes"
+ = render_if_exists 'projects/merge_request_approvals_settings', expanded: expanded
+
= render_if_exists 'projects/service_desk_settings'
%section.settings.no-animate{ class: ('expanded' if expanded) }
@@ -148,7 +150,7 @@
= link_to 'Archive project', archive_project_path(@project),
data: { confirm: "Are you sure that you want to archive this project?" },
method: :post, class: "btn btn-warning"
- .sub-section.rename-respository
+ .sub-section.rename-repository
%h4.warning-title
Rename repository
= render 'projects/errors'
@@ -165,7 +167,7 @@
.input-group
.input-group-prepend
.input-group-text
- #{URI.join(root_url, @project.namespace.full_path)}/
+ #{Gitlab::Utils.append_path(root_url, @project.namespace.full_path)}/
= f.text_field :path, class: 'form-control'
%ul
%li Be careful. Renaming a project's repository can have unintended side effects.
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index d104608b2fe..936900a0087 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -9,7 +9,7 @@
.project-empty-note-panel
%div{ class: [container_class, ("limit-container-width" unless fluid_layout)] }
.prepend-top-20
- %h4
+ %h4.append-bottom-20
= _('The repository for this project is empty')
- if @project.can_current_user_push_code?
@@ -36,7 +36,7 @@
.scrolling-tabs-container.inner-page-scroll-tabs.is-smaller
.fade-left= icon('angle-left')
.fade-right= icon('angle-right')
- .nav-links.scrolling-tabs
+ .nav-links.scrolling-tabs.quick-links
= render 'stat_anchor_list', anchors: @project.empty_repo_statistics_anchors
= render 'stat_anchor_list', anchors: @project.empty_repo_statistics_buttons
diff --git a/app/views/projects/environments/_external_url.html.haml b/app/views/projects/environments/_external_url.html.haml
index 4694bc39d54..82567f88ccc 100644
--- a/app/views/projects/environments/_external_url.html.haml
+++ b/app/views/projects/environments/_external_url.html.haml
@@ -1,4 +1,4 @@
- if environment.external_url && can?(current_user, :read_environment, environment)
- = link_to environment.external_url, target: '_blank', rel: 'noopener noreferrer', class: 'btn external-url has-tooltip', title: s_('Environments|Open live environment') do
+ = link_to environment.external_url, target: '_blank', rel: 'noopener noreferrer', class: 'btn external-url has-tooltip qa-view-deployment', title: s_('Environments|Open live environment') do
= sprite_icon('external-link')
- View deployment
+ = _("View deployment")
diff --git a/app/views/projects/environments/_form.html.haml b/app/views/projects/environments/_form.html.haml
index f942b936037..cbd5c54cecc 100644
--- a/app/views/projects/environments/_form.html.haml
+++ b/app/views/projects/environments/_form.html.haml
@@ -1,22 +1,21 @@
.row.prepend-top-default.append-bottom-default
.col-lg-3
%h4.prepend-top-0
- Environments
+ = _("Environments")
%p
- Environments allow you to track deployments of your application
- = succeed "." do
- = link_to "Read more about environments", help_page_path("ci/environments")
+ - link_to_read_more = link_to(_("Read more about environments"), help_page_path("ci/environments"))
+ = _("Environments allow you to track deployments of your application %{link_to_read_more}.").html_safe % { link_to_read_more: link_to_read_more }
= form_for [@project.namespace.becomes(Namespace), @project, @environment], html: { class: 'col-lg-9' } do |f|
= form_errors(@environment)
.form-group
- = f.label :name, 'Name', class: 'label-bold'
+ = f.label :name, _('Name'), class: 'label-bold'
= f.text_field :name, required: true, class: 'form-control'
.form-group
- = f.label :external_url, 'External URL', class: 'label-bold'
+ = f.label :external_url, _('External URL'), class: 'label-bold'
= f.url_field :external_url, class: 'form-control'
.form-actions
- = f.submit 'Save', class: 'btn btn-success'
- = link_to 'Cancel', project_environments_path(@project), class: 'btn btn-cancel'
+ = f.submit _('Save'), class: 'btn btn-save'
+ = link_to _('Cancel'), project_environments_path(@project), class: 'btn btn-cancel'
diff --git a/app/views/projects/environments/_metrics_button.html.haml b/app/views/projects/environments/_metrics_button.html.haml
index a4b27575095..c4f19ea79e7 100644
--- a/app/views/projects/environments/_metrics_button.html.haml
+++ b/app/views/projects/environments/_metrics_button.html.haml
@@ -2,6 +2,6 @@
- return unless can?(current_user, :read_environment, environment)
-= link_to environment_metrics_path(environment), title: 'See metrics', class: 'btn metrics-button' do
+= link_to environment_metrics_path(environment), title: _('See metrics'), class: 'btn metrics-button' do
= sprite_icon('chart')
- Monitoring
+ = _("Monitoring")
diff --git a/app/views/projects/environments/edit.html.haml b/app/views/projects/environments/edit.html.haml
index d6ff3f729b4..d581bd3aeab 100644
--- a/app/views/projects/environments/edit.html.haml
+++ b/app/views/projects/environments/edit.html.haml
@@ -1,8 +1,8 @@
- @no_container = true
-- page_title "Edit", @environment.name, "Environments"
+- page_title _("Edit"), @environment.name, _("Environments")
%div{ class: container_class }
%h3.page-title
- Edit environment
+ = _('Edit environment')
%hr
= render 'form'
diff --git a/app/views/projects/environments/empty.html.haml b/app/views/projects/environments/empty.html.haml
index 1413930ebdb..129dbbf4e56 100644
--- a/app/views/projects/environments/empty.html.haml
+++ b/app/views/projects/environments/empty.html.haml
@@ -1,14 +1,14 @@
- page_title _("Metrics")
-.row
+.row.empty-state
.col-sm-12
.svg-content
= image_tag 'illustrations/operations_metrics_empty.svg'
-.row.empty-environments
- .col-sm-12.text-center
- %h4
- = s_('Metrics|No deployed environments')
- .state-description
- = s_('Metrics|Check out the CI/CD documentation on deploying to an environment')
- .prepend-top-10
- = link_to s_("Metrics|Learn about environments"), help_page_path('ci/environments'), class: 'btn btn-success'
+ .col-12
+ .text-content
+ %h4.text-center
+ = s_('Metrics|No deployed environments')
+ %p.state-description
+ = s_('Metrics|Check out the CI/CD documentation on deploying to an environment')
+ .text-center
+ = link_to s_("Metrics|Learn about environments"), help_page_path('ci/environments'), class: 'btn btn-success'
diff --git a/app/views/projects/environments/folder.html.haml b/app/views/projects/environments/folder.html.haml
index 1ac7dab6775..b7e1cf85cb7 100644
--- a/app/views/projects/environments/folder.html.haml
+++ b/app/views/projects/environments/folder.html.haml
@@ -1,5 +1,5 @@
- @no_container = true
-- page_title "Environments"
+- page_title _("Environments")
#environments-folder-list-view{ data: { endpoint: folder_project_environments_path(@project, @folder, format: :json),
"folder-name" => @folder,
diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml
index 7ebe617766f..6c0ad34c486 100644
--- a/app/views/projects/environments/index.html.haml
+++ b/app/views/projects/environments/index.html.haml
@@ -1,6 +1,6 @@
- @no_container = true
-- page_title "Environments"
-- add_to_breadcrumbs("Pipelines", project_pipelines_path(@project))
+- page_title _("Environments")
+- add_to_breadcrumbs(_("Pipelines"), project_pipelines_path(@project))
#environments-list-view{ data: { environments_data: environments_list_data,
"can-create-deployment" => can?(current_user, :create_deployment, @project).to_s,
diff --git a/app/views/projects/environments/metrics.html.haml b/app/views/projects/environments/metrics.html.haml
index 4222963a754..7b847a85686 100644
--- a/app/views/projects/environments/metrics.html.haml
+++ b/app/views/projects/environments/metrics.html.haml
@@ -1,5 +1,5 @@
- @no_container = true
-- page_title "Metrics for environment", @environment.name
+- page_title _("Metrics for environment"), @environment.name
.prometheus-container{ class: container_class }
#prometheus-graphs{ data: metrics_data(@project, @environment) }
diff --git a/app/views/projects/environments/new.html.haml b/app/views/projects/environments/new.html.haml
index 62b08e85e22..c1067fdff78 100644
--- a/app/views/projects/environments/new.html.haml
+++ b/app/views/projects/environments/new.html.haml
@@ -1,9 +1,9 @@
- @no_container = true
-- breadcrumb_title "Environments"
-- page_title 'New Environment'
+- breadcrumb_title _("Environments")
+- page_title _("New Environment")
%div{ class: container_class }
%h3.page-title
- New environment
+ = _("New environment")
%hr
= render 'form'
diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml
index c7890b37381..d59b2d4fb01 100644
--- a/app/views/projects/environments/show.html.haml
+++ b/app/views/projects/environments/show.html.haml
@@ -1,7 +1,7 @@
- @no_container = true
-- add_to_breadcrumbs "Environments", project_environments_path(@project)
+- add_to_breadcrumbs _("Environments"), project_environments_path(@project)
- breadcrumb_title @environment.name
-- page_title "Environments"
+- page_title _("Environments")
%div{ class: container_class }
- if can?(current_user, :stop_environment, @environment)
@@ -10,7 +10,7 @@
.modal-content
.modal-header
%h4.modal-title.d-flex.mw-100
- Stopping
+ = s_("Environments|Stopping")
%span.has-tooltip.text-truncate.ml-1.mr-1.flex-fill{ title: @environment.name, data: { container: '#stop-environment-modal' } }
= @environment.name
?
@@ -40,7 +40,7 @@
= render 'projects/environments/external_url', environment: @environment
= render 'projects/environments/metrics_button', environment: @environment
- if can?(current_user, :update_environment, @environment)
- = link_to 'Edit', edit_project_environment_path(@project, @environment), class: 'btn'
+ = link_to _('Edit'), edit_project_environment_path(@project, @environment), class: 'btn'
- if can?(current_user, :stop_environment, @environment)
= button_tag class: 'btn btn-danger', type: 'button', data: { toggle: 'modal',
target: '#stop-environment-modal' } do
@@ -49,23 +49,22 @@
.environments-container
- if @deployments.blank?
- .blank-state-row
- .blank-state-center
- %h2.blank-state-title
- You don't have any deployments right now.
+ .empty-state
+ .text-content
+ %h4.state-title
+ = _("You don't have any deployments right now.")
%p.blank-state-text
- Define environments in the deploy stage(s) in
- %code .gitlab-ci.yml
- to track deployments here.
- = link_to "Read more", help_page_path("ci/environments"), class: "btn btn-success"
+ = _("Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here.").html_safe
+ .text-center
+ = link_to _("Read more"), help_page_path("ci/environments"), class: "btn btn-success"
- else
.table-holder
.ci-table.environments{ role: 'grid' }
.gl-responsive-table-row.table-row-header{ role: 'row' }
- .table-section.section-10{ role: 'columnheader' } ID
- .table-section.section-30{ role: 'columnheader' } Commit
- .table-section.section-25{ role: 'columnheader' } Job
- .table-section.section-15{ role: 'columnheader' } Created
+ .table-section.section-10{ role: 'columnheader' }= _('ID')
+ .table-section.section-30{ role: 'columnheader' }= _('Commit')
+ .table-section.section-25{ role: 'columnheader' }= _('Job')
+ .table-section.section-15{ role: 'columnheader' }= _('Created')
= render @deployments
diff --git a/app/views/projects/environments/terminal.html.haml b/app/views/projects/environments/terminal.html.haml
index e40d631a1a1..e837d3d56ac 100644
--- a/app/views/projects/environments/terminal.html.haml
+++ b/app/views/projects/environments/terminal.html.haml
@@ -1,5 +1,5 @@
- @no_container = true
-- page_title "Terminal for environment", @environment.name
+- page_title _("Terminal for environment"), @environment.name
- content_for :page_specific_javascripts do
= stylesheet_link_tag "xterm.css"
@@ -9,7 +9,7 @@
.row
.col-sm-6
%h3.page-title
- Terminal for environment
+ = _("Terminal for environment")
= @environment.name
.col-sm-6
diff --git a/app/views/projects/find_file/show.html.haml b/app/views/projects/find_file/show.html.haml
index 996c7b1b960..82f035f24da 100644
--- a/app/views/projects/find_file/show.html.haml
+++ b/app/views/projects/find_file/show.html.haml
@@ -1,6 +1,6 @@
- page_title "Find File", @ref
-.file-finder-holder.tree-holder.clearfix.js-file-finder{ 'data-file-find-url': "#{escape_javascript(project_files_path(@project, @ref, @options.merge(format: :json)))}", 'data-find-tree-url': escape_javascript(project_tree_path(@project, @ref)), 'data-blob-url-template': escape_javascript(project_blob_path(@project, @id || @commit.id)) }
+.file-finder-holder.tree-holder.clearfix.js-file-finder{ 'data-file-find-url': "#{escape_javascript(project_files_path(@project, @ref, format: :json))}", 'data-find-tree-url': escape_javascript(project_tree_path(@project, @ref)), 'data-blob-url-template': escape_javascript(project_blob_path(@project, @id || @commit.id)) }
.nav-block
.tree-ref-holder
= render 'shared/ref_switcher', destination: 'find_file', path: @path
diff --git a/app/views/projects/forks/_fork_button.html.haml b/app/views/projects/forks/_fork_button.html.haml
index 12cf40bb65f..a69146513d8 100644
--- a/app/views/projects/forks/_fork_button.html.haml
+++ b/app/views/projects/forks/_fork_button.html.haml
@@ -5,7 +5,7 @@
.bordered-box.fork-thumbnail.text-center.prepend-left-default.append-right-default.prepend-top-default.append-bottom-default.forked
= link_to project_path(forked_project) do
- if /no_((\w*)_)*avatar/.match(avatar)
- = project_icon(namespace, class: "avatar s100 identicon")
+ = group_icon(namespace, class: "avatar s100 identicon")
- else
.avatar-container.s100
= image_tag(avatar, class: "avatar s100")
@@ -18,7 +18,7 @@
class: ("disabled has-tooltip" unless can_create_project),
title: (_('You have reached your project limit') unless can_create_project) do
- if /no_((\w*)_)*avatar/.match(avatar)
- = project_icon(namespace, class: "avatar s100 identicon")
+ = group_icon(namespace, class: "avatar s100 identicon")
- else
.avatar-container.s100
= image_tag(avatar, class: "avatar s100")
diff --git a/app/views/projects/forks/index.html.haml b/app/views/projects/forks/index.html.haml
index b44ea89510b..c63c34c4ebb 100644
--- a/app/views/projects/forks/index.html.haml
+++ b/app/views/projects/forks/index.html.haml
@@ -9,7 +9,7 @@
spellcheck: false, data: { 'filter-selector' => 'span.namespace-name' }
.dropdown
- %button.dropdown-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
+ %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
%span.light sort:
- if @sort.present?
= sort_options_hash[@sort]
diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
index 639efd34a74..7614d40ba1f 100644
--- a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
+++ b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
@@ -48,7 +48,7 @@
- if generic_commit_status.pipeline.user
= user_avatar(user: generic_commit_status.pipeline.user, size: 20)
- else
- %span.api API
+ %span.monospace API
- if admin
%td
diff --git a/app/views/projects/graphs/charts.html.haml b/app/views/projects/graphs/charts.html.haml
index 3f1974d05f4..b0e22a35fe1 100644
--- a/app/views/projects/graphs/charts.html.haml
+++ b/app/views/projects/graphs/charts.html.haml
@@ -1,5 +1,5 @@
- @no_container = true
-- page_title "Charts"
+- page_title _("Contribution Charts")
.repo-charts{ class: container_class }
%h4.sub-header
diff --git a/app/views/projects/imports/new.html.haml b/app/views/projects/imports/new.html.haml
index 1c50cfbde85..bd0ab2c19f2 100644
--- a/app/views/projects/imports/new.html.haml
+++ b/app/views/projects/imports/new.html.haml
@@ -10,7 +10,7 @@
.card-body
%pre
:preserve
- #{h(@project.import_error)}
+ #{h(@project.import_state.last_error)}
= form_for @project, url: project_import_path(@project), method: :post do |f|
= render "shared/import_form", f: f
diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml
index 665968a64e1..4917f4b8903 100644
--- a/app/views/projects/issues/_discussion.html.haml
+++ b/app/views/projects/issues/_discussion.html.haml
@@ -6,8 +6,8 @@
= link_to 'Close issue', issue_path(@issue, issue: {state_event: :close}, format: 'json'), data: {original_text: "Close issue", alternative_text: "Comment & close issue"}, class: "btn btn-nr btn-close btn-comment js-note-target-close #{issue_button_visibility(@issue, true)}", title: 'Close issue'
%section.js-vue-notes-event
- #js-vue-notes{ data: { notes_data: notes_data(@issue),
+ #js-vue-notes{ data: { notes_data: notes_data(@issue).to_json,
noteable_data: serialize_issuable(@issue),
noteable_type: 'Issue',
target_type: 'issue',
- current_user_data: UserSerializer.new.represent(current_user, only_path: true).to_json } }
+ current_user_data: UserSerializer.new.represent(current_user, {only_path: true}, CurrentUserEntity).to_json } }
diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml
index a678cb6f058..5374f4a1de0 100644
--- a/app/views/projects/issues/_new_branch.html.haml
+++ b/app/views/projects/issues/_new_branch.html.haml
@@ -8,12 +8,13 @@
- create_branch_path = project_branches_path(@project, branch_name: @issue.to_branch_name, ref: @project.default_branch, issue_iid: @issue.iid)
- refs_path = refs_namespace_project_path(@project.namespace, @project, search: '')
- .create-mr-dropdown-wrap{ data: { can_create_path: can_create_path, create_mr_path: create_mr_path, create_branch_path: create_branch_path, refs_path: refs_path } }
+ .create-mr-dropdown-wrap.d-inline-block{ data: { can_create_path: can_create_path, create_mr_path: create_mr_path, create_branch_path: create_branch_path, refs_path: refs_path } }
.btn-group.unavailable
%button.btn.btn-grouped{ type: 'button', disabled: 'disabled' }
= icon('spinner', class: 'fa-spin')
%span.text
Checking branch availability…
+
.btn-group.available.hidden
%button.btn.js-create-merge-request.btn-success.btn-inverted{ type: 'button', data: { action: data_action } }
= value
diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml
index c39fd0063be..b50b3ca207b 100644
--- a/app/views/projects/issues/show.html.haml
+++ b/app/views/projects/issues/show.html.haml
@@ -77,11 +77,12 @@
#related-branches{ data: { url: related_branches_project_issue_path(@project, @issue) } }
// This element is filled in using JavaScript.
- .content-block.emoji-block
+ .content-block.emoji-block.emoji-block-sticky
.row
- .col-sm-8.js-noteable-awards
+ .col-md-12.col-lg-6.js-noteable-awards
= render 'award_emoji/awards_block', awardable: @issue, inline: true
- .col-sm-4.new-branch-col
+ .col-md-12.col-lg-6.new-branch-col
+ #js-vue-discussion-filter{ data: { default_filter: current_user&.notes_filter_for(@issue), notes_filters: UserPreference.notes_filters.to_json } }
= render 'new_branch' unless @issue.confidential?
%section.issuable-discussion
diff --git a/app/views/projects/jobs/_empty_state.html.haml b/app/views/projects/jobs/_empty_state.html.haml
deleted file mode 100644
index ea552c73c92..00000000000
--- a/app/views/projects/jobs/_empty_state.html.haml
+++ /dev/null
@@ -1,18 +0,0 @@
-- illustration = local_assigns.fetch(:illustration)
-- illustration_size = local_assigns.fetch(:illustration_size)
-- title = local_assigns.fetch(:title)
-- content = local_assigns.fetch(:content, nil)
-- action = local_assigns.fetch(:action, nil)
-
-.row.empty-state
- .col-12
- .svg-content{ class: illustration_size }
- = image_tag illustration
- .col-12
- .text-content
- %h4.text-center= title
- - if content
- %p= content
- - if action
- .text-center
- = action
diff --git a/app/views/projects/jobs/_empty_states.html.haml b/app/views/projects/jobs/_empty_states.html.haml
deleted file mode 100644
index e5198d047df..00000000000
--- a/app/views/projects/jobs/_empty_states.html.haml
+++ /dev/null
@@ -1,9 +0,0 @@
-- detailed_status = @build.detailed_status(current_user)
-- illustration = detailed_status.illustration
-
-= render 'empty_state',
- illustration: illustration[:image],
- illustration_size: illustration[:size],
- title: illustration[:title],
- content: illustration[:content],
- action: detailed_status.has_action? ? link_to(detailed_status.action_button_title, detailed_status.action_path, method: detailed_status.action_method, class: 'btn btn-primary', title: detailed_status.action_button_title) : nil
diff --git a/app/views/projects/jobs/_header.html.haml b/app/views/projects/jobs/_header.html.haml
index e7245622b80..018ff093475 100644
--- a/app/views/projects/jobs/_header.html.haml
+++ b/app/views/projects/jobs/_header.html.haml
@@ -1,4 +1,3 @@
-- show_controls = local_assigns.fetch(:show_controls, true)
- pipeline = @build.pipeline
.content-block.build-header.top-area.page-content-header
@@ -20,12 +19,3 @@
= render "projects/jobs/user" if @build.user
= time_ago_with_tooltip(@build.created_at)
-
- - if show_controls
- .nav-controls
- - if can?(current_user, :create_issue, @project) && @build.failed?
- = link_to "New issue", new_project_issue_path(@project, issue: build_failed_issue_options), class: 'btn btn-success btn-inverted'
- - if can?(current_user, :update_build, @build) && @build.retryable?
- = link_to "Retry job", retry_project_job_path(@project, @build), class: 'btn btn-inverted-secondary', method: :post
- %button.btn.btn-default.float-right.d-block.d-sm-none.d-md-none.build-gutter-toggle.js-sidebar-build-toggle{ role: "button", type: "button" }
- = icon('angle-double-left')
diff --git a/app/views/projects/jobs/_sidebar.html.haml b/app/views/projects/jobs/_sidebar.html.haml
deleted file mode 100644
index acc1e17b811..00000000000
--- a/app/views/projects/jobs/_sidebar.html.haml
+++ /dev/null
@@ -1,95 +0,0 @@
-%aside.right-sidebar.right-sidebar-expanded.build-sidebar.js-build-sidebar.js-right-sidebar{ data: { "offset-top" => "101", "spy" => "affix" } }
- .sidebar-container
- .blocks-container
- #js-details-block-vue{ data: { terminal_path: can?(current_user, :create_build_terminal, @build) && @build.has_terminal? ? terminal_project_job_path(@project, @build) : nil } }
-
- - if can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?)
- .block
- .title
- Job artifacts
- - if @build.artifacts_expired?
- %p.build-detail-row
- The artifacts were removed
- #{time_ago_with_tooltip(@build.artifacts_expire_at)}
- - elsif @build.has_expiring_artifacts?
- %p.build-detail-row
- The artifacts will be removed
- #{time_ago_with_tooltip(@build.artifacts_expire_at)}
-
- - if @build.artifacts?
- .btn-group.d-flex{ role: :group }
- - if @build.has_expiring_artifacts? && can?(current_user, :update_build, @build)
- = link_to keep_project_job_artifacts_path(@project, @build), class: 'btn btn-sm btn-default', method: :post do
- Keep
-
- = link_to download_project_job_artifacts_path(@project, @build), rel: 'nofollow', download: '', class: 'btn btn-sm btn-default' do
- Download
-
- - if @build.browsable_artifacts?
- = link_to browse_project_job_artifacts_path(@project, @build), class: 'btn btn-sm btn-default' do
- Browse
-
- - if @build.trigger_request
- .build-widget.block
- %h4.title
- Trigger
-
- - if @build.trigger_request&.trigger&.short_token
- %p
- %span.build-light-text Token:
- #{@build.trigger_request.trigger.short_token}
-
- - if @build.trigger_variables.any?
- %p
- %button.btn.group.js-reveal-variables Reveal Variables
-
- %dl.js-build-variables.trigger-build-variables.hide
- - @build.trigger_variables.each do |trigger_variable|
- %dt.js-build-variable.trigger-build-variable= trigger_variable[:key]
- %dd.js-build-value.trigger-build-value= trigger_variable[:value]
-
- %div{ class: (@build.pipeline.stages_count > 1 ? "block" : "block-last") }
- %p
- Commit
- = link_to @build.pipeline.short_sha, project_commit_path(@project, @build.pipeline.sha), class: 'commit-sha link-commit'
- = clipboard_button(text: @build.pipeline.short_sha, title: "Copy commit SHA to clipboard")
- - if @build.merge_request
- in
- = link_to "#{@build.merge_request.to_reference}", merge_request_path(@build.merge_request), class: 'link-commit'
-
- %p.build-light-text.append-bottom-0
- #{@build.pipeline.git_commit_title}
-
- - if @build.pipeline.stages_count > 1
- .block-last.dropdown.build-dropdown
- %div
- %span{ class: "ci-status-icon-#{@build.pipeline.status}" }
- = ci_icon_for_status(@build.pipeline.status)
- Pipeline
- = link_to "##{@build.pipeline.id}", project_pipeline_path(@project, @build.pipeline), class: 'link-commit'
- from
- = link_to "#{@build.pipeline.ref}", project_ref_path(@project, @build.pipeline.ref), class: 'link-commit ref-name'
- %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
- %span.stage-selection More
- = icon('chevron-down')
- %ul.dropdown-menu
- - @build.pipeline.legacy_stages.each do |stage|
- %li
- %a.stage-item= stage.name
-
- .builds-container
- - HasStatus::ORDERED_STATUSES.each do |build_status|
- - builds.select{|build| build.status == build_status}.each do |build|
- .build-job{ class: sidebar_build_class(build, @build), data: { stage: build.stage } }
- - tooltip = sanitize(build.tooltip_message.dup)
- = link_to(project_job_path(@project, build), data: { toggle: 'tooltip', title: tooltip, container: 'body' }) do
- = sprite_icon('arrow-right', size:16, css_class: 'icon-arrow-right')
- %span{ class: "ci-status-icon-#{build.status}" }
- = ci_icon_for_status(build.status)
- %span
- - if build.name
- = build.name
- - else
- = build.id
- - if build.retried?
- = sprite_icon('retry', size:16, css_class: 'icon-retry')
diff --git a/app/views/projects/jobs/show.html.haml b/app/views/projects/jobs/show.html.haml
index 5321bc46e73..475bae887ec 100644
--- a/app/views/projects/jobs/show.html.haml
+++ b/app/views/projects/jobs/show.html.haml
@@ -1,100 +1,13 @@
- @no_container = true
-- add_to_breadcrumbs "Jobs", project_jobs_path(@project)
+- add_to_breadcrumbs _("Jobs"), project_jobs_path(@project)
- breadcrumb_title "##{@build.id}"
-- page_title "#{@build.name} (##{@build.id})", "Jobs"
+- page_title "#{@build.name} (##{@build.id})", _("Jobs")
- content_for :page_specific_javascripts do
= stylesheet_link_tag 'page_bundles/xterm'
%div{ class: container_class }
- .build-page.js-build-page
- #js-build-header-vue
- - if @build.stuck?
- - unless @build.any_runners_online?
- .bs-callout.bs-callout-warning.js-build-stuck
- %p
- - if @project.any_runners?
- This job is stuck, because the project doesn't have any runners online assigned to it.
- - elsif @build.tags.any?
- This job is stuck, because you don't have any active runners online with any of these tags assigned to them:
- - @build.tags.each do |tag|
- %span.badge.badge-primary
- = tag
- - else
- This job is stuck, because you don't have any active runners that can run this job.
-
- %br
- Go to
- = link_to project_runners_path(@build.project, anchor: 'js-runners-settings') do
- Runners page
-
- - if @build.starts_environment?
- .prepend-top-default.js-environment-container
- .environment-information
- - if @build.outdated_deployment?
- = ci_icon_for_status('success_with_warnings')
- - else
- = ci_icon_for_status(@build.status)
-
- - environment = environment_for_build(@build.project, @build)
- - if @build.success? && @build.last_deployment.present?
- - if @build.last_deployment.last?
- This job is the most recent deployment to #{environment_link_for_build(@build.project, @build)}.
- - else
- This job is an out-of-date deployment to #{environment_link_for_build(@build.project, @build)}.
- View the most recent deployment #{deployment_link(environment.last_deployment)}.
- - elsif @build.complete? && !@build.success?
- The deployment of this job to #{environment_link_for_build(@build.project, @build)} did not succeed.
- - else
- This job is creating a deployment to #{environment_link_for_build(@build.project, @build)}
- - if environment.try(:last_deployment)
- and will overwrite the #{deployment_link(environment.last_deployment, text: 'latest deployment')}
-
- - if @build.erased?
- .prepend-top-default.js-build-erased
- .erased.alert.alert-warning
- - if @build.erased_by_user?
- Job has been erased by #{link_to(@build.erased_by_name, user_path(@build.erased_by))} #{time_ago_with_tooltip(@build.erased_at)}
- - else
- Job has been erased #{time_ago_with_tooltip(@build.erased_at)}
-
- - if @build.running? || @build.has_trace?
- .build-trace-container.prepend-top-default
- .top-bar.js-top-bar
- .js-truncated-info.truncated-info.d-none.d-sm-block.float-left.hidden<
- Showing last
- %span.js-truncated-info-size.truncated-info-size><
- of log -
- %a.js-raw-link.raw-link{ href: raw_project_job_path(@project, @build) }>< Complete Raw
-
- .controllers.float-right
- - if @build.has_trace?
- = link_to raw_project_job_path(@project, @build),
- title: 'Show complete raw',
- data: { placement: 'top', container: 'body' },
- class: 'js-raw-link-controller has-tooltip controllers-buttons' do
- = icon('file-text-o')
-
- - if @build.erasable? && can?(current_user, :erase_build, @build)
- = link_to erase_project_job_path(@project, @build),
- method: :post,
- data: { confirm: 'Are you sure you want to erase this build?', placement: 'top', container: 'body' },
- title: 'Erase job log',
- class: 'has-tooltip js-erase-link controllers-buttons' do
- = icon('trash')
- .has-tooltip.controllers-buttons{ title: 'Scroll to top', data: { placement: 'top', container: 'body'} }
- %button.js-scroll-up.btn-scroll.btn-transparent.btn-blank{ type: 'button', disabled: true }
- = custom_icon('scroll_up')
- .has-tooltip.controllers-buttons{ title: 'Scroll to bottom', data: { placement: 'top', container: 'body'} }
- %button.js-scroll-down.btn-scroll.btn-transparent.btn-blank{ type: 'button', disabled: true }
- = custom_icon('scroll_down')
-
- = render 'shared/builds/build_output'
- - else
- = render "empty_states"
-
- = render "sidebar", builds: @builds
-
-.js-build-options{ data: javascript_build_options }
-
-#js-job-details-vue{ data: { endpoint: project_job_path(@project, @build, format: :json), runner_help_url: help_page_path('ci/runners/README.html', anchor: 'setting-maximum-job-timeout-for-a-runner') } }
+ #js-job-vue-app{ data: { endpoint: project_job_path(@project, @build, format: :json),
+ runner_help_url: help_page_path('ci/runners/README.html', anchor: 'setting-maximum-job-timeout-for-a-runner'),
+ runner_settings_url: project_runners_path(@build.project, anchor: 'js-runners-settings'),
+ build_options: javascript_build_options } }
diff --git a/app/views/projects/labels/edit.html.haml b/app/views/projects/labels/edit.html.haml
index b8ee4305142..b9d45e83032 100644
--- a/app/views/projects/labels/edit.html.haml
+++ b/app/views/projects/labels/edit.html.haml
@@ -1,4 +1,6 @@
- @no_container = true
+- add_to_breadcrumbs "Labels", project_labels_path(@project)
+- breadcrumb_title "Edit"
- page_title "Edit", @label.name, "Labels"
%div{ class: container_class }
diff --git a/app/views/projects/labels/index.html.haml b/app/views/projects/labels/index.html.haml
index 683dda4f166..2c6484c2c99 100644
--- a/app/views/projects/labels/index.html.haml
+++ b/app/views/projects/labels/index.html.haml
@@ -2,32 +2,25 @@
- page_title "Labels"
- can_admin_label = can?(current_user, :admin_label, @project)
- search = params[:search]
+- subscribed = params[:subscribed]
+- labels_or_filters = @labels.exists? || @prioritized_labels.exists? || search.present? || subscribed.present?
-- if can_admin_label
+- if @labels.present? && can_admin_label
- content_for(:header_content) do
.nav-controls
- = link_to _('New label'), new_project_label_path(@project), class: "btn btn-success"
+ = link_to _('New label'), new_project_label_path(@project), class: "btn btn-success qa-label-create-new"
-- if @labels.exists? || @prioritized_labels.exists? || search.present?
+- if labels_or_filters
#promote-label-modal
%div{ class: container_class }
- .top-area.adjust
- .nav-text
- = _('Labels can be applied to issues and merge requests.')
-
- .nav-controls
- = form_tag project_labels_path(@project), method: :get do
- .input-group
- = search_field_tag :search, params[:search], { placeholder: _('Filter'), id: 'label-search', class: 'form-control search-text-input input-short', spellcheck: false }
- %span.input-group-append
- %button.btn.btn-default{ type: "submit", "aria-label" => _('Submit search') }
- = icon("search")
- = render 'shared/labels/sort_dropdown'
+ = render 'shared/labels/nav'
.labels-container.prepend-top-10
- if can_admin_label
- if search.blank?
%p.text-muted
+ = _('Labels can be applied to issues and merge requests.')
+ %br
= _('Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging.')
-# Only show it in the first page
- hide = @available_labels.empty? || (params[:page].present? && params[:page] != '1')
@@ -59,7 +52,9 @@
- else
.nothing-here-block
= _('No labels with such name or description')
-
+ - elsif subscribed.present?
+ .nothing-here-block
+ = _('You do not have any subscriptions yet')
- else
= render 'shared/empty_states/labels'
diff --git a/app/views/projects/labels/new.html.haml b/app/views/projects/labels/new.html.haml
index 02f59f30a39..c6739231e36 100644
--- a/app/views/projects/labels/new.html.haml
+++ b/app/views/projects/labels/new.html.haml
@@ -1,5 +1,6 @@
- @no_container = true
-- breadcrumb_title "Labels"
+- add_to_breadcrumbs "Labels", project_labels_path(@project)
+- breadcrumb_title "New"
- page_title "New Label"
%div{ class: container_class }
diff --git a/app/views/projects/merge_requests/_form.html.haml b/app/views/projects/merge_requests/_form.html.haml
index 5a59f956cb5..13b967beba1 100644
--- a/app/views/projects/merge_requests/_form.html.haml
+++ b/app/views/projects/merge_requests/_form.html.haml
@@ -1,4 +1,4 @@
= form_for [@project.namespace.becomes(Namespace), @project, @merge_request],
html: { class: 'merge-request-form common-note-form js-requires-input js-quick-submit' },
data: { markdown_version: @merge_request.cached_markdown_version } do |f|
- = render 'shared/issuable/form', f: f, issuable: @merge_request
+ = render 'shared/issuable/form', f: f, issuable: @merge_request, presenter: @mr_presenter
diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml
index 1bf42ded97a..3cd83feb842 100644
--- a/app/views/projects/merge_requests/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/_mr_title.html.haml
@@ -37,6 +37,6 @@
= link_to 'Reopen', merge_request_path(@merge_request, merge_request: { state_event: :reopen }), method: :put, class: 'reopen-mr-link', title: 'Reopen merge request'
- if can_update_merge_request
- = link_to 'Edit', edit_project_merge_request_path(@project, @merge_request), class: "d-none d-sm-none d-md-block btn btn-grouped js-issuable-edit"
+ = link_to 'Edit', edit_project_merge_request_path(@project, @merge_request), class: "d-none d-sm-none d-md-block btn btn-grouped js-issuable-edit qa-edit-button"
= render 'shared/issuable/close_reopen_button', issuable: @merge_request, can_update: can_update_merge_request, can_reopen: can_update_merge_request
diff --git a/app/views/projects/merge_requests/creations/_new_compare.html.haml b/app/views/projects/merge_requests/creations/_new_compare.html.haml
index 1fd71a38472..11272a67f93 100644
--- a/app/views/projects/merge_requests/creations/_new_compare.html.haml
+++ b/app/views/projects/merge_requests/creations/_new_compare.html.haml
@@ -21,7 +21,7 @@
selected: f.object.source_project_id
.merge-request-select.dropdown
= f.hidden_field :source_branch
- = dropdown_toggle f.object.source_branch || _("Select source branch"), { toggle: "dropdown", 'field-name': "#{f.object_name}[source_branch]", 'refs-url': refs_project_path(@source_project), selected: f.object.source_branch }, { toggle_class: "js-compare-dropdown js-source-branch git-revision-dropdown-toggle" }
+ = dropdown_toggle f.object.source_branch || _("Select source branch"), { toggle: "dropdown", 'field-name': "#{f.object_name}[source_branch]", 'refs-url': refs_project_path(@source_project), selected: f.object.source_branch }, { toggle_class: "js-compare-dropdown js-source-branch monospace" }
.dropdown-menu.dropdown-menu-selectable.js-source-branch-dropdown.git-revision-dropdown
= dropdown_title(_("Select source branch"))
= dropdown_filter(_("Search branches"))
@@ -49,7 +49,7 @@
selected: f.object.target_project_id
.merge-request-select.dropdown
= f.hidden_field :target_branch
- = dropdown_toggle f.object.target_branch, { toggle: "dropdown", 'field-name': "#{f.object_name}[target_branch]", 'refs-url': refs_project_path(f.object.target_project), selected: f.object.target_branch }, { toggle_class: "js-compare-dropdown js-target-branch git-revision-dropdown-toggle" }
+ = dropdown_toggle f.object.target_branch, { toggle: "dropdown", 'field-name': "#{f.object_name}[target_branch]", 'refs-url': refs_project_path(f.object.target_project), selected: f.object.target_branch }, { toggle_class: "js-compare-dropdown js-target-branch monospace" }
.dropdown-menu.dropdown-menu-selectable.js-target-branch-dropdown.git-revision-dropdown
= dropdown_title(_("Select target branch"))
= dropdown_filter(_("Search branches"))
diff --git a/app/views/projects/merge_requests/creations/_new_submit.html.haml b/app/views/projects/merge_requests/creations/_new_submit.html.haml
index d5c4134dee2..464f8fa65e9 100644
--- a/app/views/projects/merge_requests/creations/_new_submit.html.haml
+++ b/app/views/projects/merge_requests/creations/_new_submit.html.haml
@@ -11,7 +11,7 @@
= link_to 'Change branches', mr_change_branches_path(@merge_request)
%hr
= form_for [@project.namespace.becomes(Namespace), @project, @merge_request], html: { class: 'merge-request-form common-note-form js-requires-input js-quick-submit' } do |f|
- = render 'shared/issuable/form', f: f, issuable: @merge_request, commits: @commits
+ = render 'shared/issuable/form', f: f, issuable: @merge_request, commits: @commits, presenter: @mr_presenter
= f.hidden_field :source_project_id
= f.hidden_field :source_branch
= f.hidden_field :target_project_id
diff --git a/app/views/projects/merge_requests/diffs/_commit_widget.html.haml b/app/views/projects/merge_requests/diffs/_commit_widget.html.haml
index dab95b97346..066c8d5dba6 100644
--- a/app/views/projects/merge_requests/diffs/_commit_widget.html.haml
+++ b/app/views/projects/merge_requests/diffs/_commit_widget.html.haml
@@ -1,3 +1,7 @@
+-#-----------------------------------------------------------------
+ WARNING: Please keep changes up-to-date with the following files:
+ - `assets/javascripts/diffs/components/commit_widget.vue`
+-#-----------------------------------------------------------------
- if @commit
.info-well.d-none.d-sm-block.prepend-top-default
.well-segment
diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml
index b23baa22d8b..4ebb029e48b 100644
--- a/app/views/projects/merge_requests/show.html.haml
+++ b/app/views/projects/merge_requests/show.html.haml
@@ -21,6 +21,7 @@
window.gl.mrWidgetData = #{serialize_issuable(@merge_request, serializer: 'widget')}
window.gl.mrWidgetData.squash_before_merge_help_path = '#{help_page_path("user/project/merge_requests/squash_and_merge")}';
+ window.gl.mrWidgetData.troubleshooting_docs_path = '#{help_page_path('user/project/merge_requests/index.md', anchor: 'troubleshooting')}';
#js-vue-mr-widget.mr-widget
@@ -33,7 +34,7 @@
.fade-left= icon('angle-left')
.fade-right= icon('angle-right')
%ul.merge-request-tabs.nav-tabs.nav.nav-links.scrolling-tabs
- %li.notes-tab
+ %li.notes-tab.qa-notes-tab
= tab_link_for @merge_request, :show, force_link: @commit.present? do
Discussion
%span.badge.badge-pill= @merge_request.related_notes.user.count
@@ -47,12 +48,14 @@
= tab_link_for @merge_request, :pipelines do
Pipelines
%span.badge.badge-pill.js-pipelines-mr-count= @pipelines.size
- %li.diffs-tab
+ %li.diffs-tab.qa-diffs-tab
= tab_link_for @merge_request, :diffs do
Changes
%span.badge.badge-pill= @merge_request.diff_size
-
- #js-vue-discussion-counter
+ .d-inline-flex.flex-wrap
+ #js-vue-discussion-filter{ data: { default_filter: current_user&.notes_filter_for(@merge_request),
+ notes_filters: UserPreference.notes_filters.to_json } }
+ #js-vue-discussion-counter
.tab-content#diff-notes-app
#notes.notes.tab-pane.voting_notes
@@ -60,7 +63,7 @@
%section.col-md-12
%script.js-notes-data{ type: "application/json" }= initial_notes_data(true).to_json.html_safe
.issuable-discussion.js-vue-notes-event
- #js-vue-mr-discussions{ data: { notes_data: notes_data(@merge_request),
+ #js-vue-mr-discussions{ data: { notes_data: notes_data(@merge_request).to_json,
noteable_data: serialize_issuable(@merge_request),
noteable_type: 'MergeRequest',
target_type: 'merge_request',
diff --git a/app/views/projects/milestones/edit.html.haml b/app/views/projects/milestones/edit.html.haml
index af3f25c6a30..4006a468792 100644
--- a/app/views/projects/milestones/edit.html.haml
+++ b/app/views/projects/milestones/edit.html.haml
@@ -1,6 +1,9 @@
- @no_container = true
+- breadcrumb_title "Edit"
+- add_to_breadcrumbs "Milestones", project_milestones_path(@project)
- page_title "Edit", @milestone.title, "Milestones"
+
%div{ class: container_class }
%h3.page-title
diff --git a/app/views/projects/milestones/new.html.haml b/app/views/projects/milestones/new.html.haml
index c301f517013..01cc951e8c2 100644
--- a/app/views/projects/milestones/new.html.haml
+++ b/app/views/projects/milestones/new.html.haml
@@ -1,5 +1,6 @@
- @no_container = true
-- breadcrumb_title "Milestones"
+- add_to_breadcrumbs "Milestones", project_milestones_path(@project)
+- breadcrumb_title "New"
- page_title "New Milestone"
%div{ class: container_class }
diff --git a/app/views/projects/mirrors/_authentication_method.html.haml b/app/views/projects/mirrors/_authentication_method.html.haml
new file mode 100644
index 00000000000..3effdf934fb
--- /dev/null
+++ b/app/views/projects/mirrors/_authentication_method.html.haml
@@ -0,0 +1,36 @@
+- mirror = f.object
+- is_push = local_assigns.fetch(:is_push, false)
+- auth_options = [[_('Password'), 'password'], [_('SSH public key'), 'ssh_public_key']]
+- regen_data = { auth_method: 'ssh_public_key', regenerate_ssh_private_key: true }
+- ssh_public_key_present = mirror.ssh_public_key.present?
+
+.form-group
+ = f.label :auth_method, _('Authentication method'), class: 'label-bold'
+ = f.select :auth_method,
+ options_for_select(auth_options, mirror.auth_method),
+ {}, { class: "form-control js-mirror-auth-type" }
+
+.form-group
+ .collapse.js-well-changing-auth
+ .changing-auth-method= icon('spinner spin lg')
+ .well-password-auth.collapse.js-well-password-auth
+ = f.label :password, _("Password"), class: "label-bold"
+ = f.password_field :password, value: mirror.password, class: 'form-control', autocomplete: 'new-password'
+ - unless is_push
+ .well-ssh-auth.collapse.js-well-ssh-auth
+ %p.js-ssh-public-key-present{ class: ('collapse' unless ssh_public_key_present) }
+ = _('Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation.')
+ %p.js-ssh-public-key-pending{ class: ('collapse' if ssh_public_key_present) }
+ = _('An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation.')
+
+ .clearfix.js-ssh-public-key-wrap{ class: ('collapse' unless ssh_public_key_present) }
+ %code.prepend-top-10.ssh-public-key
+ = mirror.ssh_public_key
+ = clipboard_button(text: mirror.ssh_public_key, title: _("Copy SSH public key to clipboard"), class: 'prepend-top-10 btn-copy-ssh-public-key')
+
+ = button_tag type: 'button',
+ data: { endpoint: project_mirror_path(@project), project_data: { import_data_attributes: regen_data } },
+ class: "btn btn-inverted btn-warning prepend-top-10 js-btn-regenerate-ssh-key#{ ' collapse' unless ssh_public_key_present }" do
+ = icon('spinner spin', class: 'js-spinner d-none')
+ = _('Regenerate key')
+ = render 'projects/mirrors/regenerate_public_ssh_key_confirm_modal'
diff --git a/app/views/projects/mirrors/_mirror_repos.html.haml b/app/views/projects/mirrors/_mirror_repos.html.haml
index d523df1cd90..dde0fae740b 100644
--- a/app/views/projects/mirrors/_mirror_repos.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos.html.haml
@@ -32,7 +32,7 @@
= link_to icon('question-circle'), help_page_path('user/project/protected_branches')
.panel-footer
- = f.submit _('Mirror repository'), class: 'btn btn-success', name: :update_remote_mirror
+ = f.submit _('Mirror repository'), class: 'btn btn-success js-mirror-submit', name: :update_remote_mirror
.panel.panel-default
.table-responsive
@@ -59,5 +59,7 @@
.badge.mirror-error-badge{ data: { toggle: 'tooltip', html: 'true' }, title: html_escape(mirror.last_error.try(:strip)) }= _('Error')
%td.mirror-action-buttons
.btn-group.mirror-actions-group.pull-right{ role: 'group' }
+ - if mirror.ssh_key_auth?
+ = clipboard_button(text: mirror.ssh_public_key, class: 'btn btn-default', title: _('Copy SSH public key'))
= render 'shared/remote_mirror_update_button', remote_mirror: mirror
%button.js-delete-mirror.btn.btn-danger{ type: 'button', data: { mirror_id: mirror.id, toggle: 'tooltip', container: 'body' }, title: _('Remove') }= icon('trash-o')
diff --git a/app/views/projects/mirrors/_mirror_repos_form.html.haml b/app/views/projects/mirrors/_mirror_repos_form.html.haml
index 93994cb30ac..a2cce83bfab 100644
--- a/app/views/projects/mirrors/_mirror_repos_form.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos_form.html.haml
@@ -1,18 +1,5 @@
-- protocols = Gitlab::UrlSanitizer::ALLOWED_SCHEMES.join('|')
-
.form-group
= label_tag :mirror_direction, _('Mirror direction'), class: 'label-light'
= select_tag :mirror_direction, options_for_select([[_('Push'), 'push']]), class: 'form-control js-mirror-direction', disabled: true
-= f.fields_for :remote_mirrors, @project.remote_mirrors.build do |rm_f|
- = rm_f.hidden_field :enabled, value: '1'
- = rm_f.hidden_field :url, class: 'js-mirror-url-hidden', required: true, pattern: "(#{protocols}):\/\/.+"
- = rm_f.hidden_field :only_protected_branches, class: 'js-mirror-protected-hidden'
-
-.form-group
- = label_tag :auth_method, _('Authentication method'), class: 'label-bold'
- = select_tag :auth_method, options_for_select([[_('None'), 'none'], [_('Password'), 'password']], 'none'), { class: "form-control js-auth-method" }
-
-.form-group.js-password-group.collapse
- = label_tag :password, _('Password'), class: 'label-bold'
- = text_field_tag :password, '', class: 'form-control js-password'
+= render partial: "projects/mirrors/mirror_repos_push", locals: { f: f }
diff --git a/app/views/projects/mirrors/_mirror_repos_push.html.haml b/app/views/projects/mirrors/_mirror_repos_push.html.haml
new file mode 100644
index 00000000000..1d9c83653fe
--- /dev/null
+++ b/app/views/projects/mirrors/_mirror_repos_push.html.haml
@@ -0,0 +1,8 @@
+- protocols = Gitlab::UrlSanitizer::ALLOWED_SCHEMES.join('|')
+
+= f.fields_for :remote_mirrors, @project.remote_mirrors.build do |rm_f|
+ = rm_f.hidden_field :enabled, value: '1'
+ = rm_f.hidden_field :url, class: 'js-mirror-url-hidden', required: true, pattern: "(#{protocols}):\/\/.+"
+ = rm_f.hidden_field :only_protected_branches, class: 'js-mirror-protected-hidden'
+ = render partial: 'projects/mirrors/ssh_host_keys', locals: { f: rm_f }
+ = render partial: 'projects/mirrors/authentication_method', locals: { f: rm_f, is_push: true }
diff --git a/app/views/projects/mirrors/_regenerate_public_ssh_key_confirm_modal.html.haml b/app/views/projects/mirrors/_regenerate_public_ssh_key_confirm_modal.html.haml
new file mode 100644
index 00000000000..327552c9b2c
--- /dev/null
+++ b/app/views/projects/mirrors/_regenerate_public_ssh_key_confirm_modal.html.haml
@@ -0,0 +1,13 @@
+.modal.js-regenerate-public-ssh-key-confirm-modal{ tabindex: -1 }
+ .modal-dialog
+ .modal-content
+ .modal-header
+ %h3.modal-title.page-title
+ Regenerate public SSH key?
+ %button.close.js-cancel{ type: 'button', 'data-dismiss': 'modal', 'aria-label' => _('Close') }
+ %span{ 'aria-hidden': true } &times;
+ .modal-body
+ %p= _('Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again.')
+ .form-actions.modal-footer
+ = button_tag _('Cancel'), type: 'button', class: 'btn js-cancel'
+ = button_tag _('Regenerate key'), type: 'button', class: 'btn btn-inverted btn-warning js-confirm'
diff --git a/app/views/projects/mirrors/_show.html.haml b/app/views/projects/mirrors/_show.html.haml
deleted file mode 100644
index 8318d5898a1..00000000000
--- a/app/views/projects/mirrors/_show.html.haml
+++ /dev/null
@@ -1 +0,0 @@
-= render 'projects/mirrors/mirror_repos'
diff --git a/app/views/projects/mirrors/_ssh_host_keys.html.haml b/app/views/projects/mirrors/_ssh_host_keys.html.haml
new file mode 100644
index 00000000000..f61aa6ecd11
--- /dev/null
+++ b/app/views/projects/mirrors/_ssh_host_keys.html.haml
@@ -0,0 +1,33 @@
+- mirror = f.object
+- verified_by = mirror.ssh_known_hosts_verified_by
+- verified_at = mirror.ssh_known_hosts_verified_at
+
+.form-group.js-ssh-host-keys-section{ class: ('collapse' unless mirror.ssh_mirror_url?) }
+ %button.btn.btn-inverted.btn-success.inline.js-detect-host-keys.append-right-10{ type: 'button' }
+ = icon('spinner spin', class: 'js-spinner d-none')
+ = _('Detect host keys')
+ .fingerprint-ssh-info.js-fingerprint-ssh-info.prepend-top-10.append-bottom-10{ class: ('collapse' unless mirror.ssh_mirror_url?) }
+ %label.label-bold
+ = _('Fingerprints')
+ .fingerprints-list.js-fingerprints-list
+ - mirror.ssh_known_hosts_fingerprints.each do |fp|
+ %code= fp.fingerprint
+ - if verified_at
+ .form-text.text-muted.js-fingerprint-verification
+ %i.fa.fa-check.fingerprint-verified
+ Verified by
+ - if verified_by
+ = link_to verified_by.name, user_path(verified_by)
+ - else
+ = _('a deleted user')
+ #{time_ago_in_words(verified_at)} ago
+
+ .js-ssh-hosts-advanced.inline
+ %button.btn.btn-default.btn-show-advanced.show-advanced{ type: 'button' }
+ %span.label-show
+ = _('Input host keys manually')
+ %span.label-hide
+ = _('Hide host keys manual input')
+ .js-ssh-known-hosts.collapse.prepend-top-default
+ = f.label :ssh_known_hosts, _('SSH host keys'), class: 'label-bold'
+ = f.text_area :ssh_known_hosts, class: 'form-control known-hosts js-known-hosts', rows: '10'
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index f9b4cddf9b2..a760d02c4c3 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -1,14 +1,13 @@
-- @breadcrumb_link = dashboard_projects_path
-- breadcrumb_title "Projects"
+- @hide_breadcrumbs = true
- @hide_top_links = true
- page_title 'New Project'
- header_title "Projects", dashboard_projects_path
- active_tab = local_assigns.fetch(:active_tab, 'blank')
-.project-edit-container
+.project-edit-container.prepend-top-default
.project-edit-errors
= render 'projects/errors'
- .row.prepend-top-default
+ .row
.col-lg-3.profile-settings-sidebar
%h4.prepend-top-0
= _('New project')
@@ -29,15 +28,15 @@
.col-lg-9.js-toggle-container
%ul.nav.nav-tabs.nav-links.gitlab-tabs{ role: 'tablist' }
%li.nav-item{ role: 'presentation' }
- %a.nav-link.active{ href: '#blank-project-pane', id: 'blank-project-tab', data: { toggle: 'tab' }, role: 'tab' }
+ %a.nav-link.active{ href: '#blank-project-pane', id: 'blank-project-tab', data: { toggle: 'tab', track_label: 'blank_project', track_event: "click_tab" }, role: 'tab' }
%span.d-none.d-sm-block Blank project
%span.d-block.d-sm-none Blank
%li.nav-item{ role: 'presentation' }
- %a.nav-link{ href: '#create-from-template-pane', id: 'create-from-template-tab', data: { toggle: 'tab' }, role: 'tab' }
+ %a.nav-link{ href: '#create-from-template-pane', id: 'create-from-template-tab', data: { toggle: 'tab', track_label: 'create_from_template', track_event: "click_tab" }, role: 'tab' }
%span.d-none.d-sm-block Create from template
%span.d-block.d-sm-none Template
%li.nav-item{ role: 'presentation' }
- %a.nav-link{ href: '#import-project-pane', id: 'import-project-tab', data: { toggle: 'tab' }, role: 'tab' }
+ %a.nav-link{ href: '#import-project-pane', id: 'import-project-tab', data: { toggle: 'tab', track_label: 'import_project', track_event: "click_tab" }, role: 'tab' }
%span.d-none.d-sm-block Import project
%span.d-block.d-sm-none Import
@@ -51,7 +50,7 @@
.project-template
.form-group
%div
- = render 'project_templates', f: f
+ = render 'project_templates', f: f, project: @project
.tab-pane.import-project-pane.js-toggle-container{ id: 'import-project-pane', class: active_when(active_tab == 'import'), role: 'tabpanel' }
- if import_sources_enabled?
diff --git a/app/views/projects/notes/_more_actions_dropdown.html.haml b/app/views/projects/notes/_more_actions_dropdown.html.haml
index 88085c7185b..8de84f82e9f 100644
--- a/app/views/projects/notes/_more_actions_dropdown.html.haml
+++ b/app/views/projects/notes/_more_actions_dropdown.html.haml
@@ -11,8 +11,9 @@
- unless is_current_user
%li
= link_to new_abuse_report_path(user_id: note.author.id, ref_url: noteable_note_url(note)) do
- Report as abuse
+ = _('Report abuse to GitLab')
- if note_editable
%li
= link_to note_url(note), method: :delete, data: { confirm: 'Are you sure you want to delete this comment?' }, remote: true, class: 'js-note-delete' do
- %span.text-danger Delete comment
+ %span.text-danger
+ = _('Delete comment')
diff --git a/app/views/projects/pages/_https_only.html.haml b/app/views/projects/pages/_https_only.html.haml
index 57345edb90b..ce3ef29c32e 100644
--- a/app/views/projects/pages/_https_only.html.haml
+++ b/app/views/projects/pages/_https_only.html.haml
@@ -1,9 +1,9 @@
= form_for @project, url: namespace_project_pages_path(@project.namespace.becomes(Namespace), @project), html: { class: 'inline', title: pages_https_only_title } do |f|
- = f.check_box :pages_https_only, class: 'float-left', disabled: pages_https_only_disabled?
-
- .prepend-left-20
- = f.label :pages_https_only, class: pages_https_only_label_class do
- %strong Force domains with SSL certificates to use HTTPS
+ .form-group
+ .form-check
+ = f.check_box :pages_https_only, class: 'form-check-input', disabled: pages_https_only_disabled?
+ = f.label :pages_https_only, class: pages_https_only_label_class do
+ %strong Force domains with SSL certificates to use HTTPS
- unless pages_https_only_disabled?
.prepend-top-10
diff --git a/app/views/projects/pages/_list.html.haml b/app/views/projects/pages/_list.html.haml
index e7178f9160c..2427b4d7611 100644
--- a/app/views/projects/pages/_list.html.haml
+++ b/app/views/projects/pages/_list.html.haml
@@ -4,9 +4,9 @@
.card
.card-header
Domains (#{@domains.count})
- %ul.content-list.pages-domain-list{ class: ("has-verification-status" if verification_enabled) }
+ %ul.list-group.list-group-flush.pages-domain-list{ class: ("has-verification-status" if verification_enabled) }
- @domains.each do |domain|
- %li.pages-domain-list-item.unstyled
+ %li.pages-domain-list-item.list-group-item.d-flex.justify-content-between
- if verification_enabled
- tooltip, status = domain.unverified? ? [_('Unverified'), 'failed'] : [_('Verified'), 'success']
.domain-status.ci-status-icon.has-tooltip{ class: "ci-status-icon-#{status}", title: tooltip }
@@ -16,7 +16,7 @@
= domain.url
= icon('external-link')
- if domain.subject
- %p
+ %div
%span.badge.badge-gray Certificate: #{domain.subject}
- if domain.expired?
%span.badge.badge-danger Expired
@@ -24,6 +24,6 @@
= link_to 'Details', project_pages_domain_path(@project, domain), class: "btn btn-sm btn-grouped"
= link_to 'Remove', project_pages_domain_path(@project, domain), data: { confirm: 'Are you sure?'}, method: :delete, class: "btn btn-remove btn-sm btn-grouped"
- if verification_enabled && domain.unverified?
- %li.warning-row
+ %li.list-group-item.bs-callout-warning
#{domain.domain} is not verified. To learn how to verify ownership, visit your
#{link_to 'domain details', project_pages_domain_path(@project, domain)}.
diff --git a/app/views/projects/pipelines/_info.html.haml b/app/views/projects/pipelines/_info.html.haml
index ccb83148ded..2575efc0981 100644
--- a/app/views/projects/pipelines/_info.html.haml
+++ b/app/views/projects/pipelines/_info.html.haml
@@ -13,7 +13,11 @@
= pluralize @pipeline.total_size, "job"
- if @pipeline.ref
from
- = link_to @pipeline.ref, project_ref_path(@project, @pipeline.ref), class: "ref-name"
+ - if @pipeline.ref_exists?
+ = link_to @pipeline.ref, project_ref_path(@project, @pipeline.ref), class: "ref-name"
+ - else
+ %span.ref-name
+ = @pipeline.ref
- if @pipeline.duration
in
= time_interval_in_words(@pipeline.duration)
@@ -30,5 +34,3 @@
%span.js-details-content.hide
= link_to @pipeline.sha, project_commit_path(@project, @pipeline.sha), class: "commit-sha commit-hash-full"
= clipboard_button(text: @pipeline.sha, title: "Copy commit SHA to clipboard")
-
- = render_if_exists "projects/pipelines/info_extension", pipeline: @pipeline
diff --git a/app/views/projects/pipelines/_with_tabs.html.haml b/app/views/projects/pipelines/_with_tabs.html.haml
index c63ff070f70..66e202103a9 100644
--- a/app/views/projects/pipelines/_with_tabs.html.haml
+++ b/app/views/projects/pipelines/_with_tabs.html.haml
@@ -19,30 +19,23 @@
#js-pipeline-graph-vue
#js-tab-builds.tab-pane
- - if pipeline.yaml_errors.present?
- .bs-callout.bs-callout-danger
- %h4 Found errors in your .gitlab-ci.yml:
- %ul
- - pipeline.yaml_errors.split(",").each do |error|
- %li= error
- You can also test your .gitlab-ci.yml in the #{link_to "Lint", project_ci_lint_path(@project)}
+ - if pipeline.legacy_stages.present?
+ .table-holder.pipeline-holder
+ %table.table.ci-table.pipeline
+ %thead
+ %tr
+ %th Status
+ %th Job ID
+ %th Name
+ %th
+ %th Coverage
+ %th
+ = render partial: "projects/stage/stage", collection: pipeline.legacy_stages, as: :stage
- - if pipeline.project.builds_enabled? && !pipeline.ci_yaml_file
+ - elsif pipeline.project.builds_enabled? && !pipeline.ci_yaml_file
.bs-callout.bs-callout-warning
\.gitlab-ci.yml not found in this commit
- .table-holder.pipeline-holder
- %table.table.ci-table.pipeline
- %thead
- %tr
- %th Status
- %th Job ID
- %th Name
- %th
- %th Coverage
- %th
- = render partial: "projects/stage/stage", collection: pipeline.legacy_stages, as: :stage
-
- if @pipeline.failed_builds.present?
#js-tab-failures.build-failures.tab-pane.build-page
%table.table.responsive-table.ci-table.responsive-table-sm-rounded
@@ -68,12 +61,14 @@
%td.responsive-table-cell.build-failure{ data: { column: _("Failure")} }
= build.present.callout_failure_message
%td.responsive-table-cell.build-actions
- = link_to retry_project_job_path(build.project, build, return_to: request.original_url), method: :post, title: _('Retry'), class: 'btn btn-build' do
- = icon('repeat')
- %tr.build-trace-row.responsive-table-border-end
- %td
- %td.responsive-table-cell.build-trace-container{ colspan: 4 }
- %pre.build-trace.build-trace-rounded
- %code.bash.js-build-output
- = build_summary(build)
+ - if can?(current_user, :update_build, job)
+ = link_to retry_project_job_path(build.project, build, return_to: request.original_url), method: :post, title: _('Retry'), class: 'btn btn-build' do
+ = icon('repeat')
+ - if can?(current_user, :read_build, job)
+ %tr.build-trace-row.responsive-table-border-end
+ %td
+ %td.responsive-table-cell.build-trace-container{ colspan: 4 }
+ %pre.build-trace.build-trace-rounded
+ %code.bash.js-build-output
+ = build_summary(build)
= render_if_exists "projects/pipelines/tabs_content", pipeline: @pipeline, project: @project
diff --git a/app/views/projects/pipelines/charts.html.haml b/app/views/projects/pipelines/charts.html.haml
index a86cb14960a..ec17eddba79 100644
--- a/app/views/projects/pipelines/charts.html.haml
+++ b/app/views/projects/pipelines/charts.html.haml
@@ -1,6 +1,5 @@
- @no_container = true
-- breadcrumb_title "CI / CD Charts"
-- page_title _("Charts"), _("Pipelines")
+- page_title _("CI / CD Charts")
%div{ class: container_class }
.sub-header-block
diff --git a/app/views/projects/pipelines/new.html.haml b/app/views/projects/pipelines/new.html.haml
index 5b6823da1f6..f1cdc0a70dd 100644
--- a/app/views/projects/pipelines/new.html.haml
+++ b/app/views/projects/pipelines/new.html.haml
@@ -13,7 +13,7 @@
= f.label :ref, s_('Pipeline|Create for'), class: 'col-form-label'
= hidden_field_tag 'pipeline[ref]', params[:ref] || @project.default_branch
= dropdown_tag(params[:ref] || @project.default_branch,
- options: { toggle_class: 'js-branch-select wide git-revision-dropdown-toggle',
+ options: { toggle_class: 'js-branch-select wide monospace',
filter: true, dropdown_class: "dropdown-menu-selectable git-revision-dropdown", placeholder: s_("Pipeline|Search branches"),
data: { selected: params[:ref] || @project.default_branch, field_name: 'pipeline[ref]' } })
.form-text.text-muted
diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml
index ff0ed3ed30d..193d437dad1 100644
--- a/app/views/projects/pipelines/show.html.haml
+++ b/app/views/projects/pipelines/show.html.haml
@@ -9,6 +9,14 @@
- if @pipeline.commit.present?
= render "projects/pipelines/info", commit: @pipeline.commit
- = render "projects/pipelines/with_tabs", pipeline: @pipeline
+ - if @pipeline.builds.empty? && @pipeline.yaml_errors.present?
+ .bs-callout.bs-callout-danger
+ %h4 Found errors in your .gitlab-ci.yml:
+ %ul
+ - @pipeline.yaml_errors.split(",").each do |error|
+ %li= error
+ You can test your .gitlab-ci.yml in #{link_to "CI Lint", project_ci_lint_path(@project)}.
+ - else
+ = render "projects/pipelines/with_tabs", pipeline: @pipeline
.js-pipeline-details-vue{ data: { endpoint: project_pipeline_path(@project, @pipeline, format: :json) } }
diff --git a/app/views/projects/project_members/_new_project_member.html.haml b/app/views/projects/project_members/_new_project_member.html.haml
index 517fd249f6e..5e21442bb60 100644
--- a/app/views/projects/project_members/_new_project_member.html.haml
+++ b/app/views/projects/project_members/_new_project_member.html.haml
@@ -3,7 +3,7 @@
= form_for @project_member, as: :project_member, url: project_project_members_path(@project), html: { class: 'users-project-form' } do |f|
.form-group
= label_tag :user_ids, "Select members to invite", class: "label-bold"
- = users_select_tag(:user_ids, multiple: true, class: "input-clamp", scope: :all, email_user: true, placeholder: "Search for members to update or invite")
+ = users_select_tag(:user_ids, multiple: true, class: "input-clamp qa-member-select-input", scope: :all, email_user: true, placeholder: "Search for members to update or invite")
.form-group
= label_tag :access_level, "Choose a role permission", class: "label-bold"
.select-wrapper
@@ -17,5 +17,5 @@
= label_tag :expires_at, 'Access expiration date', class: 'label-bold'
= text_field_tag :expires_at, nil, class: 'form-control js-access-expiration-date', placeholder: 'Expiration date'
%i.clear-icon.js-clear-input
- = f.submit "Add to project", class: "btn btn-success"
+ = f.submit "Add to project", class: "btn btn-success qa-add-member-button"
= link_to "Import", import_project_project_members_path(@project), class: "btn btn-default", title: "Import members from another project"
diff --git a/app/views/projects/project_members/_team.html.haml b/app/views/projects/project_members/_team.html.haml
index 0c5a187f208..9682f8ac922 100644
--- a/app/views/projects/project_members/_team.html.haml
+++ b/app/views/projects/project_members/_team.html.haml
@@ -14,5 +14,5 @@
%button.member-search-btn{ type: "submit", "aria-label" => "Submit search" }
= icon("search")
= render 'shared/members/sort_dropdown'
- %ul.content-list.members-list
+ %ul.content-list.members-list.qa-members-list
= render partial: 'shared/members/member', collection: members, as: :member
diff --git a/app/views/projects/project_templates/_built_in_templates.html.haml b/app/views/projects/project_templates/_built_in_templates.html.haml
index e7636099be6..5b4d8927045 100644
--- a/app/views/projects/project_templates/_built_in_templates.html.haml
+++ b/app/views/projects/project_templates/_built_in_templates.html.haml
@@ -9,9 +9,9 @@
.text-muted
= template.description
.controls.d-flex.align-items-center
- %label.btn.btn-success.template-button.choose-template.append-right-10.append-bottom-0{ for: template.name }
- %input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: template.name, value: template.name }
+ %a.btn.btn-default.append-right-10{ href: template.preview, rel: 'noopener noreferrer', target: '_blank', data: { track_label: "create_from_template", track_property: "template_preview", track_event: "click_button", track_value: template.name } }
+ = _("Preview")
+ %label.btn.btn-success.template-button.choose-template.append-bottom-0{ for: template.name }
+ %input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: template.name, value: template.name, data: { track_label: "create_from_template", track_property: "template_use", track_event: "click_button" } }
%span
= _("Use template")
- %a.btn.btn-default{ href: template.preview, rel: 'noopener noreferrer', target: '_blank' }
- = _("Preview")
diff --git a/app/views/projects/protected_branches/shared/_branches_list.html.haml b/app/views/projects/protected_branches/shared/_branches_list.html.haml
index 9a06eca89bb..1913d06a6f8 100644
--- a/app/views/projects/protected_branches/shared/_branches_list.html.haml
+++ b/app/views/projects/protected_branches/shared/_branches_list.html.haml
@@ -1,8 +1,7 @@
.protected-branches-list.js-protected-branches-list.qa-protected-branches-list
- if @protected_branches.empty?
.card-header.bg-white
- %h3.card-title.mb-0
- Protected branch (#{@protected_branches_count})
+ Protected branch (#{@protected_branches_count})
%p.settings-message.text-center
There are currently no protected branches, protect a branch with the form above.
- else
diff --git a/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
index c3b8f2f8964..d617d85afc2 100644
--- a/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
+++ b/app/views/projects/protected_branches/shared/_create_protected_branch.html.haml
@@ -2,8 +2,7 @@
%input{ type: 'hidden', name: 'update_section', value: 'js-protected-branches-settings' }
.card
.card-header
- %h3.card-title
- Protect a branch
+ Protect a branch
.card-body
= form_errors(@protected_branch)
.form-group.row
diff --git a/app/views/projects/protected_branches/shared/_dropdown.html.haml b/app/views/projects/protected_branches/shared/_dropdown.html.haml
index b3d6068039a..67a6e8efae8 100644
--- a/app/views/projects/protected_branches/shared/_dropdown.html.haml
+++ b/app/views/projects/protected_branches/shared/_dropdown.html.haml
@@ -1,7 +1,7 @@
= f.hidden_field(:name)
= dropdown_tag('Select branch or create wildcard',
- options: { toggle_class: 'js-protected-branch-select js-filter-submit wide git-revision-dropdown-toggle qa-protected-branch-select',
+ options: { toggle_class: 'js-protected-branch-select js-filter-submit wide monospace qa-protected-branch-select',
filter: true, dropdown_class: "dropdown-menu-selectable git-revision-dropdown qa-protected-branch-dropdown", placeholder: "Search protected branches",
footer_content: true,
data: { show_no: true, show_any: true, show_upcoming: true,
diff --git a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
index b274c73d035..cbf1938664c 100644
--- a/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
+++ b/app/views/projects/protected_tags/shared/_create_protected_tag.html.haml
@@ -2,8 +2,7 @@
%input{ type: 'hidden', name: 'update_section', value: 'js-protected-tags-settings' }
.card
.card-header
- %h3.card-title
- Protect a tag
+ Protect a tag
.card-body
= form_errors(@protected_tag)
.form-group.row
diff --git a/app/views/projects/protected_tags/shared/_dropdown.html.haml b/app/views/projects/protected_tags/shared/_dropdown.html.haml
index f0d7dcccd36..824a8604f6f 100644
--- a/app/views/projects/protected_tags/shared/_dropdown.html.haml
+++ b/app/views/projects/protected_tags/shared/_dropdown.html.haml
@@ -1,7 +1,7 @@
= f.hidden_field(:name)
= dropdown_tag('Select tag or create wildcard',
- options: { toggle_class: 'js-protected-tag-select js-filter-submit wide git-revision-dropdown-toggle',
+ options: { toggle_class: 'js-protected-tag-select js-filter-submit wide monospace',
filter: true, dropdown_class: "dropdown-menu-selectable capitalize-header git-revision-dropdown", placeholder: "Search protected tags",
footer_content: true,
data: { show_no: true, show_any: true, show_upcoming: true,
diff --git a/app/views/projects/protected_tags/shared/_tags_list.html.haml b/app/views/projects/protected_tags/shared/_tags_list.html.haml
index c3081d75fb4..382ea848243 100644
--- a/app/views/projects/protected_tags/shared/_tags_list.html.haml
+++ b/app/views/projects/protected_tags/shared/_tags_list.html.haml
@@ -1,8 +1,7 @@
.protected-tags-list.js-protected-tags-list
- if @protected_tags.empty?
.card-header
- %h3.card-title
- Protected tag (#{@protected_tags_count})
+ Protected tag (#{@protected_tags_count})
%p.settings-message.text-center
There are currently no protected tags, protect a tag with the form above.
- else
diff --git a/app/views/projects/registry/repositories/index.html.haml b/app/views/projects/registry/repositories/index.html.haml
index 0426f2215ad..db1f15f96b8 100644
--- a/app/views/projects/registry/repositories/index.html.haml
+++ b/app/views/projects/registry/repositories/index.html.haml
@@ -18,8 +18,7 @@
.col-lg-12
.card
.card-header
- %h4.card-title
- = s_('ContainerRegistry|How to use the Container Registry')
+ = s_('ContainerRegistry|How to use the Container Registry')
.card-body
%p
- link_token = link_to(_('personal access token'), help_page_path('user/profile/account/two_factor_authentication', anchor: 'personal-access-tokens'), target: '_blank')
diff --git a/app/views/projects/runners/_index.html.haml b/app/views/projects/runners/_index.html.haml
index 022687b831f..ae4fee1e14c 100644
--- a/app/views/projects/runners/_index.html.haml
+++ b/app/views/projects/runners/_index.html.haml
@@ -2,7 +2,7 @@
%hr
-%p.lead To start serving your jobs you can either add specific Runners to your project or use shared Runners
+%p.lead= _('To start serving your jobs you can either add specific Runners to your project or use shared Runners')
.row
.col-sm-6
= render 'projects/runners/specific_runners'
diff --git a/app/views/projects/runners/_shared_runners.html.haml b/app/views/projects/runners/_shared_runners.html.haml
index 20a5ef039f8..080b2c0b0e9 100644
--- a/app/views/projects/runners/_shared_runners.html.haml
+++ b/app/views/projects/runners/_shared_runners.html.haml
@@ -5,21 +5,19 @@
- if Gitlab::CurrentSettings.shared_runners_text.present?
= markdown_field(Gitlab::CurrentSettings.current_application_settings, :shared_runners_text)
- else
- GitLab Shared Runners execute code of different projects on the same Runner
- unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is
- on GitLab.com).
+ = _('GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com).')
%hr
- if @project.shared_runners_enabled?
= link_to toggle_shared_runners_project_runners_path(@project), class: 'btn btn-close', method: :post do
- Disable shared Runners
+ = _('Disable shared Runners')
- else
= link_to toggle_shared_runners_project_runners_path(@project), class: 'btn btn-success', method: :post do
- Enable shared Runners
+ = _('Enable shared Runners')
&nbsp; for this project
- if @shared_runners_count.zero?
= _('This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area.')
- else
- %h4.underlined-title Available shared Runners : #{@shared_runners_count}
+ %h4.underlined-title #{_('Available shared Runners:')} #{@shared_runners_count}
%ul.bordered-list.available-shared-runners
= render partial: 'projects/runners/runner', collection: @shared_runners, as: :runner
diff --git a/app/views/projects/runners/_specific_runners.html.haml b/app/views/projects/runners/_specific_runners.html.haml
index 314af44490e..dc56a515d4c 100644
--- a/app/views/projects/runners/_specific_runners.html.haml
+++ b/app/views/projects/runners/_specific_runners.html.haml
@@ -1,16 +1,42 @@
%h3
= _('Specific Runners')
-= render partial: 'ci/runner/how_to_setup_specific_runner',
- locals: { registration_token: @project.runners_token }
+.bs-callout.help-callout
+ .append-bottom-10
+ %h4= _('Set up a specific Runner automatically')
+
+ %p
+ - link_to_help_page = link_to(_('Learn more about Kubernetes'),
+ help_page_path('user/project/clusters/index'),
+ target: '_blank',
+ rel: 'noopener noreferrer')
+
+ = _('You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}').html_safe % { link_to_help_page: link_to_help_page }
+
+ %ol
+ %li
+ = _('Click the button below to begin the install process by navigating to the Kubernetes page')
+ %li
+ = _('Select an existing Kubernetes cluster or create a new one')
+ %li
+ = _('From the Kubernetes cluster details view, install Runner from the applications list')
+
+ = link_to _('Install Runner on Kubernetes'),
+ project_clusters_path(@project),
+ class: 'btn btn-info'
+ %hr
+ = render partial: 'ci/runner/how_to_setup_runner',
+ locals: { registration_token: @project.runners_token,
+ type: 'specific',
+ reset_token_url: reset_registration_token_namespace_project_settings_ci_cd_path }
- if @project_runners.any?
- %h4.underlined-title Runners activated for this project
+ %h4.underlined-title= _('Runners activated for this project')
%ul.bordered-list.activated-specific-runners
= render partial: 'projects/runners/runner', collection: @project_runners, as: :runner
- if @assignable_runners.any?
- %h4.underlined-title Available specific runners
+ %h4.underlined-title= _('Available specific runners')
%ul.bordered-list.available-specific-runners
= render partial: 'projects/runners/runner', collection: @assignable_runners, as: :runner
= paginate @assignable_runners, theme: "gitlab", :params => { :anchor => '#js-runners-settings' }
diff --git a/app/views/projects/runners/edit.html.haml b/app/views/projects/runners/edit.html.haml
index d59f9c19862..b9d8e154913 100644
--- a/app/views/projects/runners/edit.html.haml
+++ b/app/views/projects/runners/edit.html.haml
@@ -1,4 +1,4 @@
-- page_title _('Edit'), "#{@runner.description} ##{@runner.id}", 'Runners'
+- page_title _('Edit'), "#{@runner.description} ##{@runner.id}", _('Runners')
%h4 Runner ##{@runner.id}
diff --git a/app/views/projects/services/prometheus/_configuration_banner.html.haml b/app/views/projects/services/prometheus/_configuration_banner.html.haml
index 898b55e4b39..dfcb1c5d240 100644
--- a/app/views/projects/services/prometheus/_configuration_banner.html.haml
+++ b/app/views/projects/services/prometheus/_configuration_banner.html.haml
@@ -7,7 +7,7 @@
- else
.container-fluid
.row
- - if service.prometheus_installed?
+ - if service.prometheus_available?
.col-sm-2
.svg-container
= image_tag 'illustrations/monitoring/getting_started.svg'
diff --git a/app/views/projects/services/prometheus/_metrics.html.haml b/app/views/projects/services/prometheus/_metrics.html.haml
index 98d64fafe86..597c029f755 100644
--- a/app/views/projects/services/prometheus/_metrics.html.haml
+++ b/app/views/projects/services/prometheus/_metrics.html.haml
@@ -2,9 +2,8 @@
.card.js-panel-monitored-metrics{ data: { active_metrics: active_common_project_prometheus_metrics_path(project, :json), metrics_help_path: help_page_path('user/project/integrations/prometheus_library/metrics') } }
.card-header
- %h3.card-title
- = s_('PrometheusService|Common metrics')
- %span.badge.badge-pill.js-monitored-count 0
+ = s_('PrometheusService|Common metrics')
+ %span.badge.badge-pill.js-monitored-count 0
.card-body
.loading-metrics.js-loading-metrics
%p.prepend-top-10.prepend-left-10
@@ -17,10 +16,9 @@
.card.hidden.js-panel-missing-env-vars
.card-header
- %h3.card-title
- = icon('caret-right lg fw', class: 'panel-toggle js-panel-toggle', 'aria-label' => 'Toggle panel')
- = s_('PrometheusService|Missing environment variable')
- %span.badge.badge-pill.js-env-var-count 0
+ = icon('caret-right lg fw', class: 'panel-toggle js-panel-toggle', 'aria-label' => 'Toggle panel')
+ = s_('PrometheusService|Missing environment variable')
+ %span.badge.badge-pill.js-env-var-count 0
.card-body.hidden
.flash-container
.flash-notice
diff --git a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
index ab92b757836..5ec5a06396e 100644
--- a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
@@ -39,10 +39,17 @@
= form.label :deploy_strategy_continuous, class: 'form-check-label' do
= s_('CICD|Continuous deployment to production')
= link_to icon('question-circle'), help_page_path('topics/autodevops/index.md', anchor: 'auto-deploy'), target: '_blank'
+
+ .form-check
+ = form.radio_button :deploy_strategy, 'timed_incremental', class: 'form-check-input'
+ = form.label :deploy_strategy_timed_incremental, class: 'form-check-label' do
+ = s_('CICD|Continuous deployment to production using timed incremental rollout')
+ = link_to icon('question-circle'), help_page_path('topics/autodevops/index.md', anchor: 'timed-incremental-rollout-to-production'), target: '_blank'
+
.form-check
= form.radio_button :deploy_strategy, 'manual', class: 'form-check-input'
= form.label :deploy_strategy_manual, class: 'form-check-label' do
= s_('CICD|Automatic deployment to staging, manual deployment to production')
- = link_to icon('question-circle'), help_page_path('ci/environments.md', anchor: 'manually-deploying-to-environments'), target: '_blank'
+ = link_to icon('question-circle'), help_page_path('topics/autodevops/index.md', anchor: 'incremental-rollout-to-production'), target: '_blank'
= f.submit _('Save changes'), class: "btn btn-success prepend-top-15"
diff --git a/app/views/projects/settings/ci_cd/_badge.html.haml b/app/views/projects/settings/ci_cd/_badge.html.haml
index d14360913a4..82c8ec088e5 100644
--- a/app/views/projects/settings/ci_cd/_badge.html.haml
+++ b/app/views/projects/settings/ci_cd/_badge.html.haml
@@ -15,14 +15,14 @@
.col-md-2.text-center
Markdown
.col-md-10.code.js-syntax-highlight
- = highlight('.md', badge.to_markdown)
+ = highlight('.md', badge.to_markdown, language: 'markdown')
.row
%hr
.row
.col-md-2.text-center
HTML
.col-md-10.code.js-syntax-highlight
- = highlight('.html', badge.to_html)
+ = highlight('.html', badge.to_html, language: 'html')
.row
%hr
.row
diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml
index ae923d8e6dc..621b7922072 100644
--- a/app/views/projects/settings/ci_cd/_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_form.html.haml
@@ -3,16 +3,6 @@
= form_for @project, url: project_settings_ci_cd_path(@project, anchor: 'js-general-pipeline-settings') do |f|
= form_errors(@project)
%fieldset.builds-feature
- .form-group.append-bottom-default.js-secret-runner-token
- = f.label :runners_token, _("Runner token"), class: 'label-bold'
- .form-control.js-secret-value-placeholder
- = '*' * 20
- = f.text_field :runners_token, class: "form-control hide js-secret-value", placeholder: 'xEeFCaDAB89'
- %p.form-text.text-muted= _("The secure token used by the Runner to checkout the project")
- %button.btn.btn-info.prepend-top-10.js-secret-value-reveal-button{ type: 'button', data: { secret_reveal_status: 'false' } }
- = _('Reveal value')
-
- %hr
.form-group
%h5.prepend-top-0
= _("Git strategy for pipelines")
@@ -101,7 +91,7 @@
%code \(\d+.\d+\%\) covered
%li
pytest-cov (Python) -
- %code \d+\%\s*$
+ %code ^TOTAL\s+\d+\s+\d+\s+(\d+\%)$
%li
phpunit --coverage-text --colors=never (PHP) -
%code ^\s*Lines:\s*\d+.\d+\%
diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml
index 16961784e00..98e2829ba43 100644
--- a/app/views/projects/settings/ci_cd/show.html.haml
+++ b/app/views/projects/settings/ci_cd/show.html.haml
@@ -12,7 +12,7 @@
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
- = _("Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report.")
+ = _("Customize your pipeline configuration, view your pipeline status and coverage report.")
.settings-content
= render 'form'
diff --git a/app/views/projects/settings/repository/show.html.haml b/app/views/projects/settings/repository/show.html.haml
index a0bcaaf3c54..c14e95a382c 100644
--- a/app/views/projects/settings/repository/show.html.haml
+++ b/app/views/projects/settings/repository/show.html.haml
@@ -3,7 +3,7 @@
- @content_class = "limit-container-width" unless fluid_layout
= render "projects/default_branch/show"
-= render "projects/mirrors/show"
+= render "projects/mirrors/mirror_repos"
-# Protected branches & tags use a lot of nested partials.
-# The shared parts of the views can be found in the `shared` directory.
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index aba289c790f..f29ce4f5c06 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -8,8 +8,8 @@
= render partial: 'flash_messages', locals: { project: @project }
-- if @project.repository_exists? && !@project.empty_repo?
- - signatures_path = namespace_project_signatures_path(namespace_id: @project.namespace.full_path, project_id: @project.path, id: @project.default_branch)
+- if !@project.empty_repo? && can?(current_user, :download_code, @project)
+ - signatures_path = project_signatures_path(@project, @project.default_branch)
.js-signature-container{ data: { 'signatures-path': signatures_path } }
%div{ class: [container_class, ("limit-container-width" unless fluid_layout)] }
@@ -22,7 +22,7 @@
.scrolling-tabs-container.inner-page-scroll-tabs.is-smaller
.fade-left= icon('angle-left')
.fade-right= icon('angle-right')
- .nav-links.scrolling-tabs
+ .nav-links.scrolling-tabs.quick-links
= render 'stat_anchor_list', anchors: @project.statistics_anchors(show_auto_devops_callout: show_auto_devops_callout)
= render 'stat_anchor_list', anchors: @project.statistics_buttons(show_auto_devops_callout: show_auto_devops_callout)
diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml
index 37535370940..026bc44a05f 100644
--- a/app/views/projects/tags/index.html.haml
+++ b/app/views/projects/tags/index.html.haml
@@ -14,7 +14,7 @@
= search_field_tag :search, params[:search], { placeholder: s_('TagsPage|Filter by tag name'), id: 'tag-search', class: 'form-control search-text-input input-short', spellcheck: false }
.dropdown
- %button.dropdown-toggle{ type: 'button', data: { toggle: 'dropdown'} }
+ %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown'} }
%span.light
= tags_sort_options_hash[@sort]
= icon('chevron-down')
diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml
index 24724394259..5e6d06d980e 100644
--- a/app/views/projects/tags/new.html.haml
+++ b/app/views/projects/tags/new.html.haml
@@ -20,8 +20,9 @@
.col-sm-10.create-from
.dropdown
= hidden_field_tag :ref, default_ref
- = button_tag type: 'button', title: default_ref, class: 'dropdown-menu-toggle wide js-branch-select', required: true, data: { toggle: 'dropdown', selected: default_ref, field_name: 'ref' } do
+ = button_tag type: 'button', title: default_ref, class: 'dropdown-menu-toggle wide js-branch-select monospace', required: true, data: { toggle: 'dropdown', selected: default_ref, field_name: 'ref' } do
.text-left.dropdown-toggle-text= default_ref
+ = icon('chevron-down')
= render 'shared/ref_dropdown', dropdown_class: 'wide'
.form-text.text-muted
= s_('TagsPage|Existing branch name, tag, or commit SHA')
diff --git a/app/views/projects/tree/_blob_item.html.haml b/app/views/projects/tree/_blob_item.html.haml
deleted file mode 100644
index f79f3af36d4..00000000000
--- a/app/views/projects/tree/_blob_item.html.haml
+++ /dev/null
@@ -1,12 +0,0 @@
-- is_lfs_blob = @lfs_blob_ids.include?(blob_item.id)
-%tr{ class: "tree-item #{tree_hex_class(blob_item)}" }
- %td.tree-item-file-name
- = tree_icon(type, blob_item.mode, blob_item.name)
- - file_name = blob_item.name
- = link_to project_blob_path(@project, tree_join(@id || @commit.id, blob_item.name)), class: 'str-truncated', title: file_name do
- %span= file_name
- - if is_lfs_blob
- %span.badge.label-lfs.prepend-left-5 LFS
- %td.d-none.d-sm-table-cell.tree-commit
- %td.tree-time-ago.cgray.text-right
- = render 'projects/tree/spinner'
diff --git a/app/views/projects/tree/_spinner.html.haml b/app/views/projects/tree/_spinner.html.haml
deleted file mode 100644
index b47ad0f41e4..00000000000
--- a/app/views/projects/tree/_spinner.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-%span.log_loading.hide
- %i.fa.fa-spinner.fa-spin
- Loading commit data...
diff --git a/app/views/projects/tree/_submodule_item.html.haml b/app/views/projects/tree/_submodule_item.html.haml
deleted file mode 100644
index e563c8c4036..00000000000
--- a/app/views/projects/tree/_submodule_item.html.haml
+++ /dev/null
@@ -1,6 +0,0 @@
-%tr.tree-item
- %td.tree-item-file-name
- %i.fa.fa-archive.fa-fw
- = submodule_link(submodule_item, @ref)
- %td
- %td.d-none.d-sm-table-cell
diff --git a/app/views/projects/tree/_tree_commit_column.html.haml b/app/views/projects/tree/_tree_commit_column.html.haml
index 406dccb74fb..e37fd7624be 100644
--- a/app/views/projects/tree/_tree_commit_column.html.haml
+++ b/app/views/projects/tree/_tree_commit_column.html.haml
@@ -1,2 +1,2 @@
%span.str-truncated
- = link_to_html commit.redacted_full_title_html, project_commit_path(@project, commit.id), class: 'tree-commit-link'
+ = link_to_html commit.redacted_full_title_html, project_commit_path(@project, commit.id), title: commit.redacted_full_title_html, class: 'tree-commit-link'
diff --git a/app/views/projects/tree/_tree_content.html.haml b/app/views/projects/tree/_tree_content.html.haml
index 587aeafa82f..889a13339fd 100644
--- a/app/views/projects/tree/_tree_content.html.haml
+++ b/app/views/projects/tree/_tree_content.html.haml
@@ -1,6 +1,6 @@
.tree-content-holder.js-tree-content{ 'data-logs-path': @logs_path }
- .table-holder
- %table.table#tree-slider{ class: "table_#{@hex_path} tree-table" }
+ .table-holder.bordered-box
+ %table.table#tree-slider{ class: "table_#{@hex_path} tree-table qa-file-tree" }
%thead
%tr
%th= s_('ProjectFileTree|Name')
diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml
index 9d196075bf1..601e3f25852 100644
--- a/app/views/projects/tree/_tree_header.html.haml
+++ b/app/views/projects/tree/_tree_header.html.haml
@@ -82,7 +82,7 @@
- if can_collaborate
= succeed " " do
- = link_to ide_edit_path(@project, @ref, @path), class: 'btn btn-default' do
+ = link_to ide_edit_path(@project, @ref, @path), class: 'btn btn-default qa-web-ide-button' do
= _('Web IDE')
= render 'projects/buttons/download', project: @project, ref: @ref
diff --git a/app/views/projects/tree/_tree_item.html.haml b/app/views/projects/tree/_tree_item.html.haml
deleted file mode 100644
index ce0cd95b468..00000000000
--- a/app/views/projects/tree/_tree_item.html.haml
+++ /dev/null
@@ -1,9 +0,0 @@
-%tr{ class: "tree-item #{tree_hex_class(tree_item)}" }
- %td.tree-item-file-name
- = tree_icon(type, tree_item.mode, tree_item.name)
- - path = flatten_tree(@path, tree_item)
- = link_to project_tree_path(@project, tree_join(@id || @commit.id, path)), class: 'str-truncated', title: path do
- %span= path
- %td.d-none.d-sm-table-cell.tree-commit
- %td.tree-time-ago.text-right
- = render 'projects/tree/spinner'
diff --git a/app/views/projects/tree/_tree_row.html.haml b/app/views/projects/tree/_tree_row.html.haml
index 0a5c6f048f7..8a27ea66523 100644
--- a/app/views/projects/tree/_tree_row.html.haml
+++ b/app/views/projects/tree/_tree_row.html.haml
@@ -1,6 +1,27 @@
-- if tree_row.type == :tree
- = render partial: 'projects/tree/tree_item', object: tree_row, as: 'tree_item', locals: { type: 'folder' }
-- elsif tree_row.type == :blob
- = render partial: 'projects/tree/blob_item', object: tree_row, as: 'blob_item', locals: { type: 'file' }
-- elsif tree_row.type == :commit
- = render partial: 'projects/tree/submodule_item', object: tree_row, as: 'submodule_item'
+- tree_row_name = tree_row.name
+- tree_row_type = tree_row.type
+
+%tr{ class: "tree-item file_#{hexdigest(tree_row_name)}" }
+ %td.tree-item-file-name
+ - if tree_row_type == :tree
+ = tree_icon('folder', tree_row.mode, tree_row.name)
+ - path = flatten_tree(@path, tree_row)
+ %a.str-truncated{ href: fast_project_tree_path(@project, tree_join(@id || @commit.id, path)), title: path }
+ %span= path
+
+ - elsif tree_row_type == :blob
+ = tree_icon('file', tree_row.mode, tree_row_name)
+ %a.str-truncated{ href: fast_project_blob_path(@project, tree_join(@id || @commit.id, tree_row_name)), title: tree_row_name }
+ %span= tree_row_name
+ - if @lfs_blob_ids.include?(tree_row.id)
+ %span.badge.label-lfs.prepend-left-5 LFS
+
+ - elsif tree_row_type == :commit
+ = tree_icon('archive', tree_row.mode, tree_row.name)
+ = submodule_link(tree_row, @ref)
+
+ %td.d-none.d-sm-table-cell.tree-commit
+ %td.tree-time-ago.text-right
+ %span.log_loading.hide
+ %i.fa.fa-spinner.fa-spin
+ Loading commit data...
diff --git a/app/views/projects/triggers/_index.html.haml b/app/views/projects/triggers/_index.html.haml
index a15bb4c4f3f..a559ce41e57 100644
--- a/app/views/projects/triggers/_index.html.haml
+++ b/app/views/projects/triggers/_index.html.haml
@@ -3,8 +3,7 @@
= render "projects/triggers/content"
.card
.card-header
- %h4.card-title
- Manage your project's triggers
+ Manage your project's triggers
.card-body
= render "projects/triggers/form", btn_text: "Add trigger"
%hr
diff --git a/app/views/projects/wikis/_pages_wiki_page.html.haml b/app/views/projects/wikis/_pages_wiki_page.html.haml
index cbb441d7509..c156f8cbf50 100644
--- a/app/views/projects/wikis/_pages_wiki_page.html.haml
+++ b/app/views/projects/wikis/_pages_wiki_page.html.haml
@@ -2,4 +2,5 @@
= link_to wiki_page.title, project_wiki_path(@project, wiki_page)
%small (#{wiki_page.format})
.float-right
- %small= (s_("Last edited %{date}") % { date: time_ago_with_tooltip(wiki_page.last_version.authored_date) }).html_safe
+ - if wiki_page.last_version
+ %small= (s_("Last edited %{date}") % { date: time_ago_with_tooltip(wiki_page.last_version.authored_date) }).html_safe
diff --git a/app/views/projects/wikis/_sidebar_wiki_page.html.haml b/app/views/projects/wikis/_sidebar_wiki_page.html.haml
index 2423ac6abce..769d869bd53 100644
--- a/app/views/projects/wikis/_sidebar_wiki_page.html.haml
+++ b/app/views/projects/wikis/_sidebar_wiki_page.html.haml
@@ -1,3 +1,3 @@
%li{ class: active_when(params[:id] == wiki_page.slug) }
= link_to project_wiki_path(@project, wiki_page) do
- = wiki_page.title.capitalize
+ = wiki_page.human_title
diff --git a/app/views/projects/wikis/edit.html.haml b/app/views/projects/wikis/edit.html.haml
index 80aa1500d53..26671a7b7d2 100644
--- a/app/views/projects/wikis/edit.html.haml
+++ b/app/views/projects/wikis/edit.html.haml
@@ -1,5 +1,7 @@
- @content_class = "limit-container-width" unless fluid_layout
-- page_title _("Edit"), @page.title.capitalize, _("Wiki")
+- add_to_breadcrumbs _("Wiki"), project_wiki_path(@project, @page)
+- breadcrumb_title @page.persisted? ? _("Edit") : _("New")
+- page_title @page.persisted? ? _("Edit") : _("New"), @page.human_title, _("Wiki")
= wiki_page_errors(@error)
@@ -10,9 +12,9 @@
.nav-text
%h2.wiki-page-title
- if @page.persisted?
- = link_to @page.title.capitalize, project_wiki_path(@project, @page)
+ = link_to @page.human_title, project_wiki_path(@project, @page)
- else
- = @page.title.capitalize
+ = @page.human_title
%span.light
&middot;
- if @page.persisted?
@@ -28,7 +30,7 @@
= link_to project_wiki_history_path(@project, @page), class: "btn" do
= s_("Wiki|Page history")
- if can?(current_user, :admin_wiki, @project)
- #delete-wiki-modal-wrapper{ data: { delete_wiki_url: project_wiki_path(@project, @page), page_title: @page.title.capitalize } }
+ #delete-wiki-modal-wrapper{ data: { delete_wiki_url: project_wiki_path(@project, @page), page_title: @page.human_title } }
= render 'form', uploads_path: wiki_attachment_upload_url
diff --git a/app/views/projects/wikis/history.html.haml b/app/views/projects/wikis/history.html.haml
index 969a1677d9a..c5fbeeafa54 100644
--- a/app/views/projects/wikis/history.html.haml
+++ b/app/views/projects/wikis/history.html.haml
@@ -1,4 +1,4 @@
-- page_title _("History"), @page.title.capitalize, _("Wiki")
+- page_title _("History"), @page.human_title, _("Wiki")
.wiki-page-header.has-sidebar-toggle
%button.btn.btn-default.sidebar-toggle.js-sidebar-wiki-toggle{ role: "button", type: "button" }
@@ -6,7 +6,7 @@
.nav-text
%h2.wiki-page-title
- = link_to @page.title.capitalize, project_wiki_path(@project, @page)
+ = link_to @page.human_title, project_wiki_path(@project, @page)
%span.light
&middot;
= _("History")
diff --git a/app/views/projects/wikis/show.html.haml b/app/views/projects/wikis/show.html.haml
index 19b9744b508..cc38ec12fd8 100644
--- a/app/views/projects/wikis/show.html.haml
+++ b/app/views/projects/wikis/show.html.haml
@@ -1,7 +1,7 @@
- @content_class = "limit-container-width" unless fluid_layout
-- breadcrumb_title @page.title.capitalize
+- breadcrumb_title @page.human_title
- wiki_breadcrumb_dropdown_links(@page.slug)
-- page_title @page.title.capitalize, _("Wiki")
+- page_title @page.human_title, _("Wiki")
- add_to_breadcrumbs _("Wiki"), get_project_wiki_path(@project)
.wiki-page-header.has-sidebar-toggle
@@ -9,10 +9,11 @@
= icon('angle-double-left')
.nav-text
- %h2.wiki-page-title= @page.title.capitalize
+ %h2.wiki-page-title= @page.human_title
%span.wiki-last-edit-by
- = (_("Last edited by %{name}") % { name: "<strong>#{@page.last_version.author_name}</strong>" }).html_safe
- #{time_ago_with_tooltip(@page.last_version.authored_date)}
+ - if @page.last_version
+ = (_("Last edited by %{name}") % { name: "<strong>#{@page.last_version.author_name}</strong>" }).html_safe
+ #{time_ago_with_tooltip(@page.last_version.authored_date)}
.nav-controls
= render 'main_links'
diff --git a/app/views/repository_check_mailer/notify.html.haml b/app/views/repository_check_mailer/notify.html.haml
index 94e5a5d9709..d5327a2b4cc 100644
--- a/app/views/repository_check_mailer/notify.html.haml
+++ b/app/views/repository_check_mailer/notify.html.haml
@@ -2,7 +2,7 @@
#{@message}.
%p
- = link_to "See the affected projects in the GitLab admin panel", admin_projects_url(last_repository_check_failed: 1)
+ = link_to _("See the affected projects in the GitLab admin panel"), admin_projects_url(last_repository_check_failed: 1)
%p
- You are receiving this message because you are a GitLab administrator for #{Gitlab.config.gitlab.url}.
+ = _("You are receiving this message because you are a GitLab administrator for %{url}.") % { url: Gitlab.config.gitlab.url }
diff --git a/app/views/repository_check_mailer/notify.text.haml b/app/views/repository_check_mailer/notify.text.haml
index 0902c50d052..6b64b337b0e 100644
--- a/app/views/repository_check_mailer/notify.text.haml
+++ b/app/views/repository_check_mailer/notify.text.haml
@@ -1,6 +1,5 @@
#{@message}.
\
-View details: #{admin_projects_url(last_repository_check_failed: 1)}
+= _("View details: %{details_url}") % { details_url: admin_projects_url(last_repository_check_failed: 1) }
-You are receiving this message because you are a GitLab administrator
-for #{Gitlab.config.gitlab.url}.
+= _("You are receiving this message because you are a GitLab administrator for %{url}.") % { url: Gitlab.config.gitlab.url }
diff --git a/app/views/search/results/_snippet_blob.html.haml b/app/views/search/results/_snippet_blob.html.haml
index 8b95bdf9747..b4ecd7bbae9 100644
--- a/app/views/search/results/_snippet_blob.html.haml
+++ b/app/views/search/results/_snippet_blob.html.haml
@@ -39,7 +39,7 @@
.blob-content
- snippet_chunks.each do |chunk|
- unless chunk[:data].empty?
- = highlight(snippet.file_name, chunk[:data], repository: nil, plain: snippet.blob.no_highlighting?)
+ = highlight(snippet.file_name, chunk[:data])
- else
.file-content.code
.nothing-here-block Empty file
diff --git a/app/views/shared/_allow_request_access.html.haml b/app/views/shared/_allow_request_access.html.haml
index 92268e74b1e..a50f1877d08 100644
--- a/app/views/shared/_allow_request_access.html.haml
+++ b/app/views/shared/_allow_request_access.html.haml
@@ -1,6 +1,8 @@
+- label_class = local_assigns.fetch(:bold_label, false) ? 'font-weight-bold' : ''
+
.form-check
= form.check_box :request_access_enabled, class: 'form-check-input'
= form.label :request_access_enabled, class: 'form-check-label' do
- %strong Allow users to request access
+ %span{ class: label_class }= _('Allow users to request access')
%br
- %span.descr Allow users to request access if visibility is public or internal.
+ %span.text-muted= _('Allow users to request access if visibility is public or internal.')
diff --git a/app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml b/app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml
index 6c4607b2f16..0d0a3c1aa64 100644
--- a/app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml
+++ b/app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml
@@ -1,6 +1,6 @@
- if show_auto_devops_implicitly_enabled_banner?(project)
.auto-devops-implicitly-enabled-banner.alert.alert-warning
- - more_information_link = link_to _('More information'), 'https://docs.gitlab.com/ee/topics/autodevops/', class: 'alert-link'
+ - more_information_link = link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank', class: 'alert-link'
- auto_devops_message = s_("AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}") % { more_information_link: more_information_link }
= auto_devops_message.html_safe
.alert-link-group
diff --git a/app/views/shared/_event_filter.html.haml b/app/views/shared/_event_filter.html.haml
index 7afb7b3a93b..6612497e7e2 100644
--- a/app/views/shared/_event_filter.html.haml
+++ b/app/views/shared/_event_filter.html.haml
@@ -2,13 +2,13 @@
.fade-left= icon('angle-left')
.fade-right= icon('angle-right')
%ul.nav-links.event-filter.scrolling-tabs.nav.nav-tabs
- = event_filter_link EventFilter.all, _('All'), s_('EventFilterBy|Filter by all')
+ = event_filter_link EventFilter::ALL, _('All'), s_('EventFilterBy|Filter by all')
- if event_filter_visible(:repository)
- = event_filter_link EventFilter.push, _('Push events'), s_('EventFilterBy|Filter by push events')
+ = event_filter_link EventFilter::PUSH, _('Push events'), s_('EventFilterBy|Filter by push events')
- if event_filter_visible(:merge_requests)
- = event_filter_link EventFilter.merged, _('Merge events'), s_('EventFilterBy|Filter by merge events')
+ = event_filter_link EventFilter::MERGED, _('Merge events'), s_('EventFilterBy|Filter by merge events')
- if event_filter_visible(:issues)
- = event_filter_link EventFilter.issue, _('Issue events'), s_('EventFilterBy|Filter by issue events')
+ = event_filter_link EventFilter::ISSUE, _('Issue events'), s_('EventFilterBy|Filter by issue events')
- if comments_visible?
- = event_filter_link EventFilter.comments, _('Comments'), s_('EventFilterBy|Filter by comments')
- = event_filter_link EventFilter.team, _('Team'), s_('EventFilterBy|Filter by team')
+ = event_filter_link EventFilter::COMMENTS, _('Comments'), s_('EventFilterBy|Filter by comments')
+ = event_filter_link EventFilter::TEAM, _('Team'), s_('EventFilterBy|Filter by team')
diff --git a/app/views/shared/_field.html.haml b/app/views/shared/_field.html.haml
index b89045e726a..606d0f241aa 100644
--- a/app/views/shared/_field.html.haml
+++ b/app/views/shared/_field.html.haml
@@ -24,6 +24,6 @@
- elsif type == 'select'
= form.select name, options_for_select(choices, value ? value : default_choice), {}, { class: "form-control", disabled: disabled}
- elsif type == 'password'
- = form.password_field name, autocomplete: "new-password", class: "form-control", required: value.blank? && required, disabled: disabled
+ = form.password_field name, autocomplete: "new-password", placeholder: placeholder, class: "form-control", required: value.blank? && required, disabled: disabled
- if help
%span.form-text.text-muted= help
diff --git a/app/views/shared/_file_highlight.html.haml b/app/views/shared/_file_highlight.html.haml
index 8d64cb5d698..5073e6ad48f 100644
--- a/app/views/shared/_file_highlight.html.haml
+++ b/app/views/shared/_file_highlight.html.haml
@@ -1,5 +1,3 @@
-- repository = nil unless local_assigns.key?(:repository)
-
.file-content.code.js-syntax-highlight
.line-numbers
- if blob.data.present?
@@ -13,4 +11,6 @@
= link_icon
= i
.blob-content{ data: { blob_id: blob.id } }
- = highlight(blob.path, blob.data, repository: repository, plain: blob.no_highlighting?)
+ %pre.code.highlight
+ %code
+ = blob.present.highlight
diff --git a/app/views/shared/_group_form.html.haml b/app/views/shared/_group_form.html.haml
index dbed4b94d61..973c756f496 100644
--- a/app/views/shared/_group_form.html.haml
+++ b/app/views/shared/_group_form.html.haml
@@ -2,10 +2,19 @@
- group_path = root_url
- group_path << parent.full_path + '/' if parent
-.form-group.row
- = f.label :path, class: 'col-form-label col-sm-2' do
- Group path
- .col-sm-10
+.row
+ .form-group.group-name-holder.col-sm-12
+ = f.label :name, class: 'label-bold' do
+ = _("Group name")
+ = f.text_field :name, placeholder: 'My Awesome Group', class: 'form-control input-lg',
+ required: true,
+ title: _('Please fill in a descriptive name for your group.'),
+ autofocus: true
+
+.row
+ .form-group.col-xs-12.col-sm-8
+ = f.label :path, class: 'label-bold' do
+ = _("Group URL")
.input-group.gl-field-error-anchor
.group-root-path.input-group-prepend.has-tooltip{ title: group_path, :'data-placement' => 'bottom' }
.input-group-text
@@ -13,10 +22,10 @@
- if parent
%strong= parent.full_path + '/'
= f.hidden_field :parent_id
- = f.text_field :path, placeholder: 'open-source', class: 'form-control',
+ = f.text_field :path, placeholder: 'my-awesome-group', class: 'form-control',
autofocus: local_assigns[:autofocus] || false, required: true,
pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS,
- title: 'Please choose a group path with no special characters.',
+ title: _('Please choose a group URL with no special characters.'),
"data-bind-in" => "#{'create_chat_team' if Gitlab.config.mattermost.enabled}"
- if @group.persisted?
@@ -25,23 +34,17 @@
= succeed '.' do
= link_to 'Learn more', help_page_path('user/group/index', anchor: 'changing-a-groups-path'), target: '_blank'
-.form-group.row.group-name-holder
- = f.label :name, class: 'col-form-label col-sm-2' do
- Group name
- .col-sm-10
- = f.text_field :name, class: 'form-control',
- required: true,
- title: 'You can choose a descriptive name different from the path.'
-
- if @group.persisted?
- .form-group.row.group-name-holder
- = f.label :id, class: 'col-form-label col-sm-2' do
- = _("Group ID")
- .col-sm-10
+ .row
+ .form-group.group-name-holder.col-sm-8
+ = f.label :id, class: 'label-bold' do
+ = _("Group ID")
= f.text_field :id, class: 'form-control', readonly: true
-.form-group.row.group-description-holder
- = f.label :description, class: 'col-form-label col-sm-2'
- .col-sm-10
+.row
+ .form-group.group-description-holder.col-sm-8
+ = f.label :description, class: 'label-bold' do
+ = _("Group description")
+ %span (optional)
= f.text_area :description, maxlength: 250,
class: 'form-control js-gfm-input', rows: 4
diff --git a/app/views/shared/_label.html.haml b/app/views/shared/_label.html.haml
index 71f34c0d85b..21ea188d7b3 100644
--- a/app/views/shared/_label.html.haml
+++ b/app/views/shared/_label.html.haml
@@ -23,28 +23,29 @@
%li.inline
= link_to edit_label_path(label), class: 'btn btn-transparent label-action edit has-tooltip', title: _('Edit'), data: { placement: 'bottom' }, aria_label: _('Edit') do
= sprite_icon('pencil')
- %li.inline
- .dropdown
- %button{ type: 'button', class: 'btn btn-transparent js-label-options-dropdown label-action', data: { toggle: 'dropdown' }, aria_label: _('Label actions dropdown') }
- = sprite_icon('ellipsis_v')
- .dropdown-menu.dropdown-open-left
- %ul
- - if label.is_a?(ProjectLabel) && label.project.group && can?(current_user, :admin_label, label.project.group)
- %li
- %button.js-promote-project-label-button.btn.btn-transparent.btn-action{ disabled: true, type: 'button',
- data: { url: promote_project_label_path(label.project, label),
- label_title: label.title,
- label_color: label.color,
- label_text_color: label.text_color,
- group_name: label.project.group.name,
- target: '#promote-label-modal',
- container: 'body',
- toggle: 'modal' } }
- = _('Promote to group label')
- - if can?(current_user, :admin_label, label)
- %li
- %span{ data: { toggle: 'modal', target: "#modal-delete-label-#{label.id}" } }
- %button.text-danger.remove-row{ type: 'button' }= _('Delete')
+ - if can?(current_user, :admin_label, label)
+ %li.inline
+ .dropdown
+ %button{ type: 'button', class: 'btn btn-transparent js-label-options-dropdown label-action', data: { toggle: 'dropdown' }, aria_label: _('Label actions dropdown') }
+ = sprite_icon('ellipsis_v')
+ .dropdown-menu.dropdown-open-left
+ %ul
+ - if label.is_a?(ProjectLabel) && label.project.group && can?(current_user, :admin_label, label.project.group)
+ %li
+ %button.js-promote-project-label-button.btn.btn-transparent.btn-action{ disabled: true, type: 'button',
+ data: { url: promote_project_label_path(label.project, label),
+ label_title: label.title,
+ label_color: label.color,
+ label_text_color: label.text_color,
+ group_name: label.project.group.name,
+ target: '#promote-label-modal',
+ container: 'body',
+ toggle: 'modal' } }
+ = _('Promote to group label')
+ - if can?(current_user, :admin_label, label)
+ %li
+ %span{ data: { toggle: 'modal', target: "#modal-delete-label-#{label.id}" } }
+ %button.text-danger.remove-row{ type: 'button' }= _('Delete')
- if current_user
%li.inline.label-subscription
- if can_subscribe_to_label_in_different_levels?(label)
diff --git a/app/views/shared/_labels_row.html.haml b/app/views/shared/_labels_row.html.haml
deleted file mode 100644
index 21b37a7c9ae..00000000000
--- a/app/views/shared/_labels_row.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-- labels.each do |label|
- %span.label-row.btn-group{ role: "group", aria: { label: label.name }, style: "color: #{text_color_for_bg(label.color)}" }
- = link_to_label(label, subject: @project, css_class: 'btn btn-transparent')
- %button.btn.btn-transparent.label-remove.js-label-filter-remove{ type: "button", style: "background-color: #{label.color};", data: { label: label.title } }
- = icon("times")
diff --git a/app/views/shared/_milestones_sort_dropdown.html.haml b/app/views/shared/_milestones_sort_dropdown.html.haml
index a6ba3b59365..bd68a3e4c84 100644
--- a/app/views/shared/_milestones_sort_dropdown.html.haml
+++ b/app/views/shared/_milestones_sort_dropdown.html.haml
@@ -1,5 +1,5 @@
.dropdown.inline.prepend-left-10
- %button.dropdown-toggle{ type: 'button', data: { toggle: 'dropdown' } }
+ %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown' } }
%span.light
- if @sort.present?
= milestone_sort_options_hash[@sort]
diff --git a/app/views/shared/_new_project_item_select.html.haml b/app/views/shared/_new_project_item_select.html.haml
index 9bc67a7c715..ffa61c9d1a9 100644
--- a/app/views/shared/_new_project_item_select.html.haml
+++ b/app/views/shared/_new_project_item_select.html.haml
@@ -2,6 +2,6 @@
.project-item-select-holder.btn-group
%a.btn.btn-success.new-project-item-link.qa-new-project-item-link{ href: '', data: { label: local_assigns[:label], type: local_assigns[:type] } }
= icon('spinner spin')
- = project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at', relative_path: local_assigns[:path] }, with_feature_enabled: local_assigns[:with_feature_enabled]
+ = project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at', relative_path: local_assigns[:path], with_shared: local_assigns[:with_shared], include_projects_in_subgroups: local_assigns[:include_projects_in_subgroups] }, with_feature_enabled: local_assigns[:with_feature_enabled]
%button.btn.btn-success.new-project-item-select-button.qa-new-project-item-select-button
= icon('caret-down')
diff --git a/app/views/shared/_old_visibility_level.html.haml b/app/views/shared/_old_visibility_level.html.haml
new file mode 100644
index 00000000000..fd576e4fbea
--- /dev/null
+++ b/app/views/shared/_old_visibility_level.html.haml
@@ -0,0 +1,6 @@
+.form-group.row
+ .col-sm-2.col-form-label
+ = _('Visibility level')
+ = link_to icon('question-circle'), help_page_path("public_access/public_access")
+ .col-sm-10
+ = render 'shared/visibility_level', f: f, visibility_level: visibility_level, can_change_visibility_level: can_change_visibility_level, form_model: form_model, with_label: with_label
diff --git a/app/views/shared/_personal_access_tokens_created_container.html.haml b/app/views/shared/_personal_access_tokens_created_container.html.haml
new file mode 100644
index 00000000000..3150d39b84a
--- /dev/null
+++ b/app/views/shared/_personal_access_tokens_created_container.html.haml
@@ -0,0 +1,14 @@
+- container_title = local_assigns.fetch(:container_title, 'Your New Personal Access Token')
+- clipboard_button_title = local_assigns.fetch(:clipboard_button_title, 'Copy personal access token to clipboard')
+
+.created-personal-access-token-container
+ %h5.prepend-top-0
+ = container_title
+ .form-group
+ .input-group
+ = text_field_tag 'created-personal-access-token', new_token_value, readonly: true, class: "form-control js-select-on-focus", 'aria-describedby' => "created-token-help-block"
+ %span.input-group-append
+ = clipboard_button(text: new_token_value, title: clipboard_button_title, placement: "left", class: "input-group-text btn-default btn-clipboard")
+ %span#created-token-help-block.form-text.text-muted.text-danger Make sure you save it - you won't be able to access it again.
+
+%hr
diff --git a/app/views/shared/_personal_access_tokens_table.html.haml b/app/views/shared/_personal_access_tokens_table.html.haml
index cadac1cc99d..2efd03d4867 100644
--- a/app/views/shared/_personal_access_tokens_table.html.haml
+++ b/app/views/shared/_personal_access_tokens_table.html.haml
@@ -15,8 +15,6 @@
%th Created
%th Expires
%th Scopes
- - if impersonation
- %th Token
%th
%tbody
- active_tokens.each do |token|
@@ -30,10 +28,6 @@
- else
%span.token-never-expires-label Never
%td= token.scopes.present? ? token.scopes.join(", ") : "<no scopes selected>"
- - if impersonation
- %td.token-token-container
- = text_field_tag 'impersonation-token-token', token.token, readonly: true, class: "form-control"
- = clipboard_button(text: token.token)
- path = impersonation ? revoke_admin_user_impersonation_token_path(token.user, token) : revoke_profile_personal_access_token_path(token)
%td= link_to "Revoke", path, method: :put, class: "btn btn-danger float-right", data: { confirm: "Are you sure you want to revoke this #{type} Token? This action cannot be undone." }
- else
diff --git a/app/views/shared/_sort_dropdown.html.haml b/app/views/shared/_sort_dropdown.html.haml
index be6d4f1c32b..e4463c1e0d8 100644
--- a/app/views/shared/_sort_dropdown.html.haml
+++ b/app/views/shared/_sort_dropdown.html.haml
@@ -2,7 +2,7 @@
- viewing_issues = controller.controller_name == 'issues' || controller.action_name == 'issues'
.dropdown.inline.prepend-left-10
- %button.dropdown-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' } }
+ %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' } }
= sorted_by
= icon('chevron-down')
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable.dropdown-menu-sort
diff --git a/app/views/shared/_user_dropdown_contributing_link.html.haml b/app/views/shared/_user_dropdown_contributing_link.html.haml
index 333d6fa3489..564d21a39be 100644
--- a/app/views/shared/_user_dropdown_contributing_link.html.haml
+++ b/app/views/shared/_user_dropdown_contributing_link.html.haml
@@ -1,5 +1,3 @@
%li
= link_to "https://about.gitlab.com/contributing", target: '_blank', class: 'text-nowrap' do
= _("Contribute to GitLab")
- = sprite_icon('external-link', size: 16)
-%li.divider
diff --git a/app/views/shared/_visibility_level.html.haml b/app/views/shared/_visibility_level.html.haml
index 01ce1225b8d..2f42a877beb 100644
--- a/app/views/shared/_visibility_level.html.haml
+++ b/app/views/shared/_visibility_level.html.haml
@@ -1,17 +1,19 @@
- with_label = local_assigns.fetch(:with_label, true)
-.form-group.row.visibility-level-setting
+.form-group.visibility-level-setting
- if with_label
- = f.label :visibility_level, class: 'col-form-label col-sm-2' do
- Visibility Level
- = link_to icon('question-circle'), help_page_path("public_access/public_access")
- %div{ :class => (with_label ? "col-sm-10" : "col-sm-12") }
- - if can_change_visibility_level
- = render('shared/visibility_radios', model_method: :visibility_level, form: f, selected_level: visibility_level, form_model: form_model)
- - else
- %div
- %span.info
- = visibility_level_icon(visibility_level)
- %strong
- = visibility_level_label(visibility_level)
- .light= visibility_level_description(visibility_level, form_model)
+ = f.label :visibility_level, _('Visibility level'), class: 'label-bold append-bottom-0'
+ %p
+ = _('Who can see this group?')
+ - visibility_docs_path = help_page_path('public_access/public_access')
+ - docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: visibility_docs_path }
+ = s_('Check the %{docs_link_start}documentation%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: '</a>'.html_safe }
+ - if can_change_visibility_level
+ = render('shared/visibility_radios', model_method: :visibility_level, form: f, selected_level: visibility_level, form_model: form_model)
+ - else
+ %div
+ %span.info
+ = visibility_level_icon(visibility_level)
+ %strong
+ = visibility_level_label(visibility_level)
+ .light= visibility_level_description(visibility_level, form_model)
diff --git a/app/views/shared/_visibility_radios.html.haml b/app/views/shared/_visibility_radios.html.haml
index dd6b9cce58e..9fc46afe177 100644
--- a/app/views/shared/_visibility_radios.html.haml
+++ b/app/views/shared/_visibility_radios.html.haml
@@ -3,7 +3,7 @@
- restricted = restricted_visibility_levels.include?(level)
- disabled = disallowed || restricted
.form-check{ class: [('disabled' if disabled), ('restricted' if restricted)] }
- = form.radio_button model_method, level, checked: (selected_level == level), disabled: disabled, class: 'form-check-input'
+ = form.radio_button model_method, level, checked: (selected_level == level), disabled: disabled, class: 'form-check-input', data: { track_label: "blank_project", track_event: "activate_form_input", track_property: "#{model_method}", track_value: "#{level}" }
= form.label "#{model_method}_#{level}", class: 'form-check-label' do
= visibility_level_icon(level)
.option-title
diff --git a/app/views/shared/boards/_show.html.haml b/app/views/shared/boards/_show.html.haml
index 28e6fe1b16d..f0d1dd162df 100644
--- a/app/views/shared/boards/_show.html.haml
+++ b/app/views/shared/boards/_show.html.haml
@@ -10,7 +10,7 @@
-# haml-lint:disable InlineJavaScript
%script#js-board-template{ type: "text/x-template" }= render "shared/boards/components/board"
- %script#js-board-modal-filter{ type: "text/x-template" }= render "shared/issuable/search_bar", type: :boards_modal
+ %script#js-board-modal-filter{ type: "text/x-template" }= render "shared/issuable/search_bar", type: :boards_modal, show_sorting_dropdown: false
%script#js-board-promotion{ type: "text/x-template" }= render_if_exists "shared/promotions/promote_issue_board"
#board-app.boards-app{ "v-cloak" => true, data: board_data, ":class" => "{ 'is-compact': detailIssueVisible }" }
@@ -33,7 +33,7 @@
- if @project
%board-add-issues-modal{ "new-issue-path" => new_project_issue_path(@project),
"milestone-path" => milestones_filter_dropdown_path,
- "label-path" => labels_filter_path,
+ "label-path" => labels_filter_path_with_defaults,
"empty-state-svg" => image_path('illustrations/issues.svg'),
":issue-link-base" => "issueLinkBase",
":root-path" => "rootPath",
diff --git a/app/views/shared/boards/components/_board.html.haml b/app/views/shared/boards/components/_board.html.haml
index e26f5260e5b..c6c5cadc3f5 100644
--- a/app/views/shared/boards/components/_board.html.haml
+++ b/app/views/shared/boards/components/_board.html.haml
@@ -39,14 +39,13 @@
{{ list.issuesSize }}
= render_if_exists "shared/boards/components/list_weight"
- - if can?(current_user, :admin_list, current_board_parent)
- %button.issue-count-badge-add-button.btn.btn-sm.btn-default.ml-1.has-tooltip.js-no-trigger-collapse{ type: "button",
- "@click" => "showNewIssueForm",
- "v-if" => 'list.type !== "closed"',
- "aria-label" => _("New issue"),
- "title" => _("New issue"),
- data: { placement: "top", container: "body" } }
- = icon("plus", class: "js-no-trigger-collapse")
+ %button.issue-count-badge-add-button.btn.btn-sm.btn-default.ml-1.has-tooltip.js-no-trigger-collapse{ type: "button",
+ "@click" => "showNewIssueForm",
+ "v-if" => "isNewIssueShown",
+ "aria-label" => _("New issue"),
+ "title" => _("New issue"),
+ data: { placement: "top", container: "body" } }
+ = icon("plus", class: "js-no-trigger-collapse")
%board-list{ "v-if" => 'list.type !== "blank" && list.type !== "promotion"',
":list" => "list",
diff --git a/app/views/shared/boards/components/sidebar/_labels.html.haml b/app/views/shared/boards/components/sidebar/_labels.html.haml
index 532045f3697..19159684420 100644
--- a/app/views/shared/boards/components/sidebar/_labels.html.haml
+++ b/app/views/shared/boards/components/sidebar/_labels.html.haml
@@ -19,13 +19,13 @@
":value" => "label.id" }
.dropdown
%button.dropdown-menu-toggle.js-label-select.js-multiselect.js-issue-board-sidebar{ type: "button",
- "v-bind:data-selected" => "selectedLabels",
+ ":data-selected" => "selectedLabels",
+ ":data-labels" => "issue.assignableLabelsEndpoint",
data: { toggle: "dropdown",
field_name: "issue[label_names][]",
show_no: "true",
show_any: "true",
project_id: @project&.try(:id),
- labels: labels_filter_path(false),
namespace_path: @namespace_path,
project_path: @project.try(:path) } }
%span.dropdown-toggle-text
diff --git a/app/views/shared/empty_states/_issues.html.haml b/app/views/shared/empty_states/_issues.html.haml
index 2e26fe63d3e..0ddc56dc6c3 100644
--- a/app/views/shared/empty_states/_issues.html.haml
+++ b/app/views/shared/empty_states/_issues.html.haml
@@ -8,7 +8,12 @@
= image_tag 'illustrations/issues.svg'
.col-12
.text-content
- - if current_user
+ - if has_filter_bar_param?
+ %h4.text-center
+ = _("Sorry, your filter produced no results")
+ %p.text-center
+ = _("To widen your search, change or remove filters above")
+ - elsif current_user
%h4
= _("The Issue Tracker is the place to add things that need to be improved or solved in a project")
%p
diff --git a/app/views/shared/empty_states/_labels.html.haml b/app/views/shared/empty_states/_labels.html.haml
index b629ceafeb3..bee26cd8312 100644
--- a/app/views/shared/empty_states/_labels.html.haml
+++ b/app/views/shared/empty_states/_labels.html.haml
@@ -6,6 +6,9 @@
.text-content
%h4= _("Labels can be applied to issues and merge requests to categorize them.")
%p= _("You can also star a label to make it a priority label.")
- - if can?(current_user, :admin_label, @project)
- = link_to _('New label'), new_project_label_path(@project), class: 'btn btn-success', title: _('New label'), id: 'new_label_link'
- = link_to _('Generate a default set of labels'), generate_project_labels_path(@project), method: :post, class: 'btn btn-success btn-inverted', title: _('Generate a default set of labels'), id: 'generate_labels_link'
+ .text-center
+ - if can?(current_user, :admin_label, @project)
+ = link_to _('New label'), new_project_label_path(@project), class: 'btn btn-success qa-label-create-new', title: _('New label'), id: 'new_label_link'
+ = link_to _('Generate a default set of labels'), generate_project_labels_path(@project), method: :post, class: 'btn btn-success btn-inverted', title: _('Generate a default set of labels'), id: 'generate_labels_link'
+ - if can?(current_user, :admin_label, @group)
+ = link_to _('New label'), new_group_label_path(@group), class: 'btn btn-success', title: _('New label'), id: 'new_label_link'
diff --git a/app/views/shared/empty_states/_merge_requests.html.haml b/app/views/shared/empty_states/_merge_requests.html.haml
index 421a1b2415b..06ceb9738bc 100644
--- a/app/views/shared/empty_states/_merge_requests.html.haml
+++ b/app/views/shared/empty_states/_merge_requests.html.haml
@@ -8,16 +8,19 @@
= image_tag 'illustrations/merge_requests.svg'
.col-12
.text-content
- - if has_button
+ - if has_filter_bar_param?
+ %h4.text-center
+ = _("Sorry, your filter produced no results")
+ %p.text-center
+ = _("To widen your search, change or remove filters above")
+ - else
%h4
= _("Merge requests are a place to propose changes you've made to a project and discuss those changes with others")
%p
= _("Interested parties can even contribute by pushing commits if they want to.")
- .text-center
- - if project_select_button
- = render 'shared/new_project_item_select', path: 'merge_requests/new', label: _('New merge request'), type: :merge_requests, with_feature_enabled: 'merge_requests'
- - else
- = link_to _('New merge request'), button_path, class: 'btn btn-success', title: _('New merge request'), id: 'new_merge_request_link'
- - else
- %h4.text-center
- = _("There are no merge requests to show")
+ - if has_button
+ .text-center
+ - if project_select_button
+ = render 'shared/new_project_item_select', path: 'merge_requests/new', label: _('New merge request'), type: :merge_requests, with_feature_enabled: 'merge_requests'
+ - else
+ = link_to _('New merge request'), button_path, class: 'btn btn-success', title: _('New merge request'), id: 'new_merge_request_link'
diff --git a/app/views/shared/empty_states/_wikis.html.haml b/app/views/shared/empty_states/_wikis.html.haml
index 5351c9ce6a4..df3308abe0d 100644
--- a/app/views/shared/empty_states/_wikis.html.haml
+++ b/app/views/shared/empty_states/_wikis.html.haml
@@ -5,7 +5,7 @@
- create_link = link_to s_('WikiEmpty|Create your first page'), create_path, class: 'btn btn-success', title: s_('WikiEmpty|Create your first page')
= render layout: layout_path, locals: { image_path: 'illustrations/wiki_login_empty.svg' } do
- %h4
+ %h4.text-left
= s_('WikiEmpty|The wiki lets you write documentation for your project')
%p.text-left
= s_("WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on.")
diff --git a/app/views/shared/groups/_dropdown.html.haml b/app/views/shared/groups/_dropdown.html.haml
index 2237b93a10b..1ae6d1f5ee3 100644
--- a/app/views/shared/groups/_dropdown.html.haml
+++ b/app/views/shared/groups/_dropdown.html.haml
@@ -9,7 +9,7 @@
- default_sort_by = sort_value_recently_created
.dropdown.inline.js-group-filter-dropdown-wrap.append-right-10
- %button.dropdown-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
+ %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
%span.dropdown-label
= options_hash[default_sort_by]
= icon('chevron-down')
diff --git a/app/views/shared/groups/_empty_state.html.haml b/app/views/shared/groups/_empty_state.html.haml
index c35f6f5a3c1..f6b3a49eacb 100644
--- a/app/views/shared/groups/_empty_state.html.haml
+++ b/app/views/shared/groups/_empty_state.html.haml
@@ -1,4 +1,4 @@
-.group-empty-state.row.align-items-center.justify-content-center.qa-groups-empty-state
+.group-empty-state.row.align-items-center.justify-content-center
.icon.text-center.order-md-2
= custom_icon("icon_empty_groups")
diff --git a/app/views/shared/groups/_search_form.html.haml b/app/views/shared/groups/_search_form.html.haml
index 67e1cd0d67b..49b812baefc 100644
--- a/app/views/shared/groups/_search_form.html.haml
+++ b/app/views/shared/groups/_search_form.html.haml
@@ -1,2 +1,2 @@
= form_tag request.path, method: :get, class: "group-filter-form js-group-filter-form", id: 'group-filter-form' do |f|
- = search_field_tag :filter, params[:filter], placeholder: s_('GroupsTree|Search by name'), class: 'group-filter-form-field form-control js-groups-list-filter', spellcheck: false, id: 'group-filter-form-field', tabindex: "2"
+ = search_field_tag :filter, params[:filter], placeholder: s_('GroupsTree|Search by name'), class: 'group-filter-form-field form-control js-groups-list-filter qa-groups-filter', spellcheck: false, id: 'group-filter-form-field', tabindex: "2"
diff --git a/app/views/shared/icons/_icon_status_scheduled.svg b/app/views/shared/icons/_icon_status_scheduled.svg
new file mode 100644
index 00000000000..ca6e4efce50
--- /dev/null
+++ b/app/views/shared/icons/_icon_status_scheduled.svg
@@ -0,0 +1 @@
+<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><circle cx="7" cy="7" r="7"/><circle fill="#FFF" cx="7" cy="7" r="6"/><g transform="translate(2.75 2.75)" fill-rule="nonzero"><path d="M4.165 7.81a3.644 3.644 0 1 1 0-7.29 3.644 3.644 0 0 1 0 7.29zm0-1.042a2.603 2.603 0 1 0 0-5.206 2.603 2.603 0 0 0 0 5.206z"/><rect x="3.644" y="2.083" width="1.041" height="2.603" rx=".488"/><rect x="3.644" y="3.644" width="2.083" height="1.041" rx=".488"/></g></svg> \ No newline at end of file
diff --git a/app/views/shared/icons/_icon_status_scheduled_borderless.svg b/app/views/shared/icons/_icon_status_scheduled_borderless.svg
new file mode 100644
index 00000000000..dc38c01d898
--- /dev/null
+++ b/app/views/shared/icons/_icon_status_scheduled_borderless.svg
@@ -0,0 +1 @@
+<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M6.16 11.55a5.39 5.39 0 1 1 0-10.78 5.39 5.39 0 0 1 0 10.78zm0-1.54a3.85 3.85 0 1 0 0-7.7 3.85 3.85 0 0 0 0 7.7z"/><rect x="5.39" y="3.08" width="1.54" height="3.85" rx=".767"/><rect x="5.39" y="5.39" width="3.08" height="1.54" rx=".767"/></svg> \ No newline at end of file
diff --git a/app/views/shared/issuable/_close_reopen_button.html.haml b/app/views/shared/issuable/_close_reopen_button.html.haml
index 70e05eb1c8c..4f6a71b6071 100644
--- a/app/views/shared/issuable/_close_reopen_button.html.haml
+++ b/app/views/shared/issuable/_close_reopen_button.html.haml
@@ -1,16 +1,18 @@
- is_current_user = issuable_author_is_current_user(issuable)
- display_issuable_type = issuable_display_type(issuable)
- button_method = issuable_close_reopen_button_method(issuable)
+- are_close_and_open_buttons_hidden = issuable_button_hidden?(issuable, true) && issuable_button_hidden?(issuable, false)
-- if can_update
- - if is_current_user
+- if is_current_user
+ - if can_update
= link_to "Close #{display_issuable_type}", close_issuable_path(issuable), method: button_method,
class: "d-none d-sm-none d-md-block btn btn-grouped btn-close js-btn-issue-action #{issuable_button_visibility(issuable, true)}", title: "Close #{display_issuable_type}"
- - else
- = render 'shared/issuable/close_reopen_report_toggle', issuable: issuable
- - if can_reopen && is_current_user
+ - if can_reopen
= link_to "Reopen #{display_issuable_type}", reopen_issuable_path(issuable), method: button_method,
class: "d-none d-sm-none d-md-block btn btn-grouped btn-reopen js-btn-issue-action #{issuable_button_visibility(issuable, false)}", title: "Reopen #{display_issuable_type}"
- else
- = link_to 'Report abuse', new_abuse_report_path(user_id: issuable.author.id, ref_url: issuable_url(issuable)),
- class: 'd-none d-sm-none d-md-block btn btn-grouped btn-close-color', title: 'Report abuse'
+ - if can_update && !are_close_and_open_buttons_hidden
+ = render 'shared/issuable/close_reopen_report_toggle', issuable: issuable
+ - else
+ = link_to 'Report abuse', new_abuse_report_path(user_id: issuable.author.id, ref_url: issuable_url(issuable)),
+ class: 'd-none d-sm-none d-md-block btn btn-grouped btn-close-color', title: 'Report abuse'
diff --git a/app/views/shared/issuable/_filter.html.haml b/app/views/shared/issuable/_filter.html.haml
deleted file mode 100644
index c7037335866..00000000000
--- a/app/views/shared/issuable/_filter.html.haml
+++ /dev/null
@@ -1,32 +0,0 @@
-.issues-filters
- .issues-details-filters.row-content-block.second-block
- = form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_title, :label_name, :search]), method: :get, class: 'filter-form js-filter-form' do
- - if params[:search].present?
- = hidden_field_tag :search, params[:search]
- .issues-other-filters
- .filter-item.inline
- - if params[:author_id].present?
- = hidden_field_tag(:author_id, params[:author_id])
- = dropdown_tag(user_dropdown_label(params[:author_id], "Author"), options: { toggle_class: "js-user-search js-filter-submit js-author-search", title: "Filter by author", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-author js-filter-submit",
- placeholder: "Search authors", data: { any_user: "Any Author", first_user: current_user&.username, current_user: true, project_id: @project&.id, group_id: @group&.id, selected: params[:author_id], field_name: "author_id", default_label: "Author" } })
-
- .filter-item.inline
- - if params[:assignee_id].present?
- = hidden_field_tag(:assignee_id, params[:assignee_id])
- = dropdown_tag(user_dropdown_label(params[:assignee_id], "Assignee"), options: { toggle_class: "js-user-search js-filter-submit js-assignee-search", title: "Filter by assignee", filter: true, dropdown_class: "dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee js-filter-submit",
- placeholder: "Search assignee", data: { any_user: "Any Assignee", first_user: current_user&.username, null_user: true, current_user: true, project_id: @project&.id, group_id: @group&.id, selected: params[:assignee_id], field_name: "assignee_id", default_label: "Assignee" } })
-
- .filter-item.inline.milestone-filter
- = render "shared/issuable/milestone_dropdown", selected: finder.milestones.try(:first), name: :milestone_title, show_any: true, show_upcoming: true, show_started: true
-
- .filter-item.inline.labels-filter
- = render "shared/issuable/label_dropdown", selected: selected_labels, use_id: false, selected_toggle: params[:label_name], data_options: { field_name: "label_name[]" }
-
- - unless @no_filters_set
- .float-right
- = render 'shared/sort_dropdown'
-
- - has_labels = @labels && @labels.any?
- .row-content-block.second-block.filtered-labels{ class: ("hidden" unless has_labels) }
- - if has_labels
- = render 'shared/labels_row', labels: @labels
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index 5b28a43a361..1618655182c 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -1,6 +1,7 @@
- form = local_assigns.fetch(:f)
- commits = local_assigns[:commits]
- project = @target_project || @project
+- presenter = local_assigns.fetch(:presenter, nil)
= form_errors(issuable)
@@ -16,6 +17,8 @@
= render 'shared/issuable/form/template_selector', issuable: issuable
= render 'shared/issuable/form/title', issuable: issuable, form: form, has_wip_commits: commits && commits.detect(&:work_in_progress?)
+- if Feature.enabled?(:issue_suggestions) && Feature.enabled?(:graphql)
+ #js-suggestions{ data: { project_path: @project.full_path } }
= render 'shared/form_elements/description', model: issuable, form: form, project: project
@@ -29,7 +32,7 @@
= render 'shared/issuable/form/metadata', issuable: issuable, form: form
-= render_if_exists 'shared/issuable/approvals', issuable: issuable, form: form
+= render_if_exists 'shared/issuable/approvals', issuable: issuable, presenter: presenter, form: form
= render 'shared/issuable/form/branch_chooser', issuable: issuable, form: form
diff --git a/app/views/shared/issuable/_label_dropdown.html.haml b/app/views/shared/issuable/_label_dropdown.html.haml
index 0b42b33581a..d5fb85ba0f3 100644
--- a/app/views/shared/issuable/_label_dropdown.html.haml
+++ b/app/views/shared/issuable/_label_dropdown.html.haml
@@ -8,7 +8,7 @@
- classes = local_assigns.fetch(:classes, [])
- selected = local_assigns.fetch(:selected, nil)
- dropdown_title = local_assigns.fetch(:dropdown_title, "Filter by label")
-- dropdown_data = {toggle: 'dropdown', field_name: "label_name[]", show_no: "true", show_any: "true", namespace_path: @project.try(:namespace).try(:full_path), project_path: @project.try(:path), labels: labels_filter_path, default_label: "Labels"}
+- dropdown_data = {toggle: 'dropdown', field_name: "label_name[]", show_no: "true", show_any: "true", namespace_path: @project.try(:namespace).try(:full_path), project_path: @project.try(:path), labels: labels_filter_path_with_defaults, default_label: "Labels"}
- dropdown_data.merge!(data_options)
- label_name = local_assigns.fetch(:label_name, "Labels")
- no_default_styles = local_assigns.fetch(:no_default_styles, false)
@@ -20,7 +20,7 @@
= hidden_field_tag data_options[:field_name], use_id ? label.try(:id) : label.try(:title), id: nil
.dropdown
- %button.dropdown-menu-toggle.js-label-select.js-multiselect{ class: classes.join(' '), type: "button", data: dropdown_data }
+ %button.dropdown-menu-toggle.js-label-select.js-multiselect.qa-issuable-label{ class: classes.join(' '), type: "button", data: dropdown_data }
- apply_is_default_styles = (selected.nil? || selected.empty?) && !no_default_styles
%span.dropdown-toggle-text{ class: ("is-default" if apply_is_default_styles) }
= multi_label_name(selected, label_name)
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 659e03fd67d..7c5af0b9775 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -1,15 +1,14 @@
- type = local_assigns.fetch(:type)
- board = local_assigns.fetch(:board, nil)
- block_css_class = type != :boards_modal ? 'row-content-block second-block' : ''
-- full_path = @project.present? ? @project.full_path : @group.full_path
- user_can_admin_list = board && can?(current_user, :admin_list, board.parent)
+- show_sorting_dropdown = local_assigns.fetch(:show_sorting_dropdown, true)
.issues-filters
.issues-details-filters.filtered-search-block{ class: block_css_class, "v-pre" => type == :boards_modal }
- if type == :boards
- #js-multiple-boards-switcher.inline.boards-switcher{ "v-cloak" => true }
- = render_if_exists "shared/boards/switcher", board: board
- = form_tag page_filter_path(without: [:assignee_id, :author_id, :milestone_title, :label_name, :search]), method: :get, class: 'filter-form js-filter-form' do
+ = render_if_exists "shared/boards/switcher", board: board
+ = form_tag page_filter_path, method: :get, class: 'filter-form js-filter-form' do
- if params[:search].present?
= hidden_field_tag :search, params[:search]
- if @can_bulk_update
@@ -24,7 +23,7 @@
dropdown_class: "filtered-search-history-dropdown",
content_class: "filtered-search-history-dropdown-content",
title: "Recent searches" }) do
- .js-filtered-search-history-dropdown{ data: { full_path: full_path } }
+ .js-filtered-search-history-dropdown{ data: { full_path: search_history_storage_prefix } }
.filtered-search-box-input-container.droplab-dropdown
.scroll-container
%ul.tokens-container.list-unstyled
@@ -33,13 +32,13 @@
#js-dropdown-hint.filtered-search-input-dropdown-menu.dropdown-menu.hint-dropdown
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { action: 'submit' } }
- %button.btn.btn-link
+ %button.btn.btn-link{ type: 'button' }
= sprite_icon('search')
%span
- Press Enter or click to search
+ = _('Press Enter or click to search')
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
- %button.btn.btn-link
+ %button.btn.btn-link{ type: 'button' }
-# Encapsulate static class name `{{icon}}` inside #{} to bypass
-# haml lint's ClassAttributeWithStaticValue
%svg
@@ -60,8 +59,11 @@
#js-dropdown-assignee.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'none' } }
- %button.btn.btn-link
- No Assignee
+ %button.btn.btn-link{ type: 'button' }
+ = _('None')
+ %li.filter-dropdown-item{ data: { value: 'any' } }
+ %button.btn.btn-link{ type: 'button' }
+ = _('Any')
%li.divider.droplab-item-ignore
- if current_user
= render 'shared/issuable/user_dropdown_item',
@@ -73,38 +75,60 @@
#js-dropdown-milestone.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'none' } }
- %button.btn.btn-link
- No Milestone
+ %button.btn.btn-link{ type: 'button' }
+ = _('None')
+ %li.filter-dropdown-item{ data: { value: 'any' } }
+ %button.btn.btn-link{ type: 'button' }
+ = _('Any')
%li.filter-dropdown-item{ data: { value: 'upcoming' } }
- %button.btn.btn-link
- Upcoming
- %li.filter-dropdown-item{ 'data-value' => 'started' }
- %button.btn.btn-link
- Started
+ %button.btn.btn-link{ type: 'button' }
+ = _('Upcoming')
+ %li.filter-dropdown-item{ data: { value: 'started' } }
+ %button.btn.btn-link{ type: 'button' }
+ = _('Started')
%li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
- %button.btn.btn-link.js-data-value
+ %button.btn.btn-link.js-data-value{ type: 'button' }
{{title}}
#js-dropdown-label.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'none' } }
- %button.btn.btn-link
- No Label
+ %button.btn.btn-link{ type: 'button' }
+ = _('None')
+ %li.filter-dropdown-item{ data: { value: 'any' } }
+ %button.btn.btn-link{ type: 'button' }
+ = _('Any')
%li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
- %button.btn.btn-link
+ %button.btn.btn-link{ type: 'button' }
%span.dropdown-label-box{ style: 'background: {{color}}' }
%span.label-title.js-data-value
{{title}}
#js-dropdown-my-reaction.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul{ data: { dropdown: true } }
+ %li.filter-dropdown-item{ data: { value: 'none' } }
+ %button.btn.btn-link{ type: 'button' }
+ = _('None')
+ %li.filter-dropdown-item{ data: { value: 'any' } }
+ %button.btn.btn-link{ type: 'button' }
+ = _('Any')
+ %li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
- %button.btn.btn-link
+ %button.btn.btn-link{ type: 'button' }
%gl-emoji
%span.js-data-value.prepend-left-10
{{name}}
+ #js-dropdown-wip.filtered-search-input-dropdown-menu.dropdown-menu
+ %ul.filter-dropdown{ data: { dropdown: true } }
+ %li.filter-dropdown-item{ data: { value: 'yes', capitalize: true } }
+ %button.btn.btn-link{ type: 'button' }
+ = _('Yes')
+ %li.filter-dropdown-item{ data: { value: 'no', capitalize: true } }
+ %button.btn.btn-link{ type: 'button' }
+ = _('No')
= render_if_exists 'shared/issuable/filter_weight', type: type
@@ -118,5 +142,5 @@
- if @project
#js-add-issues-btn.prepend-left-10{ data: { can_admin_list: can?(current_user, :admin_list, @project) } }
#js-toggle-focus-btn
- - elsif type != :boards_modal
+ - elsif show_sorting_dropdown
= render 'shared/sort_dropdown'
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index 32b609eed0d..5295e656ab0 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -24,7 +24,7 @@
.block.milestone
.sidebar-collapsed-icon.has-tooltip{ title: milestone_tooltip_title(issuable.milestone), data: { container: 'body', html: 'true', placement: 'left', boundary: 'viewport' } }
= icon('clock-o', 'aria-hidden': 'true')
- %span.milestone-title
+ %span.milestone-title.collapse-truncated-title
- if issuable.milestone
= issuable.milestone.title
- else
@@ -98,7 +98,7 @@
= icon('spinner spin', class: 'hidden block-loading', 'aria-hidden': 'true')
- if can_edit_issuable
= link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right'
- .value.issuable-show-labels.dont-hide.hide-collapsed{ class: ("has-labels" if selected_labels.any?) }
+ .value.issuable-show-labels.dont-hide.hide-collapsed.qa-labels-block{ class: ("has-labels" if selected_labels.any?) }
- if selected_labels.any?
- selected_labels.each do |label|
= link_to_label(label, subject: issuable.project, type: issuable.to_ability_name)
@@ -109,7 +109,7 @@
- selected_labels.each do |label|
= hidden_field_tag "#{issuable.to_ability_name}[label_names][]", label.id, id: nil
.dropdown
- %button.dropdown-menu-toggle.js-label-select.js-multiselect.js-label-sidebar-dropdown{ type: "button", data: {toggle: "dropdown", default_label: "Labels", field_name: "#{issuable.to_ability_name}[label_names][]", ability_name: issuable.to_ability_name, show_no: "true", show_any: "true", namespace_path: @project.try(:namespace).try(:full_path), project_path: @project.try(:path), issue_update: issuable_json_path(issuable), labels: (labels_filter_path(false) if @project), display: 'static' } }
+ %button.dropdown-menu-toggle.js-label-select.js-multiselect.js-label-sidebar-dropdown{ type: "button", data: {toggle: "dropdown", default_label: "Labels", field_name: "#{issuable.to_ability_name}[label_names][]", ability_name: issuable.to_ability_name, show_no: "true", show_any: "true", namespace_path: @project.try(:namespace).try(:full_path), project_path: @project.try(:path), issue_update: issuable_json_path(issuable), labels: (labels_filter_path_with_defaults if @project), display: 'static' } }
%span.dropdown-toggle-text{ class: ("is-default" if selected_labels.empty?) }
= multi_label_name(selected_labels, "Labels")
= icon('chevron-down', 'aria-hidden': 'true')
diff --git a/app/views/shared/issuable/_sidebar_todo.html.haml b/app/views/shared/issuable/_sidebar_todo.html.haml
index 583b33a8a1b..660ee6d5777 100644
--- a/app/views/shared/issuable/_sidebar_todo.html.haml
+++ b/app/views/shared/issuable/_sidebar_todo.html.haml
@@ -1,6 +1,6 @@
- is_collapsed = local_assigns.fetch(:is_collapsed, false)
-- mark_content = is_collapsed ? icon('check-square', class: 'todo-undone') : _('Mark todo as done')
-- todo_content = is_collapsed ? icon('plus-square') : _('Add todo')
+- mark_content = is_collapsed ? sprite_icon('todo-done', css_class: 'todo-undone') : _('Mark todo as done')
+- todo_content = is_collapsed ? sprite_icon('todo-add') : _('Add todo')
%button.issuable-todo-btn.js-issuable-todo{ type: 'button',
class: (is_collapsed ? 'btn-blank sidebar-collapsed-icon dont-change-state has-tooltip' : 'btn btn-default issuable-header-btn float-right'),
diff --git a/app/views/shared/issuable/form/_title.html.haml b/app/views/shared/issuable/form/_title.html.haml
index e49bdec386a..56c4b021eab 100644
--- a/app/views/shared/issuable/form/_title.html.haml
+++ b/app/views/shared/issuable/form/_title.html.haml
@@ -9,7 +9,7 @@
autocomplete: 'off', class: 'form-control pad qa-issuable-form-title', placeholder: _('Title')
- if issuable.respond_to?(:work_in_progress?)
- %p.form-text.text-muted
+ .form-text.text-muted
.js-wip-explanation
%a.js-toggle-wip{ href: '', tabindex: -1 }
Remove the
diff --git a/app/views/shared/labels/_form.html.haml b/app/views/shared/labels/_form.html.haml
index 335c34a4632..7619d0a2e9c 100644
--- a/app/views/shared/labels/_form.html.haml
+++ b/app/views/shared/labels/_form.html.haml
@@ -4,18 +4,18 @@
.form-group.row
= f.label :title, class: 'col-form-label col-sm-2'
.col-sm-10
- = f.text_field :title, class: "form-control", required: true, autofocus: true
+ = f.text_field :title, class: "form-control qa-label-title", required: true, autofocus: true
.form-group.row
= f.label :description, class: 'col-form-label col-sm-2'
.col-sm-10
- = f.text_field :description, class: "form-control js-quick-submit"
+ = f.text_field :description, class: "form-control js-quick-submit qa-label-description"
.form-group.row
= f.label :color, "Background color", class: 'col-form-label col-sm-2'
.col-sm-10
.input-group
.input-group-prepend
.input-group-text.label-color-preview &nbsp;
- = f.text_field :color, class: "form-control"
+ = f.text_field :color, class: "form-control qa-label-color"
.form-text.text-muted
Choose any color.
%br
@@ -30,5 +30,5 @@
- if @label.persisted?
= f.submit 'Save changes', class: 'btn btn-success js-save-button'
- else
- = f.submit 'Create label', class: 'btn btn-success js-save-button'
+ = f.submit 'Create label', class: 'btn btn-success js-save-button qa-label-create-button'
= link_to 'Cancel', back_path, class: 'btn btn-cancel'
diff --git a/app/views/shared/labels/_nav.html.haml b/app/views/shared/labels/_nav.html.haml
new file mode 100644
index 00000000000..98572db738b
--- /dev/null
+++ b/app/views/shared/labels/_nav.html.haml
@@ -0,0 +1,20 @@
+- subscribed = params[:subscribed]
+
+.top-area.adjust
+ %ul.nav-links.nav.nav-tabs
+ %li{ class: active_when(subscribed != 'true') }>
+ = link_to labels_filter_path do
+ = _('All')
+ - if current_user
+ %li{ class: active_when(subscribed == 'true') }>
+ = link_to labels_filter_path(subscribed: 'true') do
+ = _('Subscribed')
+ .nav-controls
+ = form_tag labels_filter_path, method: :get do
+ = hidden_field_tag :subscribed, params[:subscribed]
+ .input-group
+ = search_field_tag :search, params[:search], { placeholder: _('Filter'), id: 'label-search', class: 'form-control search-text-input input-short', spellcheck: false }
+ %span.input-group-append
+ %button.btn.btn-default{ type: "submit", "aria-label" => _('Submit search') }
+ = icon("search")
+ = render 'shared/labels/sort_dropdown'
diff --git a/app/views/shared/labels/_sort_dropdown.html.haml b/app/views/shared/labels/_sort_dropdown.html.haml
index ff6e2947ffd..d664ef1cc2f 100644
--- a/app/views/shared/labels/_sort_dropdown.html.haml
+++ b/app/views/shared/labels/_sort_dropdown.html.haml
@@ -1,9 +1,9 @@
- sort_title = label_sort_options_hash[@sort] || sort_title_name_desc
.dropdown.inline
- %button.dropdown-toggle{ type: 'button', data: { toggle: 'dropdown' } }
+ %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown' } }
= sort_title
= icon('chevron-down')
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-sort
%li
- label_sort_options_hash.each do |value, title|
- = sortable_item(title, page_filter_path(sort: value, label: true), sort_title)
+ = sortable_item(title, page_filter_path(sort: value, label: true, subscribed: params[:subscribed]), sort_title)
diff --git a/app/views/shared/members/_filter_2fa_dropdown.html.haml b/app/views/shared/members/_filter_2fa_dropdown.html.haml
index 95c35c56b3c..3e98587aeaa 100644
--- a/app/views/shared/members/_filter_2fa_dropdown.html.haml
+++ b/app/views/shared/members/_filter_2fa_dropdown.html.haml
@@ -1,10 +1,10 @@
- filter = params[:two_factor] || 'everyone'
-- filter_options = { 'everyone' => 'Everyone', 'enabled' => 'Enabled', 'disabled' => 'Disabled' }
+- filter_options = { 'everyone' => _('Everyone'), 'enabled' => _('Enabled'), 'disabled' => _('Disabled') }
.dropdown.inline.member-filter-2fa-dropdown
= dropdown_toggle('2FA: ' + filter_options[filter], { toggle: 'dropdown' })
%ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-selectable
%li.dropdown-header
- Filter by two-factor authentication
+ = _("Filter by two-factor authentication")
- filter_options.each do |value, title|
%li
= link_to filter_group_project_member_path(two_factor: value), class: ("is-active" if filter == value) do
diff --git a/app/views/shared/members/_group.html.haml b/app/views/shared/members/_group.html.haml
index d0b492b43f3..9ec76d82d18 100644
--- a/app/views/shared/members/_group.html.haml
+++ b/app/views/shared/members/_group.html.haml
@@ -12,7 +12,7 @@
- if group_link.expires?
·
%span{ class: ('text-warning' if group_link.expires_soon?) }
- Expires in #{distance_of_time_in_words_to_now(group_link.expires_at)}
+ = _("Expires in %{expires_at}").html_safe % { expires_at: distance_of_time_in_words_to_now(group_link.expires_at) }
.controls.member-controls
= form_tag project_group_link_path(@project, group_link), method: :put, remote: true, class: 'js-edit-member-form form-group row append-right-5' do
= hidden_field_tag "group_link[group_access]", group_link.group_access
@@ -24,7 +24,7 @@
= group_link.human_access
= icon("chevron-down")
.dropdown-menu.dropdown-select.dropdown-menu-right.dropdown-menu-selectable
- = dropdown_title("Change permissions")
+ = dropdown_title(_("Change permissions"))
.dropdown-content
%ul
- Gitlab::Access.options.each do |role, role_id|
@@ -33,13 +33,13 @@
class: ("is-active" if group_link.group_access == role_id),
data: { id: role_id, el_id: dom_id }
.prepend-left-5.clearable-input.member-form-control
- = text_field_tag 'group_link[expires_at]', group_link.expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: 'Expiration date', id: "member_expires_at_#{group.id}", disabled: !can_admin_member
+ = text_field_tag 'group_link[expires_at]', group_link.expires_at, class: 'form-control js-access-expiration-date js-member-update-control', placeholder: _('Expiration date'), id: "member_expires_at_#{group.id}", disabled: !can_admin_member
%i.clear-icon.js-clear-input
- if can_admin_member
= link_to project_group_link_path(@project, group_link),
method: :delete,
- data: { confirm: "Are you sure you want to remove #{group.name}?" },
+ data: { confirm: _("Are you sure you want to remove %{group_name}?") % { group_name: group.name } },
class: 'btn btn-remove prepend-left-10' do
%span.d-block.d-sm-none
- Delete
+ = _("Delete")
= icon('trash', class: 'd-none d-sm-block')
diff --git a/app/views/shared/members/_member.html.haml b/app/views/shared/members/_member.html.haml
index af29c0fe59e..a7fd75d85d7 100644
--- a/app/views/shared/members/_member.html.haml
+++ b/app/views/shared/members/_member.html.haml
@@ -14,16 +14,18 @@
= user_status(user)
%span.cgray= user.to_reference
+ = render_if_exists 'shared/members/ee/sso_badge', member: member
+
- if user == current_user
- %span.badge.badge-success.prepend-left-5 It's you
+ %span.badge.badge-success.prepend-left-5= _("It's you")
- if user.blocked?
%label.badge.badge-danger
- %strong Blocked
+ %strong= _("Blocked")
- if user.two_factor_enabled?
- %label.label.label-info
- 2FA
+ %label.badge.badge-info
+ = _("2FA")
- if source.instance_of?(Group) && source != @group
&middot;
@@ -31,14 +33,13 @@
.cgray
- if member.request?
- Requested
- = time_ago_with_tooltip(member.requested_at)
+ = _("Requested %{time_ago}").html_safe % { time_ago: time_ago_with_tooltip(member.requested_at) }
- else
- Given access #{time_ago_with_tooltip(member.created_at)}
+ = _("Given access %{time_ago}").html_safe % { time_ago: time_ago_with_tooltip(member.created_at) }
- if member.expires?
·
%span{ class: "#{"text-warning" if member.expires_soon?} has-tooltip", title: member.expires_at.to_time.in_time_zone.to_s(:medium) }
- Expires in #{distance_of_time_in_words_to_now(member.expires_at)}
+ = _("Expires in %{expires_at}").html_safe % { expires_at: distance_of_time_in_words_to_now(member.expires_at) }
- else
= image_tag avatar_icon_for_email(member.invite_email, 40), class: "avatar s40", alt: ''
@@ -59,7 +60,7 @@
= link_to icon('paper-plane'), polymorphic_path([:resend_invite, member]),
method: :post,
class: 'btn btn-default prepend-left-10 d-none d-sm-block',
- title: 'Resend invite'
+ title: _('Resend invite')
- if user != current_user && member.can_update?
= form_for member, remote: true, html: { class: 'js-edit-member-form form-group row append-right-5' } do |f|
@@ -71,7 +72,7 @@
= member.human_access
= icon("chevron-down")
.dropdown-menu.dropdown-select.dropdown-menu-right.dropdown-menu-selectable
- = dropdown_title("Change permissions")
+ = dropdown_title(_("Change permissions"))
.dropdown-content
%ul
- member.access_level_roles.each do |role, role_id|
@@ -82,7 +83,7 @@
.prepend-left-5.clearable-input.member-form-control
= f.text_field :expires_at,
class: 'form-control js-access-expiration-date js-member-update-control',
- placeholder: 'Expiration date',
+ placeholder: _('Expiration date'),
id: "member_expires_at_#{member.id}",
data: { el_id: dom_id(member) }
%i.clear-icon.js-clear-input
@@ -93,15 +94,15 @@
= link_to polymorphic_path([:approve_access_request, member]),
method: :post,
class: 'btn btn-success prepend-left-10',
- title: 'Grant access' do
+ title: _('Grant access') do
%span{ class: ('d-block d-sm-none' unless force_mobile_view) }
- Grant access
+ = _('Grant access')
- unless force_mobile_view
= icon('check inverse', class: 'd-none d-sm-block')
- if member.can_remove?
- if current_user == user
- = link_to icon('sign-out', text: 'Leave'), polymorphic_path([:leave, member.source, :members]),
+ = link_to icon('sign-out', text: _('Leave')), polymorphic_path([:leave, member.source, :members]),
method: :delete,
data: { confirm: leave_confirmation_message(member.source) },
class: 'btn btn-remove prepend-left-10'
@@ -112,7 +113,7 @@
class: 'btn btn-remove prepend-left-10',
title: remove_member_title(member) do
%span{ class: ('d-block d-sm-none' unless force_mobile_view) }
- Delete
+ = _("Delete")
- unless force_mobile_view
= icon('trash', class: 'd-none d-sm-block')
- else
diff --git a/app/views/shared/members/_requests.html.haml b/app/views/shared/members/_requests.html.haml
index 54679ab86cc..1f62c3cbcf4 100644
--- a/app/views/shared/members/_requests.html.haml
+++ b/app/views/shared/members/_requests.html.haml
@@ -6,7 +6,7 @@
.card.prepend-top-default{ class: ('card-mobile' if force_mobile_view ) }
.card-header
- Users requesting access to
+ = _("Users requesting access to")
%strong= membership_source.name
%span.badge.badge-pill= requesters.size
%ul.content-list.members-list
diff --git a/app/views/shared/members/_sort_dropdown.html.haml b/app/views/shared/members/_sort_dropdown.html.haml
index 56b8c8f033e..59bdfb73e6e 100644
--- a/app/views/shared/members/_sort_dropdown.html.haml
+++ b/app/views/shared/members/_sort_dropdown.html.haml
@@ -2,7 +2,7 @@
= dropdown_toggle(member_sort_options_hash[@sort], { toggle: 'dropdown' })
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable
%li.dropdown-header
- Sort by
+ = _("Sort by")
- member_sort_options_hash.each do |value, title|
%li
= link_to filter_group_project_member_path(sort: value), class: ("is-active" if @sort == value) do
diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml
index 3dd2842be4f..ed7fefba56d 100644
--- a/app/views/shared/milestones/_milestone.html.haml
+++ b/app/views/shared/milestones/_milestone.html.haml
@@ -35,8 +35,8 @@
.col-sm-2
.milestone-actions.d-flex.justify-content-sm-start.justify-content-md-end
- if @project
- - if can?(current_user, :admin_milestone, milestone.project) and milestone.active?
- - if @project.group
+ - if can_admin_project_milestones? and milestone.active?
+ - if can_admin_group_milestones?
%button.js-promote-project-milestone-button.btn.btn-blank.btn-sm.btn-grouped.has-tooltip{ title: _('Promote to Group Milestone'),
disabled: true,
type: 'button',
diff --git a/app/views/shared/notes/_note.html.haml b/app/views/shared/notes/_note.html.haml
index 84adbd444c5..bc918430823 100644
--- a/app/views/shared/notes/_note.html.haml
+++ b/app/views/shared/notes/_note.html.haml
@@ -5,7 +5,7 @@
- note_editable = can?(current_user, :admin_note, note)
- note_counter = local_assigns.fetch(:note_counter, 0)
-%li.timeline-entry{ id: dom_id(note),
+%li.timeline-entry.note-wrapper.outlined{ id: dom_id(note),
class: ["note", "note-row-#{note.id}", ('system-note' if note.system)],
data: { author_id: note.author.id,
editable: note_editable,
diff --git a/app/views/shared/notes/_notes_with_form.html.haml b/app/views/shared/notes/_notes_with_form.html.haml
index 9dd1c24fdfa..4c4050c6054 100644
--- a/app/views/shared/notes/_notes_with_form.html.haml
+++ b/app/views/shared/notes/_notes_with_form.html.haml
@@ -7,8 +7,8 @@
= render 'shared/notes/edit_form', project: @project
- if can_create_note?
- %ul.notes.notes-form.timeline
- %li.timeline-entry
+ .notes.notes-form.timeline
+ .timeline-entry.note-form
.timeline-entry-inner
.flash-container.timeline-content
diff --git a/app/views/shared/notifications/_button.html.haml b/app/views/shared/notifications/_button.html.haml
index 09ddf732ada..f6c7ca70ebd 100644
--- a/app/views/shared/notifications/_button.html.haml
+++ b/app/views/shared/notifications/_button.html.haml
@@ -9,11 +9,11 @@
%button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: "Notification setting", "aria-label" => "Notification setting: #{notification_title(notification_setting.level)}", data: { container: "body", toggle: "modal", target: "#" + notifications_menu_identifier("modal", notification_setting), display: 'static' } }
= icon("bell", class: "js-notification-loading")
= notification_title(notification_setting.level)
- %button.btn.dropdown-toggle{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting) } }
+ %button.btn.dropdown-toggle{ data: { toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
= icon('caret-down')
.sr-only Toggle dropdown
- else
- %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: "Notification setting", "aria-label" => "Notification setting: #{notification_title(notification_setting.level)}", data: { container: "body", toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), display: 'static' } }
+ %button.dropdown-new.btn.btn-default.has-tooltip.notifications-btn#notifications-button{ type: "button", title: "Notification setting", "aria-label" => "Notification setting: #{notification_title(notification_setting.level)}", data: { container: "body", toggle: "dropdown", target: notifications_menu_identifier("dropdown", notification_setting), flip: "false" } }
= icon("bell", class: "js-notification-loading")
= notification_title(notification_setting.level)
= icon("caret-down")
diff --git a/app/views/shared/projects/_list.html.haml b/app/views/shared/projects/_list.html.haml
index e1da05d8f08..06eb3d03e31 100644
--- a/app/views/shared/projects/_list.html.haml
+++ b/app/views/shared/projects/_list.html.haml
@@ -8,6 +8,7 @@
- user = local_assigns[:user]
- show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true
- remote = false unless local_assigns[:remote] == true
+- skip_pagination = false unless local_assigns[:skip_pagination] == true
.js-projects-list-holder
- if any_projects?(projects)
@@ -25,6 +26,6 @@
= icon('lock fw', base: 'circle', class: 'fa-lg private-fork-icon')
%strong= pluralize(@private_forks_count, 'private fork')
%span &nbsp;you have no access to.
- = paginate_collection(projects, remote: remote)
+ = paginate_collection(projects, remote: remote) unless skip_pagination
- else
.nothing-here-block No projects found
diff --git a/app/views/shared/projects/_search_form.html.haml b/app/views/shared/projects/_search_form.html.haml
index b89194bcc67..3b5c13ed93a 100644
--- a/app/views/shared/projects/_search_form.html.haml
+++ b/app/views/shared/projects/_search_form.html.haml
@@ -21,3 +21,5 @@
- if params[:visibility_level].present?
= hidden_field_tag :visibility_level, params[:visibility_level]
+
+ = render_if_exists 'shared/projects/search_fields'
diff --git a/app/views/shared/runners/show.html.haml b/app/views/shared/runners/show.html.haml
index 362569bfbaf..f62eed694d2 100644
--- a/app/views/shared/runners/show.html.haml
+++ b/app/views/shared/runners/show.html.haml
@@ -24,7 +24,7 @@
%td= @runner.active? ? 'Yes' : 'No'
%tr
%td Protected
- %td= @runner.active? ? _('Yes') : _('No')
+ %td= @runner.ref_protected? ? 'Yes' : 'No'
%tr
%td Can run untagged jobs
%td= @runner.run_untagged? ? 'Yes' : 'No'
diff --git a/app/views/shared/snippets/_form.html.haml b/app/views/shared/snippets/_form.html.haml
index 1b66d3acd40..cf9c3055499 100644
--- a/app/views/shared/snippets/_form.html.haml
+++ b/app/views/shared/snippets/_form.html.haml
@@ -14,7 +14,7 @@
= render 'shared/form_elements/description', model: @snippet, project: @project, form: f
- = render 'shared/visibility_level', f: f, visibility_level: @snippet.visibility_level, can_change_visibility_level: true, form_model: @snippet
+ = render 'shared/old_visibility_level', f: f, visibility_level: @snippet.visibility_level, can_change_visibility_level: true, form_model: @snippet, with_label: false
.file-editor
.form-group.row
diff --git a/app/views/sherlock/queries/_general.html.haml b/app/views/sherlock/queries/_general.html.haml
index ddc089b0bd7..52c7bc47ca7 100644
--- a/app/views/sherlock/queries/_general.html.haml
+++ b/app/views/sherlock/queries/_general.html.haml
@@ -36,7 +36,7 @@
%li
.code.js-syntax-highlight.sherlock-code
:preserve
- #{highlight("#{@query.id}.sql", @query.formatted_query)}
+ #{highlight("#{@query.id}.sql", @query.formatted_query, language: 'sql')}
.card
.card-header
diff --git a/app/views/sherlock/transactions/_queries.html.haml b/app/views/sherlock/transactions/_queries.html.haml
index c1ec4b91bb6..5e224f3aa0e 100644
--- a/app/views/sherlock/transactions/_queries.html.haml
+++ b/app/views/sherlock/transactions/_queries.html.haml
@@ -17,7 +17,7 @@
= t('sherlock.milliseconds')
%td
.code.js-syntax-highlight.sherlock-code
- = highlight("#{query.id}.sql", query.formatted_query)
+ = highlight("#{query.id}.sql", query.formatted_query, language: 'sql')
%td
= link_to(t('sherlock.view'),
sherlock_transaction_query_path(@transaction, query),
diff --git a/app/views/snippets/_actions.html.haml b/app/views/snippets/_actions.html.haml
index 0ce13ee7a53..ef8664e6f47 100644
--- a/app/views/snippets/_actions.html.haml
+++ b/app/views/snippets/_actions.html.haml
@@ -3,31 +3,31 @@
.d-none.d-sm-block
- if can?(current_user, :update_personal_snippet, @snippet)
= link_to edit_snippet_path(@snippet), class: "btn btn-grouped" do
- Edit
+ = _("Edit")
- if can?(current_user, :admin_personal_snippet, @snippet)
- = link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-grouped btn-inverted btn-remove", title: 'Delete Snippet' do
- Delete
- = link_to new_snippet_path, class: "btn btn-grouped btn-inverted btn-success", title: "New snippet" do
- New snippet
+ = link_to snippet_path(@snippet), method: :delete, data: { confirm: _("Are you sure?") }, class: "btn btn-grouped btn-inverted btn-remove", title: _('Delete Snippet') do
+ = _("Delete")
+ = link_to new_snippet_path, class: "btn btn-grouped btn-inverted btn-create", title: _("New snippet") do
+ = _("New snippet")
- if @snippet.submittable_as_spam_by?(current_user)
- = link_to 'Submit as spam', mark_as_spam_snippet_path(@snippet), method: :post, class: 'btn btn-grouped btn-spam', title: 'Submit as spam'
+ = link_to _('Submit as spam'), mark_as_spam_snippet_path(@snippet), method: :post, class: 'btn btn-grouped btn-spam', title: _('Submit as spam')
.d-block.d-sm-none.dropdown
%button.btn.btn-default.btn-block.append-bottom-0.prepend-top-5{ data: { toggle: "dropdown" } }
- Options
+ = _("Options")
= icon('caret-down')
.dropdown-menu.dropdown-menu-full-width
%ul
%li
- = link_to new_snippet_path, title: "New snippet" do
- New snippet
+ = link_to new_snippet_path, title: _("New snippet") do
+ = _("New snippet")
- if can?(current_user, :admin_personal_snippet, @snippet)
%li
- = link_to snippet_path(@snippet), method: :delete, data: { confirm: "Are you sure?" }, title: 'Delete Snippet' do
- Delete
+ = link_to snippet_path(@snippet), method: :delete, data: { confirm: _("Are you sure?") }, title: _('Delete Snippet') do
+ = _("Delete")
- if can?(current_user, :update_personal_snippet, @snippet)
%li
= link_to edit_snippet_path(@snippet) do
- Edit
+ = _("Edit")
- if @snippet.submittable_as_spam_by?(current_user)
%li
- = link_to 'Submit as spam', mark_as_spam_snippet_path(@snippet), method: :post
+ = link_to _('Submit as spam'), mark_as_spam_snippet_path(@snippet), method: :post
diff --git a/app/views/snippets/_snippets.html.haml b/app/views/snippets/_snippets.html.haml
index dfea8b40bd8..69d41f8fe5e 100644
--- a/app/views/snippets/_snippets.html.haml
+++ b/app/views/snippets/_snippets.html.haml
@@ -5,6 +5,6 @@
= render partial: 'shared/snippets/snippet', collection: @snippets, locals: { link_project: link_project }
- if @snippets.empty?
%li
- .nothing-here-block Nothing here.
+ .nothing-here-block= _("Nothing here.")
= paginate @snippets, theme: 'gitlab'
diff --git a/app/views/snippets/_snippets_scope_menu.html.haml b/app/views/snippets/_snippets_scope_menu.html.haml
index dc4b0fd9ba0..c312226dd6c 100644
--- a/app/views/snippets/_snippets_scope_menu.html.haml
+++ b/app/views/snippets/_snippets_scope_menu.html.haml
@@ -4,7 +4,7 @@
.nav-links.snippet-scope-menu.mobile-separator.nav.nav-tabs
%li{ class: active_when(params[:scope].nil?) }
= link_to subject_snippets_path(subject) do
- All
+ = _("All")
%span.badge.badge-pill
- if include_private
= subject.snippets.count
@@ -14,18 +14,18 @@
- if include_private
%li{ class: active_when(params[:scope] == "are_private") }
= link_to subject_snippets_path(subject, scope: 'are_private') do
- Private
+ = _("Private")
%span.badge.badge-pill
= subject.snippets.are_private.count
%li{ class: active_when(params[:scope] == "are_internal") }
= link_to subject_snippets_path(subject, scope: 'are_internal') do
- Internal
+ = _("Internal")
%span.badge.badge-pill
= subject.snippets.are_internal.count
%li{ class: active_when(params[:scope] == "are_public") }
= link_to subject_snippets_path(subject, scope: 'are_public') do
- Public
+ = _("Public")
%span.badge.badge-pill
= subject.snippets.are_public.count
diff --git a/app/views/snippets/edit.html.haml b/app/views/snippets/edit.html.haml
index 18ebeb78f87..ebc6c0a2605 100644
--- a/app/views/snippets/edit.html.haml
+++ b/app/views/snippets/edit.html.haml
@@ -1,5 +1,6 @@
-- page_title "Edit", "#{@snippet.title} (#{@snippet.to_reference})", "Snippets"
+- page_title _("Edit"), "#{@snippet.title} (#{@snippet.to_reference})", _("Snippets")
+
%h3.page-title
- Edit Snippet
+ = _("Edit Snippet")
%hr
= render 'shared/snippets/form', url: snippet_path(@snippet)
diff --git a/app/views/snippets/index.html.haml b/app/views/snippets/index.html.haml
index 9b4a7dbe68d..4f418e2381f 100644
--- a/app/views/snippets/index.html.haml
+++ b/app/views/snippets/index.html.haml
@@ -1,13 +1,13 @@
-- page_title "By #{@user.name}", "Snippets"
+- page_title _("By %{user_name}") % { user_name: @user.name }, _("Snippets")
%ol.breadcrumb
%li.breadcrumb-item
= link_to snippets_path do
- Snippets
+ = _("Snippets")
%li.breadcrumb-item
= @user.name
.float-right.d-none.d-sm-block
= link_to user_path(@user) do
- #{@user.name} profile page
+ = _("%{user_name} profile page") % { user_name: @user.name }
= render 'snippets'
diff --git a/app/views/snippets/new.html.haml b/app/views/snippets/new.html.haml
index f01915107e3..114c777bdc2 100644
--- a/app/views/snippets/new.html.haml
+++ b/app/views/snippets/new.html.haml
@@ -1,7 +1,9 @@
- @hide_top_links = true
-- breadcrumb_title "Snippets"
-- page_title "New Snippet"
-%h3.page-title
- New Snippet
-%hr
-= render "shared/snippets/form", url: snippets_path(@snippet)
+- @hide_breadcrumbs = true
+- page_title _("New Snippet")
+
+.page-title-holder
+ %h1.page-title= _('New Snippet')
+
+.prepend-top-default
+ = render "shared/snippets/form", url: snippets_path(@snippet)
diff --git a/app/views/snippets/notes/_actions.html.haml b/app/views/snippets/notes/_actions.html.haml
index 220ba2b49e6..01b95145937 100644
--- a/app/views/snippets/notes/_actions.html.haml
+++ b/app/views/snippets/notes/_actions.html.haml
@@ -1,7 +1,7 @@
- if current_user
- if note.emoji_awardable?
.note-actions-item
- = link_to '#', title: 'Add reaction', class: "note-action-button note-emoji-button js-add-award js-note-emoji has-tooltip", data: { position: 'right' } do
+ = link_to '#', title: _('Add reaction'), class: "note-action-button note-emoji-button js-add-award js-note-emoji has-tooltip", data: { position: 'right' } do
= icon('spinner spin')
%span{ class: 'link-highlight award-control-icon-neutral' }= custom_icon('emoji_slightly_smiling_face')
%span{ class: 'link-highlight award-control-icon-positive' }= custom_icon('emoji_smiley')
@@ -9,7 +9,7 @@
- if note_editable
.note-actions-item
- = button_tag title: 'Edit comment', class: 'note-action-button js-note-edit has-tooltip btn btn-transparent', data: { container: 'body' } do
+ = button_tag title: _('Edit comment'), class: 'note-action-button js-note-edit has-tooltip btn btn-transparent', data: { container: 'body' } do
%span.link-highlight
= custom_icon('icon_pencil')
diff --git a/app/views/snippets/show.html.haml b/app/views/snippets/show.html.haml
index 578327883e5..36b4e00e8d5 100644
--- a/app/views/snippets/show.html.haml
+++ b/app/views/snippets/show.html.haml
@@ -1,8 +1,8 @@
- @hide_top_links = true
- @content_class = "limit-container-width limited-inner-width-container" unless fluid_layout
-- add_to_breadcrumbs "Snippets", dashboard_snippets_path
+- add_to_breadcrumbs _("Snippets"), dashboard_snippets_path
- breadcrumb_title @snippet.to_reference
-- page_title "#{@snippet.title} (#{@snippet.to_reference})", "Snippets"
+- page_title "#{@snippet.title} (#{@snippet.to_reference})", _("Snippets")
= render 'shared/snippets/header'
diff --git a/app/views/u2f/_authenticate.html.haml b/app/views/u2f/_authenticate.html.haml
index 1c788b9a737..979f6862de3 100644
--- a/app/views/u2f/_authenticate.html.haml
+++ b/app/views/u2f/_authenticate.html.haml
@@ -1,18 +1,18 @@
#js-authenticate-u2f
-%a.btn.btn-block.btn-info#js-login-2fa-device{ href: '#' } Sign in via 2FA code
+%a.btn.btn-block.btn-info#js-login-2fa-device{ href: '#' }= _("Sign in via 2FA code")
-# haml-lint:disable InlineJavaScript
%script#js-authenticate-u2f-in-progress{ type: "text/template" }
- %p Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.
+ %p= _("Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.")
%script#js-authenticate-u2f-error{ type: "text/template" }
%div
- %p <%= error_message %> (error code: <%= error_code %>)
- %a.btn.btn-block.btn-warning#js-u2f-try-again Try again?
+ %p <%= error_message %> (#{_("error code:")} <%= error_code %>)
+ %a.btn.btn-block.btn-warning#js-u2f-try-again= _("Try again?")
%script#js-authenticate-u2f-authenticated{ type: "text/template" }
%div
- %p We heard back from your U2F device. You have been authenticated.
+ %p= _("We heard back from your U2F device. You have been authenticated.")
= form_tag(new_user_session_path, method: :post, id: 'js-login-u2f-form') do |f|
- resource_params = params[resource_name].presence || params
= hidden_field_tag 'user[remember_me]', resource_params.fetch(:remember_me, 0)
diff --git a/app/views/u2f/_register.html.haml b/app/views/u2f/_register.html.haml
index 39d4d82a77d..f6724f72307 100644
--- a/app/views/u2f/_register.html.haml
+++ b/app/views/u2f/_register.html.haml
@@ -2,39 +2,39 @@
-# haml-lint:disable InlineJavaScript
%script#js-register-u2f-not-supported{ type: "text/template" }
- %p Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer).
+ %p= _("Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer).")
%script#js-register-u2f-setup{ type: "text/template" }
- if current_user.two_factor_otp_enabled?
.row.append-bottom-10
.col-md-4
- %button#js-setup-u2f-device.btn.btn-info.btn-block Set up new U2F device
+ %button#js-setup-u2f-device.btn.btn-info.btn-block= _("Set up new U2F device")
.col-md-8
- %p Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left.
+ %p= _("Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left.")
- else
.row.append-bottom-10
.col-md-4
- %button#js-setup-u2f-device.btn.btn-info.btn-block{ disabled: true } Set up new U2F device
+ %button#js-setup-u2f-device.btn.btn-info.btn-block{ disabled: true }= _("Set up new U2F device")
.col-md-8
- %p.text-warning You need to register a two-factor authentication app before you can set up a U2F device.
+ %p.text-warning= _("You need to register a two-factor authentication app before you can set up a U2F device.")
%script#js-register-u2f-in-progress{ type: "text/template" }
- %p Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.
+ %p= _("Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.")
%script#js-register-u2f-error{ type: "text/template" }
%div
%p
- %span <%= error_message %> (error code: <%= error_code %>)
- %a.btn.btn-warning#js-u2f-try-again Try again?
+ %span <%= error_message %> (#{_("error code:")} <%= error_code %>)
+ %a.btn.btn-warning#js-u2f-try-again= _("Try again?")
%script#js-register-u2f-registered{ type: "text/template" }
.row.append-bottom-10
.col-md-12
- %p Your device was successfully set up! Give it a name and register it with the GitLab server.
+ %p= _("Your device was successfully set up! Give it a name and register it with the GitLab server.")
= form_tag(create_u2f_profile_two_factor_auth_path, method: :post) do
.row.append-bottom-10
.col-md-3
- = text_field_tag 'u2f_registration[name]', nil, class: 'form-control', placeholder: "Pick a name"
+ = text_field_tag 'u2f_registration[name]', nil, class: 'form-control', placeholder: _("Pick a name")
.col-md-3
= hidden_field_tag 'u2f_registration[device_response]', nil, class: 'form-control', required: true, id: "js-device-response"
- = submit_tag "Register U2F device", class: "btn btn-success"
+ = submit_tag _("Register U2F device"), class: "btn btn-success"
diff --git a/app/views/users/_overview.html.haml b/app/views/users/_overview.html.haml
new file mode 100644
index 00000000000..b5bc1180290
--- /dev/null
+++ b/app/views/users/_overview.html.haml
@@ -0,0 +1,30 @@
+.row
+ .col-12
+ .calendar-block.prepend-top-default.append-bottom-default
+ .user-calendar.d-none.d-sm-block{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } }
+ %h4.center.light
+ = spinner nil, true
+ .user-calendar-activities.d-none.d-sm-block
+.row
+ .col-md-12.col-lg-6
+ - if can?(current_user, :read_cross_project)
+ .activities-block
+ .prepend-top-16
+ .d-flex.align-items-center.border-bottom
+ %h4.flex-grow
+ = s_('UserProfile|Activity')
+ = link_to s_('UserProfile|View all'), user_activity_path, class: "hide js-view-all"
+ .overview-content-list{ data: { href: user_path } }
+ .center.light.loading
+ = spinner nil, true
+
+ .col-md-12.col-lg-6
+ .projects-block
+ .prepend-top-16
+ .d-flex.align-items-center.border-bottom
+ %h4.flex-grow
+ = s_('UserProfile|Personal projects')
+ = link_to s_('UserProfile|View all'), user_projects_path, class: "hide js-view-all"
+ .overview-content-list{ data: { href: user_projects_path } }
+ .center.light.loading
+ = spinner nil, true
diff --git a/app/views/users/calendar_activities.html.haml b/app/views/users/calendar_activities.html.haml
index 938cb579e9f..01acbf8eadd 100644
--- a/app/views/users/calendar_activities.html.haml
+++ b/app/views/users/calendar_activities.html.haml
@@ -7,7 +7,7 @@
%li
%span.light
%i.fa.fa-clock-o
- = event.created_at.strftime('%-I:%M%P')
+ = event.created_at.to_time.in_time_zone.strftime('%-I:%M%P')
- if event.visible_to_user?(current_user)
- if event.push?
#{event.action_name} #{event.ref_type}
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 7a38d290915..d11476738e4 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -12,22 +12,22 @@
.cover-block.user-cover-block.top-area
.cover-controls
- if @user == current_user
- = link_to profile_path, class: 'btn btn-default has-tooltip', title: 'Edit profile', 'aria-label': 'Edit profile' do
+ = link_to profile_path, class: 'btn btn-default has-tooltip', title: s_('UserProfile|Edit profile'), 'aria-label': 'Edit profile' do
= icon('pencil')
- elsif current_user
- if @user.abuse_report
- %button.btn.btn-danger{ title: 'Already reported for abuse',
+ %button.btn.btn-danger{ title: s_('UserProfile|Already reported for abuse'),
data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } }
= icon('exclamation-circle')
- else
= link_to new_abuse_report_path(user_id: @user.id, ref_url: request.referrer), class: 'btn',
- title: 'Report abuse', data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
+ title: s_('UserProfile|Report abuse'), data: { toggle: 'tooltip', placement: 'bottom', container: 'body' } do
= icon('exclamation-circle')
- if can?(current_user, :read_user_profile, @user)
- = link_to user_path(@user, rss_url_options), class: 'btn btn-default has-tooltip', title: 'Subscribe', 'aria-label': 'Subscribe' do
+ = link_to user_path(@user, rss_url_options), class: 'btn btn-default has-tooltip', title: s_('UserProfile|Subscribe'), 'aria-label': 'Subscribe' do
= icon('rss')
- if current_user && current_user.admin?
- = link_to [:admin, @user], class: 'btn btn-default', title: 'View user in admin area',
+ = link_to [:admin, @user], class: 'btn btn-default', title: s_('UserProfile|View user in admin area'),
data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('users')
@@ -51,7 +51,7 @@
@#{@user.username}
- if can?(current_user, :read_user_profile, @user)
%span.middle-dot-divider
- Member since #{@user.created_at.to_date.to_s(:long)}
+ = s_('Member since %{date}') % { date: @user.created_at.to_date.to_s(:long) }
.cover-desc
- unless @user.public_email.blank?
@@ -91,40 +91,42 @@
.fade-left= icon('angle-left')
.fade-right= icon('angle-right')
%ul.nav-links.user-profile-nav.scrolling-tabs.nav.nav-tabs
+ - if profile_tab?(:overview)
+ %li.js-overview-tab
+ = link_to user_path, data: { target: 'div#js-overview', action: 'overview', toggle: 'tab' } do
+ = s_('UserProfile|Overview')
- if profile_tab?(:activity)
%li.js-activity-tab
- = link_to user_path, data: { target: 'div#activity', action: 'activity', toggle: 'tab' } do
- Activity
+ = link_to user_activity_path, data: { target: 'div#activity', action: 'activity', toggle: 'tab' } do
+ = s_('UserProfile|Activity')
- if profile_tab?(:groups)
%li.js-groups-tab
= link_to user_groups_path, data: { target: 'div#groups', action: 'groups', toggle: 'tab', endpoint: user_groups_path(format: :json) } do
- Groups
+ = s_('UserProfile|Groups')
- if profile_tab?(:contributed)
%li.js-contributed-tab
= link_to user_contributed_projects_path, data: { target: 'div#contributed', action: 'contributed', toggle: 'tab', endpoint: user_contributed_projects_path(format: :json) } do
- Contributed projects
+ = s_('UserProfile|Contributed projects')
- if profile_tab?(:projects)
%li.js-projects-tab
= link_to user_projects_path, data: { target: 'div#projects', action: 'projects', toggle: 'tab', endpoint: user_projects_path(format: :json) } do
- Personal projects
+ = s_('UserProfile|Personal projects')
- if profile_tab?(:snippets)
%li.js-snippets-tab
= link_to user_snippets_path, data: { target: 'div#snippets', action: 'snippets', toggle: 'tab', endpoint: user_snippets_path(format: :json) } do
- Snippets
+ = s_('UserProfile|Snippets')
%div{ class: container_class }
.tab-content
+ - if profile_tab?(:overview)
+ #js-overview.tab-pane
+ = render "users/overview"
+
- if profile_tab?(:activity)
#activity.tab-pane
- .row-content-block.calender-block.white.second-block.d-none.d-sm-block
- .user-calendar{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } }
- %h4.center.light
- %i.fa.fa-spinner.fa-spin
- .user-calendar-activities
-
- if can?(current_user, :read_cross_project)
%h4.prepend-top-20
- Most Recent Activity
+ = s_('UserProfile|Most Recent Activity')
.content_list{ data: { href: user_path } }
= spinner
@@ -155,4 +157,4 @@
.col-12.text-center
.text-content
%h4
- This user has a private profile
+ = s_('UserProfile|This user has a private profile')
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 1eeb972cee9..c0b410472eb 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -28,6 +28,7 @@
- gcp_cluster:cluster_wait_for_app_installation
- gcp_cluster:wait_for_cluster_creation
- gcp_cluster:cluster_wait_for_ingress_ip_address
+- gcp_cluster:cluster_platform_configure
- github_import_advance_stage
- github_importer:github_import_import_diff_note
@@ -70,6 +71,9 @@
- pipeline_processing:pipeline_update
- pipeline_processing:stage_update
- pipeline_processing:update_head_pipeline_for_merge_request
+- pipeline_processing:ci_build_schedule
+
+- deployment:deployments_success
- repository_check:repository_check_clear
- repository_check:repository_check_batch
@@ -77,9 +81,9 @@
- todos_destroyer:todos_destroyer_confidential_issue
- todos_destroyer:todos_destroyer_entity_leave
+- todos_destroyer:todos_destroyer_group_private
- todos_destroyer:todos_destroyer_project_private
- todos_destroyer:todos_destroyer_private_features
-- todos_destroyer:todos_destroyer_group_private
- default
- mailers # ActionMailer::DeliveryJob.queue_name
diff --git a/app/workers/archive_trace_worker.rb b/app/workers/archive_trace_worker.rb
index c1283e9b2fc..4a9becf0ca7 100644
--- a/app/workers/archive_trace_worker.rb
+++ b/app/workers/archive_trace_worker.rb
@@ -7,7 +7,7 @@ class ArchiveTraceWorker
# rubocop: disable CodeReuse/ActiveRecord
def perform(job_id)
Ci::Build.without_archived_trace.find_by(id: job_id).try do |job|
- job.trace.archive!
+ Ci::ArchiveTraceService.new.execute(job)
end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/workers/build_finished_worker.rb b/app/workers/build_finished_worker.rb
index 51cbbe8882e..61d866b1f02 100644
--- a/app/workers/build_finished_worker.rb
+++ b/app/workers/build_finished_worker.rb
@@ -13,7 +13,7 @@ class BuildFinishedWorker
BuildTraceSectionsWorker.new.perform(build.id)
BuildCoverageWorker.new.perform(build.id)
- # We execute that async as this are two indepentent operations that can be executed after TraceSections and Coverage
+ # We execute that async as this are two independent operations that can be executed after TraceSections and Coverage
BuildHooksWorker.perform_async(build.id)
ArchiveTraceWorker.perform_async(build.id)
end
diff --git a/app/workers/build_success_worker.rb b/app/workers/build_success_worker.rb
index c17608f7378..9a865fea621 100644
--- a/app/workers/build_success_worker.rb
+++ b/app/workers/build_success_worker.rb
@@ -10,13 +10,27 @@ class BuildSuccessWorker
def perform(build_id)
Ci::Build.find_by(id: build_id).try do |build|
create_deployment(build) if build.has_environment?
+ stop_environment(build) if build.stops_environment?
end
end
# rubocop: enable CodeReuse/ActiveRecord
private
+ ##
+ # Deprecated:
+ # As of 11.5, we started creating a deployment record when ci_builds record is created.
+ # Therefore we no longer need to create a deployment, after a build succeeded.
+ # We're leaving this code for the transition period, but we can remove this code in 11.6.
def create_deployment(build)
- CreateDeploymentService.new(build).execute
+ build.create_deployment.try do |deployment|
+ deployment.succeed
+ end
+ end
+
+ ##
+ # TODO: This should be processed in DeploymentSuccessWorker once we started storing `action` value in `deployments` records
+ def stop_environment(build)
+ build.persisted_environment.fire_state_event(:stop)
end
end
diff --git a/app/workers/ci/archive_traces_cron_worker.rb b/app/workers/ci/archive_traces_cron_worker.rb
index 7443aad1380..f65ff239866 100644
--- a/app/workers/ci/archive_traces_cron_worker.rb
+++ b/app/workers/ci/archive_traces_cron_worker.rb
@@ -11,21 +11,9 @@ module Ci
# This could happen when ArchiveTraceWorker sidekiq jobs were lost by receiving SIGKILL
# More details in https://gitlab.com/gitlab-org/gitlab-ce/issues/36791
Ci::Build.finished.with_live_trace.find_each(batch_size: 100) do |build|
- begin
- build.trace.archive!
- rescue ::Gitlab::Ci::Trace::AlreadyArchivedError
- rescue => e
- failed_archive_counter.increment
- Rails.logger.error "Failed to archive stale live trace. id: #{build.id} message: #{e.message}"
- end
+ Ci::ArchiveTraceService.new.execute(build)
end
end
# rubocop: enable CodeReuse/ActiveRecord
-
- private
-
- def failed_archive_counter
- @failed_archive_counter ||= Gitlab::Metrics.counter(:job_trace_archive_failed_total, "Counter of failed attempts of traces archiving")
- end
end
end
diff --git a/app/workers/ci/build_schedule_worker.rb b/app/workers/ci/build_schedule_worker.rb
new file mode 100644
index 00000000000..da219adffc6
--- /dev/null
+++ b/app/workers/ci/build_schedule_worker.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Ci
+ class BuildScheduleWorker
+ include ApplicationWorker
+ include PipelineQueue
+
+ queue_namespace :pipeline_processing
+
+ def perform(build_id)
+ ::Ci::Build.find_by_id(build_id).try do |build|
+ break unless build.scheduled?
+
+ Ci::RunScheduledBuildService
+ .new(build.project, build.user).execute(build)
+ end
+ end
+ end
+end
diff --git a/app/workers/cluster_platform_configure_worker.rb b/app/workers/cluster_platform_configure_worker.rb
new file mode 100644
index 00000000000..8f3689f0166
--- /dev/null
+++ b/app/workers/cluster_platform_configure_worker.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class ClusterPlatformConfigureWorker
+ include ApplicationWorker
+ include ClusterQueue
+
+ def perform(cluster_id)
+ Clusters::Cluster.find_by_id(cluster_id).try do |cluster|
+ next unless cluster.cluster_project
+
+ kubernetes_namespace = cluster.find_or_initialize_kubernetes_namespace(cluster.cluster_project)
+
+ Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService.new(
+ cluster: cluster,
+ kubernetes_namespace: kubernetes_namespace
+ ).execute
+ end
+
+ rescue ::Kubeclient::HttpError => err
+ Rails.logger.error "Failed to create/update Kubernetes namespace for cluster_id: #{cluster_id} with error: #{err.message}"
+ end
+end
diff --git a/app/workers/cluster_provision_worker.rb b/app/workers/cluster_provision_worker.rb
index 59de7903c1c..3d5894b73ec 100644
--- a/app/workers/cluster_provision_worker.rb
+++ b/app/workers/cluster_provision_worker.rb
@@ -9,6 +9,8 @@ class ClusterProvisionWorker
cluster.provider.try do |provider|
Clusters::Gcp::ProvisionService.new.execute(provider) if cluster.gcp?
end
+
+ ClusterPlatformConfigureWorker.perform_async(cluster.id) if cluster.user?
end
end
end
diff --git a/app/workers/concerns/gitlab/github_import/stage_methods.rb b/app/workers/concerns/gitlab/github_import/stage_methods.rb
index 59e6bc2c97d..e2dee315cde 100644
--- a/app/workers/concerns/gitlab/github_import/stage_methods.rb
+++ b/app/workers/concerns/gitlab/github_import/stage_methods.rb
@@ -24,7 +24,7 @@ module Gitlab
def find_project(id)
# If the project has been marked as failed we want to bail out
# automatically.
- Project.import_started.find_by(id: id)
+ Project.joins_import_state.where(import_state: { status: :started }).find_by(id: id)
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/concerns/project_import_options.rb b/app/workers/concerns/project_import_options.rb
index 22bdf441d6b..2baf768bfd1 100644
--- a/app/workers/concerns/project_import_options.rb
+++ b/app/workers/concerns/project_import_options.rb
@@ -18,7 +18,7 @@ module ProjectImportOptions
"import"
end
- project.mark_import_as_failed("Every #{action} attempt has failed: #{job['error_message']}. Please try again.")
+ project.import_state.mark_as_failed(_("Every %{action} attempt has failed: %{job_error_message}. Please try again.") % { action: action, job_error_message: job['error_message'] })
Sidekiq.logger.warn "Failed #{job['class']} with #{job['args']}: #{job['error_message']}"
end
end
diff --git a/app/workers/concerns/project_start_import.rb b/app/workers/concerns/project_start_import.rb
index 46a133db2a1..4462bc51a24 100644
--- a/app/workers/concerns/project_start_import.rb
+++ b/app/workers/concerns/project_start_import.rb
@@ -2,11 +2,11 @@
# Used in EE by mirroring
module ProjectStartImport
- def start(project)
- if project.import_started? && project.import_jid == self.jid
+ def start(import_state)
+ if import_state.started? && import_state.jid == self.jid
return true
end
- project.import_start
+ import_state.start
end
end
diff --git a/app/workers/deployments/success_worker.rb b/app/workers/deployments/success_worker.rb
new file mode 100644
index 00000000000..da517f3fb26
--- /dev/null
+++ b/app/workers/deployments/success_worker.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Deployments
+ class SuccessWorker
+ include ApplicationWorker
+
+ queue_namespace :deployment
+
+ def perform(deployment_id)
+ Deployment.find_by_id(deployment_id).try do |deployment|
+ break unless deployment.success?
+
+ UpdateDeploymentService.new(deployment).execute
+ end
+ end
+ end
+end
diff --git a/app/workers/email_receiver_worker.rb b/app/workers/email_receiver_worker.rb
index 12706613ac2..bf637f82df2 100644
--- a/app/workers/email_receiver_worker.rb
+++ b/app/workers/email_receiver_worker.rb
@@ -40,6 +40,8 @@ class EmailReceiverWorker
"You are not allowed to perform this action. If you believe this is in error, contact a staff member."
when Gitlab::Email::NoteableNotFoundError
"The thread you are replying to no longer exists, perhaps it was deleted? If you believe this is in error, contact a staff member."
+ when Gitlab::Email::InvalidAttachment
+ error.message
when Gitlab::Email::InvalidRecordError
can_retry = true
error.message
diff --git a/app/workers/expire_build_instance_artifacts_worker.rb b/app/workers/expire_build_instance_artifacts_worker.rb
index 4fcd1e5bd24..94426dcf921 100644
--- a/app/workers/expire_build_instance_artifacts_worker.rb
+++ b/app/workers/expire_build_instance_artifacts_worker.rb
@@ -13,7 +13,7 @@ class ExpireBuildInstanceArtifactsWorker
return unless build&.project && !build.project.pending_delete
Rails.logger.info "Removing artifacts for build #{build.id}..."
- build.erase_artifacts!
+ build.erase_erasable_artifacts!
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/gitlab/github_import/advance_stage_worker.rb b/app/workers/gitlab/github_import/advance_stage_worker.rb
index cd2ceb8dcdf..0b3437a8a33 100644
--- a/app/workers/gitlab/github_import/advance_stage_worker.rb
+++ b/app/workers/gitlab/github_import/advance_stage_worker.rb
@@ -14,7 +14,7 @@ module Gitlab
INTERVAL = 30.seconds.to_i
# The number of seconds to wait (while blocking the thread) before
- # continueing to the next waiter.
+ # continuing to the next waiter.
BLOCKING_WAIT_TIME = 5
# The known importer stages and their corresponding Sidekiq workers.
@@ -31,7 +31,7 @@ module Gitlab
# next_stage - The name of the next stage to start when all jobs have been
# completed.
def perform(project_id, waiters, next_stage)
- return unless (project = find_project(project_id))
+ return unless import_state = find_import_state(project_id)
new_waiters = wait_for_jobs(waiters)
@@ -41,7 +41,7 @@ module Gitlab
# the pressure on Redis. We _only_ do this once all jobs are done so
# we don't get stuck forever if one or more jobs failed to notify the
# JobWaiter.
- project.refresh_import_jid_expiration
+ import_state.refresh_jid_expiration
STAGES.fetch(next_stage.to_sym).perform_async(project_id)
else
@@ -64,11 +64,8 @@ module Gitlab
end
# rubocop: disable CodeReuse/ActiveRecord
- def find_project(id)
- # TODO: Only select the JID
- # This is due to the fact that the JID could be present in either the project record or
- # its associated import_state record
- Project.import_started.find_by(id: id)
+ def find_import_state(project_id)
+ ProjectImportState.select(:jid).with_status(:started).find_by(project_id: project_id)
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/gitlab/github_import/refresh_import_jid_worker.rb b/app/workers/gitlab/github_import/refresh_import_jid_worker.rb
index 65473026b4c..76723e4a61f 100644
--- a/app/workers/gitlab/github_import/refresh_import_jid_worker.rb
+++ b/app/workers/gitlab/github_import/refresh_import_jid_worker.rb
@@ -16,12 +16,13 @@ module Gitlab
# project_id - The ID of the project that is being imported.
# check_job_id - The ID of the job for which to check the status.
def perform(project_id, check_job_id)
- return unless (project = find_project(project_id))
+ import_state = find_import_state(project_id)
+ return unless import_state
if SidekiqStatus.running?(check_job_id)
# As long as the repository is being cloned we want to keep refreshing
# the import JID status.
- project.refresh_import_jid_expiration
+ import_state.refresh_jid_expiration
self.class.perform_in_the_future(project_id, check_job_id)
end
@@ -31,11 +32,10 @@ module Gitlab
end
# rubocop: disable CodeReuse/ActiveRecord
- def find_project(id)
- # TODO: Only select the JID
- # This is due to the fact that the JID could be present in either the project record or
- # its associated import_state record
- Project.import_started.find_by(id: id)
+ def find_import_state(project_id)
+ ProjectImportState.select(:jid)
+ .with_status(:started)
+ .find_by(project_id: project_id)
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/workers/gitlab/github_import/stage/import_base_data_worker.rb b/app/workers/gitlab/github_import/stage/import_base_data_worker.rb
index 5726fbb573d..ccfed2ae187 100644
--- a/app/workers/gitlab/github_import/stage/import_base_data_worker.rb
+++ b/app/workers/gitlab/github_import/stage/import_base_data_worker.rb
@@ -23,7 +23,7 @@ module Gitlab
klass.new(project, client).execute
end
- project.refresh_import_jid_expiration
+ project.import_state.refresh_jid_expiration
ImportPullRequestsWorker.perform_async(project.id)
end
diff --git a/app/workers/gitlab/github_import/stage/import_pull_requests_worker.rb b/app/workers/gitlab/github_import/stage/import_pull_requests_worker.rb
index 1c5a7139802..37a7a7f4ba0 100644
--- a/app/workers/gitlab/github_import/stage/import_pull_requests_worker.rb
+++ b/app/workers/gitlab/github_import/stage/import_pull_requests_worker.rb
@@ -15,7 +15,7 @@ module Gitlab
.new(project, client)
.execute
- project.refresh_import_jid_expiration
+ project.import_state.refresh_jid_expiration
AdvanceStageWorker.perform_async(
project.id,
diff --git a/app/workers/namespaceless_project_destroy_worker.rb b/app/workers/namespaceless_project_destroy_worker.rb
index d9df42c9e17..2965f3b1150 100644
--- a/app/workers/namespaceless_project_destroy_worker.rb
+++ b/app/workers/namespaceless_project_destroy_worker.rb
@@ -32,7 +32,5 @@ class NamespacelessProjectDestroyWorker
merge_requests = project.forked_from_project.merge_requests.opened.from_project(project)
merge_requests.update_all(state: 'closed')
-
- project.forked_project_link.destroy
end
end
diff --git a/app/workers/pipeline_schedule_worker.rb b/app/workers/pipeline_schedule_worker.rb
index 85d1ffe0fa9..ac4e9710f33 100644
--- a/app/workers/pipeline_schedule_worker.rb
+++ b/app/workers/pipeline_schedule_worker.rb
@@ -9,18 +9,36 @@ class PipelineScheduleWorker
Ci::PipelineSchedule.active.where("next_run_at < ?", Time.now)
.preload(:owner, :project).find_each do |schedule|
begin
- pipeline = Ci::CreatePipelineService.new(schedule.project,
- schedule.owner,
- ref: schedule.ref)
- .execute(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: schedule)
-
- schedule.deactivate! unless pipeline.persisted?
+ Ci::CreatePipelineService.new(schedule.project,
+ schedule.owner,
+ ref: schedule.ref)
+ .execute!(:schedule, ignore_skip_ci: true, save_on_errors: true, schedule: schedule)
rescue => e
- Rails.logger.error "#{schedule.id}: Failed to create a scheduled pipeline: #{e.message}"
+ error(schedule, e)
ensure
schedule.schedule_next_run!
end
end
end
# rubocop: enable CodeReuse/ActiveRecord
+
+ private
+
+ def error(schedule, error)
+ failed_creation_counter.increment
+
+ Rails.logger.error "Failed to create a scheduled pipeline. " \
+ "schedule_id: #{schedule.id} message: #{error.message}"
+
+ Gitlab::Sentry
+ .track_exception(error,
+ issue_url: 'https://gitlab.com/gitlab-org/gitlab-ce/issues/41231',
+ extra: { schedule_id: schedule.id })
+ end
+
+ def failed_creation_counter
+ @failed_creation_counter ||=
+ Gitlab::Metrics.counter(:pipeline_schedule_creation_failed_total,
+ "Counter of failed attempts of pipeline schedule creation")
+ end
end
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index 09a594cdb4e..72a1733a2a8 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -29,15 +29,14 @@ class PostReceive
def process_project_changes(post_received)
changes = []
refs = Set.new
+ @user = post_received.identify
- post_received.changes_refs do |oldrev, newrev, ref|
- @user ||= post_received.identify(newrev)
-
- unless @user
- log("Triggered hook for non-existing user \"#{post_received.identifier}\"")
- return false # rubocop:disable Cop/AvoidReturnFromBlocks
- end
+ unless @user
+ log("Triggered hook for non-existing user \"#{post_received.identifier}\"")
+ return false
+ end
+ post_received.changes_refs do |oldrev, newrev, ref|
if Gitlab::Git.tag_ref?(ref)
GitTagPushService.new(post_received.project, @user, oldrev: oldrev, newrev: newrev, ref: ref).execute
elsif Gitlab::Git.branch_ref?(ref)
diff --git a/app/workers/process_commit_worker.rb b/app/workers/process_commit_worker.rb
index 7b167c95c29..29a7f8e691a 100644
--- a/app/workers/process_commit_worker.rb
+++ b/app/workers/process_commit_worker.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-# Worker for processing individiual commit messages pushed to a repository.
+# Worker for processing individual commit messages pushed to a repository.
#
# Jobs for this worker are scheduled for every commit that is being pushed. As a
# result of this the workload of this worker should be kept to a bare minimum.
diff --git a/app/workers/prune_old_events_worker.rb b/app/workers/prune_old_events_worker.rb
index d44ad0d8030..dc4b7670131 100644
--- a/app/workers/prune_old_events_worker.rb
+++ b/app/workers/prune_old_events_worker.rb
@@ -6,14 +6,13 @@ class PruneOldEventsWorker
# rubocop: disable CodeReuse/ActiveRecord
def perform
- # Contribution calendar shows maximum 12 months of events.
- # Double nested query is used because MySQL doesn't allow DELETE subqueries
- # on the same table.
+ # Contribution calendar shows maximum 12 months of events, we retain 2 years for data integrity.
+ # Double nested query is used because MySQL doesn't allow DELETE subqueries on the same table.
Event.unscoped.where(
'(id IN (SELECT id FROM (?) ids_to_remove))',
Event.unscoped.where(
'created_at < ?',
- (12.months + 1.day).ago)
+ (2.years + 1.day).ago)
.select(:id)
.limit(10_000))
.delete_all
diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb
index 68ec66e8499..7eae07d3f6b 100644
--- a/app/workers/repository_fork_worker.rb
+++ b/app/workers/repository_fork_worker.rb
@@ -12,7 +12,7 @@ class RepositoryForkWorker
source_project = target_project.forked_from_project
unless source_project
- return target_project.mark_import_as_failed('Source project cannot be found.')
+ return target_project.import_state.mark_as_failed(_('Source project cannot be found.'))
end
fork_repository(target_project, source_project.repository_storage, source_project.disk_path)
@@ -33,7 +33,7 @@ class RepositoryForkWorker
end
def start_fork(project)
- return true if start(project)
+ return true if start(project.import_state)
Rails.logger.info("Project #{project.full_path} was in inconsistent state (#{project.import_status}) while forking.")
false
diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb
index 82189a3c9f5..59691f48a39 100644
--- a/app/workers/repository_import_worker.rb
+++ b/app/workers/repository_import_worker.rb
@@ -34,14 +34,14 @@ class RepositoryImportWorker
attr_reader :project
def start_import
- return true if start(project)
+ return true if start(project.import_state)
Rails.logger.info("Project #{project.full_path} was in inconsistent state (#{project.import_status}) while importing.")
false
end
def fail_import(message)
- project.mark_import_as_failed(message)
+ project.import_state.mark_as_failed(message)
end
def template_import?
diff --git a/app/workers/stuck_ci_jobs_worker.rb b/app/workers/stuck_ci_jobs_worker.rb
index f6bca1176d1..25809f68080 100644
--- a/app/workers/stuck_ci_jobs_worker.rb
+++ b/app/workers/stuck_ci_jobs_worker.rb
@@ -8,6 +8,7 @@ class StuckCiJobsWorker
BUILD_RUNNING_OUTDATED_TIMEOUT = 1.hour
BUILD_PENDING_OUTDATED_TIMEOUT = 1.day
+ BUILD_SCHEDULED_OUTDATED_TIMEOUT = 1.hour
BUILD_PENDING_STUCK_TIMEOUT = 1.hour
def perform
@@ -15,9 +16,10 @@ class StuckCiJobsWorker
Rails.logger.info "#{self.class}: Cleaning stuck builds"
- drop :running, BUILD_RUNNING_OUTDATED_TIMEOUT
- drop :pending, BUILD_PENDING_OUTDATED_TIMEOUT
- drop_stuck :pending, BUILD_PENDING_STUCK_TIMEOUT
+ drop :running, BUILD_RUNNING_OUTDATED_TIMEOUT, 'ci_builds.updated_at < ?', :stuck_or_timeout_failure
+ drop :pending, BUILD_PENDING_OUTDATED_TIMEOUT, 'ci_builds.updated_at < ?', :stuck_or_timeout_failure
+ drop :scheduled, BUILD_SCHEDULED_OUTDATED_TIMEOUT, 'scheduled_at IS NOT NULL AND scheduled_at < ?', :stale_schedule
+ drop_stuck :pending, BUILD_PENDING_STUCK_TIMEOUT, 'ci_builds.updated_at < ?', :stuck_or_timeout_failure
remove_lease
end
@@ -32,25 +34,25 @@ class StuckCiJobsWorker
Gitlab::ExclusiveLease.cancel(EXCLUSIVE_LEASE_KEY, @uuid)
end
- def drop(status, timeout)
- search(status, timeout) do |build|
- drop_build :outdated, build, status, timeout
+ def drop(status, timeout, condition, reason)
+ search(status, timeout, condition) do |build|
+ drop_build :outdated, build, status, timeout, reason
end
end
- def drop_stuck(status, timeout)
- search(status, timeout) do |build|
+ def drop_stuck(status, timeout, condition, reason)
+ search(status, timeout, condition) do |build|
break unless build.stuck?
- drop_build :stuck, build, status, timeout
+ drop_build :stuck, build, status, timeout, reason
end
end
# rubocop: disable CodeReuse/ActiveRecord
- def search(status, timeout)
+ def search(status, timeout, condition)
loop do
jobs = Ci::Build.where(status: status)
- .where('ci_builds.updated_at < ?', timeout.ago)
+ .where(condition, timeout.ago)
.includes(:tags, :runner, project: :namespace)
.limit(100)
.to_a
@@ -63,10 +65,10 @@ class StuckCiJobsWorker
end
# rubocop: enable CodeReuse/ActiveRecord
- def drop_build(type, build, status, timeout)
- Rails.logger.info "#{self.class}: Dropping #{type} build #{build.id} for runner #{build.runner_id} (status: #{status}, timeout: #{timeout})"
+ def drop_build(type, build, status, timeout, reason)
+ Rails.logger.info "#{self.class}: Dropping #{type} build #{build.id} for runner #{build.runner_id} (status: #{status}, timeout: #{timeout}, reason: #{reason})"
Gitlab::OptimisticLocking.retry_lock(build, 3) do |b|
- b.drop(:stuck_or_timeout_failure)
+ b.drop(reason)
end
end
end
diff --git a/app/workers/stuck_import_jobs_worker.rb b/app/workers/stuck_import_jobs_worker.rb
index de92f3eca6a..c8a186ba4ce 100644
--- a/app/workers/stuck_import_jobs_worker.rb
+++ b/app/workers/stuck_import_jobs_worker.rb
@@ -7,64 +7,62 @@ class StuckImportJobsWorker
IMPORT_JOBS_EXPIRATION = 15.hours.to_i
def perform
- projects_without_jid_count = mark_projects_without_jid_as_failed!
- projects_with_jid_count = mark_projects_with_jid_as_failed!
+ import_state_without_jid_count = mark_import_states_without_jid_as_failed!
+ import_state_with_jid_count = mark_import_states_with_jid_as_failed!
Gitlab::Metrics.add_event(:stuck_import_jobs,
- projects_without_jid_count: projects_without_jid_count,
- projects_with_jid_count: projects_with_jid_count)
+ projects_without_jid_count: import_state_without_jid_count,
+ projects_with_jid_count: import_state_with_jid_count)
end
private
- def mark_projects_without_jid_as_failed!
- enqueued_projects_without_jid.each do |project|
- project.mark_import_as_failed(error_message)
+ def mark_import_states_without_jid_as_failed!
+ enqueued_import_states_without_jid.each do |import_state|
+ import_state.mark_as_failed(error_message)
end.count
end
# rubocop: disable CodeReuse/ActiveRecord
- def mark_projects_with_jid_as_failed!
- # TODO: Rollback this change to use SQL through #pluck
- jids_and_ids = enqueued_projects_with_jid.map { |project| [project.import_jid, project.id] }.to_h
+ def mark_import_states_with_jid_as_failed!
+ jids_and_ids = enqueued_import_states_with_jid.pluck(:jid, :id).to_h
# Find the jobs that aren't currently running or that exceeded the threshold.
completed_jids = Gitlab::SidekiqStatus.completed_jids(jids_and_ids.keys)
return unless completed_jids.any?
- completed_project_ids = jids_and_ids.values_at(*completed_jids)
+ completed_import_state_ids = jids_and_ids.values_at(*completed_jids)
- # We select the projects again, because they may have transitioned from
+ # We select the import states again, because they may have transitioned from
# scheduled/started to finished/failed while we were looking up their Sidekiq status.
- completed_projects = enqueued_projects_with_jid.where(id: completed_project_ids)
+ completed_import_states = enqueued_import_states_with_jid.where(id: completed_import_state_ids)
- Rails.logger.info("Marked stuck import jobs as failed. JIDs: #{completed_projects.map(&:import_jid).join(', ')}")
+ completed_import_state_jids = completed_import_states.map { |import_state| import_state.jid }.join(', ')
+ Rails.logger.info("Marked stuck import jobs as failed. JIDs: #{completed_import_state_jids}")
- completed_projects.each do |project|
- project.mark_import_as_failed(error_message)
+ completed_import_states.each do |import_state|
+ import_state.mark_as_failed(error_message)
end.count
end
# rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
- def enqueued_projects
- Project.joins_import_state.where("(import_state.status = 'scheduled' OR import_state.status = 'started') OR (projects.import_status = 'scheduled' OR projects.import_status = 'started')")
+ def enqueued_import_states
+ ProjectImportState.with_status([:scheduled, :started])
end
- # rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
- def enqueued_projects_with_jid
- enqueued_projects.where.not("import_state.jid IS NULL AND projects.import_jid IS NULL")
+ def enqueued_import_states_with_jid
+ enqueued_import_states.where.not(jid: nil)
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
- def enqueued_projects_without_jid
- enqueued_projects.where("import_state.jid IS NULL AND projects.import_jid IS NULL")
+ def enqueued_import_states_without_jid
+ enqueued_import_states.where(jid: nil)
end
# rubocop: enable CodeReuse/ActiveRecord
def error_message
- "Import timed out. Import took longer than #{IMPORT_JOBS_EXPIRATION} seconds"
+ _("Import timed out. Import took longer than %{import_jobs_expiration} seconds") % { import_jobs_expiration: IMPORT_JOBS_EXPIRATION }
end
end
diff --git a/bin/profile-url b/bin/profile-url
index d8d09641624..9e8585aabba 100755
--- a/bin/profile-url
+++ b/bin/profile-url
@@ -48,7 +48,7 @@ require File.expand_path('../config/environment', File.dirname(__FILE__))
result = Gitlab::Profiler.profile(options[:url],
logger: Logger.new(options[:sql_output]),
post_data: options[:post_data],
- user: User.find_by_username(options[:username]),
+ user: UserFinder.new(options[:username]).find_by_username,
private_token: ENV['PRIVATE_TOKEN'])
printer = RubyProf::CallStackPrinter.new(result)
diff --git a/bin/rails b/bin/rails
index 228f812ccaf..d21b64b3007 100755
--- a/bin/rails
+++ b/bin/rails
@@ -1,7 +1,7 @@
#!/usr/bin/env ruby
# Remove this block when upgraded to rails 5.0.
-unless %w[1 true].include?(ENV["RAILS5"])
+if %w[0 false].include?(ENV["RAILS5"])
begin
load File.expand_path('../spring', __FILE__)
rescue LoadError => e
diff --git a/bin/rake b/bin/rake
index b52a8321f1a..1362d51e3d6 100755
--- a/bin/rake
+++ b/bin/rake
@@ -1,7 +1,7 @@
#!/usr/bin/env ruby
# Remove this block when upgraded to rails 5.0.
-unless %w[1 true].include?(ENV["RAILS5"])
+if %w[0 false].include?(ENV["RAILS5"])
begin
load File.expand_path('../spring', __FILE__)
rescue LoadError => e
diff --git a/bin/rspec b/bin/rspec
index 26583242051..b0770e30a70 100755
--- a/bin/rspec
+++ b/bin/rspec
@@ -2,7 +2,7 @@
# Remove these two lines below when upgraded to rails 5.0.
# Allow run `rspec` command as `RAILS5=1 rspec ...` instead of `BUNDLE_GEMFILE=Gemfile.rails5 rspec ...`
-gemfile = %w[1 true].include?(ENV["RAILS5"]) ? "Gemfile.rails5" : "Gemfile"
+gemfile = %w[0 false].include?(ENV["RAILS5"]) ? "Gemfile.rails4" : "Gemfile"
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../#{gemfile}", __dir__)
begin
diff --git a/bin/secpick b/bin/secpick
index 5e30c8e72c5..2b263d452c9 100755
--- a/bin/secpick
+++ b/bin/secpick
@@ -15,7 +15,7 @@ parser = OptionParser.new do |opts|
options[:version] = version&.tr('.', '-')
end
- opts.on('-b', '--branch security-fix-branch', 'Original branch name') do |branch|
+ opts.on('-b', '--branch security-fix-branch', 'Original branch name (optional, defaults to current)') do |branch|
options[:branch] = branch
end
@@ -32,15 +32,21 @@ end
parser.parse!
+options[:branch] ||= `git rev-parse --abbrev-ref HEAD`
+
abort("Missing options. Use #{$0} --help to see the list of options available".red) if options.values.include?(nil)
abort("Wrong version format #{options[:version].bold}".red) unless options[:version] =~ /\A\d*\-\d*\Z/
-branch = "#{options[:branch]}-#{options[:version]}"
+ee = File.exist?('./CHANGELOG-EE.md')
+original_branch = options[:branch].strip
+branch = "#{original_branch}-#{options[:version]}"
branch.prepend("#{BRANCH_PREFIX}-") unless branch.start_with?("#{BRANCH_PREFIX}-")
branch = branch.freeze
-stable_branch = "#{BRANCH_PREFIX}-#{options[:version]}".freeze
+stable_branch = "#{BRANCH_PREFIX}-#{options[:version]}".tap do |name|
+ name << "-ee" if ee
+end.freeze
-command = "git fetch #{REMOTE} #{stable_branch} && git checkout #{stable_branch} && git pull #{REMOTE} #{stable_branch} && git checkout -B #{branch} && git cherry-pick #{options[:sha]} && git push #{REMOTE} #{branch}"
+command = "git fetch #{REMOTE} #{stable_branch} && git checkout #{stable_branch} && git pull #{REMOTE} #{stable_branch} && git checkout -B #{branch} && git cherry-pick #{options[:sha]} && git push #{REMOTE} #{branch} && git checkout #{original_branch}"
_stdin, stdout, stderr = Open3.popen3(command)
diff --git a/bin/setup b/bin/setup
index ec1ebe02950..34bb667087a 100755
--- a/bin/setup
+++ b/bin/setup
@@ -1,7 +1,7 @@
#!/usr/bin/env ruby
def rails5?
- %w[1 true].include?(ENV["RAILS5"])
+ !%w[0 false].include?(ENV["RAILS5"])
end
require "pathname"
diff --git a/bin/storage_check b/bin/storage_check
deleted file mode 100755
index 5a818732bd1..00000000000
--- a/bin/storage_check
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env ruby
-
-require 'optparse'
-require 'net/http'
-require 'json'
-require 'socket'
-require 'logger'
-
-require_relative '../lib/gitlab/storage_check'
-
-Gitlab::StorageCheck::CLI.start!(ARGV)
diff --git a/bin/web b/bin/web
index ecd0bbd10b0..06ff7c39296 100755
--- a/bin/web
+++ b/bin/web
@@ -3,6 +3,11 @@
cd $(dirname $0)/..
app_root=$(pwd)
+# Switch to experimental PUMA configuration
+if [ -n "${EXPERIMENTAL_PUMA}" ]; then
+ exec bin/web_puma "$@"
+fi
+
unicorn_pidfile="$app_root/tmp/pids/unicorn.pid"
unicorn_config="$app_root/config/unicorn.rb"
unicorn_cmd="bundle exec unicorn_rails -c $unicorn_config -E $RAILS_ENV"
diff --git a/bin/web_puma b/bin/web_puma
new file mode 100755
index 00000000000..178fe84800d
--- /dev/null
+++ b/bin/web_puma
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+set -e
+
+cd $(dirname $0)/..
+app_root=$(pwd)
+
+puma_pidfile="$app_root/tmp/pids/puma.pid"
+puma_config="$app_root/config/puma.rb"
+
+spawn_puma()
+{
+ exec bundle exec puma --config "${puma_config}" "$@"
+}
+
+get_puma_pid()
+{
+ pid=$(cat "${puma_pidfile}")
+ if [ -z "$pid" ] ; then
+ echo "Could not find a PID in $puma_pidfile"
+ exit 1
+ fi
+ echo "${pid}"
+}
+
+start()
+{
+ spawn_puma -d
+}
+
+start_foreground()
+{
+ spawn_puma
+}
+
+stop()
+{
+ get_puma_pid
+ kill -QUIT "$(get_puma_pid)"
+}
+
+reload()
+{
+ kill -USR2 "$(get_puma_pid)"
+}
+
+case "$1" in
+ start)
+ start
+ ;;
+ start_foreground)
+ start_foreground
+ ;;
+ stop)
+ stop
+ ;;
+ reload)
+ reload
+ ;;
+ *)
+ echo "Usage: RAILS_ENV=your_env $0 {start|stop|reload}"
+ ;;
+esac
diff --git a/changelogs/archive.md b/changelogs/archive.md
index b57440f7dc6..dd7c21dabd6 100644
--- a/changelogs/archive.md
+++ b/changelogs/archive.md
@@ -2267,7 +2267,7 @@
- Disable spellcheck and autocorrect for username field in admin page
- Delete tags using Rugged for performance reasons (Robert Schilling)
- Add Slack notifications when Wiki is edited (Sebastian Klier)
- - Diffs load at the correct point when linking from from number
+ - Diffs load at the correct point when linking from number
- Selected diff rows highlight
- Fix emoji categories in the emoji picker
- API: Properly display annotated tags for GET /projects/:id/repository/tags (Robert Schilling)
diff --git a/changelogs/unreleased/1979-redesign-mr-widget-approvals-ce.yml b/changelogs/unreleased/1979-redesign-mr-widget-approvals-ce.yml
new file mode 100644
index 00000000000..d05b6054b22
--- /dev/null
+++ b/changelogs/unreleased/1979-redesign-mr-widget-approvals-ce.yml
@@ -0,0 +1,5 @@
+---
+title: Redesign of MR header sections (CE)
+merge_request: 23465
+author:
+type: changed
diff --git a/changelogs/unreleased/21307-send-deployment-information-in-job-api.yml b/changelogs/unreleased/21307-send-deployment-information-in-job-api.yml
deleted file mode 100644
index 8f9e24428be..00000000000
--- a/changelogs/unreleased/21307-send-deployment-information-in-job-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Send deployment information in job API
-merge_request: 21307
-author:
-type: other
diff --git a/changelogs/unreleased/21617-initialize-projects-with-readme.yml b/changelogs/unreleased/21617-initialize-projects-with-readme.yml
deleted file mode 100644
index 168f6af60c5..00000000000
--- a/changelogs/unreleased/21617-initialize-projects-with-readme.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adds a initialize_with_readme parameter to POST /projects
-merge_request: 21617
-author: Steve
-type: added
diff --git a/changelogs/unreleased/23986-choose-commit-email.yml b/changelogs/unreleased/23986-choose-commit-email.yml
deleted file mode 100644
index 1ebd62cd5b1..00000000000
--- a/changelogs/unreleased/23986-choose-commit-email.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allow user to choose the email used for commits made through GitLab's UI.
-merge_request: 21213
-author: Joshua Campbell
-type: added
diff --git a/changelogs/unreleased/28682-can-merge-branch-before-build-is-started.yml b/changelogs/unreleased/28682-can-merge-branch-before-build-is-started.yml
new file mode 100644
index 00000000000..5ffd93e098f
--- /dev/null
+++ b/changelogs/unreleased/28682-can-merge-branch-before-build-is-started.yml
@@ -0,0 +1,5 @@
+---
+title: Strictly require a pipeline to merge.
+merge_request: 22911
+author:
+type: changed
diff --git a/changelogs/unreleased/29398-support-rbac-for-gitlab-provisioned-clusters.yml b/changelogs/unreleased/29398-support-rbac-for-gitlab-provisioned-clusters.yml
deleted file mode 100644
index 973dcd0496a..00000000000
--- a/changelogs/unreleased/29398-support-rbac-for-gitlab-provisioned-clusters.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Support Kubernetes RBAC for GitLab Managed Apps when creating new clusters
-merge_request: 21401
-author:
-type: changed
diff --git a/changelogs/unreleased/31887-remove-images-from-todos.yml b/changelogs/unreleased/31887-remove-images-from-todos.yml
deleted file mode 100644
index 36388f66514..00000000000
--- a/changelogs/unreleased/31887-remove-images-from-todos.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Images are no longer displayed in Todo descriptions
-merge_request: 21704
-author:
-type: fixed
diff --git a/changelogs/unreleased/33705-merge-request-rebase-api.yml b/changelogs/unreleased/33705-merge-request-rebase-api.yml
new file mode 100644
index 00000000000..322fe31ce87
--- /dev/null
+++ b/changelogs/unreleased/33705-merge-request-rebase-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add a rebase API endpoint for merge requests
+merge_request: 23296
+author:
+type: added
diff --git a/changelogs/unreleased/34758-group-cluster-controller.yml b/changelogs/unreleased/34758-group-cluster-controller.yml
new file mode 100644
index 00000000000..88c4c872714
--- /dev/null
+++ b/changelogs/unreleased/34758-group-cluster-controller.yml
@@ -0,0 +1,5 @@
+---
+title: Add ability to create group level clusters and install gitlab managed applications
+merge_request: 22450
+author:
+type: added
diff --git a/changelogs/unreleased/38495-calendar-activities-in-timezone.yml b/changelogs/unreleased/38495-calendar-activities-in-timezone.yml
new file mode 100644
index 00000000000..778d637609c
--- /dev/null
+++ b/changelogs/unreleased/38495-calendar-activities-in-timezone.yml
@@ -0,0 +1,5 @@
+---
+title: Show user contributions in correct timezone within user profile
+merge_request: 23419
+author:
+type: changed
diff --git a/changelogs/unreleased/40085-add-a-create_merge_request-quick-action.yml b/changelogs/unreleased/40085-add-a-create_merge_request-quick-action.yml
new file mode 100644
index 00000000000..e1614ac7669
--- /dev/null
+++ b/changelogs/unreleased/40085-add-a-create_merge_request-quick-action.yml
@@ -0,0 +1,5 @@
+---
+title: Creates /create_merge_request quickaction
+merge_request: 22485
+author: Jacopo Beschi @jacopo-beschi
+type: added
diff --git a/changelogs/unreleased/40260-reduce-gitaly-calls-project-pipeline-status.yml b/changelogs/unreleased/40260-reduce-gitaly-calls-project-pipeline-status.yml
new file mode 100644
index 00000000000..8ab104e95f5
--- /dev/null
+++ b/changelogs/unreleased/40260-reduce-gitaly-calls-project-pipeline-status.yml
@@ -0,0 +1,5 @@
+---
+title: Reduce Gitaly calls in projects dashboard
+merge_request: 23307
+author:
+type: performance
diff --git a/changelogs/unreleased/40385-prohibit_impersonation.yml b/changelogs/unreleased/40385-prohibit_impersonation.yml
new file mode 100644
index 00000000000..dd061b17939
--- /dev/null
+++ b/changelogs/unreleased/40385-prohibit_impersonation.yml
@@ -0,0 +1,5 @@
+---
+title: Add config to prohibit impersonation
+merge_request: 23338
+author:
+type: added
diff --git a/changelogs/unreleased/41040-long-webhook-url-problem.yml b/changelogs/unreleased/41040-long-webhook-url-problem.yml
deleted file mode 100644
index 4057e1ff325..00000000000
--- a/changelogs/unreleased/41040-long-webhook-url-problem.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix long webhook URL overflow for custom integration.
-merge_request:
-author: Kukovskii Vladimir
-type: fixed
diff --git a/changelogs/unreleased/41875-allow-pipelines-to-be-deleted-by-project-owners.yml b/changelogs/unreleased/41875-allow-pipelines-to-be-deleted-by-project-owners.yml
new file mode 100644
index 00000000000..0662ff6f523
--- /dev/null
+++ b/changelogs/unreleased/41875-allow-pipelines-to-be-deleted-by-project-owners.yml
@@ -0,0 +1,5 @@
+---
+title: Allow deleting a Pipeline via the API.
+merge_request: 22988
+author:
+type: added
diff --git a/changelogs/unreleased/42861-move-include-external-files-in-gitlab-ci-yml-from-starter-to-libre.yml b/changelogs/unreleased/42861-move-include-external-files-in-gitlab-ci-yml-from-starter-to-libre.yml
deleted file mode 100644
index 171779817c8..00000000000
--- a/changelogs/unreleased/42861-move-include-external-files-in-gitlab-ci-yml-from-starter-to-libre.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Move including external files in .gitlab-ci.yml from Starter to Libre
-merge_request: 21603
-author:
-type: changed
diff --git a/changelogs/unreleased/44596-double-title-merge-request-message.yml b/changelogs/unreleased/44596-double-title-merge-request-message.yml
deleted file mode 100644
index 714d16977fb..00000000000
--- a/changelogs/unreleased/44596-double-title-merge-request-message.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix double title in merge request chat messages.
-merge_request: 21670
-author: Kukovskii Vladimir
-type: fixed
diff --git a/changelogs/unreleased/44768-lazy-load-xterm-css.yml b/changelogs/unreleased/44768-lazy-load-xterm-css.yml
deleted file mode 100644
index 85f7b1984e0..00000000000
--- a/changelogs/unreleased/44768-lazy-load-xterm-css.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Lazy load xterm custom colors css
-merge_request:
-author:
-type: performance
diff --git a/changelogs/unreleased/44998-split-admin-settings-into-multiple-sub-pages.yml b/changelogs/unreleased/44998-split-admin-settings-into-multiple-sub-pages.yml
deleted file mode 100644
index 4b398e9419d..00000000000
--- a/changelogs/unreleased/44998-split-admin-settings-into-multiple-sub-pages.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Split admin settings into multiple sub pages
-merge_request: 21467
-author:
-type: other
diff --git a/changelogs/unreleased/45754-issue-mr-and-archived-projects.yml b/changelogs/unreleased/45754-issue-mr-and-archived-projects.yml
deleted file mode 100644
index d81f47d9654..00000000000
--- a/changelogs/unreleased/45754-issue-mr-and-archived-projects.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Issue and MR count now ignores archived projects
-merge_request: 21721
-author:
-type: fixed
diff --git a/changelogs/unreleased/45754-open-issues-from-archived-project-listed-in-group-issue-board.yml b/changelogs/unreleased/45754-open-issues-from-archived-project-listed-in-group-issue-board.yml
deleted file mode 100644
index 34394396020..00000000000
--- a/changelogs/unreleased/45754-open-issues-from-archived-project-listed-in-group-issue-board.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: No longer show open issues from archived projects in group issue board
-merge_request: 21721
-author:
-type: fixed
diff --git a/changelogs/unreleased/46544-webide-ctrl-enter-commit-shortcut.yml b/changelogs/unreleased/46544-webide-ctrl-enter-commit-shortcut.yml
new file mode 100644
index 00000000000..334c9b3ec9e
--- /dev/null
+++ b/changelogs/unreleased/46544-webide-ctrl-enter-commit-shortcut.yml
@@ -0,0 +1,5 @@
+---
+title: "WebIDE: Pressing Ctrl-Enter while typing on the commit message now performs the commit action"
+merge_request: 23049
+author: Thomas Pathier
+type: added
diff --git a/changelogs/unreleased/46733-move-filter-dropdown-from-font-awesome-to-our-own-icons.yml b/changelogs/unreleased/46733-move-filter-dropdown-from-font-awesome-to-our-own-icons.yml
deleted file mode 100644
index 07549781330..00000000000
--- a/changelogs/unreleased/46733-move-filter-dropdown-from-font-awesome-to-our-own-icons.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Updated icons used in filtered search dropdowns
-merge_request: 21694
-author:
-type: changed
diff --git a/changelogs/unreleased/46950-systemcheck-ruby-version.yml b/changelogs/unreleased/46950-systemcheck-ruby-version.yml
new file mode 100644
index 00000000000..e556e14223b
--- /dev/null
+++ b/changelogs/unreleased/46950-systemcheck-ruby-version.yml
@@ -0,0 +1,5 @@
+---
+title: 'SystemCheck: Use a more reliable way to detect current Ruby version'
+merge_request: 23291
+author:
+type: changed
diff --git a/changelogs/unreleased/47398-user-is-unable-revoke-a-authorized-application-unless-user-oauth-applications-is-checked-in-admin-settings.yml b/changelogs/unreleased/47398-user-is-unable-revoke-a-authorized-application-unless-user-oauth-applications-is-checked-in-admin-settings.yml
deleted file mode 100644
index e0dc26301d4..00000000000
--- a/changelogs/unreleased/47398-user-is-unable-revoke-a-authorized-application-unless-user-oauth-applications-is-checked-in-admin-settings.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Allow user to revoke an authorized application even if User OAuth applications
- setting is disabled in admin settings
-merge_request: 21835
-author:
-type: changed
diff --git a/changelogs/unreleased/48475-gitlab-pages-settings-regressions.yml b/changelogs/unreleased/48475-gitlab-pages-settings-regressions.yml
new file mode 100644
index 00000000000..f543730a57d
--- /dev/null
+++ b/changelogs/unreleased/48475-gitlab-pages-settings-regressions.yml
@@ -0,0 +1,5 @@
+---
+title: Fixing regression issues on pages settings and details
+merge_request: 22821
+author:
+type: fixed
diff --git a/changelogs/unreleased/48496-merge-request-refactor-does-not-highlight-selected-line.yml b/changelogs/unreleased/48496-merge-request-refactor-does-not-highlight-selected-line.yml
new file mode 100644
index 00000000000..cfc74bef638
--- /dev/null
+++ b/changelogs/unreleased/48496-merge-request-refactor-does-not-highlight-selected-line.yml
@@ -0,0 +1,5 @@
+---
+title: When user clicks linenumber in MR changes, highlight that line
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/48902-fix-diff-vertical-alignment.yml b/changelogs/unreleased/48902-fix-diff-vertical-alignment.yml
deleted file mode 100644
index 75018d57e5b..00000000000
--- a/changelogs/unreleased/48902-fix-diff-vertical-alignment.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix vertical alignment of text in diffs
-merge_request: 21573
-author:
-type: fixed
diff --git a/changelogs/unreleased/49479-hide-unmerged-env-perf-stats.yml b/changelogs/unreleased/49479-hide-unmerged-env-perf-stats.yml
new file mode 100644
index 00000000000..5118949f8a3
--- /dev/null
+++ b/changelogs/unreleased/49479-hide-unmerged-env-perf-stats.yml
@@ -0,0 +1,5 @@
+---
+title: Don't show Memory Usage for unmerged MRs
+merge_request:
+author:
+type: changed
diff --git a/changelogs/unreleased/49565-ssh-push-mirroring.yml b/changelogs/unreleased/49565-ssh-push-mirroring.yml
new file mode 100644
index 00000000000..2dfeffa4088
--- /dev/null
+++ b/changelogs/unreleased/49565-ssh-push-mirroring.yml
@@ -0,0 +1,5 @@
+---
+title: Allow SSH public-key authentication for push mirroring
+merge_request: 22982
+author:
+type: added
diff --git a/changelogs/unreleased/49726-upgrade-helm-to-2-11.yml b/changelogs/unreleased/49726-upgrade-helm-to-2-11.yml
new file mode 100644
index 00000000000..dd26af875f5
--- /dev/null
+++ b/changelogs/unreleased/49726-upgrade-helm-to-2-11.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade helm to 2.11.0 and upgrade on every install
+merge_request: 22693
+author:
+type: added
diff --git a/changelogs/unreleased/49943-resolve-filter-bar-height-changes.yml b/changelogs/unreleased/49943-resolve-filter-bar-height-changes.yml
deleted file mode 100644
index aa19b816b0b..00000000000
--- a/changelogs/unreleased/49943-resolve-filter-bar-height-changes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix filter bar height bug when a tag is added
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/49990-enable-omniauth-by-default.yml b/changelogs/unreleased/49990-enable-omniauth-by-default.yml
deleted file mode 100644
index 0c08bdf6ece..00000000000
--- a/changelogs/unreleased/49990-enable-omniauth-by-default.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable omniauth by default
-merge_request: 21700
-author:
-type: changed
diff --git a/changelogs/unreleased/50111-improve-design-of-cluster-apps-to-handle-larger-quantity.yml b/changelogs/unreleased/50111-improve-design-of-cluster-apps-to-handle-larger-quantity.yml
deleted file mode 100644
index 438c847327a..00000000000
--- a/changelogs/unreleased/50111-improve-design-of-cluster-apps-to-handle-larger-quantity.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Improve install flow of Kubernetes cluster apps
-merge_request: 21567
-author:
-type: changed
diff --git a/changelogs/unreleased/50264-add-border-around-the-repository-file-tree.yml b/changelogs/unreleased/50264-add-border-around-the-repository-file-tree.yml
new file mode 100644
index 00000000000..6315c3e7f36
--- /dev/null
+++ b/changelogs/unreleased/50264-add-border-around-the-repository-file-tree.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve Add border around the repository file tree
+merge_request: 23018
+author:
+type: changed
diff --git a/changelogs/unreleased/50341-cleanup-useless-project-import-attributes.yml b/changelogs/unreleased/50341-cleanup-useless-project-import-attributes.yml
new file mode 100644
index 00000000000..3893f14e15c
--- /dev/null
+++ b/changelogs/unreleased/50341-cleanup-useless-project-import-attributes.yml
@@ -0,0 +1,6 @@
+---
+title: Removes all the irrelevant code and columns that were migrated from the Project
+ table over to the ProjectImportState table
+merge_request: 21497
+author:
+type: performance
diff --git a/changelogs/unreleased/50461-add-retried-builds-in-pipeline-stage-endpoint.yml b/changelogs/unreleased/50461-add-retried-builds-in-pipeline-stage-endpoint.yml
deleted file mode 100644
index 539aea4f333..00000000000
--- a/changelogs/unreleased/50461-add-retried-builds-in-pipeline-stage-endpoint.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add retried jobs to pipeline stage
-merge_request: 21558
-author:
-type: other
diff --git a/changelogs/unreleased/50677-fix-cherry-pick-branch-empty-name.yml b/changelogs/unreleased/50677-fix-cherry-pick-branch-empty-name.yml
deleted file mode 100644
index 88a2ab802c8..00000000000
--- a/changelogs/unreleased/50677-fix-cherry-pick-branch-empty-name.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixes 500 for cherry pick API with empty branch name
-merge_request: 21501
-author: Jacopo Beschi @jacopo-beschi
-type: fixed
diff --git a/changelogs/unreleased/50678-ignores-project-pending-delete.yml b/changelogs/unreleased/50678-ignores-project-pending-delete.yml
deleted file mode 100644
index e4594abba99..00000000000
--- a/changelogs/unreleased/50678-ignores-project-pending-delete.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Excludes project marked from deletion to projects API
-merge_request: 21542
-author: Jacopo Beschi @jacopo-beschi
-type: changed
diff --git a/changelogs/unreleased/50808-choosing-initialize-repo-with-a-readme-breaks-project-created-from-template.yml b/changelogs/unreleased/50808-choosing-initialize-repo-with-a-readme-breaks-project-created-from-template.yml
deleted file mode 100644
index f9ed5683e63..00000000000
--- a/changelogs/unreleased/50808-choosing-initialize-repo-with-a-readme-breaks-project-created-from-template.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: 'create from template: hide checkbox for initializing repository with readme'
-merge_request: 21646
-author:
-type: other
diff --git a/changelogs/unreleased/50835-add-filtering-sorting-for-labels-on-labels-page.yml b/changelogs/unreleased/50835-add-filtering-sorting-for-labels-on-labels-page.yml
deleted file mode 100644
index 24e231ed88a..00000000000
--- a/changelogs/unreleased/50835-add-filtering-sorting-for-labels-on-labels-page.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add sorting for labels on labels page
-merge_request: 21642
-author:
-type: added
diff --git a/changelogs/unreleased/50839-webide-mr-dropdown-filter.yml b/changelogs/unreleased/50839-webide-mr-dropdown-filter.yml
new file mode 100644
index 00000000000..1c6c8747197
--- /dev/null
+++ b/changelogs/unreleased/50839-webide-mr-dropdown-filter.yml
@@ -0,0 +1,5 @@
+---
+title: Scope default MR search in WebIDE dropdown to current project
+merge_request: 23400
+author:
+type: changed
diff --git a/changelogs/unreleased/50989-add-trigger-information-to-job-api.yml b/changelogs/unreleased/50989-add-trigger-information-to-job-api.yml
deleted file mode 100644
index 5c8c78b8de8..00000000000
--- a/changelogs/unreleased/50989-add-trigger-information-to-job-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add trigger information in job API
-merge_request: 21495
-author:
-type: other
diff --git a/changelogs/unreleased/51029-status-emoji-currently-replaces-avatar-on-mobile.yml b/changelogs/unreleased/51029-status-emoji-currently-replaces-avatar-on-mobile.yml
new file mode 100644
index 00000000000..dc11ede5c8d
--- /dev/null
+++ b/changelogs/unreleased/51029-status-emoji-currently-replaces-avatar-on-mobile.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve status emoji being replaced by avatar on mobile
+merge_request: 23408
+author:
+type: other
diff --git a/changelogs/unreleased/51061-readme-url-n-1-rpc-call-resolved.yml b/changelogs/unreleased/51061-readme-url-n-1-rpc-call-resolved.yml
new file mode 100644
index 00000000000..86f91fcb427
--- /dev/null
+++ b/changelogs/unreleased/51061-readme-url-n-1-rpc-call-resolved.yml
@@ -0,0 +1,5 @@
+---
+title: Improves performance of Project#readme_url by caching the README path
+merge_request: 23357
+author:
+type: performance
diff --git a/changelogs/unreleased/51083-fix-move-api.yml b/changelogs/unreleased/51083-fix-move-api.yml
new file mode 100644
index 00000000000..8838f6f267e
--- /dev/null
+++ b/changelogs/unreleased/51083-fix-move-api.yml
@@ -0,0 +1,5 @@
+---
+title: 'Commits API: Preserve file content in move operations if unspecified'
+merge_request: 23387
+author:
+type: fixed
diff --git a/changelogs/unreleased/51112-add-status-illustration-in-job-api.yml b/changelogs/unreleased/51112-add-status-illustration-in-job-api.yml
deleted file mode 100644
index fdc75e28824..00000000000
--- a/changelogs/unreleased/51112-add-status-illustration-in-job-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add empty state illustration information in job API
-merge_request: 21532
-author:
-type: other
diff --git a/changelogs/unreleased/51259-ci-cd-gitlab-ui-1.yml b/changelogs/unreleased/51259-ci-cd-gitlab-ui-1.yml
new file mode 100644
index 00000000000..1d761d6299c
--- /dev/null
+++ b/changelogs/unreleased/51259-ci-cd-gitlab-ui-1.yml
@@ -0,0 +1,5 @@
+---
+title: Uses new gitlab-ui components in Jobs and Pipelines components
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/51259-ci-cd-tooltips.yml b/changelogs/unreleased/51259-ci-cd-tooltips.yml
new file mode 100644
index 00000000000..fc0010dbeba
--- /dev/null
+++ b/changelogs/unreleased/51259-ci-cd-tooltips.yml
@@ -0,0 +1,6 @@
+---
+title: Replaces tooltip directive with the new gl-tooltip directive for consistency
+ in some ci/cd code
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/51273-expose-runners-for-build-in-job-api.yml b/changelogs/unreleased/51273-expose-runners-for-build-in-job-api.yml
deleted file mode 100644
index df43f1dfbae..00000000000
--- a/changelogs/unreleased/51273-expose-runners-for-build-in-job-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Expose project runners in job API
-merge_request: 21618
-author:
-type: other
diff --git a/changelogs/unreleased/51450-vendor-refactor-registry-login.yml b/changelogs/unreleased/51450-vendor-refactor-registry-login.yml
deleted file mode 100644
index 417f12b4955..00000000000
--- a/changelogs/unreleased/51450-vendor-refactor-registry-login.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Vendor Auto-DevOps.gitlab-ci.yml to refactor registry_login
-merge_request: 21714
-author: Laurent Goderre @LaurentGoderre
-type: changed
diff --git a/changelogs/unreleased/51549-runners-table.yml b/changelogs/unreleased/51549-runners-table.yml
deleted file mode 100644
index fe36bfc1b30..00000000000
--- a/changelogs/unreleased/51549-runners-table.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixes admin runners table not wrapping content
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/51564-fix-commit-email-usage.yml b/changelogs/unreleased/51564-fix-commit-email-usage.yml
deleted file mode 100644
index 2f1b042ae8a..00000000000
--- a/changelogs/unreleased/51564-fix-commit-email-usage.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Respect the user commit email in more places
-merge_request: 21773
-author:
-type: fixed
diff --git a/changelogs/unreleased/51571-wrapper-rake-task-uploads-migrate-os.yml b/changelogs/unreleased/51571-wrapper-rake-task-uploads-migrate-os.yml
deleted file mode 100644
index 50710ca0aa8..00000000000
--- a/changelogs/unreleased/51571-wrapper-rake-task-uploads-migrate-os.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add wrapper rake task to migrate all uploads to OS
-merge_request: 21779
-author:
-type: other
diff --git a/changelogs/unreleased/51792-dont-delete-failed-install-pods.yml b/changelogs/unreleased/51792-dont-delete-failed-install-pods.yml
new file mode 100644
index 00000000000..7a900cbb86e
--- /dev/null
+++ b/changelogs/unreleased/51792-dont-delete-failed-install-pods.yml
@@ -0,0 +1,5 @@
+---
+title: Don't remove failed install pods after installing GitLab managed applications
+merge_request: 23350
+author:
+type: changed
diff --git a/changelogs/unreleased/51959-branch-and-tag-name-links.yml b/changelogs/unreleased/51959-branch-and-tag-name-links.yml
new file mode 100644
index 00000000000..64f1522c70d
--- /dev/null
+++ b/changelogs/unreleased/51959-branch-and-tag-name-links.yml
@@ -0,0 +1,5 @@
+---
+title: Chat message push notifications now include links back to GitLab branches
+merge_request: 22651
+author: Tony Castrogiovanni
+type: added
diff --git a/changelogs/unreleased/52276-jump-to-top-in-merge-request.yml b/changelogs/unreleased/52276-jump-to-top-in-merge-request.yml
new file mode 100644
index 00000000000..3dc95441eec
--- /dev/null
+++ b/changelogs/unreleased/52276-jump-to-top-in-merge-request.yml
@@ -0,0 +1,5 @@
+---
+title: Allow user to scroll to top of tab on MR page
+merge_request:
+author:
+type: added
diff --git a/changelogs/unreleased/52370-filter-by-none-any-for-labels-in-issues-mrs-boards.yml b/changelogs/unreleased/52370-filter-by-none-any-for-labels-in-issues-mrs-boards.yml
new file mode 100644
index 00000000000..9e1ee3ede5e
--- /dev/null
+++ b/changelogs/unreleased/52370-filter-by-none-any-for-labels-in-issues-mrs-boards.yml
@@ -0,0 +1,5 @@
+---
+title: Adds Any option to label filters
+merge_request: 23111
+author: Jacopo Beschi @jacopo-beschi
+type: added
diff --git a/changelogs/unreleased/52371-filter-by-none-any-for-labels-in-issues-mrs-api.yml b/changelogs/unreleased/52371-filter-by-none-any-for-labels-in-issues-mrs-api.yml
new file mode 100644
index 00000000000..bb196af3e90
--- /dev/null
+++ b/changelogs/unreleased/52371-filter-by-none-any-for-labels-in-issues-mrs-api.yml
@@ -0,0 +1,5 @@
+---
+title: Filter by None/Any for labels in issues/mrs API
+merge_request: 22622
+author: Jacopo Beschi @jacopo-beschi
+type: added
diff --git a/changelogs/unreleased/52371-removes-patially-matching-no-label-and-makes-it-case-insensitive.yml b/changelogs/unreleased/52371-removes-patially-matching-no-label-and-makes-it-case-insensitive.yml
new file mode 100644
index 00000000000..c1fc21c641a
--- /dev/null
+++ b/changelogs/unreleased/52371-removes-patially-matching-no-label-and-makes-it-case-insensitive.yml
@@ -0,0 +1,5 @@
+---
+title: removes partially matching of No Label filter and makes it case-insensitive
+merge_request: 22622
+author: Jacopo Beschi @jacopo-beschi
+type: changed
diff --git a/changelogs/unreleased/52385-search-bar-for-dashboard-list.yml b/changelogs/unreleased/52385-search-bar-for-dashboard-list.yml
new file mode 100644
index 00000000000..a437ae560cb
--- /dev/null
+++ b/changelogs/unreleased/52385-search-bar-for-dashboard-list.yml
@@ -0,0 +1,5 @@
+---
+title: Use search bar for filtering in dashboard issues / MRs
+merge_request: 22641
+author: Heinrich Lee Yu
+type: changed
diff --git a/changelogs/unreleased/52453-show-subgroups-in-group-create-issue.yml b/changelogs/unreleased/52453-show-subgroups-in-group-create-issue.yml
new file mode 100644
index 00000000000..d5877e96d07
--- /dev/null
+++ b/changelogs/unreleased/52453-show-subgroups-in-group-create-issue.yml
@@ -0,0 +1,5 @@
+---
+title: Fix project selector consistency in groups issues / MRs / boards pages
+merge_request: 22612
+author: Heinrich Lee Yu
+type: fixed
diff --git a/changelogs/unreleased/52712-further-ui-improvements-to-profile-overview-tab.yml b/changelogs/unreleased/52712-further-ui-improvements-to-profile-overview-tab.yml
new file mode 100644
index 00000000000..65aa9323d2e
--- /dev/null
+++ b/changelogs/unreleased/52712-further-ui-improvements-to-profile-overview-tab.yml
@@ -0,0 +1,5 @@
+---
+title: UI improvements to user's profile
+merge_request: 22977
+author:
+type: other
diff --git a/changelogs/unreleased/52828-inconsistency-in-fonts-used-for-branch-name-and-create-from-fields-when-creating-new-branch-from-ui.yml b/changelogs/unreleased/52828-inconsistency-in-fonts-used-for-branch-name-and-create-from-fields-when-creating-new-branch-from-ui.yml
new file mode 100644
index 00000000000..8132dde8636
--- /dev/null
+++ b/changelogs/unreleased/52828-inconsistency-in-fonts-used-for-branch-name-and-create-from-fields-when-creating-new-branch-from-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Make new branch form fields' fonts consistent
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/52940-fix-internal-email-pattern-not-respected.yml b/changelogs/unreleased/52940-fix-internal-email-pattern-not-respected.yml
new file mode 100644
index 00000000000..98e15a5cc0a
--- /dev/null
+++ b/changelogs/unreleased/52940-fix-internal-email-pattern-not-respected.yml
@@ -0,0 +1,5 @@
+---
+title: Fix a bug where internal email pattern wasn't respected
+merge_request: 22516
+author:
+type: fixed
diff --git a/changelogs/unreleased/53289-update-haml_lint-to-0-28-0.yml b/changelogs/unreleased/53289-update-haml_lint-to-0-28-0.yml
new file mode 100644
index 00000000000..9a16666c416
--- /dev/null
+++ b/changelogs/unreleased/53289-update-haml_lint-to-0-28-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update haml_lint to 0.28.0
+merge_request: 22660
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/53290-incorrect-project-list-order-select-default-label.yml b/changelogs/unreleased/53290-incorrect-project-list-order-select-default-label.yml
new file mode 100644
index 00000000000..d076352a27b
--- /dev/null
+++ b/changelogs/unreleased/53290-incorrect-project-list-order-select-default-label.yml
@@ -0,0 +1,5 @@
+---
+title: Fix default sorting for subgroups and projects list
+merge_request: 23058
+author: Jacopo Beschi @jacopo-beschi
+type: fixed
diff --git a/changelogs/unreleased/53291-update-ffaker-to-2-10-0.yml b/changelogs/unreleased/53291-update-ffaker-to-2-10-0.yml
new file mode 100644
index 00000000000..a1b95df5e32
--- /dev/null
+++ b/changelogs/unreleased/53291-update-ffaker-to-2-10-0.yml
@@ -0,0 +1,5 @@
+---
+title: Update ffaker to 2.10.0
+merge_request: 22661
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/53326-improve-issues-empty-state.yml b/changelogs/unreleased/53326-improve-issues-empty-state.yml
new file mode 100644
index 00000000000..7632db808b5
--- /dev/null
+++ b/changelogs/unreleased/53326-improve-issues-empty-state.yml
@@ -0,0 +1,5 @@
+---
+title: Show different empty state for filtered issues and MRs
+merge_request: 22775
+author: Heinrich Lee Yu
+type: changed
diff --git a/changelogs/unreleased/53400-unstar-icon-button-is-misaligned.yml b/changelogs/unreleased/53400-unstar-icon-button-is-misaligned.yml
new file mode 100644
index 00000000000..b393795f491
--- /dev/null
+++ b/changelogs/unreleased/53400-unstar-icon-button-is-misaligned.yml
@@ -0,0 +1,5 @@
+---
+title: 'Fix: Unstar icon button is misaligned'
+merge_request: 23444
+author:
+type: fixed
diff --git a/changelogs/unreleased/53578-fe-deployment-status.yml b/changelogs/unreleased/53578-fe-deployment-status.yml
new file mode 100644
index 00000000000..b88bd70ee2e
--- /dev/null
+++ b/changelogs/unreleased/53578-fe-deployment-status.yml
@@ -0,0 +1,5 @@
+---
+title: Adds states to the deployment widget
+merge_request:
+author:
+type: added
diff --git a/changelogs/unreleased/53626-update-config-map-on-install-retry.yml b/changelogs/unreleased/53626-update-config-map-on-install-retry.yml
new file mode 100644
index 00000000000..38e79c06c89
--- /dev/null
+++ b/changelogs/unreleased/53626-update-config-map-on-install-retry.yml
@@ -0,0 +1,5 @@
+---
+title: Update config map for gitlab managed application if already present on install
+merge_request: 22969
+author:
+type: other
diff --git a/changelogs/unreleased/53640-follow-up-from-resolve-redesign-activity-feed.yml b/changelogs/unreleased/53640-follow-up-from-resolve-redesign-activity-feed.yml
new file mode 100644
index 00000000000..66301329c52
--- /dev/null
+++ b/changelogs/unreleased/53640-follow-up-from-resolve-redesign-activity-feed.yml
@@ -0,0 +1,4 @@
+title: Adds new icon size to Vue icon component
+merge_request: 22899
+author:
+type: other
diff --git a/changelogs/unreleased/53700-hashed-storagemigration.yml b/changelogs/unreleased/53700-hashed-storagemigration.yml
new file mode 100644
index 00000000000..899012ffd22
--- /dev/null
+++ b/changelogs/unreleased/53700-hashed-storagemigration.yml
@@ -0,0 +1,5 @@
+---
+title: 'Hashed Storage: allow migration to be retried in partially migrated projects'
+merge_request: 23087
+author:
+type: fixed
diff --git a/changelogs/unreleased/53728-warn-in-web-editor-when-user-navigates-away.yml b/changelogs/unreleased/53728-warn-in-web-editor-when-user-navigates-away.yml
new file mode 100644
index 00000000000..8377fdc6133
--- /dev/null
+++ b/changelogs/unreleased/53728-warn-in-web-editor-when-user-navigates-away.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent user from navigating away from file edit without commit
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/53816-empty-label-menu-if-not-logged-in.yml b/changelogs/unreleased/53816-empty-label-menu-if-not-logged-in.yml
new file mode 100644
index 00000000000..a9ca56303eb
--- /dev/null
+++ b/changelogs/unreleased/53816-empty-label-menu-if-not-logged-in.yml
@@ -0,0 +1,5 @@
+---
+title: Removes promote to group label for anonymous user
+merge_request: 23042
+author: Jacopo Beschi @jacopo-beschi
+type: fixed
diff --git a/changelogs/unreleased/53874-navbar-lowres.yml b/changelogs/unreleased/53874-navbar-lowres.yml
new file mode 100644
index 00000000000..3b31b8f93fe
--- /dev/null
+++ b/changelogs/unreleased/53874-navbar-lowres.yml
@@ -0,0 +1,5 @@
+---
+title: "Fix overlapping navbar separator and overflowing navbar dropdown on small displays"
+merge_request: 23126
+author: Thomas Pathier
+type: fix
diff --git a/changelogs/unreleased/53988-remove-notes-index-on-updated-at.yml b/changelogs/unreleased/53988-remove-notes-index-on-updated-at.yml
new file mode 100644
index 00000000000..f0bbf69736d
--- /dev/null
+++ b/changelogs/unreleased/53988-remove-notes-index-on-updated-at.yml
@@ -0,0 +1,5 @@
+---
+title: Remove index for notes on updated_at
+merge_request: 23356
+author:
+type: performance
diff --git a/changelogs/unreleased/53992-add-events-index-on-project-id-and-created-at.yml b/changelogs/unreleased/53992-add-events-index-on-project-id-and-created-at.yml
new file mode 100644
index 00000000000..a2a3fa00f01
--- /dev/null
+++ b/changelogs/unreleased/53992-add-events-index-on-project-id-and-created-at.yml
@@ -0,0 +1,5 @@
+---
+title: Add index for events on project_id and created_at
+merge_request: 23354
+author:
+type: performance
diff --git a/changelogs/unreleased/54004-update-asana-to-0-8-1.yml b/changelogs/unreleased/54004-update-asana-to-0-8-1.yml
new file mode 100644
index 00000000000..a47b4f3c4d9
--- /dev/null
+++ b/changelogs/unreleased/54004-update-asana-to-0-8-1.yml
@@ -0,0 +1,5 @@
+---
+title: Update asana to 0.8.1
+merge_request: 23039
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/54010-update-asciidoctor-to-1-5-8.yml b/changelogs/unreleased/54010-update-asciidoctor-to-1-5-8.yml
new file mode 100644
index 00000000000..f0b0aa0ee1c
--- /dev/null
+++ b/changelogs/unreleased/54010-update-asciidoctor-to-1-5-8.yml
@@ -0,0 +1,5 @@
+---
+title: Update asciidoctor to 1.5.8
+merge_request: 23047
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/54015-Markdown-Editor-improve-Cursor-placement.yml b/changelogs/unreleased/54015-Markdown-Editor-improve-Cursor-placement.yml
new file mode 100644
index 00000000000..28e3fae01a9
--- /dev/null
+++ b/changelogs/unreleased/54015-Markdown-Editor-improve-Cursor-placement.yml
@@ -0,0 +1,5 @@
+---
+title: Refine cursor positioning in Markdown Editor for wrap tags
+merge_request: 23085
+author: Johann Hubert Sonntagbauer
+type: changed
diff --git a/changelogs/unreleased/54021-empty-button.yml b/changelogs/unreleased/54021-empty-button.yml
new file mode 100644
index 00000000000..3b03665cf95
--- /dev/null
+++ b/changelogs/unreleased/54021-empty-button.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent empty button being rendered in empty state
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/54032-reply-shortcut-only-discussion-text.yml b/changelogs/unreleased/54032-reply-shortcut-only-discussion-text.yml
new file mode 100644
index 00000000000..5c1f6e74b39
--- /dev/null
+++ b/changelogs/unreleased/54032-reply-shortcut-only-discussion-text.yml
@@ -0,0 +1,5 @@
+---
+title: Make reply shortcut only quote selected discussion text
+merge_request: 23096
+author: Thomas Pathier
+type: fix
diff --git a/changelogs/unreleased/54048-Line-numbers-are-misaligned-in-file-blame-view.yml b/changelogs/unreleased/54048-Line-numbers-are-misaligned-in-file-blame-view.yml
new file mode 100644
index 00000000000..8ceac4ec869
--- /dev/null
+++ b/changelogs/unreleased/54048-Line-numbers-are-misaligned-in-file-blame-view.yml
@@ -0,0 +1,5 @@
+---
+title: Fix line height of numbers in file blame view
+merge_request: 23090
+author: Johann Hubert Sonntagbauer
+type: fixed
diff --git a/changelogs/unreleased/54093-the-default_value_for-gem-doesn-t-handle-actioncontroller-parameters-correctly.yml b/changelogs/unreleased/54093-the-default_value_for-gem-doesn-t-handle-actioncontroller-parameters-correctly.yml
new file mode 100644
index 00000000000..3d6fd2d065a
--- /dev/null
+++ b/changelogs/unreleased/54093-the-default_value_for-gem-doesn-t-handle-actioncontroller-parameters-correctly.yml
@@ -0,0 +1,7 @@
+---
+title: Fixes an issue where default values from models would override values set in
+ the interface (e.g. users would be set to external even though their emails matches
+ the internal email address pattern)
+merge_request: 23114
+author:
+type: fixed
diff --git a/changelogs/unreleased/54201-update-rack-to-2-0-6.yml b/changelogs/unreleased/54201-update-rack-to-2-0-6.yml
new file mode 100644
index 00000000000..020b2bc0957
--- /dev/null
+++ b/changelogs/unreleased/54201-update-rack-to-2-0-6.yml
@@ -0,0 +1,5 @@
+---
+title: Update rack to 2.0.6 (for QA environments)
+merge_request: 23171
+author: Takuya Noguchi
+type: security
diff --git a/changelogs/unreleased/54218-fix-mergeUrlParams.yml b/changelogs/unreleased/54218-fix-mergeUrlParams.yml
new file mode 100644
index 00000000000..dae06b66e8e
--- /dev/null
+++ b/changelogs/unreleased/54218-fix-mergeUrlParams.yml
@@ -0,0 +1,5 @@
+---
+title: "Fix mergeUrlParams with fragment URL"
+merge_request: 54218
+author: Thomas Holder
+type: fixed
diff --git a/changelogs/unreleased/54391-tag.yml b/changelogs/unreleased/54391-tag.yml
new file mode 100644
index 00000000000..be571c6b0c3
--- /dev/null
+++ b/changelogs/unreleased/54391-tag.yml
@@ -0,0 +1,5 @@
+---
+title: Correctly styles tags in sidebar for job page
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/54407-fix-limited-intersection-observers.yml b/changelogs/unreleased/54407-fix-limited-intersection-observers.yml
new file mode 100644
index 00000000000..2c2bedb170b
--- /dev/null
+++ b/changelogs/unreleased/54407-fix-limited-intersection-observers.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Image Lazy Loader for some older browsers
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/54571-runner-tags.yml b/changelogs/unreleased/54571-runner-tags.yml
new file mode 100644
index 00000000000..1bb19d22e9c
--- /dev/null
+++ b/changelogs/unreleased/54571-runner-tags.yml
@@ -0,0 +1,5 @@
+---
+title: Adds margins between tags when a job is stuck
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/54648-fix-order-by-dropdown-tablet-screens.yml b/changelogs/unreleased/54648-fix-order-by-dropdown-tablet-screens.yml
new file mode 100644
index 00000000000..671d1590991
--- /dev/null
+++ b/changelogs/unreleased/54648-fix-order-by-dropdown-tablet-screens.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Order By dropdown menu styling in tablet and mobile screens
+merge_request: 23446
+author:
+type: fixed
diff --git a/changelogs/unreleased/_acet-fix-flash-styling.yml b/changelogs/unreleased/_acet-fix-flash-styling.yml
new file mode 100644
index 00000000000..57354c04899
--- /dev/null
+++ b/changelogs/unreleased/_acet-fix-flash-styling.yml
@@ -0,0 +1,5 @@
+---
+title: Fix flash notice styling for fluid layout
+merge_request: 23382
+author:
+type: fixed
diff --git a/changelogs/unreleased/ab-approximate-counts.yml b/changelogs/unreleased/ab-approximate-counts.yml
new file mode 100644
index 00000000000..8a67239d031
--- /dev/null
+++ b/changelogs/unreleased/ab-approximate-counts.yml
@@ -0,0 +1,5 @@
+---
+title: Approximate counting strategy with TABLESAMPLE.
+merge_request: 22650
+author:
+type: performance
diff --git a/changelogs/unreleased/add-2fa-button.yml b/changelogs/unreleased/add-2fa-button.yml
deleted file mode 100644
index 6cb71d52781..00000000000
--- a/changelogs/unreleased/add-2fa-button.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add button to download 2FA codes
-merge_request:
-author: Luke Picciau
-type: added
diff --git a/changelogs/unreleased/add-most-stars-for-filter-option.yml b/changelogs/unreleased/add-most-stars-for-filter-option.yml
deleted file mode 100644
index be95d6db55f..00000000000
--- a/changelogs/unreleased/add-most-stars-for-filter-option.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Allows to sort projects by most stars
-merge_request: 21762
-author: Jacopo Beschi @jacopo-beschi
-type: added
diff --git a/changelogs/unreleased/added-glob-for-ci-changes-detection.yml b/changelogs/unreleased/added-glob-for-ci-changes-detection.yml
new file mode 100644
index 00000000000..887c6ef0346
--- /dev/null
+++ b/changelogs/unreleased/added-glob-for-ci-changes-detection.yml
@@ -0,0 +1,5 @@
+---
+title: Added glob for CI changes detection
+merge_request: 23128
+author: Kirill Zaitsev
+type: added
diff --git a/changelogs/unreleased/an-gitaly-version-0-133-0.yml b/changelogs/unreleased/an-gitaly-version-0-133-0.yml
new file mode 100644
index 00000000000..4f3943ceacb
--- /dev/null
+++ b/changelogs/unreleased/an-gitaly-version-0-133-0.yml
@@ -0,0 +1,5 @@
+---
+title: Updated Gitaly to v0.133.0
+merge_request: 23148
+author:
+type: other
diff --git a/changelogs/unreleased/ashmckenzie-hmac-token-decode-and-tests.yml b/changelogs/unreleased/ashmckenzie-hmac-token-decode-and-tests.yml
new file mode 100644
index 00000000000..d15c5654d99
--- /dev/null
+++ b/changelogs/unreleased/ashmckenzie-hmac-token-decode-and-tests.yml
@@ -0,0 +1,5 @@
+---
+title: Relocate JSONWebToken::HMACToken from EE
+merge_request: 22906
+author:
+type: changed
diff --git a/changelogs/unreleased/auto_devops_kubernetes_active.yml b/changelogs/unreleased/auto_devops_kubernetes_active.yml
new file mode 100644
index 00000000000..310d37128c9
--- /dev/null
+++ b/changelogs/unreleased/auto_devops_kubernetes_active.yml
@@ -0,0 +1,5 @@
+---
+title: Switch kubernetes:active with checking in Auto-DevOps.gitlab-ci.yml
+merge_request: 22929
+author:
+type: fixed
diff --git a/changelogs/unreleased/blackst0ne-add-discord-service.yml b/changelogs/unreleased/blackst0ne-add-discord-service.yml
new file mode 100644
index 00000000000..85dedf6d81f
--- /dev/null
+++ b/changelogs/unreleased/blackst0ne-add-discord-service.yml
@@ -0,0 +1,5 @@
+---
+title: Add Discord integration
+merge_request: 22684
+author: "@blackst0ne"
+type: added
diff --git a/changelogs/unreleased/bump_gpgme_gem.yml b/changelogs/unreleased/bump_gpgme_gem.yml
new file mode 100644
index 00000000000..4c0067cb824
--- /dev/null
+++ b/changelogs/unreleased/bump_gpgme_gem.yml
@@ -0,0 +1,5 @@
+---
+title: Bump gpgme gem version from 2.0.13 to 2.0.18
+merge_request:
+author: asaparov
+type: other
diff --git a/changelogs/unreleased/bvl-use-shell-writeref.yml b/changelogs/unreleased/bvl-use-shell-writeref.yml
new file mode 100644
index 00000000000..682d428e8c5
--- /dev/null
+++ b/changelogs/unreleased/bvl-use-shell-writeref.yml
@@ -0,0 +1,5 @@
+---
+title: Avoid creating invalid refs using rugged, shelling out for writing refs
+merge_request: 23286
+author:
+type: fixed
diff --git a/changelogs/unreleased/ccr-50483_add_filter_for_group_milestones.yml b/changelogs/unreleased/ccr-50483_add_filter_for_group_milestones.yml
deleted file mode 100644
index f8fe50a2c48..00000000000
--- a/changelogs/unreleased/ccr-50483_add_filter_for_group_milestones.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Filter group milestones based on user membership.
-merge_request: 21660
-author:
-type: fixed
diff --git a/changelogs/unreleased/ce-52811-fix_namespaces_api_routing.yml b/changelogs/unreleased/ce-52811-fix_namespaces_api_routing.yml
new file mode 100644
index 00000000000..b5fd99c304f
--- /dev/null
+++ b/changelogs/unreleased/ce-52811-fix_namespaces_api_routing.yml
@@ -0,0 +1,5 @@
+---
+title: Fix API::Namespaces routing to accept namepaces with dots
+merge_request: 22912
+author:
+type: fixed
diff --git a/changelogs/unreleased/ce-54109-fix_user_by_any_email.yml b/changelogs/unreleased/ce-54109-fix_user_by_any_email.yml
new file mode 100644
index 00000000000..eb5d2e3244c
--- /dev/null
+++ b/changelogs/unreleased/ce-54109-fix_user_by_any_email.yml
@@ -0,0 +1,5 @@
+---
+title: Respect confirmed flag on secondary emails
+merge_request: 23181
+author:
+type: fixed
diff --git a/changelogs/unreleased/certmanager-temp.yml b/changelogs/unreleased/certmanager-temp.yml
new file mode 100644
index 00000000000..3f908d01c9f
--- /dev/null
+++ b/changelogs/unreleased/certmanager-temp.yml
@@ -0,0 +1,5 @@
+---
+title: "#40635: Adds support for cert-manager"
+merge_request: 23036
+author: Amit Rathi
+type: added
diff --git a/changelogs/unreleased/check-if-fetched-data-does-is-complete.yml b/changelogs/unreleased/check-if-fetched-data-does-is-complete.yml
new file mode 100644
index 00000000000..31c131045b9
--- /dev/null
+++ b/changelogs/unreleased/check-if-fetched-data-does-is-complete.yml
@@ -0,0 +1,5 @@
+---
+title: Validate chunk size when persist
+merge_request: 23341
+author:
+type: fixed
diff --git a/changelogs/unreleased/clean-gitlab-git.yml b/changelogs/unreleased/clean-gitlab-git.yml
deleted file mode 100644
index d7086b8eea0..00000000000
--- a/changelogs/unreleased/clean-gitlab-git.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove Rugged and shell code from Gitlab::Git
-merge_request: 21488
-author:
-type: other
diff --git a/changelogs/unreleased/da-synchronize-the-default-branch-when-updating-a-remote-mirror.yml b/changelogs/unreleased/da-synchronize-the-default-branch-when-updating-a-remote-mirror.yml
deleted file mode 100644
index 723aa3eee8a..00000000000
--- a/changelogs/unreleased/da-synchronize-the-default-branch-when-updating-a-remote-mirror.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Synchronize the default branch when updating a remote mirror
-merge_request: 21653
-author:
-type: fixed
diff --git a/changelogs/unreleased/discussion-perf-improvement.yml b/changelogs/unreleased/discussion-perf-improvement.yml
new file mode 100644
index 00000000000..defff8a55f5
--- /dev/null
+++ b/changelogs/unreleased/discussion-perf-improvement.yml
@@ -0,0 +1,5 @@
+---
+title: Improve initial discussion rendering performance
+merge_request: 22607
+author:
+type: changed
diff --git a/changelogs/unreleased/dm-batch-loader-key.yml b/changelogs/unreleased/dm-batch-loader-key.yml
new file mode 100644
index 00000000000..047fdbc4b3f
--- /dev/null
+++ b/changelogs/unreleased/dm-batch-loader-key.yml
@@ -0,0 +1,5 @@
+---
+title: Batch load only data from same repository when lazy object is accessed
+merge_request: 23309
+author:
+type: performance
diff --git a/changelogs/unreleased/docs-minor-aws-fixes.yml b/changelogs/unreleased/docs-minor-aws-fixes.yml
new file mode 100644
index 00000000000..64fa6b12afe
--- /dev/null
+++ b/changelogs/unreleased/docs-minor-aws-fixes.yml
@@ -0,0 +1,5 @@
+---
+title: Fixes to AWS documentation spelling and grammar
+merge_request: 23198
+author: Brendan O'Leary
+type: other
diff --git a/changelogs/unreleased/document-raw-snippet-api.yml b/changelogs/unreleased/document-raw-snippet-api.yml
new file mode 100644
index 00000000000..3b8818cea5c
--- /dev/null
+++ b/changelogs/unreleased/document-raw-snippet-api.yml
@@ -0,0 +1,5 @@
+---
+title: Fix lack of documentation on how to fetch a snippet's content using API
+merge_request: 23448
+author: Colin Leroy
+type: other
diff --git a/changelogs/unreleased/drop-default-value-status-deployments.yml b/changelogs/unreleased/drop-default-value-status-deployments.yml
new file mode 100644
index 00000000000..fdb826a0507
--- /dev/null
+++ b/changelogs/unreleased/drop-default-value-status-deployments.yml
@@ -0,0 +1,5 @@
+---
+title: Drop default value on status column in deployments table
+merge_request: 22971
+author:
+type: other
diff --git a/changelogs/unreleased/drop-gcp-cluster-table.yml b/changelogs/unreleased/drop-gcp-cluster-table.yml
new file mode 100644
index 00000000000..15964ec2eaf
--- /dev/null
+++ b/changelogs/unreleased/drop-gcp-cluster-table.yml
@@ -0,0 +1,5 @@
+---
+title: Drop gcp_clusters table
+merge_request: 22713
+author:
+type: other
diff --git a/changelogs/unreleased/feature-runner-state-filter-for-admin-view.yml b/changelogs/unreleased/feature-runner-state-filter-for-admin-view.yml
deleted file mode 100644
index b8112bd0813..00000000000
--- a/changelogs/unreleased/feature-runner-state-filter-for-admin-view.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add a filter bar to the admin runners view and add a state filter
-merge_request: 19625
-author: Alexis Reigel
-type: added
diff --git a/changelogs/unreleased/fix-chat-notification-service-for-ee.yml b/changelogs/unreleased/fix-chat-notification-service-for-ee.yml
deleted file mode 100644
index b69d08b95db..00000000000
--- a/changelogs/unreleased/fix-chat-notification-service-for-ee.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix activity titles for MRs in chat notification services
-merge_request: 21834
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-deadlock-chunked-io.yml b/changelogs/unreleased/fix-deadlock-chunked-io.yml
new file mode 100644
index 00000000000..def7a59e86e
--- /dev/null
+++ b/changelogs/unreleased/fix-deadlock-chunked-io.yml
@@ -0,0 +1,5 @@
+---
+title: Fix deadlock on ChunkedIO
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-leading-slash-in-redirects-plus-rubocop.yml b/changelogs/unreleased/fix-leading-slash-in-redirects-plus-rubocop.yml
deleted file mode 100644
index 38b2486a475..00000000000
--- a/changelogs/unreleased/fix-leading-slash-in-redirects-plus-rubocop.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix leading slash in redirects and add rubocop cop
-merge_request: 21828
-author: Sanad Liaquat
-type: fixed
diff --git a/changelogs/unreleased/fix-mention-in-edit-mr.yml b/changelogs/unreleased/fix-mention-in-edit-mr.yml
deleted file mode 100644
index a82b0ba9748..00000000000
--- a/changelogs/unreleased/fix-mention-in-edit-mr.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed mention autocomplete in edit merge request.
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-mr-widget-unrelated-deployment-status.yml b/changelogs/unreleased/fix-mr-widget-unrelated-deployment-status.yml
new file mode 100644
index 00000000000..ab926fbd43b
--- /dev/null
+++ b/changelogs/unreleased/fix-mr-widget-unrelated-deployment-status.yml
@@ -0,0 +1,5 @@
+---
+title: Fix unrelated deployment status in MR widget
+merge_request: 23175
+author:
+type: fixed
diff --git a/changelogs/unreleased/fj-47494-upgrade-git-to-2-18-0.yml b/changelogs/unreleased/fj-47494-upgrade-git-to-2-18-0.yml
new file mode 100644
index 00000000000..0f01552ff7e
--- /dev/null
+++ b/changelogs/unreleased/fj-47494-upgrade-git-to-2-18-0.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade minimum required Git version to 2.18.0
+merge_request: 22803
+author:
+type: other
diff --git a/changelogs/unreleased/fj-force-content-disposition.yml b/changelogs/unreleased/fj-force-content-disposition.yml
new file mode 100644
index 00000000000..d84555a489f
--- /dev/null
+++ b/changelogs/unreleased/fj-force-content-disposition.yml
@@ -0,0 +1,5 @@
+---
+title: Force content disposition attachment to several endpoints
+merge_request: 23223
+author:
+type: other
diff --git a/changelogs/unreleased/force-post-migration-dir-schema-load.yml b/changelogs/unreleased/force-post-migration-dir-schema-load.yml
deleted file mode 100644
index 19119515929..00000000000
--- a/changelogs/unreleased/force-post-migration-dir-schema-load.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Ensure the schema is loaded with post_migrations included
-merge_request: 21689
-author:
-type: changed
diff --git a/changelogs/unreleased/force-reload-arguments-1.yml b/changelogs/unreleased/force-reload-arguments-1.yml
new file mode 100644
index 00000000000..29f34b8bdbe
--- /dev/null
+++ b/changelogs/unreleased/force-reload-arguments-1.yml
@@ -0,0 +1,5 @@
+---
+title: Passing an argument to force an association to reload is now deprecated
+merge_request: 23334
+author: Jasper Maes
+type: other
diff --git a/changelogs/unreleased/frozen-string-app-controller.yml b/changelogs/unreleased/frozen-string-app-controller.yml
deleted file mode 100644
index 95fea4eae63..00000000000
--- a/changelogs/unreleased/frozen-string-app-controller.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable frozen string in app/controllers/**/*.rb
-merge_request: gfyoung
-author:
-type: performance
diff --git a/changelogs/unreleased/frozen-string-app-finders-graphql.yml b/changelogs/unreleased/frozen-string-app-finders-graphql.yml
deleted file mode 100644
index ea8c83f64d9..00000000000
--- a/changelogs/unreleased/frozen-string-app-finders-graphql.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable frozen string in app/graphql + app/finders
-merge_request:
-author: gfyoung
-type: performance
diff --git a/changelogs/unreleased/frozen-string-enable-app-helpers.yml b/changelogs/unreleased/frozen-string-enable-app-helpers.yml
deleted file mode 100644
index 7f6805ccb5a..00000000000
--- a/changelogs/unreleased/frozen-string-enable-app-helpers.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable frozen string for app/helpers/**/*.rb
-merge_request:
-author: gfyoung
-type: performance
diff --git a/changelogs/unreleased/frozen-string-enable-vestigial.yml b/changelogs/unreleased/frozen-string-enable-vestigial.yml
deleted file mode 100644
index 55313ff0fcc..00000000000
--- a/changelogs/unreleased/frozen-string-enable-vestigial.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Enable frozen string in vestigial files
-merge_request:
-author: gfyoung
-type: performance
diff --git a/changelogs/unreleased/frozen-string-lib-gitlab-even-even-even-more.yml b/changelogs/unreleased/frozen-string-lib-gitlab-even-even-even-more.yml
new file mode 100644
index 00000000000..e718d716647
--- /dev/null
+++ b/changelogs/unreleased/frozen-string-lib-gitlab-even-even-even-more.yml
@@ -0,0 +1,5 @@
+---
+title: Enable even more frozen string for lib/gitlab
+merge_request:
+author: gfyoung
+type: performance
diff --git a/changelogs/unreleased/frozen-string-lib-gitlab-even-even-more.yml b/changelogs/unreleased/frozen-string-lib-gitlab-even-even-more.yml
new file mode 100644
index 00000000000..e718d716647
--- /dev/null
+++ b/changelogs/unreleased/frozen-string-lib-gitlab-even-even-more.yml
@@ -0,0 +1,5 @@
+---
+title: Enable even more frozen string for lib/gitlab
+merge_request:
+author: gfyoung
+type: performance
diff --git a/changelogs/unreleased/frozen-string-lib-gitlab-even-more.yml b/changelogs/unreleased/frozen-string-lib-gitlab-even-more.yml
new file mode 100644
index 00000000000..cfbc4ced635
--- /dev/null
+++ b/changelogs/unreleased/frozen-string-lib-gitlab-even-more.yml
@@ -0,0 +1,5 @@
+---
+title: Enable even more frozen string in lib/gitlab/**/*.rb
+merge_request:
+author: gfyoung
+type: performance
diff --git a/changelogs/unreleased/frozen-string-lib-gitlab-more.yml b/changelogs/unreleased/frozen-string-lib-gitlab-more.yml
new file mode 100644
index 00000000000..cfbc4ced635
--- /dev/null
+++ b/changelogs/unreleased/frozen-string-lib-gitlab-more.yml
@@ -0,0 +1,5 @@
+---
+title: Enable even more frozen string in lib/gitlab/**/*.rb
+merge_request:
+author: gfyoung
+type: performance
diff --git a/changelogs/unreleased/frozen-string-lib-rubocop.yml b/changelogs/unreleased/frozen-string-lib-rubocop.yml
new file mode 100644
index 00000000000..9fe342e251b
--- /dev/null
+++ b/changelogs/unreleased/frozen-string-lib-rubocop.yml
@@ -0,0 +1,5 @@
+---
+title: Enable Rubocop on lib/gitlab
+merge_request:
+author: gfyoung
+type: other
diff --git a/changelogs/unreleased/gt-align-issue-status-and-confidential-icon.yml b/changelogs/unreleased/gt-align-issue-status-and-confidential-icon.yml
new file mode 100644
index 00000000000..481ce656dc7
--- /dev/null
+++ b/changelogs/unreleased/gt-align-issue-status-and-confidential-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Align issue status label and confidential icon.
+merge_request: 23046
+author: George Tsiolis
+type: fixed
diff --git a/changelogs/unreleased/gt-change-breadcrumb-title-for-contribution-charts.yml b/changelogs/unreleased/gt-change-breadcrumb-title-for-contribution-charts.yml
new file mode 100644
index 00000000000..233cc43117d
--- /dev/null
+++ b/changelogs/unreleased/gt-change-breadcrumb-title-for-contribution-charts.yml
@@ -0,0 +1,5 @@
+---
+title: Change breadcrumb title for contribution charts
+merge_request: 23071
+author: George Tsiolis
+type: changed
diff --git a/changelogs/unreleased/gt-externalize-app-views-invites.yml b/changelogs/unreleased/gt-externalize-app-views-invites.yml
new file mode 100644
index 00000000000..b5a22177f9b
--- /dev/null
+++ b/changelogs/unreleased/gt-externalize-app-views-invites.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings from `/app/views/invites`
+merge_request: 23205
+author: Tao Wang
+type: other
diff --git a/changelogs/unreleased/gt-externalize-app-views-project-runners.yml b/changelogs/unreleased/gt-externalize-app-views-project-runners.yml
new file mode 100644
index 00000000000..d7d591e2175
--- /dev/null
+++ b/changelogs/unreleased/gt-externalize-app-views-project-runners.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings from `/app/views/project/runners`
+merge_request: 23208
+author: Tao Wang
+type: other
diff --git a/changelogs/unreleased/gt-externalize-app-views-snippets.yml b/changelogs/unreleased/gt-externalize-app-views-snippets.yml
new file mode 100644
index 00000000000..633aa9f2534
--- /dev/null
+++ b/changelogs/unreleased/gt-externalize-app-views-snippets.yml
@@ -0,0 +1,5 @@
+---
+title: Externalize strings from `/app/views/snippets`
+merge_request: 23351
+author: Tao Wang
+type: other
diff --git a/changelogs/unreleased/gt-fix-typo-in-notebook-props.yml b/changelogs/unreleased/gt-fix-typo-in-notebook-props.yml
new file mode 100644
index 00000000000..60603905a2d
--- /dev/null
+++ b/changelogs/unreleased/gt-fix-typo-in-notebook-props.yml
@@ -0,0 +1,5 @@
+---
+title: Fix typo in notebook props
+merge_request: 23103
+author: George Tsiolis
+type: other
diff --git a/changelogs/unreleased/gt-fix-typos-in-lib.yml b/changelogs/unreleased/gt-fix-typos-in-lib.yml
new file mode 100644
index 00000000000..32ccd03b063
--- /dev/null
+++ b/changelogs/unreleased/gt-fix-typos-in-lib.yml
@@ -0,0 +1,5 @@
+---
+title: Fix typos in lib
+merge_request: 23106
+author: George Tsiolis
+type: other
diff --git a/changelogs/unreleased/gt-remove-instances-of-extend-monospace.yml b/changelogs/unreleased/gt-remove-instances-of-extend-monospace.yml
new file mode 100644
index 00000000000..dc41de61046
--- /dev/null
+++ b/changelogs/unreleased/gt-remove-instances-of-extend-monospace.yml
@@ -0,0 +1,5 @@
+---
+title: Remove monospace extend
+merge_request: 23089
+author: George Tsiolis
+type: performance
diff --git a/changelogs/unreleased/gt-remove-unused-project-method.yml b/changelogs/unreleased/gt-remove-unused-project-method.yml
new file mode 100644
index 00000000000..2d60c2fe423
--- /dev/null
+++ b/changelogs/unreleased/gt-remove-unused-project-method.yml
@@ -0,0 +1,5 @@
+---
+title: Remove unused project method
+merge_request: 54103
+author: George Tsiolis
+type: other
diff --git a/changelogs/unreleased/gt-rename-diffs-store-variable.yml b/changelogs/unreleased/gt-rename-diffs-store-variable.yml
new file mode 100644
index 00000000000..0aed49f3d60
--- /dev/null
+++ b/changelogs/unreleased/gt-rename-diffs-store-variable.yml
@@ -0,0 +1,5 @@
+---
+title: Rename diffs store variable
+merge_request: 23123
+author: George Tsiolis
+type: other
diff --git a/changelogs/unreleased/gt-update-env-metrics-empty-state.yml b/changelogs/unreleased/gt-update-env-metrics-empty-state.yml
new file mode 100644
index 00000000000..a05dc07e65c
--- /dev/null
+++ b/changelogs/unreleased/gt-update-env-metrics-empty-state.yml
@@ -0,0 +1,5 @@
+---
+title: Update environments metrics empty state
+merge_request: 23074
+author: George Tsiolis
+type: changed
diff --git a/changelogs/unreleased/gt-use-gl-tooltip-directive.yml b/changelogs/unreleased/gt-use-gl-tooltip-directive.yml
new file mode 100644
index 00000000000..91fdb73e3c6
--- /dev/null
+++ b/changelogs/unreleased/gt-use-gl-tooltip-directive.yml
@@ -0,0 +1,5 @@
+---
+title: Replace tooltip directive with gl-tooltip diretive in badges, cycle analytics, and diffs
+merge_request: 22770
+author: George Tsiolis
+type: performance
diff --git a/changelogs/unreleased/ide-open-all-mr-files.yml b/changelogs/unreleased/ide-open-all-mr-files.yml
new file mode 100644
index 00000000000..6a5ea8908fc
--- /dev/null
+++ b/changelogs/unreleased/ide-open-all-mr-files.yml
@@ -0,0 +1,5 @@
+---
+title: Open first 10 merge request files in IDE
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/ignore-failed-pipeline-creation-on-pipeline-schedule.yml b/changelogs/unreleased/ignore-failed-pipeline-creation-on-pipeline-schedule.yml
new file mode 100644
index 00000000000..90f47aa12db
--- /dev/null
+++ b/changelogs/unreleased/ignore-failed-pipeline-creation-on-pipeline-schedule.yml
@@ -0,0 +1,5 @@
+---
+title: Remove auto deactivation when failed to create a pipeline via pipeline schedules
+merge_request: 22243
+author:
+type: changed
diff --git a/changelogs/unreleased/improve_auto_devops_migration_debug.yml b/changelogs/unreleased/improve_auto_devops_migration_debug.yml
new file mode 100644
index 00000000000..96a78808361
--- /dev/null
+++ b/changelogs/unreleased/improve_auto_devops_migration_debug.yml
@@ -0,0 +1,6 @@
+---
+title: 'Auto DevOps: Add echo for each branch of the deploy() function where we run
+ helm upgrade'
+merge_request: 23499
+author:
+type: changed
diff --git a/changelogs/unreleased/include-new-link-in-breadcrumb.yml b/changelogs/unreleased/include-new-link-in-breadcrumb.yml
new file mode 100644
index 00000000000..68c808d66d7
--- /dev/null
+++ b/changelogs/unreleased/include-new-link-in-breadcrumb.yml
@@ -0,0 +1,5 @@
+---
+title: Include new link in breadcrumb for issues, merge requests, milestones, and labels
+merge_request: 18515
+author: George Tsiolis
+type: changed
diff --git a/changelogs/unreleased/issue_50528.yml b/changelogs/unreleased/issue_50528.yml
deleted file mode 100644
index 82d33bfa255..00000000000
--- a/changelogs/unreleased/issue_50528.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Log project services errors when executing async
-merge_request:
-author:
-type: other
diff --git a/changelogs/unreleased/jivl-add-empty-state-graphs-null-values.yml b/changelogs/unreleased/jivl-add-empty-state-graphs-null-values.yml
new file mode 100644
index 00000000000..d21254b16d0
--- /dev/null
+++ b/changelogs/unreleased/jivl-add-empty-state-graphs-null-values.yml
@@ -0,0 +1,5 @@
+---
+title: Add empty state for graphs with no values
+merge_request: 22630
+author:
+type: fixed
diff --git a/changelogs/unreleased/jupyter-tls.yml b/changelogs/unreleased/jupyter-tls.yml
new file mode 100644
index 00000000000..4111edd34ff
--- /dev/null
+++ b/changelogs/unreleased/jupyter-tls.yml
@@ -0,0 +1,5 @@
+---
+title: "#52753: HTTPS for JupyterHub installation"
+merge_request: 23479
+author: Amit Rathi
+type: added
diff --git a/changelogs/unreleased/kcj-add-philosophy.yml b/changelogs/unreleased/kcj-add-philosophy.yml
new file mode 100644
index 00000000000..d164ce165ea
--- /dev/null
+++ b/changelogs/unreleased/kcj-add-philosophy.yml
@@ -0,0 +1,5 @@
+---
+title: Adds a PHILOSOPHY.md which references GitLab Product Handbook
+merge_request: 23200
+author:
+type: other
diff --git a/changelogs/unreleased/kubernetes-http-response-code.yml b/changelogs/unreleased/kubernetes-http-response-code.yml
new file mode 100644
index 00000000000..551fe2edc3c
--- /dev/null
+++ b/changelogs/unreleased/kubernetes-http-response-code.yml
@@ -0,0 +1,5 @@
+---
+title: Show HTTP response code for Kubernetes errors
+merge_request: 22964
+author:
+type: other
diff --git a/changelogs/unreleased/legacy_fallback_for_project_clusters_only.yml b/changelogs/unreleased/legacy_fallback_for_project_clusters_only.yml
new file mode 100644
index 00000000000..c8e959176d0
--- /dev/null
+++ b/changelogs/unreleased/legacy_fallback_for_project_clusters_only.yml
@@ -0,0 +1,5 @@
+---
+title: Fallback to admin KUBE_TOKEN for project clusters only
+merge_request: 23527
+author:
+type: other
diff --git a/changelogs/unreleased/lock-trace-writes.yml b/changelogs/unreleased/lock-trace-writes.yml
new file mode 100644
index 00000000000..9c5239081b9
--- /dev/null
+++ b/changelogs/unreleased/lock-trace-writes.yml
@@ -0,0 +1,5 @@
+---
+title: Lock writes to trace stream
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/lock-unlock-quick-actions.yml b/changelogs/unreleased/lock-unlock-quick-actions.yml
deleted file mode 100644
index 9322d60ba52..00000000000
--- a/changelogs/unreleased/lock-unlock-quick-actions.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add /lock and /unlock quick actions
-merge_request: 15197
-author: Mehdi Lahmam (@mehlah)
-type: added
diff --git a/changelogs/unreleased/mr-file-tree-commit.yml b/changelogs/unreleased/mr-file-tree-commit.yml
new file mode 100644
index 00000000000..e0d47e6e61f
--- /dev/null
+++ b/changelogs/unreleased/mr-file-tree-commit.yml
@@ -0,0 +1,5 @@
+---
+title: Show tree collapse button for merge request commit diffs
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/mr-legacy-diff-notes.yml b/changelogs/unreleased/mr-legacy-diff-notes.yml
deleted file mode 100644
index bca5ac8297f..00000000000
--- a/changelogs/unreleased/mr-legacy-diff-notes.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Correctly show legacy diff notes in the merge request changes tab
-merge_request: 21652
-author:
-type: fixed
diff --git a/changelogs/unreleased/mr-origin-23218.yml b/changelogs/unreleased/mr-origin-23218.yml
new file mode 100644
index 00000000000..49867f04343
--- /dev/null
+++ b/changelogs/unreleased/mr-origin-23218.yml
@@ -0,0 +1,5 @@
+---
+title: Fix typo for scheduled pipeline
+merge_request: 23218
+author: Davy Defaud
+type: other
diff --git a/changelogs/unreleased/mr-sticky-headers.yml b/changelogs/unreleased/mr-sticky-headers.yml
new file mode 100644
index 00000000000..c20829bc2d7
--- /dev/null
+++ b/changelogs/unreleased/mr-sticky-headers.yml
@@ -0,0 +1,5 @@
+---
+title: Make diff file headers sticky
+merge_request:
+author:
+type: changed
diff --git a/changelogs/unreleased/mr-tree-filter-path-name.yml b/changelogs/unreleased/mr-tree-filter-path-name.yml
new file mode 100644
index 00000000000..152f8a67337
--- /dev/null
+++ b/changelogs/unreleased/mr-tree-filter-path-name.yml
@@ -0,0 +1,5 @@
+---
+title: Changed merge request filtering to be by path instead of name
+merge_request:
+author:
+type: changed
diff --git a/changelogs/unreleased/mr-widget-discussion-state-fix.yml b/changelogs/unreleased/mr-widget-discussion-state-fix.yml
deleted file mode 100644
index 562d78a7aa7..00000000000
--- a/changelogs/unreleased/mr-widget-discussion-state-fix.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed merge request widget discussion state not updating after resolving discussions
-merge_request: 21705
-author:
-type: fixed
diff --git a/changelogs/unreleased/non-webkit-scrollbar-fixing.yml b/changelogs/unreleased/non-webkit-scrollbar-fixing.yml
new file mode 100644
index 00000000000..526a9f25486
--- /dev/null
+++ b/changelogs/unreleased/non-webkit-scrollbar-fixing.yml
@@ -0,0 +1,5 @@
+---
+title: Fix horizontal scrollbar overlapping on horizontal scrolling-tabs
+merge_request: 23167
+author: Harry Kiselev
+type: other
diff --git a/changelogs/unreleased/optimise-job-request.yml b/changelogs/unreleased/optimise-job-request.yml
new file mode 100644
index 00000000000..e1265841b48
--- /dev/null
+++ b/changelogs/unreleased/optimise-job-request.yml
@@ -0,0 +1,5 @@
+---
+title: Use cached size when passing artifacts to Runner
+merge_request:
+author:
+type: performance
diff --git a/changelogs/unreleased/order-of-notification-settings.yml b/changelogs/unreleased/order-of-notification-settings.yml
new file mode 100644
index 00000000000..0f0243bcb40
--- /dev/null
+++ b/changelogs/unreleased/order-of-notification-settings.yml
@@ -0,0 +1,5 @@
+---
+title: reorder notification settings by noisy-ness
+merge_request:
+author: C.J. Jameson
+type: changed
diff --git a/changelogs/unreleased/osw-fallback-on-blank-refs.yml b/changelogs/unreleased/osw-fallback-on-blank-refs.yml
new file mode 100644
index 00000000000..039179f5829
--- /dev/null
+++ b/changelogs/unreleased/osw-fallback-on-blank-refs.yml
@@ -0,0 +1,5 @@
+---
+title: Avoid Gitaly RPC errors when fetching diff stats
+merge_request: 22995
+author:
+type: fixed
diff --git a/changelogs/unreleased/osw-gitaly-diff-stats-client.yml b/changelogs/unreleased/osw-gitaly-diff-stats-client.yml
deleted file mode 100644
index 9f280162409..00000000000
--- a/changelogs/unreleased/osw-gitaly-diff-stats-client.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add Gitaly diff stats RPC client
-merge_request: 21732
-author:
-type: changed
diff --git a/changelogs/unreleased/osw-use-diff-stats-rpc-on-comparison-views.yml b/changelogs/unreleased/osw-use-diff-stats-rpc-on-comparison-views.yml
deleted file mode 100644
index c71d4e58d6f..00000000000
--- a/changelogs/unreleased/osw-use-diff-stats-rpc-on-comparison-views.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Use stats RPC when comparing diffs
-merge_request: 21778
-author:
-type: fixed
diff --git a/changelogs/unreleased/project_identicon_fix.yml b/changelogs/unreleased/project_identicon_fix.yml
new file mode 100644
index 00000000000..de4876fc4a5
--- /dev/null
+++ b/changelogs/unreleased/project_identicon_fix.yml
@@ -0,0 +1,5 @@
+---
+title: Fix project identicon aligning Harry Kiselev
+merge_request: 23166
+author: Harry Kiselev
+type: other
diff --git a/changelogs/unreleased/rails5-active-record-class-value.yml b/changelogs/unreleased/rails5-active-record-class-value.yml
new file mode 100644
index 00000000000..9f9fdf10cd1
--- /dev/null
+++ b/changelogs/unreleased/rails5-active-record-class-value.yml
@@ -0,0 +1,5 @@
+---
+title: 'Rails5: Passing a class as a value in an Active Record query is deprecated'
+merge_request: 23164
+author: Jasper Maes
+type: other
diff --git a/changelogs/unreleased/rails5-deprecation-render-nothing.yml b/changelogs/unreleased/rails5-deprecation-render-nothing.yml
new file mode 100644
index 00000000000..32e2d5800c7
--- /dev/null
+++ b/changelogs/unreleased/rails5-deprecation-render-nothing.yml
@@ -0,0 +1,6 @@
+---
+title: render :nothing option is deprecated, Use head method to respond with empty
+ response body.
+merge_request: 23311
+author: Jasper Maes
+type: other
diff --git a/changelogs/unreleased/rails5-env-deprecated.yml b/changelogs/unreleased/rails5-env-deprecated.yml
new file mode 100644
index 00000000000..2f8573e2ff6
--- /dev/null
+++ b/changelogs/unreleased/rails5-env-deprecated.yml
@@ -0,0 +1,5 @@
+---
+title: 'Rails5: env is deprecated and will be removed from Rails 5.1'
+merge_request: 22626
+author: Jasper Maes
+type: other
diff --git a/changelogs/unreleased/rails5-fix-issue-move-service.yml b/changelogs/unreleased/rails5-fix-issue-move-service.yml
deleted file mode 100644
index 1e71544e587..00000000000
--- a/changelogs/unreleased/rails5-fix-issue-move-service.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: 'Rails 5: fix issue move service In rails 5, the attributes method for an enum
- returns the name instead of the database integer.'
-merge_request: 21616
-author: Jasper Maes
-type: other
diff --git a/changelogs/unreleased/remove-deployment-status-hack-from-backend.yml b/changelogs/unreleased/remove-deployment-status-hack-from-backend.yml
new file mode 100644
index 00000000000..2348bfab7d9
--- /dev/null
+++ b/changelogs/unreleased/remove-deployment-status-hack-from-backend.yml
@@ -0,0 +1,5 @@
+---
+title: Return real deployment status to frontend
+merge_request: 23270
+author:
+type: fixed
diff --git a/changelogs/unreleased/remove-duplicate-primary-button-in-dashboard-snippets.yml b/changelogs/unreleased/remove-duplicate-primary-button-in-dashboard-snippets.yml
new file mode 100644
index 00000000000..3a8b3a0df5d
--- /dev/null
+++ b/changelogs/unreleased/remove-duplicate-primary-button-in-dashboard-snippets.yml
@@ -0,0 +1,5 @@
+---
+title: Remove duplicate primary button in dashboard snippets on small viewports
+merge_request: 22902
+author: George Tsiolis
+type: fixed
diff --git a/changelogs/unreleased/remove-sidekiq.yml b/changelogs/unreleased/remove-sidekiq.yml
deleted file mode 100644
index c7bef974b89..00000000000
--- a/changelogs/unreleased/remove-sidekiq.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Remove sidekiq info from performance bar
-merge_request:
-author:
-type: removed
diff --git a/changelogs/unreleased/render-text-deprecated.yml b/changelogs/unreleased/render-text-deprecated.yml
new file mode 100644
index 00000000000..7dbbd13bcef
--- /dev/null
+++ b/changelogs/unreleased/render-text-deprecated.yml
@@ -0,0 +1,6 @@
+---
+title: 'Fix deprecation: render :text is deprecated because it does not actually render
+ a text/plain response'
+merge_request: 23425
+author: Jasper Maes
+type: other
diff --git a/changelogs/unreleased/rs-cherry-pick-api.yml b/changelogs/unreleased/rs-cherry-pick-api.yml
new file mode 100644
index 00000000000..ce844dfc939
--- /dev/null
+++ b/changelogs/unreleased/rs-cherry-pick-api.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve possible cherry pick API race condition
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/security-182-update-workhorse.yml b/changelogs/unreleased/security-182-update-workhorse.yml
new file mode 100644
index 00000000000..76850901b68
--- /dev/null
+++ b/changelogs/unreleased/security-182-update-workhorse.yml
@@ -0,0 +1,5 @@
+---
+title: Redact sensitive information on gitlab-workhorse log
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-2717-xss-username-autocomplete.yml b/changelogs/unreleased/security-2717-xss-username-autocomplete.yml
new file mode 100644
index 00000000000..d9b1015eeb4
--- /dev/null
+++ b/changelogs/unreleased/security-2717-xss-username-autocomplete.yml
@@ -0,0 +1,5 @@
+---
+title: Escape user fullname while rendering autocomplete template to prevent XSS
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-2736-prometheus-ssrf.yml b/changelogs/unreleased/security-2736-prometheus-ssrf.yml
new file mode 100644
index 00000000000..9d0dda8a75f
--- /dev/null
+++ b/changelogs/unreleased/security-2736-prometheus-ssrf.yml
@@ -0,0 +1,5 @@
+---
+title: Do not follow redirects in Prometheus service when making http requests to the configured api url
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-bvl-exposure-in-commits-list.yml b/changelogs/unreleased/security-bvl-exposure-in-commits-list.yml
new file mode 100644
index 00000000000..0361fb0c041
--- /dev/null
+++ b/changelogs/unreleased/security-bvl-exposure-in-commits-list.yml
@@ -0,0 +1,5 @@
+---
+title: Don't expose confidential information in commit message list
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-email-change-notification.yml b/changelogs/unreleased/security-email-change-notification.yml
new file mode 100644
index 00000000000..45075ff20bb
--- /dev/null
+++ b/changelogs/unreleased/security-email-change-notification.yml
@@ -0,0 +1,5 @@
+---
+title: Provide email notification when a user changes their email address
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-fix-pat-web-access.yml b/changelogs/unreleased/security-fix-pat-web-access.yml
new file mode 100644
index 00000000000..62ffb908fe5
--- /dev/null
+++ b/changelogs/unreleased/security-fix-pat-web-access.yml
@@ -0,0 +1,5 @@
+---
+title: Restrict Personal Access Tokens to API scope on web requests
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-fix-uri-xss-applications.yml b/changelogs/unreleased/security-fix-uri-xss-applications.yml
new file mode 100644
index 00000000000..0eaa1b1c4a3
--- /dev/null
+++ b/changelogs/unreleased/security-fix-uri-xss-applications.yml
@@ -0,0 +1,5 @@
+---
+title: Resolve reflected XSS in Ouath authorize window
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-fix-webhook-ssrf-ipv6.yml b/changelogs/unreleased/security-fix-webhook-ssrf-ipv6.yml
new file mode 100644
index 00000000000..32c85a2a7da
--- /dev/null
+++ b/changelogs/unreleased/security-fix-webhook-ssrf-ipv6.yml
@@ -0,0 +1,5 @@
+---
+title: Fix SSRF in project integrations
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-fj-crlf-injection.yml b/changelogs/unreleased/security-fj-crlf-injection.yml
new file mode 100644
index 00000000000..861167b8a6e
--- /dev/null
+++ b/changelogs/unreleased/security-fj-crlf-injection.yml
@@ -0,0 +1,5 @@
+---
+title: Fix CRLF vulnerability in Project hooks
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-guest-comments.yml b/changelogs/unreleased/security-guest-comments.yml
new file mode 100644
index 00000000000..2c99512433b
--- /dev/null
+++ b/changelogs/unreleased/security-guest-comments.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed ability to comment on locked/confidential issues.
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-guest-comments_2.yml b/changelogs/unreleased/security-guest-comments_2.yml
new file mode 100644
index 00000000000..be6f2d6a490
--- /dev/null
+++ b/changelogs/unreleased/security-guest-comments_2.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed ability of guest users to edit/delete comments on locked or confidential issues.
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-issue_51301.yml b/changelogs/unreleased/security-issue_51301.yml
new file mode 100644
index 00000000000..cf8ebb54b1c
--- /dev/null
+++ b/changelogs/unreleased/security-issue_51301.yml
@@ -0,0 +1,5 @@
+---
+title: Fix milestone promotion authorization check
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-mermaid-xss.yml b/changelogs/unreleased/security-mermaid-xss.yml
new file mode 100644
index 00000000000..bcf93ef37ff
--- /dev/null
+++ b/changelogs/unreleased/security-mermaid-xss.yml
@@ -0,0 +1,5 @@
+---
+title: Configure mermaid to not render HTML content in diagrams
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-pages-toctou-race.yml b/changelogs/unreleased/security-pages-toctou-race.yml
new file mode 100644
index 00000000000..1c055f6087f
--- /dev/null
+++ b/changelogs/unreleased/security-pages-toctou-race.yml
@@ -0,0 +1,6 @@
+---
+title: Fix a possible symlink time of check to time of use race condition in GitLab
+ Pages
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-private-group.yml b/changelogs/unreleased/security-private-group.yml
new file mode 100644
index 00000000000..dbb7794dfed
--- /dev/null
+++ b/changelogs/unreleased/security-private-group.yml
@@ -0,0 +1,6 @@
+---
+title: Removed ability to see private group names when the group id is entered in
+ the url.
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-stored-xss-for-environments.yml b/changelogs/unreleased/security-stored-xss-for-environments.yml
new file mode 100644
index 00000000000..5d78ca00942
--- /dev/null
+++ b/changelogs/unreleased/security-stored-xss-for-environments.yml
@@ -0,0 +1,5 @@
+---
+title: Fix stored XSS for Environments
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-xss-in-markdown-following-unrecognized-html-element.yml b/changelogs/unreleased/security-xss-in-markdown-following-unrecognized-html-element.yml
new file mode 100644
index 00000000000..3bd8123a346
--- /dev/null
+++ b/changelogs/unreleased/security-xss-in-markdown-following-unrecognized-html-element.yml
@@ -0,0 +1,5 @@
+---
+title: Fix possible XSS attack in Markdown urls with spaces
+merge_request: 2599
+author:
+type: security
diff --git a/changelogs/unreleased/sh-53180-append-path.yml b/changelogs/unreleased/sh-53180-append-path.yml
new file mode 100644
index 00000000000..64fae5522d8
--- /dev/null
+++ b/changelogs/unreleased/sh-53180-append-path.yml
@@ -0,0 +1,5 @@
+---
+title: Make sure there's only one slash as path separator
+merge_request: 22954
+author:
+type: other
diff --git a/changelogs/unreleased/sh-allow-key-id-in-params.yml b/changelogs/unreleased/sh-allow-key-id-in-params.yml
deleted file mode 100644
index 2be1cfb0ed3..00000000000
--- a/changelogs/unreleased/sh-allow-key-id-in-params.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Filter any parameters ending with "key" in logs
-merge_request: 21688
-author:
-type: changed
diff --git a/changelogs/unreleased/sh-bump-gems-security.yml b/changelogs/unreleased/sh-bump-gems-security.yml
new file mode 100644
index 00000000000..06489f6f979
--- /dev/null
+++ b/changelogs/unreleased/sh-bump-gems-security.yml
@@ -0,0 +1,5 @@
+---
+title: Bump nokogiri, loofah, and rack gems for security updates
+merge_request: 23204
+author:
+type: security
diff --git a/changelogs/unreleased/sh-bump-ruby-2-5-3.yml b/changelogs/unreleased/sh-bump-ruby-2-5-3.yml
new file mode 100644
index 00000000000..13cadc73e9c
--- /dev/null
+++ b/changelogs/unreleased/sh-bump-ruby-2-5-3.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade to Ruby 2.5.3
+merge_request: 2806
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-delete-tags-outside-transaction.yml b/changelogs/unreleased/sh-delete-tags-outside-transaction.yml
deleted file mode 100644
index 974da70251e..00000000000
--- a/changelogs/unreleased/sh-delete-tags-outside-transaction.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Delete container repository tags outside of transaction
-merge_request: 21679
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-disable-autocomplete-mirror-settings.yml b/changelogs/unreleased/sh-disable-autocomplete-mirror-settings.yml
new file mode 100644
index 00000000000..e42906e88f2
--- /dev/null
+++ b/changelogs/unreleased/sh-disable-autocomplete-mirror-settings.yml
@@ -0,0 +1,5 @@
+---
+title: Disable password autocomplete in mirror form fill
+merge_request: 23402
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-issue-38317.yml b/changelogs/unreleased/sh-fix-issue-38317.yml
new file mode 100644
index 00000000000..13fcb5b8f96
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-issue-38317.yml
@@ -0,0 +1,5 @@
+---
+title: Remove needless auto-capitalization on Wiki page titles
+merge_request: 23288
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-issue-51220.yml b/changelogs/unreleased/sh-fix-issue-51220.yml
new file mode 100644
index 00000000000..048f58611cb
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-issue-51220.yml
@@ -0,0 +1,5 @@
+---
+title: Handle force_remove_source_branch when creating merge request
+merge_request: 23281
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-issue-53783-ce.yml b/changelogs/unreleased/sh-fix-issue-53783-ce.yml
new file mode 100644
index 00000000000..10be1d81768
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-issue-53783-ce.yml
@@ -0,0 +1,5 @@
+---
+title: Fix enabling project deploy key for admins
+merge_request: 23043
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-mirrors-protected-branches.yml b/changelogs/unreleased/sh-fix-mirrors-protected-branches.yml
new file mode 100644
index 00000000000..627de25650d
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-mirrors-protected-branches.yml
@@ -0,0 +1,5 @@
+---
+title: Fix "protected branches only" checkbox not set properly at init
+merge_request: 23409
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-multipart-upload-signed-urls.yml b/changelogs/unreleased/sh-fix-multipart-upload-signed-urls.yml
deleted file mode 100644
index 994765bc1fd..00000000000
--- a/changelogs/unreleased/sh-fix-multipart-upload-signed-urls.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix object storage uploads not working with AWS v2
-merge_request: 21731
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-handle-string-null-bytes.yml b/changelogs/unreleased/sh-handle-string-null-bytes.yml
new file mode 100644
index 00000000000..edc045274e3
--- /dev/null
+++ b/changelogs/unreleased/sh-handle-string-null-bytes.yml
@@ -0,0 +1,5 @@
+---
+title: Gracefully handle references with null bytes
+merge_request: 23365
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-remove-local-sidekiq-admin-check.yml b/changelogs/unreleased/sh-remove-local-sidekiq-admin-check.yml
new file mode 100644
index 00000000000..3ec15908fc7
--- /dev/null
+++ b/changelogs/unreleased/sh-remove-local-sidekiq-admin-check.yml
@@ -0,0 +1,5 @@
+---
+title: Remove display of local Sidekiq process in /admin/sidekiq
+merge_request: 23118
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-support-adding-confirmed-emails.yml b/changelogs/unreleased/sh-support-adding-confirmed-emails.yml
deleted file mode 100644
index 1b64a1c62dc..00000000000
--- a/changelogs/unreleased/sh-support-adding-confirmed-emails.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add ability to skip user email confirmation with API
-merge_request: 21630
-author:
-type: added
diff --git a/changelogs/unreleased/sh-upgrade-katex-0-9-0.yml b/changelogs/unreleased/sh-upgrade-katex-0-9-0.yml
deleted file mode 100644
index 2a27e37c053..00000000000
--- a/changelogs/unreleased/sh-upgrade-katex-0-9-0.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Bump KaTeX version to 0.9.0
-merge_request: 21625
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-use-nakayoshi-fork.yml b/changelogs/unreleased/sh-use-nakayoshi-fork.yml
new file mode 100644
index 00000000000..5977d9b0974
--- /dev/null
+++ b/changelogs/unreleased/sh-use-nakayoshi-fork.yml
@@ -0,0 +1,5 @@
+---
+title: Improve memory performance by reducing dirty pages after fork()
+merge_request: 23169
+author:
+type: performance
diff --git a/changelogs/unreleased/sh-use-nokogiri-xml-backend.yml b/changelogs/unreleased/sh-use-nokogiri-xml-backend.yml
new file mode 100644
index 00000000000..6a82e32c416
--- /dev/null
+++ b/changelogs/unreleased/sh-use-nokogiri-xml-backend.yml
@@ -0,0 +1,5 @@
+---
+title: Use Nokogiri as the ActiveSupport XML backend
+merge_request: 23136
+author:
+type: performance
diff --git a/changelogs/unreleased/speed-up-relative-positioning.yml b/changelogs/unreleased/speed-up-relative-positioning.yml
new file mode 100644
index 00000000000..3bd865fb5de
--- /dev/null
+++ b/changelogs/unreleased/speed-up-relative-positioning.yml
@@ -0,0 +1,5 @@
+---
+title: Speed up issue board lists in groups with many projects
+merge_request:
+author:
+type: performance
diff --git a/changelogs/unreleased/switch-rails.yml b/changelogs/unreleased/switch-rails.yml
new file mode 100644
index 00000000000..4edf709dbd4
--- /dev/null
+++ b/changelogs/unreleased/switch-rails.yml
@@ -0,0 +1,5 @@
+---
+title: Switch to Rails 5
+merge_request: 21492
+author:
+type: other
diff --git a/changelogs/unreleased/tc-backfill-full-path-config.yml b/changelogs/unreleased/tc-backfill-full-path-config.yml
new file mode 100644
index 00000000000..4f06284d0e3
--- /dev/null
+++ b/changelogs/unreleased/tc-backfill-full-path-config.yml
@@ -0,0 +1,5 @@
+---
+title: Migration to write fullpath in all repository configs
+merge_request: 22322
+author:
+type: other
diff --git a/changelogs/unreleased/tc-repo-full-path-in-db.yml b/changelogs/unreleased/tc-repo-full-path-in-db.yml
new file mode 100644
index 00000000000..ead8feabeb9
--- /dev/null
+++ b/changelogs/unreleased/tc-repo-full-path-in-db.yml
@@ -0,0 +1,5 @@
+---
+title: Add model and relation to store repo full path in database
+merge_request: 23143
+author:
+type: added
diff --git a/changelogs/unreleased/triggermesh-phase2-external-ip.yml b/changelogs/unreleased/triggermesh-phase2-external-ip.yml
new file mode 100644
index 00000000000..582c8f6df2e
--- /dev/null
+++ b/changelogs/unreleased/triggermesh-phase2-external-ip.yml
@@ -0,0 +1,5 @@
+---
+title: Add an external IP address to the knative cluster application page
+merge_request:
+author: Chris Baumbauer
+type: fixed
diff --git a/changelogs/unreleased/triggermesh-phase2-knative-description.yml b/changelogs/unreleased/triggermesh-phase2-knative-description.yml
new file mode 100644
index 00000000000..c6cee1984d5
--- /dev/null
+++ b/changelogs/unreleased/triggermesh-phase2-knative-description.yml
@@ -0,0 +1,5 @@
+---
+title: Modify the wording for the knative cluster application to match upstream
+merge_request: 23289
+author: Chris Baumbauer
+type: fixed
diff --git a/changelogs/unreleased/triggermesh-phase2-serverless.yml b/changelogs/unreleased/triggermesh-phase2-serverless.yml
new file mode 100644
index 00000000000..bee2b5e1e2c
--- /dev/null
+++ b/changelogs/unreleased/triggermesh-phase2-serverless.yml
@@ -0,0 +1,5 @@
+---
+title: Add knative client to kubeclient library
+merge_request: 22968
+author: cab105
+type: added
diff --git a/changelogs/unreleased/unicorn-monkey-patch.yml b/changelogs/unreleased/unicorn-monkey-patch.yml
new file mode 100644
index 00000000000..6b0e00ca291
--- /dev/null
+++ b/changelogs/unreleased/unicorn-monkey-patch.yml
@@ -0,0 +1,5 @@
+---
+title: Add monkey patch to unicorn to fix eof? problem
+merge_request: 23385
+author:
+type: fixed
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-version.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-version.yml
new file mode 100644
index 00000000000..9051e4f79c8
--- /dev/null
+++ b/changelogs/unreleased/update-gitlab-runner-helm-chart-version.yml
@@ -0,0 +1,5 @@
+---
+title: Update used version of Runner Helm Chart to 0.1.38
+merge_request: 23304
+author:
+type: other
diff --git a/changelogs/unreleased/upgrade_kubeclient_400.yml b/changelogs/unreleased/upgrade_kubeclient_400.yml
new file mode 100644
index 00000000000..edb38710e6a
--- /dev/null
+++ b/changelogs/unreleased/upgrade_kubeclient_400.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade kubeclient to 4.0.0
+merge_request: 23261
+author: Praveen Arimbrathodiyil @pravi
+type: other
diff --git a/changelogs/unreleased/validate-foreign-keys-being-indexed.yml b/changelogs/unreleased/validate-foreign-keys-being-indexed.yml
new file mode 100644
index 00000000000..6608a93c08f
--- /dev/null
+++ b/changelogs/unreleased/validate-foreign-keys-being-indexed.yml
@@ -0,0 +1,5 @@
+---
+title: Validate foreign keys being created and indexed for column with _id
+merge_request: 22808
+author:
+type: performance
diff --git a/changelogs/unreleased/vendor-auto-devops-gitlab-ci-fix-503-on-deploy.yml b/changelogs/unreleased/vendor-auto-devops-gitlab-ci-fix-503-on-deploy.yml
deleted file mode 100644
index 11ebf567e9d..00000000000
--- a/changelogs/unreleased/vendor-auto-devops-gitlab-ci-fix-503-on-deploy.yml
+++ /dev/null
@@ -1,6 +0,0 @@
----
-title: Vendor Auto-DevOps.gitlab-ci.yml to fix bug where the deploy job does not wait
- for Deployment to complete
-merge_request: 21713
-author:
-type: fixed
diff --git a/changelogs/unreleased/vendor-gitlab-ci-auto-devops-yml.yml b/changelogs/unreleased/vendor-gitlab-ci-auto-devops-yml.yml
deleted file mode 100644
index 98d0e24c00a..00000000000
--- a/changelogs/unreleased/vendor-gitlab-ci-auto-devops-yml.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Make AutoDevOps work behind proxy
-merge_request: 21775
-author: Sergej - @kinolaev
-type: other
diff --git a/changelogs/unreleased/winh-collapse-discussions.yml b/changelogs/unreleased/winh-collapse-discussions.yml
new file mode 100644
index 00000000000..19d04506318
--- /dev/null
+++ b/changelogs/unreleased/winh-collapse-discussions.yml
@@ -0,0 +1,5 @@
+---
+title: Fix collapsing discussion replies
+merge_request: 23462
+author:
+type: fixed
diff --git a/changelogs/unreleased/winh-merge-request-commit-discussion.yml b/changelogs/unreleased/winh-merge-request-commit-discussion.yml
new file mode 100644
index 00000000000..b0c6264369b
--- /dev/null
+++ b/changelogs/unreleased/winh-merge-request-commit-discussion.yml
@@ -0,0 +1,5 @@
+---
+title: Display commit ID for commit diff discussion on merge request
+merge_request: 23370
+author:
+type: fixed
diff --git a/changelogs/unreleased/workhorse-7-3-0.yml b/changelogs/unreleased/workhorse-7-3-0.yml
new file mode 100644
index 00000000000..6708b8a3cbb
--- /dev/null
+++ b/changelogs/unreleased/workhorse-7-3-0.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade GitLab Workhorse to v7.3.0
+merge_request: 23489
+author:
+type: other
diff --git a/changelogs/unreleased/zj-improve-gitaly-pb.yml b/changelogs/unreleased/zj-improve-gitaly-pb.yml
new file mode 100644
index 00000000000..506a0303d8a
--- /dev/null
+++ b/changelogs/unreleased/zj-improve-gitaly-pb.yml
@@ -0,0 +1,5 @@
+---
+title: Show what RPC is called in the performance bar
+merge_request: 23140
+author:
+type: other
diff --git a/changelogs/unreleased/zj-remove-broken-storage.yml b/changelogs/unreleased/zj-remove-broken-storage.yml
new file mode 100644
index 00000000000..9df87b40e09
--- /dev/null
+++ b/changelogs/unreleased/zj-remove-broken-storage.yml
@@ -0,0 +1,5 @@
+---
+title: Remove obsolete gitlab_shell rake tasks
+merge_request: 22417
+author:
+type: removed
diff --git a/config.ru b/config.ru
index 405d01863ac..a5d055334dd 100644
--- a/config.ru
+++ b/config.ru
@@ -13,6 +13,10 @@ if defined?(Unicorn)
# Max memory size (RSS) per worker
use Unicorn::WorkerKiller::Oom, min, max
end
+
+ # Monkey patch for fixing Rack 2.0.6 bug:
+ # https://gitlab.com/gitlab-org/gitlab-ee/issues/8539
+ Unicorn::StreamInput.send(:public, :eof?) # rubocop:disable GitlabSecurity/PublicSend
end
require ::File.expand_path('../config/environment', __FILE__)
diff --git a/config/application.rb b/config/application.rb
index 9074cf02c46..63a5b483fc2 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -8,7 +8,7 @@ module Gitlab
# This method is used for smooth upgrading from the current Rails 4.x to Rails 5.0.
# https://gitlab.com/gitlab-org/gitlab-ce/issues/14286
def self.rails5?
- ENV["RAILS5"].in?(%w[1 true])
+ !%w[0 false].include?(ENV["RAILS5"])
end
class Application < Rails::Application
@@ -26,6 +26,9 @@ module Gitlab
# setting disabled
require_dependency Rails.root.join('lib/mysql_zero_date')
+ # This can be removed when we drop support for rails 4
+ require_dependency Rails.root.join('lib/rails4_migration_version')
+
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
@@ -66,6 +69,12 @@ module Gitlab
# config.i18n.default_locale = :de
config.i18n.enforce_available_locales = false
+ # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
+ # the I18n.default_locale when a translation can not be found).
+ # We have to explicitly set default locale since 1.1.0 - see:
+ # https://github.com/svenfuchs/i18n/pull/415
+ config.i18n.fallbacks = [:en]
+
# Translation for AR attrs is not working well for POROs like WikiPage
config.gettext_i18n_rails.use_for_active_record_attributes = false
@@ -94,6 +103,9 @@ module Gitlab
# - Webhook URLs (:hook)
# - Sentry DSN (:sentry_dsn)
# - File content from Web Editor (:content)
+ #
+ # NOTE: It is **IMPORTANT** to also update gitlab-workhorse's filter when adding parameters here to not
+ # introduce another security vulnerability: https://gitlab.com/gitlab-org/gitlab-workhorse/issues/182
config.filter_parameters += [/token$/, /password/, /secret/, /key$/]
config.filter_parameters += %i(
certificate
@@ -144,7 +156,7 @@ module Gitlab
config.assets.precompile << "errors.css"
# Import gitlab-svgs directly from vendored directory
- config.assets.paths << "#{config.root}/node_modules/@gitlab-org/gitlab-svgs/dist"
+ config.assets.paths << "#{config.root}/node_modules/@gitlab/svgs/dist"
config.assets.precompile << "icons.svg"
config.assets.precompile << "icons.json"
config.assets.precompile << "illustrations/*.svg"
@@ -158,6 +170,9 @@ module Gitlab
config.action_view.sanitized_allowed_protocols = %w(smb)
+ # Nokogiri is significantly faster and uses less memory than REXML
+ ActiveSupport::XmlMini.backend = 'Nokogiri'
+
# This middleware needs to precede ActiveRecord::QueryCache and other middlewares that
# connect to the database.
config.middleware.insert_after Rails::Rack::Logger, ::Gitlab::Middleware::BasicHealthCheck
diff --git a/config/boot.rb b/config/boot.rb
index 655c54ddb84..725473ac7f6 100644
--- a/config/boot.rb
+++ b/config/boot.rb
@@ -1,10 +1,10 @@
def rails5?
- %w[1 true].include?(ENV["RAILS5"])
+ !%w[0 false].include?(ENV["RAILS5"])
end
require 'rubygems' unless rails5?
-gemfile = rails5? ? "Gemfile.rails5" : "Gemfile"
+gemfile = rails5? ? "Gemfile" : "Gemfile.rails4"
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../#{gemfile}", __dir__)
# Set up gems listed in the Gemfile.
@@ -12,5 +12,5 @@ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
begin
require 'bootsnap/setup'
rescue LoadError
- # bootsnap is optional dependency, so if we don't have it it's fine
+ # bootsnap is an optional dependency, so if we don't have it, it's fine
end
diff --git a/config/dependency_decisions.yml b/config/dependency_decisions.yml
index 664035831a5..84d47bd52ad 100644
--- a/config/dependency_decisions.yml
+++ b/config/dependency_decisions.yml
@@ -461,7 +461,7 @@
:versions: []
:when: 2017-09-13 17:31:16.425819400 Z
- - :license
- - "@gitlab-org/gitlab-svgs"
+ - "@gitlab/svgs"
- MIT
- :who: Tim Zallmann
:why: Our own library - GitLab License https://gitlab.com/gitlab-org/gitlab-svgs
@@ -544,13 +544,6 @@
:why: https://github.com/xtuc/webassemblyjs/blob/master/LICENSE
:versions: []
:when: 2018-06-08 05:30:56.764116000 Z
-- - :license
- - "@gitlab-org/gitlab-ui"
- - MIT
- - :who: Clement Ho
- :why: Our own library
- :versions: []
- :when: 2018-07-17 21:02:54.529227000 Z
- - :approve
- lz-string
- :who: Phil Hughes
@@ -585,3 +578,17 @@
and are therefore exempt.
:versions: []
:when: 2018-08-30 12:06:35.668181000 Z
+- - :approve
+ - caniuse-lite
+ - :who: Mike Greiling
+ :why: CC-BY-4.0 license. Tool only used during build process, code is not present
+ in compiled/distributed product so attribution not needed.
+ :versions: []
+ :when: 2018-10-02 19:23:11.221660000 Z
+- - :approve
+ - node-releases
+ - :who: Mike Greiling
+ :why: CC-BY-4.0 license. Tool only used during build process, code is not present
+ in compiled/distributed product so attribution not needed.
+ :versions: []
+ :when: 2018-10-02 19:23:54.840151000 Z
diff --git a/config/environment.rb b/config/environment.rb
index 5d35937f7c6..3a52656a2c1 100644
--- a/config/environment.rb
+++ b/config/environment.rb
@@ -1,10 +1,10 @@
# Load the rails application
# Remove this condition when upgraded to rails 5.0.
-if %w[1 true].include?(ENV["RAILS5"])
- require_relative 'application'
-else
+if %w[0 false].include?(ENV["RAILS5"])
require File.expand_path('application', __dir__)
+else
+ require_relative 'application'
end
# Initialize the rails application
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 23790b84e3c..494ddd72556 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -45,4 +45,6 @@ Rails.application.configure do
# Do not log asset requests
config.assets.quiet = true
+
+ config.allow_concurrency = defined?(::Puma)
end
diff --git a/config/environments/production.rb b/config/environments/production.rb
index 9941987929c..49a4e873093 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -65,10 +65,6 @@ Rails.application.configure do
# Enable threaded mode
# config.threadsafe! unless $rails_rake_task
- # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
- # the I18n.default_locale when a translation can not be found)
- config.i18n.fallbacks = true
-
# Send deprecation notices to registered listeners
config.active_support.deprecation = :notify
@@ -83,5 +79,5 @@ Rails.application.configure do
config.eager_load = true
- config.allow_concurrency = false
+ config.allow_concurrency = defined?(::Puma)
end
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 67337f4b82f..58b7c248aaf 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -114,6 +114,9 @@ production: &base
# The default is 'shared/cache/archive/' relative to the root of the Rails app.
# repository_downloads_path: shared/cache/archive/
+ ## Impersonation settings
+ impersonation_enabled: true
+
## Reply by email
# Allow users to comment on issues and merge requests by replying to notification emails.
# For documentation on how to set this up, see http://doc.gitlab.com/ce/administration/reply_by_email.html
@@ -207,9 +210,14 @@ production: &base
# endpoint: 'http://127.0.0.1:9000' # default: nil
# path_style: true # Use 'host/bucket_name/object' instead of 'bucket_name.host/object'
+ ## Packages (maven repository so far)
+ packages:
+ enabled: false
+
## GitLab Pages
pages:
enabled: false
+ access_control: false
# The location where pages are stored (default: shared/pages).
# path: shared/pages
@@ -586,7 +594,7 @@ production: &base
gitaly:
# Path to the directory containing Gitaly client executables.
client_path: /home/git/gitaly/bin
- # Default Gitaly authentication token. Can be overriden per storage. Can
+ # Default Gitaly authentication token. Can be overridden per storage. Can
# be left blank when Gitaly is running locally on a Unix socket, which
# is the normal way to deploy Gitaly.
token:
@@ -771,9 +779,6 @@ test:
default:
path: tmp/tests/repositories/
gitaly_address: unix:tmp/tests/gitaly/gitaly.socket
- broken:
- path: tmp/tests/non-existent-repositories
- gitaly_address: unix:tmp/tests/gitaly/gitaly.socket
gitaly:
client_path: tmp/tests/gitaly
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 0caa4962128..82e3b490378 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -153,6 +153,7 @@ Settings.gitlab['domain_whitelist'] ||= []
Settings.gitlab['import_sources'] ||= Gitlab::ImportSources.values
Settings.gitlab['trusted_proxies'] ||= []
Settings.gitlab['no_todos_messages'] ||= YAML.load_file(Rails.root.join('config', 'no_todos_messages.yml'))
+Settings.gitlab['impersonation_enabled'] ||= true if Settings.gitlab['impersonation_enabled'].nil?
Settings.gitlab['usage_ping_enabled'] = true if Settings.gitlab['usage_ping_enabled'].nil?
#
@@ -200,6 +201,7 @@ Settings.registry['path'] = Settings.absolute(Settings.registry['path
#
Settings['pages'] ||= Settingslogic.new({})
Settings.pages['enabled'] = false if Settings.pages['enabled'].nil?
+Settings.pages['access_control'] = false if Settings.pages['access_control'].nil?
Settings.pages['path'] = Settings.absolute(Settings.pages['path'] || File.join(Settings.shared['path'], "pages"))
Settings.pages['https'] = false if Settings.pages['https'].nil?
Settings.pages['host'] ||= "example.com"
diff --git a/config/initializers/7_prometheus_metrics.rb b/config/initializers/7_prometheus_metrics.rb
index 146c4b1e024..8052880cc3d 100644
--- a/config/initializers/7_prometheus_metrics.rb
+++ b/config/initializers/7_prometheus_metrics.rb
@@ -26,9 +26,25 @@ Sidekiq.configure_server do |config|
end
if !Rails.env.test? && Gitlab::Metrics.prometheus_metrics_enabled?
- unless Sidekiq.server?
- Gitlab::Metrics::Samplers::UnicornSampler.initialize_instance(Settings.monitoring.unicorn_sampler_interval).start
+ Gitlab::Cluster::LifecycleEvents.on_worker_start do
+ defined?(::Prometheus::Client.reinitialize_on_pid_change) && Prometheus::Client.reinitialize_on_pid_change
+
+ unless Sidekiq.server?
+ Gitlab::Metrics::Samplers::UnicornSampler.initialize_instance(Settings.monitoring.unicorn_sampler_interval).start
+ end
+
+ Gitlab::Metrics::Samplers::RubySampler.initialize_instance(Settings.monitoring.ruby_sampler_interval).start
end
+end
- Gitlab::Metrics::Samplers::RubySampler.initialize_instance(Settings.monitoring.ruby_sampler_interval).start
+Gitlab::Cluster::LifecycleEvents.on_master_restart do
+ # The following is necessary to ensure stale Prometheus metrics don't
+ # accumulate over time. It needs to be done in this hook as opposed to
+ # inside an init script to ensure metrics files aren't deleted after new
+ # unicorn workers start after a SIGUSR2 is received.
+ prometheus_multiproc_dir = ENV['prometheus_multiproc_dir']
+ if prometheus_multiproc_dir
+ old_metrics = Dir[File.join(prometheus_multiproc_dir, '*.db')]
+ FileUtils.rm_rf(old_metrics)
+ end
end
diff --git a/config/initializers/8_metrics.rb b/config/initializers/8_metrics.rb
index 4d8d35bf6cf..468f80939d7 100644
--- a/config/initializers/8_metrics.rb
+++ b/config/initializers/8_metrics.rb
@@ -3,7 +3,6 @@
# that we can stub it for testing, as it is only called when metrics are
# enabled.
#
-# rubocop:disable Metrics/AbcSize
def instrument_classes(instrumentation)
instrumentation.instrument_instance_methods(Gitlab::Shell)
@@ -48,16 +47,6 @@ def instrument_classes(instrumentation)
instrumentation.instrument_methods(Premailer::Adapter::Nokogiri)
instrumentation.instrument_instance_methods(Premailer::Adapter::Nokogiri)
- [
- :Blame, :Branch, :BranchCollection, :Blob, :Commit, :Diff, :Repository,
- :Tag, :TagCollection, :Tree
- ].each do |name|
- const = Rugged.const_get(name)
-
- instrumentation.instrument_methods(const)
- instrumentation.instrument_instance_methods(const)
- end
-
instrumentation.instrument_methods(Banzai::Renderer)
instrumentation.instrument_methods(Banzai::Querying)
@@ -101,7 +90,6 @@ def instrument_classes(instrumentation)
# Needed for https://gitlab.com/gitlab-org/gitlab-ce/issues/30224#note_32306159
instrumentation.instrument_instance_method(MergeRequestDiff, :load_commits)
end
-# rubocop:enable Metrics/AbcSize
# With prometheus enabled by default this breaks all specs
# that stubs methods using `any_instance_of` for the models reloaded here.
@@ -110,7 +98,11 @@ end
# check: https://github.com/rspec/rspec-mocks#settings-mocks-or-stubs-on-any-instance-of-a-class
#
# Related issue: https://gitlab.com/gitlab-org/gitlab-ce/issues/33587
-if Gitlab::Metrics.enabled? && !Rails.env.test?
+#
+# In development mode, we turn off eager loading when we're running
+# `rails generate migration` because eager loading short-circuits the
+# loading of our custom migration templates.
+if Gitlab::Metrics.enabled? && !Rails.env.test? && !(Rails.env.development? && defined?(Rails::Generators))
require 'pathname'
require 'influxdb'
require 'connection_pool'
@@ -170,7 +162,9 @@ if Gitlab::Metrics.enabled? && !Rails.env.test?
GC::Profiler.enable
- Gitlab::Metrics::Samplers::InfluxSampler.initialize_instance.start
+ Gitlab::Cluster::LifecycleEvents.on_worker_start do
+ Gitlab::Metrics::Samplers::InfluxSampler.initialize_instance.start
+ end
module TrackNewRedisConnections
def connect(*args)
diff --git a/config/initializers/action_dispatch_http_mime_negotiation.rb b/config/initializers/action_dispatch_http_mime_negotiation.rb
new file mode 100644
index 00000000000..bdf5b0babfb
--- /dev/null
+++ b/config/initializers/action_dispatch_http_mime_negotiation.rb
@@ -0,0 +1,19 @@
+# Starting with Rails 5, Rails tries to determine the request format based on
+# the extension of the full URL path if no explicit `format` param or `Accept`
+# header is provided, like when simply browsing to a page in your browser.
+#
+# This is undesireable in GitLab, because many of our paths will end in a ref or
+# blob name that can end with any extension, while these pages should still be
+# presented as HTML unless otherwise specified.
+
+# We override `format_from_path_extension` to disable this behavior.
+
+module ActionDispatch
+ module Http
+ module MimeNegotiation
+ def format_from_path_extension
+ nil
+ end
+ end
+ end
+end
diff --git a/config/initializers/active_record_lifecycle.rb b/config/initializers/active_record_lifecycle.rb
new file mode 100644
index 00000000000..7fa37121efc
--- /dev/null
+++ b/config/initializers/active_record_lifecycle.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+# Don't handle sidekiq configuration as it
+# has its own special active record configuration here
+if defined?(ActiveRecord::Base) && !Sidekiq.server?
+ Gitlab::Cluster::LifecycleEvents.on_worker_start do
+ ActiveSupport.on_load(:active_record) do
+ ActiveRecord::Base.establish_connection
+
+ Rails.logger.debug("ActiveRecord connection established")
+ end
+ end
+end
+
+if defined?(ActiveRecord::Base)
+ Gitlab::Cluster::LifecycleEvents.on_before_fork do
+ # the following is highly recommended for Rails + "preload_app true"
+ # as there's no need for the master process to hold a connection
+ ActiveRecord::Base.connection.disconnect!
+
+ Rails.logger.debug("ActiveRecord connection disconnected")
+ end
+end
diff --git a/config/initializers/asset_sync.rb b/config/initializers/asset_sync.rb
deleted file mode 100644
index 7f3934853fa..00000000000
--- a/config/initializers/asset_sync.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-AssetSync.configure do |config|
- # Disable the asset_sync gem by default. If it is enabled, but not configured,
- # asset_sync will cause the build to fail.
- config.enabled = if ENV.has_key?('ASSET_SYNC_ENABLED')
- ENV['ASSET_SYNC_ENABLED'] == 'true'
- else
- false
- end
-
- # Pulled from https://github.com/AssetSync/asset_sync/blob/v2.2.0/lib/asset_sync/engine.rb#L15-L40
- # This allows us to disable asset_sync by default and configure through environment variables
- # Updates to asset_sync gem should be checked
- config.fog_provider = ENV['FOG_PROVIDER'] if ENV.has_key?('FOG_PROVIDER')
- config.fog_directory = ENV['FOG_DIRECTORY'] if ENV.has_key?('FOG_DIRECTORY')
- config.fog_region = ENV['FOG_REGION'] if ENV.has_key?('FOG_REGION')
-
- config.aws_access_key_id = ENV['ASSETS_AWS_ACCESS_KEY_ID'] if ENV.has_key?('ASSETS_AWS_ACCESS_KEY_ID')
- config.aws_secret_access_key = ENV['ASSETS_AWS_SECRET_ACCESS_KEY'] if ENV.has_key?('ASSETS_AWS_SECRET_ACCESS_KEY')
- config.aws_reduced_redundancy = ENV['AWS_REDUCED_REDUNDANCY'] == true if ENV.has_key?('AWS_REDUCED_REDUNDANCY')
-
- config.rackspace_username = ENV['RACKSPACE_USERNAME'] if ENV.has_key?('RACKSPACE_USERNAME')
- config.rackspace_api_key = ENV['RACKSPACE_API_KEY'] if ENV.has_key?('RACKSPACE_API_KEY')
-
- config.google_storage_access_key_id = ENV['GOOGLE_STORAGE_ACCESS_KEY_ID'] if ENV.has_key?('GOOGLE_STORAGE_ACCESS_KEY_ID')
- config.google_storage_secret_access_key = ENV['GOOGLE_STORAGE_SECRET_ACCESS_KEY'] if ENV.has_key?('GOOGLE_STORAGE_SECRET_ACCESS_KEY')
-
- config.existing_remote_files = ENV['ASSET_SYNC_EXISTING_REMOTE_FILES'] || "keep"
-
- config.gzip_compression = (ENV['ASSET_SYNC_GZIP_COMPRESSION'] == 'true') if ENV.has_key?('ASSET_SYNC_GZIP_COMPRESSION')
- config.manifest = (ENV['ASSET_SYNC_MANIFEST'] == 'true') if ENV.has_key?('ASSET_SYNC_MANIFEST')
-end
diff --git a/config/initializers/attr_encrypted_no_db_connection.rb b/config/initializers/attr_encrypted_no_db_connection.rb
index e007666b852..7ad458929db 100644
--- a/config/initializers/attr_encrypted_no_db_connection.rb
+++ b/config/initializers/attr_encrypted_no_db_connection.rb
@@ -1,7 +1,18 @@
module AttrEncrypted
module Adapters
module ActiveRecord
- module DBConnectionQuerier
+ module GitlabMonkeyPatches
+ # Prevent attr_encrypted from defining virtual accessors for encryption
+ # data when the code and schema are out of sync. See this issue for more
+ # details: https://github.com/attr-encrypted/attr_encrypted/issues/332
+ def attribute_instance_methods_as_symbols_available?
+ false
+ end
+
+ # Prevent attr_encrypted from checking out a database connection
+ # indefinitely. The result of this method is only used when the former
+ # is true, but it is called unconditionally, so there is still value to
+ # ensuring the connection is released
def attribute_instance_methods_as_symbols
# Use with_connection so the connection doesn't stay pinned to the thread.
connected = ::ActiveRecord::Base.connection_pool.with_connection(&:active?) rescue false
@@ -15,7 +26,16 @@ module AttrEncrypted
end
end
end
- prepend DBConnectionQuerier
end
end
end
+
+# As of v3.1.0, the attr_encrypted gem defines the AttrEncrypted and
+# AttrEncrypted::Adapters::ActiveRecord modules, and uses "extend" to mix them
+# into the ActiveRecord::Base class. This intervention overrides utility methods
+# defined by attr_encrypted to fix two bugs, as detailed above.
+#
+# The methods are used here: https://github.com/attr-encrypted/attr_encrypted/blob/3.1.0/lib/attr_encrypted.rb#L145-158
+ActiveSupport.on_load(:active_record) do
+ extend AttrEncrypted::Adapters::ActiveRecord::GitlabMonkeyPatches
+end
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
index 179e00cdbd0..67eabb0b4fc 100644
--- a/config/initializers/devise.rb
+++ b/config/initializers/devise.rb
@@ -103,6 +103,9 @@ Devise.setup do |config|
# Send a notification email when the user's password is changed
config.send_password_change_notification = true
+ # Send a notification email when the user's email is changed
+ config.send_email_changed_notification = true
+
# ==> Configuration for :validatable
# Range for password length. Default is 6..128.
config.password_length = 8..128
diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb
index f321b4ea763..6be5c00daaa 100644
--- a/config/initializers/doorkeeper.rb
+++ b/config/initializers/doorkeeper.rb
@@ -48,6 +48,13 @@ Doorkeeper.configure do
#
force_ssl_in_redirect_uri false
+ # Specify what redirect URI's you want to block during Application creation.
+ # Any redirect URI is whitelisted by default.
+ #
+ # You can use this option in order to forbid URI's with 'javascript' scheme
+ # for example.
+ forbid_redirect_uri { |uri| %w[data vbscript javascript].include?(uri.scheme.to_s.downcase) }
+
# Provide support for an owner to be assigned to each registered application (disabled by default)
# Optional parameter confirmation: true (default false) if you want to enforce ownership of
# a registered application
diff --git a/config/initializers/fill_shards.rb b/config/initializers/fill_shards.rb
new file mode 100644
index 00000000000..18e067c8854
--- /dev/null
+++ b/config/initializers/fill_shards.rb
@@ -0,0 +1,3 @@
+if Shard.connected? && !Gitlab::Database.read_only?
+ Shard.populate!
+end
diff --git a/config/initializers/gollum.rb b/config/initializers/gollum.rb
deleted file mode 100644
index ea9cc151a57..00000000000
--- a/config/initializers/gollum.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# WARNING changes in this file must be manually propagated to gitaly-ruby.
-#
-# https://gitlab.com/gitlab-org/gitaly/blob/master/ruby/lib/gitlab/gollum.rb
-
-module Gollum
- GIT_ADAPTER = "rugged".freeze
-end
-require "gollum-lib"
-
-module Gollum
- class Page
- def text_data(encoding = nil)
- data = if raw_data.respond_to?(:encoding)
- raw_data.force_encoding(encoding || Encoding::UTF_8)
- else
- raw_data
- end
-
- Gitlab::EncodingHelper.encode!(data)
- end
- end
-end
-
-Rails.application.configure do
- config.after_initialize do
- Gollum::Page.per_page = Kaminari.config.default_per_page
- end
-end
diff --git a/config/initializers/hipchat_client_patch.rb b/config/initializers/hipchat_client_patch.rb
new file mode 100644
index 00000000000..aec265312bb
--- /dev/null
+++ b/config/initializers/hipchat_client_patch.rb
@@ -0,0 +1,14 @@
+# This monkey patches the HTTParty used in https://github.com/hipchat/hipchat-rb.
+module HipChat
+ class Client
+ connection_adapter ::Gitlab::ProxyHTTPConnectionAdapter
+ end
+
+ class Room
+ connection_adapter ::Gitlab::ProxyHTTPConnectionAdapter
+ end
+
+ class User
+ connection_adapter ::Gitlab::ProxyHTTPConnectionAdapter
+ end
+end
diff --git a/config/initializers/kubeclient.rb b/config/initializers/kubeclient.rb
index 7f115268b37..f8fe1156aaa 100644
--- a/config/initializers/kubeclient.rb
+++ b/config/initializers/kubeclient.rb
@@ -1,16 +1,22 @@
class Kubeclient::Client
- # We need to monkey patch this method until
- # https://github.com/abonas/kubeclient/pull/323 is merged
- def proxy_url(kind, name, port, namespace = '')
- discover unless @discovered
- entity_name_plural =
- if %w[services pods nodes].include?(kind.to_s)
- kind.to_s
- else
- @entities[kind.to_s].resource_name
- end
-
- ns_prefix = build_namespace_prefix(namespace)
- rest_client["#{ns_prefix}#{entity_name_plural}/#{name}:#{port}/proxy"].url
+ # Monkey patch to set `max_redirects: 0`, so that kubeclient
+ # does not follow redirects and expose internal services.
+ # See https://gitlab.com/gitlab-org/gitlab-ce/issues/53158
+ def create_rest_client(path = nil)
+ path ||= @api_endpoint.path
+ options = {
+ ssl_ca_file: @ssl_options[:ca_file],
+ ssl_cert_store: @ssl_options[:cert_store],
+ verify_ssl: @ssl_options[:verify_ssl],
+ ssl_client_cert: @ssl_options[:client_cert],
+ ssl_client_key: @ssl_options[:client_key],
+ proxy: @http_proxy_uri,
+ user: @auth_options[:username],
+ password: @auth_options[:password],
+ open_timeout: @timeouts[:open],
+ read_timeout: @timeouts[:read],
+ max_redirects: 0
+ }
+ RestClient::Resource.new(@api_endpoint.merge(path).to_s, options)
end
end
diff --git a/config/initializers/macos.rb b/config/initializers/macos.rb
new file mode 100644
index 00000000000..f410af6ed47
--- /dev/null
+++ b/config/initializers/macos.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+if /darwin/ =~ RUBY_PLATFORM
+ Gitlab::Cluster::LifecycleEvents.on_before_fork do
+ require 'fiddle'
+
+ # Dynamically load Foundation.framework, ~implicitly~ initialising
+ # the Objective-C runtime before any forking happens in Unicorn
+ #
+ # From https://bugs.ruby-lang.org/issues/14009
+ Fiddle.dlopen '/System/Library/Frameworks/Foundation.framework/Foundation'
+ end
+end
diff --git a/config/initializers/mysql_set_length_for_binary_indexes.rb b/config/initializers/mysql_set_length_for_binary_indexes.rb
index 81ed2fb83de..0445d8fcae2 100644
--- a/config/initializers/mysql_set_length_for_binary_indexes.rb
+++ b/config/initializers/mysql_set_length_for_binary_indexes.rb
@@ -24,28 +24,46 @@ if defined?(ActiveRecord::ConnectionAdapters::Mysql2Adapter)
ActiveRecord::ConnectionAdapters::Mysql2Adapter.send(:prepend, MysqlSetLengthForBinaryIndex)
end
-if Gitlab.rails5?
- module MysqlSetLengthForBinaryIndexAndIgnorePostgresOptionsForSchema
- # This method is used in Rails 5 schema loading as t.index
- def index(column_names, options = {})
- options[:length] ||= {}
- Array(column_names).each do |column_name|
- column = columns.find { |c| c.name == column_name }
-
- if column&.type == :binary
- options[:length][column_name] = 20
- end
- end
+module MysqlSetLengthForBinaryIndexAndIgnorePostgresOptionsForSchema
+ # This method is used in Rails 5 schema loading as t.index
+ def index(column_names, options = {})
+ # Ignore indexes that use opclasses,
+ # also see config/initializers/mysql_ignore_postgresql_options.rb
+ if options[:opclasses]
+ warn "WARNING: index on columns #{column_names} uses unsupported option, skipping."
+ return
+ end
+
+ # when running rails 4 with rails 5 schema, rails 4 doesn't support multiple
+ # indexes on the same set of columns. Mysql doesn't support partial indexes, so if
+ # an index already exists and we add another index, skip it if it's partial:
+ # see https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21492#note_102821326
+ if !Gitlab.rails5? && indexes[column_names] && options[:where]
+ warn "WARNING: index on columns #{column_names} already exists and partial index is not supported, skipping."
+ return
+ end
+
+ options[:length] ||= {}
+ Array(column_names).each do |column_name|
+ column = columns.find { |c| c.name == column_name }
- # Ignore indexes that use opclasses,
- # also see config/initializers/mysql_ignore_postgresql_options.rb
- unless options[:opclasses]
- super(column_names, options)
+ if column&.type == :binary
+ options[:length][column_name] = 20
end
end
+
+ super(column_names, options)
end
+end
+def mysql_adapter?
+ defined?(ActiveRecord::ConnectionAdapters::Mysql2Adapter) && ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters::Mysql2Adapter)
+end
+
+if Gitlab.rails5?
if defined?(ActiveRecord::ConnectionAdapters::MySQL::TableDefinition)
ActiveRecord::ConnectionAdapters::MySQL::TableDefinition.send(:prepend, MysqlSetLengthForBinaryIndexAndIgnorePostgresOptionsForSchema)
end
+elsif mysql_adapter? && defined?(ActiveRecord::ConnectionAdapters::TableDefinition)
+ ActiveRecord::ConnectionAdapters::TableDefinition.send(:prepend, MysqlSetLengthForBinaryIndexAndIgnorePostgresOptionsForSchema)
end
diff --git a/config/initializers/postgresql_opclasses_support.rb b/config/initializers/postgresql_opclasses_support.rb
index 12a0770a455..07b06629dea 100644
--- a/config/initializers/postgresql_opclasses_support.rb
+++ b/config/initializers/postgresql_opclasses_support.rb
@@ -208,5 +208,9 @@ module ActiveRecord
index_parts << "comment: #{index.comment.inspect}" if Gitlab.rails5? && index.comment
index_parts
end
+
+ def format_options(options)
+ options.map { |key, value| "#{key}: #{value.inspect}" }.join(", ")
+ end
end
end
diff --git a/config/initializers/rack_attack_global.rb b/config/initializers/rack_attack_global.rb
index 45963831c41..86cb930eca9 100644
--- a/config/initializers/rack_attack_global.rb
+++ b/config/initializers/rack_attack_global.rb
@@ -33,22 +33,22 @@ class Rack::Attack
throttle('throttle_authenticated_api', Gitlab::Throttle.authenticated_api_options) do |req|
Gitlab::Throttle.settings.throttle_authenticated_api_enabled &&
req.api_request? &&
- req.authenticated_user_id
+ req.authenticated_user_id([:api])
end
throttle('throttle_authenticated_web', Gitlab::Throttle.authenticated_web_options) do |req|
Gitlab::Throttle.settings.throttle_authenticated_web_enabled &&
req.web_request? &&
- req.authenticated_user_id
+ req.authenticated_user_id([:api, :rss, :ics])
end
class Request
def unauthenticated?
- !authenticated_user_id
+ !authenticated_user_id([:api, :rss, :ics])
end
- def authenticated_user_id
- Gitlab::Auth::RequestAuthenticator.new(self).user&.id
+ def authenticated_user_id(request_formats)
+ Gitlab::Auth::RequestAuthenticator.new(self).user(request_formats)&.id
end
def api_request?
diff --git a/config/initializers/rbtrace.rb b/config/initializers/rbtrace.rb
new file mode 100644
index 00000000000..6a1b71bf4bd
--- /dev/null
+++ b/config/initializers/rbtrace.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+if ENV['ENABLE_RBTRACE']
+ Gitlab::Cluster::LifecycleEvents.on_worker_start do
+ # Unicorn clears out signals before it forks, so rbtrace won't work
+ # unless it is enabled after the fork.
+ require 'rbtrace'
+ end
+end
diff --git a/config/initializers/routing_draw.rb b/config/initializers/routing_draw.rb
index 25003cf0239..f0f74954eef 100644
--- a/config/initializers/routing_draw.rb
+++ b/config/initializers/routing_draw.rb
@@ -1,7 +1,3 @@
# Adds draw method into Rails routing
-# It allows us to keep routing splitted into files
-class ActionDispatch::Routing::Mapper
- def draw(routes_name)
- instance_eval(File.read(Rails.root.join("config/routes/#{routes_name}.rb")))
- end
-end
+# It allows us to keep routing split into files
+ActionDispatch::Routing::Mapper.prepend Gitlab::Patch::DrawRoute
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index 476eaabfed8..4210be2c701 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -14,14 +14,13 @@ Sidekiq.default_worker_options = { retry: 3 }
enable_json_logs = Gitlab.config.sidekiq.log_format == 'json'
Sidekiq.configure_server do |config|
- require 'rbtrace' if ENV['ENABLE_RBTRACE']
-
config.redis = queues_config_hash
config.server_middleware do |chain|
chain.add Gitlab::SidekiqMiddleware::ArgumentsLogger if ENV['SIDEKIQ_LOG_ARGUMENTS'] && !enable_json_logs
chain.add Gitlab::SidekiqMiddleware::Shutdown
chain.add Gitlab::SidekiqMiddleware::RequestStoreMiddleware unless ENV['SIDEKIQ_REQUEST_STORE'] == '0'
+ chain.add Gitlab::SidekiqMiddleware::BatchLoader
chain.add Gitlab::SidekiqStatus::ServerMiddleware
end
@@ -40,6 +39,10 @@ Sidekiq.configure_server do |config|
ActiveRecord::Base.clear_all_connections!
end
+ if Feature.enabled?(:gitlab_sidekiq_reliable_fetcher)
+ Sidekiq::ReliableFetcher.setup_reliable_fetch!(config)
+ end
+
# Sidekiq-cron: load recurring jobs from gitlab.yml
# UGLY Hack to get nested hash from settingslogic
cron_jobs = JSON.parse(Gitlab.config.cron_jobs.to_json)
@@ -55,14 +58,12 @@ Sidekiq.configure_server do |config|
end
Sidekiq::Cron::Job.load_from_hash! cron_jobs
- Gitlab::SidekiqThrottler.execute!
-
Gitlab::SidekiqVersioning.install!
- config = Gitlab::Database.config ||
+ db_config = Gitlab::Database.config ||
Rails.application.config.database_configuration[Rails.env]
- config['pool'] = Sidekiq.options[:concurrency]
- ActiveRecord::Base.establish_connection(config)
+ db_config['pool'] = Sidekiq.options[:concurrency]
+ ActiveRecord::Base.establish_connection(db_config)
Rails.logger.debug("Connection Pool size for Sidekiq Server is now: #{ActiveRecord::Base.connection.pool.instance_variable_get('@size')}")
# Avoid autoload issue such as 'Mail::Parsers::AddressStruct'
diff --git a/config/initializers/warden.rb b/config/initializers/warden.rb
index 33f55069c3e..1d2bb2bce0a 100644
--- a/config/initializers/warden.rb
+++ b/config/initializers/warden.rb
@@ -31,6 +31,11 @@ Rails.application.configure do |config|
Warden::Manager.before_logout(scope: :user) do |user, auth, opts|
user ||= auth.user
+
+ # Rails CSRF protection may attempt to log out a user before that
+ # user even logs in
+ next unless user
+
activity = Gitlab::Auth::Activity.new(opts)
tracker = Gitlab::Auth::BlockedUserTracker.new(user, auth)
diff --git a/config/karma.config.js b/config/karma.config.js
index 74dc5c13c70..e1d7c30b1c2 100644
--- a/config/karma.config.js
+++ b/config/karma.config.js
@@ -22,6 +22,13 @@ webpackConfig.optimization.splitChunks = false;
// use quicker sourcemap option
webpackConfig.devtool = 'cheap-inline-source-map';
+// set BABEL_ENV to indicate when we're running code coverage
+webpackConfig.plugins.push(
+ new webpack.DefinePlugin({
+ 'process.env.BABEL_ENV': JSON.stringify(process.env.BABEL_ENV || process.env.NODE_ENV || null),
+ })
+);
+
const specFilters = argumentsParser
.option(
'-f, --filter-spec [filter]',
@@ -84,7 +91,7 @@ module.exports = function(config) {
basePath: ROOT_PATH,
browsers: ['ChromeHeadlessCustom'],
client: {
- color: !process.env.CI
+ color: !process.env.CI,
},
customLaunchers: {
ChromeHeadlessCustom: {
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 795e5d4e6bc..0a43a1d9a6b 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -8,6 +8,8 @@ en:
issue_link:
source: Source issue
target: Target issue
+ group:
+ path: Group URL
errors:
messages:
label_already_exists_at_group_level: "already exists at group level for %{group}. Please choose another one."
diff --git a/config/puma.example.development.rb b/config/puma.example.development.rb
new file mode 100644
index 00000000000..490c940077a
--- /dev/null
+++ b/config/puma.example.development.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+# -----------------------------------------------------------------------
+# This file is used by the GDK to generate a default config/puma.rb file
+# Note that `/home/git` will be substituted for the actual GDK root
+# directory when this file is generated
+# -----------------------------------------------------------------------
+
+# Load "path" as a rackup file.
+#
+# The default is "config.ru".
+#
+rackup 'config.ru'
+pidfile '/home/git/gitlab/tmp/pids/puma.pid'
+state_path '/home/git/gitlab/tmp/pids/puma.state'
+
+stdout_redirect '/home/git/gitlab/log/puma.stdout.log',
+ '/home/git/gitlab/log/puma.stderr.log',
+ true
+
+# Configure "min" to be the minimum number of threads to use to answer
+# requests and "max" the maximum.
+#
+# The default is "0, 16".
+#
+threads 1, 4
+
+# By default, workers accept all requests and queue them to pass to handlers.
+# When false, workers accept the number of simultaneous requests configured.
+#
+# Queueing requests generally improves performance, but can cause deadlocks if
+# the app is waiting on a request to itself. See https://github.com/puma/puma/issues/612
+#
+# When set to false this may require a reverse proxy to handle slow clients and
+# queue requests before they reach puma. This is due to disabling HTTP keepalive
+queue_requests false
+
+# Bind the server to "url". "tcp://", "unix://" and "ssl://" are the only
+# accepted protocols.
+bind 'unix:///home/git/gitlab.socket'
+
+workers 2
+
+require_relative "/home/git/gitlab/lib/gitlab/cluster/lifecycle_events"
+require_relative "/home/git/gitlab/lib/gitlab/cluster/puma_worker_killer_initializer"
+
+on_restart do
+ # Signal application hooks that we're about to restart
+ Gitlab::Cluster::LifecycleEvents.do_master_restart
+end
+
+before_fork do
+ # Signal to the puma killer
+ Gitlab::Cluster::PumaWorkerKillerInitializer.start @config.options unless ENV['DISABLE_PUMA_WORKER_KILLER']
+
+ # Signal application hooks that we're about to fork
+ Gitlab::Cluster::LifecycleEvents.do_before_fork
+end
+
+Gitlab::Cluster::LifecycleEvents.set_puma_options @config.options
+on_worker_boot do
+ # Signal application hooks of worker start
+ Gitlab::Cluster::LifecycleEvents.do_worker_start
+end
+
+# Preload the application before starting the workers; this conflicts with
+# phased restart feature. (off by default)
+
+preload_app!
+
+tag 'gitlab-puma-worker'
+
+# Verifies that all workers have checked in to the master process within
+# the given timeout. If not the worker process will be restarted. Default
+# value is 60 seconds.
+#
+worker_timeout 60
diff --git a/config/routes.rb b/config/routes.rb
index 1242bbbf932..484e05114be 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -34,6 +34,8 @@ Rails.application.routes.draw do
match '*all', via: [:get, :post], to: proc { [404, {}, ['']] }
end
+ draw :oauth
+
use_doorkeeper_openid_connect
# Autocomplete
@@ -56,7 +58,6 @@ Rails.application.routes.draw do
# '/-/health' implemented by BasicHealthMiddleware
get 'liveness' => 'health#liveness'
get 'readiness' => 'health#readiness'
- post 'storage_check' => 'health#storage_check'
resources :metrics, only: [:index]
mount Peek::Railtie => '/peek', as: 'peek_routes'
@@ -79,11 +80,33 @@ Rails.application.routes.draw do
get 'ide' => 'ide#index'
get 'ide/*vueroute' => 'ide#index', format: false
+ draw :operations
draw :instance_statistics
+
+ if ENV['GITLAB_ENABLE_CHAOS_ENDPOINTS']
+ get '/chaos/leakmem' => 'chaos#leakmem'
+ get '/chaos/cpuspin' => 'chaos#cpuspin'
+ get '/chaos/sleep' => 'chaos#sleep'
+ get '/chaos/kill' => 'chaos#kill'
+ end
end
- # Koding route
- get 'koding' => 'koding#index'
+ concern :clusterable do
+ resources :clusters, only: [:index, :new, :show, :update, :destroy] do
+ collection do
+ post :create_user
+ post :create_gcp
+ end
+
+ member do
+ scope :applications do
+ post '/:application', to: 'clusters/applications#create', as: :install_applications
+ end
+
+ get :cluster_status, format: :json
+ end
+ end
+ end
draw :api
draw :sidekiq
diff --git a/config/routes/admin.rb b/config/routes/admin.rb
index 7489b01ded6..af333bdc748 100644
--- a/config/routes/admin.rb
+++ b/config/routes/admin.rb
@@ -69,10 +69,9 @@ namespace :admin do
end
resource :logs, only: [:show]
- resource :health_check, controller: 'health_check', only: [:show] do
- post :reset_storage_health
- end
+ resource :health_check, controller: 'health_check', only: [:show]
resource :background_jobs, controller: 'background_jobs', only: [:show]
+
resource :system_info, controller: 'system_info', only: [:show]
resources :requests_profiles, only: [:index, :show], param: :name, constraints: { name: /.+\.html/ }
@@ -106,8 +105,9 @@ namespace :admin do
resource :application_settings, only: [:show, :update] do
resources :services, only: [:index, :edit, :update]
+
get :usage_data
- put :reset_runners_token
+ put :reset_registration_token
put :reset_health_check_token
put :clear_repository_check_states
get :integrations, :repository, :templates, :ci_cd, :reporting, :metrics_and_profiling, :network, :geo, :preferences
diff --git a/config/routes/group.rb b/config/routes/group.rb
index 893ec8a4e58..a0aeebe4b91 100644
--- a/config/routes/group.rb
+++ b/config/routes/group.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
resources :groups, only: [:index, :new, :create] do
post :preview_markdown
end
@@ -27,7 +29,9 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
as: :group,
constraints: { group_id: Gitlab::PathRegex.full_namespace_route_regex }) do
namespace :settings do
- resource :ci_cd, only: [:show], controller: 'ci_cd'
+ resource :ci_cd, only: [:show], controller: 'ci_cd' do
+ put :reset_registration_token
+ end
end
resource :variables, only: [:show, :update]
@@ -49,6 +53,8 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
resource :avatar, only: [:destroy]
+ concerns :clusterable
+
resources :group_members, only: [:index, :create, :update, :destroy], concerns: :access_requestable do
post :resend_invite, on: :member
delete :leave, on: :collection
@@ -61,7 +67,6 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
end
end
- # On CE only index and show actions are needed
resources :boards, only: [:index, :show]
resources :runners, only: [:index, :edit, :update, :destroy, :show] do
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 8a5310b5c23..3f1ad90dfca 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -32,6 +32,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
get 'labels'
get 'milestones'
get 'commands'
+ get 'snippets'
end
end
@@ -177,6 +178,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resource :mirror, only: [:show, :update] do
member do
+ get :ssh_host_keys, constraints: { format: :json }
post :update_now
end
end
@@ -205,20 +207,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
- resources :clusters, except: [:edit, :create] do
- collection do
- post :create_gcp
- post :create_user
- end
-
- member do
- get :status, format: :json
-
- scope :applications do
- post '/:application', to: 'clusters/applications#create', as: :install_applications
- end
- end
- end
+ concerns :clusterable
resources :environments, except: [:destroy] do
member do
@@ -275,6 +264,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
member do
get :status
post :cancel
+ post :unschedule
post :retry
post :play
post :erase
@@ -365,7 +355,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
get :discussions, format: :json
end
collection do
- post :bulk_update
+ post :bulk_update
end
end
@@ -437,6 +427,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
get :members, to: redirect("%{namespace_id}/%{project_id}/project_members")
resource :ci_cd, only: [:show, :update], controller: 'ci_cd' do
post :reset_cache
+ put :reset_registration_token
end
resource :integrations, only: [:show]
resource :repository, only: [:show], controller: :repository do
diff --git a/config/routes/user.rb b/config/routes/user.rb
index bc7df5e7584..e0ae264e2c0 100644
--- a/config/routes/user.rb
+++ b/config/routes/user.rb
@@ -45,6 +45,7 @@ scope(constraints: { username: Gitlab::PathRegex.root_namespace_route_regex }) d
get :contributed, as: :contributed_projects
get :snippets
get :exists
+ get :activity
get '/', to: redirect('%{username}'), as: nil
end
diff --git a/config/routes/wiki.rb b/config/routes/wiki.rb
index 1a07b1c206b..2ca52e55fca 100644
--- a/config/routes/wiki.rb
+++ b/config/routes/wiki.rb
@@ -6,7 +6,7 @@ scope(controller: :wikis) do
post '/', to: 'wikis#create'
end
- scope(path: 'wikis/*id', as: :wiki, format: false, defaults: { format: :html }) do
+ scope(path: 'wikis/*id', as: :wiki, format: false) do
get :edit
get :history
post :preview_markdown
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 0e723cdeb9c..53e1c8778b6 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -29,6 +29,7 @@
- [pipeline_creation, 4]
- [pipeline_default, 3]
- [pipeline_cache, 3]
+ - [deployment, 3]
- [pipeline_hooks, 2]
- [gitlab_shell, 2]
- [email_receiver, 2]
diff --git a/config/unicorn.rb.example b/config/unicorn.rb.example
index 020e9a00d87..4637eb8bc6e 100644
--- a/config/unicorn.rb.example
+++ b/config/unicorn.rb.example
@@ -81,22 +81,16 @@ preload_app true
# fast LAN.
check_client_connection false
+require_relative "/home/git/gitlab/lib/gitlab/cluster/lifecycle_events"
+
before_exec do |server|
- # The following is necessary to ensure stale Prometheus metrics don't
- # accumulate over time. It needs to be done in this hook as opposed to
- # inside an init script to ensure metrics files aren't deleted after new
- # unicorn workers start after a SIGUSR2 is received.
- if ENV['prometheus_multiproc_dir']
- old_metrics = Dir[File.join(ENV['prometheus_multiproc_dir'], '*.db')]
- FileUtils.rm_rf(old_metrics)
- end
+ # Signal application hooks that we're about to restart
+ Gitlab::Cluster::LifecycleEvents.do_master_restart
end
before_fork do |server, worker|
- # the following is highly recommended for Rails + "preload_app true"
- # as there's no need for the master process to hold a connection
- defined?(ActiveRecord::Base) and
- ActiveRecord::Base.connection.disconnect!
+ # Signal application hooks that we're about to fork
+ Gitlab::Cluster::LifecycleEvents.do_before_fork
# The following is only recommended for memory/DB-constrained
# installations. It is not needed if your system can house
@@ -124,25 +118,10 @@ before_fork do |server, worker|
end
after_fork do |server, worker|
- # Unicorn clears out signals before it forks, so rbtrace won't work
- # unless it is enabled after the fork.
- require 'rbtrace' if ENV['ENABLE_RBTRACE']
+ # Signal application hooks of worker start
+ Gitlab::Cluster::LifecycleEvents.do_worker_start
# per-process listener ports for debugging/admin/migrations
# addr = "127.0.0.1:#{9293 + worker.nr}"
# server.listen(addr, :tries => -1, :delay => 5, :tcp_nopush => true)
-
- # the following is *required* for Rails + "preload_app true",
- defined?(ActiveRecord::Base) and
- ActiveRecord::Base.establish_connection
-
- # reset prometheus client, this will cause any opened metrics files to be closed
- defined?(::Prometheus::Client.reinitialize_on_pid_change) &&
- Prometheus::Client.reinitialize_on_pid_change
-
- # if preload_app is true, then you may also want to check and
- # restart any other shared sockets/descriptors such as Memcached,
- # and Redis. TokyoCabinet file handles are safe to reuse
- # between any number of forked children (assuming your kernel
- # correctly implements pread()/pwrite() system calls)
end
diff --git a/config/unicorn.rb.example.development b/config/unicorn.rb.example.development
index 5712549a66d..f7541bb9d55 100644
--- a/config/unicorn.rb.example.development
+++ b/config/unicorn.rb.example.development
@@ -1,32 +1,61 @@
+# frozen_string_literal: true
+
+# -------------------------------------------------------------------------
+# This file is used by the GDK to generate a default config/unicorn.rb file
+# Note that `/home/git` will be substituted for the actual GDK root
+# directory when this file is generated
+# -------------------------------------------------------------------------
+
worker_processes 2
timeout 60
+listen '/home/git/gitlab.socket'
+
preload_app true
check_client_connection false
+require_relative "/home/git/gitlab/lib/gitlab/cluster/lifecycle_events"
+
+before_exec do |server|
+ # Signal application hooks that we're about to restart
+ Gitlab::Cluster::LifecycleEvents.do_master_restart
+end
+
before_fork do |server, worker|
- # the following is highly recommended for Rails + "preload_app true"
- # as there's no need for the master process to hold a connection
- defined?(ActiveRecord::Base) and
- ActiveRecord::Base.connection.disconnect!
-
- if /darwin/ =~ RUBY_PLATFORM
- require 'fiddle'
-
- # Dynamically load Foundation.framework, ~implicitly~ initialising
- # the Objective-C runtime before any forking happens in Unicorn
- #
- # From https://bugs.ruby-lang.org/issues/14009
- Fiddle.dlopen '/System/Library/Frameworks/Foundation.framework/Foundation'
+ # Signal application hooks that we're about to fork
+ Gitlab::Cluster::LifecycleEvents.do_before_fork
+
+ # The following is only recommended for memory/DB-constrained
+ # installations. It is not needed if your system can house
+ # twice as many worker_processes as you have configured.
+ #
+ # This allows a new master process to incrementally
+ # phase out the old master process with SIGTTOU to avoid a
+ # thundering herd (especially in the "preload_app false" case)
+ # when doing a transparent upgrade. The last worker spawned
+ # will then kill off the old master process with a SIGQUIT.
+ old_pid = "#{server.config[:pid]}.oldbin"
+ if old_pid != server.pid
+ begin
+ sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
+ Process.kill(sig, File.read(old_pid).to_i)
+ rescue Errno::ENOENT, Errno::ESRCH
+ end
end
+ #
+ # Throttle the master from forking too quickly by sleeping. Due
+ # to the implementation of standard Unix signal handlers, this
+ # helps (but does not completely) prevent identical, repeated signals
+ # from being lost when the receiving process is busy.
+ # sleep 1
end
after_fork do |server, worker|
- # Unicorn clears out signals before it forks, so rbtrace won't work
- # unless it is enabled after the fork.
- require 'rbtrace' if ENV['ENABLE_RBTRACE']
+ # Signal application hooks of worker start
+ Gitlab::Cluster::LifecycleEvents.do_worker_start
- # the following is *required* for Rails + "preload_app true",
- defined?(ActiveRecord::Base) and
- ActiveRecord::Base.establish_connection
+ # per-process listener ports for debugging/admin/migrations
+ # addr = "127.0.0.1:#{9293 + worker.nr}"
+ # server.listen(addr, :tries => -1, :delay => 5, :tcp_nopush => true)
end
+
diff --git a/config/webpack.config.js b/config/webpack.config.js
index 583f05f2fb7..b9044e13f50 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -8,7 +8,7 @@ const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const ROOT_PATH = path.resolve(__dirname, '..');
-const CACHE_PATH = path.join(ROOT_PATH, 'tmp/cache');
+const CACHE_PATH = process.env.WEBPACK_CACHE_PATH || path.join(ROOT_PATH, 'tmp/cache');
const IS_PRODUCTION = process.env.NODE_ENV === 'production';
const IS_DEV_SERVER = process.argv.join(' ').indexOf('webpack-dev-server') !== -1;
const DEV_SERVER_HOST = process.env.DEV_SERVER_HOST || 'localhost';
@@ -84,7 +84,7 @@ module.exports = {
},
resolve: {
- extensions: ['.js'],
+ extensions: ['.js', '.gql', '.graphql'],
alias: {
'~': path.join(ROOT_PATH, 'app/assets/javascripts'),
emojis: path.join(ROOT_PATH, 'fixtures/emojis'),
@@ -101,6 +101,11 @@ module.exports = {
strictExportPresence: true,
rules: [
{
+ type: 'javascript/auto',
+ test: /\.mjs$/,
+ use: [],
+ },
+ {
test: /\.js$/,
exclude: path => /node_modules|vendor[\\/]assets/.test(path) && !/\.vue\.js/.test(path),
loader: 'babel-loader',
@@ -122,6 +127,11 @@ module.exports = {
},
},
{
+ test: /\.(graphql|gql)$/,
+ exclude: /node_modules/,
+ loader: 'graphql-tag/loader',
+ },
+ {
test: /\.svg$/,
loader: 'raw-loader',
},
diff --git a/danger/database/Dangerfile b/danger/database/Dangerfile
index ad5f1c1e0f3..38ccbd94edb 100644
--- a/danger/database/Dangerfile
+++ b/danger/database/Dangerfile
@@ -39,8 +39,6 @@ def database_paths_requiring_review(files)
to_review
end
-all_files = git.added_files + git.modified_files
-
non_geo_db_schema_updated = !git.modified_files.grep(%r{\Adb/schema\.rb}).empty?
geo_db_schema_updated = !git.modified_files.grep(%r{\Aee/db/geo/schema\.rb}).empty?
@@ -55,7 +53,7 @@ if geo_migration_created && !geo_db_schema_updated
warn format(SCHEMA_NOT_UPDATED_MESSAGE, migrations: 'Geo migrations', schema: gitlab.html_link("ee/db/geo/schema.rb"))
end
-db_paths_to_review = database_paths_requiring_review(all_files)
+db_paths_to_review = database_paths_requiring_review(helper.all_changed_files)
unless db_paths_to_review.empty?
message 'This merge request adds or changes files that require a ' \
diff --git a/danger/documentation/Dangerfile b/danger/documentation/Dangerfile
index d65bec123a9..87c61d6e90d 100644
--- a/danger/documentation/Dangerfile
+++ b/danger/documentation/Dangerfile
@@ -11,24 +11,36 @@ def docs_paths_requiring_review(files)
end
end
-all_files = git.added_files + git.modified_files
-
-docs_paths_to_review = docs_paths_requiring_review(all_files)
+docs_paths_to_review = docs_paths_requiring_review(helper.all_changed_files)
unless docs_paths_to_review.empty?
message 'This merge request adds or changes files that require a ' \
- 'review from the docs team.'
+ 'review from the Docs team.'
markdown(<<~MARKDOWN)
-## Docs Review
+## Docs review
The following files require a review from the Documentation team:
* #{docs_paths_to_review.map { |path| "`#{path}`" }.join("\n* ")}
-To make sure these changes are reviewed, mention `@gl-docsteam` in a separate
-comment, and explain what needs to be reviewed by the team. Please don't mention
-the team until your changes are ready for review.
+When your content is ready for review, mention a technical writer in a separate
+comment and explain what needs to be reviewed.
+
+You are welcome to mention them sooner if you have questions about writing or updating
+the documentation. GitLabbers are also welcome to use the [#docs](https://gitlab.slack.com/archives/C16HYA2P5) channel on Slack.
+
+Who to ping [based on DevOps stages](https://about.gitlab.com/handbook/product/categories/#devops-stages):
+
+| Tech writer | Stage(s) |
+| ------------ | ------------------------------------------------------------ |
+| `@marcia` | ~Create ~Release |
+| `@axil` | ~Distribution ~Gitaly ~Gitter ~Monitoring ~Packaging ~Secure |
+| `@eread` | ~Manage ~Configure ~Geo ~Verify |
+| `@mikelewis` | ~Plan |
+
+If you are not sure which category the change falls within, or the change is not
+part of one of these categories, you can mention one of the usernames above.
MARKDOWN
unless gitlab.mr_labels.include?('Documentation')
diff --git a/danger/eslint/Dangerfile b/danger/eslint/Dangerfile
new file mode 100644
index 00000000000..4916cacfd7e
--- /dev/null
+++ b/danger/eslint/Dangerfile
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+def get_eslint_files(files)
+ files.select do |file|
+ file.end_with?('.js', '.vue') &&
+ File.read(file).include?('/* eslint-disable')
+ end
+end
+
+eslint_candidates = get_eslint_files(helper.all_changed_files)
+
+return if eslint_candidates.empty?
+
+warn 'This merge request changed files with disabled eslint rules. Please consider fixing them.'
+
+markdown(<<~MARKDOWN)
+ ## Disabled eslint rules
+
+ The following files have disabled `eslint` rules. Please consider fixing them:
+
+ * #{eslint_candidates.map { |path| "`#{path}`" }.join("\n* ")}
+
+ Run the following command for more details
+
+ ```
+ node_modules/.bin/eslint --report-unused-disable-directives --no-inline-config \\
+ #{eslint_candidates.map { |path| " '#{path}'" }.join(" \\\n")}
+ ```
+MARKDOWN
diff --git a/danger/metadata/Dangerfile b/danger/metadata/Dangerfile
index 51fc9e6bfca..1adca152736 100644
--- a/danger/metadata/Dangerfile
+++ b/danger/metadata/Dangerfile
@@ -23,3 +23,10 @@ has_pick_into_stable_label = gitlab.mr_labels.find { |label| label.start_with?('
if gitlab.branch_for_base != "master" && !has_pick_into_stable_label
warn "Most of the time, merge requests should target `master`. Otherwise, please set the relevant `Pick into X.Y` label."
end
+
+if gitlab.mr_json['title'].length > 72
+ warn 'The title of this merge request is longer than 72 characters and ' \
+ 'would violate our commit message rules when using the Squash on Merge ' \
+ 'feature. Please consider adjusting the title, or rebase the ' \
+ "commits manually and don't use Squash on Merge."
+end
diff --git a/danger/plugins/helper.rb b/danger/plugins/helper.rb
new file mode 100644
index 00000000000..f4eb9119266
--- /dev/null
+++ b/danger/plugins/helper.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Danger
+ # Common helper functions for our danger scripts
+ # If we find ourselves repeating code in our danger files, we might as well put them in here.
+ class Helper < Plugin
+ # Returns a list of all files that have been added, modified or renamed.
+ # `git.modified_files` might contain paths that already have been renamed,
+ # so we need to remove them from the list.
+ #
+ # Considering these changes:
+ #
+ # - A new_file.rb
+ # - D deleted_file.rb
+ # - M modified_file.rb
+ # - R renamed_file_before.rb -> renamed_file_after.rb
+ #
+ # it will return
+ # ```
+ # [ 'new_file.rb', 'modified_file.rb', 'renamed_file_after.rb' ]
+ # ```
+ #
+ # @return [Array<String>]
+ def all_changed_files
+ Set.new
+ .merge(git.added_files.to_a)
+ .merge(git.modified_files.to_a)
+ .merge(git.renamed_files.map { |x| x[:after] })
+ .subtract(git.renamed_files.map { |x| x[:before] })
+ .to_a
+ .sort
+ end
+ end
+end
diff --git a/danger/prettier/Dangerfile b/danger/prettier/Dangerfile
new file mode 100644
index 00000000000..37c4b78a213
--- /dev/null
+++ b/danger/prettier/Dangerfile
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+def get_prettier_files(files)
+ files.select do |file|
+ file.end_with?('.js', '.scss', '.vue')
+ end
+end
+
+prettier_candidates = get_prettier_files(helper.all_changed_files)
+
+return if prettier_candidates.empty?
+
+unpretty = `node_modules/prettier/bin-prettier.js --list-different #{prettier_candidates.join(" ")}`
+ .split(/$/)
+ .map(&:strip)
+ .reject(&:empty?)
+
+return if unpretty.empty?
+
+warn 'This merge request changed frontend files without pretty printing them.'
+
+markdown(<<~MARKDOWN)
+ ## Pretty print Frontend files
+
+ The following files should have been pretty printed with `prettier`:
+
+ * #{unpretty.map { |path| "`#{path}`" }.join("\n* ")}
+
+ Please run
+
+ ```
+ node_modules/.bin/prettier --write \\
+ #{unpretty.map { |path| " '#{path}'" }.join(" \\\n")}
+ ```
+
+ Also consider auto-formatting [on-save].
+
+ [on-save]: https://docs.gitlab.com/ee/development/new_fe_guide/style/prettier.html
+MARKDOWN
diff --git a/danger/specs/Dangerfile b/danger/specs/Dangerfile
index 97188df8785..a526bb8adaa 100644
--- a/danger/specs/Dangerfile
+++ b/danger/specs/Dangerfile
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
NO_SPECS_LABELS = %w[backstage Documentation QA].freeze
NO_NEW_SPEC_MESSAGE = <<~MSG.freeze
You've made some app changes, but didn't add any tests.
@@ -9,8 +11,8 @@ def presented_no_changelog_labels
NO_SPECS_LABELS.map { |label| "~#{label}" }.join(', ')
end
-has_app_changes = !git.modified_files.grep(%r{\A(ee/)?(app|lib|db/(geo/)?(post_)?migrate)/}).empty?
-has_spec_changes = !git.modified_files.grep(%r{\A(ee/)?spec/}).empty?
+has_app_changes = !helper.all_changed_files.grep(%r{\A(ee/)?(app|lib|db/(geo/)?(post_)?migrate)/}).empty?
+has_spec_changes = !helper.all_changed_files.grep(%r{\A(ee/)?spec/}).empty?
new_specs_needed = (gitlab.mr_labels & NO_SPECS_LABELS).empty?
if has_app_changes && !has_spec_changes && new_specs_needed
diff --git a/db/fixtures/development/04_project.rb b/db/fixtures/development/04_project.rb
index 51e69879c79..089de211380 100644
--- a/db/fixtures/development/04_project.rb
+++ b/db/fixtures/development/04_project.rb
@@ -7,8 +7,8 @@ Sidekiq::Testing.inline! do
'https://gitlab.com/gitlab-org/gitlab-shell.git',
'https://gitlab.com/gnuwget/wget2.git',
'https://gitlab.com/Commit451/LabCoat.git',
- 'https://github.com/documentcloud/underscore.git',
- 'https://github.com/twitter/flight.git',
+ 'https://github.com/jashkenas/underscore.git',
+ 'https://github.com/flightjs/flight.git',
'https://github.com/twitter/typeahead.js.git',
'https://github.com/h5bp/html5-boilerplate.git',
'https://github.com/google/material-design-lite.git',
@@ -20,18 +20,18 @@ Sidekiq::Testing.inline! do
'https://github.com/airbnb/javascript.git',
'https://github.com/tessalt/echo-chamber-js.git',
'https://github.com/atom/atom.git',
- 'https://github.com/mattermost/platform.git',
+ 'https://github.com/mattermost/mattermost-server.git',
'https://github.com/purifycss/purifycss.git',
'https://github.com/facebook/nuclide.git',
'https://github.com/wbkd/awesome-d3.git',
'https://github.com/kilimchoi/engineering-blogs.git',
'https://github.com/gilbarbara/logos.git',
- 'https://github.com/gaearon/redux.git',
+ 'https://github.com/reduxjs/redux.git',
'https://github.com/awslabs/s2n.git',
'https://github.com/arkency/reactjs_koans.git',
'https://github.com/twbs/bootstrap.git',
'https://github.com/chjj/ttystudio.git',
- 'https://github.com/DrBoolean/mostly-adequate-guide.git',
+ 'https://github.com/MostlyAdequate/mostly-adequate-guide.git',
'https://github.com/octocat/Spoon-Knife.git',
'https://github.com/opencontainers/runc.git',
'https://github.com/googlesamples/android-topeka.git'
diff --git a/db/fixtures/development/09_issues.rb b/db/fixtures/development/09_issues.rb
index 0b32a461d56..16243b72f9a 100644
--- a/db/fixtures/development/09_issues.rb
+++ b/db/fixtures/development/09_issues.rb
@@ -8,7 +8,8 @@ Gitlab::Seeder.quiet do
description: FFaker::Lorem.sentence,
state: ['opened', 'closed'].sample,
milestone: project.milestones.sample,
- assignees: [project.team.users.sample]
+ assignees: [project.team.users.sample],
+ created_at: rand(12).months.ago
}
Issues::CreateService.new(project, project.team.users.sample, issue_params).execute
diff --git a/db/fixtures/development/14_pipelines.rb b/db/fixtures/development/14_pipelines.rb
index 5535c4a14e5..5af77c49913 100644
--- a/db/fixtures/development/14_pipelines.rb
+++ b/db/fixtures/development/14_pipelines.rb
@@ -1,7 +1,7 @@
require './spec/support/sidekiq'
class Gitlab::Seeder::Pipelines
- STAGES = %w[build test deploy notify]
+ STAGES = %w[build test security deploy notify]
BUILDS = [
# build stage
{ name: 'build:linux', stage: 'build', status: :success,
@@ -31,6 +31,16 @@ class Gitlab::Seeder::Pipelines
{ name: 'spinach:osx', stage: 'test', status: :failed, allow_failure: true,
queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
+ # security stage
+ { name: 'dast', stage: 'security', status: :success,
+ queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
+ { name: 'sast', stage: 'security', status: :success,
+ queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
+ { name: 'dependency_scanning', stage: 'security', status: :success,
+ queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
+ { name: 'container_scanning', stage: 'security', status: :success,
+ queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
+
# deploy stage
{ name: 'staging', stage: 'deploy', environment: 'staging', status_event: :success,
options: { environment: { action: 'start', on_stop: 'stop staging' } },
@@ -108,6 +118,11 @@ class Gitlab::Seeder::Pipelines
setup_artifacts(build)
setup_test_reports(build)
+ if build.ref == build.project.default_branch
+ setup_security_reports_file(build)
+ else
+ setup_security_reports_legacy_archive(build)
+ end
setup_build_log(build)
build.project.environments.
@@ -143,6 +158,55 @@ class Gitlab::Seeder::Pipelines
end
end
+ def setup_security_reports_file(build)
+ return unless build.stage == "security"
+
+ # we have two sources: master and feature-branch
+ branch_name = build.ref == build.project.default_branch ?
+ 'master' : 'feature-branch'
+
+ artifacts_cache_file(security_reports_path(branch_name, build.name)) do |file|
+ build.job_artifacts.build(
+ project: build.project,
+ file_type: build.name,
+ file_format: :raw,
+ file: file)
+ end
+ end
+
+ def setup_security_reports_legacy_archive(build)
+ return unless build.stage == "security"
+
+ # we have two sources: master and feature-branch
+ branch_name = build.ref == build.project.default_branch ?
+ 'master' : 'feature-branch'
+
+ artifacts_cache_file(security_reports_archive_path(branch_name)) do |file|
+ build.job_artifacts.build(
+ project: build.project,
+ file_type: :archive,
+ file_format: :zip,
+ file: file)
+ end
+
+ # assign dummy metadata
+ artifacts_cache_file(artifacts_metadata_path) do |file|
+ build.job_artifacts.build(
+ project: build.project,
+ file_type: :metadata,
+ file_format: :gzip,
+ file: file)
+ end
+
+ build.options = {
+ artifacts: {
+ paths: [
+ Ci::JobArtifact::DEFAULT_FILE_NAMES.fetch(build.name.to_sym)
+ ]
+ }
+ }
+ end
+
def setup_build_log(build)
if %w(running success failed).include?(build.status)
build.trace.set(FFaker::Lorem.paragraphs(6).join("\n\n"))
@@ -190,6 +254,15 @@ class Gitlab::Seeder::Pipelines
Rails.root + 'spec/fixtures/junit/junit.xml.gz'
end
+ def security_reports_archive_path(branch)
+ Rails.root.join('spec', 'fixtures', 'security-reports', branch + '.zip')
+ end
+
+ def security_reports_path(branch, name)
+ file_name = Ci::JobArtifact::DEFAULT_FILE_NAMES.fetch(name.to_sym)
+ Rails.root.join('spec', 'fixtures', 'security-reports', branch, file_name)
+ end
+
def artifacts_cache_file(file_path)
file = Tempfile.new("artifacts")
file.close
diff --git a/db/fixtures/development/17_cycle_analytics.rb b/db/fixtures/development/17_cycle_analytics.rb
index 285436f4324..7a86fe2eb7c 100644
--- a/db/fixtures/development/17_cycle_analytics.rb
+++ b/db/fixtures/development/17_cycle_analytics.rb
@@ -180,11 +180,8 @@ class Gitlab::Seeder::CycleAnalytics
ref: "refs/heads/#{merge_request.source_branch}")
pipeline = service.execute(:push, ignore_skip_ci: true, save_on_errors: false)
- pipeline.run!
- Timecop.travel rand(1..6).hours.from_now
- pipeline.succeed!
-
- PipelineMetricsWorker.new.perform(pipeline.id)
+ pipeline.builds.map(&:run!)
+ pipeline.update_status
end
end
@@ -204,7 +201,8 @@ class Gitlab::Seeder::CycleAnalytics
job = merge_request.head_pipeline.builds.where.not(environment: nil).last
- CreateDeploymentService.new(job).execute
+ job.success!
+ pipeline.update_status
end
end
end
diff --git a/db/migrate/20140313092127_init_schema.rb b/db/migrate/20140313092127_init_schema.rb
index 29fb386ad76..4188599b4b4 100644
--- a/db/migrate/20140313092127_init_schema.rb
+++ b/db/migrate/20140313092127_init_schema.rb
@@ -1,4 +1,4 @@
-class InitSchema < ActiveRecord::Migration
+class InitSchema < ActiveRecord::Migration[4.2]
DOWNTIME = true
# rubocop:disable Metrics/AbcSize
diff --git a/db/migrate/20140407135544_fix_namespaces.rb b/db/migrate/20140407135544_fix_namespaces.rb
index 3d2ca5c13c4..b16d65c4b51 100644
--- a/db/migrate/20140407135544_fix_namespaces.rb
+++ b/db/migrate/20140407135544_fix_namespaces.rb
@@ -1,4 +1,4 @@
-class FixNamespaces < ActiveRecord::Migration
+class FixNamespaces < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20140414131055_change_state_to_allow_empty_merge_request_diffs.rb b/db/migrate/20140414131055_change_state_to_allow_empty_merge_request_diffs.rb
index fb9c7a6636e..148b46f8830 100644
--- a/db/migrate/20140414131055_change_state_to_allow_empty_merge_request_diffs.rb
+++ b/db/migrate/20140414131055_change_state_to_allow_empty_merge_request_diffs.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class ChangeStateToAllowEmptyMergeRequestDiffs < ActiveRecord::Migration
+class ChangeStateToAllowEmptyMergeRequestDiffs < ActiveRecord::Migration[4.2]
def up
change_column :merge_request_diffs, :state, :string, null: true,
default: nil
diff --git a/db/migrate/20140416074002_add_index_on_iid.rb b/db/migrate/20140416074002_add_index_on_iid.rb
index 6cdaa5a3c08..c7f707ca123 100644
--- a/db/migrate/20140416074002_add_index_on_iid.rb
+++ b/db/migrate/20140416074002_add_index_on_iid.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddIndexOnIid < ActiveRecord::Migration
+class AddIndexOnIid < ActiveRecord::Migration[4.2]
def change
RemoveDuplicateIid.clean(Issue)
RemoveDuplicateIid.clean(MergeRequest, 'target_project_id')
diff --git a/db/migrate/20140416185734_index_on_current_sign_in_at.rb b/db/migrate/20140416185734_index_on_current_sign_in_at.rb
index 8c620b545bd..7dabcb937b3 100644
--- a/db/migrate/20140416185734_index_on_current_sign_in_at.rb
+++ b/db/migrate/20140416185734_index_on_current_sign_in_at.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class IndexOnCurrentSignInAt < ActiveRecord::Migration
+class IndexOnCurrentSignInAt < ActiveRecord::Migration[4.2]
def change
add_index :users, :current_sign_in_at
end
diff --git a/db/migrate/20140428105831_add_notes_index_updated_at.rb b/db/migrate/20140428105831_add_notes_index_updated_at.rb
index 0589101af93..25bdf477e24 100644
--- a/db/migrate/20140428105831_add_notes_index_updated_at.rb
+++ b/db/migrate/20140428105831_add_notes_index_updated_at.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddNotesIndexUpdatedAt < ActiveRecord::Migration
+class AddNotesIndexUpdatedAt < ActiveRecord::Migration[4.2]
def change
add_index :notes, :updated_at
end
diff --git a/db/migrate/20140502115131_add_repo_size_to_db.rb b/db/migrate/20140502115131_add_repo_size_to_db.rb
index 090b30a4f26..4cb7a01bbf2 100644
--- a/db/migrate/20140502115131_add_repo_size_to_db.rb
+++ b/db/migrate/20140502115131_add_repo_size_to_db.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddRepoSizeToDb < ActiveRecord::Migration
+class AddRepoSizeToDb < ActiveRecord::Migration[4.2]
def change
add_column :projects, :repository_size, :float, default: 0
end
diff --git a/db/migrate/20140502125220_migrate_repo_size.rb b/db/migrate/20140502125220_migrate_repo_size.rb
index ca1b054600c..a69b02cddc4 100644
--- a/db/migrate/20140502125220_migrate_repo_size.rb
+++ b/db/migrate/20140502125220_migrate_repo_size.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class MigrateRepoSize < ActiveRecord::Migration
+class MigrateRepoSize < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20140611135229_add_position_to_merge_request.rb b/db/migrate/20140611135229_add_position_to_merge_request.rb
index 3a7d2f7c359..6ec644eecce 100644
--- a/db/migrate/20140611135229_add_position_to_merge_request.rb
+++ b/db/migrate/20140611135229_add_position_to_merge_request.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddPositionToMergeRequest < ActiveRecord::Migration
+class AddPositionToMergeRequest < ActiveRecord::Migration[4.2]
def change
add_column :merge_requests, :position, :integer, default: 0
end
diff --git a/db/migrate/20140625115202_create_users_star_projects.rb b/db/migrate/20140625115202_create_users_star_projects.rb
index d4f3fe5ac62..2237927fc78 100644
--- a/db/migrate/20140625115202_create_users_star_projects.rb
+++ b/db/migrate/20140625115202_create_users_star_projects.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class CreateUsersStarProjects < ActiveRecord::Migration
+class CreateUsersStarProjects < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20140729134820_create_labels.rb b/db/migrate/20140729134820_create_labels.rb
index 66d20e741a6..1060610b660 100644
--- a/db/migrate/20140729134820_create_labels.rb
+++ b/db/migrate/20140729134820_create_labels.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class CreateLabels < ActiveRecord::Migration
+class CreateLabels < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20140729140420_create_label_links.rb b/db/migrate/20140729140420_create_label_links.rb
index dacd9f2e4b6..b8596a44a21 100644
--- a/db/migrate/20140729140420_create_label_links.rb
+++ b/db/migrate/20140729140420_create_label_links.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class CreateLabelLinks < ActiveRecord::Migration
+class CreateLabelLinks < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20140729145339_migrate_project_tags.rb b/db/migrate/20140729145339_migrate_project_tags.rb
index 5760e4bfeaa..711a2d262aa 100644
--- a/db/migrate/20140729145339_migrate_project_tags.rb
+++ b/db/migrate/20140729145339_migrate_project_tags.rb
@@ -1,4 +1,4 @@
-class MigrateProjectTags < ActiveRecord::Migration
+class MigrateProjectTags < ActiveRecord::Migration[4.2]
def up
ActsAsTaggableOn::Tagging.where(taggable_type: 'Project', context: 'labels').update_all(context: 'tags')
end
diff --git a/db/migrate/20140729152420_migrate_taggable_labels.rb b/db/migrate/20140729152420_migrate_taggable_labels.rb
index 04cdc6beadd..a8bf8022dfc 100644
--- a/db/migrate/20140729152420_migrate_taggable_labels.rb
+++ b/db/migrate/20140729152420_migrate_taggable_labels.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class MigrateTaggableLabels < ActiveRecord::Migration
+class MigrateTaggableLabels < ActiveRecord::Migration[4.2]
def up
taggings = ActsAsTaggableOn::Tagging.where(taggable_type: ['Issue', 'MergeRequest'], context: 'labels')
taggings.find_each(batch_size: 500) do |tagging|
diff --git a/db/migrate/20140730111702_add_index_to_labels.rb b/db/migrate/20140730111702_add_index_to_labels.rb
index cc7ac1fc449..21f9dfd5d47 100644
--- a/db/migrate/20140730111702_add_index_to_labels.rb
+++ b/db/migrate/20140730111702_add_index_to_labels.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddIndexToLabels < ActiveRecord::Migration
+class AddIndexToLabels < ActiveRecord::Migration[4.2]
def change
add_index "labels", :project_id
add_index "label_links", :label_id
diff --git a/db/migrate/20140903115954_migrate_to_new_shell.rb b/db/migrate/20140903115954_migrate_to_new_shell.rb
index 04acf24284b..cc0cce483b1 100644
--- a/db/migrate/20140903115954_migrate_to_new_shell.rb
+++ b/db/migrate/20140903115954_migrate_to_new_shell.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class MigrateToNewShell < ActiveRecord::Migration
+class MigrateToNewShell < ActiveRecord::Migration[4.2]
def change
return if Rails.env.test?
diff --git a/db/migrate/20140907220153_serialize_service_properties.rb b/db/migrate/20140907220153_serialize_service_properties.rb
index c2d67fad0ab..bf94c64654b 100644
--- a/db/migrate/20140907220153_serialize_service_properties.rb
+++ b/db/migrate/20140907220153_serialize_service_properties.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class SerializeServiceProperties < ActiveRecord::Migration
+class SerializeServiceProperties < ActiveRecord::Migration[4.2]
def change
unless column_exists?(:services, :properties)
add_column :services, :properties, :text
diff --git a/db/migrate/20140914113604_add_members_table.rb b/db/migrate/20140914113604_add_members_table.rb
index 0f76bb0ef79..312ea1b94df 100644
--- a/db/migrate/20140914113604_add_members_table.rb
+++ b/db/migrate/20140914113604_add_members_table.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddMembersTable < ActiveRecord::Migration
+class AddMembersTable < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20140914145549_migrate_to_new_members_model.rb b/db/migrate/20140914145549_migrate_to_new_members_model.rb
index b4c98f016d0..22d8b3d651b 100644
--- a/db/migrate/20140914145549_migrate_to_new_members_model.rb
+++ b/db/migrate/20140914145549_migrate_to_new_members_model.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class MigrateToNewMembersModel < ActiveRecord::Migration
+class MigrateToNewMembersModel < ActiveRecord::Migration[4.2]
def up
execute "INSERT INTO members ( user_id, source_id, source_type, access_level, notification_level, type ) SELECT user_id, group_id, 'Namespace', group_access, notification_level, 'GroupMember' FROM users_groups"
execute "INSERT INTO members ( user_id, source_id, source_type, access_level, notification_level, type ) SELECT user_id, project_id, 'Project', project_access, notification_level, 'ProjectMember' FROM users_projects"
diff --git a/db/migrate/20140914173417_remove_old_member_tables.rb b/db/migrate/20140914173417_remove_old_member_tables.rb
index d2ab326ef1f..edd69caa470 100644
--- a/db/migrate/20140914173417_remove_old_member_tables.rb
+++ b/db/migrate/20140914173417_remove_old_member_tables.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class RemoveOldMemberTables < ActiveRecord::Migration
+class RemoveOldMemberTables < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20141006143943_move_slack_service_to_webhook.rb b/db/migrate/20141006143943_move_slack_service_to_webhook.rb
index 561184615cc..1c9a1a74a4e 100644
--- a/db/migrate/20141006143943_move_slack_service_to_webhook.rb
+++ b/db/migrate/20141006143943_move_slack_service_to_webhook.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class MoveSlackServiceToWebhook < ActiveRecord::Migration
+class MoveSlackServiceToWebhook < ActiveRecord::Migration[4.2]
DOWNTIME = true
DOWNTIME_REASON = 'Move old fields "token" and "subdomain" to one single field "webhook"'
diff --git a/db/migrate/20141007100818_add_visibility_level_to_snippet.rb b/db/migrate/20141007100818_add_visibility_level_to_snippet.rb
index 0c14f75c154..9501aed8931 100644
--- a/db/migrate/20141007100818_add_visibility_level_to_snippet.rb
+++ b/db/migrate/20141007100818_add_visibility_level_to_snippet.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddVisibilityLevelToSnippet < ActiveRecord::Migration
+class AddVisibilityLevelToSnippet < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def up
diff --git a/db/migrate/20141118150935_add_audit_event.rb b/db/migrate/20141118150935_add_audit_event.rb
index 52d70b4a0ac..1e7dba568c9 100644
--- a/db/migrate/20141118150935_add_audit_event.rb
+++ b/db/migrate/20141118150935_add_audit_event.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddAuditEvent < ActiveRecord::Migration
+class AddAuditEvent < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20141121133009_add_timestamps_to_members.rb b/db/migrate/20141121133009_add_timestamps_to_members.rb
index ef6d4dedf32..cb575fc9ed7 100644
--- a/db/migrate/20141121133009_add_timestamps_to_members.rb
+++ b/db/migrate/20141121133009_add_timestamps_to_members.rb
@@ -3,7 +3,7 @@
# became a problem after commit c8e78d972a5a628870eefca0f2ccea0199c55bda which
# was added in GitLab 7.5. With this migration we ensure that all rows in
# 'members' have at least some created_at and updated_at timestamp.
-class AddTimestampsToMembers < ActiveRecord::Migration
+class AddTimestampsToMembers < ActiveRecord::Migration[4.2]
def up
execute "UPDATE members SET created_at = NOW() WHERE created_at is NULL"
execute "UPDATE members SET updated_at = NOW() WHERE updated_at is NULL"
diff --git a/db/migrate/20141121161704_add_identity_table.rb b/db/migrate/20141121161704_add_identity_table.rb
index 5a399f0d325..92f7a568077 100644
--- a/db/migrate/20141121161704_add_identity_table.rb
+++ b/db/migrate/20141121161704_add_identity_table.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddIdentityTable < ActiveRecord::Migration
+class AddIdentityTable < ActiveRecord::Migration[4.2]
def up
create_table :identities do |t|
t.string :extern_uid
diff --git a/db/migrate/20141126120926_add_merge_request_rebase_enabled_to_projects.rb b/db/migrate/20141126120926_add_merge_request_rebase_enabled_to_projects.rb
index 3dafdf0fde4..b9d8a5cb435 100644
--- a/db/migrate/20141126120926_add_merge_request_rebase_enabled_to_projects.rb
+++ b/db/migrate/20141126120926_add_merge_request_rebase_enabled_to_projects.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddMergeRequestRebaseEnabledToProjects < ActiveRecord::Migration
+class AddMergeRequestRebaseEnabledToProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20141205134006_add_locked_at_to_merge_request.rb b/db/migrate/20141205134006_add_locked_at_to_merge_request.rb
index 5aa91c7587a..6fdfb3eb974 100644
--- a/db/migrate/20141205134006_add_locked_at_to_merge_request.rb
+++ b/db/migrate/20141205134006_add_locked_at_to_merge_request.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddLockedAtToMergeRequest < ActiveRecord::Migration
+class AddLockedAtToMergeRequest < ActiveRecord::Migration[4.2]
def change
add_column :merge_requests, :locked_at, :datetime
end
diff --git a/db/migrate/20141216155758_create_doorkeeper_tables.rb b/db/migrate/20141216155758_create_doorkeeper_tables.rb
index 17e45a77291..7bd0a15e7f5 100644
--- a/db/migrate/20141216155758_create_doorkeeper_tables.rb
+++ b/db/migrate/20141216155758_create_doorkeeper_tables.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class CreateDoorkeeperTables < ActiveRecord::Migration
+class CreateDoorkeeperTables < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20141217125223_add_owner_to_application.rb b/db/migrate/20141217125223_add_owner_to_application.rb
index e5a669ab4d8..482a53f3ad5 100644
--- a/db/migrate/20141217125223_add_owner_to_application.rb
+++ b/db/migrate/20141217125223_add_owner_to_application.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddOwnerToApplication < ActiveRecord::Migration
+class AddOwnerToApplication < ActiveRecord::Migration[4.2]
def change
add_column :oauth_applications, :owner_id, :integer, null: true
add_column :oauth_applications, :owner_type, :string, null: true
diff --git a/db/migrate/20141223135007_add_import_data_to_project_table.rb b/db/migrate/20141223135007_add_import_data_to_project_table.rb
index 5db78f94cc9..516f58d645e 100644
--- a/db/migrate/20141223135007_add_import_data_to_project_table.rb
+++ b/db/migrate/20141223135007_add_import_data_to_project_table.rb
@@ -1,4 +1,4 @@
-class AddImportDataToProjectTable < ActiveRecord::Migration
+class AddImportDataToProjectTable < ActiveRecord::Migration[4.2]
def change
add_column :projects, :import_type, :string
add_column :projects, :import_source, :string
diff --git a/db/migrate/20141226080412_add_developers_can_push_to_protected_branches.rb b/db/migrate/20141226080412_add_developers_can_push_to_protected_branches.rb
index a18b2f4974d..43b7de85228 100644
--- a/db/migrate/20141226080412_add_developers_can_push_to_protected_branches.rb
+++ b/db/migrate/20141226080412_add_developers_can_push_to_protected_branches.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddDevelopersCanPushToProtectedBranches < ActiveRecord::Migration
+class AddDevelopersCanPushToProtectedBranches < ActiveRecord::Migration[4.2]
def change
add_column :protected_branches, :developers_can_push, :boolean, default: false, null: false
end
diff --git a/db/migrate/20150108073740_create_application_settings.rb b/db/migrate/20150108073740_create_application_settings.rb
index 0e4c66ca8c0..be139fee63a 100644
--- a/db/migrate/20150108073740_create_application_settings.rb
+++ b/db/migrate/20150108073740_create_application_settings.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class CreateApplicationSettings < ActiveRecord::Migration
+class CreateApplicationSettings < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20150116234544_add_home_page_url_for_application_settings.rb b/db/migrate/20150116234544_add_home_page_url_for_application_settings.rb
index aa179ce3a4d..e630e2cc878 100644
--- a/db/migrate/20150116234544_add_home_page_url_for_application_settings.rb
+++ b/db/migrate/20150116234544_add_home_page_url_for_application_settings.rb
@@ -1,4 +1,4 @@
-class AddHomePageUrlForApplicationSettings < ActiveRecord::Migration
+class AddHomePageUrlForApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :home_page_url, :string
end
diff --git a/db/migrate/20150116234545_add_gitlab_access_token_to_user.rb b/db/migrate/20150116234545_add_gitlab_access_token_to_user.rb
index c28ba3197ac..673628e106b 100644
--- a/db/migrate/20150116234545_add_gitlab_access_token_to_user.rb
+++ b/db/migrate/20150116234545_add_gitlab_access_token_to_user.rb
@@ -1,4 +1,4 @@
-class AddGitlabAccessTokenToUser < ActiveRecord::Migration
+class AddGitlabAccessTokenToUser < ActiveRecord::Migration[4.2]
def change
add_column :users, :gitlab_access_token, :string
end
diff --git a/db/migrate/20150125163100_add_default_branch_protection_setting.rb b/db/migrate/20150125163100_add_default_branch_protection_setting.rb
index 7ca3116d354..f6bfa422124 100644
--- a/db/migrate/20150125163100_add_default_branch_protection_setting.rb
+++ b/db/migrate/20150125163100_add_default_branch_protection_setting.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddDefaultBranchProtectionSetting < ActiveRecord::Migration
+class AddDefaultBranchProtectionSetting < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :default_branch_protection, :integer, :default => 2
end
diff --git a/db/migrate/20150205211843_add_timestamps_to_identities.rb b/db/migrate/20150205211843_add_timestamps_to_identities.rb
index a78e28eb4eb..c535a7ec781 100644
--- a/db/migrate/20150205211843_add_timestamps_to_identities.rb
+++ b/db/migrate/20150205211843_add_timestamps_to_identities.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddTimestampsToIdentities < ActiveRecord::Migration
+class AddTimestampsToIdentities < ActiveRecord::Migration[4.2]
def change
add_timestamps(:identities)
end
diff --git a/db/migrate/20150206181414_add_index_to_created_at.rb b/db/migrate/20150206181414_add_index_to_created_at.rb
index a161fad79dc..501acd6a720 100644
--- a/db/migrate/20150206181414_add_index_to_created_at.rb
+++ b/db/migrate/20150206181414_add_index_to_created_at.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddIndexToCreatedAt < ActiveRecord::Migration
+class AddIndexToCreatedAt < ActiveRecord::Migration[4.2]
def change
add_index "users", [:created_at, :id]
add_index "members", [:created_at, :id]
diff --git a/db/migrate/20150206222854_add_notification_email_to_user.rb b/db/migrate/20150206222854_add_notification_email_to_user.rb
index ab80f7e582f..7b0c251db4f 100644
--- a/db/migrate/20150206222854_add_notification_email_to_user.rb
+++ b/db/migrate/20150206222854_add_notification_email_to_user.rb
@@ -1,4 +1,4 @@
-class AddNotificationEmailToUser < ActiveRecord::Migration
+class AddNotificationEmailToUser < ActiveRecord::Migration[4.2]
def up
add_column :users, :notification_email, :string
diff --git a/db/migrate/20150209222013_add_missing_index.rb b/db/migrate/20150209222013_add_missing_index.rb
index 18e3ac2cbbb..99544ab3928 100644
--- a/db/migrate/20150209222013_add_missing_index.rb
+++ b/db/migrate/20150209222013_add_missing_index.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddMissingIndex < ActiveRecord::Migration
+class AddMissingIndex < ActiveRecord::Migration[4.2]
def change
add_index "services", [:created_at, :id]
end
diff --git a/db/migrate/20150211172122_add_template_to_service.rb b/db/migrate/20150211172122_add_template_to_service.rb
index a3e96b25c56..dd192a0fe76 100644
--- a/db/migrate/20150211172122_add_template_to_service.rb
+++ b/db/migrate/20150211172122_add_template_to_service.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddTemplateToService < ActiveRecord::Migration
+class AddTemplateToService < ActiveRecord::Migration[4.2]
def change
add_column :services, :template, :boolean, default: false
end
diff --git a/db/migrate/20150211174341_allow_null_in_services_project_id.rb b/db/migrate/20150211174341_allow_null_in_services_project_id.rb
index 68f02812791..4c90bf9c419 100644
--- a/db/migrate/20150211174341_allow_null_in_services_project_id.rb
+++ b/db/migrate/20150211174341_allow_null_in_services_project_id.rb
@@ -1,4 +1,4 @@
-class AllowNullInServicesProjectId < ActiveRecord::Migration
+class AllowNullInServicesProjectId < ActiveRecord::Migration[4.2]
def change
change_column :services, :project_id, :integer, null: true
end
diff --git a/db/migrate/20150213104043_add_twitter_sharing_enabled_to_application_settings.rb b/db/migrate/20150213104043_add_twitter_sharing_enabled_to_application_settings.rb
index 334020376e4..7d7b9242cd6 100644
--- a/db/migrate/20150213104043_add_twitter_sharing_enabled_to_application_settings.rb
+++ b/db/migrate/20150213104043_add_twitter_sharing_enabled_to_application_settings.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddTwitterSharingEnabledToApplicationSettings < ActiveRecord::Migration
+class AddTwitterSharingEnabledToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :twitter_sharing_enabled, :boolean, default: true
end
diff --git a/db/migrate/20150213114800_add_hide_no_password_to_user.rb b/db/migrate/20150213114800_add_hide_no_password_to_user.rb
index a2af3510b9c..348c0d22aba 100644
--- a/db/migrate/20150213114800_add_hide_no_password_to_user.rb
+++ b/db/migrate/20150213114800_add_hide_no_password_to_user.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddHideNoPasswordToUser < ActiveRecord::Migration
+class AddHideNoPasswordToUser < ActiveRecord::Migration[4.2]
def change
add_column :users, :hide_no_password, :boolean, default: false
end
diff --git a/db/migrate/20150213121042_add_password_automatically_set_to_user.rb b/db/migrate/20150213121042_add_password_automatically_set_to_user.rb
index 4e84a13f0d2..d0eb753b887 100644
--- a/db/migrate/20150213121042_add_password_automatically_set_to_user.rb
+++ b/db/migrate/20150213121042_add_password_automatically_set_to_user.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddPasswordAutomaticallySetToUser < ActiveRecord::Migration
+class AddPasswordAutomaticallySetToUser < ActiveRecord::Migration[4.2]
def change
add_column :users, :password_automatically_set, :boolean, default: false
end
diff --git a/db/migrate/20150217123345_add_bitbucket_access_token_and_secret_to_user.rb b/db/migrate/20150217123345_add_bitbucket_access_token_and_secret_to_user.rb
index 23ac1b399ec..639644174ca 100644
--- a/db/migrate/20150217123345_add_bitbucket_access_token_and_secret_to_user.rb
+++ b/db/migrate/20150217123345_add_bitbucket_access_token_and_secret_to_user.rb
@@ -1,4 +1,4 @@
-class AddBitbucketAccessTokenAndSecretToUser < ActiveRecord::Migration
+class AddBitbucketAccessTokenAndSecretToUser < ActiveRecord::Migration[4.2]
def change
add_column :users, :bitbucket_access_token, :string
add_column :users, :bitbucket_access_token_secret, :string
diff --git a/db/migrate/20150219004514_add_events_to_services.rb b/db/migrate/20150219004514_add_events_to_services.rb
index 560382c3fa1..7072056adcb 100644
--- a/db/migrate/20150219004514_add_events_to_services.rb
+++ b/db/migrate/20150219004514_add_events_to_services.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddEventsToServices < ActiveRecord::Migration
+class AddEventsToServices < ActiveRecord::Migration[4.2]
def change
add_column :services, :push_events, :boolean, :default => true
add_column :services, :issues_events, :boolean, :default => true
diff --git a/db/migrate/20150223022001_set_missing_last_activity_at.rb b/db/migrate/20150223022001_set_missing_last_activity_at.rb
index 3f6d4d83474..c77ffbd4ebd 100644
--- a/db/migrate/20150223022001_set_missing_last_activity_at.rb
+++ b/db/migrate/20150223022001_set_missing_last_activity_at.rb
@@ -1,4 +1,4 @@
-class SetMissingLastActivityAt < ActiveRecord::Migration
+class SetMissingLastActivityAt < ActiveRecord::Migration[4.2]
def up
execute "UPDATE projects SET last_activity_at = updated_at WHERE last_activity_at IS NULL"
end
diff --git a/db/migrate/20150225065047_add_note_events_to_services.rb b/db/migrate/20150225065047_add_note_events_to_services.rb
index 7843cabc43b..32c538e8681 100644
--- a/db/migrate/20150225065047_add_note_events_to_services.rb
+++ b/db/migrate/20150225065047_add_note_events_to_services.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddNoteEventsToServices < ActiveRecord::Migration
+class AddNoteEventsToServices < ActiveRecord::Migration[4.2]
def change
add_column :services, :note_events, :boolean, default: true, null: false
end
diff --git a/db/migrate/20150301014758_add_restricted_visibility_levels_to_application_settings.rb b/db/migrate/20150301014758_add_restricted_visibility_levels_to_application_settings.rb
index 494c3033bff..3091790f199 100644
--- a/db/migrate/20150301014758_add_restricted_visibility_levels_to_application_settings.rb
+++ b/db/migrate/20150301014758_add_restricted_visibility_levels_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddRestrictedVisibilityLevelsToApplicationSettings < ActiveRecord::Migration
+class AddRestrictedVisibilityLevelsToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :restricted_visibility_levels, :text
end
diff --git a/db/migrate/20150306023106_fix_namespace_duplication.rb b/db/migrate/20150306023106_fix_namespace_duplication.rb
index ea53a9d71f2..49be152a75c 100644
--- a/db/migrate/20150306023106_fix_namespace_duplication.rb
+++ b/db/migrate/20150306023106_fix_namespace_duplication.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class FixNamespaceDuplication < ActiveRecord::Migration
+class FixNamespaceDuplication < ActiveRecord::Migration[4.2]
def up
#fixes path duplication
select_all('SELECT MAX(id) max, COUNT(id) cnt, path FROM namespaces GROUP BY path HAVING COUNT(id) > 1').each do |nms|
diff --git a/db/migrate/20150306023112_add_unique_index_to_namespace.rb b/db/migrate/20150306023112_add_unique_index_to_namespace.rb
index f293a9b643f..11472324cbf 100644
--- a/db/migrate/20150306023112_add_unique_index_to_namespace.rb
+++ b/db/migrate/20150306023112_add_unique_index_to_namespace.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddUniqueIndexToNamespace < ActiveRecord::Migration
+class AddUniqueIndexToNamespace < ActiveRecord::Migration[4.2]
def change
remove_index :namespaces, column: :name if index_exists?(:namespaces, :name)
remove_index :namespaces, column: :path if index_exists?(:namespaces, :path)
diff --git a/db/migrate/20150310194358_add_version_check_to_application_settings.rb b/db/migrate/20150310194358_add_version_check_to_application_settings.rb
index 5d3dae6e7d8..cc1b19f302e 100644
--- a/db/migrate/20150310194358_add_version_check_to_application_settings.rb
+++ b/db/migrate/20150310194358_add_version_check_to_application_settings.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddVersionCheckToApplicationSettings < ActiveRecord::Migration
+class AddVersionCheckToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :version_check_enabled, :boolean, default: true
end
diff --git a/db/migrate/20150313012111_create_subscriptions_table.rb b/db/migrate/20150313012111_create_subscriptions_table.rb
index a9a8435330d..37011504b49 100644
--- a/db/migrate/20150313012111_create_subscriptions_table.rb
+++ b/db/migrate/20150313012111_create_subscriptions_table.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class CreateSubscriptionsTable < ActiveRecord::Migration
+class CreateSubscriptionsTable < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20150320234437_add_location_to_user.rb b/db/migrate/20150320234437_add_location_to_user.rb
index 32731d37d75..cf273ff916e 100644
--- a/db/migrate/20150320234437_add_location_to_user.rb
+++ b/db/migrate/20150320234437_add_location_to_user.rb
@@ -1,4 +1,4 @@
-class AddLocationToUser < ActiveRecord::Migration
+class AddLocationToUser < ActiveRecord::Migration[4.2]
def change
add_column :users, :location, :string
end
diff --git a/db/migrate/20150324155957_set_incorrect_assignee_id_to_null.rb b/db/migrate/20150324155957_set_incorrect_assignee_id_to_null.rb
index 42dc8173e46..a895d5f24f5 100644
--- a/db/migrate/20150324155957_set_incorrect_assignee_id_to_null.rb
+++ b/db/migrate/20150324155957_set_incorrect_assignee_id_to_null.rb
@@ -1,4 +1,4 @@
-class SetIncorrectAssigneeIdToNull < ActiveRecord::Migration
+class SetIncorrectAssigneeIdToNull < ActiveRecord::Migration[4.2]
def up
execute "UPDATE issues SET assignee_id = NULL WHERE assignee_id = -1"
execute "UPDATE merge_requests SET assignee_id = NULL WHERE assignee_id = -1"
diff --git a/db/migrate/20150327122227_add_public_to_key.rb b/db/migrate/20150327122227_add_public_to_key.rb
index 33c20d65e03..58d8c16476f 100644
--- a/db/migrate/20150327122227_add_public_to_key.rb
+++ b/db/migrate/20150327122227_add_public_to_key.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddPublicToKey < ActiveRecord::Migration
+class AddPublicToKey < ActiveRecord::Migration[4.2]
def change
add_column :keys, :public, :boolean, default: false, null: false
end
diff --git a/db/migrate/20150327150017_add_import_data_to_project.rb b/db/migrate/20150327150017_add_import_data_to_project.rb
index 12c00339eec..5d393364ee6 100644
--- a/db/migrate/20150327150017_add_import_data_to_project.rb
+++ b/db/migrate/20150327150017_add_import_data_to_project.rb
@@ -1,4 +1,4 @@
-class AddImportDataToProject < ActiveRecord::Migration
+class AddImportDataToProject < ActiveRecord::Migration[4.2]
def change
add_column :projects, :import_data, :text
end
diff --git a/db/migrate/20150327223628_add_devise_two_factor_to_users.rb b/db/migrate/20150327223628_add_devise_two_factor_to_users.rb
index 11b026ee8f3..22202796547 100644
--- a/db/migrate/20150327223628_add_devise_two_factor_to_users.rb
+++ b/db/migrate/20150327223628_add_devise_two_factor_to_users.rb
@@ -1,4 +1,4 @@
-class AddDeviseTwoFactorToUsers < ActiveRecord::Migration
+class AddDeviseTwoFactorToUsers < ActiveRecord::Migration[4.2]
def change
add_column :users, :encrypted_otp_secret, :string
add_column :users, :encrypted_otp_secret_iv, :string
diff --git a/db/migrate/20150328132231_add_max_attachment_size_to_application_settings.rb b/db/migrate/20150328132231_add_max_attachment_size_to_application_settings.rb
index 1d161674a9a..4ce60a257cb 100644
--- a/db/migrate/20150328132231_add_max_attachment_size_to_application_settings.rb
+++ b/db/migrate/20150328132231_add_max_attachment_size_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddMaxAttachmentSizeToApplicationSettings < ActiveRecord::Migration
+class AddMaxAttachmentSizeToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :max_attachment_size, :integer, default: 10, null: false
end
diff --git a/db/migrate/20150331183602_add_devise_two_factor_backupable_to_users.rb b/db/migrate/20150331183602_add_devise_two_factor_backupable_to_users.rb
index 913958db7c5..792b98c91f0 100644
--- a/db/migrate/20150331183602_add_devise_two_factor_backupable_to_users.rb
+++ b/db/migrate/20150331183602_add_devise_two_factor_backupable_to_users.rb
@@ -1,4 +1,4 @@
-class AddDeviseTwoFactorBackupableToUsers < ActiveRecord::Migration
+class AddDeviseTwoFactorBackupableToUsers < ActiveRecord::Migration[4.2]
def change
add_column :users, :otp_backup_codes, :text
end
diff --git a/db/migrate/20150406133311_add_invite_data_to_member.rb b/db/migrate/20150406133311_add_invite_data_to_member.rb
index 63d0f184f32..eee991185ab 100644
--- a/db/migrate/20150406133311_add_invite_data_to_member.rb
+++ b/db/migrate/20150406133311_add_invite_data_to_member.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddInviteDataToMember < ActiveRecord::Migration
+class AddInviteDataToMember < ActiveRecord::Migration[4.2]
def up
add_column :members, :created_by_id, :integer
add_column :members, :invite_email, :string
diff --git a/db/migrate/20150411000035_fix_identities.rb b/db/migrate/20150411000035_fix_identities.rb
index d9051f9fffd..a449fc51ecc 100644
--- a/db/migrate/20150411000035_fix_identities.rb
+++ b/db/migrate/20150411000035_fix_identities.rb
@@ -1,4 +1,4 @@
-class FixIdentities < ActiveRecord::Migration
+class FixIdentities < ActiveRecord::Migration[4.2]
def up
# Up until now, legacy 'ldap' references in the database were charitably
# interpreted to point to the first LDAP server specified in the GitLab
diff --git a/db/migrate/20150411180045_rename_buildbox_service.rb b/db/migrate/20150411180045_rename_buildbox_service.rb
index 5a0b5d07e50..ac4ccdfb723 100644
--- a/db/migrate/20150411180045_rename_buildbox_service.rb
+++ b/db/migrate/20150411180045_rename_buildbox_service.rb
@@ -1,4 +1,4 @@
-class RenameBuildboxService < ActiveRecord::Migration
+class RenameBuildboxService < ActiveRecord::Migration[4.2]
def up
execute "UPDATE services SET type = 'BuildkiteService' WHERE type = 'BuildboxService';"
end
diff --git a/db/migrate/20150413192223_add_public_email_to_users.rb b/db/migrate/20150413192223_add_public_email_to_users.rb
index 0fed5eaf461..991f0c668c3 100644
--- a/db/migrate/20150413192223_add_public_email_to_users.rb
+++ b/db/migrate/20150413192223_add_public_email_to_users.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddPublicEmailToUsers < ActiveRecord::Migration
+class AddPublicEmailToUsers < ActiveRecord::Migration[4.2]
def change
add_column :users, :public_email, :string, default: "", null: false
end
diff --git a/db/migrate/20150417121913_create_project_import_data.rb b/db/migrate/20150417121913_create_project_import_data.rb
index c78f5fde85e..383f64fd2c6 100644
--- a/db/migrate/20150417121913_create_project_import_data.rb
+++ b/db/migrate/20150417121913_create_project_import_data.rb
@@ -1,4 +1,4 @@
-class CreateProjectImportData < ActiveRecord::Migration
+class CreateProjectImportData < ActiveRecord::Migration[4.2]
def change
create_table :project_import_data do |t|
t.references :project
diff --git a/db/migrate/20150417122318_remove_import_data_from_project.rb b/db/migrate/20150417122318_remove_import_data_from_project.rb
index 5a008218fa5..c9a225a9d17 100644
--- a/db/migrate/20150417122318_remove_import_data_from_project.rb
+++ b/db/migrate/20150417122318_remove_import_data_from_project.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class RemoveImportDataFromProject < ActiveRecord::Migration
+class RemoveImportDataFromProject < ActiveRecord::Migration[4.2]
def up
remove_column :projects, :import_data
end
diff --git a/db/migrate/20150421120000_remove_periods_at_ends_of_usernames.rb b/db/migrate/20150421120000_remove_periods_at_ends_of_usernames.rb
index 3445e9ce59e..d2e7656c9d4 100644
--- a/db/migrate/20150421120000_remove_periods_at_ends_of_usernames.rb
+++ b/db/migrate/20150421120000_remove_periods_at_ends_of_usernames.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class RemovePeriodsAtEndsOfUsernames < ActiveRecord::Migration
+class RemovePeriodsAtEndsOfUsernames < ActiveRecord::Migration[4.2]
include Gitlab::ShellAdapter
class Namespace < ActiveRecord::Base
diff --git a/db/migrate/20150423033240_add_default_project_visibililty_to_application_settings.rb b/db/migrate/20150423033240_add_default_project_visibililty_to_application_settings.rb
index 50a9b2439e0..e0f35da422a 100644
--- a/db/migrate/20150423033240_add_default_project_visibililty_to_application_settings.rb
+++ b/db/migrate/20150423033240_add_default_project_visibililty_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddDefaultProjectVisibililtyToApplicationSettings < ActiveRecord::Migration
+class AddDefaultProjectVisibililtyToApplicationSettings < ActiveRecord::Migration[4.2]
def up
add_column :application_settings, :default_project_visibility, :integer
visibility = Settings.gitlab.default_projects_features['visibility_level']
diff --git a/db/migrate/20150425164646_gitlab_change_collation_for_tag_names.acts_as_taggable_on_engine.rb b/db/migrate/20150425164646_gitlab_change_collation_for_tag_names.acts_as_taggable_on_engine.rb
index 281c88d2a7d..5b2e692eb17 100644
--- a/db/migrate/20150425164646_gitlab_change_collation_for_tag_names.acts_as_taggable_on_engine.rb
+++ b/db/migrate/20150425164646_gitlab_change_collation_for_tag_names.acts_as_taggable_on_engine.rb
@@ -1,7 +1,7 @@
# This migration is a duplicate of 20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb
# It shold be applied before the index additions to ensure that `name` is case sensitive.
-class GitlabChangeCollationForTagNames < ActiveRecord::Migration
+class GitlabChangeCollationForTagNames < ActiveRecord::Migration[4.2]
def up
if ActsAsTaggableOn::Utils.using_mysql?
execute("ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;")
diff --git a/db/migrate/20150425164647_remove_duplicate_tags.rb b/db/migrate/20150425164647_remove_duplicate_tags.rb
index e77623bf507..5165eb65695 100644
--- a/db/migrate/20150425164647_remove_duplicate_tags.rb
+++ b/db/migrate/20150425164647_remove_duplicate_tags.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class RemoveDuplicateTags < ActiveRecord::Migration
+class RemoveDuplicateTags < ActiveRecord::Migration[4.2]
def up
select_all("SELECT name, COUNT(id) as cnt FROM tags GROUP BY name HAVING COUNT(id) > 1").each do |tag|
tag_name = quote_string(tag["name"])
diff --git a/db/migrate/20150425164648_add_missing_unique_indices.acts_as_taggable_on_engine.rb b/db/migrate/20150425164648_add_missing_unique_indices.acts_as_taggable_on_engine.rb
index cbff98cdbc4..d1951f640bb 100644
--- a/db/migrate/20150425164648_add_missing_unique_indices.acts_as_taggable_on_engine.rb
+++ b/db/migrate/20150425164648_add_missing_unique_indices.acts_as_taggable_on_engine.rb
@@ -1,6 +1,6 @@
# rubocop:disable all
# This migration comes from acts_as_taggable_on_engine (originally 2)
-class AddMissingUniqueIndices < ActiveRecord::Migration
+class AddMissingUniqueIndices < ActiveRecord::Migration[4.2]
def self.up
add_index :tags, :name, unique: true
diff --git a/db/migrate/20150425164649_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb b/db/migrate/20150425164649_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb
index 1568d2dd4ce..b9af394f09b 100644
--- a/db/migrate/20150425164649_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb
+++ b/db/migrate/20150425164649_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb
@@ -1,6 +1,6 @@
# rubocop:disable all
# This migration comes from acts_as_taggable_on_engine (originally 3)
-class AddTaggingsCounterCacheToTags < ActiveRecord::Migration
+class AddTaggingsCounterCacheToTags < ActiveRecord::Migration[4.2]
def self.up
add_column :tags, :taggings_count, :integer, default: 0
diff --git a/db/migrate/20150425164650_add_missing_taggable_index.acts_as_taggable_on_engine.rb b/db/migrate/20150425164650_add_missing_taggable_index.acts_as_taggable_on_engine.rb
index 71f2d7f4330..f28737615d7 100644
--- a/db/migrate/20150425164650_add_missing_taggable_index.acts_as_taggable_on_engine.rb
+++ b/db/migrate/20150425164650_add_missing_taggable_index.acts_as_taggable_on_engine.rb
@@ -1,5 +1,5 @@
# This migration comes from acts_as_taggable_on_engine (originally 4)
-class AddMissingTaggableIndex < ActiveRecord::Migration
+class AddMissingTaggableIndex < ActiveRecord::Migration[4.2]
def self.up
add_index :taggings, [:taggable_id, :taggable_type, :context]
end
diff --git a/db/migrate/20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb b/db/migrate/20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb
index bfb06bc7cda..4c144a8693f 100644
--- a/db/migrate/20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb
+++ b/db/migrate/20150425164651_change_collation_for_tag_names.acts_as_taggable_on_engine.rb
@@ -1,7 +1,7 @@
# This migration comes from acts_as_taggable_on_engine (originally 5)
# This migration is added to circumvent issue #623 and have special characters
# work properly
-class ChangeCollationForTagNames < ActiveRecord::Migration
+class ChangeCollationForTagNames < ActiveRecord::Migration[4.2]
def up
if ActsAsTaggableOn::Utils.using_mysql?
execute("ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;")
diff --git a/db/migrate/20150425173433_add_default_snippet_visibility_to_app_settings.rb b/db/migrate/20150425173433_add_default_snippet_visibility_to_app_settings.rb
index 8f1b0cc8935..a3a86d26767 100644
--- a/db/migrate/20150425173433_add_default_snippet_visibility_to_app_settings.rb
+++ b/db/migrate/20150425173433_add_default_snippet_visibility_to_app_settings.rb
@@ -1,4 +1,4 @@
-class AddDefaultSnippetVisibilityToAppSettings < ActiveRecord::Migration
+class AddDefaultSnippetVisibilityToAppSettings < ActiveRecord::Migration[4.2]
def up
add_column :application_settings, :default_snippet_visibility, :integer
visibility = Settings.gitlab.default_projects_features['visibility_level']
diff --git a/db/migrate/20150429002313_remove_abandoned_group_members_records.rb b/db/migrate/20150429002313_remove_abandoned_group_members_records.rb
index 244637e1c4a..370b807dd50 100644
--- a/db/migrate/20150429002313_remove_abandoned_group_members_records.rb
+++ b/db/migrate/20150429002313_remove_abandoned_group_members_records.rb
@@ -1,4 +1,4 @@
-class RemoveAbandonedGroupMembersRecords < ActiveRecord::Migration
+class RemoveAbandonedGroupMembersRecords < ActiveRecord::Migration[4.2]
def up
execute("DELETE FROM members WHERE type = 'GroupMember' AND source_id NOT IN(\
SELECT id FROM namespaces WHERE type='Group')")
diff --git a/db/migrate/20150502064022_add_restricted_signup_domains_to_application_settings.rb b/db/migrate/20150502064022_add_restricted_signup_domains_to_application_settings.rb
index 184e2653610..df777263ecb 100644
--- a/db/migrate/20150502064022_add_restricted_signup_domains_to_application_settings.rb
+++ b/db/migrate/20150502064022_add_restricted_signup_domains_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddRestrictedSignupDomainsToApplicationSettings < ActiveRecord::Migration
+class AddRestrictedSignupDomainsToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :restricted_signup_domains, :text
end
diff --git a/db/migrate/20150509180749_convert_legacy_reference_notes.rb b/db/migrate/20150509180749_convert_legacy_reference_notes.rb
index b02605489be..a44a908c2f5 100644
--- a/db/migrate/20150509180749_convert_legacy_reference_notes.rb
+++ b/db/migrate/20150509180749_convert_legacy_reference_notes.rb
@@ -5,7 +5,7 @@
# becomes
#
# mentioned in 54f7727c850972f0401c1312a7c4a6a380de5666
-class ConvertLegacyReferenceNotes < ActiveRecord::Migration
+class ConvertLegacyReferenceNotes < ActiveRecord::Migration[4.2]
def up
execute %q{UPDATE notes SET note = trim(both '_' from note) WHERE system = true AND note LIKE '\_%\_'}
end
diff --git a/db/migrate/20150516060434_add_note_events_to_web_hooks.rb b/db/migrate/20150516060434_add_note_events_to_web_hooks.rb
index bf72e5e2e3a..ddf26240b8b 100644
--- a/db/migrate/20150516060434_add_note_events_to_web_hooks.rb
+++ b/db/migrate/20150516060434_add_note_events_to_web_hooks.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddNoteEventsToWebHooks < ActiveRecord::Migration
+class AddNoteEventsToWebHooks < ActiveRecord::Migration[4.2]
def up
add_column :web_hooks, :note_events, :boolean, default: false, null: false
end
diff --git a/db/migrate/20150529111607_add_user_oauth_applications_to_application_settings.rb b/db/migrate/20150529111607_add_user_oauth_applications_to_application_settings.rb
index 6a78294f0b2..507e905acd6 100644
--- a/db/migrate/20150529111607_add_user_oauth_applications_to_application_settings.rb
+++ b/db/migrate/20150529111607_add_user_oauth_applications_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddUserOauthApplicationsToApplicationSettings < ActiveRecord::Migration
+class AddUserOauthApplicationsToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :user_oauth_applications, :bool, default: true
end
diff --git a/db/migrate/20150529150354_add_after_sign_out_path_for_application_settings.rb b/db/migrate/20150529150354_add_after_sign_out_path_for_application_settings.rb
index 833c36de52d..f43f20def5b 100644
--- a/db/migrate/20150529150354_add_after_sign_out_path_for_application_settings.rb
+++ b/db/migrate/20150529150354_add_after_sign_out_path_for_application_settings.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddAfterSignOutPathForApplicationSettings < ActiveRecord::Migration
+class AddAfterSignOutPathForApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :after_sign_out_path, :string
end
diff --git a/db/migrate/20150609141121_add_session_expire_delay_for_application_settings.rb b/db/migrate/20150609141121_add_session_expire_delay_for_application_settings.rb
index 61ff0af41f4..93959a9010f 100644
--- a/db/migrate/20150609141121_add_session_expire_delay_for_application_settings.rb
+++ b/db/migrate/20150609141121_add_session_expire_delay_for_application_settings.rb
@@ -1,4 +1,4 @@
-class AddSessionExpireDelayForApplicationSettings < ActiveRecord::Migration
+class AddSessionExpireDelayForApplicationSettings < ActiveRecord::Migration[4.2]
def change
unless column_exists?(:application_settings, :session_expire_delay)
add_column :application_settings, :session_expire_delay, :integer, default: 10080, null: false
diff --git a/db/migrate/20150610065936_add_dashboard_to_users.rb b/db/migrate/20150610065936_add_dashboard_to_users.rb
index df38472f893..a0bf5f31f00 100644
--- a/db/migrate/20150610065936_add_dashboard_to_users.rb
+++ b/db/migrate/20150610065936_add_dashboard_to_users.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddDashboardToUsers < ActiveRecord::Migration
+class AddDashboardToUsers < ActiveRecord::Migration[4.2]
def up
add_column :users, :dashboard, :integer, default: 0
end
diff --git a/db/migrate/20150620233230_add_default_otp_required_for_login_value.rb b/db/migrate/20150620233230_add_default_otp_required_for_login_value.rb
index 8eed8678b2f..4a085ff06f3 100644
--- a/db/migrate/20150620233230_add_default_otp_required_for_login_value.rb
+++ b/db/migrate/20150620233230_add_default_otp_required_for_login_value.rb
@@ -1,4 +1,4 @@
-class AddDefaultOtpRequiredForLoginValue < ActiveRecord::Migration
+class AddDefaultOtpRequiredForLoginValue < ActiveRecord::Migration[4.2]
def up
execute %q{UPDATE users SET otp_required_for_login = FALSE WHERE otp_required_for_login IS NULL}
diff --git a/db/migrate/20150713160110_add_project_view_to_users.rb b/db/migrate/20150713160110_add_project_view_to_users.rb
index 0de5a93035c..fea63576187 100644
--- a/db/migrate/20150713160110_add_project_view_to_users.rb
+++ b/db/migrate/20150713160110_add_project_view_to_users.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddProjectViewToUsers < ActiveRecord::Migration
+class AddProjectViewToUsers < ActiveRecord::Migration[4.2]
def change
add_column :users, :project_view, :integer, default: 0
end
diff --git a/db/migrate/20150717130904_add_commits_count_to_project.rb b/db/migrate/20150717130904_add_commits_count_to_project.rb
index 5799e068c69..df6c88f2961 100644
--- a/db/migrate/20150717130904_add_commits_count_to_project.rb
+++ b/db/migrate/20150717130904_add_commits_count_to_project.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddCommitsCountToProject < ActiveRecord::Migration
+class AddCommitsCountToProject < ActiveRecord::Migration[4.2]
def change
add_column :projects, :commit_count, :integer, default: 0
end
diff --git a/db/migrate/20150730122406_add_updated_by_to_issuables_and_notes.rb b/db/migrate/20150730122406_add_updated_by_to_issuables_and_notes.rb
index 78d45c7f96b..fab126c3d04 100644
--- a/db/migrate/20150730122406_add_updated_by_to_issuables_and_notes.rb
+++ b/db/migrate/20150730122406_add_updated_by_to_issuables_and_notes.rb
@@ -1,4 +1,4 @@
-class AddUpdatedByToIssuablesAndNotes < ActiveRecord::Migration
+class AddUpdatedByToIssuablesAndNotes < ActiveRecord::Migration[4.2]
def change
add_column :notes, :updated_by_id, :integer
add_column :issues, :updated_by_id, :integer
diff --git a/db/migrate/20150806104937_create_abuse_reports.rb b/db/migrate/20150806104937_create_abuse_reports.rb
index 52aed9e1d1d..be4fe8d1cfd 100644
--- a/db/migrate/20150806104937_create_abuse_reports.rb
+++ b/db/migrate/20150806104937_create_abuse_reports.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class CreateAbuseReports < ActiveRecord::Migration
+class CreateAbuseReports < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20150812080800_add_settings_import_sources.rb b/db/migrate/20150812080800_add_settings_import_sources.rb
index 07f417fa3e3..59db31c868a 100644
--- a/db/migrate/20150812080800_add_settings_import_sources.rb
+++ b/db/migrate/20150812080800_add_settings_import_sources.rb
@@ -1,7 +1,7 @@
# rubocop:disable all
require 'yaml'
-class AddSettingsImportSources < ActiveRecord::Migration
+class AddSettingsImportSources < ActiveRecord::Migration[4.2]
def change
unless column_exists?(:application_settings, :import_sources)
add_column :application_settings, :import_sources, :text
diff --git a/db/migrate/20150814065925_remove_oauth_tokens_from_users.rb b/db/migrate/20150814065925_remove_oauth_tokens_from_users.rb
index 7eaa7eda311..f0080ee0b46 100644
--- a/db/migrate/20150814065925_remove_oauth_tokens_from_users.rb
+++ b/db/migrate/20150814065925_remove_oauth_tokens_from_users.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class RemoveOauthTokensFromUsers < ActiveRecord::Migration
+class RemoveOauthTokensFromUsers < ActiveRecord::Migration[4.2]
def change
remove_column :users, :github_access_token, :string
remove_column :users, :gitlab_access_token, :string
diff --git a/db/migrate/20150817163600_deduplicate_user_identities.rb b/db/migrate/20150817163600_deduplicate_user_identities.rb
index b0cfad7d20f..973a87e07ea 100644
--- a/db/migrate/20150817163600_deduplicate_user_identities.rb
+++ b/db/migrate/20150817163600_deduplicate_user_identities.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class DeduplicateUserIdentities < ActiveRecord::Migration
+class DeduplicateUserIdentities < ActiveRecord::Migration[4.2]
def change
execute 'DROP TABLE IF EXISTS tt_migration_DeduplicateUserIdentities;'
execute 'CREATE TABLE tt_migration_DeduplicateUserIdentities AS SELECT id,provider,user_id FROM identities;'
diff --git a/db/migrate/20150818213832_add_sent_notifications.rb b/db/migrate/20150818213832_add_sent_notifications.rb
index 43e8d6a1a82..45e95a843e1 100644
--- a/db/migrate/20150818213832_add_sent_notifications.rb
+++ b/db/migrate/20150818213832_add_sent_notifications.rb
@@ -1,4 +1,4 @@
-class AddSentNotifications < ActiveRecord::Migration
+class AddSentNotifications < ActiveRecord::Migration[4.2]
def change
create_table :sent_notifications do |t|
t.references :project
diff --git a/db/migrate/20150824002011_add_enable_ssl_verification.rb b/db/migrate/20150824002011_add_enable_ssl_verification.rb
index 6e992f08834..2d877914f39 100644
--- a/db/migrate/20150824002011_add_enable_ssl_verification.rb
+++ b/db/migrate/20150824002011_add_enable_ssl_verification.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddEnableSslVerification < ActiveRecord::Migration
+class AddEnableSslVerification < ActiveRecord::Migration[4.2]
def change
add_column :web_hooks, :enable_ssl_verification, :boolean, default: false
end
diff --git a/db/migrate/20150826001931_add_ci_tables.rb b/db/migrate/20150826001931_add_ci_tables.rb
index d1f8506d1fe..aa2af44a15b 100644
--- a/db/migrate/20150826001931_add_ci_tables.rb
+++ b/db/migrate/20150826001931_add_ci_tables.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddCiTables < ActiveRecord::Migration
+class AddCiTables < ActiveRecord::Migration[4.2]
def change
create_table "ci_application_settings", force: true do |t|
t.boolean "all_broken_builds"
diff --git a/db/migrate/20150827121444_add_fast_forward_option_to_project.rb b/db/migrate/20150827121444_add_fast_forward_option_to_project.rb
index 35df121519e..bf7db2fb12b 100644
--- a/db/migrate/20150827121444_add_fast_forward_option_to_project.rb
+++ b/db/migrate/20150827121444_add_fast_forward_option_to_project.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddFastForwardOptionToProject < ActiveRecord::Migration
+class AddFastForwardOptionToProject < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20150902001023_add_template_to_label.rb b/db/migrate/20150902001023_add_template_to_label.rb
index 0f6ae8d6cc3..10769f29baa 100644
--- a/db/migrate/20150902001023_add_template_to_label.rb
+++ b/db/migrate/20150902001023_add_template_to_label.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddTemplateToLabel < ActiveRecord::Migration
+class AddTemplateToLabel < ActiveRecord::Migration[4.2]
def change
add_column :labels, :template, :boolean, default: false
end
diff --git a/db/migrate/20150914215247_add_ci_tags.rb b/db/migrate/20150914215247_add_ci_tags.rb
index b647bc9c8a2..9afa4540540 100644
--- a/db/migrate/20150914215247_add_ci_tags.rb
+++ b/db/migrate/20150914215247_add_ci_tags.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddCiTags < ActiveRecord::Migration
+class AddCiTags < ActiveRecord::Migration[4.2]
def change
create_table "ci_taggings", force: true do |t|
t.integer "tag_id"
diff --git a/db/migrate/20150915001905_enable_ssl_verification_by_default.rb b/db/migrate/20150915001905_enable_ssl_verification_by_default.rb
index 6e924262a13..ddd07179753 100644
--- a/db/migrate/20150915001905_enable_ssl_verification_by_default.rb
+++ b/db/migrate/20150915001905_enable_ssl_verification_by_default.rb
@@ -1,4 +1,4 @@
-class EnableSslVerificationByDefault < ActiveRecord::Migration
+class EnableSslVerificationByDefault < ActiveRecord::Migration[4.2]
def change
change_column :web_hooks, :enable_ssl_verification, :boolean, default: true
end
diff --git a/db/migrate/20150916000405_enable_ssl_verification_for_web_hooks.rb b/db/migrate/20150916000405_enable_ssl_verification_for_web_hooks.rb
index 90ce6c2db3d..49081c9d749 100644
--- a/db/migrate/20150916000405_enable_ssl_verification_for_web_hooks.rb
+++ b/db/migrate/20150916000405_enable_ssl_verification_for_web_hooks.rb
@@ -1,4 +1,4 @@
-class EnableSslVerificationForWebHooks < ActiveRecord::Migration
+class EnableSslVerificationForWebHooks < ActiveRecord::Migration[4.2]
def up
execute("UPDATE web_hooks SET enable_ssl_verification = true")
end
diff --git a/db/migrate/20150916114643_add_help_page_text_to_application_settings.rb b/db/migrate/20150916114643_add_help_page_text_to_application_settings.rb
index 37a27f11935..52867632880 100644
--- a/db/migrate/20150916114643_add_help_page_text_to_application_settings.rb
+++ b/db/migrate/20150916114643_add_help_page_text_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddHelpPageTextToApplicationSettings < ActiveRecord::Migration
+class AddHelpPageTextToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :help_page_text, :text
end
diff --git a/db/migrate/20150916145038_add_index_for_committed_at_and_id.rb b/db/migrate/20150916145038_add_index_for_committed_at_and_id.rb
index a18ed93cf37..bf78aacd9f4 100644
--- a/db/migrate/20150916145038_add_index_for_committed_at_and_id.rb
+++ b/db/migrate/20150916145038_add_index_for_committed_at_and_id.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddIndexForCommittedAtAndId < ActiveRecord::Migration
+class AddIndexForCommittedAtAndId < ActiveRecord::Migration[4.2]
def change
add_index :ci_commits, [:project_id, :committed_at, :id]
end
diff --git a/db/migrate/20150918084513_add_ci_enabled_to_application_settings.rb b/db/migrate/20150918084513_add_ci_enabled_to_application_settings.rb
index 6cf668a170e..153c1a798c3 100644
--- a/db/migrate/20150918084513_add_ci_enabled_to_application_settings.rb
+++ b/db/migrate/20150918084513_add_ci_enabled_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddCiEnabledToApplicationSettings < ActiveRecord::Migration
+class AddCiEnabledToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :ci_enabled, :boolean, null: false, default: true
end
diff --git a/db/migrate/20150918161719_remove_invalid_milestones_from_merge_requests.rb b/db/migrate/20150918161719_remove_invalid_milestones_from_merge_requests.rb
index 0aad6fe5e6e..52651e16324 100644
--- a/db/migrate/20150918161719_remove_invalid_milestones_from_merge_requests.rb
+++ b/db/migrate/20150918161719_remove_invalid_milestones_from_merge_requests.rb
@@ -1,4 +1,4 @@
-class RemoveInvalidMilestonesFromMergeRequests < ActiveRecord::Migration
+class RemoveInvalidMilestonesFromMergeRequests < ActiveRecord::Migration[4.2]
def up
execute("UPDATE merge_requests SET milestone_id = NULL where milestone_id NOT IN (SELECT id FROM milestones)")
end
diff --git a/db/migrate/20150920010715_add_consumed_timestep_to_users.rb b/db/migrate/20150920010715_add_consumed_timestep_to_users.rb
index c8438b3f6aa..c69944b1e94 100644
--- a/db/migrate/20150920010715_add_consumed_timestep_to_users.rb
+++ b/db/migrate/20150920010715_add_consumed_timestep_to_users.rb
@@ -1,4 +1,4 @@
-class AddConsumedTimestepToUsers < ActiveRecord::Migration
+class AddConsumedTimestepToUsers < ActiveRecord::Migration[4.2]
def change
add_column :users, :consumed_timestep, :integer
end
diff --git a/db/migrate/20150920161119_add_line_code_to_sent_notification.rb b/db/migrate/20150920161119_add_line_code_to_sent_notification.rb
index d9af4e71751..671476f0b07 100644
--- a/db/migrate/20150920161119_add_line_code_to_sent_notification.rb
+++ b/db/migrate/20150920161119_add_line_code_to_sent_notification.rb
@@ -1,4 +1,4 @@
-class AddLineCodeToSentNotification < ActiveRecord::Migration
+class AddLineCodeToSentNotification < ActiveRecord::Migration[4.2]
def change
add_column :sent_notifications, :line_code, :string
end
diff --git a/db/migrate/20150924125150_add_project_id_to_ci_commit.rb b/db/migrate/20150924125150_add_project_id_to_ci_commit.rb
index 1a761fe0f86..c9f16b0f3f9 100644
--- a/db/migrate/20150924125150_add_project_id_to_ci_commit.rb
+++ b/db/migrate/20150924125150_add_project_id_to_ci_commit.rb
@@ -1,4 +1,4 @@
-class AddProjectIdToCiCommit < ActiveRecord::Migration
+class AddProjectIdToCiCommit < ActiveRecord::Migration[4.2]
def up
add_column :ci_commits, :gl_project_id, :integer
end
diff --git a/db/migrate/20150924125436_migrate_project_id_for_ci_commits.rb b/db/migrate/20150924125436_migrate_project_id_for_ci_commits.rb
index 2be57b6062e..ff31e70874f 100644
--- a/db/migrate/20150924125436_migrate_project_id_for_ci_commits.rb
+++ b/db/migrate/20150924125436_migrate_project_id_for_ci_commits.rb
@@ -1,4 +1,4 @@
-class MigrateProjectIdForCiCommits < ActiveRecord::Migration
+class MigrateProjectIdForCiCommits < ActiveRecord::Migration[4.2]
def up
subquery = 'SELECT gitlab_id FROM ci_projects WHERE ci_projects.id = ci_commits.project_id'
execute("UPDATE ci_commits SET gl_project_id=(#{subquery}) WHERE gl_project_id IS NULL")
diff --git a/db/migrate/20150930001110_merge_request_error_field.rb b/db/migrate/20150930001110_merge_request_error_field.rb
index c2ee498ef3f..30f012b0a92 100644
--- a/db/migrate/20150930001110_merge_request_error_field.rb
+++ b/db/migrate/20150930001110_merge_request_error_field.rb
@@ -1,4 +1,4 @@
-class MergeRequestErrorField < ActiveRecord::Migration
+class MergeRequestErrorField < ActiveRecord::Migration[4.2]
def up
add_column :merge_requests, :merge_error, :string
end
diff --git a/db/migrate/20150930095736_add_null_to_name_for_ci_projects.rb b/db/migrate/20150930095736_add_null_to_name_for_ci_projects.rb
index 8d47dac6441..181f9f059ac 100644
--- a/db/migrate/20150930095736_add_null_to_name_for_ci_projects.rb
+++ b/db/migrate/20150930095736_add_null_to_name_for_ci_projects.rb
@@ -1,4 +1,4 @@
-class AddNullToNameForCiProjects < ActiveRecord::Migration
+class AddNullToNameForCiProjects < ActiveRecord::Migration[4.2]
def up
change_column_null :ci_projects, :name, true
end
diff --git a/db/migrate/20150930110012_add_group_share_lock.rb b/db/migrate/20150930110012_add_group_share_lock.rb
index 96938bf9ab6..62755765457 100644
--- a/db/migrate/20150930110012_add_group_share_lock.rb
+++ b/db/migrate/20150930110012_add_group_share_lock.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddGroupShareLock < ActiveRecord::Migration
+class AddGroupShareLock < ActiveRecord::Migration[4.2]
def change
add_column :namespaces, :share_with_group_lock, :boolean, default: false
end
diff --git a/db/migrate/20151002112914_add_stage_idx_to_builds.rb b/db/migrate/20151002112914_add_stage_idx_to_builds.rb
index 68a745ffef4..f73df9dc284 100644
--- a/db/migrate/20151002112914_add_stage_idx_to_builds.rb
+++ b/db/migrate/20151002112914_add_stage_idx_to_builds.rb
@@ -1,4 +1,4 @@
-class AddStageIdxToBuilds < ActiveRecord::Migration
+class AddStageIdxToBuilds < ActiveRecord::Migration[4.2]
def change
add_column :ci_builds, :stage_idx, :integer
end
diff --git a/db/migrate/20151002121400_add_index_for_builds.rb b/db/migrate/20151002121400_add_index_for_builds.rb
index bd945c54540..5e6f80a1d3d 100644
--- a/db/migrate/20151002121400_add_index_for_builds.rb
+++ b/db/migrate/20151002121400_add_index_for_builds.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddIndexForBuilds < ActiveRecord::Migration
+class AddIndexForBuilds < ActiveRecord::Migration[4.2]
def up
add_index :ci_builds, [:commit_id, :stage_idx, :created_at]
end
diff --git a/db/migrate/20151002122929_add_ref_and_tag_to_builds.rb b/db/migrate/20151002122929_add_ref_and_tag_to_builds.rb
index e3d2ac1cea5..ea41921b6ee 100644
--- a/db/migrate/20151002122929_add_ref_and_tag_to_builds.rb
+++ b/db/migrate/20151002122929_add_ref_and_tag_to_builds.rb
@@ -1,4 +1,4 @@
-class AddRefAndTagToBuilds < ActiveRecord::Migration
+class AddRefAndTagToBuilds < ActiveRecord::Migration[4.2]
def change
add_column :ci_builds, :tag, :boolean
add_column :ci_builds, :ref, :string
diff --git a/db/migrate/20151002122943_migrate_ref_and_tag_to_build.rb b/db/migrate/20151002122943_migrate_ref_and_tag_to_build.rb
index 52217ce5af2..b4038e6fa83 100644
--- a/db/migrate/20151002122943_migrate_ref_and_tag_to_build.rb
+++ b/db/migrate/20151002122943_migrate_ref_and_tag_to_build.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class MigrateRefAndTagToBuild < ActiveRecord::Migration
+class MigrateRefAndTagToBuild < ActiveRecord::Migration[4.2]
def change
execute('UPDATE ci_builds SET ref=(SELECT ref FROM ci_commits WHERE ci_commits.id = ci_builds.commit_id) WHERE ref IS NULL')
execute('UPDATE ci_builds SET tag=(SELECT tag FROM ci_commits WHERE ci_commits.id = ci_builds.commit_id) WHERE tag IS NULL')
diff --git a/db/migrate/20151005075649_add_user_id_to_build.rb b/db/migrate/20151005075649_add_user_id_to_build.rb
index 0f4b92b8b79..45372bf7cba 100644
--- a/db/migrate/20151005075649_add_user_id_to_build.rb
+++ b/db/migrate/20151005075649_add_user_id_to_build.rb
@@ -1,4 +1,4 @@
-class AddUserIdToBuild < ActiveRecord::Migration
+class AddUserIdToBuild < ActiveRecord::Migration[4.2]
def change
add_column :ci_builds, :user_id, :integer
end
diff --git a/db/migrate/20151005150751_add_layout_option_for_users.rb b/db/migrate/20151005150751_add_layout_option_for_users.rb
index 7e68606969f..66cba21320a 100644
--- a/db/migrate/20151005150751_add_layout_option_for_users.rb
+++ b/db/migrate/20151005150751_add_layout_option_for_users.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddLayoutOptionForUsers < ActiveRecord::Migration
+class AddLayoutOptionForUsers < ActiveRecord::Migration[4.2]
def change
add_column :users, :layout, :integer, default: 0
end
diff --git a/db/migrate/20151005162154_remove_ci_enabled_from_application_settings.rb b/db/migrate/20151005162154_remove_ci_enabled_from_application_settings.rb
index 07dba598749..a8e6e54062a 100644
--- a/db/migrate/20151005162154_remove_ci_enabled_from_application_settings.rb
+++ b/db/migrate/20151005162154_remove_ci_enabled_from_application_settings.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class RemoveCiEnabledFromApplicationSettings < ActiveRecord::Migration
+class RemoveCiEnabledFromApplicationSettings < ActiveRecord::Migration[4.2]
def change
remove_column :application_settings, :ci_enabled, :boolean, null: false, default: true
end
diff --git a/db/migrate/20151007120511_namespaces_projects_path_lower_indexes.rb b/db/migrate/20151007120511_namespaces_projects_path_lower_indexes.rb
index 38208e59804..d6c21bf8639 100644
--- a/db/migrate/20151007120511_namespaces_projects_path_lower_indexes.rb
+++ b/db/migrate/20151007120511_namespaces_projects_path_lower_indexes.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class NamespacesProjectsPathLowerIndexes < ActiveRecord::Migration
+class NamespacesProjectsPathLowerIndexes < ActiveRecord::Migration[4.2]
disable_ddl_transaction!
def up
diff --git a/db/migrate/20151008110232_add_users_lower_username_email_indexes.rb b/db/migrate/20151008110232_add_users_lower_username_email_indexes.rb
index 6080d2a0fcf..2ba1a6146e2 100644
--- a/db/migrate/20151008110232_add_users_lower_username_email_indexes.rb
+++ b/db/migrate/20151008110232_add_users_lower_username_email_indexes.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddUsersLowerUsernameEmailIndexes < ActiveRecord::Migration
+class AddUsersLowerUsernameEmailIndexes < ActiveRecord::Migration[4.2]
disable_ddl_transaction!
def up
diff --git a/db/migrate/20151008123042_add_type_and_description_to_builds.rb b/db/migrate/20151008123042_add_type_and_description_to_builds.rb
index a19eb6c6c49..309655cf195 100644
--- a/db/migrate/20151008123042_add_type_and_description_to_builds.rb
+++ b/db/migrate/20151008123042_add_type_and_description_to_builds.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddTypeAndDescriptionToBuilds < ActiveRecord::Migration
+class AddTypeAndDescriptionToBuilds < ActiveRecord::Migration[4.2]
def change
add_column :ci_builds, :type, :string
add_column :ci_builds, :target_url, :string
diff --git a/db/migrate/20151008130321_migrate_name_to_description_for_builds.rb b/db/migrate/20151008130321_migrate_name_to_description_for_builds.rb
index 306fa7092ea..f4445277a6f 100644
--- a/db/migrate/20151008130321_migrate_name_to_description_for_builds.rb
+++ b/db/migrate/20151008130321_migrate_name_to_description_for_builds.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class MigrateNameToDescriptionForBuilds < ActiveRecord::Migration
+class MigrateNameToDescriptionForBuilds < ActiveRecord::Migration[4.2]
def change
execute("UPDATE ci_builds SET type='Ci::Build' WHERE type IS NULL")
end
diff --git a/db/migrate/20151008143519_add_admin_notification_email_setting.rb b/db/migrate/20151008143519_add_admin_notification_email_setting.rb
index 0bb581efe2c..60e0986e5a8 100644
--- a/db/migrate/20151008143519_add_admin_notification_email_setting.rb
+++ b/db/migrate/20151008143519_add_admin_notification_email_setting.rb
@@ -1,4 +1,4 @@
-class AddAdminNotificationEmailSetting < ActiveRecord::Migration
+class AddAdminNotificationEmailSetting < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :admin_notification_email, :string
end
diff --git a/db/migrate/20151012173029_set_jira_service_api_url.rb b/db/migrate/20151012173029_set_jira_service_api_url.rb
index 2b6f61428c0..91cc6bbc783 100644
--- a/db/migrate/20151012173029_set_jira_service_api_url.rb
+++ b/db/migrate/20151012173029_set_jira_service_api_url.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class SetJiraServiceApiUrl < ActiveRecord::Migration
+class SetJiraServiceApiUrl < ActiveRecord::Migration[4.2]
# This migration can be performed online without errors, but some Jira API calls may be missed
# when doing so because api_url is not yet available.
diff --git a/db/migrate/20151013092124_add_artifacts_file_to_builds.rb b/db/migrate/20151013092124_add_artifacts_file_to_builds.rb
index 5a299f7b26d..3936386a2c0 100644
--- a/db/migrate/20151013092124_add_artifacts_file_to_builds.rb
+++ b/db/migrate/20151013092124_add_artifacts_file_to_builds.rb
@@ -1,4 +1,4 @@
-class AddArtifactsFileToBuilds < ActiveRecord::Migration
+class AddArtifactsFileToBuilds < ActiveRecord::Migration[4.2]
def change
add_column :ci_builds, :artifacts_file, :text
end
diff --git a/db/migrate/20151016131433_add_ci_projects_gl_project_id_index.rb b/db/migrate/20151016131433_add_ci_projects_gl_project_id_index.rb
index eb3351eb767..a9290fef11a 100644
--- a/db/migrate/20151016131433_add_ci_projects_gl_project_id_index.rb
+++ b/db/migrate/20151016131433_add_ci_projects_gl_project_id_index.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddCiProjectsGlProjectIdIndex < ActiveRecord::Migration
+class AddCiProjectsGlProjectIdIndex < ActiveRecord::Migration[4.2]
def change
add_index :ci_commits, :gl_project_id
end
diff --git a/db/migrate/20151016195451_add_ci_builds_and_projects_indexes.rb b/db/migrate/20151016195451_add_ci_builds_and_projects_indexes.rb
index 899e004d610..c8a79f25ae5 100644
--- a/db/migrate/20151016195451_add_ci_builds_and_projects_indexes.rb
+++ b/db/migrate/20151016195451_add_ci_builds_and_projects_indexes.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddCiBuildsAndProjectsIndexes < ActiveRecord::Migration
+class AddCiBuildsAndProjectsIndexes < ActiveRecord::Migration[4.2]
def change
add_index :ci_projects, :gitlab_id
add_index :ci_projects, :shared_runners_enabled
diff --git a/db/migrate/20151016195706_add_notes_line_code_index.rb b/db/migrate/20151016195706_add_notes_line_code_index.rb
index 3298630c1e8..0a3ad103009 100644
--- a/db/migrate/20151016195706_add_notes_line_code_index.rb
+++ b/db/migrate/20151016195706_add_notes_line_code_index.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddNotesLineCodeIndex < ActiveRecord::Migration
+class AddNotesLineCodeIndex < ActiveRecord::Migration[4.2]
def change
add_index :notes, :line_code
end
diff --git a/db/migrate/20151019111551_fix_build_tags.rb b/db/migrate/20151019111551_fix_build_tags.rb
index 299a24b0a7c..3c64388314d 100644
--- a/db/migrate/20151019111551_fix_build_tags.rb
+++ b/db/migrate/20151019111551_fix_build_tags.rb
@@ -1,4 +1,4 @@
-class FixBuildTags < ActiveRecord::Migration
+class FixBuildTags < ActiveRecord::Migration[4.2]
def up
execute("UPDATE taggings SET taggable_type='CommitStatus' WHERE taggable_type='Ci::Build'")
end
diff --git a/db/migrate/20151019111703_fail_build_without_names.rb b/db/migrate/20151019111703_fail_build_without_names.rb
index dcdb5d1b25d..2dc9ffa32b9 100644
--- a/db/migrate/20151019111703_fail_build_without_names.rb
+++ b/db/migrate/20151019111703_fail_build_without_names.rb
@@ -1,4 +1,4 @@
-class FailBuildWithoutNames < ActiveRecord::Migration
+class FailBuildWithoutNames < ActiveRecord::Migration[4.2]
def up
execute("UPDATE ci_builds SET status='failed' WHERE name IS NULL AND status='pending'")
end
diff --git a/db/migrate/20151020145526_add_services_template_index.rb b/db/migrate/20151020145526_add_services_template_index.rb
index 14ff07bd726..24c373855e2 100644
--- a/db/migrate/20151020145526_add_services_template_index.rb
+++ b/db/migrate/20151020145526_add_services_template_index.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddServicesTemplateIndex < ActiveRecord::Migration
+class AddServicesTemplateIndex < ActiveRecord::Migration[4.2]
def change
add_index :services, :template
end
diff --git a/db/migrate/20151020173516_ci_limits_to_mysql.rb b/db/migrate/20151020173516_ci_limits_to_mysql.rb
index 9bb960082f5..573922b851b 100644
--- a/db/migrate/20151020173516_ci_limits_to_mysql.rb
+++ b/db/migrate/20151020173516_ci_limits_to_mysql.rb
@@ -1,4 +1,4 @@
-class CiLimitsToMysql < ActiveRecord::Migration
+class CiLimitsToMysql < ActiveRecord::Migration[4.2]
def change
return unless ActiveRecord::Base.configurations[Rails.env]['adapter'] =~ /^mysql/
diff --git a/db/migrate/20151020173906_add_ci_builds_index_for_status.rb b/db/migrate/20151020173906_add_ci_builds_index_for_status.rb
index 81a31e46ff8..231fc4f2a17 100644
--- a/db/migrate/20151020173906_add_ci_builds_index_for_status.rb
+++ b/db/migrate/20151020173906_add_ci_builds_index_for_status.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddCiBuildsIndexForStatus < ActiveRecord::Migration
+class AddCiBuildsIndexForStatus < ActiveRecord::Migration[4.2]
def change
add_index :ci_builds, [:commit_id, :status, :type]
end
diff --git a/db/migrate/20151023112551_fail_build_with_empty_name.rb b/db/migrate/20151023112551_fail_build_with_empty_name.rb
index 41c0f0649cd..28f531463bc 100644
--- a/db/migrate/20151023112551_fail_build_with_empty_name.rb
+++ b/db/migrate/20151023112551_fail_build_with_empty_name.rb
@@ -1,4 +1,4 @@
-class FailBuildWithEmptyName < ActiveRecord::Migration
+class FailBuildWithEmptyName < ActiveRecord::Migration[4.2]
def up
execute("UPDATE ci_builds SET status='failed' WHERE (name IS NULL OR name='') AND status='pending'")
end
diff --git a/db/migrate/20151023144219_remove_satellites.rb b/db/migrate/20151023144219_remove_satellites.rb
index e73f300028a..2d1310b0208 100644
--- a/db/migrate/20151023144219_remove_satellites.rb
+++ b/db/migrate/20151023144219_remove_satellites.rb
@@ -1,6 +1,6 @@
require 'fileutils'
-class RemoveSatellites < ActiveRecord::Migration
+class RemoveSatellites < ActiveRecord::Migration[4.2]
def up
satellites = Gitlab.config['satellites']
return if satellites.nil?
diff --git a/db/migrate/20151026182941_add_project_path_index.rb b/db/migrate/20151026182941_add_project_path_index.rb
index 117f65c1a1b..bf0444450cd 100644
--- a/db/migrate/20151026182941_add_project_path_index.rb
+++ b/db/migrate/20151026182941_add_project_path_index.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddProjectPathIndex < ActiveRecord::Migration
+class AddProjectPathIndex < ActiveRecord::Migration[4.2]
def up
add_index :projects, :path
end
diff --git a/db/migrate/20151028152939_add_merge_when_build_succeeds_to_merge_request.rb b/db/migrate/20151028152939_add_merge_when_build_succeeds_to_merge_request.rb
index 4a989669464..5b11a430e30 100644
--- a/db/migrate/20151028152939_add_merge_when_build_succeeds_to_merge_request.rb
+++ b/db/migrate/20151028152939_add_merge_when_build_succeeds_to_merge_request.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddMergeWhenBuildSucceedsToMergeRequest < ActiveRecord::Migration
+class AddMergeWhenBuildSucceedsToMergeRequest < ActiveRecord::Migration[4.2]
def change
add_column :merge_requests, :merge_params, :text
add_column :merge_requests, :merge_when_build_succeeds, :boolean, default: false, null: false
diff --git a/db/migrate/20151103001141_add_public_to_group.rb b/db/migrate/20151103001141_add_public_to_group.rb
index ba1f7c27832..a5590bc1adc 100644
--- a/db/migrate/20151103001141_add_public_to_group.rb
+++ b/db/migrate/20151103001141_add_public_to_group.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddPublicToGroup < ActiveRecord::Migration
+class AddPublicToGroup < ActiveRecord::Migration[4.2]
def change
add_column :namespaces, :public, :boolean, default: false
end
diff --git a/db/migrate/20151103133339_add_shared_runners_setting.rb b/db/migrate/20151103133339_add_shared_runners_setting.rb
index 4231dfd5c2e..6fc845d1396 100644
--- a/db/migrate/20151103133339_add_shared_runners_setting.rb
+++ b/db/migrate/20151103133339_add_shared_runners_setting.rb
@@ -1,4 +1,4 @@
-class AddSharedRunnersSetting < ActiveRecord::Migration
+class AddSharedRunnersSetting < ActiveRecord::Migration[4.2]
def up
add_column :application_settings, :shared_runners_enabled, :boolean, default: true, null: false
end
diff --git a/db/migrate/20151103134857_create_lfs_objects.rb b/db/migrate/20151103134857_create_lfs_objects.rb
index db6fa27199b..2ba77e431a1 100644
--- a/db/migrate/20151103134857_create_lfs_objects.rb
+++ b/db/migrate/20151103134857_create_lfs_objects.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class CreateLfsObjects < ActiveRecord::Migration
+class CreateLfsObjects < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20151103134958_create_lfs_objects_projects.rb b/db/migrate/20151103134958_create_lfs_objects_projects.rb
index 5af1c39fd9c..6f8488463b0 100644
--- a/db/migrate/20151103134958_create_lfs_objects_projects.rb
+++ b/db/migrate/20151103134958_create_lfs_objects_projects.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class CreateLfsObjectsProjects < ActiveRecord::Migration
+class CreateLfsObjectsProjects < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20151104105513_add_file_to_lfs_objects.rb b/db/migrate/20151104105513_add_file_to_lfs_objects.rb
index 7c57f3f0df6..050b1e07503 100644
--- a/db/migrate/20151104105513_add_file_to_lfs_objects.rb
+++ b/db/migrate/20151104105513_add_file_to_lfs_objects.rb
@@ -1,4 +1,4 @@
-class AddFileToLfsObjects < ActiveRecord::Migration
+class AddFileToLfsObjects < ActiveRecord::Migration[4.2]
def change
add_column :lfs_objects, :file, :string
end
diff --git a/db/migrate/20151105094515_create_releases.rb b/db/migrate/20151105094515_create_releases.rb
index 34dd7a10942..4b180a59486 100644
--- a/db/migrate/20151105094515_create_releases.rb
+++ b/db/migrate/20151105094515_create_releases.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class CreateReleases < ActiveRecord::Migration
+class CreateReleases < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20151106000015_add_is_award_to_notes.rb b/db/migrate/20151106000015_add_is_award_to_notes.rb
index b463d939b78..1d866fb3213 100644
--- a/db/migrate/20151106000015_add_is_award_to_notes.rb
+++ b/db/migrate/20151106000015_add_is_award_to_notes.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddIsAwardToNotes < ActiveRecord::Migration
+class AddIsAwardToNotes < ActiveRecord::Migration[4.2]
def change
add_column :notes, :is_award, :boolean, default: false, null: false
add_index :notes, :is_award
diff --git a/db/migrate/20151109100728_add_max_artifacts_size_to_application_settings.rb b/db/migrate/20151109100728_add_max_artifacts_size_to_application_settings.rb
index 01d8c0f043e..9c14cfd4656 100644
--- a/db/migrate/20151109100728_add_max_artifacts_size_to_application_settings.rb
+++ b/db/migrate/20151109100728_add_max_artifacts_size_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddMaxArtifactsSizeToApplicationSettings < ActiveRecord::Migration
+class AddMaxArtifactsSizeToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :max_artifacts_size, :integer, default: 100, null: false
end
diff --git a/db/migrate/20151109134526_add_issues_state_index.rb b/db/migrate/20151109134526_add_issues_state_index.rb
index 7a9970e8591..c77ca90a0d6 100644
--- a/db/migrate/20151109134526_add_issues_state_index.rb
+++ b/db/migrate/20151109134526_add_issues_state_index.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddIssuesStateIndex < ActiveRecord::Migration
+class AddIssuesStateIndex < ActiveRecord::Migration[4.2]
def change
add_index :issues, :state
end
diff --git a/db/migrate/20151109134916_add_projects_visibility_level_index.rb b/db/migrate/20151109134916_add_projects_visibility_level_index.rb
index 471db437b11..1e945f0e56f 100644
--- a/db/migrate/20151109134916_add_projects_visibility_level_index.rb
+++ b/db/migrate/20151109134916_add_projects_visibility_level_index.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddProjectsVisibilityLevelIndex < ActiveRecord::Migration
+class AddProjectsVisibilityLevelIndex < ActiveRecord::Migration[4.2]
def change
add_index :projects, :visibility_level
end
diff --git a/db/migrate/20151110125604_add_import_error_to_project.rb b/db/migrate/20151110125604_add_import_error_to_project.rb
index 7fc990f8d0a..48a15ad0737 100644
--- a/db/migrate/20151110125604_add_import_error_to_project.rb
+++ b/db/migrate/20151110125604_add_import_error_to_project.rb
@@ -1,4 +1,4 @@
-class AddImportErrorToProject < ActiveRecord::Migration
+class AddImportErrorToProject < ActiveRecord::Migration[4.2]
def change
add_column :projects, :import_error, :text
end
diff --git a/db/migrate/20151114113410_add_index_for_lfs_oid_and_size.rb b/db/migrate/20151114113410_add_index_for_lfs_oid_and_size.rb
index 00a4c74ffbc..f2788117cc2 100644
--- a/db/migrate/20151114113410_add_index_for_lfs_oid_and_size.rb
+++ b/db/migrate/20151114113410_add_index_for_lfs_oid_and_size.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddIndexForLfsOidAndSize < ActiveRecord::Migration
+class AddIndexForLfsOidAndSize < ActiveRecord::Migration[4.2]
def change
add_index :lfs_objects, :oid
add_index :lfs_objects, [:oid, :size]
diff --git a/db/migrate/20151116144118_add_unique_for_lfs_oid_index.rb b/db/migrate/20151116144118_add_unique_for_lfs_oid_index.rb
index 1f192544ea1..3bfbae67119 100644
--- a/db/migrate/20151116144118_add_unique_for_lfs_oid_index.rb
+++ b/db/migrate/20151116144118_add_unique_for_lfs_oid_index.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddUniqueForLfsOidIndex < ActiveRecord::Migration
+class AddUniqueForLfsOidIndex < ActiveRecord::Migration[4.2]
def change
remove_index :lfs_objects, :oid
remove_index :lfs_objects, [:oid, :size]
diff --git a/db/migrate/20151118162244_add_projects_public_index.rb b/db/migrate/20151118162244_add_projects_public_index.rb
index 589f124c21e..3a525c69ad0 100644
--- a/db/migrate/20151118162244_add_projects_public_index.rb
+++ b/db/migrate/20151118162244_add_projects_public_index.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddProjectsPublicIndex < ActiveRecord::Migration
+class AddProjectsPublicIndex < ActiveRecord::Migration[4.2]
def change
add_index :namespaces, :public
end
diff --git a/db/migrate/20151201203948_raise_hook_url_limit.rb b/db/migrate/20151201203948_raise_hook_url_limit.rb
index 98a7fca6f6f..c1a4974b8c9 100644
--- a/db/migrate/20151201203948_raise_hook_url_limit.rb
+++ b/db/migrate/20151201203948_raise_hook_url_limit.rb
@@ -1,4 +1,4 @@
-class RaiseHookUrlLimit < ActiveRecord::Migration
+class RaiseHookUrlLimit < ActiveRecord::Migration[4.2]
def change
change_column :web_hooks, :url, :string, limit: 2000
end
diff --git a/db/migrate/20151203162133_add_hide_project_limit_to_users.rb b/db/migrate/20151203162133_add_hide_project_limit_to_users.rb
index 5dc6d8bf445..1b96a0dc550 100644
--- a/db/migrate/20151203162133_add_hide_project_limit_to_users.rb
+++ b/db/migrate/20151203162133_add_hide_project_limit_to_users.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddHideProjectLimitToUsers < ActiveRecord::Migration
+class AddHideProjectLimitToUsers < ActiveRecord::Migration[4.2]
def change
add_column :users, :hide_project_limit, :boolean, default: false
end
diff --git a/db/migrate/20151203162134_add_build_events_to_services.rb b/db/migrate/20151203162134_add_build_events_to_services.rb
index 455882e5ec0..c49604f8b61 100644
--- a/db/migrate/20151203162134_add_build_events_to_services.rb
+++ b/db/migrate/20151203162134_add_build_events_to_services.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddBuildEventsToServices < ActiveRecord::Migration
+class AddBuildEventsToServices < ActiveRecord::Migration[4.2]
def change
add_column :services, :build_events, :boolean, default: false, null: false
add_column :web_hooks, :build_events, :boolean, default: false, null: false
diff --git a/db/migrate/20151209144329_migrate_ci_web_hooks.rb b/db/migrate/20151209144329_migrate_ci_web_hooks.rb
index e1e4729f821..7562735cb1e 100644
--- a/db/migrate/20151209144329_migrate_ci_web_hooks.rb
+++ b/db/migrate/20151209144329_migrate_ci_web_hooks.rb
@@ -1,4 +1,4 @@
-class MigrateCiWebHooks < ActiveRecord::Migration
+class MigrateCiWebHooks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def up
diff --git a/db/migrate/20151209145909_migrate_ci_emails.rb b/db/migrate/20151209145909_migrate_ci_emails.rb
index e1d92f0157e..a1f51c55a55 100644
--- a/db/migrate/20151209145909_migrate_ci_emails.rb
+++ b/db/migrate/20151209145909_migrate_ci_emails.rb
@@ -1,4 +1,4 @@
-class MigrateCiEmails < ActiveRecord::Migration
+class MigrateCiEmails < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def up
diff --git a/db/migrate/20151210030143_add_unlock_token_to_user.rb b/db/migrate/20151210030143_add_unlock_token_to_user.rb
index 0ea66ba65df..28b736adfb5 100644
--- a/db/migrate/20151210030143_add_unlock_token_to_user.rb
+++ b/db/migrate/20151210030143_add_unlock_token_to_user.rb
@@ -1,4 +1,4 @@
-class AddUnlockTokenToUser < ActiveRecord::Migration
+class AddUnlockTokenToUser < ActiveRecord::Migration[4.2]
def change
add_column :users, :unlock_token, :string
end
diff --git a/db/migrate/20151210072243_add_runners_registration_token_to_application_settings.rb b/db/migrate/20151210072243_add_runners_registration_token_to_application_settings.rb
index 00f88180e46..5da33149b59 100644
--- a/db/migrate/20151210072243_add_runners_registration_token_to_application_settings.rb
+++ b/db/migrate/20151210072243_add_runners_registration_token_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddRunnersRegistrationTokenToApplicationSettings < ActiveRecord::Migration
+class AddRunnersRegistrationTokenToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :runners_registration_token, :string
end
diff --git a/db/migrate/20151210125232_migrate_ci_slack_service.rb b/db/migrate/20151210125232_migrate_ci_slack_service.rb
index e6dca4c0008..72c90f92377 100644
--- a/db/migrate/20151210125232_migrate_ci_slack_service.rb
+++ b/db/migrate/20151210125232_migrate_ci_slack_service.rb
@@ -1,4 +1,4 @@
-class MigrateCiSlackService < ActiveRecord::Migration
+class MigrateCiSlackService < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def up
diff --git a/db/migrate/20151210125927_migrate_ci_hip_chat_service.rb b/db/migrate/20151210125927_migrate_ci_hip_chat_service.rb
index 72fcebf2959..5ec0798c38f 100644
--- a/db/migrate/20151210125927_migrate_ci_hip_chat_service.rb
+++ b/db/migrate/20151210125927_migrate_ci_hip_chat_service.rb
@@ -1,4 +1,4 @@
-class MigrateCiHipChatService < ActiveRecord::Migration
+class MigrateCiHipChatService < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def up
diff --git a/db/migrate/20151210125928_add_ci_to_project.rb b/db/migrate/20151210125928_add_ci_to_project.rb
index a9ff49a3f7e..182f1e17b9a 100644
--- a/db/migrate/20151210125928_add_ci_to_project.rb
+++ b/db/migrate/20151210125928_add_ci_to_project.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddCiToProject < ActiveRecord::Migration
+class AddCiToProject < ActiveRecord::Migration[4.2]
def change
add_column :projects, :ci_id, :integer
add_column :projects, :builds_enabled, :boolean, default: true, null: false
diff --git a/db/migrate/20151210125929_add_project_id_to_ci.rb b/db/migrate/20151210125929_add_project_id_to_ci.rb
index 84273591fa2..f5f2c353f4a 100644
--- a/db/migrate/20151210125929_add_project_id_to_ci.rb
+++ b/db/migrate/20151210125929_add_project_id_to_ci.rb
@@ -1,4 +1,4 @@
-class AddProjectIdToCi < ActiveRecord::Migration
+class AddProjectIdToCi < ActiveRecord::Migration[4.2]
def change
add_column :ci_builds, :gl_project_id, :integer
add_column :ci_runner_projects, :gl_project_id, :integer
diff --git a/db/migrate/20151210125930_migrate_ci_to_project.rb b/db/migrate/20151210125930_migrate_ci_to_project.rb
index c32c7feb193..f7573ad1a8d 100644
--- a/db/migrate/20151210125930_migrate_ci_to_project.rb
+++ b/db/migrate/20151210125930_migrate_ci_to_project.rb
@@ -1,4 +1,4 @@
-class MigrateCiToProject < ActiveRecord::Migration
+class MigrateCiToProject < ActiveRecord::Migration[4.2]
def up
migrate_project_id_for_table('ci_runner_projects')
migrate_project_id_for_table('ci_triggers')
diff --git a/db/migrate/20151210125931_add_index_to_ci_tables.rb b/db/migrate/20151210125931_add_index_to_ci_tables.rb
index d87d335cf6b..2cbc5b50538 100644
--- a/db/migrate/20151210125931_add_index_to_ci_tables.rb
+++ b/db/migrate/20151210125931_add_index_to_ci_tables.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddIndexToCiTables < ActiveRecord::Migration
+class AddIndexToCiTables < ActiveRecord::Migration[4.2]
def change
add_index :ci_builds, :gl_project_id
add_index :ci_runner_projects, :gl_project_id
diff --git a/db/migrate/20151210125932_drop_null_for_ci_tables.rb b/db/migrate/20151210125932_drop_null_for_ci_tables.rb
index e1a0a964589..b48fef4b749 100644
--- a/db/migrate/20151210125932_drop_null_for_ci_tables.rb
+++ b/db/migrate/20151210125932_drop_null_for_ci_tables.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class DropNullForCiTables < ActiveRecord::Migration
+class DropNullForCiTables < ActiveRecord::Migration[4.2]
def change
remove_index :ci_variables, :project_id
remove_index :ci_runner_projects, :project_id
diff --git a/db/migrate/20151215132013_add_pages_size_to_application_settings.rb b/db/migrate/20151215132013_add_pages_size_to_application_settings.rb
index f3a663f805b..7190d476dc7 100644
--- a/db/migrate/20151215132013_add_pages_size_to_application_settings.rb
+++ b/db/migrate/20151215132013_add_pages_size_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddPagesSizeToApplicationSettings < ActiveRecord::Migration
+class AddPagesSizeToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20151218154042_add_tfa_to_application_settings.rb b/db/migrate/20151218154042_add_tfa_to_application_settings.rb
index dd95db775c5..a981fe2720f 100644
--- a/db/migrate/20151218154042_add_tfa_to_application_settings.rb
+++ b/db/migrate/20151218154042_add_tfa_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddTfaToApplicationSettings < ActiveRecord::Migration
+class AddTfaToApplicationSettings < ActiveRecord::Migration[4.2]
def change
change_table :application_settings do |t|
t.boolean :require_two_factor_authentication, default: false
diff --git a/db/migrate/20151221234414_add_tfa_additional_fields.rb b/db/migrate/20151221234414_add_tfa_additional_fields.rb
index c16df47932f..fed734f77f4 100644
--- a/db/migrate/20151221234414_add_tfa_additional_fields.rb
+++ b/db/migrate/20151221234414_add_tfa_additional_fields.rb
@@ -1,4 +1,4 @@
-class AddTfaAdditionalFields < ActiveRecord::Migration
+class AddTfaAdditionalFields < ActiveRecord::Migration[4.2]
def change
change_table :users do |t|
t.datetime :otp_grace_period_started_at, null: true
diff --git a/db/migrate/20151224123230_rename_emojis.rb b/db/migrate/20151224123230_rename_emojis.rb
index 62d921dfdcc..f1e4b1fe181 100644
--- a/db/migrate/20151224123230_rename_emojis.rb
+++ b/db/migrate/20151224123230_rename_emojis.rb
@@ -1,5 +1,5 @@
# Migration type: online without errors (works on previous version and new one)
-class RenameEmojis < ActiveRecord::Migration
+class RenameEmojis < ActiveRecord::Migration[4.2]
def up
# Renames aliases to main names
execute("UPDATE notes SET note ='thumbsup' WHERE is_award = true AND note = '+1'")
diff --git a/db/migrate/20151228111122_remove_public_from_namespace.rb b/db/migrate/20151228111122_remove_public_from_namespace.rb
index bcb322d9cba..ad922e3fc58 100644
--- a/db/migrate/20151228111122_remove_public_from_namespace.rb
+++ b/db/migrate/20151228111122_remove_public_from_namespace.rb
@@ -1,6 +1,6 @@
# rubocop:disable all
# Migration type: online
-class RemovePublicFromNamespace < ActiveRecord::Migration
+class RemovePublicFromNamespace < ActiveRecord::Migration[4.2]
def change
remove_column :namespaces, :public, :boolean
end
diff --git a/db/migrate/20151228150906_influxdb_settings.rb b/db/migrate/20151228150906_influxdb_settings.rb
index 2e080a02e6a..8266e3c5044 100644
--- a/db/migrate/20151228150906_influxdb_settings.rb
+++ b/db/migrate/20151228150906_influxdb_settings.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class InfluxdbSettings < ActiveRecord::Migration
+class InfluxdbSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :metrics_enabled, :boolean, default: false
diff --git a/db/migrate/20151228175719_add_recaptcha_to_application_settings.rb b/db/migrate/20151228175719_add_recaptcha_to_application_settings.rb
index 259fd0248d2..523f2cae092 100644
--- a/db/migrate/20151228175719_add_recaptcha_to_application_settings.rb
+++ b/db/migrate/20151228175719_add_recaptcha_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddRecaptchaToApplicationSettings < ActiveRecord::Migration
+class AddRecaptchaToApplicationSettings < ActiveRecord::Migration[4.2]
def change
change_table :application_settings do |t|
t.boolean :recaptcha_enabled, default: false
diff --git a/db/migrate/20151229102248_influxdb_udp_port_setting.rb b/db/migrate/20151229102248_influxdb_udp_port_setting.rb
index ae0499f936d..da37e3bc148 100644
--- a/db/migrate/20151229102248_influxdb_udp_port_setting.rb
+++ b/db/migrate/20151229102248_influxdb_udp_port_setting.rb
@@ -1,4 +1,4 @@
-class InfluxdbUdpPortSetting < ActiveRecord::Migration
+class InfluxdbUdpPortSetting < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :metrics_port, :integer, default: 8089
end
diff --git a/db/migrate/20151229112614_influxdb_remote_database_setting.rb b/db/migrate/20151229112614_influxdb_remote_database_setting.rb
index d2ac906ead3..5fdf4c6d4cb 100644
--- a/db/migrate/20151229112614_influxdb_remote_database_setting.rb
+++ b/db/migrate/20151229112614_influxdb_remote_database_setting.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class InfluxdbRemoteDatabaseSetting < ActiveRecord::Migration
+class InfluxdbRemoteDatabaseSetting < ActiveRecord::Migration[4.2]
def change
remove_column :application_settings, :metrics_database
end
diff --git a/db/migrate/20151230132518_add_artifacts_metadata_to_ci_build.rb b/db/migrate/20151230132518_add_artifacts_metadata_to_ci_build.rb
index 6c282fc5039..61a3d6486f3 100644
--- a/db/migrate/20151230132518_add_artifacts_metadata_to_ci_build.rb
+++ b/db/migrate/20151230132518_add_artifacts_metadata_to_ci_build.rb
@@ -1,4 +1,4 @@
-class AddArtifactsMetadataToCiBuild < ActiveRecord::Migration
+class AddArtifactsMetadataToCiBuild < ActiveRecord::Migration[4.2]
def change
add_column :ci_builds, :artifacts_metadata, :text
end
diff --git a/db/migrate/20151231152326_add_akismet_to_application_settings.rb b/db/migrate/20151231152326_add_akismet_to_application_settings.rb
index 3f52c758f9a..ef51ea03a5b 100644
--- a/db/migrate/20151231152326_add_akismet_to_application_settings.rb
+++ b/db/migrate/20151231152326_add_akismet_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddAkismetToApplicationSettings < ActiveRecord::Migration
+class AddAkismetToApplicationSettings < ActiveRecord::Migration[4.2]
def change
change_table :application_settings do |t|
t.boolean :akismet_enabled, default: false
diff --git a/db/migrate/20151231202530_remove_alert_type_from_broadcast_messages.rb b/db/migrate/20151231202530_remove_alert_type_from_broadcast_messages.rb
index 0bdd639eb21..2d8b44840f0 100644
--- a/db/migrate/20151231202530_remove_alert_type_from_broadcast_messages.rb
+++ b/db/migrate/20151231202530_remove_alert_type_from_broadcast_messages.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class RemoveAlertTypeFromBroadcastMessages < ActiveRecord::Migration
+class RemoveAlertTypeFromBroadcastMessages < ActiveRecord::Migration[4.2]
def change
remove_column :broadcast_messages, :alert_type, :integer
end
diff --git a/db/migrate/20160106162223_add_index_milestones_title.rb b/db/migrate/20160106162223_add_index_milestones_title.rb
index 9b9b6445a08..d42bddefe64 100644
--- a/db/migrate/20160106162223_add_index_milestones_title.rb
+++ b/db/migrate/20160106162223_add_index_milestones_title.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddIndexMilestonesTitle < ActiveRecord::Migration
+class AddIndexMilestonesTitle < ActiveRecord::Migration[4.2]
def change
add_index :milestones, :title
end
diff --git a/db/migrate/20160106164438_remove_influxdb_credentials.rb b/db/migrate/20160106164438_remove_influxdb_credentials.rb
index 987d75d6fda..569d5a0cf36 100644
--- a/db/migrate/20160106164438_remove_influxdb_credentials.rb
+++ b/db/migrate/20160106164438_remove_influxdb_credentials.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class RemoveInfluxdbCredentials < ActiveRecord::Migration
+class RemoveInfluxdbCredentials < ActiveRecord::Migration[4.2]
def change
remove_column :application_settings, :metrics_username, :string
remove_column :application_settings, :metrics_password, :string
diff --git a/db/migrate/20160109054846_create_spam_logs.rb b/db/migrate/20160109054846_create_spam_logs.rb
index f7103276639..dc97d03f7ff 100644
--- a/db/migrate/20160109054846_create_spam_logs.rb
+++ b/db/migrate/20160109054846_create_spam_logs.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class CreateSpamLogs < ActiveRecord::Migration
+class CreateSpamLogs < ActiveRecord::Migration[4.2]
def change
create_table :spam_logs do |t|
t.integer :user_id
diff --git a/db/migrate/20160113111034_add_metrics_sample_interval.rb b/db/migrate/20160113111034_add_metrics_sample_interval.rb
index b741f5d2c75..9c3377571aa 100644
--- a/db/migrate/20160113111034_add_metrics_sample_interval.rb
+++ b/db/migrate/20160113111034_add_metrics_sample_interval.rb
@@ -1,4 +1,4 @@
-class AddMetricsSampleInterval < ActiveRecord::Migration
+class AddMetricsSampleInterval < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :metrics_sample_interval, :integer,
default: 15
diff --git a/db/migrate/20160118155830_add_sentry_to_application_settings.rb b/db/migrate/20160118155830_add_sentry_to_application_settings.rb
index fa7ff9d9228..20f3925b964 100644
--- a/db/migrate/20160118155830_add_sentry_to_application_settings.rb
+++ b/db/migrate/20160118155830_add_sentry_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddSentryToApplicationSettings < ActiveRecord::Migration
+class AddSentryToApplicationSettings < ActiveRecord::Migration[4.2]
def change
change_table :application_settings do |t|
t.boolean :sentry_enabled, default: false
diff --git a/db/migrate/20160118232755_add_ip_blocking_settings_to_application_settings.rb b/db/migrate/20160118232755_add_ip_blocking_settings_to_application_settings.rb
index 19ea40b5547..809a6cceef5 100644
--- a/db/migrate/20160118232755_add_ip_blocking_settings_to_application_settings.rb
+++ b/db/migrate/20160118232755_add_ip_blocking_settings_to_application_settings.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddIpBlockingSettingsToApplicationSettings < ActiveRecord::Migration
+class AddIpBlockingSettingsToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :ip_blocking_enabled, :boolean, default: false
add_column :application_settings, :dnsbl_servers_list, :text
diff --git a/db/migrate/20160119111158_add_services_category.rb b/db/migrate/20160119111158_add_services_category.rb
index f77484b2f96..979a48584a9 100644
--- a/db/migrate/20160119111158_add_services_category.rb
+++ b/db/migrate/20160119111158_add_services_category.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddServicesCategory < ActiveRecord::Migration
+class AddServicesCategory < ActiveRecord::Migration[4.2]
def up
add_column :services, :category, :string, default: 'common', null: false
diff --git a/db/migrate/20160119112418_add_services_default.rb b/db/migrate/20160119112418_add_services_default.rb
index 7fa531899fe..41ba5d98afe 100644
--- a/db/migrate/20160119112418_add_services_default.rb
+++ b/db/migrate/20160119112418_add_services_default.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddServicesDefault < ActiveRecord::Migration
+class AddServicesDefault < ActiveRecord::Migration[4.2]
def up
add_column :services, :default, :boolean, default: false
diff --git a/db/migrate/20160119145451_add_ldap_email_to_users.rb b/db/migrate/20160119145451_add_ldap_email_to_users.rb
index 5b2b0bd31ca..bf8c27900b8 100644
--- a/db/migrate/20160119145451_add_ldap_email_to_users.rb
+++ b/db/migrate/20160119145451_add_ldap_email_to_users.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddLdapEmailToUsers < ActiveRecord::Migration
+class AddLdapEmailToUsers < ActiveRecord::Migration[4.2]
def up
add_column :users, :ldap_email, :boolean, default: false, null: false
diff --git a/db/migrate/20160120172143_add_base_commit_sha_to_merge_request_diffs.rb b/db/migrate/20160120172143_add_base_commit_sha_to_merge_request_diffs.rb
index d6c6aa4a4e8..9c0a91758f5 100644
--- a/db/migrate/20160120172143_add_base_commit_sha_to_merge_request_diffs.rb
+++ b/db/migrate/20160120172143_add_base_commit_sha_to_merge_request_diffs.rb
@@ -1,4 +1,4 @@
-class AddBaseCommitShaToMergeRequestDiffs < ActiveRecord::Migration
+class AddBaseCommitShaToMergeRequestDiffs < ActiveRecord::Migration[4.2]
def change
add_column :merge_request_diffs, :base_commit_sha, :string
end
diff --git a/db/migrate/20160121030729_add_email_author_in_body_to_application_settings.rb b/db/migrate/20160121030729_add_email_author_in_body_to_application_settings.rb
index 9a2570ae544..0cb1fbe8641 100644
--- a/db/migrate/20160121030729_add_email_author_in_body_to_application_settings.rb
+++ b/db/migrate/20160121030729_add_email_author_in_body_to_application_settings.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddEmailAuthorInBodyToApplicationSettings < ActiveRecord::Migration
+class AddEmailAuthorInBodyToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :email_author_in_body, :boolean, default: false
end
diff --git a/db/migrate/20160122185421_add_pending_delete_to_project.rb b/db/migrate/20160122185421_add_pending_delete_to_project.rb
index 61db852843f..8db0adc9221 100644
--- a/db/migrate/20160122185421_add_pending_delete_to_project.rb
+++ b/db/migrate/20160122185421_add_pending_delete_to_project.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddPendingDeleteToProject < ActiveRecord::Migration
+class AddPendingDeleteToProject < ActiveRecord::Migration[4.2]
def change
add_column :projects, :pending_delete, :boolean, default: false
end
diff --git a/db/migrate/20160128212447_remove_ip_blocking_settings_from_application_settings.rb b/db/migrate/20160128212447_remove_ip_blocking_settings_from_application_settings.rb
index 60ecda998dd..e76f0249ae5 100644
--- a/db/migrate/20160128212447_remove_ip_blocking_settings_from_application_settings.rb
+++ b/db/migrate/20160128212447_remove_ip_blocking_settings_from_application_settings.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class RemoveIpBlockingSettingsFromApplicationSettings < ActiveRecord::Migration
+class RemoveIpBlockingSettingsFromApplicationSettings < ActiveRecord::Migration[4.2]
def change
remove_column :application_settings, :ip_blocking_enabled, :boolean, default: false
remove_column :application_settings, :dnsbl_servers_list, :text
diff --git a/db/migrate/20160128233227_change_lfs_objects_size_column.rb b/db/migrate/20160128233227_change_lfs_objects_size_column.rb
index e7fd1f71777..65aaf2d9a0b 100644
--- a/db/migrate/20160128233227_change_lfs_objects_size_column.rb
+++ b/db/migrate/20160128233227_change_lfs_objects_size_column.rb
@@ -1,4 +1,4 @@
-class ChangeLfsObjectsSizeColumn < ActiveRecord::Migration
+class ChangeLfsObjectsSizeColumn < ActiveRecord::Migration[4.2]
def change
change_column :lfs_objects, :size, :integer, limit: 8
end
diff --git a/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb b/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb
index d3ea956952e..6254017615b 100644
--- a/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb
+++ b/db/migrate/20160129135155_remove_dot_atom_path_ending_of_projects.rb
@@ -1,4 +1,4 @@
-class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration
+class RemoveDotAtomPathEndingOfProjects < ActiveRecord::Migration[4.2]
include Gitlab::ShellAdapter
class ProjectPath
diff --git a/db/migrate/20160129155512_add_merge_commit_sha_to_merge_requests.rb b/db/migrate/20160129155512_add_merge_commit_sha_to_merge_requests.rb
index f0d94226514..8b84705ce7d 100644
--- a/db/migrate/20160129155512_add_merge_commit_sha_to_merge_requests.rb
+++ b/db/migrate/20160129155512_add_merge_commit_sha_to_merge_requests.rb
@@ -1,4 +1,4 @@
-class AddMergeCommitShaToMergeRequests < ActiveRecord::Migration
+class AddMergeCommitShaToMergeRequests < ActiveRecord::Migration[4.2]
def change
add_column :merge_requests, :merge_commit_sha, :string
end
diff --git a/db/migrate/20160202091601_add_erasable_to_ci_build.rb b/db/migrate/20160202091601_add_erasable_to_ci_build.rb
index 767ae160d08..214028bd8d3 100644
--- a/db/migrate/20160202091601_add_erasable_to_ci_build.rb
+++ b/db/migrate/20160202091601_add_erasable_to_ci_build.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddErasableToCiBuild < ActiveRecord::Migration
+class AddErasableToCiBuild < ActiveRecord::Migration[4.2]
def change
add_reference :ci_builds, :erased_by, references: :users, index: true
add_column :ci_builds, :erased_at, :datetime
diff --git a/db/migrate/20160202164642_add_allow_guest_to_access_builds_project.rb b/db/migrate/20160202164642_add_allow_guest_to_access_builds_project.rb
index 2c5cb307fad..542f9437911 100644
--- a/db/migrate/20160202164642_add_allow_guest_to_access_builds_project.rb
+++ b/db/migrate/20160202164642_add_allow_guest_to_access_builds_project.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddAllowGuestToAccessBuildsProject < ActiveRecord::Migration
+class AddAllowGuestToAccessBuildsProject < ActiveRecord::Migration[4.2]
def change
add_column :projects, :public_builds, :boolean, default: true, null: false
end
diff --git a/db/migrate/20160204144558_add_real_size_to_merge_request_diffs.rb b/db/migrate/20160204144558_add_real_size_to_merge_request_diffs.rb
index f996ae74dca..c1f1faf0279 100644
--- a/db/migrate/20160204144558_add_real_size_to_merge_request_diffs.rb
+++ b/db/migrate/20160204144558_add_real_size_to_merge_request_diffs.rb
@@ -1,4 +1,4 @@
-class AddRealSizeToMergeRequestDiffs < ActiveRecord::Migration
+class AddRealSizeToMergeRequestDiffs < ActiveRecord::Migration[4.2]
def change
add_column :merge_request_diffs, :real_size, :string
end
diff --git a/db/migrate/20160209130428_add_index_to_snippet.rb b/db/migrate/20160209130428_add_index_to_snippet.rb
index 4d17c3a2917..480ac193d63 100644
--- a/db/migrate/20160209130428_add_index_to_snippet.rb
+++ b/db/migrate/20160209130428_add_index_to_snippet.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddIndexToSnippet < ActiveRecord::Migration
+class AddIndexToSnippet < ActiveRecord::Migration[4.2]
def change
add_index :snippets, :updated_at
end
diff --git a/db/migrate/20160210105555_create_pages_domain.rb b/db/migrate/20160210105555_create_pages_domain.rb
index 0e8507c7e9a..a46906d64ca 100644
--- a/db/migrate/20160210105555_create_pages_domain.rb
+++ b/db/migrate/20160210105555_create_pages_domain.rb
@@ -1,4 +1,4 @@
-class CreatePagesDomain < ActiveRecord::Migration
+class CreatePagesDomain < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20160212123307_create_tasks.rb b/db/migrate/20160212123307_create_tasks.rb
index cd3ad0e4cd8..33acc8af91f 100644
--- a/db/migrate/20160212123307_create_tasks.rb
+++ b/db/migrate/20160212123307_create_tasks.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class CreateTasks < ActiveRecord::Migration
+class CreateTasks < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20160217100506_add_description_to_label.rb b/db/migrate/20160217100506_add_description_to_label.rb
index eed6d1f236a..116de8ddfa9 100644
--- a/db/migrate/20160217100506_add_description_to_label.rb
+++ b/db/migrate/20160217100506_add_description_to_label.rb
@@ -1,4 +1,4 @@
-class AddDescriptionToLabel < ActiveRecord::Migration
+class AddDescriptionToLabel < ActiveRecord::Migration[4.2]
def change
add_column :labels, :description, :string
end
diff --git a/db/migrate/20160217174422_add_note_to_tasks.rb b/db/migrate/20160217174422_add_note_to_tasks.rb
index da5cb2e05db..c2a42ce5dd8 100644
--- a/db/migrate/20160217174422_add_note_to_tasks.rb
+++ b/db/migrate/20160217174422_add_note_to_tasks.rb
@@ -1,4 +1,4 @@
-class AddNoteToTasks < ActiveRecord::Migration
+class AddNoteToTasks < ActiveRecord::Migration[4.2]
def change
add_reference :tasks, :note, index: true
end
diff --git a/db/migrate/20160220123949_rename_tasks_to_todos.rb b/db/migrate/20160220123949_rename_tasks_to_todos.rb
index 30c10d27146..0cc110a0a1a 100644
--- a/db/migrate/20160220123949_rename_tasks_to_todos.rb
+++ b/db/migrate/20160220123949_rename_tasks_to_todos.rb
@@ -1,4 +1,4 @@
-class RenameTasksToTodos < ActiveRecord::Migration
+class RenameTasksToTodos < ActiveRecord::Migration[4.2]
def change
rename_table :tasks, :todos
end
diff --git a/db/migrate/20160222153918_create_appearances_ce.rb b/db/migrate/20160222153918_create_appearances_ce.rb
index b2d5949b23f..37bbe62ad3d 100644
--- a/db/migrate/20160222153918_create_appearances_ce.rb
+++ b/db/migrate/20160222153918_create_appearances_ce.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class CreateAppearancesCe < ActiveRecord::Migration
+class CreateAppearancesCe < ActiveRecord::Migration[4.2]
def change
unless table_exists?(:appearances)
create_table :appearances do |t|
diff --git a/db/migrate/20160223192159_add_confidential_to_issues.rb b/db/migrate/20160223192159_add_confidential_to_issues.rb
index 5b99ce30e9f..ca029f12337 100644
--- a/db/migrate/20160223192159_add_confidential_to_issues.rb
+++ b/db/migrate/20160223192159_add_confidential_to_issues.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddConfidentialToIssues < ActiveRecord::Migration
+class AddConfidentialToIssues < ActiveRecord::Migration[4.2]
def change
add_column :issues, :confidential, :boolean, default: false
add_index :issues, :confidential
diff --git a/db/migrate/20160225090018_add_delete_at_to_issues.rb b/db/migrate/20160225090018_add_delete_at_to_issues.rb
index 139f911e1c9..3ae74f491f6 100644
--- a/db/migrate/20160225090018_add_delete_at_to_issues.rb
+++ b/db/migrate/20160225090018_add_delete_at_to_issues.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddDeleteAtToIssues < ActiveRecord::Migration
+class AddDeleteAtToIssues < ActiveRecord::Migration[4.2]
def change
add_column :issues, :deleted_at, :datetime
add_index :issues, :deleted_at
diff --git a/db/migrate/20160225101956_add_delete_at_to_merge_requests.rb b/db/migrate/20160225101956_add_delete_at_to_merge_requests.rb
index 4ca3f0dcdc5..ce8657ba88c 100644
--- a/db/migrate/20160225101956_add_delete_at_to_merge_requests.rb
+++ b/db/migrate/20160225101956_add_delete_at_to_merge_requests.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddDeleteAtToMergeRequests < ActiveRecord::Migration
+class AddDeleteAtToMergeRequests < ActiveRecord::Migration[4.2]
def change
add_column :merge_requests, :deleted_at, :datetime
add_index :merge_requests, :deleted_at
diff --git a/db/migrate/20160226114608_add_trigram_indexes_for_searching.rb b/db/migrate/20160226114608_add_trigram_indexes_for_searching.rb
index 7aa79bf5e02..82b54c552e0 100644
--- a/db/migrate/20160226114608_add_trigram_indexes_for_searching.rb
+++ b/db/migrate/20160226114608_add_trigram_indexes_for_searching.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddTrigramIndexesForSearching < ActiveRecord::Migration
+class AddTrigramIndexesForSearching < ActiveRecord::Migration[4.2]
disable_ddl_transaction!
def up
diff --git a/db/migrate/20160227120001_add_event_field_for_web_hook.rb b/db/migrate/20160227120001_add_event_field_for_web_hook.rb
index 89910893ee1..22bbd73114f 100644
--- a/db/migrate/20160227120001_add_event_field_for_web_hook.rb
+++ b/db/migrate/20160227120001_add_event_field_for_web_hook.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddEventFieldForWebHook < ActiveRecord::Migration
+class AddEventFieldForWebHook < ActiveRecord::Migration[4.2]
def change
add_column :web_hooks, :wiki_page_events, :boolean, default: false, null: false
end
diff --git a/db/migrate/20160227120047_add_event_to_services.rb b/db/migrate/20160227120047_add_event_to_services.rb
index fe7c54ca4eb..a3b94734ec2 100644
--- a/db/migrate/20160227120047_add_event_to_services.rb
+++ b/db/migrate/20160227120047_add_event_to_services.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddEventToServices < ActiveRecord::Migration
+class AddEventToServices < ActiveRecord::Migration[4.2]
def change
add_column :services, :wiki_page_events, :boolean, default: true
end
diff --git a/db/migrate/20160229193553_add_main_language_to_repository.rb b/db/migrate/20160229193553_add_main_language_to_repository.rb
index b5446c6a447..15f9a382802 100644
--- a/db/migrate/20160229193553_add_main_language_to_repository.rb
+++ b/db/migrate/20160229193553_add_main_language_to_repository.rb
@@ -1,4 +1,4 @@
-class AddMainLanguageToRepository < ActiveRecord::Migration
+class AddMainLanguageToRepository < ActiveRecord::Migration[4.2]
def change
add_column :projects, :main_language, :string
end
diff --git a/db/migrate/20160301124843_add_visibility_level_to_groups.rb b/db/migrate/20160301124843_add_visibility_level_to_groups.rb
index a874e6758dd..ed4bca4f1ba 100644
--- a/db/migrate/20160301124843_add_visibility_level_to_groups.rb
+++ b/db/migrate/20160301124843_add_visibility_level_to_groups.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddVisibilityLevelToGroups < ActiveRecord::Migration
+class AddVisibilityLevelToGroups < ActiveRecord::Migration[4.2]
def up
add_column :namespaces, :visibility_level, :integer, null: false, default: Gitlab::VisibilityLevel::PUBLIC
add_index :namespaces, :visibility_level
diff --git a/db/migrate/20160301174731_add_fingerprint_index.rb b/db/migrate/20160301174731_add_fingerprint_index.rb
index f2c3d1ba1ea..b13373a0468 100644
--- a/db/migrate/20160301174731_add_fingerprint_index.rb
+++ b/db/migrate/20160301174731_add_fingerprint_index.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddFingerprintIndex < ActiveRecord::Migration
+class AddFingerprintIndex < ActiveRecord::Migration[4.2]
disable_ddl_transaction!
DOWNTIME = false
diff --git a/db/migrate/20160302151724_add_import_credentials_to_project_import_data.rb b/db/migrate/20160302151724_add_import_credentials_to_project_import_data.rb
index ffcd64266e3..b0ea05bd6e1 100644
--- a/db/migrate/20160302151724_add_import_credentials_to_project_import_data.rb
+++ b/db/migrate/20160302151724_add_import_credentials_to_project_import_data.rb
@@ -1,4 +1,4 @@
-class AddImportCredentialsToProjectImportData < ActiveRecord::Migration
+class AddImportCredentialsToProjectImportData < ActiveRecord::Migration[4.2]
def change
add_column :project_import_data, :encrypted_credentials, :text
add_column :project_import_data, :encrypted_credentials_iv, :string
diff --git a/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb b/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb
index 95105118764..8a319554c28 100644
--- a/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb
+++ b/db/migrate/20160302152808_remove_wrong_import_url_from_projects.rb
@@ -2,7 +2,7 @@
# Loops through old importer projects that kept a token/password in the import URL
# and encrypts the credentials into a separate field in project#import_data
# #down method not supported
-class RemoveWrongImportUrlFromProjects < ActiveRecord::Migration
+class RemoveWrongImportUrlFromProjects < ActiveRecord::Migration[4.2]
class ProjectImportDataFake
extend AttrEncrypted
diff --git a/db/migrate/20160305220806_remove_expires_at_from_snippets.rb b/db/migrate/20160305220806_remove_expires_at_from_snippets.rb
index cac78703bc2..6835f534926 100644
--- a/db/migrate/20160305220806_remove_expires_at_from_snippets.rb
+++ b/db/migrate/20160305220806_remove_expires_at_from_snippets.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class RemoveExpiresAtFromSnippets < ActiveRecord::Migration
+class RemoveExpiresAtFromSnippets < ActiveRecord::Migration[4.2]
def change
remove_column :snippets, :expires_at, :datetime
end
diff --git a/db/migrate/20160307221555_disallow_blank_line_code_on_note.rb b/db/migrate/20160307221555_disallow_blank_line_code_on_note.rb
index 49e787d9a9a..26b65ef7037 100644
--- a/db/migrate/20160307221555_disallow_blank_line_code_on_note.rb
+++ b/db/migrate/20160307221555_disallow_blank_line_code_on_note.rb
@@ -1,4 +1,4 @@
-class DisallowBlankLineCodeOnNote < ActiveRecord::Migration
+class DisallowBlankLineCodeOnNote < ActiveRecord::Migration[4.2]
def up
execute("UPDATE notes SET line_code = NULL WHERE line_code = ''")
end
diff --git a/db/migrate/20160308212903_add_default_group_visibility_to_application_settings.rb b/db/migrate/20160308212903_add_default_group_visibility_to_application_settings.rb
index 92c0a1e088e..16053408fe0 100644
--- a/db/migrate/20160308212903_add_default_group_visibility_to_application_settings.rb
+++ b/db/migrate/20160308212903_add_default_group_visibility_to_application_settings.rb
@@ -3,7 +3,7 @@
# Sets default_visibility_level to value on settings if not restricted
# If value is restricted takes higher visibility level allowed
-class AddDefaultGroupVisibilityToApplicationSettings < ActiveRecord::Migration
+class AddDefaultGroupVisibilityToApplicationSettings < ActiveRecord::Migration[4.2]
def up
add_column :application_settings, :default_group_visibility, :integer
# Unfortunately, this can't be a `default`, since we don't want the configuration specific
diff --git a/db/migrate/20160309140734_fix_todos.rb b/db/migrate/20160309140734_fix_todos.rb
index 94fe1e4fdc3..917055f5036 100644
--- a/db/migrate/20160309140734_fix_todos.rb
+++ b/db/migrate/20160309140734_fix_todos.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class FixTodos < ActiveRecord::Migration
+class FixTodos < ActiveRecord::Migration[4.2]
def up
execute <<-SQL
DELETE FROM todos
diff --git a/db/migrate/20160310124959_add_due_date_to_issues.rb b/db/migrate/20160310124959_add_due_date_to_issues.rb
index a4eb6aaee63..8da38ea60b1 100644
--- a/db/migrate/20160310124959_add_due_date_to_issues.rb
+++ b/db/migrate/20160310124959_add_due_date_to_issues.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddDueDateToIssues < ActiveRecord::Migration
+class AddDueDateToIssues < ActiveRecord::Migration[4.2]
def change
add_column :issues, :due_date, :date
add_index :issues, :due_date
diff --git a/db/migrate/20160310185910_add_external_flag_to_users.rb b/db/migrate/20160310185910_add_external_flag_to_users.rb
index 209496dc786..768bbe4cd42 100644
--- a/db/migrate/20160310185910_add_external_flag_to_users.rb
+++ b/db/migrate/20160310185910_add_external_flag_to_users.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddExternalFlagToUsers < ActiveRecord::Migration
+class AddExternalFlagToUsers < ActiveRecord::Migration[4.2]
def change
add_column :users, :external, :boolean, default: false
end
diff --git a/db/migrate/20160314094147_add_priority_to_label.rb b/db/migrate/20160314094147_add_priority_to_label.rb
index 7fb23cba4c9..8e2aaf50109 100644
--- a/db/migrate/20160314094147_add_priority_to_label.rb
+++ b/db/migrate/20160314094147_add_priority_to_label.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddPriorityToLabel < ActiveRecord::Migration
+class AddPriorityToLabel < ActiveRecord::Migration[4.2]
def change
add_column :labels, :priority, :integer
add_index :labels, :priority
diff --git a/db/migrate/20160314114439_add_requested_at_to_members.rb b/db/migrate/20160314114439_add_requested_at_to_members.rb
index 76c8b8a1a24..e7e03f96ef8 100644
--- a/db/migrate/20160314114439_add_requested_at_to_members.rb
+++ b/db/migrate/20160314114439_add_requested_at_to_members.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Datetime
-class AddRequestedAtToMembers < ActiveRecord::Migration
+class AddRequestedAtToMembers < ActiveRecord::Migration[4.2]
def change
add_column :members, :requested_at, :datetime
end
diff --git a/db/migrate/20160314143402_projects_add_pushes_since_gc.rb b/db/migrate/20160314143402_projects_add_pushes_since_gc.rb
index 9f8ffe073a3..e64093d39cf 100644
--- a/db/migrate/20160314143402_projects_add_pushes_since_gc.rb
+++ b/db/migrate/20160314143402_projects_add_pushes_since_gc.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class ProjectsAddPushesSinceGc < ActiveRecord::Migration
+class ProjectsAddPushesSinceGc < ActiveRecord::Migration[4.2]
def change
add_column :projects, :pushes_since_gc, :integer, default: 0
end
diff --git a/db/migrate/20160315135439_project_add_repository_check.rb b/db/migrate/20160315135439_project_add_repository_check.rb
index 8fe649246c7..c03d8bb041c 100644
--- a/db/migrate/20160315135439_project_add_repository_check.rb
+++ b/db/migrate/20160315135439_project_add_repository_check.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class ProjectAddRepositoryCheck < ActiveRecord::Migration
+class ProjectAddRepositoryCheck < ActiveRecord::Migration[4.2]
def change
add_column :projects, :last_repository_check_failed, :boolean
add_index :projects, :last_repository_check_failed
diff --git a/db/migrate/20160316123110_ci_runners_token_index.rb b/db/migrate/20160316123110_ci_runners_token_index.rb
index ff3d36d68ee..026846e6464 100644
--- a/db/migrate/20160316123110_ci_runners_token_index.rb
+++ b/db/migrate/20160316123110_ci_runners_token_index.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class CiRunnersTokenIndex < ActiveRecord::Migration
+class CiRunnersTokenIndex < ActiveRecord::Migration[4.2]
disable_ddl_transaction!
def change
diff --git a/db/migrate/20160316192622_change_target_id_to_null_on_todos.rb b/db/migrate/20160316192622_change_target_id_to_null_on_todos.rb
index 6871b3920df..488c3d4945c 100644
--- a/db/migrate/20160316192622_change_target_id_to_null_on_todos.rb
+++ b/db/migrate/20160316192622_change_target_id_to_null_on_todos.rb
@@ -1,4 +1,4 @@
-class ChangeTargetIdToNullOnTodos < ActiveRecord::Migration
+class ChangeTargetIdToNullOnTodos < ActiveRecord::Migration[4.2]
def change
change_column_null :todos, :target_id, true
end
diff --git a/db/migrate/20160316204731_add_commit_id_to_todos.rb b/db/migrate/20160316204731_add_commit_id_to_todos.rb
index d79858fc920..d1c004b2ced 100644
--- a/db/migrate/20160316204731_add_commit_id_to_todos.rb
+++ b/db/migrate/20160316204731_add_commit_id_to_todos.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddCommitIdToTodos < ActiveRecord::Migration
+class AddCommitIdToTodos < ActiveRecord::Migration[4.2]
def change
add_column :todos, :commit_id, :string
add_index :todos, :commit_id
diff --git a/db/migrate/20160317092222_add_moved_to_to_issue.rb b/db/migrate/20160317092222_add_moved_to_to_issue.rb
index 2bf549d7ecd..8d81d84fd20 100644
--- a/db/migrate/20160317092222_add_moved_to_to_issue.rb
+++ b/db/migrate/20160317092222_add_moved_to_to_issue.rb
@@ -1,4 +1,4 @@
-class AddMovedToToIssue < ActiveRecord::Migration
+class AddMovedToToIssue < ActiveRecord::Migration[4.2]
def change
add_reference :issues, :moved_to, references: :issues # rubocop:disable Migration/AddReference
end
diff --git a/db/migrate/20160320204112_index_namespaces_on_visibility_level.rb b/db/migrate/20160320204112_index_namespaces_on_visibility_level.rb
index 07ae7c95477..9692def430c 100644
--- a/db/migrate/20160320204112_index_namespaces_on_visibility_level.rb
+++ b/db/migrate/20160320204112_index_namespaces_on_visibility_level.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class IndexNamespacesOnVisibilityLevel < ActiveRecord::Migration
+class IndexNamespacesOnVisibilityLevel < ActiveRecord::Migration[4.2]
def change
unless index_exists?(:namespaces, :visibility_level)
add_index :namespaces, :visibility_level
diff --git a/db/migrate/20160324020319_remove_todos_for_deleted_issues.rb b/db/migrate/20160324020319_remove_todos_for_deleted_issues.rb
index 1fff9759d1e..a25d15a81ef 100644
--- a/db/migrate/20160324020319_remove_todos_for_deleted_issues.rb
+++ b/db/migrate/20160324020319_remove_todos_for_deleted_issues.rb
@@ -1,4 +1,4 @@
-class RemoveTodosForDeletedIssues < ActiveRecord::Migration
+class RemoveTodosForDeletedIssues < ActiveRecord::Migration[4.2]
def up
execute <<-SQL
DELETE FROM todos
diff --git a/db/migrate/20160328112808_create_notification_settings.rb b/db/migrate/20160328112808_create_notification_settings.rb
index 7d77e8004ba..db19d2e370c 100644
--- a/db/migrate/20160328112808_create_notification_settings.rb
+++ b/db/migrate/20160328112808_create_notification_settings.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class CreateNotificationSettings < ActiveRecord::Migration
+class CreateNotificationSettings < ActiveRecord::Migration[4.2]
def change
create_table :notification_settings do |t|
t.references :user, null: false
diff --git a/db/migrate/20160328115649_migrate_new_notification_setting.rb b/db/migrate/20160328115649_migrate_new_notification_setting.rb
index 3c81b2c37bf..5ba09e75145 100644
--- a/db/migrate/20160328115649_migrate_new_notification_setting.rb
+++ b/db/migrate/20160328115649_migrate_new_notification_setting.rb
@@ -5,7 +5,7 @@
# - during migration some users will receive notifications based on their global settings (project/group settings will be ignored)
# - its possible to get duplicate records for notification settings since we don't create uniq index yet
#
-class MigrateNewNotificationSetting < ActiveRecord::Migration
+class MigrateNewNotificationSetting < ActiveRecord::Migration[4.2]
def up
timestamp = Time.now.strftime('%F %T')
execute "INSERT INTO notification_settings ( user_id, source_id, source_type, level, created_at, updated_at ) SELECT user_id, source_id, source_type, notification_level, '#{timestamp}', '#{timestamp}' FROM members WHERE user_id IS NOT NULL"
diff --git a/db/migrate/20160328121138_add_notification_setting_index.rb b/db/migrate/20160328121138_add_notification_setting_index.rb
index 667270d6b04..ed82b172296 100644
--- a/db/migrate/20160328121138_add_notification_setting_index.rb
+++ b/db/migrate/20160328121138_add_notification_setting_index.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddNotificationSettingIndex < ActiveRecord::Migration
+class AddNotificationSettingIndex < ActiveRecord::Migration[4.2]
def change
add_index :notification_settings, :user_id
add_index :notification_settings, [:source_id, :source_type]
diff --git a/db/migrate/20160329144452_add_index_on_pending_delete_projects.rb b/db/migrate/20160329144452_add_index_on_pending_delete_projects.rb
index a3df8fb4e2e..15c44f74451 100644
--- a/db/migrate/20160329144452_add_index_on_pending_delete_projects.rb
+++ b/db/migrate/20160329144452_add_index_on_pending_delete_projects.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddIndexOnPendingDeleteProjects < ActiveRecord::Migration
+class AddIndexOnPendingDeleteProjects < ActiveRecord::Migration[4.2]
def change
add_index :projects, :pending_delete
end
diff --git a/db/migrate/20160331133914_remove_todos_for_deleted_merge_requests.rb b/db/migrate/20160331133914_remove_todos_for_deleted_merge_requests.rb
index 54cea964ff2..634a696377c 100644
--- a/db/migrate/20160331133914_remove_todos_for_deleted_merge_requests.rb
+++ b/db/migrate/20160331133914_remove_todos_for_deleted_merge_requests.rb
@@ -1,4 +1,4 @@
-class RemoveTodosForDeletedMergeRequests < ActiveRecord::Migration
+class RemoveTodosForDeletedMergeRequests < ActiveRecord::Migration[4.2]
def up
execute <<-SQL
DELETE FROM todos
diff --git a/db/migrate/20160331223143_remove_twitter_sharing_enabled_from_application_settings.rb b/db/migrate/20160331223143_remove_twitter_sharing_enabled_from_application_settings.rb
index dec80497fb3..6e5a748d096 100644
--- a/db/migrate/20160331223143_remove_twitter_sharing_enabled_from_application_settings.rb
+++ b/db/migrate/20160331223143_remove_twitter_sharing_enabled_from_application_settings.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class RemoveTwitterSharingEnabledFromApplicationSettings < ActiveRecord::Migration
+class RemoveTwitterSharingEnabledFromApplicationSettings < ActiveRecord::Migration[4.2]
def change
remove_column :application_settings, :twitter_sharing_enabled, :boolean
end
diff --git a/db/migrate/20160407120251_add_images_enabled_for_project.rb b/db/migrate/20160407120251_add_images_enabled_for_project.rb
index 47f0ca8e8de..2c42d89ccdf 100644
--- a/db/migrate/20160407120251_add_images_enabled_for_project.rb
+++ b/db/migrate/20160407120251_add_images_enabled_for_project.rb
@@ -1,4 +1,4 @@
-class AddImagesEnabledForProject < ActiveRecord::Migration
+class AddImagesEnabledForProject < ActiveRecord::Migration[4.2]
def change
add_column :projects, :container_registry_enabled, :boolean
end
diff --git a/db/migrate/20160412140240_add_repository_checks_enabled_setting.rb b/db/migrate/20160412140240_add_repository_checks_enabled_setting.rb
index 920d4d41110..a59563b835e 100644
--- a/db/migrate/20160412140240_add_repository_checks_enabled_setting.rb
+++ b/db/migrate/20160412140240_add_repository_checks_enabled_setting.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddRepositoryChecksEnabledSetting < ActiveRecord::Migration
+class AddRepositoryChecksEnabledSetting < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :repository_checks_enabled, :boolean, default: true
end
diff --git a/db/migrate/20160412173416_add_fields_to_ci_commit.rb b/db/migrate/20160412173416_add_fields_to_ci_commit.rb
index 00162af5cda..4b3d4e8bd30 100644
--- a/db/migrate/20160412173416_add_fields_to_ci_commit.rb
+++ b/db/migrate/20160412173416_add_fields_to_ci_commit.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddFieldsToCiCommit < ActiveRecord::Migration
+class AddFieldsToCiCommit < ActiveRecord::Migration[4.2]
def change
add_column :ci_commits, :status, :string
add_column :ci_commits, :started_at, :timestamp
diff --git a/db/migrate/20160412173417_update_ci_commit.rb b/db/migrate/20160412173417_update_ci_commit.rb
index 858faeb060e..91dd4582f7a 100644
--- a/db/migrate/20160412173417_update_ci_commit.rb
+++ b/db/migrate/20160412173417_update_ci_commit.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class UpdateCiCommit < ActiveRecord::Migration
+class UpdateCiCommit < ActiveRecord::Migration[4.2]
# This migration can be run online, but needs to be executed for the second time after restarting Unicorn workers
# Otherwise Offline migration should be used.
def change
diff --git a/db/migrate/20160412173418_add_ci_commit_indexes.rb b/db/migrate/20160412173418_add_ci_commit_indexes.rb
index 414f1f8279f..709e6b84d57 100644
--- a/db/migrate/20160412173418_add_ci_commit_indexes.rb
+++ b/db/migrate/20160412173418_add_ci_commit_indexes.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddCiCommitIndexes < ActiveRecord::Migration
+class AddCiCommitIndexes < ActiveRecord::Migration[4.2]
disable_ddl_transaction!
def change
diff --git a/db/migrate/20160413115152_add_token_to_web_hooks.rb b/db/migrate/20160413115152_add_token_to_web_hooks.rb
index f04225068cd..43fe46dfe5d 100644
--- a/db/migrate/20160413115152_add_token_to_web_hooks.rb
+++ b/db/migrate/20160413115152_add_token_to_web_hooks.rb
@@ -1,4 +1,4 @@
-class AddTokenToWebHooks < ActiveRecord::Migration
+class AddTokenToWebHooks < ActiveRecord::Migration[4.2]
def change
add_column :web_hooks, :token, :string
end
diff --git a/db/migrate/20160415062917_create_personal_access_tokens.rb b/db/migrate/20160415062917_create_personal_access_tokens.rb
index 94650026994..43599db799e 100644
--- a/db/migrate/20160415062917_create_personal_access_tokens.rb
+++ b/db/migrate/20160415062917_create_personal_access_tokens.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Timestamps
-class CreatePersonalAccessTokens < ActiveRecord::Migration
+class CreatePersonalAccessTokens < ActiveRecord::Migration[4.2]
def change
create_table :personal_access_tokens do |t|
t.references :user, index: true, foreign_key: true, null: false
diff --git a/db/migrate/20160415133440_add_shared_runners_text_to_application_settings.rb b/db/migrate/20160415133440_add_shared_runners_text_to_application_settings.rb
index d493044c67b..e96c0591a07 100644
--- a/db/migrate/20160415133440_add_shared_runners_text_to_application_settings.rb
+++ b/db/migrate/20160415133440_add_shared_runners_text_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddSharedRunnersTextToApplicationSettings < ActiveRecord::Migration
+class AddSharedRunnersTextToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :shared_runners_text, :text
end
diff --git a/db/migrate/20160416180807_add_award_emoji.rb b/db/migrate/20160416180807_add_award_emoji.rb
index 0d252e5044e..99c984fd116 100644
--- a/db/migrate/20160416180807_add_award_emoji.rb
+++ b/db/migrate/20160416180807_add_award_emoji.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddAwardEmoji < ActiveRecord::Migration
+class AddAwardEmoji < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20160416182152_convert_award_note_to_emoji_award.rb b/db/migrate/20160416182152_convert_award_note_to_emoji_award.rb
index 50f159a80b1..af2820986f0 100644
--- a/db/migrate/20160416182152_convert_award_note_to_emoji_award.rb
+++ b/db/migrate/20160416182152_convert_award_note_to_emoji_award.rb
@@ -1,4 +1,4 @@
-class ConvertAwardNoteToEmojiAward < ActiveRecord::Migration
+class ConvertAwardNoteToEmojiAward < ActiveRecord::Migration[4.2]
disable_ddl_transaction!
def up
diff --git a/db/migrate/20160419120017_add_metrics_packet_size.rb b/db/migrate/20160419120017_add_metrics_packet_size.rb
index 78c163d62ac..16c3ebfe22b 100644
--- a/db/migrate/20160419120017_add_metrics_packet_size.rb
+++ b/db/migrate/20160419120017_add_metrics_packet_size.rb
@@ -1,4 +1,4 @@
-class AddMetricsPacketSize < ActiveRecord::Migration
+class AddMetricsPacketSize < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :metrics_packet_size, :integer, default: 1
end
diff --git a/db/migrate/20160419122101_add_only_allow_merge_if_build_succeeds_to_projects.rb b/db/migrate/20160419122101_add_only_allow_merge_if_build_succeeds_to_projects.rb
index 1716b6e8153..cf842a684a6 100644
--- a/db/migrate/20160419122101_add_only_allow_merge_if_build_succeeds_to_projects.rb
+++ b/db/migrate/20160419122101_add_only_allow_merge_if_build_succeeds_to_projects.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/UpdateLargeTable
-class AddOnlyAllowMergeIfBuildSucceedsToProjects < ActiveRecord::Migration
+class AddOnlyAllowMergeIfBuildSucceedsToProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160421130527_disable_repository_checks.rb b/db/migrate/20160421130527_disable_repository_checks.rb
index 7e65ddc45e7..8b3ce73c5e8 100644
--- a/db/migrate/20160421130527_disable_repository_checks.rb
+++ b/db/migrate/20160421130527_disable_repository_checks.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class DisableRepositoryChecks < ActiveRecord::Migration
+class DisableRepositoryChecks < ActiveRecord::Migration[4.2]
def up
change_column_default :application_settings, :repository_checks_enabled, false
execute 'UPDATE application_settings SET repository_checks_enabled = false'
diff --git a/db/migrate/20160425045124_create_u2f_registrations.rb b/db/migrate/20160425045124_create_u2f_registrations.rb
index 72cbe98ebba..9b48fc822b6 100644
--- a/db/migrate/20160425045124_create_u2f_registrations.rb
+++ b/db/migrate/20160425045124_create_u2f_registrations.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class CreateU2fRegistrations < ActiveRecord::Migration
+class CreateU2fRegistrations < ActiveRecord::Migration[4.2]
def change
create_table :u2f_registrations do |t|
t.text :certificate
diff --git a/db/migrate/20160504091942_add_disabled_oauth_sign_in_sources_to_application_settings.rb b/db/migrate/20160504091942_add_disabled_oauth_sign_in_sources_to_application_settings.rb
index facd33875ba..9a0d1a2d316 100644
--- a/db/migrate/20160504091942_add_disabled_oauth_sign_in_sources_to_application_settings.rb
+++ b/db/migrate/20160504091942_add_disabled_oauth_sign_in_sources_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddDisabledOauthSignInSourcesToApplicationSettings < ActiveRecord::Migration
+class AddDisabledOauthSignInSourcesToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :disabled_oauth_sign_in_sources, :text
end
diff --git a/db/migrate/20160504112519_add_run_untagged_to_ci_runner.rb b/db/migrate/20160504112519_add_run_untagged_to_ci_runner.rb
index 84e5e4eabe2..03ec29b9951 100644
--- a/db/migrate/20160504112519_add_run_untagged_to_ci_runner.rb
+++ b/db/migrate/20160504112519_add_run_untagged_to_ci_runner.rb
@@ -1,4 +1,4 @@
-class AddRunUntaggedToCiRunner < ActiveRecord::Migration
+class AddRunUntaggedToCiRunner < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160508194200_remove_wall_enabled_from_projects.rb b/db/migrate/20160508194200_remove_wall_enabled_from_projects.rb
index 6792ffc957a..4edbeb09f74 100644
--- a/db/migrate/20160508194200_remove_wall_enabled_from_projects.rb
+++ b/db/migrate/20160508194200_remove_wall_enabled_from_projects.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class RemoveWallEnabledFromProjects < ActiveRecord::Migration
+class RemoveWallEnabledFromProjects < ActiveRecord::Migration[4.2]
def change
remove_column :projects, :wall_enabled, :boolean, default: true, null: false
end
diff --git a/db/migrate/20160508202603_add_head_commit_id_to_merge_request_diffs.rb b/db/migrate/20160508202603_add_head_commit_id_to_merge_request_diffs.rb
index 1c4d60e7234..ee7c9326bfe 100644
--- a/db/migrate/20160508202603_add_head_commit_id_to_merge_request_diffs.rb
+++ b/db/migrate/20160508202603_add_head_commit_id_to_merge_request_diffs.rb
@@ -1,4 +1,4 @@
-class AddHeadCommitIdToMergeRequestDiffs < ActiveRecord::Migration
+class AddHeadCommitIdToMergeRequestDiffs < ActiveRecord::Migration[4.2]
def change
add_column :merge_request_diffs, :head_commit_sha, :string
end
diff --git a/db/migrate/20160508215820_add_type_to_notes.rb b/db/migrate/20160508215820_add_type_to_notes.rb
index 58944d4e651..343743a589c 100644
--- a/db/migrate/20160508215820_add_type_to_notes.rb
+++ b/db/migrate/20160508215820_add_type_to_notes.rb
@@ -1,4 +1,4 @@
-class AddTypeToNotes < ActiveRecord::Migration
+class AddTypeToNotes < ActiveRecord::Migration[4.2]
def change
add_column :notes, :type, :string
end
diff --git a/db/migrate/20160508215920_add_positions_to_diff_notes.rb b/db/migrate/20160508215920_add_positions_to_diff_notes.rb
index 2952c25004e..e0ee03d0fb5 100644
--- a/db/migrate/20160508215920_add_positions_to_diff_notes.rb
+++ b/db/migrate/20160508215920_add_positions_to_diff_notes.rb
@@ -1,4 +1,4 @@
-class AddPositionsToDiffNotes < ActiveRecord::Migration
+class AddPositionsToDiffNotes < ActiveRecord::Migration[4.2]
def change
add_column :notes, :position, :text
add_column :notes, :original_position, :text
diff --git a/db/migrate/20160508221410_set_type_on_legacy_diff_notes.rb b/db/migrate/20160508221410_set_type_on_legacy_diff_notes.rb
index 6dd958ff4a0..567754d4f4e 100644
--- a/db/migrate/20160508221410_set_type_on_legacy_diff_notes.rb
+++ b/db/migrate/20160508221410_set_type_on_legacy_diff_notes.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class SetTypeOnLegacyDiffNotes < ActiveRecord::Migration
+class SetTypeOnLegacyDiffNotes < ActiveRecord::Migration[4.2]
def change
execute "UPDATE notes SET type = 'LegacyDiffNote' WHERE line_code IS NOT NULL"
end
diff --git a/db/migrate/20160509091049_add_locked_to_ci_runner.rb b/db/migrate/20160509091049_add_locked_to_ci_runner.rb
index 3fbaef3b7f0..e19db5a4504 100644
--- a/db/migrate/20160509091049_add_locked_to_ci_runner.rb
+++ b/db/migrate/20160509091049_add_locked_to_ci_runner.rb
@@ -1,4 +1,4 @@
-class AddLockedToCiRunner < ActiveRecord::Migration
+class AddLockedToCiRunner < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160509201028_add_health_check_access_token_to_application_settings.rb b/db/migrate/20160509201028_add_health_check_access_token_to_application_settings.rb
index 9d729fec189..54d615f7e21 100644
--- a/db/migrate/20160509201028_add_health_check_access_token_to_application_settings.rb
+++ b/db/migrate/20160509201028_add_health_check_access_token_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddHealthCheckAccessTokenToApplicationSettings < ActiveRecord::Migration
+class AddHealthCheckAccessTokenToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :health_check_access_token, :string
end
diff --git a/db/migrate/20160516174813_add_send_user_confirmation_email_to_application_settings.rb b/db/migrate/20160516174813_add_send_user_confirmation_email_to_application_settings.rb
index 8c96353b850..9e203b97a43 100644
--- a/db/migrate/20160516174813_add_send_user_confirmation_email_to_application_settings.rb
+++ b/db/migrate/20160516174813_add_send_user_confirmation_email_to_application_settings.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddSendUserConfirmationEmailToApplicationSettings < ActiveRecord::Migration
+class AddSendUserConfirmationEmailToApplicationSettings < ActiveRecord::Migration[4.2]
def up
add_column :application_settings, :send_user_confirmation_email, :boolean, default: false
diff --git a/db/migrate/20160516224534_add_start_commit_id_to_merge_request_diffs.rb b/db/migrate/20160516224534_add_start_commit_id_to_merge_request_diffs.rb
index b7fd76ee84b..a84bfd64bda 100644
--- a/db/migrate/20160516224534_add_start_commit_id_to_merge_request_diffs.rb
+++ b/db/migrate/20160516224534_add_start_commit_id_to_merge_request_diffs.rb
@@ -1,4 +1,4 @@
-class AddStartCommitIdToMergeRequestDiffs < ActiveRecord::Migration
+class AddStartCommitIdToMergeRequestDiffs < ActiveRecord::Migration[4.2]
def change
add_column :merge_request_diffs, :start_commit_sha, :string
end
diff --git a/db/migrate/20160518200441_add_artifacts_expire_date_to_ci_builds.rb b/db/migrate/20160518200441_add_artifacts_expire_date_to_ci_builds.rb
index 8e9ab3f8acc..143b84a1662 100644
--- a/db/migrate/20160518200441_add_artifacts_expire_date_to_ci_builds.rb
+++ b/db/migrate/20160518200441_add_artifacts_expire_date_to_ci_builds.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Datetime
-class AddArtifactsExpireDateToCiBuilds < ActiveRecord::Migration
+class AddArtifactsExpireDateToCiBuilds < ActiveRecord::Migration[4.2]
def change
add_column :ci_builds, :artifacts_expire_at, :timestamp
end
diff --git a/db/migrate/20160519203051_add_developers_can_merge_to_protected_branches.rb b/db/migrate/20160519203051_add_developers_can_merge_to_protected_branches.rb
index ac50035eba4..ba0e1654379 100644
--- a/db/migrate/20160519203051_add_developers_can_merge_to_protected_branches.rb
+++ b/db/migrate/20160519203051_add_developers_can_merge_to_protected_branches.rb
@@ -1,4 +1,4 @@
-class AddDevelopersCanMergeToProtectedBranches < ActiveRecord::Migration
+class AddDevelopersCanMergeToProtectedBranches < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160522215720_add_note_type_and_position_to_sent_notification.rb b/db/migrate/20160522215720_add_note_type_and_position_to_sent_notification.rb
index 4eef16c9408..f569fc7c73f 100644
--- a/db/migrate/20160522215720_add_note_type_and_position_to_sent_notification.rb
+++ b/db/migrate/20160522215720_add_note_type_and_position_to_sent_notification.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddNoteTypeAndPositionToSentNotification < ActiveRecord::Migration
+class AddNoteTypeAndPositionToSentNotification < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# When using the methods "add_concurrent_index" or "add_column_with_default"
diff --git a/db/migrate/20160525205328_remove_main_language_from_projects.rb b/db/migrate/20160525205328_remove_main_language_from_projects.rb
index dc4ceacddb1..81d0fb5b080 100644
--- a/db/migrate/20160525205328_remove_main_language_from_projects.rb
+++ b/db/migrate/20160525205328_remove_main_language_from_projects.rb
@@ -2,7 +2,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveMainLanguageFromProjects < ActiveRecord::Migration
+class RemoveMainLanguageFromProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# When using the methods "add_concurrent_index" or "add_column_with_default"
diff --git a/db/migrate/20160527020117_remove_notification_settings_for_deleted_projects.rb b/db/migrate/20160527020117_remove_notification_settings_for_deleted_projects.rb
index 7910120b4e0..c530c09859d 100644
--- a/db/migrate/20160527020117_remove_notification_settings_for_deleted_projects.rb
+++ b/db/migrate/20160527020117_remove_notification_settings_for_deleted_projects.rb
@@ -1,4 +1,4 @@
-class RemoveNotificationSettingsForDeletedProjects < ActiveRecord::Migration
+class RemoveNotificationSettingsForDeletedProjects < ActiveRecord::Migration[4.2]
def up
execute <<-SQL
DELETE FROM notification_settings
diff --git a/db/migrate/20160528043124_add_users_state_index.rb b/db/migrate/20160528043124_add_users_state_index.rb
index 6419d2ae71d..3437b35a0c0 100644
--- a/db/migrate/20160528043124_add_users_state_index.rb
+++ b/db/migrate/20160528043124_add_users_state_index.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddUsersStateIndex < ActiveRecord::Migration
+class AddUsersStateIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160530150109_add_container_registry_token_expire_delay_to_application_settings.rb b/db/migrate/20160530150109_add_container_registry_token_expire_delay_to_application_settings.rb
index e21376bd571..7b20146e21c 100644
--- a/db/migrate/20160530150109_add_container_registry_token_expire_delay_to_application_settings.rb
+++ b/db/migrate/20160530150109_add_container_registry_token_expire_delay_to_application_settings.rb
@@ -1,6 +1,6 @@
# This is ONLINE migration
-class AddContainerRegistryTokenExpireDelayToApplicationSettings < ActiveRecord::Migration
+class AddContainerRegistryTokenExpireDelayToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def change
diff --git a/db/migrate/20160603075128_add_has_external_issue_tracker_to_projects.rb b/db/migrate/20160603075128_add_has_external_issue_tracker_to_projects.rb
index be295f0181d..a7d2d7f9952 100644
--- a/db/migrate/20160603075128_add_has_external_issue_tracker_to_projects.rb
+++ b/db/migrate/20160603075128_add_has_external_issue_tracker_to_projects.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddHasExternalIssueTrackerToProjects < ActiveRecord::Migration
+class AddHasExternalIssueTrackerToProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def change
diff --git a/db/migrate/20160603180330_remove_duplicated_notification_settings.rb b/db/migrate/20160603180330_remove_duplicated_notification_settings.rb
index fe1c863b5b9..0d8c4bf011c 100644
--- a/db/migrate/20160603180330_remove_duplicated_notification_settings.rb
+++ b/db/migrate/20160603180330_remove_duplicated_notification_settings.rb
@@ -1,4 +1,4 @@
-class RemoveDuplicatedNotificationSettings < ActiveRecord::Migration
+class RemoveDuplicatedNotificationSettings < ActiveRecord::Migration[4.2]
def up
duplicates = exec_query(%Q{
SELECT user_id, source_type, source_id
diff --git a/db/migrate/20160603182247_add_index_to_notification_settings.rb b/db/migrate/20160603182247_add_index_to_notification_settings.rb
index f6ae26d555f..cea178d555c 100644
--- a/db/migrate/20160603182247_add_index_to_notification_settings.rb
+++ b/db/migrate/20160603182247_add_index_to_notification_settings.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class AddIndexToNotificationSettings < ActiveRecord::Migration
+class AddIndexToNotificationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160608155312_add_after_sign_up_text_to_application_settings.rb b/db/migrate/20160608155312_add_after_sign_up_text_to_application_settings.rb
index 89826fb96cb..3b3f68529a5 100644
--- a/db/migrate/20160608155312_add_after_sign_up_text_to_application_settings.rb
+++ b/db/migrate/20160608155312_add_after_sign_up_text_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddAfterSignUpTextToApplicationSettings < ActiveRecord::Migration
+class AddAfterSignUpTextToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :after_sign_up_text, :text
end
diff --git a/db/migrate/20160608195742_add_repository_storage_to_projects.rb b/db/migrate/20160608195742_add_repository_storage_to_projects.rb
index e4febd1614d..2b20c9fbd5f 100644
--- a/db/migrate/20160608195742_add_repository_storage_to_projects.rb
+++ b/db/migrate/20160608195742_add_repository_storage_to_projects.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/UpdateLargeTable
-class AddRepositoryStorageToProjects < ActiveRecord::Migration
+class AddRepositoryStorageToProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160608211215_add_user_default_external_to_application_settings.rb b/db/migrate/20160608211215_add_user_default_external_to_application_settings.rb
index 34c702e3fa6..9b5cfc67d5a 100644
--- a/db/migrate/20160608211215_add_user_default_external_to_application_settings.rb
+++ b/db/migrate/20160608211215_add_user_default_external_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddUserDefaultExternalToApplicationSettings < ActiveRecord::Migration
+class AddUserDefaultExternalToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160610140403_remove_notification_setting_not_null_constraints.rb b/db/migrate/20160610140403_remove_notification_setting_not_null_constraints.rb
index 259abb08e47..d5301672dc5 100644
--- a/db/migrate/20160610140403_remove_notification_setting_not_null_constraints.rb
+++ b/db/migrate/20160610140403_remove_notification_setting_not_null_constraints.rb
@@ -1,4 +1,4 @@
-class RemoveNotificationSettingNotNullConstraints < ActiveRecord::Migration
+class RemoveNotificationSettingNotNullConstraints < ActiveRecord::Migration[4.2]
def up
change_column :notification_settings, :source_type, :string, null: true
change_column :notification_settings, :source_id, :integer, null: true
diff --git a/db/migrate/20160610194713_remove_deprecated_issues_tracker_columns_from_projects.rb b/db/migrate/20160610194713_remove_deprecated_issues_tracker_columns_from_projects.rb
index 21b367711c3..1ac65997403 100644
--- a/db/migrate/20160610194713_remove_deprecated_issues_tracker_columns_from_projects.rb
+++ b/db/migrate/20160610194713_remove_deprecated_issues_tracker_columns_from_projects.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/RemoveColumn
-class RemoveDeprecatedIssuesTrackerColumnsFromProjects < ActiveRecord::Migration
+class RemoveDeprecatedIssuesTrackerColumnsFromProjects < ActiveRecord::Migration[4.2]
def change
remove_column :projects, :issues_tracker, :string, default: 'gitlab', null: false
remove_column :projects, :issues_tracker_id, :string
diff --git a/db/migrate/20160610201627_migrate_users_notification_level.rb b/db/migrate/20160610201627_migrate_users_notification_level.rb
index cd8b505de9f..553b7f074f2 100644
--- a/db/migrate/20160610201627_migrate_users_notification_level.rb
+++ b/db/migrate/20160610201627_migrate_users_notification_level.rb
@@ -1,4 +1,4 @@
-class MigrateUsersNotificationLevel < ActiveRecord::Migration
+class MigrateUsersNotificationLevel < ActiveRecord::Migration[4.2]
DOWNTIME = false
# Migrates only users who changed their default notification level :participating
diff --git a/db/migrate/20160610204157_add_deployments.rb b/db/migrate/20160610204157_add_deployments.rb
index 0ee0b1f5a86..91b619e7d3d 100644
--- a/db/migrate/20160610204157_add_deployments.rb
+++ b/db/migrate/20160610204157_add_deployments.rb
@@ -1,6 +1,6 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddDeployments < ActiveRecord::Migration
+class AddDeployments < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def change
diff --git a/db/migrate/20160610204158_add_environments.rb b/db/migrate/20160610204158_add_environments.rb
index 534a73a5fb6..55fb8b1227b 100644
--- a/db/migrate/20160610204158_add_environments.rb
+++ b/db/migrate/20160610204158_add_environments.rb
@@ -1,6 +1,6 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddEnvironments < ActiveRecord::Migration
+class AddEnvironments < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def change
diff --git a/db/migrate/20160610211845_add_environment_to_builds.rb b/db/migrate/20160610211845_add_environment_to_builds.rb
index 990e445ac55..16d5465cafa 100644
--- a/db/migrate/20160610211845_add_environment_to_builds.rb
+++ b/db/migrate/20160610211845_add_environment_to_builds.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddEnvironmentToBuilds < ActiveRecord::Migration
+class AddEnvironmentToBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def change
diff --git a/db/migrate/20160610301627_remove_notification_level_from_users.rb b/db/migrate/20160610301627_remove_notification_level_from_users.rb
index 356e53b4b23..93f70c476d2 100644
--- a/db/migrate/20160610301627_remove_notification_level_from_users.rb
+++ b/db/migrate/20160610301627_remove_notification_level_from_users.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/RemoveColumn
-class RemoveNotificationLevelFromUsers < ActiveRecord::Migration
+class RemoveNotificationLevelFromUsers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def change
diff --git a/db/migrate/20160614182521_add_repository_storage_to_application_settings.rb b/db/migrate/20160614182521_add_repository_storage_to_application_settings.rb
index 6dae91b700b..a1bc0e5cd86 100644
--- a/db/migrate/20160614182521_add_repository_storage_to_application_settings.rb
+++ b/db/migrate/20160614182521_add_repository_storage_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddRepositoryStorageToApplicationSettings < ActiveRecord::Migration
+class AddRepositoryStorageToApplicationSettings < ActiveRecord::Migration[4.2]
def change
add_column :application_settings, :repository_storage, :string, default: 'default'
end
diff --git a/db/migrate/20160615142710_add_index_on_requested_at_to_members.rb b/db/migrate/20160615142710_add_index_on_requested_at_to_members.rb
index 178e4bf5ed3..1b1dab141f8 100644
--- a/db/migrate/20160615142710_add_index_on_requested_at_to_members.rb
+++ b/db/migrate/20160615142710_add_index_on_requested_at_to_members.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class AddIndexOnRequestedAtToMembers < ActiveRecord::Migration
+class AddIndexOnRequestedAtToMembers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160615173316_add_enabled_git_access_protocols_to_application_settings.rb b/db/migrate/20160615173316_add_enabled_git_access_protocols_to_application_settings.rb
index d0e6d8d1ea1..deb4b86a2fd 100644
--- a/db/migrate/20160615173316_add_enabled_git_access_protocols_to_application_settings.rb
+++ b/db/migrate/20160615173316_add_enabled_git_access_protocols_to_application_settings.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddEnabledGitAccessProtocolsToApplicationSettings < ActiveRecord::Migration
+class AddEnabledGitAccessProtocolsToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def change
diff --git a/db/migrate/20160615191922_set_missing_stage_on_ci_builds.rb b/db/migrate/20160615191922_set_missing_stage_on_ci_builds.rb
index c58cb957df4..11d15e7c15f 100644
--- a/db/migrate/20160615191922_set_missing_stage_on_ci_builds.rb
+++ b/db/migrate/20160615191922_set_missing_stage_on_ci_builds.rb
@@ -1,6 +1,6 @@
# rubocop:disable Migration/UpdateLargeTable
# rubocop:disable Migration/UpdateColumnInBatches
-class SetMissingStageOnCiBuilds < ActiveRecord::Migration
+class SetMissingStageOnCiBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160616084004_change_project_of_environment.rb b/db/migrate/20160616084004_change_project_of_environment.rb
index cc1daf9b621..23914a0325a 100644
--- a/db/migrate/20160616084004_change_project_of_environment.rb
+++ b/db/migrate/20160616084004_change_project_of_environment.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class ChangeProjectOfEnvironment < ActiveRecord::Migration
+class ChangeProjectOfEnvironment < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# When using the methods "add_concurrent_index" or "add_column_with_default"
diff --git a/db/migrate/20160616102642_remove_duplicated_keys.rb b/db/migrate/20160616102642_remove_duplicated_keys.rb
index 5e41cc53e32..0b896108292 100644
--- a/db/migrate/20160616102642_remove_duplicated_keys.rb
+++ b/db/migrate/20160616102642_remove_duplicated_keys.rb
@@ -1,4 +1,4 @@
-class RemoveDuplicatedKeys < ActiveRecord::Migration
+class RemoveDuplicatedKeys < ActiveRecord::Migration[4.2]
def up
select_all("SELECT fingerprint FROM #{quote_table_name(:keys)} GROUP BY fingerprint HAVING COUNT(*) > 1").each do |row|
fingerprint = connection.quote(row['fingerprint'])
diff --git a/db/migrate/20160616103005_remove_keys_fingerprint_index_if_exists.rb b/db/migrate/20160616103005_remove_keys_fingerprint_index_if_exists.rb
index 081df23f394..afccc40cc67 100644
--- a/db/migrate/20160616103005_remove_keys_fingerprint_index_if_exists.rb
+++ b/db/migrate/20160616103005_remove_keys_fingerprint_index_if_exists.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class RemoveKeysFingerprintIndexIfExists < ActiveRecord::Migration
+class RemoveKeysFingerprintIndexIfExists < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160616103948_add_unique_index_to_keys_fingerprint.rb b/db/migrate/20160616103948_add_unique_index_to_keys_fingerprint.rb
index 76bb6a09639..d619acad3d0 100644
--- a/db/migrate/20160616103948_add_unique_index_to_keys_fingerprint.rb
+++ b/db/migrate/20160616103948_add_unique_index_to_keys_fingerprint.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class AddUniqueIndexToKeysFingerprint < ActiveRecord::Migration
+class AddUniqueIndexToKeysFingerprint < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160617301627_add_events_to_notification_settings.rb b/db/migrate/20160617301627_add_events_to_notification_settings.rb
index 609596f45e4..109817e3d8a 100644
--- a/db/migrate/20160617301627_add_events_to_notification_settings.rb
+++ b/db/migrate/20160617301627_add_events_to_notification_settings.rb
@@ -1,4 +1,4 @@
-class AddEventsToNotificationSettings < ActiveRecord::Migration
+class AddEventsToNotificationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def change
diff --git a/db/migrate/20160620115026_add_index_on_runners_locked.rb b/db/migrate/20160620115026_add_index_on_runners_locked.rb
index 48f4495b0a4..c619dc07a91 100644
--- a/db/migrate/20160620115026_add_index_on_runners_locked.rb
+++ b/db/migrate/20160620115026_add_index_on_runners_locked.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class AddIndexOnRunnersLocked < ActiveRecord::Migration
+class AddIndexOnRunnersLocked < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160621123729_add_rebase_commit_sha_to_merge_requests.rb b/db/migrate/20160621123729_add_rebase_commit_sha_to_merge_requests.rb
index 1222dc640a8..2d3ab4e2583 100644
--- a/db/migrate/20160621123729_add_rebase_commit_sha_to_merge_requests.rb
+++ b/db/migrate/20160621123729_add_rebase_commit_sha_to_merge_requests.rb
@@ -5,7 +5,7 @@
# into EE.
#
# See discussion at https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3932
-class AddRebaseCommitShaToMergeRequests < ActiveRecord::Migration
+class AddRebaseCommitShaToMergeRequests < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20160628085157_add_artifacts_size_to_ci_builds.rb b/db/migrate/20160628085157_add_artifacts_size_to_ci_builds.rb
index 61dd726fac7..60bd4c36eb6 100644
--- a/db/migrate/20160628085157_add_artifacts_size_to_ci_builds.rb
+++ b/db/migrate/20160628085157_add_artifacts_size_to_ci_builds.rb
@@ -1,4 +1,4 @@
-class AddArtifactsSizeToCiBuilds < ActiveRecord::Migration
+class AddArtifactsSizeToCiBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def change
diff --git a/db/migrate/20160629025435_add_column_in_progress_merge_commit_sha_to_merge_requests.rb b/db/migrate/20160629025435_add_column_in_progress_merge_commit_sha_to_merge_requests.rb
index 7c5f76572ef..13e1280b71a 100644
--- a/db/migrate/20160629025435_add_column_in_progress_merge_commit_sha_to_merge_requests.rb
+++ b/db/migrate/20160629025435_add_column_in_progress_merge_commit_sha_to_merge_requests.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddColumnInProgressMergeCommitShaToMergeRequests < ActiveRecord::Migration
+class AddColumnInProgressMergeCommitShaToMergeRequests < ActiveRecord::Migration[4.2]
def change
add_column :merge_requests, :in_progress_merge_commit_sha, :string
end
diff --git a/db/migrate/20160703180340_add_index_on_award_emoji_user_and_name.rb b/db/migrate/20160703180340_add_index_on_award_emoji_user_and_name.rb
index 0c25f87dfb4..8a576b99de0 100644
--- a/db/migrate/20160703180340_add_index_on_award_emoji_user_and_name.rb
+++ b/db/migrate/20160703180340_add_index_on_award_emoji_user_and_name.rb
@@ -1,7 +1,7 @@
# rubocop:disable all
# Migration type: online without errors
-class AddIndexOnAwardEmojiUserAndName < ActiveRecord::Migration
+class AddIndexOnAwardEmojiUserAndName < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160705054938_add_protected_branches_push_access.rb b/db/migrate/20160705054938_add_protected_branches_push_access.rb
index de3aefcb1fb..314d90efa90 100644
--- a/db/migrate/20160705054938_add_protected_branches_push_access.rb
+++ b/db/migrate/20160705054938_add_protected_branches_push_access.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable Migration/Timestamps
-class AddProtectedBranchesPushAccess < ActiveRecord::Migration
+class AddProtectedBranchesPushAccess < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20160705054952_add_protected_branches_merge_access.rb b/db/migrate/20160705054952_add_protected_branches_merge_access.rb
index 9b18a2061b3..672e0e291db 100644
--- a/db/migrate/20160705054952_add_protected_branches_merge_access.rb
+++ b/db/migrate/20160705054952_add_protected_branches_merge_access.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable Migration/Timestamps
-class AddProtectedBranchesMergeAccess < ActiveRecord::Migration
+class AddProtectedBranchesMergeAccess < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20160705055254_move_from_developers_can_merge_to_protected_branches_merge_access.rb b/db/migrate/20160705055254_move_from_developers_can_merge_to_protected_branches_merge_access.rb
index 1db0df92bec..1bd462cab06 100644
--- a/db/migrate/20160705055254_move_from_developers_can_merge_to_protected_branches_merge_access.rb
+++ b/db/migrate/20160705055254_move_from_developers_can_merge_to_protected_branches_merge_access.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MoveFromDevelopersCanMergeToProtectedBranchesMergeAccess < ActiveRecord::Migration
+class MoveFromDevelopersCanMergeToProtectedBranchesMergeAccess < ActiveRecord::Migration[4.2]
DOWNTIME = true
DOWNTIME_REASON = <<-HEREDOC
We're creating a `merge_access_level` for each `protected_branch`. If a user creates a `protected_branch` while this
diff --git a/db/migrate/20160705055308_move_from_developers_can_push_to_protected_branches_push_access.rb b/db/migrate/20160705055308_move_from_developers_can_push_to_protected_branches_push_access.rb
index 5c3e189bb5b..d480dac777a 100644
--- a/db/migrate/20160705055308_move_from_developers_can_push_to_protected_branches_push_access.rb
+++ b/db/migrate/20160705055308_move_from_developers_can_push_to_protected_branches_push_access.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MoveFromDevelopersCanPushToProtectedBranchesPushAccess < ActiveRecord::Migration
+class MoveFromDevelopersCanPushToProtectedBranchesPushAccess < ActiveRecord::Migration[4.2]
DOWNTIME = true
DOWNTIME_REASON = <<-HEREDOC
We're creating a `push_access_level` for each `protected_branch`. If a user creates a `protected_branch` while this
diff --git a/db/migrate/20160705055809_remove_developers_can_push_from_protected_branches.rb b/db/migrate/20160705055809_remove_developers_can_push_from_protected_branches.rb
index 058bd539e65..e5c9da072cf 100644
--- a/db/migrate/20160705055809_remove_developers_can_push_from_protected_branches.rb
+++ b/db/migrate/20160705055809_remove_developers_can_push_from_protected_branches.rb
@@ -2,7 +2,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveDevelopersCanPushFromProtectedBranches < ActiveRecord::Migration
+class RemoveDevelopersCanPushFromProtectedBranches < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# This is only required for `#down`
diff --git a/db/migrate/20160705055813_remove_developers_can_merge_from_protected_branches.rb b/db/migrate/20160705055813_remove_developers_can_merge_from_protected_branches.rb
index d0e5da4d28b..2a623b55839 100644
--- a/db/migrate/20160705055813_remove_developers_can_merge_from_protected_branches.rb
+++ b/db/migrate/20160705055813_remove_developers_can_merge_from_protected_branches.rb
@@ -2,7 +2,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveDevelopersCanMergeFromProtectedBranches < ActiveRecord::Migration
+class RemoveDevelopersCanMergeFromProtectedBranches < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# This is only required for `#down`
diff --git a/db/migrate/20160705163108_remove_requesters_that_are_owners.rb b/db/migrate/20160705163108_remove_requesters_that_are_owners.rb
index 1fca230c019..449c67e1b6a 100644
--- a/db/migrate/20160705163108_remove_requesters_that_are_owners.rb
+++ b/db/migrate/20160705163108_remove_requesters_that_are_owners.rb
@@ -1,4 +1,4 @@
-class RemoveRequestersThatAreOwners < ActiveRecord::Migration
+class RemoveRequestersThatAreOwners < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def up
diff --git a/db/migrate/20160707104333_add_lock_to_issuables.rb b/db/migrate/20160707104333_add_lock_to_issuables.rb
index 54866d02cbc..fdc3abf46cc 100644
--- a/db/migrate/20160707104333_add_lock_to_issuables.rb
+++ b/db/migrate/20160707104333_add_lock_to_issuables.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddLockToIssuables < ActiveRecord::Migration
+class AddLockToIssuables < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160712171823_remove_award_emojis_with_no_user.rb b/db/migrate/20160712171823_remove_award_emojis_with_no_user.rb
index 8ebf1a5234d..0b553182a81 100644
--- a/db/migrate/20160712171823_remove_award_emojis_with_no_user.rb
+++ b/db/migrate/20160712171823_remove_award_emojis_with_no_user.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveAwardEmojisWithNoUser < ActiveRecord::Migration
+class RemoveAwardEmojisWithNoUser < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# When using the methods "add_concurrent_index" or "add_column_with_default"
diff --git a/db/migrate/20160713200638_add_repository_read_only_to_projects.rb b/db/migrate/20160713200638_add_repository_read_only_to_projects.rb
index 8ee8b55f210..ba61bc8cbb0 100644
--- a/db/migrate/20160713200638_add_repository_read_only_to_projects.rb
+++ b/db/migrate/20160713200638_add_repository_read_only_to_projects.rb
@@ -1,4 +1,4 @@
-class AddRepositoryReadOnlyToProjects < ActiveRecord::Migration
+class AddRepositoryReadOnlyToProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160713205315_add_domain_blacklist_to_application_settings.rb b/db/migrate/20160713205315_add_domain_blacklist_to_application_settings.rb
index f64dfa7675f..4b9ac12253e 100644
--- a/db/migrate/20160713205315_add_domain_blacklist_to_application_settings.rb
+++ b/db/migrate/20160713205315_add_domain_blacklist_to_application_settings.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable Migration/SaferBooleanColumn
-class AddDomainBlacklistToApplicationSettings < ActiveRecord::Migration
+class AddDomainBlacklistToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# When using the methods "add_concurrent_index" or "add_column_with_default"
diff --git a/db/migrate/20160713222618_add_usage_ping_to_application_settings.rb b/db/migrate/20160713222618_add_usage_ping_to_application_settings.rb
index a7f76cc626e..7ef02316338 100644
--- a/db/migrate/20160713222618_add_usage_ping_to_application_settings.rb
+++ b/db/migrate/20160713222618_add_usage_ping_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddUsagePingToApplicationSettings < ActiveRecord::Migration
+class AddUsagePingToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160715132507_add_user_id_to_pipeline.rb b/db/migrate/20160715132507_add_user_id_to_pipeline.rb
index af0461c4daf..b1e22b1c2bb 100644
--- a/db/migrate/20160715132507_add_user_id_to_pipeline.rb
+++ b/db/migrate/20160715132507_add_user_id_to_pipeline.rb
@@ -1,4 +1,4 @@
-class AddUserIdToPipeline < ActiveRecord::Migration
+class AddUserIdToPipeline < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def change
diff --git a/db/migrate/20160715134306_add_index_for_pipeline_user_id.rb b/db/migrate/20160715134306_add_index_for_pipeline_user_id.rb
index fec17ffb7f6..8e7ac86a8b7 100644
--- a/db/migrate/20160715134306_add_index_for_pipeline_user_id.rb
+++ b/db/migrate/20160715134306_add_index_for_pipeline_user_id.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class AddIndexForPipelineUserId < ActiveRecord::Migration
+class AddIndexForPipelineUserId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160715154212_add_request_access_enabled_to_projects.rb b/db/migrate/20160715154212_add_request_access_enabled_to_projects.rb
index 22c925799a3..96260f5fd55 100644
--- a/db/migrate/20160715154212_add_request_access_enabled_to_projects.rb
+++ b/db/migrate/20160715154212_add_request_access_enabled_to_projects.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/UpdateLargeTable
-class AddRequestAccessEnabledToProjects < ActiveRecord::Migration
+class AddRequestAccessEnabledToProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160715204316_add_request_access_enabled_to_groups.rb b/db/migrate/20160715204316_add_request_access_enabled_to_groups.rb
index 4fcb29e1325..14065434523 100644
--- a/db/migrate/20160715204316_add_request_access_enabled_to_groups.rb
+++ b/db/migrate/20160715204316_add_request_access_enabled_to_groups.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/UpdateLargeTable
-class AddRequestAccessEnabledToGroups < ActiveRecord::Migration
+class AddRequestAccessEnabledToGroups < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160715230841_rename_application_settings_restricted_signup_domains.rb b/db/migrate/20160715230841_rename_application_settings_restricted_signup_domains.rb
index dd15704800a..6a2674fb604 100644
--- a/db/migrate/20160715230841_rename_application_settings_restricted_signup_domains.rb
+++ b/db/migrate/20160715230841_rename_application_settings_restricted_signup_domains.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RenameApplicationSettingsRestrictedSignupDomains < ActiveRecord::Migration
+class RenameApplicationSettingsRestrictedSignupDomains < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# When using the methods "add_concurrent_index" or "add_column_with_default"
diff --git a/db/migrate/20160716115710_add_when_and_yaml_variables_to_ci_builds.rb b/db/migrate/20160716115710_add_when_and_yaml_variables_to_ci_builds.rb
index 3e084023a65..d403b0a3cc9 100644
--- a/db/migrate/20160716115710_add_when_and_yaml_variables_to_ci_builds.rb
+++ b/db/migrate/20160716115710_add_when_and_yaml_variables_to_ci_builds.rb
@@ -1,4 +1,4 @@
-class AddWhenAndYamlVariablesToCiBuilds < ActiveRecord::Migration
+class AddWhenAndYamlVariablesToCiBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def change
diff --git a/db/migrate/20160716115711_add_queued_at_to_ci_builds.rb b/db/migrate/20160716115711_add_queued_at_to_ci_builds.rb
index fd7a48d881e..2bb9a30e3a3 100644
--- a/db/migrate/20160716115711_add_queued_at_to_ci_builds.rb
+++ b/db/migrate/20160716115711_add_queued_at_to_ci_builds.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Datetime
-class AddQueuedAtToCiBuilds < ActiveRecord::Migration
+class AddQueuedAtToCiBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160718153603_add_has_external_wiki_to_projects.rb b/db/migrate/20160718153603_add_has_external_wiki_to_projects.rb
index 55a3e954292..e3e4afaf512 100644
--- a/db/migrate/20160718153603_add_has_external_wiki_to_projects.rb
+++ b/db/migrate/20160718153603_add_has_external_wiki_to_projects.rb
@@ -1,4 +1,4 @@
-class AddHasExternalWikiToProjects < ActiveRecord::Migration
+class AddHasExternalWikiToProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def change
diff --git a/db/migrate/20160721081015_drop_and_readd_has_external_wiki_in_projects.rb b/db/migrate/20160721081015_drop_and_readd_has_external_wiki_in_projects.rb
index 58f7f2a2841..d31bbb22392 100644
--- a/db/migrate/20160721081015_drop_and_readd_has_external_wiki_in_projects.rb
+++ b/db/migrate/20160721081015_drop_and_readd_has_external_wiki_in_projects.rb
@@ -1,6 +1,6 @@
# rubocop:disable Migration/UpdateLargeTable
# rubocop:disable Migration/UpdateColumnInBatches
-class DropAndReaddHasExternalWikiInProjects < ActiveRecord::Migration
+class DropAndReaddHasExternalWikiInProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20160722221922_nullify_blank_type_on_notes.rb b/db/migrate/20160722221922_nullify_blank_type_on_notes.rb
index c4b78e8e15c..83ca5c1e6ec 100644
--- a/db/migrate/20160722221922_nullify_blank_type_on_notes.rb
+++ b/db/migrate/20160722221922_nullify_blank_type_on_notes.rb
@@ -1,4 +1,4 @@
-class NullifyBlankTypeOnNotes < ActiveRecord::Migration
+class NullifyBlankTypeOnNotes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160724205507_add_resolved_to_notes.rb b/db/migrate/20160724205507_add_resolved_to_notes.rb
index 3aca272a3f7..fc56d3b1452 100644
--- a/db/migrate/20160724205507_add_resolved_to_notes.rb
+++ b/db/migrate/20160724205507_add_resolved_to_notes.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Datetime
-class AddResolvedToNotes < ActiveRecord::Migration
+class AddResolvedToNotes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160725083350_add_external_url_to_enviroments.rb b/db/migrate/20160725083350_add_external_url_to_enviroments.rb
index 21a8abd310b..e060c6a8499 100644
--- a/db/migrate/20160725083350_add_external_url_to_enviroments.rb
+++ b/db/migrate/20160725083350_add_external_url_to_enviroments.rb
@@ -1,4 +1,4 @@
-class AddExternalUrlToEnviroments < ActiveRecord::Migration
+class AddExternalUrlToEnviroments < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160725104020_merge_request_diff_remove_uniq.rb b/db/migrate/20160725104020_merge_request_diff_remove_uniq.rb
index 12e11bc3fbe..d8b4696a246 100644
--- a/db/migrate/20160725104020_merge_request_diff_remove_uniq.rb
+++ b/db/migrate/20160725104020_merge_request_diff_remove_uniq.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class MergeRequestDiffRemoveUniq < ActiveRecord::Migration
+class MergeRequestDiffRemoveUniq < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160725104452_merge_request_diff_add_index.rb b/db/migrate/20160725104452_merge_request_diff_add_index.rb
index 60d81e0bdc0..d3369b3f961 100644
--- a/db/migrate/20160725104452_merge_request_diff_add_index.rb
+++ b/db/migrate/20160725104452_merge_request_diff_add_index.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class MergeRequestDiffAddIndex < ActiveRecord::Migration
+class MergeRequestDiffAddIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160727163552_create_user_agent_details.rb b/db/migrate/20160727163552_create_user_agent_details.rb
index 3eb36f8464f..6ef54deca90 100644
--- a/db/migrate/20160727163552_create_user_agent_details.rb
+++ b/db/migrate/20160727163552_create_user_agent_details.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Timestamps
-class CreateUserAgentDetails < ActiveRecord::Migration
+class CreateUserAgentDetails < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20160727191041_create_boards.rb b/db/migrate/20160727191041_create_boards.rb
index 9ec8df1b8e8..60ed5508b10 100644
--- a/db/migrate/20160727191041_create_boards.rb
+++ b/db/migrate/20160727191041_create_boards.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Timestamps
-class CreateBoards < ActiveRecord::Migration
+class CreateBoards < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160727193336_create_lists.rb b/db/migrate/20160727193336_create_lists.rb
index 3fd95dc8cfc..4591c9a120f 100644
--- a/db/migrate/20160727193336_create_lists.rb
+++ b/db/migrate/20160727193336_create_lists.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Timestamps
-class CreateLists < ActiveRecord::Migration
+class CreateLists < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160728081025_add_pipeline_events_to_web_hooks.rb b/db/migrate/20160728081025_add_pipeline_events_to_web_hooks.rb
index b800e6d7283..fc3e9f03c74 100644
--- a/db/migrate/20160728081025_add_pipeline_events_to_web_hooks.rb
+++ b/db/migrate/20160728081025_add_pipeline_events_to_web_hooks.rb
@@ -1,4 +1,4 @@
-class AddPipelineEventsToWebHooks < ActiveRecord::Migration
+class AddPipelineEventsToWebHooks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160728103734_add_pipeline_events_to_services.rb b/db/migrate/20160728103734_add_pipeline_events_to_services.rb
index bcd24fe1566..421859ff5fd 100644
--- a/db/migrate/20160728103734_add_pipeline_events_to_services.rb
+++ b/db/migrate/20160728103734_add_pipeline_events_to_services.rb
@@ -1,4 +1,4 @@
-class AddPipelineEventsToServices < ActiveRecord::Migration
+class AddPipelineEventsToServices < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160729173930_remove_project_id_from_spam_logs.rb b/db/migrate/20160729173930_remove_project_id_from_spam_logs.rb
index baf254c3bcc..02e417e376f 100644
--- a/db/migrate/20160729173930_remove_project_id_from_spam_logs.rb
+++ b/db/migrate/20160729173930_remove_project_id_from_spam_logs.rb
@@ -2,7 +2,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveProjectIdFromSpamLogs < ActiveRecord::Migration
+class RemoveProjectIdFromSpamLogs < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20160801163421_add_expires_at_to_member.rb b/db/migrate/20160801163421_add_expires_at_to_member.rb
index 8db0fc60c4b..13ca1d04658 100644
--- a/db/migrate/20160801163421_add_expires_at_to_member.rb
+++ b/db/migrate/20160801163421_add_expires_at_to_member.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddExpiresAtToMember < ActiveRecord::Migration
+class AddExpiresAtToMember < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20160801163709_add_submitted_as_ham_to_spam_logs.rb b/db/migrate/20160801163709_add_submitted_as_ham_to_spam_logs.rb
index 20a77000ba8..fde9dee980e 100644
--- a/db/migrate/20160801163709_add_submitted_as_ham_to_spam_logs.rb
+++ b/db/migrate/20160801163709_add_submitted_as_ham_to_spam_logs.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddSubmittedAsHamToSpamLogs < ActiveRecord::Migration
+class AddSubmittedAsHamToSpamLogs < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20160802010328_remove_builds_enable_index_on_projects.rb b/db/migrate/20160802010328_remove_builds_enable_index_on_projects.rb
index 6d7733762c8..4ad740e0812 100644
--- a/db/migrate/20160802010328_remove_builds_enable_index_on_projects.rb
+++ b/db/migrate/20160802010328_remove_builds_enable_index_on_projects.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class RemoveBuildsEnableIndexOnProjects < ActiveRecord::Migration
+class RemoveBuildsEnableIndexOnProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160803161903_add_unique_index_to_lists_label_id.rb b/db/migrate/20160803161903_add_unique_index_to_lists_label_id.rb
index 9c1511963f7..f866fe15ec1 100644
--- a/db/migrate/20160803161903_add_unique_index_to_lists_label_id.rb
+++ b/db/migrate/20160803161903_add_unique_index_to_lists_label_id.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class AddUniqueIndexToListsLabelId < ActiveRecord::Migration
+class AddUniqueIndexToListsLabelId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160804142904_add_ci_config_file_to_project.rb b/db/migrate/20160804142904_add_ci_config_file_to_project.rb
index 341ae555c1b..abd94e63db3 100644
--- a/db/migrate/20160804142904_add_ci_config_file_to_project.rb
+++ b/db/migrate/20160804142904_add_ci_config_file_to_project.rb
@@ -1,4 +1,4 @@
-class AddCiConfigFileToProject < ActiveRecord::Migration
+class AddCiConfigFileToProject < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20160804150737_add_timestamps_to_members_again.rb b/db/migrate/20160804150737_add_timestamps_to_members_again.rb
index 6691ba57fbb..4e71197b8e7 100644
--- a/db/migrate/20160804150737_add_timestamps_to_members_again.rb
+++ b/db/migrate/20160804150737_add_timestamps_to_members_again.rb
@@ -6,7 +6,7 @@
#
# Why this happened is lost in the mists of time, so repeat the SQL query
# without speculation, just in case more than one person was affected.
-class AddTimestampsToMembersAgain < ActiveRecord::Migration
+class AddTimestampsToMembersAgain < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20160805041956_add_deleted_at_to_namespaces.rb b/db/migrate/20160805041956_add_deleted_at_to_namespaces.rb
index 404c253e18b..a0dfa3259ec 100644
--- a/db/migrate/20160805041956_add_deleted_at_to_namespaces.rb
+++ b/db/migrate/20160805041956_add_deleted_at_to_namespaces.rb
@@ -1,6 +1,6 @@
# rubocop:disable Migration/Datetime
# rubocop:disable RemoveIndex
-class AddDeletedAtToNamespaces < ActiveRecord::Migration
+class AddDeletedAtToNamespaces < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160808085531_add_token_to_build.rb b/db/migrate/20160808085531_add_token_to_build.rb
index 3ed2a103ae3..a1d8945a538 100644
--- a/db/migrate/20160808085531_add_token_to_build.rb
+++ b/db/migrate/20160808085531_add_token_to_build.rb
@@ -1,4 +1,4 @@
-class AddTokenToBuild < ActiveRecord::Migration
+class AddTokenToBuild < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20160808085602_add_index_for_build_token.rb b/db/migrate/20160808085602_add_index_for_build_token.rb
index 0446b2f2e15..22d50e4165a 100644
--- a/db/migrate/20160808085602_add_index_for_build_token.rb
+++ b/db/migrate/20160808085602_add_index_for_build_token.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class AddIndexForBuildToken < ActiveRecord::Migration
+class AddIndexForBuildToken < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20160810102349_remove_ci_runner_trigram_indexes.rb b/db/migrate/20160810102349_remove_ci_runner_trigram_indexes.rb
index 0cfb637804b..738b93912b6 100644
--- a/db/migrate/20160810102349_remove_ci_runner_trigram_indexes.rb
+++ b/db/migrate/20160810102349_remove_ci_runner_trigram_indexes.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveCiRunnerTrigramIndexes < ActiveRecord::Migration
+class RemoveCiRunnerTrigramIndexes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160810142633_remove_redundant_indexes.rb b/db/migrate/20160810142633_remove_redundant_indexes.rb
index ea7d1f9a436..91f82cf9afa 100644
--- a/db/migrate/20160810142633_remove_redundant_indexes.rb
+++ b/db/migrate/20160810142633_remove_redundant_indexes.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class RemoveRedundantIndexes < ActiveRecord::Migration
+class RemoveRedundantIndexes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160811172945_add_can_push_to_keys.rb b/db/migrate/20160811172945_add_can_push_to_keys.rb
index 5fd303fe8fb..2e78ab0249e 100644
--- a/db/migrate/20160811172945_add_can_push_to_keys.rb
+++ b/db/migrate/20160811172945_add_can_push_to_keys.rb
@@ -1,4 +1,4 @@
-class AddCanPushToKeys < ActiveRecord::Migration
+class AddCanPushToKeys < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160816161312_add_column_name_to_u2f_registrations.rb b/db/migrate/20160816161312_add_column_name_to_u2f_registrations.rb
index 7152bd04331..76b60787323 100644
--- a/db/migrate/20160816161312_add_column_name_to_u2f_registrations.rb
+++ b/db/migrate/20160816161312_add_column_name_to_u2f_registrations.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddColumnNameToU2fRegistrations < ActiveRecord::Migration
+class AddColumnNameToU2fRegistrations < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20160817133006_add_koding_to_application_settings.rb b/db/migrate/20160817133006_add_koding_to_application_settings.rb
index 46120652d8e..04f9d7be29b 100644
--- a/db/migrate/20160817133006_add_koding_to_application_settings.rb
+++ b/db/migrate/20160817133006_add_koding_to_application_settings.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/SaferBooleanColumn
-class AddKodingToApplicationSettings < ActiveRecord::Migration
+class AddKodingToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160817154936_add_discussion_ids_to_notes.rb b/db/migrate/20160817154936_add_discussion_ids_to_notes.rb
index 61facce665a..e735eeadac5 100644
--- a/db/migrate/20160817154936_add_discussion_ids_to_notes.rb
+++ b/db/migrate/20160817154936_add_discussion_ids_to_notes.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddDiscussionIdsToNotes < ActiveRecord::Migration
+class AddDiscussionIdsToNotes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160818205718_add_expires_at_to_project_group_links.rb b/db/migrate/20160818205718_add_expires_at_to_project_group_links.rb
index 0ed538b0df8..06f621c6c2e 100644
--- a/db/migrate/20160818205718_add_expires_at_to_project_group_links.rb
+++ b/db/migrate/20160818205718_add_expires_at_to_project_group_links.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddExpiresAtToProjectGroupLinks < ActiveRecord::Migration
+class AddExpiresAtToProjectGroupLinks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20160819221631_add_index_to_note_discussion_id.rb b/db/migrate/20160819221631_add_index_to_note_discussion_id.rb
index 843643c4e95..1dbc0474fd2 100644
--- a/db/migrate/20160819221631_add_index_to_note_discussion_id.rb
+++ b/db/migrate/20160819221631_add_index_to_note_discussion_id.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class AddIndexToNoteDiscussionId < ActiveRecord::Migration
+class AddIndexToNoteDiscussionId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160819221833_reset_diff_note_discussion_id_because_it_was_calculated_wrongly.rb b/db/migrate/20160819221833_reset_diff_note_discussion_id_because_it_was_calculated_wrongly.rb
index 0c68cf01900..61f593a52c5 100644
--- a/db/migrate/20160819221833_reset_diff_note_discussion_id_because_it_was_calculated_wrongly.rb
+++ b/db/migrate/20160819221833_reset_diff_note_discussion_id_because_it_was_calculated_wrongly.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class ResetDiffNoteDiscussionIdBecauseItWasCalculatedWrongly < ActiveRecord::Migration
+class ResetDiffNoteDiscussionIdBecauseItWasCalculatedWrongly < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160819232256_add_incoming_email_token_to_users.rb b/db/migrate/20160819232256_add_incoming_email_token_to_users.rb
index a004a3802a2..0a7190f632d 100644
--- a/db/migrate/20160819232256_add_incoming_email_token_to_users.rb
+++ b/db/migrate/20160819232256_add_incoming_email_token_to_users.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class AddIncomingEmailTokenToUsers < ActiveRecord::Migration
+class AddIncomingEmailTokenToUsers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20160823081327_change_merge_error_to_text.rb b/db/migrate/20160823081327_change_merge_error_to_text.rb
index 7920389cd83..23b4f35a776 100644
--- a/db/migrate/20160823081327_change_merge_error_to_text.rb
+++ b/db/migrate/20160823081327_change_merge_error_to_text.rb
@@ -1,4 +1,4 @@
-class ChangeMergeErrorToText < ActiveRecord::Migration
+class ChangeMergeErrorToText < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20160823083941_add_column_scopes_to_personal_access_tokens.rb b/db/migrate/20160823083941_add_column_scopes_to_personal_access_tokens.rb
index 91479de840b..4c320123088 100644
--- a/db/migrate/20160823083941_add_column_scopes_to_personal_access_tokens.rb
+++ b/db/migrate/20160823083941_add_column_scopes_to_personal_access_tokens.rb
@@ -2,7 +2,7 @@
# It's easier to achieve this by adding the column with the `['api']` default, and then changing the default to
# `[]`.
-class AddColumnScopesToPersonalAccessTokens < ActiveRecord::Migration
+class AddColumnScopesToPersonalAccessTokens < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160823213309_add_lfs_enabled_to_projects.rb b/db/migrate/20160823213309_add_lfs_enabled_to_projects.rb
index c169084e976..87e6e8b6945 100644
--- a/db/migrate/20160823213309_add_lfs_enabled_to_projects.rb
+++ b/db/migrate/20160823213309_add_lfs_enabled_to_projects.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddLfsEnabledToProjects < ActiveRecord::Migration
+class AddLfsEnabledToProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20160824103857_drop_unused_ci_tables.rb b/db/migrate/20160824103857_drop_unused_ci_tables.rb
index 65cf46308d9..8a207683848 100644
--- a/db/migrate/20160824103857_drop_unused_ci_tables.rb
+++ b/db/migrate/20160824103857_drop_unused_ci_tables.rb
@@ -1,4 +1,4 @@
-class DropUnusedCiTables < ActiveRecord::Migration
+class DropUnusedCiTables < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20160824124900_add_table_issue_metrics.rb b/db/migrate/20160824124900_add_table_issue_metrics.rb
index 49be8bc949b..4f34f377e22 100644
--- a/db/migrate/20160824124900_add_table_issue_metrics.rb
+++ b/db/migrate/20160824124900_add_table_issue_metrics.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
# rubocop:disable Migration/Timestamps
-class AddTableIssueMetrics < ActiveRecord::Migration
+class AddTableIssueMetrics < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20160825052008_add_table_merge_request_metrics.rb b/db/migrate/20160825052008_add_table_merge_request_metrics.rb
index 3c9dcc08190..150f698869d 100644
--- a/db/migrate/20160825052008_add_table_merge_request_metrics.rb
+++ b/db/migrate/20160825052008_add_table_merge_request_metrics.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
# rubocop:disable Migration/Timestamps
-class AddTableMergeRequestMetrics < ActiveRecord::Migration
+class AddTableMergeRequestMetrics < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20160827011312_ensure_lock_version_has_no_default.rb b/db/migrate/20160827011312_ensure_lock_version_has_no_default.rb
index 7c55bc23cf2..18c0f0be3eb 100644
--- a/db/migrate/20160827011312_ensure_lock_version_has_no_default.rb
+++ b/db/migrate/20160827011312_ensure_lock_version_has_no_default.rb
@@ -1,4 +1,4 @@
-class EnsureLockVersionHasNoDefault < ActiveRecord::Migration
+class EnsureLockVersionHasNoDefault < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160829114652_add_markdown_cache_columns.rb b/db/migrate/20160829114652_add_markdown_cache_columns.rb
index 6ad7237f4cd..b1c5e38c3c4 100644
--- a/db/migrate/20160829114652_add_markdown_cache_columns.rb
+++ b/db/migrate/20160829114652_add_markdown_cache_columns.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddMarkdownCacheColumns < ActiveRecord::Migration
+class AddMarkdownCacheColumns < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20160830203109_add_confidential_issues_events_to_web_hooks.rb b/db/migrate/20160830203109_add_confidential_issues_events_to_web_hooks.rb
index a27947212f6..771a6b84648 100644
--- a/db/migrate/20160830203109_add_confidential_issues_events_to_web_hooks.rb
+++ b/db/migrate/20160830203109_add_confidential_issues_events_to_web_hooks.rb
@@ -1,4 +1,4 @@
-class AddConfidentialIssuesEventsToWebHooks < ActiveRecord::Migration
+class AddConfidentialIssuesEventsToWebHooks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160830211132_add_confidential_issues_events_to_services.rb b/db/migrate/20160830211132_add_confidential_issues_events_to_services.rb
index 030e7c39350..a1807264341 100644
--- a/db/migrate/20160830211132_add_confidential_issues_events_to_services.rb
+++ b/db/migrate/20160830211132_add_confidential_issues_events_to_services.rb
@@ -1,4 +1,4 @@
-class AddConfidentialIssuesEventsToServices < ActiveRecord::Migration
+class AddConfidentialIssuesEventsToServices < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160830232601_change_lock_version_not_null.rb b/db/migrate/20160830232601_change_lock_version_not_null.rb
index 01c58ed5bdc..1e34b57e53f 100644
--- a/db/migrate/20160830232601_change_lock_version_not_null.rb
+++ b/db/migrate/20160830232601_change_lock_version_not_null.rb
@@ -1,4 +1,4 @@
-class ChangeLockVersionNotNull < ActiveRecord::Migration
+class ChangeLockVersionNotNull < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160831214002_create_project_features.rb b/db/migrate/20160831214002_create_project_features.rb
index 7ac6c8ec654..e1e61c3a4a2 100644
--- a/db/migrate/20160831214002_create_project_features.rb
+++ b/db/migrate/20160831214002_create_project_features.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Timestamps
-class CreateProjectFeatures < ActiveRecord::Migration
+class CreateProjectFeatures < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20160831214543_migrate_project_features.rb b/db/migrate/20160831214543_migrate_project_features.rb
index 79a5fb29d64..ba7ffd7c9f2 100644
--- a/db/migrate/20160831214543_migrate_project_features.rb
+++ b/db/migrate/20160831214543_migrate_project_features.rb
@@ -1,4 +1,4 @@
-class MigrateProjectFeatures < ActiveRecord::Migration
+class MigrateProjectFeatures < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20160831223750_remove_features_enabled_from_projects.rb b/db/migrate/20160831223750_remove_features_enabled_from_projects.rb
index 9eafd8b9477..6d39d42882b 100644
--- a/db/migrate/20160831223750_remove_features_enabled_from_projects.rb
+++ b/db/migrate/20160831223750_remove_features_enabled_from_projects.rb
@@ -3,7 +3,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable Migration/UpdateLargeTable
-class RemoveFeaturesEnabledFromProjects < ActiveRecord::Migration
+class RemoveFeaturesEnabledFromProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20160901141443_set_confidential_issues_events_on_webhooks.rb b/db/migrate/20160901141443_set_confidential_issues_events_on_webhooks.rb
index f8486e3e1a6..2921bb566c9 100644
--- a/db/migrate/20160901141443_set_confidential_issues_events_on_webhooks.rb
+++ b/db/migrate/20160901141443_set_confidential_issues_events_on_webhooks.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/UpdateColumnInBatches
-class SetConfidentialIssuesEventsOnWebhooks < ActiveRecord::Migration
+class SetConfidentialIssuesEventsOnWebhooks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160901213340_add_lfs_enabled_to_namespaces.rb b/db/migrate/20160901213340_add_lfs_enabled_to_namespaces.rb
index fd413d1ca8c..1be5f3f6ab0 100644
--- a/db/migrate/20160901213340_add_lfs_enabled_to_namespaces.rb
+++ b/db/migrate/20160901213340_add_lfs_enabled_to_namespaces.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddLfsEnabledToNamespaces < ActiveRecord::Migration
+class AddLfsEnabledToNamespaces < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160902122721_drop_gitorious_field_from_application_settings.rb b/db/migrate/20160902122721_drop_gitorious_field_from_application_settings.rb
index a80a57254dd..6c2dc58876e 100644
--- a/db/migrate/20160902122721_drop_gitorious_field_from_application_settings.rb
+++ b/db/migrate/20160902122721_drop_gitorious_field_from_application_settings.rb
@@ -1,4 +1,4 @@
-class DropGitoriousFieldFromApplicationSettings < ActiveRecord::Migration
+class DropGitoriousFieldFromApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# After the deploy the caches will be cold anyway
diff --git a/db/migrate/20160907131111_add_environment_type_to_environments.rb b/db/migrate/20160907131111_add_environment_type_to_environments.rb
index fac73753d5b..34463178fca 100644
--- a/db/migrate/20160907131111_add_environment_type_to_environments.rb
+++ b/db/migrate/20160907131111_add_environment_type_to_environments.rb
@@ -1,4 +1,4 @@
-class AddEnvironmentTypeToEnvironments < ActiveRecord::Migration
+class AddEnvironmentTypeToEnvironments < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160913162434_remove_projects_pushes_since_gc.rb b/db/migrate/20160913162434_remove_projects_pushes_since_gc.rb
index f32167037e0..51650c68170 100644
--- a/db/migrate/20160913162434_remove_projects_pushes_since_gc.rb
+++ b/db/migrate/20160913162434_remove_projects_pushes_since_gc.rb
@@ -3,7 +3,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable Migration/UpdateLargeTable
-class RemoveProjectsPushesSinceGc < ActiveRecord::Migration
+class RemoveProjectsPushesSinceGc < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20160913212128_change_artifacts_size_column.rb b/db/migrate/20160913212128_change_artifacts_size_column.rb
index 063bbca537c..f2c2aaff9a8 100644
--- a/db/migrate/20160913212128_change_artifacts_size_column.rb
+++ b/db/migrate/20160913212128_change_artifacts_size_column.rb
@@ -1,4 +1,4 @@
-class ChangeArtifactsSizeColumn < ActiveRecord::Migration
+class ChangeArtifactsSizeColumn < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20160914131004_only_allow_merge_if_all_discussions_are_resolved.rb b/db/migrate/20160914131004_only_allow_merge_if_all_discussions_are_resolved.rb
index 4da5ec9bd28..81511f9861b 100644
--- a/db/migrate/20160914131004_only_allow_merge_if_all_discussions_are_resolved.rb
+++ b/db/migrate/20160914131004_only_allow_merge_if_all_discussions_are_resolved.rb
@@ -1,4 +1,4 @@
-class OnlyAllowMergeIfAllDiscussionsAreResolved < ActiveRecord::Migration
+class OnlyAllowMergeIfAllDiscussionsAreResolved < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160915042921_create_merge_requests_closing_issues.rb b/db/migrate/20160915042921_create_merge_requests_closing_issues.rb
index 10c5604bb5c..3efe8c8901b 100644
--- a/db/migrate/20160915042921_create_merge_requests_closing_issues.rb
+++ b/db/migrate/20160915042921_create_merge_requests_closing_issues.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable Migration/Timestamps
-class CreateMergeRequestsClosingIssues < ActiveRecord::Migration
+class CreateMergeRequestsClosingIssues < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20160919144305_add_type_to_labels.rb b/db/migrate/20160919144305_add_type_to_labels.rb
index d08b339cd27..f897646d264 100644
--- a/db/migrate/20160919144305_add_type_to_labels.rb
+++ b/db/migrate/20160919144305_add_type_to_labels.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/UpdateColumnInBatches
-class AddTypeToLabels < ActiveRecord::Migration
+class AddTypeToLabels < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20160919145149_add_group_id_to_labels.rb b/db/migrate/20160919145149_add_group_id_to_labels.rb
index 917c2b0c521..df11a2fc4c8 100644
--- a/db/migrate/20160919145149_add_group_id_to_labels.rb
+++ b/db/migrate/20160919145149_add_group_id_to_labels.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class AddGroupIdToLabels < ActiveRecord::Migration
+class AddGroupIdToLabels < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160920160832_add_index_to_labels_title.rb b/db/migrate/20160920160832_add_index_to_labels_title.rb
index e38c655baee..e6c87836d4e 100644
--- a/db/migrate/20160920160832_add_index_to_labels_title.rb
+++ b/db/migrate/20160920160832_add_index_to_labels_title.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class AddIndexToLabelsTitle < ActiveRecord::Migration
+class AddIndexToLabelsTitle < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20160926145521_add_organization_to_user.rb b/db/migrate/20160926145521_add_organization_to_user.rb
index e0bef6e7548..2d8d907591d 100644
--- a/db/migrate/20160926145521_add_organization_to_user.rb
+++ b/db/migrate/20160926145521_add_organization_to_user.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddOrganizationToUser < ActiveRecord::Migration
+class AddOrganizationToUser < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161006104309_add_state_to_environment.rb b/db/migrate/20161006104309_add_state_to_environment.rb
index ccb546654f9..c51dada9bca 100644
--- a/db/migrate/20161006104309_add_state_to_environment.rb
+++ b/db/migrate/20161006104309_add_state_to_environment.rb
@@ -1,4 +1,4 @@
-class AddStateToEnvironment < ActiveRecord::Migration
+class AddStateToEnvironment < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20161007073613_create_user_activities.rb b/db/migrate/20161007073613_create_user_activities.rb
index 1d694e777a1..be3ecb17eef 100644
--- a/db/migrate/20161007073613_create_user_activities.rb
+++ b/db/migrate/20161007073613_create_user_activities.rb
@@ -1,4 +1,4 @@
-class CreateUserActivities < ActiveRecord::Migration
+class CreateUserActivities < ActiveRecord::Migration[4.2]
DOWNTIME = false
# This migration is a no-op. It just exists to match EE.
diff --git a/db/migrate/20161007133303_precalculate_trending_projects.rb b/db/migrate/20161007133303_precalculate_trending_projects.rb
index b324cd94268..c7a678c9d8f 100644
--- a/db/migrate/20161007133303_precalculate_trending_projects.rb
+++ b/db/migrate/20161007133303_precalculate_trending_projects.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class PrecalculateTrendingProjects < ActiveRecord::Migration
+class PrecalculateTrendingProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161010142410_create_project_authorizations.rb b/db/migrate/20161010142410_create_project_authorizations.rb
index e095ab969f8..b340a4ece19 100644
--- a/db/migrate/20161010142410_create_project_authorizations.rb
+++ b/db/migrate/20161010142410_create_project_authorizations.rb
@@ -1,4 +1,4 @@
-class CreateProjectAuthorizations < ActiveRecord::Migration
+class CreateProjectAuthorizations < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161012180455_add_repository_access_level_to_project_feature.rb b/db/migrate/20161012180455_add_repository_access_level_to_project_feature.rb
index 7b33da3ea11..3024ea81ed8 100644
--- a/db/migrate/20161012180455_add_repository_access_level_to_project_feature.rb
+++ b/db/migrate/20161012180455_add_repository_access_level_to_project_feature.rb
@@ -1,4 +1,4 @@
-class AddRepositoryAccessLevelToProjectFeature < ActiveRecord::Migration
+class AddRepositoryAccessLevelToProjectFeature < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20161014173530_create_label_priorities.rb b/db/migrate/20161014173530_create_label_priorities.rb
index 28937c81e02..c7d60caa7d1 100644
--- a/db/migrate/20161014173530_create_label_priorities.rb
+++ b/db/migrate/20161014173530_create_label_priorities.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Timestamps
-class CreateLabelPriorities < ActiveRecord::Migration
+class CreateLabelPriorities < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20161017091941_add_authorized_projects_populated_to_users.rb b/db/migrate/20161017091941_add_authorized_projects_populated_to_users.rb
index 8f6be9dd677..11f4fa1a1f7 100644
--- a/db/migrate/20161017091941_add_authorized_projects_populated_to_users.rb
+++ b/db/migrate/20161017091941_add_authorized_projects_populated_to_users.rb
@@ -1,4 +1,4 @@
-class AddAuthorizedProjectsPopulatedToUsers < ActiveRecord::Migration
+class AddAuthorizedProjectsPopulatedToUsers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161017095000_add_properties_to_deployment.rb b/db/migrate/20161017095000_add_properties_to_deployment.rb
index f620ee0de1c..31bd4cd24ad 100644
--- a/db/migrate/20161017095000_add_properties_to_deployment.rb
+++ b/db/migrate/20161017095000_add_properties_to_deployment.rb
@@ -1,4 +1,4 @@
-class AddPropertiesToDeployment < ActiveRecord::Migration
+class AddPropertiesToDeployment < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161017125927_add_unique_index_to_labels.rb b/db/migrate/20161017125927_add_unique_index_to_labels.rb
index fcdd79d3b02..b5326789f52 100644
--- a/db/migrate/20161017125927_add_unique_index_to_labels.rb
+++ b/db/migrate/20161017125927_add_unique_index_to_labels.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class AddUniqueIndexToLabels < ActiveRecord::Migration
+class AddUniqueIndexToLabels < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20161018024215_migrate_labels_priority.rb b/db/migrate/20161018024215_migrate_labels_priority.rb
index 22bec2382f4..3e2540c134c 100644
--- a/db/migrate/20161018024215_migrate_labels_priority.rb
+++ b/db/migrate/20161018024215_migrate_labels_priority.rb
@@ -1,4 +1,4 @@
-class MigrateLabelsPriority < ActiveRecord::Migration
+class MigrateLabelsPriority < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20161018024550_remove_priority_from_labels.rb b/db/migrate/20161018024550_remove_priority_from_labels.rb
index bc25a43526c..e164d959bdf 100644
--- a/db/migrate/20161018024550_remove_priority_from_labels.rb
+++ b/db/migrate/20161018024550_remove_priority_from_labels.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/RemoveColumn
-class RemovePriorityFromLabels < ActiveRecord::Migration
+class RemovePriorityFromLabels < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20161018124658_make_project_owners_masters.rb b/db/migrate/20161018124658_make_project_owners_masters.rb
index cb93b449067..132c17388dc 100644
--- a/db/migrate/20161018124658_make_project_owners_masters.rb
+++ b/db/migrate/20161018124658_make_project_owners_masters.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/UpdateColumnInBatches
-class MakeProjectOwnersMasters < ActiveRecord::Migration
+class MakeProjectOwnersMasters < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161019190736_migrate_sidekiq_queues_from_default.rb b/db/migrate/20161019190736_migrate_sidekiq_queues_from_default.rb
index 9f502a8df73..fc6d9784638 100644
--- a/db/migrate/20161019190736_migrate_sidekiq_queues_from_default.rb
+++ b/db/migrate/20161019190736_migrate_sidekiq_queues_from_default.rb
@@ -3,7 +3,7 @@ require 'json'
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MigrateSidekiqQueuesFromDefault < ActiveRecord::Migration
+class MigrateSidekiqQueuesFromDefault < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20161019213545_generate_project_feature_for_projects.rb b/db/migrate/20161019213545_generate_project_feature_for_projects.rb
index 4554e14b0df..587bdf60f70 100644
--- a/db/migrate/20161019213545_generate_project_feature_for_projects.rb
+++ b/db/migrate/20161019213545_generate_project_feature_for_projects.rb
@@ -1,4 +1,4 @@
-class GenerateProjectFeatureForProjects < ActiveRecord::Migration
+class GenerateProjectFeatureForProjects < ActiveRecord::Migration[4.2]
DOWNTIME = true
DOWNTIME_REASON = <<-HEREDOC
diff --git a/db/migrate/20161020075734_default_request_access_groups.rb b/db/migrate/20161020075734_default_request_access_groups.rb
index 9721cc88724..72aec86167e 100644
--- a/db/migrate/20161020075734_default_request_access_groups.rb
+++ b/db/migrate/20161020075734_default_request_access_groups.rb
@@ -1,4 +1,4 @@
-class DefaultRequestAccessGroups < ActiveRecord::Migration
+class DefaultRequestAccessGroups < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161020075830_default_request_access_projects.rb b/db/migrate/20161020075830_default_request_access_projects.rb
index a3a53350e8d..b457e39f838 100644
--- a/db/migrate/20161020075830_default_request_access_projects.rb
+++ b/db/migrate/20161020075830_default_request_access_projects.rb
@@ -1,4 +1,4 @@
-class DefaultRequestAccessProjects < ActiveRecord::Migration
+class DefaultRequestAccessProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161020083353_add_pipeline_id_to_merge_request_metrics.rb b/db/migrate/20161020083353_add_pipeline_id_to_merge_request_metrics.rb
index b77daf12f68..60352363e42 100644
--- a/db/migrate/20161020083353_add_pipeline_id_to_merge_request_metrics.rb
+++ b/db/migrate/20161020083353_add_pipeline_id_to_merge_request_metrics.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class AddPipelineIdToMergeRequestMetrics < ActiveRecord::Migration
+class AddPipelineIdToMergeRequestMetrics < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20161020180657_add_minimum_key_length_to_application_settings.rb b/db/migrate/20161020180657_add_minimum_key_length_to_application_settings.rb
index 5b6079002c0..7839bee6a5b 100644
--- a/db/migrate/20161020180657_add_minimum_key_length_to_application_settings.rb
+++ b/db/migrate/20161020180657_add_minimum_key_length_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddMinimumKeyLengthToApplicationSettings < ActiveRecord::Migration
+class AddMinimumKeyLengthToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20161021114307_add_lock_version_to_build_and_pipelines.rb b/db/migrate/20161021114307_add_lock_version_to_build_and_pipelines.rb
index b47f3aa2810..e172dc3adf2 100644
--- a/db/migrate/20161021114307_add_lock_version_to_build_and_pipelines.rb
+++ b/db/migrate/20161021114307_add_lock_version_to_build_and_pipelines.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddLockVersionToBuildAndPipelines < ActiveRecord::Migration
+class AddLockVersionToBuildAndPipelines < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20161024042317_migrate_mailroom_queue_from_default.rb b/db/migrate/20161024042317_migrate_mailroom_queue_from_default.rb
index fc2e4c12b30..d27f8fc38c8 100644
--- a/db/migrate/20161024042317_migrate_mailroom_queue_from_default.rb
+++ b/db/migrate/20161024042317_migrate_mailroom_queue_from_default.rb
@@ -3,7 +3,7 @@ require 'json'
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MigrateMailroomQueueFromDefault < ActiveRecord::Migration
+class MigrateMailroomQueueFromDefault < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20161025231710_migrate_jira_to_gem.rb b/db/migrate/20161025231710_migrate_jira_to_gem.rb
index 870b00411d2..aa1c59ec9e6 100644
--- a/db/migrate/20161025231710_migrate_jira_to_gem.rb
+++ b/db/migrate/20161025231710_migrate_jira_to_gem.rb
@@ -1,4 +1,4 @@
-class MigrateJiraToGem < ActiveRecord::Migration
+class MigrateJiraToGem < ActiveRecord::Migration[4.2]
DOWNTIME = true
DOWNTIME_REASON = <<-HEREDOC
diff --git a/db/migrate/20161031155516_add_housekeeping_to_application_settings.rb b/db/migrate/20161031155516_add_housekeeping_to_application_settings.rb
index 5a451fb575b..963358fe3e5 100644
--- a/db/migrate/20161031155516_add_housekeeping_to_application_settings.rb
+++ b/db/migrate/20161031155516_add_housekeeping_to_application_settings.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddHousekeepingToApplicationSettings < ActiveRecord::Migration
+class AddHousekeepingToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20161031171301_add_project_id_to_subscriptions.rb b/db/migrate/20161031171301_add_project_id_to_subscriptions.rb
index 8b1c10a124f..5fd10d9b359 100644
--- a/db/migrate/20161031171301_add_project_id_to_subscriptions.rb
+++ b/db/migrate/20161031171301_add_project_id_to_subscriptions.rb
@@ -1,4 +1,4 @@
-class AddProjectIdToSubscriptions < ActiveRecord::Migration
+class AddProjectIdToSubscriptions < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161031174110_migrate_subscriptions_project_id.rb b/db/migrate/20161031174110_migrate_subscriptions_project_id.rb
index 549145a0a65..7f4087fdcd3 100644
--- a/db/migrate/20161031174110_migrate_subscriptions_project_id.rb
+++ b/db/migrate/20161031174110_migrate_subscriptions_project_id.rb
@@ -1,4 +1,4 @@
-class MigrateSubscriptionsProjectId < ActiveRecord::Migration
+class MigrateSubscriptionsProjectId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20161031181638_add_unique_index_to_subscriptions.rb b/db/migrate/20161031181638_add_unique_index_to_subscriptions.rb
index f263377fbc6..23a775d6282 100644
--- a/db/migrate/20161031181638_add_unique_index_to_subscriptions.rb
+++ b/db/migrate/20161031181638_add_unique_index_to_subscriptions.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class AddUniqueIndexToSubscriptions < ActiveRecord::Migration
+class AddUniqueIndexToSubscriptions < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20161103171205_rename_repository_storage_column.rb b/db/migrate/20161103171205_rename_repository_storage_column.rb
index 93280573939..d6050500e47 100644
--- a/db/migrate/20161103171205_rename_repository_storage_column.rb
+++ b/db/migrate/20161103171205_rename_repository_storage_column.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RenameRepositoryStorageColumn < ActiveRecord::Migration
+class RenameRepositoryStorageColumn < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20161103191444_add_sidekiq_throttling_to_application_settings.rb b/db/migrate/20161103191444_add_sidekiq_throttling_to_application_settings.rb
index 522437b92b4..83c51c83509 100644
--- a/db/migrate/20161103191444_add_sidekiq_throttling_to_application_settings.rb
+++ b/db/migrate/20161103191444_add_sidekiq_throttling_to_application_settings.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable Migration/SaferBooleanColumn
-class AddSidekiqThrottlingToApplicationSettings < ActiveRecord::Migration
+class AddSidekiqThrottlingToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20161106185620_add_project_import_data_project_index.rb b/db/migrate/20161106185620_add_project_import_data_project_index.rb
index b3746dc4f6c..46809ca1707 100644
--- a/db/migrate/20161106185620_add_project_import_data_project_index.rb
+++ b/db/migrate/20161106185620_add_project_import_data_project_index.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class AddProjectImportDataProjectIndex < ActiveRecord::Migration
+class AddProjectImportDataProjectIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20161113184239_create_user_chat_names_table.rb b/db/migrate/20161113184239_create_user_chat_names_table.rb
index 7bead07fd76..0031ca66afe 100644
--- a/db/migrate/20161113184239_create_user_chat_names_table.rb
+++ b/db/migrate/20161113184239_create_user_chat_names_table.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Timestamps
-class CreateUserChatNamesTable < ActiveRecord::Migration
+class CreateUserChatNamesTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161114024742_add_coverage_regex_to_builds.rb b/db/migrate/20161114024742_add_coverage_regex_to_builds.rb
index 88aa5d52b39..631968b4aee 100644
--- a/db/migrate/20161114024742_add_coverage_regex_to_builds.rb
+++ b/db/migrate/20161114024742_add_coverage_regex_to_builds.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddCoverageRegexToBuilds < ActiveRecord::Migration
+class AddCoverageRegexToBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20161115173905_add_start_date_to_milestones.rb b/db/migrate/20161115173905_add_start_date_to_milestones.rb
index 413733b8db7..847c4f0bebb 100644
--- a/db/migrate/20161115173905_add_start_date_to_milestones.rb
+++ b/db/migrate/20161115173905_add_start_date_to_milestones.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddStartDateToMilestones < ActiveRecord::Migration
+class AddStartDateToMilestones < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161117114805_remove_undeleted_groups.rb b/db/migrate/20161117114805_remove_undeleted_groups.rb
index 29040583aa2..0a4fe1c05b7 100644
--- a/db/migrate/20161117114805_remove_undeleted_groups.rb
+++ b/db/migrate/20161117114805_remove_undeleted_groups.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveUndeletedGroups < ActiveRecord::Migration
+class RemoveUndeletedGroups < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20161118183841_add_commit_events_to_services.rb b/db/migrate/20161118183841_add_commit_events_to_services.rb
index 4f9b5dd2281..0eb08915118 100644
--- a/db/migrate/20161118183841_add_commit_events_to_services.rb
+++ b/db/migrate/20161118183841_add_commit_events_to_services.rb
@@ -1,4 +1,4 @@
-class AddCommitEventsToServices < ActiveRecord::Migration
+class AddCommitEventsToServices < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161124111390_add_parent_id_to_namespace.rb b/db/migrate/20161124111390_add_parent_id_to_namespace.rb
index a6fa1b70a9d..67f6aee2b9c 100644
--- a/db/migrate/20161124111390_add_parent_id_to_namespace.rb
+++ b/db/migrate/20161124111390_add_parent_id_to_namespace.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddParentIdToNamespace < ActiveRecord::Migration
+class AddParentIdToNamespace < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161124111395_add_index_to_parent_id.rb b/db/migrate/20161124111395_add_index_to_parent_id.rb
index 065643e058d..d7a51ec905a 100644
--- a/db/migrate/20161124111395_add_index_to_parent_id.rb
+++ b/db/migrate/20161124111395_add_index_to_parent_id.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class AddIndexToParentId < ActiveRecord::Migration
+class AddIndexToParentId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161124111402_add_routes_table.rb b/db/migrate/20161124111402_add_routes_table.rb
index f5241d906d1..36f49ef8c97 100644
--- a/db/migrate/20161124111402_add_routes_table.rb
+++ b/db/migrate/20161124111402_add_routes_table.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable Migration/Timestamps
-class AddRoutesTable < ActiveRecord::Migration
+class AddRoutesTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161124141322_migrate_process_commit_worker_jobs.rb b/db/migrate/20161124141322_migrate_process_commit_worker_jobs.rb
index 1eb6a8fa5df..0772821210c 100644
--- a/db/migrate/20161124141322_migrate_process_commit_worker_jobs.rb
+++ b/db/migrate/20161124141322_migrate_process_commit_worker_jobs.rb
@@ -1,4 +1,4 @@
-class MigrateProcessCommitWorkerJobs < ActiveRecord::Migration
+class MigrateProcessCommitWorkerJobs < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
class Repository
diff --git a/db/migrate/20161128095517_add_in_reply_to_discussion_id_to_sent_notifications.rb b/db/migrate/20161128095517_add_in_reply_to_discussion_id_to_sent_notifications.rb
index d56d83ca1d3..a2971486014 100644
--- a/db/migrate/20161128095517_add_in_reply_to_discussion_id_to_sent_notifications.rb
+++ b/db/migrate/20161128095517_add_in_reply_to_discussion_id_to_sent_notifications.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddInReplyToDiscussionIdToSentNotifications < ActiveRecord::Migration
+class AddInReplyToDiscussionIdToSentNotifications < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20161128142110_remove_unnecessary_indexes.rb b/db/migrate/20161128142110_remove_unnecessary_indexes.rb
index 699a9368eb3..b6c6e303ec7 100644
--- a/db/migrate/20161128142110_remove_unnecessary_indexes.rb
+++ b/db/migrate/20161128142110_remove_unnecessary_indexes.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class RemoveUnnecessaryIndexes < ActiveRecord::Migration
+class RemoveUnnecessaryIndexes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20161128161412_add_html_emails_enabled_to_application_settings.rb b/db/migrate/20161128161412_add_html_emails_enabled_to_application_settings.rb
index 38f5781745b..63139eb97bd 100644
--- a/db/migrate/20161128161412_add_html_emails_enabled_to_application_settings.rb
+++ b/db/migrate/20161128161412_add_html_emails_enabled_to_application_settings.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable Migration/SaferBooleanColumn
-class AddHtmlEmailsEnabledToApplicationSettings < ActiveRecord::Migration
+class AddHtmlEmailsEnabledToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20161130095245_fill_routes_table.rb b/db/migrate/20161130095245_fill_routes_table.rb
index c3536d6d911..712be187c7c 100644
--- a/db/migrate/20161130095245_fill_routes_table.rb
+++ b/db/migrate/20161130095245_fill_routes_table.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class FillRoutesTable < ActiveRecord::Migration
+class FillRoutesTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20161130101252_fill_projects_routes_table.rb b/db/migrate/20161130101252_fill_projects_routes_table.rb
index 56ba6fcdbe3..1900d6c8013 100644
--- a/db/migrate/20161130101252_fill_projects_routes_table.rb
+++ b/db/migrate/20161130101252_fill_projects_routes_table.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class FillProjectsRoutesTable < ActiveRecord::Migration
+class FillProjectsRoutesTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20161201001911_add_plant_uml_url_to_application_settings.rb b/db/migrate/20161201001911_add_plant_uml_url_to_application_settings.rb
index b8d8742ae40..79558a6b3b9 100644
--- a/db/migrate/20161201001911_add_plant_uml_url_to_application_settings.rb
+++ b/db/migrate/20161201001911_add_plant_uml_url_to_application_settings.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddPlantUmlUrlToApplicationSettings < ActiveRecord::Migration
+class AddPlantUmlUrlToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161201155511_create_project_statistics.rb b/db/migrate/20161201155511_create_project_statistics.rb
index 26e6d3623eb..6dcb5adb82b 100644
--- a/db/migrate/20161201155511_create_project_statistics.rb
+++ b/db/migrate/20161201155511_create_project_statistics.rb
@@ -1,4 +1,4 @@
-class CreateProjectStatistics < ActiveRecord::Migration
+class CreateProjectStatistics < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161201160452_migrate_project_statistics.rb b/db/migrate/20161201160452_migrate_project_statistics.rb
index a547409aaa5..42c5be07e83 100644
--- a/db/migrate/20161201160452_migrate_project_statistics.rb
+++ b/db/migrate/20161201160452_migrate_project_statistics.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/RemoveColumn
-class MigrateProjectStatistics < ActiveRecord::Migration
+class MigrateProjectStatistics < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20161202152031_remove_duplicates_from_routes.rb b/db/migrate/20161202152031_remove_duplicates_from_routes.rb
index d73b0847506..0615f683859 100644
--- a/db/migrate/20161202152031_remove_duplicates_from_routes.rb
+++ b/db/migrate/20161202152031_remove_duplicates_from_routes.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveDuplicatesFromRoutes < ActiveRecord::Migration
+class RemoveDuplicatesFromRoutes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161202152035_add_index_to_routes.rb b/db/migrate/20161202152035_add_index_to_routes.rb
index 552b5fab68c..ad2e0cd13c9 100644
--- a/db/migrate/20161202152035_add_index_to_routes.rb
+++ b/db/migrate/20161202152035_add_index_to_routes.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class AddIndexToRoutes < ActiveRecord::Migration
+class AddIndexToRoutes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20161206003819_add_plant_uml_enabled_to_application_settings.rb b/db/migrate/20161206003819_add_plant_uml_enabled_to_application_settings.rb
index 7f56ecf4c9e..bb44d56ee56 100644
--- a/db/migrate/20161206003819_add_plant_uml_enabled_to_application_settings.rb
+++ b/db/migrate/20161206003819_add_plant_uml_enabled_to_application_settings.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable Migration/SaferBooleanColumn
-class AddPlantUmlEnabledToApplicationSettings < ActiveRecord::Migration
+class AddPlantUmlEnabledToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161206153749_remove_uniq_path_index_from_namespace.rb b/db/migrate/20161206153749_remove_uniq_path_index_from_namespace.rb
index 7d39c2ae626..c301d76646e 100644
--- a/db/migrate/20161206153749_remove_uniq_path_index_from_namespace.rb
+++ b/db/migrate/20161206153749_remove_uniq_path_index_from_namespace.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class RemoveUniqPathIndexFromNamespace < ActiveRecord::Migration
+class RemoveUniqPathIndexFromNamespace < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20161206153751_add_path_index_to_namespace.rb b/db/migrate/20161206153751_add_path_index_to_namespace.rb
index 623037e35cd..f0848cc59a5 100644
--- a/db/migrate/20161206153751_add_path_index_to_namespace.rb
+++ b/db/migrate/20161206153751_add_path_index_to_namespace.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class AddPathIndexToNamespace < ActiveRecord::Migration
+class AddPathIndexToNamespace < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20161206153753_remove_uniq_name_index_from_namespace.rb b/db/migrate/20161206153753_remove_uniq_name_index_from_namespace.rb
index 9296ae36aa5..13660cec7aa 100644
--- a/db/migrate/20161206153753_remove_uniq_name_index_from_namespace.rb
+++ b/db/migrate/20161206153753_remove_uniq_name_index_from_namespace.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class RemoveUniqNameIndexFromNamespace < ActiveRecord::Migration
+class RemoveUniqNameIndexFromNamespace < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20161206153754_add_name_index_to_namespace.rb b/db/migrate/20161206153754_add_name_index_to_namespace.rb
index 2bbd039ff27..14152a6dc07 100644
--- a/db/migrate/20161206153754_add_name_index_to_namespace.rb
+++ b/db/migrate/20161206153754_add_name_index_to_namespace.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class AddNameIndexToNamespace < ActiveRecord::Migration
+class AddNameIndexToNamespace < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20161207231620_fixup_environment_name_uniqueness.rb b/db/migrate/20161207231620_fixup_environment_name_uniqueness.rb
index 1db8c68626a..7cae09021cd 100644
--- a/db/migrate/20161207231620_fixup_environment_name_uniqueness.rb
+++ b/db/migrate/20161207231620_fixup_environment_name_uniqueness.rb
@@ -1,4 +1,4 @@
-class FixupEnvironmentNameUniqueness < ActiveRecord::Migration
+class FixupEnvironmentNameUniqueness < ActiveRecord::Migration[4.2]
include Gitlab::Database::ArelMethods
include Gitlab::Database::MigrationHelpers
diff --git a/db/migrate/20161207231621_create_environment_name_unique_index.rb b/db/migrate/20161207231621_create_environment_name_unique_index.rb
index 15093350f12..28d22664405 100644
--- a/db/migrate/20161207231621_create_environment_name_unique_index.rb
+++ b/db/migrate/20161207231621_create_environment_name_unique_index.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class CreateEnvironmentNameUniqueIndex < ActiveRecord::Migration
+class CreateEnvironmentNameUniqueIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20161207231626_add_environment_slug.rb b/db/migrate/20161207231626_add_environment_slug.rb
index 162f82a01cb..4657b023dfa 100644
--- a/db/migrate/20161207231626_add_environment_slug.rb
+++ b/db/migrate/20161207231626_add_environment_slug.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddEnvironmentSlug < ActiveRecord::Migration
+class AddEnvironmentSlug < ActiveRecord::Migration[4.2]
include Gitlab::Database::ArelMethods
include Gitlab::Database::MigrationHelpers
diff --git a/db/migrate/20161209153400_add_unique_index_for_environment_slug.rb b/db/migrate/20161209153400_add_unique_index_for_environment_slug.rb
index 42a90091b87..57606a33cb9 100644
--- a/db/migrate/20161209153400_add_unique_index_for_environment_slug.rb
+++ b/db/migrate/20161209153400_add_unique_index_for_environment_slug.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class AddUniqueIndexForEnvironmentSlug < ActiveRecord::Migration
+class AddUniqueIndexForEnvironmentSlug < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20161209165216_create_doorkeeper_openid_connect_tables.rb b/db/migrate/20161209165216_create_doorkeeper_openid_connect_tables.rb
index e63d5927f86..e8ea9cf8fda 100644
--- a/db/migrate/20161209165216_create_doorkeeper_openid_connect_tables.rb
+++ b/db/migrate/20161209165216_create_doorkeeper_openid_connect_tables.rb
@@ -1,4 +1,4 @@
-class CreateDoorkeeperOpenidConnectTables < ActiveRecord::Migration
+class CreateDoorkeeperOpenidConnectTables < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161212142807_add_lower_path_index_to_routes.rb b/db/migrate/20161212142807_add_lower_path_index_to_routes.rb
index 76db5179795..92a12dbc699 100644
--- a/db/migrate/20161212142807_add_lower_path_index_to_routes.rb
+++ b/db/migrate/20161212142807_add_lower_path_index_to_routes.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class AddLowerPathIndexToRoutes < ActiveRecord::Migration
+class AddLowerPathIndexToRoutes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161213172958_change_slack_service_to_slack_notification_service.rb b/db/migrate/20161213172958_change_slack_service_to_slack_notification_service.rb
index dc38d0ac906..babac6bfc4f 100644
--- a/db/migrate/20161213172958_change_slack_service_to_slack_notification_service.rb
+++ b/db/migrate/20161213172958_change_slack_service_to_slack_notification_service.rb
@@ -1,4 +1,4 @@
-class ChangeSlackServiceToSlackNotificationService < ActiveRecord::Migration
+class ChangeSlackServiceToSlackNotificationService < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161220141214_remove_dot_git_from_group_names.rb b/db/migrate/20161220141214_remove_dot_git_from_group_names.rb
index 17357b67ab7..5c0b083325e 100644
--- a/db/migrate/20161220141214_remove_dot_git_from_group_names.rb
+++ b/db/migrate/20161220141214_remove_dot_git_from_group_names.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveDotGitFromGroupNames < ActiveRecord::Migration
+class RemoveDotGitFromGroupNames < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
include Gitlab::ShellAdapter
diff --git a/db/migrate/20161221152132_add_last_used_at_to_key.rb b/db/migrate/20161221152132_add_last_used_at_to_key.rb
index 86dc7870247..a5b3f2b6f4b 100644
--- a/db/migrate/20161221152132_add_last_used_at_to_key.rb
+++ b/db/migrate/20161221152132_add_last_used_at_to_key.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Datetime
-class AddLastUsedAtToKey < ActiveRecord::Migration
+class AddLastUsedAtToKey < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161223034433_add_estimate_to_issuables_ce.rb b/db/migrate/20161223034433_add_estimate_to_issuables_ce.rb
index d5116dfab49..75bea41387c 100644
--- a/db/migrate/20161223034433_add_estimate_to_issuables_ce.rb
+++ b/db/migrate/20161223034433_add_estimate_to_issuables_ce.rb
@@ -1,4 +1,4 @@
-class AddEstimateToIssuablesCe < ActiveRecord::Migration
+class AddEstimateToIssuablesCe < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161223034646_create_timelogs_ce.rb b/db/migrate/20161223034646_create_timelogs_ce.rb
index 1e894cc9161..489a2b35dfd 100644
--- a/db/migrate/20161223034646_create_timelogs_ce.rb
+++ b/db/migrate/20161223034646_create_timelogs_ce.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Timestamps
-class CreateTimelogsCe < ActiveRecord::Migration
+class CreateTimelogsCe < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161226122833_remove_dot_git_from_usernames.rb b/db/migrate/20161226122833_remove_dot_git_from_usernames.rb
index db10426b483..e3318780151 100644
--- a/db/migrate/20161226122833_remove_dot_git_from_usernames.rb
+++ b/db/migrate/20161226122833_remove_dot_git_from_usernames.rb
@@ -1,4 +1,4 @@
-class RemoveDotGitFromUsernames < ActiveRecord::Migration
+class RemoveDotGitFromUsernames < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
include Gitlab::ShellAdapter
diff --git a/db/migrate/20161227192806_rename_slack_and_mattermost_notification_services.rb b/db/migrate/20161227192806_rename_slack_and_mattermost_notification_services.rb
index 6b15e5caccf..df5714278f2 100644
--- a/db/migrate/20161227192806_rename_slack_and_mattermost_notification_services.rb
+++ b/db/migrate/20161227192806_rename_slack_and_mattermost_notification_services.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/UpdateColumnInBatches
-class RenameSlackAndMattermostNotificationServices < ActiveRecord::Migration
+class RenameSlackAndMattermostNotificationServices < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20161228124936_change_expires_at_to_date_in_personal_access_tokens.rb b/db/migrate/20161228124936_change_expires_at_to_date_in_personal_access_tokens.rb
index 16f7cc487ce..f9f8f11316d 100644
--- a/db/migrate/20161228124936_change_expires_at_to_date_in_personal_access_tokens.rb
+++ b/db/migrate/20161228124936_change_expires_at_to_date_in_personal_access_tokens.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable Migration/Datetime
-class ChangeExpiresAtToDateInPersonalAccessTokens < ActiveRecord::Migration
+class ChangeExpiresAtToDateInPersonalAccessTokens < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20161228135550_add_impersonation_to_personal_access_tokens.rb b/db/migrate/20161228135550_add_impersonation_to_personal_access_tokens.rb
index ea9caceaa2c..489d7fb8b75 100644
--- a/db/migrate/20161228135550_add_impersonation_to_personal_access_tokens.rb
+++ b/db/migrate/20161228135550_add_impersonation_to_personal_access_tokens.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddImpersonationToPersonalAccessTokens < ActiveRecord::Migration
+class AddImpersonationToPersonalAccessTokens < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20170120131253_create_chat_teams.rb b/db/migrate/20170120131253_create_chat_teams.rb
index 52208821911..e9b9bd7bd2f 100644
--- a/db/migrate/20170120131253_create_chat_teams.rb
+++ b/db/migrate/20170120131253_create_chat_teams.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Timestamps
-class CreateChatTeams < ActiveRecord::Migration
+class CreateChatTeams < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20170121123724_add_index_to_ci_builds_for_status_runner_id_and_type.rb b/db/migrate/20170121123724_add_index_to_ci_builds_for_status_runner_id_and_type.rb
index c006098fafd..cc1a4d2db59 100644
--- a/db/migrate/20170121123724_add_index_to_ci_builds_for_status_runner_id_and_type.rb
+++ b/db/migrate/20170121123724_add_index_to_ci_builds_for_status_runner_id_and_type.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class AddIndexToCiBuildsForStatusRunnerIdAndType < ActiveRecord::Migration
+class AddIndexToCiBuildsForStatusRunnerIdAndType < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170121130655_add_index_to_ci_runners_for_is_shared.rb b/db/migrate/20170121130655_add_index_to_ci_runners_for_is_shared.rb
index 00aa0b311b1..1b83ce4cfe3 100644
--- a/db/migrate/20170121130655_add_index_to_ci_runners_for_is_shared.rb
+++ b/db/migrate/20170121130655_add_index_to_ci_runners_for_is_shared.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class AddIndexToCiRunnersForIsShared < ActiveRecord::Migration
+class AddIndexToCiRunnersForIsShared < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170124174637_add_foreign_keys_to_timelogs.rb b/db/migrate/20170124174637_add_foreign_keys_to_timelogs.rb
index a7d4e141a1a..ffd966be086 100644
--- a/db/migrate/20170124174637_add_foreign_keys_to_timelogs.rb
+++ b/db/migrate/20170124174637_add_foreign_keys_to_timelogs.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddForeignKeysToTimelogs < ActiveRecord::Migration
+class AddForeignKeysToTimelogs < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170124193147_add_two_factor_columns_to_namespaces.rb b/db/migrate/20170124193147_add_two_factor_columns_to_namespaces.rb
index 27ebe0af33b..324e051666b 100644
--- a/db/migrate/20170124193147_add_two_factor_columns_to_namespaces.rb
+++ b/db/migrate/20170124193147_add_two_factor_columns_to_namespaces.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/UpdateLargeTable
-class AddTwoFactorColumnsToNamespaces < ActiveRecord::Migration
+class AddTwoFactorColumnsToNamespaces < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170124193205_add_two_factor_columns_to_users.rb b/db/migrate/20170124193205_add_two_factor_columns_to_users.rb
index 558a1837c79..6c80dbfc965 100644
--- a/db/migrate/20170124193205_add_two_factor_columns_to_users.rb
+++ b/db/migrate/20170124193205_add_two_factor_columns_to_users.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/UpdateLargeTable
-class AddTwoFactorColumnsToUsers < ActiveRecord::Migration
+class AddTwoFactorColumnsToUsers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170126174819_add_terminal_max_session_time_to_application_settings.rb b/db/migrate/20170126174819_add_terminal_max_session_time_to_application_settings.rb
index 334f53f9145..70f1669108a 100644
--- a/db/migrate/20170126174819_add_terminal_max_session_time_to_application_settings.rb
+++ b/db/migrate/20170126174819_add_terminal_max_session_time_to_application_settings.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddTerminalMaxSessionTimeToApplicationSettings < ActiveRecord::Migration
+class AddTerminalMaxSessionTimeToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170127032550_remove_backlog_lists_from_boards.rb b/db/migrate/20170127032550_remove_backlog_lists_from_boards.rb
index 0ee4229d1f8..2e2fecfa2a7 100644
--- a/db/migrate/20170127032550_remove_backlog_lists_from_boards.rb
+++ b/db/migrate/20170127032550_remove_backlog_lists_from_boards.rb
@@ -1,4 +1,4 @@
-class RemoveBacklogListsFromBoards < ActiveRecord::Migration
+class RemoveBacklogListsFromBoards < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20170130204620_add_index_to_project_authorizations.rb b/db/migrate/20170130204620_add_index_to_project_authorizations.rb
index f256251516a..28c4480e9c6 100644
--- a/db/migrate/20170130204620_add_index_to_project_authorizations.rb
+++ b/db/migrate/20170130204620_add_index_to_project_authorizations.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class AddIndexToProjectAuthorizations < ActiveRecord::Migration
+class AddIndexToProjectAuthorizations < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170130221926_create_uploads.rb b/db/migrate/20170130221926_create_uploads.rb
index 6f06c5dd840..7bf15ca4978 100644
--- a/db/migrate/20170130221926_create_uploads.rb
+++ b/db/migrate/20170130221926_create_uploads.rb
@@ -1,4 +1,4 @@
-class CreateUploads < ActiveRecord::Migration
+class CreateUploads < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170131221752_add_relative_position_to_issues.rb b/db/migrate/20170131221752_add_relative_position_to_issues.rb
index fd18d8b6a60..126cb9e5415 100644
--- a/db/migrate/20170131221752_add_relative_position_to_issues.rb
+++ b/db/migrate/20170131221752_add_relative_position_to_issues.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class AddRelativePositionToIssues < ActiveRecord::Migration
+class AddRelativePositionToIssues < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170204172458_add_name_to_route.rb b/db/migrate/20170204172458_add_name_to_route.rb
index 38ed1ad9039..e7c94aceb26 100644
--- a/db/migrate/20170204172458_add_name_to_route.rb
+++ b/db/migrate/20170204172458_add_name_to_route.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddNameToRoute < ActiveRecord::Migration
+class AddNameToRoute < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170204181513_add_index_to_labels_for_type_and_project.rb b/db/migrate/20170204181513_add_index_to_labels_for_type_and_project.rb
index b1b0a601007..746322885b1 100644
--- a/db/migrate/20170204181513_add_index_to_labels_for_type_and_project.rb
+++ b/db/migrate/20170204181513_add_index_to_labels_for_type_and_project.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class AddIndexToLabelsForTypeAndProject < ActiveRecord::Migration
+class AddIndexToLabelsForTypeAndProject < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170206071414_add_recaptcha_verified_to_spam_logs.rb b/db/migrate/20170206071414_add_recaptcha_verified_to_spam_logs.rb
index 44372334d21..06338ac943e 100644
--- a/db/migrate/20170206071414_add_recaptcha_verified_to_spam_logs.rb
+++ b/db/migrate/20170206071414_add_recaptcha_verified_to_spam_logs.rb
@@ -1,4 +1,4 @@
-class AddRecaptchaVerifiedToSpamLogs < ActiveRecord::Migration
+class AddRecaptchaVerifiedToSpamLogs < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20170206115204_add_column_ghost_to_users.rb b/db/migrate/20170206115204_add_column_ghost_to_users.rb
index cc1eeda1160..4b86814e05d 100644
--- a/db/migrate/20170206115204_add_column_ghost_to_users.rb
+++ b/db/migrate/20170206115204_add_column_ghost_to_users.rb
@@ -1,4 +1,4 @@
-class AddColumnGhostToUsers < ActiveRecord::Migration
+class AddColumnGhostToUsers < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20170210062829_add_index_to_labels_for_title_and_project.rb b/db/migrate/20170210062829_add_index_to_labels_for_title_and_project.rb
index 2c20f6a48ab..d0b440b8ccb 100644
--- a/db/migrate/20170210062829_add_index_to_labels_for_title_and_project.rb
+++ b/db/migrate/20170210062829_add_index_to_labels_for_title_and_project.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class AddIndexToLabelsForTitleAndProject < ActiveRecord::Migration
+class AddIndexToLabelsForTitleAndProject < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170210075922_add_index_to_ci_trigger_requests_for_commit_id.rb b/db/migrate/20170210075922_add_index_to_ci_trigger_requests_for_commit_id.rb
index c31057f2617..753d6c77e35 100644
--- a/db/migrate/20170210075922_add_index_to_ci_trigger_requests_for_commit_id.rb
+++ b/db/migrate/20170210075922_add_index_to_ci_trigger_requests_for_commit_id.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class AddIndexToCiTriggerRequestsForCommitId < ActiveRecord::Migration
+class AddIndexToCiTriggerRequestsForCommitId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170210103609_add_index_to_user_agent_detail.rb b/db/migrate/20170210103609_add_index_to_user_agent_detail.rb
index ba4976a5ce8..a2d6528ea82 100644
--- a/db/migrate/20170210103609_add_index_to_user_agent_detail.rb
+++ b/db/migrate/20170210103609_add_index_to_user_agent_detail.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class AddIndexToUserAgentDetail < ActiveRecord::Migration
+class AddIndexToUserAgentDetail < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170210131347_add_unique_ips_limit_to_application_settings.rb b/db/migrate/20170210131347_add_unique_ips_limit_to_application_settings.rb
index 9ab970134be..c286354f476 100644
--- a/db/migrate/20170210131347_add_unique_ips_limit_to_application_settings.rb
+++ b/db/migrate/20170210131347_add_unique_ips_limit_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddUniqueIpsLimitToApplicationSettings < ActiveRecord::Migration
+class AddUniqueIpsLimitToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
diff --git a/db/migrate/20170214084746_add_default_artifacts_expiration_to_application_settings.rb b/db/migrate/20170214084746_add_default_artifacts_expiration_to_application_settings.rb
index e0e3ff8957a..84814c2f8f2 100644
--- a/db/migrate/20170214084746_add_default_artifacts_expiration_to_application_settings.rb
+++ b/db/migrate/20170214084746_add_default_artifacts_expiration_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddDefaultArtifactsExpirationToApplicationSettings < ActiveRecord::Migration
+class AddDefaultArtifactsExpirationToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170216135621_add_index_for_latest_successful_pipeline.rb b/db/migrate/20170216135621_add_index_for_latest_successful_pipeline.rb
index 884c4e569d6..be393bd496d 100644
--- a/db/migrate/20170216135621_add_index_for_latest_successful_pipeline.rb
+++ b/db/migrate/20170216135621_add_index_for_latest_successful_pipeline.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class AddIndexForLatestSuccessfulPipeline < ActiveRecord::Migration
+class AddIndexForLatestSuccessfulPipeline < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170216141440_drop_index_for_builds_project_status.rb b/db/migrate/20170216141440_drop_index_for_builds_project_status.rb
index 56ad566ca67..7edf7dd7e10 100644
--- a/db/migrate/20170216141440_drop_index_for_builds_project_status.rb
+++ b/db/migrate/20170216141440_drop_index_for_builds_project_status.rb
@@ -1,5 +1,5 @@
# rubocop:disable RemoveIndex
-class DropIndexForBuildsProjectStatus < ActiveRecord::Migration
+class DropIndexForBuildsProjectStatus < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170217132157_rename_merge_when_build_succeeds.rb b/db/migrate/20170217132157_rename_merge_when_build_succeeds.rb
index 9011526565d..ee8838eff56 100644
--- a/db/migrate/20170217132157_rename_merge_when_build_succeeds.rb
+++ b/db/migrate/20170217132157_rename_merge_when_build_succeeds.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RenameMergeWhenBuildSucceeds < ActiveRecord::Migration
+class RenameMergeWhenBuildSucceeds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170217151947_rename_only_allow_merge_if_build_succeeds.rb b/db/migrate/20170217151947_rename_only_allow_merge_if_build_succeeds.rb
index b2b68ff72d1..5d35216f3af 100644
--- a/db/migrate/20170217151947_rename_only_allow_merge_if_build_succeeds.rb
+++ b/db/migrate/20170217151947_rename_only_allow_merge_if_build_succeeds.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RenameOnlyAllowMergeIfBuildSucceeds < ActiveRecord::Migration
+class RenameOnlyAllowMergeIfBuildSucceeds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170217151948_add_owner_id_to_triggers.rb b/db/migrate/20170217151948_add_owner_id_to_triggers.rb
index 16d7cc5bed6..a28711ae59a 100644
--- a/db/migrate/20170217151948_add_owner_id_to_triggers.rb
+++ b/db/migrate/20170217151948_add_owner_id_to_triggers.rb
@@ -1,4 +1,4 @@
-class AddOwnerIdToTriggers < ActiveRecord::Migration
+class AddOwnerIdToTriggers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170217151949_add_description_to_triggers.rb b/db/migrate/20170217151949_add_description_to_triggers.rb
index 1dca0e37412..27cb4b3ab31 100644
--- a/db/migrate/20170217151949_add_description_to_triggers.rb
+++ b/db/migrate/20170217151949_add_description_to_triggers.rb
@@ -1,4 +1,4 @@
-class AddDescriptionToTriggers < ActiveRecord::Migration
+class AddDescriptionToTriggers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170222111732_create_gpg_keys.rb b/db/migrate/20170222111732_create_gpg_keys.rb
index 541228e8735..012e8ef5854 100644
--- a/db/migrate/20170222111732_create_gpg_keys.rb
+++ b/db/migrate/20170222111732_create_gpg_keys.rb
@@ -1,4 +1,6 @@
-class CreateGpgKeys < ActiveRecord::Migration
+class CreateGpgKeys < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
DOWNTIME = false
def change
@@ -12,8 +14,8 @@ class CreateGpgKeys < ActiveRecord::Migration
t.text :key
- t.index :primary_keyid, unique: true, length: Gitlab::Database.mysql? ? 20 : nil
- t.index :fingerprint, unique: true, length: Gitlab::Database.mysql? ? 20 : nil
+ t.index :primary_keyid, unique: true, length: mysql_compatible_index_length
+ t.index :fingerprint, unique: true, length: mysql_compatible_index_length
end
end
end
diff --git a/db/migrate/20170222143317_drop_ci_projects.rb b/db/migrate/20170222143317_drop_ci_projects.rb
index 4db8658f36f..9f3aa2da382 100644
--- a/db/migrate/20170222143317_drop_ci_projects.rb
+++ b/db/migrate/20170222143317_drop_ci_projects.rb
@@ -1,4 +1,4 @@
-class DropCiProjects < ActiveRecord::Migration
+class DropCiProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170222143500_remove_old_project_id_columns.rb b/db/migrate/20170222143500_remove_old_project_id_columns.rb
index 9bed38a3444..356dee4a060 100644
--- a/db/migrate/20170222143500_remove_old_project_id_columns.rb
+++ b/db/migrate/20170222143500_remove_old_project_id_columns.rb
@@ -1,6 +1,6 @@
# rubocop:disable Migration/RemoveColumn
# rubocop:disable RemoveIndex
-class RemoveOldProjectIdColumns < ActiveRecord::Migration
+class RemoveOldProjectIdColumns < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20170222143603_rename_gl_project_id_to_project_id.rb b/db/migrate/20170222143603_rename_gl_project_id_to_project_id.rb
index 7c19d471557..390b2c33d91 100644
--- a/db/migrate/20170222143603_rename_gl_project_id_to_project_id.rb
+++ b/db/migrate/20170222143603_rename_gl_project_id_to_project_id.rb
@@ -1,4 +1,4 @@
-class RenameGlProjectIdToProjectId < ActiveRecord::Migration
+class RenameGlProjectIdToProjectId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20170301101006_add_ci_runner_namespaces.rb b/db/migrate/20170301101006_add_ci_runner_namespaces.rb
index deaf03e928b..aa2d8a14242 100644
--- a/db/migrate/20170301101006_add_ci_runner_namespaces.rb
+++ b/db/migrate/20170301101006_add_ci_runner_namespaces.rb
@@ -1,4 +1,4 @@
-class AddCiRunnerNamespaces < ActiveRecord::Migration
+class AddCiRunnerNamespaces < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170301125302_add_printing_merge_request_link_enabled_to_project.rb b/db/migrate/20170301125302_add_printing_merge_request_link_enabled_to_project.rb
index 6d43f346d4f..a7efeb8ae6f 100644
--- a/db/migrate/20170301125302_add_printing_merge_request_link_enabled_to_project.rb
+++ b/db/migrate/20170301125302_add_printing_merge_request_link_enabled_to_project.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable Migration/UpdateLargeTable
-class AddPrintingMergeRequestLinkEnabledToProject < ActiveRecord::Migration
+class AddPrintingMergeRequestLinkEnabledToProject < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20170301195939_rename_ci_commits_to_ci_pipelines.rb b/db/migrate/20170301195939_rename_ci_commits_to_ci_pipelines.rb
index 4f061d96392..791e9c845a6 100644
--- a/db/migrate/20170301195939_rename_ci_commits_to_ci_pipelines.rb
+++ b/db/migrate/20170301195939_rename_ci_commits_to_ci_pipelines.rb
@@ -1,4 +1,4 @@
-class RenameCiCommitsToCiPipelines < ActiveRecord::Migration
+class RenameCiCommitsToCiPipelines < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20170301205639_remove_unused_ci_tables_and_columns.rb b/db/migrate/20170301205639_remove_unused_ci_tables_and_columns.rb
index ee802ab34ca..08a11aee992 100644
--- a/db/migrate/20170301205639_remove_unused_ci_tables_and_columns.rb
+++ b/db/migrate/20170301205639_remove_unused_ci_tables_and_columns.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/RemoveColumn
-class RemoveUnusedCiTablesAndColumns < ActiveRecord::Migration
+class RemoveUnusedCiTablesAndColumns < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/migrate/20170305180853_add_auto_cancel_pending_pipelines_to_project.rb b/db/migrate/20170305180853_add_auto_cancel_pending_pipelines_to_project.rb
index 3c5cd95726a..3e317bb5248 100644
--- a/db/migrate/20170305180853_add_auto_cancel_pending_pipelines_to_project.rb
+++ b/db/migrate/20170305180853_add_auto_cancel_pending_pipelines_to_project.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/UpdateLargeTable
-class AddAutoCancelPendingPipelinesToProject < ActiveRecord::Migration
+class AddAutoCancelPendingPipelinesToProject < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170305203726_add_owner_id_foreign_key.rb b/db/migrate/20170305203726_add_owner_id_foreign_key.rb
index 5fbdc45f1a7..b3bd441ff9c 100644
--- a/db/migrate/20170305203726_add_owner_id_foreign_key.rb
+++ b/db/migrate/20170305203726_add_owner_id_foreign_key.rb
@@ -1,4 +1,4 @@
-class AddOwnerIdForeignKey < ActiveRecord::Migration
+class AddOwnerIdForeignKey < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170307125949_add_last_activity_on_to_users.rb b/db/migrate/20170307125949_add_last_activity_on_to_users.rb
index 0100836b473..42331eab753 100644
--- a/db/migrate/20170307125949_add_last_activity_on_to_users.rb
+++ b/db/migrate/20170307125949_add_last_activity_on_to_users.rb
@@ -1,4 +1,4 @@
-class AddLastActivityOnToUsers < ActiveRecord::Migration
+class AddLastActivityOnToUsers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170309173138_create_protected_tags.rb b/db/migrate/20170309173138_create_protected_tags.rb
index 4684c9964c4..f518b500bd4 100644
--- a/db/migrate/20170309173138_create_protected_tags.rb
+++ b/db/migrate/20170309173138_create_protected_tags.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Timestamps
-class CreateProtectedTags < ActiveRecord::Migration
+class CreateProtectedTags < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170312114329_add_auto_canceled_by_id_to_pipeline.rb b/db/migrate/20170312114329_add_auto_canceled_by_id_to_pipeline.rb
index 1690ce90564..26187a9e8b3 100644
--- a/db/migrate/20170312114329_add_auto_canceled_by_id_to_pipeline.rb
+++ b/db/migrate/20170312114329_add_auto_canceled_by_id_to_pipeline.rb
@@ -1,4 +1,4 @@
-class AddAutoCanceledByIdToPipeline < ActiveRecord::Migration
+class AddAutoCanceledByIdToPipeline < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170312114529_add_auto_canceled_by_id_foreign_key_to_pipeline.rb b/db/migrate/20170312114529_add_auto_canceled_by_id_foreign_key_to_pipeline.rb
index 1e7b02ecf0e..a2b5c1c4533 100644
--- a/db/migrate/20170312114529_add_auto_canceled_by_id_foreign_key_to_pipeline.rb
+++ b/db/migrate/20170312114529_add_auto_canceled_by_id_foreign_key_to_pipeline.rb
@@ -1,4 +1,4 @@
-class AddAutoCanceledByIdForeignKeyToPipeline < ActiveRecord::Migration
+class AddAutoCanceledByIdForeignKeyToPipeline < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170313213916_add_index_to_user_ghost.rb b/db/migrate/20170313213916_add_index_to_user_ghost.rb
index fe5847ed225..66e57b444a0 100644
--- a/db/migrate/20170313213916_add_index_to_user_ghost.rb
+++ b/db/migrate/20170313213916_add_index_to_user_ghost.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# rubocop:disable RemoveIndex
-class AddIndexToUserGhost < ActiveRecord::Migration
+class AddIndexToUserGhost < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170314082049_create_system_note_metadata.rb b/db/migrate/20170314082049_create_system_note_metadata.rb
index fee47e96053..d0cc6e3be36 100644
--- a/db/migrate/20170314082049_create_system_note_metadata.rb
+++ b/db/migrate/20170314082049_create_system_note_metadata.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Timestamps
-class CreateSystemNoteMetadata < ActiveRecord::Migration
+class CreateSystemNoteMetadata < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170315174634_revert_add_notified_of_own_activity_to_users.rb b/db/migrate/20170315174634_revert_add_notified_of_own_activity_to_users.rb
index 9b9098d115d..8773c7ea657 100644
--- a/db/migrate/20170315174634_revert_add_notified_of_own_activity_to_users.rb
+++ b/db/migrate/20170315174634_revert_add_notified_of_own_activity_to_users.rb
@@ -1,6 +1,6 @@
# rubocop:disable Migration/RemoveColumn
# rubocop:disable Migration/UpdateLargeTable
-class RevertAddNotifiedOfOwnActivityToUsers < ActiveRecord::Migration
+class RevertAddNotifiedOfOwnActivityToUsers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20170315194013_add_closed_at_to_issues.rb b/db/migrate/20170315194013_add_closed_at_to_issues.rb
index 34a1bd7ca8c..0b06ee6e74c 100644
--- a/db/migrate/20170315194013_add_closed_at_to_issues.rb
+++ b/db/migrate/20170315194013_add_closed_at_to_issues.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Datetime
-class AddClosedAtToIssues < ActiveRecord::Migration
+class AddClosedAtToIssues < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20170316061730_readd_notified_of_own_activity_to_users.rb b/db/migrate/20170316061730_readd_notified_of_own_activity_to_users.rb
index 524eb2557ce..82029dfd3fc 100644
--- a/db/migrate/20170316061730_readd_notified_of_own_activity_to_users.rb
+++ b/db/migrate/20170316061730_readd_notified_of_own_activity_to_users.rb
@@ -1,4 +1,4 @@
-class ReaddNotifiedOfOwnActivityToUsers < ActiveRecord::Migration
+class ReaddNotifiedOfOwnActivityToUsers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20170316163845_move_uploads_to_system_dir.rb b/db/migrate/20170316163845_move_uploads_to_system_dir.rb
index cfcb909ddaf..d24527b55cd 100644
--- a/db/migrate/20170316163845_move_uploads_to_system_dir.rb
+++ b/db/migrate/20170316163845_move_uploads_to_system_dir.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MoveUploadsToSystemDir < ActiveRecord::Migration
+class MoveUploadsToSystemDir < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20170317203554_index_routes_path_for_like.rb b/db/migrate/20170317203554_index_routes_path_for_like.rb
index 8d3609135d0..a1bee3c8783 100644
--- a/db/migrate/20170317203554_index_routes_path_for_like.rb
+++ b/db/migrate/20170317203554_index_routes_path_for_like.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class IndexRoutesPathForLike < ActiveRecord::Migration
+class IndexRoutesPathForLike < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170320173259_migrate_assignees.rb b/db/migrate/20170320173259_migrate_assignees.rb
index 255b5e9c4db..43a90758bd9 100644
--- a/db/migrate/20170320173259_migrate_assignees.rb
+++ b/db/migrate/20170320173259_migrate_assignees.rb
@@ -1,6 +1,6 @@
# rubocop:disable Migration/UpdateLargeTable
# rubocop:disable Migration/UpdateColumnInBatches
-class MigrateAssignees < ActiveRecord::Migration
+class MigrateAssignees < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170322013926_create_container_repository.rb b/db/migrate/20170322013926_create_container_repository.rb
index 242f7b8d17d..b1e778671b2 100644
--- a/db/migrate/20170322013926_create_container_repository.rb
+++ b/db/migrate/20170322013926_create_container_repository.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Timestamps
-class CreateContainerRepository < ActiveRecord::Migration
+class CreateContainerRepository < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170327091750_add_created_at_index_to_deployments.rb b/db/migrate/20170327091750_add_created_at_index_to_deployments.rb
index fd6ed499b80..f29fff7d5b9 100644
--- a/db/migrate/20170327091750_add_created_at_index_to_deployments.rb
+++ b/db/migrate/20170327091750_add_created_at_index_to_deployments.rb
@@ -1,4 +1,4 @@
-class AddCreatedAtIndexToDeployments < ActiveRecord::Migration
+class AddCreatedAtIndexToDeployments < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170328010804_add_uuid_to_application_settings.rb b/db/migrate/20170328010804_add_uuid_to_application_settings.rb
index 5dfcc751c7b..95a01c2dc8f 100644
--- a/db/migrate/20170328010804_add_uuid_to_application_settings.rb
+++ b/db/migrate/20170328010804_add_uuid_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddUuidToApplicationSettings < ActiveRecord::Migration
+class AddUuidToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170329095325_add_ref_to_triggers.rb b/db/migrate/20170329095325_add_ref_to_triggers.rb
index 4aa52dd8f8f..db09b36db17 100644
--- a/db/migrate/20170329095325_add_ref_to_triggers.rb
+++ b/db/migrate/20170329095325_add_ref_to_triggers.rb
@@ -1,4 +1,4 @@
-class AddRefToTriggers < ActiveRecord::Migration
+class AddRefToTriggers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170329095907_create_ci_trigger_schedules.rb b/db/migrate/20170329095907_create_ci_trigger_schedules.rb
index cfcfa27ebb5..7f759f908cd 100644
--- a/db/migrate/20170329095907_create_ci_trigger_schedules.rb
+++ b/db/migrate/20170329095907_create_ci_trigger_schedules.rb
@@ -1,4 +1,4 @@
-class CreateCiTriggerSchedules < ActiveRecord::Migration
+class CreateCiTriggerSchedules < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170329124448_add_polling_interval_multiplier_to_application_settings.rb b/db/migrate/20170329124448_add_polling_interval_multiplier_to_application_settings.rb
index a8affd19a0b..17307879a2a 100644
--- a/db/migrate/20170329124448_add_polling_interval_multiplier_to_application_settings.rb
+++ b/db/migrate/20170329124448_add_polling_interval_multiplier_to_application_settings.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddPollingIntervalMultiplierToApplicationSettings < ActiveRecord::Migration
+class AddPollingIntervalMultiplierToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170330141723_disable_invalid_service_templates2.rb b/db/migrate/20170330141723_disable_invalid_service_templates2.rb
index 8424e56d8a1..91ec19dfa87 100644
--- a/db/migrate/20170330141723_disable_invalid_service_templates2.rb
+++ b/db/migrate/20170330141723_disable_invalid_service_templates2.rb
@@ -1,7 +1,7 @@
# This is the same as DisableInvalidServiceTemplates. Later migrations may have
# inadventently enabled some invalid templates again.
#
-class DisableInvalidServiceTemplates2 < ActiveRecord::Migration
+class DisableInvalidServiceTemplates2 < ActiveRecord::Migration[4.2]
DOWNTIME = false
unless defined?(Service)
diff --git a/db/migrate/20170402231018_remove_index_for_users_current_sign_in_at.rb b/db/migrate/20170402231018_remove_index_for_users_current_sign_in_at.rb
index 42c90103262..4c417ce2f71 100644
--- a/db/migrate/20170402231018_remove_index_for_users_current_sign_in_at.rb
+++ b/db/migrate/20170402231018_remove_index_for_users_current_sign_in_at.rb
@@ -1,6 +1,6 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveIndexForUsersCurrentSignInAt < ActiveRecord::Migration
+class RemoveIndexForUsersCurrentSignInAt < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170404163427_add_trigger_id_foreign_key.rb b/db/migrate/20170404163427_add_trigger_id_foreign_key.rb
index 6679a95ca11..f35730c8e45 100644
--- a/db/migrate/20170404163427_add_trigger_id_foreign_key.rb
+++ b/db/migrate/20170404163427_add_trigger_id_foreign_key.rb
@@ -1,4 +1,4 @@
-class AddTriggerIdForeignKey < ActiveRecord::Migration
+class AddTriggerIdForeignKey < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170405080720_add_import_jid_to_projects.rb b/db/migrate/20170405080720_add_import_jid_to_projects.rb
index 55b87b9d56d..ddbea9d7ab6 100644
--- a/db/migrate/20170405080720_add_import_jid_to_projects.rb
+++ b/db/migrate/20170405080720_add_import_jid_to_projects.rb
@@ -1,4 +1,4 @@
-class AddImportJidToProjects < ActiveRecord::Migration
+class AddImportJidToProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170406114958_add_auto_canceled_by_id_to_ci_builds.rb b/db/migrate/20170406114958_add_auto_canceled_by_id_to_ci_builds.rb
index c1d803b4308..ba43a070587 100644
--- a/db/migrate/20170406114958_add_auto_canceled_by_id_to_ci_builds.rb
+++ b/db/migrate/20170406114958_add_auto_canceled_by_id_to_ci_builds.rb
@@ -1,4 +1,4 @@
-class AddAutoCanceledByIdToCiBuilds < ActiveRecord::Migration
+class AddAutoCanceledByIdToCiBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170406115029_add_auto_canceled_by_id_foreign_key_to_ci_builds.rb b/db/migrate/20170406115029_add_auto_canceled_by_id_foreign_key_to_ci_builds.rb
index 3004683933b..2ec281e20c1 100644
--- a/db/migrate/20170406115029_add_auto_canceled_by_id_foreign_key_to_ci_builds.rb
+++ b/db/migrate/20170406115029_add_auto_canceled_by_id_foreign_key_to_ci_builds.rb
@@ -1,4 +1,4 @@
-class AddAutoCanceledByIdForeignKeyToCiBuilds < ActiveRecord::Migration
+class AddAutoCanceledByIdForeignKeyToCiBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170407114956_add_ref_to_ci_trigger_schedule.rb b/db/migrate/20170407114956_add_ref_to_ci_trigger_schedule.rb
index 523a306f127..5d156b7ef2e 100644
--- a/db/migrate/20170407114956_add_ref_to_ci_trigger_schedule.rb
+++ b/db/migrate/20170407114956_add_ref_to_ci_trigger_schedule.rb
@@ -1,4 +1,4 @@
-class AddRefToCiTriggerSchedule < ActiveRecord::Migration
+class AddRefToCiTriggerSchedule < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170407122426_add_active_to_ci_trigger_schedule.rb b/db/migrate/20170407122426_add_active_to_ci_trigger_schedule.rb
index 36892118ac0..33295bd3f2e 100644
--- a/db/migrate/20170407122426_add_active_to_ci_trigger_schedule.rb
+++ b/db/migrate/20170407122426_add_active_to_ci_trigger_schedule.rb
@@ -1,4 +1,4 @@
-class AddActiveToCiTriggerSchedule < ActiveRecord::Migration
+class AddActiveToCiTriggerSchedule < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170407135259_add_foreigh_key_trigger_requests_trigger.rb b/db/migrate/20170407135259_add_foreigh_key_trigger_requests_trigger.rb
index 81761c65a9f..9aaa4d0eddf 100644
--- a/db/migrate/20170407135259_add_foreigh_key_trigger_requests_trigger.rb
+++ b/db/migrate/20170407135259_add_foreigh_key_trigger_requests_trigger.rb
@@ -1,4 +1,4 @@
-class AddForeighKeyTriggerRequestsTrigger < ActiveRecord::Migration
+class AddForeighKeyTriggerRequestsTrigger < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170407140450_add_index_to_next_run_at_and_active.rb b/db/migrate/20170407140450_add_index_to_next_run_at_and_active.rb
index 626c2a67fdc..0bde4f69b3b 100644
--- a/db/migrate/20170407140450_add_index_to_next_run_at_and_active.rb
+++ b/db/migrate/20170407140450_add_index_to_next_run_at_and_active.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddIndexToNextRunAtAndActive < ActiveRecord::Migration
+class AddIndexToNextRunAtAndActive < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170410133135_add_version_field_to_markdown_cache.rb b/db/migrate/20170410133135_add_version_field_to_markdown_cache.rb
index d9209fe5770..c019e0627d3 100644
--- a/db/migrate/20170410133135_add_version_field_to_markdown_cache.rb
+++ b/db/migrate/20170410133135_add_version_field_to_markdown_cache.rb
@@ -1,4 +1,4 @@
-class AddVersionFieldToMarkdownCache < ActiveRecord::Migration
+class AddVersionFieldToMarkdownCache < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170413035209_add_preferred_language_to_users.rb b/db/migrate/20170413035209_add_preferred_language_to_users.rb
index 92f1d6f2436..5b5f00ea60f 100644
--- a/db/migrate/20170413035209_add_preferred_language_to_users.rb
+++ b/db/migrate/20170413035209_add_preferred_language_to_users.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddPreferredLanguageToUsers < ActiveRecord::Migration
+class AddPreferredLanguageToUsers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170418103908_delete_orphan_notification_settings.rb b/db/migrate/20170418103908_delete_orphan_notification_settings.rb
index e4b9cf65936..c99729b9127 100644
--- a/db/migrate/20170418103908_delete_orphan_notification_settings.rb
+++ b/db/migrate/20170418103908_delete_orphan_notification_settings.rb
@@ -1,4 +1,4 @@
-class DeleteOrphanNotificationSettings < ActiveRecord::Migration
+class DeleteOrphanNotificationSettings < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20170419001229_add_index_to_system_note_metadata.rb b/db/migrate/20170419001229_add_index_to_system_note_metadata.rb
index c68fd920fff..59cd55395fc 100644
--- a/db/migrate/20170419001229_add_index_to_system_note_metadata.rb
+++ b/db/migrate/20170419001229_add_index_to_system_note_metadata.rb
@@ -1,4 +1,4 @@
-class AddIndexToSystemNoteMetadata < ActiveRecord::Migration
+class AddIndexToSystemNoteMetadata < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170421102337_remove_nil_type_services.rb b/db/migrate/20170421102337_remove_nil_type_services.rb
index b835b9c6ed9..561eddf69e0 100644
--- a/db/migrate/20170421102337_remove_nil_type_services.rb
+++ b/db/migrate/20170421102337_remove_nil_type_services.rb
@@ -1,4 +1,4 @@
-class RemoveNilTypeServices < ActiveRecord::Migration
+class RemoveNilTypeServices < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20170423064036_add_index_on_ci_builds_updated_at.rb b/db/migrate/20170423064036_add_index_on_ci_builds_updated_at.rb
index 0bbb74ee05e..76252378c2e 100644
--- a/db/migrate/20170423064036_add_index_on_ci_builds_updated_at.rb
+++ b/db/migrate/20170423064036_add_index_on_ci_builds_updated_at.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddIndexOnCiBuildsUpdatedAt < ActiveRecord::Migration
+class AddIndexOnCiBuildsUpdatedAt < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170424095707_add_index_on_ci_builds_user_id.rb b/db/migrate/20170424095707_add_index_on_ci_builds_user_id.rb
index 348d5dbc270..ab2501da941 100644
--- a/db/migrate/20170424095707_add_index_on_ci_builds_user_id.rb
+++ b/db/migrate/20170424095707_add_index_on_ci_builds_user_id.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddIndexOnCiBuildsUserId < ActiveRecord::Migration
+class AddIndexOnCiBuildsUserId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170424142900_add_index_to_web_hooks_type.rb b/db/migrate/20170424142900_add_index_to_web_hooks_type.rb
index 9af158e3844..1c56c1ed65a 100644
--- a/db/migrate/20170424142900_add_index_to_web_hooks_type.rb
+++ b/db/migrate/20170424142900_add_index_to_web_hooks_type.rb
@@ -1,4 +1,4 @@
-class AddIndexToWebHooksType < ActiveRecord::Migration
+class AddIndexToWebHooksType < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170425112128_create_pipeline_schedules_table.rb b/db/migrate/20170425112128_create_pipeline_schedules_table.rb
index bd15b9eef19..e66e81b34be 100644
--- a/db/migrate/20170425112128_create_pipeline_schedules_table.rb
+++ b/db/migrate/20170425112128_create_pipeline_schedules_table.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Timestamps
-class CreatePipelineSchedulesTable < ActiveRecord::Migration
+class CreatePipelineSchedulesTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170425112628_remove_foreigh_key_ci_trigger_schedules.rb b/db/migrate/20170425112628_remove_foreigh_key_ci_trigger_schedules.rb
index 1587eee06ae..d89c4c61cbe 100644
--- a/db/migrate/20170425112628_remove_foreigh_key_ci_trigger_schedules.rb
+++ b/db/migrate/20170425112628_remove_foreigh_key_ci_trigger_schedules.rb
@@ -1,4 +1,4 @@
-class RemoveForeighKeyCiTriggerSchedules < ActiveRecord::Migration
+class RemoveForeighKeyCiTriggerSchedules < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170425114731_add_pipeline_schedule_id_to_pipelines.rb b/db/migrate/20170425114731_add_pipeline_schedule_id_to_pipelines.rb
index ddb27d4dc81..da16d89febc 100644
--- a/db/migrate/20170425114731_add_pipeline_schedule_id_to_pipelines.rb
+++ b/db/migrate/20170425114731_add_pipeline_schedule_id_to_pipelines.rb
@@ -1,4 +1,4 @@
-class AddPipelineScheduleIdToPipelines < ActiveRecord::Migration
+class AddPipelineScheduleIdToPipelines < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170426175636_fill_missing_uuid_on_application_settings.rb b/db/migrate/20170426175636_fill_missing_uuid_on_application_settings.rb
index 58ad2c64075..eeeb216f32c 100644
--- a/db/migrate/20170426175636_fill_missing_uuid_on_application_settings.rb
+++ b/db/migrate/20170426175636_fill_missing_uuid_on_application_settings.rb
@@ -1,4 +1,4 @@
-class FillMissingUuidOnApplicationSettings < ActiveRecord::Migration
+class FillMissingUuidOnApplicationSettings < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20170426181740_add_index_on_ci_runners_contacted_at.rb b/db/migrate/20170426181740_add_index_on_ci_runners_contacted_at.rb
index 879825a1934..e14b2eb4c8a 100644
--- a/db/migrate/20170426181740_add_index_on_ci_runners_contacted_at.rb
+++ b/db/migrate/20170426181740_add_index_on_ci_runners_contacted_at.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddIndexOnCiRunnersContactedAt < ActiveRecord::Migration
+class AddIndexOnCiRunnersContactedAt < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170427103502_create_web_hook_logs.rb b/db/migrate/20170427103502_create_web_hook_logs.rb
index 3643c52180c..a7a061e7bae 100644
--- a/db/migrate/20170427103502_create_web_hook_logs.rb
+++ b/db/migrate/20170427103502_create_web_hook_logs.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class CreateWebHookLogs < ActiveRecord::Migration
+class CreateWebHookLogs < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20170427215854_create_redirect_routes.rb b/db/migrate/20170427215854_create_redirect_routes.rb
index 6db508e5db4..069c9b39d37 100644
--- a/db/migrate/20170427215854_create_redirect_routes.rb
+++ b/db/migrate/20170427215854_create_redirect_routes.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Timestamps
-class CreateRedirectRoutes < ActiveRecord::Migration
+class CreateRedirectRoutes < ActiveRecord::Migration[4.2]
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
diff --git a/db/migrate/20170428064307_add_column_delete_error_to_projects.rb b/db/migrate/20170428064307_add_column_delete_error_to_projects.rb
index 09f9d9b5b7a..bef0373309c 100644
--- a/db/migrate/20170428064307_add_column_delete_error_to_projects.rb
+++ b/db/migrate/20170428064307_add_column_delete_error_to_projects.rb
@@ -1,4 +1,4 @@
-class AddColumnDeleteErrorToProjects < ActiveRecord::Migration
+class AddColumnDeleteErrorToProjects < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20170502065653_make_auto_cancel_pending_pipelines_on_by_default.rb b/db/migrate/20170502065653_make_auto_cancel_pending_pipelines_on_by_default.rb
index 03bf626a08a..e51a790de4d 100644
--- a/db/migrate/20170502065653_make_auto_cancel_pending_pipelines_on_by_default.rb
+++ b/db/migrate/20170502065653_make_auto_cancel_pending_pipelines_on_by_default.rb
@@ -1,4 +1,4 @@
-class MakeAutoCancelPendingPipelinesOnByDefault < ActiveRecord::Migration
+class MakeAutoCancelPendingPipelinesOnByDefault < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170502135553_create_index_ci_pipelines_auto_canceled_by_id.rb b/db/migrate/20170502135553_create_index_ci_pipelines_auto_canceled_by_id.rb
index b64d7e0e3f6..7acae645c7b 100644
--- a/db/migrate/20170502135553_create_index_ci_pipelines_auto_canceled_by_id.rb
+++ b/db/migrate/20170502135553_create_index_ci_pipelines_auto_canceled_by_id.rb
@@ -1,4 +1,4 @@
-class CreateIndexCiPipelinesAutoCanceledById < ActiveRecord::Migration
+class CreateIndexCiPipelinesAutoCanceledById < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170502140503_create_index_ci_builds_auto_canceled_by_id.rb b/db/migrate/20170502140503_create_index_ci_builds_auto_canceled_by_id.rb
index 0a8d2c8ff61..f5148f6fdb8 100644
--- a/db/migrate/20170502140503_create_index_ci_builds_auto_canceled_by_id.rb
+++ b/db/migrate/20170502140503_create_index_ci_builds_auto_canceled_by_id.rb
@@ -1,4 +1,4 @@
-class CreateIndexCiBuildsAutoCanceledById < ActiveRecord::Migration
+class CreateIndexCiBuildsAutoCanceledById < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170503004125_add_last_repository_updated_at_to_projects.rb b/db/migrate/20170503004125_add_last_repository_updated_at_to_projects.rb
index 2ea49f62742..303250ff3b0 100644
--- a/db/migrate/20170503004125_add_last_repository_updated_at_to_projects.rb
+++ b/db/migrate/20170503004125_add_last_repository_updated_at_to_projects.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Datetime
-class AddLastRepositoryUpdatedAtToProjects < ActiveRecord::Migration
+class AddLastRepositoryUpdatedAtToProjects < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20170503004425_add_index_to_last_repository_updated_at_on_projects.rb b/db/migrate/20170503004425_add_index_to_last_repository_updated_at_on_projects.rb
index 6144d74745c..ae54cfb39f5 100644
--- a/db/migrate/20170503004425_add_index_to_last_repository_updated_at_on_projects.rb
+++ b/db/migrate/20170503004425_add_index_to_last_repository_updated_at_on_projects.rb
@@ -1,4 +1,4 @@
-class AddIndexToLastRepositoryUpdatedAtOnProjects < ActiveRecord::Migration
+class AddIndexToLastRepositoryUpdatedAtOnProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170503004426_add_retried_to_ci_build.rb b/db/migrate/20170503004426_add_retried_to_ci_build.rb
index 2851e3de473..ff2e0ba64c5 100644
--- a/db/migrate/20170503004426_add_retried_to_ci_build.rb
+++ b/db/migrate/20170503004426_add_retried_to_ci_build.rb
@@ -1,4 +1,4 @@
-class AddRetriedToCiBuild < ActiveRecord::Migration
+class AddRetriedToCiBuild < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170503021915_add_last_edited_at_and_last_edited_by_id_to_issues.rb b/db/migrate/20170503021915_add_last_edited_at_and_last_edited_by_id_to_issues.rb
index a5d1eca82bb..ef527bb8007 100644
--- a/db/migrate/20170503021915_add_last_edited_at_and_last_edited_by_id_to_issues.rb
+++ b/db/migrate/20170503021915_add_last_edited_at_and_last_edited_by_id_to_issues.rb
@@ -2,7 +2,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddLastEditedAtAndLastEditedByIdToIssues < ActiveRecord::Migration
+class AddLastEditedAtAndLastEditedByIdToIssues < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170503022548_add_last_edited_at_and_last_edited_by_id_to_merge_requests.rb b/db/migrate/20170503022548_add_last_edited_at_and_last_edited_by_id_to_merge_requests.rb
index 47ba6bde856..19b8a9d66e7 100644
--- a/db/migrate/20170503022548_add_last_edited_at_and_last_edited_by_id_to_merge_requests.rb
+++ b/db/migrate/20170503022548_add_last_edited_at_and_last_edited_by_id_to_merge_requests.rb
@@ -2,7 +2,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddLastEditedAtAndLastEditedByIdToMergeRequests < ActiveRecord::Migration
+class AddLastEditedAtAndLastEditedByIdToMergeRequests < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170503023315_add_repository_update_events_to_web_hooks.rb b/db/migrate/20170503023315_add_repository_update_events_to_web_hooks.rb
index 0faea87a962..4824c404ec7 100644
--- a/db/migrate/20170503023315_add_repository_update_events_to_web_hooks.rb
+++ b/db/migrate/20170503023315_add_repository_update_events_to_web_hooks.rb
@@ -1,4 +1,4 @@
-class AddRepositoryUpdateEventsToWebHooks < ActiveRecord::Migration
+class AddRepositoryUpdateEventsToWebHooks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170503114228_add_description_to_snippets.rb b/db/migrate/20170503114228_add_description_to_snippets.rb
index 3fc960b2da5..78151ed9ff6 100644
--- a/db/migrate/20170503114228_add_description_to_snippets.rb
+++ b/db/migrate/20170503114228_add_description_to_snippets.rb
@@ -1,4 +1,4 @@
-class AddDescriptionToSnippets < ActiveRecord::Migration
+class AddDescriptionToSnippets < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170503140201_reschedule_project_authorizations.rb b/db/migrate/20170503140201_reschedule_project_authorizations.rb
index fa45adadbae..aa940bed2d3 100644
--- a/db/migrate/20170503140201_reschedule_project_authorizations.rb
+++ b/db/migrate/20170503140201_reschedule_project_authorizations.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RescheduleProjectAuthorizations < ActiveRecord::Migration
+class RescheduleProjectAuthorizations < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170503140202_turn_nested_groups_into_regular_groups_for_mysql.rb b/db/migrate/20170503140202_turn_nested_groups_into_regular_groups_for_mysql.rb
index 33908ae1156..cfa63b65df4 100644
--- a/db/migrate/20170503140202_turn_nested_groups_into_regular_groups_for_mysql.rb
+++ b/db/migrate/20170503140202_turn_nested_groups_into_regular_groups_for_mysql.rb
@@ -5,7 +5,7 @@
# updating a namespace to also rename directories (uploads, GitLab pages, etc).
# The alternative is to copy hundreds of lines of code into this migration,
# adjust them where needed, etc; something which doesn't work well at all.
-class TurnNestedGroupsIntoRegularGroupsForMysql < ActiveRecord::Migration
+class TurnNestedGroupsIntoRegularGroupsForMysql < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170503184421_add_index_to_redirect_routes.rb b/db/migrate/20170503184421_add_index_to_redirect_routes.rb
index 9062cf19a73..6320d4bbc99 100644
--- a/db/migrate/20170503184421_add_index_to_redirect_routes.rb
+++ b/db/migrate/20170503184421_add_index_to_redirect_routes.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddIndexToRedirectRoutes < ActiveRecord::Migration
+class AddIndexToRedirectRoutes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170503185032_index_redirect_routes_path_for_like.rb b/db/migrate/20170503185032_index_redirect_routes_path_for_like.rb
index 8eb20faa03a..5d06fd0511c 100644
--- a/db/migrate/20170503185032_index_redirect_routes_path_for_like.rb
+++ b/db/migrate/20170503185032_index_redirect_routes_path_for_like.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class IndexRedirectRoutesPathForLike < ActiveRecord::Migration
+class IndexRedirectRoutesPathForLike < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170504102911_add_clientside_sentry_to_application_settings.rb b/db/migrate/20170504102911_add_clientside_sentry_to_application_settings.rb
index 141112f8b50..4659f694020 100644
--- a/db/migrate/20170504102911_add_clientside_sentry_to_application_settings.rb
+++ b/db/migrate/20170504102911_add_clientside_sentry_to_application_settings.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddClientsideSentryToApplicationSettings < ActiveRecord::Migration
+class AddClientsideSentryToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170504182103_add_index_project_group_links_group_id.rb b/db/migrate/20170504182103_add_index_project_group_links_group_id.rb
index 62bf641daa6..5b1c14e66dd 100644
--- a/db/migrate/20170504182103_add_index_project_group_links_group_id.rb
+++ b/db/migrate/20170504182103_add_index_project_group_links_group_id.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddIndexProjectGroupLinksGroupId < ActiveRecord::Migration
+class AddIndexProjectGroupLinksGroupId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170506085040_add_index_to_pipeline_pipeline_schedule_id.rb b/db/migrate/20170506085040_add_index_to_pipeline_pipeline_schedule_id.rb
index 08a7f3fc9ab..9d8cc8a83a2 100644
--- a/db/migrate/20170506085040_add_index_to_pipeline_pipeline_schedule_id.rb
+++ b/db/migrate/20170506085040_add_index_to_pipeline_pipeline_schedule_id.rb
@@ -1,4 +1,4 @@
-class AddIndexToPipelinePipelineScheduleId < ActiveRecord::Migration
+class AddIndexToPipelinePipelineScheduleId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170506091344_add_foreign_key_to_pipeline_schedules.rb b/db/migrate/20170506091344_add_foreign_key_to_pipeline_schedules.rb
index 7f2dba702af..244e41e2f07 100644
--- a/db/migrate/20170506091344_add_foreign_key_to_pipeline_schedules.rb
+++ b/db/migrate/20170506091344_add_foreign_key_to_pipeline_schedules.rb
@@ -1,4 +1,4 @@
-class AddForeignKeyToPipelineSchedules < ActiveRecord::Migration
+class AddForeignKeyToPipelineSchedules < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170506185517_add_foreign_key_pipeline_schedules_and_pipelines.rb b/db/migrate/20170506185517_add_foreign_key_pipeline_schedules_and_pipelines.rb
index 55bf40ba24d..50364cac259 100644
--- a/db/migrate/20170506185517_add_foreign_key_pipeline_schedules_and_pipelines.rb
+++ b/db/migrate/20170506185517_add_foreign_key_pipeline_schedules_and_pipelines.rb
@@ -1,4 +1,4 @@
-class AddForeignKeyPipelineSchedulesAndPipelines < ActiveRecord::Migration
+class AddForeignKeyPipelineSchedulesAndPipelines < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
@@ -13,7 +13,7 @@ class AddForeignKeyPipelineSchedulesAndPipelines < ActiveRecord::Migration
'SET NULL'
end
- add_concurrent_foreign_key :ci_pipelines, :ci_pipeline_schedules,
+ add_concurrent_foreign_key :ci_pipelines, :ci_pipeline_schedules,
column: :pipeline_schedule_id, on_delete: on_delete
end
diff --git a/db/migrate/20170507205316_add_head_pipeline_id_to_merge_requests.rb b/db/migrate/20170507205316_add_head_pipeline_id_to_merge_requests.rb
index 8fc6e380a77..adfe6559084 100644
--- a/db/migrate/20170507205316_add_head_pipeline_id_to_merge_requests.rb
+++ b/db/migrate/20170507205316_add_head_pipeline_id_to_merge_requests.rb
@@ -1,4 +1,4 @@
-class AddHeadPipelineIdToMergeRequests < ActiveRecord::Migration
+class AddHeadPipelineIdToMergeRequests < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20170508153950_add_not_null_contraints_to_ci_variables.rb b/db/migrate/20170508153950_add_not_null_contraints_to_ci_variables.rb
index 41c687a4f6e..2a0c7132bfd 100644
--- a/db/migrate/20170508153950_add_not_null_contraints_to_ci_variables.rb
+++ b/db/migrate/20170508153950_add_not_null_contraints_to_ci_variables.rb
@@ -1,4 +1,4 @@
-class AddNotNullContraintsToCiVariables < ActiveRecord::Migration
+class AddNotNullContraintsToCiVariables < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20170508190732_add_foreign_key_to_ci_variables.rb b/db/migrate/20170508190732_add_foreign_key_to_ci_variables.rb
index 20ecaa2c36c..305366b2171 100644
--- a/db/migrate/20170508190732_add_foreign_key_to_ci_variables.rb
+++ b/db/migrate/20170508190732_add_foreign_key_to_ci_variables.rb
@@ -1,4 +1,4 @@
-class AddForeignKeyToCiVariables < ActiveRecord::Migration
+class AddForeignKeyToCiVariables < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170511082759_rename_web_hooks_build_events_to_job_events.rb b/db/migrate/20170511082759_rename_web_hooks_build_events_to_job_events.rb
index a2320a911b7..3a44057d948 100644
--- a/db/migrate/20170511082759_rename_web_hooks_build_events_to_job_events.rb
+++ b/db/migrate/20170511082759_rename_web_hooks_build_events_to_job_events.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RenameWebHooksBuildEventsToJobEvents < ActiveRecord::Migration
+class RenameWebHooksBuildEventsToJobEvents < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170511083824_rename_services_build_events_to_job_events.rb b/db/migrate/20170511083824_rename_services_build_events_to_job_events.rb
index 303d47078e7..713adde76ef 100644
--- a/db/migrate/20170511083824_rename_services_build_events_to_job_events.rb
+++ b/db/migrate/20170511083824_rename_services_build_events_to_job_events.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RenameServicesBuildEventsToJobEvents < ActiveRecord::Migration
+class RenameServicesBuildEventsToJobEvents < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170516153305_migrate_assignee_to_separate_table.rb b/db/migrate/20170516153305_migrate_assignee_to_separate_table.rb
index eed9f00d8b2..0ed45775421 100644
--- a/db/migrate/20170516153305_migrate_assignee_to_separate_table.rb
+++ b/db/migrate/20170516153305_migrate_assignee_to_separate_table.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MigrateAssigneeToSeparateTable < ActiveRecord::Migration
+class MigrateAssigneeToSeparateTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170516183131_add_indices_to_issue_assignees.rb b/db/migrate/20170516183131_add_indices_to_issue_assignees.rb
index a1f064c6848..6877fe9ff98 100644
--- a/db/migrate/20170516183131_add_indices_to_issue_assignees.rb
+++ b/db/migrate/20170516183131_add_indices_to_issue_assignees.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddIndicesToIssueAssignees < ActiveRecord::Migration
+class AddIndicesToIssueAssignees < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170519102115_add_prometheus_settings_to_metrics_settings.rb b/db/migrate/20170519102115_add_prometheus_settings_to_metrics_settings.rb
index 6ec2ed712b9..9c8f58104bd 100644
--- a/db/migrate/20170519102115_add_prometheus_settings_to_metrics_settings.rb
+++ b/db/migrate/20170519102115_add_prometheus_settings_to_metrics_settings.rb
@@ -1,4 +1,4 @@
-class AddPrometheusSettingsToMetricsSettings < ActiveRecord::Migration
+class AddPrometheusSettingsToMetricsSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20170521184006_add_change_position_to_notes.rb b/db/migrate/20170521184006_add_change_position_to_notes.rb
index 219ed1ade4c..f0ca3a2a9ea 100644
--- a/db/migrate/20170521184006_add_change_position_to_notes.rb
+++ b/db/migrate/20170521184006_add_change_position_to_notes.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddChangePositionToNotes < ActiveRecord::Migration
+class AddChangePositionToNotes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170523091700_add_rss_token_to_users.rb b/db/migrate/20170523091700_add_rss_token_to_users.rb
index 06a85f6ac3d..e1bcd9b3fee 100644
--- a/db/migrate/20170523091700_add_rss_token_to_users.rb
+++ b/db/migrate/20170523091700_add_rss_token_to_users.rb
@@ -1,4 +1,4 @@
-class AddRssTokenToUsers < ActiveRecord::Migration
+class AddRssTokenToUsers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170523121229_create_conversational_development_index_metrics.rb b/db/migrate/20170523121229_create_conversational_development_index_metrics.rb
index 7026a867ae1..5f8c0d07e3c 100644
--- a/db/migrate/20170523121229_create_conversational_development_index_metrics.rb
+++ b/db/migrate/20170523121229_create_conversational_development_index_metrics.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Timestamps
-class CreateConversationalDevelopmentIndexMetrics < ActiveRecord::Migration
+class CreateConversationalDevelopmentIndexMetrics < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20170524125940_add_source_to_ci_pipeline.rb b/db/migrate/20170524125940_add_source_to_ci_pipeline.rb
index 1fa3d48037b..81358e7ce3d 100644
--- a/db/migrate/20170524125940_add_source_to_ci_pipeline.rb
+++ b/db/migrate/20170524125940_add_source_to_ci_pipeline.rb
@@ -1,4 +1,4 @@
-class AddSourceToCiPipeline < ActiveRecord::Migration
+class AddSourceToCiPipeline < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170524161101_add_protected_to_ci_variables.rb b/db/migrate/20170524161101_add_protected_to_ci_variables.rb
index 99d4861e889..6125ea5d5a8 100644
--- a/db/migrate/20170524161101_add_protected_to_ci_variables.rb
+++ b/db/migrate/20170524161101_add_protected_to_ci_variables.rb
@@ -1,4 +1,4 @@
-class AddProtectedToCiVariables < ActiveRecord::Migration
+class AddProtectedToCiVariables < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170525130346_create_group_variables_table.rb b/db/migrate/20170525130346_create_group_variables_table.rb
index eaa38dbc40d..6eae7eff7bd 100644
--- a/db/migrate/20170525130346_create_group_variables_table.rb
+++ b/db/migrate/20170525130346_create_group_variables_table.rb
@@ -1,4 +1,4 @@
-class CreateGroupVariablesTable < ActiveRecord::Migration
+class CreateGroupVariablesTable < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20170525130758_add_foreign_key_to_group_variables.rb b/db/migrate/20170525130758_add_foreign_key_to_group_variables.rb
index 0146235c5ba..f1f51a1dda3 100644
--- a/db/migrate/20170525130758_add_foreign_key_to_group_variables.rb
+++ b/db/migrate/20170525130758_add_foreign_key_to_group_variables.rb
@@ -1,4 +1,4 @@
-class AddForeignKeyToGroupVariables < ActiveRecord::Migration
+class AddForeignKeyToGroupVariables < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170525132202_create_pipeline_stages.rb b/db/migrate/20170525132202_create_pipeline_stages.rb
index 825993aa41e..0a6400fde90 100644
--- a/db/migrate/20170525132202_create_pipeline_stages.rb
+++ b/db/migrate/20170525132202_create_pipeline_stages.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/Timestamps
-class CreatePipelineStages < ActiveRecord::Migration
+class CreatePipelineStages < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170525174156_create_feature_tables.rb b/db/migrate/20170525174156_create_feature_tables.rb
index a083c89c85f..e1eaaff8d35 100644
--- a/db/migrate/20170525174156_create_feature_tables.rb
+++ b/db/migrate/20170525174156_create_feature_tables.rb
@@ -1,4 +1,4 @@
-class CreateFeatureTables < ActiveRecord::Migration
+class CreateFeatureTables < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170526185602_add_stage_id_to_ci_builds.rb b/db/migrate/20170526185602_add_stage_id_to_ci_builds.rb
index d27cba76d81..6958557d118 100644
--- a/db/migrate/20170526185602_add_stage_id_to_ci_builds.rb
+++ b/db/migrate/20170526185602_add_stage_id_to_ci_builds.rb
@@ -1,4 +1,4 @@
-class AddStageIdToCiBuilds < ActiveRecord::Migration
+class AddStageIdToCiBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170530130129_project_foreign_keys_with_cascading_deletes.rb b/db/migrate/20170530130129_project_foreign_keys_with_cascading_deletes.rb
index 12352d98a62..d40c61f24b1 100644
--- a/db/migrate/20170530130129_project_foreign_keys_with_cascading_deletes.rb
+++ b/db/migrate/20170530130129_project_foreign_keys_with_cascading_deletes.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class ProjectForeignKeysWithCascadingDeletes < ActiveRecord::Migration
+class ProjectForeignKeysWithCascadingDeletes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170531180233_add_authorized_keys_enabled_to_application_settings.rb b/db/migrate/20170531180233_add_authorized_keys_enabled_to_application_settings.rb
index 1d86a531eb3..f440609ff8a 100644
--- a/db/migrate/20170531180233_add_authorized_keys_enabled_to_application_settings.rb
+++ b/db/migrate/20170531180233_add_authorized_keys_enabled_to_application_settings.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddAuthorizedKeysEnabledToApplicationSettings < ActiveRecord::Migration
+class AddAuthorizedKeysEnabledToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170531202042_rename_users_ldap_email_to_external_email.rb b/db/migrate/20170531202042_rename_users_ldap_email_to_external_email.rb
index f858611d24b..7b1a7644555 100644
--- a/db/migrate/20170531202042_rename_users_ldap_email_to_external_email.rb
+++ b/db/migrate/20170531202042_rename_users_ldap_email_to_external_email.rb
@@ -1,4 +1,4 @@
-class RenameUsersLdapEmailToExternalEmail < ActiveRecord::Migration
+class RenameUsersLdapEmailToExternalEmail < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170601163708_add_artifacts_store_to_ci_build.rb b/db/migrate/20170601163708_add_artifacts_store_to_ci_build.rb
index e82109190a7..4c9ac821b20 100644
--- a/db/migrate/20170601163708_add_artifacts_store_to_ci_build.rb
+++ b/db/migrate/20170601163708_add_artifacts_store_to_ci_build.rb
@@ -1,4 +1,4 @@
-class AddArtifactsStoreToCiBuild < ActiveRecord::Migration
+class AddArtifactsStoreToCiBuild < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170602154736_add_help_page_hide_commercial_content_to_application_settings.rb b/db/migrate/20170602154736_add_help_page_hide_commercial_content_to_application_settings.rb
index d358020d182..ff9e188d7a8 100644
--- a/db/migrate/20170602154736_add_help_page_hide_commercial_content_to_application_settings.rb
+++ b/db/migrate/20170602154736_add_help_page_hide_commercial_content_to_application_settings.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/SaferBooleanColumn
-class AddHelpPageHideCommercialContentToApplicationSettings < ActiveRecord::Migration
+class AddHelpPageHideCommercialContentToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170602154813_add_help_page_support_url_to_application_settings.rb b/db/migrate/20170602154813_add_help_page_support_url_to_application_settings.rb
index 138fe9b2a37..388e130ab88 100644
--- a/db/migrate/20170602154813_add_help_page_support_url_to_application_settings.rb
+++ b/db/migrate/20170602154813_add_help_page_support_url_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddHelpPageSupportUrlToApplicationSettings < ActiveRecord::Migration
+class AddHelpPageSupportUrlToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170603200744_add_email_provider_to_users.rb b/db/migrate/20170603200744_add_email_provider_to_users.rb
index ed90af9aadc..ad6e813d31b 100644
--- a/db/migrate/20170603200744_add_email_provider_to_users.rb
+++ b/db/migrate/20170603200744_add_email_provider_to_users.rb
@@ -1,4 +1,4 @@
-class AddEmailProviderToUsers < ActiveRecord::Migration
+class AddEmailProviderToUsers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170606154216_add_notification_setting_columns.rb b/db/migrate/20170606154216_add_notification_setting_columns.rb
index 0a9b5da6583..3b9493e6b49 100644
--- a/db/migrate/20170606154216_add_notification_setting_columns.rb
+++ b/db/migrate/20170606154216_add_notification_setting_columns.rb
@@ -1,4 +1,4 @@
-class AddNotificationSettingColumns < ActiveRecord::Migration
+class AddNotificationSettingColumns < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170608152747_prepare_events_table_for_push_events_migration.rb b/db/migrate/20170608152747_prepare_events_table_for_push_events_migration.rb
index f4f03bbabaf..851af7f7bf6 100644
--- a/db/migrate/20170608152747_prepare_events_table_for_push_events_migration.rb
+++ b/db/migrate/20170608152747_prepare_events_table_for_push_events_migration.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class PrepareEventsTableForPushEventsMigration < ActiveRecord::Migration
+class PrepareEventsTableForPushEventsMigration < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170608152748_create_push_event_payloads_tables.rb b/db/migrate/20170608152748_create_push_event_payloads_tables.rb
index 6c55ad1f2f7..292d9e3ca06 100644
--- a/db/migrate/20170608152748_create_push_event_payloads_tables.rb
+++ b/db/migrate/20170608152748_create_push_event_payloads_tables.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class CreatePushEventPayloadsTables < ActiveRecord::Migration
+class CreatePushEventPayloadsTables < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170608171156_create_merge_request_diff_files.rb b/db/migrate/20170608171156_create_merge_request_diff_files.rb
index bf0c0d29adc..94b518455ee 100644
--- a/db/migrate/20170608171156_create_merge_request_diff_files.rb
+++ b/db/migrate/20170608171156_create_merge_request_diff_files.rb
@@ -1,4 +1,4 @@
-class CreateMergeRequestDiffFiles < ActiveRecord::Migration
+class CreateMergeRequestDiffFiles < ActiveRecord::Migration[4.2]
DOWNTIME = false
disable_ddl_transaction!
diff --git a/db/migrate/20170613154149_create_gpg_signatures.rb b/db/migrate/20170613154149_create_gpg_signatures.rb
index f6b5e7ebb7b..181d35fe7af 100644
--- a/db/migrate/20170613154149_create_gpg_signatures.rb
+++ b/db/migrate/20170613154149_create_gpg_signatures.rb
@@ -1,4 +1,6 @@
-class CreateGpgSignatures < ActiveRecord::Migration
+class CreateGpgSignatures < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
DOWNTIME = false
def change
@@ -16,8 +18,8 @@ class CreateGpgSignatures < ActiveRecord::Migration
t.text :gpg_key_user_name
t.text :gpg_key_user_email
- t.index :commit_sha, unique: true, length: Gitlab::Database.mysql? ? 20 : nil
- t.index :gpg_key_primary_keyid, length: Gitlab::Database.mysql? ? 20 : nil
+ t.index :commit_sha, unique: true, length: mysql_compatible_index_length
+ t.index :gpg_key_primary_keyid, length: mysql_compatible_index_length
end
end
end
diff --git a/db/migrate/20170616133147_create_merge_request_diff_commits.rb b/db/migrate/20170616133147_create_merge_request_diff_commits.rb
index 616464cb470..5e148affba2 100644
--- a/db/migrate/20170616133147_create_merge_request_diff_commits.rb
+++ b/db/migrate/20170616133147_create_merge_request_diff_commits.rb
@@ -1,4 +1,4 @@
-class CreateMergeRequestDiffCommits < ActiveRecord::Migration
+class CreateMergeRequestDiffCommits < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20170619144837_add_index_for_head_pipeline_merge_request.rb b/db/migrate/20170619144837_add_index_for_head_pipeline_merge_request.rb
index 02863bee082..f97c8a14b8d 100644
--- a/db/migrate/20170619144837_add_index_for_head_pipeline_merge_request.rb
+++ b/db/migrate/20170619144837_add_index_for_head_pipeline_merge_request.rb
@@ -1,4 +1,4 @@
-class AddIndexForHeadPipelineMergeRequest < ActiveRecord::Migration
+class AddIndexForHeadPipelineMergeRequest < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170620064728_create_ci_pipeline_schedule_variables.rb b/db/migrate/20170620064728_create_ci_pipeline_schedule_variables.rb
index 92833765a82..74f3603505b 100644
--- a/db/migrate/20170620064728_create_ci_pipeline_schedule_variables.rb
+++ b/db/migrate/20170620064728_create_ci_pipeline_schedule_variables.rb
@@ -1,4 +1,4 @@
-class CreateCiPipelineScheduleVariables < ActiveRecord::Migration
+class CreateCiPipelineScheduleVariables < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20170620065449_add_foreign_key_to_ci_pipeline_schedule_variables.rb b/db/migrate/20170620065449_add_foreign_key_to_ci_pipeline_schedule_variables.rb
index 7bbf66e0ac3..f6de19aeaf2 100644
--- a/db/migrate/20170620065449_add_foreign_key_to_ci_pipeline_schedule_variables.rb
+++ b/db/migrate/20170620065449_add_foreign_key_to_ci_pipeline_schedule_variables.rb
@@ -1,4 +1,4 @@
-class AddForeignKeyToCiPipelineScheduleVariables < ActiveRecord::Migration
+class AddForeignKeyToCiPipelineScheduleVariables < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170622130029_correct_protected_branches_foreign_keys.rb b/db/migrate/20170622130029_correct_protected_branches_foreign_keys.rb
index 46497775527..c4ba3ec2cc0 100644
--- a/db/migrate/20170622130029_correct_protected_branches_foreign_keys.rb
+++ b/db/migrate/20170622130029_correct_protected_branches_foreign_keys.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class CorrectProtectedBranchesForeignKeys < ActiveRecord::Migration
+class CorrectProtectedBranchesForeignKeys < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170622132212_add_foreign_key_for_merge_request_diffs.rb b/db/migrate/20170622132212_add_foreign_key_for_merge_request_diffs.rb
index 9f524fac8a7..b826f67ff39 100644
--- a/db/migrate/20170622132212_add_foreign_key_for_merge_request_diffs.rb
+++ b/db/migrate/20170622132212_add_foreign_key_for_merge_request_diffs.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddForeignKeyForMergeRequestDiffs < ActiveRecord::Migration
+class AddForeignKeyForMergeRequestDiffs < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170622135451_rename_duplicated_variable_key.rb b/db/migrate/20170622135451_rename_duplicated_variable_key.rb
index 368718ab0ce..06a9529ae79 100644
--- a/db/migrate/20170622135451_rename_duplicated_variable_key.rb
+++ b/db/migrate/20170622135451_rename_duplicated_variable_key.rb
@@ -1,4 +1,4 @@
-class RenameDuplicatedVariableKey < ActiveRecord::Migration
+class RenameDuplicatedVariableKey < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170622135628_add_environment_scope_to_ci_variables.rb b/db/migrate/20170622135628_add_environment_scope_to_ci_variables.rb
index 17fe062d8d5..8fbb2ab57d5 100644
--- a/db/migrate/20170622135628_add_environment_scope_to_ci_variables.rb
+++ b/db/migrate/20170622135628_add_environment_scope_to_ci_variables.rb
@@ -1,4 +1,4 @@
-class AddEnvironmentScopeToCiVariables < ActiveRecord::Migration
+class AddEnvironmentScopeToCiVariables < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170622135728_add_unique_constraint_to_ci_variables.rb b/db/migrate/20170622135728_add_unique_constraint_to_ci_variables.rb
index 787022b7bfe..240f55766d3 100644
--- a/db/migrate/20170622135728_add_unique_constraint_to_ci_variables.rb
+++ b/db/migrate/20170622135728_add_unique_constraint_to_ci_variables.rb
@@ -1,4 +1,4 @@
-class AddUniqueConstraintToCiVariables < ActiveRecord::Migration
+class AddUniqueConstraintToCiVariables < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170622162730_add_ref_fetched_to_merge_request.rb b/db/migrate/20170622162730_add_ref_fetched_to_merge_request.rb
index 62aa1a4b4f0..4715ff7a715 100644
--- a/db/migrate/20170622162730_add_ref_fetched_to_merge_request.rb
+++ b/db/migrate/20170622162730_add_ref_fetched_to_merge_request.rb
@@ -1,4 +1,4 @@
-class AddRefFetchedToMergeRequest < ActiveRecord::Migration
+class AddRefFetchedToMergeRequest < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170623080805_remove_ci_variables_project_id_index.rb b/db/migrate/20170623080805_remove_ci_variables_project_id_index.rb
index ddcc0292b9d..861dbd2ee14 100644
--- a/db/migrate/20170623080805_remove_ci_variables_project_id_index.rb
+++ b/db/migrate/20170623080805_remove_ci_variables_project_id_index.rb
@@ -1,4 +1,4 @@
-class RemoveCiVariablesProjectIdIndex < ActiveRecord::Migration
+class RemoveCiVariablesProjectIdIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170629171610_rename_application_settings_signin_enabled_to_password_authentication_enabled.rb b/db/migrate/20170629171610_rename_application_settings_signin_enabled_to_password_authentication_enabled.rb
index 858b3bebace..1651a47ebec 100644
--- a/db/migrate/20170629171610_rename_application_settings_signin_enabled_to_password_authentication_enabled.rb
+++ b/db/migrate/20170629171610_rename_application_settings_signin_enabled_to_password_authentication_enabled.rb
@@ -1,4 +1,4 @@
-class RenameApplicationSettingsSigninEnabledToPasswordAuthenticationEnabled < ActiveRecord::Migration
+class RenameApplicationSettingsSigninEnabledToPasswordAuthenticationEnabled < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170703102400_add_stage_id_foreign_key_to_builds.rb b/db/migrate/20170703102400_add_stage_id_foreign_key_to_builds.rb
index a89d348b127..36ac360fb0b 100644
--- a/db/migrate/20170703102400_add_stage_id_foreign_key_to_builds.rb
+++ b/db/migrate/20170703102400_add_stage_id_foreign_key_to_builds.rb
@@ -1,4 +1,4 @@
-class AddStageIdForeignKeyToBuilds < ActiveRecord::Migration
+class AddStageIdForeignKeyToBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170706151212_add_performance_bar_allowed_group_id_to_application_settings.rb b/db/migrate/20170706151212_add_performance_bar_allowed_group_id_to_application_settings.rb
index fe9970ddc71..61416f74b63 100644
--- a/db/migrate/20170706151212_add_performance_bar_allowed_group_id_to_application_settings.rb
+++ b/db/migrate/20170706151212_add_performance_bar_allowed_group_id_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddPerformanceBarAllowedGroupIdToApplicationSettings < ActiveRecord::Migration
+class AddPerformanceBarAllowedGroupIdToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170707183807_add_group_id_to_milestones.rb b/db/migrate/20170707183807_add_group_id_to_milestones.rb
index 675ffd4a1c9..e778a30192f 100644
--- a/db/migrate/20170707183807_add_group_id_to_milestones.rb
+++ b/db/migrate/20170707183807_add_group_id_to_milestones.rb
@@ -1,4 +1,4 @@
-class AddGroupIdToMilestones < ActiveRecord::Migration
+class AddGroupIdToMilestones < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20170707184243_add_group_milestone_id_indexes.rb b/db/migrate/20170707184243_add_group_milestone_id_indexes.rb
index aa48fe90cad..545ee070194 100644
--- a/db/migrate/20170707184243_add_group_milestone_id_indexes.rb
+++ b/db/migrate/20170707184243_add_group_milestone_id_indexes.rb
@@ -1,4 +1,4 @@
-class AddGroupMilestoneIdIndexes < ActiveRecord::Migration
+class AddGroupMilestoneIdIndexes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20170707184244_remove_wrong_versions_from_schema_versions.rb b/db/migrate/20170707184244_remove_wrong_versions_from_schema_versions.rb
index 38536a8b06a..f99206c7f78 100644
--- a/db/migrate/20170707184244_remove_wrong_versions_from_schema_versions.rb
+++ b/db/migrate/20170707184244_remove_wrong_versions_from_schema_versions.rb
@@ -1,4 +1,4 @@
-class RemoveWrongVersionsFromSchemaVersions < ActiveRecord::Migration
+class RemoveWrongVersionsFromSchemaVersions < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20170710083355_clean_stage_id_reference_migration.rb b/db/migrate/20170710083355_clean_stage_id_reference_migration.rb
index 681203eaf40..d33c6f53b15 100644
--- a/db/migrate/20170710083355_clean_stage_id_reference_migration.rb
+++ b/db/migrate/20170710083355_clean_stage_id_reference_migration.rb
@@ -1,4 +1,4 @@
-class CleanStageIdReferenceMigration < ActiveRecord::Migration
+class CleanStageIdReferenceMigration < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170711145320_add_status_to_ci_stages.rb b/db/migrate/20170711145320_add_status_to_ci_stages.rb
index d497a61a959..3ea7b750882 100644
--- a/db/migrate/20170711145320_add_status_to_ci_stages.rb
+++ b/db/migrate/20170711145320_add_status_to_ci_stages.rb
@@ -1,4 +1,4 @@
-class AddStatusToCiStages < ActiveRecord::Migration
+class AddStatusToCiStages < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170713104829_add_foreign_key_to_merge_requests.rb b/db/migrate/20170713104829_add_foreign_key_to_merge_requests.rb
index c409915ceed..908b122c659 100644
--- a/db/migrate/20170713104829_add_foreign_key_to_merge_requests.rb
+++ b/db/migrate/20170713104829_add_foreign_key_to_merge_requests.rb
@@ -1,4 +1,4 @@
-class AddForeignKeyToMergeRequests < ActiveRecord::Migration
+class AddForeignKeyToMergeRequests < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170717074009_move_system_upload_folder.rb b/db/migrate/20170717074009_move_system_upload_folder.rb
index d3caa53a7a4..6c57a751c8d 100644
--- a/db/migrate/20170717074009_move_system_upload_folder.rb
+++ b/db/migrate/20170717074009_move_system_upload_folder.rb
@@ -1,4 +1,4 @@
-class MoveSystemUploadFolder < ActiveRecord::Migration
+class MoveSystemUploadFolder < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20170717200542_add_trusted_column_to_oauth_applications.rb b/db/migrate/20170717200542_add_trusted_column_to_oauth_applications.rb
index 1a013e6aefb..d9ae86f6c52 100644
--- a/db/migrate/20170717200542_add_trusted_column_to_oauth_applications.rb
+++ b/db/migrate/20170717200542_add_trusted_column_to_oauth_applications.rb
@@ -1,4 +1,4 @@
-class AddTrustedColumnToOauthApplications < ActiveRecord::Migration
+class AddTrustedColumnToOauthApplications < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170720111708_add_lock_version_to_ci_stages.rb b/db/migrate/20170720111708_add_lock_version_to_ci_stages.rb
index e1c4f033286..a5caca7e80c 100644
--- a/db/migrate/20170720111708_add_lock_version_to_ci_stages.rb
+++ b/db/migrate/20170720111708_add_lock_version_to_ci_stages.rb
@@ -1,4 +1,4 @@
-class AddLockVersionToCiStages < ActiveRecord::Migration
+class AddLockVersionToCiStages < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170720122741_create_user_custom_attributes.rb b/db/migrate/20170720122741_create_user_custom_attributes.rb
index b1c0bebc633..0e6f37d7317 100644
--- a/db/migrate/20170720122741_create_user_custom_attributes.rb
+++ b/db/migrate/20170720122741_create_user_custom_attributes.rb
@@ -1,4 +1,4 @@
-class CreateUserCustomAttributes < ActiveRecord::Migration
+class CreateUserCustomAttributes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170720130522_create_ci_pipeline_variables.rb b/db/migrate/20170720130522_create_ci_pipeline_variables.rb
index a784f5dd142..4f162d46cf5 100644
--- a/db/migrate/20170720130522_create_ci_pipeline_variables.rb
+++ b/db/migrate/20170720130522_create_ci_pipeline_variables.rb
@@ -1,4 +1,4 @@
-class CreateCiPipelineVariables < ActiveRecord::Migration
+class CreateCiPipelineVariables < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20170720130749_add_foreign_key_to_ci_pipeline_variables.rb b/db/migrate/20170720130749_add_foreign_key_to_ci_pipeline_variables.rb
index 550b8a88f02..df9350d9ad5 100644
--- a/db/migrate/20170720130749_add_foreign_key_to_ci_pipeline_variables.rb
+++ b/db/migrate/20170720130749_add_foreign_key_to_ci_pipeline_variables.rb
@@ -1,4 +1,4 @@
-class AddForeignKeyToCiPipelineVariables < ActiveRecord::Migration
+class AddForeignKeyToCiPipelineVariables < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170724214302_add_lower_path_index_to_redirect_routes.rb b/db/migrate/20170724214302_add_lower_path_index_to_redirect_routes.rb
index a770ff63b4e..1a6516f8777 100644
--- a/db/migrate/20170724214302_add_lower_path_index_to_redirect_routes.rb
+++ b/db/migrate/20170724214302_add_lower_path_index_to_redirect_routes.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddLowerPathIndexToRedirectRoutes < ActiveRecord::Migration
+class AddLowerPathIndexToRedirectRoutes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170725145659_add_binary_to_merge_request_diff_files.rb b/db/migrate/20170725145659_add_binary_to_merge_request_diff_files.rb
index 1f5fa7e3d49..c7d377547e4 100644
--- a/db/migrate/20170725145659_add_binary_to_merge_request_diff_files.rb
+++ b/db/migrate/20170725145659_add_binary_to_merge_request_diff_files.rb
@@ -1,4 +1,4 @@
-class AddBinaryToMergeRequestDiffFiles < ActiveRecord::Migration
+class AddBinaryToMergeRequestDiffFiles < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170727123534_add_index_on_events_project_id_id.rb b/db/migrate/20170727123534_add_index_on_events_project_id_id.rb
index 1c4aaaf9dd6..076b8ee87b2 100644
--- a/db/migrate/20170727123534_add_index_on_events_project_id_id.rb
+++ b/db/migrate/20170727123534_add_index_on_events_project_id_id.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddIndexOnEventsProjectIdId < ActiveRecord::Migration
+class AddIndexOnEventsProjectIdId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170731175128_add_percentages_to_conv_dev.rb b/db/migrate/20170731175128_add_percentages_to_conv_dev.rb
index 1819bfc96bb..522e99c0751 100644
--- a/db/migrate/20170731175128_add_percentages_to_conv_dev.rb
+++ b/db/migrate/20170731175128_add_percentages_to_conv_dev.rb
@@ -1,4 +1,4 @@
-class AddPercentagesToConvDev < ActiveRecord::Migration
+class AddPercentagesToConvDev < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20170731183033_add_merge_jid_to_merge_requests.rb b/db/migrate/20170731183033_add_merge_jid_to_merge_requests.rb
index a7d8f2f3604..3c677f3bc2d 100644
--- a/db/migrate/20170731183033_add_merge_jid_to_merge_requests.rb
+++ b/db/migrate/20170731183033_add_merge_jid_to_merge_requests.rb
@@ -1,4 +1,4 @@
-class AddMergeJidToMergeRequests < ActiveRecord::Migration
+class AddMergeJidToMergeRequests < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20170802013652_add_storage_fields_to_project.rb b/db/migrate/20170802013652_add_storage_fields_to_project.rb
index c2381a9d0b2..d6672b9b3af 100644
--- a/db/migrate/20170802013652_add_storage_fields_to_project.rb
+++ b/db/migrate/20170802013652_add_storage_fields_to_project.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddStorageFieldsToProject < ActiveRecord::Migration
+class AddStorageFieldsToProject < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170803130232_reorganise_issues_indexes_for_faster_sorting.rb b/db/migrate/20170803130232_reorganise_issues_indexes_for_faster_sorting.rb
index eb7d1be1732..e92b5f28685 100644
--- a/db/migrate/20170803130232_reorganise_issues_indexes_for_faster_sorting.rb
+++ b/db/migrate/20170803130232_reorganise_issues_indexes_for_faster_sorting.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class ReorganiseIssuesIndexesForFasterSorting < ActiveRecord::Migration
+class ReorganiseIssuesIndexesForFasterSorting < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170807071105_add_hashed_storage_to_settings.rb b/db/migrate/20170807071105_add_hashed_storage_to_settings.rb
index 0846557add8..cfb89743127 100644
--- a/db/migrate/20170807071105_add_hashed_storage_to_settings.rb
+++ b/db/migrate/20170807071105_add_hashed_storage_to_settings.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddHashedStorageToSettings < ActiveRecord::Migration
+class AddHashedStorageToSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170809133343_add_broadcast_messages_index.rb b/db/migrate/20170809133343_add_broadcast_messages_index.rb
index 4ab2ddb059d..bcbc6c9f7d2 100644
--- a/db/migrate/20170809133343_add_broadcast_messages_index.rb
+++ b/db/migrate/20170809133343_add_broadcast_messages_index.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddBroadcastMessagesIndex < ActiveRecord::Migration
+class AddBroadcastMessagesIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170809134534_add_broadcast_message_not_null_constraints.rb b/db/migrate/20170809134534_add_broadcast_message_not_null_constraints.rb
index 5551fb51a6e..fd8cdbb95aa 100644
--- a/db/migrate/20170809134534_add_broadcast_message_not_null_constraints.rb
+++ b/db/migrate/20170809134534_add_broadcast_message_not_null_constraints.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddBroadcastMessageNotNullConstraints < ActiveRecord::Migration
+class AddBroadcastMessageNotNullConstraints < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170809142252_cleanup_appearances_schema.rb b/db/migrate/20170809142252_cleanup_appearances_schema.rb
index acf45060114..4c5d6a6d75d 100644
--- a/db/migrate/20170809142252_cleanup_appearances_schema.rb
+++ b/db/migrate/20170809142252_cleanup_appearances_schema.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class CleanupAppearancesSchema < ActiveRecord::Migration
+class CleanupAppearancesSchema < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170809161910_add_project_export_enabled_to_application_settings.rb b/db/migrate/20170809161910_add_project_export_enabled_to_application_settings.rb
index 4baba1ade6d..9dd520de264 100644
--- a/db/migrate/20170809161910_add_project_export_enabled_to_application_settings.rb
+++ b/db/migrate/20170809161910_add_project_export_enabled_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddProjectExportEnabledToApplicationSettings < ActiveRecord::Migration
+class AddProjectExportEnabledToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20170815221154_add_discussion_locked_to_issuable.rb b/db/migrate/20170815221154_add_discussion_locked_to_issuable.rb
index 5bd777c53a0..1444ca480b3 100644
--- a/db/migrate/20170815221154_add_discussion_locked_to_issuable.rb
+++ b/db/migrate/20170815221154_add_discussion_locked_to_issuable.rb
@@ -1,4 +1,4 @@
-class AddDiscussionLockedToIssuable < ActiveRecord::Migration
+class AddDiscussionLockedToIssuable < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20170816133938_add_access_level_to_ci_runners.rb b/db/migrate/20170816133938_add_access_level_to_ci_runners.rb
index fc484730f42..5a1ea9514d1 100644
--- a/db/migrate/20170816133938_add_access_level_to_ci_runners.rb
+++ b/db/migrate/20170816133938_add_access_level_to_ci_runners.rb
@@ -1,4 +1,4 @@
-class AddAccessLevelToCiRunners < ActiveRecord::Migration
+class AddAccessLevelToCiRunners < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170816133940_add_protected_to_ci_builds.rb b/db/migrate/20170816133940_add_protected_to_ci_builds.rb
index c73a4387d29..13e1be0d89c 100644
--- a/db/migrate/20170816133940_add_protected_to_ci_builds.rb
+++ b/db/migrate/20170816133940_add_protected_to_ci_builds.rb
@@ -1,4 +1,4 @@
-class AddProtectedToCiBuilds < ActiveRecord::Migration
+class AddProtectedToCiBuilds < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20170816143940_add_protected_to_ci_pipelines.rb b/db/migrate/20170816143940_add_protected_to_ci_pipelines.rb
index ce8f1e03686..aefaf4a487b 100644
--- a/db/migrate/20170816143940_add_protected_to_ci_pipelines.rb
+++ b/db/migrate/20170816143940_add_protected_to_ci_pipelines.rb
@@ -1,4 +1,4 @@
-class AddProtectedToCiPipelines < ActiveRecord::Migration
+class AddProtectedToCiPipelines < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20170816153940_add_index_on_ci_builds_protected.rb b/db/migrate/20170816153940_add_index_on_ci_builds_protected.rb
index caf7c705a6e..fbe5fe31ae8 100644
--- a/db/migrate/20170816153940_add_index_on_ci_builds_protected.rb
+++ b/db/migrate/20170816153940_add_index_on_ci_builds_protected.rb
@@ -1,4 +1,4 @@
-class AddIndexOnCiBuildsProtected < ActiveRecord::Migration
+class AddIndexOnCiBuildsProtected < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170816234252_add_theme_id_to_users.rb b/db/migrate/20170816234252_add_theme_id_to_users.rb
index 5043f9ec591..bd04445cac6 100644
--- a/db/migrate/20170816234252_add_theme_id_to_users.rb
+++ b/db/migrate/20170816234252_add_theme_id_to_users.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddThemeIdToUsers < ActiveRecord::Migration
+class AddThemeIdToUsers < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20170817123339_add_verification_status_to_gpg_signatures.rb b/db/migrate/20170817123339_add_verification_status_to_gpg_signatures.rb
index 128cd109f8d..c7d81dc005a 100644
--- a/db/migrate/20170817123339_add_verification_status_to_gpg_signatures.rb
+++ b/db/migrate/20170817123339_add_verification_status_to_gpg_signatures.rb
@@ -1,4 +1,4 @@
-class AddVerificationStatusToGpgSignatures < ActiveRecord::Migration
+class AddVerificationStatusToGpgSignatures < ActiveRecord::Migration[4.2]
DOWNTIME = false
include Gitlab::Database::MigrationHelpers
diff --git a/db/migrate/20170820100558_correct_protected_tags_foreign_keys.rb b/db/migrate/20170820100558_correct_protected_tags_foreign_keys.rb
index 229298e1946..82e05885b0e 100644
--- a/db/migrate/20170820100558_correct_protected_tags_foreign_keys.rb
+++ b/db/migrate/20170820100558_correct_protected_tags_foreign_keys.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class CorrectProtectedTagsForeignKeys < ActiveRecord::Migration
+class CorrectProtectedTagsForeignKeys < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170820120108_create_user_synced_attributes_metadata.rb b/db/migrate/20170820120108_create_user_synced_attributes_metadata.rb
index 79028e34987..131dcf7ac25 100644
--- a/db/migrate/20170820120108_create_user_synced_attributes_metadata.rb
+++ b/db/migrate/20170820120108_create_user_synced_attributes_metadata.rb
@@ -1,4 +1,4 @@
-class CreateUserSyncedAttributesMetadata < ActiveRecord::Migration
+class CreateUserSyncedAttributesMetadata < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170824101926_add_auto_devops_enabled_to_application_settings.rb b/db/migrate/20170824101926_add_auto_devops_enabled_to_application_settings.rb
index da518d8215c..f7c0aeab8f9 100644
--- a/db/migrate/20170824101926_add_auto_devops_enabled_to_application_settings.rb
+++ b/db/migrate/20170824101926_add_auto_devops_enabled_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddAutoDevopsEnabledToApplicationSettings < ActiveRecord::Migration
+class AddAutoDevopsEnabledToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170824162758_allow_appearances_description_html_null.rb b/db/migrate/20170824162758_allow_appearances_description_html_null.rb
index d7f481ee894..6efa3452796 100644
--- a/db/migrate/20170824162758_allow_appearances_description_html_null.rb
+++ b/db/migrate/20170824162758_allow_appearances_description_html_null.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AllowAppearancesDescriptionHtmlNull < ActiveRecord::Migration
+class AllowAppearancesDescriptionHtmlNull < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170825015534_add_file_store_to_lfs_objects.rb b/db/migrate/20170825015534_add_file_store_to_lfs_objects.rb
index 41bb031014f..be543ffc983 100644
--- a/db/migrate/20170825015534_add_file_store_to_lfs_objects.rb
+++ b/db/migrate/20170825015534_add_file_store_to_lfs_objects.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddFileStoreToLfsObjects < ActiveRecord::Migration
+class AddFileStoreToLfsObjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170825104051_migrate_issues_to_ghost_user.rb b/db/migrate/20170825104051_migrate_issues_to_ghost_user.rb
index c5fb5762d61..b1adccc9c5c 100644
--- a/db/migrate/20170825104051_migrate_issues_to_ghost_user.rb
+++ b/db/migrate/20170825104051_migrate_issues_to_ghost_user.rb
@@ -1,4 +1,4 @@
-class MigrateIssuesToGhostUser < ActiveRecord::Migration
+class MigrateIssuesToGhostUser < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170825154015_resolve_outdated_diff_discussions.rb b/db/migrate/20170825154015_resolve_outdated_diff_discussions.rb
index 235530bb1e6..1aed21f10a0 100644
--- a/db/migrate/20170825154015_resolve_outdated_diff_discussions.rb
+++ b/db/migrate/20170825154015_resolve_outdated_diff_discussions.rb
@@ -1,4 +1,4 @@
-class ResolveOutdatedDiffDiscussions < ActiveRecord::Migration
+class ResolveOutdatedDiffDiscussions < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170827123848_add_index_on_merge_request_diff_commit_sha.rb b/db/migrate/20170827123848_add_index_on_merge_request_diff_commit_sha.rb
index 1b360b231a8..e2061b5600a 100644
--- a/db/migrate/20170827123848_add_index_on_merge_request_diff_commit_sha.rb
+++ b/db/migrate/20170827123848_add_index_on_merge_request_diff_commit_sha.rb
@@ -1,6 +1,6 @@
# rubocop:disable RemoveIndex
-class AddIndexOnMergeRequestDiffCommitSha < ActiveRecord::Migration
+class AddIndexOnMergeRequestDiffCommitSha < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
@@ -8,7 +8,7 @@ class AddIndexOnMergeRequestDiffCommitSha < ActiveRecord::Migration
disable_ddl_transaction!
def up
- add_concurrent_index :merge_request_diff_commits, :sha, length: Gitlab::Database.mysql? ? 20 : nil
+ add_concurrent_index :merge_request_diff_commits, :sha, length: mysql_compatible_index_length
end
def down
diff --git a/db/migrate/20170828093725_create_project_auto_dev_ops.rb b/db/migrate/20170828093725_create_project_auto_dev_ops.rb
index c1bb4f20c1d..ea895dc14c1 100644
--- a/db/migrate/20170828093725_create_project_auto_dev_ops.rb
+++ b/db/migrate/20170828093725_create_project_auto_dev_ops.rb
@@ -1,4 +1,4 @@
-class CreateProjectAutoDevOps < ActiveRecord::Migration
+class CreateProjectAutoDevOps < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170828135939_migrate_user_external_mail_data.rb b/db/migrate/20170828135939_migrate_user_external_mail_data.rb
index f7ac87374b6..9ee4a4598bf 100644
--- a/db/migrate/20170828135939_migrate_user_external_mail_data.rb
+++ b/db/migrate/20170828135939_migrate_user_external_mail_data.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MigrateUserExternalMailData < ActiveRecord::Migration
+class MigrateUserExternalMailData < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170830125940_add_failure_reason_to_ci_builds.rb b/db/migrate/20170830125940_add_failure_reason_to_ci_builds.rb
index 5a7487b9227..44f709868ca 100644
--- a/db/migrate/20170830125940_add_failure_reason_to_ci_builds.rb
+++ b/db/migrate/20170830125940_add_failure_reason_to_ci_builds.rb
@@ -1,4 +1,4 @@
-class AddFailureReasonToCiBuilds < ActiveRecord::Migration
+class AddFailureReasonToCiBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170830130119_steal_remaining_event_migration_jobs.rb b/db/migrate/20170830130119_steal_remaining_event_migration_jobs.rb
index 0dfdc4ed261..bcc34d56d2d 100644
--- a/db/migrate/20170830130119_steal_remaining_event_migration_jobs.rb
+++ b/db/migrate/20170830130119_steal_remaining_event_migration_jobs.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class StealRemainingEventMigrationJobs < ActiveRecord::Migration
+class StealRemainingEventMigrationJobs < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170830131015_swap_event_migration_tables.rb b/db/migrate/20170830131015_swap_event_migration_tables.rb
index a256de4a8af..fb3b2472ffe 100644
--- a/db/migrate/20170830131015_swap_event_migration_tables.rb
+++ b/db/migrate/20170830131015_swap_event_migration_tables.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class SwapEventMigrationTables < ActiveRecord::Migration
+class SwapEventMigrationTables < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170831092813_add_config_source_to_pipelines.rb b/db/migrate/20170831092813_add_config_source_to_pipelines.rb
index ff51e968abd..ba1f73f0e68 100644
--- a/db/migrate/20170831092813_add_config_source_to_pipelines.rb
+++ b/db/migrate/20170831092813_add_config_source_to_pipelines.rb
@@ -1,4 +1,4 @@
-class AddConfigSourceToPipelines < ActiveRecord::Migration
+class AddConfigSourceToPipelines < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20170901071411_add_foreign_key_to_issue_author.rb b/db/migrate/20170901071411_add_foreign_key_to_issue_author.rb
index ab6e9fb565a..00d0b0f2c7f 100644
--- a/db/migrate/20170901071411_add_foreign_key_to_issue_author.rb
+++ b/db/migrate/20170901071411_add_foreign_key_to_issue_author.rb
@@ -1,4 +1,4 @@
-class AddForeignKeyToIssueAuthor < ActiveRecord::Migration
+class AddForeignKeyToIssueAuthor < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170904092148_add_email_confirmation.rb b/db/migrate/20170904092148_add_email_confirmation.rb
index 17ff424b319..8bfb2005936 100644
--- a/db/migrate/20170904092148_add_email_confirmation.rb
+++ b/db/migrate/20170904092148_add_email_confirmation.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddEmailConfirmation < ActiveRecord::Migration
+class AddEmailConfirmation < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170905112933_add_resolved_by_push_to_notes.rb b/db/migrate/20170905112933_add_resolved_by_push_to_notes.rb
index ceb31ffb08a..1f27ea3c467 100644
--- a/db/migrate/20170905112933_add_resolved_by_push_to_notes.rb
+++ b/db/migrate/20170905112933_add_resolved_by_push_to_notes.rb
@@ -1,4 +1,4 @@
-class AddResolvedByPushToNotes < ActiveRecord::Migration
+class AddResolvedByPushToNotes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170906133745_add_runners_token_to_groups.rb b/db/migrate/20170906133745_add_runners_token_to_groups.rb
index 852f4cba670..a02160feb83 100644
--- a/db/migrate/20170906133745_add_runners_token_to_groups.rb
+++ b/db/migrate/20170906133745_add_runners_token_to_groups.rb
@@ -1,4 +1,4 @@
-class AddRunnersTokenToGroups < ActiveRecord::Migration
+class AddRunnersTokenToGroups < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170909090114_add_email_confirmation_index.rb b/db/migrate/20170909090114_add_email_confirmation_index.rb
index a8c1023c482..31c48db2bd2 100644
--- a/db/migrate/20170909090114_add_email_confirmation_index.rb
+++ b/db/migrate/20170909090114_add_email_confirmation_index.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddEmailConfirmationIndex < ActiveRecord::Migration
+class AddEmailConfirmationIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170909150936_add_spent_at_to_timelogs.rb b/db/migrate/20170909150936_add_spent_at_to_timelogs.rb
index ffff719c289..3a2c900b445 100644
--- a/db/migrate/20170909150936_add_spent_at_to_timelogs.rb
+++ b/db/migrate/20170909150936_add_spent_at_to_timelogs.rb
@@ -1,4 +1,4 @@
-class AddSpentAtToTimelogs < ActiveRecord::Migration
+class AddSpentAtToTimelogs < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20170912113435_clean_stages_statuses_migration.rb b/db/migrate/20170912113435_clean_stages_statuses_migration.rb
index fc091d7894e..f2040f819cd 100644
--- a/db/migrate/20170912113435_clean_stages_statuses_migration.rb
+++ b/db/migrate/20170912113435_clean_stages_statuses_migration.rb
@@ -1,4 +1,4 @@
-class CleanStagesStatusesMigration < ActiveRecord::Migration
+class CleanStagesStatusesMigration < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170913131410_environments_project_id_not_null.rb b/db/migrate/20170913131410_environments_project_id_not_null.rb
index d5404f8ede9..ba66113945b 100644
--- a/db/migrate/20170913131410_environments_project_id_not_null.rb
+++ b/db/migrate/20170913131410_environments_project_id_not_null.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class EnvironmentsProjectIdNotNull < ActiveRecord::Migration
+class EnvironmentsProjectIdNotNull < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170914135630_add_index_for_recent_push_events.rb b/db/migrate/20170914135630_add_index_for_recent_push_events.rb
index 99f593b0465..ac86185ba50 100644
--- a/db/migrate/20170914135630_add_index_for_recent_push_events.rb
+++ b/db/migrate/20170914135630_add_index_for_recent_push_events.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddIndexForRecentPushEvents < ActiveRecord::Migration
+class AddIndexForRecentPushEvents < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170918072948_create_job_artifacts.rb b/db/migrate/20170918072948_create_job_artifacts.rb
index 95f2c6c8ce8..4dd24aaff99 100644
--- a/db/migrate/20170918072948_create_job_artifacts.rb
+++ b/db/migrate/20170918072948_create_job_artifacts.rb
@@ -1,4 +1,4 @@
-class CreateJobArtifacts < ActiveRecord::Migration
+class CreateJobArtifacts < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170918072949_add_file_store_job_artifacts.rb b/db/migrate/20170918072949_add_file_store_job_artifacts.rb
index b1f1bea6deb..3eb355c9305 100644
--- a/db/migrate/20170918072949_add_file_store_job_artifacts.rb
+++ b/db/migrate/20170918072949_add_file_store_job_artifacts.rb
@@ -1,4 +1,4 @@
-class AddFileStoreJobArtifacts < ActiveRecord::Migration
+class AddFileStoreJobArtifacts < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20170918111708_create_project_custom_attributes.rb b/db/migrate/20170918111708_create_project_custom_attributes.rb
index b5bc90ec02e..bd6064689ff 100644
--- a/db/migrate/20170918111708_create_project_custom_attributes.rb
+++ b/db/migrate/20170918111708_create_project_custom_attributes.rb
@@ -1,4 +1,4 @@
-class CreateProjectCustomAttributes < ActiveRecord::Migration
+class CreateProjectCustomAttributes < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20170918140927_create_group_custom_attributes.rb b/db/migrate/20170918140927_create_group_custom_attributes.rb
index 3879ea15eb6..215a0f16b6f 100644
--- a/db/migrate/20170918140927_create_group_custom_attributes.rb
+++ b/db/migrate/20170918140927_create_group_custom_attributes.rb
@@ -1,4 +1,4 @@
-class CreateGroupCustomAttributes < ActiveRecord::Migration
+class CreateGroupCustomAttributes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170918222253_reorganize_deployments_indexes.rb b/db/migrate/20170918222253_reorganize_deployments_indexes.rb
index 139427ed2b9..480847ac393 100644
--- a/db/migrate/20170918222253_reorganize_deployments_indexes.rb
+++ b/db/migrate/20170918222253_reorganize_deployments_indexes.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class ReorganizeDeploymentsIndexes < ActiveRecord::Migration
+class ReorganizeDeploymentsIndexes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170918223303_add_deployments_index_for_last_deployment.rb b/db/migrate/20170918223303_add_deployments_index_for_last_deployment.rb
index b91efb86d98..8e165ac647d 100644
--- a/db/migrate/20170918223303_add_deployments_index_for_last_deployment.rb
+++ b/db/migrate/20170918223303_add_deployments_index_for_last_deployment.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddDeploymentsIndexForLastDeployment < ActiveRecord::Migration
+class AddDeploymentsIndexForLastDeployment < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170919211300_remove_temporary_ci_builds_index.rb b/db/migrate/20170919211300_remove_temporary_ci_builds_index.rb
index 8423bf13fd9..23c94a809d4 100644
--- a/db/migrate/20170919211300_remove_temporary_ci_builds_index.rb
+++ b/db/migrate/20170919211300_remove_temporary_ci_builds_index.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveTemporaryCiBuildsIndex < ActiveRecord::Migration
+class RemoveTemporaryCiBuildsIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170921115009_add_project_repository_storage_index.rb b/db/migrate/20170921115009_add_project_repository_storage_index.rb
index 1c5a8fd65e1..9e1f5052f28 100644
--- a/db/migrate/20170921115009_add_project_repository_storage_index.rb
+++ b/db/migrate/20170921115009_add_project_repository_storage_index.rb
@@ -1,4 +1,4 @@
-class AddProjectRepositoryStorageIndex < ActiveRecord::Migration
+class AddProjectRepositoryStorageIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170924094327_create_gcp_clusters.rb b/db/migrate/20170924094327_create_gcp_clusters.rb
index 657dddcbbc4..43201f75ad7 100644
--- a/db/migrate/20170924094327_create_gcp_clusters.rb
+++ b/db/migrate/20170924094327_create_gcp_clusters.rb
@@ -1,4 +1,4 @@
-class CreateGcpClusters < ActiveRecord::Migration
+class CreateGcpClusters < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20170925184228_add_favicon_to_appearances.rb b/db/migrate/20170925184228_add_favicon_to_appearances.rb
index 65083733afb..1ce750f7e83 100644
--- a/db/migrate/20170925184228_add_favicon_to_appearances.rb
+++ b/db/migrate/20170925184228_add_favicon_to_appearances.rb
@@ -1,4 +1,4 @@
-class AddFaviconToAppearances < ActiveRecord::Migration
+class AddFaviconToAppearances < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20170927095921_add_ci_builds_index_for_jobscontroller.rb b/db/migrate/20170927095921_add_ci_builds_index_for_jobscontroller.rb
index c2cb1df2586..85aa78006db 100644
--- a/db/migrate/20170927095921_add_ci_builds_index_for_jobscontroller.rb
+++ b/db/migrate/20170927095921_add_ci_builds_index_for_jobscontroller.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddCiBuildsIndexForJobscontroller < ActiveRecord::Migration
+class AddCiBuildsIndexForJobscontroller < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170927122209_add_partial_index_for_labels_template.rb b/db/migrate/20170927122209_add_partial_index_for_labels_template.rb
index c3e5077ba20..dd79e024df4 100644
--- a/db/migrate/20170927122209_add_partial_index_for_labels_template.rb
+++ b/db/migrate/20170927122209_add_partial_index_for_labels_template.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddPartialIndexForLabelsTemplate < ActiveRecord::Migration
+class AddPartialIndexForLabelsTemplate < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170927161718_create_gpg_key_subkeys.rb b/db/migrate/20170927161718_create_gpg_key_subkeys.rb
index c03c40416a8..3b5d452ee12 100644
--- a/db/migrate/20170927161718_create_gpg_key_subkeys.rb
+++ b/db/migrate/20170927161718_create_gpg_key_subkeys.rb
@@ -1,4 +1,6 @@
-class CreateGpgKeySubkeys < ActiveRecord::Migration
+class CreateGpgKeySubkeys < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
DOWNTIME = false
def up
@@ -8,8 +10,8 @@ class CreateGpgKeySubkeys < ActiveRecord::Migration
t.binary :keyid
t.binary :fingerprint
- t.index :keyid, unique: true, length: Gitlab::Database.mysql? ? 20 : nil
- t.index :fingerprint, unique: true, length: Gitlab::Database.mysql? ? 20 : nil
+ t.index :keyid, unique: true, length: mysql_compatible_index_length
+ t.index :fingerprint, unique: true, length: mysql_compatible_index_length
end
add_reference :gpg_signatures, :gpg_key_subkey, index: true, foreign_key: { on_delete: :nullify }
diff --git a/db/migrate/20170928100231_add_composite_index_on_merge_requests_merge_commit_sha.rb b/db/migrate/20170928100231_add_composite_index_on_merge_requests_merge_commit_sha.rb
index 9f02daf04c1..cb16589e8db 100644
--- a/db/migrate/20170928100231_add_composite_index_on_merge_requests_merge_commit_sha.rb
+++ b/db/migrate/20170928100231_add_composite_index_on_merge_requests_merge_commit_sha.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddCompositeIndexOnMergeRequestsMergeCommitSha < ActiveRecord::Migration
+class AddCompositeIndexOnMergeRequestsMergeCommitSha < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20170928124105_create_fork_networks.rb b/db/migrate/20170928124105_create_fork_networks.rb
index 89e5b871967..01f623117f5 100644
--- a/db/migrate/20170928124105_create_fork_networks.rb
+++ b/db/migrate/20170928124105_create_fork_networks.rb
@@ -1,4 +1,4 @@
-class CreateForkNetworks < ActiveRecord::Migration
+class CreateForkNetworks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170928133643_create_fork_network_members.rb b/db/migrate/20170928133643_create_fork_network_members.rb
index 8c7d9ba859a..e2a6d7b0e8a 100644
--- a/db/migrate/20170928133643_create_fork_network_members.rb
+++ b/db/migrate/20170928133643_create_fork_network_members.rb
@@ -1,4 +1,4 @@
-class CreateForkNetworkMembers < ActiveRecord::Migration
+class CreateForkNetworkMembers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170929080234_add_failure_reason_to_pipelines.rb b/db/migrate/20170929080234_add_failure_reason_to_pipelines.rb
index 82adddbc1ec..e000ee27eef 100644
--- a/db/migrate/20170929080234_add_failure_reason_to_pipelines.rb
+++ b/db/migrate/20170929080234_add_failure_reason_to_pipelines.rb
@@ -1,4 +1,4 @@
-class AddFailureReasonToPipelines < ActiveRecord::Migration
+class AddFailureReasonToPipelines < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20170929131201_populate_fork_networks.rb b/db/migrate/20170929131201_populate_fork_networks.rb
index ddbf27e1852..ba4f8ef2531 100644
--- a/db/migrate/20170929131201_populate_fork_networks.rb
+++ b/db/migrate/20170929131201_populate_fork_networks.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class PopulateForkNetworks < ActiveRecord::Migration
+class PopulateForkNetworks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171004121444_make_sure_fast_forward_option_exists.rb b/db/migrate/20171004121444_make_sure_fast_forward_option_exists.rb
index ac266c3e22e..9b417de1793 100644
--- a/db/migrate/20171004121444_make_sure_fast_forward_option_exists.rb
+++ b/db/migrate/20171004121444_make_sure_fast_forward_option_exists.rb
@@ -1,5 +1,5 @@
# rubocop:disable all
-class MakeSureFastForwardOptionExists < ActiveRecord::Migration
+class MakeSureFastForwardOptionExists < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171006090001_create_ci_build_trace_sections.rb b/db/migrate/20171006090001_create_ci_build_trace_sections.rb
index ab5ef319618..a2eca0832f2 100644
--- a/db/migrate/20171006090001_create_ci_build_trace_sections.rb
+++ b/db/migrate/20171006090001_create_ci_build_trace_sections.rb
@@ -1,4 +1,4 @@
-class CreateCiBuildTraceSections < ActiveRecord::Migration
+class CreateCiBuildTraceSections < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171006090010_add_build_foreign_key_to_ci_build_trace_sections.rb b/db/migrate/20171006090010_add_build_foreign_key_to_ci_build_trace_sections.rb
index d279463eb4b..7b17763ac84 100644
--- a/db/migrate/20171006090010_add_build_foreign_key_to_ci_build_trace_sections.rb
+++ b/db/migrate/20171006090010_add_build_foreign_key_to_ci_build_trace_sections.rb
@@ -1,4 +1,4 @@
-class AddBuildForeignKeyToCiBuildTraceSections < ActiveRecord::Migration
+class AddBuildForeignKeyToCiBuildTraceSections < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171006090100_create_ci_build_trace_section_names.rb b/db/migrate/20171006090100_create_ci_build_trace_section_names.rb
index 88f3e60699a..00a38fa59c2 100644
--- a/db/migrate/20171006090100_create_ci_build_trace_section_names.rb
+++ b/db/migrate/20171006090100_create_ci_build_trace_section_names.rb
@@ -1,4 +1,4 @@
-class CreateCiBuildTraceSectionNames < ActiveRecord::Migration
+class CreateCiBuildTraceSectionNames < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171006091000_add_name_foreign_key_to_ci_build_trace_sections.rb b/db/migrate/20171006091000_add_name_foreign_key_to_ci_build_trace_sections.rb
index 08422885a98..1342ff013b7 100644
--- a/db/migrate/20171006091000_add_name_foreign_key_to_ci_build_trace_sections.rb
+++ b/db/migrate/20171006091000_add_name_foreign_key_to_ci_build_trace_sections.rb
@@ -1,4 +1,4 @@
-class AddNameForeignKeyToCiBuildTraceSections < ActiveRecord::Migration
+class AddNameForeignKeyToCiBuildTraceSections < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171006220837_add_global_rate_limits_to_application_settings.rb b/db/migrate/20171006220837_add_global_rate_limits_to_application_settings.rb
index 55e822752af..96d76069b35 100644
--- a/db/migrate/20171006220837_add_global_rate_limits_to_application_settings.rb
+++ b/db/migrate/20171006220837_add_global_rate_limits_to_application_settings.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddGlobalRateLimitsToApplicationSettings < ActiveRecord::Migration
+class AddGlobalRateLimitsToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171012101043_add_circuit_breaker_properties_to_application_settings.rb b/db/migrate/20171012101043_add_circuit_breaker_properties_to_application_settings.rb
index bcf7dbd8e64..91bba07b4d7 100644
--- a/db/migrate/20171012101043_add_circuit_breaker_properties_to_application_settings.rb
+++ b/db/migrate/20171012101043_add_circuit_breaker_properties_to_application_settings.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddCircuitBreakerPropertiesToApplicationSettings < ActiveRecord::Migration
+class AddCircuitBreakerPropertiesToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171012125712_migrate_user_authentication_token_to_personal_access_token.rb b/db/migrate/20171012125712_migrate_user_authentication_token_to_personal_access_token.rb
index 9a909644a44..305c12e31f8 100644
--- a/db/migrate/20171012125712_migrate_user_authentication_token_to_personal_access_token.rb
+++ b/db/migrate/20171012125712_migrate_user_authentication_token_to_personal_access_token.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MigrateUserAuthenticationTokenToPersonalAccessToken < ActiveRecord::Migration
+class MigrateUserAuthenticationTokenToPersonalAccessToken < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171013094327_create_new_clusters_architectures.rb b/db/migrate/20171013094327_create_new_clusters_architectures.rb
index dabb3e25e48..98f91e6130f 100644
--- a/db/migrate/20171013094327_create_new_clusters_architectures.rb
+++ b/db/migrate/20171013094327_create_new_clusters_architectures.rb
@@ -1,4 +1,4 @@
-class CreateNewClustersArchitectures < ActiveRecord::Migration
+class CreateNewClustersArchitectures < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20171017145932_add_new_circuitbreaker_settings_to_application_settings.rb b/db/migrate/20171017145932_add_new_circuitbreaker_settings_to_application_settings.rb
index 07eb25c0b0f..4a0cadea364 100644
--- a/db/migrate/20171017145932_add_new_circuitbreaker_settings_to_application_settings.rb
+++ b/db/migrate/20171017145932_add_new_circuitbreaker_settings_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddNewCircuitbreakerSettingsToApplicationSettings < ActiveRecord::Migration
+class AddNewCircuitbreakerSettingsToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171019141859_fix_dev_timezone_schema.rb b/db/migrate/20171019141859_fix_dev_timezone_schema.rb
index fb7c17dd747..68c8b528e17 100644
--- a/db/migrate/20171019141859_fix_dev_timezone_schema.rb
+++ b/db/migrate/20171019141859_fix_dev_timezone_schema.rb
@@ -1,4 +1,4 @@
-class FixDevTimezoneSchema < ActiveRecord::Migration
+class FixDevTimezoneSchema < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# The this migrations tries to help solve unwanted changes to `schema.rb`
diff --git a/db/migrate/20171025110159_add_latest_merge_request_diff_id_to_merge_requests.rb b/db/migrate/20171025110159_add_latest_merge_request_diff_id_to_merge_requests.rb
index 74a2badc130..1af0cf70958 100644
--- a/db/migrate/20171025110159_add_latest_merge_request_diff_id_to_merge_requests.rb
+++ b/db/migrate/20171025110159_add_latest_merge_request_diff_id_to_merge_requests.rb
@@ -1,4 +1,4 @@
-class AddLatestMergeRequestDiffIdToMergeRequests < ActiveRecord::Migration
+class AddLatestMergeRequestDiffIdToMergeRequests < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171031100710_create_clusters_kubernetes_helm_apps.rb b/db/migrate/20171031100710_create_clusters_kubernetes_helm_apps.rb
index a2ce37127ea..0af05f5c94a 100644
--- a/db/migrate/20171031100710_create_clusters_kubernetes_helm_apps.rb
+++ b/db/migrate/20171031100710_create_clusters_kubernetes_helm_apps.rb
@@ -1,4 +1,4 @@
-class CreateClustersKubernetesHelmApps < ActiveRecord::Migration
+class CreateClustersKubernetesHelmApps < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171101130535_add_gitaly_timeout_properties_to_application_settings.rb b/db/migrate/20171101130535_add_gitaly_timeout_properties_to_application_settings.rb
index de621e7111c..6d60fdc6132 100644
--- a/db/migrate/20171101130535_add_gitaly_timeout_properties_to_application_settings.rb
+++ b/db/migrate/20171101130535_add_gitaly_timeout_properties_to_application_settings.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddGitalyTimeoutPropertiesToApplicationSettings < ActiveRecord::Migration
+class AddGitalyTimeoutPropertiesToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171103000000_set_uploads_path_size_for_mysql.rb b/db/migrate/20171103000000_set_uploads_path_size_for_mysql.rb
index 1fbe505f804..93cec87f999 100644
--- a/db/migrate/20171103000000_set_uploads_path_size_for_mysql.rb
+++ b/db/migrate/20171103000000_set_uploads_path_size_for_mysql.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class SetUploadsPathSizeForMysql < ActiveRecord::Migration
+class SetUploadsPathSizeForMysql < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171106101200_create_clusters_kubernetes_ingress_apps.rb b/db/migrate/20171106101200_create_clusters_kubernetes_ingress_apps.rb
index 21f48b1d1b4..770cb94ee18 100644
--- a/db/migrate/20171106101200_create_clusters_kubernetes_ingress_apps.rb
+++ b/db/migrate/20171106101200_create_clusters_kubernetes_ingress_apps.rb
@@ -1,4 +1,4 @@
-class CreateClustersKubernetesIngressApps < ActiveRecord::Migration
+class CreateClustersKubernetesIngressApps < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171106132212_issues_confidential_not_null.rb b/db/migrate/20171106132212_issues_confidential_not_null.rb
index c959d2dd938..444a38c2dc5 100644
--- a/db/migrate/20171106132212_issues_confidential_not_null.rb
+++ b/db/migrate/20171106132212_issues_confidential_not_null.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class IssuesConfidentialNotNull < ActiveRecord::Migration
+class IssuesConfidentialNotNull < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171106133143_rename_application_settings_password_authentication_enabled_to_password_authentication_enabled_for_web.rb b/db/migrate/20171106133143_rename_application_settings_password_authentication_enabled_to_password_authentication_enabled_for_web.rb
index 6d369e93361..58762a4f852 100644
--- a/db/migrate/20171106133143_rename_application_settings_password_authentication_enabled_to_password_authentication_enabled_for_web.rb
+++ b/db/migrate/20171106133143_rename_application_settings_password_authentication_enabled_to_password_authentication_enabled_for_web.rb
@@ -1,4 +1,4 @@
-class RenameApplicationSettingsPasswordAuthenticationEnabledToPasswordAuthenticationEnabledForWeb < ActiveRecord::Migration
+class RenameApplicationSettingsPasswordAuthenticationEnabledToPasswordAuthenticationEnabledForWeb < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171106133911_add_password_authentication_enabled_for_git_to_application_settings.rb b/db/migrate/20171106133911_add_password_authentication_enabled_for_git_to_application_settings.rb
index b8aa600864e..1f96a0426a1 100644
--- a/db/migrate/20171106133911_add_password_authentication_enabled_for_git_to_application_settings.rb
+++ b/db/migrate/20171106133911_add_password_authentication_enabled_for_git_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddPasswordAuthenticationEnabledForGitToApplicationSettings < ActiveRecord::Migration
+class AddPasswordAuthenticationEnabledForGitToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171106135924_issues_milestone_id_foreign_key.rb b/db/migrate/20171106135924_issues_milestone_id_foreign_key.rb
index bfb3dcae511..1de7d5e768e 100644
--- a/db/migrate/20171106135924_issues_milestone_id_foreign_key.rb
+++ b/db/migrate/20171106135924_issues_milestone_id_foreign_key.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class IssuesMilestoneIdForeignKey < ActiveRecord::Migration
+class IssuesMilestoneIdForeignKey < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171106150657_issues_updated_by_id_foreign_key.rb b/db/migrate/20171106150657_issues_updated_by_id_foreign_key.rb
index 3b8844d7d9f..b2992b1ff5d 100644
--- a/db/migrate/20171106150657_issues_updated_by_id_foreign_key.rb
+++ b/db/migrate/20171106150657_issues_updated_by_id_foreign_key.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class IssuesUpdatedByIdForeignKey < ActiveRecord::Migration
+class IssuesUpdatedByIdForeignKey < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171106151218_issues_moved_to_id_foreign_key.rb b/db/migrate/20171106151218_issues_moved_to_id_foreign_key.rb
index 6395462384b..66bfb5718dc 100644
--- a/db/migrate/20171106151218_issues_moved_to_id_foreign_key.rb
+++ b/db/migrate/20171106151218_issues_moved_to_id_foreign_key.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class IssuesMovedToIdForeignKey < ActiveRecord::Migration
+class IssuesMovedToIdForeignKey < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171106155656_turn_issues_due_date_index_to_partial_index.rb b/db/migrate/20171106155656_turn_issues_due_date_index_to_partial_index.rb
index 08784de4043..58392de5e6b 100644
--- a/db/migrate/20171106155656_turn_issues_due_date_index_to_partial_index.rb
+++ b/db/migrate/20171106155656_turn_issues_due_date_index_to_partial_index.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class TurnIssuesDueDateIndexToPartialIndex < ActiveRecord::Migration
+class TurnIssuesDueDateIndexToPartialIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171106171453_add_timezone_to_issues_closed_at.rb b/db/migrate/20171106171453_add_timezone_to_issues_closed_at.rb
index 0f1e937545b..c6edc1af6cb 100644
--- a/db/migrate/20171106171453_add_timezone_to_issues_closed_at.rb
+++ b/db/migrate/20171106171453_add_timezone_to_issues_closed_at.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddTimezoneToIssuesClosedAt < ActiveRecord::Migration
+class AddTimezoneToIssuesClosedAt < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171114150259_merge_requests_author_id_foreign_key.rb b/db/migrate/20171114150259_merge_requests_author_id_foreign_key.rb
index 021eaa04a0c..4ebb6fad059 100644
--- a/db/migrate/20171114150259_merge_requests_author_id_foreign_key.rb
+++ b/db/migrate/20171114150259_merge_requests_author_id_foreign_key.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MergeRequestsAuthorIdForeignKey < ActiveRecord::Migration
+class MergeRequestsAuthorIdForeignKey < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171114160005_merge_requests_assignee_id_foreign_key.rb b/db/migrate/20171114160005_merge_requests_assignee_id_foreign_key.rb
index 1a242f01051..73c177c44f9 100644
--- a/db/migrate/20171114160005_merge_requests_assignee_id_foreign_key.rb
+++ b/db/migrate/20171114160005_merge_requests_assignee_id_foreign_key.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MergeRequestsAssigneeIdForeignKey < ActiveRecord::Migration
+class MergeRequestsAssigneeIdForeignKey < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171114160904_merge_requests_updated_by_id_foreign_key.rb b/db/migrate/20171114160904_merge_requests_updated_by_id_foreign_key.rb
index eb3872e38da..69f9c181c10 100644
--- a/db/migrate/20171114160904_merge_requests_updated_by_id_foreign_key.rb
+++ b/db/migrate/20171114160904_merge_requests_updated_by_id_foreign_key.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MergeRequestsUpdatedByIdForeignKey < ActiveRecord::Migration
+class MergeRequestsUpdatedByIdForeignKey < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171114161720_merge_requests_merge_user_id_foreign_key.rb b/db/migrate/20171114161720_merge_requests_merge_user_id_foreign_key.rb
index 925b3e537d7..ccd275d5bb4 100644
--- a/db/migrate/20171114161720_merge_requests_merge_user_id_foreign_key.rb
+++ b/db/migrate/20171114161720_merge_requests_merge_user_id_foreign_key.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MergeRequestsMergeUserIdForeignKey < ActiveRecord::Migration
+class MergeRequestsMergeUserIdForeignKey < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171114161914_merge_requests_source_project_id_foreign_key.rb b/db/migrate/20171114161914_merge_requests_source_project_id_foreign_key.rb
index 99740f64fe6..250928a6551 100644
--- a/db/migrate/20171114161914_merge_requests_source_project_id_foreign_key.rb
+++ b/db/migrate/20171114161914_merge_requests_source_project_id_foreign_key.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MergeRequestsSourceProjectIdForeignKey < ActiveRecord::Migration
+class MergeRequestsSourceProjectIdForeignKey < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171114162227_merge_requests_milestone_id_foreign_key.rb b/db/migrate/20171114162227_merge_requests_milestone_id_foreign_key.rb
index c005cf7d173..cafe0ce0853 100644
--- a/db/migrate/20171114162227_merge_requests_milestone_id_foreign_key.rb
+++ b/db/migrate/20171114162227_merge_requests_milestone_id_foreign_key.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MergeRequestsMilestoneIdForeignKey < ActiveRecord::Migration
+class MergeRequestsMilestoneIdForeignKey < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171115164540_populate_merge_requests_latest_merge_request_diff_id_take_two.rb b/db/migrate/20171115164540_populate_merge_requests_latest_merge_request_diff_id_take_two.rb
index 27b6b4ebddc..935092ce46a 100644
--- a/db/migrate/20171115164540_populate_merge_requests_latest_merge_request_diff_id_take_two.rb
+++ b/db/migrate/20171115164540_populate_merge_requests_latest_merge_request_diff_id_take_two.rb
@@ -1,5 +1,5 @@
# This is identical to the stolen background migration, which already has specs.
-class PopulateMergeRequestsLatestMergeRequestDiffIdTakeTwo < ActiveRecord::Migration
+class PopulateMergeRequestsLatestMergeRequestDiffIdTakeTwo < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171116135628_add_environment_scope_to_clusters.rb b/db/migrate/20171116135628_add_environment_scope_to_clusters.rb
index cce757095dd..39bb8759cc0 100644
--- a/db/migrate/20171116135628_add_environment_scope_to_clusters.rb
+++ b/db/migrate/20171116135628_add_environment_scope_to_clusters.rb
@@ -1,4 +1,4 @@
-class AddEnvironmentScopeToClusters < ActiveRecord::Migration
+class AddEnvironmentScopeToClusters < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171121135738_clean_up_from_merge_request_diffs_and_commits.rb b/db/migrate/20171121135738_clean_up_from_merge_request_diffs_and_commits.rb
index 30cf08b29fc..6be7b75492d 100644
--- a/db/migrate/20171121135738_clean_up_from_merge_request_diffs_and_commits.rb
+++ b/db/migrate/20171121135738_clean_up_from_merge_request_diffs_and_commits.rb
@@ -1,4 +1,4 @@
-class CleanUpFromMergeRequestDiffsAndCommits < ActiveRecord::Migration
+class CleanUpFromMergeRequestDiffsAndCommits < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171121144800_ci_pipelines_index_on_project_id_ref_status_id.rb b/db/migrate/20171121144800_ci_pipelines_index_on_project_id_ref_status_id.rb
index 5a8ae6e4b57..a1dcfc70650 100644
--- a/db/migrate/20171121144800_ci_pipelines_index_on_project_id_ref_status_id.rb
+++ b/db/migrate/20171121144800_ci_pipelines_index_on_project_id_ref_status_id.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class CiPipelinesIndexOnProjectIdRefStatusId < ActiveRecord::Migration
+class CiPipelinesIndexOnProjectIdRefStatusId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171122131600_add_new_project_guidelines_to_appearances.rb b/db/migrate/20171122131600_add_new_project_guidelines_to_appearances.rb
index 328cc65a549..cbcbb5d988a 100644
--- a/db/migrate/20171122131600_add_new_project_guidelines_to_appearances.rb
+++ b/db/migrate/20171122131600_add_new_project_guidelines_to_appearances.rb
@@ -1,4 +1,4 @@
-class AddNewProjectGuidelinesToAppearances < ActiveRecord::Migration
+class AddNewProjectGuidelinesToAppearances < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171123094802_add_circuitbreaker_check_interval_to_application_settings.rb b/db/migrate/20171123094802_add_circuitbreaker_check_interval_to_application_settings.rb
index 213d46018fc..94360c64926 100644
--- a/db/migrate/20171123094802_add_circuitbreaker_check_interval_to_application_settings.rb
+++ b/db/migrate/20171123094802_add_circuitbreaker_check_interval_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddCircuitbreakerCheckIntervalToApplicationSettings < ActiveRecord::Migration
+class AddCircuitbreakerCheckIntervalToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171124125042_add_default_values_to_merge_request_states.rb b/db/migrate/20171124125042_add_default_values_to_merge_request_states.rb
index d08863c3b78..d0d06863777 100644
--- a/db/migrate/20171124125042_add_default_values_to_merge_request_states.rb
+++ b/db/migrate/20171124125042_add_default_values_to_merge_request_states.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddDefaultValuesToMergeRequestStates < ActiveRecord::Migration
+class AddDefaultValuesToMergeRequestStates < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171124125748_populate_missing_merge_request_statuses.rb b/db/migrate/20171124125748_populate_missing_merge_request_statuses.rb
index 72fbab59f4c..67444f36e24 100644
--- a/db/migrate/20171124125748_populate_missing_merge_request_statuses.rb
+++ b/db/migrate/20171124125748_populate_missing_merge_request_statuses.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class PopulateMissingMergeRequestStatuses < ActiveRecord::Migration
+class PopulateMissingMergeRequestStatuses < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171124132536_make_merge_request_statuses_not_null.rb b/db/migrate/20171124132536_make_merge_request_statuses_not_null.rb
index 4bb09126036..49b693c5950 100644
--- a/db/migrate/20171124132536_make_merge_request_statuses_not_null.rb
+++ b/db/migrate/20171124132536_make_merge_request_statuses_not_null.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MakeMergeRequestStatusesNotNull < ActiveRecord::Migration
+class MakeMergeRequestStatusesNotNull < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171127151038_add_events_related_columns_to_merge_request_metrics.rb b/db/migrate/20171127151038_add_events_related_columns_to_merge_request_metrics.rb
index 18af697cf88..385de9dd73d 100644
--- a/db/migrate/20171127151038_add_events_related_columns_to_merge_request_metrics.rb
+++ b/db/migrate/20171127151038_add_events_related_columns_to_merge_request_metrics.rb
@@ -1,4 +1,4 @@
-class AddEventsRelatedColumnsToMergeRequestMetrics < ActiveRecord::Migration
+class AddEventsRelatedColumnsToMergeRequestMetrics < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171204204233_add_permanent_to_redirect_route.rb b/db/migrate/20171204204233_add_permanent_to_redirect_route.rb
index f3ae471201e..bc0658035d6 100644
--- a/db/migrate/20171204204233_add_permanent_to_redirect_route.rb
+++ b/db/migrate/20171204204233_add_permanent_to_redirect_route.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddPermanentToRedirectRoute < ActiveRecord::Migration
+class AddPermanentToRedirectRoute < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20171206221519_add_permanent_index_to_redirect_route.rb b/db/migrate/20171206221519_add_permanent_index_to_redirect_route.rb
index 33ce7e1aa68..ba924c4eecc 100644
--- a/db/migrate/20171206221519_add_permanent_index_to_redirect_route.rb
+++ b/db/migrate/20171206221519_add_permanent_index_to_redirect_route.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddPermanentIndexToRedirectRoute < ActiveRecord::Migration
+class AddPermanentIndexToRedirectRoute < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171207185153_add_merge_request_state_index.rb b/db/migrate/20171207185153_add_merge_request_state_index.rb
index 72f846c5c38..167470cf7fe 100644
--- a/db/migrate/20171207185153_add_merge_request_state_index.rb
+++ b/db/migrate/20171207185153_add_merge_request_state_index.rb
@@ -1,4 +1,4 @@
-class AddMergeRequestStateIndex < ActiveRecord::Migration
+class AddMergeRequestStateIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171211145425_add_can_push_to_deploy_keys_projects.rb b/db/migrate/20171211145425_add_can_push_to_deploy_keys_projects.rb
index 5dc723db9f9..63e86b23aad 100644
--- a/db/migrate/20171211145425_add_can_push_to_deploy_keys_projects.rb
+++ b/db/migrate/20171211145425_add_can_push_to_deploy_keys_projects.rb
@@ -1,4 +1,4 @@
-class AddCanPushToDeployKeysProjects < ActiveRecord::Migration
+class AddCanPushToDeployKeysProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171212203433_create_clusters_applications_prometheus.rb b/db/migrate/20171212203433_create_clusters_applications_prometheus.rb
index dc2531d2691..6eb9fec609e 100644
--- a/db/migrate/20171212203433_create_clusters_applications_prometheus.rb
+++ b/db/migrate/20171212203433_create_clusters_applications_prometheus.rb
@@ -1,4 +1,4 @@
-class CreateClustersApplicationsPrometheus < ActiveRecord::Migration
+class CreateClustersApplicationsPrometheus < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171214144320_add_store_column_to_uploads.rb b/db/migrate/20171214144320_add_store_column_to_uploads.rb
index e35798e2c41..11b3951a3fa 100644
--- a/db/migrate/20171214144320_add_store_column_to_uploads.rb
+++ b/db/migrate/20171214144320_add_store_column_to_uploads.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddStoreColumnToUploads < ActiveRecord::Migration
+class AddStoreColumnToUploads < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171215113714_populate_can_push_from_deploy_keys_projects.rb b/db/migrate/20171215113714_populate_can_push_from_deploy_keys_projects.rb
index 680855af945..e2d7879b140 100644
--- a/db/migrate/20171215113714_populate_can_push_from_deploy_keys_projects.rb
+++ b/db/migrate/20171215113714_populate_can_push_from_deploy_keys_projects.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class PopulateCanPushFromDeployKeysProjects < ActiveRecord::Migration
+class PopulateCanPushFromDeployKeysProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171216111734_clean_up_for_members.rb b/db/migrate/20171216111734_clean_up_for_members.rb
index 22e0997dce6..2fefc6c7fd1 100644
--- a/db/migrate/20171216111734_clean_up_for_members.rb
+++ b/db/migrate/20171216111734_clean_up_for_members.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class CleanUpForMembers < ActiveRecord::Migration
+class CleanUpForMembers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171216112339_add_foreign_key_for_members.rb b/db/migrate/20171216112339_add_foreign_key_for_members.rb
index be17769be6a..06c2c5068da 100644
--- a/db/migrate/20171216112339_add_foreign_key_for_members.rb
+++ b/db/migrate/20171216112339_add_foreign_key_for_members.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddForeignKeyForMembers < ActiveRecord::Migration
+class AddForeignKeyForMembers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171220191323_add_index_on_namespaces_lower_name.rb b/db/migrate/20171220191323_add_index_on_namespaces_lower_name.rb
index 130b24fe6f0..7543e435941 100644
--- a/db/migrate/20171220191323_add_index_on_namespaces_lower_name.rb
+++ b/db/migrate/20171220191323_add_index_on_namespaces_lower_name.rb
@@ -1,4 +1,4 @@
-class AddIndexOnNamespacesLowerName < ActiveRecord::Migration
+class AddIndexOnNamespacesLowerName < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
INDEX_NAME = 'index_on_namespaces_lower_name'
diff --git a/db/migrate/20171222115326_add_confidential_note_events_to_web_hooks.rb b/db/migrate/20171222115326_add_confidential_note_events_to_web_hooks.rb
index 900a6386922..788a842a3ad 100644
--- a/db/migrate/20171222115326_add_confidential_note_events_to_web_hooks.rb
+++ b/db/migrate/20171222115326_add_confidential_note_events_to_web_hooks.rb
@@ -1,4 +1,4 @@
-class AddConfidentialNoteEventsToWebHooks < ActiveRecord::Migration
+class AddConfidentialNoteEventsToWebHooks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20171222183504_add_jobs_cache_index_to_project.rb b/db/migrate/20171222183504_add_jobs_cache_index_to_project.rb
index 607e9d027d7..78a195c351c 100644
--- a/db/migrate/20171222183504_add_jobs_cache_index_to_project.rb
+++ b/db/migrate/20171222183504_add_jobs_cache_index_to_project.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddJobsCacheIndexToProject < ActiveRecord::Migration
+class AddJobsCacheIndexToProject < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171229225929_change_user_project_limit_not_null_and_remove_default.rb b/db/migrate/20171229225929_change_user_project_limit_not_null_and_remove_default.rb
index 54fbbcf1a0d..b9efdb8bb8f 100644
--- a/db/migrate/20171229225929_change_user_project_limit_not_null_and_remove_default.rb
+++ b/db/migrate/20171229225929_change_user_project_limit_not_null_and_remove_default.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class ChangeUserProjectLimitNotNullAndRemoveDefault < ActiveRecord::Migration
+class ChangeUserProjectLimitNotNullAndRemoveDefault < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20171230123729_add_rebase_commit_sha_to_merge_requests_ce.rb b/db/migrate/20171230123729_add_rebase_commit_sha_to_merge_requests_ce.rb
index 94a7c1019d8..4e1107e1ff5 100644
--- a/db/migrate/20171230123729_add_rebase_commit_sha_to_merge_requests_ce.rb
+++ b/db/migrate/20171230123729_add_rebase_commit_sha_to_merge_requests_ce.rb
@@ -1,4 +1,4 @@
-class AddRebaseCommitShaToMergeRequestsCe < ActiveRecord::Migration
+class AddRebaseCommitShaToMergeRequestsCe < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20180101160629_create_prometheus_metrics.rb b/db/migrate/20180101160629_create_prometheus_metrics.rb
index c3be0939b17..e3b1ed710d6 100644
--- a/db/migrate/20180101160629_create_prometheus_metrics.rb
+++ b/db/migrate/20180101160629_create_prometheus_metrics.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class CreatePrometheusMetrics < ActiveRecord::Migration
+class CreatePrometheusMetrics < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20180101160630_change_project_id_for_prometheus_metrics.rb b/db/migrate/20180101160630_change_project_id_for_prometheus_metrics.rb
index 66820f13f54..d225899af18 100644
--- a/db/migrate/20180101160630_change_project_id_for_prometheus_metrics.rb
+++ b/db/migrate/20180101160630_change_project_id_for_prometheus_metrics.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ChangeProjectIdForPrometheusMetrics < ActiveRecord::Migration
+class ChangeProjectIdForPrometheusMetrics < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180102220145_add_pages_https_only_to_projects.rb b/db/migrate/20180102220145_add_pages_https_only_to_projects.rb
index ef6bc6896c0..75488f57fa9 100644
--- a/db/migrate/20180102220145_add_pages_https_only_to_projects.rb
+++ b/db/migrate/20180102220145_add_pages_https_only_to_projects.rb
@@ -1,4 +1,4 @@
-class AddPagesHttpsOnlyToProjects < ActiveRecord::Migration
+class AddPagesHttpsOnlyToProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180103123548_add_confidential_note_events_to_services.rb b/db/migrate/20180103123548_add_confidential_note_events_to_services.rb
index b54ad88df43..02724575e6c 100644
--- a/db/migrate/20180103123548_add_confidential_note_events_to_services.rb
+++ b/db/migrate/20180103123548_add_confidential_note_events_to_services.rb
@@ -1,4 +1,4 @@
-class AddConfidentialNoteEventsToServices < ActiveRecord::Migration
+class AddConfidentialNoteEventsToServices < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180105212544_add_commits_count_to_merge_request_diff.rb b/db/migrate/20180105212544_add_commits_count_to_merge_request_diff.rb
index f942b4c062e..e27eecde906 100644
--- a/db/migrate/20180105212544_add_commits_count_to_merge_request_diff.rb
+++ b/db/migrate/20180105212544_add_commits_count_to_merge_request_diff.rb
@@ -1,4 +1,4 @@
-class AddCommitsCountToMergeRequestDiff < ActiveRecord::Migration
+class AddCommitsCountToMergeRequestDiff < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180109183319_change_default_value_for_pages_https_only.rb b/db/migrate/20180109183319_change_default_value_for_pages_https_only.rb
index c242e1b0d24..558eb60ac3f 100644
--- a/db/migrate/20180109183319_change_default_value_for_pages_https_only.rb
+++ b/db/migrate/20180109183319_change_default_value_for_pages_https_only.rb
@@ -1,4 +1,4 @@
-class ChangeDefaultValueForPagesHttpsOnly < ActiveRecord::Migration
+class ChangeDefaultValueForPagesHttpsOnly < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180113220114_rework_redirect_routes_indexes.rb b/db/migrate/20180113220114_rework_redirect_routes_indexes.rb
index 53f82a31203..4c3bb0a26ce 100644
--- a/db/migrate/20180113220114_rework_redirect_routes_indexes.rb
+++ b/db/migrate/20180113220114_rework_redirect_routes_indexes.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class ReworkRedirectRoutesIndexes < ActiveRecord::Migration
+class ReworkRedirectRoutesIndexes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20180115201419_add_index_updated_at_to_issues.rb b/db/migrate/20180115201419_add_index_updated_at_to_issues.rb
index a5a48fc97be..8707307eed0 100644
--- a/db/migrate/20180115201419_add_index_updated_at_to_issues.rb
+++ b/db/migrate/20180115201419_add_index_updated_at_to_issues.rb
@@ -1,4 +1,4 @@
-class AddIndexUpdatedAtToIssues < ActiveRecord::Migration
+class AddIndexUpdatedAtToIssues < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180116193854_create_lfs_file_locks.rb b/db/migrate/20180116193854_create_lfs_file_locks.rb
index 23b0c90484b..2dd0e71916b 100644
--- a/db/migrate/20180116193854_create_lfs_file_locks.rb
+++ b/db/migrate/20180116193854_create_lfs_file_locks.rb
@@ -1,4 +1,4 @@
-class CreateLfsFileLocks < ActiveRecord::Migration
+class CreateLfsFileLocks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180119135717_add_uploader_index_to_uploads.rb b/db/migrate/20180119135717_add_uploader_index_to_uploads.rb
index a678c3d049f..7dd0a06e3bf 100644
--- a/db/migrate/20180119135717_add_uploader_index_to_uploads.rb
+++ b/db/migrate/20180119135717_add_uploader_index_to_uploads.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddUploaderIndexToUploads < ActiveRecord::Migration
+class AddUploaderIndexToUploads < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180119160751_optimize_ci_job_artifacts.rb b/db/migrate/20180119160751_optimize_ci_job_artifacts.rb
index 9b4340ed7b7..3598689d78c 100644
--- a/db/migrate/20180119160751_optimize_ci_job_artifacts.rb
+++ b/db/migrate/20180119160751_optimize_ci_job_artifacts.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class OptimizeCiJobArtifacts < ActiveRecord::Migration
+class OptimizeCiJobArtifacts < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20180122162010_add_auto_devops_domain_to_application_settings.rb b/db/migrate/20180122162010_add_auto_devops_domain_to_application_settings.rb
index 7e16cb83087..c76dc5b3a68 100644
--- a/db/migrate/20180122162010_add_auto_devops_domain_to_application_settings.rb
+++ b/db/migrate/20180122162010_add_auto_devops_domain_to_application_settings.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddAutoDevopsDomainToApplicationSettings < ActiveRecord::Migration
+class AddAutoDevopsDomainToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20180125214301_create_user_callouts.rb b/db/migrate/20180125214301_create_user_callouts.rb
index 856eff36ae0..6eb2f932ccc 100644
--- a/db/migrate/20180125214301_create_user_callouts.rb
+++ b/db/migrate/20180125214301_create_user_callouts.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class CreateUserCallouts < ActiveRecord::Migration
+class CreateUserCallouts < ActiveRecord::Migration[4.2]
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
diff --git a/db/migrate/20180129193323_add_uploads_builder_context.rb b/db/migrate/20180129193323_add_uploads_builder_context.rb
index b3909a770ca..c7227bf0f1e 100644
--- a/db/migrate/20180129193323_add_uploads_builder_context.rb
+++ b/db/migrate/20180129193323_add_uploads_builder_context.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddUploadsBuilderContext < ActiveRecord::Migration
+class AddUploadsBuilderContext < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20180201102129_add_unique_constraint_to_trending_projects_project_id.rb b/db/migrate/20180201102129_add_unique_constraint_to_trending_projects_project_id.rb
index 02e53b8fa8a..1f2a79d36a5 100644
--- a/db/migrate/20180201102129_add_unique_constraint_to_trending_projects_project_id.rb
+++ b/db/migrate/20180201102129_add_unique_constraint_to_trending_projects_project_id.rb
@@ -1,4 +1,4 @@
-class AddUniqueConstraintToTrendingProjectsProjectId < ActiveRecord::Migration
+class AddUniqueConstraintToTrendingProjectsProjectId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180201110056_add_foreign_keys_to_todos.rb b/db/migrate/20180201110056_add_foreign_keys_to_todos.rb
index 020b0550321..6b217632a52 100644
--- a/db/migrate/20180201110056_add_foreign_keys_to_todos.rb
+++ b/db/migrate/20180201110056_add_foreign_keys_to_todos.rb
@@ -1,4 +1,4 @@
-class AddForeignKeysToTodos < ActiveRecord::Migration
+class AddForeignKeysToTodos < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
class Todo < ActiveRecord::Base
diff --git a/db/migrate/20180201145907_migrate_remaining_issues_closed_at.rb b/db/migrate/20180201145907_migrate_remaining_issues_closed_at.rb
index 36a85b61968..d398909f25b 100644
--- a/db/migrate/20180201145907_migrate_remaining_issues_closed_at.rb
+++ b/db/migrate/20180201145907_migrate_remaining_issues_closed_at.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MigrateRemainingIssuesClosedAt < ActiveRecord::Migration
+class MigrateRemainingIssuesClosedAt < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20180206200543_reset_events_primary_key_sequence.rb b/db/migrate/20180206200543_reset_events_primary_key_sequence.rb
index eb5c4a6a1e7..d395c5725e4 100644
--- a/db/migrate/20180206200543_reset_events_primary_key_sequence.rb
+++ b/db/migrate/20180206200543_reset_events_primary_key_sequence.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class ResetEventsPrimaryKeySequence < ActiveRecord::Migration
+class ResetEventsPrimaryKeySequence < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20180208183958_schedule_populate_untracked_uploads_if_needed.rb b/db/migrate/20180208183958_schedule_populate_untracked_uploads_if_needed.rb
index e46e793d9d2..b69ac8f94c1 100644
--- a/db/migrate/20180208183958_schedule_populate_untracked_uploads_if_needed.rb
+++ b/db/migrate/20180208183958_schedule_populate_untracked_uploads_if_needed.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class SchedulePopulateUntrackedUploadsIfNeeded < ActiveRecord::Migration
+class SchedulePopulateUntrackedUploadsIfNeeded < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180209165249_add_closed_by_to_issues.rb b/db/migrate/20180209165249_add_closed_by_to_issues.rb
index e251afd7b49..91a1e021ab9 100644
--- a/db/migrate/20180209165249_add_closed_by_to_issues.rb
+++ b/db/migrate/20180209165249_add_closed_by_to_issues.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddClosedByToIssues < ActiveRecord::Migration
+class AddClosedByToIssues < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20180212030105_add_external_ip_to_clusters_applications_ingress.rb b/db/migrate/20180212030105_add_external_ip_to_clusters_applications_ingress.rb
index dbe09a43aa7..e2a9a68b1ad 100644
--- a/db/migrate/20180212030105_add_external_ip_to_clusters_applications_ingress.rb
+++ b/db/migrate/20180212030105_add_external_ip_to_clusters_applications_ingress.rb
@@ -1,4 +1,4 @@
-class AddExternalIpToClustersApplicationsIngress < ActiveRecord::Migration
+class AddExternalIpToClustersApplicationsIngress < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180213131630_add_partial_index_to_projects_for_index_only_scans.rb b/db/migrate/20180213131630_add_partial_index_to_projects_for_index_only_scans.rb
index cedf2510dda..905915d9239 100644
--- a/db/migrate/20180213131630_add_partial_index_to_projects_for_index_only_scans.rb
+++ b/db/migrate/20180213131630_add_partial_index_to_projects_for_index_only_scans.rb
@@ -1,4 +1,4 @@
-class AddPartialIndexToProjectsForIndexOnlyScans < ActiveRecord::Migration
+class AddPartialIndexToProjectsForIndexOnlyScans < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180214093516_create_badges.rb b/db/migrate/20180214093516_create_badges.rb
index a1d77328f77..66e017b115a 100644
--- a/db/migrate/20180214093516_create_badges.rb
+++ b/db/migrate/20180214093516_create_badges.rb
@@ -1,4 +1,4 @@
-class CreateBadges < ActiveRecord::Migration
+class CreateBadges < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20180214155405_create_clusters_applications_runners.rb b/db/migrate/20180214155405_create_clusters_applications_runners.rb
index fc4c0881338..ce594c91890 100644
--- a/db/migrate/20180214155405_create_clusters_applications_runners.rb
+++ b/db/migrate/20180214155405_create_clusters_applications_runners.rb
@@ -1,4 +1,4 @@
-class CreateClustersApplicationsRunners < ActiveRecord::Migration
+class CreateClustersApplicationsRunners < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180215181245_users_name_lower_index.rb b/db/migrate/20180215181245_users_name_lower_index.rb
index d3f68cb7d45..3b80601a727 100644
--- a/db/migrate/20180215181245_users_name_lower_index.rb
+++ b/db/migrate/20180215181245_users_name_lower_index.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class UsersNameLowerIndex < ActiveRecord::Migration
+class UsersNameLowerIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20180216120000_add_pages_domain_verification.rb b/db/migrate/20180216120000_add_pages_domain_verification.rb
index 8b7cae92285..f709f5a5809 100644
--- a/db/migrate/20180216120000_add_pages_domain_verification.rb
+++ b/db/migrate/20180216120000_add_pages_domain_verification.rb
@@ -1,4 +1,4 @@
-class AddPagesDomainVerification < ActiveRecord::Migration
+class AddPagesDomainVerification < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20180216120010_add_pages_domain_verified_at_index.rb b/db/migrate/20180216120010_add_pages_domain_verified_at_index.rb
index 825dfb52dce..6e7cb89c765 100644
--- a/db/migrate/20180216120010_add_pages_domain_verified_at_index.rb
+++ b/db/migrate/20180216120010_add_pages_domain_verified_at_index.rb
@@ -1,4 +1,4 @@
-class AddPagesDomainVerifiedAtIndex < ActiveRecord::Migration
+class AddPagesDomainVerifiedAtIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180216120020_allow_domain_verification_to_be_disabled.rb b/db/migrate/20180216120020_allow_domain_verification_to_be_disabled.rb
index 06d458028b3..18e4f534105 100644
--- a/db/migrate/20180216120020_allow_domain_verification_to_be_disabled.rb
+++ b/db/migrate/20180216120020_allow_domain_verification_to_be_disabled.rb
@@ -1,4 +1,4 @@
-class AllowDomainVerificationToBeDisabled < ActiveRecord::Migration
+class AllowDomainVerificationToBeDisabled < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20180216120030_add_pages_domain_enabled_until.rb b/db/migrate/20180216120030_add_pages_domain_enabled_until.rb
index b40653044dd..3347bb6deaa 100644
--- a/db/migrate/20180216120030_add_pages_domain_enabled_until.rb
+++ b/db/migrate/20180216120030_add_pages_domain_enabled_until.rb
@@ -1,4 +1,4 @@
-class AddPagesDomainEnabledUntil < ActiveRecord::Migration
+class AddPagesDomainEnabledUntil < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20180216120040_add_pages_domain_enabled_until_index.rb b/db/migrate/20180216120040_add_pages_domain_enabled_until_index.rb
index 00f6e4979da..3880a8ea139 100644
--- a/db/migrate/20180216120040_add_pages_domain_enabled_until_index.rb
+++ b/db/migrate/20180216120040_add_pages_domain_enabled_until_index.rb
@@ -1,4 +1,4 @@
-class AddPagesDomainEnabledUntilIndex < ActiveRecord::Migration
+class AddPagesDomainEnabledUntilIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180216120050_pages_domains_verification_grace_period.rb b/db/migrate/20180216120050_pages_domains_verification_grace_period.rb
index d7f8634b536..e51cff68b50 100644
--- a/db/migrate/20180216120050_pages_domains_verification_grace_period.rb
+++ b/db/migrate/20180216120050_pages_domains_verification_grace_period.rb
@@ -1,4 +1,4 @@
-class PagesDomainsVerificationGracePeriod < ActiveRecord::Migration
+class PagesDomainsVerificationGracePeriod < ActiveRecord::Migration[4.2]
DOWNTIME = false
class PagesDomain < ActiveRecord::Base
diff --git a/db/migrate/20180219153455_add_maximum_timeout_to_ci_runners.rb b/db/migrate/20180219153455_add_maximum_timeout_to_ci_runners.rb
index 072e696a43e..68578c23207 100644
--- a/db/migrate/20180219153455_add_maximum_timeout_to_ci_runners.rb
+++ b/db/migrate/20180219153455_add_maximum_timeout_to_ci_runners.rb
@@ -1,4 +1,4 @@
-class AddMaximumTimeoutToCiRunners < ActiveRecord::Migration
+class AddMaximumTimeoutToCiRunners < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180221151752_add_allow_maintainer_to_push_to_merge_requests.rb b/db/migrate/20180221151752_add_allow_maintainer_to_push_to_merge_requests.rb
index 81acfbc3655..71f6bc46a88 100644
--- a/db/migrate/20180221151752_add_allow_maintainer_to_push_to_merge_requests.rb
+++ b/db/migrate/20180221151752_add_allow_maintainer_to_push_to_merge_requests.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddAllowMaintainerToPushToMergeRequests < ActiveRecord::Migration
+class AddAllowMaintainerToPushToMergeRequests < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180222043024_add_ip_address_to_runner.rb b/db/migrate/20180222043024_add_ip_address_to_runner.rb
index bf00560b5a8..b52366c0be1 100644
--- a/db/migrate/20180222043024_add_ip_address_to_runner.rb
+++ b/db/migrate/20180222043024_add_ip_address_to_runner.rb
@@ -1,4 +1,4 @@
-class AddIpAddressToRunner < ActiveRecord::Migration
+class AddIpAddressToRunner < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180223120443_create_user_interacted_projects_table.rb b/db/migrate/20180223120443_create_user_interacted_projects_table.rb
index 8da8cf68088..185a690ad3d 100644
--- a/db/migrate/20180223120443_create_user_interacted_projects_table.rb
+++ b/db/migrate/20180223120443_create_user_interacted_projects_table.rb
@@ -1,4 +1,4 @@
-class CreateUserInteractedProjectsTable < ActiveRecord::Migration
+class CreateUserInteractedProjectsTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180223144945_add_allow_local_requests_from_hooks_and_services_to_application_settings.rb b/db/migrate/20180223144945_add_allow_local_requests_from_hooks_and_services_to_application_settings.rb
index c994a54698b..3bd7d6fd827 100644
--- a/db/migrate/20180223144945_add_allow_local_requests_from_hooks_and_services_to_application_settings.rb
+++ b/db/migrate/20180223144945_add_allow_local_requests_from_hooks_and_services_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddAllowLocalRequestsFromHooksAndServicesToApplicationSettings < ActiveRecord::Migration
+class AddAllowLocalRequestsFromHooksAndServicesToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180226050030_add_checksum_to_ci_job_artifacts.rb b/db/migrate/20180226050030_add_checksum_to_ci_job_artifacts.rb
index 54e6e35449e..bccb7ac26ec 100644
--- a/db/migrate/20180226050030_add_checksum_to_ci_job_artifacts.rb
+++ b/db/migrate/20180226050030_add_checksum_to_ci_job_artifacts.rb
@@ -1,4 +1,4 @@
-class AddChecksumToCiJobArtifacts < ActiveRecord::Migration
+class AddChecksumToCiJobArtifacts < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20180227182112_add_group_id_to_boards_ce.rb b/db/migrate/20180227182112_add_group_id_to_boards_ce.rb
index 5b2691b3a00..b887be0cc55 100644
--- a/db/migrate/20180227182112_add_group_id_to_boards_ce.rb
+++ b/db/migrate/20180227182112_add_group_id_to_boards_ce.rb
@@ -1,4 +1,4 @@
-class AddGroupIdToBoardsCe < ActiveRecord::Migration
+class AddGroupIdToBoardsCe < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20180228172924_add_include_private_contributions_to_users.rb b/db/migrate/20180228172924_add_include_private_contributions_to_users.rb
index ea3ebdd83d1..7921d3a14b6 100644
--- a/db/migrate/20180228172924_add_include_private_contributions_to_users.rb
+++ b/db/migrate/20180228172924_add_include_private_contributions_to_users.rb
@@ -1,4 +1,4 @@
-class AddIncludePrivateContributionsToUsers < ActiveRecord::Migration
+class AddIncludePrivateContributionsToUsers < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20180301010859_create_ci_builds_metadata_table.rb b/db/migrate/20180301010859_create_ci_builds_metadata_table.rb
index ce737444092..29652c675e1 100644
--- a/db/migrate/20180301010859_create_ci_builds_metadata_table.rb
+++ b/db/migrate/20180301010859_create_ci_builds_metadata_table.rb
@@ -1,4 +1,4 @@
-class CreateCiBuildsMetadataTable < ActiveRecord::Migration
+class CreateCiBuildsMetadataTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180302152117_ensure_foreign_keys_on_clusters_applications.rb b/db/migrate/20180302152117_ensure_foreign_keys_on_clusters_applications.rb
index e6cec39e61f..d660c7cfd2d 100644
--- a/db/migrate/20180302152117_ensure_foreign_keys_on_clusters_applications.rb
+++ b/db/migrate/20180302152117_ensure_foreign_keys_on_clusters_applications.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class EnsureForeignKeysOnClustersApplications < ActiveRecord::Migration
+class EnsureForeignKeysOnClustersApplications < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180305095250_create_internal_ids_table.rb b/db/migrate/20180305095250_create_internal_ids_table.rb
index 432086fe98b..8565f5d848b 100644
--- a/db/migrate/20180305095250_create_internal_ids_table.rb
+++ b/db/migrate/20180305095250_create_internal_ids_table.rb
@@ -1,4 +1,4 @@
-class CreateInternalIdsTable < ActiveRecord::Migration
+class CreateInternalIdsTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180305144721_add_privileged_to_runner.rb b/db/migrate/20180305144721_add_privileged_to_runner.rb
index 32e73dba8d5..359498bf9b0 100644
--- a/db/migrate/20180305144721_add_privileged_to_runner.rb
+++ b/db/migrate/20180305144721_add_privileged_to_runner.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddPrivilegedToRunner < ActiveRecord::Migration
+class AddPrivilegedToRunner < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180306134842_add_missing_indexes_acts_as_taggable_on_engine.rb b/db/migrate/20180306134842_add_missing_indexes_acts_as_taggable_on_engine.rb
index 06e402adcd7..b400ff94dbe 100644
--- a/db/migrate/20180306134842_add_missing_indexes_acts_as_taggable_on_engine.rb
+++ b/db/migrate/20180306134842_add_missing_indexes_acts_as_taggable_on_engine.rb
@@ -2,7 +2,7 @@
#
# It has been modified to handle no-downtime GitLab migrations. Several
# indexes have been removed since they are not needed for GitLab.
-class AddMissingIndexesActsAsTaggableOnEngine < ActiveRecord::Migration
+class AddMissingIndexesActsAsTaggableOnEngine < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180308052825_add_section_name_id_index_on_ci_build_trace_sections.rb b/db/migrate/20180308052825_add_section_name_id_index_on_ci_build_trace_sections.rb
index b616cc2fd30..4d2ab7d757f 100644
--- a/db/migrate/20180308052825_add_section_name_id_index_on_ci_build_trace_sections.rb
+++ b/db/migrate/20180308052825_add_section_name_id_index_on_ci_build_trace_sections.rb
@@ -1,4 +1,4 @@
-class AddSectionNameIdIndexOnCiBuildTraceSections < ActiveRecord::Migration
+class AddSectionNameIdIndexOnCiBuildTraceSections < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20180308125206_add_user_internal_regex_to_application_setting.rb b/db/migrate/20180308125206_add_user_internal_regex_to_application_setting.rb
index fe50e909563..5e4bf96f86f 100644
--- a/db/migrate/20180308125206_add_user_internal_regex_to_application_setting.rb
+++ b/db/migrate/20180308125206_add_user_internal_regex_to_application_setting.rb
@@ -1,4 +1,4 @@
-class AddUserInternalRegexToApplicationSetting < ActiveRecord::Migration
+class AddUserInternalRegexToApplicationSetting < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180309121820_reschedule_commits_count_for_merge_request_diff.rb b/db/migrate/20180309121820_reschedule_commits_count_for_merge_request_diff.rb
index 990759104b0..ecb06dd4312 100644
--- a/db/migrate/20180309121820_reschedule_commits_count_for_merge_request_diff.rb
+++ b/db/migrate/20180309121820_reschedule_commits_count_for_merge_request_diff.rb
@@ -1,4 +1,4 @@
-class RescheduleCommitsCountForMergeRequestDiff < ActiveRecord::Migration
+class RescheduleCommitsCountForMergeRequestDiff < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180309160427_add_partial_indexes_on_todos.rb b/db/migrate/20180309160427_add_partial_indexes_on_todos.rb
index 671fa743cec..c22ed0a5177 100644
--- a/db/migrate/20180309160427_add_partial_indexes_on_todos.rb
+++ b/db/migrate/20180309160427_add_partial_indexes_on_todos.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddPartialIndexesOnTodos < ActiveRecord::Migration
+class AddPartialIndexesOnTodos < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20180319190020_create_deploy_tokens.rb b/db/migrate/20180319190020_create_deploy_tokens.rb
index d129459ea0a..a4d797679c5 100644
--- a/db/migrate/20180319190020_create_deploy_tokens.rb
+++ b/db/migrate/20180319190020_create_deploy_tokens.rb
@@ -1,4 +1,4 @@
-class CreateDeployTokens < ActiveRecord::Migration
+class CreateDeployTokens < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20180320182229_add_indexes_for_user_activity_queries.rb b/db/migrate/20180320182229_add_indexes_for_user_activity_queries.rb
index 824bbb3ac05..a15e1d68a95 100644
--- a/db/migrate/20180320182229_add_indexes_for_user_activity_queries.rb
+++ b/db/migrate/20180320182229_add_indexes_for_user_activity_queries.rb
@@ -1,4 +1,4 @@
-class AddIndexesForUserActivityQueries < ActiveRecord::Migration
+class AddIndexesForUserActivityQueries < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180323150945_add_push_to_merge_request_to_notification_settings.rb b/db/migrate/20180323150945_add_push_to_merge_request_to_notification_settings.rb
index 12b8875d8dc..3b38d21a8aa 100644
--- a/db/migrate/20180323150945_add_push_to_merge_request_to_notification_settings.rb
+++ b/db/migrate/20180323150945_add_push_to_merge_request_to_notification_settings.rb
@@ -1,4 +1,4 @@
-class AddPushToMergeRequestToNotificationSettings < ActiveRecord::Migration
+class AddPushToMergeRequestToNotificationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180326202229_create_ci_build_trace_chunks.rb b/db/migrate/20180326202229_create_ci_build_trace_chunks.rb
index fb3f5786e85..45a64ec23d1 100644
--- a/db/migrate/20180326202229_create_ci_build_trace_chunks.rb
+++ b/db/migrate/20180326202229_create_ci_build_trace_chunks.rb
@@ -1,4 +1,4 @@
-class CreateCiBuildTraceChunks < ActiveRecord::Migration
+class CreateCiBuildTraceChunks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180327101207_remove_index_from_events_table.rb b/db/migrate/20180327101207_remove_index_from_events_table.rb
index 172441da65b..0583a2641ec 100644
--- a/db/migrate/20180327101207_remove_index_from_events_table.rb
+++ b/db/migrate/20180327101207_remove_index_from_events_table.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveIndexFromEventsTable < ActiveRecord::Migration
+class RemoveIndexFromEventsTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180330121048_add_issue_due_to_notification_settings.rb b/db/migrate/20180330121048_add_issue_due_to_notification_settings.rb
index c64a481fcf0..2d9ca002872 100644
--- a/db/migrate/20180330121048_add_issue_due_to_notification_settings.rb
+++ b/db/migrate/20180330121048_add_issue_due_to_notification_settings.rb
@@ -1,4 +1,4 @@
-class AddIssueDueToNotificationSettings < ActiveRecord::Migration
+class AddIssueDueToNotificationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180403035759_create_project_ci_cd_settings.rb b/db/migrate/20180403035759_create_project_ci_cd_settings.rb
index 173e662cffc..00028689779 100644
--- a/db/migrate/20180403035759_create_project_ci_cd_settings.rb
+++ b/db/migrate/20180403035759_create_project_ci_cd_settings.rb
@@ -1,4 +1,4 @@
-class CreateProjectCiCdSettings < ActiveRecord::Migration
+class CreateProjectCiCdSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180405142733_create_project_deploy_tokens.rb b/db/migrate/20180405142733_create_project_deploy_tokens.rb
index 9d8f89243a8..ba000492247 100644
--- a/db/migrate/20180405142733_create_project_deploy_tokens.rb
+++ b/db/migrate/20180405142733_create_project_deploy_tokens.rb
@@ -1,4 +1,4 @@
-class CreateProjectDeployTokens < ActiveRecord::Migration
+class CreateProjectDeployTokens < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20180406204716_add_limits_ci_build_trace_chunks_raw_data_for_mysql.rb b/db/migrate/20180406204716_add_limits_ci_build_trace_chunks_raw_data_for_mysql.rb
index 0f2734853e6..0b541e94353 100644
--- a/db/migrate/20180406204716_add_limits_ci_build_trace_chunks_raw_data_for_mysql.rb
+++ b/db/migrate/20180406204716_add_limits_ci_build_trace_chunks_raw_data_for_mysql.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
require Rails.root.join('db/migrate/limits_ci_build_trace_chunks_raw_data_for_mysql')
-class AddLimitsCiBuildTraceChunksRawDataForMysql < ActiveRecord::Migration
+class AddLimitsCiBuildTraceChunksRawDataForMysql < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180408143354_rename_users_rss_token_to_feed_token.rb b/db/migrate/20180408143354_rename_users_rss_token_to_feed_token.rb
index e852d50b25e..4b8844a134d 100644
--- a/db/migrate/20180408143354_rename_users_rss_token_to_feed_token.rb
+++ b/db/migrate/20180408143354_rename_users_rss_token_to_feed_token.rb
@@ -1,4 +1,4 @@
-class RenameUsersRssTokenToFeedToken < ActiveRecord::Migration
+class RenameUsersRssTokenToFeedToken < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb b/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb
index 8fc558be733..90d869a8c10 100644
--- a/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb
+++ b/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb
@@ -1,4 +1,4 @@
-class CreateMissingNamespaceForInternalUsers < ActiveRecord::Migration
+class CreateMissingNamespaceForInternalUsers < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
@@ -45,7 +45,7 @@ class CreateMissingNamespaceForInternalUsers < ActiveRecord::Migration
connection.exec_query(query).present?
end
- insert_query = "INSERT INTO namespaces(owner_id, path, name) VALUES(#{user_id}, '#{path}', '#{path}')"
+ insert_query = "INSERT INTO namespaces(owner_id, path, name, created_at, updated_at) VALUES(#{user_id}, '#{path}', '#{path}', NOW(), NOW())"
namespace_id = connection.insert_sql(insert_query)
create_route(namespace_id)
@@ -57,7 +57,7 @@ class CreateMissingNamespaceForInternalUsers < ActiveRecord::Migration
row = connection.exec_query("SELECT id, path FROM namespaces WHERE id=#{namespace_id}").first
id, path = row.values_at('id', 'path')
- execute("INSERT INTO routes(source_id, source_type, path, name) VALUES(#{id}, 'Namespace', '#{path}', '#{path}')")
+ execute("INSERT INTO routes(source_id, source_type, path, name, created_at, updated_at) VALUES(#{id}, 'Namespace', '#{path}', '#{path}', NOW(), NOW())")
end
def set_notification_email(user_id)
diff --git a/db/migrate/20180416155103_add_further_scope_columns_to_internal_id_table.rb b/db/migrate/20180416155103_add_further_scope_columns_to_internal_id_table.rb
index 37e2d19e022..7c28cbb6795 100644
--- a/db/migrate/20180416155103_add_further_scope_columns_to_internal_id_table.rb
+++ b/db/migrate/20180416155103_add_further_scope_columns_to_internal_id_table.rb
@@ -1,4 +1,4 @@
-class AddFurtherScopeColumnsToInternalIdTable < ActiveRecord::Migration
+class AddFurtherScopeColumnsToInternalIdTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180417090132_add_index_constraints_to_internal_id_table.rb b/db/migrate/20180417090132_add_index_constraints_to_internal_id_table.rb
index 58de795472a..ac6bb1a8cab 100644
--- a/db/migrate/20180417090132_add_index_constraints_to_internal_id_table.rb
+++ b/db/migrate/20180417090132_add_index_constraints_to_internal_id_table.rb
@@ -1,4 +1,4 @@
-class AddIndexConstraintsToInternalIdTable < ActiveRecord::Migration
+class AddIndexConstraintsToInternalIdTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180417101040_add_tmp_stage_priority_index_to_ci_builds.rb b/db/migrate/20180417101040_add_tmp_stage_priority_index_to_ci_builds.rb
index ee82c70ecf8..ce470884999 100644
--- a/db/migrate/20180417101040_add_tmp_stage_priority_index_to_ci_builds.rb
+++ b/db/migrate/20180417101040_add_tmp_stage_priority_index_to_ci_builds.rb
@@ -1,4 +1,4 @@
-class AddTmpStagePriorityIndexToCiBuilds < ActiveRecord::Migration
+class AddTmpStagePriorityIndexToCiBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180417101940_add_index_to_ci_stage.rb b/db/migrate/20180417101940_add_index_to_ci_stage.rb
index 9dac78db774..97a8f5efce0 100644
--- a/db/migrate/20180417101940_add_index_to_ci_stage.rb
+++ b/db/migrate/20180417101940_add_index_to_ci_stage.rb
@@ -1,4 +1,4 @@
-class AddIndexToCiStage < ActiveRecord::Migration
+class AddIndexToCiStage < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180418053107_add_index_to_ci_job_artifacts_file_store.rb b/db/migrate/20180418053107_add_index_to_ci_job_artifacts_file_store.rb
index ac91624c3d5..4b574923483 100644
--- a/db/migrate/20180418053107_add_index_to_ci_job_artifacts_file_store.rb
+++ b/db/migrate/20180418053107_add_index_to_ci_job_artifacts_file_store.rb
@@ -1,4 +1,4 @@
-class AddIndexToCiJobArtifactsFileStore < ActiveRecord::Migration
+class AddIndexToCiJobArtifactsFileStore < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180420010016_add_pipeline_build_foreign_key.rb b/db/migrate/20180420010016_add_pipeline_build_foreign_key.rb
index 6fabe07bc9c..90a908feaee 100644
--- a/db/migrate/20180420010016_add_pipeline_build_foreign_key.rb
+++ b/db/migrate/20180420010016_add_pipeline_build_foreign_key.rb
@@ -1,4 +1,4 @@
-class AddPipelineBuildForeignKey < ActiveRecord::Migration
+class AddPipelineBuildForeignKey < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180420010616_cleanup_build_stage_migration.rb b/db/migrate/20180420010616_cleanup_build_stage_migration.rb
index 5e9fe756efd..30c0d97781d 100644
--- a/db/migrate/20180420010616_cleanup_build_stage_migration.rb
+++ b/db/migrate/20180420010616_cleanup_build_stage_migration.rb
@@ -1,4 +1,4 @@
-class CleanupBuildStageMigration < ActiveRecord::Migration
+class CleanupBuildStageMigration < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180423204600_add_pages_access_level_to_project_feature.rb b/db/migrate/20180423204600_add_pages_access_level_to_project_feature.rb
new file mode 100644
index 00000000000..0c536f917ce
--- /dev/null
+++ b/db/migrate/20180423204600_add_pages_access_level_to_project_feature.rb
@@ -0,0 +1,16 @@
+class AddPagesAccessLevelToProjectFeature < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+ disable_ddl_transaction!
+
+ DOWNTIME = false
+
+ def up
+ add_column_with_default(:project_features, :pages_access_level, :integer, default: ProjectFeature::PUBLIC, allow_null: false)
+
+ change_column_default(:project_features, :pages_access_level, ProjectFeature::ENABLED)
+ end
+
+ def down
+ remove_column :project_features, :pages_access_level
+ end
+end
diff --git a/db/migrate/20180424090541_add_enforce_terms_to_application_settings.rb b/db/migrate/20180424090541_add_enforce_terms_to_application_settings.rb
index f5afdb0e4e6..b8fd71002a1 100644
--- a/db/migrate/20180424090541_add_enforce_terms_to_application_settings.rb
+++ b/db/migrate/20180424090541_add_enforce_terms_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddEnforceTermsToApplicationSettings < ActiveRecord::Migration
+class AddEnforceTermsToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180424134533_create_application_setting_terms.rb b/db/migrate/20180424134533_create_application_setting_terms.rb
index f29335cfc51..8741f20daeb 100644
--- a/db/migrate/20180424134533_create_application_setting_terms.rb
+++ b/db/migrate/20180424134533_create_application_setting_terms.rb
@@ -1,4 +1,4 @@
-class CreateApplicationSettingTerms < ActiveRecord::Migration
+class CreateApplicationSettingTerms < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180424160449_add_pipeline_iid_to_ci_pipelines.rb b/db/migrate/20180424160449_add_pipeline_iid_to_ci_pipelines.rb
index e8f0c91d612..550b5a2c149 100644
--- a/db/migrate/20180424160449_add_pipeline_iid_to_ci_pipelines.rb
+++ b/db/migrate/20180424160449_add_pipeline_iid_to_ci_pipelines.rb
@@ -1,4 +1,4 @@
-class AddPipelineIidToCiPipelines < ActiveRecord::Migration
+class AddPipelineIidToCiPipelines < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180425075446_create_term_agreements.rb b/db/migrate/20180425075446_create_term_agreements.rb
index 1fa2c8dd3be..25182215841 100644
--- a/db/migrate/20180425075446_create_term_agreements.rb
+++ b/db/migrate/20180425075446_create_term_agreements.rb
@@ -1,4 +1,4 @@
-class CreateTermAgreements < ActiveRecord::Migration
+class CreateTermAgreements < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180425131009_assure_commits_count_for_merge_request_diff.rb b/db/migrate/20180425131009_assure_commits_count_for_merge_request_diff.rb
index 0e991c23bfa..7d38a15b850 100644
--- a/db/migrate/20180425131009_assure_commits_count_for_merge_request_diff.rb
+++ b/db/migrate/20180425131009_assure_commits_count_for_merge_request_diff.rb
@@ -1,4 +1,4 @@
-class AssureCommitsCountForMergeRequestDiff < ActiveRecord::Migration
+class AssureCommitsCountForMergeRequestDiff < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180425205249_add_index_constraints_to_pipeline_iid.rb b/db/migrate/20180425205249_add_index_constraints_to_pipeline_iid.rb
index 3fa59b44d5d..8a0cb7ae4e4 100644
--- a/db/migrate/20180425205249_add_index_constraints_to_pipeline_iid.rb
+++ b/db/migrate/20180425205249_add_index_constraints_to_pipeline_iid.rb
@@ -1,4 +1,4 @@
-class AddIndexConstraintsToPipelineIid < ActiveRecord::Migration
+class AddIndexConstraintsToPipelineIid < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180426102016_add_accepted_term_to_users.rb b/db/migrate/20180426102016_add_accepted_term_to_users.rb
index 3d446f66214..3c6665b4264 100644
--- a/db/migrate/20180426102016_add_accepted_term_to_users.rb
+++ b/db/migrate/20180426102016_add_accepted_term_to_users.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddAcceptedTermToUsers < ActiveRecord::Migration
+class AddAcceptedTermToUsers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180430101916_add_runner_type_to_ci_runners.rb b/db/migrate/20180430101916_add_runner_type_to_ci_runners.rb
index 42409349b75..a74231e0f44 100644
--- a/db/migrate/20180430101916_add_runner_type_to_ci_runners.rb
+++ b/db/migrate/20180430101916_add_runner_type_to_ci_runners.rb
@@ -1,4 +1,4 @@
-class AddRunnerTypeToCiRunners < ActiveRecord::Migration
+class AddRunnerTypeToCiRunners < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180502122856_create_project_mirror_data.rb b/db/migrate/20180502122856_create_project_mirror_data.rb
index d449f944844..8bc114afc0c 100644
--- a/db/migrate/20180502122856_create_project_mirror_data.rb
+++ b/db/migrate/20180502122856_create_project_mirror_data.rb
@@ -1,4 +1,4 @@
-class CreateProjectMirrorData < ActiveRecord::Migration
+class CreateProjectMirrorData < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180503131624_create_remote_mirrors.rb b/db/migrate/20180503131624_create_remote_mirrors.rb
index 249882f8613..9f4bd463e66 100644
--- a/db/migrate/20180503131624_create_remote_mirrors.rb
+++ b/db/migrate/20180503131624_create_remote_mirrors.rb
@@ -1,4 +1,4 @@
-class CreateRemoteMirrors < ActiveRecord::Migration
+class CreateRemoteMirrors < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180503141722_add_remote_mirror_available_overridden_to_projects.rb b/db/migrate/20180503141722_add_remote_mirror_available_overridden_to_projects.rb
index 841393971f4..5e2ef5706ee 100644
--- a/db/migrate/20180503141722_add_remote_mirror_available_overridden_to_projects.rb
+++ b/db/migrate/20180503141722_add_remote_mirror_available_overridden_to_projects.rb
@@ -1,4 +1,4 @@
-class AddRemoteMirrorAvailableOverriddenToProjects < ActiveRecord::Migration
+class AddRemoteMirrorAvailableOverriddenToProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180503150427_add_index_to_namespaces_runners_token.rb b/db/migrate/20180503150427_add_index_to_namespaces_runners_token.rb
index 9e55690bd33..899e4a05cbd 100644
--- a/db/migrate/20180503150427_add_index_to_namespaces_runners_token.rb
+++ b/db/migrate/20180503150427_add_index_to_namespaces_runners_token.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddIndexToNamespacesRunnersToken < ActiveRecord::Migration
+class AddIndexToNamespacesRunnersToken < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180503175053_ensure_missing_columns_to_project_mirror_data.rb b/db/migrate/20180503175053_ensure_missing_columns_to_project_mirror_data.rb
index 970a53d68d0..3775b3a08c9 100644
--- a/db/migrate/20180503175053_ensure_missing_columns_to_project_mirror_data.rb
+++ b/db/migrate/20180503175053_ensure_missing_columns_to_project_mirror_data.rb
@@ -1,4 +1,4 @@
-class EnsureMissingColumnsToProjectMirrorData < ActiveRecord::Migration
+class EnsureMissingColumnsToProjectMirrorData < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180503175054_add_indexes_to_project_mirror_data.rb b/db/migrate/20180503175054_add_indexes_to_project_mirror_data.rb
index b59b941c815..15a188594b0 100644
--- a/db/migrate/20180503175054_add_indexes_to_project_mirror_data.rb
+++ b/db/migrate/20180503175054_add_indexes_to_project_mirror_data.rb
@@ -1,4 +1,4 @@
-class AddIndexesToProjectMirrorData < ActiveRecord::Migration
+class AddIndexesToProjectMirrorData < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180503193542_add_indexes_to_remote_mirror.rb b/db/migrate/20180503193542_add_indexes_to_remote_mirror.rb
index 4af42b4fb29..bdf05c4e69b 100644
--- a/db/migrate/20180503193542_add_indexes_to_remote_mirror.rb
+++ b/db/migrate/20180503193542_add_indexes_to_remote_mirror.rb
@@ -1,4 +1,4 @@
-class AddIndexesToRemoteMirror < ActiveRecord::Migration
+class AddIndexesToRemoteMirror < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180503193953_add_mirror_available_to_application_settings.rb b/db/migrate/20180503193953_add_mirror_available_to_application_settings.rb
index 25b9905b1a9..64f65cd23be 100644
--- a/db/migrate/20180503193953_add_mirror_available_to_application_settings.rb
+++ b/db/migrate/20180503193953_add_mirror_available_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddMirrorAvailableToApplicationSettings < ActiveRecord::Migration
+class AddMirrorAvailableToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180503200320_enable_prometheus_metrics_by_default.rb b/db/migrate/20180503200320_enable_prometheus_metrics_by_default.rb
index 2c8f86ff0f4..bab3b178713 100644
--- a/db/migrate/20180503200320_enable_prometheus_metrics_by_default.rb
+++ b/db/migrate/20180503200320_enable_prometheus_metrics_by_default.rb
@@ -1,4 +1,4 @@
-class EnablePrometheusMetricsByDefault < ActiveRecord::Migration
+class EnablePrometheusMetricsByDefault < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20180504195842_project_name_lower_index.rb b/db/migrate/20180504195842_project_name_lower_index.rb
index 74f3673bb03..3fe90c3fbb1 100644
--- a/db/migrate/20180504195842_project_name_lower_index.rb
+++ b/db/migrate/20180504195842_project_name_lower_index.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class ProjectNameLowerIndex < ActiveRecord::Migration
+class ProjectNameLowerIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20180508055821_make_remote_mirrors_disabled_by_default.rb b/db/migrate/20180508055821_make_remote_mirrors_disabled_by_default.rb
index 0d8a8357a1e..81aa18c8b86 100644
--- a/db/migrate/20180508055821_make_remote_mirrors_disabled_by_default.rb
+++ b/db/migrate/20180508055821_make_remote_mirrors_disabled_by_default.rb
@@ -1,4 +1,4 @@
-class MakeRemoteMirrorsDisabledByDefault < ActiveRecord::Migration
+class MakeRemoteMirrorsDisabledByDefault < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/20180508100222_add_not_null_constraint_to_project_mirror_data_foreign_key.rb b/db/migrate/20180508100222_add_not_null_constraint_to_project_mirror_data_foreign_key.rb
index 82087d15ccb..dba5d20f276 100644
--- a/db/migrate/20180508100222_add_not_null_constraint_to_project_mirror_data_foreign_key.rb
+++ b/db/migrate/20180508100222_add_not_null_constraint_to_project_mirror_data_foreign_key.rb
@@ -1,4 +1,4 @@
-class AddNotNullConstraintToProjectMirrorDataForeignKey < ActiveRecord::Migration
+class AddNotNullConstraintToProjectMirrorDataForeignKey < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180508102840_add_unique_constraint_to_project_mirror_data_project_id_index.rb b/db/migrate/20180508102840_add_unique_constraint_to_project_mirror_data_project_id_index.rb
index acb976b52fa..b225354ca43 100644
--- a/db/migrate/20180508102840_add_unique_constraint_to_project_mirror_data_project_id_index.rb
+++ b/db/migrate/20180508102840_add_unique_constraint_to_project_mirror_data_project_id_index.rb
@@ -1,4 +1,4 @@
-class AddUniqueConstraintToProjectMirrorDataProjectIdIndex < ActiveRecord::Migration
+class AddUniqueConstraintToProjectMirrorDataProjectIdIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180508135515_set_runner_type_not_null.rb b/db/migrate/20180508135515_set_runner_type_not_null.rb
index dd043ec7179..00c546c8f47 100644
--- a/db/migrate/20180508135515_set_runner_type_not_null.rb
+++ b/db/migrate/20180508135515_set_runner_type_not_null.rb
@@ -1,4 +1,4 @@
-class SetRunnerTypeNotNull < ActiveRecord::Migration
+class SetRunnerTypeNotNull < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180511090724_add_index_on_ci_runners_runner_type.rb b/db/migrate/20180511090724_add_index_on_ci_runners_runner_type.rb
index f3ed20fd243..4913b8602c9 100644
--- a/db/migrate/20180511090724_add_index_on_ci_runners_runner_type.rb
+++ b/db/migrate/20180511090724_add_index_on_ci_runners_runner_type.rb
@@ -1,4 +1,4 @@
-class AddIndexOnCiRunnersRunnerType < ActiveRecord::Migration
+class AddIndexOnCiRunnersRunnerType < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180511131058_create_clusters_applications_jupyter.rb b/db/migrate/20180511131058_create_clusters_applications_jupyter.rb
index f3923884e37..749aeeb4792 100644
--- a/db/migrate/20180511131058_create_clusters_applications_jupyter.rb
+++ b/db/migrate/20180511131058_create_clusters_applications_jupyter.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class CreateClustersApplicationsJupyter < ActiveRecord::Migration
+class CreateClustersApplicationsJupyter < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180515005612_add_squash_to_merge_requests.rb b/db/migrate/20180515005612_add_squash_to_merge_requests.rb
index fd85e968acd..14636d6fd8e 100644
--- a/db/migrate/20180515005612_add_squash_to_merge_requests.rb
+++ b/db/migrate/20180515005612_add_squash_to_merge_requests.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddSquashToMergeRequests < ActiveRecord::Migration
+class AddSquashToMergeRequests < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/migrate/20180515121227_create_notes_diff_files.rb b/db/migrate/20180515121227_create_notes_diff_files.rb
index efcd3bb9c7e..e50324d8599 100644
--- a/db/migrate/20180515121227_create_notes_diff_files.rb
+++ b/db/migrate/20180515121227_create_notes_diff_files.rb
@@ -1,4 +1,4 @@
-class CreateNotesDiffFiles < ActiveRecord::Migration
+class CreateNotesDiffFiles < ActiveRecord::Migration[4.2]
DOWNTIME = false
disable_ddl_transaction!
diff --git a/db/migrate/20180517082340_add_not_null_constraints_to_project_authorizations.rb b/db/migrate/20180517082340_add_not_null_constraints_to_project_authorizations.rb
index 3b7b877232b..36f4770ff32 100644
--- a/db/migrate/20180517082340_add_not_null_constraints_to_project_authorizations.rb
+++ b/db/migrate/20180517082340_add_not_null_constraints_to_project_authorizations.rb
@@ -1,4 +1,4 @@
-class AddNotNullConstraintsToProjectAuthorizations < ActiveRecord::Migration
+class AddNotNullConstraintsToProjectAuthorizations < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20180523042841_rename_merge_requests_allow_maintainer_to_push.rb b/db/migrate/20180523042841_rename_merge_requests_allow_maintainer_to_push.rb
index 41bc7b71694..131dca1fbc2 100644
--- a/db/migrate/20180523042841_rename_merge_requests_allow_maintainer_to_push.rb
+++ b/db/migrate/20180523042841_rename_merge_requests_allow_maintainer_to_push.rb
@@ -1,4 +1,4 @@
-class RenameMergeRequestsAllowMaintainerToPush < ActiveRecord::Migration
+class RenameMergeRequestsAllowMaintainerToPush < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180524132016_merge_requests_target_id_iid_state_partial_index.rb b/db/migrate/20180524132016_merge_requests_target_id_iid_state_partial_index.rb
index cee576b91c8..bff4690427e 100644
--- a/db/migrate/20180524132016_merge_requests_target_id_iid_state_partial_index.rb
+++ b/db/migrate/20180524132016_merge_requests_target_id_iid_state_partial_index.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MergeRequestsTargetIdIidStatePartialIndex < ActiveRecord::Migration
+class MergeRequestsTargetIdIidStatePartialIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20180529093006_ensure_remote_mirror_columns.rb b/db/migrate/20180529093006_ensure_remote_mirror_columns.rb
index 22e9482cb1d..207e1f089fb 100644
--- a/db/migrate/20180529093006_ensure_remote_mirror_columns.rb
+++ b/db/migrate/20180529093006_ensure_remote_mirror_columns.rb
@@ -1,4 +1,4 @@
-class EnsureRemoteMirrorColumns < ActiveRecord::Migration
+class EnsureRemoteMirrorColumns < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180530135500_add_index_to_stages_position.rb b/db/migrate/20180530135500_add_index_to_stages_position.rb
index 61150f33a25..eabf94ab8ec 100644
--- a/db/migrate/20180530135500_add_index_to_stages_position.rb
+++ b/db/migrate/20180530135500_add_index_to_stages_position.rb
@@ -1,4 +1,4 @@
-class AddIndexToStagesPosition < ActiveRecord::Migration
+class AddIndexToStagesPosition < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180531185349_add_repository_languages.rb b/db/migrate/20180531185349_add_repository_languages.rb
index bfcfb618c87..26a01c3bb26 100644
--- a/db/migrate/20180531185349_add_repository_languages.rb
+++ b/db/migrate/20180531185349_add_repository_languages.rb
@@ -1,4 +1,4 @@
-class AddRepositoryLanguages < ActiveRecord::Migration
+class AddRepositoryLanguages < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180531220618_change_default_value_for_dsa_key_restriction.rb b/db/migrate/20180531220618_change_default_value_for_dsa_key_restriction.rb
index dbbbcd1f622..cf621c46f2b 100644
--- a/db/migrate/20180531220618_change_default_value_for_dsa_key_restriction.rb
+++ b/db/migrate/20180531220618_change_default_value_for_dsa_key_restriction.rb
@@ -1,4 +1,4 @@
-class ChangeDefaultValueForDsaKeyRestriction < ActiveRecord::Migration
+class ChangeDefaultValueForDsaKeyRestriction < ActiveRecord::Migration[4.2]
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
diff --git a/db/migrate/20180601213245_add_deploy_strategy_to_project_auto_devops.rb b/db/migrate/20180601213245_add_deploy_strategy_to_project_auto_devops.rb
index 6f50d428965..78a3617ec93 100644
--- a/db/migrate/20180601213245_add_deploy_strategy_to_project_auto_devops.rb
+++ b/db/migrate/20180601213245_add_deploy_strategy_to_project_auto_devops.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddDeployStrategyToProjectAutoDevops < ActiveRecord::Migration
+class AddDeployStrategyToProjectAutoDevops < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20180607071808_add_push_events_branch_filter_to_web_hooks.rb b/db/migrate/20180607071808_add_push_events_branch_filter_to_web_hooks.rb
index 6a69460e611..e6a1daaffc2 100644
--- a/db/migrate/20180607071808_add_push_events_branch_filter_to_web_hooks.rb
+++ b/db/migrate/20180607071808_add_push_events_branch_filter_to_web_hooks.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddPushEventsBranchFilterToWebHooks < ActiveRecord::Migration
+class AddPushEventsBranchFilterToWebHooks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180608091413_add_group_to_todos.rb b/db/migrate/20180608091413_add_group_to_todos.rb
index 20ba4849057..7f8efd78c59 100644
--- a/db/migrate/20180608091413_add_group_to_todos.rb
+++ b/db/migrate/20180608091413_add_group_to_todos.rb
@@ -1,4 +1,4 @@
-class AddGroupToTodos < ActiveRecord::Migration
+class AddGroupToTodos < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180608110058_rename_merge_requests_allow_collaboration.rb b/db/migrate/20180608110058_rename_merge_requests_allow_collaboration.rb
index 36f2a593fbe..0f2d5ba3a5e 100644
--- a/db/migrate/20180608110058_rename_merge_requests_allow_collaboration.rb
+++ b/db/migrate/20180608110058_rename_merge_requests_allow_collaboration.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RenameMergeRequestsAllowCollaboration < ActiveRecord::Migration
+class RenameMergeRequestsAllowCollaboration < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20180612103626_add_columns_for_helm_tiller_certificates.rb b/db/migrate/20180612103626_add_columns_for_helm_tiller_certificates.rb
index 57cea18abcd..d7273dff48e 100644
--- a/db/migrate/20180612103626_add_columns_for_helm_tiller_certificates.rb
+++ b/db/migrate/20180612103626_add_columns_for_helm_tiller_certificates.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-class AddColumnsForHelmTillerCertificates < ActiveRecord::Migration
+class AddColumnsForHelmTillerCertificates < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180613081317_create_ci_builds_runner_session.rb b/db/migrate/20180613081317_create_ci_builds_runner_session.rb
index e550c07b9ab..eb41f76b105 100644
--- a/db/migrate/20180613081317_create_ci_builds_runner_session.rb
+++ b/db/migrate/20180613081317_create_ci_builds_runner_session.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class CreateCiBuildsRunnerSession < ActiveRecord::Migration
+class CreateCiBuildsRunnerSession < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20180625113853_create_import_export_uploads.rb b/db/migrate/20180625113853_create_import_export_uploads.rb
index be42304b0ae..d76b3e8cc15 100644
--- a/db/migrate/20180625113853_create_import_export_uploads.rb
+++ b/db/migrate/20180625113853_create_import_export_uploads.rb
@@ -1,4 +1,4 @@
-class CreateImportExportUploads < ActiveRecord::Migration
+class CreateImportExportUploads < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20180626125654_add_index_on_deployable_for_deployments.rb b/db/migrate/20180626125654_add_index_on_deployable_for_deployments.rb
index a0e3a228f6c..0fc14b43fae 100644
--- a/db/migrate/20180626125654_add_index_on_deployable_for_deployments.rb
+++ b/db/migrate/20180626125654_add_index_on_deployable_for_deployments.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddIndexOnDeployableForDeployments < ActiveRecord::Migration
+class AddIndexOnDeployableForDeployments < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180628124813_alter_web_hook_logs_indexes.rb b/db/migrate/20180628124813_alter_web_hook_logs_indexes.rb
index 1878e76811d..64ef165c5e6 100644
--- a/db/migrate/20180628124813_alter_web_hook_logs_indexes.rb
+++ b/db/migrate/20180628124813_alter_web_hook_logs_indexes.rb
@@ -3,7 +3,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AlterWebHookLogsIndexes < ActiveRecord::Migration
+class AlterWebHookLogsIndexes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
@@ -12,7 +12,7 @@ class AlterWebHookLogsIndexes < ActiveRecord::Migration
disable_ddl_transaction!
# "created_at" comes first so the Sidekiq worker pruning old webhook logs can
- # use a composite index index.
+ # use a composite index.
#
# We leave the old standalone index on "web_hook_id" in place so future code
# that doesn't care about "created_at" can still use that index.
diff --git a/db/migrate/20180629153018_create_site_statistics.rb b/db/migrate/20180629153018_create_site_statistics.rb
index 085ce1ba64b..60a32b3b2a7 100644
--- a/db/migrate/20180629153018_create_site_statistics.rb
+++ b/db/migrate/20180629153018_create_site_statistics.rb
@@ -1,4 +1,4 @@
-class CreateSiteStatistics < ActiveRecord::Migration
+class CreateSiteStatistics < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180702124358_remove_orphaned_routes.rb b/db/migrate/20180702124358_remove_orphaned_routes.rb
index 4068e479b6c..62c15f9cd00 100644
--- a/db/migrate/20180702124358_remove_orphaned_routes.rb
+++ b/db/migrate/20180702124358_remove_orphaned_routes.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveOrphanedRoutes < ActiveRecord::Migration
+class RemoveOrphanedRoutes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180702134423_generate_missing_routes.rb b/db/migrate/20180702134423_generate_missing_routes.rb
index 994725f9bd1..a440bc3179c 100644
--- a/db/migrate/20180702134423_generate_missing_routes.rb
+++ b/db/migrate/20180702134423_generate_missing_routes.rb
@@ -7,7 +7,7 @@
# On GitLab.com this would insert 611 project routes, and 0 namespace routes.
# The exact number could vary per instance, so we take care of both just in
# case.
-class GenerateMissingRoutes < ActiveRecord::Migration
+class GenerateMissingRoutes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180704204006_add_hide_third_party_offers_to_application_settings.rb b/db/migrate/20180704204006_add_hide_third_party_offers_to_application_settings.rb
index 6631c5d1b6c..03afbe217b5 100644
--- a/db/migrate/20180704204006_add_hide_third_party_offers_to_application_settings.rb
+++ b/db/migrate/20180704204006_add_hide_third_party_offers_to_application_settings.rb
@@ -1,4 +1,4 @@
-class AddHideThirdPartyOffersToApplicationSettings < ActiveRecord::Migration
+class AddHideThirdPartyOffersToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180705160945_add_file_format_to_ci_job_artifacts.rb b/db/migrate/20180705160945_add_file_format_to_ci_job_artifacts.rb
index 63c188693f3..938438841a5 100644
--- a/db/migrate/20180705160945_add_file_format_to_ci_job_artifacts.rb
+++ b/db/migrate/20180705160945_add_file_format_to_ci_job_artifacts.rb
@@ -1,4 +1,4 @@
-class AddFileFormatToCiJobArtifacts < ActiveRecord::Migration
+class AddFileFormatToCiJobArtifacts < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20180710162338_add_foreign_key_from_notification_settings_to_users.rb b/db/migrate/20180710162338_add_foreign_key_from_notification_settings_to_users.rb
index 91656f194e5..79691f2b24c 100644
--- a/db/migrate/20180710162338_add_foreign_key_from_notification_settings_to_users.rb
+++ b/db/migrate/20180710162338_add_foreign_key_from_notification_settings_to_users.rb
@@ -1,4 +1,4 @@
-class AddForeignKeyFromNotificationSettingsToUsers < ActiveRecord::Migration
+class AddForeignKeyFromNotificationSettingsToUsers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
class NotificationSetting < ActiveRecord::Base
diff --git a/db/migrate/20180711103851_drop_duplicate_protected_tags.rb b/db/migrate/20180711103851_drop_duplicate_protected_tags.rb
index 8fa2137551e..6166aa65f1f 100644
--- a/db/migrate/20180711103851_drop_duplicate_protected_tags.rb
+++ b/db/migrate/20180711103851_drop_duplicate_protected_tags.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class DropDuplicateProtectedTags < ActiveRecord::Migration
+class DropDuplicateProtectedTags < ActiveRecord::Migration[4.2]
DOWNTIME = false
disable_ddl_transaction!
diff --git a/db/migrate/20180711103922_add_protected_tags_index.rb b/db/migrate/20180711103922_add_protected_tags_index.rb
index 7ed2258ebaf..ef81ca633c3 100644
--- a/db/migrate/20180711103922_add_protected_tags_index.rb
+++ b/db/migrate/20180711103922_add_protected_tags_index.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddProtectedTagsIndex < ActiveRecord::Migration
+class AddProtectedTagsIndex < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180713092803_create_user_statuses.rb b/db/migrate/20180713092803_create_user_statuses.rb
index cbe21b89ad9..43b96805c1e 100644
--- a/db/migrate/20180713092803_create_user_statuses.rb
+++ b/db/migrate/20180713092803_create_user_statuses.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class CreateUserStatuses < ActiveRecord::Migration
+class CreateUserStatuses < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180717125853_remove_restricted_todos.rb b/db/migrate/20180717125853_remove_restricted_todos.rb
index fdf43921a73..1d4bbf6571e 100644
--- a/db/migrate/20180717125853_remove_restricted_todos.rb
+++ b/db/migrate/20180717125853_remove_restricted_todos.rb
@@ -2,7 +2,7 @@
# for more information on how to write migrations for GitLab.
# frozen_string_literal: true
-class RemoveRestrictedTodos < ActiveRecord::Migration
+class RemoveRestrictedTodos < ActiveRecord::Migration[4.2]
DOWNTIME = false
disable_ddl_transaction!
diff --git a/db/migrate/20180718005113_add_instance_statistics_visibility_to_application_setting.rb b/db/migrate/20180718005113_add_instance_statistics_visibility_to_application_setting.rb
index 4b6c1f74346..ed5fa58b481 100644
--- a/db/migrate/20180718005113_add_instance_statistics_visibility_to_application_setting.rb
+++ b/db/migrate/20180718005113_add_instance_statistics_visibility_to_application_setting.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class AddInstanceStatisticsVisibilityToApplicationSetting < ActiveRecord::Migration
+class AddInstanceStatisticsVisibilityToApplicationSetting < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180720023512_add_receive_max_input_size_to_application_settings.rb b/db/migrate/20180720023512_add_receive_max_input_size_to_application_settings.rb
index 4ed851a0780..0cf3c78507e 100644
--- a/db/migrate/20180720023512_add_receive_max_input_size_to_application_settings.rb
+++ b/db/migrate/20180720023512_add_receive_max_input_size_to_application_settings.rb
@@ -2,7 +2,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddReceiveMaxInputSizeToApplicationSettings < ActiveRecord::Migration
+class AddReceiveMaxInputSizeToApplicationSettings < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20180722103201_add_private_profile_to_users.rb b/db/migrate/20180722103201_add_private_profile_to_users.rb
index 4f7ef1322d8..c8d917065bb 100644
--- a/db/migrate/20180722103201_add_private_profile_to_users.rb
+++ b/db/migrate/20180722103201_add_private_profile_to_users.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddPrivateProfileToUsers < ActiveRecord::Migration
+class AddPrivateProfileToUsers < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20180723135214_add_web_ide_client_side_preview_enabled_to_application_settings.rb b/db/migrate/20180723135214_add_web_ide_client_side_preview_enabled_to_application_settings.rb
index 1ebb91da00c..23b8e04674a 100644
--- a/db/migrate/20180723135214_add_web_ide_client_side_preview_enabled_to_application_settings.rb
+++ b/db/migrate/20180723135214_add_web_ide_client_side_preview_enabled_to_application_settings.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class AddWebIdeClientSidePreviewEnabledToApplicationSettings < ActiveRecord::Migration
+class AddWebIdeClientSidePreviewEnabledToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180726172057_create_resource_label_events.rb b/db/migrate/20180726172057_create_resource_label_events.rb
index 2ef7078d898..550e35d6f90 100644
--- a/db/migrate/20180726172057_create_resource_label_events.rb
+++ b/db/migrate/20180726172057_create_resource_label_events.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class CreateResourceLabelEvents < ActiveRecord::Migration
+class CreateResourceLabelEvents < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180807153545_remove_redundant_status_index_on_ci_builds.rb b/db/migrate/20180807153545_remove_redundant_status_index_on_ci_builds.rb
index f4f7cb6f8ca..c957fc2f6fc 100644
--- a/db/migrate/20180807153545_remove_redundant_status_index_on_ci_builds.rb
+++ b/db/migrate/20180807153545_remove_redundant_status_index_on_ci_builds.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class RemoveRedundantStatusIndexOnCiBuilds < ActiveRecord::Migration
+class RemoveRedundantStatusIndexOnCiBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180808162000_add_user_show_add_ssh_key_message_to_application_settings.rb b/db/migrate/20180808162000_add_user_show_add_ssh_key_message_to_application_settings.rb
index e3019af2cc9..946d99a4c5f 100644
--- a/db/migrate/20180808162000_add_user_show_add_ssh_key_message_to_application_settings.rb
+++ b/db/migrate/20180808162000_add_user_show_add_ssh_key_message_to_application_settings.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddUserShowAddSshKeyMessageToApplicationSettings < ActiveRecord::Migration
+class AddUserShowAddSshKeyMessageToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20180813101999_change_default_of_auto_devops_instance_wide.rb b/db/migrate/20180813101999_change_default_of_auto_devops_instance_wide.rb
index 05d1124f5c4..da101bc76e3 100644
--- a/db/migrate/20180813101999_change_default_of_auto_devops_instance_wide.rb
+++ b/db/migrate/20180813101999_change_default_of_auto_devops_instance_wide.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ChangeDefaultOfAutoDevopsInstanceWide < ActiveRecord::Migration
+class ChangeDefaultOfAutoDevopsInstanceWide < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180813102000_enable_auto_devops_instance_wide_for_everyone.rb b/db/migrate/20180813102000_enable_auto_devops_instance_wide_for_everyone.rb
index 21fb62806b3..1531fad2c6c 100644
--- a/db/migrate/20180813102000_enable_auto_devops_instance_wide_for_everyone.rb
+++ b/db/migrate/20180813102000_enable_auto_devops_instance_wide_for_everyone.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class EnableAutoDevopsInstanceWideForEveryone < ActiveRecord::Migration
+class EnableAutoDevopsInstanceWideForEveryone < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180814153625_add_commit_email_to_users.rb b/db/migrate/20180814153625_add_commit_email_to_users.rb
index 5c87d73688e..4d9217ea504 100644
--- a/db/migrate/20180814153625_add_commit_email_to_users.rb
+++ b/db/migrate/20180814153625_add_commit_email_to_users.rb
@@ -3,7 +3,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddCommitEmailToUsers < ActiveRecord::Migration
+class AddCommitEmailToUsers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/migrate/20180815040323_add_authorization_type_to_cluster_platforms_kubernetes.rb b/db/migrate/20180815040323_add_authorization_type_to_cluster_platforms_kubernetes.rb
index 6397d6dd99f..44125b4696a 100644
--- a/db/migrate/20180815040323_add_authorization_type_to_cluster_platforms_kubernetes.rb
+++ b/db/migrate/20180815040323_add_authorization_type_to_cluster_platforms_kubernetes.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class AddAuthorizationTypeToClusterPlatformsKubernetes < ActiveRecord::Migration
+class AddAuthorizationTypeToClusterPlatformsKubernetes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180815160409_add_file_location_to_ci_job_artifacts.rb b/db/migrate/20180815160409_add_file_location_to_ci_job_artifacts.rb
index 620342005fe..389101902d0 100644
--- a/db/migrate/20180815160409_add_file_location_to_ci_job_artifacts.rb
+++ b/db/migrate/20180815160409_add_file_location_to_ci_job_artifacts.rb
@@ -1,4 +1,4 @@
-class AddFileLocationToCiJobArtifacts < ActiveRecord::Migration
+class AddFileLocationToCiJobArtifacts < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180815170510_add_partial_index_to_ci_builds_artifacts_file.rb b/db/migrate/20180815170510_add_partial_index_to_ci_builds_artifacts_file.rb
index 5e041ea6559..237e6ba4559 100644
--- a/db/migrate/20180815170510_add_partial_index_to_ci_builds_artifacts_file.rb
+++ b/db/migrate/20180815170510_add_partial_index_to_ci_builds_artifacts_file.rb
@@ -1,4 +1,4 @@
-class AddPartialIndexToCiBuildsArtifactsFile < ActiveRecord::Migration
+class AddPartialIndexToCiBuildsArtifactsFile < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180815175440_add_index_on_list_type.rb b/db/migrate/20180815175440_add_index_on_list_type.rb
index aad805e436e..3fe0f6b8de5 100644
--- a/db/migrate/20180815175440_add_index_on_list_type.rb
+++ b/db/migrate/20180815175440_add_index_on_list_type.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-class AddIndexOnListType < ActiveRecord::Migration
+class AddIndexOnListType < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180831164904_fix_prometheus_metric_query_limits.rb b/db/migrate/20180831164904_fix_prometheus_metric_query_limits.rb
index 28c92e7c7ac..80c4d11a38e 100644
--- a/db/migrate/20180831164904_fix_prometheus_metric_query_limits.rb
+++ b/db/migrate/20180831164904_fix_prometheus_metric_query_limits.rb
@@ -4,7 +4,7 @@
# for more information on how to write migrations for GitLab.
require Rails.root.join('db/migrate/prometheus_metrics_limits_to_mysql')
-class FixPrometheusMetricQueryLimits < ActiveRecord::Migration
+class FixPrometheusMetricQueryLimits < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180831164905_add_common_to_prometheus_metrics.rb b/db/migrate/20180831164905_add_common_to_prometheus_metrics.rb
index e21c156fff6..5eb77d0480d 100644
--- a/db/migrate/20180831164905_add_common_to_prometheus_metrics.rb
+++ b/db/migrate/20180831164905_add_common_to_prometheus_metrics.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class AddCommonToPrometheusMetrics < ActiveRecord::Migration
+class AddCommonToPrometheusMetrics < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180831164907_add_index_on_common_for_prometheus_metrics.rb b/db/migrate/20180831164907_add_index_on_common_for_prometheus_metrics.rb
index fdbaaf67b87..5758321891a 100644
--- a/db/migrate/20180831164907_add_index_on_common_for_prometheus_metrics.rb
+++ b/db/migrate/20180831164907_add_index_on_common_for_prometheus_metrics.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class AddIndexOnCommonForPrometheusMetrics < ActiveRecord::Migration
+class AddIndexOnCommonForPrometheusMetrics < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180831164908_add_identifier_to_prometheus_metric.rb b/db/migrate/20180831164908_add_identifier_to_prometheus_metric.rb
index 67de990757e..7aa5950249c 100644
--- a/db/migrate/20180831164908_add_identifier_to_prometheus_metric.rb
+++ b/db/migrate/20180831164908_add_identifier_to_prometheus_metric.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class AddIdentifierToPrometheusMetric < ActiveRecord::Migration
+class AddIdentifierToPrometheusMetric < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180831164909_add_index_for_identifier_to_prometheus_metric.rb b/db/migrate/20180831164909_add_index_for_identifier_to_prometheus_metric.rb
index b30c24ccafe..1f6cfc181f4 100644
--- a/db/migrate/20180831164909_add_index_for_identifier_to_prometheus_metric.rb
+++ b/db/migrate/20180831164909_add_index_for_identifier_to_prometheus_metric.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class AddIndexForIdentifierToPrometheusMetric < ActiveRecord::Migration
+class AddIndexForIdentifierToPrometheusMetric < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180831164910_import_common_metrics.rb b/db/migrate/20180831164910_import_common_metrics.rb
index 72658c09b8e..f67d5f40aad 100644
--- a/db/migrate/20180831164910_import_common_metrics.rb
+++ b/db/migrate/20180831164910_import_common_metrics.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class ImportCommonMetrics < ActiveRecord::Migration
+class ImportCommonMetrics < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
require Rails.root.join('db/importers/common_metrics_importer.rb')
diff --git a/db/migrate/20180901171833_add_project_config_source_status_index_to_pipeline.rb b/db/migrate/20180901171833_add_project_config_source_status_index_to_pipeline.rb
index 99dfcc94b12..f2136657d95 100644
--- a/db/migrate/20180901171833_add_project_config_source_status_index_to_pipeline.rb
+++ b/db/migrate/20180901171833_add_project_config_source_status_index_to_pipeline.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class AddProjectConfigSourceStatusIndexToPipeline < ActiveRecord::Migration
+class AddProjectConfigSourceStatusIndexToPipeline < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180901200537_add_resource_label_event_reference_fields.rb b/db/migrate/20180901200537_add_resource_label_event_reference_fields.rb
index 264970ceed8..c8875e16914 100644
--- a/db/migrate/20180901200537_add_resource_label_event_reference_fields.rb
+++ b/db/migrate/20180901200537_add_resource_label_event_reference_fields.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class AddResourceLabelEventReferenceFields < ActiveRecord::Migration
+class AddResourceLabelEventReferenceFields < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/migrate/20180906101639_add_user_ping_consent_to_application_settings.rb b/db/migrate/20180906101639_add_user_ping_consent_to_application_settings.rb
index 5d0e67d2648..334efa12e7b 100644
--- a/db/migrate/20180906101639_add_user_ping_consent_to_application_settings.rb
+++ b/db/migrate/20180906101639_add_user_ping_consent_to_application_settings.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class AddUserPingConsentToApplicationSettings < ActiveRecord::Migration
+class AddUserPingConsentToApplicationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180907015926_add_legacy_abac_to_cluster_providers_gcp.rb b/db/migrate/20180907015926_add_legacy_abac_to_cluster_providers_gcp.rb
index 933047e32de..c57611a0f7d 100644
--- a/db/migrate/20180907015926_add_legacy_abac_to_cluster_providers_gcp.rb
+++ b/db/migrate/20180907015926_add_legacy_abac_to_cluster_providers_gcp.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class AddLegacyAbacToClusterProvidersGcp < ActiveRecord::Migration
+class AddLegacyAbacToClusterProvidersGcp < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/migrate/20180910115836_add_attr_encrypted_columns_to_web_hook.rb b/db/migrate/20180910115836_add_attr_encrypted_columns_to_web_hook.rb
new file mode 100644
index 00000000000..ca8dbdba2bb
--- /dev/null
+++ b/db/migrate/20180910115836_add_attr_encrypted_columns_to_web_hook.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddAttrEncryptedColumnsToWebHook < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :web_hooks, :encrypted_token, :string
+ add_column :web_hooks, :encrypted_token_iv, :string
+
+ add_column :web_hooks, :encrypted_url, :string
+ add_column :web_hooks, :encrypted_url_iv, :string
+ end
+end
diff --git a/db/migrate/20180910153412_add_token_digest_to_personal_access_tokens.rb b/db/migrate/20180910153412_add_token_digest_to_personal_access_tokens.rb
new file mode 100644
index 00000000000..142e454832f
--- /dev/null
+++ b/db/migrate/20180910153412_add_token_digest_to_personal_access_tokens.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddTokenDigestToPersonalAccessTokens < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ change_column :personal_access_tokens, :token, :string, null: true
+
+ add_column :personal_access_tokens, :token_digest, :string
+ end
+
+ def down
+ remove_column :personal_access_tokens, :token_digest
+
+ change_column :personal_access_tokens, :token, :string, null: false
+ end
+end
diff --git a/db/migrate/20180910153413_add_index_to_token_digest_on_personal_access_tokens.rb b/db/migrate/20180910153413_add_index_to_token_digest_on_personal_access_tokens.rb
new file mode 100644
index 00000000000..d501b07614a
--- /dev/null
+++ b/db/migrate/20180910153413_add_index_to_token_digest_on_personal_access_tokens.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddIndexToTokenDigestOnPersonalAccessTokens < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :personal_access_tokens, :token_digest, unique: true
+ end
+
+ def down
+ remove_concurrent_index :personal_access_tokens, :token_digest if index_exists?(:personal_access_tokens, :token_digest)
+ end
+end
diff --git a/db/migrate/20180912111628_add_knative_application.rb b/db/migrate/20180912111628_add_knative_application.rb
new file mode 100644
index 00000000000..86d9100d2e7
--- /dev/null
+++ b/db/migrate/20180912111628_add_knative_application.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddKnativeApplication < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table "clusters_applications_knative" do |t|
+ t.references :cluster, null: false, unique: true, foreign_key: { on_delete: :cascade }
+
+ t.datetime_with_timezone "created_at", null: false
+ t.datetime_with_timezone "updated_at", null: false
+ t.integer "status", null: false
+ t.string "version", null: false
+ t.string "hostname"
+ t.text "status_reason"
+ end
+ end
+end
diff --git a/db/migrate/20180916011959_add_index_pipelines_project_id_source.rb b/db/migrate/20180916011959_add_index_pipelines_project_id_source.rb
new file mode 100644
index 00000000000..5b71c79ac86
--- /dev/null
+++ b/db/migrate/20180916011959_add_index_pipelines_project_id_source.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddIndexPipelinesProjectIdSource < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_pipelines, [:project_id, :source]
+ end
+
+ def down
+ remove_concurrent_index :ci_pipelines, [:project_id, :source]
+ end
+end
diff --git a/db/migrate/20180924141949_add_diff_max_patch_bytes_to_application_settings.rb b/db/migrate/20180924141949_add_diff_max_patch_bytes_to_application_settings.rb
new file mode 100644
index 00000000000..5dac5f0d100
--- /dev/null
+++ b/db/migrate/20180924141949_add_diff_max_patch_bytes_to_application_settings.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddDiffMaxPatchBytesToApplicationSettings < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default(:application_settings,
+ :diff_max_patch_bytes,
+ :integer,
+ default: 100.kilobytes,
+ allow_null: false)
+ end
+
+ def down
+ remove_column(:application_settings, :diff_max_patch_bytes)
+ end
+end
diff --git a/db/migrate/20180924190739_add_scheduled_at_to_ci_builds.rb b/db/migrate/20180924190739_add_scheduled_at_to_ci_builds.rb
new file mode 100644
index 00000000000..cd2f8b59d41
--- /dev/null
+++ b/db/migrate/20180924190739_add_scheduled_at_to_ci_builds.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddScheduledAtToCiBuilds < ActiveRecord::Migration[4.2]
+ DOWNTIME = false
+
+ def change
+ add_column :ci_builds, :scheduled_at, :datetime_with_timezone
+ end
+end
diff --git a/db/migrate/20180924201039_add_partial_index_to_scheduled_at.rb b/db/migrate/20180924201039_add_partial_index_to_scheduled_at.rb
new file mode 100644
index 00000000000..378fc4e5fea
--- /dev/null
+++ b/db/migrate/20180924201039_add_partial_index_to_scheduled_at.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddPartialIndexToScheduledAt < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'partial_index_ci_builds_on_scheduled_at_with_scheduled_jobs'.freeze
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index(:ci_builds, :scheduled_at, where: "scheduled_at IS NOT NULL AND type = 'Ci::Build' AND status = 'scheduled'", name: INDEX_NAME)
+ end
+
+ def down
+ remove_concurrent_index_by_name(:ci_builds, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20180925200829_create_user_preferences.rb b/db/migrate/20180925200829_create_user_preferences.rb
new file mode 100644
index 00000000000..b46df8157a6
--- /dev/null
+++ b/db/migrate/20180925200829_create_user_preferences.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class CreateUserPreferences < ActiveRecord::Migration[4.2]
+ DOWNTIME = false
+
+ class UserPreference < ActiveRecord::Base
+ self.table_name = 'user_preferences'
+
+ NOTES_FILTERS = { all_notes: 0, comments: 1 }.freeze
+ end
+
+ def change
+ create_table :user_preferences do |t|
+ t.references :user,
+ null: false,
+ index: { unique: true },
+ foreign_key: { on_delete: :cascade }
+
+ t.integer :issue_notes_filter,
+ default: UserPreference::NOTES_FILTERS[:all_notes],
+ null: false, limit: 2
+
+ t.integer :merge_request_notes_filter,
+ default: UserPreference::NOTES_FILTERS[:all_notes],
+ null: false,
+ limit: 2
+
+ t.timestamps_with_timezone null: false
+ end
+ end
+end
diff --git a/db/migrate/20180927073410_add_index_to_project_deploy_tokens_deploy_token_id.rb b/db/migrate/20180927073410_add_index_to_project_deploy_tokens_deploy_token_id.rb
new file mode 100644
index 00000000000..80577c52a01
--- /dev/null
+++ b/db/migrate/20180927073410_add_index_to_project_deploy_tokens_deploy_token_id.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexToProjectDeployTokensDeployTokenId < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ # MySQL already has index inserted
+ add_concurrent_index :project_deploy_tokens, :deploy_token_id if Gitlab::Database.postgresql?
+ end
+
+ def down
+ remove_concurrent_index(:project_deploy_tokens, :deploy_token_id) if Gitlab::Database.postgresql?
+ end
+end
diff --git a/db/migrate/20181002172433_remove_restricted_todos_with_cte.rb b/db/migrate/20181002172433_remove_restricted_todos_with_cte.rb
new file mode 100644
index 00000000000..7826c8d802e
--- /dev/null
+++ b/db/migrate/20181002172433_remove_restricted_todos_with_cte.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+# rescheduling of the revised RemoveRestrictedTodos background migration
+class RemoveRestrictedTodosWithCte < ActiveRecord::Migration[4.2]
+ DOWNTIME = false
+ disable_ddl_transaction!
+
+ MIGRATION = 'RemoveRestrictedTodos'.freeze
+ BATCH_SIZE = 1000
+ DELAY_INTERVAL = 5.minutes.to_i
+
+ class Project < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'projects'
+ end
+
+ def up
+ Project.where('EXISTS (SELECT 1 FROM todos WHERE todos.project_id = projects.id)')
+ .each_batch(of: BATCH_SIZE) do |batch, index|
+ range = batch.pluck('MIN(id)', 'MAX(id)').first
+
+ BackgroundMigrationWorker.perform_in(index * DELAY_INTERVAL, MIGRATION, range)
+ end
+ end
+
+ def down
+ # nothing to do
+ end
+end
diff --git a/db/migrate/20181005110927_add_index_to_lfs_objects_file_store.rb b/db/migrate/20181005110927_add_index_to_lfs_objects_file_store.rb
new file mode 100644
index 00000000000..ff17a0a567d
--- /dev/null
+++ b/db/migrate/20181005110927_add_index_to_lfs_objects_file_store.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddIndexToLfsObjectsFileStore < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :lfs_objects, :file_store
+ end
+
+ def down
+ remove_concurrent_index :lfs_objects, :file_store
+ end
+end
diff --git a/db/migrate/20181005125926_add_index_to_uploads_store.rb b/db/migrate/20181005125926_add_index_to_uploads_store.rb
new file mode 100644
index 00000000000..d9e31225b6f
--- /dev/null
+++ b/db/migrate/20181005125926_add_index_to_uploads_store.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddIndexToUploadsStore < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :uploads, :store
+ end
+
+ def down
+ remove_concurrent_index :uploads, :store
+ end
+end
diff --git a/db/migrate/20181009190428_create_clusters_kubernetes_namespaces.rb b/db/migrate/20181009190428_create_clusters_kubernetes_namespaces.rb
new file mode 100644
index 00000000000..62ad6c63d0a
--- /dev/null
+++ b/db/migrate/20181009190428_create_clusters_kubernetes_namespaces.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class CreateClustersKubernetesNamespaces < ActiveRecord::Migration[4.2]
+ DOWNTIME = false
+ INDEX_NAME = 'kubernetes_namespaces_cluster_and_namespace'
+
+ def change
+ create_table :clusters_kubernetes_namespaces, id: :bigserial do |t|
+ t.references :cluster, null: false, index: true, foreign_key: { on_delete: :cascade }
+ t.references :project, index: true, foreign_key: { on_delete: :nullify }
+ t.references :cluster_project, index: true, foreign_key: { on_delete: :nullify }
+
+ t.timestamps_with_timezone null: false
+
+ t.string :encrypted_service_account_token_iv
+ t.string :namespace, null: false
+ t.string :service_account_name
+
+ t.text :encrypted_service_account_token
+
+ t.index [:cluster_id, :namespace], name: INDEX_NAME, unique: true
+ end
+ end
+end
diff --git a/db/migrate/20181010235606_create_board_project_recent_visits.rb b/db/migrate/20181010235606_create_board_project_recent_visits.rb
new file mode 100644
index 00000000000..07bfbdda26b
--- /dev/null
+++ b/db/migrate/20181010235606_create_board_project_recent_visits.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class CreateBoardProjectRecentVisits < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :board_project_recent_visits, id: :bigserial do |t|
+ t.timestamps_with_timezone null: false
+
+ t.references :user, index: true, foreign_key: { on_delete: :cascade }
+ t.references :project, index: true, foreign_key: { on_delete: :cascade }
+ t.references :board, index: true, foreign_key: { on_delete: :cascade }
+ end
+
+ add_index :board_project_recent_visits, [:user_id, :project_id, :board_id], unique: true, name: 'index_board_project_recent_visits_on_user_project_and_board'
+ end
+end
diff --git a/db/migrate/20181014203236_create_cluster_groups.rb b/db/migrate/20181014203236_create_cluster_groups.rb
new file mode 100644
index 00000000000..33ae9a4a478
--- /dev/null
+++ b/db/migrate/20181014203236_create_cluster_groups.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class CreateClusterGroups < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :cluster_groups do |t|
+ t.references :cluster, null: false, foreign_key: { on_delete: :cascade }
+ t.references :group, null: false, index: true
+
+ t.index [:cluster_id, :group_id], unique: true
+ t.foreign_key :namespaces, column: :group_id, on_delete: :cascade
+ end
+ end
+end
diff --git a/db/migrate/20181015155839_add_finished_at_to_deployments.rb b/db/migrate/20181015155839_add_finished_at_to_deployments.rb
new file mode 100644
index 00000000000..bb8d6cdcf2c
--- /dev/null
+++ b/db/migrate/20181015155839_add_finished_at_to_deployments.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddFinishedAtToDeployments < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ add_column :deployments, :finished_at, :datetime_with_timezone
+ end
+
+ def down
+ remove_column :deployments, :finished_at, :datetime_with_timezone
+ end
+end
diff --git a/db/migrate/20181016141739_add_status_to_deployments.rb b/db/migrate/20181016141739_add_status_to_deployments.rb
new file mode 100644
index 00000000000..2ff778448b4
--- /dev/null
+++ b/db/migrate/20181016141739_add_status_to_deployments.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class AddStatusToDeployments < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DEPLOYMENT_STATUS_SUCCESS = 2 # Equivalent to Deployment.state_machine.states['success'].value
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ ##
+ # NOTE:
+ # Ideally, `status` column should not have default value because it should be leveraged by state machine (i.e. application level).
+ # However, we have to use the default value for avoiding `NOT NULL` violation during the transition period.
+ # The default value should be removed in the future release.
+ def up
+ add_column_with_default(:deployments,
+ :status,
+ :integer,
+ limit: 2,
+ default: DEPLOYMENT_STATUS_SUCCESS,
+ allow_null: false)
+ end
+
+ def down
+ remove_column(:deployments, :status)
+ end
+end
diff --git a/db/migrate/20181016152238_create_board_group_recent_visits.rb b/db/migrate/20181016152238_create_board_group_recent_visits.rb
new file mode 100644
index 00000000000..9e240a5f97f
--- /dev/null
+++ b/db/migrate/20181016152238_create_board_group_recent_visits.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class CreateBoardGroupRecentVisits < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :board_group_recent_visits, id: :bigserial do |t|
+ t.timestamps_with_timezone null: false
+
+ t.references :user, index: true, foreign_key: { on_delete: :cascade }
+ t.references :board, index: true, foreign_key: { on_delete: :cascade }
+ t.references :group, references: :namespace, column: :group_id, index: true
+ t.foreign_key :namespaces, column: :group_id, on_delete: :cascade
+ end
+
+ add_index :board_group_recent_visits, [:user_id, :group_id, :board_id], unique: true, name: 'index_board_group_recent_visits_on_user_group_and_board'
+ end
+end
diff --git a/db/migrate/20181017001059_add_cluster_type_to_clusters.rb b/db/migrate/20181017001059_add_cluster_type_to_clusters.rb
new file mode 100644
index 00000000000..d032afe1a43
--- /dev/null
+++ b/db/migrate/20181017001059_add_cluster_type_to_clusters.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddClusterTypeToClusters < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ PROJECT_CLUSTER_TYPE = 3
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default(:clusters, :cluster_type, :smallint, default: PROJECT_CLUSTER_TYPE)
+ end
+
+ def down
+ remove_column(:clusters, :cluster_type)
+ end
+end
diff --git a/db/migrate/20181019032400_add_shards_table.rb b/db/migrate/20181019032400_add_shards_table.rb
new file mode 100644
index 00000000000..e31af97cc94
--- /dev/null
+++ b/db/migrate/20181019032400_add_shards_table.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddShardsTable < ActiveRecord::Migration[4.2]
+ DOWNTIME = false
+
+ def change
+ create_table :shards do |t|
+ t.string :name, null: false, index: { unique: true }
+ end
+ end
+end
diff --git a/db/migrate/20181019032408_add_repositories_table.rb b/db/migrate/20181019032408_add_repositories_table.rb
new file mode 100644
index 00000000000..2153c1c9fc6
--- /dev/null
+++ b/db/migrate/20181019032408_add_repositories_table.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddRepositoriesTable < ActiveRecord::Migration[4.2]
+ DOWNTIME = false
+
+ def change
+ create_table :repositories, id: :bigserial do |t|
+ t.references :shard, null: false, index: true, foreign_key: { on_delete: :restrict }
+ t.string :disk_path, null: false, index: { unique: true }
+ end
+
+ add_column :projects, :pool_repository_id, :bigint
+ add_index :projects, :pool_repository_id, where: 'pool_repository_id IS NOT NULL'
+ end
+end
diff --git a/db/migrate/20181019105553_add_projects_pool_repository_id_foreign_key.rb b/db/migrate/20181019105553_add_projects_pool_repository_id_foreign_key.rb
new file mode 100644
index 00000000000..dddf44ce488
--- /dev/null
+++ b/db/migrate/20181019105553_add_projects_pool_repository_id_foreign_key.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class AddProjectsPoolRepositoryIdForeignKey < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key(
+ :projects,
+ :repositories,
+ column: :pool_repository_id,
+ on_delete: :nullify
+ )
+ end
+
+ def down
+ remove_foreign_key(:projects, column: :pool_repository_id)
+ end
+end
diff --git a/db/migrate/20181022135539_add_index_on_status_to_deployments.rb b/db/migrate/20181022135539_add_index_on_status_to_deployments.rb
new file mode 100644
index 00000000000..9c7a722c626
--- /dev/null
+++ b/db/migrate/20181022135539_add_index_on_status_to_deployments.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddIndexOnStatusToDeployments < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :deployments, [:project_id, :status]
+ add_concurrent_index :deployments, [:environment_id, :status]
+ end
+
+ def down
+ remove_concurrent_index :deployments, [:project_id, :status]
+ remove_concurrent_index :deployments, [:environment_id, :status]
+ end
+end
diff --git a/db/migrate/20181023104858_add_archive_builds_duration_to_application_settings.rb b/db/migrate/20181023104858_add_archive_builds_duration_to_application_settings.rb
new file mode 100644
index 00000000000..5d7a21fc5b5
--- /dev/null
+++ b/db/migrate/20181023104858_add_archive_builds_duration_to_application_settings.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddArchiveBuildsDurationToApplicationSettings < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column(:application_settings, :archive_builds_in_seconds, :integer, allow_null: true)
+ end
+end
diff --git a/db/migrate/20181023144439_add_partial_index_for_legacy_successful_deployments.rb b/db/migrate/20181023144439_add_partial_index_for_legacy_successful_deployments.rb
new file mode 100644
index 00000000000..e90e59b57a9
--- /dev/null
+++ b/db/migrate/20181023144439_add_partial_index_for_legacy_successful_deployments.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddPartialIndexForLegacySuccessfulDeployments < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ INDEX_NAME = 'partial_index_deployments_for_legacy_successful_deployments'.freeze
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index(:deployments, :id, where: "finished_at IS NULL AND status = 2", name: INDEX_NAME)
+ end
+
+ def down
+ remove_concurrent_index_by_name(:deployments, INDEX_NAME)
+ end
+end
diff --git a/db/migrate/20181025115728_add_private_commit_email_hostname_to_application_settings.rb b/db/migrate/20181025115728_add_private_commit_email_hostname_to_application_settings.rb
new file mode 100644
index 00000000000..052a344f182
--- /dev/null
+++ b/db/migrate/20181025115728_add_private_commit_email_hostname_to_application_settings.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class AddPrivateCommitEmailHostnameToApplicationSettings < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column(:application_settings, :commit_email_hostname, :string, null: true)
+ end
+end
diff --git a/db/migrate/20181026143227_migrate_snippets_access_level_default_value.rb b/db/migrate/20181026143227_migrate_snippets_access_level_default_value.rb
new file mode 100644
index 00000000000..2f4ef33b253
--- /dev/null
+++ b/db/migrate/20181026143227_migrate_snippets_access_level_default_value.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class MigrateSnippetsAccessLevelDefaultValue < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ ENABLED = 20
+
+ disable_ddl_transaction!
+
+ class ProjectFeature < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'project_features'
+ end
+
+ def up
+ change_column_default :project_features, :snippets_access_level, ENABLED
+
+ # On GitLab.com this will update about 28 000 rows. Since our updates are
+ # very small and this column is not indexed, these updates should be very
+ # lightweight.
+ ProjectFeature.where(snippets_access_level: nil).each_batch do |batch|
+ batch.update_all(snippets_access_level: ENABLED)
+ end
+
+ # We do not need to perform this in a post-deployment migration as the
+ # ProjectFeature model already enforces a default value for all new rows.
+ change_column_null :project_features, :snippets_access_level, false
+ end
+
+ def down
+ change_column_null :project_features, :snippets_access_level, true
+ change_column_default :project_features, :snippets_access_level, nil
+
+ # We can't migrate from 20 -> NULL, as some projects may have explicitly set
+ # the access level to 20.
+ end
+end
diff --git a/db/migrate/20181030154446_add_missing_indexes_for_foreign_keys.rb b/db/migrate/20181030154446_add_missing_indexes_for_foreign_keys.rb
new file mode 100644
index 00000000000..2b5cd45e92c
--- /dev/null
+++ b/db/migrate/20181030154446_add_missing_indexes_for_foreign_keys.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+class AddMissingIndexesForForeignKeys < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index(:application_settings, :usage_stats_set_by_user_id)
+ add_concurrent_index(:ci_pipeline_schedules, :owner_id)
+ add_concurrent_index(:ci_trigger_requests, :trigger_id)
+ add_concurrent_index(:ci_triggers, :owner_id)
+ add_concurrent_index(:clusters_applications_helm, :cluster_id, unique: true)
+ add_concurrent_index(:clusters_applications_ingress, :cluster_id, unique: true)
+ add_concurrent_index(:clusters_applications_jupyter, :cluster_id, unique: true)
+ add_concurrent_index(:clusters_applications_jupyter, :oauth_application_id)
+ add_concurrent_index(:clusters_applications_knative, :cluster_id, unique: true)
+ add_concurrent_index(:clusters_applications_prometheus, :cluster_id, unique: true)
+ add_concurrent_index(:fork_network_members, :forked_from_project_id)
+ add_concurrent_index(:internal_ids, :namespace_id)
+ add_concurrent_index(:internal_ids, :project_id)
+ add_concurrent_index(:issues, :closed_by_id)
+ add_concurrent_index(:label_priorities, :label_id)
+ add_concurrent_index(:merge_request_metrics, :merged_by_id)
+ add_concurrent_index(:merge_request_metrics, :latest_closed_by_id)
+ add_concurrent_index(:oauth_openid_requests, :access_grant_id)
+ add_concurrent_index(:project_deploy_tokens, :deploy_token_id)
+ add_concurrent_index(:protected_tag_create_access_levels, :group_id)
+ add_concurrent_index(:subscriptions, :project_id)
+ add_concurrent_index(:user_statuses, :user_id)
+ add_concurrent_index(:users, :accepted_term_id)
+ end
+
+ def down
+ # MySQL requires index for FK,
+ # thus removal of indexes does fail
+ return if Gitlab::Database.mysql?
+
+ remove_concurrent_index(:application_settings, :usage_stats_set_by_user_id)
+ remove_concurrent_index(:ci_pipeline_schedules, :owner_id)
+ remove_concurrent_index(:ci_trigger_requests, :trigger_id)
+ remove_concurrent_index(:ci_triggers, :owner_id)
+ remove_concurrent_index(:clusters_applications_helm, :cluster_id, unique: true)
+ remove_concurrent_index(:clusters_applications_ingress, :cluster_id, unique: true)
+ remove_concurrent_index(:clusters_applications_jupyter, :cluster_id, unique: true)
+ remove_concurrent_index(:clusters_applications_jupyter, :oauth_application_id)
+ remove_concurrent_index(:clusters_applications_knative, :cluster_id, unique: true)
+ remove_concurrent_index(:clusters_applications_prometheus, :cluster_id, unique: true)
+ remove_concurrent_index(:fork_network_members, :forked_from_project_id)
+ remove_concurrent_index(:internal_ids, :namespace_id)
+ remove_concurrent_index(:internal_ids, :project_id)
+ remove_concurrent_index(:issues, :closed_by_id)
+ remove_concurrent_index(:label_priorities, :label_id)
+ remove_concurrent_index(:merge_request_metrics, :merged_by_id)
+ remove_concurrent_index(:merge_request_metrics, :latest_closed_by_id)
+ remove_concurrent_index(:oauth_openid_requests, :access_grant_id)
+ remove_concurrent_index(:project_deploy_tokens, :deploy_token_id)
+ remove_concurrent_index(:protected_tag_create_access_levels, :group_id)
+ remove_concurrent_index(:subscriptions, :project_id)
+ remove_concurrent_index(:user_statuses, :user_id)
+ remove_concurrent_index(:users, :accepted_term_id)
+ end
+end
diff --git a/db/migrate/20181031190558_drop_fk_gcp_clusters_table.rb b/db/migrate/20181031190558_drop_fk_gcp_clusters_table.rb
new file mode 100644
index 00000000000..2c1dea05808
--- /dev/null
+++ b/db/migrate/20181031190558_drop_fk_gcp_clusters_table.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+class DropFkGcpClustersTable < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ remove_foreign_key_if_exists :gcp_clusters, column: :project_id
+ remove_foreign_key_if_exists :gcp_clusters, column: :user_id
+ remove_foreign_key_if_exists :gcp_clusters, column: :service_id
+ end
+
+ def down
+ add_foreign_key_if_not_exists :gcp_clusters, :projects, column: :project_id, on_delete: :cascade
+ add_foreign_key_if_not_exists :gcp_clusters, :users, column: :user_id, on_delete: :nullify
+ add_foreign_key_if_not_exists :gcp_clusters, :services, column: :service_id, on_delete: :nullify
+ end
+
+ private
+
+ def add_foreign_key_if_not_exists(source, target, column:, on_delete:)
+ return unless table_exists?(source)
+ return if foreign_key_exists?(source, target, column: column)
+
+ add_concurrent_foreign_key(source, target, column: column, on_delete: on_delete)
+ end
+
+ def remove_foreign_key_if_exists(table, column:)
+ return unless table_exists?(table)
+ return unless foreign_key_exists?(table, column: column)
+
+ remove_foreign_key(table, column: column)
+ end
+end
diff --git a/db/migrate/20181031190559_drop_gcp_clusters_table.rb b/db/migrate/20181031190559_drop_gcp_clusters_table.rb
new file mode 100644
index 00000000000..597fe49f4c8
--- /dev/null
+++ b/db/migrate/20181031190559_drop_gcp_clusters_table.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+class DropGcpClustersTable < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ drop_table :gcp_clusters
+ end
+
+ def down
+ create_table :gcp_clusters do |t|
+ # Order columns by best align scheme
+ t.references :project, null: false, index: { unique: true }, foreign_key: { on_delete: :cascade }
+ t.references :user, foreign_key: { on_delete: :nullify }
+ t.references :service, foreign_key: { on_delete: :nullify }
+ t.integer :status
+ t.integer :gcp_cluster_size, null: false
+
+ # Timestamps
+ t.datetime_with_timezone :created_at, null: false
+ t.datetime_with_timezone :updated_at, null: false
+
+ # Enable/disable
+ t.boolean :enabled, default: true
+
+ # General
+ t.text :status_reason
+
+ # k8s integration specific
+ t.string :project_namespace
+
+ # Cluster details
+ t.string :endpoint
+ t.text :ca_cert
+ t.text :encrypted_kubernetes_token
+ t.string :encrypted_kubernetes_token_iv
+ t.string :username
+ t.text :encrypted_password
+ t.string :encrypted_password_iv
+
+ # GKE
+ t.string :gcp_project_id, null: false
+ t.string :gcp_cluster_zone, null: false
+ t.string :gcp_cluster_name, null: false
+ t.string :gcp_machine_type
+ t.string :gcp_operation_id
+ t.text :encrypted_gcp_token
+ t.string :encrypted_gcp_token_iv
+ end
+ end
+end
diff --git a/db/migrate/20181101144347_add_index_for_stuck_mr_query.rb b/db/migrate/20181101144347_add_index_for_stuck_mr_query.rb
new file mode 100644
index 00000000000..569eaa8b22c
--- /dev/null
+++ b/db/migrate/20181101144347_add_index_for_stuck_mr_query.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+class AddIndexForStuckMrQuery < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :merge_requests, [:id, :merge_jid], where: "merge_jid IS NOT NULL and state = 'locked'"
+ end
+
+ def down
+ remove_concurrent_index :merge_requests, [:id, :merge_jid], where: "merge_jid IS NOT NULL and state = 'locked'"
+ end
+end
diff --git a/db/migrate/20181101191341_create_clusters_applications_cert_manager.rb b/db/migrate/20181101191341_create_clusters_applications_cert_manager.rb
new file mode 100644
index 00000000000..4966b89964a
--- /dev/null
+++ b/db/migrate/20181101191341_create_clusters_applications_cert_manager.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class CreateClustersApplicationsCertManager < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :clusters_applications_cert_managers do |t|
+ t.references :cluster, null: false, index: false, foreign_key: { on_delete: :cascade }
+ t.integer :status, null: false
+ t.string :version, null: false
+ t.string :email, null: false
+ t.timestamps_with_timezone null: false
+ t.text :status_reason
+ t.index :cluster_id, unique: true
+ end
+ end
+end
diff --git a/db/migrate/20181106135939_add_index_to_deployments.rb b/db/migrate/20181106135939_add_index_to_deployments.rb
new file mode 100644
index 00000000000..e8181e61d22
--- /dev/null
+++ b/db/migrate/20181106135939_add_index_to_deployments.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddIndexToDeployments < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :deployments, [:project_id, :status, :created_at]
+ end
+
+ def down
+ remove_concurrent_index :deployments, [:project_id, :status, :created_at]
+ end
+end
diff --git a/db/migrate/20181108091549_cleanup_environments_external_url.rb b/db/migrate/20181108091549_cleanup_environments_external_url.rb
new file mode 100644
index 00000000000..8d6c20a4b15
--- /dev/null
+++ b/db/migrate/20181108091549_cleanup_environments_external_url.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class CleanupEnvironmentsExternalUrl < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ update_column_in_batches(:environments, :external_url, nil) do |table, query|
+ query.where(table[:external_url].matches('javascript://%'))
+ end
+ end
+
+ def down
+ end
+end
diff --git a/db/migrate/20181112103239_drop_default_value_on_status_deployments.rb b/db/migrate/20181112103239_drop_default_value_on_status_deployments.rb
new file mode 100644
index 00000000000..59d6d2f29ff
--- /dev/null
+++ b/db/migrate/20181112103239_drop_default_value_on_status_deployments.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class DropDefaultValueOnStatusDeployments < ActiveRecord::Migration[4.2]
+ DOWNTIME = false
+ DEPLOYMENT_STATUS_SUCCESS = 2 # Equivalent to Deployment.state_machine.states['success'].value
+
+ def up
+ change_column_default :deployments, :status, nil
+ end
+
+ def down
+ change_column_default :deployments, :status, DEPLOYMENT_STATUS_SUCCESS
+ end
+end
diff --git a/db/migrate/20181116050532_knative_external_ip.rb b/db/migrate/20181116050532_knative_external_ip.rb
new file mode 100644
index 00000000000..f1f903fb692
--- /dev/null
+++ b/db/migrate/20181116050532_knative_external_ip.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class KnativeExternalIp < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :clusters_applications_knative, :external_ip, :string
+ end
+end
diff --git a/db/migrate/20181120082911_rename_repositories_pool_repositories.rb b/db/migrate/20181120082911_rename_repositories_pool_repositories.rb
new file mode 100644
index 00000000000..165771c4775
--- /dev/null
+++ b/db/migrate/20181120082911_rename_repositories_pool_repositories.rb
@@ -0,0 +1,11 @@
+class RenameRepositoriesPoolRepositories < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ # This change doesn't require downtime as the table is not in use, so we're
+ # free to change an empty table
+ DOWNTIME = false
+
+ def change
+ rename_table :repositories, :pool_repositories
+ end
+end
diff --git a/db/migrate/20181122160027_create_project_repositories.rb b/db/migrate/20181122160027_create_project_repositories.rb
new file mode 100644
index 00000000000..e42cef9b1c6
--- /dev/null
+++ b/db/migrate/20181122160027_create_project_repositories.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class CreateProjectRepositories < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ create_table :project_repositories, id: :bigserial do |t|
+ t.references :shard, null: false, index: true, foreign_key: { on_delete: :restrict }
+ t.string :disk_path, null: false, index: { unique: true }
+ t.references :project, null: false, index: { unique: true }, foreign_key: { on_delete: :cascade }
+ end
+ end
+end
diff --git a/db/migrate/20181123135036_drop_not_null_constraint_pool_repository_disk_path.rb b/db/migrate/20181123135036_drop_not_null_constraint_pool_repository_disk_path.rb
new file mode 100644
index 00000000000..bcd969e91c5
--- /dev/null
+++ b/db/migrate/20181123135036_drop_not_null_constraint_pool_repository_disk_path.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class DropNotNullConstraintPoolRepositoryDiskPath < ActiveRecord::Migration[5.0]
+ DOWNTIME = false
+
+ def change
+ change_column_null :pool_repositories, :disk_path, true
+ end
+end
diff --git a/db/migrate/20181126150622_add_events_index_on_project_id_and_created_at.rb b/db/migrate/20181126150622_add_events_index_on_project_id_and_created_at.rb
new file mode 100644
index 00000000000..7e9c56957d5
--- /dev/null
+++ b/db/migrate/20181126150622_add_events_index_on_project_id_and_created_at.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddEventsIndexOnProjectIdAndCreatedAt < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index(*index_arguments)
+ end
+
+ def down
+ remove_concurrent_index(*index_arguments)
+ end
+
+ private
+
+ def index_arguments
+ [
+ :events,
+ [:project_id, :created_at],
+ {
+ name: 'index_events_on_project_id_and_created_at'
+ }
+ ]
+ end
+end
diff --git a/db/migrate/20181126153547_remove_notes_index_on_updated_at.rb b/db/migrate/20181126153547_remove_notes_index_on_updated_at.rb
new file mode 100644
index 00000000000..d7ca46b50e4
--- /dev/null
+++ b/db/migrate/20181126153547_remove_notes_index_on_updated_at.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class RemoveNotesIndexOnUpdatedAt < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index(*index_arguments)
+ end
+
+ def down
+ add_concurrent_index(*index_arguments)
+ end
+
+ private
+
+ def index_arguments
+ [
+ :notes,
+ [:updated_at],
+ {
+ name: 'index_notes_on_updated_at'
+ }
+ ]
+ end
+end
diff --git a/db/migrate/gpg_keys_limits_to_mysql.rb b/db/migrate/gpg_keys_limits_to_mysql.rb
index 38729320d8c..2cd347a0463 100644
--- a/db/migrate/gpg_keys_limits_to_mysql.rb
+++ b/db/migrate/gpg_keys_limits_to_mysql.rb
@@ -1,4 +1,4 @@
-class IncreaseMysqlTextLimitForGpgKeys < ActiveRecord::Migration
+class IncreaseMysqlTextLimitForGpgKeys < ActiveRecord::Migration[4.2]
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
diff --git a/db/migrate/limits_ci_build_trace_chunks_raw_data_for_mysql.rb b/db/migrate/limits_ci_build_trace_chunks_raw_data_for_mysql.rb
index 9fd23aae1e5..92402cf387b 100644
--- a/db/migrate/limits_ci_build_trace_chunks_raw_data_for_mysql.rb
+++ b/db/migrate/limits_ci_build_trace_chunks_raw_data_for_mysql.rb
@@ -1,4 +1,4 @@
-class LimitsCiBuildTraceChunksRawDataForMysql < ActiveRecord::Migration
+class LimitsCiBuildTraceChunksRawDataForMysql < ActiveRecord::Migration[4.2]
def up
return unless Gitlab::Database.mysql?
diff --git a/db/migrate/limits_to_mysql.rb b/db/migrate/limits_to_mysql.rb
index 7507a4bb431..87992b541b1 100644
--- a/db/migrate/limits_to_mysql.rb
+++ b/db/migrate/limits_to_mysql.rb
@@ -1,4 +1,4 @@
-class LimitsToMysql < ActiveRecord::Migration
+class LimitsToMysql < ActiveRecord::Migration[4.2]
def up
return unless ActiveRecord::Base.configurations[Rails.env]['adapter'] =~ /^mysql/
diff --git a/db/migrate/markdown_cache_limits_to_mysql.rb b/db/migrate/markdown_cache_limits_to_mysql.rb
index f6686db3dc0..f99d500a137 100644
--- a/db/migrate/markdown_cache_limits_to_mysql.rb
+++ b/db/migrate/markdown_cache_limits_to_mysql.rb
@@ -1,4 +1,4 @@
-class MarkdownCacheLimitsToMysql < ActiveRecord::Migration
+class MarkdownCacheLimitsToMysql < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/merge_request_diff_file_limits_to_mysql.rb b/db/migrate/merge_request_diff_file_limits_to_mysql.rb
index ca3bc7d6be9..65dd0b5b7f7 100644
--- a/db/migrate/merge_request_diff_file_limits_to_mysql.rb
+++ b/db/migrate/merge_request_diff_file_limits_to_mysql.rb
@@ -1,4 +1,4 @@
-class MergeRequestDiffFileLimitsToMysql < ActiveRecord::Migration
+class MergeRequestDiffFileLimitsToMysql < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/migrate/prometheus_metrics_limits_to_mysql.rb b/db/migrate/prometheus_metrics_limits_to_mysql.rb
index 79f4ab9b64b..f7a2fcba8c2 100644
--- a/db/migrate/prometheus_metrics_limits_to_mysql.rb
+++ b/db/migrate/prometheus_metrics_limits_to_mysql.rb
@@ -1,4 +1,4 @@
-class PrometheusMetricsLimitsToMysql < ActiveRecord::Migration
+class PrometheusMetricsLimitsToMysql < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/optional_migrations/composite_primary_keys.rb b/db/optional_migrations/composite_primary_keys.rb
index b330da13d43..e0bb0312a35 100644
--- a/db/optional_migrations/composite_primary_keys.rb
+++ b/db/optional_migrations/composite_primary_keys.rb
@@ -7,7 +7,7 @@
# which requires all tables to have a primary key constraint.
#
# In that sense, the migration is optional and not strictly needed.
-class CompositePrimaryKeysMigration < ActiveRecord::Migration
+class CompositePrimaryKeysMigration < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20160824121037_change_personal_access_tokens_default_back_to_empty_array.rb b/db/post_migrate/20160824121037_change_personal_access_tokens_default_back_to_empty_array.rb
index 7df561d82dd..099814d7556 100644
--- a/db/post_migrate/20160824121037_change_personal_access_tokens_default_back_to_empty_array.rb
+++ b/db/post_migrate/20160824121037_change_personal_access_tokens_default_back_to_empty_array.rb
@@ -4,7 +4,7 @@
#
# Details: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5951#note_19721973
-class ChangePersonalAccessTokensDefaultBackToEmptyArray < ActiveRecord::Migration
+class ChangePersonalAccessTokensDefaultBackToEmptyArray < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20161011222551_remove_inactive_jira_service_properties.rb b/db/post_migrate/20161011222551_remove_inactive_jira_service_properties.rb
index 319d86ac159..bf3aee99418 100644
--- a/db/post_migrate/20161011222551_remove_inactive_jira_service_properties.rb
+++ b/db/post_migrate/20161011222551_remove_inactive_jira_service_properties.rb
@@ -1,4 +1,4 @@
-class RemoveInactiveJiraServiceProperties < ActiveRecord::Migration
+class RemoveInactiveJiraServiceProperties < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = true
diff --git a/db/post_migrate/20161109150329_fix_project_records_with_invalid_visibility.rb b/db/post_migrate/20161109150329_fix_project_records_with_invalid_visibility.rb
index f058e85c1ec..d77a22bfb69 100644
--- a/db/post_migrate/20161109150329_fix_project_records_with_invalid_visibility.rb
+++ b/db/post_migrate/20161109150329_fix_project_records_with_invalid_visibility.rb
@@ -1,4 +1,4 @@
-class FixProjectRecordsWithInvalidVisibility < ActiveRecord::Migration
+class FixProjectRecordsWithInvalidVisibility < ActiveRecord::Migration[4.2]
include Gitlab::Database::ArelMethods
include Gitlab::Database::MigrationHelpers
diff --git a/db/post_migrate/20161128170531_drop_user_activities_table.rb b/db/post_migrate/20161128170531_drop_user_activities_table.rb
index 00bc0c73015..64d13a08953 100644
--- a/db/post_migrate/20161128170531_drop_user_activities_table.rb
+++ b/db/post_migrate/20161128170531_drop_user_activities_table.rb
@@ -1,4 +1,4 @@
-class DropUserActivitiesTable < ActiveRecord::Migration
+class DropUserActivitiesTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20161221140236_remove_unneeded_services.rb b/db/post_migrate/20161221140236_remove_unneeded_services.rb
index 6b7e94c8641..31f24263877 100644
--- a/db/post_migrate/20161221140236_remove_unneeded_services.rb
+++ b/db/post_migrate/20161221140236_remove_unneeded_services.rb
@@ -1,4 +1,4 @@
-class RemoveUnneededServices < ActiveRecord::Migration
+class RemoveUnneededServices < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20161221153951_rename_reserved_project_names.rb b/db/post_migrate/20161221153951_rename_reserved_project_names.rb
index 017c58477ac..b7665e98490 100644
--- a/db/post_migrate/20161221153951_rename_reserved_project_names.rb
+++ b/db/post_migrate/20161221153951_rename_reserved_project_names.rb
@@ -1,6 +1,4 @@
-require 'thread'
-
-class RenameReservedProjectNames < ActiveRecord::Migration
+class RenameReservedProjectNames < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
include Gitlab::ShellAdapter
@@ -115,7 +113,9 @@ class RenameReservedProjectNames < ActiveRecord::Migration
begin
# Because project path update is quite complex operation we can't safely
# copy-paste all code from GitLab. As exception we use Rails code here
- project.rename_repo if rename_project_row(project, path)
+ if rename_project_row(project, path)
+ Projects::AfterRenameService.new(project).execute
+ end
rescue Exception => e # rubocop: disable Lint/RescueException
Rails.logger.error "Exception when renaming project #{id}: #{e.message}"
end
@@ -125,6 +125,6 @@ class RenameReservedProjectNames < ActiveRecord::Migration
def rename_project_row(project, path)
project.respond_to?(:update_attributes) &&
project.update(path: path) &&
- project.respond_to?(:rename_repo)
+ defined?(Projects::AfterRenameService)
end
end
diff --git a/db/post_migrate/20170104150317_requeue_pending_delete_projects.rb b/db/post_migrate/20170104150317_requeue_pending_delete_projects.rb
index d7be004d47f..f567accb051 100644
--- a/db/post_migrate/20170104150317_requeue_pending_delete_projects.rb
+++ b/db/post_migrate/20170104150317_requeue_pending_delete_projects.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RequeuePendingDeleteProjects < ActiveRecord::Migration
+class RequeuePendingDeleteProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170106142508_fill_authorized_projects.rb b/db/post_migrate/20170106142508_fill_authorized_projects.rb
index 0ca20587981..1f1dd0f47f0 100644
--- a/db/post_migrate/20170106142508_fill_authorized_projects.rb
+++ b/db/post_migrate/20170106142508_fill_authorized_projects.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class FillAuthorizedProjects < ActiveRecord::Migration
+class FillAuthorizedProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
class User < ActiveRecord::Base
diff --git a/db/post_migrate/20170106172224_remove_project_authorizations_id_column.rb b/db/post_migrate/20170106172224_remove_project_authorizations_id_column.rb
index 7c788160022..893af23465a 100644
--- a/db/post_migrate/20170106172224_remove_project_authorizations_id_column.rb
+++ b/db/post_migrate/20170106172224_remove_project_authorizations_id_column.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveProjectAuthorizationsIdColumn < ActiveRecord::Migration
+class RemoveProjectAuthorizationsIdColumn < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170131214021_reset_users_authorized_projects_populated.rb b/db/post_migrate/20170131214021_reset_users_authorized_projects_populated.rb
index f1f81691f81..055a14ad729 100644
--- a/db/post_migrate/20170131214021_reset_users_authorized_projects_populated.rb
+++ b/db/post_migrate/20170131214021_reset_users_authorized_projects_populated.rb
@@ -1,6 +1,6 @@
# rubocop:disable Migration/UpdateLargeTable
# rubocop:disable Migration/UpdateColumnInBatches
-class ResetUsersAuthorizedProjectsPopulated < ActiveRecord::Migration
+class ResetUsersAuthorizedProjectsPopulated < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170206040400_remove_inactive_default_email_services.rb b/db/post_migrate/20170206040400_remove_inactive_default_email_services.rb
index a8e63e8bc7d..f221dac8e20 100644
--- a/db/post_migrate/20170206040400_remove_inactive_default_email_services.rb
+++ b/db/post_migrate/20170206040400_remove_inactive_default_email_services.rb
@@ -1,4 +1,4 @@
-class RemoveInactiveDefaultEmailServices < ActiveRecord::Migration
+class RemoveInactiveDefaultEmailServices < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170206101007_remove_trackable_columns_from_timelogs.rb b/db/post_migrate/20170206101007_remove_trackable_columns_from_timelogs.rb
index aee0c1b6245..14f5d0d4add 100644
--- a/db/post_migrate/20170206101007_remove_trackable_columns_from_timelogs.rb
+++ b/db/post_migrate/20170206101007_remove_trackable_columns_from_timelogs.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveTrackableColumnsFromTimelogs < ActiveRecord::Migration
+class RemoveTrackableColumnsFromTimelogs < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170206101030_validate_foreign_keys_on_timelogs.rb b/db/post_migrate/20170206101030_validate_foreign_keys_on_timelogs.rb
index f397ef919cc..b5a5c0f06c7 100644
--- a/db/post_migrate/20170206101030_validate_foreign_keys_on_timelogs.rb
+++ b/db/post_migrate/20170206101030_validate_foreign_keys_on_timelogs.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class ValidateForeignKeysOnTimelogs < ActiveRecord::Migration
+class ValidateForeignKeysOnTimelogs < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170209140523_validate_foreign_keys_on_oauth_openid_requests.rb b/db/post_migrate/20170209140523_validate_foreign_keys_on_oauth_openid_requests.rb
index e206f9af636..81ac4cf1373 100644
--- a/db/post_migrate/20170209140523_validate_foreign_keys_on_oauth_openid_requests.rb
+++ b/db/post_migrate/20170209140523_validate_foreign_keys_on_oauth_openid_requests.rb
@@ -1,4 +1,4 @@
-class ValidateForeignKeysOnOauthOpenidRequests < ActiveRecord::Migration
+class ValidateForeignKeysOnOauthOpenidRequests < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170211073944_disable_invalid_service_templates.rb b/db/post_migrate/20170211073944_disable_invalid_service_templates.rb
index 603efc43782..31234e5b086 100644
--- a/db/post_migrate/20170211073944_disable_invalid_service_templates.rb
+++ b/db/post_migrate/20170211073944_disable_invalid_service_templates.rb
@@ -1,4 +1,4 @@
-class DisableInvalidServiceTemplates < ActiveRecord::Migration
+class DisableInvalidServiceTemplates < ActiveRecord::Migration[4.2]
DOWNTIME = false
class Service < ActiveRecord::Base
diff --git a/db/post_migrate/20170214111112_delete_deprecated_gitlab_ci_service.rb b/db/post_migrate/20170214111112_delete_deprecated_gitlab_ci_service.rb
index 09a827d22b0..c273060f8b0 100644
--- a/db/post_migrate/20170214111112_delete_deprecated_gitlab_ci_service.rb
+++ b/db/post_migrate/20170214111112_delete_deprecated_gitlab_ci_service.rb
@@ -1,4 +1,4 @@
-class DeleteDeprecatedGitlabCiService < ActiveRecord::Migration
+class DeleteDeprecatedGitlabCiService < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170215200045_remove_theme_id_from_users.rb b/db/post_migrate/20170215200045_remove_theme_id_from_users.rb
index c51646fbe52..937fe3f57af 100644
--- a/db/post_migrate/20170215200045_remove_theme_id_from_users.rb
+++ b/db/post_migrate/20170215200045_remove_theme_id_from_users.rb
@@ -1,4 +1,4 @@
-class RemoveThemeIdFromUsers < ActiveRecord::Migration
+class RemoveThemeIdFromUsers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170301205640_migrate_build_events_to_pipeline_events.rb b/db/post_migrate/20170301205640_migrate_build_events_to_pipeline_events.rb
index 04bf89c9687..c2d28d79491 100644
--- a/db/post_migrate/20170301205640_migrate_build_events_to_pipeline_events.rb
+++ b/db/post_migrate/20170301205640_migrate_build_events_to_pipeline_events.rb
@@ -1,4 +1,4 @@
-class MigrateBuildEventsToPipelineEvents < ActiveRecord::Migration
+class MigrateBuildEventsToPipelineEvents < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170306170512_migrate_legacy_manual_actions.rb b/db/post_migrate/20170306170512_migrate_legacy_manual_actions.rb
index ec6e8cdfc45..aa12e8ac3da 100644
--- a/db/post_migrate/20170306170512_migrate_legacy_manual_actions.rb
+++ b/db/post_migrate/20170306170512_migrate_legacy_manual_actions.rb
@@ -1,4 +1,4 @@
-class MigrateLegacyManualActions < ActiveRecord::Migration
+class MigrateLegacyManualActions < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170309171644_reset_relative_position_for_issue.rb b/db/post_migrate/20170309171644_reset_relative_position_for_issue.rb
index 49fd46b0262..2cf4cf61d8f 100644
--- a/db/post_migrate/20170309171644_reset_relative_position_for_issue.rb
+++ b/db/post_migrate/20170309171644_reset_relative_position_for_issue.rb
@@ -1,6 +1,6 @@
# rubocop:disable Migration/UpdateLargeTable
# rubocop:disable Migration/UpdateColumnInBatches
-class ResetRelativePositionForIssue < ActiveRecord::Migration
+class ResetRelativePositionForIssue < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170313133418_rename_more_reserved_project_names.rb b/db/post_migrate/20170313133418_rename_more_reserved_project_names.rb
index 3e8ccfdb899..cac3fd713eb 100644
--- a/db/post_migrate/20170313133418_rename_more_reserved_project_names.rb
+++ b/db/post_migrate/20170313133418_rename_more_reserved_project_names.rb
@@ -1,6 +1,4 @@
-require 'thread'
-
-class RenameMoreReservedProjectNames < ActiveRecord::Migration
+class RenameMoreReservedProjectNames < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
include Gitlab::ShellAdapter
@@ -57,7 +55,9 @@ class RenameMoreReservedProjectNames < ActiveRecord::Migration
begin
# Because project path update is quite complex operation we can't safely
# copy-paste all code from GitLab. As exception we use Rails code here
- project.rename_repo if rename_project_row(project, path)
+ if rename_project_row(project, path)
+ Projects::AfterRenameService.new(project).execute
+ end
rescue Exception => e # rubocop: disable Lint/RescueException
Rails.logger.error "Exception when renaming project #{id}: #{e.message}"
end
@@ -67,6 +67,6 @@ class RenameMoreReservedProjectNames < ActiveRecord::Migration
def rename_project_row(project, path)
project.respond_to?(:update_attributes) &&
project.update(path: path) &&
- project.respond_to?(:rename_repo)
+ defined?(Projects::AfterRenameService)
end
end
diff --git a/db/post_migrate/20170317162059_update_upload_paths_to_system.rb b/db/post_migrate/20170317162059_update_upload_paths_to_system.rb
index 92e33848bf0..a5a6f043e10 100644
--- a/db/post_migrate/20170317162059_update_upload_paths_to_system.rb
+++ b/db/post_migrate/20170317162059_update_upload_paths_to_system.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class UpdateUploadPathsToSystem < ActiveRecord::Migration
+class UpdateUploadPathsToSystem < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170324160416_migrate_user_activities_to_users_last_activity_on.rb b/db/post_migrate/20170324160416_migrate_user_activities_to_users_last_activity_on.rb
index 392fa00b1ba..73989339ad9 100644
--- a/db/post_migrate/20170324160416_migrate_user_activities_to_users_last_activity_on.rb
+++ b/db/post_migrate/20170324160416_migrate_user_activities_to_users_last_activity_on.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/UpdateLargeTable
-class MigrateUserActivitiesToUsersLastActivityOn < ActiveRecord::Migration
+class MigrateUserActivitiesToUsersLastActivityOn < ActiveRecord::Migration[4.2]
include Gitlab::Database::ArelMethods
include Gitlab::Database::MigrationHelpers
diff --git a/db/post_migrate/20170404170532_remove_notes_original_discussion_id.rb b/db/post_migrate/20170404170532_remove_notes_original_discussion_id.rb
index 0c3b3bd5eb3..334742f04e4 100644
--- a/db/post_migrate/20170404170532_remove_notes_original_discussion_id.rb
+++ b/db/post_migrate/20170404170532_remove_notes_original_discussion_id.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveNotesOriginalDiscussionId < ActiveRecord::Migration
+class RemoveNotesOriginalDiscussionId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170406111121_clean_upload_symlinks.rb b/db/post_migrate/20170406111121_clean_upload_symlinks.rb
index 0ab3d61730d..5fec00aa198 100644
--- a/db/post_migrate/20170406111121_clean_upload_symlinks.rb
+++ b/db/post_migrate/20170406111121_clean_upload_symlinks.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class CleanUploadSymlinks < ActiveRecord::Migration
+class CleanUploadSymlinks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/post_migrate/20170406142253_migrate_user_project_view.rb b/db/post_migrate/20170406142253_migrate_user_project_view.rb
index d6061dd416d..3601baba787 100644
--- a/db/post_migrate/20170406142253_migrate_user_project_view.rb
+++ b/db/post_migrate/20170406142253_migrate_user_project_view.rb
@@ -2,7 +2,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MigrateUserProjectView < ActiveRecord::Migration
+class MigrateUserProjectView < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/post_migrate/20170408033905_remove_old_cache_directories.rb b/db/post_migrate/20170408033905_remove_old_cache_directories.rb
index b23b52896b9..22bc5b9db7b 100644
--- a/db/post_migrate/20170408033905_remove_old_cache_directories.rb
+++ b/db/post_migrate/20170408033905_remove_old_cache_directories.rb
@@ -4,7 +4,7 @@
# Remove all files from old custom carrierwave's cache directories.
# See https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9466
-class RemoveOldCacheDirectories < ActiveRecord::Migration
+class RemoveOldCacheDirectories < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170412174900_rename_reserved_dynamic_paths.rb b/db/post_migrate/20170412174900_rename_reserved_dynamic_paths.rb
index 08cf366f0a1..c9ff91b0401 100644
--- a/db/post_migrate/20170412174900_rename_reserved_dynamic_paths.rb
+++ b/db/post_migrate/20170412174900_rename_reserved_dynamic_paths.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RenameReservedDynamicPaths < ActiveRecord::Migration
+class RenameReservedDynamicPaths < ActiveRecord::Migration[4.2]
include Gitlab::Database::RenameReservedPathsMigration::V1
DOWNTIME = false
diff --git a/db/post_migrate/20170425121605_migrate_trigger_schedules_to_pipeline_schedules.rb b/db/post_migrate/20170425121605_migrate_trigger_schedules_to_pipeline_schedules.rb
index dae9750558f..99ded277277 100644
--- a/db/post_migrate/20170425121605_migrate_trigger_schedules_to_pipeline_schedules.rb
+++ b/db/post_migrate/20170425121605_migrate_trigger_schedules_to_pipeline_schedules.rb
@@ -1,4 +1,4 @@
-class MigrateTriggerSchedulesToPipelineSchedules < ActiveRecord::Migration
+class MigrateTriggerSchedulesToPipelineSchedules < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170425130047_drop_ci_trigger_schedules_table.rb b/db/post_migrate/20170425130047_drop_ci_trigger_schedules_table.rb
index 24750c58ef0..9d515aca8b4 100644
--- a/db/post_migrate/20170425130047_drop_ci_trigger_schedules_table.rb
+++ b/db/post_migrate/20170425130047_drop_ci_trigger_schedules_table.rb
@@ -1,4 +1,4 @@
-class DropCiTriggerSchedulesTable < ActiveRecord::Migration
+class DropCiTriggerSchedulesTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170502070007_enable_auto_cancel_pending_pipelines_for_all.rb b/db/post_migrate/20170502070007_enable_auto_cancel_pending_pipelines_for_all.rb
index 845c6f0557f..4d091d7f275 100644
--- a/db/post_migrate/20170502070007_enable_auto_cancel_pending_pipelines_for_all.rb
+++ b/db/post_migrate/20170502070007_enable_auto_cancel_pending_pipelines_for_all.rb
@@ -1,6 +1,6 @@
# rubocop:disable Migration/UpdateLargeTable
# rubocop:disable Migration/UpdateColumnInBatches
-class EnableAutoCancelPendingPipelinesForAll < ActiveRecord::Migration
+class EnableAutoCancelPendingPipelinesForAll < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/post_migrate/20170502101023_cleanup_namespaceless_pending_delete_projects.rb b/db/post_migrate/20170502101023_cleanup_namespaceless_pending_delete_projects.rb
index 5238a2ba1b7..c018d30c175 100644
--- a/db/post_migrate/20170502101023_cleanup_namespaceless_pending_delete_projects.rb
+++ b/db/post_migrate/20170502101023_cleanup_namespaceless_pending_delete_projects.rb
@@ -1,6 +1,6 @@
# This is the counterpart of RequeuePendingDeleteProjects and cleans all
# projects with `pending_delete = true` and that do not have a namespace.
-class CleanupNamespacelessPendingDeleteProjects < ActiveRecord::Migration
+class CleanupNamespacelessPendingDeleteProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170503004427_update_retried_for_ci_build.rb b/db/post_migrate/20170503004427_update_retried_for_ci_build.rb
index 079f0e7511f..596f8593308 100644
--- a/db/post_migrate/20170503004427_update_retried_for_ci_build.rb
+++ b/db/post_migrate/20170503004427_update_retried_for_ci_build.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/UpdateLargeTable
-class UpdateRetriedForCiBuild < ActiveRecord::Migration
+class UpdateRetriedForCiBuild < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170503120310_remove_users_authorized_projects_populated.rb b/db/post_migrate/20170503120310_remove_users_authorized_projects_populated.rb
index 1b44334395f..891ce44f60a 100644
--- a/db/post_migrate/20170503120310_remove_users_authorized_projects_populated.rb
+++ b/db/post_migrate/20170503120310_remove_users_authorized_projects_populated.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveUsersAuthorizedProjectsPopulated < ActiveRecord::Migration
+class RemoveUsersAuthorizedProjectsPopulated < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/post_migrate/20170508170547_add_head_pipeline_for_each_merge_request.rb b/db/post_migrate/20170508170547_add_head_pipeline_for_each_merge_request.rb
index 5df3ab71648..6e7365f4c56 100644
--- a/db/post_migrate/20170508170547_add_head_pipeline_for_each_merge_request.rb
+++ b/db/post_migrate/20170508170547_add_head_pipeline_for_each_merge_request.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/UpdateLargeTable
-class AddHeadPipelineForEachMergeRequest < ActiveRecord::Migration
+class AddHeadPipelineForEachMergeRequest < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170510101043_add_foreign_key_on_pipeline_schedule_owner.rb b/db/post_migrate/20170510101043_add_foreign_key_on_pipeline_schedule_owner.rb
index 6a870f08e89..85586aecd54 100644
--- a/db/post_migrate/20170510101043_add_foreign_key_on_pipeline_schedule_owner.rb
+++ b/db/post_migrate/20170510101043_add_foreign_key_on_pipeline_schedule_owner.rb
@@ -1,4 +1,4 @@
-class AddForeignKeyOnPipelineScheduleOwner < ActiveRecord::Migration
+class AddForeignKeyOnPipelineScheduleOwner < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170511100900_cleanup_rename_web_hooks_build_events_to_job_events.rb b/db/post_migrate/20170511100900_cleanup_rename_web_hooks_build_events_to_job_events.rb
index 281be90163a..b4a3db65607 100644
--- a/db/post_migrate/20170511100900_cleanup_rename_web_hooks_build_events_to_job_events.rb
+++ b/db/post_migrate/20170511100900_cleanup_rename_web_hooks_build_events_to_job_events.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class CleanupRenameWebHooksBuildEventsToJobEvents < ActiveRecord::Migration
+class CleanupRenameWebHooksBuildEventsToJobEvents < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170511101000_cleanup_rename_services_build_events_to_job_events.rb b/db/post_migrate/20170511101000_cleanup_rename_services_build_events_to_job_events.rb
index 5d26df5688f..65342747321 100644
--- a/db/post_migrate/20170511101000_cleanup_rename_services_build_events_to_job_events.rb
+++ b/db/post_migrate/20170511101000_cleanup_rename_services_build_events_to_job_events.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class CleanupRenameServicesBuildEventsToJobEvents < ActiveRecord::Migration
+class CleanupRenameServicesBuildEventsToJobEvents < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170516165238_cleanup_trigger_for_issues.rb b/db/post_migrate/20170516165238_cleanup_trigger_for_issues.rb
index 378fe5603c3..affeba52250 100644
--- a/db/post_migrate/20170516165238_cleanup_trigger_for_issues.rb
+++ b/db/post_migrate/20170516165238_cleanup_trigger_for_issues.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class CleanupTriggerForIssues < ActiveRecord::Migration
+class CleanupTriggerForIssues < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/post_migrate/20170516181025_add_constraints_to_issue_assignees_table.rb b/db/post_migrate/20170516181025_add_constraints_to_issue_assignees_table.rb
index 6fa573c5b49..03456a31b0d 100644
--- a/db/post_migrate/20170516181025_add_constraints_to_issue_assignees_table.rb
+++ b/db/post_migrate/20170516181025_add_constraints_to_issue_assignees_table.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddConstraintsToIssueAssigneesTable < ActiveRecord::Migration
+class AddConstraintsToIssueAssigneesTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/post_migrate/20170518200835_rename_users_with_renamed_namespace.rb b/db/post_migrate/20170518200835_rename_users_with_renamed_namespace.rb
index 17ad7de065d..4ba78727cc3 100644
--- a/db/post_migrate/20170518200835_rename_users_with_renamed_namespace.rb
+++ b/db/post_migrate/20170518200835_rename_users_with_renamed_namespace.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RenameUsersWithRenamedNamespace < ActiveRecord::Migration
+class RenameUsersWithRenamedNamespace < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170518231126_fix_wrongly_renamed_routes.rb b/db/post_migrate/20170518231126_fix_wrongly_renamed_routes.rb
index 3e952980866..28a2a2e01bf 100644
--- a/db/post_migrate/20170518231126_fix_wrongly_renamed_routes.rb
+++ b/db/post_migrate/20170518231126_fix_wrongly_renamed_routes.rb
@@ -2,7 +2,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class FixWronglyRenamedRoutes < ActiveRecord::Migration
+class FixWronglyRenamedRoutes < ActiveRecord::Migration[4.2]
include Gitlab::Database::RenameReservedPathsMigration::V1
DOWNTIME = false
diff --git a/db/post_migrate/20170523073948_remove_assignee_id_from_issue.rb b/db/post_migrate/20170523073948_remove_assignee_id_from_issue.rb
index 006d17b4d62..d75bbb2f612 100644
--- a/db/post_migrate/20170523073948_remove_assignee_id_from_issue.rb
+++ b/db/post_migrate/20170523073948_remove_assignee_id_from_issue.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveAssigneeIdFromIssue < ActiveRecord::Migration
+class RemoveAssigneeIdFromIssue < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/post_migrate/20170523083112_migrate_old_artifacts.rb b/db/post_migrate/20170523083112_migrate_old_artifacts.rb
index 3a77b9751d3..55e155c7619 100644
--- a/db/post_migrate/20170523083112_migrate_old_artifacts.rb
+++ b/db/post_migrate/20170523083112_migrate_old_artifacts.rb
@@ -1,4 +1,4 @@
-class MigrateOldArtifacts < ActiveRecord::Migration
+class MigrateOldArtifacts < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170525140254_rename_all_reserved_paths_again.rb b/db/post_migrate/20170525140254_rename_all_reserved_paths_again.rb
index c996ddbec84..59b8daaffdf 100644
--- a/db/post_migrate/20170525140254_rename_all_reserved_paths_again.rb
+++ b/db/post_migrate/20170525140254_rename_all_reserved_paths_again.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RenameAllReservedPathsAgain < ActiveRecord::Migration
+class RenameAllReservedPathsAgain < ActiveRecord::Migration[4.2]
include Gitlab::Database::RenameReservedPathsMigration::V1
DOWNTIME = false
diff --git a/db/post_migrate/20170526185842_migrate_pipeline_stages.rb b/db/post_migrate/20170526185842_migrate_pipeline_stages.rb
index 736aff77f02..53743fc16e6 100644
--- a/db/post_migrate/20170526185842_migrate_pipeline_stages.rb
+++ b/db/post_migrate/20170526185842_migrate_pipeline_stages.rb
@@ -1,4 +1,4 @@
-class MigratePipelineStages < ActiveRecord::Migration
+class MigratePipelineStages < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170526185858_create_index_in_pipeline_stages.rb b/db/post_migrate/20170526185858_create_index_in_pipeline_stages.rb
index ec9ff33b6b7..dc7b1d6d026 100644
--- a/db/post_migrate/20170526185858_create_index_in_pipeline_stages.rb
+++ b/db/post_migrate/20170526185858_create_index_in_pipeline_stages.rb
@@ -1,4 +1,4 @@
-class CreateIndexInPipelineStages < ActiveRecord::Migration
+class CreateIndexInPipelineStages < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170526185901_remove_stage_id_index_from_builds.rb b/db/post_migrate/20170526185901_remove_stage_id_index_from_builds.rb
index 3879cf9133b..de473e7bb91 100644
--- a/db/post_migrate/20170526185901_remove_stage_id_index_from_builds.rb
+++ b/db/post_migrate/20170526185901_remove_stage_id_index_from_builds.rb
@@ -1,4 +1,4 @@
-class RemoveStageIdIndexFromBuilds < ActiveRecord::Migration
+class RemoveStageIdIndexFromBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170526185921_migrate_build_stage_reference.rb b/db/post_migrate/20170526185921_migrate_build_stage_reference.rb
index 98c32d8284c..a9b392314fa 100644
--- a/db/post_migrate/20170526185921_migrate_build_stage_reference.rb
+++ b/db/post_migrate/20170526185921_migrate_build_stage_reference.rb
@@ -1,4 +1,4 @@
-class MigrateBuildStageReference < ActiveRecord::Migration
+class MigrateBuildStageReference < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170526190000_migrate_build_stage_reference_again.rb b/db/post_migrate/20170526190000_migrate_build_stage_reference_again.rb
index a7bfba0ab2b..01b6cf3a158 100644
--- a/db/post_migrate/20170526190000_migrate_build_stage_reference_again.rb
+++ b/db/post_migrate/20170526190000_migrate_build_stage_reference_again.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/UpdateLargeTable
-class MigrateBuildStageReferenceAgain < ActiveRecord::Migration
+class MigrateBuildStageReferenceAgain < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170531203055_cleanup_users_ldap_email_rename.rb b/db/post_migrate/20170531203055_cleanup_users_ldap_email_rename.rb
index a70e3985005..3d75c7e3eaf 100644
--- a/db/post_migrate/20170531203055_cleanup_users_ldap_email_rename.rb
+++ b/db/post_migrate/20170531203055_cleanup_users_ldap_email_rename.rb
@@ -1,4 +1,4 @@
-class CleanupUsersLdapEmailRename < ActiveRecord::Migration
+class CleanupUsersLdapEmailRename < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170606202615_move_appearance_to_system_dir.rb b/db/post_migrate/20170606202615_move_appearance_to_system_dir.rb
index 07935ab8a52..fb9ac8d6daf 100644
--- a/db/post_migrate/20170606202615_move_appearance_to_system_dir.rb
+++ b/db/post_migrate/20170606202615_move_appearance_to_system_dir.rb
@@ -1,4 +1,4 @@
-class MoveAppearanceToSystemDir < ActiveRecord::Migration
+class MoveAppearanceToSystemDir < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/post_migrate/20170607121233_convert_custom_notification_settings_to_columns.rb b/db/post_migrate/20170607121233_convert_custom_notification_settings_to_columns.rb
index 9abda6a1d73..8ff26130cba 100644
--- a/db/post_migrate/20170607121233_convert_custom_notification_settings_to_columns.rb
+++ b/db/post_migrate/20170607121233_convert_custom_notification_settings_to_columns.rb
@@ -1,4 +1,4 @@
-class ConvertCustomNotificationSettingsToColumns < ActiveRecord::Migration
+class ConvertCustomNotificationSettingsToColumns < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170609183112_remove_position_from_issuables.rb b/db/post_migrate/20170609183112_remove_position_from_issuables.rb
index 4caaa2e83e8..edad0a502b4 100644
--- a/db/post_migrate/20170609183112_remove_position_from_issuables.rb
+++ b/db/post_migrate/20170609183112_remove_position_from_issuables.rb
@@ -1,4 +1,4 @@
-class RemovePositionFromIssuables < ActiveRecord::Migration
+class RemovePositionFromIssuables < ActiveRecord::Migration[4.2]
DOWNTIME = false
def change
diff --git a/db/post_migrate/20170612071012_move_personal_snippets_files.rb b/db/post_migrate/20170612071012_move_personal_snippets_files.rb
index c735dc67f44..d32d92637fa 100644
--- a/db/post_migrate/20170612071012_move_personal_snippets_files.rb
+++ b/db/post_migrate/20170612071012_move_personal_snippets_files.rb
@@ -1,6 +1,6 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MovePersonalSnippetsFiles < ActiveRecord::Migration
+class MovePersonalSnippetsFiles < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/post_migrate/20170613111224_clean_appearance_symlinks.rb b/db/post_migrate/20170613111224_clean_appearance_symlinks.rb
index 17849b78ceb..14511bff3db 100644
--- a/db/post_migrate/20170613111224_clean_appearance_symlinks.rb
+++ b/db/post_migrate/20170613111224_clean_appearance_symlinks.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class CleanAppearanceSymlinks < ActiveRecord::Migration
+class CleanAppearanceSymlinks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/post_migrate/20170621102400_add_stage_id_index_to_builds.rb b/db/post_migrate/20170621102400_add_stage_id_index_to_builds.rb
index ac61b5c84a8..cca9b488547 100644
--- a/db/post_migrate/20170621102400_add_stage_id_index_to_builds.rb
+++ b/db/post_migrate/20170621102400_add_stage_id_index_to_builds.rb
@@ -1,4 +1,4 @@
-class AddStageIdIndexToBuilds < ActiveRecord::Migration
+class AddStageIdIndexToBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170627101016_schedule_event_migrations.rb b/db/post_migrate/20170627101016_schedule_event_migrations.rb
index 1e020d05f78..f026a86bc0f 100644
--- a/db/post_migrate/20170627101016_schedule_event_migrations.rb
+++ b/db/post_migrate/20170627101016_schedule_event_migrations.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class ScheduleEventMigrations < ActiveRecord::Migration
+class ScheduleEventMigrations < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170628080858_migrate_stage_id_reference_in_background.rb b/db/post_migrate/20170628080858_migrate_stage_id_reference_in_background.rb
index f31015d77a3..36aac3df071 100644
--- a/db/post_migrate/20170628080858_migrate_stage_id_reference_in_background.rb
+++ b/db/post_migrate/20170628080858_migrate_stage_id_reference_in_background.rb
@@ -1,4 +1,4 @@
-class MigrateStageIdReferenceInBackground < ActiveRecord::Migration
+class MigrateStageIdReferenceInBackground < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170629180131_cleanup_application_settings_signin_enabled_rename.rb b/db/post_migrate/20170629180131_cleanup_application_settings_signin_enabled_rename.rb
index 52a773ddfee..87268fb4b31 100644
--- a/db/post_migrate/20170629180131_cleanup_application_settings_signin_enabled_rename.rb
+++ b/db/post_migrate/20170629180131_cleanup_application_settings_signin_enabled_rename.rb
@@ -1,4 +1,4 @@
-class CleanupApplicationSettingsSigninEnabledRename < ActiveRecord::Migration
+class CleanupApplicationSettingsSigninEnabledRename < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170703130158_schedule_merge_request_diff_migrations.rb b/db/post_migrate/20170703130158_schedule_merge_request_diff_migrations.rb
index 17a9dc293f1..fd4b2859f7f 100644
--- a/db/post_migrate/20170703130158_schedule_merge_request_diff_migrations.rb
+++ b/db/post_migrate/20170703130158_schedule_merge_request_diff_migrations.rb
@@ -1,4 +1,4 @@
-class ScheduleMergeRequestDiffMigrations < ActiveRecord::Migration
+class ScheduleMergeRequestDiffMigrations < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170711145558_migrate_stages_statuses.rb b/db/post_migrate/20170711145558_migrate_stages_statuses.rb
index 265f7317b9b..8ba69ea4dce 100644
--- a/db/post_migrate/20170711145558_migrate_stages_statuses.rb
+++ b/db/post_migrate/20170711145558_migrate_stages_statuses.rb
@@ -1,4 +1,4 @@
-class MigrateStagesStatuses < ActiveRecord::Migration
+class MigrateStagesStatuses < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170717111152_cleanup_move_system_upload_folder_symlink.rb b/db/post_migrate/20170717111152_cleanup_move_system_upload_folder_symlink.rb
index c48f1c938d0..392c4f71532 100644
--- a/db/post_migrate/20170717111152_cleanup_move_system_upload_folder_symlink.rb
+++ b/db/post_migrate/20170717111152_cleanup_move_system_upload_folder_symlink.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class CleanupMoveSystemUploadFolderSymlink < ActiveRecord::Migration
+class CleanupMoveSystemUploadFolderSymlink < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
@@ -13,7 +13,7 @@ class CleanupMoveSystemUploadFolderSymlink < ActiveRecord::Migration
say "Removing #{old_directory} -> #{new_directory} symlink"
FileUtils.rm(old_directory)
else
- say "Symlink #{old_directory} non existant, nothing to do."
+ say "Symlink #{old_directory} non existent, nothing to do."
end
end
diff --git a/db/post_migrate/20170717150329_enqueue_migrate_system_uploads_to_new_folder.rb b/db/post_migrate/20170717150329_enqueue_migrate_system_uploads_to_new_folder.rb
index 87069dce006..fdd990ae2e5 100644
--- a/db/post_migrate/20170717150329_enqueue_migrate_system_uploads_to_new_folder.rb
+++ b/db/post_migrate/20170717150329_enqueue_migrate_system_uploads_to_new_folder.rb
@@ -1,4 +1,4 @@
-class EnqueueMigrateSystemUploadsToNewFolder < ActiveRecord::Migration
+class EnqueueMigrateSystemUploadsToNewFolder < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170719150301_merge_issuable_reopened_into_opened_state.rb b/db/post_migrate/20170719150301_merge_issuable_reopened_into_opened_state.rb
index acc0fc7a0ac..7af1d04f0cc 100644
--- a/db/post_migrate/20170719150301_merge_issuable_reopened_into_opened_state.rb
+++ b/db/post_migrate/20170719150301_merge_issuable_reopened_into_opened_state.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MergeIssuableReopenedIntoOpenedState < ActiveRecord::Migration
+class MergeIssuableReopenedIntoOpenedState < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170728101014_remove_events_from_notification_settings.rb b/db/post_migrate/20170728101014_remove_events_from_notification_settings.rb
index cd533391d8d..f1b0a1daec5 100644
--- a/db/post_migrate/20170728101014_remove_events_from_notification_settings.rb
+++ b/db/post_migrate/20170728101014_remove_events_from_notification_settings.rb
@@ -1,4 +1,4 @@
-class RemoveEventsFromNotificationSettings < ActiveRecord::Migration
+class RemoveEventsFromNotificationSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170803090603_calculate_conv_dev_index_percentages.rb b/db/post_migrate/20170803090603_calculate_conv_dev_index_percentages.rb
index 9af76c94bf3..a148586ca89 100644
--- a/db/post_migrate/20170803090603_calculate_conv_dev_index_percentages.rb
+++ b/db/post_migrate/20170803090603_calculate_conv_dev_index_percentages.rb
@@ -1,4 +1,4 @@
-class CalculateConvDevIndexPercentages < ActiveRecord::Migration
+class CalculateConvDevIndexPercentages < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170807160457_remove_locked_at_column_from_merge_requests.rb b/db/post_migrate/20170807160457_remove_locked_at_column_from_merge_requests.rb
index ea3d1fb3e02..6dc49211e5a 100644
--- a/db/post_migrate/20170807160457_remove_locked_at_column_from_merge_requests.rb
+++ b/db/post_migrate/20170807160457_remove_locked_at_column_from_merge_requests.rb
@@ -1,4 +1,4 @@
-class RemoveLockedAtColumnFromMergeRequests < ActiveRecord::Migration
+class RemoveLockedAtColumnFromMergeRequests < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/post_migrate/20170807190736_move_personal_snippet_files_into_correct_folder.rb b/db/post_migrate/20170807190736_move_personal_snippet_files_into_correct_folder.rb
index e3d2446b897..8341ac39c25 100644
--- a/db/post_migrate/20170807190736_move_personal_snippet_files_into_correct_folder.rb
+++ b/db/post_migrate/20170807190736_move_personal_snippet_files_into_correct_folder.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MovePersonalSnippetFilesIntoCorrectFolder < ActiveRecord::Migration
+class MovePersonalSnippetFilesIntoCorrectFolder < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/post_migrate/20170815060945_remove_duplicate_mr_events.rb b/db/post_migrate/20170815060945_remove_duplicate_mr_events.rb
index 6132b553177..fdc126b8fd6 100644
--- a/db/post_migrate/20170815060945_remove_duplicate_mr_events.rb
+++ b/db/post_migrate/20170815060945_remove_duplicate_mr_events.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveDuplicateMrEvents < ActiveRecord::Migration
+class RemoveDuplicateMrEvents < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170816102555_cleanup_nonexisting_namespace_pending_delete_projects.rb b/db/post_migrate/20170816102555_cleanup_nonexisting_namespace_pending_delete_projects.rb
index 3f085c17133..27656fd926d 100644
--- a/db/post_migrate/20170816102555_cleanup_nonexisting_namespace_pending_delete_projects.rb
+++ b/db/post_migrate/20170816102555_cleanup_nonexisting_namespace_pending_delete_projects.rb
@@ -1,7 +1,7 @@
# Follow up of CleanupNamespacelessPendingDeleteProjects and it cleans
# all projects with `pending_delete = true` and for which the
# namespace no longer exists.
-class CleanupNonexistingNamespacePendingDeleteProjects < ActiveRecord::Migration
+class CleanupNonexistingNamespacePendingDeleteProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170822101017_migrate_pipeline_sidekiq_queues.rb b/db/post_migrate/20170822101017_migrate_pipeline_sidekiq_queues.rb
index 8441cfe7968..825bc9250bd 100644
--- a/db/post_migrate/20170822101017_migrate_pipeline_sidekiq_queues.rb
+++ b/db/post_migrate/20170822101017_migrate_pipeline_sidekiq_queues.rb
@@ -1,4 +1,4 @@
-class MigratePipelineSidekiqQueues < ActiveRecord::Migration
+class MigratePipelineSidekiqQueues < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170828170502_post_deploy_migrate_user_external_mail_data.rb b/db/post_migrate/20170828170502_post_deploy_migrate_user_external_mail_data.rb
index fd1437b07f5..533155aeb7a 100644
--- a/db/post_migrate/20170828170502_post_deploy_migrate_user_external_mail_data.rb
+++ b/db/post_migrate/20170828170502_post_deploy_migrate_user_external_mail_data.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class PostDeployMigrateUserExternalMailData < ActiveRecord::Migration
+class PostDeployMigrateUserExternalMailData < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170828170513_remove_user_email_provider_column.rb b/db/post_migrate/20170828170513_remove_user_email_provider_column.rb
index 570f2b3772a..bfc8aede540 100644
--- a/db/post_migrate/20170828170513_remove_user_email_provider_column.rb
+++ b/db/post_migrate/20170828170513_remove_user_email_provider_column.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveUserEmailProviderColumn < ActiveRecord::Migration
+class RemoveUserEmailProviderColumn < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170828170516_remove_user_external_mail_columns.rb b/db/post_migrate/20170828170516_remove_user_external_mail_columns.rb
index bb81dc682b3..0104955e5c8 100644
--- a/db/post_migrate/20170828170516_remove_user_external_mail_columns.rb
+++ b/db/post_migrate/20170828170516_remove_user_external_mail_columns.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveUserExternalMailColumns < ActiveRecord::Migration
+class RemoveUserExternalMailColumns < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170830084744_destroy_gpg_signatures.rb b/db/post_migrate/20170830084744_destroy_gpg_signatures.rb
index b04d36f6537..2945eb9fde6 100644
--- a/db/post_migrate/20170830084744_destroy_gpg_signatures.rb
+++ b/db/post_migrate/20170830084744_destroy_gpg_signatures.rb
@@ -1,4 +1,4 @@
-class DestroyGpgSignatures < ActiveRecord::Migration
+class DestroyGpgSignatures < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/post_migrate/20170830150306_drop_events_for_migration_table.rb b/db/post_migrate/20170830150306_drop_events_for_migration_table.rb
index 69a612ead40..3538b52b004 100644
--- a/db/post_migrate/20170830150306_drop_events_for_migration_table.rb
+++ b/db/post_migrate/20170830150306_drop_events_for_migration_table.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class DropEventsForMigrationTable < ActiveRecord::Migration
+class DropEventsForMigrationTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170831195038_remove_valid_signature_from_gpg_signatures.rb b/db/post_migrate/20170831195038_remove_valid_signature_from_gpg_signatures.rb
index 9b6745e33d9..8e264c1ab41 100644
--- a/db/post_migrate/20170831195038_remove_valid_signature_from_gpg_signatures.rb
+++ b/db/post_migrate/20170831195038_remove_valid_signature_from_gpg_signatures.rb
@@ -1,4 +1,4 @@
-class RemoveValidSignatureFromGpgSignatures < ActiveRecord::Migration
+class RemoveValidSignatureFromGpgSignatures < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/post_migrate/20170907170235_delete_conflicting_redirect_routes.rb b/db/post_migrate/20170907170235_delete_conflicting_redirect_routes.rb
index 033019c398e..95abf2474dd 100644
--- a/db/post_migrate/20170907170235_delete_conflicting_redirect_routes.rb
+++ b/db/post_migrate/20170907170235_delete_conflicting_redirect_routes.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class DeleteConflictingRedirectRoutes < ActiveRecord::Migration
+class DeleteConflictingRedirectRoutes < ActiveRecord::Migration[4.2]
def up
# No-op.
# See https://gitlab.com/gitlab-com/infrastructure/issues/3460#note_53223252
diff --git a/db/post_migrate/20170913180600_fix_projects_without_project_feature.rb b/db/post_migrate/20170913180600_fix_projects_without_project_feature.rb
index bfa9ad80c7d..bbc624ac7c0 100644
--- a/db/post_migrate/20170913180600_fix_projects_without_project_feature.rb
+++ b/db/post_migrate/20170913180600_fix_projects_without_project_feature.rb
@@ -1,4 +1,4 @@
-class FixProjectsWithoutProjectFeature < ActiveRecord::Migration
+class FixProjectsWithoutProjectFeature < ActiveRecord::Migration[4.2]
DOWNTIME = false
def up
diff --git a/db/post_migrate/20170921101004_normalize_ldap_extern_uids.rb b/db/post_migrate/20170921101004_normalize_ldap_extern_uids.rb
index 2230bb0e53c..9080acee1d6 100644
--- a/db/post_migrate/20170921101004_normalize_ldap_extern_uids.rb
+++ b/db/post_migrate/20170921101004_normalize_ldap_extern_uids.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class NormalizeLdapExternUids < ActiveRecord::Migration
+class NormalizeLdapExternUids < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170926150348_schedule_merge_request_diff_migrations_take_two.rb b/db/post_migrate/20170926150348_schedule_merge_request_diff_migrations_take_two.rb
index 5732cb85ea5..9b675a51725 100644
--- a/db/post_migrate/20170926150348_schedule_merge_request_diff_migrations_take_two.rb
+++ b/db/post_migrate/20170926150348_schedule_merge_request_diff_migrations_take_two.rb
@@ -1,4 +1,4 @@
-class ScheduleMergeRequestDiffMigrationsTakeTwo < ActiveRecord::Migration
+class ScheduleMergeRequestDiffMigrationsTakeTwo < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170927112318_update_legacy_diff_notes_type_for_import.rb b/db/post_migrate/20170927112318_update_legacy_diff_notes_type_for_import.rb
index b040c81b316..83c21c203e0 100644
--- a/db/post_migrate/20170927112318_update_legacy_diff_notes_type_for_import.rb
+++ b/db/post_migrate/20170927112318_update_legacy_diff_notes_type_for_import.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/UpdateLargeTable
-class UpdateLegacyDiffNotesTypeForImport < ActiveRecord::Migration
+class UpdateLegacyDiffNotesTypeForImport < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20170927112319_update_notes_type_for_import.rb b/db/post_migrate/20170927112319_update_notes_type_for_import.rb
index 5a400c71b02..8c691de3192 100644
--- a/db/post_migrate/20170927112319_update_notes_type_for_import.rb
+++ b/db/post_migrate/20170927112319_update_notes_type_for_import.rb
@@ -1,5 +1,5 @@
# rubocop:disable Migration/UpdateLargeTable
-class UpdateNotesTypeForImport < ActiveRecord::Migration
+class UpdateNotesTypeForImport < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171005130944_schedule_create_gpg_key_subkeys_from_gpg_keys.rb b/db/post_migrate/20171005130944_schedule_create_gpg_key_subkeys_from_gpg_keys.rb
index 467c584c2e0..e49a70f902c 100644
--- a/db/post_migrate/20171005130944_schedule_create_gpg_key_subkeys_from_gpg_keys.rb
+++ b/db/post_migrate/20171005130944_schedule_create_gpg_key_subkeys_from_gpg_keys.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class ScheduleCreateGpgKeySubkeysFromGpgKeys < ActiveRecord::Migration
+class ScheduleCreateGpgKeySubkeysFromGpgKeys < ActiveRecord::Migration[4.2]
disable_ddl_transaction!
DOWNTIME = false
diff --git a/db/post_migrate/20171012150314_remove_user_authentication_token.rb b/db/post_migrate/20171012150314_remove_user_authentication_token.rb
index d0f3aa06e98..9313986ce85 100644
--- a/db/post_migrate/20171012150314_remove_user_authentication_token.rb
+++ b/db/post_migrate/20171012150314_remove_user_authentication_token.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveUserAuthenticationToken < ActiveRecord::Migration
+class RemoveUserAuthenticationToken < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171013104327_migrate_gcp_clusters_to_new_clusters_architectures.rb b/db/post_migrate/20171013104327_migrate_gcp_clusters_to_new_clusters_architectures.rb
index 28cd0f70cc2..9c90aa611a4 100644
--- a/db/post_migrate/20171013104327_migrate_gcp_clusters_to_new_clusters_architectures.rb
+++ b/db/post_migrate/20171013104327_migrate_gcp_clusters_to_new_clusters_architectures.rb
@@ -1,4 +1,4 @@
-class MigrateGcpClustersToNewClustersArchitectures < ActiveRecord::Migration
+class MigrateGcpClustersToNewClustersArchitectures < ActiveRecord::Migration[4.2]
DOWNTIME = false
class GcpCluster < ActiveRecord::Base
diff --git a/db/post_migrate/20171026082505_schedule_merge_request_latest_merge_request_diff_id_migrations.rb b/db/post_migrate/20171026082505_schedule_merge_request_latest_merge_request_diff_id_migrations.rb
index 7a63382cc6d..764561de997 100644
--- a/db/post_migrate/20171026082505_schedule_merge_request_latest_merge_request_diff_id_migrations.rb
+++ b/db/post_migrate/20171026082505_schedule_merge_request_latest_merge_request_diff_id_migrations.rb
@@ -1,4 +1,4 @@
-class ScheduleMergeRequestLatestMergeRequestDiffIdMigrations < ActiveRecord::Migration
+class ScheduleMergeRequestLatestMergeRequestDiffIdMigrations < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171101134435_remove_ref_fetched_from_merge_requests.rb b/db/post_migrate/20171101134435_remove_ref_fetched_from_merge_requests.rb
index 4e8f495d65d..e6a5ffc8649 100644
--- a/db/post_migrate/20171101134435_remove_ref_fetched_from_merge_requests.rb
+++ b/db/post_migrate/20171101134435_remove_ref_fetched_from_merge_requests.rb
@@ -1,4 +1,4 @@
-class RemoveRefFetchedFromMergeRequests < ActiveRecord::Migration
+class RemoveRefFetchedFromMergeRequests < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/post_migrate/20171103140253_track_untracked_uploads.rb b/db/post_migrate/20171103140253_track_untracked_uploads.rb
index 548a94d2d38..6891ef5ba12 100644
--- a/db/post_migrate/20171103140253_track_untracked_uploads.rb
+++ b/db/post_migrate/20171103140253_track_untracked_uploads.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class TrackUntrackedUploads < ActiveRecord::Migration
+class TrackUntrackedUploads < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/post_migrate/20171106133144_cleanup_application_settings_password_authentication_enabled_rename.rb b/db/post_migrate/20171106133144_cleanup_application_settings_password_authentication_enabled_rename.rb
index d54ff3d5f5e..4a01bf75f50 100644
--- a/db/post_migrate/20171106133144_cleanup_application_settings_password_authentication_enabled_rename.rb
+++ b/db/post_migrate/20171106133144_cleanup_application_settings_password_authentication_enabled_rename.rb
@@ -1,4 +1,4 @@
-class CleanupApplicationSettingsPasswordAuthenticationEnabledRename < ActiveRecord::Migration
+class CleanupApplicationSettingsPasswordAuthenticationEnabledRename < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171106154015_remove_issues_branch_name.rb b/db/post_migrate/20171106154015_remove_issues_branch_name.rb
index 3d08225c96d..4e71aa2f163 100644
--- a/db/post_migrate/20171106154015_remove_issues_branch_name.rb
+++ b/db/post_migrate/20171106154015_remove_issues_branch_name.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveIssuesBranchName < ActiveRecord::Migration
+class RemoveIssuesBranchName < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/post_migrate/20171106180641_cleanup_add_timezone_to_issues_closed_at.rb b/db/post_migrate/20171106180641_cleanup_add_timezone_to_issues_closed_at.rb
index 53f376f216b..8187d3971fc 100644
--- a/db/post_migrate/20171106180641_cleanup_add_timezone_to_issues_closed_at.rb
+++ b/db/post_migrate/20171106180641_cleanup_add_timezone_to_issues_closed_at.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class CleanupAddTimezoneToIssuesClosedAt < ActiveRecord::Migration
+class CleanupAddTimezoneToIssuesClosedAt < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171114104051_remove_empty_fork_networks.rb b/db/post_migrate/20171114104051_remove_empty_fork_networks.rb
index 2fe99a1b9c1..76862cccf60 100644
--- a/db/post_migrate/20171114104051_remove_empty_fork_networks.rb
+++ b/db/post_migrate/20171114104051_remove_empty_fork_networks.rb
@@ -1,4 +1,4 @@
-class RemoveEmptyForkNetworks < ActiveRecord::Migration
+class RemoveEmptyForkNetworks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171121160421_remove_merge_request_diff_st_commits_and_st_diffs.rb b/db/post_migrate/20171121160421_remove_merge_request_diff_st_commits_and_st_diffs.rb
index 3a7b2a7fac0..93a97993f1f 100644
--- a/db/post_migrate/20171121160421_remove_merge_request_diff_st_commits_and_st_diffs.rb
+++ b/db/post_migrate/20171121160421_remove_merge_request_diff_st_commits_and_st_diffs.rb
@@ -1,4 +1,4 @@
-class RemoveMergeRequestDiffStCommitsAndStDiffs < ActiveRecord::Migration
+class RemoveMergeRequestDiffStCommitsAndStDiffs < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171123101020_update_circuitbreaker_defaults.rb b/db/post_migrate/20171123101020_update_circuitbreaker_defaults.rb
index 8e1c9e6d6bb..ae954289291 100644
--- a/db/post_migrate/20171123101020_update_circuitbreaker_defaults.rb
+++ b/db/post_migrate/20171123101020_update_circuitbreaker_defaults.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class UpdateCircuitbreakerDefaults < ActiveRecord::Migration
+class UpdateCircuitbreakerDefaults < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171123101046_remove_old_circuitbreaker_config.rb b/db/post_migrate/20171123101046_remove_old_circuitbreaker_config.rb
index e646d4d3224..3f2c1b2170a 100644
--- a/db/post_migrate/20171123101046_remove_old_circuitbreaker_config.rb
+++ b/db/post_migrate/20171123101046_remove_old_circuitbreaker_config.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveOldCircuitbreakerConfig < ActiveRecord::Migration
+class RemoveOldCircuitbreakerConfig < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171124095655_add_index_on_merge_request_diffs_merge_request_id_and_id.rb b/db/post_migrate/20171124095655_add_index_on_merge_request_diffs_merge_request_id_and_id.rb
index 698df712c11..2c65a4ae4f5 100644
--- a/db/post_migrate/20171124095655_add_index_on_merge_request_diffs_merge_request_id_and_id.rb
+++ b/db/post_migrate/20171124095655_add_index_on_merge_request_diffs_merge_request_id_and_id.rb
@@ -1,4 +1,4 @@
-class AddIndexOnMergeRequestDiffsMergeRequestIdAndId < ActiveRecord::Migration
+class AddIndexOnMergeRequestDiffsMergeRequestIdAndId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171124100152_remove_index_on_merge_request_diffs_merge_request_diff_id.rb b/db/post_migrate/20171124100152_remove_index_on_merge_request_diffs_merge_request_diff_id.rb
index 038e4807000..efd3714d668 100644
--- a/db/post_migrate/20171124100152_remove_index_on_merge_request_diffs_merge_request_diff_id.rb
+++ b/db/post_migrate/20171124100152_remove_index_on_merge_request_diffs_merge_request_diff_id.rb
@@ -1,4 +1,4 @@
-class RemoveIndexOnMergeRequestDiffsMergeRequestDiffId < ActiveRecord::Migration
+class RemoveIndexOnMergeRequestDiffsMergeRequestDiffId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171124104327_migrate_kubernetes_service_to_new_clusters_architectures.rb b/db/post_migrate/20171124104327_migrate_kubernetes_service_to_new_clusters_architectures.rb
index a957f107405..58ceefe3c97 100644
--- a/db/post_migrate/20171124104327_migrate_kubernetes_service_to_new_clusters_architectures.rb
+++ b/db/post_migrate/20171124104327_migrate_kubernetes_service_to_new_clusters_architectures.rb
@@ -1,4 +1,4 @@
-class MigrateKubernetesServiceToNewClustersArchitectures < ActiveRecord::Migration
+class MigrateKubernetesServiceToNewClustersArchitectures < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171124150326_reschedule_fork_network_creation.rb b/db/post_migrate/20171124150326_reschedule_fork_network_creation.rb
index 26f917d5a1e..8e320ea9e8d 100644
--- a/db/post_migrate/20171124150326_reschedule_fork_network_creation.rb
+++ b/db/post_migrate/20171124150326_reschedule_fork_network_creation.rb
@@ -1,4 +1,4 @@
-class RescheduleForkNetworkCreation < ActiveRecord::Migration
+class RescheduleForkNetworkCreation < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171128214150_schedule_populate_merge_request_metrics_with_events_data.rb b/db/post_migrate/20171128214150_schedule_populate_merge_request_metrics_with_events_data.rb
index 980f76e7d57..51441a36e4b 100644
--- a/db/post_migrate/20171128214150_schedule_populate_merge_request_metrics_with_events_data.rb
+++ b/db/post_migrate/20171128214150_schedule_populate_merge_request_metrics_with_events_data.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class SchedulePopulateMergeRequestMetricsWithEventsData < ActiveRecord::Migration
+class SchedulePopulateMergeRequestMetricsWithEventsData < ActiveRecord::Migration[4.2]
DOWNTIME = false
BATCH_SIZE = 10_000
MIGRATION = 'PopulateMergeRequestMetricsWithEventsData'
diff --git a/db/post_migrate/20171205190711_reschedule_fork_network_creation_caller.rb b/db/post_migrate/20171205190711_reschedule_fork_network_creation_caller.rb
index 30ff5173192..058f3a40817 100644
--- a/db/post_migrate/20171205190711_reschedule_fork_network_creation_caller.rb
+++ b/db/post_migrate/20171205190711_reschedule_fork_network_creation_caller.rb
@@ -1,4 +1,4 @@
-class RescheduleForkNetworkCreationCaller < ActiveRecord::Migration
+class RescheduleForkNetworkCreationCaller < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171207150300_remove_project_labels_group_id_copy.rb b/db/post_migrate/20171207150300_remove_project_labels_group_id_copy.rb
index 2f339172eeb..44273cebc9d 100644
--- a/db/post_migrate/20171207150300_remove_project_labels_group_id_copy.rb
+++ b/db/post_migrate/20171207150300_remove_project_labels_group_id_copy.rb
@@ -1,7 +1,7 @@
# Copy of 20180202111106 - this one should run before 20171207150343 to fix issues related to
# the removal of groups with labels.
-class RemoveProjectLabelsGroupIdCopy < ActiveRecord::Migration
+class RemoveProjectLabelsGroupIdCopy < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171207150343_remove_soft_removed_objects.rb b/db/post_migrate/20171207150343_remove_soft_removed_objects.rb
index 3109b6dbf8e..53707c67d36 100644
--- a/db/post_migrate/20171207150343_remove_soft_removed_objects.rb
+++ b/db/post_migrate/20171207150343_remove_soft_removed_objects.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveSoftRemovedObjects < ActiveRecord::Migration
+class RemoveSoftRemovedObjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/post_migrate/20171207150344_remove_deleted_at_columns.rb b/db/post_migrate/20171207150344_remove_deleted_at_columns.rb
index 154d7a1b926..5f1c70a2797 100644
--- a/db/post_migrate/20171207150344_remove_deleted_at_columns.rb
+++ b/db/post_migrate/20171207150344_remove_deleted_at_columns.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveDeletedAtColumns < ActiveRecord::Migration
+class RemoveDeletedAtColumns < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171213160445_migrate_github_importer_advance_stage_sidekiq_queue.rb b/db/post_migrate/20171213160445_migrate_github_importer_advance_stage_sidekiq_queue.rb
index 149c28f1946..088c4b5d46b 100644
--- a/db/post_migrate/20171213160445_migrate_github_importer_advance_stage_sidekiq_queue.rb
+++ b/db/post_migrate/20171213160445_migrate_github_importer_advance_stage_sidekiq_queue.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class MigrateGithubImporterAdvanceStageSidekiqQueue < ActiveRecord::Migration
+class MigrateGithubImporterAdvanceStageSidekiqQueue < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171215121205_post_populate_can_push_from_deploy_keys_projects.rb b/db/post_migrate/20171215121205_post_populate_can_push_from_deploy_keys_projects.rb
index 3a5850df3db..1c81e56db55 100644
--- a/db/post_migrate/20171215121205_post_populate_can_push_from_deploy_keys_projects.rb
+++ b/db/post_migrate/20171215121205_post_populate_can_push_from_deploy_keys_projects.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class PostPopulateCanPushFromDeployKeysProjects < ActiveRecord::Migration
+class PostPopulateCanPushFromDeployKeysProjects < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171215121259_remove_can_push_from_keys.rb b/db/post_migrate/20171215121259_remove_can_push_from_keys.rb
index 0599811d986..fc4045a383d 100644
--- a/db/post_migrate/20171215121259_remove_can_push_from_keys.rb
+++ b/db/post_migrate/20171215121259_remove_can_push_from_keys.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveCanPushFromKeys < ActiveRecord::Migration
+class RemoveCanPushFromKeys < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171219121201_normalize_extern_uid_from_identities.rb b/db/post_migrate/20171219121201_normalize_extern_uid_from_identities.rb
index 286721a0894..45ef75fdb98 100644
--- a/db/post_migrate/20171219121201_normalize_extern_uid_from_identities.rb
+++ b/db/post_migrate/20171219121201_normalize_extern_uid_from_identities.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class NormalizeExternUidFromIdentities < ActiveRecord::Migration
+class NormalizeExternUidFromIdentities < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20171221140220_schedule_issues_closed_at_type_change.rb b/db/post_migrate/20171221140220_schedule_issues_closed_at_type_change.rb
index eeecc7b1de0..6b5e6202688 100644
--- a/db/post_migrate/20171221140220_schedule_issues_closed_at_type_change.rb
+++ b/db/post_migrate/20171221140220_schedule_issues_closed_at_type_change.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
# rubocop:disable Migration/Datetime
-class ScheduleIssuesClosedAtTypeChange < ActiveRecord::Migration
+class ScheduleIssuesClosedAtTypeChange < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180104131052_schedule_set_confidential_note_events_on_webhooks.rb b/db/post_migrate/20180104131052_schedule_set_confidential_note_events_on_webhooks.rb
index fa51ac83619..0822aebc2c6 100644
--- a/db/post_migrate/20180104131052_schedule_set_confidential_note_events_on_webhooks.rb
+++ b/db/post_migrate/20180104131052_schedule_set_confidential_note_events_on_webhooks.rb
@@ -1,4 +1,4 @@
-class ScheduleSetConfidentialNoteEventsOnWebhooks < ActiveRecord::Migration
+class ScheduleSetConfidentialNoteEventsOnWebhooks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180119121225_remove_redundant_pipeline_stages.rb b/db/post_migrate/20180119121225_remove_redundant_pipeline_stages.rb
index 269f1287f91..0a2ea7bfb7b 100644
--- a/db/post_migrate/20180119121225_remove_redundant_pipeline_stages.rb
+++ b/db/post_migrate/20180119121225_remove_redundant_pipeline_stages.rb
@@ -1,4 +1,4 @@
-class RemoveRedundantPipelineStages < ActiveRecord::Migration
+class RemoveRedundantPipelineStages < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180122154930_schedule_set_confidential_note_events_on_services.rb b/db/post_migrate/20180122154930_schedule_set_confidential_note_events_on_services.rb
index a3ff9f1719e..98bbb34dda1 100644
--- a/db/post_migrate/20180122154930_schedule_set_confidential_note_events_on_services.rb
+++ b/db/post_migrate/20180122154930_schedule_set_confidential_note_events_on_services.rb
@@ -1,4 +1,4 @@
-class ScheduleSetConfidentialNoteEventsOnServices < ActiveRecord::Migration
+class ScheduleSetConfidentialNoteEventsOnServices < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180202111106_remove_project_labels_group_id.rb b/db/post_migrate/20180202111106_remove_project_labels_group_id.rb
index db7fd0d167d..31ec84f0d6a 100644
--- a/db/post_migrate/20180202111106_remove_project_labels_group_id.rb
+++ b/db/post_migrate/20180202111106_remove_project_labels_group_id.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemoveProjectLabelsGroupId < ActiveRecord::Migration
+class RemoveProjectLabelsGroupId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180204200836_change_author_id_to_not_null_in_todos.rb b/db/post_migrate/20180204200836_change_author_id_to_not_null_in_todos.rb
index 92c32feebf7..54b8a91fa47 100644
--- a/db/post_migrate/20180204200836_change_author_id_to_not_null_in_todos.rb
+++ b/db/post_migrate/20180204200836_change_author_id_to_not_null_in_todos.rb
@@ -1,4 +1,4 @@
-class ChangeAuthorIdToNotNullInTodos < ActiveRecord::Migration
+class ChangeAuthorIdToNotNullInTodos < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
class Todo < ActiveRecord::Base
diff --git a/db/post_migrate/20180212101828_add_tmp_partial_null_index_to_builds.rb b/db/post_migrate/20180212101828_add_tmp_partial_null_index_to_builds.rb
index e55e2e6f888..f8badcac990 100644
--- a/db/post_migrate/20180212101828_add_tmp_partial_null_index_to_builds.rb
+++ b/db/post_migrate/20180212101828_add_tmp_partial_null_index_to_builds.rb
@@ -1,4 +1,4 @@
-class AddTmpPartialNullIndexToBuilds < ActiveRecord::Migration
+class AddTmpPartialNullIndexToBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/post_migrate/20180212101928_schedule_build_stage_migration.rb b/db/post_migrate/20180212101928_schedule_build_stage_migration.rb
index 0f61fa81832..2445ab1a130 100644
--- a/db/post_migrate/20180212101928_schedule_build_stage_migration.rb
+++ b/db/post_migrate/20180212101928_schedule_build_stage_migration.rb
@@ -1,4 +1,4 @@
-class ScheduleBuildStageMigration < ActiveRecord::Migration
+class ScheduleBuildStageMigration < ActiveRecord::Migration[4.2]
##
# This migration has been rescheduled to run again, see
# `20180405101928_reschedule_builds_stages_migration.rb`
diff --git a/db/post_migrate/20180212102028_remove_tmp_partial_null_index_from_builds.rb b/db/post_migrate/20180212102028_remove_tmp_partial_null_index_from_builds.rb
index ed7b1fc72f4..2444df881b8 100644
--- a/db/post_migrate/20180212102028_remove_tmp_partial_null_index_from_builds.rb
+++ b/db/post_migrate/20180212102028_remove_tmp_partial_null_index_from_builds.rb
@@ -1,4 +1,4 @@
-class RemoveTmpPartialNullIndexFromBuilds < ActiveRecord::Migration
+class RemoveTmpPartialNullIndexFromBuilds < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/post_migrate/20180216121020_fill_pages_domain_verification_code.rb b/db/post_migrate/20180216121020_fill_pages_domain_verification_code.rb
index d423673d2a5..dae43ee14df 100644
--- a/db/post_migrate/20180216121020_fill_pages_domain_verification_code.rb
+++ b/db/post_migrate/20180216121020_fill_pages_domain_verification_code.rb
@@ -1,4 +1,4 @@
-class FillPagesDomainVerificationCode < ActiveRecord::Migration
+class FillPagesDomainVerificationCode < ActiveRecord::Migration[4.2]
DOWNTIME = false
class PagesDomain < ActiveRecord::Base
diff --git a/db/post_migrate/20180216121030_enqueue_verify_pages_domain_workers.rb b/db/post_migrate/20180216121030_enqueue_verify_pages_domain_workers.rb
index bf9bf4e660f..d776fb85f00 100644
--- a/db/post_migrate/20180216121030_enqueue_verify_pages_domain_workers.rb
+++ b/db/post_migrate/20180216121030_enqueue_verify_pages_domain_workers.rb
@@ -1,4 +1,4 @@
-class EnqueueVerifyPagesDomainWorkers < ActiveRecord::Migration
+class EnqueueVerifyPagesDomainWorkers < ActiveRecord::Migration[4.2]
class PagesDomain < ActiveRecord::Base
include EachBatch
end
diff --git a/db/post_migrate/20180220150310_remove_empty_extern_uid_auth0_identities.rb b/db/post_migrate/20180220150310_remove_empty_extern_uid_auth0_identities.rb
index 2d5a8617169..86ef333685e 100644
--- a/db/post_migrate/20180220150310_remove_empty_extern_uid_auth0_identities.rb
+++ b/db/post_migrate/20180220150310_remove_empty_extern_uid_auth0_identities.rb
@@ -1,4 +1,4 @@
-class RemoveEmptyExternUidAuth0Identities < ActiveRecord::Migration
+class RemoveEmptyExternUidAuth0Identities < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180223124427_build_user_interacted_projects_table.rb b/db/post_migrate/20180223124427_build_user_interacted_projects_table.rb
index 8c8dbb1a043..fa332fd5c70 100644
--- a/db/post_migrate/20180223124427_build_user_interacted_projects_table.rb
+++ b/db/post_migrate/20180223124427_build_user_interacted_projects_table.rb
@@ -1,7 +1,7 @@
require_relative '../migrate/20180223120443_create_user_interacted_projects_table.rb'
# rubocop:disable AddIndex
# rubocop:disable AddConcurrentForeignKey
-class BuildUserInteractedProjectsTable < ActiveRecord::Migration
+class BuildUserInteractedProjectsTable < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
@@ -43,7 +43,7 @@ class BuildUserInteractedProjectsTable < ActiveRecord::Migration
end
end
- class PostgresStrategy < ActiveRecord::Migration
+ class PostgresStrategy < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
BATCH_SIZE = 100_000
@@ -141,7 +141,7 @@ class BuildUserInteractedProjectsTable < ActiveRecord::Migration
end
end
- class MysqlStrategy < ActiveRecord::Migration
+ class MysqlStrategy < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
def up
diff --git a/db/post_migrate/20180301084653_change_project_namespace_id_not_null.rb b/db/post_migrate/20180301084653_change_project_namespace_id_not_null.rb
index 0342372cbed..62a239b0e7c 100644
--- a/db/post_migrate/20180301084653_change_project_namespace_id_not_null.rb
+++ b/db/post_migrate/20180301084653_change_project_namespace_id_not_null.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class ChangeProjectNamespaceIdNotNull < ActiveRecord::Migration
+class ChangeProjectNamespaceIdNotNull < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
class Project < ActiveRecord::Base
diff --git a/db/post_migrate/20180305100050_remove_permanent_from_redirect_routes.rb b/db/post_migrate/20180305100050_remove_permanent_from_redirect_routes.rb
index aa19732ca1c..15c052da99b 100644
--- a/db/post_migrate/20180305100050_remove_permanent_from_redirect_routes.rb
+++ b/db/post_migrate/20180305100050_remove_permanent_from_redirect_routes.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class RemovePermanentFromRedirectRoutes < ActiveRecord::Migration
+class RemovePermanentFromRedirectRoutes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180306074045_migrate_create_trace_artifact_sidekiq_queue.rb b/db/post_migrate/20180306074045_migrate_create_trace_artifact_sidekiq_queue.rb
index 0af1c3bc0a5..fc74f6f1712 100644
--- a/db/post_migrate/20180306074045_migrate_create_trace_artifact_sidekiq_queue.rb
+++ b/db/post_migrate/20180306074045_migrate_create_trace_artifact_sidekiq_queue.rb
@@ -1,4 +1,4 @@
-class MigrateCreateTraceArtifactSidekiqQueue < ActiveRecord::Migration
+class MigrateCreateTraceArtifactSidekiqQueue < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180306164012_add_path_index_to_redirect_routes.rb b/db/post_migrate/20180306164012_add_path_index_to_redirect_routes.rb
index ca9212fae27..53918250b4c 100644
--- a/db/post_migrate/20180306164012_add_path_index_to_redirect_routes.rb
+++ b/db/post_migrate/20180306164012_add_path_index_to_redirect_routes.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class AddPathIndexToRedirectRoutes < ActiveRecord::Migration
+class AddPathIndexToRedirectRoutes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/post_migrate/20180307012445_migrate_update_head_pipeline_for_merge_request_sidekiq_queue.rb b/db/post_migrate/20180307012445_migrate_update_head_pipeline_for_merge_request_sidekiq_queue.rb
index 9728df6d409..372c04429c7 100644
--- a/db/post_migrate/20180307012445_migrate_update_head_pipeline_for_merge_request_sidekiq_queue.rb
+++ b/db/post_migrate/20180307012445_migrate_update_head_pipeline_for_merge_request_sidekiq_queue.rb
@@ -1,4 +1,4 @@
-class MigrateUpdateHeadPipelineForMergeRequestSidekiqQueue < ActiveRecord::Migration
+class MigrateUpdateHeadPipelineForMergeRequestSidekiqQueue < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180405101928_reschedule_builds_stages_migration.rb b/db/post_migrate/20180405101928_reschedule_builds_stages_migration.rb
index c32123454f9..213d97b71f7 100644
--- a/db/post_migrate/20180405101928_reschedule_builds_stages_migration.rb
+++ b/db/post_migrate/20180405101928_reschedule_builds_stages_migration.rb
@@ -1,4 +1,4 @@
-class RescheduleBuildsStagesMigration < ActiveRecord::Migration
+class RescheduleBuildsStagesMigration < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
##
diff --git a/db/post_migrate/20180408143355_cleanup_users_rss_token_rename.rb b/db/post_migrate/20180408143355_cleanup_users_rss_token_rename.rb
index 3d77ff921c7..813603cb3ad 100644
--- a/db/post_migrate/20180408143355_cleanup_users_rss_token_rename.rb
+++ b/db/post_migrate/20180408143355_cleanup_users_rss_token_rename.rb
@@ -1,4 +1,4 @@
-class CleanupUsersRssTokenRename < ActiveRecord::Migration
+class CleanupUsersRssTokenRename < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
diff --git a/db/post_migrate/20180409170809_populate_missing_project_ci_cd_settings.rb b/db/post_migrate/20180409170809_populate_missing_project_ci_cd_settings.rb
index 3b0fdb3aeea..0cda3d76a3d 100644
--- a/db/post_migrate/20180409170809_populate_missing_project_ci_cd_settings.rb
+++ b/db/post_migrate/20180409170809_populate_missing_project_ci_cd_settings.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class PopulateMissingProjectCiCdSettings < ActiveRecord::Migration
+class PopulateMissingProjectCiCdSettings < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180420080616_schedule_stages_index_migration.rb b/db/post_migrate/20180420080616_schedule_stages_index_migration.rb
index eb82f098639..2d72e75393f 100644
--- a/db/post_migrate/20180420080616_schedule_stages_index_migration.rb
+++ b/db/post_migrate/20180420080616_schedule_stages_index_migration.rb
@@ -1,4 +1,4 @@
-class ScheduleStagesIndexMigration < ActiveRecord::Migration
+class ScheduleStagesIndexMigration < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180424151928_fill_file_store.rb b/db/post_migrate/20180424151928_fill_file_store.rb
index 03d54dab250..45fa10c9550 100644
--- a/db/post_migrate/20180424151928_fill_file_store.rb
+++ b/db/post_migrate/20180424151928_fill_file_store.rb
@@ -1,4 +1,4 @@
-class FillFileStore < ActiveRecord::Migration
+class FillFileStore < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180430143705_backfill_runner_type_for_ci_runners_post_migrate.rb b/db/post_migrate/20180430143705_backfill_runner_type_for_ci_runners_post_migrate.rb
index 0e6ec46e5f0..ba1023866c5 100644
--- a/db/post_migrate/20180430143705_backfill_runner_type_for_ci_runners_post_migrate.rb
+++ b/db/post_migrate/20180430143705_backfill_runner_type_for_ci_runners_post_migrate.rb
@@ -1,4 +1,4 @@
-class BackfillRunnerTypeForCiRunnersPostMigrate < ActiveRecord::Migration
+class BackfillRunnerTypeForCiRunnersPostMigrate < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180502134117_migrate_import_attributes_data_from_projects_to_project_mirror_data.rb b/db/post_migrate/20180502134117_migrate_import_attributes_data_from_projects_to_project_mirror_data.rb
index 08d7d64a2c5..b82ee3569c9 100644
--- a/db/post_migrate/20180502134117_migrate_import_attributes_data_from_projects_to_project_mirror_data.rb
+++ b/db/post_migrate/20180502134117_migrate_import_attributes_data_from_projects_to_project_mirror_data.rb
@@ -1,4 +1,4 @@
-class MigrateImportAttributesDataFromProjectsToProjectMirrorData < ActiveRecord::Migration
+class MigrateImportAttributesDataFromProjectsToProjectMirrorData < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180507083701_set_minimal_project_build_timeout.rb b/db/post_migrate/20180507083701_set_minimal_project_build_timeout.rb
index fb9616f0c07..34edbb08bcf 100644
--- a/db/post_migrate/20180507083701_set_minimal_project_build_timeout.rb
+++ b/db/post_migrate/20180507083701_set_minimal_project_build_timeout.rb
@@ -1,4 +1,4 @@
-class SetMinimalProjectBuildTimeout < ActiveRecord::Migration
+class SetMinimalProjectBuildTimeout < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180511174224_add_unique_constraint_to_project_features_project_id.rb b/db/post_migrate/20180511174224_add_unique_constraint_to_project_features_project_id.rb
index 88a9f5f8256..a526001a91e 100644
--- a/db/post_migrate/20180511174224_add_unique_constraint_to_project_features_project_id.rb
+++ b/db/post_migrate/20180511174224_add_unique_constraint_to_project_features_project_id.rb
@@ -1,4 +1,4 @@
-class AddUniqueConstraintToProjectFeaturesProjectId < ActiveRecord::Migration
+class AddUniqueConstraintToProjectFeaturesProjectId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180512061621_add_not_null_constraint_to_project_features_project_id.rb b/db/post_migrate/20180512061621_add_not_null_constraint_to_project_features_project_id.rb
index 5a6d6ff4a10..e3abbc039e8 100644
--- a/db/post_migrate/20180512061621_add_not_null_constraint_to_project_features_project_id.rb
+++ b/db/post_migrate/20180512061621_add_not_null_constraint_to_project_features_project_id.rb
@@ -1,4 +1,4 @@
-class AddNotNullConstraintToProjectFeaturesProjectId < ActiveRecord::Migration
+class AddNotNullConstraintToProjectFeaturesProjectId < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180514161336_remove_gemnasium_service.rb b/db/post_migrate/20180514161336_remove_gemnasium_service.rb
index 6d7806e8daa..5842bde474c 100644
--- a/db/post_migrate/20180514161336_remove_gemnasium_service.rb
+++ b/db/post_migrate/20180514161336_remove_gemnasium_service.rb
@@ -1,4 +1,4 @@
-class RemoveGemnasiumService < ActiveRecord::Migration
+class RemoveGemnasiumService < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180521162137_migrate_remaining_mr_metrics_populating_background_migration.rb b/db/post_migrate/20180521162137_migrate_remaining_mr_metrics_populating_background_migration.rb
index 0282688fa40..39666a0cd2a 100644
--- a/db/post_migrate/20180521162137_migrate_remaining_mr_metrics_populating_background_migration.rb
+++ b/db/post_migrate/20180521162137_migrate_remaining_mr_metrics_populating_background_migration.rb
@@ -1,4 +1,4 @@
-class MigrateRemainingMrMetricsPopulatingBackgroundMigration < ActiveRecord::Migration
+class MigrateRemainingMrMetricsPopulatingBackgroundMigration < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180523125103_cleanup_merge_requests_allow_maintainer_to_push_rename.rb b/db/post_migrate/20180523125103_cleanup_merge_requests_allow_maintainer_to_push_rename.rb
index 7eca7394f5f..b3b539fd156 100644
--- a/db/post_migrate/20180523125103_cleanup_merge_requests_allow_maintainer_to_push_rename.rb
+++ b/db/post_migrate/20180523125103_cleanup_merge_requests_allow_maintainer_to_push_rename.rb
@@ -1,4 +1,4 @@
-class CleanupMergeRequestsAllowMaintainerToPushRename < ActiveRecord::Migration
+class CleanupMergeRequestsAllowMaintainerToPushRename < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180529152628_schedule_to_archive_legacy_traces.rb b/db/post_migrate/20180529152628_schedule_to_archive_legacy_traces.rb
index 965cd3a8714..6246f6afab0 100644
--- a/db/post_migrate/20180529152628_schedule_to_archive_legacy_traces.rb
+++ b/db/post_migrate/20180529152628_schedule_to_archive_legacy_traces.rb
@@ -1,4 +1,4 @@
-class ScheduleToArchiveLegacyTraces < ActiveRecord::Migration
+class ScheduleToArchiveLegacyTraces < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180603190921_migrate_object_storage_upload_sidekiq_queue.rb b/db/post_migrate/20180603190921_migrate_object_storage_upload_sidekiq_queue.rb
index 57bee6269b9..bc7c3eb5385 100644
--- a/db/post_migrate/20180603190921_migrate_object_storage_upload_sidekiq_queue.rb
+++ b/db/post_migrate/20180603190921_migrate_object_storage_upload_sidekiq_queue.rb
@@ -1,4 +1,4 @@
-class MigrateObjectStorageUploadSidekiqQueue < ActiveRecord::Migration
+class MigrateObjectStorageUploadSidekiqQueue < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180604123514_cleanup_stages_position_migration.rb b/db/post_migrate/20180604123514_cleanup_stages_position_migration.rb
index 5418f442e79..326cdfa27c3 100644
--- a/db/post_migrate/20180604123514_cleanup_stages_position_migration.rb
+++ b/db/post_migrate/20180604123514_cleanup_stages_position_migration.rb
@@ -1,4 +1,4 @@
-class CleanupStagesPositionMigration < ActiveRecord::Migration
+class CleanupStagesPositionMigration < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180608201435_cleanup_merge_requests_allow_collaboration_rename.rb b/db/post_migrate/20180608201435_cleanup_merge_requests_allow_collaboration_rename.rb
index 3f3edb8ea3d..5e892f8bace 100644
--- a/db/post_migrate/20180608201435_cleanup_merge_requests_allow_collaboration_rename.rb
+++ b/db/post_migrate/20180608201435_cleanup_merge_requests_allow_collaboration_rename.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class CleanupMergeRequestsAllowCollaborationRename < ActiveRecord::Migration
+class CleanupMergeRequestsAllowCollaborationRename < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180619121030_enqueue_delete_diff_files_workers.rb b/db/post_migrate/20180619121030_enqueue_delete_diff_files_workers.rb
index c4d2f5f61a0..73f6a3a2a43 100644
--- a/db/post_migrate/20180619121030_enqueue_delete_diff_files_workers.rb
+++ b/db/post_migrate/20180619121030_enqueue_delete_diff_files_workers.rb
@@ -1,4 +1,4 @@
-class EnqueueDeleteDiffFilesWorkers < ActiveRecord::Migration
+class EnqueueDeleteDiffFilesWorkers < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180629191052_add_partial_index_to_projects_for_last_repository_check_at.rb b/db/post_migrate/20180629191052_add_partial_index_to_projects_for_last_repository_check_at.rb
index a701d3678db..15c02cd77b8 100644
--- a/db/post_migrate/20180629191052_add_partial_index_to_projects_for_last_repository_check_at.rb
+++ b/db/post_migrate/20180629191052_add_partial_index_to_projects_for_last_repository_check_at.rb
@@ -1,4 +1,4 @@
-class AddPartialIndexToProjectsForLastRepositoryCheckAt < ActiveRecord::Migration
+class AddPartialIndexToProjectsForLastRepositoryCheckAt < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/db/post_migrate/20180702120647_enqueue_fix_cross_project_label_links.rb b/db/post_migrate/20180702120647_enqueue_fix_cross_project_label_links.rb
index 59aa41adede..3d3d49e7564 100644
--- a/db/post_migrate/20180702120647_enqueue_fix_cross_project_label_links.rb
+++ b/db/post_migrate/20180702120647_enqueue_fix_cross_project_label_links.rb
@@ -1,4 +1,4 @@
-class EnqueueFixCrossProjectLabelLinks < ActiveRecord::Migration
+class EnqueueFixCrossProjectLabelLinks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180704145007_update_project_indexes.rb b/db/post_migrate/20180704145007_update_project_indexes.rb
index 0e2601ad4fa..0a82f4535a0 100644
--- a/db/post_migrate/20180704145007_update_project_indexes.rb
+++ b/db/post_migrate/20180704145007_update_project_indexes.rb
@@ -1,7 +1,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class UpdateProjectIndexes < ActiveRecord::Migration
+class UpdateProjectIndexes < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180706223200_populate_site_statistics.rb b/db/post_migrate/20180706223200_populate_site_statistics.rb
index e78e9eb900a..896965b708f 100644
--- a/db/post_migrate/20180706223200_populate_site_statistics.rb
+++ b/db/post_migrate/20180706223200_populate_site_statistics.rb
@@ -1,4 +1,4 @@
-class PopulateSiteStatistics < ActiveRecord::Migration
+class PopulateSiteStatistics < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180723130817_delete_inconsistent_internal_id_records.rb b/db/post_migrate/20180723130817_delete_inconsistent_internal_id_records.rb
index 3b9b95ec9ca..440868005bb 100644
--- a/db/post_migrate/20180723130817_delete_inconsistent_internal_id_records.rb
+++ b/db/post_migrate/20180723130817_delete_inconsistent_internal_id_records.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-class DeleteInconsistentInternalIdRecords < ActiveRecord::Migration
+class DeleteInconsistentInternalIdRecords < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180809195358_migrate_null_wiki_access_levels.rb b/db/post_migrate/20180809195358_migrate_null_wiki_access_levels.rb
index 0a0a33299e4..363219da539 100644
--- a/db/post_migrate/20180809195358_migrate_null_wiki_access_levels.rb
+++ b/db/post_migrate/20180809195358_migrate_null_wiki_access_levels.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class MigrateNullWikiAccessLevels < ActiveRecord::Migration
+class MigrateNullWikiAccessLevels < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180816161409_migrate_legacy_artifacts_to_job_artifacts.rb b/db/post_migrate/20180816161409_migrate_legacy_artifacts_to_job_artifacts.rb
index 2dd711e9c10..6b0d1ef0d0c 100644
--- a/db/post_migrate/20180816161409_migrate_legacy_artifacts_to_job_artifacts.rb
+++ b/db/post_migrate/20180816161409_migrate_legacy_artifacts_to_job_artifacts.rb
@@ -1,4 +1,4 @@
-class MigrateLegacyArtifactsToJobArtifacts < ActiveRecord::Migration
+class MigrateLegacyArtifactsToJobArtifacts < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180816193530_rename_login_root_namespaces.rb b/db/post_migrate/20180816193530_rename_login_root_namespaces.rb
index b0c1fb98fa8..70db8f46d05 100644
--- a/db/post_migrate/20180816193530_rename_login_root_namespaces.rb
+++ b/db/post_migrate/20180816193530_rename_login_root_namespaces.rb
@@ -1,10 +1,12 @@
# frozen_string_literal: true
-class RenameLoginRootNamespaces < ActiveRecord::Migration
+class RenameLoginRootNamespaces < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
include Gitlab::Database::RenameReservedPathsMigration::V1
DOWNTIME = false
+ disable_ddl_transaction!
+
# We're taking over the /login namespace as part of a fix for the Jira integration
def up
disable_statement_timeout do
diff --git a/db/post_migrate/20180826111825_recalculate_site_statistics.rb b/db/post_migrate/20180826111825_recalculate_site_statistics.rb
index 741035a444f..6d27eca38e3 100644
--- a/db/post_migrate/20180826111825_recalculate_site_statistics.rb
+++ b/db/post_migrate/20180826111825_recalculate_site_statistics.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class RecalculateSiteStatistics < ActiveRecord::Migration
+class RecalculateSiteStatistics < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180906051323_remove_orphaned_label_links.rb b/db/post_migrate/20180906051323_remove_orphaned_label_links.rb
index b56b74f483e..a474aaf534c 100644
--- a/db/post_migrate/20180906051323_remove_orphaned_label_links.rb
+++ b/db/post_migrate/20180906051323_remove_orphaned_label_links.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class RemoveOrphanedLabelLinks < ActiveRecord::Migration
+class RemoveOrphanedLabelLinks < ActiveRecord::Migration[4.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/db/post_migrate/20180913051323_consume_remaining_diff_files_deletion_jobs.rb b/db/post_migrate/20180913051323_consume_remaining_diff_files_deletion_jobs.rb
new file mode 100644
index 00000000000..2c266a4695b
--- /dev/null
+++ b/db/post_migrate/20180913051323_consume_remaining_diff_files_deletion_jobs.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class ConsumeRemainingDiffFilesDeletionJobs < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ MIGRATION = 'ScheduleDiffFilesDeletion'.freeze
+ TMP_INDEX = 'tmp_partial_diff_id_with_files_index'.freeze
+
+ def up
+ # Perform any ongoing background migration that might still be scheduled.
+ Gitlab::BackgroundMigration.steal(MIGRATION)
+
+ remove_concurrent_index_by_name(:merge_request_diffs, TMP_INDEX)
+ end
+
+ def down
+ add_concurrent_index(:merge_request_diffs, :id, where: "(state NOT IN ('without_files', 'empty'))", name: TMP_INDEX)
+ end
+end
diff --git a/db/post_migrate/20180913142237_schedule_digest_personal_access_tokens.rb b/db/post_migrate/20180913142237_schedule_digest_personal_access_tokens.rb
new file mode 100644
index 00000000000..951cb3b088c
--- /dev/null
+++ b/db/post_migrate/20180913142237_schedule_digest_personal_access_tokens.rb
@@ -0,0 +1,28 @@
+class ScheduleDigestPersonalAccessTokens < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ BATCH_SIZE = 10_000
+ MIGRATION = 'DigestColumn'
+ DELAY_INTERVAL = 5.minutes.to_i
+
+ disable_ddl_transaction!
+
+ class PersonalAccessToken < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'personal_access_tokens'
+ end
+
+ def up
+ PersonalAccessToken.where('token is NOT NULL').each_batch(of: BATCH_SIZE) do |batch, index|
+ range = batch.pluck('MIN(id)', 'MAX(id)').first
+ BackgroundMigrationWorker.perform_in(index * DELAY_INTERVAL, MIGRATION, ['PersonalAccessToken', :token, :token_digest, *range])
+ end
+ end
+
+ def down
+ # raise ActiveRecord::IrreversibleMigration
+ end
+end
diff --git a/db/post_migrate/20180914162043_encrypt_web_hooks_columns.rb b/db/post_migrate/20180914162043_encrypt_web_hooks_columns.rb
new file mode 100644
index 00000000000..ef864f490bb
--- /dev/null
+++ b/db/post_migrate/20180914162043_encrypt_web_hooks_columns.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+class EncryptWebHooksColumns < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ BATCH_SIZE = 10000
+ RANGE_SIZE = 100
+ MIGRATION = 'EncryptColumns'
+ COLUMNS = [:token, :url]
+
+ WebHook = ::Gitlab::BackgroundMigration::Models::EncryptColumns::WebHook
+
+ disable_ddl_transaction!
+
+ def up
+ WebHook.each_batch(of: BATCH_SIZE) do |relation, index|
+ delay = index * 2.minutes
+
+ relation.each_batch(of: RANGE_SIZE) do |relation|
+ range = relation.pluck('MIN(id)', 'MAX(id)').first
+ args = [WebHook, COLUMNS, *range]
+
+ BackgroundMigrationWorker.perform_in(delay, MIGRATION, args)
+ end
+ end
+ end
+
+ def down
+ # noop
+ end
+end
diff --git a/db/post_migrate/20180914201132_remove_sidekiq_throttling_from_application_settings.rb b/db/post_migrate/20180914201132_remove_sidekiq_throttling_from_application_settings.rb
new file mode 100644
index 00000000000..2c007ec395d
--- /dev/null
+++ b/db/post_migrate/20180914201132_remove_sidekiq_throttling_from_application_settings.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class RemoveSidekiqThrottlingFromApplicationSettings < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ remove_column :application_settings, :sidekiq_throttling_enabled, :boolean, default: false
+ remove_column :application_settings, :sidekiq_throttling_queues, :string
+ remove_column :application_settings, :sidekiq_throttling_factor, :decimal
+
+ Rails.cache.delete("ApplicationSetting:#{Gitlab::VERSION}:#{Rails.version}")
+ end
+end
diff --git a/db/post_migrate/20180916014356_populate_external_pipeline_source.rb b/db/post_migrate/20180916014356_populate_external_pipeline_source.rb
new file mode 100644
index 00000000000..a3d2df1f2bd
--- /dev/null
+++ b/db/post_migrate/20180916014356_populate_external_pipeline_source.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class PopulateExternalPipelineSource < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+ MIGRATION = 'PopulateExternalPipelineSource'.freeze
+ BATCH_SIZE = 500
+
+ disable_ddl_transaction!
+
+ class Pipeline < ActiveRecord::Base
+ include EachBatch
+ self.table_name = 'ci_pipelines'
+ end
+
+ def up
+ Pipeline.where(source: nil).tap do |relation|
+ queue_background_migration_jobs_by_range_at_intervals(relation,
+ MIGRATION,
+ 5.minutes,
+ batch_size: BATCH_SIZE)
+ end
+ end
+
+ def down
+ # noop
+ end
+end
diff --git a/db/post_migrate/20180917172041_remove_wikis_count_from_site_statistics.rb b/db/post_migrate/20180917172041_remove_wikis_count_from_site_statistics.rb
new file mode 100644
index 00000000000..3b8300dabeb
--- /dev/null
+++ b/db/post_migrate/20180917172041_remove_wikis_count_from_site_statistics.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+class RemoveWikisCountFromSiteStatistics < ActiveRecord::Migration[4.2]
+ def change
+ remove_column :site_statistics, :wikis_count, :integer
+ end
+end
diff --git a/db/post_migrate/20181008145341_steal_encrypt_columns.rb b/db/post_migrate/20181008145341_steal_encrypt_columns.rb
new file mode 100644
index 00000000000..4102643ba13
--- /dev/null
+++ b/db/post_migrate/20181008145341_steal_encrypt_columns.rb
@@ -0,0 +1,15 @@
+class StealEncryptColumns < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ Gitlab::BackgroundMigration.steal('EncryptColumns')
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20181008145359_remove_web_hooks_token_and_url.rb b/db/post_migrate/20181008145359_remove_web_hooks_token_and_url.rb
new file mode 100644
index 00000000000..93e4458b795
--- /dev/null
+++ b/db/post_migrate/20181008145359_remove_web_hooks_token_and_url.rb
@@ -0,0 +1,10 @@
+class RemoveWebHooksTokenAndUrl < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ remove_column :web_hooks, :token, :string
+ remove_column :web_hooks, :url, :string, limit: 2000
+ end
+end
diff --git a/db/post_migrate/20181008200441_remove_circuit_breaker.rb b/db/post_migrate/20181008200441_remove_circuit_breaker.rb
new file mode 100644
index 00000000000..378692e8886
--- /dev/null
+++ b/db/post_migrate/20181008200441_remove_circuit_breaker.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class RemoveCircuitBreaker < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ CIRCUIT_BREAKER_COLUMS_WITH_DEFAULT = {
+ circuitbreaker_failure_count_threshold: 3,
+ circuitbreaker_failure_reset_time: 1800,
+ circuitbreaker_storage_timeout: 15,
+ circuitbreaker_access_retries: 3,
+ circuitbreaker_check_interval: 1
+ }.freeze
+
+ def up
+ CIRCUIT_BREAKER_COLUMS_WITH_DEFAULT.keys.each do |column|
+ remove_column(:application_settings, column) if column_exists?(:application_settings, column)
+ end
+ end
+
+ def down
+ CIRCUIT_BREAKER_COLUMS_WITH_DEFAULT.each do |column, default|
+ add_column_with_default(:application_settings, column, :integer, default: default) unless column_exists?(:application_settings, column)
+ end
+ end
+end
diff --git a/db/post_migrate/20181010133639_backfill_store_project_full_path_in_repo.rb b/db/post_migrate/20181010133639_backfill_store_project_full_path_in_repo.rb
new file mode 100644
index 00000000000..e9ab45ae9a1
--- /dev/null
+++ b/db/post_migrate/20181010133639_backfill_store_project_full_path_in_repo.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class BackfillStoreProjectFullPathInRepo < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ BATCH_SIZE = 1_000
+ DELAY_INTERVAL = 5.minutes
+ UP_MIGRATION = 'BackfillProjectFullpathInRepoConfig::Up'
+ DOWN_MIGRATION = 'BackfillProjectFullpathInRepoConfig::Down'
+
+ disable_ddl_transaction!
+
+ class Project < ActiveRecord::Base
+ self.table_name = 'projects'
+
+ include EachBatch
+ end
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(Project, UP_MIGRATION, DELAY_INTERVAL)
+ end
+
+ def down
+ queue_background_migration_jobs_by_range_at_intervals(Project, DOWN_MIGRATION, DELAY_INTERVAL)
+ end
+end
diff --git a/db/post_migrate/20181013005024_remove_koding_from_application_settings.rb b/db/post_migrate/20181013005024_remove_koding_from_application_settings.rb
new file mode 100644
index 00000000000..550ad94f4ab
--- /dev/null
+++ b/db/post_migrate/20181013005024_remove_koding_from_application_settings.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class RemoveKodingFromApplicationSettings < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ remove_column :application_settings, :koding_enabled
+ remove_column :application_settings, :koding_url
+ end
+
+ def down
+ add_column :application_settings, :koding_enabled, :boolean # rubocop:disable Migration/SaferBooleanColumn
+ add_column :application_settings, :koding_url, :string
+ end
+end
diff --git a/db/post_migrate/20181014121030_enqueue_redact_links.rb b/db/post_migrate/20181014121030_enqueue_redact_links.rb
new file mode 100644
index 00000000000..8d1a840d594
--- /dev/null
+++ b/db/post_migrate/20181014121030_enqueue_redact_links.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+class EnqueueRedactLinks < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ BATCH_SIZE = 1000
+ DELAY_INTERVAL = 5.minutes.to_i
+ MIGRATION = 'RedactLinks'
+
+ disable_ddl_transaction!
+
+ class Note < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'notes'
+ self.inheritance_column = :_type_disabled
+ end
+
+ class Issue < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'issues'
+ self.inheritance_column = :_type_disabled
+ end
+
+ class MergeRequest < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'merge_requests'
+ self.inheritance_column = :_type_disabled
+ end
+
+ class Snippet < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'snippets'
+ self.inheritance_column = :_type_disabled
+ end
+
+ def up
+ disable_statement_timeout do
+ schedule_migration(Note, 'note')
+ schedule_migration(Issue, 'description')
+ schedule_migration(MergeRequest, 'description')
+ schedule_migration(Snippet, 'description')
+ end
+ end
+
+ def down
+ # nothing to do
+ end
+
+ private
+
+ def schedule_migration(model, field)
+ link_pattern = "%/sent_notifications/" + ("_" * 32) + "/unsubscribe%"
+
+ model.where("#{field} like ?", link_pattern).each_batch(of: BATCH_SIZE) do |batch, index|
+ start_id, stop_id = batch.pluck('MIN(id)', 'MAX(id)').first
+
+ BackgroundMigrationWorker.perform_in(index * DELAY_INTERVAL, MIGRATION, [model.name.demodulize, field, start_id, stop_id])
+ end
+ end
+end
diff --git a/db/post_migrate/20181022173835_enqueue_populate_cluster_kubernetes_namespace.rb b/db/post_migrate/20181022173835_enqueue_populate_cluster_kubernetes_namespace.rb
new file mode 100644
index 00000000000..94a4574abff
--- /dev/null
+++ b/db/post_migrate/20181022173835_enqueue_populate_cluster_kubernetes_namespace.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class EnqueuePopulateClusterKubernetesNamespace < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ MIGRATION = 'PopulateClusterKubernetesNamespaceTable'.freeze
+
+ disable_ddl_transaction!
+
+ def up
+ BackgroundMigrationWorker.perform_async(MIGRATION)
+ end
+
+ def down
+ Clusters::KubernetesNamespace.delete_all
+ end
+end
diff --git a/db/post_migrate/20181026091631_migrate_forbidden_redirect_uris.rb b/db/post_migrate/20181026091631_migrate_forbidden_redirect_uris.rb
new file mode 100644
index 00000000000..ff5510e8eb7
--- /dev/null
+++ b/db/post_migrate/20181026091631_migrate_forbidden_redirect_uris.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+class MigrateForbiddenRedirectUris < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ FORBIDDEN_SCHEMES = %w[data:// vbscript:// javascript://]
+ NEW_URI = 'http://forbidden-scheme-has-been-overwritten'
+
+ disable_ddl_transaction!
+
+ def up
+ update_forbidden_uris(:oauth_applications)
+ update_forbidden_uris(:oauth_access_grants)
+ end
+
+ def down
+ # noop
+ end
+
+ private
+
+ def update_forbidden_uris(table_name)
+ update_column_in_batches(table_name, :redirect_uri, NEW_URI) do |table, query|
+ where_clause = FORBIDDEN_SCHEMES.map do |scheme|
+ table[:redirect_uri].matches("#{scheme}%")
+ end.inject(&:or)
+
+ query.where(where_clause)
+ end
+ end
+end
diff --git a/db/post_migrate/20181030135124_fill_empty_finished_at_in_deployments.rb b/db/post_migrate/20181030135124_fill_empty_finished_at_in_deployments.rb
new file mode 100644
index 00000000000..228841a14a0
--- /dev/null
+++ b/db/post_migrate/20181030135124_fill_empty_finished_at_in_deployments.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class FillEmptyFinishedAtInDeployments < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ DEPLOYMENT_STATUS_SUCCESS = 2 # Equivalent to Deployment.statuses[:success]
+
+ class Deployments < ActiveRecord::Base
+ self.table_name = 'deployments'
+
+ include EachBatch
+ end
+
+ def up
+ FillEmptyFinishedAtInDeployments::Deployments
+ .where('finished_at IS NULL')
+ .where('status = ?', DEPLOYMENT_STATUS_SUCCESS)
+ .each_batch(of: 10_000) do |relation|
+ relation.update_all('finished_at=created_at')
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20181105201455_steal_fill_store_upload.rb b/db/post_migrate/20181105201455_steal_fill_store_upload.rb
new file mode 100644
index 00000000000..a31a4eab472
--- /dev/null
+++ b/db/post_migrate/20181105201455_steal_fill_store_upload.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class StealFillStoreUpload < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ BATCH_SIZE = 10_000
+
+ disable_ddl_transaction!
+
+ class Upload < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'uploads'
+ self.inheritance_column = :_type_disabled # Disable STI
+ end
+
+ def up
+ Gitlab::BackgroundMigration.steal('FillStoreUpload')
+
+ Upload.where(store: nil).each_batch(of: BATCH_SIZE) do |batch|
+ range = batch.pluck('MIN(id)', 'MAX(id)').first
+
+ Gitlab::BackgroundMigration::FillStoreUpload.new.perform(*range)
+ end
+ end
+
+ def down
+ # noop
+ end
+end
diff --git a/db/post_migrate/20181107054254_remove_restricted_todos_again.rb b/db/post_migrate/20181107054254_remove_restricted_todos_again.rb
new file mode 100644
index 00000000000..bbeb4e8a1de
--- /dev/null
+++ b/db/post_migrate/20181107054254_remove_restricted_todos_again.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+# rescheduling of the revised RemoveRestrictedTodosWithCte background migration
+class RemoveRestrictedTodosAgain < ActiveRecord::Migration[4.2]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+ disable_ddl_transaction!
+
+ MIGRATION = 'RemoveRestrictedTodos'.freeze
+ BATCH_SIZE = 1000
+ DELAY_INTERVAL = 5.minutes.to_i
+
+ class Project < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'projects'
+ end
+
+ def up
+ Project.where('EXISTS (SELECT 1 FROM todos WHERE todos.project_id = projects.id)')
+ .each_batch(of: BATCH_SIZE) do |batch, index|
+ range = batch.pluck('MIN(id)', 'MAX(id)').first
+
+ BackgroundMigrationWorker.perform_in(index * DELAY_INTERVAL, MIGRATION, range)
+ end
+ end
+
+ def down
+ # nothing to do
+ end
+end
diff --git a/db/post_migrate/20181123042307_drop_site_statistics.rb b/db/post_migrate/20181123042307_drop_site_statistics.rb
new file mode 100644
index 00000000000..8986374ef65
--- /dev/null
+++ b/db/post_migrate/20181123042307_drop_site_statistics.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class DropSiteStatistics < ActiveRecord::Migration[5.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ drop_table :site_statistics
+ end
+
+ def down
+ create_table :site_statistics do |t|
+ t.integer :repositories_count, default: 0, null: false
+ end
+
+ execute('INSERT INTO site_statistics (id) VALUES(1)')
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index b299cde4898..995619bdc69 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -1,4 +1,3 @@
-# encoding: UTF-8
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
@@ -11,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20180907015926) do
+ActiveRecord::Schema.define(version: 20181126153547) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -104,8 +103,6 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.boolean "domain_blacklist_enabled", default: false
t.text "domain_blacklist"
t.boolean "usage_ping_enabled", default: true, null: false
- t.boolean "koding_enabled"
- t.string "koding_url"
t.text "sign_in_text_html"
t.text "help_page_text_html"
t.text "shared_runners_text_html"
@@ -119,9 +116,6 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.integer "housekeeping_incremental_repack_period", default: 10, null: false
t.integer "housekeeping_full_repack_period", default: 50, null: false
t.integer "housekeeping_gc_period", default: 200, null: false
- t.boolean "sidekiq_throttling_enabled", default: false
- t.string "sidekiq_throttling_queues"
- t.decimal "sidekiq_throttling_factor"
t.boolean "html_emails_enabled", default: true
t.string "plantuml_url"
t.boolean "plantuml_enabled"
@@ -131,7 +125,7 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.boolean "unique_ips_limit_enabled", default: false, null: false
t.string "default_artifacts_expire_in", default: "0", null: false
t.string "uuid"
- t.decimal "polling_interval_multiplier", default: 1.0, null: false
+ t.decimal "polling_interval_multiplier", default: "1.0", null: false
t.integer "cached_markdown_version"
t.boolean "clientside_sentry_enabled", default: false, null: false
t.string "clientside_sentry_dsn"
@@ -142,10 +136,6 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.boolean "hashed_storage_enabled", default: false, null: false
t.boolean "project_export_enabled", default: true, null: false
t.boolean "auto_devops_enabled", default: true, null: false
- t.integer "circuitbreaker_failure_count_threshold", default: 3
- t.integer "circuitbreaker_failure_reset_time", default: 1800
- t.integer "circuitbreaker_storage_timeout", default: 15
- t.integer "circuitbreaker_access_retries", default: 3
t.boolean "throttle_unauthenticated_enabled", default: false, null: false
t.integer "throttle_unauthenticated_requests_per_period", default: 3600, null: false
t.integer "throttle_unauthenticated_period_in_seconds", default: 3600, null: false
@@ -155,7 +145,6 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.boolean "throttle_authenticated_web_enabled", default: false, null: false
t.integer "throttle_authenticated_web_requests_per_period", default: 7200, null: false
t.integer "throttle_authenticated_web_period_in_seconds", default: 3600, null: false
- t.integer "circuitbreaker_check_interval", default: 1, null: false
t.boolean "password_authentication_enabled_for_web"
t.boolean "password_authentication_enabled_for_git", default: true
t.integer "gitaly_timeout_default", default: 55, null: false
@@ -174,6 +163,10 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.boolean "user_show_add_ssh_key_message", default: true, null: false
t.integer "usage_stats_set_by_user_id"
t.integer "receive_max_input_size"
+ t.integer "diff_max_patch_bytes", default: 102400, null: false
+ t.integer "archive_builds_in_seconds"
+ t.string "commit_email_hostname"
+ t.index ["usage_stats_set_by_user_id"], name: "index_application_settings_on_usage_stats_set_by_user_id", using: :btree
end
create_table "audit_events", force: :cascade do |t|
@@ -184,10 +177,9 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.text "details"
t.datetime "created_at"
t.datetime "updated_at"
+ t.index ["entity_id", "entity_type"], name: "index_audit_events_on_entity_id_and_entity_type", using: :btree
end
- add_index "audit_events", ["entity_id", "entity_type"], name: "index_audit_events_on_entity_id_and_entity_type", using: :btree
-
create_table "award_emoji", force: :cascade do |t|
t.string "name"
t.integer "user_id"
@@ -195,11 +187,10 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "awardable_type"
t.datetime "created_at"
t.datetime "updated_at"
+ t.index ["awardable_type", "awardable_id"], name: "index_award_emoji_on_awardable_type_and_awardable_id", using: :btree
+ t.index ["user_id", "name"], name: "index_award_emoji_on_user_id_and_name", using: :btree
end
- add_index "award_emoji", ["awardable_type", "awardable_id"], name: "index_award_emoji_on_awardable_type_and_awardable_id", using: :btree
- add_index "award_emoji", ["user_id", "name"], name: "index_award_emoji_on_user_id_and_name", using: :btree
-
create_table "badges", force: :cascade do |t|
t.string "link_url", null: false
t.string "image_url", null: false
@@ -208,21 +199,43 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "type", null: false
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
+ t.index ["group_id"], name: "index_badges_on_group_id", using: :btree
+ t.index ["project_id"], name: "index_badges_on_project_id", using: :btree
end
- add_index "badges", ["group_id"], name: "index_badges_on_group_id", using: :btree
- add_index "badges", ["project_id"], name: "index_badges_on_project_id", using: :btree
+ create_table "board_group_recent_visits", id: :bigserial, force: :cascade do |t|
+ t.datetime_with_timezone "created_at", null: false
+ t.datetime_with_timezone "updated_at", null: false
+ t.integer "user_id"
+ t.integer "board_id"
+ t.integer "group_id"
+ t.index ["board_id"], name: "index_board_group_recent_visits_on_board_id", using: :btree
+ t.index ["group_id"], name: "index_board_group_recent_visits_on_group_id", using: :btree
+ t.index ["user_id", "group_id", "board_id"], name: "index_board_group_recent_visits_on_user_group_and_board", unique: true, using: :btree
+ t.index ["user_id"], name: "index_board_group_recent_visits_on_user_id", using: :btree
+ end
+
+ create_table "board_project_recent_visits", id: :bigserial, force: :cascade do |t|
+ t.datetime_with_timezone "created_at", null: false
+ t.datetime_with_timezone "updated_at", null: false
+ t.integer "user_id"
+ t.integer "project_id"
+ t.integer "board_id"
+ t.index ["board_id"], name: "index_board_project_recent_visits_on_board_id", using: :btree
+ t.index ["project_id"], name: "index_board_project_recent_visits_on_project_id", using: :btree
+ t.index ["user_id", "project_id", "board_id"], name: "index_board_project_recent_visits_on_user_project_and_board", unique: true, using: :btree
+ t.index ["user_id"], name: "index_board_project_recent_visits_on_user_id", using: :btree
+ end
create_table "boards", force: :cascade do |t|
t.integer "project_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "group_id"
+ t.index ["group_id"], name: "index_boards_on_group_id", using: :btree
+ t.index ["project_id"], name: "index_boards_on_project_id", using: :btree
end
- add_index "boards", ["group_id"], name: "index_boards_on_group_id", using: :btree
- add_index "boards", ["project_id"], name: "index_boards_on_project_id", using: :btree
-
create_table "broadcast_messages", force: :cascade do |t|
t.text "message", null: false
t.datetime "starts_at", null: false
@@ -233,10 +246,9 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "font"
t.text "message_html", null: false
t.integer "cached_markdown_version"
+ t.index ["starts_at", "ends_at", "id"], name: "index_broadcast_messages_on_starts_at_and_ends_at_and_id", using: :btree
end
- add_index "broadcast_messages", ["starts_at", "ends_at", "id"], name: "index_broadcast_messages_on_starts_at_and_ends_at_and_id", using: :btree
-
create_table "chat_names", force: :cascade do |t|
t.integer "user_id", null: false
t.integer "service_id", null: false
@@ -247,51 +259,46 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime "last_used_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["service_id", "team_id", "chat_id"], name: "index_chat_names_on_service_id_and_team_id_and_chat_id", unique: true, using: :btree
+ t.index ["user_id", "service_id"], name: "index_chat_names_on_user_id_and_service_id", unique: true, using: :btree
end
- add_index "chat_names", ["service_id", "team_id", "chat_id"], name: "index_chat_names_on_service_id_and_team_id_and_chat_id", unique: true, using: :btree
- add_index "chat_names", ["user_id", "service_id"], name: "index_chat_names_on_user_id_and_service_id", unique: true, using: :btree
-
create_table "chat_teams", force: :cascade do |t|
t.integer "namespace_id", null: false
t.string "team_id"
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["namespace_id"], name: "index_chat_teams_on_namespace_id", unique: true, using: :btree
end
- add_index "chat_teams", ["namespace_id"], name: "index_chat_teams_on_namespace_id", unique: true, using: :btree
-
create_table "ci_build_trace_chunks", id: :bigserial, force: :cascade do |t|
t.integer "build_id", null: false
t.integer "chunk_index", null: false
t.integer "data_store", null: false
t.binary "raw_data"
+ t.index ["build_id", "chunk_index"], name: "index_ci_build_trace_chunks_on_build_id_and_chunk_index", unique: true, using: :btree
end
- add_index "ci_build_trace_chunks", ["build_id", "chunk_index"], name: "index_ci_build_trace_chunks_on_build_id_and_chunk_index", unique: true, using: :btree
-
create_table "ci_build_trace_section_names", force: :cascade do |t|
t.integer "project_id", null: false
t.string "name", null: false
+ t.index ["project_id", "name"], name: "index_ci_build_trace_section_names_on_project_id_and_name", unique: true, using: :btree
end
- add_index "ci_build_trace_section_names", ["project_id", "name"], name: "index_ci_build_trace_section_names_on_project_id_and_name", unique: true, using: :btree
-
create_table "ci_build_trace_sections", force: :cascade do |t|
t.integer "project_id", null: false
t.datetime_with_timezone "date_start", null: false
t.datetime_with_timezone "date_end", null: false
- t.integer "byte_start", limit: 8, null: false
- t.integer "byte_end", limit: 8, null: false
+ t.bigint "byte_start", null: false
+ t.bigint "byte_end", null: false
t.integer "build_id", null: false
t.integer "section_name_id", null: false
+ t.index ["build_id", "section_name_id"], name: "index_ci_build_trace_sections_on_build_id_and_section_name_id", unique: true, using: :btree
+ t.index ["project_id"], name: "index_ci_build_trace_sections_on_project_id", using: :btree
+ t.index ["section_name_id"], name: "index_ci_build_trace_sections_on_section_name_id", using: :btree
end
- add_index "ci_build_trace_sections", ["build_id", "section_name_id"], name: "index_ci_build_trace_sections_on_build_id_and_section_name_id", unique: true, using: :btree
- add_index "ci_build_trace_sections", ["project_id"], name: "index_ci_build_trace_sections_on_project_id", using: :btree
- add_index "ci_build_trace_sections", ["section_name_id"], name: "index_ci_build_trace_sections_on_section_name_id", using: :btree
-
create_table "ci_builds", force: :cascade do |t|
t.string "status"
t.datetime "finished_at"
@@ -322,7 +329,7 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime "erased_at"
t.datetime "artifacts_expire_at"
t.string "environment"
- t.integer "artifacts_size", limit: 8
+ t.bigint "artifacts_size"
t.string "when"
t.text "yaml_variables"
t.datetime "queued_at"
@@ -336,44 +343,43 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.integer "artifacts_metadata_store"
t.boolean "protected"
t.integer "failure_reason"
+ t.datetime_with_timezone "scheduled_at"
+ t.index ["artifacts_expire_at"], name: "index_ci_builds_on_artifacts_expire_at", where: "(artifacts_file <> ''::text)", using: :btree
+ t.index ["auto_canceled_by_id"], name: "index_ci_builds_on_auto_canceled_by_id", using: :btree
+ t.index ["commit_id", "stage_idx", "created_at"], name: "index_ci_builds_on_commit_id_and_stage_idx_and_created_at", using: :btree
+ t.index ["commit_id", "status", "type"], name: "index_ci_builds_on_commit_id_and_status_and_type", using: :btree
+ t.index ["commit_id", "type", "name", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_name_and_ref", using: :btree
+ t.index ["commit_id", "type", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_ref", using: :btree
+ t.index ["id"], name: "partial_index_ci_builds_on_id_with_legacy_artifacts", where: "(artifacts_file <> ''::text)", using: :btree
+ t.index ["project_id", "id"], name: "index_ci_builds_on_project_id_and_id", using: :btree
+ t.index ["protected"], name: "index_ci_builds_on_protected", using: :btree
+ t.index ["runner_id"], name: "index_ci_builds_on_runner_id", using: :btree
+ t.index ["scheduled_at"], name: "partial_index_ci_builds_on_scheduled_at_with_scheduled_jobs", where: "((scheduled_at IS NOT NULL) AND ((type)::text = 'Ci::Build'::text) AND ((status)::text = 'scheduled'::text))", using: :btree
+ t.index ["stage_id", "stage_idx"], name: "tmp_build_stage_position_index", where: "(stage_idx IS NOT NULL)", using: :btree
+ t.index ["stage_id"], name: "index_ci_builds_on_stage_id", using: :btree
+ t.index ["status", "type", "runner_id"], name: "index_ci_builds_on_status_and_type_and_runner_id", using: :btree
+ t.index ["token"], name: "index_ci_builds_on_token", unique: true, using: :btree
+ t.index ["updated_at"], name: "index_ci_builds_on_updated_at", using: :btree
+ t.index ["user_id"], name: "index_ci_builds_on_user_id", using: :btree
end
- add_index "ci_builds", ["artifacts_expire_at"], name: "index_ci_builds_on_artifacts_expire_at", where: "(artifacts_file <> ''::text)", using: :btree
- add_index "ci_builds", ["auto_canceled_by_id"], name: "index_ci_builds_on_auto_canceled_by_id", using: :btree
- add_index "ci_builds", ["commit_id", "stage_idx", "created_at"], name: "index_ci_builds_on_commit_id_and_stage_idx_and_created_at", using: :btree
- add_index "ci_builds", ["commit_id", "status", "type"], name: "index_ci_builds_on_commit_id_and_status_and_type", using: :btree
- add_index "ci_builds", ["commit_id", "type", "name", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_name_and_ref", using: :btree
- add_index "ci_builds", ["commit_id", "type", "ref"], name: "index_ci_builds_on_commit_id_and_type_and_ref", using: :btree
- add_index "ci_builds", ["id"], name: "partial_index_ci_builds_on_id_with_legacy_artifacts", where: "(artifacts_file <> ''::text)", using: :btree
- add_index "ci_builds", ["project_id", "id"], name: "index_ci_builds_on_project_id_and_id", using: :btree
- add_index "ci_builds", ["protected"], name: "index_ci_builds_on_protected", using: :btree
- add_index "ci_builds", ["runner_id"], name: "index_ci_builds_on_runner_id", using: :btree
- add_index "ci_builds", ["stage_id", "stage_idx"], name: "tmp_build_stage_position_index", where: "(stage_idx IS NOT NULL)", using: :btree
- add_index "ci_builds", ["stage_id"], name: "index_ci_builds_on_stage_id", using: :btree
- add_index "ci_builds", ["status", "type", "runner_id"], name: "index_ci_builds_on_status_and_type_and_runner_id", using: :btree
- add_index "ci_builds", ["token"], name: "index_ci_builds_on_token", unique: true, using: :btree
- add_index "ci_builds", ["updated_at"], name: "index_ci_builds_on_updated_at", using: :btree
- add_index "ci_builds", ["user_id"], name: "index_ci_builds_on_user_id", using: :btree
-
create_table "ci_builds_metadata", force: :cascade do |t|
t.integer "build_id", null: false
t.integer "project_id", null: false
t.integer "timeout"
t.integer "timeout_source", default: 1, null: false
+ t.index ["build_id"], name: "index_ci_builds_metadata_on_build_id", unique: true, using: :btree
+ t.index ["project_id"], name: "index_ci_builds_metadata_on_project_id", using: :btree
end
- add_index "ci_builds_metadata", ["build_id"], name: "index_ci_builds_metadata_on_build_id", unique: true, using: :btree
- add_index "ci_builds_metadata", ["project_id"], name: "index_ci_builds_metadata_on_project_id", using: :btree
-
create_table "ci_builds_runner_session", id: :bigserial, force: :cascade do |t|
t.integer "build_id", null: false
t.string "url", null: false
t.string "certificate"
t.string "authorization"
+ t.index ["build_id"], name: "index_ci_builds_runner_session_on_build_id", unique: true, using: :btree
end
- add_index "ci_builds_runner_session", ["build_id"], name: "index_ci_builds_runner_session_on_build_id", unique: true, using: :btree
-
create_table "ci_group_variables", force: :cascade do |t|
t.string "key", null: false
t.text "value"
@@ -384,16 +390,15 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.boolean "protected", default: false, null: false
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
+ t.index ["group_id", "key"], name: "index_ci_group_variables_on_group_id_and_key", unique: true, using: :btree
end
- add_index "ci_group_variables", ["group_id", "key"], name: "index_ci_group_variables_on_group_id_and_key", unique: true, using: :btree
-
create_table "ci_job_artifacts", force: :cascade do |t|
t.integer "project_id", null: false
t.integer "job_id", null: false
t.integer "file_type", null: false
t.integer "file_store"
- t.integer "size", limit: 8
+ t.bigint "size"
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.datetime_with_timezone "expire_at"
@@ -401,13 +406,12 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.binary "file_sha256"
t.integer "file_format", limit: 2
t.integer "file_location", limit: 2
+ t.index ["expire_at", "job_id"], name: "index_ci_job_artifacts_on_expire_at_and_job_id", using: :btree
+ t.index ["file_store"], name: "index_ci_job_artifacts_on_file_store", using: :btree
+ t.index ["job_id", "file_type"], name: "index_ci_job_artifacts_on_job_id_and_file_type", unique: true, using: :btree
+ t.index ["project_id"], name: "index_ci_job_artifacts_on_project_id", using: :btree
end
- add_index "ci_job_artifacts", ["expire_at", "job_id"], name: "index_ci_job_artifacts_on_expire_at_and_job_id", using: :btree
- add_index "ci_job_artifacts", ["file_store"], name: "index_ci_job_artifacts_on_file_store", using: :btree
- add_index "ci_job_artifacts", ["job_id", "file_type"], name: "index_ci_job_artifacts_on_job_id_and_file_type", unique: true, using: :btree
- add_index "ci_job_artifacts", ["project_id"], name: "index_ci_job_artifacts_on_project_id", using: :btree
-
create_table "ci_pipeline_schedule_variables", force: :cascade do |t|
t.string "key", null: false
t.text "value"
@@ -417,10 +421,9 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.integer "pipeline_schedule_id", null: false
t.datetime_with_timezone "created_at"
t.datetime_with_timezone "updated_at"
+ t.index ["pipeline_schedule_id", "key"], name: "index_ci_pipeline_schedule_variables_on_schedule_id_and_key", unique: true, using: :btree
end
- add_index "ci_pipeline_schedule_variables", ["pipeline_schedule_id", "key"], name: "index_ci_pipeline_schedule_variables_on_schedule_id_and_key", unique: true, using: :btree
-
create_table "ci_pipeline_schedules", force: :cascade do |t|
t.string "description"
t.string "ref"
@@ -432,11 +435,11 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.boolean "active", default: true
t.datetime "created_at"
t.datetime "updated_at"
+ t.index ["next_run_at", "active"], name: "index_ci_pipeline_schedules_on_next_run_at_and_active", using: :btree
+ t.index ["owner_id"], name: "index_ci_pipeline_schedules_on_owner_id", using: :btree
+ t.index ["project_id"], name: "index_ci_pipeline_schedules_on_project_id", using: :btree
end
- add_index "ci_pipeline_schedules", ["next_run_at", "active"], name: "index_ci_pipeline_schedules_on_next_run_at_and_active", using: :btree
- add_index "ci_pipeline_schedules", ["project_id"], name: "index_ci_pipeline_schedules_on_project_id", using: :btree
-
create_table "ci_pipeline_variables", force: :cascade do |t|
t.string "key", null: false
t.text "value"
@@ -444,10 +447,9 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "encrypted_value_salt"
t.string "encrypted_value_iv"
t.integer "pipeline_id", null: false
+ t.index ["pipeline_id", "key"], name: "index_ci_pipeline_variables_on_pipeline_id_and_key", unique: true, using: :btree
end
- add_index "ci_pipeline_variables", ["pipeline_id", "key"], name: "index_ci_pipeline_variables_on_pipeline_id_and_key", unique: true, using: :btree
-
create_table "ci_pipelines", force: :cascade do |t|
t.string "ref"
t.string "sha"
@@ -471,36 +473,34 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.boolean "protected"
t.integer "failure_reason"
t.integer "iid"
+ t.index ["auto_canceled_by_id"], name: "index_ci_pipelines_on_auto_canceled_by_id", using: :btree
+ t.index ["pipeline_schedule_id"], name: "index_ci_pipelines_on_pipeline_schedule_id", using: :btree
+ t.index ["project_id", "iid"], name: "index_ci_pipelines_on_project_id_and_iid", unique: true, where: "(iid IS NOT NULL)", using: :btree
+ t.index ["project_id", "ref", "status", "id"], name: "index_ci_pipelines_on_project_id_and_ref_and_status_and_id", using: :btree
+ t.index ["project_id", "sha"], name: "index_ci_pipelines_on_project_id_and_sha", using: :btree
+ t.index ["project_id", "source"], name: "index_ci_pipelines_on_project_id_and_source", using: :btree
+ t.index ["project_id", "status", "config_source"], name: "index_ci_pipelines_on_project_id_and_status_and_config_source", using: :btree
+ t.index ["project_id"], name: "index_ci_pipelines_on_project_id", using: :btree
+ t.index ["status"], name: "index_ci_pipelines_on_status", using: :btree
+ t.index ["user_id"], name: "index_ci_pipelines_on_user_id", using: :btree
end
- add_index "ci_pipelines", ["auto_canceled_by_id"], name: "index_ci_pipelines_on_auto_canceled_by_id", using: :btree
- add_index "ci_pipelines", ["pipeline_schedule_id"], name: "index_ci_pipelines_on_pipeline_schedule_id", using: :btree
- add_index "ci_pipelines", ["project_id", "iid"], name: "index_ci_pipelines_on_project_id_and_iid", unique: true, where: "(iid IS NOT NULL)", using: :btree
- add_index "ci_pipelines", ["project_id", "ref", "status", "id"], name: "index_ci_pipelines_on_project_id_and_ref_and_status_and_id", using: :btree
- add_index "ci_pipelines", ["project_id", "sha"], name: "index_ci_pipelines_on_project_id_and_sha", using: :btree
- add_index "ci_pipelines", ["project_id", "status", "config_source"], name: "index_ci_pipelines_on_project_id_and_status_and_config_source", using: :btree
- add_index "ci_pipelines", ["project_id"], name: "index_ci_pipelines_on_project_id", using: :btree
- add_index "ci_pipelines", ["status"], name: "index_ci_pipelines_on_status", using: :btree
- add_index "ci_pipelines", ["user_id"], name: "index_ci_pipelines_on_user_id", using: :btree
-
create_table "ci_runner_namespaces", force: :cascade do |t|
t.integer "runner_id"
t.integer "namespace_id"
+ t.index ["namespace_id"], name: "index_ci_runner_namespaces_on_namespace_id", using: :btree
+ t.index ["runner_id", "namespace_id"], name: "index_ci_runner_namespaces_on_runner_id_and_namespace_id", unique: true, using: :btree
end
- add_index "ci_runner_namespaces", ["namespace_id"], name: "index_ci_runner_namespaces_on_namespace_id", using: :btree
- add_index "ci_runner_namespaces", ["runner_id", "namespace_id"], name: "index_ci_runner_namespaces_on_runner_id_and_namespace_id", unique: true, using: :btree
-
create_table "ci_runner_projects", force: :cascade do |t|
t.integer "runner_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
t.integer "project_id"
+ t.index ["project_id"], name: "index_ci_runner_projects_on_project_id", using: :btree
+ t.index ["runner_id"], name: "index_ci_runner_projects_on_runner_id", using: :btree
end
- add_index "ci_runner_projects", ["project_id"], name: "index_ci_runner_projects_on_project_id", using: :btree
- add_index "ci_runner_projects", ["runner_id"], name: "index_ci_runner_projects_on_runner_id", using: :btree
-
create_table "ci_runners", force: :cascade do |t|
t.string "token"
t.datetime "created_at"
@@ -520,14 +520,13 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "ip_address"
t.integer "maximum_timeout"
t.integer "runner_type", limit: 2, null: false
+ t.index ["contacted_at"], name: "index_ci_runners_on_contacted_at", using: :btree
+ t.index ["is_shared"], name: "index_ci_runners_on_is_shared", using: :btree
+ t.index ["locked"], name: "index_ci_runners_on_locked", using: :btree
+ t.index ["runner_type"], name: "index_ci_runners_on_runner_type", using: :btree
+ t.index ["token"], name: "index_ci_runners_on_token", using: :btree
end
- add_index "ci_runners", ["contacted_at"], name: "index_ci_runners_on_contacted_at", using: :btree
- add_index "ci_runners", ["is_shared"], name: "index_ci_runners_on_is_shared", using: :btree
- add_index "ci_runners", ["locked"], name: "index_ci_runners_on_locked", using: :btree
- add_index "ci_runners", ["runner_type"], name: "index_ci_runners_on_runner_type", using: :btree
- add_index "ci_runners", ["token"], name: "index_ci_runners_on_token", using: :btree
-
create_table "ci_stages", force: :cascade do |t|
t.integer "project_id"
t.integer "pipeline_id"
@@ -537,23 +536,22 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.integer "status"
t.integer "lock_version"
t.integer "position"
+ t.index ["pipeline_id", "name"], name: "index_ci_stages_on_pipeline_id_and_name", unique: true, using: :btree
+ t.index ["pipeline_id", "position"], name: "index_ci_stages_on_pipeline_id_and_position", using: :btree
+ t.index ["pipeline_id"], name: "index_ci_stages_on_pipeline_id", using: :btree
+ t.index ["project_id"], name: "index_ci_stages_on_project_id", using: :btree
end
- add_index "ci_stages", ["pipeline_id", "name"], name: "index_ci_stages_on_pipeline_id_and_name", unique: true, using: :btree
- add_index "ci_stages", ["pipeline_id", "position"], name: "index_ci_stages_on_pipeline_id_and_position", using: :btree
- add_index "ci_stages", ["pipeline_id"], name: "index_ci_stages_on_pipeline_id", using: :btree
- add_index "ci_stages", ["project_id"], name: "index_ci_stages_on_project_id", using: :btree
-
create_table "ci_trigger_requests", force: :cascade do |t|
t.integer "trigger_id", null: false
t.text "variables"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "commit_id"
+ t.index ["commit_id"], name: "index_ci_trigger_requests_on_commit_id", using: :btree
+ t.index ["trigger_id"], name: "index_ci_trigger_requests_on_trigger_id", using: :btree
end
- add_index "ci_trigger_requests", ["commit_id"], name: "index_ci_trigger_requests_on_commit_id", using: :btree
-
create_table "ci_triggers", force: :cascade do |t|
t.string "token"
t.datetime "created_at"
@@ -562,10 +560,10 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.integer "owner_id"
t.string "description"
t.string "ref"
+ t.index ["owner_id"], name: "index_ci_triggers_on_owner_id", using: :btree
+ t.index ["project_id"], name: "index_ci_triggers_on_project_id", using: :btree
end
- add_index "ci_triggers", ["project_id"], name: "index_ci_triggers_on_project_id", using: :btree
-
create_table "ci_variables", force: :cascade do |t|
t.string "key", null: false
t.text "value"
@@ -575,9 +573,15 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.integer "project_id", null: false
t.boolean "protected", default: false, null: false
t.string "environment_scope", default: "*", null: false
+ t.index ["project_id", "key", "environment_scope"], name: "index_ci_variables_on_project_id_and_key_and_environment_scope", unique: true, using: :btree
end
- add_index "ci_variables", ["project_id", "key", "environment_scope"], name: "index_ci_variables_on_project_id_and_key_and_environment_scope", unique: true, using: :btree
+ create_table "cluster_groups", force: :cascade do |t|
+ t.integer "cluster_id", null: false
+ t.integer "group_id", null: false
+ t.index ["cluster_id", "group_id"], name: "index_cluster_groups_on_cluster_id_and_group_id", unique: true, using: :btree
+ t.index ["group_id"], name: "index_cluster_groups_on_group_id", using: :btree
+ end
create_table "cluster_platforms_kubernetes", force: :cascade do |t|
t.integer "cluster_id", null: false
@@ -592,20 +596,18 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.text "encrypted_token"
t.string "encrypted_token_iv"
t.integer "authorization_type", limit: 2
+ t.index ["cluster_id"], name: "index_cluster_platforms_kubernetes_on_cluster_id", unique: true, using: :btree
end
- add_index "cluster_platforms_kubernetes", ["cluster_id"], name: "index_cluster_platforms_kubernetes_on_cluster_id", unique: true, using: :btree
-
create_table "cluster_projects", force: :cascade do |t|
t.integer "project_id", null: false
t.integer "cluster_id", null: false
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
+ t.index ["cluster_id"], name: "index_cluster_projects_on_cluster_id", using: :btree
+ t.index ["project_id"], name: "index_cluster_projects_on_project_id", using: :btree
end
- add_index "cluster_projects", ["cluster_id"], name: "index_cluster_projects_on_cluster_id", using: :btree
- add_index "cluster_projects", ["project_id"], name: "index_cluster_projects_on_project_id", using: :btree
-
create_table "cluster_providers_gcp", force: :cascade do |t|
t.integer "cluster_id", null: false
t.integer "status"
@@ -621,10 +623,9 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.text "encrypted_access_token"
t.string "encrypted_access_token_iv"
t.boolean "legacy_abac", default: true, null: false
+ t.index ["cluster_id"], name: "index_cluster_providers_gcp_on_cluster_id", unique: true, using: :btree
end
- add_index "cluster_providers_gcp", ["cluster_id"], name: "index_cluster_providers_gcp_on_cluster_id", unique: true, using: :btree
-
create_table "clusters", force: :cascade do |t|
t.integer "user_id"
t.integer "provider_type"
@@ -634,10 +635,21 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.boolean "enabled", default: true
t.string "name", null: false
t.string "environment_scope", default: "*", null: false
+ t.integer "cluster_type", limit: 2, default: 3, null: false
+ t.index ["enabled"], name: "index_clusters_on_enabled", using: :btree
+ t.index ["user_id"], name: "index_clusters_on_user_id", using: :btree
end
- add_index "clusters", ["enabled"], name: "index_clusters_on_enabled", using: :btree
- add_index "clusters", ["user_id"], name: "index_clusters_on_user_id", using: :btree
+ create_table "clusters_applications_cert_managers", force: :cascade do |t|
+ t.integer "cluster_id", null: false
+ t.integer "status", null: false
+ t.string "version", null: false
+ t.string "email", null: false
+ t.datetime_with_timezone "created_at", null: false
+ t.datetime_with_timezone "updated_at", null: false
+ t.text "status_reason"
+ t.index ["cluster_id"], name: "index_clusters_applications_cert_managers_on_cluster_id", unique: true, using: :btree
+ end
create_table "clusters_applications_helm", force: :cascade do |t|
t.integer "cluster_id", null: false
@@ -649,6 +661,7 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.text "encrypted_ca_key"
t.text "encrypted_ca_key_iv"
t.text "ca_cert"
+ t.index ["cluster_id"], name: "index_clusters_applications_helm_on_cluster_id", unique: true, using: :btree
end
create_table "clusters_applications_ingress", force: :cascade do |t|
@@ -661,6 +674,7 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "cluster_ip"
t.text "status_reason"
t.string "external_ip"
+ t.index ["cluster_id"], name: "index_clusters_applications_ingress_on_cluster_id", unique: true, using: :btree
end
create_table "clusters_applications_jupyter", force: :cascade do |t|
@@ -672,6 +686,20 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.text "status_reason"
+ t.index ["cluster_id"], name: "index_clusters_applications_jupyter_on_cluster_id", unique: true, using: :btree
+ t.index ["oauth_application_id"], name: "index_clusters_applications_jupyter_on_oauth_application_id", using: :btree
+ end
+
+ create_table "clusters_applications_knative", force: :cascade do |t|
+ t.integer "cluster_id", null: false
+ t.datetime_with_timezone "created_at", null: false
+ t.datetime_with_timezone "updated_at", null: false
+ t.integer "status", null: false
+ t.string "version", null: false
+ t.string "hostname"
+ t.text "status_reason"
+ t.string "external_ip"
+ t.index ["cluster_id"], name: "index_clusters_applications_knative_on_cluster_id", unique: true, using: :btree
end
create_table "clusters_applications_prometheus", force: :cascade do |t|
@@ -681,6 +709,7 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.text "status_reason"
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
+ t.index ["cluster_id"], name: "index_clusters_applications_prometheus_on_cluster_id", unique: true, using: :btree
end
create_table "clusters_applications_runners", force: :cascade do |t|
@@ -692,21 +721,35 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "version", null: false
t.text "status_reason"
t.boolean "privileged", default: true, null: false
+ t.index ["cluster_id"], name: "index_clusters_applications_runners_on_cluster_id", unique: true, using: :btree
+ t.index ["runner_id"], name: "index_clusters_applications_runners_on_runner_id", using: :btree
end
- add_index "clusters_applications_runners", ["cluster_id"], name: "index_clusters_applications_runners_on_cluster_id", unique: true, using: :btree
- add_index "clusters_applications_runners", ["runner_id"], name: "index_clusters_applications_runners_on_runner_id", using: :btree
+ create_table "clusters_kubernetes_namespaces", id: :bigserial, force: :cascade do |t|
+ t.integer "cluster_id", null: false
+ t.integer "project_id"
+ t.integer "cluster_project_id"
+ t.datetime_with_timezone "created_at", null: false
+ t.datetime_with_timezone "updated_at", null: false
+ t.text "encrypted_service_account_token"
+ t.string "encrypted_service_account_token_iv"
+ t.string "namespace", null: false
+ t.string "service_account_name"
+ t.index ["cluster_id", "namespace"], name: "kubernetes_namespaces_cluster_and_namespace", unique: true, using: :btree
+ t.index ["cluster_id"], name: "index_clusters_kubernetes_namespaces_on_cluster_id", using: :btree
+ t.index ["cluster_project_id"], name: "index_clusters_kubernetes_namespaces_on_cluster_project_id", using: :btree
+ t.index ["project_id"], name: "index_clusters_kubernetes_namespaces_on_project_id", using: :btree
+ end
create_table "container_repositories", force: :cascade do |t|
t.integer "project_id", null: false
t.string "name", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["project_id", "name"], name: "index_container_repositories_on_project_id_and_name", unique: true, using: :btree
+ t.index ["project_id"], name: "index_container_repositories_on_project_id", using: :btree
end
- add_index "container_repositories", ["project_id", "name"], name: "index_container_repositories_on_project_id_and_name", unique: true, using: :btree
- add_index "container_repositories", ["project_id"], name: "index_container_repositories_on_project_id", using: :btree
-
create_table "conversational_development_index_metrics", force: :cascade do |t|
t.float "leader_issues", null: false
t.float "instance_issues", null: false
@@ -748,10 +791,9 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "can_push", default: false, null: false
+ t.index ["project_id"], name: "index_deploy_keys_projects_on_project_id", using: :btree
end
- add_index "deploy_keys_projects", ["project_id"], name: "index_deploy_keys_projects_on_project_id", using: :btree
-
create_table "deploy_tokens", force: :cascade do |t|
t.boolean "revoked", default: false
t.boolean "read_repository", default: false, null: false
@@ -760,11 +802,10 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime_with_timezone "created_at", null: false
t.string "name", null: false
t.string "token", null: false
+ t.index ["token", "expires_at", "id"], name: "index_deploy_tokens_on_token_and_expires_at_and_id", where: "(revoked IS FALSE)", using: :btree
+ t.index ["token"], name: "index_deploy_tokens_on_token", unique: true, using: :btree
end
- add_index "deploy_tokens", ["token", "expires_at", "id"], name: "index_deploy_tokens_on_token_and_expires_at_and_id", where: "(revoked IS FALSE)", using: :btree
- add_index "deploy_tokens", ["token"], name: "index_deploy_tokens_on_token", unique: true, using: :btree
-
create_table "deployments", force: :cascade do |t|
t.integer "iid", null: false
t.integer "project_id", null: false
@@ -778,14 +819,19 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime "created_at"
t.datetime "updated_at"
t.string "on_stop"
+ t.integer "status", limit: 2, null: false
+ t.datetime_with_timezone "finished_at"
+ t.index ["created_at"], name: "index_deployments_on_created_at", using: :btree
+ t.index ["deployable_type", "deployable_id"], name: "index_deployments_on_deployable_type_and_deployable_id", using: :btree
+ t.index ["environment_id", "id"], name: "index_deployments_on_environment_id_and_id", using: :btree
+ t.index ["environment_id", "iid", "project_id"], name: "index_deployments_on_environment_id_and_iid_and_project_id", using: :btree
+ t.index ["environment_id", "status"], name: "index_deployments_on_environment_id_and_status", using: :btree
+ t.index ["id"], name: "partial_index_deployments_for_legacy_successful_deployments", where: "((finished_at IS NULL) AND (status = 2))", using: :btree
+ t.index ["project_id", "iid"], name: "index_deployments_on_project_id_and_iid", unique: true, using: :btree
+ t.index ["project_id", "status", "created_at"], name: "index_deployments_on_project_id_and_status_and_created_at", using: :btree
+ t.index ["project_id", "status"], name: "index_deployments_on_project_id_and_status", using: :btree
end
- add_index "deployments", ["created_at"], name: "index_deployments_on_created_at", using: :btree
- add_index "deployments", ["deployable_type", "deployable_id"], name: "index_deployments_on_deployable_type_and_deployable_id", using: :btree
- add_index "deployments", ["environment_id", "id"], name: "index_deployments_on_environment_id_and_id", using: :btree
- add_index "deployments", ["environment_id", "iid", "project_id"], name: "index_deployments_on_environment_id_and_iid_and_project_id", using: :btree
- add_index "deployments", ["project_id", "iid"], name: "index_deployments_on_project_id_and_iid", unique: true, using: :btree
-
create_table "emails", force: :cascade do |t|
t.integer "user_id", null: false
t.string "email", null: false
@@ -794,12 +840,11 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "confirmation_token"
t.datetime_with_timezone "confirmed_at"
t.datetime_with_timezone "confirmation_sent_at"
+ t.index ["confirmation_token"], name: "index_emails_on_confirmation_token", unique: true, using: :btree
+ t.index ["email"], name: "index_emails_on_email", unique: true, using: :btree
+ t.index ["user_id"], name: "index_emails_on_user_id", using: :btree
end
- add_index "emails", ["confirmation_token"], name: "index_emails_on_confirmation_token", unique: true, using: :btree
- add_index "emails", ["email"], name: "index_emails_on_email", unique: true, using: :btree
- add_index "emails", ["user_id"], name: "index_emails_on_user_id", using: :btree
-
create_table "environments", force: :cascade do |t|
t.integer "project_id", null: false
t.string "name", null: false
@@ -809,11 +854,10 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "environment_type"
t.string "state", default: "available", null: false
t.string "slug", null: false
+ t.index ["project_id", "name"], name: "index_environments_on_project_id_and_name", unique: true, using: :btree
+ t.index ["project_id", "slug"], name: "index_environments_on_project_id_and_slug", unique: true, using: :btree
end
- add_index "environments", ["project_id", "name"], name: "index_environments_on_project_id_and_name", unique: true, using: :btree
- add_index "environments", ["project_id", "slug"], name: "index_environments_on_project_id_and_slug", unique: true, using: :btree
-
create_table "events", force: :cascade do |t|
t.integer "project_id"
t.integer "author_id", null: false
@@ -822,95 +866,61 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime_with_timezone "updated_at", null: false
t.integer "action", limit: 2, null: false
t.string "target_type"
+ t.index ["action"], name: "index_events_on_action", using: :btree
+ t.index ["author_id", "project_id"], name: "index_events_on_author_id_and_project_id", using: :btree
+ t.index ["project_id", "created_at"], name: "index_events_on_project_id_and_created_at", using: :btree
+ t.index ["project_id", "id"], name: "index_events_on_project_id_and_id", using: :btree
+ t.index ["target_type", "target_id"], name: "index_events_on_target_type_and_target_id", using: :btree
end
- add_index "events", ["action"], name: "index_events_on_action", using: :btree
- add_index "events", ["author_id", "project_id"], name: "index_events_on_author_id_and_project_id", using: :btree
- add_index "events", ["project_id", "id"], name: "index_events_on_project_id_and_id", using: :btree
- add_index "events", ["target_type", "target_id"], name: "index_events_on_target_type_and_target_id", using: :btree
-
create_table "feature_gates", force: :cascade do |t|
t.string "feature_key", null: false
t.string "key", null: false
t.string "value"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["feature_key", "key", "value"], name: "index_feature_gates_on_feature_key_and_key_and_value", unique: true, using: :btree
end
- add_index "feature_gates", ["feature_key", "key", "value"], name: "index_feature_gates_on_feature_key_and_key_and_value", unique: true, using: :btree
-
create_table "features", force: :cascade do |t|
t.string "key", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["key"], name: "index_features_on_key", unique: true, using: :btree
end
- add_index "features", ["key"], name: "index_features_on_key", unique: true, using: :btree
-
create_table "fork_network_members", force: :cascade do |t|
t.integer "fork_network_id", null: false
t.integer "project_id", null: false
t.integer "forked_from_project_id"
+ t.index ["fork_network_id"], name: "index_fork_network_members_on_fork_network_id", using: :btree
+ t.index ["forked_from_project_id"], name: "index_fork_network_members_on_forked_from_project_id", using: :btree
+ t.index ["project_id"], name: "index_fork_network_members_on_project_id", unique: true, using: :btree
end
- add_index "fork_network_members", ["fork_network_id"], name: "index_fork_network_members_on_fork_network_id", using: :btree
- add_index "fork_network_members", ["project_id"], name: "index_fork_network_members_on_project_id", unique: true, using: :btree
-
create_table "fork_networks", force: :cascade do |t|
t.integer "root_project_id"
t.string "deleted_root_project_name"
+ t.index ["root_project_id"], name: "index_fork_networks_on_root_project_id", unique: true, using: :btree
end
- add_index "fork_networks", ["root_project_id"], name: "index_fork_networks_on_root_project_id", unique: true, using: :btree
-
create_table "forked_project_links", force: :cascade do |t|
t.integer "forked_to_project_id", null: false
t.integer "forked_from_project_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
+ t.index ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree
end
- add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree
-
- create_table "gcp_clusters", force: :cascade do |t|
- t.integer "project_id", null: false
- t.integer "user_id"
- t.integer "service_id"
- t.integer "status"
- t.integer "gcp_cluster_size", null: false
- t.datetime_with_timezone "created_at", null: false
- t.datetime_with_timezone "updated_at", null: false
- t.boolean "enabled", default: true
- t.text "status_reason"
- t.string "project_namespace"
- t.string "endpoint"
- t.text "ca_cert"
- t.text "encrypted_kubernetes_token"
- t.string "encrypted_kubernetes_token_iv"
- t.string "username"
- t.text "encrypted_password"
- t.string "encrypted_password_iv"
- t.string "gcp_project_id", null: false
- t.string "gcp_cluster_zone", null: false
- t.string "gcp_cluster_name", null: false
- t.string "gcp_machine_type"
- t.string "gcp_operation_id"
- t.text "encrypted_gcp_token"
- t.string "encrypted_gcp_token_iv"
- end
-
- add_index "gcp_clusters", ["project_id"], name: "index_gcp_clusters_on_project_id", unique: true, using: :btree
-
create_table "gpg_key_subkeys", force: :cascade do |t|
t.integer "gpg_key_id", null: false
t.binary "keyid"
t.binary "fingerprint"
+ t.index ["fingerprint"], name: "index_gpg_key_subkeys_on_fingerprint", unique: true, using: :btree
+ t.index ["gpg_key_id"], name: "index_gpg_key_subkeys_on_gpg_key_id", using: :btree
+ t.index ["keyid"], name: "index_gpg_key_subkeys_on_keyid", unique: true, using: :btree
end
- add_index "gpg_key_subkeys", ["fingerprint"], name: "index_gpg_key_subkeys_on_fingerprint", unique: true, using: :btree
- add_index "gpg_key_subkeys", ["gpg_key_id"], name: "index_gpg_key_subkeys_on_gpg_key_id", using: :btree
- add_index "gpg_key_subkeys", ["keyid"], name: "index_gpg_key_subkeys_on_keyid", unique: true, using: :btree
-
create_table "gpg_keys", force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
@@ -918,12 +928,11 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.binary "primary_keyid"
t.binary "fingerprint"
t.text "key"
+ t.index ["fingerprint"], name: "index_gpg_keys_on_fingerprint", unique: true, using: :btree
+ t.index ["primary_keyid"], name: "index_gpg_keys_on_primary_keyid", unique: true, using: :btree
+ t.index ["user_id"], name: "index_gpg_keys_on_user_id", using: :btree
end
- add_index "gpg_keys", ["fingerprint"], name: "index_gpg_keys_on_fingerprint", unique: true, using: :btree
- add_index "gpg_keys", ["primary_keyid"], name: "index_gpg_keys_on_primary_keyid", unique: true, using: :btree
- add_index "gpg_keys", ["user_id"], name: "index_gpg_keys_on_user_id", using: :btree
-
create_table "gpg_signatures", force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
@@ -935,63 +944,59 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.text "gpg_key_user_email"
t.integer "verification_status", limit: 2, default: 0, null: false
t.integer "gpg_key_subkey_id"
+ t.index ["commit_sha"], name: "index_gpg_signatures_on_commit_sha", unique: true, using: :btree
+ t.index ["gpg_key_id"], name: "index_gpg_signatures_on_gpg_key_id", using: :btree
+ t.index ["gpg_key_primary_keyid"], name: "index_gpg_signatures_on_gpg_key_primary_keyid", using: :btree
+ t.index ["gpg_key_subkey_id"], name: "index_gpg_signatures_on_gpg_key_subkey_id", using: :btree
+ t.index ["project_id"], name: "index_gpg_signatures_on_project_id", using: :btree
end
- add_index "gpg_signatures", ["commit_sha"], name: "index_gpg_signatures_on_commit_sha", unique: true, using: :btree
- add_index "gpg_signatures", ["gpg_key_id"], name: "index_gpg_signatures_on_gpg_key_id", using: :btree
- add_index "gpg_signatures", ["gpg_key_primary_keyid"], name: "index_gpg_signatures_on_gpg_key_primary_keyid", using: :btree
- add_index "gpg_signatures", ["gpg_key_subkey_id"], name: "index_gpg_signatures_on_gpg_key_subkey_id", using: :btree
- add_index "gpg_signatures", ["project_id"], name: "index_gpg_signatures_on_project_id", using: :btree
-
create_table "group_custom_attributes", force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.integer "group_id", null: false
t.string "key", null: false
t.string "value", null: false
+ t.index ["group_id", "key"], name: "index_group_custom_attributes_on_group_id_and_key", unique: true, using: :btree
+ t.index ["key", "value"], name: "index_group_custom_attributes_on_key_and_value", using: :btree
end
- add_index "group_custom_attributes", ["group_id", "key"], name: "index_group_custom_attributes_on_group_id_and_key", unique: true, using: :btree
- add_index "group_custom_attributes", ["key", "value"], name: "index_group_custom_attributes_on_key_and_value", using: :btree
-
create_table "identities", force: :cascade do |t|
t.string "extern_uid"
t.string "provider"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
+ t.index ["user_id"], name: "index_identities_on_user_id", using: :btree
end
- add_index "identities", ["user_id"], name: "index_identities_on_user_id", using: :btree
-
create_table "import_export_uploads", force: :cascade do |t|
t.datetime_with_timezone "updated_at", null: false
t.integer "project_id"
t.text "import_file"
t.text "export_file"
+ t.index ["project_id"], name: "index_import_export_uploads_on_project_id", using: :btree
+ t.index ["updated_at"], name: "index_import_export_uploads_on_updated_at", using: :btree
end
- add_index "import_export_uploads", ["project_id"], name: "index_import_export_uploads_on_project_id", using: :btree
- add_index "import_export_uploads", ["updated_at"], name: "index_import_export_uploads_on_updated_at", using: :btree
-
create_table "internal_ids", id: :bigserial, force: :cascade do |t|
t.integer "project_id"
t.integer "usage", null: false
t.integer "last_value", null: false
t.integer "namespace_id"
+ t.index ["namespace_id"], name: "index_internal_ids_on_namespace_id", using: :btree
+ t.index ["project_id"], name: "index_internal_ids_on_project_id", using: :btree
+ t.index ["usage", "namespace_id"], name: "index_internal_ids_on_usage_and_namespace_id", unique: true, where: "(namespace_id IS NOT NULL)", using: :btree
+ t.index ["usage", "project_id"], name: "index_internal_ids_on_usage_and_project_id", unique: true, where: "(project_id IS NOT NULL)", using: :btree
end
- add_index "internal_ids", ["usage", "namespace_id"], name: "index_internal_ids_on_usage_and_namespace_id", unique: true, where: "(namespace_id IS NOT NULL)", using: :btree
- add_index "internal_ids", ["usage", "project_id"], name: "index_internal_ids_on_usage_and_project_id", unique: true, where: "(project_id IS NOT NULL)", using: :btree
-
create_table "issue_assignees", id: false, force: :cascade do |t|
t.integer "user_id", null: false
t.integer "issue_id", null: false
+ t.index ["issue_id", "user_id"], name: "index_issue_assignees_on_issue_id_and_user_id", unique: true, using: :btree
+ t.index ["user_id"], name: "index_issue_assignees_on_user_id", using: :btree
end
- add_index "issue_assignees", ["issue_id", "user_id"], name: "index_issue_assignees_on_issue_id_and_user_id", unique: true, using: :btree
- add_index "issue_assignees", ["user_id"], name: "index_issue_assignees_on_user_id", using: :btree
-
create_table "issue_metrics", force: :cascade do |t|
t.integer "issue_id", null: false
t.datetime "first_mentioned_in_commit_at"
@@ -999,10 +1004,9 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime "first_added_to_board_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["issue_id"], name: "index_issue_metrics", using: :btree
end
- add_index "issue_metrics", ["issue_id"], name: "index_issue_metrics", using: :btree
-
create_table "issues", force: :cascade do |t|
t.string "title"
t.integer "author_id"
@@ -1028,23 +1032,23 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.boolean "discussion_locked"
t.datetime_with_timezone "closed_at"
t.integer "closed_by_id"
+ t.index ["author_id"], name: "index_issues_on_author_id", using: :btree
+ t.index ["closed_by_id"], name: "index_issues_on_closed_by_id", using: :btree
+ t.index ["confidential"], name: "index_issues_on_confidential", using: :btree
+ t.index ["description"], name: "index_issues_on_description_trigram", using: :gin, opclasses: {"description"=>"gin_trgm_ops"}
+ t.index ["milestone_id"], name: "index_issues_on_milestone_id", using: :btree
+ t.index ["moved_to_id"], name: "index_issues_on_moved_to_id", where: "(moved_to_id IS NOT NULL)", using: :btree
+ t.index ["project_id", "created_at", "id", "state"], name: "index_issues_on_project_id_and_created_at_and_id_and_state", using: :btree
+ t.index ["project_id", "due_date", "id", "state"], name: "idx_issues_on_project_id_and_due_date_and_id_and_state_partial", where: "(due_date IS NOT NULL)", using: :btree
+ t.index ["project_id", "iid"], name: "index_issues_on_project_id_and_iid", unique: true, using: :btree
+ t.index ["project_id", "updated_at", "id", "state"], name: "index_issues_on_project_id_and_updated_at_and_id_and_state", using: :btree
+ t.index ["relative_position"], name: "index_issues_on_relative_position", using: :btree
+ t.index ["state"], name: "index_issues_on_state", using: :btree
+ t.index ["title"], name: "index_issues_on_title_trigram", using: :gin, opclasses: {"title"=>"gin_trgm_ops"}
+ t.index ["updated_at"], name: "index_issues_on_updated_at", using: :btree
+ t.index ["updated_by_id"], name: "index_issues_on_updated_by_id", where: "(updated_by_id IS NOT NULL)", using: :btree
end
- add_index "issues", ["author_id"], name: "index_issues_on_author_id", using: :btree
- add_index "issues", ["confidential"], name: "index_issues_on_confidential", using: :btree
- add_index "issues", ["description"], name: "index_issues_on_description_trigram", using: :gin, opclasses: {"description"=>"gin_trgm_ops"}
- add_index "issues", ["milestone_id"], name: "index_issues_on_milestone_id", using: :btree
- add_index "issues", ["moved_to_id"], name: "index_issues_on_moved_to_id", where: "(moved_to_id IS NOT NULL)", using: :btree
- add_index "issues", ["project_id", "created_at", "id", "state"], name: "index_issues_on_project_id_and_created_at_and_id_and_state", using: :btree
- add_index "issues", ["project_id", "due_date", "id", "state"], name: "idx_issues_on_project_id_and_due_date_and_id_and_state_partial", where: "(due_date IS NOT NULL)", using: :btree
- add_index "issues", ["project_id", "iid"], name: "index_issues_on_project_id_and_iid", unique: true, using: :btree
- add_index "issues", ["project_id", "updated_at", "id", "state"], name: "index_issues_on_project_id_and_updated_at_and_id_and_state", using: :btree
- add_index "issues", ["relative_position"], name: "index_issues_on_relative_position", using: :btree
- add_index "issues", ["state"], name: "index_issues_on_state", using: :btree
- add_index "issues", ["title"], name: "index_issues_on_title_trigram", using: :gin, opclasses: {"title"=>"gin_trgm_ops"}
- add_index "issues", ["updated_at"], name: "index_issues_on_updated_at", using: :btree
- add_index "issues", ["updated_by_id"], name: "index_issues_on_updated_by_id", where: "(updated_by_id IS NOT NULL)", using: :btree
-
create_table "keys", force: :cascade do |t|
t.integer "user_id"
t.datetime "created_at"
@@ -1055,33 +1059,31 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "fingerprint"
t.boolean "public", default: false, null: false
t.datetime "last_used_at"
+ t.index ["fingerprint"], name: "index_keys_on_fingerprint", unique: true, using: :btree
+ t.index ["user_id"], name: "index_keys_on_user_id", using: :btree
end
- add_index "keys", ["fingerprint"], name: "index_keys_on_fingerprint", unique: true, using: :btree
- add_index "keys", ["user_id"], name: "index_keys_on_user_id", using: :btree
-
create_table "label_links", force: :cascade do |t|
t.integer "label_id"
t.integer "target_id"
t.string "target_type"
t.datetime "created_at"
t.datetime "updated_at"
+ t.index ["label_id"], name: "index_label_links_on_label_id", using: :btree
+ t.index ["target_id", "target_type"], name: "index_label_links_on_target_id_and_target_type", using: :btree
end
- add_index "label_links", ["label_id"], name: "index_label_links_on_label_id", using: :btree
- add_index "label_links", ["target_id", "target_type"], name: "index_label_links_on_target_id_and_target_type", using: :btree
-
create_table "label_priorities", force: :cascade do |t|
t.integer "project_id", null: false
t.integer "label_id", null: false
t.integer "priority", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["label_id"], name: "index_label_priorities_on_label_id", using: :btree
+ t.index ["priority"], name: "index_label_priorities_on_priority", using: :btree
+ t.index ["project_id", "label_id"], name: "index_label_priorities_on_project_id_and_label_id", unique: true, using: :btree
end
- add_index "label_priorities", ["priority"], name: "index_label_priorities_on_priority", using: :btree
- add_index "label_priorities", ["project_id", "label_id"], name: "index_label_priorities_on_project_id_and_label_id", unique: true, using: :btree
-
create_table "labels", force: :cascade do |t|
t.string "title"
t.string "color"
@@ -1094,44 +1096,41 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "type"
t.integer "group_id"
t.integer "cached_markdown_version"
+ t.index ["group_id", "project_id", "title"], name: "index_labels_on_group_id_and_project_id_and_title", unique: true, using: :btree
+ t.index ["project_id"], name: "index_labels_on_project_id", using: :btree
+ t.index ["template"], name: "index_labels_on_template", where: "template", using: :btree
+ t.index ["title"], name: "index_labels_on_title", using: :btree
+ t.index ["type", "project_id"], name: "index_labels_on_type_and_project_id", using: :btree
end
- add_index "labels", ["group_id", "project_id", "title"], name: "index_labels_on_group_id_and_project_id_and_title", unique: true, using: :btree
- add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree
- add_index "labels", ["template"], name: "index_labels_on_template", where: "template", using: :btree
- add_index "labels", ["title"], name: "index_labels_on_title", using: :btree
- add_index "labels", ["type", "project_id"], name: "index_labels_on_type_and_project_id", using: :btree
-
create_table "lfs_file_locks", force: :cascade do |t|
t.integer "project_id", null: false
t.integer "user_id", null: false
t.datetime "created_at", null: false
t.string "path", limit: 511
+ t.index ["project_id", "path"], name: "index_lfs_file_locks_on_project_id_and_path", unique: true, using: :btree
+ t.index ["user_id"], name: "index_lfs_file_locks_on_user_id", using: :btree
end
- add_index "lfs_file_locks", ["project_id", "path"], name: "index_lfs_file_locks_on_project_id_and_path", unique: true, using: :btree
- add_index "lfs_file_locks", ["user_id"], name: "index_lfs_file_locks_on_user_id", using: :btree
-
create_table "lfs_objects", force: :cascade do |t|
t.string "oid", null: false
- t.integer "size", limit: 8, null: false
+ t.bigint "size", null: false
t.datetime "created_at"
t.datetime "updated_at"
t.string "file"
t.integer "file_store"
+ t.index ["file_store"], name: "index_lfs_objects_on_file_store", using: :btree
+ t.index ["oid"], name: "index_lfs_objects_on_oid", unique: true, using: :btree
end
- add_index "lfs_objects", ["oid"], name: "index_lfs_objects_on_oid", unique: true, using: :btree
-
create_table "lfs_objects_projects", force: :cascade do |t|
t.integer "lfs_object_id", null: false
t.integer "project_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
+ t.index ["project_id"], name: "index_lfs_objects_projects_on_project_id", using: :btree
end
- add_index "lfs_objects_projects", ["project_id"], name: "index_lfs_objects_projects_on_project_id", using: :btree
-
create_table "lists", force: :cascade do |t|
t.integer "board_id", null: false
t.integer "label_id"
@@ -1139,12 +1138,11 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.integer "position"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["board_id", "label_id"], name: "index_lists_on_board_id_and_label_id", unique: true, using: :btree
+ t.index ["label_id"], name: "index_lists_on_label_id", using: :btree
+ t.index ["list_type"], name: "index_lists_on_list_type", using: :btree
end
- add_index "lists", ["board_id", "label_id"], name: "index_lists_on_board_id_and_label_id", unique: true, using: :btree
- add_index "lists", ["label_id"], name: "index_lists_on_label_id", using: :btree
- add_index "lists", ["list_type"], name: "index_lists_on_list_type", using: :btree
-
create_table "members", force: :cascade do |t|
t.integer "access_level", null: false
t.integer "source_id", null: false
@@ -1160,14 +1158,13 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime "invite_accepted_at"
t.datetime "requested_at"
t.date "expires_at"
+ t.index ["access_level"], name: "index_members_on_access_level", using: :btree
+ t.index ["invite_token"], name: "index_members_on_invite_token", unique: true, using: :btree
+ t.index ["requested_at"], name: "index_members_on_requested_at", using: :btree
+ t.index ["source_id", "source_type"], name: "index_members_on_source_id_and_source_type", using: :btree
+ t.index ["user_id"], name: "index_members_on_user_id", using: :btree
end
- add_index "members", ["access_level"], name: "index_members_on_access_level", using: :btree
- add_index "members", ["invite_token"], name: "index_members_on_invite_token", unique: true, using: :btree
- add_index "members", ["requested_at"], name: "index_members_on_requested_at", using: :btree
- add_index "members", ["source_id", "source_type"], name: "index_members_on_source_id_and_source_type", using: :btree
- add_index "members", ["user_id"], name: "index_members_on_user_id", using: :btree
-
create_table "merge_request_diff_commits", id: false, force: :cascade do |t|
t.datetime_with_timezone "authored_date"
t.datetime_with_timezone "committed_date"
@@ -1179,11 +1176,10 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.text "committer_name"
t.text "committer_email"
t.text "message"
+ t.index ["merge_request_diff_id", "relative_order"], name: "index_merge_request_diff_commits_on_mr_diff_id_and_order", unique: true, using: :btree
+ t.index ["sha"], name: "index_merge_request_diff_commits_on_sha", using: :btree
end
- add_index "merge_request_diff_commits", ["merge_request_diff_id", "relative_order"], name: "index_merge_request_diff_commits_on_mr_diff_id_and_order", unique: true, using: :btree
- add_index "merge_request_diff_commits", ["sha"], name: "index_merge_request_diff_commits_on_sha", using: :btree
-
create_table "merge_request_diff_files", id: false, force: :cascade do |t|
t.integer "merge_request_diff_id", null: false
t.integer "relative_order", null: false
@@ -1197,10 +1193,9 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.text "old_path", null: false
t.text "diff", null: false
t.boolean "binary"
+ t.index ["merge_request_diff_id", "relative_order"], name: "index_merge_request_diff_files_on_mr_diff_id_and_order", unique: true, using: :btree
end
- add_index "merge_request_diff_files", ["merge_request_diff_id", "relative_order"], name: "index_merge_request_diff_files_on_mr_diff_id_and_order", unique: true, using: :btree
-
create_table "merge_request_diffs", force: :cascade do |t|
t.string "state"
t.integer "merge_request_id", null: false
@@ -1211,10 +1206,9 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "head_commit_sha"
t.string "start_commit_sha"
t.integer "commits_count"
+ t.index ["merge_request_id", "id"], name: "index_merge_request_diffs_on_merge_request_id_and_id", using: :btree
end
- add_index "merge_request_diffs", ["merge_request_id", "id"], name: "index_merge_request_diffs_on_merge_request_id_and_id", using: :btree
-
create_table "merge_request_metrics", force: :cascade do |t|
t.integer "merge_request_id", null: false
t.datetime "latest_build_started_at"
@@ -1227,12 +1221,13 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.integer "merged_by_id"
t.integer "latest_closed_by_id"
t.datetime_with_timezone "latest_closed_at"
+ t.index ["first_deployed_to_production_at"], name: "index_merge_request_metrics_on_first_deployed_to_production_at", using: :btree
+ t.index ["latest_closed_by_id"], name: "index_merge_request_metrics_on_latest_closed_by_id", using: :btree
+ t.index ["merge_request_id"], name: "index_merge_request_metrics", using: :btree
+ t.index ["merged_by_id"], name: "index_merge_request_metrics_on_merged_by_id", using: :btree
+ t.index ["pipeline_id"], name: "index_merge_request_metrics_on_pipeline_id", using: :btree
end
- add_index "merge_request_metrics", ["first_deployed_to_production_at"], name: "index_merge_request_metrics_on_first_deployed_to_production_at", using: :btree
- add_index "merge_request_metrics", ["merge_request_id"], name: "index_merge_request_metrics", using: :btree
- add_index "merge_request_metrics", ["pipeline_id"], name: "index_merge_request_metrics_on_pipeline_id", using: :btree
-
create_table "merge_requests", force: :cascade do |t|
t.string "target_branch", null: false
t.string "source_branch", null: false
@@ -1269,37 +1264,36 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "rebase_commit_sha"
t.boolean "squash", default: false, null: false
t.boolean "allow_maintainer_to_push"
+ t.index ["assignee_id"], name: "index_merge_requests_on_assignee_id", using: :btree
+ t.index ["author_id"], name: "index_merge_requests_on_author_id", using: :btree
+ t.index ["created_at"], name: "index_merge_requests_on_created_at", using: :btree
+ t.index ["description"], name: "index_merge_requests_on_description_trigram", using: :gin, opclasses: {"description"=>"gin_trgm_ops"}
+ t.index ["head_pipeline_id"], name: "index_merge_requests_on_head_pipeline_id", using: :btree
+ t.index ["id", "merge_jid"], name: "index_merge_requests_on_id_and_merge_jid", where: "((merge_jid IS NOT NULL) AND ((state)::text = 'locked'::text))", using: :btree
+ t.index ["latest_merge_request_diff_id"], name: "index_merge_requests_on_latest_merge_request_diff_id", using: :btree
+ t.index ["merge_user_id"], name: "index_merge_requests_on_merge_user_id", where: "(merge_user_id IS NOT NULL)", using: :btree
+ t.index ["milestone_id"], name: "index_merge_requests_on_milestone_id", using: :btree
+ t.index ["source_branch"], name: "index_merge_requests_on_source_branch", using: :btree
+ t.index ["source_project_id", "source_branch"], name: "index_merge_requests_on_source_project_and_branch_state_opened", where: "((state)::text = 'opened'::text)", using: :btree
+ t.index ["source_project_id", "source_branch"], name: "index_merge_requests_on_source_project_id_and_source_branch", using: :btree
+ t.index ["target_branch"], name: "index_merge_requests_on_target_branch", using: :btree
+ t.index ["target_project_id", "iid"], name: "index_merge_requests_on_target_project_id_and_iid", unique: true, using: :btree
+ t.index ["target_project_id", "iid"], name: "index_merge_requests_on_target_project_id_and_iid_opened", where: "((state)::text = 'opened'::text)", using: :btree
+ t.index ["target_project_id", "merge_commit_sha", "id"], name: "index_merge_requests_on_tp_id_and_merge_commit_sha_and_id", using: :btree
+ t.index ["title"], name: "index_merge_requests_on_title", using: :btree
+ t.index ["title"], name: "index_merge_requests_on_title_trigram", using: :gin, opclasses: {"title"=>"gin_trgm_ops"}
+ t.index ["updated_by_id"], name: "index_merge_requests_on_updated_by_id", where: "(updated_by_id IS NOT NULL)", using: :btree
end
- add_index "merge_requests", ["assignee_id"], name: "index_merge_requests_on_assignee_id", using: :btree
- add_index "merge_requests", ["author_id"], name: "index_merge_requests_on_author_id", using: :btree
- add_index "merge_requests", ["created_at"], name: "index_merge_requests_on_created_at", using: :btree
- add_index "merge_requests", ["description"], name: "index_merge_requests_on_description_trigram", using: :gin, opclasses: {"description"=>"gin_trgm_ops"}
- add_index "merge_requests", ["head_pipeline_id"], name: "index_merge_requests_on_head_pipeline_id", using: :btree
- add_index "merge_requests", ["latest_merge_request_diff_id"], name: "index_merge_requests_on_latest_merge_request_diff_id", using: :btree
- add_index "merge_requests", ["merge_user_id"], name: "index_merge_requests_on_merge_user_id", where: "(merge_user_id IS NOT NULL)", using: :btree
- add_index "merge_requests", ["milestone_id"], name: "index_merge_requests_on_milestone_id", using: :btree
- add_index "merge_requests", ["source_branch"], name: "index_merge_requests_on_source_branch", using: :btree
- add_index "merge_requests", ["source_project_id", "source_branch"], name: "index_merge_requests_on_source_project_and_branch_state_opened", where: "((state)::text = 'opened'::text)", using: :btree
- add_index "merge_requests", ["source_project_id", "source_branch"], name: "index_merge_requests_on_source_project_id_and_source_branch", using: :btree
- add_index "merge_requests", ["target_branch"], name: "index_merge_requests_on_target_branch", using: :btree
- add_index "merge_requests", ["target_project_id", "iid"], name: "index_merge_requests_on_target_project_id_and_iid", unique: true, using: :btree
- add_index "merge_requests", ["target_project_id", "iid"], name: "index_merge_requests_on_target_project_id_and_iid_opened", where: "((state)::text = 'opened'::text)", using: :btree
- add_index "merge_requests", ["target_project_id", "merge_commit_sha", "id"], name: "index_merge_requests_on_tp_id_and_merge_commit_sha_and_id", using: :btree
- add_index "merge_requests", ["title"], name: "index_merge_requests_on_title", using: :btree
- add_index "merge_requests", ["title"], name: "index_merge_requests_on_title_trigram", using: :gin, opclasses: {"title"=>"gin_trgm_ops"}
- add_index "merge_requests", ["updated_by_id"], name: "index_merge_requests_on_updated_by_id", where: "(updated_by_id IS NOT NULL)", using: :btree
-
create_table "merge_requests_closing_issues", force: :cascade do |t|
t.integer "merge_request_id", null: false
t.integer "issue_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["issue_id"], name: "index_merge_requests_closing_issues_on_issue_id", using: :btree
+ t.index ["merge_request_id"], name: "index_merge_requests_closing_issues_on_merge_request_id", using: :btree
end
- add_index "merge_requests_closing_issues", ["issue_id"], name: "index_merge_requests_closing_issues_on_issue_id", using: :btree
- add_index "merge_requests_closing_issues", ["merge_request_id"], name: "index_merge_requests_closing_issues_on_merge_request_id", using: :btree
-
create_table "milestones", force: :cascade do |t|
t.string "title", null: false
t.integer "project_id"
@@ -1314,15 +1308,14 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.date "start_date"
t.integer "cached_markdown_version"
t.integer "group_id"
+ t.index ["description"], name: "index_milestones_on_description_trigram", using: :gin, opclasses: {"description"=>"gin_trgm_ops"}
+ t.index ["due_date"], name: "index_milestones_on_due_date", using: :btree
+ t.index ["group_id"], name: "index_milestones_on_group_id", using: :btree
+ t.index ["project_id", "iid"], name: "index_milestones_on_project_id_and_iid", unique: true, using: :btree
+ t.index ["title"], name: "index_milestones_on_title", using: :btree
+ t.index ["title"], name: "index_milestones_on_title_trigram", using: :gin, opclasses: {"title"=>"gin_trgm_ops"}
end
- add_index "milestones", ["description"], name: "index_milestones_on_description_trigram", using: :gin, opclasses: {"description"=>"gin_trgm_ops"}
- add_index "milestones", ["due_date"], name: "index_milestones_on_due_date", using: :btree
- add_index "milestones", ["group_id"], name: "index_milestones_on_group_id", using: :btree
- add_index "milestones", ["project_id", "iid"], name: "index_milestones_on_project_id_and_iid", unique: true, using: :btree
- add_index "milestones", ["title"], name: "index_milestones_on_title", using: :btree
- add_index "milestones", ["title"], name: "index_milestones_on_title_trigram", using: :gin, opclasses: {"title"=>"gin_trgm_ops"}
-
create_table "namespaces", force: :cascade do |t|
t.string "name", null: false
t.string "path", null: false
@@ -1342,19 +1335,18 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.integer "two_factor_grace_period", default: 48, null: false
t.integer "cached_markdown_version"
t.string "runners_token"
+ t.index ["created_at"], name: "index_namespaces_on_created_at", using: :btree
+ t.index ["name", "parent_id"], name: "index_namespaces_on_name_and_parent_id", unique: true, using: :btree
+ t.index ["name"], name: "index_namespaces_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}
+ t.index ["owner_id"], name: "index_namespaces_on_owner_id", using: :btree
+ t.index ["parent_id", "id"], name: "index_namespaces_on_parent_id_and_id", unique: true, using: :btree
+ t.index ["path"], name: "index_namespaces_on_path", using: :btree
+ t.index ["path"], name: "index_namespaces_on_path_trigram", using: :gin, opclasses: {"path"=>"gin_trgm_ops"}
+ t.index ["require_two_factor_authentication"], name: "index_namespaces_on_require_two_factor_authentication", using: :btree
+ t.index ["runners_token"], name: "index_namespaces_on_runners_token", unique: true, using: :btree
+ t.index ["type"], name: "index_namespaces_on_type", using: :btree
end
- add_index "namespaces", ["created_at"], name: "index_namespaces_on_created_at", using: :btree
- add_index "namespaces", ["name", "parent_id"], name: "index_namespaces_on_name_and_parent_id", unique: true, using: :btree
- add_index "namespaces", ["name"], name: "index_namespaces_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}
- add_index "namespaces", ["owner_id"], name: "index_namespaces_on_owner_id", using: :btree
- add_index "namespaces", ["parent_id", "id"], name: "index_namespaces_on_parent_id_and_id", unique: true, using: :btree
- add_index "namespaces", ["path"], name: "index_namespaces_on_path", using: :btree
- add_index "namespaces", ["path"], name: "index_namespaces_on_path_trigram", using: :gin, opclasses: {"path"=>"gin_trgm_ops"}
- add_index "namespaces", ["require_two_factor_authentication"], name: "index_namespaces_on_require_two_factor_authentication", using: :btree
- add_index "namespaces", ["runners_token"], name: "index_namespaces_on_runners_token", unique: true, using: :btree
- add_index "namespaces", ["type"], name: "index_namespaces_on_type", using: :btree
-
create_table "note_diff_files", force: :cascade do |t|
t.integer "diff_note_id", null: false
t.text "diff", null: false
@@ -1365,10 +1357,9 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "b_mode", null: false
t.text "new_path", null: false
t.text "old_path", null: false
+ t.index ["diff_note_id"], name: "index_note_diff_files_on_diff_note_id", unique: true, using: :btree
end
- add_index "note_diff_files", ["diff_note_id"], name: "index_note_diff_files_on_diff_note_id", unique: true, using: :btree
-
create_table "notes", force: :cascade do |t|
t.text "note"
t.string "noteable_type"
@@ -1393,19 +1384,17 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.integer "cached_markdown_version"
t.text "change_position"
t.boolean "resolved_by_push"
+ t.index ["author_id"], name: "index_notes_on_author_id", using: :btree
+ t.index ["commit_id"], name: "index_notes_on_commit_id", using: :btree
+ t.index ["created_at"], name: "index_notes_on_created_at", using: :btree
+ t.index ["discussion_id"], name: "index_notes_on_discussion_id", using: :btree
+ t.index ["line_code"], name: "index_notes_on_line_code", using: :btree
+ t.index ["note"], name: "index_notes_on_note_trigram", using: :gin, opclasses: {"note"=>"gin_trgm_ops"}
+ t.index ["noteable_id", "noteable_type"], name: "index_notes_on_noteable_id_and_noteable_type", using: :btree
+ t.index ["noteable_type"], name: "index_notes_on_noteable_type", using: :btree
+ t.index ["project_id", "noteable_type"], name: "index_notes_on_project_id_and_noteable_type", using: :btree
end
- add_index "notes", ["author_id"], name: "index_notes_on_author_id", using: :btree
- add_index "notes", ["commit_id"], name: "index_notes_on_commit_id", using: :btree
- add_index "notes", ["created_at"], name: "index_notes_on_created_at", using: :btree
- add_index "notes", ["discussion_id"], name: "index_notes_on_discussion_id", using: :btree
- add_index "notes", ["line_code"], name: "index_notes_on_line_code", using: :btree
- add_index "notes", ["note"], name: "index_notes_on_note_trigram", using: :gin, opclasses: {"note"=>"gin_trgm_ops"}
- add_index "notes", ["noteable_id", "noteable_type"], name: "index_notes_on_noteable_id_and_noteable_type", using: :btree
- add_index "notes", ["noteable_type"], name: "index_notes_on_noteable_type", using: :btree
- add_index "notes", ["project_id", "noteable_type"], name: "index_notes_on_project_id_and_noteable_type", using: :btree
- add_index "notes", ["updated_at"], name: "index_notes_on_updated_at", using: :btree
-
create_table "notification_settings", force: :cascade do |t|
t.integer "user_id", null: false
t.integer "source_id"
@@ -1427,12 +1416,11 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.boolean "success_pipeline"
t.boolean "push_to_merge_request"
t.boolean "issue_due"
+ t.index ["source_id", "source_type"], name: "index_notification_settings_on_source_id_and_source_type", using: :btree
+ t.index ["user_id", "source_id", "source_type"], name: "index_notifications_on_user_id_and_source_id_and_source_type", unique: true, using: :btree
+ t.index ["user_id"], name: "index_notification_settings_on_user_id", using: :btree
end
- add_index "notification_settings", ["source_id", "source_type"], name: "index_notification_settings_on_source_id_and_source_type", using: :btree
- add_index "notification_settings", ["user_id", "source_id", "source_type"], name: "index_notifications_on_user_id_and_source_id_and_source_type", unique: true, using: :btree
- add_index "notification_settings", ["user_id"], name: "index_notification_settings_on_user_id", using: :btree
-
create_table "oauth_access_grants", force: :cascade do |t|
t.integer "resource_owner_id", null: false
t.integer "application_id", null: false
@@ -1442,10 +1430,9 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime "created_at", null: false
t.datetime "revoked_at"
t.string "scopes"
+ t.index ["token"], name: "index_oauth_access_grants_on_token", unique: true, using: :btree
end
- add_index "oauth_access_grants", ["token"], name: "index_oauth_access_grants_on_token", unique: true, using: :btree
-
create_table "oauth_access_tokens", force: :cascade do |t|
t.integer "resource_owner_id"
t.integer "application_id"
@@ -1455,12 +1442,11 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime "revoked_at"
t.datetime "created_at", null: false
t.string "scopes"
+ t.index ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true, using: :btree
+ t.index ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id", using: :btree
+ t.index ["token"], name: "index_oauth_access_tokens_on_token", unique: true, using: :btree
end
- add_index "oauth_access_tokens", ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true, using: :btree
- add_index "oauth_access_tokens", ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id", using: :btree
- add_index "oauth_access_tokens", ["token"], name: "index_oauth_access_tokens_on_token", unique: true, using: :btree
-
create_table "oauth_applications", force: :cascade do |t|
t.string "name", null: false
t.string "uid", null: false
@@ -1472,14 +1458,14 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.integer "owner_id"
t.string "owner_type"
t.boolean "trusted", default: false, null: false
+ t.index ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type", using: :btree
+ t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true, using: :btree
end
- add_index "oauth_applications", ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type", using: :btree
- add_index "oauth_applications", ["uid"], name: "index_oauth_applications_on_uid", unique: true, using: :btree
-
create_table "oauth_openid_requests", force: :cascade do |t|
t.integer "access_grant_id", null: false
t.string "nonce", null: false
+ t.index ["access_grant_id"], name: "index_oauth_openid_requests_on_access_grant_id", using: :btree
end
create_table "pages_domains", force: :cascade do |t|
@@ -1492,17 +1478,16 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime_with_timezone "verified_at"
t.string "verification_code", null: false
t.datetime_with_timezone "enabled_until"
+ t.index ["domain"], name: "index_pages_domains_on_domain", unique: true, using: :btree
+ t.index ["project_id", "enabled_until"], name: "index_pages_domains_on_project_id_and_enabled_until", using: :btree
+ t.index ["project_id"], name: "index_pages_domains_on_project_id", using: :btree
+ t.index ["verified_at", "enabled_until"], name: "index_pages_domains_on_verified_at_and_enabled_until", using: :btree
+ t.index ["verified_at"], name: "index_pages_domains_on_verified_at", using: :btree
end
- add_index "pages_domains", ["domain"], name: "index_pages_domains_on_domain", unique: true, using: :btree
- add_index "pages_domains", ["project_id", "enabled_until"], name: "index_pages_domains_on_project_id_and_enabled_until", using: :btree
- add_index "pages_domains", ["project_id"], name: "index_pages_domains_on_project_id", using: :btree
- add_index "pages_domains", ["verified_at", "enabled_until"], name: "index_pages_domains_on_verified_at_and_enabled_until", using: :btree
- add_index "pages_domains", ["verified_at"], name: "index_pages_domains_on_verified_at", using: :btree
-
create_table "personal_access_tokens", force: :cascade do |t|
t.integer "user_id", null: false
- t.string "token", null: false
+ t.string "token"
t.string "name", null: false
t.boolean "revoked", default: false
t.date "expires_at"
@@ -1510,28 +1495,34 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime "updated_at", null: false
t.string "scopes", default: "--- []\n", null: false
t.boolean "impersonation", default: false, null: false
+ t.string "token_digest"
+ t.index ["token"], name: "index_personal_access_tokens_on_token", unique: true, using: :btree
+ t.index ["token_digest"], name: "index_personal_access_tokens_on_token_digest", unique: true, using: :btree
+ t.index ["user_id"], name: "index_personal_access_tokens_on_user_id", using: :btree
end
- add_index "personal_access_tokens", ["token"], name: "index_personal_access_tokens_on_token", unique: true, using: :btree
- add_index "personal_access_tokens", ["user_id"], name: "index_personal_access_tokens_on_user_id", using: :btree
+ create_table "pool_repositories", id: :bigserial, force: :cascade do |t|
+ t.integer "shard_id", null: false
+ t.string "disk_path"
+ t.index ["disk_path"], name: "index_pool_repositories_on_disk_path", unique: true, using: :btree
+ t.index ["shard_id"], name: "index_pool_repositories_on_shard_id", using: :btree
+ end
create_table "programming_languages", force: :cascade do |t|
t.string "name", null: false
t.string "color", null: false
t.datetime_with_timezone "created_at", null: false
+ t.index ["name"], name: "index_programming_languages_on_name", unique: true, using: :btree
end
- add_index "programming_languages", ["name"], name: "index_programming_languages_on_name", unique: true, using: :btree
-
create_table "project_authorizations", id: false, force: :cascade do |t|
t.integer "user_id", null: false
t.integer "project_id", null: false
t.integer "access_level", null: false
+ t.index ["project_id"], name: "index_project_authorizations_on_project_id", using: :btree
+ t.index ["user_id", "project_id", "access_level"], name: "index_project_authorizations_on_user_id_project_id_access_level", unique: true, using: :btree
end
- add_index "project_authorizations", ["project_id"], name: "index_project_authorizations_on_project_id", using: :btree
- add_index "project_authorizations", ["user_id", "project_id", "access_level"], name: "index_project_authorizations_on_user_id_project_id_access_level", unique: true, using: :btree
-
create_table "project_auto_devops", force: :cascade do |t|
t.integer "project_id", null: false
t.datetime_with_timezone "created_at", null: false
@@ -1539,50 +1530,47 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.boolean "enabled"
t.string "domain"
t.integer "deploy_strategy", default: 0, null: false
+ t.index ["project_id"], name: "index_project_auto_devops_on_project_id", unique: true, using: :btree
end
- add_index "project_auto_devops", ["project_id"], name: "index_project_auto_devops_on_project_id", unique: true, using: :btree
-
create_table "project_ci_cd_settings", force: :cascade do |t|
t.integer "project_id", null: false
t.boolean "group_runners_enabled", default: true, null: false
+ t.index ["project_id"], name: "index_project_ci_cd_settings_on_project_id", unique: true, using: :btree
end
- add_index "project_ci_cd_settings", ["project_id"], name: "index_project_ci_cd_settings_on_project_id", unique: true, using: :btree
-
create_table "project_custom_attributes", force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.integer "project_id", null: false
t.string "key", null: false
t.string "value", null: false
+ t.index ["key", "value"], name: "index_project_custom_attributes_on_key_and_value", using: :btree
+ t.index ["project_id", "key"], name: "index_project_custom_attributes_on_project_id_and_key", unique: true, using: :btree
end
- add_index "project_custom_attributes", ["key", "value"], name: "index_project_custom_attributes_on_key_and_value", using: :btree
- add_index "project_custom_attributes", ["project_id", "key"], name: "index_project_custom_attributes_on_project_id_and_key", unique: true, using: :btree
-
create_table "project_deploy_tokens", force: :cascade do |t|
t.integer "project_id", null: false
t.integer "deploy_token_id", null: false
t.datetime_with_timezone "created_at", null: false
+ t.index ["deploy_token_id"], name: "index_project_deploy_tokens_on_deploy_token_id", using: :btree
+ t.index ["project_id", "deploy_token_id"], name: "index_project_deploy_tokens_on_project_id_and_deploy_token_id", unique: true, using: :btree
end
- add_index "project_deploy_tokens", ["project_id", "deploy_token_id"], name: "index_project_deploy_tokens_on_project_id_and_deploy_token_id", unique: true, using: :btree
-
create_table "project_features", force: :cascade do |t|
t.integer "project_id", null: false
t.integer "merge_requests_access_level"
t.integer "issues_access_level"
t.integer "wiki_access_level"
- t.integer "snippets_access_level"
+ t.integer "snippets_access_level", default: 20, null: false
t.integer "builds_access_level"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "repository_access_level", default: 20, null: false
+ t.integer "pages_access_level", default: 20, null: false
+ t.index ["project_id"], name: "index_project_features_on_project_id", unique: true, using: :btree
end
- add_index "project_features", ["project_id"], name: "index_project_features_on_project_id", unique: true, using: :btree
-
create_table "project_group_links", force: :cascade do |t|
t.integer "project_id", null: false
t.integer "group_id", null: false
@@ -1590,45 +1578,50 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime "updated_at"
t.integer "group_access", default: 30, null: false
t.date "expires_at"
+ t.index ["group_id"], name: "index_project_group_links_on_group_id", using: :btree
+ t.index ["project_id"], name: "index_project_group_links_on_project_id", using: :btree
end
- add_index "project_group_links", ["group_id"], name: "index_project_group_links_on_group_id", using: :btree
- add_index "project_group_links", ["project_id"], name: "index_project_group_links_on_project_id", using: :btree
-
create_table "project_import_data", force: :cascade do |t|
t.integer "project_id"
t.text "data"
t.text "encrypted_credentials"
t.string "encrypted_credentials_iv"
t.string "encrypted_credentials_salt"
+ t.index ["project_id"], name: "index_project_import_data_on_project_id", using: :btree
end
- add_index "project_import_data", ["project_id"], name: "index_project_import_data_on_project_id", using: :btree
-
create_table "project_mirror_data", force: :cascade do |t|
t.integer "project_id", null: false
t.string "status"
t.string "jid"
t.text "last_error"
+ t.index ["jid"], name: "index_project_mirror_data_on_jid", using: :btree
+ t.index ["project_id"], name: "index_project_mirror_data_on_project_id", unique: true, using: :btree
+ t.index ["status"], name: "index_project_mirror_data_on_status", using: :btree
end
- add_index "project_mirror_data", ["jid"], name: "index_project_mirror_data_on_jid", using: :btree
- add_index "project_mirror_data", ["project_id"], name: "index_project_mirror_data_on_project_id", unique: true, using: :btree
- add_index "project_mirror_data", ["status"], name: "index_project_mirror_data_on_status", using: :btree
+ create_table "project_repositories", id: :bigserial, force: :cascade do |t|
+ t.integer "shard_id", null: false
+ t.string "disk_path", null: false
+ t.integer "project_id", null: false
+ t.index ["disk_path"], name: "index_project_repositories_on_disk_path", unique: true, using: :btree
+ t.index ["project_id"], name: "index_project_repositories_on_project_id", unique: true, using: :btree
+ t.index ["shard_id"], name: "index_project_repositories_on_shard_id", using: :btree
+ end
create_table "project_statistics", force: :cascade do |t|
t.integer "project_id", null: false
t.integer "namespace_id", null: false
- t.integer "commit_count", limit: 8, default: 0, null: false
- t.integer "storage_size", limit: 8, default: 0, null: false
- t.integer "repository_size", limit: 8, default: 0, null: false
- t.integer "lfs_objects_size", limit: 8, default: 0, null: false
- t.integer "build_artifacts_size", limit: 8, default: 0, null: false
+ t.bigint "commit_count", default: 0, null: false
+ t.bigint "storage_size", default: 0, null: false
+ t.bigint "repository_size", default: 0, null: false
+ t.bigint "lfs_objects_size", default: 0, null: false
+ t.bigint "build_artifacts_size", default: 0, null: false
+ t.index ["namespace_id"], name: "index_project_statistics_on_namespace_id", using: :btree
+ t.index ["project_id"], name: "index_project_statistics_on_project_id", unique: true, using: :btree
end
- add_index "project_statistics", ["namespace_id"], name: "index_project_statistics_on_namespace_id", using: :btree
- add_index "project_statistics", ["project_id"], name: "index_project_statistics_on_project_id", unique: true, using: :btree
-
create_table "projects", force: :cascade do |t|
t.string "name"
t.string "path"
@@ -1681,28 +1674,29 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.integer "jobs_cache_index"
t.boolean "pages_https_only", default: true
t.boolean "remote_mirror_available_overridden"
+ t.bigint "pool_repository_id"
+ t.index ["ci_id"], name: "index_projects_on_ci_id", using: :btree
+ t.index ["created_at"], name: "index_projects_on_created_at", using: :btree
+ t.index ["creator_id"], name: "index_projects_on_creator_id", using: :btree
+ t.index ["description"], name: "index_projects_on_description_trigram", using: :gin, opclasses: {"description"=>"gin_trgm_ops"}
+ t.index ["id"], name: "index_projects_on_id_partial_for_visibility", unique: true, where: "(visibility_level = ANY (ARRAY[10, 20]))", using: :btree
+ t.index ["last_activity_at"], name: "index_projects_on_last_activity_at", using: :btree
+ t.index ["last_repository_check_at"], name: "index_projects_on_last_repository_check_at", where: "(last_repository_check_at IS NOT NULL)", using: :btree
+ t.index ["last_repository_check_failed"], name: "index_projects_on_last_repository_check_failed", using: :btree
+ t.index ["last_repository_updated_at"], name: "index_projects_on_last_repository_updated_at", using: :btree
+ t.index ["name"], name: "index_projects_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}
+ t.index ["namespace_id"], name: "index_projects_on_namespace_id", using: :btree
+ t.index ["path"], name: "index_projects_on_path", using: :btree
+ t.index ["path"], name: "index_projects_on_path_trigram", using: :gin, opclasses: {"path"=>"gin_trgm_ops"}
+ t.index ["pending_delete"], name: "index_projects_on_pending_delete", using: :btree
+ t.index ["pool_repository_id"], name: "index_projects_on_pool_repository_id", where: "(pool_repository_id IS NOT NULL)", using: :btree
+ t.index ["repository_storage", "created_at"], name: "idx_project_repository_check_partial", where: "(last_repository_check_at IS NULL)", using: :btree
+ t.index ["repository_storage"], name: "index_projects_on_repository_storage", using: :btree
+ t.index ["runners_token"], name: "index_projects_on_runners_token", using: :btree
+ t.index ["star_count"], name: "index_projects_on_star_count", using: :btree
+ t.index ["visibility_level"], name: "index_projects_on_visibility_level", using: :btree
end
- add_index "projects", ["ci_id"], name: "index_projects_on_ci_id", using: :btree
- add_index "projects", ["created_at"], name: "index_projects_on_created_at", using: :btree
- add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree
- add_index "projects", ["description"], name: "index_projects_on_description_trigram", using: :gin, opclasses: {"description"=>"gin_trgm_ops"}
- add_index "projects", ["id"], name: "index_projects_on_id_partial_for_visibility", unique: true, where: "(visibility_level = ANY (ARRAY[10, 20]))", using: :btree
- add_index "projects", ["last_activity_at"], name: "index_projects_on_last_activity_at", using: :btree
- add_index "projects", ["last_repository_check_at"], name: "index_projects_on_last_repository_check_at", where: "(last_repository_check_at IS NOT NULL)", using: :btree
- add_index "projects", ["last_repository_check_failed"], name: "index_projects_on_last_repository_check_failed", using: :btree
- add_index "projects", ["last_repository_updated_at"], name: "index_projects_on_last_repository_updated_at", using: :btree
- add_index "projects", ["name"], name: "index_projects_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}
- add_index "projects", ["namespace_id"], name: "index_projects_on_namespace_id", using: :btree
- add_index "projects", ["path"], name: "index_projects_on_path", using: :btree
- add_index "projects", ["path"], name: "index_projects_on_path_trigram", using: :gin, opclasses: {"path"=>"gin_trgm_ops"}
- add_index "projects", ["pending_delete"], name: "index_projects_on_pending_delete", using: :btree
- add_index "projects", ["repository_storage", "created_at"], name: "idx_project_repository_check_partial", where: "(last_repository_check_at IS NULL)", using: :btree
- add_index "projects", ["repository_storage"], name: "index_projects_on_repository_storage", using: :btree
- add_index "projects", ["runners_token"], name: "index_projects_on_runners_token", using: :btree
- add_index "projects", ["star_count"], name: "index_projects_on_star_count", using: :btree
- add_index "projects", ["visibility_level"], name: "index_projects_on_visibility_level", using: :btree
-
create_table "prometheus_metrics", force: :cascade do |t|
t.integer "project_id"
t.string "title", null: false
@@ -1715,40 +1709,36 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime_with_timezone "updated_at", null: false
t.boolean "common", default: false, null: false
t.string "identifier"
+ t.index ["common"], name: "index_prometheus_metrics_on_common", using: :btree
+ t.index ["group"], name: "index_prometheus_metrics_on_group", using: :btree
+ t.index ["identifier"], name: "index_prometheus_metrics_on_identifier", unique: true, using: :btree
+ t.index ["project_id"], name: "index_prometheus_metrics_on_project_id", using: :btree
end
- add_index "prometheus_metrics", ["common"], name: "index_prometheus_metrics_on_common", using: :btree
- add_index "prometheus_metrics", ["group"], name: "index_prometheus_metrics_on_group", using: :btree
- add_index "prometheus_metrics", ["identifier"], name: "index_prometheus_metrics_on_identifier", unique: true, using: :btree
- add_index "prometheus_metrics", ["project_id"], name: "index_prometheus_metrics_on_project_id", using: :btree
-
create_table "protected_branch_merge_access_levels", force: :cascade do |t|
t.integer "protected_branch_id", null: false
t.integer "access_level", default: 40, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["protected_branch_id"], name: "index_protected_branch_merge_access", using: :btree
end
- add_index "protected_branch_merge_access_levels", ["protected_branch_id"], name: "index_protected_branch_merge_access", using: :btree
-
create_table "protected_branch_push_access_levels", force: :cascade do |t|
t.integer "protected_branch_id", null: false
t.integer "access_level", default: 40, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["protected_branch_id"], name: "index_protected_branch_push_access", using: :btree
end
- add_index "protected_branch_push_access_levels", ["protected_branch_id"], name: "index_protected_branch_push_access", using: :btree
-
create_table "protected_branches", force: :cascade do |t|
t.integer "project_id", null: false
t.string "name", null: false
t.datetime "created_at"
t.datetime "updated_at"
+ t.index ["project_id"], name: "index_protected_branches_on_project_id", using: :btree
end
- add_index "protected_branches", ["project_id"], name: "index_protected_branches_on_project_id", using: :btree
-
create_table "protected_tag_create_access_levels", force: :cascade do |t|
t.integer "protected_tag_id", null: false
t.integer "access_level", default: 40
@@ -1756,23 +1746,22 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.integer "group_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["group_id"], name: "index_protected_tag_create_access_levels_on_group_id", using: :btree
+ t.index ["protected_tag_id"], name: "index_protected_tag_create_access", using: :btree
+ t.index ["user_id"], name: "index_protected_tag_create_access_levels_on_user_id", using: :btree
end
- add_index "protected_tag_create_access_levels", ["protected_tag_id"], name: "index_protected_tag_create_access", using: :btree
- add_index "protected_tag_create_access_levels", ["user_id"], name: "index_protected_tag_create_access_levels_on_user_id", using: :btree
-
create_table "protected_tags", force: :cascade do |t|
t.integer "project_id", null: false
t.string "name", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["project_id", "name"], name: "index_protected_tags_on_project_id_and_name", unique: true, using: :btree
+ t.index ["project_id"], name: "index_protected_tags_on_project_id", using: :btree
end
- add_index "protected_tags", ["project_id", "name"], name: "index_protected_tags_on_project_id_and_name", unique: true, using: :btree
- add_index "protected_tags", ["project_id"], name: "index_protected_tags_on_project_id", using: :btree
-
create_table "push_event_payloads", id: false, force: :cascade do |t|
- t.integer "commit_count", limit: 8, null: false
+ t.bigint "commit_count", null: false
t.integer "event_id", null: false
t.integer "action", limit: 2, null: false
t.integer "ref_type", limit: 2, null: false
@@ -1780,21 +1769,19 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.binary "commit_to"
t.text "ref"
t.string "commit_title", limit: 70
+ t.index ["event_id"], name: "index_push_event_payloads_on_event_id", unique: true, using: :btree
end
- add_index "push_event_payloads", ["event_id"], name: "index_push_event_payloads_on_event_id", unique: true, using: :btree
-
create_table "redirect_routes", force: :cascade do |t|
t.integer "source_id", null: false
t.string "source_type", null: false
t.string "path", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["path"], name: "index_redirect_routes_on_path", unique: true, using: :btree
+ t.index ["source_type", "source_id"], name: "index_redirect_routes_on_source_type_and_source_id", using: :btree
end
- add_index "redirect_routes", ["path"], name: "index_redirect_routes_on_path", unique: true, using: :btree
- add_index "redirect_routes", ["source_type", "source_id"], name: "index_redirect_routes_on_source_type_and_source_id", using: :btree
-
create_table "releases", force: :cascade do |t|
t.string "tag"
t.text "description"
@@ -1803,11 +1790,10 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime "updated_at"
t.text "description_html"
t.integer "cached_markdown_version"
+ t.index ["project_id", "tag"], name: "index_releases_on_project_id_and_tag", using: :btree
+ t.index ["project_id"], name: "index_releases_on_project_id", using: :btree
end
- add_index "releases", ["project_id", "tag"], name: "index_releases_on_project_id_and_tag", using: :btree
- add_index "releases", ["project_id"], name: "index_releases_on_project_id", using: :btree
-
create_table "remote_mirrors", force: :cascade do |t|
t.integer "project_id"
t.string "url"
@@ -1824,19 +1810,17 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "encrypted_credentials_salt"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["last_successful_update_at"], name: "index_remote_mirrors_on_last_successful_update_at", using: :btree
+ t.index ["project_id"], name: "index_remote_mirrors_on_project_id", using: :btree
end
- add_index "remote_mirrors", ["last_successful_update_at"], name: "index_remote_mirrors_on_last_successful_update_at", using: :btree
- add_index "remote_mirrors", ["project_id"], name: "index_remote_mirrors_on_project_id", using: :btree
-
create_table "repository_languages", id: false, force: :cascade do |t|
t.integer "project_id", null: false
t.integer "programming_language_id", null: false
t.float "share", null: false
+ t.index ["project_id", "programming_language_id"], name: "index_repository_languages_on_project_and_languages_id", unique: true, using: :btree
end
- add_index "repository_languages", ["project_id", "programming_language_id"], name: "index_repository_languages_on_project_and_languages_id", unique: true, using: :btree
-
create_table "resource_label_events", id: :bigserial, force: :cascade do |t|
t.integer "action", null: false
t.integer "issue_id"
@@ -1847,13 +1831,12 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.integer "cached_markdown_version"
t.text "reference"
t.text "reference_html"
+ t.index ["issue_id"], name: "index_resource_label_events_on_issue_id", using: :btree
+ t.index ["label_id"], name: "index_resource_label_events_on_label_id", using: :btree
+ t.index ["merge_request_id"], name: "index_resource_label_events_on_merge_request_id", using: :btree
+ t.index ["user_id"], name: "index_resource_label_events_on_user_id", using: :btree
end
- add_index "resource_label_events", ["issue_id"], name: "index_resource_label_events_on_issue_id", using: :btree
- add_index "resource_label_events", ["label_id"], name: "index_resource_label_events_on_label_id", using: :btree
- add_index "resource_label_events", ["merge_request_id"], name: "index_resource_label_events_on_merge_request_id", using: :btree
- add_index "resource_label_events", ["user_id"], name: "index_resource_label_events_on_user_id", using: :btree
-
create_table "routes", force: :cascade do |t|
t.integer "source_id", null: false
t.string "source_type", null: false
@@ -1861,12 +1844,11 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime "created_at"
t.datetime "updated_at"
t.string "name"
+ t.index ["path"], name: "index_routes_on_path", unique: true, using: :btree
+ t.index ["path"], name: "index_routes_on_path_text_pattern_ops", using: :btree, opclasses: {"path"=>"varchar_pattern_ops"}
+ t.index ["source_type", "source_id"], name: "index_routes_on_source_type_and_source_id", unique: true, using: :btree
end
- add_index "routes", ["path"], name: "index_routes_on_path", unique: true, using: :btree
- add_index "routes", ["path"], name: "index_routes_on_path_text_pattern_ops", using: :btree, opclasses: {"path"=>"varchar_pattern_ops"}
- add_index "routes", ["source_type", "source_id"], name: "index_routes_on_source_type_and_source_id", unique: true, using: :btree
-
create_table "sent_notifications", force: :cascade do |t|
t.integer "project_id"
t.integer "noteable_id"
@@ -1878,10 +1860,9 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "note_type"
t.text "position"
t.string "in_reply_to_discussion_id"
+ t.index ["reply_key"], name: "index_sent_notifications_on_reply_key", unique: true, using: :btree
end
- add_index "sent_notifications", ["reply_key"], name: "index_sent_notifications_on_reply_key", unique: true, using: :btree
-
create_table "services", force: :cascade do |t|
t.string "type"
t.string "title"
@@ -1904,14 +1885,13 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.boolean "commit_events", default: true, null: false
t.boolean "job_events", default: false, null: false
t.boolean "confidential_note_events", default: true
+ t.index ["project_id"], name: "index_services_on_project_id", using: :btree
+ t.index ["template"], name: "index_services_on_template", using: :btree
end
- add_index "services", ["project_id"], name: "index_services_on_project_id", using: :btree
- add_index "services", ["template"], name: "index_services_on_template", using: :btree
-
- create_table "site_statistics", force: :cascade do |t|
- t.integer "repositories_count", default: 0, null: false
- t.integer "wikis_count", default: 0, null: false
+ create_table "shards", force: :cascade do |t|
+ t.string "name", null: false
+ t.index ["name"], name: "index_shards_on_name", unique: true, using: :btree
end
create_table "snippets", force: :cascade do |t|
@@ -1929,15 +1909,14 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.integer "cached_markdown_version"
t.text "description"
t.text "description_html"
+ t.index ["author_id"], name: "index_snippets_on_author_id", using: :btree
+ t.index ["file_name"], name: "index_snippets_on_file_name_trigram", using: :gin, opclasses: {"file_name"=>"gin_trgm_ops"}
+ t.index ["project_id"], name: "index_snippets_on_project_id", using: :btree
+ t.index ["title"], name: "index_snippets_on_title_trigram", using: :gin, opclasses: {"title"=>"gin_trgm_ops"}
+ t.index ["updated_at"], name: "index_snippets_on_updated_at", using: :btree
+ t.index ["visibility_level"], name: "index_snippets_on_visibility_level", using: :btree
end
- add_index "snippets", ["author_id"], name: "index_snippets_on_author_id", using: :btree
- add_index "snippets", ["file_name"], name: "index_snippets_on_file_name_trigram", using: :gin, opclasses: {"file_name"=>"gin_trgm_ops"}
- add_index "snippets", ["project_id"], name: "index_snippets_on_project_id", using: :btree
- add_index "snippets", ["title"], name: "index_snippets_on_title_trigram", using: :gin, opclasses: {"title"=>"gin_trgm_ops"}
- add_index "snippets", ["updated_at"], name: "index_snippets_on_updated_at", using: :btree
- add_index "snippets", ["visibility_level"], name: "index_snippets_on_visibility_level", using: :btree
-
create_table "spam_logs", force: :cascade do |t|
t.integer "user_id"
t.string "source_ip"
@@ -1960,20 +1939,19 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime "created_at"
t.datetime "updated_at"
t.integer "project_id"
+ t.index ["project_id"], name: "index_subscriptions_on_project_id", using: :btree
+ t.index ["subscribable_id", "subscribable_type", "user_id", "project_id"], name: "index_subscriptions_on_subscribable_and_user_id_and_project_id", unique: true, using: :btree
end
- add_index "subscriptions", ["subscribable_id", "subscribable_type", "user_id", "project_id"], name: "index_subscriptions_on_subscribable_and_user_id_and_project_id", unique: true, using: :btree
-
create_table "system_note_metadata", force: :cascade do |t|
t.integer "note_id", null: false
t.integer "commit_count"
t.string "action"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["note_id"], name: "index_system_note_metadata_on_note_id", unique: true, using: :btree
end
- add_index "system_note_metadata", ["note_id"], name: "index_system_note_metadata_on_note_id", unique: true, using: :btree
-
create_table "taggings", force: :cascade do |t|
t.integer "tag_id"
t.integer "taggable_id"
@@ -1982,32 +1960,29 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "tagger_type"
t.string "context"
t.datetime "created_at"
+ t.index ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true, using: :btree
+ t.index ["tag_id"], name: "index_taggings_on_tag_id", using: :btree
+ t.index ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree
+ t.index ["taggable_id", "taggable_type"], name: "index_taggings_on_taggable_id_and_taggable_type", using: :btree
end
- add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true, using: :btree
- add_index "taggings", ["tag_id"], name: "index_taggings_on_tag_id", using: :btree
- add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree
- add_index "taggings", ["taggable_id", "taggable_type"], name: "index_taggings_on_taggable_id_and_taggable_type", using: :btree
-
create_table "tags", force: :cascade do |t|
t.string "name"
t.integer "taggings_count", default: 0
+ t.index ["name"], name: "index_tags_on_name", unique: true, using: :btree
end
- add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree
-
create_table "term_agreements", force: :cascade do |t|
t.integer "term_id", null: false
t.integer "user_id", null: false
t.boolean "accepted", default: false, null: false
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
+ t.index ["term_id"], name: "index_term_agreements_on_term_id", using: :btree
+ t.index ["user_id", "term_id"], name: "term_agreements_unique_index", unique: true, using: :btree
+ t.index ["user_id"], name: "index_term_agreements_on_user_id", using: :btree
end
- add_index "term_agreements", ["term_id"], name: "index_term_agreements_on_term_id", using: :btree
- add_index "term_agreements", ["user_id", "term_id"], name: "term_agreements_unique_index", unique: true, using: :btree
- add_index "term_agreements", ["user_id"], name: "index_term_agreements_on_user_id", using: :btree
-
create_table "timelogs", force: :cascade do |t|
t.integer "time_spent", null: false
t.integer "user_id"
@@ -2016,12 +1991,11 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.integer "issue_id"
t.integer "merge_request_id"
t.datetime_with_timezone "spent_at"
+ t.index ["issue_id"], name: "index_timelogs_on_issue_id", using: :btree
+ t.index ["merge_request_id"], name: "index_timelogs_on_merge_request_id", using: :btree
+ t.index ["user_id"], name: "index_timelogs_on_user_id", using: :btree
end
- add_index "timelogs", ["issue_id"], name: "index_timelogs_on_issue_id", using: :btree
- add_index "timelogs", ["merge_request_id"], name: "index_timelogs_on_merge_request_id", using: :btree
- add_index "timelogs", ["user_id"], name: "index_timelogs_on_user_id", using: :btree
-
create_table "todos", force: :cascade do |t|
t.integer "user_id", null: false
t.integer "project_id"
@@ -2035,24 +2009,22 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.integer "note_id"
t.string "commit_id"
t.integer "group_id"
+ t.index ["author_id"], name: "index_todos_on_author_id", using: :btree
+ t.index ["commit_id"], name: "index_todos_on_commit_id", using: :btree
+ t.index ["group_id"], name: "index_todos_on_group_id", using: :btree
+ t.index ["note_id"], name: "index_todos_on_note_id", using: :btree
+ t.index ["project_id"], name: "index_todos_on_project_id", using: :btree
+ t.index ["target_type", "target_id"], name: "index_todos_on_target_type_and_target_id", using: :btree
+ t.index ["user_id", "id"], name: "index_todos_on_user_id_and_id_done", where: "((state)::text = 'done'::text)", using: :btree
+ t.index ["user_id", "id"], name: "index_todos_on_user_id_and_id_pending", where: "((state)::text = 'pending'::text)", using: :btree
+ t.index ["user_id"], name: "index_todos_on_user_id", using: :btree
end
- add_index "todos", ["author_id"], name: "index_todos_on_author_id", using: :btree
- add_index "todos", ["commit_id"], name: "index_todos_on_commit_id", using: :btree
- add_index "todos", ["group_id"], name: "index_todos_on_group_id", using: :btree
- add_index "todos", ["note_id"], name: "index_todos_on_note_id", using: :btree
- add_index "todos", ["project_id"], name: "index_todos_on_project_id", using: :btree
- add_index "todos", ["target_type", "target_id"], name: "index_todos_on_target_type_and_target_id", using: :btree
- add_index "todos", ["user_id", "id"], name: "index_todos_on_user_id_and_id_done", where: "((state)::text = 'done'::text)", using: :btree
- add_index "todos", ["user_id", "id"], name: "index_todos_on_user_id_and_id_pending", where: "((state)::text = 'pending'::text)", using: :btree
- add_index "todos", ["user_id"], name: "index_todos_on_user_id", using: :btree
-
create_table "trending_projects", force: :cascade do |t|
t.integer "project_id", null: false
+ t.index ["project_id"], name: "index_trending_projects_on_project_id", unique: true, using: :btree
end
- add_index "trending_projects", ["project_id"], name: "index_trending_projects_on_project_id", unique: true, using: :btree
-
create_table "u2f_registrations", force: :cascade do |t|
t.text "certificate"
t.string "key_handle"
@@ -2062,13 +2034,12 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
+ t.index ["key_handle"], name: "index_u2f_registrations_on_key_handle", using: :btree
+ t.index ["user_id"], name: "index_u2f_registrations_on_user_id", using: :btree
end
- add_index "u2f_registrations", ["key_handle"], name: "index_u2f_registrations_on_key_handle", using: :btree
- add_index "u2f_registrations", ["user_id"], name: "index_u2f_registrations_on_user_id", using: :btree
-
create_table "uploads", force: :cascade do |t|
- t.integer "size", limit: 8, null: false
+ t.bigint "size", null: false
t.string "path", limit: 511, null: false
t.string "checksum", limit: 64
t.integer "model_id"
@@ -2078,12 +2049,12 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "mount_point"
t.string "secret"
t.integer "store"
+ t.index ["checksum"], name: "index_uploads_on_checksum", using: :btree
+ t.index ["model_id", "model_type"], name: "index_uploads_on_model_id_and_model_type", using: :btree
+ t.index ["store"], name: "index_uploads_on_store", using: :btree
+ t.index ["uploader", "path"], name: "index_uploads_on_uploader_and_path", using: :btree
end
- add_index "uploads", ["checksum"], name: "index_uploads_on_checksum", using: :btree
- add_index "uploads", ["model_id", "model_type"], name: "index_uploads_on_model_id_and_model_type", using: :btree
- add_index "uploads", ["uploader", "path"], name: "index_uploads_on_uploader_and_path", using: :btree
-
create_table "user_agent_details", force: :cascade do |t|
t.string "user_agent", null: false
t.string "ip_address", null: false
@@ -2092,42 +2063,48 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.boolean "submitted", default: false, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["subject_id", "subject_type"], name: "index_user_agent_details_on_subject_id_and_subject_type", using: :btree
end
- add_index "user_agent_details", ["subject_id", "subject_type"], name: "index_user_agent_details_on_subject_id_and_subject_type", using: :btree
-
create_table "user_callouts", force: :cascade do |t|
t.integer "feature_name", null: false
t.integer "user_id", null: false
+ t.index ["user_id", "feature_name"], name: "index_user_callouts_on_user_id_and_feature_name", unique: true, using: :btree
+ t.index ["user_id"], name: "index_user_callouts_on_user_id", using: :btree
end
- add_index "user_callouts", ["user_id", "feature_name"], name: "index_user_callouts_on_user_id_and_feature_name", unique: true, using: :btree
- add_index "user_callouts", ["user_id"], name: "index_user_callouts_on_user_id", using: :btree
-
create_table "user_custom_attributes", force: :cascade do |t|
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.integer "user_id", null: false
t.string "key", null: false
t.string "value", null: false
+ t.index ["key", "value"], name: "index_user_custom_attributes_on_key_and_value", using: :btree
+ t.index ["user_id", "key"], name: "index_user_custom_attributes_on_user_id_and_key", unique: true, using: :btree
end
- add_index "user_custom_attributes", ["key", "value"], name: "index_user_custom_attributes_on_key_and_value", using: :btree
- add_index "user_custom_attributes", ["user_id", "key"], name: "index_user_custom_attributes_on_user_id_and_key", unique: true, using: :btree
-
create_table "user_interacted_projects", id: false, force: :cascade do |t|
t.integer "user_id", null: false
t.integer "project_id", null: false
+ t.index ["project_id", "user_id"], name: "index_user_interacted_projects_on_project_id_and_user_id", unique: true, using: :btree
+ t.index ["user_id"], name: "index_user_interacted_projects_on_user_id", using: :btree
end
- add_index "user_interacted_projects", ["project_id", "user_id"], name: "index_user_interacted_projects_on_project_id_and_user_id", unique: true, using: :btree
- add_index "user_interacted_projects", ["user_id"], name: "index_user_interacted_projects_on_user_id", using: :btree
+ create_table "user_preferences", force: :cascade do |t|
+ t.integer "user_id", null: false
+ t.integer "issue_notes_filter", limit: 2, default: 0, null: false
+ t.integer "merge_request_notes_filter", limit: 2, default: 0, null: false
+ t.datetime_with_timezone "created_at", null: false
+ t.datetime_with_timezone "updated_at", null: false
+ t.index ["user_id"], name: "index_user_preferences_on_user_id", unique: true, using: :btree
+ end
create_table "user_statuses", primary_key: "user_id", force: :cascade do |t|
t.integer "cached_markdown_version"
t.string "emoji", default: "speech_balloon", null: false
t.string "message", limit: 100
t.string "message_html"
+ t.index ["user_id"], name: "index_user_statuses_on_user_id", using: :btree
end
create_table "user_synced_attributes_metadata", force: :cascade do |t|
@@ -2136,10 +2113,9 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.boolean "location_synced", default: false
t.integer "user_id", null: false
t.string "provider"
+ t.index ["user_id"], name: "index_user_synced_attributes_metadata_on_user_id", unique: true, using: :btree
end
- add_index "user_synced_attributes_metadata", ["user_id"], name: "index_user_synced_attributes_metadata_on_user_id", unique: true, using: :btree
-
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
@@ -2209,33 +2185,32 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.boolean "private_profile"
t.boolean "include_private_contributions"
t.string "commit_email"
+ t.index ["accepted_term_id"], name: "index_users_on_accepted_term_id", using: :btree
+ t.index ["admin"], name: "index_users_on_admin", using: :btree
+ t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree
+ t.index ["created_at"], name: "index_users_on_created_at", using: :btree
+ t.index ["email"], name: "index_users_on_email", unique: true, using: :btree
+ t.index ["email"], name: "index_users_on_email_trigram", using: :gin, opclasses: {"email"=>"gin_trgm_ops"}
+ t.index ["feed_token"], name: "index_users_on_feed_token", using: :btree
+ t.index ["ghost"], name: "index_users_on_ghost", using: :btree
+ t.index ["incoming_email_token"], name: "index_users_on_incoming_email_token", using: :btree
+ t.index ["name"], name: "index_users_on_name", using: :btree
+ t.index ["name"], name: "index_users_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}
+ t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
+ t.index ["state"], name: "index_users_on_state", using: :btree
+ t.index ["username"], name: "index_users_on_username", using: :btree
+ t.index ["username"], name: "index_users_on_username_trigram", using: :gin, opclasses: {"username"=>"gin_trgm_ops"}
end
- add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
- add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree
- add_index "users", ["created_at"], name: "index_users_on_created_at", using: :btree
- add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
- add_index "users", ["email"], name: "index_users_on_email_trigram", using: :gin, opclasses: {"email"=>"gin_trgm_ops"}
- add_index "users", ["feed_token"], name: "index_users_on_feed_token", using: :btree
- add_index "users", ["ghost"], name: "index_users_on_ghost", using: :btree
- add_index "users", ["incoming_email_token"], name: "index_users_on_incoming_email_token", using: :btree
- add_index "users", ["name"], name: "index_users_on_name", using: :btree
- add_index "users", ["name"], name: "index_users_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}
- add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
- add_index "users", ["state"], name: "index_users_on_state", using: :btree
- add_index "users", ["username"], name: "index_users_on_username", using: :btree
- add_index "users", ["username"], name: "index_users_on_username_trigram", using: :gin, opclasses: {"username"=>"gin_trgm_ops"}
-
create_table "users_star_projects", force: :cascade do |t|
t.integer "project_id", null: false
t.integer "user_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
+ t.index ["project_id"], name: "index_users_star_projects_on_project_id", using: :btree
+ t.index ["user_id", "project_id"], name: "index_users_star_projects_on_user_id_and_project_id", unique: true, using: :btree
end
- add_index "users_star_projects", ["project_id"], name: "index_users_star_projects_on_project_id", using: :btree
- add_index "users_star_projects", ["user_id", "project_id"], name: "index_users_star_projects_on_user_id_and_project_id", unique: true, using: :btree
-
create_table "web_hook_logs", force: :cascade do |t|
t.integer "web_hook_id", null: false
t.string "trigger"
@@ -2249,13 +2224,11 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.string "internal_error_message"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.index ["created_at", "web_hook_id"], name: "index_web_hook_logs_on_created_at_and_web_hook_id", using: :btree
+ t.index ["web_hook_id"], name: "index_web_hook_logs_on_web_hook_id", using: :btree
end
- add_index "web_hook_logs", ["created_at", "web_hook_id"], name: "index_web_hook_logs_on_created_at_and_web_hook_id", using: :btree
- add_index "web_hook_logs", ["web_hook_id"], name: "index_web_hook_logs_on_web_hook_id", using: :btree
-
create_table "web_hooks", force: :cascade do |t|
- t.string "url", limit: 2000
t.integer "project_id"
t.datetime "created_at"
t.datetime "updated_at"
@@ -2268,21 +2241,29 @@ ActiveRecord::Schema.define(version: 20180907015926) do
t.boolean "note_events", default: false, null: false
t.boolean "enable_ssl_verification", default: true
t.boolean "wiki_page_events", default: false, null: false
- t.string "token"
t.boolean "pipeline_events", default: false, null: false
t.boolean "confidential_issues_events", default: false, null: false
t.boolean "repository_update_events", default: false, null: false
t.boolean "job_events", default: false, null: false
t.boolean "confidential_note_events"
t.text "push_events_branch_filter"
+ t.string "encrypted_token"
+ t.string "encrypted_token_iv"
+ t.string "encrypted_url"
+ t.string "encrypted_url_iv"
+ t.index ["project_id"], name: "index_web_hooks_on_project_id", using: :btree
+ t.index ["type"], name: "index_web_hooks_on_type", using: :btree
end
- add_index "web_hooks", ["project_id"], name: "index_web_hooks_on_project_id", using: :btree
- add_index "web_hooks", ["type"], name: "index_web_hooks_on_type", using: :btree
-
add_foreign_key "application_settings", "users", column: "usage_stats_set_by_user_id", name: "fk_964370041d", on_delete: :nullify
add_foreign_key "badges", "namespaces", column: "group_id", on_delete: :cascade
add_foreign_key "badges", "projects", on_delete: :cascade
+ add_foreign_key "board_group_recent_visits", "boards", on_delete: :cascade
+ add_foreign_key "board_group_recent_visits", "namespaces", column: "group_id", on_delete: :cascade
+ add_foreign_key "board_group_recent_visits", "users", on_delete: :cascade
+ add_foreign_key "board_project_recent_visits", "boards", on_delete: :cascade
+ add_foreign_key "board_project_recent_visits", "projects", on_delete: :cascade
+ add_foreign_key "board_project_recent_visits", "users", on_delete: :cascade
add_foreign_key "boards", "namespaces", column: "group_id", on_delete: :cascade
add_foreign_key "boards", "projects", name: "fk_f15266b5f9", on_delete: :cascade
add_foreign_key "chat_teams", "namespaces", on_delete: :cascade
@@ -2317,18 +2298,25 @@ ActiveRecord::Schema.define(version: 20180907015926) do
add_foreign_key "ci_triggers", "projects", name: "fk_e3e63f966e", on_delete: :cascade
add_foreign_key "ci_triggers", "users", column: "owner_id", name: "fk_e8e10d1964", on_delete: :cascade
add_foreign_key "ci_variables", "projects", name: "fk_ada5eb64b3", on_delete: :cascade
+ add_foreign_key "cluster_groups", "clusters", on_delete: :cascade
+ add_foreign_key "cluster_groups", "namespaces", column: "group_id", on_delete: :cascade
add_foreign_key "cluster_platforms_kubernetes", "clusters", on_delete: :cascade
add_foreign_key "cluster_projects", "clusters", on_delete: :cascade
add_foreign_key "cluster_projects", "projects", on_delete: :cascade
add_foreign_key "cluster_providers_gcp", "clusters", on_delete: :cascade
add_foreign_key "clusters", "users", on_delete: :nullify
+ add_foreign_key "clusters_applications_cert_managers", "clusters", on_delete: :cascade
add_foreign_key "clusters_applications_helm", "clusters", on_delete: :cascade
add_foreign_key "clusters_applications_ingress", "clusters", name: "fk_753a7b41c1", on_delete: :cascade
add_foreign_key "clusters_applications_jupyter", "clusters", on_delete: :cascade
add_foreign_key "clusters_applications_jupyter", "oauth_applications", on_delete: :nullify
+ add_foreign_key "clusters_applications_knative", "clusters", on_delete: :cascade
add_foreign_key "clusters_applications_prometheus", "clusters", name: "fk_557e773639", on_delete: :cascade
add_foreign_key "clusters_applications_runners", "ci_runners", column: "runner_id", name: "fk_02de2ded36", on_delete: :nullify
add_foreign_key "clusters_applications_runners", "clusters", on_delete: :cascade
+ add_foreign_key "clusters_kubernetes_namespaces", "cluster_projects", on_delete: :nullify
+ add_foreign_key "clusters_kubernetes_namespaces", "clusters", on_delete: :cascade
+ add_foreign_key "clusters_kubernetes_namespaces", "projects", on_delete: :nullify
add_foreign_key "container_repositories", "projects"
add_foreign_key "deploy_keys_projects", "projects", name: "fk_58a901ca7e", on_delete: :cascade
add_foreign_key "deployments", "projects", name: "fk_b9a3851b82", on_delete: :cascade
@@ -2340,9 +2328,6 @@ ActiveRecord::Schema.define(version: 20180907015926) do
add_foreign_key "fork_network_members", "projects", on_delete: :cascade
add_foreign_key "fork_networks", "projects", column: "root_project_id", name: "fk_e7b436b2b5", on_delete: :nullify
add_foreign_key "forked_project_links", "projects", column: "forked_to_project_id", name: "fk_434510edb0", on_delete: :cascade
- add_foreign_key "gcp_clusters", "projects", on_delete: :cascade
- add_foreign_key "gcp_clusters", "services", on_delete: :nullify
- add_foreign_key "gcp_clusters", "users", on_delete: :nullify
add_foreign_key "gpg_key_subkeys", "gpg_keys", on_delete: :cascade
add_foreign_key "gpg_keys", "users", on_delete: :cascade
add_foreign_key "gpg_signatures", "gpg_key_subkeys", on_delete: :nullify
@@ -2397,6 +2382,7 @@ ActiveRecord::Schema.define(version: 20180907015926) do
add_foreign_key "oauth_openid_requests", "oauth_access_grants", column: "access_grant_id", name: "fk_oauth_openid_requests_oauth_access_grants_access_grant_id"
add_foreign_key "pages_domains", "projects", name: "fk_ea2f6dfc6f", on_delete: :cascade
add_foreign_key "personal_access_tokens", "users"
+ add_foreign_key "pool_repositories", "shards", on_delete: :restrict
add_foreign_key "project_authorizations", "projects", on_delete: :cascade
add_foreign_key "project_authorizations", "users", on_delete: :cascade
add_foreign_key "project_auto_devops", "projects", on_delete: :cascade
@@ -2408,7 +2394,10 @@ ActiveRecord::Schema.define(version: 20180907015926) do
add_foreign_key "project_group_links", "projects", name: "fk_daa8cee94c", on_delete: :cascade
add_foreign_key "project_import_data", "projects", name: "fk_ffb9ee3a10", on_delete: :cascade
add_foreign_key "project_mirror_data", "projects", on_delete: :cascade
+ add_foreign_key "project_repositories", "projects", on_delete: :cascade
+ add_foreign_key "project_repositories", "shards", on_delete: :restrict
add_foreign_key "project_statistics", "projects", on_delete: :cascade
+ add_foreign_key "projects", "pool_repositories", name: "fk_6e5c14658a", on_delete: :nullify
add_foreign_key "prometheus_metrics", "projects", on_delete: :cascade
add_foreign_key "protected_branch_merge_access_levels", "protected_branches", name: "fk_8a3072ccb3", on_delete: :cascade
add_foreign_key "protected_branch_push_access_levels", "protected_branches", name: "fk_9ffc86a3d9", on_delete: :cascade
@@ -2444,6 +2433,7 @@ ActiveRecord::Schema.define(version: 20180907015926) do
add_foreign_key "user_custom_attributes", "users", on_delete: :cascade
add_foreign_key "user_interacted_projects", "projects", name: "fk_722ceba4f7", on_delete: :cascade
add_foreign_key "user_interacted_projects", "users", name: "fk_0894651f08", on_delete: :cascade
+ add_foreign_key "user_preferences", "users", on_delete: :cascade
add_foreign_key "user_statuses", "users", on_delete: :cascade
add_foreign_key "user_synced_attributes_metadata", "users", on_delete: :cascade
add_foreign_key "users", "application_setting_terms", column: "accepted_term_id", name: "fk_789cd90b35", on_delete: :cascade
diff --git a/doc/README.md b/doc/README.md
index 4248f62c08c..b15c3a63d92 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -3,137 +3,227 @@ comments: false
description: 'Learn how to use and administer GitLab, the most scalable Git-based fully integrated platform for software development.'
---
+<div class="display-none">
+ <em>Visit <a href="https://docs.gitlab.com/ce/">docs.gitlab.com</a> for optimized
+ navigation, discoverability, and readability.</em>
+</div>
+<!-- the div above will not display on the docs site but will display on /help -->
+
# GitLab Documentation
-Welcome to [GitLab](https://about.gitlab.com/), a Git-based fully featured
-platform for software development!
+Welcome to [GitLab](https://about.gitlab.com/) Documentation.
+
+Here you can access the complete documentation for GitLab, the single application for the
+[entire DevOps lifecycle](#the-entire-devops-lifecycle).
+
+## Overview
+
+No matter how you use GitLab, we have documentation for you.
+
+| Essential Documentation | Essential Documentation |
+|:-------------------------------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------|
+| [**User Documentation**](user/index.md)<br/>Discover features and concepts for GitLab users. | [**Administrator documentation**](administration/index.md)<br/>Everything GitLab self-managed administrators need to know. |
+| [**Contributing to GitLab**](#contributing-to-gitlab)<br/>At GitLab, everyone can contribute! | [**New to Git and GitLab?**](#new-to-git-and-gitlab)<br/>We have resources to get you started. |
+| [**Building an integration with GitLab?**](#building-an-integration-with-gitlab)<br/>Consult our automation and integration documentation. | [**Coming to GitLab from another platform?**](#coming-to-gitlab-from-another-platform)<br/>Consult our handy guides. |
+| [**Install GitLab**](https://about.gitlab.com/install/)<br/>Installation options for different platforms. | [**Subscribe to GitLab**](#subscribe-to-gitlab)<br/>Get access to more features. |
+| [**Update GitLab**](update/README.md)<br/>Update your GitLab self-managed instance to the latest version. | [**GitLab Releases**](https://about.gitlab.com/releases/)<br/>What's new in GitLab. |
-GitLab offers the most scalable Git-based fully integrated platform for
-software development, with flexible products and subscriptions.
-To understand what features you have access to, check the [GitLab subscriptions](#gitlab-subscriptions) below.
+## Popular Documentation
-**Shortcuts to GitLab's most visited docs:**
+Have a look at some of our most popular documentation resources:
-| General documentation | GitLab CI/CD docs |
-| :----- | :----- |
-| [User documentation](user/index.md) | [GitLab CI/CD quick start guide](ci/quick_start/README.md) |
-| [Administrator documentation](administration/index.md) | [GitLab CI/CD examples](ci/examples/README.md) |
-| [Contributor documentation](#contributor-documentation) | [Configuring `.gitlab-ci.yml`](ci/yaml/README.md) |
-| [Getting started with GitLab](#getting-started-with-gitlab) | [Using Docker images](ci/docker/using_docker_images.md) |
-| [API](api/README.md) | [Auto DevOps](topics/autodevops/index.md) |
-| [SSH authentication](ssh/README.md) | [Kubernetes integration](user/project/clusters/index.md)|
-| [GitLab Pages](user/project/pages/index.md) | [GitLab Container Registry](user/project/container_registry.md) |
+| Popular Topic | Description |
+|:----------------------------------------------------------------|:-----------------------------------------------------------------|
+| [Configuring `.gitlab-ci.yml`](ci/yaml/README.md) | Complete syntax documentation for configuring your CI pipelines. |
+| [GitLab CI/CD examples](ci/examples/README.md) | Get up to speed quickly with common CI/CD scenarios. |
+| [GitLab Container Registry](user/project/container_registry.md) | Host containers within GitLab. |
+| [GitLab Pages](user/project/pages/index.md) | Host static websites for your projects with GitLab. |
+| [Kubernetes integration](user/project/clusters/index.md) | Use GitLab with Kubernetes. |
+| [SSH authentication](ssh/README.md) | Secure your network communications. |
+| [Using Docker images](ci/docker/using_docker_images.md) | Build and test your applications with Docker. |
-## Complete DevOps with GitLab
+## The entire DevOps Lifecycle
GitLab is the first single application for software development, security,
-and operations that enables Concurrent DevOps, making the software lifecycle
-three times faster and radically improving the speed of business. GitLab
-provides solutions for all the stages of the DevOps lifecycle:
-[plan](#plan), [create](#create), [verify](#verify), [package](#package),
-[release](#release), [configure](#configure), [monitor](#monitor).
+and operations that enables [Concurrent DevOps](https://about.gitlab.com/concurrent-devops/),
+making the software lifecycle faster and radically improving the speed of business.
-![DevOps Lifecycle](img/devops_lifecycle.png)
+GitLab provides solutions for [all the stages of the DevOps lifecycle](https://about.gitlab.com/stages-devops-lifecycle/):
-### Plan
+![DevOps Stages](img/devops-stages.png)
-Whether you use Waterfall, Agile, or Conversational Development,
-GitLab streamlines your collaborative workflows. Visualize, prioritize,
-coordinate, and track your progress your way with GitLab’s flexible project
-management tools.
+The following sections provide links to documentation for each DevOps stage:
+
+| DevOps Stage | Documentation for |
+|:------------------------|:------------------------------------------------------------|
+| [Manage](#manage) | Statistics and analytics features. |
+| [Plan](#plan) | Project planning and management features. |
+| [Create](#create) | Source code and data creation and management features. |
+| [Verify](#verify) | Testing, code quality, and continuous integration features. |
+| [Package](#package) | Docker container registry. |
+| [Release](#release) | Application release and delivery features. |
+| [Configure](#configure) | Application and infrastructure configuration tools. |
+| [Monitor](#monitor) | Application monitoring and metrics features. |
+| [Secure](#secure) | Security capability features. |
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
-- Chat operations
- - [Mattermost slash commands](user/project/integrations/mattermost_slash_commands.md)
- - [Slack slash commands](user/project/integrations/slack_slash_commands.md)
-- [Discussions](user/discussions/index.md): Threads, comments, and resolvable discussions in issues, commits, and merge requests.
-- [Issues](user/project/issues/index.md)
-- [Project Issue Board](user/project/issue_board.md)
-- [Issues and merge requests templates](user/project/description_templates.md): Create templates for submitting new issues and merge requests.
-- [Labels](user/project/labels.md): Categorize your issues or merge requests based on descriptive titles.
-- [Milestones](user/project/milestones/index.md): Organize issues and merge requests into a cohesive group, optionally setting a due date.
-- [Todos](workflow/todos.md): A chronological list of to-dos that are waiting for your input, all in a simple dashboard.
-- [GitLab Quick Actions](user/project/quick_actions.md): Textual shortcuts for common actions on issues or merge requests that are usually done by clicking buttons or dropdowns in GitLab's UI.
+### Manage
-#### Migrate and import your projects from other platforms
+GitLab provides statistics and insight into ways you can maximize the value of GitLab in your organization.
-- [Importing to GitLab](user/project/import/index.md): Import your projects from GitHub, Bitbucket, GitLab.com, FogBugz and SVN into GitLab.
-- [Migrating from SVN](workflow/importing/migrating_from_svn.md): Convert a SVN repository to Git and GitLab.
+The following documentation relates to the DevOps **Manage** stage:
+
+| Manage Topics | Description |
+|:--------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| [Authentication and<br/>Authorization](administration/auth/README.md) **[CORE ONLY]** | Supported authentication and authorization providers. |
+| [GitLab Cycle Analytics](user/project/cycle_analytics.md) | Measure the time it takes to go from an [idea to production](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#from-idea-to-production-with-gitlab) for each project you have. |
+| [Instance Statistics](user/instance_statistics/index.md) | Discover statistics on how many GitLab features you use and user activity. |
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+### Plan
+
+Whether you use Waterfall, Agile, or Conversational Development, GitLab streamlines your collaborative workflows.
+
+Visualize, prioritize, coordinate, and track your progress your way with GitLab’s flexible project
+management tools.
+
+The following documentation relates to the DevOps **Plan** stage:
+
+| Plan Topics | Description |
+|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------|
+| [Discussions](user/discussions/index.md) | Threads, comments, and resolvable discussions in issues, commits, and merge requests. |
+| [Due Dates](user/project/issues/due_dates.md) | Keep track of issue deadlines. |
+| [Quick Actions](user/project/quick_actions.md) | Shortcuts for common actions on issues or merge requests, replacing the need to click buttons or use dropdowns in GitLab's UI. |
+| [Issues](user/project/issues/index.md), including [confidential issues](user/project/issues/confidential_issues.md),<br/>[issue and merge request templates](user/project/description_templates.md),<br/>and [moving issues](user/project/issues/moving_issues.md) | Project issues, restricting access to issues, create templates for submitting new issues and merge requests, and moving issues between projects. |
+| [Labels](user/project/labels.md) | Categorize issues or merge requests with descriptive labels. |
+| [Milestones](user/project/milestones/index.md) | Set milestones for delivery of issues and merge requests, with optional due date. |
+| [Project Issue Board](user/project/issue_board.md) | Display issues on a Scrum or Kanban board. |
+| [Time Tracking](workflow/time_tracking.md) | Track time spent on issues and merge requests. |
+| [Todos](workflow/todos.md) | Keep track of work requiring attention with a chronological list displayed on a simple dashboard. |
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
### Create
-Consolidate source code into a single [DVCS](https://en.wikipedia.org/wiki/Distributed_version_control)
+Consolidate source code into a single [distributed version control system](https://en.wikipedia.org/wiki/Distributed_version_control)
that’s easily managed and controlled without disrupting your workflow.
-GitLab’s git repositories come complete with branching tools and access
+
+GitLab’s Git repositories come complete with branching tools and access
controls, providing a scalable, single source of truth for collaborating
on projects and code.
-#### Projects and groups
-
-- [Projects](user/project/index.md):
- - [Project settings](user/project/settings/index.md)
- - [Create a project](gitlab-basics/create-project.md)
- - [Fork a project](gitlab-basics/fork-project.md)
- - [Importing and exporting projects between instances](user/project/settings/import_export.md).
- - [Project access](public_access/public_access.md): Setting up your project's visibility to public, internal, or private.
- - [GitLab Pages](user/project/pages/index.md): Build, test, and deploy your static website with GitLab Pages.
-- [Groups](user/group/index.md): Organize your projects in groups.
- - [Subgroups](user/group/subgroups/index.md)
-- [Search through GitLab](user/search/index.md): Search for issues, merge requests, projects, groups, todos, and issues in Issue Boards.
-- [Snippets](user/snippets.md): Snippets allow you to create little bits of code.
-- [Wikis](user/project/wiki/index.md): Enhance your repository documentation with built-in wikis.
-- [Web IDE](user/project/web_ide/index.md)
+The following documentation relates to the DevOps **Create** stage:
-#### Repositories
-
-Manage your [repositories](user/project/repository/index.md) from the UI (user interface):
-
-- [Files](user/project/repository/index.md#files)
- - [Create a file](user/project/repository/web_editor.md#create-a-file)
- - [Upload a file](user/project/repository/web_editor.md#upload-a-file)
- - [File templates](user/project/repository/web_editor.md#template-dropdowns)
- - [Jupyter Notebook files](user/project/repository/index.md#jupyter-notebook-files)
- - [Create a directory](user/project/repository/web_editor.md#create-a-directory)
- - [Start a merge request](user/project/repository/web_editor.md#tips) (when committing via UI)
-- [Branches](user/project/repository/branches/index.md)
- - [Default branch](user/project/repository/branches/index.md#default-branch)
- - [Create a branch](user/project/repository/web_editor.md#create-a-new-branch)
- - [Protected branches](user/project/protected_branches.md#protected-branches)
- - [Delete merged branches](user/project/repository/branches/index.md#delete-merged-branches)
-- [Commits](user/project/repository/index.md#commits)
- - [Signing commits](user/project/repository/gpg_signed_commits/index.md): use GPG to sign your commits.
+#### Projects and Groups
-#### Merge Requests
+| Create Topics - Projects and Groups | Description |
+|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------|
+| [Create](gitlab-basics/create-project.md) and [fork](gitlab-basics/fork-project.md) projects, and<br/>[import and export<br/>projects between instances](user/project/settings/import_export.md) | Create, duplicate, and move projects. |
+| [GitLab Pages](user/project/pages/index.md) | Build, test, and deploy your static website with GitLab Pages. |
+| [Groups](user/group/index.md) and [Subgroups](user/group/subgroups/index.md) | Organize your projects in groups. |
+| [Projects](user/project/index.md), including [project access](public_access/public_access.md)<br/>and [settings](user/project/settings/index.md) | Host source code, and control your project's visibility and set configuration. |
+| [Search through GitLab](user/search/index.md) | Search for issues, merge requests, projects, groups, and todos. |
+| [Snippets](user/snippets.md) | Snippets allow you to create little bits of code. |
+| [Web IDE](user/project/web_ide/index.md) | Edit files within GitLab's user interface. |
+| [Wikis](user/project/wiki/index.md) | Enhance your repository documentation with built-in wikis. |
-- [Merge Requests](user/project/merge_requests/index.md)
- - [Work In Progress "WIP" Merge Requests](user/project/merge_requests/work_in_progress_merge_requests.md)
- - [Merge Request discussion resolution](user/discussions/index.md#moving-a-single-discussion-to-a-new-issue): Resolve discussions, move discussions in a merge request to an issue, only allow merge requests to be merged if all discussions are resolved.
- - [Checkout merge requests locally](user/project/merge_requests/index.md#checkout-merge-requests-locally)
- - [Cherry-pick](user/project/merge_requests/cherry_pick_changes.md)
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
-#### Integrations
+#### Repositories
-- [Project Services](user/project/integrations/project_services.md): Integrate a project with external services, such as CI and chat.
-- [GitLab Integration](integration/README.md): Integrate with multiple third-party services with GitLab to allow external issue trackers and external authentication.
-- [Trello Power-Up](integration/trello_power_up.md): Integrate with GitLab's Trello Power-Up
+| Create Topics - Repositories | Description |
+|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------|
+| [Branches](user/project/repository/branches/index.md) and the [default branch](user/project/repository/branches/index.md#default-branch) | How to use branches in GitLab. |
+| [Commits](user/project/repository/index.md#commits) and [signing commits](user/project/repository/gpg_signed_commits/index.md) | Work with commits, and use GPG to sign your commits. |
+| [Create branches](user/project/repository/web_editor.md#create-a-new-branch), [create](user/project/repository/web_editor.md#create-a-file)<br/>and [upload](user/project/repository/web_editor.md#upload-a-file) files, and [create directories](user/project/repository/web_editor.md#create-a-directory) | Create branches, create and upload files, and create directories within GitLab. |
+| [Delete merged branches](user/project/repository/branches/index.md#delete-merged-branches) | Bulk delete branches after their changes are merged. |
+| [File templates](user/project/repository/web_editor.md#template-dropdowns) | File templates for common files. |
+| [Files](user/project/repository/index.md#files) | Files management. |
+| [Jupyter Notebook files](user/project/repository/index.md#jupyter-notebook-files) | GitLab's support for `.ipynb` files. |
+| [Protected branches](user/project/protected_branches.md) | Use protected branches. |
+| [Repositories](user/project/repository/index.md) | Manage source code repositories in GitLab's user interface. |
+| [Start a merge request](user/project/repository/web_editor.md#tips) | Start merge request when committing via GitLab's user interface. |
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
-#### Automation
+#### Merge Requests
-- [API](api/README.md): Automate GitLab via a simple and powerful API.
-- [GitLab Webhooks](user/project/integrations/webhooks.md): Let GitLab notify you when new code has been pushed to your project.
+| Create Topics - Merge Requests | Description |
+|:------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------|
+| [Checking out merge requests locally](user/project/merge_requests/index.md#checkout-merge-requests-locally) | Tips for working with merge requests locally. |
+| [Cherry-picking](user/project/merge_requests/cherry_pick_changes.md) | Use GitLab for cherry-picking changes. |
+| [Merge request discussion resolution](user/discussions/index.md#moving-a-single-discussion-to-a-new-issue) | Resolve discussions, move discussions in a merge request to an issue, and only allow merge requests to be merged if all discussions are resolved. |
+| [Merge requests](user/project/merge_requests/index.md) | Merge request management. |
+| [Work In Progress "WIP" merge requests](user/project/merge_requests/work_in_progress_merge_requests.md) | Prevent merges of work-in-progress merge requests. |
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+#### Integration and Automation
+
+| Create Topics - Integration and Automation | Description |
+|:------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------|
+| [GitLab API](api/README.md) | Integrate GitLab via a simple and powerful API. |
+| [GitLab Integration](integration/README.md) | Integrate with multiple third-party services with GitLab to allow external issue trackers and external authentication. |
+| [GitLab Webhooks](user/project/integrations/webhooks.md) | Let GitLab notify you when new code has been pushed to your project. |
+| [Project Services](user/project/integrations/project_services.md) | Integrate a project with external services, such as CI and chat. |
+| [Trello Power-Up](integration/trello_power_up.md) | Integrate with GitLab's Trello Power-Up. |
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
### Verify
Spot errors sooner, improve security and shorten feedback cycles with built-in
-static code analysis, code testing, code quality, dependency checking and review
-apps. Customize your approval workflow controls, automatically test the quality
-of your code, and spin up a staging environment for every code change. GitLab
-Continuous Integration is the most popular next generation testing system that
+static code analysis, code testing, code quality, dependency checking, and Review
+Apps. Customize your approval workflow controls, automatically test the quality
+of your code, and spin up a staging environment for every code change.
+
+GitLab Continuous Integration is the most popular next generation testing system that
scales to run your tests faster.
-- [GitLab CI/CD](ci/README.md): Explore the features and capabilities of Continuous Integration, Continuous Delivery, and Continuous Deployment with GitLab.
-- [Review Apps](ci/review_apps/index.md): Preview changes to your app right from a merge request.
-- [Pipeline Graphs](ci/pipelines.md#pipeline-graphs)
-- [JUnit test reports](ci/junit_test_reports.md)
+The following documentation relates to the DevOps **Verify** stage:
+
+| Verify Topics | Description |
+|:---------------------------------------------------|:-----------------------------------------------------------------------------|
+| [GitLab CI/CD](ci/README.md) | Explore the features and capabilities of Continuous Integration with GitLab. |
+| [JUnit test reports](ci/junit_test_reports.md) | Display JUnit test reports on merge requests. |
+| [Pipeline Graphs](ci/pipelines.md#pipeline-graphs) | Visualize builds. |
+| [Review Apps](ci/review_apps/index.md) | Preview changes to your application right from a merge request. |
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
### Package
@@ -141,7 +231,17 @@ GitLab Container Registry gives you the enhanced security and access controls of
custom Docker images without 3rd party add-ons. Easily upload and download images
from GitLab CI/CD with full Git repository management integration.
-- [GitLab Container Registry](user/project/container_registry.md): Learn how to use GitLab's built-in Container Registry.
+The following documentation relates to the DevOps **Package** stage:
+
+| Package Topics | Description |
+|:----------------------------------------------------------------|:-------------------------------------------------------|
+| [GitLab Container Registry](user/project/container_registry.md) | Learn how to use GitLab's built-in Container Registry. |
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
### Release
@@ -149,111 +249,257 @@ Spend less time configuring your tools, and more time creating. Whether you’re
deploying to one server or thousands, build, test, and release your code
confidently and securely with GitLab’s built-in Continuous Delivery and Deployment.
-- [Auto Deploy](topics/autodevops/index.md#auto-deploy): Configure GitLab CI for the deployment of your application.
-- [Environments and deployments](ci/environments.md): With environments, you can control the continuous deployment of your software within GitLab.
-- [GitLab Pages](user/project/pages/index.md): Build, test, and deploy a static site directly from GitLab.
-- [Scheduled Pipelines](user/project/pipelines/schedules.md)
-- [Protected Runners](ci/runners/README.md#protected-runners)
+The following documentation relates to the DevOps **Release** stage:
+
+| Release Topics | Description |
+|:------------------------------------------------------------|:---------------------------------------------------------------------------------------------|
+| [Auto Deploy](topics/autodevops/index.md#auto-deploy) | Configure GitLab for the deployment of your application. |
+| [Environments and deployments](ci/environments.md) | With environments, you can control the continuous deployment of your software within GitLab. |
+| [GitLab CI/CD](ci/README.md) | Explore the features and capabilities of Continuous Deployment and Delivery with GitLab. |
+| [GitLab Pages](user/project/pages/index.md) | Build, test, and deploy a static site directly from GitLab. |
+| [Protected Runners](ci/runners/README.md#protected-runners) | Select Runners to only pick jobs for protected branches and tags. |
+| [Scheduled Pipelines](user/project/pipelines/schedules.md) | Execute pipelines on a schedule. |
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
### Configure
Automate your entire workflow from build to deploy and monitoring with GitLab
-Auto Devops. Best practice templates get you started with minimal to zero
+Auto DevOps. Best practice templates get you started with minimal to zero
configuration. Then customize everything from buildpacks to CI/CD.
-- [Auto DevOps](topics/autodevops/index.md)
-- [Deployment of Helm, Ingress, and Prometheus on Kubernetes](user/project/clusters/index.md#installing-applications)
-- [Protected variables](ci/variables/README.md#protected-variables)
-- [Easy creation of Kubernetes clusters on GKE](user/project/clusters/index.md#adding-and-creating-a-new-gke-cluster-via-gitlab)
+The following documentation relates to the DevOps **Configure** stage:
+
+| Configure Topics | Description |
+|:-----------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------|
+| [Auto DevOps](topics/autodevops/index.md) | Automatically employ a complete DevOps lifecycle. |
+| [Easy creation of Kubernetes<br/>clusters on GKE](user/project/clusters/index.md#adding-and-creating-a-new-gke-cluster-via-gitlab) | Use Google Kubernetes Engine and GitLab. |
+| [Executable Runbooks](user/project/clusters/runbooks/index.md) | Documented procedures that explain how to carry out particular processes. |
+| [Installing Applications](user/project/clusters/index.md#installing-applications) | Deploy Helm, Ingress, and Prometheus on Kubernetes. |
+| [Mattermost slash commands](user/project/integrations/mattermost_slash_commands.md) | Enable and use slash commands from within Mattermost. |
+| [Protected variables](ci/variables/README.md#protected-variables) | Restrict variables to protected branches and tags. |
+| [Slack slash commands](user/project/integrations/slack_slash_commands.md) | Enable and use slash commands from within Slack. |
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
### Monitor
-Measure how long it takes to go from planning to monitoring and ensure your
-applications are always responsive and available. GitLab collects and displays
-performance metrics for deployed apps using Prometheus so you can know in an
+Ensure your applications are always responsive and available.
+
+GitLab collects and displays performance metrics for deployed applications so you can know in an
instant how code changes impact your production environment.
-- [GitLab Prometheus](administration/monitoring/prometheus/index.md): Configure the bundled Prometheus to collect various metrics from your GitLab instance.
-- [Prometheus project integration](user/project/integrations/prometheus.md): Configure the Prometheus integration per project and monitor your CI/CD environments.
-- [Prometheus metrics](user/project/integrations/prometheus_library/metrics.md): Let Prometheus collect metrics from various services, like Kubernetes, NGINX, NGINX ingress controller, HAProxy, and Amazon Cloud Watch.
-- [GitLab Performance Monitoring](administration/monitoring/performance/index.md): Use InfluxDB and Grafana to monitor the performance of your GitLab instance (will be eventually replaced by Prometheus).
-- [Health check](user/admin_area/monitoring/health_check.md): GitLab provides liveness and readiness probes to indicate service health and reachability to required services.
-- [GitLab Cycle Analytics](user/project/cycle_analytics.md): Cycle Analytics measures the time it takes to go from an
- [idea to production](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#from-idea-to-production-with-gitlab) for each project you have.
+The following documentation relates to the DevOps **Monitor** stage:
-## Getting started with GitLab
+| Monitor Topics | Description |
+|:------------------------------------------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------|
+| [GitLab Performance Monitoring](administration/monitoring/performance/index.md) **[CORE ONLY]** | Use InfluxDB and Grafana to monitor the performance of your GitLab instance (will be eventually replaced by Prometheus). |
+| [GitLab Prometheus](administration/monitoring/prometheus/index.md) **[CORE ONLY]** | Configure the bundled Prometheus to collect various metrics from your GitLab instance. |
+| [Health check](user/admin_area/monitoring/health_check.md) | GitLab provides liveness and readiness probes to indicate service health and reachability to required services. |
+| [Prometheus project integration](user/project/integrations/prometheus.md) | Configure the Prometheus integration per project and monitor your CI/CD environments. |
+| [Prometheus metrics](user/project/integrations/prometheus_library/index.md) | Let Prometheus collect metrics from various services, like Kubernetes, NGINX, NGINX ingress controller, HAProxy, and Amazon Cloud Watch. |
-- [GitLab Basics](gitlab-basics/README.md): Start working on your command line and on GitLab.
-- [GitLab Workflow](workflow/README.md): Enhance your workflow with the best of GitLab Workflow.
- - See also [GitLab Workflow - an overview](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/).
-- [GitLab Markdown](user/markdown.md): GitLab's advanced formatting system (GitLab Flavored Markdown).
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
-### User account
+### Secure
-- [User account](user/profile/index.md): Manage your account
- - [Authentication](topics/authentication/index.md): Account security with two-factor authentication, setup your ssh keys and deploy keys for secure access to your projects.
- - [Profile settings](user/profile/index.md#profile-settings): Manage your profile settings, two factor authentication and more.
-- [User permissions](user/permissions.md): Learn what each role in a project (external/guest/reporter/developer/maintainer/owner) can do.
+GitLab can help you secure your applications from within your development lifecycle.
-### Git and GitLab
+The following documentation relates to the DevOps **Secure** stage:
-- [Git](topics/git/index.md): Getting started with Git, branching strategies, Git LFS, advanced use.
-- [Git cheatsheet](https://about.gitlab.com/images/press/git-cheat-sheet.pdf): Download a PDF describing the most used Git operations.
-- [GitLab Flow](workflow/gitlab_flow.md): explore the best of Git with the GitLab Flow strategy.
+| Monitor Topics | Description |
+|:----------------------------------------------------------------|:-----------------------------------------------------------------------------------------------------------|
+| [Container Scanning example](ci/examples/container_scanning.md) | `.gitlab-ci.yml` example of using Clair and clair-scanner to scan docker images for known vulnerabilities. |
-## Administrator documentation
+NOTE: **Note:**
+Viewing [Container Scanning reports](https://docs.gitlab.com/ee/user/project/merge_requests/container_scanning.html) within merge requests requires [GitLab Ultimate](https://about.gitlab.com/pricing/).
-[Administration documentation](administration/index.md) applies to admin users of GitLab
-self-hosted instances.
+## Subscribe to GitLab
-Learn how to install, configure, update, upgrade, integrate, and maintain your own instance.
-Regular users don't have access to GitLab administration tools and settings.
+There are two ways to use GitLab:
-## Contributor documentation
+- [GitLab self-managed](#gitlab-self-managed): Install, administer, and maintain your own GitLab instance.
+- [GitLab.com](#gitlab-com): GitLab's SaaS offering. You don't need to install anything to use GitLab.com,
+ you only need to [sign up](https://gitlab.com/users/sign_in) and start using GitLab straight away.
-GitLab Community Edition is [open source](https://gitlab.com/gitlab-org/gitlab-ce/)
-and GitLab Enterprise Edition is [open-core](https://gitlab.com/gitlab-org/gitlab-ee/).
-Learn how to contribute to GitLab:
+The following sections outline tiers and features within GitLab self-managed and GitLab.com.
-- [Development](development/README.md): All styleguides and explanations how to contribute.
-- [Legal](legal/README.md): Contributor license agreements.
-- [Writing documentation](development/documentation/index.md): Contributing to GitLab Docs.
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
-## GitLab subscriptions
+### GitLab self-managed
-You have two options to use GitLab:
+With GitLab self-managed, you deploy your own GitLab instance on-premises or on a cloud of your choice.
+GitLab self-managed is available for [free and with paid subscriptions](https://about.gitlab.com/pricing/#self-managed) in the following tiers:
-- GitLab self-hosted: Install, administer, and maintain your own GitLab instance.
-- GitLab.com: GitLab's SaaS offering. You don't need to install anything to use GitLab.com,
-you only need to [sign up](https://gitlab.com/users/sign_in) and start using GitLab
-straight away.
+| Tier | Includes |
+|:---------|:-----------------------------------------------|
+| Core | Core features. |
+| Starter | Core and Starter features. |
+| Premium | Core, Starter, and Premium features. |
+| Ultimate | Core, Starter, Premium, and Ultimate features. |
-### GitLab self-hosted
+The following resources are available for more information on GitLab self-managed:
-With GitLab self-hosted, you deploy your own GitLab instance on-premises or on a private cloud of your choice. GitLab self-hosted is available for [free and with paid subscriptions](https://about.gitlab.com/pricing/): Core, Starter, Premium, and Ultimate.
+- [Feature comparison](https://about.gitlab.com/pricing/self-managed/feature-comparison/), for information on what features are available at each tier.
+- [GitLab pricing page](https://about.gitlab.com/pricing/#self-managed), for subscription information and a free trial.
+- Our [product marketing page](https://about.gitlab.com/handbook/marketing/product-marketing/), for additional information including:
+ - How [different tiers are licensed](https://about.gitlab.com/handbook/marketing/product-marketing/#tiers).
+ - The different [GitLab distributions](https://about.gitlab.com/handbook/marketing/product-marketing/#distributions).
-Every feature available in Core is also available in Starter, Premium, and Ultimate.
-Starter features are also available in Premium and Ultimate, and Premium features are also
-available in Ultimate.
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
### GitLab.com
GitLab.com is hosted, managed, and administered by GitLab, Inc., with
-[free and paid subscriptions](https://about.gitlab.com/gitlab-com/) for individuals
-and teams: Free, Bronze, Silver, and Gold.
+[free and paid subscriptions](https://about.gitlab.com/pricing/) for individuals
+and teams in the following tiers:
+
+| Tier | Includes same features available in |
+|:-------|:----------------------------------------------------|
+| Free | [Core](#gitlab-self-managed) self-managed tier. |
+| Bronze | [Starter](#gitlab-self-managed) self-managed tier. |
+| Silver | [Premium](#gitlab-self-managed) self-managed tier. |
+| Gold | [Ultimate](#gitlab-self-managed) self-managed tier. |
+
+GitLab.com subscriptions grant access
+to the same features available in GitLab self-managed, **except
+[administration](administration/index.md) tools and settings**.
+
+TIP: **Tip:**
+To support the open source community and encourage the development of open source projects, GitLab grants access to **Gold** features for all GitLab.com **public** projects, regardless of the subscription.
+
+The following resources are available for more information on GitLab.com:
+
+- [Feature comparison](https://about.gitlab.com/pricing/gitlab-com/feature-comparison/), for information on what features are available at each tier.
+- [GitLab pricing page](https://about.gitlab.com/pricing/), for subscription information and a free trial.
+- Our [product marketing page](https://about.gitlab.com/handbook/marketing/product-marketing/), for additional information including:
+ - How [different tiers are licensed](https://about.gitlab.com/handbook/marketing/product-marketing/#tiers).
+ - The different [GitLab distributions](https://about.gitlab.com/handbook/marketing/product-marketing/#distributions).
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+## New to Git and GitLab?
+
+Working with new systems can be daunting.
+
+We have the following documentation to rapidly uplift your GitLab knowledge:
+
+| Topic | Description |
+|:-----------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------|
+| [GitLab Basics](gitlab-basics/README.md) | Start working on the command line and with GitLab. |
+| [GitLab Workflow](workflow/README.md) and [overview](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/) | Enhance your workflow with the best of GitLab Workflow. |
+| [Get started with GitLab CI/CD](ci/quick_start/README.md) | Quickly implement GitLab CI/CD. |
+| [Auto DevOps](topics/autodevops/index.md) | Learn more about GitLab's Auto DevOps. |
+| [GitLab Markdown](user/markdown.md) | GitLab's advanced formatting system (GitLab Flavored Markdown) |
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+### User account
+
+Learn more about GitLab account management:
+
+| Topic | Description |
+|:-----------------------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------|
+| [User account](user/profile/index.md) | Manage your account. |
+| [Authentication](topics/authentication/index.md) | Account security with two-factor authentication, set up your ssh keys, and deploy keys for secure access to your projects. |
+| [Profile settings](user/profile/index.md#profile-settings) | Manage your profile settings, two factor authentication, and more. |
+| [User permissions](user/permissions.md) | Learn what each role in a project can do. |
-GitLab.com subscriptions grants access
-to the same features available in GitLab self-hosted, **except
-[administration](administration/index.md) tools and settings**:
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+### Git and GitLab
+
+Learn more about using Git, and using Git with GitLab:
+
+| Topic | Description |
+|:----------------------------------------------------------------------------|:---------------------------------------------------------------------------|
+| [Git](topics/git/index.md) | Getting started with Git, branching strategies, Git LFS, and advanced use. |
+| [Git cheatsheet](https://about.gitlab.com/images/press/git-cheat-sheet.pdf) | Download a PDF describing the most used Git operations. |
+| [GitLab Flow](workflow/gitlab_flow.md) | Explore the best of Git with the GitLab Flow strategy. |
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+## Coming to GitLab from another platform
+
+If you are coming to GitLab from another platform, you'll find the following information useful:
+
+| Topic | Description |
+|:---------------------------------------------------------------|:---------------------------------------------------------------------------------------|
+| [Importing to GitLab](user/project/import/index.md) | Import your projects from GitHub, Bitbucket, GitLab.com, FogBugz, and SVN into GitLab. |
+| [Migrating from SVN](workflow/importing/migrating_from_svn.md) | Convert a SVN repository to Git and GitLab. |
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+## Building an integration with GitLab
+
+There are many ways to integrate with GitLab, including:
+
+| Topic | Description |
+|:-----------------------------------------------------------|:------------------------------------------------|
+| [GitLab API](api/README.md) | Integrate GitLab via a simple and powerful API. |
+| [Integrations and automation](#integration-and-automation) | All GitLab integration and automation options. |
+
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
+
+## Contributing to GitLab
+
+GitLab Community Edition is [open source](https://gitlab.com/gitlab-org/gitlab-ce/)
+and GitLab Enterprise Edition is [open-core](https://gitlab.com/gitlab-org/gitlab-ee/).
-- GitLab.com Free includes the same features available in Core
-- GitLab.com Bronze includes the same features available in GitLab Starter
-- GitLab.com Silver includes the same features available in GitLab Premium
-- GitLab.com Gold includes the same features available in GitLab Ultimate
+Learn how to contribute to GitLab with the following resources:
-For supporting the open source community and encouraging the development of
-open source projects, GitLab grants access to **Gold** features
-for all GitLab.com **public** projects, regardless of the subscription.
+| Topic | Description |
+|:------------------------------------------------------------|:-----------------------------------------|
+| [Development](development/README.md) | How to contribute to GitLab development. |
+| [Legal](legal/README.md) | Contributor license agreements. |
+| [Writing documentation](development/documentation/index.md) | How to contribute to GitLab Docs. |
-To know more about GitLab subscriptions and licensing, please refer to the
-[GitLab Product Marketing Handbook](https://about.gitlab.com/handbook/marketing/product-marketing/#tiers).
+<div align="right">
+ <a type="button" class="btn btn-default" href="#overview">
+ Back to Overview <i class="fa fa-angle-double-up" aria-hidden="true"></i>
+ </a>
+</div>
diff --git a/doc/administration/auth/authentiq.md b/doc/administration/auth/authentiq.md
index 252ff1f4b15..772e55cef07 100644
--- a/doc/administration/auth/authentiq.md
+++ b/doc/administration/auth/authentiq.md
@@ -6,7 +6,7 @@ Authentiq will generate a Client ID and the accompanying Client Secret for you t
1. Get your Client credentials (Client ID and Client Secret) at [Authentiq](https://www.authentiq.com/developers).
-2. On your GitLab server, open the configuration file:
+1. On your GitLab server, open the configuration file:
For omnibus installation
```sh
@@ -18,11 +18,11 @@ Authentiq will generate a Client ID and the accompanying Client Secret for you t
```sh
sudo -u git -H editor /home/git/gitlab/config/gitlab.yml
```
-
-3. See [Initial OmniAuth Configuration](../../integration/omniauth.md#initial-omniauth-configuration) for initial settings to enable single sign-on and add Authentiq as an OAuth provider.
-4. Add the provider configuration for Authentiq:
-
+1. See [Initial OmniAuth Configuration](../../integration/omniauth.md#initial-omniauth-configuration) for initial settings to enable single sign-on and add Authentiq as an OAuth provider.
+
+1. Add the provider configuration for Authentiq:
+
For Omnibus packages:
```ruby
@@ -31,15 +31,15 @@ Authentiq will generate a Client ID and the accompanying Client Secret for you t
"name" => "authentiq",
"app_id" => "YOUR_CLIENT_ID",
"app_secret" => "YOUR_CLIENT_SECRET",
- "args" => {
+ "args" => {
"scope": 'aq:name email~rs address aq:push'
}
}
]
```
-
+
For installations from source:
-
+
```yaml
- { name: 'authentiq',
app_id: 'YOUR_CLIENT_ID',
@@ -49,20 +49,20 @@ Authentiq will generate a Client ID and the accompanying Client Secret for you t
}
}
```
-
-
-5. The `scope` is set to request the user's name, email (required and signed), and permission to send push notifications to sign in on subsequent visits.
+
+
+1. The `scope` is set to request the user's name, email (required and signed), and permission to send push notifications to sign in on subsequent visits.
See [OmniAuth Authentiq strategy](https://github.com/AuthentiqID/omniauth-authentiq/wiki/Scopes,-callback-url-configuration-and-responses) for more information on scopes and modifiers.
-6. Change `YOUR_CLIENT_ID` and `YOUR_CLIENT_SECRET` to the Client credentials you received in step 1.
+1. Change `YOUR_CLIENT_ID` and `YOUR_CLIENT_SECRET` to the Client credentials you received in step 1.
-7. Save the configuration file.
+1. Save the configuration file.
-8. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect if you installed GitLab via Omnibus or from source respectively.
+1. [Reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect if you installed GitLab via Omnibus or from source respectively.
-On the sign in page there should now be an Authentiq icon below the regular sign in form. Click the icon to begin the authentication process.
+On the sign in page there should now be an Authentiq icon below the regular sign in form. Click the icon to begin the authentication process.
-- If the user has the Authentiq ID app installed in their iOS or Android device, they can scan the QR code, decide what personal details to share and sign in to your GitLab installation.
-- If not they will be prompted to download the app and then follow the procedure above.
+- If the user has the Authentiq ID app installed in their iOS or Android device, they can scan the QR code, decide what personal details to share and sign in to your GitLab installation.
+- If not they will be prompted to download the app and then follow the procedure above.
-If everything goes right, the user will be returned to GitLab and will be signed in. \ No newline at end of file
+If everything goes right, the user will be returned to GitLab and will be signed in.
diff --git a/doc/administration/auth/ldap.md b/doc/administration/auth/ldap.md
index 5c7392b99d0..54ded25291a 100644
--- a/doc/administration/auth/ldap.md
+++ b/doc/administration/auth/ldap.md
@@ -111,7 +111,7 @@ main:
uid: 'sAMAccountName' # This should be the attribute, not the value that maps to uid.
##
- ## Examples: 'america\\momo' or 'CN=Gitlab Git,CN=Users,DC=mydomain,DC=com'
+ ## Examples: 'america\momo' or 'CN=Gitlab Git,CN=Users,DC=mydomain,DC=com'
##
bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
password: '_the_password_of_the_bind_user'
@@ -132,7 +132,7 @@ main:
## Enables SSL certificate verification if encryption method is
## "start_tls" or "simple_tls". Defaults to true since GitLab 10.0 for
## security. This may break installations upon upgrade to 10.0, that did
- ## not know their LDAP SSL certificates were not setup properly.
+ ## not know their LDAP SSL certificates were not set up properly.
##
verify_certificates: true
diff --git a/doc/administration/auth/okta.md b/doc/administration/auth/okta.md
index 664657650d4..ae38094391b 100644
--- a/doc/administration/auth/okta.md
+++ b/doc/administration/auth/okta.md
@@ -11,7 +11,7 @@ The following documentation enables Okta as a SAML provider.
1. When the app screen comes up you see another button to **Create an App** and
choose SAML 2.0 on the next screen.
1. Now, very important, add a logo
- (you can choose it from https://about.gitlab.com/press/). You'll have to
+ (you can choose it from <https://about.gitlab.com/press/>). You'll have to
crop and resize it.
1. Next, you'll need the to fill in the SAML general config. Here's an example
image.
diff --git a/doc/administration/container_registry.md b/doc/administration/container_registry.md
index 890b780fe80..cfe7b0e05e3 100644
--- a/doc/administration/container_registry.md
+++ b/doc/administration/container_registry.md
@@ -71,7 +71,7 @@ A Registry init file is not shipped with GitLab if you install it from source.
Hence, [restarting GitLab][restart gitlab] will not restart the Registry should
you modify its settings. Read the upstream documentation on how to achieve that.
-At the absolute minimum, make sure your [Registry configuration][registry-auth]
+At the **absolute** minimum, make sure your [Registry configuration][registry-auth]
has `container_registry` as the service and `https://gitlab.example.com/jwt/auth`
as the realm:
@@ -84,6 +84,9 @@ auth:
rootcertbundle: /root/certs/certbundle
```
+CAUTION: **Caution:**
+If `auth` is not set up, users will be able to pull docker images without authentication.
+
## Container Registry domain configuration
There are two ways you can configure the Registry's external domain.
diff --git a/doc/administration/custom_hooks.md b/doc/administration/custom_hooks.md
index 9b0fabb9259..60ad4bf4e8f 100644
--- a/doc/administration/custom_hooks.md
+++ b/doc/administration/custom_hooks.md
@@ -50,6 +50,9 @@ Hooks can be also placed in `hooks/<hook_name>.d` (global) or
`custom_hooks/<hook_name>.d` (per project) directories supporting chained
execution of the hooks.
+NOTE: **Note:** `<hook_name>.d` would need to be either `pre-receive.d`,
+`post-receive.d`, or `update.d` to work properly. Any other names will be ignored.
+
To look in a different directory for the global custom hooks (those in
`hooks/<hook_name.d>`), set `custom_hooks_dir` in gitlab-shell config. For
Omnibus installations, this can be set in `gitlab.rb`; and in source
@@ -57,7 +60,7 @@ installations, this can be set in `gitlab-shell/config.yml`.
The hooks are searched and executed in this order:
-1. `<project>.git/hooks/` - symlink to `gitlab-shell/hooks` global dir
+1. `gitlab-shell/hooks` directory as known to Gitaly
1. `<project>.git/hooks/<hook_name>` - executed by `git` itself, this is `gitlab-shell/hooks/<hook_name>`
1. `<project>.git/custom_hooks/<hook_name>` - per project hook (this is already existing behavior)
1. `<project>.git/custom_hooks/<hook_name>.d/*` - per project hooks
diff --git a/doc/administration/external_database.md b/doc/administration/external_database.md
index 31199f2cdc7..ec2d30c82d1 100644
--- a/doc/administration/external_database.md
+++ b/doc/administration/external_database.md
@@ -9,7 +9,7 @@ separate from the GitLab Omnibus package.
If you use a cloud-managed service, or provide your own PostgreSQL instance:
-1. Setup PostgreSQL according to the
+1. Set up PostgreSQL according to the
[database requirements document](../install/requirements.md#database).
1. Set up a `gitlab` username with a password of your choice. The `gitlab` user
needs privileges to create the `gitlabhq_production` database.
diff --git a/doc/administration/git_protocol.md b/doc/administration/git_protocol.md
new file mode 100644
index 00000000000..341a00009e5
--- /dev/null
+++ b/doc/administration/git_protocol.md
@@ -0,0 +1,103 @@
+---
+description: "Set and configure Git protocol v2"
+---
+
+# Configuring Git Protocol v2
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/46555) in GitLab 11.4.
+
+Git protocol v2 improves the v1 wire protocol in several ways and is
+enabled by default in GitLab for HTTP requests. In order to enable SSH,
+further configuration is needed by the administrator.
+
+More details about the new features and improvements are available in
+the [Google Open Source Blog](https://opensource.googleblog.com/2018/05/introducing-git-protocol-version-2.html)
+and the [protocol documentation](https://github.com/git/git/blob/master/Documentation/technical/protocol-v2.txt).
+
+## Requirements
+
+From the client side, `git` `v2.18.0` or newer must be installed.
+
+From the server side, if we want to configure SSH we need to set the `sshd`
+server to accept the `GIT_PROTOCOL` environment.
+
+In installations using [GitLab Helm Charts](../install/kubernetes/gitlab_chart.md)
+and [All-in-one docker image](https://docs.gitlab.com/omnibus/docker/), the SSH
+service is already configured to accept the `GIT_PROTOCOL` environment and users
+need not do anything more.
+
+For Omnibus GitLab and installations from source, you have to manually update
+the SSH configuration of your server:
+
+```
+# /etc/ssh/sshd_config
+AcceptEnv GIT_PROTOCOL
+```
+
+Once configured, restart the SSH daemon. In Ubuntu, run:
+
+```sh
+sudo service ssh restart
+```
+
+## Instructions
+
+In order to use the new protocol, clients need to either pass the configuration
+`-c protocol.version=2` to the git command, or set it globally:
+
+```sh
+git config --global protocol.version 2
+```
+
+### HTTP connections
+
+Verify Git v2 is used by the client:
+
+```sh
+GIT_TRACE_CURL=1 git -c protocol.version=2 ls-remote https://your-gitlab-instance.com/group/repo.git 2>&1 | grep Git-Protocol
+```
+
+You should see that the `Git-Protocol` header is sent:
+
+```
+16:29:44.577888 http.c:657 => Send header: Git-Protocol: version=2
+```
+
+Verify Git v2 is used by the server:
+
+```sh
+GIT_TRACE_PACKET=1 git -c protocol.version=2 ls-remote https://your-gitlab-instance.com/group/repo.git 2>&1 | head
+```
+
+Example response using Git protocol v2:
+
+```sh
+$ GIT_TRACE_PACKET=1 git -c protocol.version=2 ls-remote https://your-gitlab-instance.com/group/repo.git 2>&1 | head
+10:42:50.574485 pkt-line.c:80 packet: git< # service=git-upload-pack
+10:42:50.574653 pkt-line.c:80 packet: git< 0000
+10:42:50.574673 pkt-line.c:80 packet: git< version 2
+10:42:50.574679 pkt-line.c:80 packet: git< agent=git/2.18.1
+10:42:50.574684 pkt-line.c:80 packet: git< ls-refs
+10:42:50.574688 pkt-line.c:80 packet: git< fetch=shallow
+10:42:50.574693 pkt-line.c:80 packet: git< server-option
+10:42:50.574697 pkt-line.c:80 packet: git< 0000
+10:42:50.574817 pkt-line.c:80 packet: git< version 2
+10:42:50.575308 pkt-line.c:80 packet: git< agent=git/2.18.1
+```
+
+### SSH Connections
+
+Verify Git v2 is used by the client:
+
+```sh
+GIT_SSH_COMMAND="ssh -v" git -c protocol.version=2 ls-remote ssh://your-gitlab-instance.com:group/repo.git 2>&1 |grep GIT_PROTOCOL
+```
+
+You should see that the `GIT_PROTOCOL` environment variable is sent:
+
+```
+debug1: Sending env GIT_PROTOCOL = version=2
+```
+
+For the server side, you can use the [same examples from HTTP](#http-connections), changing the
+URL to use SSH.
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index 49c6902bc42..dc6a71e2ebd 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -1,10 +1,8 @@
# Gitaly
-[Gitaly](https://gitlab.com/gitlab-org/gitaly) (introduced in GitLab
-9.0) is a service that provides high-level RPC access to Git
-repositories. Gitaly was optional when it was first introduced in
-GitLab, but since GitLab 9.4 it is a mandatory component of the
-application.
+[Gitaly](https://gitlab.com/gitlab-org/gitaly) is the service that
+provides high-level RPC access to Git repositories. Without it, no other
+components can read or write Git data.
GitLab components that access Git repositories (gitlab-rails,
gitlab-shell, gitlab-workhorse) act as clients to Gitaly. End users do
@@ -25,15 +23,13 @@ gitaly['prometheus_listen_addr'] = 'localhost:9236'
```
To change a Gitaly setting in installations from source you can edit
-`/home/git/gitaly/config.toml`.
+`/home/git/gitaly/config.toml`. Changes will be applied when you run
+`service gitlab restart`.
```toml
prometheus_listen_addr = "localhost:9236"
```
-Changes to `/home/git/gitaly/config.toml` are applied when you run `service
-gitlab restart`.
-
## Client-side GRPC logs
Gitaly uses the [gRPC](https://grpc.io/) RPC framework. The Ruby gRPC
@@ -49,15 +45,9 @@ installations that are larger than a single machine. Most
installations will be better served with the default configuration
used by Omnibus and the GitLab source installation guide.
-Starting with GitLab 9.4 it is possible to run Gitaly on a different
-server from the rest of the application. This can improve performance
-when running GitLab with its repositories stored on an NFS server.
-
-At the moment (GitLab 9.4) Gitaly is not yet a replacement for NFS
-because some parts of GitLab still bypass Gitaly when accessing Git
-repositories. If you choose to deploy Gitaly on your NFS server you
-must still also mount your Git shares on your GitLab application
-servers.
+Starting with GitLab 11.4, Gitaly is a replacement for NFS except
+when the [Elastic Search indexer](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer)
+is used.
Gitaly network traffic is unencrypted so you should use a firewall to
restrict access to your Gitaly server.
@@ -219,7 +209,7 @@ repository from your GitLab server over HTTP.
If you are running Gitaly [as a remote
service](#running-gitaly-on-its-own-server) you may want to disable
-the local Gitaly service that runs on your Gitlab server by default.
+the local Gitaly service that runs on your GitLab server by default.
> 'Disabling Gitaly' only makes sense when you run GitLab in a custom
cluster configuration, where different services run on different
@@ -247,3 +237,14 @@ gitaly_enabled=false
When you run `service gitlab restart` Gitaly will be disabled on this
particular machine.
+
+## Troubleshooting Gitaly in production
+
+Since GitLab 11.6, Gitaly comes with a command-line tool called
+`gitaly-debug` that can be run on a Gitaly server to aid in
+troubleshooting. In GitLab 11.6 its only sub-command is
+`simulate-http-clone` which allows you to measure the maximum possible
+Git clone speed for a specific repository on the server.
+
+For an up to date list of sub-commands see [the gitaly-debug
+README](https://gitlab.com/gitlab-org/gitaly/blob/master/cmd/gitaly-debug/README.md).
diff --git a/doc/administration/high_availability/database.md b/doc/administration/high_availability/database.md
index b5124b1d540..c1eeb40b98f 100644
--- a/doc/administration/high_availability/database.md
+++ b/doc/administration/high_availability/database.md
@@ -13,7 +13,7 @@ Database Service (RDS) that runs PostgreSQL.
If you use a cloud-managed service, or provide your own PostgreSQL:
-1. Setup PostgreSQL according to the
+1. Set up PostgreSQL according to the
[database requirements document](../../install/requirements.md#database).
1. Set up a `gitlab` username with a password of your choice. The `gitlab` user
needs privileges to create the `gitlabhq_production` database.
diff --git a/doc/administration/high_availability/gitlab.md b/doc/administration/high_availability/gitlab.md
index f16ae835ced..2ca860bd763 100644
--- a/doc/administration/high_availability/gitlab.md
+++ b/doc/administration/high_availability/gitlab.md
@@ -118,7 +118,7 @@ need some extra configuration.
gitlab_rails['db_key_base'] = 'bf2e47b68d6cafaef1d767e628b619365becf27571e10f196f98dc85e7771042b9203199d39aff91fcb6837c8ed83f2a912b278da50999bb11a2fbc0fba52964'
```
-1. Run `touch /etc/gitlab/skip-auto-migrations` to prevent database migrations
+1. Run `touch /etc/gitlab/skip-auto-reconfigure` to prevent database migrations
from running on upgrade. Only the primary GitLab application server should
handle migrations.
diff --git a/doc/administration/high_availability/nfs.md b/doc/administration/high_availability/nfs.md
index 95e2caf0cad..74b0e2c8184 100644
--- a/doc/administration/high_availability/nfs.md
+++ b/doc/administration/high_availability/nfs.md
@@ -3,6 +3,11 @@
You can view information and options set for each of the mounted NFS file
systems by running `nfsstat -m` and `cat /etc/fstab`.
+NOTE: **Note:** Filesystem performance has a big impact on overall GitLab
+performance, especially for actions that read or write to Git repositories. See
+[Filesystem Performance Benchmarking](../operations/filesystem_benchmarking.md)
+for steps to test filesystem performance.
+
## NFS Server features
### Required features
@@ -32,7 +37,31 @@ options:
circumstances it could lead to data loss if a failure occurs before data has
synced.
-## AWS Elastic File System
+### Known issues
+
+On some customer systems, we have seen NFS clients slow precipitously due to
+[excessive network traffic from numerous `TEST_STATEID` NFS
+messages](https://gitlab.com/gitlab-org/gitlab-ce/issues/52017). This is
+likely due to a [Linux kernel
+bug](https://bugzilla.redhat.com/show_bug.cgi?id=1552203) that may be fixed in
+[more recent kernels with this
+commit](https://github.com/torvalds/linux/commit/95da1b3a5aded124dd1bda1e3cdb876184813140).
+
+Users encountering a similar issue may be advised to disable the NFS server
+delegation feature, which is an optimization to reduce the number of network
+round-trips needed to read or write files. To disable NFS server delegations
+on an Linux NFS server, do the following:
+
+1. On the NFS server, run:
+
+ ```sh
+ echo 0 > /proc/sys/fs/leases-enable
+ sysctl -w fs.leases-enable=0
+ ```
+
+1. Restart the NFS server process. For example, on CentOS run `service nfs restart`.
+
+## Avoid using AWS's Elastic File System (EFS)
GitLab strongly recommends against using AWS Elastic File System (EFS).
Our support team will not be able to assist on performance issues related to
@@ -49,6 +78,23 @@ stored on a local volume.
For more details on another person's experience with EFS, see
[Amazon's Elastic File System: Burst Credits](https://rawkode.com/2017/04/16/amazons-elastic-file-system-burst-credits/)
+## Avoid using PostgreSQL with NFS
+
+GitLab strongly recommends against running your PostgreSQL database
+across NFS. The GitLab support team will not be able to assist on performance issues related to
+this configuration.
+
+Additionally, this configuration is specifically warned against in the
+[Postgres Documentation](https://www.postgresql.org/docs/current/static/creating-cluster.html#CREATING-CLUSTER-NFS):
+
+>PostgreSQL does nothing special for NFS file systems, meaning it assumes NFS behaves exactly like
+>locally-connected drives. If the client or server NFS implementation does not provide standard file
+>system semantics, this can cause reliability problems. Specifically, delayed (asynchronous) writes
+>to the NFS server can cause data corruption problems.
+
+For supported database architecture, please see our documentation on
+[Configuring a Database for GitLab HA](https://docs.gitlab.com/ee/administration/high_availability/database.html).
+
## NFS Client mount options
Below is an example of an NFS mount point defined in `/etc/fstab` we use on
@@ -58,10 +104,11 @@ GitLab.com:
10.1.1.1:/var/opt/gitlab/git-data /var/opt/gitlab/git-data nfs4 defaults,soft,rsize=1048576,wsize=1048576,noatime,nofail,lookupcache=positive 0 2
```
-Notice several options that you should consider using:
+Note there are several options that you should consider using:
| Setting | Description |
| ------- | ----------- |
+| `vers=4.1` |NFS v4.1 should be used instead of v4.0 because there is a Linux [NFS client bug in v4.0](https://gitlab.com/gitlab-org/gitaly/issues/1339) that can cause significant problems due to stale data.
| `nofail` | Don't halt boot process waiting for this mount to become available
| `lookupcache=positive` | Tells the NFS client to honor `positive` cache results but invalidates any `negative` cache results. Negative cache results cause problems with Git. Specifically, a `git push` can fail to register uniformly across all NFS clients. The negative cache causes the clients to 'remember' that the files did not exist previously.
@@ -87,7 +134,7 @@ Mount `/gitlab-nfs` then use the following Omnibus
configuration to move each data location to a subdirectory:
```ruby
-git_data_dirs({"default" => "/gitlab-nfs/gitlab-data/git-data"})
+git_data_dirs({"default" => { "path" => "/gitlab-nfs/gitlab-data/git-data"} })
user['home'] = '/gitlab-nfs/gitlab-data/home'
gitlab_rails['uploads_directory'] = '/gitlab-nfs/gitlab-data/uploads'
gitlab_rails['shared_path'] = '/gitlab-nfs/gitlab-data/shared'
@@ -133,7 +180,7 @@ following are the 5 locations need to be shared:
| Location | Description | Default configuration |
| -------- | ----------- | --------------------- |
-| `/var/opt/gitlab/git-data` | Git repository data. This will account for a large portion of your data | `git_data_dirs({"default" => "/var/opt/gitlab/git-data"})`
+| `/var/opt/gitlab/git-data` | Git repository data. This will account for a large portion of your data | `git_data_dirs({"default" => { "path" => "/var/opt/gitlab/git-data"} })`
| `/var/opt/gitlab/.ssh` | SSH `authorized_keys` file and keys used to import repositories from some other Git services | `user['home'] = '/var/opt/gitlab/'`
| `/var/opt/gitlab/gitlab-rails/uploads` | User uploaded attachments | `gitlab_rails['uploads_directory'] = '/var/opt/gitlab/gitlab-rails/uploads'`
| `/var/opt/gitlab/gitlab-rails/shared` | Build artifacts, GitLab Pages, LFS objects, temp files, etc. If you're using LFS this may also account for a large portion of your data | `gitlab_rails['shared_path'] = '/var/opt/gitlab/gitlab-rails/shared'`
diff --git a/doc/administration/high_availability/redis.md b/doc/administration/high_availability/redis.md
index e05bebbef18..833c1f367dd 100644
--- a/doc/administration/high_availability/redis.md
+++ b/doc/administration/high_availability/redis.md
@@ -15,7 +15,7 @@ Omnibus GitLab packages.
> **Notes:**
> - Redis requires authentication for High Availability. See
-> [Redis Security](http://redis.io/topics/security) documentation for more
+> [Redis Security](https://redis.io/topics/security) documentation for more
> information. We recommend using a combination of a Redis password and tight
> firewall rules to secure your Redis service.
> - You are highly encouraged to read the [Redis Sentinel][sentinel] documentation
@@ -81,8 +81,8 @@ When a **Master** fails to respond, it's the application's responsibility
(in our case GitLab) to handle timeout and reconnect (querying a **Sentinel**
for a new **Master**).
-To get a better understanding on how to correctly setup Sentinel, please read
-the [Redis Sentinel documentation](http://redis.io/topics/sentinel) first, as
+To get a better understanding on how to correctly set up Sentinel, please read
+the [Redis Sentinel documentation](https://redis.io/topics/sentinel) first, as
failing to configure it correctly can lead to data loss or can bring your
whole cluster down, invalidating the failover effort.
@@ -217,7 +217,7 @@ Pick the one that suits your needs.
and configure Sentinel, jump directly to the Sentinel section in the
[Redis HA installation from source](redis_source.md#step-3-configuring-the-redis-sentinel-instances) documentation.
- [Omnibus GitLab **Enterprise Edition** (EE) package][ee]: Both Redis and Sentinel
- are bundled in the package, so you can use the EE package to setup the whole
+ are bundled in the package, so you can use the EE package to set up the whole
Redis HA infrastructure (master, slave and Sentinel) which is described in
this document.
- If you have installed GitLab using the Omnibus GitLab packages (CE or EE),
@@ -228,7 +228,7 @@ Pick the one that suits your needs.
## Configuring Redis HA
-This is the section where we install and setup the new Redis instances.
+This is the section where we install and set up the new Redis instances.
> **Notes:**
> - We assume that you have installed GitLab and all HA components from scratch. If you
@@ -336,7 +336,7 @@ The prerequisites for a HA Redis setup are the following:
1. To prevent database migrations from running on upgrade, run:
```
- sudo touch /etc/gitlab/skip-auto-migrations
+ sudo touch /etc/gitlab/skip-auto-reconfigure
```
Only the primary GitLab application server should handle migrations.
@@ -370,7 +370,7 @@ You must have at least `3` Redis Sentinel servers, and they need to
be each in an independent machine. You can configure them in the same
machines where you've configured the other Redis servers.
-With GitLab Enterprise Edition, you can use the Omnibus package to setup
+With GitLab Enterprise Edition, you can use the Omnibus package to set up
multiple machines with the Sentinel daemon.
---
@@ -458,7 +458,7 @@ multiple machines with the Sentinel daemon.
1. To prevent database migrations from running on upgrade, run:
```
- sudo touch /etc/gitlab/skip-auto-migrations
+ sudo touch /etc/gitlab/skip-auto-reconfigure
```
Only the primary GitLab application server should handle migrations.
@@ -535,7 +535,7 @@ In this example we consider that all servers have an internal network
interface with IPs in the `10.0.0.x` range, and that they can connect
to each other using these IPs.
-In a real world usage, you would also setup firewall rules to prevent
+In a real world usage, you would also set up firewall rules to prevent
unauthorized access from other machines and block traffic from the
outside (Internet).
@@ -665,7 +665,7 @@ cache, queues, and shared_state. To make this work with Sentinel:
**Note**: Redis URLs should be in the format: `redis://:PASSWORD@SENTINEL_MASTER_NAME`
1. PASSWORD is the plaintext password for the Redis instance
- 2. SENTINEL_MASTER_NAME is the Sentinel master name (e.g. `gitlab-redis-cache`)
+ 1. SENTINEL_MASTER_NAME is the Sentinel master name (e.g. `gitlab-redis-cache`)
1. Include an array of hashes with host/port combinations, such as the following:
```ruby
@@ -684,7 +684,7 @@ cache, queues, and shared_state. To make this work with Sentinel:
```
1. Note that for each persistence class, GitLab will default to using the
configuration specified in `gitlab_rails['redis_sentinels']` unless
- overriden by the settings above.
+ overridden by the settings above.
1. Be sure to include BOTH configuration options for each persistent classes. For example,
if you choose to configure a cache instance, you must specify both `gitlab_rails['redis_cache_instance']`
and `gitlab_rails['redis_cache_sentinels']` for GitLab to generate the proper configuration files.
@@ -885,8 +885,8 @@ Read more on High Availability:
[reconfigure]: ../restart_gitlab.md#omnibus-gitlab-reconfigure
[gh-531]: https://github.com/redis/redis-rb/issues/531
[gh-534]: https://github.com/redis/redis-rb/issues/534
-[redis]: http://redis.io/
-[sentinel]: http://redis.io/topics/sentinel
+[redis]: https://redis.io/
+[sentinel]: https://redis.io/topics/sentinel
[omnifile]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-cookbooks/gitlab/libraries/gitlab_rails.rb
[source]: ../../install/installation.md
[ce]: https://about.gitlab.com/downloads
diff --git a/doc/administration/high_availability/redis_source.md b/doc/administration/high_availability/redis_source.md
index 8b7a515a076..2101d36d2b6 100644
--- a/doc/administration/high_availability/redis_source.md
+++ b/doc/administration/high_availability/redis_source.md
@@ -24,7 +24,7 @@ the Omnibus Redis HA documentation.
## Configuring your own Redis server
-This is the section where we install and setup the new Redis instances.
+This is the section where we install and set up the new Redis instances.
### Prerequisites
@@ -107,7 +107,7 @@ starting with `sentinel` prefix.
Assuming that the Redis Sentinel is installed on the same instance as Redis
master with IP `10.0.0.1` (some settings might overlap with the master):
-1. [Install Redis Sentinel](http://redis.io/topics/sentinel)
+1. [Install Redis Sentinel](https://redis.io/topics/sentinel)
1. Edit `/etc/redis/sentinel.conf`:
```conf
@@ -204,7 +204,7 @@ In this example we consider that all servers have an internal network
interface with IPs in the `10.0.0.x` range, and that they can connect
to each other using these IPs.
-In a real world usage, you would also setup firewall rules to prevent
+In a real world usage, you would also set up firewall rules to prevent
unauthorized access from other machines, and block traffic from the
outside ([Internet][it]).
@@ -363,7 +363,7 @@ production:
port: 26379 # point to sentinel, not to redis port
```
-When in doubt, please read [Redis Sentinel documentation](http://redis.io/topics/sentinel).
+When in doubt, please read [Redis Sentinel documentation](https://redis.io/topics/sentinel).
[gh-531]: https://github.com/redis/redis-rb/issues/531
[downloads]: https://about.gitlab.com/downloads
diff --git a/doc/administration/img/circuitbreaker_config.png b/doc/administration/img/circuitbreaker_config.png
deleted file mode 100644
index 20233276055..00000000000
--- a/doc/administration/img/circuitbreaker_config.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/img/failing_storage.png b/doc/administration/img/failing_storage.png
deleted file mode 100644
index 652d7dcb5d7..00000000000
--- a/doc/administration/img/failing_storage.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/index.md b/doc/administration/index.md
index 8b6a42b0ca5..6083806af6c 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -47,6 +47,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Enforcing Terms of Service](../user/admin_area/settings/terms.md)
- [Third party offers](../user/admin_area/settings/third_party_offers.md)
- [Compliance](compliance.md): A collection of features from across the application that you may configure to help ensure that your GitLab instance and DevOps workflow meet compliance standards.
+- [Diff limits](../user/admin_area/diff_limits.md): Configure the diff rendering size limits of branch comparison pages.
#### Customizing GitLab's appearance
@@ -60,7 +61,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Raketasks](../raketasks/README.md): Perform various tasks for maintenance, backups, automatic webhooks setup, etc.
- [Backup and restore](../raketasks/backup_restore.md): Backup and restore your GitLab instance.
-- [Operations](operations/index.md): Keeping GitLab up and running (clean up Redis sessions, moving repositories, Sidekiq Job throttling, Sidekiq MemoryKiller, Unicorn).
+- [Operations](operations/index.md): Keeping GitLab up and running (clean up Redis sessions, moving repositories, Sidekiq MemoryKiller, Unicorn).
- [Restart GitLab](restart_gitlab.md): Learn how to restart GitLab and its components.
#### Updating GitLab
@@ -117,10 +118,9 @@ created in snippets, wikis, and repos.
## Continuous Integration settings
- [Enable/disable GitLab CI/CD](../ci/enable_or_disable_ci.md#site-wide-admin-setting): Enable or disable GitLab CI/CD for your instance.
-- [GitLab CI/CD admin settings](../user/admin_area/settings/continuous_integration.md): Define max artifacts size and expiration time.
+- [GitLab CI/CD admin settings](../user/admin_area/settings/continuous_integration.md): Enable or disable Auto DevOps site-wide and define the artifacts' max size and expiration time.
- [Job artifacts](job_artifacts.md): Enable, disable, and configure job artifacts (a set of files and directories which are outputted by a job when it completes successfully).
- [Job traces](job_traces.md): Information about the job traces (logs).
-- [Artifacts size and expiration](../user/admin_area/settings/continuous_integration.md#maximum-artifacts-size): Define maximum artifacts limits and expiration date.
- [Register Shared and specific Runners](../ci/runners/README.md#registering-a-shared-runner): Learn how to register and configure Shared and specific Runners to your own instance.
- [Shared Runners pipelines quota](../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota): Limit the usage of pipeline minutes for Shared Runners.
- [Enable/disable Auto DevOps](../topics/autodevops/index.md#enabling-auto-devops): Enable or disable Auto DevOps for your instance.
@@ -130,6 +130,7 @@ created in snippets, wikis, and repos.
- [Custom Git hooks](custom_hooks.md): Custom Git hooks (on the filesystem) for when webhooks aren't enough.
- [Git LFS configuration](../workflow/lfs/lfs_administration.md): Learn how to configure LFS for GitLab.
- [Housekeeping](housekeeping.md): Keep your Git repositories tidy and fast.
+- [Configuring Git Protocol v2](git_protocol.md): Git protocol version 2 support.
## Monitoring GitLab
diff --git a/doc/administration/integration/koding.md b/doc/administration/integration/koding.md
deleted file mode 100644
index def0add0061..00000000000
--- a/doc/administration/integration/koding.md
+++ /dev/null
@@ -1,246 +0,0 @@
-# Koding & GitLab
-
-> **Notes:**
-> - **As of GitLab 10.0, the Koding integration is deprecated and will be removed
-> in a future version. The option to configure it is removed from GitLab's admin
-> area.**
-> - [Introduced][ce-5909] in GitLab 8.11.
-
-This document will guide you through installing and configuring Koding with
-GitLab.
-
-First of all, to be able to use Koding and GitLab together you will need public
-access to your server. This allows you to use single sign-on from GitLab to
-Koding and using vms from cloud providers like AWS. Koding has a registry for
-VMs, called Kontrol and it runs on the same server as Koding itself, VMs from
-cloud providers register themselves to Kontrol via the agent that we put into
-provisioned VMs. This agent is called Klient and it provides Koding to access
-and manage the target machine.
-
-Kontrol and Klient are based on another technology called
-[Kite](https://github.com/koding/kite), that we have written at Koding. Which is a
-microservice framework that allows you to develop microservices easily.
-
-## Requirements
-
-### Hardware
-
-Minimum requirements are;
-
- - 2 cores CPU
- - 3G RAM
- - 10G Storage
-
-If you plan to use AWS to install Koding it is recommended that you use at
-least a `c3.xlarge` instance.
-
-### Software
-
- - [Git](https://git-scm.com)
- - [Docker](https://www.docker.com)
- - [docker-compose](https://www.docker.com/products/docker-compose)
-
-Koding can run on most of the UNIX based operating systems, since it's shipped
-as containerized with Docker support, it can work on any operating system that
-supports Docker.
-
-Required services are:
-
-- **PostgreSQL** - Kontrol and Service DB provider
-- **MongoDB** - Main DB provider the application
-- **Redis** - In memory DB used by both application and services
-- **RabbitMQ** - Message Queue for both application and services
-
-which are also provided as a Docker container by Koding.
-
-
-## Getting Started with Development Versions
-
-
-### Koding
-
-You can run `docker-compose` environment for developing koding by
-executing commands in the following snippet.
-
-```bash
-git clone https://github.com/koding/koding.git
-cd koding
-docker-compose -f docker-compose-init.yml run init
-docker-compose up
-```
-
-This should start koding on `localhost:8090`.
-
-By default there is no team exists in Koding DB. You'll need to create a team
-called `gitlab` which is the default team name for GitLab integration in the
-configuration. To make things in order it's recommended to create the `gitlab`
-team first thing after setting up Koding.
-
-
-### GitLab
-
-To install GitLab to your environment for development purposes it's recommended
-to use GitLab Development Kit which you can get it from
-[here](https://gitlab.com/gitlab-org/gitlab-development-kit).
-
-After all those steps, gitlab should be running on `localhost:3000`
-
-
-## Integration
-
-Integration includes following components;
-
- - Single Sign On with OAuth from GitLab to Koding
- - System Hook integration for handling GitLab events on Koding
- (`project_created`, `user_joined` etc.)
- - Service endpoints for importing/executing stacks from GitLab to Koding
- (`Run/Try on IDE (Koding)` buttons on GitLab Projects, Issues, MRs)
-
-As it's pointed out before, you will need public access to this machine that
-you've installed Koding and GitLab on. Better to use a domain but a static IP
-is also fine.
-
-For IP based installation you can use [nip.io](https://nip.io) service which is
-free and provides DNS resolution to IP based requests like following;
-
- - 127.0.0.1.nip.io -> resolves to 127.0.0.1
- - foo.bar.baz.127.0.0.1.nip.io -> resolves to 127.0.0.1
- - and so on...
-
-As Koding needs subdomains for team names; `foo.127.0.0.1.nip.io` requests for
-a running koding instance on `127.0.0.1` server will be handled as `foo` team
-requests.
-
-
-### GitLab Side
-
-You need to enable Koding integration from Settings under Admin Area. To do
-that login with an Admin account and do followings;
-
-- open [http://127.0.0.1:3000/admin/application_settings](http://127.0.0.1:3000/admin/application_settings)
-- scroll to bottom of the page until Koding section
-- check `Enable Koding` checkbox
-- provide GitLab team page for running Koding instance as `Koding URL`*
- * For `Koding URL` you need to provide the gitlab integration enabled team on
-your Koding installation. Team called `gitlab` has integration on Koding out
-of the box, so if you didn't change anything your team on Koding should be
-`gitlab`.
-
-So, if your Koding is running on `http://1.2.3.4.nip.io:8090` your URL needs
-to be `http://gitlab.1.2.3.4.nip.io:8090`. You need to provide the same host
-with your Koding installation here.
-
-
-#### Registering Koding for OAuth integration
-
-We need `Application ID` and `Secret` to enable login to Koding via GitLab
-feature and to do that you need to register running Koding as a new application
-to your running GitLab application. Follow
-[these](http://docs.gitlab.com/ce/integration/oauth_provider.html) steps to
-enable this integration.
-
-Redirect URI should be `http://gitlab.127.0.0.1:8090/-/oauth/gitlab/callback`
-which again you need to _replace `127.0.0.1` with your instance public IP._
-
-Take a copy of `Application ID` and `Secret` that is generated by the GitLab
-application, we will need those on _Koding Part_ of this guide.
-
-
-#### Registering system hooks to Koding (optional)
-
-Koding can take actions based on the events generated by GitLab application.
-This feature is still in progress and only following events are processed by
-Koding at the moment;
-
- - user_create
- - user_destroy
-
-All system events are handled but not implemented on Koding side.
-
-To enable this feature you need to provide a `URL` and a `Secret Token` to your
-GitLab application. Open your admin area on your GitLab app from
-[http://127.0.0.1:3000/admin/hooks](http://127.0.0.1:3000/admin/hooks)
-and provide `URL` as `http://gitlab.127.0.0.1:8090/-/api/gitlab` which is the
-endpoint to handle GitLab events on Koding side. Provide a `Secret Token` and
-keep a copy of it, we will need it on _Koding Part_ of this guide.
-
-_(replace `127.0.0.1` with your instance public IP)_
-
-
-### Koding Part
-
-If you followed the steps in GitLab part we should have followings to enable
-Koding part integrations;
-
- - `Application ID` and `Secret` for OAuth integration
- - `Secret Token` for system hook integration
- - Public address of running GitLab instance
-
-
-#### Start Koding with GitLab URL
-
-Now we need to configure Koding with all this information to get things ready.
-If it's already running please stop koding first.
-
-##### From command-line
-
-Replace followings with the ones you got from GitLab part of this guide;
-
-```bash
-cd koding
-docker-compose run \
- --service-ports backend \
- /opt/koding/scripts/bootstrap-container build \
- --host=**YOUR_IP**.nip.io \
- --gitlabHost=**GITLAB_IP** \
- --gitlabPort=**GITLAB_PORT** \
- --gitlabToken=**SECRET_TOKEN** \
- --gitlabAppId=**APPLICATION_ID** \
- --gitlabAppSecret=**SECRET**
-```
-
-##### By updating configuration
-
-Alternatively you can update `gitlab` section on
-`config/credentials.default.coffee` like following;
-
-```
-gitlab =
- host: '**GITLAB_IP**'
- port: '**GITLAB_PORT**'
- applicationId: '**APPLICATION_ID**'
- applicationSecret: '**SECRET**'
- team: 'gitlab'
- redirectUri: ''
- systemHookToken: '**SECRET_TOKEN**'
- hooksEnabled: yes
-```
-
-and start by only providing the `host`;
-
-```bash
-cd koding
-docker-compose run \
- --service-ports backend \
- /opt/koding/scripts/bootstrap-container build \
- --host=**YOUR_IP**.nip.io \
-```
-
-#### Enable Single Sign On
-
-Once you restarted your Koding and logged in with your username and password
-you need to activate oauth authentication for your user. To do that
-
- - Navigate to Dashboard on Koding from;
- `http://gitlab.**YOUR_IP**.nip.io:8090/Home/my-account`
- - Scroll down to Integrations section
- - Click on toggle to turn On integration in GitLab integration section
-
-This will redirect you to your GitLab instance and will ask your permission (
-if you are not logged in to GitLab at this point you will be redirected after
-login) once you accept you will be redirected to your Koding instance.
-
-From now on you can login by using `SIGN IN WITH GITLAB` button on your Login
-screen in your Koding instance.
-
-[ce-5909]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5909
diff --git a/doc/administration/integration/plantuml.md b/doc/administration/integration/plantuml.md
index 293036f2f4b..b61c5409a56 100644
--- a/doc/administration/integration/plantuml.md
+++ b/doc/administration/integration/plantuml.md
@@ -80,10 +80,10 @@ our AsciiDoc snippets, wikis and repos using delimited blocks:
```
[plantuml, format="png", id="myDiagram", width="200px"]
- --
+ ----
Bob->Alice : hello
Alice -> Bob : Go Away
- --
+ ----
```
- **reStructuredText**
diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md
index 757865ea2c5..a1ea78b64bd 100644
--- a/doc/administration/job_artifacts.md
+++ b/doc/administration/job_artifacts.md
@@ -1,12 +1,10 @@
# Jobs artifacts administration
->**Notes:**
->- Introduced in GitLab 8.2 and GitLab Runner 0.7.0.
->- Starting with GitLab 8.4 and GitLab Runner 1.0, the artifacts archive format
- changed to `ZIP`.
->- Starting with GitLab 8.17, builds are renamed to jobs.
->- This is the administration documentation. For the user guide see
- [pipelines/job_artifacts](../user/project/pipelines/job_artifacts.md).
+> **Notes:**
+> - Introduced in GitLab 8.2 and GitLab Runner 0.7.0.
+> - Starting with GitLab 8.4 and GitLab Runner 1.0, the artifacts archive format changed to `ZIP`.
+> - Starting with GitLab 8.17, builds are renamed to jobs.
+> - This is the administration documentation. For the user guide see [pipelines/job_artifacts](../user/project/pipelines/job_artifacts.md).
Artifacts is a list of files and directories which are attached to a job
after it completes successfully. This feature is enabled by default in all
@@ -98,7 +96,7 @@ _The artifacts are stored by default in
If you don't want to use the local disk where GitLab is installed to store the
artifacts, you can use an object storage like AWS S3 instead.
This configuration relies on valid AWS credentials to be configured already.
-Use an [Object storage option][os] like AWS S3 to store job artifacts.
+Use an object storage option like AWS S3 to store job artifacts.
### Object Storage Settings
@@ -315,4 +313,3 @@ memory and disk I/O.
[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
[restart gitlab]: restart_gitlab.md#installations-from-source "How to restart GitLab"
[gitlab workhorse]: https://gitlab.com/gitlab-org/gitlab-workhorse "GitLab Workhorse repository"
-[os]: https://docs.gitlab.com/administration/job_artifacts.html#using-object-storage
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index 98134075b94..698f4caab3a 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -13,7 +13,7 @@ This guide talks about how to read and use these system log files.
This file lives in `/var/log/gitlab/gitlab-rails/production_json.log` for
Omnibus GitLab packages or in `/home/git/gitlab/log/production_json.log` for
-installations from source. (When Gitlab is running in an environment
+installations from source. (When GitLab is running in an environment
other than production, the corresponding logfile is shown here.)
It contains a structured log for Rails controller requests received from
@@ -29,9 +29,9 @@ Each line contains a JSON line that can be ingested by Elasticsearch, Splunk, et
In this example, you can see this was a GET request for a specific issue. Notice each line also contains performance data:
1. `duration`: the total time taken to retrieve the request
-2. `view`: total time taken inside the Rails views
-3. `db`: total time to retrieve data from the database
-4. `gitaly_calls`: total number of calls made to Gitaly
+1. `view`: total time taken inside the Rails views
+1. `db`: total time to retrieve data from the database
+1. `gitaly_calls`: total number of calls made to Gitaly
User clone/fetch activity using http transport appears in this log as `action: git_upload_pack`.
@@ -42,7 +42,7 @@ In addition, the log contains the IP address from which the request originated
This file lives in `/var/log/gitlab/gitlab-rails/production.log` for
Omnibus GitLab packages or in `/home/git/gitlab/log/production.log` for
-installations from source. (When Gitlab is running in an environment
+installations from source. (When GitLab is running in an environment
other than production, the corresponding logfile is shown here.)
It contains information about all performed requests. You can see the
@@ -84,7 +84,7 @@ Introduced in GitLab 10.0, this file lives in
It helps you see requests made directly to the API. For example:
```json
-{"time":"2017-10-10T12:30:11.579Z","severity":"INFO","duration":16.84,"db":1.57,"view":15.27,"status":200,"method":"POST","path":"/api/v4/internal/allowed","params":{"action":"git-upload-pack","changes":"_any","gl_repository":null,"project":"root/foobar.git","protocol":"ssh","env":"{}","key_id":"[FILTERED]","secret_token":"[FILTERED]"},"host":"127.0.0.1","ip":"127.0.0.1","ua":"Ruby"}
+{"time":"2018-10-29T12:49:42.123Z","severity":"INFO","duration":709.08,"db":14.59,"view":694.49,"status":200,"method":"GET","path":"/api/v4/projects","params":[{"key":"action","value":"git-upload-pack"},{"key":"changes","value":"_any"},{"key":"key_id","value":"secret"},{"key":"secret_token","value":"[FILTERED]"}],"host":"localhost","ip":"::1","ua":"Ruby","route":"/api/:version/projects","user_id":1,"username":"root","queue_duration":100.31,"gitaly_calls":30}
```
This entry above shows an access to an internal endpoint to check whether an
@@ -119,13 +119,32 @@ This file lives in `/var/log/gitlab/gitlab-rails/integrations_json.log` for
Omnibus GitLab packages or in `/home/git/gitlab/log/integrations_json.log` for
installations from source.
-It contains information about [integrations](../user/project/integrations/project_services.md) activities such as JIRA, Asana and Irker services. It uses JSON format like the example below:
+It contains information about [integrations](../user/project/integrations/project_services.md) activities such as JIRA, Asana and Irker services. It uses JSON format like the example below:
``` json
{"severity":"ERROR","time":"2018-09-06T14:56:20.439Z","service_class":"JiraService","project_id":8,"project_path":"h5bp/html5-boilerplate","message":"Error sending message","client_url":"http://jira.gitlap.com:8080","error":"execution expired"}
{"severity":"INFO","time":"2018-09-06T17:15:16.365Z","service_class":"JiraService","project_id":3,"project_path":"namespace2/project2","message":"Successfully posted","client_url":"http://jira.example.net"}
```
+## `kubernetes.log`
+
+Introduced in GitLab 11.6. This file lives in
+`/var/log/gitlab/gitlab-rails/kubernetes.log` for Omnibus GitLab
+packages or in `/home/git/gitlab/log/kubernetes.log` for
+installations from source.
+
+It logs information related to the Kubernetes Integration including errors
+during installing cluster applications on your GitLab managed Kubernetes
+clusters.
+
+Each line contains a JSON line that can be ingested by Elasticsearch, Splunk,
+etc. For example:
+
+```json
+{"severity":"ERROR","time":"2018-11-23T15:14:54.652Z","exception":"Kubeclient::HttpError","error_code":401,"service":"Clusters::Applications::CheckInstallationProgressService","app_id":14,"project_ids":[1],"group_ids":[],"message":"Unauthorized"}
+{"severity":"ERROR","time":"2018-11-23T15:42:11.647Z","exception":"Kubeclient::HttpError","error_code":null,"service":"Clusters::Applications::InstallService","app_id":2,"project_ids":[19],"group_ids":[],"message":"SSL_connect returned=1 errno=0 state=error: certificate verify failed (unable to get local issuer certificate)"}
+```
+
## `githost.log`
This file lives in `/var/log/gitlab/gitlab-rails/githost.log` for
@@ -144,6 +163,20 @@ December 03, 2014 13:20 -> ERROR -> Command failed [1]: /usr/bin/git --git-dir=/
error: failed to push some refs to '/Users/vsizov/gitlab-development-kit/repositories/gitlabhq/gitlab_git.git'
```
+## `audit_json.log`
+
+This file lives in `/var/log/gitlab/gitlab-rails/audit_json.log` for
+Omnibus GitLab packages or in `/home/git/gitlab/log/audit_json.log` for
+installations from source.
+
+Changes to group or project settings are logged to this file. For example:
+
+```json
+{"severity":"INFO","time":"2018-10-17T17:38:22.523Z","author_id":3,"entity_id":2,"entity_type":"Project","change":"visibility","from":"Private","to":"Public","author_name":"John Doe4","target_id":2,"target_type":"Project","target_details":"namespace2/project2"}
+{"severity":"INFO","time":"2018-10-17T17:38:22.830Z","author_id":5,"entity_id":3,"entity_type":"Project","change":"name","from":"John Doe7 / project3","to":"John Doe7 / new name","author_name":"John Doe6","target_id":3,"target_type":"Project","target_details":"namespace3/project3"}
+{"severity":"INFO","time":"2018-10-17T17:38:23.175Z","author_id":7,"entity_id":4,"entity_type":"Project","change":"path","from":"","to":"namespace4/newpath","author_name":"John Doe8","target_id":4,"target_type":"Project","target_details":"namespace4/newpath"}
+```
+
## `sidekiq.log`
This file lives in `/var/log/gitlab/gitlab-rails/sidekiq.log` for
@@ -187,7 +220,7 @@ This file lives in `/var/log/gitlab/gitlab-shell/gitlab-shell.log` for
Omnibus GitLab packages or in `/home/git/gitlab-shell/gitlab-shell.log` for
installations from source.
-GitLab shell is used by Gitlab for executing Git commands and provide
+GitLab shell is used by GitLab for executing Git commands and provide
SSH access to Git repositories. For example:
```
@@ -243,8 +276,8 @@ importer. Future importers may use this file.
## Reconfigure Logs
-Reconfigure log files live in `/var/log/gitlab/reconfigure` for Omnibus GitLab
-packages. Installations from source don't have reconfigure logs. A reconfigure log
+Reconfigure log files live in `/var/log/gitlab/reconfigure` for Omnibus GitLab
+packages. Installations from source don't have reconfigure logs. A reconfigure log
is populated whenever `gitlab-ctl reconfigure` is run manually or as part of an upgrade.
Reconfigure logs files are named according to the UNIX timestamp of when the reconfigure
diff --git a/doc/administration/monitoring/performance/img/request_profiling_token.png b/doc/administration/monitoring/performance/img/request_profiling_token.png
index 8c4109c17f0..a9160b62acb 100644
--- a/doc/administration/monitoring/performance/img/request_profiling_token.png
+++ b/doc/administration/monitoring/performance/img/request_profiling_token.png
Binary files differ
diff --git a/doc/administration/monitoring/performance/influxdb_configuration.md b/doc/administration/monitoring/performance/influxdb_configuration.md
index c30cd2950d8..fa281f47ed8 100644
--- a/doc/administration/monitoring/performance/influxdb_configuration.md
+++ b/doc/administration/monitoring/performance/influxdb_configuration.md
@@ -95,10 +95,10 @@ UDP can be done using the following settings:
This does the following:
1. Enable UDP and bind it to port 8089 for all addresses.
-2. Store any data received in the "gitlab" database.
-3. Define a batch of points to be 1000 points in size and allow a maximum of
+1. Store any data received in the "gitlab" database.
+1. Define a batch of points to be 1000 points in size and allow a maximum of
5 batches _or_ flush them automatically after 1 second.
-4. Define a UDP read buffer size of 200 MB.
+1. Define a UDP read buffer size of 200 MB.
One of the most important settings here is the UDP read buffer size as if this
value is set too low, packets will be dropped. You must also make sure the OS
diff --git a/doc/administration/monitoring/performance/performance_bar.md b/doc/administration/monitoring/performance/performance_bar.md
index dc4f685d843..6a55dbe1eb4 100644
--- a/doc/administration/monitoring/performance/performance_bar.md
+++ b/doc/administration/monitoring/performance/performance_bar.md
@@ -26,8 +26,8 @@ page was open. Only the first two requests per unique URL are captured.
## Enable the Performance Bar via the Admin panel
GitLab Performance Bar is disabled by default. To enable it for a given group,
-navigate to the Admin area in **Settings > Profiling - Performance Bar**
-(`/admin/application_settings`).
+navigate to the Admin area in **Settings > Metrics and Profiling > Profiling - Performance bar**
+(`admin/application_settings/metrics_and_profiling`).
The only required setting you need to set is the full path of the group that
will be allowed to display the Performance Bar.
diff --git a/doc/administration/monitoring/performance/request_profiling.md b/doc/administration/monitoring/performance/request_profiling.md
index c358dfbead2..dfd9be3d04c 100644
--- a/doc/administration/monitoring/performance/request_profiling.md
+++ b/doc/administration/monitoring/performance/request_profiling.md
@@ -1,16 +1,17 @@
# Request Profiling
## Procedure
+
1. Grab the profiling token from `Monitoring > Requests Profiles` admin page
-(highlighted in a blue in the image below).
-![Profile token](img/request_profiling_token.png)
-1. Pass the header `X-Profile-Token: <token>` to the request you want to profile. You can use any of these tools
- * [ModHeader](https://chrome.google.com/webstore/detail/modheader/idgpnmonknjnojddfkpgkljpfnnfcklj) Chrome extension
- * [Modify Headers](https://addons.mozilla.org/en-US/firefox/addon/modify-headers/) Firefox extension
- * `curl --header 'X-Profile-Token: <token>' https://gitlab.example.com/group/project`
+ (highlighted in a blue in the image below).
+ ![Profile token](img/request_profiling_token.png)
+1. Pass the header `X-Profile-Token: <token>` to the request you want to profile. You can use:
+ - Browser extensions. For example, [ModHeader](https://chrome.google.com/webstore/detail/modheader/idgpnmonknjnojddfkpgkljpfnnfcklj) Chrome extension.
+ - `curl`. For example, `curl --header 'X-Profile-Token: <token>' https://gitlab.example.com/group/project`.
1. Once request is finished (which will take a little longer than usual), you can
-view the profiling output from `Monitoring > Requests Profiles` admin page.
-![Profiling output](img/request_profile_result.png)
+ view the profiling output from `Monitoring > Requests Profiles` admin page.
+ ![Profiling output](img/request_profile_result.png)
## Cleaning up
+
Profiling output will be cleared out every day via a Sidekiq worker.
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index 7bc92ae77ee..c9a2778b3a4 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -45,9 +45,7 @@ The following metrics are available:
| redis_ping_success | Gauge | 9.4 | Whether or not the last redis ping succeeded |
| redis_ping_latency_seconds | Gauge | 9.4 | Round trip time of the redis ping |
| user_session_logins_total | Counter | 9.4 | Counter of how many users have logged in |
-| filesystem_circuitbreaker_latency_seconds | Gauge | 9.5 | Time spent validating if a storage is accessible |
-| filesystem_circuitbreaker | Gauge | 9.5 | Whether or not the circuit for a certain shard is broken or not |
-| circuitbreaker_storage_check_duration_seconds | Histogram | 10.3 | Time a single storage probe took |
+| upload_file_does_not_exist | Counter | 10.7 in EE, 11.5 in CE | Number of times an upload record could not find its file |
| failed_login_captcha_total | Gauge | 11.0 | Counter of failed CAPTCHA attempts during login |
| successful_login_captcha_total | Gauge | 11.0 | Counter of successful CAPTCHA attempts during login |
diff --git a/doc/administration/monitoring/prometheus/index.md b/doc/administration/monitoring/prometheus/index.md
index b1b670c3b42..8f65cd6418c 100644
--- a/doc/administration/monitoring/prometheus/index.md
+++ b/doc/administration/monitoring/prometheus/index.md
@@ -1,4 +1,4 @@
-# GitLab Prometheus
+# Monitoring GitLab with Prometheus
> **Notes:**
> - Prometheus and the various exporters listed in this page are bundled in the
@@ -24,10 +24,10 @@ dashboard tool like [Grafana].
## Configuring Prometheus
->**Note:**
+NOTE: **Note:**
For installations from source you'll have to install and configure it yourself.
-Prometheus and it's exporters are on by default, starting with GitLab 9.0.
+Prometheus and its exporters are on by default, starting with GitLab 9.0.
Prometheus will run as the `gitlab-prometheus` user and listen on
`http://localhost:9090`. By default Prometheus is only accessible from the GitLab server itself.
Each exporter will be automatically set up as a
@@ -43,17 +43,17 @@ To disable Prometheus and all of its exporters, as well as any added in the futu
```
1. Save the file and [reconfigure GitLab][reconfigure] for the changes to
- take effect
+ take effect.
-## Changing the port and address Prometheus listens on
+### Changing the port and address Prometheus listens on
->**Note:**
+NOTE: **Note:**
The following change was added in [GitLab Omnibus 8.17][1261]. Although possible,
it's not recommended to change the port Prometheus listens
on as this might affect or conflict with other services running on the GitLab
server. Proceed at your own risk.
-In order to access Prometheus from outside the GitLab server you will need to
+In order to access Prometheus from outside the GitLab server you will need to
set a FQDN or IP in `prometheus['listen_address']`.
To change the address/port that Prometheus listens on:
@@ -77,6 +77,60 @@ To change the address/port that Prometheus listens on:
1. Save the file and [reconfigure GitLab][reconfigure] for the changes to
take effect
+### Using an external Prometheus server
+
+NOTE: **Note:**
+Prometheus and most exporters do not support authentication. We do not recommend exposing them outside the local network.
+
+A few configuration changes are required to allow GitLab to be monitored by an external Prometheus server. External servers are recommended for highly available deployments of GitLab with multiple nodes.
+
+To use an external Prometheus server:
+
+1. Edit `/etc/gitlab/gitlab.rb`.
+1. Disable the bundled Prometheus:
+
+ ```ruby
+ prometheus['enable'] = false
+ ```
+
+1. Set each bundled service's [exporter](#bundled-software-metrics) to listen on a network address, for example:
+
+ ```ruby
+ gitlab_monitor['listen_address'] = '0.0.0.0'
+ gitlab_monitor['listen_port'] = '9168'
+ gitaly['prometheus_listen_addr'] = "0.0.0.0:9236"
+ node_exporter['listen_address'] = '0.0.0.0:9100'
+ redis_exporter['listen_address'] = '0.0.0.0:9121'
+ postgres_exporter['listen_address'] = '0.0.0.0:9187'
+ ```
+
+1. Install and set up a dedicated Prometheus instance, if necessary, using the [official installation instructions](https://prometheus.io/docs/prometheus/latest/installation/).
+1. Add the Prometheus server IP address to the [monitoring IP whitelist](../ip_whitelist.html). For example:
+
+ ```ruby
+ gitlab_rails['monitoring_whitelist'] = ['127.0.0.0/8', '192.168.0.1']
+ ```
+
+1. [Reconfigure GitLab][reconfigure] to apply the changes
+1. Edit the Prometheus server's configuration file.
+1. Add each node's exporters to the Prometheus server's
+ [scrape target configuration](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#%3Cscrape_config%3E).
+ For example, a sample snippet using `static_configs`:
+
+ ```yaml
+ scrape_configs:
+ - job_name: 'gitlab_exporters'
+ static_configs:
+ - targets: ['1.1.1.1:9168', '1.1.1.1:9236', '1.1.1.1:9236', '1.1.1.1:9100', '1.1.1.1:9121', '1.1.1.1:9187']
+
+ - job_name: 'gitlab_metrics'
+ metrics_path: /-/metrics
+ static_configs:
+ - targets: ['1.1.1.1:443']
+ ```
+
+1. Restart the Prometheus server.
+
## Viewing performance metrics
You can visit `http://localhost:9090` for the dashboard that Prometheus offers by default.
@@ -86,7 +140,7 @@ If SSL has been enabled on your GitLab instance, you may not be able to access
Prometheus on the same browser as GitLab if using the same FQDN due to [HSTS][hsts]. We plan to
[provide access via GitLab][multi-user-prometheus], but in the interim there are
some workarounds: using a separate FQDN, using server IP, using a separate browser for Prometheus, resetting HSTS, or
-having [Nginx proxy it][nginx-custom-config].
+having [NGINX proxy it][nginx-custom-config].
The performance data collected by Prometheus can be viewed directly in the
Prometheus console or through a compatible dashboard tool.
@@ -102,26 +156,21 @@ Sample Prometheus queries:
- **Data transmitted:** `rate(node_network_transmit_bytes_total{device!="lo"}[5m])`
- **Data received:** `rate(node_network_receive_bytes_total{device!="lo"}[5m])`
-## Configuring Prometheus to monitor Kubernetes
+## Prometheus as a Grafana data source
-> Introduced in GitLab 9.0.
-> Pod monitoring introduced in GitLab 9.4.
+Grafana allows you to import Prometheus performance metrics as a data source
+and render the metrics as graphs and dashboards which is helpful with visualisation.
-If your GitLab server is running within Kubernetes, Prometheus will collect metrics from the Nodes and [annotated Pods](https://prometheus.io/docs/operating/configuration/#kubernetes_sd_config) in the cluster, including performance data on each container. This is particularly helpful if your CI/CD environments run in the same cluster, as you can use the [Prometheus project integration][] to monitor them.
+To add a Prometheus dashboard for a single server GitLab setup:
-To disable the monitoring of Kubernetes:
+1. Create a new data source in Grafana.
+1. Name your data source i.e GitLab.
+1. Select `Prometheus` in the type drop down.
+1. Add your Prometheus listen address as the URL and set access to `Browser`.
+1. Set the HTTP method to `GET`.
+1. Save & Test your configuration to verify that it works.
-1. Edit `/etc/gitlab/gitlab.rb`
-1. Add or find and uncomment the following line and set it to `false`:
-
- ```ruby
- prometheus['monitor_kubernetes'] = false
- ```
-
-1. Save the file and [reconfigure GitLab][reconfigure] for the changes to
- take effect
-
-## GitLab Prometheus metrics
+## GitLab metrics
> Introduced in GitLab 9.3.
@@ -129,17 +178,10 @@ GitLab monitors its own internal service metrics, and makes them available at th
[âž” Read more about the GitLab Metrics.](gitlab_metrics.md)
-## Prometheus exporters
-
-There are a number of libraries and servers which help in exporting existing
-metrics from third-party systems as Prometheus metrics. This is useful for cases
-where it is not feasible to instrument a given system with Prometheus metrics
-directly (for example, HAProxy or Linux system stats). You can read more in the
-[Prometheus exporters and integrations upstream documentation][prom-exporters].
+## Bundled software metrics
-While you can use any exporter you like with your GitLab installation, the
-following ones documented here are bundled in the Omnibus GitLab packages
-making it easy to configure and use.
+Many of the GitLab dependencies bundled in Omnibus GitLab are preconfigured to
+export Prometheus metrics.
### Node exporter
@@ -166,6 +208,25 @@ The GitLab monitor exporter allows you to measure various GitLab metrics, pulled
[âž” Read more about the GitLab monitor exporter.](gitlab_monitor_exporter.md)
+## Configuring Prometheus to monitor Kubernetes
+
+> Introduced in GitLab 9.0.
+> Pod monitoring introduced in GitLab 9.4.
+
+If your GitLab server is running within Kubernetes, Prometheus will collect metrics from the Nodes and [annotated Pods](https://prometheus.io/docs/operating/configuration/#kubernetes_sd_config) in the cluster, including performance data on each container. This is particularly helpful if your CI/CD environments run in the same cluster, as you can use the [Prometheus project integration][prometheus integration] to monitor them.
+
+To disable the monitoring of Kubernetes:
+
+1. Edit `/etc/gitlab/gitlab.rb`.
+1. Add or find and uncomment the following line and set it to `false`:
+
+ ```ruby
+ prometheus['monitor_kubernetes'] = false
+ ```
+
+1. Save the file and [reconfigure GitLab][reconfigure] for the changes to
+ take effect.
+
[grafana]: https://grafana.net
[hsts]: https://en.wikipedia.org/wiki/HTTP_Strict_Transport_Security
[multi-user-prometheus]: https://gitlab.com/gitlab-org/multi-user-prometheus
diff --git a/doc/administration/operations/fast_ssh_key_lookup.md b/doc/administration/operations/fast_ssh_key_lookup.md
index eada7b19dcd..c293df3fc57 100644
--- a/doc/administration/operations/fast_ssh_key_lookup.md
+++ b/doc/administration/operations/fast_ssh_key_lookup.md
@@ -5,7 +5,7 @@ NOTE: **Note:** This document describes a drop-in replacement for the
using [ssh certificates](ssh_certificates.md), they are even faster,
but are not a drop-in replacement.
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/1631) in
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/1631) in
> [GitLab Starter](https://about.gitlab.com/gitlab-ee) 9.3.
>
> [Available in](https://gitlab.com/gitlab-org/gitlab-ee/issues/3953) GitLab
@@ -109,7 +109,7 @@ the database. The following instructions can be used to build OpenSSH 7.5:
yum install rpm-build gcc make wget openssl-devel krb5-devel pam-devel libX11-devel xmkmf libXt-devel
```
-3. Prepare the build by copying files to the right place:
+1. Prepare the build by copying files to the right place:
```
mkdir -p /root/rpmbuild/{SOURCES,SPECS}
@@ -118,7 +118,7 @@ the database. The following instructions can be used to build OpenSSH 7.5:
cd /root/rpmbuild/SPECS
```
-3. Next, set the spec settings properly:
+1. Next, set the spec settings properly:
```
sed -i -e "s/%define no_gnome_askpass 0/%define no_gnome_askpass 1/g" openssh.spec
@@ -126,13 +126,13 @@ the database. The following instructions can be used to build OpenSSH 7.5:
sed -i -e "s/BuildPreReq/BuildRequires/g" openssh.spec
```
-3. Build the RPMs:
+1. Build the RPMs:
```
rpmbuild -bb openssh.spec
```
-4. Ensure the RPMs were built:
+1. Ensure the RPMs were built:
```
ls -al /root/rpmbuild/RPMS/x86_64/
@@ -150,7 +150,7 @@ the database. The following instructions can be used to build OpenSSH 7.5:
-rw-r--r--. 1 root root 367516 Jun 20 19:37 openssh-server-7.5p1-1.x86_64.rpm
```
-5. Install the packages. OpenSSH packages will replace `/etc/pam.d/sshd`
+1. Install the packages. OpenSSH packages will replace `/etc/pam.d/sshd`
with its own version, which may prevent users from logging in, so be sure
that the file is backed up and restored after installation:
@@ -161,7 +161,7 @@ the database. The following instructions can be used to build OpenSSH 7.5:
yes | cp pam-ssh-conf-$timestamp /etc/pam.d/sshd
```
-6. Verify the installed version. In another window, attempt to login to the server:
+1. Verify the installed version. In another window, attempt to login to the server:
```
ssh -v <your-centos-machine>
@@ -171,7 +171,7 @@ the database. The following instructions can be used to build OpenSSH 7.5:
If not, you may need to restart sshd (e.g. `systemctl restart sshd.service`).
-7. *IMPORTANT!* Open a new SSH session to your server before exiting to make
+1. *IMPORTANT!* Open a new SSH session to your server before exiting to make
sure everything is working! If you need to downgrade, simple install the
older package:
diff --git a/doc/administration/operations/filesystem_benchmarking.md b/doc/administration/operations/filesystem_benchmarking.md
new file mode 100644
index 00000000000..44018e966e0
--- /dev/null
+++ b/doc/administration/operations/filesystem_benchmarking.md
@@ -0,0 +1,55 @@
+# Filesystem Performance Benchmarking
+
+Filesystem performance has a big impact on overall GitLab performance,
+especially for actions that read or write to Git repositories. This information
+will help benchmark filesystem performance against known good and bad real-world
+systems.
+
+Normally when talking about filesystem performance the biggest concern is
+with Network Filesystems (NFS). However, even some local disks can have slow
+IO. The information on this page can be used for either scenario.
+
+## Write Performance
+
+The following one-line command is a quick benchmark for filesystem write
+performance. This will write 1,000 small files to the directory in which it is
+executed.
+
+1. Change into the root of the appropriate
+ [repository storage path](../repository_storage_paths.md).
+1. Create a temporary directory for the test so it's easy to remove the files later:
+
+ ```sh
+ mkdir test; cd test
+ ```
+1. Run the command:
+
+ ```sh
+ time for i in {0..1000}; do echo 'test' > "test${i}.txt"; done
+ ```
+1. Remove the test files:
+
+ ```sh
+ cd ../; rm -rf test
+ ```
+
+The output of the `time for ...` command will look similar to the following. The
+important metric is the `real` time.
+
+```sh
+$ time for i in {0..1000}; do echo 'test' > "test${i}.txt"; done
+
+real 0m0.116s
+user 0m0.025s
+sys 0m0.091s
+```
+
+From experience with multiple customers, the following are ranges that indicate
+whether your filesystem performance is satisfactory or less than ideal:
+
+| Rating | Benchmark result |
+|:----------|:------------------------|
+| Best | Less than 10 seconds |
+| OK | 10-18 seconds |
+| Poor | 18-25 seconds |
+| Very poor | Greater than 25 seconds |
diff --git a/doc/administration/operations/img/sidekiq_job_throttling.png b/doc/administration/operations/img/sidekiq_job_throttling.png
deleted file mode 100644
index abd09f3b115..00000000000
--- a/doc/administration/operations/img/sidekiq_job_throttling.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/operations/index.md b/doc/administration/operations/index.md
index e9cad99c4b0..a16fc7ae74f 100644
--- a/doc/administration/operations/index.md
+++ b/doc/administration/operations/index.md
@@ -9,8 +9,6 @@ GitLab 7.3 we recommend cleaning up stale sessions to compact the Redis
database after you upgrade to GitLab 7.3.
- [Moving repositories](moving_repositories.md): Moving all repositories managed
by GitLab to another file system or another server.
-- [Sidekiq job throttling](sidekiq_job_throttling.md): Throttle Sidekiq queues
-that to prioritize important jobs.
- [Sidekiq MemoryKiller](sidekiq_memory_killer.md): Configure Sidekiq MemoryKiller
to restart Sidekiq.
- [Unicorn](unicorn.md): Understand Unicorn and unicorn-worker-killer.
@@ -18,3 +16,7 @@ to restart Sidekiq.
indexed lookup to the GitLab database](fast_ssh_key_lookup.md), and/or
by [doing away with user SSH keys stored on GitLab entirely in favor
of SSH certificates](ssh_certificates.md).
+- [Filesystem Performance Benchmarking](filesystem_benchmarking.md): Filesystem
+performance can have a big impact on GitLab performance, especially for actions
+that read or write Git repositories. This information will help benchmark
+filesystem performance against known good and bad real-world systems.
diff --git a/doc/administration/operations/moving_repositories.md b/doc/administration/operations/moving_repositories.md
index 54adb99386a..ec11a92db1b 100644
--- a/doc/administration/operations/moving_repositories.md
+++ b/doc/administration/operations/moving_repositories.md
@@ -22,9 +22,8 @@ However, it is not possible to resume an interrupted tar pipe: if
that happens then all data must be copied again.
```
-# As the git user
-tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\
- tar -C /mnt/gitlab/repositories -xf -
+sudo -u git sh -c 'tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\
+ tar -C /mnt/gitlab/repositories -xf -'
```
If you want to see progress, replace `-xf` with `-xvf`.
@@ -36,9 +35,8 @@ You can also use a tar pipe to copy data to another server. If your
can pipe the data through SSH.
```
-# As the git user
-tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\
- ssh git@newserver tar -C /mnt/gitlab/repositories -xf -
+sudo -u git sh -c 'tar -C /var/opt/gitlab/git-data/repositories -cf - -- . |\
+ ssh git@newserver tar -C /mnt/gitlab/repositories -xf -'
```
If you want to compress the data before it goes over the network
@@ -53,9 +51,8 @@ is either already installed on your system or easily installable
via apt, yum etc.
```
-# As the 'git' user
-rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
- /mnt/gitlab/repositories
+sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
+ /mnt/gitlab/repositories'
```
The `/.` in the command above is very important, without it you can
@@ -68,9 +65,8 @@ If the 'git' user on your source system has SSH access to the target
server you can send the repositories over the network with rsync.
```
-# As the 'git' user
-rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
- git@newserver:/mnt/gitlab/repositories
+sudo -u git sh -c 'rsync -a --delete /var/opt/gitlab/git-data/repositories/. \
+ git@newserver:/mnt/gitlab/repositories'
```
## Thousands of Git repositories: use one rsync per repository
@@ -125,7 +121,7 @@ sudo -u git -H sh -c 'bundle exec rake gitlab:list_repos > /home/git/transfer-lo
Now we can start the transfer. The command below is idempotent, and
the number of jobs done by GNU Parallel should converge to zero. If it
-does not some repositories listed in all-repos-1234.txt may have been
+does not, some repositories listed in `all-repos-1234.txt` may have been
deleted/renamed before they could be copied.
```
@@ -155,8 +151,8 @@ cat /home/git/transfer-logs/* | sort | uniq -u |\
Suppose you have already done one sync that started after 2015-10-1 12:00 UTC.
Then you might only want to sync repositories that were changed via GitLab
-_after_ that time. You can use the 'SINCE' variable to tell 'rake
-gitlab:list_repos' to only print repositories with recent activity.
+_after_ that time. You can use the `SINCE` variable to tell `rake
+gitlab:list_repos` to only print repositories with recent activity.
```
# Omnibus
diff --git a/doc/administration/operations/sidekiq_job_throttling.md b/doc/administration/operations/sidekiq_job_throttling.md
deleted file mode 100644
index ddeaa22e288..00000000000
--- a/doc/administration/operations/sidekiq_job_throttling.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# Sidekiq Job throttling
-
-> Note: Introduced with GitLab 8.14
-
-When your GitLab installation needs to handle tens of thousands of background
-jobs, it can be convenient to throttle queues that do not need to be executed
-immediately, e.g. long running jobs like Pipelines, thus allowing jobs that do
-need to be executed immediately to have access to more resources.
-
-In order to accomplish this, you can limit the amount of workers that certain
-slow running queues can have available. This is what we call Sidekiq Job
-Throttling. Depending on your infrastructure, you might have different slow
-running queues, which is why you can choose which queues you want to throttle
-and by how much you want to throttle them.
-
-These settings are available in the Application Settings of your GitLab
-installation.
-
-![Sidekiq Job Throttling](img/sidekiq_job_throttling.png)
-
-The throttle factor determines the maximum number of workers a queue can run on.
-This value gets multiplied by `:concurrency` value set in the Sidekiq settings
-and rounded up to the closest full integer.
-
-So, for example, you set the `:concurrency` to 25 and the `Throttling factor` to
-0.1, the maximum workers assigned to the selected queues would be 3.
-
-```ruby
-queue_limit = (factor * Sidekiq.options[:concurrency]).ceil
-```
-
-After enabling the job throttling, you will need to restart your GitLab
-instance, in order for the changes to take effect. \ No newline at end of file
diff --git a/doc/administration/operations/ssh_certificates.md b/doc/administration/operations/ssh_certificates.md
index 9edccd25ced..b00301fec1c 100644
--- a/doc/administration/operations/ssh_certificates.md
+++ b/doc/administration/operations/ssh_certificates.md
@@ -31,7 +31,7 @@ uploading user SSH keys to GitLab entirely.
## Setting up SSH certificate lookup via GitLab Shell
-How to fully setup SSH certificates is outside the scope of this
+How to fully set up SSH certificates is outside the scope of this
document. See [OpenSSH's
PROTOCOL.certkeys](https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?annotate=HEAD)
for how it works, and e.g. [RedHat's documentation about
@@ -132,7 +132,7 @@ message about this being an invalid user.
## Interaction with the `authorized_keys` file
SSH certificates can be used in conjunction with the `authorized_keys`
-file, and if setup as configured above the `authorized_keys` file will
+file, and if set up as configured above the `authorized_keys` file will
still serve as a fallback.
This is because if the `AuthorizedPrincipalsCommand` can't
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index 3af0a5759a7..cbd3032bd4e 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -92,9 +92,8 @@ where `example.io` is the domain under which GitLab Pages will be served
and `192.0.2.1` is the IPv4 address of your GitLab instance and `2001::1` is the
IPv6 address. If you don't have IPv6, you can omit the AAAA record.
-> **Note:**
-You should not use the GitLab domain to serve user pages. For more information
-see the [security section](#security).
+NOTE: **Note:**
+You should not use the GitLab domain to serve user pages. For more information see the [security section](#security).
[wiki-wildcard-dns]: https://en.wikipedia.org/wiki/Wildcard_DNS_record
@@ -107,12 +106,13 @@ since that is needed in all configurations.
### Wildcard domains
-> **Requirements:**
-> - [Wildcard DNS setup](#dns-configuration)
->
-> ---
->
-> URL scheme: `http://page.example.io`
+**Requirements:**
+
+- [Wildcard DNS setup](#dns-configuration)
+
+---
+
+URL scheme: `http://page.example.io`
This is the minimum setup that you can use Pages with. It is the base for all
other setups as described below. Nginx will proxy all requests to the daemon.
@@ -126,18 +126,18 @@ The Pages daemon doesn't listen to the outside world.
1. [Reconfigure GitLab][reconfigure]
-
Watch the [video tutorial][video-admin] for this configuration.
### Wildcard domains with TLS support
-> **Requirements:**
-> - [Wildcard DNS setup](#dns-configuration)
-> - Wildcard TLS certificate
->
-> ---
->
-> URL scheme: `https://page.example.io`
+**Requirements:**
+
+- [Wildcard DNS setup](#dns-configuration)
+- Wildcard TLS certificate
+
+---
+
+URL scheme: `https://page.example.io`
Nginx will proxy all requests to the daemon. Pages daemon doesn't listen to the
outside world.
@@ -168,13 +168,14 @@ you have IPv6 as well as IPv4 addresses, you can use them both.
### Custom domains
-> **Requirements:**
-> - [Wildcard DNS setup](#dns-configuration)
-> - Secondary IP
->
-> ---
->
-> URL scheme: `http://page.example.io` and `http://domain.com`
+**Requirements:**
+
+- [Wildcard DNS setup](#dns-configuration)
+- Secondary IP
+
+---
+
+URL scheme: `http://page.example.io` and `http://domain.com`
In that case, the Pages daemon is running, Nginx still proxies requests to
the daemon but the daemon is also able to receive requests from the outside
@@ -197,14 +198,15 @@ world. Custom domains are supported, but no TLS.
### Custom domains with TLS support
-> **Requirements:**
-> - [Wildcard DNS setup](#dns-configuration)
-> - Wildcard TLS certificate
-> - Secondary IP
->
-> ---
->
-> URL scheme: `https://page.example.io` and `https://domain.com`
+**Requirements:**
+
+- [Wildcard DNS setup](#dns-configuration)
+- Wildcard TLS certificate
+- Secondary IP
+
+---
+
+URL scheme: `https://page.example.io` and `https://domain.com`
In that case, the Pages daemon is running, Nginx still proxies requests to
the daemon but the daemon is also able to receive requests from the outside
@@ -240,6 +242,35 @@ verification requirement. Navigate to `Admin area âž” Settings` and uncheck
**Require users to prove ownership of custom domains** in the Pages section.
This setting is enabled by default.
+### Access control
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/33422) in GitLab 11.5.
+
+GitLab Pages access control can be configured per-project, and allows access to a Pages
+site to be controlled based on a user's membership to that project.
+
+Access control works by registering the Pages daemon as an OAuth application
+with GitLab. Whenever a request to access a private Pages site is made by an
+unauthenticated user, the Pages daemon redirects the user to GitLab. If
+authentication is successful, the user is redirected back to Pages with a token,
+which is persisted in a cookie. The cookies are signed with a secret key, so
+tampering can be detected.
+
+Each request to view a resource in a private site is authenticated by Pages
+using that token. For each request it receives, it makes a request to the GitLab
+API to check that the user is authorized to read that site.
+
+Pages access control is disabled by default. To enable it:
+
+1. Enable it in `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_pages['access_control'] = true
+ ```
+
+1. [Reconfigure GitLab][reconfigure].
+1. Users can now configure it in their [projects' settings](../../user/project/pages/introduction.md#gitlab-pages-access-control-core-only).
+
## Activate verbose logging for daemon
Verbose logging was [introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/2533) in
@@ -320,12 +351,12 @@ latest previous version.
---
-**GitLab 8.17 ([documentation][8-17-docs])**
+**GitLab 8.17 ([documentation](https://gitlab.com/gitlab-org/gitlab-ce/blob/8-17-stable/doc/administration/pages/index.md))**
- GitLab Pages were ported to Community Edition in GitLab 8.17.
- Documentation was refactored to be more modular and easy to follow.
-**GitLab 8.5 ([documentation][8-5-docs])**
+**GitLab 8.5 ([documentation](https://gitlab.com/gitlab-org/gitlab-ee/blob/8-5-stable-ee/doc/pages/administration.md))**
- In GitLab 8.5 we introduced the [gitlab-pages][] daemon which is now the
recommended way to set up GitLab Pages.
@@ -334,13 +365,10 @@ latest previous version.
- Custom CNAME and TLS certificates support.
- Documentation was moved to one place.
-**GitLab 8.3 ([documentation][8-3-docs])**
+**GitLab 8.3 ([documentation](https://gitlab.com/gitlab-org/gitlab-ee/blob/8-3-stable-ee/doc/pages/administration.md))**
- GitLab Pages feature was introduced.
-[8-3-docs]: https://gitlab.com/gitlab-org/gitlab-ee/blob/8-3-stable-ee/doc/pages/administration.md
-[8-5-docs]: https://gitlab.com/gitlab-org/gitlab-ee/blob/8-5-stable-ee/doc/pages/administration.md
-[8-17-docs]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-17-stable-ce/doc/administration/pages/index.md
[backup]: ../../raketasks/backup_restore.md
[ce-14605]: https://gitlab.com/gitlab-org/gitlab-ce/issues/14605
[ee-80]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/80
diff --git a/doc/administration/pages/source.md b/doc/administration/pages/source.md
index 295905a7625..9f2b4d9075a 100644
--- a/doc/administration/pages/source.md
+++ b/doc/administration/pages/source.md
@@ -391,6 +391,49 @@ the first one with a backslash (\). For example `pages.example.io` would be:
server_name ~^.*\.pages\.example\.io$;
```
+## Access control
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/33422) in GitLab 11.5.
+
+GitLab Pages access control can be configured per-project, and allows access to a Pages
+site to be controlled based on a user's membership to that project.
+
+Access control works by registering the Pages daemon as an OAuth application
+with GitLab. Whenever a request to access a private Pages site is made by an
+unauthenticated user, the Pages daemon redirects the user to GitLab. If
+authentication is successful, the user is redirected back to Pages with a token,
+which is persisted in a cookie. The cookies are signed with a secret key, so
+tampering can be detected.
+
+Each request to view a resource in a private site is authenticated by Pages
+using that token. For each request it receives, it makes a request to the GitLab
+API to check that the user is authorized to read that site.
+
+Pages access control is disabled by default. To enable it:
+
+1. Modify your `config/gitlab.yml` file:
+
+ ```yaml
+ pages:
+ access_control: true
+ ```
+
+1. [Restart GitLab][restart].
+1. Create a new [system OAuth application](../../integration/oauth_provider.md#adding-an-application-through-the-profile).
+ This should be called `GitLab Pages` and have a `Redirect URL` of
+ `https://projects.example.io/auth`. It does not need to be a "trusted"
+ application, but it does need the "api" scope.
+1. Start the Pages daemon with the following additional arguments:
+
+ ```shell
+ -auth-client-secret <OAuth code generated by GitLab> \
+ -auth-redirect-uri http://projects.example.io/auth \
+ -auth-secret <40 random hex characters> \
+ -auth-server <URL of the GitLab instance>
+ ```
+
+1. Users can now configure it in their [projects' settings](../../user/project/pages/introduction.md#gitlab-pages-access-control-core-only).
+
## Change storage path
Follow the steps below to change the default path where GitLab Pages' contents
diff --git a/doc/administration/raketasks/github_import.md b/doc/administration/raketasks/github_import.md
index 6b8ad1b039b..ccd9c0afb1d 100644
--- a/doc/administration/raketasks/github_import.md
+++ b/doc/administration/raketasks/github_import.md
@@ -1,37 +1,41 @@
# GitHub import
->**Note:**
->
-> - [Introduced][ce-10308] in GitLab 9.1.
-> - You need a personal access token in order to retrieve and import GitHub
-> projects. You can get it from: https://github.com/settings/tokens
-> - You also need to pass an username as the second argument to the rake task
-> which will become the owner of the project.
-> - You can also resume an import with the same command.
+> [Introduced]( https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10308) in GitLab 9.1.
+
+In order to retrieve and import GitHub repositories, you will need a
+[GitHub personal access token](https://github.com/settings/tokens).
+A username should be passed as the second argument to the rake task
+which will become the owner of the project. You can resume an import
+with the same command.
+
+Bear in mind that the syntax is very specific. Remove any spaces within the argument block and
+before/after the brackets. Also, Some shells (e.g., zsh) can interpret the open/close brackets
+(`[]`) separately. You may need to either escape the brackets or use double quotes.
+
+## Importing multiple projects
To import a project from the list of your GitHub projects available:
```bash
# Omnibus installations
-sudo gitlab-rake import:github[access_token,root,foo/bar]
+sudo gitlab-rake "import:github[access_token,root,foo/bar]"
# Installations from source
-bundle exec rake import:github[access_token,root,foo/bar] RAILS_ENV=production
+bundle exec rake "import:github[access_token,root,foo/bar]" RAILS_ENV=production
```
In this case, `access_token` is your GitHub personal access token, `root`
is your GitLab username, and `foo/bar` is the new GitLab namespace/project that
will get created from your GitHub project. Subgroups are also possible: `foo/foo/bar`.
+## Importing a single project
To import a specific GitHub project (named `foo/github_repo` here):
```bash
# Omnibus installations
-sudo gitlab-rake import:github[access_token,root,foo/bar,foo/github_repo]
+sudo gitlab-rake "import:github[access_token,root,foo/bar,foo/github_repo]"
# Installations from source
-bundle exec rake import:github[access_token,root,foo/bar,foo/github_repo] RAILS_ENV=production
+bundle exec rake "import:github[access_token,root,foo/bar,foo/github_repo]" RAILS_ENV=production
```
-
-[ce-10308]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/10308
diff --git a/doc/administration/raketasks/maintenance.md b/doc/administration/raketasks/maintenance.md
index 2b4252a7b1d..0d863594fc7 100644
--- a/doc/administration/raketasks/maintenance.md
+++ b/doc/administration/raketasks/maintenance.md
@@ -53,14 +53,15 @@ Git: /usr/bin/git
Runs the following rake tasks:
- `gitlab:gitlab_shell:check`
+- `gitlab:gitaly:check`
- `gitlab:sidekiq:check`
- `gitlab:app:check`
-It will check that each component was setup according to the installation guide and suggest fixes for issues found.
+It will check that each component was set up according to the installation guide and suggest fixes for issues found.
-You may also have a look at our Trouble Shooting Guides:
-- [Trouble Shooting Guide (GitLab)](http://docs.gitlab.com/ee/README.html#troubleshooting)
-- [Trouble Shooting Guide (Omnibus Gitlab)](http://docs.gitlab.com/omnibus/README.html#troubleshooting)
+You may also have a look at our Troubleshooting Guides:
+- [Troubleshooting Guide (GitLab)](http://docs.gitlab.com/ee/README.html#troubleshooting)
+- [Troubleshooting Guide (Omnibus Gitlab)](http://docs.gitlab.com/omnibus/README.html#troubleshooting)
**Omnibus Installation**
@@ -252,7 +253,7 @@ clear it.
To clear all exclusive leases:
-DANGER: **DANGER**:
+DANGER: **DANGER**:
Don't run it while GitLab or Sidekiq is running
```bash
diff --git a/doc/administration/reply_by_email.md b/doc/administration/reply_by_email.md
index 426245c7aca..6d7069dd461 100644
--- a/doc/administration/reply_by_email.md
+++ b/doc/administration/reply_by_email.md
@@ -5,7 +5,7 @@ replying to notification emails.
## Requirement
-Make sure [incoming email](incoming_email.md) is setup.
+Make sure [incoming email](incoming_email.md) is set up.
## How it works?
diff --git a/doc/administration/reply_by_email_postfix_setup.md b/doc/administration/reply_by_email_postfix_setup.md
index 3e8b78e56d5..4c42cb7756a 100644
--- a/doc/administration/reply_by_email_postfix_setup.md
+++ b/doc/administration/reply_by_email_postfix_setup.md
@@ -8,7 +8,7 @@ The instructions make the assumption that you will be using the email address `i
## Configure your server firewall
1. Open up port 25 on your server so that people can send email into the server over SMTP.
-2. If the mail server is different from the server running GitLab, open up port 143 on your server so that GitLab can read email from the server over IMAP.
+1. If the mail server is different from the server running GitLab, open up port 143 on your server so that GitLab can read email from the server over IMAP.
## Install packages
@@ -245,7 +245,7 @@ Courier, which we will install later to add IMAP authentication, requires mailbo
220 gitlab.example.com ESMTP Postfix (Ubuntu)
```
- If you get a `Connection refused` error instead, make sure your firewall is setup to allow inbound traffic on port 25.
+ If you get a `Connection refused` error instead, make sure your firewall is set up to allow inbound traffic on port 25.
1. Send the `incoming` user a dummy email to test SMTP, by entering the following into the SMTP prompt:
diff --git a/doc/administration/repository_checks.md b/doc/administration/repository_checks.md
index efeec9db517..8b725e50f58 100644
--- a/doc/administration/repository_checks.md
+++ b/doc/administration/repository_checks.md
@@ -18,7 +18,8 @@ repositories and wiki repositories in order to detect data corruption.
A project will be checked no more than once per month. If any projects
fail their repository checks all GitLab administrators will receive an email
notification of the situation. This notification is sent out once a week,
-by default, midnight at the start of Sunday.
+by default, midnight at the start of Sunday. Repositories with known check
+failures can be found at `/admin/projects?last_repository_check_failed=1`.
## Disabling periodic checks
@@ -30,7 +31,7 @@ panel.
If the repository check fails for some repository you should look up the error
in `repocheck.log`:
-- in the [admin panel](logs.md#repocheck.log)
+- in the [admin panel](logs.md#repocheck-log)
- or on disk, see:
- `/var/log/gitlab/gitlab-rails` for Omnibus installations
- `/home/git/gitlab/log` for installations from source
diff --git a/doc/administration/repository_storage_paths.md b/doc/administration/repository_storage_paths.md
index 7ea7ed48850..c03f23a8931 100644
--- a/doc/administration/repository_storage_paths.md
+++ b/doc/administration/repository_storage_paths.md
@@ -97,55 +97,6 @@ be stored via the **Application Settings** in the Admin area.
Beginning with GitLab 8.13.4, multiple paths can be chosen. New projects will be
randomly placed on one of the selected paths.
-## Handling failing repository storage
-
-> [Introduced][ce-11449] in GitLab 9.5.
-
-When GitLab detects access to the repositories storage fails repeatedly, it can
-gracefully prevent attempts to access the storage. This might be useful when
-the repositories are stored somewhere on the network.
-
-This can be configured from the admin interface:
-
-![circuitbreaker configuration](img/circuitbreaker_config.png)
-
-**Number of access attempts**: The number of attempts GitLab will make to access a
-storage when probing a shard.
-
-**Number of failures before backing off**: The number of failures after which
-GitLab will start temporarily disabling access to a storage shard on a host.
-
-**Maximum git storage failures:** The number of failures of after which GitLab will
-completely prevent access to the storage. The number of failures can be reset in
-the admin interface: `https://gitlab.example.com/admin/health_check` or using the
-[api](../api/repository_storage_health.md) to allow access to the storage again.
-
-**Seconds to wait after a storage failure:** When access to a storage fails. GitLab
-will prevent access to the storage for the time specified here. This allows the
-filesystem to recover.
-
-**Seconds before reseting failure information:** The time in seconds GitLab will
-keep failure information. When no failures occur during this time, information about the
-mount is reset.
-
-**Seconds to wait for a storage access attempt:** The time in seconds GitLab will
-try to access storage. After this time a timeout error will be raised.
-
-To enable the circuitbreaker for repository storage you can flip the feature flag from a rails console:
-
-```
-Feature.enable('git_storage_circuit_breaker')
-```
-
-Alternatively it can be enabled by setting `true` in the `GIT_STORAGE_CIRCUIT_BREAKER` environment variable.
-This approach would be used when enabling the circuit breaker on a single host.
-
-When storage failures occur, this will be visible in the admin interface like this:
-
-![failing storage](img/failing_storage.png)
-
-To allow access to all storages, click the `Reset git storage health information` button.
-
[ce-4578]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/4578
[restart-gitlab]: restart_gitlab.md#installations-from-source
[reconfigure-gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure
diff --git a/doc/administration/repository_storage_types.md b/doc/administration/repository_storage_types.md
index bd758c49eba..9379944b250 100644
--- a/doc/administration/repository_storage_types.md
+++ b/doc/administration/repository_storage_types.md
@@ -41,11 +41,8 @@ Registry, etc.
## Hashed Storage
-> **Warning:** Hashed storage is in **Beta**. For the latest updates, check the
-> associated [issue](https://gitlab.com/gitlab-com/infrastructure/issues/3542)
-> and please report any problems you encounter.
-Hashed Storage is the new storage behavior we are rolling out with 10.0. Instead
+Hashed Storage is the new storage behavior we rolled out with 10.0. Instead
of coupling project URL and the folder structure where the repository will be
stored on disk, we are coupling a hash, based on the project's ID. This makes
the folder structure immutable, and therefore eliminates any requirement to
diff --git a/doc/administration/troubleshooting/debug.md b/doc/administration/troubleshooting/debug.md
index 2902af8c782..643c5b9fe80 100644
--- a/doc/administration/troubleshooting/debug.md
+++ b/doc/administration/troubleshooting/debug.md
@@ -20,7 +20,7 @@ an SMTP server, but you're not seeing mail delivered. Here's how to check the se
bundle exec rails console production
```
-2. Look at the ActionMailer `delivery_method` to make sure it matches what you
+1. Look at the ActionMailer `delivery_method` to make sure it matches what you
intended. If you configured SMTP, it should say `:smtp`. If you're using
Sendmail, it should say `:sendmail`:
@@ -29,7 +29,7 @@ an SMTP server, but you're not seeing mail delivered. Here's how to check the se
=> :smtp
```
-3. If you're using SMTP, check the mail settings:
+1. If you're using SMTP, check the mail settings:
```ruby
irb(main):002:0> ActionMailer::Base.smtp_settings
@@ -39,7 +39,7 @@ an SMTP server, but you're not seeing mail delivered. Here's how to check the se
In the example above, the SMTP server is configured for the local machine. If this is intended, you may need to check your local mail
logs (e.g. `/var/log/mail.log`) for more details.
-4. Send a test message via the console.
+1. Send a test message via the console.
```ruby
irb(main):003:0> Notify.test_email('youremail@email.com', 'Hello World', 'This is a test message').deliver_now
diff --git a/doc/administration/uploads.md b/doc/administration/uploads.md
index ce83da16067..f85a1f791f9 100644
--- a/doc/administration/uploads.md
+++ b/doc/administration/uploads.md
@@ -18,7 +18,7 @@ below.
>**Notes:**
For historical reasons, uploads are stored into a base directory, which by default is `uploads/-/system`. It is strongly discouraged to change this configuration option on an existing GitLab installation.
-_The uploads are stored by default in `/var/opt/gitlab/gitlab-rails/public/uploads/-/system`._
+_The uploads are stored by default in `/var/opt/gitlab/gitlab-rails/uploads/-/system`._
1. To change the storage path for example to `/mnt/storage/uploads`, edit
`/etc/gitlab/gitlab.rb` and add the following line:
@@ -48,11 +48,12 @@ _The uploads are stored by default in
1. Save the file and [restart GitLab][] for the changes to take effect.
-### Using object storage
+### Using object storage **[CORE ONLY]**
> **Notes:**
>
-> - [Introduced][ee-3867] in [GitLab Enterprise Edition Premium][eep] 10.5.
+> - [Introduced][ee-3867] in [GitLab Premium][eep] 10.5.
+> - [Introduced][ce17358] in [GitLab Core][ce] 10.7.
> - Since version 11.1, we support direct_upload to S3.
If you don't want to use the local disk where GitLab is installed to store the
@@ -197,4 +198,6 @@ _The uploads are stored by default in
[reconfigure gitlab]: restart_gitlab.md#omnibus-gitlab-reconfigure "How to reconfigure Omnibus GitLab"
[restart gitlab]: restart_gitlab.md#installations-from-source "How to restart GitLab"
[eep]: https://about.gitlab.com/gitlab-ee/ "GitLab Enterprise Edition Premium"
+[ce]: https://about.gitlab.com/gitlab-ce/ "GitLab Community Edition"
[ee-3867]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3867
+[ce-17358]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17358
diff --git a/doc/api/README.md b/doc/api/README.md
index a3589377e9d..b49c3a198f1 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -20,10 +20,11 @@ following locations:
- [Custom Attributes](custom_attributes.md)
- [Deployments](deployments.md)
- [Deploy Keys](deploy_keys.md)
+- [Dockerfile templates](templates/dockerfiles.md)
- [Environments](environments.md)
- [Events](events.md)
- [Feature flags](features.md)
-- [Gitignores templates](templates/gitignores.md)
+- [Gitignore templates](templates/gitignores.md)
- [GitLab CI Config templates](templates/gitlab_ci_ymls.md)
- [Groups](groups.md)
- [Group Access Requests](access_requests.md)
@@ -55,10 +56,12 @@ following locations:
- [Project import/export](project_import_export.md)
- [Project Members](members.md)
- [Project Snippets](project_snippets.md)
+- [Project Templates](project_templates.md)
- [Protected Branches](protected_branches.md)
- [Protected Tags](protected_tags.md)
- [Repositories](repositories.md)
- [Repository Files](repository_files.md)
+- [Repository Submodules](repository_submodules.md)
- [Runners](runners.md)
- [Search](search.md)
- [Services](services.md)
@@ -67,6 +70,7 @@ following locations:
- [System Hooks](system_hooks.md)
- [Tags](tags.md)
- [Todos](todos.md)
+- [Triggering Pipelines](../ci/triggers/README.md)
- [Users](users.md)
- [Validate CI configuration](lint.md)
- [V3 to V4](v3_to_v4.md)
@@ -101,7 +105,7 @@ not explicit. This allows for a stable API endpoint, but also means new
features can be added to the API in the same version number.
New features and bug fixes are released in tandem with a new GitLab, and apart
-from incidental patch and security releases, are released on the 22nd each
+from incidental patch and security releases, are released on the 22nd of each
month. Backward incompatible changes (e.g. endpoints removal, parameters
removal etc.), as well as removal of entire API versions are done in tandem
with a major point release of GitLab itself. All deprecations and changes
@@ -221,6 +225,42 @@ For more information, refer to the
Impersonation tokens are used exactly like regular personal access tokens, and can be passed in either the
`private_token` parameter or the `Private-Token` header.
+#### Disable impersonation
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/40385) in GitLab
+11.6.
+
+By default, impersonation is enabled. To disable impersonation:
+
+**For Omnibus installations**
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['impersonation_enabled'] = false
+ ```
+
+1. Save the file and [reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure)
+ GitLab for the changes to take effect.
+
+To re-enable impersonation, remove this configuration and reconfigure GitLab.
+
+---
+
+**For installations from source**
+
+1. Edit `config/gitlab.yml`:
+
+ ```yaml
+ gitlab:
+ impersonation_enabled: false
+ ```
+
+1. Save the file and [restart](../administration/restart_gitlab.md#installations-from-source)
+ GitLab for the changes to take effect.
+
+To re-enable impersonation, remove this configuration and restart GitLab.
+
### Sudo
NOTE: **Note:**
@@ -233,6 +273,9 @@ You need to pass the `sudo` parameter either via query string or a header with a
the user you want to perform the operation as. If passed as a header, the
header name must be `Sudo`.
+NOTE: **Note:**
+Usernames are case insensitive.
+
If a non administrative access token is provided, an error message will
be returned with status code `403`:
diff --git a/doc/api/applications.md b/doc/api/applications.md
index 6d244594b71..d74a3cdf5c1 100644
--- a/doc/api/applications.md
+++ b/doc/api/applications.md
@@ -4,12 +4,12 @@
[ce-8160]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8160
+Only admin user can use the Applications API.
+
## Create a application
Create a application by posting a JSON payload.
-User must be admin to do that.
-
Returns `200` if the request succeeds.
```
@@ -30,8 +30,55 @@ Example response:
```json
{
+ "id":1,
"application_id": "5832fc6e14300a0d962240a8144466eef4ee93ef0d218477e55f11cf12fc3737",
+ "application_name": "MyApplication",
"secret": "ee1dd64b6adc89cf7e2c23099301ccc2c61b441064e9324d963c46902a85ec34",
"callback_url": "http://redirect.uri"
}
```
+
+## List all applications
+
+List all registered applications.
+
+```
+GET /applications
+```
+
+```bash
+curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/applications
+```
+
+Example response:
+
+```json
+[
+ {
+ "id":1,
+ "application_id": "5832fc6e14300a0d962240a8144466eef4ee93ef0d218477e55f11cf12fc3737",
+ "application_name": "MyApplication",
+ "callback_url": "http://redirect.uri"
+ }
+]
+```
+
+> Note: the `secret` value will not be exposed by this API.
+
+## Delete an application
+
+Delete a specific application.
+
+Returns `204` if the request succeeds.
+
+```
+DELETE /applications/:id
+```
+
+Parameters:
+
+- `id` (required) - The id of the application (not the application_id)
+
+```bash
+curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/applications/:id
+```
diff --git a/doc/api/avatar.md b/doc/api/avatar.md
index 7faed893066..aa6f7c185ae 100644
--- a/doc/api/avatar.md
+++ b/doc/api/avatar.md
@@ -4,7 +4,7 @@
## Get a single avatar URL
-Get a single avatar URL for a given email addres. If user with matching public
+Get a single avatar URL for a given email address. If user with matching public
email address is not found, results from external avatar services are returned.
This endpoint can be accessed without authentication. In case public visibility
is restricted, response will be `403 Forbidden` when unauthenticated.
diff --git a/doc/api/commits.md b/doc/api/commits.md
index 624ed529009..6c16216429d 100644
--- a/doc/api/commits.md
+++ b/doc/api/commits.md
@@ -79,16 +79,18 @@ POST /projects/:id/repository/commits
| `actions[]` | array | yes | An array of action hashes to commit as a batch. See the next table for what attributes it can take. |
| `author_email` | string | no | Specify the commit author's email address |
| `author_name` | string | no | Specify the commit author's name |
+| `stats` | boolean | no | Include commit stats. Default is true |
| `actions[]` Attribute | Type | Required | Description |
| --------------------- | ---- | -------- | ----------- |
-| `action` | string | yes | The action to perform, `create`, `delete`, `move`, `update` |
+| `action` | string | yes | The action to perform, `create`, `delete`, `move`, `update`, `chmod`|
| `file_path` | string | yes | Full path to the file. Ex. `lib/class.rb` |
-| `previous_path` | string | no | Original full path to the file being moved. Ex. `lib/class1.rb` |
-| `content` | string | no | File content, required for all except `delete`. Optional for `move` |
+| `previous_path` | string | no | Original full path to the file being moved. Ex. `lib/class1.rb`. Only considered for `move` action. |
+| `content` | string | no | File content, required for all except `delete`, `chmod`, and `move`. Move actions that do not specify `content` will preserve the existing file content, and any other value of `content` will overwrite the file content. |
| `encoding` | string | no | `text` or `base64`. `text` is default. |
| `last_commit_id` | string | no | Last known file commit id. Will be only considered in update, move and delete actions. |
+| `execute_filemode` | boolean | no | When `true/false` enables/disables the execute flag on the file. Only considered for `chmod` action. |
```bash
PAYLOAD=$(cat << 'JSON'
@@ -115,6 +117,11 @@ PAYLOAD=$(cat << 'JSON'
"action": "update",
"file_path": "foo/bar5",
"content": "new content"
+ },
+ {
+ "action": "chmod",
+ "file_path": "foo/bar5",
+ "execute_filemode": true
}
]
}
@@ -281,6 +288,47 @@ Example response:
}
```
+## Revert a commit
+
+> [Introduced][ce-22919] in GitLab 11.5.
+
+Reverts a commit in a given branch.
+
+```
+POST /projects/:id/repository/commits/:sha/revert
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| `sha` | string | yes | Commit SHA to revert |
+| `branch` | string | yes | Target branch name |
+
+```bash
+curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form "branch=master" "https://gitlab.example.com/api/v4/projects/5/repository/commits/a738f717824ff53aebad8b090c1b79a14f2bd9e8/revert"
+```
+
+Example response:
+
+```json
+{
+ "id":"8b090c1b79a14f2bd9e8a738f717824ff53aebad",
+ "short_id": "8b090c1b",
+ "title":"Revert \"Feature added\"",
+ "created_at":"2018-11-08T15:55:26.000Z",
+ "parent_ids":["a738f717824ff53aebad8b090c1b79a14f2bd9e8"],
+ "message":"Revert \"Feature added\"\n\nThis reverts commit a738f717824ff53aebad8b090c1b79a14f2bd9e8",
+ "author_name":"Administrator",
+ "author_email":"admin@example.com",
+ "authored_date":"2018-11-08T15:55:26.000Z",
+ "committer_name":"Administrator",
+ "committer_email":"admin@example.com",
+ "committed_date":"2018-11-08T15:55:26.000Z"
+}
+```
+
## Get the diff of a commit
Get the diff of a commit in a project.
@@ -612,3 +660,4 @@ Example response:
[ce-8047]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8047
[ce-15026]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/15026
[ce-18004]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18004
+[ce-22919]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22919
diff --git a/doc/api/deployments.md b/doc/api/deployments.md
index fd11894ea8f..1963b0a21de 100644
--- a/doc/api/deployments.md
+++ b/doc/api/deployments.md
@@ -46,19 +46,21 @@ Example of response
"status": "success",
"tag": false,
"user": {
+ "id": 1,
+ "name": "Administrator",
+ "username": "root",
+ "state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "web_url": "http://gitlab.dev/root",
+ "created_at": "2015-12-21T13:14:24.077Z",
"bio": null,
- "created_at": "2016-08-11T07:09:20.351Z",
- "id": 1,
- "linkedin": "",
"location": null,
- "name": "Administrator",
+ "public_email": "",
"skype": "",
- "state": "active",
+ "linkedin": "",
"twitter": "",
- "username": "root",
- "web_url": "http://localhost:3000/root",
- "website_url": ""
+ "website_url": "",
+ "organization": ""
}
},
"environment": {
@@ -103,19 +105,21 @@ Example of response
"status": "success",
"tag": false,
"user": {
+ "id": 1,
+ "name": "Administrator",
+ "username": "root",
+ "state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
+ "web_url": "http://gitlab.dev/root",
+ "created_at": "2015-12-21T13:14:24.077Z",
"bio": null,
- "created_at": "2016-08-11T07:09:20.351Z",
- "id": 1,
- "linkedin": "",
"location": null,
- "name": "Administrator",
+ "public_email": "",
"skype": "",
- "state": "active",
+ "linkedin": "",
"twitter": "",
- "username": "root",
- "web_url": "http://localhost:3000/root",
- "website_url": ""
+ "website_url": "",
+ "organization": ""
}
},
"environment": {
@@ -188,19 +192,20 @@ Example of response
"started_at": null,
"finished_at": "2016-08-11T11:32:35.145Z",
"user": {
+ "id": 1,
"name": "Administrator",
"username": "root",
- "id": 1,
"state": "active",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "web_url": "http://localhost:3000/root",
- "created_at": "2016-08-11T07:09:20.351Z",
+ "web_url": "http://gitlab.dev/root",
+ "created_at": "2015-12-21T13:14:24.077Z",
"bio": null,
"location": null,
"skype": "",
"linkedin": "",
"twitter": "",
- "website_url": ""
+ "website_url": "",
+ "organization": ""
},
"commit": {
"id": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
diff --git a/doc/api/discussions.md b/doc/api/discussions.md
index a1e1ff1419d..3538a577c8e 100644
--- a/doc/api/discussions.md
+++ b/doc/api/discussions.md
@@ -123,7 +123,7 @@ curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab
### Create new issue discussion
Creates a new discussion to a single project issue. This is similar to creating
-a note but but another comments (replies) can be added to it later.
+a note but other comments (replies) can be added to it later.
```
POST /projects/:id/issues/:issue_iid/discussions
@@ -329,7 +329,7 @@ curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitla
### Create new snippet discussion
Creates a new discussion to a single project snippet. This is similar to creating
-a note but but another comments (replies) can be added to it later.
+a note but other comments (replies) can be added to it later.
```
POST /projects/:id/snippets/:snippet_id/discussions
@@ -588,7 +588,7 @@ curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab
### Create new merge request discussion
Creates a new discussion to a single project merge request. This is similar to creating
-a note but but another comments (replies) can be added to it later.
+a note but other comments (replies) can be added to it later.
```
POST /projects/:id/merge_requests/:merge_request_iid/discussions
@@ -881,7 +881,7 @@ curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab
### Create new commit discussion
Creates a new discussion to a single project commit. This is similar to creating
-a note but but another comments (replies) can be added to it later.
+a note but other comments (replies) can be added to it later.
```
POST /projects/:id/commits/:commit_id/discussions
diff --git a/doc/api/events.md b/doc/api/events.md
index fb5ebb71a86..e1c6b801a77 100644
--- a/doc/api/events.md
+++ b/doc/api/events.md
@@ -44,7 +44,7 @@ YYYY-MM-DD
### Event Time Period Limit
-GitLab removes events older than 1 year from the events table for performance reasons. The range of 1 year was chosen because user contribution calendars only show contributions of the past year.
+GitLab removes events older than 2 years from the events table for performance reasons.
## List currently authenticated user's events
@@ -71,7 +71,7 @@ Parameters:
Example request:
```
-curl --header "PRIVATE-TOKEN 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/events&target_type=issue&action=created&after=2017-01-31&before=2017-03-01
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/events?target_type=issue&action=created&after=2017-01-31&before=2017-03-01
```
Example response:
@@ -276,7 +276,7 @@ Parameters:
Example request:
```
-curl --header "PRIVATE-TOKEN 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:project_id/events&target_type=issue&action=created&after=2017-01-31&before=2017-03-01
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:project_id/events?target_type=issue&action=created&after=2017-01-31&before=2017-03-01
```
Example response:
diff --git a/doc/api/groups.md b/doc/api/groups.md
index be75c363a40..59444a98086 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -37,6 +37,7 @@ GET /groups
"request_access_enabled": false,
"full_name": "Foobar Group",
"full_path": "foo-bar",
+ "file_template_project_id": 1,
"parent_id": null
}
]
@@ -62,6 +63,7 @@ GET /groups?statistics=true
"request_access_enabled": false,
"full_name": "Foobar Group",
"full_path": "foo-bar",
+ "file_template_project_id": 1,
"parent_id": null,
"statistics": {
"storage_size" : 212,
@@ -122,6 +124,7 @@ GET /groups/:id/subgroups
"request_access_enabled": false,
"full_name": "Foobar Group",
"full_path": "foo-bar",
+ "file_template_project_id": 1,
"parent_id": 123
}
]
@@ -149,8 +152,10 @@ Parameters:
| `simple` | boolean | no | Return only the ID, URL, name, and path of each project |
| `owned` | boolean | no | Limit by projects owned by the current user |
| `starred` | boolean | no | Limit by projects starred by the current user |
-| `with_issues_enabled` | boolean | no | Limit by enabled issues feature |
-| `with_merge_requests_enabled` | boolean | no | Limit by enabled merge requests feature |
+| `with_issues_enabled` | boolean | no | Limit by projects with issues feature enabled. Default is `false` |
+| `with_merge_requests_enabled` | boolean | no | Limit by projects with merge requests feature enabled. Default is `false` |
+| `with_shared` | boolean | no | Include projects shared to this group. Default is `true` |
+| `include_subgroups` | boolean | no | Include projects in subgroups of this group. Default is `false` |
| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
Example response:
@@ -232,6 +237,7 @@ Example response:
"request_access_enabled": false,
"full_name": "Twitter",
"full_path": "twitter",
+ "file_template_project_id": 1,
"parent_id": null,
"projects": [
{
@@ -386,6 +392,7 @@ Example response:
"request_access_enabled": false,
"full_name": "Twitter",
"full_path": "twitter",
+ "file_template_project_id": 1,
"parent_id": null
}
```
@@ -442,6 +449,7 @@ PUT /groups/:id
| `visibility` | string | no | The visibility level of the group. Can be `private`, `internal`, or `public`. |
| `lfs_enabled` (optional) | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group |
| `request_access_enabled` | boolean | no | Allow users to request member access. |
+| `file_template_project_id` | integer | no | **(Premium)** The ID of a project to load custom file templates from |
```bash
curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/5?name=Experimental"
@@ -462,6 +470,7 @@ Example response:
"request_access_enabled": false,
"full_name": "Foobar Group",
"full_path": "foo-bar",
+ "file_template_project_id": 1,
"parent_id": null,
"projects": [
{
diff --git a/doc/api/issues.md b/doc/api/issues.md
index f4c0f4ea65b..6a99c52234d 100644
--- a/doc/api/issues.md
+++ b/doc/api/issues.md
@@ -36,12 +36,12 @@ GET /issues?my_reaction_emoji=star
| Attribute | Type | Required | Description |
| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
-| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `No+Label` lists all issues with no labels |
-| `milestone` | string | no | The milestone title. `No+Milestone` lists all issues with no milestone |
+| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
+| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`. Defaults to `created_by_me`<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced][ce-13004] in GitLab 9.5. [Changed to snake_case][ce-18935] in GitLab 11.0)_ |
| `author_id` | integer | no | Return issues created by the given user `id`. Combine with `scope=all` or `scope=assigned_to_me`. _([Introduced][ce-13004] in GitLab 9.5)_ |
-| `assignee_id` | integer | no | Return issues assigned to the given user `id` _([Introduced][ce-13004] in GitLab 9.5)_ |
-| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji` _([Introduced][ce-14016] in GitLab 10.0)_ |
+| `assignee_id` | integer | no | Return issues assigned to the given user `id`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
+| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced][ce-14016] in GitLab 10.0)_ |
| `iids[]` | Array[integer] | no | Return only the issues having the given `iid` |
| `order_by` | string | no | Return issues ordered by `created_at` or `updated_at` fields. Default is `created_at` |
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
@@ -149,13 +149,13 @@ GET /groups/:id/issues?my_reaction_emoji=star
| ------------------- | ---------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
-| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `No+Label` lists all issues with no labels |
+| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
| `iids[]` | Array[integer] | no | Return only the issues having the given `iid` |
-| `milestone` | string | no | The milestone title. `No+Milestone` lists all issues with no milestone |
+| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced][ce-13004] in GitLab 9.5. [Changed to snake_case][ce-18935] in GitLab 11.0)_ |
| `author_id` | integer | no | Return issues created by the given user `id` _([Introduced][ce-13004] in GitLab 9.5)_ |
-| `assignee_id` | integer | no | Return issues assigned to the given user `id` _([Introduced][ce-13004] in GitLab 9.5)_ |
-| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji` _([Introduced][ce-14016] in GitLab 10.0)_ |
+| `assignee_id` | integer | no | Return issues assigned to the given user `id`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
+| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced][ce-14016] in GitLab 10.0)_ |
| `order_by` | string | no | Return issues ordered by `created_at` or `updated_at` fields. Default is `created_at` |
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
| `search` | string | no | Search group issues against their `title` and `description` |
@@ -264,12 +264,12 @@ GET /projects/:id/issues?my_reaction_emoji=star
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `iids[]` | Array[integer] | no | Return only the milestone having the given `iid` |
| `state` | string | no | Return all issues or just those that are `opened` or `closed` |
-| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `No+Label` lists all issues with no labels |
-| `milestone` | string | no | The milestone title. `No+Milestone` lists all issues with no milestone |
+| `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. |
+| `milestone` | string | no | The milestone title. `None` lists all issues with no milestone. `Any` lists all issues that have an assigned milestone. |
| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced][ce-13004] in GitLab 9.5. [Changed to snake_case][ce-18935] in GitLab 11.0)_ |
| `author_id` | integer | no | Return issues created by the given user `id` _([Introduced][ce-13004] in GitLab 9.5)_ |
-| `assignee_id` | integer | no | Return issues assigned to the given user `id` _([Introduced][ce-13004] in GitLab 9.5)_ |
-| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji` _([Introduced][ce-14016] in GitLab 10.0)_ |
+| `assignee_id` | integer | no | Return issues assigned to the given user `id`. `None` returns unassigned issues. `Any` returns issues with an assignee. _([Introduced][ce-13004] in GitLab 9.5)_ |
+| `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced][ce-14016] in GitLab 10.0)_ |
| `order_by` | string | no | Return issues ordered by `created_at` or `updated_at` fields. Default is `created_at` |
| `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` |
| `search` | string | no | Search project issues against their `title` and `description` |
@@ -658,7 +658,7 @@ POST /projects/:id/issues/:issue_iid/move
| `to_project_id` | integer | yes | The ID of the new project |
```bash
-curl --request POST --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --data '{"to_project_id": 5}' https://gitlab.example.com/api/v4/projects/4/issues/85/move
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --form to_project_id=5 https://gitlab.example.com/api/v4/projects/4/issues/85/move
```
Example response:
@@ -1113,6 +1113,93 @@ Example response:
}
```
+## List merge requests related to issue
+
+Get all the merge requests that are related to the issue.
+
+```
+GET /projects/:id/issues/:issue_id/related_merge_requests
+```
+
+| Attribute | Type | Required | Description |
+|-------------|---------|----------|--------------------------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `issue_iid` | integer | yes | The internal ID of a project's issue |
+
+```sh
+curl --request GET --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/1/issues/11/related_merge_requests
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 29,
+ "iid": 11,
+ "project_id": 1,
+ "title": "Provident eius eos blanditiis consequatur neque odit.",
+ "description": "Ut consequatur ipsa aspernatur quisquam voluptatum fugit. Qui harum corporis quo fuga ut incidunt veritatis. Autem necessitatibus et harum occaecati nihil ea.\r\n\r\ntwitter/flight#8",
+ "state": "opened",
+ "created_at": "2018-09-18T14:36:15.510Z",
+ "updated_at": "2018-09-19T07:45:13.089Z",
+ "target_branch": "v2.x",
+ "source_branch": "so_long_jquery",
+ "upvotes": 0,
+ "downvotes": 0,
+ "author": {
+ "id": 14,
+ "name": "Verna Hills",
+ "username": "lawanda_reinger",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/de68a91aeab1cff563795fb98a0c2cc0?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/lawanda_reinger"
+ },
+ "assignee": {
+ "id": 19,
+ "name": "Jody Baumbach",
+ "username": "felipa.kuvalis",
+ "state": "active",
+ "avatar_url": "https://www.gravatar.com/avatar/6541fc75fc4e87e203529bd275fafd07?s=80&d=identicon",
+ "web_url": "https://gitlab.example.com/felipa.kuvalis"
+ },
+ "source_project_id": 1,
+ "target_project_id": 1,
+ "labels": [],
+ "work_in_progress": false,
+ "milestone": {
+ "id": 27,
+ "iid": 2,
+ "project_id": 1,
+ "title": "v1.0",
+ "description": "Et tenetur voluptatem minima doloribus vero dignissimos vitae.",
+ "state": "active",
+ "created_at": "2018-09-18T14:35:44.353Z",
+ "updated_at": "2018-09-18T14:35:44.353Z",
+ "due_date": null,
+ "start_date": null,
+ "web_url": "https://gitlab.example.com/twitter/flight/milestones/2"
+ },
+ "merge_when_pipeline_succeeds": false,
+ "merge_status": "cannot_be_merged",
+ "sha": "3b7b528e9353295c1c125dad281ac5b5deae5f12",
+ "merge_commit_sha": null,
+ "user_notes_count": 9,
+ "discussion_locked": null,
+ "should_remove_source_branch": null,
+ "force_remove_source_branch": false,
+ "web_url": "https://gitlab.example.com/twitter/flight/merge_requests/4",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ },
+ "squash": false
+ }
+]
+```
+
## List merge requests that will close issue on merge
Get all the merge requests that will close issue when merged.
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index cf292adf150..aa290ff4cf8 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -53,18 +53,21 @@ Example of response
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/6",
"user": {
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "bio": null,
- "created_at": "2015-12-21T13:14:24.077Z",
"id": 1,
- "linkedin": "",
"name": "Administrator",
- "skype": "",
- "state": "active",
- "twitter": "",
"username": "root",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "http://gitlab.dev/root",
- "website_url": ""
+ "created_at": "2015-12-21T13:14:24.077Z",
+ "bio": null,
+ "location": null,
+ "public_email": "",
+ "skype": "",
+ "linkedin": "",
+ "twitter": "",
+ "website_url": "",
+ "organization": ""
}
},
{
@@ -109,18 +112,21 @@ Example of response
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/7",
"user": {
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "bio": null,
- "created_at": "2015-12-21T13:14:24.077Z",
"id": 1,
- "linkedin": "",
"name": "Administrator",
- "skype": "",
- "state": "active",
- "twitter": "",
"username": "root",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "http://gitlab.dev/root",
- "website_url": ""
+ "created_at": "2015-12-21T13:14:24.077Z",
+ "bio": null,
+ "location": null,
+ "public_email": "",
+ "skype": "",
+ "linkedin": "",
+ "twitter": "",
+ "website_url": "",
+ "organization": ""
}
}
]
@@ -180,18 +186,21 @@ Example of response
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/6",
"user": {
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "bio": null,
- "created_at": "2015-12-21T13:14:24.077Z",
"id": 1,
- "linkedin": "",
"name": "Administrator",
- "skype": "",
- "state": "active",
- "twitter": "",
"username": "root",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "http://gitlab.dev/root",
- "website_url": ""
+ "created_at": "2015-12-21T13:14:24.077Z",
+ "bio": null,
+ "location": null,
+ "public_email": "",
+ "skype": "",
+ "linkedin": "",
+ "twitter": "",
+ "website_url": "",
+ "organization": ""
}
},
{
@@ -236,18 +245,21 @@ Example of response
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/7",
"user": {
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "bio": null,
- "created_at": "2015-12-21T13:14:24.077Z",
"id": 1,
- "linkedin": "",
"name": "Administrator",
- "skype": "",
- "state": "active",
- "twitter": "",
"username": "root",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "http://gitlab.dev/root",
- "website_url": ""
+ "created_at": "2015-12-21T13:14:24.077Z",
+ "bio": null,
+ "location": null,
+ "public_email": "",
+ "skype": "",
+ "linkedin": "",
+ "twitter": "",
+ "website_url": "",
+ "organization": ""
}
}
]
@@ -305,18 +317,21 @@ Example of response
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/8",
"user": {
- "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
- "bio": null,
- "created_at": "2015-12-21T13:14:24.077Z",
"id": 1,
- "linkedin": "",
"name": "Administrator",
- "skype": "",
- "state": "active",
- "twitter": "",
"username": "root",
+ "state": "active",
+ "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
"web_url": "http://gitlab.dev/root",
- "website_url": ""
+ "created_at": "2015-12-21T13:14:24.077Z",
+ "bio": null,
+ "location": null,
+ "public_email": "",
+ "skype": "",
+ "linkedin": "",
+ "twitter": "",
+ "website_url": "",
+ "organization": ""
}
}
```
diff --git a/doc/api/keys.md b/doc/api/keys.md
index ddcf7830621..06b31a67d6a 100644
--- a/doc/api/keys.md
+++ b/doc/api/keys.md
@@ -27,10 +27,16 @@ Parameters:
"web_url": "http://localhost:3000/john_smith",
"created_at": "2015-09-03T07:24:01.670Z",
"bio": null,
+ "location": null,
+ "public_email": "john@example.com",
"skype": "",
"linkedin": "",
"twitter": "",
"website_url": "",
+ "organization": null,
+ "last_sign_in_at": "2015-09-03T07:24:01.670Z",
+ "confirmed_at": "2015-09-03T07:24:01.670Z",
+ "last_activity_on": "2015-09-03",
"email": "john@example.com",
"theme_id": 2,
"color_scheme_id": 1,
@@ -40,6 +46,8 @@ Parameters:
"can_create_group": true,
"can_create_project": true,
"two_factor_enabled": false
+ "external": false,
+ "private_profile": null
}
}
```
diff --git a/doc/api/members.md b/doc/api/members.md
index 7b228b92594..bb4fae35f52 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -15,6 +15,7 @@ The access levels are defined in the `Gitlab::Access` module. Currently, these l
## List all members of a group or project
Gets a list of group or project members viewable by the authenticated user.
+Returns only direct members and not inherited members through ancestors groups.
```
GET /groups/:id/members
@@ -61,6 +62,7 @@ Example response:
## List all members of a group or project including inherited members
Gets a list of group or project members viewable by the authenticated user, including inherited members through ancestor groups.
+Returns multiple times the same user (with different member attributes) when the user is a member of the project/group and of one or more ancestor group.
```
GET /groups/:id/members/all
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index 9e6676d62fe..fc03cf6cc39 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -30,58 +30,73 @@ Parameters:
| Attribute | Type | Required | Description |
| ------------------- | -------- | -------- | ---------------------------------------------------------------------------------------------------------------------- |
-| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged` |
+| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged` |
| `order_by` | string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` |
| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc` |
-| `milestone` | string | no | Return merge requests for a specific milestone |
+| `milestone` | string | no | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. |
| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request |
-| `labels` | string | no | Return merge requests matching a comma separated list of labels |
+| `labels` | string | no | Return merge requests matching a comma separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. |
| `created_after` | datetime | no | Return merge requests created on or after the given time |
| `created_before` | datetime | no | Return merge requests created on or before the given time |
| `updated_after` | datetime | no | Return merge requests updated on or after the given time |
| `updated_before` | datetime | no | Return merge requests updated on or before the given time |
| `scope` | string | no | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`. Defaults to `created_by_me`<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead. |
| `author_id` | integer | no | Returns merge requests created by the given user `id`. Combine with `scope=all` or `scope=assigned_to_me` |
-| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id` |
-| `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji` _([Introduced][ce-14016] in GitLab 10.0)_ |
+| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id`. `None` returns unassigned merge requests. `Any` returns merge requests with an assignee. |
+| `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced][ce-14016] in GitLab 10.0)_ |
| `source_branch` | string | no | Return merge requests with the given source branch |
| `target_branch` | string | no | Return merge requests with the given target branch |
| `search` | string | no | Search merge requests against their `title` and `description` |
+| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* WIP merge requests, `no` to return *non* WIP merge requests |
```json
[
{
"id": 1,
"iid": 1,
- "target_branch": "master",
- "source_branch": "test1",
"project_id": 3,
"title": "test1",
- "state": "opened",
+ "description": "fixed login page css paddings",
+ "state": "merged",
+ "merged_by": {
+ "id": 87854,
+ "name": "Douwe Maan",
+ "username": "DouweM",
+ "state": "active",
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
+ "web_url": "https://gitlab.com/DouweM"
+ },
+ "merged_at": "2018-09-07T11:16:17.520Z",
+ "closed_by": null,
+ "closed_at": null,
"created_at": "2017-04-29T08:46:00Z",
"updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"source_project_id": 2,
"target_project_id": 3,
- "labels": [ ],
- "description": "fixed login page css paddings",
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -92,23 +107,28 @@ Parameters:
"state": "closed",
"created_at": "2015-02-02T19:49:26.013Z",
"updated_at": "2015-02-02T19:49:26.013Z",
- "due_date": null
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
"user_notes_count": 1,
+ "discussion_locked": null,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "squash": false,
- "web_url": "http://example.com/example/example/merge_requests/1",
+ "allow_collaboration": false,
+ "allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
- }
+ },
+ "squash": false
}
]
```
@@ -145,22 +165,22 @@ Parameters:
| ------------------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `id` | integer | yes | The ID of a project |
| `iids[]` | Array[integer] | no | Return the request having the given `iid` |
-| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged` |
+| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged` |
| `order_by` | string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` |
| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc` |
-| `milestone` | string | no | Return merge requests for a specific milestone |
+| `milestone` | string | no | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. |
| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request |
-| `labels` | string | no | Return merge requests matching a comma separated list of labels |
+| `labels` | string | no | Return merge requests matching a comma separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. |
| `created_after` | datetime | no | Return merge requests created on or after the given time |
| `created_before` | datetime | no | Return merge requests created on or before the given time |
| `updated_after` | datetime | no | Return merge requests updated on or after the given time |
| `updated_before` | datetime | no | Return merge requests updated on or before the given time |
| `scope` | string | no | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced][ce-13060] in GitLab 9.5. [Changed to snake_case][ce-18935] in GitLab 11.0)_ |
| `author_id` | integer | no | Returns merge requests created by the given user `id` _([Introduced][ce-13060] in GitLab 9.5)_ |
-| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id` _([Introduced][ce-13060] in GitLab 9.5)_ |
-| `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji` _([Introduced][ce-14016] in GitLab 10.0)_ |
-| `source_branch` | string | no | Return merge requests with the given source branch |
-| `target_branch` | string | no | Return merge requests with the given target branch |
+| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id`. `None` returns unassigned merge requests. `Any` returns merge requests with an assignee. _([Introduced][ce-13060] in GitLab 9.5)_ |
+| `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced][ce-14016] in GitLab 10.0)_ |
+| `source_branch` | string | no | Return merge requests with the given source branch |
+| `target_branch` | string | no | Return merge requests with the given target branch |
| `search` | string | no | Search merge requests against their `title` and `description` |
```json
@@ -168,35 +188,49 @@ Parameters:
{
"id": 1,
"iid": 1,
- "target_branch": "master",
- "source_branch": "test1",
"project_id": 3,
"title": "test1",
- "state": "opened",
+ "description": "fixed login page css paddings",
+ "state": "merged",
+ "merged_by": {
+ "id": 87854,
+ "name": "Douwe Maan",
+ "username": "DouweM",
+ "state": "active",
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
+ "web_url": "https://gitlab.com/DouweM"
+ },
+ "merged_at": "2018-09-07T11:16:17.520Z",
+ "closed_by": null,
+ "closed_at": null,
"created_at": "2017-04-29T08:46:00Z",
"updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"source_project_id": 2,
"target_project_id": 3,
- "labels": [ ],
- "description": "fixed login page css paddings",
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -207,24 +241,28 @@ Parameters:
"state": "closed",
"created_at": "2015-02-02T19:49:26.013Z",
"updated_at": "2015-02-02T19:49:26.013Z",
- "due_date": null
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
"user_notes_count": 1,
+ "discussion_locked": null,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "squash": false,
- "web_url": "http://example.com/example/example/merge_requests/1",
- "discussion_locked": false,
+ "allow_collaboration": false,
+ "allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
- }
+ },
+ "squash": false
}
]
```
@@ -250,23 +288,23 @@ Parameters:
| Attribute | Type | Required | Description |
| ------------------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ |
-| `id` | integer | yes | The ID of a group |
-| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged` |
-| `order_by` | string | no | Return merge requests ordered by `created_at` or `updated_at` fields. Default is `created_at` |
-| `sort` | string | no | Return merge requests sorted in `asc` or `desc` order. Default is `desc` |
-| `milestone` | string | no | Return merge requests for a specific milestone |
+| `id` | integer | yes | The ID of a group |
+| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged` |
+| `order_by` | string | no | Return merge requests ordered by `created_at` or `updated_at` fields. Default is `created_at` |
+| `sort` | string | no | Return merge requests sorted in `asc` or `desc` order. Default is `desc` |
+| `milestone` | string | no | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. |
| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request |
-| `labels` | string | no | Return merge requests matching a comma separated list of labels |
+| `labels` | string | no | Return merge requests matching a comma separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. |
| `created_after` | datetime | no | Return merge requests created on or after the given time |
| `created_before` | datetime | no | Return merge requests created on or before the given time |
| `updated_after` | datetime | no | Return merge requests updated on or after the given time |
| `updated_before` | datetime | no | Return merge requests updated on or before the given time |
| `scope` | string | no | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> |
| `author_id` | integer | no | Returns merge requests created by the given user `id` _([Introduced][ce-13060] in GitLab 9.5)_ |
-| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id` _([Introduced][ce-13060] in GitLab 9.5)_ |
-| `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji` _([Introduced][ce-14016] in GitLab 10.0)_ |
-| `source_branch` | string | no | Return merge requests with the given source branch |
-| `target_branch` | string | no | Return merge requests with the given target branch |
+| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id`. `None` returns unassigned merge requests. `Any` returns merge requests with an assignee. _([Introduced][ce-13060] in GitLab 9.5)_ |
+| `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced][ce-14016] in GitLab 10.0)_ |
+| `source_branch` | string | no | Return merge requests with the given source branch |
+| `target_branch` | string | no | Return merge requests with the given target branch |
| `search` | string | no | Search merge requests against their `title` and `description` |
```json
@@ -274,35 +312,49 @@ Parameters:
{
"id": 1,
"iid": 1,
- "target_branch": "master",
- "source_branch": "test1",
"project_id": 3,
"title": "test1",
- "state": "opened",
+ "description": "fixed login page css paddings",
+ "state": "merged",
+ "merged_by": {
+ "id": 87854,
+ "name": "Douwe Maan",
+ "username": "DouweM",
+ "state": "active",
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
+ "web_url": "https://gitlab.com/DouweM"
+ },
+ "merged_at": "2018-09-07T11:16:17.520Z",
+ "closed_by": null,
+ "closed_at": null,
"created_at": "2017-04-29T08:46:00Z",
"updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"source_project_id": 2,
"target_project_id": 3,
- "labels": [ ],
- "description": "fixed login page css paddings",
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -313,23 +365,26 @@ Parameters:
"state": "closed",
"created_at": "2015-02-02T19:49:26.013Z",
"updated_at": "2015-02-02T19:49:26.013Z",
- "due_date": null
+ "due_date": "2018-10-22",
+ "start_date": "2018-09-08",
+ "web_url": "gitlab.example.com/my-group/my-project/milestones/1"
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
"user_notes_count": 1,
+ "discussion_locked": null,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "web_url": "http://example.com/example/example/merge_requests/1",
- "discussion_locked": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
- }
+ },
+ "squash": false
}
]
```
@@ -353,40 +408,44 @@ Parameters:
- `merge_request_iid` (required) - The internal ID of the merge request
- `render_html` (optional) - If `true` response includes rendered HTML for title and description
- `include_diverged_commits_count` (optional) - If `true` response includes the commits behind the target branch
+- `include_rebase_in_progress` (optional) - If `true` response includes whether a rebase operation is in progress
```json
{
"id": 1,
"iid": 1,
- "target_branch": "master",
- "source_branch": "test1",
"project_id": 3,
"title": "test1",
+ "description": "fixed login page css paddings",
"state": "merged",
"created_at": "2017-04-29T08:46:00Z",
"updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
- "state" : "active",
- "web_url" : "https://gitlab.example.com/root",
- "avatar_url" : null,
- "username" : "root",
- "id" : 1,
- "name" : "Administrator"
+ "id": 1,
+ "name": "Administrator",
+ "username": "admin",
+ "state": "active",
+ "avatar_url": null,
+ "web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
- "state" : "active",
- "web_url" : "https://gitlab.example.com/root",
- "avatar_url" : null,
- "username" : "root",
- "id" : 1,
- "name" : "Administrator"
+ "id": 1,
+ "name": "Administrator",
+ "username": "admin",
+ "state": "active",
+ "avatar_url": null,
+ "web_url" : "https://gitlab.example.com/admin"
},
"source_project_id": 2,
"target_project_id": 3,
- "labels": [ ],
- "description": "fixed login page css paddings",
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
"id": 5,
@@ -397,47 +456,59 @@ Parameters:
"state": "closed",
"created_at": "2015-02-02T19:49:26.013Z",
"updated_at": "2015-02-02T19:49:26.013Z",
- "due_date": null
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
- "subscribed" : true,
+ "merge_error": null,
"sha": "8888888888888888888888888888888888888888",
- "merge_commit_sha": "9999999999999999999999999999999999999999",
+ "merge_commit_sha": null,
"user_notes_count": 1,
- "changes_count": "1",
+ "discussion_locked": null,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "squash": false,
- "web_url": "http://example.com/example/example/merge_requests/1",
- "discussion_locked": false,
+ "allow_collaboration": false,
+ "allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
},
- "closed_at": "2018-01-19T14:36:11.086Z",
- "latest_build_started_at": null,
- "latest_build_finished_at": null,
+ "squash": false,
+ "subscribed": false,
+ "changes_count": "1",
+ "merged_by": {
+ "id": 87854,
+ "name": "Douwe Maan",
+ "username": "DouweM",
+ "state": "active",
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
+ "web_url": "https://gitlab.com/DouweM"
+ },
+ "merged_at": "2018-09-07T11:16:17.520Z",
+ "closed_by": null,
+ "closed_at": null,
+ "latest_build_started_at": "2018-09-07T07:27:38.472Z",
+ "latest_build_finished_at": "2018-09-07T08:07:06.012Z",
"first_deployed_to_production_at": null,
"pipeline": {
- "id": 8,
- "ref": "master",
- "sha": "2dc6aa325a317eda67812f05600bdf0fcdc70ab0",
- "status": "created"
+ "id": 29626725,
+ "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "ref": "patch-28",
+ "status": "success",
+ "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725"
},
- "merged_by": null,
- "merged_at": null,
- "closed_by": {
- "state" : "active",
- "web_url" : "https://gitlab.example.com/root",
- "avatar_url" : null,
- "username" : "root",
- "id" : 1,
- "name" : "Administrator"
+ "diff_refs": {
+ "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00",
+ "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
},
- "diverged_commits_count": 2
+ "diverged_commits_count": 2,
+ "rebase_in_progress": false
}
```
@@ -657,65 +728,100 @@ POST /projects/:id/merge_requests
{
"id": 1,
"iid": 1,
+ "project_id": 3,
+ "title": "test1",
+ "description": "fixed login page css paddings",
+ "state": "merged",
+ "created_at": "2017-04-29T08:46:00Z",
+ "updated_at": "2017-04-29T08:46:00Z",
"target_branch": "master",
"source_branch": "test1",
- "project_id": 4,
- "title": "test1",
- "state": "opened",
"upvotes": 0,
"downvotes": 0,
"author": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
- "source_project_id": 3,
- "target_project_id": 4,
- "labels": [ ],
- "description": "fixed login page css paddings",
+ "source_project_id": 2,
+ "target_project_id": 3,
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
"id": 5,
"iid": 1,
- "project_id": 4,
+ "project_id": 3,
"title": "v2.0",
"description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.",
"state": "closed",
"created_at": "2015-02-02T19:49:26.013Z",
"updated_at": "2015-02-02T19:49:26.013Z",
- "due_date": null
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
- "subscribed" : true,
+ "merge_error": null,
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
- "user_notes_count": 0,
- "changes_count": "1",
+ "user_notes_count": 1,
+ "discussion_locked": null,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "squash": false,
- "web_url": "http://example.com/example/example/merge_requests/1",
- "discussion_locked": false,
"allow_collaboration": false,
"allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
- }
+ },
+ "squash": false,
+ "subscribed": false,
+ "changes_count": "1",
+ "merged_by": {
+ "id": 87854,
+ "name": "Douwe Maan",
+ "username": "DouweM",
+ "state": "active",
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
+ "web_url": "https://gitlab.com/DouweM"
+ },
+ "merged_at": "2018-09-07T11:16:17.520Z",
+ "closed_by": null,
+ "closed_at": null,
+ "latest_build_started_at": "2018-09-07T07:27:38.472Z",
+ "latest_build_finished_at": "2018-09-07T08:07:06.012Z",
+ "first_deployed_to_production_at": null,
+ "pipeline": {
+ "id": 29626725,
+ "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "ref": "patch-28",
+ "status": "success",
+ "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725"
+ },
+ "diff_refs": {
+ "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00",
+ "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
+ },
+ "diverged_commits_count": 2
}
```
@@ -750,64 +856,100 @@ Must include at least one non-required attribute from above.
{
"id": 1,
"iid": 1,
- "target_branch": "master",
- "project_id": 4,
+ "project_id": 3,
"title": "test1",
- "state": "opened",
+ "description": "fixed login page css paddings",
+ "state": "merged",
+ "created_at": "2017-04-29T08:46:00Z",
+ "updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
- "source_project_id": 3,
- "target_project_id": 4,
- "labels": [ ],
- "description": "description1",
+ "source_project_id": 2,
+ "target_project_id": 3,
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
"id": 5,
"iid": 1,
- "project_id": 4,
+ "project_id": 3,
"title": "v2.0",
"description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.",
"state": "closed",
"created_at": "2015-02-02T19:49:26.013Z",
"updated_at": "2015-02-02T19:49:26.013Z",
- "due_date": null
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
- "subscribed" : true,
+ "merge_error": null,
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
"user_notes_count": 1,
- "changes_count": "1",
+ "discussion_locked": null,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "squash": false,
- "web_url": "http://example.com/example/example/merge_requests/1",
- "discussion_locked": false,
"allow_collaboration": false,
"allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
- }
+ },
+ "squash": false,
+ "subscribed": false,
+ "changes_count": "1",
+ "merged_by": {
+ "id": 87854,
+ "name": "Douwe Maan",
+ "username": "DouweM",
+ "state": "active",
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
+ "web_url": "https://gitlab.com/DouweM"
+ },
+ "merged_at": "2018-09-07T11:16:17.520Z",
+ "closed_by": null,
+ "closed_at": null,
+ "latest_build_started_at": "2018-09-07T07:27:38.472Z",
+ "latest_build_finished_at": "2018-09-07T08:07:06.012Z",
+ "first_deployed_to_production_at": null,
+ "pipeline": {
+ "id": 29626725,
+ "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "ref": "patch-28",
+ "status": "success",
+ "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725"
+ },
+ "diff_refs": {
+ "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00",
+ "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
+ },
+ "diverged_commits_count": 2
}
```
@@ -851,70 +993,107 @@ Parameters:
- `merge_request_iid` (required) - Internal ID of MR
- `merge_commit_message` (optional) - Custom merge commit message
- `should_remove_source_branch` (optional) - if `true` removes the source branch
-- `merge_when_pipeline_succeeds` (optional) - if `true` the MR is merged when the pipeline succeeds
+- `merge_when_pipeline_succeeds` (optional) - if `true` the MR is merged when the pipeline succeeds
- `sha` (optional) - if present, then this SHA must match the HEAD of the source branch, otherwise the merge will fail
```json
{
"id": 1,
"iid": 1,
- "target_branch": "master",
- "source_branch": "test1",
"project_id": 3,
"title": "test1",
+ "description": "fixed login page css paddings",
"state": "merged",
+ "created_at": "2017-04-29T08:46:00Z",
+ "updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
- "source_project_id": 4,
- "target_project_id": 4,
- "labels": [ ],
- "description": "fixed login page css paddings",
+ "source_project_id": 2,
+ "target_project_id": 3,
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
"id": 5,
"iid": 1,
- "project_id": 4,
+ "project_id": 3,
"title": "v2.0",
"description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.",
"state": "closed",
"created_at": "2015-02-02T19:49:26.013Z",
"updated_at": "2015-02-02T19:49:26.013Z",
- "due_date": null
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
- "subscribed" : true,
+ "merge_error": null,
"sha": "8888888888888888888888888888888888888888",
- "merge_commit_sha": "9999999999999999999999999999999999999999",
+ "merge_commit_sha": null,
"user_notes_count": 1,
- "changes_count": "1",
+ "discussion_locked": null,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "squash": false,
- "web_url": "http://example.com/example/example/merge_requests/1",
- "discussion_locked": false,
+ "allow_collaboration": false,
+ "allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
- }
+ },
+ "squash": false,
+ "subscribed": false,
+ "changes_count": "1",
+ "merged_by": {
+ "id": 87854,
+ "name": "Douwe Maan",
+ "username": "DouweM",
+ "state": "active",
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
+ "web_url": "https://gitlab.com/DouweM"
+ },
+ "merged_at": "2018-09-07T11:16:17.520Z",
+ "closed_by": null,
+ "closed_at": null,
+ "latest_build_started_at": "2018-09-07T07:27:38.472Z",
+ "latest_build_finished_at": "2018-09-07T08:07:06.012Z",
+ "first_deployed_to_production_at": null,
+ "pipeline": {
+ "id": 29626725,
+ "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "ref": "patch-28",
+ "status": "success",
+ "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725"
+ },
+ "diff_refs": {
+ "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00",
+ "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
+ },
+ "diverged_commits_count": 2
}
```
@@ -931,69 +1110,162 @@ PUT /projects/:id/merge_requests/:merge_request_iid/cancel_merge_when_pipeline_s
Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `merge_request_iid` (required) - Internal ID of MR
+- `merge_request_iid` (required) - Internal ID of MR
```json
{
"id": 1,
"iid": 1,
- "target_branch": "master",
- "source_branch": "test1",
"project_id": 3,
"title": "test1",
- "state": "opened",
+ "description": "fixed login page css paddings",
+ "state": "merged",
+ "created_at": "2017-04-29T08:46:00Z",
+ "updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
"id": 1,
- "username": "admin",
"name": "Administrator",
+ "username": "admin",
"state": "active",
"avatar_url": null,
"web_url" : "https://gitlab.example.com/admin"
},
- "source_project_id": 4,
- "target_project_id": 4,
- "labels": [ ],
- "description": "fixed login page css paddings",
+ "source_project_id": 2,
+ "target_project_id": 3,
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
"id": 5,
"iid": 1,
- "project_id": 4,
+ "project_id": 3,
"title": "v2.0",
"description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.",
"state": "closed",
"created_at": "2015-02-02T19:49:26.013Z",
"updated_at": "2015-02-02T19:49:26.013Z",
- "due_date": null
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
- "merge_when_pipeline_succeeds": true,
+ "merge_when_pipeline_succeeds": false,
"merge_status": "can_be_merged",
- "subscribed" : true,
+ "merge_error": null,
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
"user_notes_count": 1,
- "changes_count": "1",
+ "discussion_locked": null,
"should_remove_source_branch": true,
"force_remove_source_branch": false,
- "squash": false,
- "web_url": "http://example.com/example/example/merge_requests/1",
- "discussion_locked": false,
+ "allow_collaboration": false,
+ "allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
"time_stats": {
"time_estimate": 0,
"total_time_spent": 0,
"human_time_estimate": null,
"human_total_time_spent": null
- }
+ },
+ "squash": false,
+ "subscribed": false,
+ "changes_count": "1",
+ "merged_by": {
+ "id": 87854,
+ "name": "Douwe Maan",
+ "username": "DouweM",
+ "state": "active",
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
+ "web_url": "https://gitlab.com/DouweM"
+ },
+ "merged_at": "2018-09-07T11:16:17.520Z",
+ "closed_by": null,
+ "closed_at": null,
+ "latest_build_started_at": "2018-09-07T07:27:38.472Z",
+ "latest_build_finished_at": "2018-09-07T08:07:06.012Z",
+ "first_deployed_to_production_at": null,
+ "pipeline": {
+ "id": 29626725,
+ "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "ref": "patch-28",
+ "status": "success",
+ "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725"
+ },
+ "diff_refs": {
+ "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00",
+ "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
+ },
+ "diverged_commits_count": 2
+}
+```
+
+## Rebase a merge request
+
+Automatically rebase the `source_branch` of the merge request against its
+`target_branch`.
+
+If you don't have permissions to push to the merge request's source branch -
+you'll get a `403 Forbidden` response.
+
+```
+PUT /projects/:id/merge_requests/:merge_request_iid/rebase
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request |
+
+```bash
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/76/merge_requests/1/rebase
+```
+
+This is an asynchronous request. The API will return an empty `202 Accepted`
+response if the request is enqueued successfully.
+
+You can poll the [Get single MR](#get-single-mr) endpoint with the
+`include_rebase_in_progress` parameter to check the status of the
+asynchronous request.
+
+If the rebase operation is ongoing, the response will include the following:
+
+```json
+{
+ "rebase_in_progress": true
+ "merge_error": null
+}
+```
+
+Once the rebase operation has completed successfully, the response will include
+the following:
+
+```json
+{
+ "rebase_in_progress": false,
+ "merge_error": null,
+}
+```
+
+If the rebase operation fails, the response will include the following:
+
+```json
+{
+ "rebase_in_progress": false,
+ "merge_error": "Rebase failed. Please rebase locally",
}
```
@@ -1061,7 +1333,7 @@ Example response when the GitLab issue tracker is used:
"labels" : [],
"user_notes_count": 1,
"changes_count": "1"
- },
+ }
]
```
@@ -1098,54 +1370,101 @@ Example response:
```json
{
- "id": 17,
+ "id": 1,
"iid": 1,
- "project_id": 5,
- "title": "Et et sequi est impedit nulla ut rem et voluptatem.",
- "description": "Consequatur velit eos rerum optio autem. Quia id officia quaerat dolorum optio. Illo laudantium aut ipsum dolorem.",
- "state": "opened",
- "created_at": "2016-04-05T21:42:23.233Z",
- "updated_at": "2016-04-05T22:11:52.900Z",
- "target_branch": "ui-dev-kit",
- "source_branch": "version-1-9",
+ "project_id": 3,
+ "title": "test1",
+ "description": "fixed login page css paddings",
+ "state": "merged",
+ "created_at": "2017-04-29T08:46:00Z",
+ "updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
- "name": "Eileen Skiles",
- "username": "leila",
- "id": 19,
+ "id": 1,
+ "name": "Administrator",
+ "username": "admin",
"state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/39ce4a2822cc896933ffbd68c1470e55?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/leila"
+ "avatar_url": null,
+ "web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
- "name": "Celine Wehner",
- "username": "carli",
- "id": 16,
+ "id": 1,
+ "name": "Administrator",
+ "username": "admin",
"state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/f4cd5605b769dd2ce405a27c6e6f2684?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/carli"
+ "avatar_url": null,
+ "web_url" : "https://gitlab.example.com/admin"
},
- "source_project_id": 5,
- "target_project_id": 5,
- "labels": [],
+ "source_project_id": 2,
+ "target_project_id": 3,
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
- "id": 7,
+ "id": 5,
"iid": 1,
- "project_id": 5,
+ "project_id": 3,
"title": "v2.0",
- "description": "Corrupti eveniet et velit occaecati dolorem est rerum aut.",
+ "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.",
"state": "closed",
- "created_at": "2016-04-05T21:41:40.905Z",
- "updated_at": "2016-04-05T21:41:40.905Z",
- "due_date": null
+ "created_at": "2015-02-02T19:49:26.013Z",
+ "updated_at": "2015-02-02T19:49:26.013Z",
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
- "merge_when_pipeline_succeeds": false,
- "merge_status": "cannot_be_merged",
- "subscribed": true,
+ "merge_when_pipeline_succeeds": true,
+ "merge_status": "can_be_merged",
"sha": "8888888888888888888888888888888888888888",
- "merge_commit_sha": null
+ "merge_commit_sha": null,
+ "user_notes_count": 1,
+ "discussion_locked": null,
+ "should_remove_source_branch": true,
+ "force_remove_source_branch": false,
+ "allow_collaboration": false,
+ "allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ },
+ "squash": false,
+ "subscribed": false,
+ "changes_count": "1",
+ "merged_by": {
+ "id": 87854,
+ "name": "Douwe Maan",
+ "username": "DouweM",
+ "state": "active",
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
+ "web_url": "https://gitlab.com/DouweM"
+ },
+ "merged_at": "2018-09-07T11:16:17.520Z",
+ "closed_by": null,
+ "closed_at": null,
+ "latest_build_started_at": "2018-09-07T07:27:38.472Z",
+ "latest_build_finished_at": "2018-09-07T08:07:06.012Z",
+ "first_deployed_to_production_at": null,
+ "pipeline": {
+ "id": 29626725,
+ "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "ref": "patch-28",
+ "status": "success",
+ "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725"
+ },
+ "diff_refs": {
+ "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00",
+ "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
+ },
+ "diverged_commits_count": 2
}
```
@@ -1172,54 +1491,101 @@ Example response:
```json
{
- "id": 17,
+ "id": 1,
"iid": 1,
- "project_id": 5,
- "title": "Et et sequi est impedit nulla ut rem et voluptatem.",
- "description": "Consequatur velit eos rerum optio autem. Quia id officia quaerat dolorum optio. Illo laudantium aut ipsum dolorem.",
- "state": "opened",
- "created_at": "2016-04-05T21:42:23.233Z",
- "updated_at": "2016-04-05T22:11:52.900Z",
- "target_branch": "ui-dev-kit",
- "source_branch": "version-1-9",
+ "project_id": 3,
+ "title": "test1",
+ "description": "fixed login page css paddings",
+ "state": "merged",
+ "created_at": "2017-04-29T08:46:00Z",
+ "updated_at": "2017-04-29T08:46:00Z",
+ "target_branch": "master",
+ "source_branch": "test1",
"upvotes": 0,
"downvotes": 0,
"author": {
- "name": "Eileen Skiles",
- "username": "leila",
- "id": 19,
+ "id": 1,
+ "name": "Administrator",
+ "username": "admin",
"state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/39ce4a2822cc896933ffbd68c1470e55?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/leila"
+ "avatar_url": null,
+ "web_url" : "https://gitlab.example.com/admin"
},
"assignee": {
- "name": "Celine Wehner",
- "username": "carli",
- "id": 16,
+ "id": 1,
+ "name": "Administrator",
+ "username": "admin",
"state": "active",
- "avatar_url": "http://www.gravatar.com/avatar/f4cd5605b769dd2ce405a27c6e6f2684?s=80&d=identicon",
- "web_url": "https://gitlab.example.com/carli"
+ "avatar_url": null,
+ "web_url" : "https://gitlab.example.com/admin"
},
- "source_project_id": 5,
- "target_project_id": 5,
- "labels": [],
+ "source_project_id": 2,
+ "target_project_id": 3,
+ "labels": [
+ "Community contribution",
+ "Manage"
+ ],
"work_in_progress": false,
"milestone": {
- "id": 7,
+ "id": 5,
"iid": 1,
- "project_id": 5,
+ "project_id": 3,
"title": "v2.0",
- "description": "Corrupti eveniet et velit occaecati dolorem est rerum aut.",
+ "description": "Assumenda aut placeat expedita exercitationem labore sunt enim earum.",
"state": "closed",
- "created_at": "2016-04-05T21:41:40.905Z",
- "updated_at": "2016-04-05T21:41:40.905Z",
- "due_date": null
+ "created_at": "2015-02-02T19:49:26.013Z",
+ "updated_at": "2015-02-02T19:49:26.013Z",
+ "due_date": "2018-09-22",
+ "start_date": "2018-08-08",
+ "web_url": "https://gitlab.example.com/my-group/my-project/milestones/1"
},
- "merge_when_pipeline_succeeds": false,
- "merge_status": "cannot_be_merged",
- "subscribed": false,
+ "merge_when_pipeline_succeeds": true,
+ "merge_status": "can_be_merged",
"sha": "8888888888888888888888888888888888888888",
- "merge_commit_sha": null
+ "merge_commit_sha": null,
+ "user_notes_count": 1,
+ "discussion_locked": null,
+ "should_remove_source_branch": true,
+ "force_remove_source_branch": false,
+ "allow_collaboration": false,
+ "allow_maintainer_to_push": false,
+ "web_url": "http://gitlab.example.com/my-group/my-project/merge_requests/1",
+ "time_stats": {
+ "time_estimate": 0,
+ "total_time_spent": 0,
+ "human_time_estimate": null,
+ "human_total_time_spent": null
+ },
+ "squash": false,
+ "subscribed": false,
+ "changes_count": "1",
+ "merged_by": {
+ "id": 87854,
+ "name": "Douwe Maan",
+ "username": "DouweM",
+ "state": "active",
+ "avatar_url": "https://gitlab.example.com/uploads/-/system/user/avatar/87854/avatar.png",
+ "web_url": "https://gitlab.com/DouweM"
+ },
+ "merged_at": "2018-09-07T11:16:17.520Z",
+ "closed_by": null,
+ "closed_at": null,
+ "latest_build_started_at": "2018-09-07T07:27:38.472Z",
+ "latest_build_finished_at": "2018-09-07T08:07:06.012Z",
+ "first_deployed_to_production_at": null,
+ "pipeline": {
+ "id": 29626725,
+ "sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "ref": "patch-28",
+ "status": "success",
+ "web_url": "https://gitlab.example.com/my-group/my-project/pipelines/29626725"
+ },
+ "diff_refs": {
+ "base_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00",
+ "head_sha": "2be7ddb704c7b6b83732fdd5b9f09d5a397b5f8f",
+ "start_sha": "c380d3acebd181f13629a25d2e2acca46ffe1e00"
+ },
+ "diverged_commits_count": 2
}
```
@@ -1270,7 +1636,7 @@ Example response:
"project_id": 3,
"title": "Et voluptas laudantium minus nihil recusandae ut accusamus earum aut non.",
"description": "Veniam sunt nihil modi earum cumque illum delectus. Nihil ad quis distinctio quia. Autem eligendi at quibusdam repellendus.",
- "state": "opened",
+ "state": "merged",
"created_at": "2016-06-17T07:48:04.330Z",
"updated_at": "2016-07-01T11:14:15.537Z",
"target_branch": "allow_regex_for_project_skip_ref",
diff --git a/doc/api/notes.md b/doc/api/notes.md
index 44940bdd9e5..9f6740ad86a 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -98,7 +98,7 @@ POST /projects/:id/issues/:issue_iid/notes
Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding)
-- `issue_id` (required) - The IID of an issue
+- `issue_iid` (required) - The IID of an issue
- `body` (required) - The content of a note
- `created_at` (optional) - Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project/group owner rights)
diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md
index 77bb7a55d8c..8a1e6b52092 100644
--- a/doc/api/oauth2.md
+++ b/doc/api/oauth2.md
@@ -1,6 +1,6 @@
# GitLab as an OAuth2 provider
-This document covers using the [OAuth2](https://oauth.net/2/) protocol to allow other services access Gitlab resources on user's behalf.
+This document covers using the [OAuth2](https://oauth.net/2/) protocol to allow other services access GitLab resources on user's behalf.
If you want GitLab to be an OAuth authentication service provider to sign into other services please see the [OAuth2 provider](../integration/oauth_provider.md)
documentation.
@@ -9,7 +9,7 @@ This functionality is based on [doorkeeper gem](https://github.com/doorkeeper-ge
## Supported OAuth2 Flows
-Gitlab currently supports following authorization flows:
+GitLab currently supports following authorization flows:
* *Web Application Flow* - Most secure and common type of flow, designed for the applications with secure server-side.
* *Implicit Flow* - This flow is designed for user-agent only apps (e.g. single page web application running on GitLab Pages).
@@ -76,7 +76,7 @@ Check [RFC spec](http://tools.ietf.org/html/rfc6749#section-4.2) for a detailed
Unlike the web flow, the client receives an `access token` immediately as a result of the authorization request. The flow does not use client secret
or authorization code because all of the application code and storage is easily accessible, therefore __secrets__ can leak easily.
->**Important:** Avoid using this flow for applications that store data outside of the Gitlab instance. If you do, make sure to verify `application id`
+>**Important:** Avoid using this flow for applications that store data outside of the GitLab instance. If you do, make sure to verify `application id`
associated with access token before granting access to the data
(see [/oauth/token/info](https://github.com/doorkeeper-gem/doorkeeper/wiki/API-endpoint-descriptions-and-examples#get----oauthtokeninfo)).
@@ -146,7 +146,7 @@ access_token = client.password.get_token('user@example.com', 'secret')
puts access_token.token
```
-## Access Gitlab API with `access token`
+## Access GitLab API with `access token`
The `access token` allows you to make requests to the API on a behalf of a user. You can pass the token either as GET parameter
```
diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md
index 574be52801c..7b4c9a8fbb3 100644
--- a/doc/api/pipelines.md
+++ b/doc/api/pipelines.md
@@ -235,5 +235,22 @@ Response:
}
```
+## Delete a pipeline
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22988) in GitLab 11.6.
+
+```
+DELETE /projects/:id/pipelines/:pipeline_id
+```
+
+| Attribute | Type | Required | Description |
+|------------|---------|----------|---------------------|
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `pipeline_id` | integer | yes | The ID of a pipeline |
+
+```
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" --request "DELETE" "https://gitlab.example.com/api/v4/projects/1/pipelines/46"
+```
+
[ce-5837]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5837
[ce-7209]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7209
diff --git a/doc/api/project_templates.md b/doc/api/project_templates.md
new file mode 100644
index 00000000000..ef98205cd68
--- /dev/null
+++ b/doc/api/project_templates.md
@@ -0,0 +1,139 @@
+# Project templates API
+
+This API is a project-specific version of these endpoints:
+
+- [Dockerfile templates](templates/dockerfiles.md)
+- [Gitignore templates](templates/gitignores.md)
+- [GitLab CI Config templates](templates/gitlab_ci_ymls.md)
+- [Open source license templates](templates/licenses.md)
+
+It deprecates these endpoints, which will be removed for API version 5.
+
+In addition to templates common to the entire instance, project-specific
+templates are also available from this API endpoint.
+
+Support will be added for [Issue and Merge Request templates](../user/project/description_templates.md)
+in a future release.
+
+Support for [Group-level file templates](../user/group/index.md#group-level-file-templates-premium)
+**[PREMIUM]** was [added](https://gitlab.com/gitlab-org/gitlab-ee/issues/5987)
+in GitLab 11.5
+
+## Get all templates of a particular type
+
+```
+GET /projects/:id/templates/:type
+```
+
+| Attribute | Type | Required | Description |
+| ---------- | ------ | -------- | ----------- |
+| `id ` | integer / string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| `type` | string | yes| The type `(dockerfiles|gitignores|gitlab_ci_ymls|licenses)` of the template |
+
+Example response (licenses):
+
+```json
+[
+ {
+ "key": "epl-1.0",
+ "name": "Eclipse Public License 1.0"
+ },
+ {
+ "key": "lgpl-3.0",
+ "name": "GNU Lesser General Public License v3.0"
+ },
+ {
+ "key": "unlicense",
+ "name": "The Unlicense"
+ },
+ {
+ "key": "agpl-3.0",
+ "name": "GNU Affero General Public License v3.0"
+ },
+ {
+ "key": "gpl-3.0",
+ "name": "GNU General Public License v3.0"
+ },
+ {
+ "key": "bsd-3-clause",
+ "name": "BSD 3-clause \"New\" or \"Revised\" License"
+ },
+ {
+ "key": "lgpl-2.1",
+ "name": "GNU Lesser General Public License v2.1"
+ },
+ {
+ "key": "mit",
+ "name": "MIT License"
+ },
+ {
+ "key": "apache-2.0",
+ "name": "Apache License 2.0"
+ },
+ {
+ "key": "bsd-2-clause",
+ "name": "BSD 2-clause \"Simplified\" License"
+ },
+ {
+ "key": "mpl-2.0",
+ "name": "Mozilla Public License 2.0"
+ },
+ {
+ "key": "gpl-2.0",
+ "name": "GNU General Public License v2.0"
+ }
+]
+```
+
+## Get one template of a particular type
+
+```
+GET /projects/:id/templates/:type/:key
+```
+
+| Attribute | Type | Required | Description |
+| ---------- | ------ | -------- | ----------- |
+| `id ` | integer / string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| `type` | string | yes| The type `(dockerfiles|gitignores|gitlab_ci_ymls|licenses)` of the template |
+| `key` | string | yes | The key of the template, as obtained from the collection endpoint |
+| `project` | string | no | The project name to use when expanding placeholders in the template. Only affects licenses |
+| `fullname` | string | no | The full name of the copyright holder to use when expanding placeholders in the template. Only affects licenses |
+
+Example response (Dockerfile):
+
+
+```json
+{
+ "name": "Binary",
+ "content": "# This file is a template, and might need editing before it works on your project.\n# This Dockerfile installs a compiled binary into a bare system.\n# You must either commit your compiled binary into source control (not recommended)\n# or build the binary first as part of a CI/CD pipeline.\n\nFROM buildpack-deps:jessie\n\nWORKDIR /usr/local/bin\n\n# Change `app` to whatever your binary is called\nAdd app .\nCMD [\"./app\"]\n"
+}
+
+```
+
+Example response (license):
+
+```json
+{
+ "key": "mit",
+ "name": "MIT License",
+ "nickname": null,
+ "popular": true,
+ "html_url": "http://choosealicense.com/licenses/mit/",
+ "source_url": "https://opensource.org/licenses/MIT",
+ "description": "A short and simple permissive license with conditions only requiring preservation of copyright and license notices. Licensed works, modifications, and larger works may be distributed under different terms and without source code.",
+ "conditions": [
+ "include-copyright"
+ ],
+ "permissions": [
+ "commercial-use",
+ "modifications",
+ "distribution",
+ "private-use"
+ ],
+ "limitations": [
+ "liability",
+ "warranty"
+ ],
+ "content": "MIT License\n\nCopyright (c) 2018 [fullname]\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
+}
+```
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 947e7db9c52..ef51ea20e7f 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -451,6 +451,7 @@ GET /projects/:id
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `statistics` | boolean | no | Include project statistics |
+| `license` | boolean | no | Include project license data |
| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (admins only) |
```json
@@ -508,6 +509,14 @@ GET /projects/:id
},
"archived": false,
"avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
+ "license_url": "http://example.com/diaspora/diaspora-client/blob/master/LICENSE",
+ "license": {
+ "key": "lgpl-3.0",
+ "name": "GNU Lesser General Public License v3.0",
+ "nickname": "GNU LGPLv3",
+ "html_url": "http://choosealicense.com/licenses/lgpl-3.0/",
+ "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt"
+ },
"shared_runners_enabled": true,
"forks_count": 0,
"star_count": 0,
@@ -572,6 +581,14 @@ If the project is a fork, and you provide a valid token to authenticate, the
"http_url_to_repo":"https://gitlab.com/gitlab-org/gitlab-ce.git",
"web_url":"https://gitlab.com/gitlab-org/gitlab-ce",
"avatar_url":"https://assets.gitlab-static.net/uploads/-/system/project/avatar/13083/logo-extra-whitespace.png",
+ "license_url": "https://gitlab.com/gitlab-org/gitlab-ce/blob/master/LICENSE",
+ "license": {
+ "key": "mit",
+ "name": "MIT License",
+ "nickname": null,
+ "html_url": "http://choosealicense.com/licenses/mit/",
+ "source_url": "https://opensource.org/licenses/MIT",
+ },
"star_count":3812,
"forks_count":3561,
"last_activity_at":"2018-01-02T11:40:26.570Z",
@@ -651,7 +668,7 @@ POST /projects
| `shared_runners_enabled` | boolean | no | Enable shared runners for this project |
| `visibility` | string | no | See [project visibility level](#project-visibility-level) |
| `import_url` | string | no | URL to import repository from |
-| `public_jobs` | boolean | no | If `true`, jobs can be viewed by non-project-members |
+| `public_builds` | boolean | no | If `true`, jobs can be viewed by non-project-members |
| `only_allow_merge_if_pipeline_succeeds` | boolean | no | Set whether merge requests can only be merged with successful jobs |
| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved |
| `merge_method` | string | no | Set the merge method used |
@@ -689,7 +706,7 @@ POST /projects/user/:user_id
| `shared_runners_enabled` | boolean | no | Enable shared runners for this project |
| `visibility` | string | no | See [project visibility level](#project-visibility-level) |
| `import_url` | string | no | URL to import repository from |
-| `public_jobs` | boolean | no | If `true`, jobs can be viewed by non-project-members |
+| `public_builds` | boolean | no | If `true`, jobs can be viewed by non-project-members |
| `only_allow_merge_if_pipeline_succeeds` | boolean | no | Set whether merge requests can only be merged with successful jobs |
| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved |
| `merge_method` | string | no | Set the merge method used |
@@ -725,7 +742,7 @@ PUT /projects/:id
| `shared_runners_enabled` | boolean | no | Enable shared runners for this project |
| `visibility` | string | no | See [project visibility level](#project-visibility-level) |
| `import_url` | string | no | URL to import repository from |
-| `public_jobs` | boolean | no | If `true`, jobs can be viewed by non-project-members |
+| `public_builds` | boolean | no | If `true`, jobs can be viewed by non-project-members |
| `only_allow_merge_if_pipeline_succeeds` | boolean | no | Set whether merge requests can only be merged with successful jobs |
| `only_allow_merge_if_all_discussions_are_resolved` | boolean | no | Set whether merge requests can only be merged when all the discussions are resolved |
| `merge_method` | string | no | Set the merge method used |
@@ -905,6 +922,14 @@ Example response:
"import_status": "none",
"archived": true,
"avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
+ "license_url": "http://example.com/diaspora/diaspora-client/blob/master/LICENSE",
+ "license": {
+ "key": "lgpl-3.0",
+ "name": "GNU Lesser General Public License v3.0",
+ "nickname": "GNU LGPLv3",
+ "html_url": "http://choosealicense.com/licenses/lgpl-3.0/",
+ "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt"
+ },
"shared_runners_enabled": true,
"forks_count": 0,
"star_count": 1,
@@ -983,6 +1008,14 @@ Example response:
"import_status": "none",
"archived": true,
"avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
+ "license_url": "http://example.com/diaspora/diaspora-client/blob/master/LICENSE",
+ "license": {
+ "key": "lgpl-3.0",
+ "name": "GNU Lesser General Public License v3.0",
+ "nickname": "GNU LGPLv3",
+ "html_url": "http://choosealicense.com/licenses/lgpl-3.0/",
+ "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt"
+ },
"shared_runners_enabled": true,
"forks_count": 0,
"star_count": 0,
@@ -1101,6 +1134,14 @@ Example response:
},
"archived": true,
"avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
+ "license_url": "http://example.com/diaspora/diaspora-client/blob/master/LICENSE",
+ "license": {
+ "key": "lgpl-3.0",
+ "name": "GNU Lesser General Public License v3.0",
+ "nickname": "GNU LGPLv3",
+ "html_url": "http://choosealicense.com/licenses/lgpl-3.0/",
+ "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt"
+ },
"shared_runners_enabled": true,
"forks_count": 0,
"star_count": 0,
@@ -1197,6 +1238,14 @@ Example response:
},
"archived": false,
"avatar_url": "http://example.com/uploads/project/avatar/3/uploads/avatar.png",
+ "license_url": "http://example.com/diaspora/diaspora-client/blob/master/LICENSE",
+ "license": {
+ "key": "lgpl-3.0",
+ "name": "GNU Lesser General Public License v3.0",
+ "nickname": "GNU LGPLv3",
+ "html_url": "http://choosealicense.com/licenses/lgpl-3.0/",
+ "source_url": "http://www.gnu.org/licenses/lgpl-3.0.txt"
+ },
"shared_runners_enabled": true,
"forks_count": 0,
"star_count": 0,
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index a4fdeca162e..55f5a4cc3b2 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -14,9 +14,10 @@ GET /projects/:id/repository/tree
Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
-- `path` (optional) - The path inside repository. Used to get contend of subdirectories
+- `path` (optional) - The path inside repository. Used to get content of subdirectories
- `ref` (optional) - The name of a repository branch or tag or if not given the default branch
- `recursive` (optional) - Boolean value used to get a recursive tree (false by default)
+- `per_page` (optional) - Number of results to show per page. If not specified, defaults to `20`
```json
[
@@ -107,14 +108,18 @@ Get an archive of the repository. This endpoint can be accessed without
authentication if the repository is publicly accessible.
```
-GET /projects/:id/repository/archive
+GET /projects/:id/repository/archive[.format]
```
+`format` is an optional suffix for the archive format. Default is
+`tar.gz`. Options are `tar.gz`, `tar.bz2`, `tbz`, 'tbz2`, `tb2`,
+`bz2`, `tar`, and `zip`. For example, specifying `archive.zip`
+would send an archive in ZIP format.
+
Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `sha` (optional) - The commit SHA to download. A tag, branch reference or sha can be used. This defaults to the tip of the default branch if not specified
-- `format` (optional) - The archive format. Default is `tar.gz`. Options are `tar.gz`, `tar.bz2`, `tbz`, `tbz2`, `tb2`, `bz2`, `tar`, `zip`
## Compare branches, tags or commits
@@ -216,7 +221,7 @@ GET /projects/:id/repository/merge_base
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
-| `refs` | array | yes | The refs to find the common ancestor of, for now only 2 refs are supported |
+| `refs` | array | yes | The refs to find the common ancestor of, multiple refs can be passed |
```bash
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repository/merge_base?refs[]=304d257dcb821665ab5110318fc58a007bd104ed&refs[]=0031876facac3f2b2702a0e53a26e89939a42209"
diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md
index 49fb9bc141d..c3624f1a535 100644
--- a/doc/api/repository_files.md
+++ b/doc/api/repository_files.md
@@ -90,12 +90,17 @@ Like [Get file from repository](repository_files.md#get-file-from-repository) yo
## Create new file in repository
+This allows you to create a single file. For creating multiple files with a single request see the [commits API](commits.html#create-a-commit-with-multiple-files-and-actions).
+
```
POST /projects/:id/repository/files/:file_path
```
```bash
-curl --request POST --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fprojectrb%2E?branch=master&author_email=author%40example.com&author_name=Firstname%20Lastname&content=some%20content&commit_message=create%20a%20new%20file'
+curl --request POST --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' --header "Content-Type: application/json" \
+ --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \
+ "content": "some content", "commit_message": "create a new file"}' \
+ 'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb'
```
Example response:
@@ -120,12 +125,17 @@ Parameters:
## Update existing file in repository
+This allows you to update a single file. For updating multiple files with a single request see the [commits API](commits.html#create-a-commit-with-multiple-files-and-actions).
+
```
PUT /projects/:id/repository/files/:file_path
```
```bash
-curl --request PUT --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb?branch=master&author_email=author%40example.com&author_name=Firstname%20Lastname&content=some%20other%20content&commit_message=update%20file'
+curl --request PUT --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' --header "Content-Type: application/json" \
+ --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \
+ "content": "some content", "commit_message": "update file"}' \
+ 'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb'
```
Example response:
@@ -160,12 +170,17 @@ Currently gitlab-shell has a boolean return code, preventing GitLab from specify
## Delete existing file in repository
+This allows you to delete a single file. For deleting multiple files with a singleh request see the [commits API](commits.html#create-a-commit-with-multiple-files-and-actions).
+
```
DELETE /projects/:id/repository/files/:file_path
```
```bash
-curl --request DELETE --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' 'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb?branch=master&author_email=author%40example.com&author_name=Firstname%20Lastname&commit_message=delete%20file'
+curl --request DELETE --header 'PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK' --header "Content-Type: application/json" \
+ --data '{"branch": "master", "author_email": "author@example.com", "author_name": "Firstname Lastname", \
+ "commit_message": "delete file"}' \
+ 'https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb'
```
Parameters:
diff --git a/doc/api/repository_storage_health.md b/doc/api/repository_storage_health.md
index e0c0315c2d7..edf4b04acea 100644
--- a/doc/api/repository_storage_health.md
+++ b/doc/api/repository_storage_health.md
@@ -1,74 +1,5 @@
# Circuitbreaker API
-> [Introduced][ce-11449] in GitLab 9.5.
-
-The Circuitbreaker API is only accessible to administrators. All requests by
-guests will respond with `401 Unauthorized`, and all requests by normal users
-will respond with `403 Forbidden`.
-
-## Repository Storages
-
-### Get all storage information
-
-Returns of all currently configured storages and their health information.
-
-```
-GET /circuit_breakers/repository_storage
-```
-
-```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/circuit_breakers/repository_storage
-```
-
-```json
-[
- {
- "storage_name": "default",
- "failing_on_hosts": [],
- "total_failures": 0
- },
- {
- "storage_name": "broken",
- "failing_on_hosts": [
- "web01", "worker01"
- ],
- "total_failures": 1
- }
-]
-```
-
-### Get failing storages
-
-This returns a list of all currently failing storages.
-
-```
-GET /circuit_breakers/repository_storage/failing
-```
-
-```bash
-curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/circuit_breakers/repository_storage/failing
-```
-
-```json
-[
- {
- "storage_name":"broken",
- "failing_on_hosts":["web01", "worker01"],
- "total_failures":2
- }
-]
-```
-
-## Reset failing storage information
-
-Use this remove all failing storage information and allow access to the storage again.
-
-```
-DELETE /circuit_breakers/repository_storage
-```
-
-```bash
-curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/circuit_breakers/repository_storage
-```
-
-[ce-11449]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11449
+NOTE: **Deprecated:**
+Support of the circuit breaker is removed, as Gitaly can be configured to
+to work without NFS and [communicate solely over HTTP](../administration/gitaly/index.md).
diff --git a/doc/api/repository_submodules.md b/doc/api/repository_submodules.md
new file mode 100644
index 00000000000..2e6797f18f4
--- /dev/null
+++ b/doc/api/repository_submodules.md
@@ -0,0 +1,49 @@
+# Repository submodules API
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/41213) in GitLab 11.5
+
+## Update existing submodule reference in repository
+
+In some workflows, especially automated ones, it can be useful to update a
+submodule's reference to keep up to date other projects that use it.
+This endpoint allows you to update a [Git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules) reference in a
+specific branch.
+
+```
+PUT /projects/:id/repository/submodules/:submodule
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `submodule` | string | yes | URL encoded full path to the submodule. For example, `lib%2Fclass%2Erb` |
+| `branch` | string | yes | Name of the branch to commit into |
+| `commit_sha` | string | yes | Full commit SHA to update the submodule to |
+| `commit_message` | string | no | Commit message. If no message is provided, a default one will be set |
+
+```sh
+curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/5/repositories/submodules/lib%2Fmodules%2Fexample"
+--data "branch=master&commit_sha=3ddec28ea23acc5caa5d8331a6ecb2a65fc03e88&commit_message=Update submodule reference"
+```
+
+Example response:
+
+```json
+{
+ "id": "ed899a2f4b50b4370feeea94676502b42383c746",
+ "short_id": "ed899a2f4b5",
+ "title": "Updated submodule example_submodule with oid 3ddec28ea23acc5caa5d8331a6ecb2a65fc03e88",
+ "author_name": "Dmitriy Zaporozhets",
+ "author_email": "dzaporozhets@sphereconsultinginc.com",
+ "committer_name": "Dmitriy Zaporozhets",
+ "committer_email": "dzaporozhets@sphereconsultinginc.com",
+ "created_at": "2018-09-20T09:26:24.000-07:00",
+ "message": "Updated submodule example_submodule with oid 3ddec28ea23acc5caa5d8331a6ecb2a65fc03e88",
+ "parent_ids": [
+ "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba"
+ ],
+ "committed_date": "2018-09-20T09:26:24.000-07:00",
+ "authored_date": "2018-09-20T09:26:24.000-07:00",
+ "status": null
+}
+```
diff --git a/doc/api/runners.md b/doc/api/runners.md
index 66476e7db64..071c13f41cb 100644
--- a/doc/api/runners.md
+++ b/doc/api/runners.md
@@ -11,11 +11,15 @@ Get a list of specific runners available to the user.
```
GET /runners
GET /runners?scope=active
+GET /runners?type=project_type
+GET /runners?status=active
```
| Attribute | Type | Required | Description |
|-----------|---------|----------|---------------------|
-| `scope` | string | no | The scope of specific runners to show, one of: `active`, `paused`, `online`, `offline`; showing all runners if none provided |
+| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online`, `offline`; showing all runners if none provided |
+| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
+| `status` | string | no | The status of runners to show, one of: `active`, `paused`, `online`, `offline` |
```
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners"
@@ -56,11 +60,15 @@ is restricted to users with `admin` privileges.
```
GET /runners/all
GET /runners/all?scope=online
+GET /runners/all?type=project_type
+GET /runners/all?status=active
```
| Attribute | Type | Required | Description |
|-----------|---------|----------|---------------------|
-| `scope` | string | no | The scope of runners to show, one of: `specific`, `shared`, `active`, `paused`, `online`, `offline`; showing all runners if none provided |
+| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of runners to show, one of: `specific`, `shared`, `active`, `paused`, `online`, `offline`; showing all runners if none provided |
+| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
+| `status` | string | no | The status of runners to show, one of: `active`, `paused`, `online`, `offline` |
```
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/runners/all"
@@ -286,6 +294,7 @@ Example response:
"created_at": "2017-11-16T18:38:46.000Z",
"bio": null,
"location": null,
+ "public_email": "",
"skype": "",
"linkedin": "",
"twitter": "",
@@ -331,16 +340,21 @@ Example response:
## List project's runners
List all runners (specific and shared) available in the project. Shared runners
-are listed if at least one shared runner is defined **and** shared runners
-usage is enabled in the project's settings.
+are listed if at least one shared runner is defined.
```
GET /projects/:id/runners
+GET /projects/:id/runners?scope=active
+GET /projects/:id/runners?type=project_type
+GET /projects/:id/runners?status=active
```
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|---------------------|
+| Attribute | Type | Required | Description |
+|-----------|----------------|----------|---------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online`, `offline`; showing all runners if none provided |
+| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
+| `status` | string | no | The status of runners to show, one of: `active`, `paused`, `online`, `offline` |
```
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/9/runners"
diff --git a/doc/api/services.md b/doc/api/services.md
index 741ea83070f..f122bac6f1f 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -10,7 +10,7 @@ Asana - Teamwork without email
Set Asana service for a project.
-> This service adds commit messages as comments to Asana tasks. Once enabled, commit messages are checked for Asana task URLs (for example, `https://app.asana.com/0/123456/987654`) or task IDs starting with # (for example, `#987654`). Every task ID found will get the commit comment added to it. You can also close a task with a message containing: `fix #123456`. You can find your Api Keys here: https://asana.com/developers/documentation/getting-started/auth#api-key
+> This service adds commit messages as comments to Asana tasks. Once enabled, commit messages are checked for Asana task URLs (for example, `https://app.asana.com/0/123456/987654`) or task IDs starting with # (for example, `#987654`). Every task ID found will get the commit comment added to it. You can also close a task with a message containing: `fix #123456`. You can find your Api Keys here: <https://asana.com/developers/documentation/getting-started/auth#api-key>.
```
PUT /projects/:id/services/asana
@@ -92,7 +92,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `bamboo_url` | string | true | Bamboo root URL like https://bamboo.example.com |
+| `bamboo_url` | string | true | Bamboo root URL. For example, `https://bamboo.example.com`. |
| `build_key` | string | true | Bamboo build plan key like KEY |
| `username` | string | true | A user with API access, if applicable |
| `password` | string | true | Password of the user |
@@ -117,7 +117,7 @@ GET /projects/:id/services/bamboo
Bugzilla Issue Tracker
-### Create/Edit Buildkite service
+### Create/Edit Bugzilla service
Set Bugzilla service for a project.
@@ -168,7 +168,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `token` | string | true | Buildkite project GitLab token |
-| `project_url` | string | true | https://buildkite.com/example/project |
+| `project_url` | string | true | `https://buildkite.com/example/project` |
| `enable_ssl_verification` | boolean | false | Enable SSL verification |
### Delete Buildkite service
@@ -278,7 +278,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `token` | string | true | Drone CI project specific token |
-| `drone_url` | string | true | http://drone.example.com |
+| `drone_url` | string | true | `http://drone.example.com` |
| `enable_ssl_verification` | boolean | false | Enable SSL verification |
### Delete Drone CI service
@@ -421,7 +421,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `webhook` | string | true | The Hangouts Chat webhook. e.g. https://chat.googleapis.com/v1/spaces... |
+| `webhook` | string | true | The Hangouts Chat webhook. For example, `https://chat.googleapis.com/v1/spaces...`. |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
| `notify_only_default_branch` | boolean | false | Send notifications only for the default branch |
| `push_events` | boolean | false | Enable notifications for push events |
@@ -470,7 +470,7 @@ Parameters:
| `notify` | boolean | false | Enable notifications |
| `room` | string | false |Room name or ID |
| `api_version` | string | false | Leave blank for default (v2) |
-| `server` | string | false | Leave blank for default. https://hipchat.example.com |
+| `server` | string | false | Leave blank for default. For example, `https://hipchat.example.com`. |
### Delete HipChat service
@@ -496,7 +496,7 @@ Send IRC messages, on update, to a list of recipients through an Irker gateway.
Set Irker (IRC gateway) service for a project.
-> NOTE: Irker does NOT have built-in authentication, which makes it vulnerable to spamming IRC channels if it is hosted outside of a firewall. Please make sure you run the daemon within a secured network to prevent abuse. For more details, read: http://www.catb.org/~esr/irker/security.html.
+> NOTE: Irker does NOT have built-in authentication, which makes it vulnerable to spamming IRC channels if it is hosted outside of a firewall. Please make sure you run the daemon within a secured network to prevent abuse. For more details, read: <http://www.catb.org/~esr/irker/security.html>.
```
PUT /projects/:id/services/irker
@@ -546,7 +546,7 @@ Set JIRA service for a project.
> **Notes:**
> - Starting with GitLab 8.14, `api_url`, `issues_url`, `new_issue_url` and
-> `project_url` are replaced by `project_key`, `url`. If you are using an
+> `project_url` are replaced by `project_key`, `url`. If you are using an
> older version, [follow this documentation][old-jira-api].
```
@@ -557,7 +557,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `url` | string | yes | The URL to the JIRA project which is being linked to this GitLab project, e.g., `https://jira.example.com`. |
+| `url` | string | yes | The URL to the JIRA project which is being linked to this GitLab project. For example, `https://jira.example.com`. |
| `project_key` | string | yes | The short identifier for your JIRA project, all uppercase, e.g., `PROJ`. |
| `username` | string | yes | The username of the user created to be used with GitLab/JIRA. |
| `password` | string | yes | The password of the user created to be used with GitLab/JIRA. |
@@ -589,7 +589,7 @@ PUT /projects/:id/services/kubernetes
Parameters:
- `namespace` (**required**) - The Kubernetes namespace to use
-- `api_url` (**required**) - The URL to the Kubernetes cluster API, e.g., https://kubernetes.example.com
+- `api_url` (**required**) - The URL to the Kubernetes cluster API. For example, `https://kubernetes.example.com`
- `token` (**required**) - The service token to authenticate against the Kubernetes cluster with
- `ca_pem` (optional) - A custom certificate authority bundle to verify the Kubernetes cluster with (PEM format)
@@ -658,7 +658,6 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `token` | string | yes | The Slack token |
-
### Delete Slack slash command service
Delete Slack slash command service for a project.
@@ -823,7 +822,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `api_url` | string | true | Prometheus API Base URL, like http://prometheus.example.com/ |
+| `api_url` | string | true | Prometheus API Base URL. For example, `http://prometheus.example.com/`. |
### Delete Prometheus service
@@ -934,7 +933,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `webhook` | string | true | https://hooks.slack.com/services/... |
+| `webhook` | string | true | `https://hooks.slack.com/services/...` |
| `username` | string | false | username |
| `channel` | string | false | Default channel to use if others are not configured |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
@@ -988,7 +987,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `webhook` | string | true | The Microsoft Teams webhook. e.g. https://outlook.office.com/webhook/... |
+| `webhook` | string | true | The Microsoft Teams webhook. For example, `https://outlook.office.com/webhook/...` |
### Delete Microsoft Teams service
@@ -1024,7 +1023,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `webhook` | string | true | The Mattermost webhook. e.g. http://mattermost_host/hooks/... |
+| `webhook` | string | true | The Mattermost webhook. For example, `http://mattermost_host/hooks/...` |
| `username` | string | false | username |
| `channel` | string | false | Default channel to use if others are not configured |
| `notify_only_broken_pipelines` | boolean | false | Send notifications for broken pipelines |
@@ -1080,7 +1079,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `teamcity_url` | string | true | TeamCity root URL like https://teamcity.example.com |
+| `teamcity_url` | string | true | TeamCity root URL. For example, `https://teamcity.example.com` |
| `build_type` | string | true | Build configuration ID |
| `username` | string | true | A user with permissions to trigger a manual build |
| `password` | string | true | The password of the user |
@@ -1104,7 +1103,6 @@ GET /projects/:id/services/teamcity
[jira-doc]: ../user/project/integrations/jira.md
[old-jira-api]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-13-stable/doc/api/services.md#jira
-
## MockCI
Mock an external CI. See [`gitlab-org/gitlab-mock-ci-service`](https://gitlab.com/gitlab-org/gitlab-mock-ci-service) for an example of a companion mock service.
@@ -1123,7 +1121,7 @@ Parameters:
| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `mock_service_url` | string | true | http://localhost:4004 |
+| `mock_service_url` | string | true | `http://localhost:4004` |
### Delete MockCI service
diff --git a/doc/api/settings.md b/doc/api/settings.md
index 83fa9b055d1..9b38e3a4eb7 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -1,3 +1,7 @@
+---
+table_display_block: true
+---
+
# Application settings API
These API calls allow you to read and modify GitLab instance
@@ -45,8 +49,6 @@ Example response:
"sign_in_text" : null,
"container_registry_token_expire_delay": 5,
"repository_storages": ["default"],
- "koding_enabled": false,
- "koding_url": null,
"plantuml_enabled": false,
"plantuml_url": null,
"terminal_max_session_time": 0,
@@ -103,8 +105,6 @@ Example response:
"after_sign_out_path": "",
"container_registry_token_expire_delay": 5,
"repository_storages": ["default"],
- "koding_enabled": false,
- "koding_url": null,
"plantuml_enabled": false,
"plantuml_url": null,
"terminal_max_session_time": 0,
@@ -138,11 +138,6 @@ are listed in the descriptions of the relevant settings.
| `authorized_keys_enabled` | boolean | no | By default, we write to the `authorized_keys` file to support Git over SSH without additional configuration. GitLab can be optimized to authenticate SSH keys via the database file. Only disable this if you have configured your OpenSSH server to use the AuthorizedKeysCommand. |
| `auto_devops_domain` | string | no | Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages. |
| `auto_devops_enabled` | boolean | no | Enable Auto DevOps for projects by default. It will automatically build, test, and deploy applications based on a predefined CI/CD configuration. |
-| `circuitbreaker_access_retries` | integer | no | The number of attempts GitLab will make to access a storage. |
-| `circuitbreaker_check_interval` | integer | no | Number of seconds in between storage checks. |
-| `circuitbreaker_failure_count_threshold` | integer | no | The number of failures after which GitLab will completely prevent access to the storage. |
-| `circuitbreaker_failure_reset_time` | integer | no | Time in seconds GitLab will keep storage failure information. When no failures occur during this time, the failure information is reset. |
-| `circuitbreaker_storage_timeout` | integer | no | Seconds to wait for a storage access attempt. |
| `clientside_sentry_dsn` | string | required by: `clientside_sentry_enabled` | Clientside Sentry Data Source Name. |
| `clientside_sentry_enabled` | boolean | no | (**If enabled, requires:** `clientside_sentry_dsn`) Enable Sentry error reporting for the client side. |
| `container_registry_token_expire_delay` | integer | no | Container Registry token duration in minutes. |
@@ -180,8 +175,6 @@ are listed in the descriptions of the relevant settings.
| `html_emails_enabled` | boolean | no | Enable HTML emails. |
| `instance_statistics_visibility_private` | boolean | no | When set to `true` Instance statistics will only be available to admins. |
| `import_sources` | array of strings | no | Sources to allow project import from, possible values: `github`, `bitbucket`, `gitlab`, `google_code`, `fogbugz`, `git`, and `gitlab_project`. |
-| `koding_enabled` | boolean | no | (If enabled, requires: `koding_url`) Enable Koding integration. Default is `false`. |
-| `koding_url` | string | required by: `koding_enabled` | The Koding instance URL for integration. |
| `max_artifacts_size` | integer | no | Maximum artifacts size in MB |
| `max_attachment_size` | integer | no | Limit attachment size in MB |
| `max_pages_size` | integer | no | Maximum size of pages repositories in MB |
@@ -193,7 +186,7 @@ are listed in the descriptions of the relevant settings.
| `metrics_port` | integer | required by: `metrics_enabled` | The UDP port to use for connecting to InfluxDB. |
| `metrics_sample_interval` | integer | required by: `metrics_enabled` | The sampling interval in seconds. |
| `metrics_timeout` | integer | required by: `metrics_enabled` | The amount of seconds after which InfluxDB will time out. |
-| `mirror_available` | boolean | no | Allow mirrors to be setup for projects. If disabled, only admins will be able to setup mirrors in projects. |
+| `mirror_available` | boolean | no | Allow mirrors to be set up for projects. If disabled, only admins will be able to set up mirrors in projects. |
| `pages_domain_verification_enabled` | boolean | no | Require users to prove ownership of custom domains. Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled. |
| `password_authentication_enabled_for_git` | boolean | no | Enable authentication for Git over HTTP(S) via a GitLab account password. Default is `true`. |
| `password_authentication_enabled_for_web` | boolean | no | Enable authentication for the web interface via a GitLab account password. Default is `true`. |
@@ -219,9 +212,6 @@ are listed in the descriptions of the relevant settings.
| `session_expire_delay` | integer | no | Session duration in minutes. GitLab restart is required to apply changes |
| `shared_runners_enabled` | boolean | no | (**If enabled, requires:** `shared_runners_text`) Enable shared runners for new projects. |
| `shared_runners_text` | string | required by: `shared_runners_enabled` | Shared runners text. |
-| `sidekiq_throttling_enabled` | boolean | no | (**If enabled, requires:** `sidekiq_throttling_factor` and `sidekiq_throttling_queues`) Enable Sidekiq Job Throttling. |
-| `sidekiq_throttling_factor` | decimal | required by: `sidekiq_throttling_enabled` | The factor by which the queues should be throttled. A value between `0.0` and `1.0`, exclusive. |
-| `sidekiq_throttling_queues` | array of strings | required by: `sidekiq_throttling_enabled` | Choose which queues you wish to throttle. |
| `sign_in_text` | string | no | Text on the login page. |
| `signin_enabled` | string | no | (Deprecated: Use `password_authentication_enabled_for_web` instead) Flag indicating if password authentication is enabled for the web interface. |
| `signup_enabled` | boolean | no | Enable registration. Default is `true`. |
diff --git a/doc/api/snippets.md b/doc/api/snippets.md
index 7892866cd8e..e840e640377 100644
--- a/doc/api/snippets.md
+++ b/doc/api/snippets.md
@@ -37,13 +37,13 @@ Parameters:
| --------- | ---- | -------- | ----------- |
| `id` | Integer | yes | The ID of a snippet |
-``` bash
+```bash
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/snippets/1
```
Example response:
-``` json
+```json
{
"id": 1,
"title": "test",
@@ -65,6 +65,30 @@ Example response:
}
```
+## Single snippet contents
+
+Get a single snippet's raw contents.
+
+```
+GET /snippets/:id/raw
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | Integer | yes | The ID of a snippet |
+
+```bash
+curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/snippets/1/raw
+```
+
+Example response:
+
+```
+Hello World snippet
+```
+
## Create new snippet
Creates a new snippet. The user must have permission to create new snippets.
@@ -84,7 +108,7 @@ Parameters:
| `visibility` | String | no | The snippet's visibility |
-``` bash
+```bash
curl --request POST \
--data '{"title": "This is a snippet", "content": "Hello world", "description": "Hello World snippet", "file_name": "test.txt", "visibility": "internal" }' \
--header 'Content-Type: application/json' \
@@ -94,7 +118,7 @@ curl --request POST \
Example response:
-``` json
+```json
{
"id": 1,
"title": "This is a snippet",
@@ -136,7 +160,7 @@ Parameters:
| `visibility` | String | no | The snippet's visibility |
-``` bash
+```bash
curl --request PUT \
--data '{"title": "foo", "content": "bar"}' \
--header 'Content-Type: application/json' \
@@ -146,7 +170,7 @@ curl --request PUT \
Example response:
-``` json
+```json
{
"id": 1,
"title": "test",
@@ -201,13 +225,13 @@ GET /snippets/public
| `per_page` | Integer | no | number of snippets to return per page |
| `page` | Integer | no | the page to retrieve |
-``` bash
+```bash
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/snippets/public?per_page=2&page=1
```
Example response:
-``` json
+```json
[
{
"author": {
diff --git a/doc/api/tags.md b/doc/api/tags.md
index f2a3f9f28d2..826900ca518 100644
--- a/doc/api/tags.md
+++ b/doc/api/tags.md
@@ -134,7 +134,7 @@ Parameters:
"description": "Amazing release. Wow"
},
"name": "v1.0.0",
- "target: "2695effb5807a22ff3d138d593fd856244e155e7",
+ "target": "2695effb5807a22ff3d138d593fd856244e155e7",
"message": null
}
```
diff --git a/doc/api/templates/dockerfiles.md b/doc/api/templates/dockerfiles.md
new file mode 100644
index 00000000000..a08b8d33693
--- /dev/null
+++ b/doc/api/templates/dockerfiles.md
@@ -0,0 +1,113 @@
+# Dockerfiles API
+
+## List Dockerfile templates
+
+Get all Dockerfile templates.
+
+```
+GET /templates/dockerfiles
+```
+
+```bash
+curl https://gitlab.example.com/api/v4/templates/dockerfiles
+```
+
+Example response:
+
+```json
+[
+ {
+ "key": "Binary",
+ "name": "Binary"
+ },
+ {
+ "key": "Binary-alpine",
+ "name": "Binary-alpine"
+ },
+ {
+ "key": "Binary-scratch",
+ "name": "Binary-scratch"
+ },
+ {
+ "key": "Golang",
+ "name": "Golang"
+ },
+ {
+ "key": "Golang-alpine",
+ "name": "Golang-alpine"
+ },
+ {
+ "key": "Golang-scratch",
+ "name": "Golang-scratch"
+ },
+ {
+ "key": "HTTPd",
+ "name": "HTTPd"
+ },
+ {
+ "key": "Node",
+ "name": "Node"
+ },
+ {
+ "key": "Node-alpine",
+ "name": "Node-alpine"
+ },
+ {
+ "key": "OpenJDK",
+ "name": "OpenJDK"
+ },
+ {
+ "key": "OpenJDK-alpine",
+ "name": "OpenJDK-alpine"
+ },
+ {
+ "key": "PHP",
+ "name": "PHP"
+ },
+ {
+ "key": "Python",
+ "name": "Python"
+ },
+ {
+ "key": "Python-alpine",
+ "name": "Python-alpine"
+ },
+ {
+ "key": "Python2",
+ "name": "Python2"
+ },
+ {
+ "key": "Ruby",
+ "name": "Ruby"
+ },
+ {
+ "key": "Ruby-alpine",
+ "name": "Ruby-alpine"
+ }
+]
+```
+
+## Single Dockerfile template
+
+Get a single Dockerfile template.
+
+```
+GET /templates/dockerfiles/:key
+```
+
+| Attribute | Type | Required | Description |
+| ---------- | ------ | -------- | ----------- |
+| `key` | string | yes | The key of the Dockerfile template |
+
+```bash
+curl https://gitlab.example.com/api/v4/templates/dockerfiles/Binary
+```
+
+Example response:
+
+```json
+{
+ "name": "Binary",
+ "content": "# This file is a template, and might need editing before it works on your project.\n# This Dockerfile installs a compiled binary into a bare system.\n# You must either commit your compiled binary into source control (not recommended)\n# or build the binary first as part of a CI/CD pipeline.\n\nFROM buildpack-deps:jessie\n\nWORKDIR /usr/local/bin\n\n# Change `app` to whatever your binary is called\nAdd app .\nCMD [\"./app\"]\n"
+}
+```
diff --git a/doc/api/templates/gitignores.md b/doc/api/templates/gitignores.md
index d3f5c88ca90..3804855129c 100644
--- a/doc/api/templates/gitignores.md
+++ b/doc/api/templates/gitignores.md
@@ -17,538 +17,84 @@ Example response:
```json
[
{
- "name": "AppEngine"
- },
- {
- "name": "Laravel"
- },
- {
- "name": "Elisp"
- },
- {
- "name": "SketchUp"
+ "key": "Actionscript",
+ "name": "Actionscript"
},
{
+ "key": "Ada",
"name": "Ada"
},
{
- "name": "Ruby"
- },
- {
- "name": "Kohana"
- },
- {
- "name": "Nanoc"
- },
- {
- "name": "Erlang"
- },
- {
- "name": "OCaml"
- },
- {
- "name": "Lithium"
- },
- {
- "name": "Fortran"
- },
- {
- "name": "Scala"
- },
- {
- "name": "Node"
- },
- {
- "name": "Fancy"
- },
- {
- "name": "Perl"
- },
- {
- "name": "Zephir"
- },
- {
- "name": "WordPress"
- },
- {
- "name": "Symfony"
- },
- {
- "name": "FuelPHP"
- },
- {
- "name": "DM"
- },
- {
- "name": "Sdcc"
- },
- {
- "name": "Rust"
- },
- {
- "name": "C"
- },
- {
- "name": "Umbraco"
- },
- {
- "name": "Actionscript"
+ "key": "Agda",
+ "name": "Agda"
},
{
+ "key": "Android",
"name": "Android"
},
{
- "name": "Grails"
- },
- {
- "name": "Composer"
- },
- {
- "name": "ExpressionEngine"
- },
- {
- "name": "Gcov"
- },
- {
- "name": "Qt"
+ "key": "AppEngine",
+ "name": "AppEngine"
},
{
- "name": "Phalcon"
+ "key": "AppceleratorTitanium",
+ "name": "AppceleratorTitanium"
},
{
+ "key": "ArchLinuxPackages",
"name": "ArchLinuxPackages"
},
{
- "name": "TeX"
- },
- {
- "name": "SCons"
- },
- {
- "name": "Lilypond"
- },
- {
- "name": "CommonLisp"
- },
- {
- "name": "Rails"
- },
- {
- "name": "Mercury"
- },
- {
- "name": "Magento"
- },
- {
- "name": "ChefCookbook"
- },
- {
- "name": "GitBook"
- },
- {
- "name": "C++"
- },
- {
- "name": "Eagle"
- },
- {
- "name": "Go"
- },
- {
- "name": "OpenCart"
- },
- {
- "name": "Scheme"
- },
- {
- "name": "Typo3"
- },
- {
- "name": "SeamGen"
- },
- {
- "name": "Swift"
- },
- {
- "name": "Elm"
- },
- {
- "name": "Unity"
- },
- {
- "name": "Agda"
- },
- {
- "name": "CUDA"
- },
- {
- "name": "VVVV"
- },
- {
- "name": "Finale"
- },
- {
- "name": "LemonStand"
- },
- {
- "name": "Textpattern"
- },
- {
- "name": "Julia"
- },
- {
- "name": "Packer"
- },
- {
- "name": "Scrivener"
- },
- {
- "name": "Dart"
- },
- {
- "name": "Plone"
- },
- {
- "name": "Jekyll"
- },
- {
- "name": "Xojo"
- },
- {
- "name": "LabVIEW"
- },
- {
+ "key": "Autotools",
"name": "Autotools"
},
{
- "name": "KiCad"
- },
- {
- "name": "Prestashop"
- },
- {
- "name": "ROS"
- },
- {
- "name": "Smalltalk"
- },
- {
- "name": "GWT"
- },
- {
- "name": "OracleForms"
- },
- {
- "name": "SugarCRM"
- },
- {
- "name": "Nim"
- },
- {
- "name": "SymphonyCMS"
+ "key": "C",
+ "name": "C"
},
{
- "name": "Maven"
+ "key": "C++",
+ "name": "C++"
},
{
+ "key": "CFWheels",
"name": "CFWheels"
},
{
- "name": "Python"
- },
- {
- "name": "ZendFramework"
- },
- {
- "name": "CakePHP"
- },
- {
- "name": "Concrete5"
- },
- {
- "name": "PlayFramework"
- },
- {
- "name": "Terraform"
- },
- {
- "name": "Elixir"
- },
- {
+ "key": "CMake",
"name": "CMake"
},
{
- "name": "Joomla"
- },
- {
- "name": "Coq"
- },
- {
- "name": "Delphi"
- },
- {
- "name": "Haskell"
- },
- {
- "name": "Yii"
- },
- {
- "name": "Java"
- },
- {
- "name": "UnrealEngine"
- },
- {
- "name": "AppceleratorTitanium"
- },
- {
- "name": "CraftCMS"
- },
- {
- "name": "ForceDotCom"
- },
- {
- "name": "ExtJs"
- },
- {
- "name": "MetaProgrammingSystem"
- },
- {
- "name": "D"
- },
- {
- "name": "Objective-C"
- },
- {
- "name": "RhodesRhomobile"
- },
- {
- "name": "R"
- },
- {
- "name": "EPiServer"
- },
- {
- "name": "Yeoman"
- },
- {
- "name": "VisualStudio"
- },
- {
- "name": "Processing"
- },
- {
- "name": "Leiningen"
- },
- {
- "name": "Stella"
- },
- {
- "name": "Opa"
- },
- {
- "name": "Drupal"
- },
- {
- "name": "TurboGears2"
- },
- {
- "name": "Idris"
- },
- {
- "name": "Jboss"
- },
- {
- "name": "CodeIgniter"
- },
- {
- "name": "Qooxdoo"
- },
- {
- "name": "Waf"
+ "key": "CUDA",
+ "name": "CUDA"
},
{
- "name": "Sass"
+ "key": "CakePHP",
+ "name": "CakePHP"
},
{
- "name": "Lua"
+ "key": "ChefCookbook",
+ "name": "ChefCookbook"
},
{
+ "key": "Clojure",
"name": "Clojure"
},
{
- "name": "IGORPro"
- },
- {
- "name": "Gradle"
- },
- {
- "name": "Archives"
- },
- {
- "name": "SynopsysVCS"
- },
- {
- "name": "Ninja"
- },
- {
- "name": "Tags"
- },
- {
- "name": "OSX"
- },
- {
- "name": "Dreamweaver"
- },
- {
- "name": "CodeKit"
- },
- {
- "name": "NotepadPP"
- },
- {
- "name": "VisualStudioCode"
- },
- {
- "name": "Mercurial"
- },
- {
- "name": "BricxCC"
- },
- {
- "name": "DartEditor"
- },
- {
- "name": "Eclipse"
- },
- {
- "name": "Cloud9"
- },
- {
- "name": "TortoiseGit"
- },
- {
- "name": "NetBeans"
- },
- {
- "name": "GPG"
- },
- {
- "name": "Espresso"
- },
- {
- "name": "Redcar"
- },
- {
- "name": "Xcode"
- },
- {
- "name": "Matlab"
- },
- {
- "name": "LyX"
- },
- {
- "name": "SlickEdit"
- },
- {
- "name": "Dropbox"
- },
- {
- "name": "CVS"
- },
- {
- "name": "Calabash"
- },
- {
- "name": "JDeveloper"
- },
- {
- "name": "Vagrant"
- },
- {
- "name": "IPythonNotebook"
- },
- {
- "name": "TextMate"
- },
- {
- "name": "Ensime"
- },
- {
- "name": "WebMethods"
- },
- {
- "name": "VirtualEnv"
- },
- {
- "name": "Emacs"
- },
- {
- "name": "Momentics"
- },
- {
- "name": "JetBrains"
- },
- {
- "name": "SublimeText"
- },
- {
- "name": "Kate"
- },
- {
- "name": "ModelSim"
- },
- {
- "name": "Redis"
- },
- {
- "name": "KDevelop4"
- },
- {
- "name": "Bazaar"
- },
- {
- "name": "Linux"
- },
- {
- "name": "Windows"
- },
- {
- "name": "XilinxISE"
- },
- {
- "name": "Lazarus"
- },
- {
- "name": "EiffelStudio"
- },
- {
- "name": "Anjuta"
- },
- {
- "name": "Vim"
- },
- {
- "name": "Otto"
- },
- {
- "name": "MicrosoftOffice"
- },
- {
- "name": "LibreOffice"
- },
- {
- "name": "SBT"
+ "key": "CodeIgniter",
+ "name": "CodeIgniter"
},
{
- "name": "MonoDevelop"
+ "key": "CommonLisp",
+ "name": "CommonLisp"
},
{
- "name": "SVN"
+ "key": "Composer",
+ "name": "Composer"
},
{
- "name": "FlexBuilder"
+ "key": "Concrete5",
+ "name": "Concrete5"
}
]
```
diff --git a/doc/api/templates/gitlab_ci_ymls.md b/doc/api/templates/gitlab_ci_ymls.md
index bdb128fc336..cecfc8cd9b9 100644
--- a/doc/api/templates/gitlab_ci_ymls.md
+++ b/doc/api/templates/gitlab_ci_ymls.md
@@ -17,79 +17,84 @@ Example response:
```json
[
{
- "name": "C++"
- },
- {
- "name": "Docker"
- },
- {
- "name": "Elixir"
- },
- {
- "name": "LaTeX"
- },
- {
- "name": "Grails"
- },
- {
- "name": "Rust"
+ "key": "Android",
+ "name": "Android"
},
{
- "name": "Nodejs"
+ "key": "Auto-DevOps",
+ "name": "Auto-DevOps"
},
{
- "name": "Ruby"
+ "key": "Bash",
+ "name": "Bash"
},
{
- "name": "Scala"
+ "key": "C++",
+ "name": "C++"
},
{
- "name": "Maven"
+ "key": "Chef",
+ "name": "Chef"
},
{
- "name": "Harp"
+ "key": "Clojure",
+ "name": "Clojure"
},
{
- "name": "Pelican"
+ "key": "Crystal",
+ "name": "Crystal"
},
{
- "name": "Hyde"
+ "key": "Django",
+ "name": "Django"
},
{
- "name": "Nanoc"
+ "key": "Docker",
+ "name": "Docker"
},
{
- "name": "Octopress"
+ "key": "Elixir",
+ "name": "Elixir"
},
{
- "name": "JBake"
+ "key": "Go",
+ "name": "Go"
},
{
- "name": "HTML"
+ "key": "Gradle",
+ "name": "Gradle"
},
{
- "name": "Hugo"
+ "key": "Grails",
+ "name": "Grails"
},
{
- "name": "Metalsmith"
+ "key": "Julia",
+ "name": "Julia"
},
{
- "name": "Hexo"
+ "key": "LaTeX",
+ "name": "LaTeX"
},
{
- "name": "Lektor"
+ "key": "Laravel",
+ "name": "Laravel"
},
{
- "name": "Doxygen"
+ "key": "Maven",
+ "name": "Maven"
},
{
- "name": "Brunch"
+ "key": "Mono",
+ "name": "Mono"
},
{
- "name": "Jekyll"
+ "key": "Nodejs",
+ "name": "Nodejs"
},
{
- "name": "Middleman"
+ "key": "OpenShift",
+ "name": "OpenShift"
}
]
```
diff --git a/doc/api/users.md b/doc/api/users.md
index b0ae455a025..1cf4444319c 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -59,6 +59,9 @@ GET /users?active=true
GET /users?blocked=true
```
+NOTE: **Note:**
+Username search is case insensitive.
+
### For admins
```
@@ -67,8 +70,8 @@ GET /users
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `order_by` | string | no | Return projects ordered by `id`, `name`, `username`, `created_at`, or `updated_at` fields. Default is `id` |
-| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
+| `order_by` | string | no | Return users ordered by `id`, `name`, `username`, `created_at`, or `updated_at` fields. Default is `id` |
+| `sort` | string | no | Return users sorted in `asc` or `desc` order. Default is `desc` |
| `two_factor` | string | no | Filter users by Two-factor authentication. Filter values are `enabled` or `disabled`. By default it returns all users |
```json
@@ -199,6 +202,7 @@ Parameters:
"created_at": "2012-05-23T08:00:58Z",
"bio": null,
"location": null,
+ "public_email": "john@example.com",
"skype": "",
"linkedin": "",
"twitter": "",
@@ -230,6 +234,7 @@ Parameters:
"is_admin": false,
"bio": null,
"location": null,
+ "public_email": "john@example.com",
"skype": "",
"linkedin": "",
"twitter": "",
@@ -286,6 +291,7 @@ Parameters:
- `provider` (optional) - External provider name
- `bio` (optional) - User's biography
- `location` (optional) - User's location
+- `public_email` (optional) - The public email of the user
- `admin` (optional) - User is admin - true or false (default)
- `can_create_group` (optional) - User can create groups - true or false
- `skip_confirmation` (optional) - Skip confirmation - true or false (default)
@@ -303,26 +309,27 @@ PUT /users/:id
Parameters:
-- `email` - Email
-- `username` - Username
-- `name` - Name
-- `password` - Password
-- `skype` - Skype ID
-- `linkedin` - LinkedIn
-- `twitter` - Twitter account
-- `website_url` - Website URL
-- `organization` - Organization name
-- `projects_limit` - Limit projects each user can create
-- `extern_uid` - External UID
-- `provider` - External provider name
-- `bio` - User's biography
-- `location` (optional) - User's location
-- `admin` (optional) - User is admin - true or false (default)
-- `can_create_group` (optional) - User can create groups - true or false
+- `email` - Email
+- `username` - Username
+- `name` - Name
+- `password` - Password
+- `skype` - Skype ID
+- `linkedin` - LinkedIn
+- `twitter` - Twitter account
+- `website_url` - Website URL
+- `organization` - Organization name
+- `projects_limit` - Limit projects each user can create
+- `extern_uid` - External UID
+- `provider` - External provider name
+- `bio` - User's biography
+- `location` (optional) - User's location
+- `public_email` (optional) - The public email of the user
+- `admin` (optional) - User is admin - true or false (default)
+- `can_create_group` (optional) - User can create groups - true or false
- `skip_reconfirmation` (optional) - Skip reconfirmation - true or false (default)
-- `external` (optional) - Flags the user as external - true or false(default)
-- `avatar` (optional) - Image file for user's avatar
-- `private_profile` (optional) - User's profile is private - true or false
+- `external` (optional) - Flags the user as external - true or false(default)
+- `avatar` (optional) - Image file for user's avatar
+- `private_profile` (optional) - User's profile is private - true or false
On password update, user will be forced to change it upon next login.
Note, at the moment this method does only return a `404` error,
@@ -367,6 +374,7 @@ GET /user
"created_at": "2012-05-23T08:00:58Z",
"bio": null,
"location": null,
+ "public_email": "john@example.com",
"skype": "",
"linkedin": "",
"twitter": "",
@@ -415,6 +423,7 @@ GET /user
"is_admin": false,
"bio": null,
"location": null,
+ "public_email": "john@example.com",
"skype": "",
"linkedin": "",
"twitter": "",
@@ -552,7 +561,7 @@ Parameters:
## List SSH keys for user
-Get a list of a specified user's SSH keys. Available only for admin
+Get a list of a specified user's SSH keys.
```
GET /users/:id/keys
@@ -1063,7 +1072,6 @@ Example response:
[
{
"active" : true,
- "token" : "EsMo-vhKfXGwX9RKrwiy",
"scopes" : [
"api"
],
@@ -1080,7 +1088,6 @@ Example response:
"read_user"
],
"revoked" : true,
- "token" : "ZcZRpLeEuQRprkRjYydY",
"name" : "mytoken2",
"created_at" : "2017-03-17T17:19:28.697Z",
"id" : 3,
@@ -1116,7 +1123,6 @@ Example response:
```json
{
"active" : true,
- "token" : "EsMo-vhKfXGwX9RKrwiy",
"scopes" : [
"api"
],
@@ -1133,6 +1139,8 @@ Example response:
> Requires admin permissions.
+> Token values are returned once. Make sure you save it - you won't be able to access it again.
+
It creates a new impersonation token. Note that only administrators can do this.
You are only able to create impersonation tokens to impersonate the user and perform
both API calls and Git reads and writes. The user will not see these tokens in their profile
diff --git a/doc/api/wikis.md b/doc/api/wikis.md
index fb0ec773da5..df3b54e8f89 100644
--- a/doc/api/wikis.md
+++ b/doc/api/wikis.md
@@ -65,14 +65,12 @@ curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/a
Example response:
```json
-[
- {
- "content" : "home page",
- "format" : "markdown",
- "slug" : "home",
- "title" : "home"
- }
-]
+{
+ "content" : "home page",
+ "format" : "markdown",
+ "slug" : "home",
+ "title" : "home"
+}
```
## Create a new wiki page
diff --git a/doc/ci/README.md b/doc/ci/README.md
index d782d64e971..dba1f38abe2 100644
--- a/doc/ci/README.md
+++ b/doc/ci/README.md
@@ -132,5 +132,3 @@ your whole GitLab instance as well as in each project.
- [New CI job permissions model](../user/project/new_ci_build_permissions_model.md)
Read about what changed in GitLab 8.12 and how that affects your jobs.
There's a new way to access your Git submodules and LFS objects in jobs.
-
-[gitlab-ci-templates]: https://gitlab.com/gitlab-org/gitlab-ci-yml
diff --git a/doc/ci/autodeploy/quick_start_guide.md b/doc/ci/autodeploy/quick_start_guide.md
index cc6c9ec0e0a..1473703542d 100644
--- a/doc/ci/autodeploy/quick_start_guide.md
+++ b/doc/ci/autodeploy/quick_start_guide.md
@@ -11,7 +11,7 @@ We made a minimal [Ruby application](https://gitlab.com/gitlab-examples/minimal-
Let’s start by forking our sample application. Go to [the project page](https://gitlab.com/gitlab-examples/minimal-ruby-app) and press the `Fork` button. Soon you should have a project under your namespace with the necessary files.
-## Setup your own cluster on Google Kubernetes Engine
+## Set up your own cluster on Google Kubernetes Engine
If you do not already have a Google Cloud account, create one at https://console.cloud.google.com.
@@ -23,9 +23,9 @@ You need to have the Google Cloud SDK installed. e.g.
On OSX, install [homebrew](https://brew.sh):
1. Install Brew Caskroom: `brew install caskroom/cask/brew-cask`
-2. Install Google Cloud SDK: `brew cask install google-cloud-sdk`
-3. Add `kubectl`: `gcloud components install kubectl`
-4. Log in: `gcloud auth login`
+1. Install Google Cloud SDK: `brew cask install google-cloud-sdk`
+1. Add `kubectl`: `gcloud components install kubectl`
+1. Log in: `gcloud auth login`
Now go back to the Google interface, find your cluster, and follow the instructions under `Connect to the cluster` and open the Kubernetes Dashboard. It will look something like `gcloud container clusters get-credentials ruby-autodeploy \ --zone europe-west2-c --project api-project-XXXXXXX` and then `kubectl proxy`.
@@ -71,7 +71,7 @@ Use this IP address to configure your DNS. This part heavily depends on your pre
Use `nslookup minimal-ruby-app-staging.<yourdomain>` to confirm that domain is assigned to the cluster IP.
-## Setup Auto Deploy
+## Set up Auto Deploy
Visit the home page of your GitLab.com project and press "Set up Auto Deploy" button.
diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md
index b41101695f6..758ab37861b 100644
--- a/doc/ci/caching/index.md
+++ b/doc/ci/caching/index.md
@@ -178,8 +178,8 @@ runs of jobs for things like dependencies and commonly used libraries
so they don't have to be re-fetched from the public internet.
NOTE: **Note:**
-For more examples, check the [GitLab CI Yml](https://gitlab.com/gitlab-org/gitlab-ci-yml)
-project.
+For more examples, check out our [GitLab CI/CD
+templates](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/gitlab/ci/templates).
### Caching Nodejs dependencies
@@ -190,7 +190,7 @@ Nodejs modules are installed in `node_modules/` and are cached per-branch:
```yaml
#
-# https://gitlab.com/gitlab-org/gitlab-ci-yml/blob/master/Nodejs.gitlab-ci.yml
+# https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml
#
image: node:latest
@@ -217,7 +217,7 @@ are cached per-branch:
```yaml
#
-# https://gitlab.com/gitlab-org/gitlab-ci-yml/blob/master/PHP.gitlab-ci.yml
+# https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/gitlab/ci/templates/PHP.gitlab-ci.yml
#
image: php:7.2
@@ -246,14 +246,14 @@ pip's cache is defined under `.cache/pip/` and both are cached per-branch:
```yaml
#
-# https://gitlab.com/gitlab-org/gitlab-ci-yml/blob/master/Python.gitlab-ci.yml
+# https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/gitlab/ci/templates/Python.gitlab-ci.yml
#
image: python:latest
# Change pip's cache directory to be inside the project directory since we can
# only cache local items.
variables:
- PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache"
+ PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
# Pip's cache doesn't store the python packages
# https://pip.pypa.io/en/stable/reference/pip_install/#caching
@@ -262,7 +262,7 @@ variables:
# them in a virtualenv and cache it as well.
cache:
paths:
- - .cache/
+ - .cache/pip
- venv/
before_script:
@@ -286,7 +286,7 @@ jobs inherit it. Gems are installed in `vendor/ruby/` and are cached per-branch:
```yaml
#
-# https://gitlab.com/gitlab-org/gitlab-ci-yml/blob/master/Ruby.gitlab-ci.yml
+# https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
#
image: ruby:2.5
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index aa997d15b64..fef367051bf 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -46,18 +46,18 @@ GitLab Runner then executes job scripts as the `gitlab-runner` user.
--description "My Runner"
```
-2. Install Docker Engine on server.
+1. Install Docker Engine on server.
For more information how to install Docker Engine on different systems
checkout the [Supported installations](https://docs.docker.com/engine/installation/).
-3. Add `gitlab-runner` user to `docker` group:
+1. Add `gitlab-runner` user to `docker` group:
```bash
sudo usermod -aG docker gitlab-runner
```
-4. Verify that `gitlab-runner` has access to Docker:
+1. Verify that `gitlab-runner` has access to Docker:
```bash
sudo -u gitlab-runner -H docker info
@@ -75,7 +75,7 @@ GitLab Runner then executes job scripts as the `gitlab-runner` user.
- docker run my-docker-image /script/to/run/tests
```
-5. You can now use `docker` command and install `docker-compose` if needed.
+1. You can now use `docker` command and install `docker-compose` if needed.
NOTE: **Note:**
By adding `gitlab-runner` to the `docker` group you are effectively granting `gitlab-runner` full root permissions.
@@ -314,8 +314,8 @@ build:
stage: build
script:
- docker pull $CONTAINER_IMAGE:latest || true
- - docker build --cache-from $CONTAINER_IMAGE:latest --tag $CONTAINER_IMAGE:$CI_BUILD_REF --tag $CONTAINER_IMAGE:latest .
- - docker push $CONTAINER_IMAGE:$CI_BUILD_REF
+ - docker build --cache-from $CONTAINER_IMAGE:latest --tag $CONTAINER_IMAGE:$CI_COMMIT_SHA --tag $CONTAINER_IMAGE:latest .
+ - docker push $CONTAINER_IMAGE:$CI_COMMIT_SHA
- docker push $CONTAINER_IMAGE:latest
```
@@ -395,8 +395,67 @@ If you're running multiple Runners you will have to modify all configuration fil
> login to GitLab's Container Registry.
Once you've built a Docker image, you can push it up to the built-in
-[GitLab Container Registry](../../user/project/container_registry.md). For example,
-if you're using docker-in-docker on your runners, this is how your `.gitlab-ci.yml`
+[GitLab Container Registry](../../user/project/container_registry.md).
+Some things you should be aware of:
+
+- You must [log in to the container registry](#authenticating-to-the-container-registry)
+ before running commands. You can do this in the `before_script` if multiple
+ jobs depend on it.
+- Using `docker build --pull` fetches any changes to base
+ images before building just in case your cache is stale. It takes slightly
+ longer, but means you don’t get stuck without security patches to base images.
+- Doing an explicit `docker pull` before each `docker run` fetches
+ the latest image that was just built. This is especially important if you are
+ using multiple runners that cache images locally. Using the git SHA in your
+ image tag makes this less necessary since each job will be unique and you
+ shouldn't ever have a stale image. However, it's still possible to have a
+ stale image if you re-build a given commit after a dependency has changed.
+- You don't want to build directly to `latest` tag in case there are multiple jobs
+ happening simultaneously.
+
+### Authenticating to the Container Registry
+
+There are three ways to authenticate to the Container Registry via GitLab CI/CD
+and depend on the visibility of your project.
+
+For all projects, mostly suitable for public ones:
+
+- **Using the special `gitlab-ci-token` user**: This user is created for you in order to
+ push to the Registry connected to your project. Its password is automatically
+ set with the `$CI_JOB_TOKEN` variable. This allows you to automate building and deploying
+ your Docker images and has read/write access to the Registry. This is ephemeral,
+ so it's only valid for one job. You can use the following example as-is:
+
+ ```sh
+ docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
+ ```
+
+For private and internal projects:
+
+- **Using a personal access token**: You can create and use a
+ [personal access token](../../user/profile/personal_access_tokens.md)
+ in case your project is private:
+ - For read (pull) access, the scope should be `read_registry`.
+ - For read/write (pull/push) access, use `api`.
+ Replace the `<username>` and `<access_token>` in the following example:
+
+ ```sh
+ docker login -u <username> -p <access_token> $CI_REGISTRY
+ ```
+
+- **Using the GitLab Deploy Token**: You can create and use a
+ [special deploy token](../../user/project/deploy_tokens/index.md#gitlab-deploy-token)
+ with your private projects. It provides read-only (pull) access to the Registry.
+ Once created, you can use the special environment variables, and GitLab CI/CD
+ will fill them in for you. You can use the following example as-is:
+
+ ```sh
+ docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY
+ ```
+
+### Container Registry examples
+
+If you're using docker-in-docker on your Runners, this is how your `.gitlab-ci.yml`
could look like:
```yaml
@@ -414,11 +473,6 @@ could look like:
- docker push registry.example.com/group/project/image:latest
```
-You have to use the special `gitlab-ci-token` user created for you in order to
-push to the Registry connected to your project. Its password is provided in the
-`$CI_JOB_TOKEN` variable. This allows you to automate building and deployment
-of your Docker images.
-
You can also make use of [other variables](../variables/README.md) to avoid hardcoding:
```yaml
@@ -508,22 +562,6 @@ deploy:
- master
```
-Some things you should be aware of when using the Container Registry:
-
-- You must log in to the container registry before running commands. Putting
- this in `before_script` will run it before each job.
-- Using `docker build --pull` makes sure that Docker fetches any changes to base
- images before building just in case your cache is stale. It takes slightly
- longer, but means you don’t get stuck without security patches to base images.
-- Doing an explicit `docker pull` before each `docker run` makes sure to fetch
- the latest image that was just built. This is especially important if you are
- using multiple runners that cache images locally. Using the git SHA in your
- image tag makes this less necessary since each job will be unique and you
- shouldn't ever have a stale image, but it's still possible if you re-build a
- given commit after a dependency has changed.
-- You don't want to build directly to `latest` in case there are multiple jobs
- happening simultaneously.
-
[docker-in-docker]: https://blog.docker.com/2013/09/docker-can-now-run-within-docker/
[docker-cap]: https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities
[2fa]: ../../user/profile/account/two_factor_authentication.md
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index 9abedcc6acb..959271d8abc 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -67,6 +67,9 @@ services you need to `.gitlab-ci.yml` or manually modify `config.toml`.
Any image found at [Docker Hub][hub] or your private Container Registry can be
used as a service.
+Services inherit the same DNS servers, search domains, and additional hosts as
+the CI container itself.
+
You can see some widely used services examples in the relevant documentation of
[CI services examples](../services/README.md).
@@ -461,25 +464,25 @@ that runner.
> - If the repository is private you need to authenticate your GitLab Runner in the
> registry. Learn more about how [GitLab Runner works in this case][runner-priv-reg].
-As an example, let's assume that you want to use the `registry.example.com/private/image:latest`
+As an example, let's assume that you want to use the `registry.example.com:5000/private/image:latest`
image which is private and requires you to login into a private container registry.
Let's also assume that these are the login credentials:
-| Key | Value |
-|----------|----------------------|
-| registry | registry.example.com |
-| username | my_username |
-| password | my_password |
+| Key | Value |
+|----------|---------------------------|
+| registry | registry.example.com:5000 |
+| username | my_username |
+| password | my_password |
-To configure access for `registry.example.com`, follow these steps:
+To configure access for `registry.example.com:5000`, follow these steps:
1. Find what the value of `DOCKER_AUTH_CONFIG` should be. There are two ways to
accomplish this:
- **First way -** Do a `docker login` on your local machine:
```bash
- docker login registry.example.com --username my_username --password my_password
+ docker login registry.example.com:5000 --username my_username --password my_password
```
Then copy the content of `~/.docker/config.json`.
@@ -503,7 +506,7 @@ To configure access for `registry.example.com`, follow these steps:
```json
{
"auths": {
- "registry.example.com": {
+ "registry.example.com:5000": {
"auth": "bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ="
}
}
@@ -515,22 +518,28 @@ To configure access for `registry.example.com`, follow these steps:
registry from it:
```bash
- docker logout registry.example.com
+ docker logout registry.example.com:5000
```
-1. You can now use any private image from `registry.example.com` defined in
+1. You can now use any private image from `registry.example.com:5000` defined in
`image` and/or `services` in your `.gitlab-ci.yml` file:
```yaml
- image: my.registry.tld:5000/namespace/image:tag
+ image: registry.example.com:5000/namespace/image:tag
```
- In the example above, GitLab Runner will look at `my.registry.tld:5000` for the
+ In the example above, GitLab Runner will look at `registry.example.com:5000` for the
image `namespace/image:tag`.
You can add configuration for as many registries as you want, adding more
registries to the `"auths"` hash as described above.
+NOTE: **Note:** The full `hostname:port` combination is required everywhere
+for the Runner to match the `DOCKER_AUTH_CONFIG`. For example, if
+`registry.example.com:5000/namespace/image:tag` is specified in `.gitlab-ci.yml`,
+then the `DOCKER_AUTH_CONFIG` must also specify `registry.example.com:5000`.
+Specifying only `registry.example.com` will not work.
+
## Configuring services
Many services accept environment variables which allow you to easily change
diff --git a/doc/ci/docker/using_kaniko.md b/doc/ci/docker/using_kaniko.md
index 7d4f28e1f47..66f0d429165 100644
--- a/doc/ci/docker/using_kaniko.md
+++ b/doc/ci/docker/using_kaniko.md
@@ -39,7 +39,7 @@ few important details:
In the following example, kaniko is used to build a Docker image and then push
it to [GitLab Container Registry](../../user/project/container_registry.md).
The job will run only when a tag is pushed. A `config.json` file is created under
-`/root/.docker` with the needed GitLab Container Registry credentials taken from the
+`/kaniko/.docker` with the needed GitLab Container Registry credentials taken from the
[environment variables](../variables/README.md#predefined-variables-environment-variables)
GitLab CI/CD provides. In the last step, kaniko uses the `Dockerfile` under the
root directory of the project, builds the Docker image and pushes it to the
@@ -52,8 +52,7 @@ build:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
script:
- - mkdir -p /root/.docker
- - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /root/.docker/config.json
+ - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
only:
- tags
diff --git a/doc/ci/environments.md b/doc/ci/environments.md
index f1e5b00e927..315d0c5e7ef 100644
--- a/doc/ci/environments.md
+++ b/doc/ci/environments.md
@@ -370,7 +370,7 @@ review_app:
url: https://$CI_COMMIT_REF_SLUG.example.com
```
-It is assumed that the user has already setup NGINX and GitLab Runner in the
+It is assumed that the user has already set up NGINX and GitLab Runner in the
server this job will run on.
>**Note:**
@@ -416,19 +416,18 @@ and/or `production`) you can see this information in the merge request itself.
### Go directly from source files to public pages on the environment
-> Introduced in GitLab 8.17.
+> Introduced in GitLab 8.17. In GitLab 11.5 the file links
+are surfaced to the merge request widget.
-To go one step further, we can specify a Route Map to get GitLab to show us "View on [environment URL]" buttons to go directly from a file to that file's representation on the deployed website. It will be exposed in a few places:
-
-| In the diff for a merge request, comparison or commit | In the file view |
-| ------ | ------ |
-| !["View on env" button in merge request diff](img/view_on_env_mr.png) | !["View on env" button in file view](img/view_on_env_blob.png) |
+You can specify a Route Map to get GitLab to show "View on <environment URL>"
+buttons to go directly from a file to that file's representation on the
+[deployed website via Review Apps](review_apps/index.md).
To get this to work, you need to tell GitLab how the paths of files in your repository map to paths of pages on your website, using a Route Map.
A Route Map is a file inside the repository at `.gitlab/route-map.yml`, which contains a YAML array that maps `source` paths (in the repository) to `public` paths (on the website).
-
-This is an example of a route map for [Middleman](https://middlemanapp.com) static websites like [http://about.gitlab.com](https://gitlab.com/gitlab-com/www-gitlab-com):
+Below is an example of a route map for [Middleman](https://middlemanapp.com) static websites
+like <https://gitlab.com/gitlab-com/www-gitlab-com>:
```yaml
# Team data
@@ -467,6 +466,25 @@ In the example above, the fact that mappings are evaluated in order of their def
---
+Once you have the route mapping set up, it will be exposed in a few places:
+
+- In the merge request widget. The **View app** button will take you to the
+ environment URL you have set up in `.gitlab-ci.yml`. The dropdown will render
+ the first 5 matched items from the route map, but you can filter them if more
+ than 5 are available.
+
+ ![View app file list in merge request widget](img/view_on_mr_widget.png)
+
+- In the diff for a merge request, comparison, or commit.
+
+ !["View on env" button in merge request diff](img/view_on_env_mr.png)
+
+- In the blob file view.
+
+ !["View on env" button in file view](img/view_on_env_blob.png) |
+
+---
+
We now have a full development cycle, where our app is tested, built, deployed
as a Review app, deployed to a staging server once the merge request is merged,
and finally manually deployed to the production server. What we just described
@@ -568,13 +586,13 @@ exist, you should see something like:
>
> - For the monitoring dashboard to appear, you need to:
> - Have enabled the [Prometheus integration][prom]
-> - Configured Prometheus to collect at least one [supported metric](../user/project/integrations/prometheus_library/metrics.md)
+> - Configured Prometheus to collect at least one [supported metric](../user/project/integrations/prometheus_library/index.md)
> - With GitLab 9.2, all deployments to an environment are shown directly on the
> monitoring dashboard
If you have enabled [Prometheus for monitoring system and response metrics](https://docs.gitlab.com/ee/user/project/integrations/prometheus.html), you can monitor the performance behavior of your app running in each environment.
-Once configured, GitLab will attempt to retrieve [supported performance metrics](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/metrics.html) for any
+Once configured, GitLab will attempt to retrieve [supported performance metrics](https://docs.gitlab.com/ee/user/project/integrations/prometheus_library/index.html) for any
environment which has had a successful deployment. If monitoring data was
successfully retrieved, a Monitoring button will appear for each environment.
diff --git a/doc/ci/examples/README.md b/doc/ci/examples/README.md
index 8eb96ae10b2..a8c119edaa0 100644
--- a/doc/ci/examples/README.md
+++ b/doc/ci/examples/README.md
@@ -4,12 +4,12 @@ comments: false
# GitLab CI/CD Examples
-A collection of `.gitlab-ci.yml` template files is maintained at the [GitLab CI/CD YAML project][gitlab-ci-templates]. When you create a new file via the UI,
-GitLab will give you the option to choose one of the templates existent on this project.
+A collection of [`.gitlab-ci.yml` template files][gitlab-ci-templates] is maintained in GitLab. When you create a new file via the UI,
+GitLab will give you the option to choose one of these templates.
If your favorite programming language or framework are missing we would love your
help by sending a merge request with a new `.gitlab-ci.yml` to this project.
-There's also a collection of repositories with [example projects](https://gitlab.com/gitlab-examples) for various languages. You can fork an adjust them to your own needs.
+There's also a collection of repositories with [example projects](https://gitlab.com/gitlab-examples) for various languages. You can fork and adjust them to your own needs.
## Languages, frameworks, OSs
@@ -45,11 +45,11 @@ There's also a collection of repositories with [example projects](https://gitlab
## Test Reports
-[Collect test reports in Verify stage](../junit_test_reports.md).
+[Collect test reports in Verify stage](../junit_test_reports.md)
## Code Quality analysis
-**(Starter)** [Analyze your project's Code Quality](code_quality.md).
+**(Starter)** [Analyze your project's Code Quality](code_quality.md)
## Static Application Security Testing (SAST)
@@ -65,15 +65,15 @@ There's also a collection of repositories with [example projects](https://gitlab
## Dynamic Application Security Testing (DAST)
-Scan your app for vulnerabilities with GitLab [Dynamic Application Security Testing (DAST)](dast.md).
+Scan your app for vulnerabilities with GitLab [Dynamic Application Security Testing (DAST)](dast.md)
## Browser Performance Testing with Sitespeed.io
-Analyze your [browser performance with Sitespeed.io](browser_performance.md).
+Analyze your [browser performance with Sitespeed.io](browser_performance.md)
## GitLab CI/CD for Review Apps
-- [Example project](https://gitlab.com/gitlab-examples/review-apps-nginx/) that shows how to use GitLab CI/CD for [Review Apps](../review_apps/index.html).
+- [Example project](https://gitlab.com/gitlab-examples/review-apps-nginx/) that shows how to use GitLab CI/CD for [Review Apps](../review_apps/index.html)
- [Dockerizing GitLab Review Apps](https://about.gitlab.com/2017/07/11/dockerizing-review-apps/)
## GitLab CI/CD for GitLab Pages
@@ -87,4 +87,4 @@ language users and GitLab by sending a merge request with a guide for that langu
You may want to apply for the [GitLab Community Writers Program](https://about.gitlab.com/community-writers/)
to get paid for writing complete articles for GitLab.
-[gitlab-ci-templates]: https://gitlab.com/gitlab-org/gitlab-ci-yml
+[gitlab-ci-templates]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/gitlab/ci/templates
diff --git a/doc/ci/examples/artifactory_and_gitlab/index.md b/doc/ci/examples/artifactory_and_gitlab/index.md
index 9657f52159e..6aa0edd87b4 100644
--- a/doc/ci/examples/artifactory_and_gitlab/index.md
+++ b/doc/ci/examples/artifactory_and_gitlab/index.md
@@ -16,8 +16,8 @@ to build a [Maven](https://maven.apache.org/) project, deploy it to [Artifactory
You'll create two different projects:
-- `simple-maven-dep`: the app built and deployed to Artifactory (available at https://gitlab.com/gitlab-examples/maven/simple-maven-dep)
-- `simple-maven-app`: the app using the previous one as a dependency (available at https://gitlab.com/gitlab-examples/maven/simple-maven-app)
+- `simple-maven-dep`: the app built and deployed to Artifactory (available at https://gitlab.com/gitlab-examples/maven/simple-maven-dep )
+- `simple-maven-app`: the app using the previous one as a dependency (available at https://gitlab.com/gitlab-examples/maven/simple-maven-app )
We assume that you already have a GitLab account on [GitLab.com](https://gitlab.com/), and that you know the basic usage of Git and [GitLab CI/CD](https://about.gitlab.com/features/gitlab-ci-cd/).
We also assume that an Artifactory instance is available and reachable from the internet, and that you have valid credentials to deploy on it.
diff --git a/doc/ci/examples/browser_performance.md b/doc/ci/examples/browser_performance.md
index 0dab07a7f80..7c3b3a65675 100644
--- a/doc/ci/examples/browser_performance.md
+++ b/doc/ci/examples/browser_performance.md
@@ -1,14 +1,20 @@
# Browser Performance Testing with the Sitespeed.io container
+CAUTION: **Caution:**
+The job definition shown below is supported on GitLab 11.5 and later versions.
+It also requires the GitLab Runner 11.5 or later.
+For earlier versions, use the [previous job definitions](#previous-job-definitions).
+
This example shows how to run the
[Sitespeed.io container](https://hub.docker.com/r/sitespeedio/sitespeed.io/) on
your code by using GitLab CI/CD and [Sitespeed.io](https://www.sitespeed.io)
using Docker-in-Docker.
-First, you need a GitLab Runner with the
+First, you need GitLab Runner with
[docker-in-docker executor](../docker/using_docker_build.md#use-docker-in-docker-executor).
-Once you set up the Runner, add a new job to `.gitlab-ci.yml`, called
-`performance`:
+
+Once you set up the Runner, add a new job to `.gitlab-ci.yml` that
+generates the expected report:
```yaml
performance:
@@ -26,19 +32,22 @@ performance:
- mv sitespeed-results/data/performance.json performance.json
artifacts:
paths:
- - performance.json
- - sitespeed-results/
+ - sitespeed-results/
+ reports:
+ performance: performance.json
```
-The above example will:
+The above example will create a `performance` job in your CI/CD pipeline and will run
+Sitespeed.io against the webpage you defined in `URL` to gather key metrics.
+The [GitLab plugin](https://gitlab.com/gitlab-org/gl-performance) for
+Sitespeed.io is downloaded in order to save the report as a
+[Performance report artifact](https://docs.gitlab.com/ee//ci/yaml/README.html#artifactsreportsperformance)
+that you can later download and analyze.
+Due to implementation limitations we always take the latest Performance artifact available.
-1. Create a `performance` job in your CI/CD pipeline and will run
- Sitespeed.io against the webpage you defined in `URL`.
-1. The [GitLab plugin](https://gitlab.com/gitlab-org/gl-performance) for
- Sitespeed.io is downloaded in order to export key metrics to JSON. The full
- HTML Sitespeed.io report will also be saved as an artifact, and if you have
- [GitLab Pages](../../user/project/pages/index.md) enabled, it can be viewed
- directly in your browser.
+The full HTML Sitespeed.io report will also be saved as an artifact, and if you have
+[GitLab Pages](../../user/project/pages/index.md) enabled, it can be viewed
+directly in your browser.
For further customization options of Sitespeed.io, including the ability to
provide a list of URLs to test, please consult
@@ -46,8 +55,8 @@ provide a list of URLs to test, please consult
TIP: **Tip:**
For [GitLab Premium](https://about.gitlab.com/pricing/) users, key metrics are automatically
-extracted and shown right in the merge request widget. Learn more about
-[Browser Performance Testing](https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html).
+extracted and shown right in the merge request widget.
+[Learn more on Browser Performance Testing in merge requests](https://docs.gitlab.com/ee//user/project/merge_requests/browser_performance_testing.html).
## Performance testing on Review Apps
@@ -106,8 +115,40 @@ performance:
- mv sitespeed-results/data/performance.json performance.json
artifacts:
paths:
- - performance.json
- sitespeed-results/
+ reports:
+ performance: performance.json
```
-A complete example can be found in our [Auto DevOps CI YML](https://gitlab.com/gitlab-org/gitlab-ci-yml/blob/master/Auto-DevOps.gitlab-ci.yml).
+A complete example can be found in our [Auto DevOps CI YML](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml).
+
+## Previous job definitions
+
+CAUTION: **Caution:**
+Before GitLab 11.5, Performance job and artifact had to be named specifically
+to automatically extract report data and show it in the merge request widget.
+While these old job definitions are still maintained they have been deprecated
+and may be removed in next major release, GitLab 12.0.
+You are advised to update your current `.gitlab-ci.yml` configuration to reflect that change.
+
+For GitLab 11.4 and earlier, the job should look like:
+
+```yaml
+performance:
+ stage: performance
+ image: docker:git
+ variables:
+ URL: https://example.com
+ services:
+ - docker:stable-dind
+ script:
+ - mkdir gitlab-exporter
+ - wget -O ./gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/master/index.js
+ - mkdir sitespeed-results
+ - docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:6.3.1 --plugins.add ./gitlab-exporter --outputFolder sitespeed-results $URL
+ - mv sitespeed-results/data/performance.json performance.json
+ artifacts:
+ paths:
+ - performance.json
+ - sitespeed-results/
+``` \ No newline at end of file
diff --git a/doc/ci/examples/code_quality.md b/doc/ci/examples/code_quality.md
index 2a7040ecdeb..ae000b9d30d 100644
--- a/doc/ci/examples/code_quality.md
+++ b/doc/ci/examples/code_quality.md
@@ -1,11 +1,18 @@
# Analyze your project's Code Quality
+CAUTION: **Caution:**
+The job definition shown below is supported on GitLab 11.5 and later versions.
+It also requires the GitLab Runner 11.5 or later.
+For earlier versions, use the [previous job definitions](#previous-job-definitions).
+
This example shows how to run Code Quality on your code by using GitLab CI/CD
and Docker.
-First, you need GitLab Runner with [docker-in-docker executor][dind].
+First, you need GitLab Runner with
+[docker-in-docker executor](../docker/using_docker_build.md#use-docker-in-docker-executor).
-Once you set up the Runner, add a new job to `.gitlab-ci.yml`, called `code_quality`:
+Once you set up the Runner, add a new job to `.gitlab-ci.yml` that
+generates the expected report:
```yaml
code_quality:
@@ -23,27 +30,72 @@ code_quality:
--volume /var/run/docker.sock:/var/run/docker.sock
"registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
artifacts:
- paths: [gl-code-quality-report.json]
+ reports:
+ codequality: gl-code-quality-report.json
```
The above example will create a `code_quality` job in your CI/CD pipeline which
-will scan your source code for code quality issues. The report will be saved
-as an artifact that you can later download and analyze.
+will scan your source code for code quality issues. The report will be saved as a
+[Code Quality report artifact](../../ci/yaml/README.md#artifactsreportscodequality)
+that you can later download and analyze.
+Due to implementation limitations we always take the latest Code Quality artifact available.
TIP: **Tip:**
-Starting with [GitLab Starter][ee] 9.3, this information will
-be automatically extracted and shown right in the merge request widget. To do
-so, the CI/CD job must be named `code_quality` and the artifact path must be
-`gl-code-quality-report.json`.
+For [GitLab Starter][ee] users, this information will be automatically
+extracted and shown right in the merge request widget.
[Learn more on Code Quality in merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html).
+## Previous job definitions
+
CAUTION: **Caution:**
-Code Quality was previously using `codeclimate` and `codequality` for job name and
-`codeclimate.json` for the artifact name. While these old names
-are still maintained they have been deprecated with GitLab 11.0 and may be removed
-in next major release, GitLab 12.0. You are advised to update your current `.gitlab-ci.yml`
-configuration to reflect that change.
+Before GitLab 11.5, Code Quality job and artifact had to be named specifically
+to automatically extract report data and show it in the merge request widget.
+While these old job definitions are still maintained they have been deprecated
+and may be removed in next major release, GitLab 12.0.
+You are advised to update your current `.gitlab-ci.yml` configuration to reflect that change.
+
+For GitLab 11.4 and earlier, the job should look like:
+
+```yaml
+code_quality:
+ image: docker:stable
+ variables:
+ DOCKER_DRIVER: overlay2
+ allow_failure: true
+ services:
+ - docker:stable-dind
+ script:
+ - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
+ - docker run
+ --env SOURCE_CODE="$PWD"
+ --volume "$PWD":/code
+ --volume /var/run/docker.sock:/var/run/docker.sock
+ "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
+ artifacts:
+ paths: [gl-code-quality-report.json]
+```
+
+Alternatively the job name could be `codeclimate` or `codequality`
+and the artifact name could be `codeclimate.json`.
+These names have been deprecated with GitLab 11.0
+and may be removed in next major release, GitLab 12.0.
+
+For GitLab 10.3 and earlier, the job should look like:
+
+```yaml
+codequality:
+ image: docker:latest
+ variables:
+ DOCKER_DRIVER: overlay
+ services:
+ - docker:dind
+ script:
+ - docker pull codeclimate/codeclimate:0.69.0
+ - docker run --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc codeclimate/codeclimate:0.69.0 init
+ - docker run --env CODECLIMATE_CODE="$PWD" --volume "$PWD":/code --volume /var/run/docker.sock:/var/run/docker.sock --volume /tmp/cc:/tmp/cc codeclimate/codeclimate:0.69.0 analyze -f json > codeclimate.json || true
+ artifacts:
+ paths: [codeclimate.json]
+```
[cli]: https://github.com/codeclimate/codeclimate
-[dind]: ../docker/using_docker_build.md#use-docker-in-docker-executor
[ee]: https://about.gitlab.com/pricing/
diff --git a/doc/ci/examples/container_scanning.md b/doc/ci/examples/container_scanning.md
index 0f79f7d1b17..68330261910 100644
--- a/doc/ci/examples/container_scanning.md
+++ b/doc/ci/examples/container_scanning.md
@@ -1,13 +1,20 @@
# Container Scanning with GitLab CI/CD
+CAUTION: **Caution:**
+The job definition shown below is supported on GitLab 11.5 and later versions.
+It also requires the GitLab Runner 11.5 or later.
+For earlier versions, use the [previous job definitions](#previous-job-definitions).
+
You can check your Docker images (or more precisely the containers) for known
vulnerabilities by using [Clair](https://github.com/coreos/clair) and
[clair-scanner](https://github.com/arminc/clair-scanner), two open source tools
for Vulnerability Static Analysis for containers.
-All you need is a GitLab Runner with the Docker executor (the shared Runners on
-GitLab.com will work fine). You can then add a new job to `.gitlab-ci.yml`,
-called `container_scanning`:
+First, you need GitLab Runner with
+[docker-in-docker executor](../docker/using_docker_build.md#use-docker-in-docker-executor).
+
+Once you set up the Runner, add a new job to `.gitlab-ci.yml` that
+generates the expected report:
```yaml
container_scanning:
@@ -36,31 +43,77 @@ container_scanning:
- while( ! wget -T 10 -q -O /dev/null http://docker:6060/v1/namespaces ) ; do sleep 1 ; echo -n "." ; if [ $retries -eq 10 ] ; then echo " Timeout, aborting." ; exit 1 ; fi ; retries=$(($retries+1)) ; done
- ./clair-scanner -c http://docker:6060 --ip $(hostname -i) -r gl-container-scanning-report.json -l clair.log -w clair-whitelist.yml ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG} || true
artifacts:
- paths: [gl-container-scanning-report.json]
+ reports:
+ container_scanning: gl-container-scanning-report.json
```
The above example will create a `container_scanning` job in your CI/CD pipeline, pull
the image from the [Container Registry](../../user/project/container_registry.md)
(whose name is defined from the two `CI_APPLICATION_` variables) and scan it
-for possible vulnerabilities. The report will be saved as an artifact that you
-can later download and analyze.
+for possible vulnerabilities. The report will be saved as a
+[Container Scanning report artifact](https://docs.gitlab.com/ee//ci/yaml/README.html#artifactsreportscontainer_scanning)
+that you can later download and analyze.
+Due to implementation limitations we always take the latest Container Scanning artifact available.
If you want to whitelist some specific vulnerabilities, you can do so by defining
them in a [YAML file](https://github.com/arminc/clair-scanner/blob/master/README.md#example-whitelist-yaml-file),
in our case its named `clair-whitelist.yml`.
TIP: **Tip:**
-Starting with [GitLab Ultimate][ee] 10.4, this information will
-be automatically extracted and shown right in the merge request widget. To do
-so, the CI/CD job must be named `container_scanning` and the artifact path must be
-`gl-container-scanning-report.json`.
-[Learn more on container scanning results shown in merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/container_scanning.html).
+For [GitLab Ultimate][ee] users, this information will
+be automatically extracted and shown right in the merge request widget.
+[Learn more on Container Scanning in merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/container_scanning.html).
+
+CAUTION: **Caution:**
+Starting with GitLab 11.5, Container Scanning feature is licensed under the name `container_scanning`.
+While the old name `sast_container` is still maintained, it has been deprecated with GitLab 11.5 and
+may be removed in next major release, GitLab 12.0. You are advised to update your current `.gitlab-ci.yml`
+configuration to reflect that change if you are using the `$GITLAB_FEATURES` environment variable.
+
+## Previous job definitions
CAUTION: **Caution:**
-Before GitLab 11.0, Container Scanning was previously using `sast:container` for job name and
-`gl-sast-container-report.json` for the artifact name. While these old names
-are still maintained, they have been deprecated with GitLab 11.0 and may be removed
-in next major release, GitLab 12.0. You are advised to update your current `.gitlab-ci.yml`
-configuration to reflect that change.
+Before GitLab 11.5, Container Scanning job and artifact had to be named specifically
+to automatically extract report data and show it in the merge request widget.
+While these old job definitions are still maintained they have been deprecated
+and may be removed in next major release, GitLab 12.0.
+You are advised to update your current `.gitlab-ci.yml` configuration to reflect that change.
+
+For GitLab 11.4 and earlier, the job should look like:
+
+```yaml
+container_scanning:
+ image: docker:stable
+ variables:
+ DOCKER_DRIVER: overlay2
+ ## Define two new variables based on GitLab's CI/CD predefined variables
+ ## https://docs.gitlab.com/ee/ci/variables/#predefined-variables-environment-variables
+ CI_APPLICATION_REPOSITORY: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
+ CI_APPLICATION_TAG: $CI_COMMIT_SHA
+ allow_failure: true
+ services:
+ - docker:stable-dind
+ script:
+ - docker run -d --name db arminc/clair-db:latest
+ - docker run -p 6060:6060 --link db:postgres -d --name clair --restart on-failure arminc/clair-local-scan:v2.0.1
+ - apk add -U wget ca-certificates
+ - docker pull ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG}
+ - wget https://github.com/arminc/clair-scanner/releases/download/v8/clair-scanner_linux_amd64
+ - mv clair-scanner_linux_amd64 clair-scanner
+ - chmod +x clair-scanner
+ - touch clair-whitelist.yml
+ - while( ! wget -q -O /dev/null http://docker:6060/v1/namespaces ) ; do sleep 1 ; done
+ - retries=0
+ - echo "Waiting for clair daemon to start"
+ - while( ! wget -T 10 -q -O /dev/null http://docker:6060/v1/namespaces ) ; do sleep 1 ; echo -n "." ; if [ $retries -eq 10 ] ; then echo " Timeout, aborting." ; exit 1 ; fi ; retries=$(($retries+1)) ; done
+ - ./clair-scanner -c http://docker:6060 --ip $(hostname -i) -r gl-container-scanning-report.json -l clair.log -w clair-whitelist.yml ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG} || true
+ artifacts:
+ paths: [gl-container-scanning-report.json]
+```
+
+Alternatively the job name could be `sast:container`
+and the artifact name could be `gl-sast-container-report.json`.
+These names have been deprecated with GitLab 11.0
+and may be removed in next major release, GitLab 12.0.
[ee]: https://about.gitlab.com/pricing/
diff --git a/doc/ci/examples/dast.md b/doc/ci/examples/dast.md
index ff20f0b3b5e..0ca89eb6700 100644
--- a/doc/ci/examples/dast.md
+++ b/doc/ci/examples/dast.md
@@ -1,16 +1,26 @@
# Dynamic Application Security Testing with GitLab CI/CD
+CAUTION: **Caution:**
+The job definition shown below is supported on GitLab 11.5 and later versions.
+It also requires the GitLab Runner 11.5 or later.
+For earlier versions, use the [previous job definitions](#previous-job-definitions).
+
[Dynamic Application Security Testing (DAST)](https://en.wikipedia.org/wiki/Dynamic_program_analysis)
is using the popular open source tool [OWASP ZAProxy](https://github.com/zaproxy/zaproxy)
to perform an analysis on your running web application.
+Since it is based on [ZAP Baseline](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan)
+DAST will perform passive scanning only;
+it will not actively attack your application.
It can be very useful combined with [Review Apps](../review_apps/index.md).
## Example
-All you need is a GitLab Runner with the Docker executor (the shared Runners on
-GitLab.com will work fine). You can then add a new job to `.gitlab-ci.yml`,
-called `dast`:
+First, you need GitLab Runner with
+[docker-in-docker executor](../docker/using_docker_build.md#use-docker-in-docker-executor).
+
+Once you set up the Runner, add a new job to `.gitlab-ci.yml` that
+generates the expected report:
```yaml
dast:
@@ -23,13 +33,16 @@ dast:
- /zap/zap-baseline.py -J gl-dast-report.json -t $website || true
- cp /zap/wrk/gl-dast-report.json .
artifacts:
- paths: [gl-dast-report.json]
+ reports:
+ dast: gl-dast-report.json
```
The above example will create a `dast` job in your CI/CD pipeline which will run
the tests on the URL defined in the `website` variable (change it to use your
-own) and finally write the results in the `gl-dast-report.json` file. You can
-then download and analyze the report artifact in JSON format.
+own) and scan it for possible vulnerabilities. The report will be saved as a
+[DAST report artifact](https://docs.gitlab.com/ee//ci/yaml/README.html#artifactsreportsdast)
+that you can later download and analyze.
+Due to implementation limitations we always take the latest DAST artifact available.
It's also possible to authenticate the user before performing DAST checks:
@@ -39,25 +52,51 @@ dast:
variables:
website: "https://example.com"
login_url: "https://example.com/sign-in"
+ username: "john.doe@example.com"
+ password: "john-doe-password"
allow_failure: true
script:
- mkdir /zap/wrk/
- /zap/zap-baseline.py -J gl-dast-report.json -t $website
--auth-url $login_url
- --auth-username "john.doe@example.com"
- --auth-password "john-doe-password" || true
+ --auth-username $username
+ --auth-password $password || true
- cp /zap/wrk/gl-dast-report.json .
artifacts:
- paths: [gl-dast-report.json]
+ reports:
+ dast: gl-dast-report.json
```
See [zaproxy documentation](https://gitlab.com/gitlab-org/security-products/zaproxy)
to learn more about authentication settings.
TIP: **Tip:**
-Starting with [GitLab Ultimate][ee] 10.4, this information will
-be automatically extracted and shown right in the merge request widget. To do
-so, the CI job must be named `dast` and the artifact path must be
-`gl-dast-report.json`.
-[Learn more about DAST results shown in merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/dast.html).
+For [GitLab Ultimate][ee] users, this information will
+be automatically extracted and shown right in the merge request widget.
+[Learn more on DAST in merge requests](https://docs.gitlab.com/ee/user/project/merge_requests/dast.html).
+
+## Previous job definitions
+
+CAUTION: **Caution:**
+Before GitLab 11.5, DAST job and artifact had to be named specifically
+to automatically extract report data and show it in the merge request widget.
+While these old job definitions are still maintained they have been deprecated
+and may be removed in next major release, GitLab 12.0.
+You are advised to update your current `.gitlab-ci.yml` configuration to reflect that change.
+
+For GitLab 11.4 and earlier, the job should look like:
+
+```yaml
+dast:
+ image: registry.gitlab.com/gitlab-org/security-products/zaproxy
+ variables:
+ website: "https://example.com"
+ allow_failure: true
+ script:
+ - mkdir /zap/wrk/
+ - /zap/zap-baseline.py -J gl-dast-report.json -t $website || true
+ - cp /zap/wrk/gl-dast-report.json .
+ artifacts:
+ paths: [gl-dast-report.json]
+```
[ee]: https://about.gitlab.com/pricing/
diff --git a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/img/cloud_foundry_secret_variables.png b/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/img/cloud_foundry_secret_variables.png
deleted file mode 100644
index 5b5d91ec07a..00000000000
--- a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/img/cloud_foundry_secret_variables.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/img/cloud_foundry_variables.png b/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/img/cloud_foundry_variables.png
new file mode 100644
index 00000000000..28323e2d8de
--- /dev/null
+++ b/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/img/cloud_foundry_variables.png
Binary files differ
diff --git a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md b/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md
index b88761be56b..40ceef3d554 100644
--- a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md
+++ b/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md
@@ -64,7 +64,7 @@ applications:
## Configure GitLab CI/CD to deploy your application
-Now we need to add the the GitLab CI/CD configuration file
+Now we need to add the GitLab CI/CD configuration file
([`.gitlab-ci.yml`](../../yaml/README.md)) to our
project's root. This is how GitLab figures out what commands need to be run whenever
code is pushed to our repository. We will add the following `.gitlab-ci.yml`
@@ -106,10 +106,10 @@ Now, since the steps defined in `.gitlab-ci.yml` require credentials to login
to CF, you'll need to add your CF credentials as [environment
variables](../../variables/README.md#predefined-variables-environment-variables)
on GitLab CI/CD. To set the environment variables, navigate to your project's
-**Settings > CI/CD** and expand **Secret Variables**. Name the variables
+**Settings > CI/CD** and expand **Variables**. Name the variables
`CF_USERNAME` and `CF_PASSWORD` and set them to the correct values.
-![Secret Variable Settings in GitLab](img/cloud_foundry_secret_variables.png)
+![Variable Settings in GitLab](img/cloud_foundry_variables.png)
Once set up, GitLab CI/CD will deploy your app to CF at every push to your
repository's deafult branch. To see the build logs or watch your builds running
diff --git a/doc/ci/examples/deployment/README.md b/doc/ci/examples/deployment/README.md
index bd60d641493..46effb76d71 100644
--- a/doc/ci/examples/deployment/README.md
+++ b/doc/ci/examples/deployment/README.md
@@ -5,7 +5,7 @@ continuous deployment that's developed and used by Travis CI, but can also be
used with GitLab CI.
>**Note:**
-We recommend to use Dpl if you're deploying to any of these of these services:
+We recommend to use Dpl if you're deploying to any of these services:
https://github.com/travis-ci/dpl#supported-providers.
## Requirements
@@ -101,12 +101,12 @@ production:
We created two deploy jobs that are executed on different events:
1. `staging` is executed for all commits that were pushed to `master` branch,
-2. `production` is executed for all pushed tags.
+1. `production` is executed for all pushed tags.
We also use two secure variables:
1. `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app,
-2. `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app.
+1. `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app.
## Storing API keys
@@ -120,7 +120,7 @@ is hidden in the job log.
You access added variable by prefixing it's name with `$` (on non-Windows runners)
or `%` (for Windows Batch runners):
-1. `$SECRET_VARIABLE` - use it for non-Windows runners
-2. `%SECRET_VARIABLE%` - use it for Windows Batch runners
+1. `$VARIABLE` - use it for non-Windows runners
+1. `%VARIABLE%` - use it for Windows Batch runners
Read more about the [CI variables](../../variables/README.md).
diff --git a/doc/ci/examples/deployment/composer-npm-deploy.md b/doc/ci/examples/deployment/composer-npm-deploy.md
index bed379b0254..36358515b84 100644
--- a/doc/ci/examples/deployment/composer-npm-deploy.md
+++ b/doc/ci/examples/deployment/composer-npm-deploy.md
@@ -33,9 +33,9 @@ before_script:
In this particular case, the `npm deploy` script is a Gulp script that does the following:
1. Compile CSS & JS
-2. Create sprites
-3. Copy various assets (images, fonts) around
-4. Replace some strings
+1. Create sprites
+1. Copy various assets (images, fonts) around
+1. Replace some strings
All these operations will put all files into a `build` folder, which is ready to be deployed to a live server.
@@ -43,7 +43,7 @@ All these operations will put all files into a `build` folder, which is ready to
You have multiple options: rsync, scp, sftp and so on. For now, we will use scp.
-To make this work, you need to add a GitLab Secret Variable (accessible on _gitlab.example/your-project-name/variables_). That variable will be called `STAGING_PRIVATE_KEY` and it's the **private** ssh key of your server.
+To make this work, you need to add a GitLab CI/CD Variable (accessible on _gitlab.example/your-project-name/variables_). That variable will be called `STAGING_PRIVATE_KEY` and it's the **private** ssh key of your server.
### Security tip
@@ -62,10 +62,10 @@ before_script:
In order, this means that:
-1. We check if the `ssh-agent` is available and we install it if it's not;
-2. We create the `~/.ssh` folder;
-3. We make sure we're running bash;
-4. We disable host checking (we don't ask for user accept when we first connect to a server; and since every job will equal a first connect, we kind of need this)
+1. We check if the `ssh-agent` is available and we install it if it's not.
+1. We create the `~/.ssh` folder.
+1. We make sure we're running bash.
+1. We disable host checking (we don't ask for user accept when we first connect to a server and since every job will equal a first connect, we kind of need this).
And this is basically all you need in the `before_script` section.
@@ -91,11 +91,11 @@ stage_deploy:
Here's the breakdown:
1. `only:dev` means that this build will run only when something is pushed to the `dev` branch. You can remove this block completely and have everything be ran on every push (but probably this is something you don't want)
-2. `ssh-add ...` we will add that private key you added on the web UI to the docker container
-3. We will connect via `ssh` and create a new `_tmp` folder
-4. We will connect via `scp` and upload the `build` folder (which was generated by a `npm` script) to our previously created `_tmp` folder
-5. We will connect again to `ssh` and move the `live` folder to an `_old` folder, then move `_tmp` to `live`.
-6. We connect to ssh and remove the `_old` folder
+1. `ssh-add ...` we will add that private key you added on the web UI to the docker container
+1. We will connect via `ssh` and create a new `_tmp` folder
+1. We will connect via `scp` and upload the `build` folder (which was generated by a `npm` script) to our previously created `_tmp` folder
+1. We will connect again to `ssh` and move the `live` folder to an `_old` folder, then move `_tmp` to `live`.
+1. We connect to ssh and remove the `_old` folder
What's the deal with the artifacts? We just tell GitLab CI to keep the `build` directory (later on, you can download that as needed).
diff --git a/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md b/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md
index c226b5bfb71..cae051daa56 100644
--- a/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md
+++ b/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md
@@ -418,7 +418,7 @@ fully understand [IAM Best Practices in AWS](http://docs.aws.amazon.com/IAM/late
1. Click the **Access Keys** section and **Create New Access Key**. Create the key and keep the id and secret around, you'll need them later
![AWS Access Key Config](img/aws_config_window.png)
1. Go to your GitLab project, click **Settings > CI/CD** on the left sidebar
-1. Expand the **Secret Variables** section
+1. Expand the **Variables** section
![GitLab Secret Config](img/gitlab_config.png)
1. Add a key named `AWS_KEY_ID` and copy the key id from Step 2 into the **Value** textbox
1. Add a key named `AWS_KEY_SECRET` and copy the key secret from Step 2 into the **Value** textbox
@@ -520,7 +520,7 @@ a lot of breathing room in quickly getting changes to players.
Here are some ideas to further investigate that can speed up or improve your pipeline:
- [Yarn](https://yarnpkg.com) instead of npm
-- Setup a custom [Docker](../../../ci/docker/using_docker_images.md#define-image-and-services-from-gitlab-ci-yml) image that can preload dependencies and tools (like AWS CLI)
+- Set up a custom [Docker](../../../ci/docker/using_docker_images.md#define-image-and-services-from-gitlab-ci-yml) image that can preload dependencies and tools (like AWS CLI)
- Forward a [custom domain](http://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html) to your game's S3 static website
- Combine jobs if you find it unnecessary for a small project
- Avoid the queues and set up your own [custom GitLab CI/CD runner](https://about.gitlab.com/2016/03/01/gitlab-runner-with-docker/)
diff --git a/doc/ci/examples/laravel_with_gitlab_and_envoy/img/container_registry_checkbox.png b/doc/ci/examples/laravel_with_gitlab_and_envoy/img/container_registry_checkbox.png
deleted file mode 100644
index a56c07a0da7..00000000000
--- a/doc/ci/examples/laravel_with_gitlab_and_envoy/img/container_registry_checkbox.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/examples/laravel_with_gitlab_and_envoy/img/secret_variables_page.png b/doc/ci/examples/laravel_with_gitlab_and_envoy/img/secret_variables_page.png
deleted file mode 100644
index b7906d49dcb..00000000000
--- a/doc/ci/examples/laravel_with_gitlab_and_envoy/img/secret_variables_page.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/examples/laravel_with_gitlab_and_envoy/img/variables_page.png b/doc/ci/examples/laravel_with_gitlab_and_envoy/img/variables_page.png
new file mode 100644
index 00000000000..80d8eb0f4fc
--- /dev/null
+++ b/doc/ci/examples/laravel_with_gitlab_and_envoy/img/variables_page.png
Binary files differ
diff --git a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
index 39c65399332..b1ccce744d8 100644
--- a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
+++ b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
@@ -13,7 +13,7 @@ date: 2017-08-31
GitLab features our applications with Continuous Integration, and it is possible to easily deploy the new code changes to the production server whenever we want.
-In this tutorial, we'll show you how to initialize a [Laravel](http://laravel.com/) application and setup our [Envoy](https://laravel.com/docs/envoy) tasks, then we'll jump into see how to test and deploy it with [GitLab CI/CD](../README.md) via [Continuous Delivery](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/).
+In this tutorial, we'll show you how to initialize a [Laravel](http://laravel.com/) application and set up our [Envoy](https://laravel.com/docs/envoy) tasks, then we'll jump into see how to test and deploy it with [GitLab CI/CD](../README.md) via [Continuous Delivery](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/).
We assume you have a basic experience with Laravel, Linux servers,
and you know how to use GitLab.
@@ -23,7 +23,7 @@ It has a great community with a [fantastic documentation](https://laravel.com/do
Aside from the usual routing, controllers, requests, responses, views, and (blade) templates, out of the box Laravel provides plenty of additional services such as cache, events, localization, authentication and many others.
We will use [Envoy](https://laravel.com/docs/master/envoy) as an SSH task runner based on PHP.
-It uses a clean, minimal [Blade syntax](https://laravel.com/docs/blade) to setup tasks that can run on remote servers, such as, cloning your project from the repository, installing the Composer dependencies, and running [Artisan commands](https://laravel.com/docs/artisan).
+It uses a clean, minimal [Blade syntax](https://laravel.com/docs/blade) to set up tasks that can run on remote servers, such as, cloning your project from the repository, installing the Composer dependencies, and running [Artisan commands](https://laravel.com/docs/artisan).
## Initialize our Laravel app on GitLab
@@ -120,12 +120,12 @@ Now, let's add it to your GitLab project as a [variable](../../variables/README.
Variables are user-defined variables and are stored out of `.gitlab-ci.yml`, for security purposes.
They can be added per project by navigating to the project's **Settings** > **CI/CD**.
-![variables page](img/secret_variables_page.png)
-
To the field **KEY**, add the name `SSH_PRIVATE_KEY`, and to the **VALUE** field, paste the private key you've copied earlier.
We'll use this variable in the `.gitlab-ci.yml` later, to easily connect to our remote server as the deployer user without entering its password.
-We also need to add the public key to **Project** > **Settings** > **Repository** as [Deploy Keys](../../../ssh/README.md/#deploy-keys), which gives us the ability to access our repository from the server through [SSH protocol](../../../gitlab-basics/command-line-commands.md/#start-working-on-your-project).
+![variables page](img/variables_page.png)
+
+We also need to add the public key to **Project** > **Settings** > **Repository** as a [Deploy Key](../../../ssh/README.md#deploy-keys), which gives us the ability to access our repository from the server through [SSH protocol](../../../gitlab-basics/command-line-commands.md#start-working-on-your-project).
```bash
@@ -135,10 +135,10 @@ We also need to add the public key to **Project** > **Settings** > **Repository*
cat ~/.ssh/id_rsa.pub
```
-![deploy keys page](img/deploy_keys_page.png)
-
To the field **Title**, add any name you want, and paste the public key into the **Key** field.
+![deploy keys page](img/deploy_keys_page.png)
+
Now, let's clone our repository on the server just to make sure the `deployer` user has access to the repository.
```bash
@@ -273,6 +273,8 @@ The `releases` directory will hold all our deployments:
echo 'Cloning repository'
[ -d {{ $releases_dir }} ] || mkdir {{ $releases_dir }}
git clone --depth 1 {{ $repository }} {{ $new_release_dir }}
+ cd {{ $releases_dir }}
+ git reset --hard {{ $commit }}
@endtask
...
@@ -349,6 +351,8 @@ At the end, our `Envoy.blade.php` file will look like this:
echo 'Cloning repository'
[ -d {{ $releases_dir }} ] || mkdir {{ $releases_dir }}
git clone --depth 1 {{ $repository }} {{ $new_release_dir }}
+ cd {{ $releases_dir }}
+ git reset --hard {{ $commit }}
@endtask
@task('run_composer')
@@ -372,13 +376,13 @@ At the end, our `Envoy.blade.php` file will look like this:
One more thing we should do before any deployment is to manually copy our application `storage` folder to the `/var/www/app` directory on the server for the first time.
You might want to create another Envoy task to do that for you.
-We also create the `.env` file in the same path to setup our production environment variables for Laravel.
+We also create the `.env` file in the same path to set up our production environment variables for Laravel.
These are persistent data and will be shared to every new release.
Now, we would need to deploy our app by running `envoy run deploy`, but it won't be necessary since GitLab can handle that for us with CI's [environments](../../environments.md), which will be described [later](#setting-up-gitlab-ci-cd) in this tutorial.
Now it's time to commit [Envoy.blade.php](https://gitlab.com/mehranrasulian/laravel-sample/blob/master/Envoy.blade.php) and push it to the `master` branch.
-To keep things simple, we commit directly to `master`, without using [feature-branches](../../../workflow/gitlab_flow.md/#github-flow-as-a-simpler-alternative) since collaboration is beyond the scope of this tutorial.
+To keep things simple, we commit directly to `master`, without using [feature-branches](../../../workflow/gitlab_flow.md#github-flow-as-a-simpler-alternative) since collaboration is beyond the scope of this tutorial.
In a real world project, teams may use [Issue Tracker](../../../user/project/issues/index.md) and [Merge Requests](../../../user/project/merge_requests/index.md) to move their code across branches:
```bash
@@ -398,7 +402,7 @@ In the case you're not familiar with Docker, refer to [How to Automate Docker De
To be able to build, test, and deploy our app with GitLab CI/CD, we need to prepare our work environment.
To do that, we'll use a Docker image which has the minimum requirements that a Laravel app needs to run.
-[There are other ways](../php.md/#test-php-projects-using-the-docker-executor) to do that as well, but they may lead our builds run slowly, which is not what we want when there are faster options to use.
+[There are other ways](../php.md#test-php-projects-using-the-docker-executor) to do that as well, but they may lead our builds run slowly, which is not what we want when there are faster options to use.
With Docker images our builds run incredibly faster!
@@ -444,9 +448,7 @@ On your GitLab project repository navigate to the **Registry** tab.
![container registry page empty image](img/container_registry_page_empty_image.png)
-You may need to [enable Container Registry](../../../user/project/container_registry.md#enable-the-container-registry-for-your-project) to your project to see this tab. You'll find it under your project's **Settings > General > Sharing and permissions**.
-
-![container registry checkbox](img/container_registry_checkbox.png)
+You may need to [enable Container Registry](../../../user/project/container_registry.md#enable-the-container-registry-for-your-project) to your project to see this tab. You'll find it under your project's **Settings > General > Permissions**.
To start using Container Registry on our machine, we first need to login to the GitLab registry using our GitLab username and password:
@@ -521,7 +523,7 @@ deploy_production:
- mkdir -p ~/.ssh
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
- - ~/.composer/vendor/bin/envoy run deploy
+ - ~/.composer/vendor/bin/envoy run deploy --commit="$CI_COMMIT_SHA"
environment:
name: production
url: http://192.168.1.1
@@ -536,7 +538,7 @@ That's a lot to take in, isn't it? Let's run through it step by step.
[GitLab Runners](../../runners/README.md) run the script defined by `.gitlab-ci.yml`.
The `image` keyword tells the Runners which image to use.
-The `services` keyword defines additional images [that are linked to the main image](../../docker/using_docker_images.md/#what-is-a-service).
+The `services` keyword defines additional images [that are linked to the main image](../../docker/using_docker_images.md#what-is-a-service).
Here we use the container image we created before as our main image and also use MySQL 5.7 as a service.
```yaml
@@ -560,7 +562,7 @@ So we should adjust the configuration of MySQL instance by defining `MYSQL_DATAB
Find out more about MySQL variables at the [official MySQL Docker Image](https://hub.docker.com/r/_/mysql/).
Also set the variables `DB_HOST` to `mysql` and `DB_USERNAME` to `root`, which are Laravel specific variables.
-We define `DB_HOST` as `mysql` instead of `127.0.0.1`, as we use MySQL Docker image as a service which [is linked to the main Docker image](../../docker/using_docker_images.md/#how-services-are-linked-to-the-build).
+We define `DB_HOST` as `mysql` instead of `127.0.0.1`, as we use MySQL Docker image as a service which [is linked to the main Docker image](../../docker/using_docker_images.md#how-services-are-linked-to-the-build).
```yaml
...
@@ -587,7 +589,7 @@ unit_test:
script:
# Install app dependencies
- composer install
- # Setup .env
+ # Set up .env
- cp .env.example .env
# Generate an environment key
- php artisan key:generate
@@ -602,7 +604,7 @@ unit_test:
#### Deploy to production
The job `deploy_production` will deploy the app to the production server.
-To deploy our app with Envoy, we had to set up the `$SSH_PRIVATE_KEY` variable as an [SSH private key](../../ssh_keys/README.md/#ssh-keys-when-using-the-docker-executor).
+To deploy our app with Envoy, we had to set up the `$SSH_PRIVATE_KEY` variable as an [SSH private key](../../ssh_keys/README.md#ssh-keys-when-using-the-docker-executor).
If the SSH keys have added successfully, we can run Envoy.
As mentioned before, GitLab supports [Continuous Delivery](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-delivery) methods as well.
diff --git a/doc/ci/examples/php.md b/doc/ci/examples/php.md
index a2ba29a4ee2..c1048f3d2e3 100644
--- a/doc/ci/examples/php.md
+++ b/doc/ci/examples/php.md
@@ -20,7 +20,7 @@ build environment.
Let's first specify the PHP image that will be used for the job process
(you can read more about what an image means in the Runner's lingo reading
-about [Using Docker images](../docker/using_docker_images.md#what-is-image)).
+about [Using Docker images](../docker/using_docker_images.md#what-is-an-image)).
Start by adding the image to your `.gitlab-ci.yml`:
@@ -199,7 +199,7 @@ pecl install <extension>
```
It's not advised to add this to `.gitlab-ci.yml`. You should execute this
-command once, only to setup the build environment.
+command once, only to set up the build environment.
## Extend your tests
diff --git a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
index 087b317ab73..ec0b5aaed09 100644
--- a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
@@ -40,15 +40,17 @@ production:
```
This project has three jobs:
-1. `test` - used to test Django application,
-2. `staging` - used to automatically deploy staging environment every push to `master` branch
-3. `production` - used to automatically deploy production environment for every created tag
+
+- `test` - used to test Django application,
+- `staging` - used to automatically deploy staging environment every push to `master` branch
+- `production` - used to automatically deploy production environment for every created tag
## Store API keys
You'll need to create two variables in `Settings > CI/CD > Variables` on your GitLab project settings:
-1. `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app,
-2. `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app.
+
+- `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app.
+- `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app.
Find your Heroku API key in [Manage Account](https://dashboard.heroku.com/account).
diff --git a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
index 7f9ab1f3a5e..33a353f17f5 100644
--- a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
@@ -36,16 +36,17 @@ production:
```
This project has three jobs:
-1. `test` - used to test Rails application,
-2. `staging` - used to automatically deploy staging environment every push to `master` branch
-3. `production` - used to automatically deploy production environment for every created tag
+
+- `test` - used to test Rails application.
+- `staging` - used to automatically deploy staging environment every push to `master` branch.
+- `production` - used to automatically deploy production environment for every created tag.
## Store API keys
You'll need to create two variables in your project's **Settings > CI/CD > Variables**:
-1. `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app,
-2. `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app.
+- `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app.
+- `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app.
Find your Heroku API key in [Manage Account](https://dashboard.heroku.com/account).
diff --git a/doc/ci/examples/test-scala-application.md b/doc/ci/examples/test-scala-application.md
index 09d83c33f95..66bfa41cad9 100644
--- a/doc/ci/examples/test-scala-application.md
+++ b/doc/ci/examples/test-scala-application.md
@@ -1,6 +1,6 @@
# Test and deploy to Heroku a Scala application
-This example demonstrates the integration of Gitlab CI with Scala
+This example demonstrates the integration of GitLab CI with Scala
applications using SBT. Checkout the example
[project](https://gitlab.com/gitlab-examples/scala-sbt) and
[build status](https://gitlab.com/gitlab-examples/scala-sbt/builds).
@@ -25,7 +25,7 @@ before_script:
- apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 642AC823
- apt-get update -y
- apt-get install sbt -y
- - sbt sbt-version
+ - sbt sbtVersion
test:
stage: test
diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
index b2c73caae2e..c0346d78141 100644
--- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
+++ b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md
@@ -398,10 +398,10 @@ other reasons][ci-reasons] to keep using GitLab CI/CD. The benefits to our teams
- [Using Docker images documentation][using-docker]
- [Example project: Hello GitLab CI/CD on GitLab][hello-gitlab]
-[phoenix-site]: http://phoenixframework.org/ "Phoenix Framework"
+[phoenix-site]: https://phoenixframework.org/ "Phoenix Framework"
[phoenix-learning-guide]: https://hexdocs.pm/phoenix/learning.html "Phoenix Learning Guide"
-[phoenix-install]: http://www.phoenixframework.org/docs/installation "Phoenix Installation"
-[phoenix-mysql]: http://www.phoenixframework.org/docs/using-mysql "Phoenix with MySQL"
+[phoenix-install]: https://hexdocs.pm/phoenix/installation.html "Phoenix Installation"
+[phoenix-mysql]: https://hexdocs.pm/phoenix/ecto.html#using-mysql "Phoenix with MySQL"
[elixir-site]: http://elixir-lang.org/ "Elixir"
[elixir-mix]: http://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html "Introduction to mix"
[elixir-docs]: http://elixir-lang.org/getting-started/introduction.html "Elixir Documentation"
diff --git a/doc/ci/img/pipeline_incremental_rollout.png b/doc/ci/img/pipeline_incremental_rollout.png
new file mode 100644
index 00000000000..b3498e9a5a5
--- /dev/null
+++ b/doc/ci/img/pipeline_incremental_rollout.png
Binary files differ
diff --git a/doc/ci/img/pipelines-goal.png b/doc/ci/img/pipelines-goal.png
new file mode 100644
index 00000000000..a96368e562b
--- /dev/null
+++ b/doc/ci/img/pipelines-goal.png
Binary files differ
diff --git a/doc/ci/img/pipelines-goal.svg b/doc/ci/img/pipelines-goal.svg
deleted file mode 100644
index a925e2282a4..00000000000
--- a/doc/ci/img/pipelines-goal.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" standalone="yes"?>
-
-<svg version="1.1" viewBox="0.0 0.0 1091.020997375328 262.04461942257217" fill="none" stroke="none" stroke-linecap="square" stroke-miterlimit="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><clipPath id="p.0"><path d="m0 0l1091.021 0l0 262.04462l-1091.021 0l0 -262.04462z" clip-rule="nonzero"></path></clipPath><g clip-path="url(#p.0)"><path fill="#000000" fill-opacity="0.0" d="m0 0l1091.021 0l0 262.04462l-1091.021 0z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m226.93439 3.7664042l860.7559 0l0 249.5748l-860.7559 0z" fill-rule="nonzero"></path><path stroke="#666666" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" stroke-dasharray="4.0,3.0" d="m226.93439 3.7664042l860.7559 0l0 249.5748l-860.7559 0z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m67.72179 27.199474l147.2126 0l0 39.464565l-147.2126 0z" fill-rule="nonzero"></path><path fill="#000000" d="m126.91313 49.353848l1.796875 0.453125q-0.5625 2.21875 -2.03125 3.390625q-1.46875 1.15625 -3.59375 1.15625q-2.203125 0 -3.578125 -0.890625q-1.375 -0.90625 -2.09375 -2.59375q-0.71875 -1.703125 -0.71875 -3.65625q0 -2.125 0.796875 -3.703125q0.8125 -1.578125 2.3125 -2.390625q1.5 -0.828125 3.296875 -0.828125q2.046875 0 3.4375 1.046875q1.390625 1.03125 1.9375 2.90625l-1.765625 0.421875q-0.46875 -1.484375 -1.375 -2.15625q-0.90625 -0.6875 -2.265625 -0.6875q-1.5625 0 -2.625 0.75q-1.046875 0.75 -1.484375 2.03125q-0.421875 1.265625 -0.421875 2.609375q0 1.734375 0.5 3.03125q0.515625 1.28125 1.578125 1.921875q1.078125 0.640625 2.3125 0.640625q1.515625 0 2.5625 -0.859375q1.046875 -0.875 1.421875 -2.59375zm3.5354462 4.765625l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm12.978302 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm15.547592 4.65625q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.735092 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277054 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm14.449646 5.875l0 -13.59375l2.71875 0l3.21875 9.625q0.4375 1.34375 0.640625 2.015625q0.234375 -0.75 0.734375 -2.1875l3.25 -9.453125l2.421875 0l0 13.59375l-1.734375 0l0 -11.390625l-3.953125 11.390625l-1.625 0l-3.9375 -11.578125l0 11.578125l-1.734375 0zm15.634552 0l0 -13.59375l6.03125 0q1.8125 0 2.75 0.359375q0.953125 0.359375 1.515625 1.296875q0.5625 0.921875 0.5625 2.046875q0 1.453125 -0.9375 2.453125q-0.921875 0.984375 -2.890625 1.25q0.71875 0.34375 1.09375 0.671875q0.78125 0.734375 1.484375 1.8125l2.375 3.703125l-2.265625 0l-1.796875 -2.828125q-0.796875 -1.21875 -1.3125 -1.875q-0.5 -0.65625 -0.90625 -0.90625q-0.40625 -0.265625 -0.8125 -0.359375q-0.3125 -0.078125 -1.015625 -0.078125l-2.078125 0l0 6.046875l-1.796875 0zm1.796875 -7.59375l3.859375 0q1.234375 0 1.921875 -0.25q0.703125 -0.265625 1.0625 -0.828125q0.375 -0.5625 0.375 -1.21875q0 -0.96875 -0.703125 -1.578125q-0.703125 -0.625 -2.21875 -0.625l-4.296875 0l0 4.5z" fill-rule="nonzero"></path><path fill="#efefef" d="m765.3307 106.94125l147.21265 0l0 59.74803l-147.21265 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m765.3307 106.94125l147.21265 0l0 59.74803l-147.21265 0z" fill-rule="nonzero"></path><path fill="#000000" d="m800.99805 132.73526l0 -13.593742l4.6875 0q1.578125 0 2.421875 0.1875q1.15625 0.265625 1.984375 0.96875q1.078125 0.921875 1.609375 2.34375q0.53125 1.40625 0.53125 3.21875q0 1.546875 -0.359375 2.7499924q-0.359375 1.1875 -0.921875 1.984375q-0.5625 0.78125 -1.234375 1.234375q-0.671875 0.4375 -1.625 0.671875q-0.953125 0.234375 -2.1875 0.234375l-4.90625 0zm1.796875 -1.609375l2.90625 0q1.34375 0 2.109375 -0.25q0.765625 -0.25 1.21875 -0.703125q0.640625 -0.640625 1.0 -1.71875q0.359375 -1.0781174 0.359375 -2.6249924q0 -2.125 -0.703125 -3.265625q-0.703125 -1.15625 -1.703125 -1.546875q-0.71875 -0.28125 -2.328125 -0.28125l-2.859375 0l0 10.390617zm18.207336 -1.5625l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.7343674q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.43749237l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.7031174l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.110107 9.656242l0 -13.640617l1.53125 0l0 1.28125q0.53125 -0.75 1.203125 -1.125q0.6875 -0.375 1.640625 -0.375q1.265625 0 2.234375 0.65625q0.96875 0.640625 1.453125 1.828125q0.5 1.1875 0.5 2.59375q0 1.5156174 -0.546875 2.7343674q-0.546875 1.203125 -1.578125 1.84375q-1.03125 0.640625 -2.171875 0.640625q-0.84375 0 -1.515625 -0.34375q-0.65625 -0.359375 -1.078125 -0.890625l0 4.796875l-1.671875 0zm1.515625 -8.656242q0 1.9062424 0.765625 2.8124924q0.78125 0.90625 1.875 0.90625q1.109375 0 1.890625 -0.9375q0.796875 -0.9375 0.796875 -2.9218674q0 -1.875 -0.78125 -2.8125q-0.765625 -0.9375 -1.84375 -0.9375q-1.0625 0 -1.890625 1.0q-0.8125 1.0 -0.8125 2.890625zm8.828857 4.8749924l0 -13.593742l1.671875 0l0 13.593742l-1.671875 0zm3.5510254 -4.9218674q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.9062424 -0.578125 2.9999924q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8124924zm1.71875 0q0 1.8906174 0.828125 2.8281174q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.8906174q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.203857 8.718742l-0.171875 -1.5625q0.546875 0.140625 0.953125 0.140625q0.546875 0 0.875 -0.1875q0.34375 -0.1875 0.5625 -0.515625q0.15625 -0.25 0.5 -1.25q0.046875 -0.140625 0.15625 -0.40625l-3.734375 -9.874992l1.796875 0l2.046875 5.7187424q0.40625 1.078125 0.71875 2.28125q0.28125 -1.15625 0.6875 -2.25l2.09375 -5.7499924l1.671875 0l-3.75 10.031242q-0.59375 1.625 -0.9375 2.234375q-0.4375 0.828125 -1.015625 1.203125q-0.578125 0.390625 -1.375 0.390625q-0.484375 0 -1.078125 -0.203125zm18.245789 -5.296875l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.6562424l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.7499924q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm0.9020996 -3.4218674q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.9062424 -0.578125 2.9999924q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8124924zm1.71875 0q0 1.8906174 0.828125 2.8281174q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.8906174q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125z" fill-rule="nonzero"></path><path fill="#000000" d="m808.1591 150.36026l1.6875 -0.140625q0.125 1.015625 0.5625 1.671875q0.4375 0.65625 1.359375 1.0625q0.9375 0.40625 2.09375 0.40625q1.03125 0 1.8125 -0.3125q0.796875 -0.3125 1.1875 -0.84375q0.390625 -0.53125 0.390625 -1.15625q0 -0.640625 -0.375 -1.109375q-0.375 -0.484375 -1.234375 -0.8125q-0.546875 -0.21875 -2.421875 -0.65625q-1.875 -0.453125 -2.625 -0.859375q-0.96875 -0.515625 -1.453125 -1.265625q-0.46875 -0.75 -0.46875 -1.6875q0 -1.03125 0.578125 -1.921875q0.59375 -0.90625 1.703125 -1.359375q1.125 -0.46875 2.5 -0.46875q1.515625 0 2.671875 0.484375q1.15625 0.484375 1.765625 1.4375q0.625 0.9375 0.671875 2.140625l-1.71875 0.125q-0.140625 -1.28125 -0.953125 -1.9375q-0.796875 -0.671875 -2.359375 -0.671875q-1.625 0 -2.375 0.609375q-0.75 0.59375 -0.75 1.4375q0 0.734375 0.53125 1.203125q0.515625 0.46875 2.703125 0.96875q2.203125 0.5 3.015625 0.875q1.1875 0.546875 1.75 1.390625q0.578125 0.828125 0.578125 1.921875q0 1.09375 -0.625 2.0625q-0.625 0.953125 -1.796875 1.484375q-1.15625 0.53125 -2.609375 0.53125q-1.84375 0 -3.09375 -0.53125q-1.25 -0.546875 -1.96875 -1.625q-0.703125 -1.078125 -0.734375 -2.453125zm16.490417 2.875l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm7.9645386 0.28125q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm3.7819824 5.75l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.313232 -6.578125l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.1292114 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm10.078796 0.8125l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875z" fill-rule="nonzero"></path><path fill="#efefef" d="m925.54333 177.39108l147.21252 0l0 59.74803l-147.21252 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m925.54333 177.39108l147.21252 0l0 59.74803l-147.21252 0z" fill-rule="nonzero"></path><path fill="#000000" d="m961.2107 203.18509l0 -13.59375l4.6875 0q1.578125 0 2.421875 0.1875q1.15625 0.265625 1.984375 0.96875q1.078125 0.921875 1.609375 2.34375q0.53125 1.40625 0.53125 3.21875q0 1.546875 -0.359375 2.75q-0.359375 1.1875 -0.921875 1.984375q-0.5625 0.78125 -1.234375 1.234375q-0.671875 0.4375 -1.625 0.671875q-0.953125 0.234375 -2.1875 0.234375l-4.90625 0zm1.796875 -1.609375l2.90625 0q1.34375 0 2.109375 -0.25q0.765625 -0.25 1.21875 -0.703125q0.640625 -0.640625 1.0 -1.71875q0.359375 -1.078125 0.359375 -2.625q0 -2.125 -0.703125 -3.265625q-0.703125 -1.15625 -1.703125 -1.546875q-0.71875 -0.28125 -2.328125 -0.28125l-2.859375 0l0 10.390625zm18.207275 -1.5625l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.110107 9.65625l0 -13.640625l1.53125 0l0 1.28125q0.53125 -0.75 1.203125 -1.125q0.6875 -0.375 1.640625 -0.375q1.265625 0 2.234375 0.65625q0.96875 0.640625 1.453125 1.828125q0.5 1.1875 0.5 2.59375q0 1.515625 -0.546875 2.734375q-0.546875 1.203125 -1.578125 1.84375q-1.03125 0.640625 -2.171875 0.640625q-0.84375 0 -1.515625 -0.34375q-0.65625 -0.359375 -1.078125 -0.890625l0 4.796875l-1.671875 0zm1.515625 -8.65625q0 1.90625 0.765625 2.8125q0.78125 0.90625 1.875 0.90625q1.109375 0 1.890625 -0.9375q0.796875 -0.9375 0.796875 -2.921875q0 -1.875 -0.78125 -2.8125q-0.765625 -0.9375 -1.84375 -0.9375q-1.0625 0 -1.890625 1.0q-0.8125 1.0 -0.8125 2.890625zm8.828857 4.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm3.5510864 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.203796 8.71875l-0.171875 -1.5625q0.546875 0.140625 0.953125 0.140625q0.546875 0 0.875 -0.1875q0.34375 -0.1875 0.5625 -0.515625q0.15625 -0.25 0.5 -1.25q0.046875 -0.140625 0.15625 -0.40625l-3.734375 -9.875l1.796875 0l2.046875 5.71875q0.40625 1.078125 0.71875 2.28125q0.28125 -1.15625 0.6875 -2.25l2.09375 -5.75l1.671875 0l-3.75 10.03125q-0.59375 1.625 -0.9375 2.234375q-0.4375 0.828125 -1.015625 1.203125q-0.578125 0.390625 -1.375 0.390625q-0.484375 0 -1.078125 -0.203125zm18.24585 -5.296875l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm0.90197754 -3.421875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125z" fill-rule="nonzero"></path><path fill="#000000" d="m956.0228 225.18509l0 -13.59375l5.125 0q1.359375 0 2.078125 0.125q1.0 0.171875 1.671875 0.640625q0.671875 0.46875 1.078125 1.3125q0.421875 0.84375 0.421875 1.84375q0 1.734375 -1.109375 2.9375q-1.09375 1.203125 -3.984375 1.203125l-3.484375 0l0 5.53125l-1.796875 0zm1.796875 -7.140625l3.515625 0q1.75 0 2.46875 -0.640625q0.734375 -0.65625 0.734375 -1.828125q0 -0.859375 -0.4375 -1.46875q-0.421875 -0.609375 -1.125 -0.796875q-0.453125 -0.125 -1.671875 -0.125l-3.484375 0l0 4.859375zm10.4122925 7.140625l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm5.6033325 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm15.672607 4.921875l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375zm15.719421 4.921875l0 -1.453125q-1.140625 1.671875 -3.125 1.671875q-0.859375 0 -1.625 -0.328125q-0.75 -0.34375 -1.125 -0.84375q-0.359375 -0.5 -0.515625 -1.234375q-0.09375 -0.5 -0.09375 -1.5625l0 -6.109375l1.671875 0l0 5.46875q0 1.3125 0.09375 1.765625q0.15625 0.65625 0.671875 1.03125q0.515625 0.375 1.265625 0.375q0.75 0 1.40625 -0.375q0.65625 -0.390625 0.921875 -1.046875q0.28125 -0.671875 0.28125 -1.9375l0 -5.28125l1.671875 0l0 9.859375l-1.5 0zm10.360107 -3.609375l1.640625 0.21875q-0.265625 1.6875 -1.375 2.65625q-1.109375 0.953125 -2.734375 0.953125q-2.015625 0 -3.25 -1.3125q-1.21875 -1.328125 -1.21875 -3.796875q0 -1.59375 0.515625 -2.78125q0.53125 -1.203125 1.609375 -1.796875q1.09375 -0.609375 2.359375 -0.609375q1.609375 0 2.625 0.8125q1.015625 0.8125 1.3125 2.3125l-1.625 0.25q-0.234375 -1.0 -0.828125 -1.5q-0.59375 -0.5 -1.421875 -0.5q-1.265625 0 -2.0625 0.90625q-0.78125 0.90625 -0.78125 2.859375q0 1.984375 0.765625 2.890625q0.765625 0.890625 1.984375 0.890625q0.984375 0 1.640625 -0.59375q0.65625 -0.609375 0.84375 -1.859375zm6.546875 2.109375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426636 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5042114 -4.921875q0 -2.734375 1.531311 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.281311 -1.328125 -1.281311 -3.8125zm1.718811 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.28186 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m57.989502 117.082985l156.94489 0l0 39.46456l-156.94489 0z" fill-rule="nonzero"></path><path fill="#000000" d="m71.518036 144.00298l0 -13.59375l2.71875 0l3.21875 9.625q0.4375 1.34375 0.640625 2.015625q0.234375 -0.75 0.734375 -2.1875l3.25 -9.453125l2.421875 0l0 13.59375l-1.734375 0l0 -11.390625l-3.953125 11.390625l-1.625 0l-3.9375 -11.578125l0 11.578125l-1.734375 0zm22.134552 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.094467 5.875l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm5.931427 0.8125l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm16.047592 1.9375l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm17.949646 4.375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm0.90205383 -3.421875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm14.621521 4.921875l0 -13.59375l2.71875 0l3.21875 9.625q0.4375 1.34375 0.640625 2.015625q0.234375 -0.75 0.734375 -2.1875l3.25 -9.453125l2.421875 0l0 13.59375l-1.734375 0l0 -11.390625l-3.953125 11.390625l-1.625 0l-3.9375 -11.578125l0 11.578125l-1.734375 0zm21.822052 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm3.4069672 2.0l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277054 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.094467 5.875l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m5.0104985 187.5328l209.95276 0l0 39.46457l-209.95276 0z" fill-rule="nonzero"></path><path fill="#000000" d="m34.188858 214.4528l0 -13.59375l2.71875 0l3.21875 9.625q0.4375 1.34375 0.640625 2.015625q0.234375 -0.75 0.734375 -2.1875l3.25 -9.453125l2.421875 0l0 13.59375l-1.734375 0l0 -11.390625l-3.953125 11.390625l-1.625 0l-3.9375 -11.578125l0 11.578125l-1.734375 0zm22.134552 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.094467 5.875l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm5.931427 0.8125l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm16.047592 1.9375l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm17.949646 4.375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm0.90205383 -3.421875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm14.684021 4.921875l0 -13.59375l5.125 0q1.359375 0 2.078125 0.125q1.0 0.171875 1.671875 0.640625q0.671875 0.46875 1.078125 1.3125q0.421875 0.84375 0.421875 1.84375q0 1.734375 -1.109375 2.9375q-1.09375 1.203125 -3.984375 1.203125l-3.484375 0l0 5.53125l-1.796875 0zm1.796875 -7.140625l3.515625 0q1.75 0 2.46875 -0.640625q0.734375 -0.65625 0.734375 -1.828125q0 -0.859375 -0.4375 -1.46875q-0.421875 -0.609375 -1.125 -0.796875q-0.453125 -0.125 -1.671875 -0.125l-3.484375 0l0 4.859375zm10.412323 7.140625l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm5.603302 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm15.672592 4.921875l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375zm15.719467 4.921875l0 -1.453125q-1.140625 1.671875 -3.125 1.671875q-0.859375 0 -1.625 -0.328125q-0.75 -0.34375 -1.125 -0.84375q-0.359375 -0.5 -0.515625 -1.234375q-0.09375 -0.5 -0.09375 -1.5625l0 -6.109375l1.671875 0l0 5.46875q0 1.3125 0.09375 1.765625q0.15625 0.65625 0.671875 1.03125q0.515625 0.375 1.265625 0.375q0.75 0 1.40625 -0.375q0.65625 -0.390625 0.921875 -1.046875q0.28125 -0.671875 0.28125 -1.9375l0 -5.28125l1.671875 0l0 9.859375l-1.5 0zm10.360092 -3.609375l1.640625 0.21875q-0.265625 1.6875 -1.375 2.65625q-1.109375 0.953125 -2.734375 0.953125q-2.015625 0 -3.25 -1.3125q-1.21875 -1.328125 -1.21875 -3.796875q0 -1.59375 0.515625 -2.78125q0.53125 -1.203125 1.609375 -1.796875q1.09375 -0.609375 2.359375 -0.609375q1.609375 0 2.625 0.8125q1.015625 0.8125 1.3125 2.3125l-1.625 0.25q-0.234375 -1.0 -0.828125 -1.5q-0.59375 -0.5 -1.421875 -0.5q-1.265625 0 -2.0625 0.90625q-0.78125 0.90625 -0.78125 2.859375q0 1.984375 0.765625 2.890625q0.765625 0.890625 1.984375 0.890625q0.984375 0 1.640625 -0.59375q0.65625 -0.609375 0.84375 -1.859375zm6.546875 2.109375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426788 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5041962 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281967 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm10.813217 0l0 -1.90625l1.90625 0l0 1.90625q0 1.046875 -0.375 1.6875q-0.375 0.65625 -1.171875 1.0l-0.46875 -0.71875q0.53125 -0.21875 0.78125 -0.671875q0.25 -0.453125 0.28125 -1.296875l-0.953125 0z" fill-rule="nonzero"></path><path fill="#000000" d="m51.19565 236.4528l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.161606 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm3.7819672 5.75l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm14.887146 5.109375l0 -8.546875l-1.484375 0l0 -1.3125l1.484375 0l0 -1.046875q0 -0.984375 0.171875 -1.46875q0.234375 -0.65625 0.84375 -1.046875q0.609375 -0.40625 1.703125 -0.40625q0.703125 0 1.5625 0.15625l-0.25 1.46875q-0.515625 -0.09375 -0.984375 -0.09375q-0.765625 0 -1.078125 0.328125q-0.3125 0.3125 -0.3125 1.203125l0 0.90625l1.921875 0l0 1.3125l-1.921875 0l0 8.546875l-1.65625 0zm4.152054 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.266342 4.921875l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm11.661606 0l0 -13.59375l6.03125 0q1.8125 0 2.75 0.359375q0.953125 0.359375 1.515625 1.296875q0.5625 0.921875 0.5625 2.046875q0 1.453125 -0.9375 2.453125q-0.921875 0.984375 -2.890625 1.25q0.71875 0.34375 1.09375 0.671875q0.78125 0.734375 1.484375 1.8125l2.375 3.703125l-2.265625 0l-1.796875 -2.828125q-0.796875 -1.21875 -1.3125 -1.875q-0.5 -0.65625 -0.90625 -0.90625q-0.40625 -0.265625 -0.8125 -0.359375q-0.3125 -0.078125 -1.015625 -0.078125l-2.078125 0l0 6.046875l-1.796875 0zm1.796875 -7.59375l3.859375 0q1.234375 0 1.921875 -0.25q0.703125 -0.265625 1.0625 -0.828125q0.375 -0.5625 0.375 -1.21875q0 -0.96875 -0.703125 -1.578125q-0.703125 -0.625 -2.21875 -0.625l-4.296875 0l0 4.5zm18.176071 4.421875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.078842 5.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm10.926071 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm15.547592 4.65625q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm3.4069672 2.0l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm16.75 -0.234375l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.547592 5.875l0 -1.90625l1.90625 0l0 1.90625q0 1.046875 -0.375 1.6875q-0.375 0.65625 -1.171875 1.0l-0.46875 -0.71875q0.53125 -0.21875 0.78125 -0.671875q0.25 -0.453125 0.28125 -1.296875l-0.953125 0zm9.304108 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.266342 4.921875l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" d="m88.11708 258.45282l0 -13.593765l2.71875 0l3.21875 9.625q0.4375 1.34375 0.640625 2.0156403q0.234375 -0.75001526 0.734375 -2.1875153l3.25 -9.453125l2.421875 0l0 13.593765l-1.734375 0l0 -11.39064l-3.953125 11.39064l-1.625 0l-3.9375 -11.57814l0 11.57814l-1.734375 0zm21.822052 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.0312653q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.3281403 0.09375 2.9531403q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.7187653q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.67189026 0.5 1.1250153q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.1562653q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm4.078842 4.9375153l0 -9.85939l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625153l-1.671875 0l0 -6.0000153q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.3750153l-1.671875 0zm16.828842 0l0 -1.453125q-1.140625 1.671875 -3.125 1.671875q-0.859375 0 -1.625 -0.328125q-0.75 -0.34375 -1.125 -0.84375q-0.359375 -0.5 -0.515625 -1.234375q-0.09375 -0.50001526 -0.09375 -1.5625153l0 -6.109375l1.671875 0l0 5.46875q0 1.3125 0.09375 1.765625q0.15625 0.65626526 0.671875 1.0312653q0.515625 0.375 1.265625 0.375q0.75 0 1.40625 -0.375q0.65625 -0.390625 0.921875 -1.0468903q0.28125 -0.671875 0.28125 -1.9375l0 -5.28125l1.671875 0l0 9.85939l-1.5 0zm10.360092 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.0312653q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.3281403 0.09375 2.9531403q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.7187653q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.67189026 0.5 1.1250153q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.1562653q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm4.047592 4.9375153l0 -13.593765l1.671875 0l0 13.593765l-1.671875 0zm13.015625 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.9843903l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71876526 0.078125 0.92189026q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5114288 1.5l0 -9.85939l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.1562653l-1.671875 0zm6.243927 -11.687515l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.687515l0 -9.85939l1.671875 0l0 9.85939l-1.671875 0zm3.8323212 0.8125l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.4687653 -1.109375 -3.5156403q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.51564q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.9218903q0 1.953125 0.765625 2.8437653q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.89064026 0.78125 -2.7812653q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.000717 5.9218903l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.4687653 -1.109375 -3.5156403q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.51564q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.9218903q0 1.953125 0.765625 2.8437653q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.89064026 0.78125 -2.7812653q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm16.047592 1.9375l1.71875 0.21875q-0.40625 1.5000153 -1.515625 2.3437653q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.7343903q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.4843903q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.5468903zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.094467 5.8750153l0 -9.85939l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.1562653l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m214.93439 46.93176l13.599762 0l0 0.062992096l13.612839 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m214.93439 46.93176l13.599747 0l0 0.062992096l7.612854 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m236.14699 48.646484l4.538086 -1.6517334l-4.538086 -1.6517334z" fill-rule="evenodd"></path><path fill="#efefef" d="m242.13387 17.057743l147.2126 0l0 59.748028l-147.2126 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m242.13387 17.057743l147.2126 0l0 59.748028l-147.2126 0z" fill-rule="nonzero"></path><path fill="#000000" d="m296.38846 53.851757l0 -13.59375l5.109375 0q1.546875 0 2.484375 0.40625q0.953125 0.40625 1.484375 1.265625q0.53125 0.859375 0.53125 1.796875q0 0.875 -0.46875 1.65625q-0.46875 0.765625 -1.4375 1.234375q1.234375 0.359375 1.890625 1.234375q0.671875 0.875 0.671875 2.0625q0 0.953125 -0.40625 1.78125q-0.390625 0.8125 -0.984375 1.265625q-0.59375 0.4375 -1.5 0.671875q-0.890625 0.21875 -2.1875 0.21875l-5.1875 0zm1.796875 -7.890625l2.9375 0q1.203125 0 1.71875 -0.15625q0.6875 -0.203125 1.03125 -0.671875q0.359375 -0.46875 0.359375 -1.1875q0 -0.671875 -0.328125 -1.1875q-0.328125 -0.515625 -0.9375 -0.703125q-0.59375 -0.203125 -2.0625 -0.203125l-2.71875 0l0 4.109375zm0 6.28125l3.390625 0q0.875 0 1.21875 -0.0625q0.625 -0.109375 1.046875 -0.359375q0.421875 -0.265625 0.6875 -0.765625q0.265625 -0.5 0.265625 -1.140625q0 -0.765625 -0.390625 -1.328125q-0.390625 -0.5625 -1.078125 -0.78125q-0.6875 -0.234375 -1.984375 -0.234375l-3.15625 0l0 4.671875zm16.959198 1.609375l0 -1.453125q-1.140625 1.671875 -3.125 1.671875q-0.859375 0 -1.625 -0.328125q-0.75 -0.34375 -1.125 -0.84375q-0.359375 -0.5 -0.515625 -1.234375q-0.09375 -0.5 -0.09375 -1.5625l0 -6.109375l1.671875 0l0 5.46875q0 1.3125 0.09375 1.765625q0.15625 0.65625 0.671875 1.03125q0.515625 0.375 1.265625 0.375q0.75 0 1.40625 -0.375q0.65625 -0.390625 0.921875 -1.046875q0.28125 -0.671875 0.28125 -1.9375l0 -5.28125l1.671875 0l0 9.859375l-1.5 0zm3.9382324 -11.6875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.097931 0l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm10.566711 0l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375z" fill-rule="nonzero"></path><path fill="#efefef" d="m408.5328 17.057743l147.21262 0l0 59.748028l-147.21262 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m408.5328 17.057743l147.21262 0l0 59.748028l-147.21262 0z" fill-rule="nonzero"></path><path fill="#000000" d="m455.20813 40.258007l1.796875 0l0 7.84375q0 2.0625 -0.46875 3.265625q-0.453125 1.203125 -1.671875 1.96875q-1.203125 0.75 -3.171875 0.75q-1.90625 0 -3.125 -0.65625q-1.21875 -0.65625 -1.734375 -1.90625q-0.515625 -1.25 -0.515625 -3.421875l0 -7.84375l1.796875 0l0 7.84375q0 1.765625 0.328125 2.609375q0.328125 0.84375 1.125 1.296875q0.8125 0.453125 1.96875 0.453125q1.984375 0 2.828125 -0.890625q0.84375 -0.90625 0.84375 -3.46875l0 -7.84375zm4.332306 13.59375l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm10.391357 -11.6875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm7.785431 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm10.382233 1.5l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438202 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#efefef" d="m594.1181 37.30971l147.21259 0l0 59.748028l-147.21259 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m594.1181 37.30971l147.21259 0l0 59.748028l-147.21259 0z" fill-rule="nonzero"></path><path fill="#000000" d="m625.4092 63.103725l0 -13.59375l1.8125 0l0 13.59375l-1.8125 0zm4.6676636 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm14.031982 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277039 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.813232 6.6875l1.609375 0.24999619q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.2812462q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3124962 -0.46875 3.2656212q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.3906212zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.281982 5.109375l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm12.6657715 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.7351074 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426636 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5042114 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281982 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" d="m654.5047 85.10372l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438232 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#efefef" d="m584.5302 27.199474l147.21259 0l0 59.748035l-147.21259 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m584.5302 27.199474l147.21259 0l0 59.748035l-147.21259 0z" fill-rule="nonzero"></path><path fill="#000000" d="m615.8212 52.99349l0 -13.59375l1.8125 0l0 13.59375l-1.8125 0zm4.6677246 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm14.031921 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.2771 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.813171 6.6875l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.281982 5.109375l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm12.6658325 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.7350464 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5427246 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5041504 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281982 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" d="m644.9168 74.99349l0 -12.000004l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.000004l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438171 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375038l1.65625 -1.0l0 3.4375038l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#efefef" d="m574.93176 17.057743l147.21259 0l0 59.748028l-147.21259 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m574.93176 17.057743l147.21259 0l0 59.748028l-147.21259 0z" fill-rule="nonzero"></path><path fill="#000000" d="m606.22284 42.851757l0 -13.59375l1.8125 0l0 13.59375l-1.8125 0zm4.6676636 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm14.031982 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277039 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.813232 6.6875l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.281982 5.109375l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm12.6657715 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.7351074 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426636 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5042114 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281982 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" d="m635.31836 64.85175l0 -11.999996l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 11.999996l-1.796875 0zm14.474121 -3.1718712l1.71875 0.21875q-0.40625 1.5 -1.515625 2.3437462q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.3281212q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438232 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.7343712 -1.40625 1.1406212q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.7968712 -1.28125 -2.3593712zm13.65625 1.4375l0.234375 1.4843712q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.7499962q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m389.34647 46.93176l9.593231 0l0 0.062992096l9.58786 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m389.34647 46.93176l9.593201 0l0 0.062992096l3.5878906 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m402.52756 48.646484l4.538086 -1.6517334l-4.538086 -1.6517334z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m555.7454 46.93176l9.593201 0l0 0.062992096l9.587891 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m555.7454 46.93176l9.593201 0l0 0.062992096l3.5878906 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m568.9265 48.646484l4.538086 -1.6517334l-4.538086 -1.6517334z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m214.96326 207.26509l355.29132 0l0 0.06298828l355.29138 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m214.96326 207.26509l355.29132 0l0 0.06298828l349.29138 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m919.54596 208.97981l4.538086 -1.6517334l-4.538086 -1.6517334z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m214.93439 136.81526l14.661118 0l0 0.06300354l14.661713 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m214.93439 136.81526l14.661133 0l0 0.06300354l8.661697 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m238.25722 138.53l4.538101 -1.6517334l-4.538101 -1.6517334z" fill-rule="evenodd"></path><path fill="#efefef" d="m244.25691 106.94125l147.2126 0l0 59.74803l-147.2126 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m244.25691 106.94125l147.2126 0l0 59.74803l-147.2126 0z" fill-rule="nonzero"></path><path fill="#000000" d="m298.5115 143.73526l0 -13.59375l5.109375 0q1.546875 0 2.484375 0.40625q0.953125 0.40625 1.484375 1.265625q0.53125 0.859375 0.53125 1.796875q0 0.875 -0.46875 1.65625q-0.46875 0.765625 -1.4375 1.234375q1.234375 0.359375 1.890625 1.234375q0.671875 0.875 0.671875 2.0625q0 0.953125 -0.40625 1.78125q-0.390625 0.8125 -0.984375 1.265625q-0.59375 0.4375 -1.5 0.671875q-0.890625 0.21875 -2.1875 0.21875l-5.1875 0zm1.796875 -7.890625l2.9375 0q1.203125 0 1.71875 -0.15625q0.6875 -0.203125 1.03125 -0.671875q0.359375 -0.46875 0.359375 -1.1875q0 -0.671875 -0.328125 -1.1875q-0.328125 -0.515625 -0.9375 -0.703125q-0.59375 -0.203125 -2.0625 -0.203125l-2.71875 0l0 4.109375zm0 6.28125l3.390625 0q0.875 0 1.21875 -0.0625q0.625 -0.109375 1.046875 -0.359375q0.421875 -0.265625 0.6875 -0.765625q0.265625 -0.5 0.265625 -1.140625q0 -0.765625 -0.390625 -1.328125q-0.390625 -0.5625 -1.078125 -0.78125q-0.6875 -0.234375 -1.984375 -0.234375l-3.15625 0l0 4.671875zm16.959198 1.609375l0 -1.453125q-1.140625 1.671875 -3.125 1.671875q-0.859375 0 -1.625 -0.328125q-0.75 -0.34375 -1.125 -0.84375q-0.359375 -0.5 -0.515625 -1.234375q-0.09375 -0.5 -0.09375 -1.5625l0 -6.109375l1.671875 0l0 5.46875q0 1.3125 0.09375 1.765625q0.15625 0.65625 0.671875 1.03125q0.515625 0.375 1.265625 0.375q0.75 0 1.40625 -0.375q0.65625 -0.390625 0.921875 -1.046875q0.28125 -0.671875 0.28125 -1.9375l0 -5.28125l1.671875 0l0 9.859375l-1.5 0zm3.9382324 -11.6875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.097931 0l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm10.566711 0l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375z" fill-rule="nonzero"></path><path fill="#efefef" d="m410.65585 106.94125l147.21262 0l0 59.74803l-147.21262 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m410.65585 106.94125l147.21262 0l0 59.74803l-147.21262 0z" fill-rule="nonzero"></path><path fill="#000000" d="m457.33118 130.14151l1.796875 0l0 7.84375q0 2.0625 -0.46875 3.265625q-0.453125 1.203125 -1.671875 1.96875q-1.203125 0.75 -3.171875 0.75q-1.90625 0 -3.125 -0.65625q-1.21875 -0.65625 -1.734375 -1.90625q-0.515625 -1.25 -0.515625 -3.421875l0 -7.84375l1.796875 0l0 7.84375q0 1.765625 0.328125 2.609375q0.328125 0.84375 1.125 1.296875q0.8125 0.453125 1.96875 0.453125q1.984375 0 2.828125 -0.890625q0.84375 -0.90625 0.84375 -3.46875l0 -7.84375zm4.332306 13.59375l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm10.391357 -11.6875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm7.785431 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm10.382233 1.5l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438202 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#efefef" d="m596.24115 127.19322l147.21259 0l0 59.74803l-147.21259 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m596.24115 127.19322l147.21259 0l0 59.74803l-147.21259 0z" fill-rule="nonzero"></path><path fill="#000000" d="m627.5322 152.98723l0 -13.59375l1.8125 0l0 13.59375l-1.8125 0zm4.6676636 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm14.031982 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277039 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.813232 6.6875l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.281982 5.109375l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm12.6657715 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.7351074 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426636 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5042114 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281982 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" d="m656.62775 174.98723l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438232 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#efefef" d="m586.65326 117.082985l147.21259 0l0 59.748024l-147.21259 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m586.65326 117.082985l147.21259 0l0 59.748024l-147.21259 0z" fill-rule="nonzero"></path><path fill="#000000" d="m617.9443 142.877l0 -13.59375l1.8125 0l0 13.59375l-1.8125 0zm4.6677246 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm14.031921 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.2771 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.813171 6.6875l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.281982 5.109375l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm12.6658325 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.7350464 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5427246 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5041504 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281982 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" d="m647.03986 164.877l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438171 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#efefef" d="m577.0548 106.94125l147.21259 0l0 59.74803l-147.21259 0z" fill-rule="nonzero"></path><path stroke="#999999" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m577.0548 106.94125l147.21259 0l0 59.74803l-147.21259 0z" fill-rule="nonzero"></path><path fill="#000000" d="m608.3459 132.73526l0 -13.593742l1.8125 0l0 13.593742l-1.8125 0zm4.6676636 0l0 -9.859367l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0624924l-1.671875 0l0 -5.9999924q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.3749924l-1.671875 0zm14.031982 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.6562424l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.7499924q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277039 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.7343674q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.43749237l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.7031174l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.813232 6.6874924l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.5156174q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515617q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.9218674q0 1.9531174 0.765625 2.8437424q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.7812424q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.281982 5.1093674l0 -9.859367l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.1562424l-1.671875 0zm12.6657715 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.9531174q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.2343674q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.7187424q-0.90625 0.35936737 -2.734375 0.6249924q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.6093674zm7.7351074 3.4374924l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.6562424l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.7499924q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426636 -10.187492l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.687492l0 -9.859367l1.671875 0l0 9.859367l-1.671875 0zm3.5042114 -4.9218674q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.9062424 -0.578125 2.9999924q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8124924zm1.71875 0q0 1.8906174 0.828125 2.8281174q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.8906174q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281982 4.9218674l0 -9.859367l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0624924l-1.671875 0l0 -5.9999924q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.3749924l-1.671875 0z" fill-rule="nonzero"></path><path fill="#000000" d="m637.4414 154.73526l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438232 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m391.4695 136.81526l9.593231 0l0 0.06300354l9.58786 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m391.46954 136.81526l9.593201 0l0 0.06300354l3.5878906 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m404.65063 138.53l4.538086 -1.6517334l-4.538086 -1.6517334z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m557.86847 136.81526l9.593201 0l0 0.06300354l9.587891 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m557.86847 136.81526l9.593201 0l0 0.06300354l3.5878906 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m571.04956 138.53l4.538147 -1.6517334l-4.538147 -1.6517334z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m724.2674 136.81526l20.531738 0l0 0.06300354l20.539124 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m724.2674 136.81526l20.531738 0l0 0.06300354l14.539124 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m759.33826 138.53l4.538086 -1.6517334l-4.538086 -1.6517334z" fill-rule="evenodd"></path></g></svg>
-
diff --git a/doc/ci/img/types-of-pipelines.png b/doc/ci/img/types-of-pipelines.png
new file mode 100644
index 00000000000..bd809de5e68
--- /dev/null
+++ b/doc/ci/img/types-of-pipelines.png
Binary files differ
diff --git a/doc/ci/img/types-of-pipelines.svg b/doc/ci/img/types-of-pipelines.svg
deleted file mode 100644
index b63b5f56ba6..00000000000
--- a/doc/ci/img/types-of-pipelines.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" standalone="yes"?>
-
-<svg version="1.1" viewBox="0.0 0.0 740.6272965879265 293.7795275590551" fill="none" stroke="none" stroke-linecap="square" stroke-miterlimit="10" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><clipPath id="p.0"><path d="m0 0l740.6273 0l0 293.77954l-740.6273 0l0 -293.77954z" clip-rule="nonzero"></path></clipPath><g clip-path="url(#p.0)"><path fill="#000000" fill-opacity="0.0" d="m0 0l740.6273 0l0 293.77954l-740.6273 0z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m176.05511 4.632546l282.4567 0l0 129.10236l-282.4567 0z" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" stroke-dasharray="4.0,3.0" d="m176.05511 4.632546l282.4567 0l0 129.10236l-282.4567 0z" fill-rule="nonzero"></path><path fill="#ff0000" d="m283.34512 115.88928l1.796875 0.453125q-0.5625 2.21875 -2.03125 3.390625q-1.46875 1.15625 -3.59375 1.15625q-2.203125 0 -3.578125 -0.890625q-1.375 -0.90625 -2.09375 -2.59375q-0.71875 -1.703125 -0.71875 -3.65625q0 -2.125 0.796875 -3.703125q0.8125 -1.578125 2.3125 -2.390625q1.5 -0.828125 3.296875 -0.828125q2.046875 0 3.4375 1.046875q1.390625 1.03125 1.9375 2.90625l-1.765625 0.421875q-0.46875 -1.484375 -1.375 -2.15625q-0.90625 -0.6875 -2.265625 -0.6875q-1.5625 0 -2.625 0.75q-1.046875 0.75 -1.484375 2.03125q-0.421875 1.265625 -0.421875 2.609375q0 1.734375 0.5 3.03125q0.515625 1.28125 1.578125 1.921875q1.078125 0.640625 2.3125 0.640625q1.515625 0 2.5625 -0.859375q1.046875 -0.875 1.421875 -2.59375zm4.066681 4.765625l0 -13.59375l1.8125 0l0 13.59375l-1.8125 0zm10.069733 0l0 -13.59375l5.125 0q1.359375 0 2.078125 0.125q1.0 0.171875 1.671875 0.640625q0.671875 0.46875 1.078125 1.3125q0.421875 0.84375 0.421875 1.84375q0 1.734375 -1.109375 2.9375q-1.09375 1.203125 -3.984375 1.203125l-3.484375 0l0 5.53125l-1.796875 0zm1.796875 -7.140625l3.515625 0q1.75 0 2.46875 -0.640625q0.734375 -0.65625 0.734375 -1.828125q0 -0.859375 -0.4375 -1.46875q-0.421875 -0.609375 -1.125 -0.796875q-0.453125 -0.125 -1.671875 -0.125l-3.484375 0l0 4.859375zm10.443573 -4.546875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.1292114 3.78125l0 -13.640625l1.53125 0l0 1.28125q0.53125 -0.75 1.203125 -1.125q0.6875 -0.375 1.640625 -0.375q1.265625 0 2.234375 0.65625q0.96875 0.640625 1.453125 1.828125q0.5 1.1875 0.5 2.59375q0 1.515625 -0.546875 2.734375q-0.546875 1.203125 -1.578125 1.84375q-1.03125 0.640625 -2.171875 0.640625q-0.84375 0 -1.515625 -0.34375q-0.65625 -0.359375 -1.078125 -0.890625l0 4.796875l-1.671875 0zm1.515625 -8.65625q0 1.90625 0.765625 2.8125q0.78125 0.90625 1.875 0.90625q1.109375 0 1.890625 -0.9375q0.796875 -0.9375 0.796875 -2.921875q0 -1.875 -0.78125 -2.8125q-0.765625 -0.9375 -1.84375 -0.9375q-1.0625 0 -1.890625 1.0q-0.8125 1.0 -0.8125 2.890625zm15.610077 1.703125l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.078857 5.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm4.191681 -11.6875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.1292114 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm17.125702 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875z" fill-rule="nonzero"></path><path fill="#f3f3f3" d="m482.78796 22.986877l110.11023 0l0 59.74803l-110.11023 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m482.78796 22.986877l110.11023 0l0 59.74803l-110.11023 0z" fill-rule="nonzero"></path><path fill="#434343" d="m499.90414 48.78089l0 -13.59375l4.6875 0q1.578125 0 2.421875 0.1875q1.15625 0.265625 1.984375 0.96875q1.078125 0.921875 1.609375 2.34375q0.53125 1.40625 0.53125 3.21875q0 1.546875 -0.359375 2.75q-0.359375 1.1875 -0.921875 1.984375q-0.5625 0.78125 -1.234375 1.234375q-0.671875 0.4375 -1.625 0.671875q-0.953125 0.234375 -2.1875 0.234375l-4.90625 0zm1.796875 -1.609375l2.90625 0q1.34375 0 2.109375 -0.25q0.765625 -0.25 1.21875 -0.703125q0.640625 -0.640625 1.0 -1.71875q0.359375 -1.078125 0.359375 -2.625q0 -2.125 -0.703125 -3.265625q-0.703125 -1.15625 -1.703125 -1.546875q-0.71875 -0.28125 -2.328125 -0.28125l-2.859375 0l0 10.390625zm18.207306 -1.5625l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.110107 9.65625l0 -13.640625l1.53125 0l0 1.28125q0.53125 -0.75 1.203125 -1.125q0.6875 -0.375 1.640625 -0.375q1.265625 0 2.234375 0.65625q0.96875 0.640625 1.453125 1.828125q0.5 1.1875 0.5 2.59375q0 1.515625 -0.546875 2.734375q-0.546875 1.203125 -1.578125 1.84375q-1.03125 0.640625 -2.171875 0.640625q-0.84375 0 -1.515625 -0.34375q-0.65625 -0.359375 -1.078125 -0.890625l0 4.796875l-1.671875 0zm1.515625 -8.65625q0 1.90625 0.765625 2.8125q0.78125 0.90625 1.875 0.90625q1.109375 0 1.890625 -0.9375q0.796875 -0.9375 0.796875 -2.921875q0 -1.875 -0.78125 -2.8125q-0.765625 -0.9375 -1.84375 -0.9375q-1.0625 0 -1.890625 1.0q-0.8125 1.0 -0.8125 2.890625zm8.828857 4.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm3.5510864 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.203796 8.71875l-0.171875 -1.5625q0.546875 0.140625 0.953125 0.140625q0.546875 0 0.875 -0.1875q0.34375 -0.1875 0.5625 -0.515625q0.15625 -0.25 0.5 -1.25q0.046875 -0.140625 0.15625 -0.40625l-3.734375 -9.875l1.796875 0l2.046875 5.71875q0.40625 1.078125 0.71875 2.28125q0.28125 -1.15625 0.6875 -2.25l2.09375 -5.75l1.671875 0l-3.75 10.03125q-0.59375 1.625 -0.9375 2.234375q-0.4375 0.828125 -1.015625 1.203125q-0.578125 0.390625 -1.375 0.390625q-0.484375 0 -1.078125 -0.203125zm18.245789 -5.296875l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm0.9020996 -3.421875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125z" fill-rule="nonzero"></path><path fill="#434343" d="m507.0652 66.40589l1.6875 -0.140625q0.125 1.015625 0.5625 1.671875q0.4375 0.65625 1.359375 1.0625q0.9375 0.40625 2.09375 0.40625q1.03125 0 1.8125 -0.3125q0.796875 -0.3125 1.1875 -0.84375q0.390625 -0.53125 0.390625 -1.15625q0 -0.640625 -0.375 -1.109375q-0.375 -0.484375 -1.234375 -0.8125q-0.546875 -0.21875 -2.421875 -0.65625q-1.875 -0.453125 -2.625 -0.859375q-0.96875 -0.515625 -1.453125 -1.265625q-0.46875 -0.75 -0.46875 -1.6875q0 -1.03125 0.578125 -1.921875q0.59375 -0.90625 1.703125 -1.359375q1.125 -0.46875 2.5 -0.46875q1.515625 0 2.671875 0.484375q1.15625 0.484375 1.765625 1.4375q0.625 0.9375 0.671875 2.140625l-1.71875 0.125q-0.140625 -1.28125 -0.953125 -1.9375q-0.796875 -0.671875 -2.359375 -0.671875q-1.625 0 -2.375 0.609375q-0.75 0.59375 -0.75 1.4375q0 0.734375 0.53125 1.203125q0.515625 0.46875 2.703125 0.96875q2.203125 0.5 3.015625 0.875q1.1875 0.546875 1.75 1.390625q0.578125 0.828125 0.578125 1.921875q0 1.09375 -0.625 2.0625q-0.625 0.953125 -1.796875 1.484375q-1.15625 0.53125 -2.609375 0.53125q-1.84375 0 -3.09375 -0.53125q-1.25 -0.546875 -1.96875 -1.625q-0.703125 -1.078125 -0.734375 -2.453125zm16.490417 2.875l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm7.9645996 0.28125q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm3.7819214 5.75l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.313232 -6.578125l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.1292114 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm10.078796 0.8125l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875z" fill-rule="nonzero"></path><path fill="#f3f3f3" d="m606.1778 23.019379l110.11023 0l0 59.74803l-110.11023 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m606.1778 23.019379l110.11023 0l0 59.74803l-110.11023 0z" fill-rule="nonzero"></path><path fill="#434343" d="m623.29395 48.813393l0 -13.59375l4.6875 0q1.578125 0 2.421875 0.1875q1.15625 0.265625 1.984375 0.96875q1.078125 0.921875 1.609375 2.34375q0.53125 1.40625 0.53125 3.21875q0 1.546875 -0.359375 2.75q-0.359375 1.1875 -0.921875 1.984375q-0.5625 0.78125 -1.234375 1.234375q-0.671875 0.4375 -1.625 0.671875q-0.953125 0.234375 -2.1875 0.234375l-4.90625 0zm1.796875 -1.609375l2.90625 0q1.34375 0 2.109375 -0.25q0.765625 -0.25 1.21875 -0.703125q0.640625 -0.640625 1.0 -1.71875q0.359375 -1.078125 0.359375 -2.625q0 -2.125 -0.703125 -3.265625q-0.703125 -1.15625 -1.703125 -1.546875q-0.71875 -0.28125 -2.328125 -0.28125l-2.859375 0l0 10.390625zm18.207336 -1.5625l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.110107 9.65625l0 -13.640625l1.53125 0l0 1.28125q0.53125 -0.75 1.203125 -1.125q0.6875 -0.375 1.640625 -0.375q1.265625 0 2.234375 0.65625q0.96875 0.640625 1.453125 1.828125q0.5 1.1875 0.5 2.59375q0 1.515625 -0.546875 2.734375q-0.546875 1.203125 -1.578125 1.84375q-1.03125 0.640625 -2.171875 0.640625q-0.84375 0 -1.515625 -0.34375q-0.65625 -0.359375 -1.078125 -0.890625l0 4.796875l-1.671875 0zm1.515625 -8.65625q0 1.90625 0.765625 2.8125q0.78125 0.90625 1.875 0.90625q1.109375 0 1.890625 -0.9375q0.796875 -0.9375 0.796875 -2.921875q0 -1.875 -0.78125 -2.8125q-0.765625 -0.9375 -1.84375 -0.9375q-1.0625 0 -1.890625 1.0q-0.8125 1.0 -0.8125 2.890625zm8.828857 4.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm3.5510254 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.203857 8.71875l-0.171875 -1.5625q0.546875 0.140625 0.953125 0.140625q0.546875 0 0.875 -0.1875q0.34375 -0.1875 0.5625 -0.515625q0.15625 -0.25 0.5 -1.25q0.046875 -0.140625 0.15625 -0.40625l-3.734375 -9.875l1.796875 0l2.046875 5.71875q0.40625 1.078125 0.71875 2.28125q0.28125 -1.15625 0.6875 -2.25l2.09375 -5.75l1.671875 0l-3.75 10.03125q-0.59375 1.625 -0.9375 2.234375q-0.4375 0.828125 -1.015625 1.203125q-0.578125 0.390625 -1.375 0.390625q-0.484375 0 -1.078125 -0.203125zm18.245789 -5.296875l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm0.9020996 -3.421875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125z" fill-rule="nonzero"></path><path fill="#434343" d="m618.10614 70.81339l0 -13.59375l5.125 0q1.359375 0 2.078125 0.125q1.0 0.171875 1.671875 0.640625q0.671875 0.46875 1.078125 1.3125q0.421875 0.84375 0.421875 1.84375q0 1.734375 -1.109375 2.9375q-1.09375 1.203125 -3.984375 1.203125l-3.484375 0l0 5.53125l-1.796875 0zm1.796875 -7.140625l3.515625 0q1.75 0 2.46875 -0.640625q0.734375 -0.65625 0.734375 -1.828125q0 -0.859375 -0.4375 -1.46875q-0.421875 -0.609375 -1.125 -0.796875q-0.453125 -0.125 -1.671875 -0.125l-3.484375 0l0 4.859375zm10.4122925 7.140625l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm5.6033325 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm15.672546 4.921875l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375zm15.719482 4.921875l0 -1.453125q-1.140625 1.671875 -3.125 1.671875q-0.859375 0 -1.625 -0.328125q-0.75 -0.34375 -1.125 -0.84375q-0.359375 -0.5 -0.515625 -1.234375q-0.09375 -0.5 -0.09375 -1.5625l0 -6.109375l1.671875 0l0 5.46875q0 1.3125 0.09375 1.765625q0.15625 0.65625 0.671875 1.03125q0.515625 0.375 1.265625 0.375q0.75 0 1.40625 -0.375q0.65625 -0.390625 0.921875 -1.046875q0.28125 -0.671875 0.28125 -1.9375l0 -5.28125l1.671875 0l0 9.859375l-1.5 0zm10.360107 -3.609375l1.640625 0.21875q-0.265625 1.6875 -1.375 2.65625q-1.109375 0.953125 -2.734375 0.953125q-2.015625 0 -3.25 -1.3125q-1.21875 -1.328125 -1.21875 -3.796875q0 -1.59375 0.515625 -2.78125q0.53125 -1.203125 1.609375 -1.796875q1.09375 -0.609375 2.359375 -0.609375q1.609375 0 2.625 0.8125q1.015625 0.8125 1.3125 2.3125l-1.625 0.25q-0.234375 -1.0 -0.828125 -1.5q-0.59375 -0.5 -1.421875 -0.5q-1.265625 0 -2.0625 0.90625q-0.78125 0.90625 -0.78125 2.859375q0 1.984375 0.765625 2.890625q0.765625 0.890625 1.984375 0.890625q0.984375 0 1.640625 -0.59375q0.65625 -0.609375 0.84375 -1.859375zm6.546875 2.109375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426636 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5042114 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281982 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#f3f3f3" d="m192.52992 22.986877l110.07875 0l0 59.74803l-110.07875 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m192.52992 22.986877l110.07875 0l0 59.74803l-110.07875 0z" fill-rule="nonzero"></path><path fill="#434343" d="m228.21759 59.78089l0 -13.59375l5.109375 0q1.546875 0 2.484375 0.40625q0.953125 0.40625 1.484375 1.265625q0.53125 0.859375 0.53125 1.796875q0 0.875 -0.46875 1.65625q-0.46875 0.765625 -1.4375 1.234375q1.234375 0.359375 1.890625 1.234375q0.671875 0.875 0.671875 2.0625q0 0.953125 -0.40625 1.78125q-0.390625 0.8125 -0.984375 1.265625q-0.59375 0.4375 -1.5 0.671875q-0.890625 0.21875 -2.1875 0.21875l-5.1875 0zm1.796875 -7.890625l2.9375 0q1.203125 0 1.71875 -0.15625q0.6875 -0.203125 1.03125 -0.671875q0.359375 -0.46875 0.359375 -1.1875q0 -0.671875 -0.328125 -1.1875q-0.328125 -0.515625 -0.9375 -0.703125q-0.59375 -0.203125 -2.0625 -0.203125l-2.71875 0l0 4.109375zm0 6.28125l3.390625 0q0.875 0 1.21875 -0.0625q0.625 -0.109375 1.046875 -0.359375q0.421875 -0.265625 0.6875 -0.765625q0.265625 -0.5 0.265625 -1.140625q0 -0.765625 -0.390625 -1.328125q-0.390625 -0.5625 -1.078125 -0.78125q-0.6875 -0.234375 -1.984375 -0.234375l-3.15625 0l0 4.671875zm16.959198 1.609375l0 -1.453125q-1.140625 1.671875 -3.125 1.671875q-0.859375 0 -1.625 -0.328125q-0.75 -0.34375 -1.125 -0.84375q-0.359375 -0.5 -0.515625 -1.234375q-0.09375 -0.5 -0.09375 -1.5625l0 -6.109375l1.671875 0l0 5.46875q0 1.3125 0.09375 1.765625q0.15625 0.65625 0.671875 1.03125q0.515625 0.375 1.265625 0.375q0.75 0 1.40625 -0.375q0.65625 -0.390625 0.921875 -1.046875q0.28125 -0.671875 0.28125 -1.9375l0 -5.28125l1.671875 0l0 9.859375l-1.5 0zm3.9382172 -11.6875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.097946 0l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm10.566681 0l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375z" fill-rule="nonzero"></path><path fill="#f3f3f3" d="m331.2466 43.238846l110.078735 0l0 59.74803l-110.078735 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m331.2466 43.238846l110.078735 0l0 59.74803l-110.078735 0z" fill-rule="nonzero"></path><path fill="#434343" d="m343.97073 69.03286l0 -13.59375l1.8125 0l0 13.59375l-1.8125 0zm4.667694 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm14.031952 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277069 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.813202 6.6875l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.281982 5.109375l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm12.665802 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.735077 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426941 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.504181 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281982 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#434343" d="m373.06628 91.03286l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438202 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#f3f3f3" d="m324.0777 33.12861l110.078766 0l0 59.74803l-110.078766 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m324.0777 33.12861l110.078766 0l0 59.74803l-110.078766 0z" fill-rule="nonzero"></path><path fill="#434343" d="m336.80185 58.922623l0 -13.59375l1.8125 0l0 13.59375l-1.8125 0zm4.667694 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm14.031952 -1.5l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277069 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.813202 6.6875l1.609375 0.25q0.109375 0.75 0.578125 1.09375q0.609375 0.453125 1.6875 0.453125q1.171875 0 1.796875 -0.46875q0.625 -0.453125 0.859375 -1.28125q0.125 -0.515625 0.109375 -2.15625q-1.09375 1.296875 -2.71875 1.296875q-2.03125 0 -3.15625 -1.46875q-1.109375 -1.46875 -1.109375 -3.515625q0 -1.40625 0.515625 -2.59375q0.515625 -1.203125 1.484375 -1.84375q0.96875 -0.65625 2.265625 -0.65625q1.75 0 2.875 1.40625l0 -1.1875l1.546875 0l0 8.515625q0 2.3125 -0.46875 3.265625q-0.46875 0.96875 -1.484375 1.515625q-1.015625 0.5625 -2.5 0.5625q-1.765625 0 -2.859375 -0.796875q-1.078125 -0.796875 -1.03125 -2.390625zm1.375 -5.921875q0 1.953125 0.765625 2.84375q0.78125 0.890625 1.9375 0.890625q1.140625 0 1.921875 -0.890625q0.78125 -0.890625 0.78125 -2.78125q0 -1.8125 -0.8125 -2.71875q-0.796875 -0.921875 -1.921875 -0.921875q-1.109375 0 -1.890625 0.90625q-0.78125 0.890625 -0.78125 2.671875zm9.281982 5.109375l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm12.6657715 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.8593445 0.3125 -1.8437195 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.0312195 -0.25 2.9843445 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.9062195 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.2499695 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.7343445 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.9687195 0 1.7187195 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.7351074 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm1.5426636 -10.1875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm3.5042114 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281952 4.921875l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0z" fill-rule="nonzero"></path><path fill="#434343" d="m365.8974 80.92262l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474091 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438232 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125z" fill-rule="nonzero"></path><path fill="#f3f3f3" d="m316.90097 22.986877l110.078735 0l0 59.74803l-110.078735 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m316.90097 22.986877l110.078735 0l0 59.74803l-110.078735 0z" fill-rule="nonzero"></path><path fill="#434343" d="m354.05658 59.78089l0 -12.0l-4.46875 0l0 -1.59375l10.765625 0l0 1.59375l-4.5 0l0 12.0l-1.796875 0zm14.474121 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm8.438202 2.9375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375zm13.65625 1.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm0.8551941 -1.4375l1.65625 -0.265625q0.140625 1.0 0.765625 1.53125q0.640625 0.515625 1.78125 0.515625q1.15625 0 1.703125 -0.46875q0.5625 -0.46875 0.5625 -1.09375q0 -0.5625 -0.484375 -0.890625q-0.34375 -0.21875 -1.703125 -0.5625q-1.84375 -0.46875 -2.5625 -0.796875q-0.703125 -0.34375 -1.078125 -0.9375q-0.359375 -0.609375 -0.359375 -1.328125q0 -0.65625 0.296875 -1.21875q0.3125 -0.5625 0.828125 -0.9375q0.390625 -0.28125 1.0625 -0.484375q0.671875 -0.203125 1.4375 -0.203125q1.171875 0 2.046875 0.34375q0.875 0.328125 1.28125 0.90625q0.421875 0.5625 0.578125 1.515625l-1.625 0.21875q-0.109375 -0.75 -0.65625 -1.171875q-0.53125 -0.4375 -1.5 -0.4375q-1.15625 0 -1.640625 0.390625q-0.484375 0.375 -0.484375 0.875q0 0.328125 0.203125 0.59375q0.203125 0.265625 0.640625 0.4375q0.25 0.09375 1.46875 0.4375q1.765625 0.46875 2.46875 0.765625q0.703125 0.296875 1.09375 0.875q0.40625 0.578125 0.40625 1.4375q0 0.828125 -0.484375 1.578125q-0.484375 0.734375 -1.40625 1.140625q-0.921875 0.390625 -2.078125 0.390625q-1.921875 0 -2.9375 -0.796875q-1.0 -0.796875 -1.28125 -2.359375z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m302.60867 52.860893l7.165344 0l0 0.062992096l7.165344 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m302.60864 52.860893l7.1653748 0l0 0.062992096l1.1653442 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m310.93936 54.57562l4.5381165 -1.6517334l-4.5381165 -1.6517334z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m426.9797 52.860893l27.904388 0l0 0.062992096l27.906647 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m426.9797 52.860893l27.904388 0l0 0.062992096l21.906616 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m476.7907 54.57562l4.5381165 -1.6517334l-4.5381165 -1.6517334z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m592.8982 52.860893l6.6398315 0l0 0.062992096l6.6514893 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m592.8982 52.860893l6.6398315 0l0 0.062992096l0.6515503 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m600.1896 54.57562l4.538086 -1.6517334l-4.538086 -1.6517334z" fill-rule="evenodd"></path><path fill="#f3f3f3" d="m26.104986 22.986877l110.11024 0l0 59.74803l-110.11024 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m26.104986 22.986877l110.11024 0l0 59.74803l-110.11024 0z" fill-rule="nonzero"></path><path fill="#434343" d="m70.03193 55.015266l1.796875 0.453125q-0.5625 2.21875 -2.03125 3.390625q-1.46875 1.15625 -3.59375 1.15625q-2.203125 0 -3.5781212 -0.890625q-1.375 -0.90625 -2.09375 -2.59375q-0.71875 -1.703125 -0.71875 -3.65625q0 -2.125 0.796875 -3.703125q0.8125 -1.578125 2.3125 -2.390625q1.4999962 -0.828125 3.2968712 -0.828125q2.046875 0 3.4375 1.046875q1.390625 1.03125 1.9375 2.90625l-1.765625 0.421875q-0.46875 -1.484375 -1.375 -2.15625q-0.90625 -0.6875 -2.265625 -0.6875q-1.5625 0 -2.6249962 0.75q-1.046875 0.75 -1.484375 2.03125q-0.421875 1.265625 -0.421875 2.609375q0 1.734375 0.5 3.03125q0.515625 1.28125 1.578125 1.921875q1.0781212 0.640625 2.3124962 0.640625q1.515625 0 2.5625 -0.859375q1.046875 -0.875 1.421875 -2.59375zm2.9260712 -0.15625q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm15.672592 4.921875l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375zm16.016342 1.75l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m136.21523 52.860893l28.15747 0l0 0.062992096l28.157486 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m136.21523 52.860893l28.15747 0l0 0.062992096l22.157486 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m186.53018 54.57562l4.538101 -1.6517334l-4.538101 -1.6517334z" fill-rule="evenodd"></path><path fill="#f3f3f3" d="m26.104986 120.98688l110.11024 0l0 59.74803l-110.11024 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m26.104986 120.98688l110.11024 0l0 59.74803l-110.11024 0z" fill-rule="nonzero"></path><path fill="#434343" d="m50.508137 146.78088l0 -13.59375l6.03125 0q1.8125 0 2.75 0.359375q0.953125 0.359375 1.515625 1.296875q0.5625 0.921875 0.5625 2.046875q0 1.453125 -0.9375 2.453125q-0.921875 0.984375 -2.890625 1.25q0.71875 0.34375 1.09375 0.671875q0.78125 0.734375 1.484375 1.8125l2.375 3.703125l-2.265625 0l-1.796875 -2.828125q-0.796875 -1.21875 -1.3125 -1.875q-0.5 -0.65625 -0.90625 -0.90625q-0.40625 -0.265625 -0.8125 -0.359375q-0.3125 -0.078125 -1.015625 -0.078125l-2.078125 0l0 6.046875l-1.796875 0zm1.796875 -7.59375l3.859375 0q1.234375 0 1.921875 -0.25q0.703125 -0.265625 1.0625 -0.828125q0.375 -0.5625 0.375 -1.21875q0 -0.96875 -0.703125 -1.578125q-0.703125 -0.625 -2.21875 -0.625l-4.296875 0l0 4.5zm18.176067 4.421875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.2656212 -1.328125 -1.2656212 -3.734375q0 -2.484375 1.2656212 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.078842 5.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm10.613571 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.7351 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.4062576 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.6562576 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277054 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm15.500717 5.875l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375z" fill-rule="nonzero"></path><path fill="#434343" d="m70.03193 164.01526l1.796875 0.453125q-0.5625 2.21875 -2.03125 3.390625q-1.46875 1.15625 -3.59375 1.15625q-2.203125 0 -3.5781212 -0.890625q-1.375 -0.90625 -2.09375 -2.59375q-0.71875 -1.703125 -0.71875 -3.65625q0 -2.125 0.796875 -3.703125q0.8125 -1.578125 2.3125 -2.390625q1.4999962 -0.828125 3.2968712 -0.828125q2.046875 0 3.4375 1.046875q1.390625 1.03125 1.9375 2.90625l-1.765625 0.421875q-0.46875 -1.484375 -1.375 -2.15625q-0.90625 -0.6875 -2.265625 -0.6875q-1.5625 0 -2.6249962 0.75q-1.046875 0.75 -1.484375 2.03125q-0.421875 1.265625 -0.421875 2.609375q0 1.734375 0.5 3.03125q0.515625 1.28125 1.578125 1.921875q1.0781212 0.640625 2.3124962 0.640625q1.515625 0 2.5625 -0.859375q1.046875 -0.875 1.421875 -2.59375zm2.9260712 -0.15625q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm15.672592 4.921875l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375zm16.016342 1.75l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m136.21523 150.86089l28.15747 0l0 -98.01574l28.157486 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m136.21523 150.86089l28.15747 0l0 -98.01574l22.157486 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m186.53018 54.496876l4.538101 -1.6517296l-4.538101 -1.6517334z" fill-rule="evenodd"></path><path fill="#f3f3f3" d="m26.104986 190.98688l110.11024 0l0 59.74803l-110.11024 0z" fill-rule="nonzero"></path><path stroke="#b7b7b7" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m26.104986 190.98688l110.11024 0l0 59.74803l-110.11024 0z" fill-rule="nonzero"></path><path fill="#434343" d="m50.508137 216.78088l0 -13.59375l6.03125 0q1.8125 0 2.75 0.359375q0.953125 0.359375 1.515625 1.296875q0.5625 0.921875 0.5625 2.046875q0 1.453125 -0.9375 2.453125q-0.921875 0.984375 -2.890625 1.25q0.71875 0.34375 1.09375 0.671875q0.78125 0.734375 1.484375 1.8125l2.375 3.703125l-2.265625 0l-1.796875 -2.828125q-0.796875 -1.21875 -1.3125 -1.875q-0.5 -0.65625 -0.90625 -0.90625q-0.40625 -0.265625 -0.8125 -0.359375q-0.3125 -0.078125 -1.015625 -0.078125l-2.078125 0l0 6.046875l-1.796875 0zm1.796875 -7.59375l3.859375 0q1.234375 0 1.921875 -0.25q0.703125 -0.265625 1.0625 -0.828125q0.375 -0.5625 0.375 -1.21875q0 -0.96875 -0.703125 -1.578125q-0.703125 -0.625 -2.21875 -0.625l-4.296875 0l0 4.5zm18.176067 4.421875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.2656212 -1.328125 -1.2656212 -3.734375q0 -2.484375 1.2656212 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.078842 5.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm10.613571 -1.21875q-0.9375 0.796875 -1.796875 1.125q-0.859375 0.3125 -1.84375 0.3125q-1.609375 0 -2.484375 -0.78125q-0.875 -0.796875 -0.875 -2.03125q0 -0.734375 0.328125 -1.328125q0.328125 -0.59375 0.859375 -0.953125q0.53125 -0.359375 1.203125 -0.546875q0.5 -0.140625 1.484375 -0.25q2.03125 -0.25 2.984375 -0.578125q0 -0.34375 0 -0.4375q0 -1.015625 -0.46875 -1.4375q-0.640625 -0.5625 -1.90625 -0.5625q-1.171875 0 -1.734375 0.40625q-0.5625 0.40625 -0.828125 1.46875l-1.640625 -0.234375q0.234375 -1.046875 0.734375 -1.6875q0.515625 -0.640625 1.46875 -0.984375q0.96875 -0.359375 2.25 -0.359375q1.265625 0 2.046875 0.296875q0.78125 0.296875 1.15625 0.75q0.375 0.453125 0.515625 1.140625q0.09375 0.421875 0.09375 1.53125l0 2.234375q0 2.328125 0.09375 2.953125q0.109375 0.609375 0.4375 1.171875l-1.75 0q-0.265625 -0.515625 -0.328125 -1.21875zm-0.140625 -3.71875q-0.90625 0.359375 -2.734375 0.625q-1.03125 0.140625 -1.453125 0.328125q-0.421875 0.1875 -0.65625 0.546875q-0.234375 0.359375 -0.234375 0.796875q0 0.671875 0.5 1.125q0.515625 0.4375 1.484375 0.4375q0.96875 0 1.71875 -0.421875q0.75 -0.4375 1.109375 -1.15625q0.265625 -0.578125 0.265625 -1.671875l0 -0.609375zm7.7351 3.4375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.4062576 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.6562576 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm8.277054 -1.671875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm15.500717 5.875l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375z" fill-rule="nonzero"></path><path fill="#434343" d="m70.03193 234.01526l1.796875 0.453125q-0.5625 2.21875 -2.03125 3.390625q-1.46875 1.15625 -3.59375 1.15625q-2.203125 0 -3.5781212 -0.890625q-1.375 -0.90625 -2.09375 -2.59375q-0.71875 -1.703125 -0.71875 -3.65625q0 -2.125 0.796875 -3.703125q0.8125 -1.578125 2.3125 -2.390625q1.4999962 -0.828125 3.2968712 -0.828125q2.046875 0 3.4375 1.046875q1.390625 1.03125 1.9375 2.90625l-1.765625 0.421875q-0.46875 -1.484375 -1.375 -2.15625q-0.90625 -0.6875 -2.265625 -0.6875q-1.5625 0 -2.6249962 0.75q-1.046875 0.75 -1.484375 2.03125q-0.421875 1.265625 -0.421875 2.609375q0 1.734375 0.5 3.03125q0.515625 1.28125 1.578125 1.921875q1.0781212 0.640625 2.3124962 0.640625q1.515625 0 2.5625 -0.859375q1.046875 -0.875 1.421875 -2.59375zm2.9260712 -0.15625q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm15.672592 4.921875l0 -1.25q-0.9375 1.46875 -2.75 1.46875q-1.171875 0 -2.171875 -0.640625q-0.984375 -0.65625 -1.53125 -1.8125q-0.53125 -1.171875 -0.53125 -2.6875q0 -1.46875 0.484375 -2.671875q0.5 -1.203125 1.46875 -1.84375q0.984375 -0.640625 2.203125 -0.640625q0.890625 0 1.578125 0.375q0.703125 0.375 1.140625 0.984375l0 -4.875l1.65625 0l0 13.59375l-1.546875 0zm-5.28125 -4.921875q0 1.890625 0.796875 2.828125q0.8125 0.9375 1.890625 0.9375q1.09375 0 1.859375 -0.890625q0.765625 -0.890625 0.765625 -2.734375q0 -2.015625 -0.78125 -2.953125q-0.78125 -0.953125 -1.921875 -0.953125q-1.109375 0 -1.859375 0.90625q-0.75 0.90625 -0.75 2.859375zm16.016342 1.75l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m136.21523 220.86089l28.15747 0l0 -168.0l28.157486 0" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" d="m136.21523 220.86089l28.15747 0l0 -168.0l22.157486 0" fill-rule="evenodd"></path><path fill="#000000" stroke="#000000" stroke-width="1.0" stroke-linecap="butt" d="m186.53018 54.512627l4.538101 -1.6517334l-4.538101 -1.6517334z" fill-rule="evenodd"></path><path fill="#000000" fill-opacity="0.0" d="m5.1522307 4.632546l165.85826 0l0 283.52756l-165.85826 0z" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" stroke-dasharray="4.0,3.0" d="m5.1522307 4.632546l165.85826 0l0 283.52756l-165.85826 0z" fill-rule="nonzero"></path><path fill="#ff0000" d="m24.73604 275.0801l0 -13.59375l5.125 0q1.359375 0 2.078125 0.125q0.9999981 0.171875 1.6718731 0.640625q0.671875 0.46875 1.078125 1.3125q0.421875 0.84375 0.421875 1.84375q0 1.734375 -1.109375 2.9375q-1.09375 1.203125 -3.984373 1.203125l-3.484375 0l0 5.53125l-1.796875 0zm1.796875 -7.140625l3.515625 0q1.75 0 2.468748 -0.640625q0.734375 -0.65625 0.734375 -1.828125q0 -0.859375 -0.4375 -1.46875q-0.421875 -0.609375 -1.1249981 -0.796875q-0.453125 -0.125 -1.671875 -0.125l-3.484375 0l0 4.859375zm10.412321 7.140625l0 -9.859375l1.5 0l0 1.5q0.578125 -1.046875 1.0625 -1.375q0.484375 -0.34375 1.078125 -0.34375q0.84375 0 1.71875 0.546875l-0.578125 1.546875q-0.609375 -0.359375 -1.234375 -0.359375q-0.546875 0 -0.984375 0.328125q-0.421875 0.328125 -0.609375 0.90625q-0.28125 0.890625 -0.28125 1.953125l0 5.15625l-1.671875 0zm5.603302 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.281967 -6.734375l0 -1.9375l1.65625 0l0 1.9375l-1.65625 0zm-2.125 15.484375l0.3125 -1.421875q0.5 0.125 0.796875 0.125q0.515625 0 0.765625 -0.34375q0.25 -0.328125 0.25 -1.6875l0 -10.359375l1.65625 0l0 10.390625q0 1.828125 -0.46875 2.546875q-0.59375 0.921875 -2.0 0.921875q-0.671875 0 -1.3125 -0.171875zm13.019821 -7.0l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm15.547592 2.265625l1.640625 0.21875q-0.265625 1.6875 -1.375 2.65625q-1.109375 0.953125 -2.734375 0.953125q-2.015625 0 -3.25 -1.3125q-1.21875 -1.328125 -1.21875 -3.796875q0 -1.59375 0.515625 -2.78125q0.53125 -1.203125 1.609375 -1.796875q1.09375 -0.609375 2.359375 -0.609375q1.609375 0 2.625 0.8125q1.015625 0.8125 1.3125 2.3125l-1.625 0.25q-0.234375 -1.0 -0.828125 -1.5q-0.59375 -0.5 -1.421875 -0.5q-1.265625 0 -2.0625 0.90625q-0.78125 0.90625 -0.78125 2.859375q0 1.984375 0.765625 2.890625q0.765625 0.890625 1.984375 0.890625q0.984375 0 1.640625 -0.59375q0.65625 -0.609375 0.84375 -1.859375zm6.546875 2.109375l0.234375 1.484375q-0.703125 0.140625 -1.265625 0.140625q-0.90625 0 -1.40625 -0.28125q-0.5 -0.296875 -0.703125 -0.75q-0.203125 -0.46875 -0.203125 -1.984375l0 -5.65625l-1.234375 0l0 -1.3125l1.234375 0l0 -2.4375l1.65625 -1.0l0 3.4375l1.6875 0l0 1.3125l-1.6875 0l0 5.75q0 0.71875 0.078125 0.921875q0.09375 0.203125 0.296875 0.328125q0.203125 0.125 0.578125 0.125q0.265625 0 0.734375 -0.078125zm6.9291077 1.5l0 -13.59375l5.125 0q1.359375 0 2.078125 0.125q1.0 0.171875 1.671875 0.640625q0.671875 0.46875 1.078125 1.3125q0.421875 0.84375 0.421875 1.84375q0 1.734375 -1.109375 2.9375q-1.09375 1.203125 -3.984375 1.203125l-3.484375 0l0 5.53125l-1.796875 0zm1.796875 -7.140625l3.515625 0q1.75 0 2.46875 -0.640625q0.734375 -0.65625 0.734375 -1.828125q0 -0.859375 -0.4375 -1.46875q-0.421875 -0.609375 -1.125 -0.796875q-0.453125 -0.125 -1.671875 -0.125l-3.484375 0l0 4.859375zm10.443573 -4.546875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.129196 3.78125l0 -13.640625l1.53125 0l0 1.28125q0.53125 -0.75 1.203125 -1.125q0.6875 -0.375 1.640625 -0.375q1.265625 0 2.234375 0.65625q0.96875 0.640625 1.453125 1.828125q0.5 1.1875 0.5 2.59375q0 1.515625 -0.546875 2.734375q-0.546875 1.203125 -1.578125 1.84375q-1.03125 0.640625 -2.171875 0.640625q-0.84375 0 -1.515625 -0.34375q-0.65625 -0.359375 -1.078125 -0.890625l0 4.796875l-1.671875 0zm1.515625 -8.65625q0 1.90625 0.765625 2.8125q0.78125 0.90625 1.875 0.90625q1.109375 0 1.890625 -0.9375q0.796875 -0.9375 0.796875 -2.921875q0 -1.875 -0.78125 -2.8125q-0.765625 -0.9375 -1.84375 -0.9375q-1.0625 0 -1.890625 1.0q-0.8125 1.0 -0.8125 2.890625zm15.610092 1.703125l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.078842 5.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm4.191696 -11.6875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.129196 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm17.125732 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875z" fill-rule="nonzero"></path><path fill="#000000" fill-opacity="0.0" d="m464.70865 4.632546l270.23624 0l0 129.10236l-270.23624 0z" fill-rule="nonzero"></path><path stroke="#000000" stroke-width="1.0" stroke-linejoin="round" stroke-linecap="butt" stroke-dasharray="4.0,3.0" d="m464.70865 4.632546l270.23624 0l0 129.10236l-270.23624 0z" fill-rule="nonzero"></path><path fill="#ff0000" d="m536.47687 120.65491l0 -13.59375l4.6875 0q1.578125 0 2.421875 0.1875q1.15625 0.265625 1.984375 0.96875q1.078125 0.921875 1.609375 2.34375q0.53125 1.40625 0.53125 3.21875q0 1.546875 -0.359375 2.75q-0.359375 1.1875 -0.921875 1.984375q-0.5625 0.78125 -1.234375 1.234375q-0.671875 0.4375 -1.625 0.671875q-0.953125 0.234375 -2.1875 0.234375l-4.90625 0zm1.796875 -1.609375l2.90625 0q1.34375 0 2.109375 -0.25q0.765625 -0.25 1.21875 -0.703125q0.640625 -0.640625 1.0 -1.71875q0.359375 -1.078125 0.359375 -2.625q0 -2.125 -0.703125 -3.265625q-0.703125 -1.15625 -1.703125 -1.546875q-0.71875 -0.28125 -2.328125 -0.28125l-2.859375 0l0 10.390625zm18.207336 -1.5625l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.110107 9.65625l0 -13.640625l1.53125 0l0 1.28125q0.53125 -0.75 1.203125 -1.125q0.6875 -0.375 1.640625 -0.375q1.265625 0 2.234375 0.65625q0.96875 0.640625 1.453125 1.828125q0.5 1.1875 0.5 2.59375q0 1.515625 -0.546875 2.734375q-0.546875 1.203125 -1.578125 1.84375q-1.03125 0.640625 -2.171875 0.640625q-0.84375 0 -1.515625 -0.34375q-0.65625 -0.359375 -1.078125 -0.890625l0 4.796875l-1.671875 0zm1.515625 -8.65625q0 1.90625 0.765625 2.8125q0.78125 0.90625 1.875 0.90625q1.109375 0 1.890625 -0.9375q0.796875 -0.9375 0.796875 -2.921875q0 -1.875 -0.78125 -2.8125q-0.765625 -0.9375 -1.84375 -0.9375q-1.0625 0 -1.890625 1.0q-0.8125 1.0 -0.8125 2.890625zm8.828857 4.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm3.5510254 -4.921875q0 -2.734375 1.53125 -4.0625q1.265625 -1.09375 3.09375 -1.09375q2.03125 0 3.3125 1.34375q1.296875 1.328125 1.296875 3.671875q0 1.90625 -0.578125 3.0q-0.5625 1.078125 -1.65625 1.6875q-1.078125 0.59375 -2.375 0.59375q-2.0625 0 -3.34375 -1.328125q-1.28125 -1.328125 -1.28125 -3.8125zm1.71875 0q0 1.890625 0.828125 2.828125q0.828125 0.9375 2.078125 0.9375q1.25 0 2.0625 -0.9375q0.828125 -0.953125 0.828125 -2.890625q0 -1.828125 -0.828125 -2.765625q-0.828125 -0.9375 -2.0625 -0.9375q-1.25 0 -2.078125 0.9375q-0.828125 0.9375 -0.828125 2.828125zm9.203857 8.71875l-0.171875 -1.5625q0.546875 0.140625 0.953125 0.140625q0.546875 0 0.875 -0.1875q0.34375 -0.1875 0.5625 -0.515625q0.15625 -0.25 0.5 -1.25q0.046875 -0.140625 0.15625 -0.40625l-3.734375 -9.875l1.796875 0l2.046875 5.71875q0.40625 1.078125 0.71875 2.28125q0.28125 -1.15625 0.6875 -2.25l2.09375 -5.75l1.671875 0l-3.75 10.03125q-0.59375 1.625 -0.9375 2.234375q-0.4375 0.828125 -1.015625 1.203125q-0.578125 0.390625 -1.375 0.390625q-0.484375 0 -1.078125 -0.203125zm14.808289 -3.796875l0 -13.59375l5.125 0q1.359375 0 2.078125 0.125q1.0 0.171875 1.671875 0.640625q0.671875 0.46875 1.078125 1.3125q0.421875 0.84375 0.421875 1.84375q0 1.734375 -1.109375 2.9375q-1.09375 1.203125 -3.984375 1.203125l-3.484375 0l0 5.53125l-1.796875 0zm1.796875 -7.140625l3.515625 0q1.75 0 2.46875 -0.640625q0.734375 -0.65625 0.734375 -1.828125q0 -0.859375 -0.4375 -1.46875q-0.421875 -0.609375 -1.125 -0.796875q-0.453125 -0.125 -1.671875 -0.125l-3.484375 0l0 4.859375zm10.4436035 -4.546875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.1292114 3.78125l0 -13.640625l1.53125 0l0 1.28125q0.53125 -0.75 1.203125 -1.125q0.6875 -0.375 1.640625 -0.375q1.265625 0 2.234375 0.65625q0.96875 0.640625 1.453125 1.828125q0.5 1.1875 0.5 2.59375q0 1.515625 -0.546875 2.734375q-0.546875 1.203125 -1.578125 1.84375q-1.03125 0.640625 -2.171875 0.640625q-0.84375 0 -1.515625 -0.34375q-0.65625 -0.359375 -1.078125 -0.890625l0 4.796875l-1.671875 0zm1.515625 -8.65625q0 1.90625 0.765625 2.8125q0.78125 0.90625 1.875 0.90625q1.109375 0 1.890625 -0.9375q0.796875 -0.9375 0.796875 -2.921875q0 -1.875 -0.78125 -2.8125q-0.765625 -0.9375 -1.84375 -0.9375q-1.0625 0 -1.890625 1.0q-0.8125 1.0 -0.8125 2.890625zm15.610046 1.703125l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875zm9.078857 5.875l0 -13.59375l1.671875 0l0 13.59375l-1.671875 0zm4.1917114 -11.6875l0 -1.90625l1.671875 0l0 1.90625l-1.671875 0zm0 11.6875l0 -9.859375l1.671875 0l0 9.859375l-1.671875 0zm4.1292114 0l0 -9.859375l1.5 0l0 1.40625q1.09375 -1.625 3.140625 -1.625q0.890625 0 1.640625 0.328125q0.75 0.3125 1.109375 0.84375q0.375 0.515625 0.53125 1.21875q0.09375 0.46875 0.09375 1.625l0 6.0625l-1.671875 0l0 -6.0q0 -1.015625 -0.203125 -1.515625q-0.1875 -0.515625 -0.6875 -0.8125q-0.5 -0.296875 -1.171875 -0.296875q-1.0625 0 -1.84375 0.671875q-0.765625 0.671875 -0.765625 2.578125l0 5.375l-1.671875 0zm17.125671 -3.171875l1.71875 0.21875q-0.40625 1.5 -1.515625 2.34375q-1.09375 0.828125 -2.8125 0.828125q-2.15625 0 -3.421875 -1.328125q-1.265625 -1.328125 -1.265625 -3.734375q0 -2.484375 1.265625 -3.859375q1.28125 -1.375 3.328125 -1.375q1.984375 0 3.234375 1.34375q1.25 1.34375 1.25 3.796875q0 0.140625 -0.015625 0.4375l-7.34375 0q0.09375 1.625 0.921875 2.484375q0.828125 0.859375 2.0625 0.859375q0.90625 0 1.546875 -0.46875q0.65625 -0.484375 1.046875 -1.546875zm-5.484375 -2.703125l5.5 0q-0.109375 -1.234375 -0.625 -1.859375q-0.796875 -0.96875 -2.078125 -0.96875q-1.140625 0 -1.9375 0.78125q-0.78125 0.765625 -0.859375 2.046875z" fill-rule="nonzero"></path></g></svg>
-
diff --git a/doc/ci/img/view_on_env_blob.png b/doc/ci/img/view_on_env_blob.png
index dd9ca40280a..acc457fbb38 100644
--- a/doc/ci/img/view_on_env_blob.png
+++ b/doc/ci/img/view_on_env_blob.png
Binary files differ
diff --git a/doc/ci/img/view_on_mr_widget.png b/doc/ci/img/view_on_mr_widget.png
new file mode 100644
index 00000000000..04f4b58df62
--- /dev/null
+++ b/doc/ci/img/view_on_mr_widget.png
Binary files differ
diff --git a/doc/ci/interactive_web_terminal/index.md b/doc/ci/interactive_web_terminal/index.md
index 8ce4fe55cec..2c799e83a5f 100644
--- a/doc/ci/interactive_web_terminal/index.md
+++ b/doc/ci/interactive_web_terminal/index.md
@@ -1,15 +1,14 @@
-# Getting started with interactive web terminals
+# Getting started with interactive web terminals **[CORE ONLY]**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/50144) in GitLab 11.3.
Interactive web terminals give the user access to a terminal in GitLab for
-running one-of commands for their CI pipeline.
+running one-off commands for their CI pipeline.
NOTE: **Note:**
-This is not available for the shared Runners on GitLab.com.
-To make use of this feature, you need to provide your
-[own Runner](https://docs.gitlab.com/runner/install/) and properly
-[configure it](#configuration).
+GitLab.com does not support interactive web terminal at the moment. Please
+follow [this issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/52611) for
+progress.
## Configuration
@@ -17,7 +16,7 @@ Two things need to be configured for the interactive web terminal to work:
- The Runner needs to have [`[session_server]` configured
properly][session-server]
-- Web terminals need to be
+- If you are using a reverse proxy with your GitLab instance, web terminals need to be
[enabled](../../administration/integration/terminal.md#enabling-and-disabling-terminal-support)
## Debugging a running job
@@ -25,6 +24,12 @@ Two things need to be configured for the interactive web terminal to work:
NOTE: **Note:** Not all executors are
[supported](https://docs.gitlab.com/runner/executors/#compatibility-chart).
+NOTE: **Note:** The `docker` executor does not keep running
+after the build script is finished. At that point, the terminal will automatically
+disconnect and will not wait for the user to finish. Please follow [this
+issue](https://gitlab.com/gitlab-org/gitlab-runner/issues/3605) for updates on
+improving this behavior.
+
Sometimes, when a job is running, things don't go as you would expect, and it
would be helpful if one can have a shell to aid debugging. When a job is
running, on the right panel you can see a button `debug` that will open the terminal
diff --git a/doc/ci/junit_test_reports.md b/doc/ci/junit_test_reports.md
index cf22450914c..91a0ae327bf 100644
--- a/doc/ci/junit_test_reports.md
+++ b/doc/ci/junit_test_reports.md
@@ -61,7 +61,7 @@ For a list of supported languages on JUnit tests, check the
[Wikipedia article](https://en.wikipedia.org/wiki/JUnit#Ports).
To enable the JUnit reports in merge requests, you need to add
-[`artifacts:reports:junit`](yaml/README.md#artifacts-reports-junit)
+[`artifacts:reports:junit`](yaml/README.md#artifactsreportsjunit)
in `.gitlab-ci.yml`, and specify the path(s) of the generated test reports.
In the following examples, the job in the `test` stage runs and GitLab
@@ -69,6 +69,10 @@ collects the JUnit test report from each job. After each job is executed, the
XML reports are stored in GitLab as artifacts and their results are shown in the
merge request widget.
+NOTE: **Note:**
+If you also want the ability to browse JUnit output files, include the
+[`artifacts:paths`](yaml/README.md#artifactspaths) keyword.
+
### Ruby example
Use the following job in `.gitlab-ci.yml`:
@@ -140,6 +144,27 @@ java:
- target/failsafe-reports/TEST-*.xml
```
+### C/C++ example
+
+There are a few tools that can produce JUnit reports in C/C++.
+
+#### GoogleTest
+
+In the following example, `gtest` is used to generate the test reports.
+If there are multiple gtest executables created for different architectures (`x86`, `x64` or `arm`),
+you will be required to run each test providing a unique filename. The results
+will then be aggregated together.
+
+```yaml
+cpp:
+ stage: test
+ script:
+ - gtest.exe --gtest_output="xml:report.xml"
+ artifacts:
+ reports:
+ junit: report.xml
+```
+
## Limitations
Currently, the following tools might not work because their XML formats are unsupported in GitLab.
diff --git a/doc/ci/pipelines.md b/doc/ci/pipelines.md
index ea47d676edb..f8cf9de9aff 100644
--- a/doc/ci/pipelines.md
+++ b/doc/ci/pipelines.md
@@ -27,7 +27,7 @@ GitLab capitalizes the stages' names when shown in the [pipeline graphs](#pipeli
There are three types of pipelines that often use the single shorthand of "pipeline". People often talk about them as if each one is "the" pipeline, but really, they're just pieces of a single, comprehensive pipeline.
-![Types of Pipelines](img/types-of-pipelines.svg)
+![Types of Pipelines](img/types-of-pipelines.png)
1. **CI Pipeline**: Build and test stages defined in `.gitlab-ci.yml`.
1. **Deploy Pipeline**: Deploy stage(s) defined in `.gitlab-ci.yml` The flow of deploying code to servers through various stages: e.g. development to staging to production.
@@ -43,7 +43,7 @@ Pipelines accommodate several development workflows:
Example continuous delivery flow:
-![CD Flow](img/pipelines-goal.svg)
+![CD Flow](img/pipelines-goal.png)
## Jobs
@@ -193,6 +193,18 @@ stage has a job with a manual action.
![Pipelines example](img/pipelines.png)
+### Delay a particular job in the pipeline graph
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21767) in GitLab 11.4.
+
+When you do not want to run a job immediately, you can [delay the job to run after a certain period](yaml/README.md#when-delayed).
+This is especially useful for timed incremental rollout that new code is rolled out gradually.
+For example, if you start rolling out new code and users do not experience trouble, GitLab automatically completes the deployment from 0% to 100%.
+Alternatively, if you start rolling out and you noticed that a few users experience trouble with the version,
+you can stop the timed incremental rollout by canceling the pipeline, and [rolling](environments.md#rolling-back-changes) it back to the stable version.
+
+![Pipelines example](img/pipeline_incremental_rollout.png)
+
### Ordering of jobs in pipeline graphs
**Regular pipeline graph**
@@ -211,6 +223,7 @@ by name. The order of severity is:
- pending
- running
- manual
+- scheduled
- canceled
- success
- skipped
@@ -281,7 +294,7 @@ runners will not use regular runners, they must be tagged accordingly.
[jobs]: #jobs
[jobs-yaml]: yaml/README.md#jobs
-[manual]: yaml/README.md#manual
+[manual]: yaml/README.md#whenmanual
[env-manual]: environments.md#manually-deploying-to-environments
[stages]: yaml/README.md#stages
[runners]: runners/README.html
diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md
index 636117536a2..bdc593493ea 100644
--- a/doc/ci/quick_start/README.md
+++ b/doc/ci/quick_start/README.md
@@ -168,7 +168,7 @@ can be found at <https://docs.gitlab.com/runner/>.
In order to have a functional Runner you need to follow two steps:
1. [Install it][runner-install]
-2. [Configure it](../runners/README.md#registering-a-specific-runner)
+1. [Configure it](../runners/README.md#registering-a-specific-runner)
Follow the links above to set up your own Runner or use a Shared Runner as
described in the next section.
diff --git a/doc/ci/review_apps/img/continuous-delivery-review-apps.svg b/doc/ci/review_apps/img/continuous-delivery-review-apps.svg
new file mode 100644
index 00000000000..90ac763a01e
--- /dev/null
+++ b/doc/ci/review_apps/img/continuous-delivery-review-apps.svg
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="1170px" height="638px" viewBox="0 0 1170 638" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <!-- Generator: Sketch 41 (35326) - http://www.bohemiancoding.com/sketch -->
+ <title>review-apps-CD-outlined</title>
+ <desc>Created with Sketch.</desc>
+ <defs></defs>
+ <g id="Page-2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+ <g id="review-apps-CD-outlined">
+ <g id="Group-4-Copy" transform="translate(22.000000, 43.000000)">
+ <polygon id="Line-Copy-25" fill="#E0513E" points="163.545966 259 858.690432 259 858.690432 255 163.545966 255"></polygon>
+ <path d="M870.470919,266.702602 C875.287562,266.702602 879.19137,262.80085 879.19137,257.988848 C879.19137,253.176845 875.287562,249.275093 870.470919,249.275093 C865.654276,249.275093 861.750469,253.176845 861.750469,257.988848 C861.750469,262.80085 865.654276,266.702602 870.470919,266.702602 Z M870.470919,270.702602 C863.445609,270.702602 857.750469,265.01046 857.750469,257.988848 C857.750469,250.967235 863.445609,245.275093 870.470919,245.275093 C877.49623,245.275093 883.19137,250.967235 883.19137,257.988848 C883.19137,265.01046 877.49623,270.702602 870.470919,270.702602 Z" id="Oval-Copy-20" fill="#E04733"></path>
+ <path d="M991.315197,145.921933 C996.13184,145.921933 1000.03565,142.020181 1000.03565,137.208178 C1000.03565,132.396176 996.13184,128.494424 991.315197,128.494424 C986.498554,128.494424 982.594747,132.396176 982.594747,137.208178 C982.594747,142.020181 986.498554,145.921933 991.315197,145.921933 Z M991.315197,149.921933 C984.289886,149.921933 978.594747,144.229791 978.594747,137.208178 C978.594747,130.186566 984.289886,124.494424 991.315197,124.494424 C998.340508,124.494424 1004.03565,130.186566 1004.03565,137.208178 C1004.03565,144.229791 998.340508,149.921933 991.315197,149.921933 Z" id="Oval-Copy-22" fill="#E04733"></path>
+ <g id="Group-7" transform="translate(0.000000, 236.799257)" fill="#E04733">
+ <path d="M151.765478,29.9033457 C156.582121,29.9033457 160.485929,26.0015933 160.485929,21.1895911 C160.485929,16.3775889 156.582121,12.4758364 151.765478,12.4758364 C146.948835,12.4758364 143.045028,16.3775889 143.045028,21.1895911 C143.045028,26.0015933 146.948835,29.9033457 151.765478,29.9033457 Z M151.765478,33.9033457 C144.740168,33.9033457 139.045028,28.2112039 139.045028,21.1895911 C139.045028,14.1679783 144.740168,8.47583643 151.765478,8.47583643 C158.790789,8.47583643 164.485929,14.1679783 164.485929,21.1895911 C164.485929,28.2112039 158.790789,33.9033457 151.765478,33.9033457 Z" id="Oval-Copy-10"></path>
+ <path d="M0.187705647,10.1392011 L3.30410548,10.1392011 L7.34270526,21.3328005 L8.86910518,25.5940003 L8.99630517,25.5940003 L10.4591051,21.3328005 L14.4659049,10.1392011 L17.5823047,10.1392011 L17.5823047,31 L15.0701048,31 L15.0701048,19.5202006 C15.0701048,18.587396 15.1072045,17.5592063 15.1814048,16.4356008 C15.2556052,15.3119952 15.3351044,14.2838056 15.4199048,13.351001 L15.2927048,13.351001 L13.6073049,17.9938007 L9.60050514,28.9012001 L8.10590522,28.9012001 L4.06730544,17.9938007 L2.41370553,13.351001 L2.28650553,13.351001 C2.35010585,14.2838056 2.4243051,15.3119952 2.50910552,16.4356008 C2.59390594,17.5592063 2.63630552,18.587396 2.63630552,19.5202006 L2.63630552,31 L0.187705647,31 L0.187705647,10.1392011 Z M32.1785039,22.5094005 L31.192704,19.3294006 C30.8111021,18.1633949 30.4507057,17.0027065 30.111504,15.8473008 C29.7723024,14.6918951 29.4331058,13.510007 29.0939041,12.301601 L28.9667041,12.301601 C28.6487025,13.510007 28.3201058,14.6918951 27.9809041,15.8473008 C27.6417025,17.0027065 27.2813061,18.1633949 26.8997042,19.3294006 L25.9139043,22.5094005 L32.1785039,22.5094005 Z M32.8463039,24.6400003 L25.2461043,24.6400003 L23.2427044,31 L20.5397045,31 L27.5993042,10.1392011 L30.588504,10.1392011 L37.6481036,31 L34.8179038,31 L32.8463039,24.6400003 Z M40.6691035,26.4526002 C41.4111071,27.2370041 42.2855983,27.8676978 43.2926033,28.3447001 C44.2996083,28.8217025 45.3436978,29.0602001 46.4249032,29.0602001 C47.80291,29.0602001 48.8734992,28.7475032 49.636703,28.1221002 C50.3999068,27.4966971 50.7815029,26.6752053 50.7815029,25.6576003 C50.7815029,25.1275977 50.6914038,24.6771022 50.5112029,24.3061004 C50.331002,23.9350985 50.0872045,23.6171017 49.779803,23.3521004 C49.4724014,23.0870991 49.1067051,22.8486015 48.682703,22.6366005 C48.2587009,22.4245994 47.8029055,22.2020016 47.3153031,21.9688005 L44.3261033,20.6650006 C43.8385009,20.4529995 43.3403059,20.1986021 42.8315033,19.9018006 C42.3227008,19.6049991 41.8669054,19.2446028 41.4641034,18.8206007 C41.0613014,18.3965986 40.7327047,17.8931036 40.4783035,17.3101007 C40.2239022,16.7270979 40.0967035,16.0540046 40.0967035,15.2908008 C40.0967035,14.506397 40.2610018,13.7750043 40.5896035,13.096601 C40.9182051,12.4181976 41.3740005,11.8299035 41.9570034,11.3317011 C42.5400063,10.8334986 43.2289993,10.4466025 44.0240033,10.1710011 C44.8190072,9.89539976 45.6934984,9.75760115 46.6475031,9.75760115 C47.8983093,9.75760115 49.0536977,9.99609875 50.113703,10.4731011 C51.1737082,10.9501035 52.0746991,11.5701972 52.8167028,12.333401 L51.3857029,14.0506009 C50.7496997,13.4357979 50.0448068,12.9535027 49.271003,12.603701 C48.4971992,12.2538993 47.622708,12.079001 46.6475031,12.079001 C45.4814974,12.079001 44.5434068,12.3492983 43.8332033,12.889901 C43.1229998,13.4305037 42.7679033,14.1777961 42.7679033,15.1318009 C42.7679033,15.6406034 42.8686023,16.0698991 43.0700033,16.4197008 C43.2714043,16.7695025 43.5417016,17.0768994 43.8809033,17.3419007 C44.220105,17.606902 44.5911012,17.8400997 44.9939032,18.0415007 C45.3967052,18.2429017 45.8101011,18.4283998 46.2341032,18.5980007 L49.191503,19.8700006 C49.7851059,20.1244019 50.3469003,20.4158989 50.8769029,20.7445006 C51.4069055,21.0731022 51.8627009,21.4546983 52.2443028,21.8893005 C52.6259047,22.3239026 52.9280017,22.8326975 53.1506028,23.4157004 C53.3732039,23.9987033 53.4845028,24.6717965 53.4845028,25.4350003 C53.4845028,26.2618044 53.3202044,27.0355966 52.9916028,27.7564002 C52.6630012,28.4772037 52.1913059,29.1078974 51.5765029,29.6485001 C50.9616998,30.1891027 50.2197073,30.6130985 49.350503,30.9205 C48.4812987,31.2279015 47.4955086,31.3816 46.3931032,31.3816 C44.9302959,31.3816 43.5735096,31.1060028 42.3227034,30.5548 C41.0718972,30.0035973 39.9907081,29.2510049 39.0791035,28.2970001 L40.6691035,26.4526002 Z M61.9115023,12.365201 L55.6151027,12.365201 L55.6151027,10.1392011 L70.8791018,10.1392011 L70.8791018,12.365201 L64.5827022,12.365201 L64.5827022,31 L61.9115023,31 L61.9115023,12.365201 Z M74.6315016,10.1392011 L86.651901,10.1392011 L86.651901,12.365201 L77.2709015,12.365201 L77.2709015,18.9160007 L85.1891011,18.9160007 L85.1891011,21.1738005 L77.2709015,21.1738005 L77.2709015,28.7422001 L86.969901,28.7422001 L86.969901,31 L74.6315016,31 L74.6315016,10.1392011 Z M94.0295006,20.0290006 L97.5275004,20.0290006 C99.1599085,20.0290006 100.410696,19.6951039 101.2799,19.0273006 C102.149104,18.3594973 102.5837,17.3472075 102.5837,15.9904008 C102.5837,14.612394 102.149104,13.6478037 101.2799,13.096601 C100.410696,12.5453982 99.1599085,12.269801 97.5275004,12.269801 L94.0295006,12.269801 L94.0295006,20.0290006 Z M102.8381,31 L97.8137004,22.1914005 L94.0295006,22.1914005 L94.0295006,31 L91.3901007,31 L91.3901007,10.1392011 L97.9091004,10.1392011 C98.9691056,10.1392011 99.9495958,10.2399001 100.8506,10.4413011 C101.751605,10.6427021 102.525397,10.9765987 103.172,11.4430011 C103.818603,11.9094034 104.322098,12.5135973 104.6825,13.255601 C105.042902,13.9976046 105.2231,14.9091955 105.2231,15.9904008 C105.2231,17.6228089 104.799104,18.9265958 103.9511,19.9018006 C103.103096,20.8770054 101.968907,21.5447987 100.5485,21.9052005 L105.8273,31 L102.8381,31 Z" id="MASTER"></path>
+ </g>
+ <path d="M829.454852,142.471188 C830.196855,143.255591 831.071347,143.886285 832.078351,144.363288 C833.085356,144.84029 834.129446,145.078787 835.210651,145.078787 C836.588658,145.078787 837.659247,144.766091 838.422451,144.140688 C839.185655,143.515284 839.567251,142.693793 839.567251,141.676188 C839.567251,141.146185 839.477152,140.69569 839.296951,140.324688 C839.11675,139.953686 838.872953,139.635689 838.565551,139.370688 C838.25815,139.105686 837.892453,138.867189 837.468451,138.655188 C837.044449,138.443187 836.588654,138.220589 836.101051,137.987388 L833.111851,136.683588 C832.624249,136.471587 832.126054,136.217189 831.617252,135.920388 C831.108449,135.623586 830.652654,135.26319 830.249852,134.839188 C829.84705,134.415186 829.518453,133.911691 829.264052,133.328688 C829.00965,132.745685 828.882452,132.072592 828.882452,131.309388 C828.882452,130.524984 829.04675,129.793592 829.375352,129.115188 C829.703953,128.436785 830.159749,127.848491 830.742752,127.350288 C831.325754,126.852086 832.014748,126.46519 832.809751,126.189588 C833.604755,125.913987 834.479247,125.776189 835.433251,125.776189 C836.684057,125.776189 837.839446,126.014686 838.899451,126.491688 C839.959456,126.968691 840.860447,127.588785 841.602451,128.351988 L840.171451,130.069188 C839.535448,129.454385 838.830555,128.97209 838.056751,128.622288 C837.282947,128.272487 836.408456,128.097588 835.433251,128.097588 C834.267246,128.097588 833.329155,128.367886 832.618951,128.908488 C831.908748,129.449091 831.553652,130.196383 831.553652,131.150388 C831.553652,131.659191 831.654351,132.088486 831.855752,132.438288 C832.057152,132.78809 832.32745,133.095487 832.666651,133.360488 C833.005853,133.625489 833.376849,133.858687 833.779651,134.060088 C834.182453,134.261489 834.595849,134.446987 835.019851,134.616588 L837.977251,135.888588 C838.570854,136.142989 839.132648,136.434486 839.662651,136.763088 C840.192654,137.09169 840.648449,137.473286 841.030051,137.907888 C841.411653,138.34249 841.71375,138.851285 841.936351,139.434288 C842.158952,140.017291 842.270251,140.690384 842.270251,141.453588 C842.270251,142.280392 842.105953,143.054184 841.777351,143.774988 C841.448749,144.495791 840.977054,145.126485 840.362251,145.667087 C839.747448,146.20769 839.005455,146.631686 838.136251,146.939087 C837.267047,147.246489 836.281257,147.400187 835.178851,147.400187 C833.716044,147.400187 832.359258,147.12459 831.108452,146.573387 C829.857645,146.022185 828.776456,145.269592 827.864852,144.315588 L829.454852,142.471188 Z M850.69725,128.383788 L844.400851,128.383788 L844.400851,126.157788 L859.66485,126.157788 L859.66485,128.383788 L853.36845,128.383788 L853.36845,147.018587 L850.69725,147.018587 L850.69725,128.383788 Z M872.289449,138.527988 L871.303649,135.347988 C870.922047,134.181982 870.561651,133.021294 870.222449,131.865888 C869.883248,130.710482 869.544051,129.528594 869.204849,128.320188 L869.077649,128.320188 C868.759648,129.528594 868.431051,130.710482 868.09185,131.865888 C867.752648,133.021294 867.392251,134.181982 867.01065,135.347988 L866.02485,138.527988 L872.289449,138.527988 Z M872.957249,140.658588 L865.35705,140.658588 L863.35365,147.018587 L860.65065,147.018587 L867.71025,126.157788 L870.699449,126.157788 L877.759049,147.018587 L874.928849,147.018587 L872.957249,140.658588 Z M879.508049,136.588188 C879.508049,134.91338 879.746547,133.408195 880.223549,132.072588 C880.700551,130.736982 881.368345,129.602793 882.226949,128.669988 C883.085553,127.737184 884.097843,127.021691 885.263849,126.523488 C886.429854,126.025286 887.712441,125.776189 889.111648,125.776189 C890.553256,125.776189 891.756343,126.046486 892.720948,126.587088 C893.685553,127.127691 894.475245,127.715985 895.090048,128.351988 L893.595448,130.037388 C893.065446,129.486186 892.455952,129.02509 891.766948,128.654088 C891.077945,128.283087 890.203454,128.097588 889.143448,128.097588 C888.083443,128.097588 887.129453,128.293686 886.281449,128.685888 C885.433444,129.07809 884.712652,129.639885 884.119049,130.371288 C883.525446,131.102692 883.06435,131.987783 882.735749,133.026588 C882.407147,134.065393 882.242849,135.231382 882.242849,136.524588 C882.242849,137.838994 882.396547,139.020883 882.703949,140.070288 C883.01135,141.119693 883.456546,142.015384 884.039549,142.757388 C884.622552,143.499391 885.343344,144.071786 886.201949,144.474587 C887.060553,144.877389 888.051643,145.078787 889.175248,145.078787 C889.917252,145.078787 890.622145,144.967489 891.289948,144.744887 C891.957752,144.522286 892.503646,144.220189 892.927648,143.838588 L892.927648,138.400788 L888.507448,138.400788 L888.507448,136.206588 L895.344448,136.206588 L895.344448,144.983387 C894.666045,145.682991 893.770354,146.260685 892.657348,146.716487 C891.544343,147.17229 890.288255,147.400187 888.889048,147.400187 C887.511042,147.400187 886.249654,147.15639 885.104849,146.668787 C883.960043,146.181185 882.974253,145.476292 882.147449,144.554087 C881.320645,143.631883 880.674051,142.497694 880.207649,141.151488 C879.741247,139.805281 879.508049,138.284196 879.508049,136.588188 Z M900.337048,126.157788 L902.976448,126.157788 L902.976448,147.018587 L900.337048,147.018587 L900.337048,126.157788 Z M908.700447,126.157788 L911.435247,126.157788 L918.971847,139.259388 L921.229647,143.584188 L921.356847,143.584188 C921.293246,142.524182 921.224347,141.427093 921.150147,140.292888 C921.075946,139.158682 921.038847,138.040393 921.038847,136.937988 L921.038847,126.157788 L923.551047,126.157788 L923.551047,147.018587 L920.816247,147.018587 L913.247847,133.885188 L910.990047,129.592188 L910.862847,129.592188 C910.947648,130.652194 911.027147,131.728083 911.101347,132.819888 C911.175548,133.911694 911.212647,135.008782 911.212647,136.111188 L911.212647,147.018587 L908.700447,147.018587 L908.700447,126.157788 Z M928.066646,136.588188 C928.066646,134.91338 928.305144,133.408195 928.782146,132.072588 C929.259149,130.736982 929.926942,129.602793 930.785546,128.669988 C931.64415,127.737184 932.65644,127.021691 933.822446,126.523488 C934.988452,126.025286 936.271039,125.776189 937.670246,125.776189 C939.111853,125.776189 940.314941,126.046486 941.279546,126.587088 C942.24415,127.127691 943.033842,127.715985 943.648645,128.351988 L942.154046,130.037388 C941.624043,129.486186 941.014549,129.02509 940.325546,128.654088 C939.636542,128.283087 938.762051,128.097588 937.702046,128.097588 C936.642041,128.097588 935.68805,128.293686 934.840046,128.685888 C933.992042,129.07809 933.271249,129.639885 932.677646,130.371288 C932.084043,131.102692 931.622948,131.987783 931.294346,133.026588 C930.965745,134.065393 930.801446,135.231382 930.801446,136.524588 C930.801446,137.838994 930.955145,139.020883 931.262546,140.070288 C931.569948,141.119693 932.015143,142.015384 932.598146,142.757388 C933.181149,143.499391 933.901942,144.071786 934.760546,144.474587 C935.61915,144.877389 936.61024,145.078787 937.733846,145.078787 C938.475849,145.078787 939.180742,144.967489 939.848546,144.744887 C940.516349,144.522286 941.062243,144.220189 941.486246,143.838588 L941.486246,138.400788 L937.066046,138.400788 L937.066046,136.206588 L943.903045,136.206588 L943.903045,144.983387 C943.224642,145.682991 942.328951,146.260685 941.215946,146.716487 C940.10294,147.17229 938.846853,147.400187 937.447646,147.400187 C936.069639,147.400187 934.808252,147.15639 933.663446,146.668787 C932.51864,146.181185 931.53285,145.476292 930.706046,144.554087 C929.879242,143.631883 929.232649,142.497694 928.766246,141.151488 C928.299844,139.805281 928.066646,138.284196 928.066646,136.588188 Z" id="STAGING" fill="#E04733"></path>
+ <path d="M888.668416,1.13920113 L895.060216,1.13920113 C896.205021,1.13920113 897.254411,1.24520006 898.208415,1.45720111 C899.16242,1.66920216 899.973312,2.01369869 900.641115,2.49070105 C901.308919,2.96770341 901.828313,3.59839707 902.199315,4.38280095 C902.570317,5.16720483 902.755815,6.13179513 902.755815,7.27660079 C902.755815,8.37900625 902.570317,9.33299666 902.199315,10.1386006 C901.828313,10.9442046 901.303619,11.6119979 900.625215,12.1420005 C899.946812,12.6720032 899.13592,13.0694992 898.192515,13.3345005 C897.249111,13.5995018 896.205021,13.7320004 895.060216,13.7320004 L891.307816,13.7320004 L891.307816,22 L888.668416,22 L888.668416,1.13920113 Z M894.742216,11.5696006 C896.565425,11.5696006 897.916911,11.225104 898.796715,10.5361006 C899.67652,9.84709721 900.116415,8.76060813 900.116415,7.27660079 C900.116415,5.77139335 899.67122,4.72730385 898.780815,4.14430096 C897.890411,3.56129808 896.544224,3.26980101 894.742216,3.26980101 L891.307816,3.26980101 L891.307816,11.5696006 L894.742216,11.5696006 Z M909.624615,11.0290006 L913.122615,11.0290006 C914.755023,11.0290006 916.00581,10.6951039 916.875014,10.0273006 C917.744219,9.35949734 918.178814,8.34720752 918.178814,6.99040081 C918.178814,5.61239399 917.744219,4.64780369 916.875014,4.09660097 C916.00581,3.54539824 914.755023,3.26980101 913.122615,3.26980101 L909.624615,3.26980101 L909.624615,11.0290006 Z M918.433214,22 L913.408815,13.1914005 L909.624615,13.1914005 L909.624615,22 L906.985215,22 L906.985215,1.13920113 L913.504215,1.13920113 C914.56422,1.13920113 915.54471,1.23990011 916.445714,1.44130111 C917.346719,1.64270211 918.120511,1.97659875 918.767114,2.44300106 C919.413717,2.90940336 919.917212,3.51359729 920.277614,4.25560096 C920.638016,4.99760463 920.818214,5.90919546 920.818214,6.99040081 C920.818214,8.62280888 920.394218,9.92659578 919.546214,10.9018006 C918.69821,11.8770054 917.564021,12.5447987 916.143614,12.9052005 L921.422414,22 L918.433214,22 Z M933.156613,22.3816 C931.842207,22.3816 930.639119,22.1272025 929.547314,21.6184 C928.455508,21.1095975 927.517418,20.3835048 926.733014,19.4401001 C925.94861,18.4966955 925.339116,17.351907 924.904514,16.0057003 C924.469912,14.6594937 924.252614,13.1490089 924.252614,11.4742006 C924.252614,9.79939228 924.469912,8.29950736 924.904514,6.97450081 C925.339116,5.64949426 925.94861,4.52590555 926.733014,3.60370099 C927.517418,2.68149643 928.455508,1.97660352 929.547314,1.48900111 C930.639119,1.0013987 931.842207,0.757601147 933.156613,0.757601147 C934.47102,0.757601147 935.674108,1.00669864 936.765913,1.50490111 C937.857719,2.00310357 938.801109,2.71329643 939.596113,3.63550099 C940.391117,4.55770555 941.005911,5.68129426 941.440513,7.00630081 C941.875115,8.33130736 942.092413,9.82059239 942.092413,11.4742006 C942.092413,13.1490089 941.875115,14.6594937 941.440513,16.0057003 C941.005911,17.351907 940.391117,18.4966955 939.596113,19.4401001 C938.801109,20.3835048 937.857719,21.1095975 936.765913,21.6184 C935.674108,22.1272025 934.47102,22.3816 933.156613,22.3816 Z M933.156613,20.0602001 C934.089418,20.0602001 934.93211,19.8588021 935.684713,19.4560001 C936.437317,19.0531981 937.083911,18.475504 937.624513,17.7229002 C938.165116,16.9702965 938.583812,16.0693056 938.880613,15.0199004 C939.177415,13.9704952 939.325813,12.7886071 939.325813,11.4742006 C939.325813,10.1809942 939.177415,9.01500589 938.880613,7.97620076 C938.583812,6.93739562 938.165116,6.05760446 937.624513,5.3368009 C937.083911,4.61599733 936.437317,4.05950293 935.684713,3.66730099 C934.93211,3.27509905 934.089418,3.07900102 933.156613,3.07900102 C932.223809,3.07900102 931.381117,3.27509905 930.628514,3.66730099 C929.87591,4.05950293 929.229316,4.61599733 928.688714,5.3368009 C928.148111,6.05760446 927.729415,6.93739562 927.432614,7.97620076 C927.135812,9.01500589 926.987414,10.1809942 926.987414,11.4742006 C926.987414,12.7886071 927.135812,13.9704952 927.432614,15.0199004 C927.729415,16.0693056 928.148111,16.9702965 928.688714,17.7229002 C929.229316,18.475504 929.87591,19.0531981 930.628514,19.4560001 C931.381117,19.8588021 932.223809,20.0602001 933.156613,20.0602001 Z M946.576213,1.13920113 L951.791412,1.13920113 C955.013828,1.13920113 957.462404,2.02959217 959.137212,3.81040098 C960.81202,5.59120979 961.649412,8.14578411 961.649412,11.4742006 C961.649412,13.1278087 961.437414,14.6064939 961.013412,15.9103003 C960.58941,17.2141068 959.964016,18.3164957 959.137212,19.2175002 C958.310408,20.1185046 957.292818,20.8074977 956.084412,21.2845 C954.876006,21.7615024 953.48742,22 951.918612,22 L946.576213,22 L946.576213,1.13920113 Z M951.600612,19.8376001 C954.038625,19.8376001 955.867106,19.1062075 957.086112,17.6434002 C958.305118,16.180593 958.914612,14.1242137 958.914612,11.4742006 C958.914612,8.82418746 958.305118,6.79960782 957.086112,5.4004009 C955.867106,4.00119398 954.038625,3.30160101 951.600612,3.30160101 L949.215613,3.30160101 L949.215613,19.8376001 L951.600612,19.8376001 Z M966.037812,1.13920113 L968.677212,1.13920113 L968.677212,13.4458005 C968.677212,14.6966066 968.80441,15.7459961 969.058812,16.5940003 C969.313213,17.4420045 969.657709,18.1203977 970.092311,18.6292002 C970.526914,19.1380027 971.041008,19.503699 971.634611,19.7263001 C972.228214,19.9489012 972.864208,20.0602001 973.542611,20.0602001 C974.242215,20.0602001 974.888808,19.9489012 975.482411,19.7263001 C976.076014,19.503699 976.595409,19.1380027 977.040611,18.6292002 C977.485813,18.1203977 977.83561,17.4420045 978.090011,16.5940003 C978.344412,15.7459961 978.471611,14.6966066 978.471611,13.4458005 L978.471611,1.13920113 L981.015611,1.13920113 L981.015611,13.3822005 C981.015611,15.0570087 980.824813,16.4667946 980.443211,17.6116002 C980.061609,18.7564059 979.536914,19.6838966 978.869111,20.3941001 C978.201308,21.1043036 977.411616,21.6130985 976.500011,21.9205 C975.588407,22.2279015 974.602617,22.3816 973.542611,22.3816 C972.482606,22.3816 971.491516,22.2279015 970.569311,21.9205 C969.647107,21.6130985 968.852115,21.1043036 968.184312,20.3941001 C967.516508,19.6838966 966.991814,18.7564059 966.610212,17.6116002 C966.22861,16.4667946 966.037812,15.0570087 966.037812,13.3822005 L966.037812,1.13920113 Z M985.435811,11.5696006 C985.435811,9.89479228 985.669008,8.38960741 986.135411,7.05400081 C986.601813,5.7183942 987.248406,4.5842056 988.07521,3.65140099 C988.902015,2.71859638 989.882505,2.00310357 991.01671,1.50490111 C992.150916,1.00669864 993.385804,0.757601147 994.72141,0.757601147 C995.993416,0.757601147 997.106405,1.01729854 998.06041,1.5367011 C999.014415,2.05610367 999.798807,2.65499765 1000.41361,3.33340101 L998.91901,5.01880092 C998.367807,4.42519798 997.758313,3.95350272 997.09051,3.60370099 C996.422707,3.25389926 995.643615,3.07900102 994.75321,3.07900102 C993.756805,3.07900102 992.855814,3.27509905 992.05021,3.66730099 C991.244606,4.05950293 990.555613,4.62129728 989.98321,5.3527009 C989.410808,6.08410452 988.965612,6.96919562 988.64761,8.00800076 C988.329609,9.04680589 988.17061,10.2127942 988.17061,11.5060006 C988.17061,12.8204071 988.324309,14.0022952 988.63171,15.0517004 C988.939112,16.1011056 989.368408,16.9967966 989.91961,17.7388002 C990.470813,18.4808039 991.143906,19.0531981 991.93891,19.4560001 C992.733914,19.8588021 993.629605,20.0602001 994.62601,20.0602001 C995.643615,20.0602001 996.528706,19.8588021 997.28131,19.4560001 C998.033914,19.0531981 998.749407,18.4808039 999.42781,17.7388002 L1000.92241,19.3606001 C1000.09561,20.3146049 999.162815,21.0565974 998.12401,21.5866 C997.085205,22.1166026 995.898017,22.3816 994.56241,22.3816 C993.248004,22.3816 992.034316,22.1378024 990.92131,21.6502 C989.808305,21.1625976 988.843715,20.4577047 988.02751,19.5355001 C987.211306,18.6132956 986.575313,17.479107 986.119511,16.1329003 C985.663708,14.7866937 985.435811,13.265609 985.435811,11.5696006 Z M1009.12681,3.36520101 L1002.83041,3.36520101 L1002.83041,1.13920113 L1018.09441,1.13920113 L1018.09441,3.36520101 L1011.79801,3.36520101 L1011.79801,22 L1009.12681,22 L1009.12681,3.36520101 Z M1021.84681,1.13920113 L1024.48621,1.13920113 L1024.48621,22 L1021.84681,22 L1021.84681,1.13920113 Z M1037.90581,22.3816 C1036.5914,22.3816 1035.38831,22.1272025 1034.29651,21.6184 C1033.2047,21.1095975 1032.26661,20.3835048 1031.48221,19.4401001 C1030.6978,18.4966955 1030.08831,17.351907 1029.65371,16.0057003 C1029.21911,14.6594937 1029.00181,13.1490089 1029.00181,11.4742006 C1029.00181,9.79939228 1029.21911,8.29950736 1029.65371,6.97450081 C1030.08831,5.64949426 1030.6978,4.52590555 1031.48221,3.60370099 C1032.26661,2.68149643 1033.2047,1.97660352 1034.29651,1.48900111 C1035.38831,1.0013987 1036.5914,0.757601147 1037.90581,0.757601147 C1039.22021,0.757601147 1040.4233,1.00669864 1041.51511,1.50490111 C1042.60691,2.00310357 1043.5503,2.71329643 1044.34531,3.63550099 C1045.14031,4.55770555 1045.75511,5.68129426 1046.18971,7.00630081 C1046.62431,8.33130736 1046.84161,9.82059239 1046.84161,11.4742006 C1046.84161,13.1490089 1046.62431,14.6594937 1046.18971,16.0057003 C1045.75511,17.351907 1045.14031,18.4966955 1044.34531,19.4401001 C1043.5503,20.3835048 1042.60691,21.1095975 1041.51511,21.6184 C1040.4233,22.1272025 1039.22021,22.3816 1037.90581,22.3816 Z M1037.90581,20.0602001 C1038.83861,20.0602001 1039.6813,19.8588021 1040.43391,19.4560001 C1041.18651,19.0531981 1041.8331,18.475504 1042.37371,17.7229002 C1042.91431,16.9702965 1043.33301,16.0693056 1043.62981,15.0199004 C1043.92661,13.9704952 1044.07501,12.7886071 1044.07501,11.4742006 C1044.07501,10.1809942 1043.92661,9.01500589 1043.62981,7.97620076 C1043.33301,6.93739562 1042.91431,6.05760446 1042.37371,5.3368009 C1041.8331,4.61599733 1041.18651,4.05950293 1040.43391,3.66730099 C1039.6813,3.27509905 1038.83861,3.07900102 1037.90581,3.07900102 C1036.973,3.07900102 1036.13031,3.27509905 1035.37771,3.66730099 C1034.6251,4.05950293 1033.97851,4.61599733 1033.43791,5.3368009 C1032.89731,6.05760446 1032.47861,6.93739562 1032.18181,7.97620076 C1031.88501,9.01500589 1031.73661,10.1809942 1031.73661,11.4742006 C1031.73661,12.7886071 1031.88501,13.9704952 1032.18181,15.0199004 C1032.47861,16.0693056 1032.89731,16.9702965 1033.43791,17.7229002 C1033.97851,18.475504 1034.6251,19.0531981 1035.37771,19.4560001 C1036.13031,19.8588021 1036.973,20.0602001 1037.90581,20.0602001 Z M1051.32541,1.13920113 L1054.06021,1.13920113 L1061.59681,14.2408004 L1063.85461,18.5656002 L1063.98181,18.5656002 C1063.91821,17.5055949 1063.84931,16.408506 1063.77511,15.2743004 C1063.70091,14.1400948 1063.66381,13.021806 1063.66381,11.9194005 L1063.66381,1.13920113 L1066.17601,1.13920113 L1066.17601,22 L1063.44121,22 L1055.87281,8.86660071 L1053.61501,4.57360094 L1053.48781,4.57360094 C1053.57261,5.63360618 1053.65211,6.70949537 1053.72631,7.80130077 C1053.80051,8.89310617 1053.83761,9.99019514 1053.83761,11.0926006 L1053.83761,22 L1051.32541,22 L1051.32541,1.13920113 Z" id="PRODUCTION-Copy-2" fill="#E04733"></path>
+ <polygon id="Line-Copy-17" fill="#E0513E" points="282.270169 382 498.277674 382 498.277674 378 282.270169 378"></polygon>
+ <path d="M277.201592,391.484016 L283.029685,397.309042 L285.857368,394.47987 L280.029274,388.654844 L277.201592,391.484016 Z M286.198357,400.476046 L292.02645,406.301071 L294.854133,403.4719 L289.026039,397.646874 L286.198357,400.476046 Z M295.195122,409.468075 L301.023216,415.293101 L303.850898,412.463929 L298.022805,406.638904 L295.195122,409.468075 Z M304.191888,418.460105 L310.019981,424.285131 L312.847663,421.455959 L307.01957,415.630933 L304.191888,418.460105 Z M313.188653,427.452135 L319.016746,433.27716 L321.844429,430.447989 L316.016335,424.622963 L313.188653,427.452135 Z M322.185418,436.444164 L328.013511,442.26919 L330.841194,439.440018 L325.0131,433.614993 L322.185418,436.444164 Z M331.182183,445.436194 L337.010277,451.26122 L339.837959,448.432048 L334.009866,442.607022 L331.182183,445.436194 Z M340.178949,454.428224 L346.007042,460.253249 L348.834724,457.424078 L343.006631,451.599052 L340.178949,454.428224 Z M349.175714,463.420253 L355.003807,469.245279 L357.83149,466.416107 L352.003396,460.591082 L349.175714,463.420253 Z M358.172479,472.412283 L364.000572,478.237309 L366.828255,475.408137 L361.000162,469.583111 L358.172479,472.412283 Z M367.169244,481.404313 L372.997338,487.229338 L375.82502,484.400167 L369.996927,478.575141 L367.169244,481.404313 Z M376.16601,490.396342 L381.994103,496.221368 L384.821785,493.392196 L378.993692,487.567171 L376.16601,490.396342 Z" id="Line-Copy-18" fill="#E0513E"></path>
+ <path d="M516.770072,391.484016 L522.598165,397.309042 L525.425848,394.47987 L519.597754,388.654844 L516.770072,391.484016 Z M525.766837,400.476046 L531.594931,406.301071 L534.422613,403.4719 L528.59452,397.646874 L525.766837,400.476046 Z M534.763603,409.468075 L540.591696,415.293101 L543.419378,412.463929 L537.591285,406.638904 L534.763603,409.468075 Z M543.760368,418.460105 L549.588461,424.285131 L552.416144,421.455959 L546.58805,415.630933 L543.760368,418.460105 Z M552.757133,427.452135 L558.585226,433.27716 L561.412909,430.447989 L555.584816,424.622963 L552.757133,427.452135 Z M561.753898,436.444164 L567.581992,442.26919 L570.409674,439.440018 L564.581581,433.614993 L561.753898,436.444164 Z M570.750664,445.436194 L576.578757,451.26122 L579.406439,448.432048 L573.578346,442.607022 L570.750664,445.436194 Z M579.747429,454.428224 L585.575522,460.253249 L588.403205,457.424078 L582.575111,451.599052 L579.747429,454.428224 Z M588.744194,463.420253 L594.572288,469.245279 L597.39997,466.416107 L591.571877,460.591082 L588.744194,463.420253 Z M597.740959,472.412283 L603.569053,478.237309 L606.396735,475.408137 L600.568642,469.583111 L597.740959,472.412283 Z M606.737725,481.404313 L612.565818,487.229338 L615.3935,484.400167 L609.565407,478.575141 L606.737725,481.404313 Z M615.73449,490.396342 L621.562583,496.221368 L624.390266,493.392196 L618.562172,487.567171 L615.73449,490.396342 Z" id="Line-Copy-22" fill="#E0513E"></path>
+ <path d="M756.338552,391.484016 L762.166646,397.309042 L764.994328,394.47987 L759.166235,388.654844 L756.338552,391.484016 Z M765.335318,400.476046 L771.163411,406.301071 L773.991093,403.4719 L768.163,397.646874 L765.335318,400.476046 Z M774.332083,409.468075 L780.160176,415.293101 L782.987859,412.463929 L777.159765,406.638904 L774.332083,409.468075 Z M783.328848,418.460105 L789.156941,424.285131 L791.984624,421.455959 L786.156531,415.630933 L783.328848,418.460105 Z M792.325613,427.452135 L798.153707,433.27716 L800.981389,430.447989 L795.153296,424.622963 L792.325613,427.452135 Z M801.322379,436.444164 L807.150472,442.26919 L809.978154,439.440018 L804.150061,433.614993 L801.322379,436.444164 Z M810.319144,445.436194 L816.147237,451.26122 L818.97492,448.432048 L813.146826,442.607022 L810.319144,445.436194 Z M819.315909,454.428224 L825.144003,460.253249 L827.971685,457.424078 L822.143592,451.599052 L819.315909,454.428224 Z M828.312674,463.420253 L834.140768,469.245279 L836.96845,466.416107 L831.140357,460.591082 L828.312674,463.420253 Z M837.30944,472.412283 L843.137533,478.237309 L845.965216,475.408137 L840.137122,469.583111 L837.30944,472.412283 Z M846.306205,481.404313 L852.134298,487.229338 L854.961981,484.400167 L849.133887,478.575141 L846.306205,481.404313 Z M855.30297,490.396342 L861.131064,496.221368 L863.958746,493.392196 L858.130653,487.567171 L855.30297,490.396342 Z" id="Line-Copy-23" fill="#E0513E"></path>
+ <path d="M880.010512,252.341438 L885.838606,246.516413 L883.010923,243.687241 L877.18283,249.512267 L880.010512,252.341438 Z M889.007278,243.349409 L894.835371,237.524383 L892.007689,234.695211 L886.179595,240.520237 L889.007278,243.349409 Z M898.004043,234.357379 L903.832136,228.532353 L901.004454,225.703182 L895.176361,231.528207 L898.004043,234.357379 Z M907.000808,225.365349 L912.828902,219.540324 L910.001219,216.711152 L904.173126,222.536178 L907.000808,225.365349 Z M915.997573,216.37332 L921.825667,210.548294 L918.997984,207.719122 L913.169891,213.544148 L915.997573,216.37332 Z M924.994339,207.38129 L930.822432,201.556264 L927.99475,198.727093 L922.166656,204.552118 L924.994339,207.38129 Z M933.991104,198.38926 L939.819197,192.564235 L936.991515,189.735063 L931.163422,195.560089 L933.991104,198.38926 Z M942.987869,189.397231 L948.815963,183.572205 L945.98828,180.743033 L940.160187,186.568059 L942.987869,189.397231 Z M951.984635,180.405201 L957.812728,174.580175 L954.985045,171.751004 L949.156952,177.576029 L951.984635,180.405201 Z M960.9814,171.413171 L966.809493,165.588146 L963.981811,162.758974 L958.153717,168.584 L960.9814,171.413171 Z M969.978165,162.421142 L975.806258,156.596116 L972.978576,153.766944 L967.150483,159.59197 L969.978165,162.421142 Z M978.97493,153.429112 L984.803024,147.604086 L981.975341,144.774915 L976.147248,150.59994 L978.97493,153.429112 Z" id="Line-Copy-27" fill="#E0513E"></path>
+ <path d="M1114.27955,23.0223048 C1119.09619,23.0223048 1123,19.1205524 1123,14.3085502 C1123,9.49654797 1119.09619,5.59479554 1114.27955,5.59479554 C1109.46291,5.59479554 1105.5591,9.49654797 1105.5591,14.3085502 C1105.5591,19.1205524 1109.46291,23.0223048 1114.27955,23.0223048 Z M1114.27955,27.0223048 C1107.25424,27.0223048 1101.5591,21.330163 1101.5591,14.3085502 C1101.5591,7.28693738 1107.25424,1.59479554 1114.27955,1.59479554 C1121.30486,1.59479554 1127,7.28693738 1127,14.3085502 C1127,21.330163 1121.30486,27.0223048 1114.27955,27.0223048 Z" id="Oval-Copy-24" fill="#E04733"></path>
+ <polygon id="Line" fill="#E04733" points="758.424239 374.304508 864.800215 266.404117 861.951738 263.595883 755.575761 371.496274"></polygon>
+ <polygon id="Line-Copy" fill="#E04733" points="1000.57718 131.539201 1109.53226 24.6788494 1106.73141 21.8231038 997.776337 128.683455"></polygon>
+ <path d="M510.058161,389.60223 C514.874804,389.60223 518.778612,385.700478 518.778612,380.888476 C518.778612,376.076474 514.874804,372.174721 510.058161,372.174721 C505.241518,372.174721 501.337711,376.076474 501.337711,380.888476 C501.337711,385.700478 505.241518,389.60223 510.058161,389.60223 Z M510.058161,393.60223 C503.032851,393.60223 497.337711,387.910089 497.337711,380.888476 C497.337711,373.866863 503.032851,368.174721 510.058161,368.174721 C517.083472,368.174721 522.778612,373.866863 522.778612,380.888476 C522.778612,387.910089 517.083472,393.60223 510.058161,393.60223 Z" id="Oval-Copy-15" fill="#E04733"></path>
+ <polygon id="Line-Copy-19" fill="#E0513E" points="521.838649 382 737.846154 382 737.846154 378 521.838649 378"></polygon>
+ <path d="M749.626642,389.60223 C754.443285,389.60223 758.347092,385.700478 758.347092,380.888476 C758.347092,376.076474 754.443285,372.174721 749.626642,372.174721 C744.809999,372.174721 740.906191,376.076474 740.906191,380.888476 C740.906191,385.700478 744.809999,389.60223 749.626642,389.60223 Z M749.626642,393.60223 C742.601331,393.60223 736.906191,387.910089 736.906191,380.888476 C736.906191,373.866863 742.601331,368.174721 749.626642,368.174721 C756.651952,368.174721 762.347092,373.866863 762.347092,380.888476 C762.347092,387.910089 756.651952,393.60223 749.626642,393.60223 Z" id="Oval-Copy-16" fill="#E04733"></path>
+ <path d="M270.489681,389.60223 C275.306324,389.60223 279.210131,385.700478 279.210131,380.888476 C279.210131,376.076474 275.306324,372.174721 270.489681,372.174721 C265.673038,372.174721 261.769231,376.076474 261.769231,380.888476 C261.769231,385.700478 265.673038,389.60223 270.489681,389.60223 Z M270.489681,393.60223 C263.46437,393.60223 257.769231,387.910089 257.769231,380.888476 C257.769231,373.866863 263.46437,368.174721 270.489681,368.174721 C277.514992,368.174721 283.210131,373.866863 283.210131,380.888476 C283.210131,387.910089 277.514992,393.60223 270.489681,393.60223 Z" id="Oval-Copy-14" fill="#E04733"></path>
+ <path d="M630.902439,510.3829 C635.719082,510.3829 639.622889,506.481147 639.622889,501.669145 C639.622889,496.857143 635.719082,492.95539 630.902439,492.95539 C626.085796,492.95539 622.181989,496.857143 622.181989,501.669145 C622.181989,506.481147 626.085796,510.3829 630.902439,510.3829 Z M630.902439,514.3829 C623.877128,514.3829 618.181989,508.690758 618.181989,501.669145 C618.181989,494.647532 623.877128,488.95539 630.902439,488.95539 C637.92775,488.95539 643.622889,494.647532 643.622889,501.669145 C643.622889,508.690758 637.92775,514.3829 630.902439,514.3829 Z" id="Oval-Copy-19" fill="#E04733"></path>
+ <path d="M870.470919,510.3829 C875.287562,510.3829 879.19137,506.481147 879.19137,501.669145 C879.19137,496.857143 875.287562,492.95539 870.470919,492.95539 C865.654276,492.95539 861.750469,496.857143 861.750469,501.669145 C861.750469,506.481147 865.654276,510.3829 870.470919,510.3829 Z M870.470919,514.3829 C863.445609,514.3829 857.750469,508.690758 857.750469,501.669145 C857.750469,494.647532 863.445609,488.95539 870.470919,488.95539 C877.49623,488.95539 883.19137,494.647532 883.19137,501.669145 C883.19137,508.690758 877.49623,514.3829 870.470919,514.3829 Z" id="Oval-Copy-18" fill="#E04733"></path>
+ <path d="M391.333959,510.3829 C396.150602,510.3829 400.054409,506.481147 400.054409,501.669145 C400.054409,496.857143 396.150602,492.95539 391.333959,492.95539 C386.517316,492.95539 382.613508,496.857143 382.613508,501.669145 C382.613508,506.481147 386.517316,510.3829 391.333959,510.3829 Z M391.333959,514.3829 C384.308648,514.3829 378.613508,508.690758 378.613508,501.669145 C378.613508,494.647532 384.308648,488.95539 391.333959,488.95539 C398.359269,488.95539 404.054409,494.647532 404.054409,501.669145 C404.054409,508.690758 398.359269,514.3829 391.333959,514.3829 Z" id="Oval-Copy-17" fill="#E04733"></path>
+ <path d="M28.833894,372.064086 L22.5374943,372.064086 L22.5374943,369.838086 L37.8014935,369.838086 L37.8014935,372.064086 L31.5050938,372.064086 L31.5050938,390.698885 L28.833894,390.698885 L28.833894,372.064086 Z M49.2494929,391.080485 C47.9350864,391.080485 46.7319985,390.826087 45.6401931,390.317285 C44.5483877,389.808482 43.6102971,389.08239 42.8258932,388.138985 C42.0414893,387.19558 41.4319955,386.050792 40.9973933,384.704585 C40.5627912,383.358378 40.3454934,381.847894 40.3454934,380.173085 C40.3454934,378.498277 40.5627912,376.998392 40.9973933,375.673386 C41.4319955,374.348379 42.0414893,373.22479 42.8258932,372.302586 C43.6102971,371.380381 44.5483877,370.675488 45.6401931,370.187886 C46.7319985,369.700283 47.9350864,369.456486 49.2494929,369.456486 C50.5638994,369.456486 51.7669873,369.705583 52.8587927,370.203786 C53.9505981,370.701988 54.8939886,371.412181 55.6889925,372.334386 C56.4839965,373.25659 57.0987903,374.380179 57.5333924,375.705186 C57.9679946,377.030192 58.1852924,378.519477 58.1852924,380.173085 C58.1852924,381.847894 57.9679946,383.358378 57.5333924,384.704585 C57.0987903,386.050792 56.4839965,387.19558 55.6889925,388.138985 C54.8939886,389.08239 53.9505981,389.808482 52.8587927,390.317285 C51.7669873,390.826087 50.5638994,391.080485 49.2494929,391.080485 Z M49.2494929,388.759085 C50.1822975,388.759085 51.024989,388.557687 51.7775927,388.154885 C52.5301965,387.752083 53.17679,387.174389 53.7173926,386.421785 C54.2579953,385.669181 54.6766911,384.76819 54.9734926,383.718785 C55.270294,382.66938 55.4186925,381.487492 55.4186925,380.173085 C55.4186925,378.879879 55.270294,377.713891 54.9734926,376.675086 C54.6766911,375.63628 54.2579953,374.756489 53.7173926,374.035686 C53.17679,373.314882 52.5301965,372.758388 51.7775927,372.366186 C51.024989,371.973984 50.1822975,371.777886 49.2494929,371.777886 C48.3166883,371.777886 47.4739967,371.973984 46.721393,372.366186 C45.9687893,372.758388 45.3221958,373.314882 44.7815931,374.035686 C44.2409904,374.756489 43.8222947,375.63628 43.5254932,376.675086 C43.2286917,377.713891 43.0802932,378.879879 43.0802932,380.173085 C43.0802932,381.487492 43.2286917,382.66938 43.5254932,383.718785 C43.8222947,384.76819 44.2409904,385.669181 44.7815931,386.421785 C45.3221958,387.174389 45.9687893,387.752083 46.721393,388.154885 C47.4739967,388.557687 48.3166883,388.759085 49.2494929,388.759085 Z M62.6690922,369.838086 L69.0608918,369.838086 C70.2056975,369.838086 71.2550869,369.944085 72.2090916,370.156086 C73.1630964,370.368087 73.9739882,370.712583 74.6417915,371.189586 C75.3095948,371.666588 75.8289896,372.297282 76.1999914,373.081686 C76.5709933,373.86609 76.7564914,374.83068 76.7564914,375.975486 C76.7564914,377.077891 76.5709933,378.031881 76.1999914,378.837485 C75.8289896,379.643089 75.3042949,380.310883 74.6258915,380.840885 C73.9474882,381.370888 73.1365963,381.768384 72.1931916,382.033385 C71.249787,382.298387 70.2056975,382.430885 69.0608918,382.430885 L65.308492,382.430885 L65.308492,390.698885 L62.6690922,390.698885 L62.6690922,369.838086 Z M68.7428918,380.268485 C70.5661008,380.268485 71.9175873,379.923989 72.7973916,379.234985 C73.677196,378.545982 74.1170915,377.459493 74.1170915,375.975486 C74.1170915,374.470278 73.671896,373.426189 72.7814916,372.843186 C71.8910872,372.260183 70.5449007,371.968686 68.7428918,371.968686 L65.308492,371.968686 L65.308492,380.268485 L68.7428918,380.268485 Z M80.9858912,369.838086 L83.625291,369.838086 L83.625291,390.698885 L80.9858912,390.698885 L80.9858912,369.838086 Z M88.1408908,380.268485 C88.1408908,378.593677 88.3740884,377.088492 88.8404907,375.752886 C89.306893,374.417279 89.9534865,373.28309 90.7802906,372.350286 C91.6070947,371.417481 92.5875849,370.701988 93.7217905,370.203786 C94.8559961,369.705583 96.0908837,369.456486 97.4264903,369.456486 C98.6984966,369.456486 99.8114854,369.716183 100.76549,370.235586 C101.719495,370.754988 102.503887,371.353882 103.11869,372.032286 L101.62409,373.717686 C101.072887,373.124083 100.463393,372.652387 99.7955901,372.302586 C99.1277868,371.952784 98.3486947,371.777886 97.4582903,371.777886 C96.4618853,371.777886 95.5608944,371.973984 94.7552904,372.366186 C93.9496864,372.758388 93.2606934,373.320182 92.6882905,374.051586 C92.1158877,374.782989 91.6706922,375.66808 91.3526906,376.706886 C91.034689,377.745691 90.8756906,378.911679 90.8756906,380.204885 C90.8756906,381.519292 91.0293891,382.70118 91.3367906,383.750585 C91.6441921,384.79999 92.0734878,385.695681 92.6246905,386.437685 C93.1758933,387.179689 93.8489865,387.752083 94.6439904,388.154885 C95.4389944,388.557687 96.3346854,388.759085 97.3310903,388.759085 C98.3486953,388.759085 99.2337864,388.557687 99.9863901,388.154885 C100.738994,387.752083 101.454487,387.179689 102.13289,386.437685 L103.62749,388.059485 C102.800686,389.01349 101.867895,389.755482 100.82909,390.285485 C99.790285,390.815487 98.6030969,391.080485 97.2674903,391.080485 C95.9530838,391.080485 94.739396,390.836687 93.6263905,390.349085 C92.513385,389.861482 91.5487947,389.156589 90.7325906,388.234385 C89.9163866,387.31218 89.280393,386.177992 88.8245907,384.831785 C88.3687885,383.485578 88.1408908,381.964494 88.1408908,380.268485 Z M113.930689,369.838086 L120.131689,369.838086 C121.191694,369.838086 122.161585,369.933485 123.041389,370.124286 C123.921193,370.315087 124.673786,370.611884 125.299189,371.014686 C125.924592,371.417488 126.412187,371.942183 126.761989,372.588786 C127.11179,373.235389 127.286689,374.014481 127.286689,374.926086 C127.286689,375.964891 126.989892,376.902981 126.396289,377.740385 C125.802686,378.57779 124.891095,379.155484 123.661489,379.473485 L123.661489,379.600685 C125.187896,379.833887 126.375084,380.363881 127.223089,381.190685 C128.071093,382.017489 128.495089,383.151678 128.495089,384.593285 C128.495089,385.61089 128.304291,386.501281 127.922689,387.264485 C127.541087,388.027689 127.000492,388.663682 126.300889,389.172485 C125.601285,389.681287 124.763894,390.062884 123.788689,390.317285 C122.813484,390.571686 121.742895,390.698885 120.576889,390.698885 L113.930689,390.698885 L113.930689,369.838086 Z M119.654689,378.742085 C121.456698,378.742085 122.744585,378.434688 123.518389,377.819885 C124.292193,377.205082 124.679089,376.314691 124.679089,375.148686 C124.679089,374.00388 124.270993,373.182388 123.454789,372.684186 C122.638585,372.185983 121.414297,371.936886 119.781889,371.936886 L116.570089,371.936886 L116.570089,378.742085 L119.654689,378.742085 Z M120.195289,388.600085 C121.997298,388.600085 123.396484,388.266188 124.392889,387.598385 C125.389294,386.930582 125.887489,385.886492 125.887489,384.466085 C125.887489,383.172879 125.399894,382.224188 124.424689,381.619985 C123.449484,381.015782 122.039698,380.713685 120.195289,380.713685 L116.570089,380.713685 L116.570089,388.600085 L120.195289,388.600085 Z M135.268488,379.727885 L138.766488,379.727885 C140.398896,379.727885 141.649684,379.393989 142.518888,378.726185 C143.388092,378.058382 143.822688,377.046092 143.822688,375.689286 C143.822688,374.311279 143.388092,373.346688 142.518888,372.795486 C141.649684,372.244283 140.398896,371.968686 138.766488,371.968686 L135.268488,371.968686 L135.268488,379.727885 Z M144.077088,390.698885 L139.052688,381.890285 L135.268488,381.890285 L135.268488,390.698885 L132.629088,390.698885 L132.629088,369.838086 L139.148088,369.838086 C140.208093,369.838086 141.188583,369.938785 142.089588,370.140186 C142.990592,370.341587 143.764385,370.675484 144.410988,371.141886 C145.057591,371.608288 145.561086,372.212482 145.921488,372.954486 C146.281889,373.696489 146.462088,374.60808 146.462088,375.689286 C146.462088,377.321694 146.038092,378.625481 145.190088,379.600685 C144.342084,380.57589 143.207895,381.243683 141.787488,381.604085 L147.066288,390.698885 L144.077088,390.698885 Z M159.977087,382.208285 L158.991287,379.028285 C158.609685,377.86228 158.249289,376.701591 157.910087,375.546186 C157.570885,374.39078 157.231689,373.208892 156.892487,372.000486 L156.765287,372.000486 C156.447286,373.208892 156.118689,374.39078 155.779487,375.546186 C155.440285,376.701591 155.079889,377.86228 154.698287,379.028285 L153.712487,382.208285 L159.977087,382.208285 Z M160.644887,384.338885 L153.044687,384.338885 L151.041287,390.698885 L148.338288,390.698885 L155.397887,369.838086 L158.387087,369.838086 L165.446687,390.698885 L162.616487,390.698885 L160.644887,384.338885 Z M168.404086,369.838086 L171.138886,369.838086 L178.675486,382.939685 L180.933286,387.264485 L181.060486,387.264485 C180.996885,386.20448 180.927986,385.107391 180.853786,383.973185 C180.779585,382.83898 180.742486,381.720691 180.742486,380.618285 L180.742486,369.838086 L183.254686,369.838086 L183.254686,390.698885 L180.519886,390.698885 L172.951486,377.565485 L170.693686,373.272486 L170.566486,373.272486 C170.651287,374.332491 170.730786,375.40838 170.804986,376.500186 C170.879187,377.591991 170.916286,378.68908 170.916286,379.791485 L170.916286,390.698885 L168.404086,390.698885 L168.404086,369.838086 Z M187.770285,380.268485 C187.770285,378.593677 188.003483,377.088492 188.469885,375.752886 C188.936288,374.417279 189.582881,373.28309 190.409685,372.350286 C191.236489,371.417481 192.216979,370.701988 193.351185,370.203786 C194.485391,369.705583 195.720278,369.456486 197.055885,369.456486 C198.327891,369.456486 199.44088,369.716183 200.394885,370.235586 C201.348889,370.754988 202.133282,371.353882 202.748085,372.032286 L201.253485,373.717686 C200.702282,373.124083 200.092788,372.652387 199.424985,372.302586 C198.757181,371.952784 197.978089,371.777886 197.087685,371.777886 C196.09128,371.777886 195.190289,371.973984 194.384685,372.366186 C193.579081,372.758388 192.890088,373.320182 192.317685,374.051586 C191.745282,374.782989 191.300087,375.66808 190.982085,376.706886 C190.664084,377.745691 190.505085,378.911679 190.505085,380.204885 C190.505085,381.519292 190.658784,382.70118 190.966185,383.750585 C191.273587,384.79999 191.702882,385.695681 192.254085,386.437685 C192.805288,387.179689 193.478381,387.752083 194.273385,388.154885 C195.068389,388.557687 195.96408,388.759085 196.960485,388.759085 C197.97809,388.759085 198.863181,388.557687 199.615785,388.154885 C200.368388,387.752083 201.083881,387.179689 201.762285,386.437685 L203.256885,388.059485 C202.43008,389.01349 201.49729,389.755482 200.458485,390.285485 C199.41968,390.815487 198.232492,391.080485 196.896885,391.080485 C195.582478,391.080485 194.368791,390.836687 193.255785,390.349085 C192.14278,389.861482 191.178189,389.156589 190.361985,388.234385 C189.545781,387.31218 188.909788,386.177992 188.453985,384.831785 C187.998183,383.485578 187.770285,381.964494 187.770285,380.268485 Z M207.136484,369.838086 L209.775884,369.838086 L209.775884,378.583085 L219.474884,378.583085 L219.474884,369.838086 L222.146084,369.838086 L222.146084,390.698885 L219.474884,390.698885 L219.474884,380.872685 L209.775884,380.872685 L209.775884,390.698885 L207.136484,390.698885 L207.136484,369.838086 Z" id="TOPIC-BRANCH" fill="#E04733"></path>
+ <path d="M687.15753,304.150354 L690.273929,304.150354 L694.312529,315.343953 L695.838929,319.605153 L695.966129,319.605153 L697.428929,315.343953 L701.435729,304.150354 L704.552129,304.150354 L704.552129,325.011152 L702.039929,325.011152 L702.039929,313.531353 C702.039929,312.598548 702.077028,311.570359 702.151229,310.446753 C702.225429,309.323148 702.304928,308.294958 702.389729,307.362153 L702.262529,307.362153 L700.577129,312.004953 L696.570329,322.912353 L695.075729,322.912353 L691.037129,312.004953 L689.383529,307.362153 L689.256329,307.362153 C689.31993,308.294958 689.394129,309.323148 689.478929,310.446753 C689.56373,311.570359 689.606129,312.598548 689.606129,313.531353 L689.606129,325.011152 L687.15753,325.011152 L687.15753,304.150354 Z M710.276128,304.150354 L722.296528,304.150354 L722.296528,306.376353 L712.915528,306.376353 L712.915528,312.927153 L720.833728,312.927153 L720.833728,315.184953 L712.915528,315.184953 L712.915528,322.753353 L722.614528,322.753353 L722.614528,325.011152 L710.276128,325.011152 L710.276128,304.150354 Z M729.674127,314.040153 L733.172127,314.040153 C734.804535,314.040153 736.055323,313.706256 736.924527,313.038453 C737.793731,312.37065 738.228327,311.35836 738.228327,310.001553 C738.228327,308.623546 737.793731,307.658956 736.924527,307.107753 C736.055323,306.556551 734.804535,306.280953 733.172127,306.280953 L729.674127,306.280953 L729.674127,314.040153 Z M738.482727,325.011152 L733.458327,316.202553 L729.674127,316.202553 L729.674127,325.011152 L727.034727,325.011152 L727.034727,304.150354 L733.553727,304.150354 C734.613732,304.150354 735.594222,304.251053 736.495227,304.452454 C737.396231,304.653855 738.170024,304.987751 738.816627,305.454153 C739.46323,305.920556 739.966725,306.52475 740.327127,307.266753 C740.687528,308.008757 740.867727,308.920348 740.867727,310.001553 C740.867727,311.633961 740.443731,312.937748 739.595727,313.912953 C738.747723,314.888158 737.613534,315.555951 736.193127,315.916353 L741.471927,325.011152 L738.482727,325.011152 Z M744.302126,314.580753 C744.302126,312.905945 744.540624,311.40076 745.017626,310.065153 C745.494629,308.729547 746.162422,307.595358 747.021026,306.662553 C747.879631,305.729749 748.89192,305.014256 750.057926,304.516054 C751.223932,304.017851 752.506519,303.768754 753.905726,303.768754 C755.347333,303.768754 756.550421,304.039051 757.515026,304.579654 C758.479631,305.120256 759.269323,305.70855 759.884126,306.344553 L758.389526,308.029953 C757.859523,307.478751 757.250029,307.017655 756.561026,306.646653 C755.872022,306.275652 754.997531,306.090153 753.937526,306.090153 C752.877521,306.090153 751.92353,306.286251 751.075526,306.678453 C750.227522,307.070655 749.506729,307.63245 748.913126,308.363853 C748.319523,309.095257 747.858428,309.980348 747.529826,311.019153 C747.201225,312.057958 747.036926,313.223947 747.036926,314.517153 C747.036926,315.831559 747.190625,317.013448 747.498026,318.062853 C747.805428,319.112258 748.250623,320.007949 748.833626,320.749953 C749.416629,321.491956 750.137422,322.064351 750.996026,322.467153 C751.85463,322.869955 752.84572,323.071353 753.969326,323.071353 C754.71133,323.071353 755.416223,322.960054 756.084026,322.737453 C756.751829,322.514851 757.297724,322.212754 757.721726,321.831153 L757.721726,316.393353 L753.301526,316.393353 L753.301526,314.199153 L760.138526,314.199153 L760.138526,322.975953 C759.460122,323.675556 758.564431,324.25325 757.451426,324.709052 C756.33842,325.164855 755.082333,325.392752 753.683126,325.392752 C752.305119,325.392752 751.043732,325.148955 749.898926,324.661352 C748.754121,324.17375 747.76833,323.468857 746.941526,322.546653 C746.114722,321.624448 745.468129,320.490259 745.001726,319.144053 C744.535324,317.797846 744.302126,316.276761 744.302126,314.580753 Z M765.131125,304.150354 L777.151525,304.150354 L777.151525,306.376353 L767.770525,306.376353 L767.770525,312.927153 L775.688725,312.927153 L775.688725,315.184953 L767.770525,315.184953 L767.770525,322.753353 L777.469525,322.753353 L777.469525,325.011152 L765.131125,325.011152 L765.131125,304.150354 Z" id="MERGE" fill="#E04733"></path>
+ <path d="M189.429182,500.508554 L192.927182,500.508554 C194.55959,500.508554 195.810377,500.174658 196.679581,499.506855 C197.548786,498.839051 197.983381,497.826761 197.983381,496.469955 C197.983381,495.091948 197.548786,494.127358 196.679581,493.576155 C195.810377,493.024952 194.55959,492.749355 192.927182,492.749355 L189.429182,492.749355 L189.429182,500.508554 Z M198.237781,511.479554 L193.213382,502.670954 L189.429182,502.670954 L189.429182,511.479554 L186.789782,511.479554 L186.789782,490.618755 L193.308782,490.618755 C194.368787,490.618755 195.349277,490.719454 196.250281,490.920855 C197.151286,491.122256 197.925078,491.456153 198.571681,491.922555 C199.218284,492.388957 199.721779,492.993151 200.082181,493.735155 C200.442583,494.477159 200.622781,495.388749 200.622781,496.469955 C200.622781,498.102363 200.198785,499.40615 199.350781,500.381355 C198.502777,501.356559 197.368588,502.024353 195.948181,502.384754 L201.226981,511.479554 L198.237781,511.479554 Z M205.265581,490.618755 L217.28598,490.618755 L217.28598,492.844755 L207.904981,492.844755 L207.904981,499.395555 L215.82318,499.395555 L215.82318,501.653354 L207.904981,501.653354 L207.904981,509.221754 L217.60398,509.221754 L217.60398,511.479554 L205.265581,511.479554 L205.265581,490.618755 Z M219.16218,490.618755 L221.99238,490.618755 L225.33138,501.875954 C225.712982,503.126761 226.046878,504.282149 226.33308,505.342154 C226.619281,506.402159 226.963778,507.546948 227.36658,508.776554 L227.49378,508.776554 C227.875382,507.546948 228.214578,506.402159 228.51138,505.342154 C228.808181,504.282149 229.136778,503.126761 229.49718,501.875954 L232.836179,490.618755 L235.539179,490.618755 L228.92478,511.479554 L225.84018,511.479554 L219.16218,490.618755 Z M238.401179,490.618755 L241.040579,490.618755 L241.040579,511.479554 L238.401179,511.479554 L238.401179,490.618755 Z M246.764579,490.618755 L258.784978,490.618755 L258.784978,492.844755 L249.403978,492.844755 L249.403978,499.395555 L257.322178,499.395555 L257.322178,501.653354 L249.403978,501.653354 L249.403978,509.221754 L259.102978,509.221754 L259.102978,511.479554 L246.764579,511.479554 L246.764579,490.618755 Z M261.392578,490.618755 L264.127378,490.618755 L266.321578,501.971354 C266.512379,503.11616 266.713776,504.239749 266.925778,505.342154 C267.137779,506.44456 267.339177,507.568148 267.529977,508.712954 L267.657177,508.712954 C267.890379,507.568148 268.134176,506.43926 268.388577,505.326254 C268.642979,504.213249 268.886776,503.09496 269.119977,501.971354 L272.013777,490.618755 L274.430577,490.618755 L277.324377,501.971354 C277.578778,503.07376 277.833176,504.186749 278.087577,505.310354 C278.341978,506.43396 278.596376,507.568148 278.850777,508.712954 L278.977977,508.712954 C279.168778,507.568148 279.359576,506.43926 279.550377,505.326254 C279.741178,504.213249 279.942576,503.09496 280.154577,501.971354 L282.348777,490.618755 L284.892777,490.618755 L280.567977,511.479554 L277.387977,511.479554 L274.239777,498.918555 C274.048976,498.112951 273.874078,497.323259 273.715077,496.549455 C273.556076,495.775651 273.391778,494.985959 273.222177,494.180355 L273.094977,494.180355 C272.925376,494.985959 272.750478,495.775651 272.570277,496.549455 C272.390076,497.323259 272.215178,498.112951 272.045577,498.918555 L268.960977,511.479554 L265.812778,511.479554 L261.392578,490.618755 Z M303.813776,502.988954 L302.827976,499.808955 C302.446374,498.642949 302.085977,497.48226 301.746776,496.326855 C301.407574,495.171449 301.068377,493.989561 300.729176,492.781155 L300.601976,492.781155 C300.283974,493.989561 299.955377,495.171449 299.616176,496.326855 C299.276974,497.48226 298.916578,498.642949 298.534976,499.808955 L297.549176,502.988954 L303.813776,502.988954 Z M304.481576,505.119554 L296.881376,505.119554 L294.877976,511.479554 L292.174976,511.479554 L299.234576,490.618755 L302.223776,490.618755 L309.283375,511.479554 L306.453175,511.479554 L304.481576,505.119554 Z M312.240775,490.618755 L318.632575,490.618755 C319.77738,490.618755 320.82677,490.724754 321.780775,490.936755 C322.734779,491.148756 323.545671,491.493253 324.213474,491.970255 C324.881278,492.447257 325.400673,493.077951 325.771674,493.862355 C326.142676,494.646759 326.328174,495.611349 326.328174,496.756155 C326.328174,497.85856 326.142676,498.812551 325.771674,499.618155 C325.400673,500.423759 324.875978,501.091552 324.197574,501.621554 C323.519171,502.151557 322.708279,502.549053 321.764875,502.814054 C320.82147,503.079056 319.77738,503.211554 318.632575,503.211554 L314.880175,503.211554 L314.880175,511.479554 L312.240775,511.479554 L312.240775,490.618755 Z M318.314575,501.049154 C320.137784,501.049154 321.48927,500.704658 322.369075,500.015655 C323.248879,499.326651 323.688774,498.240162 323.688774,496.756155 C323.688774,495.250947 323.243579,494.206858 322.353175,493.623855 C321.46277,493.040852 320.116584,492.749355 318.314575,492.749355 L314.880175,492.749355 L314.880175,501.049154 L318.314575,501.049154 Z M330.557574,490.618755 L336.949374,490.618755 C338.094179,490.618755 339.143569,490.724754 340.097574,490.936755 C341.051578,491.148756 341.86247,491.493253 342.530273,491.970255 C343.198077,492.447257 343.717472,493.077951 344.088473,493.862355 C344.459475,494.646759 344.644973,495.611349 344.644973,496.756155 C344.644973,497.85856 344.459475,498.812551 344.088473,499.618155 C343.717472,500.423759 343.192777,501.091552 342.514373,501.621554 C341.83597,502.151557 341.025078,502.549053 340.081674,502.814054 C339.138269,503.079056 338.094179,503.211554 336.949374,503.211554 L333.196974,503.211554 L333.196974,511.479554 L330.557574,511.479554 L330.557574,490.618755 Z M336.631374,501.049154 C338.454583,501.049154 339.806069,500.704658 340.685874,500.015655 C341.565678,499.326651 342.005573,498.240162 342.005573,496.756155 C342.005573,495.250947 341.560378,494.206858 340.669974,493.623855 C339.779569,493.040852 338.433383,492.749355 336.631374,492.749355 L333.196974,492.749355 L333.196974,501.049154 L336.631374,501.049154 Z" id="REVIEW-APP" fill="#E04733"></path>
+ <path d="M281.839315,443.148434 C281.839315,441.89441 281.395681,440.823773 280.5084,439.936492 C279.621119,439.049211 278.550482,438.605577 277.296458,438.605577 C276.042434,438.605577 274.971797,439.049211 274.084516,439.936492 C273.197235,440.823773 272.753601,441.89441 272.753601,443.148434 C272.753601,444.402458 273.197235,445.473095 274.084516,446.360376 C274.971797,447.247657 276.042434,447.691291 277.296458,447.691291 C278.550482,447.691291 279.621119,447.247657 280.5084,446.360376 C281.395681,445.473095 281.839315,444.402458 281.839315,443.148434 Z M295.467886,452.234148 C295.467886,451.618966 295.243111,451.086605 294.793555,450.63705 C294.343999,450.187494 293.811639,449.962719 293.196457,449.962719 C292.581275,449.962719 292.048915,450.187494 291.599359,450.63705 C291.149803,451.086605 290.925029,451.618966 290.925029,452.234148 C290.925029,452.86116 291.146846,453.396478 291.590486,453.840119 C292.034127,454.283759 292.569445,454.505576 293.196457,454.505576 C293.823469,454.505576 294.358787,454.283759 294.802428,453.840119 C295.246069,453.396478 295.467886,452.86116 295.467886,452.234148 Z M295.467886,434.06272 C295.467886,433.447539 295.243111,432.915178 294.793555,432.465622 C294.343999,432.016066 293.811639,431.791292 293.196457,431.791292 C292.581275,431.791292 292.048915,432.016066 291.599359,432.465622 C291.149803,432.915178 290.925029,433.447539 290.925029,434.06272 C290.925029,434.689732 291.146846,435.22505 291.590486,435.668691 C292.034127,436.112332 292.569445,436.334149 293.196457,436.334149 C293.823469,436.334149 294.358787,436.112332 294.802428,435.668691 C295.246069,435.22505 295.467886,434.689732 295.467886,434.06272 Z M288.6536,441.53359 L288.6536,444.816514 C288.6536,444.934818 288.612194,445.050163 288.529381,445.162552 C288.446569,445.274941 288.351927,445.33705 288.245453,445.34888 L285.494895,445.774773 C285.36476,446.188838 285.175477,446.638387 284.927038,447.123434 C285.329272,447.691294 285.861633,448.371532 286.524136,449.16417 C286.606949,449.282474 286.648355,449.400777 286.648355,449.519081 C286.648355,449.661046 286.606949,449.773433 286.524136,449.856246 C286.252036,450.211159 285.764039,450.740562 285.060129,451.444471 C284.35622,452.148381 283.891883,452.500331 283.667105,452.500331 C283.53697,452.500331 283.412753,452.458925 283.294449,452.376112 L281.253712,450.779014 C280.815987,451.003792 280.360523,451.18716 279.887306,451.329125 C279.757171,452.60681 279.621124,453.523654 279.479159,454.079683 C279.396346,454.363613 279.218892,454.505576 278.946793,454.505576 L275.646123,454.505576 C275.515989,454.505576 275.397686,454.461213 275.291212,454.372485 C275.184739,454.283757 275.125588,454.180242 275.113757,454.061938 L274.70561,451.346871 C274.303376,451.228567 273.859742,451.045198 273.374695,450.796759 L271.280722,452.376112 C271.197909,452.458925 271.079606,452.500331 270.925811,452.500331 C270.795676,452.500331 270.671459,452.45301 270.553155,452.358367 C268.849575,450.784921 267.997798,449.838502 267.997798,449.519081 C267.997798,449.412607 268.039204,449.30022 268.122016,449.181916 C268.240321,449.01629 268.48284,448.702789 268.849583,448.241402 C269.216326,447.780016 269.494337,447.419194 269.683624,447.158925 C269.411524,446.638387 269.204495,446.153347 269.06253,445.703791 L266.365209,445.277898 C266.246904,445.266068 266.146347,445.209874 266.063534,445.109316 C265.980722,445.008757 265.939316,444.893412 265.939316,444.763278 L265.939316,441.480354 C265.939316,441.36205 265.980722,441.246705 266.063534,441.134316 C266.146347,441.021927 266.240989,440.959818 266.347463,440.947988 L269.098021,440.522095 C269.228155,440.10803 269.417439,439.658481 269.665878,439.173434 C269.263644,438.605574 268.731283,437.925336 268.06878,437.132698 C267.985967,437.002563 267.944561,436.884261 267.944561,436.777787 C267.944561,436.635822 267.985967,436.51752 268.06878,436.422876 C268.329049,436.067964 268.814089,435.541518 269.523914,434.843524 C270.233739,434.145529 270.701033,433.796537 270.925811,433.796537 C271.055946,433.796537 271.180163,433.837943 271.298467,433.920756 L273.339204,435.517854 C273.741438,435.304907 274.196902,435.115623 274.70561,434.949997 C274.835744,433.672312 274.971792,432.761384 275.113757,432.217185 C275.19657,431.933255 275.374024,431.791292 275.646123,431.791292 L278.946793,431.791292 C279.076927,431.791292 279.19523,431.835655 279.301703,431.924383 C279.408177,432.013111 279.467328,432.116626 279.479159,432.23493 L279.887306,434.949997 C280.28954,435.068301 280.733174,435.25167 281.218221,435.500108 L283.312194,433.920756 C283.406838,433.837943 283.52514,433.796537 283.667105,433.796537 C283.797239,433.796537 283.921457,433.843858 284.039761,433.938501 C285.743341,435.511947 286.595118,436.458366 286.595118,436.777787 C286.595118,436.884261 286.553712,436.996648 286.470899,437.114952 C286.328934,437.304239 286.080499,437.623655 285.725587,438.073211 C285.370674,438.522767 285.104494,438.877674 284.927038,439.137943 C285.199137,439.705803 285.400251,440.190843 285.530386,440.593077 L288.227707,441.001224 C288.346011,441.024885 288.446569,441.086994 288.529381,441.187552 C288.612194,441.288111 288.6536,441.403456 288.6536,441.53359 Z M300.010742,450.99196 L300.010742,453.476335 C300.010742,453.665622 299.12939,453.848991 297.366658,454.026447 C297.224693,454.345868 297.047239,454.653454 296.834292,454.949215 C297.437643,456.286052 297.739314,457.102338 297.739314,457.398098 C297.739314,457.44542 297.715653,457.486826 297.668332,457.522317 C296.225021,458.362277 295.491546,458.78225 295.467886,458.78225 C295.373242,458.78225 295.101147,458.504239 294.651591,457.94821 C294.202035,457.39218 293.894449,456.989952 293.728823,456.741514 C293.492215,456.765174 293.314761,456.777005 293.196457,456.777005 C293.078153,456.777005 292.900699,456.765174 292.664091,456.741514 C292.498465,456.989952 292.190879,457.39218 291.741323,457.94821 C291.291767,458.504239 291.019672,458.78225 290.925029,458.78225 C290.901368,458.78225 290.167893,458.362277 288.724582,457.522317 C288.677261,457.486826 288.6536,457.44542 288.6536,457.398098 C288.6536,457.102338 288.955271,456.286052 289.558622,454.949215 C289.345675,454.653454 289.168221,454.345868 289.026256,454.026447 C287.263524,453.848991 286.382172,453.665622 286.382172,453.476335 L286.382172,450.99196 C286.382172,450.802674 287.263524,450.619305 289.026256,450.441849 C289.180052,450.098767 289.357505,449.791181 289.558622,449.519081 C288.955271,448.182244 288.6536,447.365958 288.6536,447.070197 C288.6536,447.022875 288.677261,446.98147 288.724582,446.945978 C288.771904,446.922318 288.978933,446.804015 289.345676,446.591068 C289.712419,446.37812 290.061411,446.177006 290.392663,445.98772 C290.723914,445.798433 290.901368,445.703791 290.925029,445.703791 C291.019672,445.703791 291.291767,445.978844 291.741323,446.528958 C292.190879,447.079073 292.498465,447.478343 292.664091,447.726782 C292.900699,447.703121 293.078153,447.691291 293.196457,447.691291 C293.314761,447.691291 293.492215,447.703121 293.728823,447.726782 C294.332174,446.886822 294.876365,446.224329 295.361412,445.739282 L295.467886,445.703791 C295.515207,445.703791 296.248682,446.117849 297.668332,446.945978 C297.715653,446.98147 297.739314,447.022875 297.739314,447.070197 C297.739314,447.365958 297.437643,448.182244 296.834292,449.519081 C297.035409,449.791181 297.212862,450.098767 297.366658,450.441849 C299.12939,450.619305 300.010742,450.802674 300.010742,450.99196 Z M300.010742,432.820533 L300.010742,435.304908 C300.010742,435.494194 299.12939,435.677563 297.366658,435.855019 C297.224693,436.17444 297.047239,436.482027 296.834292,436.777787 C297.437643,438.114624 297.739314,438.93091 297.739314,439.226671 C297.739314,439.273992 297.715653,439.315398 297.668332,439.35089 C296.225021,440.190849 295.491546,440.610822 295.467886,440.610822 C295.373242,440.610822 295.101147,440.332812 294.651591,439.776782 C294.202035,439.220753 293.894449,438.818525 293.728823,438.570086 C293.492215,438.593747 293.314761,438.605577 293.196457,438.605577 C293.078153,438.605577 292.900699,438.593747 292.664091,438.570086 C292.498465,438.818525 292.190879,439.220753 291.741323,439.776782 C291.291767,440.332812 291.019672,440.610822 290.925029,440.610822 C290.901368,440.610822 290.167893,440.190849 288.724582,439.35089 C288.677261,439.315398 288.6536,439.273992 288.6536,439.226671 C288.6536,438.93091 288.955271,438.114624 289.558622,436.777787 C289.345675,436.482027 289.168221,436.17444 289.026256,435.855019 C287.263524,435.677563 286.382172,435.494194 286.382172,435.304908 L286.382172,432.820533 C286.382172,432.631246 287.263524,432.447877 289.026256,432.270421 C289.180052,431.927339 289.357505,431.619753 289.558622,431.347653 C288.955271,430.010816 288.6536,429.19453 288.6536,428.89877 C288.6536,428.851448 288.677261,428.810042 288.724582,428.774551 C288.771904,428.75089 288.978933,428.632588 289.345676,428.41964 C289.712419,428.206693 290.061411,428.005579 290.392663,427.816292 C290.723914,427.627005 290.901368,427.532363 290.925029,427.532363 C291.019672,427.532363 291.291767,427.807416 291.741323,428.357531 C292.190879,428.907645 292.498465,429.306916 292.664091,429.555354 C292.900699,429.531694 293.078153,429.519863 293.196457,429.519863 C293.314761,429.519863 293.492215,429.531694 293.728823,429.555354 C294.332174,428.715395 294.876365,428.052901 295.361412,427.567854 L295.467886,427.532363 C295.515207,427.532363 296.248682,427.946422 297.668332,428.774551 C297.715653,428.810042 297.739314,428.851448 297.739314,428.89877 C297.739314,429.19453 297.437643,430.010816 296.834292,431.347653 C297.035409,431.619753 297.212862,431.927339 297.366658,432.270421 C299.12939,432.447877 300.010742,432.631246 300.010742,432.820533 Z" id="ï‚…" fill="#E04733"></path>
+ <path d="M518.847717,443.148434 C518.847717,441.89441 518.404083,440.823773 517.516802,439.936492 C516.629521,439.049211 515.558884,438.605577 514.30486,438.605577 C513.050836,438.605577 511.9802,439.049211 511.092919,439.936492 C510.205637,440.823773 509.762003,441.89441 509.762003,443.148434 C509.762003,444.402458 510.205637,445.473095 511.092919,446.360376 C511.9802,447.247657 513.050836,447.691291 514.30486,447.691291 C515.558884,447.691291 516.629521,447.247657 517.516802,446.360376 C518.404083,445.473095 518.847717,444.402458 518.847717,443.148434 Z M532.476288,452.234148 C532.476288,451.618966 532.251513,451.086605 531.801958,450.63705 C531.352402,450.187494 530.820041,449.962719 530.20486,449.962719 C529.589678,449.962719 529.057317,450.187494 528.607761,450.63705 C528.158206,451.086605 527.933431,451.618966 527.933431,452.234148 C527.933431,452.86116 528.155248,453.396478 528.598889,453.840119 C529.042529,454.283759 529.577847,454.505576 530.20486,454.505576 C530.831872,454.505576 531.36719,454.283759 531.81083,453.840119 C532.254471,453.396478 532.476288,452.86116 532.476288,452.234148 Z M532.476288,434.06272 C532.476288,433.447539 532.251513,432.915178 531.801958,432.465622 C531.352402,432.016066 530.820041,431.791292 530.20486,431.791292 C529.589678,431.791292 529.057317,432.016066 528.607761,432.465622 C528.158206,432.915178 527.933431,433.447539 527.933431,434.06272 C527.933431,434.689732 528.155248,435.22505 528.598889,435.668691 C529.042529,436.112332 529.577847,436.334149 530.20486,436.334149 C530.831872,436.334149 531.36719,436.112332 531.81083,435.668691 C532.254471,435.22505 532.476288,434.689732 532.476288,434.06272 Z M525.662003,441.53359 L525.662003,444.816514 C525.662003,444.934818 525.620597,445.050163 525.537784,445.162552 C525.454971,445.274941 525.360329,445.33705 525.253855,445.34888 L522.503297,445.774773 C522.373163,446.188838 522.183879,446.638387 521.93544,447.123434 C522.337674,447.691294 522.870035,448.371532 523.532538,449.16417 C523.615351,449.282474 523.656757,449.400777 523.656757,449.519081 C523.656757,449.661046 523.615351,449.773433 523.532538,449.856246 C523.260439,450.211159 522.772442,450.740562 522.068532,451.444471 C521.364622,452.148381 520.900285,452.500331 520.675507,452.500331 C520.545373,452.500331 520.421155,452.458925 520.302851,452.376112 L518.262115,450.779014 C517.824389,451.003792 517.368925,451.18716 516.895708,451.329125 C516.765574,452.60681 516.629526,453.523654 516.487561,454.079683 C516.404748,454.363613 516.227295,454.505576 515.955195,454.505576 L512.654526,454.505576 C512.524391,454.505576 512.406089,454.461213 512.299615,454.372485 C512.193141,454.283757 512.13399,454.180242 512.12216,454.061938 L511.714012,451.346871 C511.311778,451.228567 510.868144,451.045198 510.383097,450.796759 L508.289124,452.376112 C508.206311,452.458925 508.088009,452.500331 507.934213,452.500331 C507.804079,452.500331 507.679861,452.45301 507.561557,452.358367 C505.857977,450.784921 505.0062,449.838502 505.0062,449.519081 C505.0062,449.412607 505.047606,449.30022 505.130419,449.181916 C505.248723,449.01629 505.491243,448.702789 505.857986,448.241402 C506.224729,447.780016 506.502739,447.419194 506.692026,447.158925 C506.419926,446.638387 506.212897,446.153347 506.070932,445.703791 L503.373611,445.277898 C503.255307,445.266068 503.15475,445.209874 503.071937,445.109316 C502.989124,445.008757 502.947718,444.893412 502.947718,444.763278 L502.947718,441.480354 C502.947718,441.36205 502.989124,441.246705 503.071937,441.134316 C503.15475,441.021927 503.249392,440.959818 503.355865,440.947988 L506.106423,440.522095 C506.236558,440.10803 506.425842,439.658481 506.67428,439.173434 C506.272046,438.605574 505.739686,437.925336 505.077182,437.132698 C504.994369,437.002563 504.952964,436.884261 504.952964,436.777787 C504.952964,436.635822 504.994369,436.51752 505.077182,436.422876 C505.337451,436.067964 505.822491,435.541518 506.532316,434.843524 C507.242141,434.145529 507.709436,433.796537 507.934213,433.796537 C508.064348,433.796537 508.188565,433.837943 508.30687,433.920756 L510.347606,435.517854 C510.74984,435.304907 511.205304,435.115623 511.714012,434.949997 C511.844147,433.672312 511.980195,432.761384 512.12216,432.217185 C512.204973,431.933255 512.382426,431.791292 512.654526,431.791292 L515.955195,431.791292 C516.08533,431.791292 516.203632,431.835655 516.310106,431.924383 C516.41658,432.013111 516.475731,432.116626 516.487561,432.23493 L516.895708,434.949997 C517.297943,435.068301 517.741577,435.25167 518.226624,435.500108 L520.320597,433.920756 C520.41524,433.837943 520.533542,433.796537 520.675507,433.796537 C520.805642,433.796537 520.929859,433.843858 521.048164,433.938501 C522.751743,435.511947 523.603521,436.458366 523.603521,436.777787 C523.603521,436.884261 523.562115,436.996648 523.479302,437.114952 C523.337337,437.304239 523.088902,437.623655 522.733989,438.073211 C522.379077,438.522767 522.112897,438.877674 521.93544,439.137943 C522.20754,439.705803 522.408654,440.190843 522.538789,440.593077 L525.23611,441.001224 C525.354414,441.024885 525.454971,441.086994 525.537784,441.187552 C525.620597,441.288111 525.662003,441.403456 525.662003,441.53359 Z M537.019145,450.99196 L537.019145,453.476335 C537.019145,453.665622 536.137792,453.848991 534.37506,454.026447 C534.233095,454.345868 534.055642,454.653454 533.842694,454.949215 C534.446045,456.286052 534.747716,457.102338 534.747716,457.398098 C534.747716,457.44542 534.724056,457.486826 534.676734,457.522317 C533.233424,458.362277 532.499949,458.78225 532.476288,458.78225 C532.381645,458.78225 532.109549,458.504239 531.659993,457.94821 C531.210438,457.39218 530.902851,456.989952 530.737226,456.741514 C530.500617,456.765174 530.323164,456.777005 530.20486,456.777005 C530.086555,456.777005 529.909102,456.765174 529.672493,456.741514 C529.506868,456.989952 529.199281,457.39218 528.749726,457.94821 C528.30017,458.504239 528.028074,458.78225 527.933431,458.78225 C527.90977,458.78225 527.176295,458.362277 525.732985,457.522317 C525.685663,457.486826 525.662003,457.44542 525.662003,457.398098 C525.662003,457.102338 525.963674,456.286052 526.567025,454.949215 C526.354077,454.653454 526.176624,454.345868 526.034659,454.026447 C524.271927,453.848991 523.390574,453.665622 523.390574,453.476335 L523.390574,450.99196 C523.390574,450.802674 524.271927,450.619305 526.034659,450.441849 C526.188454,450.098767 526.365908,449.791181 526.567025,449.519081 C525.963674,448.182244 525.662003,447.365958 525.662003,447.070197 C525.662003,447.022875 525.685663,446.98147 525.732985,446.945978 C525.780306,446.922318 525.987336,446.804015 526.354078,446.591068 C526.720821,446.37812 527.069813,446.177006 527.401065,445.98772 C527.732317,445.798433 527.90977,445.703791 527.933431,445.703791 C528.028074,445.703791 528.30017,445.978844 528.749726,446.528958 C529.199281,447.079073 529.506868,447.478343 529.672493,447.726782 C529.909102,447.703121 530.086555,447.691291 530.20486,447.691291 C530.323164,447.691291 530.500617,447.703121 530.737226,447.726782 C531.340577,446.886822 531.884768,446.224329 532.369815,445.739282 L532.476288,445.703791 C532.52361,445.703791 533.257084,446.117849 534.676734,446.945978 C534.724056,446.98147 534.747716,447.022875 534.747716,447.070197 C534.747716,447.365958 534.446045,448.182244 533.842694,449.519081 C534.043811,449.791181 534.221265,450.098767 534.37506,450.441849 C536.137792,450.619305 537.019145,450.802674 537.019145,450.99196 Z M537.019145,432.820533 L537.019145,435.304908 C537.019145,435.494194 536.137792,435.677563 534.37506,435.855019 C534.233095,436.17444 534.055642,436.482027 533.842694,436.777787 C534.446045,438.114624 534.747716,438.93091 534.747716,439.226671 C534.747716,439.273992 534.724056,439.315398 534.676734,439.35089 C533.233424,440.190849 532.499949,440.610822 532.476288,440.610822 C532.381645,440.610822 532.109549,440.332812 531.659993,439.776782 C531.210438,439.220753 530.902851,438.818525 530.737226,438.570086 C530.500617,438.593747 530.323164,438.605577 530.20486,438.605577 C530.086555,438.605577 529.909102,438.593747 529.672493,438.570086 C529.506868,438.818525 529.199281,439.220753 528.749726,439.776782 C528.30017,440.332812 528.028074,440.610822 527.933431,440.610822 C527.90977,440.610822 527.176295,440.190849 525.732985,439.35089 C525.685663,439.315398 525.662003,439.273992 525.662003,439.226671 C525.662003,438.93091 525.963674,438.114624 526.567025,436.777787 C526.354077,436.482027 526.176624,436.17444 526.034659,435.855019 C524.271927,435.677563 523.390574,435.494194 523.390574,435.304908 L523.390574,432.820533 C523.390574,432.631246 524.271927,432.447877 526.034659,432.270421 C526.188454,431.927339 526.365908,431.619753 526.567025,431.347653 C525.963674,430.010816 525.662003,429.19453 525.662003,428.89877 C525.662003,428.851448 525.685663,428.810042 525.732985,428.774551 C525.780306,428.75089 525.987336,428.632588 526.354078,428.41964 C526.720821,428.206693 527.069813,428.005579 527.401065,427.816292 C527.732317,427.627005 527.90977,427.532363 527.933431,427.532363 C528.028074,427.532363 528.30017,427.807416 528.749726,428.357531 C529.199281,428.907645 529.506868,429.306916 529.672493,429.555354 C529.909102,429.531694 530.086555,429.519863 530.20486,429.519863 C530.323164,429.519863 530.500617,429.531694 530.737226,429.555354 C531.340577,428.715395 531.884768,428.052901 532.369815,427.567854 L532.476288,427.532363 C532.52361,427.532363 533.257084,427.946422 534.676734,428.774551 C534.724056,428.810042 534.747716,428.851448 534.747716,428.89877 C534.747716,429.19453 534.446045,430.010816 533.842694,431.347653 C534.043811,431.619753 534.221265,431.927339 534.37506,432.270421 C536.137792,432.447877 537.019145,432.631246 537.019145,432.820533 Z" id="ï‚…-copy" fill="#E04733"></path>
+ <path d="M859.734507,544.858471 C857.81798,544.917623 856.250474,545.674758 855.031941,547.1299 L852.654039,547.1299 C851.683945,547.1299 850.867659,546.890337 850.205155,546.411205 C849.542652,545.932074 849.211405,545.231132 849.211405,544.30836 C849.211405,540.132223 849.94488,538.044186 851.411852,538.044186 C851.482834,538.044186 851.740142,538.168403 852.183782,538.416842 C852.627423,538.665281 853.204147,538.916673 853.913972,539.171027 C854.623797,539.425381 855.327696,539.552556 856.025691,539.552556 C856.818329,539.552556 857.605039,539.416509 858.385847,539.144409 C858.326695,539.582134 858.297119,539.972532 858.297119,540.315614 C858.297119,541.960042 858.776244,543.474313 859.734507,544.858471 Z M878.739975,556.162377 C878.739975,557.582027 878.308171,558.702942 877.444551,559.525156 C876.580931,560.34737 875.433398,560.75847 874.001917,560.75847 L858.49232,560.75847 C857.06084,560.75847 855.913307,560.34737 855.049686,559.525156 C854.186066,558.702942 853.754262,557.582027 853.754262,556.162377 C853.754262,555.535365 853.774965,554.92315 853.816372,554.325714 C853.857778,553.728278 853.94059,553.08353 854.064809,552.391451 C854.189028,551.699371 854.345779,551.057581 854.535066,550.46606 C854.724352,549.874539 854.978703,549.297815 855.298124,548.73587 C855.617545,548.173926 855.984282,547.694801 856.398347,547.298482 C856.812411,546.902163 857.318154,546.585704 857.91559,546.349096 C858.513026,546.112488 859.172562,545.994185 859.894217,545.994185 C860.012521,545.994185 860.266872,546.12136 860.657275,546.375714 C861.047679,546.630068 861.479483,546.913994 861.952699,547.2275 C862.425916,547.541006 863.058834,547.824932 863.851471,548.079286 C864.644109,548.33364 865.44265,548.460815 866.247119,548.460815 C867.051587,548.460815 867.850128,548.33364 868.642766,548.079286 C869.435404,547.824932 870.068321,547.541006 870.541538,547.2275 C871.014755,546.913994 871.446558,546.630068 871.836962,546.375714 C872.227366,546.12136 872.481716,545.994185 872.60002,545.994185 C873.321675,545.994185 873.981211,546.112488 874.578647,546.349096 C875.176083,546.585704 875.681826,546.902163 876.09589,547.298482 C876.509955,547.694801 876.876692,548.173926 877.196114,548.73587 C877.515535,549.297815 877.769885,549.874539 877.959172,550.46606 C878.148458,551.057581 878.305209,551.699371 878.429428,552.391451 C878.553648,553.08353 878.636459,553.728278 878.677866,554.325714 C878.719272,554.92315 878.739975,555.535365 878.739975,556.162377 Z M860.568548,533.501329 C860.568548,534.755353 860.124914,535.82599 859.237632,536.713271 C858.350351,537.600552 857.279715,538.044186 856.025691,538.044186 C854.771667,538.044186 853.70103,537.600552 852.813749,536.713271 C851.926468,535.82599 851.482834,534.755353 851.482834,533.501329 C851.482834,532.247305 851.926468,531.176668 852.813749,530.289387 C853.70103,529.402106 854.771667,528.958472 856.025691,528.958472 C857.279715,528.958472 858.350351,529.402106 859.237632,530.289387 C860.124914,531.176668 860.568548,532.247305 860.568548,533.501329 Z M873.061404,540.315614 C873.061404,542.19665 872.395953,543.802605 871.065031,545.133527 C869.73411,546.464449 868.128155,547.1299 866.247119,547.1299 C864.366083,547.1299 862.760128,546.464449 861.429206,545.133527 C860.098284,543.802605 859.432833,542.19665 859.432833,540.315614 C859.432833,538.434578 860.098284,536.828623 861.429206,535.497702 C862.760128,534.16678 864.366083,533.501329 866.247119,533.501329 C868.128155,533.501329 869.73411,534.16678 871.065031,535.497702 C872.395953,536.828623 873.061404,538.434578 873.061404,540.315614 Z M883.282832,544.30836 C883.282832,545.231132 882.951585,545.932074 882.289082,546.411205 C881.626579,546.890337 880.810292,547.1299 879.840198,547.1299 L877.462297,547.1299 C876.243764,545.674758 874.676257,544.917623 872.75973,544.858471 C873.717994,543.474313 874.197118,541.960042 874.197118,540.315614 C874.197118,539.972532 874.167543,539.582134 874.108391,539.144409 C874.889198,539.416509 875.675909,539.552556 876.468547,539.552556 C877.166541,539.552556 877.87044,539.425381 878.580265,539.171027 C879.29009,538.916673 879.866814,538.665281 880.310455,538.416842 C880.754096,538.168403 881.011403,538.044186 881.082386,538.044186 C882.549357,538.044186 883.282832,540.132223 883.282832,544.30836 Z M881.011404,533.501329 C881.011404,534.755353 880.56777,535.82599 879.680489,536.713271 C878.793207,537.600552 877.722571,538.044186 876.468547,538.044186 C875.214523,538.044186 874.143886,537.600552 873.256605,536.713271 C872.369324,535.82599 871.92569,534.755353 871.92569,533.501329 C871.92569,532.247305 872.369324,531.176668 873.256605,530.289387 C874.143886,529.402106 875.214523,528.958472 876.468547,528.958472 C877.722571,528.958472 878.793207,529.402106 879.680489,530.289387 C880.56777,531.176668 881.011404,532.247305 881.011404,533.501329 Z M920.88562,539.002445 C920.88562,539.475661 920.719997,539.877889 920.388745,540.209141 L905.127585,555.470301 C904.796334,555.801553 904.394106,555.967176 903.920889,555.967176 C903.447672,555.967176 903.045444,555.801553 902.714193,555.470301 L893.876916,546.633025 C893.545665,546.301773 893.380041,545.899545 893.380041,545.426328 C893.380041,544.953112 893.545665,544.550884 893.876916,544.219632 L896.290309,541.806239 C896.621561,541.474988 897.023789,541.309364 897.497005,541.309364 C897.970222,541.309364 898.37245,541.474988 898.703702,541.806239 L903.920889,547.041172 L915.56196,535.382356 C915.893211,535.051104 916.29544,534.885481 916.768656,534.885481 C917.241873,534.885481 917.644101,535.051104 917.975353,535.382356 L920.388745,537.795748 C920.719997,538.127 920.88562,538.529228 920.88562,539.002445 Z" id="--copy" fill="#E04733"></path>
+ <path d="M1045.7411,135.899363 C1043.82457,135.958515 1042.25707,136.715651 1041.03854,138.170792 L1038.66063,138.170792 C1037.69054,138.170792 1036.87425,137.931229 1036.21175,137.452098 C1035.54925,136.972966 1035.218,136.272024 1035.218,135.349252 C1035.218,131.173115 1035.95147,129.085078 1037.41845,129.085078 C1037.48943,129.085078 1037.74674,129.209295 1038.19038,129.457734 C1038.63402,129.706173 1039.21074,129.957566 1039.92057,130.211919 C1040.63039,130.466273 1041.33429,130.593448 1042.03229,130.593448 C1042.82492,130.593448 1043.61163,130.457401 1044.39244,130.185301 C1044.33329,130.623027 1044.30371,131.013424 1044.30371,131.356506 C1044.30371,133.000934 1044.78284,134.515205 1045.7411,135.899363 Z M1064.74657,147.203269 C1064.74657,148.622919 1064.31477,149.743834 1063.45115,150.566048 C1062.58753,151.388262 1061.43999,151.799362 1060.00851,151.799362 L1044.49891,151.799362 C1043.06743,151.799362 1041.9199,151.388262 1041.05628,150.566048 C1040.19266,149.743834 1039.76086,148.622919 1039.76086,147.203269 C1039.76086,146.576257 1039.78156,145.964042 1039.82297,145.366606 C1039.86437,144.76917 1039.94718,144.124422 1040.0714,143.432343 C1040.19562,142.740264 1040.35237,142.098473 1040.54166,141.506952 C1040.73095,140.915432 1040.9853,140.338707 1041.30472,139.776763 C1041.62414,139.214818 1041.99088,138.735693 1042.40494,138.339374 C1042.81901,137.943055 1043.32475,137.626597 1043.92218,137.389988 C1044.51962,137.15338 1045.17916,137.035078 1045.90081,137.035078 C1046.01912,137.035078 1046.27347,137.162253 1046.66387,137.416607 C1047.05427,137.67096 1047.48608,137.954886 1047.95929,138.268392 C1048.43251,138.581898 1049.06543,138.865824 1049.85807,139.120178 C1050.6507,139.374532 1051.44924,139.501707 1052.25371,139.501707 C1053.05818,139.501707 1053.85672,139.374532 1054.64936,139.120178 C1055.442,138.865824 1056.07492,138.581898 1056.54813,138.268392 C1057.02135,137.954886 1057.45315,137.67096 1057.84356,137.416607 C1058.23396,137.162253 1058.48831,137.035078 1058.60661,137.035078 C1059.32827,137.035078 1059.98781,137.15338 1060.58524,137.389988 C1061.18268,137.626597 1061.68842,137.943055 1062.10248,138.339374 C1062.51655,138.735693 1062.88329,139.214818 1063.20271,139.776763 C1063.52213,140.338707 1063.77648,140.915432 1063.96577,141.506952 C1064.15505,142.098473 1064.3118,142.740264 1064.43602,143.432343 C1064.56024,144.124422 1064.64305,144.76917 1064.68446,145.366606 C1064.72587,145.964042 1064.74657,146.576257 1064.74657,147.203269 Z M1046.57514,124.542221 C1046.57514,125.796245 1046.13151,126.866882 1045.24423,127.754163 C1044.35695,128.641444 1043.28631,129.085078 1042.03229,129.085078 C1040.77826,129.085078 1039.70762,128.641444 1038.82034,127.754163 C1037.93306,126.866882 1037.48943,125.796245 1037.48943,124.542221 C1037.48943,123.288197 1037.93306,122.21756 1038.82034,121.330279 C1039.70762,120.442998 1040.77826,119.999364 1042.03229,119.999364 C1043.28631,119.999364 1044.35695,120.442998 1045.24423,121.330279 C1046.13151,122.21756 1046.57514,123.288197 1046.57514,124.542221 Z M1059.068,131.356506 C1059.068,133.237543 1058.40255,134.843497 1057.07163,136.174419 C1055.7407,137.505341 1054.13475,138.170792 1052.25371,138.170792 C1050.37268,138.170792 1048.76672,137.505341 1047.4358,136.174419 C1046.10488,134.843497 1045.43943,133.237543 1045.43943,131.356506 C1045.43943,129.47547 1046.10488,127.869516 1047.4358,126.538594 C1048.76672,125.207672 1050.37268,124.542221 1052.25371,124.542221 C1054.13475,124.542221 1055.7407,125.207672 1057.07163,126.538594 C1058.40255,127.869516 1059.068,129.47547 1059.068,131.356506 Z M1069.28943,135.349252 C1069.28943,136.272024 1068.95818,136.972966 1068.29568,137.452098 C1067.63317,137.931229 1066.81689,138.170792 1065.84679,138.170792 L1063.46889,138.170792 C1062.25036,136.715651 1060.68285,135.958515 1058.76632,135.899363 C1059.72459,134.515205 1060.20371,133.000934 1060.20371,131.356506 C1060.20371,131.013424 1060.17414,130.623027 1060.11498,130.185301 C1060.89579,130.457401 1061.6825,130.593448 1062.47514,130.593448 C1063.17314,130.593448 1063.87703,130.466273 1064.58686,130.211919 C1065.29668,129.957566 1065.87341,129.706173 1066.31705,129.457734 C1066.76069,129.209295 1067.018,129.085078 1067.08898,129.085078 C1068.55595,129.085078 1069.28943,131.173115 1069.28943,135.349252 Z M1067.018,124.542221 C1067.018,125.796245 1066.57436,126.866882 1065.68708,127.754163 C1064.7998,128.641444 1063.72917,129.085078 1062.47514,129.085078 C1061.22112,129.085078 1060.15048,128.641444 1059.2632,127.754163 C1058.37592,126.866882 1057.93228,125.796245 1057.93228,124.542221 C1057.93228,123.288197 1058.37592,122.21756 1059.2632,121.330279 C1060.15048,120.442998 1061.22112,119.999364 1062.47514,119.999364 C1063.72917,119.999364 1064.7998,120.442998 1065.68708,121.330279 C1066.57436,122.21756 1067.018,123.288197 1067.018,124.542221 Z M1106.89221,130.043337 C1106.89221,130.516553 1106.72659,130.918782 1106.39534,131.250033 L1091.13418,146.511193 C1090.80293,146.842445 1090.4007,147.008068 1089.92748,147.008068 C1089.45427,147.008068 1089.05204,146.842445 1088.72079,146.511193 L1079.88351,137.673917 C1079.55226,137.342665 1079.38664,136.940437 1079.38664,136.46722 C1079.38664,135.994004 1079.55226,135.591776 1079.88351,135.260524 L1082.2969,132.847131 C1082.62816,132.51588 1083.03038,132.350256 1083.5036,132.350256 C1083.97682,132.350256 1084.37904,132.51588 1084.7103,132.847131 L1089.92748,138.082064 L1101.56855,126.423248 C1101.89981,126.091996 1102.30203,125.926373 1102.77525,125.926373 C1103.24847,125.926373 1103.6507,126.091996 1103.98195,126.423248 L1106.39534,128.83664 C1106.72659,129.167892 1106.89221,129.57012 1106.89221,130.043337 Z" id="--copy-2" fill="#E04733"></path>
+ <path d="M385.53174,544.858471 C383.615212,544.917623 382.047706,545.674758 380.829173,547.1299 L378.451271,547.1299 C377.481177,547.1299 376.664891,546.890337 376.002387,546.411205 C375.339884,545.932074 375.008638,545.231132 375.008638,544.30836 C375.008638,540.132223 375.742112,538.044186 377.209084,538.044186 C377.280066,538.044186 377.537374,538.168403 377.981015,538.416842 C378.424655,538.665281 379.001379,538.916673 379.711204,539.171027 C380.421029,539.425381 381.124928,539.552556 381.822923,539.552556 C382.615561,539.552556 383.402272,539.416509 384.183079,539.144409 C384.123927,539.582134 384.094351,539.972532 384.094351,540.315614 C384.094351,541.960042 384.573476,543.474313 385.53174,544.858471 Z M404.537207,556.162377 C404.537207,557.582027 404.105404,558.702942 403.241783,559.525156 C402.378163,560.34737 401.23063,560.75847 399.79915,560.75847 L384.289552,560.75847 C382.858072,560.75847 381.710539,560.34737 380.846918,559.525156 C379.983298,558.702942 379.551494,557.582027 379.551494,556.162377 C379.551494,555.535365 379.572197,554.92315 379.613604,554.325714 C379.65501,553.728278 379.737822,553.08353 379.862041,552.391451 C379.986261,551.699371 380.143011,551.057581 380.332298,550.46606 C380.521585,549.874539 380.775935,549.297815 381.095356,548.73587 C381.414777,548.173926 381.781515,547.694801 382.195579,547.298482 C382.609644,546.902163 383.115386,546.585704 383.712822,546.349096 C384.310258,546.112488 384.969794,545.994185 385.691449,545.994185 C385.809754,545.994185 386.064104,546.12136 386.454507,546.375714 C386.844911,546.630068 387.276715,546.913994 387.749932,547.2275 C388.223148,547.541006 388.856066,547.824932 389.648704,548.079286 C390.441342,548.33364 391.239883,548.460815 392.044351,548.460815 C392.848819,548.460815 393.64736,548.33364 394.439998,548.079286 C395.232636,547.824932 395.865554,547.541006 396.33877,547.2275 C396.811987,546.913994 397.243791,546.630068 397.634194,546.375714 C398.024598,546.12136 398.278948,545.994185 398.397252,545.994185 C399.118908,545.994185 399.778443,546.112488 400.375879,546.349096 C400.973315,546.585704 401.479058,546.902163 401.893123,547.298482 C402.307187,547.694801 402.673925,548.173926 402.993346,548.73587 C403.312767,549.297815 403.567117,549.874539 403.756404,550.46606 C403.945691,551.057581 404.102441,551.699371 404.226661,552.391451 C404.35088,553.08353 404.433692,553.728278 404.475098,554.325714 C404.516504,554.92315 404.537207,555.535365 404.537207,556.162377 Z M386.36578,533.501329 C386.36578,534.755353 385.922146,535.82599 385.034865,536.713271 C384.147584,537.600552 383.076947,538.044186 381.822923,538.044186 C380.568899,538.044186 379.498262,537.600552 378.610981,536.713271 C377.7237,535.82599 377.280066,534.755353 377.280066,533.501329 C377.280066,532.247305 377.7237,531.176668 378.610981,530.289387 C379.498262,529.402106 380.568899,528.958472 381.822923,528.958472 C383.076947,528.958472 384.147584,529.402106 385.034865,530.289387 C385.922146,531.176668 386.36578,532.247305 386.36578,533.501329 Z M398.858636,540.315614 C398.858636,542.19665 398.193185,543.802605 396.862264,545.133527 C395.531342,546.464449 393.925387,547.1299 392.044351,547.1299 C390.163315,547.1299 388.55736,546.464449 387.226438,545.133527 C385.895516,543.802605 385.230066,542.19665 385.230066,540.315614 C385.230066,538.434578 385.895516,536.828623 387.226438,535.497702 C388.55736,534.16678 390.163315,533.501329 392.044351,533.501329 C393.925387,533.501329 395.531342,534.16678 396.862264,535.497702 C398.193185,536.828623 398.858636,538.434578 398.858636,540.315614 Z M409.080064,544.30836 C409.080064,545.231132 408.748818,545.932074 408.086314,546.411205 C407.423811,546.890337 406.607525,547.1299 405.637431,547.1299 L403.259529,547.1299 C402.040996,545.674758 400.47349,544.917623 398.556962,544.858471 C399.515226,543.474313 399.99435,541.960042 399.99435,540.315614 C399.99435,539.972532 399.964775,539.582134 399.905623,539.144409 C400.68643,539.416509 401.473141,539.552556 402.265779,539.552556 C402.963773,539.552556 403.667673,539.425381 404.377498,539.171027 C405.087323,538.916673 405.664047,538.665281 406.107687,538.416842 C406.551328,538.168403 406.808635,538.044186 406.879618,538.044186 C408.34659,538.044186 409.080064,540.132223 409.080064,544.30836 Z M406.808636,533.501329 C406.808636,534.755353 406.365002,535.82599 405.477721,536.713271 C404.59044,537.600552 403.519803,538.044186 402.265779,538.044186 C401.011755,538.044186 399.941118,537.600552 399.053837,536.713271 C398.166556,535.82599 397.722922,534.755353 397.722922,533.501329 C397.722922,532.247305 398.166556,531.176668 399.053837,530.289387 C399.941118,529.402106 401.011755,528.958472 402.265779,528.958472 C403.519803,528.958472 404.59044,529.402106 405.477721,530.289387 C406.365002,531.176668 406.808636,532.247305 406.808636,533.501329 Z M440.063768,552.418069 C440.063768,552.891286 439.898145,553.293514 439.566893,553.624765 L437.1535,556.038158 C436.822249,556.36941 436.420021,556.535033 435.946804,556.535033 C435.473587,556.535033 435.071359,556.36941 434.740108,556.038158 L429.52292,550.820971 L424.305733,556.038158 C423.974481,556.36941 423.572253,556.535033 423.099037,556.535033 C422.62582,556.535033 422.223592,556.36941 421.89234,556.038158 L419.478948,553.624765 C419.147696,553.293514 418.982073,552.891286 418.982073,552.418069 C418.982073,551.944852 419.147696,551.542624 419.478948,551.211373 L424.696135,545.994185 L419.478948,540.776998 C419.147696,540.445747 418.982073,540.043518 418.982073,539.570302 C418.982073,539.097085 419.147696,538.694857 419.478948,538.363605 L421.89234,535.950213 C422.223592,535.618961 422.62582,535.453338 423.099037,535.453338 C423.572253,535.453338 423.974481,535.618961 424.305733,535.950213 L429.52292,541.1674 L434.740108,535.950213 C435.071359,535.618961 435.473587,535.453338 435.946804,535.453338 C436.420021,535.453338 436.822249,535.618961 437.1535,535.950213 L439.566893,538.363605 C439.898145,538.694857 440.063768,539.097085 440.063768,539.570302 C440.063768,540.043518 439.898145,540.445747 439.566893,540.776998 L434.349706,545.994185 L439.566893,551.211373 C439.898145,551.542624 440.063768,551.944852 440.063768,552.418069 Z" id="-ï€" fill="#E04733"></path>
+ <path d="M622.540142,544.858471 C620.623615,544.917623 619.056108,545.674758 617.837575,547.1299 L615.459674,547.1299 C614.48958,547.1299 613.673293,546.890337 613.01079,546.411205 C612.348287,545.932074 612.01704,545.231132 612.01704,544.30836 C612.01704,540.132223 612.750515,538.044186 614.217486,538.044186 C614.288469,538.044186 614.545777,538.168403 614.989417,538.416842 C615.433058,538.665281 616.009782,538.916673 616.719607,539.171027 C617.429432,539.425381 618.133331,539.552556 618.831325,539.552556 C619.623963,539.552556 620.410674,539.416509 621.191481,539.144409 C621.132329,539.582134 621.102754,539.972532 621.102754,540.315614 C621.102754,541.960042 621.581878,543.474313 622.540142,544.858471 Z M641.54561,556.162377 C641.54561,557.582027 641.113806,558.702942 640.250186,559.525156 C639.386565,560.34737 638.239032,560.75847 636.807552,560.75847 L621.297955,560.75847 C619.866474,560.75847 618.718941,560.34737 617.855321,559.525156 C616.991701,558.702942 616.559897,557.582027 616.559897,556.162377 C616.559897,555.535365 616.5806,554.92315 616.622006,554.325714 C616.663413,553.728278 616.746224,553.08353 616.870444,552.391451 C616.994663,551.699371 617.151414,551.057581 617.3407,550.46606 C617.529987,549.874539 617.784337,549.297815 618.103758,548.73587 C618.42318,548.173926 618.789917,547.694801 619.203982,547.298482 C619.618046,546.902163 620.123789,546.585704 620.721225,546.349096 C621.318661,546.112488 621.978197,545.994185 622.699852,545.994185 C622.818156,545.994185 623.072506,546.12136 623.46291,546.375714 C623.853314,546.630068 624.285117,546.913994 624.758334,547.2275 C625.231551,547.541006 625.864468,547.824932 626.657106,548.079286 C627.449744,548.33364 628.248285,548.460815 629.052753,548.460815 C629.857222,548.460815 630.655763,548.33364 631.448401,548.079286 C632.241038,547.824932 632.873956,547.541006 633.347173,547.2275 C633.820389,546.913994 634.252193,546.630068 634.642597,546.375714 C635.033001,546.12136 635.287351,545.994185 635.405655,545.994185 C636.12731,545.994185 636.786846,546.112488 637.384282,546.349096 C637.981718,546.585704 638.487461,546.902163 638.901525,547.298482 C639.31559,547.694801 639.682327,548.173926 640.001748,548.73587 C640.32117,549.297815 640.57552,549.874539 640.764806,550.46606 C640.954093,551.057581 641.110844,551.699371 641.235063,552.391451 C641.359282,553.08353 641.442094,553.728278 641.4835,554.325714 C641.524907,554.92315 641.54561,555.535365 641.54561,556.162377 Z M623.374182,533.501329 C623.374182,534.755353 622.930548,535.82599 622.043267,536.713271 C621.155986,537.600552 620.085349,538.044186 618.831325,538.044186 C617.577301,538.044186 616.506665,537.600552 615.619384,536.713271 C614.732102,535.82599 614.288468,534.755353 614.288468,533.501329 C614.288468,532.247305 614.732102,531.176668 615.619384,530.289387 C616.506665,529.402106 617.577301,528.958472 618.831325,528.958472 C620.085349,528.958472 621.155986,529.402106 622.043267,530.289387 C622.930548,531.176668 623.374182,532.247305 623.374182,533.501329 Z M635.867039,540.315614 C635.867039,542.19665 635.201588,543.802605 633.870666,545.133527 C632.539744,546.464449 630.933789,547.1299 629.052753,547.1299 C627.171717,547.1299 625.565762,546.464449 624.234841,545.133527 C622.903919,543.802605 622.238468,542.19665 622.238468,540.315614 C622.238468,538.434578 622.903919,536.828623 624.234841,535.497702 C625.565762,534.16678 627.171717,533.501329 629.052753,533.501329 C630.933789,533.501329 632.539744,534.16678 633.870666,535.497702 C635.201588,536.828623 635.867039,538.434578 635.867039,540.315614 Z M646.088467,544.30836 C646.088467,545.231132 645.75722,545.932074 645.094717,546.411205 C644.432214,546.890337 643.615927,547.1299 642.645833,547.1299 L640.267931,547.1299 C639.049399,545.674758 637.481892,544.917623 635.565365,544.858471 C636.523628,543.474313 637.002753,541.960042 637.002753,540.315614 C637.002753,539.972532 636.973177,539.582134 636.914025,539.144409 C637.694833,539.416509 638.481544,539.552556 639.274181,539.552556 C639.972176,539.552556 640.676075,539.425381 641.3859,539.171027 C642.095725,538.916673 642.672449,538.665281 643.11609,538.416842 C643.55973,538.168403 643.817038,538.044186 643.88802,538.044186 C645.354992,538.044186 646.088467,540.132223 646.088467,544.30836 Z M643.817038,533.501329 C643.817038,534.755353 643.373404,535.82599 642.486123,536.713271 C641.598842,537.600552 640.528205,538.044186 639.274181,538.044186 C638.020157,538.044186 636.949521,537.600552 636.06224,536.713271 C635.174958,535.82599 634.731325,534.755353 634.731325,533.501329 C634.731325,532.247305 635.174958,531.176668 636.06224,530.289387 C636.949521,529.402106 638.020157,528.958472 639.274181,528.958472 C640.528205,528.958472 641.598842,529.402106 642.486123,530.289387 C643.373404,531.176668 643.817038,532.247305 643.817038,533.501329 Z M677.07217,552.418069 C677.07217,552.891286 676.906547,553.293514 676.575295,553.624765 L674.161903,556.038158 C673.830651,556.36941 673.428423,556.535033 672.955206,556.535033 C672.48199,556.535033 672.079762,556.36941 671.74851,556.038158 L666.531323,550.820971 L661.314136,556.038158 C660.982884,556.36941 660.580656,556.535033 660.107439,556.535033 C659.634223,556.535033 659.231994,556.36941 658.900743,556.038158 L656.48735,553.624765 C656.156098,553.293514 655.990475,552.891286 655.990475,552.418069 C655.990475,551.944852 656.156098,551.542624 656.48735,551.211373 L661.704537,545.994185 L656.48735,540.776998 C656.156098,540.445747 655.990475,540.043518 655.990475,539.570302 C655.990475,539.097085 656.156098,538.694857 656.48735,538.363605 L658.900743,535.950213 C659.231994,535.618961 659.634223,535.453338 660.107439,535.453338 C660.580656,535.453338 660.982884,535.618961 661.314136,535.950213 L666.531323,541.1674 L671.74851,535.950213 C672.079762,535.618961 672.48199,535.453338 672.955206,535.453338 C673.428423,535.453338 673.830651,535.618961 674.161903,535.950213 L676.575295,538.363605 C676.906547,538.694857 677.07217,539.097085 677.07217,539.570302 C677.07217,540.043518 676.906547,540.445747 676.575295,540.776998 L671.358108,545.994185 L676.575295,551.211373 C676.906547,551.542624 677.07217,551.944852 677.07217,552.418069 Z" id="-ï€-copy" fill="#E04733"></path>
+ <path d="M756.856155,443.148434 C756.856155,441.89441 756.412521,440.823773 755.52524,439.936492 C754.637959,439.049211 753.567322,438.605577 752.313298,438.605577 C751.059274,438.605577 749.988638,439.049211 749.101357,439.936492 C748.214075,440.823773 747.770441,441.89441 747.770441,443.148434 C747.770441,444.402458 748.214075,445.473095 749.101357,446.360376 C749.988638,447.247657 751.059274,447.691291 752.313298,447.691291 C753.567322,447.691291 754.637959,447.247657 755.52524,446.360376 C756.412521,445.473095 756.856155,444.402458 756.856155,443.148434 Z M770.484726,452.234148 C770.484726,451.618966 770.259951,451.086605 769.810396,450.63705 C769.36084,450.187494 768.828479,449.962719 768.213297,449.962719 C767.598116,449.962719 767.065755,450.187494 766.616199,450.63705 C766.166644,451.086605 765.941869,451.618966 765.941869,452.234148 C765.941869,452.86116 766.163686,453.396478 766.607327,453.840119 C767.050967,454.283759 767.586285,454.505576 768.213297,454.505576 C768.840309,454.505576 769.375628,454.283759 769.819268,453.840119 C770.262909,453.396478 770.484726,452.86116 770.484726,452.234148 Z M770.484726,434.06272 C770.484726,433.447539 770.259951,432.915178 769.810396,432.465622 C769.36084,432.016066 768.828479,431.791292 768.213297,431.791292 C767.598116,431.791292 767.065755,432.016066 766.616199,432.465622 C766.166644,432.915178 765.941869,433.447539 765.941869,434.06272 C765.941869,434.689732 766.163686,435.22505 766.607327,435.668691 C767.050967,436.112332 767.586285,436.334149 768.213297,436.334149 C768.840309,436.334149 769.375628,436.112332 769.819268,435.668691 C770.262909,435.22505 770.484726,434.689732 770.484726,434.06272 Z M763.670441,441.53359 L763.670441,444.816514 C763.670441,444.934818 763.629035,445.050163 763.546222,445.162552 C763.463409,445.274941 763.368767,445.33705 763.262293,445.34888 L760.511735,445.774773 C760.381601,446.188838 760.192317,446.638387 759.943878,447.123434 C760.346112,447.691294 760.878473,448.371532 761.540976,449.16417 C761.623789,449.282474 761.665195,449.400777 761.665195,449.519081 C761.665195,449.661046 761.623789,449.773433 761.540976,449.856246 C761.268877,450.211159 760.780879,450.740562 760.07697,451.444471 C759.37306,452.148381 758.908723,452.500331 758.683945,452.500331 C758.553811,452.500331 758.429593,452.458925 758.311289,452.376112 L756.270553,450.779014 C755.832827,451.003792 755.377363,451.18716 754.904146,451.329125 C754.774012,452.60681 754.637964,453.523654 754.495999,454.079683 C754.413186,454.363613 754.235733,454.505576 753.963633,454.505576 L750.662964,454.505576 C750.532829,454.505576 750.414527,454.461213 750.308053,454.372485 C750.201579,454.283757 750.142428,454.180242 750.130598,454.061938 L749.72245,451.346871 C749.320216,451.228567 748.876582,451.045198 748.391535,450.796759 L746.297562,452.376112 C746.214749,452.458925 746.096447,452.500331 745.942651,452.500331 C745.812517,452.500331 745.688299,452.45301 745.569995,452.358367 C743.866415,450.784921 743.014638,449.838502 743.014638,449.519081 C743.014638,449.412607 743.056044,449.30022 743.138857,449.181916 C743.257161,449.01629 743.499681,448.702789 743.866424,448.241402 C744.233167,447.780016 744.511177,447.419194 744.700464,447.158925 C744.428364,446.638387 744.221335,446.153347 744.07937,445.703791 L741.382049,445.277898 C741.263745,445.266068 741.163188,445.209874 741.080375,445.109316 C740.997562,445.008757 740.956156,444.893412 740.956156,444.763278 L740.956156,441.480354 C740.956156,441.36205 740.997562,441.246705 741.080375,441.134316 C741.163188,441.021927 741.25783,440.959818 741.364303,440.947988 L744.114861,440.522095 C744.244996,440.10803 744.43428,439.658481 744.682718,439.173434 C744.280484,438.605574 743.748124,437.925336 743.08562,437.132698 C743.002807,437.002563 742.961401,436.884261 742.961401,436.777787 C742.961401,436.635822 743.002807,436.51752 743.08562,436.422876 C743.345889,436.067964 743.830929,435.541518 744.540754,434.843524 C745.250579,434.145529 745.717873,433.796537 745.942651,433.796537 C746.072786,433.796537 746.197003,433.837943 746.315308,433.920756 L748.356044,435.517854 C748.758278,435.304907 749.213742,435.115623 749.72245,434.949997 C749.852585,433.672312 749.988633,432.761384 750.130598,432.217185 C750.21341,431.933255 750.390864,431.791292 750.662964,431.791292 L753.963633,431.791292 C754.093768,431.791292 754.21207,431.835655 754.318544,431.924383 C754.425017,432.013111 754.484169,432.116626 754.495999,432.23493 L754.904146,434.949997 C755.306381,435.068301 755.750014,435.25167 756.235061,435.500108 L758.329035,433.920756 C758.423678,433.837943 758.54198,433.796537 758.683945,433.796537 C758.81408,433.796537 758.938297,433.843858 759.056602,433.938501 C760.760181,435.511947 761.611959,436.458366 761.611959,436.777787 C761.611959,436.884261 761.570553,436.996648 761.48774,437.114952 C761.345775,437.304239 761.09734,437.623655 760.742427,438.073211 C760.387515,438.522767 760.121334,438.877674 759.943878,439.137943 C760.215978,439.705803 760.417092,440.190843 760.547226,440.593077 L763.244548,441.001224 C763.362852,441.024885 763.463409,441.086994 763.546222,441.187552 C763.629035,441.288111 763.670441,441.403456 763.670441,441.53359 Z M775.027583,450.99196 L775.027583,453.476335 C775.027583,453.665622 774.14623,453.848991 772.383498,454.026447 C772.241533,454.345868 772.06408,454.653454 771.851132,454.949215 C772.454483,456.286052 772.756154,457.102338 772.756154,457.398098 C772.756154,457.44542 772.732494,457.486826 772.685172,457.522317 C771.241861,458.362277 770.508387,458.78225 770.484726,458.78225 C770.390083,458.78225 770.117987,458.504239 769.668431,457.94821 C769.218876,457.39218 768.911289,456.989952 768.745663,456.741514 C768.509055,456.765174 768.331602,456.777005 768.213297,456.777005 C768.094993,456.777005 767.91754,456.765174 767.680931,456.741514 C767.515306,456.989952 767.207719,457.39218 766.758164,457.94821 C766.308608,458.504239 766.036512,458.78225 765.941869,458.78225 C765.918208,458.78225 765.184733,458.362277 763.741423,457.522317 C763.694101,457.486826 763.670441,457.44542 763.670441,457.398098 C763.670441,457.102338 763.972112,456.286052 764.575463,454.949215 C764.362515,454.653454 764.185062,454.345868 764.043097,454.026447 C762.280365,453.848991 761.399012,453.665622 761.399012,453.476335 L761.399012,450.99196 C761.399012,450.802674 762.280365,450.619305 764.043097,450.441849 C764.196892,450.098767 764.374346,449.791181 764.575463,449.519081 C763.972112,448.182244 763.670441,447.365958 763.670441,447.070197 C763.670441,447.022875 763.694101,446.98147 763.741423,446.945978 C763.788744,446.922318 763.995774,446.804015 764.362516,446.591068 C764.729259,446.37812 765.078251,446.177006 765.409503,445.98772 C765.740755,445.798433 765.918208,445.703791 765.941869,445.703791 C766.036512,445.703791 766.308608,445.978844 766.758164,446.528958 C767.207719,447.079073 767.515306,447.478343 767.680931,447.726782 C767.91754,447.703121 768.094993,447.691291 768.213297,447.691291 C768.331602,447.691291 768.509055,447.703121 768.745663,447.726782 C769.349015,446.886822 769.893206,446.224329 770.378253,445.739282 L770.484726,445.703791 C770.532048,445.703791 771.265522,446.117849 772.685172,446.945978 C772.732494,446.98147 772.756154,447.022875 772.756154,447.070197 C772.756154,447.365958 772.454483,448.182244 771.851132,449.519081 C772.052249,449.791181 772.229703,450.098767 772.383498,450.441849 C774.14623,450.619305 775.027583,450.802674 775.027583,450.99196 Z M775.027583,432.820533 L775.027583,435.304908 C775.027583,435.494194 774.14623,435.677563 772.383498,435.855019 C772.241533,436.17444 772.06408,436.482027 771.851132,436.777787 C772.454483,438.114624 772.756154,438.93091 772.756154,439.226671 C772.756154,439.273992 772.732494,439.315398 772.685172,439.35089 C771.241861,440.190849 770.508387,440.610822 770.484726,440.610822 C770.390083,440.610822 770.117987,440.332812 769.668431,439.776782 C769.218876,439.220753 768.911289,438.818525 768.745663,438.570086 C768.509055,438.593747 768.331602,438.605577 768.213297,438.605577 C768.094993,438.605577 767.91754,438.593747 767.680931,438.570086 C767.515306,438.818525 767.207719,439.220753 766.758164,439.776782 C766.308608,440.332812 766.036512,440.610822 765.941869,440.610822 C765.918208,440.610822 765.184733,440.190849 763.741423,439.35089 C763.694101,439.315398 763.670441,439.273992 763.670441,439.226671 C763.670441,438.93091 763.972112,438.114624 764.575463,436.777787 C764.362515,436.482027 764.185062,436.17444 764.043097,435.855019 C762.280365,435.677563 761.399012,435.494194 761.399012,435.304908 L761.399012,432.820533 C761.399012,432.631246 762.280365,432.447877 764.043097,432.270421 C764.196892,431.927339 764.374346,431.619753 764.575463,431.347653 C763.972112,430.010816 763.670441,429.19453 763.670441,428.89877 C763.670441,428.851448 763.694101,428.810042 763.741423,428.774551 C763.788744,428.75089 763.995774,428.632588 764.362516,428.41964 C764.729259,428.206693 765.078251,428.005579 765.409503,427.816292 C765.740755,427.627005 765.918208,427.532363 765.941869,427.532363 C766.036512,427.532363 766.308608,427.807416 766.758164,428.357531 C767.207719,428.907645 767.515306,429.306916 767.680931,429.555354 C767.91754,429.531694 768.094993,429.519863 768.213297,429.519863 C768.331602,429.519863 768.509055,429.531694 768.745663,429.555354 C769.349015,428.715395 769.893206,428.052901 770.378253,427.567854 L770.484726,427.532363 C770.532048,427.532363 771.265522,427.946422 772.685172,428.774551 C772.732494,428.810042 772.756154,428.851448 772.756154,428.89877 C772.756154,429.19453 772.454483,430.010816 771.851132,431.347653 C772.052249,431.619753 772.229703,431.927339 772.383498,432.270421 C774.14623,432.447877 775.027583,432.631246 775.027583,432.820533 Z" id="ï‚…-copy-2" fill="#E04733"></path>
+ <path d="M885.860729,188.873341 C885.860729,187.619317 885.417095,186.54868 884.529814,185.661399 C883.642532,184.774118 882.571896,184.330484 881.317872,184.330484 C880.063848,184.330484 878.993211,184.774118 878.10593,185.661399 C877.218649,186.54868 876.775015,187.619317 876.775015,188.873341 C876.775015,190.127365 877.218649,191.198002 878.10593,192.085283 C878.993211,192.972564 880.063848,193.416198 881.317872,193.416198 C882.571896,193.416198 883.642532,192.972564 884.529814,192.085283 C885.417095,191.198002 885.860729,190.127365 885.860729,188.873341 Z M899.489299,197.959055 C899.489299,197.343873 899.264525,196.811512 898.814969,196.361957 C898.365413,195.912401 897.833053,195.687626 897.217871,195.687626 C896.602689,195.687626 896.070329,195.912401 895.620773,196.361957 C895.171217,196.811512 894.946442,197.343873 894.946442,197.959055 C894.946442,198.586067 895.168259,199.121385 895.6119,199.565026 C896.055541,200.008666 896.590859,200.230483 897.217871,200.230483 C897.844883,200.230483 898.380201,200.008666 898.823842,199.565026 C899.267482,199.121385 899.489299,198.586067 899.489299,197.959055 Z M899.489299,179.787627 C899.489299,179.172446 899.264525,178.640085 898.814969,178.190529 C898.365413,177.740973 897.833053,177.516199 897.217871,177.516199 C896.602689,177.516199 896.070329,177.740973 895.620773,178.190529 C895.171217,178.640085 894.946442,179.172446 894.946442,179.787627 C894.946442,180.414639 895.168259,180.949958 895.6119,181.393598 C896.055541,181.837239 896.590859,182.059056 897.217871,182.059056 C897.844883,182.059056 898.380201,181.837239 898.823842,181.393598 C899.267482,180.949958 899.489299,180.414639 899.489299,179.787627 Z M892.675014,187.258497 L892.675014,190.541421 C892.675014,190.659725 892.633608,190.77507 892.550795,190.887459 C892.467982,190.999848 892.37334,191.061957 892.266867,191.073787 L889.516309,191.49968 C889.386174,191.913745 889.19689,192.363294 888.948452,192.848341 C889.350686,193.416201 889.883047,194.096439 890.54555,194.889077 C890.628363,195.007381 890.669769,195.125684 890.669769,195.243988 C890.669769,195.385953 890.628363,195.49834 890.54555,195.581153 C890.27345,195.936066 889.785453,196.465469 889.081543,197.169379 C888.377634,197.873288 887.913297,198.225238 887.688519,198.225238 C887.558384,198.225238 887.434167,198.183832 887.315863,198.101019 L885.275126,196.503921 C884.837401,196.728699 884.381937,196.912068 883.90872,197.054033 C883.778585,198.331717 883.642538,199.248561 883.500573,199.80459 C883.41776,200.08852 883.240306,200.230483 882.968207,200.230483 L879.667537,200.230483 C879.537403,200.230483 879.4191,200.18612 879.312626,200.097392 C879.206153,200.008664 879.147001,199.905149 879.135171,199.786845 L878.727024,197.071778 C878.32479,196.953474 877.881156,196.770105 877.396109,196.521667 L875.302136,198.101019 C875.219323,198.183832 875.10102,198.225238 874.947225,198.225238 C874.81709,198.225238 874.692873,198.177917 874.574569,198.083274 C872.870989,196.509828 872.019212,195.563409 872.019212,195.243988 C872.019212,195.137514 872.060617,195.025127 872.14343,194.906823 C872.261734,194.741197 872.504254,194.427696 872.870997,193.96631 C873.23774,193.504923 873.515751,193.144101 873.705037,192.883832 C873.432938,192.363294 873.225909,191.878254 873.083944,191.428698 L870.386622,191.002805 C870.268318,190.990975 870.167761,190.934781 870.084948,190.834223 C870.002135,190.733664 869.96073,190.618319 869.96073,190.488185 L869.96073,187.205261 C869.96073,187.086957 870.002135,186.971612 870.084948,186.859223 C870.167761,186.746834 870.262403,186.684725 870.368877,186.672895 L873.119435,186.247002 C873.249569,185.832937 873.438853,185.383388 873.687292,184.898341 C873.285058,184.330481 872.752697,183.650243 872.090194,182.857605 C872.007381,182.72747 871.965975,182.609168 871.965975,182.502694 C871.965975,182.360729 872.007381,182.242427 872.090194,182.147783 C872.350463,181.792871 872.835503,181.266425 873.545328,180.568431 C874.255153,179.870436 874.722447,179.521444 874.947225,179.521444 C875.077359,179.521444 875.201577,179.56285 875.319881,179.645663 L877.360618,181.242761 C877.762852,181.029814 878.218316,180.84053 878.727024,180.674904 C878.857158,179.397219 878.993206,178.486291 879.135171,177.942092 C879.217984,177.658162 879.395438,177.516199 879.667537,177.516199 L882.968207,177.516199 C883.098341,177.516199 883.216643,177.560562 883.323117,177.64929 C883.429591,177.738018 883.488742,177.841533 883.500573,177.959837 L883.90872,180.674904 C884.310954,180.793208 884.754588,180.976577 885.239635,181.225016 L887.333608,179.645663 C887.428251,179.56285 887.546554,179.521444 887.688519,179.521444 C887.818653,179.521444 887.942871,179.568765 888.061175,179.663408 C889.764755,181.236854 890.616532,182.183273 890.616532,182.502694 C890.616532,182.609168 890.575126,182.721555 890.492313,182.839859 C890.350348,183.029146 890.101913,183.348562 889.747001,183.798118 C889.392088,184.247674 889.125908,184.602581 888.948452,184.86285 C889.220551,185.43071 889.421665,185.91575 889.5518,186.317984 L892.249121,186.726131 C892.367425,186.749792 892.467982,186.811901 892.550795,186.912459 C892.633608,187.013018 892.675014,187.128363 892.675014,187.258497 Z M904.032156,196.716867 L904.032156,199.201242 C904.032156,199.390529 903.150804,199.573898 901.388072,199.751354 C901.246107,200.070775 901.068653,200.378361 900.855706,200.674122 C901.459057,202.010959 901.760728,202.827245 901.760728,203.123005 C901.760728,203.170327 901.737067,203.211733 901.689746,203.247224 C900.246435,204.087184 899.51296,204.507157 899.489299,204.507157 C899.394656,204.507157 899.122561,204.229147 898.673005,203.673117 C898.223449,203.117087 897.915863,202.714859 897.750237,202.466421 C897.513629,202.490081 897.336175,202.501912 897.217871,202.501912 C897.099567,202.501912 896.922113,202.490081 896.685505,202.466421 C896.519879,202.714859 896.212293,203.117087 895.762737,203.673117 C895.313181,204.229147 895.041086,204.507157 894.946442,204.507157 C894.922782,204.507157 894.189307,204.087184 892.745996,203.247224 C892.698675,203.211733 892.675014,203.170327 892.675014,203.123005 C892.675014,202.827245 892.976685,202.010959 893.580036,200.674122 C893.367089,200.378361 893.189635,200.070775 893.04767,199.751354 C891.284938,199.573898 890.403586,199.390529 890.403586,199.201242 L890.403586,196.716867 C890.403586,196.527581 891.284938,196.344212 893.04767,196.166756 C893.201466,195.823674 893.378919,195.516088 893.580036,195.243988 C892.976685,193.907151 892.675014,193.090865 892.675014,192.795104 C892.675014,192.747783 892.698675,192.706377 892.745996,192.670885 C892.793318,192.647225 893.000347,192.528922 893.36709,192.315975 C893.733833,192.103027 894.082825,191.901913 894.414076,191.712627 C894.745328,191.52334 894.922782,191.428698 894.946442,191.428698 C895.041086,191.428698 895.313181,191.703751 895.762737,192.253865 C896.212293,192.80398 896.519879,193.20325 896.685505,193.451689 C896.922113,193.428028 897.099567,193.416198 897.217871,193.416198 C897.336175,193.416198 897.513629,193.428028 897.750237,193.451689 C898.353588,192.611729 898.897779,191.949236 899.382826,191.464189 L899.489299,191.428698 C899.536621,191.428698 900.270096,191.842756 901.689746,192.670885 C901.737067,192.706377 901.760728,192.747783 901.760728,192.795104 C901.760728,193.090865 901.459057,193.907151 900.855706,195.243988 C901.056823,195.516088 901.234276,195.823674 901.388072,196.166756 C903.150804,196.344212 904.032156,196.527581 904.032156,196.716867 Z M904.032156,178.54544 L904.032156,181.029815 C904.032156,181.219101 903.150804,181.40247 901.388072,181.579926 C901.246107,181.899347 901.068653,182.206934 900.855706,182.502694 C901.459057,183.839531 901.760728,184.655817 901.760728,184.951578 C901.760728,184.9989 901.737067,185.040305 901.689746,185.075797 C900.246435,185.915756 899.51296,186.33573 899.489299,186.33573 C899.394656,186.33573 899.122561,186.057719 898.673005,185.501689 C898.223449,184.94566 897.915863,184.543432 897.750237,184.294993 C897.513629,184.318654 897.336175,184.330484 897.217871,184.330484 C897.099567,184.330484 896.922113,184.318654 896.685505,184.294993 C896.519879,184.543432 896.212293,184.94566 895.762737,185.501689 C895.313181,186.057719 895.041086,186.33573 894.946442,186.33573 C894.922782,186.33573 894.189307,185.915756 892.745996,185.075797 C892.698675,185.040305 892.675014,184.9989 892.675014,184.951578 C892.675014,184.655817 892.976685,183.839531 893.580036,182.502694 C893.367089,182.206934 893.189635,181.899347 893.04767,181.579926 C891.284938,181.40247 890.403586,181.219101 890.403586,181.029815 L890.403586,178.54544 C890.403586,178.356153 891.284938,178.172784 893.04767,177.995328 C893.201466,177.652246 893.378919,177.34466 893.580036,177.07256 C892.976685,175.735723 892.675014,174.919437 892.675014,174.623677 C892.675014,174.576355 892.698675,174.534949 892.745996,174.499458 C892.793318,174.475797 893.000347,174.357495 893.36709,174.144547 C893.733833,173.9316 894.082825,173.730486 894.414076,173.541199 C894.745328,173.351912 894.922782,173.25727 894.946442,173.25727 C895.041086,173.25727 895.313181,173.532323 895.762737,174.082438 C896.212293,174.632552 896.519879,175.031823 896.685505,175.280261 C896.922113,175.256601 897.099567,175.24477 897.217871,175.24477 C897.336175,175.24477 897.513629,175.256601 897.750237,175.280261 C898.353588,174.440302 898.897779,173.777809 899.382826,173.292762 L899.489299,173.25727 C899.536621,173.25727 900.270096,173.671329 901.689746,174.499458 C901.737067,174.534949 901.760728,174.576355 901.760728,174.623677 C901.760728,174.919437 901.459057,175.735723 900.855706,177.07256 C901.056823,177.34466 901.234276,177.652246 901.388072,177.995328 C903.150804,178.172784 904.032156,178.356153 904.032156,178.54544 Z" id="ï‚…-copy-3" fill="#E04733"></path>
+ </g>
+ </g>
+ </g>
+</svg> \ No newline at end of file
diff --git a/doc/ci/review_apps/img/review_apps_preview_in_mr.png b/doc/ci/review_apps/img/review_apps_preview_in_mr.png
index 7d0923f198f..3e6506a6a3a 100644
--- a/doc/ci/review_apps/img/review_apps_preview_in_mr.png
+++ b/doc/ci/review_apps/img/review_apps_preview_in_mr.png
Binary files differ
diff --git a/doc/ci/review_apps/index.md b/doc/ci/review_apps/index.md
index 1b17f6ac5ea..64be011008e 100644
--- a/doc/ci/review_apps/index.md
+++ b/doc/ci/review_apps/index.md
@@ -1,95 +1,94 @@
-# Getting started with Review Apps
+# Review Apps
-> - [Introduced][ce-21971] in GitLab 8.12. Further additions were made in GitLab
-> 8.13 and 8.14.
-> - Inspired by [Heroku's Review Apps][heroku-apps] which itself was inspired by
-> [Fourchette].
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/21971) in GitLab 8.12. Further additions were made in GitLab 8.13 and 8.14.
+> - Inspired by [Heroku's Review Apps](https://devcenter.heroku.com/articles/github-integration-review-apps), which itself was inspired by [Fourchette](https://github.com/rainforestapp/fourchette).
-The basis of Review Apps is the [dynamic environments] which allow you to create
-a new environment (dynamically) for each one of your branches.
+For a video introduction to Review Apps, see [8.14 Webcast: Review Apps & Time Tracking Beta (EE) - GitLab Release](https://www.youtube.com/watch?v=CteZol_7pxo).
-A Review App can then be visible as a link when you visit the [merge request]
-relevant to the branch. That way, you are able to see live all changes introduced
-by the merge request changes. Reviewing anything, from performance to interface
-changes, becomes much easier with a live environment and as such, Review Apps
-can make a huge impact on your development flow.
+## Overview
-They mostly make sense to be used with web applications, but you can use them
-any way you'd like.
+Review Apps are a collaboration tool that takes the hard work out of providing an environment to showcase product changes.
-## Overview
+Review Apps:
+
+- Provide an automatic live preview of changes made in a feature branch by spinning up a dynamic environment for your merge requests.
+- Allow designers and product manages to see your changes without needing to check out your branch and run your changes in a sandbox environment.
+- Are fully integrated with the [GitLab DevOps LifeCycle](../../README.md#complete-devops-with-gitlab).
+- Allow you to deploy your changes wherever you want.
+
+![Review Apps Workflow](img/continuous-delivery-review-apps.svg)
+
+Reviewing anything, from performance to interface changes, becomes much easier with a live environment and so Review Apps can make a large impact on your development flow.
-Simply put, a Review App is a mapping of a branch with an environment as there
-is a 1:1 relation between them.
+## What are Review Apps?
-Here's an example of what it looks like when viewing a merge request with a
-dynamically set environment.
+A Review App is a mapping of a branch with an [environment](../environments.md). The following is an example of a merge request with an environment set dynamically.
![Review App in merge request](img/review_apps_preview_in_mr.png)
-In the image above you can see that the `add-new-line` branch was successfully
-built and deployed under a dynamic environment and can be previewed with an
-also dynamically URL.
+In this example, you can see a branch was:
+
+- Successfully built.
+- Deployed under a dynamic environment that can be reached by clicking on the **View app** button.
+
+## How do Review Apps work?
+
+The basis of Review Apps in GitLab is [dynamic environments](../environments.md#dynamic-environments), which allow you to dynamically create a new environment for each branch.
+
+Access to the Review App is made available as a link on the [merge request](../../user/project/merge_requests.md) relevant to the branch. Review Apps enable you to review all changes proposed by the merge request in live environment.
-The details of the Review Apps implementation depend widely on your real
-technology stack and on your deployment process. The simplest case is to
-deploy a simple static HTML website, but it will not be that straightforward
-when your app is using a database for example. To make a branch be deployed
-on a temporary instance and booting up this instance with all required software
-and services automatically on the fly is not a trivial task. However, it is
-doable, especially if you use Docker, or at least a configuration management
-tool like Chef, Puppet, Ansible or Salt.
+## Use cases
-## Prerequisites
+Some supported use cases include the:
-To get a better understanding of Review Apps, you must first learn how
-environments and deployments work. The following docs will help you grasp that
-knowledge:
+- Simple case of deploying a simple static HTML website.
+- More complicated case of an application that uses a database. Deploying a branch on a temporary instance and booting up this instance with all required software and services automatically on the fly is not a trivial task. However, it is possible, especially if you use Docker or a configuration management tool like Chef, Puppet, Ansible, or Salt.
-1. First, learn about [environments][] and their role in the development workflow.
-1. Then make a small stop to learn about [CI variables][variables] and how they
- can be used in your CI jobs.
-1. Next, explore the [`environment` syntax][yaml-env] as defined in `.gitlab-ci.yml`.
- This will be your primary reference when you are finally comfortable with
- how environments work.
-1. Additionally, find out about [manual actions][] and how you can use them to
- deploy to critical environments like production with the push of a button.
-1. And as a last step, follow the [example tutorials](#examples) which will
- guide you step by step to set up the infrastructure and make use of
- Review Apps.
+Review Apps usually make sense with web applications, but you can use them any way you'd like.
-## Configuration
+## Implementing Review Apps
-The configuration of Review apps depends on your technology stack and your
-infrastructure. Read the [dynamic environments] documentation to understand
-how to define and create them.
+Implementing Review Apps depends on your:
-## Creating and destroying Review Apps
+- Technology stack.
+- Deployment process.
-The creation and destruction of a Review App is defined in `.gitlab-ci.yml`
-at a job level under the `environment` keyword.
+### Prerequisite Knowledge
-Check the [environments] documentation how to do so.
+To get a better understanding of Review Apps, review documentation on how environments and deployments work. Before you implement your own Review Apps:
-## A simple workflow
+1. Learn about [environments](../environments.md) and their role in the development workflow.
+1. Learn about [CI variables](../variables/README.md) and how they can be used in your CI jobs.
+1. Explore the [`environment` syntax](../yaml/README.md#environment) as defined in `.gitlab-ci.yml`. This will become a primary reference.
+1. Additionally, find out about [manual actions](../environments.md#manual-actions) and how you can use them to deploy to critical environments like production with the push of a button.
+1. Follow the [example tutorials](#examples). These will guide you through setting up infrastructure and using Review Apps.
-The process of adding Review Apps in your workflow would look like:
+### Configuring dynamic environments
+
+Configuring Review Apps dynamic environments depends on your technology stack and infrastructure.
+
+For more information, see [dynamic environments](../environments.md#dynamic-environments) documentation to understand how to define and create them.
+
+### Creating and destroying Review Apps
+
+Creating and destroying Review Apps is defined in `.gitlab-ci.yml` at a job level under the `environment` keyword.
+
+For more information, see [Introduction to environments and deployments](../environments.md).
+
+### Adding Review Apps to your workflow
+
+The process of adding Review Apps in your workflow is as follows:
1. Set up the infrastructure to host and deploy the Review Apps.
-1. [Install][install-runner] and [configure][conf-runner] a Runner that does
- the deployment.
-1. Set up a job in `.gitlab-ci.yml` that uses the predefined
- [predefined CI environment variable][variables] `${CI_COMMIT_REF_NAME}` to
- create dynamic environments and restrict it to run only on branches.
-1. Optionally set a job that [manually stops][manual-env] the Review Apps.
+1. [Install](https://docs.gitlab.com/runner/install/) and [configure](https://docs.gitlab.com/runner/commands/) a Runner to do deployment.
+1. Set up a job in `.gitlab-ci.yml` that uses the predefined [predefined CI environment variable](../variables/README.md) `${CI_COMMIT_REF_NAME}` to create dynamic environments and restrict it to run only on branches.
+1. Optionally, set a job that [manually stops](../environments.md#stopping-an-environment) the Review Apps.
-From there on, you would follow the branched Git flow:
+After adding Review Apps to your workflow, you follow the branched Git flow. That is:
-1. Push a branch and let the Runner deploy the Review App based on the `script`
- definition of the dynamic environment job.
-1. Wait for the Runner to build and/or deploy your web app.
-1. Click on the link that's present in the MR related to the branch and see the
- changes live.
+1. Push a branch and let the Runner deploy the Review App based on the `script` definition of the dynamic environment job.
+1. Wait for the Runner to build and deploy your web application.
+1. Click on the link that provided in the merge request related to the branch to see the changes live.
## Limitations
@@ -97,27 +96,9 @@ Check the [environments limitations](../environments.md#limitations).
## Examples
-A list of examples used with Review Apps can be found below:
-
-- [Use with NGINX][app-nginx] - Use NGINX and the shell executor of GitLab Runner
- to deploy a simple HTML website.
-
-And below is a soon to be added examples list:
-
-- Use with Amazon S3
-- Use on Heroku with dpl
-- Use with OpenShift/kubernetes
-
-[app-nginx]: https://gitlab.com/gitlab-examples/review-apps-nginx
-[ce-21971]: https://gitlab.com/gitlab-org/gitlab-ce/issues/21971
-[dynamic environments]: ../environments.md#dynamic-environments
-[environments]: ../environments.md
-[fourchette]: https://github.com/rainforestapp/fourchette
-[heroku-apps]: https://devcenter.heroku.com/articles/github-integration-review-apps
-[manual actions]: ../environments.md#manual-actions
-[merge request]: ../../user/project/merge_requests.md
-[variables]: ../variables/README.md
-[yaml-env]: ../yaml/README.md#environment
-[install-runner]: https://docs.gitlab.com/runner/install/
-[conf-runner]: https://docs.gitlab.com/runner/commands/
-[manual-env]: ../environments.md#stopping-an-environment
+The following are example projects that use Review Apps with:
+
+- [NGINX](https://gitlab.com/gitlab-examples/review-apps-nginx).
+- [OpenShift](https://gitlab.com/gitlab-examples/review-apps-openshift).
+
+See also the video [Demo: Cloud Native Development with GitLab](https://www.youtube.com/watch?v=jfIyQEwrocw), which includes a Review Apps example.
diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md
index 7859d2ec631..9c9ea651678 100644
--- a/doc/ci/runners/README.md
+++ b/doc/ci/runners/README.md
@@ -29,7 +29,7 @@ are:
- **Specific Runners** are useful for jobs that have special requirements or for
projects with a specific demand. If a job has certain requirements, you can set
up the specific Runner with this in mind, while not having to do this for all
- Runners. For example, if you want to deploy a certain project, you can setup
+ Runners. For example, if you want to deploy a certain project, you can set up
a specific Runner to have the right credentials for this. The [usage of tags](#using-tags)
may be useful in this case. Specific Runners process jobs using a [FIFO] queue.
- **Group Runners** are useful when you have multiple projects under one group
@@ -138,9 +138,9 @@ project without requiring your authorization, so use it with caution.
An admin can enable/disable a specific Runner for projects:
1. Navigate to **Admin > Runners**
-2. Find the Runner you wish to enable/disable
-3. Click edit on the Runner
-4. Click **Enable** or **Disable** on the project
+1. Find the Runner you wish to enable/disable
+1. Click edit on the Runner
+1. Click **Enable** or **Disable** on the project
## Protected Runners
@@ -222,7 +222,7 @@ should keep in mind.
### Using tags
-You must setup a Runner to be able to run all the different types of jobs
+You must set up a Runner to be able to run all the different types of jobs
that it may encounter on the projects it's shared over. This would be
problematic for large amounts of projects, if it wasn't for tags.
@@ -298,7 +298,7 @@ and using more secure [Runner Executors](https://docs.gitlab.com/runner/executor
### Forks
Whenever a project is forked, it copies the settings of the jobs that relate
-to it. This means that if you have shared Runners setup for a project and
+to it. This means that if you have shared Runners set up for a project and
someone forks that project, the shared Runners will also serve jobs of this
project.
@@ -312,7 +312,7 @@ We're always looking for contributions that can mitigate these
If you think that registration token for a Project was revealed, you should
reset them. It's recommended because such token can be used to register another
-Runner to thi Project. It may be next used to obtain the values of secret
+Runner to the Project. It may be next used to obtain the values of secret
variables or clone the project code, that normally may be unavailable for the
attacker.
diff --git a/doc/ci/services/mysql.md b/doc/ci/services/mysql.md
index 338368dbbc9..b76f9618fc9 100644
--- a/doc/ci/services/mysql.md
+++ b/doc/ci/services/mysql.md
@@ -31,7 +31,7 @@ Database: el_duderino
```
If you are wondering why we used `mysql` for the `Host`, read more at
-[How is service linked to the job](../docker/using_docker_images.md#how-is-service-linked-to-the-job).
+[How services are linked to the job](../docker/using_docker_images.md#how-services-are-linked-to-the-job).
You can also use any other docker image available on [Docker Hub][hub-mysql].
For example, to use MySQL 5.5 the service becomes `mysql:5.5`.
diff --git a/doc/ci/services/redis.md b/doc/ci/services/redis.md
index 554c321fd0c..36f71427ae7 100644
--- a/doc/ci/services/redis.md
+++ b/doc/ci/services/redis.md
@@ -43,7 +43,7 @@ sudo apt-get install redis-server
Verify that you can connect to the server with the `gitlab-runner` user:
```bash
-# Try connecting the the Redis server
+# Try connecting the Redis server
sudo -u gitlab-runner -H redis-cli
# Quit the session
diff --git a/doc/ci/triggers/README.md b/doc/ci/triggers/README.md
index cf92d90ba30..bffb0121603 100644
--- a/doc/ci/triggers/README.md
+++ b/doc/ci/triggers/README.md
@@ -2,7 +2,7 @@
> **Notes**:
>
-> - [Introduced][ci-229] in GitLab CE 7.14.
+> - [Introduced](https://about.gitlab.com/2015/08/22/gitlab-7-14-released/) in GitLab 7.14.
> - GitLab 8.12 has a completely redesigned job permissions system. Read all
> about the [new model and its implications](../../user/project/new_ci_build_permissions_model.md#job-triggers).
@@ -154,10 +154,10 @@ This information is also exposed in the UI.
Using trigger variables can be proven useful for a variety of reasons:
-* Identifiable jobs. Since the variable is exposed in the UI you can know
+- Identifiable jobs. Since the variable is exposed in the UI you can know
why the rebuild was triggered if you pass a variable that explains the
purpose.
-* Conditional job processing. You can have conditional jobs that run whenever
+- Conditional job processing. You can have conditional jobs that run whenever
a certain variable is present.
Consider the following `.gitlab-ci.yml` where we set three
@@ -221,7 +221,6 @@ removed with one of the future versions of GitLab. You are advised to
[take ownership](#taking-ownership) of any legacy triggers.
[ee-2017]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2017
-[ci-229]: https://gitlab.com/gitlab-org/gitlab-ci/merge_requests/229
[ee]: https://about.gitlab.com/pricing/
[variables]: ../variables/README.md
[predef]: ../variables/README.md#predefined-variables-environment-variables
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index f11949da64e..bdbcf8c9435 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -65,6 +65,8 @@ future GitLab releases.**
| **CI_JOB_NAME** | 9.0 | 0.5 | The name of the job as defined in `.gitlab-ci.yml` |
| **CI_JOB_STAGE** | 9.0 | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` |
| **CI_JOB_TOKEN** | 9.0 | 1.2 | Token used for authenticating with the [GitLab Container Registry][registry] and downloading [dependent repositories][dependent-repositories] |
+| **CI_NODE_INDEX** | 11.5 | all | Index of the job in the job set. If the job is not parallelized, this variable is not set. |
+| **CI_NODE_TOTAL** | 11.5 | all | Total number of instances of this job running in parallel. If the job is not parallelized, this variable is set to `1`. |
| **CI_JOB_URL** | 11.1 | 0.5 | Job details URL |
| **CI_REPOSITORY_URL** | 9.0 | all | The URL to clone the Git repository |
| **CI_RUNNER_DESCRIPTION** | 8.10 | 0.5 | The description of the runner as saved in GitLab |
@@ -94,6 +96,9 @@ future GitLab releases.**
| **CI_SERVER_NAME** | all | all | The name of CI server that is used to coordinate jobs |
| **CI_SERVER_REVISION** | all | all | GitLab revision that is used to schedule jobs |
| **CI_SERVER_VERSION** | all | all | GitLab version that is used to schedule jobs |
+| **CI_SERVER_VERSION_MAJOR** | 11.4 | all | GitLab version major component |
+| **CI_SERVER_VERSION_MINOR** | 11.4 | all | GitLab version minor component |
+| **CI_SERVER_VERSION_PATCH** | 11.4 | all | GitLab version patch component |
| **CI_SHARED_ENVIRONMENT** | all | 10.1 | Marks that the job is executed in a shared environment (something that is persisted across CI invocations like `shell` or `ssh` executor). If the environment is shared, it is set to true, otherwise it is not defined at all. |
| **GET_SOURCES_ATTEMPTS** | 8.15 | 1.9 | Number of attempts to fetch sources running a job |
| **GITLAB_CI** | all | all | Mark that job is executed in GitLab CI environment |
@@ -194,7 +199,7 @@ Likewise, group-level variables can be added by going to your group's
**Settings > CI/CD**, then finding the section called **Variables**.
Any variables of [subgroups] will be inherited recursively.
-![Variables](img/secret_variables.png)
+![Variables](img/variables.png)
Once you set them, they will be available for all subsequent pipelines. You can also
[protect your variables](#protected-variables).
@@ -323,6 +328,12 @@ Running on runner-8a2f473d-project-1796893-concurrent-0 via runner-8a2f473d-mach
++ CI_SERVER_NAME='GitLab CI'
++ export CI_SERVER_VERSION=
++ CI_SERVER_VERSION=
+++ export CI_SERVER_VERSION_MAJOR=
+++ CI_SERVER_VERSION_MAJOR=
+++ export CI_SERVER_VERSION_MINOR=
+++ CI_SERVER_VERSION_MINOR=
+++ export CI_SERVER_VERSION_PATCH=
+++ CI_SERVER_VERSION_PATCH=
++ export CI_SERVER_REVISION=
++ CI_SERVER_REVISION=
++ export GITLAB_CI=true
@@ -468,6 +479,9 @@ export CI_SERVER="yes"
export CI_SERVER_NAME="GitLab"
export CI_SERVER_REVISION="70606bf"
export CI_SERVER_VERSION="8.9.0"
+export CI_SERVER_VERSION_MAJOR="8"
+export CI_SERVER_VERSION_MINOR="9"
+export CI_SERVER_VERSION_PATCH="0"
export GITLAB_USER_ID="42"
export GITLAB_USER_EMAIL="user@example.com"
export CI_REGISTRY_USER="gitlab-ci-token"
diff --git a/doc/ci/variables/img/secret_variables.png b/doc/ci/variables/img/secret_variables.png
deleted file mode 100644
index 3c1aa361dc2..00000000000
--- a/doc/ci/variables/img/secret_variables.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/variables/img/variables.png b/doc/ci/variables/img/variables.png
new file mode 100644
index 00000000000..d2dc99bbac0
--- /dev/null
+++ b/doc/ci/variables/img/variables.png
Binary files differ
diff --git a/doc/ci/variables/where_variables_can_be_used.md b/doc/ci/variables/where_variables_can_be_used.md
index b0d2ea6484d..1d98e8426fe 100644
--- a/doc/ci/variables/where_variables_can_be_used.md
+++ b/doc/ci/variables/where_variables_can_be_used.md
@@ -17,8 +17,8 @@ There are two places defined variables can be used. On the:
| Definition | Can be expanded? | Expansion place | Description |
|--------------------------------------|-------------------|-----------------|--------------|
-| `environment:url` | yes | GitLab | The variable expansion is made by GitLab's [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism).<ul><li>**Supported:** all variables defined for a job (project/group variables, variables from `.gitlab-ci.yml`, variables from triggers, variables from pipeline schedules)</li><li>**Not suported:** variables defined in Runner's `config.toml` and variables created in job's `script`</li></ul> |
-| `environment:name` | yes | GitLab | Similar to `environment:url`, but the variables expansion **doesn't support**: <ul><li>variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`)</li><li>any other variables related to environment (currently only `CI_ENVIRONMENT_URL`)</li><li>[persisted variables](#persisted-variables)</li></ul> |
+| `environment:url` | yes | GitLab | The variable expansion is made by GitLab's [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism).<ul><li>Supported: all variables defined for a job (project/group variables, variables from `.gitlab-ci.yml`, variables from triggers, variables from pipeline schedules)</li><li>Not supported: variables defined in Runner's `config.toml` and variables created in job's `script`</li></ul> |
+| `environment:name` | yes | GitLab | Similar to `environment:url`, but the variables expansion doesn't support: <ul><li>variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`)</li><li>any other variables related to environment (currently only `CI_ENVIRONMENT_URL`)</li><li>[persisted variables](#persisted-variables)</li></ul> |
| `variables` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
| `image` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
| `services:[]` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
@@ -26,7 +26,7 @@ There are two places defined variables can be used. On the:
| `cache:key` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) |
| `artifacts:name` | yes | Runner | The variable expansion is made by GitLab Runner's shell environment |
| `script`, `before_script`, `after_script` | yes | Script execution shell | The variable expansion is made by the [execution shell environment](#execution-shell-environment) |
-| `only:variables:[]`, `except:variables:[]` | no | n/a | The variable must be in the form of `$variable`.<br/>**Not supported:**<ul><li>variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`)</li><li>any other variables related to environment (currently only `CI_ENVIRONMENT_URL`)</li><li>[persisted variables](#persisted-variables)</li></ul> |
+| `only:variables:[]`, `except:variables:[]` | no | n/a | The variable must be in the form of `$variable`.<br/>Not supported:<ul><li>variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`)</li><li>any other variables related to environment (currently only `CI_ENVIRONMENT_URL`)</li><li>[persisted variables](#persisted-variables)</li></ul> |
### `config.toml` file
@@ -55,9 +55,9 @@ since the expansion is done in GitLab before any Runner will get the job.
### GitLab Runner internal variable expansion mechanism
-- **Supported:** project/group variables, `.gitlab-ci.yml` variables, `config.toml` variables, and
+- Supported: project/group variables, `.gitlab-ci.yml` variables, `config.toml` variables, and
variables from triggers, pipeline schedules, and manual pipelines.
-- **Not supported:** variables defined inside of scripts (e.g., `export MY_VARIABLE="test"`).
+- Not supported: variables defined inside of scripts (e.g., `export MY_VARIABLE="test"`).
The Runner uses Go's `os.Expand()` method for variable expansion. It means that it will handle
only variables defined as `$variable` and `${variable}`. What's also important, is that
@@ -73,7 +73,7 @@ by bash/sh (leaving empty strings or some values depending whether the variables
defined or not), but will not work with Windows' cmd/PowerShell, since these shells
are using a different variables syntax.
-**Supported:**
+Supported:
- The `script` may use all available variables that are default for the shell (e.g., `$PATH` which
should be present in all bash/sh shells) and all variables defined by GitLab CI/CD (project/group variables,
@@ -106,7 +106,9 @@ The following variables are known as "persisted":
They are:
-- **Supported** for all definitions as [described in the table](#gitlab-ci-yml-file) where the "Expansion place" is "Runner".
-- **Not supported:**
- - By the definitions [described in the table](#gitlab-ci-yml-file) where the "Expansion place" is "GitLab".
+- Supported for definitions where the ["Expansion place"](#gitlab-ci-yml-file) is:
+ - Runner.
+ - Script execution shell.
+- Not supported:
+ - For definitions where the ["Expansion place"](#gitlab-ci-yml-file) is GitLab.
- In the `only` and `except` [variables expressions](README.md#variables-expressions).
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 31a065bc196..af7e41db443 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -74,7 +74,8 @@ A job is defined by a list of parameters that define the job behavior.
| after_script | no | Override a set of commands that are executed after job |
| environment | no | Defines a name of environment to which deployment is done by this job |
| coverage | no | Define code coverage settings for a given job |
-| retry | no | Define how many times a job can be auto-retried in case of a failure |
+| retry | no | Define when and how many times a job can be auto-retried in case of a failure |
+| parallel | no | Defines how many instances of a job should be run in parallel |
### `extends`
@@ -102,10 +103,13 @@ rspec:
- $RSPEC
```
-In the example above, the `rspec` job is going to inherit from the `.tests`
-template job. GitLab will perform a reverse deep merge, which means that it will
-merge the `rspec` contents into `.tests` recursively, and this is going to result in
-the following `rspec` job:
+In the example above, the `rspec` job inherits from the `.tests` template job.
+GitLab will perform a reverse deep merge based on the keys. GitLab will:
+
+- Merge the `rspec` contents into `.tests` recursively.
+- Not merge the values of the keys.
+
+This results in the following `rspec` job:
```yaml
rspec:
@@ -118,6 +122,11 @@ rspec:
- $RSPEC
```
+NOTE: **Note:**
+Note that `script: rake test` has been overwritten by `script: rake rspec`.
+
+If you do want to include the `rake test`, have a look at [before_script-and-after_script](#before_script-and-after_script).
+
`.tests` in this example is a [hidden key](#hidden-keys-jobs), but it's
possible to inherit from regular jobs as well.
@@ -188,7 +197,7 @@ used for time of the job. The configuration of this feature is covered in
## `before_script` and `after_script`
-> Introduced in GitLab 8.7 and requires Gitlab Runner v1.2
+> Introduced in GitLab 8.7 and requires GitLab Runner v1.2
`before_script` is used to define the command that should be run before all
jobs, including deploy jobs, but after the restoration of [artifacts](#artifacts).
@@ -325,7 +334,7 @@ There are a few rules that apply to the usage of job policy:
* `only` and `except` are inclusive. If both `only` and `except` are defined
in a job specification, the ref is filtered by `only` and `except`.
-* `only` and `except` allow the use of regular expressions.
+* `only` and `except` allow the use of regular expressions (using [Ruby regexp syntax](https://ruby-doc.org/core/Regexp.html)).
* `only` and `except` allow to specify a repository path to filter jobs for
forks.
@@ -387,9 +396,11 @@ except master.
> `refs` and `kubernetes` policies introduced in GitLab 10.0
>
> `variables` policy introduced in 10.7
+>
+> `changes` policy [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/19232) in 11.4
CAUTION: **Warning:**
-This an _alpha_ feature, and it it subject to change at any time without
+This an _alpha_ feature, and it is subject to change at any time without
prior notice!
Since GitLab 10.0 it is possible to define a more elaborate only/except job
@@ -398,10 +409,15 @@ policy configuration.
GitLab now supports both, simple and complex strategies, so it is possible to
use an array and a hash configuration scheme.
-Three keys are now available: `refs`, `kubernetes` and `variables`.
+Four keys are now available: `refs`, `kubernetes` and `variables` and `changes`.
+
+### `refs` and `kubernetes`
+
Refs strategy equals to simplified only/except configuration, whereas
kubernetes strategy accepts only `active` keyword.
+### `only:variables`
+
`variables` keyword is used to define variables expressions. In other words
you can use predefined variables / project / group or
environment-scoped variables to define an expression GitLab is going to
@@ -445,6 +461,50 @@ end-to-end:
Learn more about variables expressions on [a separate page][variables-expressions].
+### `only:changes`
+
+Using `changes` keyword with `only` or `except` makes it possible to define if
+a job should be created based on files modified by a git push event.
+
+For example:
+
+```yaml
+docker build:
+ script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
+ only:
+ changes:
+ - Dockerfile
+ - docker/scripts/*
+ - dockerfiles/**/*
+ - more_scripts/*.{rb,py,sh}
+```
+
+In the scenario above, if you are pushing multiple commits to GitLab to an
+existing branch, GitLab creates and triggers `docker build` job, provided that
+one of the commits contains changes to either:
+
+- The `Dockerfile` file.
+- Any of the files inside `docker/scripts/` directory.
+- Any of the files and subfolders inside `dockerfiles` directory.
+- Any of the files with `rb`, `py`, `sh` extensions inside `more_scripts` directory.
+
+CAUTION: **Warning:**
+There are some caveats when using this feature with new branches and tags. See
+the section below.
+
+#### Using `changes` with new branches and tags
+
+If you are pushing a **new** branch or a **new** tag to GitLab, the policy
+always evaluates to true and GitLab will create a job. This feature is not
+connected with merge requests yet, and because GitLab is creating pipelines
+before an user can create a merge request we don't know a target branch at
+this point.
+
+Without a target branch, it is not possible to know what the common ancestor is,
+thus we always create a job in that case. This feature works best for stable
+branches like `master` because in that case GitLab uses the previous commit
+that is present in a branch to compare against the latest SHA that was pushed.
+
## `tags`
`tags` is used to select specific Runners from the list of all Runners that are
@@ -492,6 +552,7 @@ osx job:
`allow_failure` is used when you want to allow a job to fail without impacting
the rest of the CI suite. Failed jobs don't contribute to the commit status.
+The default value is `false`.
When enabled and the job fails, the pipeline will be successful/green for all
intents and purposes, but a "CI build passed with warnings" message will be
@@ -617,6 +678,42 @@ user wants to trigger an action. In other words, in order to trigger a manual
action assigned to a branch that the pipeline is running for, user needs to
have ability to merge to this branch.
+### `when:delayed`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21767) in GitLab 11.4.
+
+Delayed job are for executing scripts after a certain period.
+This is useful if you want to avoid jobs entering `pending` state immediately.
+
+You can set the period with `start_in` key. The value of `start_in` key is an elapsed time in seconds, unless a unit is
+provided. `start_in` key must be less than or equal to one hour. Examples of valid values include:
+
+- `10 seconds`
+- `30 minutes`
+- `1 hour`
+
+When there is a delayed job in a stage, the pipeline will not progress until the delayed job has finished.
+This means this keyword can also be used for inserting delays between different stages.
+
+The timer of a delayed job starts immediately after the previous stage has completed.
+Similar to other types of jobs, a delayed job's timer will not start unless the previous stage passed.
+
+The following example creates a job named `timed rollout 10%` that is executed 30 minutes after the previous stage has completed:
+
+```yaml
+timed rollout 10%:
+ stage: deploy
+ script: echo 'Rolling out 10% ...'
+ when: delayed
+ start_in: 30 minutes
+```
+
+You can stop the active timer of a delayed job by clicking the **Unschedule** button.
+This job will never be executed in the future unless you execute the job manually.
+
+You can start a delayed job immediately by clicking the **Play** button.
+GitLab runner will pick your job soon and start the job.
+
## `environment`
> **Notes:**
@@ -717,7 +814,7 @@ deploy to production:
> defined, GitLab will automatically trigger a stop action when the associated
> branch is deleted.
-Closing (stoping) environments can be achieved with the `on_stop` keyword defined under
+Closing (stopping) environments can be achieved with the `on_stop` keyword defined under
`environment`. It declares a different job that runs in order to close
the environment.
@@ -1200,13 +1297,17 @@ GitLab 11.2. Requires GitLab Runner 11.2 and above.
The `reports` keyword is used for collecting test reports from jobs and
exposing them in GitLab's UI (merge requests, pipeline views). Read how to use
-this with [JUnit reports](#artifacts-reports-junit).
+this with [JUnit reports](#artifactsreportsjunit).
NOTE: **Note:**
The test reports are collected regardless of the job results (success or failure).
You can use [`artifacts:expire_in`](#artifacts-expire_in) to set up an expiration
date for their artifacts.
+NOTE: **Note:**
+If you also want the ability to browse the report output files, include the
+[`artifacts:paths`](#artifactspaths) keyword.
+
#### `artifacts:reports:junit`
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/20390) in
@@ -1215,8 +1316,9 @@ GitLab 11.2. Requires GitLab Runner 11.2 and above.
The `junit` report collects [JUnit XML files](https://www.ibm.com/support/knowledgecenter/en/SSQ2R2_14.1.0/com.ibm.rsar.analysis.codereview.cobol.doc/topics/cac_useresults_junit.html)
as artifacts. Although JUnit was originally developed in Java, there are many
[third party ports](https://en.wikipedia.org/wiki/JUnit#Ports) for other
-languages like Javascript, Python, Ruby, etc.
+languages like JavaScript, Python, Ruby, etc.
+See [JUnit test reports](../junit_test_reports.md) for more details and examples.
Below is an example of collecting a JUnit XML file from Ruby's RSpec test tool:
```yaml
@@ -1233,8 +1335,6 @@ rspec:
The collected JUnit reports will be uploaded to GitLab as an artifact and will
be automatically shown in merge requests.
-For more examples, see [JUnit test reports](../junit_test_reports.md).
-
NOTE: **Note:**
In case the JUnit tool you use exports to multiple XML files, you can specify
multiple test report paths within a single job and they will be automatically
@@ -1242,6 +1342,81 @@ concatenated into a single file. Use a filename pattern (`junit: rspec-*.xml`),
an array of filenames (`junit: [rspec-1.xml, rspec-2.xml, rspec-3.xml]`), or a
combination thereof (`junit: [rspec.xml, test-results/TEST-*.xml]`).
+#### `artifacts:reports:codequality` **[STARTER]**
+
+> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
+
+The `codequality` report collects [CodeQuality issues](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html)
+as artifacts.
+
+The collected Code Quality report will be uploaded to GitLab as an artifact and will
+be automatically shown in merge requests.
+
+#### `artifacts:reports:sast` **[ULTIMATE]**
+
+> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
+
+The `sast` report collects [SAST vulnerabilities](https://docs.gitlab.com/ee/user/project/merge_requests/sast.html)
+as artifacts.
+
+The collected SAST report will be uploaded to GitLab as an artifact and will
+be automatically shown in merge requests, pipeline view and provide data for security
+dashboards.
+
+#### `artifacts:reports:dependency_scanning` **[ULTIMATE]**
+
+> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
+
+The `dependency_scanning` report collects [Dependency Scanning vulnerabilities](https://docs.gitlab.com/ee/user/project/merge_requests/dependency_scanning.html)
+as artifacts.
+
+The collected Dependency Scanning report will be uploaded to GitLab as an artifact and will
+be automatically shown in merge requests, pipeline view and provide data for security
+dashboards.
+
+#### `artifacts:reports:container_scanning` **[ULTIMATE]**
+
+> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
+
+The `container_scanning` report collects [Container Scanning vulnerabilities](https://docs.gitlab.com/ee/user/project/merge_requests/container_scanning.html)
+as artifacts.
+
+The collected Container Scanning report will be uploaded to GitLab as an artifact and will
+be automatically shown in merge requests, pipeline view and provide data for security
+dashboards.
+
+#### `artifacts:reports:dast` **[ULTIMATE]**
+
+> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
+
+The `dast` report collects [DAST vulnerabilities](https://docs.gitlab.com/ee/user/project/merge_requests/dast.html)
+as artifacts.
+
+The collected DAST report will be uploaded to GitLab as an artifact and will
+be automatically shown in merge requests, pipeline view and provide data for security
+dashboards.
+
+#### `artifacts:reports:license_management` **[ULTIMATE]**
+
+> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
+
+The `license_management` report collects [Licenses](https://docs.gitlab.com/ee/user/project/merge_requests/license_management.html)
+as artifacts.
+
+The collected License Management report will be uploaded to GitLab as an artifact and will
+be automatically shown in merge requests, pipeline view and provide data for security
+dashboards.
+
+#### `artifacts:reports:performance` **[PREMIUM]**
+
+> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
+
+The `performance` report collects [Performance metrics](https://docs.gitlab.com/ee//user/project/merge_requests/browser_performance_testing.html)
+as artifacts.
+
+The collected Performance report will be uploaded to GitLab as an artifact and will
+be automatically shown in merge requests.
+
## `dependencies`
> Introduced in GitLab 8.6 and GitLab Runner v1.1.1.
@@ -1338,18 +1513,20 @@ job1:
## `retry`
> [Introduced][ce-12909] in GitLab 9.5.
+> [Behaviour expanded](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21758)
+> in GitLab 11.5 to control on which failures to retry.
`retry` allows you to configure how many times a job is going to be retried in
case of a failure.
-When a job fails, and has `retry` configured it is going to be processed again
+When a job fails and has `retry` configured, it is going to be processed again
up to the amount of times specified by the `retry` keyword.
If `retry` is set to 2, and a job succeeds in a second run (first retry), it won't be retried
again. `retry` value has to be a positive integer, equal or larger than 0, but
lower or equal to 2 (two retries maximum, three runs in total).
-A simple example:
+A simple example to retry in all failure cases:
```yaml
test:
@@ -1357,12 +1534,84 @@ test:
retry: 2
```
+By default, a job will be retried on all failure cases. To have a better control
+on which failures to retry, `retry` can be a hash with the following keys:
+
+- `max`: The maximum number of retries.
+- `when`: The failure cases to retry.
+
+To retry only runner system failures at maximum two times:
+
+```yaml
+test:
+ script: rspec
+ retry:
+ max: 2
+ when: runner_system_failure
+```
+
+If there is another failure, other than a runner system failure, the job will
+not be retried.
+
+To retry on multiple failure cases, `when` can also be an array of failures:
+
+```yaml
+test:
+ script: rspec
+ retry:
+ max: 2
+ when:
+ - runner_system_failure
+ - stuck_or_timeout_failure
+```
+
+Possible values for `when` are:
+
+<!--
+ Please make sure to update `RETRY_WHEN_IN_DOCUMENTATION` array in
+ `spec/lib/gitlab/ci/config/entry/retry_spec.rb` if you change any of
+ the documented values below. The test there makes sure that all documented
+ values are really valid as a config option and therefore should always
+ stay in sync with this documentation.
+ -->
+
+- `always`: Retry on any failure (default).
+- `unknown_failure`: Retry when the failure reason is unknown.
+- `script_failure`: Retry when the script failed.
+- `api_failure`: Retry on API failure.
+- `stuck_or_timeout_failure`: Retry when the job got stuck or timed out.
+- `runner_system_failure`: Retry if there was a runner system failure (e.g. setting up the job failed).
+- `missing_dependency_failure`: Retry if a dependency was missing.
+- `runner_unsupported`: Retry if the runner was unsupported.
+
+
+## `parallel`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22631) in GitLab 11.5.
+
+`parallel` allows you to configure how many instances of a job to run in
+parallel. This value has to be greater than or equal to two (2) and less than or equal to 50.
+
+This creates N instances of the same job that run in parallel. They're named
+sequentially from `job_name 1/N` to `job_name N/N`.
+
+For every job, `CI_NODE_INDEX` and `CI_NODE_TOTAL` [environment variables](../variables/README.html#predefined-variables-environment-variables) are set.
+
+A simple example:
+
+```yaml
+test:
+ script: rspec
+ parallel: 5
+```
+
## `include`
-> Introduced in [GitLab Edition Premium][ee] 10.5.
-> Available for Starter, Premium and Ultimate [versions][gitlab-versions] since 10.6.
+> Introduced in [GitLab Premium](https://about.gitlab.com/pricing/) 10.5.
+> Available for Starter, Premium and Ultimate since 10.6.
> Behaviour expanded in GitLab 10.8 to allow more flexible overriding.
-> Available for Libre since [11.4](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21603)
+> [Moved](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21603)
+to GitLab Core in 11.4
Using the `include` keyword, you can allow the inclusion of external YAML files.
@@ -1388,6 +1637,10 @@ rspec:
- bundle exec rspec
```
+NOTE: **Note:**
+`include` requires the external YAML files to have the extensions `.yml` or `.yaml`.
+The external file will not be included if the extension is missing.
+
You can define it either as a single string, or, in case you want to include
more than one files, an array of different values . The following examples
are both valid cases:
@@ -1436,6 +1689,11 @@ include:
NOTE: **Note:**
The remote file must be publicly accessible through a simple GET request, as we don't support authentication schemas in the remote URL.
+ NOTE: **Note:**
+ In order to include files from another repository inside your local network,
+ you may need to enable the **Allow requests to the local network from hooks and services** checkbox
+ located in the **Settings > Network > Outbound requests** section within the **Admin area**.
+
---
@@ -1524,7 +1782,7 @@ stages:
production:
script:
- - install_depedencies
+ - install_dependencies
- deploy
- notify_owner
```
@@ -1563,13 +1821,6 @@ These variables can be later used in all executed commands and scripts.
The YAML-defined variables are also set to all created service containers,
thus allowing to fine tune them.
-To turn off global defined variables in a specific job, define an empty hash:
-
-```yaml
-job_name:
- variables: {}
-```
-
Except for the user defined variables, there are also the ones [set up by the
Runner itself](../variables/README.md#predefined-variables-environment-variables).
One example would be `CI_COMMIT_REF_NAME` which has the value of
@@ -1939,3 +2190,5 @@ CI with various languages.
[ce-12909]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12909
[schedules]: ../../user/project/pipelines/schedules.md
[variables-expressions]: ../variables/README.md#variables-expressions
+[ee]: https://about.gitlab.com/gitlab-ee/
+[gitlab-versions]: https://about.gitlab.com/products/
diff --git a/doc/development/README.md b/doc/development/README.md
index 94e604d125d..bcf57a223f5 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -7,8 +7,8 @@ description: 'Learn how to contribute to GitLab.'
## Get started!
-- Setup GitLab's development environment with [GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/README.md)
-- [GitLab contributing guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md)
+- Set up GitLab's development environment with [GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/README.md)
+- [GitLab contributing guide](contributing/index.md)
- [Architecture](architecture.md) of GitLab
- [Rake tasks](rake_tasks.md) for development
@@ -23,13 +23,14 @@ description: 'Learn how to contribute to GitLab.'
## UX and frontend guides
-- [UX guide](ux_guide/index.md) for building GitLab with existing CSS styles and elements
+- [GitLab Design System](https://design.gitlab.com/) for building GitLab with existing CSS styles and elements
- [Frontend guidelines](fe_guide/index.md)
- [Emoji guide](fe_guide/emojis.md)
## Backend guides
- [GitLab utilities](utilities.md)
+- [Logging](logging.md)
- [API styleguide](api_styleguide.md) Use this styleguide if you are
contributing to the API.
- [GraphQL API styleguide](api_graphql_styleguide.md) Use this
@@ -50,6 +51,8 @@ description: 'Learn how to contribute to GitLab.'
- [Permissions](permissions.md)
- [Prometheus metrics](prometheus_metrics.md)
- [Guidelines for reusing abstractions](reusing_abstractions.md)
+- [DeclarativePolicy framework](policies.md)
+- [Switching to Rails 5](switching_to_rails5.md)
## Performance guides
diff --git a/doc/development/adding_database_indexes.md b/doc/development/adding_database_indexes.md
index ea6f14da3b9..d1d2b8c4907 100644
--- a/doc/development/adding_database_indexes.md
+++ b/doc/development/adding_database_indexes.md
@@ -28,9 +28,9 @@ to filter data by. Instead one should ask themselves the following questions:
1. Can I write my query in such a way that it re-uses as many existing indexes
as possible?
-2. Is the data going to be large enough that using an index will actually be
+1. Is the data going to be large enough that using an index will actually be
faster than just iterating over the rows in the table?
-3. Is the overhead of maintaining the index worth the reduction in query
+1. Is the overhead of maintaining the index worth the reduction in query
timings?
We'll explore every question in detail below.
@@ -62,7 +62,7 @@ In short:
1. Try to write your query in such a way that it re-uses as many existing
indexes as possible.
-2. Run the query using `EXPLAIN ANALYZE` and study the output to find the most
+1. Run the query using `EXPLAIN ANALYZE` and study the output to find the most
ideal query.
## Data Size
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index 6c6e198a7c3..95722c027ba 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -379,7 +379,7 @@ let(:mutation) do
)
end
-it 'returns a successfull response' do
+it 'returns a successful response' do
post_graphql_mutation(mutation, current_user: user)
expect(response).to have_gitlab_http_status(:success)
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index 66d8a4f2f6e..e65c5f05505 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -10,39 +10,182 @@ For information, see the [GitLab Release Process](https://gitlab.com/gitlab-org/
Both EE and CE require some add-on components called gitlab-shell and Gitaly. These components are available from the [gitlab-shell](https://gitlab.com/gitlab-org/gitlab-shell/tree/master) and [gitaly](https://gitlab.com/gitlab-org/gitaly/tree/master) repositories respectively. New versions are usually tags but staying on the master branch will give you the latest stable version. New releases are generally around the same time as GitLab CE releases with exception for informal security updates deemed critical.
-## Physical office analogy
+## GitLab Omnibus Component by Component
-You can imagine GitLab as a physical office.
+This document is designed to be consumed by systems adminstrators and GitLab Support Engineers who want to understand more about the internals of GitLab and how they work together.
-**The repositories** are the goods GitLab handles.
-They can be stored in a warehouse.
-This can be either a hard disk, or something more complex, such as a NFS filesystem;
+When deployed, GitLab should be considered the amalgamation of the below processes. When troubleshooting or debugging, be as specific as possible as to which component you are referencing. That should increase clarity and reduce confusion.
-**Nginx** acts like the front-desk.
-Users come to Nginx and request actions to be done by workers in the office;
+### GitLab Process Descriptions
-**The database** is a series of metal file cabinets with information on:
- - The goods in the warehouse (metadata, issues, merge requests etc);
- - The users coming to the front desk (permissions)
+As of this writing, a fresh GitLab 11.3.0 install will show the following processes with `gitlab-ctl status`:
-**Redis** is a communication board with “cubby holes†that can contain tasks for office workers;
+```
+run: alertmanager: (pid 30829) 14207s; run: log: (pid 13906) 2432044s
+run: gitaly: (pid 30771) 14210s; run: log: (pid 13843) 2432046s
+run: gitlab-monitor: (pid 30788) 14209s; run: log: (pid 13868) 2432045s
+run: gitlab-workhorse: (pid 30758) 14210s; run: log: (pid 13855) 2432046s
+run: logrotate: (pid 30246) 3407s; run: log: (pid 13825) 2432047s
+run: nginx: (pid 30849) 14207s; run: log: (pid 13856) 2432046s
+run: node-exporter: (pid 30929) 14206s; run: log: (pid 13877) 2432045s
+run: postgres-exporter: (pid 30935) 14206s; run: log: (pid 13931) 2432044s
+run: postgresql: (pid 13133) 2432214s; run: log: (pid 13848) 2432046s
+run: prometheus: (pid 30807) 14209s; run: log: (pid 13884) 2432045s
+run: redis: (pid 30560) 14274s; run: log: (pid 13807) 2432047s
+run: redis-exporter: (pid 30946) 14205s; run: log: (pid 13869) 2432045s
+run: sidekiq: (pid 30953) 14205s; run: log: (pid 13810) 2432047s
+run: unicorn: (pid 30960) 14204s; run: log: (pid 13809) 2432047s
+```
+
+### Layers
+
+GitLab can be considered to have two layers from a process perspective:
+
+- **Monitoring**: Anything from this layer is not required to deliver GitLab the application, but will allow administrators more insight into their infrastructure and what the service as a whole is doing.
+- **Core**: Any process that is vital for the delivery of GitLab as a platform. If any of these processes halt there will be a GitLab outage. For the Core layer, you can further divide into:
+ - **Processors**: These processes are responsible for actually performing operations and presenting the service.
+ - **Data**: These services store/expose structured data for the GitLab service.
+
+### alertmanager
+
+- Omnibus configuration options
+- Layer: Monitoring
+
+[Alert manager](https://prometheus.io/docs/alerting/alertmanager/) is a tool provided by prometheus that _"handles alerts sent by client applications such as the Prometheus server. It takes care of deduplicating, grouping, and routing them to the correct receiver integration such as email, PagerDuty, or OpsGenie. It also takes care of silencing and inhibition of alerts."_ You can read more in [issue gitlab-ce#45740](https://gitlab.com/gitlab-org/gitlab-ce/issues/45740) about what we will be alerting on.
+
+### gitaly
+
+- [Omnibus configuration options](https://gitlab.com/gitlab-org/gitaly/tree/master/doc/configuration)
+- Layer: Core Service (Data)
+
+Gitaly is a service designed by GitLab to remove our need for NFS for Git storage in distributed deployments of GitLab. (Think GitLab.com or High Availablity Deployments) As of 11.3.0, This service handles all Git level access in GitLab. You can read more about the project [in the project's readme](https://gitlab.com/gitlab-org/gitaly).
+
+### gitlab-monitor
+
+- Omnibus configuration options
+- Layer: Monitoring
+
+GitLab Monitor is a process disigned in house that allows us to export metrics about GitLab application internals to prometheus. You can read more [in the project's readme](https://gitlab.com/gitlab-org/gitlab-monitor)
+
+### gitlab-workhorse
+
+- Omnibus configuration options
+- Layer: Core Service (Processor)
+
+[GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse) is a program designed at GitLab to help alieviate pressure from unicorn. You can read more about the [historical reasons for developing](https://about.gitlab.com/2016/04/12/a-brief-history-of-gitlab-workhorse/). It's designed to act as a smart reverse proxy to help speed up GitLab as a whole.
+
+### logrotate
+
+- [Omnibus configuration options](https://docs.gitlab.com/omnibus/settings/logs.html#logrotate)
+- Layer: Core Service
+
+GitLab is comprised of a large number of services that all log. We started bundling our own logrotate as of 7.4 to make sure we were logging responsibly. This is just a packaged version of the common opensource offering.
+
+### nginx
+
+- [Omnibus configuration options](https://docs.gitlab.com/omnibus/settings/nginx.html)
+- Layer: Core Service (Processor)
+
+Nginx as an ingress port for all HTTP requests and routes them to the approriate sub-systems within GitLab. We are bundling an unmodified version of the popular open source webserver.
+
+### node-exporter
+
+- [Omnibus configuration options](https://docs.gitlab.com/ee/administration/monitoring/prometheus/node_exporter.html)
+- Layer: Monitoring
+
+[Node Exporter](https://github.com/prometheus/node_exporter) is a Prometheus tool that gives us metrics on the underlying machine. (Think CPU/Disk/Load) It's just a packaged version of the common open source offering from the Prometheus project.
+
+### postgres-exporter
+
+- [Omnibus configuration options](https://docs.gitlab.com/ee/administration/monitoring/prometheus/postgres_exporter.html)
+- Layer: Monitoring
+
+[Postgres-exporter](https://github.com/wrouesnel/postgres_exporter) is the community provided Prometheus exporter that will deliver data about Postgres to prometheus for use in Grafana Dashboards.
+
+### postgresql
+
+- [Omnibus configuration options](https://docs.gitlab.com/omnibus/settings/database.html)
+- Layer: Core Service (Data)
+
+GitLab packages the popular Database to provide storage for Application meta data and user information.
+
+### prometheus
+
+- [Omnibus configuration options](https://docs.gitlab.com/ee/administration/monitoring/prometheus/)
+- Layer: Monitoring
+
+Prometheus is a time-series tool that helps GitLab administrators expose metrics about the individual processes used to provide GitLab the service.
+
+### redis
+
+- [Omnibus configuration options](https://docs.gitlab.com/omnibus/settings/redis.html)
+- Layer: Core Service (Data)
+
+Redis is packaged to provide a place to store:
+
+- session data
+- temporary cache information
+- background job queues.
+
+### redis-exporter
+
+- [Omnibus configuration options](https://docs.gitlab.com/ee/administration/monitoring/prometheus/redis_exporter.html)
+- Layer: Monitoring
+
+[Redis Exporter](https://github.com/oliver006/redis_exporter) is designed to give specific metrics about the Redis process to Prometheus so that we can graph these metrics in Graphana.
+
+### sidekiq
+
+- Omnibus configuration options
+- Layer: Core Service (Processor)
+
+Sidekiq is a Ruby background job processor that pulls jobs from the redis queue and processes them. Background jobs allow GitLab to provide a faster request/response cycle by moving work into the background.
+
+### unicorn
+
+- [Omnibus configuration options](https://docs.gitlab.com/omnibus/settings/unicorn.html)
+- Layer: Core Service (Processor)
+
+[Unicorn](https://bogomips.org/unicorn/) is a Ruby application server that is used to run the core Rails Application that provides the user facing features in GitLab. Often process output you will see this as `bundle` or `config.ru` depending on the GitLab version.
+
+### Additional Processes
+
+### GitLab Pages
+
+TODO
+
+### Mattermost
+
+TODO
+
+## GitLab by Request Type
+
+GitLab provides two "interfaces" for end users to access the service:
+
+- Web HTTP Requests (Viewing the UI/API)
+- Git HTTP/SSH Requests (Pushing/Pulling Git Data)
+
+It's important to understand the distinction as some processes are used in both and others are exclusive to a specific request type.
+
+### GitLab Web HTTP Request Cycle
+
+When making a request to an HTTP Endpoint (Think `/users/sign_in`) the request will take the following path through the GitLab Service:
+
+- nginx - Acts as our first line reverse proxy
+- gitlab-workhorse - This determines if it needs to go to the Rails application or somewhere else to reduce load on unicorn.
+- unicorn - Since this is a web request, and it needs to access the application it will go to Unicorn.
+- Postgres/Gitaly/Redis - Depending on the type of request, it may hit these services to store or retreive data.
-**Sidekiq** is a worker that primarily handles sending out emails.
-It takes tasks from the Redis communication board;
-**A Unicorn worker** is a worker that handles quick/mundane tasks.
-They work with the communication board (Redis).
-Their job description:
- - check permissions by checking the user session stored in a Redis “cubby holeâ€;
- - make tasks for Sidekiq;
- - fetch stuff from the warehouse or move things around in there;
+### GitLab Git Request Cycle
-**GitLab-shell** is a third kind of worker that takes orders from a fax machine (SSH) instead of the front desk (HTTP).
-GitLab-shell communicates with Sidekiq via the “communication board†(Redis), and asks quick questions of the Unicorn workers either directly or via the front desk.
+Below we describe the different pathing that HTTP vs. SSH Git requests will take. There is some overlap with the Web Request Cycle but also some differences.
-**Gitaly** is a back desk that is specialized on reaching the disks to perform git operations efficiently and keep a copy of the result of costly operations. All git operations go through Gitaly.
+### Web Request (80/443)
+TODO
-**GitLab Enterprise Edition (the application)** is the collection of processes and business practices that the office is run by.
+### SSH Request (22)
+TODO
## System Layout
diff --git a/doc/development/automatic_ce_ee_merge.md b/doc/development/automatic_ce_ee_merge.md
index f6509b5c1dd..58e08d432cc 100644
--- a/doc/development/automatic_ce_ee_merge.md
+++ b/doc/development/automatic_ce_ee_merge.md
@@ -17,6 +17,9 @@ This merge is done automatically in a
1. If all conflicts are resolved after your resolution is pushed, keep the merge
request assigned to you: **you are now responsible for the merge request to be
green**
+1. If you are the last person to resolve the conflicts, the pipeline is green,
+ and you have merge rights, merge the MR, but **do not** choose to squash.
+ Otherwise, assign the MR to someone that can merge.
1. If you need any help, you can ping the current [release managers], or ask in
the `#ce-to-ee` Slack channel
@@ -63,7 +66,7 @@ EE version of your CE merge request.
For each commit (except on `master`), the `ee_compat_check` CI job tries to
detect if the current branch's changes will conflict during the CE->EE merge.
-The job reports what files are conflicting and how to setup a merge request
+The job reports what files are conflicting and how to set up a merge request
against EE.
#### How the job works
diff --git a/doc/development/build_test_package.md b/doc/development/build_test_package.md
index 439d228baef..c5f6adfeaeb 100644
--- a/doc/development/build_test_package.md
+++ b/doc/development/build_test_package.md
@@ -4,12 +4,13 @@ While developing a new feature or modifying an existing one, it is helpful if an
installable package (or a docker image) containing those changes is available
for testing. For this very purpose, a manual job is provided in the GitLab CI/CD
pipeline that can be used to trigger a pipeline in the omnibus-gitlab repository
-that will create
-1. A deb package for Ubuntu 16.04, available as a build artifact, and
-2. A docker image, which is pushed to [Omnibus GitLab's container
-registry](https://gitlab.com/gitlab-org/omnibus-gitlab/container_registry)
-(images titled `gitlab-ce` and `gitlab-ee` respectively and image tag is the
-commit which triggered the pipeline).
+that will create:
+
+- A deb package for Ubuntu 16.04, available as a build artifact, and
+- A docker image, which is pushed to [Omnibus GitLab's container
+ registry](https://gitlab.com/gitlab-org/omnibus-gitlab/container_registry)
+ (images titled `gitlab-ce` and `gitlab-ee` respectively and image tag is the
+ commit which triggered the pipeline).
When you push a commit to either the gitlab-ce or gitlab-ee project, the
pipeline for that commit will have a `build-package` manual action you can
diff --git a/doc/development/changelog.md b/doc/development/changelog.md
index 9e0c81b3d60..cd0a1f46d27 100644
--- a/doc/development/changelog.md
+++ b/doc/development/changelog.md
@@ -110,7 +110,8 @@ At this point the script would ask you to select the category of the change (map
4. New deprecation
5. Feature removal
6. Security fix
-7. Other
+7. Performance improvement
+8. Other
```
The entry filename is based on the name of the current Git branch. If you run
@@ -132,15 +133,15 @@ If you're working on the GitLab EE repository, the entry will be added to
### Arguments
-| Argument | Shorthand | Purpose |
-| ----------------- | --------- | ---------------------------------------------------------------------------------------------------------- |
-| [`--amend`] | | Amend the previous commit |
-| [`--force`] | `-f` | Overwrite an existing entry |
-| [`--merge-request`] | `-m` | Set merge request ID |
-| [`--dry-run`] | `-n` | Don't actually write anything, just print |
-| [`--git-username`] | `-u` | Use Git user.name configuration as the author |
-| [`--type`] | `-t` | The category of the change, valid options are: added, fixed, changed, deprecated, removed, security, other |
-| [`--help`] | `-h` | Print help message |
+| Argument | Shorthand | Purpose |
+| ----------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------- |
+| [`--amend`] | | Amend the previous commit |
+| [`--force`] | `-f` | Overwrite an existing entry |
+| [`--merge-request`] | `-m` | Set merge request ID |
+| [`--dry-run`] | `-n` | Don't actually write anything, just print |
+| [`--git-username`] | `-u` | Use Git user.name configuration as the author |
+| [`--type`] | `-t` | The category of the change, valid options are: `added`, `fixed`, `changed`, `deprecated`, `removed`, `security`, `performance`, `other` |
+| [`--help`] | `-h` | Print help message |
[`--amend`]: #-amend
[`--force`]: #-force-or-f
diff --git a/doc/development/chaos_endpoints.md b/doc/development/chaos_endpoints.md
new file mode 100644
index 00000000000..403a5b21827
--- /dev/null
+++ b/doc/development/chaos_endpoints.md
@@ -0,0 +1,117 @@
+# Generating chaos in a test GitLab instance
+
+As [Werner Vogels](https://twitter.com/Werner), the CTO at Amazon Web Services, famously put it, **Everything fails, all the time**.
+
+As a developer, it's as important to consider the failure modes in which your software will operate as much as normal operation. Doing so can mean the difference between a minor hiccup leading to a scattering of `500` errors experienced by a tiny fraction of users and a full site outage that affects all users for an extended period.
+
+To paraphrase [Tolstoy](https://en.wikipedia.org/wiki/Anna_Karenina_principle), _all happy servers are alike, but all failing servers are failing in their own way_. Luckily, there are ways we can attempt to simulate these failure modes, and the chaos endpoints are tools for assisting in this process.
+
+Currently, there are four endpoints for simulating the following conditions:
+
+- Slow requests.
+- CPU-bound requests.
+- Memory leaks.
+- Unexpected process crashes.
+
+## Enabling chaos endpoints
+
+For obvious reasons, these endpoints are not enabled by default. They can be enabled by setting the `GITLAB_ENABLE_CHAOS_ENDPOINTS` environment variable to `1`.
+
+For example, if you're using the [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) this can be done with the following command:
+
+```bash
+GITLAB_ENABLE_CHAOS_ENDPOINTS=1 gdk run
+```
+
+## Securing the chaos endpoints
+
+DANGER: **Danger:**
+It is highly recommended that you secure access to the chaos endpoints using a secret token. This is recommended when enabling these endpoints locally and essential when running in a staging or other shared environment. You should not enable them in production unless you absolutely know what you're doing.
+
+A secret token can be set through the `GITLAB_CHAOS_SECRET` environment variable. For example, when using the [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) this can be done with the following command:
+
+```bash
+GITLAB_ENABLE_CHAOS_ENDPOINTS=1 GITLAB_CHAOS_SECRET=secret gdk run
+```
+
+Replace `secret` with your own secret token.
+
+## Invoking chaos
+
+Once you have enabled the chaos endpoints and restarted the application, you can start testing using the endpoints.
+
+## Memory leaks
+
+To simulate a memory leak in your application, use the `/-/chaos/leakmem` endpoint.
+
+NOTE: **Note:**
+The memory is not retained after the request finishes. Once the request has completed, the Ruby garbage collector will attempt to recover the memory.
+
+```
+GET /-/chaos/leakmem
+GET /-/chaos/leakmem?memory_mb=1024
+GET /-/chaos/leakmem?memory_mb=1024&duration_s=50
+```
+
+| Attribute | Type | Required | Description |
+| ------------ | ------- | -------- | ---------------------------------------------------------------------------------- |
+| `memory_mb` | integer | no | How much memory, in MB, should be leaked. Defaults to 100MB. |
+| `duration_s` | integer | no | Minimum duration, in seconds, that the memory should be retained. Defaults to 30s. |
+
+```bash
+curl http://localhost:3000/-/chaos/leakmem?memory_mb=1024&duration_s=10 --header 'X-Chaos-Secret: secret'
+```
+
+## CPU spin
+
+This endpoint attempts to fully utilise a single core, at 100%, for the given period.
+
+Depending on your rack server setup, your request may timeout after a predermined period (normally 60 seconds).
+If you're using Unicorn, this is done by killing the worker process.
+
+```
+GET /-/chaos/cpuspin
+GET /-/chaos/cpuspin?duration_s=50
+```
+
+| Attribute | Type | Required | Description |
+| ------------ | ------- | -------- | --------------------------------------------------------------------- |
+| `duration_s` | integer | no | Duration, in seconds, that the core will be utilised. Defaults to 30s |
+
+```bash
+curl http://localhost:3000/-/chaos/cpuspin?duration_s=60 --header 'X-Chaos-Secret: secret'
+```
+
+## Sleep
+
+This endpoint is similar to the CPU Spin endpoint but simulates off-processor activity, such as network calls to backend services. It will sleep for a given duration.
+
+As with the CPU Spin endpoint, this may lead to your request timing out if duration exceeds the configured limit.
+
+```
+GET /-/chaos/sleep
+GET /-/chaos/sleep?duration_s=50
+```
+
+| Attribute | Type | Required | Description |
+| ------------ | ------- | -------- | ---------------------------------------------------------------------- |
+| `duration_s` | integer | no | Duration, in seconds, that the request will sleep for. Defaults to 30s |
+
+```bash
+curl http://localhost:3000/-/chaos/sleep?duration_s=60 --header 'X-Chaos-Secret: secret'
+```
+
+## Kill
+
+This endpoint will simulate the unexpected death of a worker process using a `kill` signal.
+
+NOTE: **Note:**
+Since this endpoint uses the `KILL` signal, the worker is not given a chance to cleanup or shutdown.
+
+```
+GET /-/chaos/kill
+```
+
+```bash
+curl http://localhost:3000/-/chaos/kill --header 'X-Chaos-Secret: secret'
+```
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index edf0b6f46df..7788d155154 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -1,55 +1,153 @@
# Code Review Guidelines
+This guide contains advice and best practices for performing code review, and
+having your code reviewed.
+
+All merge requests for GitLab CE and EE, whether written by a GitLab team member
+or a volunteer contributor, must go through a code review process to ensure the
+code is effective, understandable, maintainable, and secure.
+
## Getting your merge request reviewed, approved, and merged
-There are a few rules to get your merge request accepted:
+You are strongly encouraged to get your code **reviewed** by a
+[reviewer](https://about.gitlab.com/handbook/engineering/#reviewer) as soon as
+there is any code to review, to get a second opinion on the chosen solution and
+implementation, and an extra pair of eyes looking for bugs, logic problems, or
+uncovered edge cases. The reviewer can be from a different team, but it is
+recommended to pick someone who knows the domain well. You can read more about the
+importance of involving reviewer(s) in the section on the responsibility of the author below.
+
+If you need some guidance (e.g. it's your first merge request), feel free to ask
+one of the [Merge request coaches][team].
+
+If you need assistance with security scans or comments, feel free to include the
+Security Team (`@gitlab-com/gl-security`) in the review.
+
+Depending on the areas your merge request touches, it must be **approved** by one
+or more [maintainers](https://about.gitlab.com/handbook/engineering/#maintainer):
+
+For approvals, we use the approval functionality found in the merge request
+widget. Reviewers can add their approval by [approving additionally](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html#adding-or-removing-an-approval).
+
+Getting your merge request **merged** also requires a maintainer. If it requires
+more than one approval, the last maintainer to review and approve it will also merge it.
+
+### Approval guidelines
-1. Your merge request should only be **merged by a [maintainer][team]**.
- 1. If your merge request includes only backend changes [^1], it must be
- **approved by a [backend maintainer][projects]**.
- 1. If your merge request includes only frontend changes [^1], it must be
- **approved by a [frontend maintainer][projects]**.
- 1. If your merge request includes UX changes [^1], it must
- be **approved by a [UX team member][team]**.
+As described in the section on the responsibility of the maintainer below, you
+are recommended to get your merge request approved and merged by maintainer(s)
+from teams other than your own.
+
+ 1. If your merge request includes backend changes [^1], it must be
+ **approved by a [backend maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab-ce_maintainers_backend)**.
+ 1. If your merge request includes frontend changes [^1], it must be
+ **approved by a [frontend maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab-ce_maintainers_frontend)**.
+ 1. If your merge request includes UX changes [^1], it must be
+ **approved by a [UX team member][team]**.
1. If your merge request includes adding a new JavaScript library [^1], it must be
**approved by a [frontend lead][team]**.
1. If your merge request includes adding a new UI/UX paradigm [^1], it must be
**approved by a [UX lead][team]**.
- 1. If your merge request includes frontend and backend changes [^1], it must
- be **approved by a [frontend and a backend maintainer][projects]**.
- 1. If your merge request includes UX and frontend changes [^1], it must
- be **approved by a [UX team member and a frontend maintainer][team]**.
- 1. If your merge request includes UX, frontend and backend changes [^1], it must
- be **approved by a [UX team member, a frontend and a backend maintainer][team]**.
- 1. If your merge request includes a new dependency or a filesystem change, it must
- be *approved by a [Distribution team member][team]*. See how to work with the [Distribution team for more details.](https://about.gitlab.com/handbook/engineering/dev-backend/distribution/)
-1. To lower the amount of merge requests maintainers need to review, you can
- ask or assign any [reviewers][projects] for a first review.
- 1. If you need some guidance (e.g. it's your first merge request), feel free
- to ask one of the [Merge request coaches][team].
- 1. It is recommended that you assign a maintainer that is from a different team than your own.
- This ensures that all code across GitLab is consistent and can be easily understood by all contributors.
-
-1. Keep in mind that maintainers are also going to perform a final code review.
- The ideal scenario is that the reviewer has already addressed any concerns
- the maintainer would have found, and the maintainer only has to perform the
- merge, but be prepared for further review comments.
-
-For more guidance, see [CONTRIBUTING.md](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md).
+ 1. If your merge request includes a new dependency or a filesystem change, it must be
+ **approved by a [Distribution team member][team]**. See how to work with the [Distribution team](https://about.gitlab.com/handbook/engineering/dev-backend/distribution/) for more details.
-## Best practices
+#### Security requirements
-This guide contains advice and best practices for performing code review, and
-having your code reviewed.
+ 1. If your merge request is processing, storing, or transferring any kind of [RED or ORANGE data](https://docs.google.com/document/d/15eNKGA3zyZazsJMldqTBFbYMnVUSQSpU14lo22JMZQY/edit) (this is a confidential document), it must be
+ **approved by a [Security Engineer][team]**.
+ 1. If your merge request involves implementing, utilizing, or is otherwise related to any type of authentication, authorization, or session handling mechanism, it must be
+ **approved by a [Security Engineer][team]**.
+ 1. If your merge request has a goal which requires a cryptographic function such as: confidentiality, integrity, authentication, or non-repudiation, it must be
+ **approved by a [Security Engineer][team]**.
-All merge requests for GitLab CE and EE, whether written by a GitLab team member
-or a volunteer contributor, must go through a code review process to ensure the
-code is effective, understandable, and maintainable.
+### The responsibility of the merge request author
+
+The responsibility to find the best solution and implement it lies with the
+merge request author.
+
+Before assigning a merge request to a maintainer for approval and merge, they
+should be confident that it actually solves the problem it was meant to solve,
+that it does so in the most appropriate way, that it satisfies all requirements,
+and that there are no remaining bugs, logical problems, uncovered edge cases,
+or known vulnerabilities. The merge request should also have a completed task
+list in its description and a passing CI pipeline to avoid unnecessary back and
+forth.
+
+To reach the required level of confidence in their solution, an author is expected
+to involve other people in the investigation and implementation processes as
+appropriate.
+
+They are encouraged to reach out to domain experts to discuss different solutions
+or get an implementation reviewed, to product managers and UX designers to clear
+up confusion or verify that the end result matches what they had in mind, to
+database specialists to get input on the data model or specific queries, or to
+any other developer to get an in-depth review of the solution.
+
+If an author is unsure if a merge request needs a domain expert's opinion, that's
+usually a pretty good sign that it does, since without it the required level of
+confidence in their solution will not have been reached.
-Any developer can, and is encouraged to, perform code review on merge requests
-of colleagues and contributors. However, the final decision to accept a merge
-request is up to one the project's maintainers, denoted on the
-[engineering projects][projects].
+Before the review, the author is requested to submit comments on the merge
+request diff alerting the reviewer to anything important as well as for anything
+that demands further explanation or attention. Examples of content that may
+warrant a comment could be:
+
+- The addition of a linting rule (Rubocop, JS etc)
+- The addition of a library (Ruby gem, JS lib etc)
+- Where not obvious, a link to the parent class or method
+- Any benchmarking performed to complement the change
+- Potentially insecure code
+
+Do not add these comments directly to the source code, unless the
+reviewer requires you to do so.
+
+This
+[saves reviewers time and helps authors catch mistakes earlier](https://www.ibm.com/developerworks/rational/library/11-proven-practices-for-peer-review/index.html#__RefHeading__97_174136755).
+
+### The responsibility of the maintainer
+
+Maintainers are responsible for the overall health, quality, and consistency of
+the GitLab codebase, across domains and product areas.
+
+Consequently, their reviews will focus primarily on things like overall
+architecture, code organization, separation of concerns, tests, DRYness,
+consistency, and readability.
+
+Since a maintainer's job only depends on their knowledge of the overall GitLab
+codebase, and not that of any specific domain, they can review, approve and merge
+merge requests from any team and in any product area.
+
+In fact, authors are encouraged to get their merge requests merged by maintainers
+from teams other than their own, to ensure that all code across GitLab is consistent
+and can be easily understood by all contributors, from both inside and outside the
+company, without requiring team-specific expertise.
+
+Maintainers will do their best to also review the specifics of the chosen solution
+before merging, but as they are not necessarily domain experts, they may be poorly
+placed to do so without an unreasonable investment of time. In those cases, they
+will defer to the judgment of the author and earlier reviewers and involved domain
+experts, in favor of focusing on their primary responsibilities.
+
+If a developer who happens to also be a maintainer was involved in a merge request
+as a domain expert and/or reviewer, it is recommended that they are not also picked
+as the maintainer to ultimately approve and merge it.
+
+Maintainers should check before merging if the merge request is approved by the
+required approvers.
+
+Maintainers must check before merging if the merge request is introducing new
+vulnerabilities, by inspecting the list in the Merge Request [Security
+Widget](https://docs.gitlab.com/ee/user/project/merge_requests/#security-reports-ultimate).
+When in doubt, a [Security Engineer][team] can be involved. The list of detected
+vulnerabilities must be either empty or containing:
+
+- dismissed vulnerabilities in case of false positives
+- vulnerabilities converted to issues
+
+Maintainers should **never** dismiss vulnerabilities to "empty" the list,
+without duly verifying them.
+
+## Best practices
### Everyone
@@ -97,6 +195,20 @@ first time.
branch. Do not squash until the branch is ready to merge. Reviewers should be
able to read individual updates based on their earlier feedback.
+### Assigning a merge request for a review
+
+If you want to have your merge request reviewed, you can assign it to any reviewer. The list of reviewers can be found on [Engineering projects](https://about.gitlab.com/handbook/engineering/projects/) page.
+
+You can also use `ready for review` label. That means that your merge request is ready to be reviewed and any reviewer can pick it. It is recommended to use that label only if there isn't time pressure and make sure the merge request is assigned to a reviewer.
+
+When your merge request was reviewed and can be passed to a maintainer you can either pick a specific maintainer or use a label `ready for merge`.
+
+It is responsibility of the author of a merge request that the merge request is reviewed. If it stays in `ready for review` state too long it is recommended to assign it to a specific reviewer.
+
+### List of merge requests ready for review
+
+Developers who have capacity can regularly check the list of [merge requests to review](https://gitlab.com/groups/gitlab-org/-/merge_requests?scope=all&utf8=%E2%9C%93&state=opened&label_name%5B%5D=ready%20for%20review) and assign any merge request they want to review.
+
### Reviewing code
Understand why the change is necessary (fixes a bug, improves the user
@@ -121,6 +233,9 @@ experience, refactors the existing code). Then:
subsequent revisions for anything that would be spotted after that.
- Consider using the [Squash and
merge][squash-and-merge] feature when the merge request has a lot of commits.
+ When merging code a maintainer should only use the squash feature if the
+ author has already set this option or if the merge request clearly contains a
+ messy commit history that is intended to be squashed.
[squash-and-merge]: https://docs.gitlab.com/ee/user/project/merge_requests/squash_and_merge.html#squash-and-merge
@@ -162,41 +277,41 @@ Enterprise Edition instance. This has some implications:
1. **Query changes** should be tested to ensure that they don't result in worse
performance at the scale of GitLab.com:
1. Generating large quantities of data locally can help.
- 2. Asking for query plans from GitLab.com is the most reliable way to validate
+ 1. Asking for query plans from GitLab.com is the most reliable way to validate
these.
-2. **Database migrations** must be:
+1. **Database migrations** must be:
1. Reversible.
- 2. Performant at the scale of GitLab.com - ask a maintainer to test the
+ 1. Performant at the scale of GitLab.com - ask a maintainer to test the
migration on the staging environment if you aren't sure.
- 3. Categorised correctly:
+ 1. Categorised correctly:
- Regular migrations run before the new code is running on the instance.
- [Post-deployment migrations](post_deployment_migrations.md) run _after_
the new code is deployed, when the instance is configured to do that.
- [Background migrations](background_migrations.md) run in Sidekiq, and
should only be done for migrations that would take an extreme amount of
time at GitLab.com scale.
-3. **Sidekiq workers**
+1. **Sidekiq workers**
[cannot change in a backwards-incompatible way](sidekiq_style_guide.md#removing-or-renaming-queues):
1. Sidekiq queues are not drained before a deploy happens, so there will be
workers in the queue from the previous version of GitLab.
- 2. If you need to change a method signature, try to do so across two releases,
+ 1. If you need to change a method signature, try to do so across two releases,
and accept both the old and new arguments in the first of those.
- 3. Similarly, if you need to remove a worker, stop it from being scheduled in
+ 1. Similarly, if you need to remove a worker, stop it from being scheduled in
one release, then remove it in the next. This will allow existing jobs to
execute.
- 4. Don't forget, not every instance will upgrade to every intermediate version
+ 1. Don't forget, not every instance will upgrade to every intermediate version
(some people may go from X.1.0 to X.10.0, or even try bigger upgrades!), so
try to be liberal in accepting the old format if it is cheap to do so.
-4. **Cached values** may persist across releases. If you are changing the type a
+1. **Cached values** may persist across releases. If you are changing the type a
cached value returns (say, from a string or nil to an array), change the
cache key at the same time.
-5. **Settings** should be added as a
+1. **Settings** should be added as a
[last resort](https://about.gitlab.com/handbook/product/#convention-over-configuration).
If you're adding a new setting in `gitlab.yml`:
1. Try to avoid that, and add to `ApplicationSetting` instead.
- 2. Ensure that it is also
+ 1. Ensure that it is also
[added to Omnibus](https://docs.gitlab.com/omnibus/settings/gitlab.yml.html#adding-a-new-setting-to-gitlab-yml).
-6. **Filesystem access** can be slow, so try to avoid
+1. **Filesystem access** can be slow, so try to avoid
[shared files](shared_files.md) when an alternative solution is available.
### Credits
diff --git a/doc/development/contributing/community_roles.md b/doc/development/contributing/community_roles.md
new file mode 100644
index 00000000000..b9c369286d2
--- /dev/null
+++ b/doc/development/contributing/community_roles.md
@@ -0,0 +1,16 @@
+### Community members & roles
+
+GitLab community members and their privileges/responsibilities.
+
+| Roles | Responsibilities | Requirements |
+|-------|------------------|--------------|
+| Maintainer | Accepts merge requests on several GitLab projects | Added to the [team page](https://about.gitlab.com/team/). An expert on code reviews and knows the product/code base |
+| Reviewer | Performs code reviews on MRs | Added to the [team page](https://about.gitlab.com/team/) |
+| Developer |Has access to GitLab internal infrastructure & issues (e.g. HR-related) | GitLab employee or a Core Team member (with an NDA) |
+| Contributor | Can make contributions to all GitLab public projects | Have a GitLab.com account |
+
+[List of current reviewers/maintainers](https://about.gitlab.com/handbook/engineering/projects/#gitlab-ce).
+
+---
+
+[Return to Contributing documentation](index.md)
diff --git a/doc/development/contributing/design.md b/doc/development/contributing/design.md
index 45fe8c26591..79750878aac 100644
--- a/doc/development/contributing/design.md
+++ b/doc/development/contributing/design.md
@@ -1,13 +1,4 @@
-<!-- START doctoc generated TOC please keep comment here to allow auto update -->
-<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
-**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
-
-- [Implement design & UI elements](#implement-design--ui-elements)
-- [Style guides](#style-guides)
-
-<!-- END doctoc generated TOC please keep comment here to allow auto update -->
-
-## Implement design & UI elements
+# Implement design & UI elements
For guidance on UX implementation at GitLab, please refer to our [Design System](https://design.gitlab.com/).
@@ -22,7 +13,10 @@ There is a special type label called ~"product discovery". It represents a disco
~"product discovery" issues are like any other issue and should contain a milestone label, ~"Deliverable" or ~"Stretch", when scheduled in the current milestone.
-The initial issue should be about the problem we are solving. If a separate [product discovery issue](#product-discovery-issues) is needed for additional research and design work, it will be created by a PM or UX person. Assign the ~UX, ~"product discovery" and ~"Deliverable" labels, add a milestone and use a title that makes it clear that the scheduled issue is product discovery
+The initial issue should be about the problem we are solving. If a separate [product discovery issue](https://about.gitlab.com/handbook/engineering/ux/ux-department-workflow/#how-we-use-labels)
+is needed for additional research and design work, it will be created by a PM or UX person.
+Assign the ~UX, ~"product discovery" and ~"Deliverable" labels, add a milestone and
+use a title that makes it clear that the scheduled issue is product discovery
(e.g. `Product discovery for XYZ`).
In order to complete a product discovery issue in a release, you must complete the following:
@@ -32,34 +26,6 @@ In order to complete a product discovery issue in a release, you must complete t
1. Copy the design to the description of the delivery issue for which the product discovery issue was created. Do not simply refer to the product discovery issue as a separate source of truth.
1. In some cases, a product discovery issue also identifies future enhancements that will not go into the issue that originated the product discovery issue. For these items, create new issues containing the designs to ensure they are not lost. Put the issues in the backlog if they are agreed upon as good ideas. Otherwise leave them for triage.
-## Style guides
-
-1. [Ruby](https://github.com/bbatsov/ruby-style-guide).
- Important sections include [Source Code Layout][rss-source] and
- [Naming][rss-naming]. Use:
- - multi-line method chaining style **Option A**: dot `.` on the second line
- - string literal quoting style **Option A**: single quoted by default
-1. [Rails](https://github.com/bbatsov/rails-style-guide)
-1. [Newlines styleguide][newlines-styleguide]
-1. [Testing][testing]
-1. [JavaScript styleguide][js-styleguide]
-1. [SCSS styleguide][scss-styleguide]
-1. [Shell commands](../shell_commands.md) created by GitLab
- contributors to enhance security
-1. [Database Migrations](../migration_style_guide.md)
-1. [Markdown](http://www.cirosantilli.com/markdown-styleguide)
-1. [Documentation styleguide](https://docs.gitlab.com/ee/development/documentation/styleguide.html)
-1. Interface text should be written subjectively instead of objectively. It
- should be the GitLab core team addressing a person. It should be written in
- present time and never use past tense (has been/was). For example instead
- of _prohibited this user from being saved due to the following errors:_ the
- text should be _sorry, we could not create your account because:_
-1. Code should be written in [US English][us-english]
-
-This is also the style used by linting tools such as
-[RuboCop](https://github.com/bbatsov/rubocop),
-[PullReview](https://www.pullreview.com/) and [Hound CI](https://houndci.com).
-
---
[Return to Contributing documentation](index.md)
diff --git a/doc/development/contributing/index.md b/doc/development/contributing/index.md
index eac7cb44c40..9da4c66933c 100644
--- a/doc/development/contributing/index.md
+++ b/doc/development/contributing/index.md
@@ -1,59 +1,26 @@
-<!-- START doctoc generated TOC please keep comment here to allow auto update -->
-<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
-**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
-
-- [Contribute to GitLab](#contribute-to-gitlab)
-- [Security vulnerability disclosure](#security-vulnerability-disclosure)
-- [Code of conduct](#code-of-conduct)
-- [Closing policy for issues and merge requests](#closing-policy-for-issues-and-merge-requests)
-- [Helping others](#helping-others)
-- [I want to contribute!](#i-want-to-contribute)
-- [Contribution Flow](#contribution-flow)
-- [Workflow labels](#workflow-labels)
- - [Type labels](#type-labels)
- - [Subject labels](#subject-labels)
- - [Team labels](#team-labels)
- - [Milestone labels](#milestone-labels)
- - [Bug Priority labels](#bug-priority-labels)
- - [Bug Severity labels](#bug-severity-labels)
- - [Severity impact guidance](#severity-impact-guidance)
- - [Label for community contributors](#label-for-community-contributors)
-- [Implement design & UI elements](#implement-design--ui-elements)
-- [Issue tracker](#issue-tracker)
- - [Issue triaging](#issue-triaging)
- - [Feature proposals](#feature-proposals)
- - [Issue tracker guidelines](#issue-tracker-guidelines)
- - [Issue weight](#issue-weight)
- - [Regression issues](#regression-issues)
- - [Technical and UX debt](#technical-and-ux-debt)
- - [Stewardship](#stewardship)
-- [Merge requests](#merge-requests)
- - [Merge request guidelines](#merge-request-guidelines)
- - [Contribution acceptance criteria](#contribution-acceptance-criteria)
-- [Definition of done](#definition-of-done)
-- [Style guides](#style-guides)
-
-<!-- END doctoc generated TOC please keep comment here to allow auto update -->
-
-## Contribute to GitLab
-
-For a first-time step-by-step guide to the contribution process, see
-["Contributing to GitLab"](https://about.gitlab.com/contributing/).
+# Contribute to GitLab
Thank you for your interest in contributing to GitLab. This guide details how
-to contribute to GitLab in a way that is efficient for everyone.
+to contribute to GitLab in a way that is easy for everyone.
+
+We want to create a welcoming environment for everyone who is interested in contributing. Please visit our [Code of Conduct page](https://about.gitlab.com/contributing/code-of-conduct) to learn more about our committment to an open and welcoming environment.
+
+For a first-time step-by-step guide to the contribution process, please see
+["Contributing to GitLab"](https://about.gitlab.com/contributing/).
-Looking for something to work on? Look for issues with the label [Accepting Merge Requests](#i-want-to-contribute).
+Looking for something to work on? Look for issues with the label [`Accepting merge requests`](#i-want-to-contribute).
-GitLab comes into two flavors, GitLab Community Edition (CE) our free and open
+GitLab comes in two flavors, GitLab Community Edition (CE) our free and open
source edition, and GitLab Enterprise Edition (EE) which is our commercial
edition. Throughout this guide you will see references to CE and EE for
abbreviation.
-If you have read this guide and want to know how the GitLab [core team]
+To get an overview of GitLab community membership including those that would be reviewing or merging your contributions, please visit [the community roles page](community_roles.md).
+
+If you want to know how the GitLab [core team]
operates please see [the GitLab contributing process](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/PROCESS.md).
-- [GitLab Inc engineers should refer to the engineering workflow document](https://about.gitlab.com/handbook/engineering/workflow/)
+[GitLab Inc engineers should refer to the engineering workflow document](https://about.gitlab.com/handbook/engineering/workflow/)
## Security vulnerability disclosure
@@ -65,33 +32,8 @@ vulnerabilities.
## Code of conduct
-As contributors and maintainers of this project, we pledge to respect all
-people who contribute through reporting issues, posting feature requests,
-updating documentation, submitting pull requests or patches, and other
-activities.
-
-We are committed to making participation in this project a harassment-free
-experience for everyone, regardless of level of experience, gender, gender
-identity and expression, sexual orientation, disability, personal appearance,
-body size, race, ethnicity, age, or religion.
-
-Examples of unacceptable behavior by participants include the use of sexual
-language or imagery, derogatory comments or personal attacks, trolling, public
-or private harassment, insults, or other unprofessional conduct.
-
-Project maintainers have the right and responsibility to remove, edit, or
-reject comments, commits, code, wiki edits, issues, and other contributions
-that are not aligned to this Code of Conduct. Project maintainers who do not
-follow the Code of Conduct may be removed from the project team.
-
-This code of conduct applies both within project spaces and in public spaces
-when an individual is representing the project or its community.
-
-Instances of abusive, harassing, or otherwise unacceptable behavior can be
-reported by emailing `contact@gitlab.com`.
-
-This Code of Conduct is adapted from the [Contributor Covenant][contributor-covenant], version 1.1.0,
-available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/).
+Our code of conduct can be found on the
+["Contributing to GitLab"](https://about.gitlab.com/contributing/) page.
## Closing policy for issues and merge requests
@@ -124,10 +66,10 @@ the remaining issues on the GitHub issue tracker.
## I want to contribute!
-If you want to contribute to GitLab [issues with the label `Accepting Merge Requests` and small weight][accepting-mrs-weight]
-is a great place to start. Issues with a lower weight (1 or 2) are deemed
-suitable for beginners. These issues will be of reasonable size and challenge,
-for anyone to start contributing to GitLab. If you have any questions or need help visit [Getting Help](https://about.gitlab.com/getting-help/#discussion) to
+If you want to contribute to GitLab,
+[issues with the `Accepting merge requests` label](issue_workflow.md#label-for-community-contributors)
+are a great place to start.
+If you have any questions or need help visit [Getting Help](https://about.gitlab.com/getting-help/#discussion) to
learn how to communicate with GitLab. If you're looking for a Gitter or Slack channel
please consider we favor
[asynchronous communication](https://about.gitlab.com/handbook/communication/#internal-communication) over real time communication. Thanks for your contribution!
@@ -154,93 +96,38 @@ When your code contains more than 500 changes, any major breaking changes, or an
This [documentation](issue_workflow.md) outlines the current workflow labels.
-### Type labels
-
-This [documentation](issue_workflow.md) outlines the current type labels.
-
-### Subject labels
-
-This [documentation](issue_workflow.md) outlines the current subject labels.
-
-### Team labels
-
-This [documentation](issue_workflow.md) outlines the current team labels.
-
-### Milestone labels
-
-This [documentation](issue_workflow.md) outlines the current milestone labels.
-
-### Bug Priority labels
-
-This [documentation](issue_workflow.md) outlines the current bug priority labels.
-
-### Bug Severity labels
-
-This [documentation](issue_workflow.md) outlines the current severity labels.
-
-#### Severity impact guidance
-
-This [documentation](issue_workflow.md) outlines the current severity impact guidance.
-
-### Label for community contributors
-
-This [documentation](issue_workflow.md) outlines the current policy regarding community contributor issues.
-
-## Implement design & UI elements
-
-This [documentation](design.md) outlines the current design and UI guidelines.
-
-## Issue tracker
-
-This [documentation](issue_workflow.md) outlines the issue tracker process.
-
-### Issue triaging
-
-This [documentation](issue_workflow.md) outlines the current issue triaging process.
-
-### Feature proposals
-
-This [documentation](issue_workflow.md) outlines the feature proposal process.
-
-### Issue tracker guidelines
-
-This [documentation](issue_workflow.md) outlines the issue tracker guidelines.
-
-### Issue weight
-
-This [documentation](issue_workflow.md) outlines the issue weight guidelines.
-
-### Regression issues
-
-This [documentation](issue_workflow.md) outlines the regression issue process.
-
-### Technical and UX debt
-
-This [documentation](issue_workflow.md) about technical and UX debt has been moved.
-
-### Stewardship
-
-This [documentation](issue_workflow.md) outlines the stewardship process.
+* [Type labels](issue_workflow.md#type-labels)
+* [Subject labels](issue_workflow.md#subject-labels)
+* [Team labels](issue_workflow.md#team-labels)
+* [Release Scoping labels](issue_workflow.md#release-scoping-labels)
+* [Priority labels](issue_workflow.md#priority-labels)
+* [Severity labels](issue_workflow.md#severity-labels)
+* [Label for community contributors](issue_workflow.md#label-for-community-contributors)
+* [Issue triaging](issue_workflow.md#issue-triaging)
+* [Feature proposals](issue_workflow.md#feature-proposals)
+* [Issue tracker guidelines](issue_workflow.md#issue-tracker-guidelines)
+* [Issue weight](issue_workflow.md#issue-weight)
+* [Regression issues](issue_workflow.md#regression-issues)
+* [Technical and UX debt](issue_workflow.md#technical-and-ux-debt)
+* [Stewardship](issue_workflow.md#stewardship)
## Merge requests
This [documentation](merge_request_workflow.md) outlines the current merge request process.
-### Merge request guidelines
-
-This [documentation](merge_request_workflow.md) outlines the current merge request guidelines.
-
-### Contribution acceptance criteria
-
-This [documentation](merge_request_workflow.md) outlines the current acceptance criteria for contributions.
-
-## Definition of done
-
-This [documentation](merge_request_workflow.md) outlines the definition of done.
+* [Merge request guidelines](merge_request_workflow.md#merge-request-guidelines)
+* [Contribution acceptance criteria](merge_request_workflow.md#contribution-acceptance-criteria)
+* [Definition of done](merge_request_workflow.md#definition-of-done)
## Style guides
-This [documentation](design.md) outlines the current style guidelines.
+
+This [documentation](style_guides.md) outlines the current style guidelines.
---
[Return to Development documentation](../README.md)
+
+[core team]: https://about.gitlab.com/core-team/
+[team]: https://about.gitlab.com/team/
+[getting-help]: https://about.gitlab.com/getting-help/
+[codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq
diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md
index 08042fa2aec..7c7da50a149 100644
--- a/doc/development/contributing/issue_workflow.md
+++ b/doc/development/contributing/issue_workflow.md
@@ -1,27 +1,4 @@
-<!-- START doctoc generated TOC please keep comment here to allow auto update -->
-<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
-**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
-
-- [Workflow labels](#workflow-labels)
- - [Type labels](#type-labels)
- - [Subject labels](#subject-labels)
- - [Team labels](#team-labels)
- - [Release Scoping labels](#release-scoping-labels)
- - [Priority labels](#priority-labels)
- - [Severity labels](#severity-labels)
- - [Severity impact guidance](#severity-impact-guidance)
- - [Label for community contributors](#label-for-community-contributors)
- - [Issue triaging](#issue-triaging)
- - [Feature proposals](#feature-proposals)
- - [Issue tracker guidelines](#issue-tracker-guidelines)
- - [Issue weight](#issue-weight)
- - [Regression issues](#regression-issues)
- - [Technical and UX debt](#technical-and-ux-debt)
- - [Stewardship](#stewardship)
-
-<!-- END doctoc generated TOC please keep comment here to allow auto update -->
-
-## Workflow labels
+# Workflow labels
To allow for asynchronous issue handling, we use [milestones][milestones-page]
and [labels][labels-page]. Leads and product managers handle most of the
@@ -31,7 +8,8 @@ Most issues will have labels for at least one of the following:
- Type: ~"feature proposal", ~bug, ~customer, etc.
- Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc.
-- Team: ~"CI/CD", ~Plan, ~Manage, ~Quality, etc.
+- Team: ~Plan, ~Manage, ~Quality, etc.
+- Stage: ~"devops:plan", ~"devops:create", etc.
- Release Scoping: ~Deliverable, ~Stretch, ~"Next Patch Release"
- Priority: ~P1, ~P2, ~P3, ~P4
- Severity: ~S1, ~S2, ~S3, ~S4
@@ -43,9 +21,8 @@ If you come across an issue that has none of these, and you're allowed to set
labels, you can _always_ add the team and type, and often also the subject.
[milestones-page]: https://gitlab.com/gitlab-org/gitlab-ce/milestones
-[labels-page]: https://gitlab.com/gitlab-org/gitlab-ce/labels
-### Type labels
+## Type labels
Type labels are very important. They define what kind of issue this is. Every
issue should have one or more.
@@ -61,7 +38,7 @@ already reserved for subject labels).
The descriptions on the [labels page][labels-page] explain what falls under each type label.
-### Subject labels
+## Subject labels
Subject labels are labels that define what area or feature of GitLab this issue
hits. They are not always necessary, but very convenient.
@@ -75,7 +52,7 @@ issue is labeled with a subject label corresponding to your expertise.
Subject labels are always all-lowercase.
-### Team labels
+## Team labels
Team labels specify what team is responsible for this issue.
Assigning a team label makes sure issues get the attention of the appropriate
@@ -83,8 +60,7 @@ people.
The current team labels are:
-- ~Configuration
-- ~"CI/CD"
+- ~Configure
- ~Create
- ~Distribution
- ~Documentation
@@ -97,6 +73,7 @@ The current team labels are:
- ~Release
- ~Secure
- ~UX
+- ~Verify
The descriptions on the [labels page][labels-page] explain what falls under the
responsibility of each team.
@@ -107,7 +84,40 @@ indicate if an issue needs backend work, frontend work, or both.
Team labels are always capitalized so that they show up as the first label for
any issue.
-### Release Scoping labels
+## Stage labels
+
+Stage labels specify which [DevOps stage][devops-stages] the issue belongs to.
+
+The current stage labels are:
+
+- ~"devops:manage"
+- ~"devops:plan"
+- ~"devops:create"
+- ~"devops:verify"
+- ~"devops:package"
+- ~"devops:release"
+- ~"devops:configure"
+- ~"devops:monitor"
+- ~"devops:secure"
+
+These labels should be mutually exclusive. If an issue belongs to multiple
+stages, the most relevant should be used.
+
+They differ from the [Team labels](#team-labels) because teams may work on
+issues outside their stage.
+
+Normally there is a 1:1 relationship between Stage labels and Team labels, but
+any issue can be picked up by any team, depending on current priorities.
+So, an issue labeled ~"devops:create" may be scheduled by the ~Plan team, for
+example. In such cases, it's usual to include both team labels so each team can
+be aware of the progress.
+
+The Stage labels are used to generate the [direction pages][direction-pages] automatically.
+
+[devops-stages]: https://about.gitlab.com/direction/#devops-stages
+[direction-pages]: https://about.gitlab.com/direction/
+
+## Release Scoping labels
Release Scoping labels help us clearly communicate expectations of the work for the
release. There are three levels of Release Scoping labels:
@@ -131,14 +141,17 @@ Priority labels help us define the time a ~bug fix should be completed. Priority
If there are multiple defects, the priority decides which defect has to be fixed immediately versus later.
This label documents the planned timeline & urgency which is used to measure against our actual SLA on delivering ~bug fixes.
-| Label | Meaning | Estimate time to fix |
-|-------|-----------------|------------------------------------------------------------------|
-| ~P1 | Urgent Priority | The current release + potentially immediate hotfix to GitLab.com |
-| ~P2 | High Priority | The next release |
-| ~P3 | Medium Priority | Within the next 3 releases (approx one quarter) |
-| ~P4 | Low Priority | Anything outside the next 3 releases (approx beyond one quarter) |
+| Label | Meaning | Defect SLA (applies only to ~bug and ~security defects) |
+|-------|-----------------|----------------------------------------------------------------------------|
+| ~P1 | Urgent Priority | The current release + potentially immediate hotfix to GitLab.com (30 days) |
+| ~P2 | High Priority | The next release (60 days) |
+| ~P3 | Medium Priority | Within the next 3 releases (approx one quarter or 90 days) |
+| ~P4 | Low Priority | Anything outside the next 3 releases (more than one quarter or 120 days) |
-### Severity labels
+If an issue seems to fall between two priority labels, assign it to the higher-
+priority label.
+
+## Severity labels
Severity labels help us clearly communicate the impact of a ~bug on users.
@@ -149,7 +162,11 @@ Severity labels help us clearly communicate the impact of a ~bug on users.
| ~S3 | Major Severity | Broken Feature, workaround acceptable | Can create merge requests only from the Merge Requests page, not through the Issue. |
| ~S4 | Low Severity | Functionality inconvenience or cosmetic issue | Label colors are incorrect / not being displayed. |
-#### Severity impact guidance
+If an issue seems to fall between two severity labels, even taking the
+[severity impact guidance](#severity-impact-guidance) into account, assign
+it to the higher-severity label.
+
+### Severity impact guidance
Severity levels can be applied further depending on the facet of the impact; e.g. Affected customers, GitLab.com availability, performance and etc. The below is a guideline.
@@ -158,16 +175,16 @@ Severity levels can be applied further depending on the facet of the impact; e.g
| ~S1 | >50% users affected (possible company extinction level event) | Significant impact on all of GitLab.com | |
| ~S2 | Many users or multiple paid customers affected (but not apocalyptic)| Significant impact on large portions of GitLab.com | Degradation is guaranteed to occur in the near future |
| ~S3 | A few users or a single paid customer affected | Limited impact on important portions of GitLab.com | Degradation is likely to occur in the near future |
-| ~S4 | No paid users/customer affected, or expected to in the near future | Minor impact on on GitLab.com | Degradation _may_ occur but it's not likely |
+| ~S4 | No paid users/customer affected, or expected to in the near future | Minor impact on GitLab.com | Degradation _may_ occur but it's not likely |
-### Label for community contributors
+## Label for community contributors
Issues that are beneficial to our users, 'nice to haves', that we currently do
not have the capacity for or want to give the priority to, are labeled as
-~"Accepting Merge Requests", so the community can make a contribution.
+~"Accepting merge requests", so the community can make a contribution.
Community contributors can submit merge requests for any issue they want, but
-the ~"Accepting Merge Requests" label has a special meaning. It points to
+the ~"Accepting merge requests" label has a special meaning. It points to
changes that:
1. We already agreed on,
@@ -175,43 +192,42 @@ changes that:
1. Are likely to get accepted by a maintainer.
We want to avoid a situation when a contributor picks an
-~"Accepting Merge Requests" issue and then their merge request gets closed,
+~"Accepting merge requests" issue and then their merge request gets closed,
because we realize that it does not fit our vision, or we want to solve it in a
different way.
-We add the ~"Accepting Merge Requests" label to:
+We add the ~"Accepting merge requests" label to:
- Low priority ~bug issues (i.e. we do not add it to the bugs that we want to
solve in the ~"Next Patch Release")
- Small ~"feature proposal"
- Small ~"technical debt" issues
-After adding the ~"Accepting Merge Requests" label, we try to estimate the
+After adding the ~"Accepting merge requests" label, we try to estimate the
[weight](#issue-weight) of the issue. We use issue weight to let contributors
know how difficult the issue is. Additionally:
-- We advertise ["Accepting Merge Requests" issues with weight < 5][up-for-grabs]
+- We advertise [`Accepting merge requests` issues with weight < 5][up-for-grabs]
as suitable for people that have never contributed to GitLab before on the
[Up For Grabs campaign](http://up-for-grabs.net)
- We encourage people that have never contributed to any open source project to
- look for ["Accepting Merge Requests" issues with a weight of 1][firt-timers]
+ look for [`Accepting merge requests` issues with a weight of 1][firt-timers]
If you've decided that you would like to work on an issue, please @-mention
the [appropriate product manager](https://about.gitlab.com/handbook/product/#who-to-talk-to-for-what)
as soon as possible. The product manager will then pull in appropriate GitLab team
members to further discuss scope, design, and technical considerations. This will
-ensure that that your contribution is aligned with the GitLab product and minimize
+ensure that your contribution is aligned with the GitLab product and minimize
any rework and delay in getting it merged into master.
-GitLab team members who apply the ~"Accepting Merge Requests" label to an issue
+GitLab team members who apply the ~"Accepting merge requests" label to an issue
should update the issue description with a responsible product manager, inviting
any potential community contributor to @-mention per above.
-[up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=Accepting+Merge+Requests&scope=all&sort=weight_asc&state=opened
-[firt-timers]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name%5B%5D=Accepting+Merge+Requests&scope=all&sort=upvotes_desc&state=opened&weight=1
+[up-for-grabs]: https://gitlab.com/groups/gitlab-org/-/issues?state=opened&label_name[]=Accepting+merge+requests&assignee_id=0&sort=weight
+[firt-timers]: https://gitlab.com/groups/gitlab-org/-/issues?state=opened&label_name[]=Accepting+merge+requests&assignee_id=0&sort=weight&weight=1
-
-### Issue triaging
+## Issue triaging
Our issue triage policies are [described in our handbook]. You are very welcome
to help the GitLab team triage issues. We also organize [issue bash events] once
@@ -224,7 +240,7 @@ on those issues. Please select someone with relevant experience from the
the commit history for the affected files to find someone.
We also use [GitLab Triage] to automate some triaging policies. This is
-currently setup as a [scheduled pipeline] running on [quality/triage-ops]
+currently set up as a [scheduled pipeline] running on [quality/triage-ops]
project.
[described in our handbook]: https://about.gitlab.com/handbook/engineering/issue-triage/
@@ -232,8 +248,9 @@ project.
[GitLab Triage]: https://gitlab.com/gitlab-org/gitlab-triage
[scheduled pipeline]: https://gitlab.com/gitlab-org/quality/triage-ops/pipeline_schedules/10512/edit
[quality/triage-ops]: https://gitlab.com/gitlab-org/quality/triage-ops
+[team]: https://about.gitlab.com/team/
-### Feature proposals
+## Feature proposals
To create a feature proposal for CE, open an issue on the
[issue tracker of CE][ce-tracker].
@@ -250,7 +267,7 @@ code snippet right after your description in a new line: `~"feature proposal"`.
Please keep feature proposals as small and simple as possible, complex ones
might be edited to make them small and simple.
-Please submit Feature Proposals using the ['Feature Proposal' issue template](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab/issue_templates/Feature%20Proposal.md) provided on the issue tracker.
+Please submit Feature Proposals using the ['Feature Proposal' issue template](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab/issue_templates/Feature%20proposal.md) provided on the issue tracker.
For changes in the interface, it is helpful to include a mockup. Issues that add to, or change, the interface should
be given the ~"UX" label. This will allow the UX team to provide input and guidance. You may
@@ -259,7 +276,9 @@ need to ask one of the [core team] members to add the label, if you do not have
If you want to create something yourself, consider opening an issue first to
discuss whether it is interesting to include this in GitLab.
-### Issue tracker guidelines
+[fpl]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=feature+proposal
+
+## Issue tracker guidelines
**[Search the issue tracker][ce-tracker]** for similar entries before
submitting your own, there's a good chance somebody else had the same issue or
@@ -271,7 +290,7 @@ The text in the parenthesis is there to help you with what to include. Omit it
when submitting the actual issue. You can copy-paste it and then edit as you
see fit.
-### Issue weight
+## Issue weight
Issue weight allows us to get an idea of the amount of work required to solve
one or multiple issues. This makes it possible to schedule work more accurately.
@@ -293,7 +312,7 @@ is probably 1, adding a new Git Hook maybe 4 or 5, big features 7-9.
issues or chunks. You can simply not set the weight of a parent issue and set
weights to children issues.
-### Regression issues
+## Regression issues
Every monthly release has a corresponding issue on the CE issue tracker to keep
track of functionality broken by that release and any fixes that need to be
@@ -313,7 +332,7 @@ addressed.
[8.3 Regressions]: https://gitlab.com/gitlab-org/gitlab-ce/issues/4127
[update the notes]: https://gitlab.com/gitlab-org/release-tools/blob/master/doc/pro-tips.md#update-the-regression-issue
-### Technical and UX debt
+## Technical and UX debt
In order to track things that can be improved in GitLab's codebase,
we use the ~"technical debt" label in [GitLab's issue tracker][ce-tracker].
@@ -337,7 +356,46 @@ for a release by the appropriate person.
Make sure to mention the merge request that the ~"technical debt" issue or
~"UX debt" issue is associated with in the description of the issue.
-### Stewardship
+## Technical debt in follow-up issues
+
+It's common to discover technical debt during development of a new feature. In
+the spirit of "minimum viable change", resolution is often deferred to a
+follow-up issue. However, this cannot be used as an excuse to merge poor-quality
+code that would otherwise not pass review, or to overlook trivial matters that
+don't deserve the be scheduled independently, and would be best resolved in the
+original merge request - or not tracked at all!
+
+The overheads of scheduling, and rate of change in the GitLab codebase, mean
+that the cost of a trivial technical debt issue can quickly exceed the value of
+tracking it. This generally means we should resolve these in the original merge
+request - or simply not create a follow-up issue at all.
+
+For example, a typo in a comment that is being copied between files is worth
+fixing in the same MR, but not worth creating a follow-up issue for. Renaming a
+method that is used in many places to make its intent slightly clearer may be
+worth fixing, but it should not happen in the same MR, and is generally not
+worth the overhead of having an issue of its own. These issues would invariably
+be labelled `~P4 ~S4` if we were to create them.
+
+More severe technical debt can have implications for development velocity. If
+it isn't addressed in a timely manner, the codebase becomes needlessly difficult
+to change, new features become difficult to add, and regressions abound.
+
+Discoveries of this kind of technical debt should be treated seriously, and
+while resolution in a follow-up issue may be appropriate, maintainers should
+generally obtain a scheduling commitment from the author of the original MR, or
+the engineering or product manager for the relevant area. This may take the form
+of appropriate Priority / Severity labels on the issue, or an explicit milestone
+and assignee.
+
+The maintainer must always agree before an outstanding discussion is resolved in
+this manner, and will be the one to create the issue. The title and description
+should be of the same quality as those created
+[in the usual manner](#technical-and-ux-debt) - in particular, the issue title
+**must not** begin with `Follow-up`! The creating maintainer should also expect
+to be involved in some capacity when work begins on the follow-up issue.
+
+## Stewardship
For issues related to the open source stewardship of GitLab,
there is the ~"stewardship" label.
@@ -355,3 +413,7 @@ A recent example of this was the issue for
---
[Return to Contributing documentation](index.md)
+
+[labels-page]: https://gitlab.com/gitlab-org/gitlab-ce/labels
+[ce-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/issues
+[ee-tracker]: https://gitlab.com/gitlab-org/gitlab-ee/issues
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index 685287f7a0c..5b32b5cd46f 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -1,22 +1,10 @@
-<!-- START doctoc generated TOC please keep comment here to allow auto update -->
-<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
-**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
-
-- [Merge requests](#merge-requests)
- - [Merge request guidelines](#merge-request-guidelines)
- - [Contribution acceptance criteria](#contribution-acceptance-criteria)
-- [Definition of done](#definition-of-done)
-
-<!-- END doctoc generated TOC please keep comment here to allow auto update -->
-
-## Merge requests
+# Merge requests
We welcome merge requests with fixes and improvements to GitLab code, tests,
and/or documentation. The issues that are specifically suitable for
-community contributions are listed with the label
-[`Accepting Merge Requests` on our issue tracker for CE][accepting-mrs-ce]
-and [EE][accepting-mrs-ee], but you are free to contribute to any other issue
-you want.
+community contributions are listed with
+[the `Accepting merge requests` label](issue_workflow.md#label-for-community-contributors),
+but you are free to contribute to any other issue you want.
Please note that if an issue is marked for the current milestone either before
or while you are working on it, a team member may take over the merge request
@@ -30,13 +18,16 @@ wireframes if the feature will also change the UI.
Merge requests should be opened at [GitLab.com][gitlab-mr-tracker].
If you are new to GitLab development (or web development in general), see the
-[I want to contribute!](#i-want-to-contribute) section to get you started with
+[I want to contribute!](index.md#i-want-to-contribute) section to get you started with
some potentially easy issues.
To start with GitLab development download the [GitLab Development Kit][gdk] and
-see the [Development section](../README.md) for some guidelines.
+see the [Development section](../../README.md) for some guidelines.
+
+[gitlab-mr-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests
+[gdk]: https://gitlab.com/gitlab-org/gitlab-development-kit
-### Merge request guidelines
+## Merge request guidelines
If you can, please submit a merge request with the fix or improvements
including tests. If you don't know how to fix the issue but can write a test
@@ -114,7 +105,11 @@ Please ensure that your merge request meets the contribution acceptance criteria
When having your code reviewed and when reviewing merge requests please take the
[code review guidelines](../code_review.md) into account.
-### Contribution acceptance criteria
+[git-squash]: https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits
+[closed-merge-requests]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests?assignee_id=&label_name=&milestone_id=&scope=&sort=&state=closed
+[team]: https://about.gitlab.com/team/
+
+## Contribution acceptance criteria
1. The change is as small as possible
1. Include proper tests and make all tests pass (unless it contains a test
@@ -144,7 +139,7 @@ When having your code reviewed and when reviewing merge requests please take the
[polling with ETag caching][polling-etag].
1. Changes after submitting the merge request should be in separate commits
(no squashing).
-1. It conforms to the [style guides](#style-guides) and the following:
+1. It conforms to the [style guides](style_guides.md) and the following:
- If your change touches a line that does not follow the style, modify the
entire line to follow it. This prevents linting tools from generating warnings.
- Don't touch neighbouring lines. As an exception, automatic mass
@@ -155,6 +150,9 @@ When having your code reviewed and when reviewing merge requests please take the
"license-finder" test with a "Dependencies that need approval" error.
1. The merge request meets the [definition of done](#definition-of-done).
+[license-finder-doc]: ../licensing.md
+[polling-etag]: ../polling.md
+
## Definition of done
If you contribute to GitLab please know that changes involve more than just
@@ -167,12 +165,13 @@ the feature you contribute through all of these steps.
1. Performance/scalability implications have been considered, addressed, and tested
1. [Documented][doc-guidelines] in the `/doc` directory
1. [Changelog entry added][changelog], if necessary
-1. Reviewed and any concerns are addressed
+1. Reviewed by UX/FE/BE and any concerns are addressed
1. Merged by a project maintainer
1. Added to the release blog article, if relevant
1. Added to [the website](https://gitlab.com/gitlab-com/www-gitlab-com/), if relevant
1. Community questions answered
1. Answers to questions radiated (in docs/wiki/support etc.)
+1. [Black-box tests/end-to-end tests](../testing_guide/testing_levels.md#black-box-tests-or-end-to-end-tests) added if required. Please contact [the quality team](https://about.gitlab.com/handbook/engineering/quality/#teams) with any questions
If you add a dependency in GitLab (such as an operating system package) please
consider updating the following and note the applicability of each in your
@@ -186,6 +185,12 @@ merge request:
1. Test suite https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/prepare_build.sh
1. Omnibus package creator https://gitlab.com/gitlab-org/omnibus-gitlab
+[definition-of-done]: http://guide.agilealliance.org/guide/definition-of-done.html
+[testing]: ../testing_guide/index.md
+
---
[Return to Contributing documentation](index.md)
+
+[changelog]: ../changelog.md "Generate a changelog entry"
+[doc-guidelines]: ../documentation/index.md "Documentation guidelines"
diff --git a/doc/development/contributing/style_guides.md b/doc/development/contributing/style_guides.md
new file mode 100644
index 00000000000..6f1ba5d62a5
--- /dev/null
+++ b/doc/development/contributing/style_guides.md
@@ -0,0 +1,39 @@
+# Style guides
+
+1. [Ruby](https://github.com/bbatsov/ruby-style-guide).
+ Important sections include [Source Code Layout][rss-source] and
+ [Naming][rss-naming]. Use:
+ - multi-line method chaining style **Option A**: dot `.` on the second line
+ - string literal quoting style **Option A**: single quoted by default
+1. [Rails](https://github.com/bbatsov/rails-style-guide)
+1. [Newlines styleguide][newlines-styleguide]
+1. [Testing][testing]
+1. [JavaScript styleguide][js-styleguide]
+1. [SCSS styleguide][scss-styleguide]
+1. [Shell commands](../shell_commands.md) created by GitLab
+ contributors to enhance security
+1. [Database Migrations](../migration_style_guide.md)
+1. [Markdown](http://www.cirosantilli.com/markdown-styleguide)
+1. [Documentation styleguide](../documentation/styleguide.md)
+1. Interface text should be written subjectively instead of objectively. It
+ should be the GitLab core team addressing a person. It should be written in
+ present time and never use past tense (has been/was). For example instead
+ of _prohibited this user from being saved due to the following errors:_ the
+ text should be _sorry, we could not create your account because:_
+1. Code should be written in [US English][us-english]
+
+This is also the style used by linting tools such as
+[RuboCop](https://github.com/bbatsov/rubocop) and [Hound CI](https://houndci.com).
+
+---
+
+[Return to Contributing documentation](index.md)
+
+[rss-source]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#source-code-layout
+[rss-naming]: https://github.com/bbatsov/ruby-style-guide/blob/master/README.md#naming
+[doc-guidelines]: ../documentation/index.md "Documentation guidelines"
+[js-styleguide]: ../fe_guide/style_guide_js.md "JavaScript styleguide"
+[scss-styleguide]: ../fe_guide/style_guide_scss.md "SCSS styleguide"
+[newlines-styleguide]: ../newlines_styleguide.md "Newlines styleguide"
+[testing]: ../testing_guide/index.md
+[us-english]: https://en.wikipedia.org/wiki/American_English
diff --git a/doc/development/database_debugging.md b/doc/development/database_debugging.md
index 9c31265e417..b2c804b2ff0 100644
--- a/doc/development/database_debugging.md
+++ b/doc/development/database_debugging.md
@@ -33,7 +33,7 @@ If your test DB is giving you problems, it is safe to nuke it because it doesn't
- `bundle exec rake db:migrate RAILS_ENV=development`: Execute any pending migrations that you may have picked up from a MR
- `bundle exec rake db:migrate:status RAILS_ENV=development`: Check if all migrations are `up` or `down`
- `bundle exec rake db:migrate:down VERSION=20170926203418 RAILS_ENV=development`: Tear down a migration
- - `bundle exec rake db:migrate:up VERSION=20170926203418 RAILS_ENV=development`: Setup a migration
+ - `bundle exec rake db:migrate:up VERSION=20170926203418 RAILS_ENV=development`: Set up a migration
- `bundle exec rake db:migrate:redo VERSION=20170926203418 RAILS_ENV=development`: Re-run a specific migration
diff --git a/doc/development/database_merge_request_checklist.md b/doc/development/database_merge_request_checklist.md
index 75c395b61ef..48864c81592 100644
--- a/doc/development/database_merge_request_checklist.md
+++ b/doc/development/database_merge_request_checklist.md
@@ -1,15 +1,15 @@
# Merge Request Checklist
When creating a merge request that performs database related changes (schema
-changes, adjusting queries to optimise performance, etc) you should use the
-merge request template called "Database Changes". This template contains a
+changes, adjusting queries to optimize performance, etc) you should use the
+merge request template called "Database changes". This template contains a
checklist of steps to follow to make sure the changes are up to snuff.
To use the checklist, create a new merge request and click on the "Choose a
-template" dropdown, then click "Database Changes".
+template" dropdown, then click "Database changes".
An example of this checklist can be found at
-https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12463.
+<https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12463>.
The source code of the checklist can be found in at
-https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab/merge_request_templates/Database%20Changes.md
+<https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab/merge_request_templates/Database%20changes.md>
diff --git a/doc/development/db_dump.md b/doc/development/db_dump.md
index e4ff72aa349..97762a62a80 100644
--- a/doc/development/db_dump.md
+++ b/doc/development/db_dump.md
@@ -13,7 +13,7 @@ large database imports.
```
# On STAGING
echo "postgresql['checkpoint_segments'] = 64" | sudo tee -a /etc/gitlab/gitlab.rb
-sudo touch /etc/gitlab/skip-auto-migrations
+sudo touch /etc/gitlab/skip-auto-reconfigure
sudo gitlab-ctl reconfigure
sudo gitlab-ctl stop unicorn
sudo gitlab-ctl stop sidekiq
diff --git a/doc/development/diffs.md b/doc/development/diffs.md
index 5e8e8cc7541..43fc125c21d 100644
--- a/doc/development/diffs.md
+++ b/doc/development/diffs.md
@@ -2,13 +2,10 @@
Currently we rely on different sources to present diffs, these include:
-- Rugged gem
- Gitaly service
- Database (through `merge_request_diff_files`)
- Redis (cached highlighted diffs)
-We're constantly moving Rugged calls to Gitaly and the progress can be followed through [Gitaly repo](https://gitlab.com/gitlab-org/gitaly).
-
## Architecture overview
### Merge request diffs
@@ -19,20 +16,21 @@ we fetch the comparison information using `Gitlab::Git::Compare`, which fetches
The diffs fetching process _limits_ single file diff sizes and the overall size of the whole diff through a series of constant values. Raw diff files are
then persisted on `merge_request_diff_files` table.
-Even though diffs higher than 10kb are collapsed (`Gitlab::Git::Diff::COLLAPSE_LIMIT`), we still keep them on Postgres. However, diff files over _safety limits_
-(see the [Diff limits section](#diff-limits)) are _not_ persisted.
+Even though diffs larger than 10% of the value of `ApplicationSettings#diff_max_patch_bytes` are collapsed,
+we still keep them on Postgres. However, diff files larger than defined _safety limits_
+(see the [Diff limits section](#diff-limits)) are _not_ persisted in the database.
In order to present diffs information on the Merge Request diffs page, we:
1. Fetch all diff files from database `merge_request_diff_files`
-2. Fetch the _old_ and _new_ file blobs in batch to:
- 1. Highlight old and new file content
- 2. Know which viewer it should use for each file (text, image, deleted, etc)
- 3. Know if the file content changed
- 4. Know if it was stored externally
- 5. Know if it had storage errors
-3. If the diff file is cacheable (text-based), it's cached on Redis
-using `Gitlab::Diff::FileCollection::MergeRequestDiff`
+1. Fetch the _old_ and _new_ file blobs in batch to:
+ - Highlight old and new file content
+ - Know which viewer it should use for each file (text, image, deleted, etc)
+ - Know if the file content changed
+ - Know if it was stored externally
+ - Know if it had storage errors
+1. If the diff file is cacheable (text-based), it's cached on Redis
+ using `Gitlab::Diff::FileCollection::MergeRequestDiff`
### Note diffs
@@ -41,9 +39,9 @@ on `NoteDiffFile` (which is associated with the actual `DiffNote`). So instead
of hitting the repository every time we need the diff of the file, we:
1. Check whether we have the `NoteDiffFile#diff` persisted and use it
-2. Otherwise, if it's a current MR revision, use the persisted
-`MergeRequestDiffFile#diff`
-3. In the last scenario, go the the repository and fetch the diff
+1. Otherwise, if it's a current MR revision, use the persisted
+ `MergeRequestDiffFile#diff`
+1. In the last scenario, go the repository and fetch the diff
## Diff limits
@@ -102,23 +100,20 @@ Gitaly will only return the safe amount of data to be persisted on `merge_reques
Limits that act onto each diff file of a collection. Files number, lines number and files size are considered.
-```ruby
-Gitlab::Git::Diff::COLLAPSE_LIMIT = 10.kilobytes
-```
+#### Expandable patches (collapsed)
-File diff will be collapsed (but be expandable) if it is larger than 10 kilobytes.
+Diff patches are collapsed when surpassing 10% of the value set in `ApplicationSettings#diff_max_patch_bytes`.
+That is, it's equivalent to 10kb if the maximum allowed value is 100kb.
+The diff will still be persisted and expandable if the patch size doesn't
+surpass `ApplicationSettings#diff_max_patch_bytes`.
*Note:* Although this nomenclature (Collapsing) is also used on Gitaly, this limit is only used on GitLab (hardcoded - not sent to Gitaly).
Gitaly will only return `Diff.Collapsed` (RPC) when surpassing collection limits.
-```ruby
-Gitlab::Git::Diff::SIZE_LIMIT = 100.kilobytes
-```
-
-File diff will not be rendered if it's larger than 100 kilobytes.
+#### Not expandable patches (too large)
-*Note:* This limit is currently hardcoded and applied on Gitaly and the RPC returns `Diff.TooLarge` when this limit is surpassed.
-Although we're still also applying it on GitLab, we should remove the redundancy from GitLab once we're confident with the Gitaly integration.
+The patch not be rendered if it's larger than `ApplicationSettings#diff_max_patch_bytes`.
+Users will see a `This source diff could not be displayed because it is too large` message.
```ruby
Commit::DIFF_SAFE_LINES = Gitlab::Git::DiffCollection::DEFAULT_LIMITS[:max_lines] = 5000
diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md
index d6ae4cb39f0..b7990e1b558 100644
--- a/doc/development/documentation/index.md
+++ b/doc/development/documentation/index.md
@@ -4,9 +4,9 @@ description: Learn how to contribute to GitLab Documentation.
# GitLab Documentation guidelines
- - **General Documentation**: written by the [developers responsible by creating features](#contributing-to-docs). Should be submitted in the same merge request containing code. Feature proposals (by GitLab contributors) should also be accompanied by its respective documentation. They can be later improved by PMs and Technical Writers.
- - **[Technical Articles](#technical-articles)**: written by any [GitLab Team](https://about.gitlab.com/team/) member, GitLab contributors, or [Community Writers](https://about.gitlab.com/handbook/product/technical-writing/community-writers/).
- - **Indexes per topic**: initially prepared by the Technical Writing Team, and kept up-to-date by developers and PMs in the same merge request containing code. They gather all resources for that topic in a single page (user and admin documentation, articles, and third-party docs).
+- **General Documentation**: written by the [developers responsible by creating features](#contributing-to-docs). Should be submitted in the same merge request containing code. Feature proposals (by GitLab contributors) should also be accompanied by its respective documentation. They can be later improved by PMs and Technical Writers.
+- **[Technical Articles](#technical-articles)**: written by any [GitLab Team](https://about.gitlab.com/team/) member, GitLab contributors, or [Community Writers](https://about.gitlab.com/handbook/product/technical-writing/community-writers/).
+- **Indexes per topic**: initially prepared by the Technical Writing Team, and kept up-to-date by developers and PMs in the same merge request containing code. They gather all resources for that topic in a single page (user and admin documentation, articles, and third-party docs).
## Contributing to docs
@@ -41,15 +41,17 @@ how to structure GitLab docs.
## Markdown and styles
-Currently GitLab docs use Redcarpet as [markdown](../../user/markdown.md) engine, but there's an [open discussion](https://gitlab.com/gitlab-com/gitlab-docs/issues/50) for implementing Kramdown in the near future.
+[GitLab docs](https://gitlab.com/gitlab-com/gitlab-docs) uses [GitLab Kramdown](https://gitlab.com/gitlab-org/gitlab_kramdown)
+as markdown engine. Check the [GitLab Markdown Kramdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/)
+for a complete Kramdown reference.
-All the docs follow the [documentation style guidelines](styleguide.md).
+Follow the [documentation style guidelines](styleguide.md) strictly.
## Documentation directory structure
The documentation is structured based on the GitLab UI structure itself,
separated by [`user`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/user),
-[`administrator`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/administration), and [`contributor`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/development).
+[`administrator`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/administration), and [`contributor`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/development).
In order to have a [solid site structure](https://searchengineland.com/seo-benefits-developing-solid-site-structure-277456) for our documentation,
all docs should be linked. Every new document should be cross-linked to its related documentation, and linked from its topic-related index, when existent.
@@ -61,11 +63,11 @@ in small iterations. Please don't create new docs in these folders.
### Documentation files
- When you create a new directory, always start with an `index.md` file.
-Do not use another file name and **do not** create `README.md` files
+ Do not use another file name and **do not** create `README.md` files.
- **Do not** use special chars and spaces, or capital letters in file names,
-directory names, branch names, and anything that generates a path.
-- Max screenshot size: 100KB
-- We do not support videos (yet)
+ directory names, branch names, and anything that generates a path.
+- Max screenshot size: 100KB.
+- We do not support videos (yet).
### Location and naming documents
@@ -83,24 +85,21 @@ and cross-link between any related content.
The table below shows what kind of documentation goes where.
-| Directory | What belongs here |
-| --------- | -------------- |
-| `doc/user/` | User related documentation. Anything that can be done within the GitLab UI goes here including `/admin`. |
-| `doc/administration/` | Documentation that requires the user to have access to the server where GitLab is installed. The admin settings that can be accessed via GitLab's interface go under `doc/user/admin_area/`. |
-| `doc/api/` | API related documentation. |
-| `doc/development/` | Documentation related to the development of GitLab. Any styleguides should go here. |
-| `doc/legal/` | Legal documents about contributing to GitLab. |
-| `doc/install/`| Probably the most visited directory, since `installation.md` is there. Ideally this should go under `doc/administration/`, but it's best to leave it as-is in order to avoid confusion (still debated though). |
-| `doc/update/` | Same with `doc/install/`. Should be under `administration/`, but this is a well known location, better leave as-is, at least for now. |
-| `doc/topics/` | Indexes per Topic (`doc/topics/topic-name/index.md`): all resources for that topic (user and admin documentation, articles, and third-party docs) |
+| Directory | What belongs here |
+|:----------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `doc/user/` | User related documentation. Anything that can be done within the GitLab UI goes here including `/admin`. |
+| `doc/administration/` | Documentation that requires the user to have access to the server where GitLab is installed. The admin settings that can be accessed via GitLab's interface go under `doc/user/admin_area/`. |
+| `doc/api/` | API related documentation. |
+| `doc/development/` | Documentation related to the development of GitLab. Any styleguides should go here. |
+| `doc/legal/` | Legal documents about contributing to GitLab. |
+| `doc/install/` | Probably the most visited directory, since `installation.md` is there. Ideally this should go under `doc/administration/`, but it's best to leave it as-is in order to avoid confusion (still debated though). |
+| `doc/update/` | Same with `doc/install/`. Should be under `administration/`, but this is a well known location, better leave as-is, at least for now. |
+| `doc/topics/` | Indexes per Topic (`doc/topics/topic-name/index.md`): all resources for that topic (user and admin documentation, articles, and third-party docs) |
---
**General rules & best practices:**
-1. The correct naming and location of a new document, is a combination
- of the relative URL of the document in question and the GitLab Map design
- that is used for UX purposes ([source][graffle], [image][gitlab-map]).
1. When creating a new document and it has more than one word in its name,
make sure to use underscores instead of spaces or dashes (`-`). For example,
a proper naming would be `import_projects_from_github.md`. The same rule
@@ -134,13 +133,13 @@ merge request.
Changing a document's location is not to be taken lightly. Remember that the
documentation is available to all installations under `help/` and not only to
-GitLab.com or http://docs.gitlab.com. Make sure this is discussed with the
+GitLab.com or <http://docs.gitlab.com>. Make sure this is discussed with the
Documentation team beforehand.
If you indeed need to change a document's location, do NOT remove the old
document, but rather replace all of its contents with a new line:
-```
+```md
This document was moved to [another location](path/to/new_doc.md).
```
@@ -154,7 +153,7 @@ For example, if you were to move `doc/workflow/lfs/lfs_administration.md` to
1. Copy `doc/workflow/lfs/lfs_administration.md` to `doc/administration/lfs.md`
1. Replace the contents of `doc/workflow/lfs/lfs_administration.md` with:
- ```
+ ```md
This document was moved to [another location](../../administration/lfs.md).
```
@@ -162,7 +161,7 @@ For example, if you were to move `doc/workflow/lfs/lfs_administration.md` to
A quick way to find them is to use `git grep`. First go to the root directory
where you cloned the `gitlab-ce` repository and then do:
- ```
+ ```sh
git grep -n "workflow/lfs/lfs_administration"
git grep -n "lfs/lfs_administration"
```
@@ -198,6 +197,11 @@ redirect_to: '../path/to/file/README.md'
It supports both full and relative URLs, e.g. `https://docs.gitlab.com/ee/path/to/file.html`, `../path/to/file.html`, `path/to/file.md`. Note that any `*.md` paths will be compiled to `*.html`.
+NOTE: **Note:**
+This redirection method will not provide a redirect fallback on GitLab `/help`. When using
+it, make sure to add a link to the new page on the doc, otherwise it's a dead end for users that
+land on the doc via `/help`.
+
### Redirections for pages with Disqus comments
If the documentation page being relocated already has any Disqus comments,
@@ -223,33 +227,14 @@ redirect_from: 'https://docs.gitlab.com/my-old-location/README.html'
Note: it is necessary to include the file name in the `redirect_from` URL,
even if it's `index.html` or `README.html`.
-## Testing
-
-We treat documentation as code, thus have implemented some testing.
-Currently, the following tests are in place:
-
-1. `docs lint`: Check that all internal (relative) links work correctly and
- that all cURL examples in API docs use the full switches. It's recommended
- to [check locally](#previewing-locally) before pushing to GitLab by executing the command
- `bundle exec nanoc check internal_links` on your local
- [`gitlab-docs`](https://gitlab.com/gitlab-com/gitlab-docs) directory.
-1. [`ee_compat_check`](../automatic_ce_ee_merge.md#avoiding-ce-gt-ee-merge-conflicts-beforehand) (runs on CE only):
- When you submit a merge request to GitLab Community Edition (CE),
- there is this additional job that runs against Enterprise Edition (EE)
- and checks if your changes can apply cleanly to the EE codebase.
- If that job fails, read the instructions in the job log for what to do next.
- As CE is merged into EE once a day, it's important to avoid merge conflicts.
- Submitting an EE-equivalent merge request cherry-picking all commits from CE to EE is
- essential to avoid them.
-
## Branch naming
If your contribution contains **only** documentation changes, you can speed up
the CI process by following some branch naming conventions. You have three
choices:
-| Branch name | Valid example |
-| ----------- | ------------- |
+| Branch name | Valid example |
+|:----------------------|:-----------------------------|
| Starting with `docs/` | `docs/update-api-issues` |
| Starting with `docs-` | `docs-update-api-issues` |
| Ending in `-docs` | `123-update-api-issues-docs` |
@@ -257,15 +242,6 @@ choices:
If your branch name matches any of the above, it will run only the docs
tests. If it doesn't, the whole test suite will run (including docs).
-## Danger bot
-
-GitLab uses [danger bot](https://github.com/danger/danger) for some elements in
-code review. For docs changes in merge requests, the following actions are taken:
-
-1. Whenever a change under `/doc` is made, the bot leaves a comment for the
- author to mention `@gl-docsteam`, so that the docs can be properly
- reviewed.
-
## Merge requests for GitLab documentation
Before getting started, make sure you read the introductory section
@@ -278,7 +254,6 @@ for GitLab Team members.
- Label the MR `Documentation`
- Assign the correct milestone (see note below)
-
NOTE: **Note:**
If the release version you want to add the documentation to has already been
frozen or released, use the label `Pick into X.Y` to get it merged into
@@ -299,112 +274,15 @@ Follow this [method for cherry-picking from CE to EE](../automatic_ce_ee_merge.m
- Create the EE-equivalent branch ending with `-ee`, e.g.,
`git checkout -b docs-example-ee`
- Once all the jobs are passing in CE and EE, and you've addressed the
-feedback from your own team, assign the CE MR to a technical writer for review
+ feedback from your own team, assign the CE MR to a technical writer for review
- When both MRs are ready, the EE merge request will be merged first, and the
-CE-equivalent will be merged next.
+ CE-equivalent will be merged next.
- Note that the review will occur only in the CE MR, as the EE MR
-contains the same commits as the CE MR.
+ contains the same commits as the CE MR.
- If you have a few more changes that apply to the EE-version only, you can submit
-a couple more commits to the EE branch, but ask the reviewer to review the EE merge request
-additionally to the CE MR. If there are many EE-only changes though, start a new MR
-to EE only.
-
-## Previewing the changes live
-
-NOTE: **Note:**
-To preview your changes to documentation locally, follow this
-[development guide](https://gitlab.com/gitlab-com/gitlab-docs/blob/master/README.md#development).
-
-The live preview is currently enabled for the following projects:
-
-- https://gitlab.com/gitlab-org/gitlab-ce
-- https://gitlab.com/gitlab-org/gitlab-ee
-- https://gitlab.com/gitlab-org/gitlab-runner
-
-If your branch contains only documentation changes, you can use
-[special branch names](#branch-naming) to avoid long running pipelines.
-
-For [docs-only changes](#branch-naming), the review app is run automatically.
-For all other branches, you can use the manual `review-docs-deploy-manual` job
-in your merge request. You will need at least Maintainer permissions to be able
-to run it. In the mini pipeline graph, you should see an `>>` icon. Clicking on it will
-reveal the `review-docs-deploy-manual` job. Hit the play button for the job to start.
-
-![Manual trigger a docs build](img/manual_build_docs.png)
-
-NOTE: **Note:**
-You will need to push a branch to those repositories, it doesn't work for forks.
-
-The `review-docs-deploy*` job will:
-
-1. Create a new branch in the [gitlab-docs](https://gitlab.com/gitlab-com/gitlab-docs)
- project named after the scheme: `$DOCS_GITLAB_REPO_SUFFIX-$CI_ENVIRONMENT_SLUG`,
- where `DOCS_GITLAB_REPO_SUFFIX` is the suffix for each product, e.g, `ce` for
- CE, etc.
-1. Trigger a cross project pipeline and build the docs site with your changes
-
-After a few minutes, the Review App will be deployed and you will be able to
-preview the changes. The docs URL can be found in two places:
-
-- In the merge request widget
-- In the output of the `review-docs-deploy*` job, which also includes the
- triggered pipeline so that you can investigate whether something went wrong
-
-In case the Review App URL returns 404, follow these steps to debug:
-
-1. **Did you follow the URL from the merge request widget?** If yes, then check if
- the link is the same as the one in the job output.
-1. **Did you follow the URL from the job output?** If yes, then it means that
- either the site is not yet deployed or something went wrong with the remote
- pipeline. Give it a few minutes and it should appear online, otherwise you
- can check the status of the remote pipeline from the link in the job output.
- If the pipeline failed or got stuck, drop a line in the `#docs` chat channel.
-
-TIP: **Tip:**
-Someone that has no merge rights to the CE/EE projects (think of forks from
-contributors) will not be able to run the manual job. In that case, you can
-ask someone from the GitLab team who has the permissions to do that for you.
-
-NOTE: **Note:**
-Make sure that you always delete the branch of the merge request you were
-working on. If you don't, the remote docs branch won't be removed either,
-and the server where the Review Apps are hosted will eventually be out of
-disk space.
-
-### Technical aspects
-
-If you want to know the hot details, here's what's really happening:
-
-1. You manually run the `review-docs-deploy` job in a CE/EE merge request.
-1. The job runs the [`scripts/trigger-build-docs`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/trigger-build-docs)
- script with the `deploy` flag, which in turn:
- 1. Takes your branch name and applies the following:
- - The slug of the branch name is used to avoid special characters since
- ultimately this will be used by NGINX.
- - The `preview-` prefix is added to avoid conflicts if there's a remote branch
- with the same name that you created in the merge request.
- - The final branch name is truncated to 42 characters to avoid filesystem
- limitations with long branch names (> 63 chars).
- 1. The remote branch is then created if it doesn't exist (meaning you can
- re-run the manual job as many times as you want and this step will be skipped).
- 1. A new cross-project pipeline is triggered in the docs project.
- 1. The preview URL is shown both at the job output and in the merge request
- widget. You also get the link to the remote pipeline.
-1. In the docs project, the pipeline is created and it
- [skips the test jobs](https://gitlab.com/gitlab-com/gitlab-docs/blob/8d5d5c750c602a835614b02f9db42ead1c4b2f5e/.gitlab-ci.yml#L50-55)
- to lower the build time.
-1. Once the docs site is built, the HTML files are uploaded as artifacts.
-1. A specific Runner tied only to the docs project, runs the Review App job
- that downloads the artifacts and uses `rsync` to transfer the files over
- to a location where NGINX serves them.
-
-The following GitLab features are used among others:
-
-- [Manual actions](../../ci/yaml/README.md#manual-actions)
-- [Multi project pipelines](https://docs.gitlab.com/ee/ci/multi_project_pipeline_graphs.html)
-- [Review Apps](../../ci/review_apps/index.md)
-- [Artifacts](../../ci/yaml/README.md#artifacts)
-- [Specific Runner](../../ci/runners/README.md#locking-a-specific-runner-from-being-enabled-for-other-projects)
+ a couple more commits to the EE branch, but ask the reviewer to review the EE merge request
+ additionally to the CE MR. If there are many EE-only changes though, start a new MR
+ to EE only.
## GitLab `/help`
@@ -413,8 +291,8 @@ Every GitLab instance includes the documentation, which is available from `/help
The documentation available online on docs.gitlab.com is continuously
deployed every hour from the `master` branch of CE, EE, Omnibus, and Runner. Therefore,
-once a merge request gets merged, it will be available online on the same day,
-but they will be shipped (and available on `/help`) within the milestone assigned
+once a merge request gets merged, it will be available online on the same day.
+However, they will be shipped (and available on `/help`) within the milestone assigned
to the MR.
For instance, let's say your merge request has a milestone set to 11.3, which
@@ -511,7 +389,7 @@ They should be placed in a new directory named `/article-title/index.md` under a
- **User guides**: technical content to guide regular users from point A to point B
- **Admin guides**: technical content to guide administrators of GitLab instances from point A to point B
- **Technical Overviews**: technical content describing features, solutions, and third-party integrations
-- **Tutorials**: technical content provided step-by-step on how to do things, or how to reach very specific objectives
+- **Tutorials**: technical content provided step-by-step on how to do things, or how to reach specific objectives
#### Understanding guides, tutorials, and technical overviews
@@ -543,7 +421,6 @@ with the following information:
For example:
-
```yaml
---
author: John Doe
@@ -558,5 +435,250 @@ date: 2017-02-01
Use the [writing method](https://about.gitlab.com/handbook/product/technical-writing/#writing-method) defined by the Technical Writing team.
+## Previewing the changes live
+
+NOTE: **Note:**
+To preview your changes to documentation locally, follow this
+[development guide](https://gitlab.com/gitlab-com/gitlab-docs/blob/master/README.md#development-when-contributing-to-gitlab-documentation) or [these instructions for GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/gitlab_docs.md).
+
+The live preview is currently enabled for the following projects:
+
+- <https://gitlab.com/gitlab-org/gitlab-ce>
+- <https://gitlab.com/gitlab-org/gitlab-ee>
+- <https://gitlab.com/gitlab-org/gitlab-runner>
+
+If your branch contains only documentation changes, you can use
+[special branch names](#branch-naming) to avoid long running pipelines.
+
+For [docs-only changes](#branch-naming), the review app is run automatically.
+For all other branches, you can use the manual `review-docs-deploy-manual` job
+in your merge request. You will need at least Maintainer permissions to be able
+to run it. In the mini pipeline graph, you should see an `>>` icon. Clicking on it will
+reveal the `review-docs-deploy-manual` job. Hit the play button for the job to start.
+
+![Manual trigger a docs build](img/manual_build_docs.png)
+
+NOTE: **Note:**
+You will need to push a branch to those repositories, it doesn't work for forks.
+
+The `review-docs-deploy*` job will:
+
+1. Create a new branch in the [gitlab-docs](https://gitlab.com/gitlab-com/gitlab-docs)
+ project named after the scheme: `$DOCS_GITLAB_REPO_SUFFIX-$CI_ENVIRONMENT_SLUG`,
+ where `DOCS_GITLAB_REPO_SUFFIX` is the suffix for each product, e.g, `ce` for
+ CE, etc.
+1. Trigger a cross project pipeline and build the docs site with your changes
+
+After a few minutes, the Review App will be deployed and you will be able to
+preview the changes. The docs URL can be found in two places:
+
+- In the merge request widget
+- In the output of the `review-docs-deploy*` job, which also includes the
+ triggered pipeline so that you can investigate whether something went wrong
+
+TIP: **Tip:**
+Someone that has no merge rights to the CE/EE projects (think of forks from
+contributors) will not be able to run the manual job. In that case, you can
+ask someone from the GitLab team who has the permissions to do that for you.
+
+NOTE: **Note:**
+Make sure that you always delete the branch of the merge request you were
+working on. If you don't, the remote docs branch won't be removed either,
+and the server where the Review Apps are hosted will eventually be out of
+disk space.
+
+### Troubleshooting review apps
+
+In case the review app URL returns 404, follow these steps to debug:
+
+1. **Did you follow the URL from the merge request widget?** If yes, then check if
+ the link is the same as the one in the job output.
+1. **Did you follow the URL from the job output?** If yes, then it means that
+ either the site is not yet deployed or something went wrong with the remote
+ pipeline. Give it a few minutes and it should appear online, otherwise you
+ can check the status of the remote pipeline from the link in the job output.
+ If the pipeline failed or got stuck, drop a line in the `#docs` chat channel.
+
+### Technical aspects
+
+If you want to know the in-depth details, here's what's really happening:
+
+1. You manually run the `review-docs-deploy` job in a CE/EE merge request.
+1. The job runs the [`scripts/trigger-build-docs`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/scripts/trigger-build-docs)
+ script with the `deploy` flag, which in turn:
+ 1. Takes your branch name and applies the following:
+ - The slug of the branch name is used to avoid special characters since
+ ultimately this will be used by NGINX.
+ - The `preview-` prefix is added to avoid conflicts if there's a remote branch
+ with the same name that you created in the merge request.
+ - The final branch name is truncated to 42 characters to avoid filesystem
+ limitations with long branch names (> 63 chars).
+ 1. The remote branch is then created if it doesn't exist (meaning you can
+ re-run the manual job as many times as you want and this step will be skipped).
+ 1. A new cross-project pipeline is triggered in the docs project.
+ 1. The preview URL is shown both at the job output and in the merge request
+ widget. You also get the link to the remote pipeline.
+1. In the docs project, the pipeline is created and it
+ [skips the test jobs](https://gitlab.com/gitlab-com/gitlab-docs/blob/8d5d5c750c602a835614b02f9db42ead1c4b2f5e/.gitlab-ci.yml#L50-55)
+ to lower the build time.
+1. Once the docs site is built, the HTML files are uploaded as artifacts.
+1. A specific Runner tied only to the docs project, runs the Review App job
+ that downloads the artifacts and uses `rsync` to transfer the files over
+ to a location where NGINX serves them.
+
+The following GitLab features are used among others:
+
+- [Manual actions](../../ci/yaml/README.md#manual-actions)
+- [Multi project pipelines](https://docs.gitlab.com/ee/ci/multi_project_pipeline_graphs.html)
+- [Review Apps](../../ci/review_apps/index.md)
+- [Artifacts](../../ci/yaml/README.md#artifacts)
+- [Specific Runner](../../ci/runners/README.md#locking-a-specific-runner-from-being-enabled-for-other-projects)
+
+## Testing
+
+We treat documentation as code, thus have implemented some testing.
+Currently, the following tests are in place:
+
+1. `docs lint`: Check that all internal (relative) links work correctly and
+ that all cURL examples in API docs use the full switches. It's recommended
+ to [check locally](#previewing-locally) before pushing to GitLab by executing the command
+ `bundle exec nanoc check internal_links` on your local
+ [`gitlab-docs`](https://gitlab.com/gitlab-com/gitlab-docs) directory.
+1. [`ee_compat_check`](../automatic_ce_ee_merge.md#avoiding-ce-gt-ee-merge-conflicts-beforehand) (runs on CE only):
+ When you submit a merge request to GitLab Community Edition (CE),
+ there is this additional job that runs against Enterprise Edition (EE)
+ and checks if your changes can apply cleanly to the EE codebase.
+ If that job fails, read the instructions in the job log for what to do next.
+ As CE is merged into EE once a day, it's important to avoid merge conflicts.
+ Submitting an EE-equivalent merge request cherry-picking all commits from CE to EE is
+ essential to avoid them.
+
+### Linting
+
+To help adhere to the [documentation style guidelines](styleguide.md), and to improve the content
+added to documentation, consider locally installing and running documentation linters. This will
+help you catch common issues before raising merge requests for review of documentation.
+
+The following are some suggested linters you can install locally and sample configuration:
+
+- [`proselint`](#proselint)
+- [`markdownlint`](#markdownlint)
+
+NOTE: **Note:**
+This list does not limit what other linters you can add to your local documentation writing toolchain.
+
+#### `proselint`
+
+`proselint` checks for common problems with English prose. It provides a
+ [plethora of checks](http://proselint.com/checks/) that are helpful for technical writing.
+
+`proselint` can be used [on the command line](http://proselint.com/utility/), either on a single
+ Markdown file or on all Markdown files in a project. For example, to run `proselint` on all
+ documentation in the [`gitlab-ce` project](https://gitlab.com/gitlab-org/gitlab-ce), run the
+ following commands from within the `gitlab-ce` project:
+
+```sh
+cd doc
+proselint **/*.md
+```
+
+`proselint` can also be run from within editors using plugins. For example, the following plugins
+ are available:
+
+- [Sublime Text](https://packagecontrol.io/packages/SublimeLinter-contrib-proselint)
+- [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=PatrykPeszko.vscode-proselint)
+- [Others](https://github.com/amperser/proselint#plugins-for-other-software)
+
+##### Sample `proselint` configuration
+
+All of the checks are good to use. However, excluding the `typography.symbols` and `misc.phrasal_adjectives` checks will reduce
+noise. The following sample `proselint` configuration disables these checks:
+
+```json
+{
+ "checks": {
+ "typography.symbols": false,
+ "misc.phrasal_adjectives": false
+ }
+}
+```
+
+A file with `proselint` configuration must be placed in a
+[valid location](https://github.com/amperser/proselint#checks). For example, `~/.config/proselint/config`.
+
+#### `markdownlint`
+
+`markdownlint` checks that certain rules ([example](https://github.com/DavidAnson/markdownlint/blob/master/README.md#rules--aliases))
+ are followed for Markdown syntax. Our [style guidelines](styleguide.md) elaborate on which choices
+ must be made when selecting Markdown syntax for GitLab documentation and this tool helps
+ catch deviations from those guidelines.
+
+`markdownlint` can be used [on the command line](https://github.com/igorshubovych/markdownlint-cli#markdownlint-cli--),
+ either on a single Markdown file or on all Markdown files in a project. For example, to run
+ `markdownlint` on all documentation in the [`gitlab-ce` project](https://gitlab.com/gitlab-org/gitlab-ce),
+ run the following commands from within the `gitlab-ce` project:
+
+```sh
+cd doc
+markdownlint **/*.md
+```
+
+`markdownlint` can also be run from within editors using plugins. For example, the following plugins
+ are available:
+
+- [Sublime Text](https://packagecontrol.io/packages/SublimeLinter-contrib-markdownlint)
+- [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint)
+- [Others](https://github.com/DavidAnson/markdownlint#related)
+
+##### Sample `markdownlint` configuration
+
+The following sample `markdownlint` configuration modifies the available default rules to:
+
+- Adhere to the [style guidelines](styleguide.md).
+- Apply conventions found in the GitLab documentation.
+- Allow the flexibility of using some inline HTML.
+
+```json
+{
+ "default": true,
+ "header-style": { "style": "atx" },
+ "ul-style": { "style": "dash" },
+ "line-length": false,
+ "no-trailing-punctuation": false,
+ "ol-prefix": { "style": "one" },
+ "blanks-around-fences": false,
+ "no-inline-html": {
+ "allowed_elements": [
+ "table",
+ "tbody",
+ "tr",
+ "td",
+ "ul",
+ "ol",
+ "li",
+ "br",
+ "img",
+ "a",
+ "strong",
+ "i",
+ "div"
+ ]
+ },
+ "hr-style": { "style": "---" },
+ "fenced-code-language": false
+}
+```
+
+For [`markdownlint`](https://github.com/DavidAnson/markdownlint/), this configuration must be
+placed in a [valid location](https://github.com/igorshubovych/markdownlint-cli#configuration). For
+example, `~/.markdownlintrc`.
+
+## Danger bot
+
+GitLab uses [danger bot](https://github.com/danger/danger) for some elements in
+code review. For docs changes in merge requests, whenever a change under `/doc`
+is made, the bot leaves a comment for the author to mention `@gl-docsteam`, so
+that the docs can be properly reviewed.
+
[gitlab-map]: https://gitlab.com/gitlab-org/gitlab-design/raw/master/production/resources/gitlab-map.png
[graffle]: https://gitlab.com/gitlab-org/gitlab-design/blob/d8d39f4a87b90fb9ae89ca12dc565347b4900d5e/production/resources/gitlab-map.graffle
diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md
index 1002836096a..607ad21d459 100644
--- a/doc/development/documentation/structure.md
+++ b/doc/development/documentation/structure.md
@@ -21,21 +21,21 @@ Before getting started, read through the following docs:
Every document should include the following content in the following sequence:
- **Feature name**: defines an intuitive name for the feature that clearly
-states what it is and is consistent with any relevant UI text.
+ states what it is and is consistent with any relevant UI text.
- **Feature overview** and description: describe what it is, what it does, and in what context it should be used.
- **Use cases**: describes real use case scenarios for that feature.
- **Requirements**: describes what software and/or configuration is required to be able to
-use the feature and, if applicable, prerequisite knowledge for being able to follow/implement the tutorial.
-For example, familiarity with GitLab CI/CD, an account on a third-party service, dependencies installed, etc.
-Link each one to its most relevant resource; i.e., where the reader can go to begin to fullfil that requirement.
-(Another doc page, a third party application's site, etc.)
+ use the feature and, if applicable, prerequisite knowledge for being able to follow/implement the tutorial.
+ For example, familiarity with GitLab CI/CD, an account on a third-party service, dependencies installed, etc.
+ Link each one to its most relevant resource; i.e., where the reader can go to begin to fullfil that requirement.
+ (Another doc page, a third party application's site, etc.)
- **Instructions**: clearly describes the steps to use the feature, leaving no gaps.
- **Troubleshooting** guide (recommended but not required): if you know beforehand what issues
-one might have when setting it up, or when something is changed, or on upgrading, it's
-important to describe those too. Think of things that may go wrong and include them in the
-docs. This is important to minimize requests for support, and to avoid doc comments with
-questions that you know someone might ask. Answering them beforehand only makes your
-document better and more approachable.
+ one might have when setting it up, or when something is changed, or on upgrading, it's
+ important to describe those too. Think of things that may go wrong and include them in the
+ docs. This is important to minimize requests for support, and to avoid doc comments with
+ questions that you know someone might ask. Answering them beforehand only makes your
+ document better and more approachable.
For additional details, see the subsections below, as well as the [Documentation template for new docs](#Documentation-template-for-new-docs).
@@ -55,10 +55,11 @@ You should answer this question: what can you do with this feature/change? Use c
are examples of how this feature or change can be used in real life.
Examples:
-- CE and EE: [Issues](../user/project/issues/index.md#use-cases)
-- CE and EE: [Merge Requests](../user/project/merge_requests/index.md#overview)
-- EE-only: [Geo](https://docs.gitlab.com/ee/gitlab-geo/README.html#overview)
-- EE-only: [Jenkins integration](https://docs.gitlab.com/ee/integration/jenkins.md#overview)
+
+- CE and EE: [Issues](../../user/project/issues/index.md#use-cases)
+- CE and EE: [Merge Requests](../../user/project/merge_requests/index.md)
+- EE-only: [Geo](https://docs.gitlab.com/ee/administration/geo/replication/index.html)
+- EE-only: [Jenkins integration](https://docs.gitlab.com/ee/integration/jenkins.html)
Note that if you don't have anything to add between the doc title (`<h1>`) and
the header `## Overview`, you can omit the header, but keep the content of the
@@ -72,14 +73,14 @@ and for every **major** feature present in Community Edition.
Your new document will be discoverable by the user only if:
- Crosslinked from the higher-level index (e.g., Issue Boards docs
-should be linked from Issues; Prometheus docs should be linked from
-Monitoring; CI/CD tutorials should be linked from CI/CD examples).
+ should be linked from Issues; Prometheus docs should be linked from
+ Monitoring; CI/CD tutorials should be linked from CI/CD examples).
- When referencing other GitLab products and features, link to their
-respective docs; when referencing third-party products or technologies,
-link out to their external sites, documentation, and resources.
+ respective docs; when referencing third-party products or technologies,
+ link out to their external sites, documentation, and resources.
- The headings are clear. E.g., "App testing" is a bad heading, "Testing
-an application with GitLab CI/CD" is much better. Think of something
-someone will search for and use these keywords in the headings.
+ an application with GitLab CI/CD" is much better. Think of something
+ someone will search for and use these keywords in the headings.
## Documentation template for new docs
@@ -133,7 +134,7 @@ is simple and the document is short.
- Be clear, concise, and stick to the goal of the doc: explain how to
use that feature.
- Use inclusive language and avoid jargons, as well as uncommon and
-fancy words. The docs should be clear and very easy to understand.
+fancy words. The docs should be clear and easy to understand.
- Write in the 3rd person (use "we", "you", "us", "one", instead of "I" or "me").
- Always provide internal and external reference links.
- Always link the doc from its higher-level index.
@@ -141,9 +142,49 @@ fancy words. The docs should be clear and very easy to understand.
<!-- ## Troubleshooting
Add a troubleshooting guide when possible/applicable. -->
-```
+
+---
Notes:
-- (1): Apply the [tier badges](styleguide.md#product-badges) accordingly
-- (2): Apply the correct format for the [GitLab version introducing the feature](styleguide.md#gitlab-versions-and-tiers)
+- (1): Apply the [tier badges](https://docs.gitlab.com/ee/development/documentation/styleguide.html#product-badges) accordingly
+- (2): Apply the correct format for the [GitLab version introducing the feature](https://docs.gitlab.com/ee/development/documentation/styleguide.html#gitlab-versions-and-tiers)
+```
+
+## Help and feedback section
+
+The "help and feedback" section (introduced by [!319](https://gitlab.com/gitlab-com/gitlab-docs/merge_requests/319)) displayed at the end of each document
+can be omitted from the doc by adding a key into the its frontmatter:
+
+```yaml
+---
+feedback: false
+---
+```
+
+The default is to leave it there. If you want to omit it from a document,
+you must check with a technical writer before doing so.
+
+### Disqus
+
+We also have integrated the docs site with Disqus (introduced by
+[!151](https://gitlab.com/gitlab-com/gitlab-docs/merge_requests/151)),
+allowing our users to post comments.
+
+To omit only the comments from the feedback section, use the following
+key on the frontmatter:
+
+```yaml
+---
+comments: false
+---
+```
+
+We are only hiding comments in main index pages, such as [the main documentation index](../../README.md), since its content is too broad to comment on. Before omitting Disqus,
+you must check with a technical writer.
+
+Note that once `feedback: false` is added to the frontmatter, it will automatically omit
+Disqus, therefore, don't add both keys to the same document.
+
+The click events in the feedback section are tracked with Google Tag Manager. The
+conversions can be viewed on Google Analytics by navigating to **Behavior > Events > Top events > docs**.
diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md
index 8083f219d4a..8309ba9a72c 100644
--- a/doc/development/documentation/styleguide.md
+++ b/doc/development/documentation/styleguide.md
@@ -10,15 +10,15 @@ GitLab documentation. Check the
Check the GitLab handbook for the [writing styles guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines).
+For help adhering to the guidelines, see [linting](index.md#linting).
+
## Files
- [Directory structure](index.md#location-and-naming-documents): place the docs
in the correct location.
- [Documentation files](index.md#documentation-files): name the files accordingly.
-- [Markdown](../../user/markdown.md): use the GitLab Flavored Markdown in the
-documentation.
-NOTE: **Note:**
+DANGER: **Attention:**
**Do not** use capital letters, spaces, or special chars in file names,
branch names, directory names, headings, or in anything that generates a path.
@@ -26,65 +26,144 @@ NOTE: **Note:**
**Do not** create new `README.md` files, name them `index.md` instead. There's
a test that will fail if it spots a new `README.md` file.
-## Text
+### Markdown
+
+The [documentation website](https://docs.gitlab.com) had its markdown engine migrated from [Redcarpet to GitLab Kramdown](https://gitlab.com/gitlab-com/gitlab-docs/merge_requests/108)
+in October, 2018.
+
+The [`gitlab-kramdown`](https://gitlab.com/gitlab-org/gitlab_kramdown)
+gem will support all [GFM markup](../../user/markdown.md) in the future. For now,
+use regular markdown markup, following the rules on this style guide. For a complete
+Kramdown reference, check the [GiLab Markdown Kramdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/).
+Use Kramdown markup wisely: do not overuse its specific markup (e.g., `{:.class}`) as it will not render properly in
+[`/help`](#gitlab-help).
+
+## Content
-- Split up long lines (wrap text), this makes it much easier to review and edit. Only
- double line breaks are shown as a full line break in [GitLab markdown][gfm].
- 80-100 characters is a good line length.
- Make sure that the documentation is added in the correct
- [directory](index.md#documentation-directory-structure) and that
- there's a link to it somewhere useful.
+ [directory](index.md#documentation-directory-structure), linked from its
+ higher-level index, and linked from other related pages.
- Do not duplicate information.
- Be brief and clear.
-- Unless there's a logical reason not to, add documents in alphabetical order.
+- Unless there's a logical reason not to, structure the document in alphabetical order
+(headings, tables, and lists).
- Write in US English.
-- Use [single spaces][] instead of double spaces.
-- Jump a line between different markups (e.g., after every paragraph, header, list, etc)
- Capitalize "G" and "L" in GitLab.
-- Use sentence case for titles, headings, labels, menu items, and buttons.
- Use title case when referring to [features](https://about.gitlab.com/features/) or
[products](https://about.gitlab.com/pricing/) (e.g., GitLab Runner, Geo,
Issue Boards, GitLab Core, Git, Prometheus, Kubernetes, etc), and methods or methodologies
(e.g., Continuous Integration, Continuous Deployment, Scrum, Agile, etc). Note that
-some features are also objects (e.g. "Merge Requests" and "merge requests").
+some features are also objects (e.g. "GitLab's Merge Requests support X." and "Create a new merge request for Z.").
-## Formatting
+## Text
+
+- Split up long lines (wrap text), this makes it much easier to review and edit. Only
+ double line breaks are shown as a full line break by creating new paragraphs.
+ 80-100 characters is the recommended line length.
+- Use sentence case for titles, headings, labels, menu items, and buttons.
+- Jump a line between different markups (e.g., after every paragraph, header, list, etc). Example:
-- Use double asterisks (`**`) to mark a word or text in bold (`**bold**`).
-- Use undescore (`_`) for text in italics (`_italic_`).
-- Put an empty line between different markups. For example:
```md
## Header
Paragraph.
- - List item
- - List item
+ - List item 1
+ - List item 2
```
-### Punctuation
+## Emphasis
+
+- Use double asterisks (`**`) to mark a word or text in bold (`**bold**`).
+- Use undescore (`_`) for text in italics (`_italic_`).
+- Use greater than (`>`) for blockquotes.
+
+## Punctuation
+
+Check the general punctuation rules for the GitLab documentation on the table below.
+Check specific punctuation rules for [list items](#list-items) below.
+
+| Rule | Example |
+| ---- | ------- |
+| Always end full sentences with a period. | _For a complete overview, read through this document._|
+| Always add a space after a period when beginning a new sentence | _For a complete overview, check this doc. For other references, check out this guide._ |
+| Do not use double spaces. | --- |
+| Do not use tabs for indentation. Use spaces instead. You can configure your code editor to output spaces instead of tabs when pressing the tab key. | --- |
+| Use serial commas ("Oxford commas") before the final 'and/or' in a list. | _You can create new issues, merge requests, and milestones._ |
+| Always add a space before and after dashes when using it in a sentence (for replacing a comma, for example). | _You should try this - or not._ |
+| Always use lowercase after a colon. | _Related Issues: a way to create a relationship between issues._ |
-For punctuation rules, please refer to the [GitLab UX guide](https://design.gitlab.com/content/punctuation/).
+## List items
-### Ordered and unordered lists
+- Always start list items with a capital letter.
+- Always leave a blank line before and after a list.
+- Begin a line with spaces (not tabs) to denote a subitem.
+- To nest subitems, indent them with two spaces.
+- To nest code blocks, indent them with four spaces.
+- Only use ordered lists when their items describe a sequence of steps to follow.
-- Use dashes (`-`) for unordered lists instead of asterisks (`*`).
-- Use the number one (`1`) for ordered lists.
+**Markup:**
+
+- Use dashes (`- `) for unordered lists instead of asterisks (`* `).
+- Use the number one (`1`) for each item in an ordered list.
+When rendered, the list items will appear with sequential numbering.
+
+**Punctuation:**
+
+- Do not add commas (`,`) or semicolons (`;`) to the end of a list item.
+- Only add periods to the end of a list item if the item consists of a complete sentence. The [definition of full sentence](https://www2.le.ac.uk/offices/ld/resources/writing/grammar/grammar-guides/sentence) is: _"a complete sentence always contains a verb, expresses a complete idea, and makes sense standing alone"_.
+- Be consistent throughout the list: if the majority of the items do not end in a period, do not end any of the items in a period, even if they consist of a complete sentence. The opposite is also valid: if the majority of the items end with a period, end all with a period.
- Separate list items from explanatory text with a colon (`:`). For example:
+
```md
The list is as follows:
- - First item: This explains the first item.
- - Second item: This explains the second item.
+ - First item: this explains the first item.
+ - Second item: this explains the second item.
```
-- For further guidance on punctuation in bullet lists, please refer to the [GitLab UX guide](https://design.gitlab.com/content/punctuation/).
+
+**Examples:**
+
+Do:
+
+- First list item
+- Second list item
+- Third list item
+
+Don't:
+
+- First list item
+- Second list item
+- Third list item.
+
+Do:
+
+- Let's say this is a complete sentence.
+- Let's say this is also a complete sentence.
+- Not a complete sentence.
+
+Don't:
+
+- Let's say this is a complete sentence.
+- Let's say this is also a complete sentence.
+- Not a complete sentence
+
+## Quotes
+
+Valid for markdown content only, not for frontmatter entries:
+
+- Standard quotes: double quotes (`"`). Example: "This is wrapped in double quotes".
+- Quote within a quote: double quotes (`"`) wrap single quotes (`'`). Example: "I am 'quoting' something within a quote".
+
+For other punctuation rules, please refer to the
+[GitLab UX guide](https://design.gitlab.com/content/punctuation/).
## Headings
- Add **only one H1** in each document, by adding `#` at the beginning of
it (when using markdown). The `h1` will be the document `<title>`.
-- Start with an h2 (`##`), and respect the order h2 > h3 > h4 > h5 > h6.
- Never skip the hierarchy level, such as h2 > h4
+- Start with an `h2` (`##`), and respect the order `h2` > `h3` > `h4` > `h5` > `h6`.
+ Never skip the hierarchy level, such as `h2` > `h4`
- Avoid putting numbers in headings. Numbers shift, hence documentation anchor
links shift too, which eventually leads to dead links. If you think it is
compelling to add numbers in headings, make sure to at least discuss it with
@@ -94,21 +173,19 @@ For punctuation rules, please refer to the [GitLab UX guide](https://design.gitl
- Avoid adding things that show ephemeral statuses. For example, if a feature is
considered beta or experimental, put this info in a note, not in the heading.
- When introducing a new document, be careful for the headings to be
- grammatically and syntactically correct. Mention one or all
- of the following GitLab members for a review: `@axil` or `@marcia`.
+ grammatically and syntactically correct. Mention an [assigned technical writer (TW)](https://about.gitlab.com/handbook/product/categories/)
+ for review.
This is to ensure that no document with wrong heading is going
live without an audit, thus preventing dead links and redirection issues when
corrected.
- Leave exactly one new line after a heading.
+- Do not use links in headings.
+- Add the corresponding [product badge](#product-badges) according to the tier the feature belongs.
## Links
-- Use the regular inline link markdown markup `[Text](https://example.com)`.
- It's easier to read, review, and maintain.
-- If there's a link that repeats several times through the same document,
- you can use `[Text][identifier]` and at the bottom of the section or the
- document add: `[identifier]: https://example.com`, in which case, we do
- encourage you to also add an alternative text: `[identifier]: https://example.com "Alternative text"` that appears when hovering your mouse on a link.
+- Use inline link markdown markup `[Text](https://example.com)`.
+ It's easier to read, review, and maintain. **Do not** use `[Text][identifier]`.
- To link to internal documentation, use relative links, not full URLs. Use `../` to
navigate tp high-level directories, and always add the file name `file.md` at the
end of the link with the `.md` extension, not `.html`.
@@ -126,11 +203,12 @@ For punctuation rules, please refer to the [GitLab UX guide](https://design.gitl
To indicate the steps of navigation through the UI:
+
- Use the exact word as shown in the UI, including any capital letters as-is.
-- Use bold text for navigation items and the char `>` as separator
+- Use bold text for navigation items and the char "greater than" (`>`) as separator
(e.g., `Navigate to your project's **Settings > CI/CD**` ).
- If there are any expandable menus, make sure to mention that the user
-needs to expand the tab to find the settings you're referring to.
+needs to expand the tab to find the settings you're referring to (e.g., `Navigate to your project's **Settings > CI/CD** and expand **General pipelines**`).
## Images
@@ -139,7 +217,7 @@ needs to expand the tab to find the settings you're referring to.
names with the name of the document that they will be included in. For
example, if there is a document called `twitter.md`, then a valid image name
could be `twitter_login_screen.png`.
-- Images should have a specific, non-generic name that will differentiate them.
+- Images should have a specific, non-generic name that will differentiate and describe them properly.
- Keep all file names in lower case.
- Consider using PNG images instead of JPEG.
- Compress all images with <https://tinypng.com/> or similar tool.
@@ -162,13 +240,39 @@ Inside the document:
- If a heading is placed right after an image, always add three dashes (`---`)
between the image and the heading.
+## Code blocks
+
+- Always wrap code added to a sentence in inline code blocks (``` ` ```).
+E.g., `.gitlab-ci.yml`, `git add .`, `CODEOWNERS`, `only: master`.
+File names, commands, entries, and anything that refers to code should be added to code blocks.
+To make things easier for the user, always add a full code block for things that can be
+useful to copy and paste, as they can easily do it with the button on code blocks.
+- For regular code blocks, always use a highlighting class corresponding to the
+language for better readability. Examples:
+
+ ```md
+ ```ruby
+ Ruby code
+ ```
+
+ ```js
+ JavaScript code
+ ```
+
+ ```md
+ Markdown code
+ ```
+ ```
+
+- For a complete reference on code blocks, check the [Kramdown guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/#code-blocks).
+
## Alert boxes
Whenever you want to call the attention to a particular sentence,
use the following markup for highlighting.
_Note that the alert boxes only work for one paragraph only. Multiple paragraphs,
-lists, headers, etc will not render correctly._
+lists, headers, etc will not render correctly. For multiple lines, use blockquotes instead._
### Note
@@ -232,6 +336,31 @@ which renders in docs.gitlab.com to:
If the text spans across multiple lines it's OK to split the line.
+For multiple paragraphs, use the symbol `>` before every line:
+
+```md
+> This is the first paragraph.
+>
+> This is the second paragraph.
+>
+> - This is a list item
+> - Second item in the list
+>
+> ### This is an `h3`
+```
+
+Which renders to:
+
+> This is the first paragraph.
+>
+> This is the second paragraph.
+>
+> - This is a list item
+> - Second item in the list
+>
+> ### This is an `h3`
+>{:.no_toc}
+
## Specific sections and terms
To mention and/or reference specific terms in GitLab, please follow the styles
@@ -251,7 +380,7 @@ below.
(in that order) that introduced it. The above quote would be then transformed to:
```md
- > [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/1242) in GitLab 8.3.
+ > [Introduced](<link-to-issue>) in GitLab 8.3.
```
- If the feature is only available in GitLab Enterprise Edition, don't forget to mention
@@ -259,10 +388,22 @@ below.
the feature is available in:
```md
- > [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/1242)
- in [GitLab Starter](https://about.gitlab.com/pricing/) 8.3.
+ > [Introduced](<link-to-issue>) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3.
```
+#### Early versions of EE
+
+If the feature was created before GitLab 9.2 (before [different EE tiers were introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1851)):
+
+- Declare it as "Introduced in GitLab Enterprise Edition X.Y".
+- Note which tier the feature is available in.
+
+For example:
+
+```md
+> [Introduced](<link-to-issue>) in GitLab Enterprise Edition 9.0. Available in [GitLab Premium](https://about.gitlab.com/pricing/).
+```
+
### Product badges
When a feature is available in EE-only tiers, add the corresponding tier according to the
@@ -276,18 +417,18 @@ feature availability:
To exclude GitLab.com tiers (when the feature is not available in GitLab.com), add the
keyword "only":
+- For GitLab Core: `**[CORE ONLY]**`.
- For GitLab Starter: `**[STARTER ONLY]**`.
- For GitLab Premium: `**[PREMIUM ONLY]**`.
- For GitLab Ultimate: `**[ULTIMATE ONLY]**`.
-- For GitLab Core: `**[CORE ONLY]**`.
The tier should be ideally added to headers, so that the full badge will be displayed.
-But it can be also mentioned from paragraphs, list items, and table cells. For these cases,
-the tier mention will be represented by an orange question mark.
+However, it can be also mentioned from paragraphs, list items, and table cells. For these cases,
+the tier mention will be represented by an orange question mark that will show the tiers on hover.
E.g., `**[STARTER]**` renders **[STARTER]**, `**[STARTER ONLY]**` renders **[STARTER ONLY]**.
The absence of tiers' mentions mean that the feature is available in GitLab Core,
-GitLab.com Free, and higher tiers.
+GitLab.com Free, and all higher tiers.
#### How it works
@@ -303,7 +444,7 @@ avoid duplication, link to the special document that can be found in
[`doc/administration/restart_gitlab.md`][doc-restart]. Usually the text will
read like:
-```
+```md
Save the file and [reconfigure GitLab](../../administration/restart_gitlab.md)
for the changes to take effect.
```
@@ -334,8 +475,8 @@ prefer to document it in the CE docs to avoid duplication.
Configuration settings include:
-- Settings that touch configuration files in `config/`.
-- NGINX settings and settings in `lib/support/` in general.
+1. Settings that touch configuration files in `config/`.
+1. NGINX settings and settings in `lib/support/` in general.
When there is a list of steps to perform, usually that entails editing the
configuration file and reconfiguring/restarting GitLab. In such case, follow
@@ -372,13 +513,13 @@ the style below as a guide:
In this case:
-- before each step list the installation method is declared in bold
-- three dashes (`---`) are used to create a horizontal line and separate the
+- Before each step list the installation method is declared in bold
+- Three dashes (`---`) are used to create a horizontal line and separate the
two methods
-- the code blocks are indented one or more spaces under the list item to render
+- The code blocks are indented one or more spaces under the list item to render
correctly
-- different highlighting languages are used for each config in the code block
-- the [references](#references) guide is used for reconfigure/restart
+- Different highlighting languages are used for each config in the code block
+- The [references](#references) guide is used for reconfigure/restart
### Fake tokens
@@ -389,19 +530,19 @@ low.
You can use the following fake tokens as examples.
-| **Token type** | **Token value** |
-| --------------------- | --------------------------------- |
-| Private user token | `9koXpg98eAheJpvBs5tK` |
-| Personal access token | `n671WNGecHugsdEDPsyo` |
+| **Token type** | **Token value** |
+|:----------------------|:-------------------------------------------------------------------|
+| Private user token | `9koXpg98eAheJpvBs5tK` |
+| Personal access token | `n671WNGecHugsdEDPsyo` |
| Application ID | `2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6` |
| Application secret | `04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df` |
-| Secret CI variable | `Li8j-mLUVA3eZYjPfd_H` |
-| Specific Runner token | `yrnZW46BrtBFqM7xDzE7dddd` |
-| Shared Runner token | `6Vk7ZsosqQyfreAxXTZr` |
-| Trigger token | `be20d8dcc028677c931e04f3871a9b` |
-| Webhook secret token | `6XhDroRcYPM5by_h-HLY` |
-| Health check token | `Tu7BgjR9qeZTEyRzGG2P` |
-| Request profile token | `7VgpS4Ax5utVD2esNstz` |
+| CI/CD variable | `Li8j-mLUVA3eZYjPfd_H` |
+| Specific Runner token | `yrnZW46BrtBFqM7xDzE7dddd` |
+| Shared Runner token | `6Vk7ZsosqQyfreAxXTZr` |
+| Trigger token | `be20d8dcc028677c931e04f3871a9b` |
+| Webhook secret token | `6XhDroRcYPM5by_h-HLY` |
+| Health check token | `Tu7BgjR9qeZTEyRzGG2P` |
+| Request profile token | `7VgpS4Ax5utVD2esNstz` |
### API
@@ -424,16 +565,16 @@ on this document. Further explanation is given below.
Use the following table headers to describe the methods. Attributes should
always be in code blocks using backticks (``` ` ```).
-```
+```md
| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
+|:----------|:-----|:---------|:------------|
```
Rendered example:
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `user` | string | yes | The GitLab username |
+| Attribute | Type | Required | Description |
+|:----------|:-------|:---------|:--------------------|
+| `user` | string | yes | The GitLab username |
#### cURL commands
@@ -445,12 +586,12 @@ Rendered example:
- Prefer to use examples using the personal access token and don't pass data of
username and password.
-| Methods | Description |
-| ------- | ----------- |
+| Methods | Description |
+|:-------------------------------------------|:------------------------------------------------------|
| `-H "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK"` | Use this method as is, whenever authentication needed |
-| `-X POST` | Use this method when creating new objects |
-| `-X PUT` | Use this method when updating existing objects |
-| `-X DELETE` | Use this method when removing existing objects |
+| `-X POST` | Use this method when creating new objects |
+| `-X PUT` | Use this method when updating existing objects |
+| `-X DELETE` | Use this method when removing existing objects |
#### cURL Examples
diff --git a/doc/development/documentation/workflow.md b/doc/development/documentation/workflow.md
index 52bc059a925..75ce8640e87 100644
--- a/doc/development/documentation/workflow.md
+++ b/doc/development/documentation/workflow.md
@@ -7,16 +7,16 @@ description: Learn the process of shipping documentation for GitLab.
At GitLab, developers contribute new or updated documentation along with their code, but product managers and technical writers also have essential roles in the process.
- Product Managers (PMs): in the issue for all new and updated features,
-PMs include specific documentation requirements that the developer who is
-writing or updating the docs must meet, along with feature descriptions
-and use cases. They call out any specific areas where collaborating with
-a technical writer is recommended, and usually act as the first reviewer
-of the docs.
+ PMs include specific documentation requirements that the developer who is
+ writing or updating the docs must meet, along with feature descriptions
+ and use cases. They call out any specific areas where collaborating with
+ a technical writer is recommended, and usually act as the first reviewer
+ of the docs.
- Developers: author documentation and merge it on time (up to a week after
-the feature freeze).
+ the feature freeze).
- Technical Writers: review each issue to ensure PM's requirements are complete,
-help developers with any questions throughout the process, and act as the final
-reviewer of all new and updated docs content before it's merged.
+ help developers with any questions throughout the process, and act as the final
+ reviewer of all new and updated docs content before it's merged.
## Requirements
@@ -112,17 +112,17 @@ and the missed-deliverable due date (the 14th of each month) are both respected.
The developer should add to the feature MR the documentation containing:
- The [documentation blurb](structure.md#documentation-blurb): copy the
-feature name, overview/description, and use cases from the feature issue
+ feature name, overview/description, and use cases from the feature issue
- Instructions: write how to use the feature, step by step, with no gaps.
- [Crosslink for discoverability](structure.md#discoverability): link with
-internal docs and external resources (if applicable)
+ internal docs and external resources (if applicable)
- Index: link the new doc or the new heading from the higher-level index
-for [discoverability](#discoverability)
+ for [discoverability](#discoverability)
- [Screenshots](styleguide.md#images): when necessary, add screenshots for:
- Illustrating a step of the process
- Indicating the location of a navigation menu
- Label the MR with `Documentation`, `Deliverable`, `docs-P1`, and assign
-the correct milestone
+ the correct milestone
- Assign the PM for review
- When done, mention the `@gl\-docsteam` in the MR asking for review
- **Due date**: feature freeze date and time
@@ -133,10 +133,10 @@ If the docs aren't being shipped within the feature MR:
- Create a new issue mentioning "docs" or "documentation" in the title (use the Documentation issue description template)
- Label the issue with: `Documentation`, `Deliverable`, `docs-P1`, `<product-label>`
-(product label == CI/CD, Pages, Prometheus, etc)
+ (product label == CI/CD, Pages, Prometheus, etc)
- Add the correct milestone
- Create a new MR for shipping the docs changes and follow the same
-process [described above](#documentation-shipped-in-the-feature-mr)
+ process [described above](#documentation-shipped-in-the-feature-mr)
- Use the MR description template called "Documentation"
- Add the same labels and milestone as you did for the issue
- Assign the PM for review
@@ -162,9 +162,9 @@ The **due date** for **merging** `missed-deliverable` MRs is on the
- **Planning**
- Once an issue contains a Documentation label and the current milestone, a
-technical writer reviews the Product Manager's documentation requirements
+ technical writer reviews the Product Manager's documentation requirements.
- Once the documentation requirements are approved, the technical writer can
-work with the developer to discuss any documentation questions and plans/outlines, as needed.
+ work with the developer to discuss any documentation questions and plans/outlines, as needed.
- **Review** - A technical writer must review the documentation for:
- Clarity
@@ -183,4 +183,3 @@ work with the developer to discuss any documentation questions and plans/outline
- Describe the difference between new features and feature updates
- Creating a new doc vs updating an existing doc
-->
-
diff --git a/doc/development/ee_features.md b/doc/development/ee_features.md
index f9e6efa2c30..790b1bf951b 100644
--- a/doc/development/ee_features.md
+++ b/doc/development/ee_features.md
@@ -119,10 +119,20 @@ This also applies to views.
### EE features based on CE features
-For features that build on existing CE features, write a module in the
-`EE` namespace and `prepend` it in the CE class. This makes conflicts
-less likely to happen during CE to EE merges because only one line is
-added to the CE class - the `prepend` line.
+For features that build on existing CE features, write a module in the `EE`
+namespace and `prepend` it in the CE class, on the last line of the file that
+the class resides in. This makes conflicts less likely to happen during CE to EE
+merges because only one line is added to the CE class - the `prepend` line. For
+example, to prepend a module into the `User` class you would use the following
+approach:
+
+```ruby
+class User < ActiveRecord::Base
+ # ... lots of code here ...
+end
+
+User.prepend(EE::User)
+```
Since the module would require an `EE` namespace, the file should also be
put in an `ee/` sub-directory. For example, we want to extend the user model
@@ -171,7 +181,7 @@ There are a few gotchas with it:
class Base
def execute
return unless enabled?
-
+
# ...
# ...
end
@@ -185,12 +195,12 @@ There are a few gotchas with it:
class Base
def execute
return unless enabled?
-
+
do_something
end
-
+
private
-
+
def do_something
# ...
# ...
@@ -204,14 +214,14 @@ There are a few gotchas with it:
```ruby
module EE::Base
extend ::Gitlab::Utils::Override
-
+
override :do_something
def do_something
# Follow the above pattern to call super and extend it
end
end
```
-
+
This would require updating CE first, or make sure this is back ported to CE.
When prepending, place them in the `ee/` specific sub-directory, and
@@ -231,7 +241,6 @@ the existing file:
```ruby
class ApplicationController < ActionController::Base
- prepend EE::ApplicationController
# ...
def after_sign_out_path_for(resource)
@@ -240,6 +249,8 @@ class ApplicationController < ActionController::Base
# ...
end
+
+ApplicationController.prepend(EE::ApplicationController)
```
And create a new file in the `ee/` sub-directory with the altered
@@ -332,6 +343,21 @@ full implementation details.
[ce-mr-full-private]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12373
[ee-mr-full-private]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2199
+### Code in `config/routes`
+
+When we add `draw :admin` in `config/routes.rb`, the application will try to
+load the file located in `config/routes/admin.rb`, and also try to load the
+file located in `ee/config/routes/admin.rb`.
+
+In EE, it should at least load one file, at most two files. If it cannot find
+any files, an error will be raised. In CE, since we don't know if there will
+be an EE route, it will not raise any errors even if it cannot find anything.
+
+This means if we want to extend a particular CE route file, just add the same
+file located in `ee/config/routes`. If we want to add an EE only route, we
+could still put `draw :ee_only` in both CE and EE, and add
+`ee/config/routes/ee_only.rb` in EE, similar to `render_if_exists`.
+
### Code in `app/controllers/`
In controllers, the most common type of conflict is with `before_action` that
@@ -393,7 +419,7 @@ view. For instance the approval code in the project's settings page.
**Mitigations**
Blocks of code that are EE-specific should be moved to partials. This
-avoids conflicts with big chunks of HAML code that that are not fun to
+avoids conflicts with big chunks of HAML code that are not fun to
resolve when you add the indentation to the equation.
EE-specific views should be placed in `ee/app/views/`, using extra
@@ -485,7 +511,7 @@ module EE
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: ::API::API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: ::API::API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
# ...
end
end
@@ -518,8 +544,6 @@ module API
end
end
- prepend EE::API::MergeRequests
-
params :optional_params do
# CE specific params go here...
@@ -527,6 +551,8 @@ module API
end
end
end
+
+API::MergeRequests.prepend(EE::API::MergeRequests)
```
And then we could override it in EE module:
@@ -567,10 +593,10 @@ module API
authorize_read_builds!
end
end
-
- prepend EE::API::JobArtifacts
end
end
+
+API::JobArtifacts.prepend(EE::API::JobArtifacts)
```
And then we can follow regular object-oriented practices to override it:
@@ -611,8 +637,6 @@ module API
end
end
- prepend EE::API::MergeRequests
-
put ':id/merge_requests/:merge_request_iid/merge' do
merge_request = find_project_merge_request(params[:merge_request_iid])
@@ -624,6 +648,8 @@ module API
end
end
end
+
+API::MergeRequests.prepend(EE::API::MergeRequests)
```
Note that `update_merge_request_ee` doesn't do anything in CE, but
@@ -661,27 +687,37 @@ or not we really need to extend it from EE. For now we're not using it much.
Sometimes we need to use different arguments for a particular API route, and we
can't easily extend it with an EE module because Grape has different context in
-different blocks. In order to overcome this, we could use class methods from the
-API class.
+different blocks. In order to overcome this, we need to move the data to a class
+method that resides in a separate module or class. This allows us to extend that
+module or class before its data is used, without having to place a `prepend` in
+the middle of CE code.
For example, in one place we need to pass an extra argument to
`at_least_one_of` so that the API could consider an EE-only argument as the
-least argument. This is not quite beautiful but it's working:
+least argument. We would approach this as follows:
```ruby
+# api/merge_requests/parameters.rb
module API
class MergeRequests < Grape::API
- def self.update_params_at_least_one_of
- %i[
- assignee_id
- description
- ]
+ module Parameters
+ def self.update_params_at_least_one_of
+ %i[
+ assignee_id
+ description
+ ]
+ end
end
+ end
+end
- prepend EE::API::MergeRequests
+API::MergeRequests::Parameters.prepend(EE::API::MergeRequests::Parameters)
+# api/merge_requests.rb
+module API
+ class MergeRequests < Grape::API
params do
- at_least_one_of(*::API::MergeRequests.update_params_at_least_one_of)
+ at_least_one_of(*Parameters.update_params_at_least_one_of)
end
end
end
@@ -693,16 +729,18 @@ And then we could easily extend that argument in the EE class method:
module EE
module API
module MergeRequests
- extend ActiveSupport::Concern
+ module Parameters
+ extend ActiveSupport::Concern
- class_methods do
- extend ::Gitlab::Utils::Override
+ class_methods do
+ extend ::Gitlab::Utils::Override
- override :update_params_at_least_one_of
- def update_params_at_least_one_of
- super.push(*%i[
- squash
- ])
+ override :update_params_at_least_one_of
+ def update_params_at_least_one_of
+ super.push(*%i[
+ squash
+ ])
+ end
end
end
end
@@ -713,6 +751,78 @@ end
It could be annoying if we need this for a lot of routes, but it might be the
simplest solution right now.
+This approach can also be used when models define validations that depend on
+class methods. For example:
+
+```ruby
+# app/models/identity.rb
+class Identity < ActiveRecord::Base
+ def self.uniqueness_scope
+ [:provider]
+ end
+
+ prepend EE::Identity
+
+ validates :extern_uid,
+ allow_blank: true,
+ uniqueness: { scope: uniqueness_scope, case_sensitive: false }
+end
+
+# ee/app/models/ee/identity.rb
+module EE
+ module Identity
+ extend ActiveSupport::Concern
+
+ class_methods do
+ extend ::Gitlab::Utils::Override
+
+ def uniqueness_scope
+ [*super, :saml_provider_id]
+ end
+ end
+ end
+end
+```
+
+Instead of taking this approach, we would refactor our code into the following:
+
+```ruby
+# ee/app/models/ee/identity/uniqueness_scopes.rb
+module EE
+ module Identity
+ module UniquenessScopes
+ extend ActiveSupport::Concern
+
+ class_methods do
+ extend ::Gitlab::Utils::Override
+
+ def uniqueness_scope
+ [*super, :saml_provider_id]
+ end
+ end
+ end
+ end
+end
+
+# app/models/identity/uniqueness_scopes.rb
+class Identity < ActiveRecord::Base
+ module UniquenessScopes
+ def self.uniqueness_scope
+ [:provider]
+ end
+ end
+end
+
+Identity::UniquenessScopes.prepend(EE::Identity::UniquenessScopes)
+
+# app/models/identity.rb
+class Identity < ActiveRecord::Base
+ validates :extern_uid,
+ allow_blank: true,
+ uniqueness: { scope: Identity::UniquenessScopes.scopes, case_sensitive: false }
+end
+```
+
### Code in `spec/`
When you're testing EE-only features, avoid adding examples to the
diff --git a/doc/development/fe_guide/components.md b/doc/development/fe_guide/components.md
index ee0c2d534ff..0e9126ee667 100644
--- a/doc/development/fe_guide/components.md
+++ b/doc/development/fe_guide/components.md
@@ -6,7 +6,7 @@
## Dropdowns
-See also the [corresponding UX guide](../ux_guide/components.md#dropdowns).
+See also the [corresponding UX guide](https://design.gitlab.com/#/components/dropdowns).
### How to style a bootstrap dropdown
1. Use the HTML structure provided by the [docs][bootstrap-dropdowns]
@@ -40,7 +40,7 @@ See also the [corresponding UX guide](../ux_guide/components.md#dropdowns).
## Modals
-See also the [corresponding UX guide](../ux_guide/components.md#modals).
+See also the [corresponding UX guide](https://design.gitlab.com/#/components/modals).
We have a reusable Vue component for modals: [vue_shared/components/gl_modal.vue](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/javascripts/vue_shared/components/gl_modal.vue)
diff --git a/doc/development/fe_guide/droplab/droplab.md b/doc/development/fe_guide/droplab/droplab.md
index 112ff3419d9..ce96a9fc8ae 100644
--- a/doc/development/fe_guide/droplab/droplab.md
+++ b/doc/development/fe_guide/droplab/droplab.md
@@ -123,7 +123,7 @@ droplab.init().addData([{
```
Alternatively, you can specify a specific dropdown to add this data to but passing
-the data as the second argument and and the `id` of the trigger element as the first argument.
+the data as the second argument and the `id` of the trigger element as the first argument.
```html
<a href="#" data-dropdown-trigger="#list" id="trigger">Toggle</a>
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
new file mode 100644
index 00000000000..f55f01720fd
--- /dev/null
+++ b/doc/development/fe_guide/graphql.md
@@ -0,0 +1,83 @@
+# GraphQL
+
+We use [Apollo] and [Vue Apollo][vue-apollo] for working with GraphQL
+on the frontend.
+
+In order to use GraphQL, you need to enable the `graphql` feature flag,
+read more about [Feature Flags][feature-flags].
+
+## Apollo Client
+
+To save duplicated clients getting created in different apps, we have a
+[default client][defualt-client] that should be used. This setups the
+Apollo client with the correct URL and also sets the CSRF headers.
+
+## GraphQL Queries
+
+To save query compilation at runtime, webpack can directly import `.graphql`
+files. This allows webpack to preprocess the query at compile time instead
+of the client doing compilation of queries.
+
+## Usage in Vue
+
+To use Vue Apollo, import the [Vue Apollo][vue-apollo] plugin as well
+as the default client. This should be created at the same point
+the Vue application is mounted.
+
+```javascript
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import defaultClient from '~/lib/graphql';
+Vue.use(VueApollo);
+
+const apolloProvider = new VueApollo({
+ defaultClient,
+});
+
+new Vue({
+ ...,
+ apolloProvider,
+ ...
+});
+```
+
+Read more about [Vue Apollo][vue-apollo] in the [Vue Apollo documentation][vue-apollo-docs].
+
+### Testing
+
+With [Vue test utils][vue-test-utils] it is easy to quickly test components that
+fetch GraphQL queries. The simplest way is to use `shallowMount` and then set
+the data on the component
+
+```javascript
+it('tests apollo component', () => {
+ const vm = shallowMount(App);
+
+ vm.setData({
+ ...mock data
+ });
+});
+```
+
+## Usage outside of Vue
+
+It is also possible to use GraphQL outside of Vue by directly importing
+and using the default client with queries.
+
+```javascript
+import defaultClient from '~/lib/graphql';
+import query from './query.graphql';
+
+defaultClient.query(query)
+ .then(result => console.log(result));
+```
+
+Read more about the [Apollo] client in the [Apollo documentation][apollo-client-docs].
+
+[Apollo]: https://www.apollographql.com/
+[vue-apollo]: https://github.com/Akryum/vue-apollo/
+[vue-apollo-docs]: https://akryum.github.io/vue-apollo/
+[feature-flags]: ../feature_flags.md
+[default-client]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/javascripts/lib/graphql.js
+[apollo-client-docs]: https://www.apollographql.com/docs/tutorial/client.html
+[vue-test-utils]: https://vue-test-utils.vuejs.org/
diff --git a/doc/development/fe_guide/icons.md b/doc/development/fe_guide/icons.md
index 3d8da6accc1..533e2001300 100644
--- a/doc/development/fe_guide/icons.md
+++ b/doc/development/fe_guide/icons.md
@@ -3,7 +3,7 @@
We manage our own Icon and Illustration library in the [gitlab-svgs][gitlab-svgs] repository.
This repository is published on [npm][npm] and managed as a dependency via yarn.
You can browse all available Icons and Illustrations [here][svg-preview].
-To upgrade to a new version run `yarn upgrade @gitlab-org/gitlab-svgs`.
+To upgrade to a new version run `yarn upgrade @gitlab/svgs`.
## Icons
@@ -111,6 +111,6 @@ export default {
</template>
```
-[npm]: https://www.npmjs.com/package/@gitlab-org/gitlab-svgs
+[npm]: https://www.npmjs.com/package/@gitlab/svgs
[gitlab-svgs]: https://gitlab.com/gitlab-org/gitlab-svgs
[svg-preview]: https://gitlab-org.gitlab.io/gitlab-svgs
diff --git a/doc/development/fe_guide/index.md b/doc/development/fe_guide/index.md
index 11b9a2e6a64..cca3ad6fae6 100644
--- a/doc/development/fe_guide/index.md
+++ b/doc/development/fe_guide/index.md
@@ -54,6 +54,9 @@ Vuex specific design patterns and practices.
## [Axios](axios.md)
Axios specific practices and gotchas.
+## [GraphQL](graphql.md)
+How to use GraphQL
+
## [Icons and Illustrations](icons.md)
How we use SVG for our Icons and Illustrations.
diff --git a/doc/development/fe_guide/style_guide_js.md b/doc/development/fe_guide/style_guide_js.md
index 656ddd868cd..1e0529262ad 100644
--- a/doc/development/fe_guide/style_guide_js.md
+++ b/doc/development/fe_guide/style_guide_js.md
@@ -1,11 +1,13 @@
# Style guides and linting
+
See the relevant style guides for our guidelines and for information on linting:
## JavaScript
+
We defer to [Airbnb][airbnb-js-style-guide] on most style-related
conventions and enforce them with eslint.
-See [our current .eslintrc][eslintrc] for specific rules and patterns.
+See [our current .eslintrc](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.eslintrc.yml) for specific rules and patterns.
### Common
@@ -21,10 +23,10 @@ refactor an existing one, you should abide by the eslint rules.
```javascript
// bad
/* eslint-disable */
-
+
// better
/* eslint-disable some-rule, some-other-rule */
-
+
// best
// nothing :)
```
@@ -34,14 +36,14 @@ refactor an existing one, you should abide by the eslint rules.
```javascript
// bad
/* eslint-disable no-new */
-
+
import Foo from 'foo';
-
+
new Foo();
-
+
// better
import Foo from 'foo';
-
+
// eslint-disable-next-line no-new
new Foo();
```
@@ -58,11 +60,11 @@ followed by any global declarations, then a blank newline prior to any imports o
/* global Foo */
/* eslint-disable no-new */
import Bar from './bar';
-
+
// good
/* eslint-disable no-new */
/* global Foo */
-
+
import Bar from './bar';
```
@@ -73,7 +75,7 @@ followed by any global declarations, then a blank newline prior to any imports o
```javascript
// bad
/* globals Flash, Cookies, jQuery */
-
+
// good
/* global Flash */
/* global Cookies */
@@ -85,7 +87,7 @@ followed by any global declarations, then a blank newline prior to any imports o
```javascript
// bad
fn(p1, p2, p3, p4) {}
-
+
// good
fn(options) {}
```
@@ -191,28 +193,28 @@ Do not use them anymore and feel free to remove them when refactoring legacy cod
```javascript
// bad
const values = {foo: 1};
-
+
function impureFunction(items) {
const bar = 1;
-
+
items.foo = items.a * bar + 2;
-
+
return items.a;
}
-
+
const c = impureFunction(values);
-
+
// good
var values = {foo: 1};
-
+
function pureFunction (foo) {
var bar = 1;
-
+
foo = foo * bar + 2;
-
+
return foo;
}
-
+
var c = pureFunction(values.foo);
```
@@ -231,10 +233,10 @@ Do not use them anymore and feel free to remove them when refactoring legacy cod
document.addEventListener('click', this.handleCallback)
},
handleCallback() {
-
+
}
}
-
+
// Good
export class Foo {
constructor() {
@@ -253,12 +255,12 @@ Do not use them anymore and feel free to remove them when refactoring legacy cod
```javascript
const users = [ { name: 'Foo' }, { name: 'Bar' } ];
-
+
// bad
users.forEach((user, index) => {
user.id = index;
});
-
+
// good
const usersWithId = users.map((user, index) => {
return Object.assign({}, user, { id: index });
@@ -272,10 +274,10 @@ Do not use them anymore and feel free to remove them when refactoring legacy cod
```javascript
// bad
+'10' // 10
-
+
// good
Number('10') // 10
-
+
// better
parseInt('10', 10);
```
@@ -289,7 +291,7 @@ Do not use them anymore and feel free to remove them when refactoring legacy cod
<button class="add-user">
Add User
</button>
-
+
// good
<button class="js-add-user">
Add User
@@ -299,10 +301,12 @@ Do not use them anymore and feel free to remove them when refactoring legacy cod
### Vue.js
#### `eslint-vue-plugin`
+
We default to [eslint-vue-plugin][eslint-plugin-vue], with the `plugin:vue/recommended`.
Please check this [rules][eslint-plugin-vue-rules] for more documentation.
#### Basic Rules
+
1. The service has it's own file
1. The store has it's own file
1. Use a function in the bundle file to instantiate the Vue component:
@@ -314,7 +318,7 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
new Component({})
}
}
-
+
// good
document.addEventListener('DOMContentLoaded', () => new Vue({
el: '#element',
@@ -336,7 +340,7 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
}
}
}
-
+
// good
class Store {
constructor() {
@@ -354,14 +358,14 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
```javascript
// bad
import cardBoard from 'cardBoard.vue'
-
+
components: {
cardBoard,
};
-
+
// good
import CardBoard from 'cardBoard.vue'
-
+
components: {
CardBoard,
};
@@ -373,13 +377,13 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
```javascript
// bad
<component class="btn">
-
+
// good
<component css-class="btn">
-
+
// bad
<component myProp="prop" />
-
+
// good
<component my-prop="prop" />
```
@@ -387,6 +391,7 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
[#34371]: https://gitlab.com/gitlab-org/gitlab-ce/issues/34371
#### Alignment
+
1. Follow these alignment styles for the template method:
1. With more than one attribute, all attributes should be on a new line:
@@ -395,31 +400,31 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
// bad
<component v-if="bar"
param="baz" />
-
+
<button class="btn">Click me</button>
-
+
// good
<component
v-if="bar"
param="baz"
/>
-
+
<button class="btn">
Click me
</button>
```
-
+
1. The tag can be inline if there is only one attribute:
```javascript
// good
<component bar="bar" />
-
+
// good
<component
bar="bar"
/>
-
+
// bad
<component
bar="bar" />
@@ -434,7 +439,7 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
template: `
<button :class='style'>Button</button>
`
-
+
// good
template: `
<button :class="style">Button</button>
@@ -447,7 +452,7 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
```javascript
// bad
props: ['foo']
-
+
// good
props: {
foo: {
@@ -467,7 +472,7 @@ Please check this [rules][eslint-plugin-vue-rules] for more documentation.
type: String,
}
}
-
+
// good
props: {
foo: {
@@ -490,7 +495,7 @@ On those a default key should not be provided.
required: false,
}
}
-
+
// good
props: {
foo: {
@@ -499,7 +504,7 @@ On those a default key should not be provided.
default: 'bar'
}
}
-
+
// good
props: {
foo: {
@@ -534,7 +539,7 @@ On those a default key should not be provided.
```javascript
// bad
<component v-on:click="eventHandler"/>
-
+
// good
<component @click="eventHandler"/>
```
@@ -544,7 +549,7 @@ On those a default key should not be provided.
```javascript
// bad
<component v-bind:class="btn"/>
-
+
// good
<component :class="btsn"/>
```
@@ -556,7 +561,7 @@ On those a default key should not be provided.
```javascript
// bad
<component></component>
-
+
// good
<component />
```
@@ -650,7 +655,7 @@ Useful links:
title="Some tooltip text">
Text
</span>
-
+
// good
<span
v-tooltip
@@ -666,10 +671,10 @@ Useful links:
```javascript
// bad
<span data-original-title="tooltip text">Foo</span>
-
+
// good
<span title="tooltip text">Foo</span>
-
+
$('span').tooltip('_fixTitle');
```
diff --git a/doc/development/fe_guide/style_guide_scss.md b/doc/development/fe_guide/style_guide_scss.md
index 48eb6d0a7d6..b09243598d5 100644
--- a/doc/development/fe_guide/style_guide_scss.md
+++ b/doc/development/fe_guide/style_guide_scss.md
@@ -183,9 +183,11 @@ Don't use ID selectors in CSS.
```
### Variables
+
Before adding a new variable for a color or a size, guarantee:
-1. There isn't already one
-2. There isn't a similar one we can use instead.
+
+- There isn't already one
+- There isn't a similar one we can use instead.
## Linting
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
index f6cbd11042c..ccfd465531a 100644
--- a/doc/development/fe_guide/vue.md
+++ b/doc/development/fe_guide/vue.md
@@ -221,6 +221,14 @@ const vm = mountComponent(Component, data);
The main return value of a Vue component is the rendered output. In order to test the component we
need to test the rendered output. [Vue][vue-test] guide's to unit test show us exactly that:
+## Vue.js Expert Role
+One should apply to be a Vue.js expert by opening an MR when the Merge Request's they create and review show:
+- Deep understanding of Vue and Vuex reactivy
+- Vue and Vuex code are structured according to both official and our guidelines
+- Full understanding of testing a Vue and Vuex application
+- Vuex code follows the [documented pattern](./vuex.md#actions-pattern-request-and-receive-namespaces)
+- Knowledge about the existing Vue and Vuex applications and existing reusable components
+
[vue-docs]: http://vuejs.org/guide/index.html
[issue-boards]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/assets/javascripts/boards
diff --git a/doc/development/fe_guide/vuex.md b/doc/development/fe_guide/vuex.md
index f582f5da323..0f57835fb87 100644
--- a/doc/development/fe_guide/vuex.md
+++ b/doc/development/fe_guide/vuex.md
@@ -114,19 +114,21 @@ When a request is made we often want to show a loading state to the user.
Instead of creating an action to toggle the loading state and dispatch it in the component,
create:
+
1. An action `requestSomething`, to toggle the loading state
1. An action `receiveSomethingSuccess`, to handle the success callback
1. An action `receiveSomethingError`, to handle the error callback
1. An action `fetchSomething` to make the request.
1. In case your application does more than a `GET` request you can use these as examples:
- 1. `PUT`: `createSomething`
- 2. `POST`: `updateSomething`
- 3. `DELETE`: `deleteSomething`
+ - `PUT`: `createSomething`
+ - `POST`: `updateSomething`
+ - `DELETE`: `deleteSomething`
The component MUST only dispatch the `fetchNamespace` action. Actions namespaced with `request` or `receive` should not be called from the component
The `fetch` action will be responsible to dispatch `requestNamespace`, `receiveNamespaceSuccess` and `receiveNamespaceError`
By following this pattern we guarantee:
+
1. All applications follow the same pattern, making it easier for anyone to maintain the code
1. All data in the application follows the same lifecycle pattern
1. Actions are contained and human friendly
@@ -297,12 +299,12 @@ export default {
```javascript
// component.vue
-
+
// bad
created() {
this.$store.commit('mutation');
}
-
+
// good
created() {
this.$store.dispatch('action');
diff --git a/doc/development/feature_flags.md b/doc/development/feature_flags.md
index 417298205f5..1019a1fd0e2 100644
--- a/doc/development/feature_flags.md
+++ b/doc/development/feature_flags.md
@@ -33,7 +33,7 @@ You can follow the progress on that [in the issue on our issue tracker](https://
In general, it's better to have a group- or user-based gate, and you should prefer
it over the use of percentage gates. This would make debugging easier, as you
-filter for example logs and errors based on actors too. Futhermore, this allows
+filter for example logs and errors based on actors too. Furthermore, this allows
for enabling for the `gitlab-org` group first, while the rest of the users
aren't impacted.
@@ -69,6 +69,37 @@ For more information about rolling out changes using feature flags, refer to the
[Rolling out changes using feature flags](rolling_out_changes_using_feature_flags.md)
guide.
+### Frontend
+
+For frontend code you can use the method `push_frontend_feature_flag`, which is
+available to all controllers that inherit from `ApplicationController`. Using
+this method you can expose the state of a feature flag as follows:
+
+```ruby
+before_action do
+ push_frontend_feature_flag(:vim_bindings)
+end
+
+def index
+ # ...
+end
+
+def edit
+ # ...
+end
+```
+
+You can then check for the state of the feature flag in JavaScript as follows:
+
+```javascript
+if ( gon.features.vimBindings ) {
+ // ...
+}
+```
+
+The name of the feature flag in JavaScript will always be camelCased, meaning
+that checking for `gon.features.vim_bindings` would not work.
+
### Specs
In the test environment `Feature.enabled?` is stubbed to always respond to `true`,
@@ -81,3 +112,8 @@ feature flag. You can stub a feature flag as follows:
```ruby
stub_feature_flags(my_feature_flag: false)
```
+
+## Enabling a feature flag
+
+Check how to [roll out changes using feature flags](rolling_out_changes_using_feature_flags.md).
+
diff --git a/doc/development/gitaly.md b/doc/development/gitaly.md
index 4f9ca1920a5..32beafad307 100644
--- a/doc/development/gitaly.md
+++ b/doc/development/gitaly.md
@@ -1,15 +1,11 @@
# GitLab Developers Guide to Working with Gitaly
[Gitaly](https://gitlab.com/gitlab-org/gitaly) is a high-level Git RPC service used by GitLab CE/EE,
-Workhorse and GitLab-Shell. All Rugged operations in GitLab CE/EE are currently being phased out to
-be replaced by Gitaly API calls.
-
-Visit the [Gitaly Migration Board](https://gitlab.com/gitlab-org/gitaly/boards/331341) for current
-status of the migration.
+Workhorse and GitLab-Shell.
## Developing new Git features
-Starting with Gitlab 10.8, all new Git features should be developed in
+Starting with GitLab 10.8, all new Git features should be developed in
Gitaly.
> This is a new process that is not clearly defined yet. If you want
@@ -52,57 +48,6 @@ comfortable writing Go code.
There is documentation for this approach in [the Gitaly
repo](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/ruby_endpoint.md).
-## Modifying existing Git features
-
-If you modify existing Git features in `lib/gitlab/git` you need to make
-sure the changes also work in Gitaly. Because we are still in the
-migration process there are a number of subtle pitfalls. Features that
-have been migrated have dual implementations (Gitaly and local). The
-Gitaly implementation may or may not use a vendored (and therefore
-possibly outdated) copy of the local implementation in `lib/gitlab/git`.
-
-To avoid unexpected problems and conflicts, all changes to
-`lib/gitlab/git` need to be approved by a member of the Gitaly team.
-
-For the time being, while the Gitaly migration is still in progress,
-there should be no Enterprise Edition-only Git code in
-`lib/gitlab/git`. Also no mixins.
-
-## Feature Flags
-
-Gitaly makes heavy use of [feature flags](feature_flags.md).
-
-Each Rugged-to-Gitaly migration goes through a [series of phases](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/MIGRATION_PROCESS.md):
-
-* **Opt-In**: by default the Rugged implementation is used.
- * Production instances can choose to enable the Gitaly endpoint by enabling the feature flag.
- * For testing purposes, you may wish to enable all feature flags by default. This can be done by exporting the following
- environment variable: `GITALY_FEATURE_DEFAULT_ON=1`.
- * On developer instances (ie, when `Rails.env.development?` is true), the Gitaly endpoint
- is enabled by default, but can be _disabled_ using feature flags.
-* **Opt-Out**: by default, the Gitaly endpoint is used, but the feature can be explicitly disabled using the feature flag.
-* **Mandatory**: The migration is complete and cannot be disabled. The old codepath is removed.
-
-### Enabling and Disabling Feature
-
-In the Rails console, type:
-
-```ruby
-Feature.enable(:gitaly_feature_name)
-Feature.disable(:gitaly_feature_name)
-```
-
-Where `gitaly_feature_name` is the name of the Gitaly feature. This can be determined by finding the appropriate
-`gitaly_migrate` code block, for example:
-
-```ruby
-gitaly_migrate(:tag_names) do
-...
-end
-```
-
-Since Gitaly features are always prefixed with `gitaly_`, the name of the feature flag in this case would be `gitaly_tag_names`.
-
## Gitaly-Related Test Failures
If your test-suite is failing with Gitaly issues, as a first step, try running:
diff --git a/doc/development/github_importer.md b/doc/development/github_importer.md
index 0d558583bb8..863ac049db6 100644
--- a/doc/development/github_importer.md
+++ b/doc/development/github_importer.md
@@ -99,8 +99,8 @@ This worker will wrap up the import process by performing some housekeeping
Advancing stages is done in one of two ways:
-1. Scheduling the worker for the next stage directly.
-2. Scheduling a job for `Gitlab::GithubImport::AdvanceStageWorker` which will
+- Scheduling the worker for the next stage directly.
+- Scheduling a job for `Gitlab::GithubImport::AdvanceStageWorker` which will
advance the stage when all work of the current stage has been completed.
The first approach should only be used by workers that perform all their work in
@@ -131,7 +131,7 @@ our import as failed because of this.
To prevent this from happening we periodically refresh the expiration time of
the import process. This works by storing the JID of the import job in the
database, then refreshing this JID's TTL at various stages throughout the import
-process. This is done by calling `Project#refresh_import_jid_expiration`. By
+process. This is done by calling `ProjectImportState#refresh_jid_expiration`. By
refreshing this TTL we can ensure our import does not get marked as failed so
long we're still performing work.
@@ -147,7 +147,7 @@ We handle this by doing the following:
1. Once we hit the rate limit all jobs will automatically reschedule themselves
in such a way that they are not executed until the rate limit has been reset.
-2. We cache the mapping of GitHub users to GitLab users in Redis.
+1. We cache the mapping of GitHub users to GitLab users in Redis.
More information on user caching can be found below.
@@ -157,21 +157,21 @@ When mapping GitHub users to GitLab users we need to (in the worst case)
perform:
1. One API call to get the user's Email address.
-2. Two database queries to see if a corresponding GitLab user exists. One query
+1. Two database queries to see if a corresponding GitLab user exists. One query
will try to find the user based on the GitHub user ID, while the second query
is used to find the user using their GitHub Email address.
Because this process is quite expensive we cache the result of these lookups in
Redis. For every user looked up we store three keys:
-1. A Redis key mapping GitHub usernames to their Email addresses.
-2. A Redis key mapping a GitHub Email addresses to a GitLab user ID.
-3. A Redis key mapping a GitHub user ID to GitLab user ID.
+- A Redis key mapping GitHub usernames to their Email addresses.
+- A Redis key mapping a GitHub Email addresses to a GitLab user ID.
+- A Redis key mapping a GitHub user ID to GitLab user ID.
There are two types of lookups we cache:
-1. A positive lookup, meaning we found a GitLab user ID.
-2. A negative lookup, meaning we didn't find a GitLab user ID. Caching this
+- A positive lookup, meaning we found a GitLab user ID.
+- A negative lookup, meaning we didn't find a GitLab user ID. Caching this
prevents us from performing the same work for users that we know don't exist
in our GitLab database.
diff --git a/doc/development/gotchas.md b/doc/development/gotchas.md
index 84dea7ce9aa..a5a34d82bec 100644
--- a/doc/development/gotchas.md
+++ b/doc/development/gotchas.md
@@ -92,7 +92,7 @@ describe API::Labels do
end
```
-## Avoid using `allow_any_instance_of` in RSpec
+## Avoid using `expect_any_instance_of` or `allow_any_instance_of` in RSpec
### Why
@@ -102,7 +102,7 @@ end
error like this:
```
- 1.1) Failure/Error: allow_any_instance_of(ApplicationSetting).to receive_messages(messages)
+ 1.1) Failure/Error: expect_any_instance_of(ApplicationSetting).to receive_messages(messages)
Using `any_instance` to stub a method (elasticsearch_indexing) that has been defined on a prepended module (EE::ApplicationSetting) is not supported.
```
@@ -112,7 +112,7 @@ Instead of writing:
```ruby
# Don't do this:
-allow_any_instance_of(Project).to receive(:add_import_job)
+expect_any_instance_of(Project).to receive(:add_import_job)
```
We could write:
diff --git a/doc/development/i18n/index.md b/doc/development/i18n/index.md
index 7290a175501..c44690a4c5d 100644
--- a/doc/development/i18n/index.md
+++ b/doc/development/i18n/index.md
@@ -50,3 +50,5 @@ able to proofread and instructions on becoming a proofreader yourself.
## Release
Translations are typically included in the next major or minor release.
+
+See [Merging translations from Crowdin](merging_translations.md)
diff --git a/doc/development/i18n/merging_translations.md b/doc/development/i18n/merging_translations.md
new file mode 100644
index 00000000000..d172aa6da21
--- /dev/null
+++ b/doc/development/i18n/merging_translations.md
@@ -0,0 +1,60 @@
+# Merging translations from Crowdin
+
+Crowdin automatically syncs the `gitlab.pot` file presenting newly
+added translations to the community of translators.
+
+At the same time, it creates a merge request to merge all newly added
+& approved translations. Find the [merge reqeust created by
+`gitlab-crowdin-bot`](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests?scope=all&utf8=%E2%9C%93&state=opened&author_username=gitlab-crowdin-bot)
+to see new and merged merge requests. They are created in EE and need
+to be ported to CE manually.
+
+## Validation
+
+By default Crowdin commits translations with `[skip ci]` in the commit
+message. This is done to avoid a bunch of pipelines being run. Before
+merging translations, make sure to trigger a pipeline to validate
+translations, we have static analysis validating things Crowdin
+doesn't do. Create a [new pipeline](https://gitlab.com/gitlab-org/gitlab-ee/pipelines/new) for the
+`master-i18n` branch.
+
+If there are validation errors, the easiest solution is to disapprove
+the offending string in Crowdin, leaving a comment with what is
+required to fix the offense. There is an
+[issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/49208)
+suggesting to automate this process. Disapproving will exclude the
+invalid translation, the merge request will be updated within a few
+minutes.
+
+It might be handy to pause the integration on the Crowdin side for a
+little while so translations don't keep coming. This can be done by
+clicking `Pause sync` on the [Crowdin integration settings
+page](https://translate.gitlab.com/project/gitlab-ee/settings#integration).
+
+When all failures are resolved, the translations need to be double
+checked once more [as discussed in this
+issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/37850).
+
+## Merging translations
+
+When all translations are found good and pipelines pass the
+translations can be merged into the master branch. After that is done,
+create a new merge request cherry-picking the translations from EE to
+CE. When merging the translations, make sure to check the `Remove
+source branch` checkbox, so Crowdin recreates the `master-i18n` from
+master after the new translation was merged.
+
+We are discussing automating this entire process
+[here](https://gitlab.com/gitlab-org/gitlab-ce/issues/39309).
+
+## Recreate the merge request
+
+Crowdin creates a new merge request as soon as the old one is closed
+or merged. But it won't recreate the `master-i18n` branch every
+time. To force Crowdin to recreate the branch, close any [open merge
+request](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests?scope=all&utf8=%E2%9C%93&state=opened&author_username=gitlab-crowdin-bot)
+and delete the
+[`master-18n`](https://gitlab.com/gitlab-org/gitlab-ee/branches/all?utf8=%E2%9C%93&search=master-i18n).
+
+This might be needed when the merge request contains failures that
+have been fixed on master.
diff --git a/doc/development/i18n/proofreader.md b/doc/development/i18n/proofreader.md
index 6e57ffbae27..fd4df64999b 100644
--- a/doc/development/i18n/proofreader.md
+++ b/doc/development/i18n/proofreader.md
@@ -5,7 +5,14 @@ are very appreciative of the work done by translators and proofreaders!
## Proofreaders
+- Albanian
+ - Proofreaders needed.
+- Arabic
+ - Proofreaders needed.
- Bulgarian
+ - Lyubomir Vasilev - [Crowdin](https://crowdin.com/profile/lyubomirv)
+- Catalan
+ - Proofreaders needed.
- Chinese Simplified
- Huang Tao - [GitLab](https://gitlab.com/htve), [Crowdin](https://crowdin.com/profile/htve)
- Chinese Traditional
@@ -14,14 +21,31 @@ are very appreciative of the work done by translators and proofreaders!
- Yi-Jyun Pan - [GitLab](https://gitlab.com/pan93412), [Crowdin](https://crowdin.com/profile/pan93412)
- Chinese Traditional, Hong Kong
- Huang Tao - [GitLab](https://gitlab.com/htve), [Crowdin](https://crowdin.com/profile/htve)
+- Czech
+ - Proofreaders needed.
+- Danish
+ - Proofreaders needed.
- Dutch
- - Emily Hendle - [GitLab](https://gitlab.com/pundachan), [Crowdin](https://crowdin.com/profile/pandachan)
+ - Emily Hendle - [GitLab](https://gitlab.com/pundachan), [Crowdin](https://crowdin.com/profile/pandachan)
- Esperanto
+- Lyubomir Vasilev - [Crowdin](https://crowdin.com/profile/lyubomirv)
+- Estonian
+ - Proofreaders needed.
+- Filipino
+ - Proofreaders needed.
- French
- Davy Defaud - [GitLab](https://gitlab.com/DevDef), [Crowdin](https://crowdin.com/profile/DevDef)
+- Galician
+ - Antón Méixome - [Crowdin](https://crowdin.com/profile/meixome)
+ - Pedro Garcia - [GitLab](https://gitlab.com/pedgarrod), [Crowdin](https://crowdin.com/profile/breaking_pitt)
- German
+ - Michael Hahnle - [GitLab](https://gitlab.com/mhah), [Crowdin](https://crowdin.com/profile/mhah)
+- Greek
+ - Proofreaders needed.
- Hebrew
- Yaron Shahrabani - [GitLab](https://gitlab.com/yarons), [Crowdin](https://crowdin.com/profile/YaronSh)
+- Hungarian
+ - Proofreaders needed.
- Indonesian
- Ahmad Naufal Mukhtar - [GitLab](https://gitlab.com/anaufalm), [Crowdin](https://crowdin.com/profile/anaufalm)
- Italian
@@ -32,18 +56,39 @@ are very appreciative of the work done by translators and proofreaders!
- Korean
- Chang-Ho Cha - [GitLab](https://gitlab.com/changho-cha), [Crowdin](https://crowdin.com/profile/zzazang)
- Huang Tao - [GitLab](https://gitlab.com/htve), [Crowdin](https://crowdin.com/profile/htve)
+ - Ji Hun Oh - [GitLab](https://gitlab.com/Baw-Appie), [Crowdin](https://crowdin.com/profile/BawAppie)
+- Mongolian
+ - Proofreaders needed.
+- Norwegian Bokmal
+ - Proofreaders needed.
- Polish
- Filip Mech - [GitLab](https://gitlab.com/mehenz), [Crowdin](https://crowdin.com/profile/mehenz)
+- Portuguese
+ - Proofreaders needed.
- Portuguese, Brazilian
- Paulo George Gomes Bezerra - [GitLab](https://gitlab.com/paulobezerra), [Crowdin](https://crowdin.com/profile/paulogomes.rep)
- André Gama - [GitLab](https://gitlab.com/andregamma), [Crowdin](https://crowdin.com/profile/ToeOficial)
+- Romanian
+ - Proofreaders needed.
- Russian
- Nikita Grylov - [GitLab](https://gitlab.com/nixel2007), [Crowdin](https://crowdin.com/profile/nixel2007)
- Alexy Lustin - [GitLab](https://gitlab.com/allustin), [Crowdin](https://crowdin.com/profile/lustin)
+ - NickVolynkin - [Crowdin](https://crowdin.com/profile/NickVolynkin)
+- Serbian (Cyrillic)
+ - Proofreaders needed.
+- Serbian (Latin)
+ - Proofreaders needed.
+- Slovak
+ - Proofreaders needed.
- Spanish
+ - Pedro Garcia - [GitLab](https://gitlab.com/pedgarrod), [Crowdin](https://crowdin.com/profile/breaking_pitt)
+- Turkish
+ - Proofreaders needed.
- Ukrainian
- Volodymyr Sobotovych - [GitLab](https://gitlab.com/wheleph), [Crowdin](https://crowdin.com/profile/wheleph)
- Andrew Vityuk - [GitLab](https://gitlab.com/3_1_3_u), [Crowdin](https://crowdin.com/profile/andruwa13)
+- Welsh
+ - Proofreaders needed.
## Become a proofreader
@@ -75,6 +120,8 @@ are very appreciative of the work done by translators and proofreaders!
have previously translated.
1. Your request to become a proofreader will be considered on the merits of
- your previous translations.
+ your previous translations by [GitLab team members](https://about.gitlab.com/team/)
+ or [Core team members](https://about.gitlab.com/core-team/) who are fluent in
+ the language or current proofreaders.
[proofreader-src]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/i18n/proofreader.md
diff --git a/doc/development/instrumentation.md b/doc/development/instrumentation.md
index a14c0752366..bef166f2aec 100644
--- a/doc/development/instrumentation.md
+++ b/doc/development/instrumentation.md
@@ -69,7 +69,7 @@ The easiest way to check if a method has been instrumented is to check its
source location. For example:
```ruby
-method = Rugged::TagCollection.instance_method(:[])
+method = Banzai::Renderer.method(:render)
method.source_location
```
@@ -82,7 +82,7 @@ method (along with its source location), this is easier than running the above
Ruby code. In case of the above snippet you'd run the following:
```
-$ Rugged::TagCollection#[]
+$ Banzai::Renderer.render
```
This will print out something along the lines of:
@@ -117,11 +117,11 @@ The block is executed and the execution time is stored as a set of fields in the
currently running transaction. If no transaction is present the block is yielded
without measuring anything.
-3 values are measured for a block:
+Three values are measured for a block:
-1. The real time elapsed, stored in NAME_real_time.
-2. The CPU time elapsed, stored in NAME_cpu_time.
-3. The call count, stored in NAME_call_count.
+- The real time elapsed, stored in NAME_real_time.
+- The CPU time elapsed, stored in NAME_cpu_time.
+- The call count, stored in NAME_call_count.
Both the real and CPU timings are measured in milliseconds.
diff --git a/doc/development/logging.md b/doc/development/logging.md
new file mode 100644
index 00000000000..5c1d96b9e0c
--- /dev/null
+++ b/doc/development/logging.md
@@ -0,0 +1,144 @@
+# GitLab Developers Guide to Logging
+
+[GitLab Logs](../administration/logs.md) play a critical role for both
+administrators and GitLab team members to diagnose problems in the field.
+
+## Don't use `Rails.logger`
+
+Currently `Rails.logger` calls all get saved into `production.log`, which contains
+a mix of Rails' logs and other calls developers have inserted in the code base.
+For example:
+
+```
+Started GET "/gitlabhq/yaml_db/tree/master" for 168.111.56.1 at 2015-02-12 19:34:53 +0200
+Processing by Projects::TreeController#show as HTML
+ Parameters: {"project_id"=>"gitlabhq/yaml_db", "id"=>"master"}
+
+ ...
+
+ Namespaces"."created_at" DESC, "namespaces"."id" DESC LIMIT 1 [["id", 26]]
+ CACHE (0.0ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = 'Project' AND "members"."type" IN ('ProjectMember') AND "members"."source_id" = $1 AND "members"."source_type" = $2 AND "members"."user_id" = 1 ORDER BY "members"."created_at" DESC, "members"."id" DESC LIMIT 1 [["source_id", 18], ["source_type", "Project"]]
+ CACHE (0.0ms) SELECT "members".* FROM "members" WHERE "members"."source_type" = 'Project' AND "members".
+ (1.4ms) SELECT COUNT(*) FROM "merge_requests" WHERE "merge_requests"."target_project_id" = $1 AND ("merge_requests"."state" IN ('opened','reopened')) [["target_project_id", 18]]
+ Rendered layouts/nav/_project.html.haml (28.0ms)
+ Rendered layouts/_collapse_button.html.haml (0.2ms)
+ Rendered layouts/_flash.html.haml (0.1ms)
+ Rendered layouts/_page.html.haml (32.9ms)
+Completed 200 OK in 166ms (Views: 117.4ms | ActiveRecord: 27.2ms)
+```
+
+These logs suffer from a number of problems:
+
+1. They often lack timestamps or other contextual information (e.g. project ID, user)
+2. They may span multiple lines, which make them hard to find via Elasticsearch.
+3. They lack a common structure, which make them hard to parse by log
+forwarders, such as Logstash or Fluentd. This also makes them hard to
+search.
+
+Note that currently on GitLab.com, any messages in `production.log` will
+NOT get indexed by Elasticsearch due to the sheer volume and noise. They
+do end up in Google Stackdriver, but it is still harder to search for
+logs there. See the [GitLab.com logging
+documentation](https://gitlab.com/gitlab-com/runbooks/blob/master/howto/logging.md)
+for more details.
+
+## Use structured (JSON) logging
+
+Structured logging solves these problems. Consider the example from an API request:
+
+```json
+{"time":"2018-10-29T12:49:42.123Z","severity":"INFO","duration":709.08,"db":14.59,"view":694.49,"status":200,"method":"GET","path":"/api/v4/projects","params":[{"key":"action","value":"git-upload-pack"},{"key":"changes","value":"_any"},{"key":"key_id","value":"secret"},{"key":"secret_token","value":"[FILTERED]"}],"host":"localhost","ip":"::1","ua":"Ruby","route":"/api/:version/projects","user_id":1,"username":"root","queue_duration":100.31,"gitaly_calls":30}
+```
+
+In a single line, we've included all the information that a user needs
+to understand what happened: the timestamp, HTTP method and path, user
+ID, etc.
+
+### How to use JSON logging
+
+Suppose you want to log the events that happen in a project
+importer. You want to log issues created, merge requests, etc. as the
+importer progresses. Here's what to do:
+
+1. Look at [the list of GitLab Logs](../administration/logs.md) to see
+if your log message might belong with one of the existing log files.
+1. If there isn't a good place, consider creating a new filename, but
+check with a maintainer if it makes sense to do so. A log file should
+make it easy for people to search pertinent logs in one place. For
+example, `geo.log` contains all logs pertaining to GitLab Geo.
+To create a new file:
+ 1. Choose a filename (e.g. `importer_json.log`).
+ 1. Create a new subclass of `Gitlab::JsonLogger`:
+
+ ```ruby
+ module Gitlab
+ module Import
+ class Logger < ::Gitlab::JsonLogger
+ def self.file_name_noext
+ 'importer'
+ end
+ end
+ end
+ end
+ ```
+
+ 1. In your class where you want to log, you might initialize the logger as an instance variable:
+
+ ```ruby
+ attr_accessor :logger
+
+ def initialize
+ @logger = Gitlab::Import::Logger.build
+ end
+ ```
+
+ Note that it's useful to memoize this because creating a new logger
+ each time you log will open a file, adding unnecessary overhead.
+
+1. Now insert log messages into your code. When adding logs,
+ make sure to include all the context as key-value pairs:
+
+ ```ruby
+ # BAD
+ logger.info("Unable to create project #{project.id}")
+ ```
+
+ ```ruby
+ # GOOD
+ logger.info(message: "Unable to create project", project_id: project.id)
+ ```
+
+1. Be sure to create a common base structure of your log messages. For example,
+ all messages might have `current_user_id` and `project_id` to make it easier
+ to search for activities by user for a given time.
+
+1. Do NOT mix and match types. Elasticsearch won't be able to index your
+ logs properly if you [mix integer and string
+ types](https://www.elastic.co/guide/en/elasticsearch/guide/current/mapping.html#_avoiding_type_gotchas):
+
+ ```ruby
+ # BAD
+ logger.info(message: "Import error", error: 1)
+ logger.info(message: "Import error", error: "I/O failure")
+ ```
+
+ ```ruby
+ # GOOD
+ logger.info(message: "Import error", error_code: 1, error: "I/O failure")
+ ```
+
+## Additional steps with new log files
+
+1. Consider log retention settings. By default, Omnibus will rotate any
+logs in `/var/log/gitlab/gitlab-rails/*.log` every hour and [keep at
+most 30 compressed files](https://docs.gitlab.com/omnibus/settings/logs.html#logrotate).
+On GitLab.com, that setting is only 6 compressed files. These settings should suffice
+for most users, but you may need to tweak them in [omnibus-gitlab](https://gitlab.com/gitlab-org/omnibus-gitlab).
+
+1. If you add a new file, submit an issue to the [production
+tracker](https://gitlab.com/gitlab-com/gl-infra/production/issues) or
+a merge request to the [gitlab_fluentd](https://gitlab.com/gitlab-cookbooks/gitlab_fluentd)
+project. See [this example](https://gitlab.com/gitlab-cookbooks/gitlab_fluentd/merge_requests/51/diffs).
+
+1. Be sure to update the [GitLab CE/EE documentation](../administration/logs.md) and the [GitLab.com
+runbooks](https://gitlab.com/gitlab-com/runbooks/blob/master/howto/logging.md).
diff --git a/doc/development/merge_request_performance_guidelines.md b/doc/development/merge_request_performance_guidelines.md
index 12badbe39b2..ee01c89e0ed 100644
--- a/doc/development/merge_request_performance_guidelines.md
+++ b/doc/development/merge_request_performance_guidelines.md
@@ -168,6 +168,7 @@ user objects for every username we can remove the need for running the same
query for every mention of `@alice`.
Caching data per transaction can be done using
-[RequestStore](https://github.com/steveklabnik/request_store). Caching data in
-Redis can be done using [Rails' caching
+[RequestStore](https://github.com/steveklabnik/request_store) (use
+`Gitlab::SafeRequestStore` to avoid having to remember to check
+`RequestStore.active?`). Caching data in Redis can be done using [Rails' caching
system](http://guides.rubyonrails.org/caching_with_rails.html).
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index 6f31e5b82e5..a99267bfbba 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -134,9 +134,9 @@ should be more than enough.
When removing an index make sure to use the method `remove_concurrent_index` instead
of the regular `remove_index` method. The `remove_concurrent_index` method
automatically drops concurrent indexes when using PostgreSQL, removing the
-need for downtime. To use this method you must disable transactions by calling
-the method `disable_ddl_transaction!` in the body of your migration class like
-so:
+need for downtime. To use this method you must disable single-transaction mode
+by calling the method `disable_ddl_transaction!` in the body of your migration
+class like so:
```ruby
class MyMigration < ActiveRecord::Migration
@@ -187,12 +187,7 @@ end
When adding a foreign-key constraint to either an existing or new
column remember to also add a index on the column.
-This is _required_ if the foreign-key constraint specifies
-`ON DELETE CASCADE` or `ON DELETE SET NULL` behavior. On a cascading
-delete, the [corresponding record needs to be retrieved using an
-index](https://www.cybertec-postgresql.com/en/postgresql-indexes-and-foreign-keys/)
-(otherwise, we'd need to scan the whole table) for subsequent update or
-deletion.
+This is _required_ for all foreign-keys.
Here's an example where we add a new column with a foreign key
constraint. Note it includes `index: true` to create an index for it.
diff --git a/doc/development/module_with_instance_variables.md b/doc/development/module_with_instance_variables.md
index 48a1b7f847e..7bdfa04fc57 100644
--- a/doc/development/module_with_instance_variables.md
+++ b/doc/development/module_with_instance_variables.md
@@ -60,7 +60,7 @@ as long as it's contained in the same module; that is, no other modules or
objects are touching them, then it would be an acceptable use.
We especially allow the case where a single instance variable is used with
-`||=` to setup the value. This would look like:
+`||=` to set up the value. This would look like:
``` ruby
module M
diff --git a/doc/development/new_fe_guide/development/performance.md b/doc/development/new_fe_guide/development/performance.md
index 244dfb3756f..5ccd5357314 100644
--- a/doc/development/new_fe_guide/development/performance.md
+++ b/doc/development/new_fe_guide/development/performance.md
@@ -2,7 +2,7 @@
## Monitoring
-We have a performance dashboard available in one of our [grafana instances](https://performance.gprd.gitlab.com/dashboard/db/sitespeed-page-summary?orgId=1). This dashboard automatically aggregates metric data from [sitespeed.io](https://sitespeed.io) every 6 hours. These changes are displayed after a set number of pages are aggregated.
+We have a performance dashboard available in one of our [grafana instances](https://dashboards.gitlab.net/d/1EBTz3Dmz/sitespeed-page-summary?orgId=1). This dashboard automatically aggregates metric data from [sitespeed.io](https://sitespeed.io) every 6 hours. These changes are displayed after a set number of pages are aggregated.
These pages can be found inside a text file in the gitlab-build-images [repository](https://gitlab.com/gitlab-org/gitlab-build-images) called [gitlab.txt](https://gitlab.com/gitlab-org/gitlab-build-images/blob/master/scripts/gitlab.txt)
Any frontend engineer can contribute to this dashboard. They can contribute by adding or removing urls of pages from this text file. Please have a [frontend monitoring expert](https://about.gitlab.com/team) review your changes before assigning to a maintainer of the `gitlab-build-images` project. The changes will go live on the next scheduled run after the changes are merged into `master`.
diff --git a/doc/development/new_fe_guide/development/testing.md b/doc/development/new_fe_guide/development/testing.md
index a9223ac6b0f..082acbedcd2 100644
--- a/doc/development/new_fe_guide/development/testing.md
+++ b/doc/development/new_fe_guide/development/testing.md
@@ -1,30 +1,247 @@
# Overview of Frontend Testing
-## Types of tests in our codebase
+Tests relevant for frontend development can be found at two places:
+
+- `spec/javascripts/` which are run by Karma and contain
+ - [frontend unit tests](#frontend-unit-tests)
+ - [frontend component tests](#frontend-component-tests)
+ - [frontend integration tests](#frontend-integration-tests)
+- `spec/features/` which are run by RSpec and contain
+ - [feature tests](#feature-tests)
+
+In addition there were feature tests in `features/` run by Spinach in the past.
+These have been removed from our codebase in May 2018 ([#23036](https://gitlab.com/gitlab-org/gitlab-ce/issues/23036)).
+
+See also:
-* **RSpec**
- * **[Ruby unit tests](#ruby-unit-tests-spec-rb)** for models, controllers, helpers, etc. (`/spec/**/*.rb`)
- * **[Full feature tests](#full-feature-tests-spec-features-rb)** (`/spec/features/**/*.rb`)
-* **[Karma](#karma-tests-spec-javascripts-js)** (`/spec/javascripts/**/*.js`)
-* <s>Spinach</s> — These have been removed from our codebase in May 2018. (`/features/`)
+- [old testing guide](../../testing_guide/frontend_testing.html)
+- [notes on testing Vue components](../../fe_guide/vue.html#testing-vue-components)
-## RSpec: Ruby unit tests `/spec/**/*.rb`
+## Frontend unit tests
-These tests are meant to unit test the ruby models, controllers and helpers.
+Unit tests are on the lowest abstraction level and typically test functionality that is not directly perceivable by a user.
-### When do we write/update these tests?
+### When to use unit tests
-Whenever we create or modify any Ruby models, controllers or helpers we add/update corresponding tests.
+<details>
+ <summary>exported functions and classes</summary>
+ Anything that is exported can be reused at various places in a way you have no control over.
+ Therefore it is necessary to document the expected behavior of the public interface with tests.
+</details>
----
+<details>
+ <summary>Vuex actions</summary>
+ Any Vuex action needs to work in a consistent way independent of the component it is triggered from.
+</details>
-## RSpec: Full feature tests `/spec/features/**/*.rb`
+<details>
+ <summary>Vuex mutations</summary>
+ For complex Vuex mutations it helps to identify the source of a problem by separating the tests from other parts of the Vuex store.
+</details>
-Full feature tests will load a full app environment and allow us to test things like rendering DOM, interacting with links and buttons, testing the outcome of those interactions through multiple pages if necessary. These are also called end-to-end tests but should not be confused with QA end-to-end tests (`package-and-qa` manual pipeline job).
+### When *not* to use unit tests
-### When do we write/update these tests?
+<details>
+ <summary>non-exported functions or classes</summary>
+ Anything that is not exported from a module can be considered private or an implementation detail and doesn't need to be tested.
+</details>
-When we add a new feature, we write at least two tests covering the success and the failure scenarios.
+<details>
+ <summary>constants</summary>
+ Testing the value of a constant would mean to copy it.
+ This results in extra effort without additional confidence that the value is correct.
+</details>
+
+<details>
+ <summary>Vue components</summary>
+ Computed properties, methods, and lifecycle hooks can be considered an implementation detail of components and don't need to be tested.
+ They are implicitly covered by component tests.
+ The <a href="https://vue-test-utils.vuejs.org/guides/#getting-started">official Vue guidelines</a> suggest the same.
+</details>
+
+### What to mock in unit tests
+
+<details>
+ <summary>state of the class under test</summary>
+ Modifying the state of the class under test directly rather than using methods of the class avoids side-effects in test setup.
+</details>
+
+<details>
+ <summary>other exported classes</summary>
+ Every class needs to be tested in isolation to prevent test scenarios from growing exponentially.
+</details>
+
+<details>
+ <summary>single DOM elements if passed as parameters</summary>
+ For tests that only operate on single DOM elements rather than a whole page, creating these elements is cheaper than loading a whole HTML fixture.
+</details>
+
+<details>
+ <summary>all server requests</summary>
+ When running frontend unit tests, the backend may not be reachable.
+ Therefore all outgoing requests need to be mocked.
+</details>
+
+<details>
+ <summary>asynchronous background operations</summary>
+ Background operations cannot be stopped or waited on, so they will continue running in the following tests and cause side effects.
+</details>
+
+### What *not* to mock in unit tests
+
+<details>
+ <summary>non-exported functions or classes</summary>
+ Everything that is not exported can be considered private to the module and will be implicitly tested via the exported classes / functions.
+</details>
+
+<details>
+ <summary>methods of the class under test</summary>
+ By mocking methods of the class under test, the mocks will be tested and not the real methods.
+</details>
+
+<details>
+ <summary>utility functions (pure functions, or those that only modify parameters)</summary>
+ If a function has no side effects because it has no state, it is safe to not mock it in tests.
+</details>
+
+<details>
+ <summary>full HTML pages</summary>
+ Loading the HTML of a full page slows down tests, so it should be avoided in unit tests.
+</details>
+
+## Frontend component tests
+
+Component tests cover the state of a single component that is perceivable by a user depending on external signals such as user input, events fired from other components, or application state.
+
+### When to use component tests
+
+- Vue components
+
+### When *not* to use component tests
+
+<details>
+ <summary>Vue applications</summary>
+ Vue applications may contain many components.
+ Testing them on a component level requires too much effort.
+ Therefore they are tested on frontend integration level.
+</details>
+
+<details>
+ <summary>HAML templates</summary>
+ HAML templates contain only Markup and no frontend-side logic.
+ Therefore they are not complete components.
+</details>
+
+### What to mock in component tests
+
+<details>
+ <summary>DOM</summary>
+ Operating on the real DOM is significantly slower than on the virtual DOM.
+</details>
+
+<details>
+ <summary>properties and state of the component under test</summary>
+ Similarly to testing classes, modifying the properties directly (rather than relying on methods of the component) avoids side-effects.
+</details>
+
+<details>
+ <summary>Vuex store</summary>
+ To avoid side effects and keep component tests simple, Vuex stores are replaced with mocks.
+</details>
+
+<details>
+ <summary>all server requests</summary>
+ Similar to unit tests, when running component tests, the backend may not be reachable.
+ Therefore all outgoing requests need to be mocked.
+</details>
+
+<details>
+ <summary>asynchronous background operations</summary>
+ Similar to unit tests, background operations cannot be stopped or waited on, so they will continue running in the following tests and cause side effects.
+</details>
+
+<details>
+ <summary>child components</summary>
+ Every component is tested individually, so child components are mocked.
+ See also <a href="https://vue-test-utils.vuejs.org/api/#shallowmount">shallowMount()</a>
+</details>
+
+### What *not* to mock in component tests
+
+<details>
+ <summary>methods or computed properties of the component under test</summary>
+ By mocking part of the component under test, the mocks will be tested and not the real component.
+</details>
+
+<details>
+ <summary>functions and classes independent from Vue</summary>
+ All plain JavaScript code is already covered by unit tests and needs not to be mocked in component tests.
+</details>
+
+## Frontend integration tests
+
+Integration tests cover the interaction between all components on a single page.
+Their abstraction level is comparable to how a user would interact with the UI.
+
+### When to use integration tests
+
+<details>
+ <summary>page bundles (<code>index.js</code> files in <code>app/assets/javascripts/pages/</code>)</summary>
+ Testing the page bundles ensures the corresponding frontend components integrate well.
+</details>
+
+<details>
+ <summary>Vue applications outside of page bundles</summary>
+ Testing Vue applications as a whole ensures the corresponding frontend components integrate well.
+</details>
+
+### What to mock in integration tests
+
+<details>
+ <summary>HAML views (use fixtures instead)</summary>
+ Rendering HAML views requires a Rails environment including a running database which we cannot rely on in frontend tests.
+</details>
+
+<details>
+ <summary>all server requests</summary>
+ Similar to unit and component tests, when running component tests, the backend may not be reachable.
+ Therefore all outgoing requests need to be mocked.
+</details>
+
+<details>
+ <summary>asynchronous background operations that are not perceivable on the page</summary>
+ Background operations that affect the page need to be tested on this level.
+ All other background operations cannot be stopped or waited on, so they will continue running in the following tests and cause side effects.
+</details>
+
+### What *not* to mock in integration tests
+
+<details>
+ <summary>DOM</summary>
+ Testing on the real DOM ensures our components work in the environment they are meant for.
+ Part of this will be delegated to <a href="https://gitlab.com/gitlab-org/quality/team-tasks/issues/45">cross-browser testing</a>.
+</details>
+
+<details>
+ <summary>properties or state of components</summary>
+ On this level, all tests can only perform actions a user would do.
+ For example to change the state of a component, a click event would be fired.
+</details>
+
+<details>
+ <summary>Vuex stores</summary>
+ When testing the frontend code of a page as a whole, the interaction between Vue components and Vuex stores is covered as well.
+</details>
+
+## Feature tests
+
+In contrast to [frontend integration tests](#frontend-integration-tests), feature tests make requests against the real backend instead of using fixtures.
+This also implies that database queries are executed which makes this category significantly slower.
+
+### When to use feature tests
+
+- use cases that require a backend and cannot be tested using fixtures
+- behavior that is not part of a page bundle but defined globally
### Relevant notes
@@ -48,33 +265,9 @@ wait_for_requests
expect(page).not_to have_selector('.card')
```
----
-
-## Karma tests `/spec/javascripts/**/*.js`
-
-These are the more frontend-focused, at the moment. They're **faster** than `rspec` and make for very quick testing of frontend components.
-
-### When do we write/update these tests?
-
-When we add/update a method/action/mutation to Vue or Vuex, we write karma tests to ensure the logic we wrote doesn't break. We should, however, refrain from writing tests that double-test Vue's internal features.
-
-### Relevant notes
-
-Karma tests are run against a virtual DOM.
+## Test helpers
-To populate the DOM, we can use fixtures to fake the generation of HTML instead of having Rails do that.
-
-Be sure to check the [best practices for karma tests](../../testing_guide/frontend_testing.html#best-practices).
-
-### Vue and Vuex
-
-Test as much as possible without double-testing Vue's internal features, as mentioned above.
-
-Make sure to test computedProperties, mutations, actions. Run the action and test that the proper mutations are committed.
-
-Also check these [notes on testing Vue components](../../fe_guide/vue.html#testing-vue-components).
-
-#### Vuex Helper: `testAction`
+### Vuex Helper: `testAction`
We have a helper available to make testing actions easier, as per [official documentation](https://vuex.vuejs.org/en/testing.html):
@@ -97,7 +290,7 @@ testAction(
Check an example in [spec/javascripts/ide/stores/actions_spec.jsspec/javascripts/ide/stores/actions_spec.js](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/spec/javascripts/ide/stores/actions_spec.js).
-#### Vue Helper: `mountComponent`
+### Vue Helper: `mountComponent`
To make mounting a Vue component easier and more readable, we have a few helpers available in `spec/helpers/vue_mount_component_helper`.
@@ -133,6 +326,7 @@ afterEach(() => {
vm.$destroy();
});
```
+
## Testing with older browsers
Some regressions only affect a specific browser version. We can install and test in particular browsers with either Firefox or Browserstack using the following steps:
@@ -140,20 +334,21 @@ Some regressions only affect a specific browser version. We can install and test
### Browserstack
-[Browserstack](https://www.browserstack.com/) allows you to test more than 1200 mobile devices and browsers.
+[Browserstack](https://www.browserstack.com/) allows you to test more than 1200 mobile devices and browsers.
You can use it directly through the [live app](https://www.browserstack.com/live) or you can install the [chrome extension](https://chrome.google.com/webstore/detail/browserstack/nkihdmlheodkdfojglpcjjmioefjahjb) for easy access.
You can find the credentials on 1Password, under `frontendteam@gitlab.com`.
### Firefox
#### macOS
+
You can download any older version of Firefox from the releases FTP server, https://ftp.mozilla.org/pub/firefox/releases/
1. From the website, select a version, in this case `50.0.1`.
-2. Go to the mac folder.
-3. Select your preferred language, you will find the dmg package inside, download it.
-4. Drag and drop the application to any other folder but the `Applications` folder.
-5. Rename the application to something like `Firefox_Old`.
-6. Move the application to the `Applications` folder.
-7. Open up a terminal and run `/Applications/Firefox_Old.app/Contents/MacOS/firefox-bin -profilemanager` to create a new profile specific to that Firefox version.
-8. Once the profile has been created, quit the app, and run it again like normal. You now have a working older Firefox version.
+1. Go to the mac folder.
+1. Select your preferred language, you will find the dmg package inside, download it.
+1. Drag and drop the application to any other folder but the `Applications` folder.
+1. Rename the application to something like `Firefox_Old`.
+1. Move the application to the `Applications` folder.
+1. Open up a terminal and run `/Applications/Firefox_Old.app/Contents/MacOS/firefox-bin -profilemanager` to create a new profile specific to that Firefox version.
+1. Once the profile has been created, quit the app, and run it again like normal. You now have a working older Firefox version.
diff --git a/doc/development/new_fe_guide/index.md b/doc/development/new_fe_guide/index.md
index 78931defa24..bfcca9cec7b 100644
--- a/doc/development/new_fe_guide/index.md
+++ b/doc/development/new_fe_guide/index.md
@@ -19,6 +19,10 @@ Guidance on topics related to development.
Learn about all the dependencies that make up our frontend, including some of our own custom built libraries.
+## [Modules](modules/index.md)
+
+Learn about all the internal JavaScript modules that make up our frontend.
+
## [Style guides](style/index.md)
Style guides to keep our code consistent.
diff --git a/doc/development/new_fe_guide/modules/dirty_submit.md b/doc/development/new_fe_guide/modules/dirty_submit.md
new file mode 100644
index 00000000000..6c03958b463
--- /dev/null
+++ b/doc/development/new_fe_guide/modules/dirty_submit.md
@@ -0,0 +1,23 @@
+# Dirty Submit
+
+> [Introduced][ce-21115] in GitLab 11.3.
+> [dirty_submit][dirty-submit]
+
+## Summary
+
+Prevent submitting forms with no changes.
+
+Currently handles `input`, `textarea` and `select` elements.
+
+## Usage
+
+```js
+import dirtySubmitFactory from './dirty_submit/dirty_submit_form';
+
+new DirtySubmitForm(document.querySelector('form'));
+// or
+new DirtySubmitForm(document.querySelectorAll('form'));
+```
+
+[ce-21115]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21115
+[dirty-submit]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/assets/javascripts/dirty_submit/ \ No newline at end of file
diff --git a/doc/development/new_fe_guide/modules/index.md b/doc/development/new_fe_guide/modules/index.md
new file mode 100644
index 00000000000..0a7f2dbd819
--- /dev/null
+++ b/doc/development/new_fe_guide/modules/index.md
@@ -0,0 +1,5 @@
+# Modules
+
+* [DirtySubmit](dirty_submit.md)
+
+ Disable form submits until there are unsaved changes. \ No newline at end of file
diff --git a/doc/development/new_fe_guide/style/prettier.md b/doc/development/new_fe_guide/style/prettier.md
index 6395af6f815..baaea67d38b 100644
--- a/doc/development/new_fe_guide/style/prettier.md
+++ b/doc/development/new_fe_guide/style/prettier.md
@@ -47,13 +47,13 @@ The source of these Yarn scripts can be found in `/scripts/frontend/prettier.js`
### Scripts during Conversion period
```
-node ./scripts/frontend/prettier.js check ./vendor/
+node ./scripts/frontend/prettier.js check-all ./vendor/
```
This will go over all files in a specific folder check it.
```
-node ./scripts/frontend/prettier.js save ./vendor/
+node ./scripts/frontend/prettier.js save-all ./vendor/
```
This will go over all files in a specific folder and save it.
diff --git a/doc/development/ordering_table_columns.md b/doc/development/ordering_table_columns.md
index 5d00e1f7a0c..e9c6481635b 100644
--- a/doc/development/ordering_table_columns.md
+++ b/doc/development/ordering_table_columns.md
@@ -1,32 +1,49 @@
-# Ordering Table Columns
+# Ordering Table Columns in PostgreSQL
Similar to C structures the space of a table is influenced by the order of
columns. This is because the size of columns is aligned depending on the type of
-the column. Take the following column order for example:
+the following column. Let's consider an example:
-* id (integer, 4 bytes)
-* name (text, variable)
-* user_id (integer, 4 bytes)
+- `id` (integer, 4 bytes)
+- `name` (text, variable)
+- `user_id` (integer, 4 bytes)
-Integers are aligned to the word size. This means that on a 64 bit platform the
-actual size of each column would be: 8 bytes, variable, 8 bytes. This means that
-each row will require at least 16 bytes for the two integers, and a variable
-amount for the text field. If a table has a few rows this is not an issue, but
-once you start storing millions of rows you can save space by using a different
-order. For the above example a more ideal column order would be the following:
+The first column is a 4-byte integer. The next is text of variable length. The
+`text` data type requires 1-word alignment, and on 64-bit platform, 1 word is 8
+bytes. To meet the alignment requirements, four zeros are to be added right
+after the first column, so `id` occupies 4 bytes, then 4 bytes of alignment
+padding, and only next `name` is being stored. Therefore, in this case, 8 bytes
+will be spent for storing a 4-byte integer.
-* id (integer, 4 bytes)
-* user_id (integer, 4 bytes)
-* name (text, variable)
+The space between rows is also subject to alignment padding. The `user_id`
+column takes only 4 bytes, and on 64-bit platform, 4 zeroes will be added for
+alignment padding, to allow storing the next row beginning with the "clear" word.
-In this setup the `id` and `user_id` columns can be packed together, which means
-we only need 8 bytes to store _both_ of them. This in turn each row will require
-8 bytes less of space.
+As a result, the actual size of each column would be (ommiting variable length
+data and 24-byte tuple header): 8 bytes, variable, 8 bytes. This means that
+each row will require at least 16 bytes for the two 4-byte integers. If a table
+has a few rows this is not an issue. However, once you start storing millions of
+rows you can save space by using a different order. For the above example, the
+ideal column order would be the following:
+
+- `id` (integer, 4 bytes)
+- `user_id` (integer, 4 bytes)
+- `name` (text, variable)
+
+or
+
+- `name` (text, variable)
+- `id` (integer, 4 bytes)
+- `user_id` (integer, 4 bytes)
+
+In these examples, the `id` and `user_id` columns are packed together, which
+means we only need 8 bytes to store _both_ of them. This in turn means each row
+will require 8 bytes less space.
For GitLab we require that columns of new tables are ordered based to use the
least amount of space. An easy way of doing this is to order them based on the
-type size in descending order with variable sizes (string and text columns for
-example) at the end.
+type size in descending order with variable sizes (`text`, `varchar`, arrays,
+`json`, `jsonb`, and so on) at the end.
## Type Sizes
@@ -36,7 +53,7 @@ of information we will list the sizes of common types here so it's easier to
look them up. Here "word" refers to the word size, which is 4 bytes for a 32
bits platform and 8 bytes for a 64 bits platform.
-| Type | Size | Aligned To |
+| Type | Size | Alignment needed |
|:-----------------|:-------------------------------------|:-----------|
| smallint | 2 bytes | 1 word |
| integer | 4 bytes | 1 word |
@@ -58,7 +75,7 @@ always be at the end of a table.
## Real Example
-Let's use the "events" table as an example, which currently has the following
+Let's use the `events` table as an example, which currently has the following
layout:
| Column | Type | Size |
@@ -89,8 +106,8 @@ divided into fixed size chunks as follows:
| 8 bytes | updated_at |
| 8 bytes | action, author_id |
-This means that excluding the variable sized data we need at least 48 bytes per
-row.
+This means that excluding the variable sized data and tuple header, we need at
+least 8 * 6 = 48 bytes per row.
We can optimise this by using the following column order instead:
@@ -120,8 +137,8 @@ This would produce the following chunks:
| variable | title |
| variable | data |
-Here we only need 40 bytes per row excluding the variable sized data. 8 bytes
-being saved may not sound like much, but for tables as large as the "events"
-table it does begin to matter. For example, when storing 80 000 000 rows this
-translates to a space saving of at least 610 MB: all by just changing the order
-of a few columns.
+Here we only need 40 bytes per row excluding the variable sized data and 24-byte
+tuple header. 8 bytes being saved may not sound like much, but for tables as
+large as the `events` table it does begin to matter. For example, when storing
+80 000 000 rows this translates to a space saving of at least 610 MB, all by
+just changing the order of a few columns.
diff --git a/doc/development/performance.md b/doc/development/performance.md
index 05caffb150a..4cc2fdc9a58 100644
--- a/doc/development/performance.md
+++ b/doc/development/performance.md
@@ -9,17 +9,17 @@ The process of solving performance problems is roughly as follows:
1. Make sure there's an issue open somewhere (e.g., on the GitLab CE issue
tracker), create one if there isn't. See [#15607][#15607] for an example.
-2. Measure the performance of the code in a production environment such as
+1. Measure the performance of the code in a production environment such as
GitLab.com (see the [Tooling](#tooling) section below). Performance should be
measured over a period of _at least_ 24 hours.
-3. Add your findings based on the measurement period (screenshots of graphs,
+1. Add your findings based on the measurement period (screenshots of graphs,
timings, etc) to the issue mentioned in step 1.
-4. Solve the problem.
-5. Create a merge request, assign the "Performance" label and assign it to
+1. Solve the problem.
+1. Create a merge request, assign the "Performance" label and assign it to
[@yorickpeterse][yorickpeterse] for reviewing.
-6. Once a change has been deployed make sure to _again_ measure for at least 24
+1. Once a change has been deployed make sure to _again_ measure for at least 24
hours to see if your changes have any impact on the production environment.
-7. Repeat until you're done.
+1. Repeat until you're done.
When providing timings make sure to provide:
@@ -34,13 +34,14 @@ graphs/dashboards.
## Tooling
-GitLab provides built-in tools to aid the process of improving performance:
+GitLab provides built-in tools to help improve performance and availability:
* [Profiling](profiling.md)
* [Sherlock](profiling.md#sherlock)
* [GitLab Performance Monitoring](../administration/monitoring/performance/index.md)
* [Request Profiling](../administration/monitoring/performance/request_profiling.md)
* [QueryRecoder](query_recorder.md) for preventing `N+1` regressions
+* [Chaos endpoints](chaos_endpoints.md) for testing failure scenarios. Intended mainly for testing availability.
GitLab employees can use GitLab.com's performance monitoring systems located at
<https://dashboards.gitlab.net>, this requires you to log in using your
@@ -93,14 +94,14 @@ result of this should be used instead of the `Benchmark` module.
In short:
-1. Don't trust benchmarks you find on the internet.
-2. Never make claims based on just benchmarks, always measure in production to
+- Don't trust benchmarks you find on the internet.
+- Never make claims based on just benchmarks, always measure in production to
confirm your findings.
-3. X being N times faster than Y is meaningless if you don't know what impact it
+- X being N times faster than Y is meaningless if you don't know what impact it
will actually have on your production environment.
-4. A production environment is the _only_ benchmark that always tells the truth
+- A production environment is the _only_ benchmark that always tells the truth
(unless your performance monitoring systems are not set up correctly).
-5. If you must write a benchmark use the benchmark-ips Gem instead of Ruby's
+- If you must write a benchmark use the benchmark-ips Gem instead of Ruby's
`Benchmark` module.
## Profiling
@@ -364,8 +365,7 @@ Depending on the size of the String and how frequently it would be allocated
there's no guarantee it will.
Strings will be frozen by default in Ruby 3.0. To prepare our code base for
-this eventuality, it's a good practice to add the following header to all
-Ruby files:
+this eventuality, we will be adding the following header to all Ruby files:
```ruby
# frozen_string_literal: true
@@ -379,6 +379,9 @@ test = +"hello"
test += " world"
```
+When adding new Ruby files, please check that you can add the above header,
+as omitting it may lead to style check failures.
+
## Anti-Patterns
This is a collection of [anti-patterns][anti-pattern] that should be avoided
diff --git a/doc/development/post_deployment_migrations.md b/doc/development/post_deployment_migrations.md
index cfc91539bee..5986efa9974 100644
--- a/doc/development/post_deployment_migrations.md
+++ b/doc/development/post_deployment_migrations.md
@@ -57,13 +57,13 @@ depends on this column being present while it's running. Normally you'd follow
these steps in such a case:
1. Stop the GitLab instance
-2. Run the migration removing the column
-3. Start the GitLab instance again
+1. Run the migration removing the column
+1. Start the GitLab instance again
Using post deployment migrations we can instead follow these steps:
1. Deploy a new version of GitLab while ignoring post deployment migrations
-2. Re-run `rake db:migrate` but without the environment variable set
+1. Re-run `rake db:migrate` but without the environment variable set
Here we don't need any downtime as the migration takes place _after_ a new
version (which doesn't depend on the column anymore) has been deployed.
diff --git a/doc/development/query_count_limits.md b/doc/development/query_count_limits.md
index 310e3faf61b..b3ecaf30d8a 100644
--- a/doc/development/query_count_limits.md
+++ b/doc/development/query_count_limits.md
@@ -8,8 +8,8 @@ in test environments we'll raise an error when this threshold is exceeded.
When a test fails because it executes more than 100 SQL queries there are two
solutions to this problem:
-1. Reduce the number of SQL queries that are executed.
-2. Whitelist the controller or API endpoint.
+- Reduce the number of SQL queries that are executed.
+- Whitelist the controller or API endpoint.
You should only resort to whitelisting when an existing controller or endpoint
is to blame as in this case reducing the number of SQL queries can take a lot of
diff --git a/doc/development/rake_tasks.md b/doc/development/rake_tasks.md
index fc51b74da1d..2ad748d4802 100644
--- a/doc/development/rake_tasks.md
+++ b/doc/development/rake_tasks.md
@@ -1,6 +1,6 @@
# Rake tasks for developers
-## Setup db with developer seeds
+## Set up db with developer seeds
Note that if your db user does not have advanced privileges you must create the db manually before running this command.
diff --git a/doc/development/rolling_out_changes_using_feature_flags.md b/doc/development/rolling_out_changes_using_feature_flags.md
index 905aa26a40b..b65fbc9d958 100644
--- a/doc/development/rolling_out_changes_using_feature_flags.md
+++ b/doc/development/rolling_out_changes_using_feature_flags.md
@@ -151,3 +151,40 @@ most cases this will translate to a feature (with a feature flag) being shipped
in RC1, followed by the feature flag being removed in RC2. This in turn means
the feature will be stable by the time we publish a stable package around the
22nd of the month.
+
+## Implicit feature flags
+
+The [`Project#feature_available?`][project-fa],
+[`Namespace#feature_available?`][namespace-fa] (EE), and
+[`License.feature_available?`][license-fa] (EE) methods all implicitly check for
+a feature flag by the same name as the provided argument.
+
+For example if a feature is license-gated, there's no need to add an additional
+explicit feature flag check since the flag will be checked as part of the
+`License.feature_available?` call. Similarly, there's no need to "clean up" a
+feature flag once the feature has reached general availability.
+
+You'd still want to use an explicit `Feature.enabled?` check if your new feature
+isn't gated by a License or Plan.
+
+[project-fa]: https://gitlab.com/gitlab-org/gitlab-ee/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/app/models/project_feature.rb#L63-68
+[namespace-fa]: https://gitlab.com/gitlab-org/gitlab-ee/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/ee/app/models/ee/namespace.rb#L71-85
+[license-fa]: https://gitlab.com/gitlab-org/gitlab-ee/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/ee/app/models/license.rb#L293-300
+
+### Undefined feature flags default to "on"
+
+An important side-effect of the [implicit feature
+flags][#implicit-feature-flags] mentioned above is that unless the feature is
+explicitly disabled or limited to a percentage of users, the feature flag check
+will default to `true`.
+
+As an example, if you were to ship the backend half of a feature behind a flag,
+you'd want to explicitly disable that flag until the frontend half is also ready
+to be shipped. You can do this via ChatOps:
+
+```
+/chatops run feature set some_feature 0
+```
+
+Note that you can do this at any time, even before the merge request using the
+flag has been merged!
diff --git a/doc/development/sidekiq_style_guide.md b/doc/development/sidekiq_style_guide.md
index 76ff51446ba..8e268224c98 100644
--- a/doc/development/sidekiq_style_guide.md
+++ b/doc/development/sidekiq_style_guide.md
@@ -17,8 +17,8 @@ would be `process_something`. If you're not sure what queue a worker uses,
you can find it using `SomeWorker.queue`. There is almost never a reason to
manually override the queue name using `sidekiq_options queue: :some_queue`.
-You must always add any new queues to `app/workers/all_queues.yml` otherwise
-your worker will not run.
+You must always add any new queues to `app/workers/all_queues.yml` or `ee/app/workers/all_queues.yml`
+otherwise your worker will not run.
## Queue Namespaces
diff --git a/doc/development/swapping_tables.md b/doc/development/swapping_tables.md
index 6b990ece72c..29cd6a43aff 100644
--- a/doc/development/swapping_tables.md
+++ b/doc/development/swapping_tables.md
@@ -8,8 +8,8 @@ Let's say you want to swap the table "events" with "events_for_migration". In
this case you need to follow 3 steps:
1. Rename "events" to "events_temporary"
-2. Rename "events_for_migration" to "events"
-3. Rename "events_temporary" to "events_for_migration"
+1. Rename "events_for_migration" to "events"
+1. Rename "events_temporary" to "events_for_migration"
Rails allows you to do this using the `rename_table` method:
diff --git a/doc/development/switching_to_rails5.md b/doc/development/switching_to_rails5.md
new file mode 100644
index 00000000000..c9a4ce1a1d1
--- /dev/null
+++ b/doc/development/switching_to_rails5.md
@@ -0,0 +1,27 @@
+# Switching to Rails 5
+
+GitLab switched recently to Rails 5. This is a big change (especially for backend development) and it introduces couple of temporary inconveniences.
+
+## After the switch, I found a broken feature. What do I do?
+
+Many fixes and tweaks were done to make our codebase compatible with Rails 5, but it's possible that not all issues were found. If you find an bug, please create an issue and assign it the ~rails5 label.
+
+## It takes much longer to run CI pipelines that build GitLab. Why?
+
+We are temporarily running CI pipelines with Rails 4 and 5 so that we ensure we remain compatible with Rails 4 in case we must revert back to Rails 4 from Rails 5 (this can double the duration of CI pipelines).
+
+We might revert back to Rails 4 if we found a major issue we were unable to quickly fix.
+
+Once we are sure we can stay with Rails 5, we will stop running CI pipelines with Rails 4.
+
+## Can I skip running Rails 4 tests?
+
+If you are sure that your merge request doesn't introduce any incompatibility, you can just include `norails4` anywhere in your branch name and Rails 4 tests will be skipped.
+
+## CI is failing on my test with Rails 4. How can I debug it?
+
+You can run specs locally with Rails 4 using the following command:
+
+```sh
+BUNDLE_GEMFILE=Gemfile.rails4 RAILS5=0 bundle exec rspec ...
+```
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index acbfa1850b4..72abda26e3d 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -209,6 +209,130 @@ it 'is overdue' do
end
```
+### Pristine test environments
+
+The code exercised by a single GitLab test may access and modify many items of
+data. Without careful preparation before a test runs, and cleanup afterward,
+data can be changed by a test in such a way that it affects the behaviour of
+following tests. This should be avoided at all costs! Fortunately, the existing
+test framework handles most cases already.
+
+When the test environment does get polluted, a common outcome is
+[flaky tests](flaky_tests.md). Pollution will often manifest as an order
+dependency: running spec A followed by spec B will reliably fail, but running
+spec B followed by spec A will reliably succeed. In these cases, you can use
+`rspec --bisect` (or a manual pairwise bisect of spec files) to determine which
+spec is at fault. Fixing the problem requires some understanding of how the test
+suite ensures the environment is pristine. Read on to discover more about each
+data store!
+
+#### SQL database
+
+This is managed for us by the `database_cleaner` gem. Each spec is surrounded in
+a transaction, which is rolled back once the test completes. Certain specs will
+instead issue `DELETE FROM` queries against every table after completion; this
+allows the created rows to be viewed from multiple database connections, which
+is important for specs that run in a browser, or migration specs, among others.
+
+One consequence of using these strategies, instead of the well-known
+`TRUNCATE TABLES` approach, is that primary keys and other sequences are **not**
+reset across specs. So if you create a project in spec A, then create a project
+in spec B, the first will have `id=1`, while the second will have `id=2`.
+
+This means that specs should **never** rely on the value of an ID, or any other
+sequence-generated column. To avoid accidental conflicts, specs should also
+avoid manually specifying any values in these kinds of columns. Instead, leave
+them unspecified, and look up the value after the row is created.
+
+#### Redis
+
+GitLab stores two main categories of data in Redis: cached items, and sidekiq
+jobs.
+
+In most specs, the Rails cache is actually an in-memory store. This is replaced
+between specs, so calls to `Rails.cache.read` and `Rails.cache.write` are safe.
+However, if a spec makes direct Redis calls, it should mark itself with the
+`:clean_gitlab_redis_cache`, `:clean_gitlab_redis_shared_state` or
+`:clean_gitlab_redis_queues` traits as appropriate.
+
+Sidekiq jobs are typically not run in specs, but this behaviour can be altered
+in each spec through the use of `Sidekiq::Testing.inline!` blocks. Any spec that
+causes Sidekiq jobs to be pushed to Redis should use the `:sidekiq` trait, to
+ensure that they are removed once the spec completes.
+
+#### Filesystem
+
+Filesystem data can be roughly split into "repositories", and "everything else".
+Repositories are stored in `tmp/tests/repositories`. This directory is emptied
+before a test run starts, and after the test run ends. It is not emptied between
+specs, so created repositories accumulate within this directory over the
+lifetime of the process. Deleting them is expensive, but this could lead to
+pollution unless carefully managed.
+
+To avoid this, [hashed storage](../../administration/repository_storage_types.md)
+is enabled in the test suite. This means that repositories are given a unique
+path that depends on their project's ID. Since the project IDs are not reset
+between specs, this guarantees that each spec gets its own repository on disk,
+and prevents changes from being visible between specs.
+
+If a spec manually specifies a project ID, or inspects the state of the
+`tmp/tests/repositories/` directory directly, then it should clean up the
+directory both before and after it runs. In general, these patterns should be
+completely avoided.
+
+Other classes of file linked to database objects, such as uploads, are generally
+managed in the same way. With hashed storage enabled in the specs, they are
+written to disk in locations determined by ID, so conflicts should not occur.
+
+Some specs disable hashed storage by passing the `:legacy_storage` trait to the
+`projects` factory. Specs that do this must **never** override the `path` of the
+project, or any of its groups. The default path includes the project ID, so will
+not conflict; but if two specs create a `:legacy_storage` project with the same
+path, they will use the same repository on disk and lead to test environment
+pollution.
+
+Other files must be managed manually by the spec. If you run code that creates a
+`tmp/test-file.csv` file, for instance, the spec must ensure that the file is
+removed as part of cleanup.
+
+#### Persistent in-memory application state
+
+All the specs in a given `rspec` run share the same Ruby process, which means
+they can affect each other by modifying Ruby objects that are accessible between
+specs. In practice, this means global variables, and constants (which includes
+Ruby classes, modules, etc).
+
+Global variables should generally not be modified. If absolutely necessary, a
+block like this can be used to ensure the change is rolled back afterwards:
+
+```ruby
+around(:each) do |example|
+ old_value = $0
+
+ begin
+ $0 = "new-value"
+ example.run
+ ensure
+ $0 = old_value
+ end
+end
+```
+
+If a spec needs to modify a constant, it should use the `stub_const` helper to
+ensure the change is rolled back.
+
+If you need to modify the contents of the `ENV` constant, you can use the
+`stub_env` helper method instead.
+
+While most Ruby **instances** are not shared between specs, **classes**
+and **modules** generally are. Class and module instance variables, accessors,
+class variables, and other stateful idioms, should be treated in the same way as
+global variables - don't modify them unless you have to! In particular, prefer
+using expectations, or dependency injection along with stubs, to avoid the need
+for modifications. If you have no other choice, an `around` block similar to the
+example for global variables, above, can be used, but this should be avoided if
+at all possible.
+
### Table-based / Parameterized tests
This style of testing is used to exercise one piece of code with a comprehensive
@@ -270,7 +394,7 @@ This is especially useful whenever it's showing 500 internal server error.
### Shared contexts
-All shared contexts should be be placed under `spec/support/shared_contexts/`.
+All shared contexts should be placed under `spec/support/shared_contexts/`.
Shared contexts can be placed in subfolder if they apply to a certain type of
specs only (e.g. features, requests etc.) but shouldn't be if they apply to
multiple type of specs.
@@ -280,7 +404,7 @@ Each file should include only one context and have a descriptive name, e.g.
### Shared examples
-All shared examples should be be placed under `spec/support/shared_examples/`.
+All shared examples should be placed under `spec/support/shared_examples/`.
Shared examples can be placed in subfolder if they apply to a certain type of
specs only (e.g. features, requests etc.) but shouldn't be if they apply to
multiple type of specs.
@@ -292,7 +416,7 @@ Each file should include only one context and have a descriptive name, e.g.
Helpers are usually modules that provide some methods to hide the complexity of
specific RSpec examples. You can define helpers in RSpec files if they're not
-intended to be shared with other specs. Otherwise, they should be be placed
+intended to be shared with other specs. Otherwise, they should be placed
under `spec/support/helpers/`. Helpers can be placed in subfolder if they apply
to a certain type of specs only (e.g. features, requests etc.) but shouldn't be
if they apply to multiple type of specs.
@@ -346,7 +470,38 @@ GitLab uses [factory_bot] as a test fixture replacement.
### Fixtures
-All fixtures should be be placed under `spec/fixtures/`.
+All fixtures should be placed under `spec/fixtures/`.
+
+### Repositories
+
+Testing some functionality, e.g., merging a merge request, requires a git
+repository with a certain state to be present in the test environment. GitLab
+maintains the [gitlab-test](https://gitlab.com/gitlab-org/gitlab-test)
+repository for certain common cases - you can ensure a copy of the repository is
+used with the `:repository` trait for project factories:
+
+```ruby
+let(:project) { create(:project, :repository) }
+```
+
+Where you can, consider using the `:custom_repo` trait instead of `:repository`.
+This allows you to specify exactly what files will appear in the `master` branch
+of the project's repository. For example:
+
+```ruby
+let(:project) do
+ create(
+ :project, :custom_repo,
+ files: {
+ 'README.md' => 'Content here',
+ 'foo/bar/baz.txt' => 'More content here'
+ }
+ )
+end
+```
+
+This will create a repository containing two files, with default permissions and
+the specified content.
### Config
diff --git a/doc/development/testing_guide/end_to_end_tests.md b/doc/development/testing_guide/end_to_end_tests.md
index 21ec926414d..e9f236c6b3a 100644
--- a/doc/development/testing_guide/end_to_end_tests.md
+++ b/doc/development/testing_guide/end_to_end_tests.md
@@ -1,32 +1,37 @@
-# End-to-End Testing
+# End-to-end Testing
-## What is End-to-End testing?
+## What is end-to-end testing?
-End-to-End testing is a strategy used to check whether your application works
-as expected across entire software stack and architecture, including
-integration of all microservices and components that are supposed to work
+End-to-end testing is a strategy used to check whether your application works
+as expected across the entire software stack and architecture, including
+integration of all micro-services and components that are supposed to work
together.
## How do we test GitLab?
We use [Omnibus GitLab][omnibus-gitlab] to build GitLab packages and then we
-test these packages using [GitLab QA][gitlab-qa] project, which is entirely
-black-box, click-driven testing framework.
+test these packages using the [GitLab QA orchestrator][gitlab-qa] tool, which is
+a black-box testing framework for the API and the UI.
### Testing nightly builds
We run scheduled pipeline each night to test nightly builds created by Omnibus.
-You can find these nightly pipelines at [GitLab QA pipelines page][gitlab-qa-pipelines].
+You can find these nightly pipelines at [gitlab-org/quality/nightly/pipelines][quality-nightly-pipelines].
+
+### Testing staging
+
+We run scheduled pipeline each night to test staging.
+You can find these nightly pipelines at [gitlab-org/quality/staging/pipelines][quality-staging-pipelines].
### Testing code in merge requests
It is possible to run end-to-end tests (eventually being run within a
[GitLab QA pipeline][gitlab-qa-pipelines]) for a merge request by triggering
-the `package-and-qa` manual action, that should be present in a merge request
-widget.
+the `package-and-qa` manual action in the `test` stage, that should be present
+in a merge request widget (unless the merge request is from a fork).
Manual action that starts end-to-end tests is also available in merge requests
-in Omnibus GitLab project.
+in [Omnibus GitLab][omnibus-gitlab].
Below you can read more about how to use it and how does it work.
@@ -35,46 +40,56 @@ Below you can read more about how to use it and how does it work.
Currently, we are using _multi-project pipeline_-like approach to run QA
pipelines.
-1. Developer triggers a manual action, that can be found in CE and EE merge
+1. Developer triggers a manual action, that can be found in CE / EE merge
requests. This starts a chain of pipelines in multiple projects.
-1. The script being executed triggers a pipeline in GitLab Omnibus and waits
-for the resulting status. We call this a _status attribution_.
+1. The script being executed triggers a pipeline in [Omnibus GitLab][omnibus-gitlab]
+and waits for the resulting status. We call this a _status attribution_.
-1. GitLab packages are being built in Omnibus pipeline. Packages are going to be
-pushed to Container Registry.
+1. GitLab packages are being built in the [Omnibus GitLab][omnibus-gitlab]
+pipeline. Packages are then pushed to its Container Registry.
1. When packages are ready, and available in the registry, a final step in the
-pipeline, that is now running in Omnibus, triggers a new pipeline in the GitLab
-QA project. It also waits for a resulting status.
+[Omnibus GitLab][omnibus-gitlab] pipeline, triggers a new
+[GitLab QA pipeline][gitlab-qa-pipelines]. It also waits for a resulting status.
1. GitLab QA pulls images from the registry, spins-up containers and runs tests
against a test environment that has been just orchestrated by the `gitlab-qa`
tool.
-1. The result of the GitLab QA pipeline is being propagated upstream, through
-Omnibus, back to CE / EE merge request.
+1. The result of the [GitLab QA pipeline][gitlab-qa-pipelines] is being
+propagated upstream, through Omnibus, back to the CE / EE merge request.
#### How do I write tests?
In order to write new tests, you first need to learn more about GitLab QA
-architecture. See the [documentation about it][gitlab-qa-architecture] in
-GitLab QA project.
+architecture. See the [documentation about it][gitlab-qa-architecture].
-Once you decided where to put test environment orchestration scenarios and
-instance specs, take a look at the [relevant documentation][instance-qa-readme]
-and examples in [the `qa/` directory][instance-qa-examples].
+Once you decided where to put [test environment orchestration scenarios] and
+[instance-level scenarios], take a look at the [GitLab QA README][instance-qa-readme],
+the [GitLab QA orchestrator README][gitlab-qa-readme], and [the already existing
+instance-level scenarios][instance-level scenarios].
## Where can I ask for help?
You can ask question in the `#quality` channel on Slack (GitLab internal) or
you can find an issue you would like to work on in
-[the issue tracker][gitlab-qa-issues] and start a new discussion there.
+[the `gitlab-ce` issue tracker][gitlab-ce-issues],
+[the `gitlab-ee` issue tracker][gitlab-ce-issues], or
+[the `gitlab-qa` issue tracker][gitlab-qa-issues].
[omnibus-gitlab]: https://gitlab.com/gitlab-org/omnibus-gitlab
[gitlab-qa]: https://gitlab.com/gitlab-org/gitlab-qa
+[gitlab-qa-readme]: https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md
[gitlab-qa-pipelines]: https://gitlab.com/gitlab-org/gitlab-qa/pipelines
+[quality-nightly-pipelines]: https://gitlab.com/gitlab-org/quality/nightly/pipelines
+[quality-staging-pipelines]: https://gitlab.com/gitlab-org/quality/staging/pipelines
[gitlab-qa-architecture]: https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/architecture.md
-[gitlab-qa-issues]: https://gitlab.com/gitlab-org/gitlab-qa/issues
+[gitlab-qa-issues]: https://gitlab.com/gitlab-org/gitlab-qa/issues?label_name%5B%5D=new+scenario
+[gitlab-ce-issues]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name[]=QA&label_name[]=test
+[gitlab-ee-issues]: https://gitlab.com/gitlab-org/gitlab-ee/issues?label_name[]=QA&label_name[]=test
+[test environment orchestration scenarios]: https://gitlab.com/gitlab-org/gitlab-qa/tree/master/lib/gitlab/qa/scenario
+[instance-level scenarios]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/qa/specs/features
+[Page objects documentation]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/qa/page/README.md
[instance-qa-readme]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/README.md
[instance-qa-examples]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa/qa
diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md
index 38ea2f1dde1..a6ed9e85a41 100644
--- a/doc/development/testing_guide/review_apps.md
+++ b/doc/development/testing_guide/review_apps.md
@@ -1,81 +1,104 @@
-# Review apps
+# Review Apps
-We currently have review apps available as a manual job in EE pipelines. Here is
-[the first implementation](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/6259).
-
-That said, [the Quality team is working](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/6665)
-on making Review Apps automatically deployed by each pipeline, both in CE and EE.
+Review Apps are automatically deployed by each pipeline, both in
+[CE](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22010) and
+[EE](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/6665).
## How does it work?
-1. On every EE [pipeline][gitlab-pipeline] during the `test` stage, you can
- start the [`review` job][review-job]
-1. The `review` job [triggers a pipeline][cng-pipeline] in the
- [`CNG-mirror`][cng-mirror] [^1] project
-1. The `CNG-mirror` pipeline creates the Docker images of each component (e.g. `gitlab-rails-ee`,
- `gitlab-shell`, `gitaly` etc.) based on the commit from the
- [GitLab pipeline][gitlab-pipeline] and store them in its
- [registry][cng-mirror-registry]
-1. Once all images are built, the review app is deployed using
- [the official GitLab Helm chart][helm-chart] [^2] to the
- [`review-apps-ee` Kubernetes cluster on GCP][review-apps-ee]
- - The actual scripts used to deploy the review app can be found at
- [`scripts/review_apps/review-apps.sh`][review-apps.sh]
- - These scripts are basically
- [our official Auto DevOps scripts][Auto-DevOps.gitlab-ci.yml] where the
- default CNG images are overriden with the images built and stored in the
- [`CNG-mirror` project's registry][cng-mirror-registry]
-1. Once the `review` job succeeds, you should be able to use your review app
- thanks to the direct link to it from the MR widget. The default username is
- `root` and its password can be found in the 1Password secure note named
- **gitlab-{ce,ee} review app's root password**.
+1. On every [pipeline][gitlab-pipeline] during the `test` stage, the
+ [`review-deploy`][review-deploy-job] job is automatically started.
+1. The `review-deploy` job:
+ 1. Waits for the `gitlab:assets:compile` job to finish since the
+ [`CNG-mirror`][cng-mirror] pipeline triggerred in the following step
+ depends on it.
+ 1. [Triggers a pipeline][cng-pipeline] in the [`CNG-mirror`][cng-mirror]
+ project.
+ - We use the `CNG-mirror` project so that the `CNG`, (**C**loud
+ **N**ative **G**itLab), project's registry is not overloaded with a
+ lot of transient Docker images.
+ - The `CNG-mirror` pipeline creates the Docker images of each component
+ (e.g. `gitlab-rails-ee`, `gitlab-shell`, `gitaly` etc.) based on the
+ commit from the [GitLab pipeline][gitlab-pipeline] and store them in
+ its [registry][cng-mirror-registry].
+ 1. Once all images are built by [`CNG-mirror`][cng-mirror], the Review App
+ is deployed using [the official GitLab Helm chart][helm-chart] to the
+ [`review-apps-ce`][review-apps-ce] / [`review-apps-ee`][review-apps-ee]
+ Kubernetes cluster on GCP.
+ - The actual scripts used to deploy the Review App can be found at
+ [`scripts/review_apps/review-apps.sh`][review-apps.sh].
+ - These scripts are basically
+ [our official Auto DevOps scripts][Auto-DevOps.gitlab-ci.yml] where the
+ default CNG images are overridden with the images built and stored in the
+ [`CNG-mirror` project's registry][cng-mirror-registry].
+ - Since we're using [the official GitLab Helm chart][helm-chart], this means
+ you get a dedicated environment for your branch that's very close to what
+ it would look in production.
+1. Once the `review-deploy` job succeeds, you should be able to use your Review
+ App thanks to the direct link to it from the MR widget. The default username
+ is `root` and its password can be found in the 1Password secure note named
+ **gitlab-{ce,ee} Review App's root password** (note that there's currently
+ [a bug where the default password seems to be overridden][password-bug]).
**Additional notes:**
-- The Kubernetes cluster is connected to the `gitlab-ee` project using [GitLab's
- Kubernetes integration][gitlab-k8s-integration]. This basically allows to have
- a link to the review app directly from the merge request widget.
-- The manual `stop_review` in the `post-cleanup` stage can be used to stop a
- review app manually, and is also started by GitLab once a branch is deleted
-- [TBD] Review apps are cleaned up regularly using a pipeline schedule that runs
- the [`scripts/review_apps/automated_cleanup.rb`][automated_cleanup.rb] script
+- The Kubernetes cluster is connected to the `gitlab-{ce,ee}` projects using
+ [GitLab's Kubernetes integration][gitlab-k8s-integration]. This basically
+ allows to have a link to the Review App directly from the merge request
+ widget.
+- If the Review App deployment fails, you can simply retry it (there's no need
+ to run the [`review-stop`][gitlab-ci-yml] job first).
+- The manual [`review-stop`][gitlab-ci-yml] in the `test` stage can be used to
+ stop a Review App manually, and is also started by GitLab once a branch is
+ deleted.
+- Review Apps are cleaned up regularly using a pipeline schedule that runs
+ the [`schedule:review-cleanup`][gitlab-ci-yml] job.
+
+## QA runs
+
+On every [pipeline][gitlab-pipeline] during the `test` stage, the
+`review-qa-smoke` job is automatically started: it runs the smoke QA suite.
+You can also manually start the `review-qa-all`: it runs the full QA suite.
-[^1]: We use the `CNG-mirror` project so that the `CNG`, (**C**loud **N**ative **G**itLab), project's registry is
- not overloaded with a lot of transient Docker images.
-[^2]: Since we're using [the official GitLab Helm chart][helm-chart], this means
- you get the a dedicated environment for your branch that's very close to what it
- would look in production
+Note that both jobs first wait for the `review-deploy` job to be finished.
## Frequently Asked Questions
-**Will it be too much to trigger CNG image builds on every test run? This could create thousands of unused docker images.**
+**Isn't it too much to trigger CNG image builds on every test run? This creates
+thousands of unused Docker images.**
- > We have to start somewhere and improve later. If we see this getting out of hand, we will revisit.
+ > We have to start somewhere and improve later. Also, we're using the
+ CNG-mirror project to store these Docker images so that we can just wipe out
+ the registry at some point, and use a new fresh, empty one.
-**How big is the Kubernetes cluster?**
+**How big are the Kubernetes clusters (`review-apps-ce` and `review-apps-ee`)?**
- > The cluster is currently setup with a single pool of preemptible
- nodes, with a minimum of 1 node and a maximum of 30 nodes.
+ > The clusters are currently set up with a single pool of preemptible nodes,
+ with a minimum of 1 node and a maximum of 100 nodes.
**What are the machine running on the cluster?**
> We're currently using `n1-standard-4` (4 vCPUs, 15 GB memory) machines.
-**How do we secure this from abuse? Apps are open to the world so we need to find a way to limit it to only us.**
+**How do we secure this from abuse? Apps are open to the world so we need to
+find a way to limit it to only us.**
- > This won't work for forks. We will add a root password to 1password shared vault.
+ > This isn't enabled for forks.
-[gitlab-pipeline]: https://gitlab.com/gitlab-org/gitlab-ee/pipelines/29302122
-[review-job]: https://gitlab.com/gitlab-org/gitlab-ee/-/jobs/94294136
+[gitlab-pipeline]: https://gitlab.com/gitlab-org/gitlab-ce/pipelines/35850709
+[review-deploy-job]: https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/118076368
[cng-mirror]: https://gitlab.com/gitlab-org/build/CNG-mirror
-[cng-pipeline]: https://gitlab.com/gitlab-org/build/CNG-mirror/pipelines/29307727
+[cng-pipeline]: https://gitlab.com/gitlab-org/build/CNG-mirror/pipelines/35883435
[cng-mirror-registry]: https://gitlab.com/gitlab-org/build/CNG-mirror/container_registry
[helm-chart]: https://gitlab.com/charts/gitlab/
+[review-apps-ce]: https://console.cloud.google.com/kubernetes/clusters/details/us-central1-a/review-apps-ce?project=gitlab-review-apps
[review-apps-ee]: https://console.cloud.google.com/kubernetes/clusters/details/us-central1-b/review-apps-ee?project=gitlab-review-apps
[review-apps.sh]: https://gitlab.com/gitlab-org/gitlab-ee/blob/master/scripts/review_apps/review-apps.sh
[automated_cleanup.rb]: https://gitlab.com/gitlab-org/gitlab-ee/blob/master/scripts/review_apps/automated_cleanup.rb
-[Auto-DevOps.gitlab-ci.yml]: https://gitlab.com/gitlab-org/gitlab-ci-yml/blob/master/Auto-DevOps.gitlab-ci.yml
+[Auto-DevOps.gitlab-ci.yml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+[gitlab-ci-yml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml
[gitlab-k8s-integration]: https://docs.gitlab.com/ee/user/project/clusters/index.html
+[password-bug]: https://gitlab.com/gitlab-org/gitlab-ce/issues/53621
---
diff --git a/doc/development/testing_guide/smoke.md b/doc/development/testing_guide/smoke.md
index 3f2843cba6e..3360031c220 100644
--- a/doc/development/testing_guide/smoke.md
+++ b/doc/development/testing_guide/smoke.md
@@ -1,8 +1,9 @@
# Smoke Tests
-It is imperative in any testing suite that we have Smoke Tests. In short, smoke tests are will run quick sanity
-end-to-end functional tests from GitLab QA and are designed to run against the specified environment to ensure that
-basic functionality is working.
+It is imperative in any testing suite that we have Smoke Tests. In short, smoke
+tests will run quick sanity end-to-end functional tests from GitLab QA and are
+designed to run against the specified environment to ensure that basic
+functionality is working.
Currently, our suite consists of this basic functionality coverage:
@@ -11,6 +12,8 @@ Currently, our suite consists of this basic functionality coverage:
- Issue Creation
- Merge Request Creation
+Smoke tests have the `:smoke` RSpec metadata.
+
---
[Return to Testing documentation](index.md)
diff --git a/doc/development/testing_guide/testing_levels.md b/doc/development/testing_guide/testing_levels.md
index 32ed22ca3ed..a8671fc3aa3 100644
--- a/doc/development/testing_guide/testing_levels.md
+++ b/doc/development/testing_guide/testing_levels.md
@@ -34,7 +34,11 @@ records should use stubs/doubles as much as possible.
Formal definition: https://en.wikipedia.org/wiki/Integration_testing
-These kind of tests ensure that individual parts of the application work well together, without the overhead of the actual app environment (i.e. the browser). These tests should assert at the request/response level: status code, headers, body. They're useful to test permissions, redirections, what view is rendered etc.
+These kind of tests ensure that individual parts of the application work well
+together, without the overhead of the actual app environment (i.e. the browser).
+These tests should assert at the request/response level: status code, headers,
+body.
+They're useful to test permissions, redirections, what view is rendered etc.
| Code path | Tests path | Testing engine | Notes |
| --------- | ---------- | -------------- | ----- |
@@ -67,20 +71,40 @@ run JavaScript tests, so you can either run unit tests (e.g. test a single
JavaScript method), or integration tests (e.g. test a component that is composed
of multiple components).
-## System tests or feature tests
+## White-box tests at the system level (formerly known as System / Feature tests)
-Formal definition: https://en.wikipedia.org/wiki/System_testing.
+Formal definitions:
-These kind of tests ensure the application works as expected from a user point
-of view (aka black-box testing). These tests should test a happy path for a
-given page or set of pages, and a test case should be added for any regression
+- https://en.wikipedia.org/wiki/System_testing
+- https://en.wikipedia.org/wiki/White-box_testing
+
+These kind of tests ensure the GitLab *Rails* application (i.e.
+`gitlab-ce`/`gitlab-ee`) works as expected from a *browser* point of view.
+
+Note that:
+
+- knowledge of the internals of the application are still required
+- data needed for the tests are usually created directly using RSpec factories
+- expectations are often set on the database or objects state
+
+These tests should only be used when:
+
+- the functionality/component being tested is small
+- the internal state of the objects/database *needs* to be tested
+- it cannot be tested at a lower level
+
+For instance, to test the breadcrumbs on a given page, writing a system test
+makes sense since it's a small component, which cannot be tested at the unit or
+controller level.
+
+Only test the happy path, but make sure to add a test case for any regression
that couldn't have been caught at lower levels with better tests (i.e. if a
regression is found, regression tests should be added at the lowest-level
possible).
| Tests path | Testing engine | Notes |
| ---------- | -------------- | ----- |
-| `spec/features/` | [Capybara] + [RSpec] | If your spec has the `:js` metadata, the browser driver will be [Poltergeist], otherwise it's using [RackTest]. |
+| `spec/features/` | [Capybara] + [RSpec] | If your test has the `:js` metadata, the browser driver will be [Poltergeist], otherwise it's using [RackTest]. |
### Consider **not** writing a system test!
@@ -89,7 +113,7 @@ we have enough Unit & Integration tests), we shouldn't need to duplicate their
thorough testing at the System test level.
It's very easy to add tests, but a lot harder to remove or improve tests, so one
-should take care of not introducing too many (slow and duplicated) specs.
+should take care of not introducing too many (slow and duplicated) tests.
The reasons why we should follow these best practices are as follows:
@@ -107,29 +131,33 @@ The reasons why we should follow these best practices are as follows:
[Poltergeist]: https://github.com/teamcapybara/capybara#poltergeist
[RackTest]: https://github.com/teamcapybara/capybara#racktest
-## Black-box tests or end-to-end tests
+## Black-box tests at the system level, aka end-to-end tests
+
+Formal definitions:
+
+- https://en.wikipedia.org/wiki/System_testing
+- https://en.wikipedia.org/wiki/Black-box_testing
GitLab consists of [multiple pieces] such as [GitLab Shell], [GitLab Workhorse],
[Gitaly], [GitLab Pages], [GitLab Runner], and GitLab Rails. All theses pieces
are configured and packaged by [GitLab Omnibus].
-[GitLab QA] is a tool that allows to test that all these pieces integrate well
-together by building a Docker image for a given version of GitLab Rails and
-running feature tests (i.e. using Capybara) against it.
+The QA framework and instance-level scenarios are [part of GitLab Rails] so that
+they're always in-sync with the codebase (especially the views).
-The actual test scenarios and steps are [part of GitLab Rails] so that they're
-always in-sync with the codebase.
+Note that:
-### Smoke tests
-
-Smoke tests are quick tests that may be run at any time (especially after the pre-deployment migrations).
+- knowledge of the internals of the application are not required
+- data needed for the tests can only be created using the GUI or the API
+- expectations can only be made against the browser page and API responses
-Much like feature tests - these tests run against the UI and ensure that basic functionality is working.
+Every new feature should come with a [test plan].
-> See [Smoke Tests](smoke.md) for more information.
+| Tests path | Testing engine | Notes |
+| ---------- | -------------- | ----- |
+| `qa/qa/specs/features/` | [Capybara] + [RSpec] + Custom QA framework | Tests should be placed under their corresponding [Product category] |
-Read a separate document about [end-to-end tests](end_to_end_tests.md) to
-learn more.
+> See [end-to-end tests](end_to_end_tests.md) for more information.
[multiple pieces]: ../architecture.md#components
[GitLab Shell]: https://gitlab.com/gitlab-org/gitlab-shell
@@ -138,8 +166,29 @@ learn more.
[GitLab Pages]: https://gitlab.com/gitlab-org/gitlab-pages
[GitLab Runner]: https://gitlab.com/gitlab-org/gitlab-runner
[GitLab Omnibus]: https://gitlab.com/gitlab-org/omnibus-gitlab
-[GitLab QA]: https://gitlab.com/gitlab-org/gitlab-qa
[part of GitLab Rails]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/qa
+[test plan]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/.gitlab/issue_templates/Test%20plan.md
+[Product category]: https://about.gitlab.com/handbook/product/categories/
+
+### Smoke tests
+
+Smoke tests are quick tests that may be run at any time (especially after the
+pre-deployment migrations).
+
+These tests run against the UI and ensure that basic functionality is working.
+
+> See [Smoke Tests](smoke.md) for more information.
+
+### GitLab QA orchestrator
+
+[GitLab QA orchestrator] is a tool that allows to test that all these pieces
+integrate well together by building a Docker image for a given version of GitLab
+Rails and running end-to-end tests (i.e. using Capybara) against it.
+
+Learn more in the [GitLab QA orchestrator README][gitlab-qa-readme].
+
+[GitLab QA orchestrator]: https://gitlab.com/gitlab-org/gitlab-qa
+[gitlab-qa-readme]: https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md
## EE-specific tests
diff --git a/doc/development/ui_guide.md b/doc/development/ui_guide.md
index df6ac452300..1e84bf608f4 100644
--- a/doc/development/ui_guide.md
+++ b/doc/development/ui_guide.md
@@ -1,107 +1,5 @@
-# UI Guide for building GitLab
+---
+redirect_to: 'https://design.gitlab.com/'
+---
-## GitLab UI development kit
-
-We created a page inside GitLab where you can check commonly used html and css elements.
-
-When you run GitLab instance locally - just visit http://localhost:3000/help/ui page to see UI examples
-you can use during GitLab development.
-
-## Design repository
-
-All design files are stored in the [gitlab-design](https://gitlab.com/gitlab-org/gitlab-design)
-repository and maintained by GitLab UX designers.
-
-## Navigation
-
-GitLab's layout contains 2 sections: the left sidebar and the content. The left sidebar contains a static navigation menu.
-This menu will be visible regardless of what page you visit.
-The content section contains a header and the content itself. The header describes the current GitLab page and what navigation is
-available to the user in this area. Depending on the area (project, group, profile setting) the header name and navigation may change. For example, when the user visits one of the
-project pages the header will contain the project's name and navigation for that project. When the user visits a group page it will contain the group's name and navigation related to this group.
-
-You can see a visual representation of the navigation in GitLab in the GitLab Product Map, which is located in the [Design Repository][gitlab-map-graffle]
-along with [PDF][gitlab-map-pdf] and [PNG][gitlab-map-png] exports.
-
-
-### Adding new tab to header navigation
-
-We try to keep the amount of tabs in the header navigation between 5 and 10 so that it fits on a typical laptop screen. We also try not to confuse the user with too many options. Ideally each
-tab should represent separate functionality. Everything related to the issue
-tracker should be under the 'Issues' tab while everything related to the wiki should
-be under 'Wiki' tab and so on and so forth.
-When adding a new tab to the header don't use more than 2 words for text in the link.
-We want to keep links short and easy to remember and fit all of them in the small screen.
-
-## Mobile screen size
-
-We want GitLab to work well on small mobile screens as well. Size limitations make it is impossible to fit everything on a mobile screen. In this case it is OK to hide
-part of the UI for smaller resolutions in favor of a better user experience.
-However core functionality like browsing files, creating issues, writing comments, should
-be available on all resolutions.
-
-## Icons
-
-* `trash` icon for button or link that does destructive action like removing
-information from database or file system
-* `x` icon for closing/hiding UI element. For example close modal window
-* `pencil` icon for edit button or link
-* `eye` icon for subscribe action
-* `rss` for rss/atom feed
-* `plus` for link or dropdown that lead to page where you create new object (For example new issue page)
-
-### SVGs
-
-When exporting SVGs, be sure to follow the following guidelines:
-
-1. Convert all strokes to outlines.
-2. Use pathfinder tools to combine overlapping paths and create compound paths.
-3. SVGs that are limited to one color should be exported without a fill color so the color can be set using CSS.
-4. Ensure that exported SVGs have been run through an [SVG cleaner](https://github.com/RazrFalcon/SVGCleaner) to remove unused elements and attributes.
-
-You can open your svg in a text editor to ensure that it is clean.
-Incorrect files will look like this:
-
-```xml
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg width="16px" height="17px" viewBox="0 0 16 17" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <!-- Generator: Sketch 3.7.2 (28276) - http://www.bohemiancoding.com/sketch -->
- <title>Group</title>
- <desc>Created with Sketch.</desc>
- <defs></defs>
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
- <g id="Group" fill="#7E7C7C">
- <path d="M15.1111,1 L0.8891,1 C0.3981,1 0.0001,1.446 0.0001,1.996 L0.0001,15.945 C0.0001,16.495 0.3981,16.941 0.8891,16.941 L15.1111,16.941 C15.6021,16.941 16.0001,16.495 16.0001,15.945 L16.0001,1.996 C16.0001,1.446 15.6021,1 15.1111,1 L15.1111,1 L15.1111,1 Z M14.0001,6.0002 L14.0001,14.949 L2.0001,14.949 L2.0001,6.0002 L14.0001,6.0002 Z M14.0001,4.0002 L14.0001,2.993 L2.0001,2.993 L2.0001,4.0002 L14.0001,4.0002 Z" id="Combined-Shape"></path>
- <polygon id="Fill-11" points="3 2.0002 5 2.0002 5 0.0002 3 0.0002"></polygon>
- <polygon id="Fill-16" points="11 2.0002 13 2.0002 13 0.0002 11 0.0002"></polygon>
- <path d="M5.37709616,11.5511984 L6.92309616,12.7821984 C7.35112915,13.123019 7.97359761,13.0565604 8.32002627,12.6330535 L10.7740263,9.63305349 C11.1237073,9.20557058 11.0606364,8.57555475 10.6331535,8.22587373 C10.2056706,7.87619272 9.57565475,7.93926361 9.22597373,8.36674651 L6.77197373,11.3667465 L8.16890384,11.2176016 L6.62290384,9.98660159 C6.19085236,9.6425813 5.56172188,9.71394467 5.21770159,10.1459962 C4.8736813,10.5780476 4.94504467,11.2071781 5.37709616,11.5511984 L5.37709616,11.5511984 Z" id="Stroke-21"></path>
- </g>
- </g>
-</svg>
-```
-
-Correct file will look like this:
-
-```xml
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 17" enable-background="new 0 0 16 17"><path d="m15.1 1h-2.1v-1h-2v1h-6v-1h-2v1h-2.1c-.5 0-.9.5-.9 1v14c0 .6.4 1 .9 1h14.2c.5 0 .9-.4.9-1v-14c0-.5-.4-1-.9-1m-1.1 14h-12v-9h12v9m0-11h-12v-1h12v1"/><path d="m5.4 11.6l1.5 1.2c.4.3 1.1.3 1.4-.1l2.5-3c.3-.4.3-1.1-.1-1.4-.5-.4-1.1-.3-1.5.1l-1.8 2.2-.8-.6c-.4-.3-1.1-.3-1.4.2-.3.4-.3 1 .2 1.4"/></svg>
-```
-
-
-## Buttons
-
-* Button should contain icon or text. Exceptions should be approved by UX designer.
-* Use red button for destructive actions (not revertable). For example removing issue.
-* Use green or blue button for primary action. Primary button should be only one.
-Do not use both green and blue button in one form.
-* For all other cases use default white button.
-* Text button should have only first word capitalized. So should be "Create issue" instead of "Create Issue"
-
-## Counts
-
-* Always use the [`number_with_delimiter`][number_with_delimiter] helper to
- display counts in the UI.
-
-[number_with_delimiter]: http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html#method-i-number_with_delimiter
-[gitlab-map-graffle]: https://gitlab.com/gitlab-org/gitlab-design/blob/master/production/resources/gitlab-map.graffle
-[gitlab-map-pdf]: https://gitlab.com/gitlab-org/gitlab-design/raw/master/production/resources/gitlab-map.pdf
-[gitlab-map-png]: https://gitlab.com/gitlab-org/gitlab-design/raw/master/production/resources/gitlab-map.png
+The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/utilities.md b/doc/development/utilities.md
index 0d074a3ef05..e5466ae8914 100644
--- a/doc/development/utilities.md
+++ b/doc/development/utilities.md
@@ -171,8 +171,8 @@ class Commit
extend Gitlab::Cache::RequestCache
def author
- User.find_by_any_email(author_email.downcase)
+ User.find_by_any_email(author_email)
end
- request_cache(:author) { author_email.downcase }
+ request_cache(:author) { author_email }
end
```
diff --git a/doc/development/ux_guide/animation.md b/doc/development/ux_guide/animation.md
index 797390a6845..583ff19bc69 100644
--- a/doc/development/ux_guide/animation.md
+++ b/doc/development/ux_guide/animation.md
@@ -1,65 +1,5 @@
-# Animation
+---
+redirect_to: 'https://design.gitlab.com/foundations/motion'
+---
-Motion is a tool to help convey important relationships, changes or transitions between elements. It should be used sparingly and intentionally, highlighting the right elements at the right moment.
-
-## Timings
-
-The longer distance an object travel, the timing should be longer for the animation. However, when in doubt, we should avoid large, full screen animations.
-
-Subtle animations, or objects leaving the screen should take **100-200 milliseconds**. Objects entering the screen, or motion we want to use to direct user attention can take between **200-400 milliseconds**. We should avoid animations of longer than 400 milliseconds as they will make the experience appear sluggish. If a specific animation feels like it will need more than 400 milliseconds, revisit the animation to see if there is a simpler, easier, shorter animation to implement.
-
-## Easing
-
-Easing specifies the rate of change of a parameter over time (see [easings.net](http://easings.net/)). Adding an easing curve will make the motion feel more natural. Being consistent with the easing curves will make the whole experience feel more cohesive and connected.
-
-* When an object is entering the screen, or transforming the scale, position, or shape, use the **easeOutQuint** curve (`cubic-bezier(0.23, 1, 0.32, 1)`)
-* When an object is leaving the screen, or transforming the opacity or color, no easing curve is needed. It shouldn't _slow down_ as it is exiting the screen, as that draws attention on the leaving object, where we don't want it. Adding easing to opacity and color transitions will make the motion appear less smooth. Therefore, for these cases, motion should just be **linear**.
-
-## Types of animations
-
-### Hover
-
-Interactive elements (links, buttons, etc.) should have a hover state. A subtle animation for this transition adds a polished feel. We should target a `100ms - 150ms linear` transition for a color hover effect.
-
-View the [interactive example](http://codepen.io/awhildy/full/GNyEvM/) here.
-
-![Hover animation](img/animation-hover.gif)
-
-### Dropdowns
-
-The dropdown menu should feel like it is appearing from the triggering element. Combining a position shift `400ms cubic-bezier(0.23, 1, 0.32, 1)` with an opacity animation `200ms linear` on the second half of the motion achieves this affect.
-
-View the [interactive example](http://codepen.io/awhildy/full/jVLJpb/) here.
-
-![Dropdown animation](img/animation-dropdown.gif)
-
-### Quick update
-
-When information is updating in place, a quick, subtle animation is needed. The previous content should cut out, and the new content should have a quick, `200ms linear` fade in.
-
-![Quick update animation](img/animation-quickupdate.gif)
-
-### Skeleton loading
-
-Skeleton loading is explained in the [component section](components.html#skeleton-loading) of the UX guide. It includes a horizontally pulsating animation that shows motion as if it's growing. It's timing is a slower `linear 1s`.
-
-![Skeleton loading animation](img/skeleton-loading.gif)
-
-### Moving transitions
-
-When elements move on screen, there should be a quick animation so it is clear to users what moved where. The timing of this animation differs based on the amount of movement and change. Consider animations between `200ms` and `400ms`.
-
-#### Shifting elements on reorder
-An example of a moving transition is when elements have to move out of the way when you drag an element.
-
-View the [interactive example](http://codepen.io/awhildy/full/ALyKPE/) here.
-
-![Reorder animation](img/animation-reorder.gif)
-
-#### Autoscroll the page
-
-Another example of a moving transition is when you have to autoscroll the page to keep an active element visible.
-
-View the [interactive example](http://codepen.io/awhildy/full/PbxgVo/) here.
-
-![Autoscroll animation](img/animation-autoscroll.gif)
+The content of this document was moved into the [GitLab Design System](https://design.gitlab.com).
diff --git a/doc/development/ux_guide/basics.md b/doc/development/ux_guide/basics.md
index e215026bcca..1e84bf608f4 100644
--- a/doc/development/ux_guide/basics.md
+++ b/doc/development/ux_guide/basics.md
@@ -1,82 +1,5 @@
-# Basics
-
-## Contents
-* [Responsive](#responsive)
-* [Typography](#typography)
-* [Icons](#icons)
-* [Color](#color)
-* [Cursors](#cursors)
-
----
-
-## Responsive
-GitLab is a responsive experience that works well across all screen sizes, from mobile devices to large monitors. In order to provide a great user experience, the core functionality (browsing files, creating issues, writing comments, etc.) must be available at all resolutions. However, due to size limitations, some secondary functionality may be hidden on smaller screens. Please keep this functionality limited to rare actions that aren't expected to be needed on small devices.
-
----
-
-## Typography
-### Primary typeface
-GitLab's main typeface used throughout the UI is **Source Sans Pro**. We support both the bold and regular weight.
-
-![Source Sans Pro sample](img/sourcesanspro-sample.png)
-
-
-### Monospace typeface
-This is the typeface used for code blocks and references to commits, branches, and tags (`.commit-sha` or `.ref-name`). GitLab uses the OS default font.
-- **Menlo** (Mac)
-- **Consolas** (Windows)
-- **Liberation Mono** (Linux)
-
-![Monospace font sample](img/monospacefont-sample.png)
-
----
-
-## Icons
-
-GitLab has a strong, unique personality. When you look at any screen, you should know immediately that it is GitLab.
-Iconography is a powerful visual cue to the user and is a great way for us to reflect our particular sense of style.
-
-- **Standard size:** 16px * 16px
-- **Border thickness:** 2px
-- **Border radius:** 3px
-
-![Icon sampler](img/icon-spec.png)
-
-> TODO: List all icons, proper usage, hover, and active states.
-
---
-
-## Color
-
-| | State | Action |
-| :------: | :------- | :------- |
-| ![Blue](img/color-blue.png) | Primary and active (such as the current tab) | Organizational, managing, and retry commands|
-| ![Green](img/color-green.png) | Opened | Create new objects |
-| ![Orange](img/color-orange.png) | Warning | Non destructive action |
-| ![Red](img/color-red.png) | Closed | Delete and other destructive commands |
-| ![Grey](img/color-grey.png) | Neutral | Neutral secondary commands |
-
-### Text colors
-
-|||
-| :---: | :--- |
-| ![Text primary](img/color-textprimary.png) | Used for primary body text, such as issue description and comment |
-| ![Text secondary](img/color-textsecondary.png) | Used for secondary body text, such as username and date |
-
-> TODO: Establish a perspective for color in terms of our personality and rationalize with Marketing usage.
-
+redirect_to: 'https://design.gitlab.com/'
---
-## Cursors
-The mouse cursor is key in helping users understand how to interact with elements on the screen.
-
-| | |
-| :------: | :------- |
-| ![Default cursor](img/cursors-default.png) | Default cursor |
-| ![Pointer cursor](img/cursors-pointer.png) | Pointer cursor: used to indicate that you can click on an element to invoke a command or navigate, such as links and buttons |
-| ![Move cursor](img/cursors-move.png) | Move cursor: used to indicate that you can move an element around on the screen |
-| ![Pan opened cursor](img/cursors-panopened.png) | Pan cursor (opened): indicates that you can grab and move the entire canvas, affecting what is seen in the view port. |
-| ![Pan closed cursor](img/cursors-panclosed.png) | Pan cursor (closed): indicates that you are actively panning the canvas. |
-| ![I-beam cursor](img/cursors-ibeam.png) | I-beam cursor: indicates that this is either text that you can select and copy, or a text field that you can click into to enter text. |
-
-
+The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/components.md b/doc/development/ux_guide/components.md
index 4a3b3125f59..1e84bf608f4 100644
--- a/doc/development/ux_guide/components.md
+++ b/doc/development/ux_guide/components.md
@@ -1,387 +1,5 @@
-# Components
-
-## Contents
-* [Tooltips](#tooltips)
-* [Anchor links](#anchor-links)
-* [Buttons](#buttons)
-* [Dropdowns](#dropdowns)
-* [Counts](#counts)
-* [Lists](#lists)
-* [Tables](#tables)
-* [Blocks](#blocks)
-* [Panels](#panels)
-* [Modals](#modals)
-* [Alerts](#alerts)
-* [Forms](#forms)
-* [Search box](#search-box)
-* [File holders](#file-holders)
-* [Data formats](#data-formats)
-
----
-
-## Tooltips
-Tooltips identify elements or provide additional, useful information about the referring elements. Tooltips are different from ALT-attributes, which are intended primarily for static images. Tooltips are summoned by:
-
-* Hovering over an element with a cursor
-* Focusing on an element with a keyboard (usually the tab key)
-* Upon touch
-
-### Usage
-A tooltip should be used:
-* When there isn’t enough space to show the information
-* When it isn’t critical for the user to see the information
-* For icons that don’t have a label
-
-Tooltips shouldn’t repeat information that is shown near the referring element. However, they can show the same data in a different format (e.g. date or timestamps).
-
-![Tooltip usage](img/tooltip-usage.png)
-
-### Placement
-By default, tooltips should be placed below the referring element. However, if there isn’t enough space in the viewport, the tooltip should be moved to the side as needed.
-
-![Tooltip placement location](img/tooltip-placement.png)
-
----
-
-## Popovers
-
-Popovers provide additional, useful, unique information about the referring elements and can provide one or multiple actionable elements. They inform the user of additional information within the context of their original view, but without forcing the user to act upon it like a modal. Popovers are different from tooltips, which do not provide rich markup and actionable items. A popover can contain a header section with a different background color.
-
-Popovers are summoned:
-
-* Upon hover or touch on an element
-
-### Usage
-A popover should be used:
-* When you don't want to let the user lose context, but still want to provide additional useful unique information about referring elements
-* When it isn’t critical for the user to act upon the information
-* When you want to give a user a summary of extended information and the option to switch context if they want to dive in deeper.
-
-### Styling
-
-A popover can contain a header section with a different background color if that improves readability and separation of content within.
-
-![Popover usage](img/popover-placement-below.png)
-
-This example shows two sections, where each section includes an actionable element. The first section shows a summary of the content shown when clicking the "read more" link. With this information the user can decide to dive deeper or start their GitLab Enterprise Edition trial immediately.
-
-### Placement
-By default, tooltips should be placed below the referring element. However, if there isn’t enough space in the viewport or it blocks related content, the tooltip should be moved to the side or above as needed.
-
-![Tooltip placement location](img/popover-placement-above.png)
-
-In this example we let the user know more about the setting they are deciding over, without loosing context. If they want to know even more they can do so, but with the expectation of opening that content in a new view.
-
----
-
-## Anchor links
-
-Anchor links are used for navigational actions and lone, secondary commands (such as 'Reset filters' on the Issues List) when deemed appropriate by the UX team.
-
-### States
-
-#### Rest
-
-Primary links are blue in their rest state. Secondary links (such as the time stamp on comments) are a neutral gray color in rest. Details on the main GitLab navigation links can be found on the [features](features.md#navigation) page.
-
-#### Hover
-
-On hover, an underline should be added and the color should change. Both the primary and secondary link should become the darker blue color on hover.
-
-#### Focus
-
-The focus state should match the hover state.
-
-![Anchor link states ](img/components-anchorlinks.png)
-
----
-
-## Buttons
-
-Buttons communicate the command that will occur when the user clicks on them.
-
-### Types
-
-#### Primary
-Primary buttons communicate the main call to action. There should only be one call to action in any given experience. Visually, primary buttons are conveyed with a full background fill
-
-![Primary button example](img/button-primary.png)
-
-#### Secondary
-Secondary buttons are for alternative commands. They should be conveyed by a button with a stroke, and no background fill.
-
-![Secondary button example](img/button-secondary.png)
-
-### Icon and text treatment
-Text should be in sentence case, where only the first word is capitalized. "Create issue" is correct, not "Create Issue". Buttons should only contain an icon or a text, not both.
-
-> TODO: Rationalize this. Ensure that we still believe this.
-
-### Colors
-The default color treatment is the white/grey button. Follow the guidance on the [basics](basics.md#color) page to add meaningful color to a button.
-
-### Secondary states
-
-Primary buttons darken the color of their background and border for hover, focus and active states. An inner shadow is added to the active state to denote the button being pressed.
-
-| Values | Info | Success | Warning | Danger |
-| :------ | :------: | :------: | :------: | :------: |
-| Background: `$color-light` <br> Border: `$border-color-light` | ![](img/button-info--resting.png) | ![](img/button-success--resting.png) | ![](img/button-warning--resting.png) | ![](img/button-danger--resting.png) |
-| Background: `$color-normal` <br> Border: `$border-color-normal` | ![](img/button-info--hover.png) | ![](img/button-success--hover.png) | ![](img/button-warning--hover.png) | ![](img/button-danger--hover.png) |
-| Background: `$color-dark` <br> Border: `$border-color-dark` | ![](img/button-info--active.png) | ![](img/button-success--active.png) | ![](img/button-warning--active.png) | ![](img/button-danger--active.png) |
-
-Since secondary buttons only have a border on their resting state, their hover and focus states add a background color, which gets darkened on active.
-
-| Values | Success Secondary | Close | Spam |
-| :------ | :------: | :------: | :------: |
-| Font: `$border-color-light` <br> Border: `$border-color-light` | ![](img/button-success-secondary--resting.png) | ![](img/button-close--resting.png) | ![](img/button-spam--resting.png) |
-| Background: `$color-light` <br> Border: `$border-color-light` | ![](img/button-success-secondary--hover.png) | ![](img/button-close--hover.png) | ![](img/button-spam--hover.png) |
-| Background: `$color-normal` <br> Border: `$border-color-normal` | ![](img/button-success-secondary--active.png) | ![](img/button-close--active.png) | ![](img/button-spam--active.png) |
-
-### Placement
-
-When there are a group of buttons in a dialog or a form, we need to be consistent with the placement.
-
-#### Dismissive actions on the left
-The dismissive action returns the user to the previous state.
-
-> Example: Cancel
-
-#### Affirmative actions on the right
-Affirmative actions continue to progress towards the user goal that triggered the dialog or form.
-
-> Example: Submit, Ok, Delete
-
----
-
-
-## Dropdowns
-
-Dropdowns are used to allow users to choose one (or many) options from a list of options. If this list of options is more 20, there should generally be a way to search through and filter the options (see the complex filter dropdowns below.)
-
-> TODO: Will update this section when the new filters UI is implemented.
-
-![Dropdown states](img/components-dropdown.png)
-
-### Max size
-
-The max height for dropdowns should target **10-15** single line items, or **7-10** multi-line items. If the height of the dropdown is too large, the list becomes very hard to parse and it is easy to visually lose track of the item you are looking for. Usability also suffers as more mouse movement is required, and you have a larger area in which you hijack the scroll away from the page level. While it may initially seem counterintuitive to not show as many items as you can, it is actually quicker and easier to process the information when it is cropped at a reasonable height.
-
----
-
-## Counts
-
-A count element is used in navigation contexts where it is helpful to indicate the count, or number of items, in a list. Always use the [`number_with_delimiter`][number_with_delimiter] helper to display counts in the UI.
-
-![Counts example](img/components-counts.png)
-
-[number_with_delimiter]: http://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html#method-i-number_with_delimiter
-
----
-
-## Lists
-
-Lists are used where ever there is a single column of information to display. Ths [issues list](https://gitlab.com/gitlab-org/gitlab-ce/issues) is an example of an important list in the GitLab UI.
-
-### Types
-
-Simple list using .content-list
-
-![Simple list](img/components-simplelist.png)
-
-List with avatar, title and description using .content-list
-
-![List with avatar](img/components-listwithavatar.png)
-
-List with hover effect .content-list
-
-![List with hover effect](img/components-listwithhover.png)
-
-List inside panel
-
-![List inside panel](img/components-listinsidepanel.png)
-
----
-
-## Tables
-
-When the information is too complex for a list, with multiple columns of information, a table can be used. For example, the [pipelines page](https://gitlab.com/gitlab-org/gitlab-ce/pipelines) uses a table.
-
-![Table](img/components-table.png)
-
----
-
-## Blocks
-
-Blocks are a way to group related information.
-
-### Types
-
-#### Content blocks
-
-Content blocks (`.content-block`) are the basic grouping of content. They are commonly used in [lists](#lists), and are separated by a button border.
-
-![Content block](img/components-contentblock.png)
-
-#### Row content blocks
-
-A background color can be added to this blocks. For example, items in the [issue list](https://gitlab.com/gitlab-org/gitlab-ce/issues) have a green background if they were created recently. Below is an example of a gray content block with side padding using `.row-content-block`.
-
-![Row content block](img/components-rowcontentblock.png)
-
-#### Cover blocks
-Cover blocks are generally used to create a heading element for a page, such as a new project, or a user profile page. Below is a cover block (`.cover-block`) for the profile page with an avatar, name and description.
-
-![Cover block](img/components-coverblock.png)
-
----
-
-## Skeleton loading
-
-Skeleton loading is a way to convey to the user what kind of content is currently being loaded. It's a paradigm with which content can independently and asynchronously be loaded, while still adhering to the structure and look of the completely loaded view.
-
-### Requirements
-
-* A skeleton should represent an organism in a recognisable way
-* Atom elements within organisms (for reference see this article on [atomic design methodology](http://atomicdesign.bradfrost.com/chapter-2/)) may be represented in a maximum of 3 repetitions, if applicable.
-* Skeletons should only be presented in grayscale using the HEX colors: `#fafafa` or `#ffffff` (except for shadows)
-* Animate the grey atoms in a pulsating way to show motion, as if "loading". The pulse animation transitions colors horizontally from left to right, starting with `#f2f2f2` to `#fafafa`.
-
-![Skeleton loading animation](img/skeleton-loading.gif)
-
-### Usage
-
-Skeleton loading can replace any existing UI elements for the period in which they are loaded and should aim for maintaining a similar structure visually.
-
----
-
-## Modals
-
-Modals are only used for having a conversation and confirmation with the user. The user is not able to access the features on the main page until closing the modal.
-
-### Usage
-
-* When the action is irreversible, modals provide the details and confirm with the user before they take an advanced action.
-* When the action will affect privacy or authorization, modals provide advanced information and confirm with the user.
-
-### Style
-
-* Modals contain the header, body, and actions.
- * **Header(1):** The header title is a question instead of a descriptive phrase.
- * **Body(2):** The content in body should never be ambiguous and unclear. It provides specific information.
- * **Actions(3):** Contains an affirmative action, a dismissive action, and an extra action. The order of actions from left to right: Dismissive action → Extra action → Affirmative action
-* Confirmations regarding labels should keep labeling styling.
-* References to commits, branches, and tags should be **monospaced**.
-
-![layout-modal](img/modals-layout-for-modals.png)
-
-### Placement
-
-* Modals should always be the center of the screen horizontally and be positioned **72px** from the top.
-
-| Modal with 2 actions | Modal with 3 actions | Special confirmation |
-| --------------------- | --------------------- | -------------------- |
-| ![two-actions](img/modals-general-confimation-dialog.png) | ![three-actions](img/modals-three-buttons.png) | ![special-confirmation](img/modals-special-confimation-dialog.png) |
-
-> TODO: Special case for modal.
-
----
-
-## Panels
-
-> TODO: Catalog how we are currently using panels and rationalize how they relate to alerts
-
-![Panels](img/components-panels.png)
-
----
-
-## Alerts
-
-> TODO: Catalog how we are currently using alerts
-
-![Alerts](img/components-alerts.png)
-
---
-
-## Forms
-
-There are two options shown below regarding the positioning of labels in forms. Both are options to consider based on context and available size. However, it is important to have a consistent treatment of labels in the same form.
-
-### Types
-
-#### Labels stack vertically
-
-Form (`form`) with label rendered above input.
-
-![Vertical form](img/components-verticalform.png)
-
-#### Labels side-by-side
-
-Horizontal form (`form.horizontal-form`) with label rendered inline with input.
-
-![Horizontal form](img/components-horizontalform.png)
-
+redirect_to: 'https://design.gitlab.com/'
---
-## Search box
-
-Search boxes across GitLab have a consistent rest, active and text entered state. When text isn't entered in the box, there should be a magnifying glass right aligned with the input field. When text is entered, the magnifying glass should become a x, allowing users to clear their text.
-
-![Search box](img/components-searchbox.png)
-
-If needed, we indicate the scope of the search in the search box.
-
-![Scoped Search box](img/components-searchboxscoped.png)
-
----
-
-## File holders
-A file holder (`.file-holder`) is used to show the contents of a file inline on a page of GitLab.
-
-![File Holder component](img/components-fileholder.png)
-
----
-
-## Data formats
-
-### Dates
-
-#### Exact
-
-Format for exacts dates should be ‘Mon DD, YYYY’, such as the examples below.
-
-![Exact date](img/components-dateexact.png)
-
-#### Relative
-
-This format relates how long since an action has occurred. The exact date can be shown as a tooltip on hover.
-
-![Relative date](img/components-daterelative.png)
-
-### References
-
-Referencing GitLab items depends on a symbol for each type of item. Typing that symbol will invoke a dropdown that allows you to search for and autocomplete the item you were looking for. References are shown as [links](#links) in context, and hovering on them shows the full title or name of the item.
-
-![Hovering on a reference](img/components-referencehover.png)
-
-#### `%` Milestones
-
-![Milestone reference](img/components-referencemilestone.png)
-
-#### `#` Issues
-
-![Issue reference](img/components-referenceissues.png)
-
-#### `!` Merge Requests
-
-![Merge request reference](img/components-referencemrs.png)
-
-#### `~` Labels
-
-![Labels reference](img/components-referencelabels.png)
-
-#### `@` People
-
-![People reference](img/components-referencepeople.png)
-
-> TODO: Open issue: Some commit references use monospace fonts, but others don't. Need to standardize this.
+The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/copy.md b/doc/development/ux_guide/copy.md
index d5afa544372..1e84bf608f4 100644
--- a/doc/development/ux_guide/copy.md
+++ b/doc/development/ux_guide/copy.md
@@ -1,198 +1,5 @@
-# Copy
-
-The copy for GitLab is clear and direct. We strike a clear balance between professional and friendly. We can empathesize with users (such as celebrating completing all Todos), and remain respectful of the importance of the work. We are that trusted, friendly coworker that is helpful and understanding.
-
-The copy and messaging is a core part of the experience of GitLab and the conversation with our users. Follow the below conventions throughout GitLab.
-
-Portions of this page are inspired by work found in the [Material Design guidelines][material design].
-
->**Note:**
-We are currently inconsistent with this guidance. Images below are created to illustrate the point. As this guidance is refined, we will ensure that our experiences align.
-
-## Contents
-* [Brevity](#brevity)
-* [Capitalization and punctuation](#capitalization-and-punctuation)
-* [Terminology](#terminology)
-
----
-
-## Brevity
-Users will skim content, rather than read text carefully.
-When familiar with a web app, users rely on muscle memory, and may read even less when moving quickly.
-A good experience should quickly orient a user, regardless of their experience, to the purpose of the current screen. This should happen without the user having to consciously read long strings of text.
-In general, text is burdensome and adds cognitive load. This is especially pronounced in a powerful productivity tool such as GitLab.
-We should _not_ rely on words as a crutch to explain the purpose of a screen.
-The current navigation and composition of the elements on the screen should get the user 95% there, with the remaining 5% being specific elements such as text.
-This means that, as a rule, copy should be very short. A long message or label is a red flag hinting at design that needs improvement.
-
->**Example:**
-Use `Add` instead of `Add issue` as a button label.
-Preferably use context and placement of controls to make it obvious what clicking on them will do.
-
----
-
-## Capitalization and punctuation
-
-### Case
-Use sentence case for titles, headings, labels, menu items, and buttons. Use title case when referring to [features][features] or [products][products]. Note that some features are also objects (e.g. “Merge Requests†and “merge requestsâ€).
-
-| :white_check_mark: Do | :no_entry_sign: Don’t |
-| --- | --- |
-| Add issues to the Issue Board feature in GitLab Hosted | Add Issues To The Issue Board Feature In GitLab Hosted |
-
-### Avoid periods
-Avoid using periods in solitary sentences in these elements:
-
-* Labels
-* Hover text
-* Bulleted lists
-* Modal body text
-
-Periods should be used for:
-
-* Lists or modals with multiple sentences
-* Any sentence followed by a link
-
-| :white_check_mark: **Do** place periods after sentences followed by a link | :no_entry_sign: **Don’t** place periods after a link if it‘s not followed by a sentence |
-| --- | --- |
-| Mention someone to notify them. [Learn more](#) | Mention someone to notify them. [Learn more](#). |
-
-| :white_check_mark: **Do** skip periods after solo sentences of body text | :no_entry_sign: **Don’t** place periods after body text if there is only a single sentence |
-| --- | --- |
-| To see the available commands, enter `/gitlab help` | To see the available commands, enter `/gitlab help`. |
-
-### Use contractions
-Don’t make a sentence harder to understand just to follow this rule. For example, “do not†can give more emphasis than “don’t†when needed.
-
-| :white_check_mark: Do | :no_entry_sign: Don’t |
-| --- | --- |
-| it’s, can’t, wouldn’t, you’re, you’ve, haven’t, don’t | it is, cannot, would not, it’ll, should’ve |
-
-### Use numerals for numbers
-Use “1, 2, 3†instead of “one, two, three†for numbers. One exception is when mixing uses of numbers, such as “Enter two 3s.â€
-
-| :white_check_mark: Do | :no_entry_sign: Don’t |
-| --- | --- |
-| 3 new commits | Three new commits |
-
-### Punctuation
-Omit punctuation after phrases and labels to create a cleaner and more readable interface. Use punctuation to add clarity or be grammatically correct.
-
-| Punctuation mark | Copy and paste | HTML entity | Unicode | Mac shortcut | Windows shortcut | Description |
-|---|---|---|---|---|---|---|
-| Period | **.** | | | | | Omit for single sentences in affordances like labels, hover text, bulleted lists, and modal body text.<br><br>Use in lists or modals with multiple sentences, and any sentence followed by a link or inline code.<br><br>Place inside quotation marks unless you’re telling the reader what to enter and it’s ambiguous whether to include the period. |
-| Comma | **,** | | | | | Place inside quotation marks.<br><br>Use a [serial comma][serial comma] in lists of three or more terms. |
-| Exclamation point | **!** | | | | | Avoid exclamation points as they tend to come across as shouting. Some exceptions include greetings or congratulatory messages. |
-| Colon | **:** | `&#58;` | `\u003A` | | | Omit from labels, for example, in the labels for fields in a form. |
-| Apostrophe | **’** | `&rsquo;` | `\u2019` | <kbd>⌥ Option</kbd>+<kbd>⇧ Shift</kbd>+<kbd>]</kbd> | <kbd>Alt</kbd>+<kbd>0 1 4 6</kbd> | Use for contractions (I’m, you’re, ’89) and to show possession.<br><br>To show possession, add an *’s* to all singular common nouns and names, even if they already end in an *s*: “Look into this worker process’s log.†For singular proper names ending in *s*, use only an apostrophe: “James’ commits.†For plurals of a single letter, add an *’s*: “Dot your i’s and cross your t’s.â€<br><br>Omit for decades or acronyms: “the 1990sâ€, “MRs.†|
-| Quotation marks | **“**<br><br>**â€**<br><br>**‘**<br><br>**’** | `&ldquo;`<br><br>`&rdquo;`<br><br>`&lsquo;`<br><br>`&rsquo;` | `\u201C`<br><br>`\u201D`<br><br>`\u2018`<br><br>`\u2019` | <kbd>⌥ Option</kbd>+<kbd>[</kbd><br><br><kbd>⌥ Option</kbd>+<kbd>⇧ Shift</kbd>+<kbd>[</kbd><br><br><kbd>⌥ Option</kbd>+<kbd>]</kbd><br><br><kbd>⌥ Option</kbd>+<kbd>⇧ Shift</kbd>+<kbd>]</kbd> | <kbd>Alt</kbd>+<kbd>0 1 4 7</kbd><br><br><kbd>Alt</kbd>+<kbd>0 1 4 8</kbd><br><br><kbd>Alt</kbd>+<kbd>0 1 4 5</kbd><br><br><kbd>Alt</kbd>+<kbd>0 1 4 6</kbd> | Use proper quotation marks (also known as smart quotes, curly quotes, or typographer’s quotes) for quotes. Single quotation marks are used for quotes inside of quotes.<br><br>The right single quotation mark symbol is also used for apostrophes.<br><br>Don’t use primes, straight quotes, or free-standing accents for quotation marks. |
-| Primes | **′**<br><br>**″** | `&prime;`<br><br>`&Prime;` | `\u2032`<br><br>`\u2033` | | <kbd>Alt</kbd>+<kbd>8 2 4 2</kbd><br><br><kbd>Alt</kbd>+<kbd>8 2 4 3</kbd> | Use prime (′) only in abbreviations for feet, arcminutes, and minutes: 3° 15′<br><br>Use double-prime (″) only in abbreviations for inches, arcseconds, and seconds: 3° 15′ 35″<br><br>Don’t use quotation marks, straight quotes, or free-standing accents for primes. |
-| Straight quotes and accents | **"**<br><br>**'**<br><br>**`**<br><br>**´** | `&quot;`<br><br>`&#39;`<br><br>`&#96;`<br><br>`&acute;` | `\u0022`<br><br>`\u0027`<br><br>`\u0060`<br><br>`\u00B4` | | | Don’t use straight quotes or free-standing accents for primes or quotation marks.<br><br>Proper typography never uses straight quotes. They are left over from the age of typewriters and their only modern use is for code. |
-| Ellipsis | **…** | `&hellip;` | | <kbd>⌥ Option</kbd>+<kbd>;</kbd> | <kbd>Alt</kbd>+<kbd>0 1 3 3</kbd> | Use to indicate an action in progress (“Downloading…â€) or incomplete or truncated text. No space before the ellipsis.<br><br>Omit from menu items or buttons that open a modal or start some other process. |
-| Chevrons | **«**<br><br>**»**<br><br>**‹**<br><br>**›**<br><br>**<**<br><br>**>** | `&#171;`<br><br>`&#187;`<br><br>`&#8249;`<br><br>`&#8250;`<br><br>`&lt;`<br><br>`&gt;` | `\u00AB`<br><br>`\u00BB`<br><br>`\u2039`<br><br>`\u203A`<br><br>`\u003C`<br><br>`\u003E`<br><br> | | | Omit from links or buttons that open another page or move to the next or previous step in a process. Also known as angle brackets, angular quote brackets, or guillemets. |
-| Em dash | **—** | `&mdash;` | `\u2014` | <kbd>⌥ Option</kbd>+<kbd>⇧ Shift</kbd>+<kbd>-</kbd> | <kbd>Alt</kbd>+<kbd>0 1 5 1</kbd> | Avoid using dashes to separate text. If you must use dashes for this purpose — like this — use an em dash surrounded by spaces. |
-| En dash | **–** | `&ndash;` | `\u2013` | <kbd>⌥ Option</kbd>+<kbd>-</kbd> | <kbd>Alt</kbd>+<kbd>0 1 5 0</kbd> | Use an en dash without spaces instead of a hyphen to indicate a range of values, such as numbers, times, and dates: “3–5 kgâ€, “8:00 AM–12:30 PMâ€, “10–17 Jan†|
-| Hyphen | **-** | | | | | Use to represent negative numbers, or to avoid ambiguity in adjective-noun or noun-participle pairs. Example: “anti-inflammatoryâ€; “5-mile walk.â€<br><br>Omit in commonly understood terms and adverbs that end in *ly*: “frontendâ€, “greatly improved performance.â€<br><br>Omit in the term “open source.†|
-| Parentheses | **( )** | | | | | Use only to define acronyms or jargon: “Secure web connections are based on a technology called SSL (the secure sockets layer).â€<br><br>Avoid other uses and instead rewrite the text, or use dashes or commas to set off the information. If parentheses are required: If the parenthetical is a complete, independent sentence, place the period inside the parentheses; if not, the period goes outside. |
-
-When using the <kbd>Alt</kbd> keystrokes in Windows, use the numeric keypad, not the row of numbers above the alphabet, and be sure Num Lock is turned on.
-
----
-
-## Terminology
-Only use the terms below.
-
-When using verbs or adjectives:
-* If the context clearly refers to the object, use them alone. Example: `Edit` or `Closed`
-* If the context isn’t clear enough, use them with the object. Example: `Edit issue` or `Closed issues`
-
-### Search
-
-| Term | Use |
-| ---- | --- |
-| Search | When using all metadata to add criteria that match/don't match. Search can also affect ordering, by ranking best results. |
-| Filter | When taking a single criteria that removes items within a list that match/don't match. Filters do not affect ordering. |
-| Sort | Orders a list based on a single or grouped criteria |
-
-### Projects and Groups
-
-| Term | Use | :no_entry_sign: Don't |
-| ---- | --- | ----- |
-| Members | When discussing the people who are a part of a project or a group. | Don't use `users`. |
-
-### Issues
-
-#### Adjectives (states)
-
-| Term | :no_entry_sign: Don’t |
-| ---- | --- |
-| Open | Don’t use `Pending` or `Created` |
-| Closed | Don’t use `Archived` |
-| Deleted | Don’t use `Removed` or `Trashed` |
-
-#### Verbs (actions)
-
-| Term | Use | :no_entry_sign: Don’t |
-| ---- | --- | --- |
-| New | Although it’s not a verb, `New` is a common standard and used for entering the creation mode of a non-existent issue | Don’t use `Create`, `Open`, or `Add` |
-| Create | Only to indicate when or who created an issue ||
-| Add | Associate an existing issue with an item or a list of items | Don’t use `New` or `Create` |
-| View | Open the detail page of an issue | Don’t use `Open` or `See` |
-| Edit | Enter the editing mode of an issue | Don’t use `Change`, `Modify` or `Update` |
-| Submit | Finalize the *creation* process of an issue | Don’t use `Add`, `Create`, `New`, `Open`, `Save` or `Save changes` |
-| Save | Finalize the *editing* process of an issue | Don’t use `Edit`, `Modify`, `Update`, `Submit`, or `Save changes` |
-| Cancel | Cancel the *creation* or *editing* process of an issue | Don’t use `Back`, `Close`, or `Discard` |
-| Close | Close an open issue | Don’t use `Archive` |
-| Re-open | Re-open a closed issue | Don’t use `Open` |
-| Delete | Permanently remove an issue from the system | Don’t use `Remove` |
-| Remove | Remove the association an issue with an item or a list of items | Don’t use `Delete` |
-
-### Merge requests
-
-#### Adjectives (states)
-
-| Term |
-| ---- |
-| Open |
-| Merged |
-
-#### Verbs (actions)
-
-| Term | Use | :no_entry_sign: Don’t |
-| ---- | --- | --- |
-| Add | Add a merge request | Do not use `create` or `new` |
-| View | View an open or merged merge request ||
-| Edit | Edit an open or merged merge request| Do not use `update` |
-| Approve | Approve an open merge request ||
-| Remove approval, unapproved | Remove approval of an open merge request | Do not use `unapprove` as that is not an English word|
-| Merge | Merge an open merge request ||
-
-### Comments & Discussions
-
-#### Comment
-A **comment** is a written piece of text that users of GitLab can create. Comments have the meta data of author and timestamp. Comments can be added in a variety of contexts, such as issues, merge requests, and discussions.
-
-#### Discussion
-A **discussion** is a group of 1 or more comments. A discussion can include subdiscussions. Some discussions have the special capability of being able to be **resolved**. Both the comments in the discussion and the discussion itself can be resolved.
-
-## Modals
-
-- Destruction buttons should be clear and always say what they are destroying.
- E.g., `Delete page` instead of just `Delete`.
-- If the copy describes another action the user can take instead of the
- destructive one, provide a way for them to do that as a secondary button.
-- Avoid the word `cancel` or `canceled` in the descriptive copy. It can be
- confusing when you then see the `Cancel` button.
-
-see also: guidelines for [modal components](components.md#modals)
-
----
-
-Portions of this page are modifications based on work created and shared by the [Android Open Source Project][android project] and used according to terms described in the [Creative Commons 2.5 Attribution License][creative commons].
-
-[material design]: https://material.io/guidelines/
-[features]: https://about.gitlab.com/features/ "GitLab features page"
-[products]: https://about.gitlab.com/pricing/ "GitLab products page"
-[serial comma]: https://en.wikipedia.org/wiki/Serial_comma "“Serial comma†in Wikipedia"
-[android project]: http://source.android.com/
-[creative commons]: http://creativecommons.org/licenses/by/2.5/
+---
+redirect_to: 'https://design.gitlab.com/'
+---
+
+The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/features.md b/doc/development/ux_guide/features.md
index 9472995c68c..1e84bf608f4 100644
--- a/doc/development/ux_guide/features.md
+++ b/doc/development/ux_guide/features.md
@@ -1,57 +1,5 @@
-# Features
-
-## Contents
-* [Navigation](#navigation)
-* [Filtering](#filtering)
-* [Search results](#search-results)
-* [Conversations](#conversations)
-* [Empty states](#empty-states)
-
---
-
-## Navigation
-
-### Global navigation
-
-The global navigation is accessible via the menu button on the top left of the screen, and can be pinned to keep it open. It contains a consistent list of pages that allow you to view content that is across GitLab. For example, you can view your todos, issues and merge requests across projects and groups.
-
-![Global nav](img/features-globalnav.png)
-
-
-### Contextual navigation
-
-The navigation in the header is contextual to each page. These options change depending on if you are looking at a project, group, or settings page. There should be no more than 10 items on a level in the contextual navigation, allowing it to comfortably fit on a typical laptop screen. There can be up to too levels of navigation. Each sub nav group should be a self-contained group of functionality. For example, everything related to the issue tracker should be under the 'Issue' tab, while everything relating to the wiki will be grouped under the 'Wiki' tab. The names used for each section should be short and easy to remember, ideally 1-2 words in length.
-
-![Contextual nav](img/features-contextualnav.png)
-
-### Information architecture
-
-The [GitLab Product Map](https://gitlab.com/gitlab-org/gitlab-design/raw/master/production/resources/gitlab-map.png) shows a visual representation of the information architecture for GitLab.
-
+redirect_to: 'https://design.gitlab.com/'
---
-## Filtering
-
-Today, lists are filtered by a series of dropdowns. Some of these dropdowns allow multiselect (labels), while others allow you to filter to one option (milestones). However, we are currently implementing a [new model](https://gitlab.com/gitlab-org/gitlab-ce/issues/21747) for this, and will update the guide when it is ready.
-
-![Filters](img/features-filters.png)
-
----
-
-## Search results
-
-### Global search
-
-[Global search](https://gitlab.com/search?group_id=&project_id=13083&repository_ref=&scope=issues&search=mobile) allows you to search across items in a project, or even across multiple projects. You can switch tabs to filter on type of object, or filter by group.
-
-### List search
-
-There are several core lists in the GitLab experience, such as the Issue list and the Merge Request list. You are also able to [filter and search these lists](https://gitlab.com/gitlab-org/gitlab-ce/issues?utf8=%E2%9C%93&search=mobile). This UI will be updated with the [new filtering model](https://gitlab.com/gitlab-org/gitlab-ce/issues/21747).
-
----
-
-## Empty states
-
-Empty states need to be considered in the design of features. They are vital to helping onboard new users, making the experience feel more approachable and understandable. Empty states should feel inviting and provide just enough information to get people started. There should be a single call to action and a clear explanation of what to use the feature for.
-
-![Empty states](img/features-emptystates.png)
+The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/illustrations.md b/doc/development/ux_guide/illustrations.md
index 7e16c300921..ed072b6515f 100644
--- a/doc/development/ux_guide/illustrations.md
+++ b/doc/development/ux_guide/illustrations.md
@@ -1,86 +1,5 @@
-# Illustrations
-
-The illustrations should always align with topics and goals in specific context.
-
-## Principles
-
-#### Be simple.
-- For clarity, we use simple and specific elements to create our illustrations.
-
-#### Be optimistic.
-- We are an open-minded, optimistic, and friendly team. We should reflect those values in our illustrations to connect with our brand experience.
-
-#### Be gentle.
-- Our illustrations assist users in understanding context and guide users in the right direction. Illustrations are supportive, so they should be obvious but not aggressive.
-
-
-## Style
-
-#### Shapes
-- All illustrations are geometric rather than organic.
-- The illustrations are made by circles, rectangles, squares, and triangles.
-
-<img src="img/illustrations-geometric.png" width=224px alt="Example for geometric" />
-
-#### Stroke
-- Standard border thickness: **4px**
-- Depending on the situation, border thickness can be changed to **3px**. For example, when the illustration size is small, an illustration with 4px border thickness would look tight. In this case, the border thickness can be changed to 3px.
-- We use **rounded caps** and **rounded corner**.
-
-| Do | Don't |
-| -------- | -------- |
-| <img src="img/illustrations-caps-do.png" width= 133px alt="Do: caps and corner" /> | <img src="img/illustrations-caps-don't.png" width= 133px alt="Don't: caps and corner"/> |
-
-#### Radius
-- Standard corner radius: **10px**
-- Depending on the situation, corner radius can be changed to **5px**. For example, when the illustration size is small, an illustration with 10px corner radius would be over-rounded. In this case, the corner radius can be changed to 5px.
-
-<img src="img/illustrations-border-radius.png" width= 464px alt="Example for border radius"/>
-
-#### Size
-Depends on the situation, the illustration size can be the 3 types below:
-
-**Large**
-* Use case: Empty states, error pages(e.g. 404, 403)
-* For vertical layout, the illustration should not larger than **430*300 px**.
-* For horizontal layout, the illustration should not larger than **430*380 px**.
-
-| Vertical layout | Horizontal layout |
-| --------------- | ----------------- |
-| <img src="img/illustration-size-large-vertical.png" /> | <img src="img/illustration-size-large-horizontal.png" />
-
-**Medium**
-* Use case: Banner
-* The illustration should not larger than **240*160 px**
-* The illustration should keep simple and clear. We recommend not including too many elements in the medium size illustration.
-
-<img src="img/illustration-size-medium.png" width=983px />
-
-**Small**
-* Use case: Graphics for explanatory text, graphics for status.
-* The illustration should not larger than **160*90 px**.
-* The illustration should keep simple and clear. We recommend not including too many elements in the small size illustration.
-
-<img src="img/illustration-size-small.png" width=983px />
-
-**Illustration on mobile**
-- Keep the proportions in original ratio.
-
-#### Colors palette
-
-For consistency, we recommend choosing colors from our color palette.
-
-| Orange | Purple | Grey |
-| -------- | -------- | -------- |
-| <img src="img/illustrations-color-orange.png" width= 160px alt="Orange" /> | <img src="img/illustrations-color-purple.png" width= 160px alt="Purple" /> | <img src="img/illustrations-color-grey.png" width= 160px alt="Grey" /> |
-| #FC6D26 | #6B4FBB | #EEEEEE |
-
-#### Don't
-- Don't include the typography in the illustration.
-- Don't include tanuki in the illustration. If necessary, we recommend having tanuki monochromatic.
-
+---
+redirect_to: 'https://design.gitlab.com/foundations/illustration/'
---
-| Orange | Purple |
-| -------- | -------- |
-| <img src="img/illustrations-palette-oragne.png" width= 160px alt="Palette - Orange" /> | <img src="img/illustrations-palette-purple.png" width= 160px alt="Palette - Purple" /> |
+The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/index.md b/doc/development/ux_guide/index.md
index c59e7b72a1a..1e84bf608f4 100644
--- a/doc/development/ux_guide/index.md
+++ b/doc/development/ux_guide/index.md
@@ -1,70 +1,5 @@
-> We are in the process of transferring UX documentation to the [design.gitlab.com](https://gitlab.com/gitlab-org/design.gitlab.com) project. Any updates to these docs should be made in that project. If documentation does not yet exist within [design.gitlab.com](https://gitlab.com/gitlab-org/design.gitlab.com), [create an issue](https://gitlab.com/gitlab-org/design.gitlab.com/issues) and merge request to add your new changes.
-
-# GitLab UX Guide
-
-The goal of this guide is to provide standards, principles and in-depth information to design beautiful and effective GitLab features. This will be a living document, and we welcome contributions, feedback and suggestions.
-
-## Design
-
----
-
-### [Principles](principles.md)
-These guiding principles set a solid foundation for our design system, and should remain relatively stable over multiple releases. They should be referenced as new design patterns are created.
-
----
-
-### [Basics](basics.md)
-The basic ingredients of our experience establish our personality and feel. This section includes details about typography, iconography, and color.
-
---
-
-### [Animation](animation.md)
-Guidance on the timing, curving and motion for GitLab.
-
----
-
-### [Illustrations](illustrations.md)
-Guidelines for principals and styles related to illustrations for GitLab.
-
----
-
-### [Copy](copy.md)
-Conventions on text and messaging within labels, buttons, and other components.
-
----
-
-### [Components](components.md)
-Components are the controls that make up the GitLab experience, including guidance around buttons, links, dropdowns, etc.
-
----
-
-### [Surfaces](surfaces.md)
-The GitLab experience is broken apart into several surfaces. Each of these surfaces is designated for a specific scope or type of content. Examples include the header, global menu, side pane, etc.
-
----
-
-### [Features](features.md)
-The previous building blocks are combined into complete features in the GitLab UX. Examples include our navigation, filters, search results, and empty states.
-
----
-
-## Research
-
----
-
-### [Users](users.md)
-How we think about the variety of users of GitLab, from small to large teams, comparing opensource usage to enterprise, etc.
-
----
-
-## Other
-
----
-
-### [Tips for designers](tips.md)
-Tips for exporting assets, and other guidance.
-
+redirect_to: 'https://design.gitlab.com/'
---
-### [Resources](resources.md)
-Resources for GitLab UX
+The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/principles.md b/doc/development/ux_guide/principles.md
index 1a297cba2cc..1e84bf608f4 100644
--- a/doc/development/ux_guide/principles.md
+++ b/doc/development/ux_guide/principles.md
@@ -1,17 +1,5 @@
-# Principles
+---
+redirect_to: 'https://design.gitlab.com/'
+---
-These are the guiding principles that we should strive for to establish a solid foundation for the GitLab experience.
-
-## Professional and productive
-GitLab is a tool to support what people do, day in, day out. We need to respect the importance of their work, and avoid gimicky details.
-
-## Minimal and efficient
-While work can get complicated, GitLab is about bringing a sharp focus, helping our customers know what matters now.
-
-## Immediately recognizable
-When you look at any screen, you should know immediately that it is GitLab. Our personality is strong and consistent across product and marketing experiences.
-
-## Human and quirky
-We need to build empathy with our users, understanding their state of mind, and connect with them at a human level. Quirkiness is part of our DNA, and we should embrace it in the right moments and contexts.
-
-> TODO: Ensure these principles align well with the goals of the Marketing team
+The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/resources.md b/doc/development/ux_guide/resources.md
index db57258237f..baec235a8dd 100644
--- a/doc/development/ux_guide/resources.md
+++ b/doc/development/ux_guide/resources.md
@@ -1,17 +1,5 @@
-# Resources
+---
+redirect_to: 'https://design.gitlab.com/resources/design-resources'
+---
-## GitLab UI development kit
-
-We created a page inside GitLab where you can check commonly used html and css elements.
-
-When you run GitLab instance locally - just visit http://localhost:3000/help/ui page to see UI examples
-you can use during GitLab development.
-
-## Design repository
-
-All design files are stored in the [gitlab-design](https://gitlab.com/gitlab-org/gitlab-design)
-repository and maintained by GitLab UX designers.
-
-## [brand.ai](https://brand.ai/git-lab/primary-brand)
-
-We are in the process of capturing our UI paradigms on brand.ai, see https://brand.ai/git-lab/primary-brand
+The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/surfaces.md b/doc/development/ux_guide/surfaces.md
index 881d6aa4cd6..1e84bf608f4 100644
--- a/doc/development/ux_guide/surfaces.md
+++ b/doc/development/ux_guide/surfaces.md
@@ -1,47 +1,5 @@
-# Surfaces
-
-## Contents
-* [Header](#header)
-* [Global menu](#global-menu)
-* [Side pane](#side-pane)
-* [Content area](#content-area)
-
----
-
-![Surfaces UX](img/surfaces-ux.png)
-
-## Global menu
-
-This menu is to navigate to pages that contain content global to GitLab.
-
----
-
-## Header
-
-The header contains 3 main elements: Project switching and searching, user account avatar and settings, and a contextual menu that changes based on the current page.
-
-![Surfaces Header](img/surfaces-header.png)
-
---
-
-## Side pane
-
-The side pane holds supporting information and meta data for the information in the content area.
-
+redirect_to: 'https://design.gitlab.com/'
---
-## Content area
-
-The main content of the page. The content area can include other surfaces.
-
-### Item title bar
-
-The item title bar contains the top level information to identify the item, such as the name, id and status.
-
-![Item title](img/surfaces-contentitemtitle.png)
-
-### Item system information
-
-The system information block contains relevant system controlled information.
-
-![Item system information](img/surfaces-systeminformationblock.png)
+The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/tips.md b/doc/development/ux_guide/tips.md
index 8348de4f8a2..1e84bf608f4 100644
--- a/doc/development/ux_guide/tips.md
+++ b/doc/development/ux_guide/tips.md
@@ -1,44 +1,5 @@
-# Tips
-
-## Contents
-* [SVGs](#svgs)
-
+---
+redirect_to: 'https://design.gitlab.com/'
---
-## SVGs
-
-When exporting SVGs, be sure to follow the following guidelines:
-
-1. Convert all strokes to outlines.
-2. Use pathfinder tools to combine overlapping paths and create compound paths.
-3. SVGs that are limited to one color should be exported without a fill color so the color can be set using CSS.
-4. Ensure that exported SVGs have been run through an [SVG cleaner](https://github.com/RazrFalcon/SVGCleaner) to remove unused elements and attributes.
-
-You can open your svg in a text editor to ensure that it is clean.
-Incorrect files will look like this:
-
-```xml
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<svg width="16px" height="17px" viewBox="0 0 16 17" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
- <!-- Generator: Sketch 3.7.2 (28276) - http://www.bohemiancoding.com/sketch -->
- <title>Group</title>
- <desc>Created with Sketch.</desc>
- <defs></defs>
- <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
- <g id="Group" fill="#7E7C7C">
- <path d="M15.1111,1 L0.8891,1 C0.3981,1 0.0001,1.446 0.0001,1.996 L0.0001,15.945 C0.0001,16.495 0.3981,16.941 0.8891,16.941 L15.1111,16.941 C15.6021,16.941 16.0001,16.495 16.0001,15.945 L16.0001,1.996 C16.0001,1.446 15.6021,1 15.1111,1 L15.1111,1 L15.1111,1 Z M14.0001,6.0002 L14.0001,14.949 L2.0001,14.949 L2.0001,6.0002 L14.0001,6.0002 Z M14.0001,4.0002 L14.0001,2.993 L2.0001,2.993 L2.0001,4.0002 L14.0001,4.0002 Z" id="Combined-Shape"></path>
- <polygon id="Fill-11" points="3 2.0002 5 2.0002 5 0.0002 3 0.0002"></polygon>
- <polygon id="Fill-16" points="11 2.0002 13 2.0002 13 0.0002 11 0.0002"></polygon>
- <path d="M5.37709616,11.5511984 L6.92309616,12.7821984 C7.35112915,13.123019 7.97359761,13.0565604 8.32002627,12.6330535 L10.7740263,9.63305349 C11.1237073,9.20557058 11.0606364,8.57555475 10.6331535,8.22587373 C10.2056706,7.87619272 9.57565475,7.93926361 9.22597373,8.36674651 L6.77197373,11.3667465 L8.16890384,11.2176016 L6.62290384,9.98660159 C6.19085236,9.6425813 5.56172188,9.71394467 5.21770159,10.1459962 C4.8736813,10.5780476 4.94504467,11.2071781 5.37709616,11.5511984 L5.37709616,11.5511984 Z" id="Stroke-21"></path>
- </g>
- </g>
-</svg>
-```
-
-Correct file will look like this:
-
-```xml
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 17" enable-background="new 0 0 16 17"><path d="m15.1 1h-2.1v-1h-2v1h-6v-1h-2v1h-2.1c-.5 0-.9.5-.9 1v14c0 .6.4 1 .9 1h14.2c.5 0 .9-.4.9-1v-14c0-.5-.4-1-.9-1m-1.1 14h-12v-9h12v9m0-11h-12v-1h12v1"/><path d="m5.4 11.6l1.5 1.2c.4.3 1.1.3 1.4-.1l2.5-3c.3-.4.3-1.1-.1-1.4-.5-.4-1.1-.3-1.5.1l-1.8 2.2-.8-.6c-.4-.3-1.1-.3-1.4.2-.3.4-.3 1 .2 1.4"/></svg>
-```
-
-> TODO: Checkout [https://github.com/svg/svgo](https://github.com/svg/svgo)
+The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/ux_guide/users.md b/doc/development/ux_guide/users.md
index 6afb33cfc36..11bac11257c 100644
--- a/doc/development/ux_guide/users.md
+++ b/doc/development/ux_guide/users.md
@@ -1,310 +1,5 @@
-# UX Personas
-
-* [Nazim Ramesh](#nazim-ramesh)
- - Small to medium size organizations using GitLab CE
-* [Matthieu Poirier](#matthieu-poirier)
- - Responsible for managing and maintaining GitLab installation
- - Any size organization
- - Using CE or EE
-* [James Mackey](#james-mackey)
- - Medium to large size organizations using CE or EE
- - Small organizations using EE
-* [Karolina Plaskaty](#karolina-plaskaty)
- - Using GitLab.com for personal/hobby projects
- - Would like to use GitLab at work
- - Working within a medium to large size organization
-
----
-
-## Nazim Ramesh
-- Small to medium size organizations using GitLab CE
-
-![nazim-ramesh](img/nazim-ramesh.png)
-
-### Demographics
-
-**Age**
-
-32 years old
-
-**Location**
-
-Germany
-
-**Education**
-
-Bachelor of Science in Computer Science
-
-**Occupation**
-
-Full-stack web developer
-
-**Programming experience**
-
-Over 10 years
-
-**Frequently used programming languages**
-
-JavaScript, SQL, PHP
-
-**Hobbies / interests**
-
-Functional programming, open source, gaming, web development, and web security.
-
-### Motivations
-Nazim works for a software development company which currently hires around 80 people. When Nazim first joined the company, the engineering team were using Subversion (SVN) as their primary form of source control. However, Nazim felt SVN was not flexible enough to work with many feature branches and noticed that developers with less experience of source control struggled with the central-repository nature of SVN. Armed with a wish list of features, Nazim began comparing source control tools. A search for "self-hosted Git server repository management" returned GitLab. In his own words, Nazim explains why he wanted the engineering team to start using GitLab:
-
->"I wanted them to switch away from SVN. I needed a server application to manage repositories. The common tools that were around just didn't meet the requirements. Most of them were too simple or plain...GitLab provided all the required features. Also, costs had to be low since we don't have a big budget for those things...the Community Edition was perfect in this regard."
-
-In his role as a full-stack web developer, Nazim could recommend products that he would like the engineering team to use, but final approval lay with his line manager, Mike, VP of Engineering. Nazim recalls that he was met with reluctance from his colleagues when he raised moving to Git and using GitLab.
-
->"The biggest challenge...why should we change anything at all from the status quo? We needed to switch from SVN to Git. They knew they needed to learn Git and a Git workflow...using Git was scary to my colleagues...they thought it was more complex than SVN to use."
-
-Undeterred, Nazim decided to migrate a couple of projects across to GitLab.
-
->"Old SVN users couldn't see the benefits of Git at first. It took a month or two to convince them."
-
-Slowly, by showing his colleagues how easy it was to use Git, the majority of the team's projects were migrated to GitLab.
-
-The engineering team have been using GitLab CE for around 2 years now. Nazim credits himself as being entirely responsible for his company's decision to move to GitLab.
-
-### Frustrations
-#### Adoption to GitLab has been slow
-Not only has the engineering team had to get to grips with Git, they've also had to adapt to using GitLab. Due to lack of training and existing skills in other tools, the full feature set of GitLab CE is not being utilized. Nazim sold GitLab to his manager as an ‘all in one' tool which would replace multiple tools used within the company, thus saving costs. Nazim hasn't had the time to integrate the legacy tools to GitLab and he's struggling to convince his peers to change their habits.
-
-#### Missing Features
-Nazim's company want GitLab to be able to do everything. There isn't a large budget for software, so they're selective about what tools are implemented. It needs to add real value to the company. In order for GitLab to be widely adopted and to meet the requirements of different roles within the company, it needs a host of features. When an individual within Nazim's company wants to know if GitLab has a specific feature or does a particular thing, Nazim is the person to ask. He becomes the point of contact to investigate, build or sometimes just raise the feature request. Nazim gets frustrated when GitLab isn't able to do what he or his colleagues need it to do.
-
-#### Regressions and bugs
-Nazim often has to calm down his colleagues, when a release contains regressions or new bugs. As he puts it "every new version adds something awesome, but breaks something". He feels that "old issues for minor annoyances get quickly buried in the mass of open issues and linger for a very long time. More generally, I have the feeling that GitLab focus on adding new functionalities, but overlook a bunch of annoying minor regressions or introduced bugs." Due to limited resource and expertise within the team, not only is it difficult to remain up-to-date with the frequent release cycle, it's also counterproductive to fix workflows every month.
-
-#### Uses too much RAM and CPU
->"Memory usages mean that if we host it from a cloud-based host like AWS, we spend almost as much on the instance as what we would pay GitHub"
-
-
-#### UI/UX
-GitLab's interface initially attracted Nazim when he was comparing version control software. He thought it would help his less technical colleagues to adapt to using Git and perhaps, GitLab could be rolled out to other areas of the business, beyond engineering. However, using GitLab's interface daily has left him frustrated at the lack of personalization/control over his user experience. He's also regularly lost in a maze of navigation. Whilst he acknowledges that GitLab listens to its users and that the interface is improving, he becomes annoyed when the changes are too progressive. "Too frequent UI changes. Most of them tend to turn out great after a few cycles of fixes, but the frequency is still far too high for me to feel comfortable to always stay on the current release."
-
-### Goals
-* To convince his colleagues to fully adopt GitLab CE, thus improving workflow and collaboration.
-* To use a feature-rich version control platform that covers all stages of the development lifecycle, in order to reduce dependencies on other tools.
-* To use an intuitive and stable product, so he can spend more time on his core job responsibilities and less time bug-fixing, guiding colleagues, etc.
-
----
-## Matthieu Poirier
-- Responsible for managing and maintaining GitLab installation
-- Any size organization
-- Using CE or EE
-
-![matthieu-poirier](img/matthieu-poirier.png)
-
-### Demographics
-
-**Age**
-
-42 years old
-
-**Location**
-
-France
-
-**Education**
-
-Masters Degree in Computer Science
-
-**Occupation**
-
-DevOps Engineer
-
-**Programming experience**
-
-Over 10 years
-
-**Frequently used programming languages**
-
-JavaScript, SQL, PHP and Node.js
-
-**Hobbies / interests**
-
-Functional programming, data analysis, building apps, and tools.
-
-### Motivations
-Matthieu works in DevOps for a web services company which currently hires 90 staff. When Matthieu first joined the company, he was responsible for managing a custom built in-house bug tracking tool and release management system. Over time, as the company grew, his colleagues requested more features and tools to help them in their day-to-day work. To meet their needs, Matthieu was forced to "hack together" a solution. In his own words, Matthieu explains that it became:
-
->"...a huge pain managing access to all the individual pieces. In addition, they didn't have any integration with each other, nobody ended up using them and we couldn't do any workflows with merge requests and the like. I was sick of managing all those separate parts and wanted to move to a single platform that would handle it all."
-
-
-He further explains that he wanted to introduce "better, easier, more formal code reviews" and to start using continuous integration and deployment.
-
-Matthieu tried to find a platform which would consolidate the company's existing toolset, and centralize code, documentation, and issues. He discovered GitHub, but the price was an issue:
-
->"We needed to host our code on-site and wanted GitHub Enterprise functionality without the GitHub Enterprise costs."
-
-
-Not only was GitLab cheaper than GitHub, it was also more cost-effective than maintaining multiple tools. Subsequently, Matthieu found it easy to sell the merits of GitLab to his manager.
-
-Matthieu describes GitLab as:
-
->"the only tool that offers the real feeling of having everything you need in one place."
-
-
-He credits himself as being entirely responsible for moving his company to GitLab.
-
-### Frustrations
-#### Updating to the latest release
-Matthieu introduced his company to GitLab. He is responsible for maintaining and managing the company's installation in addition to his day job. He feels updates are too frequent and he doesn't always have sufficient time to update GitLab. As a result, he's not up to date with releases.
-
-Matthieu tried to set up automatic updates, however, as he isn't a Systems Administrator, he wasn't confident in his set-up. He feels he should be able to "upgrade without users even noticing" but hasn't figured out how to do this yet. Matthieu would like the "update process to be triggered from the Admin Panel, perhaps accompanied with a changelog and the option to skip updates."
-
-Matthieu is looking for confirmation that his update procedure is "secure and efficient" so more tutorials related to this topic would be useful to him.
-
-#### Configuration
-Matthieu dislikes using the combination of gitlab.rb and the UI for changing settings. He explains that it "would be nice to be able to configure more from the Admin UI rather than just the config files."
-
-#### Creating a backup
-Matthieu explains that the "backup solution is not well integrated into the UI", for example, he "cannot see if backups succeeded" or whether they have been rolled back to via the UI.
-
-#### Onboarding
-It's Matthieu's responsibility to get teams across his organization up and running with GitLab. He explains that whilst many teams might be leveraging GitLab, they are:
-
->"..not aware of GitLab's powerful CI or our omnibus install of Mattermost...It would be nice to have a tutorial type walkthrough available when a new user logs in on how to get started with all these features. AutoDevOps may solve some of this, but GitLab has many powerful features wrapped up into it and some [teams] may just think that it is only a Git repo similar to GitHub."
-
-
-He states that there has been: "a sluggishness of others to adapt" and it's "a low-effort adaptation at that."
-
-### Goals
-* To save time. One of the reasons Matthieu moved his company to GitLab was to reduce the effort it took him to manage and configure multiple tools, thus saving him time. He has to balance his day job in addition to managing the company's GitLab installation and onboarding new teams to GitLab.
-* To use a platform which is easy to manage. Matthieu isn't a Systems Administrator, and when updating GitLab, creating backups, etc. He would prefer to work within GitLab's UI. Explanations / guided instructions when configuring settings in GitLab's interface would really help Matthieu. He needs reassurance that what he is about to change is
-
-1. the right setting
-2. will provide him with the desired result he wants.
-
-* Matthieu needs to educate his colleagues about GitLab. Matthieu's colleagues won't adopt GitLab as they're unaware of its capabilities and the positive impact it could have on their work. Matthieu needs support in getting this message across to them.
-
---
-
-## James Mackey
-- Medium to large size organizations using CE or EE
-- Small organizations using EE
-
-![james-mackey.png](img/james-mackey.png)
-
-### Demographics
-
-**Age**
-
-36 years old
-
-**Location**
-
-US
-
-**Education**
-
-Masters degree in Computer Science
-
-**Occupation**
-
-Full-stack web developer
-
-**Programming experience**
-
-Over 10 years
-
-**Frequently used programming languages**
-
-JavaScript, SQL, Node.js, Java, PHP, Python
-
-**Hobbies / interests**
-
-DevOps, open source, web development, science, automation, and electronics.
-
-### Motivations
-James works for a research company which currently hires around 800 staff. He began using GitLab.com back in 2013 for his own open source, hobby projects and loved "the simplicity of installation, administration and use". After using GitLab for over a year, he began to wonder about using it at work. James explains:
-
->"We first installed the CE edition...on a staging server for a PoC and asked a beta team to use it, specifically for the Merge Request features. Soon other teams began asking us to be beta users too because the team that was already using GitLab was really enjoying it."
-
-
-James and his colleagues also reviewed competitor products including GitHub Enterprise, but they found it "less innovative and with considerable costs...GitLab had the features we wanted at a much lower cost per head than GitHub".
-
-The company James works for provides employees with a discretionary budget to spend how they want on software, so James and his team decided to upgrade to EE.
-
-James feels partially responsible for his organization's decision to start using GitLab.
-
->"It's still up to the teams themselves [to decide] which tools to use. We just had a great experience moving our daily development to GitLab, so other teams have followed the path or are thinking about switching."
-
-
-### Frustrations
-#### Third Party Integration
-Some of GitLab EE's features are too basic, in particular, issues boards which do not have the level of reporting that James and his team need. Subsequently, they still need to use GitLab EE in conjunction with other tools, such as JIRA. Whilst James feels it isn't essential for GitLab to meet all his needs (his company are happy for him to use, and pay for, multiple tools), he sometimes isn't sure what is/isn't possible with plugins and what level of custom development he and his team will need to do.
-
-#### UX/UI
-James and his team use CI quite heavily for several projects. Whilst they've welcomed improvements to the builds and pipelines interface, they still have some difficulty following build process on the different tabs under Pipelines. Some confusion has arisen from not knowing where to find different pieces of information or how to get to the next stages logs from the current stage's log output screen. They feel more intuitive linking and flow may alleviate the problem. Generally, they feel GitLab's navigation needs to reviewed and optimized.
-
-#### Permissions
->"There is no granular control over user or group permissions. The permissions for a project are too tightly coupled to the permissions for Gitlab CI/build pipelines."
-
-
-### Goals
-* To be able to integrate third-party tools easily with GitLab EE and to create custom integrations and patches where needed.
-* To use GitLab EE primarily for code hosting, merge requests, continuous integration and issue management. James and his team want to be able to understand and use these particular features easily.
-* To able to share one instance of GitLab EE with multiple teams across the business. Advanced user management, the ability to separate permissions on different parts of the source code, etc are important to James.
-
+redirect_to: 'https://design.gitlab.com/getting-started/personas/'
---
-## Karolina Plaskaty
-- Using GitLab.com for personal/hobby projects
-- Would like to use GitLab at work
-- Working within a medium to large size organization
-
-![karolina-plaskaty.png](img/karolina-plaskaty.png)
-
-### Demographics
-
-**Age**
-
-26 years old
-
-**Location**
-
-UK
-
-**Education**
-
-Self taught
-
-**Occupation**
-
-Junior web-developer
-
-**Programming experience**
-
-6 years
-
-**Frequently used programming languages**
-
-JavaScript and SQL
-
-**Hobbies / interests**
-
-Web development, mobile development, UX, open source, gaming, and travel.
-
-### Motivations
-Karolina has been using GitLab.com for around a year. She roughly spends 8 hours every week programming, of that, 2 hours is spent contributing to open source projects. Karolina contributes to open source projects to gain programming experience and to give back to the community. She likes GitLab.com for its free private repositories and range of features which provide her with everything she needs for her personal projects. Karolina is also a massive fan of GitLab's values and the fact that it isn't a "behemoth of a company". She explains that "displaying every single thing (doc, culture, assumptions, development...) in the open gives me greater confidence to choose Gitlab personally and to recommend it at work." She's also an avid reader of GitLab's blog.
-
-Karolina works for a software development company which currently hires around 500 people. Karolina would love to use GitLab at work but the company has used GitHub Enterprise for a number of years. She describes management at her company as "old fashioned" and explains that it's "less of a technical issue and more of a cultural issue" to convince upper management to move to GitLab. Karolina is also relatively new to the company so she's apprehensive about pushing too hard to change version control platforms.
-
-### Frustrations
-#### Unable to use GitLab at work
-Karolina wants to use GitLab at work but isn't sure how to approach the subject with management. In her current role, she doesn't feel that she has the authority to request GitLab.
-
-#### Performance
-GitLab.com is frequently slow and unavailable. Karolina has also heard that GitLab is a "memory hog" which has deterred her from running GitLab on her own machine for just hobby / personal projects.
-
-#### UX/UI
-Karolina has an interest in UX and therefore has strong opinions about how GitLab should look and feel. She feels the interface is cluttered, "it has too many links/buttons" and the navigation "feels a bit weird sometimes. I get lost if I don't pay attention." As Karolina also enjoys contributing to open-source projects, it's important to her that GitLab is well designed for public repositories, she doesn't feel that GitLab currently achieves this.
-
-### Goals
-* To develop her programming experience and to learn from other developers.
-* To contribute to both her own and other open source projects.
-* To use a fast and intuitive version control platform. \ No newline at end of file
+The content of this document was moved into the [GitLab Design System](https://design.gitlab.com/).
diff --git a/doc/development/what_requires_downtime.md b/doc/development/what_requires_downtime.md
index b668c9de6a0..3630a28fae9 100644
--- a/doc/development/what_requires_downtime.md
+++ b/doc/development/what_requires_downtime.md
@@ -300,7 +300,7 @@ The same applies to `rename_column_using_background_migration`:
1. Create a migration using the helper, which will schedule background
migrations to spread the writes over a longer period of time.
-2. In the next monthly release, create a clean-up migration to steal from the
+1. In the next monthly release, create a clean-up migration to steal from the
Sidekiq queues, migrate any missing rows, and cleanup the rename. This
migration should skip the steps after stealing from the Sidekiq queues if the
column has already been renamed.
diff --git a/doc/gitlab-basics/add-image.md b/doc/gitlab-basics/add-image.md
index 1a44123aa81..17c210c43e0 100644
--- a/doc/gitlab-basics/add-image.md
+++ b/doc/gitlab-basics/add-image.md
@@ -5,7 +5,7 @@ in Windows, or...), put the image file into the GitLab project. You can find the
project as a regular folder in your files.
Go to your [shell](command-line-commands.md), and move into the folder of your
-Gitlab project. This usually means running the following command until you get
+GitLab project. This usually means running the following command until you get
to the desired destination:
```
diff --git a/doc/gitlab-basics/create-your-ssh-keys.md b/doc/gitlab-basics/create-your-ssh-keys.md
index b6ebe374de3..881629c3bfd 100644
--- a/doc/gitlab-basics/create-your-ssh-keys.md
+++ b/doc/gitlab-basics/create-your-ssh-keys.md
@@ -12,7 +12,7 @@
![SSH Keys](img/profile_settings_ssh_keys.png)
-3. Paste your **public** key that you generated in the first step in the 'Key'
+1. Paste your **public** key that you generated in the first step in the 'Key'
box.
![Paste SSH public key](img/profile_settings_ssh_keys_paste_pub.png)
diff --git a/doc/img/devops-stages.png b/doc/img/devops-stages.png
new file mode 100644
index 00000000000..a971e81a419
--- /dev/null
+++ b/doc/img/devops-stages.png
Binary files differ
diff --git a/doc/img/devops_lifecycle.png b/doc/img/devops_lifecycle.png
deleted file mode 100644
index 0b15e9619a5..00000000000
--- a/doc/img/devops_lifecycle.png
+++ /dev/null
Binary files differ
diff --git a/doc/install/README.md b/doc/install/README.md
index 27df03c6ac6..92116305775 100644
--- a/doc/install/README.md
+++ b/doc/install/README.md
@@ -34,11 +34,11 @@ the hardware requirements.
- [Install GitLab on Google Cloud Platform](google_cloud_platform/index.md)
- [Install GitLab on Google Kubernetes Engine (GKE)](https://about.gitlab.com/2017/01/23/video-tutorial-idea-to-production-on-google-container-engine-gke/): video tutorial on
the full process of installing GitLab on Google Kubernetes Engine (GKE), pushing an application to GitLab, building the app with GitLab CI/CD, and deploying to production.
-- [Install on AWS](https://about.gitlab.com/aws/)
-- _Testing only!_ [DigitalOcean and Docker Machine](digitaloceandocker.md) -
- Quickly test any version of GitLab on DigitalOcean using Docker Machine.
+- [Install on AWS](aws/index.md): Install GitLab on AWS using the community AMIs that GitLab provides.
- [Getting started with GitLab and DigitalOcean](https://about.gitlab.com/2016/04/27/getting-started-with-gitlab-and-digitalocean/): requirements, installation process, updates.
- [Demo: Cloud Native Development with GitLab](https://about.gitlab.com/2017/04/18/cloud-native-demo/): video demonstration on how to install GitLab on Kubernetes, build a project, create Review Apps, store Docker images in Container Registry, deploy to production on Kubernetes, and monitor with Prometheus.
+- _Testing only!_ [DigitalOcean and Docker Machine](digitaloceandocker.md) -
+ Quickly test any version of GitLab on DigitalOcean using Docker Machine.
## Database
diff --git a/doc/install/aws/img/add_tags.png b/doc/install/aws/img/add_tags.png
new file mode 100644
index 00000000000..3572cd5daa1
--- /dev/null
+++ b/doc/install/aws/img/add_tags.png
Binary files differ
diff --git a/doc/install/aws/img/associate_subnet_gateway.png b/doc/install/aws/img/associate_subnet_gateway.png
new file mode 100644
index 00000000000..1edca974fca
--- /dev/null
+++ b/doc/install/aws/img/associate_subnet_gateway.png
Binary files differ
diff --git a/doc/install/aws/img/associate_subnet_gateway_2.png b/doc/install/aws/img/associate_subnet_gateway_2.png
new file mode 100644
index 00000000000..76e101d32a3
--- /dev/null
+++ b/doc/install/aws/img/associate_subnet_gateway_2.png
Binary files differ
diff --git a/doc/install/aws/img/aws_diagram.png b/doc/install/aws/img/aws_diagram.png
new file mode 100644
index 00000000000..bcd5c69bbeb
--- /dev/null
+++ b/doc/install/aws/img/aws_diagram.png
Binary files differ
diff --git a/doc/install/aws/img/choose_ami.png b/doc/install/aws/img/choose_ami.png
new file mode 100644
index 00000000000..034ac92691d
--- /dev/null
+++ b/doc/install/aws/img/choose_ami.png
Binary files differ
diff --git a/doc/install/aws/img/create_gateway.png b/doc/install/aws/img/create_gateway.png
new file mode 100644
index 00000000000..9408520e050
--- /dev/null
+++ b/doc/install/aws/img/create_gateway.png
Binary files differ
diff --git a/doc/install/aws/img/create_route_table.png b/doc/install/aws/img/create_route_table.png
new file mode 100644
index 00000000000..ea72c57257e
--- /dev/null
+++ b/doc/install/aws/img/create_route_table.png
Binary files differ
diff --git a/doc/install/aws/img/create_security_group.png b/doc/install/aws/img/create_security_group.png
new file mode 100644
index 00000000000..9a0dfccfe37
--- /dev/null
+++ b/doc/install/aws/img/create_security_group.png
Binary files differ
diff --git a/doc/install/aws/img/create_subnet.png b/doc/install/aws/img/create_subnet.png
new file mode 100644
index 00000000000..26f5ab1b625
--- /dev/null
+++ b/doc/install/aws/img/create_subnet.png
Binary files differ
diff --git a/doc/install/aws/img/create_vpc.png b/doc/install/aws/img/create_vpc.png
new file mode 100644
index 00000000000..a678f7013fd
--- /dev/null
+++ b/doc/install/aws/img/create_vpc.png
Binary files differ
diff --git a/doc/install/aws/img/ec_az.png b/doc/install/aws/img/ec_az.png
new file mode 100644
index 00000000000..22a8291c593
--- /dev/null
+++ b/doc/install/aws/img/ec_az.png
Binary files differ
diff --git a/doc/install/aws/img/ec_subnet.png b/doc/install/aws/img/ec_subnet.png
new file mode 100644
index 00000000000..c44fb4485e3
--- /dev/null
+++ b/doc/install/aws/img/ec_subnet.png
Binary files differ
diff --git a/doc/install/aws/img/policies.png b/doc/install/aws/img/policies.png
new file mode 100644
index 00000000000..e99497a52a2
--- /dev/null
+++ b/doc/install/aws/img/policies.png
Binary files differ
diff --git a/doc/install/aws/img/rds_subnet_group.png b/doc/install/aws/img/rds_subnet_group.png
new file mode 100644
index 00000000000..7c6157e38e0
--- /dev/null
+++ b/doc/install/aws/img/rds_subnet_group.png
Binary files differ
diff --git a/doc/install/aws/index.md b/doc/install/aws/index.md
new file mode 100644
index 00000000000..ce61ace60a0
--- /dev/null
+++ b/doc/install/aws/index.md
@@ -0,0 +1,655 @@
+# Installing GitLab on Amazon Web Services (AWS)
+
+To install GitLab on AWS, you can use the Amazon Machine Images (AMIs) that GitLab
+provides with [each release](https://about.gitlab.com/releases/).
+
+This page offers a walkthrough of a common HA (Highly Available) configuration
+for GitLab on AWS. You should customize it to accommodate your needs.
+
+## Introduction
+
+GitLab on AWS can leverage many of the services that are already
+configurable with GitLab High Availability (HA). These services offer a great deal of
+flexibility and can be adapted to the needs of most companies, while enabling the
+automation of both vertical and horizontal scaling.
+
+In this guide, we'll go through a basic HA setup where we'll start by
+configuring our Virtual Private Cloud and subnets to later integrate
+services such as RDS for our database server and ElastiCache as a Redis
+cluster to finally manage them within an auto scaling group with custom
+scaling policies.
+
+## Requirements
+
+In addition to having a basic familiarity with [AWS](https://docs.aws.amazon.com/) and [Amazon EC2](https://docs.aws.amazon.com/ec2/), you will need:
+
+- [An AWS account](https://console.aws.amazon.com/console/home)
+- [To create or upload an SSH key](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html)
+ to connect to the instance via SSH
+- A domain name for the GitLab instance
+
+## Architecture
+
+Below is a diagram of the recommended architecture.
+
+![AWS architecture diagram](img/aws_diagram.png)
+
+## AWS costs
+
+Here's a list of the AWS services we will use, with links to pricing information:
+
+- **EC2**: GitLab will deployed on shared hardware which means
+ [on-demand pricing](https://aws.amazon.com/ec2/pricing/on-demand)
+ will apply. If you want to run it on a dedicated or reserved instance,
+ consult the [EC2 pricing page](https://aws.amazon.com/ec2/pricing/) for more
+ information on the cost.
+- **EBS**: We will also use an EBS volume to store the Git data. See the
+ [Amazon EBS pricing](https://aws.amazon.com/ebs/pricing/).
+- **S3**: We will use S3 to store backups, artifacts, LFS objects, etc. See the
+ [Amazon S3 pricing](https://aws.amazon.com/s3/pricing/).
+- **ALB**: An Application Load Balancer will be used to route requests to the
+ GitLab instance. See the [Amazon ELB pricing](https://aws.amazon.com/elasticloadbalancing/pricing/).
+- **RDS**: An Amazon Relational Database Service using PostgreSQL will be used
+ to provide a High Availability database configuration. See the
+ [Amazon RDS pricing](https://aws.amazon.com/rds/postgresql/pricing/).
+- **ElastiCache**: An in-memory cache environment will be used to provide a
+ High Availability Redis configuration. See the
+ [Amazon ElastiCache pricing](https://aws.amazon.com/elasticache/pricing/).
+
+## Creating an IAM EC2 instance role and profile
+To minimize the permissions of the user, we'll create a new [IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html)
+role with limited access:
+
+1. Navigate to the IAM dashboard https://console.aws.amazon.com/iam/home and
+ click **Create role**.
+1. Create a new role by selecting **AWS service > EC2**, then click
+ **Next: Permissions**.
+1. Choose **AmazonEC2FullAccess** and **AmazonS3FullAccess**, then click **Next: Review**.
+1. Give the role the name `GitLabAdmin` and click **Create role**.
+
+## Configuring the network
+
+We'll start by creating a VPC for our GitLab cloud infrastructure, then
+we can create subnets to have public and private instances in at least
+two [Availability Zones (AZs)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html). Public subnets will require a Route Table keep and an associated
+Internet Gateway.
+
+### Creating the Virtual Private Cloud (VPC)
+
+We'll now create a VPC, a virtual networking environment that you'll control:
+
+1. Navigate to https://console.aws.amazon.com/vpc/home.
+1. Select **Your VPCs** from the left menu and then click **Create VPC**.
+ At the "Name tag" enter `gitlab-vpc` and at the "IPv4 CIDR block" enter
+ `10.0.0.0/16`. If you don't require dedicated hardware, you can leave
+ "Tenancy" as default. Click **Yes, Create** when ready.
+
+ ![Create VPC](img/create_vpc.png)
+
+### Subnets
+
+Now, let's create some subnets in different Availability Zones. Make sure
+that each subnet is associated to the VPC we just created and
+that CIDR blocks don't overlap. This will also
+allow us to enable multi AZ for redundancy.
+
+We will create private and public subnets to match load balancers and
+RDS instances as well:
+
+1. Select **Subnets** from the left menu.
+1. Click **Create subnet**. Give it a descriptive name tag based on the IP,
+ for example `gitlab-public-10.0.0.0`, select the VPC we created previously,
+ and at the IPv4 CIDR block let's give it a 24 subnet `10.0.0.0/24`:
+
+ ![Create subnet](img/create_subnet.png)
+
+1. Follow the same steps to create all subnets:
+
+ | Name tag | Type |Availability Zone | CIDR block |
+ | -------- | ---- | ---------------- | ---------- |
+ | gitlab-public-10.0.0.0 | public | us-west-2a | 10.0.0.0 |
+ | gitlab-private-10.0.1.0 | private | us-west-2a | 10.0.1.0 |
+ | gitlab-public-10.0.2.0 | public | us-west-2b | 10.0.2.0 |
+ | gitlab-private-10.0.3.0 | private | us-west-2b | 10.0.3.0 |
+
+### Route Table
+
+Up to now all our subnets are private. We need to create a Route Table
+to associate an Internet Gateway. On the same VPC dashboard:
+
+1. Select **Route Tables** from the left menu.
+1. Click **Create Route Table**.
+1. At the "Name tag" enter `gitlab-public` and choose `gitlab-vpc` under "VPC".
+1. Hit **Yes, Create**.
+
+### Internet Gateway
+
+Now, still on the same dashboard, go to Internet Gateways and
+create a new one:
+
+1. Select **Internet Gateways** from the left menu.
+1. Click **Create internet gateway**, give it the name `gitlab-gateway` and
+ click **Create**.
+1. Select it from the table, and then under the **Actions** dropdown choose
+ "Attach to VPC".
+
+ ![Create gateway](img/create_gateway.png)
+
+1. Choose `gitlab-vpc` from the list and hit **Attach**.
+
+### Configuring subnets
+
+We now need to add a new target which will be our Internet Gateway and have
+it receive traffic from any destination.
+
+1. Select **Route Tables** from the left menu and select the `gitlab-public`
+ route to show the options at the bottom.
+1. Select the **Routes** tab, hit **Edit > Add another route** and set `0.0.0.0/0`
+ as destination. In the target, select the `gitlab-gateway` we created previously.
+ Hit **Save** once done.
+
+ ![Associate subnet with gateway](img/associate_subnet_gateway.png)
+
+Next, we must associate the **public** subnets to the route table:
+
+1. Select the **Subnet Associations** tab and hit **Edit**.
+1. Check only the public subnet and hit **Save**.
+
+ ![Associate subnet with gateway](img/associate_subnet_gateway_2.png)
+
+---
+
+Now that we're done with the network, let's create a security group.
+
+## Creating a security group
+
+The security group is basically the firewall:
+
+1. Select **Security Groups** from the left menu.
+1. Click **Create Security Group** and fill in the details. Give it a name,
+ add a description, and choose the VPC we created previously
+1. Select the security group from the list and at the bottom select the
+ Inbound Rules tab. You will need to open the SSH, HTTP, and HTTPS ports. Set
+ the source to `0.0.0.0/0`.
+
+ ![Create security group](img/create_security_group.png)
+
+ TIP: **Tip:**
+ Based on best practices, you should allow SSH traffic from only a known
+ host or CIDR block. In that case, change the SSH source to be custom and give
+ it the IP you want to SSH from.
+
+1. When done, click **Save**.
+
+## PostgreSQL with RDS
+
+For our database server we will use Amazon RDS which offers Multi AZ
+for redundancy. Let's start by creating a subnet group and then we'll
+create the actual RDS instance.
+
+### RDS Subnet Group
+
+1. Navigate to the RDS dashboard and select **Subnet Groups** from the left menu.
+1. Give it a name (`gitlab-rds-group`), a description, and choose the VPC from
+ the VPC dropdown.
+1. Click "Add all the subnets related to this VPC" and
+ remove the public ones, we only want the **private subnets**.
+ In the end, you should see `10.0.1.0/24` and `10.0.3.0/24` (as
+ we defined them in the [subnets section](#subnets)).
+ Click **Create** when ready.
+
+ ![RDS Subnet Group](img/rds_subnet_group.png)
+
+### Creating the database
+
+Now, it's time to create the database:
+
+1. Select **Instances** from the left menu and click **Create database**.
+1. Select PostgreSQL and click **Next**.
+1. Since this is a production server, let's choose "Production". Click **Next**.
+1. Let's see the instance specifications:
+ 1. Leave the license model as is (`postgresql-license`).
+ 1. For the version, select the latest of the 9.6 series (check the
+ [database requirements](../../install/requirements.md#postgresql-requirements))
+ if there are any updates on this).
+ 1. For the size, let's select a `t2.medium` instance.
+ 1. Multi-AZ-deployment is recommended as redundancy, so choose "Create
+ replica in different zone". Read more at
+ [High Availability (Multi-AZ)](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.MultiAZ.html).
+ 1. A Provisioned IOPS (SSD) storage type is best suited for HA (though you can
+ choose a General Purpose (SSD) to reduce the costs). Read more about it at
+ [Storage for Amazon RDS](http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Storage.html).
+
+1. The rest of the settings on this page request a DB isntance identifier, username
+ and a master password. We've chosen to use `gitlab-db-ha`, `gitlab` and a
+ very secure password respectively. Keep these in hand for later.
+1. Click **Next** to proceed to the advanced settings.
+1. Make sure to choose our gitlab VPC, our subnet group, set public accessibility to
+ **No**, and to leave it to create a new security group. The only additional
+ change which will be helpful is the database name for which we can use
+ `gitlabhq_production`. At the very bottom, there's an option to enable
+ auto updates to minor versions. You may want to turn it off.
+1. When done, click **Create database**.
+
+### Installing the `pg_trgm` extension for PostgreSQL
+
+Once the database is created, connect to your new RDS instance to verify access
+and to install a required extension.
+
+You can find the host or endpoint by selecting the instance you just created and
+after the details drop down you'll find it labeled as 'Endpoint'. Do not to
+include the colon and port number:
+
+```sh
+sudo /opt/gitlab/embedded/bin/psql -U gitlab -h <rds-endpoint> -d gitlabhq_production
+```
+
+At the psql prompt create the extension and then quit the session:
+
+```sh
+psql (9.4.7)
+Type "help" for help.
+
+gitlab=# CREATE EXTENSION pg_trgm;
+gitlab=# \q
+```
+
+---
+
+Now that the database is created, let's move on setting up Redis with ElasticCache.
+
+## Redis with ElastiCache
+
+ElastiCache is an in-memory hosted caching solution. Redis maintains its own
+persistence and is used for certain types of the GitLab application.
+
+To set up Redis:
+
+1. Navigate to the ElastiCache dashboard from your AWS console.
+1. Go to **Subnet Groups** in the left menu, and create a new subnet group.
+ Make sure to select our VPC and its [private subnets](#subnets). Click
+ **Create** when ready.
+
+ ![ElastiCache subnet](img/ec_subnet.png)
+
+1. Select **Redis** on the left menu and click **Create** to create a new
+ Redis cluster. Depending on your load, you can choose whether to enable
+ cluster mode or not. Even without cluster mode on, you still get the
+ chance to deploy Redis in multi availability zones. In this guide, we chose
+ not to enable it.
+1. In the settings section:
+ 1. Give the cluster a name (`gitlab-redis`) and a description.
+ 1. For the version, select the latest of `3.2` series (e.g., `3.2.10`).
+ 1. Select the node type and the number of replicas.
+1. In the advanced settings section:
+ 1. Select the multi-AZ auto-failover option.
+ 1. Select the subnet group we created previously.
+ 1. Manually select the preferred availability zones, and under "Replica 2"
+ choose a different zone than the other two.
+
+ ![Redis availability zones](img/ec_az.png)
+
+1. In the security settings, edit the security groups and choose the
+ `gitlab-security-group` we had previously created.
+1. Leave the rest of the settings to their default values or edit to your liking.
+1. When done, click **Create**.
+
+## RDS and Redis Security Group
+
+Let's navigate to our EC2 security groups and add a small change for our EC2
+instances to be able to connect to RDS. First, copy the security group name we
+defined, namely `gitlab-security-group`, select the RDS security group and edit the
+inbound rules. Choose the rule type to be PostgreSQL and paste the name under
+source.
+
+Similar to the above, jump to the `gitlab-security-group` group
+and add a custom TCP rule for port `6379` accessible within itself.
+
+## Load Balancer
+
+On the EC2 dashboard, look for Load Balancer on the left column:
+
+1. Click the **Create Load Balancer** button.
+ 1. Choose the Application Load Balancer.
+ 1. Give it a name (`gitlab-loadbalancer`) and set the scheme to "internet-facing".
+ 1. In the "Listeners" section, make sure it has HTTP and HTTPS.
+ 1. In the "Availability Zones" section, select the `gitlab-vpc` we have created
+ and associate the **public subnets**.
+1. Click **Configure Security Settings** to go to the next section to
+ select the TLS certificate. When done, go to the next step.
+1. In the "Security Groups" section, create a new one by giving it a name
+ (`gitlab-loadbalancer-sec-group`) and allow both HTTP ad HTTPS traffic
+ from anywhere (`0.0.0.0/0, ::/0`).
+1. In the next step, configure the routing and select an existing target group
+ (`gitlab-public`). The Load Balancer Health will allow us to indicate where to
+ ping and what makes up a healthy or unhealthy instance.
+1. Leave the "Register Targets" section as is, and finally review the settings
+ and create the ELB.
+
+After the Load Balancer is up and running, you can revisit your Security
+Groups to refine the access only through the ELB and any other requirement
+you might have.
+
+## Deploying GitLab inside an auto scaling group
+
+We'll use AWS's wizard to deploy GitLab and then SSH into the instance to
+configure the PostgreSQL and Redis connections.
+
+The Auto Scaling Group option is available through the EC2 dashboard on the left
+sidebar.
+
+1. Click **Create Auto Scaling group**.
+1. Create a new launch configuration.
+
+### Choose the AMI
+
+Choose the AMI:
+
+1. Go to the Community AMIs and search for `GitLab EE <version>`
+ where `<version>` the latest version as seen on the
+ [releases page](https://about.gitlab.com/releases/).
+
+ ![Choose AMI](img/choose_ami.png)
+
+### Choose an instance type
+
+You should choose an instance type based on your workload. Consult
+[the hardware requirements](../requirements.md#hardware-requirements) to choose
+one that fits your needs (at least `c4.xlarge`, which is enough to accommodate 100 users):
+
+1. Choose the your instance type.
+1. Click **Next: Configure Instance Details**.
+
+### Configure details
+
+In this step we'll configure some details:
+
+1. Enter a name (`gitlab-autoscaling`).
+1. Select the IAM role we created.
+1. Optionally, enable CloudWatch and the EBS-optimized instance settings.
+1. In the "Advanced Details" section, set the IP address type to
+ "Do not assign a public IP address to any instances."
+1. Click **Next: Add Storage**.
+
+### Add storage
+
+The root volume is 8GB by default and should be enough given that we won't store
+any data there. Let's create a new EBS volume that will host the Git data. Its
+size depends on your needs and you can always migrate to a bigger volume later.
+You will be able to [set up that volume](#setting-up-the-ebs-volume)
+after the instance is created.
+
+### Configure security group
+
+As a last step, configure the security group:
+
+1. Select the existing load balancer security group we have [created](#load-balancer).
+1. Select **Review**.
+
+### Review and launch
+
+Now is a good time to review all the previous settings. When ready, click
+**Create launch configuration** and select the SSH key pair with which you will
+connect to the instance.
+
+### Create Auto Scaling Group
+
+We are now able to start creating our Auto Scaling Group:
+
+1. Give it a group name.
+1. Set the group size to 2 as we want to always start with two instances.
+1. Assign it our network VPC and add the **private subnets**.
+1. In the "Advanced Details" section, choose to receive traffic from ELBs
+ and select our ELB.
+1. Choose the ELB health check.
+1. Click **Next: Configure scaling policies**.
+
+This is the really great part of Auto Scaling; we get to choose when AWS
+launches new instances and when it removes them. For this group we'll
+scale between 2 and 4 instances where one instance will be added if CPU
+utilization is greater than 60% and one instance is removed if it falls
+to less than 45%.
+
+![Auto scaling group policies](img/policies.png)
+
+Finally, configure notifications and tags as you see fit, and create the
+auto scaling group.
+
+You'll notice that after we save the configuration, AWS starts launching our two
+instances in different AZs and without a public IP which is exactly what
+we intended.
+
+## After deployment
+
+After a few minutes, the instances should be up and accessible via the internet.
+Let's connect to the primary and configure some things before logging in.
+
+### Configuring GitLab to connect with postgres and Redis
+
+While connected to your server, let's connect to the RDS instance to verify
+access and to install a required extension:
+
+```sh
+sudo /opt/gitlab/embedded/bin/psql -U gitlab -h <rds-endpoint> -d gitlabhq_production
+```
+
+Edit the `gitlab.rb` file at `/etc/gitlab/gitlab.rb`
+find the `external_url 'http://gitlab.example.com'` option and change it
+to the domain you will be using or the public IP address of the current
+instance to test the configuration.
+
+For a more detailed description about configuring GitLab, see [Configuring GitLab for HA](../../administration/high_availability/gitlab.md)
+
+Now look for the GitLab database settings and uncomment as necessary. In
+our current case we'll specify the database adapter, encoding, host, name,
+username, and password:
+
+```ruby
+# Disable the built-in Postgres
+postgresql['enable'] = false
+
+# Fill in the connection details
+gitlab_rails['db_adapter'] = "postgresql"
+gitlab_rails['db_encoding'] = "unicode"
+gitlab_rails['db_database'] = "gitlabhq_production"
+gitlab_rails['db_username'] = "gitlab"
+gitlab_rails['db_password'] = "mypassword"
+gitlab_rails['db_host'] = "<rds-endpoint>"
+```
+
+Next, we need to configure the Redis section by adding the host and
+uncommenting the port:
+
+```ruby
+# Disable the built-in Redis
+redis['enable'] = false
+
+# Fill in the connection details
+gitlab_rails['redis_host'] = "<redis-endpoint>"
+gitlab_rails['redis_port'] = 6379
+```
+
+Finally, reconfigure GitLab for the change to take effect:
+
+
+```sh
+sudo gitlab-ctl reconfigure
+```
+
+You might also find it useful to run a check and a service status to make sure
+everything has been setup correctly:
+
+```sh
+sudo gitlab-rake gitlab:check
+sudo gitlab-ctl status
+```
+
+If everything looks good, you should be able to reach GitLab in your browser.
+
+### Setting up the EBS volume
+
+The EBS volume will host the Git repositories data:
+
+1. First, format the `/dev/xvdb` volume and then mount it under the directory
+ where the data will be stored. For example, `/mnt/gitlab-data/`.
+1. Tell GitLab to store its data in the new directory by editing
+ `/etc/gitlab/gitlab.rb` with your editor:
+
+ ```ruby
+ git_data_dirs({
+ "default" => { "path" => "/mnt/gitlab-data" }
+ })
+ ```
+
+ where `/mnt/gitlab-data` the location where you will store the Git data.
+
+1. Save the file and reconfigure GitLab:
+
+ ```sh
+ sudo gitlab-ctl reconfigure
+ ```
+
+TIP: **Tip:**
+If you wish to add more than one data volumes to store the Git repositories,
+read the [repository storage paths docs](../../administration/repository_storage_paths.md).
+
+### Setting up Gitaly
+
+Gitaly is a service that provides high-level RPC access to Git repositories.
+It should be enabled and configured in a separate EC2 instance on the
+[private VPC](#subnets) we configured previously.
+
+Follow the [documentation to set up Gitaly](../../administration/gitaly/index.md).
+
+### Using Amazon S3 object storage
+
+GitLab stores many objects outside the Git repository, many of which can be
+uploaded to S3. That way, you can offload the root disk volume of these objects
+which would otherwise take much space.
+
+In particular, you can store in S3:
+
+- [The Git LFS objects](../../workflow/lfs/lfs_administration.md#s3-for-omnibus-installations) ((Omnibus GitLab installations))
+- [The Container Registry images](../../administration/container_registry.md#container-registry-storage-driver) (Omnibus GitLab installations)
+- [The GitLab CI/CD job artifacts](../../administration/job_artifacts.md#using-object-storage) (Omnibus GitLab installations)
+
+### Setting up a domain name
+
+After you SSH into the instance, configure the domain name:
+
+1. Open `/etc/gitlab/gitlab.rb` with your preferred editor.
+1. Edit the `external_url` value:
+
+ ```ruby
+ external_url 'http://example.com'
+ ```
+
+1. Reconfigure GitLab:
+
+ ```sh
+ sudo gitlab-ctl reconfigure
+ ```
+
+You should now be able to reach GitLab at the URL you defined. To use HTTPS
+(recommended), see the [HTTPS documentation](https://docs.gitlab.com/omnibus/settings/nginx.html#enable-https).
+
+### Logging in for the first time
+
+If you followed the previous section, you should be now able to visit GitLab
+in your browser. The very first time, you will be asked to set up a password
+for the `root` user which has admin privileges on the GitLab instance.
+
+After you set it up, login with username `root` and the newly created password.
+
+## Health check and monitoring with Prometheus
+
+Apart from Amazon's Cloudwatch which you can enable on various services,
+GitLab provides its own integrated monitoring solution based on Prometheus.
+For more information on how to set it up, visit the
+[GitLab Prometheus documentation](../../administration/monitoring/prometheus/index.md)
+
+GitLab also has various [health check endpoints](../..//user/admin_area/monitoring/health_check.md)
+that you can ping and get reports.
+
+## GitLab Runners
+
+If you want to take advantage of [GitLab CI/CD](../../ci/README.md), you have to
+set up at least one [GitLab Runner](https://docs.gitlab.com/runner/).
+
+Read more on configuring an
+[autoscaling GitLab Runner on AWS](https://docs.gitlab.com/runner/configuration/runner_autoscale_aws/).
+
+## Backup and restore
+
+GitLab provides [a tool to backup](../../raketasks/backup_restore.md#creating-a-backup-of-the-gitlab-system)
+and restore its Git data, database, attachments, LFS objects, etc.
+
+Some important things to know:
+
+- The backup/restore tool **does not** store some configuration files, like secrets; you'll
+ need to [configure this yourself](../../raketasks/backup_restore.md#storing-configuration-files).
+- By default, the backup files are stored locally, but you can
+ [backup GitLab using S3](../../raketasks/backup_restore.md#using-amazon-s3).
+- You can [exclude specific directories form the backup](../../raketasks/backup_restore.md#excluding-specific-directories-from-the-backup).
+
+### Backing up GitLab
+
+To back up GitLab:
+
+1. SSH into your instance.
+1. Take a backup:
+
+ ```sh
+ sudo gitlab-rake gitlab:backup:create
+ ```
+
+### Restoring GitLab from a backup
+
+To restore GitLab, first review the [restore documentation](../../raketasks/backup_restore.md#restore),
+and primarily the restore prerequisites. Then, follow the steps under the
+[Omnibus installations section](../../raketasks/backup_restore.md#restore-for-omnibus-installations).
+
+## Updating GitLab
+
+GitLab releases a new version every month on the 22nd. Whenever a new version is
+released, you can update your GitLab instance:
+
+1. SSH into your instance
+1. Take a backup:
+
+ ```sh
+ sudo gitlab-rake gitlab:backup:create
+ ```
+
+1. Update the repositories and install GitLab:
+
+ ```sh
+ sudo apt update
+ sudo apt install gitlab-ee
+ ```
+
+After a few minutes, the new version should be up and running.
+
+## Conclusion
+
+In this guide, we went mostly through scaling and some redundancy options,
+your mileage may vary.
+
+Keep in mind that all Highly Available solutions come with a trade-off between
+cost/complexity and uptime. The more uptime you want, the more complex the solution.
+And the more complex the solution, the more work is involved in setting up and
+maintaining it.
+
+Have a read through these other resources and feel free to
+[open an issue](https://gitlab.com/gitlab-org/gitlab-ce/issues/new)
+to request additional material:
+
+- [GitLab High Availability](https://docs.gitlab.com/ee/administration/high_availability/):
+ GitLab supports several different types of clustering and high-availability.
+- [Geo replication](https://docs.gitlab.com/ee/administration/geo/replication/):
+ Geo is the solution for widely distributed development teams.
+- [Omnibus GitLab](https://docs.gitlab.com/omnibus/) - Everything you need to know
+ about administering your GitLab instance.
+- [Upload a license](https://docs.gitlab.com/ee/user/admin_area/license.html):
+ Activate all GitLab Enterprise Edition functionality with a license.
+- [Pricing](https://about.gitlab.com/pricing): Pricing for the different tiers.
diff --git a/doc/install/azure/index.md b/doc/install/azure/index.md
index 570bd18c172..19a6e46f969 100644
--- a/doc/install/azure/index.md
+++ b/doc/install/azure/index.md
@@ -37,7 +37,7 @@ Once you have an Azure account, you can get started. Login to Azure using
![Azure Dashboard](img/azure-dashboard.png)
-The Dashboard gives you a quick overview of Azure resources, and from here you you can build VMs,
+The Dashboard gives you a quick overview of Azure resources, and from here you can build VMs,
create SQL Databases, author websites, and perform lots of other cloud tasks.
## Create New VM
@@ -74,7 +74,7 @@ The first items we need to configure are the basic settings of the underlying vi
> **Note:** if you're unsure which authentication type to use, select **Password**
1. If you chose **SSH public key** - enter your `SSH public key` into the field provided
- _(read the [SSH documentation][GitLab-Docs-SSH] to learn more about how to setup SSH
+ _(read the [SSH documentation][GitLab-Docs-SSH] to learn more about how to set up SSH
public keys)_
1. If you chose **Password** - enter the password you wish to use _(this is the password that you
will use later in this tutorial to [SSH] into the VM, so make sure it's a strong password/passphrase)_
@@ -154,7 +154,7 @@ on the Azure Dashboard (you may need to refresh the page):
The new VM can also be accessed by clicking the `All resources` or `Virtual machines` icons in the
Azure Portal sidebar navigation menu.
-## Setup a domain name
+## Set up a domain name
The VM will have a public IP address (static by default), but Azure allows us to assign a friendly
DNS name to the VM, so let's go ahead and do that.
@@ -296,7 +296,7 @@ homepage for the project:
![GitLab - Empty Project](img/gitlab-project-home-empty.png)
If you scroll further down the project's home page, you'll see some basic instructions on how to
-setup a local clone of your new repository and push and pull from it:
+set up a local clone of your new repository and push and pull from it:
![GitLab - Empty Project - Basic Instructions](img/gitlab-project-home-instructions.png)
@@ -347,7 +347,7 @@ If you're running [SSH] from the command-line (terminal), then type in the follo
connect to your VM, substituting `username` and `your-azure-domain-name.com` for the correct values.
Again, remember that your Azure VM domain name will be the one you
-[setup previously in the tutorial](#set-up-a-domain-name). If you didn't setup a domain name for
+[set up previously in the tutorial](#set-up-a-domain-name). If you didn't set up a domain name for
your VM, you can use the IP address in its place in the following command:
```bash
@@ -401,7 +401,7 @@ is now showing **"up-to-date"**:
Naturally, we believe that GitLab is a great git repository tool. However, GitLab is a whole lot
more than that too. GitLab unifies issues, code review, CI and CD into a single UI, helping you to
move faster from idea to production, and in this tutorial we showed you how quick and easy it is to
-setup and run your own instance of GitLab on Azure, Microsoft's cloud service.
+set up and run your own instance of GitLab on Azure, Microsoft's cloud service.
Azure is a great way to experiment with GitLab, and if you decide (as we hope) that GitLab is for
you, you can continue to use Azure as your secure, scalable cloud provider or of course run GitLab
@@ -424,7 +424,7 @@ Check out our other [Technical Articles][GitLab-Technical-Articles] or browse th
- [Azure - Properly Shutdown an Azure VM][Azure-Properly-Shutdown-VM]
- [SSH], [PuTTY] and [Using SSH in PuTTY][Using-SSH-In-Putty]
-[Original-Blog-Post]: https://about.gitlab.com/2016/07/13/how-to-setup-a-gitlab-instance-on-microsoft-azure/ "How to Setup a GitLab Instance on Microsoft Azure"
+[Original-Blog-Post]: https://about.gitlab.com/2016/07/13/how-to-setup-a-gitlab-instance-on-microsoft-azure/ "How to Set up a GitLab Instance on Microsoft Azure"
[GitLab-Docs]: https://docs.gitlab.com/ce/README.html "GitLab Documentation"
[GitLab-Technical-Articles]: https://docs.gitlab.com/ce/articles/index.html "GitLab Technical Articles"
[GitLab-Docs-SSH]: https://docs.gitlab.com/ce/ssh/README.html "GitLab Documentation: SSH"
diff --git a/doc/install/database_mysql.md b/doc/install/database_mysql.md
index 4cf18f53239..e89846107b6 100644
--- a/doc/install/database_mysql.md
+++ b/doc/install/database_mysql.md
@@ -1,15 +1,20 @@
# Database MySQL
-> **Note:**
-> - We do not recommend using MySQL due to various issues. For example, case
- [(in)sensitivity](https://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html)
- and [problems](https://bugs.mysql.com/bug.php?id=65830) that
- [suggested](https://bugs.mysql.com/bug.php?id=50909)
- [fixes](https://bugs.mysql.com/bug.php?id=65830) [have](https://bugs.mysql.com/bug.php?id=63164).
+NOTE: **Note:**
+We do not recommend using MySQL due to various issues.
+For example, there have been bugs with case
+[(in)sensitivity](https://dev.mysql.com/doc/refman/5.7/en/case-sensitivity.html).
+
+Bugs relating to case sensitivity:
+
+- <https://bugs.mysql.com/bug.php?id=65830>
+- <https://bugs.mysql.com/bug.php?id=50909>
+- <https://bugs.mysql.com/bug.php?id=65830>
+- <https://bugs.mysql.com/bug.php?id=63164>
## Initial database setup
-```
+```sh
# Install the database packages
sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev
@@ -79,19 +84,20 @@ After installation or upgrade, remember to [convert any new tables](#tables-and-
---
-GitLab 8.14 has introduced [a feature](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7420) requiring `utf8mb4` encoding to be supported in your GitLab MySQL Database, which is not the case if you have setup your database before GitLab 8.16.
+GitLab 8.14 has introduced [a feature](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7420) requiring `utf8mb4` encoding to be supported in your GitLab MySQL Database, which is not the case if you have set up your database before GitLab 8.16.
Follow the below instructions to ensure you use the most up to date requirements for your GitLab MySQL Database.
**We are about to do the following:**
+
- Ensure you can enable `utf8mb4` encoding and `utf8mb4_general_ci` collation for your GitLab DB, tables and data.
-- Convert your GitLab tables and data from `utf8`/`utf8_general_ci` to `utf8mb4`/`utf8mb4_general_ci`
+- Convert your GitLab tables and data from `utf8`/`utf8_general_ci` to `utf8mb4`/`utf8mb4_general_ci`.
### Check for utf8mb4 support
#### Check for InnoDB File-Per-Table Tablespaces
-We need to check, enable and maybe convert your existing GitLab DB tables to the [InnoDB File-Per-Table Tablespaces](http://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html) as a prerequisite for supporting **utfb8mb4 with long indexes** required by recent GitLab databases.
+We need to check, enable and maybe convert your existing GitLab DB tables to the [InnoDB File-Per-Table Tablespaces](https://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html) as a prerequisite for supporting **utfb8mb4 with long indexes** required by recent GitLab databases.
# Login to MySQL
mysql -u root -p
@@ -128,9 +134,10 @@ We need to check, enable and maybe convert your existing GitLab DB tables to the
> You need **MySQL 5.5.3 or later** to perform this update.
-Whatever the results of your checks above, we now need to check if your GitLab database has been created using [InnoDB File-Per-Table Tablespaces](http://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html) (i.e. `innodb_file_per_table` was set to **1** at initial setup time).
+Whatever the results of your checks above, we now need to check if your GitLab database has been created using [InnoDB File-Per-Table Tablespaces](https://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html) (i.e. `innodb_file_per_table` was set to **1** at initial setup time).
-> Note: This setting is [enabled by default](http://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_file_per_table) since MySQL 5.6.6.
+NOTE: **Note:**
+This setting is [enabled by default](http://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_file_per_table) since MySQL 5.6.6.
# Run this command with root privileges, replace the data dir if different:
sudo ls -lh /var/lib/mysql/gitlabhq_production/*.ibd | wc -l
@@ -138,26 +145,25 @@ Whatever the results of your checks above, we now need to check if your GitLab d
# Run this command with root privileges, replace the data dir if different:
sudo ls -lh /var/lib/mysql/gitlabhq_production/*.frm | wc -l
-
- **Case 1: a result > 0 for both commands**
-Congrats, your GitLab database uses the right InnoDB tablespace format.
+Congratulations, your GitLab database uses the right InnoDB tablespace format.
However, you must still ensure that any **future tables** created by GitLab will still use the right format:
- If `SELECT @@innodb_file_per_table` returned **1** previously, your server is running correctly.
- > It's however a requirement to check *now* that this setting is indeed persisted in your [my.cnf](https://dev.mysql.com/doc/refman/5.7/en/tablespace-enabling.html) file!
+ > It's however a requirement to check *now* that this setting is indeed persisted in your [`my.cnf`](https://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html) file!
- If `SELECT @@innodb_file_per_table` returned **0** previously, your server is not running correctly.
- > [Enable innodb_file_per_table](https://dev.mysql.com/doc/refman/5.7/en/tablespace-enabling.html) by running in a MySQL session as root the command `SET GLOBAL innodb_file_per_table=1, innodb_file_format=Barracuda;` and persist the two settings in your [my.cnf](https://dev.mysql.com/doc/refman/5.7/en/tablespace-enabling.html) file
+ > [Enable innodb_file_per_table](https://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html) by running in a MySQL session as root the command `SET GLOBAL innodb_file_per_table=1, innodb_file_format=Barracuda;` and persist the two settings in your [`my.cnf`](https://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html) file.
Now, if you have a **different result** returned by the 2 commands above, it means you have a **mix of tables format** uses in your GitLab database. This can happen if your MySQL server had different values for `innodb_file_per_table` in its life and you updated GitLab at different moments with those inconsistent values. So keep reading.
- **Case 2: a result equals to "0" OR not the same result for both commands**
-Unfortunately, none or only some of your GitLab database tables use the GitLab requirement of [InnoDB File-Per-Table Tablespaces](http://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html).
+Unfortunately, none or only some of your GitLab database tables use the GitLab requirement of [InnoDB File-Per-Table Tablespaces](https://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html).
Let's enable what we need on the running server:
@@ -172,7 +178,7 @@ Let's enable what we need on the running server:
# You can now quit the database session
mysql> \q
-> Now, **persist** [innodb_file_per_table](https://dev.mysql.com/doc/refman/5.6/en/tablespace-enabling.html) and [innodb_file_format](https://dev.mysql.com/doc/refman/5.6/en/innodb-file-format-enabling.html) in your `my.cnf` file.
+> Now, **persist** [innodb_file_per_table](https://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html) and [innodb_file_format](https://dev.mysql.com/doc/refman/5.7/en/innodb-file-format-enabling.html) in your `my.cnf` file.
Ensure at this stage that your GitLab instance is indeed **stopped**.
@@ -184,7 +190,7 @@ Now, let's convert all the GitLab database tables to the new tablespace format:
# Type the MySQL root password
mysql > use gitlabhq_production;
- # Safety check: you should still have those values set as follow:
+ # Safety check: you should still have those values set as follows:
mysql> SELECT @@innodb_file_per_table, @@innodb_file_format;
+-------------------------+----------------------+
| @@innodb_file_per_table | @@innodb_file_format |
@@ -203,7 +209,7 @@ Now, let's convert all the GitLab database tables to the new tablespace format:
#### Check for proper InnoDB File Format, Row Format, Large Prefix and tables conversion
-We need to check, enable and probably convert your existing GitLab DB tables to use the [Barracuda InnoDB file format](https://dev.mysql.com/doc/refman/5.6/en/innodb-file-format.html), the [DYNAMIC row format](https://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_dynamic_row_format) and [innodb_large_prefix](http://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_large_prefix) as a second prerequisite for supporting **utfb8mb4 with long indexes** used by recent GitLab databases.
+We need to check, enable and probably convert your existing GitLab DB tables to use the [Barracuda InnoDB file format](https://dev.mysql.com/doc/refman/5.7/en/innodb-file-format.html), the [DYNAMIC row format](https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_dynamic_row_format) and [innodb_large_prefix](http://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_large_prefix) as a second prerequisite for supporting **utfb8mb4 with long indexes** used by recent GitLab databases.
# Login to MySQL
mysql -u root -p
@@ -229,7 +235,7 @@ We need to check, enable and probably convert your existing GitLab DB tables to
| utf8 | utf8_general_ci |
+--------------------------+----------------------+
-> Now, ensure that [innodb_file_format](https://dev.mysql.com/doc/refman/5.6/en/tablespace-enabling.html) and [innodb_large_prefix](http://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_large_prefix) are **persisted** in your `my.cnf` file.
+> Now, ensure that [innodb_file_format](https://dev.mysql.com/doc/refman/5.7/en/innodb-multiple-tablespaces.html) and [innodb_large_prefix](http://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_large_prefix) are **persisted** in your `my.cnf` file.
#### Tables and data conversion to utf8mb4
@@ -257,7 +263,7 @@ Now that you have a persistent MySQL setup, you can safely upgrade tables after
Ensure your GitLab database configuration file uses a proper connection encoding and collation:
-```sudo -u git -H editor config/database.yml```
+`sudo -u git -H editor config/database.yml`
production:
adapter: mysql2
@@ -266,19 +272,19 @@ Ensure your GitLab database configuration file uses a proper connection encoding
[Restart your GitLab instance](../administration/restart_gitlab.md).
-
## MySQL strings limits
After installation or upgrade, remember to run the `add_limits_mysql` Rake task:
**Omnibus GitLab installations**
-```
+
+```sh
sudo gitlab-rake add_limits_mysql
```
**Installations from source**
-```
+```sh
bundle exec rake add_limits_mysql RAILS_ENV=production
```
@@ -291,8 +297,7 @@ GitLab database to `longtext` columns, which can persist values of up to 4GB
(sometimes less if the value contains multibyte characters).
Details can be found in the [PostgreSQL][postgres-text-type] and
-[MySQL][mysql-text-types] manuals.
+[MySQL](https://dev.mysql.com/doc/refman/5.7/en/string-type-overview.html) manuals.
[postgres-text-type]: http://www.postgresql.org/docs/9.2/static/datatype-character.html
-[mysql-text-types]: http://dev.mysql.com/doc/refman/5.7/en/string-type-overview.html
[ce-38152]: https://gitlab.com/gitlab-org/gitlab-ce/issues/38152
diff --git a/doc/install/digitaloceandocker.md b/doc/install/digitaloceandocker.md
index 8efc0530b8a..d67695d75b4 100644
--- a/doc/install/digitaloceandocker.md
+++ b/doc/install/digitaloceandocker.md
@@ -1,7 +1,8 @@
# Digital Ocean and Docker Machine test environment
-## Warning. This guide is for quickly testing different versions of GitLab and
-## not recommended for ease of future upgrades or keeping the data you create.
+CAUTION: **Caution:**
+This guide is for quickly testing different versions of GitLab and not recommended for ease of
+future upgrades or keeping the data you create.
## Initial setup
@@ -12,92 +13,88 @@ locally on either macOS or Linux.
#### Install Docker Toolbox
-1. [https://www.docker.com/products/docker-toolbox](https://www.docker.com/products/docker-toolbox)
+- <https://www.docker.com/products/docker-toolbox>
### On Linux
#### Install Docker Engine
-1. [https://docs.docker.com/engine/installation/linux](https://docs.docker.com/engine/installation/linux/)
+- <https://docs.docker.com/engine/installation/linux/>
#### Install Docker Machine
-1. [https://docs.docker.com/machine/install-machine](https://docs.docker.com/machine/install-machine/)
+- <https://docs.docker.com/machine/install-machine/>
-_The rest of the steps are identical for macOS and Linux_
+NOTE: **Note:**
+The rest of the steps are identical for macOS and Linux.
### Create new docker host
-1. Login to Digital Ocean
-1. Generate a new API token at https://cloud.digitalocean.com/settings/api/tokens
+1. Login to Digital Ocean.
+1. Generate a new API token at <https://cloud.digitalocean.com/settings/api/tokens>.
+ This command will create a new DO droplet called `gitlab-test-env-do` that will act as a docker host.
-This command will create a new DO droplet called `gitlab-test-env-do` that will act as a docker host.
+ NOTE: **Note:**
+ 4GB is the minimum requirement for a Docker host that will run more than one GitLab instance.
-**Note: 4GB is the minimum requirement for a Docker host that will run more then one GitLab instance**
+ - RAM: 4GB
+ - Name: `gitlab-test-env-do`
+ - Driver: `digitalocean`
-+ RAM: 4GB
-+ Name: `gitlab-test-env-do`
-+ Driver: `digitalocean`
+1. Set the DO token:
+ ```sh
+ export DOTOKEN=<your generated token>
+ ```
-**Set the DO token** - Replace the string below with your generated token
+1. Create the machine:
-```
-export DOTOKEN=cf3dfd0662933203005c4a73396214b7879d70aabc6352573fe178d340a80248
-```
-
-**Create the machine**
-
-```
-docker-machine create \
- --driver digitalocean \
- --digitalocean-access-token=$DOTOKEN \
- --digitalocean-size "4gb" \
- gitlab-test-env-do
-```
-
-+ Resource: https://docs.docker.com/machine/drivers/digital-ocean/
+ ```sh
+ docker-machine create \
+ --driver digitalocean \
+ --digitalocean-access-token=$DOTOKEN \
+ --digitalocean-size "4gb" \
+ gitlab-test-env-do
+ ```
+Resource: <https://docs.docker.com/machine/drivers/digital-ocean/>.
### Creating GitLab test instance
-
#### Connect your shell to the new machine
-
In this example we'll create a GitLab EE 8.10.8 instance.
-
First connect the docker client to the docker host you created previously.
-```
+```sh
eval "$(docker-machine env gitlab-test-env-do)"
```
You can add this to your `~/.bash_profile` file to ensure the `docker` client uses the `gitlab-test-env-do` docker host
-
#### Create new GitLab container
-+ HTTP port: `8888`
-+ SSH port: `2222`
- + Set `gitlab_shell_ssh_port` using `--env GITLAB_OMNIBUS_CONFIG `
-+ Hostname: IP of docker host
-+ Container name: `gitlab-test-8.10`
-+ GitLab version: **EE** `8.10.8-ee.0`
+- HTTP port: `8888`
+- SSH port: `2222`
+ - Set `gitlab_shell_ssh_port` using `--env GITLAB_OMNIBUS_CONFIG`
+- Hostname: IP of docker host
+- Container name: `gitlab-test-8.10`
+- GitLab version: **EE** `8.10.8-ee.0`
-##### Setup container settings
+##### Set up container settings
-```
+```sh
export SSH_PORT=2222
export HTTP_PORT=8888
export VERSION=8.10.8-ee.0
export NAME=gitlab-test-8.10
```
-##### Create container
-```
+##### Create container
+
+```sh
docker run --detach \
--env GITLAB_OMNIBUS_CONFIG="external_url 'http://$(docker-machine ip gitlab-test-env-do):$HTTP_PORT'; gitlab_rails['gitlab_shell_ssh_port'] = $SSH_PORT;" \
--hostname $(docker-machine ip gitlab-test-env-do) \
@@ -110,23 +107,20 @@ gitlab/gitlab-ee:$VERSION
##### Retrieve the docker host IP
-```
+```sh
docker-machine ip gitlab-test-env-do
# example output: 192.168.151.134
```
-
-+ Browse to: http://192.168.151.134:8888/
-
+Browse to: <http://192.168.151.134:8888/>.
##### Execute interactive shell/edit configuration
-
-```
+```sh
docker exec -it $NAME /bin/bash
```
-```
+```sh
# example commands
root@192:/# vi /etc/gitlab/gitlab.rb
root@192:/# gitlab-ctl reconfigure
@@ -134,6 +128,6 @@ root@192:/# gitlab-ctl reconfigure
#### Resources
-+ [https://docs.gitlab.com/omnibus/docker/](https://docs.gitlab.com/omnibus/docker/)
-+ [https://docs.docker.com/machine/get-started/](https://docs.docker.com/machine/get-started/)
-+ [https://docs.docker.com/machine/reference/ip/](https://docs.docker.com/machine/reference/ip/)+
+- <https://docs.gitlab.com/omnibus/docker/>.
+- <https://docs.docker.com/machine/get-started/>.
+- <https://docs.docker.com/machine/reference/ip/>.
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 85431a80a81..06293b8caf5 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -12,7 +12,7 @@ Since installations from source don't have Runit, Sidekiq can't be terminated an
## Select Version to Install
-Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install (e.g., `11-3-stable`).
+Make sure you view [this installation guide](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/installation.md) from the branch (version) of GitLab you would like to install (e.g., `11-5-stable`).
You can select the branch in the version dropdown in the top left corner of GitLab (below the menu bar).
If the highest number stable branch is unclear please check the [GitLab Blog](https://about.gitlab.com/blog/) for installation guide links by version.
@@ -79,7 +79,7 @@ Make sure you have the right version of Git installed
# Install Git
sudo apt-get install -y git-core
- # Make sure Git is version 2.9.5 or higher
+ # Make sure Git is version 2.18.0 or higher
git --version
Is the system packaged Git too old? Remove it and compile from source.
@@ -103,7 +103,7 @@ Is the system packaged Git too old? Remove it and compile from source.
# When editing config/gitlab.yml (Step 5), change the git -> bin_path to /usr/local/bin/git
-**Note:** In order to receive mail notifications, make sure to install a mail server. By default, Debian is shipped with exim4 but this [has problems](https://github.com/gitlabhq/gitlabhq/issues/4866#issuecomment-32726573) while Ubuntu does not ship with one. The recommended mail server is postfix and you can install it with:
+**Note:** In order to receive mail notifications, make sure to install a mail server. By default, Debian is shipped with exim4 but this [has problems](https://gitlab.com/gitlab-org/gitlab-ce/issues/12754) while Ubuntu does not ship with one. The recommended mail server is postfix and you can install it with:
sudo apt-get install -y postfix
@@ -132,9 +132,9 @@ Remove the old Ruby 1.8 if present:
Download Ruby and compile it:
mkdir /tmp/ruby && cd /tmp/ruby
- curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.4.tar.gz
- echo 'ec82b0d53bd0adad9b19e6b45e44d54e9ec3f10c ruby-2.4.4.tar.gz' | shasum -c - && tar xzf ruby-2.4.4.tar.gz
- cd ruby-2.4.4
+ curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.3.tar.gz
+ echo 'f919a9fbcdb7abecd887157b49833663c5c15fda ruby-2.5.3.tar.gz' | shasum -c - && tar xzf ruby-2.5.3.tar.gz
+ cd ruby-2.5.3
./configure --disable-install-rdoc
make
@@ -300,9 +300,9 @@ sudo usermod -aG redis git
### Clone the Source
# Clone GitLab repository
- sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 11-3-stable gitlab
+ sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 11-5-stable gitlab
-**Note:** You can change `11-3-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
+**Note:** You can change `11-5-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
### Configure It
@@ -460,11 +460,11 @@ GitLab-Pages uses [GNU Make](https://www.gnu.org/software/make/). This step is o
### Install Gitaly
# Fetch Gitaly source with Git and compile with Go
- sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly]" RAILS_ENV=production
+ sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly,/home/git/repositories]" RAILS_ENV=production
You can specify a different Git repository by providing it as an extra parameter:
- sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly,https://example.com/gitaly.git]" RAILS_ENV=production
+ sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly,/home/git/repositories,https://example.com/gitaly.git]" RAILS_ENV=production
Next, make sure gitaly configured:
@@ -515,7 +515,7 @@ Make GitLab start on boot:
sudo update-rc.d gitlab defaults 21
-### Setup Logrotate
+### Set up Logrotate
sudo cp lib/support/logrotate/gitlab /etc/logrotate.d/gitlab
diff --git a/doc/install/kubernetes/gitlab_chart.md b/doc/install/kubernetes/gitlab_chart.md
index 09f5aaa04a7..5749eb0a9ec 100644
--- a/doc/install/kubernetes/gitlab_chart.md
+++ b/doc/install/kubernetes/gitlab_chart.md
@@ -31,7 +31,7 @@ to deploy.
TIP: **Tip:**
For production deployments, we strongly recommend using the
-[detailed installation instructions](https://gitlab.com/charts/gitlab/blob/master/doc/installation/README.md)
+[detailed installation instructions](https://gitlab.com/charts/gitlab/blob/master/doc/installation/index.md)
utilizing [external Postgres, Redis, and object storage](https://gitlab.com/charts/gitlab/tree/master/doc/advanced) services.
### Requirements
@@ -93,7 +93,7 @@ You can access the GitLab instance by visiting the domain name beginning with
above, the URL would be `https://gitlab.example.com`.
If you manually created the secret for initial root password, you
-can use that to sign in as `root` user. If not, Gitlab automatically
+can use that to sign in as `root` user. If not, GitLab automatically
created a random password for `root` user. This can be extracted by the
following command (replace `<name>` by name of the release - which is `gitlab`
if you used the command above):
@@ -112,8 +112,7 @@ If your SMTP server requires authentication make sure to read the section on pro
your password in the [secrets documentation](https://gitlab.com/charts/gitlab/blob/master/doc/installation/secrets.md#smtp-password).
You can disable authentication settings with `--set global.smtp.authentication=""`.
-If your Kubernetes cluster is on GKE, be aware that SMTP ports [25, 465, and 587
-are blocked](https://cloud.google.com/compute/docs/tutorials/sending-mail/#using_standard_email_ports).
+If your Kubernetes cluster is on GKE, be aware that SMTP port [25 is blocked](https://cloud.google.com/compute/docs/tutorials/sending-mail/#using_standard_email_ports).
### Deploying the Community Edition
diff --git a/doc/install/kubernetes/gitlab_runner_chart.md b/doc/install/kubernetes/gitlab_runner_chart.md
index 2aab225fcdb..3c2f883f29d 100644
--- a/doc/install/kubernetes/gitlab_runner_chart.md
+++ b/doc/install/kubernetes/gitlab_runner_chart.md
@@ -1,6 +1,6 @@
# GitLab Runner Helm Chart
> **Note:**
-These charts have been tested on Google Kubernetes Engine and Azure Container Service. Other Kubernetes installations may work as well, if not please [open an issue](https://gitlab.com/charts/gitlab-runner/issues).
+These charts have been tested on Google Kubernetes Engine and Azure Container Service. Other Kubernetes installations may work as well, if not please [open an issue](https://gitlab.com/gitlab-org/gitlab-runner/issues).
The `gitlab-runner` Helm chart deploys a GitLab Runner instance into your
Kubernetes cluster.
@@ -84,7 +84,7 @@ rbac:
##
# serviceAccountName: default
-## Configuration for the Pods that that the runner launches for each new job
+## Configuration for the Pods that the runner launches for each new job
##
runners:
## Default container image to use for builds when none is specified
@@ -132,7 +132,7 @@ runners:
If your cluster has RBAC enabled, you can choose to either have the chart create its own service account or provide one.
-To have the chart create the service account for you, set `rbac.create` to true.
+To have the chart create the service account for you, set `rbac.create` to true.
### Controlling maximum Runner concurrency
diff --git a/doc/install/openshift_and_gitlab/index.md b/doc/install/openshift_and_gitlab/index.md
index 70bc3ff770f..4c88b6f97fc 100644
--- a/doc/install/openshift_and_gitlab/index.md
+++ b/doc/install/openshift_and_gitlab/index.md
@@ -80,7 +80,7 @@ This will download the VirtualBox image and fire up the VM with some preconfigur
values as you can see in the Vagrantfile. As you may have noticed, you need
plenty of RAM (5GB in our example), so make sure you have enough.
-Now that OpenShift is setup, let's see how the web console looks like.
+Now that OpenShift is set up, let's see how the web console looks like.
### Explore the OpenShift web console
@@ -505,7 +505,7 @@ PaaS and managing your applications with the ease of containers.
[RedHat]: https://www.redhat.com/en "RedHat website"
[openshift]: https://www.openshift.org "OpenShift Origin website"
[vm]: https://www.openshift.org/vm/ "OpenShift All-in-one VM"
-[vm-new]: https://atlas.hashicorp.com/openshift/boxes/origin-all-in-one "Official OpenShift Vagrant box on Atlas"
+[vm-new]: https://app.vagrantup.com/openshift/boxes/origin-all-in-one "Official OpenShift Vagrant box on Vagrant Cloud"
[template]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/docker/openshift-template.json "OpenShift template for GitLab"
[openshift.com]: https://openshift.com "OpenShift Online"
[kubernetes]: http://kubernetes.io/ "Kubernetes website"
diff --git a/doc/install/relative_url.md b/doc/install/relative_url.md
index 2f5d4142d04..5f129fd3bd1 100644
--- a/doc/install/relative_url.md
+++ b/doc/install/relative_url.md
@@ -124,5 +124,5 @@ To disable the relative URL:
1. Follow the same as above starting from 2. and set up the
GitLab URL to one that doesn't contain a relative path.
-[omnibus-rel]: http://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab "How to setup relative URL in Omnibus GitLab"
+[omnibus-rel]: http://docs.gitlab.com/omnibus/settings/configuration.html#configuring-a-relative-url-for-gitlab "How to set up relative URL in Omnibus GitLab"
[restart gitlab]: ../administration/restart_gitlab.md#installations-from-source "How to restart GitLab"
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index df59ce9837c..1b7e0d1d0ab 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -36,7 +36,7 @@ Please consider using a virtual machine to run GitLab.
GitLab requires Ruby (MRI) 2.3. Support for Ruby versions below 2.3 (2.1, 2.2) will stop with GitLab 8.13.
You will have to use the standard MRI implementation of Ruby.
-We love [JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/) but GitLab
+We love [JRuby](https://www.jruby.org/) and [Rubinius](https://rubinius.com) but GitLab
needs several Gems that have native extensions.
## Hardware requirements
@@ -103,8 +103,8 @@ features of GitLab work with MySQL/MariaDB:
1. MySQL support for subgroups was [dropped with GitLab 9.3][post].
See [issue #30472][30472] for more information.
-1. Geo **[STARTER ONLY]** does [not support MySQL](https://docs.gitlab.com/ee/gitlab-geo/database.html#mysql-replication). This means no supported Disaster Recovery solution if using MySQL.
-1. [Zero downtime migrations][../update/README.md#upgrading-without-downtime] do not work with MySQL.
+1. Geo does [not support MySQL](https://docs.gitlab.com/ee/administration/geo/replication/database.html#mysql-replication). This means no supported Disaster Recovery solution if using MySQL. **[PREMIUM ONLY]**
+1. [Zero downtime migrations](../update/README.md#upgrading-without-downtime) do not work with MySQL.
1. GitLab [optimizes the loading of dashboard events](https://gitlab.com/gitlab-org/gitlab-ce/issues/31806) using [PostgreSQL LATERAL JOINs](https://blog.heapanalytics.com/postgresqls-powerful-new-join-type-lateral/).
1. In general, SQL optimized for PostgreSQL may run much slower in MySQL due to
differences in query planners. For example, subqueries that work well in PostgreSQL
@@ -197,7 +197,13 @@ use the CI features.
## Supported web browsers
-We support the current and the previous major release of Firefox, Chrome/Chromium, Safari and Microsoft browsers (Microsoft Edge and Internet Explorer 11).
+We support the current and the previous major release of:
+
+- Firefox
+- Chrome/Chromium
+- Safari
+- Microsoft Edge
+- Internet Explorer 11
Each time a new browser version is released, we begin supporting that version and stop supporting the third most recent version.
diff --git a/doc/integration/akismet.md b/doc/integration/akismet.md
index a6436b5f926..200fe6f5206 100644
--- a/doc/integration/akismet.md
+++ b/doc/integration/akismet.md
@@ -20,17 +20,17 @@ To use Akismet:
1. Go to the URL: https://akismet.com/account/
-2. Sign-in or create a new account.
+1. Sign-in or create a new account.
-3. Click on **Show** to reveal the API key.
+1. Click on **Show** to reveal the API key.
-4. Go to Applications Settings on Admin Area (`admin/application_settings`)
+1. Go to Applications Settings on Admin Area (`admin/application_settings`)
-5. Check the **Enable Akismet** checkbox
+1. Check the **Enable Akismet** checkbox
-6. Fill in the API key from step 3.
+1. Fill in the API key from step 3.
-7. Save the configuration.
+1. Save the configuration.
![Screenshot of Akismet settings](img/akismet_settings.png)
@@ -42,9 +42,9 @@ To use Akismet:
As a way to better recognize between spam and ham, you can train the Akismet
filter whenever there is a false positive or false negative.
-When an entry is recognized as spam, it is rejected and added to the Spam Logs.
+When an entry is recognized as spam, it is rejected and added to the Spam Logs.
From here you can review if they are really spam. If one of them is not really
-spam, you can use the **Submit as ham** button to tell Akismet that it falsely
+spam, you can use the **Submit as ham** button to tell Akismet that it falsely
recognized an entry as spam.
![Screenshot of Spam Logs](img/spam_log.png)
diff --git a/doc/integration/auth0.md b/doc/integration/auth0.md
index a75836a915a..bccaeec3706 100644
--- a/doc/integration/auth0.md
+++ b/doc/integration/auth0.md
@@ -3,7 +3,7 @@
To enable the Auth0 OmniAuth provider, you must create an Auth0 account, and an
application.
-1. Sign in to the [Auth0 Console](https://manage.auth0.com). If you need to
+1. Sign in to the [Auth0 Console](https://auth0.com/auth/login). If you need to
create an account, you can do so at the same link.
1. Select "New App/API".
diff --git a/doc/integration/bitbucket.md b/doc/integration/bitbucket.md
index bf587b5b296..a69db1d1a6e 100644
--- a/doc/integration/bitbucket.md
+++ b/doc/integration/bitbucket.md
@@ -54,6 +54,7 @@ you to use.
```
Account: Email, Read
+ Projects: Read
Repositories: Read
Pull Requests: Read
Issues: Read
diff --git a/doc/integration/github.md b/doc/integration/github.md
index 680712f9e01..b8156b2b593 100644
--- a/doc/integration/github.md
+++ b/doc/integration/github.md
@@ -1,28 +1,32 @@
-# Integrate your server with GitHub
+# Integrate your GitLab instance with GitHub
-Import projects from GitHub and login to your GitLab instance with your GitHub account.
+You can integrate your GitLab instance with GitHub.com as well as GitHub Enterprise to enable users to import projects from GitHub and/or to login to your GitLab instance with your GitHub account.
-To enable the GitHub OmniAuth provider you must register your application with GitHub.
-GitHub will generate an application ID and secret key for you to use.
+## Enabling GitHub OAuth
-1. Sign in to GitHub.
+To enable GitHub OmniAuth provider, you must use GitHub's credentials for your GitLab instance.
+To get the credentials (a pair of Client ID and Client Secret), you must register an application as an OAuth App on GitHub.
-1. Navigate to your individual user settings or an organization's settings, depending on how you want the application registered. It does not matter if the application is registered as an individual or an organization - that is entirely up to you.
+1. Sign in to GitHub.
-1. Select "OAuth applications" in the left menu.
+1. Navigate to your individual user or organization settings, depending on how you want the application registered. It does not matter if the application is registered as an individual or an organization - that is entirely up to you.
-1. If you already have applications listed, switch to the "Developer applications" tab.
+ - For individual accounts, select **Developer settings** from the left menu, then select **OAuth Apps**.
+ - For organization accounts, directly select **OAuth Apps** from the left menu.
-1. Select "Register new application".
+1. Select **Register an application** (if you don't have any OAuth App) or **New OAuth App** (if you already have OAuth Apps).
+ ![Register OAuth App](img/github_app_entry.png)
1. Provide the required details.
- Application name: This can be anything. Consider something like `<Organization>'s GitLab` or `<Your Name>'s GitLab` or something else descriptive.
- - Homepage URL: The URL to your GitLab installation. 'https://gitlab.company.com'
+ - Homepage URL: the URL to your GitLab installation. e.g., `https://gitlab.company.com`
- Application description: Fill this in if you wish.
- - Authorization callback URL is 'http(s)://${YOUR_DOMAIN}'. Please make sure the port is included if your Gitlab instance is not configured on default port.
-1. Select "Register application".
+ - Authorization callback URL: `http(s)://${YOUR_DOMAIN}`. Please make sure the port is included if your GitLab instance is not configured on default port.
+ ![Register OAuth App](img/github_register_app.png)
+
+1. Select **Register application**.
-1. You should now see a Client ID and Client Secret near the top right of the page (see screenshot).
+1. You should now see a pair of **Client ID** and **Client Secret** near the top right of the page (see screenshot).
Keep this page open as you continue configuration.
![GitHub app](img/github_app.png)
@@ -97,9 +101,9 @@ GitHub will generate an application ID and secret key for you to use.
__Replace `https://github.example.com/` with your GitHub URL.__
-1. Change 'YOUR_APP_ID' to the client ID from the GitHub application page from step 7.
+1. Change `YOUR_APP_ID` to the Client ID from the GitHub application page from step 6.
-1. Change 'YOUR_APP_SECRET' to the client secret from the GitHub application page from step 7.
+1. Change `YOUR_APP_SECRET` to the Client Secret from the GitHub application page from step 6.
1. Save the configuration file.
@@ -154,7 +158,7 @@ You will also need to disable Git SSL verification on the server hosting GitLab.
$ git config --global http.sslVerify false
```
-For the changes to take effect, [reconfigure Gitlab] if you installed
+For the changes to take effect, [reconfigure GitLab] if you installed
via Omnibus, or [restart GitLab] if you installed from source.
[reconfigure GitLab]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
diff --git a/doc/integration/gmail_action_buttons_for_gitlab.md b/doc/integration/gmail_action_buttons_for_gitlab.md
index 05a91d9bef9..c19320471e3 100644
--- a/doc/integration/gmail_action_buttons_for_gitlab.md
+++ b/doc/integration/gmail_action_buttons_for_gitlab.md
@@ -2,7 +2,7 @@
GitLab supports [Google actions in email](https://developers.google.com/gmail/markup/actions/actions-overview).
-If correctly setup, emails that require an action will be marked in Gmail.
+If correctly set up, emails that require an action will be marked in Gmail.
![gmail_actions_button.png](img/gmail_action_buttons_for_gitlab.png)
diff --git a/doc/integration/google.md b/doc/integration/google.md
index 73e2f5826ff..b91d40d4bd4 100644
--- a/doc/integration/google.md
+++ b/doc/integration/google.md
@@ -35,7 +35,7 @@ In Google's side:
1. You should now be able to see a Client ID and Client secret. Note them down
or keep this page open as you will need them later.
-1. From the **Dashboard** select **ENABLE APIS AND SERVICES > Compute > Google+ API > Enable**
+1. From the **Dashboard** select **ENABLE APIS AND SERVICES > Social > Google+ API > Enable**
1. To enable projects to access [Google Kubernetes Engine](../user/project/clusters/index.md), you must also
enable these APIs:
- Google Kubernetes Engine API
diff --git a/doc/integration/img/github_app.png b/doc/integration/img/github_app.png
index d6c289a1de1..4a1523d41ac 100644
--- a/doc/integration/img/github_app.png
+++ b/doc/integration/img/github_app.png
Binary files differ
diff --git a/doc/integration/img/github_app_entry.png b/doc/integration/img/github_app_entry.png
new file mode 100644
index 00000000000..9e151f8cdff
--- /dev/null
+++ b/doc/integration/img/github_app_entry.png
Binary files differ
diff --git a/doc/integration/img/github_register_app.png b/doc/integration/img/github_register_app.png
new file mode 100644
index 00000000000..edd3f660f4e
--- /dev/null
+++ b/doc/integration/img/github_register_app.png
Binary files differ
diff --git a/doc/integration/recaptcha.md b/doc/integration/recaptcha.md
index 932cd479d56..8fdadb008ec 100644
--- a/doc/integration/recaptcha.md
+++ b/doc/integration/recaptcha.md
@@ -8,19 +8,13 @@ to confirm that a real user, not a bot, is attempting to create an account.
To use reCAPTCHA, first you must create a site and private key.
-1. Go to the URL: https://www.google.com/recaptcha/admin
-
-2. Fill out the form necessary to obtain reCAPTCHA keys.
-
-3. Login to your GitLab server, with administrator credentials.
-
-4. Go to Applications Settings on Admin Area (`admin/application_settings`)
-
-5. Fill all recaptcha fields with keys from previous steps
-
-6. Check the `Enable reCAPTCHA` checkbox
-
-7. Save the configuration.
+1. Go to the URL: <https://www.google.com/recaptcha/admin>.
+1. Fill out the form necessary to obtain reCAPTCHA keys.
+1. Login to your GitLab server, with administrator credentials.
+1. Go to Applications Settings on Admin Area (`admin/application_settings`).
+1. Fill all recaptcha fields with keys from previous steps.
+1. Check the `Enable reCAPTCHA` checkbox.
+1. Save the configuration.
## Enabling reCAPTCHA for user logins via passwords
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index e2eea57d694..a7470d27b4b 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -339,6 +339,23 @@ args: {
}
```
+### `uid_attribute`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/43806) in GitLab 10.7.
+
+By default, the `uid` is set as the `name_id` in the SAML response. If you'd like to designate a unique attribute for the `uid`, you can set the `uid_attribute`. In the example below, the value of `uid` attribute in the SAML response is set as the `uid_attribute`.
+
+```yaml
+args: {
+ assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
+ idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
+ idp_sso_target_url: 'https://login.example.com/idp',
+ issuer: 'https://gitlab.example.com',
+ name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
+ uid_attribute: 'uid'
+}
+```
+
## Troubleshooting
### 500 error after login
diff --git a/doc/integration/shibboleth.md b/doc/integration/shibboleth.md
index 41fa63ae6f2..616f3a76b2c 100644
--- a/doc/integration/shibboleth.md
+++ b/doc/integration/shibboleth.md
@@ -4,92 +4,95 @@ This documentation is for enabling shibboleth with omnibus-gitlab package.
In order to enable Shibboleth support in gitlab we need to use Apache instead of Nginx (It may be possible to use Nginx, however this is difficult to configure using the bundled Nginx provided in the omnibus-gitlab package). Apache uses mod_shib2 module for shibboleth authentication and can pass attributes as headers to omniauth-shibboleth provider.
-
-To enable the Shibboleth OmniAuth provider you must:
-
-1. Configure Apache shibboleth module. Installation and configuration of module it self is out of scope of this document.
-Check https://wiki.shibboleth.net/ for more info.
-
-1. You can find Apache config in gitlab-recipes (https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache)
-
-Following changes are needed to enable shibboleth:
-
-protect omniauth-shibboleth callback URL:
-```
- <Location /users/auth/shibboleth/callback>
- AuthType shibboleth
- ShibRequestSetting requireSession 1
- ShibUseHeaders On
- require valid-user
- </Location>
-
- Alias /shibboleth-sp /usr/share/shibboleth
- <Location /shibboleth-sp>
- Satisfy any
- </Location>
-
- <Location /Shibboleth.sso>
- SetHandler shib
- </Location>
-```
-exclude shibboleth URLs from rewriting, add "RewriteCond %{REQUEST_URI} !/Shibboleth.sso" and "RewriteCond %{REQUEST_URI} !/shibboleth-sp", config should look like this:
-```
- # Apache equivalent of Nginx try files
- RewriteEngine on
- RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
- RewriteCond %{REQUEST_URI} !/Shibboleth.sso
- RewriteCond %{REQUEST_URI} !/shibboleth-sp
- RewriteRule .* http://127.0.0.1:8080%{REQUEST_URI} [P,QSA]
- RequestHeader set X_FORWARDED_PROTO 'https'
-```
-
-1. Edit /etc/gitlab/gitlab.rb configuration file to enable OmniAuth and add
-Shibboleth as an OmniAuth provider. User attributes will be sent from the
-Apache reverse proxy to GitLab as headers with the names from the Shibboleth
-attribute mapping. Therefore the values of the `args` hash
-should be in the form of `"HTTP_ATTRIBUTE"`. The keys in the hash are arguments
-to the [OmniAuth::Strategies::Shibboleth class](https://github.com/toyokazu/omniauth-shibboleth/blob/master/lib/omniauth/strategies/shibboleth.rb)
-and are documented by the [omniauth-shibboleth gem](https://github.com/toyokazu/omniauth-shibboleth)
-(take care to note the version of the gem packaged with GitLab). If some of
-your users appear to be authenticated by Shibboleth and Apache, but GitLab
-rejects their account with a URI that contains "e-mail is invalid" then your
-Shibboleth Identity Provider or Attribute Authority may be asserting multiple
-e-mail addresses. In this instance, you might consider setting the
-`multi_values` argument to `first`.
-
-File should look like this:
-```
-external_url 'https://gitlab.example.com'
-gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
-
-# disable Nginx
-nginx['enable'] = false
-
-gitlab_rails['omniauth_allow_single_sign_on'] = true
-gitlab_rails['omniauth_block_auto_created_users'] = false
-gitlab_rails['omniauth_enabled'] = true
-gitlab_rails['omniauth_providers'] = [
- {
- "name" => "'shibboleth"',
- "label" => "Text for Login Button",
- "args" => {
- "shib_session_id_field" => "HTTP_SHIB_SESSION_ID",
- "shib_application_id_field" => "HTTP_SHIB_APPLICATION_ID",
- "uid_field" => 'HTTP_EPPN',
- "name_field" => 'HTTP_CN',
- "info_fields" => { "email" => 'HTTP_MAIL'}
- }
- }
-]
-
-```
-
-1. [Reconfigure][] or [restart GitLab][] for the changes to take effect if you
+To enable the Shibboleth OmniAuth provider you must configure Apache shibboleth module.
+Installation and configuration of module it self is out of scope of this document.
+Check <https://wiki.shibboleth.net/> for more info.
+
+You can find Apache config in gitlab-recipes (<https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache>).
+
+The following changes are needed to enable Shibboleth:
+
+1. Protect omniauth-shibboleth callback URL:
+
+ ```
+ <Location /users/auth/shibboleth/callback>
+ AuthType shibboleth
+ ShibRequestSetting requireSession 1
+ ShibUseHeaders On
+ require valid-user
+ </Location>
+
+ Alias /shibboleth-sp /usr/share/shibboleth
+ <Location /shibboleth-sp>
+ Satisfy any
+ </Location>
+
+ <Location /Shibboleth.sso>
+ SetHandler shib
+ </Location>
+ ```
+
+1. Exclude shibboleth URLs from rewriting. Add `RewriteCond %{REQUEST_URI} !/Shibboleth.sso` and `RewriteCond %{REQUEST_URI} !/shibboleth-sp`. Config should look like this:
+
+ ```
+ # Apache equivalent of Nginx try files
+ RewriteEngine on
+ RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
+ RewriteCond %{REQUEST_URI} !/Shibboleth.sso
+ RewriteCond %{REQUEST_URI} !/shibboleth-sp
+ RewriteRule .* http://127.0.0.1:8080%{REQUEST_URI} [P,QSA]
+ RequestHeader set X_FORWARDED_PROTO 'https'
+ ```
+
+1. Edit `/etc/gitlab/gitlab.rb` configuration file to enable OmniAuth and add
+ Shibboleth as an OmniAuth provider. User attributes will be sent from the
+ Apache reverse proxy to GitLab as headers with the names from the Shibboleth
+ attribute mapping. Therefore the values of the `args` hash
+ should be in the form of `"HTTP_ATTRIBUTE"`. The keys in the hash are arguments
+ to the [OmniAuth::Strategies::Shibboleth class](https://github.com/toyokazu/omniauth-shibboleth/blob/master/lib/omniauth/strategies/shibboleth.rb)
+ and are documented by the [omniauth-shibboleth gem](https://github.com/toyokazu/omniauth-shibboleth)
+ (take care to note the version of the gem packaged with GitLab). If some of
+ your users appear to be authenticated by Shibboleth and Apache, but GitLab
+ rejects their account with a URI that contains "e-mail is invalid" then your
+ Shibboleth Identity Provider or Attribute Authority may be asserting multiple
+ e-mail addresses. In this instance, you might consider setting the
+ `multi_values` argument to `first`.
+
+ The file should look like this:
+
+ ```
+ external_url 'https://gitlab.example.com'
+ gitlab_rails['internal_api_url'] = 'https://gitlab.example.com'
+
+ # disable Nginx
+ nginx['enable'] = false
+
+ gitlab_rails['omniauth_allow_single_sign_on'] = true
+ gitlab_rails['omniauth_block_auto_created_users'] = false
+ gitlab_rails['omniauth_enabled'] = true
+ gitlab_rails['omniauth_providers'] = [
+ {
+ "name" => "'shibboleth"',
+ "label" => "Text for Login Button",
+ "args" => {
+ "shib_session_id_field" => "HTTP_SHIB_SESSION_ID",
+ "shib_application_id_field" => "HTTP_SHIB_APPLICATION_ID",
+ "uid_field" => 'HTTP_EPPN',
+ "name_field" => 'HTTP_CN',
+ "info_fields" => { "email" => 'HTTP_MAIL'}
+ }
+ }
+ ]
+
+ ```
+
+1. [Reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart](../administration/restart_gitlab.md#installations-from-source) GitLab for the changes to take effect if you
installed GitLab via Omnibus or from source respectively.
-On the sign in page there should now be a "Sign in with: Shibboleth" icon below the regular sign in form. Click the icon to begin the authentication process. You will be redirected to IdP server (Depends on your Shibboleth module configuration). If everything goes well the user will be returned to GitLab and will be signed in.
+On the sign in page, there should now be a "Sign in with: Shibboleth" icon below the regular sign in form. Click the icon to begin the authentication process. You will be redirected to IdP server (depends on your Shibboleth module configuration). If everything goes well the user will be returned to GitLab and will be signed in.
## Apache 2.4 / GitLab 8.6 update
+
The order of the first 2 Location directives is important. If they are reversed,
you will not get a shibboleth session!
@@ -135,6 +138,3 @@ you will not get a shibboleth session!
RequestHeader set X_FORWARDED_PROTO 'https'
RequestHeader set X-Forwarded-Ssl on
```
-
-[reconfigure]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
-[restart GitLab]: ../administration/restart_gitlab.md#installations-from-source
diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md
index fc7b97b3cc2..03ba2ae8817 100644
--- a/doc/policy/maintenance.md
+++ b/doc/policy/maintenance.md
@@ -75,7 +75,8 @@ Please see the table below for some examples:
| Latest stable version | Your version | Recommended upgrade path | Note |
| -------------- | ------------ | ------------------------ | ---------------- |
| 9.4.5 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.4.5` | `8.17.7` is the last version in version `8` |
-| 10.1.4 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.5.8` -> `10.1.4` | `8.17.7` is the last version in version `8`, `9.5.8` is the last version in version `9` |
+| 10.1.4 | 8.13.4 | `8.13.4 -> 8.17.7 -> 9.5.10 -> 10.1.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9` |
+| 11.3.4 | 8.13.4 | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version `8`, `9.5.10` is the last version in version `9`, `10.8.7` is the last version in version `10` |
More information about the release procedures can be found in our
[release-tools documentation][rel]. You may also want to read our
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index 1d29f6d4e43..a63656fafef 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -9,37 +9,39 @@ You can only restore a backup to **exactly the same version and type (CE/EE)**
of GitLab on which it was created. The best way to migrate your repositories
from one server to another is through backup restore.
-## Backup
+## Requirements
-GitLab provides a simple command line interface to backup your whole installation,
-and is flexible enough to fit your needs.
+In order to be able to backup and restore, you need two essential tools
+installed on your system.
-### Requirements
+### Rsync
-* rsync
+If you installed GitLab:
-If you're using GitLab with the Omnibus package, you're all set. If you
-installed GitLab from source, make sure you have rsync installed.
+- Using the Omnibus package, you're all set.
+- From source, make sure `rsync` is installed:
-If you're using Ubuntu, you could run:
+ ```sh
+ # Debian/Ubuntu
+ sudo apt-get install rsync
-```
-sudo apt-get install -y rsync
-```
+ # RHEL/CentOS
+ sudo yum install rsync
+ ```
-* tar
+### Tar
Backup and restore tasks use `tar` under the hood to create and extract
archives. Ensure you have version 1.30 or above of `tar` available in your
system. To check the version, run:
-```
+```sh
tar --version
```
-### Backup timestamp
+## Backup timestamp
->**Note:**
+NOTE: **Note:**
In GitLab 9.2 the timestamp format was changed from `EPOCH_YYYY_MM_DD` to
`EPOCH_YYYY_MM_DD_GitLab_version`, for example `1493107454_2018_04_25`
would become `1493107454_2018_04_25_10.6.4-ce`.
@@ -54,31 +56,48 @@ available.
For example, if the backup name is `1493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar`,
then the timestamp is `1493107454_2018_04_25_10.6.4-ce`.
-### Creating a backup of the GitLab system
+## Creating a backup of the GitLab system
+
+GitLab provides a simple command line interface to backup your whole instance.
+It backs up your:
+
+- Database
+- Attachments
+- Git repositories data
+- CI/CD job output logs
+- CI/CD job artifacts
+- LFS objects
+- Container Registry images
+- GitLab Pages content
+
+CAUTION: **Warning:**
+GitLab does not back up any configuration files, SSL certificates, or system files.
+You are highly advised to [read about storing configuration files](#storing-configuration-files).
Use this command if you've installed GitLab with the Omnibus package:
-```
+```sh
sudo gitlab-rake gitlab:backup:create
```
Use this if you've installed GitLab from source:
-```
+```sh
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
If you are running GitLab within a Docker container, you can run the backup from the host:
-```
+```sh
docker exec -t <container name> gitlab-rake gitlab:backup:create
```
-If you are using the gitlab-omnibus helm chart on a Kubernetes cluster, you can
-run the backup task on the gitlab application pod using kubectl
+If you are using the [GitLab helm chart](https://gitlab.com/charts/gitlab) on a
+Kubernetes cluster, you can run the backup task using `backup-utility` script on
+the gitlab task runner pod via `kubectl`. Refer to [backing up a GitLab installation](https://gitlab.com/charts/gitlab/blob/master/doc/backup-restore/backup.md#backing-up-a-gitlab-installation) for more details:
-```
-kubectl exec -it <gitlab-gitlab pod> gitlab-rake gitlab:backup:create
+```sh
+kubectl exec -it <gitlab task-runner pod> backup-utility
```
Example output:
@@ -110,9 +129,50 @@ Deleting tmp directories...[DONE]
Deleting old backups... [SKIPPING]
```
+## Storing configuration files
+
+A backup performed by the [raketask GitLab provides](#creating-a-backup-of-the-gitlab-system)
+does **not** store your configuration files. The primary reason for this is that your
+database contains encrypted information for two-factor authentication, the CI/CD
+'secure variables', etc. Storing encrypted information along with its key in the
+same place defeats the purpose of using encryption in the first place.
+
+CAUTION: **Warning:**
+The secrets file is essential to preserve your database encryption key.
+
+At the very **minimum**, you must backup:
+
+For Omnibus:
+
+- `/etc/gitlab/gitlab-secrets.json`
+- `/etc/gitlab/gitlab.rb`
+
+For installation from source:
+
+- `/home/git/gitlab/config/secrets.yml`
+- `/home/git/gitlab/config/gitlab.yml`
+
+For [Docker installations](https://docs.gitlab.com/omnibus/docker/), you must
+back up the volume where the configuration files are stored. If you have created
+the GitLab container according to the documentation, it should be under
+`/srv/gitlab/config`.
+
+You may also want to back up any TLS keys and certificates, and your
+[SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079).
+
+If you use Omnibus GitLab, see some additional information
+[to backup your configuration](https://docs.gitlab.com/omnibus/settings/backups.html).
+
+In the unlikely event that the secrets file is lost, see the
+[troubleshooting section](#when-the-secrets-file-is-lost).
+
+## Backup options
+
+The command line tool GitLab provides to backup your instance can take more options.
+
### Backup strategy option
-> **Note:** Introduced as an option in GitLab 8.17.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8728) in GitLab 8.17.
The default backup strategy is to essentially stream data from the respective
data locations to the backup using the Linux command `tar` and `gzip`. This works
@@ -129,8 +189,11 @@ so the problem doesn't compound, but it could be a considerable change for large
installations. This is why the `copy` strategy is not the default in 8.17.
To use the `copy` strategy instead of the default streaming strategy, specify
-`STRATEGY=copy` in the Rake task command. For example,
-`sudo gitlab-rake gitlab:backup:create STRATEGY=copy`.
+`STRATEGY=copy` in the Rake task command. For example:
+
+```sh
+sudo gitlab-rake gitlab:backup:create STRATEGY=copy
+```
### Excluding specific directories from the backup
@@ -151,11 +214,15 @@ Use a comma to specify several options at the same time:
All wikis will be backed up as part of the `repositories` group. Non-existent wikis
will be skipped during a backup.
-```
-# use this command if you've installed GitLab with the Omnibus package
+For Omnibus GitLab packages:
+
+```sh
sudo gitlab-rake gitlab:backup:create SKIP=db,uploads
+```
+
+For installations from source:
-# if you've installed GitLab from source
+```sh
sudo -u git -H bundle exec rake gitlab:backup:create SKIP=db,uploads RAILS_ENV=production
```
@@ -208,7 +275,7 @@ This example can be used for a bucket in Amsterdam (AMS3).
1. [Reconfigure GitLab] for the changes to take effect
-CAUTION: **Warning:**
+NOTE: **Note:**
If you see `400 Bad Request` by using Digital Ocean Spaces, the cause may be the
usage of backup encryption. Remove or comment the line that
contains `gitlab_rails['backup_encryption']` since Digital Ocean Spaces
@@ -370,33 +437,43 @@ backups will be copied to, and will be created if it does not exist. If the
directory that you want to copy the tarballs to is the root of your mounted
directory, just use `.` instead.
-For omnibus packages:
-```ruby
-gitlab_rails['backup_upload_connection'] = {
- :provider => 'Local',
- :local_root => '/mnt/backups'
-}
+For Omnibus GitLab packages:
-# The directory inside the mounted folder to copy backups to
-# Use '.' to store them in the root directory
-gitlab_rails['backup_upload_remote_directory'] = 'gitlab_backups'
-```
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ gitlab_rails['backup_upload_connection'] = {
+ :provider => 'Local',
+ :local_root => '/mnt/backups'
+ }
+
+ # The directory inside the mounted folder to copy backups to
+ # Use '.' to store them in the root directory
+ gitlab_rails['backup_upload_remote_directory'] = 'gitlab_backups'
+ ```
+
+1. [Reconfigure GitLab] for the changes to take effect.
+
+---
For installations from source:
-```yaml
- backup:
- # snip
- upload:
- # Fog storage connection settings, see http://fog.io/storage/ .
- connection:
- provider: Local
- local_root: '/mnt/backups'
- # The directory inside the mounted folder to copy backups to
- # Use '.' to store them in the root directory
- remote_directory: 'gitlab_backups'
-```
+1. Edit `home/git/gitlab/config/gitlab.yml`:
+
+ ```yaml
+ backup:
+ upload:
+ # Fog storage connection settings, see http://fog.io/storage/ .
+ connection:
+ provider: Local
+ local_root: '/mnt/backups'
+ # The directory inside the mounted folder to copy backups to
+ # Use '.' to store them in the root directory
+ remote_directory: 'gitlab_backups'
+ ```
+
+1. [Restart GitLab] for the changes to take effect.
### Backup archive permissions
@@ -405,45 +482,56 @@ will have owner/group git:git and 0600 permissions by default.
This is meant to avoid other system users reading GitLab's data.
If you need the backup archives to have different permissions you can use the 'archive_permissions' setting.
-```
-# In /etc/gitlab/gitlab.rb, for omnibus packages
-gitlab_rails['backup_archive_permissions'] = 0644 # Makes the backup archives world-readable
-```
+For Omnibus GitLab packages:
-```
-# In gitlab.yml, for installations from source:
- backup:
- archive_permissions: 0644 # Makes the backup archives world-readable
-```
+1. Edit `/etc/gitlab/gitlab.rb`:
-### Storing configuration files
+ ```ruby
+ gitlab_rails['backup_archive_permissions'] = 0644 # Makes the backup archives world-readable
+ ```
-Please be informed that a backup does not store your configuration
-files. One reason for this is that your database contains encrypted
-information for two-factor authentication. Storing encrypted
-information along with its key in the same place defeats the purpose
-of using encryption in the first place!
+1. [Reconfigure GitLab] for the changes to take effect.
-If you use an Omnibus package please see the [instructions in the readme to backup your configuration](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md#backup-and-restore-omnibus-gitlab-configuration).
-If you have a cookbook installation there should be a copy of your configuration in Chef.
-If you installed from source, please consider backing up your `config/secrets.yml` file, `gitlab.yml` file, any SSL keys and certificates, and your [SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079).
+---
-At the very **minimum** you should backup `/etc/gitlab/gitlab.rb` and
-`/etc/gitlab/gitlab-secrets.json` (Omnibus), or
-`/home/git/gitlab/config/secrets.yml` (source) to preserve your database
-encryption key.
+For installations from source:
+
+1. Edit `/home/git/gitlab/config/gitlab.yml`:
+
+ ```yaml
+ backup:
+ archive_permissions: 0644 # Makes the backup archives world-readable
+ ```
+
+1. [Restart GitLab] for the changes to take effect.
### Configuring cron to make daily backups
->**Note:**
+NOTE: **Note:**
The following cron jobs do not [backup your GitLab configuration files](#storing-configuration-files)
or [SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079).
-**For Omnibus installations**
+For Omnibus GitLab packages:
+
+1. Edit `/etc/gitlab/gitlab.rb`:
+
+ ```ruby
+ ## Limit backup lifetime to 7 days - 604800 seconds
+ gitlab_rails['backup_keep_time'] = 604800
+ ```
+
+1. [Reconfigure GitLab] for the changes to take effect.
+
+Note that the `backup_keep_time` configuration option only manages local
+files. GitLab does not automatically prune old files stored in a third-party
+object storage (e.g., AWS S3) because the user may not have permission to list
+and delete files. We recommend that you configure the appropriate retention
+policy for your object storage. For example, you can configure [the S3 backup
+policy as described here](http://stackoverflow.com/questions/37553070/gitlab-omnibus-delete-backup-from-amazon-s3).
To schedule a cron job that backs up your repositories and GitLab metadata, use the root user:
-```
+```sh
sudo su -
crontab -e
```
@@ -455,26 +543,24 @@ There, add the following line to schedule the backup for everyday at 2 AM:
```
You may also want to set a limited lifetime for backups to prevent regular
-backups using all your disk space. To do this add the following lines to
-`/etc/gitlab/gitlab.rb` and reconfigure:
+backups using all your disk space.
-```
-# limit backup lifetime to 7 days - 604800 seconds
-gitlab_rails['backup_keep_time'] = 604800
-```
+---
-Note that the `backup_keep_time` configuration option only manages local
-files. GitLab does not automatically prune old files stored in a third-party
-object storage (e.g., AWS S3) because the user may not have permission to list
-and delete files. We recommend that you configure the appropriate retention
-policy for your object storage. For example, you can configure [the S3 backup
-policy as described here](http://stackoverflow.com/questions/37553070/gitlab-omnibus-delete-backup-from-amazon-s3).
+For installations from source:
+
+1. Edit `home/git/gitlab/config/gitlab.yml`:
-**For installation from source**
+ ```yaml
+ backup:
+ ## Limit backup lifetime to 7 days - 604800 seconds
+ keep_time: 604800
+ ```
-```
-cd /home/git/gitlab
-sudo -u git -H editor config/gitlab.yml # Enable keep_time in the backup section to automatically delete old backups
+1. [Restart GitLab] for the changes to take effect.
+
+
+```sh
sudo -u git crontab -e # Edit the crontab for the git user
```
@@ -518,12 +604,14 @@ If you fail to restore this encryption key file along with the application data
backup, users with two-factor authentication enabled and GitLab Runners will
lose access to your GitLab server.
+You may also want to restore any TLS keys, certificates, or [SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079).
+
Depending on your case, you might want to run the restore command with one or
more of the following options:
- `BACKUP=timestamp_of_backup` - Required if more than one backup exists.
Read what the [backup timestamp is about](#backup-timestamp).
-- `force=yes` - Does not ask if the authorized_keys file should get regenerated and assumes 'yes' for warning that database tables will be removed.
+- `force=yes` - Does not ask if the authorized_keys file should get regenerated and assumes 'yes' for warning that database tables will be removed, enabling the "Write to authorized_keys file" setting, and updating LDAP providers.
If you are restoring into directories that are mountpoints you will need to make
sure these directories are empty before attempting a restore. Otherwise GitLab
@@ -580,7 +668,7 @@ Restart GitLab:
sudo service gitlab restart
```
-### Restore for Omnibus installations
+### Restore for Omnibus GitLab installations
This procedure assumes that:
@@ -591,10 +679,11 @@ This procedure assumes that:
First make sure your backup tar file is in the backup directory described in the
`gitlab.rb` configuration `gitlab_rails['backup_path']`. The default is
-`/var/opt/gitlab/backups`.
+`/var/opt/gitlab/backups`. It needs to be owned by the `git` user.
```shell
sudo cp 11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar /var/opt/gitlab/backups/
+sudo chown git.git /var/opt/gitlab/backups/11493107454_2018_04_25_10.6.4-ce_gitlab_backup.tar
```
Stop the processes that are connected to the database. Leave the rest of GitLab
@@ -628,10 +717,10 @@ If there is a GitLab version mismatch between your backup tar file and the insta
version of GitLab, the restore command will abort with an error. Install the
[correct GitLab version](https://packages.gitlab.com/gitlab/) and try again.
-### Restore for Docker image and gitlab-omnibus helm chart
+### Restore for Docker image and GitLab helm chart installations
-For GitLab installations using docker image or the gitlab-omnibus helm chart on
-a Kubernetes cluster, restore task expects the restore directories to be empty.
+For GitLab installations using the Docker image or the GitLab helm chart on
+a Kubernetes cluster, the restore task expects the restore directories to be empty.
However, with docker and Kubernetes volume mounts, some system level directories
may be created at the volume roots, like `lost+found` directory found in Linux
operating systems. These directories are usually owned by `root`, which can
@@ -642,19 +731,14 @@ directories are empty.
For both these installation types, the backup tarball has to be available in the
backup location (default location is `/var/opt/gitlab/backups`).
-For docker installations, the restore task can be run from host using the
-command
+For docker installations, the restore task can be run from host:
-```
+```sh
docker exec -it <name of container> gitlab-rake gitlab:backup:restore
```
-Similarly, for gitlab-omnibus helm chart, the restore task can be run on the
-gitlab application pod using kubectl
-
-```
-kubectl exec -it <gitlab-gitlab pod> gitlab-rake gitlab:backup:restore
-```
+The GitLab helm chart uses a different process, documented in
+[restoring a GitLab helm chart installation](https://gitlab.com/charts/gitlab/blob/master/doc/backup-restore/restore.md).
## Alternative backup strategies
@@ -710,5 +794,53 @@ Those objects have no influence on the database backup/restore but they give thi
For more information see similar questions on postgresql issue tracker[here](http://www.postgresql.org/message-id/201110220712.30886.adrian.klaver@gmail.com) and [here](http://www.postgresql.org/message-id/2039.1177339749@sss.pgh.pa.us) as well as [stack overflow](http://stackoverflow.com/questions/4368789/error-must-be-owner-of-language-plpgsql).
+### When the secrets file is lost
+
+If you have failed to [back up the secrets file](#storing-configuration-files),
+then users with 2FA enabled will not be able to log into GitLab. In that case,
+you need to [disable 2FA for everyone](../security/two_factor_authentication.md#disabling-2fa-for-everyone).
+
+In the case of CI/CD, if your project has secure variables set, you might experience
+some weird behavior, like stuck jobs or 500 errors. In that case, you can try
+deleting the `ci_variables` table from the database.
+
+CAUTION: **Warning:**
+Use the following commands at your own risk, and make sure you've taken a
+backup beforehand.
+
+1. Enter the Rails console:
+
+ For Omnibus GitLab packages:
+
+ ```sh
+ sudo gitlab-rails dbconsole
+ ```
+
+ For installations from source:
+
+ ```sh
+ sudo -u git -H bundle exec rails dbconsole RAILS_ENV=production
+ ```
+
+1. Check the `ci_variables` table:
+
+ ```sql
+ SELECT * FROM public."ci_variables";
+ ```
+
+ Those are the variables that you need to delete.
+
+1. Drop the table:
+
+ ```sql
+ DELETE FROM ci_variables;
+ ```
+
+1. You may need to reconfigure or restart GitLab for the changes to take
+ effect.
+
+You should now be able to visit your project, and the jobs will start
+running again.
+
[reconfigure GitLab]: ../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
[restart GitLab]: ../administration/restart_gitlab.md#installations-from-source
diff --git a/doc/raketasks/import.md b/doc/raketasks/import.md
index 97e9b36d1a6..bb316df5b9a 100644
--- a/doc/raketasks/import.md
+++ b/doc/raketasks/import.md
@@ -6,6 +6,7 @@
- The groups will be created as needed, including subgroups
- The owner of the group will be the first admin
- Existing projects will be skipped
+- Projects in hashed storage may be skipped (see [Importing bare repositories from hashed storage](#importing-bare-repositories-from-hashed-storage))
- The existing Git repos will be moved from disk (removed from the original path)
## How to use
@@ -26,7 +27,6 @@ sudo -u git mkdir /var/opt/gitlab/git-data/repository-import-<date>/new_group
If we copy the repos to `/var/opt/gitlab/git-data/repository-import-<date>`, and repo A needs to be under the groups G1 and G2, it will
have to be created under those folders: `/var/opt/gitlab/git-data/repository-import-<date>/G1/G2/A.git`.
-
```
sudo cp -r /old/git/foo.git /var/opt/gitlab/git-data/repository-import-<date>/new_group/
@@ -70,3 +70,73 @@ Processing /var/opt/gitlab/git-data/repository-import-1/group/xyz.git
* Skipping repo /var/opt/gitlab/git-data/repository-import-1/@shared/a/b/abcd.git
[...]
```
+
+## Importing bare repositories from hashed storage
+
+### Background
+
+Projects in legacy storage have a directory structure that mirrors their full
+project path in GitLab, including their namespace structure. This information is
+leveraged by the bare repository importer to import projects into their proper
+locations. Each project and its parent namespaces are meaningfully named.
+
+However, the directory structure of projects in hashed storage do not contain
+this information. This is beneficial for a variety of reasons, especially
+improved performance and data integrity. See
+[Repository Storage Types](../administration/repository_storage_types.md) for
+more details.
+
+### Which repositories are importable?
+
+#### GitLab 10.3 or earlier
+
+Importing bare repositories from hashed storage is unsupported.
+
+#### GitLab 10.4 and later
+
+To support importing bare repositories from hashed storage, GitLab 10.4 and
+later stores the full project path with each repository, in a special section of
+the git repository's config file. This section is formatted as follows:
+
+```
+[gitlab]
+ fullpath = gitlab-org/gitlab-ce
+```
+
+However, existing repositories were not migrated to include this path.
+
+Bare repositories are importable if the following events occurred to the
+repository in GitLab 10.4 and later:
+
+- Created
+- Migrated to hashed storage
+- Renamed
+- Transferred to another namespace
+- Ancestor renamed
+- Ancestor transferred to another namespace
+
+Bare repositories are **not** importable by GitLab 10.4 and later when all the following are true about the repository:
+
+- It was created in GitLab 10.3 or earlier.
+- It was not renamed, transferred, or migrated to hashed storage in GitLab 10.4 and later.
+- Its ancestor namespaces were not renamed or transferred in GitLab 10.4 and later.
+
+There is an [open issue to add a migration to make all bare repositories
+importable](https://gitlab.com/gitlab-org/gitlab-ce/issues/41776).
+
+Until then, you may wish to manually migrate repositories yourself. You can use
+[Rails console](https://docs.gitlab.com/omnibus/maintenance/#starting-a-rails-console-session)
+to do so. In a Rails console session, run the following to migrate a project:
+
+```
+project = Project.find_by_full_path('gitlab-org/gitlab-ce')
+project.write_repository_config
+```
+
+In a Rails console session, run the following to migrate all of a namespace's
+projects (this may take a while if there are 1000s of projects in a namespace):
+
+```
+namespace = Namespace.find_by_full_path('gitlab-org')
+namespace.send(:write_projects_repository_config)
+```
diff --git a/doc/security/rack_attack.md b/doc/security/rack_attack.md
index 3efb19c1526..dcdc9f42c22 100644
--- a/doc/security/rack_attack.md
+++ b/doc/security/rack_attack.md
@@ -10,7 +10,7 @@ Rack Attack offers IP whitelisting, blacklisting, Fail2ban style filtering and
tracking.
**Note:** Starting with 11.2, Rack Attack is disabled by default. To continue
-using this feature, please enable it in your `gitlab.rb` by setting
+using this feature, please enable it in your `gitlab.rb` by setting
`gitlab_rails['rack_attack_git_basic_auth'] = true`.
By default, user sign-in, user sign-up (if enabled), and user password reset is
@@ -35,13 +35,13 @@ For more information on how to use these options check out
gitlab_rails['rack_attack_git_basic_auth'] = {
'enabled' => true,
'ip_whitelist' => ["127.0.0.1"],
- 'maxretry' => 10,
- 'findtime' => 60,
- 'bantime' => 3600
+ 'maxretry' => 10, # Limit the number of Git HTTP authentication attempts per IP
+ 'findtime' => 60, # Reset the auth attempt counter per IP after 60 seconds
+ 'bantime' => 3600 # Ban an IP for one hour (3600s) after too many auth attempts
}
```
-3. Reconfigure GitLab:
+1. Reconfigure GitLab:
```
sudo gitlab-ctl reconfigure
@@ -55,9 +55,9 @@ The following settings can be configured:
- `maxretry`: The maximum amount of times a request can be made in the
specified time.
- `findtime`: The maximum amount of time failed requests can count against an IP
- before it's blacklisted.
-- `bantime`: The total amount of time that a blacklisted IP will be blocked in
- seconds.
+ before it's blacklisted (in seconds).
+- `bantime`: The total amount of time that a blacklisted IP will be blocked (in
+ seconds).
**Installations from source**
@@ -98,26 +98,26 @@ In case you want to remove a blocked IP, follow these steps:
grep "Rack_Attack" /var/log/gitlab/gitlab-rails/production.log
```
-2. Since the blacklist is stored in Redis, you need to open up `redis-cli`:
+1. Since the blacklist is stored in Redis, you need to open up `redis-cli`:
```sh
/opt/gitlab/embedded/bin/redis-cli -s /var/opt/gitlab/redis/redis.socket
```
-3. You can remove the block using the following syntax, replacing `<ip>` with
+1. You can remove the block using the following syntax, replacing `<ip>` with
the actual IP that is blacklisted:
```
del cache:gitlab:rack::attack:allow2ban:ban:<ip>
```
-4. Confirm that the key with the IP no longer shows up:
+1. Confirm that the key with the IP no longer shows up:
```
keys *rack::attack*
```
-5. Optionally, add the IP to the whitelist to prevent it from being blacklisted
+1. Optionally, add the IP to the whitelist to prevent it from being blacklisted
again (see [settings](#settings)).
## Troubleshooting
@@ -129,11 +129,11 @@ the load balancer. In that case, you will need to:
1. [Configure `nginx[real_ip_trusted_addresses]`](https://docs.gitlab.com/omnibus/settings/nginx.html#configuring-gitlab-trusted_proxies-and-the-nginx-real_ip-module).
This will keep users' IPs from being listed as the load balancer IPs.
-2. Whitelist the load balancer's IP address(es) in the Rack Attack [settings](#settings).
-3. Reconfigure GitLab:
+1. Whitelist the load balancer's IP address(es) in the Rack Attack [settings](#settings).
+1. Reconfigure GitLab:
```
sudo gitlab-ctl reconfigure
```
-4. [Remove the block via Redis.](#remove-blocked-ips-from-rack-attack-via-redis)
+1. [Remove the block via Redis.](#remove-blocked-ips-from-rack-attack-via-redis)
diff --git a/doc/security/two_factor_authentication.md b/doc/security/two_factor_authentication.md
index f02f7b807cf..b770f2544d2 100644
--- a/doc/security/two_factor_authentication.md
+++ b/doc/security/two_factor_authentication.md
@@ -11,10 +11,10 @@ You can read more about it here:
## Enforcing 2FA for all users
Users on GitLab, can enable it without any admin's intervention. If you want to
-enforce everyone to setup 2FA, you can choose from two different ways:
+enforce everyone to set up 2FA, you can choose from two different ways:
- 1. Enforce on next login
- 2. Suggest on next login, but allow a grace period before enforcing.
+- Enforce on next login.
+- Suggest on next login, but allow a grace period before enforcing.
In the Admin area under **Settings** (`/admin/application_settings`), look for
the "Sign-in Restrictions" area, where you can configure both.
diff --git a/doc/security/user_email_confirmation.md b/doc/security/user_email_confirmation.md
index 48c79cd4769..8c07e11dcb1 100644
--- a/doc/security/user_email_confirmation.md
+++ b/doc/security/user_email_confirmation.md
@@ -1,6 +1,6 @@
# User email confirmation at sign-up
-Gitlab admin can enable email confirmation on sign-up, if you want to confirm all
+GitLab admin can enable email confirmation on sign-up, if you want to confirm all
user emails before they are able to sign-in.
In the Admin area under **Settings** (`/admin/application_settings`), go to section
diff --git a/doc/ssh/README.md b/doc/ssh/README.md
index 5db042326f3..d9ae3c08172 100644
--- a/doc/ssh/README.md
+++ b/doc/ssh/README.md
@@ -8,163 +8,224 @@ you need a secure communication channel for sharing information.
The SSH protocol provides this security and allows you to authenticate to the
GitLab remote server without supplying your username or password each time.
-For a more detailed explanation of how the SSH protocol works, we advise you to
-read [this nice tutorial by DigitalOcean](https://www.digitalocean.com/community/tutorials/understanding-the-ssh-encryption-and-connection-process).
+For a more detailed explanation of how the SSH protocol works, read
+[this nice tutorial by DigitalOcean](https://www.digitalocean.com/community/tutorials/understanding-the-ssh-encryption-and-connection-process).
-## Locating an existing SSH key pair
+## Requirements
-Before generating a new SSH key pair check if your system already has one
-at the default location by opening a shell, or Command Prompt on Windows,
-and running the following command:
+The only requirement is to have the OpenSSH client installed on your system. This
+comes pre-installed on GNU/Linux and macOS, but not on Windows.
-**Windows Command Prompt:**
+Depending on your Windows version, there are different methods to work with
+SSH keys.
-```bash
-type %userprofile%\.ssh\id_rsa.pub
-```
+### Installing the SSH client for Windows 10
-**Git Bash on Windows / GNU/Linux / macOS / PowerShell:**
+Starting with Windows 10, you can
+[install the Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install-win10)
+where you can run Linux distributions directly on Windows, without the overhead
+of a virtual machine. Once installed and set up, you'll have the Git and SSH
+clients at your disposal.
-```bash
-cat ~/.ssh/id_rsa.pub
-```
+### Installing the SSH client for Windows 8.1 and Windows 7
+
+The easiest way to install Git and the SSH client on Windows 8.1 and Windows 7
+is [Git for Windows](https://gitforwindows.org). It provides a BASH
+emulation (Git Bash) used for running Git from the command line and the
+`ssh-keygen` command that is useful to create SSH keys as you'll learn below.
+
+NOTE: **Alternative tools:**
+Although not explored in this page, you can use some alternative tools.
+[Cygwin](https://www.cygwin.com) is a large collection of GNU and open source
+tools which provide functionality similar to a Unix distribution.
+[PuttyGen](https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html)
+provides a graphical user interface to [create SSH keys](https://tartarus.org/~simon/putty-snapshots/htmldoc/Chapter8.html#pubkey-puttygen).
+
+## Types of SSH keys and which to choose
+
+GitLab supports RSA, DSA, ECDSA, and ED25519 keys. Their difference lies on
+the signing algorithm, and some of them have advantages over the others. For
+more information, you can read this
+[nice article on ArchWiki](https://wiki.archlinux.org/index.php/SSH_keys#Choosing_the_authentication_key_type).
+We'll focus on ED25519 and RSA and here.
+
+NOTE: **Note:**
+As an admin, you can restrict
+[which keys should be permitted and their minimum length](../security/ssh_keys_restrictions.md).
+By default, all keys are permitted, which is also the case for
+[GitLab.com](../user/gitlab_com/index.md#ssh-host-keys-fingerprints).
-If you see a string starting with `ssh-rsa` you already have an SSH key pair
-and you can skip the generate portion of the next section and skip to the copy
-to clipboard step.
-If you don't see the string or would like to generate a SSH key pair with a
-custom name continue onto the next step.
+## ED25519 SSH keys
-Note that Public SSH key may also be named as follows:
+Following [best practices](https://linux-audit.com/using-ed25519-openssh-keys-instead-of-dsa-rsa-ecdsa/),
+you should always favor [ED25519](https://ed25519.cr.yp.to/) SSH keys, since they
+are more secure and have better performance over the other types.
-- `id_dsa.pub`
-- `id_ecdsa.pub`
-- `id_ed25519.pub`
+They were introduced in OpenSSH 6.5, so any modern OS should include the
+option to create them. If for any reason your OS or the GitLab instance you
+interact with doesn't support this, you can fallback to RSA.
+
+## RSA SSH keys
+
+RSA keys are the most common ones and therefore the most compatible with
+servers that may have an old OpenSSH version. Use them if the GitLab server
+doesn't work with ED25519 keys.
+
+The minimum key size is 1024 bits, defaulting to 2048. If you wish to generate a
+stronger RSA key pair, specify the `-b` flag with a higher bit value than the
+default.
+
+The old, default password encoding for SSH private keys is
+[insecure](https://latacora.singles/2018/08/03/the-default-openssh.html);
+it's only a single round of an MD5 hash. Since OpenSSH version 6.5, you should
+use the `-o` option to `ssh-keygen` to encode your private key in a new, more
+secure format.
+
+If you already have an RSA SSH key pair to use with GitLab, consider upgrading it
+to use the more secure password encryption format by using the following command
+on the private key:
+
+```bash
+ssh-keygen -o -f ~/.ssh/id_rsa
+```
## Generating a new SSH key pair
-1. To generate a new SSH key pair, use the following command:
+Before creating an SSH key pair, make sure to read about the
+[different types of keys](#types-of-ssh-keys-and-which-to-choose) to understand
+their differences.
+
+To create a new SSH key pair:
- **Git Bash on Windows / GNU/Linux / macOS:**
+1. Open a terminal on Linux or macOS, or Git Bash / WSL on Windows.
+1. Generate a new ED25519 SSH key pair:
```bash
- ssh-keygen -o -t rsa -C "your.email@example.com" -b 4096
+ ssh-keygen -t ed25519 -C "email@example.com"
```
- (Note: the `-o` option was introduced in 2014; if this command does not work for you, simply remove the `-o` option and try again)
+ Or, if you want to use RSA:
- **Windows:**
+ ```bash
+ ssh-keygen -o -t rsa -b 4096 -C "email@example.com"
+ ```
- Alternatively on Windows you can download
- [PuttyGen](http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html)
- and follow [this documentation article][winputty] to generate a SSH key pair.
+ The `-C` flag adds a comment in the key in case you have multiple of them
+ and want to tell which is which. It is optional.
1. Next, you will be prompted to input a file path to save your SSH key pair to.
+ If you don't already have an SSH key pair, use the suggested path by pressing
+ <kbd>Enter</kbd>. Using the suggested path will normally allow your SSH client
+ to automatically use the SSH key pair with no additional configuration.
- If you don't already have an SSH key pair use the suggested path by pressing
- enter. Using the suggested path will normally allow your SSH client
- to automatically use the SSH key pair with no additional configuration.
+ If you already have an SSH key pair with the suggested file path, you will need
+ to input a new file path and [declare what host](#working-with-non-default-ssh-key-pair-paths)
+ this SSH key pair will be used for in your `~/.ssh/config` file.
- If you already have a SSH key pair with the suggested file path, you will need
- to input a new file path and declare what host this SSH key pair will be used
- for in your `.ssh/config` file, see [**Working with non-default SSH key pair paths**](#working-with-non-default-ssh-key-pair-paths)
- for more information.
+1. Once the path is decided, you will be prompted to input a password to
+ secure your new SSH key pair. It's a best practice to use a password,
+ but it's not required and you can skip creating it by pressing
+ <kbd>Enter</kbd> twice.
-1. Once you have input a file path you will be prompted to input a password to
- secure your SSH key pair. It is a best practice to use a password for an SSH
- key pair, but it is not required and you can skip creating a password by
- pressing enter.
+ If, in any case, you want to add or change the password of your SSH key pair,
+ you can use the `-p`flag:
- NOTE: **Note:**
- If you want to change the password of your SSH key pair, you can use
- `ssh-keygen -p -o -f <keyname>`.
- The `-o` option was added in 2014, so if this command does not work for you,
- simply remove the `-o` option and try again.
+ ```
+ ssh-keygen -p -o -f <keyname>
+ ```
-## Adding a SSH key to your GitLab account
+Now, it's time to add the newly created public key to your GitLab account.
-1. The next step is to copy the public SSH key as we will need it afterwards.
+## Adding an SSH key to your GitLab account
- To copy your public SSH key to the clipboard, use the appropriate code below:
+1. Copy your **public** SSH key to the clipboard by using one of the commands below
+ depending on your Operating System:
**macOS:**
```bash
- pbcopy < ~/.ssh/id_rsa.pub
+ pbcopy < ~/.ssh/id_ed25519.pub
```
- **GNU/Linux (requires the xclip package):**
+ **WSL / GNU/Linux (requires the xclip package):**
```bash
- xclip -sel clip < ~/.ssh/id_rsa.pub
+ xclip -sel clip < ~/.ssh/id_ed25519.pub
```
- **Windows Command Line:**
+ **Git Bash on Windows:**
```bash
- type %userprofile%\.ssh\id_rsa.pub | clip
+ cat ~/.ssh/id_ed25519.pub | clip
```
- **Git Bash on Windows / Windows PowerShell:**
+ You can also open the key in a graphical editor and copy it from there,
+ but be careful not to accidentally change anything.
- ```bash
- cat ~/.ssh/id_rsa.pub | clip
- ```
-
-1. The final step is to add your public SSH key to GitLab.
+ NOTE: **Note:**
+ If you opted to create an RSA key, the name might differ.
- Navigate to the 'SSH Keys' tab in your 'Profile Settings'.
- Paste your key in the 'Key' section and give it a relevant 'Title'.
- Use an identifiable title like 'Work Laptop - Windows 7' or
- 'Home MacBook Pro 15'.
+1. Add your public SSH key to your GitLab account by clicking your avatar
+ in the upper right corner and selecting **Settings**. From there on,
+ navigate to **SSH Keys** and paste your public key in the "Key" section.
+ If you created the key with a comment, this will appear under "Title".
+ If not, give your key an identifiable title like _Work Laptop_ or
+ _Home Workstation_, and click **Add key**.
+ NOTE: **Note:**
If you manually copied your public SSH key make sure you copied the entire
- key starting with `ssh-rsa` and ending with your email.
+ key starting with `ssh-ed25519` (or `ssh-rsa`) and ending with your email.
+
+## Testing that everything is set up correctly
+
+To test whether your SSH key was added correctly, run the following command in
+your terminal (replacing `gitlab.com` with your GitLab's instance domain):
-1. Optionally you can test your setup by running `ssh -T git@example.com`
- (replacing `example.com` with your GitLab domain) and verifying that you
- receive a `Welcome to GitLab` message.
+```bash
+ssh -T git@gitlab.com
+```
+
+You should receive a _Welcome to GitLab, `@username`!_ message.
+
+If the welcome message doesn't appear, run SSH's verbose mode by replacing `-T`
+with `-vvvT` to understand where the error is.
## Working with non-default SSH key pair paths
If you used a non-default file path for your GitLab SSH key pair,
you must configure your SSH client to find your GitLab private SSH key
-for connections to your GitLab server (perhaps `gitlab.com`).
+for connections to GitLab.
-For your current terminal session you can do so using the following commands
+Open a terminal and use the following commands
(replacing `other_id_rsa` with your private SSH key):
-**Git Bash on Windows / GNU/Linux / macOS:**
-
```bash
eval $(ssh-agent -s)
ssh-add ~/.ssh/other_id_rsa
```
-To retain these settings you'll need to save them to a configuration file.
-For OpenSSH clients this is configured in the `~/.ssh/config` file for some
-operating systems.
+To retain these settings, you'll need to save them to a configuration file.
+For OpenSSH clients this is configured in the `~/.ssh/config` file. In this
+file you can set up configurations for multiple hosts, like GitLab.com, your
+own GitLab instance, GitHub, Bitbucket, etc.
+
Below are two example host configurations using their own SSH key:
-```
-# GitLab.com server
+```conf
+# GitLab.com
Host gitlab.com
-RSAAuthentication yes
-IdentityFile ~/.ssh/config/private-key-filename-01
+ Preferredauthentications publickey
+ IdentityFile ~/.ssh/gitlab_com_rsa
-# Private GitLab server
+# Private GitLab instance
Host gitlab.company.com
-RSAAuthentication yes
-IdentityFile ~/.ssh/config/private-key-filename
+ Preferredauthentications publickey
+ IdentityFile ~/.ssh/example_com_rsa
```
-Due to the wide variety of SSH clients and their very large number of
-configuration options, further explanation of these topics is beyond the scope
-of this document.
-
-Public SSH keys need to be unique, as they will bind to your account.
-Your SSH key is the only identifier you'll have when pushing code via SSH.
-That's why it needs to uniquely map to a single user.
+Public SSH keys need to be unique to GitLab, as they will bind to your account.
+Your SSH key is the only identifier you'll have when pushing code via SSH,
+that's why it needs to uniquely map to a single user.
## Deploy keys
@@ -240,8 +301,6 @@ not implicitly give any access just by setting them up.
How to add your SSH key to Eclipse: https://wiki.eclipse.org/EGit/User_Guide#Eclipse_SSH_Configuration
-[winputty]: https://the.earth.li/~sgtatham/putty/0.67/htmldoc/Chapter8.html#pubkey-puttygen
-
## SSH on the GitLab server
GitLab integrates with the system-installed SSH daemon, designating a user
diff --git a/doc/topics/authentication/index.md b/doc/topics/authentication/index.md
index a8aa11265d0..766a23c419d 100644
--- a/doc/topics/authentication/index.md
+++ b/doc/topics/authentication/index.md
@@ -23,7 +23,7 @@ This page gathers all the resources for the topic **Authentication** within GitL
- [How to Configure LDAP with GitLab CE](../../administration/auth/how_to_configure_ldap_gitlab_ce/index.md)
- [How to Configure LDAP with GitLab EE](https://docs.gitlab.com/ee/articles/how_to_configure_ldap_gitlab_ee/)
- [Feature Highlight: LDAP Integration](https://about.gitlab.com/2014/07/10/feature-highlight-ldap-sync/)
- - [Debugging LDAP](https://about.gitlab.com/handbook/support/workflows/ldap/debugging_ldap.html)
+ - [Debugging LDAP](https://about.gitlab.com/handbook/support/workflows/support-engineering/ldap/debugging_ldap.html)
- **Integrations:**
- [OmniAuth](../../integration/omniauth.md)
- [Authentiq OmniAuth Provider](../../administration/auth/authentiq.md#authentiq-omniauth-provider)
@@ -36,14 +36,13 @@ This page gathers all the resources for the topic **Authentication** within GitL
## API
- [OAuth 2 Tokens](../../api/README.md#oauth-2-tokens)
-- [Private Tokens](../../api/README.md#private-tokens)
+- [Personal access tokens](../../api/README.md#personal-access-tokens)
- [Impersonation tokens](../../api/README.md#impersonation-tokens)
- [GitLab as an OAuth2 provider](../../api/oauth2.md#gitlab-as-an-oauth2-provider)
## Third-party resources
-- [Kanboard Plugin GitLab Authentication](https://kanboard.net/plugin/gitlab-auth)
-- [Jenkins GitLab OAuth Plugin](https://wiki.jenkins-ci.org/display/JENKINS/GitLab+OAuth+Plugin)
-- [Setup Gitlab CE with Active Directory authentication](https://www.caseylabs.com/setup-gitlab-ce-with-active-directory-authentication/)
+- [Kanboard Plugin GitLab Authentication](https://github.com/kanboard/plugin-gitlab-auth)
+- [Jenkins GitLab OAuth Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+OAuth+Plugin)
- [How to customize GitLab to support OpenID authentication](http://eric.van-der-vlist.com/blog/2013/11/23/how-to-customize-gitlab-to-support-openid-authentication/)
- [Openshift - Configuring Authentication and User Agent](https://docs.openshift.org/latest/install_config/configuring_authentication.html#GitLab)
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index e778f1d83df..63e7497cbbc 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -2,40 +2,54 @@
> [Introduced][ce-37115] in GitLab 10.0. Generally available on GitLab 11.0.
-Auto DevOps automatically detects, builds, tests, deploys, and monitors your
-applications.
+Auto DevOps provides pre-defined CI/CD configuration which allows you to automatically detect, build, test,
+deploy, and monitor your applications. Leveraging CI/CD best practices and tools, Auto DevOps aims
+to simplify the setup and execution of a mature & modern software development lifecycle.
## Overview
+NOTE: **Enabled by default:**
+Starting with GitLab 11.3, the Auto DevOps pipeline is enabled by default for all
+projects. If it has not been explicitly enabled for the project, Auto DevOps will be automatically
+disabled on the first pipeline failure. Your project will continue to use an alternative
+[CI/CD configuration file](../../ci/yaml/README.md) if one is found. A GitLab
+administrator can [change this setting](../../user/admin_area/settings/continuous_integration.html#auto-devops)
+in the admin area.
+
With Auto DevOps, the software development process becomes easier to set up
as every project can have a complete workflow from verification to monitoring
-without needing to configure anything. Just push your code and GitLab takes
+with minimal configuration. Just push your code and GitLab takes
care of everything else. This makes it easier to start new projects and brings
consistency to how applications are set up throughout a company.
## Quick start
If you are using GitLab.com, see the [quick start guide](quick_start_guide.md)
-for using Auto DevOps with GitLab.com and a Kubernetes cluster on Google Kubernetes
-Engine.
+for how to use Auto DevOps with GitLab.com and a Kubernetes cluster on Google Kubernetes
+Engine (GKE).
+
+If you are using a self-hosted instance of GitLab, you will need to configure the
+[Google OAuth2 OmniAuth Provider](../../integration/google.md) before
+you can configure a cluster on GKE. Once this is set up, you can follow the steps on the
+[quick start guide](quick_start_guide.md) to get started.
## Comparison to application platforms and PaaS
-Auto DevOps provides functionality described by others as an application
-platform or as a Platform as a Service (PaaS). It takes inspiration from the
+Auto DevOps provides functionality that is often included in an application
+platform or a Platform as a Service (PaaS). It takes inspiration from the
innovative work done by [Heroku](https://www.heroku.com/) and goes beyond it
-in a couple of ways:
+in multiple ways:
-1. Auto DevOps works with any Kubernetes cluster, you're not limited to running
- on GitLab's infrastructure (note that many features also work without Kubernetes).
+1. Auto DevOps works with any Kubernetes cluster; you're not limited to running
+ on GitLab's infrastructure. (Note that many features also work without Kubernetes.)
1. There is no additional cost (no markup on the infrastructure costs), and you
can use a self-hosted Kubernetes cluster or Containers as a Service on any
- public cloud (for example [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine/)).
+ public cloud (for example, [Google Kubernetes Engine](https://cloud.google.com/kubernetes-engine/)).
1. Auto DevOps has more features including security testing, performance testing,
and code quality testing.
-1. It offers an incremental graduation path. If you need advanced customizations
+1. Auto DevOps offers an incremental graduation path. If you need advanced customizations,
you can start modifying the templates without having to start over on a
- completely different platform.
+ completely different platform. Review the [customizing](#customizing) section for more information.
## Features
@@ -71,11 +85,6 @@ For an overview on the creation of Auto DevOps, read the blog post [From 2/3 of
## Requirements
-TIP: **Tip:**
-For self-hosted installations, the easiest way to make use of Auto DevOps is to
-install GitLab inside a Kubernetes cluster using the [GitLab Omnibus Helm Chart]
-which automatically installs and configures everything you need!
-
To make full use of Auto DevOps, you will need:
1. **GitLab Runner** (needed for all stages) - Your Runner needs to be
@@ -101,10 +110,6 @@ To make full use of Auto DevOps, you will need:
Kubernetes cluster using the
[`nginx-ingress`](https://github.com/kubernetes/charts/tree/master/stable/nginx-ingress)
Helm chart.
- 1. **Wildcard TLS termination** - You can deploy the
- [`kube-lego`](https://github.com/kubernetes/charts/tree/master/stable/kube-lego)
- Helm chart to your Kubernetes cluster to automatically issue certificates
- for your domains using Let's Encrypt.
1. **Prometheus** (needed for Auto Monitoring) - To enable Auto Monitoring, you
will need Prometheus installed somewhere (inside or outside your cluster) and
configured to scrape your Kubernetes cluster. To get response metrics
@@ -148,18 +153,13 @@ Auto DevOps base domain to `1.2.3.4.nip.io`.
Once set up, all requests will hit the load balancer, which in turn will route
them to the Kubernetes pods that run your application(s).
-NOTE: **Note:**
-If GitLab is installed using the [GitLab Omnibus Helm Chart], there are two
-options: provide a static IP, or have one assigned. For more information see the
-relevant docs on the [network prerequisites](../../install/kubernetes/gitlab_omnibus.md#networking-prerequisites).
-
## Using multiple Kubernetes clusters **[PREMIUM]**
When using Auto DevOps, you may want to deploy different environments to
different Kubernetes clusters. This is possible due to the 1:1 connection that
[exists between them](../../user/project/clusters/index.md#multiple-kubernetes-clusters).
-In the [Auto DevOps template](https://gitlab.com/gitlab-org/gitlab-ci-yml/blob/master/Auto-DevOps.gitlab-ci.yml)
+In the [Auto DevOps template](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
(used behind the scenes by Auto DevOps), there are currently 3 defined environment names that you need to know:
- `review/` (every environment starting with `review/`)
@@ -203,23 +203,38 @@ and verifying that your app is deployed as a review app in the Kubernetes
cluster with the `review/*` environment scope. Similarly, you can check the
other environments.
-## Enabling Auto DevOps
+## Enabling/Disabling Auto DevOps
-If you haven't done already, read the [requirements](#requirements) to make
-full use of Auto DevOps. If this is your fist time, we recommend you follow the
+When first using Auto Devops, review the [requirements](#requirements) to ensure all necessary components to make
+full use of Auto DevOps are available. If this is your fist time, we recommend you follow the
[quick start guide](quick_start_guide.md).
-To enable Auto DevOps to your project:
+GitLab.com users can enable/disable Auto DevOps at the project-level only. Self-managed users
+can enable/disable Auto DevOps at either the project-level or instance-level.
+
+### Enabling/disabling Auto DevOps at the instance-level (Administrators only)
+
+1. Go to **Admin area > Settings > Continuous Integration and Deployment**.
+1. Toggle the checkbox labeled **Default to Auto DevOps pipeline for all projects**.
+1. If enabling, optionally set up the Auto DevOps [base domain](#auto-devops-base-domain) which will be used for Auto Deploy and Auto Review Apps.
+1. Click **Save changes** for the changes to take effect.
+
+NOTE: **Note:**
+Even when disabled at the instance level, project maintainers are still able to enable
+Auto DevOps at the project level.
+
+### Enabling/disabling Auto DevOps at the project-level
+
+If enabling, check that your project doesn't have a `.gitlab-ci.yml`, or if one exists, remove it.
-1. Check that your project doesn't have a `.gitlab-ci.yml`, or remove it otherwise
-1. Go to your project's **Settings > CI/CD > Auto DevOps**
-1. Select "Enable Auto DevOps"
-1. Optionally, but recommended, add in the [base domain](#auto-devops-base-domain)
- that will be used by Kubernetes to [deploy your application](#auto-deploy)
- and choose the [deployment strategy](#deployment-strategy)
-1. Hit **Save changes** for the changes to take effect
+1. Go to your project's **Settings > CI/CD > Auto DevOps**.
+1. Toggle the **Default to Auto DevOps pipeline** checkbox (checked to enable, unchecked to disable)
+1. When enabling, it's optional but recommended to add in the [base domain](#auto-devops-base-domain)
+ that will be used by Auto DevOps to [deploy your application](#auto-deploy)
+ and choose the [deployment strategy](#deployment-strategy).
+1. Click **Save changes** for the changes to take effect.
-Once saved, an Auto DevOps pipeline will be triggered on the default branch.
+When the feature has been enabled, an Auto DevOps pipeline is triggered on the default branch.
NOTE: **Note:**
For GitLab versions 10.0 - 10.2, when enabling Auto DevOps, a pipeline needs to be
@@ -228,22 +243,10 @@ manually triggered either by pushing a new commit to the repository or by visiti
a new pipeline for your default branch, generally `master`.
NOTE: **Note:**
-If you are a GitLab Administrator, you can enable Auto DevOps instance wide
-in **Admin Area > Settings > Continuous Integration and Deployment**. Doing that,
-all the projects that haven't explicitly set an option will have Auto DevOps
-enabled by default.
-
-NOTE: **Note:**
There is also a feature flag to enable Auto DevOps to a percentage of projects
which can be enabled from the console with
`Feature.get(:force_autodevops_on_by_default).enable_percentage_of_actors(10)`.
-NOTE: **Enabled by default:**
-Starting with GitLab 11.3, the Auto DevOps pipeline will be enabled by default for all
-projects. If it's not explicitly enabled for the project, Auto DevOps will be automatically
-disabled on the first pipeline failure. Your project will continue to use an alternative
-[CI/CD configuration file](../../ci/yaml/README.md) if one is found.
-
### Deployment strategy
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/38542) in GitLab 11.0.
@@ -253,14 +256,19 @@ project's **Settings > CI/CD > Auto DevOps**.
The available options are:
-- **Continuous deployment to production** - enables [Auto Deploy](#auto-deploy)
- by setting the [`STAGING_ENABLED`](#deploy-policy-for-staging-and-production-environments) and
- [`INCREMENTAL_ROLLOUT_ENABLED`](#incremental-rollout-to-production) variables
- to false.
-- **Automatic deployment to staging, manual deployment to production** - sets the
+- **Continuous deployment to production**: Enables [Auto Deploy](#auto-deploy)
+ with `master` branch directly deployed to production.
+- **Continuous deployment to production using timed incremental rollout**: Sets the
+ [`INCREMENTAL_ROLLOUT_MODE`](#timed-incremental-rollout-to-production) variable
+ to `timed`, and production deployment will be executed with a 5 minute delay between
+ each increment in rollout.
+- **Automatic deployment to staging, manual deployment to production**: Sets the
[`STAGING_ENABLED`](#deploy-policy-for-staging-and-production-environments) and
- [`INCREMENTAL_ROLLOUT_ENABLED`](#incremental-rollout-to-production) variables
- to true, and the user is responsible for manually deploying to staging and production.
+ [`INCREMENTAL_ROLLOUT_MODE`](#incremental-rollout-to-production) variables
+ to `1` and `manual`. This means:
+
+ - `master` branch is directly deployed to staging.
+ - Manual actions are provided for incremental rollout to production.
## Stages of Auto DevOps
@@ -306,8 +314,7 @@ static analysis and other code checks on the current code. The report is
created, and is uploaded as an artifact which you can later download and check
out.
-In GitLab Starter, differences between the source and
-target branches are also
+Any differences between the source and target branches are also
[shown in the merge request widget](https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html).
### Auto SAST **[ULTIMATE]**
@@ -320,9 +327,12 @@ analysis on the current code and checks for potential security issues. Once the
report is created, it's uploaded as an artifact which you can later download and
check out.
-In GitLab Ultimate, any security warnings are also
+Any security warnings are also
[shown in the merge request widget](https://docs.gitlab.com/ee//user/project/merge_requests/sast.html).
+NOTE: **Note:**
+The Auto SAST stage will be skipped on licenses other than Ultimate.
+
### Auto Dependency Scanning **[ULTIMATE]**
> Introduced in [GitLab Ultimate][ee] 10.7.
@@ -336,6 +346,9 @@ check out.
Any security warnings are also
[shown in the merge request widget](https://docs.gitlab.com/ee//user/project/merge_requests/dependency_scanning.html).
+NOTE: **Note:**
+The Auto Dependency Scanning stage will be skipped on licenses other than Ultimate.
+
### Auto License Management **[ULTIMATE]**
> Introduced in [GitLab Ultimate][ee] 11.0.
@@ -349,6 +362,9 @@ check out.
Any licenses are also
[shown in the merge request widget](https://docs.gitlab.com/ee//user/project/merge_requests/license_management.html).
+NOTE: **Note:**
+The Auto License Management stage will be skipped on licenses other than Ultimate.
+
### Auto Container Scanning
> Introduced in GitLab 10.4.
@@ -359,9 +375,12 @@ Docker image and checks for potential security issues. Once the report is
created, it's uploaded as an artifact which you can later download and
check out.
-In GitLab Ultimate, any security warnings are also
+Any security warnings are also
[shown in the merge request widget](https://docs.gitlab.com/ee//user/project/merge_requests/container_scanning.html).
+NOTE: **Note:**
+The Auto Container Scanning stage will be skipped on licenses other than Ultimate.
+
### Auto Review Apps
NOTE: **Note:**
@@ -381,6 +400,9 @@ branch's code so developers, designers, QA, product managers, and other
reviewers can actually see and interact with code changes as part of the review
process. Auto Review Apps create a Review App for each branch.
+Auto Review Apps will deploy your app to your Kubernetes cluster only. When no cluster
+is available, no deployment will occur.
+
The Review App will have a unique URL based on the project name, the branch
name, and a unique number, combined with the Auto DevOps base domain. For
example, `user-project-branch-1234.example.com`. A link to the Review App shows
@@ -398,9 +420,12 @@ to perform an analysis on the current code and checks for potential security
issues. Once the report is created, it's uploaded as an artifact which you can
later download and check out.
-In GitLab Ultimate, any security warnings are also
+Any security warnings are also
[shown in the merge request widget](https://docs.gitlab.com/ee//user/project/merge_requests/dast.html).
+NOTE: **Note:**
+The Auto DAST stage will be skipped on licenses other than Ultimate.
+
### Auto Browser Performance Testing **[PREMIUM]**
> Introduced in [GitLab Premium][ee] 10.4.
@@ -413,8 +438,8 @@ Auto Browser Performance Testing utilizes the [Sitespeed.io container](https://h
/direction
```
-In GitLab Premium, performance differences between the source
-and target branches are [shown in the merge request widget](https://docs.gitlab.com/ee//user/project/merge_requests/browser_performance_testing.html).
+Any performance differences between the source and target branches are also
+[shown in the merge request widget](https://docs.gitlab.com/ee//user/project/merge_requests/browser_performance_testing.html).
### Auto Deploy
@@ -454,6 +479,39 @@ no longer be valid as soon as the deployment job finishes. This means that
Kubernetes can run the application, but in case it should be restarted or
executed somewhere else, it cannot be accessed again.
+#### Migrations
+
+> [Introduced][ce-21955] in GitLab 11.4
+
+Database initialization and migrations for PostgreSQL can be configured to run
+within the application pod by setting the project variables `DB_INITIALIZE` and
+`DB_MIGRATE` respectively.
+
+If present, `DB_INITIALIZE` will be run as a shell command within an
+application pod as a helm post-install hook. As some applications will
+not run without a successful database initialization step, GitLab will
+deploy the first release without the application deployment and only the
+database initialization step. After the database initialization completes,
+GitLab will deploy a second release with the application deployment as
+normal.
+
+Note that a post-install hook means that if any deploy succeeds,
+`DB_INITIALIZE` will not be processed thereafter.
+
+If present, `DB_MIGRATE` will be run as a shell command within an application pod as
+a helm pre-upgrade hook.
+
+For example, in a Rails application:
+
+* `DB_INITIALIZE` can be set to `cd /app && RAILS_ENV=production
+ bin/setup`
+* `DB_MIGRATE` can be set to `cd /app && RAILS_ENV=production bin/update`
+
+NOTE: **Note:**
+The `/app` path is the directory of your project inside the docker image
+as [configured by
+Herokuish](https://github.com/gliderlabs/herokuish#paths)
+
> [Introduced][ce-19507] in GitLab 11.0.
For internal and private projects a [GitLab Deploy Token](../../user/project/deploy_tokens/index.md###gitlab-deploy-token)
@@ -482,10 +540,7 @@ The metrics include:
- **Response Metrics:** latency, throughput, error rate
- **System Metrics:** CPU utilization, memory utilization
-If GitLab has been deployed using the [GitLab Omnibus Helm Chart], no
-configuration is required.
-
-If you have installed GitLab using a different method, you need to:
+In order to make use of monitoring you need to:
1. [Deploy Prometheus](../../user/project/integrations/prometheus.md#configuring-your-own-prometheus-server-within-kubernetes) into your Kubernetes cluster
1. If you would like response metrics, ensure you are running at least version
@@ -540,7 +595,7 @@ repo or by specifying a project variable:
file in it, Auto DevOps will detect the chart and use it instead of the [default
one](https://gitlab.com/charts/auto-deploy-app).
This can be a great way to control exactly how your application is deployed.
-- **Project variable** - Create a [project variable](../../ci/variables/README.md#secret-variables)
+- **Project variable** - Create a [project variable](../../ci/variables/README.md#variables)
`AUTO_DEVOPS_CHART` with the URL of a custom chart to use.
### Customizing `.gitlab-ci.yml`
@@ -598,9 +653,11 @@ also be customized, and you can easily use a [custom buildpack](#custom-buildpac
| `BUILDPACK_URL` | The buildpack's full URL. It can point to either Git repositories or a tarball URL. For Git repositories, it is possible to point to a specific `ref`, for example `https://github.com/heroku/heroku-buildpack-ruby.git#v142` |
| `SAST_CONFIDENCE_LEVEL` | The minimum confidence level of security issues you want to be reported; `1` for Low, `2` for Medium, `3` for High; defaults to `3`.|
| `DEP_SCAN_DISABLE_REMOTE_CHECKS` | Whether remote Dependency Scanning checks are disabled; defaults to `"false"`. Set to `"true"` to disable checks that send data to GitLab central servers. [Read more about remote checks](https://gitlab.com/gitlab-org/security-products/dependency-scanning#remote-checks).|
+| `DB_INITIALIZE` | From GitLab 11.4, this variable can be used to specify the command to run to initialize the application's PostgreSQL database. It runs inside the application pod. |
+| `DB_MIGRATE` | From GitLab 11.4, this variable can be used to specify the command to run to migrate the application's PostgreSQL database. It runs inside the application pod. |
| `STAGING_ENABLED` | From GitLab 10.8, this variable can be used to define a [deploy policy for staging and production environments](#deploy-policy-for-staging-and-production-environments). |
| `CANARY_ENABLED` | From GitLab 11.0, this variable can be used to define a [deploy policy for canary environments](#deploy-policy-for-canary-environments). |
-| `INCREMENTAL_ROLLOUT_ENABLED`| From GitLab 10.8, this variable can be used to enable an [incremental rollout](#incremental-rollout-to-production) of your application for the production environment. |
+| `INCREMENTAL_ROLLOUT_MODE`| From GitLab 11.4, this variable, if present, can be used to enable an [incremental rollout](#incremental-rollout-to-production) of your application for the production environment.<br/>Set to: <ul><li>`manual`, for manual deployment jobs.</li><li>`timed`, for automatic rollout deployments with a 5 minute delay each one.</li></ul> |
| `TEST_DISABLED` | From GitLab 11.0, this variable can be used to disable the `test` job. If the variable is present, the job will not be created. |
| `CODE_QUALITY_DISABLED` | From GitLab 11.0, this variable can be used to disable the `codequality` job. If the variable is present, the job will not be created. |
| `SAST_DISABLED` | From GitLab 11.0, this variable can be used to disable the `sast` job. If the variable is present, the job will not be created. |
@@ -612,7 +669,7 @@ also be customized, and you can easily use a [custom buildpack](#custom-buildpac
TIP: **Tip:**
Set up the replica variables using a
-[project variable](../../ci/variables/README.md#secret-variables)
+[project variable](../../ci/variables/README.md#variables)
and scale your application by just redeploying it!
CAUTION: **Caution:**
@@ -690,7 +747,7 @@ staging environment and deploy to production manually. For this scenario, the
`STAGING_ENABLED` environment variable was introduced.
If `STAGING_ENABLED` is defined in your project (e.g., set `STAGING_ENABLED` to
-`1` as a secret variable), then the application will be automatically deployed
+`1` as a CI/CD variable), then the application will be automatically deployed
to a `staging` environment, and a `production_manual` job will be created for
you when you're ready to manually deploy to production.
@@ -703,7 +760,7 @@ A [canary environment](https://docs.gitlab.com/ee/user/project/canary_deployment
before any changes are deployed to production.
If `CANARY_ENABLED` is defined in your project (e.g., set `CANARY_ENABLED` to
-`1` as a secret variable) then two manual jobs will be created:
+`1` as a CI/CD variable) then two manual jobs will be created:
- `canary` which will deploy the application to the canary environment
- `production_manual` which is to be used by you when you're ready to manually
@@ -721,9 +778,8 @@ to use an incremental rollout to replace just a few pods with the latest code.
This will allow you to first check how the app is behaving, and later manually
increasing the rollout up to 100%.
-If `INCREMENTAL_ROLLOUT_ENABLED` is defined in your project (e.g., set
-`INCREMENTAL_ROLLOUT_ENABLED` to `1` as a secret variable), then instead of the
-standard `production` job, 4 different
+If `INCREMENTAL_ROLLOUT_MODE` is set to `manual` in your project, then instead
+of the standard `production` job, 4 different
[manual jobs](../../ci/pipelines.md#manual-actions-from-the-pipeline-graph)
will be created:
@@ -747,21 +803,45 @@ environment page.
Below, you can see how the pipeline will look if the rollout or staging
variables are defined.
-- **Without `INCREMENTAL_ROLLOUT_ENABLED` and without `STAGING_ENABLED`**
+Without `INCREMENTAL_ROLLOUT_MODE` and without `STAGING_ENABLED`:
+
+![Staging and rollout disabled](img/rollout_staging_disabled.png)
+
+Without `INCREMENTAL_ROLLOUT_MODE` and with `STAGING_ENABLED`:
+
+![Staging enabled](img/staging_enabled.png)
+
+With `INCREMENTAL_ROLLOUT_MODE` set to `manual` and without `STAGING_ENABLED`:
- ![Staging and rollout disabled](img/rollout_staging_disabled.png)
+![Rollout enabled](img/rollout_enabled.png)
-- **Without `INCREMENTAL_ROLLOUT_ENABLED` and with `STAGING_ENABLED`**
+With `INCREMENTAL_ROLLOUT_MODE` set to `manual` and with `STAGING_ENABLED`
- ![Staging enabled](img/staging_enabled.png)
+![Rollout and staging enabled](img/rollout_staging_enabled.png)
-- **With `INCREMENTAL_ROLLOUT_ENABLED` and without `STAGING_ENABLED`**
+CAUTION: **Caution:**
+Before GitLab 11.4 this feature was enabled by the presence of the
+`INCREMENTAL_ROLLOUT_ENABLED` environment variable.
+This configuration is deprecated and will be removed in the future.
+
+#### Timed incremental rollout to production **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/7545) in GitLab 11.4.
+
+TIP: **Tip:**
+You can also set this inside your [project's settings](#deployment-strategy).
- ![Rollout enabled](img/rollout_enabled.png)
+This configuration based on
+[incremental rollout to production](#incremental-rollout-to-production).
-- **With `INCREMENTAL_ROLLOUT_ENABLED` and with `STAGING_ENABLED`**
+Everything behaves the same way, except:
- ![Rollout and staging enabled](img/rollout_staging_enabled.png)
+- It's enabled by setting the `INCREMENTAL_ROLLOUT_MODE` variable to `timed`.
+- Instead of the standard `production` job, the following jobs with a 5 minute delay between each are created:
+ 1. `timed rollout 10%`
+ 1. `timed rollout 25%`
+ 1. `timed rollout 50%`
+ 1. `timed rollout 100%`
## Currently supported languages
@@ -849,7 +929,7 @@ curl --data "value=true" --header "PRIVATE-TOKEN: personal_access_token" https:/
[review-app]: ../../ci/review_apps/index.md
[container-registry]: ../../user/project/container_registry.md
[postgresql]: https://www.postgresql.org/
-[Auto DevOps template]: https://gitlab.com/gitlab-org/gitlab-ci-yml/blob/master/Auto-DevOps.gitlab-ci.yml
-[GitLab Omnibus Helm Chart]: ../../install/kubernetes/gitlab_omnibus.md
+[Auto DevOps template]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
[ee]: https://about.gitlab.com/pricing/
+[ce-21955]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21955
[ce-19507]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19507
diff --git a/doc/topics/autodevops/quick_start_guide.md b/doc/topics/autodevops/quick_start_guide.md
index 7ca441a2f74..6326aadcdf2 100644
--- a/doc/topics/autodevops/quick_start_guide.md
+++ b/doc/topics/autodevops/quick_start_guide.md
@@ -15,7 +15,7 @@ need to ensure your own [Runners are configured](../../ci/runners/README.md) and
Before creating and connecting your Kubernetes cluster to your GitLab project,
you need a Google Cloud Platform account. If you don't already have one,
-sign up at https://console.cloud.google.com. You'll need to either sign in with an existing
+sign up at <https://console.cloud.google.com>. You'll need to either sign in with an existing
Google account (for example, one that you use to access Gmail, Drive, etc.) or create a new one.
1. Follow the steps as outlined in the ["Before you begin" section of the Kubernetes Engine docs](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin)
@@ -83,6 +83,9 @@ under which this application will be deployed.
![GitLab GKE cluster details](img/guide_gitlab_gke_details.png)
1. Once ready, click **Create Kubernetes cluster**.
+
+NOTE: **Note:**
+Do not select `f1-micro` from the **Machine type** dropdown. `f1-micro` machines cannot support a full GitLab installation.
After a couple of minutes, the cluster will be created. You can also see its
status on your [GCP dashboard](https://console.cloud.google.com/kubernetes).
@@ -205,7 +208,7 @@ applications. In the rightmost column for the production environment, you can ma
application is running.
Right below, there is the
-[Deploy Board](https://docs.gitlab.com/ee/user/project/deploy_boards.md).
+[Deploy Board](https://docs.gitlab.com/ee/user/project/deploy_boards.html).
The squares represent pods in your Kubernetes cluster that are associated with
the given environment. Hovering above each square you can see the state of a
deployment and clicking a square will take you to the pod's logs page.
@@ -264,8 +267,8 @@ Let's fix that:
to stage the changes.
1. Write a commit message and click **Commit**.
-Now, if you go back to the merge request you should not only see the test passing,
-but also the application deployed as a [review app](index.md#auto-review-apps). You
+Now, if you go back to the merge request you should not only see the test passing, but
+also the application deployed as a [review app](index.md#auto-review-apps). You
can visit it by following the URL in the merge request. The changes that we
previously made should be there.
diff --git a/doc/topics/git/how_to_install_git/index.md b/doc/topics/git/how_to_install_git/index.md
index 58d86f7d387..d7e1979217e 100644
--- a/doc/topics/git/how_to_install_git/index.md
+++ b/doc/topics/git/how_to_install_git/index.md
@@ -22,7 +22,7 @@ an extensive selection of dependency managed libraries and applications.
If you are sure you don't need access to any additional development libraries
or don't have approximately 15gb of available disk space for Xcode and Homebrew
-use one of the the aforementioned methods.
+use one of the aforementioned methods.
### Installing Xcode
diff --git a/doc/topics/git/troubleshooting_git.md b/doc/topics/git/troubleshooting_git.md
index 8555c5e91ea..d1729d70158 100644
--- a/doc/topics/git/troubleshooting_git.md
+++ b/doc/topics/git/troubleshooting_git.md
@@ -78,5 +78,20 @@ git push
In case you're running an older version of Git (< 2.9), consider upgrading
to >= 2.9 (see [Broken pipe when pushing to Git repository][Broken-Pipe]).
+## Timeout during git push/pull
+
+If pulling/pushing from/to your repository ends up taking more than 50 seconds,
+a timeout will be issued with a log of the number of operations performed
+and their respective timings, like the example below:
+
+```
+remote: Running checks for branch: master
+remote: Scanning for LFS objects... (153ms)
+remote: Calculating new repository size... (cancelled after 729ms)
+```
+
+This could be used to further investigate what operation is performing poorly
+and provide GitLab with more information on how to improve the service.
+
[SSH troubleshooting]: ../../ssh/README.md#troubleshooting "SSH Troubleshooting"
[Broken-Pipe]: https://stackoverflow.com/questions/19120120/broken-pipe-when-pushing-to-git-repository/36971469#36971469 "StackOverflow: 'Broken pipe when pushing to Git repository'"
diff --git a/doc/university/README.md b/doc/university/README.md
index 203981b85ec..3e7d02770e4 100644
--- a/doc/university/README.md
+++ b/doc/university/README.md
@@ -11,7 +11,7 @@ and [Blog Articles](https://about.gitlab.com/blog/).
Would you like to contribute to GitLab University? Then please take a look at our contribution [process](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/PROCESS.md) for more information.
-## Gitlab University Curriculum
+## GitLab University Curriculum
The curriculum is composed of GitLab videos, screencasts, presentations, projects and external GitLab content hosted on other services and has been organized into the following sections.
@@ -104,7 +104,7 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
1. [Due Dates and Milestones for GitLab Issues](https://about.gitlab.com/2016/08/05/feature-highlight-set-dates-for-issues/)
1. [How to Use GitLab Labels](https://about.gitlab.com/2016/08/17/using-gitlab-labels/)
1. [Applying GitLab Labels Automatically](https://about.gitlab.com/2016/08/19/applying-gitlab-labels-automatically/)
-1. [GitLab Issue Board - Product Page](https://about.gitlab.com/solutions/issueboard/)
+1. [GitLab Issue Board - Product Page](https://about.gitlab.com/product/issueboard/)
1. [An Overview of GitLab Issue Board](https://about.gitlab.com/2016/08/22/announcing-the-gitlab-issue-board/)
1. [Designing GitLab Issue Board](https://about.gitlab.com/2016/08/31/designing-issue-boards/)
1. [From Idea to Production with GitLab - Video](https://www.youtube.com/watch?v=25pHyknRgEo&index=14&list=PLFGfElNsQthbQu_IWlNOxul0TbS_2JH-e)
@@ -125,7 +125,7 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
1. [Setting up GitLab CI for iOS projects](https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/)
1. [IBM: Continuous Delivery vs Continuous Deployment - Video](https://www.youtube.com/watch?v=igwFj8PPSnw)
1. [Amazon: Transition to Continuous Delivery - Video](https://www.youtube.com/watch?v=esEFaY0FDKc)
-2. [TechBeacon: Doing continuous delivery? Focus first on reducing release cycle times](https://techbeacon.com/doing-continuous-delivery-focus-first-reducing-release-cycle-times)
+1. [TechBeacon: Doing continuous delivery? Focus first on reducing release cycle times](https://techbeacon.com/doing-continuous-delivery-focus-first-reducing-release-cycle-times)
1. See **[Integrations](#39-integrations)** for integrations with other CI services.
#### 2.4. Workflow
@@ -140,7 +140,7 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
1. [GitLab Compared to Other Tools](https://about.gitlab.com/comparison/)
1. [Comparing GitLab Terminology](https://about.gitlab.com/2016/01/27/comparing-terms-gitlab-github-bitbucket/)
-1. [GitLab Compared to Atlassian (Recording 2016-03-03) ](https://youtu.be/Nbzp1t45ERo)
+1. [GitLab Compared to Atlassian (Recording 2016-03-03)](https://youtu.be/Nbzp1t45ERo)
1. [GitLab Position FAQ](https://about.gitlab.com/handbook/positioning-faq)
1. [Customer review of GitLab with points on why they prefer GitLab](https://www.enovate.co.uk/web-design-blog/2015/11/25/gitlab-review/)
@@ -189,7 +189,7 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
#### 3.8 Cycle Analytics
1. [GitLab Cycle Analytics Overview](https://about.gitlab.com/2016/09/21/cycle-analytics-feature-highlight/)
-1. [GitLab Cycle Analytics - Product Page](https://about.gitlab.com/solutions/cycle-analytics/)
+1. [GitLab Cycle Analytics - Product Page](https://about.gitlab.com/product/cycle-analytics/)
#### 3.9. Integrations
@@ -205,7 +205,7 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
### 4. External Articles
-1. [2011 WSJ article by Marc Andreessen - Software is Eating the World](http://www.wsj.com/articles/SB10001424053111903480904576512250915629460)
+1. [2011 WSJ article by Marc Andreessen - Software is Eating the World](https://www.wsj.com/articles/SB10001424053111903480904576512250915629460)
1. [2014 Blog post by Chris Dixon - Software eats software development](http://cdixon.org/2014/04/13/software-eats-software-development/)
1. [2015 Venture Beat article - Actually, Open Source is Eating the World](http://venturebeat.com/2015/12/06/its-actually-open-source-software-thats-eating-the-world/)
@@ -213,7 +213,8 @@ The curriculum is composed of GitLab videos, screencasts, presentations, project
### 5. Resources for GitLab Team Members
-*Some content can only be accessed by GitLab team members*
+NOTE: **Note:**
+Some content can only be accessed by GitLab team members
1. [Support Path](support/README.md)
1. [Sales Path (redirect to sales handbook)](https://about.gitlab.com/handbook/sales-onboarding/)
diff --git a/doc/university/bookclub/booklist.md b/doc/university/bookclub/booklist.md
index 26c3851276b..d5662be6fa6 100644
--- a/doc/university/bookclub/booklist.md
+++ b/doc/university/bookclub/booklist.md
@@ -10,108 +10,108 @@ List of books and resources, that may be worth reading.
1. **The Humble Programmer**
- Edsger W. Dijkstra, 1972 ([paper](http://dl.acm.org/citation.cfm?id=361591))
+ Edsger W. Dijkstra, 1972 ([paper](https://dl.acm.org/citation.cfm?id=361591))
## Programming
1. **Design Patterns: Elements of Reusable Object-Oriented Software**
- Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides, 1994 ([amazon](http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612))
+ Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides, 1994 ([amazon](https://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612))
1. **Clean Code: A Handbook of Agile Software Craftsmanship**
- Robert C. "Uncle Bob" Martin, 2008 ([amazon](http://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882))
+ Robert C. "Uncle Bob" Martin, 2008 ([amazon](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882))
1. **Code Complete: A Practical Handbook of Software Construction**, 2nd Edition
- Steve McConnell, 2004 ([amazon](http://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670))
+ Steve McConnell, 2004 ([amazon](https://www.amazon.com/Code-Complete-Practical-Handbook-Construction/dp/0735619670))
1. **The Pragmatic Programmer: From Journeyman to Master**
- Andrew Hunt, David Thomas, 1999 ([amazon](http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X))
+ Andrew Hunt, David Thomas, 1999 ([amazon](https://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X))
1. **Working Effectively with Legacy Code**
- Michael Feathers, 2004 ([amazon](http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052))
+ Michael Feathers, 2004 ([amazon](https://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052))
1. **Eloquent Ruby**
- Russ Olsen, 2011 ([amazon](http://www.amazon.com/Eloquent-Ruby-Addison-Wesley-Professional/dp/0321584104))
+ Russ Olsen, 2011 ([amazon](https://www.amazon.com/Eloquent-Ruby-Addison-Wesley-Professional/dp/0321584104))
1. **Domain-Driven Design: Tackling Complexity in the Heart of Software**
- Eric Evans, 2003 ([amazon](http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215))
+ Eric Evans, 2003 ([amazon](https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215))
1. **How to Solve It: A New Aspect of Mathematical Method**
- Polya G. 1957 ([amazon](http://www.amazon.com/How-Solve-Mathematical-Princeton-Science/dp/069116407X))
+ Polya G. 1957 ([amazon](https://www.amazon.com/How-Solve-Mathematical-Princeton-Science/dp/069116407X))
1. **Software Creativity 2.0**
- Robert L. Glass, 2006 ([amazon](http://www.amazon.com/Software-Creativity-2-0-Robert-Glass/dp/0977213315))
+ Robert L. Glass, 2006 ([amazon](https://www.amazon.com/Software-Creativity-2-0-Robert-Glass/dp/0977213315))
1. **Object-Oriented Software Construction**
- Bertrand Meyer, 1997 ([amazon](http://www.amazon.com/Object-Oriented-Software-Construction-Book-CD-ROM/dp/0136291554))
+ Bertrand Meyer, 1997 ([amazon](https://www.amazon.com/Object-Oriented-Software-Construction-Book-CD-ROM/dp/0136291554))
1. **Refactoring: Improving the Design of Existing Code**
- Martin Fowler, Kent Beck, 1999 ([amazon](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672))
+ Martin Fowler, Kent Beck, 1999 ([amazon](https://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672))
1. **Test Driven Development: By Example**
- Kent Beck, 2002 ([amazon](http://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530))
+ Kent Beck, 2002 ([amazon](https://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530))
1. **Algorithms in C++: Fundamentals, Data Structure, Sorting, Searching**
- Robert Sedgewick, 1990 ([amazon](http://www.amazon.com/Algorithms-Parts-1-4-Fundamentals-Structure/dp/0201350882))
+ Robert Sedgewick, 1990 ([amazon](https://www.amazon.com/Algorithms-Parts-1-4-Fundamentals-Structure/dp/0201350882))
1. **Effective C++**
- Scott Mayers, 1996 ([amazon](http://www.amazon.com/Effective-Specific-Improve-Programs-Designs/dp/0321334876))
+ Scott Mayers, 1996 ([amazon](https://www.amazon.com/Effective-Specific-Improve-Programs-Designs/dp/0321334876))
1. **Extreme Programming Explained: Embrace Change**
- Kent Beck, 1999 ([amazon](http://www.amazon.com/Extreme-Programming-Explained-Embrace-Change/dp/0321278658))
+ Kent Beck, 1999 ([amazon](https://www.amazon.com/Extreme-Programming-Explained-Embrace-Change/dp/0321278658))
1. **The Art of Computer Programming**
- Donald E. Knuth, 1997 ([amazon](http://www.amazon.com/Computer-Programming-Volumes-1-4A-Boxed/dp/0321751043))
+ Donald E. Knuth, 1997 ([amazon](https://www.amazon.com/Computer-Programming-Volumes-1-4A-Boxed/dp/0321751043))
1. **Writing Efficient Programs**
- Jon Louis Bentley, 1982 ([amazon](http://www.amazon.com/Writing-Efficient-Programs-Prentice-Hall-Software/dp/013970244X))
+ Jon Louis Bentley, 1982 ([amazon](https://www.amazon.com/Writing-Efficient-Programs-Prentice-Hall-Software/dp/013970244X))
1. **The Mythical Man-Month: Essays on Software Engineering**
- Frederick Phillips Brooks, 1975 ([amazon](http://www.amazon.com/Mythical-Man-Month-Essays-Software-Engineering/dp/0201006502))
+ Frederick Phillips Brooks, 1975 ([amazon](https://www.amazon.com/Mythical-Man-Month-Essays-Software-Engineering/dp/0201006502))
1. **Peopleware: Productive Projects and Teams** 3rd Edition
- Tom DeMarco, Tim Lister, 2013 ([amazon](http://www.amazon.com/Peopleware-Productive-Projects-Teams-3rd/dp/0321934113))
+ Tom DeMarco, Tim Lister, 2013 ([amazon](https://www.amazon.com/Peopleware-Productive-Projects-Teams-3rd/dp/0321934113))
1. **Principles Of Software Engineering Management**
- Tom Gilb, 1988 ([amazon](http://www.amazon.com/Principles-Software-Engineering-Management-Gilb/dp/0201192462))
+ Tom Gilb, 1988 ([amazon](https://www.amazon.com/Principles-Software-Engineering-Management-Gilb/dp/0201192462))
## Other
1. **Thinking, Fast and Slow**
- Daniel Kahneman, 2013 ([amazon](http://www.amazon.com/Thinking-Fast-Slow-Daniel-Kahneman/dp/0374533555))
+ Daniel Kahneman, 2013 ([amazon](https://www.amazon.com/Thinking-Fast-Slow-Daniel-Kahneman/dp/0374533555))
1. **The Social Animal** 11th Edition
- Elliot Aronson, 2011 ([amazon](http://www.amazon.com/Social-Animal-Elliot-Aronson/dp/1429233419))
+ Elliot Aronson, 2011 ([amazon](https://www.amazon.com/Social-Animal-Elliot-Aronson/dp/1429233419))
1. **Influence: Science and Practice** 5th Edition
- Robert B. Cialdini, 2008 ([amazon](http://www.amazon.com/Influence-Practice-Robert-B-Cialdini/dp/0205609996))
+ Robert B. Cialdini, 2008 ([amazon](https://www.amazon.com/Influence-Practice-Robert-B-Cialdini/dp/0205609996))
1. **Getting to Yes: Negotiating Agreement Without Giving In**
- Roger Fisher, William L. Ury, Bruce Patton, 2011 ([amazon](http://www.amazon.com/Getting-Yes-Negotiating-Agreement-Without/dp/0143118757))
+ Roger Fisher, William L. Ury, Bruce Patton, 2011 ([amazon](https://www.amazon.com/Getting-Yes-Negotiating-Agreement-Without/dp/0143118757))
1. **How to Win Friends & Influence People**
- Dale Carnegie, 1981 ([amazon](http://www.amazon.com/How-Win-Friends-Influence-People/dp/0671027034))
+ Dale Carnegie, 1981 ([amazon](https://www.amazon.com/How-Win-Friends-Influence-People/dp/0671027034))
diff --git a/doc/university/glossary/README.md b/doc/university/glossary/README.md
index 89516dba60b..7c7e44d29e7 100644
--- a/doc/university/glossary/README.md
+++ b/doc/university/glossary/README.md
@@ -303,7 +303,7 @@ A [tool](https://docs.gitlab.com/ee/integration/external-issue-tracker.html) use
### Jenkins
-An Open Source CI tool written using the Java programming language. [Jenkins](https://jenkins-ci.org/) does the same job as GitLab CI, Bamboo, and Travis CI. It is extremely popular. Related [documentation](https://docs.gitlab.com/ee/integration/jenkins.html).
+An Open Source CI tool written using the Java programming language. [Jenkins](https://jenkins.io/) does the same job as GitLab CI, Bamboo, and Travis CI. It is extremely popular. Related [documentation](https://docs.gitlab.com/ee/integration/jenkins.html).
### Jira
@@ -395,7 +395,7 @@ Allow you to [organize issues](../../user/project/milestones/index.md) and merge
### Mirror Repositories
-A project that is setup to automatically have its branches, tags, and commits [updated from an upstream repository](https://docs.gitlab.com/ee/workflow/repository_mirroring.html). This is useful when a repository you're interested in is located on a different server, and you want to be able to browse its content and activity using the familiar GitLab interface.
+A project that is set up to automatically have its branches, tags, and commits [updated from an upstream repository](https://docs.gitlab.com/ee/workflow/repository_mirroring.html). This is useful when a repository you're interested in is located on a different server, and you want to be able to browse its content and activity using the familiar GitLab interface.
### MIT License
@@ -673,7 +673,7 @@ Version control is a system that records changes to a file or set of files over
### Virtual Private Cloud (VPC)
-A [VPC](https://docs.gitlab.com/ce/university/glossary/README.html#virtual-private-cloud-vpc) is an on demand configurable pool of shared computing resources allocated within a public cloud environment, providing some isolation between the different users using the resources. GitLab users need to create a new Amazon VPC in order to [setup High Availability](https://docs.gitlab.com/ce/university/high-availability/aws/).
+A [VPC](https://docs.gitlab.com/ce/university/glossary/README.html#virtual-private-cloud-vpc) is an on demand configurable pool of shared computing resources allocated within a public cloud environment, providing some isolation between the different users using the resources. GitLab users need to create a new Amazon VPC in order to [set up High Availability](https://docs.gitlab.com/ce/university/high-availability/aws/).
### Virtual private server (VPS)
@@ -689,7 +689,7 @@ A [model](http://www.umsl.edu/~hugheyd/is6840/waterfall.html) of building softwa
### Webhooks
-A way for for an app to [provide](https://docs.gitlab.com/ce/user/project/integrations/webhooks.html) other applications with real-time information (e.g., send a message to a slack channel when a commit is pushed.) Read about setting up [custom git hooks](https://gitlab.com/help/administration/custom_hooks.md) for when webhooks are insufficient.
+A way for an app to [provide](https://docs.gitlab.com/ce/user/project/integrations/webhooks.html) other applications with real-time information (e.g., send a message to a slack channel when a commit is pushed.) Read about setting up [custom git hooks](https://gitlab.com/help/administration/custom_hooks.md) for when webhooks are insufficient.
### Wiki
diff --git a/doc/university/high-availability/aws/README.md b/doc/university/high-availability/aws/README.md
index 1bff1488746..b21cf27c1d3 100644
--- a/doc/university/high-availability/aws/README.md
+++ b/doc/university/high-availability/aws/README.md
@@ -9,7 +9,7 @@ in [significantly degraded performance](https://gitlab.com/gitlab-org/gitlab-ee/
GitLab on AWS can leverage many of the services that are already
configurable with High Availability. These services have a lot of
-flexibility and are able to adopt to most companies, best of all is the
+flexibility and are able to adapt to most companies, best of all is the
ability to automate both vertical and horizontal scaling.
In this article we'll go through a basic HA setup where we'll start by
@@ -55,9 +55,9 @@ and from the Actions dropdown choose Edit DNS Hostnames and select Yes.
### Subnet
Now let's create some subnets in different Availability Zones. Make sure
-that each subnet is associated the the VPC we just created, that it has
+that each subnet is associated to the VPC we just created, that it has
a distinct VPC and lastly that CIDR blocks don't overlap. This will also
-allow us to enable multi AZ for redundancy.
+allow us to enable multi-AZ for redundancy.
We will create private and public subnets to match load balancers and
RDS instances as well.
@@ -98,7 +98,7 @@ traffic from any destination.
![Subnet Config](img/ig-rt.png)
-Before leaving this screen select the next tab to the rgiht which is
+Before leaving this screen select the next tab to the right which is
Subnet Associations and add our public subnets. If you followed our
naming convention they should be easy to find.
@@ -106,8 +106,8 @@ naming convention they should be easy to find.
## Database with RDS
-For our database server we will use Amazon RDS which offers Multi AZ
-for redundancy. Lets start by creating a subnet group and then we'll
+For our database server we will use Amazon RDS which offers Multi-AZ
+for redundancy. Let's start by creating a subnet group and then we'll
create the actual RDS instance.
### Subnet Group
@@ -122,7 +122,7 @@ the VPC ID dropdown and at the bottom we can add our private subnets.
Select the RDS service from the Database section and create a new
PostgreSQL instance. After choosing between a Production or
Development instance we'll start with the actual configuration. On the
-image bellow we have the settings for this article but note the
+image below we have the settings for this article but note the
following two options which are of particular interest for HA:
1. Multi-AZ-Deployment is recommended as redundancy. Read more at
@@ -133,7 +133,7 @@ IOPS (SSD) is best suited for HA. Read more about it at
![RDS Instance Specs](img/instance_specs.png)
-The rest of the setting on this page request a DB identifier, username
+The rest of the setting on this page request a DB identifier, username,
and a master password. We've chosen to use `gitlab-ha`, `gitlab` and a
very secure password respectively. Keep these in hand for later.
@@ -152,7 +152,7 @@ EC is an in-memory hosted caching solution. Redis maintains its own
persistence and is used for certain types of application.
Let's choose the ElastiCache service in the Database section from our
-AWS console. Now lets create a cache subnet group which will be very
+AWS console. Now let's create a cache subnet group which will be very
similar to the RDS subnet group. Make sure to select our VPC and its
private subnets.
@@ -160,7 +160,7 @@ private subnets.
Now press the Launch a Cache Cluster and choose Redis for our
DB engine. You'll be able to configure details such as replication,
-Multi AZ and node types. The second section will allow us to choose our
+Multi-AZ and node types. The second section will allow us to choose our
subnet and security group and
![Redis Cluster details](img/redis-cluster-det.png)
@@ -274,7 +274,7 @@ username, and password.
gitlab_rails['db_password'] = "mypassword"
gitlab_rails['db_host'] = "<rds-endpoint>"
-Next we only need to configure the Redis section by adding the host and
+Next, we only need to configure the Redis section by adding the host and
uncommenting the port.
@@ -285,8 +285,8 @@ to make the EFS integration easier to manage.
gitlab_rails['redis_host'] = "<redis-endpoint>"
gitlab_rails['redis_port'] = 6379
-Finally run reconfigure, you might find it useful to run a check and
-a service status to make sure everything has been setup correctly.
+Finally, run reconfigure. You might find it useful to run a check and
+a service status to make sure everything has been set up correctly.
sudo gitlab-ctl reconfigure
sudo gitlab-rake gitlab:check
@@ -321,10 +321,10 @@ The Load Balancer Health will allow us to indicate where to ping and what
makes up a healthy or unhealthy instance.
We won't add the instance on the next session because we'll destroy it
-momentarily as we'll be using the image we where creating. We will keep
+momentarily as we'll be using the image we were creating. We will keep
the Enable Cross-Zone and Enable Connection Draining active.
-After we finish creating the Load Balancer we can re visit our Security
+After we finish creating the Load Balancer we can revisit our Security
Groups to improve access only through the ELB and any other requirement
you might have.
@@ -363,7 +363,7 @@ After this is launched we are able to start creating our Auto Scaling
Group. Start by giving it a name and assigning it our VPC and private
subnets. We also want to always start with two instances and if you
scroll down to Advanced Details we can choose to receive traffic from ELBs.
-Lets enable that option and select our ELB. We also want to use the ELB's
+Let's enable that option and select our ELB. We also want to use the ELB's
health check.
![Auto scaling](img/auto-scaling-det.png)
@@ -388,9 +388,9 @@ we where aiming for.
After you're done with the policies section have some fun trying to break
instances. You should be able to see how the Auto Scaling Group and the
-EC2 screen start bringing them up again.
+EC2 screen starts bringing them up again.
-High Availability is a very big area, we went mostly through scaling and
+High Availability is a vast area, we went mostly through scaling and
some redundancy options but it might also imply Geographic replication.
There is a lot of ground yet to cover so have a read through these other
resources and feel free to open an issue to request additional material.
diff --git a/doc/university/support/README.md b/doc/university/support/README.md
index 0cbae71d1f5..805af253367 100644
--- a/doc/university/support/README.md
+++ b/doc/university/support/README.md
@@ -37,7 +37,7 @@ Continue to look over remaining portions of the [University Overview](../README.
Get your development machine ready to familiarize yourself with the codebase, the components, and to be prepared to reproduce issues that our users encounter
- Install the [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit)
- - [Setup OpenLDAP as part of this](https://gitlab.com/gitlab-org/gitlab-development-kit#openldap)
+ - [Set up OpenLDAP as part of this](https://gitlab.com/gitlab-org/gitlab-development-kit#openldap)
#### Become comfortable with the Installation processes that we support
diff --git a/doc/university/training/end-user/README.md b/doc/university/training/end-user/README.md
index 9b8a8db58e2..701533358c8 100644
--- a/doc/university/training/end-user/README.md
+++ b/doc/university/training/end-user/README.md
@@ -78,9 +78,9 @@ Workshop Time!
```bash
git config --global user.name "Your Name"
git config --global user.email you@example.com
-```
+```
-- If you don't use the global flag you can setup a different author for
+- If you don't use the global flag you can set up a different author for
each project
- Check settings with:
@@ -107,14 +107,14 @@ cd ~/development
-or-
mkdir ~/workspace
-cd ~/workspace
+cd ~/workspace
```
---
## Git Basics
----
+---
### Git Workflow
@@ -136,7 +136,7 @@ cd ~/workspace
issue tracking, Merge Requests, and other features.
- The hosted version of GitLab is gitlab.com
----
+---
### New Project
@@ -150,12 +150,12 @@ cd ~/workspace
### Git and GitLab basics
1. Edit `edit_this_file.rb` in `training-examples`
-2. See it listed as a changed file (working area)
-3. View the differences
-4. Stage the file
-5. Commit
-6. Push the commit to the remote
-7. View the git log
+1. See it listed as a changed file (working area)
+1. View the differences
+1. Stage the file
+1. Commit
+1. Push the commit to the remote
+1. View the git log
---
@@ -169,14 +169,14 @@ git push origin master
git log
```
----
+---
### Feature Branching
1. Create a new feature branch called `squash_some_bugs`
-2. Edit `bugs.rb` and remove all the bugs.
-3. Commit
-4. Push
+1. Edit `bugs.rb` and remove all the bugs.
+1. Commit
+1. Push
---
@@ -250,16 +250,17 @@ git push origin squash_some_bugs
---
### Example Plan
+
1. Checkout a new branch and edit conflicts.rb. Add 'Line4' and 'Line5'.
-2. Commit and push
-3. Checkout master and edit conflicts.rb. Add 'Line6' and 'Line7' below 'Line3'.
-4. Commit and push to master
-5. Create a merge request and watch it fail
-6. Rebase our new branch with master
-7. Fix conflicts on the conflicts.rb file.
-8. Stage the file and continue rebasing
-9. Force push the changes
-10. Finally continue with the Merge Request
+1. Commit and push
+1. Checkout master and edit conflicts.rb. Add 'Line6' and 'Line7' below 'Line3'.
+1. Commit and push to master
+1. Create a merge request and watch it fail
+1. Rebase our new branch with master
+1. Fix conflicts on the conflicts.rb file.
+1. Stage the file and continue rebasing
+1. Force push the changes
+1. Finally continue with the Merge Request
---
@@ -362,15 +363,15 @@ Don't reset after pushing
### Reset Workflow
1. Edit file again 'edit_this_file.rb'
-2. Check status
-3. Add and commit with wrong message
-4. Check log
-5. Amend commit
-6. Check log
-7. Soft reset
-8. Check log
-9. Pull for updates
-10. Push changes
+1. Check status
+1. Add and commit with wrong message
+1. Check log
+1. Amend commit
+1. Check log
+1. Soft reset
+1. Check log
+1. Pull for updates
+1. Push changes
----
@@ -389,9 +390,9 @@ Don't reset after pushing
### Note
-git revert vs git reset
-Reset removes the commit while revert removes the changes but leaves the commit
-Revert is safer considering we can revert a revert
+git revert vs git reset
+Reset removes the commit while revert removes the changes but leaves the commit
+Revert is safer considering we can revert a revert
# Changed file
diff --git a/doc/university/training/topics/additional_resources.md b/doc/university/training/topics/additional_resources.md
index d01634df744..4871372d105 100644
--- a/doc/university/training/topics/additional_resources.md
+++ b/doc/university/training/topics/additional_resources.md
@@ -4,9 +4,9 @@ comments: false
# Additional Resources
-1. GitLab Documentation [http://docs.gitlab.com](http://docs.gitlab.com/)
-2. GUI Clients [http://git-scm.com/downloads/guis](http://git-scm.com/downloads/guis)
-3. Pro git book [http://git-scm.com/book](http://git-scm.com/book)
-4. Platzi Course [https://courses.platzi.com/courses/git-gitlab/](https://courses.platzi.com/courses/git-gitlab/)
-5. Code School tutorial [http://try.github.io/](http://try.github.io/)
-6. Contact Us at `subscribers@gitlab.com`
+1. GitLab Documentation: <http://docs.gitlab.com>.
+1. GUI Clients: <http://git-scm.com/downloads/guis>.
+1. Pro Git book: <http://git-scm.com/book>.
+1. Platzi Course: <https://courses.platzi.com/courses/git-gitlab/>.
+1. Code School tutorial: <http://try.github.io/>.
+1. Contact us at `subscribers@gitlab.com`.
diff --git a/doc/university/training/topics/bisect.md b/doc/university/training/topics/bisect.md
index 01e93e4dcb0..4848d0412c1 100644
--- a/doc/university/training/topics/bisect.md
+++ b/doc/university/training/topics/bisect.md
@@ -2,7 +2,7 @@
comments: false
---
-# Bisect
+# Bisect
----------
@@ -17,11 +17,11 @@ comments: false
## Bisect
1. Start the bisect process
-2. Enter the bad revision (usually latest commit)
-3. Enter a known good revision (commit/branch)
-4. Run code to see if bug still exists
-5. Tell bisect the result
-6. Repeat the previous 2 items until you find the offending commit
+1. Enter the bad revision (usually latest commit)
+1. Enter a known good revision (commit/branch)
+1. Run code to see if bug still exists
+1. Tell bisect the result
+1. Repeat the previous 2 items until you find the offending commit
----------
diff --git a/doc/university/training/topics/getting_started.md b/doc/university/training/topics/getting_started.md
index 1441e4b89b2..66cb08feacb 100644
--- a/doc/university/training/topics/getting_started.md
+++ b/doc/university/training/topics/getting_started.md
@@ -35,11 +35,10 @@ comments: false
## Instantiate workflow with clone
-1. Create a project in your user namespace
- - Choose to import from 'Any Repo by URL' and use
- https://gitlab.com/gitlab-org/training-examples.git
-2. Create a '`Workspace`' directory in your home directory.
-3. Clone the '`training-examples`' project
+1. Create a project in your user namespace.
+ - Choose to import from 'Any Repo by URL' and use <https://gitlab.com/gitlab-org/training-examples.git>.
+1. Create a '`Workspace`' directory in your home directory.
+1. Clone the '`training-examples`' project.
----------
diff --git a/doc/university/training/topics/git_log.md b/doc/university/training/topics/git_log.md
index 3e39ea5cc9a..6ba6f9eb69d 100644
--- a/doc/university/training/topics/git_log.md
+++ b/doc/university/training/topics/git_log.md
@@ -46,11 +46,11 @@ Git log lists commit history. It allows searching and filtering.
## Git Log Workflow
1. Change to workspace directory
-2. Clone the multi runner projects
-3. Change to project dir
-4. Search by author
-5. Search by date
-6. Combine
+1. Clone the multi runner projects
+1. Change to project dir
+1. Search by author
+1. Search by date
+1. Combine
----------
diff --git a/doc/university/training/topics/merge_conflicts.md b/doc/university/training/topics/merge_conflicts.md
index 9a1ce550868..071baddf508 100644
--- a/doc/university/training/topics/merge_conflicts.md
+++ b/doc/university/training/topics/merge_conflicts.md
@@ -16,15 +16,15 @@ comments: false
## Merge conflicts
1. Checkout a new branch and edit `conflicts.rb`. Add 'Line4' and 'Line5'.
-2. Commit and push
-3. Checkout master and edit `conflicts.rb`. Add 'Line6' and 'Line7' below 'Line3'.
-4. Commit and push to master
-5. Create a merge request and watch it fail
-6. Rebase our new branch with master
-7. Fix conflicts on the `conflicts.rb` file.
-8. Stage the file and continue rebasing
-9. Force push the changes
-10. Finally continue with the Merge Request
+1. Commit and push.
+1. Checkout master and edit `conflicts.rb`. Add 'Line6' and 'Line7' below 'Line3'.
+1. Commit and push to master.
+1. Create a merge request and watch it fail.
+1. Rebase our new branch with master.
+1. Fix conflicts on the `conflicts.rb` file.
+1. Stage the file and continue rebasing.
+1. Force push the changes.
+1. Finally continue with the Merge Request.
----------
diff --git a/doc/university/training/topics/rollback_commits.md b/doc/university/training/topics/rollback_commits.md
index 11cb557651f..44304634f36 100644
--- a/doc/university/training/topics/rollback_commits.md
+++ b/doc/university/training/topics/rollback_commits.md
@@ -41,15 +41,15 @@ comments: false
## Reset Workflow
1. Edit file again 'edit_this_file.rb'
-2. Check status
-3. Add and commit with wrong message
-4. Check log
-5. Amend commit
-6. Check log
-7. Soft reset
-8. Check log
-9. Pull for updates
-10. Push changes
+1. Check status
+1. Add and commit with wrong message
+1. Check log
+1. Amend commit
+1. Check log
+1. Soft reset
+1. Check log
+1. Pull for updates
+1. Push changes
----------
diff --git a/doc/university/training/topics/stash.md b/doc/university/training/topics/stash.md
index 315ced1a196..42eedea14e5 100644
--- a/doc/university/training/topics/stash.md
+++ b/doc/university/training/topics/stash.md
@@ -66,12 +66,12 @@ stashes.
## Git Stash
1. Modify a file
-2. Stage file
-3. Stash it
-4. View our stash list
-5. Confirm no pending changes through status
-5. Apply with pop
-6. View list to confirm changes
+1. Stage file
+1. Stash it
+1. View our stash list
+1. Confirm no pending changes through status
+1. Apply with pop
+1. View list to confirm changes
----------
diff --git a/doc/university/training/topics/tags.md b/doc/university/training/topics/tags.md
index 6333ceedbd7..14c39457838 100644
--- a/doc/university/training/topics/tags.md
+++ b/doc/university/training/topics/tags.md
@@ -22,7 +22,7 @@ comments: false
**Additional resources**
-[http://git-scm.com/book/en/Git-Basics-Tagging](http://git-scm.com/book/en/Git-Basics-Tagging)
+<https://git-scm.com/book/en/Git-Basics-Tagging>
----------
diff --git a/doc/university/training/user_training.md b/doc/university/training/user_training.md
index dccb6cbf071..ca3f777f403 100644
--- a/doc/university/training/user_training.md
+++ b/doc/university/training/user_training.md
@@ -6,91 +6,90 @@ comments: false
---
-# Agenda
+## Agenda
-1. Brief history of Git
-1. GitLab walkthrough
-1. Configure your environment
-1. Workshop
+1. Brief history of Git.
+1. GitLab walkthrough.
+1. Configure your environment.
+1. Workshop.
---
-# Git introduction
+## Git introduction
-https://git-scm.com/about
+<https://git-scm.com/about>
-- Distributed version control
- - Does not rely on connection to a central server
- - Many copies of the complete history
-- Powerful branching and merging
-- Adapts to nearly any workflow
-- Fast, reliable and stable file format
+- Distributed version control.
+ - Does not rely on connection to a central server.
+ - Many copies of the complete history.
+- Powerful branching and merging.
+- Adapts to nearly any workflow.
+- Fast, reliable and stable file format.
---
-# Help!
+## Help!
Use the tools at your disposal when you get stuck.
-- Use '`git help <command>`' command
-- Use Google
-- Read documentation at https://git-scm.com
+- Use '`git help <command>`' command.
+- Use Google.
+- Read documentation at <https://git-scm.com>.
---
-# GitLab Walkthrough
+## GitLab Walkthrough
![fit](logo.png)
---
-# Configure your environment
+## Configure your environment
- Windows: Install 'Git for Windows'
-> https://git-for-windows.github.io
+> <https://git-for-windows.github.io>
- Mac: Type '`git`' in the Terminal application.
> If it's not installed, it will prompt you to install it.
-- Debian: '`sudo apt-get install git-all`'
-or Red Hat '`sudo yum install git-all`'
+- Debian: '`sudo apt-get install git-all`' or Red Hat '`sudo yum install git-all`'
---
-# Git Workshop
+## Git Workshop
-## Overview
+### Overview
-1. Configure Git
-1. Configure SSH Key
-1. Create a project
-1. Committing
-1. Feature branching
-1. Merge requests
-1. Feedback and Collaboration
+1. Configure Git.
+1. Configure SSH Key.
+1. Create a project.
+1. Committing.
+1. Feature branching.
+1. Merge requests.
+1. Feedback and Collaboration.
---
-# Configure Git
+## Configure Git
-One-time configuration of the Git client
+One-time configuration of the Git client:
-```bash
+```sh
git config --global user.name "Your Name"
git config --global user.email you@example.com
```
---
-# Configure SSH Key
+## Configure SSH Key
-```bash
+```sh
ssh-keygen -t rsa -b 4096 -C "you@computer-name"
```
-```bash
+```sh
# You will be prompted for the following information. Press enter to accept the defaults. Defaults appear in parentheses.
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/you/.ssh/id_rsa):
@@ -102,31 +101,30 @@ The key fingerprint is:
39:fc:ce:94:f4:09:13:95:64:9a:65:c1:de:05:4d:01 you@computer-name
```
-Copy your public key and add it to your GitLab profile
+Copy your public key and add it to your GitLab profile:
-```bash
+```sh
cat ~/.ssh/id_rsa.pub
```
-```bash
+```sh
ssh-rsa AAAAB3NzaC1yc2EAAAADAQEL17Ufacg8cDhlQMS5NhV8z3GHZdhCrZbl4gz you@example.com
```
---
-# Create a project
+## Create a project
-- Create a project in your user namespace
- - Choose to import from 'Any Repo by URL' and use
- https://gitlab.com/gitlab-org/training-examples.git
+- Create a project in your user namespace.
+ - Choose to import from 'Any Repo by URL' and use <https://gitlab.com/gitlab-org/training-examples.git>.
- Create a '`development`' or '`workspace`' directory in your home directory.
-- Clone the '`training-examples`' project
+- Clone the '`training-examples`' project.
---
-# Commands
+## Commands (project)
-```
+```sh
mkdir ~/development
cd ~/development
@@ -141,37 +139,37 @@ cd training-examples
---
-# Git concepts
+## Git concepts
-**Untracked files**
+### Untracked files
New files that Git has not been told to track previously.
-**Working area**
+### Working area
Files that have been modified but are not committed.
-**Staging area**
+### Staging area
Modified files that have been marked to go in the next commit.
---
-# Committing
+## Committing
-1. Edit '`edit_this_file.rb`' in '`training-examples`'
-1. See it listed as a changed file (working area)
-1. View the differences
-1. Stage the file
-1. Commit
-1. Push the commit to the remote
-1. View the git log
+1. Edit '`edit_this_file.rb`' in '`training-examples`'.
+1. See it listed as a changed file (working area).
+1. View the differences.
+1. Stage the file.
+1. Commit.
+1. Push the commit to the remote.
+1. View the git log.
---
-# Commands
+## Commands (committing)
-```
+```sh
# Edit `edit_this_file.rb`
git status
git diff
@@ -183,29 +181,29 @@ git log
---
-# Feature branching
+## Feature branching
-- Efficient parallel workflow for teams
-- Develop each feature in a branch
-- Keeps changes isolated
-- Consider a 1-to-1 link to issues
-- Push branches to the server frequently
- - Hint: This is a cheap backup for your work-in-progress code
+- Efficient parallel workflow for teams.
+- Develop each feature in a branch.
+- Keeps changes isolated.
+- Consider a 1-to-1 link to issues.
+- Push branches to the server frequently.
+ - Hint: This is a cheap backup for your work-in-progress code.
---
-# Feature branching
+## Feature branching steps
-1. Create a new feature branch called 'squash_some_bugs'
+1. Create a new feature branch called 'squash_some_bugs'.
1. Edit '`bugs.rb`' and remove all the bugs.
-1. Commit
-1. Push
+1. Commit.
+1. Push.
---
-# Commands
+## Commands (feature branching)
-```
+```sh
git checkout -b squash_some_bugs
# Edit `bugs.rb`
git status
@@ -216,51 +214,50 @@ git push origin squash_some_bugs
---
-# Merge requests
+## Merge requests
-- When you want feedback create a merge request
-- Target is the ‘default’ branch (usually master)
-- Assign or mention the person you would like to review
-- Add 'WIP' to the title if it's a work in progress
-- When accepting, always delete the branch
-- Anyone can comment, not just the assignee
-- Push corrections to the same branch
+- When you want feedback create a merge request.
+- Target is the ‘default’ branch (usually master).
+- Assign or mention the person you would like to review.
+- Add 'WIP' to the title if it's a work in progress.
+- When accepting, always delete the branch.
+- Anyone can comment, not just the assignee.
+- Push corrections to the same branch.
---
-# Merge requests
+## Merge requests steps
-**Create your first merge request**
+Create your first merge request:
-1. Use the blue button in the activity feed
-1. View the diff (changes) and leave a comment
-1. Push a new commit to the same branch
-1. Review the changes again and notice the update
+1. Use the blue button in the activity feed.
+1. View the diff (changes) and leave a comment.
+1. Push a new commit to the same branch.
+1. Review the changes again and notice the update.
---
-# Feedback and Collaboration
+## Feedback and Collaboration
-- Merge requests are a time for feedback and collaboration
-- Giving feedback is hard
-- Be as kind as possible
-- Receiving feedback is hard
-- Be as receptive as possible
-- Feedback is about the best code, not the person. You are not your code
+- Merge requests are a time for feedback and collaboration.
+- Giving feedback is hard.
+- Be as kind as possible.
+- Receiving feedback is hard.
+- Be as receptive as possible.
+- Feedback is about the best code, not the person. You are not your code.
---
-# Feedback and Collaboration
+## Feedback and Collaboration resources
Review the Thoughtbot code-review guide for suggestions to follow when reviewing merge requests:
-[https://github.com/thoughtbot/guides/tree/master/code-review](https://github.com/thoughtbot/guides/tree/master/code-review)
+<https://github.com/thoughtbot/guides/tree/master/code-review>.
-See GitLab merge requests for examples:
-[https://gitlab.com/gitlab-org/gitlab-ce/merge_requests](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests)
+See GitLab merge requests for examples: <https://gitlab.com/gitlab-org/gitlab-ce/merge_requests>.
---
-# Explore GitLab projects
+## Explore GitLab projects
![fit](logo.png)
@@ -274,31 +271,29 @@ See GitLab merge requests for examples:
---
-# Tags
+## Tags
-- Useful for marking deployments and releases
-- Annotated tags are an unchangeable part of Git history
-- Soft/lightweight tags can be set and removed at will
-- Many projects combine an annotated release tag with a stable branch
-- Consider setting deployment/release tags automatically
+- Useful for marking deployments and releases.
+- Annotated tags are an unchangeable part of Git history.
+- Soft/lightweight tags can be set and removed at will.
+- Many projects combine an annotated release tag with a stable branch.
+- Consider setting deployment/release tags automatically.
---
-# Tags
-
-- Create a lightweight tag
-- Create an annotated tag
-- Push the tags to the remote repository
+## Tags steps
-**Additional resources**
+1. Create a lightweight tag.
+1. Create an annotated tag.
+1. Push the tags to the remote repository.
-[http://git-scm.com/book/en/Git-Basics-Tagging](http://git-scm.com/book/en/Git-Basics-Tagging)
+Additional resources: <http://git-scm.com/book/en/Git-Basics-Tagging>.
---
-# Commands
+## Commands (tags)
-```
+```sh
git checkout master
# Lightweight tag
@@ -313,31 +308,31 @@ git push origin --tags
---
-# Merge conflicts
+## Merge conflicts
-- Happen often
-- Learning to fix conflicts is hard
-- Practice makes perfect
+- Happen often.
+- Learning to fix conflicts is hard.
+- Practice makes perfect.
- Force push after fixing conflicts. Be careful!
---
-# Merge conflicts
+## Merge conflicts steps
1. Checkout a new branch and edit `conflicts.rb`. Add 'Line4' and 'Line5'.
-1. Commit and push
+1. Commit and push.
1. Checkout master and edit `conflicts.rb`. Add 'Line6' and 'Line7' below 'Line3'.
-1. Commit and push to master
-1. Create a merge request
+1. Commit and push to master.
+1. Create a merge request.
---
-# Merge conflicts
+## Merge conflicts commands
After creating a merge request you should notice that conflicts exist. Resolve
the conflicts locally by rebasing.
-```
+```sh
git rebase master
# Fix conflicts by editing the files.
@@ -350,7 +345,7 @@ git push origin <branch> -f
---
-# Rebase with squash
+## Rebase with squash
You may end up with a commit log that looks like this:
@@ -368,11 +363,11 @@ Squash these in to meaningful commits using an interactive rebase.
---
-# Rebase with squash
+## Rebase with squash commands
Squash the commits on the same branch we used for the merge conflicts step.
-```
+```sh
git rebase -i master
```
@@ -380,17 +375,17 @@ In the editor, leave the first commit as 'pick' and set others to 'fixup'.
---
-# Questions?
+## Questions?
![fit](logo.png)
Thank you for your hard work!
-**Additional Resources**
+## Additional Resources
-GitLab Documentation [http://docs.gitlab.com](http://docs.gitlab.com/)
-GUI Clients [http://git-scm.com/downloads/guis](http://git-scm.com/downloads/guis)
-Pro git book [http://git-scm.com/book](http://git-scm.com/book)
-Platzi Course [https://courses.platzi.com/courses/git-gitlab/](https://courses.platzi.com/courses/git-gitlab/)
-Code School tutorial [http://try.github.io/](http://try.github.io/)
-Contact Us at `subscribers@gitlab.com`
+- GitLab Documentation: <http://docs.gitlab.com/>.
+- GUI Clients: <http://git-scm.com/downloads/guis>.
+- Pro Git book: <http://git-scm.com/book>.
+- Platzi Course: <https://courses.platzi.com/courses/git-gitlab/>.
+- Code School tutorial: <http://try.github.io/>.
+- Contact us at `subscribers@gitlab.com`.
diff --git a/doc/update/11.2-to-11-3.md b/doc/update/11.2-to-11-3.md
deleted file mode 100644
index d77f879ee57..00000000000
--- a/doc/update/11.2-to-11-3.md
+++ /dev/null
@@ -1,378 +0,0 @@
----
-comments: false
----
-
-# From 11.2 to 11.3
-
-Make sure you view this update guide from the branch (version) of GitLab you would
-like to install (e.g., `11-3-stable`. You can select the branch in the version
-dropdown at the top left corner of GitLab (below the menu bar).
-
-If the highest number stable branch is unclear please check the
-[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
-guide links by version.
-
-### 1. Stop server
-
-```bash
-sudo service gitlab stop
-```
-
-### 2. Backup
-
-NOTE: If you installed GitLab from source, make sure `rsync` is installed.
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
-```
-
-### 3. Update Ruby
-
-NOTE: GitLab 11.0 and higher only support Ruby 2.4.x and dropped support for Ruby 2.3.x. Be
-sure to upgrade your interpreter if necessary.
-
-You can check which version you are running with `ruby -v`.
-
-Download Ruby and compile it:
-
-```bash
-mkdir /tmp/ruby && cd /tmp/ruby
-curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.4.tar.gz
-echo 'ec82b0d53bd0adad9b19e6b45e44d54e9ec3f10c ruby-2.4.4.tar.gz' | shasum -c - && tar xzf ruby-2.4.4.tar.gz
-cd ruby-2.4.4
-
-./configure --disable-install-rdoc
-make
-sudo make install
-```
-
-Install Bundler:
-
-```bash
-sudo gem install bundler --no-ri --no-rdoc
-```
-
-### 4. Update Node
-
-GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets.
-This requires a minimum version of node v6.0.0.
-
-You can check which version you are running with `node -v`. If you are running
-a version older than `v6.0.0` you will need to update to a newer version. You
-can find instructions to install from community maintained packages or compile
-from source at the nodejs.org website.
-
-<https://nodejs.org/en/download/>
-
-GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript
-dependencies.
-
-```bash
-curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
-echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
-sudo apt-get update
-sudo apt-get install yarn
-```
-
-More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
-
-### 5. Update Go
-
-NOTE: GitLab 11.0 and higher only supports Go 1.9.x and newer, and dropped support for Go
-1.5.x through 1.8.x. Be sure to upgrade your installation if necessary.
-
-You can check which version you are running with `go version`.
-
-Download and install Go:
-
-```bash
-# Remove former Go installation folder
-sudo rm -rf /usr/local/go
-
-curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
-echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
- sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
-sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
-rm go1.10.3.linux-amd64.tar.gz
-```
-
-### 6. Get latest code
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git fetch --all --prune
-sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
-sudo -u git -H git checkout -- locale
-```
-
-For GitLab Community Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 11-3-stable
-```
-
-OR
-
-For GitLab Enterprise Edition:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H git checkout 11-3-stable-ee
-```
-
-### 7. Update gitlab-shell
-
-```bash
-cd /home/git/gitlab-shell
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
-sudo -u git -H bin/compile
-```
-
-### 8. Update gitlab-workhorse
-
-Install and compile gitlab-workhorse. GitLab-Workhorse uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-workhorse
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
-sudo -u git -H make
-```
-
-### 9. Update Gitaly
-
-#### New Gitaly configuration options required
-
-In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
-
-```shell
-echo '
-[gitaly-ruby]
-dir = "/home/git/gitaly/ruby"
-
-[gitlab-shell]
-dir = "/home/git/gitlab-shell"
-' | sudo -u git tee -a /home/git/gitaly/config.toml
-```
-
-#### Check Gitaly configuration
-
-Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
-configuration file may contain syntax errors. The block name
-`[[storages]]`, which may occur more than once in your `config.toml`
-file, should be `[[storage]]` instead.
-
-```shell
-sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
-```
-
-#### Compile Gitaly
-
-```shell
-cd /home/git/gitaly
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
-sudo -u git -H make
-```
-
-### 10. Update gitlab-pages
-
-#### Only needed if you use GitLab Pages.
-
-Install and compile gitlab-pages. GitLab-Pages uses
-[GNU Make](https://www.gnu.org/software/make/).
-If you are not using Linux you may have to run `gmake` instead of
-`make` below.
-
-```bash
-cd /home/git/gitlab-pages
-
-sudo -u git -H git fetch --all --tags --prune
-sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
-sudo -u git -H make
-```
-
-### 11. Update MySQL permissions
-
-If you are using MySQL you need to grant the GitLab user the necessary
-permissions on the database:
-
-```bash
-mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
-```
-
-If you use MySQL with replication, or just have MySQL configured with binary logging,
-you will need to also run the following on all of your MySQL servers:
-
-```bash
-mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
-```
-
-You can make this setting permanent by adding it to your `my.cnf`:
-
-```
-log_bin_trust_function_creators=1
-```
-
-### 12. Update configuration files
-
-#### New configuration options for `gitlab.yml`
-
-There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/11-1-stable:config/gitlab.yml.example origin/11-3-stable:config/gitlab.yml.example
-```
-
-#### Nginx configuration
-
-Ensure you're still up-to-date with the latest NGINX configuration changes:
-
-```sh
-cd /home/git/gitlab
-
-# For HTTPS configurations
-git diff origin/11-1-stable:lib/support/nginx/gitlab-ssl origin/11-3-stable:lib/support/nginx/gitlab-ssl
-
-# For HTTP configurations
-git diff origin/11-1-stable:lib/support/nginx/gitlab origin/11-3-stable:lib/support/nginx/gitlab
-```
-
-If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
-configuration as GitLab application no longer handles setting it.
-
-If you are using Apache instead of NGINX please see the updated [Apache templates].
-Also note that because Apache does not support upstreams behind Unix sockets you
-will need to let gitlab-workhorse listen on a TCP port. You can do this
-via [/etc/default/gitlab].
-
-[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
-[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-3-stable/lib/support/init.d/gitlab.default.example#L38
-
-#### SMTP configuration
-
-If you're installing from source and use SMTP to deliver mail, you will need to add the following line
-to config/initializers/smtp_settings.rb:
-
-```ruby
-ActionMailer::Base.delivery_method = :smtp
-```
-
-See [smtp_settings.rb.sample] as an example.
-
-[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-3-stable/config/initializers/smtp_settings.rb.sample#L13
-
-#### Init script
-
-There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
-
-```sh
-cd /home/git/gitlab
-
-git diff origin/11-1-stable:lib/support/init.d/gitlab.default.example origin/11-3-stable:lib/support/init.d/gitlab.default.example
-```
-
-Ensure you're still up-to-date with the latest init script changes:
-
-```bash
-cd /home/git/gitlab
-
-sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
-```
-
-For Ubuntu 16.04.1 LTS:
-
-```bash
-sudo systemctl daemon-reload
-```
-
-### 13. Install libs, migrations, etc.
-
-```bash
-cd /home/git/gitlab
-
-# MySQL installations (note: the line below states '--without postgres')
-sudo -u git -H bundle install --without postgres development test --deployment
-
-# PostgreSQL installations (note: the line below states '--without mysql')
-sudo -u git -H bundle install --without mysql development test --deployment
-
-# Optional: clean up old gems
-sudo -u git -H bundle clean
-
-# Run database migrations
-sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
-
-# Compile GetText PO files
-
-sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
-
-# Update node dependencies and recompile assets
-sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
-
-# Clean up cache
-sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
-```
-
-**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
-
-### 14. Start application
-
-```bash
-sudo service gitlab start
-sudo service nginx restart
-```
-
-### 15. Check application status
-
-Check if GitLab and its environment are configured correctly:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
-```
-
-To make sure you didn't miss anything run a more thorough check:
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
-```
-
-If all items are green, then congratulations, the upgrade is complete!
-
-## Things went south? Revert to previous version (11.2)
-
-### 1. Revert the code to the previous version
-
-Follow the [upgrade guide from 11.1 to 11.2](11.1-to-11.2.md), except for the
-database migration (the backup is already migrated to the previous version).
-
-### 2. Restore from the backup
-
-```bash
-cd /home/git/gitlab
-
-sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
-```
-
-If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
-
-[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-3-stable/config/gitlab.yml.example
-[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-3-stable/lib/support/init.d/gitlab.default.example
diff --git a/doc/update/11.2-to-11.3.md b/doc/update/11.2-to-11.3.md
new file mode 100644
index 00000000000..f2b8efc3e6e
--- /dev/null
+++ b/doc/update/11.2-to-11.3.md
@@ -0,0 +1,378 @@
+---
+comments: false
+---
+
+# From 11.2 to 11.3
+
+Make sure you view this update guide from the branch (version) of GitLab you would
+like to install (e.g., `11-3-stable`. You can select the branch in the version
+dropdown at the top left corner of GitLab (below the menu bar).
+
+If the highest number stable branch is unclear please check the
+[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
+guide links by version.
+
+### 1. Stop server
+
+```bash
+sudo service gitlab stop
+```
+
+### 2. Backup
+
+NOTE: If you installed GitLab from source, make sure `rsync` is installed.
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 3. Update Ruby
+
+NOTE: GitLab 11.0 and higher only support Ruby 2.4.x and dropped support for Ruby 2.3.x. Be
+sure to upgrade your interpreter if necessary.
+
+You can check which version you are running with `ruby -v`.
+
+Download Ruby and compile it:
+
+```bash
+mkdir /tmp/ruby && cd /tmp/ruby
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.4.tar.gz
+echo 'ec82b0d53bd0adad9b19e6b45e44d54e9ec3f10c ruby-2.4.4.tar.gz' | shasum -c - && tar xzf ruby-2.4.4.tar.gz
+cd ruby-2.4.4
+
+./configure --disable-install-rdoc
+make
+sudo make install
+```
+
+Install Bundler:
+
+```bash
+sudo gem install bundler --no-ri --no-rdoc
+```
+
+### 4. Update Node
+
+GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets.
+This requires a minimum version of node v6.0.0.
+
+You can check which version you are running with `node -v`. If you are running
+a version older than `v6.0.0` you will need to update to a newer version. You
+can find instructions to install from community maintained packages or compile
+from source at the nodejs.org website.
+
+<https://nodejs.org/en/download/>
+
+GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript
+dependencies.
+
+```bash
+curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
+echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
+sudo apt-get update
+sudo apt-get install yarn
+```
+
+More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
+
+### 5. Update Go
+
+NOTE: GitLab 11.0 and higher only supports Go 1.9.x and newer, and dropped support for Go
+1.5.x through 1.8.x. Be sure to upgrade your installation if necessary.
+
+You can check which version you are running with `go version`.
+
+Download and install Go:
+
+```bash
+# Remove former Go installation folder
+sudo rm -rf /usr/local/go
+
+curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
+echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
+ sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
+sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
+rm go1.10.3.linux-amd64.tar.gz
+```
+
+### 6. Get latest code
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git fetch --all --prune
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+sudo -u git -H git checkout -- locale
+```
+
+For GitLab Community Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 11-3-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 11-3-stable-ee
+```
+
+### 7. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+
+sudo -u git -H git fetch --all --tags --prune
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
+sudo -u git -H bin/compile
+```
+
+### 8. Update gitlab-workhorse
+
+Install and compile gitlab-workhorse. GitLab-Workhorse uses
+[GNU Make](https://www.gnu.org/software/make/).
+If you are not using Linux you may have to run `gmake` instead of
+`make` below.
+
+```bash
+cd /home/git/gitlab-workhorse
+
+sudo -u git -H git fetch --all --tags --prune
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
+sudo -u git -H make
+```
+
+### 9. Update Gitaly
+
+#### New Gitaly configuration options required
+
+In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
+
+```shell
+echo '
+[gitaly-ruby]
+dir = "/home/git/gitaly/ruby"
+
+[gitlab-shell]
+dir = "/home/git/gitlab-shell"
+' | sudo -u git tee -a /home/git/gitaly/config.toml
+```
+
+#### Check Gitaly configuration
+
+Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
+configuration file may contain syntax errors. The block name
+`[[storages]]`, which may occur more than once in your `config.toml`
+file, should be `[[storage]]` instead.
+
+```shell
+sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
+```
+
+#### Compile Gitaly
+
+```shell
+cd /home/git/gitaly
+sudo -u git -H git fetch --all --tags --prune
+sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
+sudo -u git -H make
+```
+
+### 10. Update gitlab-pages
+
+#### Only needed if you use GitLab Pages.
+
+Install and compile gitlab-pages. GitLab-Pages uses
+[GNU Make](https://www.gnu.org/software/make/).
+If you are not using Linux you may have to run `gmake` instead of
+`make` below.
+
+```bash
+cd /home/git/gitlab-pages
+
+sudo -u git -H git fetch --all --tags --prune
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
+sudo -u git -H make
+```
+
+### 11. Update MySQL permissions
+
+If you are using MySQL you need to grant the GitLab user the necessary
+permissions on the database:
+
+```bash
+mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
+```
+
+If you use MySQL with replication, or just have MySQL configured with binary logging,
+you will need to also run the following on all of your MySQL servers:
+
+```bash
+mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
+```
+
+You can make this setting permanent by adding it to your `my.cnf`:
+
+```
+log_bin_trust_function_creators=1
+```
+
+### 12. Update configuration files
+
+#### New configuration options for `gitlab.yml`
+
+There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/11-2-stable:config/gitlab.yml.example origin/11-3-stable:config/gitlab.yml.example
+```
+
+#### Nginx configuration
+
+Ensure you're still up-to-date with the latest NGINX configuration changes:
+
+```sh
+cd /home/git/gitlab
+
+# For HTTPS configurations
+git diff origin/11-2-stable:lib/support/nginx/gitlab-ssl origin/11-3-stable:lib/support/nginx/gitlab-ssl
+
+# For HTTP configurations
+git diff origin/11-2-stable:lib/support/nginx/gitlab origin/11-3-stable:lib/support/nginx/gitlab
+```
+
+If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
+configuration as GitLab application no longer handles setting it.
+
+If you are using Apache instead of NGINX please see the updated [Apache templates].
+Also note that because Apache does not support upstreams behind Unix sockets you
+will need to let gitlab-workhorse listen on a TCP port. You can do this
+via [/etc/default/gitlab].
+
+[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
+[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-3-stable/lib/support/init.d/gitlab.default.example#L38
+
+#### SMTP configuration
+
+If you're installing from source and use SMTP to deliver mail, you will need to add the following line
+to config/initializers/smtp_settings.rb:
+
+```ruby
+ActionMailer::Base.delivery_method = :smtp
+```
+
+See [smtp_settings.rb.sample] as an example.
+
+[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-3-stable/config/initializers/smtp_settings.rb.sample#L13
+
+#### Init script
+
+There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/11-2-stable:lib/support/init.d/gitlab.default.example origin/11-3-stable:lib/support/init.d/gitlab.default.example
+```
+
+Ensure you're still up-to-date with the latest init script changes:
+
+```bash
+cd /home/git/gitlab
+
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
+For Ubuntu 16.04.1 LTS:
+
+```bash
+sudo systemctl daemon-reload
+```
+
+### 13. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without postgres')
+sudo -u git -H bundle install --without postgres development test --deployment
+
+# PostgreSQL installations (note: the line below states '--without mysql')
+sudo -u git -H bundle install --without mysql development test --deployment
+
+# Optional: clean up old gems
+sudo -u git -H bundle clean
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Compile GetText PO files
+
+sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
+
+# Update node dependencies and recompile assets
+sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
+
+# Clean up cache
+sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
+```
+
+**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
+
+### 14. Start application
+
+```bash
+sudo service gitlab start
+sudo service nginx restart
+```
+
+### 15. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+```
+
+To make sure you didn't miss anything run a more thorough check:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+```
+
+If all items are green, then congratulations, the upgrade is complete!
+
+## Things went south? Revert to previous version (11.2)
+
+### 1. Revert the code to the previous version
+
+Follow the [upgrade guide from 11.1 to 11.2](11.1-to-11.2.md), except for the
+database migration (the backup is already migrated to the previous version).
+
+### 2. Restore from the backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+
+If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-3-stable/config/gitlab.yml.example
+[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-3-stable/lib/support/init.d/gitlab.default.example
diff --git a/doc/update/11.3-to-11.4.md b/doc/update/11.3-to-11.4.md
new file mode 100644
index 00000000000..fddec45e57a
--- /dev/null
+++ b/doc/update/11.3-to-11.4.md
@@ -0,0 +1,378 @@
+---
+comments: false
+---
+
+# From 11.3 to 11.4
+
+Make sure you view this update guide from the branch (version) of GitLab you would
+like to install (e.g., `11-4-stable`. You can select the branch in the version
+dropdown at the top left corner of GitLab (below the menu bar).
+
+If the highest number stable branch is unclear please check the
+[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
+guide links by version.
+
+### 1. Stop server
+
+```bash
+sudo service gitlab stop
+```
+
+### 2. Backup
+
+NOTE: If you installed GitLab from source, make sure `rsync` is installed.
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 3. Update Ruby
+
+NOTE: GitLab 11.0 and higher only support Ruby 2.4.x and dropped support for Ruby 2.3.x. Be
+sure to upgrade your interpreter if necessary.
+
+You can check which version you are running with `ruby -v`.
+
+Download Ruby and compile it:
+
+```bash
+mkdir /tmp/ruby && cd /tmp/ruby
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.5.tar.gz
+echo '4d650f302f1ec00256450b112bb023644b6ab6dd ruby-2.4.5.tar.gz' | shasum -c - && tar xzf ruby-2.4.5.tar.gz
+cd ruby-2.4.5
+
+./configure --disable-install-rdoc
+make
+sudo make install
+```
+
+Install Bundler:
+
+```bash
+sudo gem install bundler --no-ri --no-rdoc
+```
+
+### 4. Update Node
+
+GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets.
+This requires a minimum version of node v6.0.0.
+
+You can check which version you are running with `node -v`. If you are running
+a version older than `v6.0.0` you will need to update to a newer version. You
+can find instructions to install from community maintained packages or compile
+from source at the nodejs.org website.
+
+<https://nodejs.org/en/download/>
+
+GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript
+dependencies.
+
+```bash
+curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
+echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
+sudo apt-get update
+sudo apt-get install yarn
+```
+
+More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
+
+### 5. Update Go
+
+NOTE: GitLab 11.4 and higher only supports Go 1.10.x and newer, and dropped support for Go
+1.9.x. Be sure to upgrade your installation if necessary.
+
+You can check which version you are running with `go version`.
+
+Download and install Go:
+
+```bash
+# Remove former Go installation folder
+sudo rm -rf /usr/local/go
+
+curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz
+echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \
+ sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
+sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
+rm go1.10.3.linux-amd64.tar.gz
+```
+
+### 6. Get latest code
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git fetch --all --prune
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+sudo -u git -H git checkout -- locale
+```
+
+For GitLab Community Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 11-4-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 11-4-stable-ee
+```
+
+### 7. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+
+sudo -u git -H git fetch --all --tags --prune
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
+sudo -u git -H bin/compile
+```
+
+### 8. Update gitlab-workhorse
+
+Install and compile gitlab-workhorse. GitLab-Workhorse uses
+[GNU Make](https://www.gnu.org/software/make/).
+If you are not using Linux you may have to run `gmake` instead of
+`make` below.
+
+```bash
+cd /home/git/gitlab-workhorse
+
+sudo -u git -H git fetch --all --tags --prune
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
+sudo -u git -H make
+```
+
+### 9. Update Gitaly
+
+#### New Gitaly configuration options required
+
+In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`.
+
+```shell
+echo '
+[gitaly-ruby]
+dir = "/home/git/gitaly/ruby"
+
+[gitlab-shell]
+dir = "/home/git/gitlab-shell"
+' | sudo -u git tee -a /home/git/gitaly/config.toml
+```
+
+#### Check Gitaly configuration
+
+Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
+configuration file may contain syntax errors. The block name
+`[[storages]]`, which may occur more than once in your `config.toml`
+file, should be `[[storage]]` instead.
+
+```shell
+sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
+```
+
+#### Compile Gitaly
+
+```shell
+cd /home/git/gitaly
+sudo -u git -H git fetch --all --tags --prune
+sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
+sudo -u git -H make
+```
+
+### 10. Update gitlab-pages
+
+#### Only needed if you use GitLab Pages.
+
+Install and compile gitlab-pages. GitLab-Pages uses
+[GNU Make](https://www.gnu.org/software/make/).
+If you are not using Linux you may have to run `gmake` instead of
+`make` below.
+
+```bash
+cd /home/git/gitlab-pages
+
+sudo -u git -H git fetch --all --tags --prune
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
+sudo -u git -H make
+```
+
+### 11. Update MySQL permissions
+
+If you are using MySQL you need to grant the GitLab user the necessary
+permissions on the database:
+
+```bash
+mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
+```
+
+If you use MySQL with replication, or just have MySQL configured with binary logging,
+you will need to also run the following on all of your MySQL servers:
+
+```bash
+mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
+```
+
+You can make this setting permanent by adding it to your `my.cnf`:
+
+```
+log_bin_trust_function_creators=1
+```
+
+### 12. Update configuration files
+
+#### New configuration options for `gitlab.yml`
+
+There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/11-3-stable:config/gitlab.yml.example origin/11-4-stable:config/gitlab.yml.example
+```
+
+#### Nginx configuration
+
+Ensure you're still up-to-date with the latest NGINX configuration changes:
+
+```sh
+cd /home/git/gitlab
+
+# For HTTPS configurations
+git diff origin/11-3-stable:lib/support/nginx/gitlab-ssl origin/11-4-stable:lib/support/nginx/gitlab-ssl
+
+# For HTTP configurations
+git diff origin/11-3-stable:lib/support/nginx/gitlab origin/11-4-stable:lib/support/nginx/gitlab
+```
+
+If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
+configuration as GitLab application no longer handles setting it.
+
+If you are using Apache instead of NGINX please see the updated [Apache templates].
+Also note that because Apache does not support upstreams behind Unix sockets you
+will need to let gitlab-workhorse listen on a TCP port. You can do this
+via [/etc/default/gitlab].
+
+[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
+[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-4-stable/lib/support/init.d/gitlab.default.example#L38
+
+#### SMTP configuration
+
+If you're installing from source and use SMTP to deliver mail, you will need to add the following line
+to config/initializers/smtp_settings.rb:
+
+```ruby
+ActionMailer::Base.delivery_method = :smtp
+```
+
+See [smtp_settings.rb.sample] as an example.
+
+[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-4-stable/config/initializers/smtp_settings.rb.sample#L13
+
+#### Init script
+
+There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/11-3-stable:lib/support/init.d/gitlab.default.example origin/11-4-stable:lib/support/init.d/gitlab.default.example
+```
+
+Ensure you're still up-to-date with the latest init script changes:
+
+```bash
+cd /home/git/gitlab
+
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
+For Ubuntu 16.04.1 LTS:
+
+```bash
+sudo systemctl daemon-reload
+```
+
+### 13. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without postgres')
+sudo -u git -H bundle install --without postgres development test --deployment
+
+# PostgreSQL installations (note: the line below states '--without mysql')
+sudo -u git -H bundle install --without mysql development test --deployment
+
+# Optional: clean up old gems
+sudo -u git -H bundle clean
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Compile GetText PO files
+
+sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
+
+# Update node dependencies and recompile assets
+sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
+
+# Clean up cache
+sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
+```
+
+**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
+
+### 14. Start application
+
+```bash
+sudo service gitlab start
+sudo service nginx restart
+```
+
+### 15. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+```
+
+To make sure you didn't miss anything run a more thorough check:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+```
+
+If all items are green, then congratulations, the upgrade is complete!
+
+## Things went south? Revert to previous version (11.3)
+
+### 1. Revert the code to the previous version
+
+Follow the [upgrade guide from 11.2 to 11.3](11.2-to-11.3.md), except for the
+database migration (the backup is already migrated to the previous version).
+
+### 2. Restore from the backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+
+If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-4-stable/config/gitlab.yml.example
+[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-4-stable/lib/support/init.d/gitlab.default.example
diff --git a/doc/update/11.4-to-11.5.md b/doc/update/11.4-to-11.5.md
new file mode 100644
index 00000000000..44105348d14
--- /dev/null
+++ b/doc/update/11.4-to-11.5.md
@@ -0,0 +1,390 @@
+---
+comments: false
+---
+
+# From 11.4 to 11.5
+
+Make sure you view this update guide from the branch (version) of GitLab you would
+like to install (e.g., `11-5-stable`. You can select the branch in the version
+dropdown at the top left corner of GitLab (below the menu bar).
+
+If the highest number stable branch is unclear please check the
+[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation
+guide links by version.
+
+### 1. Stop server
+
+```bash
+sudo service gitlab stop
+```
+
+### 2. Backup
+
+NOTE: If you installed GitLab from source, make sure `rsync` is installed.
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
+```
+
+### 3. Update Ruby
+
+NOTE: GitLab 11.0 and higher only support Ruby 2.4.x and dropped support for Ruby 2.3.x. Be
+sure to upgrade your interpreter if necessary.
+
+You can check which version you are running with `ruby -v`.
+
+Download Ruby and compile it:
+
+```bash
+mkdir /tmp/ruby && cd /tmp/ruby
+curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.5.tar.gz
+echo '4d650f302f1ec00256450b112bb023644b6ab6dd ruby-2.4.5.tar.gz' | shasum -c - && tar xzf ruby-2.4.5.tar.gz
+cd ruby-2.4.5
+
+./configure --disable-install-rdoc
+make
+sudo make install
+```
+
+Install Bundler:
+
+```bash
+sudo gem install bundler --no-ri --no-rdoc
+```
+
+### 4. Update Node
+
+GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets.
+This requires a minimum version of node v6.0.0.
+
+You can check which version you are running with `node -v`. If you are running
+a version older than `v6.0.0` you will need to update to a newer version. You
+can find instructions to install from community maintained packages or compile
+from source at the nodejs.org website.
+
+<https://nodejs.org/en/download/>
+
+GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript
+dependencies.
+
+```bash
+curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
+echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
+sudo apt-get update
+sudo apt-get install yarn
+```
+
+More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install).
+
+### 5. Update Go
+
+NOTE: GitLab 11.4 and higher only supports Go 1.10.x and newer, and dropped support for Go
+1.9.x. Be sure to upgrade your installation if necessary.
+
+You can check which version you are running with `go version`.
+
+Download and install Go:
+
+```bash
+# Remove former Go installation folder
+sudo rm -rf /usr/local/go
+
+curl --remote-name --progress https://dl.google.com/go/go1.10.5.linux-amd64.tar.gz
+echo 'a035d9beda8341b645d3f45a1b620cf2d8fb0c5eb409be36b389c0fd384ecc3a go1.10.5.linux-amd64.tar.gz' | shasum -a256 -c - && \
+ sudo tar -C /usr/local -xzf go1.10.5.linux-amd64.tar.gz
+sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/
+rm go1.10.5.linux-amd64.tar.gz
+```
+
+### 6. Get latest code
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git fetch --all --prune
+sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
+sudo -u git -H git checkout -- locale
+```
+
+For GitLab Community Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 11-5-stable
+```
+
+OR
+
+For GitLab Enterprise Edition:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H git checkout 11-5-stable-ee
+```
+
+### 7. Update gitlab-shell
+
+```bash
+cd /home/git/gitlab-shell
+
+sudo -u git -H git fetch --all --tags --prune
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION)
+sudo -u git -H bin/compile
+```
+
+### 8. Update gitlab-workhorse
+
+Install and compile gitlab-workhorse. GitLab-Workhorse uses
+[GNU Make](https://www.gnu.org/software/make/).
+If you are not using Linux you may have to run `gmake` instead of
+`make` below.
+
+```bash
+cd /home/git/gitlab-workhorse
+
+sudo -u git -H git fetch --all --tags --prune
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION)
+sudo -u git -H make
+```
+
+### 9. Update Gitaly
+
+#### Check Gitaly configuration
+
+Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly
+configuration file may contain syntax errors. The block name
+`[[storages]]`, which may occur more than once in your `config.toml`
+file, should be `[[storage]]` instead.
+
+```shell
+sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml
+```
+
+#### Compile Gitaly
+
+```shell
+cd /home/git/gitaly
+sudo -u git -H git fetch --all --tags --prune
+sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION)
+sudo -u git -H make
+```
+
+### 10. Update gitlab-pages
+
+#### Only needed if you use GitLab Pages.
+
+Install and compile gitlab-pages. GitLab-Pages uses
+[GNU Make](https://www.gnu.org/software/make/).
+If you are not using Linux you may have to run `gmake` instead of
+`make` below.
+
+```bash
+cd /home/git/gitlab-pages
+
+sudo -u git -H git fetch --all --tags --prune
+sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_PAGES_VERSION)
+sudo -u git -H make
+```
+
+### 11. Update MySQL permissions
+
+If you are using MySQL you need to grant the GitLab user the necessary
+permissions on the database:
+
+```bash
+mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';"
+```
+
+If you use MySQL with replication, or just have MySQL configured with binary logging,
+you will need to also run the following on all of your MySQL servers:
+
+```bash
+mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;"
+```
+
+You can make this setting permanent by adding it to your `my.cnf`:
+
+```
+log_bin_trust_function_creators=1
+```
+
+### 12. Update configuration files
+
+#### New `unicorn.rb` configuration
+
+Note: we have made [changes](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22372) to `unicorn.rb` to allow GitLab run with both Unicorn and Puma in future.
+
+- Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/11-5-stable/config/unicorn.rb.example but with your settings.
+ - In particular, make sure that `require_relative "/home/git/gitlab/lib/gitlab/cluster/lifecycle_events"` line exists and the `before_exec`, `before_fork`, and `after_fork` handlers are configured as shown below:
+
+```ruby
+require_relative "/home/git/gitlab/lib/gitlab/cluster/lifecycle_events"
+
+before_exec do |server|
+ # Signal application hooks that we're about to restart
+ Gitlab::Cluster::LifecycleEvents.do_master_restart
+end
+
+before_fork do |server, worker|
+ # Signal application hooks that we're about to fork
+ Gitlab::Cluster::LifecycleEvents.do_before_fork
+end
+
+after_fork do |server, worker|
+ # Signal application hooks of worker start
+ Gitlab::Cluster::LifecycleEvents.do_worker_start
+end
+```
+
+#### New configuration options for `gitlab.yml`
+
+There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/11-4-stable:config/gitlab.yml.example origin/11-5-stable:config/gitlab.yml.example
+```
+
+#### Nginx configuration
+
+Ensure you're still up-to-date with the latest NGINX configuration changes:
+
+```sh
+cd /home/git/gitlab
+
+# For HTTPS configurations
+git diff origin/11-4-stable:lib/support/nginx/gitlab-ssl origin/11-5-stable:lib/support/nginx/gitlab-ssl
+
+# For HTTP configurations
+git diff origin/11-4-stable:lib/support/nginx/gitlab origin/11-5-stable:lib/support/nginx/gitlab
+```
+
+If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
+configuration as GitLab application no longer handles setting it.
+
+If you are using Apache instead of NGINX please see the updated [Apache templates].
+Also note that because Apache does not support upstreams behind Unix sockets you
+will need to let gitlab-workhorse listen on a TCP port. You can do this
+via [/etc/default/gitlab].
+
+[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache
+[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-5-stable/lib/support/init.d/gitlab.default.example#L38
+
+#### SMTP configuration
+
+If you're installing from source and use SMTP to deliver mail, you will need to add the following line
+to config/initializers/smtp_settings.rb:
+
+```ruby
+ActionMailer::Base.delivery_method = :smtp
+```
+
+See [smtp_settings.rb.sample] as an example.
+
+[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-5-stable/config/initializers/smtp_settings.rb.sample#L13
+
+#### Init script
+
+There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`:
+
+```sh
+cd /home/git/gitlab
+
+git diff origin/11-4-stable:lib/support/init.d/gitlab.default.example origin/11-5-stable:lib/support/init.d/gitlab.default.example
+```
+
+Ensure you're still up-to-date with the latest init script changes:
+
+```bash
+cd /home/git/gitlab
+
+sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
+```
+
+For Ubuntu 16.04.1 LTS:
+
+```bash
+sudo systemctl daemon-reload
+```
+
+### 13. Install libs, migrations, etc.
+
+```bash
+cd /home/git/gitlab
+
+# MySQL installations (note: the line below states '--without postgres')
+sudo -u git -H bundle install --without postgres development test --deployment
+
+# PostgreSQL installations (note: the line below states '--without mysql')
+sudo -u git -H bundle install --without mysql development test --deployment
+
+# Optional: clean up old gems
+sudo -u git -H bundle clean
+
+# Run database migrations
+sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Compile GetText PO files
+
+sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
+
+# Update node dependencies and recompile assets
+sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
+
+# Clean up cache
+sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production
+```
+
+**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md).
+
+### 14. Start application
+
+```bash
+sudo service gitlab start
+sudo service nginx restart
+```
+
+### 15. Check application status
+
+Check if GitLab and its environment are configured correctly:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
+```
+
+To make sure you didn't miss anything run a more thorough check:
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
+```
+
+If all items are green, then congratulations, the upgrade is complete!
+
+## Things went south? Revert to previous version (11.4)
+
+### 1. Revert the code to the previous version
+
+Follow the [upgrade guide from 11.3 to 11.4](11.3-to-11.4.md), except for the
+database migration (the backup is already migrated to the previous version).
+
+### 2. Restore from the backup
+
+```bash
+cd /home/git/gitlab
+
+sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
+```
+
+If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above.
+
+[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-5-stable/config/gitlab.yml.example
+[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-5-stable/lib/support/init.d/gitlab.default.example
diff --git a/doc/update/4.2-to-5.0.md b/doc/update/4.2-to-5.0.md
index 311664b2bc1..d292327efbd 100644
--- a/doc/update/4.2-to-5.0.md
+++ b/doc/update/4.2-to-5.0.md
@@ -32,7 +32,7 @@ cd /home/git/
sudo -u git -H git clone https://github.com/gitlabhq/gitlab-shell.git /home/git/gitlab-shell
```
-## 3. setup gitlab-shell
+## 3. set up gitlab-shell
```bash
# chmod all repos and files under git
diff --git a/doc/update/6.x-or-7.x-to-7.14.md b/doc/update/6.x-or-7.x-to-7.14.md
index 41d0e78b7d8..61854b91aa2 100644
--- a/doc/update/6.x-or-7.x-to-7.14.md
+++ b/doc/update/6.x-or-7.x-to-7.14.md
@@ -20,7 +20,7 @@ database migrations for GitLab 7.2.
## Stash changes
-If you [deleted the vendors folder during your original installation](https://github.com/gitlabhq/gitlabhq/issues/4883#issuecomment-31108431), [you will get an error](https://gitlab.com/gitlab-org/gitlab-ce/issues/1494) when you attempt to rebuild the assets in step 7. To avoid this, stash the changes in your GitLab working copy before starting:
+If you deleted the vendors folder during your original installation, [you will get an error](https://gitlab.com/gitlab-org/gitlab-ce/issues/1494) when you attempt to rebuild the assets in step 7. To avoid this, stash the changes in your GitLab working copy before starting:
git stash
diff --git a/doc/update/7.5-to-7.6.md b/doc/update/7.5-to-7.6.md
index f0dfb177b79..0d45a9528b9 100644
--- a/doc/update/7.5-to-7.6.md
+++ b/doc/update/7.5-to-7.6.md
@@ -82,7 +82,7 @@ git diff origin/7-5-stable:config/gitlab.yml.example origin/7-6-stable:config/gi
* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`][nginx] but with your settings
* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`][nginx-ssl] but with your setting
-#### Setup time zone (optional)
+#### Set up time zone (optional)
Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`][app] (unlikely), unset it.
diff --git a/doc/update/7.6-to-7.7.md b/doc/update/7.6-to-7.7.md
index 85de6b0c546..5e0b2ca7bcd 100644
--- a/doc/update/7.6-to-7.7.md
+++ b/doc/update/7.6-to-7.7.md
@@ -82,7 +82,7 @@ git diff origin/7-6-stable:config/gitlab.yml.example origin/7-7-stable:config/gi
* HTTP setups: Make `/etc/nginx/sites-available/gitlab` the same as [`lib/support/nginx/gitlab`][nginx] but with your settings
* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`][nginx-ssl] but with your setting
-#### Setup time zone (optional)
+#### Set up time zone (optional)
Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`][app] (unlikely), unset it.
diff --git a/doc/update/7.7-to-7.8.md b/doc/update/7.7-to-7.8.md
index 7cee5f79a13..f5b1ebf0a9c 100644
--- a/doc/update/7.7-to-7.8.md
+++ b/doc/update/7.7-to-7.8.md
@@ -83,7 +83,7 @@ git diff origin/7-7-stable:config/gitlab.yml.example origin/7-8-stable:config/gi
* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`][nginx-ssl] but with your settings.
* A new `location /uploads/` section has been added that needs to have the same content as the existing `location @gitlab` section.
-#### Setup time zone (optional)
+#### Set up time zone (optional)
Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`][app] (unlikely), unset it.
diff --git a/doc/update/7.8-to-7.9.md b/doc/update/7.8-to-7.9.md
index 5a8b689dbc1..0db7698936b 100644
--- a/doc/update/7.8-to-7.9.md
+++ b/doc/update/7.8-to-7.9.md
@@ -85,7 +85,7 @@ git diff origin/7-8-stable:config/gitlab.yml.example origin/7-9-stable:config/gi
* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`][nginx-ssl] but with your settings.
* A new `location /uploads/` section has been added that needs to have the same content as the existing `location @gitlab` section.
-#### Setup time zone (optional)
+#### Set up time zone (optional)
Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`][app] (unlikely), unset it.
diff --git a/doc/update/7.9-to-7.10.md b/doc/update/7.9-to-7.10.md
index 99df51dbb99..782fb0736e6 100644
--- a/doc/update/7.9-to-7.10.md
+++ b/doc/update/7.9-to-7.10.md
@@ -81,7 +81,7 @@ git diff origin/7-9-stable:config/gitlab.yml.example origin/7-10-stable:config/g
* HTTPS setups: Make `/etc/nginx/sites-available/gitlab-ssl` the same as [`lib/support/nginx/gitlab-ssl`][nginx-ssl] but with your settings.
* A new `location /uploads/` section has been added that needs to have the same content as the existing `location @gitlab` section.
-#### Setup time zone (optional)
+#### Set up time zone (optional)
Consider setting the time zone in `gitlab.yml` otherwise GitLab will default to UTC. If you set a time zone previously in [`application.rb`][app] (unlikely), unset it.
diff --git a/doc/update/8.17-to-9.0.md b/doc/update/8.17-to-9.0.md
index 74ce52859fa..3c73bc573a6 100644
--- a/doc/update/8.17-to-9.0.md
+++ b/doc/update/8.17-to-9.0.md
@@ -269,7 +269,7 @@ sudo systemctl daemon-reload
### 9. Install libs, migrations, etc.
GitLab 9.0.11 [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/24570)
-a dependency on on the `re2` regular expression library. To install this dependency:
+a dependency on the `re2` regular expression library. To install this dependency:
```bash
sudo apt-get install libre2-dev
diff --git a/doc/update/9.0-to-9.1.md b/doc/update/9.0-to-9.1.md
index 3a806d2f8c8..7c9dacc9b90 100644
--- a/doc/update/9.0-to-9.1.md
+++ b/doc/update/9.0-to-9.1.md
@@ -269,7 +269,7 @@ sudo systemctl daemon-reload
### 9. Install libs, migrations, etc.
GitLab 9.1.8 [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/24570)
-a dependency on on the `re2` regular expression library. To install this dependency:
+a dependency on the `re2` regular expression library. To install this dependency:
```bash
sudo apt-get install libre2-dev
diff --git a/doc/update/9.1-to-9.2.md b/doc/update/9.1-to-9.2.md
index 2fff6544797..b815242ab4e 100644
--- a/doc/update/9.1-to-9.2.md
+++ b/doc/update/9.1-to-9.2.md
@@ -227,7 +227,7 @@ sudo systemctl daemon-reload
### 10. Install libs, migrations, etc.
GitLab 9.2.8 [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/24570)
-a dependency on on the `re2` regular expression library. To install this dependency:
+a dependency on the `re2` regular expression library. To install this dependency:
```bash
sudo apt-get install libre2-dev
diff --git a/doc/update/9.2-to-9.3.md b/doc/update/9.2-to-9.3.md
index 1b36cf53f4c..a58b12cb81c 100644
--- a/doc/update/9.2-to-9.3.md
+++ b/doc/update/9.2-to-9.3.md
@@ -263,7 +263,7 @@ sudo systemctl daemon-reload
### 12. Install libs, migrations, etc.
GitLab 9.3.8 [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/24570)
-a dependency on on the `re2` regular expression library. To install this dependency:
+a dependency on the `re2` regular expression library. To install this dependency:
```bash
sudo apt-get install libre2-dev
diff --git a/doc/update/9.3-to-9.4.md b/doc/update/9.3-to-9.4.md
index 210b6eb607d..0c87468334b 100644
--- a/doc/update/9.3-to-9.4.md
+++ b/doc/update/9.3-to-9.4.md
@@ -276,7 +276,7 @@ sudo systemctl daemon-reload
### 12. Install libs, migrations, etc.
GitLab 9.4 [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/24570)
-a dependency on on the `re2` regular expression library. To install this dependency:
+a dependency on the `re2` regular expression library. To install this dependency:
```bash
sudo apt-get install libre2-dev
diff --git a/doc/update/README.md b/doc/update/README.md
index 2c1fbc15719..d4fc0cc91bf 100644
--- a/doc/update/README.md
+++ b/doc/update/README.md
@@ -38,11 +38,12 @@ Starting with GitLab 9.1.0 it's possible to upgrade to a newer major, minor, or
patch version of GitLab without having to take your GitLab instance offline.
However, for this to work there are the following requirements:
-1. You can only upgrade 1 minor release at a time. So from 9.1 to 9.2, not to
+- You can only upgrade 1 minor release at a time. So from 9.1 to 9.2, not to
9.3.
-2. You have to use [post-deployment
- migrations](../development/post_deployment_migrations.md).
-3. You are using PostgreSQL. If you are using MySQL please look at the release
+- You have to use [post-deployment
+ migrations](../development/post_deployment_migrations.md) (included in
+ zero downtime update steps below).
+- You are using PostgreSQL. If you are using MySQL please look at the release
post to see if downtime is required.
Most of the time you can safely upgrade from a patch release to the next minor
diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md
index a4f17746b69..2e8380aa5d8 100644
--- a/doc/update/patch_versions.md
+++ b/doc/update/patch_versions.md
@@ -83,7 +83,7 @@ sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workh
```bash
cd /home/git/gitlab
-sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly]" RAILS_ENV=production
+sudo -u git -H bundle exec rake "gitlab:gitaly:install[/home/git/gitaly,/home/git/repositories]" RAILS_ENV=production
```
### 6. Update gitlab-shell to the corresponding version
diff --git a/doc/user/admin_area/custom_project_templates.md b/doc/user/admin_area/custom_project_templates.md
new file mode 100644
index 00000000000..5afbf9f2934
--- /dev/null
+++ b/doc/user/admin_area/custom_project_templates.md
@@ -0,0 +1,25 @@
+# Custom instance-level project templates **[PREMIUM ONLY]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/6860) in [GitLab Premium](https://about.gitlab.com/pricing) 11.2.
+
+When you create a new project, creating it based on custom project templates is
+a convenient option to bootstrap from an existing project boilerplate.
+The administration setting to configure a GitLab group that serves as template
+source can be found under **Admin > Settings > Custom project templates**.
+
+Within this section, you can configure the group where all the custom project
+templates are sourced. Every project directly under the group namespace will be
+available to the user if they have access to them. For example, every public
+project in the group will be available to every logged user. However,
+private projects will be available only if the user has view [permissions](../permissions.md)
+in the project:
+
+- Project Owner, Maintainer, Developer, Reporter or Guest
+- Is a member of the Group: Owner, Maintainer, Developer, Reporter or Guest
+
+Projects below subgroups of the template group are **not** supported.
+
+Repository and database information that are copied over to each new project are
+identical to the data exported with [GitLab's Project Import/Export](../project/settings/import_export.md).
+
+If you would like to set project templates at a group level, please see [Custom group-level project templates](../group/custom_project_templates.md). \ No newline at end of file
diff --git a/doc/user/admin_area/diff_limits.md b/doc/user/admin_area/diff_limits.md
new file mode 100644
index 00000000000..9205860ef1f
--- /dev/null
+++ b/doc/user/admin_area/diff_limits.md
@@ -0,0 +1,21 @@
+# Diff limits administration
+
+NOTE: **Note:**
+Merge requests and branch comparison views will be affected.
+
+CAUTION: **Caution:**
+These settings are currently under experimental state. They'll
+increase the resource consumption of your instance and should
+be edited mindfully.
+
+1. Access **Admin area > Settings > General**
+1. Expand **Diff limits**
+
+### Maximum diff patch size
+
+This is the content size each diff file (patch) is allowed to reach before
+it's collapsed, without the possibility of being expanded. A link redirecting
+to the blob view will be presented for the patches that surpass this limit.
+
+Patches surpassing 10% of this content size will be automatically collapsed,
+but expandable (a link to expand the diff will be presented).
diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md
index 6025a5bbcda..d4853a5842e 100644
--- a/doc/user/admin_area/settings/continuous_integration.md
+++ b/doc/user/admin_area/settings/continuous_integration.md
@@ -49,3 +49,19 @@ and the default value is `30 days`. On GitLab.com they
This setting is set per job and can be overridden in
[`.gitlab-ci.yml`](../../../ci/yaml/README.md#artifacts-expire_in).
To disable the expiration, set it to `0`. The default unit is in seconds.
+
+## Archive jobs **[CORE ONLY]**
+
+Archiving jobs is useful for reducing the CI/CD footprint on the system by
+removing some of the capabilities of the jobs (metadata needed to run the job),
+but persisting the traces and artifacts for auditing purposes.
+
+To set the duration for which the jobs will be considered as old and expired:
+
+1. Go to **Admin area > Settings > CI/CD > Continuous Integration and Deployment**.
+1. Change the value of "Archive jobs".
+1. Hit **Save changes** for the changes to take effect.
+
+Once that time passes, the jobs will be archived and no longer able to be
+retried. Make it empty to never expire jobs. It has to be no less than 1 day,
+for example: <code>15 days</code>, <code>1 month</code>, <code>2 years</code>.
diff --git a/doc/user/admin_area/settings/email.md b/doc/user/admin_area/settings/email.md
index 7c9e5bf882e..50c318a4969 100644
--- a/doc/user/admin_area/settings/email.md
+++ b/doc/user/admin_area/settings/email.md
@@ -3,3 +3,20 @@
## Custom logo
The logo in the header of some emails can be customized, see the [logo customization section](../../../customization/branded_page_and_email_header.md).
+
+## Custom hostname for private commit emails
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22560) in GitLab 11.5.
+
+This configuration option sets the email hostname for [private commit emails](../../profile/index.md#private-commit-email),
+and it's, by default, set to `users.noreply.YOUR_CONFIGURED_HOSTNAME`.
+
+In order to change this option:
+
+1. Go to **Admin area > Settings** (`/admin/application_settings`).
+1. Under the **Email** section, change the **Custom hostname (for private commit emails)** field.
+1. Hit **Save** for the changes to take effect.
+
+NOTE: **Note**: Once the hostname gets configured, every private commit email using the previous hostname, will not get
+recognized by GitLab. This can directly conflict with certain [Push rules](https://docs.gitlab.com/ee/push_rules/push_rules.html) such as
+`Check whether author is a GitLab user` and `Check whether committer is the current authenticated user`.
diff --git a/doc/user/admin_area/settings/img/import_sources.png b/doc/user/admin_area/settings/img/import_sources.png
new file mode 100644
index 00000000000..4257f02448f
--- /dev/null
+++ b/doc/user/admin_area/settings/img/import_sources.png
Binary files differ
diff --git a/doc/user/admin_area/settings/sign_up_restrictions.md b/doc/user/admin_area/settings/sign_up_restrictions.md
index 9801a0a14ed..d3ecfd42903 100644
--- a/doc/user/admin_area/settings/sign_up_restrictions.md
+++ b/doc/user/admin_area/settings/sign_up_restrictions.md
@@ -4,7 +4,7 @@ You can block email addresses of specific domains, or whitelist only some
specific domains via the **Application Settings** in the Admin area.
>**Note**: These restrictions are only applied during sign-up. An admin is
-able to add add a user through the admin panel with a disallowed domain. Also
+able to add a user through the admin panel with a disallowed domain. Also
note that the users can change their email addresses after signup to
disallowed domains.
diff --git a/doc/user/admin_area/settings/terms.md b/doc/user/admin_area/settings/terms.md
index aa817c9a209..e2290bf0598 100644
--- a/doc/user/admin_area/settings/terms.md
+++ b/doc/user/admin_area/settings/terms.md
@@ -35,17 +35,17 @@ continue their registration afterwards.
## Accepting terms
-When this feature was enabled, the users that have not accepted the
+When this feature is enabled, the users that have not accepted the
terms of service will be presented with a screen where they can either
accept or decline the terms.
![Respond to terms](img/respond_to_terms.png)
-When the user accepts the terms, they will be directed to where they
+If the user accepts the terms, they will be directed to where they
were going. After a sign-in or sign-up this will most likely be the
dashboard.
-When the user was already logged in when the feature was turned on,
+If the user was already logged in when the feature was turned on,
they will be asked to accept the terms on their next interaction.
-When a user declines the terms, they will be signed out.
+If a user declines the terms, they will be signed out.
diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md
index 35a9d7adb28..bd0155dc712 100644
--- a/doc/user/admin_area/settings/usage_statistics.md
+++ b/doc/user/admin_area/settings/usage_statistics.md
@@ -42,7 +42,11 @@ not send any project names, usernames, or any other specific data. The
information from the usage ping is not anonymous, it is linked to the hostname
of the instance.
-You can view the exact JSON payload in the administration panel.
+You can view the exact JSON payload in the administration panel. To view the payload:
+
+1. Go to the **Admin area** (spanner symbol on the top bar).
+1. Expand **Settings** in the left sidebar and click on **Metrics and profiling**.
+1. Expand **Usage statistics** and click on the **Preview payload** button.
### Deactivate the usage ping
diff --git a/doc/user/admin_area/settings/visibility_and_access_controls.md b/doc/user/admin_area/settings/visibility_and_access_controls.md
index 3d38588a9ed..6a1e8004f87 100644
--- a/doc/user/admin_area/settings/visibility_and_access_controls.md
+++ b/doc/user/admin_area/settings/visibility_and_access_controls.md
@@ -1,5 +1,12 @@
# Visibility and access controls
+## Import sources
+
+Choose from which hosting sites the users can
+[import their projects](../../project/import/index.md).
+
+![import sources](img/import_sources.png)
+
## Enabled Git access protocols
> [Introduced][ce-4696] in GitLab 8.10.
diff --git a/doc/user/discussions/img/index_notes_filters.png b/doc/user/discussions/img/index_notes_filters.png
new file mode 100644
index 00000000000..977a3770c05
--- /dev/null
+++ b/doc/user/discussions/img/index_notes_filters.png
Binary files differ
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index 1b3fb9db4ec..0f89d261ff6 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -273,6 +273,26 @@ edit existing comments. Non-team members are restricted from adding or editing c
Additionally locked issues can not be reopened.
+## Filtering notes
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/26723) in GitLab 11.5.
+
+For issues with many comments like activity notes and user comments, sometimes
+finding useful information can be hard. There is a way to filter comments from single notes and discussions for merge requests and issues.
+
+From a merge request's **Discussion** tab, or from an issue overview, find the filter's dropdown menu on the right side of the page, from which you can choose one of the following options:
+
+- **Show all activity**: displays all user comments and system notes
+(issue updates, mentions from other issues, changes to the description, etc).
+- **Show comments only**: only displays user comments in the list.
+- **Show history only**: only displays activity notes.
+
+![Notes filters dropdown options](img/index_notes_filters.png)
+
+Once you select one of the filters in a given issue or MR, GitLab will save
+your preference, so that it will persist when you visit the same page again
+from any device you're logged into.
+
[ce-5022]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5022
[ce-7125]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7125
[ce-7527]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7527
@@ -281,7 +301,7 @@ Additionally locked issues can not be reopened.
[ce-14053]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14053
[ce-14061]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14061
[ce-14531]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14531
-[ce-31847]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/31847
+[ce-31847]: https://gitlab.com/gitlab-org/gitlab-ce/issues/31847
[resolve-discussion-button]: img/resolve_discussion_button.png
[resolve-comment-button]: img/resolve_comment_button.png
[discussion-view]: img/discussion_view.png
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index 0b9395914f9..e14e716a5eb 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -221,7 +221,7 @@ and the following environment variables:
## Cron jobs
-Periodically executed jobs by Sidekiq, to self-heal Gitlab, do external
+Periodically executed jobs by Sidekiq, to self-heal GitLab, do external
synchronizations, run scheduled pipelines, etc.:
| Setting | GitLab.com | Default |
diff --git a/doc/user/group/custom_project_templates.md b/doc/user/group/custom_project_templates.md
new file mode 100644
index 00000000000..eaf0273050b
--- /dev/null
+++ b/doc/user/group/custom_project_templates.md
@@ -0,0 +1,23 @@
+# Custom group-level project templates **[PREMIUM ONLY]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/6861) in [GitLab Premium](https://about.gitlab.com/pricing) 11.6.
+
+When you create a new project, creating it based on custom project templates is
+a convenient option to bootstrap from an existing project boilerplate.
+The group-level setting to configure a GitLab group that serves as template
+source can be found under **Group > Settings > General > Custom project templates**.
+
+Within this section, you can configure the group where all the custom project
+templates are sourced. Every project directly under the group namespace will be
+available to the user if they have access to them. For example, every public
+project in the group will be available to every logged in user. However,
+private projects will be available only if the user has view [permissions](../permissions.md)
+in the project. That is, users with Owner, Maintainer, Developer, Reporter or Guest roles for projects,
+or for groups to which the project belongs.
+
+Projects of nested subgroups of a selected template source cannot be used.
+
+Repository and database information that are copied over to each new project are
+identical to the data exported with [GitLab's Project Import/Export](../project/settings/import_export.md).
+
+If you would like to set project templates at an instance level, please see [Custom instance-level project templates](../admin_area/custom_project_templates.md). \ No newline at end of file
diff --git a/doc/user/group/img/access_requests_management.png b/doc/user/group/img/access_requests_management.png
index 36deaa89a70..7de6a1c0a5e 100644
--- a/doc/user/group/img/access_requests_management.png
+++ b/doc/user/group/img/access_requests_management.png
Binary files differ
diff --git a/doc/user/group/img/add_new_members.png b/doc/user/group/img/add_new_members.png
index 99b8e52ea13..4431c9fbe0b 100644
--- a/doc/user/group/img/add_new_members.png
+++ b/doc/user/group/img/add_new_members.png
Binary files differ
diff --git a/doc/user/group/img/create_new_group_info.png b/doc/user/group/img/create_new_group_info.png
index 1ac26fb08d9..c2e6ed43c5b 100644
--- a/doc/user/group/img/create_new_group_info.png
+++ b/doc/user/group/img/create_new_group_info.png
Binary files differ
diff --git a/doc/user/group/img/create_new_project_from_group.png b/doc/user/group/img/create_new_project_from_group.png
index 553cd0759aa..b6286ac7800 100644
--- a/doc/user/group/img/create_new_project_from_group.png
+++ b/doc/user/group/img/create_new_project_from_group.png
Binary files differ
diff --git a/doc/user/group/img/group_settings.png b/doc/user/group/img/group_settings.png
index 1705bf4ce8e..f3a75f1bde8 100644
--- a/doc/user/group/img/group_settings.png
+++ b/doc/user/group/img/group_settings.png
Binary files differ
diff --git a/doc/user/group/img/request_access_button.png b/doc/user/group/img/request_access_button.png
index 54b490a3bb2..4d73990ec7e 100644
--- a/doc/user/group/img/request_access_button.png
+++ b/doc/user/group/img/request_access_button.png
Binary files differ
diff --git a/doc/user/group/img/select_group_dropdown.png b/doc/user/group/img/select_group_dropdown.png
index 79eca5d94d5..8c03ffffbde 100644
--- a/doc/user/group/img/select_group_dropdown.png
+++ b/doc/user/group/img/select_group_dropdown.png
Binary files differ
diff --git a/doc/user/group/img/withdraw_access_request_button.png b/doc/user/group/img/withdraw_access_request_button.png
index 4365f7fa788..a5fe78eb090 100644
--- a/doc/user/group/img/withdraw_access_request_button.png
+++ b/doc/user/group/img/withdraw_access_request_button.png
Binary files differ
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index b14377a72b6..36b9318c0e0 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -252,12 +252,23 @@ level of members in group.
Learn more about [Member Lock](https://docs.gitlab.com/ee/user/group/index.html#member-lock).
+#### Group-level file templates **[PREMIUM]**
+
+Group-level file templates allow you to share a set of templates for common file
+types with every project in a group.
+
+Learn more about [Group-level file templates](https://docs.gitlab.com/ee/user/group/index.html#group-level-file-templates-premium).
+
+#### Group-level project templates **[PREMIUM]**
+
+Define project templates at a group-level by setting a group as a template source.
+[Learn more about group-level project templates](custom_project_templates.md).
+
### Advanced settings
- **Projects**: view all projects within that group, add members to each project,
access each project's settings, and remove any project from the same screen.
- **Webhooks**: configure [webhooks](../project/integrations/webhooks.md) to your group.
-- **Push rules**: configure [push rules](https://docs.gitlab.com/ee/push_rules/push_rules.html#push-rules) to your group. **[STARTER]**
- **Audit Events**: view [Audit Events](https://docs.gitlab.com/ee/administration/audit_events.html#audit-events)
for the group. **[STARTER ONLY]**
- **Pipelines quota**: keep track of the [pipeline quota](../admin_area/settings/continuous_integration.md) for the group
diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md
index b55946a788f..8db36c4a0e8 100644
--- a/doc/user/group/subgroups/index.md
+++ b/doc/user/group/subgroups/index.md
@@ -1,9 +1,8 @@
# Subgroups
-> **Notes:**
-> - [Introduced][ce-2772] in GitLab 9.0.
-> - Not available when using MySQL as external database (support removed in
-> GitLab 9.3 [due to performance reasons][issue]).
+NOTE: **Note:**
+[Introduced][ce-2772] in GitLab 9.0. Not available when using MySQL as external
+database (support removed in GitLab 9.3 [due to performance reasons][issue]).
With subgroups (aka nested groups or hierarchical groups) you can have
up to 20 levels of nested groups, which among other things can help you to:
@@ -79,14 +78,14 @@ structure.
## Creating a subgroup
-> **Notes:**
-> - You need to be an Owner of a group in order to be able to create
-> a subgroup. For more information check the [permissions table][permissions].
-> - For a list of words that are not allowed to be used as group names see the
-> [reserved names][reserved].
-> - Users can always create subgroups if they are explicitly added as an Owner to
-> a parent group even if group creation is disabled by an administrator in their
-> settings.
+NOTE: **Note:**
+You need to be an Owner of a group in order to be able to create a subgroup. For
+more information check the [permissions table][permissions].
+For a list of words that are not allowed to be used as group names see the
+[reserved names][reserved].
+Users can always create subgroups if they are explicitly added as an Owner to
+a parent group even if group creation is disabled by an administrator in their
+settings.
To create a subgroup:
@@ -136,12 +135,15 @@ From the image above, we can deduct the following things:
### Overriding the ancestor group membership
->**Note:**
+NOTE: **Note:**
You need to be an Owner of a group in order to be able to add members to it.
+NOTE: **Note:**
+A user's permissions in a subgroup cannot be lower than in any of its ancestor groups.
+Therefore, you cannot reduce a user's permissions in a subgroup with respect to its ancestor groups.
+
To override a user's membership of an ancestor group (the first group they were
-added to), simply add the user in the new subgroup again, but with different
-permissions.
+added to), add the user to the new subgroup again with a higher set of permissions.
For example, if User0 was first added to group `group-1/group-1-1` with Developer
permissions, then they will inherit those permissions in every other subgroup
diff --git a/doc/user/img/color_inline_colorchip_render_gfm.png b/doc/user/img/color_inline_colorchip_render_gfm.png
new file mode 100644
index 00000000000..6a8a674d6e0
--- /dev/null
+++ b/doc/user/img/color_inline_colorchip_render_gfm.png
Binary files differ
diff --git a/doc/user/img/math_inline_sup_render_gfm.png b/doc/user/img/math_inline_sup_render_gfm.png
new file mode 100644
index 00000000000..bf1464457bc
--- /dev/null
+++ b/doc/user/img/math_inline_sup_render_gfm.png
Binary files differ
diff --git a/doc/user/img/mermaid_diagram_render_gfm.png b/doc/user/img/mermaid_diagram_render_gfm.png
new file mode 100644
index 00000000000..3b3eb3a738a
--- /dev/null
+++ b/doc/user/img/mermaid_diagram_render_gfm.png
Binary files differ
diff --git a/doc/user/img/task_list_ordered_render_gfm.png b/doc/user/img/task_list_ordered_render_gfm.png
new file mode 100644
index 00000000000..fdff8a9886c
--- /dev/null
+++ b/doc/user/img/task_list_ordered_render_gfm.png
Binary files differ
diff --git a/doc/user/img/unordered_check_list_render_gfm.png b/doc/user/img/unordered_check_list_render_gfm.png
new file mode 100644
index 00000000000..2e3fb7cbb79
--- /dev/null
+++ b/doc/user/img/unordered_check_list_render_gfm.png
Binary files differ
diff --git a/doc/user/index.md b/doc/user/index.md
index 649c0b664a5..08995032cb1 100644
--- a/doc/user/index.md
+++ b/doc/user/index.md
@@ -96,7 +96,7 @@ directly from GitLab. No third-party integrations needed.
- [GitLab Auto Deploy](../ci/autodeploy/index.md): Deploy your application out-of-the-box with GitLab Auto Deploy.
- [Review Apps](../ci/review_apps/index.md): Live-preview the changes introduced by a merge request with Review Apps.
- [GitLab Pages](project/pages/index.md): Publish your static site directly from
-GitLab with Gitlab Pages. You can build, test, and deploy any Static Site Generator with Pages.
+GitLab with GitLab Pages. You can build, test, and deploy any Static Site Generator with Pages.
- [GitLab Container Registry](project/container_registry.md): Build and deploy Docker
images with Container Registry.
diff --git a/doc/user/instance_statistics/convdev.md b/doc/user/instance_statistics/convdev.md
index d2795e092fc..52b99b69a02 100644
--- a/doc/user/instance_statistics/convdev.md
+++ b/doc/user/instance_statistics/convdev.md
@@ -2,20 +2,21 @@
> [Introduced][ce-30469] in GitLab 9.3.
-Conversational Development Index (ConvDev) gives you an overview of your entire
-instance's feature usage, from idea to production. It looks at your usage in the
-past 30 days, averaged over the number of active users in that time period. It also
-provides a lead score per feature, which is calculated based on GitLab's analysis
-of top performing instances, based on [usage ping data][ping] that GitLab has
+The Conversational Development Index (ConvDev Index) gives you an overview of your entire
+instance's adoption of [Concurrent DevOps](https://about.gitlab.com/concurrent-devops/)
+from planning to monitoring. It displays the usage of these GitLab features over
+the last 30 days, averaged over the number of active users in that time period. It also
+provides a Lead score per feature, which is calculated based on GitLab's analysis
+of top-performing instances based on [usage ping data][ping] that GitLab has
collected. Your score is compared to the lead score, expressed as a percentage.
-The overall index score is an average over all your feature scores.
+Your overall index score is an average of all your feature score percentages.
![ConvDev index](img/convdev_index.png)
The page also provides helpful links to articles and GitLab docs, to help you
improve your scores.
-Your GitLab instance's usage ping must be activated in order to use this feature.
+Your GitLab instance's [usage ping][ping] must be activated in order to use this feature.
Usage ping data is aggregated on GitLab's servers for analysis. Your usage
information is **not sent** to any other GitLab instances.
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index fb132f0613b..debebd4c081 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -1,36 +1,52 @@
-# Markdown
+# GitLab Markdown
-## GitLab Flavored Markdown (GFM)
-
-> **Note:**
-> Not all of the GitLab-specific extensions to Markdown that are described in
-> this document currently work on our documentation website.
->
-> For the best result, we encourage you to check this document out as rendered
-> by GitLab: [markdown.md]
+This markdown guide is **valid for GitLab's system markdown entries and files**.
+It is not valid for the [GitLab documentation website](https://docs.gitlab.com)
+nor [GitLab's main website](https://about.gitlab.com), as they both use
+[Kramdown](https://kramdown.gettalong.org) as their markdown engine.
+The documentation website uses an extended Kramdown gem, [GitLab Kramdown](https://gitlab.com/gitlab-org/gitlab_kramdown).
+Consult the [GitLab Kramdown Guide](https://about.gitlab.com/handbook/product/technical-writing/markdown-guide/) for a complete Kramdown reference._
-_GitLab uses (as of 11.1) the [CommonMark Ruby Library][commonmarker] for Markdown processing of all new issues, merge requests, comments, and other Markdown content in the GitLab system. As of 11.3, wiki pages and Markdown files (`.md`) in the repositories are also processed with CommonMark. Older content in issues/comments are still processed using the [Redcarpet Ruby library][redcarpet]._
-
-_Where there are significant differences, we will try to call them out in this document._
+## GitLab Flavored Markdown (GFM)
GitLab uses "GitLab Flavored Markdown" (GFM). It extends the [CommonMark specification][commonmark-spec] (which is based on standard Markdown) in a few significant ways to add some useful functionality. It was inspired by [GitHub Flavored Markdown](https://help.github.com/articles/basic-writing-and-formatting-syntax/).
You can use GFM in the following areas:
-- comments
-- issues
-- merge requests
-- milestones
-- snippets (the snippet must be named with a `.md` extension)
-- wiki pages
-- markdown documents inside the repository
+- Comments
+- Issues
+- Merge requests
+- Milestones
+- Snippets (the snippet must be named with a `.md` extension)
+- Wiki pages
+- Markdown documents inside repositories
You can also use other rich text files in GitLab. You might have to install a
-dependency to do so. Please see the [github-markup gem readme](https://github.com/gitlabhq/markup#markups) for more information.
+dependency to do so. Please see the [`github-markup` gem readme](https://github.com/gitlabhq/markup#markups) for more information.
+
+> **Notes:**
+>
+> For the best result, we encourage you to check this document out as [rendered
+> by GitLab itself](markdown.md).
+>
+> As of 11.1, GitLab uses the [CommonMark Ruby Library][commonmarker] for Markdown
+processing of all new issues, merge requests, comments, and other Markdown content
+in the GitLab system. As of 11.3, wiki pages and Markdown files (`.md`) in the
+repositories are also processed with CommonMark. Older content in issues/comments
+are still processed using the [Redcarpet Ruby library][redcarpet].
+>
+> The documentation website had its [markdown engine migrated from Redcarpet to Kramdown](https://gitlab.com/gitlab-com/gitlab-docs/merge_requests/108)
+in October 2018.
+>
+> _Where there are significant differences, we will try to call them out in this document._
### Transitioning to CommonMark
-You may have Markdown documents in your repository that were written using some of the nuances of RedCarpet's version of Markdown. Since CommonMark uses a slightly stricter syntax, these documents may now display a little strangely since we've transitioned to CommonMark. Numbered lists with nested lists in particular can be displayed incorrectly.
+You may have Markdown documents in your repository that were written using some
+of the nuances of RedCarpet's version of Markdown. Since CommonMark uses a
+slightly stricter syntax, these documents may now display a little strangely
+since we've transitioned to CommonMark. Numbered lists with nested lists in
+particular can be displayed incorrectly.
It is usually quite easy to fix. In the case of a nested list such as this:
@@ -50,11 +66,18 @@ simply add a space to each nested item:
In the documentation below, we try to highlight some of the differences.
-If you have a need to view a document using RedCarpet, you can add the token `legacy_render=1` to the end of the url, like this:
+If you have a need to view a document using RedCarpet, you can add the token
+`legacy_render=1` to the end of the url, like this:
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md?legacy_render=1
-If you have a large volume of Markdown files, it can be tedious to determine if they will be displayed correctly or not. You can use the [diff_redcarpet_cmark](https://gitlab.com/digitalmoksha/diff_redcarpet_cmark) tool (not an officially supported product) to generate a list of files and differences between how RedCarpet and CommonMark render the files. It can give you a great idea if anything needs to be changed - many times nothing will need to changed.
+If you have a large volume of Markdown files, it can be tedious to determine
+if they will be displayed correctly or not. You can use the
+[diff_redcarpet_cmark](https://gitlab.com/digitalmoksha/diff_redcarpet_cmark)
+tool (not an officially supported product) to generate a list of files and
+differences between how RedCarpet and CommonMark render the files. It can give
+you a great idea if anything needs to be changed - many times nothing will need
+to changed.
### Newlines
@@ -63,7 +86,8 @@ https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#newline
GFM honors the markdown specification in how [paragraphs and line breaks are handled][commonmark-spec].
-A paragraph is simply one or more consecutive lines of text, separated by one or more blank lines.
+A paragraph is simply one or more consecutive lines of text, separated by one or
+more blank lines.
Line-breaks, or soft returns, are rendered if you end a line with two or more spaces:
<!-- (Do *NOT* remove the two ending whitespaces in the following line.) -->
@@ -85,7 +109,9 @@ Sugar is sweet
> If this is not rendered correctly, see
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#multiple-underscores-in-words
-It is not reasonable to italicize just _part_ of a word, especially when you're dealing with code and names that often appear with multiple underscores. Therefore, GFM ignores multiple underscores in words:
+It is not reasonable to italicize just _part_ of a word, especially when you're
+dealing with code and names that often appear with multiple underscores.
+Therefore, GFM ignores multiple underscores in words:
perform_complicated_task
@@ -112,8 +138,8 @@ GFM will autolink almost any URL you copy and paste into your text:
* https://www.google.com
* https://google.com/
* ftp://ftp.us.debian.org/debian/
-* smb://foo/bar/baz
-* irc://irc.freenode.net/gitlab
+* <a href="smb://foo/bar/baz">smb://foo/bar/baz</a>
+* <a href="irc://irc.freenode.net/gitlab">irc://irc.freenode.net/gitlab</a>
* http://localhost:3000
### Multiline Blockquote
@@ -124,7 +150,7 @@ https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#multili
On top of standard Markdown [blockquotes](#blockquotes), which require prepending `>` to quoted lines,
GFM supports multiline blockquotes fenced by <code>>>></code>:
-```no-highlight
+```
>>>
If you paste a message from somewhere else
@@ -138,17 +164,13 @@ you can quote that without having to manually prepend `>` to every line!
>>>
```
->>>
-If you paste a message from somewhere else
-
-that
-
-spans
-
-multiple lines,
-
-you can quote that without having to manually prepend `>` to every line!
->>>
+<blockquote dir="auto">
+<p>If you paste a message from somewhere else</p>
+<p>that</p>
+<p>spans</p>
+<p>multiple lines,</p>
+<p>you can quote that without having to manually prepend <code>&gt;</code> to every line!</p>
+</blockquote>
### Code and Syntax Highlighting
@@ -162,7 +184,7 @@ Blocks of code are either fenced by lines with three back-ticks <code>```</code>
or are indented with four spaces. Only the fenced code blocks support syntax
highlighting:
-```no-highlight
+```
Inline `code` has `back-ticks around` it.
```
@@ -252,32 +274,34 @@ However the wrapping tags cannot be mixed as such:
> If this is not rendered correctly, see
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#emoji
- Sometimes you want to :monkey: around a bit and add some :star2: to your :speech_balloon:. Well we have a gift for you:
+```
+Sometimes you want to :monkey: around a bit and add some :star2: to your :speech_balloon:. Well we have a gift for you:
- :zap: You can use emoji anywhere GFM is supported. :v:
+:zap: You can use emoji anywhere GFM is supported. :v:
- You can use it to point out a :bug: or warn about :speak_no_evil: patches. And if someone improves your really :snail: code, send them some :birthday:. People will :heart: you for that.
+You can use it to point out a :bug: or warn about :speak_no_evil: patches. And if someone improves your really :snail: code, send them some :birthday:. People will :heart: you for that.
- If you are new to this, don't be :fearful:. You can easily join the emoji :family:. All you need to do is to look up one of the supported codes.
+If you are new to this, don't be :fearful:. You can easily join the emoji :family:. All you need to do is to look up one of the supported codes.
- Consult the [Emoji Cheat Sheet](https://www.emojicopy.com) for a list of all supported emoji codes. :thumbsup:
+Consult the [Emoji Cheat Sheet](https://www.emojicopy.com) for a list of all supported emoji codes. :thumbsup:
- Most emoji are natively supported on macOS, Windows, iOS, Android and will fallback to image-based emoji where there is lack of support.
+Most emoji are natively supported on macOS, Windows, iOS, Android and will fallback to image-based emoji where there is lack of support.
- On Linux, you can download [Noto Color Emoji](https://www.google.com/get/noto/help/emoji/) to get full native emoji support.
+On Linux, you can download [Noto Color Emoji](https://www.google.com/get/noto/help/emoji/) to get full native emoji support.
- Ubuntu 18.04 (like many modern Linux distros) has this font installed by default.
+Ubuntu 18.04 (like many modern Linux distros) has this font installed by default.
+```
-Sometimes you want to :monkey: around a bit and add some :star2: to your :speech_balloon:. Well we have a gift for you:
+Sometimes you want to <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/monkey.png" width="20px" height="20px"> around a bit and add some <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/star2.png" width="20px" height="20px"> to your <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/speech_balloon.png" width="20px" height="20px">. Well we have a gift for you:
-:zap: You can use emoji anywhere GFM is supported. :v:
+<img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/zap.png" width="20px" height="20px">You can use emoji anywhere GFM is supported. <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/v.png" width="20px" height="20px">
-You can use it to point out a :bug: or warn about :speak_no_evil: patches. And if someone improves your really :snail: code, send them some :birthday:. People will :heart: you for that.
+You can use it to point out a <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/bug.png" width="20px" height="20px"> or warn about <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/speak_no_evil.png" width="20px" height="20px"> patches. And if someone improves your really <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/snail.png" width="20px" height="20px"> code, send them some <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/birthday.png" width="20px" height="20px">. People will <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/heart.png" width="20px" height="20px"> you for that.
-If you are new to this, don't be :fearful:. You can easily join the emoji :family:. All you need to do is to look up one of the supported codes.
+If you are new to this, don't be <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/fearful.png" width="20px" height="20px">. You can easily join the emoji <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/family.png" width="20px" height="20px">. All you need to do is to look up one of the supported codes.
-Consult the [Emoji Cheat Sheet](https://www.emojicopy.com) for a list of all supported emoji codes. :thumbsup:
+Consult the [Emoji Cheat Sheet](https://www.emojicopy.com) for a list of all supported emoji codes. <img src="https://gitlab.com/gitlab-org/gitlab-ce/raw/master/app/assets/images/emoji/thumbsup.png" width="20px" height="20px">
Most emoji are natively supported on macOS, Windows, iOS, Android and will fallback to image-based emoji where there is lack of support.
@@ -285,8 +309,6 @@ On Linux, you can download [Noto Color Emoji](https://www.google.com/get/noto/he
Ubuntu 18.04 (like many modern Linux distros) has this font installed by default.
-
-
### Special GitLab References
GFM recognizes special references.
@@ -348,7 +370,7 @@ https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#task-li
You can add task lists to issues, merge requests and comments. To create a task list, add a specially-formatted Markdown list, like so:
-```no-highlight
+```
- [x] Completed task
- [ ] Incomplete task
- [ ] Sub-task 1
@@ -356,25 +378,18 @@ You can add task lists to issues, merge requests and comments. To create a task
- [ ] Sub-task 3
```
-- [x] Completed task
-- [ ] Incomplete task
- - [ ] Sub-task 1
- - [x] Sub-task 2
- - [ ] Sub-task 3
+![alt unordered-check-list-render-gfm](img/unordered_check_list_render_gfm.png)
Tasks formatted as ordered lists are supported as well:
-```no-highlight
+```
1. [x] Completed task
1. [ ] Incomplete task
1. [ ] Sub-task 1
1. [x] Sub-task 2
```
-1. [x] Completed task
-1. [ ] Incomplete task
- 1. [ ] Sub-task 1
- 1. [x] Sub-task 2
+![alt task-list-ordered-render-gfm](img/task_list_ordered_render_gfm.png)
Task lists can only be created in descriptions, not in titles. Task item state can be managed by editing the description's Markdown or by toggling the rendered check boxes.
@@ -393,7 +408,10 @@ The valid video extensions are `.mp4`, `.m4v`, `.mov`, `.webm`, and `.ogv`.
Here's a sample video:
-![Sample Video](img/markdown_video.mp4)
+<div class="video-container">
+ <video src="img/markdown_video.mp4" width="400" controls="true" data-setup="{}" data-title="Sample Video"></video>
+ <p><a href="img/markdown_video.mp4" target="_blank" rel="noopener noreferrer" title="Download 'Sample Video'">Sample Video</a></p>
+</div>
### Math
@@ -417,12 +435,11 @@ Example:
Becomes:
-This math is inline $`a^2+b^2=c^2`$.
+This math is inline ![alt text](img/math_inline_sup_render_gfm.png).
This is on a separate line
-```math
-a^2+b^2=c^2
-```
+
+<img src="./img/math_inline_sup_render_gfm.png" >
_Be advised that KaTeX only supports a [subset][katex-subset] of LaTeX._
@@ -450,17 +467,9 @@ Examples:
`HSL(540,70%,50%)`
`HSLA(540,70%,50%,0.7)`
-Become:
+Becomes:
-`#F00`
-`#F00A`
-`#FF0000`
-`#FF0000AA`
-`RGB(0,255,0)`
-`RGB(0%,100%,0%)`
-`RGBA(0,255,0,0.7)`
-`HSL(540,70%,50%)`
-`HSLA(540,70%,50%,0.7)`
+![alt color-inline-colorchip-render-gfm](img/color_inline_colorchip_render_gfm.png)
#### Supported formats:
@@ -492,13 +501,7 @@ Example:
Becomes:
-```mermaid
-graph TD;
- A-->B;
- A-->C;
- B-->D;
- C-->D;
-```
+<img src="./img/mermaid_diagram_render_gfm.png" width="200px" height="400px">
For details see the [Mermaid official page][mermaid].
@@ -506,7 +509,7 @@ For details see the [Mermaid official page][mermaid].
### Headers
-```no-highlight
+```
# H1
## H2
### H3
@@ -564,7 +567,7 @@ Note that the Emoji processing happens before the header IDs are generated, so t
Examples:
-```no-highlight
+```
Emphasis, aka italics, with *asterisks* or _underscores_.
Strong emphasis, aka bold, with **asterisks** or __underscores__.
@@ -574,7 +577,7 @@ Combined emphasis with **asterisks and _underscores_**.
Strikethrough uses two tildes. ~~Scratch this.~~
```
-Become:
+Becomes:
Emphasis, aka italics, with *asterisks* or _underscores_.
@@ -588,7 +591,7 @@ Strikethrough uses two tildes. ~~Scratch this.~~
Examples:
-```no-highlight
+```
1. First ordered list item
2. Another item
* Unordered sub-list.
@@ -601,7 +604,7 @@ Examples:
+ Or pluses
```
-Become:
+Becomes:
1. First ordered list item
2. Another item
@@ -619,7 +622,7 @@ each subsequent paragraph should be indented to the same level as the start of t
Example:
-```no-highlight
+```
1. First ordered list item
Second paragraph of first item.
@@ -640,7 +643,7 @@ the paragraph will appear outside the list, instead of properly indented under t
Example:
-```no-highlight
+```
1. First ordered list item
Paragraph of first item.
@@ -700,7 +703,7 @@ Examples:
[logo]: img/markdown_logo.png
-Become:
+Becomes:
Here's our logo:
@@ -718,7 +721,7 @@ Reference-style:
Examples:
-```no-highlight
+```
> Blockquotes are very handy in email to emulate reply text.
> This line is part of the same quote.
@@ -727,7 +730,7 @@ Quote break.
> This is a very long line that will still be quoted properly when it wraps. Oh boy let's keep writing to make sure this is long enough to actually wrap for everyone. Oh, you can *put* **Markdown** into a blockquote.
```
-Become:
+Becomes:
> Blockquotes are very handy in email to emulate reply text.
> This line is part of the same quote.
@@ -744,7 +747,7 @@ See the documentation for HTML::Pipeline's [SanitizationFilter](http://www.rubyd
Examples:
-```no-highlight
+```
<dl>
<dt>Definition list</dt>
<dd>Is something people use sometimes.</dd>
@@ -754,7 +757,7 @@ Examples:
</dl>
```
-Become:
+Becomes:
<dl>
<dt>Definition list</dt>
@@ -779,7 +782,7 @@ These details <em>will</em> remain <strong>hidden</strong> until expanded.
</details>
</p>
-**Note:** Markdown inside these tags is supported, as long as you have a blank link after the `</summary>` tag and before the `</details>` tag, as shown in the example. _Redcarpet does not support Markdown inside these tags. You can work around this by using HTML, for example you can use `<pre><code>` tags instead of [code fences](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#code-and-syntax-highlighting)._
+**Note:** Markdown inside these tags is supported, as long as you have a blank line after the `</summary>` tag and before the `</details>` tag, as shown in the example. _Redcarpet does not support Markdown inside these tags. You can work around this by using HTML, for example you can use `<pre><code>` tags instead of [code fences](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#code-and-syntax-highlighting)._
```html
<details>
@@ -812,7 +815,7 @@ ___
Underscores
```
-Become:
+Becomes:
Three or more...
@@ -850,7 +853,7 @@ This line is *on its own line*, because the previous line ends with two spaces.
spaces.
```
-Become:
+Becomes:
Here's a line for us to start with.
@@ -1019,7 +1022,7 @@ A link starting with a `/` is relative to the wiki root.
[rouge]: http://rouge.jneen.net/ "Rouge website"
[redcarpet]: https://github.com/vmg/redcarpet "Redcarpet website"
[katex]: https://github.com/Khan/KaTeX "KaTeX website"
-[katex-subset]: https://github.com/Khan/KaTeX/wiki/Function-Support-in-KaTeX "Macros supported by KaTeX"
+[katex-subset]: https://katex.org/docs/supported.html "Macros supported by KaTeX"
[asciidoctor-manual]: http://asciidoctor.org/docs/user-manual/#activating-stem-support "Asciidoctor user manual"
[commonmarker]: https://github.com/gjtorikian/commonmarker
[commonmark-spec]: https://spec.commonmark.org/current/
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 8369cff2386..c4a2d5f66e5 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -42,6 +42,8 @@ The following table depicts the various user permission levels in a project.
| See a job log | ✓ [^3] | ✓ | ✓ | ✓ | ✓ |
| Download and browse job artifacts | ✓ [^3] | ✓ | ✓ | ✓ | ✓ |
| View wiki pages | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
+| View license management reports **[ULTIMATE]** | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
+| View Security reports **[ULTIMATE]** | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
| Pull project code | [^1] | ✓ | ✓ | ✓ | ✓ |
| Download project | [^1] | ✓ | ✓ | ✓ | ✓ |
| Assign issues | | ✓ | ✓ | ✓ | ✓ |
@@ -57,6 +59,7 @@ The following table depicts the various user permission levels in a project.
| See a list of merge requests | | ✓ | ✓ | ✓ | ✓ |
| Manage related issues **[STARTER]** | | ✓ | ✓ | ✓ | ✓ |
| Lock issue discussions | | ✓ | ✓ | ✓ | ✓ |
+| Create issue from vulnerability **[ULTIMATE]** | | ✓ | ✓ | ✓ | ✓ |
| Lock merge request discussions | | | ✓ | ✓ | ✓ |
| Create new environments | | | ✓ | ✓ | ✓ |
| Stop environments | | | ✓ | ✓ | ✓ |
@@ -73,6 +76,9 @@ The following table depicts the various user permission levels in a project.
| Update a container registry | | | ✓ | ✓ | ✓ |
| Remove a container registry image | | | ✓ | ✓ | ✓ |
| Create/edit/delete project milestones | | | ✓ | ✓ | ✓ |
+| View approved/blacklisted licenses **[ULTIMATE]** | | | ✓ | ✓ | ✓ |
+| Use security dashboard **[ULTIMATE]** | | | ✓ | ✓ | ✓ |
+| Dismiss vulnerability **[ULTIMATE]** | | | ✓ | ✓ | ✓ |
| Use environment terminals | | | | ✓ | ✓ |
| Add new team members | | | | ✓ | ✓ |
| Push to protected branches | | | | ✓ | ✓ |
@@ -89,7 +95,9 @@ The following table depicts the various user permission levels in a project.
| Manage GitLab Pages | | | | ✓ | ✓ |
| Manage GitLab Pages domains and certificates | | | | ✓ | ✓ |
| Remove GitLab Pages | | | | | ✓ |
+| View GitLab Pages protected by [access control](project/pages/introduction.md#gitlab-pages-access-control-core-only) | ✓ | ✓ | ✓ | ✓ | ✓ |
| Manage clusters | | | | ✓ | ✓ |
+| Manage license policy **[ULTIMATE]** | | | | ✓ | ✓ |
| Edit comments (posted by any user) | | | | ✓ | ✓ |
| Switch visibility level | | | | | ✓ |
| Transfer project to another namespace | | | | | ✓ |
@@ -98,7 +106,7 @@ The following table depicts the various user permission levels in a project.
| Remove pages | | | | | ✓ |
| Force push to protected branches [^4] | | | | | |
| Remove protected branches [^4] | | | | | |
-| View project Audit Events | | | | ✓ | ✓ |
+| View project Audit Events | | | | ✓ | ✓ |
## Project features permissions
@@ -110,6 +118,7 @@ which visibility level you select on project settings.
- Disabled: disabled for everyone
- Only team members: only team members will see even if your project is public or internal
- Everyone with access: everyone can see depending on your project visibility level
+- Everyone: enabled for everyone (only available for GitLab Pages)
### Protected branches
@@ -198,7 +207,7 @@ They will, like usual users, receive a role in the project or group with all
the abilities that are mentioned in the table above. They cannot however create
groups or projects, and they have the same access as logged out users in all
other cases.
-
+
An administrator can flag a user as external [through the API](../api/users.md)
or by checking the checkbox on the admin panel. As an administrator, navigate
to **Admin > Users** to create a new user or edit an existing one. There, you
@@ -209,7 +218,7 @@ by an administrator under **Admin > Application Settings**.
### Default internal users
-The "Internal users" field allows specifying an e-mail address regex pattern to identify default internal users.
+The "Internal users" field allows specifying an e-mail address regex pattern to identify default internal users.
New users whose email address matches the regex pattern will be set to internal by default rather than an external collaborator.
@@ -242,6 +251,7 @@ which visibility level you select on project settings.
- Disabled: disabled for everyone
- Only team members: only team members will see even if your project is public or internal
- Everyone with access: everyone can see depending on your project visibility level
+- Everyone: enabled for everyone (only available for GitLab Pages)
## GitLab CI/CD permissions
diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md
index 8838efb18fe..76f7e869ff7 100644
--- a/doc/user/profile/account/two_factor_authentication.md
+++ b/doc/user/profile/account/two_factor_authentication.md
@@ -2,18 +2,18 @@
Two-factor Authentication (2FA) provides an additional level of security to your
GitLab account. Once enabled, in addition to supplying your username and
-password to login, you'll be prompted for a code generated by an application on
-your phone.
+password to login, you'll be prompted for a code generated by your one time password
+authenticator. For example, a password manager on one of your devices.
By enabling 2FA, the only way someone other than you can log into your account
-is to know your username and password *and* have access to your phone.
+is to know your username and password *and* have access to your one time password secret.
## Overview
> **Note:**
When you enable 2FA, don't forget to back up your recovery codes.
-In addition to a phone application, GitLab supports U2F (universal 2nd factor) devices as
+In addition to one time authenticators (TOTP), GitLab supports U2F (universal 2nd factor) devices as
the second factor of authentication. Once enabled, in addition to supplying your username and
password to login, you'll be prompted to activate your U2F device (usually by pressing
a button on it), and it will perform secure authentication on your behalf.
@@ -24,10 +24,10 @@ from other browsers.
## Enabling 2FA
-There are two ways to enable two-factor authentication: via a mobile application
+There are two ways to enable two-factor authentication: via a one time password authenticator
or a U2F device.
-### Enable 2FA via mobile application
+### Enable 2FA via one time password authenticator
**In GitLab:**
@@ -69,7 +69,7 @@ of recovery codes.
1. Go to **Account**.
1. Click **Enable Two-Factor Authentication**.
1. Plug in your U2F device.
-1. Click on **Setup New U2F Device**.
+1. Click on **Set up New U2F Device**.
1. A light will start blinking on your device. Activate it by pressing its button.
You will see a message indicating that your device was successfully set up.
@@ -82,10 +82,12 @@ Click on **Register U2F Device** to complete the process.
> **Note:**
Recovery codes are not generated for U2F devices.
-Should you ever lose access to your phone, you can use one of the ten provided
-backup codes to login to your account. We suggest copying or printing them for
-storage in a safe place. **Each code can be used only once** to log in to your
-account.
+Should you ever lose access to your one time password authenticator, you can use one of the ten provided
+backup codes to login to your account. We suggest copying them, printing them, or downloading them using
+the **Download codes** button for storage in a safe place.
+
+CAUTION: **Caution:**
+Each code can be used only once to log in to your account.
If you lose the recovery codes or just want to generate new ones, you can do so
[using SSH](#generate-new-recovery-codes-using-ssh).
@@ -98,7 +100,7 @@ be presented with a second prompt, depending on which type of 2FA you've enabled
### Log in via mobile application
-Enter the pin from your phone's application or a recovery code to log in.
+Enter the pin from your one time password authenticator's application or a recovery code to log in.
![Two-Factor Authentication on sign in via OTP](img/2fa_auth.png)
@@ -156,7 +158,7 @@ authentication. If an SSH key is added to your GitLab account, you can generate
a new set of recovery codes with SSH.
1. Run `ssh git@gitlab.example.com 2fa_recovery_codes`.
-2. You are prompted to confirm that you want to generate new codes. Continuing this process invalidates previously saved codes.
+1. You are prompted to confirm that you want to generate new codes. Continuing this process invalidates previously saved codes.
```
bash
$ ssh git@gitlab.example.com 2fa_recovery_codes
@@ -183,7 +185,7 @@ a new set of recovery codes with SSH.
so you do not lose access to your account again.
```
-3. Go to the GitLab sign-in page and enter your username/email and password.
+1. Go to the GitLab sign-in page and enter your username/email and password.
When prompted for a two-factor code, enter one of the recovery codes obtained
from the command-line output.
diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md
index 8604ea27f99..2f989a26725 100644
--- a/doc/user/profile/index.md
+++ b/doc/user/profile/index.md
@@ -31,6 +31,7 @@ From there, you can:
- Update your personal information
- Set a [custom status](#current-status) for your profile
+- Manage your [commit email](#commit-email) for your profile
- Manage [2FA](account/two_factor_authentication.md)
- Change your username and [delete your account](account/delete_account.md)
- Manage applications that can
@@ -96,13 +97,13 @@ You and GitLab admins can see your the abovementioned information on your profil
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/14078) in GitLab 11.3.
-Enabling private contributions will include contributions to private projects, in the user contribution calendar graph and user recent activity.
+Enabling private contributions will include contributions to private projects, in the user contribution calendar graph and user recent activity.
To enable private contributions:
1. Navigate to your personal [profile settings](#profile-settings).
-2. Check the "Private contributions" option.
-3. Hit **Update profile settings**.
+1. Check the "Private contributions" option.
+1. Hit **Update profile settings**.
## Current status
@@ -115,6 +116,13 @@ Please be aware that your status is publicly visible even if your [profile is pr
To set your current status:
+1. Open the user menu in the top-right corner of the navigation bar.
+1. Hit **Set status**, or **Edit status** if you have already set a status.
+1. Set the emoji and/or status message to your liking.
+1. Hit **Set status**. Alternatively, you can also hit **Remove status** to remove your user status entirely.
+
+or
+
1. Navigate to your personal [profile settings](#profile-settings).
1. In the text field below `Your status`, enter your status message.
1. Select an emoji from the dropdown if you like.
@@ -125,6 +133,45 @@ They may however contain emoji codes such as `I'm on vacation :palm_tree:`.
You can also set your current status [using the API](../../api/users.md#user-status).
+## Commit email
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21598) in GitLab 11.4.
+
+A commit email, is the email that will be displayed in every Git-related action done through the
+GitLab interface.
+
+You are able to select from the list of your own verified emails which email you want to use as the commit email.
+
+To change it:
+
+1. Open the user menu in the top-right corner of the navigation bar.
+1. Hit **Commit email** selection box.
+1. Select any of the verified emails.
+1. Hit **Update profile settings**.
+
+### Private commit email
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22560) in GitLab 11.5.
+
+GitLab provides the user with an automatically generated private commit email option,
+which allows the user to not make their email information public.
+
+To enable this option:
+
+1. Open the user menu in the top-right corner of the navigation bar.
+1. Hit **Commit email** selection box.
+1. Select **Use a private email** option.
+1. Hit **Update profile settings**.
+
+Once this option is enabled, every Git-related action will be performed using the private commit email.
+
+In order to stay fully annonymous, you can also copy this private commit email
+and configure it on your local machine using the following command:
+
+```
+git config --global user.email "YOUR_PRIVATE_COMMIT_EMAIL"
+```
+
## Troubleshooting
### Why do I keep getting signed out?
diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md
index 25d6c34409c..7d55048c994 100644
--- a/doc/user/profile/personal_access_tokens.md
+++ b/doc/user/profile/personal_access_tokens.md
@@ -45,16 +45,14 @@ the following table.
| Scope | Description |
| ----- | ----------- |
|`read_user` | Allows access to the read-only endpoints under `/users`. Essentially, any of the `GET` requests in the [Users API][users] are allowed ([introduced][ce-5951] in GitLab 8.15). |
-| `api` | Grants complete access to the API (read/write) ([introduced][ce-5951] in GitLab 8.15). Required for accessing Git repositories over HTTP when 2FA is enabled. |
-| `read_registry` | Allows to read [container registry] images if a project is private and authorization is required ([introduced][ce-11845] in GitLab 9.3). |
+| `api` | Grants complete access to the API and Container Registry (read/write) ([introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5951) in GitLab 8.15). Required for accessing Git repositories over HTTP when 2FA is enabled. |
+| `read_registry` | Allows to read (pull) [container registry] images if a project is private and authorization is required ([introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11845) in GitLab 9.3). |
| `sudo` | Allows performing API actions as any user in the system (if the authenticated user is an admin) ([introduced][ce-14838] in GitLab 10.2). |
-| `read_repository` | Allows read-access to the repository through git clone. |
+| `read_repository` | Allows read-access (pull) to the repository through git clone. |
[2fa]: ../account/two_factor_authentication.md
[api]: ../../api/README.md
[ce-3749]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3749
-[ce-5951]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5951
-[ce-11845]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11845
[ce-14838]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/14838
[container registry]: ../project/container_registry.md
[users]: ../../api/users.md
diff --git a/doc/user/project/clusters/eks_and_gitlab/img/new_project.png b/doc/user/project/clusters/eks_and_gitlab/img/new_project.png
deleted file mode 100644
index 02afc099f10..00000000000
--- a/doc/user/project/clusters/eks_and_gitlab/img/new_project.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/clusters/eks_and_gitlab/img/rbac.png b/doc/user/project/clusters/eks_and_gitlab/img/rbac.png
new file mode 100644
index 00000000000..517e4f7ca44
--- /dev/null
+++ b/doc/user/project/clusters/eks_and_gitlab/img/rbac.png
Binary files differ
diff --git a/doc/user/project/clusters/eks_and_gitlab/index.md b/doc/user/project/clusters/eks_and_gitlab/index.md
index 10f0cdb333e..fa2ed21f980 100644
--- a/doc/user/project/clusters/eks_and_gitlab/index.md
+++ b/doc/user/project/clusters/eks_and_gitlab/index.md
@@ -1,72 +1,171 @@
----
-author: Joshua Lambert
-author_gitlab: joshlambert
-level: intermediate
-article_type: tutorial
-date: 2018-06-05
----
-
# Connecting and deploying to an Amazon EKS cluster
-## Introduction
+In this tutorial, we will show how to integrate an
+[Amazon EKS](https://aws.amazon.com/eks/) cluster with GitLab and begin
+deploying applications.
-In this tutorial, we will show how easy it is to integrate an [Amazon EKS](https://aws.amazon.com/eks/) cluster with GitLab, and begin deploying applications.
+## Introduction
For an end-to-end walkthrough we will:
-1. Start with a new project based on the sample Ruby on Rails template
-1. Integrate an EKS cluster
-1. Utilize [Auto DevOps](../../../../topics/autodevops/) to build, test, and deploy our application
+
+1. Start with a new project based on the sample Ruby on Rails template.
+1. Integrate an EKS cluster.
+1. Utilize [Auto DevOps](../../../../topics/autodevops/) to build, test, and deploy our application.
You will need:
-1. An account on GitLab, like [GitLab.com](https://gitlab.com)
-1. An Amazon EKS cluster
-1. `kubectl` [installed and configured for access to the EKS cluster](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html#get-started-kubectl)
-If you don't have an Amazon EKS cluster, one can be created by following [the EKS getting started guide](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html).
+1. An account on GitLab, like [GitLab.com](https://gitlab.com).
+1. An Amazon EKS cluster (with worker nodes properly configured).
+1. `kubectl` [installed and configured for access to the EKS cluster](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html#get-started-kubectl).
-## Creating a new project
+If you don't have an Amazon EKS cluster, one can be created by following the
+[EKS getting started guide](https://docs.aws.amazon.com/eks/latest/userguide/getting-started.html).
-On GitLab, create a new project by clicking on the `+` icon in the top navigation bar, and selecting `New project`.
+## Creating a new project
-![New Project](img/new_project.png)
+On GitLab, create a new project by clicking on the `+` icon in the top navigation
+bar and selecting **New project**.
-On the new project screen, click on the `Create from template` tab, and select `Use template` for the Ruby on Rails sample project.
+On the new project screen, click on the **Create from template** tab, and select
+"Use template" for the Ruby on Rails sample project.
-Give the project a name, and then select `Create project`.
+Give the project a name, and then select **Create project**.
![Create Project](img/create_project.png)
-## Connecting the EKS cluster
+## Configuring and connecting the EKS cluster
+
+From the left side bar, hover over **Operations > Kubernetes > Add Kubernetes cluster**,
+then click **Add an existing Kubernetes cluster**.
+
+A few details from the EKS cluster will be required to connect it to GitLab:
+
+1. **Retrieve the certificate**: A valid Kubernetes certificate is needed to
+ authenticate to the EKS cluster. We will use the certificate created by default.
+ Open a shell and use `kubectl` to retrieve it:
+
+ - List the secrets with `kubectl get secrets`, and one should named similar to
+ `default-token-xxxxx`. Copy that token name for use below.
+ - Get the certificate with:
+
+ ```sh
+ kubectl get secret <secret name> -o jsonpath="{['data']['ca\.crt']}" | base64 -D
+ ```
+
+1. **Create admin token**: A `cluster-admin` token is required to install and
+ manage Helm Tiller. GitLab establishes mutual SSL auth with Helm Tiller
+ and creates limited service accounts for each application. To create the
+ token we will create an admin service account as follows:
+
+ 2.1. Create a file called `eks-admin-service-account.yaml` with contents:
+
+ ```yaml
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+ name: eks-admin
+ namespace: kube-system
+ ```
+
+ 2.2. Apply the service account to your cluster:
+
+ ```bash
+ kubectl apply -f eks-admin-service-account.yaml
+ ```
+
+ Output:
-From the left side bar, hover over `Operations` and select `Kubernetes`, then click on `Add Kubernetes cluster`, and finally `Add an existing Kubernetes cluster`.
+ ```bash
+ serviceaccount "eks-admin" created
+ ```
-A few details from the EKS cluster will be required to connect it to GitLab.
+ 2.3. Create a file called `eks-admin-cluster-role-binding.yaml` with contents:
-1. A valid Kubernetes certificate and token are needed to authenticate to the EKS cluster. A pair is created by default, which can be used. Open a shell and use `kubectl` to retrieve them:
- * List the secrets with `kubectl get secrets`, and one should named similar to `default-token-xxxxx`. Copy that token name for use below.
- * Get the certificate with `kubectl get secret <secret name> -o jsonpath="{['data']['ca\.crt']}" | base64 -D`
- * Retrieve the token with `kubectl get secret <secret name> -o jsonpath="{['data']['token']}" | base64 -D`.
-1. The API server endpoint is also required, so GitLab can connect to the cluster. This is displayed on the AWS EKS console, when viewing the EKS cluster details.
+ ```yaml
+ apiVersion: rbac.authorization.k8s.io/v1beta1
+ kind: ClusterRoleBinding
+ metadata:
+ name: eks-admin
+ roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: cluster-admin
+ subjects:
+ - kind: ServiceAccount
+ name: eks-admin
+ namespace: kube-system
+ ```
+
+ 2.4. Apply the cluster role binding to your cluster:
+
+ ```bash
+ kubectl apply -f eks-admin-cluster-role-binding.yaml
+ ```
+
+ Output:
+
+ ```bash
+ clusterrolebinding "eks-admin" created
+ ```
+
+ 2.5. Retrieve the token for the `eks-admin` service account:
+
+ ```bash
+ kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep eks-admin | awk '{print $1}')
+ ```
+
+ Copy the `<authentication_token>` value from the output:
+
+ ```yaml
+ Name: eks-admin-token-b5zv4
+ Namespace: kube-system
+ Labels: <none>
+ Annotations: kubernetes.io/service-account.name=eks-admin
+ kubernetes.io/service-account.uid=bcfe66ac-39be-11e8-97e8-026dce96b6e8
+
+ Type: kubernetes.io/service-account-token
+
+ Data
+ ====
+ ca.crt: 1025 bytes
+ namespace: 11 bytes
+ token: <authentication_token>
+ ```
+
+1. The API server endpoint is also required, so GitLab can connect to the cluster.
+ This is displayed on the AWS EKS console, when viewing the EKS cluster details.
You now have all the information needed to connect the EKS cluster:
-* Kubernetes cluster name: Provide a name for the cluster to identify it within GitLab.
-* Environment scope: Leave this as `*` for now, since we are only connecting a single cluster.
-* API URL: Paste in the API server endpoint retrieved above.
-* CA Certificate: Paste the certificate data from the earlier step, as-is.
-* Paste the token value. Note on some versions of Kubernetes a trailing `%` is output, do not include it.
-* Project namespace: This can be left blank to accept the default namespace, based on the project name.
+
+- Kubernetes cluster name: Provide a name for the cluster to identify it within GitLab.
+- Environment scope: Leave this as `*` for now, since we are only connecting a single cluster.
+- API URL: Paste in the API server endpoint retrieved above.
+- CA Certificate: Paste the certificate data from the earlier step, as-is.
+- Paste the admin token value.
+- Project namespace: This can be left blank to accept the default namespace, based on the project name.
![Add Cluster](img/add_cluster.png)
-Click on `Add Kubernetes cluster`, the cluster is now connected to GitLab. At this point, [Kubernetes deployment variables](../#deployment-variables) will automatically be available during CI jobs, making it easy to interact with the cluster.
+Click on **Add Kubernetes cluster**, the cluster is now connected to GitLab.
+At this point, [Kubernetes deployment variables](../#deployment-variables) will
+automatically be available during CI/CD jobs, making it easy to interact with the cluster.
If you would like to utilize your own CI/CD scripts to deploy to the cluster, you can stop here.
-## Disable Role-Based Access Control (RBAC)
+## Disable Role-Based Access Control (RBAC) (optional)
+
+When connecting a cluster via GitLab integration, you may specify whether the
+cluster is RBAC-enabled or not. This will affect how GitLab interacts with the
+cluster for certain operations. If you **did not** check the "RBAC-enabled cluster"
+checkbox at creation time, GitLab will assume RBAC is disabled for your cluster
+when interacting with it. If so, you must disable RBAC on your cluster for the
+integration to work properly.
-Presently, Auto DevOps and one-click app installs do not support [Kubernetes role-based access control](https://kubernetes.io/docs/reference/access-authn-authz/rbac/). Support is [being worked on](https://gitlab.com/groups/gitlab-org/-/epics/136), but in the interim RBAC must be disabled to utilize for these features.
+![rbac](img/rbac.png)
-> **Note**: Disabling RBAC means that any application running in the cluster, or user who can authenticate to the cluster, has full API access. This is a [security concern](https://docs.gitlab.com/ee/user/project/clusters/#security-implications), and may not be desirable.
+NOTE: **Note**: Disabling RBAC means that any application running in the cluster,
+or user who can authenticate to the cluster, has full API access. This is a
+[security concern](../index.md#security-implications), and may not be desirable.
To effectively disable RBAC, global permissions can be applied granting full access:
@@ -80,56 +179,100 @@ kubectl create clusterrolebinding permissive-binding \
## Deploy services to the cluster
-GitLab supports one-click deployment of helpful services to the cluster, many of which support Auto DevOps. Back on the Kubernetes cluster screen in GitLab, a list of applications is now available to deploy.
+GitLab supports one-click deployment of helpful services to the cluster, many of
+which support Auto DevOps. Back on the Kubernetes cluster screen in GitLab, a
+list of applications is now available to deploy.
-First install Helm Tiller, a package manager for Kubernetes. This enables deployment of the other applications.
+First, install Helm Tiller, a package manager for Kubernetes. This enables
+deployment of the other applications.
![Deploy Apps](img/deploy_apps.png)
### Deploying NGINX Ingress (optional)
-Next, if you would like the deployed app to be reachable on the internet, deploy the Ingress. Note that this will also cause an [Elastic Load Balancer](https://aws.amazon.com/documentation/elastic-load-balancing/) to be created, which will incur additional AWS costs.
+Next, if you would like the deployed app to be reachable on the internet, deploy
+the Ingress. Note that this will also cause an
+[Elastic Load Balancer](https://aws.amazon.com/documentation/elastic-load-balancing/)
+to be created, which will incur additional AWS costs.
-Once installed, you may see a `?` for `Ingress IP Address`. This is because the created ELB is available at a DNS name, not an IP address. To get the DNS name, run: `kubectl get service ingress-nginx-ingress-controller -n gitlab-managed-apps -o jsonpath="{.status.loadBalancer.ingress[0].hostname}"`. Note, you may see a trailing `%` on some Kubernetes versions, do not include it.
+Once installed, you may see a `?` for "Ingress IP Address". This is because the
+created ELB is available at a DNS name, not an IP address. To get the DNS name,
+run:
-The Ingress is now available at this address, and will route incoming requests to the proper service based on the DNS name in the request. To support this, a wildcard DNS CNAME record should be created for the desired domain name. For example `*.myekscluster.com` would point to the Ingress hostname obtained earlier.
+```sh
+kubectl get service ingress-nginx-ingress-controller -n gitlab-managed-apps -o jsonpath="{.status.loadBalancer.ingress[0].hostname}"
+```
+
+Note that you may see a trailing `%` on some Kubernetes versions, **do not include it**.
+
+The Ingress is now available at this address and will route incoming requests to
+the proper service based on the DNS name in the request. To support this, a
+wildcard DNS CNAME record should be created for the desired domain name. For example,
+`*.myekscluster.com` would point to the Ingress hostname obtained earlier.
![Create DNS](img/create_dns.png)
### Deploying the GitLab Runner (optional)
-If the project is on GitLab.com, free shared runners are available and you do not have to deploy one. If a project specific runner is desired, or there are no shared runners, it is easy to deploy one.
+If the project is on GitLab.com, free shared Runners are available and you do
+not have to deploy one. If a project specific Runner is desired, or there are no
+shared Runners, it is easy to deploy one.
-Simply click on the `Install` button for the GitLab Runner. It is important to note that the runner deployed is set as **privileged**, which means it essentially has root access to the underlying machine. This is required to build docker images, and so is on by default.
+Simply click on the **Install** button for the GitLab Runner. It is important to
+note that the Runner deployed is set as **privileged**, which means it essentially
+has root access to the underlying machine. This is required to build docker images,
+and so is on by default.
### Deploying Prometheus (optional)
-GitLab is able to monitor applications automatically, utilizing [Prometheus](../../integrations/prometheus.html). Kubernetes container CPU and memory metrics are automatically collected, and response metrics are retrieved from NGINX Ingress as well.
+GitLab is able to monitor applications automatically, utilizing
+[Prometheus](../../integrations/prometheus.html). Kubernetes container CPU and
+memory metrics are automatically collected, and response metrics are retrieved
+from NGINX Ingress as well.
-To enable monitoring, simply install Prometheus into the cluster with the `Install` button.
+To enable monitoring, simply install Prometheus into the cluster with the
+**Install** button.
## Create a default Storage Class
-Amazon EKS does not have a default Storage Class out of the box, which means requests for persistent volumes will not be automatically fulfilled. As part of Auto DevOps, the deployed Postgres instance requests persistent storage, and without a default storage class it will fail to start.
+Amazon EKS doesn't have a default Storage Class out of the box, which means
+requests for persistent volumes will not be automatically fulfilled. As part
+of Auto DevOps, the deployed Postgres instance requests persistent storage,
+and without a default storage class it will fail to start.
-If a default Storage Class does not already exist and is desired, follow Amazon's [short guide](https://docs.aws.amazon.com/eks/latest/userguide/storage-classes.html) to create one.
+If a default Storage Class doesn't already exist and is desired, follow Amazon's
+[guide on storage classes](https://docs.aws.amazon.com/eks/latest/userguide/storage-classes.html)
+to create one.
-Alternatively, disable Postgres by setting the project variable [`POSTGRES_ENABLED`](../../../../topics/autodevops/#environment-variables) to `false`.
+Alternatively, disable Postgres by setting the project variable
+[`POSTGRES_ENABLED`](../../../../topics/autodevops/#environment-variables) to `false`.
## Deploy the app to EKS
-With RBAC disabled and services deployed, [Auto DevOps](https://docs.gitlab.com/ee/topics/autodevops/) can now be leveraged to build, test, and deploy the app. To enable, click on `Settings` in the left sidebar, then `CI/CD`. You will see a section for `Auto DevOps`, expand it. Click on the radio button to `Enable Auto DevOps`.
+With RBAC disabled and services deployed,
+[Auto DevOps](../../../../topics/autodevops/index.md) can now be leveraged
+to build, test, and deploy the app.
-If a wildcard DNS entry was created resolving to the Load Balancer, enter it in the `domain` field. Otherwise, the deployed app will not be externally available outside of the cluster. To save, click `Save changes`.
+[Enable Auto DevOps](../../../../topics/autodevops/index.md##enablingdisabling-auto-devops-at-the-project-level)
+if not already enabled. If a wildcard DNS entry was created resolving to the
+Load Balancer, enter it in the `domain` field under the Auto DevOps settings.
+Otherwise, the deployed app will not be externally available outside of the cluster.
![Deploy Pipeline](img/pipeline.png)
-A new pipeline will automatically be created, which will begin to build, test, and deploy the app.
+A new pipeline will automatically be created, which will begin to build, test,
+and deploy the app.
-After the pipeline has finished, your app will be running in EKS and available to users. Click on `CI/CD` tab in the left navigation bar, and choose `Environments`.
+After the pipeline has finished, your app will be running in EKS and available
+to users. Click on **CI/CD > Environments**.
![Deployed Environment](img/environment.png)
-You will see a list of the environments and their deploy status, as well as options to browse to the app, view monitoring metrics, and even access a shell on the running pod.
+You will see a list of the environments and their deploy status, as well as
+options to browse to the app, view monitoring metrics, and even access a shell
+on the running pod.
+
+## Learn more
-To learn more about Auto DevOps, review our [documentation](../../../../topics/autodevops/).
+To learn more on automatically deploying your applications,
+read about [Auto DevOps](../../../../topics/autodevops/index.md).
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index 41768998a59..79b36e5263e 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -49,8 +49,8 @@ new Kubernetes cluster to your project:
NOTE: **Note:**
You need Maintainer [permissions] and above to access the Kubernetes page.
-1. Click on **Add Kubernetes cluster**.
-1. Click on **Create with Google Kubernetes Engine**.
+1. Click **Add Kubernetes cluster**.
+1. Click **Create with Google Kubernetes Engine**.
1. Connect your Google account if you haven't done already by clicking the
**Sign in with Google** button.
1. From there on, choose your cluster's settings:
@@ -78,8 +78,8 @@ To add an existing Kubernetes cluster to your project:
NOTE: **Note:**
You need Maintainer [permissions] and above to access the Kubernetes page.
-1. Click on **Add Kubernetes cluster**.
-1. Click on **Add an existing Kubernetes cluster** and fill in the details:
+1. Click **Add Kubernetes cluster**.
+1. Click **Add an existing Kubernetes cluster** and fill in the details:
- **Kubernetes cluster name** (required) - The name you wish to give the cluster.
- **Environment scope** (required)- The
[associated environment](#setting-the-environment-scope) to this cluster.
@@ -92,13 +92,47 @@ To add an existing Kubernetes cluster to your project:
the `ca.crt` contents here.
- **Token** -
GitLab authenticates against Kubernetes using service tokens, which are
- scoped to a particular `namespace`. If you don't have a service token yet,
- you can follow the
- [Kubernetes documentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/)
- to create one. You can also view or create service tokens in the
- [Kubernetes dashboard](https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/)
- (under **Config > Secrets**). **The account that will issue the service token
- must have admin privileges on the cluster.**
+ scoped to a particular `namespace`.
+ **The token used should belong to a service account with
+ [`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)
+ privileges.** To create this service account:
+
+ 1. Create a `gitlab` service account in the `default` namespace:
+
+ ```bash
+ kubectl create -f - <<EOF
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+ name: gitlab
+ namespace: default
+ EOF
+ ```
+ 1. Create a cluster role binding to give the `gitlab` service account
+ `cluster-admin` privileges:
+
+ ```bash
+ kubectl create -f - <<EOF
+ kind: ClusterRoleBinding
+ apiVersion: rbac.authorization.k8s.io/v1
+ metadata:
+ name: gitlab-cluster-admin
+ subjects:
+ - kind: ServiceAccount
+ name: gitlab
+ namespace: default
+ roleRef:
+ kind: ClusterRole
+ name: cluster-admin
+ apiGroup: rbac.authorization.k8s.io
+ EOF
+ ```
+ NOTE: **Note:**
+ For GKE clusters, you will need the
+ `container.clusterRoleBindings.create` permission to create a cluster
+ role binding. You can follow the [Google Cloud
+ documentation](https://cloud.google.com/iam/docs/granting-changing-revoking-access)
+ to grant access.
- **Project namespace** (optional) - You don't have to fill it in; by leaving
it blank, GitLab will create one for you. Also:
- Each project should have a unique namespace.
@@ -113,6 +147,14 @@ To add an existing Kubernetes cluster to your project:
After a couple of minutes, your cluster will be ready to go. You can now proceed
to install some [pre-defined applications](#installing-applications).
+To determine the:
+
+- API URL, run `kubectl cluster-info | grep 'Kubernetes master' | awk '/http/ {print $NF}'`.
+- Token:
+ 1. List the secrets by running: `kubectl get secrets`. Note the name of the secret you need the token for.
+ 1. Get the token for the appropriate secret by running: `kubectl get secret <SECRET_NAME> -o jsonpath="{['data']['token']}" | base64 -D`.
+- CA certificate, run `kubectl get secret <secret name> -o jsonpath="{['data']['ca\.crt']}" | base64 -D`.
+
## Security implications
CAUTION: **Important:**
@@ -124,84 +166,64 @@ functionalities needed to successfully build and deploy a containerized
application. Bare in mind that the same credentials are used for all the
applications running on the cluster.
-When GitLab creates the cluster, it enables and uses the legacy
-[Attribute-based access control (ABAC)](https://kubernetes.io/docs/admin/authorization/abac/).
-The newer [RBAC](https://kubernetes.io/docs/admin/authorization/rbac/)
-authorization is [experimental](#role-based-access-control-rbac).
-
-### Role-based access control (RBAC) **[CORE ONLY]**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21401) in GitLab 11.4.
-
-CAUTION: **Warning:**
-The RBAC authorization is experimental. To enable it you need access to the
-server where GitLab is installed.
-
-The support for RBAC-enabled clusters is hidden behind a feature flag. Once
-the feature flag is enabled, GitLab will create the necessary service accounts
-and privileges in order to install and run [GitLab managed applications](#installing-applications).
-
-To enable the feature flag:
-
-1. SSH into the server where GitLab is installed.
-1. Enter the Rails console:
-
- **For Omnibus GitLab**
-
- ```sh
- sudo gitlab-rails console
- ```
-
- **For installations from source**
-
- ```sh
- sudo -u git -H bundle exec rails console
- ```
-
-1. Enable the RBAC authorization:
-
- ```ruby
- Feature.enable('rbac_clusters')
- ```
-
-If you are creating a [new GKE cluster via
-GitLab](#adding-and-creating-a-new-gke-cluster-via-gitlab), you will be
-asked if you would like to create an RBAC-enabled cluster. Enabling this
-setting will create a `gitlab` service account which will be used by
-GitLab to manage the newly created cluster. To enable this, this service
-account will have the `cluster-admin` privilege.
-
-If you are [adding an existing Kubernetes
-cluster](#adding-an-existing-kubernetes-cluster), you will be asked if
-the cluster you are adding is a RBAC-enabled cluster. Ensure the
-token of the account has administrator privileges for the cluster.
-
-In both cases above, when you install Helm Tiller into your cluster, an
-RBAC-enabled cluster will create a `tiller` service account, with `cluster-admin`
-privileges in the `gitlab-managed-apps` namespace. This service account will be
-added to the installed Helm Tiller and will be used by Helm to install and run
-[GitLab managed applications](#installing-applications).
-
-The table below summarizes which resources will be created in a
-RBAC-enabled cluster :
-
-| Name | Kind | Details | Created when |
-| --- | --- | --- | --- |
-| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new GKE Cluster |
-| `gitlab-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Creating a new GKE Cluster |
-| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new GKE Cluster |
-| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
-| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
-
-
-Helm Tiller will also create additional service accounts and other RBAC
-resources for each installed application. Consult the documentation for the
-Helm charts for each application for details.
-
-NOTE: **Note:**
-Auto DevOps will not successfully complete in a cluster that only has RBAC
-authorization enabled. RBAC support for Auto DevOps is planned in a
-[future release](https://gitlab.com/gitlab-org/gitlab-ce/issues/44597).
+## Access controls
+
+When creating a cluster in GitLab, you will be asked if you would like to create an
+[Attribute-based access control (ABAC)](https://kubernetes.io/docs/admin/authorization/abac/) cluster, or
+a [Role-based access control (RBAC)](https://kubernetes.io/docs/admin/authorization/rbac/) one.
+
+Whether ABAC or RBAC is enabled, GitLab will create the necessary
+service accounts and privileges in order to install and run
+[GitLab managed applications](#installing-applications):
+
+- If GitLab is creating the cluster, a `gitlab` service account with
+ `cluster-admin` privileges will be created in the `default` namespace,
+ which will be used by GitLab to manage the newly created cluster.
+
+- A project service account with [`edit`
+ privileges](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles)
+ will be created in the project namespace (also created by GitLab), which will
+ be used in [deployment jobs](#deployment-variables).
+
+ NOTE: **Note:**
+ Restricted service account for deployment was [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/51716) in GitLab 11.5.
+
+- When you install Helm Tiller into your cluster, the `tiller` service account
+ will be created with `cluster-admin` privileges in the `gitlab-managed-apps`
+ namespace. This service account will be added to the installed Helm Tiller and will
+ be used by Helm to install and run [GitLab managed applications](#installing-applications).
+ Helm Tiller will also create additional service accounts and other resources for each
+ installed application. Consult the documentation of the Helm charts for each application
+ for details.
+
+If you are [adding an existing Kubernetes cluster](#adding-an-existing-kubernetes-cluster),
+ensure the token of the account has administrator privileges for the cluster.
+
+The following sections summarize which resources will be created on ABAC/RBAC clusters.
+
+### Attribute-based access control (ABAC)
+
+| Name | Kind | Details | Created when |
+| --- | --- | --- | --- |
+| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new GKE Cluster |
+| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new GKE Cluster |
+| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
+| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
+| Project namespace | `ServiceAccount` | Uses namespace of Project | Creating/Adding a new GKE Cluster |
+| Project namespace | `Secret` | Token for project ServiceAccount | Creating/Adding a new GKE Cluster |
+
+### Role-based access control (RBAC)
+
+| Name | Kind | Details | Created when |
+| --- | --- | --- | --- |
+| `gitlab` | `ServiceAccount` | `default` namespace | Creating a new GKE Cluster |
+| `gitlab-admin` | `ClusterRoleBinding` | [`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Creating a new GKE Cluster |
+| `gitlab-token` | `Secret` | Token for `gitlab` ServiceAccount | Creating a new GKE Cluster |
+| `tiller` | `ServiceAccount` | `gitlab-managed-apps` namespace | Installing Helm Tiller |
+| `tiller-admin` | `ClusterRoleBinding` | `cluster-admin` roleRef | Installing Helm Tiller |
+| Project namespace | `ServiceAccount` | Uses namespace of Project | Creating/Adding a new GKE Cluster |
+| Project namespace | `Secret` | Token for project ServiceAccount | Creating/Adding a new GKE Cluster |
+| Project namespace | `RoleBinding` | [`edit`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) roleRef | Creating/Adding a new GKE Cluster |
### Security of GitLab Runners
@@ -228,7 +250,7 @@ added directly to your configured cluster. Those applications are needed for
[Review Apps](../../../ci/review_apps/index.md) and [deployments](../../../ci/environments.md).
NOTE: **Note:**
-The applications will be installed in a dedicated namespace called
+With the exception of Knative, the applications will be installed in a dedicated namespace called
`gitlab-managed-apps`. In case you have added an existing Kubernetes cluster
with Tiller already installed, you should be careful as GitLab cannot
detect it. By installing it via the applications will result into having it
@@ -238,16 +260,23 @@ twice, which can lead to confusion during deployments.
| ----------- | :------------: | ----------- | --------------- |
| [Helm Tiller](https://docs.helm.sh/) | 10.2+ | Helm is a package manager for Kubernetes and is required to install all the other applications. It is installed in its own pod inside the cluster which can run the `helm` CLI in a safe environment. | n/a |
| [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) | 10.2+ | Ingress can provide load balancing, SSL termination, and name-based virtual hosting. It acts as a web proxy for your applications and is useful if you want to use [Auto DevOps] or deploy your own web apps. | [stable/nginx-ingress](https://github.com/helm/charts/tree/master/stable/nginx-ingress) |
+| [Cert Manager](http://docs.cert-manager.io/en/latest/) | 11.6+ | Cert Manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing Cert Manager on your cluster will issue a certificate by [Let's Encrypt](https://letsencrypt.org/) and ensure that certificates are valid and up to date. The email address used by Let's Encrypt registration will be taken from the GitLab user that installed Cert Manager on the cluster. | [stable/cert-manager](https://github.com/helm/charts/tree/master/stable/cert-manager) |
| [Prometheus](https://prometheus.io/docs/introduction/overview/) | 10.4+ | Prometheus is an open-source monitoring and alerting system useful to supervise your deployed applications. | [stable/prometheus](https://github.com/helm/charts/tree/master/stable/prometheus) |
| [GitLab Runner](https://docs.gitlab.com/runner/) | 10.6+ | GitLab Runner is the open source project that is used to run your jobs and send the results back to GitLab. It is used in conjunction with [GitLab CI/CD](https://about.gitlab.com/features/gitlab-ci-cd/), the open-source continuous integration service included with GitLab that coordinates the jobs. When installing the GitLab Runner via the applications, it will run in **privileged mode** by default. Make sure you read the [security implications](#security-implications) before doing so. | [runner/gitlab-runner](https://gitlab.com/charts/gitlab-runner) |
-| [JupyterHub](http://jupyter.org/) | 11.0+ | [JupyterHub](https://jupyterhub.readthedocs.io/en/stable/) is a multi-user service for managing notebooks across a team. [Jupyter Notebooks](https://jupyter-notebook.readthedocs.io/en/latest/) provide a web-based interactive programming environment used for data analysis, visualization, and machine learning. We use [this](https://gitlab.com/gitlab-org/jupyterhub-user-image/blob/master/Dockerfile) custom Jupyter image that installs additional useful packages on top of the base Jupyter. **Note**: Authentication will be enabled for any user of the GitLab server via OAuth2. HTTPS will be supported in a future release. | [jupyter/jupyterhub](https://jupyterhub.github.io/helm-chart/) |
+| [JupyterHub](http://jupyter.org/) | 11.0+ | [JupyterHub](https://jupyterhub.readthedocs.io/en/stable/) is a multi-user service for managing notebooks across a team. [Jupyter Notebooks](https://jupyter-notebook.readthedocs.io/en/latest/) provide a web-based interactive programming environment used for data analysis, visualization, and machine learning. We use [this](https://gitlab.com/gitlab-org/jupyterhub-user-image/blob/master/Dockerfile) custom Jupyter image that installs additional useful packages on top of the base Jupyter. You will also see ready-to-use DevOps Runbooks built with Nurtch's [Rubix library](https://github.com/amit1rrr/rubix). More information on creating executable runbooks can be found at [Nurtch Documentation](http://docs.nurtch.com/en/latest). **Note**: Authentication will be enabled for any user of the GitLab server via OAuth2. HTTPS will be supported in a future release. | [jupyter/jupyterhub](https://jupyterhub.github.io/helm-chart/) |
+| [Knative](https://cloud.google.com/knative) | 11.5+ | Knative provides a platform to create, deploy, and manage serverless workloads from a Kubernetes cluster. It is used in conjunction with, and includes [Istio](https://istio.io) to provide an external IP address for all programs hosted by Knative. You will be prompted to enter a wildcard domain where your applications will be exposed. Configure your DNS server to use the external IP address for that domain. For any application created and installed, they will be accessible as `<program_name>.<kubernetes_namespace>.<domain_name>`. This will require your kubernetes cluster to have [RBAC enabled](#role-based-access-control-rbac). | [knative/knative](https://storage.googleapis.com/triggermesh-charts)
+
+NOTE: **Note:**
+As of GitLab 11.6 Helm Tiller will be upgraded to the latest version supported
+by GitLab before installing any of the above applications.
## Getting the external IP address
NOTE: **Note:**
-You need a load balancer installed in your cluster in order to obtain the
-external IP address with the following procedure. It can be deployed using the
-[**Ingress** application](#installing-applications).
+With the following procedure, a load balancer must be installed in your cluster
+to obtain the external IP address. You can use either
+[Ingress](#installing-applications), or Knative's own load balancer
+([Istio](https://istio.io)) if using [Knative](#installing-applications).
In order to publish your web application, you first need to find the external IP
address associated to your load balancer.
@@ -256,21 +285,24 @@ address associated to your load balancer.
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17052) in GitLab 10.6.
-If you installed the Ingress [via the **Applications**](#installing-applications),
+If you [installed Ingress or Knative](#installing-applications),
you should see the Ingress IP address on this same page within a few minutes.
If you don't see this, GitLab might not be able to determine the IP address of
your ingress application in which case you should manually determine it.
### Manually determining the IP address
-If the cluster is on GKE, click on the **Google Kubernetes Engine** link in the
+If the cluster is on GKE, click the **Google Kubernetes Engine** link in the
**Advanced settings**, or go directly to the
[Google Kubernetes Engine dashboard](https://console.cloud.google.com/kubernetes/)
-and select the proper project and cluster. Then click on **Connect** and execute
+and select the proper project and cluster. Then click **Connect** and execute
the `gcloud` command in a local terminal or using the **Cloud Shell**.
If the cluster is not on GKE, follow the specific instructions for your
Kubernetes provider to configure `kubectl` with the right credentials.
+The output of the following examples will show the external IP address of your
+cluster. This information can then be used to set up DNS entries and forwarding
+rules that allow external access to your deployed applications.
If you installed the Ingress [via the **Applications**](#installing-applications),
run the following command:
@@ -279,20 +311,23 @@ run the following command:
kubectl get svc --namespace=gitlab-managed-apps ingress-nginx-ingress-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip} '
```
-Otherwise, you can list the IP addresses of all load balancers:
+For Istio/Knative, the command will be different:
```bash
-kubectl get svc --all-namespaces -o jsonpath='{range.items[?(@.status.loadBalancer.ingress)]}{.status.loadBalancer.ingress[*].ip} '
+kubectl get svc --namespace=istio-system knative-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip} '
+```
+
+Some Kubernetes clusters return a hostname instead, like [Amazon EKS](https://aws.amazon.com/eks/). For these platforms, run:
+
+```bash
+kubectl get service ingress-nginx-ingress-controller -n gitlab-managed-apps -o jsonpath="{.status.loadBalancer.ingress[0].hostname}".
```
-> **Note**: Some Kubernetes clusters return a hostname instead, like [Amazon EKS](https://aws.amazon.com/eks/). For these platforms, run:
-> ```bash
-> kubectl get service ingress-nginx-ingress-controller -n gitlab-managed-apps -o jsonpath="{.status.loadBalancer.ingress[0].hostname}".
-> ```
+Otherwise, you can list the IP addresses of all load balancers:
-The output is the external IP address of your cluster. This information can then
-be used to set up DNS entries and forwarding rules that allow external access to
-your deployed applications.
+```bash
+kubectl get svc --all-namespaces -o jsonpath='{range.items[?(@.status.loadBalancer.ingress)]}{.status.loadBalancer.ingress[*].ip} '
+```
### Using a static IP
@@ -302,7 +337,7 @@ your apps will not be able to be reached, and you'd have to change the DNS
record again. In order to avoid that, you should change it into a static
reserved IP.
-[Read how to promote an ephemeral external IP address in GKE.](https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address#promote_ephemeral_ip)
+Read how to [promote an ephemeral external IP address in GKE](https://cloud.google.com/compute/docs/ip-addresses/reserve-static-external-ip-address#promote_ephemeral_ip).
### Pointing your DNS at the cluster IP
@@ -393,18 +428,22 @@ GitLab CI/CD build environment.
| Variable | Description |
| -------- | ----------- |
| `KUBE_URL` | Equal to the API URL. |
-| `KUBE_TOKEN` | The Kubernetes token. |
+| `KUBE_TOKEN` | The Kubernetes token of the [project service account](#access-controls). |
| `KUBE_NAMESPACE` | The Kubernetes namespace is auto-generated if not specified. The default value is `<project_name>-<project_id>`. You can overwrite it to use different one if needed, otherwise the `KUBE_NAMESPACE` variable will receive the default value. |
-| `KUBE_CA_PEM_FILE` | Only present if a custom CA bundle was specified. Path to a file containing PEM data. |
-| `KUBE_CA_PEM` | (**deprecated**) Only if a custom CA bundle was specified. Raw PEM data. |
+| `KUBE_CA_PEM_FILE` | Path to a file containing PEM data. Only present if a custom CA bundle was specified. |
+| `KUBE_CA_PEM` | (**deprecated**) Raw PEM data. Only if a custom CA bundle was specified. |
| `KUBECONFIG` | Path to a file containing `kubeconfig` for this deployment. CA bundle would be embedded if specified. |
+NOTE: **NOTE:**
+Prior to GitLab 11.5, `KUBE_TOKEN` was the Kubernetes token of the main
+service account of the cluster integration.
+
## Enabling or disabling the Kubernetes cluster integration
After you have successfully added your cluster information, you can enable the
Kubernetes cluster integration:
-1. Click the "Enabled/Disabled" switch
+1. Click the **Enabled/Disabled** switch
1. Hit **Save** for the changes to take effect
You can now start using your Kubernetes cluster for your deployments.
@@ -421,7 +460,7 @@ When you remove a cluster, you only remove its relation to GitLab, not the
cluster itself. To remove the cluster, you can do so by visiting the GKE
dashboard or using `kubectl`.
-To remove the Kubernetes cluster integration from your project, simply click on the
+To remove the Kubernetes cluster integration from your project, simply click the
**Remove integration** button. You will then be able to follow the procedure
and add a Kubernetes cluster again.
@@ -484,7 +523,13 @@ the deployment variables above, ensuring any pods you create are labelled with
## Read more
-- [Connecting and deploying to an Amazon EKS cluster](eks_and_gitlab/index.md)
+### Integrating Amazon EKS cluster with GitLab
+
+- Learn how to [connect and deploy to an Amazon EKS cluster](eks_and_gitlab/index.md).
+
+### Serverless
+
+- [Run serverless workloads on Kubernetes with Knative.](serverless/index.md)
[permissions]: ../../permissions.md
[ee]: https://about.gitlab.com/pricing/
diff --git a/doc/user/project/clusters/runbooks/img/authorize-jupyter.png b/doc/user/project/clusters/runbooks/img/authorize-jupyter.png
new file mode 100644
index 00000000000..64f95ed45f0
--- /dev/null
+++ b/doc/user/project/clusters/runbooks/img/authorize-jupyter.png
Binary files differ
diff --git a/doc/user/project/clusters/runbooks/img/demo-runbook.png b/doc/user/project/clusters/runbooks/img/demo-runbook.png
new file mode 100644
index 00000000000..25c9df4126d
--- /dev/null
+++ b/doc/user/project/clusters/runbooks/img/demo-runbook.png
Binary files differ
diff --git a/doc/user/project/clusters/runbooks/img/gitlab-variables.png b/doc/user/project/clusters/runbooks/img/gitlab-variables.png
new file mode 100644
index 00000000000..f76ed21145f
--- /dev/null
+++ b/doc/user/project/clusters/runbooks/img/gitlab-variables.png
Binary files differ
diff --git a/doc/user/project/clusters/runbooks/img/helm-install.png b/doc/user/project/clusters/runbooks/img/helm-install.png
new file mode 100644
index 00000000000..e39094bcbf7
--- /dev/null
+++ b/doc/user/project/clusters/runbooks/img/helm-install.png
Binary files differ
diff --git a/doc/user/project/clusters/runbooks/img/ingress-install.png b/doc/user/project/clusters/runbooks/img/ingress-install.png
new file mode 100644
index 00000000000..093c61f2d0e
--- /dev/null
+++ b/doc/user/project/clusters/runbooks/img/ingress-install.png
Binary files differ
diff --git a/doc/user/project/clusters/runbooks/img/jupyterhub-install.png b/doc/user/project/clusters/runbooks/img/jupyterhub-install.png
new file mode 100644
index 00000000000..2115ec9745b
--- /dev/null
+++ b/doc/user/project/clusters/runbooks/img/jupyterhub-install.png
Binary files differ
diff --git a/doc/user/project/clusters/runbooks/img/postgres-query.png b/doc/user/project/clusters/runbooks/img/postgres-query.png
new file mode 100644
index 00000000000..3880438c97a
--- /dev/null
+++ b/doc/user/project/clusters/runbooks/img/postgres-query.png
Binary files differ
diff --git a/doc/user/project/clusters/runbooks/img/sample-runbook.png b/doc/user/project/clusters/runbooks/img/sample-runbook.png
new file mode 100644
index 00000000000..c12ce8990a4
--- /dev/null
+++ b/doc/user/project/clusters/runbooks/img/sample-runbook.png
Binary files differ
diff --git a/doc/user/project/clusters/runbooks/index.md b/doc/user/project/clusters/runbooks/index.md
new file mode 100644
index 00000000000..e1b8dc07b50
--- /dev/null
+++ b/doc/user/project/clusters/runbooks/index.md
@@ -0,0 +1,137 @@
+# Runbooks
+
+Runbooks are a collection of documented procedures that explain how to
+carry out a particular process, be it starting, stopping, debugging,
+or troubleshooting a particular system.
+
+## Overview
+
+Historically, runbooks took the form of a decision tree or a detailed
+step-by-step guide depending on the condition or system.
+
+Modern implementations have introduced the concept of an "executable
+runbooks", where, along with a well-defined process, operators can execute
+pre-written code blocks or database queries against a given environment.
+
+## Nurtch Executable Runbooks
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/45912) in GitLab 11.4.
+
+The JupyterHub app offered via GitLab’s Kubernetes integration now ships
+with Nurtch’s Rubix library, providing a simple way to create DevOps
+runbooks. A sample runbook is provided, showcasing common operations.
+
+**<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+Watch this [video](https://www.youtube.com/watch?v=Q_OqHIIUPjE)
+for an overview of how this is acomplished in GitLab!**
+
+## Requirements
+
+To create an executable runbook, you will need:
+
+1. **Kubernetes** - A Kubernetes cluster is required to deploy the rest of the applications.
+ The simplest way to get started is to add a cluster using [GitLab's GKE integration](https://docs.gitlab.com/ee/user/project/clusters/#adding-and-creating-a-new-gke-cluster-via-gitlab).
+1. **Helm Tiller** - Helm is a package manager for Kubernetes and is required to install
+ all the other applications. It is installed in its own pod inside the cluster which
+ can run the helm CLI in a safe environment.
+1. **Ingress** - Ingress can provide load balancing, SSL termination, and name-based
+ virtual hosting. It acts as a web proxy for your applications.
+1. **JupyterHub** - JupyterHub is a multi-user service for managing notebooks across
+ a team. Jupyter Notebooks provide a web-based interactive programming environment
+ used for data analysis, visualization, and machine learning.
+
+## Nurtch
+
+Nurtch is the company behind the [Rubix library](https://github.com/Nurtch/rubix). Rubix is
+an open-source python library that makes it easy to perform common DevOps tasks inside Jupyter Notebooks.
+Tasks such as plotting Cloudwatch metrics and rolling your ECS/Kubernetes app are simplified
+down to a couple of lines of code. See the [Nurtch Documentation](http://docs.nurtch.com/en/latest)
+for more information.
+
+## Configure an executable runbook with GitLab
+
+Follow this step-by-step guide to configure an executable runbook in GitLab using
+the components outlined above and the preloaded demo runbook.
+
+### 1. Add a Kubernetes cluster
+
+Follow the steps outlined in [Adding and creating a new GKE cluster via GitLab](https://docs.gitlab.com/ee/user/project/clusters/#adding-and-creating-a-new-gke-cluster-via-gitlab)
+to add a Kubernetes cluster to your project.
+
+### 2. Install Helm Tiller, Ingress, and JupyterHub
+
+Once the cluster has been provisioned in GKE, click the **Install** button next to the **Helm Tiller** app.
+
+![install helm](img/helm-install.png)
+
+Once Tiller has been installed successfully, click the **Install** button next to the **Ingress** app.
+
+![install ingress](img/ingress-install.png)
+
+Once Ingress has been installed successfully, click the **Install** button next to the **JupyterHub** app.
+
+![install jupyterhub](img/jupyterhub-install.png)
+
+### 3. Login to JupyterHub and start the server
+
+Once JupyterHub has been installed successfully, navigate to the displayed **Jupyter Hostname** URL and click
+**Sign in with GitLab**. Authentication is automatically enabled for any user of the GitLab instance via OAuth2. This
+will redirect to GitLab in order to authorize JupyterHub to use your GitLab account. Click **Authorize**.
+
+![authorize jupyter](img/authorize-jupyter.png)
+
+Once the application has been authorized you will taken back to the JupyterHub application. Click **Start My Server**.
+The server will take a couple of seconds to start.
+
+### 4. Configure access
+
+In order for the runbook to access your GitLab project, you will need to enter a
+[GitLab Access Token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html)
+as well as your Project ID in the **Setup** section of the demo runbook.
+
+Double-click the **DevOps-Runbook-Demo** folder located on the left panel.
+
+![demo runbook](img/demo-runbook.png)
+
+Double-click the "Nurtch-DevOps-Demo.ipynb" runbook.
+
+![sample runbook](img/sample-runbook.png)
+
+The contents on the runbook will be displayed on the right side of the screen. Under the "Setup" section, you will find
+entries for both your `PRIVATE_TOKEN` and your `PROJECT_ID`. Enter both these values, conserving the single quotes as follows:
+
+```sql
+PRIVATE_TOKEN = 'n671WNGecHugsdEDPsyo'
+PROJECT_ID = '1234567'
+```
+
+Update the `VARIABLE_NAME` on the last line of this section to match the name of the variable you are using for your
+access token. In this example our variable name is `PRIVATE_TOKEN`.
+
+```sql
+VARIABLE_VALUE = project.variables.get('PRIVATE_TOKEN').value
+```
+
+### 5. Configure an operation
+
+For this example we'll use the "**Run SQL queries in Notebook**" section in the sample runbook to query
+a postgres database. The first 4 lines of the section define the variables that are required for this query to function.
+
+```sql
+%env DB_USER={project.variables.get('DB_USER').value}
+%env DB_PASSWORD={project.variables.get('DB_PASSWORD').value}
+%env DB_ENDPOINT={project.variables.get('DB_ENDPOINT').value}
+%env DB_NAME={project.variables.get('DB_NAME').value}
+```
+
+Create the matching variables in your project's **Settings >> CI/CD >> Variables**
+
+![gitlab variables](img/gitlab-variables.png)
+
+Back in Jupyter, click the "Run SQL queries in Notebook" heading and the click *Run*. The results will be
+displayed in-line as follows:
+
+![postgres query](img/postgres-query.png)
+
+You can try other operations such as running shell scripts or interacting with a Kubernetes cluster. Visit the
+[Nurtch Documentation](http://docs.nurtch.com/) for more information. \ No newline at end of file
diff --git a/doc/user/project/clusters/serverless/img/deploy-stage.png b/doc/user/project/clusters/serverless/img/deploy-stage.png
new file mode 100644
index 00000000000..dc2f8af9c63
--- /dev/null
+++ b/doc/user/project/clusters/serverless/img/deploy-stage.png
Binary files differ
diff --git a/doc/user/project/clusters/serverless/img/dns-entry.png b/doc/user/project/clusters/serverless/img/dns-entry.png
new file mode 100644
index 00000000000..2e7655c6041
--- /dev/null
+++ b/doc/user/project/clusters/serverless/img/dns-entry.png
Binary files differ
diff --git a/doc/user/project/clusters/serverless/img/install-knative.png b/doc/user/project/clusters/serverless/img/install-knative.png
new file mode 100644
index 00000000000..dd576a9df35
--- /dev/null
+++ b/doc/user/project/clusters/serverless/img/install-knative.png
Binary files differ
diff --git a/doc/user/project/clusters/serverless/img/knative-app.png b/doc/user/project/clusters/serverless/img/knative-app.png
new file mode 100644
index 00000000000..54301e1786f
--- /dev/null
+++ b/doc/user/project/clusters/serverless/img/knative-app.png
Binary files differ
diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md
new file mode 100644
index 00000000000..bdbc4f7f09d
--- /dev/null
+++ b/doc/user/project/clusters/serverless/index.md
@@ -0,0 +1,137 @@
+# Serverless
+
+> Introduced in GitLab 11.5.
+
+Run serverless workloads on Kubernetes using [Knative](https://cloud.google.com/knative/).
+
+## Overview
+
+Knative extends Kubernetes to provide a set of middleware components that are useful to build modern, source-centric, container-based applications. Knative brings some significant benefits out of the box through its main components:
+
+- [Build:](https://github.com/knative/build) Source-to-container build orchestration
+- [Eventing:](https://github.com/knative/eventing) Management and delivery of events
+- [Serving:](https://github.com/knative/serving) Request-driven compute that can scale to zero
+
+For more information on Knative, visit the [Knative docs repo](https://github.com/knative/docs).
+
+## Requirements
+
+To run Knative on Gitlab, you will need:
+
+1. **Kubernetes:** An RBAC-enabled Kubernetes cluster is required to deploy Knative.
+ The simplest way to get started is to add a cluster using [GitLab's GKE integration](https://docs.gitlab.com/ee/user/project/clusters/#adding-and-creating-a-new-gke-cluster-via-gitlab).
+ GitLab recommends
+1. **Helm Tiller:** Helm is a package manager for Kubernetes and is required to install
+ all the other applications.
+1. **Domain Name:** Knative will provide its own load balancer using Istio. It will provide an
+ external IP address for all the applications served by Knative. You will be prompted to enter a
+ wildcard domain where your applications will be served. Configure your DNS server to use the
+ external IP address for that domain.
+1. **Serverless `gitlab-ci.yml` Template:** GitLab uses [Kaniko](https://github.com/GoogleContainerTools/kaniko)
+ to build the application and the [TriggerMesh CLI](https://github.com/triggermesh/tm), to simplify the
+ deployment of knative services and functions.
+
+ Add the following `.gitlab-ci.yml` to the root of your repository (you may skip this step if using the sample
+ [Knative Ruby App](https://gitlab.com/knative-examples/knative-ruby-app) mentioned below).
+
+ ```yaml
+ stages:
+ - build
+ - deploy
+
+ build:
+ stage: build
+ image:
+ name: gcr.io/kaniko-project/executor:debug
+ entrypoint: [""]
+ only:
+ - master
+ script:
+ - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
+ - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $CI_REGISTRY_IMAGE
+
+ deploy:
+ stage: deploy
+ image: gcr.io/triggermesh/tm@sha256:e3ee74db94d215bd297738d93577481f3e4db38013326c90d57f873df7ab41d5
+ only:
+ - master
+ environment: production
+ script:
+ - echo "$CI_REGISTRY_IMAGE"
+ - tm -n "$KUBE_NAMESPACE" --config "$KUBECONFIG" deploy service "$CI_PROJECT_NAME" --from-image "$CI_REGISTRY_IMAGE" --wait
+ ```
+
+1. **Dockerfile:** Knative requires a Dockerfile in order to build your application. It should be included
+ at the root of your project's repo and expose port 8080.
+
+## Installing Knative via GitLab's Kubernetes integration
+
+NOTE: **Note:**
+Minimum recommended cluster size to run Knative is 3-nodes, 6 vCPUs, and 22.50 GB memory. RBAC must be enabled.
+
+You may download the sample [Knative Ruby App](https://gitlab.com/knative-examples/knative-ruby-app) to get started.
+
+1. [Add a Kubernetes cluster](https://docs.gitlab.com/ce/user/project/clusters/) and install Helm.
+
+1. Once Helm has been successfully installed, on the Knative app section, enter the domain to be used with
+ your application and click "Install".
+
+ ![install-knative](img/install-knative.png)
+
+1. After the Knative installation has finished, retrieve the Istio Ingress IP address by running the following command:
+
+ ```bash
+ kubectl get svc --namespace=istio-system knative-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip} '
+ ```
+
+ Output:
+
+ ```bash
+ 35.161.143.124 my-machine-name:~ my-user$
+ ```
+
+1. The ingress is now available at this address and will route incoming requests to the proper service based on the DNS
+ name in the request. To support this, a wildcard DNS A record should be created for the desired domain name. For example,
+ if your Knative base domain is `knative.example.com` then you need to create an A record with domain `*.knative.example.com`
+ pointing the ip address of the ingress.
+
+ ![dns entry](img/dns-entry.png)
+
+## Deploy the application with Knative
+
+With all the pieces in place, you can simply create a new CI pipeline to deploy the Knative application. Navigate to
+**CI/CD >> Pipelines** and click the **Run Pipeline** button at the upper-right part of the screen. Then, on the
+Pipelines page, click **Create pipeline**.
+
+## Obtain the URL for the Knative deployment
+
+Once all the stages of the pipeline finish, click the **deploy** stage.
+
+![deploy stage](img/deploy-stage.png)
+
+The output will look like this:
+
+```bash
+Running with gitlab-runner 11.5.0~beta.844.g96d88322 (96d88322)
+ on docker-auto-scale 72989761
+Using Docker executor with image gcr.io/triggermesh/tm@sha256:e3ee74db94d215bd297738d93577481f3e4db38013326c90d57f873df7ab41d5 ...
+Pulling docker image gcr.io/triggermesh/tm@sha256:e3ee74db94d215bd297738d93577481f3e4db38013326c90d57f873df7ab41d5 ...
+Using docker image sha256:6b3f6590a9b30bd7aafb9573f047d930c70066e43955b4beb18a1eee175f6de1 for gcr.io/triggermesh/tm@sha256:e3ee74db94d215bd297738d93577481f3e4db38013326c90d57f873df7ab41d5 ...
+Running on runner-72989761-project-4342902-concurrent-0 via runner-72989761-stg-srm-1541795796-27929c96...
+Cloning repository...
+Cloning into '/builds/danielgruesso/knative'...
+Checking out 8671ad20 as master...
+Skipping Git submodules setup
+$ echo "$CI_REGISTRY_IMAGE"
+registry.staging.gitlab.com/danielgruesso/knative
+$ tm -n "$KUBE_NAMESPACE" --config "$KUBECONFIG" deploy service "$CI_PROJECT_NAME" --from-image "$CI_REGISTRY_IMAGE" --wait
+Deployment started. Run "tm -n knative-4342902 describe service knative" to see the details
+Waiting for ready state.......
+Service domain: knative.knative-4342902.knative.info
+Job succeeded
+```
+
+The second to last line, labeled **Service domain** contains the URL for the deployment. Copy and paste the domain into your
+browser to see the app live.
+
+![knative app](img/knative-app.png) \ No newline at end of file
diff --git a/doc/user/project/container_registry.md b/doc/user/project/container_registry.md
index df850d4f68d..cac64fc0cb6 100644
--- a/doc/user/project/container_registry.md
+++ b/doc/user/project/container_registry.md
@@ -27,7 +27,7 @@ to enable it.
1. First, ask your system administrator to enable GitLab Container Registry
following the [administration documentation](../../administration/container_registry.md).
If you are using GitLab.com, this is enabled by default so you can start using
- the Registry immediately. Currently there is a soft (10GB) size restriction for
+ the Registry immediately. Currently there is a soft (10GB) size restriction for
registry on GitLab.com, as part of the [repository size limit](repository/index.html#repository-size).
1. Go to your [project's General settings](settings/index.md#sharing-and-permissions)
and enable the **Container Registry** feature on your project. For new
@@ -119,12 +119,17 @@ and [Using the GitLab Container Registry documentation](../../ci/docker/using_do
> Project Deploy Tokens were [introduced][ce-17894] in GitLab 10.7
If a project is private, credentials will need to be provided for authorization.
-The preferred way to do this, is either by using a [personal access tokens][pat] or a [project deploy token][pdt].
+There are two ways to do this:
+
+- By using a [personal access token](../profile/personal_access_tokens.md).
+- By using a [deploy token](../project/deploy_tokens/index.md).
+
The minimal scope needed for both of them is `read_registry`.
-Example of using a personal access token:
-```
-docker login registry.example.com -u <your_username> -p <your_access_token>
+Example of using a token:
+
+```sh
+docker login registry.example.com -u <username> -p <token>
```
## Troubleshooting the GitLab Container Registry
@@ -134,12 +139,12 @@ docker login registry.example.com -u <your_username> -p <your_access_token>
1. Check to make sure that the system clock on your Docker client and GitLab server have
been synchronized (e.g. via NTP).
-2. If you are using an S3-backed Registry, double check that the IAM
+1. If you are using an S3-backed Registry, double check that the IAM
permissions and the S3 credentials (including region) are correct. See [the
sample IAM policy](https://docs.docker.com/registry/storage-drivers/s3/)
for more details.
-3. Check the Registry logs (e.g. `/var/log/gitlab/registry/current`) and the GitLab production logs
+1. Check the Registry logs (e.g. `/var/log/gitlab/registry/current`) and the GitLab production logs
for errors (e.g. `/var/log/gitlab/gitlab-rails/production.log`). You may be able to find clues
there.
@@ -216,7 +221,7 @@ needs to trust the mitmproxy SSL certificates for this to work.
The following installation instructions assume you are running Ubuntu:
-1. Install mitmproxy (see http://docs.mitmproxy.org/en/stable/install.html)
+1. [Install mitmproxy](https://docs.mitmproxy.org/stable/overview-installation/).
1. Run `mitmproxy --port 9000` to generate its certificates.
Enter <kbd>CTRL</kbd>-<kbd>C</kbd> to quit.
1. Install the certificate from `~/.mitmproxy` to your system:
@@ -245,7 +250,7 @@ This will run mitmproxy on port `9000`. In another window, run:
curl --proxy http://localhost:9000 https://httpbin.org/status/200
```
-If everything is setup correctly, you will see information on the mitmproxy window and
+If everything is set up correctly, you will see information on the mitmproxy window and
no errors from the curl commands.
#### Running the Docker daemon with a proxy
@@ -293,4 +298,4 @@ Once the right permissions were set, the error will go away.
[docker-docs]: https://docs.docker.com/engine/userguide/intro/
[pat]: ../profile/personal_access_tokens.md
[pdt]: ../project/deploy_tokens/index.md
-[reconfigure]: ../../administration/restart_gitlab.md#omnibus-gitlab-reconfigure \ No newline at end of file
+[reconfigure]: ../../administration/restart_gitlab.md#omnibus-gitlab-reconfigure
diff --git a/doc/user/project/deploy_tokens/index.md b/doc/user/project/deploy_tokens/index.md
index 0b9b49f326f..7688508c6ac 100644
--- a/doc/user/project/deploy_tokens/index.md
+++ b/doc/user/project/deploy_tokens/index.md
@@ -9,12 +9,12 @@ at midnight UTC and that they can be only managed by [maintainers](https://docs.
## Creating a Deploy Token
-You can create as many deploy tokens as you like from the settings of your project:
+You can create as many deploy tokens as you like from the settings of your project:
1. Log in to your GitLab account.
1. Go to the project you want to create Deploy Tokens for.
-1. Go to **Settings** > **Repository**
-1. Click on "Expand" on **Deploy Tokens** section
+1. Go to **Settings** > **Repository**.
+1. Click on "Expand" on **Deploy Tokens** section.
1. Choose a name and optionally an expiry date for the token.
1. Choose the [desired scopes](#limiting-scopes-of-a-deploy-token).
1. Click on **Create deploy token**.
@@ -46,39 +46,46 @@ the following table.
To download a repository using a Deploy Token, you just need to:
1. Create a Deploy Token with `read_repository` as a scope.
-2. Take note of your `username` and `token`
-3. `git clone` the project using the Deploy Token:
+1. Take note of your `username` and `token`.
+1. `git clone` the project using the Deploy Token:
+ ```sh
+ git clone http://<username>:<deploy_token>@gitlab.example.com/tanuki/awesome_project.git
+ ```
-```bash
-git clone http://<username>:<deploy_token>@gitlab.example.com/tanuki/awesome_project.git
-```
-
-Just replace `<username>` and `<deploy_token>` with the proper values
+Replace `<username>` and `<deploy_token>` with the proper values.
-### Read container registry images
+### Read Container Registry images
To read the container registry images, you'll need to:
1. Create a Deploy Token with `read_registry` as a scope.
-2. Take note of your `username` and `token`
-3. Log in to GitLab’s Container Registry using the deploy token:
+1. Take note of your `username` and `token`.
+1. Log in to GitLab’s Container Registry using the deploy token:
-```
+```sh
docker login registry.example.com -u <username> -p <deploy_token>
```
-Just replace `<username>` and `<deploy_token>` with the proper values. Then you can simply
+Just replace `<username>` and `<deploy_token>` with the proper values. Then you can simply
pull images from your Container Registry.
### GitLab Deploy Token
> [Introduced][ce-18414] in GitLab 10.8.
-There's a special case when it comes to Deploy Tokens, if a user creates one
-named `gitlab-deploy-token`, the username and token of the Deploy Token will be
-automatically exposed to the CI/CD jobs as environment variables: `CI_DEPLOY_USER` and
-`CI_DEPLOY_PASSWORD`, respectively.
+There's a special case when it comes to Deploy Tokens. If a user creates one
+named `gitlab-deploy-token`, the username and token of the Deploy Token will be
+automatically exposed to the CI/CD jobs as environment variables: `CI_DEPLOY_USER` and
+`CI_DEPLOY_PASSWORD`, respectively. With the GitLab Deploy Token, the
+`read_registry` scope is implied.
+
+After you create the token, you can login to the Container Registry using
+those variables:
+
+```sh
+docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY
+```
[ce-17894]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/17894
[ce-11845]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/11845
diff --git a/doc/user/project/img/issue_board.png b/doc/user/project/img/issue_board.png
index 925b969eebe..b46b995d8bb 100644
--- a/doc/user/project/img/issue_board.png
+++ b/doc/user/project/img/issue_board.png
Binary files differ
diff --git a/doc/user/project/img/issue_board_milestone_lists.png b/doc/user/project/img/issue_board_milestone_lists.png
new file mode 100644
index 00000000000..91926f58f87
--- /dev/null
+++ b/doc/user/project/img/issue_board_milestone_lists.png
Binary files differ
diff --git a/doc/user/project/img/issue_board_summed_weights.png b/doc/user/project/img/issue_board_summed_weights.png
new file mode 100644
index 00000000000..2288d767d8c
--- /dev/null
+++ b/doc/user/project/img/issue_board_summed_weights.png
Binary files differ
diff --git a/doc/user/project/img/issue_boards_core.png b/doc/user/project/img/issue_boards_core.png
new file mode 100644
index 00000000000..8bc187482ad
--- /dev/null
+++ b/doc/user/project/img/issue_boards_core.png
Binary files differ
diff --git a/doc/user/project/img/issue_boards_premium.png b/doc/user/project/img/issue_boards_premium.png
new file mode 100644
index 00000000000..4e238ea6983
--- /dev/null
+++ b/doc/user/project/img/issue_boards_premium.png
Binary files differ
diff --git a/doc/user/project/img/koding_build-in-progress.png b/doc/user/project/img/koding_build-in-progress.png
deleted file mode 100644
index 118b97c07e1..00000000000
--- a/doc/user/project/img/koding_build-in-progress.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_build-logs.png b/doc/user/project/img/koding_build-logs.png
deleted file mode 100644
index b30c8375b20..00000000000
--- a/doc/user/project/img/koding_build-logs.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_build-success.png b/doc/user/project/img/koding_build-success.png
deleted file mode 100644
index 0f3b954abf5..00000000000
--- a/doc/user/project/img/koding_build-success.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_commit-koding.yml.png b/doc/user/project/img/koding_commit-koding.yml.png
deleted file mode 100644
index d921c73dc73..00000000000
--- a/doc/user/project/img/koding_commit-koding.yml.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_different-stack-on-mr-try.png b/doc/user/project/img/koding_different-stack-on-mr-try.png
deleted file mode 100644
index 10c7c51d2e6..00000000000
--- a/doc/user/project/img/koding_different-stack-on-mr-try.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_edit-on-ide.png b/doc/user/project/img/koding_edit-on-ide.png
deleted file mode 100644
index 25ca7694fe0..00000000000
--- a/doc/user/project/img/koding_edit-on-ide.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_enable-koding.png b/doc/user/project/img/koding_enable-koding.png
deleted file mode 100644
index 7e6c1735df2..00000000000
--- a/doc/user/project/img/koding_enable-koding.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_landing.png b/doc/user/project/img/koding_landing.png
deleted file mode 100644
index ac880376e09..00000000000
--- a/doc/user/project/img/koding_landing.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_open-gitlab-from-koding.png b/doc/user/project/img/koding_open-gitlab-from-koding.png
deleted file mode 100644
index 4235a72b36f..00000000000
--- a/doc/user/project/img/koding_open-gitlab-from-koding.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_run-in-ide.png b/doc/user/project/img/koding_run-in-ide.png
deleted file mode 100644
index fb5825a4010..00000000000
--- a/doc/user/project/img/koding_run-in-ide.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_run-mr-in-ide.png b/doc/user/project/img/koding_run-mr-in-ide.png
deleted file mode 100644
index cb1112c4034..00000000000
--- a/doc/user/project/img/koding_run-mr-in-ide.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_set-up-ide.png b/doc/user/project/img/koding_set-up-ide.png
deleted file mode 100644
index 033d41729a2..00000000000
--- a/doc/user/project/img/koding_set-up-ide.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_stack-import.png b/doc/user/project/img/koding_stack-import.png
deleted file mode 100644
index 483bfad7d6a..00000000000
--- a/doc/user/project/img/koding_stack-import.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/img/koding_start-build.png b/doc/user/project/img/koding_start-build.png
deleted file mode 100644
index c09a6d669f0..00000000000
--- a/doc/user/project/img/koding_start-build.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/import/clearcase.md b/doc/user/project/import/clearcase.md
index f23623ed485..89a9f7da852 100644
--- a/doc/user/project/import/clearcase.md
+++ b/doc/user/project/import/clearcase.md
@@ -1,6 +1,6 @@
# Migrating from ClearCase
-[ClearCase](https://www-03.ibm.com/software/products/en/clearcase/) is a set of
+[ClearCase](https://www.ibm.com/us-en/marketplace/rational-clearcase) is a set of
tools developed by IBM which also include a centralized version control system
similar to Git.
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index fcd6192e82f..42da2210fab 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -17,6 +17,7 @@ the [GitHub rake task](../../../administration/raketasks/github_import.md) to im
GitHub without the constraints of a Sidekiq worker.
The following aspects of a project are imported:
+
* Repository description (GitLab.com & 7.7+)
* Git repository data (GitLab.com & 7.7+)
* Issues (GitLab.com & 7.7+)
@@ -65,9 +66,9 @@ developer documentation.
Before you begin, ensure that any GitHub users who you want to map to GitLab users have either:
-1. A GitLab account that has logged in using the GitHub icon
+- A GitLab account that has logged in using the GitHub icon
\- or -
-2. A GitLab account with an email address that matches the [public email address](https://help.github.com/articles/setting-your-commit-email-address-on-github/) of the GitHub user
+- A GitLab account with an email address that matches the [public email address](https://help.github.com/articles/setting-your-commit-email-address-on-github/) of the GitHub user
User-matching attempts occur in that order, and if a user is not identified either way, the activity is associated with
the user account that is performing the import.
@@ -77,10 +78,10 @@ If you are using a self-hosted GitLab instance, this process requires that you h
[GitHub integration][gh-import].
1. From the top navigation bar, click **+** and select **New project**.
-2. Select the **Import project** tab and then select **GitHub**.
-3. Select the first button to **List your GitHub repositories**. You are redirected to a page on github.com to authorize the GitLab application.
-4. Click **Authorize gitlabhq**. You are redirected back to GitLab's Import page and all of your GitHub repositories are listed.
-5. Continue on to [selecting which repositories to import](#selecting-which-repositories-to-import).
+1. Select the **Import project** tab and then select **GitHub**.
+1. Select the first button to **List your GitHub repositories**. You are redirected to a page on github.com to authorize the GitLab application.
+1. Click **Authorize gitlabhq**. You are redirected back to GitLab's Import page and all of your GitHub repositories are listed.
+1. Continue on to [selecting which repositories to import](#selecting-which-repositories-to-import).
### Using a GitHub token
@@ -92,12 +93,12 @@ integration enabled, that should be the preferred method to import your reposito
If you are not using the GitHub integration, you can still perform an authorization with GitHub to grant GitLab access your repositories:
1. Go to https://github.com/settings/tokens/new
-2. Enter a token description.
-3. Select the repo scope.
-4. Click **Generate token**.
-5. Copy the token hash.
-6. Go back to GitLab and provide the token to the GitHub importer.
-7. Hit the **List Your GitHub Repositories** button and wait while GitLab reads your repositories' information.
+1. Enter a token description.
+1. Select the repo scope.
+1. Click **Generate token**.
+1. Copy the token hash.
+1. Go back to GitLab and provide the token to the GitHub importer.
+1. Hit the **List Your GitHub Repositories** button and wait while GitLab reads your repositories' information.
Once done, you'll be taken to the importer page to select the repositories to import.
### Selecting which repositories to import
@@ -107,10 +108,10 @@ your GitHub repositories are listed.
1. By default, the proposed repository namespaces match the names as they exist in GitHub, but based on your permissions,
you can choose to edit these names before you proceed to import any of them.
-2. Select the **Import** button next to any number of repositories, or select **Import all repositories**.
-3. The **Status** column shows the import status of each repository. You can choose to leave the page open and it will
+1. Select the **Import** button next to any number of repositories, or select **Import all repositories**.
+1. The **Status** column shows the import status of each repository. You can choose to leave the page open and it will
update in realtime or you can return to it later.
-4. Once a repository has been imported, click its GitLab path to open its GitLab URL.
+1. Once a repository has been imported, click its GitLab path to open its GitLab URL.
## Mirroring and pipeline status sharing
diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md
index 4ea35a30bbf..2f5efbe84d9 100644
--- a/doc/user/project/import/index.md
+++ b/doc/user/project/import/index.md
@@ -1,6 +1,7 @@
# Migrating projects to a GitLab instance
-1. [From Bitbucket.org](bitbucket.md)
+1. [From Bitbucket Cloud (aka bitbucket.org)](bitbucket.md)
+1. [From Bitbucket Server (aka Stash)](bitbucket_server.md)
1. [From ClearCase](clearcase.md)
1. [From CVS](cvs.md)
1. [From FogBugz](fogbugz.md)
diff --git a/doc/user/project/import/manifest.md b/doc/user/project/import/manifest.md
index 24bf6541a9d..baf410d9c9e 100644
--- a/doc/user/project/import/manifest.md
+++ b/doc/user/project/import/manifest.md
@@ -29,7 +29,7 @@ Below is a valid example of a manifest file:
```xml
<manifest>
- <remote review="https://android-review.googlesource.com/" />
+ <remote review="https://android.googlesource.com/" />
<project path="build/make" name="platform/build" />
<project path="build/blueprint" name="platform/build/blueprint" />
@@ -38,10 +38,10 @@ Below is a valid example of a manifest file:
As a result, the following projects will be created:
-| GitLab | Import URL |
-|---|---|
-| https://gitlab.com/YOUR_GROUP/build/make | https://android-review.googlesource.com/platform/build |
-| https://gitlab.com/YOUR_GROUP/build/blueprint | https://android-review.googlesource.com/platform/build/blueprint |
+| GitLab | Import URL |
+|:------------------------------------------------|:------------------------------------------------------------|
+| `https://gitlab.com/YOUR_GROUP/build/make` | <https://android.googlesource.com/platform/build> |
+| `https://gitlab.com/YOUR_GROUP/build/blueprint` | <https://android.googlesource.com/platform/build/blueprint> |
## Importing the repositories
diff --git a/doc/user/project/import/svn.md b/doc/user/project/import/svn.md
index 16bc5121027..a5923986292 100644
--- a/doc/user/project/import/svn.md
+++ b/doc/user/project/import/svn.md
@@ -29,7 +29,7 @@ directly in a filesystem level.
1. Install Oracle JRE 1.8 or newer. On Debian-based Linux distributions you can
follow [this article](http://www.webupd8.org/2012/09/install-oracle-java-8-in-ubuntu-via-ppa.html).
-1. Download SubGit from https://subgit.com/download/.
+1. Download SubGit from <https://subgit.com/download/>.
1. Unpack the downloaded SubGit zip archive to the `/opt` directory. The `subgit`
command will be available at `/opt/subgit-VERSION/bin/subgit`.
@@ -71,7 +71,7 @@ edit $GIT_REPO_PATH/subgit/config
```
For more information regarding the SubGit configuration options, refer to
-[SubGit's documentation](https://subgit.com/documentation.html) website.
+[SubGit's documentation](https://subgit.com/documentation/) website.
### Initial translation
@@ -97,7 +97,7 @@ subgit import $GIT_REPO_PATH
### SubGit licensing
Running SubGit in a mirror mode requires a
-[registration](https://subgit.com/pricing.html). Registration is free for open
+[registration](https://subgit.com/pricing/). Registration is free for open
source, academic and startup projects.
We're currently working on deeper GitLab/SubGit integration. You may track our
@@ -179,5 +179,6 @@ git push --tags origin
```
## Contribute to this guide
+
We welcome all contributions that would expand this guide with instructions on
how to migrate from SVN and other version control systems.
diff --git a/doc/user/project/integrations/bugzilla.md b/doc/user/project/integrations/bugzilla.md
index 671804035cc..040e80d529d 100644
--- a/doc/user/project/integrations/bugzilla.md
+++ b/doc/user/project/integrations/bugzilla.md
@@ -16,8 +16,9 @@ Once you have configured and enabled Bugzilla you'll see the Bugzilla link on th
## Referencing issues in Bugzilla
Issues in Bugzilla can be referenced in two alternative ways:
-1. `#<ID>` where `<ID>` is a number (example `#143`).
-2. `<PROJECT>-<ID>` where `<PROJECT>` starts with a capital letter which is
+
+- `#<ID>` where `<ID>` is a number (example `#143`).
+- `<PROJECT>-<ID>` where `<PROJECT>` starts with a capital letter which is
then followed by capital letters, numbers or underscores, and `<ID>` is
a number (example `API_32-143`).
diff --git a/doc/user/project/integrations/discord_notifications.md b/doc/user/project/integrations/discord_notifications.md
new file mode 100644
index 00000000000..cb98105e0c0
--- /dev/null
+++ b/doc/user/project/integrations/discord_notifications.md
@@ -0,0 +1,29 @@
+# Discord Notifications service
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22684) in GitLab 11.6.
+
+The Discord Notifications service sends event notifications from GitLab to the channel for which the webhook was created.
+
+To send GitLab event notifications to a Discord channel, create a webhook in Discord and configure it in GitLab.
+
+## Create webhook
+
+1. Open the Discord channel you want to receive GitLab event notifications.
+1. From the channel menu, select **Edit channel**.
+1. Click on **Webhooks** menu item.
+1. Click the **Create Webhook** button and fill in the name of the bot that will post the messages. Optionally, edit the avatar.
+1. Note the URL from the **WEBHOOK URL** field.
+1. Click the **Save** button.
+
+## Configure created webhook in GitLab
+
+With the webhook URL created in the Discord channel, you can set up the Discord Notifications service in GitLab.
+
+1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services) in your project's settings. That is, **Project > Settings > Integrations**.
+1. Select the **Discord Notifications** project service to configure it.
+1. Check the **Active** checkbox to turn on the service.
+1. Check the checkboxes corresponding to the GitLab events for which you want to send notifications to Discord.
+1. Paste the webhook URL that you copied from the create Discord webhook step.
+1. Configure the remaining options and click the **Save changes** button.
+
+The Discord channel you created the webhook for will now receive notification of the GitLab events that were configured.
diff --git a/doc/user/project/integrations/hangouts_chat.md b/doc/user/project/integrations/hangouts_chat.md
index 47525617d95..20a71da927c 100644
--- a/doc/user/project/integrations/hangouts_chat.md
+++ b/doc/user/project/integrations/hangouts_chat.md
@@ -15,7 +15,7 @@ See also [the Hangouts Chat documentation for configuring incoming webhooks](htt
## On GitLab
-When you have the **Webhook URL** for your Hangouts Chat room webhook, you can setup the GitLab service.
+When you have the **Webhook URL** for your Hangouts Chat room webhook, you can set up the GitLab service.
1. Navigate to the [Integrations page](project_services.md#accessing-the-project-services) in your project's settings, i.e. **Project > Settings > Integrations**.
1. Select the **Hangouts Chat** project service to configure it.
diff --git a/doc/user/project/integrations/img/jira_api_token.png b/doc/user/project/integrations/img/jira_api_token.png
new file mode 100644
index 00000000000..2c64f7bc44f
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_api_token.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_api_token_menu.png b/doc/user/project/integrations/img/jira_api_token_menu.png
new file mode 100644
index 00000000000..20655ba3c0e
--- /dev/null
+++ b/doc/user/project/integrations/img/jira_api_token_menu.png
Binary files differ
diff --git a/doc/user/project/integrations/img/jira_service_page.png b/doc/user/project/integrations/img/jira_service_page.png
index c75c11888a8..869d562ed5b 100644
--- a/doc/user/project/integrations/img/jira_service_page.png
+++ b/doc/user/project/integrations/img/jira_service_page.png
Binary files differ
diff --git a/doc/user/project/integrations/jira.md b/doc/user/project/integrations/jira.md
index b3821cf8391..bc4bba40e59 100644
--- a/doc/user/project/integrations/jira.md
+++ b/doc/user/project/integrations/jira.md
@@ -1,123 +1,84 @@
-# GitLab JIRA integration
+# GitLab Jira integration
-GitLab can be configured to interact with [JIRA], a project management platform.
+GitLab Issues are a powerful tool for discussing ideas and planning and tracking work.
+However, many organizations have been using Jira for these purposes and have
+extensive data and business processes built into it.
-Once your GitLab project is connected to JIRA, you can reference and close the
-issues in JIRA directly from GitLab.
+While you can always migrate content and process from Jira to GitLab Issues,
+you can also opt to continue using Jira and use it together with GitLab through
+our integration.
-For a use case, check out this article of [How and why to integrate GitLab with
-JIRA](https://www.programmableweb.com/news/how-and-why-to-integrate-gitlab-jira/how-to/2017/04/25).
+Once you integrate your GitLab project with your Jira instance, you can automatically
+detect and cross-reference activity between the GitLab project and any of your projects
+in Jira. This includes the ability to close or transition Jira issues when the work
+is completed in GitLab.
-## Configuration
-
-Each GitLab project can be configured to connect to a different JIRA instance. That
-means one GitLab project maps to _all_ JIRA projects in that JIRA instance once
-the configuration is set up. Therefore, you don't have to explicitly associate
-one GitLab project to any JIRA project. Once the configuration is set up, any JIRA
-projects in the JIRA instance are already mapped to the GitLab project.
-
-If you have one JIRA instance you can pre-fill the settings page with a default
-template, see the [Services Templates][services-templates] docs.
-
-Configuration happens via user name and password. Connecting to a JIRA server
-via CAS is not possible.
-
-In order to enable the JIRA service in GitLab, you need to first configure the
-project in JIRA and then enter the correct values in GitLab.
-
-### Configuring JIRA
-
-We need to create a user in JIRA which will have access to all projects that
-need to integrate with GitLab. Login to your JIRA instance as admin and under
-Administration go to User Management and create a new user.
-
-As an example, we'll create a user named `gitlab` and add it to `JIRA-developers`
-group.
-
-**It is important that the user `GitLab` has write-access to projects in JIRA**
-
-We have split this stage in steps so it is easier to follow.
-
----
-
-1. Login to your JIRA instance as an administrator and under **Administration**
- go to **User Management** to create a new user.
-
- ![JIRA user management link](img/jira_user_management_link.png)
-
- ---
+Here's how the integration responds when you take the following actions in GitLab:
-1. The next step is to create a new user (e.g., `gitlab`) who has write access
- to projects in JIRA. Enter the user's name and a _valid_ e-mail address
- since JIRA sends a verification e-mail to set-up the password.
- _**Note:** JIRA creates the username automatically by using the e-mail
- prefix. You can change it later if you want._
+- **Mention a Jira issue ID** in a commit message or MR (merge request).
+ - GitLab hyperlinks to the Jira issue.
+ - The Jira issue adds an issue link to the commit/MR in GitLab.
+ - The Jira issue adds a comment reflecting the comment made in GitLab, the comment author, and a link to the commit/MR in GitLab.
+- **Mention that a commit or MR 'closes', 'resolves', or 'fixes' a Jira issue ID**. When the commit is made on master or the change is merged to master:
+ - GitLab's merge request page displays a note that it "Closed" the Jira issue, with a link to the issue. (Note: Before the merge, an MR will display that it "Closes" the Jira issue.)
+ - The Jira issue shows the activity and the Jira issue is closed, or otherwise transitioned.
- ![JIRA create new user](img/jira_create_new_user.png)
+You can also use [Jira's Smart Commits](https://confluence.atlassian.com/fisheye/using-smart-commits-298976812.html)
+directly from GitLab, as covered in the article
+[How and why to integrate GitLab with Jira](https://www.programmableweb.com/news/how-and-why-to-integrate-gitlab-Jira/how-to/2017/04/25).
- ---
-
-1. Now, let's create a `gitlab-developers` group which will have write access
- to projects in JIRA. Go to the **Groups** tab and select **Create group**.
-
- ![JIRA create new user](img/jira_create_new_group.png)
-
- ---
-
- Give it an optional description and hit **Create group**.
-
- ![jira create new group](img/jira_create_new_group_name.png)
-
- ---
+## Configuration
-1. Give the newly-created group write access by going to
- **Application access âž” View configuration** and adding the `gitlab-developers`
- group to JIRA Core.
+Each GitLab project can be configured to connect to an entire Jira instance. That
+means one GitLab project can interact with _all_ Jira projects in that instance, once
+configured. Therefore, you will not have to explicitly associate
+a GitLab project with any single Jira project.
- ![JIRA group access](img/jira_group_access.png)
+If you have one Jira instance, you can pre-fill the settings page with a default
+template. See the [Services Templates][services-templates] docs.
- ---
+Configuration happens via user name and password. Connecting to a Jira server
+via CAS is not possible.
-1. Add the `gitlab` user to the `gitlab-developers` group by going to
- **Users âž” GitLab user âž” Add group** and selecting the `gitlab-developers`
- group from the dropdown menu. Notice that the group says _Access_ which is
- what we aim for.
+In order to enable the Jira service in GitLab, you need to first configure the
+project in Jira and then enter the correct values in GitLab.
- ![JIRA add user to group](img/jira_add_user_to_group.png)
+### Configuring Jira
- ---
+When connecting to **JIRA Server**, which supports basic authentication, a **username and password** are required. Check the link below and proceed to the next step:
+* [Setting up an user in JIRA server](jira_server_configuration.md)
-The JIRA configuration is over. Write down the new JIRA username and its
-password as they will be needed when configuring GitLab in the next section.
+When connecting to **JIRA Cloud**, which supports authentication via API token, an **email and API token**, are required. Check the link below and proceed to the next step:
+* [Setting up an user in JIRA cloud](jira_cloud_configuration.md)
### Configuring GitLab
> **Notes:**
-> - The currently supported JIRA versions are `v6.x` and `v7.x.`. GitLab 7.8 or
+> - The currently supported Jira versions are `v6.x` and `v7.x.`. GitLab 7.8 or
> higher is required.
-> - GitLab 8.14 introduced a new way to integrate with JIRA which greatly simplified
+> - GitLab 8.14 introduced a new way to integrate with Jira which greatly simplified
> the configuration options you have to enter. If you are using an older version,
> [follow this documentation][jira-repo-old-docs].
> - In order to support Oracle's Access Manager, GitLab will send additional cookies
> to enable Basic Auth. The cookie being added to each request is `OBBasicAuth` with
> a value of `fromDialog`.
-To enable JIRA integration in a project, navigate to the
+To enable Jira integration in a project, navigate to the
[Integrations page](project_services.md#accessing-the-project-services), click
-the **JIRA** service, and fill in the required details on the page as described
+the **Jira** service, and fill in the required details on the page as described
in the table below.
| Field | Description |
| ----- | ----------- |
-| `Web URL` | The base URL to the JIRA instance web interface which is being linked to this GitLab project. E.g., `https://jira.example.com`. |
-| `JIRA API URL` | The base URL to the JIRA instance API. Web URL value will be used if not set. E.g., `https://jira-api.example.com`. |
-| `Username` | The user name created in [configuring JIRA step](#configuring-jira). Using the email address will cause `401 unauthorized`. |
-| `Password` |The password of the user created in [configuring JIRA step](#configuring-jira). |
-| `Transition ID` | This is the ID of a transition that moves issues to the desired state. It is possible to insert transition ids separated by `,` or `;` which means the issue will be moved to each state after another using the given order. **Closing JIRA issues via commits or Merge Requests won't work if you don't set the ID correctly.** |
+| `Web URL` | The base URL to the Jira instance web interface which is being linked to this GitLab project. E.g., `https://Jira.example.com`. |
+| `Jira API URL` | The base URL to the Jira instance API. Web URL value will be used if not set. E.g., `https://jira-api.example.com`. |
+| `Username/Email` | Created when [configuring Jira step](#configuring-jira). Use `username` for **JIRA server** or `email` for **JIRA cloud**. |
+| `Password/API token` |Created in [configuring Jira step](#configuring-jira). Use `password` for **JIRA server** or `API token` for **JIRA cloud**. |
+| `Transition ID` | This is the ID of a transition that moves issues to the desired state. It is possible to insert transition ids separated by `,` or `;` which means the issue will be moved to each state after another using the given order. **Closing Jira issues via commits or Merge Requests won't work if you don't set the ID correctly.** |
-### Getting a transition ID
+### Obtaining a transition ID
-In the most recent JIRA UI, you can no longer see transition IDs in the workflow
+In the most recent Jira user interface, you can no longer see transition IDs in the workflow
administration UI. You can get the ID you need in either of the following ways:
1. By using the API, with a request like `https://yourcompany.atlassian.net/rest/api/2/issue/ISSUE-123/transitions`
@@ -129,25 +90,23 @@ Note that the transition ID may vary between workflows (e.g., bug vs. story),
even if the status you are changing to is the same.
After saving the configuration, your GitLab project will be able to interact
-with all JIRA projects in your JIRA instance and you'll see the JIRA link on the GitLab project pages that takes you to the appropriate JIRA project.
+with all Jira projects in your Jira instance and you'll see the Jira link on the GitLab project pages that takes you to the appropriate Jira project.
-![JIRA service page](img/jira_service_page.png)
+![Jira service page](img/jira_service_page.png)
----
+## Jira issues
-## JIRA issues
-
-By now you should have [configured JIRA](#configuring-jira) and enabled the
-[JIRA service in GitLab](#configuring-gitlab). If everything is set up correctly
-you should be able to reference and close JIRA issues by just mentioning their
+By now you should have [configured Jira](#configuring-jira) and enabled the
+[Jira service in GitLab](#configuring-gitlab). If everything is set up correctly
+you should be able to reference and close Jira issues by just mentioning their
ID in GitLab commits and merge requests.
-### Referencing JIRA Issues
+### Referencing Jira Issues
-When GitLab project has JIRA issue tracker configured and enabled, mentioning
-JIRA issue in GitLab will automatically add a comment in JIRA issue with the
+When GitLab project has Jira issue tracker configured and enabled, mentioning
+Jira issue in GitLab will automatically add a comment in Jira issue with the
link back to GitLab. This means that in comments in merge requests and commits
-referencing an issue, e.g., `PROJECT-7`, will add a comment in JIRA issue in the
+referencing an issue, e.g., `PROJECT-7`, will add a comment in Jira issue in the
format:
```
@@ -156,21 +115,19 @@ ENTITY_TITLE
```
* `USER` A user that mentioned the issue. This is the link to the user profile in GitLab.
-* `LINK_TO_THE_COMMENT` Link to the origin of mention with a name of the entity where JIRA issue was mentioned.
+* `LINK_TO_THE_COMMENT` Link to the origin of mention with a name of the entity where Jira issue was mentioned.
* `RESOURCE_NAME` Kind of resource which referenced the issue. Can be a commit or merge request.
* `PROJECT_NAME` GitLab project name.
* `ENTITY_TITLE` Merge request title or commit message first line.
-![example of mentioning or closing the JIRA issue](img/jira_issue_reference.png)
-
----
+![example of mentioning or closing the Jira issue](img/jira_issue_reference.png)
-### Closing JIRA Issues
+### Closing Jira Issues
-JIRA issues can be closed directly from GitLab by using trigger words in
+Jira issues can be closed directly from GitLab by using trigger words in
commits and merge requests. When a commit which contains the trigger word
-followed by the JIRA issue ID in the commit message is pushed, GitLab will
-add a comment in the mentioned JIRA issue and immediately close it (provided
+followed by the Jira issue ID in the commit message is pushed, GitLab will
+add a comment in the mentioned Jira issue and immediately close it (provided
the transition ID was set up correctly).
There are currently three trigger words, and you can use either one to achieve
@@ -180,66 +137,66 @@ the same goal:
- `Closes PROJECT-1`
- `Fixes PROJECT-1`
-where `PROJECT-1` is the issue ID of the JIRA project.
+where `PROJECT-1` is the issue ID of the Jira project.
> **Notes:**
> - Only commits and merges into the project's default branch (usually **master**) will
> close an issue in Jira. You can change your projects default branch under
> [project settings](img/jira_project_settings.png).
-> - The JIRA issue will not be transitioned if it has a resolution.
+> - The Jira issue will not be transitioned if it has a resolution.
-### JIRA issue closing example
+### Jira issue closing example
Let's consider the following example:
-1. For the project named `PROJECT` in JIRA, we implemented a new feature
+1. For the project named `PROJECT` in Jira, we implemented a new feature
and created a merge request in GitLab.
-1. This feature was requested in JIRA issue `PROJECT-7` and the merge request
+1. This feature was requested in Jira issue `PROJECT-7` and the merge request
in GitLab contains the improvement
1. In the merge request description we use the issue closing trigger
`Closes PROJECT-7`.
-1. Once the merge request is merged, the JIRA issue will be automatically closed
+1. Once the merge request is merged, the Jira issue will be automatically closed
with a comment and an associated link to the commit that resolved the issue.
----
-
-In the following screenshot you can see what the link references to the JIRA
+In the following screenshot you can see what the link references to the Jira
issue look like.
-![A Git commit that causes the JIRA issue to be closed](img/jira_merge_request_close.png)
-
----
+![A Git commit that causes the Jira issue to be closed](img/jira_merge_request_close.png)
-Once this merge request is merged, the JIRA issue will be automatically closed
+Once this merge request is merged, the Jira issue will be automatically closed
with a link to the commit that resolved the issue.
-![The GitLab integration closes JIRA issue](img/jira_service_close_issue.png)
+![The GitLab integration closes Jira issue](img/jira_service_close_issue.png)
----
-
-![The GitLab integration creates a comment and a link on JIRA issue.](img/jira_service_close_comment.png)
+![The GitLab integration creates a comment and a link on Jira issue.](img/jira_service_close_comment.png)
## Troubleshooting
-If things don't work as expected that's usually because you have configured
-incorrectly the JIRA-GitLab integration.
+If these features do not work as expected, it is likely due to a problem with the way the integration settings were configured.
+
+### GitLab is unable to comment on a Jira issue
+
+Make sure that the Jira user you set up for the integration has the
+correct access permission to post comments on a Jira issue and also to transition
+the issue, if you'd like GitLab to also be able to do so.
+Jira issue references and update comments will not work if the GitLab issue tracker is disabled.
-### GitLab is unable to comment on a ticket
+### GitLab is unable to close a Jira issue
-Make sure that the user you set up for GitLab to communicate with JIRA has the
-correct access permission to post comments on a ticket and to also transition
-the ticket, if you'd like GitLab to also take care of closing them.
-JIRA issue references and update comments will not work if the GitLab issue tracker is disabled.
+Make sure the `Transition ID` you set within the Jira settings matches the one
+your project needs to close an issue.
-### GitLab is unable to close a ticket
+Make sure that the Jira issue is not already marked as resolved; that is,
+the Jira issue resolution field is not set. (It should not be struck through in
+Jira lists.)
-Make sure the `Transition ID` you set within the JIRA settings matches the one
-your project needs to close a ticket.
+### CAPTCHA
-Make sure that the JIRA issue is not already marked as resolved, in other words that
-the JIRA issue resolution field is not set. (It should not be struck through in
-JIRA lists.)
+CAPTCHA may be triggered after several consecutive failed login attempts
+which may lead to a `401 unauthorized` error when testing your Jira integration.
+If CAPTCHA has been triggered, you will not be able to use Jira's REST API to
+authenticate with the Jira site. You will need to log in to your Jira instance
+and complete the CAPTCHA.
[services-templates]: services_templates.md
[jira-repo-old-docs]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-13-stable/doc/project_services/jira.md
-[jira]: https://www.atlassian.com/software/jira
diff --git a/doc/user/project/integrations/jira_cloud_configuration.md b/doc/user/project/integrations/jira_cloud_configuration.md
new file mode 100644
index 00000000000..cae66526175
--- /dev/null
+++ b/doc/user/project/integrations/jira_cloud_configuration.md
@@ -0,0 +1,18 @@
+# Creating an API token in JIRA cloud
+
+An API token is needed when integrating with JIRA Cloud, follow the steps
+below to create one:
+
+1. Log in to https://id.atlassian.com with your email.
+1. **Click API tokens**, then **Create API token**.
+
+![JIRA API token](img/jira_api_token_menu.png)
+
+![JIRA API token](img/jira_api_token.png)
+
+1. Make sure to write down your new API token as you will need it in the next [steps](jira.md#configuring-gitlab).
+
+NOTE: **Note**
+It is important that the user associated with this email has 'write' access to projects in JIRA.
+
+The JIRA configuration is complete. You are going to need this new created token and the email you used to log in when [configuring GitLab in the next section](jira.md#configuring-gitlab).
diff --git a/doc/user/project/integrations/jira_server_configuration.md b/doc/user/project/integrations/jira_server_configuration.md
new file mode 100644
index 00000000000..20036183187
--- /dev/null
+++ b/doc/user/project/integrations/jira_server_configuration.md
@@ -0,0 +1,53 @@
+# Creating a username and password for JIRA server
+
+We need to create a user in Jira which will have access to all projects that
+need to integrate with GitLab. Login to your Jira instance as admin and under
+*Administration*, go to *User Management* and create a new user.
+
+As an example, we'll create a user named `gitlab` and add it to the `Jira-developers`
+group.
+
+NOTE: **Note**
+It is important that the user `gitlab` has 'write' access to projects in Jira.
+
+We have split this stage in steps so it is easier to follow.
+
+1. Log in to your Jira instance as an administrator and under **Administration**
+ go to **User Management** to create a new user.
+
+ ![Jira user management link](img/jira_user_management_link.png)
+
+1. The next step is to create a new user (e.g., `gitlab`) who has write access
+ to projects in Jira. Enter the user's name and a _valid_ e-mail address
+ since Jira sends a verification e-mail to set up the password.
+ _**Note:** Jira creates the username automatically by using the e-mail
+ prefix. You can change it later, if needed. Our integration does not support SSO (such as SAML). You will need to create
+ an HTTP basic authentication password. You can do this by visiting the user
+ profile, looking up the username, and setting a password._
+
+ ![Jira create new user](img/jira_create_new_user.png)
+
+1. Create a `gitlab-developers` group which will have write access
+ to projects in Jira. Go to the **Groups** tab and select **Create group**.
+
+ ![Jira create new user](img/jira_create_new_group.png)
+
+ Give it an optional description and click **Create group**.
+
+ ![Jira create new group](img/jira_create_new_group_name.png)
+
+1. To give the newly-created group 'write' access, go to
+ **Application access > View configuration** and add the `gitlab-developers`
+ group to Jira Core.
+
+ ![Jira group access](img/jira_group_access.png)
+
+1. Add the `gitlab` user to the `gitlab-developers` group by going to
+ **Users > GitLab user > Add group** and selecting the `gitlab-developers`
+ group from the dropdown menu. Notice that the group says _Access_, which is
+ intended as part of this process.
+
+ ![Jira add user to group](img/jira_add_user_to_group.png)
+
+The Jira configuration is complete. Write down the new Jira username and its
+password as they will be needed when [configuring GitLab in the next section](jira.md#configuring-gitlab).
diff --git a/doc/user/project/integrations/mattermost.md b/doc/user/project/integrations/mattermost.md
index 3e77823a6aa..ed4367c1135 100644
--- a/doc/user/project/integrations/mattermost.md
+++ b/doc/user/project/integrations/mattermost.md
@@ -4,9 +4,9 @@
To enable Mattermost integration you must create an incoming webhook integration:
-1. Sign in to your Mattermost instance
-1. Visit incoming webhooks, that will be something like: https://mattermost.example/your_team_name/integrations/incoming_webhooks/add
-1. Choose a display name, description and channel, those can be overridden on GitLab
+1. Sign in to your Mattermost instance.
+1. Visit incoming webhooks, that will be something like: `https://mattermost.example.com/your_team_name/integrations/incoming_webhooks/add`.
+1. Choose a display name, description and channel, those can be overridden on GitLab.
1. Save it, copy the **Webhook URL**, we'll need this later for GitLab.
There might be some cases that Incoming Webhooks are blocked by admin, ask your mattermost admin to enable
@@ -38,7 +38,7 @@ At the end, fill in your Mattermost details:
| Field | Description |
| ----- | ----------- |
-| **Webhook** | The incoming webhook URL which you have to setup on Mattermost, it will be something like: http://mattermost.example/hooks/5xo… |
+| **Webhook** | The incoming webhook URL which you have to set up on Mattermost, it will be something like: http://mattermost.example/hooks/5xo… |
| **Username** | Optional username which can be on messages sent to Mattermost. Fill this in if you want to change the username of the bot. |
| **Notify only broken pipelines** | If you choose to enable the **Pipeline** event and you want to be only notified about failed pipelines. |
diff --git a/doc/user/project/integrations/mattermost_slash_commands.md b/doc/user/project/integrations/mattermost_slash_commands.md
index 488f61c77a3..e031dcad2c3 100644
--- a/doc/user/project/integrations/mattermost_slash_commands.md
+++ b/doc/user/project/integrations/mattermost_slash_commands.md
@@ -102,7 +102,7 @@ in a new slash command.
![Mattermost add command configuration](img/mattermost_slash_command_configuration.png)
-1. After you setup all the values, copy the token (we will use it below) and
+1. After you set up all the values, copy the token (we will use it below) and
click **Done**.
![Mattermost slash command token](img/mattermost_slash_command_token.png)
diff --git a/doc/user/project/integrations/microsoft_teams.md b/doc/user/project/integrations/microsoft_teams.md
index 140c6738a49..ca32689910c 100644
--- a/doc/user/project/integrations/microsoft_teams.md
+++ b/doc/user/project/integrations/microsoft_teams.md
@@ -25,7 +25,7 @@ At the end fill in your Microsoft Teams details:
| Field | Description |
| ----- | ----------- |
-| **Webhook** | The incoming webhook URL which you have to setup on Microsoft Teams. |
+| **Webhook** | The incoming webhook URL which you have to set up on Microsoft Teams. |
| **Notify only broken pipelines** | If you choose to enable the **Pipeline** event and you want to be only notified about failed pipelines. |
After you are all done, click **Save changes** for the changes to take effect.
diff --git a/doc/user/project/integrations/mock_ci.md b/doc/user/project/integrations/mock_ci.md
index 6aefe5dbded..8b1908c46fe 100644
--- a/doc/user/project/integrations/mock_ci.md
+++ b/doc/user/project/integrations/mock_ci.md
@@ -2,7 +2,7 @@
**NB: This service is only listed if you are in a development environment!**
-To setup the mock CI service server, respond to the following endpoints
+To set up the mock CI service server, respond to the following endpoints
- `commit_status`: `#{project.namespace.path}/#{project.path}/status/#{sha}.json`
- Have your service return `200 { status: ['failed'|'canceled'|'running'|'pending'|'success'|'success_with_warnings'|'skipped'|'not_found'] }`
diff --git a/doc/user/project/integrations/project_services.md b/doc/user/project/integrations/project_services.md
index efb0381d7aa..be45ce46dfd 100644
--- a/doc/user/project/integrations/project_services.md
+++ b/doc/user/project/integrations/project_services.md
@@ -30,6 +30,7 @@ Click on the service links to see further configuration instructions and details
| [Bugzilla](bugzilla.md) | Bugzilla issue tracker |
| Campfire | Simple web-based real-time group chat |
| Custom Issue Tracker | Custom issue tracker |
+| [Discord Notifications](discord_notifications.md) | Receive event notifications in Discord |
| Drone CI | Continuous Integration platform built on Docker, written in Go |
| [Emails on push](emails_on_push.md) | Email the commits and diff of each push to a list of recipients |
| External Wiki | Replaces the link to the internal wiki with a link to an external wiki |
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index f687027e8c8..7d0e567cae7 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -8,7 +8,7 @@ within the GitLab interface.
![Environment Dashboard](img/prometheus_dashboard.png)
-There are two ways to setup Prometheus integration, depending on where your apps are running:
+There are two ways to set up Prometheus integration, depending on where your apps are running:
* For deployments on Kubernetes, GitLab can automatically [deploy and manage Prometheus](#managed-prometheus-on-kubernetes)
* For other deployment targets, simply [specify the Prometheus server](#manual-configuration-of-prometheus).
@@ -56,7 +56,7 @@ The [NGINX Ingress](../clusters/index.md#installing-applications) that is deploy
Integration with Prometheus requires the following:
1. GitLab 9.0 or higher
-1. Prometheus must be configured to collect one of the [supported metrics](prometheus_library/metrics.md)
+1. Prometheus must be configured to collect one of the [supported metrics](prometheus_library/index.md)
1. Each metric must be have a label to indicate the environment
1. GitLab must have network connectivity to the Prometheus server
@@ -65,7 +65,7 @@ Integration with Prometheus requires the following:
Installing and configuring Prometheus to monitor applications is fairly straight forward.
1. [Install Prometheus](https://prometheus.io/docs/introduction/install/)
-1. Set up one of the [supported monitoring targets](prometheus_library/metrics.md)
+1. Set up one of the [supported monitoring targets](prometheus_library/index.md)
1. Configure the Prometheus server to [collect their metrics](https://prometheus.io/docs/operating/configuration/#scrape_config)
#### Configuration in GitLab
diff --git a/doc/user/project/integrations/prometheus_library/cloudwatch.md b/doc/user/project/integrations/prometheus_library/cloudwatch.md
index bf6c0dc0e7e..66f1b587070 100644
--- a/doc/user/project/integrations/prometheus_library/cloudwatch.md
+++ b/doc/user/project/integrations/prometheus_library/cloudwatch.md
@@ -27,4 +27,4 @@ A sample Cloudwatch Exporter configuration file, configured for basic AWS ELB mo
## Specifying the Environment label
In order to isolate and only display relevant metrics for a given environment
-however, GitLab needs a method to detect which labels are associated. To do this, GitLab will [look for an `environment` label](metrics.md#identifying-environments).
+however, GitLab needs a method to detect which labels are associated. To do this, GitLab will [look for an `environment` label](index.md#identifying-environments).
diff --git a/doc/user/project/integrations/prometheus_library/haproxy.md b/doc/user/project/integrations/prometheus_library/haproxy.md
index cd398f7c0fd..abb0c01ad18 100644
--- a/doc/user/project/integrations/prometheus_library/haproxy.md
+++ b/doc/user/project/integrations/prometheus_library/haproxy.md
@@ -21,4 +21,4 @@ To get started with NGINX monitoring, you should install and configure the [HAPr
## Specifying the Environment label
In order to isolate and only display relevant metrics for a given environment
-however, GitLab needs a method to detect which labels are associated. To do this, GitLab will [look for an `environment` label](metrics.md#identifying-environments).
+however, GitLab needs a method to detect which labels are associated. To do this, GitLab will [look for an `environment` label](index.md#identifying-environments).
diff --git a/doc/user/project/integrations/prometheus_library/index.md b/doc/user/project/integrations/prometheus_library/index.md
new file mode 100644
index 00000000000..9b9b4f6c8ca
--- /dev/null
+++ b/doc/user/project/integrations/prometheus_library/index.md
@@ -0,0 +1,33 @@
+# Prometheus Metrics library
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8935) in GitLab 9.0.
+
+GitLab offers automatic detection of select [Prometheus exporters](https://prometheus.io/docs/instrumenting/exporters/).
+
+## Exporters
+
+Currently supported exporters are:
+
+- [Kubernetes](kubernetes.md)
+- [NGINX](nginx.md)
+- [NGINX Ingress Controller](nginx_ingress.md)
+- [HAProxy](haproxy.md)
+- [Amazon Cloud Watch](cloudwatch.md)
+
+We have tried to surface the most important metrics for each exporter, and will
+be continuing to add support for additional exporters in future releases. If you
+would like to add support for other official exporters, contributions are welcome.
+
+## Identifying Environments
+
+GitLab retrieves performance data from the configured Prometheus server, and
+attempts to identifying the presence of known metrics. Once identified, GitLab
+then needs to be able to map the data to a particular environment.
+
+In order to isolate and only display relevant metrics for a given environment,
+GitLab needs a method to detect which labels are associated. To do that,
+GitLab uses the defined queries and fills in the environment specific variables.
+Typically this involves looking for the
+[`$CI_ENVIRONMENT_SLUG`](../../../../ci/variables/README.md#predefined-variables-environment-variables),
+but may also include other information such as the project's Kubernetes namespace.
+Each search query is defined in the [exporter specific documentation](#exporters).
diff --git a/doc/user/project/integrations/prometheus_library/metrics.md b/doc/user/project/integrations/prometheus_library/metrics.md
index ec16902fcc8..37a5388d2fc 100644
--- a/doc/user/project/integrations/prometheus_library/metrics.md
+++ b/doc/user/project/integrations/prometheus_library/metrics.md
@@ -1,19 +1 @@
-# Prometheus Metrics library
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8935) in GitLab 9.0
-
-GitLab offers automatic detection of select [Prometheus exporters](https://prometheus.io/docs/instrumenting/exporters/). Currently supported exporters are:
-* [Kubernetes](kubernetes.md)
-* [NGINX](nginx.md)
-* [NGINX Ingress Controller](nginx_ingress.md)
-* [HAProxy](haproxy.md)
-* [Amazon Cloud Watch](cloudwatch.md)
-
-We have tried to surface the most important metrics for each exporter, and will be continuing to add support for additional exporters in future releases. If you would like to add support for other official exporters, [contributions](#adding-to-the-library) are welcome.
-
-## Identifying Environments
-
-GitLab retrieves performance data from the configured Prometheus server, and attempts to identifying the presence of known metrics. Once identified, GitLab then needs to be able to map the data to a particular environment.
-
-In order to isolate and only display relevant metrics for a given environment, GitLab needs a method to detect which labels are associated. To do that,
-GitLab uses the defined queries and fills in the environment specific variables. Typically this involves looking for the [$CI_ENVIRONMENT_SLUG](../../../../ci/variables/README.md#predefined-variables-environment-variables), but may also include other information such as the project's Kubernetes namespace. Each search query is defined in the [exporter specific documentation](#prometheus-metrics-library).
+This document was moved to [another location](index.md).
diff --git a/doc/user/project/integrations/prometheus_library/nginx.md b/doc/user/project/integrations/prometheus_library/nginx.md
index 557487e1a75..c4fea178ab5 100644
--- a/doc/user/project/integrations/prometheus_library/nginx.md
+++ b/doc/user/project/integrations/prometheus_library/nginx.md
@@ -27,4 +27,4 @@ If you are using NGINX as your Kubernetes ingress, GitLab will [automatically de
## Specifying the Environment label
In order to isolate and only display relevant metrics for a given environment
-however, GitLab needs a method to detect which labels are associated. To do this, GitLab will [look for an `environment` label](metrics.md#identifying-environments).
+however, GitLab needs a method to detect which labels are associated. To do this, GitLab will [look for an `environment` label](index.md#identifying-environments).
diff --git a/doc/user/project/integrations/prometheus_library/nginx_ingress.md b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
index a1db79538a4..40ac855c74f 100644
--- a/doc/user/project/integrations/prometheus_library/nginx_ingress.md
+++ b/doc/user/project/integrations/prometheus_library/nginx_ingress.md
@@ -1,8 +1,8 @@
# Monitoring NGINX Ingress Controller
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/13438) in GitLab 9.5
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/13438) in GitLab 9.5.
-GitLab has support for automatically detecting and monitoring the Kubernetes NGINX ingress controller. This is provided by leveraging the built in Prometheus metrics included in [version 0.9.0](https://github.com/kubernetes/ingress/blob/master/controllers/nginx/Changelog.md#09-beta1) and above of the ingress.
+GitLab has support for automatically detecting and monitoring the Kubernetes NGINX ingress controller. This is provided by leveraging the built in Prometheus metrics included in [version 0.9.0](https://github.com/kubernetes/ingress-nginx/blob/master/Changelog.md#09-beta1) and above of the ingress.
## Requirements
@@ -38,7 +38,7 @@ When used in conjunction with the GitLab deployed Prometheus service, response m
### Manually setting up NGINX Ingress for Prometheus monitoring
-Version 0.9.0 and above of [NGINX ingress](https://github.com/kubernetes/ingress/tree/master/controllers/nginx) have built-in support for exporting Prometheus metrics. To enable, a ConfigMap setting must be passed: `enable-vts-status: "true"`. Once enabled, a Prometheus metrics endpoint will start running on port 10254.
+Version 0.9.0 and above of [NGINX ingress](https://github.com/kubernetes/ingress-nginx) have built-in support for exporting Prometheus metrics. To enable, a ConfigMap setting must be passed: `enable-vts-status: "true"`. Once enabled, a Prometheus metrics endpoint will start running on port 10254.
Next, the ingress needs to be annotated for Prometheus monitoring. Two new annotations need to be added:
diff --git a/doc/user/project/integrations/redmine.md b/doc/user/project/integrations/redmine.md
index de2cf6d4647..76a2617125e 100644
--- a/doc/user/project/integrations/redmine.md
+++ b/doc/user/project/integrations/redmine.md
@@ -18,15 +18,16 @@ in the table below.
![Redmine configuration](img/redmine_configuration.png)
-2. To disable the internal issue tracking system in a project, navigate to the General page, expand [Permissions](../settings/index.md#sharing-and-permissions), and slide the Issues switch invalid.
+1. To disable the internal issue tracking system in a project, navigate to the General page, expand [Permissions](../settings/index.md#sharing-and-permissions), and slide the Issues switch invalid.
![Issue configuration](img/issue_configuration.png)
## Referencing issues in Redmine
Issues in Redmine can be referenced in two alternative ways:
-1. `#<ID>` where `<ID>` is a number (example `#143`)
-2. `<PROJECT>-<ID>` where `<PROJECT>` starts with a capital letter which is
+
+- `#<ID>` where `<ID>` is a number (example `#143`).
+- `<PROJECT>-<ID>` where `<PROJECT>` starts with a capital letter which is
then followed by capital letters, numbers or underscores, and `<ID>` is
a number (example `API_32-143`).
diff --git a/doc/user/project/integrations/services_templates.md b/doc/user/project/integrations/services_templates.md
index 5b04d7d88b8..a0bf31c526f 100644
--- a/doc/user/project/integrations/services_templates.md
+++ b/doc/user/project/integrations/services_templates.md
@@ -1,8 +1,10 @@
# Services templates
A GitLab administrator can add a service template that sets a default for each
-project. After a service template is enabled, it will be applied to new
-projects only and its details will be pre-filled on the project's Service page.
+project. After a service template is enabled, it will be applied to **all**
+projects that don't have it already enabled and its details will be pre-filled
+on the project's Service page. By disabling the template, it will be disabled
+for new projects only.
## Enable a service template
diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md
index e22f8e976be..4d1d95da6f0 100644
--- a/doc/user/project/integrations/webhooks.md
+++ b/doc/user/project/integrations/webhooks.md
@@ -7,7 +7,7 @@
> - the `project.http_url` key is deprecated in favor of the `project.git_http_url` key
>
> **Note:**
-> Starting from GitLab 11.1, the logs of web hooks are automatically removed after
+> Starting from GitLab 11.1, the logs of webhooks are automatically removed after
> one month.
>
> **Note:**
@@ -73,8 +73,8 @@ Below are described the supported events.
Triggered when you push to the repository except when pushing tags.
-> **Note:** When more than 20 commits are pushed at once, the `commits` web hook
- attribute will only contain the first 20 for performance reasons. Loading
+> **Note:** When more than 20 commits are pushed at once, the `commits` webhook
+ attribute will only contain the first 20 for performance reasons. Loading
detailed commit data is expensive. Note that despite only 20 commits being
present in the `commits` attribute, the `total_commits_count` attribute will
contain the actual total.
@@ -338,10 +338,10 @@ payload will also include information about the target of the comment. For examp
a comment on an issue will include the specific issue information under the `issue` key.
Valid target types:
-1. `commit`
-2. `merge_request`
-3. `issue`
-4. `snippet`
+- `commit`
+- `merge_request`
+- `issue`
+- `snippet`
#### Comment on commit
@@ -943,7 +943,13 @@ X-Gitlab-Event: Pipeline Hook
],
"created_at": "2016-08-12 15:23:28 UTC",
"finished_at": "2016-08-12 15:26:29 UTC",
- "duration": 63
+ "duration": 63,
+ "variables": [
+ {
+ "key": "NESTOR_PROD_ENVIRONMENT",
+ "value": "us-west-1"
+ }
+ ]
},
"user":{
"name": "Administrator",
@@ -1151,10 +1157,11 @@ its description:
```
It will appear in the webhook body as the below (assuming that GitLab is
-installed at gitlab.example.com):
+installed at gitlab.example.com, and the project is at
+example-group/example-project):
```markdown
-![image](https://gitlab.example.com/uploads/$sha/image.png)
+![image](https://gitlab.example.com/example-group/example-project/uploads/$sha/image.png)
```
This will not rewrite URLs that already are pointing to HTTP, HTTPS, or
@@ -1170,7 +1177,7 @@ You can trigger the webhook manually. Sample data from the project will be used.
## Troubleshoot webhooks
-Gitlab stores each perform of the webhook.
+GitLab stores each perform of the webhook.
You can find records for last 2 days in "Recent Deliveries" section on the edit page of each webhook.
![Recent deliveries](img/webhook_logs.png)
@@ -1184,7 +1191,7 @@ From this page, you can repeat delivery with the same data by clicking `Resend R
> **Note:** If URL or secret token of the webhook were updated, data will be delivered to the new address.
-### Receiving duplicate or multiple web hook requests triggered by one event
+### Receiving duplicate or multiple webhook requests triggered by one event
When GitLab sends a webhook it expects a response in 10 seconds (set default value). If it does not receive one, it'll retry the webhook.
If the endpoint doesn't send its HTTP response within those 10 seconds, GitLab may decide the hook failed and retry it.
diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md
index 7c6d547d626..9e2434c02ec 100644
--- a/doc/user/project/issue_board.md
+++ b/doc/user/project/issue_board.md
@@ -2,13 +2,44 @@
> [Introduced][ce-5554] in [GitLab 8.11](https://about.gitlab.com/2016/08/22/gitlab-8-11-released/#issue-board).
+## Overview
+
The GitLab Issue Board is a software project management tool used to plan,
organize, and visualize a workflow for a feature or product release.
It can be used as a [Kanban] or a [Scrum] board.
-![GitLab Issue Board](img/issue_board.png)
+It provides perfect pairing between issue tracking and project management,
+keeping everything in the same place, so that you don't need to jump
+between different platforms to organize your workflow.
-## Overview
+With GitLab Issue Boards, you organize your issues in lists that correspond to
+their assigned labels, visualizing issues designed as cards throughout that lists.
+
+You define your process and GitLab organizes it for you. You add your labels
+then create the corresponding list to pull in your existing issues. When
+you're ready, you can drag and drop your issue cards from one step to the next.
+
+![GitLab Issue Board - Core](img/issue_boards_core.png)
+
+**<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+Watch a [video presentation](https://youtu.be/UWsJ8tkHAa8) of
+Issue Boards** (version introduced in GitLab 8.11 - August 2016).
+
+### Advanced features of Issue Boards
+
+With [GitLab Starter](https://about.gitlab.com/pricing/), you can create
+[multiple issue boards](#multiple-issue-boards) for a given project. **[STARTER]**
+
+With [GitLab Premium](https://about.gitlab.com/pricing/), you can also create multiple
+issue boards for your groups, and add lists for [assignees](#assignee-lists) and
+[milestones](#milestone-lists). **[PREMIUM]**
+
+Check all the [advanced features of Issue Boards](#gitlab-enterprise-features-for-issue-boards)
+below.
+
+![GitLab Issue Boards - Premium](img/issue_boards_premium.png)
+
+## How it works
The Issue Board builds on GitLab's existing
[issue tracking functionality](issues/index.md#issue-tracker) and
@@ -28,15 +59,12 @@ and deploy from one single platform. Issue Boards help you to visualize
and manage the entire process _in_ GitLab.
With [Multiple Issue Boards](#use-cases-for-multiple-issue-boards), available
-only in [GitLab Enterprise Edition](#features-per-tier),
+only in [different tiers of GitLab Enterprise Edition](#gitlab-enterprise-features-for-issue-boards),
you go even further, as you can not only keep yourself and your project
organized from a broader perspective with one Issue Board per project,
but also allow your team members to organize their own workflow by creating
multiple Issue Boards within the same project.
-For a visual overview, see our [Issue Board feature page](https://about.gitlab.com/features/issueboard/)
-on about.gitlab.com or our [video introduction to Issue Boards](https://www.youtube.com/watch?v=UWsJ8tkHAa8).
-
## Use cases
There are many ways to use GitLab Issue Boards tailored to your own preferred workflow.
@@ -111,11 +139,6 @@ to improve their workflow with multiple boards.
Create lists for each of your team members and quickly drag-and-drop issues onto each team member.
-## Permissions
-
-[Developers and up](../permissions.md) can use all the functionality of the
-Issue Board, that is, create or delete lists and drag issues from one list to another.
-
## Issue Board terminology
- **Issue Board** - Each board represents a unique view for your issues. It can have multiple lists with each list consisting of issues represented by cards.
@@ -126,6 +149,142 @@ Issue Board, that is, create or delete lists and drag issues from one list to an
- **Closed** (default): shows all closed issues. Always appears as the rightmost list.
- **Card** - A box in the list that represents an individual issue. The information you can see on a card consists of the issue number, the issue title, the assignee, and the labels associated with the issue. You can drag cards from one list to another to change their label or assignee from that of the source list to that of the destination list.
+## Permissions
+
+[Developers and up](../permissions.md) can use all the functionality of the
+Issue Board, that is, create or delete lists and drag issues from one list to another.
+
+## GitLab Enterprise features for Issue Boards
+
+GitLab Issue Boards are available on GitLab Core and GitLab.com Free, but some
+advanced functionalities are only present in higher tiers: GitLab.com Bronze,
+Silver, or Gold, or GitLab self-managed Starter, Premium, and Ultimate, as described
+on the following sections.
+
+For a collection of [features per tier](#summary-of-features-per-tier), check the summary below.
+
+### Multiple Issue Boards **[STARTER]**
+
+> Introduced in [GitLab Enterprise Edition 8.13](https://about.gitlab.com/2016/10/22/gitlab-8-13-released/#multiple-issue-boards-ee).
+
+Multiple Issue Boards, as the name suggests, allow for more than one Issue Board
+for a given project or group. This is great for large projects with more than one team
+or in situations where a repository is used to host the code of multiple
+products.
+
+Clicking on the current board name in the upper left corner will reveal a
+menu from where you can create another Issue Board and rename or delete the
+existing one.
+
+When you're revisiting an issue board in a project or group with multiple boards,
+GitLab will automatically load the last board you visited.
+
+NOTE: **Note:**
+The Multiple Issue Boards feature is available for
+**projects in GitLab Starter Edition** and for **groups in GitLab Premium Edition**.
+
+![Multiple Issue Boards](img/issue_boards_multiple.png)
+
+### Configurable Issue Boards **[STARTER]**
+
+> Introduced in [GitLab Starter Edition 10.2](https://about.gitlab.com/2017/11/22/gitlab-10-2-released/#issue-boards-configuration).
+
+An Issue Board can be associated with a GitLab [Milestone](milestones/index.md#milestones),
+[Labels](labels.md), Assignee and Weight
+which will automatically filter the Board issues according to these fields.
+This allows you to create unique boards according to your team's need.
+
+![Create scoped board](img/issue_board_creation.png)
+
+You can define the scope of your board when creating it or by clicking on the "Edit board" button. Once a milestone, assignee or weight is assigned to an Issue Board, you will no longer be able to filter
+through these in the search bar. In order to do that, you need to remove the desired scope (e.g. milestone, assignee or weight) from the Issue Board.
+
+![Edit board configuration](img/issue_board_edit_button.png)
+
+If you don't have editing permission in a board, you're still able to see the configuration by clicking on "View scope".
+
+![Viewing board configuration](img/issue_board_view_scope.png)
+
+### Focus mode **[STARTER]**
+
+> Introduced in [GitLab Starter 9.1](https://about.gitlab.com/2017/04/22/gitlab-9-1-released/#issue-boards-focus-mode-ees-eep).
+
+Click the button at the top right to toggle focus mode on and off. In focus mode, the navigation UI is hidden, allowing you to focus on issues in the board.
+
+![Board focus mode](img/issue_board_focus_mode.gif)
+
+### Sum of Issue Weights **[STARTER]**
+
+The top of each list indicates the sum of issue weights for the issues that
+belong to that list. This is useful when using boards for capacity allocation,
+especially in combination with [assignee lists](#assignee-lists).
+
+![Issue Board summed weights](img/issue_board_summed_weights.png)
+
+### Group Issue Boards **[PREMIUM]**
+
+> Introduced in [GitLab Premium 10.0](https://about.gitlab.com/2017/09/22/gitlab-10-0-released/#group-issue-boards).
+
+Accessible at the group navigation level, a group issue board offers the same features as a project-level board,
+but it can display issues from all projects in that
+group and its descendant subgroups. Similarly, you can only filter by group labels for these
+boards. When updating milestones and labels for an issue through the sidebar update mechanism, again only
+group-level objects are available.
+
+NOTE: **Note:**
+Multiple group issue boards were originally introduced in [GitLab 10.0 Premium](https://about.gitlab.com/2017/09/22/gitlab-10-0-released/#group-issue-boards) and
+one group issue board per group was made available in GitLab 10.6 Core.
+
+![Group issue board](img/group_issue_board.png)
+
+### Assignee lists **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5784) in GitLab 11.0 Premium.
+
+Like a regular list that shows all issues that have the list label, you can add
+an assignee list that shows all issues assigned to the given user.
+You can have a board with both label lists and assignee lists. To add an
+assignee list:
+
+1. Click **Add list**.
+1. Select the **Assignee list** tab.
+1. Search and click on the user you want to add as an assignee.
+
+Now that the assignee list is added, you can assign or unassign issues to that user
+by [dragging issues](#dragging-issues-between-lists) to and/or from an assignee list.
+To remove an assignee list, just as with a label list, click the trash icon.
+
+![Assignee lists](img/issue_board_assignee_lists.png)
+
+### Milestone lists **[PREMIUM]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/6469) in GitLab 11.2 Premium.
+
+As of 11.2, you're also able to create lists of a milestone. As the name states,
+these are lists that filter issues by the assigned milestone, giving you more
+freedom and visibility on the Issue Board. To do so:
+
+1. Click **Add list**.
+1. Select the **Milestone** tab.
+1. Search and click on the milestone.
+
+Similar to the assignee lists, you're now able to [drag issues](#dragging-issues-between-lists)
+to and/or from a milestone list to manipulate the milestone of the dragged issues.
+As on another list types, click on the trash icon to remove it.
+
+![Milestone lists](img/issue_board_milestone_lists.png)
+
+### Summary of features per tier
+
+Different issue board features are available in different [GitLab tiers](https://about.gitlab.com/pricing/), as shown in the following table:
+
+| Tier | Number of Project Issue Boards | Number of Group Issue Boards | Configurable Issue Boards | Assignee Lists |
+|----------|--------------------------------|------------------------------|---------------------------|----------------|
+| Core / Free | 1 | 1 | No | No |
+| Starter / Bronze | Multiple | 1 | Yes | No |
+| Premium / Silver | Multiple | Multiple | Yes | Yes |
+| Ultimate / Gold | Multiple | Multiple | Yes | Yes |
+
## Actions you can take on an Issue Board
- [Create a new list](#creating-a-new-list).
@@ -142,7 +301,7 @@ Issue Board, that is, create or delete lists and drag issues from one list to an
If you are not able to perform one or more of the things above, make sure you
have the right [permissions](#permissions).
-## First time using the Issue Board
+### First time using the Issue Board
The first time you navigate to your Issue Board, you will be presented with
a default list (**Done**) and a welcoming message that gives
@@ -157,7 +316,7 @@ which means the system has no way of populating them automatically. That's of
course if the predefined labels don't already exist. If any of them does exist,
the list will be created and filled with the issues that have that label.
-## Creating a new list
+### Creating a new list
Create a new list by clicking on the **Add list** button at the upper
right corner of the Issue Board.
@@ -172,7 +331,7 @@ To create a list for a label that doesn't yet exist, simply create the label by
choosing **Create new label**. The label will be created on-the-fly and it will
be immediately added to the dropdown. You can now choose it to create a list.
-## Deleting a list
+### Deleting a list
To delete a list from the Issue Board use the small trash icon that is present
in the list's heading. A confirmation dialog will appear for you to confirm.
@@ -180,7 +339,7 @@ in the list's heading. A confirmation dialog will appear for you to confirm.
Deleting a list doesn't have any effect in issues and labels, it's just the
list view that is removed. You can always add it back later if you need.
-## Adding issues to a list
+### Adding issues to a list
You can add issues to a list by clicking the **Add issues** button that is
present in the upper right corner of the Issue Board. This will open up a modal
@@ -192,7 +351,7 @@ the list by filtering by author, assignee, milestone and label.
![Bulk adding issues to lists](img/issue_boards_add_issues_modal.png)
-## Removing an issue from a list
+### Removing an issue from a list
Removing an issue from a list can be done by clicking on the issue card and then
clicking the **Remove from board** button in the sidebar. Under the hood, the
@@ -201,7 +360,7 @@ board itself.
![Remove issue from list](img/issue_boards_remove_issue.png)
-## Issue ordering in a list
+### Issue ordering in a list
When visiting a board, issues appear ordered in any list. You are able to change
that order simply by dragging and dropping the issues. The changed order will be saved
@@ -224,7 +383,7 @@ a given board inside your GitLab instance, any time those two issues are subsequ
loaded in any board in the same instance (could be a different project board or a different group board, for example),
that ordering will be maintained.
-## Filtering issues
+### Filtering issues
You should be able to use the filters on top of your Issue Board to show only
the results you want. This is similar to the filtering used in the issue tracker
@@ -232,7 +391,7 @@ since the metadata from the issues and labels are re-used in the Issue Board.
You can filter by author, assignee, milestone and label.
-## Creating workflows
+### Creating workflows
By reordering your lists, you can create workflows. As lists in Issue Boards are
based on labels, it works out of the box with your existing issues. So if you've
@@ -267,89 +426,7 @@ to another list the label changes and a system not is recorded.
![Issue Board system notes](img/issue_board_system_notes.png)
-## Multiple Issue Boards **[STARTER]**
-
-> Introduced in [GitLab Enterprise Edition 8.13](https://about.gitlab.com/2016/10/22/gitlab-8-13-released/#multiple-issue-boards-ee).
-
-Multiple Issue Boards, as the name suggests, allow for more than one Issue Board
-for a given project or group. This is great for large projects with more than one team
-or in situations where a repository is used to host the code of multiple
-products.
-
-Clicking on the current board name in the upper left corner will reveal a
-menu from where you can create another Issue Board and rename or delete the
-existing one.
-
-NOTE: **Note:**
-The Multiple Issue Boards feature is available for
-**projects in GitLab Starter Edition** and for **groups in GitLab Premium Edition**.
-
-![Multiple Issue Boards](img/issue_boards_multiple.png)
-
-## Configurable Issue Boards **[STARTER]**
-
-> Introduced in [GitLab Starter Edition 10.2](https://about.gitlab.com/2017/11/22/gitlab-10-2-released/#issue-boards-configuration).
-
-An Issue Board can be associated with GitLab [Milestone](milestones/index.md#milestones),
-[Labels](labels.md), Assignee and Weight
-which will automatically filter the Board issues according to these fields.
-This allows you to create unique boards according to your team's need.
-
-![Create scoped board](img/issue_board_creation.png)
-
-You can define the scope of your board when creating it or by clicking on the "Edit board" button. Once a milestone, assignee or weight is assigned to an Issue Board, you will no longer be able to filter
-through these in the search bar. In order to do that, you need to remove the desired scope (e.g. milestone, assignee or weight) from the Issue Board.
-
-![Edit board configuration](img/issue_board_edit_button.png)
-
-If you don't have editing permission in a board, you're still able to see the configuration by clicking on "View scope".
-
-![Viewing board configuration](img/issue_board_view_scope.png)
-
-## Focus mode **[STARTER]**
-
-> Introduced in [GitLab Starter 9.1](https://about.gitlab.com/2017/04/22/gitlab-9-1-released/#issue-boards-focus-mode-ees-eep).
-
-Click the button at the top right to toggle focus mode on and off. In focus mode, the navigation UI is hidden, allowing you to focus on issues in the board.
-
-![Board focus mode](img/issue_board_focus_mode.gif)
-
-## Group Issue Boards **[PREMIUM]**
-
-> Introduced in [GitLab Premium 10.0](https://about.gitlab.com/2017/09/22/gitlab-10-0-released/#group-issue-boards).
-
-Accessible at the group navigation level, a group issue board offers the same features as a project-level board,
-but it can display issues from all projects in that
-group and its descendant subgroups. Similarly, you can only filter by group labels for these
-boards. When updating milestones and labels for an issue through the sidebar update mechanism, again only
-group-level objects are available.
-
-NOTE: **Note:**
-Multiple group issue boards were originally introduced in [GitLab 10.0 Premium](https://about.gitlab.com/2017/09/22/gitlab-10-0-released/#group-issue-boards) and
-one group issue board per group was made available in GitLab 10.6 Core.
-
-![Group issue board](img/group_issue_board.png)
-
-## Assignee lists **[PREMIUM]**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5784) in GitLab 11.0 Premium.
-
-Like a regular list that shows all issues that have the list label, you can add
-an assignee list that shows all issues assigned to the given user.
-You can have a board with both label lists and assignee lists. To add an
-assignee list:
-
-1. Click **Add list**.
-1. Select the **Assignee list** tab.
-1. Search and click on the user you want to add as an assignee.
-
-Now that the assignee list is added, you can assign or unassign issues to that user
-by [dragging issues](#dragging-issues-between-lists) to and/or from an assignee list.
-To remove an assignee list, just as with a label list, click the trash icon.
-
-![Assignee lists](img/issue_board_assignee_lists.png)
-
-## Dragging issues between lists
+### Dragging issues between lists
When dragging issues between lists, different behavior occurs depending on the source list and the target list.
@@ -360,17 +437,6 @@ When dragging issues between lists, different behavior occurs depending on the s
| From label `A` list | `A` removed | Issue closed | `A` removed<br/>`B` added | `Bob` assigned |
| From assignee `Alice` list | `Alice` unassigned | Issue closed | `B` added | `Alice` unassigned<br/>`Bob` assigned |
-## Features per tier
-
-Different issue board features are available in different [GitLab tiers](https://about.gitlab.com/pricing/), as shown in the following table:
-
-| Tier | Number of Project Issue Boards | Number of Group Issue Boards | Configurable Issue Boards | Assignee Lists |
-|----------|--------------------------------|------------------------------|---------------------------|----------------|
-| Core | 1 | 1 | No | No |
-| Starter | Multiple | 1 | Yes | No |
-| Premium | Multiple | Multiple | Yes | Yes |
-| Ultimate | Multiple | Multiple | Yes | Yes |
-
## Tips
A few things to remember:
diff --git a/doc/user/project/issues/automatic_issue_closing.md b/doc/user/project/issues/automatic_issue_closing.md
index b6570c777ae..afb7d9ada5f 100644
--- a/doc/user/project/issues/automatic_issue_closing.md
+++ b/doc/user/project/issues/automatic_issue_closing.md
@@ -27,10 +27,11 @@ used:
Note that `%{issue_ref}` is a complex regular expression defined inside GitLab's
source code that can match references to:
-1. a local issue (`#123`),
-2. a cross-project issue (`group/project#123`)
-3. a link to an issue
-(`https://gitlab.example.com/group/project/issues/123`).
+
+- A local issue (`#123`).
+- A cross-project issue (`group/project#123`).
+- A link to an issue
+ (`https://gitlab.example.com/group/project/issues/123`).
---
diff --git a/doc/user/project/issues/create_new_issue.md b/doc/user/project/issues/create_new_issue.md
index 1688edc1ee2..c33d1365001 100644
--- a/doc/user/project/issues/create_new_issue.md
+++ b/doc/user/project/issues/create_new_issue.md
@@ -58,3 +58,21 @@ body becomes the issue description. [Markdown] and [quick actions] are
supported.
![Bottom of a project issues page](img/new_issue_from_email.png)
+
+## New issue via URL with prefilled fields
+
+You can link directly to the new issue page for a given project, with prefilled
+field values using query string parameters in a URL. This is useful for embedding
+a URL in an external HTML page, and also certain scenarios where you want the user to
+create an issue with certain fields prefilled.
+
+The title, description, and description template fields can be prefilled using
+this method. The description and description template fields cannot be pre-entered
+in the same URL (since a description template just populates the description field).
+
+Follow these examples to form your new issue URL with prefilled fields.
+
+- For a new issue in the GitLab Community Edition project with a pre-entered title
+and a pre-entered description, the URL would be `https://gitlab.com/gitlab-org/gitlab-ce/issues/new?issue[title]=Validate%20new%20concept&issue[description]=Research%20idea`
+- For a new issue in the GitLab Community Edition project with a pre-entered title
+and a pre-entered description template, the URL would be `https://gitlab.com/gitlab-org/gitlab-ce/issues/new?issue[title]=Validate%20new%20concept&issuable_template=Research%20proposal`
diff --git a/doc/user/project/issues/img/issue_board.png b/doc/user/project/issues/img/issue_board.png
index df9d6f64985..c75c35a382e 100644
--- a/doc/user/project/issues/img/issue_board.png
+++ b/doc/user/project/issues/img/issue_board.png
Binary files differ
diff --git a/doc/user/project/issues/issues_functionalities.md b/doc/user/project/issues/issues_functionalities.md
index 46f25417fde..d78721f8658 100644
--- a/doc/user/project/issues/issues_functionalities.md
+++ b/doc/user/project/issues/issues_functionalities.md
@@ -69,7 +69,7 @@ Learn more on the [Time Tracking documentation](../../../workflow/time_tracking.
#### 6. Due date
When you work on a tight schedule, and it's important to
-have a way to setup a deadline for implementations and for solving
+have a way to set up a deadline for implementations and for solving
problems. This can be facilitated by the [due date](due_dates.md)). Due dates
can be changed as many times as needed.
@@ -118,9 +118,12 @@ is the `project-name`, and `xxx` is the issue number.
#### 13. @mentions
-- Mentions: you can either `@mention` a user or a group present in your
-GitLab instance and they will be notified via todos and email, unless that
-person has disabled all notifications in their profile settings.
+- You can either `@mention` a user or a group present in your
+ GitLab instance and they will be notified via todos and email, unless that
+ person has disabled all notifications in their profile settings.
+- Mentions for yourself (the current logged in user),will be distinctly highlighted
+ in a different color, allowing you to easily see which comments involve you,
+ helping you focus on them quickly.
To change your [notification settings](../../../workflow/notifications.md) navigate to
**Profile Settings** > **Notifications** > **Global notification level**
diff --git a/doc/user/project/koding.md b/doc/user/project/koding.md
deleted file mode 100644
index 2c886d7916a..00000000000
--- a/doc/user/project/koding.md
+++ /dev/null
@@ -1,131 +0,0 @@
-# Koding integration
-
-> **Notes:**
-> - **As of GitLab 10.0, the Koding integration is deprecated and will be removed
-> in a future version.**
-> - [Introduced][ce-5909] in GitLab 8.11.
-
-This document will guide you through using Koding integration on GitLab in
-detail. For configuring and installing please follow the
-[administrator guide](../../administration/integration/koding.md).
-
-You can use Koding integration to run and develop your projects on GitLab. This
-will allow you and the users to test your project without leaving the browser.
-Koding handles projects as stacks which are basic recipes to define your
-environment for your project. With this integration you can automatically
-create a proper stack template for your projects. Currently auto-generated
-stack templates are designed to work with AWS which requires a valid AWS
-credential to be able to use these stacks. You can find more information about
-stacks and the other providers that you can use on Koding following the
-[Koding documentation][koding-docs].
-
-## Enable Integration
-
-You can enable Koding integration by providing the running Koding instance URL
-in Application Settings under **Admin area > Settings** (`/admin/application_settings`).
-
-![Enable Koding](img/koding_enable-koding.png)
-
-Once enabled you will see `Koding` link on your sidebar which leads you to
-Koding Landing page.
-
-![Koding Landing](img/koding_landing.png)
-
-You can navigate to running Koding instance from here. For more information and
-details about configuring the integration, please follow the
-[administrator guide](../../administration/integration/koding.md).
-
-## Set up Koding on Projects
-
-Once it's enabled, you will see some integration buttons on Project pages,
-Merge Requests etc. To get started working on a specific project you first need
-to create a `.koding.yml` file under your project root. You can easily do that
-by using `Set Up Koding` button which will be visible on every project's
-landing page;
-
-![Set Up Koding](img/koding_set-up-ide.png)
-
-Once you click this will open a New File page on GitLab with auto-generated
-`.koding.yml` content based on your server and repository configuration.
-
-![Commit .koding.yml](img/koding_commit-koding.yml.png)
-
-
-## Run a project on Koding
-
-If there is `.koding.yml` exists in your project root, you will see
-`Run in IDE (Koding)` button in your project landing page. You can initiate the
-process from here.
-
-![Run on Koding](img/koding_run-in-ide.png)
-
-This will open Koding defined in the settings in a new window and will start
-importing the project's stack file.
-
-![Import Stack](img/koding_stack-import.png)
-
-You should see the details of your repository imported into your Koding
-instance. Once it's completed it will lead you to the Stack Editor and from
-there you can start using your new stack integrated with your project on your
-GitLab instance. For details about what's next you can follow
-[this guide](https://www.koding.com/docs/creating-an-aws-stack) from step 8.
-
-Once stack initialized you will see the `README.md` content from your project
-in `Stack Build` wizard, this wizard will let you build the stack and import
-your project into it. **Once it's completed it will automatically open the
-related vm instead of importing from scratch**.
-
-![Stack Building](img/koding_start-build.png)
-
-This will take time depending on the required environment.
-
-![Stack Building in Progress](img/koding_build-in-progress.png)
-
-It usually takes ~4 min. to make it ready with a `t2.nano` instance on given
-AWS region. (`t2.nano` is default vm type on auto-generated stack template
-which can be manually changed).
-
-![Stack Building Success](img/koding_build-success.png)
-
-You can check out the `Build Logs` from this success modal as well.
-
-![Stack Build Logs](img/koding_build-logs.png)
-
-You can now `Start Coding`!
-
-![Edit On IDE](img/koding_edit-on-ide.png)
-
-## Try a Merge Request on IDE
-
-It's also possible to try a change on IDE before merging it. This flow only
-enabled if the target project has `.koding.yml` in it's target branch. You
-should see the alternative version of `Run in IDE (Koding)` button in merge
-request pages as well;
-
-![Run in IDE on MR](img/koding_run-mr-in-ide.png)
-
-This will again take you to Koding with proper arguments passed, which will
-allow Koding to modify the stack template provided by target branch. You can
-see the difference;
-
-![Different Branch for MR](img/koding_different-stack-on-mr-try.png)
-
-The flow for the branch stack is also same with the regular project flow.
-
-## Open GitLab from Koding
-
-Since stacks generated with import flow defined in previous steps, they have
-information about the repository they are belonging to. By using this
-information you can access to related GitLab page from stacks on your sidebar
-on Koding.
-
-![Open GitLab from Koding](img/koding_open-gitlab-from-koding.png)
-
-## Other links
-
-- [YouTube video on GitLab + Koding workflow][youtube]
-- [Koding documentation][koding-docs]
-
-[ce-5909]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5909
-[youtube]: https://youtu.be/3wei5yv_Ye8
-[koding-docs]: https://www.koding.com/docs
diff --git a/doc/user/project/labels.md b/doc/user/project/labels.md
index 3ae6dbe585e..9c045dfcce4 100644
--- a/doc/user/project/labels.md
+++ b/doc/user/project/labels.md
@@ -19,6 +19,7 @@ A permission level of `Developer` or higher is required to create labels.
### New project label
To create a **project label**, navigate to **Issues > Labels** in the project.
+This page only shows project labels in this project and group labels of this project's parent group.
Click the **New label** button. Enter the title, an optional description, and the background color. Click **Create label** to create the label.
@@ -33,6 +34,7 @@ GitLab will add the following default labels to the project:
### New group label
To create a **group label**, follow similar steps from above to project labels. Navigate to **Issues > Labels** in the group and create it from there.
+This page only shows group labels in this group.
Group labels appear in every label list page of the group's child projects.
@@ -95,7 +97,7 @@ From the group issue list page and the group merge request list page, you can [f
## Subscribing to labels
-From the project label list page and the group label list page, you can subscribe to [notifications](../../workflow/notifications.md) of a given label, to alert you that that label has been assigned to an issue or merge request.
+From the project label list page and the group label list page, you can subscribe to [notifications](../../workflow/notifications.md) of a given label, to alert you that the label has been assigned to an issue or merge request.
![Labels subscriptions](img/labels_subscriptions.png)
diff --git a/doc/user/project/merge_requests/cherry_pick_changes.md b/doc/user/project/merge_requests/cherry_pick_changes.md
index 22ef11e4049..06b3779668b 100644
--- a/doc/user/project/merge_requests/cherry_pick_changes.md
+++ b/doc/user/project/merge_requests/cherry_pick_changes.md
@@ -12,9 +12,11 @@ to cherry-pick the changes introduced by that merge request.
![Cherry-pick Merge Request](img/cherry_pick_changes_mr.png)
-After you click that button, a modal will appear where you can choose to
-cherry-pick the changes directly into the selected branch or you can opt to
-create a new merge request with the cherry-pick changes
+After you click that button, a modal will appear showing a [branch filter search box](../repository/branches/index.md#branch-filter-search-box)
+where you can choose to either:
+
+- Cherry-pick the changes directly into the selected branch.
+- Create a new merge request with the cherry-picked changes.
## Cherry-picking a Commit
diff --git a/doc/user/project/merge_requests/img/comment-on-any-diff-line.png b/doc/user/project/merge_requests/img/comment-on-any-diff-line.png
new file mode 100644
index 00000000000..856ede41527
--- /dev/null
+++ b/doc/user/project/merge_requests/img/comment-on-any-diff-line.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/filter_wip_merge_requests.png b/doc/user/project/merge_requests/img/filter_wip_merge_requests.png
new file mode 100644
index 00000000000..40913718385
--- /dev/null
+++ b/doc/user/project/merge_requests/img/filter_wip_merge_requests.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png b/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png
index ac766c99935..1cdac5ef573 100644
--- a/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png
+++ b/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_request_pipeline.png b/doc/user/project/merge_requests/img/merge_request_pipeline.png
new file mode 100644
index 00000000000..183d9cb910b
--- /dev/null
+++ b/doc/user/project/merge_requests/img/merge_request_pipeline.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_request_widget.png b/doc/user/project/merge_requests/img/merge_request_widget.png
index 6c2317b29b5..58562fcb034 100644
--- a/doc/user/project/merge_requests/img/merge_request_widget.png
+++ b/doc/user/project/merge_requests/img/merge_request_widget.png
Binary files differ
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
index 43ca498d006..5b54b6ecdd5 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -9,7 +9,7 @@ collaborate with other people on the same project.
A Merge Request (**MR**) is the basis of GitLab as a code collaboration
and version control platform.
-Is it simple as the name implies: a _request_ to _merge_ one branch into another.
+It is as simple as the name implies: a _request_ to _merge_ one branch into another.
With GitLab merge requests, you can:
@@ -141,6 +141,15 @@ you hide discussions that are no longer relevant.
[Read more about resolving discussion comments in merge requests reviews.](../../discussions/index.md)
+## Commenting on any file line in merge requests
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/13950) in GitLab 11.5.
+
+GitLab provides a way of leaving comments in any part of the file being changed
+in a Merge Request. To do so, click the **...** button in the gutter of the Merge Request diff UI to expand the diff lines and leave a comment, just as you would for a changed line.
+
+![Comment on any diff file line](img/comment-on-any-diff-line.png)
+
## Resolve conflicts
When a merge request has conflicts, GitLab may provide the option to resolve
@@ -166,9 +175,26 @@ administrator to do so.
![Create new merge requests by email](img/create_from_email.png)
+### Adding patches when creating a merge request via e-mail
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22723) in GitLab 11.5.
+
+You can add commits to the merge request being created by adding
+patches as attachments to the email. All attachments with a filename
+ending in `.patch` will be considered patches and they will be processed
+ordered by name.
+
+The combined size of the patches can be 2MB.
+
+If the source branch from the subject does not exist, it will be
+created from the repository's HEAD or the specified target branch to
+apply the patches. The target branch can be specified using the
+[`/target_branch` quick action](../quick_actions.md). If the source
+branch already exists, the patches will be applied on top of it.
+
## Find the merge request that introduced a change
-> **Note**: this feature was [implemented in GitLab 10.5](https://gitlab.com/gitlab-org/gitlab-ce/issues/2383).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/2383) in GitLab 10.5.
When viewing the commit details page, GitLab will link to the merge request (or
merge requests, if it's in more than one) containing that commit.
@@ -205,9 +231,10 @@ have been marked as a **Work In Progress**.
## Merge request diff file navigation
-The diff view has a persistent dropdown for file navigation. As you scroll through
-diffs with a large number of files and/or many changes in those files, you can
-easily jump to any changed file through the dropdown navigation.
+When reviewing changes in the **Changes** tab the diff can be navigated using
+the file tree or file list. As you scroll through large diffs with many
+changes, you can quickly jump to any changed file using the file tree or file
+list.
![Merge request diff file navigation](img/merge_request_diff_file_navigation.png)
@@ -232,10 +259,67 @@ all your changes will be available to preview by anyone with the Review Apps lin
[Read more about Review Apps.](../../../ci/review_apps/index.md)
+## Pipeline status in merge requests
+
+If you've set up [GitLab CI/CD](../../../ci/README.md) in your project,
+you will be able to see:
+
+- Both pre and post-merge pipelines and the environment information if any.
+- Which deployments are in progress.
+
+If there's an [environment](../../../ci/environments.md) and the application is
+successfully deployed to it, the deployed environment and the link to the
+Review App will be shown as well.
+
+### Post-merge pipeline status
+
+When a merge request is merged, you can see the post-merge pipeline status of
+the branch the merge request was merged into. For example, when a merge request
+is merged into the master branch and then triggers a deployment to the staging
+environment.
+
+Deployments that are ongoing will be shown, as well as the deploying/deployed state
+for environments. If it's the first time the branch is deployed, the link
+will return a `404` error until done. During the deployment, the stop button will
+be disabled. If the pipeline fails to deploy, the deployment info will be hidden.
+
+![Merge request pipeline](img/merge_request_pipeline.png)
+
+For more information, [read about pipelines](../../../ci/pipelines.md).
+
## Bulk editing merge requests
Find out about [bulk editing merge requests](../../project/bulk_editing.md).
+## Troubleshooting
+
+Sometimes things don't go as expected in a merge request, here are some
+troubleshooting steps.
+
+### Merge request cannot retrieve the pipeline status
+
+This can occur for one of two reasons:
+
+* Sidekiq doesn't pick up the changes fast enough
+* Because of the bug described in [#41545](https://gitlab.com/gitlab-org/gitlab-ce/issues/41545)
+
+#### Sidekiq
+
+Sidekiq didn't process the CI state change fast enough. Please wait a few
+seconds and the status will update automatically.
+
+#### Bug
+
+Merge Request pipeline statuses can't be retrieved when the following occurs:
+
+1. A Merge Requst is created
+1. The Merge Request is closed
+1. Changes are made in the project
+1. The Merge Request is reopened
+
+To enable the pipeline status to be properly retrieved, close and reopen the
+Merge Request again.
+
## Tips
Here are some tips that will help you be more efficient with merge requests in
diff --git a/doc/user/project/merge_requests/resolve_conflicts.md b/doc/user/project/merge_requests/resolve_conflicts.md
index ecbc8534eea..ccef2853e3f 100644
--- a/doc/user/project/merge_requests/resolve_conflicts.md
+++ b/doc/user/project/merge_requests/resolve_conflicts.md
@@ -1,15 +1,31 @@
-# Merge conflict resolution
+# Merge request conflict resolution
-> [Introduced][ce-5479] in GitLab 8.11.
+Merge conflicts occur when two branches have different changes that cannot be
+merged automatically.
-When a merge request has conflicts, GitLab may provide the option to resolve
-those conflicts in the GitLab UI. (See
-[conflicts available for resolution](#conflicts-available-for-resolution) for
-more information on when this is available.) If this is an option, you will see
-a **resolve these conflicts** link in the merge request widget:
+Git is able to automatically merge changes between branches in most cases, but
+there are situations where Git will require your assistance to resolve the
+conflicts manually. Typically, this is necessary when people change the same
+parts of the same files.
+
+GitLab will prevent merge requests from being merged until all conflicts are
+resolved. Conflicts can be resolved locally, or in many cases within GitLab
+(see [conflicts available for resolution](#conflicts-available-for-resolution)
+for information on when this is available).
![Merge request widget](img/merge_request_widget.png)
+NOTE: **Note:**
+GitLab resolves conflicts by creating a merge commit in the source branch that
+is not automatically merged into the target branch. This allows the merge
+commit to be reviewed and tested before the changes are merged, preventing
+unintended changes entering the target branch without review or breaking the
+build.
+
+## Resolve conflicts: interactive mode
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5479) in GitLab 8.11.
+
Clicking this will show a list of files with conflicts, with conflict sections
highlighted:
@@ -21,9 +37,9 @@ request into the source branch, resolving the conflicts using the options
chosen. If the source branch is `feature` and the target branch is `master`,
this is similar to performing `git checkout feature; git merge master` locally.
-## Merge conflict editor
+## Resolve conflicts: inline editor
-> Introduced in GitLab 8.13.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6374) in GitLab 8.13.
The merge conflict resolution editor allows for more complex merge conflicts,
which require the user to manually modify a file in order to resolve a conflict,
@@ -50,5 +66,3 @@ Additionally, GitLab does not detect conflicts in renames away from a path. For
example, this will not create a conflict: on branch `a`, doing `git mv file1
file2`; on branch `b`, doing `git mv file1 file3`. Instead, both files will be
present in the branch after the merge request is merged.
-
-[ce-5479]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5479
diff --git a/doc/user/project/merge_requests/revert_changes.md b/doc/user/project/merge_requests/revert_changes.md
index 8cf8a59dbfe..b9102798a49 100644
--- a/doc/user/project/merge_requests/revert_changes.md
+++ b/doc/user/project/merge_requests/revert_changes.md
@@ -12,6 +12,12 @@ The **Revert** button will only be available for merge requests
created since GitLab 8.5. However, you can still revert a merge request
by reverting the merge commit from the list of Commits page.
+NOTE: **Note:**
+The **Revert** button will only be shown for projects that use the
+merge method "Merge Commit", which can be set under the project's
+**Settings > General > Merge request**. [Fast-forward commits](fast_forward_merge.md)
+can not be reverted via the MR view.
+
After the Merge Request has been merged, a **Revert** button will be available
to revert the changes introduced by that merge request.
diff --git a/doc/user/project/merge_requests/work_in_progress_merge_requests.md b/doc/user/project/merge_requests/work_in_progress_merge_requests.md
index f01da06fa6e..66ac7740157 100644
--- a/doc/user/project/merge_requests/work_in_progress_merge_requests.md
+++ b/doc/user/project/merge_requests/work_in_progress_merge_requests.md
@@ -7,7 +7,7 @@ have been marked a **Work In Progress**.
![Blocked Accept Button](img/wip_blocked_accept_button.png)
To mark a merge request a Work In Progress, simply start its title with `[WIP]`
-or `WIP:`. As an alternative, you're also able to do it by sending a commit
+or `WIP:`. As an alternative, you're also able to do it by sending a commit
with its title starting with `wip` or `WIP` to the merge request's source branch.
![Mark as WIP](img/wip_mark_as_wip.png)
@@ -15,4 +15,11 @@ with its title starting with `wip` or `WIP` to the merge request's source branch
To allow a Work In Progress merge request to be accepted again when it's ready,
simply remove the `WIP` prefix.
-![Unark as WIP](img/wip_unmark_as_wip.png)
+![Unmark as WIP](img/wip_unmark_as_wip.png)
+
+## Filtering merge requests with WIP Status
+
+To filter merge requests with the `WIP` status, you can type `wip`
+and select the value for your filter from the merge request search input.
+
+![Filter WIP MRs](img/filter_wip_merge_requests.png)
diff --git a/doc/user/project/milestones/index.md b/doc/user/project/milestones/index.md
index 632253db94c..ac58a0b5c18 100644
--- a/doc/user/project/milestones/index.md
+++ b/doc/user/project/milestones/index.md
@@ -6,6 +6,26 @@ Milestones in GitLab are a way to track issues and merge requests created to ach
Milestones allow you to organize issues and merge requests into a cohesive group, with an optional start date and an optional due date.
+## Milestones as Agile sprints
+
+Milestones can be used as Agile sprints.
+Set the milestone start date and due date to represent
+the start and end of your Agile sprint.
+Set the milestone title to the name of your Agile sprint,
+such as `November 2018 sprint`.
+Add an issue to your Agile sprint by associating
+the milestone to the issue.
+
+## Milestones as releases
+
+Milestones can be used as releases.
+Set the milestone due date to represent the release date of your release.
+(And leave the milestone start date blank.)
+Set the milestone title to the version of your release,
+such as `Version 9.4`.
+Add an issue to your release by associating
+the milestone to the issue.
+
## Project milestones and group milestones
- **Project milestones** can be assigned to issues or merge requests in that project only.
@@ -68,7 +88,8 @@ From [project issue boards](../issue_board.md), you can filter by both group mil
When filtering by milestone, in addition to choosing a specific project milestone or group milestone, you can choose a special milestone filter.
-- **No Milestone**: Show issues or merge requests with no assigned milestone.
+- **None**: Show issues or merge requests with no assigned milestone.
+- **Any**: Show issues or merge requests that have an assigned milestone.
- **Upcoming**: Show issues or merge requests that have been assigned the open milestone that has the next upcoming due date (i.e. nearest due date in the future).
- **Started**: Show issues or merge requests that have an assigned milestone with a start date that is before today.
diff --git a/doc/user/project/new_ci_build_permissions_model.md b/doc/user/project/new_ci_build_permissions_model.md
index 23d5b34504c..9a53036b4d1 100644
--- a/doc/user/project/new_ci_build_permissions_model.md
+++ b/doc/user/project/new_ci_build_permissions_model.md
@@ -60,7 +60,7 @@ Let's consider the following scenario:
hosted in private repositories and you have multiple CI jobs that make use
of these repositories.
-2. You invite a new [external user][ext]. CI jobs created by that user do not
+1. You invite a new [external user][ext]. CI jobs created by that user do not
have access to internal repositories, because the user also doesn't have the
access from within GitLab. You as an employee have to grant explicit access
for this user. This allows us to prevent from accidental data leakage.
diff --git a/doc/user/project/pages/getting_started_part_three.md b/doc/user/project/pages/getting_started_part_three.md
index e1eede8bbed..247e8d2a6a0 100644
--- a/doc/user/project/pages/getting_started_part_three.md
+++ b/doc/user/project/pages/getting_started_part_three.md
@@ -1,5 +1,5 @@
---
-last_updated: 2018-08-16
+last_updated: 2018-11-19
author: Marcia Ramos
author_gitlab: marcia
level: beginner
@@ -11,7 +11,7 @@ date: 2017-02-22
Setting up GitLab Pages with custom domains, and adding SSL/TLS certificates to them, are optional features of GitLab Pages.
-These steps assume you've already [set your site up](getting_started_part_two.md) and and it's served under the default Pages domain `namespace.gitlab.io`, or `namespace.gitlab.io/project-name`.
+These steps assume you've already [set your site up](getting_started_part_two.md) and it's served under the default Pages domain `namespace.gitlab.io`, or `namespace.gitlab.io/project-name`.
## Adding your custom domain to GitLab Pages
@@ -183,7 +183,7 @@ you can use the following setup:
- In Cloudflare, create a DNS `A` record pointing `domain.com` to `35.185.44.232`
- In GitLab, add the domain to GitLab Pages
- In Cloudflare, create a DNS `TXT` record to verify your domain
-- In Cloudflare, create a DNS `CNAME` record poiting `www` to `domain.com`
+- In Cloudflare, create a DNS `CNAME` record pointing `www` to `domain.com`
## SSL/TLS Certificates
@@ -212,7 +212,7 @@ security measure, necessary just for big companies, like banks and shoppings sit
with financial transactions.
Now we have a different picture. [According to Josh Aas](https://letsencrypt.org/2015/10/29/phishing-and-malware.html), Executive Director at [ISRG](https://en.wikipedia.org/wiki/Internet_Security_Research_Group):
-> _We’ve since come to realize that HTTPS is important for almost all websites. It’s important for any website that allows people to log in with a password, any website that [tracks its users](https://www.washingtonpost.com/news/the-switch/wp/2013/12/10/nsa-uses-google-cookies-to-pinpoint-targets-for-hacking/) in any way, any website that [doesn’t want its content altered](http://arstechnica.com/tech-policy/2014/09/why-comcasts-javascript-ad-injections-threaten-security-net-neutrality/), and for any site that offers content people might not want others to know they are consuming. We’ve also learned that any site not secured by HTTPS [can be used to attack other sites](http://krebsonsecurity.com/2015/04/dont-be-fodder-for-chinas-great-cannon/)._
+> _We’ve since come to realize that HTTPS is important for almost all websites. It’s important for any website that allows people to log in with a password, any website that [tracks its users](https://www.washingtonpost.com/news/the-switch/wp/2013/12/10/nsa-uses-google-cookies-to-pinpoint-targets-for-hacking/) in any way, any website that [doesn’t want its content altered](http://arstechnica.com/tech-policy/2014/09/why-comcasts-javascript-ad-injections-threaten-security-net-neutrality/), and for any site that offers content people might not want others to know they are consuming. We’ve also learned that any site not secured by HTTPS [can be used to attack other sites](https://krebsonsecurity.com/2015/04/dont-be-fodder-for-chinas-great-cannon/)._
Therefore, the reason why certificates are so important is that they encrypt
the connection between the **client** (you, me, your visitors)
diff --git a/doc/user/project/pages/img/icons/click.png b/doc/user/project/pages/img/icons/click.png
new file mode 100644
index 00000000000..daaf760ec08
--- /dev/null
+++ b/doc/user/project/pages/img/icons/click.png
Binary files differ
diff --git a/doc/user/project/pages/img/icons/cogs.png b/doc/user/project/pages/img/icons/cogs.png
new file mode 100644
index 00000000000..a12da1b5e8c
--- /dev/null
+++ b/doc/user/project/pages/img/icons/cogs.png
Binary files differ
diff --git a/doc/user/project/pages/img/icons/fork.png b/doc/user/project/pages/img/icons/fork.png
new file mode 100644
index 00000000000..e2c9577e7ce
--- /dev/null
+++ b/doc/user/project/pages/img/icons/fork.png
Binary files differ
diff --git a/doc/user/project/pages/img/icons/free.png b/doc/user/project/pages/img/icons/free.png
new file mode 100644
index 00000000000..3b8f8f6863e
--- /dev/null
+++ b/doc/user/project/pages/img/icons/free.png
Binary files differ
diff --git a/doc/user/project/pages/img/icons/lock.png b/doc/user/project/pages/img/icons/lock.png
new file mode 100644
index 00000000000..1c1f0b4457b
--- /dev/null
+++ b/doc/user/project/pages/img/icons/lock.png
Binary files differ
diff --git a/doc/user/project/pages/img/icons/monitor.png b/doc/user/project/pages/img/icons/monitor.png
new file mode 100644
index 00000000000..7b99d430eef
--- /dev/null
+++ b/doc/user/project/pages/img/icons/monitor.png
Binary files differ
diff --git a/doc/user/project/pages/img/icons/terminal.png b/doc/user/project/pages/img/icons/terminal.png
new file mode 100644
index 00000000000..ab5ae11310c
--- /dev/null
+++ b/doc/user/project/pages/img/icons/terminal.png
Binary files differ
diff --git a/doc/user/project/pages/img/ssgs_pages.png b/doc/user/project/pages/img/ssgs_pages.png
new file mode 100644
index 00000000000..608881c8e31
--- /dev/null
+++ b/doc/user/project/pages/img/ssgs_pages.png
Binary files differ
diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md
index 4f0774dba5c..7de9ae0caea 100644
--- a/doc/user/project/pages/index.md
+++ b/doc/user/project/pages/index.md
@@ -4,71 +4,180 @@ description: 'Learn how to use GitLab Pages to deploy a static website at no add
# GitLab Pages
-With GitLab Pages it's easy to publish your project website. GitLab Pages is a hosting service for static websites, at no additional cost.
-
-## Getting Started
-
-[Create a project from scratch](getting_started_part_two.md#create-a-project-from-scratch)
-to get you started quickly, or,
-alternatively, start from an existing project as follows:
-
-1. [Fork](../../../gitlab-basics/fork-project.md#how-to-fork-a-project) an [example project](https://gitlab.com/pages):
+**GitLab Pages is a feature that allows you to publish static websites
+directly from a repository in GitLab.**
+
+You can use it either for personal or business websites, such as
+portfolios, documentation, manifestos, and business presentations,
+and attribute any license to your content.
+
+<table class="borderless-table center fixed-table">
+ <tr>
+ <td style="width: 22%"><img src="img/icons/cogs.png" alt="SSGs" class="image-noshadow half-width"></td>
+ <td style="width: 4%">
+ <strong>
+ <i class="fa fa-angle-double-right" aria-hidden="true"></i>
+ </strong>
+ </td>
+ <td style="width: 22%"><img src="img/icons/monitor.png" alt="Websites" class="image-noshadow half-width"></td>
+ <td style="width: 4%">
+ <strong>
+ <i class="fa fa-angle-double-right" aria-hidden="true"></i>
+ </strong>
+ </td>
+ <td style="width: 22%"><img src="img/icons/free.png" alt="Pages is free" class="image-noshadow half-width"></td>
+ <td style="width: 4%">
+ <strong>
+ <i class="fa fa-angle-double-right" aria-hidden="true"></i>
+ </strong>
+ </td>
+ <td style="width: 22%"><img src="img/icons/lock.png" alt="Secure your website" class="image-noshadow half-width"></td>
+ </tr>
+ <tr>
+ <td><em>Use any static website generator or plain HTML</em></td>
+ <td></td>
+ <td><em>Create websites for your projects, groups, or user account</em></td>
+ <td></td>
+ <td><em>Host on GitLab.com for free, or on your own GitLab instance</em></td>
+ <td></td>
+ <td><em>Connect your custom domain(s) and TLS certificates</em></td>
+ </tr>
+</table>
+
+Pages is available for free for all GitLab.com users as well as for self-managed
+instances (GitLab Core, Starter, Premium, and Ultimate).
+
+## Overview
+
+<div class="row">
+<div class="col-md-9">
+<p style="margin-top: 18px;">
+To publish a website with Pages, you can use any Static Site Generator (SSG),
+such as Jekyll, Hugo, Middleman, Harp, Hexo, and Brunch, just to name a few. You can also
+publish any website written directly in plain HTML, CSS, and JavaScript.</p>
+<p>Pages does <strong>not</strong> support dynamic server-side processing, for instance, as <code>.php</code> and <code>.asp</code> requires. See this article to learn more about
+<a href="https://about.gitlab.com/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/">static websites vs dynamic websites</a>.</p>
+</div>
+<div class="col-md-3"><img src="img/ssgs_pages.png" alt="Examples of SSGs supported by Pages" class="image-noshadow middle display-block"></div>
+</div>
+
+### Availability
+
+If you're using GitLab.com, your website will be publicly available to the internet.
+If you're using self-managed instances (Core, Starter, Premium, or Ultimate),
+your websites will be published on your own server, according to the
+[Pages admin settings](../../../administration/pages/index.md) chosen by your sysdamin,
+who can opt for making them public or internal to your server.
+
+### How it works
+
+To use GitLab Pages, first you need to create a project in GitLab to upload your website's
+files to. These projects can be either public, internal, or private, at your own choice.
+GitLab will always deploy your website from a very specific folder called `public` in your
+repository. Note that when you create a new project in GitLab, a [repository](../repository/index.md)
+becomes available automatically.
+
+To deploy your site, GitLab will use its built-in tool called [GitLab CI/CD](../../../ci/README.md),
+that will build your site and publish it to the GitLab Pages server. The sequence of
+scripts that GitLab CI/CD runs to accomplish this task is created from a file named
+`.gitlab-ci.yml`, which you can [create and modify](getting_started_part_four.md) at will.
+
+You can either use GitLab's [default domain for GitLab Pages websites](getting_started_part_one.md#gitlab-pages-domain),
+`*.gitlab.io`, or your own domain (`example.com`). In that case, you'll
+need admin access to your domain's registrar (or control panel) to set it up with Pages.
+
+Optionally, when adding your own domain, you can add an SSL/TLS certificate to secure your
+site under the HTTPS protocol.
+
+## Getting started
+
+To get started with GitLab Pages, you can either [create a project from scratch](getting_started_part_two.md#create-a-project-from-scratch)
+or quickly start from copying an existing example project, as follows:
+
+1. Choose an [example project](https://gitlab.com/pages) to [fork](../../../gitlab-basics/fork-project.md#how-to-fork-a-project):
by forking a project, you create a copy of the codebase you're forking from to start from a template instead of starting from scratch.
-2. Change a file to trigger a GitLab CI/CD pipeline: GitLab CI/CD will build and deploy your site to GitLab Pages.
-3. Visit your project's **Settings > Pages** to see your **website link**, and click on it. Bam! Your website is live! :)
-
- _Further steps (optional):_
-
-4. Remove the [fork relationship](getting_started_part_two.md#fork-a-project-to-get-started-from)
+1. From the left sidebar, navigate to your project's **CI/CD > Pipelines** and click
+**Run pipeline** so that GitLab CI/CD will build and deploy your site to the server.
+1. Once the pipeline has finished successfully, find the link to visit your website from your
+ project's **Settings > Pages**.
+
+<table class="borderless-table center fixed-table middle width-80">
+ <tr>
+ <td style="width: 30%"><img src="img/icons/fork.png" alt="Fork" class="image-noshadow half-width"></td>
+ <td style="width: 10%">
+ <strong>
+ <i class="fa fa-angle-double-right" aria-hidden="true"></i>
+ </strong>
+ </td>
+ <td style="width: 30%"><img src="img/icons/terminal.png" alt="Deploy" class="image-noshadow half-width"></td>
+ <td style="width: 10%">
+ <strong>
+ <i class="fa fa-angle-double-right" aria-hidden="true"></i>
+ </strong>
+ </td>
+ <td style="width: 30%"><img src="img/icons/click.png" alt="Visit" class="image-noshadow half-width"></td>
+ </tr>
+ <tr>
+ <td><em>Fork an example project</em></td>
+ <td></td>
+ <td><em>Deploy your website</em></td>
+ <td></td>
+ <td><em>Visit your website's URL</em></td>
+ </tr>
+</table>
+
+Your website is then visible on your domain, and you can modify your files
+as you wish. For every modification pushed to your repository, GitLab CI/CD will run
+a new pipeline to publish your changes to the server.
+
+You can also take some optional further steps:
+
+- Remove the [fork relationship](getting_started_part_two.md#fork-a-project-to-get-started-from)
(_You don't need the relationship unless you intent to contribute back to the example project you forked from_).
-5. Make it a [user/group website](getting_started_part_one.md#user-and-group-websites)
+- Make it a [user/group website](getting_started_part_one.md#user-and-group-websites)
-**Watch a video with the steps above: https://www.youtube.com/watch?v=TWqh9MtT4Bg**
+**<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> Watch a [video tutorial](https://www.youtube.com/watch?v=TWqh9MtT4Bg) with all the steps above!**
_Advanced options:_
- [Use a custom domain](getting_started_part_three.md#adding-your-custom-domain-to-gitlab-pages)
- Apply [SSL/TLS certification](getting_started_part_three.md#ssl-tls-certificates) to your custom domain
-## How Does It Work?
-
-With GitLab Pages you can create [static websites](getting_started_part_one.md#what-you-need-to-know-before-getting-started)
-for your GitLab projects, groups, or user accounts.
-
-It supports plain static content, such as HTML, and **all** [static site generators (SSGs)](https://about.gitlab.com/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/), such as Jekyll, Middleman, Hexo, Hugo, and Pelican.
-
-Connect as many custom domains as you like and bring your own TLS certificate
-to secure them.
-
-Your files live in a project [repository](../repository/index.md) on GitLab.
-[GitLab CI](../../../ci/README.md) picks up those files and makes them available at, typically,
-`https://<username>.gitlab.io/<projectname>`. Please read through the docs on
-[GitLab Pages domains](getting_started_part_one.md#gitlab-pages-domain) for more info.
-
## Explore GitLab Pages
-Read the following tutorials to know more about:
+To learn more about GitLab Pages, read the following tutorials:
- [Static websites and GitLab Pages domains](getting_started_part_one.md): Understand what is a static website, and how GitLab Pages default domains work
- [Projects for GitLab Pages and URL structure](getting_started_part_two.md): Forking projects and creating new ones from scratch, understanding URLs structure and baseurls
-- [GitLab Pages custom domains and SSL/TLS Certificates](getting_started_part_three.md): How to add custom domains and subdomains to your website, configure DNS records, and SSL/TLS certificates
+- [GitLab Pages custom domains and SSL/TLS Certificates](getting_started_part_three.md): How to add custom domains and subdomains to your website, configure DNS records and SSL/TLS certificates
- [Creating and Tweaking GitLab CI/CD for GitLab Pages](getting_started_part_four.md): Understand how to create your own `.gitlab-ci.yml` for your site
- [Technical aspects, custom 404 pages, limitations](introduction.md)
-- [Hosting on GitLab.com with GitLab Pages](https://about.gitlab.com/2016/04/07/gitlab-pages-setup/) (outdated)
-_Blog posts series about Static Site Generators (SSGs):_
+### GitLab Pages with Static Site Generators (SSGs)
+
+To understand more about SSGs, their advantages, and how to get the most from them
+with Pages, read through this series:
- [SSGs part 1: Static vs dynamic websites](https://about.gitlab.com/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/)
- [SSGs part 2: Modern static site generators](https://about.gitlab.com/2016/06/10/ssg-overview-gitlab-pages-part-2/)
- [SSGs part 3: Build any SSG site with GitLab Pages](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/)
-_Blog posts for securing GitLab Pages custom domains with SSL/TLS certificates:_
+### GitLab Pages with SSL/TLS certificates
+
+If you're using GitLab Pages default domain (`.gitlab.io`), your website will be
+automatically secure and available under HTTPS. If you're using your own domain, you can
+optionally secure it with SSL/TLS certificates. You can read the following
+tutorials to learn how to use these third-party certificates with GitLab Pages:
- [CloudFlare](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/)
-- [Let's Encrypt](https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/) (outdated)
+- [Let's Encrypt](https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/) (mind that although this article is out-of-date, it can still be useful to guide you through the basic steps)
## Advanced use
+There are quite some great examples of GitLab Pages websites built for some
+specific reasons. These examples can teach you some advanced techniques
+to use and adapt to your own needs:
+
- [Posting to your GitLab Pages blog from iOS](https://about.gitlab.com/2016/08/19/posting-to-your-gitlab-pages-blog-from-ios/)
- [GitLab CI: Run jobs sequentially, in parallel, or build a custom pipeline](https://about.gitlab.com/2016/07/29/the-basics-of-gitlab-ci/)
- [GitLab CI: Deployment & environments](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/)
@@ -80,10 +189,9 @@ _Blog posts for securing GitLab Pages custom domains with SSL/TLS certificates:_
Enable and configure GitLab Pages on your own instance (GitLab Community Edition and Enterprise Editions) with
the [admin guide](../../../administration/pages/index.md).
-**Watch the video: https://www.youtube.com/watch?v=dD8c7WNcc6s**
+**<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> Watch a [video tutorial](https://www.youtube.com/watch?v=dD8c7WNcc6s) for getting started with GitLab Pages admin!**
## More information about GitLab Pages
-- For an overview, visit the [feature webpage](https://about.gitlab.com/features/pages/)
- Announcement (2016-12-24): ["We're bringing GitLab Pages to CE"](https://about.gitlab.com/2016/12/24/were-bringing-gitlab-pages-to-community-edition/)
- Announcement (2017-03-06): ["We are changing the IP of GitLab Pages on GitLab.com"](https://about.gitlab.com/2017/03/06/we-are-changing-the-ip-of-gitlab-pages-on-gitlab-com/)
diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md
index fe4d15adfa1..ed049e2e648 100644
--- a/doc/user/project/pages/introduction.md
+++ b/doc/user/project/pages/introduction.md
@@ -441,6 +441,48 @@ The rest of the guide still applies.
See also: [GitLab Pages from A to Z: Part 1 - Static sites and GitLab Pages domains](getting_started_part_one.md#gitlab-pages-domain).
+## GitLab Pages access control **[CORE ONLY]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/33422) in GitLab 11.5.
+
+NOTE: **Note:**
+GitLab Pages access control is not activated on GitLab.com. You can check its
+progress on the
+[infrastructure issue tracker](https://gitlab.com/gitlab-com/gl-infra/infrastructure/issues/5576).
+
+You can enable Pages access control on your project, so that only
+[members of your project](../../permissions.md#project-members-permissions)
+(at least Guest) can access your website:
+
+1. Navigate to your project's **Settings > General > Permissions**.
+1. Toggle the **Pages** button to enable the access control.
+
+ NOTE: **Note:**
+ If you don't see the toggle button, that means that it's not enabled.
+ Ask your administrator to [enable it](../../../administration/pages/index.md#access-control).
+
+1. The Pages access control dropdown allows you to set who can view pages hosted
+ with GitLab Pages, depending on your project's visibility:
+
+ - If your project is private:
+ - **Only project members**: Only project members will be able to browse the website.
+ - **Everyone**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
+ - If your project is internal:
+ - **Only project members**: Only project members will be able to browse the website.
+ - **Everyone with access**: Everyone logged into GitLab will be able to browse the website, no matter their project membership.
+ - **Everyone**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
+ - If your project is public:
+ - **Only project members**: Only project members will be able to browse the website.
+ - **Everyone with access**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership.
+
+1. Click **Save changes**.
+
+---
+
+The next time someone tries to access your website and the access control is
+enabled, they will be presented with a page to sign into GitLab and verify they
+can access the website.
+
## Limitations
When using Pages under the general domain of a GitLab instance (`*.example.io`),
diff --git a/doc/user/project/pipelines/job_artifacts.md b/doc/user/project/pipelines/job_artifacts.md
index fc3970e2014..a8b47558c99 100644
--- a/doc/user/project/pipelines/job_artifacts.md
+++ b/doc/user/project/pipelines/job_artifacts.md
@@ -151,6 +151,20 @@ For example:
https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/artifacts/master/browse?job=coverage
```
+There is also a URL to specific files, including html files that
+are shown in [GitLab Pages](../../../administration/pages/index.md):
+
+```
+https://example.com/<namespace>/<project>/-/jobs/artifacts/<ref>/file/<path>?job=<job_name>
+```
+
+For example, when a job `coverage` creates the artifact `htmlcov/index.html`,
+you can access it at:
+
+```
+https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/artifacts/master/file/htmlcov/index.html?job=coverage
+```
+
The latest builds are also exposed in the UI in various places. Specifically,
look for the download button in:
diff --git a/doc/user/project/pipelines/schedules.md b/doc/user/project/pipelines/schedules.md
index 9daacc37994..051277dfe02 100644
--- a/doc/user/project/pipelines/schedules.md
+++ b/doc/user/project/pipelines/schedules.md
@@ -83,12 +83,12 @@ The next time a pipeline is scheduled, your credentials will be used.
![Schedules list](img/pipeline_schedules_ownership.png)
-> **Note:**
-When the owner of the schedule doesn't have the ability to create pipelines
-anymore, due to e.g., being blocked or removed from the project, or lacking
-the permission to run on protected branches or tags. When this happened, the
-schedule is deactivated. Another user can take ownership and activate it, so
-the schedule can be run again.
+NOTE: **Note:**
+If the owner of a pipeline schedule doesn't have the ability to create pipelines
+on the target branch, the schedule will stop creating new pipelines. This can
+happen if, for example, the owner is blocked or removed from the project, or
+the target branch or tag is protected. In this case, someone with sufficient
+privileges must take ownership of the schedule.
## Advanced admin configuration
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
index 9ad9155258f..85a03d125dd 100644
--- a/doc/user/project/quick_actions.md
+++ b/doc/user/project/quick_actions.md
@@ -1,48 +1,85 @@
# GitLab quick actions
-Quick actions are textual shortcuts for common actions on issues, merge requests
-or commits that are usually done by clicking buttons or dropdowns in GitLab's UI.
-You can enter these commands while creating a new issue or merge request, and
-in comments. Each command should be on a separate line in order to be properly
-detected and executed. The commands are removed from the issue, merge request or
-comment body before it is saved and will not be visible to anyone else.
-
-Below is a list of all of the available commands and descriptions about what they
-do.
-
-| Command | Action |
-|:---------------------------|:-------------|
-| `/close` | Close the issue or merge request |
-| `/reopen` | Reopen the issue or merge request |
-| `/merge` | Merge (when pipeline succeeds) |
-| `/title <New title>` | Change title |
-| `/assign @username` | Assign |
-| `/unassign` | Remove assignee |
-| `/milestone %milestone` | Set milestone |
-| `/remove_milestone` | Remove milestone |
-| `/label ~foo ~"bar baz"` | Add label(s) |
-| `/unlabel ~foo ~"bar baz"` | Remove all or specific label(s) |
-| `/relabel ~foo ~"bar baz"` | Replace all label(s) |
-| `/todo` | Add a todo |
-| `/done` | Mark todo as done |
-| `/subscribe` | Subscribe |
-| `/unsubscribe` | Unsubscribe |
-| <code>/due &lt;in 2 days &#124; this Friday &#124; December 31st&gt;</code> | Set due date |
-| `/remove_due_date` | Remove due date |
-| `/wip` | Toggle the Work In Progress status |
-| <code>/estimate &lt;1w 3d 2h 14m&gt;</code> | Set time estimate |
-| `/remove_estimate` | Remove estimated time |
-| <code>/spend &lt;time(1h 30m &#124; -1h 5m)&gt; &lt;date(YYYY-MM-DD)&gt;</code> | Add or subtract spent time; optionally, specify the date that time was spent on |
-| `/remove_time_spent` | Remove time spent |
-| `/target_branch <Branch Name>` | Set target branch for current merge request |
-| `/award :emoji:` | Toggle award for :emoji: |
-| `/board_move ~column` | Move issue to column on the board |
-| `/duplicate #issue` | Closes this issue and marks it as a duplicate of another issue |
-| `/move path/to/project` | Moves issue to another project |
-| `/tag v1.2.3 <message>` | Tags a commit with a given tag name and optional message |
-| `/tableflip` | Append the comment with `(╯°□°)╯︵ â”»â”â”»` |
-| `/shrug` | Append the comment with `¯\_(ツ)_/¯` |
-| <code>/copy_metadata #issue &#124; !merge_request</code> | Copy labels and milestone from other issue or merge request |
-| `/confidential` | Makes the issue confidential |
-| `/lock` | Lock the discussion |
-| `/unlock` | Unlock the discussion |
+Quick actions are textual shortcuts for common actions on issues, epics, merge requests,
+and commits that are usually done by clicking buttons or dropdowns in GitLab's UI.
+You can enter these commands while creating a new issue or merge request, or
+in comments of issues, epics, merge requests, and commits. Each command should be
+on a separate line in order to be properly detected and executed. Once executed,
+the commands are removed from the text body and not visible to anyone else.
+
+## Quick actions for issues and merge requests
+
+The following quick actions are applicable to both issues and merge requests threads,
+discussions, and descriptions:
+
+| Command | Action | Issue | Merge request |
+|:---------------------------|:------------------------------ |:------|:--------------|
+| `/tableflip <Comment>` | Append the comment with `(╯°□°)╯︵ â”»â”â”»` | ✓ | ✓ |
+| `/shrug <Comment>` | Append the comment with `¯\_(ツ)_/¯` | ✓ | ✓ |
+| `/todo` | Add a todo | ✓ | ✓ |
+| `/done` | Mark todo as done | ✓ | ✓ |
+| `/subscribe` | Subscribe | ✓ | ✓ |
+| `/unsubscribe` | Unsubscribe | ✓ | ✓ |
+| `/close` | Close | ✓ | ✓ |
+| `/reopen` | Reopen | ✓ | ✓ |
+| `/title <New title>` | Change title | ✓ | ✓ |
+| `/award :emoji:` | Toggle emoji award | ✓ | ✓ |
+| `/assign me` | Assign yourself | ✓ | ✓ |
+| `/assign @user` | Assign one user | ✓ | ✓ |
+| `/assign @user1 @user2` | Assign multiple users **[STARTER]** | ✓ | |
+| `/unassign` | Remove assignee(s) | ✓ | ✓ |
+| `/reassign @user1 @user2` | Change assignee | ✓ | ✓ |
+| `/milestone %milestone` | Set milestone | ✓ | ✓ |
+| `/remove_milestone` | Remove milestone | ✓ | ✓ |
+| `/label ~label1 ~label2` | Add label(s) | ✓ | ✓ |
+| `/unlabel ~label1 ~label2` | Remove all or specific label(s)| ✓ | ✓ |
+| `/relabel ~label1 ~label2` | Replace label | ✓ | ✓ |
+| <code>/copy_metadata #issue &#124; !merge_request</code> | Copy labels and milestone from other issue or merge request | ✓ | ✓ |
+| <code>/estimate &lt;1w 3d 2h 14m&gt;</code> | Set time estimate | ✓ | ✓ |
+| `/remove_estimate` | Remove time estimate | ✓ | ✓ |
+| <code>/spend &lt;time(1h 30m &#124; -1h 5m)&gt; &lt;date(YYYY-MM-DD)&gt;</code> | Add or subtract spent time; optionally, specify the date that time was spent on | ✓ | ✓ |
+| `/remove_time_spent` | Remove time spent | ✓ | ✓ |
+| `/lock` | Lock the discussion | ✓ | ✓ |
+| `/unlock` | Unlock the discussion | ✓ | ✓ |
+| <code>/due &lt;in 2 days &#124; this Friday &#124; December 31st&gt;</code>| Set due date | ✓ | |
+| `/remove_due_date` | Remove due date | ✓ | |
+| `/weight 0,1,2, ...` | Set weight **[STARTER]** | ✓ | |
+| `/clear_weight` | Clears weight **[STARTER]** | ✓ | |
+| `/epic <group&epic &#124; Epic URL>` | Add to epic **[ULTIMATE]** | ✓ | |
+| `/remove_epic` | Removes from epic **[ULTIMATE]** | ✓ | |
+| `/confidential` | Make confidential | ✓ | |
+| `/duplicate #issue` | Mark this issue as a duplicate of another issue | ✓ |
+| `/move path/to/project` | Move this issue to another project | ✓ | |
+| `/target_branch <Local branch Name>` | Set target branch | | ✓ |
+| `/wip` | Toggle the Work In Progress status | | ✓ |
+| `/merge` | Merge (when pipeline succeeds) | | ✓ |
+| `/create_merge_request <branch name>` | Create a new merge request starting from the current issue | ✓ | |
+
+
+## Quick actions for commit messages
+
+The following quick actions are applicable for commit messages:
+
+| Command | Action |
+|:------------------------|:------------------------------------------|
+| `/tag v1.2.3 <message>` | Tags this commit with an optional message |
+
+## Quick actions for Epics **[ULTIMATE]**
+
+The following quick actions are applicable for epics threads and description:
+
+| Command | Action |
+|:---------------------------|:----------------------------------------|
+| `/tableflip <Comment>` | Append the comment with `(╯°□°)╯︵ â”»â”â”»` |
+| `/shrug <Comment>` | Append the comment with `¯\_(ツ)_/¯` |
+| `/todo` | Add a todo |
+| `/done` | Mark todo as done |
+| `/subscribe` | Subscribe |
+| `/unsubscribe` | Unsubscribe |
+| `/close` | Close |
+| `/reopen` | Reopen |
+| `/title <New title>` | Change title |
+| `/award :emoji:` | Toggle emoji award |
+| `/label ~label1 ~label2` | Add label(s) |
+| `/unlabel ~label1 ~label2` | Remove all or specific label(s) |
+| `/relabel ~label1 ~label2` | Replace label |
diff --git a/doc/user/project/repository/branches/img/branch_filter_search_box.png b/doc/user/project/repository/branches/img/branch_filter_search_box.png
new file mode 100644
index 00000000000..c4364ef39f4
--- /dev/null
+++ b/doc/user/project/repository/branches/img/branch_filter_search_box.png
Binary files differ
diff --git a/doc/user/project/repository/branches/index.md b/doc/user/project/repository/branches/index.md
index 19417d91fec..783081cec26 100644
--- a/doc/user/project/repository/branches/index.md
+++ b/doc/user/project/repository/branches/index.md
@@ -6,6 +6,7 @@ Read through GiLab's branching documentation:
- [Default branch](#default-branch)
- [Protected branches](../../protected_branches.md#protected-branches)
- [Delete merged branches](#delete-merged-branches)
+- [Branch filter search box](#branch-filter-search-box)
See also:
@@ -29,16 +30,30 @@ to learn more.
## Delete merged branches
-> [Introduced][ce-6449] in GitLab 8.14.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6449) in GitLab 8.14.
![Delete merged branches](img/delete_merged_branches.png)
This feature allows merged branches to be deleted in bulk. Only branches that
-have been merged and [are not protected][protected] will be deleted as part of
+have been merged and [are not protected](../../protected_branches.md) will be deleted as part of
this operation.
It's particularly useful to clean up old branches that were not deleted
automatically when a merge request was merged.
-[ce-6449]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6449 "Add button to delete all merged branches"
-[protected]: ../../protected_branches.md
+
+## Branch filter search box
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22166) in GitLab 11.5.
+
+![Branch filter search box](img/branch_filter_search_box.png)
+
+This feature allows you to search and select branches quickly. Search results appear in the following order:
+
+- Branches with names that matched search terms exactly.
+- Other branches with names that include search terms, sorted alphabetically.
+
+Sometimes when you have hundreds of branches you may want a more flexible matching pattern. In such cases you can use the following:
+
+- `^feature` will only match branch names that begin with 'feature'.
+- `feature$` will only match branch names that end with 'feature'.
diff --git a/doc/user/project/repository/gpg_signed_commits/index.md b/doc/user/project/repository/gpg_signed_commits/index.md
index 4f076ee01b8..c6239c8e41c 100644
--- a/doc/user/project/repository/gpg_signed_commits/index.md
+++ b/doc/user/project/repository/gpg_signed_commits/index.md
@@ -57,7 +57,7 @@ started:
gpg --full-gen-key
```
-_NOTE: In some cases like Gpg4win on Windows and other Mac OS versions the command here may be ` gpg --gen-key`_
+ _NOTE: In some cases like Gpg4win on Windows and other Mac OS versions the command here may be ` gpg --gen-key`_
This will spawn a series of questions.
diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md
index 1c3915a5fdd..1710bba2fd0 100644
--- a/doc/user/project/repository/index.md
+++ b/doc/user/project/repository/index.md
@@ -53,6 +53,46 @@ To get started with the command line, please read through the
Use GitLab's [file finder](../../../workflow/file_finder.md) to search for files in a repository.
+### Supported markup languages and extensions
+
+GitLab supports a number of markup languages (sometimes called [lightweight
+markup languages](https://en.wikipedia.org/wiki/Lightweight_markup_language))
+that you can use for the content of your files in a repository. They are mostly
+used for documentation purposes.
+
+Just pick the right extension for your files and GitLab will render them
+according to the markup language.
+
+| Markup language | Extensions |
+| --------------- | ---------- |
+| Plain text | `txt` |
+| [Markdown](../../markdown.md) | `mdown`, `mkd`, `mkdn`, `md`, `markdown` |
+| [reStructuredText](http://docutils.sourceforge.net/rst.html) | `rst` |
+| [Asciidoc](https://asciidoctor.org/docs/what-is-asciidoc/) | `adoc`, `ad`, `asciidoc` |
+| [Textile](https://txstyle.org/) | `textile` |
+| [rdoc](http://rdoc.sourceforge.net/doc/index.html) | `rdoc` |
+| [Orgmode](https://orgmode.org/) | `org` |
+| [creole](http://www.wikicreole.org/) | `creole` |
+| [Mediawiki](https://www.mediawiki.org/wiki/MediaWiki) | `wiki`, `mediawiki` |
+
+### Repository README and index files
+
+When a `README` or `index` file is present in a repository, its contents will be
+automatically pre-rendered by GitLab without opening it.
+
+They can either be plain text or have an extension of a
+[supported markup language](#supported-markup-languages-and-extensions):
+
+Some things to note about precedence:
+
+1. When both a `README` and an `index` file are present, the `README` will always
+ take precedence.
+1. When more than one file is present with different extensions, they are
+ ordered alphabetically, with the exception of a file without an extension
+ which will always be last in precedence. For example, `README.adoc` will take
+ precedence over `README.md`, and `README.rst` will take precedence over
+ `README`.
+
### Jupyter Notebook files
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/2508) in GitLab 9.1
@@ -85,12 +125,13 @@ You can live preview changes submitted to a new branch with
With [GitLab Starter](https://about.gitlab.com/pricing/), you can also request
[approval](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html) from your managers.
-To create, delete, and [branches](branches/index.md) via GitLab's UI:
+To create, delete, and view [branches](branches/index.md) via GitLab's UI:
- [Default branches](branches/index.md#default-branch)
- [Create a branch](web_editor.md#create-a-new-branch)
- [Protected branches](../protected_branches.md#protected-branches)
- [Delete merged branches](branches/index.md#delete-merged-branches)
+- [Branch filter search box](branches/index.md#branch-filter-search-box)
Alternatively, you can use the
[command line](../../../gitlab-basics/start-using-git.md#create-a-branch).
@@ -158,16 +199,22 @@ Find it under your project's **Repository > Graph**.
## Repository Languages
For the default branch of each repository, GitLab will determine what programming languages
-were used and display this on the projects pages.
+were used and display this on the projects pages. If this information is missing, it will
+be added after updating the default branch on the project. This process can take up to 5
+minutes.
![Repository Languages bar](img/repository_languages.png)
-Not all files are detected, among others; documentation,
-vendored code, and most markup languages are excluded.
+Not all files are detected, among others; documentation,
+vendored code, and most markup languages are excluded. This behaviour can be
+adjusted by overriding the default. For example, to enable `.proto` files to be
+detected, add the following to `.gitattributes` in the root of your repository.
+
+> *.proto linguist-detectable=true
## Compare
-Select branches to compare and view the changes inline:
+Select branches to compare using the [branch filter search box](branches/index.md#branch-filter-search-box), then click the **Compare** button to view the changes inline:
![compare branches](img/compare_branches.png)
diff --git a/doc/user/project/settings/img/sharing_and_permissions_settings.png b/doc/user/project/settings/img/sharing_and_permissions_settings.png
index f5e3e32f95c..6cb89c6ea1d 100644
--- a/doc/user/project/settings/img/sharing_and_permissions_settings.png
+++ b/doc/user/project/settings/img/sharing_and_permissions_settings.png
Binary files differ
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index 084d1161633..d6754372816 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -18,6 +18,8 @@ Adjust your project's name, description, avatar, [default branch](../repository/
![general project settings](img/general_settings.png)
+The project description also partially supports [standard markdown](../../markdown.md#standard-markdown). You can use [emphasis](../../markdown.md#emphasis), [links](../../markdown.md#links), and [line-breaks](../../markdown.md#line-breaks) to add more context to the project description.
+
### Sharing and permissions
Set up your project's access, [visibility](../../../public_access/public_access.md), and enable [Container Registry](../container_registry.md) for your projects:
diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md
index 9429b1268f0..e6b1f6b6aae 100644
--- a/doc/user/project/web_ide/index.md
+++ b/doc/user/project/web_ide/index.md
@@ -22,6 +22,27 @@ searching. The file finder is launched using the keyboard shortcut `Command-p`,
`Control-p`, or `t` (when editor is not in focus). Type the filename or
file path fragments to start seeing results.
+## Syntax highligting
+
+As expected from an IDE, syntax highlighting for many languages within
+the Web IDE will make your direct editing even easier.
+
+The Web IDE currently provides:
+
+- Basic syntax colorization for a variety of programming, scripting and markup
+languages such as XML, PHP, C#, C++, Markdown, Java, VB, Batch, Python, Ruby
+and Objective-C.
+- IntelliSense and validation support (displaying errors and warnings, providing
+smart completions, formatting, and outlining) for some languages. For example:
+TypeScript, JavaScript, CSS, LESS, SCSS, JSON and HTML.
+
+Because the Web IDE is based on the [Monaco Editor](https://microsoft.github.io/monaco-editor/),
+you can find a more complete list of supported languages in the
+[Monaco languages](https://github.com/Microsoft/monaco-languages) repository.
+
+NOTE: **Note:**
+Single file editing is based on the [Ace Editor](https://ace.c9.io).
+
## Stage and commit changes
After making your changes, click the Commit button in the bottom left to
diff --git a/doc/user/reserved_names.md b/doc/user/reserved_names.md
index 52610378ad5..45c306f5988 100644
--- a/doc/user/reserved_names.md
+++ b/doc/user/reserved_names.md
@@ -68,7 +68,6 @@ Currently the following names are reserved as top level groups:
- import
- invites
- jwt
-- koding
- notification_settings
- oauth
- profile
diff --git a/doc/user/search/img/dashboard_links.png b/doc/user/search/img/dashboard_links.png
new file mode 100644
index 00000000000..2c472c7e464
--- /dev/null
+++ b/doc/user/search/img/dashboard_links.png
Binary files differ
diff --git a/doc/user/search/img/issues_assigned_to_you.png b/doc/user/search/img/issues_assigned_to_you.png
index 36c670eedd5..d2fff5e9a67 100644
--- a/doc/user/search/img/issues_assigned_to_you.png
+++ b/doc/user/search/img/issues_assigned_to_you.png
Binary files differ
diff --git a/doc/user/search/img/issues_filter_none_any.png b/doc/user/search/img/issues_filter_none_any.png
new file mode 100644
index 00000000000..9682fc55315
--- /dev/null
+++ b/doc/user/search/img/issues_filter_none_any.png
Binary files differ
diff --git a/doc/user/search/img/left_menu_bar.png b/doc/user/search/img/left_menu_bar.png
deleted file mode 100644
index d68a71cba8e..00000000000
--- a/doc/user/search/img/left_menu_bar.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index 4f1b96b775c..78c1294346b 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -2,27 +2,27 @@
## Issues and merge requests
-To search through issues and merge requests in multiple projects, you can use the left-sidebar.
+To search through issues and merge requests in multiple projects, you can use the **Issues** or **Merge Requests** links
+in the top-right part of your screen.
-Click the menu bar, then **Issues** or **Merge Requests**, which work in the same way,
-therefore, the following notes are valid for both.
+Both of them work in the same way, therefore, the following notes are valid for both.
The number displayed on their right represents the number of issues and merge requests assigned to you.
-![menu bar - issues and MRs assigned to you](img/left_menu_bar.png)
+![issues and MRs dashboard links](img/dashboard_links.png)
When you click **Issues**, you'll see the opened issues assigned to you straight away:
![Issues assigned to you](img/issues_assigned_to_you.png)
-You can filter them by **Author**, **Assignee**, **Milestone**, and **Labels**,
-searching through **Open**, **Closed**, and **All** issues.
+You can search through **Open**, **Closed**, or **All** issues.
-Of course, you can combine all filters together.
+You can also filter the results using the search and filter field. This works in the same way as the ones found in the
+per project pages described below.
### Issues and MRs assigned to you or created by you
-You'll find a shortcut to issues and merge requests create by you or assigned to you
+You'll also find shortcuts to issues and merge requests created by you or assigned to you
on the search field on the top-right of your screen:
![shortcut to your issues and mrs](img/issues_mrs_shortcut.png)
@@ -40,6 +40,16 @@ The same process is valid for merge requests. Navigate to your project's **Merge
and click **Search or filter results...**. Merge requests can be filtered by author, assignee,
milestone, and label.
+### Filtering by **None** / **Any**
+
+Some filter fields like milestone and assignee, allow you to filter by **None** or **Any**.
+
+![filter by none any](img/issues_filter_none_any.png)
+
+Selecting **None** returns results that have an empty value for that field. E.g.: no milestone, no assignee.
+
+Selecting **Any** does the opposite. It returns results that have a non-empty value for that field.
+
### Searching for specific terms
You can filter issues and merge requests by specific terms included in titles or descriptions.
diff --git a/doc/workflow/img/repository_mirroring_force_update.png b/doc/workflow/img/repository_mirroring_force_update.png
new file mode 100644
index 00000000000..8ba715d1ba3
--- /dev/null
+++ b/doc/workflow/img/repository_mirroring_force_update.png
Binary files differ
diff --git a/doc/workflow/img/repository_mirroring_pull_settings_lower.png b/doc/workflow/img/repository_mirroring_pull_settings_lower.png
new file mode 100644
index 00000000000..a3e0b74ddf8
--- /dev/null
+++ b/doc/workflow/img/repository_mirroring_pull_settings_lower.png
Binary files differ
diff --git a/doc/workflow/img/repository_mirroring_pull_settings_upper.png b/doc/workflow/img/repository_mirroring_pull_settings_upper.png
new file mode 100644
index 00000000000..c60354fdca7
--- /dev/null
+++ b/doc/workflow/img/repository_mirroring_pull_settings_upper.png
Binary files differ
diff --git a/doc/workflow/img/repository_mirroring_push_settings.png b/doc/workflow/img/repository_mirroring_push_settings.png
new file mode 100644
index 00000000000..21a6aca4526
--- /dev/null
+++ b/doc/workflow/img/repository_mirroring_push_settings.png
Binary files differ
diff --git a/doc/workflow/lfs/lfs_administration.md b/doc/workflow/lfs/lfs_administration.md
index 444d1483fcc..ec5943fd51b 100644
--- a/doc/workflow/lfs/lfs_administration.md
+++ b/doc/workflow/lfs/lfs_administration.md
@@ -54,7 +54,7 @@ to offload local hard disk R/W operations, and free up disk space significantly.
GitLab is tightly integrated with `Fog`, so you can refer to its [documentation](http://fog.io/about/provider_documentation.html)
to check which storage services can be integrated with GitLab.
You can also use external object storage in a private local network. For example,
-[Minio](https://www.minio.io/) is a standalone object storage service, is easy to setup, and works well with GitLab instances.
+[Minio](https://www.minio.io/) is a standalone object storage service, is easy to set up, and works well with GitLab instances.
GitLab provides two different options for the uploading mechanism: "Direct upload" and "Background upload".
diff --git a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
index 9adbafee255..d02e921fa84 100644
--- a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
+++ b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
@@ -78,10 +78,10 @@ git clone git@gitlab.example.com:group/project.git
```
If you already cloned the repository and you want to get the latest LFS object
-that are on the remote repository, eg. from branch `master`:
+that are on the remote repository, eg. for a branch from origin:
```bash
-git lfs fetch master
+git lfs fetch origin master
```
## File Locking
diff --git a/doc/workflow/notifications.md b/doc/workflow/notifications.md
index 731c9209224..020aa73f809 100644
--- a/doc/workflow/notifications.md
+++ b/doc/workflow/notifications.md
@@ -10,31 +10,32 @@ You can find notification settings under the user profile.
Notification settings are divided into three groups:
-* Global Settings
-* Group Settings
-* Project Settings
+- Global settings
+- Group settings
+- Project settings
Each of these settings have levels of notification:
-* Disabled - turns off notifications
-* Participating - receive notifications from related resources
-* Watch - receive notifications from projects or groups user is a member of
-* Global - notifications as set at the global settings
-* Custom - user will receive notifications when mentioned, is participant and custom selected events.
+- Watch: Receive notifications for any activity.
+- On Mention: Receive notifications when `@mentioned` in comments.
+- Participate: Receive notifications for threads you have participated in.
+- Disabled: Turns off notifications.
+- Custom: Receive notifications for custom selected events.
+- Global: For groups and projects, notifications as per global settings.
-#### Global Settings
+### Global Settings
-Global Settings are at the bottom of the hierarchy.
+Global settings are at the bottom of the hierarchy.
Any setting set here will be overridden by a setting at the group or a project level.
Group or Project settings can use `global` notification setting which will then use
anything that is set at Global Settings.
-#### Group Settings
+### Group Settings
![notification settings](img/notification_group_settings.png)
-Group Settings are taking precedence over Global Settings but are on a level below Project or Subgroup Settings:
+Group settings are taking precedence over Global Settings but are on a level below Project or Subgroup settings:
```
Group < Subgroup < Project
@@ -46,11 +47,11 @@ Organization like this is suitable for users that belong to different groups but
same need for being notified for every group they are member of.
These settings can be configured on group page under the name of the group. It will be the dropdown with the bell icon. They can also be configured on the user profile notifications dropdown.
-#### Project Settings
+### Project Settings
![notification settings](img/notification_project_settings.png)
-Project Settings are at the top level and any setting placed at this level will take precedence of any
+Project settings are at the top level and any setting placed at this level will take precedence of any
other setting.
This is suitable for users that have different needs for notifications per project basis.
These settings can be configured on project page under the name of the project. It will be the dropdown with the bell icon. They can also be configured on the user profile notifications dropdown.
@@ -63,6 +64,8 @@ Below is the table of events users can be notified of:
|------------------------------|-------------------------------------------------------------------|------------------------------|
| New SSH key added | User | Security email, always sent. |
| New email added | User | Security email, always sent. |
+| Email changed | User | Security email, always sent. |
+| Password changed | User | Security email, always sent. |
| New user created | User | Sent on user creation, except for omniauth (LDAP)|
| User added to project | User | Sent when user is added to project |
| Project access level changed | User | Sent when user project access level is changed |
@@ -73,11 +76,12 @@ Below is the table of events users can be notified of:
### Issue / Merge request events
In most of the below cases, the notification will be sent to:
+
- Participants:
- the author and assignee of the issue/merge request
- authors of comments on the issue/merge request
- anyone mentioned by `@username` in the issue/merge request title or description
- - anyone mentioned by `@username` in any of the comments on the issue/merge request
+ - anyone mentioned by `@username` in any of the comments on the issue/merge request
...with notification level "Participating" or higher
- Watchers: users with notification level "Watch"
- Subscribers: anyone who manually subscribed to the issue/merge request
@@ -90,12 +94,16 @@ In most of the below cases, the notification will be sent to:
| Reassign issue | The above, plus the old assignee |
| Reopen issue | |
| Due issue | Participants and Custom notification level with this event selected |
+| Change milestone issue | Subscribers, participants mentioned, and Custom notification level with this event selected |
+| Remove milestone issue | Subscribers, participants mentioned, and Custom notification level with this event selected |
| New merge request | |
| Push to merge request | Participants and Custom notification level with this event selected |
| Reassign merge request | The above, plus the old assignee |
| Close merge request | |
| Reopen merge request | |
| Merge merge request | |
+| Change milestone merge request | Subscribers, participants mentioned, and Custom notification level with this event selected |
+| Remove milestone merge request | Subscribers, participants mentioned, and Custom notification level with this event selected |
| New comment | The above, plus anyone mentioned by `@username` in the comment, with notification level "Mention" or higher |
| Failed pipeline | The author of the pipeline |
| Successful pipeline | The author of the pipeline, if they have the custom notification setting for successful pipelines set |
@@ -129,16 +137,19 @@ Notification emails include headers that provide extra content about the notific
| X-GitLab-NotificationReason | The reason for being notified. "mentioned", "assigned", etc |
#### X-GitLab-NotificationReason
+
This header holds the reason for the notification to have been sent out,
where reason can be `mentioned`, `assigned`, `own_activity`, etc.
Only one reason is sent out according to its priority:
+
- `own_activity`
- `assigned`
- `mentioned`
-The reason in this header will also be shown in the footer of the notification email. For example an email with the
+The reason in this header will also be shown in the footer of the notification email. For example an email with the
reason `assigned` will have this sentence in the footer:
`"You are receiving this email because you have been assigned an item on {configured GitLab hostname}"`
-**Note: Only reasons listed above have been implemented so far**
-Further implementation is [being discussed here](https://gitlab.com/gitlab-org/gitlab-ce/issues/42062)
+NOTE: **Note:**
+Only reasons listed above have been implemented so far.
+Further implementation is [being discussed](https://gitlab.com/gitlab-org/gitlab-ce/issues/42062).
diff --git a/doc/workflow/repository_mirroring.md b/doc/workflow/repository_mirroring.md
index 8c4e6ea8eab..e259e6fe50c 100644
--- a/doc/workflow/repository_mirroring.md
+++ b/doc/workflow/repository_mirroring.md
@@ -1,351 +1,399 @@
# Repository mirroring
-Repository mirroring is a way to mirror repositories from external sources.
-It can be used to mirror all branches, tags, and commits that you have
-in your repository.
+Repository mirroring allows for mirroring of repositories to and from external sources. It can be
+used to mirror branches, tags, and commits between repositories.
-Your mirror at GitLab will be updated automatically. You can
-also manually trigger an update at most once every 5 minutes.
+A repository mirror at GitLab will be updated automatically. You can also manually trigger an update
+at most once every 5 minutes.
## Overview
-Repository mirroring is very useful when, for some reason, you must use a
-project from another source.
+Repository mirroring is useful when you want to use a repository outside of GitLab.
-There are two kinds of repository mirroring features supported by GitLab:
-**push** and **pull**, the latter being only available in GitLab Enterprise Edition.
-The **push** method mirrors the repository in GitLab to another location.
+There are two kinds of repository mirroring supported by GitLab:
-Once the mirror repository is updated, all new branches,
-tags, and commits will be visible in the project's activity feed.
-Users with at least [developer access][perms] to the project can also force an
-immediate update with the click of a button. This button will not be available if
-the mirror is already being updated or 5 minutes still haven't passed since its last update.
+- Push: for mirroring a GitLab repository to another location.
+- Pull: for mirroring a repository from another location to GitLab. **[STARTER]**
-A few things/limitations to consider:
+When the mirror repository is updated, all new branches, tags, and commits will be visible in the
+project's activity feed.
-- The repository must be accessible over `http://`, `https://`, `ssh://` or `git://`.
-- If your HTTP repository is not publicly accessible, add authentication
- information to the URL, like: `https://username@gitlab.company.com/group/project.git`.
- In some cases, you might need to use a personal access token instead of a
- password, e.g., you want to mirror to GitHub and have 2FA enabled.
-- The import will time out after 15 minutes. For repositories that take longer
- use a clone/push combination.
-- The Git LFS objects will not be synced. You'll need to push/pull them
- manually.
+Users with at least [developer access](../user/permissions.md) to the project can also force an
+immediate update, unless:
+
+- The mirror is already being updated.
+- 5 minutes haven't elapsed since its last update.
## Use cases
-- You migrated to GitLab but still need to keep your project in another source.
- In that case, you can simply set it up to mirror to GitLab (pull) and all the
- essential history of commits, tags and branches will be available in your
- GitLab instance.
-- You have old projects in another source that you don't use actively anymore,
- but don't want to remove for archiving purposes. In that case, you can create
- a push mirror so that your active GitLab repository can push its changes to the
- old location.
+The following are some possible use cases for repository mirroring:
-## Pulling from a remote repository **[STARTER]**
+- You migrated to GitLab but still need to keep your project in another source. In that case, you
+ can simply set it up to mirror to GitLab (pull) and all the essential history of commits, tags,
+ and branches will be available in your GitLab instance. **[STARTER]**
+- You have old projects in another source that you don't use actively anymore, but don't want to
+ remove for archiving purposes. In that case, you can create a push mirror so that your active
+ GitLab repository can push its changes to the old location.
->[Introduced][ee-51] in GitLab Enterprise Edition 8.2.
+## Pushing to a remote repository **[CORE]**
-You can set up a repository to automatically have its branches, tags, and commits
-updated from an upstream repository. This is useful when a repository you're
-interested in is located on a different server, and you want to be able to
-browse its content and its activity using the familiar GitLab interface.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/249) in GitLab Enterprise
+> Edition 8.7. [Moved to GitLab Core](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18715) in 10.8.
-When creating a new project, you can enable repository mirroring when you choose
-to import the repository from "Any repo by URL". Enter the full URL of the Git
-repository to pull from and click on the **Mirror repository** checkbox.
+For an existing project, you can set up push mirroring as follows:
-![New project](repository_mirroring/repository_mirroring_new_project.png)
+1. Navigate to your project's **Settings > Repository** and expand the **Mirroring repositories** section.
+1. Enter a repository URL.
+1. Select **Push** from the **Mirror direction** dropdown.
+1. Select an authentication method from the **Authentication method** dropdown, if necessary.
+1. Check the **Only mirror protected branches** box, if necessary.
+1. Click the **Mirror repository** button to save the configuration.
-For an existing project, you can set up mirror pulling by visiting your project's
-**Settings âž” Repository** and searching for the "Pull from a remote repository"
-section. Check the "Mirror repository" box and hit **Save changes** at the bottom.
-You have a few options to choose from one being the user who will be the author
-of all events in the activity feed that are the result of an update. This user
-needs to have at least [master access][perms] to the project. Another option is
-whether you want to trigger builds for mirror updates.
+![Repository mirroring push settings screen](img/repository_mirroring_push_settings.png)
-![Pull settings](repository_mirroring/repository_mirroring_pull_settings.png)
+When push mirroring is enabled, only push commits directly to the mirrored repository to prevent the
+mirror diverging. All changes will end up in the mirrored repository whenever:
-Since the repository on GitLab functions as a mirror of the upstream repository,
-you are advised not to push commits directly to the repository on GitLab.
-Instead, any commits should be pushed to the upstream repository, and will end
-up in the GitLab repository automatically within a certain period of time
-or when a [forced update](#forcing-an-update) is initiated.
+- Commits are pushed to GitLab.
+- A [forced update](#forcing-an-update) is initiated.
-If you do manually update a branch in the GitLab repository, the branch will
-become diverged from upstream, and GitLab will no longer automatically update
-this branch to prevent any changes from being lost.
+Changes pushed to files in the repository are automatically pushed to the remote mirror at least:
-![Diverged branch](repository_mirroring/repository_mirroring_diverged_branch.png)
+- Within five minutes of being received.
+- Within one minute if **Only mirror protected branches** is enabled.
-### Trigger update using API **[STARTER]**
+In the case of a diverged branch, you will see an error indicated at the **Mirroring repositories**
+section.
->[Introduced][ee-3453] in GitLab Enterprise Edition 10.3.
+### Push only protected branches **[CORE]**
-Pull mirroring uses polling to detect new branches and commits added upstream,
-often many minutes afterwards. If you notify GitLab by [API][pull-api], updates
-will be pulled immediately.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3350) in
+> [GitLab Starter](https://about.gitlab.com/pricing/) 10.3. [Moved to GitLab Core](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18715) in 10.8.
-Read the [Pull Mirror Trigger API docs][pull-api].
+You can choose to only push your protected branches from GitLab to your remote repository.
-### Pull only protected branches **[STARTER]**
+To use this option, check the **Only mirror protected branches** box when creating a repository
+mirror.
->[Introduced][ee-3326] in GitLab Enterprise Edition 10.3.
+## Setting up a push mirror from GitLab to GitHub **[CORE]**
-You can choose to only pull the protected branches from your remote repository to GitLab.
+To set up a mirror from GitLab to GitHub, you need to follow these steps:
-To use this option go to your project's repository settings page under pull mirror.
+1. Create a [GitHub personal access token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/) with the `public_repo` box checked.
+1. Fill in the **Git repository URL** field, with the personal access token instead of a password.
+ For example: `https://<GitHubUsername>:<GitHubPersonalAccessToken>@github.com/group/project.git`.
+1. Click the **Mirror repository** button.
+1. Wait, or click the update button.
-### Overwrite diverged branches **[STARTER]**
+## Pulling from a remote repository **[STARTER]**
->[Introduced][ee-4559] in GitLab Enterprise Edition 10.6.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/51) in GitLab Enterprise Edition 8.2.
-You can choose to always update your local branch with the remote version even
-if your local version has diverged from the remote.
+You can set up a repository to automatically have its branches, tags, and commits updated from an
+upstream repository.
-To use this option go to your project's repository settings page under pull mirror.
+This is useful when a repository you're interested in is located on a different server, and you want
+to be able to browse its content and its activity using the familiar GitLab interface.
-### Hard failure **[STARTER]**
+To configure mirror pulling for an existing project:
->[Introduced][ee-3117] in GitLab Enterprise Edition 10.2.
+1. Navigate to your project's **Settings > Repository** and expand the **Mirroring repositories**
+ section.
+1. Enter a repository URL.
+1. Select **Pull** from the **Mirror direction** dropdown.
+1. Select an authentication method from the **Authentication method** dropdown, if necessary.
+1. If necessary, check the following boxes:
+ - **Overwrite diverged branches**.
+ - **Trigger pipelines for mirror updates**.
+ - **Only mirror protected branches**.
+1. Click the **Mirror repository** button to save the configuration.
-Once a mirror gets retried 14 times in a row, it will get marked as hard failed,
-this will become visible in either the project main dashboard or in the
-pull mirror settings page.
+![Repository mirroring pull settings screen - upper part](img/repository_mirroring_pull_settings_upper.png)
-![Hard failed mirror main notice](repository_mirroring/repository_mirroring_hard_failed_main.png)
+---
-![Hard failed mirror settings notice](repository_mirroring/repository_mirroring_hard_failed_settings.png)
+![Repository mirroring pull settings screen - lower part](img/repository_mirroring_pull_settings_lower.png)
-When a project is hard failed, it will no longer get picked up for mirroring.
-A user can resume the project mirroring again by either [forcing an update](#forcing-an-update)
-or by changing the import URL in repository settings.
+Because GitLab is now set to pull changes from the upstream repository, you should not push commits
+directly to the repository on GitLab. Instead, any commits should be pushed to the upstream repository.
+Changes pushed to the upstream repository will be pulled into the GitLab repository, either:
-### SSH authentication **[STARTER]**
+- Automatically within a certain period of time.
+- When a [forced update](#forcing-an-update) is initiated.
-> [Introduced][ee-2551] in GitLab Starter 9.5
+CAUTION: **Caution:**
+If you do manually update a branch in the GitLab repository, the branch will become diverged from
+upstream and GitLab will no longer automatically update this branch to prevent any changes from being lost.
-If you're mirroring over SSH (i.e., an `ssh://` URL), you can authenticate using
-password-based authentication, just as over HTTPS, but you can also use public
-key authentication. This is often more secure than password authentication,
-especially when the source repository supports [Deploy Keys][deploy-key].
+### How it works
-To get started, navigate to **Settings âž” Repository âž” Pull from a remote repository**,
-enable mirroring (if not already enabled) and enter an `ssh://` URL.
+Once you activate the pull mirroring feature, the mirror will be inserted into a queue. A scheduler
+will start every minute and schedule a fixed number of mirrors for update, based on the configured maximum capacity.
-> **NOTE**: SCP-style URLs, e.g., `git@example.com:group/project.git`, are not
-supported at this time.
+If the mirror updates successfully, it will be enqueued once again with a small backoff period.
-Entering the URL adds two features to the page - `Fingerprints` and
-`SSH public key authentication`:
+If the mirror fails (for example, a branch diverged from upstream), the project's backoff period is
+increased each time it fails, up to a maximum amount of time.
-![Pull settings for SSH](repository_mirroring/repository_mirroring_pull_settings_for_ssh.png)
+### SSH authentication
-SSH authentication is mutual. You have to prove to the server that you're
-allowed to access the repository, but the server also has to prove to *you* that
-it's who it claims to be. You provide your credentials as a password or public
-key. The server that the source repository resides on provides its credentials
-as a "host key", the fingerprint of which needs to be verified manually.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2551) for Push mirroring in [GitLab Starter](https://about.gitlab.com/pricing/) 9.5.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22982) for Pull mirroring in [GitLab Core](https://about.gitlab.com/pricing/) 11.6
-Press the `Detect host keys` button. GitLab will fetch the host keys from the
-server, and display the fingerprints to you:
+SSH authentication is mutual:
-![Detect SSH host keys](repository_mirroring/repository_mirroring_detect_host_keys.png)
+- You have to prove to the server that you're allowed to access the repository.
+- The server also has to prove to *you* that it's who it claims to be.
-You now need to verify that the fingerprints are those you expect. GitLab.com
-and other code hosting sites publish their fingerprints in the open for you
-to check:
+You provide your credentials as a password or public key. The server that the
+other repository resides on provides its credentials as a "host key", the
+fingerprint of which needs to be verified manually.
-* [AWS CodeCommit](http://docs.aws.amazon.com/codecommit/latest/userguide/regions.html#regions-fingerprints)
-* [Bitbucket](https://confluence.atlassian.com/bitbucket/use-the-ssh-protocol-with-bitbucket-cloud-221449711.html#UsetheSSHprotocolwithBitbucketCloud-KnownhostorBitbucket%27spublickeyfingerprints)
-* [GitHub](https://help.github.com/articles/github-s-ssh-key-fingerprints/)
-* [GitLab.com](https://about.gitlab.com/gitlab-com/settings/#ssh-host-keys-fingerprints)
-* [Launchpad](https://help.launchpad.net/SSHFingerprints)
-* [Savannah](http://savannah.gnu.org/maintenance/SshAccess/)
-* [SourceForge](https://sourceforge.net/p/forge/documentation/SSH%20Key%20Fingerprints/)
+If you're mirroring over SSH (that is, using an `ssh://` URL), you can authenticate using:
-Other providers will vary. If you're running on-premises GitLab, or otherwise
-have access to the source server, you can securely gather the key fingerprints:
+- Password-based authentication, just as over HTTPS.
+- Public key authentication. This is often more secure than password authentication,
+ especially when the other repository supports [Deploy Keys](../ssh/README.md#deploy-keys).
-```
-$ cat /etc/ssh/ssh_host*pub | ssh-keygen -E md5 -l -f -
-256 MD5:f4:28:9f:23:99:15:21:1b:bf:ed:1f:8e:a0:76:b2:9d root@example.com (ECDSA)
-256 MD5:e6:eb:45:8a:3c:59:35:5f:e9:5b:80:12:be:7e:22:73 root@example.com (ED25519)
-2048 MD5:3f:72:be:3d:62:03:5c:62:83:e8:6e:14:34:3a:85:1d root@example.com (RSA)
-```
+To get started:
-(You may need to exclude `-E md5` for some older versions of SSH).
+1. Navigate to your project's **Settings > Repository** and expand the **Mirroring repositories** section.
+1. Enter an `ssh://` URL for mirroring.
-If you're an SSH expert and already have a `known_hosts` file you'd like to use
-unaltered, then you can skip these steps. Just press the "Show advanced" button
-and paste in the file contents:
+NOTE: **Note:**
+SCP-style URLs (that is, `git@example.com:group/project.git`) are not supported at this time.
-![Advanced SSH host key management](repository_mirroring/repository_mirroring_pull_advanced_host_keys.png)
+Entering the URL adds two buttons to the page:
-Once you've **carefully verified** that all the fingerprints match your trusted
-source, you can press `Save changes`. This will record the host keys, along with
-the person who verified them (you!) and the date:
+- **Detect host keys**.
+- **Input host keys manually**.
-![SSH host keys submitted](repository_mirroring/repository_mirroring_ssh_host_keys_verified.png)
+If you click the:
-When pulling changes from the source repository, GitLab will now check that at
-least one of the stored host keys matches before connecting. This can prevent
-malicious code from being injected into your mirror, or your password being
-stolen!
+- **Detect host keys** button, GitLab will fetch the host keys from the server and display the fingerprints.
+- **Input host keys manually** button, a field is displayed where you can paste in host keys.
-To use SSH public key authentication, you'll also need to choose that option
-from the authentication methods dropdown. GitLab will generate a 4096-bit RSA
-key and display the public component of that key to you:
+Assuming you used the former, you now need to verify that the fingerprints are
+those you expect. GitLab.com and other code hosting sites publish their
+fingerprints in the open for you to check:
-![SSH public key authentication](repository_mirroring/repository_mirroring_ssh_public_key_authentication.png)
+- [AWS CodeCommit](http://docs.aws.amazon.com/codecommit/latest/userguide/regions.html#regions-fingerprints)
+- [Bitbucket](https://confluence.atlassian.com/bitbucket/use-the-ssh-protocol-with-bitbucket-cloud-221449711.html#UsetheSSHprotocolwithBitbucketCloud-KnownhostorBitbucket%27spublickeyfingerprints)
+- [GitHub](https://help.github.com/articles/github-s-ssh-key-fingerprints/)
+- [GitLab.com](https://about.gitlab.com/gitlab-com/settings/#ssh-host-keys-fingerprints)
+- [Launchpad](https://help.launchpad.net/SSHFingerprints)
+- [Savannah](http://savannah.gnu.org/maintenance/SshAccess/)
+- [SourceForge](https://sourceforge.net/p/forge/documentation/SSH%20Key%20Fingerprints/)
-You then need to add the public SSH key to the source repository configuration.
-If the source is hosted on GitLab, you should add it as a [Deploy Key][deploy-key].
-Other sources may require you to add the key to your user's `authorized_keys`
-file - just paste the entire `ssh-rsa AAA.... user@host` block into the file on
-its own line and save it.
+Other providers will vary. If you're running self-managed GitLab, or otherwise
+have access to the server for the other repository, you can securely gather the
+key fingerprints:
-Once the public key is set up on the source repository, press `Save changes` and your
-mirror will begin working.
+```sh
+$ cat /etc/ssh/ssh_host*pub | ssh-keygen -E md5 -l -f -
+256 MD5:f4:28:9f:23:99:15:21:1b:bf:ed:1f:8e:a0:76:b2:9d root@example.com (ECDSA)
+256 MD5:e6:eb:45:8a:3c:59:35:5f:e9:5b:80:12:be:7e:22:73 root@example.com (ED25519)
+2048 MD5:3f:72:be:3d:62:03:5c:62:83:e8:6e:14:34:3a:85:1d root@example.com (RSA)
+```
-If you need to change the key at any time, you can press the `Regenerate key`
-button to do so. You'll have to update the source repository with the new key
-to keep the mirror running.
+NOTE: **Note:**
+You may need to exclude `-E md5` for some older versions of SSH.
-### How it works
+When mirroring the repository, GitLab will now check that at least one of the
+stored host keys matches before connecting. This can prevent malicious code from
+being injected into your mirror, or your password being stolen.
-Once you activate the pull mirroring feature, the mirror will be inserted into
-a queue. A scheduler will start every minute and schedule a fixed amount of
-mirrors for update, based on the configured maximum capacity.
+### SSH public key authentication
-If the mirror successfully updates it will be enqueued once again with a small
-backoff period.
+To use SSH public key authentication, you'll also need to choose that option
+from the **Authentication method** dropdown. GitLab will generate a 4096-bit RSA
+key and display the public component of that key to you.
-If the mirror fails (eg: branch diverged from upstream), the project's backoff
-period will be penalized each time it fails up to a maximum amount of time.
+You then need to add the public SSH key to the other repository's configuration:
-## Pushing to a remote repository
+- If the other repository is hosted on GitLab, you should add the public SSH key
+ as a [Deploy Key](../ssh/README.md#deploy-keys).
+- If the other repository is hosted elsewhere, you may need to add the key to
+ your user's `authorized_keys` file. Paste the entire public SSH key into the
+ file on its own line and save it.
->[Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/249) in
-GitLab Enterprise Edition 8.7. [Moved to GitLab Community Edition][ce-18715] in 10.8.
+If you need to change the key at any time, you can remove and re-add the mirror
+to generate a new key. You'll have to update the other repository with the new
+key to keep the mirror running.
-For an existing project, you can set up push mirror from your project's
-**Settings âž” Repository** and searching for the "Push to a remote repository"
-section. Check the "Remote mirror repository" box and fill in the Git URL of
-the repository to push to. Click **Save changes** for the changes to take
-effect.
+### Overwrite diverged branches **[STARTER]**
-![Push settings](repository_mirroring/repository_mirroring_push_settings.png)
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/4559) in
+> [GitLab Starter](https://about.gitlab.com/pricing/) 10.6.
-When push mirroring is enabled, you are advised not to push commits directly
-to the mirrored repository to prevent the mirror diverging.
-All changes will end up in the mirrored repository whenever commits
-are pushed to GitLab, or when a [forced update](#forcing-an-update) is
-initiated.
+You can choose to always update your local branches with remote versions, even if they have
+diverged from the remote.
-Pushes into GitLab are automatically pushed to the remote mirror at least once
-every 5 minutes after they are received or once every minute if **push only
-protected branches** is enabled.
+CAUTION: **Caution:**
+For mirrored branches, enabling this option results in the loss of local changes.
-In case of a diverged branch, you will see an error indicated at the **Mirror
-repository** settings.
+To use this option, check the **Overwrite diverged branches** box when creating a repository mirror.
-![Diverged branch](
-repository_mirroring/repository_mirroring_diverged_branch_push.png)
+### Only mirror protected branches **[STARTER]**
-### Push only protected branches
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3326) in
+> [GitLab Starter](https://about.gitlab.com/pricing/) 10.3.
->[Introduced][ee-3350] in GitLab Enterprise Edition 10.3. [Moved to GitLab Community Edition][ce-18715] in 10.8.
+You can choose to pull mirror only the protected branches from your remote repository to GitLab.
+Non-protected branches are not mirrored and can diverge.
-You can choose to only push your protected branches from GitLab to your remote repository.
+To use this option, check the **Only mirror protected branches** box when creating a repository mirror.
-To use this option go to your project's repository settings page under push mirror.
+### Hard failure **[STARTER]**
-## Setting up a push mirror from GitLab to GitHub
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3117) in
+> [GitLab Starter](https://about.gitlab.com/pricing/) 10.2.
-To set up a mirror from GitLab to GitHub, you need to follow these steps:
+Once the mirroring process is unsuccessfully retried 14 times in a row, it will get marked as hard
+failed. This will become visible in either the:
-1. Create a [GitHub personal access token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/) with the "public_repo" box checked:
+- Project's main dashboard.
+- Pull mirror settings page.
- ![edit personal access token GitHub](repository_mirroring/repository_mirroring_github_edit_personal_access_token.png)
+When a project is hard failed, it will no longer get picked up for mirroring. A user can resume the
+project mirroring again by [Forcing an update](#forcing-an-update).
-1. Fill in the "Git repository URL" with the personal access token replacing the password `https://GitHubUsername:GitHubPersonalAccessToken@github.com/group/project.git`:
+### Trigger update using API **[STARTER]**
- ![push to remote repo](repository_mirroring/repository_mirroring_gitlab_push_to_a_remote_repository.png)
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3453) in
+[GitLab Starter](https://about.gitlab.com/pricing/) 10.3.
-1. Save
-1. And either wait or trigger the "Update Now" button:
+Pull mirroring uses polling to detect new branches and commits added upstream, often minutes
+afterwards. If you notify GitLab by [API](https://docs.gitlab.com/ee/api/projects.html#start-the-pull-mirroring-process-for-a-project),
+updates will be pulled immediately.
+
+For more information, see [Start the pull mirroring process for a Project](https://docs.gitlab.com/ee/api/projects.html#start-the-pull-mirroring-process-for-a-project).
+
+## Forcing an update **[CORE]**
+
+While mirrors are scheduled to update automatically, you can always force an update by using the
+update button which is available on the **Mirroring repositories** section of the **Repository Settings** page.
+
+![Repository mirroring force update user interface](img/repository_mirroring_force_update.png)
+
+## Bidirectional mirroring **[STARTER]**
+
+CAUTION: **Caution:**
+Bidirectional mirroring may cause conflicts.
+
+If you configure a GitLab repository to both pull from, and push to, the same remote source, there
+is no guarantee that either repository will update correctly. If you set up a repository for
+bidirectional mirroring, you should prepare for the likely conflicts by deciding who will resolve
+them and how they will be resolved.
+
+Rewriting any mirrored commit on either remote will cause conflicts and mirroring to fail. This can
+be prevented by:
+
+- [Pulling only protected branches](#pull-only-protected-branches).
+- [Pushing only protected branches](#push-only-protected-branches).
+
+You should [protect the branches](../user/project/protected_branches.md) you wish to mirror on both
+remotes to prevent conflicts caused by rewriting history.
+
+Bidirectional mirroring also creates a race condition where commits made close together to the same
+branch causes conflicts. The race condition can be mitigated by reducing the mirroring delay by using
+a [Push event webhook](../user/project/integrations/webhooks.md#push-events) to trigger an immediate
+pull to GitLab. Push mirroring from GitLab is rate limited to once per minute when only push mirroring
+protected branches.
+
+### Preventing conflicts using a `pre-receive` hook
+
+> **Warning:** The solution proposed will negatively impact the performance of
+> Git push operations because they will be proxied to the upstream Git
+> repository.
+
+A server-side `pre-receive` hook can be used to prevent the race condition
+described above by only accepting the push after first pushing the commit to
+the upstream Git repository. In this configuration one Git repository acts as
+the authoritative upstream, and the other as downstream. The `pre-receive` hook
+will be installed on the downstream repository.
+
+Read about [configuring custom Git hooks](../administration/custom_hooks.md) on the GitLab server.
+
+A sample `pre-receive` hook is provided below.
+
+```bash
+#!/usr/bin/env bash
+
+# --- Assume only one push mirror target
+# Push mirroring remotes are named `remote_mirror_<id>`, this finds the first remote and uses that.
+TARGET_REPO=$(git remote | grep -m 1 remote_mirror)
+
+proxy_push()
+{
+ # --- Arguments
+ OLDREV=$(git rev-parse $1)
+ NEWREV=$(git rev-parse $2)
+ REFNAME="$3"
+
+ # --- Pattern of branches to proxy pushes
+ whitelisted=$(expr "$branch" : "\(master\)")
+
+ case "$refname" in
+ refs/heads/*)
+ branch=$(expr "$refname" : "refs/heads/\(.*\)")
+
+ if [ "$whitelisted" = "$branch" ]; then
+ error="$(git push --quiet $TARGET_REPO $NEWREV:$REFNAME 2>&1)"
+ fail=$?
+
+ if [ "$fail" != "0" ]; then
+ echo >&2 ""
+ echo >&2 " Error: updates were rejected by upstream server"
+ echo >&2 " This is usually caused by another repository pushing changes"
+ echo >&2 " to the same ref. You may want to first integrate remote changes"
+ echo >&2 ""
+ return
+ fi
+ fi
+ ;;
+ esac
+}
+
+# Allow dual mode: run from the command line just like the update hook, or
+# if no arguments are given then run as a hook script
+if [ -n "$1" -a -n "$2" -a -n "$3" ]; then
+ # Output to the terminal in command line mode - if someone wanted to
+ # resend an email; they could redirect the output to sendmail
+ # themselves
+ PAGER= proxy_push $2 $3 $1
+else
+ # Push is proxied upstream one ref at a time. Because of this it is possible
+ # for some refs to succeed, and others to fail. This will result in a failed
+ # push.
+ while read oldrev newrev refname
+ do
+ proxy_push $oldrev $newrev $refname
+ done
+fi
+```
- ![update now](repository_mirroring/repository_mirroring_gitlab_push_to_a_remote_repository_update_now.png)
+### Mirroring with Perforce Helix via Git Fusion **[STARTER]**
-## Forcing an update
+CAUTION: **Warning:**
+Bidirectional mirroring should not be used as a permanent configuration. Refer to
+[Migrating from Perforce Helix](../user/project/import/perforce.md) for alternative migration approaches.
-While mirrors are scheduled to update automatically, you can always force an update
-by using the **Update now** button which is exposed in various places:
+[Git Fusion](https://www.perforce.com/video-tutorials/git-fusion-overview) provides a Git interface
+to [Perforce Helix](https://www.perforce.com/products) which can be used by GitLab to bidirectionally
+mirror projects with GitLab. This may be useful in some situations when migrating from Perforce Helix
+to GitLab where overlapping Perforce Helix workspaces cannot be migrated simultaneously to GitLab.
-- in the commits page
-- in the branches page
-- in the tags page
-- in the **Mirror repository** settings page
+If using mirroring with Perforce Helix, you should only mirror protected branches. Perforce Helix
+will reject any pushes that rewrite history. Only the fewest number of branches should be mirrored
+due to the performance limitations of Git Fusion.
-## Bidirectional mirroring
+When configuring mirroring with Perforce Helix via Git Fusion, the following Git Fusion
+settings are recommended:
-CAUTION: **Warning:**
-There is no bidirectional support without conflicts. If you
-configure a repository to pull and push to a second remote, there is no
-guarantee that it will update correctly on both remotes. If you configure
-a repository for bidirectional mirroring, you should consider when conflicts
-occur who and how they will be resolved.
-
-Rewriting any mirrored commit on either remote will cause conflicts and
-mirroring to fail. This can be prevented by [only pulling protected branches](
-#pull-only-protected-branches) and [only pushing protected branches](
-#push-only-protected-branches). You should protect the branches you wish to
-mirror on both remotes to prevent conflicts caused by rewriting history.
-
-Bidirectional mirroring also creates a race condition where commits to the same
-branch in close proximity will cause conflicts. The race condition can be
-mitigated by reducing the mirroring delay by using a Push event webhook to
-trigger an immediate pull to GitLab. Push mirroring from GitLab is rate limited
-to once per minute when only push mirroring protected branches.
-
-It may be possible to implement a locking mechanism using the server-side
-`pre-receive` hook to prevent the race condition. Read about [configuring
-custom Git hooks][hooks] on the GitLab server.
-
-### Mirroring with Perforce via GitFusion
+- `change-pusher` should be disabled. Otherwise, every commit will be rewritten as being committed
+ by the mirroring account, rather than being mapped to existing Perforce Helix users or the `unknown_git` user.
+- `unknown_git` user will be used as the commit author if the GitLab user does not exist in
+ Perforce Helix.
-CAUTION: **Warning:**
-Bidirectional mirroring should not be used as a permanent
-configuration. There is no bidirectional mirroring without conflicts.
-Refer to [Migrating from Perforce Helix][perforce] for alternative migration
-approaches.
-
-GitFusion provides a Git interface to Perforce which can be used by GitLab to
-bidirectionally mirror projects with GitLab. This may be useful in some
-situations when migrating from Perforce to GitLab where overlapping Perforce
-workspaces cannot be migrated simultaneously to GitLab.
-
-If using mirroring with Perforce you should only mirror protected branches.
-Perforce will reject any pushes that rewrite history. It is recommended that
-only the fewest number of branches are mirrored due to the performance
-limitations of GitFusion.
-
-[ee-51]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/51
-[ee-2551]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/2551
-[ee-3117]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3117
-[ee-3326]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3326
-[ee-3350]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3350
-[ee-3453]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/3453
-[ee-4559]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/4559
-[ce-18715]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18715
-[perms]: ../user/permissions.md
-[hooks]: ../administration/custom_hooks.md
-[deploy-key]: ../ssh/README.md#deploy-keys
-[webhook]: ../user/project/integrations/webhooks.md#push-events
-[pull-api]: ../api/projects.md#start-the-pull-mirroring-process-for-a-project
-[perforce]: ../user/project/import/perforce.md
+Read about [Git Fusion settings on Perforce.com](https://www.perforce.com/perforce/doc.current/manuals/git-fusion/Content/Git-Fusion/section_vss_bdw_w3.html#section_zdp_zz1_3l).
diff --git a/doc/workflow/repository_mirroring/repository_mirroring_detect_host_keys.png b/doc/workflow/repository_mirroring/repository_mirroring_detect_host_keys.png
deleted file mode 100644
index 2377a4a6516..00000000000
--- a/doc/workflow/repository_mirroring/repository_mirroring_detect_host_keys.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/repository_mirroring/repository_mirroring_diverged_branch.png b/doc/workflow/repository_mirroring/repository_mirroring_diverged_branch.png
deleted file mode 100644
index 45c9bce0889..00000000000
--- a/doc/workflow/repository_mirroring/repository_mirroring_diverged_branch.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/repository_mirroring/repository_mirroring_diverged_branch_push.png b/doc/workflow/repository_mirroring/repository_mirroring_diverged_branch_push.png
deleted file mode 100644
index 786bd23eee6..00000000000
--- a/doc/workflow/repository_mirroring/repository_mirroring_diverged_branch_push.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/repository_mirroring/repository_mirroring_github_edit_personal_access_token.png b/doc/workflow/repository_mirroring/repository_mirroring_github_edit_personal_access_token.png
deleted file mode 100644
index 139de42d8db..00000000000
--- a/doc/workflow/repository_mirroring/repository_mirroring_github_edit_personal_access_token.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/repository_mirroring/repository_mirroring_gitlab_push_to_a_remote_repository.png b/doc/workflow/repository_mirroring/repository_mirroring_gitlab_push_to_a_remote_repository.png
deleted file mode 100644
index ccbc1d92329..00000000000
--- a/doc/workflow/repository_mirroring/repository_mirroring_gitlab_push_to_a_remote_repository.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/repository_mirroring/repository_mirroring_gitlab_push_to_a_remote_repository_update_now.png b/doc/workflow/repository_mirroring/repository_mirroring_gitlab_push_to_a_remote_repository_update_now.png
deleted file mode 100644
index b16b3d2828e..00000000000
--- a/doc/workflow/repository_mirroring/repository_mirroring_gitlab_push_to_a_remote_repository_update_now.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/repository_mirroring/repository_mirroring_hard_failed_main.png b/doc/workflow/repository_mirroring/repository_mirroring_hard_failed_main.png
deleted file mode 100644
index d8af5ce129e..00000000000
--- a/doc/workflow/repository_mirroring/repository_mirroring_hard_failed_main.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/repository_mirroring/repository_mirroring_hard_failed_settings.png b/doc/workflow/repository_mirroring/repository_mirroring_hard_failed_settings.png
deleted file mode 100644
index a10102e97ac..00000000000
--- a/doc/workflow/repository_mirroring/repository_mirroring_hard_failed_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/repository_mirroring/repository_mirroring_new_project.png b/doc/workflow/repository_mirroring/repository_mirroring_new_project.png
deleted file mode 100644
index 43bf304838f..00000000000
--- a/doc/workflow/repository_mirroring/repository_mirroring_new_project.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/repository_mirroring/repository_mirroring_pull_advanced_host_keys.png b/doc/workflow/repository_mirroring/repository_mirroring_pull_advanced_host_keys.png
deleted file mode 100644
index 1f1b3e1d5fb..00000000000
--- a/doc/workflow/repository_mirroring/repository_mirroring_pull_advanced_host_keys.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/repository_mirroring/repository_mirroring_pull_settings.png b/doc/workflow/repository_mirroring/repository_mirroring_pull_settings.png
deleted file mode 100644
index b8dfddb3d02..00000000000
--- a/doc/workflow/repository_mirroring/repository_mirroring_pull_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/repository_mirroring/repository_mirroring_pull_settings_for_ssh.png b/doc/workflow/repository_mirroring/repository_mirroring_pull_settings_for_ssh.png
deleted file mode 100644
index 8f1de1d3003..00000000000
--- a/doc/workflow/repository_mirroring/repository_mirroring_pull_settings_for_ssh.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/repository_mirroring/repository_mirroring_push_settings.png b/doc/workflow/repository_mirroring/repository_mirroring_push_settings.png
deleted file mode 100644
index f8199aa7c0f..00000000000
--- a/doc/workflow/repository_mirroring/repository_mirroring_push_settings.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/repository_mirroring/repository_mirroring_ssh_host_keys_verified.png b/doc/workflow/repository_mirroring/repository_mirroring_ssh_host_keys_verified.png
deleted file mode 100644
index 930d10a0822..00000000000
--- a/doc/workflow/repository_mirroring/repository_mirroring_ssh_host_keys_verified.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/repository_mirroring/repository_mirroring_ssh_public_key_authentication.png b/doc/workflow/repository_mirroring/repository_mirroring_ssh_public_key_authentication.png
deleted file mode 100644
index adc1eedac44..00000000000
--- a/doc/workflow/repository_mirroring/repository_mirroring_ssh_public_key_authentication.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/shortcuts.md b/doc/workflow/shortcuts.md
index b2f1cbec204..7359e1c6119 100644
--- a/doc/workflow/shortcuts.md
+++ b/doc/workflow/shortcuts.md
@@ -93,4 +93,5 @@ You can see GitLab's keyboard shortcuts by using 'shift + ?'
| Keyboard Shortcut | Description |
| ----------------- | ----------- |
-| <kbd>⌘</kbd> + <kbd>p</kbd> | Go to file |
+| <kbd>Cmd</kbd>/<kbd>Ctrl</kbd> + <kbd>p</kbd> | Go to file |
+| <kbd>Cmd</kbd>/<kbd>Ctrl</kbd> + <kbd>Enter</kbd> | Commit (when editing the commit message) |
diff --git a/doc/workflow/time_tracking.md b/doc/workflow/time_tracking.md
index bfe87bb2ceb..8a75687e4f5 100644
--- a/doc/workflow/time_tracking.md
+++ b/doc/workflow/time_tracking.md
@@ -62,12 +62,13 @@ To remove all the time spent at once, use `/remove_time_spent`.
## Configuration
The following time units are available:
+* months (mo)
* weeks (w)
* days (d)
* hours (h)
* minutes (m)
-Default conversion rates are 1w = 5d and 1d = 8h.
+Default conversion rates are 1mo = 4w, 1w = 5d and 1d = 8h.
[landing]: https://about.gitlab.com/features/time-tracking
[quick actions]: ../user/project/quick_actions.md
diff --git a/generator_templates/active_record/migration/create_table_migration.rb b/generator_templates/active_record/migration/create_table_migration.rb
index 92e963911d0..4a6bea2796c 100644
--- a/generator_templates/active_record/migration/create_table_migration.rb
+++ b/generator_templates/active_record/migration/create_table_migration.rb
@@ -3,7 +3,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class <%= migration_class_name %> < ActiveRecord::Migration
+class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/generator_templates/active_record/migration/migration.rb b/generator_templates/active_record/migration/migration.rb
index 38edab82550..153280cd4b7 100644
--- a/generator_templates/active_record/migration/migration.rb
+++ b/generator_templates/active_record/migration/migration.rb
@@ -3,7 +3,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class <%= migration_class_name %> < ActiveRecord::Migration
+class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
diff --git a/generator_templates/rails/post_deployment_migration/migration.rb b/generator_templates/rails/post_deployment_migration/migration.rb
index 353709f7c9c..4c1685545b5 100644
--- a/generator_templates/rails/post_deployment_migration/migration.rb
+++ b/generator_templates/rails/post_deployment_migration/migration.rb
@@ -3,7 +3,7 @@
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
-class <%= migration_class_name %> < ActiveRecord::Migration
+class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
diff --git a/lib/after_commit_queue.rb b/lib/after_commit_queue.rb
index a4d8507960e..6fb7985f955 100644
--- a/lib/after_commit_queue.rb
+++ b/lib/after_commit_queue.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module AfterCommitQueue
extend ActiveSupport::Concern
diff --git a/lib/api/access_requests.rb b/lib/api/access_requests.rb
index 18063fb20a2..ee8dc822098 100644
--- a/lib/api/access_requests.rb
+++ b/lib/api/access_requests.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class AccessRequests < Grape::API
include PaginationParams
@@ -10,7 +12,7 @@ module API
params do
requires :id, type: String, desc: "The #{source_type} ID"
end
- resource source_type.pluralize, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource source_type.pluralize, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc "Gets a list of access requests for a #{source_type}." do
detail 'This feature was introduced in GitLab 8.11.'
success Entities::AccessRequester
diff --git a/lib/api/api.rb b/lib/api/api.rb
index e89d9337853..a4bf0d77eb1 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class API < Grape::API
include APIGuard
@@ -5,8 +7,8 @@ module API
LOG_FILENAME = Rails.root.join("log", "api_json.log")
NO_SLASH_URL_PART_REGEX = %r{[^/]+}
- PROJECT_ENDPOINT_REQUIREMENTS = { id: NO_SLASH_URL_PART_REGEX }.freeze
- COMMIT_ENDPOINT_REQUIREMENTS = PROJECT_ENDPOINT_REQUIREMENTS.merge(sha: NO_SLASH_URL_PART_REGEX).freeze
+ NAMESPACE_OR_PROJECT_REQUIREMENTS = { id: NO_SLASH_URL_PART_REGEX }.freeze
+ COMMIT_ENDPOINT_REQUIREMENTS = NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(sha: NO_SLASH_URL_PART_REGEX).freeze
insert_before Grape::Middleware::Error,
GrapeLogging::Middleware::RequestLogger,
@@ -48,6 +50,10 @@ module API
rack_response({ 'message' => '404 Not found' }.to_json, 404)
end
+ rescue_from ::Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError do
+ rack_response({ 'message' => '409 Conflict: Resource lock' }.to_json, 409)
+ end
+
rescue_from UploadedFile::InvalidPathError do |e|
rack_response({ 'message' => e.message }.to_json, 400)
end
@@ -130,6 +136,7 @@ module API
mount ::API::Projects
mount ::API::ProjectSnapshots
mount ::API::ProjectSnippets
+ mount ::API::ProjectTemplates
mount ::API::ProtectedBranches
mount ::API::ProtectedTags
mount ::API::Repositories
@@ -140,6 +147,7 @@ module API
mount ::API::Settings
mount ::API::SidekiqMetrics
mount ::API::Snippets
+ mount ::API::Submodules
mount ::API::Subscriptions
mount ::API::SystemHooks
mount ::API::Tags
diff --git a/lib/api/api_guard.rb b/lib/api/api_guard.rb
index 8ee7987cfff..af9b519ed9e 100644
--- a/lib/api/api_guard.rb
+++ b/lib/api/api_guard.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Guard API with OAuth 2.0 Access Token
require 'rack/oauth2'
@@ -92,6 +94,7 @@ module API
Gitlab::Auth::TokenNotFoundError,
Gitlab::Auth::ExpiredError,
Gitlab::Auth::RevokedError,
+ Gitlab::Auth::ImpersonationDisabled,
Gitlab::Auth::InsufficientScopeError]
base.__send__(:rescue_from, *error_classes, oauth2_bearer_token_error_handler) # rubocop:disable GitlabSecurity/PublicSend
@@ -119,6 +122,11 @@ module API
:invalid_token,
"Token was revoked. You have to re-authorize from the user.")
+ when Gitlab::Auth::ImpersonationDisabled
+ Rack::OAuth2::Server::Resource::Bearer::Unauthorized.new(
+ :invalid_token,
+ "Token is an impersonation token but impersonation was disabled.")
+
when Gitlab::Auth::InsufficientScopeError
# FIXME: ForbiddenError (inherited from Bearer::Forbidden of Rack::Oauth2)
# does not include WWW-Authenticate header, which breaks the standard.
diff --git a/lib/api/applications.rb b/lib/api/applications.rb
index b122cdefe4e..92717e04543 100644
--- a/lib/api/applications.rb
+++ b/lib/api/applications.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
# External applications API
class Applications < Grape::API
@@ -22,6 +24,22 @@ module API
render_validation_error! application
end
end
+
+ desc 'Get applications' do
+ success Entities::Application
+ end
+ get do
+ applications = ApplicationsFinder.new.execute
+ present applications, with: Entities::Application
+ end
+
+ desc 'Delete an application'
+ delete ':id' do
+ application = ApplicationsFinder.new(params).execute
+ application.destroy
+
+ status 204
+ end
end
end
end
diff --git a/lib/api/avatar.rb b/lib/api/avatar.rb
index 70219bc8ea0..0f14d003065 100644
--- a/lib/api/avatar.rb
+++ b/lib/api/avatar.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Avatar < Grape::API
resource :avatar do
diff --git a/lib/api/award_emoji.rb b/lib/api/award_emoji.rb
index e334af22183..a1851ba3627 100644
--- a/lib/api/award_emoji.rb
+++ b/lib/api/award_emoji.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class AwardEmoji < Grape::API
include PaginationParams
@@ -12,7 +14,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
AWARDABLES.each do |awardable_params|
awardable_string = awardable_params[:type].pluralize
awardable_id_string = "#{awardable_params[:type]}_#{awardable_params[:find_by]}"
diff --git a/lib/api/badges.rb b/lib/api/badges.rb
index 8ceffe9c5ef..ba554e00a16 100644
--- a/lib/api/badges.rb
+++ b/lib/api/badges.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Badges < Grape::API
include PaginationParams
@@ -20,7 +22,7 @@ module API
params do
requires :id, type: String, desc: "The ID of a #{source_type}"
end
- resource source_type.pluralize, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource source_type.pluralize, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc "Gets a list of #{source_type} badges viewable by the authenticated user." do
detail 'This feature was introduced in GitLab 10.6.'
success Entities::Badge
diff --git a/lib/api/boards.rb b/lib/api/boards.rb
index 0f89414148b..b7c77730afb 100644
--- a/lib/api/boards.rb
+++ b/lib/api/boards.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Boards < Grape::API
include BoardsResponses
@@ -14,7 +16,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
segment ':id/boards' do
desc 'Get all project boards' do
detail 'This feature was introduced in 8.13'
diff --git a/lib/api/boards_responses.rb b/lib/api/boards_responses.rb
index 3322b37c6ff..86d9b24802f 100644
--- a/lib/api/boards_responses.rb
+++ b/lib/api/boards_responses.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module BoardsResponses
extend ActiveSupport::Concern
diff --git a/lib/api/branches.rb b/lib/api/branches.rb
index 5d106ed93a0..e7e58ad0e66 100644
--- a/lib/api/branches.rb
+++ b/lib/api/branches.rb
@@ -1,10 +1,12 @@
+# frozen_string_literal: true
+
require 'mime/types'
module API
class Branches < Grape::API
include PaginationParams
- BRANCH_ENDPOINT_REQUIREMENTS = API::PROJECT_ENDPOINT_REQUIREMENTS.merge(branch: API::NO_SLASH_URL_PART_REGEX)
+ BRANCH_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(branch: API::NO_SLASH_URL_PART_REGEX)
before { authorize! :download_code, user_project }
@@ -18,7 +20,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get a project repository branches' do
success Entities::Branch
end
diff --git a/lib/api/broadcast_messages.rb b/lib/api/broadcast_messages.rb
index d7138b2f2fe..19148758fc5 100644
--- a/lib/api/broadcast_messages.rb
+++ b/lib/api/broadcast_messages.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class BroadcastMessages < Grape::API
include PaginationParams
diff --git a/lib/api/circuit_breakers.rb b/lib/api/circuit_breakers.rb
index c13154dc0ec..da756daadcc 100644
--- a/lib/api/circuit_breakers.rb
+++ b/lib/api/circuit_breakers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class CircuitBreakers < Grape::API
before { authenticated_as_admin! }
@@ -11,37 +13,24 @@ module API
end
resource ':type' do
namespace '', requirements: { type: 'repository_storage' } do
- helpers do
- def failing_storage_health
- @failing_storage_health ||= Gitlab::Git::Storage::Health.for_failing_storages
- end
-
- def storage_health
- @storage_health ||= Gitlab::Git::Storage::Health.for_all_storages
- end
- end
-
desc 'Get all git storages' do
detail 'This feature was introduced in GitLab 9.5'
- success Entities::RepositoryStorageHealth
end
get do
- present storage_health, with: Entities::RepositoryStorageHealth
+ present []
end
desc 'Get all failing git storages' do
detail 'This feature was introduced in GitLab 9.5'
- success Entities::RepositoryStorageHealth
end
get 'failing' do
- present failing_storage_health, with: Entities::RepositoryStorageHealth
+ present []
end
desc 'Reset all storage failures and open circuitbreaker' do
detail 'This feature was introduced in GitLab 9.5'
end
delete do
- Gitlab::Git::Storage::FailureInfo.reset_all!
end
end
end
diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb
index 8e6f706afd4..1ba2c150cb4 100644
--- a/lib/api/commit_statuses.rb
+++ b/lib/api/commit_statuses.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'mime/types'
module API
@@ -5,7 +7,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
include PaginationParams
before { authenticate! }
diff --git a/lib/api/commits.rb b/lib/api/commits.rb
index fcaff35459e..9d23daafe95 100644
--- a/lib/api/commits.rb
+++ b/lib/api/commits.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'mime/types'
module API
@@ -21,7 +23,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get a project repository commits' do
success Entities::Commit
end
@@ -73,10 +75,30 @@ module API
params do
requires :branch, type: String, desc: 'Name of the branch to commit into. To create a new branch, also provide `start_branch`.', allow_blank: false
requires :commit_message, type: String, desc: 'Commit message'
- requires :actions, type: Array[Hash], desc: 'Actions to perform in commit'
+ requires :actions, type: Array, desc: 'Actions to perform in commit' do
+ requires :action, type: String, desc: 'The action to perform, `create`, `delete`, `move`, `update`, `chmod`', values: %w[create update move delete chmod].freeze
+ requires :file_path, type: String, desc: 'Full path to the file. Ex. `lib/class.rb`'
+ given action: ->(action) { action == 'move' } do
+ requires :previous_path, type: String, desc: 'Original full path to the file being moved. Ex. `lib/class1.rb`'
+ end
+ given action: ->(action) { %w[create move].include? action } do
+ optional :content, type: String, desc: 'File content'
+ end
+ given action: ->(action) { action == 'update' } do
+ requires :content, type: String, desc: 'File content'
+ end
+ optional :encoding, type: String, desc: '`text` or `base64`', default: 'text', values: %w[text base64]
+ given action: ->(action) { %w[update move delete].include? action } do
+ optional :last_commit_id, type: String, desc: 'Last known file commit id'
+ end
+ given action: ->(action) { action == 'chmod' } do
+ requires :execute_filemode, type: Boolean, desc: 'When `true/false` enables/disables the execute flag on the file.'
+ end
+ end
optional :start_branch, type: String, desc: 'Name of the branch to start the new commit from'
optional :author_email, type: String, desc: 'Author email for commit'
optional :author_name, type: String, desc: 'Author name for commit'
+ optional :stats, type: Boolean, default: true, desc: 'Include commit stats'
end
post ':id/repository/commits' do
authorize_push_to_branch!(params[:branch])
@@ -89,7 +111,10 @@ module API
if result[:status] == :success
commit_detail = user_project.repository.commit(result[:result])
- present commit_detail, with: Entities::CommitDetail
+
+ Gitlab::WebIdeCommitsCounter.increment if find_user_from_warden
+
+ present commit_detail, with: Entities::CommitDetail, stats: params[:stats]
else
render_api_error!(result[:message], 400)
end
@@ -169,11 +194,47 @@ module API
branch_name: params[:branch]
}
- result = ::Commits::CherryPickService.new(user_project, current_user, commit_params).execute
+ result = ::Commits::CherryPickService
+ .new(user_project, current_user, commit_params)
+ .execute
+
+ if result[:status] == :success
+ present user_project.repository.commit(result[:result]),
+ with: Entities::Commit
+ else
+ render_api_error!(result[:message], 400)
+ end
+ end
+
+ desc 'Revert a commit in a branch' do
+ detail 'This feature was introduced in GitLab 11.5'
+ success Entities::Commit
+ end
+ params do
+ requires :sha, type: String, desc: 'Commit SHA to revert'
+ requires :branch, type: String, desc: 'Target branch name', allow_blank: false
+ end
+ post ':id/repository/commits/:sha/revert', requirements: API::COMMIT_ENDPOINT_REQUIREMENTS do
+ authorize_push_to_branch!(params[:branch])
+
+ commit = user_project.commit(params[:sha])
+ not_found!('Commit') unless commit
+
+ find_branch!(params[:branch])
+
+ commit_params = {
+ commit: commit,
+ start_branch: params[:branch],
+ branch_name: params[:branch]
+ }
+
+ result = ::Commits::RevertService
+ .new(user_project, current_user, commit_params)
+ .execute
if result[:status] == :success
- branch = find_branch!(params[:branch])
- present user_project.repository.commit(branch.dereferenced_target), with: Entities::Commit
+ present user_project.repository.commit(result[:result]),
+ with: Entities::Commit
else
render_api_error!(result[:message], 400)
end
diff --git a/lib/api/custom_attributes_endpoints.rb b/lib/api/custom_attributes_endpoints.rb
index b5864665cc3..2149e04451e 100644
--- a/lib/api/custom_attributes_endpoints.rb
+++ b/lib/api/custom_attributes_endpoints.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module CustomAttributesEndpoints
extend ActiveSupport::Concern
diff --git a/lib/api/deploy_keys.rb b/lib/api/deploy_keys.rb
index 501e9f64db0..df6d2721977 100644
--- a/lib/api/deploy_keys.rb
+++ b/lib/api/deploy_keys.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class DeployKeys < Grape::API
include PaginationParams
@@ -29,7 +31,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of the project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before { authorize_admin_project }
desc "Get a specific project's deploy keys" do
diff --git a/lib/api/deployments.rb b/lib/api/deployments.rb
index b7892599295..8706a971a1a 100644
--- a/lib/api/deployments.rb
+++ b/lib/api/deployments.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
# Deployments RESTful API endpoints
class Deployments < Grape::API
@@ -8,7 +10,7 @@ module API
params do
requires :id, type: String, desc: 'The project ID'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get all deployments of the project' do
detail 'This feature was introduced in GitLab 8.11.'
success Entities::Deployment
diff --git a/lib/api/discussions.rb b/lib/api/discussions.rb
index 88668992215..91eb6a23701 100644
--- a/lib/api/discussions.rb
+++ b/lib/api/discussions.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Discussions < Grape::API
include PaginationParams
@@ -15,7 +17,7 @@ module API
params do
requires :id, type: String, desc: "The ID of a #{parent_type}"
end
- resource parent_type.pluralize.to_sym, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource parent_type.pluralize.to_sym, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc "Get a list of #{noteable_type.to_s.downcase} discussions" do
success Entities::Discussion
end
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 0fec3dc3dc4..5dbfbb85e9e 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module Entities
class WikiPageBasic < Grape::Entity
@@ -53,7 +55,7 @@ module API
class User < UserBasic
expose :created_at, if: ->(user, opts) { Ability.allowed?(opts[:current_user], :read_user_profile, user) }
- expose :bio, :location, :skype, :linkedin, :twitter, :website_url, :organization
+ expose :bio, :location, :public_email, :skype, :linkedin, :twitter, :website_url, :organization
end
class UserActivity < Grape::Entity
@@ -143,7 +145,9 @@ module API
expose :import_status
# TODO: Use `expose_nil` once we upgrade the grape-entity gem
- expose :import_error, if: lambda { |status, _ops| status.import_error }
+ expose :import_error, if: lambda { |project, _ops| project.import_state&.last_error } do |project|
+ project.import_state.last_error
+ end
end
class BasicProjectDetails < ProjectIdentity
@@ -158,13 +162,27 @@ module API
# (fixed in https://github.com/rails/rails/pull/25976).
project.tags.map(&:name).sort
end
+
expose :ssh_url_to_repo, :http_url_to_repo, :web_url, :readme_url
+
+ expose :license_url, if: :license do |project|
+ license = project.repository.license_blob
+
+ if license
+ Gitlab::Routing.url_helpers.project_blob_url(project, File.join(project.default_branch, license.path))
+ end
+ end
+
+ expose :license, with: 'API::Entities::LicenseBasic', if: :license do |project|
+ project.repository.license
+ end
+
expose :avatar_url do |project, options|
project.avatar_url(only_path: false)
end
+
expose :star_count, :forks_count
expose :last_activity_at
-
expose :namespace, using: 'API::Entities::NamespaceBasic'
expose :custom_attributes, using: 'API::Entities::CustomAttribute', if: :with_custom_attributes
@@ -232,7 +250,10 @@ module API
expose :creator_id
expose :forked_from_project, using: Entities::BasicProjectDetails, if: lambda { |project, options| project.forked? }
expose :import_status
- expose :import_error, if: lambda { |_project, options| options[:user_can_admin_project] }
+
+ expose :import_error, if: lambda { |_project, options| options[:user_can_admin_project] } do |project|
+ project.import_state&.last_error
+ end
expose :open_issues_count, if: lambda { |project, options| project.feature_available?(:issues, options[:current_user]) }
expose :runners_token, if: lambda { |_project, options| options[:user_can_admin_project] }
@@ -258,7 +279,7 @@ module API
super(projects_relation).preload(:group)
.preload(project_group_links: :group,
fork_network: :root_project,
- forked_project_link: :forked_from_project,
+ fork_network_member: :forked_from_project,
forked_from_project: [:route, :forks, :tags, namespace: :route])
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -591,6 +612,22 @@ module API
end
class MergeRequestBasic < ProjectEntity
+ expose :merged_by, using: Entities::UserBasic do |merge_request, _options|
+ merge_request.metrics&.merged_by
+ end
+
+ expose :merged_at do |merge_request, _options|
+ merge_request.metrics&.merged_at
+ end
+
+ expose :closed_by, using: Entities::UserBasic do |merge_request, _options|
+ merge_request.metrics&.latest_closed_by
+ end
+
+ expose :closed_at do |merge_request, _options|
+ merge_request.metrics&.latest_closed_at
+ end
+
expose :title_html, if: -> (_, options) { options[:render_html] } do |entity|
MarkupHelper.markdown_field(entity, :title)
end
@@ -660,22 +697,6 @@ module API
merge_request.merge_request_diff.real_size
end
- expose :merged_by, using: Entities::UserBasic do |merge_request, _options|
- merge_request.metrics&.merged_by
- end
-
- expose :merged_at do |merge_request, _options|
- merge_request.metrics&.merged_at
- end
-
- expose :closed_by, using: Entities::UserBasic do |merge_request, _options|
- merge_request.metrics&.latest_closed_by
- end
-
- expose :closed_at do |merge_request, _options|
- merge_request.metrics&.latest_closed_at
- end
-
expose :latest_build_started_at, if: -> (_, options) { build_available?(options) } do |merge_request, _options|
merge_request.metrics&.latest_build_started_at
end
@@ -694,6 +715,10 @@ module API
expose :diff_refs, using: Entities::DiffRefs
+ # Allow the status of a rebase to be determined
+ expose :merge_error
+ expose :rebase_in_progress?, as: :rebase_in_progress, if: -> (_, options) { options[:include_rebase_in_progress] }
+
expose :diverged_commits_count, as: :diverged_commits_count, if: -> (_, options) { options[:include_diverged_commits_count] }
def build_available?(options)
@@ -1126,7 +1151,8 @@ module API
end
class JobArtifactFile < Grape::Entity
- expose :filename, :size
+ expose :filename
+ expose :cached_size, as: :size
end
class JobArtifact < Grape::Entity
@@ -1206,11 +1232,14 @@ module API
expose :deployable, using: Entities::Job
end
- class License < Grape::Entity
+ class LicenseBasic < Grape::Entity
expose :key, :name, :nickname
- expose :popular?, as: :popular
expose :url, as: :html_url
expose(:source_url) { |license| license.meta['source'] }
+ end
+
+ class License < LicenseBasic
+ expose :popular?, as: :popular
expose(:description) { |license| license.meta['description'] }
expose(:conditions) { |license| license.meta['conditions'] }
expose(:permissions) { |license| license.meta['permissions'] }
@@ -1219,6 +1248,7 @@ module API
end
class TemplatesList < Grape::Entity
+ expose :key
expose :name
end
@@ -1243,7 +1273,11 @@ module API
expose :token
end
- class ImpersonationToken < PersonalAccessTokenWithToken
+ class ImpersonationToken < PersonalAccessToken
+ expose :impersonation
+ end
+
+ class ImpersonationTokenWithToken < PersonalAccessTokenWithToken
expose :impersonation
end
@@ -1361,12 +1395,6 @@ module API
expose :submitted, as: :akismet_submitted
end
- class RepositoryStorageHealth < Grape::Entity
- expose :storage_name
- expose :failing_on_hosts
- expose :total_failures
- end
-
class CustomAttribute < Grape::Entity
expose :key
expose :value
@@ -1415,7 +1443,9 @@ module API
end
class Application < Grape::Entity
+ expose :id
expose :uid, as: :application_id
+ expose :name, as: :application_name
expose :redirect_uri, as: :callback_url
end
diff --git a/lib/api/environments.rb b/lib/api/environments.rb
index fa828f43001..633f24d3c9a 100644
--- a/lib/api/environments.rb
+++ b/lib/api/environments.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
# Environments RESTfull API endpoints
class Environments < Grape::API
@@ -9,7 +11,7 @@ module API
params do
requires :id, type: String, desc: 'The project ID'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get all environments of the project' do
detail 'This feature was introduced in GitLab 8.11.'
success Entities::Environment
diff --git a/lib/api/events.rb b/lib/api/events.rb
index dfe0e81af26..44dae57770d 100644
--- a/lib/api/events.rb
+++ b/lib/api/events.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Events < Grape::API
include PaginationParams
@@ -16,12 +18,27 @@ module API
desc: 'Return events sorted in ascending and descending order'
end
+ RedactedEvent = OpenStruct.new(target_title: 'Confidential event').freeze
+
+ def redact_events(events)
+ events.map do |event|
+ if event.visible_to_user?(current_user)
+ event
+ else
+ RedactedEvent
+ end
+ end
+ end
+
# rubocop: disable CodeReuse/ActiveRecord
- def present_events(events)
+ def present_events(events, redact: true)
events = events.reorder(created_at: params[:sort])
.with_associations
- present paginate(events), with: Entities::Event
+ events = paginate(events)
+ events = redact_events(events) if redact
+
+ present events, with: Entities::Event
end
# rubocop: enable CodeReuse/ActiveRecord
end
@@ -44,7 +61,8 @@ module API
events = EventsFinder.new(params.merge(source: current_user, current_user: current_user)).execute.preload(:author, :target)
- present_events(events)
+ # Since we're viewing our own events, redaction is unnecessary
+ present_events(events, redact: false)
end
# rubocop: enable CodeReuse/ActiveRecord
end
@@ -79,7 +97,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc "List a Project's visible events" do
success Entities::Event
end
diff --git a/lib/api/features.rb b/lib/api/features.rb
index 79be8c1903e..1331248699f 100644
--- a/lib/api/features.rb
+++ b/lib/api/features.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Features < Grape::API
before { authenticated_as_admin! }
@@ -18,7 +20,7 @@ module API
def gate_targets(params)
targets = []
targets << Feature.group(params[:feature_group]) if params[:feature_group]
- targets << User.find_by_username(params[:user]) if params[:user]
+ targets << UserFinder.new(params[:user]).find_by_username if params[:user]
targets
end
diff --git a/lib/api/files.rb b/lib/api/files.rb
index ac02488d30c..becf66d1467 100644
--- a/lib/api/files.rb
+++ b/lib/api/files.rb
@@ -1,6 +1,8 @@
+# frozen_string_literal: true
+
module API
class Files < Grape::API
- FILE_ENDPOINT_REQUIREMENTS = API::PROJECT_ENDPOINT_REQUIREMENTS.merge(file_path: API::NO_SLASH_URL_PART_REGEX)
+ FILE_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(file_path: API::NO_SLASH_URL_PART_REGEX)
# Prevents returning plain/text responses for files with .txt extension
after_validation { content_type "application/json" }
diff --git a/lib/api/group_boards.rb b/lib/api/group_boards.rb
index 3832cdc10a8..9a20ee8c8b9 100644
--- a/lib/api/group_boards.rb
+++ b/lib/api/group_boards.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class GroupBoards < Grape::API
include BoardsResponses
@@ -17,7 +19,7 @@ module API
requires :id, type: String, desc: 'The ID of a group'
end
- resource :groups, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
segment ':id/boards' do
desc 'Find a group board' do
detail 'This feature was introduced in 10.6'
diff --git a/lib/api/group_milestones.rb b/lib/api/group_milestones.rb
index 4b4352c2b27..d4287e4a7c4 100644
--- a/lib/api/group_milestones.rb
+++ b/lib/api/group_milestones.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class GroupMilestones < Grape::API
include MilestoneResponses
@@ -10,7 +12,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a group'
end
- resource :groups, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get a list of group milestones' do
success Entities::Milestone
end
diff --git a/lib/api/group_variables.rb b/lib/api/group_variables.rb
index b6610dd04b3..3f048e0dc56 100644
--- a/lib/api/group_variables.rb
+++ b/lib/api/group_variables.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class GroupVariables < Grape::API
include PaginationParams
@@ -9,7 +11,7 @@ module API
requires :id, type: String, desc: 'The ID of a group'
end
- resource :groups, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get group-level variables' do
success Entities::Variable
end
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 018ca72c32a..626a2008dee 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Groups < Grape::API
include PaginationParams
@@ -58,7 +60,17 @@ module API
def find_group_projects(params)
group = find_group!(params[:id])
- projects = GroupProjectsFinder.new(group: group, current_user: current_user, params: project_finder_params).execute
+ options = {
+ only_owned: !params[:with_shared],
+ include_subgroups: params[:include_subgroups]
+ }
+
+ projects = GroupProjectsFinder.new(
+ group: group,
+ current_user: current_user,
+ params: project_finder_params,
+ options: options
+ ).execute
projects = projects.with_issues_available_for_user(current_user) if params[:with_issues_enabled]
projects = projects.with_merge_requests_enabled if params[:with_merge_requests_enabled]
projects = reorder_projects(projects)
@@ -128,7 +140,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a group'
end
- resource :groups, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Update a group. Available only for users who can administrate groups.' do
success Entities::Group
end
@@ -199,6 +211,8 @@ module API
optional :starred, type: Boolean, default: false, desc: 'Limit by starred status'
optional :with_issues_enabled, type: Boolean, default: false, desc: 'Limit by enabled issues feature'
optional :with_merge_requests_enabled, type: Boolean, default: false, desc: 'Limit by enabled merge requests feature'
+ optional :with_shared, type: Boolean, default: true, desc: 'Include projects shared to this group'
+ optional :include_subgroups, type: Boolean, default: false, desc: 'Includes projects in subgroups of this group'
use :pagination
use :with_custom_attributes
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 85e3e06e4fd..9fda73d5b92 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module Helpers
include Gitlab::Utils
@@ -94,15 +96,9 @@ module API
LabelsFinder.new(current_user, search_params).execute
end
- # rubocop: disable CodeReuse/ActiveRecord
def find_user(id)
- if id =~ /^\d+$/
- User.find_by(id: id)
- else
- User.find_by(username: id)
- end
+ UserFinder.new(id).find_by_id_or_username
end
- # rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def find_project(id)
@@ -381,9 +377,10 @@ module API
# lifted from https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb#L60
trace = exception.backtrace
- message = "\n#{exception.class} (#{exception.message}):\n"
+ message = ["\n#{exception.class} (#{exception.message}):\n"]
message << exception.annoted_source_code.to_s if exception.respond_to?(:annoted_source_code)
message << " " << trace.join("\n ")
+ message = message.join
API.logger.add Logger::FATAL, message
@@ -497,6 +494,7 @@ module API
def send_git_blob(repository, blob)
env['api.format'] = :txt
content_type 'text/plain'
+ header['Content-Disposition'] = "attachment; filename=#{blob.name.inspect}"
header(*Gitlab::Workhorse.send_git_blob(repository, blob))
end
diff --git a/lib/api/helpers/badges_helpers.rb b/lib/api/helpers/badges_helpers.rb
index 1f8afbf3c90..46ce5b4e7b5 100644
--- a/lib/api/helpers/badges_helpers.rb
+++ b/lib/api/helpers/badges_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module Helpers
module BadgesHelpers
diff --git a/lib/api/helpers/common_helpers.rb b/lib/api/helpers/common_helpers.rb
index 9993caa5249..7551ca50a7f 100644
--- a/lib/api/helpers/common_helpers.rb
+++ b/lib/api/helpers/common_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module Helpers
module CommonHelpers
diff --git a/lib/api/helpers/custom_attributes.rb b/lib/api/helpers/custom_attributes.rb
index 3bbe827967e..88208226c40 100644
--- a/lib/api/helpers/custom_attributes.rb
+++ b/lib/api/helpers/custom_attributes.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module Helpers
module CustomAttributes
diff --git a/lib/api/helpers/custom_validators.rb b/lib/api/helpers/custom_validators.rb
index dd4f6c41131..1058f4e8a5e 100644
--- a/lib/api/helpers/custom_validators.rb
+++ b/lib/api/helpers/custom_validators.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module Helpers
module CustomValidators
@@ -8,8 +10,21 @@ module API
raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)], message: message(:absence)
end
end
+
+ class IntegerNoneAny < Grape::Validations::Base
+ def validate_param!(attr_name, params)
+ value = params[attr_name]
+
+ return if value.is_a?(Integer) ||
+ [IssuableFinder::FILTER_NONE, IssuableFinder::FILTER_ANY].include?(value.to_s.downcase)
+
+ raise Grape::Exceptions::Validation, params: [@scope.full_name(attr_name)],
+ message: "should be an integer, 'None' or 'Any'"
+ end
+ end
end
end
end
Grape::Validations.register_validator(:absence, ::API::Helpers::CustomValidators::Absence)
+Grape::Validations.register_validator(:integer_none_any, ::API::Helpers::CustomValidators::IntegerNoneAny)
diff --git a/lib/api/helpers/headers_helpers.rb b/lib/api/helpers/headers_helpers.rb
index c9c44e3c218..7553af9d156 100644
--- a/lib/api/helpers/headers_helpers.rb
+++ b/lib/api/helpers/headers_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module Helpers
module HeadersHelpers
diff --git a/lib/api/helpers/internal_helpers.rb b/lib/api/helpers/internal_helpers.rb
index 83151be82ad..4eaaca96b49 100644
--- a/lib/api/helpers/internal_helpers.rb
+++ b/lib/api/helpers/internal_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module Helpers
module InternalHelpers
diff --git a/lib/api/helpers/members_helpers.rb b/lib/api/helpers/members_helpers.rb
index 518aaa62aef..73d58ee7f37 100644
--- a/lib/api/helpers/members_helpers.rb
+++ b/lib/api/helpers/members_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# rubocop:disable GitlabSecurity/PublicSend
module API
diff --git a/lib/api/helpers/notes_helpers.rb b/lib/api/helpers/notes_helpers.rb
index 7b1f5c2584b..216b2c45741 100644
--- a/lib/api/helpers/notes_helpers.rb
+++ b/lib/api/helpers/notes_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module Helpers
module NotesHelpers
diff --git a/lib/api/helpers/pagination.rb b/lib/api/helpers/pagination.rb
index 50bcd4e0437..d311cbb5f7e 100644
--- a/lib/api/helpers/pagination.rb
+++ b/lib/api/helpers/pagination.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module Helpers
module Pagination
diff --git a/lib/api/helpers/project_snapshots_helpers.rb b/lib/api/helpers/project_snapshots_helpers.rb
index 94798a8cb51..1b5dc281e38 100644
--- a/lib/api/helpers/project_snapshots_helpers.rb
+++ b/lib/api/helpers/project_snapshots_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module Helpers
module ProjectSnapshotsHelpers
diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb
index 98672f2f765..e6a72b949f9 100644
--- a/lib/api/helpers/projects_helpers.rb
+++ b/lib/api/helpers/projects_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module Helpers
module ProjectsHelpers
diff --git a/lib/api/helpers/related_resources_helpers.rb b/lib/api/helpers/related_resources_helpers.rb
index bc7333ca4b3..793ae11b41d 100644
--- a/lib/api/helpers/related_resources_helpers.rb
+++ b/lib/api/helpers/related_resources_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module Helpers
module RelatedResourcesHelpers
diff --git a/lib/api/helpers/runner.rb b/lib/api/helpers/runner.rb
index 61eb88d3331..45d0343bc89 100644
--- a/lib/api/helpers/runner.rb
+++ b/lib/api/helpers/runner.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module Helpers
module Runner
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index 71b87f60bf6..ae40b5f7557 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
# Internal access API
class Internal < Grape::API
@@ -38,7 +40,7 @@ module API
elsif params[:user_id]
User.find_by(id: params[:user_id])
elsif params[:username]
- User.find_by_username(params[:username])
+ UserFinder.new(params[:username]).find_by_username
end
protocol = params[:protocol]
@@ -63,6 +65,8 @@ module API
result
rescue Gitlab::GitAccess::UnauthorizedError => e
break response_with_status(code: 401, success: false, message: e.message)
+ rescue Gitlab::GitAccess::TimeoutError => e
+ break response_with_status(code: 503, success: false, message: e.message)
rescue Gitlab::GitAccess::NotFoundError => e
break response_with_status(code: 404, success: false, message: e.message)
end
@@ -152,7 +156,7 @@ module API
elsif params[:user_id]
user = User.find_by(id: params[:user_id])
elsif params[:username]
- user = User.find_by(username: params[:username])
+ user = UserFinder.new(params[:username]).find_by_username
end
present user, with: Entities::UserSafe
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index bcb03a0b540..dac700482b4 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Issues < Grape::API
include PaginationParams
@@ -6,6 +8,15 @@ module API
helpers ::Gitlab::IssuableMetadata
+ # EE::API::Issues would override the following helpers
+ helpers do
+ params :issues_params_ee do
+ end
+
+ params :issue_params_ee do
+ end
+ end
+
helpers do
# rubocop: disable CodeReuse/ActiveRecord
def find_issues(args = {})
@@ -17,7 +28,7 @@ module API
args[:scope] = args[:scope].underscore if args[:scope]
issues = IssuesFinder.new(current_user, args).execute
- .preload(:assignees, :labels, :notes, :timelogs, :project, :author)
+ .preload(:assignees, :labels, :notes, :timelogs, :project, :author, :closed_by)
issues.reorder(args[:order_by] => args[:sort])
end
@@ -38,14 +49,17 @@ module API
optional :updated_after, type: DateTime, desc: 'Return issues updated after the specified time'
optional :updated_before, type: DateTime, desc: 'Return issues updated before the specified time'
optional :author_id, type: Integer, desc: 'Return issues which are authored by the user with the given ID'
- optional :assignee_id, type: Integer, desc: 'Return issues which are assigned to the user with the given ID'
+ optional :assignee_id, types: [Integer, String], integer_none_any: true,
+ desc: 'Return issues which are assigned to the user with the given ID'
optional :scope, type: String, values: %w[created-by-me assigned-to-me created_by_me assigned_to_me all],
desc: 'Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`'
optional :my_reaction_emoji, type: String, desc: 'Return issues reacted by the authenticated user by the given emoji'
use :pagination
+
+ use :issues_params_ee
end
- params :issue_params_ce do
+ params :issue_params do
optional :description, type: String, desc: 'The description of an issue'
optional :assignee_ids, type: Array[Integer], desc: 'The array of user IDs to assign issue'
optional :assignee_id, type: Integer, desc: '[Deprecated] The ID of a user to assign issue'
@@ -54,10 +68,8 @@ module API
optional :due_date, type: String, desc: 'Date string in the format YEAR-MONTH-DAY'
optional :confidential, type: Boolean, desc: 'Boolean parameter if the issue should be confidential'
optional :discussion_locked, type: Boolean, desc: " Boolean parameter indicating if the issue's discussion is locked"
- end
- params :issue_params do
- use :issue_params_ce
+ use :issue_params_ee
end
end
@@ -89,7 +101,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a group'
end
- resource :groups, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get a list of group issues' do
success Entities::IssueBasic
end
@@ -116,7 +128,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
include TimeTrackingEndpoints
desc 'Get a list of project issues' do
@@ -282,6 +294,30 @@ module API
end
# rubocop: enable CodeReuse/ActiveRecord
+ desc 'List merge requests that are related to the issue' do
+ success Entities::MergeRequestBasic
+ end
+ params do
+ requires :issue_iid, type: Integer, desc: 'The internal ID of a project issue'
+ end
+ get ':id/issues/:issue_iid/related_merge_requests' do
+ issue = find_project_issue(params[:issue_iid])
+
+ merge_request_iids = ::Issues::ReferencedMergeRequestsService.new(user_project, current_user)
+ .execute(issue)
+ .flatten
+ .map(&:iid)
+
+ merge_requests =
+ if merge_request_iids.present?
+ MergeRequestsFinder.new(current_user, project_id: user_project.id, iids: merge_request_iids).execute
+ else
+ MergeRequest.none
+ end
+
+ present paginate(merge_requests), with: Entities::MergeRequestBasic, current_user: current_user, project: user_project
+ end
+
desc 'List merge requests closing issue' do
success Entities::MergeRequestBasic
end
diff --git a/lib/api/job_artifacts.rb b/lib/api/job_artifacts.rb
index ab4203c4e25..7c2d8ff11bf 100644
--- a/lib/api/job_artifacts.rb
+++ b/lib/api/job_artifacts.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class JobArtifacts < Grape::API
before { authenticate_non_get! }
@@ -12,7 +14,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Download the artifacts archive from a job' do
detail 'This feature was introduced in GitLab 8.10'
end
diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb
index 27ffd42834c..c3f8a84d742 100644
--- a/lib/api/jobs.rb
+++ b/lib/api/jobs.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Jobs < Grape::API
include PaginationParams
@@ -7,7 +9,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
helpers do
params :optional_scope do
optional :scope, types: [String, Array[String]], desc: 'The scope of builds to show',
@@ -149,7 +151,7 @@ module API
present build, with: Entities::Job
end
- desc 'Trigger a manual job' do
+ desc 'Trigger a actionable job (manual, delayed, etc)' do
success Entities::Job
detail 'This feature was added in GitLab 8.11'
end
diff --git a/lib/api/keys.rb b/lib/api/keys.rb
index fd93f797f72..d5280a0035d 100644
--- a/lib/api/keys.rb
+++ b/lib/api/keys.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
# Keys API
class Keys < Grape::API
diff --git a/lib/api/labels.rb b/lib/api/labels.rb
index 98c9818db39..2e676b0aa6b 100644
--- a/lib/api/labels.rb
+++ b/lib/api/labels.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Labels < Grape::API
include PaginationParams
@@ -7,7 +9,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get all labels of the project' do
success Entities::Label
end
diff --git a/lib/api/lint.rb b/lib/api/lint.rb
index d202eaa4c49..0342a4b6654 100644
--- a/lib/api/lint.rb
+++ b/lib/api/lint.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Lint < Grape::API
namespace :ci do
diff --git a/lib/api/markdown.rb b/lib/api/markdown.rb
index 5d55224c1a7..de77bef43ce 100644
--- a/lib/api/markdown.rb
+++ b/lib/api/markdown.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Markdown < Grape::API
params do
@@ -10,7 +12,8 @@ module API
detail "This feature was introduced in GitLab 11.0."
end
post do
- context = { only_path: false }
+ context = { only_path: false, current_user: current_user }
+ context[:pipeline] = params[:gfm] ? :full : :plain_markdown
if params[:project]
project = Project.find_by_full_path(params[:project])
@@ -22,9 +25,7 @@ module API
context[:skip_project_check] = true
end
- context[:pipeline] = params[:gfm] ? :full : :plain_markdown
-
- { html: Banzai.render(params[:text], context) }
+ { html: Banzai.render_and_post_process(params[:text], context) }
end
end
end
diff --git a/lib/api/members.rb b/lib/api/members.rb
index 4d8e23dee91..461ffe71a62 100644
--- a/lib/api/members.rb
+++ b/lib/api/members.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Members < Grape::API
include PaginationParams
@@ -10,7 +12,7 @@ module API
params do
requires :id, type: String, desc: "The #{source_type} ID"
end
- resource source_type.pluralize, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource source_type.pluralize, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Gets a list of group or project members viewable by the authenticated user.' do
success Entities::Member
end
diff --git a/lib/api/merge_request_diffs.rb b/lib/api/merge_request_diffs.rb
index 95ef8f42954..6ad30aa56e0 100644
--- a/lib/api/merge_request_diffs.rb
+++ b/lib/api/merge_request_diffs.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
# MergeRequestDiff API
class MergeRequestDiffs < Grape::API
@@ -8,7 +10,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get a list of merge request diff versions' do
detail 'This feature was introduced in GitLab 8.12.'
success Entities::MergeRequestDiff
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index cad38271cbb..8c1951cc535 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class MergeRequests < Grape::API
include PaginationParams
@@ -31,7 +33,6 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
def find_merge_requests(args = {})
args = declared_params.merge(args)
-
args[:milestone_title] = args.delete(:milestone)
args[:label_name] = args.delete(:labels)
args[:scope] = args[:scope].underscore if args[:scope]
@@ -44,7 +45,7 @@ module API
return merge_requests if args[:view] == 'simple'
merge_requests
- .preload(:notes, :author, :assignee, :milestone, :latest_merge_request_diff, :labels, :timelogs)
+ .preload(:notes, :author, :assignee, :milestone, :latest_merge_request_diff, :labels, :timelogs, metrics: [:latest_closed_by, :merged_by])
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -73,6 +74,19 @@ module API
options
end
+ def authorize_push_to_merge_request!(merge_request)
+ forbidden!('Source branch does not exist') unless
+ merge_request.source_branch_exists?
+
+ user_access = Gitlab::UserAccess.new(
+ current_user,
+ project: merge_request.source_project
+ )
+
+ forbidden!('Cannot push to source branch') unless
+ user_access.can_push_to_branch?(merge_request.source_branch)
+ end
+
params :merge_requests_params do
optional :state, type: String, values: %w[opened closed locked merged all], default: 'all',
desc: 'Return opened, closed, locked, merged, or all merge requests'
@@ -88,13 +102,15 @@ module API
optional :updated_before, type: DateTime, desc: 'Return merge requests updated before the specified time'
optional :view, type: String, values: %w[simple], desc: 'If simple, returns the `iid`, URL, title, description, and basic state of merge request'
optional :author_id, type: Integer, desc: 'Return merge requests which are authored by the user with the given ID'
- optional :assignee_id, type: Integer, desc: 'Return merge requests which are assigned to the user with the given ID'
+ optional :assignee_id, types: [Integer, String], integer_none_any: true,
+ desc: 'Return merge requests which are assigned to the user with the given ID'
optional :scope, type: String, values: %w[created-by-me assigned-to-me created_by_me assigned_to_me all],
desc: 'Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`'
optional :my_reaction_emoji, type: String, desc: 'Return issues reacted by the authenticated user by the given emoji'
optional :source_branch, type: String, desc: 'Return merge requests with the given source branch'
optional :target_branch, type: String, desc: 'Return merge requests with the given target branch'
optional :search, type: String, desc: 'Search merge requests for text present in the title or description'
+ optional :wip, type: String, values: %w[yes no], desc: 'Search merge requests for WIP in the title'
use :pagination
end
end
@@ -119,7 +135,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a group'
end
- resource :groups, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get a list of group merge requests' do
success Entities::MergeRequestBasic
end
@@ -138,7 +154,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
include TimeTrackingEndpoints
helpers do
@@ -236,6 +252,7 @@ module API
requires :merge_request_iid, type: Integer, desc: 'The IID of a merge request'
optional :render_html, type: Boolean, desc: 'Returns the description and title rendered HTML'
optional :include_diverged_commits_count, type: Boolean, desc: 'Returns the commits count behind the target branch'
+ optional :include_rebase_in_progress, type: Boolean, desc: 'Returns whether a rebase operation is ongoing '
end
desc 'Get a single merge request' do
success Entities::MergeRequest
@@ -243,7 +260,13 @@ module API
get ':id/merge_requests/:merge_request_iid' do
merge_request = find_merge_request_with_access(params[:merge_request_iid])
- present merge_request, with: Entities::MergeRequest, current_user: current_user, project: user_project, render_html: params[:render_html], include_diverged_commits_count: params[:include_diverged_commits_count]
+ present merge_request,
+ with: Entities::MergeRequest,
+ current_user: current_user,
+ project: user_project,
+ render_html: params[:render_html],
+ include_diverged_commits_count: params[:include_diverged_commits_count],
+ include_rebase_in_progress: params[:include_rebase_in_progress]
end
desc 'Get the participants of a merge request' do
@@ -375,6 +398,19 @@ module API
.cancel(merge_request)
end
+ desc 'Rebase the merge request against its target branch' do
+ detail 'This feature was added in GitLab 11.6'
+ end
+ put ':id/merge_requests/:merge_request_iid/rebase' do
+ merge_request = find_project_merge_request(params[:merge_request_iid])
+
+ authorize_push_to_merge_request!(merge_request)
+
+ RebaseWorker.perform_async(merge_request.id, current_user.id)
+
+ status :accepted
+ end
+
desc 'List issues that will be closed on merge' do
success Entities::MRNote
end
diff --git a/lib/api/milestone_responses.rb b/lib/api/milestone_responses.rb
index a8eb137e46a..a0ca39b69d4 100644
--- a/lib/api/milestone_responses.rb
+++ b/lib/api/milestone_responses.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module MilestoneResponses
extend ActiveSupport::Concern
diff --git a/lib/api/namespaces.rb b/lib/api/namespaces.rb
index 32b77aedba8..06a57e3cd6f 100644
--- a/lib/api/namespaces.rb
+++ b/lib/api/namespaces.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Namespaces < Grape::API
include PaginationParams
@@ -26,7 +28,7 @@ module API
params do
requires :id, type: String, desc: "Namespace's ID or path"
end
- get ':id' do
+ get ':id', requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
present user_namespace, with: Entities::Namespace, current_user: current_user
end
end
diff --git a/lib/api/notes.rb b/lib/api/notes.rb
index dc9373bb3c2..1bdf7aeb119 100644
--- a/lib/api/notes.rb
+++ b/lib/api/notes.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Notes < Grape::API
include PaginationParams
@@ -14,7 +16,7 @@ module API
params do
requires :id, type: String, desc: "The ID of a #{parent_type}"
end
- resource parent_type.pluralize.to_sym, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource parent_type.pluralize.to_sym, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
noteables_str = noteable_type.to_s.underscore.pluralize
desc "Get a list of #{noteable_type.to_s.downcase} notes" do
diff --git a/lib/api/notification_settings.rb b/lib/api/notification_settings.rb
index bf0d6b9e434..8cb46bd3ad6 100644
--- a/lib/api/notification_settings.rb
+++ b/lib/api/notification_settings.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
# notification_settings API
class NotificationSettings < Grape::API
@@ -56,7 +58,7 @@ module API
params do
requires :id, type: String, desc: "The #{source_type} ID"
end
- resource source_type.pluralize, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource source_type.pluralize, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc "Get #{source_type} level notification level settings, defaults to Global" do
detail 'This feature was introduced in GitLab 8.12'
success Entities::NotificationSetting
diff --git a/lib/api/pages_domains.rb b/lib/api/pages_domains.rb
index 8730c91b426..78442f465bd 100644
--- a/lib/api/pages_domains.rb
+++ b/lib/api/pages_domains.rb
@@ -1,8 +1,10 @@
+# frozen_string_literal: true
+
module API
class PagesDomains < Grape::API
include PaginationParams
- PAGES_DOMAINS_ENDPOINT_REQUIREMENTS = API::PROJECT_ENDPOINT_REQUIREMENTS.merge(domain: API::NO_SLASH_URL_PART_REGEX)
+ PAGES_DOMAINS_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(domain: API::NO_SLASH_URL_PART_REGEX)
before do
authenticate!
@@ -52,7 +54,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do
require_pages_enabled!
end
diff --git a/lib/api/pagination_params.rb b/lib/api/pagination_params.rb
index f566eb3ed2b..ae03595eb25 100644
--- a/lib/api/pagination_params.rb
+++ b/lib/api/pagination_params.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
# Concern for declare pagination params.
#
diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb
index 5bd1ce8c5e1..47b711917e2 100644
--- a/lib/api/pipeline_schedules.rb
+++ b/lib/api/pipeline_schedules.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class PipelineSchedules < Grape::API
include PaginationParams
@@ -7,7 +9,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get all pipeline schedules' do
success Entities::PipelineSchedule
end
diff --git a/lib/api/pipelines.rb b/lib/api/pipelines.rb
index 5cce96d5ae7..62d07d945e2 100644
--- a/lib/api/pipelines.rb
+++ b/lib/api/pipelines.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Pipelines < Grape::API
include PaginationParams
@@ -7,7 +9,7 @@ module API
params do
requires :id, type: String, desc: 'The project ID'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get all Pipelines of the project' do
detail 'This feature was introduced in GitLab 8.11.'
success Entities::PipelineBasic
@@ -79,6 +81,21 @@ module API
present pipeline, with: Entities::Pipeline
end
+ desc 'Deletes a pipeline' do
+ detail 'This feature was introduced in GitLab 11.6'
+ http_codes [[204, 'Pipeline was deleted'], [403, 'Forbidden']]
+ end
+ params do
+ requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
+ end
+ delete ':id/pipelines/:pipeline_id' do
+ authorize! :destroy_pipeline, pipeline
+
+ destroy_conditionally!(pipeline) do
+ ::Ci::DestroyPipelineService.new(user_project, current_user).execute(pipeline)
+ end
+ end
+
desc 'Retry builds in the pipeline' do
detail 'This feature was introduced in GitLab 8.11.'
success Entities::Pipeline
diff --git a/lib/api/project_export.rb b/lib/api/project_export.rb
index 8562ae6d737..e34ed0bdb44 100644
--- a/lib/api/project_export.rb
+++ b/lib/api/project_export.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class ProjectExport < Grape::API
before do
diff --git a/lib/api/project_hooks.rb b/lib/api/project_hooks.rb
index 0fb454bc22e..0e7576c9243 100644
--- a/lib/api/project_hooks.rb
+++ b/lib/api/project_hooks.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class ProjectHooks < Grape::API
include PaginationParams
@@ -27,7 +29,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get project hooks' do
success Entities::ProjectHook
end
diff --git a/lib/api/project_import.rb b/lib/api/project_import.rb
index bc5152e539f..c64ec2fcc95 100644
--- a/lib/api/project_import.rb
+++ b/lib/api/project_import.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class ProjectImport < Grape::API
include PaginationParams
@@ -21,7 +23,7 @@ module API
forbidden! unless Gitlab::CurrentSettings.import_sources.include?('gitlab_project')
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
params do
requires :path, type: String, desc: 'The new project path and name'
requires :file, type: File, desc: 'The project export file to be imported'
diff --git a/lib/api/project_milestones.rb b/lib/api/project_milestones.rb
index 72cf32d7717..da31bcb8dac 100644
--- a/lib/api/project_milestones.rb
+++ b/lib/api/project_milestones.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class ProjectMilestones < Grape::API
include PaginationParams
@@ -10,7 +12,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get a list of project milestones' do
success Entities::Milestone
end
diff --git a/lib/api/project_snapshots.rb b/lib/api/project_snapshots.rb
index 71005acc587..175fbb2ce92 100644
--- a/lib/api/project_snapshots.rb
+++ b/lib/api/project_snapshots.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class ProjectSnapshots < Grape::API
helpers ::API::Helpers::ProjectSnapshotsHelpers
diff --git a/lib/api/project_snippets.rb b/lib/api/project_snippets.rb
index 1ef176b1320..a607df411a6 100644
--- a/lib/api/project_snippets.rb
+++ b/lib/api/project_snippets.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class ProjectSnippets < Grape::API
include PaginationParams
@@ -7,7 +9,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
helpers do
def handle_project_member_errors(errors)
if errors[:project_access].any?
diff --git a/lib/api/project_templates.rb b/lib/api/project_templates.rb
new file mode 100644
index 00000000000..d05ddad7466
--- /dev/null
+++ b/lib/api/project_templates.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+module API
+ class ProjectTemplates < Grape::API
+ include PaginationParams
+
+ TEMPLATE_TYPES = %w[dockerfiles gitignores gitlab_ci_ymls licenses].freeze
+
+ before { authenticate_non_get! }
+
+ params do
+ requires :id, type: String, desc: 'The ID of a project'
+ requires :type, type: String, values: TEMPLATE_TYPES, desc: 'The type (dockerfiles|gitignores|gitlab_ci_ymls|licenses) of the template'
+ end
+ resource :projects do
+ desc 'Get a list of templates available to this project' do
+ detail 'This endpoint was introduced in GitLab 11.4'
+ end
+ params do
+ use :pagination
+ end
+ get ':id/templates/:type' do
+ templates = TemplateFinder
+ .build(params[:type], user_project)
+ .execute
+
+ present paginate(::Kaminari.paginate_array(templates)), with: Entities::TemplatesList
+ end
+
+ desc 'Download a template available to this project' do
+ detail 'This endpoint was introduced in GitLab 11.4'
+ end
+ params do
+ requires :name, type: String, desc: 'The name of the template'
+
+ optional :project, type: String, desc: 'The project name to use when expanding placeholders in the template. Only affects licenses'
+ optional :fullname, type: String, desc: 'The full name of the copyright holder to use when expanding placeholders in the template. Only affects licenses'
+ end
+ get ':id/templates/:type/:name', requirements: { name: /[\w\.-]+/ } do
+ template = TemplateFinder
+ .build(params[:type], user_project, name: params[:name])
+ .execute
+
+ not_found!('Template') unless template.present?
+
+ template.resolve!(
+ project_name: params[:project].presence,
+ fullname: params[:fullname].presence || current_user&.name
+ )
+
+ if template.is_a?(::LicenseTemplate)
+ present template, with: Entities::License
+ else
+ present template, with: Entities::Template
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index ee426f39523..f5d21d8923f 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_dependency 'declarative_policy'
module API
@@ -112,7 +114,8 @@ module API
options = options.reverse_merge(
with: current_user ? Entities::ProjectWithAccess : Entities::BasicProjectDetails,
statistics: params[:statistics],
- current_user: current_user
+ current_user: current_user,
+ license: false
)
options[:with] = Entities::BasicProjectDetails if params[:simple]
@@ -125,7 +128,7 @@ module API
end
end
- resource :users, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :users, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get a user projects' do
success Entities::BasicProjectDetails
end
@@ -221,20 +224,24 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get a single project' do
success Entities::ProjectWithAccess
end
params do
use :statistics_params
use :with_custom_attributes
+
+ optional :license, type: Boolean, default: false,
+ desc: 'Include project license data'
end
get ":id" do
options = {
with: current_user ? Entities::ProjectWithAccess : Entities::BasicProjectDetails,
current_user: current_user,
user_can_admin_project: can?(current_user, :admin_project, user_project),
- statistics: params[:statistics]
+ statistics: params[:statistics],
+ license: params[:license]
}
project, options = with_custom_attributes(user_project, options)
@@ -285,6 +292,12 @@ module API
present_projects forks
end
+ desc 'Check pages access of this project'
+ get ':id/pages_access' do
+ authorize! :read_pages_content, user_project unless user_project.public_pages?
+ status 200
+ end
+
desc 'Update an existing project' do
success Entities::Project
end
diff --git a/lib/api/projects_relation_builder.rb b/lib/api/projects_relation_builder.rb
index 9fd79c491c2..8edcfea7c93 100644
--- a/lib/api/projects_relation_builder.rb
+++ b/lib/api/projects_relation_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module ProjectsRelationBuilder
extend ActiveSupport::Concern
diff --git a/lib/api/protected_branches.rb b/lib/api/protected_branches.rb
index 804f6fa9b73..5af43448727 100644
--- a/lib/api/protected_branches.rb
+++ b/lib/api/protected_branches.rb
@@ -1,15 +1,17 @@
+# frozen_string_literal: true
+
module API
class ProtectedBranches < Grape::API
include PaginationParams
- BRANCH_ENDPOINT_REQUIREMENTS = API::PROJECT_ENDPOINT_REQUIREMENTS.merge(name: API::NO_SLASH_URL_PART_REGEX)
+ BRANCH_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(name: API::NO_SLASH_URL_PART_REGEX)
before { authorize_admin_project }
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc "Get a project's protected branches" do
success Entities::ProtectedBranch
end
diff --git a/lib/api/protected_tags.rb b/lib/api/protected_tags.rb
index e406344e42d..ee13473c848 100644
--- a/lib/api/protected_tags.rb
+++ b/lib/api/protected_tags.rb
@@ -1,15 +1,17 @@
+# frozen_string_literal: true
+
module API
class ProtectedTags < Grape::API
include PaginationParams
- TAG_ENDPOINT_REQUIREMENTS = API::PROJECT_ENDPOINT_REQUIREMENTS.merge(name: API::NO_SLASH_URL_PART_REGEX)
+ TAG_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(name: API::NO_SLASH_URL_PART_REGEX)
before { authorize_admin_project }
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc "Get a project's protected tags" do
detail 'This feature was introduced in GitLab 11.3.'
success Entities::ProtectedTag
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index 79736107bbb..32e05d84491 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'mime/types'
module API
@@ -9,7 +11,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
helpers do
def handle_project_member_errors(errors)
if errors[:project_access].any?
@@ -128,18 +130,13 @@ module API
success Entities::Commit
end
params do
- # For now we just support 2 refs passed, but `merge-base` supports
- # multiple defining this as an Array instead of 2 separate params will
- # make sure we don't need to deprecate this API in favor of one
- # supporting multiple commits when this functionality gets added to
- # Gitaly
requires :refs, type: Array[String]
end
get ':id/repository/merge_base' do
refs = params[:refs]
- unless refs.size == 2
- render_api_error!('Provide exactly 2 refs', 400)
+ if refs.size < 2
+ render_api_error!('Provide at least 2 refs', 400)
end
merge_base = Gitlab::Git::MergeBase.new(user_project.repository, refs)
diff --git a/lib/api/resource_label_events.rb b/lib/api/resource_label_events.rb
index b6fbe8c0235..0c328f7268e 100644
--- a/lib/api/resource_label_events.rb
+++ b/lib/api/resource_label_events.rb
@@ -16,7 +16,7 @@ module API
params do
requires :id, type: String, desc: "The ID of a #{parent_type}"
end
- resource parent_type.pluralize.to_sym, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource parent_type.pluralize.to_sym, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc "Get a list of #{eventable_type.to_s.downcase} resource label events" do
success Entities::ResourceLabelEvent
detail 'This feature was introduced in 11.3'
diff --git a/lib/api/runner.rb b/lib/api/runner.rb
index b2d46cef23c..2f15f3a7d76 100644
--- a/lib/api/runner.rb
+++ b/lib/api/runner.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Runner < Grape::API
helpers ::API::Helpers::Runner
@@ -140,8 +142,7 @@ module API
requires :id, type: Integer, desc: %q(Job's ID)
optional :trace, type: String, desc: %q(Job's full trace)
optional :state, type: String, desc: %q(Job's status: success, failed)
- optional :failure_reason, type: String, values: CommitStatus.failure_reasons.keys,
- desc: %q(Job's failure_reason)
+ optional :failure_reason, type: String, desc: %q(Job's failure_reason)
end
put '/:id' do
job = authenticate_job!
diff --git a/lib/api/runners.rb b/lib/api/runners.rb
index 30abd0b63e9..f72b33605a7 100644
--- a/lib/api/runners.rb
+++ b/lib/api/runners.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Runners < Grape::API
include PaginationParams
@@ -11,10 +13,18 @@ module API
params do
optional :scope, type: String, values: Ci::Runner::AVAILABLE_STATUSES,
desc: 'The scope of specific runners to show'
+ optional :type, type: String, values: Ci::Runner::AVAILABLE_TYPES,
+ desc: 'The type of the runners to show'
+ optional :status, type: String, values: Ci::Runner::AVAILABLE_STATUSES,
+ desc: 'The status of the runners to show'
use :pagination
end
get do
- runners = filter_runners(current_user.ci_owned_runners, params[:scope], allowed_scopes: Ci::Runner::AVAILABLE_STATUSES)
+ runners = current_user.ci_owned_runners
+ runners = filter_runners(runners, params[:scope], allowed_scopes: Ci::Runner::AVAILABLE_STATUSES)
+ runners = filter_runners(runners, params[:type], allowed_scopes: Ci::Runner::AVAILABLE_TYPES)
+ runners = filter_runners(runners, params[:status], allowed_scopes: Ci::Runner::AVAILABLE_STATUSES)
+
present paginate(runners), with: Entities::Runner
end
@@ -24,11 +34,20 @@ module API
params do
optional :scope, type: String, values: Ci::Runner::AVAILABLE_SCOPES,
desc: 'The scope of specific runners to show'
+ optional :type, type: String, values: Ci::Runner::AVAILABLE_TYPES,
+ desc: 'The type of the runners to show'
+ optional :status, type: String, values: Ci::Runner::AVAILABLE_STATUSES,
+ desc: 'The status of the runners to show'
use :pagination
end
get 'all' do
authenticated_as_admin!
- runners = filter_runners(Ci::Runner.all, params[:scope])
+
+ runners = Ci::Runner.all
+ runners = filter_runners(runners, params[:scope])
+ runners = filter_runners(runners, params[:type], allowed_scopes: Ci::Runner::AVAILABLE_TYPES)
+ runners = filter_runners(runners, params[:status], allowed_scopes: Ci::Runner::AVAILABLE_STATUSES)
+
present paginate(runners), with: Entities::Runner
end
@@ -94,7 +113,7 @@ module API
optional :status, type: String, desc: 'Status of the job', values: Ci::Build::AVAILABLE_STATUSES
use :pagination
end
- get ':id/jobs' do
+ get ':id/jobs' do
runner = get_runner(params[:id])
authenticate_list_runners_jobs!(runner)
@@ -107,7 +126,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before { authorize_admin_project }
desc 'Get runners available for project' do
@@ -116,10 +135,18 @@ module API
params do
optional :scope, type: String, values: Ci::Runner::AVAILABLE_SCOPES,
desc: 'The scope of specific runners to show'
+ optional :type, type: String, values: Ci::Runner::AVAILABLE_TYPES,
+ desc: 'The type of the runners to show'
+ optional :status, type: String, values: Ci::Runner::AVAILABLE_STATUSES,
+ desc: 'The status of the runners to show'
use :pagination
end
get ':id/runners' do
- runners = filter_runners(Ci::Runner.owned_or_instance_wide(user_project.id), params[:scope])
+ runners = Ci::Runner.owned_or_instance_wide(user_project.id)
+ runners = filter_runners(runners, params[:scope])
+ runners = filter_runners(runners, params[:type], allowed_scopes: Ci::Runner::AVAILABLE_TYPES)
+ runners = filter_runners(runners, params[:status], allowed_scopes: Ci::Runner::AVAILABLE_STATUSES)
+
present paginate(runners), with: Entities::Runner
end
diff --git a/lib/api/scope.rb b/lib/api/scope.rb
index d5165b2e482..707775e5d15 100644
--- a/lib/api/scope.rb
+++ b/lib/api/scope.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Encapsulate a scope used for authorization, such as `api`, or `read_user`
module API
class Scope
diff --git a/lib/api/search.rb b/lib/api/search.rb
index 37fbabe419c..5900e1cccc2 100644
--- a/lib/api/search.rb
+++ b/lib/api/search.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Search < Grape::API
include PaginationParams
@@ -68,7 +70,7 @@ module API
end
end
- resource :groups, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Search on GitLab' do
detail 'This feature was introduced in GitLab 10.5.'
end
@@ -87,7 +89,7 @@ module API
end
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Search on GitLab' do
detail 'This feature was introduced in GitLab 10.5.'
end
diff --git a/lib/api/services.rb b/lib/api/services.rb
index 0ae05ce08f1..d60f0f5f08d 100644
--- a/lib/api/services.rb
+++ b/lib/api/services.rb
@@ -298,6 +298,14 @@ module API
desc: 'Title'
}
],
+ 'discord' => [
+ {
+ required: true,
+ name: :webhook,
+ type: String,
+ desc: 'Discord webhook. e.g. https://discordapp.com/api/webhooks/…'
+ }
+ ],
'drone-ci' => [
{
required: true,
@@ -677,6 +685,7 @@ module API
BuildkiteService,
CampfireService,
CustomIssueTrackerService,
+ DiscordService,
DroneCiService,
EmailsOnPushService,
ExternalWikiService,
@@ -754,7 +763,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before { authenticate! }
before { authorize_admin_project }
@@ -833,7 +842,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc "Trigger a slash command for #{service_slug}" do
detail 'Added in GitLab 8.13'
end
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index c80d9890706..f53ba0ab761 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Settings < Grape::API
before { authenticated_as_admin! }
@@ -64,10 +66,6 @@ module API
optional :html_emails_enabled, type: Boolean, desc: 'By default GitLab sends emails in HTML and plain text formats so mail clients can choose what format to use. Disable this option if you only want to send emails in plain text format.'
optional :import_sources, type: Array[String], values: %w[github bitbucket gitlab google_code fogbugz git gitlab_project manifest],
desc: 'Enabled sources for code import during project creation. OmniAuth must be configured for GitHub, Bitbucket, and GitLab.com'
- optional :koding_enabled, type: Boolean, desc: 'Enable Koding'
- given koding_enabled: ->(val) { val } do
- requires :koding_url, type: String, desc: 'The Koding team URL'
- end
optional :max_artifacts_size, type: Integer, desc: "Set the maximum file size for each job's artifacts"
optional :max_attachment_size, type: Integer, desc: 'Maximum attachment size in MB'
optional :max_pages_size, type: Integer, desc: 'Maximum size of pages in MB'
@@ -117,11 +115,6 @@ module API
given shared_runners_enabled: ->(val) { val } do
requires :shared_runners_text, type: String, desc: 'Shared runners text '
end
- optional :sidekiq_throttling_enabled, type: Boolean, desc: 'Enable Sidekiq Job Throttling'
- given sidekiq_throttling_enabled: ->(val) { val } do
- requires :sidekiq_throttling_factor, type: Float, desc: 'The factor by which the queues should be throttled. A value between 0.0 and 1.0, exclusive.'
- requires :sidekiq_throttling_queues, type: Array[String], desc: 'Choose which queues you wish to throttle'
- end
optional :sign_in_text, type: String, desc: 'The sign in text of the GitLab application'
optional :signin_enabled, type: Boolean, desc: 'Flag indicating if password authentication is enabled for the web interface' # support legacy names, can be removed in v5
optional :signup_enabled, type: Boolean, desc: 'Flag indicating if sign up is enabled'
diff --git a/lib/api/sidekiq_metrics.rb b/lib/api/sidekiq_metrics.rb
index 11f2b40269a..daa9598a204 100644
--- a/lib/api/sidekiq_metrics.rb
+++ b/lib/api/sidekiq_metrics.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'sidekiq/api'
module API
diff --git a/lib/api/snippets.rb b/lib/api/snippets.rb
index 6352a9c8742..326d55afd0e 100644
--- a/lib/api/snippets.rb
+++ b/lib/api/snippets.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
# Snippets API
class Snippets < Grape::API
@@ -12,7 +14,7 @@ module API
end
def public_snippets
- SnippetsFinder.new(current_user, visibility: Snippet::PUBLIC).execute
+ SnippetsFinder.new(current_user, scope: :are_public).execute
end
end
@@ -144,6 +146,7 @@ module API
env['api.format'] = :txt
content_type 'text/plain'
+ header['Content-Disposition'] = 'attachment'
present snippet.content
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/lib/api/submodules.rb b/lib/api/submodules.rb
new file mode 100644
index 00000000000..72d7d994102
--- /dev/null
+++ b/lib/api/submodules.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module API
+ class Submodules < Grape::API
+ before { authenticate! }
+
+ helpers do
+ def commit_params(attrs)
+ {
+ submodule: attrs[:submodule],
+ commit_sha: attrs[:commit_sha],
+ branch_name: attrs[:branch],
+ commit_message: attrs[:commit_message]
+ }
+ end
+ end
+
+ params do
+ requires :id, type: String, desc: 'The project ID'
+ end
+ resource :projects, requirements: Files::FILE_ENDPOINT_REQUIREMENTS do
+ desc 'Update existing submodule reference in repository' do
+ success Entities::Commit
+ end
+ params do
+ requires :submodule, type: String, desc: 'Url encoded full path to submodule.'
+ requires :commit_sha, type: String, desc: 'Commit sha to update the submodule to.'
+ requires :branch, type: String, desc: 'Name of the branch to commit into.'
+ optional :commit_message, type: String, desc: 'Commit message. If no message is provided a default one will be set.'
+ end
+ put ":id/repository/submodules/:submodule", requirements: Files::FILE_ENDPOINT_REQUIREMENTS do
+ authorize! :push_code, user_project
+
+ submodule_params = declared_params(include_missing: false)
+
+ result = ::Submodules::UpdateService.new(user_project, current_user, commit_params(submodule_params)).execute
+
+ if result[:status] == :success
+ commit_detail = user_project.repository.commit(result[:result])
+ present commit_detail, with: Entities::CommitDetail
+ else
+ render_api_error!(result[:message], result[:http_status] || 400)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/subscriptions.rb b/lib/api/subscriptions.rb
index b3e1e23031a..74ad3c35a61 100644
--- a/lib/api/subscriptions.rb
+++ b/lib/api/subscriptions.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Subscriptions < Grape::API
before { authenticate! }
@@ -12,7 +14,7 @@ module API
requires :id, type: String, desc: 'The ID of a project'
requires :subscribable_id, type: String, desc: 'The ID of a resource'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
subscribable_types.each do |type, finder|
type_singularized = type.singularize
entity_class = Entities.const_get(type_singularized.camelcase)
diff --git a/lib/api/system_hooks.rb b/lib/api/system_hooks.rb
index 07552aa18e8..51fae0e54aa 100644
--- a/lib/api/system_hooks.rb
+++ b/lib/api/system_hooks.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class SystemHooks < Grape::API
include PaginationParams
diff --git a/lib/api/tags.rb b/lib/api/tags.rb
index 5e0afc6a7e4..b18eec7d796 100644
--- a/lib/api/tags.rb
+++ b/lib/api/tags.rb
@@ -1,15 +1,17 @@
+# frozen_string_literal: true
+
module API
class Tags < Grape::API
include PaginationParams
- TAG_ENDPOINT_REQUIREMENTS = API::PROJECT_ENDPOINT_REQUIREMENTS.merge(tag_name: API::NO_SLASH_URL_PART_REGEX)
+ TAG_ENDPOINT_REQUIREMENTS = API::NAMESPACE_OR_PROJECT_REQUIREMENTS.merge(tag_name: API::NO_SLASH_URL_PART_REGEX)
before { authorize! :download_code, user_project }
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get a project repository tags' do
success Entities::Tag
end
diff --git a/lib/api/templates.rb b/lib/api/templates.rb
index 7bf0e0f5934..8dab19d50c2 100644
--- a/lib/api/templates.rb
+++ b/lib/api/templates.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Templates < Grape::API
include PaginationParams
@@ -33,7 +35,7 @@ module API
popular = declared(params)[:popular]
popular = to_boolean(popular) if popular.present?
- templates = TemplateFinder.build(:licenses, popular: popular).execute
+ templates = TemplateFinder.build(:licenses, nil, popular: popular).execute
present paginate(::Kaminari.paginate_array(templates)), with: ::API::Entities::License
end
@@ -46,8 +48,7 @@ module API
requires :name, type: String, desc: 'The name of the template'
end
get "templates/licenses/:name", requirements: { name: /[\w\.-]+/ } do
- templates = TemplateFinder.build(:licenses).execute
- template = templates.find { |template| template.key == params[:name] }
+ template = TemplateFinder.build(:licenses, nil, name: params[:name]).execute
not_found!('License') unless template.present?
@@ -70,7 +71,7 @@ module API
use :pagination
end
get "templates/#{template_type}" do
- templates = ::Kaminari.paginate_array(TemplateFinder.new(template_type).execute)
+ templates = ::Kaminari.paginate_array(TemplateFinder.build(template_type, nil).execute)
present paginate(templates), with: Entities::TemplatesList
end
@@ -82,7 +83,7 @@ module API
requires :name, type: String, desc: 'The name of the template'
end
get "templates/#{template_type}/:name" do
- finder = TemplateFinder.build(template_type, name: declared(params)[:name])
+ finder = TemplateFinder.build(template_type, nil, name: declared(params)[:name])
new_template = finder.execute
render_response(template_type, new_template)
diff --git a/lib/api/time_tracking_endpoints.rb b/lib/api/time_tracking_endpoints.rb
index 2bb451dea89..93fe06bec27 100644
--- a/lib/api/time_tracking_endpoints.rb
+++ b/lib/api/time_tracking_endpoints.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
module TimeTrackingEndpoints
extend ActiveSupport::Concern
diff --git a/lib/api/todos.rb b/lib/api/todos.rb
index c6dbcf84e3a..d2c8cf7c1aa 100644
--- a/lib/api/todos.rb
+++ b/lib/api/todos.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Todos < Grape::API
include PaginationParams
@@ -12,7 +14,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
ISSUABLE_TYPES.each do |type, finder|
type_id_str = "#{type.singularize}_iid".to_sym
diff --git a/lib/api/triggers.rb b/lib/api/triggers.rb
index 2339505b05b..3ce1529f259 100644
--- a/lib/api/triggers.rb
+++ b/lib/api/triggers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Triggers < Grape::API
include PaginationParams
@@ -5,7 +7,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Trigger a GitLab project pipeline' do
success Entities::Pipeline
end
diff --git a/lib/api/users.rb b/lib/api/users.rb
index ac09ca7f7b7..b41fce76df0 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Users < Grape::API
include PaginationParams
@@ -42,12 +44,12 @@ module API
optional :provider, type: String, desc: 'The external provider'
optional :bio, type: String, desc: 'The biography of the user'
optional :location, type: String, desc: 'The location of the user'
+ optional :public_email, type: String, desc: 'The public email of the user'
optional :admin, type: Boolean, desc: 'Flag indicating the user is an administrator'
optional :can_create_group, type: Boolean, desc: 'Flag indicating the user can create groups'
optional :external, type: Boolean, desc: 'Flag indicating the user is an external user'
optional :avatar, type: File, desc: 'Avatar image for user'
optional :private_profile, type: Boolean, desc: 'Flag indicating the user has a private profile'
- optional :min_access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'Limit by minimum access level of authenticated user'
all_or_none_of :extern_uid, :provider
end
@@ -153,7 +155,6 @@ module API
requires :username, type: String, desc: 'The username of the user'
use :optional_attributes
end
- # rubocop: disable CodeReuse/ActiveRecord
post do
authenticated_as_admin!
@@ -164,17 +165,16 @@ module API
present user, with: Entities::UserPublic, current_user: current_user
else
conflict!('Email has already been taken') if User
- .where(email: user.email)
- .count > 0
+ .by_any_email(user.email.downcase)
+ .any?
conflict!('Username has already been taken') if User
- .where(username: user.username)
- .count > 0
+ .by_username(user.username)
+ .any?
render_validation_error!(user)
end
end
- # rubocop: enable CodeReuse/ActiveRecord
desc 'Update a user. Available only for admins.' do
success Entities::UserPublic
@@ -196,11 +196,11 @@ module API
not_found!('User') unless user
conflict!('Email has already been taken') if params[:email] &&
- User.where(email: params[:email])
+ User.by_any_email(params[:email].downcase)
.where.not(id: user.id).count > 0
conflict!('Username has already been taken') if params[:username] &&
- User.where(username: params[:username])
+ User.by_username(params[:username])
.where.not(id: user.id).count > 0
user_params = declared_params(include_missing: false)
@@ -254,7 +254,7 @@ module API
end
# rubocop: enable CodeReuse/ActiveRecord
- desc 'Get the SSH keys of a specified user. Available only for admins.' do
+ desc 'Get the SSH keys of a specified user.' do
success Entities::SSHKey
end
params do
@@ -263,10 +263,8 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
get ':id/keys' do
- authenticated_as_admin!
-
user = User.find_by(id: params[:id])
- not_found!('User') unless user
+ not_found!('User') unless user && can?(current_user, :read_user, user)
present paginate(user.keys), with: Entities::SSHKey
end
@@ -514,11 +512,9 @@ module API
PersonalAccessTokensFinder.new({ user: user, impersonation: true }.merge(options))
end
- # rubocop: disable CodeReuse/ActiveRecord
def find_impersonation_token
- finder.find_by(id: declared_params[:impersonation_token_id]) || not_found!('Impersonation Token')
+ finder.find_by_id(declared_params[:impersonation_token_id]) || not_found!('Impersonation Token')
end
- # rubocop: enable CodeReuse/ActiveRecord
end
before { authenticated_as_admin! }
@@ -535,7 +531,7 @@ module API
desc 'Create a impersonation token. Available only for admins.' do
detail 'This feature was introduced in GitLab 9.0'
- success Entities::ImpersonationToken
+ success Entities::ImpersonationTokenWithToken
end
params do
requires :name, type: String, desc: 'The name of the impersonation token'
@@ -546,7 +542,7 @@ module API
impersonation_token = finder.build(declared_params(include_missing: false))
if impersonation_token.save
- present impersonation_token, with: Entities::ImpersonationToken
+ present impersonation_token, with: Entities::ImpersonationTokenWithToken
else
render_validation_error!(impersonation_token)
end
diff --git a/lib/api/validations/types/safe_file.rb b/lib/api/validations/types/safe_file.rb
new file mode 100644
index 00000000000..53b5790bfa2
--- /dev/null
+++ b/lib/api/validations/types/safe_file.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+# This module overrides the Grape type validator defined in
+# https://github.com/ruby-grape/grape/blob/master/lib/grape/validations/types/file.rb
+module API
+ module Validations
+ module Types
+ class SafeFile < ::Grape::Validations::Types::File
+ def value_coerced?(value)
+ super && value[:tempfile].is_a?(Tempfile)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/variables.rb b/lib/api/variables.rb
index 50e6fa6bcdf..f7cae2251c2 100644
--- a/lib/api/variables.rb
+++ b/lib/api/variables.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Variables < Grape::API
include PaginationParams
@@ -9,7 +11,7 @@ module API
requires :id, type: String, desc: 'The ID of a project'
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get project variables' do
success Entities::Variable
end
diff --git a/lib/api/version.rb b/lib/api/version.rb
index 3b10bfa6a7d..74cd857f447 100644
--- a/lib/api/version.rb
+++ b/lib/api/version.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module API
class Version < Grape::API
before { authenticate! }
diff --git a/lib/api/wikis.rb b/lib/api/wikis.rb
index e86ebc573f2..302b2797a34 100644
--- a/lib/api/wikis.rb
+++ b/lib/api/wikis.rb
@@ -1,10 +1,12 @@
+# frozen_string_literal: true
+
module API
class Wikis < Grape::API
helpers do
def commit_params(attrs)
{
file_name: attrs[:file][:filename],
- file_content: File.read(attrs[:file][:tempfile]),
+ file_content: attrs[:file][:tempfile].read,
branch_name: attrs[:branch]
}
end
@@ -20,7 +22,7 @@ module API
end
end
- resource :projects, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get a list of wiki pages' do
success Entities::WikiPageBasic
end
@@ -98,10 +100,10 @@ module API
success Entities::WikiAttachment
end
params do
- requires :file, type: File, desc: 'The attachment file to be uploaded'
+ requires :file, type: ::API::Validations::Types::SafeFile, desc: 'The attachment file to be uploaded'
optional :branch, type: String, desc: 'The name of the branch'
end
- post ":id/wikis/attachments", requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
+ post ":id/wikis/attachments", requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
authorize! :create_wiki, user_project
result = ::Wikis::CreateAttachmentService.new(user_project,
diff --git a/lib/backup.rb b/lib/backup.rb
index e2c62af23ae..2712b33b4b4 100644
--- a/lib/backup.rb
+++ b/lib/backup.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Backup
Error = Class.new(StandardError)
end
diff --git a/lib/backup/artifacts.rb b/lib/backup/artifacts.rb
index 45a935ab352..33658ae225f 100644
--- a/lib/backup/artifacts.rb
+++ b/lib/backup/artifacts.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'backup/files'
module Backup
diff --git a/lib/backup/builds.rb b/lib/backup/builds.rb
index adf85ca4719..5e795a449de 100644
--- a/lib/backup/builds.rb
+++ b/lib/backup/builds.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'backup/files'
module Backup
diff --git a/lib/backup/database.rb b/lib/backup/database.rb
index 086ca5986bd..e6bf3d1856f 100644
--- a/lib/backup/database.rb
+++ b/lib/backup/database.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'yaml'
module Backup
diff --git a/lib/backup/files.rb b/lib/backup/files.rb
index e287aa1e392..0032ae8f84b 100644
--- a/lib/backup/files.rb
+++ b/lib/backup/files.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'open3'
require_relative 'helper'
diff --git a/lib/backup/helper.rb b/lib/backup/helper.rb
index 54b9ce10b4d..22f00aef569 100644
--- a/lib/backup/helper.rb
+++ b/lib/backup/helper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Backup
module Helper
def access_denied_error(path)
diff --git a/lib/backup/lfs.rb b/lib/backup/lfs.rb
index 185ff8ae6bd..0dfe56e214f 100644
--- a/lib/backup/lfs.rb
+++ b/lib/backup/lfs.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'backup/files'
module Backup
diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb
index a3641505196..a0434a66ef1 100644
--- a/lib/backup/manager.rb
+++ b/lib/backup/manager.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Backup
class Manager
ARCHIVES_TO_BACKUP = %w[uploads builds artifacts pages lfs registry].freeze
@@ -162,7 +164,7 @@ module Backup
def tar_version
tar_version, _ = Gitlab::Popen.popen(%w(tar --version))
- tar_version.force_encoding('locale').split("\n").first
+ tar_version.dup.force_encoding('locale').split("\n").first
end
def skipped?(item)
@@ -241,6 +243,7 @@ module Backup
backup_created_at: Time.now,
gitlab_version: Gitlab::VERSION,
tar_version: tar_version,
+ installation_type: Gitlab::INSTALLATION_TYPE,
skipped: ENV["SKIP"]
}
end
diff --git a/lib/backup/pages.rb b/lib/backup/pages.rb
index 542e35a7c7c..a4be728df08 100644
--- a/lib/backup/pages.rb
+++ b/lib/backup/pages.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'backup/files'
module Backup
diff --git a/lib/backup/registry.rb b/lib/backup/registry.rb
index 35821805797..d16ed2facf1 100644
--- a/lib/backup/registry.rb
+++ b/lib/backup/registry.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'backup/files'
module Backup
diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb
index 906ed498026..c8a5377bfa0 100644
--- a/lib/backup/repository.rb
+++ b/lib/backup/repository.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'yaml'
module Backup
diff --git a/lib/backup/uploads.rb b/lib/backup/uploads.rb
index 49b117a7ee3..9577df2634a 100644
--- a/lib/backup/uploads.rb
+++ b/lib/backup/uploads.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'backup/files'
module Backup
diff --git a/lib/banzai.rb b/lib/banzai.rb
index 5df98f66f3b..1eb41ff7133 100644
--- a/lib/banzai.rb
+++ b/lib/banzai.rb
@@ -1,4 +1,13 @@
+# frozen_string_literal: true
+
module Banzai
+ # if you need to render markdown, then you probably need to post_process as well,
+ # such as removing references that the current user doesn't have
+ # permission to make
+ def self.render_and_post_process(text, context = {})
+ post_process(render(text, context), context)
+ end
+
def self.render(text, context = {})
Renderer.render(text, context)
end
diff --git a/lib/banzai/color_parser.rb b/lib/banzai/color_parser.rb
index 355c364b07b..6d01d51955c 100644
--- a/lib/banzai/color_parser.rb
+++ b/lib/banzai/color_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module ColorParser
ALPHA = /0(?:\.\d+)?|\.\d+|1(?:\.0+)?/ # 0.0..1.0
diff --git a/lib/banzai/commit_renderer.rb b/lib/banzai/commit_renderer.rb
index c351a155ae5..f346151a3c1 100644
--- a/lib/banzai/commit_renderer.rb
+++ b/lib/banzai/commit_renderer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module CommitRenderer
ATTRIBUTES = [:description, :title].freeze
diff --git a/lib/banzai/cross_project_reference.rb b/lib/banzai/cross_project_reference.rb
index 3f1e95d4cc0..b7344808989 100644
--- a/lib/banzai/cross_project_reference.rb
+++ b/lib/banzai/cross_project_reference.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
# Common methods for ReferenceFilters that support an optional cross-project
# reference.
@@ -13,6 +15,7 @@ module Banzai
# Returns a Project, or nil if the reference can't be found
def parent_from_ref(ref)
return context[:project] || context[:group] unless ref
+ return context[:project] if context[:project]&.full_path == ref
Project.find_by_full_path(ref)
end
diff --git a/lib/banzai/filter.rb b/lib/banzai/filter.rb
index 3eb544dfef9..7d9766c906c 100644
--- a/lib/banzai/filter.rb
+++ b/lib/banzai/filter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
def self.[](name)
diff --git a/lib/banzai/filter/absolute_link_filter.rb b/lib/banzai/filter/absolute_link_filter.rb
index 04ec568eee3..a9bdb004c4b 100644
--- a/lib/banzai/filter/absolute_link_filter.rb
+++ b/lib/banzai/filter/absolute_link_filter.rb
@@ -29,6 +29,7 @@ module Banzai
end
def absolute_link_attr(uri)
+ # Here we really want to expand relative path to absolute path
URI.join(Gitlab.config.gitlab.url, uri).to_s
end
end
diff --git a/lib/banzai/filter/abstract_reference_filter.rb b/lib/banzai/filter/abstract_reference_filter.rb
index ad0806df8e6..4764f8e1e19 100644
--- a/lib/banzai/filter/abstract_reference_filter.rb
+++ b/lib/banzai/filter/abstract_reference_filter.rb
@@ -296,7 +296,7 @@ module Banzai
# Returns projects for the given paths.
def find_for_paths(paths)
- if RequestStore.active?
+ if Gitlab::SafeRequestStore.active?
cache = refs_cache
to_query = paths - cache.keys
@@ -340,7 +340,7 @@ module Banzai
end
def refs_cache
- RequestStore["banzai_#{parent_type}_refs".to_sym] ||= {}
+ Gitlab::SafeRequestStore["banzai_#{parent_type}_refs".to_sym] ||= {}
end
def parent_type
diff --git a/lib/banzai/filter/epic_reference_filter.rb b/lib/banzai/filter/epic_reference_filter.rb
index e06e2fb3870..26bcf5c04b4 100644
--- a/lib/banzai/filter/epic_reference_filter.rb
+++ b/lib/banzai/filter/epic_reference_filter.rb
@@ -9,6 +9,12 @@ module Banzai
def self.object_class
Epic
end
+
+ private
+
+ def group
+ context[:group] || context[:project]&.group
+ end
end
end
end
diff --git a/lib/banzai/filter/external_issue_reference_filter.rb b/lib/banzai/filter/external_issue_reference_filter.rb
index b4a7a44e109..8159dcfed72 100644
--- a/lib/banzai/filter/external_issue_reference_filter.rb
+++ b/lib/banzai/filter/external_issue_reference_filter.rb
@@ -97,9 +97,7 @@ module Banzai
private
def external_issues_cached(attribute)
- return project.public_send(attribute) unless RequestStore.active? # rubocop:disable GitlabSecurity/PublicSend
-
- cached_attributes = RequestStore[:banzai_external_issues_tracker_attributes] ||= Hash.new { |h, k| h[k] = {} }
+ cached_attributes = Gitlab::SafeRequestStore[:banzai_external_issues_tracker_attributes] ||= Hash.new { |h, k| h[k] = {} }
cached_attributes[project.id][attribute] = project.public_send(attribute) if cached_attributes[project.id][attribute].nil? # rubocop:disable GitlabSecurity/PublicSend
cached_attributes[project.id][attribute]
end
diff --git a/lib/banzai/filter/issuable_state_filter.rb b/lib/banzai/filter/issuable_state_filter.rb
index d7fe012883d..8e2358694d4 100644
--- a/lib/banzai/filter/issuable_state_filter.rb
+++ b/lib/banzai/filter/issuable_state_filter.rb
@@ -18,7 +18,7 @@ module Banzai
issuables = extractor.extract([doc])
issuables.each do |node, issuable|
- next if !can_read_cross_project? && issuable.project != project
+ next if !can_read_cross_project? && cross_reference?(issuable)
if VISIBLE_STATES.include?(issuable.state) && issuable_reference?(node.inner_html, issuable)
node.content += " (#{issuable.state})"
@@ -31,7 +31,14 @@ module Banzai
private
def issuable_reference?(text, issuable)
- text == issuable.reference_link_text(project || group)
+ CGI.unescapeHTML(text) == issuable.reference_link_text(project || group)
+ end
+
+ def cross_reference?(issuable)
+ return true if issuable.project != project
+ return true if issuable.respond_to?(:group) && issuable.group != group
+
+ false
end
def can_read_cross_project?
diff --git a/lib/banzai/filter/label_reference_filter.rb b/lib/banzai/filter/label_reference_filter.rb
index b92e9e55bb9..04ec38209c7 100644
--- a/lib/banzai/filter/label_reference_filter.rb
+++ b/lib/banzai/filter/label_reference_filter.rb
@@ -48,7 +48,7 @@ module Banzai
include_ancestor_groups: true,
only_group_labels: true }
else
- { project_id: parent.id,
+ { project: parent,
include_ancestor_groups: true }
end
diff --git a/lib/banzai/filter/markdown_engines/common_mark.rb b/lib/banzai/filter/markdown_engines/common_mark.rb
index dbb25280849..e52c0d15b31 100644
--- a/lib/banzai/filter/markdown_engines/common_mark.rb
+++ b/lib/banzai/filter/markdown_engines/common_mark.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# `CommonMark` markdown engine for GitLab's Banzai markdown filter.
# This module is used in Banzai::Filter::MarkdownFilter.
# Used gem is `commonmarker` which is a ruby wrapper for libcmark (CommonMark parser)
diff --git a/lib/banzai/filter/markdown_engines/redcarpet.rb b/lib/banzai/filter/markdown_engines/redcarpet.rb
index ac99941fefa..ec150d041ff 100644
--- a/lib/banzai/filter/markdown_engines/redcarpet.rb
+++ b/lib/banzai/filter/markdown_engines/redcarpet.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# `Redcarpet` markdown engine for GitLab's Banzai markdown filter.
# This module is used in Banzai::Filter::MarkdownFilter.
# Used gem is `redcarpet` which is a ruby library for markdown processing.
diff --git a/lib/banzai/filter/relative_link_filter.rb b/lib/banzai/filter/relative_link_filter.rb
index 8e838d04bad..7acbc933adc 100644
--- a/lib/banzai/filter/relative_link_filter.rb
+++ b/lib/banzai/filter/relative_link_filter.rb
@@ -60,7 +60,11 @@ module Banzai
path_parts.unshift(relative_url_root, project.full_path)
end
- path = Addressable::URI.escape(File.join(*path_parts))
+ begin
+ path = Addressable::URI.escape(File.join(*path_parts))
+ rescue Addressable::URI::InvalidURIError
+ return
+ end
html_attr.value =
if context[:only_path]
diff --git a/lib/banzai/filter/spaced_link_filter.rb b/lib/banzai/filter/spaced_link_filter.rb
index a27f1d46863..c6a3a763c23 100644
--- a/lib/banzai/filter/spaced_link_filter.rb
+++ b/lib/banzai/filter/spaced_link_filter.rb
@@ -17,6 +17,9 @@ module Banzai
# This is a small extension to the CommonMark spec. If they start allowing
# spaces in urls, we could then remove this filter.
#
+ # Note: Filter::SanitizationFilter should always be run sometime after this filter
+ # to prevent XSS attacks
+ #
class SpacedLinkFilter < HTML::Pipeline::Filter
include ActionView::Helpers::TagHelper
diff --git a/lib/banzai/filter/wiki_link_filter/rewriter.rb b/lib/banzai/filter/wiki_link_filter/rewriter.rb
index 4bf80aff418..f4cc8beeb52 100644
--- a/lib/banzai/filter/wiki_link_filter/rewriter.rb
+++ b/lib/banzai/filter/wiki_link_filter/rewriter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Filter
class WikiLinkFilter < HTML::Pipeline::Filter
diff --git a/lib/banzai/filter_array.rb b/lib/banzai/filter_array.rb
index 77835a14027..818af4643a7 100644
--- a/lib/banzai/filter_array.rb
+++ b/lib/banzai/filter_array.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
class FilterArray < Array
# Insert a value immediately after another value
diff --git a/lib/banzai/issuable_extractor.rb b/lib/banzai/issuable_extractor.rb
index ae7dc71e7eb..341dbb74fe0 100644
--- a/lib/banzai/issuable_extractor.rb
+++ b/lib/banzai/issuable_extractor.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
# Extract references to issuables from multiple documents
@@ -7,13 +9,11 @@ module Banzai
# so we can avoid N+1 queries problem
class IssuableExtractor
- QUERY = %q(
- descendant-or-self::a[contains(concat(" ", @class, " "), " gfm ")]
- [@data-reference-type="issue" or @data-reference-type="merge_request"]
- ).freeze
-
attr_reader :context
+ ISSUE_REFERENCE_TYPE = '@data-reference-type="issue"'.freeze
+ MERGE_REQUEST_REFERENCE_TYPE = '@data-reference-type="merge_request"'.freeze
+
# context - An instance of Banzai::RenderContext.
def initialize(context)
@context = context
@@ -22,21 +22,38 @@ module Banzai
# Returns Hash in the form { node => issuable_instance }
def extract(documents)
nodes = documents.flat_map do |document|
- document.xpath(QUERY)
+ document.xpath(query)
end
- issue_parser = Banzai::ReferenceParser::IssueParser.new(context)
+ # The project or group for the issuable might be pending for deletion!
+ # Filter them out because we don't care about them.
+ issuables_for_nodes(nodes).select { |node, issuable| issuable.project || issuable.group }
+ end
+
+ private
- merge_request_parser =
+ def issuables_for_nodes(nodes)
+ parsers.each_with_object({}) do |parser, result|
+ result.merge!(parser.records_for_nodes(nodes))
+ end
+ end
+
+ def parsers
+ [
+ Banzai::ReferenceParser::IssueParser.new(context),
Banzai::ReferenceParser::MergeRequestParser.new(context)
+ ]
+ end
- issuables_for_nodes = issue_parser.records_for_nodes(nodes).merge(
- merge_request_parser.records_for_nodes(nodes)
+ def query
+ %Q(
+ descendant-or-self::a[contains(concat(" ", @class, " "), " gfm ")]
+ [#{reference_types.join(' or ')}]
)
+ end
- # The project for the issue/MR might be pending for deletion!
- # Filter them out because we don't care about them.
- issuables_for_nodes.select { |node, issuable| issuable.project }
+ def reference_types
+ [ISSUE_REFERENCE_TYPE, MERGE_REQUEST_REFERENCE_TYPE]
end
end
end
diff --git a/lib/banzai/object_renderer.rb b/lib/banzai/object_renderer.rb
index a176f1e261b..75661ffa233 100644
--- a/lib/banzai/object_renderer.rb
+++ b/lib/banzai/object_renderer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
# Class for rendering multiple objects (e.g. Note instances) in a single pass,
# using +render_field+ to benefit from caching in the database. Rendering and
@@ -38,6 +40,7 @@ module Banzai
redacted_data = redacted[index]
object.__send__("redacted_#{attribute}_html=", redacted_data[:document].to_html(save_options).html_safe) # rubocop:disable GitlabSecurity/PublicSend
object.user_visible_reference_count = redacted_data[:visible_reference_count] if object.respond_to?(:user_visible_reference_count)
+ object.total_reference_count = redacted_data[:total_reference_count] if object.respond_to?(:total_reference_count)
end
end
diff --git a/lib/banzai/pipeline.rb b/lib/banzai/pipeline.rb
index 142a9962eb1..e8a81bebaa9 100644
--- a/lib/banzai/pipeline.rb
+++ b/lib/banzai/pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
def self.[](name)
diff --git a/lib/banzai/pipeline/ascii_doc_pipeline.rb b/lib/banzai/pipeline/ascii_doc_pipeline.rb
index 1048b927cd3..cc4af280872 100644
--- a/lib/banzai/pipeline/ascii_doc_pipeline.rb
+++ b/lib/banzai/pipeline/ascii_doc_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
class AsciiDocPipeline < BasePipeline
diff --git a/lib/banzai/pipeline/atom_pipeline.rb b/lib/banzai/pipeline/atom_pipeline.rb
index 9694e4bc23f..13a342351b6 100644
--- a/lib/banzai/pipeline/atom_pipeline.rb
+++ b/lib/banzai/pipeline/atom_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
class AtomPipeline < FullPipeline
diff --git a/lib/banzai/pipeline/base_pipeline.rb b/lib/banzai/pipeline/base_pipeline.rb
index 3ae3bed570d..87d1cf9912f 100644
--- a/lib/banzai/pipeline/base_pipeline.rb
+++ b/lib/banzai/pipeline/base_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
class BasePipeline
diff --git a/lib/banzai/pipeline/broadcast_message_pipeline.rb b/lib/banzai/pipeline/broadcast_message_pipeline.rb
index 5dd572de3a1..a3d63e0aaf5 100644
--- a/lib/banzai/pipeline/broadcast_message_pipeline.rb
+++ b/lib/banzai/pipeline/broadcast_message_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
class BroadcastMessagePipeline < DescriptionPipeline
diff --git a/lib/banzai/pipeline/combined_pipeline.rb b/lib/banzai/pipeline/combined_pipeline.rb
index 60190f8d9dd..56b424dc8e0 100644
--- a/lib/banzai/pipeline/combined_pipeline.rb
+++ b/lib/banzai/pipeline/combined_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
module CombinedPipeline
diff --git a/lib/banzai/pipeline/commit_description_pipeline.rb b/lib/banzai/pipeline/commit_description_pipeline.rb
index 607c2731ed3..e8ec7453f0f 100644
--- a/lib/banzai/pipeline/commit_description_pipeline.rb
+++ b/lib/banzai/pipeline/commit_description_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
class CommitDescriptionPipeline < SingleLinePipeline
diff --git a/lib/banzai/pipeline/description_pipeline.rb b/lib/banzai/pipeline/description_pipeline.rb
index 042fb2e6e14..d5ff9b025cc 100644
--- a/lib/banzai/pipeline/description_pipeline.rb
+++ b/lib/banzai/pipeline/description_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
class DescriptionPipeline < FullPipeline
diff --git a/lib/banzai/pipeline/email_pipeline.rb b/lib/banzai/pipeline/email_pipeline.rb
index 8f5f144d582..2c08581ce0d 100644
--- a/lib/banzai/pipeline/email_pipeline.rb
+++ b/lib/banzai/pipeline/email_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
class EmailPipeline < FullPipeline
diff --git a/lib/banzai/pipeline/full_pipeline.rb b/lib/banzai/pipeline/full_pipeline.rb
index 3c974f73176..a5b1cbdd030 100644
--- a/lib/banzai/pipeline/full_pipeline.rb
+++ b/lib/banzai/pipeline/full_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
class FullPipeline < CombinedPipeline.new(PlainMarkdownPipeline, GfmPipeline)
diff --git a/lib/banzai/pipeline/gfm_pipeline.rb b/lib/banzai/pipeline/gfm_pipeline.rb
index bd34614f149..96bea7ca935 100644
--- a/lib/banzai/pipeline/gfm_pipeline.rb
+++ b/lib/banzai/pipeline/gfm_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
class GfmPipeline < BasePipeline
@@ -10,13 +12,16 @@ module Banzai
def self.filters
@filters ||= FilterArray[
Filter::PlantumlFilter,
+
+ # Must always be before the SanitizationFilter to prevent XSS attacks
+ Filter::SpacedLinkFilter,
+
Filter::SanitizationFilter,
Filter::SyntaxHighlightFilter,
Filter::MathFilter,
Filter::ColorFilter,
Filter::MermaidFilter,
- Filter::SpacedLinkFilter,
Filter::VideoLinkFilter,
Filter::ImageLazyLoadFilter,
Filter::ImageLinkFilter,
diff --git a/lib/banzai/pipeline/markup_pipeline.rb b/lib/banzai/pipeline/markup_pipeline.rb
index c56d908009f..db79a22549c 100644
--- a/lib/banzai/pipeline/markup_pipeline.rb
+++ b/lib/banzai/pipeline/markup_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
class MarkupPipeline < BasePipeline
diff --git a/lib/banzai/pipeline/note_pipeline.rb b/lib/banzai/pipeline/note_pipeline.rb
index 7890f20f716..4480d7ede05 100644
--- a/lib/banzai/pipeline/note_pipeline.rb
+++ b/lib/banzai/pipeline/note_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
class NotePipeline < FullPipeline
diff --git a/lib/banzai/pipeline/plain_markdown_pipeline.rb b/lib/banzai/pipeline/plain_markdown_pipeline.rb
index 3f45db21869..b64f13cde47 100644
--- a/lib/banzai/pipeline/plain_markdown_pipeline.rb
+++ b/lib/banzai/pipeline/plain_markdown_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
class PlainMarkdownPipeline < BasePipeline
diff --git a/lib/banzai/pipeline/post_process_pipeline.rb b/lib/banzai/pipeline/post_process_pipeline.rb
index 0b2e584ef16..63a998a2c1f 100644
--- a/lib/banzai/pipeline/post_process_pipeline.rb
+++ b/lib/banzai/pipeline/post_process_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
class PostProcessPipeline < BasePipeline
diff --git a/lib/banzai/pipeline/pre_process_pipeline.rb b/lib/banzai/pipeline/pre_process_pipeline.rb
index 6cf219661d3..c937f783180 100644
--- a/lib/banzai/pipeline/pre_process_pipeline.rb
+++ b/lib/banzai/pipeline/pre_process_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
class PreProcessPipeline < BasePipeline
diff --git a/lib/banzai/pipeline/relative_link_pipeline.rb b/lib/banzai/pipeline/relative_link_pipeline.rb
index 270990e7ab4..88651892acc 100644
--- a/lib/banzai/pipeline/relative_link_pipeline.rb
+++ b/lib/banzai/pipeline/relative_link_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
class RelativeLinkPipeline < BasePipeline
diff --git a/lib/banzai/pipeline/single_line_pipeline.rb b/lib/banzai/pipeline/single_line_pipeline.rb
index cd5a6c8875c..61ff7b0bcce 100644
--- a/lib/banzai/pipeline/single_line_pipeline.rb
+++ b/lib/banzai/pipeline/single_line_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
class SingleLinePipeline < GfmPipeline
diff --git a/lib/banzai/pipeline/wiki_pipeline.rb b/lib/banzai/pipeline/wiki_pipeline.rb
index c37b8e71cb0..97a03895ff3 100644
--- a/lib/banzai/pipeline/wiki_pipeline.rb
+++ b/lib/banzai/pipeline/wiki_pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Pipeline
class WikiPipeline < FullPipeline
diff --git a/lib/banzai/querying.rb b/lib/banzai/querying.rb
index a19a05e8c0d..55aa5fa66c3 100644
--- a/lib/banzai/querying.rb
+++ b/lib/banzai/querying.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Querying
module_function
diff --git a/lib/banzai/redactor.rb b/lib/banzai/redactor.rb
index 28928d6f376..7db5f5e1f7d 100644
--- a/lib/banzai/redactor.rb
+++ b/lib/banzai/redactor.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
# Class for removing Markdown references a certain user is not allowed to
# view.
@@ -37,7 +39,13 @@ module Banzai
all_document_nodes.each do |entry|
nodes_for_document = entry[:nodes]
- doc_data = { document: entry[:document], visible_reference_count: nodes_for_document.count }
+
+ doc_data = {
+ document: entry[:document],
+ total_reference_count: nodes_for_document.count,
+ visible_reference_count: nodes_for_document.count
+ }
+
metadata << doc_data
nodes_for_document.each do |node|
diff --git a/lib/banzai/reference_extractor.rb b/lib/banzai/reference_extractor.rb
index 78588299c18..3fc3ae02088 100644
--- a/lib/banzai/reference_extractor.rb
+++ b/lib/banzai/reference_extractor.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
# Extract possible GFM references from an arbitrary String for further processing.
class ReferenceExtractor
diff --git a/lib/banzai/reference_parser.rb b/lib/banzai/reference_parser.rb
index 557bec4316e..efe15096f08 100644
--- a/lib/banzai/reference_parser.rb
+++ b/lib/banzai/reference_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module ReferenceParser
# Returns the reference parser class for the given type
diff --git a/lib/banzai/reference_parser/base_parser.rb b/lib/banzai/reference_parser/base_parser.rb
index 68752f5bb5a..8419769085a 100644
--- a/lib/banzai/reference_parser/base_parser.rb
+++ b/lib/banzai/reference_parser/base_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module ReferenceParser
# Base class for reference parsing classes.
@@ -166,7 +168,7 @@ module Banzai
# objects that have not yet been queried. For objects that have already
# been queried the object is returned from the cache.
def collection_objects_for_ids(collection, ids)
- if RequestStore.active?
+ if Gitlab::SafeRequestStore.active?
ids = ids.map(&:to_i)
cache = collection_cache[collection_cache_key(collection)]
to_query = ids - cache.keys
@@ -215,7 +217,7 @@ module Banzai
#
def projects_for_nodes(nodes)
@projects_for_nodes ||=
- grouped_objects_for_nodes(nodes, Project, 'data-project')
+ grouped_objects_for_nodes(nodes, Project.includes(:project_feature), 'data-project')
end
def can?(user, permission, subject = :global)
@@ -248,7 +250,7 @@ module Banzai
end
def collection_cache
- RequestStore[:banzai_collection_cache] ||= Hash.new do |hash, key|
+ Gitlab::SafeRequestStore[:banzai_collection_cache] ||= Hash.new do |hash, key|
hash[key] = {}
end
end
diff --git a/lib/banzai/reference_parser/commit_parser.rb b/lib/banzai/reference_parser/commit_parser.rb
index 30dc87248b4..0bfb6a92020 100644
--- a/lib/banzai/reference_parser/commit_parser.rb
+++ b/lib/banzai/reference_parser/commit_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module ReferenceParser
class CommitParser < BaseParser
diff --git a/lib/banzai/reference_parser/commit_range_parser.rb b/lib/banzai/reference_parser/commit_range_parser.rb
index 2920e886938..480eefd5c4d 100644
--- a/lib/banzai/reference_parser/commit_range_parser.rb
+++ b/lib/banzai/reference_parser/commit_range_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module ReferenceParser
class CommitRangeParser < BaseParser
diff --git a/lib/banzai/reference_parser/directly_addressed_user_parser.rb b/lib/banzai/reference_parser/directly_addressed_user_parser.rb
index 77df9bbd024..1f18f82b916 100644
--- a/lib/banzai/reference_parser/directly_addressed_user_parser.rb
+++ b/lib/banzai/reference_parser/directly_addressed_user_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module ReferenceParser
class DirectlyAddressedUserParser < UserParser
diff --git a/lib/banzai/reference_parser/epic_parser.rb b/lib/banzai/reference_parser/epic_parser.rb
index 08b8a4c9a0f..7f366f0f8ab 100644
--- a/lib/banzai/reference_parser/epic_parser.rb
+++ b/lib/banzai/reference_parser/epic_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module ReferenceParser
# The actual parser is implemented in the EE mixin
diff --git a/lib/banzai/reference_parser/external_issue_parser.rb b/lib/banzai/reference_parser/external_issue_parser.rb
index 1802cd04854..029b09dcd25 100644
--- a/lib/banzai/reference_parser/external_issue_parser.rb
+++ b/lib/banzai/reference_parser/external_issue_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module ReferenceParser
class ExternalIssueParser < BaseParser
diff --git a/lib/banzai/reference_parser/issuable_parser.rb b/lib/banzai/reference_parser/issuable_parser.rb
index fad127d7e5b..f8c26288017 100644
--- a/lib/banzai/reference_parser/issuable_parser.rb
+++ b/lib/banzai/reference_parser/issuable_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module ReferenceParser
class IssuableParser < BaseParser
diff --git a/lib/banzai/reference_parser/issue_parser.rb b/lib/banzai/reference_parser/issue_parser.rb
index 7b5915899cf..97c7173ac0f 100644
--- a/lib/banzai/reference_parser/issue_parser.rb
+++ b/lib/banzai/reference_parser/issue_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module ReferenceParser
class IssueParser < IssuableParser
diff --git a/lib/banzai/reference_parser/label_parser.rb b/lib/banzai/reference_parser/label_parser.rb
index 30e2a012f09..398cc45fea0 100644
--- a/lib/banzai/reference_parser/label_parser.rb
+++ b/lib/banzai/reference_parser/label_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module ReferenceParser
class LabelParser < BaseParser
diff --git a/lib/banzai/reference_parser/merge_request_parser.rb b/lib/banzai/reference_parser/merge_request_parser.rb
index 9e5d55f72bc..e8147ac591a 100644
--- a/lib/banzai/reference_parser/merge_request_parser.rb
+++ b/lib/banzai/reference_parser/merge_request_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module ReferenceParser
class MergeRequestParser < IssuableParser
diff --git a/lib/banzai/reference_parser/milestone_parser.rb b/lib/banzai/reference_parser/milestone_parser.rb
index 68675abe22a..925d736fb9a 100644
--- a/lib/banzai/reference_parser/milestone_parser.rb
+++ b/lib/banzai/reference_parser/milestone_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module ReferenceParser
class MilestoneParser < BaseParser
diff --git a/lib/banzai/reference_parser/snippet_parser.rb b/lib/banzai/reference_parser/snippet_parser.rb
index 3ade168b566..6f6ac08de04 100644
--- a/lib/banzai/reference_parser/snippet_parser.rb
+++ b/lib/banzai/reference_parser/snippet_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module ReferenceParser
class SnippetParser < BaseParser
diff --git a/lib/banzai/reference_parser/user_parser.rb b/lib/banzai/reference_parser/user_parser.rb
index ceb7f1d165c..067b06b7590 100644
--- a/lib/banzai/reference_parser/user_parser.rb
+++ b/lib/banzai/reference_parser/user_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module ReferenceParser
class UserParser < BaseParser
diff --git a/lib/banzai/renderer.rb b/lib/banzai/renderer.rb
index 0050295eeda..c7239a5eaa6 100644
--- a/lib/banzai/renderer.rb
+++ b/lib/banzai/renderer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Renderer
# Convert a Markdown String into an HTML-safe String of HTML
diff --git a/lib/banzai/renderer/common_mark/html.rb b/lib/banzai/renderer/common_mark/html.rb
index 0b27316da1b..837665451a1 100644
--- a/lib/banzai/renderer/common_mark/html.rb
+++ b/lib/banzai/renderer/common_mark/html.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Renderer
module CommonMark
diff --git a/lib/banzai/renderer/redcarpet/html.rb b/lib/banzai/renderer/redcarpet/html.rb
index 30e815f1224..84931fdc784 100644
--- a/lib/banzai/renderer/redcarpet/html.rb
+++ b/lib/banzai/renderer/redcarpet/html.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Banzai
module Renderer
module Redcarpet
diff --git a/lib/banzai/request_store_reference_cache.rb b/lib/banzai/request_store_reference_cache.rb
index 426131442a2..91fb489b72d 100644
--- a/lib/banzai/request_store_reference_cache.rb
+++ b/lib/banzai/request_store_reference_cache.rb
@@ -1,8 +1,10 @@
+# frozen_string_literal: true
+
module Banzai
module RequestStoreReferenceCache
def cached_call(request_store_key, cache_key, path: [])
- if RequestStore.active?
- cache = RequestStore[request_store_key] ||= Hash.new do |hash, key|
+ if Gitlab::SafeRequestStore.active?
+ cache = Gitlab::SafeRequestStore[request_store_key] ||= Hash.new do |hash, key|
hash[key] = Hash.new { |h, k| h[k] = {} }
end
diff --git a/lib/bitbucket/client.rb b/lib/bitbucket/client.rb
index f8ee7e0f9ae..1343f424c51 100644
--- a/lib/bitbucket/client.rb
+++ b/lib/bitbucket/client.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Bitbucket
class Client
attr_reader :connection
diff --git a/lib/bitbucket/collection.rb b/lib/bitbucket/collection.rb
index a78495dbf5e..9c496daccaa 100644
--- a/lib/bitbucket/collection.rb
+++ b/lib/bitbucket/collection.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Bitbucket
class Collection < Enumerator
def initialize(paginator)
diff --git a/lib/bitbucket/connection.rb b/lib/bitbucket/connection.rb
index ba5a9e2f04c..0041634f9e3 100644
--- a/lib/bitbucket/connection.rb
+++ b/lib/bitbucket/connection.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Bitbucket
class Connection
DEFAULT_API_VERSION = '2.0'.freeze
diff --git a/lib/bitbucket/error/unauthorized.rb b/lib/bitbucket/error/unauthorized.rb
index efe10542f19..3cde11babee 100644
--- a/lib/bitbucket/error/unauthorized.rb
+++ b/lib/bitbucket/error/unauthorized.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Bitbucket
module Error
Unauthorized = Class.new(StandardError)
diff --git a/lib/bitbucket/page.rb b/lib/bitbucket/page.rb
index 2b0a3fe7b1a..7cc1342ad65 100644
--- a/lib/bitbucket/page.rb
+++ b/lib/bitbucket/page.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Bitbucket
class Page
attr_reader :attrs, :items
diff --git a/lib/bitbucket/paginator.rb b/lib/bitbucket/paginator.rb
index 135d0d55674..0d004592e67 100644
--- a/lib/bitbucket/paginator.rb
+++ b/lib/bitbucket/paginator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Bitbucket
class Paginator
PAGE_LENGTH = 50 # The minimum length is 10 and the maximum is 100.
diff --git a/lib/bitbucket/representation/base.rb b/lib/bitbucket/representation/base.rb
index 800d5a075c6..bb8dcd91ad5 100644
--- a/lib/bitbucket/representation/base.rb
+++ b/lib/bitbucket/representation/base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Bitbucket
module Representation
class Base
diff --git a/lib/bitbucket/representation/comment.rb b/lib/bitbucket/representation/comment.rb
index 4937aa9728f..1b8dc27793a 100644
--- a/lib/bitbucket/representation/comment.rb
+++ b/lib/bitbucket/representation/comment.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Bitbucket
module Representation
class Comment < Representation::Base
diff --git a/lib/bitbucket/representation/issue.rb b/lib/bitbucket/representation/issue.rb
index 44bcbc250b3..a88797cdab9 100644
--- a/lib/bitbucket/representation/issue.rb
+++ b/lib/bitbucket/representation/issue.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Bitbucket
module Representation
class Issue < Representation::Base
diff --git a/lib/bitbucket/representation/pull_request.rb b/lib/bitbucket/representation/pull_request.rb
index eebf8093380..6a0e8b354bf 100644
--- a/lib/bitbucket/representation/pull_request.rb
+++ b/lib/bitbucket/representation/pull_request.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Bitbucket
module Representation
class PullRequest < Representation::Base
diff --git a/lib/bitbucket/representation/pull_request_comment.rb b/lib/bitbucket/representation/pull_request_comment.rb
index c52acbc3ddc..34dbf9ad22d 100644
--- a/lib/bitbucket/representation/pull_request_comment.rb
+++ b/lib/bitbucket/representation/pull_request_comment.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Bitbucket
module Representation
class PullRequestComment < Comment
diff --git a/lib/bitbucket/representation/repo.rb b/lib/bitbucket/representation/repo.rb
index 59b0fda8e14..c5bfc91e43d 100644
--- a/lib/bitbucket/representation/repo.rb
+++ b/lib/bitbucket/representation/repo.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Bitbucket
module Representation
class Repo < Representation::Base
diff --git a/lib/bitbucket/representation/user.rb b/lib/bitbucket/representation/user.rb
index ba6b7667b49..2b45d751e70 100644
--- a/lib/bitbucket/representation/user.rb
+++ b/lib/bitbucket/representation/user.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Bitbucket
module Representation
class User < Representation::Base
diff --git a/lib/bitbucket_server/client.rb b/lib/bitbucket_server/client.rb
index 15e59f93141..83e8808db07 100644
--- a/lib/bitbucket_server/client.rb
+++ b/lib/bitbucket_server/client.rb
@@ -35,9 +35,9 @@ module BitbucketServer
BitbucketServer::Representation::Repo.new(parsed_response)
end
- def repos
+ def repos(page_offset: 0, limit: nil)
path = "/repos"
- get_collection(path, :repo)
+ get_collection(path, :repo, page_offset: page_offset, limit: limit)
end
def create_branch(project_key, repo, branch_name, sha)
@@ -61,8 +61,8 @@ module BitbucketServer
private
- def get_collection(path, type)
- paginator = BitbucketServer::Paginator.new(connection, Addressable::URI.escape(path), type)
+ def get_collection(path, type, page_offset: 0, limit: nil)
+ paginator = BitbucketServer::Paginator.new(connection, Addressable::URI.escape(path), type, page_offset: page_offset, limit: limit)
BitbucketServer::Collection.new(paginator)
rescue *SERVER_ERRORS => e
raise ServerError, e
diff --git a/lib/bitbucket_server/collection.rb b/lib/bitbucket_server/collection.rb
index b50c5dde352..7e4b2277bbe 100644
--- a/lib/bitbucket_server/collection.rb
+++ b/lib/bitbucket_server/collection.rb
@@ -2,7 +2,13 @@
module BitbucketServer
class Collection < Enumerator
+ attr_reader :paginator
+
+ delegate :page_offset, :has_next_page?, to: :paginator
+
def initialize(paginator)
+ @paginator = paginator
+
super() do |yielder|
loop do
paginator.items.each { |item| yielder << item }
@@ -12,6 +18,24 @@ module BitbucketServer
lazy
end
+ def current_page
+ return 1 if page_offset <= 1
+
+ [1, page_offset].max
+ end
+
+ def prev_page
+ return nil unless current_page > 1
+
+ current_page - 1
+ end
+
+ def next_page
+ return nil unless has_next_page?
+
+ current_page + 1
+ end
+
def method_missing(method, *args)
return super unless self.respond_to?(method)
diff --git a/lib/bitbucket_server/connection.rb b/lib/bitbucket_server/connection.rb
index 45a437844bd..7efcdcf8619 100644
--- a/lib/bitbucket_server/connection.rb
+++ b/lib/bitbucket_server/connection.rb
@@ -88,35 +88,19 @@ module BitbucketServer
def build_url(path)
return path if path.starts_with?(root_url)
- url_join_paths(root_url, path)
+ Gitlab::Utils.append_path(root_url, path)
end
def root_url
- url_join_paths(base_uri, "/rest/api/#{api_version}")
+ Gitlab::Utils.append_path(base_uri, "rest/api/#{api_version}")
end
def delete_url(resource, path)
if resource == :branches
- url_join_paths(base_uri, "/rest/branch-utils/#{api_version}#{path}")
+ Gitlab::Utils.append_path(base_uri, "rest/branch-utils/#{api_version}#{path}")
else
build_url(path)
end
end
-
- # URI.join is stupid in that slashes are important:
- #
- # # URI.join('http://example.com/subpath', 'hello')
- # => http://example.com/hello
- #
- # We really want http://example.com/subpath/hello
- #
- def url_join_paths(*paths)
- paths.map { |path| strip_slashes(path) }.join(SEPARATOR)
- end
-
- def strip_slashes(path)
- path = path[1..-1] if path.starts_with?(SEPARATOR)
- path.chomp(SEPARATOR)
- end
end
end
diff --git a/lib/bitbucket_server/paginator.rb b/lib/bitbucket_server/paginator.rb
index c351fb2f11f..aa5f84f44b3 100644
--- a/lib/bitbucket_server/paginator.rb
+++ b/lib/bitbucket_server/paginator.rb
@@ -4,34 +4,49 @@ module BitbucketServer
class Paginator
PAGE_LENGTH = 25
- def initialize(connection, url, type)
+ attr_reader :page_offset
+
+ def initialize(connection, url, type, page_offset: 0, limit: nil)
@connection = connection
@type = type
@url = url
@page = nil
+ @page_offset = page_offset
+ @limit = limit || PAGE_LENGTH
+ @total = 0
end
def items
raise StopIteration unless has_next_page?
+ raise StopIteration if over_limit?
@page = fetch_next_page
+ @total += @page.items.count
@page.items
end
+ def has_next_page?
+ page.nil? || page.next?
+ end
+
private
- attr_reader :connection, :page, :url, :type
+ attr_reader :connection, :page, :url, :type, :limit
- def has_next_page?
- page.nil? || page.next?
+ def over_limit?
+ @limit.positive? && @total >= @limit
end
def next_offset
- page.nil? ? 0 : page.next
+ page.nil? ? starting_offset : page.next
+ end
+
+ def starting_offset
+ [0, page_offset - 1].max * limit
end
def fetch_next_page
- parsed_response = connection.get(@url, start: next_offset, limit: PAGE_LENGTH)
+ parsed_response = connection.get(@url, start: next_offset, limit: @limit)
Page.new(parsed_response, type)
end
end
diff --git a/lib/carrier_wave_string_file.rb b/lib/carrier_wave_string_file.rb
index 6c848902e4a..c9a64d9e631 100644
--- a/lib/carrier_wave_string_file.rb
+++ b/lib/carrier_wave_string_file.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class CarrierWaveStringFile < StringIO
def original_filename
""
diff --git a/lib/constraints/feature_constrainer.rb b/lib/constraints/feature_constrainer.rb
index 05d48b0f25a..ca4376a9d38 100644
--- a/lib/constraints/feature_constrainer.rb
+++ b/lib/constraints/feature_constrainer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Constraints
class FeatureConstrainer
attr_reader :feature
diff --git a/lib/constraints/group_url_constrainer.rb b/lib/constraints/group_url_constrainer.rb
index 87649c50424..8a3f8d2faaf 100644
--- a/lib/constraints/group_url_constrainer.rb
+++ b/lib/constraints/group_url_constrainer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Constraints
class GroupUrlConstrainer
def matches?(request)
diff --git a/lib/constraints/project_url_constrainer.rb b/lib/constraints/project_url_constrainer.rb
index 32aea98f0f7..eadfbf7bc01 100644
--- a/lib/constraints/project_url_constrainer.rb
+++ b/lib/constraints/project_url_constrainer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Constraints
class ProjectUrlConstrainer
def matches?(request)
diff --git a/lib/constraints/user_url_constrainer.rb b/lib/constraints/user_url_constrainer.rb
index 8afa04d29a4..e763569cb2e 100644
--- a/lib/constraints/user_url_constrainer.rb
+++ b/lib/constraints/user_url_constrainer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Constraints
class UserUrlConstrainer
def matches?(request)
diff --git a/lib/container_registry/blob.rb b/lib/container_registry/blob.rb
index d5f85f9fcad..837b22c3082 100644
--- a/lib/container_registry/blob.rb
+++ b/lib/container_registry/blob.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ContainerRegistry
class Blob
attr_reader :repository, :config
diff --git a/lib/container_registry/client.rb b/lib/container_registry/client.rb
index 010ca1ec27b..c80f49f5ae0 100644
--- a/lib/container_registry/client.rb
+++ b/lib/container_registry/client.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'faraday'
require 'faraday_middleware'
diff --git a/lib/container_registry/config.rb b/lib/container_registry/config.rb
index 589f9f4380a..740c0e13da0 100644
--- a/lib/container_registry/config.rb
+++ b/lib/container_registry/config.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ContainerRegistry
class Config
attr_reader :tag, :blob, :data
diff --git a/lib/container_registry/path.rb b/lib/container_registry/path.rb
index 1ab14c1c155..9b2a61cdedc 100644
--- a/lib/container_registry/path.rb
+++ b/lib/container_registry/path.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ContainerRegistry
##
# Class responsible for extracting project and repository name from
diff --git a/lib/container_registry/registry.rb b/lib/container_registry/registry.rb
index f90d711474a..523364ac7c7 100644
--- a/lib/container_registry/registry.rb
+++ b/lib/container_registry/registry.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ContainerRegistry
class Registry
attr_reader :uri, :client, :path
diff --git a/lib/container_registry/tag.rb b/lib/container_registry/tag.rb
index c785bca4dad..8633e764f90 100644
--- a/lib/container_registry/tag.rb
+++ b/lib/container_registry/tag.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ContainerRegistry
class Tag
attr_reader :repository, :name
diff --git a/lib/declarative_policy.rb b/lib/declarative_policy.rb
index dda6cd38dcd..5e22523e45a 100644
--- a/lib/declarative_policy.rb
+++ b/lib/declarative_policy.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_dependency 'declarative_policy/cache'
require_dependency 'declarative_policy/condition'
require_dependency 'declarative_policy/delegate_dsl'
@@ -10,8 +12,6 @@ require_dependency 'declarative_policy/step'
require_dependency 'declarative_policy/base'
-require 'thread'
-
module DeclarativePolicy
CLASS_CACHE_MUTEX = Mutex.new
CLASS_CACHE_IVAR = :@__DeclarativePolicy_CLASS_CACHE
diff --git a/lib/declarative_policy/base.rb b/lib/declarative_policy/base.rb
index da3fabba39b..cd6e1606f22 100644
--- a/lib/declarative_policy/base.rb
+++ b/lib/declarative_policy/base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module DeclarativePolicy
class Base
# A map of ability => list of rules together with :enable
diff --git a/lib/declarative_policy/cache.rb b/lib/declarative_policy/cache.rb
index 780d8f707bd..13006e56454 100644
--- a/lib/declarative_policy/cache.rb
+++ b/lib/declarative_policy/cache.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module DeclarativePolicy
module Cache
class << self
diff --git a/lib/declarative_policy/condition.rb b/lib/declarative_policy/condition.rb
index 51c4a8b2bbe..b77f40b1093 100644
--- a/lib/declarative_policy/condition.rb
+++ b/lib/declarative_policy/condition.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module DeclarativePolicy
# A Condition is the data structure that is created by the
# `condition` declaration on DeclarativePolicy::Base. It is
diff --git a/lib/declarative_policy/delegate_dsl.rb b/lib/declarative_policy/delegate_dsl.rb
index ca2eb98e3e8..67e3429b696 100644
--- a/lib/declarative_policy/delegate_dsl.rb
+++ b/lib/declarative_policy/delegate_dsl.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module DeclarativePolicy
# Used when the name of a delegate is mentioned in
# the rule DSL.
diff --git a/lib/declarative_policy/policy_dsl.rb b/lib/declarative_policy/policy_dsl.rb
index c96049768a1..96741c0478e 100644
--- a/lib/declarative_policy/policy_dsl.rb
+++ b/lib/declarative_policy/policy_dsl.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module DeclarativePolicy
# The return value of a rule { ... } declaration.
# Can call back to register rules with the containing
diff --git a/lib/declarative_policy/preferred_scope.rb b/lib/declarative_policy/preferred_scope.rb
index c77784cb49d..239780d8626 100644
--- a/lib/declarative_policy/preferred_scope.rb
+++ b/lib/declarative_policy/preferred_scope.rb
@@ -1,4 +1,7 @@
-module DeclarativePolicy # rubocop:disable Naming/FileName
+# rubocop:disable Naming/FileName
+# frozen_string_literal: true
+
+module DeclarativePolicy
PREFERRED_SCOPE_KEY = :"DeclarativePolicy.preferred_scope"
class << self
diff --git a/lib/declarative_policy/rule.rb b/lib/declarative_policy/rule.rb
index 407398cc770..f38f4f0a50f 100644
--- a/lib/declarative_policy/rule.rb
+++ b/lib/declarative_policy/rule.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module DeclarativePolicy
module Rule
# A Rule is the object that results from the `rule` declaration,
diff --git a/lib/declarative_policy/rule_dsl.rb b/lib/declarative_policy/rule_dsl.rb
index 7254b08eda5..85da7f261fa 100644
--- a/lib/declarative_policy/rule_dsl.rb
+++ b/lib/declarative_policy/rule_dsl.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module DeclarativePolicy
# The DSL evaluation context inside rule { ... } blocks.
# Responsible for creating and combining Rule objects.
diff --git a/lib/declarative_policy/runner.rb b/lib/declarative_policy/runner.rb
index fec672f4b8c..f739fe5e16e 100644
--- a/lib/declarative_policy/runner.rb
+++ b/lib/declarative_policy/runner.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module DeclarativePolicy
class Runner
class State
diff --git a/lib/declarative_policy/step.rb b/lib/declarative_policy/step.rb
index 3469fe9f991..c289c17cc19 100644
--- a/lib/declarative_policy/step.rb
+++ b/lib/declarative_policy/step.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module DeclarativePolicy
# This object represents one step in the runtime decision of whether
# an ability is allowed. It contains a Rule and a context (instance
diff --git a/lib/event_filter.rb b/lib/event_filter.rb
index f756a211a12..24fdcd6fbb1 100644
--- a/lib/event_filter.rb
+++ b/lib/event_filter.rb
@@ -1,76 +1,42 @@
-class EventFilter
- attr_accessor :params
-
- class << self
- def all
- 'all'
- end
-
- def push
- 'push'
- end
-
- def merged
- 'merged'
- end
+# frozen_string_literal: true
- def issue
- 'issue'
- end
-
- def comments
- 'comments'
- end
-
- def team
- 'team'
- end
+class EventFilter
+ attr_accessor :filter
+
+ ALL = 'all'
+ PUSH = 'push'
+ MERGED = 'merged'
+ ISSUE = 'issue'
+ COMMENTS = 'comments'
+ TEAM = 'team'
+ FILTERS = [ALL, PUSH, MERGED, ISSUE, COMMENTS, TEAM].freeze
+
+ def initialize(filter)
+ # Split using comma to maintain backward compatibility Ex/ "filter1,filter2"
+ filter = filter.to_s.split(',')[0].to_s
+ @filter = FILTERS.include?(filter) ? filter : ALL
end
- def initialize(params)
- @params = if params
- params.dup
- else
- [] # EventFilter.default_filter
- end
+ def active?(key)
+ filter == key.to_s
end
# rubocop: disable CodeReuse/ActiveRecord
def apply_filter(events)
- return events if params.blank? || params == EventFilter.all
-
- case params
- when EventFilter.push
+ case filter
+ when PUSH
events.where(action: Event::PUSHED)
- when EventFilter.merged
+ when MERGED
events.where(action: Event::MERGED)
- when EventFilter.comments
+ when COMMENTS
events.where(action: Event::COMMENTED)
- when EventFilter.team
+ when TEAM
events.where(action: [Event::JOINED, Event::LEFT, Event::EXPIRED])
- when EventFilter.issue
+ when ISSUE
events.where(action: [Event::CREATED, Event::UPDATED, Event::CLOSED, Event::REOPENED])
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def options(key)
- filter = params.dup
-
- if filter.include? key
- filter.delete key
else
- filter << key
- end
-
- filter
- end
-
- def active?(key)
- if params.present?
- params.include? key
- else
- key == EventFilter.all
+ events
end
end
+ # rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/lib/expand_variables.rb b/lib/expand_variables.rb
index 7b1533d0d32..c83cec9dc4a 100644
--- a/lib/expand_variables.rb
+++ b/lib/expand_variables.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ExpandVariables
class << self
def expand(value, variables)
diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index e02d403f7b1..b2c8d46ede1 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Module providing methods for dealing with separating a tree-ish string and a
# file path string when combined in a request parameter
module ExtractsPath
@@ -50,7 +52,9 @@ module ExtractsPath
# branches and tags
# Append a trailing slash if we only get a ref and no file path
- id += '/' unless id.ends_with?('/')
+ unless id.ends_with?('/')
+ id = [id, '/'].join
+ end
valid_refs = ref_names.select { |v| id.start_with?("#{v}/") }
@@ -106,11 +110,6 @@ module ExtractsPath
# resolved (e.g., when a user inserts an invalid path or ref).
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def assign_ref_vars
- # assign allowed options
- allowed_options = ["filter_ref"]
- @options = params.select {|key, value| allowed_options.include?(key) && !value.blank? }
- @options = HashWithIndifferentAccess.new(@options)
-
@id = get_id
@ref, @path = extract_ref(@id)
@repo = @project.repository
@@ -149,11 +148,11 @@ module ExtractsPath
private
- # overriden in subclasses, do not remove
+ # overridden in subclasses, do not remove
def get_id
- id = params[:id] || params[:ref]
- id += "/" + params[:path] unless params[:path].blank?
- id
+ id = [params[:id] || params[:ref]]
+ id << "/" + params[:path] unless params[:path].blank?
+ id.join
end
def ref_names
diff --git a/lib/feature.rb b/lib/feature.rb
index f4b57376313..e048a443abc 100644
--- a/lib/feature.rb
+++ b/lib/feature.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'flipper/adapters/active_record'
require 'flipper/adapters/active_support_cache_store'
@@ -28,11 +30,7 @@ class Feature
end
def persisted_names
- if RequestStore.active?
- RequestStore[:flipper_persisted_names] ||= FlipperFeature.feature_names
- else
- FlipperFeature.feature_names
- end
+ Gitlab::SafeRequestStore[:flipper_persisted_names] ||= FlipperFeature.feature_names
end
def persisted?(feature)
@@ -76,8 +74,8 @@ class Feature
end
def flipper
- if RequestStore.active?
- RequestStore[:flipper] ||= build_flipper_instance
+ if Gitlab::SafeRequestStore.active?
+ Gitlab::SafeRequestStore[:flipper] ||= build_flipper_instance
else
@flipper ||= build_flipper_instance
end
diff --git a/lib/file_size_validator.rb b/lib/file_size_validator.rb
index 53aa8d04e5c..70a145cd5bd 100644
--- a/lib/file_size_validator.rb
+++ b/lib/file_size_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class FileSizeValidator < ActiveModel::EachValidator
MESSAGES = { is: :wrong_size, minimum: :size_too_small, maximum: :size_too_big }.freeze
CHECKS = { is: :==, minimum: :>=, maximum: :<= }.freeze
diff --git a/lib/flowdock/git.rb b/lib/flowdock/git.rb
new file mode 100644
index 00000000000..f165ecfc1fa
--- /dev/null
+++ b/lib/flowdock/git.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+require 'flowdock'
+require 'flowdock/git/builder'
+
+module Flowdock
+ class Git
+ TokenError = Class.new(StandardError)
+
+ DEFAULT_PERMANENT_REFS = [
+ Regexp.new('refs/heads/master')
+ ].freeze
+
+ class << self
+ def post(ref, from, to, options = {})
+ Git.new(ref, from, to, options).post
+ end
+ end
+
+ def initialize(ref, from, to, options = {})
+ raise TokenError.new("Flowdock API token not found") unless options[:token]
+
+ @ref = ref
+ @from = from
+ @to = to
+ @options = options
+ @token = options[:token]
+ @commit_url = options[:commit_url]
+ @diff_url = options[:diff_url]
+ @repo_url = options[:repo_url]
+ @repo_name = options[:repo_name]
+ @permanent_refs = options.fetch(:permanent_refs, DEFAULT_PERMANENT_REFS)
+ end
+
+ # Send git push notification to Flowdock
+ def post
+ messages.each do |message|
+ Flowdock::Client.new(flow_token: @token).post_to_thread(message)
+ end
+ end
+
+ def repo
+ @options[:repo]
+ end
+
+ private
+
+ def messages
+ Git::Builder.new(repo: repo,
+ ref: @ref,
+ before: @from,
+ after: @to,
+ commit_url: @commit_url,
+ branch_url: @branch_url,
+ diff_url: @diff_url,
+ repo_url: @repo_url,
+ repo_name: @repo_name,
+ permanent_refs: @permanent_refs,
+ tags: tags
+ ).to_hashes
+ end
+
+ # Flowdock tags attached to the push notification
+ def tags
+ Array(@options[:tags]).map { |tag| CGI.escape(tag) }
+ end
+ end
+end
diff --git a/lib/flowdock/git/builder.rb b/lib/flowdock/git/builder.rb
new file mode 100644
index 00000000000..6f4428d1f42
--- /dev/null
+++ b/lib/flowdock/git/builder.rb
@@ -0,0 +1,145 @@
+# frozen_string_literal: true
+module Flowdock
+ class Git
+ class Commit
+ def initialize(external_thread_id, thread, tags, commit)
+ @commit = commit
+ @external_thread_id = external_thread_id
+ @thread = thread
+ @tags = tags
+ end
+
+ def to_hash
+ hash = {
+ external_thread_id: @external_thread_id,
+ event: "activity",
+ author: {
+ name: @commit[:author][:name],
+ email: @commit[:author][:email]
+ },
+ title: title,
+ thread: @thread,
+ body: body
+ }
+ hash[:tags] = @tags if @tags
+ encode(hash)
+ end
+
+ private
+
+ def encode(hash)
+ return hash unless "".respond_to?(:encode)
+
+ encode_as_utf8(hash)
+ end
+
+ # This only works on Ruby 1.9
+ def encode_as_utf8(obj)
+ if obj.is_a? Hash
+ obj.each_pair do |key, val|
+ encode_as_utf8(val)
+ end
+ elsif obj.is_a?(Array)
+ obj.each do |val|
+ encode_as_utf8(val)
+ end
+ elsif obj.is_a?(String) && obj.encoding != Encoding::UTF_8
+ unless obj.force_encoding("UTF-8").valid_encoding?
+ obj.force_encoding("ISO-8859-1").encode!(Encoding::UTF_8, invalid: :replace, undef: :replace)
+ end
+ end
+ end
+
+ def body
+ content = @commit[:message][first_line.size..-1]
+ content.strip! if content
+ "<pre>#{content}</pre>" unless content.empty?
+ end
+
+ def first_line
+ @first_line ||= (@commit[:message].split("\n")[0] || @commit[:message])
+ end
+
+ def title
+ commit_id = @commit[:id][0, 7]
+ if @commit[:url]
+ "<a href=\"#{@commit[:url]}\">#{commit_id}</a> #{message_title}"
+ else
+ "#{commit_id} #{message_title}"
+ end
+ end
+
+ def message_title
+ CGI.escape_html(first_line.strip)
+ end
+ end
+
+ # Class used to build Git payload
+ class Builder
+ include ::Gitlab::Utils::StrongMemoize
+
+ def initialize(opts)
+ @repo = opts[:repo]
+ @ref = opts[:ref]
+ @before = opts[:before]
+ @after = opts[:after]
+ @opts = opts
+ end
+
+ def commits
+ @repo.commits_between(@before, @after).map do |commit|
+ {
+ url: @opts[:commit_url] ? @opts[:commit_url] % [commit.sha] : nil,
+ id: commit.sha,
+ message: commit.message,
+ author: {
+ name: commit.author_name,
+ email: commit.author_email
+ }
+ }
+ end
+ end
+
+ def ref_name
+ @ref.to_s.sub(%r{\Arefs/(heads|tags)/}, '')
+ end
+
+ def to_hashes
+ commits.map do |commit|
+ Commit.new(external_thread_id, thread, @opts[:tags], commit).to_hash
+ end
+ end
+
+ private
+
+ def thread
+ @thread ||= {
+ title: thread_title,
+ external_url: @opts[:repo_url]
+ }
+ end
+
+ def permanent?
+ strong_memoize(:permanent) do
+ @opts[:permanent_refs].any? { |regex| regex.match(@ref) }
+ end
+ end
+
+ def thread_title
+ action = "updated" if permanent?
+ type = @ref =~ %r(^refs/heads/) ? "branch" : "tag"
+
+ [@opts[:repo_name], type, ref_name, action].compact.join(" ")
+ end
+
+ def external_thread_id
+ @external_thread_id ||=
+ if permanent?
+ SecureRandom.hex
+ else
+ @ref
+ end
+ end
+ end
+ end
+end
diff --git a/lib/forever.rb b/lib/forever.rb
index 7df17912544..0a37118fe68 100644
--- a/lib/forever.rb
+++ b/lib/forever.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class Forever
POSTGRESQL_DATE = DateTime.new(3000, 1, 1)
MYSQL_DATE = DateTime.new(2038, 01, 19)
diff --git a/lib/generators/rails/post_deployment_migration/post_deployment_migration_generator.rb b/lib/generators/rails/post_deployment_migration/post_deployment_migration_generator.rb
index 91175b49c79..15cdd25e711 100644
--- a/lib/generators/rails/post_deployment_migration/post_deployment_migration_generator.rb
+++ b/lib/generators/rails/post_deployment_migration/post_deployment_migration_generator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rails/generators'
module Rails
diff --git a/lib/gitaly/server.rb b/lib/gitaly/server.rb
index f95e423ef22..7b238623418 100644
--- a/lib/gitaly/server.rb
+++ b/lib/gitaly/server.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitaly
class Server
def self.all
diff --git a/lib/gitlab.rb b/lib/gitlab.rb
index ab6b609d099..2ef54658a11 100644
--- a/lib/gitlab.rb
+++ b/lib/gitlab.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_dependency 'gitlab/popen'
module Gitlab
@@ -47,4 +49,12 @@ module Gitlab
def self.dev_env_or_com?
Rails.env.development? || org? || com?
end
+
+ def self.pre_release?
+ VERSION.include?('pre')
+ end
+
+ def self.version_info
+ Gitlab::VersionInfo.parse(Gitlab::VERSION)
+ end
end
diff --git a/lib/gitlab/access.rb b/lib/gitlab/access.rb
index b170145f013..ec090aea784 100644
--- a/lib/gitlab/access.rb
+++ b/lib/gitlab/access.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Gitlab::Access module
#
# Define allowed roles that can be used
diff --git a/lib/gitlab/action_rate_limiter.rb b/lib/gitlab/action_rate_limiter.rb
index 4cd3bdefda3..c442211e073 100644
--- a/lib/gitlab/action_rate_limiter.rb
+++ b/lib/gitlab/action_rate_limiter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
# This class implements a simple rate limiter that can be used to throttle
# certain actions. Unlike Rack Attack and Rack::Throttle, which operate at
diff --git a/lib/gitlab/allowable.rb b/lib/gitlab/allowable.rb
index 45c2b01dd8f..4518c8a862c 100644
--- a/lib/gitlab/allowable.rb
+++ b/lib/gitlab/allowable.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Allowable
def can?(*args)
diff --git a/lib/gitlab/app_logger.rb b/lib/gitlab/app_logger.rb
index dddcb2538f9..5edec8b3efe 100644
--- a/lib/gitlab/app_logger.rb
+++ b/lib/gitlab/app_logger.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class AppLogger < Gitlab::Logger
def self.file_name_noext
diff --git a/lib/gitlab/asciidoc.rb b/lib/gitlab/asciidoc.rb
index 62c41801d75..df8f0470063 100644
--- a/lib/gitlab/asciidoc.rb
+++ b/lib/gitlab/asciidoc.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'asciidoctor'
require 'asciidoctor/converter/html5'
require "asciidoctor-plantuml"
diff --git a/lib/gitlab/audit_json_logger.rb b/lib/gitlab/audit_json_logger.rb
new file mode 100644
index 00000000000..12e0645f3e4
--- /dev/null
+++ b/lib/gitlab/audit_json_logger.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Gitlab
+ class AuditJsonLogger < Gitlab::JsonLogger
+ def self.file_name_noext
+ 'audit_json'
+ end
+ end
+end
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index a36d551d1d7..6eb5f9e2300 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
MissingPersonalAccessTokenError = Class.new(StandardError)
@@ -149,17 +151,15 @@ module Gitlab
end
# rubocop: enable CodeReuse/ActiveRecord
- # rubocop: disable CodeReuse/ActiveRecord
def personal_access_token_check(password)
return unless password.present?
- token = PersonalAccessTokensFinder.new(state: 'active').find_by(token: password)
+ token = PersonalAccessTokensFinder.new(state: 'active').find_by_token(password)
if token && valid_scoped_token?(token, available_scopes)
Gitlab::Auth::Result.new(token.user, nil, :personal_access_token, abilities_for_scopes(token.scopes))
end
end
- # rubocop: enable CodeReuse/ActiveRecord
def valid_oauth_token?(token)
token && token.accessible? && valid_scoped_token?(token, [:api])
diff --git a/lib/gitlab/auth/activity.rb b/lib/gitlab/auth/activity.rb
index 761f0819c60..558628b5422 100644
--- a/lib/gitlab/auth/activity.rb
+++ b/lib/gitlab/auth/activity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
##
diff --git a/lib/gitlab/auth/database/authentication.rb b/lib/gitlab/auth/database/authentication.rb
index 1234ace0334..c0dc2b0875f 100644
--- a/lib/gitlab/auth/database/authentication.rb
+++ b/lib/gitlab/auth/database/authentication.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# These calls help to authenticate to OAuth provider by providing username and password
#
diff --git a/lib/gitlab/auth/ip_rate_limiter.rb b/lib/gitlab/auth/ip_rate_limiter.rb
index e6173d45af3..81e616fa20a 100644
--- a/lib/gitlab/auth/ip_rate_limiter.rb
+++ b/lib/gitlab/auth/ip_rate_limiter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
class IpRateLimiter
diff --git a/lib/gitlab/auth/ldap/access.rb b/lib/gitlab/auth/ldap/access.rb
index f323d2e0f7a..c875bba4bcb 100644
--- a/lib/gitlab/auth/ldap/access.rb
+++ b/lib/gitlab/auth/ldap/access.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# LDAP authorization model
#
# * Check if we are allowed access (not blocked)
diff --git a/lib/gitlab/auth/ldap/adapter.rb b/lib/gitlab/auth/ldap/adapter.rb
index 82ff1e77e5c..42c657afe6a 100644
--- a/lib/gitlab/auth/ldap/adapter.rb
+++ b/lib/gitlab/auth/ldap/adapter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
module LDAP
diff --git a/lib/gitlab/auth/ldap/auth_hash.rb b/lib/gitlab/auth/ldap/auth_hash.rb
index ac5c14d374d..83fdc8a8c76 100644
--- a/lib/gitlab/auth/ldap/auth_hash.rb
+++ b/lib/gitlab/auth/ldap/auth_hash.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Class to parse and transform the info provided by omniauth
#
module Gitlab
diff --git a/lib/gitlab/auth/ldap/authentication.rb b/lib/gitlab/auth/ldap/authentication.rb
index 7c134fb6438..174e81dd603 100644
--- a/lib/gitlab/auth/ldap/authentication.rb
+++ b/lib/gitlab/auth/ldap/authentication.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# These calls help to authenticate to LDAP by providing username and password
#
# Since multiple LDAP servers are supported, it will loop through all of them
diff --git a/lib/gitlab/auth/ldap/config.rb b/lib/gitlab/auth/ldap/config.rb
index d4415eaa6dc..7ceb96f502b 100644
--- a/lib/gitlab/auth/ldap/config.rb
+++ b/lib/gitlab/auth/ldap/config.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Load a specific server configuration
module Gitlab
module Auth
diff --git a/lib/gitlab/auth/ldap/dn.rb b/lib/gitlab/auth/ldap/dn.rb
index 1fa5338f5a6..5df914aa367 100644
--- a/lib/gitlab/auth/ldap/dn.rb
+++ b/lib/gitlab/auth/ldap/dn.rb
@@ -1,4 +1,5 @@
# -*- ruby encoding: utf-8 -*-
+# frozen_string_literal: true
# Based on the `ruby-net-ldap` gem's `Net::LDAP::DN`
#
diff --git a/lib/gitlab/auth/ldap/ldap_connection_error.rb b/lib/gitlab/auth/ldap/ldap_connection_error.rb
index ef0a695742b..d0e5f24d203 100644
--- a/lib/gitlab/auth/ldap/ldap_connection_error.rb
+++ b/lib/gitlab/auth/ldap/ldap_connection_error.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
module LDAP
diff --git a/lib/gitlab/auth/ldap/person.rb b/lib/gitlab/auth/ldap/person.rb
index 8dfae3ee541..a0244a3cea1 100644
--- a/lib/gitlab/auth/ldap/person.rb
+++ b/lib/gitlab/auth/ldap/person.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
module LDAP
diff --git a/lib/gitlab/auth/ldap/user.rb b/lib/gitlab/auth/ldap/user.rb
index 3c21ddf3241..9c71671f409 100644
--- a/lib/gitlab/auth/ldap/user.rb
+++ b/lib/gitlab/auth/ldap/user.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# LDAP extension for User model
#
# * Find or create user from omniauth.auth data
diff --git a/lib/gitlab/auth/o_auth/auth_hash.rb b/lib/gitlab/auth/o_auth/auth_hash.rb
index ed8fba94305..36fc8061d92 100644
--- a/lib/gitlab/auth/o_auth/auth_hash.rb
+++ b/lib/gitlab/auth/o_auth/auth_hash.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Class to parse and transform the info provided by omniauth
#
module Gitlab
@@ -78,7 +80,7 @@ module Gitlab
end
# Get the first part of the email address (before @)
- # In addtion in removes illegal characters
+ # In addition in removes illegal characters
def generate_username(email)
email.match(/^[^@]*/)[0].mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/, '').to_s
end
diff --git a/lib/gitlab/auth/o_auth/authentication.rb b/lib/gitlab/auth/o_auth/authentication.rb
index d4e7f35c857..5f008678bd1 100644
--- a/lib/gitlab/auth/o_auth/authentication.rb
+++ b/lib/gitlab/auth/o_auth/authentication.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# These calls help to authenticate to OAuth provider by providing username and password
#
diff --git a/lib/gitlab/auth/o_auth/identity_linker.rb b/lib/gitlab/auth/o_auth/identity_linker.rb
index de92d7a214d..e69c2bb54dc 100644
--- a/lib/gitlab/auth/o_auth/identity_linker.rb
+++ b/lib/gitlab/auth/o_auth/identity_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
module OAuth
diff --git a/lib/gitlab/auth/o_auth/provider.rb b/lib/gitlab/auth/o_auth/provider.rb
index 26da9d09ccc..9fdf3324db3 100644
--- a/lib/gitlab/auth/o_auth/provider.rb
+++ b/lib/gitlab/auth/o_auth/provider.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
module OAuth
diff --git a/lib/gitlab/auth/o_auth/session.rb b/lib/gitlab/auth/o_auth/session.rb
index 8f2b4d58552..4925b107042 100644
--- a/lib/gitlab/auth/o_auth/session.rb
+++ b/lib/gitlab/auth/o_auth/session.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# :nocov:
module Gitlab
module Auth
diff --git a/lib/gitlab/auth/o_auth/user.rb b/lib/gitlab/auth/o_auth/user.rb
index 2b4f6ed75e5..a4e8a41b246 100644
--- a/lib/gitlab/auth/o_auth/user.rb
+++ b/lib/gitlab/auth/o_auth/user.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# OAuth extension for User model
#
# * Find GitLab user based on omniauth uid and provider
diff --git a/lib/gitlab/auth/omniauth_identity_linker_base.rb b/lib/gitlab/auth/omniauth_identity_linker_base.rb
index 8ae29a02a13..253445570f2 100644
--- a/lib/gitlab/auth/omniauth_identity_linker_base.rb
+++ b/lib/gitlab/auth/omniauth_identity_linker_base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
class OmniauthIdentityLinkerBase
diff --git a/lib/gitlab/auth/request_authenticator.rb b/lib/gitlab/auth/request_authenticator.rb
index 66de52506ce..176766d1a8b 100644
--- a/lib/gitlab/auth/request_authenticator.rb
+++ b/lib/gitlab/auth/request_authenticator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Use for authentication only, in particular for Rack::Attack.
# Does not perform authorization of scopes, etc.
module Gitlab
@@ -11,12 +13,18 @@ module Gitlab
@request = request
end
- def user
- find_sessionless_user || find_user_from_warden
+ def user(request_formats)
+ request_formats.each do |format|
+ user = find_sessionless_user(format)
+
+ return user if user
+ end
+
+ find_user_from_warden
end
- def find_sessionless_user
- find_user_from_access_token || find_user_from_feed_token
+ def find_sessionless_user(request_format)
+ find_user_from_web_access_token(request_format) || find_user_from_feed_token(request_format)
rescue Gitlab::Auth::AuthenticationError
nil
end
diff --git a/lib/gitlab/auth/result.rb b/lib/gitlab/auth/result.rb
index 00cdc94a9ef..78fa25c5516 100644
--- a/lib/gitlab/auth/result.rb
+++ b/lib/gitlab/auth/result.rb
@@ -1,4 +1,7 @@
-module Gitlab # rubocop:disable Naming/FileName
+# rubocop:disable Naming/FileName
+# frozen_string_literal: true
+
+module Gitlab
module Auth
Result = Struct.new(:actor, :project, :type, :authentication_abilities) do
def ci?(for_project)
diff --git a/lib/gitlab/auth/saml/auth_hash.rb b/lib/gitlab/auth/saml/auth_hash.rb
index 3bc5e2864df..1af9fa40c3a 100644
--- a/lib/gitlab/auth/saml/auth_hash.rb
+++ b/lib/gitlab/auth/saml/auth_hash.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
module Saml
@@ -26,7 +28,7 @@ module Gitlab
end
def extract_authn_context(document)
- REXML::XPath.first(document, "//saml:AuthnStatement/saml:AuthnContext/saml:AuthnContextClassRef/text()").to_s
+ REXML::XPath.first(document, "//*[name()='saml:AuthnStatement' or name()='saml2:AuthnStatement']/*[name()='saml:AuthnContext' or name()='saml2:AuthnContext']/*[name()='saml:AuthnContextClassRef' or name()='saml2:AuthnContextClassRef']/text()").to_s
end
end
end
diff --git a/lib/gitlab/auth/saml/config.rb b/lib/gitlab/auth/saml/config.rb
index 625dab7c6f4..8cb999f50d4 100644
--- a/lib/gitlab/auth/saml/config.rb
+++ b/lib/gitlab/auth/saml/config.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
module Saml
diff --git a/lib/gitlab/auth/saml/identity_linker.rb b/lib/gitlab/auth/saml/identity_linker.rb
index 7e4b191d512..ae0d6dded4e 100644
--- a/lib/gitlab/auth/saml/identity_linker.rb
+++ b/lib/gitlab/auth/saml/identity_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
module Saml
diff --git a/lib/gitlab/auth/saml/user.rb b/lib/gitlab/auth/saml/user.rb
index 6c3b75f3eb0..ec95bc46791 100644
--- a/lib/gitlab/auth/saml/user.rb
+++ b/lib/gitlab/auth/saml/user.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# SAML extension for User model
#
# * Find GitLab user based on SAML uid and provider
diff --git a/lib/gitlab/auth/too_many_ips.rb b/lib/gitlab/auth/too_many_ips.rb
index ed862791551..ee4d80e6b89 100644
--- a/lib/gitlab/auth/too_many_ips.rb
+++ b/lib/gitlab/auth/too_many_ips.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
class TooManyIps < StandardError
diff --git a/lib/gitlab/auth/unique_ips_limiter.rb b/lib/gitlab/auth/unique_ips_limiter.rb
index baa1f802d8a..31dd61ae6cf 100644
--- a/lib/gitlab/auth/unique_ips_limiter.rb
+++ b/lib/gitlab/auth/unique_ips_limiter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
class UniqueIpsLimiter
diff --git a/lib/gitlab/auth/user_access_denied_reason.rb b/lib/gitlab/auth/user_access_denied_reason.rb
index 1893cb001b2..fd09fe76c02 100644
--- a/lib/gitlab/auth/user_access_denied_reason.rb
+++ b/lib/gitlab/auth/user_access_denied_reason.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
class UserAccessDeniedReason
diff --git a/lib/gitlab/auth/user_auth_finders.rb b/lib/gitlab/auth/user_auth_finders.rb
index 064cba43278..a5efe33bdc6 100644
--- a/lib/gitlab/auth/user_auth_finders.rb
+++ b/lib/gitlab/auth/user_auth_finders.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Auth
AuthenticationError = Class.new(StandardError)
@@ -5,6 +7,7 @@ module Gitlab
TokenNotFoundError = Class.new(AuthenticationError)
ExpiredError = Class.new(AuthenticationError)
RevokedError = Class.new(AuthenticationError)
+ ImpersonationDisabled = Class.new(AuthenticationError)
UnauthorizedError = Class.new(AuthenticationError)
class InsufficientScopeError < AuthenticationError
@@ -25,8 +28,8 @@ module Gitlab
current_request.env['warden']&.authenticate if verified_request?
end
- def find_user_from_feed_token
- return unless rss_request? || ics_request?
+ def find_user_from_feed_token(request_format)
+ return unless valid_rss_format?(request_format)
# NOTE: feed_token was renamed from rss_token but both needs to be supported because
# users might have already added the feed to their RSS reader before the rename
@@ -36,6 +39,17 @@ module Gitlab
User.find_by_feed_token(token) || raise(UnauthorizedError)
end
+ # We only allow Private Access Tokens with `api` scope to be used by web
+ # requests on RSS feeds or ICS files for backwards compatibility.
+ # It is also used by GraphQL/API requests.
+ def find_user_from_web_access_token(request_format)
+ return unless access_token && valid_web_access_format?(request_format)
+
+ validate_access_token!(scopes: [:api])
+
+ access_token.user || raise(UnauthorizedError)
+ end
+
def find_user_from_access_token
return unless access_token
@@ -54,6 +68,8 @@ module Gitlab
raise ExpiredError
when AccessTokenValidationService::REVOKED
raise RevokedError
+ when AccessTokenValidationService::IMPERSONATION_DISABLED
+ raise ImpersonationDisabled
end
end
@@ -71,7 +87,6 @@ module Gitlab
end
end
- # rubocop: disable CodeReuse/ActiveRecord
def find_personal_access_token
token =
current_request.params[PRIVATE_TOKEN_PARAM].presence ||
@@ -80,9 +95,8 @@ module Gitlab
return unless token
# Expiration, revocation and scopes are verified in `validate_access_token!`
- PersonalAccessToken.find_by(token: token) || raise(UnauthorizedError)
+ PersonalAccessToken.find_by_token(token) || raise(UnauthorizedError)
end
- # rubocop: enable CodeReuse/ActiveRecord
def find_oauth_access_token
token = Doorkeeper::OAuth::Token.from_request(current_request, *Doorkeeper.configuration.access_token_methods)
@@ -109,6 +123,26 @@ module Gitlab
@current_request ||= ensure_action_dispatch_request(request)
end
+ def valid_web_access_format?(request_format)
+ case request_format
+ when :rss
+ rss_request?
+ when :ics
+ ics_request?
+ when :api
+ api_request?
+ end
+ end
+
+ def valid_rss_format?(request_format)
+ case request_format
+ when :rss
+ rss_request?
+ when :ics
+ ics_request?
+ end
+ end
+
def rss_request?
current_request.path.ends_with?('.atom') || current_request.format.atom?
end
@@ -116,6 +150,10 @@ module Gitlab
def ics_request?
current_request.path.ends_with?('.ics') || current_request.format.ics?
end
+
+ def api_request?
+ current_request.path.starts_with?("/api/")
+ end
end
end
end
diff --git a/lib/gitlab/background_migration.rb b/lib/gitlab/background_migration.rb
index 36c85dec544..d72befce571 100644
--- a/lib/gitlab/background_migration.rb
+++ b/lib/gitlab/background_migration.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module BackgroundMigration
def self.queue
diff --git a/lib/gitlab/background_migration/backfill_project_fullpath_in_repo_config.rb b/lib/gitlab/background_migration/backfill_project_fullpath_in_repo_config.rb
new file mode 100644
index 00000000000..29fa0f18448
--- /dev/null
+++ b/lib/gitlab/background_migration/backfill_project_fullpath_in_repo_config.rb
@@ -0,0 +1,209 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # This module is used to write the full path of all projects to
+ # the git repository config file.
+ # Storing the full project path in the git config allows admins to
+ # easily identify a project when it is using hashed storage.
+ module BackfillProjectFullpathInRepoConfig
+ OrphanedNamespaceError = Class.new(StandardError)
+
+ module Storage
+ # Class that returns the disk path for a project using hashed storage
+ class HashedProject
+ attr_accessor :project
+
+ ROOT_PATH_PREFIX = '@hashed'
+
+ def initialize(project)
+ @project = project
+ end
+
+ def disk_path
+ "#{ROOT_PATH_PREFIX}/#{disk_hash[0..1]}/#{disk_hash[2..3]}/#{disk_hash}"
+ end
+
+ def disk_hash
+ @disk_hash ||= Digest::SHA2.hexdigest(project.id.to_s) if project.id
+ end
+ end
+
+ # Class that returns the disk path for a project using legacy storage
+ class LegacyProject
+ attr_accessor :project
+
+ def initialize(project)
+ @project = project
+ end
+
+ def disk_path
+ project.full_path
+ end
+ end
+ end
+
+ # Concern used by Project and Namespace to determine the full
+ # route to the project
+ module Routable
+ extend ActiveSupport::Concern
+
+ def full_path
+ @full_path ||= build_full_path
+ end
+
+ def build_full_path
+ return path unless has_parent?
+
+ raise OrphanedNamespaceError if parent.nil?
+
+ parent.full_path + '/' + path
+ end
+
+ def has_parent?
+ read_attribute(association(:parent).reflection.foreign_key)
+ end
+ end
+
+ # Class used to interact with repository using Gitaly
+ class Repository
+ attr_reader :storage
+
+ def initialize(storage, relative_path)
+ @storage = storage
+ @relative_path = relative_path
+ end
+
+ def gitaly_repository
+ Gitaly::Repository.new(storage_name: @storage, relative_path: @relative_path)
+ end
+ end
+
+ # Namespace can be a user or group. It can be the root or a
+ # child of another namespace.
+ class Namespace < ActiveRecord::Base
+ self.table_name = 'namespaces'
+ self.inheritance_column = nil
+
+ include Routable
+
+ belongs_to :parent, class_name: 'Namespace', inverse_of: 'namespaces'
+ has_many :projects, inverse_of: :parent
+ has_many :namespaces, inverse_of: :parent
+ end
+
+ # Project is where the repository (etc.) is stored
+ class Project < ActiveRecord::Base
+ self.table_name = 'projects'
+
+ include Routable
+ include EachBatch
+
+ FULLPATH_CONFIG_KEY = 'gitlab.fullpath'
+
+ belongs_to :parent, class_name: 'Namespace', foreign_key: :namespace_id, inverse_of: 'projects'
+ delegate :disk_path, to: :storage
+
+ def add_fullpath_config
+ entries = { FULLPATH_CONFIG_KEY => full_path }
+
+ repository_service.set_config(entries)
+ end
+
+ def remove_fullpath_config
+ repository_service.delete_config([FULLPATH_CONFIG_KEY])
+ end
+
+ def cleanup_repository
+ repository_service.cleanup
+ end
+
+ def storage
+ @storage ||=
+ if hashed_storage?
+ Storage::HashedProject.new(self)
+ else
+ Storage::LegacyProject.new(self)
+ end
+ end
+
+ def hashed_storage?
+ self.storage_version && self.storage_version >= 1
+ end
+
+ def repository
+ @repository ||= Repository.new(repository_storage, disk_path + '.git')
+ end
+
+ def repository_service
+ @repository_service ||= Gitlab::GitalyClient::RepositoryService.new(repository)
+ end
+ end
+
+ # Base class for Up and Down migration classes
+ class BackfillFullpathMigration
+ RETRY_DELAY = 15.minutes
+ MAX_RETRIES = 2
+
+ # Base class for retrying one project
+ class BaseRetryOne
+ def perform(project_id, retry_count)
+ project = Project.find(project_id)
+
+ return unless project
+
+ migration_class.new.safe_perform_one(project, retry_count)
+ end
+ end
+
+ def perform(start_id, end_id)
+ Project.includes(:parent).where(id: start_id..end_id).each do |project|
+ safe_perform_one(project)
+ end
+ end
+
+ def safe_perform_one(project, retry_count = 0)
+ perform_one(project)
+ rescue GRPC::NotFound, GRPC::InvalidArgument, OrphanedNamespaceError
+ nil
+ rescue GRPC::BadStatus
+ schedule_retry(project, retry_count + 1) if retry_count < MAX_RETRIES
+ end
+
+ def schedule_retry(project, retry_count)
+ BackgroundMigrationWorker.perform_in(RETRY_DELAY, self.class::RetryOne.name, [project.id, retry_count])
+ end
+ end
+
+ # Class to add the fullpath to the git repo config
+ class Up < BackfillFullpathMigration
+ # Class used to retry
+ class RetryOne < BaseRetryOne
+ def migration_class
+ Up
+ end
+ end
+
+ def perform_one(project)
+ project.cleanup_repository
+ project.add_fullpath_config
+ end
+ end
+
+ # Class to rollback adding the fullpath to the git repo config
+ class Down < BackfillFullpathMigration
+ # Class used to retry
+ class RetryOne < BaseRetryOne
+ def migration_class
+ Down
+ end
+ end
+
+ def perform_one(project)
+ project.cleanup_repository
+ project.remove_fullpath_config
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/digest_column.rb b/lib/gitlab/background_migration/digest_column.rb
new file mode 100644
index 00000000000..22a3bb8f8f3
--- /dev/null
+++ b/lib/gitlab/background_migration/digest_column.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+# rubocop:disable Style/Documentation
+module Gitlab
+ module BackgroundMigration
+ class DigestColumn
+ class PersonalAccessToken < ActiveRecord::Base
+ self.table_name = 'personal_access_tokens'
+ end
+
+ def perform(model, attribute_from, attribute_to, start_id, stop_id)
+ model = model.constantize if model.is_a?(String)
+
+ model.transaction do
+ relation = model.where(id: start_id..stop_id).where.not(attribute_from => nil).lock
+
+ relation.each do |instance|
+ instance.update_columns(attribute_to => Gitlab::CryptoHelper.sha256(instance.read_attribute(attribute_from)),
+ attribute_from => nil)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/encrypt_columns.rb b/lib/gitlab/background_migration/encrypt_columns.rb
new file mode 100644
index 00000000000..bd5f12276ab
--- /dev/null
+++ b/lib/gitlab/background_migration/encrypt_columns.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # EncryptColumn migrates data from an unencrypted column - `foo`, say - to
+ # an encrypted column - `encrypted_foo`, say.
+ #
+ # For this background migration to work, the table that is migrated _has_ to
+ # have an `id` column as the primary key. Additionally, the encrypted column
+ # should be managed by attr_encrypted, and map to an attribute with the same
+ # name as the unencrypted column (i.e., the unencrypted column should be
+ # shadowed).
+ #
+ # To avoid depending on a particular version of the model in app/, add a
+ # model to `lib/gitlab/background_migration/models/encrypt_columns` and use
+ # it in the migration that enqueues the jobs, so code can be shared.
+ class EncryptColumns
+ def perform(model, attributes, from, to)
+ model = model.constantize if model.is_a?(String)
+
+ # If sidekiq hasn't undergone a restart, its idea of what columns are
+ # present may be inaccurate, so ensure this is as fresh as possible
+ model.reset_column_information
+ model.define_attribute_methods
+
+ attributes = expand_attributes(model, Array(attributes).map(&:to_sym))
+
+ model.transaction do
+ # Use SELECT ... FOR UPDATE to prevent the value being changed while
+ # we are encrypting it
+ relation = model.where(id: from..to).lock
+
+ relation.each do |instance|
+ encrypt!(instance, attributes)
+ end
+ end
+ end
+
+ private
+
+ # Build a hash of { attribute => encrypted column name }
+ def expand_attributes(klass, attributes)
+ expanded = attributes.flat_map do |attribute|
+ attr_config = klass.encrypted_attributes[attribute]
+ crypt_column_name = attr_config&.fetch(:attribute)
+
+ raise "Couldn't determine encrypted column for #{klass}##{attribute}" if
+ crypt_column_name.nil?
+
+ raise "#{klass} source column: #{attribute} is missing" unless
+ klass.column_names.include?(attribute.to_s)
+
+ # Running the migration without the destination column being present
+ # leads to data loss
+ raise "#{klass} destination column: #{crypt_column_name} is missing" unless
+ klass.column_names.include?(crypt_column_name.to_s)
+
+ [attribute, crypt_column_name]
+ end
+
+ Hash[*expanded]
+ end
+
+ # Generate ciphertext for each column and update the database
+ def encrypt!(instance, attributes)
+ to_clear = attributes
+ .map { |plain, crypt| apply_attribute!(instance, plain, crypt) }
+ .compact
+ .flat_map { |plain| [plain, nil] }
+
+ to_clear = Hash[*to_clear]
+
+ if instance.changed?
+ instance.save!
+ instance.update_columns(to_clear)
+ end
+ end
+
+ def apply_attribute!(instance, plain_column, crypt_column)
+ plaintext = instance[plain_column]
+ ciphertext = instance[crypt_column]
+
+ # No need to do anything if the plaintext is nil, or an encrypted
+ # value already exists
+ return nil unless plaintext.present? && !ciphertext.present?
+
+ # attr_encrypted will calculate and set the expected value for us
+ instance.public_send("#{plain_column}=", plaintext) # rubocop:disable GitlabSecurity/PublicSend
+
+ plain_column
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/models/encrypt_columns/web_hook.rb b/lib/gitlab/background_migration/models/encrypt_columns/web_hook.rb
new file mode 100644
index 00000000000..bb76eb8ed48
--- /dev/null
+++ b/lib/gitlab/background_migration/models/encrypt_columns/web_hook.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ module Models
+ module EncryptColumns
+ # This model is shared between synchronous and background migrations to
+ # encrypt the `token` and `url` columns
+ class WebHook < ActiveRecord::Base
+ include ::EachBatch
+
+ self.table_name = 'web_hooks'
+ self.inheritance_column = :_type_disabled
+
+ attr_encrypted :token,
+ mode: :per_attribute_iv,
+ algorithm: 'aes-256-gcm',
+ key: Settings.attr_encrypted_db_key_base_truncated
+
+ attr_encrypted :url,
+ mode: :per_attribute_iv,
+ algorithm: 'aes-256-gcm',
+ key: Settings.attr_encrypted_db_key_base_truncated
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table.rb b/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table.rb
new file mode 100644
index 00000000000..35bfc381180
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table.rb
@@ -0,0 +1,82 @@
+# frozen_string_literal: true
+#
+# rubocop:disable Style/Documentation
+
+module Gitlab
+ module BackgroundMigration
+ class PopulateClusterKubernetesNamespaceTable
+ include Gitlab::Database::MigrationHelpers
+
+ BATCH_SIZE = 1_000
+
+ module Migratable
+ class KubernetesNamespace < ActiveRecord::Base
+ self.table_name = 'clusters_kubernetes_namespaces'
+ end
+
+ class ClusterProject < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'cluster_projects'
+
+ belongs_to :project
+
+ def self.with_no_kubernetes_namespace
+ where.not(id: Migratable::KubernetesNamespace.select(:cluster_project_id))
+ end
+
+ def namespace
+ slug = "#{project.path}-#{project.id}".downcase
+ slug.gsub(/[^-a-z0-9]/, '-').gsub(/^-+/, '')
+ end
+
+ def service_account
+ "#{namespace}-service-account"
+ end
+ end
+
+ class Project < ActiveRecord::Base
+ self.table_name = 'projects'
+ end
+ end
+
+ def perform
+ cluster_projects_with_no_kubernetes_namespace.each_batch(of: BATCH_SIZE) do |cluster_projects_batch, index|
+ sql_values = sql_values_for(cluster_projects_batch)
+
+ insert_into_cluster_kubernetes_namespace(sql_values)
+ end
+ end
+
+ private
+
+ def cluster_projects_with_no_kubernetes_namespace
+ Migratable::ClusterProject.with_no_kubernetes_namespace
+ end
+
+ def sql_values_for(cluster_projects)
+ cluster_projects.map do |cluster_project|
+ values_for_cluster_project(cluster_project)
+ end
+ end
+
+ def values_for_cluster_project(cluster_project)
+ {
+ cluster_project_id: cluster_project.id,
+ cluster_id: cluster_project.cluster_id,
+ project_id: cluster_project.project_id,
+ namespace: cluster_project.namespace,
+ service_account_name: cluster_project.service_account,
+ created_at: 'NOW()',
+ updated_at: 'NOW()'
+ }
+ end
+
+ def insert_into_cluster_kubernetes_namespace(rows)
+ Gitlab::Database.bulk_insert(Migratable::KubernetesNamespace.table_name,
+ rows,
+ disable_quote: [:created_at, :updated_at])
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/populate_external_pipeline_source.rb b/lib/gitlab/background_migration/populate_external_pipeline_source.rb
new file mode 100644
index 00000000000..036fe641757
--- /dev/null
+++ b/lib/gitlab/background_migration/populate_external_pipeline_source.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+# rubocop:disable Style/Documentation
+
+module Gitlab
+ module BackgroundMigration
+ class PopulateExternalPipelineSource
+ module Migratable
+ class Pipeline < ActiveRecord::Base
+ self.table_name = 'ci_pipelines'
+
+ def self.sources
+ {
+ unknown: nil,
+ push: 1,
+ web: 2,
+ trigger: 3,
+ schedule: 4,
+ api: 5,
+ external: 6
+ }
+ end
+ end
+
+ class CommitStatus < ActiveRecord::Base
+ self.table_name = 'ci_builds'
+ self.inheritance_column = :_type_disabled
+
+ scope :has_pipeline, -> { where('ci_builds.commit_id=ci_pipelines.id') }
+ scope :of_type, -> (type) { where('type=?', type) }
+ end
+ end
+
+ def perform(start_id, stop_id)
+ external_pipelines(start_id, stop_id)
+ .update_all(source: Migratable::Pipeline.sources[:external])
+ end
+
+ private
+
+ def external_pipelines(start_id, stop_id)
+ Migratable::Pipeline.where(id: (start_id..stop_id))
+ .where(
+ 'EXISTS (?) AND NOT EXISTS (?)',
+ Migratable::CommitStatus.of_type('GenericCommitStatus').has_pipeline.select(1),
+ Migratable::CommitStatus.of_type('Ci::Build').has_pipeline.select(1)
+ )
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/redact_links.rb b/lib/gitlab/background_migration/redact_links.rb
new file mode 100644
index 00000000000..92256e59a6c
--- /dev/null
+++ b/lib/gitlab/background_migration/redact_links.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+# rubocop:disable Style/Documentation
+
+require_relative 'redact_links/redactable'
+
+module Gitlab
+ module BackgroundMigration
+ class RedactLinks
+ class Note < ActiveRecord::Base
+ include EachBatch
+ include ::Gitlab::BackgroundMigration::RedactLinks::Redactable
+
+ self.table_name = 'notes'
+ self.inheritance_column = :_type_disabled
+ end
+
+ class Issue < ActiveRecord::Base
+ include EachBatch
+ include ::Gitlab::BackgroundMigration::RedactLinks::Redactable
+
+ self.table_name = 'issues'
+ self.inheritance_column = :_type_disabled
+ end
+
+ class MergeRequest < ActiveRecord::Base
+ include EachBatch
+ include ::Gitlab::BackgroundMigration::RedactLinks::Redactable
+
+ self.table_name = 'merge_requests'
+ self.inheritance_column = :_type_disabled
+ end
+
+ class Snippet < ActiveRecord::Base
+ include EachBatch
+ include ::Gitlab::BackgroundMigration::RedactLinks::Redactable
+
+ self.table_name = 'snippets'
+ self.inheritance_column = :_type_disabled
+ end
+
+ def perform(model_name, field, start_id, stop_id)
+ link_pattern = "%/sent_notifications/" + ("_" * 32) + "/unsubscribe%"
+ model = "Gitlab::BackgroundMigration::RedactLinks::#{model_name}".constantize
+
+ model.where("#{field} like ?", link_pattern).where(id: start_id..stop_id).each do |resource|
+ resource.redact_field!(field)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/redact_links/redactable.rb b/lib/gitlab/background_migration/redact_links/redactable.rb
new file mode 100644
index 00000000000..baab34221f1
--- /dev/null
+++ b/lib/gitlab/background_migration/redact_links/redactable.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+# rubocop:disable Style/Documentation
+
+module Gitlab
+ module BackgroundMigration
+ class RedactLinks
+ module Redactable
+ extend ActiveSupport::Concern
+
+ def redact_field!(field)
+ self[field].gsub!(%r{/sent_notifications/\h{32}/unsubscribe}, '/sent_notifications/REDACTED/unsubscribe')
+
+ if self.changed?
+ self.update_columns(field => self[field],
+ "#{field}_html" => nil)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/remove_restricted_todos.rb b/lib/gitlab/background_migration/remove_restricted_todos.rb
index 68f3fa62170..47579d46c1b 100644
--- a/lib/gitlab/background_migration/remove_restricted_todos.rb
+++ b/lib/gitlab/background_migration/remove_restricted_todos.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
# rubocop:disable Style/Documentation
+# rubocop:disable Metrics/ClassLength
module Gitlab
module BackgroundMigration
@@ -49,11 +50,14 @@ module Gitlab
private
def remove_non_members_todos(project_id)
- Todo.where(project_id: project_id)
- .where('user_id NOT IN (?)', authorized_users(project_id))
- .each_batch(of: 5000) do |batch|
- batch.delete_all
- end
+ if Gitlab::Database.postgresql?
+ batch_remove_todos_cte(project_id)
+ else
+ unauthorized_project_todos(project_id)
+ .each_batch(of: 5000) do |batch|
+ batch.delete_all
+ end
+ end
end
def remove_confidential_issue_todos(project_id)
@@ -63,7 +67,7 @@ module Gitlab
.where('access_level >= ?', 20)
confidential_issues = Issue.select(:id, :author_id).where(confidential: true, project_id: project_id)
- confidential_issues.each_batch(of: 100) do |batch|
+ confidential_issues.each_batch(of: 100, order_hint: :confidential) do |batch|
batch.each do |issue|
assigned_users = IssueAssignee.select(:user_id).where(issue_id: issue.id)
@@ -86,10 +90,13 @@ module Gitlab
next if target_types.empty?
- Todo.where(project_id: project_id)
- .where('user_id NOT IN (?)', authorized_users(project_id))
- .where(target_type: target_types)
- .delete_all
+ if Gitlab::Database.postgresql?
+ batch_remove_todos_cte(project_id, target_types)
+ else
+ unauthorized_project_todos(project_id)
+ .where(target_type: target_types)
+ .delete_all
+ end
end
end
@@ -100,6 +107,65 @@ module Gitlab
def authorized_users(project_id)
ProjectAuthorization.select(:user_id).where(project_id: project_id)
end
+
+ def unauthorized_project_todos(project_id)
+ Todo.where(project_id: project_id)
+ .where('user_id NOT IN (?)', authorized_users(project_id))
+ end
+
+ def batch_remove_todos_cte(project_id, target_types = nil)
+ loop do
+ count = remove_todos_cte(project_id, target_types)
+
+ break if count == 0
+ end
+ end
+
+ def remove_todos_cte(project_id, target_types = nil)
+ sql = []
+ sql << with_all_todos_sql(project_id, target_types)
+ sql << as_deleted_sql
+ sql << "SELECT count(*) FROM deleted"
+
+ result = Todo.connection.exec_query(sql.join(' '))
+ result.rows[0][0].to_i
+ end
+
+ def with_all_todos_sql(project_id, target_types = nil)
+ if target_types
+ table = Arel::Table.new(:todos)
+ in_target = table[:target_type].in(target_types)
+ target_types_sql = " AND #{in_target.to_sql}"
+ end
+
+ <<-SQL
+ WITH all_todos AS (
+ SELECT id
+ FROM "todos"
+ WHERE "todos"."project_id" = #{project_id}
+ AND (user_id NOT IN (
+ SELECT "project_authorizations"."user_id"
+ FROM "project_authorizations"
+ WHERE "project_authorizations"."project_id" = #{project_id})
+ #{target_types_sql}
+ )
+ ),
+ SQL
+ end
+
+ def as_deleted_sql
+ <<-SQL
+ deleted AS (
+ DELETE FROM todos
+ WHERE id IN (
+ SELECT id
+ FROM all_todos
+ LIMIT 5000
+ )
+ RETURNING id
+ )
+ SQL
+ end
end
end
end
diff --git a/lib/gitlab/background_migration/set_confidential_note_events_on_services.rb b/lib/gitlab/background_migration/set_confidential_note_events_on_services.rb
index e5e8837221e..bc434b0cb64 100644
--- a/lib/gitlab/background_migration/set_confidential_note_events_on_services.rb
+++ b/lib/gitlab/background_migration/set_confidential_note_events_on_services.rb
@@ -3,8 +3,8 @@
module Gitlab
module BackgroundMigration
- # Ensures services which previously recieved all notes events continue
- # to recieve confidential ones.
+ # Ensures services which previously received all notes events continue
+ # to receive confidential ones.
class SetConfidentialNoteEventsOnServices
class Service < ActiveRecord::Base
self.table_name = 'services'
diff --git a/lib/gitlab/background_migration/set_confidential_note_events_on_webhooks.rb b/lib/gitlab/background_migration/set_confidential_note_events_on_webhooks.rb
index 171c8ef21b7..28d8d2c640b 100644
--- a/lib/gitlab/background_migration/set_confidential_note_events_on_webhooks.rb
+++ b/lib/gitlab/background_migration/set_confidential_note_events_on_webhooks.rb
@@ -3,8 +3,8 @@
module Gitlab
module BackgroundMigration
- # Ensures hooks which previously recieved all notes events continue
- # to recieve confidential ones.
+ # Ensures hooks which previously received all notes events continue
+ # to receive confidential ones.
class SetConfidentialNoteEventsOnWebhooks
class WebHook < ActiveRecord::Base
self.table_name = 'web_hooks'
diff --git a/lib/gitlab/badge/base.rb b/lib/gitlab/badge/base.rb
index 909fa24fa90..fb55b9e2f1f 100644
--- a/lib/gitlab/badge/base.rb
+++ b/lib/gitlab/badge/base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
class Base
diff --git a/lib/gitlab/badge/coverage/metadata.rb b/lib/gitlab/badge/coverage/metadata.rb
index e898f5d790e..9181ba2d4b0 100644
--- a/lib/gitlab/badge/coverage/metadata.rb
+++ b/lib/gitlab/badge/coverage/metadata.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
module Coverage
diff --git a/lib/gitlab/badge/coverage/report.rb b/lib/gitlab/badge/coverage/report.rb
index 16fd6f01495..a7fcb6b0fca 100644
--- a/lib/gitlab/badge/coverage/report.rb
+++ b/lib/gitlab/badge/coverage/report.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
module Coverage
diff --git a/lib/gitlab/badge/coverage/template.rb b/lib/gitlab/badge/coverage/template.rb
index afbf9dd17e3..817dc28f84a 100644
--- a/lib/gitlab/badge/coverage/template.rb
+++ b/lib/gitlab/badge/coverage/template.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
module Coverage
diff --git a/lib/gitlab/badge/metadata.rb b/lib/gitlab/badge/metadata.rb
index 8ad6f3cb986..b9ae68134b0 100644
--- a/lib/gitlab/badge/metadata.rb
+++ b/lib/gitlab/badge/metadata.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
##
diff --git a/lib/gitlab/badge/pipeline/metadata.rb b/lib/gitlab/badge/pipeline/metadata.rb
index db1e9f8cfb8..d4d789558c9 100644
--- a/lib/gitlab/badge/pipeline/metadata.rb
+++ b/lib/gitlab/badge/pipeline/metadata.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
module Pipeline
diff --git a/lib/gitlab/badge/pipeline/status.rb b/lib/gitlab/badge/pipeline/status.rb
index d1d9b7949f5..37e61f07e5b 100644
--- a/lib/gitlab/badge/pipeline/status.rb
+++ b/lib/gitlab/badge/pipeline/status.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
module Pipeline
diff --git a/lib/gitlab/badge/pipeline/template.rb b/lib/gitlab/badge/pipeline/template.rb
index e09db32262d..64c3dfcd10b 100644
--- a/lib/gitlab/badge/pipeline/template.rb
+++ b/lib/gitlab/badge/pipeline/template.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
module Pipeline
diff --git a/lib/gitlab/badge/template.rb b/lib/gitlab/badge/template.rb
index bfeb0052642..ed2ec50b197 100644
--- a/lib/gitlab/badge/template.rb
+++ b/lib/gitlab/badge/template.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Badge
##
diff --git a/lib/gitlab/bare_repository_import/importer.rb b/lib/gitlab/bare_repository_import/importer.rb
index 04aa6aab771..3cd327f5109 100644
--- a/lib/gitlab/bare_repository_import/importer.rb
+++ b/lib/gitlab/bare_repository_import/importer.rb
@@ -1,10 +1,15 @@
+# frozen_string_literal: true
+
module Gitlab
module BareRepositoryImport
class Importer
NoAdminError = Class.new(StandardError)
def self.execute(import_path)
- import_path << '/' unless import_path.ends_with?('/')
+ unless import_path.ends_with?('/')
+ import_path = "#{import_path}/"
+ end
+
repos_to_import = Dir.glob(import_path + '**/*.git')
unless user = User.admins.order_id_asc.first
diff --git a/lib/gitlab/bare_repository_import/repository.rb b/lib/gitlab/bare_repository_import/repository.rb
index c0c666dfb7b..b903c581aac 100644
--- a/lib/gitlab/bare_repository_import/repository.rb
+++ b/lib/gitlab/bare_repository_import/repository.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module BareRepositoryImport
class Repository
@@ -6,9 +8,12 @@ module Gitlab
attr_reader :group_path, :project_name, :repo_path
def initialize(root_path, repo_path)
+ unless root_path.ends_with?('/')
+ root_path = "#{root_path}/"
+ end
+
@root_path = root_path
@repo_path = repo_path
- @root_path << '/' unless root_path.ends_with?('/')
full_path =
if hashed? && !wiki?
diff --git a/lib/gitlab/base_doorkeeper_controller.rb b/lib/gitlab/base_doorkeeper_controller.rb
index e4227af25d2..b78993aba30 100644
--- a/lib/gitlab/base_doorkeeper_controller.rb
+++ b/lib/gitlab/base_doorkeeper_controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This is a base controller for doorkeeper.
# It adds the `can?` helper used in the views.
module Gitlab
diff --git a/lib/gitlab/bitbucket_import/importer.rb b/lib/gitlab/bitbucket_import/importer.rb
index a7dfccea2f6..eaead41a720 100644
--- a/lib/gitlab/bitbucket_import/importer.rb
+++ b/lib/gitlab/bitbucket_import/importer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module BitbucketImport
class Importer
@@ -33,7 +35,7 @@ module Gitlab
def handle_errors
return unless errors.any?
- project.update_column(:import_error, {
+ project.import_state.update_column(:last_error, {
message: 'The remote data could not be fully imported.',
errors: errors
}.to_json)
diff --git a/lib/gitlab/bitbucket_import/project_creator.rb b/lib/gitlab/bitbucket_import/project_creator.rb
index d94f70fd1fb..11070a68e02 100644
--- a/lib/gitlab/bitbucket_import/project_creator.rb
+++ b/lib/gitlab/bitbucket_import/project_creator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module BitbucketImport
class ProjectCreator
diff --git a/lib/gitlab/bitbucket_server_import/importer.rb b/lib/gitlab/bitbucket_server_import/importer.rb
index 15aa4739ee9..d4080536d81 100644
--- a/lib/gitlab/bitbucket_server_import/importer.rb
+++ b/lib/gitlab/bitbucket_server_import/importer.rb
@@ -56,7 +56,7 @@ module Gitlab
def handle_errors
return unless errors.any?
- project.update_column(:import_error, {
+ project.import_state.update_column(:last_error, {
message: 'The remote data could not be fully imported.',
errors: errors
}.to_json)
diff --git a/lib/gitlab/bitbucket_server_import/project_creator.rb b/lib/gitlab/bitbucket_server_import/project_creator.rb
index 35e8cd7e0ab..48ca4951957 100644
--- a/lib/gitlab/bitbucket_server_import/project_creator.rb
+++ b/lib/gitlab/bitbucket_server_import/project_creator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module BitbucketServerImport
class ProjectCreator
diff --git a/lib/gitlab/blame.rb b/lib/gitlab/blame.rb
index 169aac79854..f1a653a9d95 100644
--- a/lib/gitlab/blame.rb
+++ b/lib/gitlab/blame.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class Blame
attr_accessor :blob, :commit
@@ -41,8 +43,7 @@ module Gitlab
def highlighted_lines
@blob.load_all_data!
- @highlighted_lines ||=
- Gitlab::Highlight.highlight(@blob.path, @blob.data, repository: repository).lines
+ @highlighted_lines ||= @blob.present.highlight.lines
end
def project
diff --git a/lib/gitlab/blob_helper.rb b/lib/gitlab/blob_helper.rb
new file mode 100644
index 00000000000..488c1d85387
--- /dev/null
+++ b/lib/gitlab/blob_helper.rb
@@ -0,0 +1,147 @@
+# frozen_string_literal: true
+
+# This has been extracted from https://github.com/github/linguist/blob/master/lib/linguist/blob_helper.rb
+module Gitlab
+ module BlobHelper
+ def extname
+ File.extname(name.to_s)
+ end
+
+ def known_extension?
+ LanguageData.extensions.include?(extname)
+ end
+
+ def viewable?
+ !large? && text?
+ end
+
+ MEGABYTE = 1024 * 1024
+
+ def large?
+ size.to_i > MEGABYTE
+ end
+
+ def binary?
+ # Large blobs aren't even loaded into memory
+ if data.nil?
+ true
+
+ # Treat blank files as text
+ elsif data == ""
+ false
+
+ # Charlock doesn't know what to think
+ elsif encoding.nil?
+ true
+
+ # If Charlock says its binary
+ else
+ detect_encoding[:type] == :binary
+ end
+ end
+
+ def text?
+ !binary?
+ end
+
+ def image?
+ ['.png', '.jpg', '.jpeg', '.gif'].include?(extname.downcase)
+ end
+
+ # Internal: Lookup mime type for extension.
+ #
+ # Returns a MIME::Type
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ def _mime_type
+ if defined? @_mime_type
+ @_mime_type
+ else
+ guesses = ::MIME::Types.type_for(extname.to_s)
+
+ # Prefer text mime types over binary
+ @_mime_type = guesses.detect { |type| type.ascii? } || guesses.first
+ end
+ end
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
+
+ # Public: Get the actual blob mime type
+ #
+ # Examples
+ #
+ # # => 'text/plain'
+ # # => 'text/html'
+ #
+ # Returns a mime type String.
+ def mime_type
+ _mime_type ? _mime_type.to_s : 'text/plain'
+ end
+
+ def binary_mime_type?
+ _mime_type ? _mime_type.binary? : false
+ end
+
+ def lines
+ @lines ||=
+ if viewable? && data
+ # `data` is usually encoded as ASCII-8BIT even when the content has
+ # been detected as a different encoding. However, we are not allowed
+ # to change the encoding of `data` because we've made the implicit
+ # guarantee that each entry in `lines` is encoded the same way as
+ # `data`.
+ #
+ # Instead, we re-encode each possible newline sequence as the
+ # detected encoding, then force them back to the encoding of `data`
+ # (usually a binary encoding like ASCII-8BIT). This means that the
+ # byte sequence will match how newlines are likely encoded in the
+ # file, but we don't have to change the encoding of `data` as far as
+ # Ruby is concerned. This allows us to correctly parse out each line
+ # without changing the encoding of `data`, and
+ # also--importantly--without having to duplicate many (potentially
+ # large) strings.
+ begin
+ data.split(encoded_newlines_re, -1)
+ rescue Encoding::ConverterNotFoundError
+ # The data is not splittable in the detected encoding. Assume it's
+ # one big line.
+ [data]
+ end
+ else
+ []
+ end
+ end
+
+ def content_type
+ # rubocop:disable Style/MultilineTernaryOperator
+ # rubocop:disable Style/NestedTernaryOperator
+ @content_type ||= binary_mime_type? || binary? ? mime_type :
+ (encoding ? "text/plain; charset=#{encoding.downcase}" : "text/plain")
+ # rubocop:enable Style/NestedTernaryOperator
+ # rubocop:enable Style/MultilineTernaryOperator
+ end
+
+ def encoded_newlines_re
+ @encoded_newlines_re ||=
+ Regexp.union(["\r\n", "\r", "\n"].map { |nl| nl.encode(ruby_encoding, "ASCII-8BIT").force_encoding(data.encoding) })
+ end
+
+ def ruby_encoding
+ if hash = detect_encoding
+ hash[:ruby_encoding]
+ end
+ end
+
+ def encoding
+ if hash = detect_encoding
+ hash[:encoding]
+ end
+ end
+
+ def detect_encoding
+ @detect_encoding ||= CharlockHolmes::EncodingDetector.new.detect(data) if data # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ end
+
+ def empty?
+ data.nil? || data == ""
+ end
+ end
+end
diff --git a/lib/gitlab/build_access.rb b/lib/gitlab/build_access.rb
index 08a8f846ca5..37e79413541 100644
--- a/lib/gitlab/build_access.rb
+++ b/lib/gitlab/build_access.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class BuildAccess < UserAccess
attr_accessor :user, :project
diff --git a/lib/gitlab/cache/ci/project_pipeline_status.rb b/lib/gitlab/cache/ci/project_pipeline_status.rb
index add048d671e..ea7013db2ce 100644
--- a/lib/gitlab/cache/ci/project_pipeline_status.rb
+++ b/lib/gitlab/cache/ci/project_pipeline_status.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This class is not backed by a table in the main database.
# It loads the latest Pipeline for the HEAD of a repository, and caches that
# in Redis.
@@ -5,9 +7,9 @@ module Gitlab
module Cache
module Ci
class ProjectPipelineStatus
- attr_accessor :sha, :status, :ref, :project, :loaded
+ include Gitlab::Utils::StrongMemoize
- delegate :commit, to: :project
+ attr_accessor :sha, :status, :ref, :project, :loaded
def self.load_for_project(project)
new(project).tap do |status|
@@ -16,33 +18,12 @@ module Gitlab
end
def self.load_in_batch_for_projects(projects)
- cached_results_for_projects(projects).zip(projects).each do |result, project|
- project.pipeline_status = new(project, result)
+ projects.each do |project|
+ project.pipeline_status = new(project)
project.pipeline_status.load_status
end
end
- def self.cached_results_for_projects(projects)
- result = Gitlab::Redis::Cache.with do |redis|
- redis.multi do
- projects.each do |project|
- cache_key = cache_key_for_project(project)
- redis.exists(cache_key)
- redis.hmget(cache_key, :sha, :status, :ref)
- end
- end
- end
-
- result.each_slice(2).map do |(cache_key_exists, (sha, status, ref))|
- pipeline_info = { sha: sha, status: status, ref: ref }
- { loaded_from_cache: cache_key_exists, pipeline_info: pipeline_info }
- end
- end
-
- def self.cache_key_for_project(project)
- "#{Gitlab::Redis::Cache::CACHE_NAMESPACE}:projects/#{project.id}/pipeline_status"
- end
-
def self.update_for_pipeline(pipeline)
pipeline_info = {
sha: pipeline.sha,
@@ -68,6 +49,7 @@ module Gitlab
def load_status
return if loaded?
+ return unless commit
if has_cache?
load_from_cache
@@ -80,11 +62,7 @@ module Gitlab
end
def load_from_project
- return unless commit
-
- self.sha = commit.sha
- self.status = commit.status
- self.ref = project.default_branch
+ self.sha, self.status, self.ref = commit.sha, commit.status, project.default_branch
end
# We only cache the status for the HEAD commit of a project
@@ -102,6 +80,8 @@ module Gitlab
def load_from_cache
Gitlab::Redis::Cache.with do |redis|
self.sha, self.status, self.ref = redis.hmget(cache_key, :sha, :status, :ref)
+
+ self.status = nil if self.status.empty?
end
end
@@ -130,7 +110,13 @@ module Gitlab
end
def cache_key
- self.class.cache_key_for_project(project)
+ "#{Gitlab::Redis::Cache::CACHE_NAMESPACE}:project:#{project.id}:pipeline_status:#{commit&.sha}"
+ end
+
+ def commit
+ strong_memoize(:commit) do
+ project.commit
+ end
end
end
end
diff --git a/lib/gitlab/cache/request_cache.rb b/lib/gitlab/cache/request_cache.rb
index 671b8e7e1b1..4c658dc0b8d 100644
--- a/lib/gitlab/cache/request_cache.rb
+++ b/lib/gitlab/cache/request_cache.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Cache
# See https://docs.gitlab.com/ee/development/utilities.html#requestcache
@@ -26,8 +28,8 @@ module Gitlab
define_method(method_name) do |*args|
store =
- if RequestStore.active?
- RequestStore.store
+ if Gitlab::SafeRequestStore.active?
+ Gitlab::SafeRequestStore.store
else
ivar_name = # ! and ? cannot be used as ivar name
"@cache_#{method_name.to_s.tr('!?', "\u2605\u2606")}"
diff --git a/lib/gitlab/changes_list.rb b/lib/gitlab/changes_list.rb
index 9c9e6668e6f..fb75a78a978 100644
--- a/lib/gitlab/changes_list.rb
+++ b/lib/gitlab/changes_list.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class ChangesList
include Enumerable
diff --git a/lib/gitlab/chat_name_token.rb b/lib/gitlab/chat_name_token.rb
index e63e5437331..8b3c5dc9e8b 100644
--- a/lib/gitlab/chat_name_token.rb
+++ b/lib/gitlab/chat_name_token.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'json'
module Gitlab
diff --git a/lib/gitlab/checks/base_checker.rb b/lib/gitlab/checks/base_checker.rb
new file mode 100644
index 00000000000..f8cda0382fe
--- /dev/null
+++ b/lib/gitlab/checks/base_checker.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Checks
+ class BaseChecker
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :change_access
+ delegate(*ChangeAccess::ATTRIBUTES, to: :change_access)
+
+ def initialize(change_access)
+ @change_access = change_access
+ end
+
+ def validate!
+ raise NotImplementedError
+ end
+
+ private
+
+ def deletion?
+ Gitlab::Git.blank_ref?(newrev)
+ end
+
+ def update?
+ !Gitlab::Git.blank_ref?(oldrev) && !deletion?
+ end
+
+ def updated_from_web?
+ protocol == 'web'
+ end
+
+ def tag_exists?
+ project.repository.tag_exists?(tag_name)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/checks/branch_check.rb b/lib/gitlab/checks/branch_check.rb
new file mode 100644
index 00000000000..d06b2df36f2
--- /dev/null
+++ b/lib/gitlab/checks/branch_check.rb
@@ -0,0 +1,110 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Checks
+ class BranchCheck < BaseChecker
+ ERROR_MESSAGES = {
+ delete_default_branch: 'The default branch of a project cannot be deleted.',
+ force_push_protected_branch: 'You are not allowed to force push code to a protected branch on this project.',
+ non_master_delete_protected_branch: 'You are not allowed to delete protected branches from this project. Only a project maintainer or owner can delete a protected branch.',
+ non_web_delete_protected_branch: 'You can only delete protected branches using the web interface.',
+ merge_protected_branch: 'You are not allowed to merge code into protected branches on this project.',
+ push_protected_branch: 'You are not allowed to push code to protected branches on this project.'
+ }.freeze
+
+ LOG_MESSAGES = {
+ delete_default_branch_check: "Checking if default branch is being deleted...",
+ protected_branch_checks: "Checking if you are force pushing to a protected branch...",
+ protected_branch_push_checks: "Checking if you are allowed to push to the protected branch...",
+ protected_branch_deletion_checks: "Checking if you are allowed to delete the protected branch..."
+ }.freeze
+
+ def validate!
+ return unless branch_name
+
+ logger.log_timed(LOG_MESSAGES[:delete_default_branch_check]) do
+ if deletion? && branch_name == project.default_branch
+ raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:delete_default_branch]
+ end
+ end
+
+ protected_branch_checks
+ end
+
+ private
+
+ def protected_branch_checks
+ logger.log_timed(LOG_MESSAGES[:protected_branch_checks]) do
+ return unless ProtectedBranch.protected?(project, branch_name) # rubocop:disable Cop/AvoidReturnFromBlocks
+
+ if forced_push?
+ raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:force_push_protected_branch]
+ end
+ end
+
+ if deletion?
+ protected_branch_deletion_checks
+ else
+ protected_branch_push_checks
+ end
+ end
+
+ def protected_branch_deletion_checks
+ logger.log_timed(LOG_MESSAGES[:protected_branch_deletion_checks]) do
+ unless user_access.can_delete_branch?(branch_name)
+ raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:non_master_delete_protected_branch]
+ end
+
+ unless updated_from_web?
+ raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:non_web_delete_protected_branch]
+ end
+ end
+ end
+
+ def protected_branch_push_checks
+ logger.log_timed(LOG_MESSAGES[:protected_branch_push_checks]) do
+ if matching_merge_request?
+ unless user_access.can_merge_to_branch?(branch_name) || user_access.can_push_to_branch?(branch_name)
+ raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:merge_protected_branch]
+ end
+ else
+ unless user_access.can_push_to_branch?(branch_name)
+ raise GitAccess::UnauthorizedError, push_to_protected_branch_rejected_message
+ end
+ end
+ end
+ end
+
+ def push_to_protected_branch_rejected_message
+ if project.empty_repo?
+ empty_project_push_message
+ else
+ ERROR_MESSAGES[:push_protected_branch]
+ end
+ end
+
+ def empty_project_push_message
+ <<~MESSAGE
+
+ A default branch (e.g. master) does not yet exist for #{project.full_path}
+ Ask a project Owner or Maintainer to create a default branch:
+
+ #{project_members_url}
+
+ MESSAGE
+ end
+
+ def project_members_url
+ Gitlab::Routing.url_helpers.project_project_members_url(project)
+ end
+
+ def matching_merge_request?
+ Checks::MatchingMergeRequest.new(newrev, branch_name, project).match?
+ end
+
+ def forced_push?
+ Gitlab::Checks::ForcePush.force_push?(project, oldrev, newrev)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/checks/change_access.rb b/lib/gitlab/checks/change_access.rb
index 7a4224e5bbe..7778d3068cc 100644
--- a/lib/gitlab/checks/change_access.rb
+++ b/lib/gitlab/checks/change_access.rb
@@ -1,26 +1,17 @@
+# frozen_string_literal: true
+
module Gitlab
module Checks
class ChangeAccess
- ERROR_MESSAGES = {
- push_code: 'You are not allowed to push code to this project.',
- delete_default_branch: 'The default branch of a project cannot be deleted.',
- force_push_protected_branch: 'You are not allowed to force push code to a protected branch on this project.',
- non_master_delete_protected_branch: 'You are not allowed to delete protected branches from this project. Only a project maintainer or owner can delete a protected branch.',
- non_web_delete_protected_branch: 'You can only delete protected branches using the web interface.',
- merge_protected_branch: 'You are not allowed to merge code into protected branches on this project.',
- push_protected_branch: 'You are not allowed to push code to protected branches on this project.',
- change_existing_tags: 'You are not allowed to change existing tags on this project.',
- update_protected_tag: 'Protected tags cannot be updated.',
- delete_protected_tag: 'Protected tags cannot be deleted.',
- create_protected_tag: 'You are not allowed to create this tag as it is protected.',
- lfs_objects_missing: 'LFS objects are missing. Ensure LFS is properly set up or try a manual "git lfs push --all".'
- }.freeze
+ ATTRIBUTES = %i[user_access project skip_authorization
+ skip_lfs_integrity_check protocol oldrev newrev ref
+ branch_name tag_name logger commits].freeze
- attr_reader :user_access, :project, :skip_authorization, :skip_lfs_integrity_check, :protocol, :oldrev, :newrev, :ref, :branch_name, :tag_name
+ attr_reader(*ATTRIBUTES)
def initialize(
change, user_access:, project:, skip_authorization: false,
- skip_lfs_integrity_check: false, protocol:
+ skip_lfs_integrity_check: false, protocol:, logger:
)
@oldrev, @newrev, @ref = change.values_at(:oldrev, :newrev, :ref)
@branch_name = Gitlab::Git.branch_name(@ref)
@@ -30,186 +21,37 @@ module Gitlab
@skip_authorization = skip_authorization
@skip_lfs_integrity_check = skip_lfs_integrity_check
@protocol = protocol
+
+ @logger = logger
+ @logger.append_message("Running checks for ref: #{@branch_name || @tag_name}")
end
- def exec(skip_commits_check: false)
+ def exec
return true if skip_authorization
- push_checks
- branch_checks
- tag_checks
- lfs_objects_exist_check unless skip_lfs_integrity_check
- commits_check unless skip_commits_check
+ ref_level_checks
+ # Check of commits should happen as the last step
+ # given they're expensive in terms of performance
+ commits_check
true
end
- protected
-
- def push_checks
- unless can_push?
- raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:push_code]
- end
- end
-
- def branch_checks
- return unless branch_name
-
- if deletion? && branch_name == project.default_branch
- raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:delete_default_branch]
- end
-
- protected_branch_checks
- end
-
- def protected_branch_checks
- return unless ProtectedBranch.protected?(project, branch_name)
-
- if forced_push?
- raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:force_push_protected_branch]
- end
-
- if deletion?
- protected_branch_deletion_checks
- else
- protected_branch_push_checks
- end
- end
-
- def protected_branch_deletion_checks
- unless user_access.can_delete_branch?(branch_name)
- raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:non_master_delete_protected_branch]
- end
-
- unless updated_from_web?
- raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:non_web_delete_protected_branch]
- end
- end
-
- def protected_branch_push_checks
- if matching_merge_request?
- unless user_access.can_merge_to_branch?(branch_name) || user_access.can_push_to_branch?(branch_name)
- raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:merge_protected_branch]
- end
- else
- unless user_access.can_push_to_branch?(branch_name)
- raise GitAccess::UnauthorizedError, push_to_protected_branch_rejected_message
- end
- end
- end
-
- def tag_checks
- return unless tag_name
-
- if tag_exists? && user_access.cannot_do_action?(:admin_project)
- raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:change_existing_tags]
- end
-
- protected_tag_checks
+ def commits
+ @commits ||= project.repository.new_commits(newrev)
end
- def protected_tag_checks
- return unless ProtectedTag.protected?(project, tag_name)
-
- raise(GitAccess::UnauthorizedError, ERROR_MESSAGES[:update_protected_tag]) if update?
- raise(GitAccess::UnauthorizedError, ERROR_MESSAGES[:delete_protected_tag]) if deletion?
+ protected
- unless user_access.can_create_tag?(tag_name)
- raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:create_protected_tag]
- end
+ def ref_level_checks
+ Gitlab::Checks::PushCheck.new(self).validate!
+ Gitlab::Checks::BranchCheck.new(self).validate!
+ Gitlab::Checks::TagCheck.new(self).validate!
+ Gitlab::Checks::LfsCheck.new(self).validate!
end
def commits_check
- return if deletion? || newrev.nil?
- return unless should_run_commit_validations?
-
- # n+1: https://gitlab.com/gitlab-org/gitlab-ee/issues/3593
- ::Gitlab::GitalyClient.allow_n_plus_1_calls do
- commits.each do |commit|
- commit_check.validate(commit, validations_for_commit(commit))
- end
- end
-
- commit_check.validate_file_paths
- end
-
- # Method overwritten in EE to inject custom validations
- def validations_for_commit(_)
- []
- end
-
- private
-
- def push_to_protected_branch_rejected_message
- if project.empty_repo?
- empty_project_push_message
- else
- ERROR_MESSAGES[:push_protected_branch]
- end
- end
-
- def empty_project_push_message
- <<~MESSAGE
-
- A default branch (e.g. master) does not yet exist for #{project.full_path}
- Ask a project Owner or Maintainer to create a default branch:
-
- #{project_members_url}
-
- MESSAGE
- end
-
- def project_members_url
- Gitlab::Routing.url_helpers.project_project_members_url(project)
- end
-
- def should_run_commit_validations?
- commit_check.validate_lfs_file_locks?
- end
-
- def updated_from_web?
- protocol == 'web'
- end
-
- def tag_exists?
- project.repository.tag_exists?(tag_name)
- end
-
- def forced_push?
- Gitlab::Checks::ForcePush.force_push?(project, oldrev, newrev)
- end
-
- def update?
- !Gitlab::Git.blank_ref?(oldrev) && !deletion?
- end
-
- def deletion?
- Gitlab::Git.blank_ref?(newrev)
- end
-
- def matching_merge_request?
- Checks::MatchingMergeRequest.new(newrev, branch_name, project).match?
- end
-
- def lfs_objects_exist_check
- lfs_check = Checks::LfsIntegrity.new(project, newrev)
-
- if lfs_check.objects_missing?
- raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:lfs_objects_missing]
- end
- end
-
- def commit_check
- @commit_check ||= Gitlab::Checks::CommitCheck.new(project, user_access.user, newrev, oldrev)
- end
-
- def commits
- @commits ||= project.repository.new_commits(newrev)
- end
-
- def can_push?
- user_access.can_do_action?(:push_code) ||
- user_access.can_push_to_branch?(branch_name)
+ Gitlab::Checks::DiffCheck.new(self).validate!
end
end
end
diff --git a/lib/gitlab/checks/commit_check.rb b/lib/gitlab/checks/commit_check.rb
deleted file mode 100644
index 7e0c34aada3..00000000000
--- a/lib/gitlab/checks/commit_check.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-module Gitlab
- module Checks
- class CommitCheck
- include Gitlab::Utils::StrongMemoize
-
- attr_reader :project, :user, :newrev, :oldrev
-
- def initialize(project, user, newrev, oldrev)
- @project = project
- @user = user
- @newrev = user
- @oldrev = user
- @file_paths = []
- end
-
- def validate(commit, validations)
- return if validations.empty? && path_validations.empty?
-
- commit.raw_deltas.each do |diff|
- @file_paths << (diff.new_path || diff.old_path)
-
- validations.each do |validation|
- if error = validation.call(diff)
- raise ::Gitlab::GitAccess::UnauthorizedError, error
- end
- end
- end
- end
-
- def validate_file_paths
- path_validations.each do |validation|
- if error = validation.call(@file_paths)
- raise ::Gitlab::GitAccess::UnauthorizedError, error
- end
- end
- end
-
- def validate_lfs_file_locks?
- strong_memoize(:validate_lfs_file_locks) do
- project.lfs_enabled? && newrev && oldrev && project.any_lfs_file_locks?
- end
- end
-
- private
-
- # rubocop: disable CodeReuse/ActiveRecord
- def lfs_file_locks_validation
- lambda do |paths|
- lfs_lock = project.lfs_file_locks.where(path: paths).where.not(user_id: user.id).first
-
- if lfs_lock
- return "The path '#{lfs_lock.path}' is locked in Git LFS by #{lfs_lock.user.name}"
- end
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def path_validations
- validate_lfs_file_locks? ? [lfs_file_locks_validation] : []
- end
- end
- end
-end
diff --git a/lib/gitlab/checks/diff_check.rb b/lib/gitlab/checks/diff_check.rb
new file mode 100644
index 00000000000..49d361fcef7
--- /dev/null
+++ b/lib/gitlab/checks/diff_check.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Checks
+ class DiffCheck < BaseChecker
+ include Gitlab::Utils::StrongMemoize
+
+ LOG_MESSAGES = {
+ validate_file_paths: "Validating diffs' file paths...",
+ diff_content_check: "Validating diff contents..."
+ }.freeze
+
+ def validate!
+ return unless should_run_diff_validations?
+ return if commits.empty?
+ return unless uses_raw_delta_validations?
+
+ file_paths = []
+ process_raw_deltas do |diff|
+ file_paths << (diff.new_path || diff.old_path)
+
+ validate_diff(diff)
+ end
+
+ validate_file_paths(file_paths)
+ end
+
+ private
+
+ def should_run_diff_validations?
+ newrev && oldrev && !deletion? && validate_lfs_file_locks?
+ end
+
+ def validate_lfs_file_locks?
+ strong_memoize(:validate_lfs_file_locks) do
+ project.lfs_enabled? && project.any_lfs_file_locks?
+ end
+ end
+
+ def uses_raw_delta_validations?
+ validations_for_diff.present? || path_validations.present?
+ end
+
+ def validate_diff(diff)
+ validations_for_diff.each do |validation|
+ if error = validation.call(diff)
+ raise ::Gitlab::GitAccess::UnauthorizedError, error
+ end
+ end
+ end
+
+ # Method overwritten in EE to inject custom validations
+ def validations_for_diff
+ []
+ end
+
+ def path_validations
+ validate_lfs_file_locks? ? [lfs_file_locks_validation] : []
+ end
+
+ def process_raw_deltas
+ logger.log_timed(LOG_MESSAGES[:diff_content_check]) do
+ # n+1: https://gitlab.com/gitlab-org/gitlab-ee/issues/3593
+ ::Gitlab::GitalyClient.allow_n_plus_1_calls do
+ commits.each do |commit|
+ logger.check_timeout_reached
+
+ commit.raw_deltas.each do |diff|
+ yield(diff)
+ end
+ end
+ end
+ end
+ end
+
+ def validate_file_paths(file_paths)
+ logger.log_timed(LOG_MESSAGES[__method__]) do
+ path_validations.each do |validation|
+ if error = validation.call(file_paths)
+ raise ::Gitlab::GitAccess::UnauthorizedError, error
+ end
+ end
+ end
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def lfs_file_locks_validation
+ lambda do |paths|
+ lfs_lock = project.lfs_file_locks.where(path: paths).where.not(user_id: user_access.user.id).take
+
+ if lfs_lock
+ return "The path '#{lfs_lock.path}' is locked in Git LFS by #{lfs_lock.user.name}"
+ end
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+ end
+end
diff --git a/lib/gitlab/checks/force_push.rb b/lib/gitlab/checks/force_push.rb
index 87af4a90572..263972923ed 100644
--- a/lib/gitlab/checks/force_push.rb
+++ b/lib/gitlab/checks/force_push.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Checks
class ForcePush
diff --git a/lib/gitlab/checks/lfs_check.rb b/lib/gitlab/checks/lfs_check.rb
new file mode 100644
index 00000000000..e42684e679a
--- /dev/null
+++ b/lib/gitlab/checks/lfs_check.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Checks
+ class LfsCheck < BaseChecker
+ LOG_MESSAGE = "Scanning repository for blobs stored in LFS and verifying their files have been uploaded to GitLab...".freeze
+ ERROR_MESSAGE = 'LFS objects are missing. Ensure LFS is properly set up or try a manual "git lfs push --all".'.freeze
+
+ def validate!
+ return if skip_lfs_integrity_check
+
+ logger.log_timed(LOG_MESSAGE) do
+ lfs_check = Checks::LfsIntegrity.new(project, newrev, logger.time_left)
+
+ if lfs_check.objects_missing?
+ raise GitAccess::UnauthorizedError, ERROR_MESSAGE
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/checks/lfs_integrity.rb b/lib/gitlab/checks/lfs_integrity.rb
index 3f7adecc621..1652d5a30a4 100644
--- a/lib/gitlab/checks/lfs_integrity.rb
+++ b/lib/gitlab/checks/lfs_integrity.rb
@@ -1,9 +1,12 @@
+# frozen_string_literal: true
+
module Gitlab
module Checks
class LfsIntegrity
- def initialize(project, newrev)
+ def initialize(project, newrev, time_left)
@project = project
@newrev = newrev
+ @time_left = time_left
end
# rubocop: disable CodeReuse/ActiveRecord
@@ -11,7 +14,7 @@ module Gitlab
return false unless @newrev && @project.lfs_enabled?
new_lfs_pointers = Gitlab::Git::LfsChanges.new(@project.repository, @newrev)
- .new_pointers(object_limit: ::Gitlab::Git::Repository::REV_LIST_COMMIT_LIMIT)
+ .new_pointers(object_limit: ::Gitlab::Git::Repository::REV_LIST_COMMIT_LIMIT, dynamic_timeout: @time_left)
return false unless new_lfs_pointers.present?
diff --git a/lib/gitlab/checks/matching_merge_request.rb b/lib/gitlab/checks/matching_merge_request.rb
index 86f4aaeb4d3..71361b12d07 100644
--- a/lib/gitlab/checks/matching_merge_request.rb
+++ b/lib/gitlab/checks/matching_merge_request.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Checks
class MatchingMergeRequest
diff --git a/lib/gitlab/checks/post_push_message.rb b/lib/gitlab/checks/post_push_message.rb
index 473c0385b34..492dbb5a596 100644
--- a/lib/gitlab/checks/post_push_message.rb
+++ b/lib/gitlab/checks/post_push_message.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Checks
class PostPushMessage
diff --git a/lib/gitlab/checks/project_created.rb b/lib/gitlab/checks/project_created.rb
index cec270d6a58..0058a402a62 100644
--- a/lib/gitlab/checks/project_created.rb
+++ b/lib/gitlab/checks/project_created.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Checks
class ProjectCreated < PostPushMessage
diff --git a/lib/gitlab/checks/project_moved.rb b/lib/gitlab/checks/project_moved.rb
index 3a197078d08..cb3b7acaaad 100644
--- a/lib/gitlab/checks/project_moved.rb
+++ b/lib/gitlab/checks/project_moved.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Checks
class ProjectMoved < PostPushMessage
diff --git a/lib/gitlab/checks/push_check.rb b/lib/gitlab/checks/push_check.rb
new file mode 100644
index 00000000000..f3a52f09868
--- /dev/null
+++ b/lib/gitlab/checks/push_check.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Checks
+ class PushCheck < BaseChecker
+ def validate!
+ logger.log_timed("Checking if you are allowed to push...") do
+ unless can_push?
+ raise GitAccess::UnauthorizedError, 'You are not allowed to push code to this project.'
+ end
+ end
+ end
+
+ private
+
+ def can_push?
+ user_access.can_do_action?(:push_code) ||
+ user_access.can_push_to_branch?(branch_name)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/checks/tag_check.rb b/lib/gitlab/checks/tag_check.rb
new file mode 100644
index 00000000000..2a75c8059bd
--- /dev/null
+++ b/lib/gitlab/checks/tag_check.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Checks
+ class TagCheck < BaseChecker
+ ERROR_MESSAGES = {
+ change_existing_tags: 'You are not allowed to change existing tags on this project.',
+ update_protected_tag: 'Protected tags cannot be updated.',
+ delete_protected_tag: 'Protected tags cannot be deleted.',
+ create_protected_tag: 'You are not allowed to create this tag as it is protected.'
+ }.freeze
+
+ LOG_MESSAGES = {
+ tag_checks: "Checking if you are allowed to change existing tags...",
+ protected_tag_checks: "Checking if you are creating, updating or deleting a protected tag..."
+ }.freeze
+
+ def validate!
+ return unless tag_name
+
+ logger.log_timed(LOG_MESSAGES[:tag_checks]) do
+ if tag_exists? && user_access.cannot_do_action?(:admin_project)
+ raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:change_existing_tags]
+ end
+ end
+
+ protected_tag_checks
+ end
+
+ private
+
+ def protected_tag_checks
+ logger.log_timed(LOG_MESSAGES[__method__]) do
+ return unless ProtectedTag.protected?(project, tag_name) # rubocop:disable Cop/AvoidReturnFromBlocks
+
+ raise(GitAccess::UnauthorizedError, ERROR_MESSAGES[:update_protected_tag]) if update?
+ raise(GitAccess::UnauthorizedError, ERROR_MESSAGES[:delete_protected_tag]) if deletion?
+
+ unless user_access.can_create_tag?(tag_name)
+ raise GitAccess::UnauthorizedError, ERROR_MESSAGES[:create_protected_tag]
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/checks/timed_logger.rb b/lib/gitlab/checks/timed_logger.rb
new file mode 100644
index 00000000000..f365e0a43f6
--- /dev/null
+++ b/lib/gitlab/checks/timed_logger.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Checks
+ class TimedLogger
+ TimeoutError = Class.new(StandardError)
+
+ attr_reader :start_time, :header, :log, :timeout
+
+ def initialize(start_time: Time.now, log: [], header: "", timeout:)
+ @start_time = start_time
+ @timeout = timeout
+ @header = header
+ @log = log
+ end
+
+ # Adds trace of method being tracked with
+ # the correspondent time it took to run it.
+ # We make use of the start default argument
+ # on unit tests related to this method
+ #
+ def log_timed(log_message, start = Time.now)
+ check_timeout_reached
+
+ timed = true
+
+ yield
+
+ append_message(log_message + time_suffix_message(start: start))
+ rescue GRPC::DeadlineExceeded, TimeoutError
+ args = { cancelled: true }
+ args[:start] = start if timed
+
+ append_message(log_message + time_suffix_message(args))
+
+ raise TimeoutError
+ end
+
+ def check_timeout_reached
+ return unless time_expired?
+
+ raise TimeoutError
+ end
+
+ def time_left
+ (start_time + timeout.seconds) - Time.now
+ end
+
+ def full_message
+ header + log.join("\n")
+ end
+
+ # We always want to append in-place on the log
+ def append_message(message)
+ log << message
+ end
+
+ private
+
+ def time_expired?
+ time_left <= 0
+ end
+
+ def time_suffix_message(cancelled: false, start: nil)
+ return " (#{elapsed_time(start)}ms)" unless cancelled
+
+ if start
+ " (cancelled after #{elapsed_time(start)}ms)"
+ else
+ " (cancelled)"
+ end
+ end
+
+ def elapsed_time(start)
+ to_ms(Time.now - start)
+ end
+
+ def to_ms(elapsed)
+ (elapsed.to_f * 1000).round(2)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/ansi2html.rb b/lib/gitlab/ci/ansi2html.rb
index e780f8c646b..974b5ad6877 100644
--- a/lib/gitlab/ci/ansi2html.rb
+++ b/lib/gitlab/ci/ansi2html.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# ANSI color library
#
# Implementation per http://en.wikipedia.org/wiki/ANSI_escape_code
@@ -265,7 +267,7 @@ module Gitlab
def reset_state
@offset = 0
@n_open_tags = 0
- @out = ''
+ @out = +''
reset
end
diff --git a/lib/gitlab/ci/build/artifacts/adapters/gzip_stream.rb b/lib/gitlab/ci/build/artifacts/adapters/gzip_stream.rb
new file mode 100644
index 00000000000..25a82086676
--- /dev/null
+++ b/lib/gitlab/ci/build/artifacts/adapters/gzip_stream.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Build
+ module Artifacts
+ module Adapters
+ class GzipStream
+ attr_reader :stream
+
+ InvalidStreamError = Class.new(StandardError)
+
+ def initialize(stream)
+ raise InvalidStreamError, "Stream is required" unless stream
+
+ @stream = stream
+ end
+
+ def each_blob
+ stream.seek(0)
+
+ until stream.eof?
+ gzip(stream) do |gz|
+ yield gz.read, gz.orig_name
+ unused = gz.unused&.length.to_i
+ # pos has already reached to EOF at the moment
+ # We rewind the pos to the top of unused files
+ # to read next gzip stream, to support multistream archives
+ # https://golang.org/src/compress/gzip/gunzip.go#L117
+ stream.seek(-unused, IO::SEEK_CUR)
+ end
+ end
+ end
+
+ private
+
+ def gzip(stream, &block)
+ gz = Zlib::GzipReader.new(stream)
+ yield(gz)
+ rescue Zlib::Error => e
+ raise InvalidStreamError, e.message
+ ensure
+ gz&.finish
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/build/artifacts/adapters/raw_stream.rb b/lib/gitlab/ci/build/artifacts/adapters/raw_stream.rb
new file mode 100644
index 00000000000..cf37d700991
--- /dev/null
+++ b/lib/gitlab/ci/build/artifacts/adapters/raw_stream.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Build
+ module Artifacts
+ module Adapters
+ class RawStream
+ attr_reader :stream
+
+ InvalidStreamError = Class.new(StandardError)
+
+ def initialize(stream)
+ raise InvalidStreamError, "Stream is required" unless stream
+
+ @stream = stream
+ end
+
+ def each_blob
+ stream.seek(0)
+
+ yield(stream.read, 'raw') unless stream.eof?
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/build/artifacts/gzip_file_adapter.rb b/lib/gitlab/ci/build/artifacts/gzip_file_adapter.rb
deleted file mode 100644
index 65f65cdce08..00000000000
--- a/lib/gitlab/ci/build/artifacts/gzip_file_adapter.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-module Gitlab
- module Ci
- module Build
- module Artifacts
- class GzipFileAdapter
- attr_reader :stream
-
- InvalidStreamError = Class.new(StandardError)
-
- def initialize(stream)
- raise InvalidStreamError, "Stream is required" unless stream
-
- @stream = stream
- end
-
- def each_blob
- stream.seek(0)
-
- until stream.eof?
- gzip(stream) do |gz|
- yield gz.read, gz.orig_name
- unused = gz.unused&.length.to_i
- # pos has already reached to EOF at the moment
- # We rewind the pos to the top of unused files
- # to read next gzip stream, to support multistream archives
- # https://golang.org/src/compress/gzip/gunzip.go#L117
- stream.seek(-unused, IO::SEEK_CUR)
- end
- end
- end
-
- private
-
- def gzip(stream, &block)
- gz = Zlib::GzipReader.new(stream)
- yield(gz)
- rescue Zlib::Error => e
- raise InvalidStreamError, e.message
- ensure
- gz&.finish
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb
index 375d8bc1ff5..08dac756cc1 100644
--- a/lib/gitlab/ci/build/artifacts/metadata.rb
+++ b/lib/gitlab/ci/build/artifacts/metadata.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'zlib'
require 'json'
@@ -59,9 +61,12 @@ module Gitlab
until gz.eof?
begin
- path = read_string(gz).force_encoding('UTF-8')
- meta = read_string(gz).force_encoding('UTF-8')
+ path = read_string(gz)&.force_encoding('UTF-8')
+ meta = read_string(gz)&.force_encoding('UTF-8')
+ # We might hit an EOF while reading either value, so we should
+ # abort if we don't get any data.
+ next unless path && meta
next unless path.valid_encoding? && meta.valid_encoding?
next unless path =~ match_pattern
next if path =~ INVALID_PATH_PATTERN
diff --git a/lib/gitlab/ci/build/artifacts/metadata/entry.rb b/lib/gitlab/ci/build/artifacts/metadata/entry.rb
index 85072a072d6..d0a80518ae8 100644
--- a/lib/gitlab/ci/build/artifacts/metadata/entry.rb
+++ b/lib/gitlab/ci/build/artifacts/metadata/entry.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Build
diff --git a/lib/gitlab/ci/build/artifacts/path.rb b/lib/gitlab/ci/build/artifacts/path.rb
index 9cd9b36c5f8..65cd935afaa 100644
--- a/lib/gitlab/ci/build/artifacts/path.rb
+++ b/lib/gitlab/ci/build/artifacts/path.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Build
diff --git a/lib/gitlab/ci/build/credentials/base.rb b/lib/gitlab/ci/build/credentials/base.rb
index 29a7a27c963..58adf6e506d 100644
--- a/lib/gitlab/ci/build/credentials/base.rb
+++ b/lib/gitlab/ci/build/credentials/base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Build
diff --git a/lib/gitlab/ci/build/credentials/factory.rb b/lib/gitlab/ci/build/credentials/factory.rb
index 2423aa8857d..fa805abb8bb 100644
--- a/lib/gitlab/ci/build/credentials/factory.rb
+++ b/lib/gitlab/ci/build/credentials/factory.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Build
diff --git a/lib/gitlab/ci/build/credentials/registry.rb b/lib/gitlab/ci/build/credentials/registry.rb
index 55eafcaed10..1c8588d9913 100644
--- a/lib/gitlab/ci/build/credentials/registry.rb
+++ b/lib/gitlab/ci/build/credentials/registry.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Build
diff --git a/lib/gitlab/ci/build/image.rb b/lib/gitlab/ci/build/image.rb
index c811f88f483..4dd932f61d4 100644
--- a/lib/gitlab/ci/build/image.rb
+++ b/lib/gitlab/ci/build/image.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Build
diff --git a/lib/gitlab/ci/build/policy.rb b/lib/gitlab/ci/build/policy.rb
index d10cc7802d4..43c46ad74af 100644
--- a/lib/gitlab/ci/build/policy.rb
+++ b/lib/gitlab/ci/build/policy.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Build
diff --git a/lib/gitlab/ci/build/policy/changes.rb b/lib/gitlab/ci/build/policy/changes.rb
new file mode 100644
index 00000000000..1663c875426
--- /dev/null
+++ b/lib/gitlab/ci/build/policy/changes.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Build
+ module Policy
+ class Changes < Policy::Specification
+ def initialize(globs)
+ @globs = Array(globs)
+ end
+
+ def satisfied_by?(pipeline, seed)
+ return true unless pipeline.branch_updated?
+
+ pipeline.modified_paths.any? do |path|
+ @globs.any? do |glob|
+ File.fnmatch?(glob, path, File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/build/policy/kubernetes.rb b/lib/gitlab/ci/build/policy/kubernetes.rb
index 782f6c4c0af..4c7dc947cd0 100644
--- a/lib/gitlab/ci/build/policy/kubernetes.rb
+++ b/lib/gitlab/ci/build/policy/kubernetes.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Build
diff --git a/lib/gitlab/ci/build/policy/refs.rb b/lib/gitlab/ci/build/policy/refs.rb
index 4aa5dc89f47..10934536536 100644
--- a/lib/gitlab/ci/build/policy/refs.rb
+++ b/lib/gitlab/ci/build/policy/refs.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Build
diff --git a/lib/gitlab/ci/build/policy/specification.rb b/lib/gitlab/ci/build/policy/specification.rb
index f09ba42c074..ceb5210cfb5 100644
--- a/lib/gitlab/ci/build/policy/specification.rb
+++ b/lib/gitlab/ci/build/policy/specification.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Build
diff --git a/lib/gitlab/ci/build/policy/variables.rb b/lib/gitlab/ci/build/policy/variables.rb
index 9d2a362b7d4..0698136166a 100644
--- a/lib/gitlab/ci/build/policy/variables.rb
+++ b/lib/gitlab/ci/build/policy/variables.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Build
diff --git a/lib/gitlab/ci/build/step.rb b/lib/gitlab/ci/build/step.rb
index 0b1ebe4e048..d587c896712 100644
--- a/lib/gitlab/ci/build/step.rb
+++ b/lib/gitlab/ci/build/step.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Build
diff --git a/lib/gitlab/ci/charts.rb b/lib/gitlab/ci/charts.rb
index 7b7354bce16..a4f01468e8e 100644
--- a/lib/gitlab/ci/charts.rb
+++ b/lib/gitlab/ci/charts.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Charts
diff --git a/lib/gitlab/ci/config.rb b/lib/gitlab/ci/config.rb
index fe98d25af29..6333799a491 100644
--- a/lib/gitlab/ci/config.rb
+++ b/lib/gitlab/ci/config.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
#
@@ -13,10 +15,10 @@ module Gitlab
@global = Entry::Global.new(@config)
@global.compose!
- rescue Loader::FormatError, Extendable::ExtensionError => e
+ rescue Gitlab::Config::Loader::FormatError,
+ Extendable::ExtensionError,
+ External::Processor::IncludeError => e
raise Config::ConfigError, e.message
- rescue ::Gitlab::Ci::External::Processor::FileError => e
- raise ::Gitlab::Ci::YamlProcessor::ValidationError, e.message
end
def valid?
@@ -69,7 +71,7 @@ module Gitlab
private
def build_config(config, opts = {})
- initial_config = Loader.new(config).load!
+ initial_config = Gitlab::Config::Loader::Yaml.new(config).load!
project = opts.fetch(:project, nil)
if project
@@ -81,7 +83,7 @@ module Gitlab
def process_external_files(config, project, opts)
sha = opts.fetch(:sha) { project.repository.root_ref_sha }
- ::Gitlab::Ci::External::Processor.new(config, project, sha).perform
+ Config::External::Processor.new(config, project, sha).perform
end
end
end
diff --git a/lib/gitlab/ci/config/entry/artifacts.rb b/lib/gitlab/ci/config/entry/artifacts.rb
index e80f9d2e452..41613369ca2 100644
--- a/lib/gitlab/ci/config/entry/artifacts.rb
+++ b/lib/gitlab/ci/config/entry/artifacts.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,10 +7,10 @@ module Gitlab
##
# Entry that represents a configuration of job artifacts.
#
- class Artifacts < Node
- include Configurable
- include Validatable
- include Attributable
+ class Artifacts < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Configurable
+ include ::Gitlab::Config::Entry::Validatable
+ include ::Gitlab::Config::Entry::Attributable
ALLOWED_KEYS = %i[name untracked paths reports when expire_in].freeze
diff --git a/lib/gitlab/ci/config/entry/attributable.rb b/lib/gitlab/ci/config/entry/attributable.rb
deleted file mode 100644
index 3e87a09704e..00000000000
--- a/lib/gitlab/ci/config/entry/attributable.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-module Gitlab
- module Ci
- class Config
- module Entry
- module Attributable
- extend ActiveSupport::Concern
-
- class_methods do
- def attributes(*attributes)
- attributes.flatten.each do |attribute|
- if method_defined?(attribute)
- raise ArgumentError, 'Method already defined!'
- end
-
- define_method(attribute) do
- return unless config.is_a?(Hash)
-
- config[attribute]
- end
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/entry/boolean.rb b/lib/gitlab/ci/config/entry/boolean.rb
deleted file mode 100644
index f3357f85b99..00000000000
--- a/lib/gitlab/ci/config/entry/boolean.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-module Gitlab
- module Ci
- class Config
- module Entry
- ##
- # Entry that represents a boolean value.
- #
- class Boolean < Node
- include Validatable
-
- validations do
- validates :config, boolean: true
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/entry/cache.rb b/lib/gitlab/ci/config/entry/cache.rb
index d7e09acbbf3..7b94af24c09 100644
--- a/lib/gitlab/ci/config/entry/cache.rb
+++ b/lib/gitlab/ci/config/entry/cache.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,9 +7,9 @@ module Gitlab
##
# Entry that represents a cache configuration
#
- class Cache < Node
- include Configurable
- include Attributable
+ class Cache < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Configurable
+ include ::Gitlab::Config::Entry::Attributable
ALLOWED_KEYS = %i[key untracked paths policy].freeze
DEFAULT_POLICY = 'pull-push'.freeze
@@ -20,7 +22,7 @@ module Gitlab
entry :key, Entry::Key,
description: 'Cache key used to define a cache affinity.'
- entry :untracked, Entry::Boolean,
+ entry :untracked, ::Gitlab::Config::Entry::Boolean,
description: 'Cache all untracked files.'
entry :paths, Entry::Paths,
diff --git a/lib/gitlab/ci/config/entry/commands.rb b/lib/gitlab/ci/config/entry/commands.rb
index 9f66f11be9b..02e368c1813 100644
--- a/lib/gitlab/ci/config/entry/commands.rb
+++ b/lib/gitlab/ci/config/entry/commands.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,8 +7,8 @@ module Gitlab
##
# Entry that represents a job script.
#
- class Commands < Node
- include Validatable
+ class Commands < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
validations do
validates :config, array_of_strings_or_string: true
diff --git a/lib/gitlab/ci/config/entry/configurable.rb b/lib/gitlab/ci/config/entry/configurable.rb
deleted file mode 100644
index 697f622c45e..00000000000
--- a/lib/gitlab/ci/config/entry/configurable.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-module Gitlab
- module Ci
- class Config
- module Entry
- ##
- # This mixin is responsible for adding DSL, which purpose is to
- # simplifly process of adding child nodes.
- #
- # This can be used only if parent node is a configuration entry that
- # holds a hash as a configuration value, for example:
- #
- # job:
- # script: ...
- # artifacts: ...
- #
- module Configurable
- extend ActiveSupport::Concern
-
- included do
- include Validatable
-
- validations do
- validates :config, type: Hash
- end
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def compose!(deps = nil)
- return unless valid?
-
- self.class.nodes.each do |key, factory|
- factory
- .value(config[key])
- .with(key: key, parent: self)
-
- entries[key] = factory.create!
- end
-
- yield if block_given?
-
- entries.each_value do |entry|
- entry.compose!(deps)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- class_methods do
- def nodes
- Hash[(@nodes || {}).map { |key, factory| [key, factory.dup] }]
- end
-
- private
-
- # rubocop: disable CodeReuse/ActiveRecord
- def entry(key, entry, metadata)
- factory = Entry::Factory.new(entry)
- .with(description: metadata[:description])
-
- (@nodes ||= {}).merge!(key.to_sym => factory)
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- def helpers(*nodes)
- nodes.each do |symbol|
- define_method("#{symbol}_defined?") do
- entries[symbol]&.specified?
- end
-
- define_method("#{symbol}_value") do
- return unless entries[symbol] && entries[symbol].valid?
-
- entries[symbol].value
- end
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/entry/coverage.rb b/lib/gitlab/ci/config/entry/coverage.rb
index 12a063059cb..89545158bed 100644
--- a/lib/gitlab/ci/config/entry/coverage.rb
+++ b/lib/gitlab/ci/config/entry/coverage.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,8 +7,8 @@ module Gitlab
##
# Entry that represents Coverage settings.
#
- class Coverage < Node
- include Validatable
+ class Coverage < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
validations do
validates :config, regexp: true
diff --git a/lib/gitlab/ci/config/entry/environment.rb b/lib/gitlab/ci/config/entry/environment.rb
index 0c1f9eb7cbf..69a3a1aedef 100644
--- a/lib/gitlab/ci/config/entry/environment.rb
+++ b/lib/gitlab/ci/config/entry/environment.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,8 +7,8 @@ module Gitlab
##
# Entry that represents an environment.
#
- class Environment < Node
- include Validatable
+ class Environment < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
ALLOWED_KEYS = %i[name url action on_stop].freeze
diff --git a/lib/gitlab/ci/config/entry/factory.rb b/lib/gitlab/ci/config/entry/factory.rb
deleted file mode 100644
index 6be8288748f..00000000000
--- a/lib/gitlab/ci/config/entry/factory.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-module Gitlab
- module Ci
- class Config
- module Entry
- ##
- # Factory class responsible for fabricating entry objects.
- #
- class Factory
- InvalidFactory = Class.new(StandardError)
-
- def initialize(entry)
- @entry = entry
- @metadata = {}
- @attributes = {}
- end
-
- def value(value)
- @value = value
- self
- end
-
- def metadata(metadata)
- @metadata.merge!(metadata)
- self
- end
-
- def with(attributes)
- @attributes.merge!(attributes)
- self
- end
-
- def create!
- raise InvalidFactory unless defined?(@value)
-
- ##
- # We assume that unspecified entry is undefined.
- # See issue #18775.
- #
- if @value.nil?
- Entry::Unspecified.new(
- fabricate_unspecified
- )
- else
- fabricate(@entry, @value)
- end
- end
-
- private
-
- def fabricate_unspecified
- ##
- # If entry has a default value we fabricate concrete node
- # with default value.
- #
- if @entry.default.nil?
- fabricate(Entry::Undefined)
- else
- fabricate(@entry, @entry.default)
- end
- end
-
- def fabricate(entry, value = nil)
- entry.new(value, @metadata).tap do |node|
- node.key = @attributes[:key]
- node.parent = @attributes[:parent]
- node.description = @attributes[:description]
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/entry/global.rb b/lib/gitlab/ci/config/entry/global.rb
index 04077fa7a61..09ecb5fdb99 100644
--- a/lib/gitlab/ci/config/entry/global.rb
+++ b/lib/gitlab/ci/config/entry/global.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -6,8 +8,8 @@ module Gitlab
# This class represents a global entry - root Entry for entire
# GitLab CI Configuration file.
#
- class Global < Node
- include Configurable
+ class Global < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Configurable
entry :before_script, Entry::Script,
description: 'Script that will be executed before each job.'
@@ -47,7 +49,7 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def compose_jobs!
- factory = Entry::Factory.new(Entry::Jobs)
+ factory = ::Gitlab::Config::Entry::Factory.new(Entry::Jobs)
.value(@config.except(*self.class.nodes.keys))
.with(key: :jobs, parent: self,
description: 'Jobs definition for this pipeline')
diff --git a/lib/gitlab/ci/config/entry/hidden.rb b/lib/gitlab/ci/config/entry/hidden.rb
index 6fc3aa385bc..76e5d05639f 100644
--- a/lib/gitlab/ci/config/entry/hidden.rb
+++ b/lib/gitlab/ci/config/entry/hidden.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,8 +7,8 @@ module Gitlab
##
# Entry that represents a hidden CI/CD key.
#
- class Hidden < Node
- include Validatable
+ class Hidden < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
validations do
validates :config, presence: true
diff --git a/lib/gitlab/ci/config/entry/image.rb b/lib/gitlab/ci/config/entry/image.rb
index 2844be80a84..a13a0625e90 100644
--- a/lib/gitlab/ci/config/entry/image.rb
+++ b/lib/gitlab/ci/config/entry/image.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,8 +7,8 @@ module Gitlab
##
# Entry that represents a Docker image.
#
- class Image < Node
- include Validatable
+ class Image < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
ALLOWED_KEYS = %i[name entrypoint].freeze
diff --git a/lib/gitlab/ci/config/entry/job.rb b/lib/gitlab/ci/config/entry/job.rb
index 016a896bde5..4f2ac94b6c3 100644
--- a/lib/gitlab/ci/config/entry/job.rb
+++ b/lib/gitlab/ci/config/entry/job.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,14 +7,14 @@ module Gitlab
##
# Entry that represents a concrete CI/CD job.
#
- class Job < Node
- include Configurable
- include Attributable
+ class Job < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Configurable
+ include ::Gitlab::Config::Entry::Attributable
ALLOWED_KEYS = %i[tags script only except type image services
- allow_failure type stage when artifacts cache
+ allow_failure type stage when start_in artifacts cache
dependencies before_script after_script variables
- environment coverage retry extends].freeze
+ environment coverage retry parallel extends].freeze
validations do
validates :config, allowed_keys: ALLOWED_KEYS
@@ -24,17 +26,19 @@ module Gitlab
with_options allow_nil: true do
validates :tags, array_of_strings: true
validates :allow_failure, boolean: true
- validates :retry, numericality: { only_integer: true,
- greater_than_or_equal_to: 0,
- less_than_or_equal_to: 2 }
+ validates :parallel, numericality: { only_integer: true,
+ greater_than_or_equal_to: 2,
+ less_than_or_equal_to: 50 }
validates :when,
- inclusion: { in: %w[on_success on_failure always manual],
+ inclusion: { in: %w[on_success on_failure always manual delayed],
message: 'should be on_success, on_failure, ' \
- 'always or manual' }
-
+ 'always, manual or delayed' }
validates :dependencies, array_of_strings: true
validates :extends, type: String
end
+
+ validates :start_in, duration: { limit: '1 day' }, if: :delayed?
+ validates :start_in, absence: true, unless: :delayed?
end
entry :before_script, Entry::Script,
@@ -74,17 +78,21 @@ module Gitlab
description: 'Artifacts configuration for this job.'
entry :environment, Entry::Environment,
- description: 'Environment configuration for this job.'
+ description: 'Environment configuration for this job.'
entry :coverage, Entry::Coverage,
- description: 'Coverage configuration for this job.'
+ description: 'Coverage configuration for this job.'
+
+ entry :retry, Entry::Retry,
+ description: 'Retry configuration for this job.'
helpers :before_script, :script, :stage, :type, :after_script,
:cache, :image, :services, :only, :except, :variables,
- :artifacts, :commands, :environment, :coverage, :retry
+ :artifacts, :commands, :environment, :coverage, :retry,
+ :parallel
attributes :script, :tags, :allow_failure, :when, :dependencies,
- :retry, :extends
+ :retry, :parallel, :extends, :start_in
def compose!(deps = nil)
super do
@@ -114,6 +122,10 @@ module Gitlab
self.when == 'manual'
end
+ def delayed?
+ self.when == 'delayed'
+ end
+
def ignored?
allow_failure.nil? ? manual_action? : allow_failure
end
@@ -148,7 +160,8 @@ module Gitlab
environment: environment_defined? ? environment_value : nil,
environment_name: environment_defined? ? environment_value[:name] : nil,
coverage: coverage_defined? ? coverage_value : nil,
- retry: retry_defined? ? retry_value.to_i : nil,
+ retry: retry_defined? ? retry_value : nil,
+ parallel: parallel_defined? ? parallel_value.to_i : nil,
artifacts: artifacts_value,
after_script: after_script_value,
ignore: ignored? }
diff --git a/lib/gitlab/ci/config/entry/jobs.rb b/lib/gitlab/ci/config/entry/jobs.rb
index 96b6f2e5d6c..82b72e40404 100644
--- a/lib/gitlab/ci/config/entry/jobs.rb
+++ b/lib/gitlab/ci/config/entry/jobs.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,8 +7,8 @@ module Gitlab
##
# Entry that represents a set of jobs.
#
- class Jobs < Node
- include Validatable
+ class Jobs < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
validations do
validates :config, type: Hash
@@ -32,7 +34,7 @@ module Gitlab
@config.each do |name, config|
node = hidden?(name) ? Entry::Hidden : Entry::Job
- factory = Entry::Factory.new(node)
+ factory = ::Gitlab::Config::Entry::Factory.new(node)
.value(config || {})
.metadata(name: name)
.with(key: name, parent: self,
diff --git a/lib/gitlab/ci/config/entry/key.rb b/lib/gitlab/ci/config/entry/key.rb
index f27ad0a7759..0c10967e629 100644
--- a/lib/gitlab/ci/config/entry/key.rb
+++ b/lib/gitlab/ci/config/entry/key.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,8 +7,8 @@ module Gitlab
##
# Entry that represents a key.
#
- class Key < Node
- include Validatable
+ class Key < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
validations do
validates :config, key: true
diff --git a/lib/gitlab/ci/config/entry/legacy_validation_helpers.rb b/lib/gitlab/ci/config/entry/legacy_validation_helpers.rb
deleted file mode 100644
index a78a85397bd..00000000000
--- a/lib/gitlab/ci/config/entry/legacy_validation_helpers.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-module Gitlab
- module Ci
- class Config
- module Entry
- module LegacyValidationHelpers
- private
-
- def validate_duration(value)
- value.is_a?(String) && ChronicDuration.parse(value)
- rescue ChronicDuration::DurationParseError
- false
- end
-
- def validate_array_of_strings(values)
- values.is_a?(Array) && values.all? { |value| validate_string(value) }
- end
-
- def validate_array_of_strings_or_regexps(values)
- values.is_a?(Array) && values.all? { |value| validate_string_or_regexp(value) }
- end
-
- def validate_variables(variables)
- variables.is_a?(Hash) &&
- variables.flatten.all? do |value|
- validate_string(value) || validate_integer(value)
- end
- end
-
- def validate_integer(value)
- value.is_a?(Integer)
- end
-
- def validate_string(value)
- value.is_a?(String) || value.is_a?(Symbol)
- end
-
- def validate_regexp(value)
- !value.nil? && Regexp.new(value.to_s) && true
- rescue RegexpError, TypeError
- false
- end
-
- def validate_string_or_regexp(value)
- return true if value.is_a?(Symbol)
- return false unless value.is_a?(String)
-
- if value.first == '/' && value.last == '/'
- validate_regexp(value[1...-1])
- else
- true
- end
- end
-
- def validate_boolean(value)
- value.in?([true, false])
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/entry/node.rb b/lib/gitlab/ci/config/entry/node.rb
deleted file mode 100644
index 26505c91be3..00000000000
--- a/lib/gitlab/ci/config/entry/node.rb
+++ /dev/null
@@ -1,101 +0,0 @@
-module Gitlab
- module Ci
- class Config
- module Entry
- ##
- # Base abstract class for each configuration entry node.
- #
- class Node
- InvalidError = Class.new(StandardError)
-
- attr_reader :config, :metadata
- attr_accessor :key, :parent, :description
-
- def initialize(config, **metadata)
- @config = config
- @metadata = metadata
- @entries = {}
-
- self.class.aspects.to_a.each do |aspect|
- instance_exec(&aspect)
- end
- end
-
- def [](key)
- @entries[key] || Entry::Undefined.new
- end
-
- def compose!(deps = nil)
- return unless valid?
-
- yield if block_given?
- end
-
- def leaf?
- @entries.none?
- end
-
- def descendants
- @entries.values
- end
-
- def ancestors
- @parent ? @parent.ancestors + [@parent] : []
- end
-
- def valid?
- errors.none?
- end
-
- def errors
- []
- end
-
- def value
- if leaf?
- @config
- else
- meaningful = @entries.select do |_key, value|
- value.specified? && value.relevant?
- end
-
- Hash[meaningful.map { |key, entry| [key, entry.value] }]
- end
- end
-
- def specified?
- true
- end
-
- def relevant?
- true
- end
-
- def location
- name = @key.presence || self.class.name.to_s.demodulize
- .underscore.humanize.downcase
-
- ancestors.map(&:key).append(name).compact.join(':')
- end
-
- def inspect
- val = leaf? ? config : descendants
- unspecified = specified? ? '' : '(unspecified) '
- "#<#{self.class.name} #{unspecified}{#{key}: #{val.inspect}}>"
- end
-
- def self.default
- end
-
- def self.aspects
- @aspects ||= []
- end
-
- private
-
- attr_reader :entries
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/entry/paths.rb b/lib/gitlab/ci/config/entry/paths.rb
index 68dad161149..d6f287c6552 100644
--- a/lib/gitlab/ci/config/entry/paths.rb
+++ b/lib/gitlab/ci/config/entry/paths.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,8 +7,8 @@ module Gitlab
##
# Entry that represents an array of paths.
#
- class Paths < Node
- include Validatable
+ class Paths < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
validations do
validates :config, array_of_strings: true
diff --git a/lib/gitlab/ci/config/entry/policy.rb b/lib/gitlab/ci/config/entry/policy.rb
index 09e8e52b60f..998da1f6837 100644
--- a/lib/gitlab/ci/config/entry/policy.rb
+++ b/lib/gitlab/ci/config/entry/policy.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,12 +7,12 @@ module Gitlab
##
# Entry that represents an only/except trigger policy for the job.
#
- class Policy < Simplifiable
+ class Policy < ::Gitlab::Config::Entry::Simplifiable
strategy :RefsPolicy, if: -> (config) { config.is_a?(Array) }
strategy :ComplexPolicy, if: -> (config) { config.is_a?(Hash) }
- class RefsPolicy < Entry::Node
- include Entry::Validatable
+ class RefsPolicy < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
validations do
validates :config, array_of_strings_or_regexps: true
@@ -21,21 +23,23 @@ module Gitlab
end
end
- class ComplexPolicy < Entry::Node
- include Entry::Validatable
- include Entry::Attributable
+ class ComplexPolicy < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
+ include ::Gitlab::Config::Entry::Attributable
- attributes :refs, :kubernetes, :variables
+ ALLOWED_KEYS = %i[refs kubernetes variables changes].freeze
+ attributes :refs, :kubernetes, :variables, :changes
validations do
validates :config, presence: true
- validates :config, allowed_keys: %i[refs kubernetes variables]
+ validates :config, allowed_keys: ALLOWED_KEYS
validate :variables_expressions_syntax
with_options allow_nil: true do
validates :refs, array_of_strings_or_regexps: true
validates :kubernetes, allowed_values: %w[active]
validates :variables, array_of_strings: true
+ validates :changes, array_of_strings: true
end
def variables_expressions_syntax
@@ -54,7 +58,7 @@ module Gitlab
end
end
- class UnknownStrategy < Entry::Node
+ class UnknownStrategy < ::Gitlab::Config::Entry::Node
def errors
["#{location} has to be either an array of conditions or a hash"]
end
diff --git a/lib/gitlab/ci/config/entry/reports.rb b/lib/gitlab/ci/config/entry/reports.rb
index 5963f3eb90c..a3f6cc31321 100644
--- a/lib/gitlab/ci/config/entry/reports.rb
+++ b/lib/gitlab/ci/config/entry/reports.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,11 +7,11 @@ module Gitlab
##
# Entry that represents a configuration of job artifacts.
#
- class Reports < Node
- include Validatable
- include Attributable
+ class Reports < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
+ include ::Gitlab::Config::Entry::Attributable
- ALLOWED_KEYS = %i[junit].freeze
+ ALLOWED_KEYS = %i[junit codequality sast dependency_scanning container_scanning dast performance license_management].freeze
attributes ALLOWED_KEYS
@@ -19,6 +21,13 @@ module Gitlab
with_options allow_nil: true do
validates :junit, array_of_strings_or_string: true
+ validates :codequality, array_of_strings_or_string: true
+ validates :sast, array_of_strings_or_string: true
+ validates :dependency_scanning, array_of_strings_or_string: true
+ validates :container_scanning, array_of_strings_or_string: true
+ validates :dast, array_of_strings_or_string: true
+ validates :performance, array_of_strings_or_string: true
+ validates :license_management, array_of_strings_or_string: true
end
end
diff --git a/lib/gitlab/ci/config/entry/retry.rb b/lib/gitlab/ci/config/entry/retry.rb
new file mode 100644
index 00000000000..eaf8b38aa3c
--- /dev/null
+++ b/lib/gitlab/ci/config/entry/retry.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ module Entry
+ ##
+ # Entry that represents a retry config for a job.
+ #
+ class Retry < ::Gitlab::Config::Entry::Simplifiable
+ strategy :SimpleRetry, if: -> (config) { config.is_a?(Integer) }
+ strategy :FullRetry, if: -> (config) { config.is_a?(Hash) }
+
+ class SimpleRetry < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
+
+ validations do
+ validates :config, numericality: { only_integer: true,
+ greater_than_or_equal_to: 0,
+ less_than_or_equal_to: 2 }
+ end
+
+ def value
+ {
+ max: config
+ }
+ end
+
+ def location
+ 'retry'
+ end
+ end
+
+ class FullRetry < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
+ include ::Gitlab::Config::Entry::Attributable
+
+ ALLOWED_KEYS = %i[max when].freeze
+ attributes :max, :when
+
+ validations do
+ validates :config, allowed_keys: ALLOWED_KEYS
+
+ with_options allow_nil: true do
+ validates :max, numericality: { only_integer: true,
+ greater_than_or_equal_to: 0,
+ less_than_or_equal_to: 2 }
+
+ validates :when, array_of_strings_or_string: true
+ validates :when,
+ allowed_array_values: { in: FullRetry.possible_retry_when_values },
+ if: -> (config) { config.when.is_a?(Array) }
+ validates :when,
+ inclusion: { in: FullRetry.possible_retry_when_values },
+ if: -> (config) { config.when.is_a?(String) }
+ end
+ end
+
+ def self.possible_retry_when_values
+ @possible_retry_when_values ||= ::Ci::Build.failure_reasons.keys.map(&:to_s) + ['always']
+ end
+
+ def value
+ super.tap do |config|
+ # make sure that `when` is an array, because we allow it to
+ # be passed as a String in config for simplicity
+ config[:when] = Array.wrap(config[:when]) if config[:when]
+ end
+ end
+
+ def location
+ 'retry'
+ end
+ end
+
+ class UnknownStrategy < ::Gitlab::Config::Entry::Node
+ def errors
+ ["#{location} has to be either an integer or a hash"]
+ end
+
+ def location
+ 'retry config'
+ end
+ end
+
+ def self.default
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/entry/script.rb b/lib/gitlab/ci/config/entry/script.rb
index 29ecd9995ca..9d25a82b521 100644
--- a/lib/gitlab/ci/config/entry/script.rb
+++ b/lib/gitlab/ci/config/entry/script.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,8 +7,8 @@ module Gitlab
##
# Entry that represents a script.
#
- class Script < Node
- include Validatable
+ class Script < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
validations do
validates :config, array_of_strings: true
diff --git a/lib/gitlab/ci/config/entry/service.rb b/lib/gitlab/ci/config/entry/service.rb
index 3e2ebcff31a..6df67083310 100644
--- a/lib/gitlab/ci/config/entry/service.rb
+++ b/lib/gitlab/ci/config/entry/service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -6,7 +8,7 @@ module Gitlab
# Entry that represents a configuration of Docker service.
#
class Service < Image
- include Validatable
+ include ::Gitlab::Config::Entry::Validatable
ALLOWED_KEYS = %i[name entrypoint command alias].freeze
diff --git a/lib/gitlab/ci/config/entry/services.rb b/lib/gitlab/ci/config/entry/services.rb
index 0066894e069..71475f69218 100644
--- a/lib/gitlab/ci/config/entry/services.rb
+++ b/lib/gitlab/ci/config/entry/services.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,8 +7,8 @@ module Gitlab
##
# Entry that represents a configuration of Docker services.
#
- class Services < Node
- include Validatable
+ class Services < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
validations do
validates :config, type: Array
@@ -16,7 +18,7 @@ module Gitlab
super do
@entries = []
@config.each do |config|
- @entries << Entry::Factory.new(Entry::Service)
+ @entries << ::Gitlab::Config::Entry::Factory.new(Entry::Service)
.value(config || {})
.create!
end
diff --git a/lib/gitlab/ci/config/entry/simplifiable.rb b/lib/gitlab/ci/config/entry/simplifiable.rb
deleted file mode 100644
index 12764629686..00000000000
--- a/lib/gitlab/ci/config/entry/simplifiable.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-module Gitlab
- module Ci
- class Config
- module Entry
- class Simplifiable < SimpleDelegator
- EntryStrategy = Struct.new(:name, :condition)
-
- def initialize(config, **metadata)
- unless self.class.const_defined?(:UnknownStrategy)
- raise ArgumentError, 'UndefinedStrategy not available!'
- end
-
- strategy = self.class.strategies.find do |variant|
- variant.condition.call(config)
- end
-
- entry = self.class.entry_class(strategy)
-
- super(entry.new(config, metadata))
- end
-
- def self.strategy(name, **opts)
- EntryStrategy.new(name, opts.fetch(:if)).tap do |strategy|
- strategies.append(strategy)
- end
- end
-
- def self.strategies
- @strategies ||= []
- end
-
- def self.entry_class(strategy)
- if strategy.present?
- self.const_get(strategy.name)
- else
- self::UnknownStrategy
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/entry/stage.rb b/lib/gitlab/ci/config/entry/stage.rb
index b7afaba1de8..d6d576a3139 100644
--- a/lib/gitlab/ci/config/entry/stage.rb
+++ b/lib/gitlab/ci/config/entry/stage.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,8 +7,8 @@ module Gitlab
##
# Entry that represents a stage for a job.
#
- class Stage < Node
- include Validatable
+ class Stage < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
validations do
validates :config, type: String
diff --git a/lib/gitlab/ci/config/entry/stages.rb b/lib/gitlab/ci/config/entry/stages.rb
index ec187bd3732..2d715cbc6bb 100644
--- a/lib/gitlab/ci/config/entry/stages.rb
+++ b/lib/gitlab/ci/config/entry/stages.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,8 +7,8 @@ module Gitlab
##
# Entry that represents a configuration for pipeline stages.
#
- class Stages < Node
- include Validatable
+ class Stages < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
validations do
validates :config, array_of_strings: true
diff --git a/lib/gitlab/ci/config/entry/undefined.rb b/lib/gitlab/ci/config/entry/undefined.rb
deleted file mode 100644
index 1171ac10f22..00000000000
--- a/lib/gitlab/ci/config/entry/undefined.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-module Gitlab
- module Ci
- class Config
- module Entry
- ##
- # This class represents an undefined entry.
- #
- class Undefined < Node
- def initialize(*)
- super(nil)
- end
-
- def value
- nil
- end
-
- def valid?
- true
- end
-
- def errors
- []
- end
-
- def specified?
- false
- end
-
- def relevant?
- false
- end
-
- def inspect
- "#<#{self.class.name}>"
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/entry/unspecified.rb b/lib/gitlab/ci/config/entry/unspecified.rb
deleted file mode 100644
index fbb2551e870..00000000000
--- a/lib/gitlab/ci/config/entry/unspecified.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-module Gitlab
- module Ci
- class Config
- module Entry
- ##
- # This class represents an unspecified entry.
- #
- # It decorates original entry adding method that indicates it is
- # unspecified.
- #
- class Unspecified < SimpleDelegator
- def specified?
- false
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/entry/validatable.rb b/lib/gitlab/ci/config/entry/validatable.rb
deleted file mode 100644
index e45787773a8..00000000000
--- a/lib/gitlab/ci/config/entry/validatable.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-module Gitlab
- module Ci
- class Config
- module Entry
- module Validatable
- extend ActiveSupport::Concern
-
- def self.included(node)
- node.aspects.append -> do
- @validator = self.class.validator.new(self)
- @validator.validate(:new)
- end
- end
-
- def errors
- @validator.messages + descendants.flat_map(&:errors) # rubocop:disable Gitlab/ModuleWithInstanceVariables
- end
-
- class_methods do
- def validator
- @validator ||= Class.new(Entry::Validator).tap do |validator|
- if defined?(@validations)
- @validations.each { |rules| validator.class_eval(&rules) }
- end
- end
- end
-
- private
-
- def validations(&block)
- (@validations ||= []).append(block)
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/entry/validator.rb b/lib/gitlab/ci/config/entry/validator.rb
deleted file mode 100644
index 2df23a3edcd..00000000000
--- a/lib/gitlab/ci/config/entry/validator.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-module Gitlab
- module Ci
- class Config
- module Entry
- class Validator < SimpleDelegator
- include ActiveModel::Validations
- include Entry::Validators
-
- def initialize(entry)
- super(entry)
- end
-
- def messages
- errors.full_messages.map do |error|
- "#{location} #{error}".downcase
- end
- end
-
- def self.name
- 'Validator'
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/entry/validators.rb b/lib/gitlab/ci/config/entry/validators.rb
deleted file mode 100644
index b3c889ee92f..00000000000
--- a/lib/gitlab/ci/config/entry/validators.rb
+++ /dev/null
@@ -1,172 +0,0 @@
-module Gitlab
- module Ci
- class Config
- module Entry
- module Validators
- class AllowedKeysValidator < ActiveModel::EachValidator
- def validate_each(record, attribute, value)
- unknown_keys = record.config.try(:keys).to_a - options[:in]
-
- if unknown_keys.any?
- record.errors.add(:config, 'contains unknown keys: ' +
- unknown_keys.join(', '))
- end
- end
- end
-
- class AllowedValuesValidator < ActiveModel::EachValidator
- def validate_each(record, attribute, value)
- unless options[:in].include?(value.to_s)
- record.errors.add(attribute, "unknown value: #{value}")
- end
- end
- end
-
- class ArrayOfStringsValidator < ActiveModel::EachValidator
- include LegacyValidationHelpers
-
- def validate_each(record, attribute, value)
- unless validate_array_of_strings(value)
- record.errors.add(attribute, 'should be an array of strings')
- end
- end
- end
-
- class BooleanValidator < ActiveModel::EachValidator
- include LegacyValidationHelpers
-
- def validate_each(record, attribute, value)
- unless validate_boolean(value)
- record.errors.add(attribute, 'should be a boolean value')
- end
- end
- end
-
- class DurationValidator < ActiveModel::EachValidator
- include LegacyValidationHelpers
-
- def validate_each(record, attribute, value)
- unless validate_duration(value)
- record.errors.add(attribute, 'should be a duration')
- end
- end
- end
-
- class HashOrStringValidator < ActiveModel::EachValidator
- def validate_each(record, attribute, value)
- unless value.is_a?(Hash) || value.is_a?(String)
- record.errors.add(attribute, 'should be a hash or a string')
- end
- end
- end
-
- class KeyValidator < ActiveModel::EachValidator
- include LegacyValidationHelpers
-
- def validate_each(record, attribute, value)
- if validate_string(value)
- validate_path(record, attribute, value)
- else
- record.errors.add(attribute, 'should be a string or symbol')
- end
- end
-
- private
-
- def validate_path(record, attribute, value)
- path = CGI.unescape(value.to_s)
-
- if path.include?('/')
- record.errors.add(attribute, 'cannot contain the "/" character')
- elsif path == '.' || path == '..'
- record.errors.add(attribute, 'cannot be "." or ".."')
- end
- end
- end
-
- class RegexpValidator < ActiveModel::EachValidator
- include LegacyValidationHelpers
-
- def validate_each(record, attribute, value)
- unless validate_regexp(value)
- record.errors.add(attribute, 'must be a regular expression')
- end
- end
-
- private
-
- def look_like_regexp?(value)
- value.is_a?(String) && value.start_with?('/') &&
- value.end_with?('/')
- end
-
- def validate_regexp(value)
- look_like_regexp?(value) &&
- Regexp.new(value.to_s[1...-1]) &&
- true
- rescue RegexpError
- false
- end
- end
-
- class ArrayOfStringsOrRegexpsValidator < RegexpValidator
- def validate_each(record, attribute, value)
- unless validate_array_of_strings_or_regexps(value)
- record.errors.add(attribute, 'should be an array of strings or regexps')
- end
- end
-
- private
-
- def validate_array_of_strings_or_regexps(values)
- values.is_a?(Array) && values.all?(&method(:validate_string_or_regexp))
- end
-
- def validate_string_or_regexp(value)
- return false unless value.is_a?(String)
- return validate_regexp(value) if look_like_regexp?(value)
-
- true
- end
- end
-
- class ArrayOfStringsOrStringValidator < RegexpValidator
- def validate_each(record, attribute, value)
- unless validate_array_of_strings_or_string(value)
- record.errors.add(attribute, 'should be an array of strings or a string')
- end
- end
-
- private
-
- def validate_array_of_strings_or_string(values)
- validate_array_of_strings(values) || validate_string(values)
- end
- end
-
- class TypeValidator < ActiveModel::EachValidator
- def validate_each(record, attribute, value)
- type = options[:with]
- raise unless type.is_a?(Class)
-
- unless value.is_a?(type)
- message = options[:message] || "should be a #{type.name}"
- record.errors.add(attribute, message)
- end
- end
- end
-
- class VariablesValidator < ActiveModel::EachValidator
- include LegacyValidationHelpers
-
- def validate_each(record, attribute, value)
- unless validate_variables(value)
- record.errors.add(attribute, 'should be a hash of key value pairs')
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/entry/variables.rb b/lib/gitlab/ci/config/entry/variables.rb
index 8acab605c91..89d790ebfa6 100644
--- a/lib/gitlab/ci/config/entry/variables.rb
+++ b/lib/gitlab/ci/config/entry/variables.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Config
@@ -5,8 +7,8 @@ module Gitlab
##
# Entry that represents environment variables.
#
- class Variables < Node
- include Validatable
+ class Variables < ::Gitlab::Config::Entry::Node
+ include ::Gitlab::Config::Entry::Validatable
validations do
validates :config, variables: true
diff --git a/lib/gitlab/ci/config/external/file/base.rb b/lib/gitlab/ci/config/external/file/base.rb
new file mode 100644
index 00000000000..ee4ea9bbb1d
--- /dev/null
+++ b/lib/gitlab/ci/config/external/file/base.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ module External
+ module File
+ class Base
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :location, :opts, :errors
+
+ YAML_WHITELIST_EXTENSION = /.+\.(yml|yaml)$/i.freeze
+
+ def initialize(location, opts = {})
+ @location = location
+ @opts = opts
+ @errors = []
+
+ validate!
+ end
+
+ def invalid_extension?
+ !::File.basename(location).match(YAML_WHITELIST_EXTENSION)
+ end
+
+ def valid?
+ errors.none?
+ end
+
+ def error_message
+ errors.first
+ end
+
+ def content
+ raise NotImplementedError, 'subclass must implement fetching raw content'
+ end
+
+ def to_hash
+ @hash ||= Gitlab::Config::Loader::Yaml.new(content).load!
+ rescue Gitlab::Config::Loader::FormatError
+ nil
+ end
+
+ protected
+
+ def validate!
+ validate_location!
+ validate_content! if errors.none?
+ validate_hash! if errors.none?
+ end
+
+ def validate_location!
+ if invalid_extension?
+ errors.push("Included file `#{location}` does not have YAML extension!")
+ end
+ end
+
+ def validate_content!
+ if content.blank?
+ errors.push("Included file `#{location}` is empty or does not exist!")
+ end
+ end
+
+ def validate_hash!
+ if to_hash.blank?
+ errors.push("Included file `#{location}` does not have valid YAML syntax!")
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/external/file/local.rb b/lib/gitlab/ci/config/external/file/local.rb
new file mode 100644
index 00000000000..2a256aff65c
--- /dev/null
+++ b/lib/gitlab/ci/config/external/file/local.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ module External
+ module File
+ class Local < Base
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :project, :sha
+
+ def initialize(location, opts = {})
+ @project = opts.fetch(:project)
+ @sha = opts.fetch(:sha)
+
+ super
+ end
+
+ def content
+ strong_memoize(:content) { fetch_local_content }
+ end
+
+ private
+
+ def validate_content!
+ if content.nil?
+ errors.push("Local file `#{location}` does not exist!")
+ elsif content.blank?
+ errors.push("Local file `#{location}` is empty!")
+ end
+ end
+
+ def fetch_local_content
+ project.repository.blob_data_at(sha, location)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/external/file/remote.rb b/lib/gitlab/ci/config/external/file/remote.rb
new file mode 100644
index 00000000000..86fa5ad8800
--- /dev/null
+++ b/lib/gitlab/ci/config/external/file/remote.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ module External
+ module File
+ class Remote < Base
+ include Gitlab::Utils::StrongMemoize
+
+ def content
+ strong_memoize(:content) { fetch_remote_content }
+ end
+
+ private
+
+ def validate_location!
+ super
+
+ unless ::Gitlab::UrlSanitizer.valid?(location)
+ errors.push("Remote file `#{location}` does not have a valid address!")
+ end
+ end
+
+ def fetch_remote_content
+ begin
+ response = Gitlab::HTTP.get(location)
+ rescue SocketError
+ errors.push("Remote file `#{location}` could not be fetched because of a socket error!")
+ rescue Timeout::Error
+ errors.push("Remote file `#{location}` could not be fetched because of a timeout error!")
+ rescue Gitlab::HTTP::Error
+ errors.push("Remote file `#{location}` could not be fetched because of HTTP error!")
+ rescue Gitlab::HTTP::BlockedUrlError => e
+ errors.push("Remote file could not be fetched because #{e}!")
+ end
+
+ if response&.code.to_i >= 400
+ errors.push("Remote file `#{location}` could not be fetched because of HTTP code `#{response.code}` error!")
+ end
+
+ response.to_s if errors.none?
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/external/mapper.rb b/lib/gitlab/ci/config/external/mapper.rb
new file mode 100644
index 00000000000..def3563e505
--- /dev/null
+++ b/lib/gitlab/ci/config/external/mapper.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ module External
+ class Mapper
+ def initialize(values, project, sha)
+ @locations = Array(values.fetch(:include, []))
+ @project = project
+ @sha = sha
+ end
+
+ def process
+ locations.map { |location| build_external_file(location) }
+ end
+
+ private
+
+ attr_reader :locations, :project, :sha
+
+ def build_external_file(location)
+ if ::Gitlab::UrlSanitizer.valid?(location)
+ External::File::Remote.new(location)
+ else
+ External::File::Local.new(location, project: project, sha: sha)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/external/processor.rb b/lib/gitlab/ci/config/external/processor.rb
new file mode 100644
index 00000000000..eae0bdeb644
--- /dev/null
+++ b/lib/gitlab/ci/config/external/processor.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ module External
+ class Processor
+ IncludeError = Class.new(StandardError)
+
+ def initialize(values, project, sha)
+ @values = values
+ @external_files = External::Mapper.new(values, project, sha).process
+ @content = {}
+ end
+
+ def perform
+ return @values if @external_files.empty?
+
+ validate_external_files!
+ merge_external_files!
+ append_inline_content!
+ remove_include_keyword!
+ end
+
+ private
+
+ def validate_external_files!
+ @external_files.each do |file|
+ raise IncludeError, file.error_message unless file.valid?
+ end
+ end
+
+ def merge_external_files!
+ @external_files.each do |file|
+ @content.deep_merge!(file.to_hash)
+ end
+ end
+
+ def append_inline_content!
+ @content.deep_merge!(@values)
+ end
+
+ def remove_include_keyword!
+ @content.tap { @content.delete(:include) }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/config/loader.rb b/lib/gitlab/ci/config/loader.rb
deleted file mode 100644
index 141d2714cb6..00000000000
--- a/lib/gitlab/ci/config/loader.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-module Gitlab
- module Ci
- class Config
- class Loader
- FormatError = Class.new(StandardError)
-
- def initialize(config)
- @config = YAML.safe_load(config, [Symbol], [], true)
- rescue Psych::Exception => e
- raise FormatError, e.message
- end
-
- def valid?
- @config.is_a?(Hash)
- end
-
- def load!
- unless valid?
- raise FormatError, 'Invalid configuration format'
- end
-
- @config.deep_symbolize_keys
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/config/normalizer.rb b/lib/gitlab/ci/config/normalizer.rb
new file mode 100644
index 00000000000..b7743bd2090
--- /dev/null
+++ b/lib/gitlab/ci/config/normalizer.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ class Config
+ class Normalizer
+ def initialize(jobs_config)
+ @jobs_config = jobs_config
+ end
+
+ def normalize_jobs
+ extract_parallelized_jobs!
+ return @jobs_config if @parallelized_jobs.empty?
+
+ parallelized_config = parallelize_jobs
+ parallelize_dependencies(parallelized_config)
+ end
+
+ private
+
+ def extract_parallelized_jobs!
+ @parallelized_jobs = {}
+
+ @jobs_config.each do |job_name, config|
+ if config[:parallel]
+ @parallelized_jobs[job_name] = self.class.parallelize_job_names(job_name, config[:parallel])
+ end
+ end
+
+ @parallelized_jobs
+ end
+
+ def parallelize_jobs
+ @jobs_config.each_with_object({}) do |(job_name, config), hash|
+ if @parallelized_jobs.key?(job_name)
+ @parallelized_jobs[job_name].each { |name, index| hash[name.to_sym] = config.merge(name: name, instance: index) }
+ else
+ hash[job_name] = config
+ end
+
+ hash
+ end
+ end
+
+ def parallelize_dependencies(parallelized_config)
+ parallelized_job_names = @parallelized_jobs.keys.map(&:to_s)
+ parallelized_config.each_with_object({}) do |(job_name, config), hash|
+ if config[:dependencies] && (intersection = config[:dependencies] & parallelized_job_names).any?
+ deps = intersection.map { |dep| @parallelized_jobs[dep.to_sym].map(&:first) }.flatten
+ hash[job_name] = config.merge(dependencies: deps)
+ else
+ hash[job_name] = config
+ end
+
+ hash
+ end
+ end
+
+ def self.parallelize_job_names(name, total)
+ Array.new(total) { |index| ["#{name} #{index + 1}/#{total}", index + 1] }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/cron_parser.rb b/lib/gitlab/ci/cron_parser.rb
index 73f36735e35..b1db9084662 100644
--- a/lib/gitlab/ci/cron_parser.rb
+++ b/lib/gitlab/ci/cron_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class CronParser
diff --git a/lib/gitlab/ci/external/file/base.rb b/lib/gitlab/ci/external/file/base.rb
deleted file mode 100644
index f4da07b0b02..00000000000
--- a/lib/gitlab/ci/external/file/base.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- module External
- module File
- class Base
- YAML_WHITELIST_EXTENSION = /(yml|yaml)$/i.freeze
-
- def initialize(location, opts = {})
- @location = location
- end
-
- def valid?
- location.match(YAML_WHITELIST_EXTENSION) && content
- end
-
- def content
- raise NotImplementedError, 'content must be implemented and return a string or nil'
- end
-
- def error_message
- raise NotImplementedError, 'error_message must be implemented and return a string'
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/external/file/local.rb b/lib/gitlab/ci/external/file/local.rb
deleted file mode 100644
index 1aa7f687507..00000000000
--- a/lib/gitlab/ci/external/file/local.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- module External
- module File
- class Local < Base
- attr_reader :location, :project, :sha
-
- def initialize(location, opts = {})
- super
-
- @project = opts.fetch(:project)
- @sha = opts.fetch(:sha)
- end
-
- def content
- @content ||= fetch_local_content
- end
-
- def error_message
- "Local file '#{location}' is not valid."
- end
-
- private
-
- def fetch_local_content
- project.repository.blob_data_at(sha, location)
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/external/file/remote.rb b/lib/gitlab/ci/external/file/remote.rb
deleted file mode 100644
index 59bb3e8999e..00000000000
--- a/lib/gitlab/ci/external/file/remote.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- module External
- module File
- class Remote < Base
- include Gitlab::Utils::StrongMemoize
- attr_reader :location
-
- def content
- return @content if defined?(@content)
-
- @content = strong_memoize(:content) do
- begin
- Gitlab::HTTP.get(location)
- rescue Gitlab::HTTP::Error, Timeout::Error, SocketError, Gitlab::HTTP::BlockedUrlError
- nil
- end
- end
- end
-
- def error_message
- "Remote file '#{location}' is not valid."
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/external/mapper.rb b/lib/gitlab/ci/external/mapper.rb
deleted file mode 100644
index 58bd6a19acf..00000000000
--- a/lib/gitlab/ci/external/mapper.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- module External
- class Mapper
- def initialize(values, project, sha)
- @locations = Array(values.fetch(:include, []))
- @project = project
- @sha = sha
- end
-
- def process
- locations.map { |location| build_external_file(location) }
- end
-
- private
-
- attr_reader :locations, :project, :sha
-
- def build_external_file(location)
- if ::Gitlab::UrlSanitizer.valid?(location)
- Gitlab::Ci::External::File::Remote.new(location)
- else
- options = { project: project, sha: sha }
- Gitlab::Ci::External::File::Local.new(location, options)
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/external/processor.rb b/lib/gitlab/ci/external/processor.rb
deleted file mode 100644
index 76cf3ce89f9..00000000000
--- a/lib/gitlab/ci/external/processor.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- module External
- class Processor
- FileError = Class.new(StandardError)
-
- def initialize(values, project, sha)
- @values = values
- @external_files = Gitlab::Ci::External::Mapper.new(values, project, sha).process
- @content = {}
- end
-
- def perform
- return values if external_files.empty?
-
- external_files.each do |external_file|
- validate_external_file(external_file)
- @content.deep_merge!(content_of(external_file))
- end
-
- append_inline_content
- remove_include_keyword
- end
-
- private
-
- attr_reader :values, :external_files, :content
-
- def validate_external_file(external_file)
- unless external_file.valid?
- raise FileError, external_file.error_message
- end
- end
-
- def content_of(external_file)
- Gitlab::Ci::Config::Loader.new(external_file.content).load!
- end
-
- def append_inline_content
- @content.deep_merge!(@values)
- end
-
- def remove_include_keyword
- content.delete(:include)
- content
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/mask_secret.rb b/lib/gitlab/ci/mask_secret.rb
index 0daddaa638c..58d55b1bd6f 100644
--- a/lib/gitlab/ci/mask_secret.rb
+++ b/lib/gitlab/ci/mask_secret.rb
@@ -1,9 +1,13 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci::MaskSecret
class << self
def mask!(value, token)
return value unless value.present? && token.present?
+ # We assume 'value' must be mutable, given
+ # that frozen string is enabled.
value.gsub!(token, 'x' * token.length)
value
end
diff --git a/lib/gitlab/ci/model.rb b/lib/gitlab/ci/model.rb
index 3994a50772b..fbdb84c0522 100644
--- a/lib/gitlab/ci/model.rb
+++ b/lib/gitlab/ci/model.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Model
diff --git a/lib/gitlab/ci/parsers.rb b/lib/gitlab/ci/parsers.rb
deleted file mode 100644
index a4eccc08dfc..00000000000
--- a/lib/gitlab/ci/parsers.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-module Gitlab
- module Ci
- module Parsers
- def self.fabricate!(file_type)
- "Gitlab::Ci::Parsers::#{file_type.classify}".constantize.new
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/parsers/junit.rb b/lib/gitlab/ci/parsers/junit.rb
deleted file mode 100644
index d1c136f2009..00000000000
--- a/lib/gitlab/ci/parsers/junit.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-module Gitlab
- module Ci
- module Parsers
- class Junit
- JunitParserError = Class.new(StandardError)
-
- def parse!(xml_data, test_suite)
- root = Hash.from_xml(xml_data)
-
- all_cases(root) do |test_case|
- test_case = create_test_case(test_case)
- test_suite.add_test_case(test_case)
- end
- rescue REXML::ParseException => e
- raise JunitParserError, "XML parsing failed: #{e.message}"
- rescue => e
- raise JunitParserError, "JUnit parsing failed: #{e.message}"
- end
-
- private
-
- def all_cases(root, parent = nil, &blk)
- return unless root.present?
-
- [root].flatten.compact.map do |node|
- next unless node.is_a?(Hash)
-
- # we allow only one top-level 'testsuites'
- all_cases(node['testsuites'], root, &blk) unless parent
-
- # we require at least one level of testsuites or testsuite
- each_case(node['testcase'], &blk) if parent
-
- # we allow multiple nested 'testsuite' (eg. PHPUnit)
- all_cases(node['testsuite'], root, &blk)
- end
- end
-
- def each_case(testcase, &blk)
- return unless testcase.present?
-
- [testcase].flatten.compact.map(&blk)
- end
-
- def create_test_case(data)
- if data['failure']
- status = ::Gitlab::Ci::Reports::TestCase::STATUS_FAILED
- system_output = data['failure']
- else
- status = ::Gitlab::Ci::Reports::TestCase::STATUS_SUCCESS
- system_output = nil
- end
-
- ::Gitlab::Ci::Reports::TestCase.new(
- classname: data['classname'],
- name: data['name'],
- file: data['file'],
- execution_time: data['time'],
- status: status,
- system_output: system_output
- )
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/parsers/test.rb b/lib/gitlab/ci/parsers/test.rb
new file mode 100644
index 00000000000..c6bc9662b07
--- /dev/null
+++ b/lib/gitlab/ci/parsers/test.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Parsers
+ module Test
+ ParserNotFoundError = Class.new(StandardError)
+
+ PARSERS = {
+ junit: ::Gitlab::Ci::Parsers::Test::Junit
+ }.freeze
+
+ def self.fabricate!(file_type)
+ PARSERS.fetch(file_type.to_sym).new
+ rescue KeyError
+ raise ParserNotFoundError, "Cannot find any parser matching file type '#{file_type}'"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/parsers/test/junit.rb b/lib/gitlab/ci/parsers/test/junit.rb
new file mode 100644
index 00000000000..2791730fd26
--- /dev/null
+++ b/lib/gitlab/ci/parsers/test/junit.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Parsers
+ module Test
+ class Junit
+ JunitParserError = Class.new(StandardError)
+
+ def parse!(xml_data, test_suite)
+ root = Hash.from_xml(xml_data)
+
+ all_cases(root) do |test_case|
+ test_case = create_test_case(test_case)
+ test_suite.add_test_case(test_case)
+ end
+ rescue Nokogiri::XML::SyntaxError
+ raise JunitParserError, "XML parsing failed"
+ rescue
+ raise JunitParserError, "JUnit parsing failed"
+ end
+
+ private
+
+ def all_cases(root, parent = nil, &blk)
+ return unless root.present?
+
+ [root].flatten.compact.map do |node|
+ next unless node.is_a?(Hash)
+
+ # we allow only one top-level 'testsuites'
+ all_cases(node['testsuites'], root, &blk) unless parent
+
+ # we require at least one level of testsuites or testsuite
+ each_case(node['testcase'], &blk) if parent
+
+ # we allow multiple nested 'testsuite' (eg. PHPUnit)
+ all_cases(node['testsuite'], root, &blk)
+ end
+ end
+
+ def each_case(testcase, &blk)
+ return unless testcase.present?
+
+ [testcase].flatten.compact.map(&blk)
+ end
+
+ def create_test_case(data)
+ if data['failure']
+ status = ::Gitlab::Ci::Reports::TestCase::STATUS_FAILED
+ system_output = data['failure']
+ else
+ status = ::Gitlab::Ci::Reports::TestCase::STATUS_SUCCESS
+ system_output = nil
+ end
+
+ ::Gitlab::Ci::Reports::TestCase.new(
+ classname: data['classname'],
+ name: data['name'],
+ file: data['file'],
+ execution_time: data['time'],
+ status: status,
+ system_output: system_output
+ )
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/chain/base.rb b/lib/gitlab/ci/pipeline/chain/base.rb
index efed19da21c..bab1c73e2f1 100644
--- a/lib/gitlab/ci/pipeline/chain/base.rb
+++ b/lib/gitlab/ci/pipeline/chain/base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/chain/build.rb b/lib/gitlab/ci/pipeline/chain/build.rb
index b5eb0cfa2f0..b445a872b3d 100644
--- a/lib/gitlab/ci/pipeline/chain/build.rb
+++ b/lib/gitlab/ci/pipeline/chain/build.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/chain/command.rb b/lib/gitlab/ci/pipeline/chain/command.rb
index a53c80d34f7..05978804d92 100644
--- a/lib/gitlab/ci/pipeline/chain/command.rb
+++ b/lib/gitlab/ci/pipeline/chain/command.rb
@@ -1,4 +1,7 @@
-module Gitlab # rubocop:disable Naming/FileName
+# rubocop:disable Naming/FileName
+# frozen_string_literal: true
+
+module Gitlab
module Ci
module Pipeline
module Chain
diff --git a/lib/gitlab/ci/pipeline/chain/create.rb b/lib/gitlab/ci/pipeline/chain/create.rb
index 02493c7fe02..aa627bdb009 100644
--- a/lib/gitlab/ci/pipeline/chain/create.rb
+++ b/lib/gitlab/ci/pipeline/chain/create.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
@@ -5,26 +7,11 @@ module Gitlab
class Create < Chain::Base
include Chain::Helpers
- # rubocop: disable CodeReuse/ActiveRecord
def perform!
- ::Ci::Pipeline.transaction do
- pipeline.save!
-
- ##
- # Create environments before the pipeline starts.
- #
- pipeline.builds.each do |build|
- if build.has_environment?
- project.environments.find_or_create_by(
- name: build.expanded_environment_name
- )
- end
- end
- end
+ pipeline.save!
rescue ActiveRecord::RecordInvalid => e
error("Failed to persist the pipeline: #{e}")
end
- # rubocop: enable CodeReuse/ActiveRecord
def break?
!pipeline.persisted?
diff --git a/lib/gitlab/ci/pipeline/chain/helpers.rb b/lib/gitlab/ci/pipeline/chain/helpers.rb
index bf1380a1da9..6bb3a75291b 100644
--- a/lib/gitlab/ci/pipeline/chain/helpers.rb
+++ b/lib/gitlab/ci/pipeline/chain/helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/chain/populate.rb b/lib/gitlab/ci/pipeline/chain/populate.rb
index f34c11ca3c2..633d3cd4f6b 100644
--- a/lib/gitlab/ci/pipeline/chain/populate.rb
+++ b/lib/gitlab/ci/pipeline/chain/populate.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/chain/sequence.rb b/lib/gitlab/ci/pipeline/chain/sequence.rb
index e24630656d3..99780409085 100644
--- a/lib/gitlab/ci/pipeline/chain/sequence.rb
+++ b/lib/gitlab/ci/pipeline/chain/sequence.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/chain/skip.rb b/lib/gitlab/ci/pipeline/chain/skip.rb
index 32cbb7ca6af..b9707d2f8f5 100644
--- a/lib/gitlab/ci/pipeline/chain/skip.rb
+++ b/lib/gitlab/ci/pipeline/chain/skip.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/chain/validate/abilities.rb b/lib/gitlab/ci/pipeline/chain/validate/abilities.rb
index 13c6fedd831..ebd7e6e8289 100644
--- a/lib/gitlab/ci/pipeline/chain/validate/abilities.rb
+++ b/lib/gitlab/ci/pipeline/chain/validate/abilities.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/chain/validate/config.rb b/lib/gitlab/ci/pipeline/chain/validate/config.rb
index a3bd2a5a23a..28c38cc3d18 100644
--- a/lib/gitlab/ci/pipeline/chain/validate/config.rb
+++ b/lib/gitlab/ci/pipeline/chain/validate/config.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/chain/validate/repository.rb b/lib/gitlab/ci/pipeline/chain/validate/repository.rb
index 9699c24e5b6..d88851d8245 100644
--- a/lib/gitlab/ci/pipeline/chain/validate/repository.rb
+++ b/lib/gitlab/ci/pipeline/chain/validate/repository.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/duration.rb b/lib/gitlab/ci/pipeline/duration.rb
index 30701e1de1b..de24bbf688b 100644
--- a/lib/gitlab/ci/pipeline/duration.rb
+++ b/lib/gitlab/ci/pipeline/duration.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/expression.rb b/lib/gitlab/ci/pipeline/expression.rb
index f57df7c5637..61d392121d8 100644
--- a/lib/gitlab/ci/pipeline/expression.rb
+++ b/lib/gitlab/ci/pipeline/expression.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/base.rb b/lib/gitlab/ci/pipeline/expression/lexeme/base.rb
index 047ab66e9b3..70c774416f6 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/base.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/equals.rb b/lib/gitlab/ci/pipeline/expression/lexeme/equals.rb
index 3a2f0c6924e..668e85f5b9e 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/equals.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/equals.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/matches.rb b/lib/gitlab/ci/pipeline/expression/lexeme/matches.rb
index 10957598f76..cd17bc4d78b 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/matches.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/matches.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/null.rb b/lib/gitlab/ci/pipeline/expression/lexeme/null.rb
index a2778716924..be7258c201a 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/null.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/null.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/operator.rb b/lib/gitlab/ci/pipeline/expression/lexeme/operator.rb
index f640d0b5855..3ebceb92eb7 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/operator.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/operator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb b/lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb
index 9b239c29ea4..d7e6dacf068 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/pattern.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/string.rb b/lib/gitlab/ci/pipeline/expression/lexeme/string.rb
index 346c92dc51e..2db2bf011f1 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/string.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/string.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/value.rb b/lib/gitlab/ci/pipeline/expression/lexeme/value.rb
index f2611d65faf..ef9ddb6cae9 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/value.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/value.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/variable.rb b/lib/gitlab/ci/pipeline/expression/lexeme/variable.rb
index 37643c8ef53..85c0899e4f6 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/variable.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/variable.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/expression/lexer.rb b/lib/gitlab/ci/pipeline/expression/lexer.rb
index 4cacb1e62c9..f26542361a2 100644
--- a/lib/gitlab/ci/pipeline/expression/lexer.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/expression/parser.rb b/lib/gitlab/ci/pipeline/expression/parser.rb
index 90f94d0b763..ed184309ab4 100644
--- a/lib/gitlab/ci/pipeline/expression/parser.rb
+++ b/lib/gitlab/ci/pipeline/expression/parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/expression/statement.rb b/lib/gitlab/ci/pipeline/expression/statement.rb
index b36f1e0f865..b03611f756e 100644
--- a/lib/gitlab/ci/pipeline/expression/statement.rb
+++ b/lib/gitlab/ci/pipeline/expression/statement.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/expression/token.rb b/lib/gitlab/ci/pipeline/expression/token.rb
index 58211800b88..513d43f6fca 100644
--- a/lib/gitlab/ci/pipeline/expression/token.rb
+++ b/lib/gitlab/ci/pipeline/expression/token.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/seed/base.rb b/lib/gitlab/ci/pipeline/seed/base.rb
index db9706924bb..1fd3a61017f 100644
--- a/lib/gitlab/ci/pipeline/seed/base.rb
+++ b/lib/gitlab/ci/pipeline/seed/base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/seed/build.rb b/lib/gitlab/ci/pipeline/seed/build.rb
index 6980b0b7aff..ef738a93bfe 100644
--- a/lib/gitlab/ci/pipeline/seed/build.rb
+++ b/lib/gitlab/ci/pipeline/seed/build.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/pipeline/seed/stage.rb b/lib/gitlab/ci/pipeline/seed/stage.rb
index 2b58d9863a0..4775ff15581 100644
--- a/lib/gitlab/ci/pipeline/seed/stage.rb
+++ b/lib/gitlab/ci/pipeline/seed/stage.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Pipeline
diff --git a/lib/gitlab/ci/reports/test_case.rb b/lib/gitlab/ci/reports/test_case.rb
index b4d08ed257f..292e273a03a 100644
--- a/lib/gitlab/ci/reports/test_case.rb
+++ b/lib/gitlab/ci/reports/test_case.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Reports
diff --git a/lib/gitlab/ci/reports/test_reports.rb b/lib/gitlab/ci/reports/test_reports.rb
index c87bdb4a8a2..7397ff35d46 100644
--- a/lib/gitlab/ci/reports/test_reports.rb
+++ b/lib/gitlab/ci/reports/test_reports.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Reports
diff --git a/lib/gitlab/ci/reports/test_reports_comparer.rb b/lib/gitlab/ci/reports/test_reports_comparer.rb
index 726c6a11a81..11810bdc0a8 100644
--- a/lib/gitlab/ci/reports/test_reports_comparer.rb
+++ b/lib/gitlab/ci/reports/test_reports_comparer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Reports
diff --git a/lib/gitlab/ci/reports/test_suite.rb b/lib/gitlab/ci/reports/test_suite.rb
index b5f15397c0f..b0391160c15 100644
--- a/lib/gitlab/ci/reports/test_suite.rb
+++ b/lib/gitlab/ci/reports/test_suite.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Reports
diff --git a/lib/gitlab/ci/reports/test_suite_comparer.rb b/lib/gitlab/ci/reports/test_suite_comparer.rb
index 642aa593092..9cb7db5934c 100644
--- a/lib/gitlab/ci/reports/test_suite_comparer.rb
+++ b/lib/gitlab/ci/reports/test_suite_comparer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Reports
diff --git a/lib/gitlab/ci/status/build/action.rb b/lib/gitlab/ci/status/build/action.rb
index 6c9125647ad..45d9ba41e92 100644
--- a/lib/gitlab/ci/status/build/action.rb
+++ b/lib/gitlab/ci/status/build/action.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/build/cancelable.rb b/lib/gitlab/ci/status/build/cancelable.rb
index 024047d4983..43fb5cdbbe6 100644
--- a/lib/gitlab/ci/status/build/cancelable.rb
+++ b/lib/gitlab/ci/status/build/cancelable.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/build/canceled.rb b/lib/gitlab/ci/status/build/canceled.rb
index c83e2734a73..0518b9e673d 100644
--- a/lib/gitlab/ci/status/build/canceled.rb
+++ b/lib/gitlab/ci/status/build/canceled.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/build/common.rb b/lib/gitlab/ci/status/build/common.rb
index c1fc70ac266..6a75ec5c37f 100644
--- a/lib/gitlab/ci/status/build/common.rb
+++ b/lib/gitlab/ci/status/build/common.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/build/created.rb b/lib/gitlab/ci/status/build/created.rb
index 5be8e9de425..780fea23123 100644
--- a/lib/gitlab/ci/status/build/created.rb
+++ b/lib/gitlab/ci/status/build/created.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/build/erased.rb b/lib/gitlab/ci/status/build/erased.rb
index 495227c2ffb..d74cfc1ee77 100644
--- a/lib/gitlab/ci/status/build/erased.rb
+++ b/lib/gitlab/ci/status/build/erased.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/build/factory.rb b/lib/gitlab/ci/status/build/factory.rb
index 2b26ebb45a1..6e4bfe23f2b 100644
--- a/lib/gitlab/ci/status/build/factory.rb
+++ b/lib/gitlab/ci/status/build/factory.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
@@ -5,6 +7,7 @@ module Gitlab
class Factory < Status::Factory
def self.extended_statuses
[[Status::Build::Erased,
+ Status::Build::Scheduled,
Status::Build::Manual,
Status::Build::Canceled,
Status::Build::Created,
@@ -14,6 +17,7 @@ module Gitlab
Status::Build::Retryable],
[Status::Build::Failed],
[Status::Build::FailedAllowed,
+ Status::Build::Unschedule,
Status::Build::Play,
Status::Build::Stop],
[Status::Build::Action],
diff --git a/lib/gitlab/ci/status/build/failed.rb b/lib/gitlab/ci/status/build/failed.rb
index 2fa9a0d4541..d40454df737 100644
--- a/lib/gitlab/ci/status/build/failed.rb
+++ b/lib/gitlab/ci/status/build/failed.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
@@ -10,7 +12,10 @@ module Gitlab
stuck_or_timeout_failure: 'stuck or timeout failure',
runner_system_failure: 'runner system failure',
missing_dependency_failure: 'missing dependency failure',
- runner_unsupported: 'unsupported runner'
+ runner_unsupported: 'unsupported runner',
+ stale_schedule: 'stale schedule',
+ job_execution_timeout: 'job execution timeout',
+ archived_failure: 'archived failure'
}.freeze
private_constant :REASONS
diff --git a/lib/gitlab/ci/status/build/failed_allowed.rb b/lib/gitlab/ci/status/build/failed_allowed.rb
index ca0046fb1f7..d7570fdd3e2 100644
--- a/lib/gitlab/ci/status/build/failed_allowed.rb
+++ b/lib/gitlab/ci/status/build/failed_allowed.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/build/manual.rb b/lib/gitlab/ci/status/build/manual.rb
index 042da6392d3..d01b09f1398 100644
--- a/lib/gitlab/ci/status/build/manual.rb
+++ b/lib/gitlab/ci/status/build/manual.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/build/pending.rb b/lib/gitlab/ci/status/build/pending.rb
index 9dd9a27ad57..95f668295dd 100644
--- a/lib/gitlab/ci/status/build/pending.rb
+++ b/lib/gitlab/ci/status/build/pending.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/build/play.rb b/lib/gitlab/ci/status/build/play.rb
index a8b9ebf0803..c66b8ca5654 100644
--- a/lib/gitlab/ci/status/build/play.rb
+++ b/lib/gitlab/ci/status/build/play.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/build/retried.rb b/lib/gitlab/ci/status/build/retried.rb
index 6e190e4ee3c..b489dc68733 100644
--- a/lib/gitlab/ci/status/build/retried.rb
+++ b/lib/gitlab/ci/status/build/retried.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/build/retryable.rb b/lib/gitlab/ci/status/build/retryable.rb
index 5aeb8e51480..eb6b3f21604 100644
--- a/lib/gitlab/ci/status/build/retryable.rb
+++ b/lib/gitlab/ci/status/build/retryable.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/build/scheduled.rb b/lib/gitlab/ci/status/build/scheduled.rb
new file mode 100644
index 00000000000..0a09dbe5f42
--- /dev/null
+++ b/lib/gitlab/ci/status/build/scheduled.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Status
+ module Build
+ class Scheduled < Status::Extended
+ def illustration
+ {
+ image: 'illustrations/illustrations_scheduled-job_countdown.svg',
+ size: 'svg-394',
+ title: _("This is a delayed job to run in %{remainingTime}"),
+ content: _("This job will automatically run after its timer finishes. " \
+ "Often they are used for incremental roll-out deploys " \
+ "to production environments. When unscheduled it converts " \
+ "into a manual action.")
+ }
+ end
+
+ def status_tooltip
+ "delayed manual action (%{remainingTime})"
+ end
+
+ def self.matches?(build, user)
+ build.scheduled? && build.scheduled_at
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/status/build/skipped.rb b/lib/gitlab/ci/status/build/skipped.rb
index 3e678d0baee..4fe2f7b3114 100644
--- a/lib/gitlab/ci/status/build/skipped.rb
+++ b/lib/gitlab/ci/status/build/skipped.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/build/stop.rb b/lib/gitlab/ci/status/build/stop.rb
index dea838bfa39..a620e7ad126 100644
--- a/lib/gitlab/ci/status/build/stop.rb
+++ b/lib/gitlab/ci/status/build/stop.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/build/unschedule.rb b/lib/gitlab/ci/status/build/unschedule.rb
new file mode 100644
index 00000000000..9110839cb55
--- /dev/null
+++ b/lib/gitlab/ci/status/build/unschedule.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Status
+ module Build
+ class Unschedule < Status::Extended
+ def label
+ 'unschedule action'
+ end
+
+ def has_action?
+ can?(user, :update_build, subject)
+ end
+
+ def action_icon
+ 'time-out'
+ end
+
+ def action_title
+ 'Unschedule'
+ end
+
+ def action_button_title
+ _('Unschedule job')
+ end
+
+ def action_path
+ unschedule_project_job_path(subject.project, subject)
+ end
+
+ def action_method
+ :post
+ end
+
+ def self.matches?(build, user)
+ build.scheduled?
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/status/canceled.rb b/lib/gitlab/ci/status/canceled.rb
index e6195a60d4f..07f37732023 100644
--- a/lib/gitlab/ci/status/canceled.rb
+++ b/lib/gitlab/ci/status/canceled.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/core.rb b/lib/gitlab/ci/status/core.rb
index 9d6a2f51c11..ea773ee9944 100644
--- a/lib/gitlab/ci/status/core.rb
+++ b/lib/gitlab/ci/status/core.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/created.rb b/lib/gitlab/ci/status/created.rb
index 846f00b83dd..fface4bb97b 100644
--- a/lib/gitlab/ci/status/created.rb
+++ b/lib/gitlab/ci/status/created.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/extended.rb b/lib/gitlab/ci/status/extended.rb
index 1e8101f8949..b72a28ed0b6 100644
--- a/lib/gitlab/ci/status/extended.rb
+++ b/lib/gitlab/ci/status/extended.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/external/common.rb b/lib/gitlab/ci/status/external/common.rb
index 9307545b5b1..4169f5b3210 100644
--- a/lib/gitlab/ci/status/external/common.rb
+++ b/lib/gitlab/ci/status/external/common.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/external/factory.rb b/lib/gitlab/ci/status/external/factory.rb
index 07b15bd8d97..91fafb940a8 100644
--- a/lib/gitlab/ci/status/external/factory.rb
+++ b/lib/gitlab/ci/status/external/factory.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/factory.rb b/lib/gitlab/ci/status/factory.rb
index 15836c699c7..3446644eff8 100644
--- a/lib/gitlab/ci/status/factory.rb
+++ b/lib/gitlab/ci/status/factory.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/failed.rb b/lib/gitlab/ci/status/failed.rb
index 27ce85bd3ed..770ed7d4d5a 100644
--- a/lib/gitlab/ci/status/failed.rb
+++ b/lib/gitlab/ci/status/failed.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/group/common.rb b/lib/gitlab/ci/status/group/common.rb
index cfd4329a923..0b5ea0712ca 100644
--- a/lib/gitlab/ci/status/group/common.rb
+++ b/lib/gitlab/ci/status/group/common.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/group/factory.rb b/lib/gitlab/ci/status/group/factory.rb
index d118116cfc3..ee785856fdd 100644
--- a/lib/gitlab/ci/status/group/factory.rb
+++ b/lib/gitlab/ci/status/group/factory.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/manual.rb b/lib/gitlab/ci/status/manual.rb
index fc387e2fd25..50c92add400 100644
--- a/lib/gitlab/ci/status/manual.rb
+++ b/lib/gitlab/ci/status/manual.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/pending.rb b/lib/gitlab/ci/status/pending.rb
index 6780780db32..cea7e6ed938 100644
--- a/lib/gitlab/ci/status/pending.rb
+++ b/lib/gitlab/ci/status/pending.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/pipeline/blocked.rb b/lib/gitlab/ci/status/pipeline/blocked.rb
index bf7e484ee9b..ed13a439be0 100644
--- a/lib/gitlab/ci/status/pipeline/blocked.rb
+++ b/lib/gitlab/ci/status/pipeline/blocked.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/pipeline/common.rb b/lib/gitlab/ci/status/pipeline/common.rb
index 61bb07beb0f..7b34a2ea858 100644
--- a/lib/gitlab/ci/status/pipeline/common.rb
+++ b/lib/gitlab/ci/status/pipeline/common.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/pipeline/delayed.rb b/lib/gitlab/ci/status/pipeline/delayed.rb
new file mode 100644
index 00000000000..e61acdcd167
--- /dev/null
+++ b/lib/gitlab/ci/status/pipeline/delayed.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Status
+ module Pipeline
+ class Delayed < Status::Extended
+ def text
+ s_('CiStatusText|delayed')
+ end
+
+ def label
+ s_('CiStatusLabel|waiting for delayed job')
+ end
+
+ def self.matches?(pipeline, user)
+ pipeline.scheduled?
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/status/pipeline/factory.rb b/lib/gitlab/ci/status/pipeline/factory.rb
index 17f9a75f436..5d1a8bbd924 100644
--- a/lib/gitlab/ci/status/pipeline/factory.rb
+++ b/lib/gitlab/ci/status/pipeline/factory.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
@@ -5,6 +7,7 @@ module Gitlab
class Factory < Status::Factory
def self.extended_statuses
[[Status::SuccessWarning,
+ Status::Pipeline::Delayed,
Status::Pipeline::Blocked]]
end
diff --git a/lib/gitlab/ci/status/running.rb b/lib/gitlab/ci/status/running.rb
index ee13905e46d..ac7dd74cdce 100644
--- a/lib/gitlab/ci/status/running.rb
+++ b/lib/gitlab/ci/status/running.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/scheduled.rb b/lib/gitlab/ci/status/scheduled.rb
new file mode 100644
index 00000000000..16ad1da89e3
--- /dev/null
+++ b/lib/gitlab/ci/status/scheduled.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Status
+ class Scheduled < Status::Core
+ def text
+ s_('CiStatusText|delayed')
+ end
+
+ def label
+ s_('CiStatusLabel|delayed')
+ end
+
+ def icon
+ 'status_scheduled'
+ end
+
+ def favicon
+ 'favicon_status_scheduled'
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/status/skipped.rb b/lib/gitlab/ci/status/skipped.rb
index 0dbdc4de426..aaec1e1d201 100644
--- a/lib/gitlab/ci/status/skipped.rb
+++ b/lib/gitlab/ci/status/skipped.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/stage/common.rb b/lib/gitlab/ci/status/stage/common.rb
index f60a7662075..f12daaa9676 100644
--- a/lib/gitlab/ci/status/stage/common.rb
+++ b/lib/gitlab/ci/status/stage/common.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/stage/factory.rb b/lib/gitlab/ci/status/stage/factory.rb
index 4c37f084d07..58f4642510b 100644
--- a/lib/gitlab/ci/status/stage/factory.rb
+++ b/lib/gitlab/ci/status/stage/factory.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/success.rb b/lib/gitlab/ci/status/success.rb
index 731013ec017..020f2c5b89f 100644
--- a/lib/gitlab/ci/status/success.rb
+++ b/lib/gitlab/ci/status/success.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/status/success_warning.rb b/lib/gitlab/ci/status/success_warning.rb
index 32b4cf43e48..6632cd9b143 100644
--- a/lib/gitlab/ci/status/success_warning.rb
+++ b/lib/gitlab/ci/status/success_warning.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Status
diff --git a/lib/gitlab/ci/templates/Android.gitlab-ci.yml b/lib/gitlab/ci/templates/Android.gitlab-ci.yml
new file mode 100644
index 00000000000..6e138639b71
--- /dev/null
+++ b/lib/gitlab/ci/templates/Android.gitlab-ci.yml
@@ -0,0 +1,45 @@
+# Read more about this script on this blog post https://about.gitlab.com/2018/10/24/setting-up-gitlab-ci-for-android-projects/, by Jason Lenny
+image: openjdk:8-jdk
+
+variables:
+ ANDROID_COMPILE_SDK: "28"
+ ANDROID_BUILD_TOOLS: "28.0.2"
+ ANDROID_SDK_TOOLS: "4333796"
+
+before_script:
+ - apt-get --quiet update --yes
+ - apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1
+ - wget --quiet --output-document=android-sdk.zip https://dl.google.com/android/repository/sdk-tools-linux-${ANDROID_SDK_TOOLS}.zip
+ - unzip -d android-sdk-linux android-sdk.zip
+ - echo y | android-sdk-linux/tools/bin/sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}" >/dev/null
+ - echo y | android-sdk-linux/tools/bin/sdkmanager "platform-tools" >/dev/null
+ - echo y | android-sdk-linux/tools/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS}" >/dev/null
+ - export ANDROID_HOME=$PWD/android-sdk-linux
+ - export PATH=$PATH:$PWD/android-sdk-linux/platform-tools/
+ - chmod +x ./gradlew
+ # temporarily disable checking for EPIPE error and use yes to accept all licenses
+ - set +o pipefail
+ - yes | android-sdk-linux/tools/bin/sdkmanager --licenses
+ - set -o pipefail
+
+stages:
+ - build
+ - test
+
+lintDebug:
+ stage: build
+ script:
+ - ./gradlew -Pci --console=plain :app:lintDebug -PbuildDir=lint
+
+assembleDebug:
+ stage: build
+ script:
+ - ./gradlew assembleDebug
+ artifacts:
+ paths:
+ - app/build/outputs/
+
+debugTests:
+ stage: test
+ script:
+ - ./gradlew -Pci --console=plain :app:testDebug
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
new file mode 100644
index 00000000000..3b2cae07c12
--- /dev/null
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -0,0 +1,901 @@
+# Auto DevOps
+# This CI/CD configuration provides a standard pipeline for
+# * building a Docker image (using a buildpack if necessary),
+# * storing the image in the container registry,
+# * running tests from a buildpack,
+# * running code quality analysis,
+# * creating a review app for each topic branch,
+# * and continuous deployment to production
+#
+# Test jobs may be disabled by setting environment variables:
+# * test: TEST_DISABLED
+# * code_quality: CODE_QUALITY_DISABLED
+# * license_management: LICENSE_MANAGEMENT_DISABLED
+# * performance: PERFORMANCE_DISABLED
+# * sast: SAST_DISABLED
+# * dependency_scanning: DEPENDENCY_SCANNING_DISABLED
+# * container_scanning: CONTAINER_SCANNING_DISABLED
+# * dast: DAST_DISABLED
+# * review: REVIEW_DISABLED
+# * stop_review: REVIEW_DISABLED
+#
+# In order to deploy, you must have a Kubernetes cluster configured either
+# via a project integration, or via group/project variables.
+# AUTO_DEVOPS_DOMAIN must also be set as a variable at the group or project
+# level, or manually added below.
+#
+# Continuous deployment to production is enabled by default.
+# If you want to deploy to staging first, set STAGING_ENABLED environment variable.
+# If you want to enable incremental rollout, either manual or time based,
+# set INCREMENTAL_ROLLOUT_MODE environment variable to "manual" or "timed".
+# If you want to use canary deployments, set CANARY_ENABLED environment variable.
+#
+# If Auto DevOps fails to detect the proper buildpack, or if you want to
+# specify a custom buildpack, set a project variable `BUILDPACK_URL` to the
+# repository URL of the buildpack.
+# e.g. BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-ruby.git#v142
+# If you need multiple buildpacks, add a file to your project called
+# `.buildpacks` that contains the URLs, one on each line, in order.
+# Note: Auto CI does not work with multiple buildpacks yet
+
+image: alpine:latest
+
+variables:
+ # AUTO_DEVOPS_DOMAIN is the application deployment domain and should be set as a variable at the group or project level.
+ # AUTO_DEVOPS_DOMAIN: domain.example.com
+
+ POSTGRES_USER: user
+ POSTGRES_PASSWORD: testing-password
+ POSTGRES_ENABLED: "true"
+ POSTGRES_DB: $CI_ENVIRONMENT_SLUG
+
+ KUBERNETES_VERSION: 1.10.9
+ HELM_VERSION: 2.11.0
+
+ DOCKER_DRIVER: overlay2
+
+stages:
+ - build
+ - test
+ - review
+ - dast
+ - staging
+ - canary
+ - production
+ - incremental rollout 10%
+ - incremental rollout 25%
+ - incremental rollout 50%
+ - incremental rollout 100%
+ - performance
+ - cleanup
+
+build:
+ stage: build
+ image: docker:stable-git
+ services:
+ - docker:stable-dind
+ script:
+ - setup_docker
+ - build
+ only:
+ - branches
+
+test:
+ services:
+ - postgres:latest
+ variables:
+ POSTGRES_DB: test
+ stage: test
+ image: gliderlabs/herokuish:latest
+ script:
+ - setup_test_db
+ - cp -R . /tmp/app
+ - /bin/herokuish buildpack test
+ only:
+ - branches
+ except:
+ variables:
+ - $TEST_DISABLED
+
+code_quality:
+ stage: test
+ image: docker:stable
+ allow_failure: true
+ services:
+ - docker:stable-dind
+ script:
+ - setup_docker
+ - code_quality
+ artifacts:
+ paths: [gl-code-quality-report.json]
+ only:
+ - branches
+ except:
+ variables:
+ - $CODE_QUALITY_DISABLED
+
+license_management:
+ stage: test
+ image:
+ name: "registry.gitlab.com/gitlab-org/security-products/license-management:$CI_SERVER_VERSION_MAJOR-$CI_SERVER_VERSION_MINOR-stable"
+ entrypoint: [""]
+ allow_failure: true
+ script:
+ - license_management
+ artifacts:
+ paths: [gl-license-management-report.json]
+ only:
+ refs:
+ - branches
+ variables:
+ - $GITLAB_FEATURES =~ /\blicense_management\b/
+ except:
+ variables:
+ - $LICENSE_MANAGEMENT_DISABLED
+
+performance:
+ stage: performance
+ image: docker:stable
+ allow_failure: true
+ services:
+ - docker:stable-dind
+ script:
+ - setup_docker
+ - performance
+ artifacts:
+ paths:
+ - performance.json
+ - sitespeed-results/
+ only:
+ refs:
+ - branches
+ except:
+ variables:
+ - $PERFORMANCE_DISABLED
+ - $KUBECONFIG == null
+
+sast:
+ stage: test
+ image: docker:stable
+ allow_failure: true
+ services:
+ - docker:stable-dind
+ script:
+ - setup_docker
+ - sast
+ artifacts:
+ paths: [gl-sast-report.json]
+ only:
+ refs:
+ - branches
+ variables:
+ - $GITLAB_FEATURES =~ /\bsast\b/
+ except:
+ variables:
+ - $SAST_DISABLED
+
+dependency_scanning:
+ stage: test
+ image: docker:stable
+ allow_failure: true
+ services:
+ - docker:stable-dind
+ script:
+ - setup_docker
+ - dependency_scanning
+ artifacts:
+ paths: [gl-dependency-scanning-report.json]
+ only:
+ refs:
+ - branches
+ variables:
+ - $GITLAB_FEATURES =~ /\bdependency_scanning\b/
+ except:
+ variables:
+ - $DEPENDENCY_SCANNING_DISABLED
+
+container_scanning:
+ stage: test
+ image: docker:stable
+ allow_failure: true
+ services:
+ - docker:stable-dind
+ script:
+ - setup_docker
+ - container_scanning
+ artifacts:
+ paths: [gl-container-scanning-report.json]
+ only:
+ refs:
+ - branches
+ variables:
+ - $GITLAB_FEATURES =~ /\bcontainer_scanning\b/
+ except:
+ variables:
+ - $CONTAINER_SCANNING_DISABLED
+
+dast:
+ stage: dast
+ allow_failure: true
+ image: registry.gitlab.com/gitlab-org/security-products/zaproxy
+ variables:
+ POSTGRES_DB: "false"
+ script:
+ - dast
+ artifacts:
+ paths: [gl-dast-report.json]
+ only:
+ refs:
+ - branches
+ variables:
+ - $GITLAB_FEATURES =~ /\bdast\b/
+ except:
+ refs:
+ - master
+ variables:
+ - $DAST_DISABLED
+ - $KUBECONFIG == null
+
+review:
+ stage: review
+ script:
+ - check_kube_domain
+ - install_dependencies
+ - download_chart
+ - ensure_namespace
+ - initialize_tiller
+ - create_secret
+ - deploy
+ - persist_environment_url
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ url: http://$CI_PROJECT_PATH_SLUG-$CI_ENVIRONMENT_SLUG.$AUTO_DEVOPS_DOMAIN
+ on_stop: stop_review
+ artifacts:
+ paths: [environment_url.txt]
+ only:
+ refs:
+ - branches
+ except:
+ refs:
+ - master
+ variables:
+ - $REVIEW_DISABLED
+ - $KUBECONFIG == null
+
+stop_review:
+ stage: cleanup
+ variables:
+ GIT_STRATEGY: none
+ script:
+ - install_dependencies
+ - initialize_tiller
+ - delete
+ environment:
+ name: review/$CI_COMMIT_REF_NAME
+ action: stop
+ when: manual
+ allow_failure: true
+ only:
+ refs:
+ - branches
+ except:
+ refs:
+ - master
+ variables:
+ - $REVIEW_DISABLED
+ - $KUBECONFIG == null
+
+# Staging deploys are disabled by default since
+# continuous deployment to production is enabled by default
+# If you prefer to automatically deploy to staging and
+# only manually promote to production, enable this job by setting
+# STAGING_ENABLED.
+
+staging:
+ stage: staging
+ script:
+ - check_kube_domain
+ - install_dependencies
+ - download_chart
+ - ensure_namespace
+ - initialize_tiller
+ - create_secret
+ - deploy
+ environment:
+ name: staging
+ url: http://$CI_PROJECT_PATH_SLUG-staging.$AUTO_DEVOPS_DOMAIN
+ only:
+ refs:
+ - master
+ variables:
+ - $STAGING_ENABLED
+ except:
+ variables:
+ - $KUBECONFIG == null
+
+# Canaries are also disabled by default, but if you want them,
+# and know what the downsides are, you can enable this by setting
+# CANARY_ENABLED.
+
+canary:
+ stage: canary
+ script:
+ - check_kube_domain
+ - install_dependencies
+ - download_chart
+ - ensure_namespace
+ - initialize_tiller
+ - create_secret
+ - deploy canary
+ environment:
+ name: production
+ url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN
+ when: manual
+ only:
+ refs:
+ - master
+ variables:
+ - $CANARY_ENABLED
+ except:
+ variables:
+ - $KUBECONFIG == null
+
+.production: &production_template
+ stage: production
+ script:
+ - check_kube_domain
+ - install_dependencies
+ - download_chart
+ - ensure_namespace
+ - initialize_tiller
+ - create_secret
+ - deploy
+ - delete canary
+ - delete rollout
+ - persist_environment_url
+ environment:
+ name: production
+ url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN
+ artifacts:
+ paths: [environment_url.txt]
+
+production:
+ <<: *production_template
+ only:
+ refs:
+ - master
+ except:
+ variables:
+ - $STAGING_ENABLED
+ - $CANARY_ENABLED
+ - $INCREMENTAL_ROLLOUT_ENABLED
+ - $INCREMENTAL_ROLLOUT_MODE
+ - $KUBECONFIG == null
+
+production_manual:
+ <<: *production_template
+ when: manual
+ allow_failure: false
+ only:
+ refs:
+ - master
+ variables:
+ - $STAGING_ENABLED
+ - $CANARY_ENABLED
+ except:
+ variables:
+ - $INCREMENTAL_ROLLOUT_ENABLED
+ - $INCREMENTAL_ROLLOUT_MODE
+ - $KUBECONFIG == null
+
+# This job implements incremental rollout on for every push to `master`.
+
+.rollout: &rollout_template
+ script:
+ - check_kube_domain
+ - install_dependencies
+ - download_chart
+ - ensure_namespace
+ - initialize_tiller
+ - create_secret
+ - deploy rollout $ROLLOUT_PERCENTAGE
+ - scale stable $((100-ROLLOUT_PERCENTAGE))
+ - delete canary
+ - persist_environment_url
+ environment:
+ name: production
+ url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN
+ artifacts:
+ paths: [environment_url.txt]
+
+.manual_rollout_template: &manual_rollout_template
+ <<: *rollout_template
+ stage: production
+ when: manual
+ # This selectors are backward compatible mode with $INCREMENTAL_ROLLOUT_ENABLED (before 11.4)
+ only:
+ refs:
+ - master
+ variables:
+ - $INCREMENTAL_ROLLOUT_MODE == "manual"
+ - $INCREMENTAL_ROLLOUT_ENABLED
+ except:
+ variables:
+ - $INCREMENTAL_ROLLOUT_MODE == "timed"
+ - $KUBECONFIG == null
+
+.timed_rollout_template: &timed_rollout_template
+ <<: *rollout_template
+ when: delayed
+ start_in: 5 minutes
+ only:
+ refs:
+ - master
+ variables:
+ - $INCREMENTAL_ROLLOUT_MODE == "timed"
+ except:
+ variables:
+ - $KUBECONFIG == null
+
+timed rollout 10%:
+ <<: *timed_rollout_template
+ stage: incremental rollout 10%
+ variables:
+ ROLLOUT_PERCENTAGE: 10
+
+timed rollout 25%:
+ <<: *timed_rollout_template
+ stage: incremental rollout 25%
+ variables:
+ ROLLOUT_PERCENTAGE: 25
+
+timed rollout 50%:
+ <<: *timed_rollout_template
+ stage: incremental rollout 50%
+ variables:
+ ROLLOUT_PERCENTAGE: 50
+
+timed rollout 100%:
+ <<: *timed_rollout_template
+ <<: *production_template
+ stage: incremental rollout 100%
+ variables:
+ ROLLOUT_PERCENTAGE: 100
+
+rollout 10%:
+ <<: *manual_rollout_template
+ variables:
+ ROLLOUT_PERCENTAGE: 10
+
+rollout 25%:
+ <<: *manual_rollout_template
+ variables:
+ ROLLOUT_PERCENTAGE: 25
+
+rollout 50%:
+ <<: *manual_rollout_template
+ variables:
+ ROLLOUT_PERCENTAGE: 50
+
+rollout 100%:
+ <<: *manual_rollout_template
+ <<: *production_template
+ allow_failure: false
+
+# ---------------------------------------------------------------------------
+
+.auto_devops: &auto_devops |
+ # Auto DevOps variables and functions
+ [[ "$TRACE" ]] && set -x
+ auto_database_url=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${CI_ENVIRONMENT_SLUG}-postgres:5432/${POSTGRES_DB}
+ export DATABASE_URL=${DATABASE_URL-$auto_database_url}
+ export CI_APPLICATION_REPOSITORY=$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
+ export CI_APPLICATION_TAG=$CI_COMMIT_SHA
+ export CI_CONTAINER_NAME=ci_job_build_${CI_JOB_ID}
+ export TILLER_NAMESPACE=$KUBE_NAMESPACE
+ # Extract "MAJOR.MINOR" from CI_SERVER_VERSION and generate "MAJOR-MINOR-stable" for Security Products
+ export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
+
+ function registry_login() {
+ if [[ -n "$CI_REGISTRY_USER" ]]; then
+ echo "Logging to GitLab Container Registry with CI credentials..."
+ docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
+ echo ""
+ fi
+ }
+
+ function container_scanning() {
+ registry_login
+
+ docker run -d --name db arminc/clair-db:latest
+ docker run -p 6060:6060 --link db:postgres -d --name clair --restart on-failure arminc/clair-local-scan:v2.0.1
+ apk add -U wget ca-certificates
+ docker pull ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG}
+ wget https://github.com/arminc/clair-scanner/releases/download/v8/clair-scanner_linux_amd64
+ mv clair-scanner_linux_amd64 clair-scanner
+ chmod +x clair-scanner
+ touch clair-whitelist.yml
+ retries=0
+ echo "Waiting for clair daemon to start"
+ while( ! wget -T 10 -q -O /dev/null http://docker:6060/v1/namespaces ) ; do sleep 1 ; echo -n "." ; if [ $retries -eq 10 ] ; then echo " Timeout, aborting." ; exit 1 ; fi ; retries=$(($retries+1)) ; done
+ ./clair-scanner -c http://docker:6060 --ip $(hostname -i) -r gl-container-scanning-report.json -l clair.log -w clair-whitelist.yml ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG} || true
+ }
+
+ function code_quality() {
+ docker run --env SOURCE_CODE="$PWD" \
+ --volume "$PWD":/code \
+ --volume /var/run/docker.sock:/var/run/docker.sock \
+ "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
+ }
+
+ function license_management() {
+ /run.sh analyze .
+ }
+
+ function sast() {
+ case "$CI_SERVER_VERSION" in
+ *-ee)
+
+ # Deprecation notice for CONFIDENCE_LEVEL variable
+ if [ -z "$SAST_CONFIDENCE_LEVEL" -a "$CONFIDENCE_LEVEL" ]; then
+ SAST_CONFIDENCE_LEVEL="$CONFIDENCE_LEVEL"
+ echo "WARNING: CONFIDENCE_LEVEL is deprecated and MUST be replaced with SAST_CONFIDENCE_LEVEL"
+ fi
+
+ docker run --env SAST_CONFIDENCE_LEVEL="${SAST_CONFIDENCE_LEVEL:-3}" \
+ --volume "$PWD:/code" \
+ --volume /var/run/docker.sock:/var/run/docker.sock \
+ "registry.gitlab.com/gitlab-org/security-products/sast:$SP_VERSION" /app/bin/run /code
+ ;;
+ *)
+ echo "GitLab EE is required"
+ ;;
+ esac
+ }
+
+ function dependency_scanning() {
+ case "$CI_SERVER_VERSION" in
+ *-ee)
+ docker run --env DEP_SCAN_DISABLE_REMOTE_CHECKS="${DEP_SCAN_DISABLE_REMOTE_CHECKS:-false}" \
+ --volume "$PWD:/code" \
+ --volume /var/run/docker.sock:/var/run/docker.sock \
+ "registry.gitlab.com/gitlab-org/security-products/dependency-scanning:$SP_VERSION" /code
+ ;;
+ *)
+ echo "GitLab EE is required"
+ ;;
+ esac
+ }
+
+ function get_replicas() {
+ track="${1:-stable}"
+ percentage="${2:-100}"
+
+ env_track=$( echo $track | tr -s '[:lower:]' '[:upper:]' )
+ env_slug=$( echo ${CI_ENVIRONMENT_SLUG//-/_} | tr -s '[:lower:]' '[:upper:]' )
+
+ if [[ "$track" == "stable" ]] || [[ "$track" == "rollout" ]]; then
+ # for stable track get number of replicas from `PRODUCTION_REPLICAS`
+ eval new_replicas=\$${env_slug}_REPLICAS
+ if [[ -z "$new_replicas" ]]; then
+ new_replicas=$REPLICAS
+ fi
+ else
+ # for all tracks get number of replicas from `CANARY_PRODUCTION_REPLICAS`
+ eval new_replicas=\$${env_track}_${env_slug}_REPLICAS
+ if [[ -z "$new_replicas" ]]; then
+ eval new_replicas=\${env_track}_REPLICAS
+ fi
+ fi
+
+ replicas="${new_replicas:-1}"
+ replicas="$(($replicas * $percentage / 100))"
+
+ # always return at least one replicas
+ if [[ $replicas -gt 0 ]]; then
+ echo "$replicas"
+ else
+ echo 1
+ fi
+ }
+
+ function deploy() {
+ track="${1-stable}"
+ percentage="${2:-100}"
+ name="$CI_ENVIRONMENT_SLUG"
+
+ replicas="1"
+ service_enabled="true"
+ postgres_enabled="$POSTGRES_ENABLED"
+
+ # if track is different than stable,
+ # re-use all attached resources
+ if [[ "$track" != "stable" ]]; then
+ name="$name-$track"
+ service_enabled="false"
+ postgres_enabled="false"
+ fi
+
+ replicas=$(get_replicas "$track" "$percentage")
+
+ if [[ "$CI_PROJECT_VISIBILITY" != "public" ]]; then
+ secret_name='gitlab-registry'
+ else
+ secret_name=''
+ fi
+
+ if [[ -n "$DB_INITIALIZE" && -z "$(helm ls -q "^$name$")" ]]; then
+ echo "Deploying first release with database initialization..."
+ helm upgrade --install \
+ --wait \
+ --set service.enabled="$service_enabled" \
+ --set releaseOverride="$CI_ENVIRONMENT_SLUG" \
+ --set image.repository="$CI_APPLICATION_REPOSITORY" \
+ --set image.tag="$CI_APPLICATION_TAG" \
+ --set image.pullPolicy=IfNotPresent \
+ --set image.secrets[0].name="$secret_name" \
+ --set application.track="$track" \
+ --set application.database_url="$DATABASE_URL" \
+ --set service.url="$CI_ENVIRONMENT_URL" \
+ --set replicaCount="$replicas" \
+ --set postgresql.enabled="$postgres_enabled" \
+ --set postgresql.nameOverride="postgres" \
+ --set postgresql.postgresUser="$POSTGRES_USER" \
+ --set postgresql.postgresPassword="$POSTGRES_PASSWORD" \
+ --set postgresql.postgresDatabase="$POSTGRES_DB" \
+ --set application.initializeCommand="$DB_INITIALIZE" \
+ --namespace="$KUBE_NAMESPACE" \
+ "$name" \
+ chart/
+
+ echo "Deploying second release..."
+ helm upgrade --reuse-values \
+ --wait \
+ --set application.initializeCommand="" \
+ --set application.migrateCommand="$DB_MIGRATE" \
+ --namespace="$KUBE_NAMESPACE" \
+ "$name" \
+ chart/
+ else
+ echo "Deploying new release..."
+ helm upgrade --install \
+ --wait \
+ --set service.enabled="$service_enabled" \
+ --set releaseOverride="$CI_ENVIRONMENT_SLUG" \
+ --set image.repository="$CI_APPLICATION_REPOSITORY" \
+ --set image.tag="$CI_APPLICATION_TAG" \
+ --set image.pullPolicy=IfNotPresent \
+ --set image.secrets[0].name="$secret_name" \
+ --set application.track="$track" \
+ --set application.database_url="$DATABASE_URL" \
+ --set service.url="$CI_ENVIRONMENT_URL" \
+ --set replicaCount="$replicas" \
+ --set postgresql.enabled="$postgres_enabled" \
+ --set postgresql.nameOverride="postgres" \
+ --set postgresql.postgresUser="$POSTGRES_USER" \
+ --set postgresql.postgresPassword="$POSTGRES_PASSWORD" \
+ --set postgresql.postgresDatabase="$POSTGRES_DB" \
+ --set application.migrateCommand="$DB_MIGRATE" \
+ --namespace="$KUBE_NAMESPACE" \
+ "$name" \
+ chart/
+ fi
+
+ kubectl rollout status -n "$KUBE_NAMESPACE" -w "deployment/$name"
+ }
+
+ function scale() {
+ track="${1-stable}"
+ percentage="${2-100}"
+ name="$CI_ENVIRONMENT_SLUG"
+
+ if [[ "$track" != "stable" ]]; then
+ name="$name-$track"
+ fi
+
+ replicas=$(get_replicas "$track" "$percentage")
+
+ if [[ -n "$(helm ls -q "^$name$")" ]]; then
+ helm upgrade --reuse-values \
+ --wait \
+ --set replicaCount="$replicas" \
+ --namespace="$KUBE_NAMESPACE" \
+ "$name" \
+ chart/
+ fi
+ }
+
+ function install_dependencies() {
+ apk add -U openssl curl tar gzip bash ca-certificates git
+ curl -L -o /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub
+ curl -L -O https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.28-r0/glibc-2.28-r0.apk
+ apk add glibc-2.28-r0.apk
+ rm glibc-2.28-r0.apk
+
+ curl "https://kubernetes-helm.storage.googleapis.com/helm-v${HELM_VERSION}-linux-amd64.tar.gz" | tar zx
+ mv linux-amd64/helm /usr/bin/
+ mv linux-amd64/tiller /usr/bin/
+ helm version --client
+ tiller -version
+
+ curl -L -o /usr/bin/kubectl "https://storage.googleapis.com/kubernetes-release/release/v${KUBERNETES_VERSION}/bin/linux/amd64/kubectl"
+ chmod +x /usr/bin/kubectl
+ kubectl version --client
+ }
+
+ function setup_docker() {
+ if ! docker info &>/dev/null; then
+ if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then
+ export DOCKER_HOST='tcp://localhost:2375'
+ fi
+ fi
+ }
+
+ function setup_test_db() {
+ if [ -z ${KUBERNETES_PORT+x} ]; then
+ DB_HOST=postgres
+ else
+ DB_HOST=localhost
+ fi
+ export DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${DB_HOST}:5432/${POSTGRES_DB}"
+ }
+
+ function download_chart() {
+ if [[ ! -d chart ]]; then
+ auto_chart=${AUTO_DEVOPS_CHART:-gitlab/auto-deploy-app}
+ auto_chart_name=$(basename $auto_chart)
+ auto_chart_name=${auto_chart_name%.tgz}
+ auto_chart_name=${auto_chart_name%.tar.gz}
+ else
+ auto_chart="chart"
+ auto_chart_name="chart"
+ fi
+
+ helm init --client-only
+ helm repo add gitlab https://charts.gitlab.io
+ if [[ ! -d "$auto_chart" ]]; then
+ helm fetch ${auto_chart} --untar
+ fi
+ if [ "$auto_chart_name" != "chart" ]; then
+ mv ${auto_chart_name} chart
+ fi
+
+ helm dependency update chart/
+ helm dependency build chart/
+ }
+
+ function ensure_namespace() {
+ kubectl describe namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE"
+ }
+
+ function check_kube_domain() {
+ if [ -z ${AUTO_DEVOPS_DOMAIN+x} ]; then
+ echo "In order to deploy or use Review Apps, AUTO_DEVOPS_DOMAIN variable must be set"
+ echo "You can do it in Auto DevOps project settings or defining a variable at group or project level"
+ echo "You can also manually add it in .gitlab-ci.yml"
+ false
+ else
+ true
+ fi
+ }
+
+ function build() {
+ registry_login
+
+ if [[ -f Dockerfile ]]; then
+ echo "Building Dockerfile-based application..."
+ docker build \
+ --build-arg HTTP_PROXY="$HTTP_PROXY" \
+ --build-arg http_proxy="$http_proxy" \
+ --build-arg HTTPS_PROXY="$HTTPS_PROXY" \
+ --build-arg https_proxy="$https_proxy" \
+ --build-arg FTP_PROXY="$FTP_PROXY" \
+ --build-arg ftp_proxy="$ftp_proxy" \
+ --build-arg NO_PROXY="$NO_PROXY" \
+ --build-arg no_proxy="$no_proxy" \
+ -t "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" .
+ else
+ echo "Building Heroku-based application using gliderlabs/herokuish docker image..."
+ docker run -i \
+ -e BUILDPACK_URL \
+ -e HTTP_PROXY \
+ -e http_proxy \
+ -e HTTPS_PROXY \
+ -e https_proxy \
+ -e FTP_PROXY \
+ -e ftp_proxy \
+ -e NO_PROXY \
+ -e no_proxy \
+ --name="$CI_CONTAINER_NAME" -v "$(pwd):/tmp/app:ro" gliderlabs/herokuish /bin/herokuish buildpack build
+ docker commit "$CI_CONTAINER_NAME" "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG"
+ docker rm "$CI_CONTAINER_NAME" >/dev/null
+ echo ""
+
+ echo "Configuring $CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG docker image..."
+ docker create --expose 5000 --env PORT=5000 --name="$CI_CONTAINER_NAME" "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" /bin/herokuish procfile start web
+ docker commit "$CI_CONTAINER_NAME" "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG"
+ docker rm "$CI_CONTAINER_NAME" >/dev/null
+ echo ""
+ fi
+
+ echo "Pushing to GitLab Container Registry..."
+ docker push "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG"
+ echo ""
+ }
+
+ function initialize_tiller() {
+ echo "Checking Tiller..."
+
+ export HELM_HOST="localhost:44134"
+ tiller -listen ${HELM_HOST} -alsologtostderr > /dev/null 2>&1 &
+ echo "Tiller is listening on ${HELM_HOST}"
+
+ if ! helm version --debug; then
+ echo "Failed to init Tiller."
+ return 1
+ fi
+ echo ""
+ }
+
+ function create_secret() {
+ echo "Create secret..."
+ if [[ "$CI_PROJECT_VISIBILITY" == "public" ]]; then
+ return
+ fi
+
+ kubectl create secret -n "$KUBE_NAMESPACE" \
+ docker-registry gitlab-registry \
+ --docker-server="$CI_REGISTRY" \
+ --docker-username="${CI_DEPLOY_USER:-$CI_REGISTRY_USER}" \
+ --docker-password="${CI_DEPLOY_PASSWORD:-$CI_REGISTRY_PASSWORD}" \
+ --docker-email="$GITLAB_USER_EMAIL" \
+ -o yaml --dry-run | kubectl replace -n "$KUBE_NAMESPACE" --force -f -
+ }
+
+ function dast() {
+ export CI_ENVIRONMENT_URL=$(cat environment_url.txt)
+
+ mkdir /zap/wrk/
+ /zap/zap-baseline.py -J gl-dast-report.json -t "$CI_ENVIRONMENT_URL" || true
+ cp /zap/wrk/gl-dast-report.json .
+ }
+
+ function performance() {
+ export CI_ENVIRONMENT_URL=$(cat environment_url.txt)
+
+ mkdir gitlab-exporter
+ wget -O gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/10-5/index.js
+
+ mkdir sitespeed-results
+
+ if [ -f .gitlab-urls.txt ]
+ then
+ sed -i -e 's@^@'"$CI_ENVIRONMENT_URL"'@' .gitlab-urls.txt
+ docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:6.3.1 --plugins.add ./gitlab-exporter --outputFolder sitespeed-results .gitlab-urls.txt
+ else
+ docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:6.3.1 --plugins.add ./gitlab-exporter --outputFolder sitespeed-results "$CI_ENVIRONMENT_URL"
+ fi
+
+ mv sitespeed-results/data/performance.json performance.json
+ }
+
+ function persist_environment_url() {
+ echo $CI_ENVIRONMENT_URL > environment_url.txt
+ }
+
+ function delete() {
+ track="${1-stable}"
+ name="$CI_ENVIRONMENT_SLUG"
+
+ if [[ "$track" != "stable" ]]; then
+ name="$name-$track"
+ fi
+
+ if [[ -n "$(helm ls -q "^$name$")" ]]; then
+ helm delete --purge "$name"
+ fi
+ }
+
+before_script:
+ - *auto_devops
diff --git a/vendor/gitlab-ci-yml/Bash.gitlab-ci.yml b/lib/gitlab/ci/templates/Bash.gitlab-ci.yml
index 2d218b2e164..2d218b2e164 100644
--- a/vendor/gitlab-ci-yml/Bash.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Bash.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/C++.gitlab-ci.yml b/lib/gitlab/ci/templates/C++.gitlab-ci.yml
index c83c49d8c95..c83c49d8c95 100644
--- a/vendor/gitlab-ci-yml/C++.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/C++.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Chef.gitlab-ci.yml b/lib/gitlab/ci/templates/Chef.gitlab-ci.yml
index 4d5b6484d6e..4d5b6484d6e 100644
--- a/vendor/gitlab-ci-yml/Chef.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Chef.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Clojure.gitlab-ci.yml b/lib/gitlab/ci/templates/Clojure.gitlab-ci.yml
index f066285b1ad..f066285b1ad 100644
--- a/vendor/gitlab-ci-yml/Clojure.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Clojure.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Crystal.gitlab-ci.yml b/lib/gitlab/ci/templates/Crystal.gitlab-ci.yml
index 36386a19fdc..36386a19fdc 100644
--- a/vendor/gitlab-ci-yml/Crystal.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Crystal.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Django.gitlab-ci.yml b/lib/gitlab/ci/templates/Django.gitlab-ci.yml
index 57afcbbe8b5..57afcbbe8b5 100644
--- a/vendor/gitlab-ci-yml/Django.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Django.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Docker.gitlab-ci.yml b/lib/gitlab/ci/templates/Docker.gitlab-ci.yml
index eeefadaa019..eeefadaa019 100644
--- a/vendor/gitlab-ci-yml/Docker.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Docker.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Elixir.gitlab-ci.yml b/lib/gitlab/ci/templates/Elixir.gitlab-ci.yml
index cf9c731637c..cf9c731637c 100644
--- a/vendor/gitlab-ci-yml/Elixir.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Elixir.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Go.gitlab-ci.yml b/lib/gitlab/ci/templates/Go.gitlab-ci.yml
index d572d7a1edc..d572d7a1edc 100644
--- a/vendor/gitlab-ci-yml/Go.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Go.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Gradle.gitlab-ci.yml b/lib/gitlab/ci/templates/Gradle.gitlab-ci.yml
index 48d98dddfad..48d98dddfad 100644
--- a/vendor/gitlab-ci-yml/Gradle.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Gradle.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Grails.gitlab-ci.yml b/lib/gitlab/ci/templates/Grails.gitlab-ci.yml
index 7fc698d50cf..7fc698d50cf 100644
--- a/vendor/gitlab-ci-yml/Grails.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Grails.gitlab-ci.yml
diff --git a/lib/gitlab/ci/templates/Julia.gitlab-ci.yml b/lib/gitlab/ci/templates/Julia.gitlab-ci.yml
new file mode 100644
index 00000000000..04c21b4725d
--- /dev/null
+++ b/lib/gitlab/ci/templates/Julia.gitlab-ci.yml
@@ -0,0 +1,76 @@
+# This is an example .gitlab-ci.yml file to test (and optionally report the coverage
+# results of) your [Julia][1] packages. Please refer to the [documentation][2]
+# for more information about package development in Julia.
+#
+# Here, it is assumed that your Julia package is named `MyPackage`. Change it to
+# whatever name you have given to your package.
+#
+# [1]: http://julialang.org/
+# [2]: https://docs.julialang.org/en/v1/manual/documentation/index.html
+
+# Below is the template to run your tests in Julia
+.test_template: &test_definition
+ # Uncomment below if you would like to run the tests on specific references
+ # only, such as the branches `master`, `development`, etc.
+ # only:
+ # - master
+ # - development
+ script:
+ # Let's run the tests. Substitute `coverage = false` below, if you do not
+ # want coverage results.
+ - julia -e 'using Pkg; Pkg.clone(pwd()); Pkg.build("MyPackage"); Pkg.test("MyPackage"; coverage = true)'
+ # Comment out below if you do not want coverage results.
+ - julia -e 'using Pkg; Pkg.add("Coverage");
+ import MyPackage; cd(joinpath(dirname(pathof(MyPackage)), ".."));
+ using Coverage; cl, tl = get_summary(process_folder());
+ println("(", cl/tl*100, "%) covered")'
+
+# Name a test and select an appropriate image.
+# images comes from Docker hub
+test:0.7:
+ image: julia:0.7
+ <<: *test_definition
+
+test:1.0:
+ image: julia:1.0
+ <<: *test_definition
+
+# Maybe you would like to test your package against the development branch:
+# test:1.1-dev (not sure there is such an image in docker, so not tested yet):
+# image: julia:v1.1-dev
+# # ... allowing for failures, since we are testing against the development
+# # branch:
+# allow_failure: true
+# <<: *test_definition
+
+# REMARK: Do not forget to enable the coverage feature for your project, if you
+# are using code coverage reporting above. This can be done by
+#
+# - Navigating to the `CI/CD Pipelines` settings of your project,
+# - Copying and pasting the default `Simplecov` regex example provided, i.e.,
+# `\(\d+.\d+\%\) covered` in the `test coverage parsing` textfield.
+
+# Example documentation deployment
+pages:
+ image: julia:0.7
+ stage: deploy
+ script:
+ - apt-get update -qq && apt-get install -y git # needed by Documenter
+ - julia -e 'using Pkg; Pkg.clone(pwd()); Pkg.build("MyPackage");' # rebuild Julia (can be put somewhere else I'm sure
+ - julia -e 'using Pkg; import MyPackage; Pkg.add("Documenter")' # install Documenter
+ - julia --color=yes docs/make.jl # make documentation
+ - mv docs/build public # move to the directory picked up by Gitlab pages
+ artifacts:
+ paths:
+ - public
+ only:
+ - master
+
+
+# WARNING: This template is using the `julia` images from [Docker
+# Hub][3]. One can use custom Julia images and/or the official ones found
+# in the same place. However, care must be taken to correctly locate the binary
+# file (`/opt/julia/bin/julia` above), which is usually given on the image's
+# description page.
+#
+# [3]: https://hub.docker.com/_/julia/
diff --git a/vendor/gitlab-ci-yml/LaTeX.gitlab-ci.yml b/lib/gitlab/ci/templates/LaTeX.gitlab-ci.yml
index a4aed36889e..a4aed36889e 100644
--- a/vendor/gitlab-ci-yml/LaTeX.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/LaTeX.gitlab-ci.yml
diff --git a/lib/gitlab/ci/templates/Laravel.gitlab-ci.yml b/lib/gitlab/ci/templates/Laravel.gitlab-ci.yml
new file mode 100644
index 00000000000..d0cad285572
--- /dev/null
+++ b/lib/gitlab/ci/templates/Laravel.gitlab-ci.yml
@@ -0,0 +1,85 @@
+# Official framework image. Look for the different tagged releases at:
+# https://hub.docker.com/r/library/php
+image: php:latest
+
+# Pick zero or more services to be used on all builds.
+# Only needed when using a docker container to run your tests in.
+# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service
+services:
+ - mysql:latest
+
+variables:
+ MYSQL_DATABASE: project_name
+ MYSQL_ROOT_PASSWORD: secret
+
+# This folder is cached between builds
+# http://docs.gitlab.com/ce/ci/yaml/README.html#cache
+cache:
+ paths:
+ - vendor/
+ - node_modules/
+
+# This is a basic example for a gem or script which doesn't use
+# services such as redis or postgres
+before_script:
+ # Update packages
+ - apt-get update -yqq
+
+ # Prep for Node
+ - apt-get install gnupg -yqq
+
+ # Upgrade to Node 8
+ - curl -sL https://deb.nodesource.com/setup_8.x | bash -
+
+ # Install dependencies
+ - apt-get install git nodejs libcurl4-gnutls-dev libicu-dev libmcrypt-dev libvpx-dev libjpeg-dev libpng-dev libxpm-dev zlib1g-dev libfreetype6-dev libxml2-dev libexpat1-dev libbz2-dev libgmp3-dev libldap2-dev unixodbc-dev libpq-dev libsqlite3-dev libaspell-dev libsnmp-dev libpcre3-dev libtidy-dev -yqq
+
+ # Install php extensions
+ - docker-php-ext-install mbstring pdo_mysql curl json intl gd xml zip bz2 opcache
+
+ # Install & enable Xdebug for code coverage reports
+ - pecl install xdebug
+ - docker-php-ext-enable xdebug
+
+ # Install Composer and project dependencies.
+ - curl -sS https://getcomposer.org/installer | php
+ - php composer.phar install
+
+ # Install Node dependencies.
+ # comment this out if you don't have a node dependency
+ - npm install
+
+ # Copy over testing configuration.
+ # Don't forget to set the database config in .env.testing correctly
+ # DB_HOST=mysql
+ # DB_DATABASE=project_name
+ # DB_USERNAME=root
+ # DB_PASSWORD=secret
+ - cp .env.testing .env
+
+ # Run npm build
+ # comment this out if you don't have a frontend build
+ # you can change this to to your frontend building script like
+ # npm run build
+ - npm run dev
+
+ # Generate an application key. Re-cache.
+ - php artisan key:generate
+ - php artisan config:cache
+
+ # Run database migrations.
+ - php artisan migrate
+
+ # Run database seed
+ - php artisan db:seed
+
+test:
+ script:
+ # run laravel tests
+ - php vendor/bin/phpunit --coverage-text --colors=never
+
+ # run frontend tests
+ # if you have any task for testing frontend
+ # set it in your package.json script
+ # comment this out if you don't have a frontend test
+ - npm test
diff --git a/lib/gitlab/ci/templates/Maven.gitlab-ci.yml b/lib/gitlab/ci/templates/Maven.gitlab-ci.yml
new file mode 100644
index 00000000000..492b3d03db2
--- /dev/null
+++ b/lib/gitlab/ci/templates/Maven.gitlab-ci.yml
@@ -0,0 +1,102 @@
+---
+# Build JAVA applications using Apache Maven (http://maven.apache.org)
+# For docker image tags see https://hub.docker.com/_/maven/
+#
+# For general lifecycle information see https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
+#
+# This template will build and test your projects as well as create the documentation.
+#
+# * Caches downloaded dependencies and plugins between invocation.
+# * Verify but don't deploy merge requests.
+# * Deploy built artifacts from master branch only.
+# * Shows how to use multiple jobs in test stage for verifying functionality
+# with multiple JDKs.
+# * Uses site:stage to collect the documentation for multi-module projects.
+# * Publishes the documentation for `master` branch.
+
+variables:
+ # This will suppress any download for dependencies and plugins or upload messages which would clutter the console log.
+ # `showDateTime` will show the passed time in milliseconds. You need to specify `--batch-mode` to make this work.
+ MAVEN_OPTS: "-Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true"
+ # As of Maven 3.3.0 instead of this you may define these options in `.mvn/maven.config` so the same config is used
+ # when running from the command line.
+ # `installAtEnd` and `deployAtEnd` are only effective with recent version of the corresponding plugins.
+ MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true"
+
+# Cache downloaded dependencies and plugins between builds.
+# To keep cache across branches add 'key: "$CI_JOB_NAME"'
+cache:
+ paths:
+ - .m2/repository
+
+# This will only validate and compile stuff and run e.g. maven-enforcer-plugin.
+# Because some enforcer rules might check dependency convergence and class duplications
+# we use `test-compile` here instead of `validate`, so the correct classpath is picked up.
+.validate: &validate
+ stage: build
+ script:
+ - 'mvn $MAVEN_CLI_OPTS test-compile'
+
+# For merge requests do not `deploy` but only run `verify`.
+# See https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
+.verify: &verify
+ stage: test
+ script:
+ - 'mvn $MAVEN_CLI_OPTS verify site site:stage'
+ except:
+ - master
+
+# Validate merge requests using JDK7
+validate:jdk7:
+ <<: *validate
+ image: maven:3.3.9-jdk-7
+
+# Validate merge requests using JDK8
+validate:jdk8:
+ <<: *validate
+ image: maven:3.3.9-jdk-8
+
+# Verify merge requests using JDK7
+verify:jdk7:
+ <<: *verify
+ image: maven:3.3.9-jdk-7
+
+# Verify merge requests using JDK8
+verify:jdk8:
+ <<: *verify
+ image: maven:3.3.9-jdk-8
+
+
+# For `master` branch run `mvn deploy` automatically.
+# Here you need to decide whether you want to use JDK7 or 8.
+# To get this working you need to define a volume while configuring your gitlab-ci-multi-runner.
+# Mount your `settings.xml` as `/root/.m2/settings.xml` which holds your secrets.
+# See https://maven.apache.org/settings.html
+deploy:jdk8:
+ # Use stage test here, so the pages job may later pickup the created site.
+ stage: test
+ script:
+ - 'mvn $MAVEN_CLI_OPTS deploy site site:stage'
+ only:
+ - master
+ # Archive up the built documentation site.
+ artifacts:
+ paths:
+ - target/staging
+ image: maven:3.3.9-jdk-8
+
+
+pages:
+ image: busybox:latest
+ stage: deploy
+ script:
+ # Because Maven appends the artifactId automatically to the staging path if you did define a parent pom,
+ # you might need to use `mv target/staging/YOUR_ARTIFACT_ID public` instead.
+ - mv target/staging public
+ dependencies:
+ - deploy:jdk8
+ artifacts:
+ paths:
+ - public
+ only:
+ - master
diff --git a/vendor/gitlab-ci-yml/Mono.gitlab-ci.yml b/lib/gitlab/ci/templates/Mono.gitlab-ci.yml
index 3585f99760f..3585f99760f 100644
--- a/vendor/gitlab-ci-yml/Mono.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Mono.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Nodejs.gitlab-ci.yml b/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml
index 41de1458582..41de1458582 100644
--- a/vendor/gitlab-ci-yml/Nodejs.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Nodejs.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/OpenShift.gitlab-ci.yml b/lib/gitlab/ci/templates/OpenShift.gitlab-ci.yml
index 290b9997084..290b9997084 100644
--- a/vendor/gitlab-ci-yml/OpenShift.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/OpenShift.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/PHP.gitlab-ci.yml b/lib/gitlab/ci/templates/PHP.gitlab-ci.yml
index 33f44ee9222..33f44ee9222 100644
--- a/vendor/gitlab-ci-yml/PHP.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/PHP.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Packer.gitlab-ci.yml b/lib/gitlab/ci/templates/Packer.gitlab-ci.yml
index fa296057c72..fa296057c72 100644
--- a/vendor/gitlab-ci-yml/Packer.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Packer.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/Brunch.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Brunch.gitlab-ci.yml
index 7fcc0b436b5..7fcc0b436b5 100644
--- a/vendor/gitlab-ci-yml/Pages/Brunch.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Brunch.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/Doxygen.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Doxygen.gitlab-ci.yml
index 791afdd23f1..791afdd23f1 100644
--- a/vendor/gitlab-ci-yml/Pages/Doxygen.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Doxygen.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/Gatsby.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Gatsby.gitlab-ci.yml
index 9df2a4797b2..9df2a4797b2 100644
--- a/vendor/gitlab-ci-yml/Pages/Gatsby.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Gatsby.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/HTML.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml
index 249a168aa33..249a168aa33 100644
--- a/vendor/gitlab-ci-yml/Pages/HTML.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/Harp.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Harp.gitlab-ci.yml
index dd3ef149668..dd3ef149668 100644
--- a/vendor/gitlab-ci-yml/Pages/Harp.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Harp.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/Hexo.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Hexo.gitlab-ci.yml
index 02d02250bbf..02d02250bbf 100644
--- a/vendor/gitlab-ci-yml/Pages/Hexo.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Hexo.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/Hugo.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml
index b8cfb0f56f6..b8cfb0f56f6 100644
--- a/vendor/gitlab-ci-yml/Pages/Hugo.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Hugo.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/Hyde.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Hyde.gitlab-ci.yml
index f5b40f2b9f1..f5b40f2b9f1 100644
--- a/vendor/gitlab-ci-yml/Pages/Hyde.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Hyde.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/JBake.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/JBake.gitlab-ci.yml
index 7abfaf53e8e..7abfaf53e8e 100644
--- a/vendor/gitlab-ci-yml/Pages/JBake.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/JBake.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/Jekyll.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Jekyll.gitlab-ci.yml
index 37f50554036..37f50554036 100644
--- a/vendor/gitlab-ci-yml/Pages/Jekyll.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Jekyll.gitlab-ci.yml
diff --git a/lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml
new file mode 100644
index 00000000000..0e5fb410a4e
--- /dev/null
+++ b/lib/gitlab/ci/templates/Pages/Jigsaw.gitlab-ci.yml
@@ -0,0 +1,42 @@
+# Jigsaw is a simple static sites generator with Laravel's Blade.
+#
+# Full project: https://github.com/tightenco/jigsaw
+
+image: php:7.2
+
+# These folders are cached between builds
+cache:
+ paths:
+ - vendor/
+ - node_modules/
+
+before_script:
+ # Update packages
+ - apt-get update -yqq
+
+ # Install dependencies
+ - apt-get install -yqq gnupg zlib1g-dev libpng-dev
+
+ # Install Node 8
+ - curl -sL https://deb.nodesource.com/setup_8.x | bash -
+ - apt-get install -yqq nodejs
+
+ # Install php extensions
+ - docker-php-ext-install zip
+
+ # Install Composer and project dependencies.
+ - curl -sS https://getcomposer.org/installer | php
+ - php composer.phar install
+
+ # Install Node dependencies.
+ - npm install
+
+pages:
+ script:
+ - npm run production
+ - mv build_production public
+ artifacts:
+ paths:
+ - public
+ only:
+ - master
diff --git a/vendor/gitlab-ci-yml/Pages/Lektor.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Lektor.gitlab-ci.yml
index c5c44a5d86c..c5c44a5d86c 100644
--- a/vendor/gitlab-ci-yml/Pages/Lektor.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Lektor.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/Metalsmith.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Metalsmith.gitlab-ci.yml
index 50e8b7ccd46..50e8b7ccd46 100644
--- a/vendor/gitlab-ci-yml/Pages/Metalsmith.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Metalsmith.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/Middleman.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Middleman.gitlab-ci.yml
index 9f4cc0574d6..9f4cc0574d6 100644
--- a/vendor/gitlab-ci-yml/Pages/Middleman.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Middleman.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/Nanoc.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Nanoc.gitlab-ci.yml
index b469b316ba5..b469b316ba5 100644
--- a/vendor/gitlab-ci-yml/Pages/Nanoc.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Nanoc.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/Octopress.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Octopress.gitlab-ci.yml
index 4762ec9acfd..4762ec9acfd 100644
--- a/vendor/gitlab-ci-yml/Pages/Octopress.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Octopress.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/Pelican.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/Pelican.gitlab-ci.yml
index c5f3154f587..c5f3154f587 100644
--- a/vendor/gitlab-ci-yml/Pages/Pelican.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/Pelican.gitlab-ci.yml
diff --git a/lib/gitlab/ci/templates/Python.gitlab-ci.yml b/lib/gitlab/ci/templates/Python.gitlab-ci.yml
new file mode 100644
index 00000000000..098abe4daf5
--- /dev/null
+++ b/lib/gitlab/ci/templates/Python.gitlab-ci.yml
@@ -0,0 +1,51 @@
+# Official language image. Look for the different tagged releases at:
+# https://hub.docker.com/r/library/python/tags/
+image: python:latest
+
+# Change pip's cache directory to be inside the project directory since we can
+# only cache local items.
+variables:
+ PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
+
+# Pip's cache doesn't store the python packages
+# https://pip.pypa.io/en/stable/reference/pip_install/#caching
+#
+# If you want to also cache the installed packages, you have to install
+# them in a virtualenv and cache it as well.
+cache:
+ paths:
+ - .cache/pip
+ - venv/
+
+before_script:
+ - python -V # Print out python version for debugging
+ - pip install virtualenv
+ - virtualenv venv
+ - source venv/bin/activate
+
+test:
+ script:
+ - python setup.py test
+ - pip install tox flake8 # you can also use tox
+ - tox -e py36,flake8
+
+run:
+ script:
+ - python setup.py bdist_wheel
+ # an alternative approach is to install and run:
+ - pip install dist/*
+ # run the command here
+ artifacts:
+ paths:
+ - dist/*.whl
+
+pages:
+ script:
+ - pip install sphinx sphinx-rtd-theme
+ - cd doc ; make html
+ - mv build/html/ ../public/
+ artifacts:
+ paths:
+ - public
+ only:
+ - master
diff --git a/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml b/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
index 93cb31f48c0..93cb31f48c0 100644
--- a/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Rust.gitlab-ci.yml b/lib/gitlab/ci/templates/Rust.gitlab-ci.yml
index cab087c48c7..cab087c48c7 100644
--- a/vendor/gitlab-ci-yml/Rust.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Rust.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Scala.gitlab-ci.yml b/lib/gitlab/ci/templates/Scala.gitlab-ci.yml
index b4208ed9d7d..b4208ed9d7d 100644
--- a/vendor/gitlab-ci-yml/Scala.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Scala.gitlab-ci.yml
diff --git a/lib/gitlab/ci/templates/Swift.gitlab-ci.yml b/lib/gitlab/ci/templates/Swift.gitlab-ci.yml
new file mode 100644
index 00000000000..ba8a802ba4f
--- /dev/null
+++ b/lib/gitlab/ci/templates/Swift.gitlab-ci.yml
@@ -0,0 +1,30 @@
+# Lifted from: https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/
+# This file assumes an own GitLab CI runner, setup on a macOS system.
+stages:
+ - build
+ - archive
+
+build_project:
+ stage: build
+ script:
+ - xcodebuild clean -project ProjectName.xcodeproj -scheme SchemeName | xcpretty
+ - xcodebuild test -project ProjectName.xcodeproj -scheme SchemeName -destination 'platform=iOS Simulator,name=iPhone 8,OS=11.3' | xcpretty -s
+ tags:
+ - ios_11-3
+ - xcode_9-3
+ - macos_10-13
+
+archive_project:
+ stage: archive
+ script:
+ - xcodebuild clean archive -archivePath build/ProjectName -scheme SchemeName
+ - xcodebuild -exportArchive -exportFormat ipa -archivePath "build/ProjectName.xcarchive" -exportPath "build/ProjectName.ipa" -exportProvisioningProfile "ProvisioningProfileName"
+ only:
+ - master
+ artifacts:
+ paths:
+ - build/ProjectName.ipa
+ tags:
+ - ios_11-3
+ - xcode_9-3
+ - macos_10-13
diff --git a/vendor/gitlab-ci-yml/Terraform.gitlab-ci.yml b/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml
index 7160fce26a8..7160fce26a8 100644
--- a/vendor/gitlab-ci-yml/Terraform.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Terraform.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/dotNET.gitlab-ci.yml b/lib/gitlab/ci/templates/dotNET.gitlab-ci.yml
index fc3d4ecdbba..fc3d4ecdbba 100644
--- a/vendor/gitlab-ci-yml/dotNET.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/dotNET.gitlab-ci.yml
diff --git a/lib/gitlab/ci/trace.rb b/lib/gitlab/ci/trace.rb
index 93e219a21f9..bf5f2a31f0e 100644
--- a/lib/gitlab/ci/trace.rb
+++ b/lib/gitlab/ci/trace.rb
@@ -1,9 +1,13 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Trace
- include ExclusiveLeaseGuard
+ include ::Gitlab::ExclusiveLeaseHelpers
- LEASE_TIMEOUT = 1.hour
+ LOCK_TTL = 1.minute
+ LOCK_RETRIES = 2
+ LOCK_SLEEP = 0.001.seconds
ArchiveError = Class.new(StandardError)
AlreadyArchivedError = Class.new(StandardError)
@@ -80,24 +84,10 @@ module Gitlab
stream&.close
end
- def write(mode)
- stream = Gitlab::Ci::Trace::Stream.new do
- if trace_artifact
- raise AlreadyArchivedError, 'Could not write to the archived trace'
- elsif current_path
- File.open(current_path, mode)
- elsif Feature.enabled?('ci_enable_live_trace')
- Gitlab::Ci::Trace::ChunkedIO.new(job)
- else
- File.open(ensure_path, mode)
- end
+ def write(mode, &blk)
+ in_write_lock do
+ unsafe_write!(mode, &blk)
end
-
- yield(stream).tap do
- job.touch if job.needs_touch?
- end
- ensure
- stream&.close
end
def erase!
@@ -115,13 +105,33 @@ module Gitlab
end
def archive!
- try_obtain_lease do
+ in_write_lock do
unsafe_archive!
end
end
private
+ def unsafe_write!(mode, &blk)
+ stream = Gitlab::Ci::Trace::Stream.new do
+ if trace_artifact
+ raise AlreadyArchivedError, 'Could not write to the archived trace'
+ elsif current_path
+ File.open(current_path, mode)
+ elsif Feature.enabled?('ci_enable_live_trace')
+ Gitlab::Ci::Trace::ChunkedIO.new(job)
+ else
+ File.open(ensure_path, mode)
+ end
+ end
+
+ yield(stream).tap do
+ job.touch if job.needs_touch?
+ end
+ ensure
+ stream&.close
+ end
+
def unsafe_archive!
raise AlreadyArchivedError, 'Could not archive again' if trace_artifact
raise ArchiveError, 'Job is not finished yet' unless job.complete?
@@ -144,6 +154,11 @@ module Gitlab
end
end
+ def in_write_lock(&blk)
+ lock_key = "trace:write:lock:#{job.id}"
+ in_lock(lock_key, ttl: LOCK_TTL, retries: LOCK_RETRIES, sleep_sec: LOCK_SLEEP, &blk)
+ end
+
def archive_stream!(stream)
clone_file!(stream, JobArtifactUploader.workhorse_upload_path) do |clone_path|
create_build_trace!(job, clone_path)
@@ -224,16 +239,6 @@ module Gitlab
def trace_artifact
job.job_artifacts_trace
end
-
- # For ExclusiveLeaseGuard concern
- def lease_key
- @lease_key ||= "trace:archive:#{job.id}"
- end
-
- # For ExclusiveLeaseGuard concern
- def lease_timeout
- LEASE_TIMEOUT
- end
end
end
end
diff --git a/lib/gitlab/ci/trace/chunked_io.rb b/lib/gitlab/ci/trace/chunked_io.rb
index 2147f62a84a..8c6fd56493f 100644
--- a/lib/gitlab/ci/trace/chunked_io.rb
+++ b/lib/gitlab/ci/trace/chunked_io.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
##
# This class is compatible with IO class (https://ruby-doc.org/core-2.3.1/IO.html)
# source: https://gitlab.com/snippets/1685610
@@ -11,7 +13,7 @@ module Gitlab
attr_reader :build
attr_reader :tell, :size
- attr_reader :chunk, :chunk_range
+ attr_reader :chunk_data, :chunk_range
alias_method :pos, :tell
@@ -66,42 +68,46 @@ module Gitlab
end
end
- def read(length = nil, outbuf = "")
- out = ""
+ def read(length = nil, outbuf = nil)
+ out = []
length ||= size - tell
until length <= 0 || eof?
data = chunk_slice_from_offset
- break if data.empty?
+ raise FailedToGetChunkError if data.empty?
chunk_bytes = [CHUNK_SIZE - chunk_offset, length].min
- chunk_data = data.byteslice(0, chunk_bytes)
+ chunk_data_slice = data.byteslice(0, chunk_bytes)
- out << chunk_data
- @tell += chunk_data.bytesize
- length -= chunk_data.bytesize
+ out << chunk_data_slice
+ @tell += chunk_data_slice.bytesize
+ length -= chunk_data_slice.bytesize
end
+ out = out.join
+
# If outbuf is passed, we put the output into the buffer. This supports IO.copy_stream functionality
if outbuf
- outbuf.slice!(0, outbuf.bytesize)
- outbuf << out
+ outbuf.replace(out)
end
out
end
def readline
- out = ""
+ out = []
until eof?
data = chunk_slice_from_offset
+ raise FailedToGetChunkError if data.empty?
+
new_line = data.index("\n")
if !new_line.nil?
- out << data[0..new_line]
- @tell += new_line + 1
+ raw_data = data[0..new_line]
+ out << raw_data
+ @tell += raw_data.bytesize
break
else
out << data
@@ -109,7 +115,7 @@ module Gitlab
end
end
- out
+ out.join
end
def write(data)
@@ -118,13 +124,13 @@ module Gitlab
while tell < start_pos + data.bytesize
# get slice from current offset till the end where it falls into chunk
chunk_bytes = CHUNK_SIZE - chunk_offset
- chunk_data = data.byteslice(tell - start_pos, chunk_bytes)
+ data_slice = data.byteslice(tell - start_pos, chunk_bytes)
# append data to chunk, overwriting from that point
- ensure_chunk.append(chunk_data, chunk_offset)
+ ensure_chunk.append(data_slice, chunk_offset)
# move offsets within buffer
- @tell += chunk_data.bytesize
+ @tell += data_slice.bytesize
@size = [size, tell].max
end
@@ -180,12 +186,12 @@ module Gitlab
current_chunk.tap do |chunk|
raise FailedToGetChunkError unless chunk
- @chunk = chunk.data
+ @chunk_data = chunk.data
@chunk_range = chunk.range
end
end
- @chunk[chunk_offset..CHUNK_SIZE]
+ @chunk_data.byteslice(chunk_offset, CHUNK_SIZE)
end
def chunk_offset
diff --git a/lib/gitlab/ci/trace/section_parser.rb b/lib/gitlab/ci/trace/section_parser.rb
index c09089d6475..f33f8cc56c1 100644
--- a/lib/gitlab/ci/trace/section_parser.rb
+++ b/lib/gitlab/ci/trace/section_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Trace
diff --git a/lib/gitlab/ci/trace/stream.rb b/lib/gitlab/ci/trace/stream.rb
index a71040e5e56..0f23b95ba15 100644
--- a/lib/gitlab/ci/trace/stream.rb
+++ b/lib/gitlab/ci/trace/stream.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class Trace
@@ -41,19 +43,14 @@ module Gitlab
def append(data, offset)
data = data.force_encoding(Encoding::BINARY)
- stream.truncate(offset)
- stream.seek(0, IO::SEEK_END)
+ stream.seek(offset, IO::SEEK_SET)
stream.write(data)
+ stream.truncate(offset + data.bytesize)
stream.flush()
end
def set(data)
- data = data.force_encoding(Encoding::BINARY)
-
- stream.seek(0, IO::SEEK_SET)
- stream.write(data)
- stream.truncate(data.bytesize)
- stream.flush()
+ append(data, 0)
end
def raw(last_lines: nil)
@@ -129,8 +126,7 @@ module Gitlab
debris = ''
until (buf = read_backward(BUFFER_SIZE)).empty?
- buf += debris
- debris, *lines = buf.each_line.to_a
+ debris, *lines = (buf + debris).each_line.to_a
lines.reverse_each do |line|
yield(line.force_encoding(Encoding.default_external))
end
diff --git a/lib/gitlab/ci/variables/collection.rb b/lib/gitlab/ci/variables/collection.rb
index ad30b3f427c..a7b4e0348c2 100644
--- a/lib/gitlab/ci/variables/collection.rb
+++ b/lib/gitlab/ci/variables/collection.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Variables
diff --git a/lib/gitlab/ci/variables/collection/item.rb b/lib/gitlab/ci/variables/collection/item.rb
index 7da6d09d440..e3e4e62cc02 100644
--- a/lib/gitlab/ci/variables/collection/item.rb
+++ b/lib/gitlab/ci/variables/collection/item.rb
@@ -1,10 +1,12 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
module Variables
class Collection
class Item
def initialize(key:, value:, public: true, file: false)
- raise ArgumentError, "`value` must be of type String, while it was: #{value.class}" unless
+ raise ArgumentError, "`#{key}` must be of type String or nil value, while it was: #{value.class}" unless
value.is_a?(String) || value.nil?
@variable = {
diff --git a/lib/gitlab/ci/yaml_processor.rb b/lib/gitlab/ci/yaml_processor.rb
index 5d1864ae9e2..172926b8ab0 100644
--- a/lib/gitlab/ci/yaml_processor.rb
+++ b/lib/gitlab/ci/yaml_processor.rb
@@ -1,9 +1,11 @@
+# frozen_string_literal: true
+
module Gitlab
module Ci
class YamlProcessor
ValidationError = Class.new(StandardError)
- include Gitlab::Ci::Config::Entry::LegacyValidationHelpers
+ include Gitlab::Config::Entry::LegacyValidationHelpers
attr_reader :cache, :stages, :jobs
@@ -49,7 +51,10 @@ module Gitlab
script: job[:script],
after_script: job[:after_script],
environment: job[:environment],
- retry: job[:retry]
+ retry: job[:retry],
+ parallel: job[:parallel],
+ instance: job[:instance],
+ start_in: job[:start_in]
}.compact }
end
@@ -101,7 +106,7 @@ module Gitlab
##
# Jobs
#
- @jobs = @ci_config.jobs
+ @jobs = Ci::Config::Normalizer.new(@ci_config.jobs).normalize_jobs
@jobs.each do |name, job|
# logical validation for job
diff --git a/lib/gitlab/ci_access.rb b/lib/gitlab/ci_access.rb
index def1373d8cf..d5d3eb804ae 100644
--- a/lib/gitlab/ci_access.rb
+++ b/lib/gitlab/ci_access.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
# For backwards compatibility, generic CI (which is a build without a user) is
# allowed to :build_download_code without any other checks.
diff --git a/lib/gitlab/closing_issue_extractor.rb b/lib/gitlab/closing_issue_extractor.rb
index 7e7aaeeaa17..4ba921569ad 100644
--- a/lib/gitlab/closing_issue_extractor.rb
+++ b/lib/gitlab/closing_issue_extractor.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class ClosingIssueExtractor
ISSUE_CLOSING_REGEX = begin
diff --git a/lib/gitlab/cluster/lifecycle_events.rb b/lib/gitlab/cluster/lifecycle_events.rb
new file mode 100644
index 00000000000..b05dca409d1
--- /dev/null
+++ b/lib/gitlab/cluster/lifecycle_events.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Cluster
+ #
+ # LifecycleEvents lets Rails initializers register application startup hooks
+ # that are sensitive to forking. For example, to defer the creation of
+ # watchdog threads. This lets us abstract away the Unix process
+ # lifecycles of Unicorn, Sidekiq, Puma, Puma Cluster, etc.
+ #
+ # We have three lifecycle events.
+ #
+ # - before_fork (only in forking processes)
+ # - worker_start
+ # - before_master_restart (only in forking processes)
+ #
+ # Blocks will be executed in the order in which they are registered.
+ #
+ class LifecycleEvents
+ class << self
+ #
+ # Hook registration methods (called from initializers)
+ #
+ def on_worker_start(&block)
+ if in_clustered_environment?
+ # Defer block execution
+ (@worker_start_hooks ||= []) << block
+ else
+ yield
+ end
+ end
+
+ def on_before_fork(&block)
+ return unless in_clustered_environment?
+
+ # Defer block execution
+ (@before_fork_hooks ||= []) << block
+ end
+
+ def on_master_restart(&block)
+ return unless in_clustered_environment?
+
+ # Defer block execution
+ (@master_restart_hooks ||= []) << block
+ end
+
+ #
+ # Lifecycle integration methods (called from unicorn.rb, puma.rb, etc.)
+ #
+ def do_worker_start
+ @worker_start_hooks&.each do |block|
+ block.call
+ end
+ end
+
+ def do_before_fork
+ @before_fork_hooks&.each do |block|
+ block.call
+ end
+ end
+
+ def do_master_restart
+ @master_restart_hooks && @master_restart_hooks.each do |block|
+ block.call
+ end
+ end
+
+ # Puma doesn't use singletons (which is good) but
+ # this means we need to pass through whether the
+ # puma server is running in single mode or cluster mode
+ def set_puma_options(options)
+ @puma_options = options
+ end
+
+ private
+
+ def in_clustered_environment?
+ # Sidekiq doesn't fork
+ return false if Sidekiq.server?
+
+ # Unicorn always forks
+ return true if defined?(::Unicorn)
+
+ # Puma sometimes forks
+ return true if in_clustered_puma?
+
+ # Default assumption is that we don't fork
+ false
+ end
+
+ def in_clustered_puma?
+ return false unless defined?(::Puma)
+
+ @puma_options && @puma_options[:workers] && @puma_options[:workers] > 0
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/cluster/puma_worker_killer_initializer.rb b/lib/gitlab/cluster/puma_worker_killer_initializer.rb
new file mode 100644
index 00000000000..4ed9a9a02ab
--- /dev/null
+++ b/lib/gitlab/cluster/puma_worker_killer_initializer.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Cluster
+ class PumaWorkerKillerInitializer
+ def self.start(puma_options, puma_per_worker_max_memory_mb: 650)
+ require 'puma_worker_killer'
+
+ PumaWorkerKiller.config do |config|
+ # Note! ram is expressed in megabytes (whereas GITLAB_UNICORN_MEMORY_MAX is in bytes)
+ # Importantly RAM is for _all_workers (ie, the cluster),
+ # not each worker as is the case with GITLAB_UNICORN_MEMORY_MAX
+ worker_count = puma_options[:workers] || 1
+ # The Puma Worker Killer checks the total RAM used by both the master
+ # and worker processes. Bump the limits to N+1 instead of N workers
+ # to account for this:
+ # https://github.com/schneems/puma_worker_killer/blob/v0.1.0/lib/puma_worker_killer/puma_memory.rb#L57
+ config.ram = (worker_count + 1) * puma_per_worker_max_memory_mb
+
+ config.frequency = 20 # seconds
+
+ # We just want to limit to a fixed maximum, unrelated to the total amount
+ # of available RAM.
+ config.percent_usage = 0.98
+
+ # Ideally we'll never hit the maximum amount of memory. If so the worker
+ # is restarted already, thus periodically restarting workers shouldn't be
+ # needed.
+ config.rolling_restart_frequency = false
+ end
+
+ PumaWorkerKiller.start
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/color_schemes.rb b/lib/gitlab/color_schemes.rb
index 9c4664df903..a5e4065cf09 100644
--- a/lib/gitlab/color_schemes.rb
+++ b/lib/gitlab/color_schemes.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
# Module containing GitLab's syntax color scheme definitions and helper
# methods for accessing them.
diff --git a/lib/gitlab/config/entry/attributable.rb b/lib/gitlab/config/entry/attributable.rb
new file mode 100644
index 00000000000..560fe63df0e
--- /dev/null
+++ b/lib/gitlab/config/entry/attributable.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Config
+ module Entry
+ module Attributable
+ extend ActiveSupport::Concern
+
+ class_methods do
+ def attributes(*attributes)
+ attributes.flatten.each do |attribute|
+ if method_defined?(attribute)
+ raise ArgumentError, 'Method already defined!'
+ end
+
+ define_method(attribute) do
+ return unless config.is_a?(Hash)
+
+ config[attribute]
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/config/entry/boolean.rb b/lib/gitlab/config/entry/boolean.rb
new file mode 100644
index 00000000000..1e8a57356e3
--- /dev/null
+++ b/lib/gitlab/config/entry/boolean.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Config
+ module Entry
+ ##
+ # Entry that represents a boolean value.
+ #
+ class Boolean < Node
+ include Validatable
+
+ validations do
+ validates :config, boolean: true
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/config/entry/configurable.rb b/lib/gitlab/config/entry/configurable.rb
new file mode 100644
index 00000000000..afdb60b2cd5
--- /dev/null
+++ b/lib/gitlab/config/entry/configurable.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Config
+ module Entry
+ ##
+ # This mixin is responsible for adding DSL, which purpose is to
+ # simplifly process of adding child nodes.
+ #
+ # This can be used only if parent node is a configuration entry that
+ # holds a hash as a configuration value, for example:
+ #
+ # job:
+ # script: ...
+ # artifacts: ...
+ #
+ module Configurable
+ extend ActiveSupport::Concern
+
+ included do
+ include Validatable
+
+ validations do
+ validates :config, type: Hash
+ end
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def compose!(deps = nil)
+ return unless valid?
+
+ self.class.nodes.each do |key, factory|
+ factory
+ .value(config[key])
+ .with(key: key, parent: self)
+
+ entries[key] = factory.create!
+ end
+
+ yield if block_given?
+
+ entries.each_value do |entry|
+ entry.compose!(deps)
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ class_methods do
+ def nodes
+ Hash[(@nodes || {}).map { |key, factory| [key, factory.dup] }]
+ end
+
+ private
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def entry(key, entry, metadata)
+ factory = ::Gitlab::Config::Entry::Factory.new(entry)
+ .with(description: metadata[:description])
+
+ (@nodes ||= {}).merge!(key.to_sym => factory)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def helpers(*nodes)
+ nodes.each do |symbol|
+ define_method("#{symbol}_defined?") do
+ entries[symbol]&.specified?
+ end
+
+ define_method("#{symbol}_value") do
+ return unless entries[symbol] && entries[symbol].valid?
+
+ entries[symbol].value
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/config/entry/factory.rb b/lib/gitlab/config/entry/factory.rb
new file mode 100644
index 00000000000..30d43c9f9a1
--- /dev/null
+++ b/lib/gitlab/config/entry/factory.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Config
+ module Entry
+ ##
+ # Factory class responsible for fabricating entry objects.
+ #
+ class Factory
+ InvalidFactory = Class.new(StandardError)
+
+ def initialize(entry)
+ @entry = entry
+ @metadata = {}
+ @attributes = {}
+ end
+
+ def value(value)
+ @value = value
+ self
+ end
+
+ def metadata(metadata)
+ @metadata.merge!(metadata)
+ self
+ end
+
+ def with(attributes)
+ @attributes.merge!(attributes)
+ self
+ end
+
+ def create!
+ raise InvalidFactory unless defined?(@value)
+
+ ##
+ # We assume that unspecified entry is undefined.
+ # See issue #18775.
+ #
+ if @value.nil?
+ Entry::Unspecified.new(
+ fabricate_unspecified
+ )
+ else
+ fabricate(@entry, @value)
+ end
+ end
+
+ private
+
+ def fabricate_unspecified
+ ##
+ # If entry has a default value we fabricate concrete node
+ # with default value.
+ #
+ if @entry.default.nil?
+ fabricate(Entry::Undefined)
+ else
+ fabricate(@entry, @entry.default)
+ end
+ end
+
+ def fabricate(entry, value = nil)
+ entry.new(value, @metadata).tap do |node|
+ node.key = @attributes[:key]
+ node.parent = @attributes[:parent]
+ node.description = @attributes[:description]
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/config/entry/legacy_validation_helpers.rb b/lib/gitlab/config/entry/legacy_validation_helpers.rb
new file mode 100644
index 00000000000..d3ab5625743
--- /dev/null
+++ b/lib/gitlab/config/entry/legacy_validation_helpers.rb
@@ -0,0 +1,70 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Config
+ module Entry
+ module LegacyValidationHelpers
+ private
+
+ def validate_duration(value)
+ value.is_a?(String) && ChronicDuration.parse(value)
+ rescue ChronicDuration::DurationParseError
+ false
+ end
+
+ def validate_duration_limit(value, limit)
+ return false unless value.is_a?(String)
+
+ ChronicDuration.parse(value).second.from_now <
+ ChronicDuration.parse(limit).second.from_now
+ rescue ChronicDuration::DurationParseError
+ false
+ end
+
+ def validate_array_of_strings(values)
+ values.is_a?(Array) && values.all? { |value| validate_string(value) }
+ end
+
+ def validate_array_of_strings_or_regexps(values)
+ values.is_a?(Array) && values.all? { |value| validate_string_or_regexp(value) }
+ end
+
+ def validate_variables(variables)
+ variables.is_a?(Hash) &&
+ variables.flatten.all? do |value|
+ validate_string(value) || validate_integer(value)
+ end
+ end
+
+ def validate_integer(value)
+ value.is_a?(Integer)
+ end
+
+ def validate_string(value)
+ value.is_a?(String) || value.is_a?(Symbol)
+ end
+
+ def validate_regexp(value)
+ !value.nil? && Regexp.new(value.to_s) && true
+ rescue RegexpError, TypeError
+ false
+ end
+
+ def validate_string_or_regexp(value)
+ return true if value.is_a?(Symbol)
+ return false unless value.is_a?(String)
+
+ if value.first == '/' && value.last == '/'
+ validate_regexp(value[1...-1])
+ else
+ true
+ end
+ end
+
+ def validate_boolean(value)
+ value.in?([true, false])
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/config/entry/node.rb b/lib/gitlab/config/entry/node.rb
new file mode 100644
index 00000000000..30357b2c95b
--- /dev/null
+++ b/lib/gitlab/config/entry/node.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Config
+ module Entry
+ ##
+ # Base abstract class for each configuration entry node.
+ #
+ class Node
+ InvalidError = Class.new(StandardError)
+
+ attr_reader :config, :metadata
+ attr_accessor :key, :parent, :description
+
+ def initialize(config, **metadata)
+ @config = config
+ @metadata = metadata
+ @entries = {}
+
+ self.class.aspects.to_a.each do |aspect|
+ instance_exec(&aspect)
+ end
+ end
+
+ def [](key)
+ @entries[key] || Entry::Undefined.new
+ end
+
+ def compose!(deps = nil)
+ return unless valid?
+
+ yield if block_given?
+ end
+
+ def leaf?
+ @entries.none?
+ end
+
+ def descendants
+ @entries.values
+ end
+
+ def ancestors
+ @parent ? @parent.ancestors + [@parent] : []
+ end
+
+ def valid?
+ errors.none?
+ end
+
+ def errors
+ []
+ end
+
+ def value
+ if leaf?
+ @config
+ else
+ meaningful = @entries.select do |_key, value|
+ value.specified? && value.relevant?
+ end
+
+ Hash[meaningful.map { |key, entry| [key, entry.value] }]
+ end
+ end
+
+ def specified?
+ true
+ end
+
+ def relevant?
+ true
+ end
+
+ def location
+ name = @key.presence || self.class.name.to_s.demodulize
+ .underscore.humanize.downcase
+
+ ancestors.map(&:key).append(name).compact.join(':')
+ end
+
+ def inspect
+ val = leaf? ? config : descendants
+ unspecified = specified? ? '' : '(unspecified) '
+ "#<#{self.class.name} #{unspecified}{#{key}: #{val.inspect}}>"
+ end
+
+ def self.default
+ end
+
+ def self.aspects
+ @aspects ||= []
+ end
+
+ private
+
+ attr_reader :entries
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/config/entry/simplifiable.rb b/lib/gitlab/config/entry/simplifiable.rb
new file mode 100644
index 00000000000..3e148fe2e91
--- /dev/null
+++ b/lib/gitlab/config/entry/simplifiable.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Config
+ module Entry
+ class Simplifiable < SimpleDelegator
+ EntryStrategy = Struct.new(:name, :condition)
+
+ def initialize(config, **metadata)
+ unless self.class.const_defined?(:UnknownStrategy)
+ raise ArgumentError, 'UndefinedStrategy not available!'
+ end
+
+ strategy = self.class.strategies.find do |variant|
+ variant.condition.call(config)
+ end
+
+ entry = self.class.entry_class(strategy)
+
+ super(entry.new(config, metadata))
+ end
+
+ def self.strategy(name, **opts)
+ EntryStrategy.new(name, opts.fetch(:if)).tap do |strategy|
+ strategies.append(strategy)
+ end
+ end
+
+ def self.strategies
+ @strategies ||= []
+ end
+
+ def self.entry_class(strategy)
+ if strategy.present?
+ self.const_get(strategy.name)
+ else
+ self::UnknownStrategy
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/config/entry/undefined.rb b/lib/gitlab/config/entry/undefined.rb
new file mode 100644
index 00000000000..5f708abc80c
--- /dev/null
+++ b/lib/gitlab/config/entry/undefined.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Config
+ module Entry
+ ##
+ # This class represents an undefined entry.
+ #
+ class Undefined < Node
+ def initialize(*)
+ super(nil)
+ end
+
+ def value
+ nil
+ end
+
+ def valid?
+ true
+ end
+
+ def errors
+ []
+ end
+
+ def specified?
+ false
+ end
+
+ def relevant?
+ false
+ end
+
+ def inspect
+ "#<#{self.class.name}>"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/config/entry/unspecified.rb b/lib/gitlab/config/entry/unspecified.rb
new file mode 100644
index 00000000000..c096180d0f8
--- /dev/null
+++ b/lib/gitlab/config/entry/unspecified.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Config
+ module Entry
+ ##
+ # This class represents an unspecified entry.
+ #
+ # It decorates original entry adding method that indicates it is
+ # unspecified.
+ #
+ class Unspecified < SimpleDelegator
+ def specified?
+ false
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/config/entry/validatable.rb b/lib/gitlab/config/entry/validatable.rb
new file mode 100644
index 00000000000..1c88c68c11c
--- /dev/null
+++ b/lib/gitlab/config/entry/validatable.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Config
+ module Entry
+ module Validatable
+ extend ActiveSupport::Concern
+
+ def self.included(node)
+ node.aspects.append -> do
+ @validator = self.class.validator.new(self)
+ @validator.validate(:new)
+ end
+ end
+
+ def errors
+ @validator.messages + descendants.flat_map(&:errors) # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ end
+
+ class_methods do
+ def validator
+ @validator ||= Class.new(Entry::Validator).tap do |validator|
+ if defined?(@validations)
+ @validations.each { |rules| validator.class_eval(&rules) }
+ end
+ end
+ end
+
+ private
+
+ def validations(&block)
+ (@validations ||= []).append(block)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/config/entry/validator.rb b/lib/gitlab/config/entry/validator.rb
new file mode 100644
index 00000000000..e5efd4a7b0a
--- /dev/null
+++ b/lib/gitlab/config/entry/validator.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Config
+ module Entry
+ class Validator < SimpleDelegator
+ include ActiveModel::Validations
+ include Entry::Validators
+
+ def initialize(entry)
+ super(entry)
+ end
+
+ def messages
+ errors.full_messages.map do |error|
+ "#{location} #{error}".downcase
+ end
+ end
+
+ def self.name
+ 'Validator'
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/config/entry/validators.rb b/lib/gitlab/config/entry/validators.rb
new file mode 100644
index 00000000000..25bfa50f829
--- /dev/null
+++ b/lib/gitlab/config/entry/validators.rb
@@ -0,0 +1,196 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Config
+ module Entry
+ module Validators
+ class AllowedKeysValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ unknown_keys = value.try(:keys).to_a - options[:in]
+
+ if unknown_keys.any?
+ record.errors.add(attribute, "contains unknown keys: " +
+ unknown_keys.join(', '))
+ end
+ end
+ end
+
+ class AllowedValuesValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ unless options[:in].include?(value.to_s)
+ record.errors.add(attribute, "unknown value: #{value}")
+ end
+ end
+ end
+
+ class AllowedArrayValuesValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ unkown_values = value - options[:in]
+ unless unkown_values.empty?
+ record.errors.add(attribute, "contains unknown values: " +
+ unkown_values.join(', '))
+ end
+ end
+ end
+
+ class ArrayOfStringsValidator < ActiveModel::EachValidator
+ include LegacyValidationHelpers
+
+ def validate_each(record, attribute, value)
+ unless validate_array_of_strings(value)
+ record.errors.add(attribute, 'should be an array of strings')
+ end
+ end
+ end
+
+ class BooleanValidator < ActiveModel::EachValidator
+ include LegacyValidationHelpers
+
+ def validate_each(record, attribute, value)
+ unless validate_boolean(value)
+ record.errors.add(attribute, 'should be a boolean value')
+ end
+ end
+ end
+
+ class DurationValidator < ActiveModel::EachValidator
+ include LegacyValidationHelpers
+
+ def validate_each(record, attribute, value)
+ unless validate_duration(value)
+ record.errors.add(attribute, 'should be a duration')
+ end
+
+ if options[:limit]
+ unless validate_duration_limit(value, options[:limit])
+ record.errors.add(attribute, 'should not exceed the limit')
+ end
+ end
+ end
+ end
+
+ class HashOrStringValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ unless value.is_a?(Hash) || value.is_a?(String)
+ record.errors.add(attribute, 'should be a hash or a string')
+ end
+ end
+ end
+
+ class HashOrIntegerValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ unless value.is_a?(Hash) || value.is_a?(Integer)
+ record.errors.add(attribute, 'should be a hash or an integer')
+ end
+ end
+ end
+
+ class KeyValidator < ActiveModel::EachValidator
+ include LegacyValidationHelpers
+
+ def validate_each(record, attribute, value)
+ if validate_string(value)
+ validate_path(record, attribute, value)
+ else
+ record.errors.add(attribute, 'should be a string or symbol')
+ end
+ end
+
+ private
+
+ def validate_path(record, attribute, value)
+ path = CGI.unescape(value.to_s)
+
+ if path.include?('/')
+ record.errors.add(attribute, 'cannot contain the "/" character')
+ elsif path == '.' || path == '..'
+ record.errors.add(attribute, 'cannot be "." or ".."')
+ end
+ end
+ end
+
+ class RegexpValidator < ActiveModel::EachValidator
+ include LegacyValidationHelpers
+
+ def validate_each(record, attribute, value)
+ unless validate_regexp(value)
+ record.errors.add(attribute, 'must be a regular expression')
+ end
+ end
+
+ private
+
+ def look_like_regexp?(value)
+ value.is_a?(String) && value.start_with?('/') &&
+ value.end_with?('/')
+ end
+
+ def validate_regexp(value)
+ look_like_regexp?(value) &&
+ Regexp.new(value.to_s[1...-1]) &&
+ true
+ rescue RegexpError
+ false
+ end
+ end
+
+ class ArrayOfStringsOrRegexpsValidator < RegexpValidator
+ def validate_each(record, attribute, value)
+ unless validate_array_of_strings_or_regexps(value)
+ record.errors.add(attribute, 'should be an array of strings or regexps')
+ end
+ end
+
+ private
+
+ def validate_array_of_strings_or_regexps(values)
+ values.is_a?(Array) && values.all?(&method(:validate_string_or_regexp))
+ end
+
+ def validate_string_or_regexp(value)
+ return false unless value.is_a?(String)
+ return validate_regexp(value) if look_like_regexp?(value)
+
+ true
+ end
+ end
+
+ class ArrayOfStringsOrStringValidator < RegexpValidator
+ def validate_each(record, attribute, value)
+ unless validate_array_of_strings_or_string(value)
+ record.errors.add(attribute, 'should be an array of strings or a string')
+ end
+ end
+
+ private
+
+ def validate_array_of_strings_or_string(values)
+ validate_array_of_strings(values) || validate_string(values)
+ end
+ end
+
+ class TypeValidator < ActiveModel::EachValidator
+ def validate_each(record, attribute, value)
+ type = options[:with]
+ raise unless type.is_a?(Class)
+
+ unless value.is_a?(type)
+ message = options[:message] || "should be a #{type.name}"
+ record.errors.add(attribute, message)
+ end
+ end
+ end
+
+ class VariablesValidator < ActiveModel::EachValidator
+ include LegacyValidationHelpers
+
+ def validate_each(record, attribute, value)
+ unless validate_variables(value)
+ record.errors.add(attribute, 'should be a hash of key value pairs')
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/config/loader/format_error.rb b/lib/gitlab/config/loader/format_error.rb
new file mode 100644
index 00000000000..848ff96d201
--- /dev/null
+++ b/lib/gitlab/config/loader/format_error.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Config
+ module Loader
+ FormatError = Class.new(StandardError)
+ end
+ end
+end
diff --git a/lib/gitlab/config/loader/yaml.rb b/lib/gitlab/config/loader/yaml.rb
new file mode 100644
index 00000000000..8159f8b8026
--- /dev/null
+++ b/lib/gitlab/config/loader/yaml.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Config
+ module Loader
+ class Yaml
+ def initialize(config)
+ @config = YAML.safe_load(config, [Symbol], [], true)
+ rescue Psych::Exception => e
+ raise Loader::FormatError, e.message
+ end
+
+ def valid?
+ @config.is_a?(Hash)
+ end
+
+ def load!
+ unless valid?
+ raise Loader::FormatError, 'Invalid configuration format'
+ end
+
+ @config.deep_symbolize_keys
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/config_helper.rb b/lib/gitlab/config_helper.rb
index 41880069e4c..b7aa03384b7 100644
--- a/lib/gitlab/config_helper.rb
+++ b/lib/gitlab/config_helper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab::ConfigHelper
def gitlab_config_features
Gitlab.config.gitlab.default_projects_features
diff --git a/lib/gitlab/conflict/file.rb b/lib/gitlab/conflict/file.rb
index 2a0cb640a14..0ca99506311 100644
--- a/lib/gitlab/conflict/file.rb
+++ b/lib/gitlab/conflict/file.rb
@@ -1,8 +1,11 @@
+# frozen_string_literal: true
+
module Gitlab
module Conflict
class File
include Gitlab::Routing
include IconsHelper
+ include Gitlab::Utils::StrongMemoize
CONTEXT_LINES = 3
@@ -30,11 +33,8 @@ module Gitlab
end
def highlight_lines!
- their_file = lines.reject { |line| line.type == 'new' }.map(&:text).join("\n")
- our_file = lines.reject { |line| line.type == 'old' }.map(&:text).join("\n")
-
- their_highlight = Gitlab::Highlight.highlight(their_path, their_file, repository: repository).lines
- our_highlight = Gitlab::Highlight.highlight(our_path, our_file, repository: repository).lines
+ their_highlight = Gitlab::Highlight.highlight(their_path, their_lines, language: their_language).lines
+ our_highlight = Gitlab::Highlight.highlight(our_path, our_lines, language: our_language).lines
lines.each do |line|
line.rich_text =
@@ -158,7 +158,6 @@ module Gitlab
json_hash.tap do |json_hash|
if opts[:full_content]
json_hash[:content] = content
- json_hash[:blob_ace_mode] = our_blob && our_blob.language.try(:ace_mode)
else
json_hash[:sections] = sections if type.text?
json_hash[:type] = type
@@ -183,6 +182,34 @@ module Gitlab
raw_line[:line_new], parent_file: self)
end
end
+
+ def their_language
+ strong_memoize(:their_language) do
+ repository.gitattribute(their_path, 'gitlab-language')
+ end
+ end
+
+ def our_language
+ strong_memoize(:our_language) do
+ if our_path == their_path
+ their_language
+ else
+ repository.gitattribute(our_path, 'gitlab-language')
+ end
+ end
+ end
+
+ def their_lines
+ strong_memoize(:their_lines) do
+ lines.reject { |line| line.type == 'new' }.map(&:text).join("\n")
+ end
+ end
+
+ def our_lines
+ strong_memoize(:our_lines) do
+ lines.reject { |line| line.type == 'old' }.map(&:text).join("\n")
+ end
+ end
end
end
end
diff --git a/lib/gitlab/conflict/file_collection.rb b/lib/gitlab/conflict/file_collection.rb
index 65a65b67975..53406af2c4e 100644
--- a/lib/gitlab/conflict/file_collection.rb
+++ b/lib/gitlab/conflict/file_collection.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Conflict
class FileCollection
diff --git a/lib/gitlab/contributions_calendar.rb b/lib/gitlab/contributions_calendar.rb
index 1ffc2639237..5ed6427072a 100644
--- a/lib/gitlab/contributions_calendar.rb
+++ b/lib/gitlab/contributions_calendar.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class ContributionsCalendar
attr_reader :contributor
@@ -71,7 +73,7 @@ module Gitlab
# re-running the contributed projects query in each union is expensive, so
# use IN(project_ids...) instead. It's the intersection of two users so
# the list will be (relatively) short
- @contributed_project_ids ||= projects.uniq.pluck(:id)
+ @contributed_project_ids ||= projects.distinct.pluck(:id)
authed_projects = Project.where(id: @contributed_project_ids)
.with_feature_available_for_user(feature, current_user)
.reorder(nil)
diff --git a/lib/gitlab/contributor.rb b/lib/gitlab/contributor.rb
index c41e92b620f..d74d5a86aa0 100644
--- a/lib/gitlab/contributor.rb
+++ b/lib/gitlab/contributor.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class Contributor
attr_accessor :email, :name, :commits, :additions, :deletions
diff --git a/lib/gitlab/cross_project_access.rb b/lib/gitlab/cross_project_access.rb
index 6eaed51b64c..4ddc7e02d1b 100644
--- a/lib/gitlab/cross_project_access.rb
+++ b/lib/gitlab/cross_project_access.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class CrossProjectAccess
class << self
diff --git a/lib/gitlab/cross_project_access/check_collection.rb b/lib/gitlab/cross_project_access/check_collection.rb
index 88376232065..55527ba5e87 100644
--- a/lib/gitlab/cross_project_access/check_collection.rb
+++ b/lib/gitlab/cross_project_access/check_collection.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class CrossProjectAccess
class CheckCollection
diff --git a/lib/gitlab/cross_project_access/check_info.rb b/lib/gitlab/cross_project_access/check_info.rb
index e8a845c7f1e..2a9eacad680 100644
--- a/lib/gitlab/cross_project_access/check_info.rb
+++ b/lib/gitlab/cross_project_access/check_info.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class CrossProjectAccess
class CheckInfo
diff --git a/lib/gitlab/cross_project_access/class_methods.rb b/lib/gitlab/cross_project_access/class_methods.rb
index 90eac94800c..64ad30794d3 100644
--- a/lib/gitlab/cross_project_access/class_methods.rb
+++ b/lib/gitlab/cross_project_access/class_methods.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class CrossProjectAccess
module ClassMethods
diff --git a/lib/gitlab/crypto_helper.rb b/lib/gitlab/crypto_helper.rb
new file mode 100644
index 00000000000..68d0b5d8f8a
--- /dev/null
+++ b/lib/gitlab/crypto_helper.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module CryptoHelper
+ extend self
+
+ AES256_GCM_OPTIONS = {
+ algorithm: 'aes-256-gcm',
+ key: Settings.attr_encrypted_db_key_base_truncated,
+ iv: Settings.attr_encrypted_db_key_base_truncated[0..11]
+ }.freeze
+
+ def sha256(value)
+ salt = Settings.attr_encrypted_db_key_base_truncated
+ ::Digest::SHA256.base64digest("#{value}#{salt}")
+ end
+
+ def aes256_gcm_encrypt(value)
+ encrypted_token = Encryptor.encrypt(AES256_GCM_OPTIONS.merge(value: value))
+ Base64.encode64(encrypted_token)
+ end
+
+ def aes256_gcm_decrypt(value)
+ return unless value
+
+ encrypted_token = Base64.decode64(value)
+ Encryptor.decrypt(AES256_GCM_OPTIONS.merge(value: encrypted_token))
+ end
+ end
+end
diff --git a/lib/gitlab/current_settings.rb b/lib/gitlab/current_settings.rb
index c9dbd2d2e5f..477f9101e98 100644
--- a/lib/gitlab/current_settings.rb
+++ b/lib/gitlab/current_settings.rb
@@ -1,12 +1,10 @@
+# frozen_string_literal: true
+
module Gitlab
module CurrentSettings
class << self
def current_application_settings
- if RequestStore.active?
- RequestStore.fetch(:current_application_settings) { ensure_application_settings! }
- else
- ensure_application_settings!
- end
+ Gitlab::SafeRequestStore.fetch(:current_application_settings) { ensure_application_settings! }
end
def fake_application_settings(attributes = {})
diff --git a/lib/gitlab/cycle_analytics/base_event_fetcher.rb b/lib/gitlab/cycle_analytics/base_event_fetcher.rb
index e3e3767cc75..304d60996a6 100644
--- a/lib/gitlab/cycle_analytics/base_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/base_event_fetcher.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class BaseEventFetcher
diff --git a/lib/gitlab/cycle_analytics/base_query.rb b/lib/gitlab/cycle_analytics/base_query.rb
index 86d708be0d6..36231b187cd 100644
--- a/lib/gitlab/cycle_analytics/base_query.rb
+++ b/lib/gitlab/cycle_analytics/base_query.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
module BaseQuery
diff --git a/lib/gitlab/cycle_analytics/base_stage.rb b/lib/gitlab/cycle_analytics/base_stage.rb
index 038d5a19bc4..e2d6a301734 100644
--- a/lib/gitlab/cycle_analytics/base_stage.rb
+++ b/lib/gitlab/cycle_analytics/base_stage.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class BaseStage
diff --git a/lib/gitlab/cycle_analytics/code_event_fetcher.rb b/lib/gitlab/cycle_analytics/code_event_fetcher.rb
index 06357c9b377..591db3c35e6 100644
--- a/lib/gitlab/cycle_analytics/code_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/code_event_fetcher.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class CodeEventFetcher < BaseEventFetcher
diff --git a/lib/gitlab/cycle_analytics/code_stage.rb b/lib/gitlab/cycle_analytics/code_stage.rb
index 5f9dc9a4303..2e5f9ef5a40 100644
--- a/lib/gitlab/cycle_analytics/code_stage.rb
+++ b/lib/gitlab/cycle_analytics/code_stage.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class CodeStage < BaseStage
diff --git a/lib/gitlab/cycle_analytics/event_fetcher.rb b/lib/gitlab/cycle_analytics/event_fetcher.rb
index 50e126cf00b..98a30a8fc97 100644
--- a/lib/gitlab/cycle_analytics/event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/event_fetcher.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
module EventFetcher
diff --git a/lib/gitlab/cycle_analytics/issue_event_fetcher.rb b/lib/gitlab/cycle_analytics/issue_event_fetcher.rb
index 1754f91dccb..30c6ead8968 100644
--- a/lib/gitlab/cycle_analytics/issue_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/issue_event_fetcher.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class IssueEventFetcher < BaseEventFetcher
diff --git a/lib/gitlab/cycle_analytics/issue_stage.rb b/lib/gitlab/cycle_analytics/issue_stage.rb
index 7b03811efb2..4eae2da512c 100644
--- a/lib/gitlab/cycle_analytics/issue_stage.rb
+++ b/lib/gitlab/cycle_analytics/issue_stage.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class IssueStage < BaseStage
diff --git a/lib/gitlab/cycle_analytics/metrics_tables.rb b/lib/gitlab/cycle_analytics/metrics_tables.rb
index f5d08c0b658..3e0302d308d 100644
--- a/lib/gitlab/cycle_analytics/metrics_tables.rb
+++ b/lib/gitlab/cycle_analytics/metrics_tables.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
module MetricsTables
diff --git a/lib/gitlab/cycle_analytics/permissions.rb b/lib/gitlab/cycle_analytics/permissions.rb
index 1e11e84a9cb..afefd09b614 100644
--- a/lib/gitlab/cycle_analytics/permissions.rb
+++ b/lib/gitlab/cycle_analytics/permissions.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class Permissions
diff --git a/lib/gitlab/cycle_analytics/plan_event_fetcher.rb b/lib/gitlab/cycle_analytics/plan_event_fetcher.rb
index 086203b9ccc..db8ac3becea 100644
--- a/lib/gitlab/cycle_analytics/plan_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/plan_event_fetcher.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class PlanEventFetcher < BaseEventFetcher
diff --git a/lib/gitlab/cycle_analytics/plan_stage.rb b/lib/gitlab/cycle_analytics/plan_stage.rb
index 1a0afb56b4f..513e4575be0 100644
--- a/lib/gitlab/cycle_analytics/plan_stage.rb
+++ b/lib/gitlab/cycle_analytics/plan_stage.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class PlanStage < BaseStage
diff --git a/lib/gitlab/cycle_analytics/production_event_fetcher.rb b/lib/gitlab/cycle_analytics/production_event_fetcher.rb
index 0fa2e87f673..6681cb42c90 100644
--- a/lib/gitlab/cycle_analytics/production_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/production_event_fetcher.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class ProductionEventFetcher < IssueEventFetcher
diff --git a/lib/gitlab/cycle_analytics/production_helper.rb b/lib/gitlab/cycle_analytics/production_helper.rb
index d0ca62e46e4..aff65b150fb 100644
--- a/lib/gitlab/cycle_analytics/production_helper.rb
+++ b/lib/gitlab/cycle_analytics/production_helper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
module ProductionHelper
diff --git a/lib/gitlab/cycle_analytics/production_stage.rb b/lib/gitlab/cycle_analytics/production_stage.rb
index 0fa8a65cb99..6fd7214dce7 100644
--- a/lib/gitlab/cycle_analytics/production_stage.rb
+++ b/lib/gitlab/cycle_analytics/production_stage.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class ProductionStage < BaseStage
diff --git a/lib/gitlab/cycle_analytics/review_event_fetcher.rb b/lib/gitlab/cycle_analytics/review_event_fetcher.rb
index dada819a2a8..de100295281 100644
--- a/lib/gitlab/cycle_analytics/review_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/review_event_fetcher.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class ReviewEventFetcher < BaseEventFetcher
diff --git a/lib/gitlab/cycle_analytics/review_stage.rb b/lib/gitlab/cycle_analytics/review_stage.rb
index cfbbdc43fd9..294b656bc55 100644
--- a/lib/gitlab/cycle_analytics/review_stage.rb
+++ b/lib/gitlab/cycle_analytics/review_stage.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class ReviewStage < BaseStage
diff --git a/lib/gitlab/cycle_analytics/stage.rb b/lib/gitlab/cycle_analytics/stage.rb
index 28e0455df59..1bd40a7aa18 100644
--- a/lib/gitlab/cycle_analytics/stage.rb
+++ b/lib/gitlab/cycle_analytics/stage.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
module Stage
diff --git a/lib/gitlab/cycle_analytics/stage_summary.rb b/lib/gitlab/cycle_analytics/stage_summary.rb
index fc77bd86097..5198dd5b4eb 100644
--- a/lib/gitlab/cycle_analytics/stage_summary.rb
+++ b/lib/gitlab/cycle_analytics/stage_summary.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class StageSummary
diff --git a/lib/gitlab/cycle_analytics/staging_event_fetcher.rb b/lib/gitlab/cycle_analytics/staging_event_fetcher.rb
index 2f014153ca5..70ce82383b3 100644
--- a/lib/gitlab/cycle_analytics/staging_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/staging_event_fetcher.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class StagingEventFetcher < BaseEventFetcher
diff --git a/lib/gitlab/cycle_analytics/staging_stage.rb b/lib/gitlab/cycle_analytics/staging_stage.rb
index d5684bb9201..dbc2414ff66 100644
--- a/lib/gitlab/cycle_analytics/staging_stage.rb
+++ b/lib/gitlab/cycle_analytics/staging_stage.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class StagingStage < BaseStage
diff --git a/lib/gitlab/cycle_analytics/summary/base.rb b/lib/gitlab/cycle_analytics/summary/base.rb
index a917ddccac7..709221c648e 100644
--- a/lib/gitlab/cycle_analytics/summary/base.rb
+++ b/lib/gitlab/cycle_analytics/summary/base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
module Summary
diff --git a/lib/gitlab/cycle_analytics/summary/commit.rb b/lib/gitlab/cycle_analytics/summary/commit.rb
index 550c1755a71..f0019b26fa2 100644
--- a/lib/gitlab/cycle_analytics/summary/commit.rb
+++ b/lib/gitlab/cycle_analytics/summary/commit.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
module Summary
diff --git a/lib/gitlab/cycle_analytics/summary/deploy.rb b/lib/gitlab/cycle_analytics/summary/deploy.rb
index 099d798aac6..3b56dc2a7bc 100644
--- a/lib/gitlab/cycle_analytics/summary/deploy.rb
+++ b/lib/gitlab/cycle_analytics/summary/deploy.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
module Summary
diff --git a/lib/gitlab/cycle_analytics/summary/issue.rb b/lib/gitlab/cycle_analytics/summary/issue.rb
index 9bbf7a2685f..51695c86192 100644
--- a/lib/gitlab/cycle_analytics/summary/issue.rb
+++ b/lib/gitlab/cycle_analytics/summary/issue.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
module Summary
diff --git a/lib/gitlab/cycle_analytics/test_event_fetcher.rb b/lib/gitlab/cycle_analytics/test_event_fetcher.rb
index a2589c6601a..4d5ea5b7c34 100644
--- a/lib/gitlab/cycle_analytics/test_event_fetcher.rb
+++ b/lib/gitlab/cycle_analytics/test_event_fetcher.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class TestEventFetcher < StagingEventFetcher
diff --git a/lib/gitlab/cycle_analytics/test_stage.rb b/lib/gitlab/cycle_analytics/test_stage.rb
index 0e9d235ca79..c31b664148b 100644
--- a/lib/gitlab/cycle_analytics/test_stage.rb
+++ b/lib/gitlab/cycle_analytics/test_stage.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class TestStage < BaseStage
diff --git a/lib/gitlab/cycle_analytics/updater.rb b/lib/gitlab/cycle_analytics/updater.rb
index 953268ebd46..c642809a792 100644
--- a/lib/gitlab/cycle_analytics/updater.rb
+++ b/lib/gitlab/cycle_analytics/updater.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class Updater
diff --git a/lib/gitlab/cycle_analytics/usage_data.rb b/lib/gitlab/cycle_analytics/usage_data.rb
index 5122e3417ca..913ee373f54 100644
--- a/lib/gitlab/cycle_analytics/usage_data.rb
+++ b/lib/gitlab/cycle_analytics/usage_data.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module CycleAnalytics
class UsageData
diff --git a/lib/gitlab/daemon.rb b/lib/gitlab/daemon.rb
index bd14c7eece3..6d5fc4219fb 100644
--- a/lib/gitlab/daemon.rb
+++ b/lib/gitlab/daemon.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class Daemon
def self.initialize_instance(*args)
diff --git a/lib/gitlab/data_builder/build.rb b/lib/gitlab/data_builder/build.rb
index 0b71b31a476..3407380127e 100644
--- a/lib/gitlab/data_builder/build.rb
+++ b/lib/gitlab/data_builder/build.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DataBuilder
module Build
diff --git a/lib/gitlab/data_builder/note.rb b/lib/gitlab/data_builder/note.rb
index f573368e572..65601dcdf31 100644
--- a/lib/gitlab/data_builder/note.rb
+++ b/lib/gitlab/data_builder/note.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DataBuilder
module Note
diff --git a/lib/gitlab/data_builder/pipeline.rb b/lib/gitlab/data_builder/pipeline.rb
index eb246d393a1..76c8b4ec5c2 100644
--- a/lib/gitlab/data_builder/pipeline.rb
+++ b/lib/gitlab/data_builder/pipeline.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DataBuilder
module Pipeline
@@ -26,7 +28,8 @@ module Gitlab
stages: pipeline.stages_names,
created_at: pipeline.created_at,
finished_at: pipeline.finished_at,
- duration: pipeline.duration
+ duration: pipeline.duration,
+ variables: pipeline.variables.map(&:hook_attrs)
}
end
diff --git a/lib/gitlab/data_builder/push.rb b/lib/gitlab/data_builder/push.rb
index b498f113859..9bf2f9291a8 100644
--- a/lib/gitlab/data_builder/push.rb
+++ b/lib/gitlab/data_builder/push.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DataBuilder
module Push
diff --git a/lib/gitlab/data_builder/repository.rb b/lib/gitlab/data_builder/repository.rb
index c9c13ec6487..0e627fd623e 100644
--- a/lib/gitlab/data_builder/repository.rb
+++ b/lib/gitlab/data_builder/repository.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DataBuilder
module Repository
diff --git a/lib/gitlab/data_builder/wiki_page.rb b/lib/gitlab/data_builder/wiki_page.rb
index 226974b698c..9368446fa59 100644
--- a/lib/gitlab/data_builder/wiki_page.rb
+++ b/lib/gitlab/data_builder/wiki_page.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DataBuilder
module WikiPage
diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb
index 42f9605f5ac..6d40e00c035 100644
--- a/lib/gitlab/database.rb
+++ b/lib/gitlab/database.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Database
# The max value of INTEGER type is the same between MySQL and PostgreSQL:
@@ -33,7 +35,6 @@ module Gitlab
adapter_name.casecmp('postgresql').zero?
end
- # Overridden in EE
def self.read_only?
false
end
@@ -42,12 +43,14 @@ module Gitlab
!self.read_only?
end
- # check whether the underlying database is in read-only mode
+ # Check whether the underlying database is in read-only mode
def self.db_read_only?
if postgresql?
- ActiveRecord::Base.connection.execute('SELECT pg_is_in_recovery()')
- .first
- .fetch('pg_is_in_recovery') == 't'
+ pg_is_in_recovery =
+ ActiveRecord::Base.connection.execute('SELECT pg_is_in_recovery()')
+ .first.fetch('pg_is_in_recovery')
+
+ Gitlab::Utils.to_boolean(pg_is_in_recovery)
else
false
end
@@ -99,11 +102,11 @@ module Gitlab
order = "#{field} #{direction}"
if postgresql?
- order << ' NULLS LAST'
+ order = "#{order} NULLS LAST"
else
# `field IS NULL` will be `0` for non-NULL columns and `1` for NULL
# columns. In the (default) ascending order, `0` comes first.
- order.prepend("#{field} IS NULL, ") if direction == 'ASC'
+ order = "#{field} IS NULL, #{order}" if direction == 'ASC'
end
order
@@ -113,11 +116,11 @@ module Gitlab
order = "#{field} #{direction}"
if postgresql?
- order << ' NULLS FIRST'
+ order = "#{order} NULLS FIRST"
else
# `field IS NULL` will be `0` for non-NULL columns and `1` for NULL
# columns. In the (default) ascending order, `0` comes first.
- order.prepend("#{field} IS NULL, ") if direction == 'DESC'
+ order = "#{field} IS NULL, #{order}" if direction == 'DESC'
end
order
@@ -184,7 +187,7 @@ module Gitlab
EOF
if return_ids
- sql << 'RETURNING id'
+ sql = "#{sql}RETURNING id"
end
result = connection.execute(sql)
diff --git a/lib/gitlab/database/arel_methods.rb b/lib/gitlab/database/arel_methods.rb
index d7e3ce08b32..991e4152dcb 100644
--- a/lib/gitlab/database/arel_methods.rb
+++ b/lib/gitlab/database/arel_methods.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Database
module ArelMethods
diff --git a/lib/gitlab/database/count.rb b/lib/gitlab/database/count.rb
index 5f549ed2b3c..c996d786909 100644
--- a/lib/gitlab/database/count.rb
+++ b/lib/gitlab/database/count.rb
@@ -1,5 +1,12 @@
+# frozen_string_literal: true
+
# For large tables, PostgreSQL can take a long time to count rows due to MVCC.
-# We can optimize this by using the reltuples count as described in https://wiki.postgresql.org/wiki/Slow_Counting.
+# We can optimize this by using various strategies for approximate counting.
+#
+# For example, we can use the reltuples count as described in https://wiki.postgresql.org/wiki/Slow_Counting.
+#
+# However, since statistics are not always up to date, we also implement a table sampling strategy
+# that performs an exact count but only on a sample of the table. See TablesampleCountStrategy.
module Gitlab
module Database
module Count
@@ -18,68 +25,30 @@ module Gitlab
end
# Takes in an array of models and returns a Hash for the approximate
- # counts for them. If the model's table has not been vacuumed or
- # analyzed recently, simply run the Model.count to get the data.
+ # counts for them.
+ #
+ # Various count strategies can be specified that are executed in
+ # sequence until all tables have an approximate count attached
+ # or we run out of strategies.
+ #
+ # Note that not all strategies are available on all supported RDBMS.
#
# @param [Array]
# @return [Hash] of Model -> count mapping
- def self.approximate_counts(models)
- table_to_model_map = models.each_with_object({}) do |model, hash|
- hash[model.table_name] = model
- end
-
- table_names = table_to_model_map.keys
- counts_by_table_name = Gitlab::Database.postgresql? ? reltuples_from_recently_updated(table_names) : {}
-
- # Convert table -> count to Model -> count
- counts_by_model = counts_by_table_name.each_with_object({}) do |pair, hash|
- model = table_to_model_map[pair.first]
- hash[model] = pair.second
- end
-
- missing_tables = table_names - counts_by_table_name.keys
+ def self.approximate_counts(models, strategies: [TablesampleCountStrategy, ReltuplesCountStrategy, ExactCountStrategy])
+ strategies.each_with_object({}) do |strategy, counts_by_model|
+ if strategy.enabled?
+ models_with_missing_counts = models - counts_by_model.keys
- missing_tables.each do |table|
- model = table_to_model_map[table]
- counts_by_model[model] = model.count
- end
-
- counts_by_model
- end
+ break if models_with_missing_counts.empty?
- # Returns a hash of the table names that have recently updated tuples.
- #
- # @param [Array] table names
- # @returns [Hash] Table name to count mapping (e.g. { 'projects' => 5, 'users' => 100 })
- def self.reltuples_from_recently_updated(table_names)
- query = postgresql_estimate_query(table_names)
- rows = []
+ counts = strategy.new(models_with_missing_counts).count
- # Querying tuple stats only works on the primary. Due to load
- # balancing, we need to ensure this query hits the load balancer. The
- # easiest way to do this is to start a transaction.
- ActiveRecord::Base.transaction do
- rows = ActiveRecord::Base.connection.select_all(query)
+ counts.each do |model, count|
+ counts_by_model[model] = count
+ end
+ end
end
-
- rows.each_with_object({}) { |row, data| data[row['table_name']] = row['estimate'].to_i }
- rescue *CONNECTION_ERRORS
- {}
- end
-
- # Generates the PostgreSQL query to return the tuples for tables
- # that have been vacuumed or analyzed in the last hour.
- #
- # @param [Array] table names
- # @returns [Hash] Table name to count mapping (e.g. { 'projects' => 5, 'users' => 100 })
- def self.postgresql_estimate_query(table_names)
- time = "to_timestamp(#{1.hour.ago.to_i})"
- <<~SQL
- SELECT pg_class.relname AS table_name, reltuples::bigint AS estimate FROM pg_class
- LEFT JOIN pg_stat_user_tables ON pg_class.relname = pg_stat_user_tables.relname
- WHERE pg_class.relname IN (#{table_names.map { |table| "'#{table}'" }.join(',')})
- AND (last_vacuum > #{time} OR last_autovacuum > #{time} OR last_analyze > #{time} OR last_autoanalyze > #{time})
- SQL
end
end
end
diff --git a/lib/gitlab/database/count/exact_count_strategy.rb b/lib/gitlab/database/count/exact_count_strategy.rb
new file mode 100644
index 00000000000..0276fe2b54f
--- /dev/null
+++ b/lib/gitlab/database/count/exact_count_strategy.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Count
+ # This strategy performs an exact count on the model.
+ #
+ # This is guaranteed to be accurate, however it also scans the
+ # whole table. Hence, there are no guarantees with respect
+ # to runtime.
+ #
+ # Note that for very large tables, this may even timeout.
+ class ExactCountStrategy
+ attr_reader :models
+ def initialize(models)
+ @models = models
+ end
+
+ def count
+ models.each_with_object({}) do |model, data|
+ data[model] = model.count
+ end
+ end
+
+ def self.enabled?
+ true
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/count/reltuples_count_strategy.rb b/lib/gitlab/database/count/reltuples_count_strategy.rb
new file mode 100644
index 00000000000..c3a674aeb7e
--- /dev/null
+++ b/lib/gitlab/database/count/reltuples_count_strategy.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Count
+ class PgClass < ActiveRecord::Base
+ self.table_name = 'pg_class'
+ end
+
+ # This strategy counts based on PostgreSQL's statistics in pg_stat_user_tables.
+ #
+ # Specifically, it relies on the column reltuples in said table. An additional
+ # check is performed to make sure statistics were updated within the last hour.
+ #
+ # Otherwise, this strategy skips tables with outdated statistics.
+ #
+ # There are no guarantees with respect to the accuracy of this strategy. Runtime
+ # however is guaranteed to be "fast", because it only looks up statistics.
+ class ReltuplesCountStrategy
+ attr_reader :models
+ def initialize(models)
+ @models = models
+ end
+
+ # Returns a hash of the table names that have recently updated tuples.
+ #
+ # @returns [Hash] Table name to count mapping (e.g. { 'projects' => 5, 'users' => 100 })
+ def count
+ size_estimates
+ rescue *CONNECTION_ERRORS
+ {}
+ end
+
+ def self.enabled?
+ Gitlab::Database.postgresql?
+ end
+
+ private
+
+ def table_names
+ models.map(&:table_name)
+ end
+
+ def size_estimates(check_statistics: true)
+ table_to_model = models.each_with_object({}) { |model, h| h[model.table_name] = model }
+
+ # Querying tuple stats only works on the primary. Due to load balancing, the
+ # easiest way to do this is to start a transaction.
+ ActiveRecord::Base.transaction do
+ get_statistics(table_names, check_statistics: check_statistics).each_with_object({}) do |row, data|
+ model = table_to_model[row.table_name]
+ data[model] = row.estimate
+ end
+ end
+ end
+
+ # Generates the PostgreSQL query to return the tuples for tables
+ # that have been vacuumed or analyzed in the last hour.
+ #
+ # @param [Array] table names
+ # @returns [Hash] Table name to count mapping (e.g. { 'projects' => 5, 'users' => 100 })
+ def get_statistics(table_names, check_statistics: true)
+ time = 1.hour.ago
+
+ query = PgClass.joins("LEFT JOIN pg_stat_user_tables USING (relname)")
+ .where(relname: table_names)
+ .select('pg_class.relname AS table_name, reltuples::bigint AS estimate')
+
+ if check_statistics
+ query = query.where('last_vacuum > ? OR last_autovacuum > ? OR last_analyze > ? OR last_autoanalyze > ?',
+ time, time, time, time)
+ end
+
+ query
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/count/tablesample_count_strategy.rb b/lib/gitlab/database/count/tablesample_count_strategy.rb
new file mode 100644
index 00000000000..cf1cf054dbf
--- /dev/null
+++ b/lib/gitlab/database/count/tablesample_count_strategy.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Count
+ # A tablesample count executes in two phases:
+ # * Estimate table sizes based on reltuples.
+ # * Based on the estimate:
+ # * If the table is considered 'small', execute an exact relation count.
+ # * Otherwise, count on a sample of the table using TABLESAMPLE.
+ #
+ # The size of the sample is chosen in a way that we always roughly scan
+ # the same amount of rows (see TABLESAMPLE_ROW_TARGET).
+ #
+ # There are no guarantees with respect to the accuracy of the result or runtime.
+ class TablesampleCountStrategy < ReltuplesCountStrategy
+ EXACT_COUNT_THRESHOLD = 10_000
+ TABLESAMPLE_ROW_TARGET = 10_000
+
+ def count
+ estimates = size_estimates(check_statistics: false)
+
+ models.each_with_object({}) do |model, count_by_model|
+ count = perform_count(model, estimates[model])
+ count_by_model[model] = count if count
+ end
+ rescue *CONNECTION_ERRORS
+ {}
+ end
+
+ def self.enabled?
+ Gitlab::Database.postgresql? && Feature.enabled?(:tablesample_counts)
+ end
+
+ private
+
+ def perform_count(model, estimate)
+ # If we estimate 0, we may not have statistics at all. Don't use them.
+ return nil unless estimate && estimate > 0
+
+ if estimate < EXACT_COUNT_THRESHOLD
+ # The table is considered small, the assumption here is that
+ # the exact count will be fast anyways.
+ model.count
+ else
+ # The table is considered large, let's only count on a sample.
+ tablesample_count(model, estimate)
+ end
+ end
+
+ def tablesample_count(model, estimate)
+ portion = (TABLESAMPLE_ROW_TARGET.to_f / estimate).round(4)
+ inverse = 1 / portion
+ query = <<~SQL
+ SELECT (COUNT(*)*#{inverse})::integer AS count
+ FROM #{model.table_name} TABLESAMPLE SYSTEM (#{portion * 100})
+ SQL
+
+ rows = ActiveRecord::Base.connection.select_all(query)
+
+ Integer(rows.first['count'])
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/date_time.rb b/lib/gitlab/database/date_time.rb
index 25e56998038..79d2caff151 100644
--- a/lib/gitlab/database/date_time.rb
+++ b/lib/gitlab/database/date_time.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Database
module DateTime
diff --git a/lib/gitlab/database/grant.rb b/lib/gitlab/database/grant.rb
index 7d334a79009..862ab96c887 100644
--- a/lib/gitlab/database/grant.rb
+++ b/lib/gitlab/database/grant.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Database
# Model that can be used for querying permissions of a SQL user.
diff --git a/lib/gitlab/database/median.rb b/lib/gitlab/database/median.rb
index f64e3d53138..0da5119a3ed 100644
--- a/lib/gitlab/database/median.rb
+++ b/lib/gitlab/database/median.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# https://www.periscopedata.com/blog/medians-in-sql.html
module Gitlab
module Database
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index 7f012312819..134d1e7a724 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Database
module MigrationHelpers
@@ -879,7 +881,7 @@ module Gitlab
columns(table).find { |column| column.name == name }
end
- # This will replace the first occurance of a string in a column with
+ # This will replace the first occurrence of a string in a column with
# the replacement
# On postgresql we can use `regexp_replace` for that.
# On mysql we find the location of the pattern, and overwrite it
@@ -937,7 +939,7 @@ database (#{dbname}) using a super user and running:
For MySQL you instead need to run:
- GRANT ALL PRIVILEGES ON *.* TO #{user}@'%'
+ GRANT ALL PRIVILEGES ON #{dbname}.* TO #{user}@'%'
Both queries will grant the user super user permissions, ensuring you don't run
into similar problems in the future (e.g. when new tables are created).
@@ -1073,6 +1075,10 @@ into similar problems in the future (e.g. when new tables are created).
connection.select_value(index_sql).to_i > 0
end
+
+ def mysql_compatible_index_length
+ Gitlab::Database.mysql? ? 20 : nil
+ end
end
end
end
diff --git a/lib/gitlab/database/multi_threaded_migration.rb b/lib/gitlab/database/multi_threaded_migration.rb
index 7ae5a4c17c8..1d39a3d0b57 100644
--- a/lib/gitlab/database/multi_threaded_migration.rb
+++ b/lib/gitlab/database/multi_threaded_migration.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Database
module MultiThreadedMigration
diff --git a/lib/gitlab/database/read_only_relation.rb b/lib/gitlab/database/read_only_relation.rb
index 4571ad122ce..2362208e5dd 100644
--- a/lib/gitlab/database/read_only_relation.rb
+++ b/lib/gitlab/database/read_only_relation.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Database
# Module that can be injected into a ActiveRecord::Relation to make it
diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1.rb
index f333ff22300..2314246da55 100644
--- a/lib/gitlab/database/rename_reserved_paths_migration/v1.rb
+++ b/lib/gitlab/database/rename_reserved_paths_migration/v1.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This module can be included in migrations to make it easier to rename paths
# of `Namespace` & `Project` models certain paths would become `reserved`.
#
diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb
index 26ae6966746..f1dc3ed74fe 100644
--- a/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb
+++ b/lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Database
module RenameReservedPathsMigration
diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb
index 14de28a1d08..a5b42bbfdd9 100644
--- a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb
+++ b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Database
module RenameReservedPathsMigration
diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb
index 73971af6a74..6bbad707f0f 100644
--- a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb
+++ b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Database
module RenameReservedPathsMigration
diff --git a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects.rb b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects.rb
index 827aeb12a02..580be9fe267 100644
--- a/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects.rb
+++ b/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_projects.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Database
module RenameReservedPathsMigration
diff --git a/lib/gitlab/database/sha_attribute.rb b/lib/gitlab/database/sha_attribute.rb
index b2d8ee81977..6516d6e648d 100644
--- a/lib/gitlab/database/sha_attribute.rb
+++ b/lib/gitlab/database/sha_attribute.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Database
BINARY_TYPE =
diff --git a/lib/gitlab/database/subquery.rb b/lib/gitlab/database/subquery.rb
index 2a6f39c6a27..36e4559b554 100644
--- a/lib/gitlab/database/subquery.rb
+++ b/lib/gitlab/database/subquery.rb
@@ -6,7 +6,15 @@ module Gitlab
class << self
def self_join(relation)
t = relation.arel_table
- t2 = relation.arel.as('t2')
+ t2 = if !Gitlab.rails5?
+ relation.arel.as('t2')
+ else
+ # Work around a bug in Rails 5, where LIMIT causes trouble
+ # See https://gitlab.com/gitlab-org/gitlab-ce/issues/51729
+ r = relation.limit(nil).arel
+ r.take(relation.limit_value) if relation.limit_value
+ r.as('t2')
+ end
relation.unscoped.joins(t.join(t2).on(t[:id].eq(t2[:id])).join_sources.first)
end
diff --git a/lib/gitlab/dependency_linker.rb b/lib/gitlab/dependency_linker.rb
index 3192bf6f667..c63d9e5bb71 100644
--- a/lib/gitlab/dependency_linker.rb
+++ b/lib/gitlab/dependency_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DependencyLinker
LINKERS = [
diff --git a/lib/gitlab/dependency_linker/base_linker.rb b/lib/gitlab/dependency_linker/base_linker.rb
index d2360583741..ac2efe598b4 100644
--- a/lib/gitlab/dependency_linker/base_linker.rb
+++ b/lib/gitlab/dependency_linker/base_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DependencyLinker
class BaseLinker
diff --git a/lib/gitlab/dependency_linker/cartfile_linker.rb b/lib/gitlab/dependency_linker/cartfile_linker.rb
index 4f69f2c4ab2..0e33f0956dd 100644
--- a/lib/gitlab/dependency_linker/cartfile_linker.rb
+++ b/lib/gitlab/dependency_linker/cartfile_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DependencyLinker
class CartfileLinker < MethodLinker
diff --git a/lib/gitlab/dependency_linker/cocoapods.rb b/lib/gitlab/dependency_linker/cocoapods.rb
index 2fbde7da1b4..38eabe303de 100644
--- a/lib/gitlab/dependency_linker/cocoapods.rb
+++ b/lib/gitlab/dependency_linker/cocoapods.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DependencyLinker
module Cocoapods
diff --git a/lib/gitlab/dependency_linker/composer_json_linker.rb b/lib/gitlab/dependency_linker/composer_json_linker.rb
index cfd4ec15125..22d2bead891 100644
--- a/lib/gitlab/dependency_linker/composer_json_linker.rb
+++ b/lib/gitlab/dependency_linker/composer_json_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DependencyLinker
class ComposerJsonLinker < PackageJsonLinker
diff --git a/lib/gitlab/dependency_linker/gemfile_linker.rb b/lib/gitlab/dependency_linker/gemfile_linker.rb
index bfea836bcb2..8ab219c4962 100644
--- a/lib/gitlab/dependency_linker/gemfile_linker.rb
+++ b/lib/gitlab/dependency_linker/gemfile_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DependencyLinker
class GemfileLinker < MethodLinker
diff --git a/lib/gitlab/dependency_linker/gemspec_linker.rb b/lib/gitlab/dependency_linker/gemspec_linker.rb
index f1783ee2ab4..b924ea86d89 100644
--- a/lib/gitlab/dependency_linker/gemspec_linker.rb
+++ b/lib/gitlab/dependency_linker/gemspec_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DependencyLinker
class GemspecLinker < MethodLinker
diff --git a/lib/gitlab/dependency_linker/godeps_json_linker.rb b/lib/gitlab/dependency_linker/godeps_json_linker.rb
index fe091baee6d..d24c137793e 100644
--- a/lib/gitlab/dependency_linker/godeps_json_linker.rb
+++ b/lib/gitlab/dependency_linker/godeps_json_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DependencyLinker
class GodepsJsonLinker < JsonLinker
diff --git a/lib/gitlab/dependency_linker/json_linker.rb b/lib/gitlab/dependency_linker/json_linker.rb
index a8ef25233d8..298d214df61 100644
--- a/lib/gitlab/dependency_linker/json_linker.rb
+++ b/lib/gitlab/dependency_linker/json_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DependencyLinker
class JsonLinker < BaseLinker
diff --git a/lib/gitlab/dependency_linker/method_linker.rb b/lib/gitlab/dependency_linker/method_linker.rb
index 0ffa2a83c93..d4d85bb3390 100644
--- a/lib/gitlab/dependency_linker/method_linker.rb
+++ b/lib/gitlab/dependency_linker/method_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DependencyLinker
class MethodLinker < BaseLinker
diff --git a/lib/gitlab/dependency_linker/package_json_linker.rb b/lib/gitlab/dependency_linker/package_json_linker.rb
index 330c95f0880..578e25f806a 100644
--- a/lib/gitlab/dependency_linker/package_json_linker.rb
+++ b/lib/gitlab/dependency_linker/package_json_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DependencyLinker
class PackageJsonLinker < JsonLinker
diff --git a/lib/gitlab/dependency_linker/podfile_linker.rb b/lib/gitlab/dependency_linker/podfile_linker.rb
index 60ad166ea17..def9b04cca9 100644
--- a/lib/gitlab/dependency_linker/podfile_linker.rb
+++ b/lib/gitlab/dependency_linker/podfile_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DependencyLinker
class PodfileLinker < GemfileLinker
diff --git a/lib/gitlab/dependency_linker/podspec_json_linker.rb b/lib/gitlab/dependency_linker/podspec_json_linker.rb
index d82237ed3f1..1a2493e7cc0 100644
--- a/lib/gitlab/dependency_linker/podspec_json_linker.rb
+++ b/lib/gitlab/dependency_linker/podspec_json_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DependencyLinker
class PodspecJsonLinker < JsonLinker
diff --git a/lib/gitlab/dependency_linker/podspec_linker.rb b/lib/gitlab/dependency_linker/podspec_linker.rb
index 924e55e9820..6b1758c5a43 100644
--- a/lib/gitlab/dependency_linker/podspec_linker.rb
+++ b/lib/gitlab/dependency_linker/podspec_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DependencyLinker
class PodspecLinker < MethodLinker
diff --git a/lib/gitlab/dependency_linker/requirements_txt_linker.rb b/lib/gitlab/dependency_linker/requirements_txt_linker.rb
index 9c9620bc36a..f630c13b760 100644
--- a/lib/gitlab/dependency_linker/requirements_txt_linker.rb
+++ b/lib/gitlab/dependency_linker/requirements_txt_linker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module DependencyLinker
class RequirementsTxtLinker < BaseLinker
diff --git a/lib/gitlab/diff/diff_refs.rb b/lib/gitlab/diff/diff_refs.rb
index 81df47964be..dc245377ccc 100644
--- a/lib/gitlab/diff/diff_refs.rb
+++ b/lib/gitlab/diff/diff_refs.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Diff
class DiffRefs
@@ -21,7 +23,7 @@ module Gitlab
alias_method :eql?, :==
def hash
- [base_sha, start_sha, head_sha].hash
+ [self.class, base_sha, start_sha, head_sha].hash
end
# There is only one case in which we will have `start_sha` and `head_sha`,
diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb
index fb117baca9e..8ba44dff06f 100644
--- a/lib/gitlab/diff/file.rb
+++ b/lib/gitlab/diff/file.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Diff
class File
@@ -26,6 +28,7 @@ module Gitlab
@repository = repository
@diff_refs = diff_refs
@fallback_diff_refs = fallback_diff_refs
+ @unfolded = false
# Ensure items are collected in the the batch
new_blob_lazy
@@ -135,6 +138,24 @@ module Gitlab
Gitlab::Diff::Parser.new.parse(raw_diff.each_line, diff_file: self).to_a
end
+ # Changes diff_lines according to the given position. That is,
+ # it checks whether the position requires blob lines into the diff
+ # in order to be presented.
+ def unfold_diff_lines(position)
+ return unless position
+
+ unfolder = Gitlab::Diff::LinesUnfolder.new(self, position)
+
+ if unfolder.unfold_required?
+ @diff_lines = unfolder.unfolded_diff_lines
+ @unfolded = true
+ end
+ end
+
+ def unfolded?
+ @unfolded
+ end
+
def highlighted_diff_lines
@highlighted_diff_lines ||=
Gitlab::Diff::Highlight.new(self, repository: self.repository).highlight
diff --git a/lib/gitlab/diff/file_collection/base.rb b/lib/gitlab/diff/file_collection/base.rb
index b79ff771a2b..10df037a0dd 100644
--- a/lib/gitlab/diff/file_collection/base.rb
+++ b/lib/gitlab/diff/file_collection/base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Diff
module FileCollection
@@ -17,7 +19,6 @@ module Gitlab
@diffable = diffable
@include_stats = diff_options.delete(:include_stats)
- @diffs = diffable.raw_diffs(diff_options)
@project = project
@diff_options = diff_options
@diff_refs = diff_refs
@@ -25,8 +26,12 @@ module Gitlab
@repository = project.repository
end
+ def diffs
+ @diffs ||= diffable.raw_diffs(diff_options)
+ end
+
def diff_files
- @diff_files ||= @diffs.decorate! { |diff| decorate_diff!(diff) }
+ @diff_files ||= diffs.decorate! { |diff| decorate_diff!(diff) }
end
def diff_file_with_old_path(old_path)
diff --git a/lib/gitlab/diff/file_collection/commit.rb b/lib/gitlab/diff/file_collection/commit.rb
index 4dc297ec036..7b1d6171e82 100644
--- a/lib/gitlab/diff/file_collection/commit.rb
+++ b/lib/gitlab/diff/file_collection/commit.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Diff
module FileCollection
diff --git a/lib/gitlab/diff/file_collection/compare.rb b/lib/gitlab/diff/file_collection/compare.rb
index 20d8f891cc3..586c5cf87af 100644
--- a/lib/gitlab/diff/file_collection/compare.rb
+++ b/lib/gitlab/diff/file_collection/compare.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Diff
module FileCollection
diff --git a/lib/gitlab/diff/file_collection/merge_request_diff.rb b/lib/gitlab/diff/file_collection/merge_request_diff.rb
index 0dd073a3a8e..e29bf75f341 100644
--- a/lib/gitlab/diff/file_collection/merge_request_diff.rb
+++ b/lib/gitlab/diff/file_collection/merge_request_diff.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Diff
module FileCollection
diff --git a/lib/gitlab/diff/formatters/base_formatter.rb b/lib/gitlab/diff/formatters/base_formatter.rb
index 5e923b9e602..9704aed82c1 100644
--- a/lib/gitlab/diff/formatters/base_formatter.rb
+++ b/lib/gitlab/diff/formatters/base_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Diff
module Formatters
diff --git a/lib/gitlab/diff/formatters/image_formatter.rb b/lib/gitlab/diff/formatters/image_formatter.rb
index ccd0d309972..5bc9f0c337f 100644
--- a/lib/gitlab/diff/formatters/image_formatter.rb
+++ b/lib/gitlab/diff/formatters/image_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Diff
module Formatters
diff --git a/lib/gitlab/diff/formatters/text_formatter.rb b/lib/gitlab/diff/formatters/text_formatter.rb
index 01c7e9f51ab..f6e247ef665 100644
--- a/lib/gitlab/diff/formatters/text_formatter.rb
+++ b/lib/gitlab/diff/formatters/text_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Diff
module Formatters
diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb
index 1f012043e56..d2484217ab9 100644
--- a/lib/gitlab/diff/highlight.rb
+++ b/lib/gitlab/diff/highlight.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Diff
class Highlight
@@ -24,7 +26,7 @@ module Gitlab
# ignore highlighting for "match" lines
next diff_line if diff_line.meta?
- rich_line = highlight_line(diff_line) || diff_line.text
+ rich_line = highlight_line(diff_line) || ERB::Util.html_escape(diff_line.text)
if line_inline_diffs = inline_diffs[i]
begin
@@ -79,7 +81,7 @@ module Gitlab
return [] unless blob
blob.load_all_data!
- Gitlab::Highlight.highlight(blob.path, blob.data, repository: repository).lines
+ blob.present.highlight.lines
end
end
end
diff --git a/lib/gitlab/diff/image_point.rb b/lib/gitlab/diff/image_point.rb
index 1f157354ea4..a3ce032f8e2 100644
--- a/lib/gitlab/diff/image_point.rb
+++ b/lib/gitlab/diff/image_point.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Diff
class ImagePoint
diff --git a/lib/gitlab/diff/inline_diff.rb b/lib/gitlab/diff/inline_diff.rb
index 72d5ec547da..5815d1bae4a 100644
--- a/lib/gitlab/diff/inline_diff.rb
+++ b/lib/gitlab/diff/inline_diff.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Diff
class InlineDiff
@@ -71,7 +73,7 @@ module Gitlab
def find_changed_line_pairs(lines)
# Prefixes of all diff lines, indicating their types
# For example: `" - + -+ ---+++ --+ -++"`
- line_prefixes = lines.each_with_object("") { |line, s| s << (line[0] || ' ') }.gsub(/[^ +-]/, ' ')
+ line_prefixes = lines.each_with_object(+"") { |line, s| s << (line[0] || ' ') }.gsub(/[^ +-]/, ' ')
changed_line_pairs = []
line_prefixes.scan(LINE_PAIRS_PATTERN) do
diff --git a/lib/gitlab/diff/inline_diff_markdown_marker.rb b/lib/gitlab/diff/inline_diff_markdown_marker.rb
index c2a2eb15931..3c536c43a9e 100644
--- a/lib/gitlab/diff/inline_diff_markdown_marker.rb
+++ b/lib/gitlab/diff/inline_diff_markdown_marker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Diff
class InlineDiffMarkdownMarker < Gitlab::StringRangeMarker
diff --git a/lib/gitlab/diff/inline_diff_marker.rb b/lib/gitlab/diff/inline_diff_marker.rb
index 81e91ea0ab7..1bbde1ffd2a 100644
--- a/lib/gitlab/diff/inline_diff_marker.rb
+++ b/lib/gitlab/diff/inline_diff_marker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Diff
class InlineDiffMarker < Gitlab::StringRangeMarker
diff --git a/lib/gitlab/diff/line.rb b/lib/gitlab/diff/line.rb
index 5b67cd46c48..f0c4977fc50 100644
--- a/lib/gitlab/diff/line.rb
+++ b/lib/gitlab/diff/line.rb
@@ -1,11 +1,13 @@
+# frozen_string_literal: true
+
module Gitlab
module Diff
class Line
SERIALIZE_KEYS = %i(line_code rich_text text type index old_pos new_pos).freeze
- attr_reader :line_code, :type, :index, :old_pos, :new_pos
+ attr_reader :line_code, :type, :old_pos, :new_pos
attr_writer :rich_text
- attr_accessor :text
+ attr_accessor :text, :index
def initialize(text, type, index, old_pos, new_pos, parent_file: nil, line_code: nil, rich_text: nil)
@text, @type, @index = text, type, index
@@ -19,7 +21,14 @@ module Gitlab
end
def self.init_from_hash(hash)
- new(hash[:text], hash[:type], hash[:index], hash[:old_pos], hash[:new_pos], line_code: hash[:line_code], rich_text: hash[:rich_text])
+ new(hash[:text],
+ hash[:type],
+ hash[:index],
+ hash[:old_pos],
+ hash[:new_pos],
+ parent_file: hash[:parent_file],
+ line_code: hash[:line_code],
+ rich_text: hash[:rich_text])
end
def to_hash
diff --git a/lib/gitlab/diff/line_mapper.rb b/lib/gitlab/diff/line_mapper.rb
index cf71d47df8e..fba7bff4781 100644
--- a/lib/gitlab/diff/line_mapper.rb
+++ b/lib/gitlab/diff/line_mapper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# When provided a diff for a specific file, maps old line numbers to new line
# numbers and back, to find out where a specific line in a file was moved by the
# changes.
diff --git a/lib/gitlab/diff/lines_unfolder.rb b/lib/gitlab/diff/lines_unfolder.rb
new file mode 100644
index 00000000000..9306b7e16a2
--- /dev/null
+++ b/lib/gitlab/diff/lines_unfolder.rb
@@ -0,0 +1,235 @@
+# frozen_string_literal: true
+
+# Given a position, calculates which Blob lines should be extracted, treated and
+# injected in the current diff file lines in order to present a "unfolded" diff.
+module Gitlab
+ module Diff
+ class LinesUnfolder
+ include Gitlab::Utils::StrongMemoize
+
+ UNFOLD_CONTEXT_SIZE = 3
+
+ def initialize(diff_file, position)
+ @diff_file = diff_file
+ @blob = diff_file.old_blob
+ @position = position
+ @generate_top_match_line = true
+ @generate_bottom_match_line = true
+
+ # These methods update `@generate_top_match_line` and
+ # `@generate_bottom_match_line`.
+ @from_blob_line = calculate_from_blob_line!
+ @to_blob_line = calculate_to_blob_line!
+ end
+
+ # Returns merged diff lines with required blob lines with correct
+ # positions.
+ def unfolded_diff_lines
+ strong_memoize(:unfolded_diff_lines) do
+ next unless unfold_required?
+
+ merged_diff_with_blob_lines
+ end
+ end
+
+ # Returns the extracted lines from the old blob which should be merged
+ # with the current diff lines.
+ def blob_lines
+ strong_memoize(:blob_lines) do
+ # Blob lines, unlike diffs, doesn't start with an empty space for
+ # unchanged line, so the parsing and highlighting step can get fuzzy
+ # without the following change.
+ line_prefix = ' '
+ blob_as_diff_lines = @blob.data.each_line.map { |line| "#{line_prefix}#{line}" }
+
+ lines = Gitlab::Diff::Parser.new.parse(blob_as_diff_lines, diff_file: @diff_file).to_a
+
+ from = from_blob_line - 1
+ to = to_blob_line - 1
+
+ lines[from..to]
+ end
+ end
+
+ def unfold_required?
+ strong_memoize(:unfold_required) do
+ next false unless @diff_file.text?
+ next false unless @position.unchanged?
+ next false if @diff_file.new_file? || @diff_file.deleted_file?
+ next false unless @position.old_line
+ # Invalid position (MR import scenario)
+ next false if @position.old_line > @blob.lines.size
+ next false if @diff_file.diff_lines.empty?
+ next false if @diff_file.line_for_position(@position)
+ next false unless unfold_line
+
+ true
+ end
+ end
+
+ private
+
+ attr_reader :from_blob_line, :to_blob_line
+
+ def merged_diff_with_blob_lines
+ lines = @diff_file.diff_lines
+ match_line = unfold_line
+ insert_index = bottom? ? -1 : match_line.index
+
+ lines -= [match_line] unless bottom?
+
+ lines.insert(insert_index, *blob_lines_with_matches)
+
+ # The inserted blob lines have invalid indexes, so we need
+ # to reindex them.
+ reindex(lines)
+
+ lines
+ end
+
+ # Returns 'unchanged' blob lines with recalculated `old_pos` and
+ # `new_pos` and the recalculated new match line (needed if we for instance
+ # we unfolded once, but there are still folded lines).
+ def blob_lines_with_matches
+ old_pos = from_blob_line
+ new_pos = from_blob_line + offset
+
+ new_blob_lines = []
+
+ new_blob_lines.push(top_blob_match_line) if top_blob_match_line
+
+ blob_lines.each do |line|
+ new_blob_lines << Gitlab::Diff::Line.new(line.text, line.type, nil, old_pos, new_pos,
+ parent_file: @diff_file)
+
+ old_pos += 1
+ new_pos += 1
+ end
+
+ new_blob_lines.push(bottom_blob_match_line) if bottom_blob_match_line
+
+ new_blob_lines
+ end
+
+ def reindex(lines)
+ lines.each_with_index { |line, i| line.index = i }
+ end
+
+ def top_blob_match_line
+ strong_memoize(:top_blob_match_line) do
+ next unless @generate_top_match_line
+
+ old_pos = from_blob_line
+ new_pos = from_blob_line + offset
+
+ build_match_line(old_pos, new_pos)
+ end
+ end
+
+ def bottom_blob_match_line
+ strong_memoize(:bottom_blob_match_line) do
+ # The bottom line match addition is already handled on
+ # Diff::File#diff_lines_for_serializer
+ next if bottom?
+ next unless @generate_bottom_match_line
+
+ position = line_after_unfold_position.old_pos
+
+ old_pos = position
+ new_pos = position + offset
+
+ build_match_line(old_pos, new_pos)
+ end
+ end
+
+ def build_match_line(old_pos, new_pos)
+ blob_lines_length = blob_lines.length
+ old_line_ref = [old_pos, blob_lines_length].join(',')
+ new_line_ref = [new_pos, blob_lines_length].join(',')
+ new_match_line_str = "@@ -#{old_line_ref}+#{new_line_ref} @@"
+
+ Gitlab::Diff::Line.new(new_match_line_str, 'match', nil, old_pos, new_pos)
+ end
+
+ # Returns the first line position that should be extracted
+ # from `blob_lines`.
+ def calculate_from_blob_line!
+ return unless unfold_required?
+
+ from = comment_position - UNFOLD_CONTEXT_SIZE
+
+ # There's no line before the match if it's in the top-most
+ # position.
+ prev_line_number = line_before_unfold_position&.old_pos || 0
+
+ if from <= prev_line_number + 1
+ @generate_top_match_line = false
+ from = prev_line_number + 1
+ end
+
+ from
+ end
+
+ # Returns the last line position that should be extracted
+ # from `blob_lines`.
+ def calculate_to_blob_line!
+ return unless unfold_required?
+
+ to = comment_position + UNFOLD_CONTEXT_SIZE
+
+ return to if bottom?
+
+ next_line_number = line_after_unfold_position.old_pos
+
+ if to >= next_line_number - 1
+ @generate_bottom_match_line = false
+ to = next_line_number - 1
+ end
+
+ to
+ end
+
+ def offset
+ unfold_line.new_pos - unfold_line.old_pos
+ end
+
+ def line_before_unfold_position
+ return unless index = unfold_line&.index
+
+ @diff_file.diff_lines[index - 1] if index > 0
+ end
+
+ def line_after_unfold_position
+ return unless index = unfold_line&.index
+
+ @diff_file.diff_lines[index + 1] if index >= 0
+ end
+
+ def bottom?
+ strong_memoize(:bottom) do
+ @position.old_line > last_line.old_pos
+ end
+ end
+
+ # Returns the line which needed to be expanded in order to send a comment
+ # in `@position`.
+ def unfold_line
+ strong_memoize(:unfold_line) do
+ next last_line if bottom?
+
+ @diff_file.diff_lines.find do |line|
+ line.old_pos > comment_position && line.type == 'match'
+ end
+ end
+ end
+
+ def comment_position
+ @position.old_line
+ end
+
+ def last_line
+ @diff_file.diff_lines.last
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/diff/parallel_diff.rb b/lib/gitlab/diff/parallel_diff.rb
index 0cb26fa45c8..77b65fea726 100644
--- a/lib/gitlab/diff/parallel_diff.rb
+++ b/lib/gitlab/diff/parallel_diff.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Diff
class ParallelDiff
diff --git a/lib/gitlab/diff/parser.rb b/lib/gitlab/diff/parser.rb
index 7ae7ed286ed..4a47e4b80b6 100644
--- a/lib/gitlab/diff/parser.rb
+++ b/lib/gitlab/diff/parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Diff
class Parser
diff --git a/lib/gitlab/diff/position.rb b/lib/gitlab/diff/position.rb
index 4b6016e00bc..e8f98f52111 100644
--- a/lib/gitlab/diff/position.rb
+++ b/lib/gitlab/diff/position.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Defines a specific location, identified by paths line numbers and image coordinates,
# within a specific diff, identified by start, head and base commit ids.
module Gitlab
@@ -69,6 +71,10 @@ module Gitlab
JSON.generate(formatter.to_h, opts)
end
+ def as_json(opts = nil)
+ to_h.as_json(opts)
+ end
+
def type
formatter.line_age
end
@@ -97,22 +103,22 @@ module Gitlab
@diff_refs ||= DiffRefs.new(base_sha: base_sha, start_sha: start_sha, head_sha: head_sha)
end
+ def unfolded_diff?(repository)
+ diff_file(repository)&.unfolded?
+ end
+
def diff_file(repository)
return @diff_file if defined?(@diff_file)
@diff_file = begin
- if RequestStore.active?
- key = {
- project_id: repository.project.id,
- start_sha: start_sha,
- head_sha: head_sha,
- path: file_path
- }
-
- RequestStore.fetch(key) { find_diff_file(repository) }
- else
- find_diff_file(repository)
- end
+ key = {
+ project_id: repository.project.id,
+ start_sha: start_sha,
+ head_sha: head_sha,
+ path: file_path
+ }
+
+ Gitlab::SafeRequestStore.fetch(key) { find_diff_file(repository) }
end
end
@@ -134,7 +140,13 @@ module Gitlab
return unless diff_refs.complete?
return unless comparison = diff_refs.compare_in(repository.project)
- comparison.diffs(diff_options).diff_files.first
+ file = comparison.diffs(diff_options).diff_files.first
+
+ # We need to unfold diff lines according to the position in order
+ # to correctly calculate the line code and trace position changes.
+ file&.unfold_diff_lines(self)
+
+ file
end
def get_formatter_class(type)
diff --git a/lib/gitlab/diff/position_tracer.rb b/lib/gitlab/diff/position_tracer.rb
index b68a1636814..af3df820422 100644
--- a/lib/gitlab/diff/position_tracer.rb
+++ b/lib/gitlab/diff/position_tracer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Finds the diff position in the new diff that corresponds to the same location
# specified by the provided position in the old diff.
module Gitlab
@@ -24,7 +26,7 @@ module Gitlab
# head of `feature` was commit B, resulting in the original diff A->B.
# Since creation, `master` was updated to C.
# Now `feature` is being updated to D, and the newly generated MR diff is C->D.
- # It is possible that C and D are direct decendants of A and B respectively,
+ # It is possible that C and D are direct descendants of A and B respectively,
# but this isn't necessarily the case as rebases and merges come into play.
#
# Suppose we have a diff note on the original diff A->B. Now that the MR
diff --git a/lib/gitlab/downtime_check.rb b/lib/gitlab/downtime_check.rb
index 941244694e2..31bb6810391 100644
--- a/lib/gitlab/downtime_check.rb
+++ b/lib/gitlab/downtime_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
# Checks if a set of migrations requires downtime or not.
class DowntimeCheck
diff --git a/lib/gitlab/downtime_check/message.rb b/lib/gitlab/downtime_check/message.rb
index 543e62794c5..ec38bd769a3 100644
--- a/lib/gitlab/downtime_check/message.rb
+++ b/lib/gitlab/downtime_check/message.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class DowntimeCheck
class Message
@@ -18,13 +20,13 @@ module Gitlab
def to_s
label = offline ? OFFLINE : ONLINE
- message = "[#{label}]: #{path}"
+ message = ["[#{label}]: #{path}"]
if reason?
- message += ":\n\n#{reason}\n\n"
+ message << ":\n\n#{reason}\n\n"
end
- message
+ message.join
end
def reason?
diff --git a/lib/gitlab/ee_compat_check.rb b/lib/gitlab/ee_compat_check.rb
index ee604e66154..5d9ecd651a0 100644
--- a/lib/gitlab/ee_compat_check.rb
+++ b/lib/gitlab/ee_compat_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# rubocop: disable Rails/Output
module Gitlab
# Checks if a set of migrations requires downtime or not.
@@ -284,7 +286,7 @@ module Gitlab
end
def patch_name_from_branch(branch_name)
- branch_name.parameterize << '.patch'
+ "#{branch_name.parameterize}.patch"
end
def patch_url
@@ -432,9 +434,11 @@ module Gitlab
end
def conflicting_files_msg
- failed_files.reduce("The conflicts detected were as follows:\n") do |memo, file|
- memo << "\n - #{file}"
- end
+ header = "The conflicts detected were as follows:\n"
+ separator = "\n - "
+ failed_items = failed_files.join(separator)
+
+ "#{header}#{separator}#{failed_items}"
end
end
end
diff --git a/lib/gitlab/email/attachment_uploader.rb b/lib/gitlab/email/attachment_uploader.rb
index 83440ae227d..a826519b2dd 100644
--- a/lib/gitlab/email/attachment_uploader.rb
+++ b/lib/gitlab/email/attachment_uploader.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Email
class AttachmentUploader
diff --git a/lib/gitlab/email/handler/create_merge_request_handler.rb b/lib/gitlab/email/handler/create_merge_request_handler.rb
index e68ae60ff98..5772727e855 100644
--- a/lib/gitlab/email/handler/create_merge_request_handler.rb
+++ b/lib/gitlab/email/handler/create_merge_request_handler.rb
@@ -44,10 +44,26 @@ module Gitlab
@project ||= Project.find_by_full_path(project_path)
end
+ def metrics_params
+ super.merge(includes_patches: patch_attachments.any?)
+ end
+
private
+ def build_merge_request
+ MergeRequests::BuildService.new(project, author, merge_request_params).execute
+ end
+
def create_merge_request
- merge_request = MergeRequests::BuildService.new(project, author, merge_request_params).execute
+ merge_request = build_merge_request
+
+ if patch_attachments.any?
+ apply_patches_to_source_branch(start_branch: merge_request.target_branch)
+ remove_patch_attachments
+ # Rebuild the merge request as the source branch might just have
+ # been created, so we should re-validate.
+ merge_request = build_merge_request
+ end
if merge_request.errors.any?
merge_request
@@ -59,12 +75,42 @@ module Gitlab
def merge_request_params
params = {
source_project_id: project.id,
- source_branch: mail.subject,
+ source_branch: source_branch,
target_project_id: project.id
}
params[:description] = message if message.present?
params
end
+
+ def apply_patches_to_source_branch(start_branch:)
+ patches = patch_attachments.map { |patch| patch.body.decoded }
+
+ result = Commits::CommitPatchService
+ .new(project, author, branch_name: source_branch, patches: patches, start_branch: start_branch)
+ .execute
+
+ if result[:status] != :success
+ message = "Could not apply patches to #{source_branch}:\n#{result[:message]}"
+ raise InvalidAttachment, message
+ end
+ end
+
+ def remove_patch_attachments
+ patch_attachments.each { |patch| mail.parts.delete(patch) }
+ # reset the message, so it needs to be reporocessed when the attachments
+ # have been modified
+ @message = nil
+ end
+
+ def patch_attachments
+ @patches ||= mail.attachments
+ .select { |attachment| attachment.filename.ends_with?('.patch') }
+ .sort_by(&:filename)
+ end
+
+ def source_branch
+ @source_branch ||= mail.subject
+ end
end
end
end
diff --git a/lib/gitlab/email/hook/additional_headers_interceptor.rb b/lib/gitlab/email/hook/additional_headers_interceptor.rb
index 064cb5e659a..aa2ef76069b 100644
--- a/lib/gitlab/email/hook/additional_headers_interceptor.rb
+++ b/lib/gitlab/email/hook/additional_headers_interceptor.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Email
module Hook
diff --git a/lib/gitlab/email/hook/delivery_metrics_observer.rb b/lib/gitlab/email/hook/delivery_metrics_observer.rb
index 1c2985f6045..c7af485fcc5 100644
--- a/lib/gitlab/email/hook/delivery_metrics_observer.rb
+++ b/lib/gitlab/email/hook/delivery_metrics_observer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Email
module Hook
diff --git a/lib/gitlab/email/hook/disable_email_interceptor.rb b/lib/gitlab/email/hook/disable_email_interceptor.rb
index 7bb8b53f0c8..6b6b1d85109 100644
--- a/lib/gitlab/email/hook/disable_email_interceptor.rb
+++ b/lib/gitlab/email/hook/disable_email_interceptor.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Email
module Hook
diff --git a/lib/gitlab/email/hook/email_template_interceptor.rb b/lib/gitlab/email/hook/email_template_interceptor.rb
index be0c4dd862e..13f8db2051d 100644
--- a/lib/gitlab/email/hook/email_template_interceptor.rb
+++ b/lib/gitlab/email/hook/email_template_interceptor.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Email
module Hook
diff --git a/lib/gitlab/email/html_parser.rb b/lib/gitlab/email/html_parser.rb
index 50559a48973..77f299bcade 100644
--- a/lib/gitlab/email/html_parser.rb
+++ b/lib/gitlab/email/html_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Email
class HTMLParser
diff --git a/lib/gitlab/email/message/repository_push.rb b/lib/gitlab/email/message/repository_push.rb
index cd9d3a6483f..ec412e7a8b1 100644
--- a/lib/gitlab/email/message/repository_push.rb
+++ b/lib/gitlab/email/message/repository_push.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Email
module Message
@@ -116,7 +118,7 @@ module Gitlab
end
def subject
- subject_text = '[Git]'
+ subject_text = ['[Git]']
subject_text << "[#{project.full_path}]"
subject_text << "[#{ref_name}]" if @action == :push
subject_text << ' '
@@ -134,6 +136,8 @@ module Gitlab
subject_action[0] = subject_action[0].capitalize
subject_text << "#{subject_action} #{ref_type} #{ref_name}"
end
+
+ subject_text.join
end
end
end
diff --git a/lib/gitlab/email/receiver.rb b/lib/gitlab/email/receiver.rb
index d8c594ad0e7..d28f6b301fa 100644
--- a/lib/gitlab/email/receiver.rb
+++ b/lib/gitlab/email/receiver.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_dependency 'gitlab/email/handler'
# Inspired in great part by Discourse's Email::Receiver
@@ -18,6 +20,7 @@ module Gitlab
InvalidIssueError = Class.new(InvalidRecordError)
InvalidMergeRequestError = Class.new(InvalidRecordError)
UnknownIncomingEmail = Class.new(ProcessingError)
+ InvalidAttachment = Class.new(ProcessingError)
class Receiver
def initialize(raw)
diff --git a/lib/gitlab/email/reply_parser.rb b/lib/gitlab/email/reply_parser.rb
index ae6b84607d6..2743f011ca6 100644
--- a/lib/gitlab/email/reply_parser.rb
+++ b/lib/gitlab/email/reply_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Inspired in great part by Discourse's Email::Receiver
module Gitlab
module Email
diff --git a/lib/gitlab/emoji.rb b/lib/gitlab/emoji.rb
index 89cf659bce4..ce1dfb0753c 100644
--- a/lib/gitlab/emoji.rb
+++ b/lib/gitlab/emoji.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Emoji
extend self
diff --git a/lib/gitlab/encoding_helper.rb b/lib/gitlab/encoding_helper.rb
index 0f336fbaa10..a4a154c80f7 100644
--- a/lib/gitlab/encoding_helper.rb
+++ b/lib/gitlab/encoding_helper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module EncodingHelper
extend self
diff --git a/lib/gitlab/environment.rb b/lib/gitlab/environment.rb
index 5e0dd6e7859..b1a9603d3a5 100644
--- a/lib/gitlab/environment.rb
+++ b/lib/gitlab/environment.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Environment
def self.hostname
diff --git a/lib/gitlab/environment_logger.rb b/lib/gitlab/environment_logger.rb
index 407cc572656..862a516ca71 100644
--- a/lib/gitlab/environment_logger.rb
+++ b/lib/gitlab/environment_logger.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class EnvironmentLogger < Gitlab::Logger
def self.file_name_noext
diff --git a/lib/gitlab/etag_caching/middleware.rb b/lib/gitlab/etag_caching/middleware.rb
index d5d35dbd97f..0341f930b9c 100644
--- a/lib/gitlab/etag_caching/middleware.rb
+++ b/lib/gitlab/etag_caching/middleware.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module EtagCaching
class Middleware
diff --git a/lib/gitlab/etag_caching/router.rb b/lib/gitlab/etag_caching/router.rb
index 75167a6b088..08e30214b46 100644
--- a/lib/gitlab/etag_caching/router.rb
+++ b/lib/gitlab/etag_caching/router.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module EtagCaching
class Router
diff --git a/lib/gitlab/etag_caching/store.rb b/lib/gitlab/etag_caching/store.rb
index 21172ff8d93..2395e7be026 100644
--- a/lib/gitlab/etag_caching/store.rb
+++ b/lib/gitlab/etag_caching/store.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module EtagCaching
class Store
diff --git a/lib/gitlab/exclusive_lease.rb b/lib/gitlab/exclusive_lease.rb
index 12b5e240962..d466d2a514c 100644
--- a/lib/gitlab/exclusive_lease.rb
+++ b/lib/gitlab/exclusive_lease.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'securerandom'
module Gitlab
diff --git a/lib/gitlab/exclusive_lease_helpers.rb b/lib/gitlab/exclusive_lease_helpers.rb
index e998548cff9..7961d4bbd6e 100644
--- a/lib/gitlab/exclusive_lease_helpers.rb
+++ b/lib/gitlab/exclusive_lease_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
# This module provides helper methods which are intregrated with GitLab::ExclusiveLease
module ExclusiveLeaseHelpers
@@ -10,6 +12,8 @@ module Gitlab
# because it holds the connection until all `retries` is consumed.
# This could potentially eat up all connection pools.
def in_lock(key, ttl: 1.minute, retries: 10, sleep_sec: 0.01.seconds)
+ raise ArgumentError, 'Key needs to be specified' unless key
+
lease = Gitlab::ExclusiveLease.new(key, timeout: ttl)
until uuid = lease.try_obtain
diff --git a/lib/gitlab/fake_application_settings.rb b/lib/gitlab/fake_application_settings.rb
index 2c827265d8c..db1aeeea8d3 100644
--- a/lib/gitlab/fake_application_settings.rb
+++ b/lib/gitlab/fake_application_settings.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This class extends an OpenStruct object by adding predicate methods to mimic
# ActiveRecord access. We rely on the initial values being true or false to
# determine whether to define a predicate method because for a newly-added
diff --git a/lib/gitlab/favicon.rb b/lib/gitlab/favicon.rb
index 4850a6c0430..1ae2f9dfd93 100644
--- a/lib/gitlab/favicon.rb
+++ b/lib/gitlab/favicon.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class Favicon
class << self
@@ -47,7 +49,7 @@ module Gitlab
end
def appearance
- RequestStore.store[:appearance] ||= (Appearance.current || Appearance.new)
+ Gitlab::SafeRequestStore[:appearance] ||= (Appearance.current || Appearance.new)
end
def appearance_favicon
diff --git a/lib/gitlab/file_detector.rb b/lib/gitlab/file_detector.rb
index 8f55e94975c..2770469ca9f 100644
--- a/lib/gitlab/file_detector.rb
+++ b/lib/gitlab/file_detector.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'set'
module Gitlab
@@ -6,7 +8,7 @@ module Gitlab
module FileDetector
PATTERNS = {
# Project files
- readme: %r{\Areadme[^/]*\z}i,
+ readme: /\A(#{Regexp.union(*Gitlab::MarkupHelper::PLAIN_FILENAMES).source})(\.(#{Regexp.union(*Gitlab::MarkupHelper::EXTENSIONS).source}))?\z/i,
changelog: %r{\A(changelog|history|changes|news)[^/]*\z}i,
license: %r{\A((un)?licen[sc]e|copying)(\.[^/]+)?\z}i,
contributing: %r{\Acontributing[^/]*\z}i,
@@ -18,7 +20,6 @@ module Gitlab
# Configuration files
gitignore: '.gitignore',
- koding: '.koding.yml',
gitlab_ci: '.gitlab-ci.yml',
route_map: '.gitlab/route-map.yml',
diff --git a/lib/gitlab/file_finder.rb b/lib/gitlab/file_finder.rb
index af8270c8db8..b4db3f93c9c 100644
--- a/lib/gitlab/file_finder.rb
+++ b/lib/gitlab/file_finder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This class finds files in a repository by name and content
# the result is joined and sorted by file name
module Gitlab
diff --git a/lib/gitlab/file_markdown_link_builder.rb b/lib/gitlab/file_markdown_link_builder.rb
index 5386656efe7..180140e7da2 100644
--- a/lib/gitlab/file_markdown_link_builder.rb
+++ b/lib/gitlab/file_markdown_link_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Builds the markdown link of a file
# It needs the methods filename and secure_url (final destination url) to be defined.
module Gitlab
@@ -8,7 +10,7 @@ module Gitlab
return unless name = markdown_name
markdown = "[#{name.gsub(']', '\\]')}](#{secure_url})"
- markdown.prepend("!") if image_or_video? || dangerous?
+ markdown = "!#{markdown}" if image_or_video? || dangerous?
markdown
end
diff --git a/lib/gitlab/fogbugz_import/client.rb b/lib/gitlab/fogbugz_import/client.rb
index acb000e3e23..dd747a79673 100644
--- a/lib/gitlab/fogbugz_import/client.rb
+++ b/lib/gitlab/fogbugz_import/client.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'fogbugz'
module Gitlab
diff --git a/lib/gitlab/fogbugz_import/importer.rb b/lib/gitlab/fogbugz_import/importer.rb
index 98ea5b309a1..431911d1eee 100644
--- a/lib/gitlab/fogbugz_import/importer.rb
+++ b/lib/gitlab/fogbugz_import/importer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module FogbugzImport
class Importer
diff --git a/lib/gitlab/fogbugz_import/project_creator.rb b/lib/gitlab/fogbugz_import/project_creator.rb
index 1918d5b208d..3c71031a8d9 100644
--- a/lib/gitlab/fogbugz_import/project_creator.rb
+++ b/lib/gitlab/fogbugz_import/project_creator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module FogbugzImport
class ProjectCreator
diff --git a/lib/gitlab/fogbugz_import/repository.rb b/lib/gitlab/fogbugz_import/repository.rb
index d1dc63db2b2..b958dcf6cbf 100644
--- a/lib/gitlab/fogbugz_import/repository.rb
+++ b/lib/gitlab/fogbugz_import/repository.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module FogbugzImport
class Repository
diff --git a/lib/gitlab/gfm/reference_rewriter.rb b/lib/gitlab/gfm/reference_rewriter.rb
index 455814a9159..08d7db49ad7 100644
--- a/lib/gitlab/gfm/reference_rewriter.rb
+++ b/lib/gitlab/gfm/reference_rewriter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Gfm
##
@@ -31,19 +33,19 @@ module Gitlab
class ReferenceRewriter
RewriteError = Class.new(StandardError)
- def initialize(text, source_project, current_user)
+ def initialize(text, source_parent, current_user)
@text = text
- @source_project = source_project
+ @source_parent = source_parent
@current_user = current_user
@original_html = markdown(text)
@pattern = Gitlab::ReferenceExtractor.references_pattern
end
- def rewrite(target_project)
+ def rewrite(target_parent)
return @text unless needs_rewrite?
@text.gsub(@pattern) do |reference|
- unfold_reference(reference, Regexp.last_match, target_project)
+ unfold_reference(reference, Regexp.last_match, target_parent)
end
end
@@ -53,14 +55,14 @@ module Gitlab
private
- def unfold_reference(reference, match, target_project)
+ def unfold_reference(reference, match, target_parent)
before = @text[0...match.begin(0)]
after = @text[match.end(0)..-1]
referable = find_referable(reference)
return reference unless referable
- cross_reference = build_cross_reference(referable, target_project)
+ cross_reference = build_cross_reference(referable, target_parent)
return reference if reference == cross_reference
if cross_reference.nil?
@@ -72,17 +74,17 @@ module Gitlab
end
def find_referable(reference)
- extractor = Gitlab::ReferenceExtractor.new(@source_project,
+ extractor = Gitlab::ReferenceExtractor.new(@source_parent,
@current_user)
extractor.analyze(reference)
extractor.all.first
end
- def build_cross_reference(referable, target_project)
+ def build_cross_reference(referable, target_parent)
if referable.respond_to?(:project)
- referable.to_reference(target_project)
+ referable.to_reference(target_parent)
else
- referable.to_reference(@source_project, target_project: target_project)
+ referable.to_reference(@source_parent, target_project: target_parent)
end
end
@@ -91,7 +93,7 @@ module Gitlab
end
def markdown(text)
- Banzai.render(text, project: @source_project, no_original_data: true)
+ Banzai.render(text, project: @source_parent, no_original_data: true)
end
end
end
diff --git a/lib/gitlab/gfm/uploads_rewriter.rb b/lib/gitlab/gfm/uploads_rewriter.rb
index f7e66697da3..2d1c9ac40ae 100644
--- a/lib/gitlab/gfm/uploads_rewriter.rb
+++ b/lib/gitlab/gfm/uploads_rewriter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'fileutils'
module Gitlab
@@ -6,7 +8,7 @@ module Gitlab
# Class that rewrites markdown links for uploads
#
# Using a pattern defined in `FileUploader` it copies files to a new
- # project and rewrites all links to uploads in in a given text.
+ # project and rewrites all links to uploads in a given text.
#
#
class UploadsRewriter
@@ -16,14 +18,15 @@ module Gitlab
@pattern = FileUploader::MARKDOWN_PATTERN
end
- def rewrite(target_project)
+ def rewrite(target_parent)
return @text unless needs_rewrite?
@text.gsub(@pattern) do |markdown|
file = find_file(@source_project, $~[:secret], $~[:file])
break markdown unless file.try(:exists?)
- moved = FileUploader.copy_to(file, target_project)
+ klass = target_parent.is_a?(Namespace) ? NamespaceFileUploader : FileUploader
+ moved = klass.copy_to(file, target_parent)
moved.markdown_link
end
end
diff --git a/lib/gitlab/git.rb b/lib/gitlab/git.rb
index 2913a3e416d..c4aac228b2f 100644
--- a/lib/gitlab/git.rb
+++ b/lib/gitlab/git.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_dependency 'gitlab/encoding_helper'
module Gitlab
diff --git a/lib/gitlab/git/attributes_at_ref_parser.rb b/lib/gitlab/git/attributes_at_ref_parser.rb
index 26b5bd520d5..cbddf836ce8 100644
--- a/lib/gitlab/git/attributes_at_ref_parser.rb
+++ b/lib/gitlab/git/attributes_at_ref_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
# Parses root .gitattributes file at a given ref
diff --git a/lib/gitlab/git/attributes_parser.rb b/lib/gitlab/git/attributes_parser.rb
index 08f4d7d4f5c..8b9d74ae8e7 100644
--- a/lib/gitlab/git/attributes_parser.rb
+++ b/lib/gitlab/git/attributes_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
# Class for parsing Git attribute files and extracting the attributes for
diff --git a/lib/gitlab/git/blame.rb b/lib/gitlab/git/blame.rb
index e25e15f5c80..b118eda37f8 100644
--- a/lib/gitlab/git/blame.rb
+++ b/lib/gitlab/git/blame.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
class Blame
diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb
index 71857bd2d87..2d25389594e 100644
--- a/lib/gitlab/git/blob.rb
+++ b/lib/gitlab/git/blob.rb
@@ -1,15 +1,16 @@
-# Gitaly note: JV: seems to be completely migrated (behind feature flags).
+# frozen_string_literal: true
module Gitlab
module Git
class Blob
- include Linguist::BlobHelper
+ include Gitlab::BlobHelper
include Gitlab::EncodingHelper
+ extend Gitlab::Git::WrapsGitalyErrors
# This number is the maximum amount of data that we want to display to
- # the user. We load as much as we can for encoding detection
- # (Linguist) and LFS pointer parsing. All other cases where we need full
- # blob data should use load_all_data!.
+ # the user. We load as much as we can for encoding detection and LFS
+ # pointer parsing. All other cases where we need full blob data should
+ # use load_all_data!.
MAX_DATA_DISPLAY_SIZE = 10.megabytes
# These limits are used as a heuristic to ignore files which can't be LFS
@@ -75,7 +76,7 @@ module Gitlab
# Returns array of Gitlab::Git::Blob
# Does not guarantee blob data will be set
def batch_lfs_pointers(repository, blob_ids)
- repository.wrapped_gitaly_errors do
+ wrapped_gitaly_errors do
repository.gitaly_blob_client.batch_lfs_pointers(blob_ids.to_a)
end
end
diff --git a/lib/gitlab/git/blob_snippet.rb b/lib/gitlab/git/blob_snippet.rb
deleted file mode 100644
index 68116e775c6..00000000000
--- a/lib/gitlab/git/blob_snippet.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# Gitaly note: JV: no RPC's here.
-
-module Gitlab
- module Git
- class BlobSnippet
- include Linguist::BlobHelper
-
- attr_accessor :ref
- attr_accessor :lines
- attr_accessor :filename
- attr_accessor :startline
-
- def initialize(ref, lines, startline, filename)
- @ref, @lines, @startline, @filename = ref, lines, startline, filename
- end
-
- def data
- lines&.join("\n")
- end
-
- def name
- filename
- end
-
- def size
- data.length
- end
-
- def mode
- nil
- end
- end
- end
-end
diff --git a/lib/gitlab/git/branch.rb b/lib/gitlab/git/branch.rb
index 6351cfb83e3..9447cfa0fb6 100644
--- a/lib/gitlab/git/branch.rb
+++ b/lib/gitlab/git/branch.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
class Branch < Ref
diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb
index 5b264868af0..5863815ca85 100644
--- a/lib/gitlab/git/commit.rb
+++ b/lib/gitlab/git/commit.rb
@@ -1,8 +1,11 @@
+# frozen_string_literal: true
+
# Gitlab::Git::Commit is a wrapper around Gitaly::GitCommit
module Gitlab
module Git
class Commit
include Gitlab::EncodingHelper
+ extend Gitlab::Git::WrapsGitalyErrors
attr_accessor :raw_commit, :head
@@ -53,16 +56,13 @@ module Gitlab
# Already a commit?
return commit_id if commit_id.is_a?(Gitlab::Git::Commit)
- # A rugged reference?
- commit_id = Gitlab::Git::Ref.dereference_object(commit_id)
-
# Some weird thing?
return nil unless commit_id.is_a?(String)
# This saves us an RPC round trip.
return nil if commit_id.include?(':')
- commit = repo.wrapped_gitaly_errors do
+ commit = wrapped_gitaly_errors do
repo.gitaly_commit_client.find_commit(commit_id)
end
@@ -103,7 +103,7 @@ module Gitlab
# Commit.between(repo, '29eda46b', 'master')
#
def between(repo, base, head)
- repo.wrapped_gitaly_errors do
+ wrapped_gitaly_errors do
repo.gitaly_commit_client.between(base, head)
end
end
@@ -127,10 +127,8 @@ module Gitlab
# :topo, or any combination of them (in an array). Commit ordering types
# are documented here:
# http://www.rubydoc.info/github/libgit2/rugged/Rugged#SORT_NONE-constant)
- #
- # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/326
def find_all(repo, options = {})
- repo.wrapped_gitaly_errors do
+ wrapped_gitaly_errors do
Gitlab::GitalyClient::CommitService.new(repo).find_all_commits(options)
end
end
@@ -147,7 +145,7 @@ module Gitlab
# relation to each other. The last 10 commits for a branch for example,
# should go through .where
def batch_by_oid(repo, oids)
- repo.wrapped_gitaly_errors do
+ wrapped_gitaly_errors do
repo.gitaly_commit_client.list_commits_by_oid(oids)
end
end
@@ -157,17 +155,9 @@ module Gitlab
end
def extract_signature_lazily(repository, commit_id)
- BatchLoader.for({ repository: repository, commit_id: commit_id }).batch do |items, loader|
- items_by_repo = items.group_by { |i| i[:repository] }
-
- items_by_repo.each do |repo, items|
- commit_ids = items.map { |i| i[:commit_id] }
-
- signatures = batch_signature_extraction(repository, commit_ids)
-
- signatures.each do |commit_sha, signature_data|
- loader.call({ repository: repository, commit_id: commit_sha }, signature_data)
- end
+ BatchLoader.for(commit_id).batch(key: repository) do |commit_ids, loader, args|
+ batch_signature_extraction(args[:key], commit_ids).each do |commit_id, signature_data|
+ loader.call(commit_id, signature_data)
end
end
end
@@ -177,17 +167,9 @@ module Gitlab
end
def get_message(repository, commit_id)
- BatchLoader.for({ repository: repository, commit_id: commit_id }).batch do |items, loader|
- items_by_repo = items.group_by { |i| i[:repository] }
-
- items_by_repo.each do |repo, items|
- commit_ids = items.map { |i| i[:commit_id] }
-
- messages = get_messages(repository, commit_ids)
-
- messages.each do |commit_sha, message|
- loader.call({ repository: repository, commit_id: commit_sha }, message)
- end
+ BatchLoader.for(commit_id).batch(key: repository) do |commit_ids, loader, args|
+ get_messages(args[:key], commit_ids).each do |commit_id, message|
+ loader.call(commit_id, message)
end
end
end
@@ -328,7 +310,6 @@ module Gitlab
entry = @repository.gitaly_commit_client.tree_entry(id, path, 1)
return unless entry
- # To be compatible with the rugged format
entry = entry.to_h
entry.delete(:data)
entry[:name] = File.basename(path)
@@ -346,8 +327,8 @@ module Gitlab
subject: message_split[0] ? message_split[0].chomp.b : "",
body: raw_commit.message.b,
parent_ids: raw_commit.parent_ids,
- author: gitaly_commit_author_from_rugged(raw_commit.author),
- committer: gitaly_commit_author_from_rugged(raw_commit.committer)
+ author: gitaly_commit_author_from_raw(raw_commit.author),
+ committer: gitaly_commit_author_from_raw(raw_commit.committer)
)
end
@@ -381,7 +362,7 @@ module Gitlab
SERIALIZE_KEYS
end
- def gitaly_commit_author_from_rugged(author_or_committer)
+ def gitaly_commit_author_from_raw(author_or_committer)
Gitaly::CommitAuthor.new(
name: author_or_committer[:name].b,
email: author_or_committer[:email].b,
diff --git a/lib/gitlab/git/commit_stats.rb b/lib/gitlab/git/commit_stats.rb
index ae6f554bc06..8815088d23c 100644
--- a/lib/gitlab/git/commit_stats.rb
+++ b/lib/gitlab/git/commit_stats.rb
@@ -1,8 +1,12 @@
+# frozen_string_literal: true
+
# Gitlab::Git::CommitStats counts the additions, deletions, and total changes
# in a commit.
module Gitlab
module Git
class CommitStats
+ include Gitlab::Git::WrapsGitalyErrors
+
attr_reader :id, :additions, :deletions, :total
# Instantiate a CommitStats object
@@ -14,7 +18,7 @@ module Gitlab
@deletions = 0
@total = 0
- repo.wrapped_gitaly_errors do
+ wrapped_gitaly_errors do
gitaly_stats(repo, commit)
end
end
diff --git a/lib/gitlab/git/compare.rb b/lib/gitlab/git/compare.rb
index 7cb842256d0..ab5245ba7cb 100644
--- a/lib/gitlab/git/compare.rb
+++ b/lib/gitlab/git/compare.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Gitaly note: JV: no RPC's here.
module Gitlab
diff --git a/lib/gitlab/git/conflict/file.rb b/lib/gitlab/git/conflict/file.rb
index f08dab59ce4..7ffe4a7ae81 100644
--- a/lib/gitlab/git/conflict/file.rb
+++ b/lib/gitlab/git/conflict/file.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
module Conflict
diff --git a/lib/gitlab/git/conflict/parser.rb b/lib/gitlab/git/conflict/parser.rb
index fb5717dd556..20de8ebde4e 100644
--- a/lib/gitlab/git/conflict/parser.rb
+++ b/lib/gitlab/git/conflict/parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
module Conflict
diff --git a/lib/gitlab/git/conflict/resolution.rb b/lib/gitlab/git/conflict/resolution.rb
index ab9be683e15..04299a2d10c 100644
--- a/lib/gitlab/git/conflict/resolution.rb
+++ b/lib/gitlab/git/conflict/resolution.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
module Conflict
diff --git a/lib/gitlab/git/conflict/resolver.rb b/lib/gitlab/git/conflict/resolver.rb
index 6dc792c16b8..26e82643a4c 100644
--- a/lib/gitlab/git/conflict/resolver.rb
+++ b/lib/gitlab/git/conflict/resolver.rb
@@ -1,7 +1,11 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
module Conflict
class Resolver
+ include Gitlab::Git::WrapsGitalyErrors
+
ConflictSideMissing = Class.new(StandardError)
ResolutionError = Class.new(StandardError)
@@ -12,7 +16,7 @@ module Gitlab
end
def conflicts
- @conflicts ||= @target_repository.wrapped_gitaly_errors do
+ @conflicts ||= wrapped_gitaly_errors do
gitaly_conflicts_client(@target_repository).list_conflict_files.to_a
end
rescue GRPC::FailedPrecondition => e
@@ -22,7 +26,7 @@ module Gitlab
end
def resolve_conflicts(source_repository, resolution, source_branch:, target_branch:)
- source_repository.wrapped_gitaly_errors do
+ wrapped_gitaly_errors do
gitaly_conflicts_client(source_repository).resolve_conflicts(@target_repository, resolution, source_branch, target_branch)
end
end
diff --git a/lib/gitlab/git/diff.rb b/lib/gitlab/git/diff.rb
index f6b51dc3982..74a4633424f 100644
--- a/lib/gitlab/git/diff.rb
+++ b/lib/gitlab/git/diff.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
class Diff
@@ -19,13 +21,17 @@ module Gitlab
alias_method :expanded?, :expanded
- SERIALIZE_KEYS = %i(diff new_path old_path a_mode b_mode new_file renamed_file deleted_file too_large).freeze
+ # The default maximum content size to display a diff patch.
+ #
+ # If this value ever changes, make sure to create a migration to update
+ # current records, and default of `ApplicationSettings#diff_max_patch_bytes`.
+ DEFAULT_MAX_PATCH_BYTES = 100.kilobytes
- # The maximum size of a diff to display.
- SIZE_LIMIT = 100.kilobytes
+ # This is a limitation applied on the source (Gitaly), therefore we don't allow
+ # persisting limits over that.
+ MAX_PATCH_BYTES_UPPER_BOUND = 500.kilobytes
- # The maximum size before a diff is collapsed.
- COLLAPSE_LIMIT = 10.kilobytes
+ SERIALIZE_KEYS = %i(diff new_path old_path a_mode b_mode new_file renamed_file deleted_file too_large).freeze
class << self
def between(repo, head, base, options = {}, *paths)
@@ -68,7 +74,7 @@ module Gitlab
# and `safe_max_bytes`
#
# :expanded ::
- # If true, patch raw data will not be included in the diff after
+ # If false, patch raw data will not be included in the diff after
# `max_files`, `max_lines` or any of the limits in `limits` are
# exceeded
def filter_diff_options(options, default_options = {})
@@ -105,6 +111,26 @@ module Gitlab
def binary_message(old_path, new_path)
"Binary files #{old_path} and #{new_path} differ\n"
end
+
+ # Returns the limit of bytes a single diff file can reach before it
+ # appears as 'collapsed' for end-users.
+ # By convention, it's 10% of the persisted `diff_max_patch_bytes`.
+ #
+ # Example: If we have 100k for the `diff_max_patch_bytes`, it will be 10k by
+ # default.
+ #
+ # Patches surpassing this limit should still be persisted in the database.
+ def patch_safe_limit_bytes
+ patch_hard_limit_bytes / 10
+ end
+
+ # Returns the limit for a single diff file (patch).
+ #
+ # Patches surpassing this limit shouldn't be persisted in the database
+ # and will be presented as 'too large' for end-users.
+ def patch_hard_limit_bytes
+ Gitlab::CurrentSettings.diff_max_patch_bytes
+ end
end
def initialize(raw_diff, expanded: true)
@@ -150,7 +176,7 @@ module Gitlab
def too_large?
if @too_large.nil?
- @too_large = @diff.bytesize >= SIZE_LIMIT
+ @too_large = @diff.bytesize >= self.class.patch_hard_limit_bytes
else
@too_large
end
@@ -168,7 +194,7 @@ module Gitlab
def collapsed?
return @collapsed if defined?(@collapsed)
- @collapsed = !expanded && @diff.bytesize >= COLLAPSE_LIMIT
+ @collapsed = !expanded && @diff.bytesize >= self.class.patch_safe_limit_bytes
end
def collapse!
@@ -219,30 +245,6 @@ module Gitlab
collapse!
end
end
-
- # If the patch surpasses any of the diff limits it calls the appropiate
- # prune method and returns true. Otherwise returns false.
- def prune_large_patch(patch)
- size = 0
-
- patch.each_hunk do |hunk|
- hunk.each_line do |line|
- size += line.content.bytesize
-
- if size >= SIZE_LIMIT
- too_large!
- return true # rubocop:disable Cop/AvoidReturnFromBlocks
- end
- end
- end
-
- if !expanded && size >= COLLAPSE_LIMIT
- collapse!
- return true
- end
-
- false
- end
end
end
end
diff --git a/lib/gitlab/git/diff_collection.rb b/lib/gitlab/git/diff_collection.rb
index 20dce8d0e06..5c70cb6c66c 100644
--- a/lib/gitlab/git/diff_collection.rb
+++ b/lib/gitlab/git/diff_collection.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Gitaly note: JV: no RPC's here.
module Gitlab
@@ -19,7 +21,7 @@ module Gitlab
limits[:safe_max_files] = [limits[:max_files], DEFAULT_LIMITS[:max_files]].min
limits[:safe_max_lines] = [limits[:max_lines], DEFAULT_LIMITS[:max_lines]].min
limits[:safe_max_bytes] = limits[:safe_max_files] * 5.kilobytes # Average 5 KB per file
- limits[:max_patch_bytes] = Gitlab::Git::Diff::SIZE_LIMIT
+ limits[:max_patch_bytes] = Gitlab::Git::Diff.patch_hard_limit_bytes
OpenStruct.new(limits)
end
diff --git a/lib/gitlab/git/diff_stats_collection.rb b/lib/gitlab/git/diff_stats_collection.rb
index d4033f56387..998c41497a2 100644
--- a/lib/gitlab/git/diff_stats_collection.rb
+++ b/lib/gitlab/git/diff_stats_collection.rb
@@ -18,6 +18,10 @@ module Gitlab
indexed_by_path[path]
end
+ def paths
+ @collection.map(&:path)
+ end
+
private
def indexed_by_path
diff --git a/lib/gitlab/git/gitmodules_parser.rb b/lib/gitlab/git/gitmodules_parser.rb
index 4b505312f60..575e12390cd 100644
--- a/lib/gitlab/git/gitmodules_parser.rb
+++ b/lib/gitlab/git/gitmodules_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Gitaly note: JV: no RPC's here.
module Gitlab
diff --git a/lib/gitlab/git/hook_env.rb b/lib/gitlab/git/hook_env.rb
index 455e8451c10..892a069a3b7 100644
--- a/lib/gitlab/git/hook_env.rb
+++ b/lib/gitlab/git/hook_env.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Gitaly note: JV: no RPC's here.
module Gitlab
@@ -17,18 +19,18 @@ module Gitlab
].freeze
def self.set(gl_repository, env)
- return unless RequestStore.active?
+ return unless Gitlab::SafeRequestStore.active?
raise "missing gl_repository" if gl_repository.blank?
- RequestStore.store[:gitlab_git_env] ||= {}
- RequestStore.store[:gitlab_git_env][gl_repository] = whitelist_git_env(env)
+ Gitlab::SafeRequestStore[:gitlab_git_env] ||= {}
+ Gitlab::SafeRequestStore[:gitlab_git_env][gl_repository] = whitelist_git_env(env)
end
def self.all(gl_repository)
- return {} unless RequestStore.active?
+ return {} unless Gitlab::SafeRequestStore.active?
- h = RequestStore.fetch(:gitlab_git_env) { {} }
+ h = Gitlab::SafeRequestStore.fetch(:gitlab_git_env) { {} }
h.fetch(gl_repository, {})
end
diff --git a/lib/gitlab/git/index.rb b/lib/gitlab/git/index.rb
index c2e4274e3ee..3b9b516308f 100644
--- a/lib/gitlab/git/index.rb
+++ b/lib/gitlab/git/index.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
class Index
diff --git a/lib/gitlab/git/lfs_changes.rb b/lib/gitlab/git/lfs_changes.rb
index f0fab1e76a3..8e2a925dfea 100644
--- a/lib/gitlab/git/lfs_changes.rb
+++ b/lib/gitlab/git/lfs_changes.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
class LfsChanges
@@ -6,8 +8,8 @@ module Gitlab
@newrev = newrev
end
- def new_pointers(object_limit: nil, not_in: nil)
- @repository.gitaly_blob_client.get_new_lfs_pointers(@newrev, object_limit, not_in)
+ def new_pointers(object_limit: nil, not_in: nil, dynamic_timeout: nil)
+ @repository.gitaly_blob_client.get_new_lfs_pointers(@newrev, object_limit, not_in, dynamic_timeout)
end
def all_pointers
diff --git a/lib/gitlab/git/lfs_pointer_file.rb b/lib/gitlab/git/lfs_pointer_file.rb
index 2ae0a889590..b7019a221ac 100644
--- a/lib/gitlab/git/lfs_pointer_file.rb
+++ b/lib/gitlab/git/lfs_pointer_file.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
class LfsPointerFile
diff --git a/lib/gitlab/git/operation_service.rb b/lib/gitlab/git/operation_service.rb
index 0584629ac84..8797d3dce24 100644
--- a/lib/gitlab/git/operation_service.rb
+++ b/lib/gitlab/git/operation_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
class OperationService
diff --git a/lib/gitlab/git/patches/collection.rb b/lib/gitlab/git/patches/collection.rb
new file mode 100644
index 00000000000..ad6b5d32abc
--- /dev/null
+++ b/lib/gitlab/git/patches/collection.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Git
+ module Patches
+ class Collection
+ MAX_PATCH_SIZE = 2.megabytes
+
+ def initialize(one_or_more_patches)
+ @patches = Array(one_or_more_patches).map do |patch_content|
+ Gitlab::Git::Patches::Patch.new(patch_content)
+ end
+ end
+
+ def content
+ @patches.map(&:content).join("\n")
+ end
+
+ def valid_size?
+ size < MAX_PATCH_SIZE
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ # `@patches` is not an `ActiveRecord` relation, but an `Enumerable`
+ # We're using sum from `ActiveSupport`
+ def size
+ @size ||= @patches.sum(&:size)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/patches/commit_patches.rb b/lib/gitlab/git/patches/commit_patches.rb
new file mode 100644
index 00000000000..c62994432d3
--- /dev/null
+++ b/lib/gitlab/git/patches/commit_patches.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Git
+ module Patches
+ class CommitPatches
+ include Gitlab::Git::WrapsGitalyErrors
+
+ def initialize(user, repository, branch, patch_collection)
+ @user, @repository, @branch, @patches = user, repository, branch, patch_collection
+ end
+
+ def commit
+ repository.with_cache_hooks do
+ wrapped_gitaly_errors do
+ operation_service.user_commit_patches(user, branch, patches.content)
+ end
+ end
+ end
+
+ private
+
+ attr_reader :user, :repository, :branch, :patches
+
+ def operation_service
+ repository.raw.gitaly_operation_client
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/patches/patch.rb b/lib/gitlab/git/patches/patch.rb
new file mode 100644
index 00000000000..fe6ae1b5b00
--- /dev/null
+++ b/lib/gitlab/git/patches/patch.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Git
+ module Patches
+ class Patch
+ attr_reader :content
+
+ def initialize(content)
+ @content = content
+ end
+
+ def size
+ content.bytesize
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/path_helper.rb b/lib/gitlab/git/path_helper.rb
index 57b82a37d6c..e3a2031eeca 100644
--- a/lib/gitlab/git/path_helper.rb
+++ b/lib/gitlab/git/path_helper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Gitaly note: JV: no RPC's here.
module Gitlab
diff --git a/lib/gitlab/git/pre_receive_error.rb b/lib/gitlab/git/pre_receive_error.rb
index ac1ab7c39d5..03caace6fce 100644
--- a/lib/gitlab/git/pre_receive_error.rb
+++ b/lib/gitlab/git/pre_receive_error.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
#
diff --git a/lib/gitlab/git/push.rb b/lib/gitlab/git/push.rb
new file mode 100644
index 00000000000..b6577ba17f1
--- /dev/null
+++ b/lib/gitlab/git/push.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Git
+ class Push
+ include Gitlab::Utils::StrongMemoize
+
+ attr_reader :ref, :oldrev, :newrev
+
+ def initialize(project, oldrev, newrev, ref)
+ @project = project
+ @oldrev = oldrev.presence || Gitlab::Git::BLANK_SHA
+ @newrev = newrev.presence || Gitlab::Git::BLANK_SHA
+ @ref = ref
+ end
+
+ def branch_name
+ strong_memoize(:branch_name) do
+ Gitlab::Git.branch_name(@ref)
+ end
+ end
+
+ def branch_added?
+ Gitlab::Git.blank_ref?(@oldrev)
+ end
+
+ def branch_removed?
+ Gitlab::Git.blank_ref?(@newrev)
+ end
+
+ def branch_updated?
+ branch_push? && !branch_added? && !branch_removed?
+ end
+
+ def force_push?
+ Gitlab::Checks::ForcePush.force_push?(@project, @oldrev, @newrev)
+ end
+
+ def branch_push?
+ strong_memoize(:branch_push) do
+ Gitlab::Git.branch_ref?(@ref)
+ end
+ end
+
+ def modified_paths
+ unless branch_updated?
+ raise ArgumentError, 'Unable to calculate modified paths!'
+ end
+
+ strong_memoize(:modified_paths) do
+ @project.repository.diff_stats(@oldrev, @newrev).paths
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/raw_diff_change.rb b/lib/gitlab/git/raw_diff_change.rb
index 98de9328071..e1002af40f6 100644
--- a/lib/gitlab/git/raw_diff_change.rb
+++ b/lib/gitlab/git/raw_diff_change.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
# This class behaves like a struct with fields :blob_id, :blob_size, :operation, :old_path, :new_path
diff --git a/lib/gitlab/git/ref.rb b/lib/gitlab/git/ref.rb
index fa71a4e7ea7..eec91194949 100644
--- a/lib/gitlab/git/ref.rb
+++ b/lib/gitlab/git/ref.rb
@@ -1,4 +1,4 @@
-# Gitaly note: JV: probably no RPC's here (just one interaction with Rugged).
+# frozen_string_literal: true
module Gitlab
module Git
@@ -26,13 +26,6 @@ module Gitlab
str.gsub(%r{\Arefs/heads/}, '')
end
- # Gitaly: this method will probably be migrated indirectly via its call sites.
- def self.dereference_object(object)
- object = object.target while object.is_a?(Rugged::Tag::Annotation)
-
- object
- end
-
def initialize(repository, name, target, dereferenced_target)
@name = Gitlab::Git.ref_name(name)
@dereferenced_target = dereferenced_target
diff --git a/lib/gitlab/git/remote_mirror.rb b/lib/gitlab/git/remote_mirror.rb
index e4743b4db0a..df3cd422527 100644
--- a/lib/gitlab/git/remote_mirror.rb
+++ b/lib/gitlab/git/remote_mirror.rb
@@ -1,14 +1,28 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
class RemoteMirror
- def initialize(repository, ref_name)
+ include Gitlab::Git::WrapsGitalyErrors
+
+ attr_reader :repository, :ref_name, :only_branches_matching, :ssh_key, :known_hosts
+
+ def initialize(repository, ref_name, only_branches_matching: [], ssh_key: nil, known_hosts: nil)
@repository = repository
@ref_name = ref_name
+ @only_branches_matching = only_branches_matching
+ @ssh_key = ssh_key
+ @known_hosts = known_hosts
end
- def update(only_branches_matching: [])
- @repository.wrapped_gitaly_errors do
- @repository.gitaly_remote_client.update_remote_mirror(@ref_name, only_branches_matching)
+ def update
+ wrapped_gitaly_errors do
+ repository.gitaly_remote_client.update_remote_mirror(
+ ref_name,
+ only_branches_matching,
+ ssh_key: ssh_key,
+ known_hosts: known_hosts
+ )
end
end
end
diff --git a/lib/gitlab/git/remote_repository.rb b/lib/gitlab/git/remote_repository.rb
index f40e59a8dd0..234541d8145 100644
--- a/lib/gitlab/git/remote_repository.rb
+++ b/lib/gitlab/git/remote_repository.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
#
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 3d5a63bdbac..0a541031884 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'tempfile'
require 'forwardable'
require "rubygems/package"
@@ -6,17 +8,10 @@ module Gitlab
module Git
class Repository
include Gitlab::Git::RepositoryMirroring
+ include Gitlab::Git::WrapsGitalyErrors
include Gitlab::EncodingHelper
include Gitlab::Utils::StrongMemoize
- ALLOWED_OBJECT_DIRECTORIES_VARIABLES = %w[
- GIT_OBJECT_DIRECTORY
- GIT_ALTERNATE_OBJECT_DIRECTORIES
- ].freeze
- ALLOWED_OBJECT_RELATIVE_DIRECTORIES_VARIABLES = %w[
- GIT_OBJECT_DIRECTORY_RELATIVE
- GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE
- ].freeze
SEARCH_CONTEXT_LINES = 3
REV_LIST_COMMIT_LIMIT = 2_000
# In https://gitlab.com/gitlab-org/gitaly/merge_requests/698
@@ -85,7 +80,13 @@ module Gitlab
end
def ==(other)
- [storage, relative_path] == [other.storage, other.relative_path]
+ other.is_a?(self.class) && [storage, relative_path] == [other.storage, other.relative_path]
+ end
+
+ alias_method :eql?, :==
+
+ def hash
+ [self.class, storage, relative_path].hash
end
# This method will be removed when Gitaly reaches v1.1.
@@ -104,19 +105,6 @@ module Gitlab
raise Gitlab::Git::CommandError.new(e.message)
end
- # This method will be removed when Gitaly reaches v1.1.
- def rugged
- circuit_breaker.perform do
- Rugged::Repository.new(path, alternates: alternate_object_directories)
- end
- rescue Rugged::RepositoryError, Rugged::OSError
- raise NoRepository.new('no repository for such path')
- end
-
- def circuit_breaker
- @circuit_breaker ||= Gitlab::Git::Storage::CircuitBreaker.for_storage(storage)
- end
-
def exists?
gitaly_repository_client.exists?
end
@@ -403,9 +391,9 @@ module Gitlab
end
# Returns the SHA of the most recent common ancestor of +from+ and +to+
- def merge_base(from, to)
+ def merge_base(*commits)
wrapped_gitaly_errors do
- gitaly_repository_client.find_merge_base(from, to)
+ gitaly_repository_client.find_merge_base(*commits)
end
end
@@ -439,13 +427,17 @@ module Gitlab
end
def diff_stats(left_id, right_id)
+ if [left_id, right_id].any? { |ref| ref.blank? || Gitlab::Git.blank_ref?(ref) }
+ return empty_diff_stats
+ end
+
stats = wrapped_gitaly_errors do
gitaly_commit_client.diff_stats(left_id, right_id)
end
Gitlab::Git::DiffStatsCollection.new(stats)
rescue CommandError, TypeError
- Gitlab::Git::DiffStatsCollection.new([])
+ empty_diff_stats
end
# Returns a RefName for a given SHA
@@ -455,7 +447,7 @@ module Gitlab
gitaly_ref_client.find_ref_name(sha, ref_path)
end
- # Get refs hash which key is is the commit id
+ # Get refs hash which key is the commit id
# and value is a Gitlab::Git::Tag or Gitlab::Git::Branch
# Note that both inherit from Gitlab::Git::Ref
def refs_hash
@@ -591,6 +583,20 @@ module Gitlab
end
end
+ def update_submodule(user:, submodule:, commit_sha:, message:, branch:)
+ args = {
+ user: user,
+ submodule: submodule,
+ commit_sha: commit_sha,
+ branch: branch,
+ message: message
+ }
+
+ wrapped_gitaly_errors do
+ gitaly_operation_client.user_update_submodule(args)
+ end
+ end
+
# Delete the specified branch from the repository
def delete_branch(branch_name)
wrapped_gitaly_errors do
@@ -638,20 +644,6 @@ module Gitlab
end
end
- AUTOCRLF_VALUES = {
- "true" => true,
- "false" => false,
- "input" => :input
- }.freeze
-
- def autocrlf
- AUTOCRLF_VALUES[rugged.config['core.autocrlf']]
- end
-
- def autocrlf=(value)
- rugged.config['core.autocrlf'] = AUTOCRLF_VALUES.invert[value]
- end
-
# Returns result like "git ls-files" , recursive and full file path
#
# Ex.
@@ -731,11 +723,11 @@ module Gitlab
delete_refs(tmp_ref)
end
- def write_ref(ref_path, ref, old_ref: nil, shell: true)
+ def write_ref(ref_path, ref, old_ref: nil)
ref_path = "#{Gitlab::Git::BRANCH_REF_PREFIX}#{ref_path}" unless ref_path.start_with?("refs/") || ref_path == "HEAD"
wrapped_gitaly_errors do
- gitaly_repository_client.write_ref(ref_path, ref, old_ref, shell)
+ gitaly_repository_client.write_ref(ref_path, ref, old_ref)
end
end
@@ -754,6 +746,26 @@ module Gitlab
end
end
+ # Fetch remote for repository
+ #
+ # remote - remote name
+ # ssh_auth - SSH known_hosts data and a private key to use for public-key authentication
+ # forced - should we use --force flag?
+ # no_tags - should we use --no-tags flag?
+ # prune - should we use --prune flag?
+ def fetch_remote(remote, ssh_auth: nil, forced: false, no_tags: false, prune: true)
+ wrapped_gitaly_errors do
+ gitaly_repository_client.fetch_remote(
+ remote,
+ ssh_auth: ssh_auth,
+ forced: forced,
+ no_tags: no_tags,
+ prune: prune,
+ timeout: GITLAB_PROJECTS_TIMEOUT
+ )
+ end
+ end
+
def blob_at(sha, path)
Gitlab::Git::Blob.find(self, sha, path) unless Gitlab::Git.blank_ref?(sha)
end
@@ -879,26 +891,6 @@ module Gitlab
Gitlab::GitalyClient::ConflictsService.new(self, our_commit_oid, their_commit_oid)
end
- def gitaly_migrate(method, status: Gitlab::GitalyClient::MigrationStatus::OPT_IN, &block)
- Gitlab::GitalyClient.migrate(method, status: status, &block)
- rescue GRPC::NotFound => e
- raise NoRepository.new(e)
- rescue GRPC::InvalidArgument => e
- raise ArgumentError.new(e)
- rescue GRPC::BadStatus => e
- raise CommandError.new(e)
- end
-
- def wrapped_gitaly_errors(&block)
- yield block
- rescue GRPC::NotFound => e
- raise NoRepository.new(e)
- rescue GRPC::InvalidArgument => e
- raise ArgumentError.new(e)
- rescue GRPC::BadStatus => e
- raise CommandError.new(e)
- end
-
def clean_stale_repository_files
wrapped_gitaly_errors do
gitaly_repository_client.cleanup if exists?
@@ -953,6 +945,12 @@ module Gitlab
end
end
+ def list_last_commits_for_tree(sha, path, offset: 0, limit: 25)
+ wrapped_gitaly_errors do
+ gitaly_commit_client.list_last_commits_for_tree(sha, path, offset: offset, limit: limit)
+ end
+ end
+
def last_commit_for_path(sha, path)
wrapped_gitaly_errors do
gitaly_commit_client.last_commit_for_path(sha, path)
@@ -970,6 +968,10 @@ module Gitlab
private
+ def empty_diff_stats
+ Gitlab::Git::DiffStatsCollection.new([])
+ end
+
def uncached_has_local_branches?
wrapped_gitaly_errors do
gitaly_repository_client.has_local_branches?
@@ -1018,14 +1020,6 @@ module Gitlab
found_module && found_module['url']
end
- def alternate_object_directories
- relative_object_directories.map { |d| File.join(path, d) }
- end
-
- def relative_object_directories
- Gitlab::Git::HookEnv.all(gl_repository).values_at(*ALLOWED_OBJECT_RELATIVE_DIRECTORIES_VARIABLES).flatten.compact
- end
-
# Returns true if the given ref name exists
#
# Ref names must start with `refs/`.
diff --git a/lib/gitlab/git/repository_mirroring.rb b/lib/gitlab/git/repository_mirroring.rb
index 752a91fbb60..7e63a6dc7cb 100644
--- a/lib/gitlab/git/repository_mirroring.rb
+++ b/lib/gitlab/git/repository_mirroring.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
module RepositoryMirroring
diff --git a/lib/gitlab/git/storage.rb b/lib/gitlab/git/storage.rb
deleted file mode 100644
index 5933312b0b5..00000000000
--- a/lib/gitlab/git/storage.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-module Gitlab
- module Git
- module Storage
- class Inaccessible < StandardError
- attr_reader :retry_after
-
- def initialize(message = nil, retry_after = nil)
- super(message)
- @retry_after = retry_after
- end
- end
-
- CircuitOpen = Class.new(Inaccessible)
- Misconfiguration = Class.new(Inaccessible)
- Failing = Class.new(Inaccessible)
-
- REDIS_KEY_PREFIX = 'storage_accessible:'.freeze
- REDIS_KNOWN_KEYS = "#{REDIS_KEY_PREFIX}known_keys_set".freeze
-
- def self.redis
- Gitlab::Redis::SharedState
- end
- end
- end
-end
diff --git a/lib/gitlab/git/storage/checker.rb b/lib/gitlab/git/storage/checker.rb
deleted file mode 100644
index 391f0d70583..00000000000
--- a/lib/gitlab/git/storage/checker.rb
+++ /dev/null
@@ -1,120 +0,0 @@
-module Gitlab
- module Git
- module Storage
- class Checker
- include CircuitBreakerSettings
-
- attr_reader :storage_path, :storage, :hostname, :logger
- METRICS_MUTEX = Mutex.new
- STORAGE_TIMING_BUCKETS = [0.1, 0.15, 0.25, 0.33, 0.5, 1, 1.5, 2.5, 5, 10, 15].freeze
-
- def self.check_all(logger = Rails.logger)
- threads = Gitlab.config.repositories.storages.keys.map do |storage_name|
- Thread.new do
- Thread.current[:result] = new(storage_name, logger).check_with_lease
- end
- end
-
- threads.map do |thread|
- thread.join
- thread[:result]
- end
- end
-
- def self.check_histogram
- @check_histogram ||=
- METRICS_MUTEX.synchronize do
- @check_histogram || Gitlab::Metrics.histogram(:circuitbreaker_storage_check_duration_seconds,
- 'Storage check time in seconds',
- {},
- STORAGE_TIMING_BUCKETS
- )
- end
- end
-
- def initialize(storage, logger = Rails.logger)
- @storage = storage
- config = Gitlab.config.repositories.storages[@storage]
- @storage_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access { config.legacy_disk_path }
- @logger = logger
-
- @hostname = Gitlab::Environment.hostname
- end
-
- def check_with_lease
- lease_key = "storage_check:#{cache_key}"
- lease = Gitlab::ExclusiveLease.new(lease_key, timeout: storage_timeout)
- result = { storage: storage, success: nil }
-
- if uuid = lease.try_obtain
- result[:success] = check
-
- Gitlab::ExclusiveLease.cancel(lease_key, uuid)
- else
- logger.warn("#{hostname}: #{storage}: Skipping check, previous check still running")
- end
-
- result
- end
-
- def check
- if perform_access_check
- track_storage_accessible
- true
- else
- track_storage_inaccessible
- logger.error("#{hostname}: #{storage}: Not accessible.")
- false
- end
- end
-
- private
-
- def perform_access_check
- start_time = Gitlab::Metrics::System.monotonic_time
-
- Gitlab::Git::Storage::ForkedStorageCheck.storage_available?(storage_path, storage_timeout, access_retries)
- ensure
- execution_time = Gitlab::Metrics::System.monotonic_time - start_time
- self.class.check_histogram.observe({ storage: storage }, execution_time)
- end
-
- def track_storage_inaccessible
- first_failure = current_failure_info.first_failure || Time.now
- last_failure = Time.now
-
- Gitlab::Git::Storage.redis.with do |redis|
- redis.pipelined do
- redis.hset(cache_key, :first_failure, first_failure.to_i)
- redis.hset(cache_key, :last_failure, last_failure.to_i)
- redis.hincrby(cache_key, :failure_count, 1)
- redis.expire(cache_key, failure_reset_time)
- maintain_known_keys(redis)
- end
- end
- end
-
- def track_storage_accessible
- Gitlab::Git::Storage.redis.with do |redis|
- redis.pipelined do
- redis.hset(cache_key, :first_failure, nil)
- redis.hset(cache_key, :last_failure, nil)
- redis.hset(cache_key, :failure_count, 0)
- maintain_known_keys(redis)
- end
- end
- end
-
- def maintain_known_keys(redis)
- expire_time = Time.now.to_i + failure_reset_time
- redis.zadd(Gitlab::Git::Storage::REDIS_KNOWN_KEYS, expire_time, cache_key)
- redis.zremrangebyscore(Gitlab::Git::Storage::REDIS_KNOWN_KEYS, '-inf', Time.now.to_i)
- end
-
- def current_failure_info
- FailureInfo.load(cache_key)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/git/storage/circuit_breaker.rb b/lib/gitlab/git/storage/circuit_breaker.rb
deleted file mode 100644
index 62427ac9cc4..00000000000
--- a/lib/gitlab/git/storage/circuit_breaker.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-module Gitlab
- module Git
- module Storage
- class CircuitBreaker
- include CircuitBreakerSettings
-
- attr_reader :storage,
- :hostname
-
- delegate :last_failure, :failure_count, :no_failures?,
- to: :failure_info
-
- def self.for_storage(storage)
- cached_circuitbreakers = RequestStore.fetch(:circuitbreaker_cache) do
- Hash.new do |hash, storage_name|
- hash[storage_name] = build(storage_name)
- end
- end
-
- cached_circuitbreakers[storage]
- end
-
- def self.build(storage, hostname = Gitlab::Environment.hostname)
- config = Gitlab.config.repositories.storages[storage]
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- if !config.present?
- NullCircuitBreaker.new(storage, hostname, error: Misconfiguration.new("Storage '#{storage}' is not configured"))
- elsif !config.legacy_disk_path.present?
- NullCircuitBreaker.new(storage, hostname, error: Misconfiguration.new("Path for storage '#{storage}' is not configured"))
- else
- new(storage, hostname)
- end
- end
- end
-
- def initialize(storage, hostname)
- @storage = storage
- @hostname = hostname
- end
-
- def perform
- return yield unless enabled?
-
- check_storage_accessible!
-
- yield
- end
-
- def circuit_broken?
- return false if no_failures?
-
- failure_count > failure_count_threshold
- end
-
- private
-
- # The circuitbreaker can be enabled for the entire fleet using a Feature
- # flag.
- #
- # Enabling it for a single host can be done setting the
- # `GIT_STORAGE_CIRCUIT_BREAKER` environment variable.
- def enabled?
- ENV['GIT_STORAGE_CIRCUIT_BREAKER'].present? || Feature.enabled?('git_storage_circuit_breaker')
- end
-
- def failure_info
- @failure_info ||= FailureInfo.load(cache_key)
- end
-
- def check_storage_accessible!
- if circuit_broken?
- raise Gitlab::Git::Storage::CircuitOpen.new("Circuit for #{storage} is broken", failure_reset_time)
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/git/storage/circuit_breaker_settings.rb b/lib/gitlab/git/storage/circuit_breaker_settings.rb
deleted file mode 100644
index c9e225f187d..00000000000
--- a/lib/gitlab/git/storage/circuit_breaker_settings.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-module Gitlab
- module Git
- module Storage
- module CircuitBreakerSettings
- def failure_count_threshold
- application_settings.circuitbreaker_failure_count_threshold
- end
-
- def failure_reset_time
- application_settings.circuitbreaker_failure_reset_time
- end
-
- def storage_timeout
- application_settings.circuitbreaker_storage_timeout
- end
-
- def access_retries
- application_settings.circuitbreaker_access_retries
- end
-
- def check_interval
- application_settings.circuitbreaker_check_interval
- end
-
- def cache_key
- @cache_key ||= "#{Gitlab::Git::Storage::REDIS_KEY_PREFIX}#{storage}:#{hostname}"
- end
-
- private
-
- def application_settings
- Gitlab::CurrentSettings.current_application_settings
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/git/storage/failure_info.rb b/lib/gitlab/git/storage/failure_info.rb
deleted file mode 100644
index 387279c110d..00000000000
--- a/lib/gitlab/git/storage/failure_info.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-module Gitlab
- module Git
- module Storage
- class FailureInfo
- attr_accessor :first_failure, :last_failure, :failure_count
-
- def self.reset_all!
- Gitlab::Git::Storage.redis.with do |redis|
- all_storage_keys = redis.zrange(Gitlab::Git::Storage::REDIS_KNOWN_KEYS, 0, -1)
- redis.del(*all_storage_keys) unless all_storage_keys.empty?
- end
-
- RequestStore.delete(:circuitbreaker_cache)
- end
-
- def self.load(cache_key)
- first_failure, last_failure, failure_count = Gitlab::Git::Storage.redis.with do |redis|
- redis.hmget(cache_key, :first_failure, :last_failure, :failure_count)
- end
-
- last_failure = Time.at(last_failure.to_i) if last_failure.present?
- first_failure = Time.at(first_failure.to_i) if first_failure.present?
-
- new(first_failure, last_failure, failure_count.to_i)
- end
-
- def initialize(first_failure, last_failure, failure_count)
- @first_failure = first_failure
- @last_failure = last_failure
- @failure_count = failure_count
- end
-
- def no_failures?
- first_failure.blank? && last_failure.blank? && failure_count == 0
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/git/storage/forked_storage_check.rb b/lib/gitlab/git/storage/forked_storage_check.rb
deleted file mode 100644
index 0a4e557b59b..00000000000
--- a/lib/gitlab/git/storage/forked_storage_check.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-module Gitlab
- module Git
- module Storage
- module ForkedStorageCheck
- extend self
-
- def storage_available?(path, timeout_seconds = 5, retries = 1)
- partial_timeout = timeout_seconds / retries
- status = timeout_check(path, partial_timeout)
-
- # If the status check did not succeed the first time, we retry a few
- # more times to avoid one-off failures
- current_attempts = 1
- while current_attempts < retries && !status.success?
- status = timeout_check(path, partial_timeout)
- current_attempts += 1
- end
-
- status.success?
- end
-
- def timeout_check(path, timeout_seconds)
- filesystem_check_pid = check_filesystem_in_process(path)
-
- deadline = timeout_seconds.seconds.from_now.utc
- wait_time = 0.01
- status = nil
-
- while status.nil?
-
- if deadline > Time.now.utc
- sleep(wait_time)
- _pid, status = Process.wait2(filesystem_check_pid, Process::WNOHANG)
- else
- Process.kill('KILL', filesystem_check_pid)
- # Blocking wait, so we are sure the process is gone before continuing
- _pid, status = Process.wait2(filesystem_check_pid)
- end
- end
-
- status
- end
-
- # This will spawn a new 2 processes to do the check:
- # The outer child (waiter) will spawn another child process (stater).
- #
- # The stater is the process is performing the actual filesystem check
- # the check might hang if the filesystem is acting up.
- # In this case we will send a `KILL` to the waiter, which will still
- # be responsive while the stater is hanging.
- def check_filesystem_in_process(path)
- spawn('ruby', '-e', ruby_check, path, [:out, :err] => '/dev/null')
- end
-
- def ruby_check
- <<~RUBY_FILESYSTEM_CHECK
- inner_pid = fork { File.stat(ARGV.first) }
- Process.waitpid(inner_pid)
- exit $?.exitstatus
- RUBY_FILESYSTEM_CHECK
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/git/storage/health.rb b/lib/gitlab/git/storage/health.rb
deleted file mode 100644
index 8e14acb4ccb..00000000000
--- a/lib/gitlab/git/storage/health.rb
+++ /dev/null
@@ -1,92 +0,0 @@
-module Gitlab
- module Git
- module Storage
- class Health
- attr_reader :storage_name, :info
-
- def self.prefix_for_storage(storage_name)
- "#{Gitlab::Git::Storage::REDIS_KEY_PREFIX}#{storage_name}:"
- end
-
- def self.for_all_storages
- storage_names = Gitlab.config.repositories.storages.keys
- results_per_storage = nil
-
- Gitlab::Git::Storage.redis.with do |redis|
- keys_per_storage = all_keys_for_storages(storage_names, redis)
- results_per_storage = load_for_keys(keys_per_storage, redis)
- end
-
- results_per_storage.map do |name, info|
- info.each { |i| i[:failure_count] = i[:failure_count].value.to_i }
- new(name, info)
- end
- end
-
- private_class_method def self.all_keys_for_storages(storage_names, redis)
- keys_per_storage = {}
- all_keys = redis.zrange(Gitlab::Git::Storage::REDIS_KNOWN_KEYS, 0, -1)
-
- storage_names.each do |storage_name|
- prefix = prefix_for_storage(storage_name)
-
- keys_per_storage[storage_name] = all_keys.select { |key| key.starts_with?(prefix) }
- end
-
- keys_per_storage
- end
-
- private_class_method def self.load_for_keys(keys_per_storage, redis)
- info_for_keys = {}
-
- redis.pipelined do
- keys_per_storage.each do |storage_name, keys_future|
- info_for_storage = keys_future.map do |key|
- { name: key, failure_count: redis.hget(key, :failure_count) }
- end
-
- info_for_keys[storage_name] = info_for_storage
- end
- end
-
- info_for_keys
- end
-
- def self.for_failing_storages
- for_all_storages.select(&:failing?)
- end
-
- def initialize(storage_name, info)
- @storage_name = storage_name
- @info = info
- end
-
- def failing_info
- @failing_info ||= info.select { |info_for_host| info_for_host[:failure_count] > 0 }
- end
-
- def failing?
- failing_info.any?
- end
-
- def failing_on_hosts
- @failing_on_hosts ||= failing_info.map do |info_for_host|
- info_for_host[:name].split(':').last
- end
- end
-
- def failing_circuit_breakers
- @failing_circuit_breakers ||= failing_on_hosts.map do |hostname|
- CircuitBreaker.build(storage_name, hostname)
- end
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def total_failures
- @total_failures ||= failing_info.sum { |info_for_host| info_for_host[:failure_count] }
- end
- # rubocop: enable CodeReuse/ActiveRecord
- end
- end
- end
-end
diff --git a/lib/gitlab/git/storage/null_circuit_breaker.rb b/lib/gitlab/git/storage/null_circuit_breaker.rb
deleted file mode 100644
index 261c936c689..00000000000
--- a/lib/gitlab/git/storage/null_circuit_breaker.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-module Gitlab
- module Git
- module Storage
- class NullCircuitBreaker
- include CircuitBreakerSettings
-
- # These will have actual values
- attr_reader :storage,
- :hostname
-
- # These will always have nil values
- attr_reader :storage_path
-
- delegate :last_failure, :failure_count, :no_failures?,
- to: :failure_info
-
- def initialize(storage, hostname, error: nil)
- @storage = storage
- @hostname = hostname
- @error = error
- end
-
- def perform
- @error ? raise(@error) : yield
- end
-
- def circuit_broken?
- !!@error
- end
-
- def backing_off?
- false
- end
-
- def failure_info
- @failure_info ||=
- if circuit_broken?
- Gitlab::Git::Storage::FailureInfo.new(Time.now,
- Time.now,
- failure_count_threshold)
- else
- Gitlab::Git::Storage::FailureInfo.new(nil,
- nil,
- 0)
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/git/tag.rb b/lib/gitlab/git/tag.rb
index bbf2ecdb1fa..23d989ff258 100644
--- a/lib/gitlab/git/tag.rb
+++ b/lib/gitlab/git/tag.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
class Tag < Ref
@@ -12,17 +14,9 @@ module Gitlab
class << self
def get_message(repository, tag_id)
- BatchLoader.for({ repository: repository, tag_id: tag_id }).batch do |items, loader|
- items_by_repo = items.group_by { |i| i[:repository] }
-
- items_by_repo.each do |repo, items|
- tag_ids = items.map { |i| i[:tag_id] }
-
- messages = get_messages(repository, tag_ids)
-
- messages.each do |id, message|
- loader.call({ repository: repository, tag_id: id }, message)
- end
+ BatchLoader.for(tag_id).batch(key: repository) do |tag_ids, loader, args|
+ get_messages(args[:key], tag_ids).each do |tag_id, message|
+ loader.call(tag_id, message)
end
end
end
diff --git a/lib/gitlab/git/tree.rb b/lib/gitlab/git/tree.rb
index e0867aeb5a7..51542bcaaa2 100644
--- a/lib/gitlab/git/tree.rb
+++ b/lib/gitlab/git/tree.rb
@@ -1,7 +1,10 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
class Tree
include Gitlab::EncodingHelper
+ extend Gitlab::Git::WrapsGitalyErrors
attr_accessor :id, :root_id, :name, :path, :flat_path, :type,
:mode, :commit_id, :submodule_url
@@ -15,7 +18,7 @@ module Gitlab
def where(repository, sha, path = nil, recursive = false)
path = nil if path == '' || path == '/'
- repository.wrapped_gitaly_errors do
+ wrapped_gitaly_errors do
repository.gitaly_commit_client.tree_entries(repository, sha, path, recursive)
end
end
diff --git a/lib/gitlab/git/user.rb b/lib/gitlab/git/user.rb
index 338e1a30c45..2c798844798 100644
--- a/lib/gitlab/git/user.rb
+++ b/lib/gitlab/git/user.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
class User
diff --git a/lib/gitlab/git/util.rb b/lib/gitlab/git/util.rb
index 4708f22dcb3..03c2c1367b0 100644
--- a/lib/gitlab/git/util.rb
+++ b/lib/gitlab/git/util.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Gitaly note: JV: no RPC's here.
module Gitlab
diff --git a/lib/gitlab/git/version.rb b/lib/gitlab/git/version.rb
index 4bd91898457..64c89656167 100644
--- a/lib/gitlab/git/version.rb
+++ b/lib/gitlab/git/version.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
module Version
diff --git a/lib/gitlab/git/wiki.rb b/lib/gitlab/git/wiki.rb
index ae92a624e05..c43331bed60 100644
--- a/lib/gitlab/git/wiki.rb
+++ b/lib/gitlab/git/wiki.rb
@@ -1,15 +1,57 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
class Wiki
+ include Gitlab::Git::WrapsGitalyErrors
+
DuplicatePageError = Class.new(StandardError)
OperationError = Class.new(StandardError)
+ DEFAULT_PAGINATION = Kaminari.config.default_per_page
+
CommitDetails = Struct.new(:user_id, :username, :name, :email, :message) do
def to_h
{ user_id: user_id, username: username, name: name, email: email, message: message }
end
end
- PageBlob = Struct.new(:name)
+
+ # GollumSlug inlines just enough knowledge from Gollum::Page to generate a
+ # slug, which is used when previewing pages that haven't been persisted
+ class GollumSlug
+ class << self
+ def cname(name, char_white_sub = '-', char_other_sub = '-')
+ if name.respond_to?(:gsub)
+ name.gsub(/\s/, char_white_sub).gsub(/[<>+]/, char_other_sub)
+ else
+ ''
+ end
+ end
+
+ def format_to_ext(format)
+ format == :markdown ? "md" : format.to_s
+ end
+
+ def canonicalize_filename(filename)
+ ::File.basename(filename, ::File.extname(filename)).tr('-', ' ')
+ end
+
+ def generate(title, format)
+ ext = format_to_ext(format.to_sym)
+ name = cname(title) + '.' + ext
+ canonical_name = canonicalize_filename(name)
+
+ path =
+ if name.include?('/')
+ name.sub(%r{/[^/]+$}, '/')
+ else
+ ''
+ end
+
+ path + cname(canonical_name, '-', '-')
+ end
+ end
+ end
attr_reader :repository
@@ -27,37 +69,37 @@ module Gitlab
end
def write_page(name, format, content, commit_details)
- @repository.wrapped_gitaly_errors do
+ wrapped_gitaly_errors do
gitaly_write_page(name, format, content, commit_details)
end
end
def delete_page(page_path, commit_details)
- @repository.wrapped_gitaly_errors do
+ wrapped_gitaly_errors do
gitaly_delete_page(page_path, commit_details)
end
end
def update_page(page_path, title, format, content, commit_details)
- @repository.wrapped_gitaly_errors do
+ wrapped_gitaly_errors do
gitaly_update_page(page_path, title, format, content, commit_details)
end
end
def pages(limit: 0)
- @repository.wrapped_gitaly_errors do
+ wrapped_gitaly_errors do
gitaly_get_all_pages(limit: limit)
end
end
def page(title:, version: nil, dir: nil)
- @repository.wrapped_gitaly_errors do
+ wrapped_gitaly_errors do
gitaly_find_page(title: title, version: version, dir: dir)
end
end
def file(name, version)
- @repository.wrapped_gitaly_errors do
+ wrapped_gitaly_errors do
gitaly_find_file(name, version)
end
end
@@ -67,14 +109,14 @@ module Gitlab
# :per_page - The number of items per page.
# :limit - Total number of items to return.
def page_versions(page_path, options = {})
- versions = @repository.wrapped_gitaly_errors do
+ versions = wrapped_gitaly_errors do
gitaly_wiki_client.page_versions(page_path, options)
end
# Gitaly uses gollum-lib to get the versions. Gollum defaults to 20
# per page, but also fetches 20 if `limit` or `per_page` < 20.
# Slicing returns an array with the expected number of items.
- slice_bound = options[:limit] || options[:per_page] || Gollum::Page.per_page
+ slice_bound = options[:limit] || options[:per_page] || DEFAULT_PAGINATION
versions[0..slice_bound]
end
@@ -83,51 +125,19 @@ module Gitlab
end
def preview_slug(title, format)
- # Adapted from gollum gem (Gollum::Wiki#preview_page) to avoid
- # using Rugged through a Gollum::Wiki instance
- page_class = Gollum::Page
- page = page_class.new(nil)
- ext = page_class.format_to_ext(format.to_sym)
- name = page_class.cname(title) + '.' + ext
- blob = PageBlob.new(name)
- page.populate(blob)
- page.url_path
+ GollumSlug.generate(title, format)
end
def page_formatted_data(title:, dir: nil, version: nil)
version = version&.id
- @repository.wrapped_gitaly_errors do
+ wrapped_gitaly_errors do
gitaly_wiki_client.get_formatted_data(title: title, dir: dir, version: version)
end
end
private
- def new_page(gollum_page)
- Gitlab::Git::WikiPage.new(gollum_page, new_version(gollum_page, gollum_page.version.id))
- end
-
- def new_version(gollum_page, commit_id)
- Gitlab::Git::WikiPageVersion.new(version(commit_id), gollum_page&.format)
- end
-
- def version(commit_id)
- commit_find_proc = -> { Gitlab::Git::Commit.find(@repository, commit_id) }
-
- if RequestStore.active?
- RequestStore.fetch([:wiki_version_commit, commit_id]) { commit_find_proc.call }
- else
- commit_find_proc.call
- end
- end
-
- def assert_type!(object, klass)
- unless object.is_a?(klass)
- raise ArgumentError, "expected a #{klass}, got #{object.inspect}"
- end
- end
-
def gitaly_wiki_client
@gitaly_wiki_client ||= Gitlab::GitalyClient::WikiService.new(@repository)
end
diff --git a/lib/gitlab/git/wiki_file.rb b/lib/gitlab/git/wiki_file.rb
index 84335aca4bc..c05a5adc00c 100644
--- a/lib/gitlab/git/wiki_file.rb
+++ b/lib/gitlab/git/wiki_file.rb
@@ -1,19 +1,16 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
class WikiFile
attr_reader :mime_type, :raw_data, :name, :path
- # This class is meant to be serializable so that it can be constructed
- # by Gitaly and sent over the network to GitLab.
- #
- # Because Gollum::File is not serializable we must get all the data from
- # 'gollum_file' during initialization, and NOT store it in an instance
- # variable.
- def initialize(gollum_file)
- @mime_type = gollum_file.mime_type
- @raw_data = gollum_file.raw_data
- @name = gollum_file.name
- @path = gollum_file.path
+ # This class wraps Gitlab::GitalyClient::WikiFile
+ def initialize(gitaly_file)
+ @mime_type = gitaly_file.mime_type
+ @raw_data = gitaly_file.raw_data
+ @name = gitaly_file.name
+ @path = gitaly_file.path
end
end
end
diff --git a/lib/gitlab/git/wiki_page.rb b/lib/gitlab/git/wiki_page.rb
index 669ae11a423..f6cac398548 100644
--- a/lib/gitlab/git/wiki_page.rb
+++ b/lib/gitlab/git/wiki_page.rb
@@ -1,27 +1,19 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
class WikiPage
attr_reader :url_path, :title, :format, :path, :version, :raw_data, :name, :text_data, :historical, :formatted_data
- # This class is meant to be serializable so that it can be constructed
- # by Gitaly and sent over the network to GitLab.
- #
- # Because Gollum::Page is not serializable we must get all the data from
- # 'gollum_page' during initialization, and NOT store it in an instance
- # variable.
- #
- # Note that 'version' is a WikiPageVersion instance which it itself
- # serializable. That means it's OK to store 'version' in an instance
- # variable.
- def initialize(gollum_page, version)
- @url_path = gollum_page.url_path
- @title = gollum_page.title
- @format = gollum_page.format
- @path = gollum_page.path
- @raw_data = gollum_page.raw_data
- @name = gollum_page.name
- @historical = gollum_page.historical?
- @formatted_data = gollum_page.formatted_data if gollum_page.is_a?(Gollum::Page)
+ # This class abstracts away Gitlab::GitalyClient::WikiPage
+ def initialize(gitaly_page, version)
+ @url_path = gitaly_page.url_path
+ @title = gitaly_page.title
+ @format = gitaly_page.format
+ @path = gitaly_page.path
+ @raw_data = gitaly_page.raw_data
+ @name = gitaly_page.name
+ @historical = gitaly_page.historical?
@version = version
end
diff --git a/lib/gitlab/git/wiki_page_version.rb b/lib/gitlab/git/wiki_page_version.rb
index 55f1afedcab..475a9d4d1b9 100644
--- a/lib/gitlab/git/wiki_page_version.rb
+++ b/lib/gitlab/git/wiki_page_version.rb
@@ -1,13 +1,10 @@
+# frozen_string_literal: true
+
module Gitlab
module Git
class WikiPageVersion
attr_reader :commit, :format
- # This class is meant to be serializable so that it can be constructed
- # by Gitaly and sent over the network to GitLab.
- #
- # Both 'commit' (a Gitlab::Git::Commit) and 'format' (a string) are
- # serializable.
def initialize(commit, format)
@commit = commit
@format = format
diff --git a/lib/gitlab/git/wraps_gitaly_errors.rb b/lib/gitlab/git/wraps_gitaly_errors.rb
new file mode 100644
index 00000000000..9963bcfbf1c
--- /dev/null
+++ b/lib/gitlab/git/wraps_gitaly_errors.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Git
+ module WrapsGitalyErrors
+ def wrapped_gitaly_errors(&block)
+ yield block
+ rescue GRPC::NotFound => e
+ raise Gitlab::Git::Repository::NoRepository.new(e)
+ rescue GRPC::InvalidArgument => e
+ raise ArgumentError.new(e)
+ rescue GRPC::BadStatus => e
+ raise Gitlab::Git::CommandError.new(e)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index 30cd09a0ca7..802fa65dd63 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Check a user's access to perform a git action. All public methods in this
# class return an instance of `GitlabAccessStatus`
module Gitlab
@@ -7,6 +9,7 @@ module Gitlab
UnauthorizedError = Class.new(StandardError)
NotFoundError = Class.new(StandardError)
ProjectCreationError = Class.new(StandardError)
+ TimeoutError = Class.new(StandardError)
ProjectMovedError = Class.new(NotFoundError)
ERROR_MESSAGES = {
@@ -24,11 +27,18 @@ module Gitlab
cannot_push_to_read_only: "You can't push code to a read-only GitLab instance."
}.freeze
- DOWNLOAD_COMMANDS = %w{ git-upload-pack git-upload-archive }.freeze
- PUSH_COMMANDS = %w{ git-receive-pack }.freeze
+ INTERNAL_TIMEOUT = 50.seconds.freeze
+ LOG_HEADER = <<~MESSAGE
+ Push operation timed out
+
+ Timing information for debugging purposes:
+ MESSAGE
+
+ DOWNLOAD_COMMANDS = %w{git-upload-pack git-upload-archive}.freeze
+ PUSH_COMMANDS = %w{git-receive-pack}.freeze
ALL_COMMANDS = DOWNLOAD_COMMANDS + PUSH_COMMANDS
- attr_reader :actor, :project, :protocol, :authentication_abilities, :namespace_path, :project_path, :redirected_path, :auth_result_type, :changes
+ attr_reader :actor, :project, :protocol, :authentication_abilities, :namespace_path, :project_path, :redirected_path, :auth_result_type, :changes, :logger
def initialize(actor, project, protocol, authentication_abilities:, namespace_path: nil, project_path: nil, redirected_path: nil, auth_result_type: nil)
@actor = actor
@@ -42,6 +52,7 @@ module Gitlab
end
def check(cmd, changes)
+ @logger = Checks::TimedLogger.new(timeout: INTERNAL_TIMEOUT, header: LOG_HEADER)
@changes = changes
check_protocol!
@@ -267,14 +278,19 @@ module Gitlab
end
def check_single_change_access(change, skip_lfs_integrity_check: false)
- Checks::ChangeAccess.new(
+ change_access = Checks::ChangeAccess.new(
change,
user_access: user_access,
project: project,
skip_authorization: deploy_key?,
skip_lfs_integrity_check: skip_lfs_integrity_check,
- protocol: protocol
- ).exec
+ protocol: protocol,
+ logger: logger
+ )
+
+ change_access.exec
+ rescue Checks::TimedLogger::TimeoutError
+ raise TimeoutError, logger.full_message
end
def deploy_key
diff --git a/lib/gitlab/git_access_wiki.rb b/lib/gitlab/git_access_wiki.rb
index a5b3902ebf4..3f24001e4ee 100644
--- a/lib/gitlab/git_access_wiki.rb
+++ b/lib/gitlab/git_access_wiki.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class GitAccessWiki < GitAccess
ERROR_MESSAGES = {
diff --git a/lib/gitlab/git_logger.rb b/lib/gitlab/git_logger.rb
index 9e02ccc0f44..dac4ddd320f 100644
--- a/lib/gitlab/git_logger.rb
+++ b/lib/gitlab/git_logger.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class GitLogger < Gitlab::Logger
def self.file_name_noext
diff --git a/lib/gitlab/git_post_receive.rb b/lib/gitlab/git_post_receive.rb
index e731e654f3c..cf2329e489d 100644
--- a/lib/gitlab/git_post_receive.rb
+++ b/lib/gitlab/git_post_receive.rb
@@ -11,8 +11,8 @@ module Gitlab
@changes = deserialize_changes(changes)
end
- def identify(revision)
- super(identifier, project, revision)
+ def identify
+ super(identifier)
end
def changes_refs
diff --git a/lib/gitlab/git_ref_validator.rb b/lib/gitlab/git_ref_validator.rb
index 40636fb204e..3f13ebeb9d0 100644
--- a/lib/gitlab/git_ref_validator.rb
+++ b/lib/gitlab/git_ref_validator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Gitaly note: JV: does not need to be migrated, works without a repo.
module Gitlab
@@ -11,7 +13,11 @@ module Gitlab
return false if ref_name.start_with?(*not_allowed_prefixes)
return false if ref_name == 'HEAD'
- Rugged::Reference.valid_name? "refs/heads/#{ref_name}"
+ begin
+ Rugged::Reference.valid_name?("refs/heads/#{ref_name}")
+ rescue ArgumentError
+ return false
+ end
end
end
end
diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb
index 12307338972..9be553a8b86 100644
--- a/lib/gitlab/gitaly_client.rb
+++ b/lib/gitlab/gitaly_client.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'base64'
require 'gitaly'
@@ -7,11 +9,6 @@ require 'grpc/health/v1/health_services_pb'
module Gitlab
module GitalyClient
include Gitlab::Metrics::Methods
- module MigrationStatus
- DISABLED = 1
- OPT_IN = 2
- OPT_OUT = 3
- end
class TooManyInvocationsError < StandardError
attr_reader :call_site, :invocation_count, :max_call_stack
@@ -23,13 +20,13 @@ module Gitlab
stacks = most_invoked_stack.join('\n') if most_invoked_stack
msg = "GitalyClient##{call_site} called #{invocation_count} times from single request. Potential n+1?"
- msg << "\nThe following call site called into Gitaly #{max_call_stack} times:\n#{stacks}\n" if stacks
+ msg = "#{msg}\nThe following call site called into Gitaly #{max_call_stack} times:\n#{stacks}\n" if stacks
super(msg)
end
end
- SERVER_VERSION_FILE = 'GITALY_SERVER_VERSION'.freeze
+ SERVER_VERSION_FILE = 'GITALY_SERVER_VERSION'
MAXIMUM_GITALY_CALLS = 35
CLIENT_NAME = (Sidekiq.server? ? 'gitlab-sidekiq' : 'gitlab-web').freeze
@@ -41,11 +38,6 @@ module Gitlab
self.query_time = 0
- define_histogram :gitaly_migrate_call_duration_seconds do
- docstring "Gitaly migration call execution timings"
- base_labels gitaly_enabled: nil, feature: nil
- end
-
define_histogram :gitaly_controller_action_duration_seconds do
docstring "Gitaly endpoint histogram by controller and action combination"
base_labels Gitlab::Metrics::Transaction::BASE_LABELS.merge(gitaly_service: nil, rpc: nil)
@@ -124,7 +116,6 @@ module Gitlab
def self.call(storage, service, rpc, request, remote_storage: nil, timeout: nil)
start = Gitlab::Metrics::System.monotonic_time
request_hash = request.is_a?(Google::Protobuf::MessageExts) ? request.to_h : {}
- @current_call_id ||= SecureRandom.uuid
enforce_gitaly_request_limits(:call)
@@ -137,15 +128,13 @@ module Gitlab
ensure
duration = Gitlab::Metrics::System.monotonic_time - start
- # Keep track, seperately, for the performance bar
+ # Keep track, separately, for the performance bar
self.query_time += duration
gitaly_controller_action_duration_seconds.observe(
current_transaction_labels.merge(gitaly_service: service.to_s, rpc: rpc.to_s),
duration)
- add_call_details(id: @current_call_id, feature: service, duration: duration, request: request_hash)
-
- @current_call_id = nil
+ add_call_details(feature: "#{service}##{rpc}", duration: duration, request: request_hash, rpc: rpc)
end
def self.handle_grpc_unavailable!(ex)
@@ -174,10 +163,29 @@ module Gitlab
end
private_class_method :current_transaction_labels
+ # For some time related tasks we can't rely on `Time.now` since it will be
+ # affected by Timecop in some tests, and the clock of some gitaly-related
+ # components (grpc's c-core and gitaly server) use system time instead of
+ # timecop's time, so tests will fail.
+ # `Time.at(Process.clock_gettime(Process::CLOCK_REALTIME))` will circumvent
+ # timecop.
+ def self.real_time
+ Time.at(Process.clock_gettime(Process::CLOCK_REALTIME))
+ end
+ private_class_method :real_time
+
+ def self.authorization_token(storage)
+ token = token(storage).to_s
+ issued_at = real_time.to_i.to_s
+ hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, token, issued_at)
+
+ "v2.#{hmac}.#{issued_at}"
+ end
+ private_class_method :authorization_token
+
def self.request_kwargs(storage, timeout, remote_storage: nil)
- encoded_token = Base64.strict_encode64(token(storage).to_s)
metadata = {
- 'authorization' => "Bearer #{encoded_token}",
+ 'authorization' => "Bearer #{authorization_token(storage)}",
'client_name' => CLIENT_NAME
}
@@ -195,18 +203,13 @@ module Gitlab
return result unless timeout > 0
- # Do not use `Time.now` for deadline calculation, since it
- # will be affected by Timecop in some tests, but grpc's c-core
- # uses system time instead of timecop's time, so tests will fail
- # `Time.at(Process.clock_gettime(Process::CLOCK_REALTIME))` will
- # circumvent timecop
- deadline = Time.at(Process.clock_gettime(Process::CLOCK_REALTIME)) + timeout
+ deadline = real_time + timeout
result[:deadline] = deadline
result
end
- SERVER_FEATURE_FLAGS = %w[gogit_findcommit git_v2].freeze
+ SERVER_FEATURE_FLAGS = %w[].freeze
def self.server_feature_flags
SERVER_FEATURE_FLAGS.map do |f|
@@ -221,88 +224,14 @@ module Gitlab
params['gitaly_token'].presence || Gitlab.config.gitaly['token']
end
- # Evaluates whether a feature toggle is on or off
- def self.feature_enabled?(feature_name, status: MigrationStatus::OPT_IN)
- # Disabled features are always off!
- return false if status == MigrationStatus::DISABLED
-
- feature = Feature.get("gitaly_#{feature_name}")
-
- # If the feature has been set, always evaluate
- if Feature.persisted?(feature)
- if feature.percentage_of_time_value > 0
- # Probabilistically enable this feature
- return Random.rand() * 100 < feature.percentage_of_time_value
- end
-
- return feature.enabled?
- end
-
- # If the feature has not been set, the default depends
- # on it's status
- case status
- when MigrationStatus::OPT_OUT
- true
- when MigrationStatus::OPT_IN
- opt_into_all_features? && !explicit_opt_in_required.include?(feature_name)
- else
- false
- end
- rescue => ex
- # During application startup feature lookups in SQL can fail
- Rails.logger.warn "exception while checking Gitaly feature status for #{feature_name}: #{ex}"
- false
- end
-
- # We have a mechanism to let GitLab automatically opt in to all Gitaly
- # features. We want to be able to exclude some features from automatic
- # opt-in. This function has an override in EE.
- def self.explicit_opt_in_required
- []
- end
-
- # opt_into_all_features? returns true when the current environment
- # is one in which we opt into features automatically
- def self.opt_into_all_features?
- Rails.env.development? || ENV["GITALY_FEATURE_DEFAULT_ON"] == "1"
- end
- private_class_method :opt_into_all_features?
-
- def self.migrate(feature, status: MigrationStatus::OPT_IN)
- # Enforce limits at both the `migrate` and `call` sites to ensure that
- # problems are not hidden by a feature being disabled
- enforce_gitaly_request_limits(:migrate)
-
- is_enabled = feature_enabled?(feature, status: status)
- metric_name = feature.to_s
- metric_name += "_gitaly" if is_enabled
-
- Gitlab::Metrics.measure(metric_name) do
- # Some migrate calls wrap other migrate calls
- allow_n_plus_1_calls do
- feature_stack = Thread.current[:gitaly_feature_stack] ||= []
- feature_stack.unshift(feature)
- begin
- start = Gitlab::Metrics::System.monotonic_time
- @current_call_id = SecureRandom.uuid
- call_details = { id: @current_call_id }
- yield is_enabled
- ensure
- total_time = Gitlab::Metrics::System.monotonic_time - start
- gitaly_migrate_call_duration_seconds.observe({ gitaly_enabled: is_enabled, feature: feature }, total_time)
- feature_stack.shift
- Thread.current[:gitaly_feature_stack] = nil if feature_stack.empty?
-
- add_call_details(call_details.merge(feature: feature, duration: total_time))
- end
- end
- end
+ def self.feature_enabled?(feature_name)
+ Feature.enabled?("gitaly_#{feature_name}")
end
# Ensures that Gitaly is not being abuse through n+1 misuse etc
def self.enforce_gitaly_request_limits(call_site)
# Only count limits in request-response environments (not sidekiq for example)
- return unless RequestStore.active?
+ return unless Gitlab::SafeRequestStore.active?
# This is this actual number of times this call was made. Used for information purposes only
actual_call_count = increment_call_count("gitaly_#{call_site}_actual")
@@ -326,7 +255,7 @@ module Gitlab
end
def self.allow_n_plus_1_calls
- return yield unless RequestStore.active?
+ return yield unless Gitlab::SafeRequestStore.active?
begin
increment_call_count(:gitaly_call_count_exception_block_depth)
@@ -337,63 +266,44 @@ module Gitlab
end
def self.get_call_count(key)
- RequestStore.store[key] || 0
+ Gitlab::SafeRequestStore[key] || 0
end
private_class_method :get_call_count
def self.increment_call_count(key)
- RequestStore.store[key] ||= 0
- RequestStore.store[key] += 1
+ Gitlab::SafeRequestStore[key] ||= 0
+ Gitlab::SafeRequestStore[key] += 1
end
private_class_method :increment_call_count
def self.decrement_call_count(key)
- RequestStore.store[key] -= 1
+ Gitlab::SafeRequestStore[key] -= 1
end
private_class_method :decrement_call_count
- # Returns an estimate of the number of Gitaly calls made for this
- # request
+ # Returns the of the number of Gitaly calls made for this request
def self.get_request_count
- return 0 unless RequestStore.active?
-
- gitaly_migrate_count = get_call_count("gitaly_migrate_actual")
- gitaly_call_count = get_call_count("gitaly_call_actual")
-
- # Using the maximum of migrate and call_count will provide an
- # indicator of how many Gitaly calls will be made, even
- # before a feature is enabled. This provides us with a single
- # metric, but not an exact number, but this tradeoff is acceptable
- if gitaly_migrate_count > gitaly_call_count
- gitaly_migrate_count
- else
- gitaly_call_count
- end
+ get_call_count("gitaly_call_actual")
end
def self.reset_counts
- return unless RequestStore.active?
+ return unless Gitlab::SafeRequestStore.active?
- %w[migrate call].each do |call_site|
- RequestStore.store["gitaly_#{call_site}_actual"] = 0
- RequestStore.store["gitaly_#{call_site}_permitted"] = 0
- end
+ Gitlab::SafeRequestStore["gitaly_call_actual"] = 0
+ Gitlab::SafeRequestStore["gitaly_call_permitted"] = 0
end
def self.add_call_details(details)
- id = details.delete(:id)
-
- return unless id && RequestStore.active? && RequestStore.store[:peek_enabled]
+ return unless Gitlab::SafeRequestStore[:peek_enabled]
- RequestStore.store['gitaly_call_details'] ||= {}
- RequestStore.store['gitaly_call_details'][id] ||= {}
- RequestStore.store['gitaly_call_details'][id].merge!(details)
+ Gitlab::SafeRequestStore['gitaly_call_details'] ||= []
+ Gitlab::SafeRequestStore['gitaly_call_details'] << details
end
def self.list_call_details
- return {} unless RequestStore.active? && RequestStore.store[:peek_enabled]
+ return [] unless Gitlab::SafeRequestStore[:peek_enabled]
- RequestStore.store['gitaly_call_details'] || {}
+ Gitlab::SafeRequestStore['gitaly_call_details'] || []
end
def self.expected_server_version
@@ -431,22 +341,22 @@ module Gitlab
# Count a stack. Used for n+1 detection
def self.count_stack
- return unless RequestStore.active?
+ return unless Gitlab::SafeRequestStore.active?
stack_string = Gitlab::Profiler.clean_backtrace(caller).drop(1).join("\n")
- RequestStore.store[:stack_counter] ||= Hash.new
+ Gitlab::SafeRequestStore[:stack_counter] ||= Hash.new
- count = RequestStore.store[:stack_counter][stack_string] || 0
- RequestStore.store[:stack_counter][stack_string] = count + 1
+ count = Gitlab::SafeRequestStore[:stack_counter][stack_string] || 0
+ Gitlab::SafeRequestStore[:stack_counter][stack_string] = count + 1
end
private_class_method :count_stack
# Returns a count for the stack which called Gitaly the most times. Used for n+1 detection
def self.max_call_count
- return 0 unless RequestStore.active?
+ return 0 unless Gitlab::SafeRequestStore.active?
- stack_counter = RequestStore.store[:stack_counter]
+ stack_counter = Gitlab::SafeRequestStore[:stack_counter]
return 0 unless stack_counter
stack_counter.values.max
@@ -455,9 +365,9 @@ module Gitlab
# Returns the stacks that calls Gitaly the most times. Used for n+1 detection
def self.max_stacks
- return nil unless RequestStore.active?
+ return nil unless Gitlab::SafeRequestStore.active?
- stack_counter = RequestStore.store[:stack_counter]
+ stack_counter = Gitlab::SafeRequestStore[:stack_counter]
return nil unless stack_counter
max = max_call_count
diff --git a/lib/gitlab/gitaly_client/attributes_bag.rb b/lib/gitlab/gitaly_client/attributes_bag.rb
index 198a1de91c7..3f1a0ef4888 100644
--- a/lib/gitlab/gitaly_client/attributes_bag.rb
+++ b/lib/gitlab/gitaly_client/attributes_bag.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
# This module expects an `ATTRS` const to be defined on the subclass
diff --git a/lib/gitlab/gitaly_client/blob_service.rb b/lib/gitlab/gitaly_client/blob_service.rb
index 1840bf45154..39547328210 100644
--- a/lib/gitlab/gitaly_client/blob_service.rb
+++ b/lib/gitlab/gitaly_client/blob_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class BlobService
@@ -15,7 +17,7 @@ module Gitlab
)
response = GitalyClient.call(@gitaly_repo.storage_name, :blob_service, :get_blob, request, timeout: GitalyClient.fast_timeout)
- data = ''
+ data = []
blob = nil
response.each do |msg|
if blob.nil?
@@ -27,6 +29,8 @@ module Gitlab
return nil if blob.oid.blank?
+ data = data.join
+
Gitlab::Git::Blob.new(
id: blob.oid,
size: blob.size,
@@ -72,7 +76,7 @@ module Gitlab
GitalyClient::BlobsStitcher.new(response)
end
- def get_new_lfs_pointers(revision, limit, not_in)
+ def get_new_lfs_pointers(revision, limit, not_in, dynamic_timeout = nil)
request = Gitaly::GetNewLFSPointersRequest.new(
repository: @gitaly_repo,
revision: encode_binary(revision),
@@ -85,7 +89,20 @@ module Gitlab
request.not_in_refs += not_in
end
- response = GitalyClient.call(@gitaly_repo.storage_name, :blob_service, :get_new_lfs_pointers, request, timeout: GitalyClient.medium_timeout)
+ timeout =
+ if dynamic_timeout
+ [dynamic_timeout, GitalyClient.medium_timeout].min
+ else
+ GitalyClient.medium_timeout
+ end
+
+ response = GitalyClient.call(
+ @gitaly_repo.storage_name,
+ :blob_service,
+ :get_new_lfs_pointers,
+ request,
+ timeout: timeout
+ )
map_lfs_pointers(response)
end
diff --git a/lib/gitlab/gitaly_client/blobs_stitcher.rb b/lib/gitlab/gitaly_client/blobs_stitcher.rb
index 5ca592ff812..01bab854082 100644
--- a/lib/gitlab/gitaly_client/blobs_stitcher.rb
+++ b/lib/gitlab/gitaly_client/blobs_stitcher.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class BlobsStitcher
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index 6c95abdcb4b..4e46cb9f05c 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class CommitService
@@ -93,7 +95,7 @@ module Gitlab
response = GitalyClient.call(@repository.storage, :commit_service, :tree_entry, request, timeout: GitalyClient.medium_timeout)
entry = nil
- data = ''
+ data = []
response.each do |msg|
if entry.nil?
entry = msg
@@ -103,7 +105,7 @@ module Gitlab
data << msg.data
end
- entry.data = data
+ entry.data = data.join
entry unless entry.oid.blank?
end
@@ -148,6 +150,24 @@ module Gitlab
GitalyClient.call(@repository.storage, :commit_service, :count_commits, request, timeout: GitalyClient.medium_timeout).count
end
+ def list_last_commits_for_tree(revision, path, offset: 0, limit: 25)
+ request = Gitaly::ListLastCommitsForTreeRequest.new(
+ repository: @gitaly_repo,
+ revision: encode_binary(revision),
+ path: encode_binary(path.to_s),
+ offset: offset,
+ limit: limit
+ )
+
+ response = GitalyClient.call(@repository.storage, :commit_service, :list_last_commits_for_tree, request, timeout: GitalyClient.medium_timeout)
+
+ response.each_with_object({}) do |gitaly_response, hsh|
+ gitaly_response.commits.each do |commit_for_tree|
+ hsh[commit_for_tree.path] = Gitlab::Git::Commit.new(@repository, commit_for_tree.commit)
+ end
+ end
+ end
+
def last_commit_for_path(revision, path)
request = Gitaly::LastCommitForPathRequest.new(
repository: @gitaly_repo,
@@ -236,26 +256,27 @@ module Gitlab
)
response = GitalyClient.call(@repository.storage, :commit_service, :raw_blame, request, timeout: GitalyClient.medium_timeout)
- response.reduce("") { |memo, msg| memo << msg.data }
+ response.reduce([]) { |memo, msg| memo << msg.data }.join
end
def find_commit(revision)
- if RequestStore.active?
- # We don't use RequeStstore.fetch(key) { ... } directly because `revision`
- # can be a branch name, so we can't use it as a key as it could point
- # to another commit later on (happens a lot in tests).
+ if Gitlab::SafeRequestStore.active?
+ # We don't use Gitlab::SafeRequestStore.fetch(key) { ... } directly
+ # because `revision` can be a branch name, so we can't use it as a key
+ # as it could point to another commit later on (happens a lot in
+ # tests).
key = {
storage: @gitaly_repo.storage_name,
relative_path: @gitaly_repo.relative_path,
commit_id: revision
}
- return RequestStore[key] if RequestStore.exist?(key)
+ return Gitlab::SafeRequestStore[key] if Gitlab::SafeRequestStore.exist?(key)
commit = call_find_commit(revision)
return unless commit
key[:commit_id] = commit.id
- RequestStore[key] = commit
+ Gitlab::SafeRequestStore[key] = commit
else
call_find_commit(revision)
end
@@ -326,8 +347,8 @@ module Gitlab
request = Gitaly::ExtractCommitSignatureRequest.new(repository: @gitaly_repo, commit_id: commit_id)
response = GitalyClient.call(@repository.storage, :commit_service, :extract_commit_signature, request)
- signature = ''.b
- signed_text = ''.b
+ signature = +''.b
+ signed_text = +''.b
response.each do |message|
signature << message.signature
@@ -345,7 +366,7 @@ module Gitlab
request = Gitaly::GetCommitSignaturesRequest.new(repository: @gitaly_repo, commit_ids: commit_ids)
response = GitalyClient.call(@repository.storage, :commit_service, :get_commit_signatures, request, timeout: GitalyClient.fast_timeout)
- signatures = Hash.new { |h, k| h[k] = [''.b, ''.b] }
+ signatures = Hash.new { |h, k| h[k] = [+''.b, +''.b] }
current_commit_id = nil
response.each do |message|
@@ -364,7 +385,7 @@ module Gitlab
request = Gitaly::GetCommitMessagesRequest.new(repository: @gitaly_repo, commit_ids: commit_ids)
response = GitalyClient.call(@repository.storage, :commit_service, :get_commit_messages, request, timeout: GitalyClient.fast_timeout)
- messages = Hash.new { |h, k| h[k] = ''.b }
+ messages = Hash.new { |h, k| h[k] = +''.b }
current_commit_id = nil
response.each do |rpc_message|
diff --git a/lib/gitlab/gitaly_client/conflict_files_stitcher.rb b/lib/gitlab/gitaly_client/conflict_files_stitcher.rb
index c275a065bce..0e00f6e8c44 100644
--- a/lib/gitlab/gitaly_client/conflict_files_stitcher.rb
+++ b/lib/gitlab/gitaly_client/conflict_files_stitcher.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class ConflictFilesStitcher
@@ -17,7 +19,7 @@ module Gitlab
current_file = file_from_gitaly_header(gitaly_file.header)
else
- current_file.raw_content << gitaly_file.content
+ current_file.raw_content = "#{current_file.raw_content}#{gitaly_file.content}"
end
end
end
diff --git a/lib/gitlab/gitaly_client/conflicts_service.rb b/lib/gitlab/gitaly_client/conflicts_service.rb
index aa7e03301f5..6304f998563 100644
--- a/lib/gitlab/gitaly_client/conflicts_service.rb
+++ b/lib/gitlab/gitaly_client/conflicts_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class ConflictsService
diff --git a/lib/gitlab/gitaly_client/diff.rb b/lib/gitlab/gitaly_client/diff.rb
index af9d674535b..dd192ccde1a 100644
--- a/lib/gitlab/gitaly_client/diff.rb
+++ b/lib/gitlab/gitaly_client/diff.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class Diff
diff --git a/lib/gitlab/gitaly_client/diff_stitcher.rb b/lib/gitlab/gitaly_client/diff_stitcher.rb
index da243ee2d1a..98d327a7329 100644
--- a/lib/gitlab/gitaly_client/diff_stitcher.rb
+++ b/lib/gitlab/gitaly_client/diff_stitcher.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class DiffStitcher
@@ -20,7 +22,7 @@ module Gitlab
current_diff = GitalyClient::Diff.new(diff_params)
else
- current_diff.patch += diff_msg.raw_patch_data
+ current_diff.patch = "#{current_diff.patch}#{diff_msg.raw_patch_data}"
end
if diff_msg.end_of_patch
diff --git a/lib/gitlab/gitaly_client/health_check_service.rb b/lib/gitlab/gitaly_client/health_check_service.rb
index 6c1213f5e20..0c495f60633 100644
--- a/lib/gitlab/gitaly_client/health_check_service.rb
+++ b/lib/gitlab/gitaly_client/health_check_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class HealthCheckService
diff --git a/lib/gitlab/gitaly_client/namespace_service.rb b/lib/gitlab/gitaly_client/namespace_service.rb
index d4e982b649a..f0be3cbebd2 100644
--- a/lib/gitlab/gitaly_client/namespace_service.rb
+++ b/lib/gitlab/gitaly_client/namespace_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class NamespaceService
diff --git a/lib/gitlab/gitaly_client/notification_service.rb b/lib/gitlab/gitaly_client/notification_service.rb
index 326e6f7dafc..873c3e4086d 100644
--- a/lib/gitlab/gitaly_client/notification_service.rb
+++ b/lib/gitlab/gitaly_client/notification_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class NotificationService
diff --git a/lib/gitlab/gitaly_client/operation_service.rb b/lib/gitlab/gitaly_client/operation_service.rb
index 54c78fdb680..22d2d149e65 100644
--- a/lib/gitlab/gitaly_client/operation_service.rb
+++ b/lib/gitlab/gitaly_client/operation_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class OperationService
@@ -230,6 +232,32 @@ module Gitlab
response.squash_sha
end
+ def user_update_submodule(user:, submodule:, commit_sha:, branch:, message:)
+ request = Gitaly::UserUpdateSubmoduleRequest.new(
+ repository: @gitaly_repo,
+ user: Gitlab::Git::User.from_gitlab(user).to_gitaly,
+ commit_sha: commit_sha,
+ branch: encode_binary(branch),
+ submodule: encode_binary(submodule),
+ commit_message: encode_binary(message)
+ )
+
+ response = GitalyClient.call(
+ @repository.storage,
+ :operation_service,
+ :user_update_submodule,
+ request
+ )
+
+ if response.pre_receive_error.present?
+ raise Gitlab::Git::PreReceiveError, response.pre_receive_error
+ elsif response.commit_error.present?
+ raise Gitlab::Git::CommitError, response.commit_error
+ else
+ Gitlab::Git::OperationService::BranchUpdate.from_gitaly(response.branch_update)
+ end
+ end
+
def user_commit_files(
user, branch_name, commit_message, actions, author_email, author_name,
start_branch_name, start_repository)
@@ -273,6 +301,29 @@ module Gitlab
Gitlab::Git::OperationService::BranchUpdate.from_gitaly(response.branch_update)
end
+ def user_commit_patches(user, branch_name, patches)
+ header = Gitaly::UserApplyPatchRequest::Header.new(
+ repository: @gitaly_repo,
+ user: Gitlab::Git::User.from_gitlab(user).to_gitaly,
+ target_branch: encode_binary(branch_name)
+ )
+ reader = binary_stringio(patches)
+
+ chunks = Enumerator.new do |chunk|
+ chunk.yield Gitaly::UserApplyPatchRequest.new(header: header)
+
+ until reader.eof?
+ patch_chunk = reader.read(MAX_MSG_SIZE)
+
+ chunk.yield(Gitaly::UserApplyPatchRequest.new(patches: patch_chunk))
+ end
+ end
+
+ response = GitalyClient.call(@repository.storage, :operation_service, :user_apply_patch, chunks)
+
+ Gitlab::Git::OperationService::BranchUpdate.from_gitaly(response.branch_update)
+ end
+
private
def call_cherry_pick_or_revert(rpc, user:, commit:, branch_name:, message:, start_branch_name:, start_repository:)
@@ -333,7 +384,9 @@ module Gitlab
action: action[:action].upcase.to_sym,
file_path: encode_binary(action[:file_path]),
previous_path: encode_binary(action[:previous_path]),
- base64_content: action[:encoding] == 'base64'
+ base64_content: action[:encoding] == 'base64',
+ execute_filemode: !!action[:execute_filemode],
+ infer_content: !!action[:infer_content]
)
rescue RangeError
raise ArgumentError, "Unknown action '#{action[:action]}'"
diff --git a/lib/gitlab/gitaly_client/queue_enumerator.rb b/lib/gitlab/gitaly_client/queue_enumerator.rb
index b8018029552..3a412102abe 100644
--- a/lib/gitlab/gitaly_client/queue_enumerator.rb
+++ b/lib/gitlab/gitaly_client/queue_enumerator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class QueueEnumerator
diff --git a/lib/gitlab/gitaly_client/ref_service.rb b/lib/gitlab/gitaly_client/ref_service.rb
index 8acc22e809e..d5633d167ac 100644
--- a/lib/gitlab/gitaly_client/ref_service.rb
+++ b/lib/gitlab/gitaly_client/ref_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class RefService
@@ -218,7 +220,7 @@ module Gitlab
request = Gitaly::GetTagMessagesRequest.new(repository: @gitaly_repo, tag_ids: tag_ids)
response = GitalyClient.call(@repository.storage, :ref_service, :get_tag_messages, request, timeout: GitalyClient.fast_timeout)
- messages = Hash.new { |h, k| h[k] = ''.b }
+ messages = Hash.new { |h, k| h[k] = +''.b }
current_tag_id = nil
response.each do |rpc_message|
diff --git a/lib/gitlab/gitaly_client/remote_service.rb b/lib/gitlab/gitaly_client/remote_service.rb
index 4661448621b..81fac37ee68 100644
--- a/lib/gitlab/gitaly_client/remote_service.rb
+++ b/lib/gitlab/gitaly_client/remote_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class RemoteService
@@ -66,13 +68,18 @@ module Gitlab
encode_utf8(response.ref)
end
- def update_remote_mirror(ref_name, only_branches_matching)
+ def update_remote_mirror(ref_name, only_branches_matching, ssh_key: nil, known_hosts: nil)
req_enum = Enumerator.new do |y|
- y.yield Gitaly::UpdateRemoteMirrorRequest.new(
+ first_request = Gitaly::UpdateRemoteMirrorRequest.new(
repository: @gitaly_repo,
ref_name: ref_name
)
+ first_request.ssh_key = ssh_key if ssh_key.present?
+ first_request.known_hosts = known_hosts if known_hosts.present?
+
+ y.yield(first_request)
+
current_size = 0
slices = only_branches_matching.slice_before do |branch_name|
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index 2956ed4b911..8a1abfbf874 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class RepositoryService
@@ -56,9 +58,9 @@ module Gitlab
request = Gitaly::GetInfoAttributesRequest.new(repository: @gitaly_repo)
response = GitalyClient.call(@storage, :repository_service, :get_info_attributes, request, timeout: GitalyClient.fast_timeout)
- response.each_with_object("") do |message, attributes|
+ response.each_with_object([]) do |message, attributes|
attributes << message.attributes
- end
+ end.join
end
def fetch_remote(remote, ssh_auth:, forced:, no_tags:, timeout:, prune: true)
@@ -67,7 +69,7 @@ module Gitlab
no_tags: no_tags, timeout: timeout, no_prune: !prune
)
- if ssh_auth&.ssh_import?
+ if ssh_auth&.ssh_mirror_url?
if ssh_auth.ssh_key_auth? && ssh_auth.ssh_private_key.present?
request.ssh_key = ssh_auth.ssh_private_key
end
@@ -249,20 +251,15 @@ module Gitlab
)
end
- def write_ref(ref_path, ref, old_ref, shell)
+ def write_ref(ref_path, ref, old_ref)
request = Gitaly::WriteRefRequest.new(
repository: @gitaly_repo,
ref: ref_path.b,
- revision: ref.b,
- shell: shell
+ revision: ref.b
)
request.old_revision = old_ref.b unless old_ref.nil?
- response = GitalyClient.call(@storage, :repository_service, :write_ref, request, timeout: GitalyClient.fast_timeout)
-
- raise Gitlab::Git::CommandError, encode!(response.error) if response.error.present?
-
- true
+ GitalyClient.call(@storage, :repository_service, :write_ref, request, timeout: GitalyClient.fast_timeout)
end
def set_config(entries)
@@ -349,7 +346,7 @@ module Gitlab
f.write(message.data)
end
end
- # If the file is empty means that we recieved an empty stream, we delete the file
+ # If the file is empty means that we received an empty stream, we delete the file
FileUtils.rm(save_path) if File.zero?(save_path)
end
diff --git a/lib/gitlab/gitaly_client/server_service.rb b/lib/gitlab/gitaly_client/server_service.rb
index ad898278353..0ade6942db9 100644
--- a/lib/gitlab/gitaly_client/server_service.rb
+++ b/lib/gitlab/gitaly_client/server_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
# Meant for extraction of server data, and later maybe to perform misc task
diff --git a/lib/gitlab/gitaly_client/storage_service.rb b/lib/gitlab/gitaly_client/storage_service.rb
index 3a26dd58ff4..4edcb0b8ba9 100644
--- a/lib/gitlab/gitaly_client/storage_service.rb
+++ b/lib/gitlab/gitaly_client/storage_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class StorageService
diff --git a/lib/gitlab/gitaly_client/storage_settings.rb b/lib/gitlab/gitaly_client/storage_settings.rb
index 26d1f53f26c..754cccb6b3f 100644
--- a/lib/gitlab/gitaly_client/storage_settings.rb
+++ b/lib/gitlab/gitaly_client/storage_settings.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
# This is a chokepoint that is meant to help us stop remove all places
diff --git a/lib/gitlab/gitaly_client/util.rb b/lib/gitlab/gitaly_client/util.rb
index 9c19c51d412..dce5d6a8ad0 100644
--- a/lib/gitlab/gitaly_client/util.rb
+++ b/lib/gitlab/gitaly_client/util.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
module Util
diff --git a/lib/gitlab/gitaly_client/wiki_file.rb b/lib/gitlab/gitaly_client/wiki_file.rb
index 47c60c92484..ef2b23732d1 100644
--- a/lib/gitlab/gitaly_client/wiki_file.rb
+++ b/lib/gitlab/gitaly_client/wiki_file.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class WikiFile
diff --git a/lib/gitlab/gitaly_client/wiki_page.rb b/lib/gitlab/gitaly_client/wiki_page.rb
index a02d15db5dd..757a429fb8a 100644
--- a/lib/gitlab/gitaly_client/wiki_page.rb
+++ b/lib/gitlab/gitaly_client/wiki_page.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitalyClient
class WikiPage
diff --git a/lib/gitlab/gitaly_client/wiki_service.rb b/lib/gitlab/gitaly_client/wiki_service.rb
index 75be7d1f5a0..2b3d622af4d 100644
--- a/lib/gitlab/gitaly_client/wiki_service.rb
+++ b/lib/gitlab/gitaly_client/wiki_service.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'stringio'
module Gitlab
@@ -110,7 +112,7 @@ module Gitlab
repository: @gitaly_repo,
page_path: encode_binary(page_path),
page: options[:page] || 1,
- per_page: options[:per_page] || Gollum::Page.per_page
+ per_page: options[:per_page] || Gitlab::Git::Wiki::DEFAULT_PAGINATION
)
stream = GitalyClient.call(@repository.storage, :wiki_service, :wiki_get_page_versions, request, timeout: GitalyClient.medium_timeout)
@@ -139,7 +141,7 @@ module Gitlab
next unless message.name.present? || wiki_file
if wiki_file
- wiki_file.raw_data << message.raw_data
+ wiki_file.raw_data = "#{wiki_file.raw_data}#{message.raw_data}"
else
wiki_file = GitalyClient::WikiFile.new(message.to_h)
# All gRPC strings in a response are frozen, so we get
@@ -160,7 +162,7 @@ module Gitlab
)
response = GitalyClient.call(@repository.storage, :wiki_service, :wiki_get_formatted_data, request)
- response.reduce("") { |memo, msg| memo << msg.data }
+ response.reduce([]) { |memo, msg| memo << msg.data }.join
end
private
diff --git a/lib/gitlab/github_import.rb b/lib/gitlab/github_import.rb
index d40b06f969f..14a6d6443ec 100644
--- a/lib/gitlab/github_import.rb
+++ b/lib/gitlab/github_import.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GithubImport
def self.refmap
diff --git a/lib/gitlab/github_import/importer/repository_importer.rb b/lib/gitlab/github_import/importer/repository_importer.rb
index 374dc9d3c00..bc3ea9e9226 100644
--- a/lib/gitlab/github_import/importer/repository_importer.rb
+++ b/lib/gitlab/github_import/importer/repository_importer.rb
@@ -80,7 +80,7 @@ module Gitlab
end
def fail_import(message)
- project.mark_import_as_failed(message)
+ project.import_state.mark_as_failed(message)
false
end
end
diff --git a/lib/gitlab/github_import/parallel_importer.rb b/lib/gitlab/github_import/parallel_importer.rb
index a77ac1e4fa6..9d81441d96e 100644
--- a/lib/gitlab/github_import/parallel_importer.rb
+++ b/lib/gitlab/github_import/parallel_importer.rb
@@ -41,8 +41,7 @@ module Gitlab
Gitlab::SidekiqStatus
.set(jid, StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION)
- project.ensure_import_state
- project.import_state&.update_column(:jid, jid)
+ project.import_state.update_column(:jid, jid)
Stage::ImportRepositoryWorker
.perform_async(project.id)
diff --git a/lib/gitlab/gitlab_import/client.rb b/lib/gitlab/gitlab_import/client.rb
index 38ef12491df..86474159f8b 100644
--- a/lib/gitlab/gitlab_import/client.rb
+++ b/lib/gitlab/gitlab_import/client.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitlabImport
class Client
diff --git a/lib/gitlab/gitlab_import/importer.rb b/lib/gitlab/gitlab_import/importer.rb
index 047487f1d24..e84863deba8 100644
--- a/lib/gitlab/gitlab_import/importer.rb
+++ b/lib/gitlab/gitlab_import/importer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitlabImport
class Importer
@@ -22,22 +24,22 @@ module Gitlab
issues = client.issues(project_identifier)
issues.each do |issue|
- body = @formatter.author_line(issue["author"]["name"])
- body += issue["description"]
+ body = [@formatter.author_line(issue["author"]["name"])]
+ body << issue["description"]
comments = client.issue_comments(project_identifier, issue["iid"])
if comments.any?
- body += @formatter.comments_header
+ body << @formatter.comments_header
end
comments.each do |comment|
- body += @formatter.comment(comment["author"]["name"], comment["created_at"], comment["body"])
+ body << @formatter.comment(comment["author"]["name"], comment["created_at"], comment["body"])
end
project.issues.create!(
iid: issue["iid"],
- description: body,
+ description: body.join,
title: issue["title"],
state: issue["state"],
updated_at: issue["updated_at"],
diff --git a/lib/gitlab/gitlab_import/project_creator.rb b/lib/gitlab/gitlab_import/project_creator.rb
index 430b8c10058..35feea17351 100644
--- a/lib/gitlab/gitlab_import/project_creator.rb
+++ b/lib/gitlab/gitlab_import/project_creator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GitlabImport
class ProjectCreator
diff --git a/lib/gitlab/gl_id.rb b/lib/gitlab/gl_id.rb
index a53d156b41f..1ed842c2264 100644
--- a/lib/gitlab/gl_id.rb
+++ b/lib/gitlab/gl_id.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GlId
def self.gl_id(user)
diff --git a/lib/gitlab/gl_repository.rb b/lib/gitlab/gl_repository.rb
index b54e45de4fe..435b74806e7 100644
--- a/lib/gitlab/gl_repository.rb
+++ b/lib/gitlab/gl_repository.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GlRepository
def self.gl_repository(project, is_wiki)
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index deaa14c8434..15137140639 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# rubocop:disable Metrics/AbcSize
module Gitlab
@@ -6,7 +8,10 @@ module Gitlab
def add_gon_variables
gon.api_version = 'v4'
- gon.default_avatar_url = URI.join(Gitlab.config.gitlab.url, ActionController::Base.helpers.image_path('no_avatar.png')).to_s
+ gon.default_avatar_url =
+ Gitlab::Utils.append_path(
+ Gitlab.config.gitlab.url,
+ ActionController::Base.helpers.image_path('no_avatar.png'))
gon.max_file_size = Gitlab::CurrentSettings.max_attachment_size
gon.asset_host = ActionController::Base.asset_host
gon.webpack_public_path = webpack_public_path
@@ -30,5 +35,20 @@ module Gitlab
gon.current_user_avatar_url = current_user.avatar_url
end
end
+
+ # Exposes the state of a feature flag to the frontend code.
+ #
+ # name - The name of the feature flag, e.g. `my_feature`.
+ # args - Any additional arguments to pass to `Feature.enabled?`. This allows
+ # you to check if a flag is enabled for a particular user.
+ def push_frontend_feature_flag(name, *args)
+ var_name = name.to_s.camelize(:lower)
+ enabled = Feature.enabled?(name, *args)
+
+ # Here the `true` argument signals gon that the value should be merged
+ # into any existing ones, instead of overwriting them. This allows you to
+ # use this method to push multiple feature flags.
+ gon.push({ features: { var_name => enabled } }, true)
+ end
end
end
diff --git a/lib/gitlab/google_code_import/client.rb b/lib/gitlab/google_code_import/client.rb
index b1dbf554e41..52d714880b5 100644
--- a/lib/gitlab/google_code_import/client.rb
+++ b/lib/gitlab/google_code_import/client.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GoogleCodeImport
class Client
diff --git a/lib/gitlab/google_code_import/importer.rb b/lib/gitlab/google_code_import/importer.rb
index 94c15739231..1e7203cb82a 100644
--- a/lib/gitlab/google_code_import/importer.rb
+++ b/lib/gitlab/google_code_import/importer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GoogleCodeImport
class Importer
@@ -102,7 +104,7 @@ module Gitlab
if username.start_with?("@")
username = username[1..-1]
- if user = User.find_by(username: username)
+ if user = UserFinder.new(username).find_by_username
assignee_id = user.id
end
end
diff --git a/lib/gitlab/google_code_import/project_creator.rb b/lib/gitlab/google_code_import/project_creator.rb
index 326cfcaa8af..eaef85acb98 100644
--- a/lib/gitlab/google_code_import/project_creator.rb
+++ b/lib/gitlab/google_code_import/project_creator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GoogleCodeImport
class ProjectCreator
diff --git a/lib/gitlab/google_code_import/repository.rb b/lib/gitlab/google_code_import/repository.rb
index ad33fc2cad2..19627c8cd35 100644
--- a/lib/gitlab/google_code_import/repository.rb
+++ b/lib/gitlab/google_code_import/repository.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GoogleCodeImport
class Repository
diff --git a/lib/gitlab/gpg.rb b/lib/gitlab/gpg.rb
index 8a91e034377..e53c2d00743 100644
--- a/lib/gitlab/gpg.rb
+++ b/lib/gitlab/gpg.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Gpg
extend self
diff --git a/lib/gitlab/gpg/commit.rb b/lib/gitlab/gpg/commit.rb
index 2bc081a6181..31bab20b044 100644
--- a/lib/gitlab/gpg/commit.rb
+++ b/lib/gitlab/gpg/commit.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Gpg
class Commit
diff --git a/lib/gitlab/gpg/invalid_gpg_signature_updater.rb b/lib/gitlab/gpg/invalid_gpg_signature_updater.rb
index 6972bd685f7..d892d27a917 100644
--- a/lib/gitlab/gpg/invalid_gpg_signature_updater.rb
+++ b/lib/gitlab/gpg/invalid_gpg_signature_updater.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Gpg
class InvalidGpgSignatureUpdater
diff --git a/lib/gitlab/grape_logging/formatters/lograge_with_timestamp.rb b/lib/gitlab/grape_logging/formatters/lograge_with_timestamp.rb
index 0014ce2689b..9bb1e8fc7a2 100644
--- a/lib/gitlab/grape_logging/formatters/lograge_with_timestamp.rb
+++ b/lib/gitlab/grape_logging/formatters/lograge_with_timestamp.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module GrapeLogging
module Formatters
@@ -6,7 +8,7 @@ module Gitlab
def call(severity, datetime, _, data)
time = data.delete :time
- data[:params] = utf8_encode_values(data[:params]) if data.has_key?(:params)
+ data[:params] = process_params(data)
attributes = {
time: datetime.utc.iso8601(3),
@@ -20,6 +22,14 @@ module Gitlab
private
+ def process_params(data)
+ return [] unless data.has_key?(:params)
+
+ data[:params]
+ .each_pair
+ .map { |k, v| { key: k, value: utf8_encode_values(v) } }
+ end
+
def utf8_encode_values(data)
case data
when Hash
diff --git a/lib/gitlab/grape_logging/loggers/queue_duration_logger.rb b/lib/gitlab/grape_logging/loggers/queue_duration_logger.rb
index 0adac79f25a..705e23adff2 100644
--- a/lib/gitlab/grape_logging/loggers/queue_duration_logger.rb
+++ b/lib/gitlab/grape_logging/loggers/queue_duration_logger.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This grape_logging module (https://github.com/aserafin/grape_logging) makes it
# possible to log how much time an API request was queued by Workhorse.
module Gitlab
diff --git a/lib/gitlab/grape_logging/loggers/user_logger.rb b/lib/gitlab/grape_logging/loggers/user_logger.rb
index fa172861967..6caa6c715e7 100644
--- a/lib/gitlab/grape_logging/loggers/user_logger.rb
+++ b/lib/gitlab/grape_logging/loggers/user_logger.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This grape_logging module (https://github.com/aserafin/grape_logging) makes it
# possible to log the user who performed the Grape API action by retrieving
# the user context from the request environment.
diff --git a/lib/gitlab/graphql.rb b/lib/gitlab/graphql.rb
index 04a89432230..74c04e5380e 100644
--- a/lib/gitlab/graphql.rb
+++ b/lib/gitlab/graphql.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Graphql
StandardGraphqlError = Class.new(StandardError)
diff --git a/lib/gitlab/graphql/authorize.rb b/lib/gitlab/graphql/authorize.rb
index 93a903915b0..5e48bf9043d 100644
--- a/lib/gitlab/graphql/authorize.rb
+++ b/lib/gitlab/graphql/authorize.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Graphql
# Allow fields to declare permissions their objects must have. The field
diff --git a/lib/gitlab/graphql/authorize/authorize_resource.rb b/lib/gitlab/graphql/authorize/authorize_resource.rb
index 40895686a8a..a56c4f6368d 100644
--- a/lib/gitlab/graphql/authorize/authorize_resource.rb
+++ b/lib/gitlab/graphql/authorize/authorize_resource.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Graphql
module Authorize
diff --git a/lib/gitlab/graphql/authorize/instrumentation.rb b/lib/gitlab/graphql/authorize/instrumentation.rb
index 6cb8e617f62..d638d2b43ee 100644
--- a/lib/gitlab/graphql/authorize/instrumentation.rb
+++ b/lib/gitlab/graphql/authorize/instrumentation.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Graphql
module Authorize
diff --git a/lib/gitlab/graphql/connections.rb b/lib/gitlab/graphql/connections.rb
index 2582ffeb2a8..fbccdfa7b08 100644
--- a/lib/gitlab/graphql/connections.rb
+++ b/lib/gitlab/graphql/connections.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Graphql
module Connections
diff --git a/lib/gitlab/graphql/connections/keyset_connection.rb b/lib/gitlab/graphql/connections/keyset_connection.rb
index 3c0d7e9784a..851054c0393 100644
--- a/lib/gitlab/graphql/connections/keyset_connection.rb
+++ b/lib/gitlab/graphql/connections/keyset_connection.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Graphql
module Connections
diff --git a/lib/gitlab/graphql/errors.rb b/lib/gitlab/graphql/errors.rb
index f8c7ec24be1..fe74549e322 100644
--- a/lib/gitlab/graphql/errors.rb
+++ b/lib/gitlab/graphql/errors.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Graphql
module Errors
diff --git a/lib/gitlab/graphql/expose_permissions.rb b/lib/gitlab/graphql/expose_permissions.rb
index e3779995406..365b7cca24f 100644
--- a/lib/gitlab/graphql/expose_permissions.rb
+++ b/lib/gitlab/graphql/expose_permissions.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Graphql
module ExposePermissions
diff --git a/lib/gitlab/graphql/loaders/batch_model_loader.rb b/lib/gitlab/graphql/loaders/batch_model_loader.rb
new file mode 100644
index 00000000000..5a0099dc6b1
--- /dev/null
+++ b/lib/gitlab/graphql/loaders/batch_model_loader.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Graphql
+ module Loaders
+ class BatchModelLoader
+ attr_reader :model_class, :model_id
+
+ def initialize(model_class, model_id)
+ @model_class, @model_id = model_class, model_id
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def find
+ BatchLoader.for({ model: model_class, id: model_id }).batch do |loader_info, loader|
+ per_model = loader_info.group_by { |info| info[:model] }
+ per_model.each do |model, info|
+ ids = info.map { |i| i[:id] }
+ results = model.where(id: ids)
+
+ results.each { |record| loader.call({ model: model, id: record.id }, record) }
+ end
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/graphql/present.rb b/lib/gitlab/graphql/present.rb
index 2c7b64f1be9..7f69bf601d6 100644
--- a/lib/gitlab/graphql/present.rb
+++ b/lib/gitlab/graphql/present.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Graphql
module Present
diff --git a/lib/gitlab/graphql/present/instrumentation.rb b/lib/gitlab/graphql/present/instrumentation.rb
index f87fd147b15..ab03c40c22d 100644
--- a/lib/gitlab/graphql/present/instrumentation.rb
+++ b/lib/gitlab/graphql/present/instrumentation.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Graphql
module Present
diff --git a/lib/gitlab/graphql/variables.rb b/lib/gitlab/graphql/variables.rb
index ffbaf65b512..b13ea37c21f 100644
--- a/lib/gitlab/graphql/variables.rb
+++ b/lib/gitlab/graphql/variables.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Graphql
class Variables
diff --git a/lib/gitlab/graphs/commits.rb b/lib/gitlab/graphs/commits.rb
index c4ffc19df09..66e1b2e78b4 100644
--- a/lib/gitlab/graphs/commits.rb
+++ b/lib/gitlab/graphs/commits.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Graphs
class Commits
diff --git a/lib/gitlab/group_hierarchy.rb b/lib/gitlab/group_hierarchy.rb
index 8fbfa1a86bf..c940ea7305e 100644
--- a/lib/gitlab/group_hierarchy.rb
+++ b/lib/gitlab/group_hierarchy.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
# Retrieving of parent or child groups based on a base ActiveRecord relation.
#
diff --git a/lib/gitlab/hashed_storage/migrator.rb b/lib/gitlab/hashed_storage/migrator.rb
index 4edc251facb..1f29cf10cad 100644
--- a/lib/gitlab/hashed_storage/migrator.rb
+++ b/lib/gitlab/hashed_storage/migrator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HashedStorage
# Hashed Storage Migrator
diff --git a/lib/gitlab/hashed_storage/rake_helper.rb b/lib/gitlab/hashed_storage/rake_helper.rb
index 22edd5f999d..38f552fab03 100644
--- a/lib/gitlab/hashed_storage/rake_helper.rb
+++ b/lib/gitlab/hashed_storage/rake_helper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HashedStorage
module RakeHelper
diff --git a/lib/gitlab/health_checks/base_abstract_check.rb b/lib/gitlab/health_checks/base_abstract_check.rb
index 8b365dab185..1d31f59999c 100644
--- a/lib/gitlab/health_checks/base_abstract_check.rb
+++ b/lib/gitlab/health_checks/base_abstract_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HealthChecks
module BaseAbstractCheck
diff --git a/lib/gitlab/health_checks/db_check.rb b/lib/gitlab/health_checks/db_check.rb
index 08495c0a59e..2bcd25cd3cc 100644
--- a/lib/gitlab/health_checks/db_check.rb
+++ b/lib/gitlab/health_checks/db_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HealthChecks
class DbCheck
diff --git a/lib/gitlab/health_checks/gitaly_check.rb b/lib/gitlab/health_checks/gitaly_check.rb
index 1f623e0b6ec..898733fea5d 100644
--- a/lib/gitlab/health_checks/gitaly_check.rb
+++ b/lib/gitlab/health_checks/gitaly_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HealthChecks
class GitalyCheck
diff --git a/lib/gitlab/health_checks/metric.rb b/lib/gitlab/health_checks/metric.rb
index d62d9136886..62a5216d159 100644
--- a/lib/gitlab/health_checks/metric.rb
+++ b/lib/gitlab/health_checks/metric.rb
@@ -1,3 +1,6 @@
-module Gitlab::HealthChecks # rubocop:disable Naming/FileName
+# rubocop:disable Naming/FileName
+# frozen_string_literal: true
+
+module Gitlab::HealthChecks
Metric = Struct.new(:name, :value, :labels)
end
diff --git a/lib/gitlab/health_checks/prometheus_text_format.rb b/lib/gitlab/health_checks/prometheus_text_format.rb
index b3c759b4730..2a8f9d31cd5 100644
--- a/lib/gitlab/health_checks/prometheus_text_format.rb
+++ b/lib/gitlab/health_checks/prometheus_text_format.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HealthChecks
class PrometheusTextFormat
diff --git a/lib/gitlab/health_checks/redis/cache_check.rb b/lib/gitlab/health_checks/redis/cache_check.rb
index 2f6c4db12bb..0c8fe83893b 100644
--- a/lib/gitlab/health_checks/redis/cache_check.rb
+++ b/lib/gitlab/health_checks/redis/cache_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HealthChecks
module Redis
diff --git a/lib/gitlab/health_checks/redis/queues_check.rb b/lib/gitlab/health_checks/redis/queues_check.rb
index 63d2882c5b2..b1e33b9f459 100644
--- a/lib/gitlab/health_checks/redis/queues_check.rb
+++ b/lib/gitlab/health_checks/redis/queues_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HealthChecks
module Redis
diff --git a/lib/gitlab/health_checks/redis/redis_check.rb b/lib/gitlab/health_checks/redis/redis_check.rb
index 8ceb0a0aa46..f7e46fce134 100644
--- a/lib/gitlab/health_checks/redis/redis_check.rb
+++ b/lib/gitlab/health_checks/redis/redis_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HealthChecks
module Redis
diff --git a/lib/gitlab/health_checks/redis/shared_state_check.rb b/lib/gitlab/health_checks/redis/shared_state_check.rb
index f1ea1ffe1be..285ac271929 100644
--- a/lib/gitlab/health_checks/redis/shared_state_check.rb
+++ b/lib/gitlab/health_checks/redis/shared_state_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HealthChecks
module Redis
diff --git a/lib/gitlab/health_checks/result.rb b/lib/gitlab/health_checks/result.rb
index e323e2c9723..d32a6980eb8 100644
--- a/lib/gitlab/health_checks/result.rb
+++ b/lib/gitlab/health_checks/result.rb
@@ -1,3 +1,6 @@
-module Gitlab::HealthChecks # rubocop:disable Naming/FileName
+# rubocop:disable Naming/FileName
+# frozen_string_literal: true
+
+module Gitlab::HealthChecks
Result = Struct.new(:success, :message, :labels)
end
diff --git a/lib/gitlab/health_checks/simple_abstract_check.rb b/lib/gitlab/health_checks/simple_abstract_check.rb
index 96945ce5b20..3588260d6eb 100644
--- a/lib/gitlab/health_checks/simple_abstract_check.rb
+++ b/lib/gitlab/health_checks/simple_abstract_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HealthChecks
module SimpleAbstractCheck
diff --git a/lib/gitlab/highlight.rb b/lib/gitlab/highlight.rb
index 5408a1a6838..a4e60bbd828 100644
--- a/lib/gitlab/highlight.rb
+++ b/lib/gitlab/highlight.rb
@@ -1,20 +1,28 @@
+# frozen_string_literal: true
+
module Gitlab
class Highlight
- def self.highlight(blob_name, blob_content, repository: nil, plain: false)
- new(blob_name, blob_content, repository: repository)
+ TIMEOUT_BACKGROUND = 30.seconds
+ TIMEOUT_FOREGROUND = 3.seconds
+ MAXIMUM_TEXT_HIGHLIGHT_SIZE = 1.megabyte
+
+ def self.highlight(blob_name, blob_content, language: nil, plain: false)
+ new(blob_name, blob_content, language: language)
.highlight(blob_content, continue: false, plain: plain)
end
attr_reader :blob_name
- def initialize(blob_name, blob_content, repository: nil)
+ def initialize(blob_name, blob_content, language: nil)
@formatter = Rouge::Formatters::HTMLGitlab
- @repository = repository
+ @language = language
@blob_name = blob_name
@blob_content = blob_content
end
def highlight(text, continue: true, plain: false)
+ plain ||= text.length > MAXIMUM_TEXT_HIGHLIGHT_SIZE
+
highlighted_text = highlight_text(text, continue: continue, plain: plain)
highlighted_text = link_dependencies(text, highlighted_text) if blob_name
highlighted_text
@@ -31,11 +39,9 @@ module Gitlab
private
def custom_language
- language_name = @repository && @repository.gitattribute(@blob_name, 'gitlab-language')
-
- return nil unless language_name
+ return nil unless @language
- Rouge::Lexer.find_fancy(language_name)
+ Rouge::Lexer.find_fancy(@language)
end
def highlight_text(text, continue: true, plain: false)
@@ -51,11 +57,20 @@ module Gitlab
end
def highlight_rich(text, continue: true)
- @formatter.format(lexer.lex(text, continue: continue), tag: lexer.tag).html_safe
+ tag = lexer.tag
+ tokens = lexer.lex(text, continue: continue)
+ Timeout.timeout(timeout_time) { @formatter.format(tokens, tag: tag).html_safe }
+ rescue Timeout::Error => e
+ Gitlab::Sentry.track_exception(e)
+ highlight_plain(text)
rescue
highlight_plain(text)
end
+ def timeout_time
+ Sidekiq.server? ? TIMEOUT_BACKGROUND : TIMEOUT_FOREGROUND
+ end
+
def link_dependencies(text, highlighted_text)
Gitlab::DependencyLinker.link(blob_name, text, highlighted_text)
end
diff --git a/lib/gitlab/hook_data/base_builder.rb b/lib/gitlab/hook_data/base_builder.rb
index 4ffca356b29..d54175bce81 100644
--- a/lib/gitlab/hook_data/base_builder.rb
+++ b/lib/gitlab/hook_data/base_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HookData
class BaseBuilder
@@ -25,6 +27,7 @@ module Gitlab
markdown_text.gsub(MARKDOWN_SIMPLE_IMAGE) do
if $~[:image]
url = $~[:url]
+ url = "#{uploads_prefix}#{url}" if url.start_with?('/uploads')
url = "/#{url}" unless url.start_with?('/')
"![#{$~[:title]}](#{Gitlab.config.gitlab.url}#{url})"
@@ -33,6 +36,16 @@ module Gitlab
end
end
end
+
+ def uploads_prefix
+ project&.full_path || ''
+ end
+
+ def project
+ return unless object.respond_to?(:project)
+
+ object.project
+ end
end
end
end
diff --git a/lib/gitlab/hook_data/issuable_builder.rb b/lib/gitlab/hook_data/issuable_builder.rb
index 65389835ad7..0803df65632 100644
--- a/lib/gitlab/hook_data/issuable_builder.rb
+++ b/lib/gitlab/hook_data/issuable_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HookData
class IssuableBuilder < BaseBuilder
diff --git a/lib/gitlab/hook_data/issue_builder.rb b/lib/gitlab/hook_data/issue_builder.rb
index dd63db969f6..c99353b9d49 100644
--- a/lib/gitlab/hook_data/issue_builder.rb
+++ b/lib/gitlab/hook_data/issue_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HookData
class IssueBuilder < BaseBuilder
diff --git a/lib/gitlab/hook_data/merge_request_builder.rb b/lib/gitlab/hook_data/merge_request_builder.rb
index 3aa6a4f3767..ad38e26e40a 100644
--- a/lib/gitlab/hook_data/merge_request_builder.rb
+++ b/lib/gitlab/hook_data/merge_request_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HookData
class MergeRequestBuilder < BaseBuilder
diff --git a/lib/gitlab/hook_data/note_builder.rb b/lib/gitlab/hook_data/note_builder.rb
index 81873e345d5..ae30ef6364b 100644
--- a/lib/gitlab/hook_data/note_builder.rb
+++ b/lib/gitlab/hook_data/note_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HookData
class NoteBuilder < BaseBuilder
diff --git a/lib/gitlab/hook_data/wiki_page_builder.rb b/lib/gitlab/hook_data/wiki_page_builder.rb
index 59c94a61cf2..67f06b1ca46 100644
--- a/lib/gitlab/hook_data/wiki_page_builder.rb
+++ b/lib/gitlab/hook_data/wiki_page_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module HookData
class WikiPageBuilder < BaseBuilder
diff --git a/lib/gitlab/http.rb b/lib/gitlab/http.rb
index 9aca3b0fb26..bcd9e2be35f 100644
--- a/lib/gitlab/http.rb
+++ b/lib/gitlab/http.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This class is used as a proxy for all outbounding http connection
# coming from callbacks, services and hooks. The direct use of the HTTParty
# is discouraged because it can lead to several security problems, like SSRF
@@ -5,9 +7,16 @@
module Gitlab
class HTTP
BlockedUrlError = Class.new(StandardError)
+ RedirectionTooDeep = Class.new(StandardError)
include HTTParty # rubocop:disable Gitlab/HTTParty
connection_adapter ProxyHTTPConnectionAdapter
+
+ def self.perform_request(http_method, path, options, &block)
+ super
+ rescue HTTParty::RedirectionTooDeep
+ raise RedirectionTooDeep
+ end
end
end
diff --git a/lib/gitlab/http_io.rb b/lib/gitlab/http_io.rb
index ce24817db54..6a9fb85b054 100644
--- a/lib/gitlab/http_io.rb
+++ b/lib/gitlab/http_io.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
##
# This class is compatible with IO class (https://ruby-doc.org/core-2.3.1/IO.html)
# source: https://gitlab.com/snippets/1685610
@@ -73,8 +75,8 @@ module Gitlab
end
end
- def read(length = nil, outbuf = "")
- out = ""
+ def read(length = nil, outbuf = nil)
+ out = []
length ||= size - tell
@@ -83,24 +85,25 @@ module Gitlab
break if data.empty?
chunk_bytes = [BUFFER_SIZE - chunk_offset, length].min
- chunk_data = data.byteslice(0, chunk_bytes)
+ data_slice = data.byteslice(0, chunk_bytes)
- out << chunk_data
- @tell += chunk_data.bytesize
- length -= chunk_data.bytesize
+ out << data_slice
+ @tell += data_slice.bytesize
+ length -= data_slice.bytesize
end
+ out = out.join
+
# If outbuf is passed, we put the output into the buffer. This supports IO.copy_stream functionality
if outbuf
- outbuf.slice!(0, outbuf.bytesize)
- outbuf << out
+ outbuf.replace(out)
end
out
end
def readline
- out = ""
+ out = []
until eof?
data = get_chunk
@@ -116,7 +119,7 @@ module Gitlab
end
end
- out
+ out.join
end
def write(data)
@@ -158,14 +161,14 @@ module Gitlab
##
# Note: If provider does not return content_range, then we set it as we requested
# Provider: minio
- # - When the file size is larger than requested Content-range, the Content-range is included in responces with Net::HTTPPartialContent 206
- # - When the file size is smaller than requested Content-range, the Content-range is included in responces with Net::HTTPPartialContent 206
+ # - When the file size is larger than requested Content-range, the Content-range is included in responses with Net::HTTPPartialContent 206
+ # - When the file size is smaller than requested Content-range, the Content-range is included in responses with Net::HTTPPartialContent 206
# Provider: AWS
- # - When the file size is larger than requested Content-range, the Content-range is included in responces with Net::HTTPPartialContent 206
- # - When the file size is smaller than requested Content-range, the Content-range is included in responces with Net::HTTPPartialContent 206
+ # - When the file size is larger than requested Content-range, the Content-range is included in responses with Net::HTTPPartialContent 206
+ # - When the file size is smaller than requested Content-range, the Content-range is included in responses with Net::HTTPPartialContent 206
# Provider: GCS
- # - When the file size is larger than requested Content-range, the Content-range is included in responces with Net::HTTPPartialContent 206
- # - When the file size is smaller than requested Content-range, the Content-range is included in responces with Net::HTTPOK 200
+ # - When the file size is larger than requested Content-range, the Content-range is included in responses with Net::HTTPPartialContent 206
+ # - When the file size is smaller than requested Content-range, the Content-range is included in responses with Net::HTTPOK 200
@chunk_range ||= (chunk_start...(chunk_start + @chunk.bytesize))
end
diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb
index 7346eab9e76..7e0398f09af 100644
--- a/lib/gitlab/i18n.rb
+++ b/lib/gitlab/i18n.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module I18n
extend self
diff --git a/lib/gitlab/i18n/metadata_entry.rb b/lib/gitlab/i18n/metadata_entry.rb
index 36fc1bcdcb7..3764e379681 100644
--- a/lib/gitlab/i18n/metadata_entry.rb
+++ b/lib/gitlab/i18n/metadata_entry.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module I18n
class MetadataEntry
diff --git a/lib/gitlab/i18n/po_linter.rb b/lib/gitlab/i18n/po_linter.rb
index d8e7269a2c2..3e9a035010f 100644
--- a/lib/gitlab/i18n/po_linter.rb
+++ b/lib/gitlab/i18n/po_linter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module I18n
class PoLinter
@@ -249,7 +251,7 @@ module Gitlab
def validate_variable_usage(errors, translation, required_variables)
# We don't need to validate when the message is empty.
- # In this case we fall back to the default, which has all the the
+ # In this case we fall back to the default, which has all the
# required variables.
return if translation.empty?
diff --git a/lib/gitlab/i18n/translation_entry.rb b/lib/gitlab/i18n/translation_entry.rb
index 54adb98f42d..19c10b2e402 100644
--- a/lib/gitlab/i18n/translation_entry.rb
+++ b/lib/gitlab/i18n/translation_entry.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module I18n
class TranslationEntry
diff --git a/lib/gitlab/identifier.rb b/lib/gitlab/identifier.rb
index a8b93f1d4b2..d5f94ad04f1 100644
--- a/lib/gitlab/identifier.rb
+++ b/lib/gitlab/identifier.rb
@@ -1,11 +1,11 @@
+# frozen_string_literal: true
+
# Detect user based on identifier like
-# key-13 or user-36 or last commit
+# key-13 or user-36
module Gitlab
module Identifier
- def identify(identifier, project = nil, newrev = nil)
- if identifier.blank?
- identify_using_commit(project, newrev)
- elsif identifier =~ /\Auser-\d+\Z/
+ def identify(identifier)
+ if identifier =~ /\Auser-\d+\Z/
# git push over http
identify_using_user(identifier)
elsif identifier =~ /\Akey-\d+\Z/
@@ -14,19 +14,6 @@ module Gitlab
end
end
- # Tries to identify a user based on a commit SHA.
- def identify_using_commit(project, ref)
- return if project.nil? && ref.nil?
-
- commit = project.commit(ref)
-
- return if !commit || !commit.author_email
-
- identify_with_cache(:email, commit.author_email) do
- commit.author
- end
- end
-
# Tries to identify a user based on a user identifier (e.g. "user-123").
# rubocop: disable CodeReuse/ActiveRecord
def identify_using_user(identifier)
diff --git a/lib/gitlab/import/logger.rb b/lib/gitlab/import/logger.rb
index 8414954d141..ab3e822a4e9 100644
--- a/lib/gitlab/import/logger.rb
+++ b/lib/gitlab/import/logger.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Import
class Logger < ::Gitlab::JsonLogger
diff --git a/lib/gitlab/import/merge_request_creator.rb b/lib/gitlab/import/merge_request_creator.rb
index a01951b0762..8291372bba9 100644
--- a/lib/gitlab/import/merge_request_creator.rb
+++ b/lib/gitlab/import/merge_request_creator.rb
@@ -6,10 +6,10 @@
# used for rendering Markdown) are completely unnecessary and may even lead to
# transaction timeouts.
#
-# To ensure importing merge requests requests has a minimal impact and can
-# complete in a reasonable time we bypass all the hooks by inserting the row
-# and then retrieving it. We then only perform the additional work that is
-# strictly necessary.
+# To ensure importing merge requests has a minimal impact and can complete in
+# a reasonable time we bypass all the hooks by inserting the row and then
+# retrieving it. We then only perform the additional work that is strictly
+# necessary.
module Gitlab
module Import
class MergeRequestCreator
diff --git a/lib/gitlab/import/merge_request_helpers.rb b/lib/gitlab/import/merge_request_helpers.rb
index 97dc1a987c4..9215067d973 100644
--- a/lib/gitlab/import/merge_request_helpers.rb
+++ b/lib/gitlab/import/merge_request_helpers.rb
@@ -22,7 +22,7 @@ module Gitlab
# additional work that is strictly necessary.
merge_request_id = insert_and_return_id(attributes, project.merge_requests)
- merge_request = project.merge_requests.find(merge_request_id)
+ merge_request = project.merge_requests.reload.find(merge_request_id)
# We use .insert_and_return_id which effectively disables all callbacks.
# Trigger iid logic here to make sure we track internal id values consistently.
diff --git a/lib/gitlab/import_export.rb b/lib/gitlab/import_export.rb
index 53fe2f8e436..f63a5ece71e 100644
--- a/lib/gitlab/import_export.rb
+++ b/lib/gitlab/import_export.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
extend self
diff --git a/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb b/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb
index 7cbf653dd97..d39b6fe5955 100644
--- a/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb
+++ b/lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
module AfterExportStrategies
diff --git a/lib/gitlab/import_export/after_export_strategies/download_notification_strategy.rb b/lib/gitlab/import_export/after_export_strategies/download_notification_strategy.rb
index 4371a7eff56..1b391314a74 100644
--- a/lib/gitlab/import_export/after_export_strategies/download_notification_strategy.rb
+++ b/lib/gitlab/import_export/after_export_strategies/download_notification_strategy.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
module AfterExportStrategies
diff --git a/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb b/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb
index 4f29bdcea2c..b30900f7c61 100644
--- a/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb
+++ b/lib/gitlab/import_export/after_export_strategies/web_upload_strategy.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
module AfterExportStrategies
diff --git a/lib/gitlab/import_export/after_export_strategy_builder.rb b/lib/gitlab/import_export/after_export_strategy_builder.rb
index 7eabcae2380..37394f46a99 100644
--- a/lib/gitlab/import_export/after_export_strategy_builder.rb
+++ b/lib/gitlab/import_export/after_export_strategy_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class AfterExportStrategyBuilder
diff --git a/lib/gitlab/import_export/attribute_cleaner.rb b/lib/gitlab/import_export/attribute_cleaner.rb
index 7c9fc5c15bb..93b37b7bc5f 100644
--- a/lib/gitlab/import_export/attribute_cleaner.rb
+++ b/lib/gitlab/import_export/attribute_cleaner.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class AttributeCleaner
diff --git a/lib/gitlab/import_export/attributes_finder.rb b/lib/gitlab/import_export/attributes_finder.rb
index 0c8fda07294..409243e68a5 100644
--- a/lib/gitlab/import_export/attributes_finder.rb
+++ b/lib/gitlab/import_export/attributes_finder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class AttributesFinder
diff --git a/lib/gitlab/import_export/avatar_restorer.rb b/lib/gitlab/import_export/avatar_restorer.rb
index 17796430811..be1b97bd7a7 100644
--- a/lib/gitlab/import_export/avatar_restorer.rb
+++ b/lib/gitlab/import_export/avatar_restorer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class AvatarRestorer
diff --git a/lib/gitlab/import_export/avatar_saver.rb b/lib/gitlab/import_export/avatar_saver.rb
index 6ffebf83dd2..47ca898c690 100644
--- a/lib/gitlab/import_export/avatar_saver.rb
+++ b/lib/gitlab/import_export/avatar_saver.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class AvatarSaver
diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb
index 3adc44f8044..c9e2a6a78d9 100644
--- a/lib/gitlab/import_export/command_line_util.rb
+++ b/lib/gitlab/import_export/command_line_util.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
module CommandLineUtil
diff --git a/lib/gitlab/import_export/error.rb b/lib/gitlab/import_export/error.rb
index 788eedf2686..454dc778b6b 100644
--- a/lib/gitlab/import_export/error.rb
+++ b/lib/gitlab/import_export/error.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
Error = Class.new(StandardError)
diff --git a/lib/gitlab/import_export/file_importer.rb b/lib/gitlab/import_export/file_importer.rb
index 7fd66b4e244..05432f433e7 100644
--- a/lib/gitlab/import_export/file_importer.rb
+++ b/lib/gitlab/import_export/file_importer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class FileImporter
diff --git a/lib/gitlab/import_export/group_project_object_builder.rb b/lib/gitlab/import_export/group_project_object_builder.rb
index 6c2af770119..1c62591ed5a 100644
--- a/lib/gitlab/import_export/group_project_object_builder.rb
+++ b/lib/gitlab/import_export/group_project_object_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
# Given a class, it finds or creates a new object
diff --git a/lib/gitlab/import_export/hash_util.rb b/lib/gitlab/import_export/hash_util.rb
index d4adeeb3797..b6ce89a973b 100644
--- a/lib/gitlab/import_export/hash_util.rb
+++ b/lib/gitlab/import_export/hash_util.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class HashUtil
diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml
index a19b3c88627..8380e86c128 100644
--- a/lib/gitlab/import_export/import_export.yml
+++ b/lib/gitlab/import_export/import_export.yml
@@ -92,18 +92,17 @@ excluded_attributes:
- :path
- :namespace_id
- :creator_id
+ - :pool_repository_id
- :import_url
- :import_status
- :avatar
- :import_type
- :import_source
- - :import_error
- :mirror
- :runners_token
- :repository_storage
- :repository_read_only
- :lfs_enabled
- - :import_jid
- :created_at
- :updated_at
- :id
@@ -115,6 +114,9 @@ excluded_attributes:
- :remote_mirror_available_overridden
- :description_html
- :repository_languages
+ project_import_state:
+ - :last_error
+ - :jid
prometheus_metrics:
- :common
- :identifier
@@ -147,6 +149,14 @@ excluded_attributes:
- :reference
- :reference_html
- :epic_id
+ hooks:
+ - :token
+ - :encrypted_token
+ - :encrypted_token_iv
+ - :encrypted_url
+ - :encrypted_url_iv
+ services:
+ - :template
methods:
labels:
diff --git a/lib/gitlab/import_export/importer.rb b/lib/gitlab/import_export/importer.rb
index 72d5b9b830c..767f1b5de0e 100644
--- a/lib/gitlab/import_export/importer.rb
+++ b/lib/gitlab/import_export/importer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class Importer
diff --git a/lib/gitlab/import_export/json_hash_builder.rb b/lib/gitlab/import_export/json_hash_builder.rb
index b48f63bcd7e..477499e1688 100644
--- a/lib/gitlab/import_export/json_hash_builder.rb
+++ b/lib/gitlab/import_export/json_hash_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
# Generates a hash that conforms with http://apidock.com/rails/Hash/to_json
diff --git a/lib/gitlab/import_export/lfs_restorer.rb b/lib/gitlab/import_export/lfs_restorer.rb
index b28c3c161b7..345c7880e30 100644
--- a/lib/gitlab/import_export/lfs_restorer.rb
+++ b/lib/gitlab/import_export/lfs_restorer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class LfsRestorer
diff --git a/lib/gitlab/import_export/lfs_saver.rb b/lib/gitlab/import_export/lfs_saver.rb
index 29410e2331c..954f6f00078 100644
--- a/lib/gitlab/import_export/lfs_saver.rb
+++ b/lib/gitlab/import_export/lfs_saver.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class LfsSaver
diff --git a/lib/gitlab/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb
index bcbaf00e11b..6be95a16513 100644
--- a/lib/gitlab/import_export/members_mapper.rb
+++ b/lib/gitlab/import_export/members_mapper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class MembersMapper
diff --git a/lib/gitlab/import_export/merge_request_parser.rb b/lib/gitlab/import_export/merge_request_parser.rb
index 62a1833b39c..040a70d6775 100644
--- a/lib/gitlab/import_export/merge_request_parser.rb
+++ b/lib/gitlab/import_export/merge_request_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class MergeRequestParser
diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb
index 00ea4b833e2..8cd4efd91cc 100644
--- a/lib/gitlab/import_export/project_tree_restorer.rb
+++ b/lib/gitlab/import_export/project_tree_restorer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class ProjectTreeRestorer
@@ -136,16 +138,25 @@ module Gitlab
return if tree_hash[relation_key].blank?
tree_array = [tree_hash[relation_key]].flatten
+ null_iid_pipelines = []
# Avoid keeping a possible heavy object in memory once we are done with it
- while relation_item = tree_array.shift
+ while relation_item = (tree_array.shift || null_iid_pipelines.shift)
+ if nil_iid_pipeline?(relation_key, relation_item) && tree_array.any?
+ # Move pipelines with NULL IIDs to the end
+ # so they don't clash with existing IIDs.
+ null_iid_pipelines << relation_item
+
+ next
+ end
+
# The transaction at this level is less speedy than one single transaction
# But we can't have it in the upper level or GC won't get rid of the AR objects
# after we save the batch.
Project.transaction do
process_sub_relation(relation, relation_item)
- # For every subrelation that hangs from Project, save the associated records alltogether
+ # For every subrelation that hangs from Project, save the associated records altogether
# This effectively batches all records per subrelation item, only keeping those in memory
# We have to keep in mind that more batch granularity << Memory, but >> Slowness
if save
@@ -201,6 +212,10 @@ module Gitlab
def excluded_keys_for_relation(relation)
reader.attributes_finder.find_excluded_keys(relation)
end
+
+ def nil_iid_pipeline?(relation_key, relation_item)
+ relation_key == 'pipelines' && relation_item['iid'].nil?
+ end
end
end
end
diff --git a/lib/gitlab/import_export/project_tree_saver.rb b/lib/gitlab/import_export/project_tree_saver.rb
index 5510c0b8b2f..29f2dc80813 100644
--- a/lib/gitlab/import_export/project_tree_saver.rb
+++ b/lib/gitlab/import_export/project_tree_saver.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class ProjectTreeSaver
diff --git a/lib/gitlab/import_export/reader.rb b/lib/gitlab/import_export/reader.rb
index e621c40fc7a..bc0d18e03fa 100644
--- a/lib/gitlab/import_export/reader.rb
+++ b/lib/gitlab/import_export/reader.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class Reader
diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb
index 81807ed659c..097c7653754 100644
--- a/lib/gitlab/import_export/relation_factory.rb
+++ b/lib/gitlab/import_export/relation_factory.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class RelationFactory
@@ -86,7 +88,6 @@ module Gitlab
case @relation_name
when :merge_request_diff_files then setup_diff
when :notes then setup_note
- when 'Ci::Pipeline' then setup_pipeline
end
update_user_references
@@ -94,6 +95,8 @@ module Gitlab
update_group_references
remove_duplicate_assignees
+ setup_pipeline if @relation_name == 'Ci::Pipeline'
+
reset_tokens!
remove_encrypted_attributes!
end
@@ -210,7 +213,7 @@ module Gitlab
def update_note_for_missing_author(author_name)
@relation_hash['note'] = '*Blank note*' if @relation_hash['note'].blank?
- @relation_hash['note'] += missing_author_note(@relation_hash['updated_at'], author_name)
+ @relation_hash['note'] = "#{@relation_hash['note']}#{missing_author_note(@relation_hash['updated_at'], author_name)}"
end
def admin_user?
diff --git a/lib/gitlab/import_export/repo_restorer.rb b/lib/gitlab/import_export/repo_restorer.rb
index 5a9bbceac67..921a06b4023 100644
--- a/lib/gitlab/import_export/repo_restorer.rb
+++ b/lib/gitlab/import_export/repo_restorer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class RepoRestorer
diff --git a/lib/gitlab/import_export/repo_saver.rb b/lib/gitlab/import_export/repo_saver.rb
index 0c224bd1971..a60618dfcec 100644
--- a/lib/gitlab/import_export/repo_saver.rb
+++ b/lib/gitlab/import_export/repo_saver.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class RepoSaver
diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb
index 59a74083395..72f575db095 100644
--- a/lib/gitlab/import_export/saver.rb
+++ b/lib/gitlab/import_export/saver.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class Saver
diff --git a/lib/gitlab/import_export/shared.rb b/lib/gitlab/import_export/shared.rb
index 6d7c36ce38b..c13e6c1d83b 100644
--- a/lib/gitlab/import_export/shared.rb
+++ b/lib/gitlab/import_export/shared.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class Shared
diff --git a/lib/gitlab/import_export/statistics_restorer.rb b/lib/gitlab/import_export/statistics_restorer.rb
index bcdd9c12c85..3fafb01c37c 100644
--- a/lib/gitlab/import_export/statistics_restorer.rb
+++ b/lib/gitlab/import_export/statistics_restorer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class StatisticsRestorer
diff --git a/lib/gitlab/import_export/uploads_manager.rb b/lib/gitlab/import_export/uploads_manager.rb
index 8511319cb1c..474e9d45566 100644
--- a/lib/gitlab/import_export/uploads_manager.rb
+++ b/lib/gitlab/import_export/uploads_manager.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class UploadsManager
diff --git a/lib/gitlab/import_export/uploads_restorer.rb b/lib/gitlab/import_export/uploads_restorer.rb
index b4313ff4cb4..5f422dcbefa 100644
--- a/lib/gitlab/import_export/uploads_restorer.rb
+++ b/lib/gitlab/import_export/uploads_restorer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class UploadsRestorer < UploadsSaver
diff --git a/lib/gitlab/import_export/uploads_saver.rb b/lib/gitlab/import_export/uploads_saver.rb
index 0275f686c5e..be1066c30b2 100644
--- a/lib/gitlab/import_export/uploads_saver.rb
+++ b/lib/gitlab/import_export/uploads_saver.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class UploadsSaver
diff --git a/lib/gitlab/import_export/version_checker.rb b/lib/gitlab/import_export/version_checker.rb
index bd3c3ee3b2f..6d978d00ea5 100644
--- a/lib/gitlab/import_export/version_checker.rb
+++ b/lib/gitlab/import_export/version_checker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class VersionChecker
diff --git a/lib/gitlab/import_export/version_saver.rb b/lib/gitlab/import_export/version_saver.rb
index 7cf88298642..8230c0f1e77 100644
--- a/lib/gitlab/import_export/version_saver.rb
+++ b/lib/gitlab/import_export/version_saver.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class VersionSaver
diff --git a/lib/gitlab/import_export/wiki_repo_saver.rb b/lib/gitlab/import_export/wiki_repo_saver.rb
index 2fd62c0fc7b..7303bcf61a4 100644
--- a/lib/gitlab/import_export/wiki_repo_saver.rb
+++ b/lib/gitlab/import_export/wiki_repo_saver.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class WikiRepoSaver < RepoSaver
diff --git a/lib/gitlab/import_export/wiki_restorer.rb b/lib/gitlab/import_export/wiki_restorer.rb
index f33bfb332ab..28b5e7449cd 100644
--- a/lib/gitlab/import_export/wiki_restorer.rb
+++ b/lib/gitlab/import_export/wiki_restorer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ImportExport
class WikiRestorer < RepoRestorer
diff --git a/lib/gitlab/import_formatter.rb b/lib/gitlab/import_formatter.rb
index 4e611e7f16c..d4ba4d1181d 100644
--- a/lib/gitlab/import_formatter.rb
+++ b/lib/gitlab/import_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class ImportFormatter
def comment(author, date, body)
diff --git a/lib/gitlab/import_sources.rb b/lib/gitlab/import_sources.rb
index f7f5c5787f6..f46bb837cf7 100644
--- a/lib/gitlab/import_sources.rb
+++ b/lib/gitlab/import_sources.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Gitlab::ImportSources module
#
# Define import sources that can be used
diff --git a/lib/gitlab/incoming_email.rb b/lib/gitlab/incoming_email.rb
index d323cb9dadf..20fc8226611 100644
--- a/lib/gitlab/incoming_email.rb
+++ b/lib/gitlab/incoming_email.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module IncomingEmail
UNSUBSCRIBE_SUFFIX = '+unsubscribe'.freeze
diff --git a/lib/gitlab/insecure_key_fingerprint.rb b/lib/gitlab/insecure_key_fingerprint.rb
index f85b6e9197f..e4f0e9d2c73 100644
--- a/lib/gitlab/insecure_key_fingerprint.rb
+++ b/lib/gitlab/insecure_key_fingerprint.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
#
# Calculates the fingerprint of a given key without using
diff --git a/lib/gitlab/issuable_metadata.rb b/lib/gitlab/issuable_metadata.rb
index 0c9de72329c..351d15605e0 100644
--- a/lib/gitlab/issuable_metadata.rb
+++ b/lib/gitlab/issuable_metadata.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module IssuableMetadata
def issuable_meta_data(issuable_collection, collection_type)
diff --git a/lib/gitlab/issuable_sorter.rb b/lib/gitlab/issuable_sorter.rb
index d392214867a..42bbfb32d0b 100644
--- a/lib/gitlab/issuable_sorter.rb
+++ b/lib/gitlab/issuable_sorter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module IssuableSorter
class << self
diff --git a/lib/gitlab/issuables_count_for_state.rb b/lib/gitlab/issuables_count_for_state.rb
index 505810964bc..659fb1472d2 100644
--- a/lib/gitlab/issuables_count_for_state.rb
+++ b/lib/gitlab/issuables_count_for_state.rb
@@ -1,7 +1,9 @@
+# frozen_string_literal: true
+
module Gitlab
# Class for counting and caching the number of issuables per state.
class IssuablesCountForState
- # The name of the RequestStore cache key.
+ # The name of the Gitlab::SafeRequestStore cache key.
CACHE_KEY = :issuables_count_for_state
# The state values that can be safely casted to a Symbol.
@@ -10,12 +12,7 @@ module Gitlab
# finder - The finder class to use for retrieving the issuables.
def initialize(finder)
@finder = finder
- @cache =
- if RequestStore.active?
- RequestStore[CACHE_KEY] ||= initialize_cache
- else
- initialize_cache
- end
+ @cache = Gitlab::SafeRequestStore[CACHE_KEY] ||= initialize_cache
end
def for_state_or_opened(state = nil)
diff --git a/lib/gitlab/issues_labels.rb b/lib/gitlab/issues_labels.rb
index b8ca7f2f55f..17c9cb969df 100644
--- a/lib/gitlab/issues_labels.rb
+++ b/lib/gitlab/issues_labels.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class IssuesLabels
class << self
diff --git a/lib/gitlab/job_waiter.rb b/lib/gitlab/job_waiter.rb
index f7a8eae0be4..e97e961771c 100644
--- a/lib/gitlab/job_waiter.rb
+++ b/lib/gitlab/job_waiter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
# JobWaiter can be used to wait for a number of Sidekiq jobs to complete.
#
diff --git a/lib/gitlab/json_logger.rb b/lib/gitlab/json_logger.rb
index 28e258196ca..3bff77731f6 100644
--- a/lib/gitlab/json_logger.rb
+++ b/lib/gitlab/json_logger.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class JsonLogger < ::Gitlab::Logger
def self.file_name_noext
diff --git a/lib/gitlab/kubernetes.rb b/lib/gitlab/kubernetes.rb
index 15c5ece2350..3748fd6b5ef 100644
--- a/lib/gitlab/kubernetes.rb
+++ b/lib/gitlab/kubernetes.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
# Helper methods to do with Kubernetes network services & resources
module Kubernetes
diff --git a/lib/gitlab/kubernetes/config_map.rb b/lib/gitlab/kubernetes/config_map.rb
index 9e55dae137c..0bcaaa03974 100644
--- a/lib/gitlab/kubernetes/config_map.rb
+++ b/lib/gitlab/kubernetes/config_map.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
class ConfigMap
diff --git a/lib/gitlab/kubernetes/helm.rb b/lib/gitlab/kubernetes/helm.rb
index 4a1bdf34c3e..03d38ec78fd 100644
--- a/lib/gitlab/kubernetes/helm.rb
+++ b/lib/gitlab/kubernetes/helm.rb
@@ -1,7 +1,10 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
module Helm
- HELM_VERSION = '2.7.2'.freeze
+ HELM_VERSION = '2.11.0'.freeze
+ KUBECTL_VERSION = '1.11.0'.freeze
NAMESPACE = 'gitlab-managed-apps'.freeze
SERVICE_ACCOUNT = 'tiller'.freeze
CLUSTER_ROLE_BINDING = 'tiller-admin'.freeze
diff --git a/lib/gitlab/kubernetes/helm/api.rb b/lib/gitlab/kubernetes/helm/api.rb
index 2dd74c68075..b9903e37f40 100644
--- a/lib/gitlab/kubernetes/helm/api.rb
+++ b/lib/gitlab/kubernetes/helm/api.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
module Helm
@@ -14,6 +16,16 @@ module Gitlab
create_cluster_role_binding(command)
create_config_map(command)
+ delete_pod!(command.pod_name)
+ kubeclient.create_pod(command.pod_resource)
+ end
+
+ def update(command)
+ namespace.ensure_exists!
+
+ update_config_map(command)
+
+ delete_pod!(command.pod_name)
kubeclient.create_pod(command.pod_resource)
end
@@ -34,6 +46,14 @@ module Gitlab
def delete_pod!(pod_name)
kubeclient.delete_pod(pod_name, namespace.name)
+ rescue ::Kubeclient::ResourceNotFoundError
+ # no-op
+ end
+
+ def get_config_map(config_map_name)
+ namespace.ensure_exists!
+
+ kubeclient.get_config_map(config_map_name, namespace.name)
end
private
@@ -42,7 +62,17 @@ module Gitlab
def create_config_map(command)
command.config_map_resource.tap do |config_map_resource|
- kubeclient.create_config_map(config_map_resource)
+ if config_map_exists?(config_map_resource)
+ kubeclient.update_config_map(config_map_resource)
+ else
+ kubeclient.create_config_map(config_map_resource)
+ end
+ end
+ end
+
+ def update_config_map(command)
+ command.config_map_resource.tap do |config_map_resource|
+ kubeclient.update_config_map(config_map_resource)
end
end
@@ -70,23 +100,21 @@ module Gitlab
end
end
- def service_account_exists?(resource)
- resource_exists? do
- kubeclient.get_service_account(resource.metadata.name, resource.metadata.namespace)
- end
+ def config_map_exists?(resource)
+ kubeclient.get_config_map(resource.metadata.name, resource.metadata.namespace)
+ rescue ::Kubeclient::ResourceNotFoundError
+ false
end
- def cluster_role_binding_exists?(resource)
- resource_exists? do
- kubeclient.get_cluster_role_binding(resource.metadata.name)
- end
+ def service_account_exists?(resource)
+ kubeclient.get_service_account(resource.metadata.name, resource.metadata.namespace)
+ rescue ::Kubeclient::ResourceNotFoundError
+ false
end
- def resource_exists?
- yield
- rescue ::Kubeclient::HttpError => e
- raise e unless e.error_code == 404
-
+ def cluster_role_binding_exists?(resource)
+ kubeclient.get_cluster_role_binding(resource.metadata.name)
+ rescue ::Kubeclient::ResourceNotFoundError
false
end
end
diff --git a/lib/gitlab/kubernetes/helm/base_command.rb b/lib/gitlab/kubernetes/helm/base_command.rb
index 6752f2cff43..2bcb428b25d 100644
--- a/lib/gitlab/kubernetes/helm/base_command.rb
+++ b/lib/gitlab/kubernetes/helm/base_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
module Helm
@@ -10,13 +12,7 @@ module Gitlab
def generate_script
<<~HEREDOC
- set -eo pipefail
- ALPINE_VERSION=$(cat /etc/alpine-release | cut -d '.' -f 1,2)
- echo http://mirror.clarkson.edu/alpine/v$ALPINE_VERSION/main >> /etc/apk/repositories
- echo http://mirror1.hs-esslingen.de/pub/Mirrors/alpine/v$ALPINE_VERSION/main >> /etc/apk/repositories
- apk add -U wget ca-certificates openssl >/dev/null
- wget -q -O - https://kubernetes-helm.storage.googleapis.com/helm-v#{Gitlab::Kubernetes::Helm::HELM_VERSION}-linux-amd64.tar.gz | tar zxC /tmp >/dev/null
- mv /tmp/linux-amd64/helm /usr/bin/
+ set -xeo pipefail
HEREDOC
end
diff --git a/lib/gitlab/kubernetes/helm/client_command.rb b/lib/gitlab/kubernetes/helm/client_command.rb
new file mode 100644
index 00000000000..9940272a8bf
--- /dev/null
+++ b/lib/gitlab/kubernetes/helm/client_command.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ module Helm
+ module ClientCommand
+ def init_command
+ # Here we are always upgrading to the latest version of Tiller when
+ # installing an app. We ensure the helm version stored in the
+ # database is correct by also updating this after transition to
+ # :installed,:updated in Clusters::Concerns::ApplicationStatus
+ 'helm init --upgrade'
+ end
+
+ def wait_for_tiller_command
+ # This is necessary to give Tiller time to restart after upgrade.
+ # Ideally we'd be able to use --wait but cannot because of
+ # https://github.com/helm/helm/issues/4855
+ 'for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done'
+ end
+
+ def repository_command
+ ['helm', 'repo', 'add', name, repository].shelljoin if repository
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/helm/init_command.rb b/lib/gitlab/kubernetes/helm/init_command.rb
index c7046a9ea75..88ed8572ffc 100644
--- a/lib/gitlab/kubernetes/helm/init_command.rb
+++ b/lib/gitlab/kubernetes/helm/init_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
module Helm
@@ -45,7 +47,7 @@ module Gitlab
def init_helm_command
command = %w[helm init] + init_command_flags
- command.shelljoin + " >/dev/null\n"
+ command.shelljoin
end
def init_command_flags
diff --git a/lib/gitlab/kubernetes/helm/install_command.rb b/lib/gitlab/kubernetes/helm/install_command.rb
index 1be7924d6ac..a1ab5e048ac 100644
--- a/lib/gitlab/kubernetes/helm/install_command.rb
+++ b/lib/gitlab/kubernetes/helm/install_command.rb
@@ -1,25 +1,34 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
module Helm
class InstallCommand
include BaseCommand
+ include ClientCommand
- attr_reader :name, :files, :chart, :version, :repository
+ attr_reader :name, :files, :chart, :version, :repository, :preinstall, :postinstall
- def initialize(name:, chart:, files:, rbac:, version: nil, repository: nil)
+ def initialize(name:, chart:, files:, rbac:, version: nil, repository: nil, preinstall: nil, postinstall: nil)
@name = name
@chart = chart
@version = version
@rbac = rbac
@files = files
@repository = repository
+ @preinstall = preinstall
+ @postinstall = postinstall
end
def generate_script
super + [
init_command,
+ wait_for_tiller_command,
repository_command,
- script_command
+ repository_update_command,
+ preinstall_command,
+ install_command,
+ postinstall_command
].compact.join("\n")
end
@@ -29,18 +38,22 @@ module Gitlab
private
- def init_command
- 'helm init --client-only >/dev/null'
+ def repository_update_command
+ 'helm repo update' if repository
end
- def repository_command
- ['helm', 'repo', 'add', name, repository].shelljoin if repository
+ def install_command
+ command = ['helm', 'install', chart] + install_command_flags
+
+ command.shelljoin
end
- def script_command
- command = ['helm', 'install', chart] + install_command_flags
+ def preinstall_command
+ preinstall.join("\n") if preinstall
+ end
- command.shelljoin + " >/dev/null\n"
+ def postinstall_command
+ postinstall.join("\n") if postinstall
end
def install_command_flags
@@ -51,17 +64,17 @@ module Gitlab
name_flag +
optional_tls_flags +
optional_version_flag +
- optional_rbac_create_flag +
+ rbac_create_flag +
namespace_flag +
value_flag
end
- def optional_rbac_create_flag
- return [] unless rbac?
-
- # jupyterhub helm chart is using rbac.enabled
- # https://github.com/jupyterhub/zero-to-jupyterhub-k8s/tree/master/jupyterhub
- %w[--set rbac.create=true,rbac.enabled=true]
+ def rbac_create_flag
+ if rbac?
+ %w[--set rbac.create=true,rbac.enabled=true]
+ else
+ %w[--set rbac.create=false,rbac.enabled=false]
+ end
end
def optional_version_flag
diff --git a/lib/gitlab/kubernetes/helm/pod.rb b/lib/gitlab/kubernetes/helm/pod.rb
index 95192b11c0d..75484f80070 100644
--- a/lib/gitlab/kubernetes/helm/pod.rb
+++ b/lib/gitlab/kubernetes/helm/pod.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
module Helm
@@ -25,7 +27,7 @@ module Gitlab
def container_specification
{
name: 'helm',
- image: 'alpine:3.6',
+ image: "registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/#{Gitlab::Kubernetes::Helm::HELM_VERSION}-kube-#{Gitlab::Kubernetes::Helm::KUBECTL_VERSION}",
env: generate_pod_env(command),
command: %w(/bin/sh),
args: %w(-c $(COMMAND_SCRIPT))
diff --git a/lib/gitlab/kubernetes/helm/upgrade_command.rb b/lib/gitlab/kubernetes/helm/upgrade_command.rb
new file mode 100644
index 00000000000..9daffc138b5
--- /dev/null
+++ b/lib/gitlab/kubernetes/helm/upgrade_command.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ module Helm
+ class UpgradeCommand
+ include BaseCommand
+ include ClientCommand
+
+ attr_reader :name, :chart, :version, :repository, :files
+
+ def initialize(name, chart:, files:, rbac:, version: nil, repository: nil)
+ @name = name
+ @chart = chart
+ @rbac = rbac
+ @version = version
+ @files = files
+ @repository = repository
+ end
+
+ def generate_script
+ super + [
+ init_command,
+ wait_for_tiller_command,
+ repository_command,
+ script_command
+ ].compact.join("\n")
+ end
+
+ def rbac?
+ @rbac
+ end
+
+ def pod_name
+ "upgrade-#{name}"
+ end
+
+ private
+
+ def script_command
+ upgrade_flags = "#{optional_version_flag}#{optional_tls_flags}" \
+ " --reset-values" \
+ " --install" \
+ " --namespace #{::Gitlab::Kubernetes::Helm::NAMESPACE}" \
+ " -f /data/helm/#{name}/config/values.yaml"
+
+ "helm upgrade #{name} #{chart}#{upgrade_flags}"
+ end
+
+ def optional_version_flag
+ " --version #{version}" if version
+ end
+
+ def optional_tls_flags
+ return unless files.key?(:'ca.pem')
+
+ " --tls" \
+ " --tls-ca-cert #{files_dir}/ca.pem" \
+ " --tls-cert #{files_dir}/cert.pem" \
+ " --tls-key #{files_dir}/key.pem"
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/kube_client.rb b/lib/gitlab/kubernetes/kube_client.rb
index 588238de608..b947f6b551e 100644
--- a/lib/gitlab/kubernetes/kube_client.rb
+++ b/lib/gitlab/kubernetes/kube_client.rb
@@ -13,11 +13,22 @@ module Gitlab
class KubeClient
include Gitlab::Utils::StrongMemoize
- SUPPORTED_API_GROUPS = [
- 'api',
- 'apis/rbac.authorization.k8s.io',
- 'apis/extensions'
- ].freeze
+ SUPPORTED_API_GROUPS = {
+ core: { group: 'api', version: 'v1' },
+ rbac: { group: 'apis/rbac.authorization.k8s.io', version: 'v1' },
+ extensions: { group: 'apis/extensions', version: 'v1beta1' },
+ knative: { group: 'apis/serving.knative.dev', version: 'v1alpha1' }
+ }.freeze
+
+ SUPPORTED_API_GROUPS.each do |name, params|
+ client_method_name = "#{name}_client".to_sym
+
+ define_method(client_method_name) do
+ strong_memoize(client_method_name) do
+ build_kubeclient(params[:group], params[:version])
+ end
+ end
+ end
# Core API methods delegates to the core api group client
delegate :get_pods,
@@ -45,6 +56,13 @@ module Gitlab
:update_cluster_role_binding,
to: :rbac_client
+ # RBAC methods delegates to the apis/rbac.authorization.k8s.io api
+ # group client
+ delegate :create_role_binding,
+ :get_role_binding,
+ :update_role_binding,
+ to: :rbac_client
+
# Deployments resource is currently on the apis/extensions api group
delegate :get_deployments,
to: :extensions_client
@@ -55,48 +73,21 @@ module Gitlab
:watch_pod_log,
to: :core_client
- def initialize(api_prefix, api_groups = ['api'], api_version = 'v1', **kubeclient_options)
- raise ArgumentError unless check_api_groups_supported?(api_groups)
+ attr_reader :api_prefix, :kubeclient_options
+ def initialize(api_prefix, **kubeclient_options)
@api_prefix = api_prefix
- @api_groups = api_groups
- @api_version = api_version
@kubeclient_options = kubeclient_options
end
- def discover!
- clients.each(&:discover)
- end
-
- def clients
- hashed_clients.values
- end
-
- def core_client
- hashed_clients['api']
- end
-
- def rbac_client
- hashed_clients['apis/rbac.authorization.k8s.io']
- end
-
- def extensions_client
- hashed_clients['apis/extensions']
- end
-
- def hashed_clients
- strong_memoize(:hashed_clients) do
- @api_groups.map do |api_group|
- api_url = join_api_url(@api_prefix, api_group)
- [api_group, ::Kubeclient::Client.new(api_url, @api_version, **@kubeclient_options)]
- end.to_h
- end
- end
-
private
- def check_api_groups_supported?(api_groups)
- api_groups.all? {|api_group| SUPPORTED_API_GROUPS.include?(api_group) }
+ def build_kubeclient(api_group, api_version)
+ ::Kubeclient::Client.new(
+ join_api_url(api_prefix, api_group),
+ api_version,
+ **kubeclient_options
+ )
end
def join_api_url(api_prefix, api_path)
diff --git a/lib/gitlab/kubernetes/logger.rb b/lib/gitlab/kubernetes/logger.rb
new file mode 100644
index 00000000000..5e59482419b
--- /dev/null
+++ b/lib/gitlab/kubernetes/logger.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ class Logger < ::Gitlab::JsonLogger
+ def self.file_name_noext
+ 'kubernetes'
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/kubernetes/namespace.rb b/lib/gitlab/kubernetes/namespace.rb
index e6ff6160ab9..919f19c86d7 100644
--- a/lib/gitlab/kubernetes/namespace.rb
+++ b/lib/gitlab/kubernetes/namespace.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
class Namespace
@@ -10,9 +12,7 @@ module Gitlab
def exists?
@client.get_namespace(name)
- rescue ::Kubeclient::HttpError => ke
- raise ke unless ke.error_code == 404
-
+ rescue ::Kubeclient::ResourceNotFoundError
false
end
diff --git a/lib/gitlab/kubernetes/pod.rb b/lib/gitlab/kubernetes/pod.rb
index f3842cdf762..81317e532b2 100644
--- a/lib/gitlab/kubernetes/pod.rb
+++ b/lib/gitlab/kubernetes/pod.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Kubernetes
module Pod
diff --git a/lib/gitlab/kubernetes/role_binding.rb b/lib/gitlab/kubernetes/role_binding.rb
new file mode 100644
index 00000000000..cb0cb42d007
--- /dev/null
+++ b/lib/gitlab/kubernetes/role_binding.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Kubernetes
+ class RoleBinding
+ def initialize(name:, role_name:, namespace:, service_account_name:)
+ @name = name
+ @role_name = role_name
+ @namespace = namespace
+ @service_account_name = service_account_name
+ end
+
+ def generate
+ ::Kubeclient::Resource.new.tap do |resource|
+ resource.metadata = metadata
+ resource.roleRef = role_ref
+ resource.subjects = subjects
+ end
+ end
+
+ private
+
+ attr_reader :name, :role_name, :namespace, :service_account_name
+
+ def metadata
+ { name: name, namespace: namespace }
+ end
+
+ def role_ref
+ {
+ apiGroup: 'rbac.authorization.k8s.io',
+ kind: 'ClusterRole',
+ name: role_name
+ }
+ end
+
+ def subjects
+ [
+ {
+ kind: 'ServiceAccount',
+ name: service_account_name,
+ namespace: namespace
+ }
+ ]
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/language_data.rb b/lib/gitlab/language_data.rb
new file mode 100644
index 00000000000..bfdd7175198
--- /dev/null
+++ b/lib/gitlab/language_data.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module LanguageData
+ EXTENSION_MUTEX = Mutex.new
+
+ class << self
+ include Gitlab::Utils::StrongMemoize
+
+ def extensions
+ EXTENSION_MUTEX.synchronize do
+ strong_memoize(:extensions) do
+ Set.new.tap do |set|
+ YAML.load_file(Rails.root.join('vendor', 'languages.yml')).each do |_name, details|
+ details['extensions']&.each do |ext|
+ next unless ext.start_with?('.')
+
+ set << ext.downcase
+ end
+ end
+ end
+ end
+ end
+ end
+
+ def clear_extensions!
+ EXTENSION_MUTEX.synchronize do
+ clear_memoization(:extensions)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/language_detection.rb b/lib/gitlab/language_detection.rb
index a41435fdb79..7600e60b904 100644
--- a/lib/gitlab/language_detection.rb
+++ b/lib/gitlab/language_detection.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class LanguageDetection
MAX_LANGUAGES = 5
diff --git a/lib/gitlab/lazy.rb b/lib/gitlab/lazy.rb
index 99594577141..d7a22aa339e 100644
--- a/lib/gitlab/lazy.rb
+++ b/lib/gitlab/lazy.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
# A class that can be wrapped around an expensive method call so it's only
# executed when actually needed.
diff --git a/lib/gitlab/legacy_github_import/base_formatter.rb b/lib/gitlab/legacy_github_import/base_formatter.rb
index 11d1300e51e..0b19cf742ed 100644
--- a/lib/gitlab/legacy_github_import/base_formatter.rb
+++ b/lib/gitlab/legacy_github_import/base_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class BaseFormatter
diff --git a/lib/gitlab/legacy_github_import/branch_formatter.rb b/lib/gitlab/legacy_github_import/branch_formatter.rb
index 80fe1d67209..1177751457f 100644
--- a/lib/gitlab/legacy_github_import/branch_formatter.rb
+++ b/lib/gitlab/legacy_github_import/branch_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class BranchFormatter < BaseFormatter
diff --git a/lib/gitlab/legacy_github_import/client.rb b/lib/gitlab/legacy_github_import/client.rb
index d8ed0ebca9d..bc952147667 100644
--- a/lib/gitlab/legacy_github_import/client.rb
+++ b/lib/gitlab/legacy_github_import/client.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class Client
diff --git a/lib/gitlab/legacy_github_import/comment_formatter.rb b/lib/gitlab/legacy_github_import/comment_formatter.rb
index d2c7a8ae9f4..d83cc4f6b3c 100644
--- a/lib/gitlab/legacy_github_import/comment_formatter.rb
+++ b/lib/gitlab/legacy_github_import/comment_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class CommentFormatter < BaseFormatter
diff --git a/lib/gitlab/legacy_github_import/importer.rb b/lib/gitlab/legacy_github_import/importer.rb
index c5bde681365..c526d31a591 100644
--- a/lib/gitlab/legacy_github_import/importer.rb
+++ b/lib/gitlab/legacy_github_import/importer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class Importer
@@ -78,8 +80,7 @@ module Gitlab
def handle_errors
return unless errors.any?
- project.ensure_import_state
- project.import_state&.update_column(:last_error, {
+ project.import_state.update_column(:last_error, {
message: 'The remote data could not be fully imported.',
errors: errors
}.to_json)
diff --git a/lib/gitlab/legacy_github_import/issuable_formatter.rb b/lib/gitlab/legacy_github_import/issuable_formatter.rb
index 7db4a54267e..1a0aefbbd62 100644
--- a/lib/gitlab/legacy_github_import/issuable_formatter.rb
+++ b/lib/gitlab/legacy_github_import/issuable_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class IssuableFormatter < BaseFormatter
diff --git a/lib/gitlab/legacy_github_import/issue_formatter.rb b/lib/gitlab/legacy_github_import/issue_formatter.rb
index 4c8825ccf19..2f46e2e30d1 100644
--- a/lib/gitlab/legacy_github_import/issue_formatter.rb
+++ b/lib/gitlab/legacy_github_import/issue_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class IssueFormatter < IssuableFormatter
diff --git a/lib/gitlab/legacy_github_import/label_formatter.rb b/lib/gitlab/legacy_github_import/label_formatter.rb
index e9663650903..89200e794d8 100644
--- a/lib/gitlab/legacy_github_import/label_formatter.rb
+++ b/lib/gitlab/legacy_github_import/label_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class LabelFormatter < BaseFormatter
diff --git a/lib/gitlab/legacy_github_import/milestone_formatter.rb b/lib/gitlab/legacy_github_import/milestone_formatter.rb
index a565294384d..2fe1b4258d3 100644
--- a/lib/gitlab/legacy_github_import/milestone_formatter.rb
+++ b/lib/gitlab/legacy_github_import/milestone_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class MilestoneFormatter < BaseFormatter
diff --git a/lib/gitlab/legacy_github_import/project_creator.rb b/lib/gitlab/legacy_github_import/project_creator.rb
index 5e96eb16754..ca1a1b8e9bd 100644
--- a/lib/gitlab/legacy_github_import/project_creator.rb
+++ b/lib/gitlab/legacy_github_import/project_creator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class ProjectCreator
diff --git a/lib/gitlab/legacy_github_import/pull_request_formatter.rb b/lib/gitlab/legacy_github_import/pull_request_formatter.rb
index 94c2e99066a..5b847f13d4a 100644
--- a/lib/gitlab/legacy_github_import/pull_request_formatter.rb
+++ b/lib/gitlab/legacy_github_import/pull_request_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class PullRequestFormatter < IssuableFormatter
diff --git a/lib/gitlab/legacy_github_import/release_formatter.rb b/lib/gitlab/legacy_github_import/release_formatter.rb
index 3ed9d4f76da..8c0c17780ca 100644
--- a/lib/gitlab/legacy_github_import/release_formatter.rb
+++ b/lib/gitlab/legacy_github_import/release_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class ReleaseFormatter < BaseFormatter
diff --git a/lib/gitlab/legacy_github_import/user_formatter.rb b/lib/gitlab/legacy_github_import/user_formatter.rb
index 3794380e2d0..ec0e221b1ff 100644
--- a/lib/gitlab/legacy_github_import/user_formatter.rb
+++ b/lib/gitlab/legacy_github_import/user_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class UserFormatter
diff --git a/lib/gitlab/legacy_github_import/wiki_formatter.rb b/lib/gitlab/legacy_github_import/wiki_formatter.rb
index 27f45875c7c..ea52be5ee0f 100644
--- a/lib/gitlab/legacy_github_import/wiki_formatter.rb
+++ b/lib/gitlab/legacy_github_import/wiki_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module LegacyGithubImport
class WikiFormatter
diff --git a/lib/gitlab/lfs_token.rb b/lib/gitlab/lfs_token.rb
index ead5d566871..fa44bd842b2 100644
--- a/lib/gitlab/lfs_token.rb
+++ b/lib/gitlab/lfs_token.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class LfsToken
attr_accessor :actor
diff --git a/lib/gitlab/logger.rb b/lib/gitlab/logger.rb
index e58927a40b9..128a5dd8936 100644
--- a/lib/gitlab/logger.rb
+++ b/lib/gitlab/logger.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class Logger < ::Logger
def self.file_name
@@ -30,7 +32,7 @@ module Gitlab
end
def self.build
- RequestStore[self.cache_key] ||= new(self.full_log_path)
+ Gitlab::SafeRequestStore[self.cache_key] ||= new(self.full_log_path)
end
def self.full_log_path
diff --git a/lib/gitlab/mail_room.rb b/lib/gitlab/mail_room.rb
index db04356a5e9..78f2d83c1af 100644
--- a/lib/gitlab/mail_room.rb
+++ b/lib/gitlab/mail_room.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'yaml'
require 'json'
require_relative 'redis/queues' unless defined?(Gitlab::Redis::Queues)
diff --git a/lib/gitlab/manifest_import/manifest.rb b/lib/gitlab/manifest_import/manifest.rb
index 4d6034fb956..7208fe5bbc5 100644
--- a/lib/gitlab/manifest_import/manifest.rb
+++ b/lib/gitlab/manifest_import/manifest.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Class to parse manifest file and build a list of repositories for import
#
# <manifest>
@@ -63,7 +65,7 @@ module Gitlab
end
def repository_url(name)
- URI.join(remote, name).to_s
+ Gitlab::Utils.append_path(remote, name)
end
def remote
diff --git a/lib/gitlab/manifest_import/project_creator.rb b/lib/gitlab/manifest_import/project_creator.rb
index b5967c93735..837d65e5f7c 100644
--- a/lib/gitlab/manifest_import/project_creator.rb
+++ b/lib/gitlab/manifest_import/project_creator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ManifestImport
class ProjectCreator
diff --git a/lib/gitlab/markup_helper.rb b/lib/gitlab/markup_helper.rb
index 49285e35251..d419fa66e57 100644
--- a/lib/gitlab/markup_helper.rb
+++ b/lib/gitlab/markup_helper.rb
@@ -1,11 +1,14 @@
+# frozen_string_literal: true
+
module Gitlab
module MarkupHelper
extend self
- MARKDOWN_EXTENSIONS = %w(mdown mkd mkdn md markdown).freeze
- ASCIIDOC_EXTENSIONS = %w(adoc ad asciidoc).freeze
- OTHER_EXTENSIONS = %w(textile rdoc org creole wiki mediawiki rst).freeze
+ MARKDOWN_EXTENSIONS = %w[mdown mkd mkdn md markdown].freeze
+ ASCIIDOC_EXTENSIONS = %w[adoc ad asciidoc].freeze
+ OTHER_EXTENSIONS = %w[textile rdoc org creole wiki mediawiki rst].freeze
EXTENSIONS = MARKDOWN_EXTENSIONS + ASCIIDOC_EXTENSIONS + OTHER_EXTENSIONS
+ PLAIN_FILENAMES = %w[readme index].freeze
# Public: Determines if a given filename is compatible with GitHub::Markup.
#
@@ -41,7 +44,7 @@ module Gitlab
#
# Returns boolean
def plain?(filename)
- extension(filename) == 'txt' || filename.casecmp('readme').zero?
+ extension(filename) == 'txt' || plain_filename?(filename)
end
def previewable?(filename)
@@ -53,5 +56,9 @@ module Gitlab
def extension(filename)
File.extname(filename).downcase.delete('.')
end
+
+ def plain_filename?(filename)
+ PLAIN_FILENAMES.include?(filename.downcase)
+ end
end
end
diff --git a/lib/gitlab/metrics.rb b/lib/gitlab/metrics.rb
index 7d63ca5627d..61ed20ad623 100644
--- a/lib/gitlab/metrics.rb
+++ b/lib/gitlab/metrics.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
include Gitlab::Metrics::InfluxDb
diff --git a/lib/gitlab/metrics/background_transaction.rb b/lib/gitlab/metrics/background_transaction.rb
index 5919ebb1493..fe1722b1095 100644
--- a/lib/gitlab/metrics/background_transaction.rb
+++ b/lib/gitlab/metrics/background_transaction.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
class BackgroundTransaction < Transaction
diff --git a/lib/gitlab/metrics/delta.rb b/lib/gitlab/metrics/delta.rb
index bcf28eed84d..ab2d9e46390 100644
--- a/lib/gitlab/metrics/delta.rb
+++ b/lib/gitlab/metrics/delta.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Class for calculating the difference between two numeric values.
diff --git a/lib/gitlab/metrics/influx_db.rb b/lib/gitlab/metrics/influx_db.rb
index 04135dac4ff..1359e973590 100644
--- a/lib/gitlab/metrics/influx_db.rb
+++ b/lib/gitlab/metrics/influx_db.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
module InfluxDb
@@ -86,7 +88,7 @@ module Gitlab
# Example:
#
# Gitlab::Metrics.measure(:find_by_username_duration) do
- # User.find_by_username(some_username)
+ # UserFinder.new(some_username).find_by_username
# end
#
# name - The name of the field to store the execution time in.
diff --git a/lib/gitlab/metrics/instrumentation.rb b/lib/gitlab/metrics/instrumentation.rb
index 023e9963493..651e241362c 100644
--- a/lib/gitlab/metrics/instrumentation.rb
+++ b/lib/gitlab/metrics/instrumentation.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Module for instrumenting methods.
diff --git a/lib/gitlab/metrics/method_call.rb b/lib/gitlab/metrics/method_call.rb
index f3290e3149c..85438011cb9 100644
--- a/lib/gitlab/metrics/method_call.rb
+++ b/lib/gitlab/metrics/method_call.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Class for tracking timing information about method calls
diff --git a/lib/gitlab/metrics/methods.rb b/lib/gitlab/metrics/methods.rb
index f79eb0cd1bf..447d03bfca4 100644
--- a/lib/gitlab/metrics/methods.rb
+++ b/lib/gitlab/metrics/methods.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# rubocop:disable Style/ClassVars
module Gitlab
diff --git a/lib/gitlab/metrics/methods/metric_options.rb b/lib/gitlab/metrics/methods/metric_options.rb
index 70e122d4e15..8e6ceb74c09 100644
--- a/lib/gitlab/metrics/methods/metric_options.rb
+++ b/lib/gitlab/metrics/methods/metric_options.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
module Methods
diff --git a/lib/gitlab/metrics/metric.rb b/lib/gitlab/metrics/metric.rb
index bd0afe53c51..9e4d70a71ff 100644
--- a/lib/gitlab/metrics/metric.rb
+++ b/lib/gitlab/metrics/metric.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Class for storing details of a single metric (label, value, etc).
diff --git a/lib/gitlab/metrics/null_metric.rb b/lib/gitlab/metrics/null_metric.rb
index aabada5c21a..7dbd2a1f8e3 100644
--- a/lib/gitlab/metrics/null_metric.rb
+++ b/lib/gitlab/metrics/null_metric.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Mocks ::Prometheus::Client::Metric and all derived metrics
diff --git a/lib/gitlab/metrics/prometheus.rb b/lib/gitlab/metrics/prometheus.rb
index d41a855bff1..cab1edab48f 100644
--- a/lib/gitlab/metrics/prometheus.rb
+++ b/lib/gitlab/metrics/prometheus.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'prometheus/client'
module Gitlab
diff --git a/lib/gitlab/metrics/rack_middleware.rb b/lib/gitlab/metrics/rack_middleware.rb
index 2d45765df3f..9aa97515961 100644
--- a/lib/gitlab/metrics/rack_middleware.rb
+++ b/lib/gitlab/metrics/rack_middleware.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Rack middleware for tracking Rails and Grape requests.
diff --git a/lib/gitlab/metrics/requests_rack_middleware.rb b/lib/gitlab/metrics/requests_rack_middleware.rb
index 0dc19f31d03..74c956ab5af 100644
--- a/lib/gitlab/metrics/requests_rack_middleware.rb
+++ b/lib/gitlab/metrics/requests_rack_middleware.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
class RequestsRackMiddleware
diff --git a/lib/gitlab/metrics/samplers/base_sampler.rb b/lib/gitlab/metrics/samplers/base_sampler.rb
index 37f90c4673d..6a062e93f0f 100644
--- a/lib/gitlab/metrics/samplers/base_sampler.rb
+++ b/lib/gitlab/metrics/samplers/base_sampler.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'logger'
module Gitlab
diff --git a/lib/gitlab/metrics/samplers/influx_sampler.rb b/lib/gitlab/metrics/samplers/influx_sampler.rb
index ad97632e4eb..c4c38b23a55 100644
--- a/lib/gitlab/metrics/samplers/influx_sampler.rb
+++ b/lib/gitlab/metrics/samplers/influx_sampler.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
module Samplers
diff --git a/lib/gitlab/metrics/samplers/ruby_sampler.rb b/lib/gitlab/metrics/samplers/ruby_sampler.rb
index 7b2b3bedf04..232a58a7d69 100644
--- a/lib/gitlab/metrics/samplers/ruby_sampler.rb
+++ b/lib/gitlab/metrics/samplers/ruby_sampler.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'prometheus/client/support/unicorn'
module Gitlab
diff --git a/lib/gitlab/metrics/samplers/unicorn_sampler.rb b/lib/gitlab/metrics/samplers/unicorn_sampler.rb
index ea325651fbb..4c4ec026823 100644
--- a/lib/gitlab/metrics/samplers/unicorn_sampler.rb
+++ b/lib/gitlab/metrics/samplers/unicorn_sampler.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
module Samplers
diff --git a/lib/gitlab/metrics/sidekiq_metrics_exporter.rb b/lib/gitlab/metrics/sidekiq_metrics_exporter.rb
index 47b4af5d649..56e106b9612 100644
--- a/lib/gitlab/metrics/sidekiq_metrics_exporter.rb
+++ b/lib/gitlab/metrics/sidekiq_metrics_exporter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'webrick'
require 'prometheus/client/rack/exporter'
diff --git a/lib/gitlab/metrics/sidekiq_middleware.rb b/lib/gitlab/metrics/sidekiq_middleware.rb
index df4bdf16847..0b4485feea9 100644
--- a/lib/gitlab/metrics/sidekiq_middleware.rb
+++ b/lib/gitlab/metrics/sidekiq_middleware.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Sidekiq middleware for tracking jobs.
diff --git a/lib/gitlab/metrics/subscribers/action_view.rb b/lib/gitlab/metrics/subscribers/action_view.rb
index b600e8a2a50..c068f8017fd 100644
--- a/lib/gitlab/metrics/subscribers/action_view.rb
+++ b/lib/gitlab/metrics/subscribers/action_view.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
module Subscribers
diff --git a/lib/gitlab/metrics/subscribers/active_record.rb b/lib/gitlab/metrics/subscribers/active_record.rb
index 04107296ae3..a02dd850582 100644
--- a/lib/gitlab/metrics/subscribers/active_record.rb
+++ b/lib/gitlab/metrics/subscribers/active_record.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
module Subscribers
diff --git a/lib/gitlab/metrics/subscribers/rails_cache.rb b/lib/gitlab/metrics/subscribers/rails_cache.rb
index 250897a79c2..f633e1a9d7c 100644
--- a/lib/gitlab/metrics/subscribers/rails_cache.rb
+++ b/lib/gitlab/metrics/subscribers/rails_cache.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
module Subscribers
diff --git a/lib/gitlab/metrics/system.rb b/lib/gitlab/metrics/system.rb
index e60e245cf89..426496855e3 100644
--- a/lib/gitlab/metrics/system.rb
+++ b/lib/gitlab/metrics/system.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Module for gathering system/process statistics such as the memory usage.
diff --git a/lib/gitlab/metrics/transaction.rb b/lib/gitlab/metrics/transaction.rb
index 9f903e96585..468d7cb56fc 100644
--- a/lib/gitlab/metrics/transaction.rb
+++ b/lib/gitlab/metrics/transaction.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
# Class for storing metrics information of a single transaction.
diff --git a/lib/gitlab/metrics/web_transaction.rb b/lib/gitlab/metrics/web_transaction.rb
index 723ca576aab..b2a43d46fb2 100644
--- a/lib/gitlab/metrics/web_transaction.rb
+++ b/lib/gitlab/metrics/web_transaction.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Metrics
class WebTransaction < Transaction
@@ -40,7 +42,7 @@ module Gitlab
# increasing the cardinality of our metrics, we limit the number of
# possible suffixes.
if suffix && ALLOWED_SUFFIXES.include?(suffix)
- action += ".#{suffix}"
+ action = "#{action}.#{suffix}"
end
{ controller: controller.class.name, action: action }
diff --git a/lib/gitlab/middleware/go.rb b/lib/gitlab/middleware/go.rb
index 1fd8f147b44..d1a87c3b3bb 100644
--- a/lib/gitlab/middleware/go.rb
+++ b/lib/gitlab/middleware/go.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# A dumb middleware that returns a Go HTML document if the go-get=1 query string
# is used irrespective if the namespace/project exists
module Gitlab
@@ -38,7 +40,7 @@ module Gitlab
def go_body(path)
config = Gitlab.config
- project_url = URI.join(config.gitlab.url, path)
+ project_url = Gitlab::Utils.append_path(config.gitlab.url, path)
import_prefix = strip_url(project_url.to_s)
repository_url = if Gitlab::CurrentSettings.enabled_git_access_protocol == 'ssh'
diff --git a/lib/gitlab/middleware/multipart.rb b/lib/gitlab/middleware/multipart.rb
index 10cb1e7127e..84c2f0d5720 100644
--- a/lib/gitlab/middleware/multipart.rb
+++ b/lib/gitlab/middleware/multipart.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Gitlab::Middleware::Multipart - a Rack::Multipart replacement
#
# Rack::Multipart leaves behind tempfiles in /tmp and uses valuable Ruby
diff --git a/lib/gitlab/middleware/rails_queue_duration.rb b/lib/gitlab/middleware/rails_queue_duration.rb
index bc70b2459ef..96c6a0a7d28 100644
--- a/lib/gitlab/middleware/rails_queue_duration.rb
+++ b/lib/gitlab/middleware/rails_queue_duration.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This Rack middleware is intended to measure the latency between
# gitlab-workhorse forwarding a request to the Rails application and the
# time this middleware is reached.
diff --git a/lib/gitlab/middleware/read_only.rb b/lib/gitlab/middleware/read_only.rb
index 7f63e39b3aa..83c52a6c6e0 100644
--- a/lib/gitlab/middleware/read_only.rb
+++ b/lib/gitlab/middleware/read_only.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Middleware
class ReadOnly
diff --git a/lib/gitlab/middleware/read_only/controller.rb b/lib/gitlab/middleware/read_only/controller.rb
index 8dca431c005..89941a9efa0 100644
--- a/lib/gitlab/middleware/read_only/controller.rb
+++ b/lib/gitlab/middleware/read_only/controller.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Middleware
class ReadOnly
diff --git a/lib/gitlab/middleware/release_env.rb b/lib/gitlab/middleware/release_env.rb
index bfe8e113b5e..849cf8f759b 100644
--- a/lib/gitlab/middleware/release_env.rb
+++ b/lib/gitlab/middleware/release_env.rb
@@ -1,4 +1,7 @@
-module Gitlab # rubocop:disable Naming/FileName
+# rubocop:disable Naming/FileName
+# frozen_string_literal: true
+
+module Gitlab
module Middleware
# Some of middleware would hold env for no good reason even after the
# request had already been processed, and we could not garbage collect
diff --git a/lib/gitlab/middleware/static.rb b/lib/gitlab/middleware/static.rb
index aa1e9dc0fdb..972fed2134c 100644
--- a/lib/gitlab/middleware/static.rb
+++ b/lib/gitlab/middleware/static.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Middleware
class Static < ActionDispatch::Static
diff --git a/lib/gitlab/multi_collection_paginator.rb b/lib/gitlab/multi_collection_paginator.rb
index fab7a43dd30..5375077d7dc 100644
--- a/lib/gitlab/multi_collection_paginator.rb
+++ b/lib/gitlab/multi_collection_paginator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class MultiCollectionPaginator
attr_reader :first_collection, :second_collection, :per_page
diff --git a/lib/gitlab/namespace_sanitizer.rb b/lib/gitlab/namespace_sanitizer.rb
new file mode 100644
index 00000000000..d755bbbcaf9
--- /dev/null
+++ b/lib/gitlab/namespace_sanitizer.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Gitlab
+ class NamespaceSanitizer
+ def self.sanitize(namespace)
+ namespace.gsub(/[^-a-z0-9]/, '-').gsub(/^-+/, '')
+ end
+ end
+end
diff --git a/lib/gitlab/null_request_store.rb b/lib/gitlab/null_request_store.rb
new file mode 100644
index 00000000000..8db331dcb9f
--- /dev/null
+++ b/lib/gitlab/null_request_store.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+# Used by Gitlab::SafeRequestStore
+module Gitlab
+ # The methods `begin!`, `clear!`, and `end!` are not defined because they
+ # should only be called directly on `RequestStore`.
+ class NullRequestStore
+ def store
+ {}
+ end
+
+ def active?
+ end
+
+ def read(key)
+ end
+
+ def [](key)
+ end
+
+ def write(key, value)
+ value
+ end
+
+ def []=(key, value)
+ value
+ end
+
+ def exist?(key)
+ false
+ end
+
+ def fetch(key, &block)
+ yield
+ end
+
+ def delete(key, &block)
+ yield(key) if block_given?
+ end
+ end
+end
diff --git a/lib/gitlab/omniauth_initializer.rb b/lib/gitlab/omniauth_initializer.rb
index f33ea0880df..e0ac9eec1f2 100644
--- a/lib/gitlab/omniauth_initializer.rb
+++ b/lib/gitlab/omniauth_initializer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class OmniauthInitializer
def initialize(devise_config)
diff --git a/lib/gitlab/optimistic_locking.rb b/lib/gitlab/optimistic_locking.rb
index d09bce642b0..ce4ba9f752b 100644
--- a/lib/gitlab/optimistic_locking.rb
+++ b/lib/gitlab/optimistic_locking.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module OptimisticLocking
module_function
diff --git a/lib/gitlab/other_markup.rb b/lib/gitlab/other_markup.rb
index fc3f21233dd..bc467486eee 100644
--- a/lib/gitlab/other_markup.rb
+++ b/lib/gitlab/other_markup.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
# Parser/renderer for markups without other special support code.
module OtherMarkup
diff --git a/lib/gitlab/otp_key_rotator.rb b/lib/gitlab/otp_key_rotator.rb
index ca5d49eedb9..1d3200aa099 100644
--- a/lib/gitlab/otp_key_rotator.rb
+++ b/lib/gitlab/otp_key_rotator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
# The +otp_key_base+ param is used to encrypt the User#otp_secret attribute.
#
diff --git a/lib/gitlab/pages.rb b/lib/gitlab/pages.rb
index 981ef8faa9a..16df0700b08 100644
--- a/lib/gitlab/pages.rb
+++ b/lib/gitlab/pages.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Pages
VERSION = File.read(Rails.root.join("GITLAB_PAGES_VERSION")).strip.freeze
diff --git a/lib/gitlab/pages_client.rb b/lib/gitlab/pages_client.rb
index 7b358a3bd1b..3626e53f84c 100644
--- a/lib/gitlab/pages_client.rb
+++ b/lib/gitlab/pages_client.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class PagesClient
class << self
diff --git a/lib/gitlab/pages_transfer.rb b/lib/gitlab/pages_transfer.rb
index fb215f27cbd..a70dc826f97 100644
--- a/lib/gitlab/pages_transfer.rb
+++ b/lib/gitlab/pages_transfer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class PagesTransfer < ProjectTransfer
def root_dir
diff --git a/lib/gitlab/patch/draw_route.rb b/lib/gitlab/patch/draw_route.rb
new file mode 100644
index 00000000000..b00244a6e04
--- /dev/null
+++ b/lib/gitlab/patch/draw_route.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+# We're patching `ActionDispatch::Routing::Mapper` in
+# config/initializers/routing_draw.rb
+module Gitlab
+ module Patch
+ module DrawRoute
+ RoutesNotFound = Class.new(StandardError)
+
+ def draw(routes_name)
+ drawn_any = draw_ce(routes_name) | draw_ee(routes_name)
+
+ drawn_any || raise(RoutesNotFound.new("Cannot find #{routes_name}"))
+ end
+
+ def draw_ce(routes_name)
+ draw_route(route_path("config/routes/#{routes_name}.rb"))
+ end
+
+ def draw_ee(_)
+ true
+ end
+
+ def route_path(routes_name)
+ Rails.root.join(routes_name)
+ end
+
+ def draw_route(path)
+ if File.exist?(path)
+ instance_eval(File.read(path))
+ true
+ else
+ false
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/path_regex.rb b/lib/gitlab/path_regex.rb
index 359dd2bcbc7..fa68dead80b 100644
--- a/lib/gitlab/path_regex.rb
+++ b/lib/gitlab/path_regex.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module PathRegex
extend self
@@ -39,7 +41,6 @@ module Gitlab
import
invites
jwt
- koding
login
notification_settings
oauth
@@ -235,7 +236,7 @@ module Gitlab
def single_line_regexp(regex)
# Turns a multiline extended regexp into a single line one,
- # beacuse `rake routes` breaks on multiline regexes.
+ # because `rake routes` breaks on multiline regexes.
Regexp.new(regex.source.gsub(/\(\?#.+?\)/, '').gsub(/\s*/, ''), regex.options ^ Regexp::EXTENDED).freeze
end
end
diff --git a/lib/gitlab/performance_bar.rb b/lib/gitlab/performance_bar.rb
index fda61000f6a..4b0c7b5c7f8 100644
--- a/lib/gitlab/performance_bar.rb
+++ b/lib/gitlab/performance_bar.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module PerformanceBar
ALLOWED_USER_IDS_KEY = 'performance_bar_allowed_user_ids:v2'.freeze
diff --git a/lib/gitlab/performance_bar/peek_query_tracker.rb b/lib/gitlab/performance_bar/peek_query_tracker.rb
index f2825db59ae..ac392432427 100644
--- a/lib/gitlab/performance_bar/peek_query_tracker.rb
+++ b/lib/gitlab/performance_bar/peek_query_tracker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Inspired by https://github.com/peek/peek-pg/blob/master/lib/peek/views/pg.rb
# PEEK_DB_CLIENT is a constant set in config/initializers/peek.rb
module Gitlab
@@ -23,7 +25,7 @@ module Gitlab
end
subscribe('sql.active_record') do |_, start, finish, _, data|
- if RequestStore.active? && RequestStore.store[:peek_enabled]
+ if Gitlab::SafeRequestStore.store[:peek_enabled]
# data[:cached] is only available starting from Rails 5.1.0
# https://github.com/rails/rails/blob/v5.1.0/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb#L113
# Before that, data[:name] was set to 'CACHE'
diff --git a/lib/gitlab/plugin.rb b/lib/gitlab/plugin.rb
index 0d1cb16b378..23353f36025 100644
--- a/lib/gitlab/plugin.rb
+++ b/lib/gitlab/plugin.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Plugin
def self.files
diff --git a/lib/gitlab/plugin_logger.rb b/lib/gitlab/plugin_logger.rb
index c4f6ec3e21d..df3bd56fd2f 100644
--- a/lib/gitlab/plugin_logger.rb
+++ b/lib/gitlab/plugin_logger.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class PluginLogger < Gitlab::Logger
def self.file_name_noext
diff --git a/lib/gitlab/polling_interval.rb b/lib/gitlab/polling_interval.rb
index fe4bdfe3831..0f69990df63 100644
--- a/lib/gitlab/polling_interval.rb
+++ b/lib/gitlab/polling_interval.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class PollingInterval
HEADER_NAME = 'Poll-Interval'.freeze
diff --git a/lib/gitlab/popen.rb b/lib/gitlab/popen.rb
index d0cb7c1a7cf..7fa00d0c68c 100644
--- a/lib/gitlab/popen.rb
+++ b/lib/gitlab/popen.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'fileutils'
require 'open3'
@@ -11,7 +13,7 @@ module Gitlab
def popen(cmd, path = nil, vars = {}, &block)
result = popen_with_detail(cmd, path, vars, &block)
- [result.stdout << result.stderr, result.status&.exitstatus]
+ ["#{result.stdout}#{result.stderr}", result.status&.exitstatus]
end
# Returns Result
diff --git a/lib/gitlab/popen/runner.rb b/lib/gitlab/popen/runner.rb
index f44035a48bb..cd9ad270cd8 100644
--- a/lib/gitlab/popen/runner.rb
+++ b/lib/gitlab/popen/runner.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Popen
class Runner
diff --git a/lib/gitlab/private_commit_email.rb b/lib/gitlab/private_commit_email.rb
new file mode 100644
index 00000000000..536fc9dae3a
--- /dev/null
+++ b/lib/gitlab/private_commit_email.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module PrivateCommitEmail
+ TOKEN = "_private".freeze
+
+ class << self
+ def regex
+ hostname_regexp = Regexp.escape(Gitlab::CurrentSettings.current_application_settings.commit_email_hostname)
+
+ /\A(?<id>([0-9]+))\-([^@]+)@#{hostname_regexp}\z/
+ end
+
+ def user_id_for_email(email)
+ match = email&.match(regex)
+ return unless match
+
+ match[:id].to_i
+ end
+
+ def user_ids_for_emails(emails)
+ emails.map { |email| user_id_for_email(email) }.compact.uniq
+ end
+
+ def for_user(user)
+ hostname = Gitlab::CurrentSettings.current_application_settings.commit_email_hostname
+
+ "#{user.id}-#{user.username}@#{hostname}"
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/profiler.rb b/lib/gitlab/profiler.rb
index 15391b1330b..93a9fcf1591 100644
--- a/lib/gitlab/profiler.rb
+++ b/lib/gitlab/profiler.rb
@@ -1,4 +1,6 @@
# coding: utf-8
+# frozen_string_literal: true
+
module Gitlab
module Profiler
FILTERED_STRING = '[FILTERED]'.freeze
@@ -34,7 +36,6 @@ module Gitlab
#
# - private_token: instead of providing a user instance, the token can be
# given as a string. Takes precedence over the user option.
- # rubocop: disable CodeReuse/ActiveRecord
def self.profile(url, logger: nil, post_data: nil, user: nil, private_token: nil)
app = ActionDispatch::Integration::Session.new(Rails.application)
verb = :get
@@ -45,12 +46,11 @@ module Gitlab
headers['Content-Type'] = 'application/json'
end
- if user
- private_token ||= user.personal_access_tokens.active.pluck(:token).first
- raise 'Your user must have a personal_access_token' unless private_token
+ if private_token
+ headers['Private-Token'] = private_token
+ user = nil # private_token overrides user
end
- headers['Private-Token'] = private_token if private_token
logger = create_custom_logger(logger, private_token: private_token)
RequestStore.begin!
@@ -68,7 +68,9 @@ module Gitlab
app.get('/api/v4/users')
result = with_custom_logger(logger) do
- RubyProf.profile { app.public_send(verb, url, post_data, headers) } # rubocop:disable GitlabSecurity/PublicSend
+ with_user(user) do
+ RubyProf.profile { app.public_send(verb, url, post_data, headers) } # rubocop:disable GitlabSecurity/PublicSend
+ end
end
RequestStore.end!
@@ -77,7 +79,6 @@ module Gitlab
result
end
- # rubocop: enable CodeReuse/ActiveRecord
def self.create_custom_logger(logger, private_token: nil)
return unless logger
@@ -128,13 +129,29 @@ module Gitlab
ActionController::Base.logger = logger
end
- result = yield
+ yield.tap do
+ ActiveSupport::LogSubscriber.colorize_logging = original_colorize_logging
+ ActiveRecord::Base.logger = original_activerecord_logger
+ ActionController::Base.logger = original_actioncontroller_logger
+ end
+ end
- ActiveSupport::LogSubscriber.colorize_logging = original_colorize_logging
- ActiveRecord::Base.logger = original_activerecord_logger
- ActionController::Base.logger = original_actioncontroller_logger
+ def self.with_user(user)
+ if user
+ API::Helpers::CommonHelpers.send(:define_method, :find_current_user!) { user } # rubocop:disable GitlabSecurity/PublicSend
+ ApplicationController.send(:define_method, :current_user) { user } # rubocop:disable GitlabSecurity/PublicSend
+ ApplicationController.send(:define_method, :authenticate_user!) { } # rubocop:disable GitlabSecurity/PublicSend
+ end
- result
+ yield.tap do
+ remove_method(API::Helpers::CommonHelpers, :find_current_user!)
+ remove_method(ApplicationController, :current_user)
+ remove_method(ApplicationController, :authenticate_user!)
+ end
+ end
+
+ def self.remove_method(klass, meth)
+ klass.send(:remove_method, meth) if klass.instance_methods(false).include?(meth) # rubocop:disable GitlabSecurity/PublicSend
end
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/lib/gitlab/profiler/total_time_flat_printer.rb b/lib/gitlab/profiler/total_time_flat_printer.rb
index 2fd0ec10ba8..2c105d2722b 100644
--- a/lib/gitlab/profiler/total_time_flat_printer.rb
+++ b/lib/gitlab/profiler/total_time_flat_printer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Profiler
class TotalTimeFlatPrinter < RubyProf::FlatPrinter
diff --git a/lib/gitlab/project_authorizations/with_nested_groups.rb b/lib/gitlab/project_authorizations/with_nested_groups.rb
index 448c3f3a7d8..2372a316ab0 100644
--- a/lib/gitlab/project_authorizations/with_nested_groups.rb
+++ b/lib/gitlab/project_authorizations/with_nested_groups.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ProjectAuthorizations
# Calculating new project authorizations when supporting nested groups.
diff --git a/lib/gitlab/project_authorizations/without_nested_groups.rb b/lib/gitlab/project_authorizations/without_nested_groups.rb
index ed2287dcc7e..50b41b17649 100644
--- a/lib/gitlab/project_authorizations/without_nested_groups.rb
+++ b/lib/gitlab/project_authorizations/without_nested_groups.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ProjectAuthorizations
# Calculating new project authorizations when not supporting nested groups.
diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb
index 71e9cc7f238..04df881bf03 100644
--- a/lib/gitlab/project_search_results.rb
+++ b/lib/gitlab/project_search_results.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class ProjectSearchResults < SearchResults
attr_reader :project, :repository_ref
@@ -57,7 +59,8 @@ module Gitlab
ref = nil
filename = nil
basename = nil
- data = ""
+
+ data = []
startline = 0
result.each_line.each_with_index do |line, index|
@@ -78,8 +81,8 @@ module Gitlab
basename: basename,
ref: ref,
startline: startline,
- data: data,
- project_id: project ? project.id : nil
+ data: data.join,
+ project: project
)
end
diff --git a/lib/gitlab/project_service_logger.rb b/lib/gitlab/project_service_logger.rb
index e84dca97962..9b0357d3161 100644
--- a/lib/gitlab/project_service_logger.rb
+++ b/lib/gitlab/project_service_logger.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class ProjectServiceLogger < Gitlab::JsonLogger
def self.file_name_noext
diff --git a/lib/gitlab/project_template.rb b/lib/gitlab/project_template.rb
index 08f6a54776f..3bfd6ee892c 100644
--- a/lib/gitlab/project_template.rb
+++ b/lib/gitlab/project_template.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class ProjectTemplate
attr_reader :title, :name, :description, :preview
diff --git a/lib/gitlab/project_transfer.rb b/lib/gitlab/project_transfer.rb
index 690c38737c0..d8f1d1e2316 100644
--- a/lib/gitlab/project_transfer.rb
+++ b/lib/gitlab/project_transfer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
# This class is used to move local, unhashed files owned by projects to their new location
class ProjectTransfer
diff --git a/lib/gitlab/prometheus/additional_metrics_parser.rb b/lib/gitlab/prometheus/additional_metrics_parser.rb
index a240d090074..bd4ca578840 100644
--- a/lib/gitlab/prometheus/additional_metrics_parser.rb
+++ b/lib/gitlab/prometheus/additional_metrics_parser.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Prometheus
module AdditionalMetricsParser
diff --git a/lib/gitlab/prometheus/metric.rb b/lib/gitlab/prometheus/metric.rb
index 13cc59df795..7ebfc2e25a9 100644
--- a/lib/gitlab/prometheus/metric.rb
+++ b/lib/gitlab/prometheus/metric.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Prometheus
class Metric
diff --git a/lib/gitlab/prometheus/metric_group.rb b/lib/gitlab/prometheus/metric_group.rb
index d696a8fc00c..8f30cdee232 100644
--- a/lib/gitlab/prometheus/metric_group.rb
+++ b/lib/gitlab/prometheus/metric_group.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Prometheus
class MetricGroup
diff --git a/lib/gitlab/prometheus/parsing_error.rb b/lib/gitlab/prometheus/parsing_error.rb
index 49cc0e16080..20b5ef5ce55 100644
--- a/lib/gitlab/prometheus/parsing_error.rb
+++ b/lib/gitlab/prometheus/parsing_error.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Prometheus
ParsingError = Class.new(StandardError)
diff --git a/lib/gitlab/prometheus/queries/additional_metrics_deployment_query.rb b/lib/gitlab/prometheus/queries/additional_metrics_deployment_query.rb
index fa86d2dfd6c..ab6ef7d5466 100644
--- a/lib/gitlab/prometheus/queries/additional_metrics_deployment_query.rb
+++ b/lib/gitlab/prometheus/queries/additional_metrics_deployment_query.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Prometheus
module Queries
diff --git a/lib/gitlab/prometheus/queries/additional_metrics_environment_query.rb b/lib/gitlab/prometheus/queries/additional_metrics_environment_query.rb
index 09f8f1103d2..34b705138ba 100644
--- a/lib/gitlab/prometheus/queries/additional_metrics_environment_query.rb
+++ b/lib/gitlab/prometheus/queries/additional_metrics_environment_query.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Prometheus
module Queries
diff --git a/lib/gitlab/prometheus/queries/base_query.rb b/lib/gitlab/prometheus/queries/base_query.rb
index 29cab6e9c15..9ff414d5236 100644
--- a/lib/gitlab/prometheus/queries/base_query.rb
+++ b/lib/gitlab/prometheus/queries/base_query.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Prometheus
module Queries
diff --git a/lib/gitlab/prometheus/queries/deployment_query.rb b/lib/gitlab/prometheus/queries/deployment_query.rb
index 3a609a795ba..fc32c4353f0 100644
--- a/lib/gitlab/prometheus/queries/deployment_query.rb
+++ b/lib/gitlab/prometheus/queries/deployment_query.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Prometheus
module Queries
diff --git a/lib/gitlab/prometheus/queries/environment_query.rb b/lib/gitlab/prometheus/queries/environment_query.rb
index 4d8b136d7af..56195f85a70 100644
--- a/lib/gitlab/prometheus/queries/environment_query.rb
+++ b/lib/gitlab/prometheus/queries/environment_query.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Prometheus
module Queries
diff --git a/lib/gitlab/prometheus/queries/matched_metric_query.rb b/lib/gitlab/prometheus/queries/matched_metric_query.rb
index d920e9a749f..32294756aa2 100644
--- a/lib/gitlab/prometheus/queries/matched_metric_query.rb
+++ b/lib/gitlab/prometheus/queries/matched_metric_query.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Prometheus
module Queries
diff --git a/lib/gitlab/prometheus/queries/query_additional_metrics.rb b/lib/gitlab/prometheus/queries/query_additional_metrics.rb
index 3be35f189d0..960d3536ec0 100644
--- a/lib/gitlab/prometheus/queries/query_additional_metrics.rb
+++ b/lib/gitlab/prometheus/queries/query_additional_metrics.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Prometheus
module Queries
@@ -81,11 +83,8 @@ module Gitlab
end
def common_query_context(environment, timeframe_start:, timeframe_end:)
- base_query_context(timeframe_start, timeframe_end).merge({
- ci_environment_slug: environment.slug,
- kube_namespace: environment.deployment_platform&.actual_namespace || '',
- environment_filter: %{container_name!="POD",environment="#{environment.slug}"}
- })
+ base_query_context(timeframe_start, timeframe_end)
+ .merge(QueryVariables.call(environment))
end
def base_query_context(timeframe_start, timeframe_end)
diff --git a/lib/gitlab/prometheus/query_variables.rb b/lib/gitlab/prometheus/query_variables.rb
new file mode 100644
index 00000000000..1cc85d4b4a6
--- /dev/null
+++ b/lib/gitlab/prometheus/query_variables.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Prometheus
+ module QueryVariables
+ def self.call(environment)
+ {
+ ci_environment_slug: environment.slug,
+ kube_namespace: environment.deployment_platform&.actual_namespace || '',
+ environment_filter: %{container_name!="POD",environment="#{environment.slug}"}
+ }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/prometheus_client.rb b/lib/gitlab/prometheus_client.rb
index b66253a10e0..45828c77a33 100644
--- a/lib/gitlab/prometheus_client.rb
+++ b/lib/gitlab/prometheus_client.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
# Helper methods to interact with Prometheus network services & resources
class PrometheusClient
diff --git a/lib/gitlab/protocol_access.rb b/lib/gitlab/protocol_access.rb
index 2819c7d062c..efeb1e07d49 100644
--- a/lib/gitlab/protocol_access.rb
+++ b/lib/gitlab/protocol_access.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module ProtocolAccess
def self.allowed?(protocol)
diff --git a/lib/gitlab/proxy_http_connection_adapter.rb b/lib/gitlab/proxy_http_connection_adapter.rb
index d682289b632..a64cb47e77e 100644
--- a/lib/gitlab/proxy_http_connection_adapter.rb
+++ b/lib/gitlab/proxy_http_connection_adapter.rb
@@ -1,8 +1,10 @@
+# frozen_string_literal: true
+
# This class is part of the Gitlab::HTTP wrapper. Depending on the value
# of the global setting allow_local_requests_from_hooks_and_services this adapter
# will allow/block connection to internal IPs and/or urls.
#
-# This functionality can be overriden by providing the setting the option
+# This functionality can be overridden by providing the setting the option
# allow_local_requests = true in the request. For example:
# Gitlab::HTTP.get('http://www.gitlab.com', allow_local_requests: true)
#
diff --git a/lib/gitlab/query_limiting.rb b/lib/gitlab/query_limiting.rb
index 9f69a9e4a39..31e6b120e45 100644
--- a/lib/gitlab/query_limiting.rb
+++ b/lib/gitlab/query_limiting.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module QueryLimiting
# Returns true if we should enable tracking of query counts.
diff --git a/lib/gitlab/query_limiting/active_support_subscriber.rb b/lib/gitlab/query_limiting/active_support_subscriber.rb
index 3c4ff5d1928..065862174bb 100644
--- a/lib/gitlab/query_limiting/active_support_subscriber.rb
+++ b/lib/gitlab/query_limiting/active_support_subscriber.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module QueryLimiting
class ActiveSupportSubscriber < ActiveSupport::Subscriber
diff --git a/lib/gitlab/query_limiting/transaction.rb b/lib/gitlab/query_limiting/transaction.rb
index 66d7d9275cf..e8fad067fa6 100644
--- a/lib/gitlab/query_limiting/transaction.rb
+++ b/lib/gitlab/query_limiting/transaction.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module QueryLimiting
class Transaction
@@ -68,7 +70,7 @@ module Gitlab
def error_message
header = 'Too many SQL queries were executed'
- header += " in #{action}" if action
+ header = "#{header} in #{action}" if action
"#{header}: a maximum of #{THRESHOLD} is allowed but #{count} SQL queries were executed"
end
diff --git a/lib/gitlab/quick_actions/command_definition.rb b/lib/gitlab/quick_actions/command_definition.rb
index 96415271316..259345b8a9a 100644
--- a/lib/gitlab/quick_actions/command_definition.rb
+++ b/lib/gitlab/quick_actions/command_definition.rb
@@ -1,14 +1,17 @@
+# frozen_string_literal: true
+
module Gitlab
module QuickActions
class CommandDefinition
attr_accessor :name, :aliases, :description, :explanation, :params,
- :condition_block, :parse_params_block, :action_block
+ :condition_block, :parse_params_block, :action_block, :warning
def initialize(name, attributes = {})
@name = name
@aliases = attributes[:aliases] || []
@description = attributes[:description] || ''
+ @warning = attributes[:warning] || ''
@explanation = attributes[:explanation] || ''
@params = attributes[:params] || []
@condition_block = attributes[:condition_block]
@@ -33,11 +36,13 @@ module Gitlab
def explain(context, arg)
return unless available?(context)
- if explanation.respond_to?(:call)
- execute_block(explanation, context, arg)
- else
- explanation
- end
+ message = if explanation.respond_to?(:call)
+ execute_block(explanation, context, arg)
+ else
+ explanation
+ end
+
+ warning.empty? ? message : "#{message} (#{warning})"
end
def execute(context, arg)
@@ -61,6 +66,7 @@ module Gitlab
name: name,
aliases: aliases,
description: desc,
+ warning: warning,
params: prms
}
end
diff --git a/lib/gitlab/quick_actions/dsl.rb b/lib/gitlab/quick_actions/dsl.rb
index d82dccd0db5..a3aab92061b 100644
--- a/lib/gitlab/quick_actions/dsl.rb
+++ b/lib/gitlab/quick_actions/dsl.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module QuickActions
module Dsl
@@ -31,6 +33,10 @@ module Gitlab
@description = block_given? ? block : text
end
+ def warning(message = '')
+ @warning = message
+ end
+
# Allows to define params for the next quick action.
# These params are shown in the autocomplete menu.
#
@@ -133,6 +139,7 @@ module Gitlab
name,
aliases: aliases,
description: @description,
+ warning: @warning,
explanation: @explanation,
params: @params,
condition_block: @condition_block,
@@ -150,6 +157,7 @@ module Gitlab
@explanation = nil
@params = nil
@condition_block = nil
+ @warning = nil
@parse_params_block = nil
end
end
diff --git a/lib/gitlab/quick_actions/extractor.rb b/lib/gitlab/quick_actions/extractor.rb
index 30c6806b68e..ff9bb293b47 100644
--- a/lib/gitlab/quick_actions/extractor.rb
+++ b/lib/gitlab/quick_actions/extractor.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module QuickActions
# This class takes an array of commands that should be extracted from a
@@ -29,7 +31,7 @@ module Gitlab
# commands = extractor.extract_commands(msg) #=> [['labels', '~foo ~"bar baz"']]
# msg #=> "hello\nworld"
# ```
- def extract_commands(content)
+ def extract_commands(content, only: nil)
return [content, []] unless content
content = content.dup
@@ -37,7 +39,7 @@ module Gitlab
commands = []
content.delete!("\r")
- content.gsub!(commands_regex) do
+ content.gsub!(commands_regex(only: only)) do
if $~[:cmd]
commands << [$~[:cmd].downcase, $~[:arg]].reject(&:blank?)
''
@@ -60,8 +62,8 @@ module Gitlab
# It looks something like:
#
# /^\/(?<cmd>close|reopen|...)(?:( |$))(?<arg>[^\/\n]*)(?:\n|$)/
- def commands_regex
- names = command_names.map(&:to_s)
+ def commands_regex(only:)
+ names = command_names(limit_to_commands: only).map(&:to_s)
@commands_regex ||= %r{
(?<code>
@@ -133,10 +135,14 @@ module Gitlab
[content, commands]
end
- def command_names
+ def command_names(limit_to_commands:)
command_definitions.flat_map do |command|
next if command.noop?
+ if limit_to_commands && (command.all_names & limit_to_commands).empty?
+ next
+ end
+
command.all_names
end.compact
end
diff --git a/lib/gitlab/quick_actions/spend_time_and_date_separator.rb b/lib/gitlab/quick_actions/spend_time_and_date_separator.rb
index 7328c517a30..f5176376a60 100644
--- a/lib/gitlab/quick_actions/spend_time_and_date_separator.rb
+++ b/lib/gitlab/quick_actions/spend_time_and_date_separator.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module QuickActions
# This class takes spend command argument
diff --git a/lib/gitlab/quick_actions/substitution_definition.rb b/lib/gitlab/quick_actions/substitution_definition.rb
index 688056e5d73..2f78ea05cf0 100644
--- a/lib/gitlab/quick_actions/substitution_definition.rb
+++ b/lib/gitlab/quick_actions/substitution_definition.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module QuickActions
class SubstitutionDefinition < CommandDefinition
diff --git a/lib/gitlab/recaptcha.rb b/lib/gitlab/recaptcha.rb
index c9efa28d7e7..6559c3e3c57 100644
--- a/lib/gitlab/recaptcha.rb
+++ b/lib/gitlab/recaptcha.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Recaptcha
def self.load_configurations!
diff --git a/lib/gitlab/redis/cache.rb b/lib/gitlab/redis/cache.rb
index a991933e910..6e8403ad878 100644
--- a/lib/gitlab/redis/cache.rb
+++ b/lib/gitlab/redis/cache.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# please require all dependencies below:
require_relative 'wrapper' unless defined?(::Rails) && ::Rails.root.present?
diff --git a/lib/gitlab/redis/queues.rb b/lib/gitlab/redis/queues.rb
index e1695aafbeb..8b42c269dd0 100644
--- a/lib/gitlab/redis/queues.rb
+++ b/lib/gitlab/redis/queues.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# please require all dependencies below:
require_relative 'wrapper' unless defined?(::Gitlab::Redis::Wrapper)
diff --git a/lib/gitlab/redis/shared_state.rb b/lib/gitlab/redis/shared_state.rb
index e5a0fdae7ef..9066606ca21 100644
--- a/lib/gitlab/redis/shared_state.rb
+++ b/lib/gitlab/redis/shared_state.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# please require all dependencies below:
require_relative 'wrapper' unless defined?(::Gitlab::Redis::Wrapper)
diff --git a/lib/gitlab/redis/wrapper.rb b/lib/gitlab/redis/wrapper.rb
index 4178b436acf..07a1e20b076 100644
--- a/lib/gitlab/redis/wrapper.rb
+++ b/lib/gitlab/redis/wrapper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This file should only be used by sub-classes, not directly by any clients of the sub-classes
# please require all dependencies below:
require 'active_support/core_ext/hash/keys'
diff --git a/lib/gitlab/reference_counter.rb b/lib/gitlab/reference_counter.rb
index bb26f1b610a..d2dbc6f5ef5 100644
--- a/lib/gitlab/reference_counter.rb
+++ b/lib/gitlab/reference_counter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class ReferenceCounter
REFERENCE_EXPIRE_TIME = 600
diff --git a/lib/gitlab/reference_extractor.rb b/lib/gitlab/reference_extractor.rb
index 9ff82d628c0..00f817c2399 100644
--- a/lib/gitlab/reference_extractor.rb
+++ b/lib/gitlab/reference_extractor.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
# Extract possible GFM references from an arbitrary String for further processing.
class ReferenceExtractor < Banzai::ReferenceExtractor
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index 0f26fcfe8cb..7a1a2eaf6c0 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Regex
extend self
diff --git a/lib/gitlab/repo_path.rb b/lib/gitlab/repo_path.rb
index 4888184403c..202d310e237 100644
--- a/lib/gitlab/repo_path.rb
+++ b/lib/gitlab/repo_path.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module RepoPath
NotFoundError = Class.new(StandardError)
diff --git a/lib/gitlab/repository_cache.rb b/lib/gitlab/repository_cache.rb
index b1bf3ca4143..6b0808f5304 100644
--- a/lib/gitlab/repository_cache.rb
+++ b/lib/gitlab/repository_cache.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Interface to the Redis-backed cache store
module Gitlab
class RepositoryCache
@@ -5,13 +7,13 @@ module Gitlab
def initialize(repository, extra_namespace: nil, backend: Rails.cache)
@repository = repository
- @namespace = "#{repository.full_path}:#{repository.project.id}"
- @namespace += ":#{extra_namespace}" if extra_namespace
+ @namespace = "project:#{repository.project.id}"
+ @namespace = "#{@namespace}:#{extra_namespace}" if extra_namespace
@backend = backend
end
def cache_key(type)
- "#{type}:#{namespace}"
+ "#{namespace}:#{type}"
end
def expire(key)
@@ -29,5 +31,21 @@ module Gitlab
def read(key)
backend.read(cache_key(key))
end
+
+ def write(key, value)
+ backend.write(cache_key(key), value)
+ end
+
+ def fetch_without_caching_false(key, &block)
+ value = read(key)
+ return value if value
+
+ value = yield
+
+ # Don't cache false values
+ write(key, value) if value
+
+ value
+ end
end
end
diff --git a/lib/gitlab/repository_cache_adapter.rb b/lib/gitlab/repository_cache_adapter.rb
index 2ec871f0754..931298b5117 100644
--- a/lib/gitlab/repository_cache_adapter.rb
+++ b/lib/gitlab/repository_cache_adapter.rb
@@ -1,23 +1,82 @@
+# frozen_string_literal: true
+
module Gitlab
module RepositoryCacheAdapter
extend ActiveSupport::Concern
+ include Gitlab::Utils::StrongMemoize
class_methods do
- # Wraps around the given method and caches its output in Redis and an instance
- # variable.
+ # Caches and strongly memoizes the method.
#
# This only works for methods that do not take any arguments.
- def cache_method(name, fallback: nil, memoize_only: false)
- original = :"_uncached_#{name}"
+ #
+ # name - The name of the method to be cached.
+ # fallback - A value to fall back to if the repository does not exist, or
+ # in case of a Git error. Defaults to nil.
+ def cache_method(name, fallback: nil)
+ uncached_name = alias_uncached_method(name)
+
+ define_method(name) do
+ cache_method_output(name, fallback: fallback) do
+ __send__(uncached_name) # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
+ end
- alias_method(original, name)
+ # Caches truthy values from the method. All values are strongly memoized,
+ # and cached in RequestStore.
+ #
+ # Currently only used to cache `exists?` since stale false values are
+ # particularly troublesome. This can occur, for example, when an NFS mount
+ # is temporarily down.
+ #
+ # This only works for methods that do not take any arguments.
+ #
+ # name - The name of the method to be cached.
+ def cache_method_asymmetrically(name)
+ uncached_name = alias_uncached_method(name)
define_method(name) do
- cache_method_output(name, fallback: fallback, memoize_only: memoize_only) do
- __send__(original) # rubocop:disable GitlabSecurity/PublicSend
+ cache_method_output_asymmetrically(name) do
+ __send__(uncached_name) # rubocop:disable GitlabSecurity/PublicSend
end
end
end
+
+ # Strongly memoizes the method.
+ #
+ # This only works for methods that do not take any arguments.
+ #
+ # name - The name of the method to be memoized.
+ # fallback - A value to fall back to if the repository does not exist, or
+ # in case of a Git error. Defaults to nil. The fallback value
+ # is not memoized.
+ def memoize_method(name, fallback: nil)
+ uncached_name = alias_uncached_method(name)
+
+ define_method(name) do
+ memoize_method_output(name, fallback: fallback) do
+ __send__(uncached_name) # rubocop:disable GitlabSecurity/PublicSend
+ end
+ end
+ end
+
+ # Prepends "_uncached_" to the target method name
+ #
+ # Returns the uncached method name
+ def alias_uncached_method(name)
+ uncached_name = :"_uncached_#{name}"
+
+ alias_method(uncached_name, name)
+
+ uncached_name
+ end
+ end
+
+ # RequestStore-backed RepositoryCache to be used. Should be overridden by
+ # the including class
+ def request_store_cache
+ raise NotImplementedError
end
# RepositoryCache to be used. Should be overridden by the including class
@@ -30,65 +89,93 @@ module Gitlab
raise NotImplementedError
end
- # Caches the supplied block both in a cache and in an instance variable.
+ # Caches and strongly memoizes the supplied block.
#
- # The cache key and instance variable are named the same way as the value of
- # the `key` argument.
+ # name - The name of the method to be cached.
+ # fallback - A value to fall back to if the repository does not exist, or
+ # in case of a Git error. Defaults to nil.
+ def cache_method_output(name, fallback: nil, &block)
+ memoize_method_output(name, fallback: fallback) do
+ cache.fetch(name, &block)
+ end
+ end
+
+ # Caches truthy values from the supplied block. All values are strongly
+ # memoized, and cached in RequestStore.
#
- # This method will return `nil` if the corresponding instance variable is also
- # set to `nil`. This ensures we don't keep yielding the block when it returns
- # `nil`.
+ # Currently only used to cache `exists?` since stale false values are
+ # particularly troublesome. This can occur, for example, when an NFS mount
+ # is temporarily down.
#
- # key - The name of the key to cache the data in.
- # fallback - A value to fall back to in the event of a Git error.
- def cache_method_output(key, fallback: nil, memoize_only: false, &block)
- ivar = cache_instance_variable_name(key)
-
- if instance_variable_defined?(ivar)
- instance_variable_get(ivar)
- else
- # If the repository doesn't exist and a fallback was specified we return
- # that value inmediately. This saves us Rugged/gRPC invocations.
- return fallback unless fallback.nil? || cache.repository.exists?
-
- begin
- value =
- if memoize_only
- yield
- else
- cache.fetch(key, &block)
- end
-
- instance_variable_set(ivar, value)
- rescue Gitlab::Git::Repository::NoRepository
- # Even if the above `#exists?` check passes these errors might still
- # occur (for example because of a non-existing HEAD). We want to
- # gracefully handle this and not cache anything
- fallback
+ # name - The name of the method to be cached.
+ def cache_method_output_asymmetrically(name, &block)
+ memoize_method_output(name) do
+ request_store_cache.fetch(name) do
+ cache.fetch_without_caching_false(name, &block)
end
end
end
+ # Strongly memoizes the supplied block.
+ #
+ # name - The name of the method to be memoized.
+ # fallback - A value to fall back to if the repository does not exist, or
+ # in case of a Git error. Defaults to nil. The fallback value is
+ # not memoized.
+ def memoize_method_output(name, fallback: nil, &block)
+ no_repository_fallback(name, fallback: fallback) do
+ strong_memoize(memoizable_name(name), &block)
+ end
+ end
+
+ # Returns the fallback value if the repository does not exist
+ def no_repository_fallback(name, fallback: nil, &block)
+ # Avoid unnecessary gRPC invocations
+ return fallback if fallback && fallback_early?(name)
+
+ yield
+ rescue Gitlab::Git::Repository::NoRepository
+ # Even if the `#exists?` check in `fallback_early?` passes, these errors
+ # might still occur (for example because of a non-existing HEAD). We
+ # want to gracefully handle this and not memoize anything.
+ fallback
+ end
+
# Expires the caches of a specific set of methods
def expire_method_caches(methods)
- methods.each do |key|
- unless cached_methods.include?(key.to_sym)
- Rails.logger.error "Requested to expire non-existent method '#{key}' for Repository"
+ methods.each do |name|
+ unless cached_methods.include?(name.to_sym)
+ Rails.logger.error "Requested to expire non-existent method '#{name}' for Repository"
next
end
- cache.expire(key)
+ cache.expire(name)
- ivar = cache_instance_variable_name(key)
-
- remove_instance_variable(ivar) if instance_variable_defined?(ivar)
+ clear_memoization(memoizable_name(name))
end
+
+ expire_request_store_method_caches(methods)
end
private
- def cache_instance_variable_name(key)
- :"@#{key.to_s.tr('?!', '')}"
+ def memoizable_name(name)
+ "#{name.to_s.tr('?!', '')}"
+ end
+
+ def expire_request_store_method_caches(methods)
+ methods.each do |name|
+ request_store_cache.expire(name)
+ end
+ end
+
+ # All cached repository methods depend on the existence of a Git repository,
+ # so if the repository doesn't exist, we already know not to call it.
+ def fallback_early?(method_name)
+ # Avoid infinite loop
+ return false if method_name == :exists?
+
+ !exists?
end
end
end
diff --git a/lib/gitlab/repository_check_logger.rb b/lib/gitlab/repository_check_logger.rb
index 485b596ca57..e90b0a002af 100644
--- a/lib/gitlab/repository_check_logger.rb
+++ b/lib/gitlab/repository_check_logger.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class RepositoryCheckLogger < Gitlab::Logger
def self.file_name_noext
diff --git a/lib/gitlab/request_context.rb b/lib/gitlab/request_context.rb
index fef536ecb0b..f8f8ec789ce 100644
--- a/lib/gitlab/request_context.rb
+++ b/lib/gitlab/request_context.rb
@@ -1,8 +1,10 @@
+# frozen_string_literal: true
+
module Gitlab
class RequestContext
class << self
def client_ip
- RequestStore[:client_ip]
+ Gitlab::SafeRequestStore[:client_ip]
end
end
@@ -13,7 +15,7 @@ module Gitlab
def call(env)
req = Rack::Request.new(env)
- RequestStore[:client_ip] = req.ip
+ Gitlab::SafeRequestStore[:client_ip] = req.ip
@app.call(env)
end
diff --git a/lib/gitlab/request_forgery_protection.rb b/lib/gitlab/request_forgery_protection.rb
index a502ad8a541..b1e478093d3 100644
--- a/lib/gitlab/request_forgery_protection.rb
+++ b/lib/gitlab/request_forgery_protection.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# A module to check CSRF tokens in requests.
# It's used in API helpers and OmniAuth.
# Usage: GitLab::RequestForgeryProtection.call(env)
diff --git a/lib/gitlab/request_profiler.rb b/lib/gitlab/request_profiler.rb
index 0c9ab759e81..64593153686 100644
--- a/lib/gitlab/request_profiler.rb
+++ b/lib/gitlab/request_profiler.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'fileutils'
module Gitlab
diff --git a/lib/gitlab/request_profiler/middleware.rb b/lib/gitlab/request_profiler/middleware.rb
index ef42b0557e0..7615f6f443b 100644
--- a/lib/gitlab/request_profiler/middleware.rb
+++ b/lib/gitlab/request_profiler/middleware.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'ruby-prof'
module Gitlab
diff --git a/lib/gitlab/request_profiler/profile.rb b/lib/gitlab/request_profiler/profile.rb
index f89d56903ef..46996ef8c51 100644
--- a/lib/gitlab/request_profiler/profile.rb
+++ b/lib/gitlab/request_profiler/profile.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module RequestProfiler
class Profile
diff --git a/lib/gitlab/route_map.rb b/lib/gitlab/route_map.rb
index f3952657983..a555bf1d812 100644
--- a/lib/gitlab/route_map.rb
+++ b/lib/gitlab/route_map.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class RouteMap
FormatError = Class.new(StandardError)
diff --git a/lib/gitlab/routing.rb b/lib/gitlab/routing.rb
index 2c994536060..3b05f181ed2 100644
--- a/lib/gitlab/routing.rb
+++ b/lib/gitlab/routing.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Routing
extend ActiveSupport::Concern
@@ -47,7 +49,7 @@ module Gitlab
#
# `request.fullpath` includes the querystring
new_path = request.path.sub(%r{/#{path}(/*)(?!.*#{path})}, "/-/#{path}\\1")
- new_path << "?#{request.query_string}" if request.query_string.present?
+ new_path = "#{new_path}?#{request.query_string}" if request.query_string.present?
new_path
end
diff --git a/lib/gitlab/safe_request_store.rb b/lib/gitlab/safe_request_store.rb
new file mode 100644
index 00000000000..4e82353adb6
--- /dev/null
+++ b/lib/gitlab/safe_request_store.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SafeRequestStore
+ NULL_STORE = Gitlab::NullRequestStore.new
+
+ class << self
+ # These methods should always run directly against RequestStore
+ delegate :clear!, :begin!, :end!, :active?, to: :RequestStore
+
+ # These methods will run against NullRequestStore if RequestStore is disabled
+ delegate :read, :[], :write, :[]=, :exist?, :fetch, :delete, to: :store
+ end
+
+ def self.store
+ if RequestStore.active?
+ RequestStore
+ else
+ NULL_STORE
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/sanitizers/svg.rb b/lib/gitlab/sanitizers/svg.rb
index 8304b9a482c..0d4e6be2129 100644
--- a/lib/gitlab/sanitizers/svg.rb
+++ b/lib/gitlab/sanitizers/svg.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Sanitizers
module SVG
diff --git a/lib/gitlab/sanitizers/svg/whitelist.rb b/lib/gitlab/sanitizers/svg/whitelist.rb
index d50f826f924..b4da24b3215 100644
--- a/lib/gitlab/sanitizers/svg/whitelist.rb
+++ b/lib/gitlab/sanitizers/svg/whitelist.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Generated from:
# SVG element list: https://www.w3.org/TR/SVG/eltindex.html
# SVG Attribute list: https://www.w3.org/TR/SVG/attindex.html
diff --git a/lib/gitlab/search/parsed_query.rb b/lib/gitlab/search/parsed_query.rb
index 23595f23f01..c4fb0199558 100644
--- a/lib/gitlab/search/parsed_query.rb
+++ b/lib/gitlab/search/parsed_query.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Search
class ParsedQuery
diff --git a/lib/gitlab/search/query.rb b/lib/gitlab/search/query.rb
index 8583bce7792..7f69083a492 100644
--- a/lib/gitlab/search/query.rb
+++ b/lib/gitlab/search/query.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Search
class Query < SimpleDelegator
diff --git a/lib/gitlab/search_results.rb b/lib/gitlab/search_results.rb
index d1cf8e10228..458737f31eb 100644
--- a/lib/gitlab/search_results.rb
+++ b/lib/gitlab/search_results.rb
@@ -1,9 +1,13 @@
+# frozen_string_literal: true
+
module Gitlab
class SearchResults
class FoundBlob
include EncodingHelper
+ include Presentable
+ include BlobLanguageFromGitAttributes
- attr_reader :id, :filename, :basename, :ref, :startline, :data, :project_id
+ attr_reader :id, :filename, :basename, :ref, :startline, :data, :project
def initialize(opts = {})
@id = opts.fetch(:id, nil)
@@ -13,6 +17,11 @@ module Gitlab
@startline = opts.fetch(:startline, nil)
@data = encode_utf8(opts.fetch(:data, nil))
@per_page = opts.fetch(:per_page, 20)
+ @project = opts.fetch(:project, nil)
+ # Some caller does not have project object (e.g. elastic search),
+ # yet they can trigger many calls in one go,
+ # causing duplicated queries.
+ # Allow those to just pass project_id instead.
@project_id = opts.fetch(:project_id, nil)
end
@@ -20,8 +29,12 @@ module Gitlab
filename
end
- def no_highlighting?
- false
+ def project_id
+ @project_id || @project&.id
+ end
+
+ def present
+ super(presenter_class: BlobPresenter)
end
end
diff --git a/lib/gitlab/seeder.rb b/lib/gitlab/seeder.rb
index 98f005cb61b..84a51773276 100644
--- a/lib/gitlab/seeder.rb
+++ b/lib/gitlab/seeder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# :nocov:
module DeliverNever
def deliver_later
diff --git a/lib/gitlab/sentry.rb b/lib/gitlab/sentry.rb
index 6381e94c1d2..8079c5882c4 100644
--- a/lib/gitlab/sentry.rb
+++ b/lib/gitlab/sentry.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Sentry
def self.enabled?
@@ -5,7 +7,7 @@ module Gitlab
end
def self.context(current_user = nil)
- return unless self.enabled?
+ return unless enabled?
Raven.tags_context(locale: I18n.locale)
@@ -27,14 +29,22 @@ module Gitlab
#
# Provide an issue URL for follow up.
def self.track_exception(exception, issue_url: nil, extra: {})
+ track_acceptable_exception(exception, issue_url: issue_url, extra: extra)
+
+ raise exception if should_raise?
+ end
+
+ # This should be used when you do not want to raise an exception in
+ # development and test. If you need development and test to behave
+ # just the same as production you can use this instead of
+ # track_exception.
+ def self.track_acceptable_exception(exception, issue_url: nil, extra: {})
if enabled?
extra[:issue_url] = issue_url if issue_url
context # Make sure we've set everything we know in the context
Raven.capture_exception(exception, extra: extra)
end
-
- raise exception if should_raise?
end
def self.program_context
diff --git a/lib/gitlab/serializer/ci/variables.rb b/lib/gitlab/serializer/ci/variables.rb
index 292c8de6229..9abf3a54f37 100644
--- a/lib/gitlab/serializer/ci/variables.rb
+++ b/lib/gitlab/serializer/ci/variables.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Serializer
module Ci
diff --git a/lib/gitlab/serializer/pagination.rb b/lib/gitlab/serializer/pagination.rb
index 6bb00d8ae21..eb242cc7c20 100644
--- a/lib/gitlab/serializer/pagination.rb
+++ b/lib/gitlab/serializer/pagination.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Serializer
class Pagination
diff --git a/lib/gitlab/setup_helper.rb b/lib/gitlab/setup_helper.rb
index 5b68e4470cd..2b7e12639be 100644
--- a/lib/gitlab/setup_helper.rb
+++ b/lib/gitlab/setup_helper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'toml-rb'
module Gitlab
@@ -30,7 +32,10 @@ module Gitlab
end
if Rails.env.test?
- storages << { name: 'test_second_storage', path: Rails.root.join('tmp', 'tests', 'second_storage').to_s }
+ storage_path = Rails.root.join('tmp', 'tests', 'second_storage').to_s
+
+ FileUtils.mkdir(storage_path) unless File.exist?(storage_path)
+ storages << { name: 'test_second_storage', path: storage_path }
end
config = { socket_path: address.sub(/\Aunix:/, ''), storage: storages }
diff --git a/lib/gitlab/shard_health_cache.rb b/lib/gitlab/shard_health_cache.rb
index 3f03f46d4b1..6612347438e 100644
--- a/lib/gitlab/shard_health_cache.rb
+++ b/lib/gitlab/shard_health_cache.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class ShardHealthCache
HEALTHY_SHARDS_KEY = 'gitlab-healthy-shards'.freeze
diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb
index 89d2028d7b0..c6a6fb9b5ce 100644
--- a/lib/gitlab/shell.rb
+++ b/lib/gitlab/shell.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Gitaly note: SSH key operations are not part of Gitaly so will never be migrated.
require 'securerandom'
@@ -106,23 +108,6 @@ module Gitlab
success
end
- # Fetch remote for repository
- #
- # repository - an instance of Git::Repository
- # remote - remote name
- # ssh_auth - SSH known_hosts data and a private key to use for public-key authentication
- # forced - should we use --force flag?
- # no_tags - should we use --no-tags flag?
- #
- # Ex.
- # fetch_remote(my_repo, "upstream")
- #
- def fetch_remote(repository, remote, ssh_auth: nil, forced: false, no_tags: false, prune: true)
- wrapped_gitaly_errors do
- repository.gitaly_repository_client.fetch_remote(remote, ssh_auth: ssh_auth, forced: forced, no_tags: no_tags, timeout: git_timeout, prune: prune)
- end
- end
-
# Move repository reroutes to mv_directory which is an alias for
# mv_namespace. Given the underlying implementation is a move action,
# indescriminate of what the folders might be.
diff --git a/lib/gitlab/shell_adapter.rb b/lib/gitlab/shell_adapter.rb
index 053dd4ab9e0..59fc6ee8dc8 100644
--- a/lib/gitlab/shell_adapter.rb
+++ b/lib/gitlab/shell_adapter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# == GitLab Shell mixin
#
# Provide a shortcut to Gitlab::Shell instance by gitlab_shell
diff --git a/lib/gitlab/sherlock.rb b/lib/gitlab/sherlock.rb
index 6360527a7aa..a1471c9de47 100644
--- a/lib/gitlab/sherlock.rb
+++ b/lib/gitlab/sherlock.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'securerandom'
module Gitlab
diff --git a/lib/gitlab/sherlock/collection.rb b/lib/gitlab/sherlock/collection.rb
index 66bd6258521..ce3a376cf75 100644
--- a/lib/gitlab/sherlock/collection.rb
+++ b/lib/gitlab/sherlock/collection.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Sherlock
# A collection of transactions recorded by Sherlock.
diff --git a/lib/gitlab/sherlock/file_sample.rb b/lib/gitlab/sherlock/file_sample.rb
index 89072b01f2e..604b6df12cc 100644
--- a/lib/gitlab/sherlock/file_sample.rb
+++ b/lib/gitlab/sherlock/file_sample.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Sherlock
class FileSample
diff --git a/lib/gitlab/sherlock/line_profiler.rb b/lib/gitlab/sherlock/line_profiler.rb
index b5f9d040047..209ba784f9c 100644
--- a/lib/gitlab/sherlock/line_profiler.rb
+++ b/lib/gitlab/sherlock/line_profiler.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Sherlock
# Class for profiling code on a per line basis.
diff --git a/lib/gitlab/sherlock/line_sample.rb b/lib/gitlab/sherlock/line_sample.rb
index eb1948eb6d6..c92fa9ea1ff 100644
--- a/lib/gitlab/sherlock/line_sample.rb
+++ b/lib/gitlab/sherlock/line_sample.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Sherlock
class LineSample
diff --git a/lib/gitlab/sherlock/location.rb b/lib/gitlab/sherlock/location.rb
index 5ac265618ad..4bba60f3490 100644
--- a/lib/gitlab/sherlock/location.rb
+++ b/lib/gitlab/sherlock/location.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Sherlock
class Location
diff --git a/lib/gitlab/sherlock/middleware.rb b/lib/gitlab/sherlock/middleware.rb
index 4c88e33699a..747cb0f9142 100644
--- a/lib/gitlab/sherlock/middleware.rb
+++ b/lib/gitlab/sherlock/middleware.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Sherlock
# Rack middleware used for tracking request metrics.
diff --git a/lib/gitlab/sherlock/query.rb b/lib/gitlab/sherlock/query.rb
index 02ddc3f47eb..11561eec32a 100644
--- a/lib/gitlab/sherlock/query.rb
+++ b/lib/gitlab/sherlock/query.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Sherlock
class Query
@@ -48,7 +50,7 @@ module Gitlab
end
unless @query.end_with?(';')
- @query += ';'
+ @query = "#{@query};"
end
end
diff --git a/lib/gitlab/sherlock/transaction.rb b/lib/gitlab/sherlock/transaction.rb
index 400a552bf99..d04624977dc 100644
--- a/lib/gitlab/sherlock/transaction.rb
+++ b/lib/gitlab/sherlock/transaction.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Sherlock
class Transaction
diff --git a/lib/gitlab/sidekiq_config.rb b/lib/gitlab/sidekiq_config.rb
index c3d7814551c..3b8de64913b 100644
--- a/lib/gitlab/sidekiq_config.rb
+++ b/lib/gitlab/sidekiq_config.rb
@@ -1,13 +1,22 @@
+# frozen_string_literal: true
+
require 'yaml'
require 'set'
module Gitlab
module SidekiqConfig
+ QUEUE_CONFIG_PATHS = %w[app/workers/all_queues.yml ee/app/workers/all_queues.yml].freeze
+
# This method is called by `bin/sidekiq-cluster` in EE, which runs outside
# of bundler/Rails context, so we cannot use any gem or Rails methods.
def self.worker_queues(rails_path = Rails.root.to_s)
@worker_queues ||= {}
- @worker_queues[rails_path] ||= YAML.load_file(File.join(rails_path, 'app/workers/all_queues.yml'))
+
+ @worker_queues[rails_path] ||= QUEUE_CONFIG_PATHS.flat_map do |path|
+ full_path = File.join(rails_path, path)
+
+ File.exist?(full_path) ? YAML.load_file(full_path) : []
+ end
end
# This method is called by `bin/sidekiq-cluster` in EE, which runs outside
diff --git a/lib/gitlab/sidekiq_logger.rb b/lib/gitlab/sidekiq_logger.rb
index c1dab87a432..ce82a6f04bb 100644
--- a/lib/gitlab/sidekiq_logger.rb
+++ b/lib/gitlab/sidekiq_logger.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class SidekiqLogger < Gitlab::Logger
def self.file_name_noext
diff --git a/lib/gitlab/sidekiq_logging/json_formatter.rb b/lib/gitlab/sidekiq_logging/json_formatter.rb
index 98f8222fd03..88888c5994e 100644
--- a/lib/gitlab/sidekiq_logging/json_formatter.rb
+++ b/lib/gitlab/sidekiq_logging/json_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SidekiqLogging
class JSONFormatter
diff --git a/lib/gitlab/sidekiq_logging/structured_logger.rb b/lib/gitlab/sidekiq_logging/structured_logger.rb
index 9a89ae70b98..e86db8db3a1 100644
--- a/lib/gitlab/sidekiq_logging/structured_logger.rb
+++ b/lib/gitlab/sidekiq_logging/structured_logger.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SidekiqLogging
class StructuredLogger
diff --git a/lib/gitlab/sidekiq_middleware/arguments_logger.rb b/lib/gitlab/sidekiq_middleware/arguments_logger.rb
index 82a59a7a87e..2859aa5f4a6 100644
--- a/lib/gitlab/sidekiq_middleware/arguments_logger.rb
+++ b/lib/gitlab/sidekiq_middleware/arguments_logger.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SidekiqMiddleware
class ArgumentsLogger
diff --git a/lib/gitlab/sidekiq_middleware/batch_loader.rb b/lib/gitlab/sidekiq_middleware/batch_loader.rb
new file mode 100644
index 00000000000..75c4efc3042
--- /dev/null
+++ b/lib/gitlab/sidekiq_middleware/batch_loader.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module SidekiqMiddleware
+ class BatchLoader
+ def call(worker, job, queue)
+ yield
+ ensure
+ ::BatchLoader::Executor.clear_current
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/sidekiq_middleware/request_store_middleware.rb b/lib/gitlab/sidekiq_middleware/request_store_middleware.rb
index b1fa0e3cb4e..8824f81e8e3 100644
--- a/lib/gitlab/sidekiq_middleware/request_store_middleware.rb
+++ b/lib/gitlab/sidekiq_middleware/request_store_middleware.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SidekiqMiddleware
class RequestStoreMiddleware
diff --git a/lib/gitlab/sidekiq_middleware/shutdown.rb b/lib/gitlab/sidekiq_middleware/shutdown.rb
index b232ac4da33..19f3be83bce 100644
--- a/lib/gitlab/sidekiq_middleware/shutdown.rb
+++ b/lib/gitlab/sidekiq_middleware/shutdown.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'mutex_m'
module Gitlab
diff --git a/lib/gitlab/sidekiq_status.rb b/lib/gitlab/sidekiq_status.rb
index a1f689d94d9..583a970bf4e 100644
--- a/lib/gitlab/sidekiq_status.rb
+++ b/lib/gitlab/sidekiq_status.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
# The SidekiqStatus module and its child classes can be used for checking if a
# Sidekiq job has been processed or not.
diff --git a/lib/gitlab/sidekiq_status/client_middleware.rb b/lib/gitlab/sidekiq_status/client_middleware.rb
index 00983b3284a..bfd5038557d 100644
--- a/lib/gitlab/sidekiq_status/client_middleware.rb
+++ b/lib/gitlab/sidekiq_status/client_middleware.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SidekiqStatus
class ClientMiddleware
diff --git a/lib/gitlab/sidekiq_status/server_middleware.rb b/lib/gitlab/sidekiq_status/server_middleware.rb
index ceab10b8301..01bc58fd2be 100644
--- a/lib/gitlab/sidekiq_status/server_middleware.rb
+++ b/lib/gitlab/sidekiq_status/server_middleware.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SidekiqStatus
class ServerMiddleware
diff --git a/lib/gitlab/sidekiq_throttler.rb b/lib/gitlab/sidekiq_throttler.rb
deleted file mode 100644
index 5512afa45a8..00000000000
--- a/lib/gitlab/sidekiq_throttler.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-module Gitlab
- class SidekiqThrottler
- class << self
- def execute!
- if Gitlab::CurrentSettings.sidekiq_throttling_enabled?
- require 'sidekiq-limit_fetch'
-
- Gitlab::CurrentSettings.current_application_settings.sidekiq_throttling_queues.each do |queue|
- Sidekiq::Queue[queue].limit = queue_limit
- end
- end
- end
-
- private
-
- def queue_limit
- @queue_limit ||=
- begin
- factor = Gitlab::CurrentSettings.current_application_settings.sidekiq_throttling_factor
- (factor * Sidekiq.options[:concurrency]).ceil
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/sidekiq_versioning.rb b/lib/gitlab/sidekiq_versioning.rb
index 9683214ec18..8164a5a9d7a 100644
--- a/lib/gitlab/sidekiq_versioning.rb
+++ b/lib/gitlab/sidekiq_versioning.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SidekiqVersioning
def self.install!
diff --git a/lib/gitlab/sidekiq_versioning/manager.rb b/lib/gitlab/sidekiq_versioning/manager.rb
index 308be0fdf76..e5852b43003 100644
--- a/lib/gitlab/sidekiq_versioning/manager.rb
+++ b/lib/gitlab/sidekiq_versioning/manager.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SidekiqVersioning
module Manager
diff --git a/lib/gitlab/slash_commands/base_command.rb b/lib/gitlab/slash_commands/base_command.rb
index 0c76378d51c..fcc120112f2 100644
--- a/lib/gitlab/slash_commands/base_command.rb
+++ b/lib/gitlab/slash_commands/base_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
class BaseCommand
diff --git a/lib/gitlab/slash_commands/command.rb b/lib/gitlab/slash_commands/command.rb
index c82320a6036..474c09b9c4d 100644
--- a/lib/gitlab/slash_commands/command.rb
+++ b/lib/gitlab/slash_commands/command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
class Command < BaseCommand
diff --git a/lib/gitlab/slash_commands/deploy.rb b/lib/gitlab/slash_commands/deploy.rb
index b308fd9637f..157d924f99f 100644
--- a/lib/gitlab/slash_commands/deploy.rb
+++ b/lib/gitlab/slash_commands/deploy.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
class Deploy < BaseCommand
diff --git a/lib/gitlab/slash_commands/help.rb b/lib/gitlab/slash_commands/help.rb
index 81f3707e03e..dbe15baa3d7 100644
--- a/lib/gitlab/slash_commands/help.rb
+++ b/lib/gitlab/slash_commands/help.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
class Help < BaseCommand
diff --git a/lib/gitlab/slash_commands/issue_command.rb b/lib/gitlab/slash_commands/issue_command.rb
index 3d96982b820..4c8dc4b1784 100644
--- a/lib/gitlab/slash_commands/issue_command.rb
+++ b/lib/gitlab/slash_commands/issue_command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
class IssueCommand < BaseCommand
diff --git a/lib/gitlab/slash_commands/issue_move.rb b/lib/gitlab/slash_commands/issue_move.rb
index 3985e635983..d2f1f130b38 100644
--- a/lib/gitlab/slash_commands/issue_move.rb
+++ b/lib/gitlab/slash_commands/issue_move.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
class IssueMove < IssueCommand
diff --git a/lib/gitlab/slash_commands/issue_new.rb b/lib/gitlab/slash_commands/issue_new.rb
index 25f965e843d..48379031537 100644
--- a/lib/gitlab/slash_commands/issue_new.rb
+++ b/lib/gitlab/slash_commands/issue_new.rb
@@ -1,9 +1,11 @@
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
class IssueNew < IssueCommand
def self.match(text)
# we can not match \n with the dot by passing the m modifier as than
- # the title and description are not seperated
+ # the title and description are not separated
/\Aissue\s+(new|create)\s+(?<title>[^\n]*)\n*(?<description>(.|\n)*)/.match(text)
end
diff --git a/lib/gitlab/slash_commands/issue_search.rb b/lib/gitlab/slash_commands/issue_search.rb
index ee78f0f832e..0a705de4484 100644
--- a/lib/gitlab/slash_commands/issue_search.rb
+++ b/lib/gitlab/slash_commands/issue_search.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
class IssueSearch < IssueCommand
diff --git a/lib/gitlab/slash_commands/issue_show.rb b/lib/gitlab/slash_commands/issue_show.rb
index ffa5184e5cb..5f5fa32ff20 100644
--- a/lib/gitlab/slash_commands/issue_show.rb
+++ b/lib/gitlab/slash_commands/issue_show.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
class IssueShow < IssueCommand
diff --git a/lib/gitlab/slash_commands/presenters/access.rb b/lib/gitlab/slash_commands/presenters/access.rb
index 81f7cd3ffe8..fa163cb098e 100644
--- a/lib/gitlab/slash_commands/presenters/access.rb
+++ b/lib/gitlab/slash_commands/presenters/access.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
module Presenters
diff --git a/lib/gitlab/slash_commands/presenters/base.rb b/lib/gitlab/slash_commands/presenters/base.rb
index e13808a2720..73814aa180f 100644
--- a/lib/gitlab/slash_commands/presenters/base.rb
+++ b/lib/gitlab/slash_commands/presenters/base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
module Presenters
diff --git a/lib/gitlab/slash_commands/presenters/deploy.rb b/lib/gitlab/slash_commands/presenters/deploy.rb
index ebae0f57f9b..7d852eb1f9a 100644
--- a/lib/gitlab/slash_commands/presenters/deploy.rb
+++ b/lib/gitlab/slash_commands/presenters/deploy.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
module Presenters
diff --git a/lib/gitlab/slash_commands/presenters/help.rb b/lib/gitlab/slash_commands/presenters/help.rb
index ab855319077..480d7aa6a30 100644
--- a/lib/gitlab/slash_commands/presenters/help.rb
+++ b/lib/gitlab/slash_commands/presenters/help.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
module Presenters
diff --git a/lib/gitlab/slash_commands/presenters/issue_base.rb b/lib/gitlab/slash_commands/presenters/issue_base.rb
index 31c1e97efba..b6db103b82b 100644
--- a/lib/gitlab/slash_commands/presenters/issue_base.rb
+++ b/lib/gitlab/slash_commands/presenters/issue_base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
module Presenters
diff --git a/lib/gitlab/slash_commands/presenters/issue_move.rb b/lib/gitlab/slash_commands/presenters/issue_move.rb
index 03921729941..ca0644ede95 100644
--- a/lib/gitlab/slash_commands/presenters/issue_move.rb
+++ b/lib/gitlab/slash_commands/presenters/issue_move.rb
@@ -1,4 +1,6 @@
# coding: utf-8
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
module Presenters
diff --git a/lib/gitlab/slash_commands/presenters/issue_new.rb b/lib/gitlab/slash_commands/presenters/issue_new.rb
index 5964bfe9960..ac78745ae70 100644
--- a/lib/gitlab/slash_commands/presenters/issue_new.rb
+++ b/lib/gitlab/slash_commands/presenters/issue_new.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
module Presenters
diff --git a/lib/gitlab/slash_commands/presenters/issue_search.rb b/lib/gitlab/slash_commands/presenters/issue_search.rb
index 4e27d668685..0d497efec0e 100644
--- a/lib/gitlab/slash_commands/presenters/issue_search.rb
+++ b/lib/gitlab/slash_commands/presenters/issue_search.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
module Presenters
diff --git a/lib/gitlab/slash_commands/presenters/issue_show.rb b/lib/gitlab/slash_commands/presenters/issue_show.rb
index 562f15f403c..5a2c79a928e 100644
--- a/lib/gitlab/slash_commands/presenters/issue_show.rb
+++ b/lib/gitlab/slash_commands/presenters/issue_show.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SlashCommands
module Presenters
@@ -38,10 +40,10 @@ module Gitlab
end
def text
- message = "**#{status_text(@resource)}**"
+ message = ["**#{status_text(@resource)}**"]
if @resource.upvotes.zero? && @resource.downvotes.zero? && @resource.user_notes_count.zero?
- return message
+ return message.join
end
message << " · "
@@ -49,7 +51,7 @@ module Gitlab
message << ":-1: #{@resource.downvotes} " unless @resource.downvotes.zero?
message << ":speech_balloon: #{@resource.user_notes_count}" unless @resource.user_notes_count.zero?
- message
+ message.join
end
def pretext
diff --git a/lib/gitlab/slash_commands/result.rb b/lib/gitlab/slash_commands/result.rb
index 3669dedf0fe..607c9c8dec1 100644
--- a/lib/gitlab/slash_commands/result.rb
+++ b/lib/gitlab/slash_commands/result.rb
@@ -1,4 +1,7 @@
-module Gitlab # rubocop:disable Naming/FileName
+# rubocop:disable Naming/FileName
+# frozen_string_literal: true
+
+module Gitlab
module SlashCommands
Result = Struct.new(:type, :message)
end
diff --git a/lib/gitlab/snippet_search_results.rb b/lib/gitlab/snippet_search_results.rb
index 95e37dfbdab..e360b552f89 100644
--- a/lib/gitlab/snippet_search_results.rb
+++ b/lib/gitlab/snippet_search_results.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class SnippetSearchResults < SearchResults
include SnippetsHelper
diff --git a/lib/gitlab/sql/cte.rb b/lib/gitlab/sql/cte.rb
index f357829ba3f..7817a2a1ce2 100644
--- a/lib/gitlab/sql/cte.rb
+++ b/lib/gitlab/sql/cte.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SQL
# Class for easily building CTE statements.
diff --git a/lib/gitlab/sql/glob.rb b/lib/gitlab/sql/glob.rb
index 5e89e12b2b1..f3421bd95d2 100644
--- a/lib/gitlab/sql/glob.rb
+++ b/lib/gitlab/sql/glob.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SQL
module Glob
diff --git a/lib/gitlab/sql/pattern.rb b/lib/gitlab/sql/pattern.rb
index 53744bad1f4..92388262035 100644
--- a/lib/gitlab/sql/pattern.rb
+++ b/lib/gitlab/sql/pattern.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SQL
module Pattern
diff --git a/lib/gitlab/sql/recursive_cte.rb b/lib/gitlab/sql/recursive_cte.rb
index 16ec002f139..ec1f00a3a91 100644
--- a/lib/gitlab/sql/recursive_cte.rb
+++ b/lib/gitlab/sql/recursive_cte.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SQL
# Class for easily building recursive CTE statements.
diff --git a/lib/gitlab/sql/union.rb b/lib/gitlab/sql/union.rb
index c99b262f1ca..d24d5116167 100644
--- a/lib/gitlab/sql/union.rb
+++ b/lib/gitlab/sql/union.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module SQL
# Class for building SQL UNION statements.
diff --git a/lib/gitlab/ssh_public_key.rb b/lib/gitlab/ssh_public_key.rb
index 6f63ea91ae8..47571239b5c 100644
--- a/lib/gitlab/ssh_public_key.rb
+++ b/lib/gitlab/ssh_public_key.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class SSHPublicKey
Technology = Struct.new(:name, :key_class, :supported_sizes)
@@ -26,7 +28,7 @@ module Gitlab
return key_content if parts.empty?
- parts.each_with_object("#{ssh_type} ").with_index do |(part, content), index|
+ parts.each_with_object(+"#{ssh_type} ").with_index do |(part, content), index|
content << part
if Gitlab::SSHPublicKey.new(content).valid?
diff --git a/lib/gitlab/storage_check.rb b/lib/gitlab/storage_check.rb
deleted file mode 100644
index fe81513c9ec..00000000000
--- a/lib/gitlab/storage_check.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-require_relative 'storage_check/cli'
-require_relative 'storage_check/gitlab_caller'
-require_relative 'storage_check/option_parser'
-require_relative 'storage_check/response'
-
-module Gitlab
- module StorageCheck
- ENDPOINT = '/-/storage_check'.freeze
- Options = Struct.new(:target, :token, :interval, :dryrun)
- end
-end
diff --git a/lib/gitlab/storage_check/cli.rb b/lib/gitlab/storage_check/cli.rb
deleted file mode 100644
index 9b64c8e033a..00000000000
--- a/lib/gitlab/storage_check/cli.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-module Gitlab
- module StorageCheck
- class CLI
- def self.start!(args)
- runner = new(Gitlab::StorageCheck::OptionParser.parse!(args))
- runner.start_loop
- end
-
- attr_reader :logger, :options
-
- def initialize(options)
- @options = options
- @logger = Logger.new(STDOUT)
- end
-
- def start_loop
- logger.info "Checking #{options.target} every #{options.interval} seconds"
-
- if options.dryrun
- logger.info "Dryrun, exiting..."
- return
- end
-
- begin
- loop do
- response = GitlabCaller.new(options).call!
- log_response(response)
- update_settings(response)
-
- sleep options.interval
- end
- rescue Interrupt
- logger.info "Ending storage-check"
- end
- end
-
- def update_settings(response)
- previous_interval = options.interval
-
- if response.valid?
- options.interval = response.check_interval || previous_interval
- end
-
- if previous_interval != options.interval
- logger.info "Interval changed: #{options.interval} seconds"
- end
- end
-
- def log_response(response)
- unless response.valid?
- return logger.error("Invalid response checking nfs storage: #{response.http_response.inspect}")
- end
-
- if response.responsive_shards.any?
- logger.debug("Responsive shards: #{response.responsive_shards.join(', ')}")
- end
-
- warnings = []
- if response.skipped_shards.any?
- warnings << "Skipped shards: #{response.skipped_shards.join(', ')}"
- end
-
- if response.failing_shards.any?
- warnings << "Failing shards: #{response.failing_shards.join(', ')}"
- end
-
- logger.warn(warnings.join(' - ')) if warnings.any?
- end
- end
- end
-end
diff --git a/lib/gitlab/storage_check/gitlab_caller.rb b/lib/gitlab/storage_check/gitlab_caller.rb
deleted file mode 100644
index 44952b68844..00000000000
--- a/lib/gitlab/storage_check/gitlab_caller.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-require 'excon'
-
-module Gitlab
- module StorageCheck
- class GitlabCaller
- def initialize(options)
- @options = options
- end
-
- def call!
- Gitlab::StorageCheck::Response.new(get_response)
- rescue Errno::ECONNREFUSED, Excon::Error
- # Server not ready, treated as invalid response.
- Gitlab::StorageCheck::Response.new(nil)
- end
-
- def get_response
- scheme, *other_parts = URI.split(@options.target)
- socket_path = if scheme == 'unix'
- other_parts.compact.join
- end
-
- connection = Excon.new(@options.target, socket: socket_path)
- connection.post(path: Gitlab::StorageCheck::ENDPOINT,
- headers: headers)
- end
-
- def headers
- @headers ||= begin
- headers = {}
- headers['Content-Type'] = headers['Accept'] = 'application/json'
- headers['TOKEN'] = @options.token if @options.token
-
- headers
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/storage_check/option_parser.rb b/lib/gitlab/storage_check/option_parser.rb
deleted file mode 100644
index 66ed7906f97..00000000000
--- a/lib/gitlab/storage_check/option_parser.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-module Gitlab
- module StorageCheck
- class OptionParser
- def self.parse!(args)
- # Start out with some defaults
- options = Gitlab::StorageCheck::Options.new(nil, nil, 1, false)
-
- parser = ::OptionParser.new do |opts|
- opts.banner = "Usage: bin/storage_check [options]"
-
- opts.on('-t=string', '--target string', 'URL or socket to trigger storage check') do |value|
- options.target = value
- end
-
- opts.on('-T=string', '--token string', 'Health token to use') { |value| options.token = value }
-
- opts.on('-i=n', '--interval n', ::OptionParser::DecimalInteger, 'Seconds between checks') do |value|
- options.interval = value
- end
-
- opts.on('-d', '--dryrun', "Output what will be performed, but don't start the process") do |value|
- options.dryrun = value
- end
- end
- parser.parse!(args)
-
- unless options.target
- raise ::OptionParser::InvalidArgument.new('Provide a URI to provide checks')
- end
-
- if URI.parse(options.target).scheme.nil?
- raise ::OptionParser::InvalidArgument.new('Add the scheme to the target, `unix://`, `https://` or `http://` are supported')
- end
-
- options
- end
- end
- end
-end
diff --git a/lib/gitlab/storage_check/response.rb b/lib/gitlab/storage_check/response.rb
deleted file mode 100644
index 326ab236e3e..00000000000
--- a/lib/gitlab/storage_check/response.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-require 'json'
-
-module Gitlab
- module StorageCheck
- class Response
- attr_reader :http_response
-
- def initialize(http_response)
- @http_response = http_response
- end
-
- def valid?
- @http_response && (200...299).cover?(@http_response.status) &&
- @http_response.headers['Content-Type'].include?('application/json') &&
- parsed_response
- end
-
- def check_interval
- return nil unless parsed_response
-
- parsed_response['check_interval']
- end
-
- def responsive_shards
- divided_results[:responsive_shards]
- end
-
- def skipped_shards
- divided_results[:skipped_shards]
- end
-
- def failing_shards
- divided_results[:failing_shards]
- end
-
- private
-
- def results
- return [] unless parsed_response
-
- parsed_response['results']
- end
-
- def divided_results
- return @divided_results if @divided_results
-
- @divided_results = {}
- @divided_results[:responsive_shards] = []
- @divided_results[:skipped_shards] = []
- @divided_results[:failing_shards] = []
-
- results.each do |info|
- name = info['storage']
-
- case info['success']
- when true
- @divided_results[:responsive_shards] << name
- when false
- @divided_results[:failing_shards] << name
- else
- @divided_results[:skipped_shards] << name
- end
- end
-
- @divided_results
- end
-
- def parsed_response
- return @parsed_response if defined?(@parsed_response)
-
- @parsed_response = JSON.parse(@http_response.body)
- rescue JSON::JSONError
- @parsed_response = nil
- end
- end
- end
-end
diff --git a/lib/gitlab/string_placeholder_replacer.rb b/lib/gitlab/string_placeholder_replacer.rb
index 9a2219b7d77..62621255a53 100644
--- a/lib/gitlab/string_placeholder_replacer.rb
+++ b/lib/gitlab/string_placeholder_replacer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class StringPlaceholderReplacer
# This method accepts the following paras
diff --git a/lib/gitlab/string_range_marker.rb b/lib/gitlab/string_range_marker.rb
index c6ad997a4d4..780fe4c7725 100644
--- a/lib/gitlab/string_range_marker.rb
+++ b/lib/gitlab/string_range_marker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class StringRangeMarker
attr_accessor :raw_line, :rich_line, :html_escaped
diff --git a/lib/gitlab/string_regex_marker.rb b/lib/gitlab/string_regex_marker.rb
index 1c87c56c45e..f1982ff914c 100644
--- a/lib/gitlab/string_regex_marker.rb
+++ b/lib/gitlab/string_regex_marker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class StringRegexMarker < StringRangeMarker
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/lib/gitlab/task_helpers.rb b/lib/gitlab/task_helpers.rb
index 922418966e9..224bb648d8f 100644
--- a/lib/gitlab/task_helpers.rb
+++ b/lib/gitlab/task_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'rainbow/ext/string'
require 'gitlab/utils/strong_memoize'
@@ -39,7 +41,7 @@ module Gitlab
File.read('/etc/os-release').match(/PRETTY_NAME=\"(.+)\"/)[1]
end
- os_name.try(:squish!)
+ os_name.try(:squish)
end
# Prompt the user to input something
diff --git a/lib/gitlab/tcp_checker.rb b/lib/gitlab/tcp_checker.rb
index 6e24e46d0ea..f37a044b607 100644
--- a/lib/gitlab/tcp_checker.rb
+++ b/lib/gitlab/tcp_checker.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class TcpChecker
attr_reader :remote_host, :remote_port, :local_host, :local_port, :error
diff --git a/lib/gitlab/template/base_template.rb b/lib/gitlab/template/base_template.rb
index 3770f3f250b..0b4cc571dc0 100644
--- a/lib/gitlab/template/base_template.rb
+++ b/lib/gitlab/template/base_template.rb
@@ -1,7 +1,9 @@
+# frozen_string_literal: true
+
module Gitlab
module Template
class BaseTemplate
- attr_reader :category
+ attr_accessor :category
def initialize(path, project = nil, category: nil)
@path = path
@@ -12,14 +14,21 @@ module Gitlab
def name
File.basename(@path, self.class.extension)
end
- alias_method :id, :name
+ alias_method :key, :name
def content
@finder.read(@path)
end
+ # Present for compatibility with license templates, which can replace text
+ # like `[fullname]` with a user-specified string. This is a no-op for
+ # other templates
+ def resolve!(_placeholders = {})
+ self
+ end
+
def to_json
- { name: name, content: content }
+ { key: key, name: name, content: content }
end
def <=>(other)
diff --git a/lib/gitlab/template/dockerfile_template.rb b/lib/gitlab/template/dockerfile_template.rb
index 20b054b0bd8..3b516bb862a 100644
--- a/lib/gitlab/template/dockerfile_template.rb
+++ b/lib/gitlab/template/dockerfile_template.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Template
class DockerfileTemplate < BaseTemplate
diff --git a/lib/gitlab/template/finders/base_template_finder.rb b/lib/gitlab/template/finders/base_template_finder.rb
index a5105439b12..93c229af143 100644
--- a/lib/gitlab/template/finders/base_template_finder.rb
+++ b/lib/gitlab/template/finders/base_template_finder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Template
module Finders
diff --git a/lib/gitlab/template/finders/global_template_finder.rb b/lib/gitlab/template/finders/global_template_finder.rb
index b08d9a99e99..76bb9eb611e 100644
--- a/lib/gitlab/template/finders/global_template_finder.rb
+++ b/lib/gitlab/template/finders/global_template_finder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Searches and reads file present on GitLab installation directory
module Gitlab
module Template
@@ -21,7 +23,7 @@ module Gitlab
end
def list_files_for(dir)
- dir << '/' unless dir.end_with?('/')
+ dir = "#{dir}/" unless dir.end_with?('/')
Dir.glob(File.join(dir, "*#{@extension}")).select { |f| f =~ self.class.filter_regex(@extension) }
end
diff --git a/lib/gitlab/template/finders/repo_template_finder.rb b/lib/gitlab/template/finders/repo_template_finder.rb
index 9140ace879f..b92cefefb8f 100644
--- a/lib/gitlab/template/finders/repo_template_finder.rb
+++ b/lib/gitlab/template/finders/repo_template_finder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Searches and reads files present on each GitLab project repository
module Gitlab
module Template
@@ -33,7 +35,7 @@ module Gitlab
def list_files_for(dir)
return [] unless @commit
- dir << '/' unless dir.end_with?('/')
+ dir = "#{dir}/" unless dir.end_with?('/')
entries = @repository.tree(:head, dir).entries
diff --git a/lib/gitlab/template/gitignore_template.rb b/lib/gitlab/template/gitignore_template.rb
index 8d2a9d2305c..72a1b7460c2 100644
--- a/lib/gitlab/template/gitignore_template.rb
+++ b/lib/gitlab/template/gitignore_template.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Template
class GitignoreTemplate < BaseTemplate
diff --git a/lib/gitlab/template/gitlab_ci_yml_template.rb b/lib/gitlab/template/gitlab_ci_yml_template.rb
index fd040148a1e..fbefb5f7f0e 100644
--- a/lib/gitlab/template/gitlab_ci_yml_template.rb
+++ b/lib/gitlab/template/gitlab_ci_yml_template.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Template
class GitlabCiYmlTemplate < BaseTemplate
@@ -20,7 +22,7 @@ module Gitlab
end
def base_dir
- Rails.root.join('vendor/gitlab-ci-yml')
+ Rails.root.join('lib/gitlab/ci/templates')
end
def finder(project = nil)
diff --git a/lib/gitlab/template/issue_template.rb b/lib/gitlab/template/issue_template.rb
index c6fa8d3eafc..01b191733d4 100644
--- a/lib/gitlab/template/issue_template.rb
+++ b/lib/gitlab/template/issue_template.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Template
class IssueTemplate < BaseTemplate
diff --git a/lib/gitlab/template/merge_request_template.rb b/lib/gitlab/template/merge_request_template.rb
index f826c02f3b5..357b31cd82e 100644
--- a/lib/gitlab/template/merge_request_template.rb
+++ b/lib/gitlab/template/merge_request_template.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Template
class MergeRequestTemplate < BaseTemplate
diff --git a/lib/gitlab/template_helper.rb b/lib/gitlab/template_helper.rb
index fc498dde723..b0e01697a66 100644
--- a/lib/gitlab/template_helper.rb
+++ b/lib/gitlab/template_helper.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module TemplateHelper
def prepare_template_environment(file)
diff --git a/lib/gitlab/temporarily_allow.rb b/lib/gitlab/temporarily_allow.rb
index 880e55f71df..000f8ca699d 100644
--- a/lib/gitlab/temporarily_allow.rb
+++ b/lib/gitlab/temporarily_allow.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module TemporarilyAllow
TEMPORARILY_ALLOW_MUTEX = Mutex.new
@@ -10,7 +12,7 @@ module Gitlab
end
def temporarily_allowed?(key)
- if RequestStore.active?
+ if Gitlab::SafeRequestStore.active?
temporarily_allow_request_store[key] > 0
else
TEMPORARILY_ALLOW_MUTEX.synchronize do
@@ -26,11 +28,11 @@ module Gitlab
end
def temporarily_allow_request_store
- RequestStore[:temporarily_allow] ||= Hash.new(0)
+ Gitlab::SafeRequestStore[:temporarily_allow] ||= Hash.new(0)
end
def temporarily_allow_add(key, value)
- if RequestStore.active?
+ if Gitlab::SafeRequestStore.active?
temporarily_allow_request_store[key] += value
else
TEMPORARILY_ALLOW_MUTEX.synchronize do
diff --git a/lib/gitlab/testing/request_blocker_middleware.rb b/lib/gitlab/testing/request_blocker_middleware.rb
index 53333b9b06b..513cbe839ba 100644
--- a/lib/gitlab/testing/request_blocker_middleware.rb
+++ b/lib/gitlab/testing/request_blocker_middleware.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# rubocop:disable Style/ClassVars
# This is inspired by http://www.salsify.com/blog/engineering/tearing-capybara-ajax-tests
diff --git a/lib/gitlab/testing/request_inspector_middleware.rb b/lib/gitlab/testing/request_inspector_middleware.rb
index e387667480d..36cdfebcc28 100644
--- a/lib/gitlab/testing/request_inspector_middleware.rb
+++ b/lib/gitlab/testing/request_inspector_middleware.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# rubocop:disable Style/ClassVars
module Gitlab
@@ -35,11 +37,15 @@ module Gitlab
request_headers = env_http_headers(env)
status, headers, body = @app.call(env)
+ full_body = +''
+ body.each { |b| full_body << b }
+
request = OpenStruct.new(
url: url,
status_code: status,
request_headers: request_headers,
- response_headers: headers
+ response_headers: headers,
+ body: full_body
)
log_request request
diff --git a/lib/gitlab/themes.rb b/lib/gitlab/themes.rb
index 694b01b272c..63860b9cb26 100644
--- a/lib/gitlab/themes.rb
+++ b/lib/gitlab/themes.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
# Module containing GitLab's application theme definitions and helper methods
# for accessing them.
diff --git a/lib/gitlab/time_tracking_formatter.rb b/lib/gitlab/time_tracking_formatter.rb
index d615c24149a..cc206010e74 100644
--- a/lib/gitlab/time_tracking_formatter.rb
+++ b/lib/gitlab/time_tracking_formatter.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module TimeTrackingFormatter
extend self
diff --git a/lib/gitlab/timeless.rb b/lib/gitlab/timeless.rb
index 76a1808c8ac..4f974c98c71 100644
--- a/lib/gitlab/timeless.rb
+++ b/lib/gitlab/timeless.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Timeless
def self.timeless(model, &block)
diff --git a/lib/gitlab/tree_summary.rb b/lib/gitlab/tree_summary.rb
index b05d408b1c0..453d78e2f7b 100644
--- a/lib/gitlab/tree_summary.rb
+++ b/lib/gitlab/tree_summary.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class TreeSummary
include ::Gitlab::Utils::StrongMemoize
@@ -73,25 +75,29 @@ module Gitlab
end
def fill_last_commits!(entries)
- # n+1: https://gitlab.com/gitlab-org/gitlab-ce/issues/37433
- Gitlab::GitalyClient.allow_n_plus_1_calls do
- entries.each do |entry|
- raw_commit = repository.last_commit_for_path(commit.id, entry_path(entry))
+ # Ensure the path is in "path/" format
+ ensured_path =
+ if path
+ File.join(*[path, ""])
+ end
+
+ commits_hsh = repository.list_last_commits_for_tree(commit.id, ensured_path, offset: offset, limit: limit)
- if raw_commit
- commit = resolve_commit(raw_commit)
+ entries.each do |entry|
+ path_key = entry_path(entry)
+ commit = cache_commit(commits_hsh[path_key])
- entry[:commit] = commit
- entry[:commit_path] = commit_path(commit)
- end
+ if commit
+ entry[:commit] = commit
+ entry[:commit_path] = commit_path(commit)
end
end
end
- def resolve_commit(raw_commit)
- return nil unless raw_commit.present?
+ def cache_commit(commit)
+ return nil unless commit.present?
- resolved_commits[raw_commit.id] ||= ::Commit.new(raw_commit, project)
+ resolved_commits[commit.id] ||= commit
end
def commit_path(commit)
diff --git a/lib/gitlab/untrusted_regexp.rb b/lib/gitlab/untrusted_regexp.rb
index dc2d91dfa23..ba1137313d8 100644
--- a/lib/gitlab/untrusted_regexp.rb
+++ b/lib/gitlab/untrusted_regexp.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
# An untrusted regular expression is any regexp containing patterns sourced
# from user input.
diff --git a/lib/gitlab/update_path_error.rb b/lib/gitlab/update_path_error.rb
index 8947ecfb92e..bc066bf4143 100644
--- a/lib/gitlab/update_path_error.rb
+++ b/lib/gitlab/update_path_error.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
UpdatePathError = Class.new(StandardError)
end
diff --git a/lib/gitlab/upgrader.rb b/lib/gitlab/upgrader.rb
index 024be6aca44..ccab0e4dd73 100644
--- a/lib/gitlab/upgrader.rb
+++ b/lib/gitlab/upgrader.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class Upgrader
def execute
diff --git a/lib/gitlab/uploads_transfer.rb b/lib/gitlab/uploads_transfer.rb
index 7d7400bdabf..e0e7084e27e 100644
--- a/lib/gitlab/uploads_transfer.rb
+++ b/lib/gitlab/uploads_transfer.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class UploadsTransfer < ProjectTransfer
def root_dir
diff --git a/lib/gitlab/url_blocker.rb b/lib/gitlab/url_blocker.rb
index 3b483f27e70..b8040f73cee 100644
--- a/lib/gitlab/url_blocker.rb
+++ b/lib/gitlab/url_blocker.rb
@@ -1,4 +1,7 @@
+# frozen_string_literal: true
+
require 'resolv'
+require 'ipaddress'
module Gitlab
class UrlBlocker
@@ -8,11 +11,8 @@ module Gitlab
def validate!(url, allow_localhost: false, allow_local_network: true, enforce_user: false, ports: [], protocols: [])
return true if url.nil?
- begin
- uri = Addressable::URI.parse(url)
- rescue Addressable::URI::InvalidURIError
- raise BlockedUrlError, "URI is invalid"
- end
+ # Param url can be a string, URI or Addressable::URI
+ uri = parse_url(url)
# Allow imports from the GitLab instance itself but only from the configured ports
return true if internal?(uri)
@@ -24,12 +24,15 @@ module Gitlab
validate_hostname!(uri.hostname)
begin
- addrs_info = Addrinfo.getaddrinfo(uri.hostname, port, nil, :STREAM)
+ addrs_info = Addrinfo.getaddrinfo(uri.hostname, port, nil, :STREAM).map do |addr|
+ addr.ipv6_v4mapped? ? addr.ipv6_to_ipv4 : addr
+ end
rescue SocketError
return true
end
validate_localhost!(addrs_info) unless allow_localhost
+ validate_loopback!(addrs_info) unless allow_localhost
validate_local_network!(addrs_info) unless allow_local_network
validate_link_local!(addrs_info) unless allow_local_network
@@ -46,6 +49,18 @@ module Gitlab
private
+ def parse_url(url)
+ raise Addressable::URI::InvalidURIError if multiline?(url)
+
+ Addressable::URI.parse(url)
+ rescue Addressable::URI::InvalidURIError, URI::InvalidURIError
+ raise BlockedUrlError, 'URI is invalid'
+ end
+
+ def multiline?(url)
+ CGI.unescape(url.to_s) =~ /\n|\r/
+ end
+
def validate_port!(port, ports)
return if port.blank?
# Only ports under 1024 are restricted
@@ -70,13 +85,14 @@ module Gitlab
def validate_hostname!(value)
return if value.blank?
+ return if IPAddress.valid?(value)
return if value =~ /\A\p{Alnum}/
- raise BlockedUrlError, "Hostname needs to start with an alphanumeric character"
+ raise BlockedUrlError, "Hostname or IP address invalid"
end
def validate_localhost!(addrs_info)
- local_ips = ["127.0.0.1", "::1", "0.0.0.0"]
+ local_ips = ["::", "0.0.0.0"]
local_ips.concat(Socket.ip_address_list.map(&:ip_address))
return if (local_ips & addrs_info.map(&:ip_address)).empty?
@@ -84,8 +100,14 @@ module Gitlab
raise BlockedUrlError, "Requests to localhost are not allowed"
end
+ def validate_loopback!(addrs_info)
+ return unless addrs_info.any? { |addr| addr.ipv4_loopback? || addr.ipv6_loopback? }
+
+ raise BlockedUrlError, "Requests to loopback addresses are not allowed"
+ end
+
def validate_local_network!(addrs_info)
- return unless addrs_info.any? { |addr| addr.ipv4_private? || addr.ipv6_sitelocal? }
+ return unless addrs_info.any? { |addr| addr.ipv4_private? || addr.ipv6_sitelocal? || addr.ipv6_unique_local? }
raise BlockedUrlError, "Requests to the local network are not allowed"
end
@@ -102,12 +124,14 @@ module Gitlab
end
def internal_web?(uri)
- uri.hostname == config.gitlab.host &&
+ uri.scheme == config.gitlab.protocol &&
+ uri.hostname == config.gitlab.host &&
(uri.port.blank? || uri.port == config.gitlab.port)
end
def internal_shell?(uri)
- uri.hostname == config.gitlab_shell.ssh_host &&
+ uri.scheme == 'ssh' &&
+ uri.hostname == config.gitlab_shell.ssh_host &&
(uri.port.blank? || uri.port == config.gitlab_shell.ssh_port)
end
diff --git a/lib/gitlab/url_builder.rb b/lib/gitlab/url_builder.rb
index e64033b0dba..f86d599e4cb 100644
--- a/lib/gitlab/url_builder.rb
+++ b/lib/gitlab/url_builder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class UrlBuilder
include Gitlab::Routing
diff --git a/lib/gitlab/url_sanitizer.rb b/lib/gitlab/url_sanitizer.rb
index 308a95d2f09..035268bc4f2 100644
--- a/lib/gitlab/url_sanitizer.rb
+++ b/lib/gitlab/url_sanitizer.rb
@@ -1,9 +1,11 @@
+# frozen_string_literal: true
+
module Gitlab
class UrlSanitizer
ALLOWED_SCHEMES = %w[http https ssh git].freeze
def self.sanitize(content)
- regexp = URI::Parser.new.make_regexp(ALLOWED_SCHEMES)
+ regexp = URI::DEFAULT_PARSER.make_regexp(ALLOWED_SCHEMES)
content.gsub(regexp) { |url| new(url).masked_url }
rescue Addressable::URI::InvalidURIError
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index f7d8ee571cd..9bceec749fc 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class UsageData
class << self
@@ -10,6 +12,7 @@ module Gitlab
.merge(features_usage_data)
.merge(components_usage_data)
.merge(cycle_analytics_usage_data)
+ .merge(usage_counters)
end
def to_json(force_refresh: false)
@@ -57,8 +60,10 @@ module Gitlab
clusters_platforms_user: count(::Clusters::Cluster.user_provided.enabled),
clusters_applications_helm: count(::Clusters::Applications::Helm.installed),
clusters_applications_ingress: count(::Clusters::Applications::Ingress.installed),
+ clusters_applications_cert_managers: count(::Clusters::Applications::CertManager.installed),
clusters_applications_prometheus: count(::Clusters::Applications::Prometheus.installed),
clusters_applications_runner: count(::Clusters::Applications::Runner.installed),
+ clusters_applications_knative: count(::Clusters::Applications::Knative.installed),
in_review_folder: count(::Environment.in_review_folder),
groups: count(Group),
issues: count(Issue),
@@ -106,6 +111,12 @@ module Gitlab
}
end
+ def usage_counters
+ {
+ web_ide_commits: Gitlab::WebIdeCommitsCounter.total_count
+ }
+ end
+
def components_usage_data
{
gitlab_pages: { enabled: Gitlab.config.pages.enabled, version: Gitlab::Pages::VERSION },
@@ -117,7 +128,6 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def services_usage
types = {
- JiraService: :projects_jira_active,
SlackService: :projects_slack_notifications_active,
SlackSlashCommandsService: :projects_slack_slash_active,
PrometheusService: :projects_prometheus_active
@@ -125,6 +135,23 @@ module Gitlab
results = count(Service.unscoped.where(type: types.keys, active: true).group(:type), fallback: Hash.new(-1))
types.each_with_object({}) { |(klass, key), response| response[key] = results[klass.to_s] || 0 }
+ .merge(jira_usage)
+ end
+
+ def jira_usage
+ # Jira Cloud does not support custom domains as per https://jira.atlassian.com/browse/CLOUD-6999
+ # so we can just check for subdomains of atlassian.net
+ services = count(
+ Service.unscoped.where(type: :JiraService, active: true)
+ .group("CASE WHEN properties LIKE '%.atlassian.net%' THEN 'cloud' ELSE 'server' END"),
+ fallback: Hash.new(-1)
+ )
+
+ {
+ projects_jira_server_active: services['server'] || 0,
+ projects_jira_cloud_active: services['cloud'] || 0,
+ projects_jira_active: services['server'] == -1 ? -1 : services.values.sum
+ }
end
def count(relation, fallback: -1)
diff --git a/lib/gitlab/user_access.rb b/lib/gitlab/user_access.rb
index 27560abfb96..980a8014409 100644
--- a/lib/gitlab/user_access.rb
+++ b/lib/gitlab/user_access.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class UserAccess
extend Gitlab::Cache::RequestCache
diff --git a/lib/gitlab/user_extractor.rb b/lib/gitlab/user_extractor.rb
index bd0d24e4369..874599688bb 100644
--- a/lib/gitlab/user_extractor.rb
+++ b/lib/gitlab/user_extractor.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
# This class extracts all users found in a piece of text by the username or the
-# email adress
+# email address
module Gitlab
class UserExtractor
@@ -14,13 +14,11 @@ module Gitlab
@text = text
end
- # rubocop: disable CodeReuse/ActiveRecord
def users
return User.none unless @text.present?
@users ||= User.from_union(union_relations)
end
- # rubocop: enable CodeReuse/ActiveRecord
def usernames
matches[:usernames]
diff --git a/lib/gitlab/utils.rb b/lib/gitlab/utils.rb
index aeda66763e8..9e59137a2c0 100644
--- a/lib/gitlab/utils.rb
+++ b/lib/gitlab/utils.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Utils
extend self
@@ -14,6 +16,11 @@ module Gitlab
str.force_encoding(Encoding::UTF_8)
end
+ # Append path to host, making sure there's one single / in between
+ def append_path(host, path)
+ "#{host.to_s.sub(%r{\/+$}, '')}/#{path.to_s.sub(%r{^\/+}, '')}"
+ end
+
# A slugified version of the string, suitable for inclusion in URLs and
# domain names. Rules:
#
diff --git a/lib/gitlab/utils/merge_hash.rb b/lib/gitlab/utils/merge_hash.rb
index 385141d44d0..fc237861e2f 100644
--- a/lib/gitlab/utils/merge_hash.rb
+++ b/lib/gitlab/utils/merge_hash.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Utils
module MergeHash
diff --git a/lib/gitlab/utils/override.rb b/lib/gitlab/utils/override.rb
index d00921e6cdc..c412961ea3f 100644
--- a/lib/gitlab/utils/override.rb
+++ b/lib/gitlab/utils/override.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Utils
module Override
diff --git a/lib/gitlab/utils/strong_memoize.rb b/lib/gitlab/utils/strong_memoize.rb
index fe091f4611b..aa1f8e2fdda 100644
--- a/lib/gitlab/utils/strong_memoize.rb
+++ b/lib/gitlab/utils/strong_memoize.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Utils
module StrongMemoize
diff --git a/lib/gitlab/verify/batch_verifier.rb b/lib/gitlab/verify/batch_verifier.rb
index 167ba1b3149..dbda19a4a66 100644
--- a/lib/gitlab/verify/batch_verifier.rb
+++ b/lib/gitlab/verify/batch_verifier.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Verify
class BatchVerifier
diff --git a/lib/gitlab/verify/job_artifacts.rb b/lib/gitlab/verify/job_artifacts.rb
index dbadfbde9e3..3b90c8b1a8e 100644
--- a/lib/gitlab/verify/job_artifacts.rb
+++ b/lib/gitlab/verify/job_artifacts.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Verify
class JobArtifacts < BatchVerifier
diff --git a/lib/gitlab/verify/lfs_objects.rb b/lib/gitlab/verify/lfs_objects.rb
index d3f58a73ac7..20dbb7addff 100644
--- a/lib/gitlab/verify/lfs_objects.rb
+++ b/lib/gitlab/verify/lfs_objects.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Verify
class LfsObjects < BatchVerifier
diff --git a/lib/gitlab/verify/rake_task.rb b/lib/gitlab/verify/rake_task.rb
index e190eaddc79..3efed311237 100644
--- a/lib/gitlab/verify/rake_task.rb
+++ b/lib/gitlab/verify/rake_task.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Verify
class RakeTask
diff --git a/lib/gitlab/verify/uploads.rb b/lib/gitlab/verify/uploads.rb
index 201fcc7de7f..875e8a120e9 100644
--- a/lib/gitlab/verify/uploads.rb
+++ b/lib/gitlab/verify/uploads.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module Verify
class Uploads < BatchVerifier
diff --git a/lib/gitlab/version_info.rb b/lib/gitlab/version_info.rb
index 6ee41e85cc9..aa6d5310161 100644
--- a/lib/gitlab/version_info.rb
+++ b/lib/gitlab/version_info.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class VersionInfo
include Comparable
diff --git a/lib/gitlab/view/presenter/base.rb b/lib/gitlab/view/presenter/base.rb
index 36162faa1eb..5e70afe730a 100644
--- a/lib/gitlab/view/presenter/base.rb
+++ b/lib/gitlab/view/presenter/base.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module View
module Presenter
@@ -11,8 +13,8 @@ module Gitlab
attr_reader :subject
- def can?(user, action, overriden_subject = nil)
- super(user, action, overriden_subject || subject)
+ def can?(user, action, overridden_subject = nil)
+ super(user, action, overridden_subject || subject)
end
# delegate all #can? queries to the subject
diff --git a/lib/gitlab/view/presenter/delegated.rb b/lib/gitlab/view/presenter/delegated.rb
index 387ff0f5d43..4a90ab758fb 100644
--- a/lib/gitlab/view/presenter/delegated.rb
+++ b/lib/gitlab/view/presenter/delegated.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module View
module Presenter
diff --git a/lib/gitlab/view/presenter/factory.rb b/lib/gitlab/view/presenter/factory.rb
index 570f0723e39..302697ff8eb 100644
--- a/lib/gitlab/view/presenter/factory.rb
+++ b/lib/gitlab/view/presenter/factory.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module View
module Presenter
diff --git a/lib/gitlab/view/presenter/simple.rb b/lib/gitlab/view/presenter/simple.rb
index b7653a0f3cc..31dcd1d4c4c 100644
--- a/lib/gitlab/view/presenter/simple.rb
+++ b/lib/gitlab/view/presenter/simple.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
module View
module Presenter
diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb
index 2612208a927..a3c7de87765 100644
--- a/lib/gitlab/visibility_level.rb
+++ b/lib/gitlab/visibility_level.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Gitlab::VisibilityLevel module
#
# Define allowed public modes that can be used for
diff --git a/lib/gitlab/web_ide_commits_counter.rb b/lib/gitlab/web_ide_commits_counter.rb
new file mode 100644
index 00000000000..1cd9b5295b9
--- /dev/null
+++ b/lib/gitlab/web_ide_commits_counter.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module WebIdeCommitsCounter
+ WEB_IDE_COMMITS_KEY = "WEB_IDE_COMMITS_COUNT".freeze
+
+ class << self
+ def increment
+ Gitlab::Redis::SharedState.with { |redis| redis.incr(WEB_IDE_COMMITS_KEY) }
+ end
+
+ def total_count
+ Gitlab::Redis::SharedState.with { |redis| redis.get(WEB_IDE_COMMITS_KEY).to_i }
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/webpack/dev_server_middleware.rb b/lib/gitlab/webpack/dev_server_middleware.rb
index 529f7d6a8d6..fda41da5a94 100644
--- a/lib/gitlab/webpack/dev_server_middleware.rb
+++ b/lib/gitlab/webpack/dev_server_middleware.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# This Rack middleware is intended to proxy the webpack assets directory to the
# webpack-dev-server. It is only intended for use in development.
diff --git a/lib/gitlab/webpack/manifest.rb b/lib/gitlab/webpack/manifest.rb
index 0c343e5bc1d..1d2aff5e5b4 100644
--- a/lib/gitlab/webpack/manifest.rb
+++ b/lib/gitlab/webpack/manifest.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'webpack/rails/manifest'
module Gitlab
diff --git a/lib/gitlab/wiki_file_finder.rb b/lib/gitlab/wiki_file_finder.rb
index f97278f05cd..a00cd65594c 100644
--- a/lib/gitlab/wiki_file_finder.rb
+++ b/lib/gitlab/wiki_file_finder.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Gitlab
class WikiFileFinder < FileFinder
attr_reader :repository
diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb
index 30a8c3578d8..e1f777e9cd1 100644
--- a/lib/gitlab/workhorse.rb
+++ b/lib/gitlab/workhorse.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'base64'
require 'json'
require 'securerandom'
@@ -63,7 +65,7 @@ module Gitlab
def send_git_archive(repository, ref:, format:, append_sha:)
format ||= 'tar.gz'
- format.downcase!
+ format = format.downcase
params = repository.archive_metadata(ref, Gitlab.config.gitlab.repository_downloads_path, format, append_sha: append_sha)
raise "Repository or ref not found" if params.empty?
diff --git a/lib/google_api/auth.rb b/lib/google_api/auth.rb
index 1aeaa387a49..56f056fd869 100644
--- a/lib/google_api/auth.rb
+++ b/lib/google_api/auth.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module GoogleApi
class Auth
attr_reader :access_token, :redirect_uri, :state
@@ -14,7 +16,7 @@ module GoogleApi
client.auth_code.authorize_url(
redirect_uri: redirect_uri,
scope: scope,
- state: state # This is used for arbitary redirection
+ state: state # This is used for arbitrary redirection
)
end
diff --git a/lib/google_api/cloud_platform/client.rb b/lib/google_api/cloud_platform/client.rb
index 77b6610286f..e74ff6a9129 100644
--- a/lib/google_api/cloud_platform/client.rb
+++ b/lib/google_api/cloud_platform/client.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'google/apis/compute_v1'
require 'google/apis/container_v1'
require 'google/apis/cloudbilling_v1'
diff --git a/lib/gt_one_coercion.rb b/lib/gt_one_coercion.rb
index ef2dc09767c..99be51bc8c6 100644
--- a/lib/gt_one_coercion.rb
+++ b/lib/gt_one_coercion.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
class GtOneCoercion < Virtus::Attribute
def coerce(value)
[1, value.to_i].max
diff --git a/lib/haml_lint/inline_javascript.rb b/lib/haml_lint/inline_javascript.rb
index adbed20f152..2e98227a05e 100644
--- a/lib/haml_lint/inline_javascript.rb
+++ b/lib/haml_lint/inline_javascript.rb
@@ -1,7 +1,10 @@
-unless Rails.env.production? # rubocop:disable Naming/FileName
- require 'haml_lint/haml_visitor'
- require 'haml_lint/linter'
- require 'haml_lint/linter_registry'
+# rubocop:disable Naming/FileName
+# frozen_string_literal: true
+
+unless Rails.env.production?
+ require_dependency 'haml_lint/haml_visitor'
+ require_dependency 'haml_lint/linter'
+ require_dependency 'haml_lint/linter_registry'
module HamlLint
class Linter::InlineJavaScript < Linter
diff --git a/lib/json_web_token/hmac_token.rb b/lib/json_web_token/hmac_token.rb
new file mode 100644
index 00000000000..ceb1b9c913f
--- /dev/null
+++ b/lib/json_web_token/hmac_token.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'jwt'
+
+module JSONWebToken
+ class HMACToken < Token
+ IAT_LEEWAY = 60
+ JWT_ALGORITHM = 'HS256'
+
+ def initialize(secret)
+ super()
+
+ @secret = secret
+ end
+
+ def self.decode(token, secret, leeway: IAT_LEEWAY, verify_iat: true)
+ JWT.decode(token, secret, true, leeway: leeway, verify_iat: verify_iat, algorithm: JWT_ALGORITHM)
+ end
+
+ def encoded
+ JWT.encode(payload, secret, JWT_ALGORITHM)
+ end
+
+ private
+
+ attr_reader :secret
+ end
+end
diff --git a/lib/json_web_token/rsa_token.rb b/lib/json_web_token/rsa_token.rb
index d6d6af7089c..160e1e506f1 100644
--- a/lib/json_web_token/rsa_token.rb
+++ b/lib/json_web_token/rsa_token.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module JSONWebToken
class RSAToken < Token
attr_reader :key_file
diff --git a/lib/json_web_token/token.rb b/lib/json_web_token/token.rb
index 5b67715b0b2..c59beef02c9 100644
--- a/lib/json_web_token/token.rb
+++ b/lib/json_web_token/token.rb
@@ -1,15 +1,22 @@
+# frozen_string_literal: true
+
+require 'securerandom'
+
module JSONWebToken
class Token
attr_accessor :issuer, :subject, :audience, :id
attr_accessor :issued_at, :not_before, :expire_time
+ DEFAULT_NOT_BEFORE_TIME = 5
+ DEFAULT_EXPIRE_TIME = 60
+
def initialize
@id = SecureRandom.uuid
@issued_at = Time.now
# we give a few seconds for time shift
- @not_before = issued_at - 5.seconds
+ @not_before = issued_at - DEFAULT_NOT_BEFORE_TIME
# default 60 seconds should be more than enough for this authentication token
- @expire_time = issued_at + 1.minute
+ @expire_time = issued_at + DEFAULT_EXPIRE_TIME
@custom_payload = {}
end
diff --git a/lib/mattermost/client.rb b/lib/mattermost/client.rb
index d80cd7d2a4e..293d0c563c5 100644
--- a/lib/mattermost/client.rb
+++ b/lib/mattermost/client.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Mattermost
ClientError = Class.new(Mattermost::Error)
diff --git a/lib/mattermost/command.rb b/lib/mattermost/command.rb
index 704813dfdf0..a02745486d6 100644
--- a/lib/mattermost/command.rb
+++ b/lib/mattermost/command.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Mattermost
class Command < Client
def create(params)
diff --git a/lib/mattermost/error.rb b/lib/mattermost/error.rb
index dee6deb7974..054bd5457bd 100644
--- a/lib/mattermost/error.rb
+++ b/lib/mattermost/error.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Mattermost
Error = Class.new(StandardError)
end
diff --git a/lib/mattermost/session.rb b/lib/mattermost/session.rb
index 2aa7a2f64d8..e2083848a8d 100644
--- a/lib/mattermost/session.rb
+++ b/lib/mattermost/session.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Mattermost
class NoSessionError < Mattermost::Error
def message
diff --git a/lib/mattermost/team.rb b/lib/mattermost/team.rb
index 95c2f6f9d6b..58120178f50 100644
--- a/lib/mattermost/team.rb
+++ b/lib/mattermost/team.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Mattermost
class Team < Client
# Returns all teams that the current user is a member of
diff --git a/lib/microsoft_teams/activity.rb b/lib/microsoft_teams/activity.rb
index d2c420efdaf..207e90d2638 100644
--- a/lib/microsoft_teams/activity.rb
+++ b/lib/microsoft_teams/activity.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module MicrosoftTeams
class Activity
def initialize(title:, subtitle:, text:, image:)
diff --git a/lib/microsoft_teams/notifier.rb b/lib/microsoft_teams/notifier.rb
index 226ee1373db..c7dec09ba6b 100644
--- a/lib/microsoft_teams/notifier.rb
+++ b/lib/microsoft_teams/notifier.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module MicrosoftTeams
class Notifier
def initialize(webhook)
diff --git a/lib/milestone_array.rb b/lib/milestone_array.rb
index 4ed8485b36a..461e73e9670 100644
--- a/lib/milestone_array.rb
+++ b/lib/milestone_array.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module MilestoneArray
class << self
def sort(array, sort_method)
diff --git a/lib/mysql_zero_date.rb b/lib/mysql_zero_date.rb
index 64634f789da..216560148fa 100644
--- a/lib/mysql_zero_date.rb
+++ b/lib/mysql_zero_date.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Disable NO_ZERO_DATE mode for mysql in rails 5.
# We use zero date as a default value
# (config/initializers/active_record_mysql_timestamp.rb), in
diff --git a/lib/object_storage/direct_upload.rb b/lib/object_storage/direct_upload.rb
index 97f56e10ccf..fd26663fef0 100644
--- a/lib/object_storage/direct_upload.rb
+++ b/lib/object_storage/direct_upload.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module ObjectStorage
#
# The DirectUpload c;ass generates a set of presigned URLs
diff --git a/lib/omni_auth/strategies/bitbucket.rb b/lib/omni_auth/strategies/bitbucket.rb
index ce1bdfe6ee4..6c914b4222a 100644
--- a/lib/omni_auth/strategies/bitbucket.rb
+++ b/lib/omni_auth/strategies/bitbucket.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'omniauth-oauth2'
module OmniAuth
diff --git a/lib/omni_auth/strategies/jwt.rb b/lib/omni_auth/strategies/jwt.rb
index ebdb5c7faf0..a792903fde7 100644
--- a/lib/omni_auth/strategies/jwt.rb
+++ b/lib/omni_auth/strategies/jwt.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'omniauth'
require 'jwt'
diff --git a/lib/peek/rblineprof/custom_controller_helpers.rb b/lib/peek/rblineprof/custom_controller_helpers.rb
index 9beb442bfa3..581cc6a37b4 100644
--- a/lib/peek/rblineprof/custom_controller_helpers.rb
+++ b/lib/peek/rblineprof/custom_controller_helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Peek
module Rblineprof
module CustomControllerHelpers
@@ -41,7 +43,7 @@ module Peek
]
end.sort_by{ |a,b,c,d,e,f| -f }
- output = "<div class='modal-dialog modal-xl'><div class='modal-content'>"
+ output = ["<div class='modal-dialog modal-xl'><div class='modal-content'>"]
output << "<div class='modal-header'>"
output << "<h4>Line profiling: #{human_description(params[:lineprofiler])}</h4>"
output << "<button class='close' type='button' data-dismiss='modal' aria-label='close'><span aria-hidden='true'>&times;</span></button>"
@@ -93,7 +95,7 @@ module Peek
output << "</div></div></div>"
- response.body += "<div class='modal' id='modal-peek-line-profile' tabindex=-1>#{output}</div>".html_safe
+ response.body += "<div class='modal' id='modal-peek-line-profile' tabindex=-1>#{output.join}</div>".html_safe
end
ret
diff --git a/lib/peek/views/gitaly.rb b/lib/peek/views/gitaly.rb
index ab35f7a2258..30f95a10024 100644
--- a/lib/peek/views/gitaly.rb
+++ b/lib/peek/views/gitaly.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Peek
module Views
class Gitaly < View
@@ -21,7 +23,6 @@ module Peek
def details
::Gitlab::GitalyClient.list_call_details
- .values
.sort { |a, b| b[:duration] <=> a[:duration] }
.map(&method(:format_call_details))
end
diff --git a/lib/peek/views/host.rb b/lib/peek/views/host.rb
index 43c8a35c7ea..b77355ea11b 100644
--- a/lib/peek/views/host.rb
+++ b/lib/peek/views/host.rb
@@ -1,8 +1,13 @@
+# frozen_string_literal: true
+
module Peek
module Views
class Host < View
def results
- { hostname: Gitlab::Environment.hostname }
+ {
+ hostname: Gitlab::Environment.hostname,
+ canary: Gitlab::Utils.to_boolean(ENV['CANARY'])
+ }
end
end
end
diff --git a/lib/quality/helm_client.rb b/lib/quality/helm_client.rb
new file mode 100644
index 00000000000..cf1f03b35b5
--- /dev/null
+++ b/lib/quality/helm_client.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+require 'time'
+require_relative '../gitlab/popen' unless defined?(Gitlab::Popen)
+
+module Quality
+ class HelmClient
+ CommandFailedError = Class.new(StandardError)
+
+ attr_reader :namespace
+
+ RELEASE_JSON_ATTRIBUTES = %w[Name Revision Updated Status Chart AppVersion Namespace].freeze
+
+ Release = Struct.new(:name, :revision, :last_update, :status, :chart, :app_version, :namespace) do
+ def revision
+ @revision ||= self[:revision].to_i
+ end
+
+ def last_update
+ @last_update ||= Time.parse(self[:last_update])
+ end
+ end
+
+ # A single page of data and the corresponding page number.
+ Page = Struct.new(:releases, :number)
+
+ def initialize(namespace:)
+ @namespace = namespace
+ end
+
+ def releases(args: [])
+ each_release(args)
+ end
+
+ def delete(release_name:)
+ run_command([
+ 'delete',
+ %(--tiller-namespace "#{namespace}"),
+ '--purge',
+ release_name
+ ])
+ end
+
+ private
+
+ def run_command(command)
+ final_command = ['helm', *command].join(' ')
+ puts "Running command: `#{final_command}`" # rubocop:disable Rails/Output
+
+ result = Gitlab::Popen.popen_with_detail([final_command])
+
+ if result.status.success?
+ result.stdout.chomp.freeze
+ else
+ raise CommandFailedError, "The `#{final_command}` command failed (status: #{result.status}) with the following error:\n#{result.stderr}"
+ end
+ end
+
+ def raw_releases(args = [])
+ command = [
+ 'list',
+ %(--namespace "#{namespace}"),
+ %(--tiller-namespace "#{namespace}" --output json),
+ *args
+ ]
+ json = JSON.parse(run_command(command))
+
+ releases = json['Releases'].map do |json_release|
+ Release.new(*json_release.values_at(*RELEASE_JSON_ATTRIBUTES))
+ end
+
+ [releases, json['Next']]
+ rescue JSON::ParserError => ex
+ puts "Ignoring this JSON parsing error: #{ex}" # rubocop:disable Rails/Output
+ [[], nil]
+ end
+
+ # Fetches data from Helm and yields a Page object for every page
+ # of data, without loading all of them into memory.
+ #
+ # method - The Octokit method to use for getting the data.
+ # args - Arguments to pass to the `helm list` command.
+ def each_releases_page(args, &block)
+ return to_enum(__method__, args) unless block_given?
+
+ page = 1
+ offset = ''
+
+ loop do
+ final_args = args.dup
+ final_args << "--offset #{offset}" unless offset.to_s.empty?
+ collection, offset = raw_releases(final_args)
+
+ yield Page.new(collection, page += 1)
+
+ break if offset.to_s.empty?
+ end
+ end
+
+ # Iterates over all of the releases.
+ #
+ # args - Any arguments to pass to the `helm list` command.
+ def each_release(args, &block)
+ return to_enum(__method__, args) unless block_given?
+
+ each_releases_page(args) do |page|
+ page.releases.each do |release|
+ yield release
+ end
+ end
+ end
+ end
+end
diff --git a/lib/quality/kubernetes_client.rb b/lib/quality/kubernetes_client.rb
new file mode 100644
index 00000000000..2ff9e811425
--- /dev/null
+++ b/lib/quality/kubernetes_client.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require_relative '../gitlab/popen' unless defined?(Gitlab::Popen)
+
+module Quality
+ class KubernetesClient
+ CommandFailedError = Class.new(StandardError)
+
+ attr_reader :namespace
+
+ def initialize(namespace:)
+ @namespace = namespace
+ end
+
+ def cleanup(release_name:)
+ command = [
+ %(--namespace "#{namespace}"),
+ 'delete',
+ 'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa',
+ '--now',
+ %(-l release="#{release_name}")
+ ]
+
+ run_command(command)
+ end
+
+ private
+
+ def run_command(command)
+ final_command = ['kubectl', *command].join(' ')
+ puts "Running command: `#{final_command}`" # rubocop:disable Rails/Output
+
+ result = Gitlab::Popen.popen_with_detail([final_command])
+
+ if result.status.success?
+ result.stdout.chomp.freeze
+ else
+ raise CommandFailedError, "The `#{final_command}` command failed (status: #{result.status}) with the following error:\n#{result.stderr}"
+ end
+ end
+ end
+end
diff --git a/lib/rails4_migration_version.rb b/lib/rails4_migration_version.rb
new file mode 100644
index 00000000000..ae48734dfad
--- /dev/null
+++ b/lib/rails4_migration_version.rb
@@ -0,0 +1,16 @@
+# rubocop:disable Naming/FileName
+# frozen_string_literal: true
+
+# When switching to rails 5, we added migration version to all migration
+# classes. This patch makes it possible to run versioned migrations
+# also with rails 4
+
+unless Gitlab.rails5?
+ module ActiveRecord
+ class Migration
+ def self.[](version)
+ Migration
+ end
+ end
+ end
+end
diff --git a/lib/rouge/formatters/html_gitlab.rb b/lib/rouge/formatters/html_gitlab.rb
index e877ab10248..e2a7d3ef5ba 100644
--- a/lib/rouge/formatters/html_gitlab.rb
+++ b/lib/rouge/formatters/html_gitlab.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module Rouge
module Formatters
class HTMLGitlab < Rouge::Formatters::HTML
diff --git a/lib/rouge/plugins/common_mark.rb b/lib/rouge/plugins/common_mark.rb
index 8f9de061124..d240df5a0e0 100644
--- a/lib/rouge/plugins/common_mark.rb
+++ b/lib/rouge/plugins/common_mark.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# A rouge plugin for CommonMark markdown engine.
# Used to highlight code generated by CommonMark.
diff --git a/lib/rspec_flaky/config.rb b/lib/rspec_flaky/config.rb
index 06e96f969f1..55c1d4747b4 100644
--- a/lib/rspec_flaky/config.rb
+++ b/lib/rspec_flaky/config.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module RspecFlaky
class Config
def self.generate_report?
diff --git a/lib/rspec_flaky/example.rb b/lib/rspec_flaky/example.rb
index b6e790cbbab..3c1b05257a0 100644
--- a/lib/rspec_flaky/example.rb
+++ b/lib/rspec_flaky/example.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module RspecFlaky
# This is a wrapper class for RSpec::Core::Example
class Example
diff --git a/lib/rspec_flaky/flaky_example.rb b/lib/rspec_flaky/flaky_example.rb
index 6be24014d89..da5dbf06bc9 100644
--- a/lib/rspec_flaky/flaky_example.rb
+++ b/lib/rspec_flaky/flaky_example.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module RspecFlaky
# This represents a flaky RSpec example and is mainly meant to be saved in a JSON file
class FlakyExample < OpenStruct
diff --git a/lib/rspec_flaky/flaky_examples_collection.rb b/lib/rspec_flaky/flaky_examples_collection.rb
index dea23c325be..290a51766e9 100644
--- a/lib/rspec_flaky/flaky_examples_collection.rb
+++ b/lib/rspec_flaky/flaky_examples_collection.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'active_support/hash_with_indifferent_access'
require_relative 'flaky_example'
diff --git a/lib/rspec_flaky/listener.rb b/lib/rspec_flaky/listener.rb
index 9cd0c38cb55..19cc0baa2d3 100644
--- a/lib/rspec_flaky/listener.rb
+++ b/lib/rspec_flaky/listener.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'json'
require_dependency 'rspec_flaky/config'
diff --git a/lib/rspec_flaky/report.rb b/lib/rspec_flaky/report.rb
index 1c362fdd20d..9a0fb88c424 100644
--- a/lib/rspec_flaky/report.rb
+++ b/lib/rspec_flaky/report.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'json'
require 'time'
diff --git a/lib/static_model.rb b/lib/static_model.rb
index 44673c2b5f6..86bf8d62f9a 100644
--- a/lib/static_model.rb
+++ b/lib/static_model.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Provides an ActiveRecord-like interface to a model whose data is not persisted to a database.
module StaticModel
extend ActiveSupport::Concern
diff --git a/lib/system_check.rb b/lib/system_check.rb
index 466c39904fa..7ffd7c03c5b 100644
--- a/lib/system_check.rb
+++ b/lib/system_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# Library to perform System Checks
#
# Every Check is implemented as its own class inherited from SystemCheck::BaseCheck
diff --git a/lib/system_check/app/active_users_check.rb b/lib/system_check/app/active_users_check.rb
index 1d72c8d6903..8446c2fc2c8 100644
--- a/lib/system_check/app/active_users_check.rb
+++ b/lib/system_check/app/active_users_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class ActiveUsersCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/database_config_exists_check.rb b/lib/system_check/app/database_config_exists_check.rb
index d1fae192350..1769145ed63 100644
--- a/lib/system_check/app/database_config_exists_check.rb
+++ b/lib/system_check/app/database_config_exists_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class DatabaseConfigExistsCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/git_config_check.rb b/lib/system_check/app/git_config_check.rb
index d08a81639e3..4e8d607096c 100644
--- a/lib/system_check/app/git_config_check.rb
+++ b/lib/system_check/app/git_config_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class GitConfigCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/git_user_default_ssh_config_check.rb b/lib/system_check/app/git_user_default_ssh_config_check.rb
index ad41760dff2..6cd53779bfd 100644
--- a/lib/system_check/app/git_user_default_ssh_config_check.rb
+++ b/lib/system_check/app/git_user_default_ssh_config_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class GitUserDefaultSSHConfigCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/git_version_check.rb b/lib/system_check/app/git_version_check.rb
index 44ec888c197..7c3e7759dd0 100644
--- a/lib/system_check/app/git_version_check.rb
+++ b/lib/system_check/app/git_version_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class GitVersionCheck < SystemCheck::BaseCheck
@@ -5,7 +7,7 @@ module SystemCheck
set_check_pass -> { "yes (#{self.current_version})" }
def self.required_version
- @required_version ||= Gitlab::VersionInfo.new(2, 9, 5)
+ @required_version ||= Gitlab::VersionInfo.parse('2.18.0')
end
def self.current_version
diff --git a/lib/system_check/app/gitlab_config_exists_check.rb b/lib/system_check/app/gitlab_config_exists_check.rb
index 247aa0994e4..1cc5ead0d89 100644
--- a/lib/system_check/app/gitlab_config_exists_check.rb
+++ b/lib/system_check/app/gitlab_config_exists_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class GitlabConfigExistsCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/gitlab_config_up_to_date_check.rb b/lib/system_check/app/gitlab_config_up_to_date_check.rb
index c609e48e133..58c7e3039c8 100644
--- a/lib/system_check/app/gitlab_config_up_to_date_check.rb
+++ b/lib/system_check/app/gitlab_config_up_to_date_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class GitlabConfigUpToDateCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/init_script_exists_check.rb b/lib/system_check/app/init_script_exists_check.rb
index d246e058e86..d36dbe7d67d 100644
--- a/lib/system_check/app/init_script_exists_check.rb
+++ b/lib/system_check/app/init_script_exists_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class InitScriptExistsCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/init_script_up_to_date_check.rb b/lib/system_check/app/init_script_up_to_date_check.rb
index 53a47eb0f42..569c41df6e4 100644
--- a/lib/system_check/app/init_script_up_to_date_check.rb
+++ b/lib/system_check/app/init_script_up_to_date_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class InitScriptUpToDateCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/log_writable_check.rb b/lib/system_check/app/log_writable_check.rb
index 3e0c436d6ee..e26ad143eb8 100644
--- a/lib/system_check/app/log_writable_check.rb
+++ b/lib/system_check/app/log_writable_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class LogWritableCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/migrations_are_up_check.rb b/lib/system_check/app/migrations_are_up_check.rb
index 5eedbacce77..b12e9ac6bba 100644
--- a/lib/system_check/app/migrations_are_up_check.rb
+++ b/lib/system_check/app/migrations_are_up_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class MigrationsAreUpCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/orphaned_group_members_check.rb b/lib/system_check/app/orphaned_group_members_check.rb
index 2b46d36fe51..3e6ffb8190b 100644
--- a/lib/system_check/app/orphaned_group_members_check.rb
+++ b/lib/system_check/app/orphaned_group_members_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class OrphanedGroupMembersCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/projects_have_namespace_check.rb b/lib/system_check/app/projects_have_namespace_check.rb
index a6ec9f7665c..2bf2529acf1 100644
--- a/lib/system_check/app/projects_have_namespace_check.rb
+++ b/lib/system_check/app/projects_have_namespace_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class ProjectsHaveNamespaceCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/redis_version_check.rb b/lib/system_check/app/redis_version_check.rb
index a0610e73576..890f8b44d13 100644
--- a/lib/system_check/app/redis_version_check.rb
+++ b/lib/system_check/app/redis_version_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class RedisVersionCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/ruby_version_check.rb b/lib/system_check/app/ruby_version_check.rb
index 57bbabece1f..60e07718338 100644
--- a/lib/system_check/app/ruby_version_check.rb
+++ b/lib/system_check/app/ruby_version_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class RubyVersionCheck < SystemCheck::BaseCheck
@@ -9,7 +11,7 @@ module SystemCheck
end
def self.current_version
- @current_version ||= Gitlab::VersionInfo.parse(Gitlab::TaskHelpers.run_command(%w(ruby --version)))
+ @current_version ||= Gitlab::VersionInfo.parse(RUBY_VERSION)
end
def check?
diff --git a/lib/system_check/app/tmp_writable_check.rb b/lib/system_check/app/tmp_writable_check.rb
index 99a75e57abf..6687df091d3 100644
--- a/lib/system_check/app/tmp_writable_check.rb
+++ b/lib/system_check/app/tmp_writable_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class TmpWritableCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/uploads_directory_exists_check.rb b/lib/system_check/app/uploads_directory_exists_check.rb
index 7026d0ba075..940eff9d4cf 100644
--- a/lib/system_check/app/uploads_directory_exists_check.rb
+++ b/lib/system_check/app/uploads_directory_exists_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class UploadsDirectoryExistsCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/uploads_path_permission_check.rb b/lib/system_check/app/uploads_path_permission_check.rb
index 7df6c060254..4a49f3bc2bb 100644
--- a/lib/system_check/app/uploads_path_permission_check.rb
+++ b/lib/system_check/app/uploads_path_permission_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class UploadsPathPermissionCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/app/uploads_path_tmp_permission_check.rb b/lib/system_check/app/uploads_path_tmp_permission_check.rb
index b276a81eac1..ae374f4707c 100644
--- a/lib/system_check/app/uploads_path_tmp_permission_check.rb
+++ b/lib/system_check/app/uploads_path_tmp_permission_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module App
class UploadsPathTmpPermissionCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/base_check.rb b/lib/system_check/base_check.rb
index 0f5742dd67f..e06245294c4 100644
--- a/lib/system_check/base_check.rb
+++ b/lib/system_check/base_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
# Base class for Checks. You must inherit from here
# and implement the methods below when necessary
diff --git a/lib/system_check/helpers.rb b/lib/system_check/helpers.rb
index 6227e461d24..07d479848fe 100644
--- a/lib/system_check/helpers.rb
+++ b/lib/system_check/helpers.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module Helpers
include ::Gitlab::TaskHelpers
diff --git a/lib/system_check/incoming_email/foreman_configured_check.rb b/lib/system_check/incoming_email/foreman_configured_check.rb
index 1db7bf2b782..944913087da 100644
--- a/lib/system_check/incoming_email/foreman_configured_check.rb
+++ b/lib/system_check/incoming_email/foreman_configured_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module IncomingEmail
class ForemanConfiguredCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/incoming_email/imap_authentication_check.rb b/lib/system_check/incoming_email/imap_authentication_check.rb
index 3550c5796b0..613c2296375 100644
--- a/lib/system_check/incoming_email/imap_authentication_check.rb
+++ b/lib/system_check/incoming_email/imap_authentication_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module IncomingEmail
class ImapAuthenticationCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/incoming_email/initd_configured_check.rb b/lib/system_check/incoming_email/initd_configured_check.rb
index ea23b8ef49c..acb4b5a9e74 100644
--- a/lib/system_check/incoming_email/initd_configured_check.rb
+++ b/lib/system_check/incoming_email/initd_configured_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module IncomingEmail
class InitdConfiguredCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/incoming_email/mail_room_running_check.rb b/lib/system_check/incoming_email/mail_room_running_check.rb
index c1807501829..b7aead4624e 100644
--- a/lib/system_check/incoming_email/mail_room_running_check.rb
+++ b/lib/system_check/incoming_email/mail_room_running_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module IncomingEmail
class MailRoomRunningCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/orphans/namespace_check.rb b/lib/system_check/orphans/namespace_check.rb
index 09b57c7b408..53b2d8fd5b3 100644
--- a/lib/system_check/orphans/namespace_check.rb
+++ b/lib/system_check/orphans/namespace_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module Orphans
class NamespaceCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/orphans/repository_check.rb b/lib/system_check/orphans/repository_check.rb
index 2695c658874..ef8fe945f61 100644
--- a/lib/system_check/orphans/repository_check.rb
+++ b/lib/system_check/orphans/repository_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
module Orphans
class RepositoryCheck < SystemCheck::BaseCheck
diff --git a/lib/system_check/simple_executor.rb b/lib/system_check/simple_executor.rb
index 99c9e984107..11818ae54f8 100644
--- a/lib/system_check/simple_executor.rb
+++ b/lib/system_check/simple_executor.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module SystemCheck
# Simple Executor is current default executor for GitLab
# It is a simple port from display logic in the old check.rake
diff --git a/lib/tasks/gettext.rake b/lib/tasks/gettext.rake
index a497d26312e..2235a6ba194 100644
--- a/lib/tasks/gettext.rake
+++ b/lib/tasks/gettext.rake
@@ -82,7 +82,7 @@ namespace :gettext do
# `gettext:find` writes touches to temp files to `stderr` which would cause
# `static-analysis` to report failures. We can ignore these.
- silence_sdterr do
+ silence_stderr do
Rake::Task['gettext:find'].invoke
end
@@ -119,7 +119,7 @@ namespace :gettext do
end
end
- def silence_sdterr(&block)
+ def silence_stderr(&block)
old_stderr = $stderr.dup
$stderr.reopen(File::NULL)
$stderr.sync = true
diff --git a/lib/tasks/gitlab/artifacts/migrate.rake b/lib/tasks/gitlab/artifacts/migrate.rake
index bfca4bfb3f7..e7634d2ed4f 100644
--- a/lib/tasks/gitlab/artifacts/migrate.rake
+++ b/lib/tasks/gitlab/artifacts/migrate.rake
@@ -15,7 +15,7 @@ namespace :gitlab do
build.artifacts_file.migrate!(ObjectStorage::Store::REMOTE)
build.artifacts_metadata.migrate!(ObjectStorage::Store::REMOTE)
- logger.info("Transferred artifacts of #{build.id} of #{build.artifacts_size} to object storage")
+ logger.info("Transferred artifact ID #{build.id} with size #{build.artifacts_size} to object storage")
rescue => e
logger.error("Failed to transfer artifacts of #{build.id} with error: #{e.message}")
end
diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index e5b5f3548e4..a2c3e32948f 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -1,6 +1,7 @@
namespace :gitlab do
desc 'GitLab | Check the configuration of GitLab and its environment'
task check: %w{gitlab:gitlab_shell:check
+ gitlab:gitaly:check
gitlab:sidekiq:check
gitlab:incoming_email:check
gitlab:ldap:check
@@ -44,13 +45,6 @@ namespace :gitlab do
start_checking "GitLab Shell"
check_gitlab_shell
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- check_repo_base_exists
- check_repo_base_is_not_symlink
- check_repo_base_user_and_group
- check_repo_base_permissions
- check_repos_hooks_directory_is_link
- end
check_gitlab_shell_self_test
finished_checking "GitLab Shell"
@@ -59,152 +53,6 @@ namespace :gitlab do
# Checks
########################
- def check_repo_base_exists
- puts "Repo base directory exists?"
-
- Gitlab.config.repositories.storages.each do |name, repository_storage|
- repo_base_path = repository_storage.legacy_disk_path
- print "#{name}... "
-
- if File.exist?(repo_base_path)
- puts "yes".color(:green)
- else
- puts "no".color(:red)
- puts "#{repo_base_path} is missing".color(:red)
- try_fixing_it(
- "This should have been created when setting up GitLab Shell.",
- "Make sure it's set correctly in config/gitlab.yml",
- "Make sure GitLab Shell is installed correctly."
- )
- for_more_information(
- see_installation_guide_section "GitLab Shell"
- )
- fix_and_rerun
- end
- end
- end
-
- def check_repo_base_is_not_symlink
- puts "Repo storage directories are symlinks?"
-
- Gitlab.config.repositories.storages.each do |name, repository_storage|
- repo_base_path = repository_storage.legacy_disk_path
- print "#{name}... "
-
- unless File.exist?(repo_base_path)
- puts "can't check because of previous errors".color(:magenta)
- break
- end
-
- unless File.symlink?(repo_base_path)
- puts "no".color(:green)
- else
- puts "yes".color(:red)
- try_fixing_it(
- "Make sure it's set to the real directory in config/gitlab.yml"
- )
- fix_and_rerun
- end
- end
- end
-
- def check_repo_base_permissions
- puts "Repo paths access is drwxrws---?"
-
- Gitlab.config.repositories.storages.each do |name, repository_storage|
- repo_base_path = repository_storage.legacy_disk_path
- print "#{name}... "
-
- unless File.exist?(repo_base_path)
- puts "can't check because of previous errors".color(:magenta)
- break
- end
-
- if File.stat(repo_base_path).mode.to_s(8).ends_with?("2770")
- puts "yes".color(:green)
- else
- puts "no".color(:red)
- try_fixing_it(
- "sudo chmod -R ug+rwX,o-rwx #{repo_base_path}",
- "sudo chmod -R ug-s #{repo_base_path}",
- "sudo find #{repo_base_path} -type d -print0 | sudo xargs -0 chmod g+s"
- )
- for_more_information(
- see_installation_guide_section "GitLab Shell"
- )
- fix_and_rerun
- end
- end
- end
-
- def check_repo_base_user_and_group
- gitlab_shell_ssh_user = Gitlab.config.gitlab_shell.ssh_user
- puts "Repo paths owned by #{gitlab_shell_ssh_user}:root, or #{gitlab_shell_ssh_user}:#{Gitlab.config.gitlab_shell.owner_group}?"
-
- Gitlab.config.repositories.storages.each do |name, repository_storage|
- repo_base_path = repository_storage.legacy_disk_path
- print "#{name}... "
-
- unless File.exist?(repo_base_path)
- puts "can't check because of previous errors".color(:magenta)
- break
- end
-
- user_id = uid_for(gitlab_shell_ssh_user)
- root_group_id = gid_for('root')
- group_ids = [root_group_id, gid_for(Gitlab.config.gitlab_shell.owner_group)]
- if File.stat(repo_base_path).uid == user_id && group_ids.include?(File.stat(repo_base_path).gid)
- puts "yes".color(:green)
- else
- puts "no".color(:red)
- puts " User id for #{gitlab_shell_ssh_user}: #{user_id}. Groupd id for root: #{root_group_id}".color(:blue)
- try_fixing_it(
- "sudo chown -R #{gitlab_shell_ssh_user}:root #{repo_base_path}"
- )
- for_more_information(
- see_installation_guide_section "GitLab Shell"
- )
- fix_and_rerun
- end
- end
- end
-
- def check_repos_hooks_directory_is_link
- print "hooks directories in repos are links: ... "
-
- gitlab_shell_hooks_path = Gitlab.config.gitlab_shell.hooks_path
-
- unless Project.count > 0
- puts "can't check, you have no projects".color(:magenta)
- return
- end
-
- puts ""
-
- Project.find_each(batch_size: 100) do |project|
- print sanitized_message(project)
- project_hook_directory = File.join(project.repository.path_to_repo, "hooks")
-
- if project.empty_repo?
- puts "repository is empty".color(:magenta)
- elsif File.directory?(project_hook_directory) && File.directory?(gitlab_shell_hooks_path) &&
- (File.realpath(project_hook_directory) == File.realpath(gitlab_shell_hooks_path))
- puts 'ok'.color(:green)
- else
- puts "wrong or missing hooks".color(:red)
- try_fixing_it(
- sudo_gitlab("#{File.join(gitlab_shell_path, 'bin/create-hooks')} #{repository_storage_paths_args.join(' ')}"),
- 'Check the hooks_path in config/gitlab.yml',
- 'Check your gitlab-shell installation'
- )
- for_more_information(
- see_installation_guide_section "GitLab Shell"
- )
- fix_and_rerun
- end
- end
- end
-
def check_gitlab_shell_self_test
gitlab_shell_repo_base = gitlab_shell_path
check_cmd = File.expand_path('bin/check', gitlab_shell_repo_base)
@@ -247,6 +95,26 @@ namespace :gitlab do
end
end
+ namespace :gitaly do
+ desc 'GitLab | Check the health of Gitaly'
+ task check: :gitlab_environment do
+ warn_user_is_not_gitlab
+ start_checking 'Gitaly'
+
+ Gitlab::HealthChecks::GitalyCheck.readiness.each do |result|
+ print "#{result.labels[:shard]} ... "
+
+ if result.success
+ puts 'OK'.color(:green)
+ else
+ puts "FAIL: #{result.message}".color(:red)
+ end
+ end
+
+ finished_checking 'Gitaly'
+ end
+ end
+
namespace :sidekiq do
desc "GitLab | Check the configuration of Sidekiq"
task check: :gitlab_environment do
diff --git a/lib/tasks/gitlab/cleanup.rake b/lib/tasks/gitlab/cleanup.rake
index e8ae5dfa540..451ba651674 100644
--- a/lib/tasks/gitlab/cleanup.rake
+++ b/lib/tasks/gitlab/cleanup.rake
@@ -6,7 +6,7 @@ namespace :gitlab do
desc "GitLab | Cleanup | Clean namespaces"
task dirs: :gitlab_environment do
namespaces = Set.new(Namespace.pluck(:path))
- namespaces << Storage::HashedProject::ROOT_PATH_PREFIX
+ namespaces << Storage::HashedProject::REPOSITORY_PATH_PREFIX
Gitaly::Server.all.each do |server|
all_dirs = Gitlab::GitalyClient::StorageService
@@ -49,7 +49,7 @@ namespace :gitlab do
# TODO ignoring hashed repositories for now. But revisit to fully support
# possible orphaned hashed repos
- next if repo_with_namespace.start_with?(Storage::HashedProject::ROOT_PATH_PREFIX)
+ next if repo_with_namespace.start_with?(Storage::HashedProject::REPOSITORY_PATH_PREFIX)
next if Project.find_by_full_path(repo_with_namespace)
new_path = path + move_suffix
diff --git a/lib/tasks/gitlab/ldap.rake b/lib/tasks/gitlab/ldap.rake
index c66a2a263dc..0459de27c96 100644
--- a/lib/tasks/gitlab/ldap.rake
+++ b/lib/tasks/gitlab/ldap.rake
@@ -1,7 +1,7 @@
namespace :gitlab do
namespace :ldap do
desc 'GitLab | LDAP | Rename provider'
- task :rename_provider, [:old_provider, :new_provider] => :environment do |_, args|
+ task :rename_provider, [:old_provider, :new_provider] => :gitlab_environment do |_, args|
old_provider = args[:old_provider] ||
prompt('What is the old provider? Ex. \'ldapmain\': '.color(:blue))
new_provider = args[:new_provider] ||
diff --git a/lib/tasks/gitlab/shell.rake b/lib/tasks/gitlab/shell.rake
index 4fcbbbf8c9d..0ebc6f00793 100644
--- a/lib/tasks/gitlab/shell.rake
+++ b/lib/tasks/gitlab/shell.rake
@@ -92,9 +92,11 @@ namespace :gitlab do
def setup
warn_user_is_not_gitlab
+ ensure_write_to_authorized_keys_is_enabled
+
unless ENV['force'] == 'yes'
- puts "This will rebuild an authorized_keys file."
- puts "You will lose any data stored in authorized_keys file."
+ puts "This task will now rebuild the authorized_keys file."
+ puts "You will lose any data stored in the authorized_keys file."
ask_to_continue
puts ""
end
@@ -118,4 +120,44 @@ namespace :gitlab do
puts "Quitting...".color(:red)
exit 1
end
+
+ def ensure_write_to_authorized_keys_is_enabled
+ return if Gitlab::CurrentSettings.current_application_settings.authorized_keys_enabled
+
+ puts authorized_keys_is_disabled_warning
+
+ unless ENV['force'] == 'yes'
+ puts 'Do you want to permanently enable the "Write to authorized_keys file" setting now?'
+ ask_to_continue
+ end
+
+ puts 'Enabling the "Write to authorized_keys file" setting...'
+ Gitlab::CurrentSettings.current_application_settings.update!(authorized_keys_enabled: true)
+
+ puts 'Successfully enabled "Write to authorized_keys file"!'
+ puts ''
+ end
+
+ def authorized_keys_is_disabled_warning
+ <<-MSG.strip_heredoc
+ WARNING
+
+ The "Write to authorized_keys file" setting is disabled, which prevents
+ the file from being rebuilt!
+
+ It should be enabled for most GitLab installations. Large installations
+ may wish to disable it as part of speeding up SSH operations.
+
+ See https://docs.gitlab.com/ee/administration/operations/fast_ssh_key_lookup.html
+
+ If you did not intentionally disable this option in Admin Area > Settings,
+ then you may have been affected by the 9.3.0 bug in which the new setting
+ was disabled by default.
+
+ https://gitlab.com/gitlab-org/gitlab-ee/issues/2738
+
+ It was reverted in 9.3.1 and fixed in 9.3.3, however, if Settings were
+ saved while the setting was unchecked, then it is still disabled.
+ MSG
+ end
end
diff --git a/lib/tasks/gitlab/site_statistics.rake b/lib/tasks/gitlab/site_statistics.rake
deleted file mode 100644
index 7d24ec72a9d..00000000000
--- a/lib/tasks/gitlab/site_statistics.rake
+++ /dev/null
@@ -1,23 +0,0 @@
-namespace :gitlab do
- desc "GitLab | Refresh Site Statistics counters"
- task refresh_site_statistics: :environment do
- puts 'Updating Site Statistics counters: '
-
- print '* Repositories... '
- SiteStatistic.transaction do
- # see https://gitlab.com/gitlab-org/gitlab-ce/issues/48967
- ActiveRecord::Base.connection.execute('SET LOCAL statement_timeout TO 0') if Gitlab::Database.postgresql?
- SiteStatistic.update_all('repositories_count = (SELECT COUNT(*) FROM projects)')
- end
- puts 'OK!'.color(:green)
-
- print '* Wikis... '
- SiteStatistic.transaction do
- # see https://gitlab.com/gitlab-org/gitlab-ce/issues/48967
- ActiveRecord::Base.connection.execute('SET LOCAL statement_timeout TO 0') if Gitlab::Database.postgresql?
- SiteStatistic.update_all('wikis_count = (SELECT COUNT(*) FROM project_features WHERE wiki_access_level != 0)')
- end
- puts 'OK!'.color(:green)
- puts
- end
-end
diff --git a/lib/tasks/gitlab/update_templates.rake b/lib/tasks/gitlab/update_templates.rake
index ef6a32d6730..abe10f5580e 100644
--- a/lib/tasks/gitlab/update_templates.rake
+++ b/lib/tasks/gitlab/update_templates.rake
@@ -100,10 +100,6 @@ namespace :gitlab do
/(\.{1,2}|LICENSE|Global|\.gitignore)\z/
),
Template.new(
- "https://gitlab.com/gitlab-org/gitlab-ci-yml.git",
- /(\.{1,2}|LICENSE|CONTRIBUTING.md|Pages|autodeploy|\.gitlab-ci.yml)\z/
- ),
- Template.new(
"https://gitlab.com/gitlab-org/Dockerfile.git",
/(\.{1,2}|LICENSE|CONTRIBUTING.md|\.Dockerfile)\z/
)
diff --git a/lib/tasks/haml-lint.rake b/lib/tasks/haml-lint.rake
index ad2d034b0b4..786efd14b1a 100644
--- a/lib/tasks/haml-lint.rake
+++ b/lib/tasks/haml-lint.rake
@@ -2,5 +2,16 @@ unless Rails.env.production?
require 'haml_lint/rake_task'
require 'haml_lint/inline_javascript'
+ # Workaround for warnings from parser/current
+ # Keep it even if it no longer emits any warnings,
+ # because we'll still see warnings in console/server anyway,
+ # and we don't need to break static-analysis for this.
+ task :haml_lint do
+ require 'parser'
+ def Parser.warn(*args)
+ puts(*args) # static-analysis ignores stdout if status is 0
+ end
+ end
+
HamlLint::RakeTask.new
end
diff --git a/lib/tasks/import.rake b/lib/tasks/import.rake
index fc59b3f937d..f912f521dfb 100644
--- a/lib/tasks/import.rake
+++ b/lib/tasks/import.rake
@@ -9,7 +9,7 @@ class GithubImport
def initialize(token, gitlab_username, project_path, extras)
@options = { token: token }
@project_path = project_path
- @current_user = User.find_by(username: gitlab_username)
+ @current_user = UserFinder.new(gitlab_username).find_by_username
raise "GitLab user #{gitlab_username} not found. Please specify a valid username." unless @current_user
@@ -42,7 +42,7 @@ class GithubImport
end
def import!
- @project.force_import_start
+ @project.import_state.force_start
import_success = false
@@ -57,7 +57,7 @@ class GithubImport
puts "Import finished. Timings: #{timings}".color(:green)
else
puts "Import was not successful. Errors were as follows:"
- puts @project.import_error
+ puts @project.import_state.last_error
end
end
diff --git a/lib/tasks/tokens.rake b/lib/tasks/tokens.rake
index 81829668de8..eec024f9bbb 100644
--- a/lib/tasks/tokens.rake
+++ b/lib/tasks/tokens.rake
@@ -1,4 +1,7 @@
require_relative '../../app/models/concerns/token_authenticatable.rb'
+require_relative '../../app/models/concerns/token_authenticatable_strategies/base.rb'
+require_relative '../../app/models/concerns/token_authenticatable_strategies/insecure.rb'
+require_relative '../../app/models/concerns/token_authenticatable_strategies/digest.rb'
namespace :tokens do
desc "Reset all GitLab incoming email tokens"
@@ -26,13 +29,6 @@ class TmpUser < ActiveRecord::Base
self.table_name = 'users'
- def reset_incoming_email_token!
- write_new_token(:incoming_email_token)
- save!(validate: false)
- end
-
- def reset_feed_token!
- write_new_token(:feed_token)
- save!(validate: false)
- end
+ add_authentication_token_field :incoming_email_token, token_generator: -> { SecureRandom.hex.to_i(16).to_s(36) }
+ add_authentication_token_field :feed_token
end
diff --git a/lib/unfold_form.rb b/lib/unfold_form.rb
index fcd01503d1b..05bb3ed7f1c 100644
--- a/lib/unfold_form.rb
+++ b/lib/unfold_form.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require_relative 'gt_one_coercion'
class UnfoldForm
diff --git a/lib/uploaded_file.rb b/lib/uploaded_file.rb
index 53e5ac02e42..aae542f02ac 100644
--- a/lib/uploaded_file.rb
+++ b/lib/uploaded_file.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "tempfile"
require "tmpdir"
require "fileutils"
diff --git a/lib/version_check.rb b/lib/version_check.rb
index 91ad07feee5..ccf7bb493db 100644
--- a/lib/version_check.rb
+++ b/lib/version_check.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require "base64"
# This class is used to build image URL to
diff --git a/locale/ar_SA/gitlab.po b/locale/ar_SA/gitlab.po
index 662e69e27c6..4047b9bfd81 100644
--- a/locale/ar_SA/gitlab.po
+++ b/locale/ar_SA/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Arabic\n"
"Language: ar_SA\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ar\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:32\n"
+"PO-Revision-Date: 2018-11-19 17:20\n"
msgid " Status"
msgstr ""
@@ -39,6 +39,18 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -66,6 +78,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -147,15 +168,6 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] ""
@@ -168,12 +180,21 @@ msgstr[5] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] ""
@@ -183,6 +204,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -192,6 +222,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -207,27 +240,12 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr ""
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr ""
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -243,43 +261,13 @@ msgstr ""
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -450,6 +438,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr ""
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -492,13 +489,10 @@ msgstr ""
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
-msgstr ""
-
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgid "Access expiration date"
msgstr ""
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -528,27 +522,48 @@ msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
+msgid "Add Kubernetes cluster"
msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -558,6 +573,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -591,9 +609,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -630,12 +645,21 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr ""
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "All"
msgstr ""
@@ -651,6 +675,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -660,6 +687,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -675,6 +708,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -696,7 +732,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -720,6 +756,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -732,6 +774,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -744,6 +789,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -771,6 +819,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -813,12 +864,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr ""
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -837,7 +894,7 @@ msgstr ""
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -855,9 +912,15 @@ msgstr ""
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -876,6 +939,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -1014,6 +1080,9 @@ msgstr ""
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -1050,9 +1119,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -1131,6 +1197,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1425,6 +1500,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1455,9 +1533,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1512,7 +1587,7 @@ msgstr ""
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1539,6 +1614,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1569,6 +1650,9 @@ msgstr ""
msgid "CiStatusLabel|created"
msgstr ""
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr ""
@@ -1587,6 +1671,9 @@ msgstr ""
msgid "CiStatusLabel|skipped"
msgstr ""
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr ""
@@ -1599,6 +1686,9 @@ msgstr ""
msgid "CiStatusText|created"
msgstr ""
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr ""
@@ -1653,10 +1743,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1701,6 +1791,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1713,12 +1806,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1749,10 +1854,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1779,6 +1884,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1815,6 +1926,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1845,9 +1959,6 @@ msgstr ""
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1869,25 +1980,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster details"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster health"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1899,7 +2004,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1908,16 +2013,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1935,9 +2037,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1965,6 +2064,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1977,6 +2079,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -2007,9 +2112,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -2049,13 +2151,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -2073,6 +2172,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2091,9 +2193,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -2103,6 +2202,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -2112,12 +2214,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2160,6 +2268,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr ""
@@ -2232,7 +2343,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2241,10 +2352,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2334,6 +2445,9 @@ msgstr ""
msgid "Contribution guide"
msgstr ""
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2367,6 +2481,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2388,15 +2514,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2472,7 +2610,7 @@ msgstr ""
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
+msgid "Create your first page"
msgstr ""
msgid "CreateTag|Tag"
@@ -2523,6 +2661,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -2541,6 +2682,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr ""
@@ -2592,6 +2736,9 @@ msgstr ""
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2604,6 +2751,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr ""
@@ -2613,6 +2775,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2754,6 +2919,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2778,6 +2949,12 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2799,12 +2976,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2820,6 +3012,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2901,7 +3096,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2946,9 +3141,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2961,6 +3153,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -3063,7 +3261,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -3096,10 +3294,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3210,6 +3408,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3264,6 +3468,12 @@ msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3273,6 +3483,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3282,6 +3495,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3291,6 +3579,9 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr ""
@@ -3303,9 +3594,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr ""
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr ""
@@ -3321,6 +3621,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3333,7 +3636,7 @@ msgstr ""
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3372,21 +3675,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -3402,6 +3702,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3444,6 +3747,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3618,10 +3924,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3630,6 +3948,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3651,7 +3972,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3663,6 +3984,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3672,19 +3996,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3702,6 +4032,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3714,9 +4050,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3726,9 +4080,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3795,12 +4146,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr ""
-
-msgid "GoToYourFork|Fork"
-msgstr ""
-
msgid "Google Code import"
msgstr ""
@@ -3831,9 +4176,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3843,6 +4200,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3861,13 +4221,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3894,9 +4254,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3954,6 +4311,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3966,19 +4326,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -4020,6 +4380,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4188,6 +4551,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4260,6 +4626,12 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4284,6 +4656,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4299,9 +4701,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4338,7 +4737,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4356,12 +4755,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4434,6 +4827,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
@@ -4449,12 +4845,18 @@ msgstr ""
msgid "Last commit"
msgstr ""
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4503,6 +4905,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4512,6 +4923,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4521,6 +4935,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4530,6 +4947,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4542,9 +4962,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4575,6 +5001,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4620,6 +5049,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4689,13 +5121,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4707,6 +5169,12 @@ msgstr ""
msgid "Median"
msgstr ""
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -4740,6 +5208,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4749,9 +5232,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4761,6 +5241,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4776,6 +5262,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4992,6 +5481,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -5115,6 +5607,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -5124,9 +5622,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -5136,6 +5631,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5163,6 +5661,9 @@ msgstr ""
msgid "No repository"
msgstr ""
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr ""
@@ -5199,6 +5700,9 @@ msgstr ""
msgid "Not enough data"
msgstr ""
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -5217,6 +5721,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -5289,9 +5805,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5322,9 +5835,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5346,6 +5856,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5370,6 +5883,21 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5436,6 +5964,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5463,13 +5994,13 @@ msgstr ""
msgid "Permissions"
msgstr ""
-msgid "Personal Access Token"
+msgid "Permissions, LFS, 2FA"
msgstr ""
-msgid "Pipeline"
+msgid "Personal Access Token"
msgstr ""
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
+msgid "Pipeline"
msgstr ""
msgid "Pipeline Health"
@@ -5589,15 +6120,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5607,6 +6147,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5634,12 +6180,6 @@ msgstr ""
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5649,12 +6189,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5667,6 +6213,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5679,9 +6228,18 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5727,15 +6285,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5748,39 +6321,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -5790,6 +6444,15 @@ msgstr ""
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5826,6 +6489,9 @@ msgstr ""
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr ""
@@ -5853,6 +6519,9 @@ msgstr ""
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -5880,6 +6549,27 @@ msgstr ""
msgid "ProjectLifecycle|Stage"
msgstr ""
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5922,6 +6612,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5991,9 +6684,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6186,6 +6876,12 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6252,12 +6948,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6267,6 +6972,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6276,18 +6984,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6300,6 +7023,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6333,10 +7059,10 @@ msgstr ""
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6354,9 +7080,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6411,9 +7149,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6423,6 +7176,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6447,6 +7206,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6471,6 +7233,9 @@ msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -6525,15 +7290,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6558,31 +7332,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard"
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6600,9 +7398,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr ""
@@ -6633,6 +7437,9 @@ msgstr ""
msgid "Select target branch"
msgstr ""
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6645,6 +7452,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6669,6 +7479,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6687,7 +7500,10 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
@@ -6699,13 +7515,31 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "Settings"
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
msgstr ""
msgid "Share"
@@ -6717,6 +7551,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6804,12 +7641,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6837,9 +7680,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6852,12 +7701,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -6888,6 +7749,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6918,6 +7782,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6948,6 +7815,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -7023,9 +7893,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -7038,6 +7920,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -7047,6 +7932,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -7056,9 +7944,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -7071,6 +7965,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -7089,6 +7989,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -7197,6 +8100,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7245,12 +8151,6 @@ msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7299,9 +8199,6 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr ""
@@ -7311,21 +8208,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr ""
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7335,6 +8226,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7344,7 +8238,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7392,10 +8292,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7416,6 +8319,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7455,7 +8361,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7476,6 +8385,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
@@ -7500,6 +8412,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7509,6 +8424,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7536,9 +8457,15 @@ msgstr ""
msgid "Time before an issue starts implementation"
msgstr ""
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr ""
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7737,12 +8664,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7758,6 +8697,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7770,12 +8712,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7785,9 +8730,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7803,6 +8754,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7818,6 +8772,9 @@ msgstr ""
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7827,6 +8784,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7845,24 +8805,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7878,6 +8856,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7911,13 +8895,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7947,15 +8934,15 @@ msgstr ""
msgid "Upload file"
msgstr ""
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr ""
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7983,6 +8970,9 @@ msgstr ""
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7992,10 +8982,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -8022,6 +9054,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -8055,9 +9096,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -8076,6 +9123,36 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -8115,6 +9192,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8265,6 +9348,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8283,9 +9369,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8295,9 +9378,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8319,12 +9399,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8346,9 +9432,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr ""
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8358,6 +9441,12 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr ""
@@ -8424,6 +9513,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8445,24 +9537,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
-
msgid "assign yourself"
msgstr ""
@@ -8490,61 +9564,94 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8577,9 +9684,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8610,6 +9714,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8628,13 +9735,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8643,9 +9744,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8676,9 +9774,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8694,9 +9789,6 @@ msgstr[5] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8730,17 +9822,14 @@ msgstr[5] ""
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-msgstr[4] ""
-msgstr[5] ""
+msgid "disabled"
+msgstr ""
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
@@ -8748,22 +9837,19 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "detected no vulnerabilities"
-msgstr ""
-
-msgid "disabled"
+msgid "enabled"
msgstr ""
-msgid "done"
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
-msgid "enabled"
+msgid "for this project"
msgstr ""
-msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgid "from"
msgstr ""
-msgid "for this project"
+msgid "help"
msgstr ""
msgid "here"
@@ -8799,6 +9885,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -9039,6 +10128,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -9057,6 +10149,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr ""
@@ -9093,6 +10188,15 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "remaining"
msgstr ""
@@ -9105,6 +10209,15 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "source"
msgstr ""
@@ -9120,6 +10233,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index dc4d2618ab7..7175ea66422 100644
--- a/locale/bg/gitlab.po
+++ b/locale/bg/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Bulgarian\n"
"Language: bg_BG\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: bg\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:33\n"
+"PO-Revision-Date: 2018-11-19 17:21\n"
msgid " Status"
msgstr ""
@@ -31,6 +31,14 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -46,6 +54,11 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -91,11 +104,6 @@ msgid_plural "%d unstaged changes"
msgstr[0] ""
msgstr[1] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] "%s подаване беше пропуÑнато, за да не Ñе натоварва ÑиÑтемата."
@@ -104,17 +112,31 @@ msgstr[1] "%s Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ð±Ñха пропуÑнати, за да не Ñ
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] ""
msgstr[1] ""
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -124,6 +146,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -139,23 +164,12 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr ""
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr ""
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -167,27 +181,13 @@ msgstr ""
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -314,6 +314,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr "Ðабор от графики отноÑно непрекъÑнатата интеграциÑ"
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -356,13 +365,10 @@ msgstr ""
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
+msgid "Access expiration date"
msgstr ""
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr ""
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -392,27 +398,48 @@ msgstr "ДобавÑне на ръководÑтво за ÑътрудничеÑ
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
-msgstr "ДобавÑне на лиценз"
+msgid "Add Kubernetes cluster"
+msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr "ДобавÑне на нова папка"
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -422,6 +449,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -455,9 +485,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -494,12 +521,17 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr ""
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "All"
msgstr ""
@@ -515,6 +547,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -524,6 +559,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -539,6 +580,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -560,7 +604,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -584,6 +628,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -596,6 +646,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -608,6 +661,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -635,6 +691,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -677,12 +736,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr ""
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -701,7 +766,7 @@ msgstr ""
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -719,9 +784,15 @@ msgstr ""
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "ÐаиÑтина ли иÑкате да изтриете този план за Ñхема?"
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -740,6 +811,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -878,6 +952,9 @@ msgstr ""
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -914,9 +991,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -995,6 +1069,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1285,6 +1368,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1315,9 +1401,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1372,7 +1455,7 @@ msgstr "Графики"
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1399,6 +1482,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1429,6 +1518,9 @@ msgstr "отказано"
msgid "CiStatusLabel|created"
msgstr "Ñъздадено"
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr "неуÑпешно"
@@ -1447,6 +1539,9 @@ msgstr "на изчакване"
msgid "CiStatusLabel|skipped"
msgstr "пропуÑнато"
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr "чакане за ръчно дейÑтвие"
@@ -1459,6 +1554,9 @@ msgstr "отказано"
msgid "CiStatusText|created"
msgstr "Ñъздадено"
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr "неуÑпешно"
@@ -1513,10 +1611,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1561,6 +1659,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1573,12 +1674,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1609,10 +1722,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1639,6 +1752,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1675,6 +1794,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1705,9 +1827,6 @@ msgstr ""
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1729,25 +1848,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster details"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster health"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1759,7 +1872,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1768,16 +1881,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1795,9 +1905,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1825,6 +1932,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1837,6 +1947,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1867,9 +1980,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1909,13 +2019,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -1933,6 +2040,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -1951,9 +2061,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -1963,6 +2070,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -1972,12 +2082,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2012,6 +2128,9 @@ msgstr "Подаване"
msgid "CommitMessage|Add %{file_name}"
msgstr "ДобавÑне на „%{file_name}“"
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr "ПодаваниÑ"
@@ -2084,7 +2203,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2093,10 +2212,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2186,6 +2305,9 @@ msgstr ""
msgid "Contribution guide"
msgstr "РъководÑтво за ÑътрудничеÑтво"
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2219,6 +2341,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2240,15 +2374,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2324,8 +2470,8 @@ msgstr "Създаване на нов…"
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
-msgstr "РазклонÑване"
+msgid "Create your first page"
+msgstr ""
msgid "CreateTag|Tag"
msgstr "Етикет"
@@ -2375,6 +2521,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr "ПерÑонализирани ÑÑŠÐ±Ð¸Ñ‚Ð¸Ñ Ð·Ð° извеÑÑ‚Ñване"
@@ -2393,6 +2542,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr "Ðнализ на циклите"
@@ -2444,6 +2596,9 @@ msgstr ""
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2456,6 +2611,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Задайте потребителÑки шаблон, използвайки ÑинтакÑиÑа на „Cron“"
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr "Изтриване"
@@ -2465,6 +2635,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2602,6 +2775,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2626,6 +2805,12 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2647,12 +2832,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2668,6 +2868,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2749,7 +2952,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2794,9 +2997,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2809,6 +3009,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2911,7 +3117,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -2944,10 +3150,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3058,6 +3264,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3112,6 +3324,12 @@ msgstr "СобÑтвеникът не може да бъде променен"
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3121,6 +3339,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "Планът за Ñхема не може да бъде премахнат"
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3130,6 +3351,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3139,6 +3435,9 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr "Файлове"
@@ -3151,9 +3450,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr "Филтриране по Ñъобщение"
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr "ТърÑене по път"
@@ -3169,6 +3477,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3181,7 +3492,7 @@ msgstr "изпращане на промени от"
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3220,17 +3531,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] "Разклонение"
-msgstr[1] "РазклонениÑ"
-
msgid "ForkedFromProjectPath|Forked from"
msgstr "Разклонение на"
@@ -3246,6 +3558,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3288,6 +3603,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3462,10 +3780,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3474,6 +3804,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3495,7 +3828,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3507,6 +3840,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3516,19 +3852,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3546,6 +3888,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3558,9 +3906,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3570,9 +3936,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3639,12 +4002,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr "Към Вашето разклонение"
-
-msgid "GoToYourFork|Fork"
-msgstr "Разклонение"
-
msgid "Google Code import"
msgstr ""
@@ -3675,9 +4032,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3687,6 +4056,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3705,13 +4077,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3738,9 +4110,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3798,6 +4167,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3810,19 +4182,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -3864,6 +4236,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4028,6 +4403,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4096,6 +4474,12 @@ msgstr "Шаблон за интервала"
msgid "Introducing Cycle Analytics"
msgstr "ПредÑтавÑме Ви анализа на циклите"
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4120,6 +4504,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4135,9 +4549,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4174,7 +4585,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4192,12 +4603,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4270,6 +4675,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] "ПоÑÐ»ÐµÐ´Ð½Ð¸Ñ %d ден"
@@ -4281,12 +4689,18 @@ msgstr "ПоÑледна Ñхема"
msgid "Last commit"
msgstr "ПоÑледно подаване"
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4335,6 +4749,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4344,6 +4767,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4353,6 +4779,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4362,6 +4791,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4374,9 +4806,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4403,6 +4841,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4448,6 +4889,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4517,13 +4961,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4535,6 +5009,12 @@ msgstr ""
msgid "Median"
msgstr "Медиана"
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -4568,6 +5048,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4577,9 +5072,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4589,6 +5081,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4604,6 +5102,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4820,6 +5321,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -4939,6 +5443,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -4948,9 +5458,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -4960,6 +5467,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -4987,6 +5497,9 @@ msgstr ""
msgid "No repository"
msgstr "ÐÑма хранилище"
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr "ÐÑма планове"
@@ -5023,6 +5536,9 @@ msgstr ""
msgid "Not enough data"
msgstr "ÐÑма доÑтатъчно данни"
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -5041,6 +5557,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr "Ð¡ÑŠÐ±Ð¸Ñ‚Ð¸Ñ Ð·Ð° извеÑÑ‚Ñване"
@@ -5113,9 +5641,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5142,9 +5667,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5166,6 +5688,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5190,6 +5715,21 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5256,6 +5796,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5283,15 +5826,15 @@ msgstr ""
msgid "Permissions"
msgstr ""
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
msgid "Personal Access Token"
msgstr ""
msgid "Pipeline"
msgstr "Схема"
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
-msgstr ""
-
msgid "Pipeline Health"
msgstr "СъÑтоÑние"
@@ -5409,15 +5952,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5427,6 +5979,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5454,12 +6012,6 @@ msgstr "Ñ ÐµÑ‚Ð°Ð¿Ð¸"
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5469,12 +6021,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5487,6 +6045,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5499,9 +6060,18 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5547,15 +6117,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5568,39 +6153,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -5610,6 +6276,15 @@ msgstr ""
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5646,6 +6321,9 @@ msgstr "Проектът „%{project_name}“ беше обновен уÑпеÑ
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr "ДоÑтъпът до проекта Ñ‚Ñ€Ñбва да бъде даван поотделно на вÑеки потребител."
@@ -5673,6 +6351,9 @@ msgstr "ИзнаÑÑнето на проекта започна. Ще получ
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -5700,6 +6381,27 @@ msgstr "Ðикога"
msgid "ProjectLifecycle|Stage"
msgstr "Етап"
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5742,6 +6444,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5811,9 +6516,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6006,6 +6708,12 @@ msgstr "ПрочетиМе"
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6068,12 +6776,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr "Премахване на проекта"
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6083,6 +6800,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6092,18 +6812,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6116,6 +6851,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6149,10 +6887,10 @@ msgstr "ЗаÑвка за доÑтъп"
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6170,9 +6908,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6223,9 +6973,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6235,6 +7000,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6259,6 +7030,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6283,6 +7057,9 @@ msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Запазване на плана за Ñхема"
@@ -6337,15 +7114,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6370,27 +7156,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard"
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6408,9 +7222,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr "Изберете формата на архива"
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr "Изберете чаÑова зона"
@@ -6441,6 +7261,9 @@ msgstr ""
msgid "Select target branch"
msgstr "Изберете целеви клон"
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6453,6 +7276,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6477,6 +7303,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Задайте парола на акаунта Ñи, за да можете да изтеглÑте и изпращате промени чрез %{protocol}."
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6495,8 +7324,11 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr "ÐаÑтройка на „Koding“"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
@@ -6507,13 +7339,31 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "зададете парола"
-msgid "Settings"
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
msgstr ""
msgid "Share"
@@ -6525,6 +7375,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6608,12 +7461,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6641,9 +7500,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6656,12 +7521,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -6692,6 +7569,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6722,6 +7602,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6752,6 +7635,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6827,9 +7713,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr "Създайте %{new_merge_request} Ñ Ñ‚ÐµÐ·Ð¸ промени"
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6842,6 +7740,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6851,6 +7752,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6860,9 +7764,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6875,6 +7785,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Преминаване към клон/етикет"
@@ -6893,6 +7809,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -6997,6 +7916,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7045,12 +7967,6 @@ msgstr "Етапът на проблемите показва колко е вр
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7099,9 +8015,6 @@ msgstr "Етапът на преглед и одобрение показва в
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "Етапът на подготовка за издаване показва времето между прилагането на заÑвката за Ñливане и внедрÑването на кода в Ñредата на работещата крайна верÑиÑ. Данните ще бъдат добавени автоматично Ñлед като направите първото Ñи внедрÑване в крайната верÑиÑ."
@@ -7111,21 +8024,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr "Етапът на теÑтване показва времето, което е нужно на „Gitlab CI“ да изпълни вÑÑка Ñхема от задачи за Ñвързаната заÑвка за Ñливане. Данните ще бъдат добавени автоматично Ñлед като приключи изпълнението на първата Ви Ñхема."
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr "Времето, което отнема вÑеки Ð·Ð°Ð¿Ð¸Ñ Ð¾Ñ‚ данни за ÑÑŠÐ¾Ñ‚Ð²ÐµÑ‚Ð½Ð¸Ñ ÐµÑ‚Ð°Ð¿."
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7135,6 +8042,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "СтойноÑтта, коÑто Ñе намира в Ñредата на поÑледователноÑтта от наблюдавани данни. Ðапример: медианата на 3, 5 и 9 е 5, а медианата на 3, 5, 7 и 8 е (5+7)/2 = 6."
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7144,7 +8054,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7192,10 +8108,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7216,6 +8135,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7255,7 +8177,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7276,6 +8201,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Това означава, че нÑма да можете да изпращате код, докато не Ñъздадете празно хранилище или не внеÑете ÑъщеÑтвуващо такова."
@@ -7300,6 +8228,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7309,6 +8240,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7336,9 +8273,15 @@ msgstr "Време преди един проблем да бъде планир
msgid "Time before an issue starts implementation"
msgstr "Време преди работата по проблем да започне"
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr "Време между Ñъздаване на заÑвка за Ñливане и прилагането/отхвърлÑнето Ñ"
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7529,12 +8472,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7550,6 +8505,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7562,12 +8520,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7577,9 +8538,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7595,6 +8562,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7610,6 +8580,9 @@ msgstr "Общо време за теÑтване на вÑички подава
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7619,6 +8592,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7637,24 +8613,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7670,6 +8664,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7703,13 +8703,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7739,15 +8742,15 @@ msgstr "Качване на нов файл"
msgid "Upload file"
msgstr "Качване на файл"
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr "щракнете за качване"
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7775,6 +8778,9 @@ msgstr "Използване на глобалната Ви наÑтройка Ð
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7784,10 +8790,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7814,6 +8862,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7847,9 +8904,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7868,6 +8931,36 @@ msgstr "Публичен"
msgid "VisibilityLevel|Unknown"
msgstr "ÐеизвеÑтно"
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "ИÑкате ли да видите данните? Помолете админиÑтратор за доÑтъп."
@@ -7907,6 +9000,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8057,6 +9156,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8075,9 +9177,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8087,9 +9186,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8111,12 +9207,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8138,9 +9240,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr "ТрÑбва да Ñе впишете, за да отбележите проект ÑÑŠÑ Ð·Ð²ÐµÐ·Ð´Ð°"
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8150,6 +9249,12 @@ msgstr ""
msgid "You need permission."
msgstr "Ðуждаете Ñе от разрешение."
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr "ÐÑма да получавате никакви извеÑÑ‚Ð¸Ñ Ð¿Ð¾ е-поща"
@@ -8216,6 +9321,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8237,16 +9345,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "assign yourself"
msgstr ""
@@ -8274,61 +9372,78 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8361,9 +9476,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8386,6 +9498,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8404,13 +9519,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8419,9 +9528,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8452,9 +9558,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8466,9 +9569,6 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8498,25 +9598,17 @@ msgstr[1] "дни"
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
-
msgid "disabled"
msgstr ""
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "enabled"
msgstr ""
@@ -8526,6 +9618,12 @@ msgstr ""
msgid "for this project"
msgstr ""
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -8555,6 +9653,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8783,6 +9884,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8801,6 +9905,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr "нова заÑвка за Ñливане"
@@ -8829,6 +9936,11 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "remaining"
msgstr ""
@@ -8841,6 +9953,11 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "source"
msgstr ""
@@ -8856,6 +9973,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/ca_ES/gitlab.po b/locale/ca_ES/gitlab.po
index 6bfe59669b5..904717e7d03 100644
--- a/locale/ca_ES/gitlab.po
+++ b/locale/ca_ES/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Catalan\n"
"Language: ca_ES\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ca\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:33\n"
+"PO-Revision-Date: 2018-11-19 17:21\n"
msgid " Status"
msgstr ""
@@ -31,6 +31,14 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -46,6 +54,11 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -68,13 +81,13 @@ msgstr[1] ""
msgid "%d layer"
msgid_plural "%d layers"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d capa"
+msgstr[1] "%d capes"
msgid "%d merge request"
msgid_plural "%d merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d petició de fusió"
+msgstr[1] "%d peticions de fusió"
msgid "%d metric"
msgid_plural "%d metrics"
@@ -91,11 +104,6 @@ msgid_plural "%d unstaged changes"
msgstr[0] ""
msgstr[1] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] ""
@@ -104,17 +112,31 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] ""
msgstr[1] ""
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -124,6 +146,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -139,27 +164,16 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr ""
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr ""
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{text} %{files}"
+msgstr[1] "%{text} %{files} fitxers"
msgid "%{text} is available"
msgstr ""
@@ -167,27 +181,13 @@ msgstr ""
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -249,19 +249,19 @@ msgstr[1] ""
msgid "1 role"
msgid_plural "%d roles"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 rol"
+msgstr[1] "%d rols"
msgid "1 user"
msgid_plural "%d users"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 usuari"
+msgstr[1] "%d usuaris"
msgid "1st contribution!"
msgstr ""
msgid "2FA enabled"
-msgstr ""
+msgstr "2FA activat"
msgid "403|Please contact your GitLab administrator to get the permission."
msgstr ""
@@ -273,7 +273,7 @@ msgid "404|Make sure the address is correct and the page hasn't moved."
msgstr ""
msgid "404|Page Not Found"
-msgstr ""
+msgstr "404|No s'ha trobat la pàgina"
msgid "404|Please contact your GitLab administrator if you think this is a mistake."
msgstr ""
@@ -314,6 +314,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr ""
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -327,7 +336,7 @@ msgid "A user with write access to the source branch selected this option"
msgstr ""
msgid "About GitLab"
-msgstr ""
+msgstr "Quant al GitLab"
msgid "About GitLab CE"
msgstr "Quant al GitLab CE"
@@ -342,7 +351,7 @@ msgid "Abuse Reports"
msgstr ""
msgid "Abuse reports"
-msgstr ""
+msgstr "Informes d'abús"
msgid "Accept terms"
msgstr ""
@@ -356,29 +365,26 @@ msgstr ""
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
-msgstr ""
-
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgid "Access expiration date"
msgstr ""
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
msgstr "Compte"
msgid "Account and limit"
-msgstr ""
+msgstr "Compte i límit"
msgid "Active"
-msgstr ""
+msgstr "Actiu"
msgid "Active Sessions"
-msgstr ""
+msgstr "Sessions actives"
msgid "Activity"
-msgstr ""
+msgstr "Activitat"
msgid "Add"
msgstr "Afegeix"
@@ -392,47 +398,71 @@ msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
+msgid "Add Kubernetes cluster"
msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
+msgstr "Afegeix un directori nou"
+
+msgid "Add projects"
msgstr ""
msgid "Add reaction"
+msgstr "Afegeix una reacció"
+
+msgid "Add to review"
msgstr ""
msgid "Add todo"
msgstr ""
msgid "Add user(s) to the group:"
-msgstr ""
+msgstr "Afegeix usuaris al grup:"
msgid "Add users to group"
+msgstr "Afegeix usuaris al grup"
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
msgstr ""
msgid "Additional text"
-msgstr ""
+msgstr "Text addicional"
msgid "Admin Area"
-msgstr ""
+msgstr "Àrea d'administració"
msgid "Admin Overview"
-msgstr ""
+msgstr "Informació general d'administració"
msgid "Admin area"
-msgstr ""
+msgstr "Àrea d'administració"
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -455,9 +485,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -494,11 +521,16 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
-msgstr ""
+msgstr "Configuració avançada"
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
msgid "All"
msgstr ""
@@ -510,11 +542,14 @@ msgid "All features are enabled for blank projects, from templates, or when impo
msgstr ""
msgid "All users"
-msgstr ""
+msgstr "Tots els usuaris"
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -524,6 +559,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -539,6 +580,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -560,7 +604,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -584,6 +628,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -596,6 +646,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -608,6 +661,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -635,6 +691,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -677,12 +736,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr ""
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr "Anònim"
@@ -690,10 +755,10 @@ msgid "Anti-spam verification"
msgstr ""
msgid "Any"
-msgstr ""
+msgstr "Qualsevol"
msgid "Any Label"
-msgstr ""
+msgstr "Qualsevol etiqueta"
msgid "Appearance"
msgstr "Aparença"
@@ -701,27 +766,33 @@ msgstr "Aparença"
msgid "Application"
msgstr "Aplicació"
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
msgstr "Aplicació: %{name}"
msgid "Applications"
-msgstr ""
+msgstr "Aplicacions"
msgid "Apr"
-msgstr ""
+msgstr "abr"
msgid "April"
-msgstr ""
+msgstr "abril"
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -740,6 +811,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -777,7 +851,7 @@ msgid "Assigned Issues"
msgstr ""
msgid "Assigned Merge Requests"
-msgstr ""
+msgstr "Peticions de fusió assignades"
msgid "Assigned to :name"
msgstr ""
@@ -807,7 +881,7 @@ msgid "Aug"
msgstr ""
msgid "August"
-msgstr ""
+msgstr "agost"
msgid "Authentication Log"
msgstr ""
@@ -819,7 +893,7 @@ msgid "Authentication method"
msgstr ""
msgid "Author"
-msgstr ""
+msgstr "Autor"
msgid "Authorization code:"
msgstr ""
@@ -878,6 +952,9 @@ msgstr ""
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -906,7 +983,7 @@ msgid "Average per day: %{average}"
msgstr ""
msgid "Background Color"
-msgstr ""
+msgstr "Color de fons"
msgid "Background Jobs"
msgstr ""
@@ -914,9 +991,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -995,6 +1069,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1285,6 +1368,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1315,9 +1401,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1372,7 +1455,7 @@ msgstr ""
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1399,6 +1482,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1429,6 +1518,9 @@ msgstr ""
msgid "CiStatusLabel|created"
msgstr ""
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr ""
@@ -1447,6 +1539,9 @@ msgstr ""
msgid "CiStatusLabel|skipped"
msgstr ""
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr ""
@@ -1459,6 +1554,9 @@ msgstr ""
msgid "CiStatusText|created"
msgstr ""
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr ""
@@ -1513,10 +1611,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1561,6 +1659,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1573,12 +1674,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1609,10 +1722,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1639,6 +1752,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1675,6 +1794,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1705,9 +1827,6 @@ msgstr ""
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1729,25 +1848,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster details"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster health"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1759,7 +1872,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1768,16 +1881,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1795,9 +1905,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1825,6 +1932,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1837,6 +1947,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1867,9 +1980,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1909,13 +2019,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -1933,6 +2040,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -1951,9 +2061,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -1963,6 +2070,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -1972,12 +2082,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2012,6 +2128,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr ""
@@ -2084,7 +2203,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2093,10 +2212,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2186,6 +2305,9 @@ msgstr ""
msgid "Contribution guide"
msgstr ""
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2219,6 +2341,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2240,15 +2374,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2324,7 +2470,7 @@ msgstr ""
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
+msgid "Create your first page"
msgstr ""
msgid "CreateTag|Tag"
@@ -2375,6 +2521,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -2393,6 +2542,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr ""
@@ -2444,6 +2596,9 @@ msgstr ""
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2456,6 +2611,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr ""
@@ -2465,6 +2635,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2602,6 +2775,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2626,6 +2805,12 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2647,12 +2832,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2668,6 +2868,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2749,7 +2952,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2794,9 +2997,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2809,6 +3009,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2911,7 +3117,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -2944,10 +3150,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3058,6 +3264,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3112,6 +3324,12 @@ msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3121,6 +3339,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3130,6 +3351,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3139,6 +3435,9 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr ""
@@ -3151,9 +3450,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr ""
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr ""
@@ -3169,6 +3477,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3181,7 +3492,7 @@ msgstr ""
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3220,17 +3531,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -3246,6 +3558,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3288,6 +3603,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3462,10 +3780,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3474,6 +3804,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3495,7 +3828,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3507,6 +3840,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3516,19 +3852,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3546,6 +3888,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3558,9 +3906,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3570,9 +3936,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3639,12 +4002,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr ""
-
-msgid "GoToYourFork|Fork"
-msgstr ""
-
msgid "Google Code import"
msgstr ""
@@ -3675,9 +4032,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3687,6 +4056,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3705,13 +4077,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3738,9 +4110,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3798,6 +4167,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3810,19 +4182,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -3864,6 +4236,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4028,6 +4403,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4096,6 +4474,12 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4120,6 +4504,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4135,9 +4549,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4174,7 +4585,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4192,12 +4603,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4270,6 +4675,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
@@ -4281,12 +4689,18 @@ msgstr ""
msgid "Last commit"
msgstr ""
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4335,6 +4749,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4344,6 +4767,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4353,6 +4779,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4362,6 +4791,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4374,9 +4806,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4403,6 +4841,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4448,6 +4889,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4517,13 +4961,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4535,6 +5009,12 @@ msgstr ""
msgid "Median"
msgstr ""
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -4568,6 +5048,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4577,9 +5072,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4589,6 +5081,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4604,6 +5102,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4820,6 +5321,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -4939,6 +5443,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -4948,9 +5458,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -4960,6 +5467,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -4987,6 +5497,9 @@ msgstr ""
msgid "No repository"
msgstr ""
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr ""
@@ -5023,6 +5536,9 @@ msgstr ""
msgid "Not enough data"
msgstr ""
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -5041,6 +5557,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -5113,9 +5641,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5142,9 +5667,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5166,6 +5688,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5190,6 +5715,21 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5256,6 +5796,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5283,13 +5826,13 @@ msgstr ""
msgid "Permissions"
msgstr ""
-msgid "Personal Access Token"
+msgid "Permissions, LFS, 2FA"
msgstr ""
-msgid "Pipeline"
+msgid "Personal Access Token"
msgstr ""
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
+msgid "Pipeline"
msgstr ""
msgid "Pipeline Health"
@@ -5409,15 +5952,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5427,6 +5979,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5454,12 +6012,6 @@ msgstr ""
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5469,12 +6021,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5487,6 +6045,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5499,9 +6060,18 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5547,15 +6117,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5568,39 +6153,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -5610,6 +6276,15 @@ msgstr ""
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5646,6 +6321,9 @@ msgstr ""
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr ""
@@ -5673,6 +6351,9 @@ msgstr ""
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -5700,6 +6381,27 @@ msgstr ""
msgid "ProjectLifecycle|Stage"
msgstr ""
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5742,6 +6444,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5811,9 +6516,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6006,6 +6708,12 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6068,12 +6776,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6083,6 +6800,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6092,18 +6812,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6116,6 +6851,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6149,10 +6887,10 @@ msgstr ""
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6170,9 +6908,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6223,9 +6973,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6235,6 +7000,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6259,6 +7030,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6283,6 +7057,9 @@ msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -6337,15 +7114,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6370,27 +7156,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard"
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6408,9 +7222,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr ""
@@ -6441,6 +7261,9 @@ msgstr ""
msgid "Select target branch"
msgstr ""
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6453,6 +7276,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6477,6 +7303,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6495,7 +7324,10 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
@@ -6507,13 +7339,31 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "Settings"
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
msgstr ""
msgid "Share"
@@ -6525,6 +7375,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6608,12 +7461,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6641,9 +7500,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6656,12 +7521,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -6692,6 +7569,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6722,6 +7602,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6752,6 +7635,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6827,9 +7713,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6842,6 +7740,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6851,6 +7752,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6860,9 +7764,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6875,6 +7785,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -6893,6 +7809,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -6997,6 +7916,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7045,12 +7967,6 @@ msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7099,9 +8015,6 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr ""
@@ -7111,21 +8024,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr ""
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7135,6 +8042,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7144,7 +8054,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7192,10 +8108,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7216,6 +8135,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7255,7 +8177,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7276,6 +8201,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
@@ -7300,6 +8228,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7309,6 +8240,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7336,9 +8273,15 @@ msgstr ""
msgid "Time before an issue starts implementation"
msgstr ""
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr ""
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7529,12 +8472,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7550,6 +8505,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7562,12 +8520,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7577,9 +8538,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7595,6 +8562,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7610,6 +8580,9 @@ msgstr ""
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7619,6 +8592,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7637,24 +8613,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7670,6 +8664,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7703,13 +8703,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7739,15 +8742,15 @@ msgstr ""
msgid "Upload file"
msgstr ""
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr ""
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7775,6 +8778,9 @@ msgstr ""
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7784,10 +8790,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7814,6 +8862,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7847,9 +8904,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7868,6 +8931,36 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -7907,6 +9000,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8057,6 +9156,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8075,9 +9177,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8087,9 +9186,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8111,12 +9207,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8138,9 +9240,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr ""
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8150,6 +9249,12 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr ""
@@ -8216,6 +9321,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8237,16 +9345,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "assign yourself"
msgstr ""
@@ -8274,61 +9372,78 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8361,9 +9476,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8386,6 +9498,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8404,13 +9519,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8419,9 +9528,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8452,9 +9558,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8466,9 +9569,6 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8498,25 +9598,17 @@ msgstr[1] ""
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
-
msgid "disabled"
msgstr ""
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "enabled"
msgstr ""
@@ -8526,6 +9618,12 @@ msgstr ""
msgid "for this project"
msgstr ""
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -8555,6 +9653,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8783,6 +9884,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8801,6 +9905,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr ""
@@ -8829,6 +9936,11 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "remaining"
msgstr ""
@@ -8841,6 +9953,11 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "source"
msgstr ""
@@ -8856,6 +9973,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/cs_CZ/gitlab.po b/locale/cs_CZ/gitlab.po
index 0e349d2b12a..9e25b8de9f4 100644
--- a/locale/cs_CZ/gitlab.po
+++ b/locale/cs_CZ/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Czech\n"
"Language: cs_CZ\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: cs\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:32\n"
+"PO-Revision-Date: 2018-11-19 17:22\n"
msgid " Status"
msgstr ""
@@ -35,6 +35,16 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -56,6 +66,13 @@ msgstr[1] "%d commity pozadu"
msgstr[2] "%d commitů pozadu"
msgstr[3] "%d commitů pozadu"
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -119,13 +136,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] "%s další commit byl vynechán, aby se předešlo problémům s výkonem."
@@ -136,12 +146,21 @@ msgstr[3] "%s dalších commitů bylo vynecháno, aby se předešlo problémům
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] ""
@@ -149,6 +168,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -158,6 +184,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -173,25 +202,12 @@ msgstr "%{nip_domain} lze použít jako alternativu vlastní domény."
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr ""
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr ""
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr "%{percent}%% dokonÄeno"
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -205,35 +221,13 @@ msgstr "%{text} je k dispozici"
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -382,6 +376,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr ""
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -424,13 +427,10 @@ msgstr ""
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
+msgid "Access expiration date"
msgstr ""
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr ""
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -460,27 +460,48 @@ msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
+msgid "Add Kubernetes cluster"
msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "Přidat reakci"
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr "Přidat úkol"
@@ -490,6 +511,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr "DodateÄný text"
@@ -523,9 +547,6 @@ msgstr "Zastavení úloh selhalo"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "Chystáte se zastavit všechny úlohy. To způsobí přerušení všech aktuálně spuštěných úloh."
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -562,12 +583,19 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr ""
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "All"
msgstr ""
@@ -583,6 +611,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -592,6 +623,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -607,6 +644,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -628,7 +668,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -652,6 +692,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -664,6 +710,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -676,6 +725,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -703,6 +755,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -745,12 +800,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr ""
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -769,7 +830,7 @@ msgstr "Vzhled"
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -787,9 +848,15 @@ msgstr "Duben"
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -808,6 +875,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -946,6 +1016,9 @@ msgstr ""
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -982,9 +1055,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -1063,6 +1133,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1355,6 +1434,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1385,9 +1467,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1442,7 +1521,7 @@ msgstr ""
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1469,6 +1548,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1499,6 +1584,9 @@ msgstr ""
msgid "CiStatusLabel|created"
msgstr ""
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr ""
@@ -1517,6 +1605,9 @@ msgstr ""
msgid "CiStatusLabel|skipped"
msgstr ""
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr ""
@@ -1529,6 +1620,9 @@ msgstr ""
msgid "CiStatusText|created"
msgstr ""
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr ""
@@ -1583,10 +1677,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1631,6 +1725,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1643,12 +1740,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1679,10 +1788,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1709,6 +1818,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1745,6 +1860,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1775,9 +1893,6 @@ msgstr ""
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1799,25 +1914,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster details"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster health"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1829,7 +1938,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1838,16 +1947,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1865,9 +1971,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1895,6 +1998,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1907,6 +2013,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1937,9 +2046,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1979,13 +2085,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -2003,6 +2106,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2021,9 +2127,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -2033,6 +2136,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -2042,12 +2148,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2086,6 +2198,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr ""
@@ -2158,7 +2273,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2167,10 +2282,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2260,6 +2375,9 @@ msgstr ""
msgid "Contribution guide"
msgstr ""
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2293,6 +2411,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2314,15 +2444,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2398,7 +2540,7 @@ msgstr ""
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
+msgid "Create your first page"
msgstr ""
msgid "CreateTag|Tag"
@@ -2449,6 +2591,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -2467,6 +2612,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr ""
@@ -2518,6 +2666,9 @@ msgstr ""
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2530,6 +2681,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr ""
@@ -2539,6 +2705,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2678,6 +2847,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2702,6 +2877,12 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2723,12 +2904,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2744,6 +2940,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2825,7 +3024,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2870,9 +3069,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2885,6 +3081,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2987,7 +3189,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -3020,10 +3222,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3134,6 +3336,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3188,6 +3396,12 @@ msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3197,6 +3411,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3206,6 +3423,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3215,6 +3507,9 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr ""
@@ -3227,9 +3522,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr ""
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr ""
@@ -3245,6 +3549,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3257,7 +3564,7 @@ msgstr ""
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3296,19 +3603,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -3324,6 +3630,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3366,6 +3675,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3540,10 +3852,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3552,6 +3876,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3573,7 +3900,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3585,6 +3912,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3594,19 +3924,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3624,6 +3960,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3636,9 +3978,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3648,9 +4008,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3717,12 +4074,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr ""
-
-msgid "GoToYourFork|Fork"
-msgstr ""
-
msgid "Google Code import"
msgstr ""
@@ -3753,9 +4104,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3765,6 +4128,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3783,13 +4149,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3816,9 +4182,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3876,6 +4239,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3888,19 +4254,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -3942,6 +4308,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4108,6 +4477,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4178,6 +4550,12 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4202,6 +4580,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4217,9 +4625,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4256,7 +4661,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4274,12 +4679,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4352,6 +4751,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
@@ -4365,12 +4767,18 @@ msgstr ""
msgid "Last commit"
msgstr ""
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4419,6 +4827,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4428,6 +4845,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4437,6 +4857,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4446,6 +4869,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4458,9 +4884,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4489,6 +4921,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4534,6 +4969,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4603,13 +5041,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4621,6 +5089,12 @@ msgstr ""
msgid "Median"
msgstr ""
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -4654,6 +5128,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4663,9 +5152,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4675,6 +5161,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4690,6 +5182,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4906,6 +5401,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -5027,6 +5525,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -5036,9 +5540,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -5048,6 +5549,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5075,6 +5579,9 @@ msgstr ""
msgid "No repository"
msgstr ""
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr ""
@@ -5111,6 +5618,9 @@ msgstr ""
msgid "Not enough data"
msgstr ""
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -5129,6 +5639,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -5201,9 +5723,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5232,9 +5751,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5256,6 +5772,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5280,6 +5799,21 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5346,6 +5880,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5373,13 +5910,13 @@ msgstr ""
msgid "Permissions"
msgstr ""
-msgid "Personal Access Token"
+msgid "Permissions, LFS, 2FA"
msgstr ""
-msgid "Pipeline"
+msgid "Personal Access Token"
msgstr ""
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
+msgid "Pipeline"
msgstr ""
msgid "Pipeline Health"
@@ -5499,15 +6036,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5517,6 +6063,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5544,12 +6096,6 @@ msgstr ""
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5559,12 +6105,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5577,6 +6129,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5589,9 +6144,18 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5637,15 +6201,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5658,39 +6237,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -5700,6 +6360,15 @@ msgstr ""
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5736,6 +6405,9 @@ msgstr ""
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr ""
@@ -5763,6 +6435,9 @@ msgstr ""
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -5790,6 +6465,27 @@ msgstr ""
msgid "ProjectLifecycle|Stage"
msgstr ""
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5832,6 +6528,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5901,9 +6600,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6096,6 +6792,12 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6160,12 +6862,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6175,6 +6886,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6184,18 +6898,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6208,6 +6937,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6241,10 +6973,10 @@ msgstr ""
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6262,9 +6994,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6317,9 +7061,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6329,6 +7088,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6353,6 +7118,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6377,6 +7145,9 @@ msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -6431,15 +7202,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6464,29 +7244,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard"
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6504,9 +7310,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr ""
@@ -6537,6 +7349,9 @@ msgstr ""
msgid "Select target branch"
msgstr ""
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6549,6 +7364,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6573,6 +7391,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6591,7 +7412,10 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
@@ -6603,13 +7427,31 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "Settings"
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
msgstr ""
msgid "Share"
@@ -6621,6 +7463,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6706,12 +7551,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6739,9 +7590,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6754,12 +7611,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -6790,6 +7659,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6820,6 +7692,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6850,6 +7725,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6925,9 +7803,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6940,6 +7830,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6949,6 +7842,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6958,9 +7854,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6973,6 +7875,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -6991,6 +7899,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -7097,6 +8008,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7145,12 +8059,6 @@ msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7199,9 +8107,6 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr ""
@@ -7211,21 +8116,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr ""
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7235,6 +8134,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7244,7 +8146,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7292,10 +8200,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7316,6 +8227,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7355,7 +8269,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7376,6 +8293,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
@@ -7400,6 +8320,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7409,6 +8332,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7436,9 +8365,15 @@ msgstr ""
msgid "Time before an issue starts implementation"
msgstr ""
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr ""
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7633,12 +8568,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7654,6 +8601,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7666,12 +8616,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7681,9 +8634,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7699,6 +8658,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7714,6 +8676,9 @@ msgstr ""
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7723,6 +8688,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7741,24 +8709,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7774,6 +8760,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7807,13 +8799,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7843,15 +8838,15 @@ msgstr ""
msgid "Upload file"
msgstr ""
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr ""
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7879,6 +8874,9 @@ msgstr ""
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7888,10 +8886,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7918,6 +8958,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7951,9 +9000,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7972,6 +9027,36 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -8011,6 +9096,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8161,6 +9252,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8179,9 +9273,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8191,9 +9282,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8215,12 +9303,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8242,9 +9336,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr ""
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8254,6 +9345,12 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr ""
@@ -8320,6 +9417,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8341,20 +9441,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "assign yourself"
msgstr ""
@@ -8382,61 +9468,86 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8469,9 +9580,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8498,6 +9606,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8516,13 +9627,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8531,9 +9636,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8564,9 +9666,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8580,9 +9679,6 @@ msgstr[3] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8614,36 +9710,32 @@ msgstr[3] ""
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "disabled"
+msgstr ""
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "detected no vulnerabilities"
-msgstr ""
-
-msgid "disabled"
+msgid "enabled"
msgstr ""
-msgid "done"
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
-msgid "enabled"
+msgid "for this project"
msgstr ""
-msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgid "from"
msgstr ""
-msgid "for this project"
+msgid "help"
msgstr ""
msgid "here"
@@ -8677,6 +9769,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8911,6 +10006,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8929,6 +10027,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr ""
@@ -8961,6 +10062,13 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "remaining"
msgstr ""
@@ -8973,6 +10081,13 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "source"
msgstr ""
@@ -8988,6 +10103,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/cy_GB/gitlab.po b/locale/cy_GB/gitlab.po
new file mode 100644
index 00000000000..8d06e64d3e0
--- /dev/null
+++ b/locale/cy_GB/gitlab.po
@@ -0,0 +1,10259 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
+"Language-Team: Welsh\n"
+"Language: cy_GB\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=6; plural=(n == 0) ? 0 : ((n == 1) ? 1 : ((n == 2) ? 2 : ((n == 3) ? 3 : ((n == 6) ? 4 : 5))));\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: cy\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"PO-Revision-Date: 2018-11-19 17:23\n"
+
+msgid " Status"
+msgstr ""
+
+msgid " and"
+msgstr ""
+
+msgid " degraded on %d point"
+msgid_plural " degraded on %d points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid " improved on %d point"
+msgid_plural " improved on %d points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d changed file"
+msgid_plural "%d changed files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d failed test result"
+msgid_plural "%d failed test results"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d staged change"
+msgid_plural "%d staged changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%d unstaged change"
+msgid_plural "%d unstaged changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_timeago}"
+msgstr ""
+
+msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgstr ""
+
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{loadingIcon} Started"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+msgid "%{nip_domain} can be used as an alternative to a custom domain."
+msgstr ""
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr ""
+
+msgid "%{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
+
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid "- Runner is active and can process any new jobs"
+msgstr ""
+
+msgid "- Runner is paused and will not receive any new jobs"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "1 %{type} addition"
+msgid_plural "%{count} %{type} additions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "1 %{type} modification"
+msgid_plural "%{count} %{type} modifications"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "1 closed issue"
+msgid_plural "%d closed issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "1 closed merge request"
+msgid_plural "%d closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "1 merged merge request"
+msgid_plural "%d merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "1 open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "1 open merge request"
+msgid_plural "%d open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "1 user"
+msgid_plural "%d users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "2FA enabled"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get the permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
+msgstr ""
+
+msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
+msgstr ""
+
+msgid "<strong>%{group_name}</strong> group members"
+msgstr ""
+
+msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
+msgstr ""
+
+msgid "<strong>Removes</strong> source branch"
+msgstr ""
+
+msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
+msgstr ""
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
+msgstr ""
+
+msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About GitLab CE"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Accepted MR"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied! Please verify you can add deploy keys to this repository."
+msgstr ""
+
+msgid "Access expiration date"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add Changelog"
+msgstr ""
+
+msgid "Add Contribution guide"
+msgstr ""
+
+msgid "Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add Readme"
+msgstr ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add projects"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add todo"
+msgstr ""
+
+msgid "Add user(s) to the group:"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Admin Area"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "Admin area"
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminProjects|Delete project"
+msgstr ""
+
+msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
+
+msgid "Advanced settings"
+msgstr ""
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "All"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr ""
+
+msgid "All users"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch."
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts"
+msgstr ""
+
+msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
+msgstr ""
+
+msgid "Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An error accured whilst committing your changes."
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error occured creating the new branch."
+msgstr ""
+
+msgid "An error occured whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occured whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occured whilst loading all the files."
+msgstr ""
+
+msgid "An error occured whilst loading the file content."
+msgstr ""
+
+msgid "An error occured whilst loading the file."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request."
+msgstr ""
+
+msgid "An error occured whilst loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
+msgstr ""
+
+msgid "An error occurred while adding approver"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while fetching markdown preview"
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching sidebar data"
+msgstr ""
+
+msgid "An error occurred while fetching stages."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the pipeline."
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while importing project: %{details}"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while removing approver"
+msgstr ""
+
+msgid "An error occurred while rendering KaTeX"
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while retrieving calendar activity"
+msgstr ""
+
+msgid "An error occurred while retrieving diff"
+msgstr ""
+
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
+msgstr ""
+
+msgid "An error occurred while subscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while unsubscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any Label"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read-only"
+msgstr ""
+
+msgid "Archived projects"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Artifact ID"
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer to set up a group Runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned Merge Requests"
+msgstr ""
+
+msgid "Assigned to :name"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assignee"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee lists show all issues assigned to the selected user."
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto DevOps, runners and job artifacts"
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
+msgstr ""
+
+msgid "Auto-cancel redundant, pending pipelines"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
+msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
+msgstr ""
+
+msgid "AutoDevOps|add a Kubernetes cluster"
+msgstr ""
+
+msgid "AutoDevOps|enable Auto DevOps"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available group Runners : %{runners}"
+msgstr ""
+
+msgid "Available group Runners : %{runners}."
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|A new badge was added."
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Delete badge"
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|No badge image"
+msgstr ""
+
+msgid "Badges|No image to preview"
+msgstr ""
+
+msgid "Badges|Please fill in a valid URL"
+msgstr ""
+
+msgid "Badges|Project Badge"
+msgstr ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|The badge was saved."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "Badges|e.g. %{exampleUrl}"
+msgstr ""
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are examples of regex for existing tools:"
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
+msgstr ""
+
+msgid "BillingPlans|Current plan"
+msgstr ""
+
+msgid "BillingPlans|Customer Support"
+msgstr ""
+
+msgid "BillingPlans|Downgrade"
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
+msgstr ""
+
+msgid "BillingPlans|Manage plan"
+msgstr ""
+
+msgid "BillingPlans|Please contact %{customer_support_link} in that case."
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Upgrade"
+msgstr ""
+
+msgid "BillingPlans|You are currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
+msgstr ""
+
+msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
+msgstr ""
+
+msgid "BillingPlans|features"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|paid annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch (%{branch_count})"
+msgid_plural "Branches (%{branch_count})"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch has changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "BranchSwitcherPlaceholder|Search branches"
+msgstr ""
+
+msgid "BranchSwitcherTitle|Switch branch"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cant find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch '%{branch_name}'?"
+msgstr ""
+
+msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+msgstr ""
+
+msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Branches|Only a project maintainer or owner can delete a protected branch"
+msgstr ""
+
+msgid "Branches|Overview"
+msgstr ""
+
+msgid "Branches|Protected branches can be managed in %{project_settings_link}."
+msgstr ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Sort by"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+msgstr ""
+
+msgid "Branches|The default branch cannot be deleted"
+msgstr ""
+
+msgid "Branches|This branch hasn’t been merged into %{default_branch}."
+msgstr ""
+
+msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
+msgid "Branches|To confirm, type %{branch_name_confirmation}:"
+msgstr ""
+
+msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
+msgstr ""
+
+msgid "Branches|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|project settings"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "Built-In"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CI / CD"
+msgstr ""
+
+msgid "CI / CD Settings"
+msgstr ""
+
+msgid "CI will run using the credentials assigned above."
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD for external repo"
+msgstr ""
+
+msgid "CI/CD settings"
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Deployment strategy needs a domain name to work correctly."
+msgstr ""
+
+msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|Learn more about Auto DevOps"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "Callback URL"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Certificate fingerprint"
+msgstr ""
+
+msgid "Change Weight"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates."
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "Changelog"
+msgstr ""
+
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
+msgstr ""
+
+msgid "Choose <strong>Next</strong> at the bottom of the page."
+msgstr ""
+
+msgid "Choose File ..."
+msgstr ""
+
+msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
+msgstr ""
+
+msgid "Choose file..."
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose which groups you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose which repositories you want to import."
+msgstr ""
+
+msgid "Choose which shards you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Error occured while saving variables"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "CiVariable|Validation failed"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
+msgstr ""
+
+msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
+msgstr ""
+
+msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
+msgstr ""
+
+msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
+msgstr ""
+
+msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Client authentication certificate"
+msgstr ""
+
+msgid "Client authentication key"
+msgstr ""
+
+msgid "Client authentication key password"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
+msgstr ""
+
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgstr ""
+
+msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|Applications"
+msgstr ""
+
+msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Token"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Helm Tiller"
+msgstr ""
+
+msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
+msgstr ""
+
+msgid "ClusterIntegration|Hide"
+msgstr ""
+
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|In order to show the health of the cluster, we'll need to provision your cluster with Prometheus to collect the required data."
+msgstr ""
+
+msgid "ClusterIntegration|Ingress"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress IP Address"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
+msgstr ""
+
+msgid "ClusterIntegration|Install"
+msgstr ""
+
+msgid "ClusterIntegration|Install Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Installed"
+msgstr ""
+
+msgid "ClusterIntegration|Installing"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
+msgstr ""
+
+msgid "ClusterIntegration|Integration status"
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster health"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
+msgstr ""
+
+msgid "ClusterIntegration|More information"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Note:"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Service token"
+msgstr ""
+
+msgid "ClusterIntegration|Show"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Token"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|check the pricing here"
+msgstr ""
+
+msgid "ClusterIntegration|documentation"
+msgstr ""
+
+msgid "ClusterIntegration|help page"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|properly configured"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "Code owners"
+msgstr ""
+
+msgid "Cohorts"
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & resolve discussion"
+msgstr ""
+
+msgid "Comment & unresolve discussion"
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "Commit (%{commit_count})"
+msgid_plural "Commits (%{commit_count})"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit duration in minutes for last 30 commits"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|Commit: %{commitText}"
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Commit…"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|Compare"
+msgstr ""
+
+msgid "CompareBranches|Source"
+msgstr ""
+
+msgid "CompareBranches|Target"
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Tracing"
+msgstr ""
+
+msgid "Configure automatic git checks and housekeeping on repositories."
+msgstr ""
+
+msgid "Configure limits for web and API requests."
+msgstr ""
+
+msgid "Configure push mirrors."
+msgstr ""
+
+msgid "Configure storage path settings."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the way a user creates a new account."
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Created"
+msgstr ""
+
+msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
+msgstr ""
+
+msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
+msgstr ""
+
+msgid "ContainerRegistry|How to use the Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Learn more about"
+msgstr ""
+
+msgid "ContainerRegistry|No tags in Container Registry for this container image."
+msgstr ""
+
+msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgstr ""
+
+msgid "ContainerRegistry|Size"
+msgstr ""
+
+msgid "ContainerRegistry|Tag"
+msgstr ""
+
+msgid "ContainerRegistry|Tag ID"
+msgstr ""
+
+msgid "ContainerRegistry|Use different image names"
+msgstr ""
+
+msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
+msgstr ""
+
+msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution guide"
+msgstr ""
+
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "ContributorsPage|%{startDate} – %{endDate}"
+msgstr ""
+
+msgid "ContributorsPage|Building repository graph."
+msgstr ""
+
+msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Control the display of third party offers."
+msgstr ""
+
+msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of repository backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of verification operations for this Geo node"
+msgstr ""
+
+msgid "ConvDev Index"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key to clipboard"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy branch name to clipboard"
+msgstr ""
+
+msgid "Copy command to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Copy file path to clipboard"
+msgstr ""
+
+msgid "Copy incoming email address to clipboard"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
+msgid "Copy reference to clipboard"
+msgstr ""
+
+msgid "Copy secret to clipboard"
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token to clipboard"
+msgstr ""
+
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new branch and merge request"
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create branch"
+msgstr ""
+
+msgid "Create commit"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty repository"
+msgstr ""
+
+msgid "Create epic"
+msgstr ""
+
+msgid "Create file"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created on"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron syntax"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current node"
+msgstr ""
+
+msgid "CurrentUser|Profile"
+msgstr ""
+
+msgid "CurrentUser|Settings"
+msgstr ""
+
+msgid "Custom"
+msgstr ""
+
+msgid "Custom CI config path"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Production"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Default Branch"
+msgstr ""
+
+msgid "Default classification label"
+msgstr ""
+
+msgid "Default: Directly import the Google Code email address or username"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete Package"
+msgstr ""
+
+msgid "Delete Snippet"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete list"
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployKeys|Write access allowed"
+msgstr ""
+
+msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Add a deploy token"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository"
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Copy username to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Deploy Tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|This project has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "DeployTokens|Use this username as a login."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|You are about to revoke"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group Runners"
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "Discard review"
+msgstr ""
+
+msgid "Discover GitLab Geo."
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss Cycle Analytics introduction box"
+msgstr ""
+
+msgid "Dismiss Merge Request promotion"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Each Runner can be in one of the following states:"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Elasticsearch"
+msgstr ""
+
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable SAML authentication for this group"
+msgstr ""
+
+msgid "Enable Sentry for error reporting and logging."
+msgstr ""
+
+msgid "Enable and configure InfluxDB metrics."
+msgstr ""
+
+msgid "Enable and configure Prometheus metrics."
+msgstr ""
+
+msgid "Enable classification control using an external service"
+msgstr ""
+
+msgid "Enable for this project"
+msgstr ""
+
+msgid "Enable group Runners"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable reCAPTCHA or Akismet and set IP limits."
+msgstr ""
+
+msgid "Enable the Performance Bar for a given group."
+msgstr ""
+
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter the issue description"
+msgstr ""
+
+msgid "Enter the issue title"
+msgstr ""
+
+msgid "Enter the merge request description"
+msgstr ""
+
+msgid "Enter the merge request title"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No pod name has been specified"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod logs from"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Read more about environments"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epic will be removed! Are you sure?"
+msgstr ""
+
+msgid "Epics"
+msgstr ""
+
+msgid "Epics Roadmap"
+msgstr ""
+
+msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
+msgstr ""
+
+msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgstr ""
+
+msgid "Epics|How can I solve this?"
+msgstr ""
+
+msgid "Epics|More information"
+msgstr ""
+
+msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+msgstr ""
+
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr ""
+
+msgid "Epics|due"
+msgstr ""
+
+msgid "Epics|start"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Reporting and Logging"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error fetching contributors data."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching usage ping data."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error updating status for all todos."
+msgstr ""
+
+msgid "Error updating todo status."
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "Every day (at 4:00am)"
+msgstr ""
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr ""
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
+msgid "Explore"
+msgstr ""
+
+msgid "Explore GitLab"
+msgstr ""
+
+msgid "Explore Groups"
+msgstr ""
+
+msgid "Explore groups"
+msgstr ""
+
+msgid "Explore projects"
+msgstr ""
+
+msgid "Explore public groups"
+msgstr ""
+
+msgid "External Classification Policy Authorization"
+msgstr ""
+
+msgid "External authentication"
+msgstr ""
+
+msgid "External authorization denied access to this project"
+msgstr ""
+
+msgid "External authorization request timeout"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification Label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to remove issue from board, please try again."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to update issues, please try again."
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fields on this page are now uneditable, you can configure"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Files (%{human_size})"
+msgstr ""
+
+msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
+msgid "Filter by commit message"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Find the downloaded ZIP file and decompress it."
+msgstr ""
+
+msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish review"
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "FirstPushedBy|First"
+msgstr ""
+
+msgid "FirstPushedBy|pushed by"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Follow the steps below to export your Google Code project data."
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Format"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
+msgid "From %{provider_title}"
+msgstr ""
+
+msgid "From Bitbucket"
+msgstr ""
+
+msgid "From Bitbucket Server"
+msgstr ""
+
+msgid "From FogBugz"
+msgstr ""
+
+msgid "From GitLab.com"
+msgstr ""
+
+msgid "From Google Code"
+msgstr ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "From milestones:"
+msgstr ""
+
+msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Nodes"
+msgstr ""
+
+msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is failing or broken."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
+msgstr ""
+
+msgid "GeoNodes|Checksummed"
+msgstr ""
+
+msgid "GeoNodes|Data is out of date from %{timeago}"
+msgstr ""
+
+msgid "GeoNodes|Data replication lag"
+msgstr ""
+
+msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "GeoNodes|Failed"
+msgstr ""
+
+msgid "GeoNodes|Full"
+msgstr ""
+
+msgid "GeoNodes|GitLab version"
+msgstr ""
+
+msgid "GeoNodes|GitLab version does not match the primary node version"
+msgstr ""
+
+msgid "GeoNodes|Health status"
+msgstr ""
+
+msgid "GeoNodes|Last event ID processed by cursor"
+msgstr ""
+
+msgid "GeoNodes|Last event ID seen from primary"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository verification"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki verification"
+msgstr ""
+
+msgid "GeoNodes|Loading nodes"
+msgstr ""
+
+msgid "GeoNodes|Local LFS objects"
+msgstr ""
+
+msgid "GeoNodes|Local attachments"
+msgstr ""
+
+msgid "GeoNodes|Local job artifacts"
+msgstr ""
+
+msgid "GeoNodes|New node"
+msgstr ""
+
+msgid "GeoNodes|Node Authentication was successfully repaired."
+msgstr ""
+
+msgid "GeoNodes|Node was successfully removed."
+msgstr ""
+
+msgid "GeoNodes|Not checksummed"
+msgstr ""
+
+msgid "GeoNodes|Out of sync"
+msgstr ""
+
+msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Replication slot WAL"
+msgstr ""
+
+msgid "GeoNodes|Replication slots"
+msgstr ""
+
+msgid "GeoNodes|Repositories"
+msgstr ""
+
+msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Repositories verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Repository verification progress"
+msgstr ""
+
+msgid "GeoNodes|Selective"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while changing node status"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while fetching nodes"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while removing node"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while repairing node"
+msgstr ""
+
+msgid "GeoNodes|Storage config"
+msgstr ""
+
+msgid "GeoNodes|Sync settings"
+msgstr ""
+
+msgid "GeoNodes|Synced"
+msgstr ""
+
+msgid "GeoNodes|Unused slots"
+msgstr ""
+
+msgid "GeoNodes|Unverified"
+msgstr ""
+
+msgid "GeoNodes|Used slots"
+msgstr ""
+
+msgid "GeoNodes|Verified"
+msgstr ""
+
+msgid "GeoNodes|Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Wiki verification progress"
+msgstr ""
+
+msgid "GeoNodes|Wikis"
+msgstr ""
+
+msgid "GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for forced re-download"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-check"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|All"
+msgstr ""
+
+msgid "Geo|All projects"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|File sync capacity"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Groups to synchronize"
+msgstr ""
+
+msgid "Geo|In sync"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|Not synced yet"
+msgstr ""
+
+msgid "Geo|Pending"
+msgstr ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Recheck"
+msgstr ""
+
+msgid "Geo|Recheck all projects"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Repository sync capacity"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all projects"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Select groups to replicate."
+msgstr ""
+
+msgid "Geo|Shards to synchronize"
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
+msgid "Geo|Unknown state"
+msgstr ""
+
+msgid "Geo|Verification capacity"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|You need a different license to use Geo replication"
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Git"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git strategy for pipelines"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitLab CI Linter has been moved"
+msgstr ""
+
+msgid "GitLab Geo"
+msgstr ""
+
+msgid "GitLab Group Runners can execute code for all the projects in this group."
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab single sign on URL"
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLab’s issue tracker"
+msgstr ""
+
+msgid "Gitaly"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go to"
+msgstr ""
+
+msgid "Go to %{link_to_google_takeout}."
+msgstr ""
+
+msgid "Google Code import"
+msgstr ""
+
+msgid "Google Takeout"
+msgstr ""
+
+msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group CI/CD settings"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group Runners"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group details"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group maintainers can register group runners in the %{link}"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Loading roadmap"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|Until %{dateWord}"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Customize your group badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about badges."
+msgstr ""
+
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+msgstr ""
+
+msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
+msgstr ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Create a project in this group."
+msgstr ""
+
+msgid "GroupsTree|Create a subgroup in this group."
+msgstr ""
+
+msgid "GroupsTree|Edit group"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave this group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Have your users email"
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help page"
+msgstr ""
+
+msgid "Help page text and support page url."
+msgstr ""
+
+msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "Hide whitespace changes"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Client side evaluation"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Open in file view"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "Identity provider single sign on URL"
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr ""
+
+msgid "If disabled, the access level will depend on the user's permissions in the project."
+msgstr ""
+
+msgid "If enabled"
+msgstr ""
+
+msgid "If enabled, access to projects will be validated on an external service using their classification label."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you already have files you can push them using the %{link_to_cli} below."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import all compatible projects"
+msgstr ""
+
+msgid "Import all projects"
+msgstr ""
+
+msgid "Import all repositories"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import projects from Google Code"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "Improve Issue boards with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
+msgid "In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "Incompatible Project"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input your repository URL"
+msgstr ""
+
+msgid "Install GitLab Runner"
+msgstr ""
+
+msgid "Install Runner on Kubernetes"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "Instance Statistics"
+msgstr ""
+
+msgid "Instance Statistics visibility"
+msgstr ""
+
+msgid "Instance does not support multiple Kubernetes clusters"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations Settings"
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Cycle Analytics"
+msgstr ""
+
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue board focus mode"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Job"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed in"
+msgstr ""
+
+msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration was not removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes configured"
+msgstr ""
+
+msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label lists show all issues with the selected label."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{name}"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
+msgstr ""
+
+msgid "Learn more about Kubernetes"
+msgstr ""
+
+msgid "Learn more about protected branches"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
+msgid "LicenseManagement|Approve license"
+msgstr ""
+
+msgid "LicenseManagement|Approve license?"
+msgstr ""
+
+msgid "LicenseManagement|Approved"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license?"
+msgstr ""
+
+msgid "LicenseManagement|Blacklisted"
+msgstr ""
+
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
+msgid "LicenseManagement|License"
+msgstr ""
+
+msgid "LicenseManagement|License Management"
+msgstr ""
+
+msgid "LicenseManagement|License details"
+msgstr ""
+
+msgid "LicenseManagement|License name"
+msgstr ""
+
+msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
+msgstr ""
+
+msgid "LicenseManagement|Packages"
+msgstr ""
+
+msgid "LicenseManagement|Remove license"
+msgstr ""
+
+msgid "LicenseManagement|Remove license?"
+msgstr ""
+
+msgid "LicenseManagement|Submit"
+msgstr ""
+
+msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
+msgstr ""
+
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseManagement|URL"
+msgstr ""
+
+msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "LinkedIn"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "List Your Gitea Repositories"
+msgstr ""
+
+msgid "List available repositories"
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "List your GitHub repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked to current projects"
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make sure you're logged into the account that owns the projects you'd like to import."
+msgstr ""
+
+msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
+msgstr ""
+
+msgid "Manage Web IDE features"
+msgstr ""
+
+msgid "Manage access"
+msgstr ""
+
+msgid "Manage all notifications"
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a full email address"
+msgstr ""
+
+msgid "Map a Google Code user to a full name"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark todo as done"
+msgstr ""
+
+msgid "Markdown enabled"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
+msgid "Maven Metadata"
+msgstr ""
+
+msgid "Maven package"
+msgstr ""
+
+msgid "Max access level"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Median"
+msgstr ""
+
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Request:"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge requests"
+msgstr ""
+
+msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
+msgid "MergeRequests|Resolve this discussion in a new issue"
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|Toggle comments for this file"
+msgstr ""
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr ""
+
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Influx"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics|Business"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgstr ""
+
+msgid "Metrics|Environment"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgstr ""
+
+msgid "Metrics|Learn about environments"
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|Name"
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|No deployed environments"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|Query"
+msgstr ""
+
+msgid "Metrics|Response"
+msgstr ""
+
+msgid "Metrics|System"
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|Type"
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
+msgid "Milestone"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Mirror a repository"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror user"
+msgstr ""
+
+msgid "Mirrored repositories"
+msgstr ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
+msgid "Modal|Cancel"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More actions"
+msgstr ""
+
+msgid "More info"
+msgstr ""
+
+msgid "More information"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Multiple issue boards"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name your individual key via a title"
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Snippets"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No Label"
+msgstr ""
+
+msgid "No assignee"
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No container images stored for this project. Add one by following the instructions above."
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No issues for the selected time period."
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No merge requests for the selected time period."
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No packages stored for this project."
+msgstr ""
+
+msgid "No prioritised labels with such name or description"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No pushes for the selected time period."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No, directly import the existing email addresses and usernames."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "Not all comments are displayed because you're comparing two versions of the diff."
+msgstr ""
+
+msgid "Not all comments are displayed because you're viewing an old version of the diff."
+msgstr ""
+
+msgid "Not allowed to merge"
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not enough data"
+msgstr ""
+
+msgid "Not now"
+msgstr ""
+
+msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "Only admins"
+msgstr ""
+
+msgid "Only comments from the following commit are shown below"
+msgstr ""
+
+msgid "Only mirror protected branches"
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open in Xcode"
+msgstr ""
+
+msgid "Open projects"
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open source software to collaborate on code"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened MR"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Otherwise it is recommended you start with one of the options below."
+msgstr ""
+
+msgid "Outbound requests"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Package information"
+msgstr ""
+
+msgid "Package was removed"
+msgstr ""
+
+msgid "Packages"
+msgstr ""
+
+msgid "Pages"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
+
+msgid "Path, transfer, remove"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Paused Runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "Per job. If a job passes this threshold, it will be marked as failed"
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, or removing the group."
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline Health"
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline quota"
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines for last month"
+msgstr ""
+
+msgid "Pipelines for last week"
+msgstr ""
+
+msgid "Pipelines for last year"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|CI Lint"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgstr ""
+
+msgid "Pipelines|Get started with Pipelines"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|There are currently no %{scope} pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+msgstr ""
+
+msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Create for"
+msgstr ""
+
+msgid "Pipeline|Create pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Existing branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Search branches"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|all"
+msgstr ""
+
+msgid "Pipeline|success"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Please accept the Terms of Service before continuing."
+msgstr ""
+
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please solve the reCAPTCHA"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences|Navigation theme"
+msgstr ""
+
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Private - Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|Add status emoji"
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
+msgid "Profiles|Clear status"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Delete Account"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Delete your account?"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Website"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project avatar in repository: %{link}"
+msgstr ""
+
+msgid "Project details"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectLifecycle|Stage"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Customize your project badges."
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Learn more about badges."
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
+msgstr ""
+
+msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "PrometheusAlerts|Add alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Edit alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error creating alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error deleting alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error fetching alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error saving alert"
+msgstr ""
+
+msgid "PrometheusAlerts|No alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Operator"
+msgstr ""
+
+msgid "PrometheusAlerts|Threshold"
+msgstr ""
+
+msgid "PrometheusDashboard|Time"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration"
+msgstr ""
+
+msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
+msgstr ""
+
+msgid "PrometheusService|Common metrics"
+msgstr ""
+
+msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
+msgstr ""
+
+msgid "PrometheusService|Custom metrics"
+msgstr ""
+
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr ""
+
+msgid "PrometheusService|Finding custom metrics..."
+msgstr ""
+
+msgid "PrometheusService|Install Prometheus on clusters"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+msgstr ""
+
+msgid "PrometheusService|More information"
+msgstr ""
+
+msgid "PrometheusService|New metric"
+msgstr ""
+
+msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|Time-series monitoring service"
+msgstr ""
+
+msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
+msgstr ""
+
+msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
+msgstr ""
+
+msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote these project milestones into a group milestone."
+msgstr ""
+
+msgid "Promote to Group Milestone"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Environments"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "Protip:"
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Pseudonymizer data collection"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRule|Committer restriction"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
+
+msgid "Readme"
+msgstr ""
+
+msgid "Real-time features"
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Reference:"
+msgstr ""
+
+msgid "Refresh"
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "Regenerate key"
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register and see your runners for this group."
+msgstr ""
+
+msgid "Register and see your runners for this project."
+msgstr ""
+
+msgid "Registry"
+msgstr ""
+
+msgid "Related Commits"
+msgstr ""
+
+msgid "Related Deployed Jobs"
+msgstr ""
+
+msgid "Related Issues"
+msgstr ""
+
+msgid "Related Jobs"
+msgstr ""
+
+msgid "Related Merge Requests"
+msgstr ""
+
+msgid "Related Merged Requests"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove Runner"
+msgstr ""
+
+msgid "Remove avatar"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
+msgid "Rename"
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Repair authentication"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{failedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|Class"
+msgstr ""
+
+msgid "Reports|Confidence"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository URL"
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirror"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Requests Profiles"
+msgstr ""
+
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
+msgid "Resolve all discussions in new issue"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve discussion"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal Variables"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
+msgid "Runner token"
+msgstr ""
+
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners API"
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, and even on your local machine."
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|You have used all your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML Single Sign On"
+msgstr ""
+
+msgid "SAML Single Sign On Settings"
+msgstr ""
+
+msgid "SAST"
+msgstr ""
+
+msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save variables"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scoped issue boards"
+msgstr ""
+
+msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or jump to…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in this group"
+msgstr ""
+
+msgid "SearchAutocomplete|in this project"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr ""
+
+msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgstr ""
+
+msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select a group to invite"
+msgstr ""
+
+msgid "Select a namespace to fork the project"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select an existing Kubernetes cluster or create a new one"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select branch/tag"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project and zone to choose machine type"
+msgstr ""
+
+msgid "Select project to choose zone"
+msgstr ""
+
+msgid "Select projects you want to import."
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Select the custom project template source group."
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Selective synchronization"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send usage data"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
+msgstr ""
+
+msgid "Session expiration, projects limit and attachment size."
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set instance-wide template repository"
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Sherlock Transactions"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show latest version of the diff"
+msgstr ""
+
+msgid "Show parent pages"
+msgstr ""
+
+msgid "Show parent subgroups"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|Change weight"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in to %{group_name}"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong when toggling the button"
+msgstr ""
+
+msgid "Something went wrong while closing the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while fetching %{listType} list"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the projects."
+msgstr ""
+
+msgid "Something went wrong while fetching the registry list."
+msgstr ""
+
+msgid "Something went wrong while reopening the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Sorry, no epics matched your search"
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "SortOptions|Access level, ascending"
+msgstr ""
+
+msgid "SortOptions|Access level, descending"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Milestone"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest joined"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source code"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Specific Runners"
+msgstr ""
+
+msgid "Specify an e-mail address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage & Commit"
+msgstr ""
+
+msgid "Stage all changes"
+msgstr ""
+
+msgid "Stage changes"
+msgstr ""
+
+msgid "Staged"
+msgstr ""
+
+msgid "Staged %{type}"
+msgstr ""
+
+msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start the Runner!"
+msgstr ""
+
+msgid "Start your trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Stop environment"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Sync information"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System header and footer:"
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "Tag (%{tag_count})"
+msgid_plural "Tags (%{tag_count})"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release notes"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag."
+msgstr ""
+
+msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Sort by"
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Test SAML SSO"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+msgid "Thanks! Don't show me this again"
+msgstr ""
+
+msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
+msgstr ""
+
+msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr ""
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The deployment of this job to %{environmentLink} did not succeed."
+msgstr ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr ""
+
+msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
+msgstr ""
+
+msgid "The phase of the development lifecycle."
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr ""
+
+msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
+msgstr ""
+
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr ""
+
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
+msgstr ""
+
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The tabs below will be removed in a future version"
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no merge requests to show"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
+
+msgid "There was an error adding a todo."
+msgstr ""
+
+msgid "There was an error deleting the todo."
+msgstr ""
+
+msgid "There was an error loading users activity calendar."
+msgstr ""
+
+msgid "There was an error saving your notification settings."
+msgstr ""
+
+msgid "There was an error subscribing to this label."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "They can be managed using the %{link}."
+msgstr ""
+
+msgid "Third party offers"
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
+msgstr ""
+
+msgid "This application was created by %{link_to_owner}."
+msgstr ""
+
+msgid "This application will be able to:"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This branch has changed since you started editing. Would you like to create a new branch?"
+msgstr ""
+
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This group"
+msgstr ""
+
+msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgstr ""
+
+msgid "This group does not provide any group Runners yet."
+msgstr ""
+
+msgid "This is a confidential issue."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is the author's first Merge Request to this project."
+msgstr ""
+
+msgid "This issue is confidential"
+msgstr ""
+
+msgid "This issue is confidential and locked."
+msgstr ""
+
+msgid "This issue is locked."
+msgstr ""
+
+msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "This job is the most recent deployment to %{link}."
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This option is disabled as you don't have write permissions for the current branch"
+msgstr ""
+
+msgid "This option is disabled while you still have unstaged changes"
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page will be removed in a future release."
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project does not belong to a group and can therefore not make use of group Runners."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "This source diff could not be displayed because it is too large."
+msgstr ""
+
+msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
+msgstr ""
+
+msgid "This will delete the custom metric, Are you sure?"
+msgstr ""
+
+msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time before enforced"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds ago"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip:"
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr ""
+
+msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
+msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr ""
+
+msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
+msgstr ""
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr ""
+
+msgid "To start serving your jobs you can add Runners to your group"
+msgstr ""
+
+msgid "To this GitLab instance"
+msgstr ""
+
+msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
+msgstr ""
+
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
+
+msgid "To widen your search, change or remove filters."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Todo"
+msgstr ""
+
+msgid "Todos"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle discussion"
+msgstr ""
+
+msgid "Toggle file browser"
+msgstr ""
+
+msgid "Toggle navigation"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: OFF"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: ON"
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Time"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track activity with Contribution Analytics."
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trigger"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Turn on Service Desk"
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to save your changes"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unresolve discussion"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
+msgid "Unstage all changes"
+msgstr ""
+
+msgid "Unstage changes"
+msgstr ""
+
+msgid "Unstaged"
+msgstr ""
+
+msgid "Unstaged %{type}"
+msgstr ""
+
+msgid "Unstaged and staged %{type}"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Upgrade your plan to activate Advanced Global Search."
+msgstr ""
+
+msgid "Upgrade your plan to activate Contribution Analytics."
+msgstr ""
+
+msgid "Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Upgrade your plan to activate Issue weight."
+msgstr ""
+
+msgid "Upgrade your plan to improve Issue boards."
+msgstr ""
+
+msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage ping is not enabled"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "Use <code>%{native_redirect_uri}</code> for local tests"
+msgstr ""
+
+msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
+msgstr ""
+
+msgid "Use group milestones to manage issues from multiple projects in the same milestone."
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use the following registration token during setup:"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "Used by members to sign in to your group in GitLab"
+msgstr ""
+
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Variables"
+msgstr ""
+
+msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification information"
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View epics list"
+msgstr ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View group labels"
+msgstr ""
+
+msgid "View issue"
+msgstr ""
+
+msgid "View it on GitLab"
+msgstr ""
+
+msgid "View jobs"
+msgstr ""
+
+msgid "View labels"
+msgstr ""
+
+msgid "View log"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr ""
+
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|It is recommended to install %{markdown} so that GFM features render locally:"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgstr ""
+
+msgid "WikiMarkdownDocs|documentation"
+msgstr ""
+
+msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgstr ""
+
+msgid "WikiNewPagePlaceholder|how-to-setup"
+msgstr ""
+
+msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiNewPageTitle|New Wiki Page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgstr ""
+
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPageConflictMessage|the page"
+msgstr ""
+
+msgid "WikiPageCreate|Create %{page_title}"
+msgstr ""
+
+msgid "WikiPageEdit|Update %{page_title}"
+msgstr ""
+
+msgid "WikiPage|Page slug"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wiki|Create Page"
+msgstr ""
+
+msgid "Wiki|Create page"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|More Pages"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, let me map Google Code users to full names or GitLab users."
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
+msgstr ""
+
+msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You can %{linkStart}view the blob%{linkEnd} instead."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
+msgid "You can only edit files when you are on a branch"
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
+msgstr ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+msgstr ""
+
+msgid "You cannot write to this read-only GitLab instance."
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You must accept our Terms of Service and privacy policy in order to register an account"
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're receiving this email because %{reason}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your Todos"
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your comment will not be visible to the public."
+msgstr ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your projects"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "among other things"
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{namespace} is affected by %{vulnerability}."
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr ""
+
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr ""
+
+msgid "ciReport|(is loading)"
+msgstr ""
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr ""
+
+msgid "ciReport|Class"
+msgstr ""
+
+msgid "ciReport|Code quality"
+msgstr ""
+
+msgid "ciReport|Confidence"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Description"
+msgstr ""
+
+msgid "ciReport|Dismiss vulnerability"
+msgstr ""
+
+msgid "ciReport|Dismissed by"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|File"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Identifiers"
+msgstr ""
+
+msgid "ciReport|Instances"
+msgstr ""
+
+msgid "ciReport|Learn more about interacting with security reports (Alpha)."
+msgstr ""
+
+msgid "ciReport|License management detected %d license for the source branch only"
+msgid_plural "ciReport|License management detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "ciReport|License management detected %d new license"
+msgid_plural "ciReport|License management detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "ciReport|License management detected no licenses for the source branch only"
+msgstr ""
+
+msgid "ciReport|License management detected no new licenses"
+msgstr ""
+
+msgid "ciReport|Links"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|Method"
+msgstr ""
+
+msgid "ciReport|Namespace"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No changes to performance metrics"
+msgstr ""
+
+msgid "ciReport|Performance metrics"
+msgstr ""
+
+msgid "ciReport|Revert dismissal"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Severity"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error loading DAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading SAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading container scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error loading dependency scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "ciReport|on pipeline"
+msgstr ""
+
+msgid "command line instructions"
+msgstr ""
+
+msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgstr ""
+
+msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
+msgstr ""
+
+msgid "connecting"
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "customize"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "deploy token"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "here"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "importing"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "issue boards"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "license management"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|Add approval"
+msgstr ""
+
+msgid "mrWidget|Allows commits from members who can merge to the target branch"
+msgstr ""
+
+msgid "mrWidget|An error occured while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Cancel automatic merge"
+msgstr ""
+
+msgid "mrWidget|Check out branch"
+msgstr ""
+
+msgid "mrWidget|Checking ability to merge automatically"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes"
+msgstr ""
+
+msgid "mrWidget|Create an issue to resolve them later"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mentions"
+msgstr ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge request approved"
+msgstr ""
+
+msgid "mrWidget|Merge request approved; you can approve additionally"
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|No Approval required"
+msgstr ""
+
+msgid "mrWidget|No Approval required; you can still approve"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove Source Branch"
+msgstr ""
+
+msgid "mrWidget|Remove source branch"
+msgstr ""
+
+msgid "mrWidget|Remove your approval"
+msgstr ""
+
+msgid "mrWidget|Request to merge"
+msgstr ""
+
+msgid "mrWidget|Requires 1 more approval"
+msgid_plural "mrWidget|Requires %d more approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "mrWidget|Requires 1 more approval by"
+msgid_plural "mrWidget|Requires %d more approvals by"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Set by"
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The changes will be merged into"
+msgstr ""
+
+msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+msgstr ""
+
+msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
+msgstr ""
+
+msgid "mrWidget|The source branch has been removed"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will be removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will not be removed"
+msgstr ""
+
+msgid "mrWidget|There are merge conflicts"
+msgstr ""
+
+msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|This merge request is in the process of being merged"
+msgstr ""
+
+msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr ""
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|You can remove source branch now"
+msgstr ""
+
+msgid "mrWidget|branch does not exist."
+msgstr ""
+
+msgid "mrWidget|command line"
+msgstr ""
+
+msgid "mrWidget|into"
+msgstr ""
+
+msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "notification emails"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "password"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+msgid "source"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time spent."
+msgstr ""
+
+msgid "started"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "toggle collapse"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "within %d minute "
+msgid_plural "within %d minutes "
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
diff --git a/locale/da_DK/gitlab.po b/locale/da_DK/gitlab.po
index c32bf9eb38d..a81ab6f60b3 100644
--- a/locale/da_DK/gitlab.po
+++ b/locale/da_DK/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Danish\n"
"Language: da_DK\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: da\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:32\n"
+"PO-Revision-Date: 2018-11-19 17:20\n"
msgid " Status"
msgstr ""
@@ -31,6 +31,14 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -46,6 +54,11 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -91,11 +104,6 @@ msgid_plural "%d unstaged changes"
msgstr[0] ""
msgstr[1] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] ""
@@ -104,17 +112,31 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] ""
msgstr[1] ""
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -124,6 +146,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -139,23 +164,12 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr ""
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr ""
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -167,27 +181,13 @@ msgstr ""
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -314,6 +314,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr ""
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -356,13 +365,10 @@ msgstr ""
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
+msgid "Access expiration date"
msgstr ""
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr ""
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -392,27 +398,48 @@ msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
+msgid "Add Kubernetes cluster"
msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -422,6 +449,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -455,9 +485,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -494,12 +521,17 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr ""
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "All"
msgstr ""
@@ -515,6 +547,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -524,6 +559,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -539,6 +580,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -560,7 +604,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -584,6 +628,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -596,6 +646,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -608,6 +661,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -635,6 +691,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -677,12 +736,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr ""
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -701,7 +766,7 @@ msgstr ""
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -719,9 +784,15 @@ msgstr ""
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -740,6 +811,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -878,6 +952,9 @@ msgstr ""
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -914,9 +991,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -995,6 +1069,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1285,6 +1368,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1315,9 +1401,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1372,7 +1455,7 @@ msgstr ""
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1399,6 +1482,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1429,6 +1518,9 @@ msgstr ""
msgid "CiStatusLabel|created"
msgstr ""
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr ""
@@ -1447,6 +1539,9 @@ msgstr ""
msgid "CiStatusLabel|skipped"
msgstr ""
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr ""
@@ -1459,6 +1554,9 @@ msgstr ""
msgid "CiStatusText|created"
msgstr ""
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr ""
@@ -1513,10 +1611,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1561,6 +1659,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1573,12 +1674,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1609,10 +1722,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1639,6 +1752,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1675,6 +1794,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1705,9 +1827,6 @@ msgstr ""
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1729,25 +1848,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster details"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster health"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1759,7 +1872,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1768,16 +1881,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1795,9 +1905,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1825,6 +1932,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1837,6 +1947,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1867,9 +1980,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1909,13 +2019,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -1933,6 +2040,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -1951,9 +2061,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -1963,6 +2070,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -1972,12 +2082,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2012,6 +2128,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr ""
@@ -2084,7 +2203,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2093,10 +2212,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2186,6 +2305,9 @@ msgstr ""
msgid "Contribution guide"
msgstr ""
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2219,6 +2341,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2240,15 +2374,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2324,7 +2470,7 @@ msgstr ""
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
+msgid "Create your first page"
msgstr ""
msgid "CreateTag|Tag"
@@ -2375,6 +2521,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -2393,6 +2542,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr ""
@@ -2444,6 +2596,9 @@ msgstr ""
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2456,6 +2611,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr ""
@@ -2465,6 +2635,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2602,6 +2775,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2626,6 +2805,12 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2647,12 +2832,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2668,6 +2868,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2749,7 +2952,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2794,9 +2997,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2809,6 +3009,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2911,7 +3117,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -2944,10 +3150,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3058,6 +3264,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3112,6 +3324,12 @@ msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3121,6 +3339,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3130,6 +3351,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3139,6 +3435,9 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr ""
@@ -3151,9 +3450,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr ""
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr ""
@@ -3169,6 +3477,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3181,7 +3492,7 @@ msgstr ""
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3220,17 +3531,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -3246,6 +3558,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3288,6 +3603,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3462,10 +3780,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3474,6 +3804,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3495,7 +3828,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3507,6 +3840,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3516,19 +3852,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3546,6 +3888,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3558,9 +3906,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3570,9 +3936,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3639,12 +4002,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr ""
-
-msgid "GoToYourFork|Fork"
-msgstr ""
-
msgid "Google Code import"
msgstr ""
@@ -3675,9 +4032,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3687,6 +4056,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3705,13 +4077,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3738,9 +4110,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3798,6 +4167,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3810,19 +4182,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -3864,6 +4236,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4028,6 +4403,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4096,6 +4474,12 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4120,6 +4504,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4135,9 +4549,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4174,7 +4585,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4192,12 +4603,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4270,6 +4675,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
@@ -4281,12 +4689,18 @@ msgstr ""
msgid "Last commit"
msgstr ""
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4335,6 +4749,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4344,6 +4767,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4353,6 +4779,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4362,6 +4791,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4374,9 +4806,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4403,6 +4841,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4448,6 +4889,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4517,13 +4961,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4535,6 +5009,12 @@ msgstr ""
msgid "Median"
msgstr ""
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -4568,6 +5048,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4577,9 +5072,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4589,6 +5081,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4604,6 +5102,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4820,6 +5321,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -4939,6 +5443,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -4948,9 +5458,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -4960,6 +5467,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -4987,6 +5497,9 @@ msgstr ""
msgid "No repository"
msgstr ""
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr ""
@@ -5023,6 +5536,9 @@ msgstr ""
msgid "Not enough data"
msgstr ""
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -5041,6 +5557,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -5113,9 +5641,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5142,9 +5667,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5166,6 +5688,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5190,6 +5715,21 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5256,6 +5796,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5283,13 +5826,13 @@ msgstr ""
msgid "Permissions"
msgstr ""
-msgid "Personal Access Token"
+msgid "Permissions, LFS, 2FA"
msgstr ""
-msgid "Pipeline"
+msgid "Personal Access Token"
msgstr ""
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
+msgid "Pipeline"
msgstr ""
msgid "Pipeline Health"
@@ -5409,15 +5952,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5427,6 +5979,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5454,12 +6012,6 @@ msgstr ""
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5469,12 +6021,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5487,6 +6045,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5499,9 +6060,18 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5547,15 +6117,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5568,39 +6153,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -5610,6 +6276,15 @@ msgstr ""
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5646,6 +6321,9 @@ msgstr ""
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr ""
@@ -5673,6 +6351,9 @@ msgstr ""
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -5700,6 +6381,27 @@ msgstr ""
msgid "ProjectLifecycle|Stage"
msgstr ""
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5742,6 +6444,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5811,9 +6516,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6006,6 +6708,12 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6068,12 +6776,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6083,6 +6800,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6092,18 +6812,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6116,6 +6851,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6149,10 +6887,10 @@ msgstr ""
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6170,9 +6908,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6223,9 +6973,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6235,6 +7000,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6259,6 +7030,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6283,6 +7057,9 @@ msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -6337,15 +7114,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6370,27 +7156,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard"
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6408,9 +7222,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr ""
@@ -6441,6 +7261,9 @@ msgstr ""
msgid "Select target branch"
msgstr ""
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6453,6 +7276,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6477,6 +7303,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6495,7 +7324,10 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
@@ -6507,13 +7339,31 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "Settings"
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
msgstr ""
msgid "Share"
@@ -6525,6 +7375,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6608,12 +7461,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6641,9 +7500,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6656,12 +7521,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -6692,6 +7569,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6722,6 +7602,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6752,6 +7635,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6827,9 +7713,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6842,6 +7740,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6851,6 +7752,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6860,9 +7764,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6875,6 +7785,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -6893,6 +7809,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -6997,6 +7916,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7045,12 +7967,6 @@ msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7099,9 +8015,6 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr ""
@@ -7111,21 +8024,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr ""
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7135,6 +8042,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7144,7 +8054,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7192,10 +8108,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7216,6 +8135,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7255,7 +8177,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7276,6 +8201,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
@@ -7300,6 +8228,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7309,6 +8240,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7336,9 +8273,15 @@ msgstr ""
msgid "Time before an issue starts implementation"
msgstr ""
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr ""
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7529,12 +8472,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7550,6 +8505,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7562,12 +8520,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7577,9 +8538,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7595,6 +8562,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7610,6 +8580,9 @@ msgstr ""
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7619,6 +8592,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7637,24 +8613,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7670,6 +8664,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7703,13 +8703,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7739,15 +8742,15 @@ msgstr ""
msgid "Upload file"
msgstr ""
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr ""
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7775,6 +8778,9 @@ msgstr ""
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7784,10 +8790,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7814,6 +8862,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7847,9 +8904,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7868,6 +8931,36 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -7907,6 +9000,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8057,6 +9156,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8075,9 +9177,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8087,9 +9186,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8111,12 +9207,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8138,9 +9240,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr ""
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8150,6 +9249,12 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr ""
@@ -8216,6 +9321,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8237,16 +9345,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "assign yourself"
msgstr ""
@@ -8274,61 +9372,78 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8361,9 +9476,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8386,6 +9498,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8404,13 +9519,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8419,9 +9528,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8452,9 +9558,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8466,9 +9569,6 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8498,25 +9598,17 @@ msgstr[1] ""
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
-
msgid "disabled"
msgstr ""
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "enabled"
msgstr ""
@@ -8526,6 +9618,12 @@ msgstr ""
msgid "for this project"
msgstr ""
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -8555,6 +9653,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8783,6 +9884,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8801,6 +9905,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr ""
@@ -8829,6 +9936,11 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "remaining"
msgstr ""
@@ -8841,6 +9953,11 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "source"
msgstr ""
@@ -8856,6 +9973,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index 71e6504e306..440622b08af 100644
--- a/locale/de/gitlab.po
+++ b/locale/de/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: German\n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
@@ -13,28 +13,36 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: de\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:30\n"
+"PO-Revision-Date: 2018-11-19 17:23\n"
msgid " Status"
-msgstr ""
+msgstr " Status"
msgid " and"
-msgstr ""
+msgstr " und"
msgid " degraded on %d point"
msgid_plural " degraded on %d points"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] " um %d Punkt verschlechtert"
+msgstr[1] " um %d Punkte verschlechtert"
msgid " improved on %d point"
msgid_plural " improved on %d points"
+msgstr[0] " um %d Punkt verbessert"
+msgstr[1] " um %d Punkte verbessert"
+
+msgid "\"%{query}\" in projects"
+msgstr "\"%{query}\" in Projekten"
+
+msgid "%d addition"
+msgid_plural "%d additions"
msgstr[0] ""
msgstr[1] ""
msgid "%d changed file"
msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d geänderte Datei"
+msgstr[1] "%d geänderte Dateien"
msgid "%d commit"
msgid_plural "%d commits"
@@ -43,58 +51,58 @@ msgstr[1] "%d Commits"
msgid "%d commit behind"
msgid_plural "%d commits behind"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Commit hinterher"
+msgstr[1] "%d Commits hinterher"
+
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] "%d gelöscht"
+msgstr[1] "%d Löschungen"
msgid "%d exporter"
msgid_plural "%d exporters"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Exporter"
+msgstr[1] "%d Exporter"
msgid "%d failed test result"
msgid_plural "%d failed test results"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d fehlgeschlagenes Testergebnis"
+msgstr[1] "%d fehlgeschlagene Testergebnisse"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d festes Testergebnis"
+msgstr[1] "%d feste Testergebnisse"
msgid "%d issue"
msgid_plural "%d issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Ticket"
+msgstr[1] "%d Tickets"
msgid "%d layer"
msgid_plural "%d layers"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Ebene"
+msgstr[1] "%d Ebenen"
msgid "%d merge request"
msgid_plural "%d merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Merge-Request"
+msgstr[1] "%d Merge-Requests"
msgid "%d metric"
msgid_plural "%d metrics"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Metrik"
+msgstr[1] "%d Metriken"
msgid "%d staged change"
msgid_plural "%d staged changes"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d vorgemerkte Änderung"
+msgstr[1] "%d vorgemerkte Änderungen"
msgid "%d unstaged change"
msgid_plural "%d unstaged changes"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d nicht vorgemerkte Änderung"
+msgstr[1] "%d nicht vorgemerkte Änderungen"
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
@@ -102,1005 +110,1080 @@ msgstr[0] "%s zusätzlicher Commit wurde ausgelassen um Leistungsprobleme zu ver
msgstr[1] "%s zusätzliche Commits wurden ausgelassen um Leistungsprobleme zu verhindern."
msgid "%{actionText} & %{openOrClose} %{noteable}"
-msgstr ""
+msgstr "%{actionText} & %{openOrClose} %{noteable}"
+
+msgid "%{authorsName}'s discussion"
+msgstr "%{authorsName}'s Diskussion"
msgid "%{commit_author_link} authored %{commit_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} verfasste %{commit_timeago}"
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgstr "%{counter_storage} (%{counter_repositories} Repositories, %{counter_build_artifacts} Buildartefakte, %{counter_lfs_objects} LFS)"
+
+msgid "%{count} %{alerts}"
msgstr ""
+msgid "%{count} more assignees"
+msgstr "%{count} weitere Zugewiesene"
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} Teilnehmer"
+msgstr[1] "%{count} Teilnehmer"
+
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] "%{count} ausstehender Kommentar"
+msgstr[1] "%{count} ausstehende Kommentare"
msgid "%{filePath} deleted"
-msgstr ""
+msgstr "%{filePath} gelöscht"
msgid "%{firstLabel} +%{labelCount} more"
-msgstr ""
+msgstr "%{firstLabel} +%{labelCount} mehr"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
+msgstr "%{group_docs_link_start}Gruppen%{group_docs_link_end} ermöglichen dir die Verwaltung und die Zusammenarbeit über mehrere Projekte hinweg. Mitglieder einer Gruppe haben Zugriff auf alle Projekte darin."
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr "%{issuableType} wird entfernt! Bist du sicher?"
msgid "%{loadingIcon} Started"
-msgstr ""
+msgstr "%{loadingIcon} Gestartet"
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
-msgstr ""
+msgstr "%{lock_path} ist durch Gitlab-Benutzer(in) %{lock_user_id} gesperrt"
msgid "%{name}'s avatar"
-msgstr ""
+msgstr "Avatar von %{name}"
msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr ""
+msgstr "%{nip_domain} kann als Alternative zu einer benutzerdefinierten Domain verwendet werden."
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
-msgstr ""
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr "%{number_of_failures} von %{maximum_failures} Fehlschlägen. GitLab wird den Zugriff beim nächsten Versuch zulassen."
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr "%{number_of_failures} von %{maximum_failures} Fehlschlägen. GitLab wird es nicht weiter versuchen. Setze die Speicherinformation nach Behebung des Problems zurück."
+msgstr "%{number_commits_behind} Commits hinter %{default_branch}, %{number_commits_ahead} Commits voraus"
msgid "%{openOrClose} %{noteable}"
-msgstr ""
+msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
-msgstr ""
-
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] "%{storage_name}: fehlgeschlagener Speicherzugriff auf Host:"
-msgstr[1] "%{storage_name}: %{failed_attempts} fehlgeschlagene Speicherzugriffe:"
+msgstr "%{percent}%% abgeschlossen"
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{text} %{files}"
+msgstr[1] "%{text} %{files} Dateien"
msgid "%{text} is available"
-msgstr ""
+msgstr "%{text} ist verfügbar"
msgid "%{title} changes"
-msgstr ""
-
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgstr "%{title} Änderungen"
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr "%{unstaged} nicht vorgemerkte und %{staged} vorgemerkte Änderungen"
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr "%{usage_ping_link_start}Erfahre mehr%{usage_ping_link_end} darüber, welche Informationen mit GitLab Inc. geteilt werden."
-msgid "%{unstaged} unstaged and %{staged} staged changes"
-msgstr ""
+msgid "+ %{count} more"
+msgstr "+ %{count} weitere"
msgid "+ %{moreCount} more"
-msgstr ""
+msgstr "+ %{moreCount} weitere"
msgid "- Runner is active and can process any new jobs"
-msgstr ""
+msgstr "- Prozessor ist aktiv und kann neue Jobs verarbeiten"
msgid "- Runner is paused and will not receive any new jobs"
-msgstr ""
+msgstr "- Runner ist angehalten und wird keine neuen Aufgaben entgegennehmen"
msgid "- show less"
-msgstr ""
+msgstr "- weniger anzeigen"
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 %{type} Zusatz"
+msgstr[1] "%{count} %{type} Zusätze"
msgid "1 %{type} modification"
msgid_plural "%{count} %{type} modifications"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 %{type} Änderung"
+msgstr[1] "%{count} %{type} Änderungen"
msgid "1 closed issue"
msgid_plural "%d closed issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 geschlossenes Ticket"
+msgstr[1] "%d geschlossene Tickets"
msgid "1 closed merge request"
msgid_plural "%d closed merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 geschlossener Merge-Request"
+msgstr[1] "%d geschlossene Merge-Requests"
msgid "1 group"
msgid_plural "%d groups"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Eine Gruppe"
+msgstr[1] "%d Gruppen"
msgid "1 merged merge request"
msgid_plural "%d merged merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 zusammengeführter Merge-Request"
+msgstr[1] "%d zusammengeführte Merge-Requests"
msgid "1 open issue"
msgid_plural "%d open issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 offenes Ticket"
+msgstr[1] "%d offene Tickets"
msgid "1 open merge request"
msgid_plural "%d open merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 offener Merge-Request"
+msgstr[1] "%d offene Merge-Requests"
msgid "1 pipeline"
msgid_plural "%d pipelines"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 Pipeline"
+msgstr[1] "%d Pipelines"
msgid "1 role"
msgid_plural "%d roles"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 Rolle"
+msgstr[1] "%d Rollen"
msgid "1 user"
msgid_plural "%d users"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 Benutzer(in)"
+msgstr[1] "%d Benutzer(innen)"
msgid "1st contribution!"
-msgstr ""
+msgstr "Erster Beitrag!"
msgid "2FA enabled"
-msgstr ""
+msgstr "Zwei-Faktor-Authentifizierung aktiviert"
msgid "403|Please contact your GitLab administrator to get the permission."
-msgstr ""
+msgstr "Bitte kontaktiere deine(n) GitLab-Administrator(in), um die Erlaubnis zu erhalten."
msgid "403|You don't have the permission to access this page."
-msgstr ""
+msgstr "Du hast nicht die Berechtigung auf diese Seite zuzugreifen."
msgid "404|Make sure the address is correct and the page hasn't moved."
-msgstr ""
+msgstr "Stelle sicher, dass die Adresse korrekt ist und die Seite nicht verschoben wurde."
msgid "404|Page Not Found"
-msgstr ""
+msgstr "Seite nicht gefunden"
msgid "404|Please contact your GitLab administrator if you think this is a mistake."
-msgstr ""
+msgstr "Bitte kontaktiere deine(n) GitLab-Administrator(in), wenn du denkst, dass dies ein Fehler ist."
msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> fügt allen von johnsmith@example.com erstellten Tickets und Kommentaren \"Von <a href=\"#\">@johnsmith</a>\" hinzu und setzt <a href=\"#\">@johnsmith</a> als Zuständigen für alle Tickets die ursprünglich johnsmith@example.com zugewiesen waren."
msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"John Smith\"</code> fügt \"Von John Smith\" zu allen Tickets und Kommentaren hinzu, die ursprünglich von johnsmith@example.com erstellt wurden."
msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> fügt \"Von johnsm...@example.com\" zu allen Tickets und Kommentaren hinzu, die ursprünglich von johnsmith@example.com erstellt wurden. Die E-Mail-Adresse oder der Benutzername ist maskiert, um die Privatsphäre des/der Benutzers/Benutzerin zu gewährleisten."
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> fügt \"Von <a href=\"#\">johnsmith@example.com</a>\" zu allen Tickets und Kommentaren hinzu, die ursprünglich von johnsmith@example.com erstellt wurden. Standardmäßig wird die E-Mail-Adresse maskiert, um den Datenschutz des Nutzers zu gewährleisten. Nutze diese Option, wenn du die volle E-Mail-Adresse anzeigen willst."
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
-msgstr ""
+msgstr "<strong>%{changedFilesLength} nicht vorgemerkte</strong> und <strong>%{stagedFilesLength} vorgemerkte</strong> Änderungen"
msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
-msgstr ""
+msgstr "<strong>%{created_count}</strong> erstellt, <strong>%{accepted_count}</strong> akzeptiert."
msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
-msgstr ""
+msgstr "<strong>%{created_count}</strong> erstellt, <strong>%{closed_count}</strong> geschlossen."
msgid "<strong>%{group_name}</strong> group members"
-msgstr ""
+msgstr "<strong>%{group_name}</strong> Gruppenmitglieder"
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
-msgstr ""
+msgstr "<strong>%{pushes}</strong> Pushes, mehr als <strong>%{commits}</strong> Commits von <strong>%{people}</strong> Mitwirkenden."
msgid "<strong>Removes</strong> source branch"
-msgstr ""
+msgstr "<strong>Entfernt</strong> Quell-Branch"
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr ""
+msgstr "Ein 'Runner' ist ein Prozess, welcher ein Job ausführt. Du kannst so viele Runner erstellen wie du benötigst."
msgid "A collection of graphs regarding Continuous Integration"
msgstr "Eine Sammlung von Graphen bezüglich kontinuierlicher Integration"
-msgid "A new branch will be created in your fork and a new merge request will be started."
+msgid "A default branch cannot be chosen for an empty project."
+msgstr "Ein Default-Branch kann nicht für ein leeres Projekt ausgewählt werden."
+
+msgid "A deleted user"
+msgstr "Ein(e) gelöschte(r) Benutzer(in)"
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
msgstr ""
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr "Ein neuer Branch wird in deinem Fork erzeugt und ein neuer Merge-Request wird gestartet."
+
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
+msgstr "In einem Projekt speicherst du deine Dateien (Repository), planst deine Arbeit (Tickets) und veröffentlichst deine Dokumentation (Wiki), %{among_other_things_link}."
msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
-msgstr ""
+msgstr "Ein regulärer Ausdruck, um die Ausgabe der Testabdeckung in der Fehlerprotokollierung des Jobs zu finden. Zum Deaktivieren leer lassen"
msgid "A user with write access to the source branch selected this option"
-msgstr ""
+msgstr "Ein(e) Benutzer(in) mit Schreibzugriff auf den Quellbranch hat diese Option ausgewählt"
msgid "About GitLab"
-msgstr ""
+msgstr "Ãœber GitLab"
msgid "About GitLab CE"
-msgstr ""
+msgstr "Ãœber GitLab CE"
msgid "About auto deploy"
msgstr "Ãœber automatische Bereitstellung "
msgid "About this feature"
-msgstr ""
+msgstr "Ãœber dieses Feature"
msgid "Abuse Reports"
-msgstr ""
+msgstr "Missbrauchsmeldungen"
msgid "Abuse reports"
-msgstr ""
+msgstr "Missbrauchsmeldungen"
msgid "Accept terms"
-msgstr ""
+msgstr "Bedingungen akzeptieren"
msgid "Accepted MR"
-msgstr ""
+msgstr "Akzeptierter MR"
msgid "Access Tokens"
-msgstr ""
+msgstr "Zugangs-Token"
msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr ""
-
-msgid "Access to '%{classification_label}' not allowed"
-msgstr ""
+msgstr "Zugriff abgelehnt! Stelle sicher, dass du diesem Repository Bereitstellungsschlüssel hinzufügen kannst."
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr "Zugriff auf fehlerhafte Speicher wurde vorübergehend deaktiviert, um die Wiederherstellung zu ermöglichen. Für den zukünftigen Zugriff, behebe bitte das Problem und setze danach die Speicherinformationen zurück."
+msgid "Access expiration date"
+msgstr "Zugriff auf das Ablaufdatum"
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
-msgstr ""
+msgid "Access to '%{classification_label}' not allowed"
+msgstr "Zugriff auf '%{classification_label}' nicht erlaubt"
msgid "Account"
msgstr "Konto"
msgid "Account and limit"
-msgstr ""
+msgstr "Konto und Limit"
msgid "Active"
msgstr "Aktiv"
msgid "Active Sessions"
-msgstr ""
+msgstr "Aktive Sitzungen"
msgid "Activity"
msgstr "Aktivität"
msgid "Add"
-msgstr ""
+msgstr "Hinzufügen"
msgid "Add Changelog"
-msgstr "Änderungsliste hinzufügen "
+msgstr "Änderungsprotokoll hinzufügen"
msgid "Add Contribution guide"
msgstr "Mitarbeitsanleitung hinzufügen"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
-msgstr ""
+msgstr "Gruppen-Webhooks und GitLab Enterprise Edition hinzufügen."
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
-msgstr "Lizenz hinzufügen"
+msgid "Add Kubernetes cluster"
+msgstr "Kubernetes-Cluster hinzufügen"
msgid "Add Readme"
+msgstr "Readme anlegen"
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
msgstr ""
+msgid "Add a table"
+msgstr "Tabelle hinzufügen"
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
-msgstr ""
+msgstr "Füge zusätzlichen Text hinzu, der in jeglicher E-Mail-Kommunikation angezeigt wird. Maximal %{character_limit} Zeichen"
+
+msgid "Add comment now"
+msgstr "Jetzt kommentieren"
+
+msgid "Add image comment"
+msgstr "Bildkommentar hinzufügen"
+
+msgid "Add license"
+msgstr "Lizenz hinzufügen"
msgid "Add new application"
-msgstr ""
+msgstr "Neue Anwendung hinzufügen"
msgid "Add new directory"
msgstr "Erstelle eine neues Verzeichnis"
+msgid "Add projects"
+msgstr "Projekte hinzufügen"
+
msgid "Add reaction"
-msgstr ""
+msgstr "Reaktion hinzufügen"
+
+msgid "Add to review"
+msgstr "Zum Review hinzufügen"
msgid "Add todo"
-msgstr ""
+msgstr "To-do hinzufügen"
msgid "Add user(s) to the group:"
-msgstr ""
+msgstr "Benutzer(innen) zur Gruppe hinzufügen:"
msgid "Add users to group"
-msgstr ""
+msgstr "Füge Benutzer(innen) zur Gruppe hinzu"
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr "Das Hinzufügen neuer Anwendungen ist in deiner GitLab-Instanz deaktiviert. Bitte kontaktiere deine(n) GitLab-Administrator(in), um die Berechtigung zu erhalten"
msgid "Additional text"
-msgstr ""
+msgstr "Zusätzlicher Text"
msgid "Admin Area"
-msgstr ""
+msgstr "Adminbereich"
msgid "Admin Overview"
-msgstr ""
+msgstr "Admin-Ãœbersicht"
msgid "Admin area"
-msgstr ""
+msgstr "Adminbereich"
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Du bist gerade dabei den/die Benutzer(in) %{username} dauerhaft zu löschen. Tickets, Merge-Requests und Gruppen, die mit ihm/ihr verknüpft sind, werden einem systemweiten \"Ghost-user\" zugewiesen. Um Datenverlust zu vermeiden, ziehe in Erwägung stattdessen die Funktion %{strong_start}Benutzer(in) blockieren%{strong_end} zu verwenden. Nachdem du %{strong_start}Benutzer(in) entfernen%{strong_end} ausgeführt hast, kann es nicht rückgängig gemacht oder der/die Benutzer(in) wiederhergestellt werden."
msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Du bist gerade dabei den/die Benutzer(in) %{username} dauerhaft zu löschen. Tickets, Merge-Requests und Gruppen, die mit ihm/ihr verknüpft sind werden gelöscht. Um Datenverlust zu vermeiden, ziehe in Erwägung stattdessen die Funktion %{strong_start}Benutzer(in) blockieren%{strong_end} zu nutzen. Nachdem du %{strong_start}Benutzer(in) entfernen%{strong_end} ausgeführt hast, kann es nicht rückgängig gemacht oder der/die Benutzer(in) wiederhergestellt werden."
msgid "AdminArea|Stop all jobs"
-msgstr ""
+msgstr "Alle Jobs stoppen"
msgid "AdminArea|Stop all jobs?"
-msgstr ""
+msgstr "Alle Jobs stoppen?"
msgid "AdminArea|Stop jobs"
-msgstr ""
+msgstr "Jobs stoppen"
msgid "AdminArea|Stopping jobs failed"
-msgstr ""
+msgstr "Stoppen von Jobs ist fehlgeschlagen"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
-msgstr ""
-
-msgid "AdminHealthPageLink|health page"
-msgstr ""
+msgstr "Du bist dabei, alle Jobs zu stoppen. Dies hält alle aktuellen Jobs, die ausgeführt werden, an."
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Du bist gerade dabei das Projekt %{projectName}, sein Repository und alle verknüpften Ressourcen einschließlich Tickets, Merge-Requests, etc. zu löschen. Nachdem du %{strong_start}Projekt entfernen%{strong_end} ausgeführt hast, kann es nicht rückgängig gemacht oder wiederhergestellt werden."
msgid "AdminProjects|Delete"
-msgstr ""
+msgstr "Löschen"
msgid "AdminProjects|Delete Project %{projectName}?"
-msgstr ""
+msgstr "Projekt %{projectName} löschen?"
msgid "AdminProjects|Delete project"
-msgstr ""
+msgstr "Projekt löschen"
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
-msgstr ""
+msgstr "Gib eine Domäne an, die standardmäßig für die Auto-Review-Anwendungen- und Auto-Bereitstsellungs-Phasen jedes Projekts verwendet werden soll."
msgid "AdminUsers|Block user"
-msgstr ""
+msgstr "Benutzer(in) blockieren"
msgid "AdminUsers|Delete User %{username} and contributions?"
-msgstr ""
+msgstr "Benutzer(in) %{username} und seine/ihre Beiträge löschen?"
msgid "AdminUsers|Delete User %{username}?"
-msgstr ""
+msgstr "Benutzer(in) %{username} löschen?"
msgid "AdminUsers|Delete user"
-msgstr ""
+msgstr "Benutzer(in) löschen"
msgid "AdminUsers|Delete user and contributions"
-msgstr ""
+msgstr "Benutzer(in) und Beiträge löschen"
msgid "AdminUsers|To confirm, type %{projectName}"
-msgstr ""
+msgstr "Zur Bestätigung %{projectName} eingeben"
msgid "AdminUsers|To confirm, type %{username}"
-msgstr ""
+msgstr "Zur Bestätigung %{username} eingeben"
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
-msgstr ""
+msgstr "Erweiterte Einstellungen"
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] "Alarm"
+msgstr[1] "Alarme"
msgid "All"
msgstr "Alle"
msgid "All changes are committed"
-msgstr ""
+msgstr "Alle Änderungen sind committed"
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
+msgstr "Alle Features sind für leere Projekte, Vorlagen, oder beim Import aktiviert. Du kannst sie aber danach in den Projekteinstellungen deaktivieren."
msgid "All users"
-msgstr ""
+msgstr "Alle Benutzer(innen)"
msgid "Allow commits from members who can merge to the target branch."
-msgstr ""
+msgstr "Erlaube Commits von Mitgliedern die zum Zielbranch mergen können."
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr "Erlaube es Projekten in dieser Gruppe Git LFS zu verwenden"
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
-msgstr ""
+msgstr "Erlaube den öffentlichen Zugriff auf Pipelines und Jobdetails, einschließlich Ausgabeprotokollen und Artefakten"
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
-msgstr ""
+msgstr "Rendering von PlantUML-Diagrammen in Asciidoc-Dokumenten erlauben."
msgid "Allow requests to the local network from hooks and services."
-msgstr ""
+msgstr "Erlaube Anfragen an das lokale Netzwerk von Hooks und Diensten."
+
+msgid "Allow users to request access"
+msgstr "Erlaube es Benutzer(innen) Zugriff zu beantragen"
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr "Erlaube es Benutzer(innen) Zugriff zu beantragen, wenn die Sichtbarkeit Öffentlich oder Intern ist."
msgid "Allows you to add and manage Kubernetes clusters."
-msgstr ""
+msgstr "Ermöglicht dir das Hinzufügen und Verwalten von Kubernetes-Clustern."
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
-msgstr ""
+msgstr "Wird auch \"Herausgeber\" oder \"Relying-Party-Trust-Identifier\" genannt"
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
-msgstr ""
+msgstr "Wird auch \"Relying-Party-Service-URL\" oder \"Antwort-URL\" genannt"
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
-msgstr ""
+msgstr "Alternativ kannst du einen %{personal_access_token_link} verwenden. Wenn du deinen persönlichen Access-Token erzeugst, musst du den Gültigkeitsbereich <code>repo</code> auswählen, damit wir eine Liste deiner öffentlichen und privaten Repositories anzeigen können, die für die Verbindung verfügbar sind."
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr "Alternativ kannst du einen %{personal_access_token_link} verwenden. Wenn du deinen persönlichen Access-Token erzeugst, musst du den Gültigkeitsbereich <code>repo</code> auswählen, damit wir eine Liste deiner öffentlichen und privaten Repositories anzeigen können, die für den Import verfügbar sind."
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
+msgstr "Beim Absenden des Formulars wird automatisch ein SSH-Schlüssel generiert. Weitere Informationen findest du in der Dokumentation."
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
-msgstr ""
+msgstr "Eine Anwendung namens %{link_to_client} fordert Zugriff auf dein GitLab-Konto an."
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
-msgstr ""
+msgstr "Bei einem leeren GitLab-Benutzerfeld wird der vollständigen Namen des FogBugz-Benutzers/-Benutzerin (z. B. \"Von John Smith\") in die Beschreibung aller Tickets und Kommentare eingefügt. Außerdem werden diese Tickets und Kommentare auch mit dem/der Projektersteller(in) assoziiert und/oder ihm/ihr zugewiesen."
msgid "An error accured whilst committing your changes."
-msgstr ""
+msgstr "Beim Committen der Änderungen ist ein Fehler aufgetreten."
msgid "An error has occurred"
-msgstr ""
+msgstr "Es ist ein Fehler aufgetreten"
msgid "An error occured creating the new branch."
-msgstr ""
+msgstr "Beim Anlegen des neuen Branchs ist ein Fehler aufgetreten."
msgid "An error occured whilst fetching the job trace."
-msgstr ""
+msgstr "Beim Abrufen der Fehlerprotokollierung des Jobs ist ein Fehler aufgetreten."
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
-msgstr ""
+msgstr "Beim Laden aller Dateien ist ein Fehler aufgetreten."
msgid "An error occured whilst loading the file content."
-msgstr ""
+msgstr "Beim Laden des Dateiinhalts ist ein Fehler aufgetreten."
msgid "An error occured whilst loading the file."
-msgstr ""
+msgstr "Beim Laden der Datei ist ein Fehler aufgetreten."
msgid "An error occured whilst loading the merge request changes."
-msgstr ""
+msgstr "Beim Laden der Merge-Request-Änderungen ist ein Fehler aufgetreten."
msgid "An error occured whilst loading the merge request version data."
-msgstr ""
+msgstr "Beim Laden der Versionsdaten des Merge-Requests ist ein Fehler aufgetreten."
msgid "An error occured whilst loading the merge request."
-msgstr ""
+msgstr "Beim Laden des Merge-Requests ist ein Fehler aufgetreten."
msgid "An error occured whilst loading the pipelines jobs."
-msgstr ""
+msgstr "Beim Laden der Pipeline-Jobs ist ein Fehler aufgetreten."
+
+msgid "An error occurred adding a draft to the discussion."
+msgstr "Beim Hinzufügen eines Entwurfs zur Diskussion ist ein Fehler aufgetreten."
+
+msgid "An error occurred adding a new draft."
+msgstr "Beim Hinzufügen eines neuen Entwurfs ist ein Fehler aufgetreten."
msgid "An error occurred previewing the blob"
-msgstr ""
+msgstr "Bei der Vorschau des Blobs ist ein Fehler aufgetreten"
msgid "An error occurred when toggling the notification subscription"
-msgstr ""
+msgstr "Beim Umschalten des Benachrichtigungs-Abonnements trat ein Fehler auf"
msgid "An error occurred when updating the issue weight"
-msgstr ""
+msgstr "Beim Aktualisieren der Ticket-Gewichtung ist ein Fehler aufgetreten"
msgid "An error occurred while adding approver"
-msgstr ""
+msgstr "Beim Hinzufügen eines Genehmigungsberechtigten ist ein Fehler aufgetreten"
+
+msgid "An error occurred while deleting the comment"
+msgstr "Beim Löschen des Kommentars ist ein Fehler aufgetreten"
msgid "An error occurred while detecting host keys"
-msgstr ""
+msgstr "Bei der Erkennung von Hostschlüsseln ist ein Fehler aufgetreten"
msgid "An error occurred while dismissing the alert. Refresh the page and try again."
-msgstr ""
+msgstr "Beim Ausblenden des Alarms ist ein Fehler aufgetreten. Aktualisiere die Seite und versuche es erneut."
msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
-msgstr ""
+msgstr "Beim Ausblenden des Feature-Highlights ist ein Fehler aufgetreten. Aktualisiere die Seite und versuche es erneut auszublenden."
msgid "An error occurred while fetching markdown preview"
-msgstr ""
+msgstr "Beim Abrufen der Markdown-Vorschau ist ein Fehler aufgetreten"
+
+msgid "An error occurred while fetching pending comments"
+msgstr "Beim Abrufen der ausstehenden Kommentare ist ein Fehler aufgetreten"
msgid "An error occurred while fetching sidebar data"
-msgstr ""
+msgstr "Während des Abrufens der Daten für die Seitenleiste ist ein Fehler aufgetreten"
msgid "An error occurred while fetching stages."
-msgstr ""
+msgstr "Beim Abrufen der Phasen ist ein Fehler aufgetreten."
msgid "An error occurred while fetching the job log."
-msgstr ""
+msgstr "Beim Abrufen des Jobprotokolls ist ein Fehler aufgetreten."
msgid "An error occurred while fetching the job."
-msgstr ""
+msgstr "Beim Abrufen des Jobs ist ein Fehler aufgetreten."
msgid "An error occurred while fetching the jobs."
-msgstr ""
+msgstr "Beim Abrufen der Jobs ist ein Fehler aufgetreten."
msgid "An error occurred while fetching the pipeline."
-msgstr ""
+msgstr "Beim Abrufen der Pipeline ist ein Fehler aufgetreten."
msgid "An error occurred while getting projects"
-msgstr ""
+msgstr "Beim Abrufen der Projekte ist ein Fehler aufgetreten"
msgid "An error occurred while importing project: %{details}"
-msgstr ""
+msgstr "Beim Importieren des Projektes ist ein Fehler aufgetreten: %{details}"
msgid "An error occurred while initializing path locks"
-msgstr ""
+msgstr "Beim Initialisieren der Pfadsperren ist ein Fehler aufgetreten"
+
+msgid "An error occurred while loading chart data"
+msgstr "Beim Laden der Diagrammdaten ist ein Fehler aufgetreten"
msgid "An error occurred while loading commit signatures"
-msgstr ""
+msgstr "Beim Laden der Commit-Signaturen ist ein Fehler aufgetreten"
msgid "An error occurred while loading diff"
-msgstr ""
+msgstr "Beim Laden des Diffs ist ein Fehler aufgetreten"
msgid "An error occurred while loading filenames"
-msgstr ""
+msgstr "Beim Laden der Dateinamen ist ein Fehler aufgetreten"
msgid "An error occurred while loading the file"
-msgstr ""
+msgstr "Beim Laden der Datei ist ein Fehler aufgetreten"
msgid "An error occurred while making the request."
-msgstr ""
+msgstr "Beim Bearbeiten der Anfrage ist ein Fehler aufgetreten."
msgid "An error occurred while removing approver"
-msgstr ""
+msgstr "Beim Löschen eines Genehmigungsberechtigten ist ein Fehler aufgetreten"
msgid "An error occurred while rendering KaTeX"
-msgstr ""
+msgstr "Beim Erstellen der Vorschau für KaTeX trat ein Fehler auf"
msgid "An error occurred while rendering preview broadcast message"
-msgstr ""
+msgstr "Beim Rendern der Vorschau der Broadcast-Nachricht ist ein Fehler aufgetreten"
msgid "An error occurred while retrieving calendar activity"
-msgstr ""
+msgstr "Beim Abrufen der Kalenderaktivität ist ein Fehler aufgetreten"
msgid "An error occurred while retrieving diff"
-msgstr ""
+msgstr "Beim Abrufen des Diffs ist ein Fehler aufgetreten"
msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
+msgstr "Beim Speichern des LDAP-Ãœberschreibungsstatus ist ein Fehler aufgetreten. Bitte versuche es erneut."
msgid "An error occurred while saving assignees"
-msgstr ""
+msgstr "Beim Speichern der Zuweisungen ist ein Fehler aufgetreten"
msgid "An error occurred while subscribing to notifications."
-msgstr ""
+msgstr "Beim Abonnieren von Benachrichtigungen ist ein Fehler aufgetreten."
msgid "An error occurred while unsubscribing to notifications."
-msgstr ""
+msgstr "Beim Abbestellen der Benachrichtigungen ist ein Fehler aufgetreten."
+
+msgid "An error occurred while updating the comment"
+msgstr "Beim Aktualisieren des Kommentars ist ein Fehler aufgetreten"
msgid "An error occurred while validating username"
-msgstr ""
+msgstr "Beim Validieren des Benutzernamens ist ein Fehler aufgetreten"
msgid "An error occurred. Please try again."
-msgstr ""
+msgstr "Ein Fehler ist aufgetreten. Bitte versuche es erneut."
+
+msgid "Analytics"
+msgstr "Analysen"
msgid "Anonymous"
-msgstr ""
+msgstr "Anonym"
msgid "Anti-spam verification"
-msgstr ""
+msgstr "Anti-Spam-Überprüfung"
msgid "Any"
-msgstr ""
+msgstr "Irgendein"
msgid "Any Label"
-msgstr ""
+msgstr "Beliebiges Label"
msgid "Appearance"
-msgstr ""
+msgstr "Aussehen"
msgid "Application"
-msgstr ""
+msgstr "Anwendung"
-msgid "Application Id"
-msgstr ""
+msgid "Application ID"
+msgstr "Anwendungs-ID"
msgid "Application: %{name}"
-msgstr ""
+msgstr "Anwendung: %{name}"
msgid "Applications"
msgstr "Anwendungen"
msgid "Apr"
-msgstr ""
+msgstr "Apr"
msgid "April"
-msgstr ""
+msgstr "April"
msgid "Archived project! Repository and other project resources are read-only"
-msgstr ""
+msgstr "Archiviertes Projekt! Repository und andere Projektressourcen sind schreibgeschützt"
+
+msgid "Archived projects"
+msgstr "Archivierte Projekte"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Bist Du sicher, dass Du diesen Pipeline-Zeitplan löschen möchtest?"
+msgid "Are you sure you want to erase this build?"
+msgstr "Bist du sicher, dass du diesen Build löschen möchtest?"
+
msgid "Are you sure you want to lose unsaved changes?"
-msgstr ""
+msgstr "Bist du sicher, dass du alle nicht gespeicherten Änderungen verwerfen möchtest?"
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
-msgstr ""
+msgstr "Möchtest du den öffentlichen Schlüssel wirklich neu generieren? Du musst dann den öffentlichen Schlüssel auf dem Remote-Server aktualisieren, bevor die Spiegelung wieder funktioniert."
msgid "Are you sure you want to remove %{group_name}?"
-msgstr ""
+msgstr "Bist du sicher, dass du %{group_name} wirklich entfernen willst?"
msgid "Are you sure you want to remove this identity?"
-msgstr ""
+msgstr "Bist du sicher, dass du diese Identität entfernen willst?"
msgid "Are you sure you want to reset registration token?"
-msgstr "Bist Du sicher, dass Du den Registrierungstoken zurücksetzen willst?"
+msgstr "Bist du sicher, dass du den Registrierungstoken zurücksetzen willst?"
msgid "Are you sure you want to reset the health check token?"
-msgstr "Bist Du sicher, dass Du den Systemüberwachungstoken zurücksetzen willst?"
+msgstr "Bist du sicher, dass du den Health-Check-Token zurücksetzen willst?"
+
+msgid "Are you sure you want to stop this environment?"
+msgstr "Bist du sicher, dass du diese Umgebung stoppen möchtest?"
msgid "Are you sure you want to unlock %{path_lock_path}?"
-msgstr ""
+msgstr "Bist du sicher, dass du %{path_lock_path} entsperren willst?"
msgid "Are you sure?"
msgstr "Bist Du sicher?"
msgid "Artifact ID"
-msgstr ""
+msgstr "Artefakt-ID"
msgid "Artifacts"
-msgstr ""
+msgstr "Artefakte"
msgid "Ascending"
-msgstr ""
+msgstr "Aufsteigend"
msgid "Ask your group maintainer to set up a group Runner."
-msgstr ""
+msgstr "Bitte deine(n) Gruppenbetreuer(in) einen Gruppenrunner einzurichten."
msgid "Assertion consumer service URL"
-msgstr ""
+msgstr "Assertion-Consumer-Service-URL"
msgid "Assign custom color like #FF0000"
-msgstr ""
+msgstr "Benutzerdefinierte Farbe wie #FF0000 zuweisen"
msgid "Assign labels"
-msgstr ""
+msgstr "Label zuweisen"
msgid "Assign milestone"
-msgstr ""
+msgstr "Meilenstein zuweisen"
msgid "Assign to"
-msgstr ""
+msgstr "Zuweisen an"
msgid "Assigned Issues"
-msgstr ""
+msgstr "Zugewiesene Tickets"
msgid "Assigned Merge Requests"
-msgstr ""
+msgstr "Zugewiesene Merge-Requests"
msgid "Assigned to :name"
-msgstr ""
+msgstr "Zugewiesen an :name"
msgid "Assigned to me"
-msgstr ""
+msgstr "Mir zugewiesen"
msgid "Assignee"
-msgstr ""
+msgstr "Zugewiesen an"
msgid "Assignee lists not available with your current license"
-msgstr ""
+msgstr "Zuweisungslisten sind mit deiner momentanen Lizenz nicht verfügbar"
msgid "Assignee lists show all issues assigned to the selected user."
-msgstr ""
+msgstr "Zuweisungslisten zeigen alle dem ausgewählten Benutzer zugewiesenen Tickets an."
msgid "Assignee(s)"
-msgstr ""
+msgstr "Zugewiesene Personen"
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Datei mittels Drag &amp; Drop oder %{upload_link} hinzufügen"
msgid "Audit Events"
-msgstr ""
+msgstr "Audit-Ereignisse"
msgid "Aug"
-msgstr ""
+msgstr "Aug"
msgid "August"
-msgstr ""
+msgstr "August"
msgid "Authentication Log"
-msgstr ""
+msgstr "Authentifizierungsprotokoll"
msgid "Authentication log"
-msgstr ""
+msgstr "Authentifizierungsprotokoll"
msgid "Authentication method"
-msgstr ""
+msgstr "Authentifizierungsmethode"
msgid "Author"
-msgstr ""
+msgstr "Autor(in)"
msgid "Authorization code:"
-msgstr ""
+msgstr "Autorisierungscode:"
msgid "Authorization was granted by entering your username and password in the application."
-msgstr ""
+msgstr "Die Autorisierung wurde erteilt, indem du deinen Benutzernamen und Passwort in die Anwendung eingeben hast."
msgid "Authorize"
-msgstr ""
+msgstr "Autorisieren"
msgid "Authorize %{link_to_client} to use your account?"
-msgstr ""
+msgstr "Autorisierst du %{link_to_client} dein Konto zu verwenden?"
msgid "Authorized At"
-msgstr ""
+msgstr "Autorisiert bei"
msgid "Authorized applications (%{size})"
-msgstr ""
+msgstr "Autorisierte Anwendungen (%{size})"
msgid "Authors: %{authors}"
-msgstr ""
+msgstr "Autoren: %{authors}"
msgid "Auto DevOps"
-msgstr ""
+msgstr "Auto-DevOps"
msgid "Auto DevOps enabled"
-msgstr ""
+msgstr "Auto-DevOps aktiviert"
msgid "Auto DevOps, runners and job artifacts"
-msgstr ""
+msgstr "Auto-DevOps, Runners und Jobartefakte"
msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
-msgstr ""
+msgstr "Auto-Review-Anwendungen und automatische Bereitstellung benötigen ein %{kubernetes} um korrekt zu funktionieren."
msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
-msgstr ""
+msgstr "Auto-Review-Anwendungen und automatische Bereitstellung benötigen einen Domänennamen und ein %{kubernetes} um korrekt zu funktionieren."
msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
-msgstr ""
+msgstr "Auto-Review-Anwendungen und automatische Bereitstellung benötigen einen Domänennamen um korrekt zu funktionieren."
msgid "Auto-cancel redundant, pending pipelines"
-msgstr ""
+msgstr "Lösche redundante, ausstehende Pipelines automatisch"
msgid "AutoDevOps|Auto DevOps"
-msgstr ""
+msgstr "Auto-DevOps"
msgid "AutoDevOps|Auto DevOps documentation"
-msgstr ""
+msgstr "Auto-DevOps-Dokumentation"
msgid "AutoDevOps|Enable in settings"
-msgstr ""
+msgstr "Aktiviere in den Einstellungen"
msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
-msgstr ""
+msgstr "Deine Anwendung wird, basierend auf den vordefinierten CI/CD-Einstellungen, automatisch gebaut, getestet und bereitgestellt."
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
-msgstr ""
+msgstr "Erfahre mehr in der %{link_to_documentation}"
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr "Die Auto-DevOps-Pipeline wurde aktiviert und wir verwendet, falls keine alternative CI-Konfigurationsdatei gefunden wurde. %{more_information_link}"
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
-msgstr ""
+msgstr "Du kannst deine Anwendung automatisiert erstellen und testen, wenn du für dieses Projekt %{link_to_auto_devops_settings}. Du kannst sie auch automatisch bereitstellen, wenn du %{link_to_add_kubernetes_cluster}."
msgid "AutoDevOps|add a Kubernetes cluster"
-msgstr ""
+msgstr "Ein Kubernetes-Cluster hinzufügen"
msgid "AutoDevOps|enable Auto DevOps"
-msgstr ""
+msgstr "aktiviere Auto-DevOps"
msgid "Automatically marked as default internal user"
-msgstr ""
+msgstr "Automatisch als interne(r) Standardbenutzer(in) gekennzeichnet"
msgid "Available"
-msgstr ""
+msgstr "Verfügbar"
msgid "Available group Runners : %{runners}"
-msgstr ""
+msgstr "Verfügbare Gruppen-Runner: %{runners}"
msgid "Available group Runners : %{runners}."
-msgstr ""
+msgstr "Verfügbare Gruppen-Runner: %{runners}."
msgid "Avatar will be removed. Are you sure?"
-msgstr ""
+msgstr "Avatar wird entfernt. Bist du sicher?"
msgid "Average per day: %{average}"
-msgstr ""
+msgstr "Durchschnitt pro Tag: %{average}"
msgid "Background Color"
-msgstr ""
+msgstr "Hintergrundfarbe"
msgid "Background Jobs"
-msgstr ""
+msgstr "Hintergrundjobs"
msgid "Background color"
-msgstr ""
-
-msgid "Background jobs"
-msgstr ""
+msgstr "Hintergrundfarbe"
msgid "Badges"
-msgstr ""
+msgstr "Badges"
msgid "Badges|A new badge was added."
-msgstr ""
+msgstr "Ein neuer Badge wurde hinzugefügt."
msgid "Badges|Add badge"
-msgstr ""
+msgstr "Badge hinzufügen"
msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
-msgstr ""
+msgstr "Hinzufügen des Badges fehlgeschlagen, bitte überprüfe die eingegebenen URLs und versuche es erneut."
msgid "Badges|Badge image URL"
-msgstr ""
+msgstr "Badge-Bild-URL"
msgid "Badges|Badge image preview"
-msgstr ""
+msgstr "Badge-Bild-Vorschau"
msgid "Badges|Delete badge"
-msgstr ""
+msgstr "Badge löschen"
msgid "Badges|Delete badge?"
-msgstr ""
+msgstr "Badge löschen?"
msgid "Badges|Deleting the badge failed, please try again."
-msgstr ""
+msgstr "Löschen des Badges fehlgeschlagen, bitte versuchen es erneut."
msgid "Badges|Group Badge"
-msgstr ""
+msgstr "Gruppen-Badge"
msgid "Badges|Link"
-msgstr ""
+msgstr "Link"
msgid "Badges|No badge image"
-msgstr ""
+msgstr "Kein Badge-Bild"
msgid "Badges|No image to preview"
-msgstr ""
+msgstr "Kein Bild zur Vorschau"
msgid "Badges|Please fill in a valid URL"
-msgstr ""
+msgstr "Bitte trage eine gültige URL ein"
msgid "Badges|Project Badge"
-msgstr ""
+msgstr "Projekt-Badge"
msgid "Badges|Reload badge image"
-msgstr ""
+msgstr "Badge-Bild neu laden"
msgid "Badges|Save changes"
-msgstr ""
+msgstr "Änderungen speichern"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
-msgstr ""
+msgstr "Speichern des Badges fehlgeschlagen, bitte überprüfe die eingegebenen URLs und versuche es erneut."
msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr ""
+msgstr "Die %{docsLinkStart}Variablen%{docsLinkEnd} die GitLab unterstützt: %{placeholders}"
msgid "Badges|The badge was deleted."
-msgstr ""
+msgstr "Das Badge wurde gelöscht."
msgid "Badges|The badge was saved."
-msgstr ""
+msgstr "Das Badge wurde gespeichert."
msgid "Badges|This group has no badges"
-msgstr ""
+msgstr "Diese Gruppe hat keine Badges"
msgid "Badges|This project has no badges"
-msgstr ""
+msgstr "Dieses Projekt hat keine Badges"
msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr ""
+msgstr "Du bist gerade dabei dieses Badge zu entfernen. Entfernte Badges können <strong>nicht</strong> rückgängig gemacht werden."
msgid "Badges|Your badges"
-msgstr ""
+msgstr "Deine Badges"
msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
+msgstr "z. B. %{exampleUrl}"
+
+msgid "BatchComments|Delete all pending comments"
+msgstr "Alle ausstehenden Kommentare löschen"
+
+msgid "BatchComments|Discard review?"
+msgstr "Review verwerfen?"
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr "Du bist dabei deinen Review zu verwerfen und damit alle ausstehenden Kommentare zu löschen. Die gelöschten Kommentare können %{strong_start}nicht%{strong_end} wiederhergestellt werden."
msgid "Begin with the selected commit"
-msgstr ""
+msgstr "Mit dem ausgewählten Commit beginnen"
msgid "Below are examples of regex for existing tools:"
-msgstr ""
+msgstr "Im Folgenden findest du Beispiele für Regex für vorhandene Tools:"
msgid "Below you will find all the groups that are public."
-msgstr ""
+msgstr "Unten findest du alle Gruppen, die öffentlich sind."
msgid "Billing"
-msgstr ""
+msgstr "Abrechnung"
msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
-msgstr ""
+msgstr "%{group_name} nutzt aktuell den Tarif %{plan_link}."
msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
-msgstr ""
+msgstr "Derzeit ist ein automatisches Downgrade und Upgrade auf einige Tarife nicht möglich."
msgid "BillingPlans|Current plan"
-msgstr ""
+msgstr "Aktueller Tarif"
msgid "BillingPlans|Customer Support"
-msgstr ""
+msgstr "Kundensupport"
msgid "BillingPlans|Downgrade"
-msgstr ""
+msgstr "Downgrade"
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
-msgstr ""
+msgstr "Erfahre mehr über unsere Tarife, indem du unsere %{faq_link} liest, oder beginne einen kostenlosen 30-Tage Test von GitLab.com Gold."
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
-msgstr ""
+msgstr "Erfahre mehr über die einzelnen Tarife, indem du unsere %{faq_link} liest."
msgid "BillingPlans|Manage plan"
-msgstr ""
+msgstr "Tarif verwalten"
msgid "BillingPlans|Please contact %{customer_support_link} in that case."
-msgstr ""
+msgstr "Wende dich in diesem Fall bitte an %{customer_support_link}."
msgid "BillingPlans|See all %{plan_name} features"
-msgstr ""
+msgstr "Alle Features von %{plan_name} ansehen"
msgid "BillingPlans|This group uses the plan associated with its parent group."
-msgstr ""
+msgstr "Diese Gruppe verwendet den Tarif der übergeordneten Gruppe."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
-msgstr ""
+msgstr "Im Abschnitt Abrechnung von %{parent_billing_page_link} können Sie den Tarif für diese Gruppe verwalten."
msgid "BillingPlans|Upgrade"
-msgstr ""
+msgstr "Upgrade"
msgid "BillingPlans|You are currently on the %{plan_link} plan."
-msgstr ""
+msgstr "Dein aktueller Tarif ist %{plan_link}."
msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
-msgstr ""
+msgstr "Deine GitLab.com Testversion ist am %{expiration_date} abgelaufen. %{learn_more_text}"
msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
-msgstr ""
+msgstr "Deine Gold-Testversion <strong>läuft am %{expiration_date}</strong> ab. Erfahre mehr über GitLab.com Gold, indem du unsere %{features_link} liest."
msgid "BillingPlans|features"
-msgstr ""
+msgstr "Features"
msgid "BillingPlans|frequently asked questions"
-msgstr ""
+msgstr "Häufig gestellte Fragen (FAQ)"
msgid "BillingPlans|monthly"
-msgstr ""
+msgstr "monatlich"
msgid "BillingPlans|paid annually at %{price_per_year}"
-msgstr ""
+msgstr "%{price_per_year} jährlich"
msgid "BillingPlans|per user"
-msgstr ""
+msgstr "je Benutzer(in)"
msgid "Bitbucket Server Import"
-msgstr ""
+msgstr "Bitbucket-Server-Import"
msgid "Bitbucket import"
-msgstr ""
+msgstr "Bitbucket-Import"
msgid "Blog"
-msgstr ""
+msgstr "Blog"
msgid "Boards"
-msgstr ""
+msgstr "Boards"
msgid "Branch %{branchName} was not found in this project's repository."
-msgstr ""
+msgstr "Branch %{branchName} wurde im Repository dieses Projekts nicht gefunden."
msgid "Branch (%{branch_count})"
msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Branch (%{branch_count})"
+msgstr[1] "Branches (%{branch_count})"
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr "Branch <strong>%{branch_name}</strong> wurde erstellt. Um die automatische Bereitstellung einzurichten, wähle eine GitLab CI Yaml Vorlage und committe Deine Änderungen. %{link_to_autodeploy_doc}"
+msgstr "Branch <strong>%{branch_name}</strong> wurde erstellt. Um die automatische Bereitstellung einzurichten, wähle eine GitLab CI Yaml Vorlage und committe deine Änderungen. %{link_to_autodeploy_doc}"
msgid "Branch has changed"
-msgstr ""
+msgstr "Branch wurde geändert"
msgid "Branch is already taken"
-msgstr ""
+msgstr "Branch existiert bereits"
msgid "Branch name"
-msgstr ""
+msgstr "Branch-Name"
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "Branches durchsuchen"
@@ -1109,130 +1192,130 @@ msgid "BranchSwitcherTitle|Switch branch"
msgstr "Branch wechseln"
msgid "Branches"
-msgstr ""
+msgstr "Branches"
msgid "Branches|Active"
-msgstr ""
+msgstr "Aktiv"
msgid "Branches|Active branches"
-msgstr ""
+msgstr "Aktive Branches"
msgid "Branches|All"
-msgstr ""
+msgstr "Alle"
msgid "Branches|Cant find HEAD commit for this branch"
-msgstr ""
+msgstr "HEAD-Commit kann für diesen Branch nicht gefunden werden"
msgid "Branches|Compare"
-msgstr ""
+msgstr "Vergleichen"
msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
-msgstr ""
+msgstr "Löschen Sie alle Branches, die in \"%{default_branch}\" zusammengeführt werden"
msgid "Branches|Delete branch"
-msgstr ""
+msgstr "Branch löschen"
msgid "Branches|Delete merged branches"
-msgstr ""
+msgstr "Zusammengeführte Branches löschen"
msgid "Branches|Delete protected branch"
-msgstr ""
+msgstr "Geschützten Branch löschen"
msgid "Branches|Delete protected branch '%{branch_name}'?"
-msgstr ""
+msgstr "Geschützten Branch '%{branch_name}' löschen?"
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
-msgstr ""
+msgstr "Das Löschen des Branches '%{branch_name}' kann nicht rückgängig gemacht werden. Bist du sicher?"
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
-msgstr ""
+msgstr "Löschen der zusammengeführten Branches kann nicht rückgängig gemacht werden. Bist du sicher?"
msgid "Branches|Filter by branch name"
-msgstr ""
+msgstr "Filtern nach dem Branch-Namen"
msgid "Branches|Merged into %{default_branch}"
-msgstr ""
+msgstr "In %{default_branch} zusammengeführt"
msgid "Branches|New branch"
-msgstr ""
+msgstr "Neuer Branch"
msgid "Branches|No branches to show"
-msgstr ""
+msgstr "Keine Branches vorhanden"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Sobald du bestätigst und %{delete_protected_branch} drückst, kann der Vorgang weder rückgängig gemacht noch wiederhergestellt werden."
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
-msgstr ""
+msgstr "Nur ein Projektbetreuer oder -besitzer kann einen geschützten Branch löschen"
msgid "Branches|Overview"
-msgstr ""
+msgstr "Ãœbersicht"
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
-msgstr ""
+msgstr "Geschützte Branches können in %{project_settings_link} verwaltet werden."
msgid "Branches|Show active branches"
-msgstr ""
+msgstr "Aktive Branches anzeigen"
msgid "Branches|Show all branches"
-msgstr ""
+msgstr "Alle Branches anzeigen"
msgid "Branches|Show more active branches"
-msgstr ""
+msgstr "Mehr aktive Branches anzeigen"
msgid "Branches|Show more stale branches"
-msgstr ""
+msgstr "Mehr inaktive Branches anzeigen"
msgid "Branches|Show overview of the branches"
-msgstr ""
+msgstr "Ãœbersicht der Branches anzeigen"
msgid "Branches|Show stale branches"
-msgstr ""
+msgstr "Inaktive Branches anzeigen"
msgid "Branches|Sort by"
-msgstr ""
+msgstr "Sortieren nach"
msgid "Branches|Stale"
-msgstr ""
+msgstr "Inaktiv"
msgid "Branches|Stale branches"
-msgstr ""
+msgstr "Inaktive Branches"
msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
-msgstr ""
+msgstr "Der Branch konnte nicht automatisch aktualisiert werden, da er von seinem Upstream-Gegenstück abweicht."
msgid "Branches|The default branch cannot be deleted"
-msgstr ""
+msgstr "Der Standardbranch kann nicht gelöscht werden"
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
-msgstr ""
+msgstr "Dieser Branch wurde noch nicht mit %{default_branch} zusammengeführt."
msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
+msgstr "Um Datenverlust zu vermeiden, überlege diesen Branch zu mergen, bevor du ihn löschst."
msgid "Branches|To confirm, type %{branch_name_confirmation}:"
-msgstr ""
+msgstr "Gib zur Bestätigung %{branch_name_confirmation} ein:"
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
-msgstr ""
+msgstr "Um die lokalen Änderungen zu verwerfen und den Branch mit der Upstream-Version zu überschreiben, lösche ihn hier und wähle oben \"Jetzt aktualisieren\"."
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
-msgstr ""
+msgstr "Du bist dabei den geschützten Branch %{branch_name} dauerhaft löschen."
msgid "Branches|diverged from upstream"
-msgstr ""
+msgstr "weicht vom Upstream ab"
msgid "Branches|merged"
-msgstr ""
+msgstr "merged"
msgid "Branches|project settings"
-msgstr ""
+msgstr "Projekteinstellungen"
msgid "Branches|protected"
-msgstr ""
+msgstr "geschützt"
msgid "Browse Directory"
-msgstr "Verzeichnisse durchsuchen"
+msgstr "Verzeichnis durchsuchen"
msgid "Browse File"
msgstr "Datei durchsuchen"
@@ -1244,10 +1327,10 @@ msgid "Browse files"
msgstr "Dateien durchsuchen"
msgid "Built-In"
-msgstr ""
+msgstr "Integriert"
msgid "Business metrics (Custom)"
-msgstr ""
+msgstr "Business-Metriken (benutzerdefiniert)"
msgid "ByAuthor|by"
msgstr "von"
@@ -1256,94 +1339,94 @@ msgid "CI / CD"
msgstr "CI / CD"
msgid "CI / CD Settings"
-msgstr ""
+msgstr "CI/CD-Einstellungen"
msgid "CI will run using the credentials assigned above."
-msgstr ""
+msgstr "CI wird mit den oben angegebenen Anmeldeinformationen ausgeführt."
msgid "CI/CD"
-msgstr ""
+msgstr "CI/CD"
msgid "CI/CD configuration"
-msgstr ""
+msgstr "CI/CD-Konfiguration"
msgid "CI/CD for external repo"
-msgstr ""
+msgstr "CI/CD für externes Repo"
msgid "CI/CD settings"
-msgstr ""
+msgstr "CI/CD-Einstellungen"
msgid "CICD|Auto DevOps"
-msgstr ""
+msgstr "Auto-DevOps"
msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
-msgstr ""
+msgstr "Auto-DevOps wird deine Anwendung basierend auf einer vordefinierten CI/CD-Konfiguration automatisch bauen, testen und bereitstellen."
msgid "CICD|Automatic deployment to staging, manual deployment to production"
-msgstr ""
+msgstr "Automatische Bereitstellung für Staging, manuelle Bereitstellung für Produktion"
msgid "CICD|Continuous deployment to production"
+msgstr "Kontinuierliche Bereitstellung für Produktion"
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
msgstr ""
msgid "CICD|Default to Auto DevOps pipeline"
-msgstr ""
+msgstr "Standard für Auto-DevOps-Pipeline"
msgid "CICD|Deployment strategy"
-msgstr ""
+msgstr "Bereitstellungsstrategie"
msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
+msgstr "Die Bereitstellungsstrategie benötigt einen Domänennamen, um korrekt zu funktionieren."
msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
+msgstr "Richte hier keine Domäne ein, wenn du mehrere Kubernetes-Cluster mit Auto-DevOps einrichtest."
msgid "CICD|Jobs"
-msgstr ""
+msgstr "Jobs"
msgid "CICD|Learn more about Auto DevOps"
-msgstr ""
+msgstr "Erfahre mehr über Auto-DevOps"
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
-msgstr ""
+msgstr "Die Auto-DevOps-Pipeline wird ausgeführt, wenn keine alternative CI-Konfigurationsdatei gefunden wird."
msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
-msgstr ""
+msgstr "Du musst eine Domäne angeben, wenn du Auto Review-Anwendungen und automatische Bereitstellungsphasen verwenden möchtest."
msgid "CICD|instance enabled"
-msgstr ""
+msgstr "Instanz aktiviert"
msgid "Callback URL"
-msgstr ""
-
-msgid "Callback url"
-msgstr ""
+msgstr "Callback-URL"
msgid "Can't find HEAD commit for this branch"
-msgstr ""
+msgstr "HEAD-Commit kann für diesen Branch nicht gefunden werden"
msgid "Cancel"
msgstr "Abbrechen"
msgid "Cancel this job"
-msgstr ""
+msgstr "Job abbrechen"
msgid "Cannot be merged automatically"
-msgstr ""
+msgstr "Kann nicht automatisch zusammengeführt werden"
msgid "Cannot modify managed Kubernetes cluster"
-msgstr ""
+msgstr "Kann verwalteten Kubernetes-Cluster nicht ändern"
msgid "Certificate fingerprint"
-msgstr ""
+msgstr "Zertifikat-Fingerabdruck"
msgid "Change Weight"
-msgstr ""
+msgstr "Gewichtung ändern"
msgid "Change template"
-msgstr ""
+msgstr "Vorlage ändern"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
-msgstr ""
+msgstr "Ändere diesen Wert, um zu beeinflussen, wie oft die GitLab UI nach Updates fragt."
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "In dem Branch wählen"
@@ -1352,19 +1435,19 @@ msgid "ChangeTypeActionLabel|Revert in branch"
msgstr "Im Branch wiederherstellen"
msgid "ChangeTypeAction|Cherry-pick"
-msgstr "Herauspicken"
+msgstr "Cherry-Pick"
msgid "ChangeTypeAction|Revert"
msgstr "Wiederherstellen "
msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
-msgstr ""
+msgstr "Dies wird einen neuen Commit erzeugen, um die vorhandenen Änderungen rückgängig zu machen."
msgid "Changelog"
-msgstr "Änderungsliste "
+msgstr "Änderungsprotokoll"
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
-msgstr ""
+msgstr "Änderungen werden angezeigt, als ob die <b>Quell</b>-Revision in die <b>Ziel</b>-Revision gemerged wurde."
msgid "Charts"
msgstr "Diagramme"
@@ -1372,56 +1455,62 @@ msgstr "Diagramme"
msgid "Chat"
msgstr "Chat"
-msgid "Check interval"
-msgstr ""
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr "Lies die %{docs_link_start}Dokumentation%{docs_link_end}."
msgid "Checking %{text} availability…"
-msgstr ""
+msgstr "Prüfe %{text} Verfügbarkeit…"
msgid "Checking branch availability..."
-msgstr ""
+msgstr "Überprüfe Verfügbarkeit des Branches..."
msgid "Cherry-pick this commit"
-msgstr "Diesen Commit herauspicken "
+msgstr "Diesen Commit cherry picken"
msgid "Cherry-pick this merge request"
-msgstr "Diesen Merge Request herauspicken"
+msgstr "Diesen Merge-Request cherry picken"
msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
-msgstr ""
+msgstr "Wähle <strong>Archiv erstellen</strong> und warte, bis die Archivierung abgeschlossen ist."
msgid "Choose <strong>Next</strong> at the bottom of the page."
-msgstr ""
+msgstr "Wähle <strong>Nächste</strong> unten auf der Seite."
msgid "Choose File ..."
-msgstr ""
+msgstr "Datei auswählen ..."
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
+msgstr "Wähle einen Branch/Tag (z. B. %{master}) oder gib einen Commit ein (z. B. %{sha}), um zu sehen, was geändert wurde oder um einen Merge-Request zu erstellen."
+
+msgid "Choose a template..."
+msgstr "Wählen Sie eine Vorlage..."
+
+msgid "Choose a type..."
+msgstr "Typ auswählen..."
msgid "Choose any color."
-msgstr ""
+msgstr "Wähle eine Farbe."
msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
-msgstr ""
+msgstr "Wähle zwischen <code>clone</code> oder <code>fetch</code>, um den aktuellen Anwendungscode zu erhalten"
msgid "Choose file..."
-msgstr ""
+msgstr "Datei auswählen..."
msgid "Choose the top-level group for your repository imports."
-msgstr ""
+msgstr "Wähle die übergeordnetste Gruppe für deine Repository-Importe."
msgid "Choose which groups you wish to synchronize to this secondary node."
-msgstr ""
+msgstr "Wähle die Gruppen aus, die du mit diesem sekundären Knoten synchronisieren möchtest."
msgid "Choose which repositories you want to connect and run CI/CD pipelines."
-msgstr ""
+msgstr "Wähle welche Repositories du verbinden und die CI/CD-Pipelines ausführen möchtest."
msgid "Choose which repositories you want to import."
-msgstr ""
+msgstr "Wähle aus, welche Repositories du importieren möchtest."
msgid "Choose which shards you wish to synchronize to this secondary node."
-msgstr ""
+msgstr "Wähle die Fragmente aus, die du mit diesem sekundären Knoten synchronisieren möchtest."
msgid "CiStatusLabel|canceled"
msgstr "abgebrochen"
@@ -1429,6 +1518,9 @@ msgstr "abgebrochen"
msgid "CiStatusLabel|created"
msgstr "erstellt"
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr "fehlgeschlagen"
@@ -1436,10 +1528,10 @@ msgid "CiStatusLabel|manual action"
msgstr "manuelles Eingreifen"
msgid "CiStatusLabel|passed"
-msgstr "absolviert"
+msgstr "bestanden"
msgid "CiStatusLabel|passed with warnings"
-msgstr "mit Warnungen absolviert"
+msgstr "mit Warnungen bestanden"
msgid "CiStatusLabel|pending"
msgstr "ausstehend"
@@ -1447,6 +1539,9 @@ msgstr "ausstehend"
msgid "CiStatusLabel|skipped"
msgstr "übersprungen"
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr "warte auf einen verzögerten Job"
+
msgid "CiStatusLabel|waiting for manual action"
msgstr "wartet auf manuelles Eingreifen"
@@ -1459,6 +1554,9 @@ msgstr "abgebrochen"
msgid "CiStatusText|created"
msgstr "erstellt"
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr "fehlgeschlagen"
@@ -1466,7 +1564,7 @@ msgid "CiStatusText|manual"
msgstr "manuell"
msgid "CiStatusText|passed"
-msgstr "absolviert"
+msgstr "bestanden"
msgid "CiStatusText|pending"
msgstr "ausstehend"
@@ -1478,505 +1576,523 @@ msgid "CiStatus|running"
msgstr "laufend"
msgid "CiVariables|Input variable key"
-msgstr ""
+msgstr "Variablenschlüssel eingeben"
msgid "CiVariables|Input variable value"
-msgstr ""
+msgstr "Variablenwert eingeben"
msgid "CiVariables|Remove variable row"
-msgstr ""
+msgstr "Variable jetzt löschen"
msgid "CiVariable|* (All environments)"
-msgstr ""
+msgstr "* (Alle Umgebungen)"
msgid "CiVariable|All environments"
-msgstr ""
+msgstr "Alle Umgebungen"
msgid "CiVariable|Create wildcard"
-msgstr ""
+msgstr "Wildcard erstellen"
msgid "CiVariable|Error occured while saving variables"
-msgstr ""
+msgstr "Beim Speichern der Variablen ist ein Fehler aufgetreten"
msgid "CiVariable|New environment"
-msgstr ""
+msgstr "Neue Umgebung"
msgid "CiVariable|Protected"
-msgstr ""
+msgstr "Geschützt"
msgid "CiVariable|Search environments"
-msgstr ""
+msgstr "Umgebungen durchsuchen"
msgid "CiVariable|Toggle protected"
-msgstr ""
+msgstr "Schutzstatus umschalten"
msgid "CiVariable|Validation failed"
-msgstr ""
-
-msgid "CircuitBreakerApiLink|circuitbreaker api"
-msgstr ""
+msgstr "Validierung fehlgeschlagen"
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
-msgstr ""
+msgstr "ist nicht verfügbar: %{reason}"
+
+msgid "Clear search"
+msgstr "Suche löschen"
msgid "Clear search input"
-msgstr ""
+msgstr "Suchfelder löschen"
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
-msgstr ""
+msgstr "Klicke auf einen beliebigen <strong>-Projektnamen</strong> in der folgenden Projektliste, um zum Projektmeilenstein zu navigieren."
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
-msgstr ""
+msgstr "Klicke auf den <strong>Download</strong>-Button und warte bis das Herunterladen abgeschlossen ist."
msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
-msgstr ""
+msgstr "Klicke auf die Schaltfläche <strong>Hochstufen</strong> in der oberen rechten Ecke, um einen ihn zu einem Gruppenmeilenstein hochzustufen."
msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
-msgstr ""
+msgstr "Klicke auf die Schaltfläche <strong>Keine auswählen</strong> auf der rechten Seite, da wir nur \"Google Code Project Hosting\" benötigen."
msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
-msgstr ""
+msgstr "Klicke auf die Schaltfläche unten um den Installationsprozess zu starten indem du auf die Kubernetes-Seite gehst"
msgid "Click to expand it."
-msgstr ""
+msgstr "Zum Erweitern klicken."
msgid "Click to expand text"
-msgstr ""
+msgstr "Klicke hier, um den Text zu erweitern"
msgid "Client authentication certificate"
-msgstr ""
+msgstr "Client-Authentifizierungszertifikat"
msgid "Client authentication key"
-msgstr ""
+msgstr "Client-Authentifizierungsschlüssel"
msgid "Client authentication key password"
-msgstr ""
+msgstr "Kennwort für den Client-Authentifizierungsschlüssel"
msgid "Clients"
-msgstr ""
+msgstr "Kunden"
msgid "Clone repository"
-msgstr ""
+msgstr "Repository klonen"
msgid "Close"
-msgstr ""
+msgstr "Schließen"
+
+msgid "Close epic"
+msgstr "Epic schließen"
msgid "Closed"
-msgstr ""
+msgstr "Geschlossen"
msgid "Closed issues"
-msgstr ""
+msgstr "Geschlossene Tickets"
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
-msgstr ""
+msgstr "%{appList} wurde erfolgreich auf deinem Kubernetes-Cluster installiert"
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
+msgstr "%{boldNotice} Hierdurch werden einige zusätzliche Ressourcen wie ein Load-Balancer hinzugefügt, was je nach Hosting-Provider, auf dem dein Kubernetes-Cluster installiert ist, zusätzliche Kosten verursachen kann. Wenn du Google Kubernetes-Engine verwendest, kannst du %{pricingLink}."
+
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
msgstr ""
msgid "ClusterIntegration|API URL"
-msgstr ""
+msgstr "API-URL"
msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr "Kubernetes-Cluster hinzufügen"
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
msgstr ""
-msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
-msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
msgstr ""
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgstr "Erweiterte Optionen für die Integration dieses Kubernetes-Clusters"
+
+msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr "Nachdem Ingress installiert wurde, solltest du deine Wildcard-DNS an die generierte externe IP-Adresse anpassen, um deine App nach der Bereitstellung sichtbar zu machen. %{ingressHelpLink}"
+
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
-msgstr ""
+msgstr "Beim Abrufen der Projektzonen ist ein Fehler aufgetreten: %{error}"
msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
-msgstr ""
+msgstr "Beim Abrufen deiner Projekte ist ein Fehler aufgetreten: %{error}"
msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
-msgstr ""
+msgstr "Ein Fehler ist bei dem Versuch aufgetreten die Maschinentypen der Zone aufzurufen: %{error}"
msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
-msgstr ""
+msgstr "Ein Fehler ist bei dem Verbindungsversuch mit der Google Cloud API aufgetreten. Bitte versuche es später erneut."
msgid "ClusterIntegration|Applications"
-msgstr ""
+msgstr "Anwendungen"
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
-msgstr ""
+msgstr "Bist du sicher, dass du die Integration dieses Kubernetes-Clusters entfernen möchtest? Dadurch wird dein tatsächlicher Kubernetes-Cluster nicht gelöscht."
msgid "ClusterIntegration|CA Certificate"
-msgstr ""
+msgstr "CA-Zertifikat"
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
-msgstr ""
+msgstr "Zertifizierungsstellen-Bundle (PEM-Format)"
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
-msgstr ""
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr "Wähle, welche Anwendungen auf deinem Kubernetes Cluster installiert werden sollen. Um eine der folgenden Anwendungen zu installieren ist Helm Tiller erforderlich."
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
-msgstr ""
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr "Wähle, welche deiner Umgebungen du für dieses Cluster verwenden willst."
msgid "ClusterIntegration|Copy API URL"
-msgstr ""
+msgstr "API-URL kopieren"
msgid "ClusterIntegration|Copy CA Certificate"
-msgstr ""
+msgstr "CA-Zertifikat kopieren"
msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
-msgstr ""
+msgstr "Ingress-IP-Adresse in die Zwischenablage kopieren"
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
-msgstr ""
+msgstr "Jupyter-Hostnamen in die Zwischenablage kopieren"
msgid "ClusterIntegration|Copy Kubernetes cluster name"
-msgstr ""
+msgstr "Kubernetes-Clusternamen kopieren"
msgid "ClusterIntegration|Copy Token"
-msgstr ""
+msgstr "Token kopieren"
msgid "ClusterIntegration|Create Kubernetes cluster"
-msgstr ""
+msgstr "Kubernetes-Cluster erstellen"
msgid "ClusterIntegration|Did you know?"
-msgstr ""
+msgstr "Wusstest du schon?"
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr "Aktiviere oder deaktiviere die Verbindung zwischen GitLab und deinem Kubernetes-Cluster."
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr "Aktiviere diese Einstellung, wenn rollenbasierte Zugriffskontrolle (RBAC) verwendet werden soll."
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
-msgstr ""
+msgstr "Gib die Details für deinen Kubernetes-Cluster ein"
msgid "ClusterIntegration|Environment scope"
-msgstr ""
+msgstr "Umgebungsumfang"
msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
-msgstr ""
+msgstr "Jedes neue Google Cloud Platform-Konto (GCP-Konto) erhält 300 $ Guthaben bei %{sign_up_link}. In Zusammenarbeit mit Google kann GitLab zusätzlich 200 $ für neue und bestehende GCP-Konten anbieten, um mit GitLabs Integration der Google Kubernetes-Engine zu beginnen."
msgid "ClusterIntegration|Fetching machine types"
-msgstr ""
+msgstr "Abrufen von Maschinentypen"
msgid "ClusterIntegration|Fetching projects"
-msgstr ""
+msgstr "Abrufen der Projekte"
msgid "ClusterIntegration|Fetching zones"
-msgstr ""
+msgstr "Rufe Zonen ab"
msgid "ClusterIntegration|GitLab Integration"
-msgstr ""
+msgstr "GitLab-Integration"
msgid "ClusterIntegration|GitLab Runner"
-msgstr ""
+msgstr "GitLab Runner"
msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
-msgstr ""
+msgstr "Gitlab Runner verbindet sich mit dem Repository für dieses Projekt und führt CI/CD-Jobs aus, ruft die Ergebnisse ab und veröffentlicht die Anwendung zur Produktionsumgebung."
msgid "ClusterIntegration|Google Cloud Platform project"
-msgstr ""
+msgstr "Google Cloud Platform-Projekt"
msgid "ClusterIntegration|Google Kubernetes Engine"
-msgstr ""
+msgstr "Google Kubernetes-Engine"
msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr "Google Kubernetes-Engine-Projekt"
+
+msgid "ClusterIntegration|Group cluster"
msgstr ""
msgid "ClusterIntegration|Helm Tiller"
-msgstr ""
+msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
+msgstr "Helm optimiert die Installation und Verwaltung von Kubernetes-Anwendungen. Tiller läuft innerhalb deines Kubernetes-Clusters und verwaltet Versionen deiner Charts."
msgid "ClusterIntegration|Hide"
-msgstr ""
+msgstr "Ausblenden"
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
-msgstr ""
+msgstr "Wenn du mehrere Cluster einrichtest und Auto-DevOps verwendest, lies zuerst %{help_link_start}dies%{help_link_end}."
msgid "ClusterIntegration|In order to show the health of the cluster, we'll need to provision your cluster with Prometheus to collect the required data."
-msgstr ""
+msgstr "Um den Zustand des Clusters anzuzeigen, müssen wir dein Cluster mit Prometheus bereitstellen, um die erforderlichen Daten zu sammeln."
msgid "ClusterIntegration|Ingress"
-msgstr ""
+msgstr "Ingress"
msgid "ClusterIntegration|Ingress IP Address"
-msgstr ""
+msgstr "Ingress-IP-Adresse"
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
-msgstr ""
+msgstr "Ingress bietet die Möglichkeit, Dienste-Anfragen je nach Anfragehost oder -pfad weiterzuleiten. So werden viele Dienste an einer Stelle zentral zusammengefasst."
msgid "ClusterIntegration|Install"
-msgstr ""
+msgstr "Installieren"
msgid "ClusterIntegration|Install Prometheus"
-msgstr ""
-
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
+msgstr "Prometheus installieren"
msgid "ClusterIntegration|Installed"
-msgstr ""
+msgstr "Installiert"
msgid "ClusterIntegration|Installing"
-msgstr ""
+msgstr "Installiere"
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
-msgstr ""
+msgstr "Kubernetes-Cluster-Automatisierung integrieren"
msgid "ClusterIntegration|Integration status"
-msgstr ""
+msgstr "Integrationsstatus"
msgid "ClusterIntegration|Jupyter Hostname"
-msgstr ""
+msgstr "Jupyter-Hostname"
msgid "ClusterIntegration|JupyterHub"
-msgstr ""
+msgstr "JupyterHub"
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
-msgstr ""
+msgstr "JupyterHub, ein Mehrbenutzer-Hub, erstellt, verwaltet und leitet mehrere Instanzen des Jupyter-Notebook-Servers für Einzelbenutzer. JupyterHub kann verwendet werden, um Notebooks an eine Klasse von Studenten, eine Unternehmens-Data-Science-Gruppe oder eine wissenschaftliche Forschungsgruppe zu liefern."
-msgid "ClusterIntegration|Kubernetes cluster"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster details"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster health"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
-msgstr ""
+msgid "ClusterIntegration|Kubernetes cluster"
+msgstr "Kubernetes-Cluster"
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
-msgstr ""
+msgid "ClusterIntegration|Kubernetes cluster details"
+msgstr "Kubernetes-Cluster-Details"
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
-msgstr ""
+msgid "ClusterIntegration|Kubernetes cluster health"
+msgstr "Zustand des Kubernetes-Cluster"
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
-msgstr ""
+msgstr "Kubernetes-Cluster wird mit der Google Kubernetes-Engine erstellt..."
msgid "ClusterIntegration|Kubernetes cluster name"
-msgstr ""
+msgstr "Kubernetes-Clustername"
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
-msgstr ""
+msgstr "Kubernetes-Cluster wurde erfolgreich mit der Google Kubernetes Engine erstellt. Aktualisiere die Seite um Clusterdetails anzuzeigen"
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
-msgstr ""
+msgstr "Kubernetes-Cluster können zum Bereitstellen von Anwendungen und zur Zur­ver­fü­gung­stel­lung von Review-Anwendungen für dieses Projekt verwendet werden"
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
-msgstr ""
-
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
+msgstr "Erfahre mehr über %{help_link_start_machine_type}Maschinentypen%{help_link_end} und %{help_link_start_pricing}Preise%{help_link_end}."
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
-msgstr ""
+msgstr "Erfahre mehr über %{help_link_start}Zonen%{help_link_end}."
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
-msgstr ""
+msgstr "Maschinentyp"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
-msgstr ""
+msgstr "Stelle sicher, dass dein Konto %{link_to_requirements}, um Kubernetes-Cluster zu erstellen"
msgid "ClusterIntegration|Manage"
-msgstr ""
+msgstr "Manage"
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
-msgstr ""
+msgstr "Verwalte dein Kubernetes-Cluster hier: %{link_gke}"
msgid "ClusterIntegration|More information"
-msgstr ""
-
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
+msgstr "Mehr Informationen"
msgid "ClusterIntegration|No machine types matched your search"
-msgstr ""
+msgstr "Keine Maschinentypen stimmen mit deiner Suche überein"
msgid "ClusterIntegration|No projects found"
-msgstr ""
+msgstr "Keine Projekte gefunden"
msgid "ClusterIntegration|No projects matched your search"
-msgstr ""
+msgstr "Keine Projekte entsprechen deiner Suche"
msgid "ClusterIntegration|No zones matched your search"
-msgstr ""
+msgstr "Keine Zonen entsprechen deiner Suche"
msgid "ClusterIntegration|Note:"
-msgstr ""
+msgstr "Hinweis:"
msgid "ClusterIntegration|Number of nodes"
-msgstr ""
+msgstr "Anzahl der Knoten"
msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
-msgstr ""
+msgstr "Bitte gib die Zugangsinformationen deines Kubernetes-Clusters ein. Wenn du Hilfe benötigst, kannst du unsere %{link_to_help_page} zu Kubernetes lesen"
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
-msgstr ""
+msgstr "Bitte stelle sicher, dass dein Google-Konto die folgenden Voraussetzungen erfüllt:"
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
+msgstr "Verweise mit einem Wildcard-DNS auf diese generierte IP-Adresse um auf deine Anwendung zugreifen zu können, nachdem sie bereitgestellt wurde."
+
+msgid "ClusterIntegration|Project cluster"
msgstr ""
msgid "ClusterIntegration|Project namespace"
-msgstr ""
+msgstr "Projekt-Namensraum"
msgid "ClusterIntegration|Project namespace (optional, unique)"
-msgstr ""
+msgstr "Projekt-Namensraum (optional, einzigartig)"
msgid "ClusterIntegration|Prometheus"
-msgstr ""
+msgstr "Prometheus"
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
+msgstr "Prometheus ist ein Open-Source-Ãœberwachungssystem mit %{gitlabIntegrationLink} zur Ãœberwachung von bereitgestellten Anwendungen."
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
msgstr ""
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
-msgstr ""
+msgstr "Lies unsere %{link_to_help_page} zur Kubernetes-Cluster-Integration."
msgid "ClusterIntegration|Remove Kubernetes cluster integration"
-msgstr ""
+msgstr "Entferne die Kubernetes-Cluster-Integration"
msgid "ClusterIntegration|Remove integration"
-msgstr ""
+msgstr "Integration entfernen"
msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
-msgstr ""
+msgstr "Entferne die Konfiguration dieses Kubernetes-Clusters aus diesem Projekt. Dein eigentliches Kubernetes-Cluster wird hierbei nicht gelöscht."
msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
-msgstr ""
+msgstr "Ersetze dies mit deinem eigenen Hostnamen wenn du möchtest. Wenn du dies tust, verweise mit deinem Hostnamen auf die Ingress-IP-Adresse oben."
msgid "ClusterIntegration|Request to begin installing failed"
-msgstr ""
+msgstr "Anfrage zur Installation fehlgeschlagen"
msgid "ClusterIntegration|Save changes"
-msgstr ""
+msgstr "Änderungen speichern"
msgid "ClusterIntegration|Search machine types"
-msgstr ""
+msgstr "Suche Maschinentypen"
msgid "ClusterIntegration|Search projects"
-msgstr ""
+msgstr "Suche Projekte"
msgid "ClusterIntegration|Search zones"
-msgstr ""
-
-msgid "ClusterIntegration|Security"
-msgstr ""
+msgstr "Suche Zonen"
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
-msgstr ""
+msgstr "Betrachte und ändere die Details deines Kubernetes-Clusters"
msgid "ClusterIntegration|Select machine type"
-msgstr ""
+msgstr "Wähle den Maschinentyp aus"
msgid "ClusterIntegration|Select project"
-msgstr ""
+msgstr "Wähle ein Projekt"
msgid "ClusterIntegration|Select project and zone to choose machine type"
-msgstr ""
+msgstr "Wähle ein Projekt und ein Zone, um den Maschinentyp auszuwählen"
msgid "ClusterIntegration|Select project to choose zone"
-msgstr ""
+msgstr "Wähle ein Projekt aus, um die Zone auszuwählen"
msgid "ClusterIntegration|Select zone"
-msgstr ""
+msgstr "Wähle eine Zone aus"
msgid "ClusterIntegration|Select zone to choose machine type"
-msgstr ""
+msgstr "Wähle eine Zone aus, um den Maschinentyp auszuwählen"
msgid "ClusterIntegration|Service token"
-msgstr ""
+msgstr "Servicetoken"
msgid "ClusterIntegration|Show"
-msgstr ""
+msgstr "Zeige"
msgid "ClusterIntegration|Something went wrong on our end."
-msgstr ""
+msgstr "Auf unserer Seite ist etwas schief gelaufen."
msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
-msgstr ""
+msgstr "Beim Erstellen deines Kubernetes-Clusters auf der Google Kubernetes Engine ist etwas schief gelaufen"
msgid "ClusterIntegration|Something went wrong while installing %{title}"
-msgstr ""
+msgstr "Beim Installieren von %{title} ist ein Fehler aufgetreten"
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
-msgstr ""
-
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
+msgstr "Die IP-Adresse wird gerade zugewiesen. Wenn es lange dauert, überprüfe bitte dein Kubernetes-Cluster oder dein Kontingent für die Google Kubernetes-Engine."
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
-msgstr ""
+msgstr "Dieses Konto benötigt die Berechtigungen um ein Kubernetes-Cluster in dem untenstehenden %{link_to_container_project} zu erstellen"
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
-msgstr ""
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr "Mit dieser Option kannst du Anwendungen auf RBAC-Clustern installieren."
msgid "ClusterIntegration|Toggle Kubernetes cluster"
-msgstr ""
+msgstr "Kubernetes-Cluster umschalten"
msgid "ClusterIntegration|Token"
-msgstr ""
+msgstr "Token"
msgid "ClusterIntegration|Validating project billing status"
-msgstr ""
+msgstr "Validierung des Projektabrechnungsstatus"
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
-msgstr ""
+msgstr "Wir konnten nicht verifizieren, ob für eines deiner Projekte auf GCP die Abrechnung aktiviert ist. Bitte versuche es erneut."
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr ""
+msgstr "Mit einem Kubernetes-Cluster innerhalb dieses Projekts kannst du auf einfache Weise Review-Anwendungen verwenden, deine Anwendungen bereitstellen, Pipelines ausführen und vieles mehr."
+
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr "Du musst zuerst Helm Tiller installieren, bevor du die Anwendung unten installierst"
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
-msgstr ""
+msgstr "Dein Account benötigt eine %{link_to_kubernetes_engine}"
msgid "ClusterIntegration|Zone"
-msgstr ""
+msgstr "Zone"
msgid "ClusterIntegration|access to Google Kubernetes Engine"
-msgstr ""
+msgstr "Zugriff zur Google Kubernetes-Engine"
msgid "ClusterIntegration|check the pricing here"
-msgstr ""
+msgstr "Unsere Preise findest du hier"
msgid "ClusterIntegration|documentation"
-msgstr ""
+msgstr "Dokumentation"
msgid "ClusterIntegration|help page"
-msgstr ""
-
-msgid "ClusterIntegration|installing applications"
-msgstr ""
+msgstr "Hilfeseite"
msgid "ClusterIntegration|meets the requirements"
-msgstr ""
+msgstr "erfüllt die Anforderungen"
msgid "ClusterIntegration|properly configured"
-msgstr ""
+msgstr "ordnungsgemäß konfiguriert"
msgid "ClusterIntegration|sign up"
-msgstr ""
+msgstr "Registrierung"
+
+msgid "Code owners"
+msgstr "Code-Besitzer(innen)"
msgid "Cohorts"
-msgstr ""
+msgstr "Kohorten"
msgid "Collapse"
-msgstr ""
+msgstr "Reduzieren"
msgid "Collapse sidebar"
-msgstr ""
+msgstr "Seitenleiste einklappen"
+
+msgid "Comment"
+msgstr "Kommentar"
msgid "Comment & resolve discussion"
-msgstr ""
+msgstr "Kommentieren & Diskussion beenden"
msgid "Comment & unresolve discussion"
-msgstr ""
+msgstr "Kommentieren & Diskussion wieder eröffnen"
+
+msgid "Comment form position"
+msgstr "Position des Kommentarformulars"
msgid "Comments"
msgstr "Kommentare"
@@ -1988,11 +2104,11 @@ msgstr[1] "Commits"
msgid "Commit (%{commit_count})"
msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Commit (%{commit_count})"
+msgstr[1] "Commits (%{commit_count})"
msgid "Commit Message"
-msgstr ""
+msgstr "Commit-Nachricht"
msgid "Commit duration in minutes for last 30 commits"
msgstr "Dauer der Commits in Minuten für die letzten 30 Commits"
@@ -2001,10 +2117,10 @@ msgid "Commit message"
msgstr "Commit Nachricht"
msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
-msgstr ""
+msgstr "Commit-Statistik für %{ref} %{start_time} - %{end_time}"
msgid "Commit to %{branchName} branch"
-msgstr ""
+msgstr "Committe zum %{branchName}-Branch"
msgid "CommitBoxTitle|Commit"
msgstr "Commit"
@@ -2012,6 +2128,9 @@ msgstr "Commit"
msgid "CommitMessage|Add %{file_name}"
msgstr "%{file_name} hinzufügen"
+msgid "CommitWidget|authored"
+msgstr "erstellt"
+
msgid "Commits"
msgstr "Commits"
@@ -2019,313 +2138,340 @@ msgid "Commits feed"
msgstr "Liste der Commits"
msgid "Commits per day hour (UTC)"
-msgstr ""
+msgstr "Commits pro Stunde des Tages (UTC)"
msgid "Commits per day of month"
-msgstr ""
+msgstr "Commits pro Tag des Monats"
msgid "Commits per weekday"
-msgstr ""
+msgstr "Commits pro Wochentag"
msgid "Commits|An error occurred while fetching merge requests data."
-msgstr ""
+msgstr "Beim Abrufen der Daten des Merge-Requests ist ein Fehler aufgetreten."
msgid "Commits|Commit: %{commitText}"
-msgstr ""
+msgstr "Commit: %{commitText}"
msgid "Commits|History"
msgstr "Verlauf"
msgid "Commits|No related merge requests found"
-msgstr ""
+msgstr "Keine zugehörigen Merge-Requests gefunden"
msgid "Committed by"
msgstr "Committed von"
msgid "Commit…"
-msgstr ""
+msgstr "Commit…"
msgid "Compare"
msgstr "Vergleichen"
msgid "Compare Git revisions"
-msgstr ""
+msgstr "Vergleiche Git-Revisionen"
msgid "Compare Revisions"
-msgstr ""
+msgstr "Vergleiche Revisionen"
msgid "Compare changes with the last commit"
-msgstr ""
+msgstr "Vergleiche Änderungen mit dem letzten Commit"
msgid "Compare changes with the merge request target branch"
-msgstr ""
+msgstr "Vergleiche die Änderungen mit dem Zielbranch des Merge-Requests"
msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
-msgstr ""
+msgstr "%{source_branch} und %{target_branch} sind gleich."
msgid "CompareBranches|Compare"
-msgstr ""
+msgstr "Vergleichen"
msgid "CompareBranches|Source"
-msgstr ""
+msgstr "Quelle"
msgid "CompareBranches|Target"
-msgstr ""
+msgstr "Ziel"
msgid "CompareBranches|There isn't anything to compare."
-msgstr ""
+msgstr "Es gibt nichts zu vergleichen."
msgid "Confidential"
-msgstr ""
+msgstr "Vertraulich"
msgid "Confidentiality"
-msgstr ""
+msgstr "Vertraulichkeit"
msgid "Configure Gitaly timeouts."
-msgstr ""
+msgstr "Zeitüberschreitung für Gitaly konfigurieren."
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
-msgstr ""
+msgstr "Automatische \"Git-Checks\" und Bereinigung für Repositories konfigurieren."
msgid "Configure limits for web and API requests."
-msgstr ""
+msgstr "Einschränkungen für Web- und API-Anfragen konfigurieren."
-msgid "Configure push and pull mirrors."
-msgstr ""
+msgid "Configure push mirrors."
+msgstr "Push-Mirrors konfigurieren."
-msgid "Configure storage path and circuit breaker settings."
-msgstr ""
+msgid "Configure storage path settings."
+msgstr "Konfiguriere die Speicherpfadeinstellungen."
msgid "Configure the %{link} integration."
-msgstr ""
+msgstr "Die %{link}-Integration konfigurieren."
msgid "Configure the way a user creates a new account."
-msgstr ""
+msgstr "Konfiguriere, wie ein(e) Benutzer(in) ein neues Konto erstellt."
msgid "Connect"
-msgstr ""
+msgstr "Verbinden"
msgid "Connect all repositories"
-msgstr ""
+msgstr "Alle Repositorys verbinden"
msgid "Connect repositories from GitHub"
-msgstr ""
+msgstr "GitHub-Repositorys verbinden"
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
-msgstr ""
+msgstr "Verbinde deine externen Repositories, und CI/CD-Pipelines werden für neue Commits ausgeführt. Ein GitLab-Projekt wird nur mit aktivierten CI/CD-Funktionen erstellt."
msgid "Connecting..."
-msgstr ""
+msgstr "Verbinden..."
msgid "Container Registry"
-msgstr ""
+msgstr "Container-Registry"
msgid "ContainerRegistry|Created"
-msgstr ""
+msgstr "Erstellt"
msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
-msgstr ""
+msgstr "Melde dich zunächst mit deinem GitLab-Benutzernamen und Passwort in GitLabs Container-Registry an. Wenn du %{link_2fa} hast, musst du ein %{link_token} verwenden:"
msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
-msgstr ""
+msgstr "GitLab unterstützt bis zu 3 Ebenen von Image-Namen. Die folgenden Beispiel-Images gelten für dein Projekt:"
msgid "ContainerRegistry|How to use the Container Registry"
-msgstr ""
+msgstr "Wie man die Container-Registry verwendet"
msgid "ContainerRegistry|Learn more about"
-msgstr ""
+msgstr "Erfahre mehr über"
msgid "ContainerRegistry|No tags in Container Registry for this container image."
-msgstr ""
+msgstr "Keine Tags in der Container-Registry für dieses Container-Image."
msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
-msgstr ""
+msgstr "Sobald du dich eingeloggt hast, steht es dir frei, ein Container-Image mit den üblichen %{build}- und %{push}-Befehlen zu erstellen und hochzuladen"
msgid "ContainerRegistry|Remove repository"
-msgstr ""
+msgstr "Repository entfernen"
msgid "ContainerRegistry|Remove tag"
-msgstr ""
+msgstr "Tag entfernen"
msgid "ContainerRegistry|Size"
-msgstr ""
+msgstr "Größe"
msgid "ContainerRegistry|Tag"
-msgstr ""
+msgstr "Tag"
msgid "ContainerRegistry|Tag ID"
-msgstr ""
+msgstr "Tag-ID"
msgid "ContainerRegistry|Use different image names"
-msgstr ""
+msgstr "Verwende einen anderen Image-Namen"
msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
-msgstr ""
+msgstr "Mit der in GitLab integrierten Docker-Container-Registry kann jedes Projekt seinen eigenen Speicherplatz haben um seine Docker-Images zu speichern."
msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
-msgstr ""
+msgstr "Du kannst auch %{deploy_token} für den schreibgeschützten Zugriff auf die Registry-Images verwenden."
msgid "Continue"
-msgstr ""
+msgstr "Fortsetzen"
msgid "Continue to the next step"
-msgstr ""
+msgstr "Fahre mit dem nächsten Schritt fort"
msgid "Continuous Integration and Deployment"
-msgstr ""
+msgstr "Kontinuierliche Integration und Bereitstellung"
msgid "Contribute to GitLab"
-msgstr ""
+msgstr "Trage etwas zu GitLab bei"
msgid "Contribution"
-msgstr ""
+msgstr "Beitrag"
msgid "Contribution guide"
-msgstr "Mitarbeitsanleitung"
+msgstr "Anleitung zur Mitarbeit"
+
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr "Beiträge am <strong>%{calendar_date}</strong>"
msgid "Contributions per group member"
-msgstr ""
+msgstr "Beiträge pro Gruppenmitglied"
msgid "Contributors"
-msgstr "Mitarbeiter"
+msgstr "Mitwirkende"
msgid "ContributorsPage|%{startDate} – %{endDate}"
-msgstr ""
+msgstr "%{startDate} – %{endDate}"
msgid "ContributorsPage|Building repository graph."
-msgstr ""
+msgstr "Repository-Graph wird erstellt."
msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
-msgstr ""
+msgstr "Commits für %{branch_name}, ausgenommen Merge-Commits. Limitiert auf 6.000 Commits."
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
-msgstr ""
+msgstr "Bitte warte einen Moment, diese Seite wird automatisch aktualisiert, wenn bereit."
msgid "Control the display of third party offers."
-msgstr ""
+msgstr "Steuern Sie die Anzeige von Angeboten Dritter."
msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
-msgstr ""
+msgstr "Kontrolliere die maximale Parallelität des LFS/Anhangs-Backfills für diesen sekundären Knoten"
msgid "Control the maximum concurrency of repository backfill for this secondary node"
-msgstr ""
+msgstr "Steuere die maximale Parallelität des Repository-Backfills für diesen sekundären Knoten"
msgid "Control the maximum concurrency of verification operations for this Geo node"
-msgstr ""
+msgstr "Steuere die maximale Parallelität von Verifizierungsoperationen für diesen Geo-Knoten"
msgid "ConvDev Index"
-msgstr ""
+msgstr "ConvDev-Index"
+
+msgid "Copy %{protocol} clone URL"
+msgstr "Kopiere %{protocol} clone-URL"
+
+msgid "Copy HTTPS clone URL"
+msgstr "Kopiere HTTPS clone-URL"
+
+msgid "Copy ID to clipboard"
+msgstr "ID in Zwischenablage kopieren"
+
+msgid "Copy SSH clone URL"
+msgstr "Kopiere SSH clone-URL"
msgid "Copy SSH public key to clipboard"
-msgstr ""
+msgstr "Kopiere öffentlichen SSH-Schlüssel in die Zwischenablage"
msgid "Copy URL to clipboard"
msgstr "Kopiere URL in die Zwischenablage"
msgid "Copy branch name to clipboard"
-msgstr ""
+msgstr "Branch-Name in Zwischenablage kopieren"
msgid "Copy command to clipboard"
-msgstr ""
+msgstr "Kommando in Zwischenablage kopieren"
msgid "Copy commit SHA to clipboard"
msgstr "Kopiere Commit SHA in die Zwischenablage"
msgid "Copy file path to clipboard"
-msgstr ""
+msgstr "Dateipfad in Zwischenablage kopieren"
msgid "Copy incoming email address to clipboard"
+msgstr "Eingehende E-Mail-Adresse in Zwischenablage kopieren"
+
+msgid "Copy link"
msgstr ""
+msgid "Copy name to clipboard"
+msgstr "Name in Zwischenablage kopieren"
+
msgid "Copy reference to clipboard"
+msgstr "Referenz in Zwischenablage kopieren"
+
+msgid "Copy secret to clipboard"
msgstr ""
msgid "Copy to clipboard"
-msgstr ""
+msgstr "In Zwischenablage kopieren"
msgid "Copy token to clipboard"
+msgstr "Token in Zwischenablage kopieren"
+
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
msgstr ""
msgid "Create"
-msgstr ""
+msgstr "Erstellen"
msgid "Create New Directory"
msgstr "Erstelle neues Verzeichnis"
msgid "Create a new branch"
-msgstr ""
+msgstr "Erstelle einen neuen Branch"
msgid "Create a new branch and merge request"
-msgstr ""
+msgstr "Erstelle einen neuen Branch und Merge-Request"
msgid "Create a new issue"
-msgstr ""
+msgstr "Neues Ticket erstellen"
msgid "Create a personal access token on your account to pull or push via %{protocol}."
-msgstr "Erstelle einen persönlichen Zugriffstoken in Deinem Konto um mittels %{protocol} zu übertragen (push) oder abzurufen (pull)."
+msgstr "Erstelle einen persönlichen Zugriffstoken in deinem Konto um mittels %{protocol} zu übertragen (push) oder abzurufen (pull)."
msgid "Create branch"
-msgstr ""
+msgstr "Branch erstellen"
msgid "Create commit"
-msgstr ""
+msgstr "Commit erstellen"
msgid "Create directory"
msgstr "Erstelle Verzeichnis"
msgid "Create empty repository"
-msgstr ""
+msgstr "Erstelle leeres Repository"
msgid "Create epic"
-msgstr ""
+msgstr "Epic anlegen"
msgid "Create file"
-msgstr ""
+msgstr "Datei erstellen"
msgid "Create group"
-msgstr ""
+msgstr "Gruppe erstellen"
msgid "Create group label"
-msgstr ""
+msgstr "Gruppen-Label erstellen"
msgid "Create issue"
-msgstr ""
+msgstr "Ticket erstellen"
msgid "Create lists from labels. Issues with that label appear in that list."
-msgstr ""
+msgstr "Erstelle Listen anhand von Labels. Tickets mit diesem Label werden in dieser Liste angezeigt."
msgid "Create merge request"
-msgstr "Erstelle Merge Request"
+msgstr "Erstelle Merge-Request"
msgid "Create merge request and branch"
-msgstr ""
+msgstr "Merge-Request und Branch erstellen"
msgid "Create new branch"
-msgstr ""
+msgstr "Neuen Branch erstellen"
msgid "Create new directory"
-msgstr ""
+msgstr "Neues Verzeichnis erstellen"
msgid "Create new file"
-msgstr ""
+msgstr "Neue Datei erstellen"
msgid "Create new file or directory"
-msgstr ""
+msgstr "Erstelle eine neue Datei oder ein neues Verzeichnis"
msgid "Create new label"
-msgstr ""
+msgstr "Neues Label erstellen"
msgid "Create new..."
-msgstr "Erstelle neues..."
+msgstr "Neu erstellen..."
msgid "Create project label"
-msgstr ""
+msgstr "Projektlabel erstellen"
-msgid "CreateNewFork|Fork"
-msgstr "Ableger"
+msgid "Create your first page"
+msgstr "Erstelle deine erste Seite"
msgid "CreateTag|Tag"
msgstr "Tag "
@@ -2334,73 +2480,79 @@ msgid "CreateTokenToCloneLink|create a personal access token"
msgstr "Erstelle einen persönlichen Zugriffstoken"
msgid "Created"
-msgstr ""
+msgstr "Erstellt"
msgid "Created At"
-msgstr ""
+msgstr "Erstellt am"
msgid "Created by me"
-msgstr ""
+msgstr "Von mir erstellt"
msgid "Created on"
-msgstr ""
+msgstr "Erstellt am"
msgid "Created on:"
-msgstr ""
+msgstr "Erstellt am:"
msgid "Creating epic"
-msgstr ""
+msgstr "Epic wird angelegt"
msgid "Cron Timezone"
-msgstr "Cron Zeitzone"
+msgstr "Cron-Zeitzone"
msgid "Cron syntax"
-msgstr "Cron Syntax"
+msgstr "Cron-Syntax"
msgid "Current Branch"
-msgstr ""
+msgstr "Aktueller Branch"
msgid "Current node"
-msgstr ""
+msgstr "Aktueller Knoten"
msgid "CurrentUser|Profile"
-msgstr ""
+msgstr "Profil"
msgid "CurrentUser|Settings"
-msgstr ""
+msgstr "Einstellungen"
msgid "Custom"
-msgstr ""
+msgstr "Benutzerdefiniert"
msgid "Custom CI config path"
-msgstr ""
+msgstr "Benutzerdefinierter CI-Konfigurationspfad"
+
+msgid "Custom hostname (for private commit emails)"
+msgstr "Benutzerdefinierter Hostname (für private Commit-E-Mails)"
msgid "Custom notification events"
-msgstr "Individuelle Benachrichtigungsereignisse"
+msgstr "Benutzerdefinierte Benachrichtigungsereignisse"
msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
-msgstr "Individuelle Benachrichtigungsstufen sind identisch mit den Beteiligungsstufen. Mit individuellen Benachrichtigungsstufen erhältst Du ebenfalls Mitteilungen für ausgewählte Ereignisse. Für weitere Informationen lies %{notification_link}. "
+msgstr "Benutzerdefinierte Benachrichtigungsstufen sind identisch mit den Beteiligungsstufen. Mit benutzerdefinierten Benachrichtigungsstufen erhältst du ebenfalls Mitteilungen für ausgewählte Ereignisse. Für weitere Informationen lies %{notification_link}."
msgid "Custom project templates"
-msgstr ""
+msgstr "Benutzerspezifische Projektvorlage"
msgid "Customize colors"
-msgstr ""
+msgstr "Farben anpassen"
msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
-msgstr ""
+msgstr "Passe an, wie E-Mail-Adressen und Benutzernamen von FogBugz in GitLab importiert werden. Im nächsten Schritt kannst du die Projekte auswählen, die du importieren möchtest."
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr "Passe an, wie E-Mail-Adressen und Benutzernamen von Google Code in GitLab importiert werden. Im nächsten Schritt kannst du die Projekte auswählen, die du importieren möchtest."
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
msgid "Cycle Analytics"
-msgstr "Arbeitsablaufsanalysen"
+msgstr "Zyklusanalysen"
msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
-msgstr ""
+msgstr "Zyklusanalysen liefern einen Überblick darüber, wie viel Zeit in deinem Projekt von einer Idee bis zur Bereitstellung vergeht."
msgid "CycleAnalyticsStage|Code"
-msgstr "Entwicklung"
+msgstr "Code"
msgid "CycleAnalyticsStage|Issue"
msgstr "Ticket"
@@ -2412,7 +2564,7 @@ msgid "CycleAnalyticsStage|Production"
msgstr "Produktion"
msgid "CycleAnalyticsStage|Review"
-msgstr "Überprüfung"
+msgstr "Review"
msgid "CycleAnalyticsStage|Staging"
msgstr "Staging"
@@ -2421,58 +2573,79 @@ msgid "CycleAnalyticsStage|Test"
msgstr "Test"
msgid "Dashboard"
-msgstr ""
+msgstr "Dashboard"
msgid "DashboardProjects|All"
-msgstr ""
+msgstr "Alle"
msgid "DashboardProjects|Personal"
-msgstr ""
+msgstr "Persönliche"
msgid "Date picker"
-msgstr ""
+msgstr "Datumsauswahl"
msgid "Debug"
-msgstr ""
+msgstr "Debug"
msgid "Dec"
-msgstr ""
+msgstr "Dez"
msgid "December"
-msgstr ""
+msgstr "Dezember"
msgid "Decline and sign out"
-msgstr ""
+msgstr "Ablehnen und abmelden"
+
+msgid "Default Branch"
+msgstr "Default-Branch"
msgid "Default classification label"
-msgstr ""
+msgstr "Standardklassifikationslabel"
msgid "Default: Directly import the Google Code email address or username"
-msgstr ""
+msgstr "Standard: Importiere direkt die Google Code-E-Mail-Adresse oder den Nutzernamen"
msgid "Default: Map a FogBugz account ID to a full name"
-msgstr ""
+msgstr "Standard: Ordne eine FogBugz-Konto-ID einem vollständigen Namen zu"
msgid "Define a custom pattern with cron syntax"
-msgstr "Erstelle ein individuelles Muster mittels Cron Syntax"
+msgstr "Erstelle ein benutzerdefiniertes Muster mittels Cron-Syntax"
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr "Jetzt starten"
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
msgid "Delete"
msgstr "Löschen"
msgid "Delete Package"
-msgstr ""
+msgstr "Paket löschen"
msgid "Delete Snippet"
+msgstr "Codeausschnitt löschen"
+
+msgid "Delete comment"
msgstr ""
msgid "Delete list"
-msgstr ""
+msgstr "Liste löschen"
msgid "Deleted"
-msgstr ""
+msgstr "Gelöscht"
msgid "Deny"
-msgstr ""
+msgstr "Verweigern"
msgid "Deploy"
msgid_plural "Deploys"
@@ -2480,208 +2653,238 @@ msgstr[0] "Bereitstellung"
msgstr[1] "Bereitstellungen"
msgid "Deploy Keys"
-msgstr ""
+msgstr "Bereitstellungsschlüssel"
msgid "DeployKeys|+%{count} others"
-msgstr ""
+msgstr "+%{count} andere"
msgid "DeployKeys|Current project"
-msgstr ""
+msgstr "Aktuelles Projekt"
msgid "DeployKeys|Deploy key"
-msgstr ""
+msgstr "Bereitstellungsschlüssel"
msgid "DeployKeys|Enabled deploy keys"
-msgstr ""
+msgstr "Aktive Bereitstellungsschlüssel"
msgid "DeployKeys|Error enabling deploy key"
-msgstr ""
+msgstr "Fehler beim aktivieren des Bereitstellungsschlüssel"
msgid "DeployKeys|Error getting deploy keys"
-msgstr ""
+msgstr "Fehler beim Abrufen der Bereitstellungsschlüssel"
msgid "DeployKeys|Error removing deploy key"
-msgstr ""
+msgstr "Fehler beim entfernen der Bereitstellungsschlüssel"
msgid "DeployKeys|Expand %{count} other projects"
-msgstr ""
+msgstr "Erweitere %{count} andere Projekte"
msgid "DeployKeys|Loading deploy keys"
-msgstr ""
+msgstr "Lade Bereitstellungsschlüssel"
msgid "DeployKeys|No deploy keys found. Create one with the form above."
-msgstr ""
+msgstr "Keine Bereitstellungsschlüssel gefunden. Erstelle einem mit dem Formular oben."
msgid "DeployKeys|Privately accessible deploy keys"
-msgstr ""
+msgstr "Privat zugängliche Bereitstellungsschlüssel"
msgid "DeployKeys|Project usage"
-msgstr ""
+msgstr "Projektnutzung"
msgid "DeployKeys|Publicly accessible deploy keys"
-msgstr ""
+msgstr "Öffentlich zugängliche Bereitstellungsschlüssel"
msgid "DeployKeys|Read access only"
-msgstr ""
+msgstr "Nur Lesezugriff"
msgid "DeployKeys|Write access allowed"
-msgstr ""
+msgstr "Nur Schreibzugriff"
msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
-msgstr ""
+msgstr "Du bist dabei diesen Bereitstellungsschlüssel zu entfernen. Bist du sicher?"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
-msgstr ""
+msgstr "Aktive Bereitstellungstoken (%{active_tokens})"
msgid "DeployTokens|Add a deploy token"
-msgstr ""
+msgstr "Bereitstellungstoken hinzufügen"
msgid "DeployTokens|Allows read-only access to the registry images"
-msgstr ""
+msgstr "Ermöglicht schreibgeschützten Zugriff auf die Registry-Images"
msgid "DeployTokens|Allows read-only access to the repository"
-msgstr ""
+msgstr "Ermöglicht schreibgeschützten Zugriff auf das Repository"
msgid "DeployTokens|Copy deploy token to clipboard"
-msgstr ""
+msgstr "Kopiere den Bereitstellungstoken in die Zwischenablage"
msgid "DeployTokens|Copy username to clipboard"
-msgstr ""
+msgstr "Kopiere den Benutzernamen in die Zwischenablage"
msgid "DeployTokens|Create deploy token"
-msgstr ""
+msgstr "Bereitstellungstoken erstellen"
msgid "DeployTokens|Created"
-msgstr ""
+msgstr "Erstellt"
msgid "DeployTokens|Deploy Tokens"
-msgstr ""
+msgstr "Bereitstellungstoken"
msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
-msgstr ""
+msgstr "Bereitstellungstoken ermöglichen schreibgeschützten Zugriff auf deine Repositories und Registry-Images."
msgid "DeployTokens|Expires"
-msgstr ""
+msgstr "Verfällt"
msgid "DeployTokens|Name"
-msgstr ""
+msgstr "Name"
msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
-msgstr ""
+msgstr "Wähle einen Namen für die Anwendung und wir geben dir einen eindeutigen Bereitstellungstoken."
msgid "DeployTokens|Revoke"
-msgstr ""
+msgstr "Widerrufen"
msgid "DeployTokens|Revoke %{name}"
-msgstr ""
+msgstr "Widerrufe %{name}"
msgid "DeployTokens|Scopes"
-msgstr ""
+msgstr "Gültigkeitsbereiche"
msgid "DeployTokens|This action cannot be undone."
-msgstr ""
+msgstr "Diese Aktion kann nicht rückgängig gemacht werden."
msgid "DeployTokens|This project has no active Deploy Tokens."
-msgstr ""
+msgstr "Dieses Projekt hat keine aktiven Bereitstellungstoken."
msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
-msgstr ""
+msgstr "Verwende diesen Token als Kennwort. Stelle sicher, dass du ihn speicherst - du wirst später nicht mehr darauf zugreifen können."
msgid "DeployTokens|Use this username as a login."
-msgstr ""
+msgstr "Verwende diesen Benutzernamen als Login."
msgid "DeployTokens|Username"
-msgstr ""
+msgstr "Benutzername"
msgid "DeployTokens|You are about to revoke"
-msgstr ""
+msgstr "Du bist dabei zu widerrufen"
msgid "DeployTokens|Your New Deploy Token"
-msgstr ""
+msgstr "Dein neuer Bereitstellungstoken"
msgid "DeployTokens|Your new project deploy token has been created."
-msgstr ""
+msgstr "Dein neuer Projektbereitstellungstoken wurde erstellt."
+
+msgid "Deployed to"
+msgstr "Bereitgestellt für"
+
+msgid "Deploying to"
+msgstr "Bereitstellung für"
msgid "Deprioritize label"
-msgstr ""
+msgstr "Label entpriorisieren"
msgid "Descending"
-msgstr ""
+msgstr "Absteigend"
msgid "Description"
msgstr "Beschreibung"
msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
-msgstr ""
+msgstr "Beschreibungsvorlagen ermöglichen dir, kontextspezifische Vorlagen für das Beschreibungsfeld von Tickets und Merge-Requests für dein Projekts zu definieren."
msgid "Description:"
-msgstr ""
+msgstr "Beschreibung:"
msgid "Destroy"
-msgstr ""
+msgstr "Löschen"
msgid "Details"
msgstr "Details"
msgid "Detect host keys"
+msgstr "Hostschlüssel erkennen"
+
+msgid "Diff content limits"
msgstr ""
+msgid "Diff limits"
+msgstr "Diff-Grenzen"
+
msgid "Diffs|No file name available"
-msgstr ""
+msgstr "Kein Dateiname verfügbar"
msgid "Diffs|Something went wrong while fetching diff lines."
-msgstr ""
+msgstr "Etwas ging schief, während die Diff-Zeilen abgerufen wurden."
msgid "Direction"
-msgstr ""
+msgstr "Richtung"
msgid "Directory name"
msgstr "Verzeichnisname"
msgid "Disable"
-msgstr ""
+msgstr "Deaktivieren"
msgid "Disable for this project"
-msgstr ""
+msgstr "Für dieses Projekt deaktivieren"
msgid "Disable group Runners"
-msgstr ""
+msgstr "Gruppen-Runner deaktivieren"
+
+msgid "Discard"
+msgstr "Verwerfen"
+
+msgid "Discard all changes"
+msgstr "Alle Änderungen verwerfen"
+
+msgid "Discard all unstaged changes?"
+msgstr "Nicht vorgemerkte Änderungen verwerfen?"
msgid "Discard changes"
-msgstr ""
+msgstr "Änderungen verwerfen"
+
+msgid "Discard changes to %{path}?"
+msgstr "Änderungen in %{path} verwerfen?"
msgid "Discard draft"
-msgstr ""
+msgstr "Entwurf verwerfen"
+
+msgid "Discard review"
+msgstr "Review verwerfen"
msgid "Discover GitLab Geo."
-msgstr ""
+msgstr "Entdecke GitLab Geo."
msgid "Discover projects, groups and snippets. Share your projects with others"
-msgstr ""
+msgstr "Entdecke Projekte, Gruppen und Codeausschnitte. Teile deine Projekte mit anderen"
msgid "Dismiss"
-msgstr ""
+msgstr "Verwerfen"
msgid "Dismiss Cycle Analytics introduction box"
-msgstr ""
+msgstr "Einführungsbox zur Zyklusanalyse ausblenden"
msgid "Dismiss Merge Request promotion"
+msgstr "Hervorheben des Merge-Requests beenden"
+
+msgid "Dismiss trial promotion"
msgstr ""
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
-msgstr ""
+msgstr "Möchtest du festlegen, wie die E-Mail-Adressen und Nutzernamen von Google Code in GitLab importiert werden?"
msgid "Documentation for popular identity providers"
-msgstr ""
+msgstr "Dokumentation für gängige Identitätsanbieter"
msgid "Domain"
-msgstr ""
+msgstr "Domäne"
msgid "Don't show again"
msgstr "Nicht erneut anzeigen"
msgid "Done"
-msgstr ""
+msgstr "Erledigt"
msgid "Download"
msgstr "Herunterladen"
@@ -2702,322 +2905,325 @@ msgid "DownloadArtifacts|Download"
msgstr "Herunterladen"
msgid "DownloadCommit|Email Patches"
-msgstr "E-Mail Patch"
+msgstr "E-Mail-Patch"
msgid "DownloadCommit|Plain Diff"
-msgstr "Unterschiede"
+msgstr "Einfaches Diff"
msgid "DownloadSource|Download"
msgstr "Herunterladen"
msgid "Downvotes"
-msgstr ""
+msgstr "Negativ bewertet"
msgid "Due date"
-msgstr ""
+msgstr "Fälligkeitsdatum"
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
-msgstr ""
+msgstr "Während dieses Vorgangs wirst du nach URLs von GitLab gefragt. Verwende die unten angezeigten URLs."
msgid "Each Runner can be in one of the following states:"
-msgstr ""
+msgstr "Jeder Runner kann in einem der folgenden Zustände sein:"
msgid "Edit"
msgstr "Bearbeiten"
msgid "Edit Label"
-msgstr ""
+msgstr "Label bearbeiten"
msgid "Edit Pipeline Schedule %{id}"
-msgstr "Pipeline Zeitplan bearbeiten %{id}"
+msgstr "Pipeline-Zeitplan bearbeiten %{id}"
msgid "Edit Snippet"
-msgstr ""
+msgstr "Codeausschnitt bearbeiten"
msgid "Edit application"
-msgstr ""
+msgstr "Anwendung bearbeiten"
msgid "Edit files in the editor and commit changes here"
-msgstr ""
+msgstr "Bearbeite Dateien im Editor und committe die Änderungen hier"
msgid "Edit group: %{group_name}"
-msgstr ""
+msgstr "Gruppe bearbeiten: %{group_name}"
msgid "Edit identity for %{user_name}"
-msgstr ""
+msgstr "Identität für %{user_name} bearbeiten"
msgid "Elasticsearch"
-msgstr ""
+msgstr "Elasticsearch"
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
-msgstr ""
+msgstr "E-Mail"
msgid "Email patch"
-msgstr ""
+msgstr "E-Mail-Patch"
msgid "Emails"
msgstr "E-Mails"
msgid "Embed"
-msgstr ""
+msgstr "Einbetten"
msgid "Enable"
-msgstr ""
+msgstr "Aktivieren"
msgid "Enable Auto DevOps"
-msgstr ""
+msgstr "Auto-DevOps aktivieren"
msgid "Enable Pseudonymizer data collection"
-msgstr ""
+msgstr "Aktiviere die Pseudonymizer-Datensammlung"
msgid "Enable SAML authentication for this group"
-msgstr ""
+msgstr "SAML-Authentifizierung für diese Gruppe aktivieren"
msgid "Enable Sentry for error reporting and logging."
-msgstr ""
+msgstr "Aktiviere Sentry für die Fehlerberichterstattung und -protokollierung."
msgid "Enable and configure InfluxDB metrics."
-msgstr ""
+msgstr "Aktiviere und konfiguriere InfluxDB-Messwerte."
msgid "Enable and configure Prometheus metrics."
-msgstr ""
+msgstr "Aktiviere und konfiguriere Prometheus-Messwerte."
msgid "Enable classification control using an external service"
-msgstr ""
+msgstr "Aktiviere die Klassifizierungskontrolle mithilfe eines externen Service"
msgid "Enable for this project"
-msgstr ""
+msgstr "Für dieses Projekt aktivieren"
msgid "Enable group Runners"
-msgstr ""
-
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
+msgstr "Gruppen-Runner aktivieren"
msgid "Enable or disable the Pseudonymizer data collection."
-msgstr ""
+msgstr "Aktiviere oder deaktiviere die Pseudonymizer-Datensammlung."
msgid "Enable or disable version check and usage ping."
-msgstr ""
+msgstr "Aktiviere oder deaktiviere die Versionsprüfung und den Nutzungsbericht."
msgid "Enable reCAPTCHA or Akismet and set IP limits."
-msgstr ""
+msgstr "Aktiviere reCAPTCHA oder Akismet und lege die IP-Grenzwerte fest."
msgid "Enable the Performance Bar for a given group."
-msgstr ""
+msgstr "Aktiviere die Performance-Leiste für eine bestimmte Gruppe."
+
+msgid "Enable usage ping"
+msgstr "Nutzungsbericht einschalten"
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr "Nutzungsbericht einschalten um einen Ãœberblick zu erhalten, welche Features von GitLab wie benutzt werden."
msgid "Enabled"
-msgstr ""
+msgstr "Aktiviert"
msgid "Ends at (UTC)"
-msgstr ""
+msgstr "Endet am (UTC)"
msgid "Enter in your Bitbucket Server URL and personal access token below"
-msgstr ""
+msgstr "Gib unten deine Bitbucket-Server-URL und deinen persönlichen Zugriffstoken ein"
msgid "Enter the issue description"
-msgstr ""
+msgstr "Gib die Beschreibung des Tickets ein"
msgid "Enter the issue title"
-msgstr ""
+msgstr "Gib den Titel des Tickets ein"
msgid "Enter the merge request description"
-msgstr ""
+msgstr "Gib die Beschreibung des Merge-Requests ein"
msgid "Enter the merge request title"
-msgstr ""
+msgstr "Gib den Titel des Merge-Requests ein"
msgid "Environments"
-msgstr ""
+msgstr "Umgebungen"
msgid "Environments|An error occurred while fetching the environments."
-msgstr ""
+msgstr "Beim Abrufen der Umgebungen ist ein Fehler aufgetreten."
msgid "Environments|An error occurred while making the request."
-msgstr ""
+msgstr "Während der Anfrage ist ein Fehler aufgetreten."
msgid "Environments|An error occurred while stopping the environment, please try again"
-msgstr ""
+msgstr "Beim Anhalten der Umgebung ist ein Fehler aufgetreten. Bitte versuche es erneut"
msgid "Environments|Are you sure you want to stop this environment?"
-msgstr ""
+msgstr "Bist du sicher, dass du diese Umgebung stoppen möchtest?"
msgid "Environments|Commit"
-msgstr ""
+msgstr "Commit"
msgid "Environments|Deploy to..."
-msgstr ""
+msgstr "Bereitstellen für..."
msgid "Environments|Deployment"
-msgstr ""
+msgstr "Bereitstellung"
msgid "Environments|Environment"
-msgstr ""
+msgstr "Umgebung"
msgid "Environments|Environments"
-msgstr ""
+msgstr "Umgebungen"
msgid "Environments|Environments are places where code gets deployed, such as staging or production."
-msgstr ""
+msgstr "Umgebungen sind Orte, an denen Code bereitgestellt wird, z. B. Staging oder Produktion."
msgid "Environments|Job"
-msgstr ""
+msgstr "Job"
msgid "Environments|Learn more about stopping environments"
-msgstr ""
+msgstr "Erfahre mehr über das Stoppen von Umgebungen"
msgid "Environments|New environment"
-msgstr ""
+msgstr "Neue Umgebung"
msgid "Environments|No deployments yet"
-msgstr ""
+msgstr "Noch keine Bereitstellungen"
msgid "Environments|No pod name has been specified"
-msgstr ""
+msgstr "Kein Pod-Name angegeben"
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
-msgstr ""
+msgstr "Beachte, dass diese Aktion die Umgebung stoppen wird, es aber %{emphasisStart}keine%{emphasisEnd} Auswirkungen auf bestehende Bereitstellung haben wird, da keine \"stop environment action\" in der Datei %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} definiert ist."
msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
-msgstr ""
+msgstr "Beachte, dass diese Aktion die Umgebung stoppen wird, es aber %{emphasis_start}keine%{emphasis_end} Auswirkungen auf bestehende Bereitstellung haben wird, da keine \"stop environment action\" in der Datei %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} definiert ist."
msgid "Environments|Open live environment"
-msgstr ""
+msgstr "Öffne Live-Umgebung"
msgid "Environments|Pod logs from"
-msgstr ""
+msgstr "Pod-Protokolle von"
msgid "Environments|Re-deploy to environment"
-msgstr ""
+msgstr "Erneute Bereitstellung in der Umgebung"
msgid "Environments|Read more about environments"
-msgstr ""
+msgstr "Lies mehr über Umgebungen"
msgid "Environments|Rollback environment"
-msgstr ""
+msgstr "Umgebung wiederherstellen"
msgid "Environments|Show all"
-msgstr ""
+msgstr "Alle anzeigen"
msgid "Environments|Stop"
-msgstr ""
+msgstr "Stopp"
msgid "Environments|Stop environment"
-msgstr ""
+msgstr "Umgebung stoppen"
msgid "Environments|Updated"
-msgstr ""
+msgstr "Aktualisiert"
-msgid "Environments|You don't have any environments right now."
-msgstr ""
+msgid "Environments|You don't have any environments right now"
+msgstr "Du hast momentan keine Umgebungen"
msgid "Environments|protected"
-msgstr ""
+msgstr "geschützt"
msgid "Epic"
-msgstr ""
+msgstr "Epic"
msgid "Epic will be removed! Are you sure?"
-msgstr ""
+msgstr "Epic wird entfernt! Bist du dir sicher?"
msgid "Epics"
-msgstr ""
+msgstr "Epics"
msgid "Epics Roadmap"
-msgstr ""
+msgstr "Epics Roadmap"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
-msgstr ""
+msgstr "Mit Epics können Sie Ihre Projekte effizienter und mit weniger Aufwand verwalten"
msgid "Epics|An error occurred while saving %{epicDateType} date"
-msgstr ""
+msgstr "Fehler beim Speichern des %{epicDateType}-Datums"
msgid "Epics|How can I solve this?"
-msgstr ""
+msgstr "Wie kann ich dieses Problem lösen?"
msgid "Epics|More information"
-msgstr ""
+msgstr "Weitere Informationen"
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
-msgstr ""
+msgstr "Diese Daten beeinflussen, wie deine Epics in der Roadmap erscheinen. Die Daten der Meilensteine ​​stammen aus den Meilensteinen, die den Tickets im Epic zugewiesen wurden. Du kannst auch feste Termine festlegen oder sie vollständig entfernen."
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
-msgstr ""
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr "Um dein Epics %{epicDateType} basierend auf den Meilensteinen zu planen, weise einen Meilenstein mit einem %{epicDateType} einem beliebigen Ticket im Epic zu."
-msgid "Epics|finish"
-msgstr ""
+msgid "Epics|due"
+msgstr "fällig"
msgid "Epics|start"
-msgstr ""
+msgstr "starten"
msgid "Error"
-msgstr ""
+msgstr "Fehler"
msgid "Error Reporting and Logging"
-msgstr ""
+msgstr "Fehlerberichterstattung und Protokollierung"
msgid "Error creating epic"
-msgstr ""
+msgstr "Fehler beim Erstellen des Epics"
msgid "Error fetching contributors data."
-msgstr ""
+msgstr "Fehler beim Abrufen der Daten der Mitwirkenden."
msgid "Error fetching labels."
-msgstr ""
+msgstr "Fehler beim Abrufen der Label."
msgid "Error fetching network graph."
-msgstr ""
+msgstr "Fehler beim Abrufen des Netzwerkgraphen."
msgid "Error fetching refs"
-msgstr ""
+msgstr "Fehler beim Abrufen der Referenzen"
msgid "Error fetching usage ping data."
-msgstr ""
+msgstr "Fehler beim Abrufen der Daten des Nutzungsberichts."
msgid "Error loading branch data. Please try again."
-msgstr ""
+msgstr "Fehler beim Laden der Branch-Daten. Bitte versuche es erneut."
msgid "Error loading branches."
-msgstr ""
+msgstr "Fehler beim Laden der Branches."
msgid "Error loading last commit."
-msgstr ""
+msgstr "Fehler beim Laden des letzten Commits."
msgid "Error loading markdown preview"
-msgstr ""
+msgstr "Fehler beim Laden der Markdown-Vorschau"
msgid "Error loading merge requests."
-msgstr ""
+msgstr "Fehler beim Laden der Merge-Requests."
msgid "Error loading project data. Please try again."
-msgstr ""
+msgstr "Fehler beim Laden der Projektdaten. Bitte versuche es erneut."
msgid "Error loading template types."
-msgstr ""
+msgstr "Fehler beim Laden der Vorlagentypen."
msgid "Error loading template."
-msgstr ""
+msgstr "Fehler beim Laden der Vorlage."
msgid "Error occurred when toggling the notification subscription"
-msgstr ""
+msgstr "Beim Umschalten des Benachrichtigungs-Abonnements trat ein Fehler auf"
msgid "Error saving label update."
-msgstr ""
+msgstr "Fehler beim Speichern der Label-Aktualisierung."
msgid "Error updating status for all todos."
-msgstr ""
+msgstr "Fehler beim Aktualisieren des Status für alle To-dos."
msgid "Error updating todo status."
-msgstr ""
+msgstr "Fehler beim Aktualisieren des To-do-Status."
msgid "Error while loading the merge request. Please try again."
-msgstr ""
+msgstr "Fehler beim Laden des Merge-Requests. Bitte versuche es erneut."
msgid "Estimated"
-msgstr ""
+msgstr "Geschätzt"
msgid "EventFilterBy|Filter by all"
msgstr "Filtere alle"
@@ -3026,13 +3232,13 @@ msgid "EventFilterBy|Filter by comments"
msgstr "Filtere nach Kommentaren"
msgid "EventFilterBy|Filter by issue events"
-msgstr "Filtere nach Tickets"
+msgstr "Filtere nach Ticketereignissen"
msgid "EventFilterBy|Filter by merge events"
-msgstr "Filtere nach Merge Requests"
+msgstr "Filtere nach Merge-Requests"
msgid "EventFilterBy|Filter by push events"
-msgstr "Filtere nach Ãœbertragungen"
+msgstr "Filtere nach Push-Ereignissen"
msgid "EventFilterBy|Filter by team"
msgstr "Filtere nach Teams"
@@ -3047,112 +3253,214 @@ msgid "Every week (Sundays at 4:00am)"
msgstr "Wöchentlich (Sonntags um 4:00 Uhr)"
msgid "Everyone can contribute"
-msgstr ""
+msgstr "Jeder kann beitragen"
msgid "Expand"
-msgstr ""
+msgstr "Aufklappen"
msgid "Expand all"
-msgstr ""
+msgstr "Alle erweitern"
msgid "Expand sidebar"
+msgstr "Menüleiste ausklappen"
+
+msgid "Expiration date"
+msgstr "Ablaufdatum"
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
msgid "Explore"
-msgstr ""
+msgstr "Erkunden"
msgid "Explore GitLab"
-msgstr ""
+msgstr "Erkunde GitLab"
msgid "Explore Groups"
-msgstr ""
+msgstr "Erkunde Gruppen"
msgid "Explore groups"
-msgstr ""
+msgstr "Erkunde Gruppen"
msgid "Explore projects"
-msgstr ""
+msgstr "Projekte erkunden"
msgid "Explore public groups"
-msgstr ""
+msgstr "Erkunde öffentliche Gruppen"
msgid "External Classification Policy Authorization"
-msgstr ""
+msgstr "Externe Autorisierung der Klassifikationsrichtlinie"
msgid "External authentication"
-msgstr ""
+msgstr "Externe Authentifizierung"
msgid "External authorization denied access to this project"
-msgstr ""
+msgstr "Externe Autorisierung verbietet den Zugriff auf dieses Projekt"
msgid "External authorization request timeout"
-msgstr ""
+msgstr "Zeitüberschreitung für externe Autorisierungsanfrage"
msgid "ExternalAuthorizationService|Classification Label"
-msgstr ""
+msgstr "Klassifizierungslabel"
msgid "ExternalAuthorizationService|Classification label"
-msgstr ""
+msgstr "Klassifizierungslabel"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
-msgstr ""
+msgstr "Wenn kein Klassifizierungslabel gesetzt ist, wird das Standardlabel `%{default_label}` benutzt."
msgid "Facebook"
-msgstr ""
+msgstr "Facebook"
msgid "Failed"
-msgstr ""
+msgstr "Fehlgeschlagen"
msgid "Failed Jobs"
-msgstr ""
+msgstr "Fehlgeschlagene Jobs"
msgid "Failed to change the owner"
-msgstr "Wechsel des Besitzers fehlgeschlagen"
+msgstr "Wechsel des/der Besitzers/-in fehlgeschlagen"
msgid "Failed to check related branches."
-msgstr ""
+msgstr "Verwandte Branches konnten nicht überprüft werden."
+
+msgid "Failed to deploy to"
+msgstr "Bereitstellung fehlgeschlagen für"
+
+msgid "Failed to load emoji list."
+msgstr "Fehler beim Laden der Emoji-Liste."
msgid "Failed to remove issue from board, please try again."
-msgstr ""
+msgstr "Fehler beim Entfernen des Tickets vom Bord, bitte versuche es erneut."
msgid "Failed to remove mirror."
-msgstr ""
+msgstr "Fehler beim Entfernen des Mirrors."
msgid "Failed to remove the pipeline schedule"
msgstr "Entfernung der Pipelineplanung fehlgeschlagen"
-msgid "Failed to update issues, please try again."
+msgid "Failed to signing using smartcard authentication"
msgstr ""
+msgid "Failed to update issues, please try again."
+msgstr "Tickets konnten nicht aktualisiert werden, bitte versuche es erneut."
+
msgid "Failure"
-msgstr ""
+msgstr "Fehlschlag"
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
+msgstr "Schneller als wenn es den Projektarbeitsplatz wieder benützt (fällt zurück auf den Clone wenn es nicht existiert)"
+
+msgid "Feature Flags"
msgstr ""
-msgid "Feb"
+msgid "FeatureFlags|API URL"
+msgstr "API-URL"
+
+msgid "FeatureFlags|Active"
+msgstr "Aktiv"
+
+msgid "FeatureFlags|Application name"
+msgstr "Anwendungsname"
+
+msgid "FeatureFlags|Configure"
+msgstr "Konfiguriere"
+
+msgid "FeatureFlags|Configure feature flags"
msgstr ""
-msgid "February"
+msgid "FeatureFlags|Create feature flag"
msgstr ""
-msgid "Fields on this page are now uneditable, you can configure"
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr "%{feature_flag_name} löschen?"
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
msgstr ""
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr "Weitere Informationen"
+
+msgid "FeatureFlags|Name"
+msgstr "Name"
+
+msgid "FeatureFlags|New"
+msgstr "Neu"
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr "Änderungen speichern"
+
+msgid "FeatureFlags|Status"
+msgstr "Status"
+
+msgid "Feb"
+msgstr "Feb"
+
+msgid "February"
+msgstr "Februar"
+
+msgid "Fields on this page are now uneditable, you can configure"
+msgstr "Felder auf dieser Seite sind jetzt nicht mehr editierbar, du kannst nun konfigurieren"
+
+msgid "File templates"
+msgstr "Dateivorlagen"
+
msgid "Files"
msgstr "Dateien"
msgid "Files (%{human_size})"
-msgstr ""
+msgstr "Dateien (%{human_size})"
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
-msgstr ""
+msgstr "Fülle die Felder unten aus, schalte <strong>%{enable_label}</strong> an, und drücke <strong>%{save_changes}</strong>"
msgid "Filter"
-msgstr ""
+msgstr "Filter"
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr "Filtern nach %{issuable_type}, die derzeit geschlossen sind."
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr "Filtern nach %{issuable_type}, die derzeit offen sind."
msgid "Filter by commit message"
-msgstr "Filter nach Commit Nachricht"
+msgstr "Filter nach Commit-Nachricht"
+
+msgid "Filter..."
+msgstr "Filter..."
msgid "Find by path"
msgstr "Finde über den Pfad"
@@ -3161,108 +3469,115 @@ msgid "Find file"
msgstr "Finde Datei"
msgid "Find the downloaded ZIP file and decompress it."
-msgstr ""
+msgstr "Finde die heruntergeladene ZIP-Datei und dekomprimiere sie."
msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
-msgstr ""
+msgstr "Suche die neu extrahierte Datei <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code>."
msgid "Fingerprints"
+msgstr "Fingerabdrücke"
+
+msgid "Finish review"
msgstr ""
msgid "Finished"
-msgstr ""
+msgstr "Fertiggestellt"
msgid "FirstPushedBy|First"
msgstr "Erster"
msgid "FirstPushedBy|pushed by"
-msgstr "übertragen von"
+msgstr "gepusht von"
msgid "Fixed date"
-msgstr ""
+msgstr "Fester Termin"
-msgid "Fixed finish date"
-msgstr ""
+msgid "Fixed due date"
+msgstr "Fixes Fälligkeitsdatum"
msgid "Fixed start date"
-msgstr ""
+msgstr "Fixer Starttermin"
msgid "Fixed:"
-msgstr ""
+msgstr "Behoben:"
msgid "FogBugz Email"
-msgstr ""
+msgstr "FogBugz-E-Mail"
msgid "FogBugz Import"
-msgstr ""
+msgstr "FogBugz-Import"
msgid "FogBugz Password"
-msgstr ""
+msgstr "FogBugz-Passwort"
msgid "FogBugz URL"
-msgstr ""
+msgstr "FogBugz-URL"
msgid "FogBugz import"
-msgstr ""
+msgstr "FogBugz-Import"
msgid "Follow the steps below to export your Google Code project data."
-msgstr ""
+msgstr "Befolge die nachstehenden Schritte, um deine Google Code-Projektdaten zu exportieren."
msgid "Font Color"
-msgstr ""
+msgstr "Schriftfarbe"
msgid "Footer message"
-msgstr ""
+msgstr "Fußzeilennachricht"
msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
+msgstr "Bei interne Projekte kann jede(r) angemeldete Benutzer(in) die Pipelines anzeigen lassen und auf Job-Details (Ausgabeprotokolle und Artefakte) zugreifen"
msgid "For more information, go to the "
+msgstr "Für mehr Informationen, gehe zu "
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
msgstr ""
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr "Weitere Informationen zum %{deactivating_usage_ping_link_start}Deaktivieren des Nutzungsberichts%{deactivating_usage_ping_link_end} findest du in der Dokumentation."
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
+msgstr "Bei privaten Projekten kann jedes Mitglied (Gast oder höher) Pipelines ansehen und auf Job-Details zugreifen (Ausgabeprotokolle und Artefakte)"
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
-msgstr ""
-
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] "Ableger"
-msgstr[1] "Ableger"
+msgstr "Bei öffentlichen Projekten, kann jeder sich die Pipelines ansehen und auf Job-Details (Ausgabeprotokolle und Artefakte) zugreifen"
msgid "ForkedFromProjectPath|Forked from"
-msgstr "Ableger von"
+msgstr "Fork von"
msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
-msgstr ""
+msgstr "Geforkt von %{project_name} (gelöscht)"
msgid "Forking in progress"
-msgstr ""
+msgstr "Fork wird erstellt"
msgid "Format"
-msgstr ""
+msgstr "Format"
msgid "Found errors in your .gitlab-ci.yml:"
+msgstr "Fehler in deiner .gitlab-ci.yml gefunden:"
+
+msgid "Free Trial of GitLab.com Gold"
msgstr ""
msgid "From %{provider_title}"
-msgstr ""
+msgstr "Von %{provider_title}"
msgid "From Bitbucket"
-msgstr ""
+msgstr "Von Bitbucket"
msgid "From Bitbucket Server"
-msgstr ""
+msgstr "Vom Bitbucket-Server"
msgid "From FogBugz"
-msgstr ""
+msgstr "Von FogBugz"
msgid "From GitLab.com"
-msgstr ""
+msgstr "Von GitLab.com"
msgid "From Google Code"
-msgstr ""
+msgstr "Von Google Code"
msgid "From issue creation until deploy to production"
msgstr "Von der Ticketbeschreibung bis zur Bereitstellung"
@@ -3271,568 +3586,625 @@ msgid "From merge request merge until deploy to production"
msgstr "Vom Umsetzen des Merge Request bis zur Bereitstellung auf dem Produktivsystem"
msgid "From milestones:"
-msgstr ""
+msgstr "Von Meilensteinen:"
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
-msgstr ""
+msgstr "Installiere den Runner aus der Anwendungsliste in der Kubernetes-Cluster Detailansicht"
msgid "GPG Keys"
-msgstr ""
+msgstr "GPG-Schlüssel"
msgid "General"
-msgstr ""
+msgstr "Allgemein"
msgid "General pipelines"
-msgstr ""
+msgstr "Allgemeine Pipelines"
msgid "Generate a default set of labels"
-msgstr ""
+msgstr "Generiere einen Standardsatz von Labels"
+
+msgid "Geo"
+msgstr "Geo"
msgid "Geo Nodes"
-msgstr ""
+msgstr "Geo-Knoten"
msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
-msgstr ""
+msgstr "Mit Geo kannst du deine GitLab-Instanz an andere geografische Orte replizieren."
msgid "GeoNodeSyncStatus|Node is failing or broken."
-msgstr ""
+msgstr "Knoten fällt aus oder ist kaputt."
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
-msgstr ""
+msgstr "Knoten ist langsam, überlastet oder er erholt sich nur von einem Ausfall."
msgid "GeoNodes|Checksummed"
-msgstr ""
+msgstr "Prüfsumme verifiziert"
msgid "GeoNodes|Data is out of date from %{timeago}"
-msgstr ""
+msgstr "Daten sind veraltet von %{timeago}"
msgid "GeoNodes|Data replication lag"
-msgstr ""
+msgstr "Datenreplikationsverzögerung"
msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
-msgstr ""
+msgstr "Durch das Deaktivieren eines Knotens wird der Synchronisierungsprozess gestoppt. Bist du sicher?"
msgid "GeoNodes|Does not match the primary storage configuration"
-msgstr ""
+msgstr "Stimmt nicht mit der primären Speicherkonfiguration überein"
msgid "GeoNodes|Failed"
-msgstr ""
+msgstr "Fehlgeschlagen"
msgid "GeoNodes|Full"
-msgstr ""
+msgstr "Voll"
msgid "GeoNodes|GitLab version"
-msgstr ""
+msgstr "GitLab-Version"
msgid "GeoNodes|GitLab version does not match the primary node version"
-msgstr ""
+msgstr "Die GitLab Version stimmt nicht mit der Version des primären Knotens überein"
msgid "GeoNodes|Health status"
-msgstr ""
+msgstr "Systemzustand"
msgid "GeoNodes|Last event ID processed by cursor"
-msgstr ""
+msgstr "Letzte Event-ID, die vom Cursor verarbeitet wurde"
msgid "GeoNodes|Last event ID seen from primary"
-msgstr ""
+msgstr "Letzte Ereignis-ID vom Primärknoten aus gesehen"
msgid "GeoNodes|Learn more about Repository checksum progress"
-msgstr ""
+msgstr "Erfahre mehr über den Repository-Prüfsummenfortschritt"
msgid "GeoNodes|Learn more about Repository verification"
-msgstr ""
+msgstr "Erfahre mehr über die Repository-Verifizierung"
msgid "GeoNodes|Learn more about Wiki checksum progress"
-msgstr ""
+msgstr "Erfahre mehr über den Wiki-Prüfsummenfortschritt"
msgid "GeoNodes|Learn more about Wiki verification"
-msgstr ""
+msgstr "Erfahren Sie mehr über die Wiki-Verifikation"
msgid "GeoNodes|Loading nodes"
-msgstr ""
+msgstr "Knoten werden geladen"
msgid "GeoNodes|Local LFS objects"
-msgstr ""
+msgstr "Lokale LFS Objekte"
msgid "GeoNodes|Local attachments"
-msgstr ""
+msgstr "Lokale Anhänge"
msgid "GeoNodes|Local job artifacts"
-msgstr ""
+msgstr "Lokale Job-Artefakte"
msgid "GeoNodes|New node"
-msgstr ""
+msgstr "Neuer Knoten"
msgid "GeoNodes|Node Authentication was successfully repaired."
-msgstr ""
+msgstr "Knoten-Authentifizierung wurde erfolgreich repariert."
msgid "GeoNodes|Node was successfully removed."
-msgstr ""
+msgstr "Knoten wurde erfolgreich entfernt."
msgid "GeoNodes|Not checksummed"
-msgstr ""
+msgstr "Keine Prüfsumme"
msgid "GeoNodes|Out of sync"
-msgstr ""
+msgstr "Nicht synchron"
msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
-msgstr ""
+msgstr "Durch das Entfernen eines Knotens wird der Synchronisierungsprozess gestoppt. Bist du sicher?"
msgid "GeoNodes|Replication slot WAL"
-msgstr ""
+msgstr "Replikations-Slot WAL"
msgid "GeoNodes|Replication slots"
-msgstr ""
+msgstr "Replikations-Slots"
msgid "GeoNodes|Repositories"
-msgstr ""
+msgstr "Repositorien"
msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
-msgstr ""
+msgstr "Repository-Prüfsummen wurden mit ihren Gegenstücken auf dem sekundären Knoten verglichen"
msgid "GeoNodes|Repositories verified with their counterparts on the Primary node"
-msgstr ""
+msgstr "Repositories mit ihren Gegenstücken am primären Knoten verifiziert"
msgid "GeoNodes|Repository checksum progress"
-msgstr ""
+msgstr "Repository-Prüfsummenfortschritt"
msgid "GeoNodes|Repository verification progress"
-msgstr ""
+msgstr "Repository-Üerprüfungsfortschritt"
msgid "GeoNodes|Selective"
-msgstr ""
+msgstr "Selektiv"
msgid "GeoNodes|Something went wrong while changing node status"
-msgstr ""
+msgstr "Etwas ist schiefgelaufen während der Änderung des Knotenstatuses"
msgid "GeoNodes|Something went wrong while fetching nodes"
-msgstr ""
+msgstr "Beim Laden der Knoten ist etwas schief gelaufen"
msgid "GeoNodes|Something went wrong while removing node"
-msgstr ""
+msgstr "Etwas ist schiefgegangen während dem Entfernen des Knotens"
msgid "GeoNodes|Something went wrong while repairing node"
-msgstr ""
+msgstr "Während der Reparatur des Knotens ist etwas schief gelaufen"
msgid "GeoNodes|Storage config"
-msgstr ""
+msgstr "Speicherkonfiguration"
msgid "GeoNodes|Sync settings"
-msgstr ""
+msgstr "Synchronisierungseinstellungen"
msgid "GeoNodes|Synced"
-msgstr ""
+msgstr "Synchronisiert"
msgid "GeoNodes|Unused slots"
-msgstr ""
+msgstr "Unbenutzte Slots"
msgid "GeoNodes|Unverified"
-msgstr ""
+msgstr "Nicht verifiziert"
msgid "GeoNodes|Used slots"
-msgstr ""
+msgstr "Benutzte Slots"
msgid "GeoNodes|Verified"
-msgstr ""
+msgstr "Verifiziert"
msgid "GeoNodes|Wiki checksum progress"
-msgstr ""
+msgstr "Wiki-Prüfsummenfortschritt"
msgid "GeoNodes|Wiki verification progress"
-msgstr ""
+msgstr "Wiki-Verifizierungsfortschritt"
msgid "GeoNodes|Wikis"
-msgstr ""
+msgstr "Wikis"
msgid "GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes"
-msgstr ""
+msgstr "Wiki-Prüfsummen wurden mit ihren Gegenstücken auf dem sekundären Knoten verglichen"
msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
-msgstr ""
+msgstr "Wikis wurden mit ihren Gegenstücken auf dem primären Knoten verifiziert"
msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
-msgstr ""
+msgstr "Du hast Geo-Knoten mit einer unsicheren HTTP-Verbindung konfiguriert. Wir empfehlen die Verwendung von HTTPS."
msgid "Geo|%{name} is scheduled for forced re-download"
-msgstr ""
+msgstr "%{name} ist für einen erzwungenen erneuten Download vorgemerkt"
msgid "Geo|%{name} is scheduled for re-check"
-msgstr ""
+msgstr "%{name} ist für eine erneute Prüfung vorgemerkt"
msgid "Geo|%{name} is scheduled for re-sync"
-msgstr ""
+msgstr "%{name} ist für die erneute Synchronisierung vorgemerkt"
+
+msgid "Geo|All"
+msgstr "Alle"
msgid "Geo|All projects"
+msgstr "Alle Projekte"
+
+msgid "Geo|All projects are being scheduled for re-check"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-sync"
msgstr ""
+msgid "Geo|Batch operations"
+msgstr "Stapelverarbeitung"
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr "Tracking-Eintrag für ein vorhandenes Projekt konnte nicht entfernt werden."
+
msgid "Geo|Failed"
-msgstr ""
+msgstr "Fehlgeschlagen"
msgid "Geo|File sync capacity"
-msgstr ""
+msgstr "Dateisynchronisationskapazität"
+
+msgid "Geo|Geo Status"
+msgstr "Geo-Status"
msgid "Geo|Groups to synchronize"
-msgstr ""
+msgstr "Gruppen für die Synchronisierung"
msgid "Geo|In sync"
-msgstr ""
+msgstr "Wird synchronisiert"
msgid "Geo|Last successful sync"
-msgstr ""
+msgstr "Letzte erfolgreiche Synchronisierung"
msgid "Geo|Last sync attempt"
-msgstr ""
+msgstr "Letzter Synchronisierungsversuch"
msgid "Geo|Last time verified"
-msgstr ""
+msgstr "Zuletzt überprüft"
msgid "Geo|Never"
-msgstr ""
+msgstr "Nie"
msgid "Geo|Next sync scheduled at"
-msgstr ""
+msgstr "Nächste Synchronisierung geplant um"
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
-msgstr ""
+msgstr "Ausstehend"
msgid "Geo|Pending synchronization"
-msgstr ""
+msgstr "Ausstehende Synchronisation"
msgid "Geo|Pending verification"
-msgstr ""
+msgstr "Ausstehende Überprüfung"
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr "Projekt (ID: %{project_id}) existiert nicht mehr in der Primärdatenbank. Es ist sicher, diesen Eintrag zu entfernen, da dadurch keine Daten auf der Festplatte gelöscht werden."
msgid "Geo|Projects in certain groups"
-msgstr ""
+msgstr "Projekte in bestimmten Gruppen"
msgid "Geo|Projects in certain storage shards"
-msgstr ""
+msgstr "Projekte in bestimmten Speicherfragmenten"
msgid "Geo|Recheck"
+msgstr "Neuprüfung"
+
+msgid "Geo|Recheck all projects"
msgstr ""
msgid "Geo|Redownload"
-msgstr ""
+msgstr "Erneuter Download"
+
+msgid "Geo|Remove"
+msgstr "Entfernen"
msgid "Geo|Repository sync capacity"
-msgstr ""
+msgstr "Repository-Synchronisierungskapazität"
msgid "Geo|Resync"
-msgstr ""
+msgstr "Resynchronisation"
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
-msgstr ""
+msgid "Geo|Retry count"
+msgstr "Wiederholversuch"
msgid "Geo|Select groups to replicate."
-msgstr ""
+msgstr "Wähle zu replizierende Gruppen aus."
msgid "Geo|Shards to synchronize"
-msgstr ""
+msgstr "Zu synchronisierende Fragmente"
msgid "Geo|Status"
-msgstr ""
+msgstr "Status"
msgid "Geo|Synced"
-msgstr ""
+msgstr "Synchronisiert"
msgid "Geo|Synchronization failed - %{error}"
-msgstr ""
+msgstr "Synchronisierung fehlgeschlagen - %{error}"
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr "Tracking-Eintrag für Projekt (%{project_id}) wurde erfolgreich entfernt."
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr "Tracking-Eintrag wird entfernt. Bist du sicher?"
msgid "Geo|Unknown state"
-msgstr ""
+msgstr "Unbekannter Status"
msgid "Geo|Verification capacity"
-msgstr ""
+msgstr "Überprüfungskapazität"
msgid "Geo|Verification failed - %{error}"
-msgstr ""
+msgstr "Überprüfung fehlgeschlagen - %{error}"
msgid "Geo|Waiting for scheduler"
+msgstr "Warte auf den Scheduler"
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
msgstr ""
-msgid "Geo|You need a different license to use Geo replication"
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
+msgid "Geo|You need a different license to use Geo replication"
+msgstr "Du benötigst eine andere Lizenz, um die Geo-Replikation zu verwenden"
+
+msgid "Geo|misconfigured"
+msgstr "falsch konfiguriert"
+
+msgid "Geo|primary"
+msgstr "primär"
+
+msgid "Geo|secondary"
+msgstr "sekundär"
+
+msgid "Get a free instance review"
+msgstr "Erhalte eine kostenlose Instanzprüfung"
+
msgid "Git"
-msgstr ""
+msgstr "Git"
msgid "Git repository URL"
-msgstr ""
+msgstr "Git-Repository-URL"
msgid "Git revision"
-msgstr ""
-
-msgid "Git storage health information has been reset"
-msgstr "Informationen über den Speicherzustand von Gitlab wurden zurückgesetzt."
+msgstr "Git-Revision"
msgid "Git strategy for pipelines"
-msgstr ""
+msgstr "Git-Strategie für Pipelines"
msgid "Git version"
-msgstr ""
+msgstr "Git-Version"
msgid "GitHub import"
-msgstr ""
+msgstr "GitHub-Import"
msgid "GitLab CI Linter has been moved"
-msgstr ""
+msgstr "GitLab CI Linter wurde verschoben"
msgid "GitLab Geo"
-msgstr ""
+msgstr "GitLab Geo"
msgid "GitLab Group Runners can execute code for all the projects in this group."
-msgstr ""
+msgstr "GitLab Gruppenrunner können Code für alle Projekte in dieser Gruppe ausführen."
msgid "GitLab Import"
-msgstr ""
+msgstr "GitLab-Import"
msgid "GitLab User"
-msgstr ""
+msgstr "GitLab-Nutzer(in)"
msgid "GitLab project export"
-msgstr ""
+msgstr "GitLab-Projekt exportieren"
msgid "GitLab single sign on URL"
-msgstr ""
+msgstr "GitLab Single Sign On-URL"
msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
+msgstr "GitLab wird einen Hintergrundjob ausführen, der pseudonymisierte CSVs der GitLab-Datenbank erzeugt, die in dein konfiguriertes Objektspeicherverzeichnis hochgeladen werden."
msgid "GitLab.com import"
-msgstr ""
+msgstr "GitLab.com-Import"
msgid "GitLab’s issue tracker"
-msgstr ""
+msgstr "GitLabs Ticketsystem"
msgid "Gitaly"
-msgstr ""
+msgstr "Gitaly"
msgid "Gitaly Servers"
-msgstr ""
+msgstr "Gitaly-Server"
msgid "Gitaly|Address"
-msgstr ""
+msgstr "Adresse"
msgid "Gitea Host URL"
-msgstr ""
+msgstr "Gitea-Host-URL"
msgid "Gitea Import"
-msgstr ""
+msgstr "Gitea-Import"
msgid "Go Back"
-msgstr ""
+msgstr "Zurück"
msgid "Go back"
-msgstr ""
+msgstr "Zurück"
msgid "Go to"
-msgstr ""
+msgstr "Gehe zu"
msgid "Go to %{link_to_google_takeout}."
-msgstr ""
-
-msgid "Go to your fork"
-msgstr "Gehe zu Deinem Ableger"
-
-msgid "GoToYourFork|Fork"
-msgstr "Ableger"
+msgstr "Gehe zu %{link_to_google_takeout}."
msgid "Google Code import"
-msgstr ""
+msgstr "Google Code-Import"
msgid "Google Takeout"
-msgstr ""
+msgstr "Google Takeout"
msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
-msgstr ""
+msgstr "Google-Authentifizierung ist nicht %{link_to_documentation}. Frage deinen GitLab Administrator, wenn du diesen Service nutzen möchtest."
msgid "Got it!"
-msgstr ""
+msgstr "Verstanden!"
msgid "Graph"
-msgstr ""
+msgstr "Diagramm"
msgid "Group"
-msgstr ""
+msgstr "Gruppe"
msgid "Group CI/CD settings"
-msgstr ""
+msgstr "Gruppen-CI/CD-Einstellungen"
msgid "Group Git LFS status:"
-msgstr ""
+msgstr "Gruppen-Git-LFS-Status:"
msgid "Group ID"
-msgstr ""
+msgstr "Gruppen-ID"
msgid "Group Runners"
+msgstr "Gruppen Runner"
+
+msgid "Group SAML must be enabled to test"
msgstr ""
+msgid "Group URL"
+msgstr "Gruppen-URL"
+
msgid "Group avatar"
-msgstr ""
+msgstr "Gruppenavatar"
+
+msgid "Group description"
+msgstr "Gruppenbeschreibung"
+
+msgid "Group description (optional)"
+msgstr "Gruppenbeschreibung (optional)"
msgid "Group details"
-msgstr ""
+msgstr "Gruppendetails"
msgid "Group info:"
-msgstr ""
+msgstr "Gruppeninfo:"
msgid "Group maintainers can register group runners in the %{link}"
-msgstr ""
+msgstr "Gruppenbetreuer können Gruppen-Runner unter %{link} registrieren"
+
+msgid "Group name"
+msgstr "Gruppenname"
msgid "Group: %{group_name}"
-msgstr ""
+msgstr "Gruppe: %{group_name}"
msgid "GroupRoadmap|From %{dateWord}"
-msgstr ""
+msgstr "Vom %{dateWord}"
msgid "GroupRoadmap|Loading roadmap"
-msgstr ""
+msgstr "Roadmap wird geladen"
msgid "GroupRoadmap|Something went wrong while fetching epics"
-msgstr ""
+msgstr "Beim Abfragen der Epics ist etwas schief gelaufen"
msgid "GroupRoadmap|Sorry, no epics matched your search"
-msgstr ""
+msgstr "Entschuldigung, keine Epics stimmen mit deiner Suche überein"
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
-msgstr ""
+msgstr "Die Roadmap zeigt den Fortschritt deiner Epics anhand einer Zeitleiste an"
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr "Füge ein Start- oder Fälligkeitsdatum zu einem deiner Epics in dieser Gruppe oder ihrer Untergruppen hinzu, um die Roadmap anzuzeigen. Nur Epics der letzten oder nächsten Monate werden angezeigt &ndash; von %{startDate} bis %{endDate}."
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr "Füge ein Start- oder Fälligkeitsdatum zu einem deiner Epics in dieser Gruppe oder ihrer Untergruppen hinzu, um die Roadmap anzuzeigen. In der Quartalsansicht werden nur Epics im letzten Quartal, im aktuellen Quartal und in den nächsten 4 Quartalen angezeigt &ndash; von %{startDate} bis %{endDate}."
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr "Füge ein Start- oder Fälligkeitsdatum zu einem deiner Epics in dieser Gruppe oder ihrer Untergruppen hinzu, um die Roadmap anzuzeigen. In der Wochenansicht werden nur Epics der letzten Woche, der aktuellen Woche und der nächsten 4 Wochen angezeigt &ndash; von %{startDate} bis %{endDate}."
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
+msgstr "Um deine Suche auszuweiten, ändere oder entferne Filter. In der Monatsansicht werden nur Epics des letzten Monats, des aktuellen Monats und der nächsten 5 Monate angezeigt &ndash; von %{startDate} bis %{endDate}."
msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
+msgstr "Um deine Suche auszuweiten, ändere oder entferne Filter. In der Quartalsansicht werden nur Epics des letzten Quartals, des aktuellen Quartals und der nächsten 4 Quartale angezeigt &ndash; von %{startDate} bis %{endDate}."
msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr ""
+msgstr "Um deine Suche auszuweiten, ändere oder entferne Filter. In der Wochenansicht werden nur Epics der letzten Woche, de aktuellen Woche und der nächsten 4 Wochen angezeigt &ndash; von %{startDate} bis %{endDate}."
msgid "GroupRoadmap|Until %{dateWord}"
-msgstr ""
+msgstr "Bis %{dateWord}"
msgid "GroupSettings|Badges"
-msgstr ""
+msgstr "Badges"
msgid "GroupSettings|Customize your group badges."
-msgstr ""
+msgstr "Deine Gruppen-Badges anpassen."
msgid "GroupSettings|Learn more about badges."
-msgstr ""
+msgstr "Erfahre mehr über Badges."
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
-msgstr ""
-
-msgid "GroupSettings|Share with group lock"
-msgstr ""
+msgstr "Freigabe eines Projekts innerhalb %{group} mit anderen Gruppen verhindern"
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
-msgstr ""
+msgstr "Diese Einstellung wird auf %{ancestor_group} angewendet und wurde für diese Untergruppe überschrieben."
msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
-msgstr ""
+msgstr "Diese Einstellung wird auf %{ancestor_group} angewendet. Um Projekte in dieser Gruppe mit einer anderen Gruppe zu teilen, bitte den/die Eigentümer(in), die Einstellung zu überschreiben oder %{remove_ancestor_share_with_group_lock}."
msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
-msgstr ""
+msgstr "Diese Einstellung wird auf %{ancestor_group} angewendet. Du kannst die Einstellung überschreiben oder %{remove_ancestor_share_with_group_lock}."
msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
-msgstr ""
+msgstr "Diese Einstellung wird auf alle Untergruppen angewendet, es sei denn, sie wird von einem/einer Gruppenbesitzer(in) überschrieben. Gruppen, die bereits Zugriff auf das Projekt haben, behalten diesen, bis sie manuell entfernt werden."
msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
-msgstr ""
+msgstr "wenn bei der übergeordneten Gruppe „Freigeben mit Gruppensperre“ aktiviert ist, kann nur der/die Eigentümer(in) der übergeordneten Gruppe dies deaktivieren"
msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
-msgstr ""
+msgstr "entferne die Freigabe mit Gruppensperre von %{ancestor_group_name}"
msgid "Groups"
-msgstr ""
+msgstr "Gruppen"
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
-msgstr ""
+msgstr "Gruppen können durch %{subgroup_docs_link_start}Untergruppen%{subgroup_docs_link_end} verschachtelt werden."
msgid "GroupsDropdown|Frequently visited"
-msgstr ""
+msgstr "Häufig besucht"
msgid "GroupsDropdown|Groups you visit often will appear here"
-msgstr ""
+msgstr "Gruppen, die Sie häufig besuchen, werden hier angezeigt"
msgid "GroupsDropdown|Loading groups"
-msgstr ""
+msgstr "Gruppen werden geladen"
msgid "GroupsDropdown|Search your groups"
-msgstr ""
+msgstr "Durchsuche deine Gruppen"
msgid "GroupsDropdown|Something went wrong on our end."
-msgstr ""
+msgstr "Auf unserer Seite ist etwas schief gelaufen."
msgid "GroupsDropdown|Sorry, no groups matched your search"
-msgstr ""
+msgstr "Entschuldigung, keine Gruppe entsprachen deiner Suche"
msgid "GroupsDropdown|This feature requires browser localStorage support"
-msgstr ""
+msgstr "Dieses Feature erfordert einen Browser, der LocalStorage unterstützt"
msgid "GroupsEmptyState|A group is a collection of several projects."
-msgstr ""
+msgstr "Eine Gruppe ist eine Ansammlung mehrerer Projekte."
msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
-msgstr ""
+msgstr "Wenn du deine Projekte in einer Gruppe organisierst, funktioniert dies wie ein Ordner."
msgid "GroupsEmptyState|No groups found"
-msgstr ""
+msgstr "Keine Gruppen gefunden"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
-msgstr ""
+msgstr "Du kannst die Berechtigungen deiner Gruppenmitglieder und den Zugriff auf jedes Projekt in der Gruppe verwalten."
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr "Bist du sicher, dass du die Gruppe \"%{fullName}\" verlassen willst?"
msgid "GroupsTree|Create a project in this group."
-msgstr ""
+msgstr "Erstelle ein Projekt in dieser Gruppe."
msgid "GroupsTree|Create a subgroup in this group."
-msgstr ""
+msgstr "Erstelle eine Untergruppe in dieser Gruppe."
msgid "GroupsTree|Edit group"
-msgstr ""
+msgstr "Gruppe bearbeiten"
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
-msgstr ""
-
-msgid "GroupsTree|Filter by name..."
-msgstr ""
+msgstr "Konnte die Gruppe nicht verlassen. Bitte stelle sicher, dass du nicht der/die einzige Besitzer(in) bist."
msgid "GroupsTree|Leave this group"
-msgstr ""
+msgstr "Diese Gruppe verlassen"
msgid "GroupsTree|Loading groups"
-msgstr ""
+msgstr "Lade Gruppen"
-msgid "GroupsTree|Sorry, no groups matched your search"
-msgstr ""
+msgid "GroupsTree|No groups matched your search"
+msgstr "Keine Gruppen entsprachen Ihrer Suche"
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
-msgstr ""
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr "Keine Gruppen oder Projekte entsprachen deiner Suche"
+
+msgid "GroupsTree|Search by name"
+msgstr "Nach Namen suchen"
msgid "Have your users email"
-msgstr ""
+msgstr "Lasse deine Nutzer an diese Adresse mailen"
msgid "Header message"
-msgstr ""
+msgstr "Kopfzeilennachricht"
msgid "Health Check"
-msgstr "Systemzustand"
+msgstr "Health-Check"
msgid "Health information can be retrieved from the following endpoints. More information is available"
msgstr "Informationen über den Systemzustand können von folgenden Endpunkten erhalten werden. Mehr Informationen gibt es"
@@ -3850,245 +4222,251 @@ msgid "HealthCheck|Unhealthy"
msgstr "Problematisch"
msgid "Help"
-msgstr ""
+msgstr "Hilfe"
msgid "Help page"
-msgstr ""
+msgstr "Hilfe-Seite"
msgid "Help page text and support page url."
-msgstr ""
+msgstr "Text der Hilfeseite und die Supportseiten-URL."
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
-msgstr ""
+msgstr "Hier ist der öffentliche SSH-Schlüssel, der auf dem Remote-Server hinzugefügt werden muss. Weitere Informationen findest du in der Dokumentation."
msgid "Hide host keys manual input"
-msgstr ""
+msgstr "Manuelle Eingabe der Host-Tasten ausblenden"
+
+msgid "Hide payload"
+msgstr "Nutzdaten ausblenden"
msgid "Hide value"
msgid_plural "Hide values"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Wert ausblenden"
+msgstr[1] "Werte ausblenden"
msgid "Hide whitespace changes"
-msgstr ""
+msgstr "Leerzeichenänderungen ausblenden"
msgid "History"
-msgstr ""
+msgstr "Verlauf"
msgid "Housekeeping successfully started"
-msgstr "Aufräumen erfolgreich gestartet"
+msgstr "Bereinigung erfolgreich gestartet"
msgid "I accept the %{terms_link}"
-msgstr ""
+msgstr "Ich akzeptiere die %{terms_link}"
msgid "I accept the|Terms of Service and Privacy Policy"
-msgstr ""
+msgstr "Nutzungs- und Datenschutzbestimmungen"
msgid "ID"
-msgstr ""
+msgstr "ID"
msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
-msgstr ""
+msgstr "Ermöglicht Live-Vorschauen von JavaScript-Projekten in der Web-IDE mithilfe der clientseitigen CodeSandbox-Auswertung."
msgid "IDE|Back"
-msgstr ""
+msgstr "Zurück"
msgid "IDE|Client side evaluation"
-msgstr ""
+msgstr "Clientseitige Auswertung"
msgid "IDE|Commit"
-msgstr ""
+msgstr "Commit"
msgid "IDE|Edit"
-msgstr ""
+msgstr "Bearbeiten"
msgid "IDE|Get started with Live Preview"
-msgstr ""
+msgstr "Erste Schritte mit der Live-Vorschau"
msgid "IDE|Go to project"
-msgstr ""
+msgstr "Zum Projekt"
msgid "IDE|Live Preview"
-msgstr ""
+msgstr "Live-Vorschau"
msgid "IDE|Open in file view"
-msgstr ""
+msgstr "In Dateiansicht öffnen"
msgid "IDE|Preview your web application using Web IDE client-side evaluation."
-msgstr ""
+msgstr "Zeig eine Vorschau deiner Webanwendung mit der clientseitigen Auswertung der Web-IDE."
msgid "IDE|Refresh preview"
-msgstr ""
+msgstr "Vorschau aktualisieren"
msgid "IDE|Review"
-msgstr ""
+msgstr "Review"
msgid "IP Address"
-msgstr ""
+msgstr "IP-Adresse"
msgid "Identifier"
-msgstr ""
+msgstr "Identifikator"
msgid "Identities"
-msgstr ""
+msgstr "Identitäten"
msgid "Identity provider single sign on URL"
-msgstr ""
+msgstr "Single Sign On-URL des Identitätsanbieters"
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
-msgstr ""
+msgstr "Wenn diese Option deaktiviert ist, wird ein abweichender lokaler Branch nicht automatisch mit Commits von seinem remote Gegenstück aktualisiert, um lokalen Datenverlust zu verhindern. Wenn der Standardbranch (%{default_branch}) abweicht und nicht aktualisiert werden kann, schlägt die Spiegelung fehl. Andere abweichende Branches werden ohne Meldung ignoriert."
msgid "If disabled, the access level will depend on the user's permissions in the project."
-msgstr ""
+msgstr "Wenn deaktiviert, hängt der Zugriffslevel von den Berechtigungen des/der Benutzers/Benutzerin im Projekts ab."
msgid "If enabled"
-msgstr ""
+msgstr "When aktiv"
msgid "If enabled, access to projects will be validated on an external service using their classification label."
-msgstr ""
+msgstr "Wenn diese Option aktiviert ist, wird der Zugriff auf Projekte mit einem externen Service anhand ihrer Klassifizierungslabels überprüft."
msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
-msgstr ""
+msgstr "Wenn du GitHub verwendest, siehst du den Pipeline-Status für deine Commits und Pull-Anfragen, auf GitHub. %{more_info_link}"
msgid "If you already have files you can push them using the %{link_to_cli} below."
-msgstr ""
+msgstr "Wenn du bereits Dateien hast, kannst du diese pushen in dem du den %{link_to_cli} unten verwendest."
msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
-msgstr ""
+msgstr "Wenn dein HTTP-Repository nicht öffentlich zugänglich ist, füge der URL Authentifizierungsinformationen hinzu: <code>https://benutzername:password@gitlab.company.com/group/project.git</code>."
msgid "ImageDiffViewer|2-up"
-msgstr ""
+msgstr "2-up"
msgid "ImageDiffViewer|Onion skin"
-msgstr ""
+msgstr "Onion-Skin"
msgid "ImageDiffViewer|Swipe"
-msgstr ""
+msgstr "Wischen"
msgid "Import"
-msgstr ""
+msgstr "Importieren"
msgid "Import Projects from Gitea"
-msgstr ""
+msgstr "Importiere Projekte von Gitea"
msgid "Import all compatible projects"
-msgstr ""
+msgstr "Importiere alle kompatiblen Projekte"
msgid "Import all projects"
-msgstr ""
+msgstr "Alle Projekte importieren"
msgid "Import all repositories"
-msgstr ""
+msgstr "Alle Repositories importieren"
msgid "Import an exported GitLab project"
-msgstr ""
+msgstr "Importiere ein exportiertes GitLab-Projekt"
msgid "Import in progress"
-msgstr ""
+msgstr "Import wird durchgeführt"
msgid "Import multiple repositories by uploading a manifest file."
-msgstr ""
+msgstr "Importiere mehrere Repositorys, indem du eine Manifestdatei hochlädst."
msgid "Import project"
-msgstr ""
+msgstr "Projekt importieren"
msgid "Import projects from Bitbucket"
-msgstr ""
+msgstr "Importiere Projekte von Bitbucket"
msgid "Import projects from Bitbucket Server"
-msgstr ""
+msgstr "Importiere Projekte von einem Bitbucket-Server"
msgid "Import projects from FogBugz"
-msgstr ""
+msgstr "Importiere Projekte von FogBugz"
msgid "Import projects from GitLab.com"
-msgstr ""
+msgstr "Importiere Projekte von GitLab.com"
msgid "Import projects from Google Code"
-msgstr ""
+msgstr "Importiere Projekte von Google Code"
msgid "Import repositories from Bitbucket Server"
-msgstr ""
+msgstr "Importiere Repositories von einem Bitbucket-Server"
msgid "Import repositories from GitHub"
-msgstr ""
+msgstr "Importiere Repositories von GitHub"
msgid "Import repository"
msgstr "Repository importieren"
msgid "ImportButtons|Connect repositories from"
-msgstr ""
+msgstr "Verbinde Repositories von"
msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr ""
+msgstr "Verbessere Ticketboards mit der GitLab Enterprise Edition."
msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
-msgstr ""
+msgstr "Verbessere das Ticketmanagement mit Ticketgewichtung und der Gitlab Enterprise Edition."
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
-msgstr ""
+msgstr "Verbessere die Suche mit der „Erweiterten globalen Suche“ und GitLab Enterprise Edition."
+
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr "Um die Analyse auf Instanzebene zu aktivieren, bitte eine(n) Administrator(in), den %{usage_ping_link_start}Nutzungsbericht%{usage_ping_link_end} zu aktivieren."
msgid "In the next step, you'll be able to select the projects you want to import."
-msgstr ""
+msgstr "Im nächsten Schritt kannst du die Projekte auswählen, die du importieren möchtest."
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
-msgstr ""
+msgstr "Füge Nutzungsbedingungen und eine Datenschutzrichtlinie hinzu, die alle Benutzer(innen) akzeptieren müssen."
msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
-msgstr ""
+msgstr "Füge bei Bedarf den Benutzernamen in die URL ein: <code>https://benutzername@gitlab.company.com/group/project.git</code>."
msgid "Incompatible Project"
-msgstr ""
+msgstr "Inkompatibles Projekt"
msgid "Indicates whether this runner can pick jobs without tags"
-msgstr ""
+msgstr "Gibt an, ob dieser Runner Jobs ohne Tags auswählen kann"
msgid "Inline"
-msgstr ""
+msgstr "Inline"
msgid "Input host keys manually"
-msgstr ""
+msgstr "Gib die Host-Schlüssel manuell ein"
msgid "Input your repository URL"
-msgstr ""
+msgstr "Gib deine Repository-URL ein"
msgid "Install GitLab Runner"
-msgstr ""
+msgstr "Installiere einen GitLab Runner"
msgid "Install Runner on Kubernetes"
-msgstr ""
+msgstr "Installiere einen Runner auf Kubernetes"
msgid "Instance"
msgid_plural "Instances"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Instanz"
+msgstr[1] "Instanzen"
msgid "Instance Statistics"
-msgstr ""
+msgstr "Instanzstatistiken"
msgid "Instance Statistics visibility"
-msgstr ""
+msgstr "Sichtbarkeit der Instanzstatistiken"
msgid "Instance does not support multiple Kubernetes clusters"
-msgstr ""
+msgstr "Instanz unterstützt nicht mehrere Kubernetes-Cluster"
msgid "Integrations"
-msgstr ""
+msgstr "Integrationen"
msgid "Integrations Settings"
-msgstr ""
+msgstr "Integrationseinstellungen"
msgid "Interested parties can even contribute by pushing commits if they want to."
-msgstr ""
+msgstr "Interessierte können auch etwas beitragen wenn sie möchten, indem sie Commits pushen."
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
-msgstr ""
+msgstr "Intern - Die Gruppe und alle internen Projekte können von jedem/jeder angemeldeten Benutzer(in) angesehen werden."
msgid "Internal - The project can be accessed by any logged in user."
-msgstr ""
+msgstr "Intern - Auf das Projekt kann von jedem/jeder angemeldeten Benutzer(in) zugegriffen werden."
msgid "Internal users"
-msgstr ""
+msgstr "Interne Benutzer(innen)"
msgid "Interval Pattern"
msgstr "Intervallmuster"
@@ -4096,134 +4474,161 @@ msgstr "Intervallmuster"
msgid "Introducing Cycle Analytics"
msgstr "Arbeitsablaufsanalysen vorgestellt"
+msgid "Invite"
+msgstr "Einladen"
+
+msgid "Issue"
+msgstr "Ticket"
+
msgid "Issue Boards"
-msgstr ""
+msgstr "Ticketboards"
msgid "Issue board focus mode"
-msgstr ""
+msgstr "Ticket-Board Fokusmodus"
msgid "Issue events"
msgstr "Ticketereignisse"
msgid "IssueBoards|Board"
-msgstr ""
+msgstr "Board"
msgid "IssueBoards|Boards"
-msgstr ""
+msgstr "Boards"
msgid "Issues"
-msgstr ""
+msgstr "Tickets"
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
-msgstr ""
+msgstr "Tickets können Bugs, Tasks oder zu diskutierende Ideen sein. Tickets sind darüber hinaus auch durchsuchbar und filterbar."
msgid "Issues closed"
+msgstr "Geschlossene Tickets"
+
+msgid "Issues, merge requests, pushes and comments."
msgstr ""
-msgid "Jan"
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
msgstr ""
-msgid "January"
+msgid "IssuesAnalytics|Issues Created"
msgstr ""
-msgid "Job"
+msgid "IssuesAnalytics|Issues created per month"
msgstr ""
-msgid "Job has been erased"
+msgid "IssuesAnalytics|Last 12 months"
msgstr ""
-msgid "Jobs"
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
msgstr ""
-msgid "Job|Browse"
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
msgstr ""
-msgid "Job|Complete Raw"
+msgid "Jaeger URL"
msgstr ""
-msgid "Job|Download"
+msgid "Jaeger tracing"
msgstr ""
+msgid "Jan"
+msgstr "Jan"
+
+msgid "January"
+msgstr "Januar"
+
+msgid "Job"
+msgstr "Job"
+
+msgid "Job has been erased"
+msgstr "Job wurde gelöscht"
+
+msgid "Jobs"
+msgstr "Jobs"
+
+msgid "Job|Browse"
+msgstr "Durchsuchen"
+
+msgid "Job|Complete Raw"
+msgstr "Komplette Rohdaten"
+
+msgid "Job|Download"
+msgstr "Herunterladen"
+
msgid "Job|Erase job log"
-msgstr ""
+msgstr "Jobprotokoll löschen"
msgid "Job|Job artifacts"
-msgstr ""
+msgstr "Jobartefakte"
msgid "Job|Job has been erased"
-msgstr ""
+msgstr "Job wurde gelöscht"
msgid "Job|Job has been erased by"
-msgstr ""
+msgstr "Job wurde gelöscht von"
msgid "Job|Keep"
-msgstr ""
+msgstr "Behalten"
msgid "Job|Scroll to bottom"
-msgstr ""
+msgstr "Zum Seitenende scrollen"
msgid "Job|Scroll to top"
-msgstr ""
+msgstr "Scrolle nach oben"
msgid "Job|Show complete raw"
-msgstr ""
+msgstr "Zeige komplette Rohdaten"
msgid "Job|The artifacts were removed"
-msgstr ""
+msgstr "Die Artefakte wurden entfernt"
-msgid "Job|The artifacts will be removed"
-msgstr ""
+msgid "Job|The artifacts will be removed in"
+msgstr "Die Artefakte werden entfernt in"
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
-msgstr ""
+msgstr "Der Job hängt, da das Projekt keine zugewiesenen Runner besitzt, die online sind."
msgid "Jul"
-msgstr ""
+msgstr "Juli"
msgid "July"
-msgstr ""
+msgstr "Juli"
msgid "Jun"
-msgstr ""
+msgstr "Juni"
msgid "June"
-msgstr ""
-
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
+msgstr "Juni"
msgid "Kubernetes"
-msgstr ""
+msgstr "Kubernetes"
msgid "Kubernetes Cluster"
-msgstr ""
+msgstr "Kubernetes-Cluster"
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
-msgstr ""
+msgstr "Zeitüberschreitung beim Erstellen des Kubernetes-Clusters; %{timeout}"
msgid "Kubernetes cluster integration was not removed."
-msgstr ""
+msgstr "Kubernetes-Cluster-Integration wurde nicht entfernt."
msgid "Kubernetes cluster integration was successfully removed."
-msgstr ""
+msgstr "Kubernetes-Cluster-Integration wurde erfolgreich entfernt."
msgid "Kubernetes cluster was successfully updated."
-msgstr ""
+msgstr "Kubernetes-Cluster wurde erfolgreich aktualisiert."
msgid "Kubernetes configured"
-msgstr ""
+msgstr "Kubernetes konfiguriert"
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
-msgstr ""
+msgstr "Die Kubernetes-Service-Integration wurde eingestellt. %{deprecated_message_content} deine Kubernetes-Cluster mit der neuen Seite <a href=\"%{url}\"/>Kubernetes-Cluster</a>"
msgid "LFS"
-msgstr ""
+msgstr "LFS"
msgid "LFSStatus|Disabled"
msgstr "Deaktiviert"
@@ -4232,42 +4637,45 @@ msgid "LFSStatus|Enabled"
msgstr "Aktiviert"
msgid "Label"
-msgstr ""
+msgstr "Label"
msgid "Label actions dropdown"
-msgstr ""
+msgstr "Dropdown-Menü für die Label-Aktionen"
msgid "Label lists show all issues with the selected label."
-msgstr ""
+msgstr "Labellisten zeigen alle Tickets mit dem gewählten Label."
msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
-msgstr ""
+msgstr "%{firstLabelName} +%{remainingLabelCount} weitere"
msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
-msgstr ""
+msgstr "%{labelsString} und %{remainingLabelCount} weitere"
msgid "LabelSelect|Labels"
-msgstr ""
+msgstr "Labels"
msgid "Labels"
-msgstr ""
+msgstr "Labels"
msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
-msgstr ""
+msgstr "Labels können auf %{features} angewendet werden. Gruppenlabels stehen für jedes Projekt innerhalb der Gruppe zur Verfügung."
msgid "Labels can be applied to issues and merge requests to categorize them."
-msgstr ""
+msgstr "Labels können Tickets und Merge-Requests hinzugefügt werden um diese zu kategorisieren."
msgid "Labels can be applied to issues and merge requests."
-msgstr ""
+msgstr "Labels können auf Tickets und Merge-Requests angewendet werden."
msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
-msgstr ""
+msgstr "<span>Label</span> %{labelTitle} <span>zu Gruppenlabel hochstufen?</span>"
msgid "Labels|Promote Label"
-msgstr ""
+msgstr "Label hochstufen"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
+msgstr "%{labelTitle} hochzustufen macht es für alle Projekte in %{groupName} verfügbar. Existierende Projektlabels mit dem selben Titel werden zusammengeführt. Diese Aktion kann nicht rückgängig gemacht werden."
+
+msgid "Large File Storage"
msgstr ""
msgid "Last %d day"
@@ -4281,38 +4689,44 @@ msgstr "Letzte Pipeline"
msgid "Last commit"
msgstr "Letzter Commit"
+msgid "Last contact"
+msgstr "Letzter Kontakt"
+
msgid "Last edited %{date}"
-msgstr ""
+msgstr "Zuletzt bearbeitet %{date}"
msgid "Last edited by %{name}"
+msgstr "Zuletzt bearbeitet von %{name}"
+
+msgid "Last reply by"
msgstr ""
msgid "Last update"
-msgstr ""
+msgstr "Letzte Aktualisierung"
msgid "Last updated"
-msgstr ""
+msgstr "Letzte Aktualisierung"
msgid "LastPushEvent|You pushed to"
-msgstr "Du übertrugst an"
+msgstr "Du hast gepusht zu"
msgid "LastPushEvent|at"
msgstr "am"
msgid "Latest changes"
-msgstr ""
+msgstr "Letzte Änderungen"
msgid "Learn more"
-msgstr ""
+msgstr "Mehr Informationen"
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
-msgstr ""
+msgstr "Erfahre mehr über %{issue_boards_url}, um Tickets in mehreren Listen zu verfolgen, indem du Labels, Verantwortliche und Meilensteine verwendest. Falls du etwas im Ticketboard vermisst, erstelle bitte ein Ticket auf %{gitlab_issues_url}."
msgid "Learn more about Kubernetes"
-msgstr ""
+msgstr "Erfahre mehr über Kubernetes"
msgid "Learn more about protected branches"
-msgstr ""
+msgstr "Erfahre mehr über geschützte Branches"
msgid "Learn more in the"
msgstr "Erfahre mehr in den"
@@ -4321,7 +4735,7 @@ msgid "Learn more in the|pipeline schedules documentation"
msgstr "Pipelineplanungsdokumentation"
msgid "Leave"
-msgstr ""
+msgstr "Verlassen"
msgid "Leave group"
msgstr "Verlasse die Gruppe"
@@ -4330,525 +4744,615 @@ msgid "Leave project"
msgstr "Verlasse das Projekt"
msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
-msgstr ""
+msgstr "Belasse die Optionen \"Dateityp\" und \"Ãœbergabemethode\" auf ihren Standardwerten."
msgid "License"
-msgstr ""
+msgstr "Lizenz"
+
+msgid "LicenseManagement|Add a license"
+msgstr "Lizenz hinzufügen"
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr "Füge eine Lizenz manuell hinzu um sie zu genehmigen oder zu sperren"
+
+msgid "LicenseManagement|Approve"
+msgstr "Genehmigen"
msgid "LicenseManagement|Approve license"
-msgstr ""
+msgstr "Lizenz genehmigen"
msgid "LicenseManagement|Approve license?"
-msgstr ""
+msgstr "Lizenz genehmigen?"
msgid "LicenseManagement|Approved"
-msgstr ""
+msgstr "Genehmigt"
+
+msgid "LicenseManagement|Blacklist"
+msgstr "Sperren"
msgid "LicenseManagement|Blacklist license"
-msgstr ""
+msgstr "Lizenz sperren"
msgid "LicenseManagement|Blacklist license?"
-msgstr ""
+msgstr "Lizenz sperren?"
msgid "LicenseManagement|Blacklisted"
-msgstr ""
+msgstr "Gesperrt"
+
+msgid "LicenseManagement|Cancel"
+msgstr "Abbrechen"
msgid "LicenseManagement|License"
-msgstr ""
+msgstr "Lizenz"
msgid "LicenseManagement|License Management"
-msgstr ""
+msgstr "Lizenz-Management"
msgid "LicenseManagement|License details"
-msgstr ""
+msgstr "Lizenzdetails"
+
+msgid "LicenseManagement|License name"
+msgstr "Lizenzname"
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
-msgstr ""
+msgstr "Verwalte genehmigte und gesperrte Lizenzen für dieses Projekt."
msgid "LicenseManagement|Packages"
-msgstr ""
+msgstr "Pakete"
msgid "LicenseManagement|Remove license"
-msgstr ""
+msgstr "Lizenz entfernen"
msgid "LicenseManagement|Remove license?"
-msgstr ""
+msgstr "Lizenz entfernen?"
+
+msgid "LicenseManagement|Submit"
+msgstr "Senden"
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
-msgstr ""
+msgstr "Derzeit gibt es in diesem Projekt keine genehmigten oder gesperrte Lizenzen."
+
+msgid "LicenseManagement|This license already exists in this project."
+msgstr "Diese Lizenz ist in diesem Projekt bereits vorhanden."
msgid "LicenseManagement|URL"
-msgstr ""
+msgstr "URL"
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
-msgstr ""
+msgstr "Du bist im Begriff, die Lizenz %{name} aus diesem Projekt zu entfernen."
msgid "Licenses"
-msgstr ""
+msgstr "Lizenzen"
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Anzeige beschränkt auf maximal %d Ereignis"
+msgstr[1] "Anzeige beschränkt auf maximal %d Ereignisse"
msgid "LinkedIn"
-msgstr ""
+msgstr "LinkedIn"
msgid "List"
-msgstr ""
+msgstr "Liste"
msgid "List Your Gitea Repositories"
-msgstr ""
+msgstr "Liste deine Gitea-Repositories auf"
msgid "List available repositories"
-msgstr ""
+msgstr "Verfügbare Repositories auflisten"
+
+msgid "List view"
+msgstr "Listenansicht"
msgid "List your Bitbucket Server repositories"
-msgstr ""
+msgstr "Liste deine Bitbucket-Server-Repositorys auf"
msgid "List your GitHub repositories"
-msgstr ""
+msgstr "Liste deine GitHub-Repositories auf"
msgid "Live preview"
-msgstr ""
+msgstr "Live-Vorschau"
msgid "Loading contribution stats for group members"
-msgstr ""
+msgstr "Beitragsstatistiken für Gruppenmitglieder laden"
msgid "Loading the GitLab IDE..."
-msgstr ""
+msgstr "Laden der GitLab IDE..."
msgid "Loading..."
-msgstr ""
+msgstr "Lade..."
msgid "Lock"
-msgstr ""
+msgstr "Sperren"
msgid "Lock %{issuableDisplayName}"
-msgstr ""
+msgstr "Sperre %{issuableDisplayName}"
msgid "Lock not found"
-msgstr ""
+msgstr "Sperrung nicht gefunden"
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
-msgstr ""
+msgstr "%{issuableDisplayName} sperren? Es werden nur noch <strong>Projektmitglieder</strong> kommentieren können."
msgid "Lock to current projects"
-msgstr ""
+msgstr "Auf aktuelle Projekte beschränken"
msgid "Locked"
-msgstr ""
+msgstr "Gesperrt"
msgid "Locked Files"
-msgstr ""
+msgstr "Gesperrte Dateien"
msgid "Locked to current projects"
-msgstr ""
+msgstr "Auf aktuelle Projekte beschränkt"
msgid "Locks give the ability to lock specific file or folder."
+msgstr "Sperrungen bieten die Möglichkeit, bestimmte Dateien oder Ordner zu sperren."
+
+msgid "Login with smartcard"
msgstr ""
msgid "Logs"
-msgstr ""
+msgstr "Protokolle"
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
-msgstr ""
+msgstr "Mache alle in deinem Team unabhängig von ihrem Standort produktiver. GitLab Geo erstellt schreibgeschützte Mirror deiner GitLab-Instanz, sodass du die Zeit zum Klonen und Abrufen großer Repos reduzieren kannst."
msgid "Make sure you're logged into the account that owns the projects you'd like to import."
-msgstr ""
+msgstr "Stelle sicher, dass du mit dem Konto angemeldet bist, welches Besitzer der zu importierenden Projekte ist."
msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
-msgstr ""
+msgstr "Verwalte Git-Repositories mit detaillierten Zugriffskontrollen, die deinen Code schützen. Führe Codeüberprüfungen durch und verbessere die Zusammenarbeit mit Merge-Requests. Jedes Projekt kann auch ein Ticketsystem und ein Wiki haben."
msgid "Manage Web IDE features"
-msgstr ""
+msgstr "Web-IDE Funktionen verwalten"
msgid "Manage access"
-msgstr ""
+msgstr "Zugriff verwalten"
msgid "Manage all notifications"
-msgstr ""
+msgstr "Alle Benachrichtigungen verwalten"
msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
-msgstr ""
+msgstr "Verwalte Anwendungen, die GitLab als OAuth-Anbieter verwenden können, und Anwendungen, die du zur Verwendung deines Kontos autorisiert hast."
msgid "Manage applications that you've authorized to use your account."
-msgstr ""
+msgstr "Verwalte Anwendungen, die du autorisiert hast dein Konto verwenden zu dürfen."
msgid "Manage group labels"
-msgstr ""
+msgstr "Gruppenlabels verwalten"
msgid "Manage labels"
-msgstr ""
+msgstr "Label verwalten"
msgid "Manage project labels"
-msgstr ""
+msgstr "Projektlabel verwalten"
msgid "Manage your group’s membership while adding another level of security with SAML."
-msgstr ""
+msgstr "Verwalte die Mitgliedschaft deiner Gruppe, während du mit SAML eine weitere Sicherheitsstufe hinzufügst."
msgid "Manifest"
-msgstr ""
+msgstr "Manifest"
msgid "Manifest file import"
-msgstr ""
+msgstr "Manifestdateiimport"
msgid "Map a FogBugz account ID to a GitLab user"
-msgstr ""
+msgstr "Ordne eine FogBugz-Konto-ID einem/einer GitLab-Benutzer(in) zu"
msgid "Map a Google Code user to a GitLab user"
-msgstr ""
+msgstr "Ordne eine(n) Google Code-Benutzer(in) einem/einer GitLab-Benutzer(in) zu"
msgid "Map a Google Code user to a full email address"
-msgstr ""
+msgstr "Ordne eine(n) Google Code-Benutzer(in) einer vollständige E-Mail-Adresse zu"
msgid "Map a Google Code user to a full name"
-msgstr ""
+msgstr "Ordne eine(n) Google Code-Benutzer(in) einem vollständigen Namen zu"
msgid "Mar"
-msgstr ""
+msgstr "März"
msgid "March"
-msgstr ""
+msgstr "März"
msgid "Mark todo as done"
-msgstr ""
+msgstr "To-do als erledigt markieren"
msgid "Markdown enabled"
-msgstr ""
+msgstr "Markdown aktiviert"
+
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr "Eine Punktliste hinzufügen"
+
+msgid "MarkdownToolbar|Add a link"
+msgstr "Einen Link hinzufügen"
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr "Eine nummerierte Liste hinzufügen"
+
+msgid "MarkdownToolbar|Add a table"
+msgstr "Eine Tabelle hinzufügen"
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr "Eine Aufgabenliste hinzufügen"
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr "Einen fetten Text hinzufügen"
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr "Einen kursiven Text hinzufügen"
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr "Gehe in den Vollbildmodus"
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr "Füge ein Zitat ein"
+
+msgid "MarkdownToolbar|Insert code"
+msgstr "Füge Code ein"
msgid "Maven Metadata"
-msgstr ""
+msgstr "Maven-Metadaten"
msgid "Maven package"
-msgstr ""
+msgstr "Maven-Paket"
-msgid "Maximum git storage failures"
-msgstr ""
+msgid "Max access level"
+msgstr "Maximale Zugriffsstufe"
msgid "Maximum job timeout"
-msgstr ""
+msgstr "Maximale Job-Zeitüberschreitung"
msgid "May"
-msgstr ""
+msgstr "Mai"
msgid "Median"
msgstr "Median"
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr "Mitglied seit %{date}"
+
msgid "Members"
msgstr "Mitglieder"
msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
-msgstr ""
+msgstr "Mitglieder werden hierher weitergeleitet, wenn diese sich bei deiner Gruppe anmelden. Diese URL bekommst du von deinem Identitätsanbieter, wo es auch als \"SSO Service Location\", \"SAML Token Issuance Endpoint\" oder \"SAML 2.0/W-Federation URL\" bezeichnet sein könnte."
msgid "Merge Request"
-msgstr ""
+msgstr "Merge-Request"
msgid "Merge Request:"
-msgstr ""
+msgstr "Merge-Request:"
msgid "Merge Requests"
-msgstr ""
+msgstr "Merge-Requests"
msgid "Merge Requests created"
-msgstr ""
+msgstr "Merge_Request erstellt"
msgid "Merge events"
msgstr "Ereignisse zusammenführen"
msgid "Merge request"
-msgstr ""
+msgstr "Merge-Request"
msgid "Merge request approvals"
-msgstr ""
+msgstr "Merge-Request-Genehmigungen"
msgid "Merge requests"
-msgstr ""
+msgstr "Merge-Requests"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
-msgstr ""
+msgstr "Merge-Requests dienen dazu, deine Änderungsvorschläge für ein Projekt einzureichen und sie mit anderen zu diskutieren"
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr "Beim Hinzufügen des Kommentarentwurfs ist ein Fehler aufgetreten."
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr "Die Diskussion bleibt gelöst."
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr "Die Diskussion bleibt ungelöst."
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr "Diskussion wird gelöst."
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr "Diskussion wird nicht mehr gelöst sein."
msgid "MergeRequests|Resolve this discussion in a new issue"
-msgstr ""
+msgstr "Löse diese Diskussion in einem neuen Ticket"
msgid "MergeRequests|Saving the comment failed"
-msgstr ""
+msgstr "Speichern des Kommentars fehlgeschlagen"
msgid "MergeRequests|Toggle comments for this file"
-msgstr ""
-
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
+msgstr "Kommentare für diese Datei umschalten"
msgid "MergeRequests|View file @ %{commitId}"
-msgstr ""
+msgstr "Datei anzeigen @ %{commitId}"
msgid "MergeRequests|View replaced file @ %{commitId}"
-msgstr ""
+msgstr "Ersetzte Datei anzeigen @ %{commitId}"
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
-msgstr ""
+msgstr "%{paragraphStart}hat die Beschreibung %{descriptionChangedTimes} Mal %{timeDifferenceMinutes} geändert%{paragraphEnd}"
+
+msgid "MergeRequest|Filter files"
+msgstr "Dateien filtern"
+
+msgid "MergeRequest|No files found"
+msgstr "Keine Dateien gefunden"
msgid "Merged"
-msgstr ""
+msgstr "Merged"
msgid "Messages"
msgstr "Nachrichten"
msgid "Metrics"
-msgstr ""
+msgstr "Metriken"
msgid "Metrics - Influx"
-msgstr ""
+msgstr "Metriken - Influx"
msgid "Metrics - Prometheus"
-msgstr ""
+msgstr "Metriken - Prometheus"
+
+msgid "Metrics and profiling"
+msgstr "Metriken und Profiling"
msgid "Metrics|Business"
-msgstr ""
+msgstr "Business"
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
-msgstr ""
+msgstr "Sieh dir die CI/CD-Dokumentation zur Bereitstellung in einer Umgebung an"
msgid "Metrics|Create metric"
-msgstr ""
+msgstr "Metrik erstellen"
msgid "Metrics|Edit metric"
-msgstr ""
+msgstr "Metrik bearbeiten"
msgid "Metrics|Environment"
-msgstr ""
+msgstr "Umgebung"
msgid "Metrics|For grouping similar metrics"
-msgstr ""
+msgstr "Zum Gruppieren ähnlicher Metriken"
msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
-msgstr ""
+msgstr "Beizeichnung der vertikalen Achse des Diagramms. Normalerweise der Typ der dargestellten Einheit. Die horizontale Achse (X-Achse) entspricht immer der Zeit."
msgid "Metrics|Learn about environments"
-msgstr ""
+msgstr "Erfahre mehr über Umgebungen"
msgid "Metrics|Legend label (optional)"
-msgstr ""
+msgstr "Legendenbeschriftung (optional)"
msgid "Metrics|Must be a valid PromQL query."
-msgstr ""
+msgstr "Muss eine gültige PromQL-Abfrage sein."
msgid "Metrics|Name"
-msgstr ""
+msgstr "Name"
msgid "Metrics|New metric"
-msgstr ""
+msgstr "Neue Metrik"
msgid "Metrics|No deployed environments"
-msgstr ""
+msgstr "Keine bereitgestellten Umgebungen"
msgid "Metrics|Prometheus Query Documentation"
-msgstr ""
+msgstr "Prometheus Query-Dokumentation"
msgid "Metrics|Query"
-msgstr ""
+msgstr "Abfrage"
msgid "Metrics|Response"
-msgstr ""
+msgstr "Antwort"
msgid "Metrics|System"
-msgstr ""
+msgstr "System"
msgid "Metrics|There was an error fetching the environments data, please try again"
-msgstr ""
+msgstr "Beim Abrufen der Umgebungsdaten trat ein Fehler auf, bitte versuche es erneut"
msgid "Metrics|There was an error getting deployment information."
-msgstr ""
+msgstr "Es ist ein Fehler beim Abrufen der Bereitstellungsinformationen aufgetreten."
msgid "Metrics|There was an error getting environments information."
-msgstr ""
+msgstr "Es gab ein Fehler beim Abrufen der Umgebungsinformationen."
msgid "Metrics|There was an error while retrieving metrics"
-msgstr ""
+msgstr "Beim Abrufen der Metriken ist ein Fehler aufgetreten"
msgid "Metrics|Type"
-msgstr ""
+msgstr "Typ"
msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
-msgstr ""
+msgstr "Unerwartete Bereitstellungs-Datenantwort vom Prometheus-Endpunkt"
msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
-msgstr ""
+msgstr "Unerwartete Metriken-Datenantwort vom Prometheus-Endpunkt"
msgid "Metrics|Unit label"
-msgstr ""
+msgstr "Bezeichnung der Einheit"
msgid "Metrics|Used as a title for the chart"
-msgstr ""
+msgstr "Wird als Titel für das Diagramm verwendet"
msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
-msgstr ""
+msgstr "Wird verwendet, wenn die Abfrage eine einzelne Serie zurückgibt. Wenn mehrere Serien zurückgegeben werden, werden ihre Legendenbeschriftungen aus der Antwort übernommen."
msgid "Metrics|Y-axis label"
-msgstr ""
+msgstr "Y-Achsen-Bezeichnung"
msgid "Metrics|e.g. HTTP requests"
-msgstr ""
+msgstr "z. B. HTTP-Anfragen"
msgid "Metrics|e.g. Requests/second"
-msgstr ""
+msgstr "z. B. Anfragen/Sekunde"
msgid "Metrics|e.g. Throughput"
-msgstr ""
+msgstr "z. B. Durchsatz"
msgid "Metrics|e.g. rate(http_requests_total[5m])"
-msgstr ""
+msgstr "z. B. Rate(http_requests_total[5m])"
msgid "Metrics|e.g. req/sec"
-msgstr ""
+msgstr "z. B. Anfr./Sek."
msgid "Milestone"
-msgstr ""
+msgstr "Meilenstein"
msgid "Milestone lists not available with your current license"
-msgstr ""
+msgstr "Meilensteinlisten ist mit deiner momentanen Lizenz nicht verfügbar"
msgid "Milestone lists show all issues from the selected milestone."
-msgstr ""
+msgstr "Meilensteinlisten zeigen alle Tickets des ausgewählten Meilensteins an."
msgid "Milestones"
-msgstr ""
+msgstr "Meilensteine"
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
-msgstr ""
+msgstr "Du bist dabei, den Meilenstein %{milestoneTitle} endgültig zu löschen und ihn von %{issuesWithCount} und %{mergeRequestsWithCount} zu entfernen. Einmal gelöscht, kann es nicht rückgängig gemacht oder der Meilenstein wiederhergestellt werden."
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
-msgstr ""
+msgstr "Du bist dabei, den Meilenstein %{milestoneTitle} endgültig zu löschen. Dieser Meilenstein wird zur Zeit von keinem Ticket und keinem Merge-Request verwendet."
msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
+msgstr "<p>%{milestonePromotion}</p> %{finalWarning}"
msgid "Milestones|Delete milestone"
-msgstr ""
+msgstr "Meilenstein löschen"
msgid "Milestones|Delete milestone %{milestoneTitle}?"
-msgstr ""
+msgstr "Meilenstein %{milestoneTitle} löschen?"
msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
-msgstr ""
+msgstr "Das Löschen des Meilenstein %{milestoneTitle} ist fehlgeschlagen"
msgid "Milestones|Milestone %{milestoneTitle} was not found"
-msgstr ""
+msgstr "Meilenstein %{milestoneTitle} wurde nicht gefunden"
msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
-msgstr ""
+msgstr "%{milestoneTitle} zum Gruppenmeilenstein hochstufen?"
msgid "Milestones|Promote Milestone"
-msgstr ""
+msgstr "Meilenstein hochstufen"
msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
-msgstr ""
+msgstr "Die Hochstufung von %{milestone} wird ihn für alle Projekte innerhalb von %{groupName} verfügbar machen. Bereits existierende Projekt-Meilensteine mit dem selben Namen werden zusammengeführt. "
msgid "Milestones|This action cannot be reversed."
-msgstr ""
+msgstr "Diese Aktion kann nicht rückgängig gemacht werden."
msgid "Mirror a repository"
-msgstr ""
+msgstr "Repository spiegeln"
msgid "Mirror direction"
-msgstr ""
+msgstr "Richtung der Spiegelung"
msgid "Mirror repository"
-msgstr ""
+msgstr "Repository spiegeln"
msgid "Mirror user"
-msgstr ""
+msgstr "Benutzer(in) spiegeln"
msgid "Mirrored repositories"
-msgstr ""
+msgstr "Gespiegelte Repositories"
msgid "Mirroring repositories"
-msgstr ""
+msgstr "Spiegelnde Repositories"
msgid "MissingSSHKeyWarningLink|add an SSH key"
-msgstr "einen SSH Schlüssel hinzufügst"
+msgstr "einen SSH-Schlüssel hinzufügen"
msgid "Modal|Cancel"
-msgstr ""
+msgstr "Abbrechen"
msgid "Modal|Close"
-msgstr ""
+msgstr "Schließen"
msgid "Monitoring"
msgstr "Ãœberwachung"
msgid "Months"
-msgstr ""
+msgstr "Monate"
msgid "More"
-msgstr ""
+msgstr "Mehr"
msgid "More actions"
-msgstr ""
+msgstr "Weitere Aktionen"
msgid "More info"
-msgstr ""
+msgstr "Mehr Info"
msgid "More information"
-msgstr ""
+msgstr "Mehr Informationen"
msgid "More information is available|here"
msgstr "hier"
msgid "Most stars"
-msgstr ""
+msgstr "Die meisten Sterne"
msgid "Move"
-msgstr ""
+msgstr "Verschieben"
msgid "Move issue"
-msgstr ""
+msgstr "Ticket verschieben"
msgid "Multiple issue boards"
-msgstr ""
+msgstr "Mehrere Ticket-Boards"
msgid "Name"
-msgstr ""
+msgstr "Name"
msgid "Name new label"
-msgstr ""
+msgstr "Neues Label benennen"
msgid "Name your individual key via a title"
-msgstr ""
+msgstr "Benenne deinen individuellen Schlüssel mit einem Titel"
msgid "Name:"
+msgstr "Name:"
+
+msgid "Naming, visibility"
msgstr ""
msgid "Nav|Help"
-msgstr ""
+msgstr "Hilfe"
msgid "Nav|Home"
-msgstr ""
+msgstr "Startseite"
msgid "Nav|Sign In / Register"
-msgstr ""
+msgstr "Anmelden / Registrieren"
msgid "Nav|Sign out and sign in with a different account"
-msgstr ""
+msgstr "Abmelden und mit einem anderen Konto anmelden"
msgid "Network"
-msgstr ""
+msgstr "Netzwerk"
msgid "Never"
-msgstr ""
+msgstr "Niemals"
msgid "New"
-msgstr ""
+msgstr "Neu"
msgid "New Application"
-msgstr ""
+msgstr "Neue Anwendung"
msgid "New Group"
-msgstr ""
+msgstr "Neue Gruppe"
msgid "New Identity"
-msgstr ""
+msgstr "Neue Identität"
msgid "New Issue"
msgid_plural "New Issues"
@@ -4856,214 +5360,238 @@ msgstr[0] "Neues Ticket"
msgstr[1] "Neue Tickets"
msgid "New Label"
-msgstr ""
+msgstr "Neues Label"
msgid "New Pipeline Schedule"
msgstr "Neuer Pipeline Zeitplan"
msgid "New Snippet"
-msgstr ""
+msgstr "Neuer Codeausschnitt"
msgid "New Snippets"
-msgstr ""
+msgstr "Neue Codeausschnitte"
msgid "New branch"
msgstr "Neuer Branch"
msgid "New branch unavailable"
-msgstr ""
+msgstr "Neuer Branch ist nicht verfügbar"
msgid "New directory"
msgstr "Neues Verzeichnis"
msgid "New epic"
-msgstr ""
+msgstr "Neuer Epic"
msgid "New file"
msgstr "Neue Datei"
msgid "New group"
-msgstr ""
+msgstr "Neue Gruppe"
msgid "New identity"
-msgstr ""
+msgstr "Neue Identität"
msgid "New issue"
msgstr "Neues Ticket"
msgid "New label"
-msgstr ""
+msgstr "Neues Label"
msgid "New merge request"
-msgstr "Neuer Merge Request"
+msgstr "Neuer Merge-Request"
msgid "New pipelines will cancel older, pending pipelines on the same branch"
-msgstr ""
+msgstr "Neue Pipelines brechen ältere, ausstehende Pipelines in dem selben Branch ab"
msgid "New project"
-msgstr ""
+msgstr "Neues Projekt"
msgid "New schedule"
msgstr "Neuer Zeitplan"
msgid "New snippet"
-msgstr "Neuer Schnipsel"
+msgstr "Neuer Codeausschnitt"
msgid "New subgroup"
-msgstr ""
+msgstr "Neue Untergruppe"
msgid "New tag"
msgstr "Neuer Tag"
msgid "New..."
-msgstr ""
+msgstr "Neu..."
msgid "No"
-msgstr ""
+msgstr "Nein"
msgid "No Label"
-msgstr ""
+msgstr "Kein Label"
msgid "No assignee"
-msgstr ""
+msgstr "Niemandem zugewiesen"
msgid "No branches found"
-msgstr ""
+msgstr "Keine Branches gefunden"
msgid "No changes"
-msgstr ""
+msgstr "Keine Änderungen"
msgid "No connection could be made to a Gitaly Server, please check your logs!"
-msgstr ""
+msgstr "Es konnte keine Verbindung zu einem Gitaly-Server hergestellt werden. Bitte überprüfe deine Protokolle!"
msgid "No container images stored for this project. Add one by following the instructions above."
+msgstr "Für dieses Projekt wurden keine Container-Images gespeichert. Füge eines hinzu, indem du den Anweisungen oben folgst."
+
+msgid "No contributions were found"
+msgstr "Keine Beiträge gefunden"
+
+msgid "No credit card required."
msgstr ""
msgid "No due date"
-msgstr ""
+msgstr "Kein Fälligkeitsdatum"
msgid "No estimate or time spent"
-msgstr ""
+msgstr "Keine geschätzte oder verbrauchte Zeit"
msgid "No file chosen"
-msgstr ""
-
-msgid "No files found"
-msgstr ""
+msgstr "Keine Datei ausgewählt"
msgid "No files found."
-msgstr ""
+msgstr "Keine Dateien gefunden."
msgid "No issues for the selected time period."
-msgstr ""
+msgstr "Keine Tickets für den ausgewählten Zeitraum."
msgid "No labels with such name or description"
-msgstr ""
+msgstr "Keine Tags mit einem solchen Namen oder einer solchen Beschreibung"
+
+msgid "No license. All rights reserved"
+msgstr "Keine Lizenz. Alle Rechte vorbehalten"
msgid "No merge requests for the selected time period."
-msgstr ""
+msgstr "Keine Merge-Requests für den gewählten Zeitraum."
msgid "No merge requests found"
-msgstr ""
+msgstr "Keine Merge-Requests gefunden"
msgid "No messages were logged"
-msgstr ""
+msgstr "Es wurden Nachrichten protokolliert"
msgid "No other labels with such name or description"
-msgstr ""
+msgstr "Keine anderen Tags mit einem solchen Namen oder einer solchen Beschreibung"
msgid "No packages stored for this project."
-msgstr ""
+msgstr "Keine Pakete für dieses Projekt gespeichert."
msgid "No prioritised labels with such name or description"
-msgstr ""
+msgstr "Keine priorisierten Labels mit einem solchen Namen oder einer solchen Beschreibung"
msgid "No public groups"
-msgstr ""
+msgstr "Keine öffentlichen Gruppen"
msgid "No pushes for the selected time period."
-msgstr ""
+msgstr "Keine Pushs für den ausgewählten Zeitraum."
msgid "No repository"
msgstr "Kein Repository"
+msgid "No runners found"
+msgstr "Keine Runner gefunden"
+
msgid "No schedules"
msgstr "Keine Zeitpläne"
msgid "No, directly import the existing email addresses and usernames."
-msgstr ""
+msgstr "Nein, importiere die vorhandenen E-Mail-Adressen und Benutzernamen direkt."
msgid "Nodes"
-msgstr ""
+msgstr "Knoten"
msgid "None"
-msgstr ""
+msgstr "Keine"
msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
+msgstr "Nicht alle Kommentare werden angezeigt, da du zwei Versionen des Diffs vergleichst."
msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
+msgstr "Nicht alle Kommentare werden angezeigt, da du eine alte Versionen des Diffs betrachtest."
msgid "Not allowed to merge"
-msgstr ""
+msgstr "Keine Berechtigung um zu mergen"
msgid "Not available"
msgstr "Nicht verfügbar"
msgid "Not available for private projects"
-msgstr ""
+msgstr "Nicht verfügbar für private Projekte"
msgid "Not available for protected branches"
-msgstr ""
+msgstr "Für geschützte Branches nicht verfügbar"
msgid "Not confidential"
-msgstr ""
+msgstr "Nicht vertraulich"
msgid "Not enough data"
msgstr "Nicht genügend Daten"
+msgid "Not now"
+msgstr "Nicht jetzt"
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
-msgstr ""
+msgstr "Beachte, dass der master-Branch automatisch geschützt ist. %{link_to_protected_branches}"
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
-msgstr ""
+msgstr "Hinweis: Als Administrator(in) möchtest du möglicherweise %{github_integration_link} konfigurieren, mit dem du dich über GitHub anmelden und das Verbinden von Repositories ohne Erstellung eines persönlichen Zugriffstokens erlauben kannst."
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
-msgstr ""
+msgstr "Hinweis: Als Administrator(in) möchtest du möglicherweise %{github_integration_link} konfigurieren, mit dem du dich über GitHub anmelden und das Importieren von Repositories ohne Erstellung eines persönlichen Zugriffstokens erlauben kannst."
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
-msgstr ""
+msgstr "Hinweis: Überlege dir, deine(n) GitLab-Administrator(in) zu bitten, einen %{github_integration_link} zu konfigurieren. Mit diesem kannst du dich über GitHub anmelden und Repositories verbinden, ohne einen persönlichen Access-Token generieren zu müssen."
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
-msgstr ""
+msgstr "Hinweis: Überlege dir, deine(n) GitLab Administrator(in) zu bitten, einen %{github_integration_link} zu konfigurieren. Mit diesem kannst du dich über GitHub anmelden und Repositories importieren, ohne einen persönlichen Access-Token generieren zu müssen."
msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr "Bist du sicher, dass du die Erstellung dieses Kommentars abbrechen möchtest?"
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
msgstr ""
msgid "Notification events"
msgstr "Benachrichtigungsereignisse"
msgid "NotificationEvent|Close issue"
-msgstr "Ticket abschließen"
+msgstr "Ticket schließen"
msgid "NotificationEvent|Close merge request"
-msgstr "Merge Request abschließen"
+msgstr "Merge-Request schließen"
msgid "NotificationEvent|Failed pipeline"
msgstr "Fehlgeschlagene Pipeline"
msgid "NotificationEvent|Merge merge request"
-msgstr "Merge Request umsetzen"
+msgstr "Merge-Request mergen"
msgid "NotificationEvent|New epic"
-msgstr ""
+msgstr "Neues Epic"
msgid "NotificationEvent|New issue"
msgstr "Neues Ticket"
msgid "NotificationEvent|New merge request"
-msgstr "Neuer Merge Request"
+msgstr "Neuer Merge-Request"
msgid "NotificationEvent|New note"
msgstr "Neue Notiz"
@@ -5072,7 +5600,7 @@ msgid "NotificationEvent|Reassign issue"
msgstr "Ticket neu zuweisen"
msgid "NotificationEvent|Reassign merge request"
-msgstr "Merge Request neu zuweisen"
+msgstr "Merge-Request neu zuweisen"
msgid "NotificationEvent|Reopen issue"
msgstr "Ticket wieder öffnen"
@@ -5081,7 +5609,7 @@ msgid "NotificationEvent|Successful pipeline"
msgstr "Erfolgreiche Pipeline"
msgid "NotificationLevel|Custom"
-msgstr "Individuell"
+msgstr "Benutzerdefiniert"
msgid "NotificationLevel|Disabled"
msgstr "Deaktiviert"
@@ -5102,195 +5630,210 @@ msgid "Notifications"
msgstr "Benachrichtigungen"
msgid "Notifications off"
-msgstr ""
+msgstr "Benachrichtigungen aus"
msgid "Notifications on"
-msgstr ""
+msgstr "Benachrichtigungen ein"
msgid "Nov"
-msgstr ""
+msgstr "Nov"
msgid "November"
-msgstr ""
-
-msgid "Number of access attempts"
-msgstr ""
+msgstr "November"
msgid "OK"
-msgstr ""
+msgstr "OK"
msgid "Oct"
-msgstr ""
+msgstr "Okt"
msgid "October"
-msgstr ""
+msgstr "Oktober"
msgid "OfSearchInADropdown|Filter"
msgstr "Filter"
msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
-msgstr ""
+msgstr "Nach dem Import können Repositories über SSH gespiegelt werden. Lies mehr %{ssh_link}"
msgid "One more item"
msgid_plural "%d more items"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Ein weiteres Element"
+msgstr[1] "%d weitere Elemente"
msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
-msgstr ""
+msgstr "Ein oder mehrere deiner Bitbucket-Projekte kann/können nicht direkt in GitLab importiert werden, da sie Subversion oder Mercurial für die Versionskontrolle anstelle von Git verwenden."
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
-msgstr ""
-
-msgid "Online IDE integration settings."
-msgstr ""
+msgstr "Ein oder mehrere Ihrer Google Code-Projekte kann/können nicht direkt in GitLab importiert werden, da sie Subversion oder Mercurial für die Versionskontrolle anstelle von Git verwenden."
msgid "Only admins"
-msgstr ""
+msgstr "Nur Administrator(inn)en"
msgid "Only comments from the following commit are shown below"
-msgstr ""
+msgstr "Nur Kommentare des folgende Commits werden unten angezeigt"
msgid "Only mirror protected branches"
-msgstr ""
+msgstr "Nur geschützte Branches spiegeln"
msgid "Only project members can comment."
-msgstr ""
+msgstr "Nur Projektmitglieder können kommentieren."
msgid "Oops, are you sure?"
-msgstr ""
+msgstr "Ups, bist du sicher?"
msgid "Open"
-msgstr ""
+msgstr "Öffnen"
msgid "Open in Xcode"
-msgstr ""
+msgstr "In Xcode öffnen"
+
+msgid "Open projects"
+msgstr "Projekte öffnen"
msgid "Open sidebar"
-msgstr ""
+msgstr "Menüleiste öffnen"
msgid "Open source software to collaborate on code"
-msgstr ""
+msgstr "Open-Source-Software für die Zusammenarbeit an Code"
msgid "Opened"
-msgstr ""
+msgstr "Geöffnet"
msgid "Opened MR"
-msgstr ""
+msgstr "Geöffneter MR"
msgid "Opened issues"
-msgstr ""
+msgstr "Geöffnete Tickets"
msgid "OpenedNDaysAgo|Opened"
-msgstr "Ungelöst"
+msgstr "Erstellt"
msgid "Opens in a new window"
-msgstr ""
+msgstr "Wird in einem neuen Fenster geöffnet"
msgid "Operations"
+msgstr "Vorgänge"
+
+msgid "Operations Dashboard"
msgstr ""
-msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgid "Operations Settings"
msgstr ""
-msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
msgstr ""
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr "Optional kannst du %{link_to_customize}, wie FogBugz E-Mail-Adressen und Benutzernamen in GitLab importiert werden."
+
+msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
+msgstr "Optional kannst du %{link_to_customize}, wie Google Code E-Mail-Adressen und Benutzernamen in GitLab importiert werden."
+
msgid "Options"
msgstr "Optionen"
msgid "Or you can choose one of the suggested colors below"
-msgstr ""
+msgstr "Oder du wählst eine der unten vorgeschlagenen Farben"
msgid "Other Labels"
-msgstr ""
+msgstr "Andere Labels"
msgid "Other information"
-msgstr ""
+msgstr "Andere Informationen"
msgid "Otherwise it is recommended you start with one of the options below."
-msgstr ""
+msgstr "Andernfalls empfiehlt es sich, mit einer der folgenden Optionen zu beginnen."
msgid "Outbound requests"
-msgstr ""
+msgstr "Ausgehende Anfragen"
msgid "Overview"
msgstr "Ãœbersicht"
msgid "Overwrite diverged branches"
-msgstr ""
+msgstr "Ãœberschreibe abweichende Branches"
msgid "Owner"
-msgstr "Besitzer"
+msgstr "Besitzer(in)"
msgid "Package information"
-msgstr ""
+msgstr "Paketinformationen"
msgid "Package was removed"
-msgstr ""
+msgstr "Paket wurde entfernt"
msgid "Packages"
-msgstr ""
+msgstr "Pakete"
msgid "Pages"
-msgstr ""
+msgstr "Seiten"
msgid "Pagination|Last »"
-msgstr ""
+msgstr "Letzte »"
msgid "Pagination|Next"
-msgstr ""
+msgstr "Nächste"
msgid "Pagination|Prev"
-msgstr ""
+msgstr "Vorherige"
msgid "Pagination|« First"
-msgstr ""
+msgstr "« Erste"
msgid "Part of merge request changes"
-msgstr ""
+msgstr "Teil der Merge-Request-Änderungen"
msgid "Password"
msgstr "Passwort"
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgstr "Füge deinen öffentlichen SSH-Schlüssel ein, der normalerweise in der Datei '~/.ssh/id_rsa.pub' enthalten ist und mit 'ssh-rsa' beginnt. Verwende nicht deinen privaten SSH-Schlüssel."
+
+msgid "Path, transfer, remove"
msgstr ""
msgid "Path:"
-msgstr ""
+msgstr "Pfad:"
msgid "Pause"
-msgstr ""
+msgstr "Pausieren"
msgid "Paused Runners don't accept new jobs"
-msgstr ""
+msgstr "Angehaltene Runner akzeptieren keine neuen Jobs"
msgid "Pending"
-msgstr ""
+msgstr "In Arbeit"
msgid "People without permission will never get a notification and won't be able to comment."
-msgstr ""
+msgstr "Personen ohne Berechtigung werden nie eine Benachrichtigung bekommen und können auch nicht kommentieren."
msgid "Per job. If a job passes this threshold, it will be marked as failed"
-msgstr ""
+msgstr "Pro Job. Wenn ein Job diesen Schwellenwert überschreitet, wird er als fehlgeschlagen markiert"
msgid "Perform advanced options such as changing path, transferring, or removing the group."
-msgstr ""
+msgstr "Führe erweiterte Optionen aus, wie z. B. das Ändern des Pfades, Übertragen oder Entfernen einer Gruppe."
msgid "Performance optimization"
-msgstr ""
+msgstr "Leistungsoptimierung"
msgid "Permissions"
-msgstr ""
+msgstr "Zugriffsberechtigungen"
+
+msgid "Permissions, LFS, 2FA"
+msgstr "Berechtigungen, LFS, 2FA"
msgid "Personal Access Token"
-msgstr ""
+msgstr "Persönlicher Zugangs-Token"
msgid "Pipeline"
-msgstr ""
-
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
-msgstr ""
+msgstr "Pipeline"
msgid "Pipeline Health"
msgstr "Zustand der Pipeline"
@@ -5299,22 +5842,22 @@ msgid "Pipeline Schedule"
msgstr "Zeitplan der Pipeline"
msgid "Pipeline Schedules"
-msgstr "Zustände der Pipeline"
+msgstr "Zietpläne der Pipeline"
msgid "Pipeline quota"
-msgstr ""
+msgstr "Pipeline-Kontingent"
msgid "Pipeline triggers"
-msgstr ""
+msgstr "Pipeline-Trigger"
msgid "PipelineCharts|Failed:"
msgstr "Fehlgeschlagen:"
msgid "PipelineCharts|Overall statistics"
-msgstr "Gesamte Statisktiken"
+msgstr "Gesamtstatistik"
msgid "PipelineCharts|Success ratio:"
-msgstr "Erfolgsverhältnis:"
+msgstr "Erfolgsquote:"
msgid "PipelineCharts|Successful:"
msgstr "Erfolgreich:"
@@ -5341,10 +5884,10 @@ msgid "PipelineSchedules|None"
msgstr "Nichts"
msgid "PipelineSchedules|Provide a short description for this pipeline"
-msgstr "Beschreibe diese Pipeline"
+msgstr "Gib eine kurze Beschreibung für diese Pipeline ein"
msgid "PipelineSchedules|Take ownership"
-msgstr "Eigentümer werden"
+msgstr "Eigentümer(in) werden"
msgid "PipelineSchedules|Target"
msgstr "Ziel"
@@ -5353,91 +5896,106 @@ msgid "PipelineSchedules|Variables"
msgstr "Variablen"
msgid "PipelineSheduleIntervalPattern|Custom"
-msgstr "Individuell"
+msgstr "Benutzerdefiniert"
msgid "Pipelines"
-msgstr ""
+msgstr "Pipelines"
msgid "Pipelines charts"
msgstr "Pipelinediagramme"
msgid "Pipelines for last month"
-msgstr ""
+msgstr "Pipelines des letzten Monats"
msgid "Pipelines for last week"
-msgstr ""
+msgstr "Pipelines der letzten Woche"
msgid "Pipelines for last year"
msgstr "Pipelines des letzten Jahres"
msgid "Pipelines|Build with confidence"
-msgstr ""
+msgstr "Baue mit Vertrauen"
msgid "Pipelines|CI Lint"
-msgstr ""
+msgstr "CI Lint"
msgid "Pipelines|Clear Runner Caches"
-msgstr ""
+msgstr "Runner-Caches löschen"
msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
-msgstr ""
+msgstr "Kontinuierliche Integration (CI) kann dabei helfen, Fehler zu erkennen, indem es deine Tests automatisch ausführt. Kontinuierliche Bereitstellung (CD) wiederum kann dir helfen, Code für deine Produktumgebung bereitzustellen."
msgid "Pipelines|Get started with Pipelines"
-msgstr ""
+msgstr "Erste Schritte mit Pipelines"
msgid "Pipelines|Loading Pipelines"
-msgstr ""
+msgstr "Pipelines laden"
msgid "Pipelines|Project cache successfully reset."
-msgstr ""
+msgstr "Der Projekt-Cache wurde erfolgreich zurückgesetzt."
msgid "Pipelines|Run Pipeline"
-msgstr ""
+msgstr "Pipeline ausführen"
msgid "Pipelines|Something went wrong while cleaning runners cache."
-msgstr ""
+msgstr "Beim Löschen des Runner-Caches ist etwas schief gelaufen."
msgid "Pipelines|There are currently no %{scope} pipelines."
-msgstr ""
+msgstr "Derzeit gibt es keine %{scope} Pipelines."
msgid "Pipelines|There are currently no pipelines."
-msgstr ""
+msgstr "Derzeit gibt es keine Pipelines."
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
-msgstr ""
+msgstr "Beim Abrufen der Pipelines ist ein Fehler aufgetreten. Versuche es in einigen Augenblicken noch einmal oder wende dich an dein Support-Team."
msgid "Pipelines|This project is not currently set up to run pipelines."
-msgstr ""
+msgstr "Dieses Projekt ist derzeit nicht zum Ausführen von Pipelines eingerichtet."
+
+msgid "Pipeline|Commit"
+msgstr "Commit"
msgid "Pipeline|Create for"
-msgstr ""
+msgstr "Erstellen für"
msgid "Pipeline|Create pipeline"
-msgstr ""
+msgstr "Pipeline erstellen"
+
+msgid "Pipeline|Duration"
+msgstr "Dauer"
msgid "Pipeline|Existing branch name or tag"
-msgstr ""
+msgstr "Bestehender Branchname oder Tag"
+
+msgid "Pipeline|Pipeline"
+msgstr "Pipeline"
msgid "Pipeline|Run Pipeline"
-msgstr ""
+msgstr "Pipeline ausführen"
msgid "Pipeline|Search branches"
-msgstr ""
+msgstr "Branches durchsuchen"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
-msgstr ""
+msgstr "Gib die für diesen Lauf zu verwendenden Variablenwerte an. Die in %{settings_link} angegebenen Werte werden standardmäßig verwendet."
+
+msgid "Pipeline|Stages"
+msgstr "Phasen"
+
+msgid "Pipeline|Status"
+msgstr "Status"
msgid "Pipeline|Stop pipeline"
-msgstr ""
+msgstr "Pipeline stoppen"
msgid "Pipeline|Stop pipeline #%{pipelineId}?"
-msgstr ""
+msgstr "Pipeline #%{pipelineId} stoppen?"
msgid "Pipeline|Variables"
-msgstr ""
+msgstr "Variabeln"
msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
-msgstr ""
+msgstr "Du bist dabei die Pipeline %{pipelineId} zu stoppen."
msgid "Pipeline|all"
msgstr "Alle"
@@ -5446,193 +6004,310 @@ msgid "Pipeline|success"
msgstr "Erfolg"
msgid "Pipeline|with stage"
-msgstr "mit Stage"
+msgstr "mit Phase"
msgid "Pipeline|with stages"
-msgstr "mit Stages"
+msgstr "mit Phasen"
msgid "Plain diff"
-msgstr ""
-
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
+msgstr "Unformatierter Diff"
msgid "PlantUML"
-msgstr ""
+msgstr "PlantUML"
msgid "Play"
-msgstr ""
+msgstr "Ausführen"
msgid "Please accept the Terms of Service before continuing."
-msgstr ""
+msgstr "Bitte akzeptiere die Nutzungsbedingungen, um fortzufahren."
+
+msgid "Please choose a group URL with no special characters."
+msgstr "Bitte wähle eine Gruppen-URL ohne Sonderzeichen."
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
-msgstr ""
+msgstr "Bitte wandle sie in %{link_to_git} um und durchlaufe erneut die %{link_to_import_flow}."
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
-msgstr ""
+msgstr "Bitte wandle sie in Git auf Google Code um und durchlaufe erneut die %{link_to_import_flow}."
+
+msgid "Please fill in a descriptive name for your group."
+msgstr "Bitte gib einen beschreibenden Namen für deine Gruppe ein."
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
-msgstr ""
+msgstr "Bitte beachte, dass diese Anwendung nicht von GitLab bereitgestellt wird. Du solltest daher die Authentizität überprüfen, bevor du den Zugriff erlaubst."
msgid "Please select at least one filter to see results"
-msgstr ""
+msgstr "Bitte wähle zumindest einen Filter um Ergebnisse zu sehen"
msgid "Please solve the reCAPTCHA"
-msgstr ""
+msgstr "Bitte löse das reCAPTCHA"
msgid "Please try again"
+msgstr "Bitte erneut versuchen"
+
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait while we connect to your repository. Refresh at will."
-msgstr ""
+msgstr "Bitte warte, während wir uns mit deinem Repository verbinden. Aktualisiere nach Belieben."
msgid "Please wait while we import the repository for you. Refresh at will."
-msgstr ""
+msgstr "Warte bitte, während wir das Repository für dich importieren. Aktualisiere nach Belieben."
msgid "Preferences"
-msgstr ""
+msgstr "Einstellungen"
msgid "Preferences|Navigation theme"
-msgstr ""
+msgstr "Navigationsthema"
+
+msgid "Press Enter or click to search"
+msgstr "Drücke Eingabe oder klicke um zu suchen"
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr "Verhindere das Hinzufügen neuer Mitglieder zur Projektmitgliedschaft in dieser Gruppe"
msgid "Preview"
-msgstr ""
+msgstr "Vorschau"
+
+msgid "Preview payload"
+msgstr "Vorschau der Nutzdaten"
msgid "Primary"
-msgstr ""
+msgstr "Primär"
msgid "Prioritize"
-msgstr ""
+msgstr "Priorisieren"
msgid "Prioritize label"
-msgstr ""
+msgstr "Label priorisieren"
msgid "Prioritized Labels"
-msgstr ""
+msgstr "Priorisierte Labels"
msgid "Prioritized label"
-msgstr ""
+msgstr "Priorisiertes Label"
msgid "Private - Project access must be granted explicitly to each user."
-msgstr ""
+msgstr "Privat - Projektzugriff muss explizit jedem/jeder Benutzer(in) gewährt werden."
msgid "Private - The group and its projects can only be viewed by members."
-msgstr ""
+msgstr "Privat - Die Gruppe und dessen Projekte können nur von Mitgliedern eingesehen werden."
msgid "Private projects can be created in your personal namespace with:"
-msgstr ""
+msgstr "Private Projekte können in deinem persönlichen Namensraum erstellt werden:"
msgid "Profile"
msgstr "Profil"
msgid "Profile Settings"
-msgstr ""
+msgstr "Profileinstellungen"
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Du bist dabei, %{yourAccount} permanent zu löschen, inklusive aller Tickets, Merge-Requests und Gruppen die mit deinem Account verknüpft sind. Sobald du %{deleteAccount} bestätigst, kann diese Aktion nicht rückgängig gemacht werden."
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
-msgstr ""
+msgstr "Du bist dabei, deinen Benutzernamen von %{currentUsernameBold} in %{newUsernameBold} zu ändern. Profile und Projekte werden auf den neuen %{newUsername}-Namensraum umgeleitet, aber diese Umleitung wird auslaufen, sobald der %{currentUsername}-Namensraum von einem anderen Benutzer oder einer anderen Gruppe registriert wird. Bitte aktualisiere deine Git-Repository-Remotes so bald wie möglich."
msgid "Profiles|Account scheduled for removal."
-msgstr ""
+msgstr "Konto zur Löschung vorgemerkt."
msgid "Profiles|Add key"
-msgstr ""
+msgstr "Schlüssel hinzufügen"
msgid "Profiles|Add status emoji"
-msgstr ""
+msgstr "Füge Status-Emoji hinzu"
+
+msgid "Profiles|Avatar cropper"
+msgstr "Avatar zuschneiden"
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr "Avatar wird entfernt. Bist du sicher?"
msgid "Profiles|Change username"
-msgstr ""
+msgstr "Benutzernamen ändern"
+
+msgid "Profiles|Choose file..."
+msgstr "Datei auswählen..."
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr "Wähle dies aus, um Beiträge privater Projekte in deinem öffentlichen Profil ohne Projekt-, Repository- oder Organisationsinformationen anzuzeigen."
msgid "Profiles|Clear status"
-msgstr ""
+msgstr "Status löschen"
msgid "Profiles|Current path: %{path}"
-msgstr ""
+msgstr "Aktueller Pfad: %{path}"
+
+msgid "Profiles|Current status"
+msgstr "Aktueller Status"
msgid "Profiles|Delete Account"
-msgstr ""
+msgstr "Konto löschen"
msgid "Profiles|Delete account"
-msgstr ""
+msgstr "Konto löschen"
msgid "Profiles|Delete your account?"
-msgstr ""
+msgstr "Dein Konto löschen?"
msgid "Profiles|Deleting an account has the following effects:"
-msgstr ""
+msgstr "Löschen eines Kontos hat folgende Auswirkungen:"
+
+msgid "Profiles|Do not show on profile"
+msgstr "Nicht im Profil zeigen"
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr "Zeige keine aktivitätsbezogenen persönlichen Informationen in deinem Profilen an"
+
+msgid "Profiles|Edit Profile"
+msgstr "Profil bearbeiten"
msgid "Profiles|Invalid password"
-msgstr ""
+msgstr "Ungültiges Kennwort"
msgid "Profiles|Invalid username"
+msgstr "Ungültiger Benutzername"
+
+msgid "Profiles|Learn more"
+msgstr "Erfahre mehr"
+
+msgid "Profiles|Made a private contribution"
msgstr ""
+msgid "Profiles|Main settings"
+msgstr "Haupteinstellungen"
+
+msgid "Profiles|No file chosen"
+msgstr "Keine Datei ausgewählt"
+
msgid "Profiles|Path"
-msgstr ""
+msgstr "Pfad"
+
+msgid "Profiles|Position and size your new avatar"
+msgstr "Lege Position und Größe deines neuen Avatars fest"
+
+msgid "Profiles|Private contributions"
+msgstr "Private Beiträge"
+
+msgid "Profiles|Public Avatar"
+msgstr "Öffentlicher Avatar"
+
+msgid "Profiles|Remove avatar"
+msgstr "Avatar entfernen"
+
+msgid "Profiles|Set new profile picture"
+msgstr "Neues Profilbild festlegen"
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr "Einige Optionen sind für LDAP-Accounts nicht verfügbar"
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr "Erzähle uns von dir in weniger als 250 Zeichen."
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr "Die maximal zulässige Dateigröße beträgt 200KB."
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
-msgstr ""
+msgstr "Das sieht nicht aus wie ein öffentlicher SSH-Schlüssel aus. Bist du sicher, dass du ihn hinzufügen willst?"
+
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr "Diese E-Mail wird in deinem öffentlichen Profil angezeigt."
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr "Diese E-Mail-Adresse wird für webbasierte Vorgänge wie Bearbeitungen und Merges verwendet. %{learn_more}"
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
-msgstr ""
+msgstr "Dieses Emoji und diese Nachricht werden in deinem Profil und auf der gesamten Benutzeroberfläche angezeigt."
+
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr "Dieses Feature ist experimentell und die Ãœbersetzungen sind noch nicht abgeschlossen."
+
+msgid "Profiles|This information will appear on your profile."
+msgstr "Diese Informationen werden in deinem Profil angezeigt."
msgid "Profiles|Type your %{confirmationValue} to confirm:"
-msgstr ""
+msgstr "Gib deinen %{confirmationValue} zur Bestätigung ein:"
msgid "Profiles|Typically starts with \"ssh-rsa …\""
-msgstr ""
+msgstr "Beginnt normalerweise mit \"ssh-rsa ...\""
+
+msgid "Profiles|Update profile settings"
+msgstr "Profileinstellungen aktualisieren"
msgid "Profiles|Update username"
-msgstr ""
+msgstr "Benutzername aktualisieren"
+
+msgid "Profiles|Upload new avatar"
+msgstr "Neuen Avatar hochladen"
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr "Private E-Mail verwenden - %{email}"
msgid "Profiles|Username change failed - %{message}"
-msgstr ""
+msgstr "Änderung des Benutzernamens fehlgeschlagen - %{message}"
msgid "Profiles|Username successfully changed"
-msgstr ""
+msgstr "Benutzername erfolgreich geändert"
+
+msgid "Profiles|Website"
+msgstr "Webseite"
msgid "Profiles|What's your status?"
-msgstr ""
+msgstr "Was ist dein Status?"
+
+msgid "Profiles|You can change your avatar here"
+msgstr "Du kannst deinen Avatar hier ändern"
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr "Du kannst deinen Avatar hier ändern oder den aktuellen Avatar entfernen, um zu %{gravatar_link} zurückzukehren"
+
+msgid "Profiles|You can upload your avatar here"
+msgstr "Du kannst deinen Avatar hier hochladen"
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr "Du kannst deinen Avatar hier hochladen oder bei %{gravatar_link} ändern"
msgid "Profiles|You don't have access to delete this user."
-msgstr ""
+msgstr "Du hast keine Berechtigung, um diese(n) Benutzer(in) zu löschen."
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
-msgstr ""
+msgstr "Du musst die Eigentumsrechte dieser Gruppen übertragen oder die Gruppen löschen, bevor du dein Konto löschen kannst."
msgid "Profiles|Your account is currently an owner in these groups:"
-msgstr ""
+msgstr "Dein Konto ist derzeit ein Besitzer in diesen Gruppen:"
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr "Deine E-Mail-Adresse wurde automatisch basierend auf deinem %{provider_label} Konto festgelegt."
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr "Dein Standort wurde automatisch basierend auf deinem %{provider_label} Konto festgelegt."
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr "Dein Name wurde automatisch basierend auf deinem %{provider_label} Konto festgelegt, sodass du von dir bekannten Personen erkannt werden kannst."
msgid "Profiles|Your status"
-msgstr ""
+msgstr "Dein Status"
msgid "Profiles|e.g. My MacBook key"
-msgstr ""
+msgstr "z. B. Mein MacBook-Schlüssel"
msgid "Profiles|your account"
-msgstr ""
+msgstr "Dein Konto"
msgid "Profiling - Performance bar"
-msgstr ""
+msgstr "Pro­fi­ling - Performance-Leiste"
msgid "Programming languages used in this repository"
-msgstr ""
+msgstr "Programmiersprachen, die in diesem Repository verwendet werden"
msgid "Progress"
-msgstr ""
+msgstr "Fortschritt"
msgid "Project"
-msgstr ""
+msgstr "Projekt"
msgid "Project '%{project_name}' is in the process of being deleted."
-msgstr ""
+msgstr "Projekt \"%{project_name}\" wird gerade gelöscht."
msgid "Project '%{project_name}' queued for deletion."
msgstr "Das Projekt '%{project_name}' wurde zur Löschung eingeplant."
@@ -5644,22 +6319,25 @@ msgid "Project '%{project_name}' was successfully updated."
msgstr "Das Projekt '%{project_name}' wurde erfolgreich aktualisiert."
msgid "Project Badges"
-msgstr ""
+msgstr "Projekt-Badges"
+
+msgid "Project URL"
+msgstr "Projekt-URL"
msgid "Project access must be granted explicitly to each user."
-msgstr "Jedem Nutzer muss explizit der Zugriff auf das Projekt gewährt werden."
+msgstr "Jedem/Jeder Benutzer(in) muss explizit der Zugriff auf das Projekt gewährt werden."
msgid "Project avatar"
-msgstr ""
+msgstr "Projektavatar"
msgid "Project avatar in repository: %{link}"
-msgstr ""
+msgstr "Projektavatar im Repository: %{link}"
msgid "Project details"
msgstr "Projektdetails"
msgid "Project export could not be deleted."
-msgstr "Der Export des Projekts konnte nich gelöscht werden."
+msgstr "Der Export des Projekts konnte nicht gelöscht werden."
msgid "Project export has been deleted."
msgstr "Der Export des Projekts wurde gelöscht."
@@ -5668,28 +6346,31 @@ msgid "Project export link has expired. Please generate a new export from your p
msgstr "Der Link für den Export des Projektes ist abgelaufen. Bitte generiere einen neuen Export in den Projekteinstellungen."
msgid "Project export started. A download link will be sent by email."
-msgstr "Export des Projektes gestartet. Ein Link zum herunterladen wir Dir per E-Mail zugesandt."
+msgstr "Export des Projektes gestartet. Ein Link zum Herunterladen wir dir per E-Mail zugesandt."
msgid "Project name"
-msgstr ""
+msgstr "Projektname"
+
+msgid "Project slug"
+msgstr "Projekt-Slug"
msgid "ProjectActivityRSS|Subscribe"
msgstr "Abonnieren"
msgid "ProjectCreationLevel|Allowed to create projects"
-msgstr ""
+msgstr "Erlaubt das Erstellen von Projekten"
msgid "ProjectCreationLevel|Default project creation protection"
-msgstr ""
+msgstr "Standard-Projekterstellungsschutz"
msgid "ProjectCreationLevel|Developers + Maintainers"
-msgstr ""
+msgstr "Entwickler(innen) + Betreuer(innen)"
msgid "ProjectCreationLevel|Maintainers"
-msgstr ""
+msgstr "Betreuer(innen)"
msgid "ProjectCreationLevel|No one"
-msgstr ""
+msgstr "Niemand"
msgid "ProjectFileTree|Name"
msgstr "Name"
@@ -5698,348 +6379,375 @@ msgid "ProjectLastActivity|Never"
msgstr "Niemals"
msgid "ProjectLifecycle|Stage"
-msgstr "Stage"
+msgstr "Phase"
+
+msgid "ProjectOverview|Fork"
+msgstr "Fork"
+
+msgid "ProjectOverview|Forks"
+msgstr "Forks"
+
+msgid "ProjectOverview|Go to your fork"
+msgstr "Gehe zu deinem Fork"
+
+msgid "ProjectOverview|Star"
+msgstr "Markieren"
+
+msgid "ProjectOverview|Unstar"
+msgstr "Markierung entfernen"
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr "Du hast dein Projektlimit erreicht"
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr "Du musst dich anmelden, um ein Projekt zu markieren"
msgid "ProjectPage|Project ID: %{project_id}"
-msgstr ""
+msgstr "Projekt ID: %{project_id}"
msgid "ProjectSettings|Badges"
-msgstr ""
+msgstr "Badges"
msgid "ProjectSettings|Contact an admin to change this setting."
-msgstr ""
+msgstr "Kontaktiere eine(n) Administrator(in), um diese Einstellung zu ändern."
msgid "ProjectSettings|Customize your project badges."
-msgstr ""
+msgstr "Deine Projekt-Badges anpassen."
msgid "ProjectSettings|Failed to protect the tag"
-msgstr ""
+msgstr "Fehler beim Schützen des Tags"
msgid "ProjectSettings|Failed to update tag!"
-msgstr ""
+msgstr "Fehler beim Aktualisieren des Tags!"
msgid "ProjectSettings|Learn more about badges."
-msgstr ""
+msgstr "Erfahre mehr über Badges."
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
-msgstr ""
+msgstr "Nur signierte Commits können zu diesem Repository gepusht werden."
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
-msgstr ""
+msgstr "Diese Einstellung wird auf Serverebene angewendet und kann von einem Admin überschrieben werden."
msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
-msgstr ""
+msgstr "Diese Einstellung wird auf Serverebene angewendet, wurde aber für dieses Projekt überschrieben."
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
-msgstr ""
+msgstr "Diese Einstellung wird auf alle Projekte angewendet, sofern sie nicht von einem Admin überschrieben wird."
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
-msgstr ""
+msgstr "Benutzer(innen) können nur Commits in dieses Repository pushen die mit einer ihrer eigenen verifizierten E-Mail-Adressen committet wurden."
msgid "Projects"
-msgstr ""
+msgstr "Projekte"
msgid "Projects shared with %{group_name}"
+msgstr "Geteilte Projekte mit %{group_name}"
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
msgstr ""
msgid "ProjectsDropdown|Frequently visited"
-msgstr ""
+msgstr "Häufig besucht"
msgid "ProjectsDropdown|Loading projects"
-msgstr ""
+msgstr "Lade Projekte"
msgid "ProjectsDropdown|Projects you visit often will appear here"
msgstr "Projekte, die du häufig besuchst, werden hier angezeigt"
msgid "ProjectsDropdown|Search your projects"
-msgstr ""
+msgstr "Durchsuche deine Projekte"
msgid "ProjectsDropdown|Something went wrong on our end."
-msgstr ""
+msgstr "Auf unserer Seite ist etwas schief gelaufen."
msgid "ProjectsDropdown|Sorry, no projects matched your search"
-msgstr ""
+msgstr "Entschuldigung, es wurden keine Projekte mit diesen Suchkriterien gefunden"
msgid "ProjectsDropdown|This feature requires browser localStorage support"
-msgstr ""
+msgstr "Dieses Feature erfordert einen Browser, der LocalStorage unterstützt"
msgid "PrometheusAlerts|Add alert"
-msgstr ""
+msgstr "Alarm hinzufügen"
msgid "PrometheusAlerts|Alert set"
-msgstr ""
+msgstr "Alarm eingerichtet"
msgid "PrometheusAlerts|Edit alert"
-msgstr ""
+msgstr "Alarm bearbeiten"
msgid "PrometheusAlerts|Error creating alert"
-msgstr ""
+msgstr "Fehler beim erstellen des Alarms"
msgid "PrometheusAlerts|Error deleting alert"
-msgstr ""
+msgstr "Fehler beim Löschen des Alarms"
msgid "PrometheusAlerts|Error fetching alert"
-msgstr ""
+msgstr "Fehler beim Abrufen des Alarms"
msgid "PrometheusAlerts|Error saving alert"
-msgstr ""
+msgstr "Fehler beim Speichern des Alarm"
msgid "PrometheusAlerts|No alert set"
-msgstr ""
+msgstr "Kein Alarm eingerichtet"
msgid "PrometheusAlerts|Operator"
-msgstr ""
+msgstr "Operator"
msgid "PrometheusAlerts|Threshold"
-msgstr ""
+msgstr "Grenzwert"
msgid "PrometheusDashboard|Time"
-msgstr ""
+msgstr "Zeit"
msgid "PrometheusService|%{exporters} with %{metrics} were found"
-msgstr ""
+msgstr "Es wurden %{exporters} mit %{metrics} gefunden"
msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
-msgstr ""
+msgstr "<p class=\"text-tertiary\">Es wurden keine <a href=\"%{docsUrl}\">allgemeinen Metriken</a> gefunden</p>"
msgid "PrometheusService|Active"
-msgstr ""
+msgstr "Aktiv"
msgid "PrometheusService|Auto configuration"
-msgstr ""
+msgstr "Automatische Konfiguration"
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
-msgstr ""
-
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
+msgstr "Konfiguriere und stelle Prometheus automatisch auf deinen Clustern bereit, um deine Projektumgebungen zu überwachen"
msgid "PrometheusService|Common metrics"
-msgstr ""
+msgstr "Allgemeine Metriken"
msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
-msgstr ""
+msgstr "Gemeinsame Metriken werden anhand einer Bibliothek von Metriken bekannter Exporter automatisch überwacht."
msgid "PrometheusService|Custom metrics"
-msgstr ""
+msgstr "Benutzerdefinierte Metriken"
msgid "PrometheusService|Finding and configuring metrics..."
-msgstr ""
+msgstr "Metriken finden und konfigurieren..."
msgid "PrometheusService|Finding custom metrics..."
-msgstr ""
+msgstr "Benutzerdefinierte Metriken werden gesucht..."
msgid "PrometheusService|Install Prometheus on clusters"
-msgstr ""
+msgstr "Installiere Prometheus auf Clustern"
msgid "PrometheusService|Manage clusters"
-msgstr ""
+msgstr "Verwalten von Clustern"
msgid "PrometheusService|Manual configuration"
-msgstr ""
+msgstr "Manuelle Konfiguration"
msgid "PrometheusService|Metrics"
-msgstr ""
+msgstr "Metriken"
msgid "PrometheusService|Missing environment variable"
-msgstr ""
+msgstr "Fehlende Umgebungsvariable"
msgid "PrometheusService|More information"
-msgstr ""
+msgstr "Weitere Informationen"
msgid "PrometheusService|New metric"
-msgstr ""
+msgstr "Neue Metrik"
msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
-msgstr ""
+msgstr "Prometheus-API-Basis-URL, wie http://prometheus.example.com/"
msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
-msgstr ""
+msgstr "Prometheus wird automatisch auf deinen Clustern verwaltet"
msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
-msgstr ""
+msgstr "Diese Metriken werden erst nach deiner ersten Bereitstellung in einer Umgebung überwacht"
msgid "PrometheusService|Time-series monitoring service"
-msgstr ""
+msgstr "Zeitreihen-Monitoring-Service"
msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
-msgstr ""
+msgstr "Deinstalliere Prometheus aus deinen Clustern, um die manuelle Konfiguration zu aktivieren"
msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
-msgstr ""
+msgstr "Deaktivier die manuelle Konfiguration unten, um die Installation von Prometheus auf deinen Clustern zu ermöglichen"
msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
-msgstr ""
+msgstr "Warte auf deine erste Bereitstellung in eine Umgebung, um allgemeine Metriken zu finden"
msgid "Promote"
-msgstr ""
+msgstr "Hochstufen"
msgid "Promote these project milestones into a group milestone."
-msgstr ""
+msgstr "Stufe diese Projektmeilensteine zu einem Gruppenmeilenstein hoch."
msgid "Promote to Group Milestone"
-msgstr ""
+msgstr "Zum Gruppenmeilenstein hochstufen"
msgid "Promote to group label"
-msgstr ""
+msgstr "Hochstufen zum Gruppenlabel"
msgid "Promotions|Don't show me this again"
-msgstr ""
+msgstr "Nicht wieder anzeigen"
msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
-msgstr ""
+msgstr "Mit Epics kannst du dein Projekt-Portfolio effizienter und mit weniger Aufwand verwalten, indem du Gruppen von Tickets, die ein Thema teilen, über Projekte und Meilensteine ​​hinweg verfolgst."
msgid "Promotions|This feature is locked."
-msgstr ""
+msgstr "Diese Funktion ist gesperrt."
msgid "Promotions|Upgrade plan"
-msgstr ""
+msgstr "Upgrade-Plan"
msgid "Protected"
-msgstr ""
+msgstr "Geschützt"
msgid "Protected Environments"
-msgstr ""
+msgstr "Geschützte Umgebungen"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
-msgstr ""
+msgstr "%{environment_name} wird für Entwickler änderbar sein. Bist du sicher?"
msgid "ProtectedEnvironment|Allowed to deploy"
-msgstr ""
+msgstr "Für Bereitstellung zugelassen"
msgid "ProtectedEnvironment|Choose who is allowed to deploy"
-msgstr ""
+msgstr "Wähle aus, wer die Bereitstellung durchführen darf"
msgid "ProtectedEnvironment|Environment"
-msgstr ""
+msgstr "Umgebung"
msgid "ProtectedEnvironment|Protect"
-msgstr ""
+msgstr "Schützen"
msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
+msgstr "Schütze Umgebungen um einzuschränken, wer Bereitstellungen ausführen darf."
msgid "ProtectedEnvironment|Protect an environment"
-msgstr ""
+msgstr "Schütze eine Umgebung"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
-msgstr ""
+msgstr "Geschützte Umgebung (%{protected_environments_count})"
msgid "ProtectedEnvironment|Select an environment"
-msgstr ""
+msgstr "Wähle eine Umgebung"
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
-msgstr ""
+msgstr "Es gibt derzeit keine geschützten Umgebungen, schütze eine Umgebung mit dem Formular oben."
msgid "ProtectedEnvironment|Unprotect"
-msgstr ""
+msgstr "Schutz aufheben"
msgid "ProtectedEnvironment|Your environment can't be unprotected"
-msgstr ""
+msgstr "Deine Umgebung kann nicht ungeschützt sein"
msgid "ProtectedEnvironment|Your environment has been protected."
-msgstr ""
+msgstr "Deine Umgebung wurde geschützt."
msgid "ProtectedEnvironment|Your environment has been unprotected"
-msgstr ""
+msgstr "Der Schutz deiner Umgebung wurde aufgehoben"
msgid "Protip:"
-msgstr ""
+msgstr "Protipp:"
msgid "Provider"
-msgstr ""
+msgstr "Provider"
msgid "Pseudonymizer data collection"
-msgstr ""
+msgstr "Pseudonymizer-Datensammlung"
msgid "Public - The group and any public projects can be viewed without any authentication."
-msgstr ""
+msgstr "Öffentlich - Die Gruppe und alle öffentlichen Projekte können ohne Authentifizierung eingesehen werden."
msgid "Public - The project can be accessed without any authentication."
-msgstr ""
+msgstr "Öffentlich - Auf das Projekt kann ohne Authentifizierung zugegriffen werden."
msgid "Public pipelines"
-msgstr ""
+msgstr "Öffentliche Pipelines"
msgid "Pull"
-msgstr ""
+msgstr "Pull"
msgid "Push"
-msgstr ""
+msgstr "Push"
msgid "Push Rules"
-msgstr ""
+msgstr "Push-Regeln"
msgid "Push events"
-msgstr "Ãœbertragungsereignisse"
+msgstr "Push-Ereignisse"
msgid "Push project from command line"
-msgstr ""
+msgstr "Pushe das Projekt von der Kommandozeile aus"
msgid "Push to create a project"
-msgstr ""
+msgstr "Pushe um ein Projekt zu erstellen"
msgid "PushRule|Committer restriction"
-msgstr ""
+msgstr "Committer-Beschränkung"
msgid "Pushed"
-msgstr ""
+msgstr "Pushed"
msgid "Pushes"
-msgstr ""
+msgstr "Pushes"
msgid "Quarters"
-msgstr ""
+msgstr "Quartale"
msgid "Quick actions can be used in the issues description and comment boxes."
-msgstr ""
+msgstr "Kurzbefehle können in Ticket-Beschreibungen und Kommentarfeldern verwendet werden."
msgid "Read more"
msgstr "Mehr lesen"
msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
-msgstr ""
+msgstr "Lies mehr über Projektberechtigungen <strong>%{link_to_help}</strong>"
msgid "Readme"
-msgstr "Lies mich"
+msgstr "Readme"
msgid "Real-time features"
+msgstr "Echtzeit-Features"
+
+msgid "Recent searches"
+msgstr "Zuletzt gesucht"
+
+msgid "Redirect to SAML provider to test configuration"
msgstr ""
msgid "Reference:"
-msgstr ""
+msgstr "Referenz:"
msgid "Refresh"
-msgstr ""
+msgstr "Aktualisieren"
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "In einer Sekunde aktualisieren, um den aktualisierten Status anzuzeigen..."
+msgstr[1] "In %d Sekunden aktualisieren, um den aktualisierten Status anzuzeigen..."
msgid "Regenerate key"
-msgstr ""
+msgstr "Schlüssel neu generieren"
msgid "Regex pattern"
-msgstr ""
+msgstr "Regex-Muster"
msgid "Register / Sign In"
-msgstr ""
+msgstr "Anmelden"
msgid "Register and see your runners for this group."
-msgstr ""
+msgstr "Registriere dich und sieh deine Runner für diese Gruppe."
msgid "Register and see your runners for this project."
-msgstr ""
+msgstr "Registriere die Runner für dieses Projekt und zeige sie an."
msgid "Registry"
-msgstr ""
+msgstr "Registry"
msgid "Related Commits"
msgstr "Zugehörige Commits"
msgid "Related Deployed Jobs"
-msgstr "Zugehörige ausgelieferte Jobs"
+msgstr "Zugehörige Bereitstellungsjobs"
msgid "Related Issues"
msgstr "Zugehörige Tickets"
@@ -6048,515 +6756,660 @@ msgid "Related Jobs"
msgstr "Zugehörige Jobs"
msgid "Related Merge Requests"
-msgstr "Zugehörige Merge Requests"
+msgstr "Zugehörige Merge-Requests"
msgid "Related Merged Requests"
-msgstr "Zugehörige umgesetzte Merge Requests"
+msgstr "Zugehörige umgesetzte Merge-Requests"
msgid "Related merge requests"
-msgstr ""
+msgstr "Zugehörige Merge-Requests"
msgid "Remind later"
msgstr "Später erinnern"
msgid "Remove"
-msgstr ""
+msgstr "Entfernen"
msgid "Remove Runner"
-msgstr ""
+msgstr "Runner entfernen"
msgid "Remove avatar"
-msgstr ""
+msgstr "Avatar entfernen"
+
+msgid "Remove group"
+msgstr "Gruppe entfernen"
msgid "Remove priority"
-msgstr ""
+msgstr "Priorität entfernen"
msgid "Remove project"
msgstr "Projekt entfernen"
+msgid "Removed group can not be restored!"
+msgstr "Entfernte Gruppe kann nicht wiederhergestellt werden!"
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr "Durch das Entfernen der Gruppe werden alle untergeordneten Projekte und Ressourcen entfernt."
+
msgid "Rename"
-msgstr ""
+msgstr "Umbenennen"
msgid "Rename file"
-msgstr ""
+msgstr "Datei umbenennen"
msgid "Rename folder"
-msgstr ""
+msgstr "Ordner umbenennen"
+
+msgid "Reopen epic"
+msgstr "Epic erneut öffnen"
msgid "Repair authentication"
-msgstr ""
+msgstr "Authentifizierung reparieren"
msgid "Reply to this email directly or %{view_it_on_gitlab}."
-msgstr ""
+msgstr "Antworte direkt auf diese E-Mail oder %{view_it_on_gitlab}."
msgid "Repo by URL"
+msgstr "Repo via URL"
+
+msgid "Report abuse to GitLab"
msgstr ""
+msgid "Reporting"
+msgstr "Statusbericht"
+
msgid "Reports|%{failedString} and %{resolvedString}"
-msgstr ""
+msgstr "%{failedString} und %{resolvedString}"
+
+msgid "Reports|Actions"
+msgstr "Aktionen"
msgid "Reports|Class"
-msgstr ""
+msgstr "Klasse"
+
+msgid "Reports|Confidence"
+msgstr "Vertrauen"
msgid "Reports|Execution time"
-msgstr ""
+msgstr "Ausführungszeit"
msgid "Reports|Failure"
-msgstr ""
+msgstr "Fehlschlag"
+
+msgid "Reports|Severity"
+msgstr "Schweregrad"
msgid "Reports|System output"
-msgstr ""
+msgstr "Systemausgabe"
msgid "Reports|Test summary"
-msgstr ""
+msgstr "Testzusammenfassung"
msgid "Reports|Test summary failed loading results"
-msgstr ""
+msgstr "Das Laden der Ergebnisse durch die Testzusammenfassung ist fehlgeschlagen"
msgid "Reports|Test summary results are being parsed"
-msgstr ""
+msgstr "Ergebnisse der Testzusammenfassung werden analysiert"
+
+msgid "Reports|Vulnerability"
+msgstr "Sicherheitslücke"
msgid "Reports|no changed test results"
-msgstr ""
+msgstr "Keine geänderten Testergebnisse"
msgid "Repository"
-msgstr ""
+msgstr "Repository"
msgid "Repository Settings"
-msgstr ""
+msgstr "Repository-Einstellungen"
msgid "Repository URL"
-msgstr ""
+msgstr "Repository-URL"
msgid "Repository has no locks."
-msgstr ""
+msgstr "Das Repository hat keine Sperren."
msgid "Repository maintenance"
-msgstr ""
+msgstr "Repository-Wartung"
msgid "Repository mirror"
-msgstr ""
+msgstr "Repository-Mirror"
msgid "Repository storage"
-msgstr ""
+msgstr "Repository-Speicher"
msgid "RepositorySettingsAccessLevel|Select"
-msgstr ""
+msgstr "Auswählen"
msgid "Request Access"
msgstr "Anfrage auf Zugriff"
msgid "Requests Profiles"
-msgstr ""
+msgstr "Fordert Profile an"
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
-msgstr "Informationen über Speicherzustand zurücksetzen"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr "Fordere alle Benutzer(innen) auf, die Nutzungsbedingungen und Datenschutzrichtlinien zu akzeptieren, wenn sie auf GitLab zugreifen."
msgid "Reset health check access token"
-msgstr "Zugriffstoken für Systemzustand zurücksetzen"
+msgstr "Zugriffstoken für den Health-Check zurücksetzen"
msgid "Reset runners registration token"
msgstr "Registrierungstoken für Runner zurücksetzen"
msgid "Resolve all discussions in new issue"
-msgstr ""
+msgstr "Löse alle Diskussionen in einem neuen Ticket"
msgid "Resolve conflicts on source branch"
-msgstr ""
+msgstr "Konflikte im Quell-Branch lösen"
msgid "Resolve discussion"
-msgstr ""
+msgstr "Diskussion beenden"
+
+msgid "Response metrics (AWS ELB)"
+msgstr "Antwortmesswerte (AWS ELB)"
msgid "Response metrics (Custom)"
-msgstr ""
+msgstr "Antwortmesswerte (benutzerdefiniert)"
+
+msgid "Response metrics (HA Proxy)"
+msgstr "Antwortmesswerte (HA Proxy)"
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr "Antwortmesswerte (NGINX Ingress)"
+
+msgid "Response metrics (NGINX)"
+msgstr "Antwortmesswerte (NGINX)"
msgid "Resume"
-msgstr ""
+msgstr "Fortsetzen"
msgid "Retry"
-msgstr ""
+msgstr "Wiederholen"
msgid "Retry this job"
-msgstr ""
+msgstr "Wiederhole diese Aufgabe"
msgid "Retry verification"
-msgstr ""
+msgstr "Wiederhole die Überprüfung"
msgid "Reveal Variables"
-msgstr ""
+msgstr "Variablen anzeigen"
msgid "Reveal value"
msgid_plural "Reveal values"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Wert anzeigen"
+msgstr[1] "Werte anzeigen"
msgid "Revert this commit"
-msgstr "Commit zurücksetzen"
+msgstr "Diesen Commit zurücksetzen"
msgid "Revert this merge request"
-msgstr "Merge Request zurücksetzen"
+msgstr "Merge-Request zurücksetzen"
msgid "Review"
-msgstr ""
+msgstr "Review"
msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
-msgstr ""
+msgstr "Überprüfe den Prozess zum Konfigurieren von Dienstanbietern bei deinem Identitätsanbieter. In diesem Fall ist GitLab der \"Dienstanbieter\" oder die \"vertrauende Seite\"."
msgid "Reviewing"
-msgstr ""
+msgstr "Überprüfung"
msgid "Reviewing (merge request !%{mergeRequestId})"
-msgstr ""
+msgstr "Überprüfung (Merge-Request !%{mergeRequestId})"
msgid "Revoke"
-msgstr ""
+msgstr "Zurücknehmen"
msgid "Roadmap"
-msgstr ""
+msgstr "Roadmap"
msgid "Run CI/CD pipelines for external repositories"
-msgstr ""
+msgstr "Führe CI/CD-Pipelines für externe Repositories aus"
msgid "Run untagged jobs"
-msgstr ""
+msgstr "Unmarkierte Jobs ausführen"
+
+msgid "Runner cannot be assigned to other projects"
+msgstr "Runner kann keinem anderen Projekt zugewiesen werden"
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr "Runner führt Jobs von allen nicht zugewiesenen Projekten aus"
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr "Runner führt Jobs von allen nicht zugewiesenen Projekten in seiner Gruppe aus"
+
+msgid "Runner runs jobs from assigned projects"
+msgstr "Runner führt Jobs von zugewiesenen Projekten aus"
msgid "Runner token"
-msgstr ""
+msgstr "Runner-Token"
+
+msgid "Runner will not receive any new jobs"
+msgstr "Runner wird keine neuen Jobs annehmen"
msgid "Runners"
-msgstr ""
+msgstr "Runners"
msgid "Runners API"
-msgstr ""
+msgstr "Runners-API"
msgid "Runners can be placed on separate users, servers, and even on your local machine."
-msgstr ""
+msgstr "Runner können durch separate Benutzer, auf Servern und sogar auf deinem lokalen Rechner ausgeführt werden."
+
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr "Runner können durch separate Benutzer, auf Servern und sogar auf deinem lokalen Rechner ausgeführt werden."
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr "Runner derzeit online: %{active_runners_count}"
msgid "Runners page"
-msgstr ""
+msgstr "Runners-Seite"
msgid "Runners page."
-msgstr ""
+msgstr "Runners-Seite."
msgid "Runners|You have used all your shared Runners pipeline minutes."
-msgstr ""
+msgstr "Du hast alle deine Pipeline-Minuten für geteilte Runner verbraucht."
msgid "Running"
-msgstr ""
+msgstr "Wird ausgeführt"
msgid "SAML SSO"
-msgstr ""
+msgstr "SAML SSO"
msgid "SAML SSO for %{group_name}"
-msgstr ""
+msgstr "SAML SSO für %{group_name}"
msgid "SAML Single Sign On"
-msgstr ""
+msgstr "SAML Single Sign On"
msgid "SAML Single Sign On Settings"
-msgstr ""
+msgstr "SAML Single Sign On-Einstellungen"
+
+msgid "SAST"
+msgstr "SAST"
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
-msgstr ""
+msgstr "SHA-1-Fingerabdruck des SAML-Tokensignaturzertifikats. Hole diesen von deinem Identitätsanbieter, wo es auch \"Daumenabdruck (Thumbprint)\" heißen könnte."
msgid "SSH Keys"
msgstr "SSH-Schlüssel"
msgid "SSH host keys"
-msgstr ""
+msgstr "SSH-Hostschlüssel"
msgid "SSH public key"
-msgstr ""
+msgstr "Öffentlicher SSH-Schlüssel"
msgid "SSL Verification"
-msgstr ""
+msgstr "SSL-Verifizierung"
msgid "Save"
-msgstr ""
+msgstr "Speichern"
msgid "Save application"
-msgstr ""
+msgstr "Anwendung speichern"
msgid "Save changes"
-msgstr ""
+msgstr "Änderungen speichern"
+
+msgid "Save changes before testing"
+msgstr "Änderungen vor dem Testen speichern"
msgid "Save pipeline schedule"
msgstr "Zeitplan der Pipeline speichern"
msgid "Save variables"
-msgstr ""
+msgstr "Variablen speichern"
msgid "Schedule a new pipeline"
msgstr "Plane eine neue Pipeline"
msgid "Scheduled"
-msgstr ""
+msgstr "Geplant"
msgid "Schedules"
-msgstr ""
+msgstr "Zeitpläne"
msgid "Scheduling Pipelines"
msgstr "Pipelines planen"
msgid "Scope"
-msgstr ""
+msgstr "Gültigkeitsbereich"
msgid "Scoped issue boards"
-msgstr ""
+msgstr "Ticketboards mit festgelegtem Umfang"
msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
-msgstr ""
+msgstr "Scrolle nach unten zu <strong>Google Code Project Hosting</strong> und aktiviere den Schalter auf der rechten Seite."
msgid "Scroll to bottom"
-msgstr ""
+msgstr "Zum Seitenende scrollen"
msgid "Scroll to top"
-msgstr ""
+msgstr "Nach oben scrollen"
msgid "Search"
-msgstr ""
+msgstr "Suche"
msgid "Search branches"
-msgstr ""
+msgstr "Branches durchsuchen"
msgid "Search branches and tags"
msgstr "Suche nach Branches und Tags"
msgid "Search files"
-msgstr ""
+msgstr "Dateien durchsuchen"
msgid "Search for projects, issues, etc."
-msgstr ""
+msgstr "Suche nach Projekten, Tickets usw."
msgid "Search merge requests"
-msgstr ""
+msgstr "Merge-Requests durchsuchen"
msgid "Search milestones"
-msgstr ""
+msgstr "Suche Meilensteine"
+
+msgid "Search or filter results..."
+msgstr "Suche oder filtere Ergebnisse..."
msgid "Search or jump to…"
-msgstr ""
+msgstr "Suche oder springe zu…"
msgid "Search project"
-msgstr ""
+msgstr "Projekt suchen"
+
+msgid "Search projects"
+msgstr "Projekte suchen"
msgid "Search users"
-msgstr ""
+msgstr "Suche Benutzer(innen)"
+
+msgid "Search your projects"
+msgstr "Deine Projekte durchsuchen"
msgid "SearchAutocomplete|All GitLab"
-msgstr ""
+msgstr "Ganz GitLab"
msgid "SearchAutocomplete|Issues I've created"
-msgstr ""
+msgstr "Tickets, die ich erstellt habe"
msgid "SearchAutocomplete|Issues assigned to me"
-msgstr ""
+msgstr "Tickets, die mir zugewiesen sind"
msgid "SearchAutocomplete|Merge requests I've created"
-msgstr ""
+msgstr "Merge-Requests, die ich erstellt habe"
msgid "SearchAutocomplete|Merge requests assigned to me"
-msgstr ""
+msgstr "Merge-Requests, die mir zugewiesen sind"
msgid "SearchAutocomplete|in all GitLab"
-msgstr ""
+msgstr "im ganzen GitLab"
msgid "SearchAutocomplete|in this group"
-msgstr ""
+msgstr "in dieser Gruppe"
msgid "SearchAutocomplete|in this project"
+msgstr "in diesem Projekt"
+
+msgid "Secret"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Security"
+msgstr "Sicherheit"
+
+msgid "Security Dashboard"
+msgstr "Sicherheits-Dashboard"
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Security Reports|Create issue"
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|Dismiss vulnerability"
msgstr ""
-msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgid "Security Reports|More info"
msgstr ""
-msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgid "Security Reports|Revert dismissal"
msgstr ""
-msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgid "Security Reports|Security dashboard documentation"
msgstr ""
-msgid "Select"
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
msgstr ""
+msgid "Security Reports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr "Das Sicherheits-Dashboard zeigt den neuesten Sicherheitsbericht an. Verwende es, um Schwachstellen zu finden und zu beheben."
+
+msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgstr "Überwache Sicherheitslücken in deinem Code"
+
+msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgstr "Pipeline %{pipelineLink} ausgelöst"
+
+msgid "Select"
+msgstr "Auswählen"
+
msgid "Select Archive Format"
msgstr "Archivierungsformat auswählen"
+msgid "Select a group to invite"
+msgstr "Wähle eine Gruppe aus, die du einladen möchtest"
+
msgid "Select a namespace to fork the project"
-msgstr ""
+msgstr "Wähle einen Namensraum aus, um einen Fork des Projekts zu erstellen"
+
+msgid "Select a template repository"
+msgstr "Wähle ein Vorlagen-Repository aus"
msgid "Select a timezone"
msgstr "Zeitzone auswählen"
msgid "Select an existing Kubernetes cluster or create a new one"
-msgstr ""
+msgstr "Wähle eine existierendes Kubernetes-Cluster aus oder erstelle ein neues"
msgid "Select assignee"
-msgstr ""
+msgstr "Bearbeiter auswählen"
msgid "Select branch/tag"
-msgstr ""
+msgstr "Branch/Tag auswählen"
msgid "Select project"
-msgstr ""
+msgstr "Projekt wählen"
msgid "Select project and zone to choose machine type"
-msgstr ""
+msgstr "Wähle ein Projekt und eine Zone, um den Maschinentyp auszuwählen"
msgid "Select project to choose zone"
-msgstr ""
+msgstr "Wähle ein Projekt aus, um die Zone auszuwählen"
msgid "Select projects you want to import."
-msgstr ""
+msgstr "Wähle die Projekte aus, die du importieren möchtest."
msgid "Select source branch"
-msgstr ""
+msgstr "Quellbranch auswählen"
msgid "Select target branch"
msgstr "Zielbranch auswählen"
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr "Wähle den Branch aus, den du als Standard für dieses Projekt festlegen möchtest. Alle Merge-Requests und Commits werden automatisch für diesen Branch ausgeführt, es sei denn, du gibst einen anderen an."
+
msgid "Select the custom project template source group."
-msgstr ""
+msgstr "Wähle die Quellgruppe der benutzerdefinierten Projektvorlage aus."
msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
-msgstr ""
+msgstr "Wenn du eine(n) GitLab-Benutzer(in) azswählst, wird in der Beschreibung des Tickets und den Kommentaren ein Link zum/zur Benutzer(in) hinzugefügt (z. B. \"Von <a href=\"#\">@johnsmith</a>\"). Außerdem wird der/die ausgewählte Benutzer(in) dem Ticket oder Kommentar zugeordnet und/oder es ihm/ihr zugewiesen."
msgid "Selective synchronization"
-msgstr ""
+msgstr "Selektive Synchronisation"
msgid "Send email"
-msgstr ""
+msgstr "E-Mail senden"
+
+msgid "Send usage data"
+msgstr "Nutzungsdaten senden"
msgid "Sep"
-msgstr ""
+msgstr "Sept"
msgid "September"
-msgstr ""
+msgstr "September"
msgid "Server version"
-msgstr ""
+msgstr "Serverversion"
msgid "Service Desk"
-msgstr ""
+msgstr "Service-Desk"
msgid "Service Templates"
-msgstr ""
+msgstr "Servicevorlagen"
msgid "Service URL"
-msgstr ""
+msgstr "Service-URL"
msgid "Session expiration, projects limit and attachment size."
-msgstr ""
+msgstr "Sitzungsablauf, Projektlimit und Anhangsgröße."
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Lege ein Passwort für dein Konto fest, um mittels %{protocol} zu übertragen (push) oder abzurufen (pull)."
+msgid "Set a template repository for projects in this group"
+msgstr "Lege ein Vorlagen-Repository für Projekte in dieser Gruppe fest"
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
-msgstr ""
+msgstr "Lege die Standardeinstellungen fest und beschränke die Sichtbarkeitsstufen. Konfiguriere die Importquellen und das Git-Zugriffsprotokoll."
msgid "Set instance-wide template repository"
-msgstr ""
+msgstr "Lege ein Instanz-weites Vorlagen-Repository"
msgid "Set max session time for web terminal."
-msgstr ""
+msgstr "Lege die maximale Sitzungszeit für das Web-Terminal fest."
msgid "Set notification email for abuse reports."
-msgstr ""
+msgstr "Benachrichtigungs-E-Mail für Missbrauchsberichte festlegen."
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
-msgstr ""
+msgstr "Lege Anforderungen für eine(n) Benutzer(in) fest, um sich anzumelden. Aktiviere die erforderliche Zwei-Faktor-Authentifizierung."
msgid "Set up CI/CD"
-msgstr ""
+msgstr "CI/CD einrichten"
+
+msgid "Set up a %{type} Runner manually"
+msgstr "Einen %{type} Runner manuell erstellen"
-msgid "Set up Koding"
-msgstr "Koding einrichten"
+msgid "Set up a specific Runner automatically"
+msgstr "Richte einen bestimmten Runner automatisch ein"
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
-msgstr ""
+msgstr "Richte notwendige Angaben (E-Mail, Vorname, Nachname) und NameID gemäß %{docsLinkStart}der Dokumentation %{icon}%{docsLinkEnd} ein"
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
-msgstr ""
+msgstr "Richte dein Projekt so ein, dass Änderungen automatisch an ein anderes Repository gesendet bzw. von diesem abgerufen werden. Branches, Tags und Commits werden automatisch synchronisiert."
msgid "SetPasswordToCloneLink|set a password"
msgstr "ein Passwort festlegst"
-msgid "Settings"
-msgstr "Einstellungen"
+msgid "SetStatusModal|Add status emoji"
+msgstr "Statusemoji hinzufügen"
-msgid "Set up a %{type} Runner manually"
-msgstr ""
+msgid "SetStatusModal|Clear status"
+msgstr "Status löschen"
-msgid "Set up a specific Runner automatically"
-msgstr ""
+msgid "SetStatusModal|Edit status"
+msgstr "Status bearbeiten"
+
+msgid "SetStatusModal|Remove status"
+msgstr "Status entfernen"
+
+msgid "SetStatusModal|Set a status"
+msgstr "Einen Status setzen"
+
+msgid "SetStatusModal|Set status"
+msgstr "Status setzen"
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr "Leider konnten wir deinen Status nicht festlegen. Bitte versuche es später erneut."
+
+msgid "SetStatusModal|What's your status?"
+msgstr "Wie ist dein Status?"
+
+msgid "Settings"
+msgstr "Einstellungen"
msgid "Share"
-msgstr ""
+msgstr "Teilen"
msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
-msgstr ""
+msgstr "Teile das <strong>%{sso_label}</strong> mit Mitgliedern, damit sie sich über deinen Identitätsanbieter bei deiner Gruppe anmelden können"
msgid "Shared Runners"
-msgstr ""
+msgstr "Geteilte Runner"
+
+msgid "Shared projects"
+msgstr "Geteilte Projekte"
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
-msgstr ""
+msgstr "Durch Zurücksetzen der Pipeline-Minuten für diesen Namensraum werden die aktuell verwendeten Minuten auf Null gesetzt."
msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
-msgstr ""
+msgstr "Pipeline-Minuten zurücksetzen"
msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
-msgstr ""
+msgstr "Verwendete Pipeline-Minuten zurücksetzen"
msgid "Sherlock Transactions"
-msgstr ""
+msgstr "Sherlock-Transaktionen"
msgid "Show command"
-msgstr ""
+msgstr "Befehl anzeigen"
msgid "Show complete raw log"
-msgstr ""
+msgstr "Zeige komplettes Rohprotokoll"
msgid "Show latest version"
-msgstr ""
+msgstr "Neuste Version zeigen"
msgid "Show latest version of the diff"
-msgstr ""
+msgstr "Zeige die letzte Version des Diffs"
msgid "Show parent pages"
-msgstr ""
+msgstr "Ãœbergeordnete Seiten anzeigen"
msgid "Show parent subgroups"
-msgstr ""
+msgstr "Zeige übergeordnete Untergruppen"
msgid "Show whitespace changes"
-msgstr ""
+msgstr "Leerzeichenänderungen anzeigen"
msgid "Showing %d event"
msgid_plural "Showing %d events"
@@ -6564,771 +7417,855 @@ msgstr[0] "Zeige %d Ereignis"
msgstr[1] "Zeige %d Ereignisse"
msgid "Side-by-side"
-msgstr ""
+msgstr "Nebeneinander"
msgid "Sidebar|Change weight"
-msgstr ""
+msgstr "Gewichtung ändern"
msgid "Sidebar|None"
-msgstr ""
+msgstr "Keine"
msgid "Sidebar|Only numeral characters allowed"
-msgstr ""
+msgstr "Nur numerische Zeichen erlaubt"
msgid "Sidebar|Weight"
-msgstr ""
+msgstr "Gewichtung"
msgid "Sign in"
-msgstr ""
+msgstr "Anmelden"
msgid "Sign in / Register"
-msgstr ""
+msgstr "Anmelden / Registrieren"
msgid "Sign in to %{group_name}"
-msgstr ""
+msgstr "Melde dich bei %{group_name} an"
msgid "Sign in with Single Sign-On"
-msgstr ""
+msgstr "Melde dich mit Single Sign-On an"
msgid "Sign out"
-msgstr ""
+msgstr "Abmelden"
msgid "Sign-in restrictions"
-msgstr ""
+msgstr "Anmeldebeschränkungen"
msgid "Sign-up restrictions"
-msgstr ""
+msgstr "Registrierungsbeschränkungen"
msgid "Size"
-msgstr ""
+msgstr "Größe"
msgid "Size and domain settings for static websites"
-msgstr ""
+msgstr "Größe und Domain-Einstellungen für statische Webseiten"
msgid "Slack application"
-msgstr ""
+msgstr "Slack-Anwendung"
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
-msgstr ""
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr "Die Slack-Integration ermöglicht es dir, mit GitLab über Slash-Befehle im Chat-Fenster zu interagieren."
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
+msgstr "Langsamer, aber stellt sicher, dass der Projektarbeitsbereich unberührt ist, da das Repository für jeden Job neu geklont wird"
+
+msgid "Smartcard"
msgstr ""
-msgid "Snippets"
+msgid "Smartcard authentication failed: client certificate header is missing."
msgstr ""
+msgid "Snippets"
+msgstr "Codeausschnitte"
+
msgid "Something went wrong on our end"
-msgstr ""
+msgstr "Bei uns ist etwas schief gelaufen"
msgid "Something went wrong on our end."
-msgstr ""
+msgstr "Bei uns ist etwas schief gelaufen."
msgid "Something went wrong on our end. Please try again!"
-msgstr ""
+msgstr "Etwas ist an unserem Ende schief gelaufen. Bitte versuche es erneut!"
msgid "Something went wrong trying to change the confidentiality of this issue"
-msgstr ""
+msgstr "Etwas ist beim Ändern der Vertraulichkeit dieses Tickets fehlgeschlagen"
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
-msgstr ""
+msgstr "Etwas ist beim Ändern des Sperrzustandes von %{issuableDisplayName} schief gelaufen"
msgid "Something went wrong when toggling the button"
-msgstr ""
+msgstr "Beim Umschalten des Buttons ist etwas schief gelaufen"
msgid "Something went wrong while closing the %{issuable}. Please try again later"
-msgstr ""
+msgstr "Beim Schließen des %{issuable} ist etwas schief gelaufen. Bitte versuche es später erneut"
msgid "Something went wrong while fetching %{listType} list"
-msgstr ""
+msgstr "Etwas ist beim Laden der Liste %{listType} fehlgeschlagen"
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr "Beim Abrufen der Kommentare ist etwas schiefgelaufen. Bitte versuche es erneut."
msgid "Something went wrong while fetching group member contributions"
-msgstr ""
+msgstr "Beim Abrufen von Gruppenmitgliedsbeiträgen ist ein Fehler aufgetreten"
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr "Beim Abrufen der Umgebungen für diesen Merge-Request ist etwas schiefgelaufen. Bitte versuche es erneut."
msgid "Something went wrong while fetching the projects."
-msgstr ""
+msgstr "Beim Abrufen der Projekte ist etwas schief gegangen."
msgid "Something went wrong while fetching the registry list."
-msgstr ""
+msgstr "Beim Abrufen der Registryliste ist etwas schief gegangen."
msgid "Something went wrong while reopening the %{issuable}. Please try again later"
-msgstr ""
+msgstr "Etwas ist beim Wiedereröffnen von %{issuable} fehlgeschlagen. Versuche es später nochmal"
msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr "Etwas ist beim Auflösen der Diskussion fehlgeschlagen. Versuche es später nochmal."
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr "Etwas lief schief, %{project} konnte nicht zum Dashboard hinzugefügt werden"
+
+msgid "Something went wrong, unable to get operations projects"
msgstr ""
+msgid "Something went wrong, unable to remove project"
+msgstr "Etwas lief schief, Projekt konnte nicht entfernt werden"
+
msgid "Something went wrong. Please try again."
-msgstr ""
+msgstr "Etwas ist schief gelaufen. Bitte versuche es erneut."
msgid "Sorry, no epics matched your search"
-msgstr ""
+msgstr "Entschuldigung, keine Epics stimmten mit deiner Suche überein"
+
+msgid "Sorry, no projects matched your search"
+msgstr "Entschuldigung, keine Projekte stimmten mit deiner Suche überein"
msgid "Sort by"
-msgstr ""
+msgstr "Sortieren nach"
msgid "SortOptions|Access level, ascending"
-msgstr ""
+msgstr "Zugriffsebene, aufsteigend"
msgid "SortOptions|Access level, descending"
-msgstr ""
+msgstr "Zugriffsebene, absteigend"
msgid "SortOptions|Created date"
-msgstr ""
+msgstr "Erstellungsdatum"
msgid "SortOptions|Due date"
-msgstr ""
+msgstr "Fälligkeitsdatum"
msgid "SortOptions|Due later"
-msgstr ""
+msgstr "Spätere Fälligkeit"
msgid "SortOptions|Due soon"
-msgstr ""
+msgstr "Bald fällig"
msgid "SortOptions|Label priority"
-msgstr ""
+msgstr "Label-Priorität"
msgid "SortOptions|Largest group"
-msgstr ""
+msgstr "Größte Gruppe"
msgid "SortOptions|Largest repository"
-msgstr ""
+msgstr "Größtes Repository"
+
+msgid "SortOptions|Last Contact"
+msgstr "Zuletzt gesehen"
msgid "SortOptions|Last created"
-msgstr ""
+msgstr "Zuletzt erstellt"
msgid "SortOptions|Last joined"
-msgstr ""
+msgstr "Zuletzt beigetreten"
msgid "SortOptions|Last updated"
-msgstr ""
+msgstr "Zuletzt aktualisiert"
msgid "SortOptions|Least popular"
-msgstr ""
+msgstr "Am unbeliebtesten"
msgid "SortOptions|Less weight"
-msgstr ""
+msgstr "Niedrigere Gewichtung"
msgid "SortOptions|Milestone"
-msgstr ""
+msgstr "Meilenstein"
msgid "SortOptions|Milestone due later"
-msgstr ""
+msgstr "Meilenstein später fällig"
msgid "SortOptions|Milestone due soon"
-msgstr ""
+msgstr "Meilenstein bald fällig"
msgid "SortOptions|More weight"
-msgstr ""
+msgstr "Höhere Gewichtung"
msgid "SortOptions|Most popular"
-msgstr ""
+msgstr "Am beliebtesten"
+
+msgid "SortOptions|Most stars"
+msgstr "Am häufigsten markiert"
msgid "SortOptions|Name"
-msgstr ""
+msgstr "Name"
msgid "SortOptions|Name, ascending"
-msgstr ""
+msgstr "Name, aufsteigend"
msgid "SortOptions|Name, descending"
-msgstr ""
+msgstr "Name, absteigend"
msgid "SortOptions|Oldest created"
-msgstr ""
+msgstr "Zuerst erstellt"
msgid "SortOptions|Oldest joined"
-msgstr ""
+msgstr "Zuerst beigetreten"
msgid "SortOptions|Oldest sign in"
-msgstr ""
+msgstr "Älteste Anmeldung"
msgid "SortOptions|Oldest updated"
-msgstr ""
+msgstr "Älteste Aktualisierung"
msgid "SortOptions|Popularity"
-msgstr ""
+msgstr "Beliebtheit"
msgid "SortOptions|Priority"
-msgstr ""
+msgstr "Priorität"
msgid "SortOptions|Recent sign in"
-msgstr ""
+msgstr "Zuletzt angemeldet"
+
+msgid "SortOptions|Start date"
+msgstr "Startdatum"
msgid "SortOptions|Start later"
-msgstr ""
+msgstr "Später starten"
msgid "SortOptions|Start soon"
-msgstr ""
+msgstr "Baldiger Start"
msgid "SortOptions|Weight"
-msgstr ""
+msgstr "Gewichtung"
msgid "Source"
-msgstr ""
+msgstr "Quelle"
msgid "Source (branch or tag)"
-msgstr ""
+msgstr "Quelle (Branch oder Tag)"
msgid "Source code"
msgstr "Quellcode"
msgid "Source is not available"
-msgstr ""
+msgstr "Quelle ist nicht verfügbar"
msgid "Spam Logs"
msgstr "Spam-Protokolle"
msgid "Spam and Anti-bot Protection"
-msgstr ""
+msgstr "Spam- und Anti-Bot-Schutz"
msgid "Specific Runners"
-msgstr ""
+msgstr "Spezifische Runner"
msgid "Specify an e-mail address regex pattern to identify default internal users."
-msgstr ""
+msgstr "Gib ein Regex-Muster für E-Mail-Adressen an, um interne Standardbenutzer(innen) zu identifizieren."
msgid "Specify the following URL during the Runner setup:"
-msgstr "Lege die folgende URL während des Runner Setups fest:"
+msgstr "Gib die folgende URL während des Runner-Setups an:"
msgid "Squash commits"
-msgstr ""
+msgstr "Squash Commits"
msgid "Stage"
-msgstr ""
+msgstr "Phase"
msgid "Stage & Commit"
-msgstr ""
+msgstr "Vormerken & Committen"
msgid "Stage all changes"
-msgstr ""
+msgstr "Alle Änderungen vormerken"
msgid "Stage changes"
-msgstr ""
+msgstr "Änderungen vormerken"
msgid "Staged"
-msgstr ""
+msgstr "Vorgemerkt"
msgid "Staged %{type}"
-msgstr ""
+msgstr "Vorgemerkt %{type}"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
-msgstr ""
+msgstr "Markiere ein Label, um es zu einem priorisierten Label zu machen. Ordne die priorisierten Labels durch Ziehen an, um ihre relative Priorität zu ändern."
msgid "StarProject|Star"
msgstr "Favorisieren"
msgid "Starred Projects"
-msgstr ""
+msgstr "Markierte Projekte"
msgid "Starred Projects' Activity"
-msgstr ""
+msgstr "Aktivität markierter Projekte"
msgid "Starred projects"
-msgstr ""
+msgstr "Markierte Projekte"
msgid "Start a %{new_merge_request} with these changes"
msgstr "Beginne einen %{new_merge_request} mit diesen Änderungen"
+msgid "Start a review"
+msgstr "Einen Review starten"
+
+msgid "Start and due date"
+msgstr "Start- und Fälligkeitsdatum"
+
+msgid "Start date"
+msgstr "Startdatum"
+
msgid "Start the Runner!"
msgstr "Starte den Runner!"
-msgid "Started"
+msgid "Start your trial"
msgstr ""
+msgid "Started"
+msgstr "Begonnen"
+
msgid "Starts at (UTC)"
-msgstr ""
+msgstr "Beginnt am (UTC)"
msgid "State your message to activate"
-msgstr ""
+msgstr "Gib deine Nachricht an, um sie zu aktivieren"
msgid "Status"
+msgstr "Status"
+
+msgid "Stop environment"
msgstr ""
msgid "Stop impersonation"
-msgstr ""
+msgstr "Stoppe die Personifikation"
msgid "Stop this environment"
-msgstr ""
+msgstr "Stoppe diese Umgebung"
msgid "Stopped"
+msgstr "Gestoppt"
+
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
msgid "Storage"
-msgstr ""
+msgstr "Speicherplatz"
msgid "Storage:"
-msgstr ""
+msgstr "Speicher:"
msgid "Subgroups"
-msgstr ""
+msgstr "Untergruppen"
+
+msgid "Subgroups and projects"
+msgstr "Untergruppen und Projekte"
msgid "Submit as spam"
-msgstr ""
+msgstr "Als Spam einreichen"
+
+msgid "Submit review"
+msgstr "Review senden"
msgid "Submit search"
-msgstr ""
+msgstr "Suche ausführen"
msgid "Subscribe"
-msgstr ""
+msgstr "Abonnieren"
msgid "Subscribe at group level"
-msgstr ""
+msgstr "Abonniere auf Gruppenebene"
msgid "Subscribe at project level"
+msgstr "Abonniere auf Projektebene"
+
+msgid "Subscribed"
+msgstr "Abonniert"
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
msgstr ""
msgid "Switch branch/tag"
msgstr "Zu Branch/Tag wechseln"
msgid "Sync information"
-msgstr ""
+msgstr "Informationen synchronisieren"
msgid "System Hooks"
-msgstr ""
+msgstr "System-Hooks"
msgid "System Info"
-msgstr ""
+msgstr "Systeminformationen"
msgid "System header and footer:"
-msgstr ""
+msgstr "Kopfzeile und Fußzeile des Systems:"
msgid "System metrics (Custom)"
-msgstr ""
+msgstr "Systemmetriken (benutzerdefiniert)"
+
+msgid "System metrics (Kubernetes)"
+msgstr "Systemmetriken (Kubernetes)"
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Tag (%{tag_count})"
+msgstr[1] "Tags (%{tag_count})"
msgid "Tags"
-msgstr ""
+msgstr "Tags"
msgid "Tags feed"
-msgstr ""
+msgstr "Tags-Feed"
msgid "Tags:"
-msgstr ""
+msgstr "Tags:"
msgid "TagsPage|Browse commits"
-msgstr ""
+msgstr "Commits durchsuchen"
msgid "TagsPage|Browse files"
-msgstr ""
+msgstr "Dateien durchsuchen"
msgid "TagsPage|Can't find HEAD commit for this tag"
-msgstr ""
+msgstr "HEAD-Commit für dieses Tag kann nicht gefunden werden"
msgid "TagsPage|Cancel"
-msgstr ""
+msgstr "Abbrechen"
msgid "TagsPage|Create tag"
-msgstr ""
+msgstr "Tag erstellen"
msgid "TagsPage|Delete tag"
-msgstr ""
+msgstr "Tag löschen"
msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
-msgstr ""
+msgstr "Löschen des Tags '%{tag_name}' kann nicht rückgängig gemacht werden. Bist du sicher?"
msgid "TagsPage|Edit release notes"
-msgstr ""
+msgstr "Versionshinweise bearbeiten"
msgid "TagsPage|Existing branch name, tag, or commit SHA"
-msgstr ""
+msgstr "Existierender Branch, Tag oder Commit-SHA"
msgid "TagsPage|Filter by tag name"
-msgstr ""
+msgstr "Nach Tag-Namen filtern"
msgid "TagsPage|New Tag"
-msgstr ""
+msgstr "Neuer Tag"
msgid "TagsPage|New tag"
-msgstr ""
+msgstr "Neuer Tag"
msgid "TagsPage|Optionally, add a message to the tag."
-msgstr ""
+msgstr "Optional kannst du dem Tag eine Nachricht hinzufügen."
msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
-msgstr ""
+msgstr "Optional kannst du dem Tag Versionshinweise hinzufügen. Diese werden in der GitLab-Datenbank gespeichert und auf der Tags-Seite angezeigt."
msgid "TagsPage|Release notes"
-msgstr ""
+msgstr "Versionshinweise"
msgid "TagsPage|Repository has no tags yet."
-msgstr ""
+msgstr "Repository hat noch keine Tags."
msgid "TagsPage|Sort by"
-msgstr ""
+msgstr "Sortieren nach"
msgid "TagsPage|Tags"
-msgstr ""
+msgstr "Tags"
msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
-msgstr ""
+msgstr "Tags erlauben es, bestimmte Punkte in der git-Historie als wichtig zu markieren"
msgid "TagsPage|This tag has no release notes."
-msgstr ""
+msgstr "Dieses Tag enthält keine Versionshinweise."
msgid "TagsPage|Use git tag command to add a new one:"
-msgstr ""
+msgstr "Verwenden Sie den Befehl git tag, um einen neuen Tag hinzuzufügen:"
msgid "TagsPage|Write your release notes or drag files here…"
-msgstr ""
+msgstr "Schreibe deine Versionshinweise oder ziehen Dateien hier hinein…"
msgid "TagsPage|protected"
-msgstr ""
+msgstr "geschützt"
msgid "Target Branch"
msgstr "Zielbranch"
msgid "Target branch"
-msgstr ""
+msgstr "Zielbranch"
msgid "Team"
-msgstr ""
+msgstr "Team"
msgid "Template"
-msgstr ""
+msgstr "Vorlage"
msgid "Templates"
-msgstr ""
+msgstr "Vorlagen"
msgid "Terms of Service Agreement and Privacy Policy"
-msgstr ""
+msgstr "Nutzungsbedingungen und Datenschutzerklärung"
msgid "Terms of Service and Privacy Policy"
-msgstr ""
+msgstr "Nutzungsbedingungen und Datenschutzerklärung"
+
+msgid "Test SAML SSO"
+msgstr "SAML SSO testen"
msgid "Test coverage parsing"
-msgstr ""
+msgstr "Testabdeckung analysieren"
msgid "Thanks! Don't show me this again"
-msgstr ""
+msgstr "Vielen Dank! Zeig es mir nicht nochmal"
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
-msgstr ""
+msgstr "Die „Erweiterte Globale Suche“ in GitLab ist ein leistungsfähiger Suchdienst, der dir Zeit spart. Anstatt doppelten Code zu erstellen und Zeit zu verschwenden, kannst du nun bei anderen Teams nach Code suchen, der für dein eigenes Projekt hilfreich sein kann."
msgid "The Git LFS objects will <strong>not</strong> be synced."
-msgstr ""
+msgstr "Die Git LFS-Objekte werden <strong>nicht</strong> synchronisiert werden."
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
-msgstr ""
+msgstr "Das Ticketsystem ist der Ort, um Dinge hinzuzufügen, die in einem Projekt verbessert oder gelöst werden müssen"
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
-msgstr ""
+msgstr "Das Ticketsystem ist der Ort, um Dinge hinzuzufügen, die in einem Projekt verbessert oder Probleme anzuführen, die gelöst werden müssen. Du kannst dich registrieren oder anmelden, um Tickets für dieses Projekt zu erstellen."
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
-msgstr ""
+msgstr "Das zu verwendende X.509-Zertifikat, wenn über MTLS mit dem externen Autorisierungsdienst kommunizieren muss. Wenn dieses Feld leer gelassen wird, wird das Serverzertifikat beim Zugriff über HTTPS weiterhin überprüft."
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
-msgstr ""
+msgstr "Das Character-Highlighter hilft dir, die Betreffzeile auf %{titleLength} Zeichen zu beschränken und den Textkörper auf %{bodyLength} zu kürzen, damit sie in Git lesbar sind."
msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
-msgstr "Die Entwicklungsphase stellt die Zeit vom ersten Commit bis zum Erstellen eines Merge Requests dar. Sobald Du Deinen ersten Merge Request anlegst, werden dessen Daten automatisch ergänzt."
+msgstr "Die Entwicklungsphase stellt die Zeit vom ersten Commit bis zum Erstellen eines Merge-Requests dar. Sobald du deinen ersten Merge-Request anlegst, werden die Daten hier automatisch ergänzt."
msgid "The collection of events added to the data gathered for that stage."
msgstr "Ereignisse, die für diese Phase ausgewertet wurden."
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
-msgstr ""
+msgstr "Die Verbindung wird nach %{timeout} beendet. Verwende eine Clone/Push-Kombination für Repositorys, die länger brauchen."
msgid "The deployment of this job to %{environmentLink} did not succeed."
-msgstr ""
+msgstr "Die Bereitstellung dieses Jobs auf %{environmentLink} war nicht erfolgreich."
msgid "The fork relationship has been removed."
-msgstr "Die Beziehung des Ablegers wurde entfernt."
+msgstr "Die Beziehung des Forks wurde entfernt."
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
-msgstr ""
+msgstr "Der Import wird nach %{timeout} beendet. Verwende eine Clone/Push-Kombination für Repositorys, die länger brauchen."
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
-msgstr "Die Ticketphase stellt die Zeit vom Anlegen eines Tickets bis zum Zuweisen eines Meilensteins oder Hinzufügen zur Aufgabentafel dar. Erstelle einen Ticket, damit dessen Daten hier erscheinen."
+msgstr "Die Ticketphase stellt die Zeit vom Anlegen eines Tickets bis zum Zuweisen zu einem Meilenstein oder dem Hinzufügen zu deinem Ticket-Board dar. Erstelle einen Ticket, damit dessen Daten hier erscheinen."
msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
+msgstr "Die maximal zulässige Dateigröße beträgt 200 KB."
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
-msgstr ""
+msgstr "Das Kennwort, das zum Entschlüsseln des privaten Schlüssels erforderlich ist. Dies ist optional und der Wert wird im Ruhezustand verschlüsselt."
msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
-msgstr ""
+msgstr "Der Pfad zur CI-Konfigurationsdatei. Der Standardwert ist <code>.gitlab-ci.yml</code>"
msgid "The phase of the development lifecycle."
msgstr "Die Phase des Entwicklungslebenszyklus."
msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
-msgstr ""
+msgstr "Die Pipelinezeitplan startet in Zukunft wiederholt Pipelines für bestimmte Branches oder Tags. Diese geplanten Pipelines haben denselben begrenzten Zugriff auf das Projekt, wie der zugeordnete Nutzer."
msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
-msgstr "Die Planungsphase stellt die Zeit von der vorherigen Phase bis zum Übertragen des ersten Commits dar. Sobald Du den ersten Commit überträgst, werden dessen Daten hier erscheinen."
+msgstr "Die Planungsphase stellt die Zeit vom vorherigen Schritt bis zum Pushen des ersten Commits dar. Sobald du den ersten Commit pusht, wird diese Zeit automatisch hinzugefügt."
msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
-msgstr ""
+msgstr "Der private Schlüssel, der verwendet werden soll, wenn ein Clientzertifikat bereitgestellt wird. Dieser Wert wird im Ruhezustand verschlüsselt."
msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
-msgstr "Die Produktionsphase stellt die Gesamtzeit vom Anlegen eines Tickets bis zur Bereitstellung des Codes auf dem Produktivsystem dar. Sobald Du den vollständigen Entwicklungszyklus, von einer Idee bis zur Fertigstellung, durchlaufen hast, erscheinen die zugehörigen Daten hier."
+msgstr "Die Produktionsphase stellt die Gesamtzeit vom Anlegen eines Tickets bis zur Bereitstellung des Codes auf der Produktivumgebung dar. Sobald du den vollständigen Entwicklungszyklus, von einer Idee bis zur Fertigstellung, durchlaufen hast, erscheinen die Daten hier."
msgid "The project can be accessed by any logged in user."
-msgstr "Auf das Projekt kann jeder angemeldete Nutzer zugreifen."
+msgstr "Auf das Projekt kann jede(r) angemeldete Nutzer(in) zugreifen."
msgid "The project can be accessed without any authentication."
msgstr "Auf das Projekt kann ohne Authentifizierung zugegriffen werden."
msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
-msgstr ""
+msgstr "Die Pseudonymizer-Datensammlung ist deaktiviert. Wenn sie aktiv ist, führt GitLab einen Hintergrundjob aus, der pseudonymisierte CSVs der GitLab-Datenbank erzeugt, die in dein konfiguriertes Objektspeicherverzeichnis hochgeladen werden."
msgid "The repository for this project does not exist."
-msgstr "Das Repository für das Projekt existiert nicht."
+msgstr "Das Repository für dieses Projekt existiert nicht."
msgid "The repository for this project is empty"
-msgstr ""
+msgstr "Das Repository für dieses Projekt ist leer"
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
-msgstr ""
+msgstr "Das Repository muss über <code>http://</code>, <code>https://</code> oder <code>git://</code> erreichbar sein."
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
-msgstr ""
+msgstr "Das Repository muss über <code>http://</code>, <code>https://</code>, <code>ssh://</code> oder <code>git://</code> erreichbar sein."
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
-msgstr "Die Überprüfungsphase stellt die Zeit vom Anlegen eines Merge Requests bis dessen Umsetzung dar. Sobald Du Deinen ersten Merge Request abschließt, werden dessen Daten hier automatisch angezeigt."
+msgstr "Die Review-Phase stellt die Zeit vom Anlegen eines Merge-Requests bis zu dessen Merge dar. Sobald du deinen ersten Merge-Request abschließt, werden diese Daten hier automatisch angezeigt."
msgid "The roadmap shows the progress of your epics along a timeline"
-msgstr ""
-
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
+msgstr "Die Roadmap zeigt den Fortschritt deiner Epics anhand einer Zeitleiste an"
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
-msgstr "Die Staging-Phase stellt die Zeit zwischen der Umsetzung eines Merge Requests und der Bereitstellung des Codes auf dem Produktivsystem dar. Sobald Du das erste Mal auf das Produktivsystem ausgeliefert hast, werden dessen Daten hier automatisch angezeigt."
+msgstr "Die Staging-Phase stellt die Zeit zwischen dem Mergen des Merge-Requests und der Bereitstellung des Codes zur Produktivumgebung dar. Sobald du das erste Mal zur Produktivumgebung ausgeliefert hast, werden deren Daten hier automatisch angezeigt."
msgid "The tabs below will be removed in a future version"
-msgstr ""
+msgstr "Die folgenden Tabs werden in einer zukünftigen Version entfernt werden"
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
-msgstr "Die Testphase stellt die Zeit dar, die GitLab CI benötigt um die Pipelines von zugehörigen Merge Requests abzuarbeiten. Sobald die erste Pipeline abgeschlossen ist, werden deren Daten hier automatisch angezeigt."
-
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
+msgstr "Die Testphase stellt die Zeit dar, die GitLab CI benötigt um die Pipelines von zugehörigen Merge-Requests abzuarbeiten. Sobald die erste Pipeline abgeschlossen ist, werden deren Daten hier automatisch angezeigt."
msgid "The time taken by each data entry gathered by that stage."
-msgstr "Zeit, die für das jeweilige Ereignis in der Phase ermittelt wurde."
+msgstr "Die Zeit, die jede Dateneingabe in dieser Phase benötigt."
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
-msgstr ""
+msgstr "Die Aktualisierungsaktion wird nach %{number_of_minutes} Minuten abgebrochen. Verwende für große Repositories eine Clone / Push-Kombination."
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr "Der Nutzungsbericht ist deaktiviert und kann nicht über dieses Formular konfiguriert werden."
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
-msgstr ""
+msgstr "Die Benutzerzuordnung ist ein JSON-Dokument das festlegt, wie die E-Mail-Adressen und Benutzernamen der Google Code-Benutzer(innen), die an deinem Projekt teilnehmen, in GitLab importiert werden. Du kannst dies ändern, indem du den Wert auf der rechten Seite von <code>:</code> anpasst. Stelle sicher, dass du umgebenden Anführungszeichen, andere Interpunktion sowie die E-Mail-Adresse oder den Benutzernamen auf der linken Seite erhältst."
msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
-msgstr ""
+msgstr "Die Benutzerzuordnung legt fest, wie die E-Mail-Adressen und Benutzernamen der FogBuz-Benutzer(innen), die an deinem Projekt teilnehmen, in GitLab importiert werden. Du kannst dies ändern, indem du die Tabelle unten ausfüllst."
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "Der mittlere aller erfassten Werte. Zum Beispiel ist für 3, 5, 9 der Median 5. Bei 3, 5, 7, 8 ist der Median (5+7)/2 = 6."
+msgid "There are no archived projects yet"
+msgstr "Es gibt noch keine archivierten Projekte"
+
msgid "There are no issues to show"
-msgstr ""
+msgstr "Es gibt keine Tickets die angezeigt werden können"
msgid "There are no labels yet"
-msgstr ""
+msgstr "Es gibt noch keine Labels"
msgid "There are no merge requests to show"
-msgstr ""
+msgstr "Es sind keine Merge-Requests zum Anzeigen vorhanden"
+
+msgid "There are no projects shared with this group yet"
+msgstr "Es gibt noch keine geteilten Projekte mit dieser Gruppe"
-msgid "There are problems accessing Git storage: "
-msgstr "Es gibt ein Problem beim Zugriff auf den Gitspeicher:"
+msgid "There are no staged changes"
+msgstr "Es gibt keine vorgemerkten Änderungen"
+
+msgid "There are no unstaged changes"
+msgstr "Es gibt keine nicht vorgemerkten Änderungen"
msgid "There was an error adding a todo."
-msgstr ""
+msgstr "Beim Hinzufügen eines To-dos ist ein Fehler aufgetreten."
msgid "There was an error deleting the todo."
-msgstr ""
+msgstr "Beim Löschen des To-dos ist ein Fehler aufgetreten."
msgid "There was an error loading users activity calendar."
-msgstr ""
+msgstr "Beim Laden des Benutzeraktivitäts-Kalenders ist ein Fehler aufgetreten."
msgid "There was an error saving your notification settings."
-msgstr ""
+msgstr "Beim Speichern deiner Benachrichtigungseinstellungen ist ein Fehler aufgetreten."
msgid "There was an error subscribing to this label."
-msgstr ""
+msgstr "Beim Abonnieren dieses Labels ist ein Fehler aufgetreten."
msgid "There was an error when reseting email token."
-msgstr ""
+msgstr "Beim Zurücksetzen des E-Mail-Tokens ist ein Fehler aufgetreten."
msgid "There was an error when subscribing to this label."
-msgstr ""
+msgstr "Beim Abonnieren dieses Labels ist ein Fehler aufgetreten."
msgid "There was an error when unsubscribing from this label."
-msgstr ""
+msgstr "Beim Abmelden von der Abonnierung dieses Labels ist ein Fehler aufgetreten."
msgid "They can be managed using the %{link}."
-msgstr ""
+msgstr "Können unter %{link} verwaltet werden."
msgid "Third party offers"
-msgstr ""
+msgstr "Angebote von Drittanbietern"
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
-msgstr ""
+msgstr "Diese GitLab-Instanz stellt noch keine geteilten Runner bereit. Instanz-Administrator(inn)en können geteilte Runner im Admin-Bereich registrieren."
msgid "This application was created by %{link_to_owner}."
-msgstr ""
+msgstr "Diese Anwendung wurde erstellt von %{link_to_owner}."
msgid "This application will be able to:"
-msgstr ""
+msgstr "Diese Anwendung wird in der Lage sein:"
msgid "This board's scope is reduced"
-msgstr ""
+msgstr "Der Umfang dieses Boards ist reduziert"
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
-msgstr ""
+msgstr "Dieser Branch wurde verändert, seit du begonnen hast ihn zu bearbeiten. Möchtest du einen neuen Branch anlegen?"
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
-msgstr ""
+msgid "This container registry has been scheduled for deletion."
+msgstr "Diese Container-Registry wurde zur Löschung vorgesehen."
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
-msgstr ""
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr "Dieses Datum ist nach dem Fälligkeitsdatum, daher erscheint dieses Epic nicht in der Roadmap."
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr "Dieses Datum ist vor dem Startdatum, daher erscheint dieses Epic nicht in der Roadmap."
msgid "This diff is collapsed."
-msgstr ""
+msgstr "Dieser Diff ist reduziert."
msgid "This directory"
-msgstr ""
+msgstr "Dieses Verzeichnis"
msgid "This group"
-msgstr ""
+msgstr "Diese Gruppe"
msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
-msgstr ""
+msgstr "In dieser Gruppe kannst du dich mit deinem %{group_name}-Single Sign-On-Konto anmelden. Dabei wirst du auf eine externe Anmeldeseite weitergeleitet."
msgid "This group does not provide any group Runners yet."
-msgstr ""
+msgstr "Diese Gruppe stellt noch keine Gruppenrunner zur Verfügung."
msgid "This is a confidential issue."
+msgstr "Dies ist ein vertrauliches Ticket."
+
+msgid "This is a delayed job to run in %{remainingTime}"
msgstr ""
msgid "This is the author's first Merge Request to this project."
-msgstr ""
+msgstr "Dies ist der erste Merge-Request des Autors für dieses Projekt."
msgid "This issue is confidential"
-msgstr ""
+msgstr "Dieses Ticket ist vertraulich"
msgid "This issue is confidential and locked."
-msgstr ""
+msgstr "Dieses Ticket ist vertraulich und gesperrt."
msgid "This issue is locked."
-msgstr ""
+msgstr "Dieses Ticket ist gesperrt."
msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
-msgstr ""
+msgstr "Dieser Job ist davon abhängig, dass ein(e) Benutzer(in) den Prozess auslöst. Sie werden oft zum Bereitstellen von Code in Produktionsumgebungen verwendet"
msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
-msgstr ""
+msgstr "Dieser Job hängt von Upstream-Jobs ab, die erfolgreich ausgeführt werden müssen, damit dieser Job getriggert wird"
msgid "This job does not have a trace."
-msgstr ""
+msgstr "Dieser Job hat keine Ablaufverfolgung."
msgid "This job has been canceled"
-msgstr ""
+msgstr "Dieser Job wurde abgebrochen"
msgid "This job has been skipped"
-msgstr ""
+msgstr "Dieser Job wurde übersprungen"
msgid "This job has not been triggered yet"
-msgstr ""
+msgstr "Dieser Job wurde noch nicht getriggert"
msgid "This job has not started yet"
-msgstr ""
+msgstr "Dieser Job hat noch nicht begonnen"
msgid "This job is an out-of-date deployment to %{environmentLink}."
-msgstr ""
+msgstr "Dieser Job ist eine veraltet Bereitstellung für %{environmentLink}."
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
+msgstr "Dieser Job ist eine veraltete Bereitstellung für %{environmentLink}. Zeige die neueste Bereitstellung an %{deploymentLink}."
+
+msgid "This job is archived. Only the complete pipeline can be retried."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
-msgstr ""
+msgstr "Dieser Job erstellt eine Bereitstellung für %{environmentLink}."
msgid "This job is in pending state and is waiting to be picked by a runner"
-msgstr ""
+msgstr "Dieser Job befindet sich im Status \"ausstehend\" und wartet darauf, durch einen Runner ausgewählt zu werden"
msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
-msgstr ""
+msgstr "Dieser Job ist blockiert, da du keine aktiven Runner online hast, die einem dieser Tags zugeordnet sind:"
msgid "This job is stuck, because you don't have any active runners that can run this job."
-msgstr ""
+msgstr "Dieser Job hängt, da du keine aktiven Runner hast, die diesen Job ausführen können."
msgid "This job is the most recent deployment to %{link}."
-msgstr ""
+msgstr "Dieser Job ist die neueste Bereitstellung für %{link}."
msgid "This job requires a manual action"
+msgstr "Dieser Job erfordert eine manuelle Aktion"
+
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
-msgstr "Dies bedeutet, dass Du keinen Code übertragen kannst, bevor Du kein leeres Repositorium erstellt oder ein Existierendes importiert hast."
+msgstr "Dies bedeutet, dass du keinen Code pushen kannst, bevor du kein leeres Repository erstellt oder ein existierendes importiert hast."
msgid "This merge request is locked."
-msgstr ""
+msgstr "Dieser Merge-Request ist gesperrt."
msgid "This option is disabled as you don't have write permissions for the current branch"
-msgstr ""
+msgstr "Diese Option wurde deaktiviert, da du keine Schreibrechte für diesen Branch hast"
msgid "This option is disabled while you still have unstaged changes"
-msgstr ""
+msgstr "Diese Option ist deaktiviert, solange du noch nicht vorgemerkte Änderungen hast"
msgid "This page is unavailable because you are not allowed to read information across multiple projects."
-msgstr ""
+msgstr "Diese Seite ist nicht verfügbar, da du nicht Informationen über mehrere Projekte hinweg lesen darfst."
msgid "This page will be removed in a future release."
-msgstr ""
+msgstr "Diese Seite wird in einer zukünftigen Version entfernt."
msgid "This project"
-msgstr ""
+msgstr "Dieses Projekt"
msgid "This project does not belong to a group and can therefore not make use of group Runners."
+msgstr "Dieses Projekt gehört keiner Gruppe an und kann daher keine Gruppenrunner verwenden."
+
+msgid "This project does not have a wiki homepage yet"
msgstr ""
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
+msgstr "Für dieses Projekt ist keine Abrechnung aktiviert. Um ein Cluster zu erstellen, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">aktiviere die Abrechnung<i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> und versuche es erneut."
msgid "This repository"
-msgstr ""
+msgstr "Dieses Repository"
msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr "Dieser Runner wird nur Pipelines von geschützen Branches ausführen"
+
+msgid "This setting can be overridden in each project."
msgstr ""
-msgid "This source diff could not be displayed because it is too large."
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
msgstr ""
+msgid "This source diff could not be displayed because it is too large."
+msgstr "Dieser Quelltext-Diff konnte nicht angezeigt werden, da er zu groß ist."
+
msgid "This timeout will take precedence when lower than Project-defined timeout"
-msgstr ""
+msgstr "Dieser Timeout wird den projektspezifischen Timeout überschreiben, wenn er niedriger ist"
msgid "This user has no identities"
-msgstr ""
+msgstr "Diese(r) Benutzer(in) hat keine Identitäten"
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
-msgstr ""
+msgstr "Diese(r) Benutzer(in) wird der/die Autor(in) aller Ereignisse im Aktivitätsfeed sein, die die Folge eines Updates, wie die Erstellung neuer Branches oder das Pushen neuer Commits zu existierenden Branches, sind."
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
-msgstr ""
+msgstr "Diese(r) Benutzer(in) wird der/die Autor(in) aller Ereignisse im Aktivitätsfeed sein, die die Folge eines Updates, wie die Erstellung neuer Branches oder das Pushen neuer Commits zu existierenden Branches, sind. Bei der Erstellung oder der Neuzuweisung kannst du nur dich selbst als Mirror-Benutzer(in) zuweisen."
msgid "This will delete the custom metric, Are you sure?"
-msgstr ""
+msgstr "Dadurch wird die benutzerdefinierte Metrik gelöscht. Bist du sicher?"
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
-msgstr ""
+msgstr "Diese E-Mails werden automatisch zu hier gelisteten Tickets (wobei die Kommentare zur E-Mail-Konversation werden)."
msgid "Time before an issue gets scheduled"
msgstr "Zeit bis ein Ticket geplant wird"
@@ -7336,32 +8273,38 @@ msgstr "Zeit bis ein Ticket geplant wird"
msgid "Time before an issue starts implementation"
msgstr "Zeit bis die Implementierung für ein Ticket beginnt"
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
-msgstr "Zeit zwischen einem Merge Request und dessen Umsetzung / Schließung"
+msgstr "Zeit zwischen Anlegen und Mergen/Schließen eines Merge-Requests"
-msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgid "Time estimate"
msgstr ""
+msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgstr "Zeit in Sekunden die GitLab auf die Antwort des externen Dienstes warten wird. Wenn der Dienst nicht rechtzeitig antwortet, wird der Zugriff verweigert."
+
msgid "Time remaining"
-msgstr ""
+msgstr "Verbleibende Zeit"
msgid "Time spent"
-msgstr ""
+msgstr "Benötigte Zeit"
msgid "Time tracking"
-msgstr ""
+msgstr "Zeiterfassung"
msgid "Time until first merge request"
-msgstr "Zeit bis zum ersten Merge Request"
+msgstr "Zeit bis zum ersten Merge-Request"
msgid "TimeTrackingEstimated|Est"
-msgstr ""
+msgstr "Geschätzt"
msgid "TimeTracking|Estimated:"
-msgstr ""
+msgstr "Geschätzt:"
msgid "TimeTracking|Spent"
-msgstr ""
+msgstr "Verbracht"
msgid "Timeago|%s days ago"
msgstr "vor %s Tagen"
@@ -7370,79 +8313,79 @@ msgid "Timeago|%s days remaining"
msgstr "%s Tage verbleibend"
msgid "Timeago|%s hours ago"
-msgstr ""
+msgstr "vor %s Stunden"
msgid "Timeago|%s hours remaining"
msgstr "%s Stunden verbleibend"
msgid "Timeago|%s minutes ago"
-msgstr ""
+msgstr "vor %s Minuten "
msgid "Timeago|%s minutes remaining"
msgstr "%s Minuten verbleibend"
msgid "Timeago|%s months ago"
-msgstr ""
+msgstr "vor %s Monaten"
msgid "Timeago|%s months remaining"
msgstr "%s Monate verbleibend"
msgid "Timeago|%s seconds ago"
-msgstr ""
+msgstr "vor %s Sekunden"
msgid "Timeago|%s seconds remaining"
msgstr "%s Sekunden verbleibend"
msgid "Timeago|%s weeks ago"
-msgstr ""
+msgstr "vor %s Wochen"
msgid "Timeago|%s weeks remaining"
msgstr "%s Wochen verbleibend"
msgid "Timeago|%s years ago"
-msgstr ""
+msgstr "vor %s Jahren"
msgid "Timeago|%s years remaining"
msgstr "%s Jahre verbleibend"
msgid "Timeago|1 day ago"
-msgstr ""
+msgstr "vor 1 Tag"
msgid "Timeago|1 day remaining"
msgstr "1 Tag verbleibend"
msgid "Timeago|1 hour ago"
-msgstr ""
+msgstr "vor 1 Stunde"
msgid "Timeago|1 hour remaining"
msgstr "1 Stunde verbleibend"
msgid "Timeago|1 minute ago"
-msgstr ""
+msgstr "vor 1 Minute"
msgid "Timeago|1 minute remaining"
msgstr "1 Minute verbleibend"
msgid "Timeago|1 month ago"
-msgstr ""
+msgstr "vor 1 Monat"
msgid "Timeago|1 month remaining"
msgstr "1 Monat verbleibend"
msgid "Timeago|1 week ago"
-msgstr ""
+msgstr "vor 1 Woche"
msgid "Timeago|1 week remaining"
msgstr "1 Woche verbleibend"
msgid "Timeago|1 year ago"
-msgstr ""
+msgstr "vor 1 Jahr"
msgid "Timeago|1 year remaining"
msgstr "1 Jahr verbleibend"
msgid "Timeago|Past due"
-msgstr "Fällig"
+msgstr "Überfällig"
msgid "Timeago|in %s days"
msgstr "in %s Tagen"
@@ -7484,13 +8427,13 @@ msgid "Timeago|in 1 year"
msgstr "in 1 Jahr"
msgid "Timeago|just now"
-msgstr ""
+msgstr "vor kurzem"
msgid "Timeago|right now"
-msgstr ""
+msgstr "gerade jetzt"
msgid "Timeout"
-msgstr ""
+msgstr "Zeitüberschreitung"
msgid "Time|hr"
msgid_plural "Time|hrs"
@@ -7506,100 +8449,127 @@ msgid "Time|s"
msgstr "Sek."
msgid "Tip:"
-msgstr ""
+msgstr "Tipp:"
msgid "Title"
-msgstr ""
+msgstr "Titel"
msgid "To GitLab"
-msgstr ""
+msgstr "Zu GitLab"
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
-msgstr ""
+msgstr "Um einen SSH-Schlüssel hinzuzufügen, musst du %{generate_link_start}einen generieren%{link_end} oder einen %{existing_link_start}vorhandenen Schlüssel%{link_end} verwenden."
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
-msgstr ""
+msgstr "Um GitHub-Repositories zu verbinden kannst du einen %{personal_access_token_link} verwenden. Wenn du deinen persönlichen Access-Token erzeugst, musst du den Gültigkeitsbereich <code>repo</code> auswählen, damit wir eine Liste deiner öffentlichen und privaten Repositories anzeigen können, die für die Verbindung verfügbar sind."
msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
-msgstr ""
+msgstr "Um GitHub-Repositories zu verbinden, musst du GitLab zunächst erlauben, auf die Liste deiner GitHub-Repositories zuzugreifen:"
msgid "To connect an SVN repository, check out %{svn_link}."
-msgstr ""
+msgstr "Um ein SVN-Repository zu verbinden, lies %{svn_link}."
msgid "To define internal users, first enable new users set to external"
-msgstr ""
+msgstr "Um interne Benutzer(innen) zu definieren, musst du zunächst externe Benutzer(innen) aktivieren"
+
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr "Um es zu aktivieren und Benutzer-Kohorten zu sehen, gehe zu den %{application_settings_link_start}Anwendungseinstellungen%{application_settings_link_end}."
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr "Gib zunächst deine FogBuz-URL und Anmeldeinformationen unten ein. In den nächsten Schritten kannst du Benutzer(innen) zuordnen und die Projekte für den Import auswählen."
+
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
msgstr ""
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
-msgstr ""
+msgstr "Gib zunächst deine Gitea-Host-URL und einen %{link_to_personal_token} ein."
+
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr "Zur Verbesserung von GitLab und seiner Benutzererfahrung sammelt GitLab regelmäßig Nutzungsinformationen."
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr "Zur Verbesserung von GitLab würden wir gerne regelmäßig Nutzungsinformationen sammeln. Dies kann jederzeit in den %{settings_link_start}Einstellungen%{link_end} geändert werden. %{info_link_start}Weitere Informationen%{link_end}"
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
-msgstr ""
+msgstr "Um GitHub-Repositories zu importieren kannst du einen %{personal_access_token_link} verwenden. Wenn du deinen persönlichen Access-Token erzeugst, musst du den Gültigkeitsbereich <code>repo</code> auswählen, damit wir eine Liste deiner öffentlichen und privaten Repositories anzeigen können, die für den Import verfügbar sind."
msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
-msgstr ""
+msgstr "Um GitHub-Repositories zu importieren, musst du GitLab zunächst erlauben, auf die Liste deiner GitHub-Repositories zuzugreifen:"
msgid "To import an SVN repository, check out %{svn_link}."
-msgstr ""
+msgstr "Um ein SVN-Repository zu importieren, schaue dir %{svn_link} an."
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
-msgstr ""
+msgstr "Um ein komplettes GitLab-Projekt von einer GitLab-Installation zu einer anderen umzuziehen oder zu kopieren, navigiere zur Einstellungsseite des Originalprojektes, erzeuge eine Export-Datei und lade sie hier hoch."
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
+msgstr "Um die CI/CD-Funktionen nur für ein externes Repository zu verwenden, wähle <strong>CI/CD für externes Repo</strong> aus."
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
msgstr ""
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
-msgstr ""
+msgstr "So richtest du die SAML-Authentifizierung für deine Gruppe über einen Identitätsanbieter wie Azure, Okta, Onelogin, Ping Identity oder deinen benutzerdefinierten SAML 2.0-Anbieter ein:"
msgid "To start serving your jobs you can add Runners to your group"
-msgstr ""
+msgstr "Um deine Jobs zur Verfügung zu stellen, kannst du Runner zu deiner Gruppe hinzufügen"
msgid "To this GitLab instance"
-msgstr ""
+msgstr "Zu dieser GitLab-Instanz"
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
-msgstr ""
+msgstr "Um deine GitLab CI-Konfigurationen zu validieren, gehe in deinem Projekt zu \"CI/CD → Pipelines\" und klicke auf die Schaltfläche \"CI Lint\"."
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
-msgstr ""
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr "Füge ein Start- oder Fälligkeitsdatum zu einem deiner Epics in dieser Gruppe oder ihrer Untergruppen hinzu, um die Roadmap anzuzeigen. In der Monatsansicht werden nur Epics des letzten Monats, des aktuellen Monats und der nächsten 5 Monate angezeigt."
msgid "To widen your search, change or remove filters."
-msgstr ""
+msgstr "Um deine Suche zu erweitern, verändere oder entferne Filter."
+
+msgid "Today"
+msgstr "Heute"
msgid "Todo"
-msgstr ""
+msgstr "To-do"
msgid "Todos"
-msgstr ""
+msgstr "To-dos"
msgid "Toggle Sidebar"
-msgstr ""
+msgstr "Seitenleiste ein-/ausblenden"
+
+msgid "Toggle commit description"
+msgstr "Beschreibung des Commits ein-/ausklappen"
msgid "Toggle discussion"
-msgstr ""
+msgstr "Diskussion ein-/ausblenden"
+
+msgid "Toggle file browser"
+msgstr "Dateibrowser umschalten"
msgid "Toggle navigation"
-msgstr ""
+msgstr "Navigation umschalten"
msgid "Toggle sidebar"
-msgstr ""
+msgstr "Seitenleiste ein-/ausblenden"
msgid "ToggleButton|Toggle Status: OFF"
-msgstr ""
+msgstr "Toggle Status: OFF"
msgid "ToggleButton|Toggle Status: ON"
-msgstr ""
+msgstr "Toggle Status: ON"
msgid "Token"
-msgstr ""
+msgstr "Token"
+
+msgid "Tomorrow"
+msgstr "Morgen"
msgid "Too many changes to show."
-msgstr ""
+msgstr "Zu viele Änderungen um sie anzuzeigen."
msgid "Total Contributions"
-msgstr ""
+msgstr "Gesamte Beiträge"
msgid "Total Time"
msgstr "Gesamtzeit"
@@ -7608,253 +8578,346 @@ msgid "Total test time for all commits/merges"
msgstr "Gesamte Testzeit für alle Commits/Merges"
msgid "Total: %{total}"
+msgstr "Gesamt: %{total}"
+
+msgid "Tracing"
msgstr ""
msgid "Track activity with Contribution Analytics."
-msgstr ""
+msgstr "Verfolge Aktivitäten mit der Beitragsanalyse."
msgid "Track groups of issues that share a theme, across projects and milestones"
-msgstr ""
+msgstr "Verfolge Gruppen von Tickets, die ein Thema teilen, über Projekte und Meilensteine hinweg"
msgid "Track time with quick actions"
-msgstr ""
+msgstr "Verfolge die Zeit mit Kurzbefehlen"
+
+msgid "Tree view"
+msgstr "Baumstrukturansicht"
msgid "Trending"
-msgstr ""
+msgstr "Beliebt"
msgid "Trigger"
-msgstr ""
+msgstr "Trigger"
msgid "Trigger pipelines for mirror updates"
-msgstr ""
+msgstr "Pipelines für Mirror-Updates auslösen"
msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
-msgstr ""
+msgstr "Triggere Pipelines, wenn Branches oder Tags aus dem Upstream-Repository aktualisiert werden. Abhängig von der Aktivität des Upstream-Repositorys kann dies die Auslastung deiner CI-Runner erheblich erhöhen. Aktiviere diese Option nur, wenn du weißt, dass sie mit der Last umgehen können."
msgid "Trigger this manual action"
-msgstr ""
+msgstr "Löse diese manuelle Aktion aus"
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgstr "Trigger können erzwingen, dass einen bestimmten Branch oder Tag mit einem API-Aufruf neu erstellt wird. Diese Token nehmen die Identität ihres/ihrer verbundenen Benutzers/Benutzerin an, einschließlich ihres Zugriffs auf Projekte und ihrer Projektberechtigungen."
+
+msgid "Troubleshoot and monitor your application with tracing"
msgstr ""
msgid "Try again"
+msgstr "Wiederholen"
+
+msgid "Try all GitLab has to offer for 30 days."
msgstr ""
msgid "Turn on Service Desk"
-msgstr ""
+msgstr "Aktiviere den Service-Desk"
msgid "Twitter"
+msgstr "Twitter"
+
+msgid "Two-factor authentication"
msgstr ""
msgid "Type"
-msgstr ""
+msgstr "Typ"
msgid "Unable to load the diff. %{button_try_again}"
+msgstr "Der Diff konnten nicht geladen werden. %{button_try_again}"
+
+msgid "Unable to save your changes"
msgstr ""
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
-msgstr ""
+msgstr "Aufgrund von \"%{reason}\" konntest du dich nicht mit SAML anmelden"
+
+msgid "Unable to update this epic at this time."
+msgstr "Dieses Epic kann gerade nicht aktualisiert werden."
+
+msgid "Undo"
+msgstr "Rückgängig machen"
msgid "Unknown"
-msgstr ""
+msgstr "Unbekannt"
msgid "Unlock"
-msgstr ""
+msgstr "Entsperren"
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
-msgstr ""
+msgstr "Dieses %{issuableDisplayName} entsperren? <strong>Jeder</strong> wird in der Lage sein zu kommentieren."
msgid "Unlocked"
-msgstr ""
+msgstr "Entsperrt"
msgid "Unresolve discussion"
+msgstr "Diskussion wieder starten"
+
+msgid "Unschedule job"
msgstr ""
+msgid "Unstage"
+msgstr "Nicht mehr vormerken"
+
msgid "Unstage all changes"
-msgstr ""
+msgstr "Alle Änderungen nicht mehr vormerken"
msgid "Unstage changes"
-msgstr ""
+msgstr "Nicht vorgemerkte Änderungen"
msgid "Unstaged"
-msgstr ""
+msgstr "Nicht vorgemerkt"
msgid "Unstaged %{type}"
-msgstr ""
+msgstr "Nicht vorgemerkt %{type}"
msgid "Unstaged and staged %{type}"
-msgstr ""
+msgstr "Nicht vorgemerkt und vorgemerkt %{type}"
msgid "Unstar"
msgstr "Entfavorisieren"
msgid "Unsubscribe"
-msgstr ""
+msgstr "Abonnement entfernen"
msgid "Unsubscribe at group level"
-msgstr ""
+msgstr "Abmeldung auf Gruppenebene"
msgid "Unsubscribe at project level"
-msgstr ""
+msgstr "Abmeldung auf Projektebene"
msgid "Unverified"
-msgstr ""
+msgstr "Nicht bestätigt"
msgid "Up to date"
+msgstr "Aktuell"
+
+msgid "Upcoming"
msgstr ""
msgid "Update"
-msgstr ""
+msgstr "Aktualisieren"
msgid "Update now"
-msgstr ""
+msgstr "Jetzt updaten"
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
-msgstr ""
+msgstr "Aktualisiere"
msgid "Upgrade your plan to activate Advanced Global Search."
-msgstr ""
+msgstr "Aktualisiere deinen Tarif, um die erweiterte globale Suche zu aktivieren."
msgid "Upgrade your plan to activate Contribution Analytics."
-msgstr ""
+msgstr "Aktualisiere deinen Tarif, um Beitragsanalysen zu aktivieren."
msgid "Upgrade your plan to activate Group Webhooks."
-msgstr ""
+msgstr "Aktualisiere deinen Tarif, um Gruppen-Webhooks zu aktivieren."
msgid "Upgrade your plan to activate Issue weight."
-msgstr ""
+msgstr "Aktualisiere deinen Tarif, um die Ticket-Gewichtung zu aktivieren."
msgid "Upgrade your plan to improve Issue boards."
-msgstr ""
+msgstr "Upgrade deinen Tarif um die Ticketboards zu verbessern."
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
-msgstr ""
+msgstr "Lade <code>GoogleCodeProjectHosting.json</code> hier hoch:"
msgid "Upload New File"
-msgstr "Eine Neue Datei hochladen"
+msgstr "Neue Datei hochladen"
msgid "Upload file"
-msgstr "Eine Datei hochladen"
-
-msgid "Upload new avatar"
-msgstr ""
+msgstr "Datei hochladen"
msgid "UploadLink|click to upload"
msgstr "Zum Upload klicken"
msgid "Upvotes"
-msgstr ""
+msgstr "Upvotes"
+
+msgid "Usage ping is not enabled"
+msgstr "Der Nutzungsbericht ist nicht aktiviert"
msgid "Usage statistics"
-msgstr ""
+msgstr "Nutzungsstatistiken"
msgid "Use <code>%{native_redirect_uri}</code> for local tests"
-msgstr ""
+msgstr "Verwende <code>%{native_redirect_uri}</code> für lokale Tests"
msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
-msgstr ""
+msgstr "Nutze den Service-Desk, um dich direkt in GitLab via E-Mail mit deinen Benutzer(inne)n zu verbinden (z. B. um Kunden-Support anzubieten)"
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
-msgstr ""
+msgstr "Verwende Gruppenmeilensteine, um Tickets aus mehreren Projekten im selben Meilenstein zu verwalten."
msgid "Use one line per URI"
-msgstr ""
+msgstr "Verwende eine Zeile pro URI"
msgid "Use template"
-msgstr ""
+msgstr "Template verwenden"
msgid "Use the following registration token during setup:"
msgstr "Benutze den folgenden Registrierungstoken während des Setups:"
msgid "Use your global notification setting"
-msgstr "Benutze Deine globalen Benachrichtigungseinstellungen"
+msgstr "Benutze deine globalen Benachrichtigungseinstellungen"
msgid "Used by members to sign in to your group in GitLab"
-msgstr ""
+msgstr "Wird von Mitgliedern verwendet, um sich in GitLab in deiner Gruppe anzumelden"
+
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr "Benutzer-Kohorten sind nur sichtbar, wenn der %{usage_ping_link_start}Nutzungsbericht%{usage_ping_link_end} aktiviert ist."
msgid "User Settings"
-msgstr ""
+msgstr "Benutzereinstellungen"
msgid "User and IP Rate Limits"
-msgstr ""
+msgstr "Benutzer- und IP-Beschränkungen"
msgid "User map"
+msgstr "Benutzerzuordnung"
+
+msgid "UserProfile|Activity"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Already reported for abuse"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|Contributed projects"
msgstr ""
-msgid "Variables"
+msgid "UserProfile|Edit profile"
msgstr ""
-msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgid "UserProfile|Groups"
msgstr ""
-msgid "Various container registry settings."
+msgid "UserProfile|Most Recent Activity"
msgstr ""
-msgid "Various email settings."
+msgid "UserProfile|Overview"
msgstr ""
-msgid "Various settings that affect GitLab performance."
+msgid "UserProfile|Personal projects"
msgstr ""
-msgid "Verification information"
+msgid "UserProfile|Recent contributions"
msgstr ""
-msgid "Verified"
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
msgstr ""
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
+msgstr "Benutzer(innen)"
+
+msgid "Variables"
+msgstr "Variablen"
+
+msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgstr "Variablen werden über den Runner auf Umgebungen angewendet. Sie können geschützt werden, indem sie nur für geschützten Branches oder Tags sichtbar gemacht werden. Du kannst Variablen für Passwörter, geheime Schlüssel oder was immer du möchtest verwenden."
+
+msgid "Various container registry settings."
+msgstr "Verschiedene Einstellungen für die Container-Registry."
+
+msgid "Various email settings."
+msgstr "Verschiedene E-Mail-Einstellungen."
+
+msgid "Various settings that affect GitLab performance."
+msgstr "Verschiedene Einstellungen, die sich auf die GitLab-Leistung auswirken."
+
+msgid "Verification information"
+msgstr "Bestätigungsinformationen"
+
+msgid "Verified"
+msgstr "Bestätigt"
+
msgid "Version"
+msgstr "Version"
+
+msgid "View %{alerts}"
msgstr ""
-msgid "View epics list"
+msgid "View app"
msgstr ""
-msgid "View file @ "
+msgid "View documentation"
msgstr ""
+msgid "View epics list"
+msgstr "Epic-Liste anzeigen"
+
+msgid "View file @ "
+msgstr "Zeige Datei @ "
+
msgid "View group labels"
-msgstr ""
+msgstr "Gruppenlabels ansehen"
msgid "View issue"
-msgstr ""
+msgstr "Ticket anzeigen"
msgid "View it on GitLab"
-msgstr ""
+msgstr "Sieh es auf GitLab an"
msgid "View jobs"
-msgstr ""
+msgstr "Jobs ansehen"
msgid "View labels"
-msgstr ""
+msgstr "Labels anzeigen"
msgid "View log"
-msgstr ""
+msgstr "Protokoll ansehen"
msgid "View open merge request"
-msgstr "Zeige offene Merge Requests."
+msgstr "Zeige offene Merge-Requests"
msgid "View project labels"
-msgstr ""
+msgstr "Projektlabels ansehen"
msgid "View replaced file @ "
+msgstr "Zeige ersetzte Datei @ "
+
+msgid "View the documentation"
msgstr ""
msgid "Visibility and access controls"
-msgstr ""
+msgstr "Sichtbarkeit und Zugriffskontrollen"
+
+msgid "Visibility level"
+msgstr "Sichtbarkeitsstufe"
msgid "Visibility level:"
-msgstr ""
+msgstr "Sichtbarkeitsstufe:"
msgid "Visibility:"
-msgstr ""
+msgstr "Sichtbarkeit:"
msgid "VisibilityLevel|Internal"
msgstr "Intern"
@@ -7868,359 +8931,404 @@ msgstr "Öffentlich"
msgid "VisibilityLevel|Unknown"
msgstr "Unbekannt"
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr "Schweregrad"
+
+msgid "Vulnerability|Solution"
+msgstr "Lösung"
+
msgid "Want to see the data? Please ask an administrator for access."
-msgstr "Du möchtest diese Daten sehen? Bitte frage einen Administrator nach dem Zugang."
+msgstr "Du möchtest die Daten sehen? Bitte frage eine(n) Administrator(in) nach dem Zugang."
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
-msgstr ""
+msgstr "Wir haben potenziellen Spam in %{humanized_resource_name} gefunden. Bitte löse den reCAPTCHA um fortzufahren."
msgid "We don't have enough data to show this stage."
msgstr "Es liegen nicht genügend Daten vor, um diese Phase anzuzeigen."
msgid "We want to be sure it is you, please confirm you are not a robot."
-msgstr ""
+msgstr "Wir wollen sicher gehen, dass du es bist. Bitte bestätige, dass du kein Roboter bist."
msgid "Web IDE"
-msgstr ""
+msgstr "Web IDE"
msgid "Web terminal"
-msgstr ""
+msgstr "Web-Terminal"
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
-msgstr ""
+msgstr "Webhooks ermöglichen es dir eine URL aufzurufen, wenn z. B. neuer Code gepusht oder ein neues Ticket erstellt wird. Du kannst Webhooks so konfigurieren, dass sie auf bestimmte Ereignisse wie Pushes, Tickets oder Merge-Requests reagieren. Gruppen-Webhooks werden auf alle Projekte in einer Gruppe angewendet, so dass du die Webhook-Funktionalität in der gesamten Gruppe standardisieren kannst."
msgid "Weeks"
-msgstr ""
+msgstr "Wochen"
msgid "Weight"
-msgstr ""
+msgstr "Gewichtung"
msgid "Weight %{weight}"
-msgstr ""
+msgstr "Gewichtung %{weight}"
msgid "When a runner is locked, it cannot be assigned to other projects"
-msgstr ""
+msgstr "Wenn ein Runner gesperrt ist, kann er keinem anderen Projekt zugewiesen werden"
msgid "When enabled, users cannot use GitLab until the terms have been accepted."
-msgstr ""
+msgstr "Wenn diese Option aktiviert ist, können Benutzer(innen) GitLab nicht verwenden, bis die Bedingungen akzeptiert wurden."
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
-msgstr ""
+msgstr "Wenn die URL leer gelassen wird, können Klassifizierungslabels weiterhin angegeben werden ohne projektübergreifende Eigenschaften auszuschalten oder einen externen Autorisierungscheck durchzuführen."
+
+msgid "Who can see this group?"
+msgstr "Wer kann diese Gruppe sehen?"
+
+msgid "Who will be able to see this group?"
+msgstr "Wer wird in der Lage sein diese Gruppe zu sehen?"
msgid "Wiki"
msgstr "Wiki"
msgid "WikiClone|Clone your wiki"
-msgstr ""
+msgstr "Wiki klonen"
msgid "WikiClone|Git Access"
-msgstr ""
+msgstr "Git-Zugang"
msgid "WikiClone|Install Gollum"
-msgstr ""
+msgstr "Gollum installieren"
msgid "WikiClone|It is recommended to install %{markdown} so that GFM features render locally:"
-msgstr ""
+msgstr "Es wird empfohlen, %{markdown} zu installieren, damit die GFM-Funktionen lokal gerendert werden:"
msgid "WikiClone|Start Gollum and edit locally"
-msgstr ""
+msgstr "Gollum starten und lokal bearbeiten"
msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
-msgstr ""
+msgstr "Tipp: Du kannst diese Seite verschieben, indem du den Pfad zum Beginn des Titels hinzufügst."
msgid "WikiEdit|There is already a page with the same title in that path."
-msgstr ""
+msgstr "Es gibt bereits eine Seite mit demselben Titel in diesem Pfad."
msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
-msgstr ""
+msgstr "Schlage eine Verbesserung des Wikis vor"
msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
-msgstr ""
+msgstr "Du musst Projekt-Mitglied sein um Wiki-Seiten hinzufügen zu können. Hast du Verbesserungsvorschläge, wie du das Wiki für dieses Projekt verbessern kannst, dann öffne ein Thema in der %{issues_link}."
msgid "WikiEmptyIssueMessage|issue tracker"
-msgstr ""
+msgstr "Ticketsystem"
msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
-msgstr ""
+msgstr "In einem Wiki können alle Details zu deinem Projekt gespeichert werden. Dies kann z. B. beinhalten, warum du es erstellt hast, seine Grundlagen, wie das Projekt verwendet werden kann und so weiter."
msgid "WikiEmpty|Create your first page"
-msgstr ""
+msgstr "Erstelle deine erste Seite"
msgid "WikiEmpty|Suggest wiki improvement"
-msgstr ""
+msgstr "Schlage eine Verbesserung des Wikis vor"
msgid "WikiEmpty|The wiki lets you write documentation for your project"
-msgstr ""
+msgstr "Mit dem Wiki kannst du eine Dokumentation für dein Projekt schreiben"
msgid "WikiEmpty|This project has no wiki pages"
-msgstr ""
+msgstr "Dieses Projekt hat keine Wiki-Seiten"
msgid "WikiEmpty|You must be a project member in order to add wiki pages."
-msgstr ""
+msgstr "Du musst ein Projektmitglied sein, um Wiki-Seiten hinzufügen zu können."
msgid "WikiHistoricalPage|This is an old version of this page."
-msgstr ""
+msgstr "Dies ist eine alte Version dieser Seite."
msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
-msgstr ""
+msgstr "Du kannst den %{most_recent_link} ansehen oder den %{history_link} durchsuchen."
msgid "WikiHistoricalPage|history"
-msgstr ""
+msgstr "Verlauf"
msgid "WikiHistoricalPage|most recent version"
-msgstr ""
+msgstr "neueste Version"
msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
-msgstr ""
+msgstr "Weitere Beispiele sind in der %{docs_link}"
msgid "WikiMarkdownDocs|documentation"
-msgstr ""
+msgstr "Dokumentation"
msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
-msgstr ""
+msgstr "Um zu einer (neuen) Seite zu verknüpfen, gib einfach %{link_example} ein"
msgid "WikiNewPagePlaceholder|how-to-setup"
-msgstr ""
+msgstr "Anleitung zum Einrichten"
msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
-msgstr ""
+msgstr "Hinweis: Du kannst den vollständigen Pfad für die neue Datei angeben. Fehlende Verzeichnisse werden automatisch erstellt."
msgid "WikiNewPageTitle|New Wiki Page"
-msgstr ""
+msgstr "Neue Wiki-Seite"
msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
-msgstr ""
+msgstr "Bist du sicher, dass du diese Seite löschen möchtest?"
msgid "WikiPageConfirmDelete|Delete page"
-msgstr ""
+msgstr "Seite löschen"
msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
-msgstr ""
+msgstr "Seite %{pageTitle} löschen?"
msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs."
-msgstr ""
+msgstr "Jemand hat die Seite zur selben Zeit wie du bearbeitet. Bitte überprüfe %{page_link} und stelle sicher, dass deine Änderungen nicht unbeabsichtigt deren Änderungen entfernen."
msgid "WikiPageConflictMessage|the page"
-msgstr ""
+msgstr "die Seite"
msgid "WikiPageCreate|Create %{page_title}"
-msgstr ""
+msgstr "%{page_title} erstellen"
msgid "WikiPageEdit|Update %{page_title}"
-msgstr ""
+msgstr "%{page_title} aktualisieren"
msgid "WikiPage|Page slug"
-msgstr ""
+msgstr "Seiten-Slug"
msgid "WikiPage|Write your content or drag files here…"
-msgstr ""
+msgstr "Schreibe deinen Inhalt oder ziehe hier Dateien hinein…"
msgid "Wiki|Create Page"
-msgstr ""
+msgstr "Seite erstellen"
msgid "Wiki|Create page"
-msgstr ""
+msgstr "Seite erstellen"
msgid "Wiki|Edit Page"
-msgstr ""
+msgstr "Seite bearbeiten"
msgid "Wiki|More Pages"
-msgstr ""
+msgstr "Weitere Seiten"
msgid "Wiki|New page"
-msgstr ""
+msgstr "Neue Seite"
msgid "Wiki|Page history"
-msgstr ""
+msgstr "Seitenverlauf"
msgid "Wiki|Page version"
-msgstr ""
+msgstr "Seitenversion"
msgid "Wiki|Pages"
-msgstr ""
+msgstr "Seiten"
msgid "Wiki|Wiki Pages"
-msgstr ""
+msgstr "Wiki-Seiten"
msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
-msgstr ""
+msgstr "Mit der Beitragsanalyse hast du einen Überblick über die Aktivitäten von Tickets, Merge-Requests und Push-Events deiner Organisation und seiner Mitglieder."
msgid "Withdraw Access Request"
msgstr "Zugriffsanfrage widerrufen"
msgid "Yes"
-msgstr ""
+msgstr "Ja"
msgid "Yes, add it"
-msgstr ""
+msgstr "Ja, füg' es hinzu"
msgid "Yes, let me map Google Code users to full names or GitLab users."
-msgstr ""
+msgstr "Ja, lass mich Google Code-Benutzer(innen) vollständigen Namen oder GitLab-Benutzer(innen) zuordnen."
+
+msgid "Yesterday"
+msgstr "Gestern"
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
-msgstr ""
+msgstr "Du bist Administrator(in). Wenn du <strong>%{client_name}</strong> Zugriff gewährst, wird es auch als Administrator mit GitLab interagieren können. Mit Vorsicht fortfahren."
msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr "Du bist dabei %{group_name} zu entfernen. Entfernte Gruppen können NICHT wiederhergestellt werden! Bist Du dir WIRKLICH sicher?"
+msgstr "Du bist dabei %{group_name} zu entfernen. Entfernte Gruppen können NICHT wiederhergestellt werden! Bist du dir WIRKLICH sicher?"
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "Du bist dabei %{project_full_name} zu entfernen. Entfernte Projekte können NICHT wiederhergestellt werden! Bist Du dir WIRKLICH sicher?"
msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
-msgstr "Du bist dabei, die Beziehung des Ablegers zum Ursprungsprojekt %{forked_from_project}, zu entfernen. Bist Du dir WIRKLICH sicher?"
+msgstr "Du bist dabei, die Beziehung des Forks zum Ursprungsprojekt %{forked_from_project}, zu entfernen. Bist du dir WIRKLICH sicher?"
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "Du bist dabei %{project_full_name} einem/einer andere(n) Besitzer(in) zu übergeben. Bist du dir WIRKLICH sicher?"
msgid "You are on a read-only GitLab instance."
-msgstr ""
-
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
+msgstr "Du bist auf einer GitLab-Instanz, die nur Lesezugriff erlaubt."
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
-msgstr ""
+msgstr "Du kannst stattdessen %{linkStart}den Blob anzeigen%{linkEnd}."
msgid "You can also create a project from the command line."
-msgstr ""
+msgstr "Du kannst ein Projekt auch über die Kommandozeile erstellen."
msgid "You can also star a label to make it a priority label."
-msgstr ""
-
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
+msgstr "Du kannst auch ein Label markieren, um es zu einem Prioritätslabel zu machen."
msgid "You can easily contribute to them by requesting to join these groups."
-msgstr ""
+msgstr "Du kannst einfach dazu beitragen, indem du um Beitritt zu dieser Gruppen bittest."
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
+msgstr "Du kannst ganz einfach einen Runner auf einem Kubernetes-Cluster installieren. %{link_to_help_page}"
msgid "You can move around the graph by using the arrow keys."
-msgstr ""
+msgstr "Du kannst das Diagramm mit den Pfeiltasten bewegen."
msgid "You can only add files when you are on a branch"
-msgstr "Du kannst Dateien nur hinzufügen, wenn Du dich auf einem Branch befindest."
+msgstr "Du kannst Dateien nur hinzufügen, wenn du dich auf einem Branch befindest"
msgid "You can only edit files when you are on a branch"
-msgstr ""
+msgstr "Du kannst Dateien nur bearbeiten, wenn du dich auf einem Branch befindest"
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
-msgstr ""
+msgstr "Du kannst den Merge-Konflikt lösen, indem du entweder den interaktiven Modus verwendest, indem du die Schaltflächen %{use_ours} oder %{use_theirs} wählst, oder indem du die Dateien direkt bearbeitest. Übernimm diese Änderungen mittels Commit in %{branch_name}"
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
-msgstr ""
+msgstr "Du kannst Jobs so einrichten, dass nur Runner mit bestimmten Tags verwendet werden. Trenne die Tags durch Kommas."
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr "Du kannst deine .gitlab-ci.yml mit %{linkStart}CI Lint%{linkEnd} testen."
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
-msgstr ""
+msgstr "Du kannst nicht auf eine schreibgeschützte sekundäre Gitlab Geo-Instanz schreiben. Bitte verwende stattdessen %{link_to_primary_node}."
msgid "You cannot write to this read-only GitLab instance."
-msgstr ""
+msgstr "Du kannst nicht auf dieser schreibgeschützte GitLab-Instanz schreiben."
+
+msgid "You do not have any subscriptions yet"
+msgstr "Du hast noch keine Abonnements"
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
-msgstr ""
+msgstr "Du verfügst nicht über die erforderlichen Berechtigungen um die Einstellungen der LDAP-Gruppensynchronisierung zu überschreiben."
msgid "You don't have any applications"
-msgstr ""
+msgstr "Du hast keine Anwendungen"
msgid "You don't have any authorized applications"
-msgstr ""
+msgstr "Du hast keine autorisierten Anwendungen"
msgid "You have no permissions"
-msgstr ""
+msgstr "Du hast keine Berechtigungen"
msgid "You have reached your project limit"
-msgstr "Du hast die Projektbegrenzung erreicht."
+msgstr "Du hast die Projektbegrenzung erreicht"
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
-msgstr ""
+msgstr "Du musst unsere Nutzungsbedingungen und Datenschutzerklärung akzeptieren, um ein Konto registrieren zu können"
msgid "You must have maintainer access to force delete a lock"
-msgstr ""
-
-msgid "You must sign in to star a project"
-msgstr "Du musst angemeldet sein, um ein Projekt zu favorisieren."
+msgstr "Du musst Betreuerzugriff besitzen, um das Entfernen einer Sperre zu erzwingen"
msgid "You need a different license to enable FileLocks feature"
-msgstr ""
+msgstr "Du benötigst eine andere Lizenz, um die FileLocks-Funktion zu aktivieren"
msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
-msgstr ""
+msgstr "Du benötigst git-lfs in Version %{min_git_lfs_version} (oder höher) um fortzufahren. Bitte besuche https://git-lfs.github.com"
msgid "You need permission."
msgstr "Du brauchst eine Genehmigung."
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr "Du wirst alle Änderungen an dieser Datei verlieren. Dies kann nicht rückgängig gemacht werden."
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr "Du wirst alle nicht vorgemerkten Änderungen an diesem Projekt verlieren. Dies kann nicht rückgängig gemacht werden."
+
msgid "You will not get any notifications via email"
-msgstr "Du wirst keine Benachrichtigungen per E-Mail erhalten."
+msgstr "Du wirst keine Benachrichtigungen per E-Mail erhalten"
msgid "You will only receive notifications for the events you choose"
-msgstr "Du wirst nur Benachrichtigungen für, von Dir ausgewählte, Ereignisse erhalten."
+msgstr "Du wirst nur Benachrichtigungen für von dir ausgewählte Ereignisse erhalten"
msgid "You will only receive notifications for threads you have participated in"
-msgstr "Du wirst nur Benachrichtigungen für Unterhaltungen, an denen Du teilgenommen hast, erhalten."
+msgstr "Du wirst nur Benachrichtigungen für Unterhaltungen, an denen Du teilgenommen hast, erhalten"
msgid "You will receive notifications for any activity"
-msgstr "Du wirst bei jeder Aktivität Benachrichtigungen erhalten."
+msgstr "Du wirst bei jeder Aktivität Benachrichtigungen erhalten"
msgid "You will receive notifications only for comments in which you were @mentioned"
-msgstr "Du wirst nur Benachrichtigungen für Kommentare erhalten, in denen du @erwähnt wurdest."
+msgstr "Du wirst nur Benachrichtigungen für Kommentare erhalten, in denen du @erwähnt wurdest"
msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
-msgstr "Du kannst erst mittels '%{protocol}' übertragen (push) oder abrufen (pull), nachdem Du für dein Konto '%{set_password_link}'."
+msgstr "Du kannst erst mittels '%{protocol}' übertragen (push) oder abrufen (pull), nachdem du für dein Konto '%{set_password_link}'"
msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
-msgstr "Du kannst erst mittels SSH übertragen (push) oder abrufen (pull), nachdem Du Deinem Konto '%{add_ssh_key_link}'."
+msgstr "Du kannst erst mittels SSH übertragen (push) oder abrufen (pull), nachdem du deinem Konto '%{add_ssh_key_link}'"
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
-msgstr ""
+msgstr "Du musst einen deinem Profil einen SSH-Schlüssel hinzufügen, bevor du deinen Projekt-Code mittels Pull oder Push über SSH übertragen kannst"
msgid "You'll need to use different branch names to get a valid comparison."
-msgstr ""
+msgstr "Du musst unterschiedliche Branchnamen verwenden, um einen gültigen Vergleich zu erhalten."
msgid "You're receiving this email because %{reason}."
-msgstr ""
+msgstr "Du erhältst diese E-Mail, weil %{reason}."
msgid "You're receiving this email because of your account on %{host}."
-msgstr ""
+msgstr "Du erhältst diese E-Mail aufgrund deines Accounts auf %{host}."
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
-msgstr ""
+msgstr "Du erhältst diese E-Mail aufgrund deines Kontos auf %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgid "YouTube"
-msgstr ""
+msgstr "YouTube"
msgid "Your Groups"
-msgstr ""
+msgstr "Deine Gruppen"
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
-msgstr ""
+msgstr "Die Informationen zu deinem Kubernetes-Cluster auf dieser Seite können weiterhin bearbeitet werden. Es wird jedoch empfohlen, die Konfiguration zu deaktivieren und neu zu konfigurieren"
msgid "Your Projects (default)"
-msgstr ""
+msgstr "Deine Projekte (Standard)"
msgid "Your Projects' Activity"
-msgstr ""
+msgstr "Aktivitäten deiner Projekte"
msgid "Your Todos"
-msgstr ""
+msgstr "Deine To-dos"
msgid "Your applications (%{size})"
-msgstr ""
+msgstr "Deine Anwendungen (%{size})"
msgid "Your authorized applications"
-msgstr ""
+msgstr "Deine autorisierten Anwendungen"
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
-msgstr ""
+msgstr "Deine Änderungen können an %{branch_name} committet werden, da eine Merge-Request geöffnet ist."
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr "Deine Änderungen wurden committet. Commit %{commitId}%{commitStats}"
+
+msgid "Your changes have been saved"
msgstr ""
msgid "Your comment will not be visible to the public."
-msgstr ""
+msgstr "Dein Kommentar wird nicht öffentlich sichtbar sein."
msgid "Your groups"
-msgstr ""
+msgstr "Deine Gruppen"
msgid "Your name"
msgstr "Dein Name"
@@ -8229,266 +9337,258 @@ msgid "Your projects"
msgstr "Deine Projekte"
msgid "a deleted user"
-msgstr ""
+msgstr "ein(e) gelöschte(r) Benutzer(in)"
msgid "ago"
-msgstr ""
+msgstr "vor"
msgid "among other things"
-msgstr ""
-
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgstr "unter anderem"
msgid "assign yourself"
-msgstr ""
+msgstr "selber zuweisen"
msgid "branch name"
-msgstr ""
+msgstr "Branch-Name"
msgid "by"
-msgstr ""
+msgstr "von"
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}Lerne mehr über Containerüberprüfung%{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}Lerne mehr über DAST%{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}Lerne mehr über Abhängigkeitsüberprüfung%{linkEndTag}"
msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
-msgstr ""
+msgstr "%{linkStartTag}Lerne mehr über SAST%{linkEndTag}"
msgid "ciReport|%{namespace} is affected by %{vulnerability}."
-msgstr ""
+msgstr "%{namespace} ist von %{vulnerability} betroffen."
msgid "ciReport|%{remainingPackagesCount} more"
-msgstr ""
+msgstr "%{remainingPackagesCount} mehr"
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] "%{reportType} %{status} hat %{fixedCount} behobene Sicherheitslücke entdeckt"
+msgstr[1] "%{reportType} %{status} hat %{fixedCount} behobene Sicherheitslücke entdeckt"
-msgid "ciReport|%{reportName} resulted in error while loading results"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] "%{reportType} %{status} hat %{newCount} neue Sicherheitslücke entdeckt"
+msgstr[1] "%{reportType} %{status} hat %{newCount} neue Sicherheitslücken entdeckt"
-msgid "ciReport|%{type} detected no new security vulnerabilities"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr "%{reportType} %{status} hat %{newCount} neue und %{fixedCount} behobene Sicherheitslücken entdeckt"
-msgid "ciReport|%{type} detected no security vulnerabilities"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] "%{reportType} %{status} hat %{newCount} Sicherheitslücke für den Quellbranch festgestellt"
+msgstr[1] "%{reportType} %{status} hat %{newCount} Sicherheitslücken für den Quellbranch festgestellt"
-msgid "ciReport|%{type} detected no vulnerabilities"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr "%{reportType} %{status} hat keine neue Sicherheitslücke entdeckt"
-msgid "ciReport|Class"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr "%{reportType} %{status} hat keine Sicherheitslücken entdeckt"
-msgid "ciReport|Code quality"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr "%{reportType} %{status} hat nur für den Quellbranch keine Sicherheitslücken festgestellt"
-msgid "ciReport|Confidence"
-msgstr ""
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] "%{reportType} hat %{vulnerabilityCount} Sicherheitslücke gefunden"
+msgstr[1] "%{reportType} hat %{vulnerabilityCount} Sicherheitslücken gefunden"
-msgid "ciReport|Container scanning detected"
-msgstr ""
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr "%{reportType} hat keine Sicherheitslücken gefunden"
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
-msgstr ""
+msgid "ciReport|%{reportType} is loading"
+msgstr "%{reportType} wird geladen"
-msgid "ciReport|Container scanning is loading"
-msgstr ""
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr "%{reportType}: Beim Laden trat ein Fehler auf"
-msgid "ciReport|Container scanning resulted in error while loading results"
-msgstr ""
+msgid "ciReport|(errors when loading results)"
+msgstr "(Fehler beim Laden der Ergebnisse)"
-msgid "ciReport|DAST detected"
-msgstr ""
+msgid "ciReport|(is loading)"
+msgstr "(wird geladen)"
-msgid "ciReport|DAST is loading"
-msgstr ""
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr "(Lädt, Fehler beim Laden der Ergebnisse)"
-msgid "ciReport|DAST resulted in error while loading results"
-msgstr ""
+msgid "ciReport|Class"
+msgstr "Klasse"
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
-msgstr ""
+msgid "ciReport|Code quality"
+msgstr "Code-Qualität"
-msgid "ciReport|Dependency scanning detected"
-msgstr ""
+msgid "ciReport|Confidence"
+msgstr "Vertrauen"
-msgid "ciReport|Dependency scanning is loading"
-msgstr ""
+msgid "ciReport|Container scanning"
+msgstr "Container-Scan"
-msgid "ciReport|Dependency scanning resulted in error while loading results"
-msgstr ""
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr "Containerüberprüfung entdeckt bekannte Sicherheitslücken in deinen Docker-Images."
+
+msgid "ciReport|DAST"
+msgstr "DAST"
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr "Die Abhängigkeitsüberprüfung entdeckt bekannte Sicherheitslücken in den Abhängigkeiten deines Quellcodes."
+
+msgid "ciReport|Dependency scanning"
+msgstr "Abhängigkeitsüberprüfung"
msgid "ciReport|Description"
-msgstr ""
+msgstr "Beschreibung"
msgid "ciReport|Dismiss vulnerability"
-msgstr ""
+msgstr "Sicherheitslücke ausblenden"
msgid "ciReport|Dismissed by"
-msgstr ""
+msgstr "Abgelehnt von"
msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
-msgstr ""
+msgstr "Dynamic Application Security Testing (DAST) entdeckt Schwachstellen in deiner Webanwendung."
msgid "ciReport|Failed to load %{reportName} report"
-msgstr ""
+msgstr "Fehler beim Laden des Berichts %{reportName}"
msgid "ciReport|File"
-msgstr ""
+msgstr "Datei"
msgid "ciReport|Fixed:"
-msgstr ""
+msgstr "Behoben:"
msgid "ciReport|Identifiers"
-msgstr ""
+msgstr "Bezeichner"
msgid "ciReport|Instances"
-msgstr ""
+msgstr "Instanzen"
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
-msgstr ""
-
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
+msgstr "Lerne mehr über die Interaktion mit Sicherheitsberichten (Alpha)."
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Lizenzmanagement hat nur %d Lizenz für den Quellbranch gefunden"
+msgstr[1] "Lizenzmanagement hat nur %d Lizenzen für den Quellbranch gefunden"
msgid "ciReport|License management detected %d new license"
msgid_plural "ciReport|License management detected %d new licenses"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Lizenzmanagement hat %d neue Lizenz entdeckt"
+msgstr[1] "Lizenzmanagement hat %d neue Lizenzen entdeckt"
msgid "ciReport|License management detected no licenses for the source branch only"
-msgstr ""
+msgstr "Lizenzmanagement hat nur keine Lizenzen für den Quellbranch gefunden"
msgid "ciReport|License management detected no new licenses"
-msgstr ""
+msgstr "Lizenzmanagement hat keine neuen Lizenzen entdeckt"
msgid "ciReport|Links"
-msgstr ""
+msgstr "Links"
msgid "ciReport|Loading %{reportName} report"
-msgstr ""
+msgstr "Lade Bericht %{reportName}"
+
+msgid "ciReport|Manage licenses"
+msgstr "Lizenzen verwalten"
msgid "ciReport|Method"
-msgstr ""
+msgstr "Methode"
msgid "ciReport|Namespace"
-msgstr ""
+msgstr "Namensraum"
msgid "ciReport|No changes to code quality"
-msgstr ""
+msgstr "Keine Änderungen an der Codequalität"
msgid "ciReport|No changes to performance metrics"
-msgstr ""
+msgstr "Keine Änderungen an den Leistungsmetriken"
msgid "ciReport|Performance metrics"
-msgstr ""
+msgstr "Leistungsmetriken"
msgid "ciReport|Revert dismissal"
-msgstr ""
-
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
+msgstr "Ausblenden rückgängig machen"
-msgid "ciReport|SAST resulted in error while loading results"
-msgstr ""
+msgid "ciReport|SAST"
+msgstr "SAST"
msgid "ciReport|Security scanning"
-msgstr ""
+msgstr "Sicherheitsüberprüfung"
msgid "ciReport|Security scanning failed loading any results"
-msgstr ""
-
-msgid "ciReport|Security scanning is loading"
-msgstr ""
+msgstr "Sicherheitsscan schlug beim Laden der Ergebnisse fehl"
msgid "ciReport|Severity"
-msgstr ""
+msgstr "Schweregrad"
msgid "ciReport|Solution"
-msgstr ""
+msgstr "Lösung"
msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
-msgstr ""
+msgstr "Static Application Security Testing (SAST) entdeckt bekannte Sicherheitslücken in deinem Quellcode."
msgid "ciReport|There was an error creating the issue. Please try again."
-msgstr ""
+msgstr "Fehler beim Erzeugen des Tickets. Bitte versuche es erneut."
msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
-msgstr ""
+msgstr "Fehler beim Ausblenden der Sicherheitslücke. Bitte versuche es erneut."
msgid "ciReport|There was an error loading DAST report"
-msgstr ""
+msgstr "Beim Laden des DAST-Berichtes ist ein Fehler aufgetreten"
msgid "ciReport|There was an error loading SAST report"
-msgstr ""
+msgstr "Beim Laden des SAST-Berichtes ist ein Fehler aufgetreten"
msgid "ciReport|There was an error loading container scanning report"
-msgstr ""
+msgstr "Fehler beim Laden des Containerüberprüfungs-Berichtes"
msgid "ciReport|There was an error loading dependency scanning report"
-msgstr ""
+msgstr "Fehler beim Laden des Abhängigkeitsprüfungs-Berichtes"
msgid "ciReport|There was an error reverting the dismissal. Please try again."
-msgstr ""
-
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
+msgstr "Fehler beim Wiedereinblenden. Bitte versuche es erneut."
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
-msgstr ""
+msgstr "Upgrade %{name} von %{version} zu %{fixed}."
msgid "ciReport|Used by %{packagesString}"
msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Verwendet von %{packagesString}"
+msgstr[1] "Verwendet von %{packagesString} und %{lastPackage}"
msgid "ciReport|View full report"
-msgstr ""
-
-msgid "ciReport|no vulnerabilities"
-msgstr ""
+msgstr "Gesamten Bericht anzeigen"
msgid "ciReport|on pipeline"
-msgstr ""
+msgstr "in der Pipeline"
msgid "command line instructions"
-msgstr ""
+msgstr "Befehlszeilenanweisungen"
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
+msgstr "Du willst die Vertraulichkeit deaktivieren. Das bedeutet, dass <strong>jeder</strong> das Ticket betrachten und kommentieren kann."
msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
+msgstr "Du willst die Vertraulichkeit aktivieren. Das bedeutet, dass nur Teammitglieder mit <strong>mindestens Reporter-Zugriff</strong> das Ticket betrachten und kommentieren können."
msgid "connecting"
-msgstr ""
+msgstr "Verbinde"
msgid "could not read private key, is the passphrase correct?"
-msgstr ""
+msgstr "konnte den privaten Schlüssel nicht lesen, ist die Passphrase korrekt?"
msgid "customize"
-msgstr ""
+msgstr "anpassen"
msgid "day"
msgid_plural "days"
@@ -8496,380 +9596,400 @@ msgstr[0] "Tag"
msgstr[1] "Tage"
msgid "deploy token"
-msgstr ""
-
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
+msgstr "Bereitstellungstoken"
msgid "disabled"
-msgstr ""
+msgstr "dektiviert"
msgid "done"
-msgstr ""
+msgstr "erledigt"
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] "Entwurf"
+msgstr[1] "Entwürfe"
msgid "enabled"
-msgstr ""
+msgstr "aktiviert"
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
-msgstr ""
+msgstr "%{slash_command} aktualisiert die geschätzte Zeit mit dem aktuellsten Befehl."
msgid "for this project"
-msgstr ""
+msgstr "für dieses Projekt"
+
+msgid "from"
+msgstr "von"
+
+msgid "help"
+msgstr "Hilfe"
msgid "here"
-msgstr ""
+msgstr "hier"
msgid "https://your-bitbucket-server"
-msgstr ""
+msgstr "https://dein-bitbucket-server"
msgid "import flow"
-msgstr ""
+msgstr "Vorgehen beim Import"
msgid "importing"
-msgstr ""
+msgstr "Importiere"
msgid "instance completed"
msgid_plural "instances completed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Instanz abgeschlossen"
+msgstr[1] "Instanzen abgeschlossen"
msgid "is invalid because there is downstream lock"
-msgstr ""
+msgstr "ist ungültig, weil es eine Downstream-Sperre gibt"
msgid "is invalid because there is upstream lock"
-msgstr ""
+msgstr "ist aufgrund einer Upstream-Sperre ungültig"
msgid "is not a valid X509 certificate."
-msgstr ""
+msgstr "ist kein gültiges X509-Zertifikat."
msgid "issue boards"
-msgstr ""
+msgstr "Ticketboards"
+
+msgid "latest deployment"
+msgstr "neuste Bereitstellung"
msgid "latest version"
-msgstr ""
+msgstr "Neuste Version"
msgid "license management"
-msgstr ""
+msgstr "Lizenzverwaltung"
msgid "locked by %{path_lock_user_name} %{created_at}"
-msgstr ""
+msgstr "gesperrt durch %{path_lock_user_name} %{created_at}"
msgid "merge request"
msgid_plural "merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Merge-Request"
+msgstr[1] "Merge-Requests"
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
+msgstr "Bitte stelle es wieder her, oder verwende einen anderen Branch %{missingBranchName}"
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
-msgstr ""
+msgstr "%{metricsLinkStart} Speicherauslastung %{metricsLinkEnd} %{emphasisStart} gesunken %{emphasisEnd} von %{memoryFrom} MB auf %{memoryTo} MB"
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
-msgstr ""
+msgstr "%{metricsLinkStart} Speicherauslastung %{metricsLinkEnd} %{emphasisStart} gestiegen %{emphasisEnd} von %{memoryFrom} MB auf %{memoryTo} MB"
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
-msgstr ""
+msgstr "%{metricsLinkStart} Speicherauslastung %{metricsLinkEnd} ist %{emphasisStart} unverändert %{emphasisEnd} bei %{memoryFrom} MB"
msgid "mrWidget|Add approval"
-msgstr ""
+msgstr "Genehmigung hinzufügen"
msgid "mrWidget|Allows commits from members who can merge to the target branch"
-msgstr ""
+msgstr "Erlaube Commits von Mitgliedern die zum Zielbranch mergen können"
msgid "mrWidget|An error occured while removing your approval."
-msgstr ""
+msgstr "Beim Entfernen deiner Genehmigung ist ein Fehler aufgetreten."
msgid "mrWidget|An error occured while retrieving approval data for this merge request."
-msgstr ""
+msgstr "Beim Abrufen der Genehmigungsdaten für diesen Merge-Request ist ein Fehler aufgetreten."
msgid "mrWidget|An error occurred while submitting your approval."
-msgstr ""
+msgstr "Während des Sendens deiner Genehmigung trat ein Fehler auf."
msgid "mrWidget|Approve"
-msgstr ""
+msgstr "Genehmigen"
msgid "mrWidget|Approved by"
-msgstr ""
+msgstr "Genehmigt von"
msgid "mrWidget|Cancel automatic merge"
-msgstr ""
+msgstr "Automatischen Merge abbrechen"
msgid "mrWidget|Check out branch"
-msgstr ""
+msgstr "Branch auschecken"
msgid "mrWidget|Checking ability to merge automatically"
-msgstr ""
+msgstr "Prüft die Fähigkeit zum automatischen Merge"
msgid "mrWidget|Cherry-pick"
-msgstr ""
+msgstr "Cherry-Pick"
msgid "mrWidget|Cherry-pick this merge request in a new merge request"
-msgstr ""
+msgstr "Cherry-picke diesen Merge-Request in einen neuen Merge-Request"
msgid "mrWidget|Closed"
-msgstr ""
+msgstr "Geschlossen"
msgid "mrWidget|Closed by"
-msgstr ""
+msgstr "Geschlossen von"
msgid "mrWidget|Closes"
-msgstr ""
+msgstr "Schließt"
msgid "mrWidget|Create an issue to resolve them later"
-msgstr ""
+msgstr "Erstelle ein Ticket, um es später zu lösen"
msgid "mrWidget|Deployment statistics are not available currently"
-msgstr ""
+msgstr "Bereitstellungsstatistiken derzeit nicht verfügbar"
msgid "mrWidget|Did not close"
-msgstr ""
+msgstr "Wurde nicht geschlossen"
msgid "mrWidget|Email patches"
-msgstr ""
+msgstr "E-Mail-Patches"
msgid "mrWidget|Failed to load deployment statistics"
-msgstr ""
+msgstr "Fehler beim Laden der Bereitstellungsstatistiken"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
-msgstr ""
+msgstr "Schnelles Mergen ist nicht möglich. Um diesen Merge_request zu mergen, rebase zuerst lokal."
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
-msgstr ""
+msgstr "Wenn der %{branch} Branch in deinem lokalen Repository existiert kannst du den Merge-Request manuell mergen mit Hilfe des"
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
-msgstr ""
+msgstr "Wenn der Branch %{missingBranchName} in deinem lokalen Repository vorhanden ist, kannst du diesen Merge-Request manuell über die Befehlszeile zusammenführen"
msgid "mrWidget|Loading deployment statistics"
-msgstr ""
+msgstr "Lade Bereitstellungsstatistiken"
msgid "mrWidget|Mentions"
-msgstr ""
+msgstr "Erwähnungen"
msgid "mrWidget|Merge"
-msgstr ""
+msgstr "Merge"
msgid "mrWidget|Merge failed."
-msgstr ""
+msgstr "Merge fehlgeschlagen."
msgid "mrWidget|Merge locally"
-msgstr ""
+msgstr "Lokal mergen"
msgid "mrWidget|Merge request approved"
-msgstr ""
+msgstr "Merge-Request genehmigt"
msgid "mrWidget|Merge request approved; you can approve additionally"
-msgstr ""
+msgstr "Merge-Request genehmigt; du kannst zusätzlich genehmigen"
msgid "mrWidget|Merged by"
-msgstr ""
+msgstr "Merged von"
msgid "mrWidget|No Approval required"
-msgstr ""
+msgstr "Keine Genehmigung erforderlich"
msgid "mrWidget|No Approval required; you can still approve"
-msgstr ""
+msgstr "Keine Genehmigung erforderlich; du kannst noch genehmigen"
msgid "mrWidget|Open in Web IDE"
-msgstr ""
+msgstr "Öffnen im Web-IDE"
msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
-msgstr ""
+msgstr "Pipeline blockiert. Die Pipeline für diesen Merge-Request erfordert eine manuelle Aktion um fortzufahren"
msgid "mrWidget|Plain diff"
-msgstr ""
+msgstr "Unformatiertes Diff"
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
-msgstr ""
+msgstr "Bereit zum automatischen Mergen. Bitte jemanden mit Schreibrechten zu diesem Repository diesen Merge-Request zu mergen"
msgid "mrWidget|Refresh"
-msgstr ""
+msgstr "Aktualisieren"
msgid "mrWidget|Refresh now"
-msgstr ""
+msgstr "Jetzt aktualisieren"
msgid "mrWidget|Refreshing now"
-msgstr ""
+msgstr "Aktualisiere gerade"
msgid "mrWidget|Remove Source Branch"
-msgstr ""
+msgstr "Quellbranch entfernen"
msgid "mrWidget|Remove source branch"
-msgstr ""
+msgstr "Quellbranch entfernen"
msgid "mrWidget|Remove your approval"
-msgstr ""
+msgstr "Entferne deine Genehmigung"
msgid "mrWidget|Request to merge"
-msgstr ""
+msgstr "Anfrage zum Mergen"
msgid "mrWidget|Requires 1 more approval"
msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Erfordert 1 weitere Genehmigung"
+msgstr[1] "Erfordert %d weitere Genehmigungen"
msgid "mrWidget|Requires 1 more approval by"
msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Erfordert 1 weitere Genehmigung durch"
+msgstr[1] "Erfordert %d weitere Genehmigungen durch"
msgid "mrWidget|Resolve conflicts"
-msgstr ""
+msgstr "Konflikte auflösen"
msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
-msgstr ""
+msgstr "Löse diese Konflikte oder frage jemanden mit Schreibzugriff auf dieses Repository, um es lokal zusammenzuführen"
msgid "mrWidget|Revert"
-msgstr ""
+msgstr "Zurücksetzen"
msgid "mrWidget|Revert this merge request in a new merge request"
-msgstr ""
+msgstr "Diesen Merge-Request in einem neuen Merge-Request rückgängig machen"
msgid "mrWidget|Set by"
-msgstr ""
+msgstr "Festlegt von"
msgid "mrWidget|The changes were merged into"
-msgstr ""
+msgstr "Die Änderungen wurden gemerged nach"
msgid "mrWidget|The changes were not merged into"
-msgstr ""
+msgstr "Die Änderungen wurden nicht gemerged nach"
msgid "mrWidget|The changes will be merged into"
-msgstr ""
+msgstr "Die Änderungen werden gemerged nach"
msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
-msgstr ""
+msgstr "Die Pipeline für diesen Merge-Request ist fehlgeschlagen. Bitte wiederhole den Job oder pushe einen neuen Commit, um den Fehler zu beheben"
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
-msgstr ""
+msgstr "Der HEAD des Quellbranches wurde kürzlich geändert. Bitte lade die Seite neu und überprüfe die Änderungen vor dem Mergen"
msgid "mrWidget|The source branch has been removed"
-msgstr ""
+msgstr "Der Quellbranch wurde entfernt"
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
-msgstr ""
+msgstr "Der Quellbranch ist %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} dem Zielbranch"
msgid "mrWidget|The source branch is being removed"
-msgstr ""
+msgstr "Der Quellbranch wird gerade entfernt"
msgid "mrWidget|The source branch will be removed"
-msgstr ""
+msgstr "Der Quellbranch wird entfernt"
msgid "mrWidget|The source branch will not be removed"
-msgstr ""
+msgstr "Der Quellbranch wird nicht entfernt"
msgid "mrWidget|There are merge conflicts"
-msgstr ""
+msgstr "Es gibt Merge-Konflikte"
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
-msgstr ""
+msgstr "Es gibt ungelöste Diskussionen. Bitte löse diese Diskussionen"
msgid "mrWidget|This merge request failed to be merged automatically"
-msgstr ""
+msgstr "Dieser Merge-Request konnte nicht automatisch gemerged werden"
msgid "mrWidget|This merge request is in the process of being merged"
-msgstr ""
+msgstr "Dieser Merge-Reqeust wird gerade gemerged"
msgid "mrWidget|This project is archived, write access has been disabled"
-msgstr ""
+msgstr "Dieses Projekt wurde archiviert, der Schreibzugriff wurde deaktiviert"
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr "Du darfst dieses Projekt nicht direkt bearbeiten. Bitte erstelle einen Fork, um Änderungen vorzunehmen."
msgid "mrWidget|You can merge this merge request manually using the"
-msgstr ""
+msgstr "Du kannst diesen Merge-Request manuell mergen mit dem"
msgid "mrWidget|You can remove source branch now"
-msgstr ""
+msgstr "Du kannst den Quellbranch jetzt entfernen"
msgid "mrWidget|branch does not exist."
-msgstr ""
+msgstr "Branch existiert nicht."
msgid "mrWidget|command line"
-msgstr ""
+msgstr "Befehlszeile"
msgid "mrWidget|into"
-msgstr ""
+msgstr "hinein"
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
-msgstr ""
+msgstr "wird automatisch zusammengeführt, wenn die Pipeline erfolgreich ist"
+
+msgid "n/a"
+msgstr "nicht verfügbar"
msgid "new merge request"
-msgstr "Neuer Merge Request"
+msgstr "Neuer Merge-Request"
msgid "notification emails"
-msgstr "Benachrichtungsemail"
+msgstr "Benachrichtungs-E-mails"
msgid "or"
-msgstr ""
+msgstr "oder"
msgid "out of %d total test"
msgid_plural "out of %d total tests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "von insgesamt %d Test"
+msgstr[1] "von insgesamt %d Tests"
msgid "parent"
msgid_plural "parents"
-msgstr[0] "Vorgänger"
-msgstr[1] "Vorgänger"
+msgstr[0] "Ãœbergeordneter"
+msgstr[1] "Ãœbergeordnete"
msgid "password"
-msgstr ""
+msgstr "Passwort"
msgid "personal access token"
-msgstr ""
+msgstr "Persönlicher Zugangs-Token"
msgid "private key does not match certificate."
-msgstr ""
+msgstr "Der private Schlüssel stimmt nicht mit dem Zertifikat überein."
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] "Projekt"
+msgstr[1] "Projekte"
msgid "remaining"
-msgstr ""
+msgstr "verbleibend"
msgid "remove"
-msgstr ""
+msgstr "Entfernen"
msgid "remove due date"
-msgstr ""
+msgstr "Fälligkeitsdatum entfernen"
msgid "remove weight"
-msgstr ""
+msgstr "Gewichtung entfernen"
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
msgid "source"
-msgstr ""
+msgstr "Quelle"
msgid "spendCommand|%{slash_command} will update the sum of the time spent."
-msgstr ""
+msgstr "%{slash_command} aktualisiert die Summe der aufgewendeten Zeit."
msgid "started"
-msgstr ""
+msgstr "gestartet"
msgid "this document"
-msgstr ""
+msgstr "dieses Dokument"
msgid "to help your contributors communicate effectively!"
-msgstr ""
+msgstr "um deinen Mitwirkenden zu helfen möglichst effizient zu kommunizieren!"
+
+msgid "toggle collapse"
+msgstr "Ein- und ausklappen"
msgid "username"
-msgstr ""
+msgstr "Benutzername"
msgid "uses Kubernetes clusters to deploy your code!"
-msgstr ""
+msgstr "verwendet Kubernetes-Cluster, um deinen Code bereitzustellen!"
msgid "view it on GitLab"
-msgstr ""
+msgstr "sieh es auf GitLab an"
msgid "with %{additions} additions, %{deletions} deletions."
-msgstr ""
+msgstr "mit %{additions} Ergänzungen, %{deletions} Löschungen."
msgid "within %d minute "
msgid_plural "within %d minutes "
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "innerhalb %d Minute "
+msgstr[1] "innerhalb %d Minuten "
diff --git a/locale/el_GR/gitlab.po b/locale/el_GR/gitlab.po
new file mode 100644
index 00000000000..1184b396e13
--- /dev/null
+++ b/locale/el_GR/gitlab.po
@@ -0,0 +1,9995 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
+"Language-Team: Greek\n"
+"Language: el_GR\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: el\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"PO-Revision-Date: 2018-11-19 17:23\n"
+
+msgid " Status"
+msgstr ""
+
+msgid " and"
+msgstr ""
+
+msgid " degraded on %d point"
+msgid_plural " degraded on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " improved on %d point"
+msgid_plural " improved on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d changed file"
+msgid_plural "%d changed files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d failed test result"
+msgid_plural "%d failed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d staged change"
+msgid_plural "%d staged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unstaged change"
+msgid_plural "%d unstaged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_timeago}"
+msgstr ""
+
+msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgstr ""
+
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{loadingIcon} Started"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+msgid "%{nip_domain} can be used as an alternative to a custom domain."
+msgstr ""
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr ""
+
+msgid "%{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
+
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid "- Runner is active and can process any new jobs"
+msgstr ""
+
+msgid "- Runner is paused and will not receive any new jobs"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "1 %{type} addition"
+msgid_plural "%{count} %{type} additions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 %{type} modification"
+msgid_plural "%{count} %{type} modifications"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed issue"
+msgid_plural "%d closed issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed merge request"
+msgid_plural "%d closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merged merge request"
+msgid_plural "%d merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open merge request"
+msgid_plural "%d open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 user"
+msgid_plural "%d users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "2FA enabled"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get the permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
+msgstr ""
+
+msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
+msgstr ""
+
+msgid "<strong>%{group_name}</strong> group members"
+msgstr ""
+
+msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
+msgstr ""
+
+msgid "<strong>Removes</strong> source branch"
+msgstr ""
+
+msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
+msgstr ""
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
+msgstr ""
+
+msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About GitLab CE"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Accepted MR"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied! Please verify you can add deploy keys to this repository."
+msgstr ""
+
+msgid "Access expiration date"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add Changelog"
+msgstr ""
+
+msgid "Add Contribution guide"
+msgstr ""
+
+msgid "Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add Readme"
+msgstr ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add projects"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add todo"
+msgstr ""
+
+msgid "Add user(s) to the group:"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Admin Area"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "Admin area"
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminProjects|Delete project"
+msgstr ""
+
+msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
+
+msgid "Advanced settings"
+msgstr ""
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "All"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr ""
+
+msgid "All users"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch."
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts"
+msgstr ""
+
+msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
+msgstr ""
+
+msgid "Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An error accured whilst committing your changes."
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error occured creating the new branch."
+msgstr ""
+
+msgid "An error occured whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occured whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occured whilst loading all the files."
+msgstr ""
+
+msgid "An error occured whilst loading the file content."
+msgstr ""
+
+msgid "An error occured whilst loading the file."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request."
+msgstr ""
+
+msgid "An error occured whilst loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
+msgstr ""
+
+msgid "An error occurred while adding approver"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while fetching markdown preview"
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching sidebar data"
+msgstr ""
+
+msgid "An error occurred while fetching stages."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the pipeline."
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while importing project: %{details}"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while removing approver"
+msgstr ""
+
+msgid "An error occurred while rendering KaTeX"
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while retrieving calendar activity"
+msgstr ""
+
+msgid "An error occurred while retrieving diff"
+msgstr ""
+
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
+msgstr ""
+
+msgid "An error occurred while subscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while unsubscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any Label"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read-only"
+msgstr ""
+
+msgid "Archived projects"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Artifact ID"
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer to set up a group Runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned Merge Requests"
+msgstr ""
+
+msgid "Assigned to :name"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assignee"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee lists show all issues assigned to the selected user."
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto DevOps, runners and job artifacts"
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
+msgstr ""
+
+msgid "Auto-cancel redundant, pending pipelines"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
+msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
+msgstr ""
+
+msgid "AutoDevOps|add a Kubernetes cluster"
+msgstr ""
+
+msgid "AutoDevOps|enable Auto DevOps"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available group Runners : %{runners}"
+msgstr ""
+
+msgid "Available group Runners : %{runners}."
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|A new badge was added."
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Delete badge"
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|No badge image"
+msgstr ""
+
+msgid "Badges|No image to preview"
+msgstr ""
+
+msgid "Badges|Please fill in a valid URL"
+msgstr ""
+
+msgid "Badges|Project Badge"
+msgstr ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|The badge was saved."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "Badges|e.g. %{exampleUrl}"
+msgstr ""
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are examples of regex for existing tools:"
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
+msgstr ""
+
+msgid "BillingPlans|Current plan"
+msgstr ""
+
+msgid "BillingPlans|Customer Support"
+msgstr ""
+
+msgid "BillingPlans|Downgrade"
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
+msgstr ""
+
+msgid "BillingPlans|Manage plan"
+msgstr ""
+
+msgid "BillingPlans|Please contact %{customer_support_link} in that case."
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Upgrade"
+msgstr ""
+
+msgid "BillingPlans|You are currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
+msgstr ""
+
+msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
+msgstr ""
+
+msgid "BillingPlans|features"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|paid annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch (%{branch_count})"
+msgid_plural "Branches (%{branch_count})"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch has changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "BranchSwitcherPlaceholder|Search branches"
+msgstr ""
+
+msgid "BranchSwitcherTitle|Switch branch"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cant find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch '%{branch_name}'?"
+msgstr ""
+
+msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+msgstr ""
+
+msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Branches|Only a project maintainer or owner can delete a protected branch"
+msgstr ""
+
+msgid "Branches|Overview"
+msgstr ""
+
+msgid "Branches|Protected branches can be managed in %{project_settings_link}."
+msgstr ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Sort by"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+msgstr ""
+
+msgid "Branches|The default branch cannot be deleted"
+msgstr ""
+
+msgid "Branches|This branch hasn’t been merged into %{default_branch}."
+msgstr ""
+
+msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
+msgid "Branches|To confirm, type %{branch_name_confirmation}:"
+msgstr ""
+
+msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
+msgstr ""
+
+msgid "Branches|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|project settings"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "Built-In"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CI / CD"
+msgstr ""
+
+msgid "CI / CD Settings"
+msgstr ""
+
+msgid "CI will run using the credentials assigned above."
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD for external repo"
+msgstr ""
+
+msgid "CI/CD settings"
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Deployment strategy needs a domain name to work correctly."
+msgstr ""
+
+msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|Learn more about Auto DevOps"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "Callback URL"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Certificate fingerprint"
+msgstr ""
+
+msgid "Change Weight"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates."
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "Changelog"
+msgstr ""
+
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
+msgstr ""
+
+msgid "Choose <strong>Next</strong> at the bottom of the page."
+msgstr ""
+
+msgid "Choose File ..."
+msgstr ""
+
+msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
+msgstr ""
+
+msgid "Choose file..."
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose which groups you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose which repositories you want to import."
+msgstr ""
+
+msgid "Choose which shards you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Error occured while saving variables"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "CiVariable|Validation failed"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
+msgstr ""
+
+msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
+msgstr ""
+
+msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
+msgstr ""
+
+msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
+msgstr ""
+
+msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Client authentication certificate"
+msgstr ""
+
+msgid "Client authentication key"
+msgstr ""
+
+msgid "Client authentication key password"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
+msgstr ""
+
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgstr ""
+
+msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|Applications"
+msgstr ""
+
+msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Token"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Helm Tiller"
+msgstr ""
+
+msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
+msgstr ""
+
+msgid "ClusterIntegration|Hide"
+msgstr ""
+
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|In order to show the health of the cluster, we'll need to provision your cluster with Prometheus to collect the required data."
+msgstr ""
+
+msgid "ClusterIntegration|Ingress"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress IP Address"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
+msgstr ""
+
+msgid "ClusterIntegration|Install"
+msgstr ""
+
+msgid "ClusterIntegration|Install Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Installed"
+msgstr ""
+
+msgid "ClusterIntegration|Installing"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
+msgstr ""
+
+msgid "ClusterIntegration|Integration status"
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster health"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
+msgstr ""
+
+msgid "ClusterIntegration|More information"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Note:"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Service token"
+msgstr ""
+
+msgid "ClusterIntegration|Show"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Token"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|check the pricing here"
+msgstr ""
+
+msgid "ClusterIntegration|documentation"
+msgstr ""
+
+msgid "ClusterIntegration|help page"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|properly configured"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "Code owners"
+msgstr ""
+
+msgid "Cohorts"
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & resolve discussion"
+msgstr ""
+
+msgid "Comment & unresolve discussion"
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit (%{commit_count})"
+msgid_plural "Commits (%{commit_count})"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit duration in minutes for last 30 commits"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|Commit: %{commitText}"
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Commit…"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|Compare"
+msgstr ""
+
+msgid "CompareBranches|Source"
+msgstr ""
+
+msgid "CompareBranches|Target"
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Tracing"
+msgstr ""
+
+msgid "Configure automatic git checks and housekeeping on repositories."
+msgstr ""
+
+msgid "Configure limits for web and API requests."
+msgstr ""
+
+msgid "Configure push mirrors."
+msgstr ""
+
+msgid "Configure storage path settings."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the way a user creates a new account."
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Created"
+msgstr ""
+
+msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
+msgstr ""
+
+msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
+msgstr ""
+
+msgid "ContainerRegistry|How to use the Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Learn more about"
+msgstr ""
+
+msgid "ContainerRegistry|No tags in Container Registry for this container image."
+msgstr ""
+
+msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgstr ""
+
+msgid "ContainerRegistry|Size"
+msgstr ""
+
+msgid "ContainerRegistry|Tag"
+msgstr ""
+
+msgid "ContainerRegistry|Tag ID"
+msgstr ""
+
+msgid "ContainerRegistry|Use different image names"
+msgstr ""
+
+msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
+msgstr ""
+
+msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution guide"
+msgstr ""
+
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "ContributorsPage|%{startDate} – %{endDate}"
+msgstr ""
+
+msgid "ContributorsPage|Building repository graph."
+msgstr ""
+
+msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Control the display of third party offers."
+msgstr ""
+
+msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of repository backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of verification operations for this Geo node"
+msgstr ""
+
+msgid "ConvDev Index"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key to clipboard"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy branch name to clipboard"
+msgstr ""
+
+msgid "Copy command to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Copy file path to clipboard"
+msgstr ""
+
+msgid "Copy incoming email address to clipboard"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
+msgid "Copy reference to clipboard"
+msgstr ""
+
+msgid "Copy secret to clipboard"
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token to clipboard"
+msgstr ""
+
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new branch and merge request"
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create branch"
+msgstr ""
+
+msgid "Create commit"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty repository"
+msgstr ""
+
+msgid "Create epic"
+msgstr ""
+
+msgid "Create file"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created on"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron syntax"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current node"
+msgstr ""
+
+msgid "CurrentUser|Profile"
+msgstr ""
+
+msgid "CurrentUser|Settings"
+msgstr ""
+
+msgid "Custom"
+msgstr ""
+
+msgid "Custom CI config path"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Production"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Default Branch"
+msgstr ""
+
+msgid "Default classification label"
+msgstr ""
+
+msgid "Default: Directly import the Google Code email address or username"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete Package"
+msgstr ""
+
+msgid "Delete Snippet"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete list"
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployKeys|Write access allowed"
+msgstr ""
+
+msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Add a deploy token"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository"
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Copy username to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Deploy Tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|This project has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "DeployTokens|Use this username as a login."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|You are about to revoke"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group Runners"
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "Discard review"
+msgstr ""
+
+msgid "Discover GitLab Geo."
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss Cycle Analytics introduction box"
+msgstr ""
+
+msgid "Dismiss Merge Request promotion"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Each Runner can be in one of the following states:"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Elasticsearch"
+msgstr ""
+
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable SAML authentication for this group"
+msgstr ""
+
+msgid "Enable Sentry for error reporting and logging."
+msgstr ""
+
+msgid "Enable and configure InfluxDB metrics."
+msgstr ""
+
+msgid "Enable and configure Prometheus metrics."
+msgstr ""
+
+msgid "Enable classification control using an external service"
+msgstr ""
+
+msgid "Enable for this project"
+msgstr ""
+
+msgid "Enable group Runners"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable reCAPTCHA or Akismet and set IP limits."
+msgstr ""
+
+msgid "Enable the Performance Bar for a given group."
+msgstr ""
+
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter the issue description"
+msgstr ""
+
+msgid "Enter the issue title"
+msgstr ""
+
+msgid "Enter the merge request description"
+msgstr ""
+
+msgid "Enter the merge request title"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No pod name has been specified"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod logs from"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Read more about environments"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epic will be removed! Are you sure?"
+msgstr ""
+
+msgid "Epics"
+msgstr ""
+
+msgid "Epics Roadmap"
+msgstr ""
+
+msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
+msgstr ""
+
+msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgstr ""
+
+msgid "Epics|How can I solve this?"
+msgstr ""
+
+msgid "Epics|More information"
+msgstr ""
+
+msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+msgstr ""
+
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr ""
+
+msgid "Epics|due"
+msgstr ""
+
+msgid "Epics|start"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Reporting and Logging"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error fetching contributors data."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching usage ping data."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error updating status for all todos."
+msgstr ""
+
+msgid "Error updating todo status."
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "Every day (at 4:00am)"
+msgstr ""
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr ""
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
+msgid "Explore"
+msgstr ""
+
+msgid "Explore GitLab"
+msgstr ""
+
+msgid "Explore Groups"
+msgstr ""
+
+msgid "Explore groups"
+msgstr ""
+
+msgid "Explore projects"
+msgstr ""
+
+msgid "Explore public groups"
+msgstr ""
+
+msgid "External Classification Policy Authorization"
+msgstr ""
+
+msgid "External authentication"
+msgstr ""
+
+msgid "External authorization denied access to this project"
+msgstr ""
+
+msgid "External authorization request timeout"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification Label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to remove issue from board, please try again."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to update issues, please try again."
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fields on this page are now uneditable, you can configure"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Files (%{human_size})"
+msgstr ""
+
+msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
+msgid "Filter by commit message"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Find the downloaded ZIP file and decompress it."
+msgstr ""
+
+msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish review"
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "FirstPushedBy|First"
+msgstr ""
+
+msgid "FirstPushedBy|pushed by"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Follow the steps below to export your Google Code project data."
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Format"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
+msgid "From %{provider_title}"
+msgstr ""
+
+msgid "From Bitbucket"
+msgstr ""
+
+msgid "From Bitbucket Server"
+msgstr ""
+
+msgid "From FogBugz"
+msgstr ""
+
+msgid "From GitLab.com"
+msgstr ""
+
+msgid "From Google Code"
+msgstr ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "From milestones:"
+msgstr ""
+
+msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Nodes"
+msgstr ""
+
+msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is failing or broken."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
+msgstr ""
+
+msgid "GeoNodes|Checksummed"
+msgstr ""
+
+msgid "GeoNodes|Data is out of date from %{timeago}"
+msgstr ""
+
+msgid "GeoNodes|Data replication lag"
+msgstr ""
+
+msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "GeoNodes|Failed"
+msgstr ""
+
+msgid "GeoNodes|Full"
+msgstr ""
+
+msgid "GeoNodes|GitLab version"
+msgstr ""
+
+msgid "GeoNodes|GitLab version does not match the primary node version"
+msgstr ""
+
+msgid "GeoNodes|Health status"
+msgstr ""
+
+msgid "GeoNodes|Last event ID processed by cursor"
+msgstr ""
+
+msgid "GeoNodes|Last event ID seen from primary"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository verification"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki verification"
+msgstr ""
+
+msgid "GeoNodes|Loading nodes"
+msgstr ""
+
+msgid "GeoNodes|Local LFS objects"
+msgstr ""
+
+msgid "GeoNodes|Local attachments"
+msgstr ""
+
+msgid "GeoNodes|Local job artifacts"
+msgstr ""
+
+msgid "GeoNodes|New node"
+msgstr ""
+
+msgid "GeoNodes|Node Authentication was successfully repaired."
+msgstr ""
+
+msgid "GeoNodes|Node was successfully removed."
+msgstr ""
+
+msgid "GeoNodes|Not checksummed"
+msgstr ""
+
+msgid "GeoNodes|Out of sync"
+msgstr ""
+
+msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Replication slot WAL"
+msgstr ""
+
+msgid "GeoNodes|Replication slots"
+msgstr ""
+
+msgid "GeoNodes|Repositories"
+msgstr ""
+
+msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Repositories verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Repository verification progress"
+msgstr ""
+
+msgid "GeoNodes|Selective"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while changing node status"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while fetching nodes"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while removing node"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while repairing node"
+msgstr ""
+
+msgid "GeoNodes|Storage config"
+msgstr ""
+
+msgid "GeoNodes|Sync settings"
+msgstr ""
+
+msgid "GeoNodes|Synced"
+msgstr ""
+
+msgid "GeoNodes|Unused slots"
+msgstr ""
+
+msgid "GeoNodes|Unverified"
+msgstr ""
+
+msgid "GeoNodes|Used slots"
+msgstr ""
+
+msgid "GeoNodes|Verified"
+msgstr ""
+
+msgid "GeoNodes|Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Wiki verification progress"
+msgstr ""
+
+msgid "GeoNodes|Wikis"
+msgstr ""
+
+msgid "GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for forced re-download"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-check"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|All"
+msgstr ""
+
+msgid "Geo|All projects"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|File sync capacity"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Groups to synchronize"
+msgstr ""
+
+msgid "Geo|In sync"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|Not synced yet"
+msgstr ""
+
+msgid "Geo|Pending"
+msgstr ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Recheck"
+msgstr ""
+
+msgid "Geo|Recheck all projects"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Repository sync capacity"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all projects"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Select groups to replicate."
+msgstr ""
+
+msgid "Geo|Shards to synchronize"
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
+msgid "Geo|Unknown state"
+msgstr ""
+
+msgid "Geo|Verification capacity"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|You need a different license to use Geo replication"
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Git"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git strategy for pipelines"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitLab CI Linter has been moved"
+msgstr ""
+
+msgid "GitLab Geo"
+msgstr ""
+
+msgid "GitLab Group Runners can execute code for all the projects in this group."
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab single sign on URL"
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLab’s issue tracker"
+msgstr ""
+
+msgid "Gitaly"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go to"
+msgstr ""
+
+msgid "Go to %{link_to_google_takeout}."
+msgstr ""
+
+msgid "Google Code import"
+msgstr ""
+
+msgid "Google Takeout"
+msgstr ""
+
+msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group CI/CD settings"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group Runners"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group details"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group maintainers can register group runners in the %{link}"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Loading roadmap"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|Until %{dateWord}"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Customize your group badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about badges."
+msgstr ""
+
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+msgstr ""
+
+msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
+msgstr ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Create a project in this group."
+msgstr ""
+
+msgid "GroupsTree|Create a subgroup in this group."
+msgstr ""
+
+msgid "GroupsTree|Edit group"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave this group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Have your users email"
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help page"
+msgstr ""
+
+msgid "Help page text and support page url."
+msgstr ""
+
+msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide whitespace changes"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Client side evaluation"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Open in file view"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "Identity provider single sign on URL"
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr ""
+
+msgid "If disabled, the access level will depend on the user's permissions in the project."
+msgstr ""
+
+msgid "If enabled"
+msgstr ""
+
+msgid "If enabled, access to projects will be validated on an external service using their classification label."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you already have files you can push them using the %{link_to_cli} below."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import all compatible projects"
+msgstr ""
+
+msgid "Import all projects"
+msgstr ""
+
+msgid "Import all repositories"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import projects from Google Code"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "Improve Issue boards with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
+msgid "In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "Incompatible Project"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input your repository URL"
+msgstr ""
+
+msgid "Install GitLab Runner"
+msgstr ""
+
+msgid "Install Runner on Kubernetes"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Instance Statistics"
+msgstr ""
+
+msgid "Instance Statistics visibility"
+msgstr ""
+
+msgid "Instance does not support multiple Kubernetes clusters"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations Settings"
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Cycle Analytics"
+msgstr ""
+
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue board focus mode"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Job"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed in"
+msgstr ""
+
+msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration was not removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes configured"
+msgstr ""
+
+msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label lists show all issues with the selected label."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{name}"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
+msgstr ""
+
+msgid "Learn more about Kubernetes"
+msgstr ""
+
+msgid "Learn more about protected branches"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
+msgid "LicenseManagement|Approve license"
+msgstr ""
+
+msgid "LicenseManagement|Approve license?"
+msgstr ""
+
+msgid "LicenseManagement|Approved"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license?"
+msgstr ""
+
+msgid "LicenseManagement|Blacklisted"
+msgstr ""
+
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
+msgid "LicenseManagement|License"
+msgstr ""
+
+msgid "LicenseManagement|License Management"
+msgstr ""
+
+msgid "LicenseManagement|License details"
+msgstr ""
+
+msgid "LicenseManagement|License name"
+msgstr ""
+
+msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
+msgstr ""
+
+msgid "LicenseManagement|Packages"
+msgstr ""
+
+msgid "LicenseManagement|Remove license"
+msgstr ""
+
+msgid "LicenseManagement|Remove license?"
+msgstr ""
+
+msgid "LicenseManagement|Submit"
+msgstr ""
+
+msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
+msgstr ""
+
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseManagement|URL"
+msgstr ""
+
+msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LinkedIn"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "List Your Gitea Repositories"
+msgstr ""
+
+msgid "List available repositories"
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "List your GitHub repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked to current projects"
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make sure you're logged into the account that owns the projects you'd like to import."
+msgstr ""
+
+msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
+msgstr ""
+
+msgid "Manage Web IDE features"
+msgstr ""
+
+msgid "Manage access"
+msgstr ""
+
+msgid "Manage all notifications"
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a full email address"
+msgstr ""
+
+msgid "Map a Google Code user to a full name"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark todo as done"
+msgstr ""
+
+msgid "Markdown enabled"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
+msgid "Maven Metadata"
+msgstr ""
+
+msgid "Maven package"
+msgstr ""
+
+msgid "Max access level"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Median"
+msgstr ""
+
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Request:"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge requests"
+msgstr ""
+
+msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
+msgid "MergeRequests|Resolve this discussion in a new issue"
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|Toggle comments for this file"
+msgstr ""
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr ""
+
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Influx"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics|Business"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgstr ""
+
+msgid "Metrics|Environment"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgstr ""
+
+msgid "Metrics|Learn about environments"
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|Name"
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|No deployed environments"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|Query"
+msgstr ""
+
+msgid "Metrics|Response"
+msgstr ""
+
+msgid "Metrics|System"
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|Type"
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
+msgid "Milestone"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Mirror a repository"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror user"
+msgstr ""
+
+msgid "Mirrored repositories"
+msgstr ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
+msgid "Modal|Cancel"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More actions"
+msgstr ""
+
+msgid "More info"
+msgstr ""
+
+msgid "More information"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Multiple issue boards"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name your individual key via a title"
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Snippets"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No Label"
+msgstr ""
+
+msgid "No assignee"
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No container images stored for this project. Add one by following the instructions above."
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No issues for the selected time period."
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No merge requests for the selected time period."
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No packages stored for this project."
+msgstr ""
+
+msgid "No prioritised labels with such name or description"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No pushes for the selected time period."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No, directly import the existing email addresses and usernames."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "Not all comments are displayed because you're comparing two versions of the diff."
+msgstr ""
+
+msgid "Not all comments are displayed because you're viewing an old version of the diff."
+msgstr ""
+
+msgid "Not allowed to merge"
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not enough data"
+msgstr ""
+
+msgid "Not now"
+msgstr ""
+
+msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "Only admins"
+msgstr ""
+
+msgid "Only comments from the following commit are shown below"
+msgstr ""
+
+msgid "Only mirror protected branches"
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open in Xcode"
+msgstr ""
+
+msgid "Open projects"
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open source software to collaborate on code"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened MR"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Otherwise it is recommended you start with one of the options below."
+msgstr ""
+
+msgid "Outbound requests"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Package information"
+msgstr ""
+
+msgid "Package was removed"
+msgstr ""
+
+msgid "Packages"
+msgstr ""
+
+msgid "Pages"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
+
+msgid "Path, transfer, remove"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Paused Runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "Per job. If a job passes this threshold, it will be marked as failed"
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, or removing the group."
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline Health"
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline quota"
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines for last month"
+msgstr ""
+
+msgid "Pipelines for last week"
+msgstr ""
+
+msgid "Pipelines for last year"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|CI Lint"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgstr ""
+
+msgid "Pipelines|Get started with Pipelines"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|There are currently no %{scope} pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+msgstr ""
+
+msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Create for"
+msgstr ""
+
+msgid "Pipeline|Create pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Existing branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Search branches"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|all"
+msgstr ""
+
+msgid "Pipeline|success"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Please accept the Terms of Service before continuing."
+msgstr ""
+
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please solve the reCAPTCHA"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences|Navigation theme"
+msgstr ""
+
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Private - Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|Add status emoji"
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
+msgid "Profiles|Clear status"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Delete Account"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Delete your account?"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Website"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project avatar in repository: %{link}"
+msgstr ""
+
+msgid "Project details"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectLifecycle|Stage"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Customize your project badges."
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Learn more about badges."
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
+msgstr ""
+
+msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "PrometheusAlerts|Add alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Edit alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error creating alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error deleting alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error fetching alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error saving alert"
+msgstr ""
+
+msgid "PrometheusAlerts|No alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Operator"
+msgstr ""
+
+msgid "PrometheusAlerts|Threshold"
+msgstr ""
+
+msgid "PrometheusDashboard|Time"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration"
+msgstr ""
+
+msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
+msgstr ""
+
+msgid "PrometheusService|Common metrics"
+msgstr ""
+
+msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
+msgstr ""
+
+msgid "PrometheusService|Custom metrics"
+msgstr ""
+
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr ""
+
+msgid "PrometheusService|Finding custom metrics..."
+msgstr ""
+
+msgid "PrometheusService|Install Prometheus on clusters"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+msgstr ""
+
+msgid "PrometheusService|More information"
+msgstr ""
+
+msgid "PrometheusService|New metric"
+msgstr ""
+
+msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|Time-series monitoring service"
+msgstr ""
+
+msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
+msgstr ""
+
+msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
+msgstr ""
+
+msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote these project milestones into a group milestone."
+msgstr ""
+
+msgid "Promote to Group Milestone"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Environments"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "Protip:"
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Pseudonymizer data collection"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRule|Committer restriction"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
+
+msgid "Readme"
+msgstr ""
+
+msgid "Real-time features"
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Reference:"
+msgstr ""
+
+msgid "Refresh"
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Regenerate key"
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register and see your runners for this group."
+msgstr ""
+
+msgid "Register and see your runners for this project."
+msgstr ""
+
+msgid "Registry"
+msgstr ""
+
+msgid "Related Commits"
+msgstr ""
+
+msgid "Related Deployed Jobs"
+msgstr ""
+
+msgid "Related Issues"
+msgstr ""
+
+msgid "Related Jobs"
+msgstr ""
+
+msgid "Related Merge Requests"
+msgstr ""
+
+msgid "Related Merged Requests"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove Runner"
+msgstr ""
+
+msgid "Remove avatar"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
+msgid "Rename"
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Repair authentication"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{failedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|Class"
+msgstr ""
+
+msgid "Reports|Confidence"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository URL"
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirror"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Requests Profiles"
+msgstr ""
+
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
+msgid "Resolve all discussions in new issue"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve discussion"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal Variables"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
+msgid "Runner token"
+msgstr ""
+
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners API"
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, and even on your local machine."
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|You have used all your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML Single Sign On"
+msgstr ""
+
+msgid "SAML Single Sign On Settings"
+msgstr ""
+
+msgid "SAST"
+msgstr ""
+
+msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save variables"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scoped issue boards"
+msgstr ""
+
+msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or jump to…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in this group"
+msgstr ""
+
+msgid "SearchAutocomplete|in this project"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr ""
+
+msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgstr ""
+
+msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select a group to invite"
+msgstr ""
+
+msgid "Select a namespace to fork the project"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select an existing Kubernetes cluster or create a new one"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select branch/tag"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project and zone to choose machine type"
+msgstr ""
+
+msgid "Select project to choose zone"
+msgstr ""
+
+msgid "Select projects you want to import."
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Select the custom project template source group."
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Selective synchronization"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send usage data"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
+msgstr ""
+
+msgid "Session expiration, projects limit and attachment size."
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set instance-wide template repository"
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Sherlock Transactions"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show latest version of the diff"
+msgstr ""
+
+msgid "Show parent pages"
+msgstr ""
+
+msgid "Show parent subgroups"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|Change weight"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in to %{group_name}"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong when toggling the button"
+msgstr ""
+
+msgid "Something went wrong while closing the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while fetching %{listType} list"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the projects."
+msgstr ""
+
+msgid "Something went wrong while fetching the registry list."
+msgstr ""
+
+msgid "Something went wrong while reopening the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Sorry, no epics matched your search"
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "SortOptions|Access level, ascending"
+msgstr ""
+
+msgid "SortOptions|Access level, descending"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Milestone"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest joined"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source code"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Specific Runners"
+msgstr ""
+
+msgid "Specify an e-mail address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage & Commit"
+msgstr ""
+
+msgid "Stage all changes"
+msgstr ""
+
+msgid "Stage changes"
+msgstr ""
+
+msgid "Staged"
+msgstr ""
+
+msgid "Staged %{type}"
+msgstr ""
+
+msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start the Runner!"
+msgstr ""
+
+msgid "Start your trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Stop environment"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Sync information"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System header and footer:"
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "Tag (%{tag_count})"
+msgid_plural "Tags (%{tag_count})"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release notes"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag."
+msgstr ""
+
+msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Sort by"
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Test SAML SSO"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+msgid "Thanks! Don't show me this again"
+msgstr ""
+
+msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
+msgstr ""
+
+msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr ""
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The deployment of this job to %{environmentLink} did not succeed."
+msgstr ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr ""
+
+msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
+msgstr ""
+
+msgid "The phase of the development lifecycle."
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr ""
+
+msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
+msgstr ""
+
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr ""
+
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
+msgstr ""
+
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The tabs below will be removed in a future version"
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no merge requests to show"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
+
+msgid "There was an error adding a todo."
+msgstr ""
+
+msgid "There was an error deleting the todo."
+msgstr ""
+
+msgid "There was an error loading users activity calendar."
+msgstr ""
+
+msgid "There was an error saving your notification settings."
+msgstr ""
+
+msgid "There was an error subscribing to this label."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "They can be managed using the %{link}."
+msgstr ""
+
+msgid "Third party offers"
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
+msgstr ""
+
+msgid "This application was created by %{link_to_owner}."
+msgstr ""
+
+msgid "This application will be able to:"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This branch has changed since you started editing. Would you like to create a new branch?"
+msgstr ""
+
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This group"
+msgstr ""
+
+msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgstr ""
+
+msgid "This group does not provide any group Runners yet."
+msgstr ""
+
+msgid "This is a confidential issue."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is the author's first Merge Request to this project."
+msgstr ""
+
+msgid "This issue is confidential"
+msgstr ""
+
+msgid "This issue is confidential and locked."
+msgstr ""
+
+msgid "This issue is locked."
+msgstr ""
+
+msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "This job is the most recent deployment to %{link}."
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This option is disabled as you don't have write permissions for the current branch"
+msgstr ""
+
+msgid "This option is disabled while you still have unstaged changes"
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page will be removed in a future release."
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project does not belong to a group and can therefore not make use of group Runners."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "This source diff could not be displayed because it is too large."
+msgstr ""
+
+msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
+msgstr ""
+
+msgid "This will delete the custom metric, Are you sure?"
+msgstr ""
+
+msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time before enforced"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds ago"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip:"
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr ""
+
+msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
+msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr ""
+
+msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
+msgstr ""
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr ""
+
+msgid "To start serving your jobs you can add Runners to your group"
+msgstr ""
+
+msgid "To this GitLab instance"
+msgstr ""
+
+msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
+msgstr ""
+
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
+
+msgid "To widen your search, change or remove filters."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Todo"
+msgstr ""
+
+msgid "Todos"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle discussion"
+msgstr ""
+
+msgid "Toggle file browser"
+msgstr ""
+
+msgid "Toggle navigation"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: OFF"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: ON"
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Time"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track activity with Contribution Analytics."
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trigger"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Turn on Service Desk"
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to save your changes"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unresolve discussion"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
+msgid "Unstage all changes"
+msgstr ""
+
+msgid "Unstage changes"
+msgstr ""
+
+msgid "Unstaged"
+msgstr ""
+
+msgid "Unstaged %{type}"
+msgstr ""
+
+msgid "Unstaged and staged %{type}"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Upgrade your plan to activate Advanced Global Search."
+msgstr ""
+
+msgid "Upgrade your plan to activate Contribution Analytics."
+msgstr ""
+
+msgid "Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Upgrade your plan to activate Issue weight."
+msgstr ""
+
+msgid "Upgrade your plan to improve Issue boards."
+msgstr ""
+
+msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage ping is not enabled"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "Use <code>%{native_redirect_uri}</code> for local tests"
+msgstr ""
+
+msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
+msgstr ""
+
+msgid "Use group milestones to manage issues from multiple projects in the same milestone."
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use the following registration token during setup:"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "Used by members to sign in to your group in GitLab"
+msgstr ""
+
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Variables"
+msgstr ""
+
+msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification information"
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View epics list"
+msgstr ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View group labels"
+msgstr ""
+
+msgid "View issue"
+msgstr ""
+
+msgid "View it on GitLab"
+msgstr ""
+
+msgid "View jobs"
+msgstr ""
+
+msgid "View labels"
+msgstr ""
+
+msgid "View log"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr ""
+
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|It is recommended to install %{markdown} so that GFM features render locally:"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgstr ""
+
+msgid "WikiMarkdownDocs|documentation"
+msgstr ""
+
+msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgstr ""
+
+msgid "WikiNewPagePlaceholder|how-to-setup"
+msgstr ""
+
+msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiNewPageTitle|New Wiki Page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgstr ""
+
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPageConflictMessage|the page"
+msgstr ""
+
+msgid "WikiPageCreate|Create %{page_title}"
+msgstr ""
+
+msgid "WikiPageEdit|Update %{page_title}"
+msgstr ""
+
+msgid "WikiPage|Page slug"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wiki|Create Page"
+msgstr ""
+
+msgid "Wiki|Create page"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|More Pages"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, let me map Google Code users to full names or GitLab users."
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
+msgstr ""
+
+msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You can %{linkStart}view the blob%{linkEnd} instead."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
+msgid "You can only edit files when you are on a branch"
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
+msgstr ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+msgstr ""
+
+msgid "You cannot write to this read-only GitLab instance."
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You must accept our Terms of Service and privacy policy in order to register an account"
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're receiving this email because %{reason}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your Todos"
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your comment will not be visible to the public."
+msgstr ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your projects"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "among other things"
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{namespace} is affected by %{vulnerability}."
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr ""
+
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr ""
+
+msgid "ciReport|(is loading)"
+msgstr ""
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr ""
+
+msgid "ciReport|Class"
+msgstr ""
+
+msgid "ciReport|Code quality"
+msgstr ""
+
+msgid "ciReport|Confidence"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Description"
+msgstr ""
+
+msgid "ciReport|Dismiss vulnerability"
+msgstr ""
+
+msgid "ciReport|Dismissed by"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|File"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Identifiers"
+msgstr ""
+
+msgid "ciReport|Instances"
+msgstr ""
+
+msgid "ciReport|Learn more about interacting with security reports (Alpha)."
+msgstr ""
+
+msgid "ciReport|License management detected %d license for the source branch only"
+msgid_plural "ciReport|License management detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected %d new license"
+msgid_plural "ciReport|License management detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected no licenses for the source branch only"
+msgstr ""
+
+msgid "ciReport|License management detected no new licenses"
+msgstr ""
+
+msgid "ciReport|Links"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|Method"
+msgstr ""
+
+msgid "ciReport|Namespace"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No changes to performance metrics"
+msgstr ""
+
+msgid "ciReport|Performance metrics"
+msgstr ""
+
+msgid "ciReport|Revert dismissal"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Severity"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error loading DAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading SAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading container scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error loading dependency scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "ciReport|on pipeline"
+msgstr ""
+
+msgid "command line instructions"
+msgstr ""
+
+msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgstr ""
+
+msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
+msgstr ""
+
+msgid "connecting"
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "customize"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "deploy token"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "here"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "importing"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "issue boards"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "license management"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|Add approval"
+msgstr ""
+
+msgid "mrWidget|Allows commits from members who can merge to the target branch"
+msgstr ""
+
+msgid "mrWidget|An error occured while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Cancel automatic merge"
+msgstr ""
+
+msgid "mrWidget|Check out branch"
+msgstr ""
+
+msgid "mrWidget|Checking ability to merge automatically"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes"
+msgstr ""
+
+msgid "mrWidget|Create an issue to resolve them later"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mentions"
+msgstr ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge request approved"
+msgstr ""
+
+msgid "mrWidget|Merge request approved; you can approve additionally"
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|No Approval required"
+msgstr ""
+
+msgid "mrWidget|No Approval required; you can still approve"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove Source Branch"
+msgstr ""
+
+msgid "mrWidget|Remove source branch"
+msgstr ""
+
+msgid "mrWidget|Remove your approval"
+msgstr ""
+
+msgid "mrWidget|Request to merge"
+msgstr ""
+
+msgid "mrWidget|Requires 1 more approval"
+msgid_plural "mrWidget|Requires %d more approvals"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Requires 1 more approval by"
+msgid_plural "mrWidget|Requires %d more approvals by"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Set by"
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The changes will be merged into"
+msgstr ""
+
+msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+msgstr ""
+
+msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
+msgstr ""
+
+msgid "mrWidget|The source branch has been removed"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will be removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will not be removed"
+msgstr ""
+
+msgid "mrWidget|There are merge conflicts"
+msgstr ""
+
+msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|This merge request is in the process of being merged"
+msgstr ""
+
+msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr ""
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|You can remove source branch now"
+msgstr ""
+
+msgid "mrWidget|branch does not exist."
+msgstr ""
+
+msgid "mrWidget|command line"
+msgstr ""
+
+msgid "mrWidget|into"
+msgstr ""
+
+msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "notification emails"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "password"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "source"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time spent."
+msgstr ""
+
+msgid "started"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "toggle collapse"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "within %d minute "
+msgid_plural "within %d minutes "
+msgstr[0] ""
+msgstr[1] ""
+
diff --git a/locale/en/gitlab.po b/locale/en/gitlab.po
index b50685514e1..5e14e94e6fc 100644
--- a/locale/en/gitlab.po
+++ b/locale/en/gitlab.po
@@ -882,9 +882,6 @@ msgstr ""
msgid "Set up CI"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up auto deploy"
msgstr ""
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index 456235b2fa6..aed12521a79 100644
--- a/locale/eo/gitlab.po
+++ b/locale/eo/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Esperanto\n"
"Language: eo_UY\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: eo\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:32\n"
+"PO-Revision-Date: 2018-11-19 17:22\n"
msgid " Status"
msgstr ""
@@ -31,6 +31,14 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -46,6 +54,11 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -91,11 +104,6 @@ msgid_plural "%d unstaged changes"
msgstr[0] ""
msgstr[1] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] "%s enmetado estis transsaltita, por ne troÅarÄi la sistemon."
@@ -104,17 +112,31 @@ msgstr[1] "%s enmetadoj estis transsaltitaj, por ne troÅarÄi la sistemon."
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] ""
msgstr[1] ""
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -124,6 +146,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -139,23 +164,12 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr ""
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr ""
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -167,27 +181,13 @@ msgstr ""
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -314,6 +314,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr "Aro da diagramoj pri la seninterrompa integrado"
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -356,13 +365,10 @@ msgstr ""
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
+msgid "Access expiration date"
msgstr ""
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr ""
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -392,27 +398,48 @@ msgstr "Aldoni gvidliniojn por kontribuado"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
-msgstr "Aldoni rajtigilon"
+msgid "Add Kubernetes cluster"
+msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr "Aldoni novan dosierujon"
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -422,6 +449,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -455,9 +485,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -494,12 +521,17 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr ""
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "All"
msgstr ""
@@ -515,6 +547,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -524,6 +559,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -539,6 +580,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -560,7 +604,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -584,6 +628,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -596,6 +646,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -608,6 +661,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -635,6 +691,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -677,12 +736,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr ""
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -701,7 +766,7 @@ msgstr ""
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -719,9 +784,15 @@ msgstr ""
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Ĉu vi certe volas forigi ĉi tiun ĉenstablan planon?"
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -740,6 +811,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -878,6 +952,9 @@ msgstr ""
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -914,9 +991,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -995,6 +1069,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1285,6 +1368,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1315,9 +1401,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1372,7 +1455,7 @@ msgstr "Diagramoj"
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1399,6 +1482,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1429,6 +1518,9 @@ msgstr "nuligita"
msgid "CiStatusLabel|created"
msgstr "kreita"
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr "malsukcesa"
@@ -1447,6 +1539,9 @@ msgstr "okazonta"
msgid "CiStatusLabel|skipped"
msgstr "transsaltita"
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr "atendanta manan agon"
@@ -1459,6 +1554,9 @@ msgstr "nuligita"
msgid "CiStatusText|created"
msgstr "kreita"
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr "malsukcesa"
@@ -1513,10 +1611,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1561,6 +1659,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1573,12 +1674,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1609,10 +1722,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1639,6 +1752,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1675,6 +1794,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1705,9 +1827,6 @@ msgstr ""
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1729,25 +1848,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster details"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster health"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1759,7 +1872,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1768,16 +1881,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1795,9 +1905,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1825,6 +1932,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1837,6 +1947,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1867,9 +1980,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1909,13 +2019,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -1933,6 +2040,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -1951,9 +2061,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -1963,6 +2070,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -1972,12 +2082,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2012,6 +2128,9 @@ msgstr "Enmeti"
msgid "CommitMessage|Add %{file_name}"
msgstr "Aldoni „%{file_name}“"
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr "Enmetadoj"
@@ -2084,7 +2203,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2093,10 +2212,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2186,6 +2305,9 @@ msgstr ""
msgid "Contribution guide"
msgstr "Gvidlinioj por kontribuado"
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2219,6 +2341,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2240,15 +2374,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2324,8 +2470,8 @@ msgstr "Krei novan…"
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
-msgstr "Disbranĉigi"
+msgid "Create your first page"
+msgstr ""
msgid "CreateTag|Tag"
msgstr "Etikedo"
@@ -2375,6 +2521,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr "Propraj sciigaj eventoj"
@@ -2393,6 +2542,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr "Cikla analizo"
@@ -2444,6 +2596,9 @@ msgstr ""
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2456,6 +2611,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Difini propran Åablonon, uzante la sintakson de Cron"
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr "Forigi"
@@ -2465,6 +2635,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2602,6 +2775,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2626,6 +2805,12 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2647,12 +2832,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2668,6 +2868,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2749,7 +2952,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2794,9 +2997,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2809,6 +3009,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2911,7 +3117,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -2944,10 +3150,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3058,6 +3264,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3112,6 +3324,12 @@ msgstr "Ne eblas ÅanÄi la posedanton"
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3121,6 +3339,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "Ne eblas forigi la ĉenstablan planon"
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3130,6 +3351,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3139,6 +3435,9 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr "Dosieroj"
@@ -3151,9 +3450,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr "Filtri per mesaÄo"
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr "Trovi per dosierindiko"
@@ -3169,6 +3477,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3181,7 +3492,7 @@ msgstr "alpuÅita de"
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3220,17 +3531,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] "Disbranĉigo"
-msgstr[1] "Disbranĉigoj"
-
msgid "ForkedFromProjectPath|Forked from"
msgstr "Disbranĉigita el"
@@ -3246,6 +3558,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3288,6 +3603,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3462,10 +3780,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3474,6 +3804,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3495,7 +3828,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3507,6 +3840,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3516,19 +3852,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3546,6 +3888,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3558,9 +3906,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3570,9 +3936,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3639,12 +4002,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr "Al via disbranĉigo"
-
-msgid "GoToYourFork|Fork"
-msgstr "Disbranĉigo"
-
msgid "Google Code import"
msgstr ""
@@ -3675,9 +4032,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3687,6 +4056,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3705,13 +4077,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3738,9 +4110,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3798,6 +4167,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3810,19 +4182,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -3864,6 +4236,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4028,6 +4403,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4096,6 +4474,12 @@ msgstr "Intervala Åablono"
msgid "Introducing Cycle Analytics"
msgstr "Ni prezentas al vi la ciklan analizon"
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4120,6 +4504,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4135,9 +4549,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4174,7 +4585,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4192,12 +4603,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4270,6 +4675,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] "La lasta %d tago"
@@ -4281,12 +4689,18 @@ msgstr "Lasta ĉenstablo"
msgid "Last commit"
msgstr "Lasta enmetado"
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4335,6 +4749,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4344,6 +4767,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4353,6 +4779,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4362,6 +4791,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4374,9 +4806,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4403,6 +4841,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4448,6 +4889,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4517,13 +4961,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4535,6 +5009,12 @@ msgstr ""
msgid "Median"
msgstr "Mediano"
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -4568,6 +5048,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4577,9 +5072,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4589,6 +5081,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4604,6 +5102,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4820,6 +5321,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -4939,6 +5443,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -4948,9 +5458,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -4960,6 +5467,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -4987,6 +5497,9 @@ msgstr ""
msgid "No repository"
msgstr "Ne estas deponejo"
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr "Ne estas planoj"
@@ -5023,6 +5536,9 @@ msgstr ""
msgid "Not enough data"
msgstr "Ne estas sufiĉe da datenoj"
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -5041,6 +5557,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr "Sciigaj eventoj"
@@ -5113,9 +5641,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5142,9 +5667,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5166,6 +5688,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5190,6 +5715,21 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5256,6 +5796,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5283,15 +5826,15 @@ msgstr ""
msgid "Permissions"
msgstr ""
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
msgid "Personal Access Token"
msgstr ""
msgid "Pipeline"
msgstr "Ĉenstablo"
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
-msgstr ""
-
msgid "Pipeline Health"
msgstr "Stato"
@@ -5409,15 +5952,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5427,6 +5979,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5454,12 +6012,6 @@ msgstr "kun etapoj"
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5469,12 +6021,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5487,6 +6045,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5499,9 +6060,18 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5547,15 +6117,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5568,39 +6153,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -5610,6 +6276,15 @@ msgstr ""
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5646,6 +6321,9 @@ msgstr "La projekto „%{project_name}“ estis sukcese Äisdatigita."
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr "Ĉiu uzanto devas akiri propran atingon al la projekto."
@@ -5673,6 +6351,9 @@ msgstr "La elporto de la projekto komenciÄis. Vi ricevos ligilon per retpoÅto
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -5700,6 +6381,27 @@ msgstr "Neniam"
msgid "ProjectLifecycle|Stage"
msgstr "Etapo"
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5742,6 +6444,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5811,9 +6516,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6006,6 +6708,12 @@ msgstr "LeguMin"
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6068,12 +6776,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr "Forigi la projekton"
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6083,6 +6800,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6092,18 +6812,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6116,6 +6851,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6149,10 +6887,10 @@ msgstr "Peti atingeblon"
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6170,9 +6908,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6223,9 +6973,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6235,6 +7000,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6259,6 +7030,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6283,6 +7057,9 @@ msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Konservi ĉenstablan planon"
@@ -6337,15 +7114,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6370,27 +7156,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard"
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6408,9 +7222,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr "Elektu formaton de arkivo"
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr "Elektu horzonon"
@@ -6441,6 +7261,9 @@ msgstr ""
msgid "Select target branch"
msgstr "Elektu celan branĉon"
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6453,6 +7276,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6477,6 +7303,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Kreu pasvorton por via konto por ebligi al vi eltiri kaj alpuÅi per %{protocol}."
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6495,8 +7324,11 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr "Agordi „Koding“"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
@@ -6507,13 +7339,31 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "kreos pasvorton"
-msgid "Settings"
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
msgstr ""
msgid "Share"
@@ -6525,6 +7375,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6608,12 +7461,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6641,9 +7500,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6656,12 +7521,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -6692,6 +7569,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6722,6 +7602,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6752,6 +7635,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6827,9 +7713,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr "Kreu %{new_merge_request} kun ĉi tiuj ÅanÄoj"
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6842,6 +7740,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6851,6 +7752,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6860,9 +7764,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6875,6 +7785,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Iri al branĉo/etikedo"
@@ -6893,6 +7809,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -6997,6 +7916,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7045,12 +7967,6 @@ msgstr "La etapo de la problemo montras kiom la tempo pasas de la kreado de prob
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7099,9 +8015,6 @@ msgstr "La etapo de la kontrolo montras la tempon de la kreado de la peto pri ku
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "La etapo de preparo por eldono montras la tempon inter la aplikado de la peto pri kunfando kaj la disponigado de la kodo en la publika versio. La datenoj aldoniÄos aÅ­tomate post kiam vi faros la unuan disponigadon en la publika versio."
@@ -7111,21 +8024,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr "La etapo de testado montras kiom da tempo necesas al „GitLab CI“ por plenumi ĉiujn ĉenstablojn por la rilata peto pri kunfando. La datenoj aldoniÄos aÅ­tomate post kiam via unua ĉenstablo finiÄos."
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr "La tempo, kiu estas necesa por ĉiu dateno kolektita de la etapo."
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7135,6 +8042,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "La valoro, kiu troviÄas en la mezo de aro da rigardataj valoroj. Ekzemple: inter 3, 5 kaj 9, la mediano estas 5. Inter 3, 5, 7 kaj 8, la mediano estas (5+7)/2 = 6."
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7144,7 +8054,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7192,10 +8108,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7216,6 +8135,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7255,7 +8177,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7276,6 +8201,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Ĉi tiu signifas, ke vi ne povos alpuÅi kodon, antaÅ­ ol vi kreos malplenan deponejon aÅ­ enportos jam ekzistantan."
@@ -7300,6 +8228,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7309,6 +8240,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7336,9 +8273,15 @@ msgstr "Tempo antaÅ­ problemo estas planita por ellabori"
msgid "Time before an issue starts implementation"
msgstr "Tempo antaÅ­ la komenco de laboro super problemo"
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr "Tempo inter la kreado de poeto pri kunfando kaj Äia aplikado/fermado"
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7529,12 +8472,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7550,6 +8505,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7562,12 +8520,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7577,9 +8538,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7595,6 +8562,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7610,6 +8580,9 @@ msgstr "Totala tempo por la testado de ĉiuj enmetadoj/kunfandoj"
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7619,6 +8592,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7637,24 +8613,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7670,6 +8664,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7703,13 +8703,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7739,15 +8742,15 @@ msgstr "AlÅuti novan dosieron"
msgid "Upload file"
msgstr "AlÅuti dosieron"
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr "alklaku por alÅuti"
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7775,6 +8778,9 @@ msgstr "Uzi vian Äeneralan agordon pri la sciigoj"
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7784,10 +8790,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7814,6 +8862,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7847,9 +8904,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7868,6 +8931,36 @@ msgstr "Publika"
msgid "VisibilityLevel|Unknown"
msgstr "Nekonata"
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Ĉu vi volas vidi la datenojn? Bonvolu peti atingeblon de administranto."
@@ -7907,6 +9000,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8057,6 +9156,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8075,9 +9177,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8087,9 +9186,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8111,12 +9207,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8138,9 +9240,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr "Oni devas ensaluti por steligi projekton"
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8150,6 +9249,12 @@ msgstr ""
msgid "You need permission."
msgstr "VI bezonas permeson."
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr "VI ne ricevos sciigojn per retpoÅto"
@@ -8216,6 +9321,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8237,16 +9345,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "assign yourself"
msgstr ""
@@ -8274,61 +9372,78 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8361,9 +9476,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8386,6 +9498,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8404,13 +9519,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8419,9 +9528,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8452,9 +9558,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8466,9 +9569,6 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8498,25 +9598,17 @@ msgstr[1] "tagoj"
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
-
msgid "disabled"
msgstr ""
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "enabled"
msgstr ""
@@ -8526,6 +9618,12 @@ msgstr ""
msgid "for this project"
msgstr ""
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -8555,6 +9653,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8783,6 +9884,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8801,6 +9905,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr "novan peton pri kunfando"
@@ -8829,6 +9936,11 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "remaining"
msgstr ""
@@ -8841,6 +9953,11 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "source"
msgstr ""
@@ -8856,6 +9973,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index eba59fdd3d8..d838e5e2418 100644
--- a/locale/es/gitlab.po
+++ b/locale/es/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Spanish\n"
"Language: es_ES\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: es-ES\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:31\n"
+"PO-Revision-Date: 2018-11-19 17:19\n"
msgid " Status"
msgstr ""
@@ -31,6 +31,14 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -46,6 +54,11 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -91,11 +104,6 @@ msgid_plural "%d unstaged changes"
msgstr[0] ""
msgstr[1] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] "%s cambio adicional ha sido omitido para evitar problemas de rendimiento."
@@ -104,17 +112,31 @@ msgstr[1] "%s cambios adicionales han sido omitidos para evitar problemas de ren
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] "%{count} participante"
msgstr[1] "%{count} participantes"
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -124,6 +146,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -139,23 +164,12 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{number_commits_behind} commits detrás de %{default_branch}, %{number_commits_ahead} commits por delante"
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr "%{number_of_failures} de %{maximum_failures} intentos fallidos. GitLab permitirá el acceso en el siguiente intento."
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr "%{number_of_failures} de %{maximum_failures} intentos fallidos. GitLab no reintentará automáticamente. Debe reinicializar la información de almacenamiento cuando el problema sea solventado."
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] "%{storage_name}: intento de acceso fallido al almacenamiento en host:"
-msgstr[1] "%{storage_name}: %{failed_attempts} intentos de acceso fallido al almacenamiento:"
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -167,27 +181,13 @@ msgstr "%{text} esta disponible"
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -314,6 +314,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr "Una colección de gráficos sobre Integración Continua"
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -356,13 +365,10 @@ msgstr "Tokens de acceso"
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
-msgstr ""
-
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgid "Access expiration date"
msgstr ""
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -392,27 +398,48 @@ msgstr "Agregar guía de contribución"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
-msgstr "Agregar Licencia"
+msgid "Add Kubernetes cluster"
+msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr "Agregar nuevo directorio"
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -422,6 +449,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -455,9 +485,6 @@ msgstr "Error al detener trabajos"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr "Página de estado"
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -494,12 +521,17 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr "Configuración avanzada"
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "All"
msgstr "Todos"
@@ -515,6 +547,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -524,6 +559,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -539,6 +580,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -560,7 +604,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -584,6 +628,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "Ha ocurrido un error visualizando el blob"
@@ -596,6 +646,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -608,6 +661,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Se produjo un error al obtener datos de la barra lateral"
@@ -635,6 +691,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -677,12 +736,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr "Se produjo un error. Por favor inténtelo de nuevo."
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -701,7 +766,7 @@ msgstr "Apariencia"
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -719,9 +784,15 @@ msgstr "Abril"
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "¿Estás seguro que deseas eliminar esta programación del pipeline?"
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -740,6 +811,9 @@ msgstr "¿Está seguro que desea reinicializar el token de registro?"
msgid "Are you sure you want to reset the health check token?"
msgstr "¿Está seguro que desea reinicializar el token de Verificación de Estado?"
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -878,6 +952,9 @@ msgstr "Automáticamente construirán, probarán y desplegarán su aplicación c
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "Más información en %{link_to_documentation}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -914,9 +991,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -995,6 +1069,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr "Iniciar con el commit seleccionado"
@@ -1285,6 +1368,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1315,9 +1401,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1372,7 +1455,7 @@ msgstr "Gráficos"
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1399,6 +1482,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1429,6 +1518,9 @@ msgstr "cancelado"
msgid "CiStatusLabel|created"
msgstr "creado"
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr "fallido"
@@ -1447,6 +1539,9 @@ msgstr "pendiente"
msgid "CiStatusLabel|skipped"
msgstr "omitido"
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr "esperando acción manual"
@@ -1459,6 +1554,9 @@ msgstr "cancelado"
msgid "CiStatusText|created"
msgstr "creado"
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr "fallado"
@@ -1513,10 +1611,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1561,6 +1659,9 @@ msgstr ""
msgid "Close"
msgstr "Cerrar"
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1573,12 +1674,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1609,10 +1722,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1639,6 +1752,12 @@ msgstr "Crear cluster de Kubernetes"
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1675,6 +1794,9 @@ msgstr "Google Kubernetes Engine"
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr "Proyecto Google Kubernetes Engine"
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
@@ -1705,9 +1827,6 @@ msgstr "Instalar"
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr "Instalado"
@@ -1729,6 +1848,12 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr "cluster de Kubernetes"
@@ -1738,18 +1863,6 @@ msgstr "Detalles del cluster de Kubernetes"
msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration"
-msgstr "Integración de cluster de Kubernetes"
-
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
-msgstr ""
-
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
msgstr ""
@@ -1759,7 +1872,7 @@ msgstr "Nombre de cluster de Kubernetes"
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1768,16 +1881,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
-msgstr "Conozca más sobre los entornos"
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1795,9 +1905,6 @@ msgstr "Administre su cluster de Kubernetes visitando %{link_gke}"
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1825,6 +1932,9 @@ msgstr "Asegúrese de que su cuenta de Google cumpla con los siguientes requisit
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1837,6 +1947,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1867,9 +1980,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1909,13 +2019,10 @@ msgstr "Algo salió mal durante la instalación de %{title}"
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -1933,6 +2040,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Su cuenta debe tener %{link_to_kubernetes_engine}"
@@ -1951,9 +2061,6 @@ msgstr "documentación"
msgid "ClusterIntegration|help page"
msgstr "página de ayuda"
-msgid "ClusterIntegration|installing applications"
-msgstr "Instalando aplicaciones"
-
msgid "ClusterIntegration|meets the requirements"
msgstr "cumple con los requisitos"
@@ -1963,6 +2070,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -1972,12 +2082,18 @@ msgstr "Contraer"
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr "Comentarios"
@@ -2012,6 +2128,9 @@ msgstr "Cambio"
msgid "CommitMessage|Add %{file_name}"
msgstr "Agregar %{file_name}"
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr "Cambios"
@@ -2084,7 +2203,7 @@ msgstr "Confidencialidad"
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2093,10 +2212,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2186,6 +2305,9 @@ msgstr ""
msgid "Contribution guide"
msgstr "Guía de contribución"
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2219,6 +2341,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2240,15 +2374,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr "Crear"
@@ -2324,8 +2470,8 @@ msgstr "Crear nuevo..."
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
-msgstr "Bifurcar"
+msgid "Create your first page"
+msgstr ""
msgid "CreateTag|Tag"
msgstr "Etiqueta"
@@ -2375,6 +2521,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr "Eventos de notificaciones personalizadas"
@@ -2393,6 +2542,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr ""
@@ -2444,6 +2596,9 @@ msgstr "Diciembre"
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2456,6 +2611,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Definir un patrón personalizado con la sintaxis de cron"
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr "Eliminar"
@@ -2465,6 +2635,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2602,6 +2775,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2626,6 +2805,12 @@ msgstr "Detalles"
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2647,12 +2832,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2668,6 +2868,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2749,7 +2952,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2794,9 +2997,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2809,6 +3009,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2911,8 +3117,8 @@ msgstr ""
msgid "Environments|Updated"
msgstr "Actualizado"
-msgid "Environments|You don't have any environments right now."
-msgstr "No tiene ningún entorno en este momento."
+msgid "Environments|You don't have any environments right now"
+msgstr ""
msgid "Environments|protected"
msgstr ""
@@ -2944,10 +3150,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3058,6 +3264,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3112,6 +3324,12 @@ msgstr "Error al cambiar el propietario"
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3121,6 +3339,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "Error al eliminar la programación del pipeline"
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3130,6 +3351,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3139,6 +3435,9 @@ msgstr "Febrero"
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr "Archivos"
@@ -3151,9 +3450,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr "Filtrar por mensaje del cambio"
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr "Buscar por ruta"
@@ -3169,6 +3477,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3181,7 +3492,7 @@ msgstr "enviado por"
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3220,17 +3531,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] "Bifurcación"
-msgstr[1] "Bifurcaciones"
-
msgid "ForkedFromProjectPath|Forked from"
msgstr "Bifurcado de"
@@ -3246,6 +3558,9 @@ msgstr "Formato"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3288,6 +3603,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3462,10 +3780,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3474,6 +3804,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3495,7 +3828,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3507,6 +3840,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3516,19 +3852,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3546,6 +3888,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3558,9 +3906,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3570,9 +3936,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3639,12 +4002,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr "Ir a tu bifurcación"
-
-msgid "GoToYourFork|Fork"
-msgstr "Bifurcación"
-
msgid "Google Code import"
msgstr ""
@@ -3675,9 +4032,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3687,6 +4056,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3705,13 +4077,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3738,9 +4110,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Prevenir que se comparta un proyecto de %{group} con otros grupos"
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3798,6 +4167,9 @@ msgstr "No se encuentran grupos"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr "Crear un proyecto en este grupo."
@@ -3810,20 +4182,20 @@ msgstr "Editar grupo"
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr "No pudiste dejar el grupo. Por favor, asegúrate que no seas el único propietario."
-msgid "GroupsTree|Filter by name..."
-msgstr "Filtrar por nombre..."
-
msgid "GroupsTree|Leave this group"
msgstr "Dejar este grupo"
msgid "GroupsTree|Loading groups"
msgstr "Cargando grupos"
-msgid "GroupsTree|Sorry, no groups matched your search"
-msgstr "Lo sentimos, no existen grupos que coincidan con su búsqueda"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
-msgstr "Lo sentimos, no existen grupos ni proyectos que coincidan con su búsqueda"
+msgid "GroupsTree|Search by name"
+msgstr ""
msgid "Have your users email"
msgstr ""
@@ -3864,6 +4236,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4028,6 +4403,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4096,6 +4474,12 @@ msgstr "Patrón de intervalo"
msgid "Introducing Cycle Analytics"
msgstr "Introducción a Cycle Analytics"
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4120,6 +4504,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4135,9 +4549,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4174,7 +4585,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4192,12 +4603,6 @@ msgstr ""
msgid "June"
msgstr "Junio"
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4270,6 +4675,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] "Último %d día"
@@ -4281,12 +4689,18 @@ msgstr "Último Pipeline"
msgid "Last commit"
msgstr "Último cambio"
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr "Última edición por %{name}"
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr "Última actualización"
@@ -4335,6 +4749,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4344,6 +4767,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4353,6 +4779,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4362,6 +4791,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4374,9 +4806,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4403,6 +4841,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4448,6 +4889,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4517,13 +4961,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4535,6 +5009,12 @@ msgstr ""
msgid "Median"
msgstr "Mediana"
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr "Miembros"
@@ -4568,6 +5048,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4577,9 +5072,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4589,6 +5081,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4604,6 +5102,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4820,6 +5321,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -4939,6 +5443,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -4948,9 +5458,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -4960,6 +5467,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -4987,6 +5497,9 @@ msgstr ""
msgid "No repository"
msgstr "No hay repositorio"
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr "No hay programaciones"
@@ -5023,6 +5536,9 @@ msgstr ""
msgid "Not enough data"
msgstr "No hay suficientes datos"
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -5041,6 +5557,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr "Eventos de notificación"
@@ -5113,9 +5641,6 @@ msgstr ""
msgid "November"
msgstr "Noviembre"
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5142,9 +5667,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5166,6 +5688,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5190,6 +5715,21 @@ msgstr "Abre en una nueva ventana"
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5256,6 +5796,9 @@ msgstr "Contraseña"
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5283,15 +5826,15 @@ msgstr ""
msgid "Permissions"
msgstr ""
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
msgid "Personal Access Token"
msgstr ""
msgid "Pipeline"
msgstr "Pipeline"
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
-msgstr ""
-
msgid "Pipeline Health"
msgstr "Estado del Pipeline"
@@ -5409,15 +5952,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5427,6 +5979,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5454,12 +6012,6 @@ msgstr "con etapas"
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5469,12 +6021,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5487,6 +6045,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5499,9 +6060,18 @@ msgstr "Preferencias"
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5547,15 +6117,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5568,39 +6153,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr "Contraseña inválida"
msgid "Profiles|Invalid username"
msgstr "Nombre de usuario inválido"
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Escribe tu %{confirmationValue} para confirmar:"
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr "No tienes acceso para eliminar este usuario."
@@ -5610,6 +6276,15 @@ msgstr "Debes transferir o eliminar estos grupos antes de que puedas eliminar tu
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "Actualmente su cuenta es propietaria de estos grupos:"
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5646,6 +6321,9 @@ msgstr "Proyecto ‘%{project_name}’ fue actualizado satisfactoriamente."
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr "El acceso al proyecto debe concederse explícitamente a cada usuario."
@@ -5673,6 +6351,9 @@ msgstr "Se inició la exportación del proyecto. Se enviará un enlace de descar
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "Suscribirse"
@@ -5700,6 +6381,27 @@ msgstr "Nunca"
msgid "ProjectLifecycle|Stage"
msgstr "Etapa"
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5742,6 +6444,9 @@ msgstr "Proyectos"
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5811,9 +6516,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr "De manera predeterminada, Prometheus escucha en 'http://localhost:9090'. No se recomienda cambiar la dirección y el puerto predeterminados, ya que esto podría afectar o entrar en conflicto con otros servicios que se ejecutan en el servidor de GitLab."
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6006,6 +6708,12 @@ msgstr "Léeme"
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6068,12 +6776,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr "Eliminar proyecto"
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6083,6 +6800,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6092,18 +6812,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6116,6 +6851,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6149,10 +6887,10 @@ msgstr "Solicitar acceso"
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6170,9 +6908,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6223,9 +6973,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6235,6 +7000,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6259,6 +7030,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6283,6 +7057,9 @@ msgstr ""
msgid "Save changes"
msgstr "Guardar los cambios"
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Guardar programación del pipeline"
@@ -6337,15 +7114,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6370,13 +7156,7 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
-msgstr "Segundos antes de reinicializar información de fallas"
-
-msgid "Seconds to wait for a storage access attempt"
-msgstr "Segundos a esperar para intentar acceder al almacenamiento"
-
-msgid "Secret:"
+msgid "Secret"
msgstr ""
msgid "Security"
@@ -6385,12 +7165,46 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6408,9 +7222,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr "Seleccionar formato de archivo"
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr "Selecciona una zona horaria"
@@ -6441,6 +7261,9 @@ msgstr ""
msgid "Select target branch"
msgstr "Selecciona una rama de destino"
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6453,6 +7276,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6477,6 +7303,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Establezca una contraseña en su cuenta para actualizar o enviar a través de %{protocol}."
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6495,8 +7324,11 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr "Configurar Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
@@ -6507,15 +7339,33 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "establecer una contraseña"
-msgid "Settings"
-msgstr "Configuración"
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
msgstr ""
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr "Configuración"
+
msgid "Share"
msgstr ""
@@ -6525,6 +7375,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6608,12 +7461,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6641,9 +7500,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6656,12 +7521,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr "Ordenar por"
@@ -6692,6 +7569,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6722,6 +7602,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6752,6 +7635,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6827,9 +7713,21 @@ msgstr "Proyectos favoritos"
msgid "Start a %{new_merge_request} with these changes"
msgstr "Iniciar una %{new_merge_request} con estos cambios"
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6842,6 +7740,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6851,6 +7752,9 @@ msgstr ""
msgid "Stopped"
msgstr "Detenido"
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6860,9 +7764,15 @@ msgstr ""
msgid "Subgroups"
msgstr "Sub-grupos"
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6875,6 +7785,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Cambiar rama/etiqueta"
@@ -6893,6 +7809,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -6997,6 +7916,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7045,12 +7967,6 @@ msgstr "La etapa de incidencia muestra el tiempo que toma desde la creación de
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7099,9 +8015,6 @@ msgstr "La etapa de revisión muestra el tiempo desde la creación de la solicit
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "La etapa de puesta en escena muestra el tiempo entre la fusión y el despliegue de código en el entorno de producción. Los datos se añadirán automáticamente una vez que se despliega a producción por primera vez."
@@ -7111,21 +8024,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr "La etapa de pruebas muestra el tiempo que GitLab CI toma para ejecutar cada pipeline para la solicitud de fusión relacionada. Los datos se añadirán automáticamente luego de que el primer pipeline termine de ejecutarse."
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr "El tiempo utilizado por cada entrada de datos obtenido por esa etapa."
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7135,6 +8042,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "El valor en el punto medio de una serie de valores observados. Por ejemplo, entre 3, 5, 9, la mediana es 5. Entre 3, 5, 7, 8, la mediana es (5 + 7) / 2 = 6."
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7144,7 +8054,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7192,10 +8108,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7216,6 +8135,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7255,7 +8177,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7276,6 +8201,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Esto significa que no puede enviar código hasta que cree un repositorio vacío o importe uno existente."
@@ -7300,6 +8228,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7309,6 +8240,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7336,9 +8273,15 @@ msgstr "Tiempo antes de que una incidencia sea programada"
msgid "Time before an issue starts implementation"
msgstr "Tiempo antes de que empieze la implementación de una incidencia"
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr "Tiempo entre la creación de la solicitud de fusión y la integración o cierre de ésta"
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7529,12 +8472,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7550,6 +8505,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7562,12 +8520,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7577,9 +8538,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7595,6 +8562,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7610,6 +8580,9 @@ msgstr "Tiempo total de pruebas para todos los cambios o integraciones"
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7619,6 +8592,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7637,24 +8613,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7670,6 +8664,12 @@ msgstr "Desbloqueado"
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7703,13 +8703,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7739,15 +8742,15 @@ msgstr "Subir nuevo archivo"
msgid "Upload file"
msgstr "Subir archivo"
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr "Hacer clic para subir"
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7775,6 +8778,9 @@ msgstr "Utiliza tu configuración de notificación global"
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7784,10 +8790,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7814,6 +8862,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7847,9 +8904,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr "Ver archivo reemplazado @ "
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7868,6 +8931,36 @@ msgstr "Público"
msgid "VisibilityLevel|Unknown"
msgstr "Desconocido"
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "¿Quieres ver los datos? Por favor pide acceso al administrador."
@@ -7907,6 +9000,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr "Wiki"
@@ -8057,6 +9156,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8075,9 +9177,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8087,9 +9186,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8111,12 +9207,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8138,9 +9240,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr "Debes iniciar sesión para destacar un proyecto"
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8150,6 +9249,12 @@ msgstr ""
msgid "You need permission."
msgstr "Necesitas permisos."
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr "No recibirás ninguna notificación por correo electrónico"
@@ -8216,6 +9321,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr "Tus comentarios no serán visibles al público."
@@ -8237,16 +9345,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "assign yourself"
msgstr ""
@@ -8274,61 +9372,78 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8361,9 +9476,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8386,6 +9498,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8404,13 +9519,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8419,9 +9528,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8452,9 +9558,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8466,9 +9569,6 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8498,25 +9598,17 @@ msgstr[1] "días"
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
-
msgid "disabled"
msgstr ""
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "enabled"
msgstr ""
@@ -8526,6 +9618,12 @@ msgstr ""
msgid "for this project"
msgstr ""
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -8555,6 +9653,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8783,6 +9884,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8801,6 +9905,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr "nueva solicitud de fusión"
@@ -8829,6 +9936,11 @@ msgstr "token de acceso personal"
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "remaining"
msgstr ""
@@ -8841,6 +9953,11 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "source"
msgstr ""
@@ -8856,6 +9973,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr "usuario"
diff --git a/locale/et_EE/gitlab.po b/locale/et_EE/gitlab.po
index dbaff32f1b5..849926d8ae2 100644
--- a/locale/et_EE/gitlab.po
+++ b/locale/et_EE/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Estonian\n"
"Language: et_EE\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: et\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:32\n"
+"PO-Revision-Date: 2018-11-19 17:22\n"
msgid " Status"
msgstr ""
@@ -31,6 +31,14 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -46,6 +54,11 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -91,11 +104,6 @@ msgid_plural "%d unstaged changes"
msgstr[0] ""
msgstr[1] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] ""
@@ -104,17 +112,31 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] ""
msgstr[1] ""
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -124,6 +146,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -139,23 +164,12 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr ""
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr ""
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -167,27 +181,13 @@ msgstr ""
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -314,6 +314,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr ""
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -356,13 +365,10 @@ msgstr ""
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
+msgid "Access expiration date"
msgstr ""
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr ""
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -392,27 +398,48 @@ msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
+msgid "Add Kubernetes cluster"
msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -422,6 +449,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -455,9 +485,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -494,12 +521,17 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr ""
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "All"
msgstr ""
@@ -515,6 +547,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -524,6 +559,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -539,6 +580,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -560,7 +604,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -584,6 +628,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -596,6 +646,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -608,6 +661,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -635,6 +691,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -677,12 +736,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr ""
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -701,7 +766,7 @@ msgstr ""
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -719,9 +784,15 @@ msgstr ""
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -740,6 +811,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -878,6 +952,9 @@ msgstr ""
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -914,9 +991,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -995,6 +1069,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1285,6 +1368,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1315,9 +1401,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1372,7 +1455,7 @@ msgstr ""
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1399,6 +1482,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1429,6 +1518,9 @@ msgstr ""
msgid "CiStatusLabel|created"
msgstr ""
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr ""
@@ -1447,6 +1539,9 @@ msgstr ""
msgid "CiStatusLabel|skipped"
msgstr ""
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr ""
@@ -1459,6 +1554,9 @@ msgstr ""
msgid "CiStatusText|created"
msgstr ""
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr ""
@@ -1513,10 +1611,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1561,6 +1659,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1573,12 +1674,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1609,10 +1722,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1639,6 +1752,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1675,6 +1794,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1705,9 +1827,6 @@ msgstr ""
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1729,25 +1848,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster details"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster health"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1759,7 +1872,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1768,16 +1881,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1795,9 +1905,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1825,6 +1932,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1837,6 +1947,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1867,9 +1980,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1909,13 +2019,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -1933,6 +2040,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -1951,9 +2061,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -1963,6 +2070,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -1972,12 +2082,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2012,6 +2128,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr ""
@@ -2084,7 +2203,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2093,10 +2212,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2186,6 +2305,9 @@ msgstr ""
msgid "Contribution guide"
msgstr ""
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2219,6 +2341,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2240,15 +2374,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2324,7 +2470,7 @@ msgstr ""
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
+msgid "Create your first page"
msgstr ""
msgid "CreateTag|Tag"
@@ -2375,6 +2521,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -2393,6 +2542,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr ""
@@ -2444,6 +2596,9 @@ msgstr ""
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2456,6 +2611,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr ""
@@ -2465,6 +2635,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2602,6 +2775,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2626,6 +2805,12 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2647,12 +2832,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2668,6 +2868,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2749,7 +2952,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2794,9 +2997,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2809,6 +3009,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2911,7 +3117,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -2944,10 +3150,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3058,6 +3264,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3112,6 +3324,12 @@ msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3121,6 +3339,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3130,6 +3351,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3139,6 +3435,9 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr ""
@@ -3151,9 +3450,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr ""
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr ""
@@ -3169,6 +3477,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3181,7 +3492,7 @@ msgstr ""
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3220,17 +3531,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -3246,6 +3558,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3288,6 +3603,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3462,10 +3780,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3474,6 +3804,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3495,7 +3828,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3507,6 +3840,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3516,19 +3852,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3546,6 +3888,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3558,9 +3906,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3570,9 +3936,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3639,12 +4002,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr ""
-
-msgid "GoToYourFork|Fork"
-msgstr ""
-
msgid "Google Code import"
msgstr ""
@@ -3675,9 +4032,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3687,6 +4056,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3705,13 +4077,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3738,9 +4110,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3798,6 +4167,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3810,19 +4182,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -3864,6 +4236,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4028,6 +4403,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4096,6 +4474,12 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4120,6 +4504,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4135,9 +4549,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4174,7 +4585,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4192,12 +4603,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4270,6 +4675,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
@@ -4281,12 +4689,18 @@ msgstr ""
msgid "Last commit"
msgstr ""
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4335,6 +4749,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4344,6 +4767,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4353,6 +4779,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4362,6 +4791,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4374,9 +4806,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4403,6 +4841,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4448,6 +4889,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4517,13 +4961,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4535,6 +5009,12 @@ msgstr ""
msgid "Median"
msgstr ""
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -4568,6 +5048,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4577,9 +5072,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4589,6 +5081,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4604,6 +5102,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4820,6 +5321,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -4939,6 +5443,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -4948,9 +5458,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -4960,6 +5467,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -4987,6 +5497,9 @@ msgstr ""
msgid "No repository"
msgstr ""
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr ""
@@ -5023,6 +5536,9 @@ msgstr ""
msgid "Not enough data"
msgstr ""
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -5041,6 +5557,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -5113,9 +5641,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5142,9 +5667,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5166,6 +5688,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5190,6 +5715,21 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5256,6 +5796,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5283,13 +5826,13 @@ msgstr ""
msgid "Permissions"
msgstr ""
-msgid "Personal Access Token"
+msgid "Permissions, LFS, 2FA"
msgstr ""
-msgid "Pipeline"
+msgid "Personal Access Token"
msgstr ""
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
+msgid "Pipeline"
msgstr ""
msgid "Pipeline Health"
@@ -5409,15 +5952,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5427,6 +5979,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5454,12 +6012,6 @@ msgstr ""
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5469,12 +6021,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5487,6 +6045,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5499,9 +6060,18 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5547,15 +6117,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5568,39 +6153,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -5610,6 +6276,15 @@ msgstr ""
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5646,6 +6321,9 @@ msgstr ""
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr ""
@@ -5673,6 +6351,9 @@ msgstr ""
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -5700,6 +6381,27 @@ msgstr ""
msgid "ProjectLifecycle|Stage"
msgstr ""
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5742,6 +6444,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5811,9 +6516,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6006,6 +6708,12 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6068,12 +6776,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6083,6 +6800,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6092,18 +6812,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6116,6 +6851,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6149,10 +6887,10 @@ msgstr ""
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6170,9 +6908,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6223,9 +6973,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6235,6 +7000,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6259,6 +7030,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6283,6 +7057,9 @@ msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -6337,15 +7114,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6370,27 +7156,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard"
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6408,9 +7222,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr ""
@@ -6441,6 +7261,9 @@ msgstr ""
msgid "Select target branch"
msgstr ""
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6453,6 +7276,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6477,6 +7303,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6495,7 +7324,10 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
@@ -6507,13 +7339,31 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "Settings"
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
msgstr ""
msgid "Share"
@@ -6525,6 +7375,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6608,12 +7461,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6641,9 +7500,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6656,12 +7521,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -6692,6 +7569,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6722,6 +7602,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6752,6 +7635,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6827,9 +7713,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6842,6 +7740,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6851,6 +7752,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6860,9 +7764,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6875,6 +7785,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -6893,6 +7809,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -6997,6 +7916,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7045,12 +7967,6 @@ msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7099,9 +8015,6 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr ""
@@ -7111,21 +8024,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr ""
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7135,6 +8042,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7144,7 +8054,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7192,10 +8108,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7216,6 +8135,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7255,7 +8177,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7276,6 +8201,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
@@ -7300,6 +8228,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7309,6 +8240,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7336,9 +8273,15 @@ msgstr ""
msgid "Time before an issue starts implementation"
msgstr ""
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr ""
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7529,12 +8472,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7550,6 +8505,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7562,12 +8520,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7577,9 +8538,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7595,6 +8562,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7610,6 +8580,9 @@ msgstr ""
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7619,6 +8592,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7637,24 +8613,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7670,6 +8664,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7703,13 +8703,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7739,15 +8742,15 @@ msgstr ""
msgid "Upload file"
msgstr ""
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr ""
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7775,6 +8778,9 @@ msgstr ""
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7784,10 +8790,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7814,6 +8862,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7847,9 +8904,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7868,6 +8931,36 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -7907,6 +9000,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8057,6 +9156,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8075,9 +9177,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8087,9 +9186,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8111,12 +9207,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8138,9 +9240,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr ""
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8150,6 +9249,12 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr ""
@@ -8216,6 +9321,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8237,16 +9345,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "assign yourself"
msgstr ""
@@ -8274,61 +9372,78 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8361,9 +9476,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8386,6 +9498,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8404,13 +9519,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8419,9 +9528,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8452,9 +9558,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8466,9 +9569,6 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8498,25 +9598,17 @@ msgstr[1] ""
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
-
msgid "disabled"
msgstr ""
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "enabled"
msgstr ""
@@ -8526,6 +9618,12 @@ msgstr ""
msgid "for this project"
msgstr ""
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -8555,6 +9653,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8783,6 +9884,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8801,6 +9905,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr ""
@@ -8829,6 +9936,11 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "remaining"
msgstr ""
@@ -8841,6 +9953,11 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "source"
msgstr ""
@@ -8856,6 +9973,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/fil_PH/gitlab.po b/locale/fil_PH/gitlab.po
index 20943d89ea0..39e45baf002 100644
--- a/locale/fil_PH/gitlab.po
+++ b/locale/fil_PH/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Filipino\n"
"Language: fil_PH\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: fil\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:32\n"
+"PO-Revision-Date: 2018-11-19 17:22\n"
msgid " Status"
msgstr ""
@@ -31,6 +31,14 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -46,6 +54,11 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -91,11 +104,6 @@ msgid_plural "%d unstaged changes"
msgstr[0] ""
msgstr[1] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] ""
@@ -104,17 +112,31 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] ""
msgstr[1] ""
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -124,6 +146,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -139,23 +164,12 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr ""
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr ""
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -167,27 +181,13 @@ msgstr ""
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -314,6 +314,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr ""
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -356,13 +365,10 @@ msgstr ""
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
+msgid "Access expiration date"
msgstr ""
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr ""
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -392,27 +398,48 @@ msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
+msgid "Add Kubernetes cluster"
msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -422,6 +449,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -455,9 +485,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -494,12 +521,17 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr ""
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "All"
msgstr ""
@@ -515,6 +547,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -524,6 +559,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -539,6 +580,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -560,7 +604,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -584,6 +628,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -596,6 +646,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -608,6 +661,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -635,6 +691,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -677,12 +736,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr ""
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -701,7 +766,7 @@ msgstr ""
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -719,9 +784,15 @@ msgstr ""
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -740,6 +811,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -878,6 +952,9 @@ msgstr ""
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -914,9 +991,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -995,6 +1069,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1285,6 +1368,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1315,9 +1401,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1372,7 +1455,7 @@ msgstr ""
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1399,6 +1482,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1429,6 +1518,9 @@ msgstr ""
msgid "CiStatusLabel|created"
msgstr ""
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr ""
@@ -1447,6 +1539,9 @@ msgstr ""
msgid "CiStatusLabel|skipped"
msgstr ""
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr ""
@@ -1459,6 +1554,9 @@ msgstr ""
msgid "CiStatusText|created"
msgstr ""
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr ""
@@ -1513,10 +1611,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1561,6 +1659,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1573,12 +1674,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1609,10 +1722,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1639,6 +1752,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1675,6 +1794,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1705,9 +1827,6 @@ msgstr ""
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1729,25 +1848,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster details"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster health"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1759,7 +1872,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1768,16 +1881,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1795,9 +1905,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1825,6 +1932,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1837,6 +1947,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1867,9 +1980,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1909,13 +2019,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -1933,6 +2040,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -1951,9 +2061,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -1963,6 +2070,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -1972,12 +2082,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2012,6 +2128,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr ""
@@ -2084,7 +2203,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2093,10 +2212,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2186,6 +2305,9 @@ msgstr ""
msgid "Contribution guide"
msgstr ""
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2219,6 +2341,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2240,15 +2374,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2324,7 +2470,7 @@ msgstr ""
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
+msgid "Create your first page"
msgstr ""
msgid "CreateTag|Tag"
@@ -2375,6 +2521,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -2393,6 +2542,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr ""
@@ -2444,6 +2596,9 @@ msgstr ""
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2456,6 +2611,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr ""
@@ -2465,6 +2635,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2602,6 +2775,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2626,6 +2805,12 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2647,12 +2832,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2668,6 +2868,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2749,7 +2952,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2794,9 +2997,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2809,6 +3009,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2911,7 +3117,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -2944,10 +3150,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3058,6 +3264,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3112,6 +3324,12 @@ msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3121,6 +3339,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3130,6 +3351,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3139,6 +3435,9 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr ""
@@ -3151,9 +3450,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr ""
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr ""
@@ -3169,6 +3477,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3181,7 +3492,7 @@ msgstr ""
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3220,17 +3531,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -3246,6 +3558,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3288,6 +3603,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3462,10 +3780,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3474,6 +3804,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3495,7 +3828,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3507,6 +3840,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3516,19 +3852,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3546,6 +3888,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3558,9 +3906,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3570,9 +3936,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3639,12 +4002,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr ""
-
-msgid "GoToYourFork|Fork"
-msgstr ""
-
msgid "Google Code import"
msgstr ""
@@ -3675,9 +4032,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3687,6 +4056,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3705,13 +4077,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3738,9 +4110,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3798,6 +4167,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3810,19 +4182,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -3864,6 +4236,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4028,6 +4403,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4096,6 +4474,12 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4120,6 +4504,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4135,9 +4549,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4174,7 +4585,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4192,12 +4603,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4270,6 +4675,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
@@ -4281,12 +4689,18 @@ msgstr ""
msgid "Last commit"
msgstr ""
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4335,6 +4749,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4344,6 +4767,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4353,6 +4779,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4362,6 +4791,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4374,9 +4806,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4403,6 +4841,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4448,6 +4889,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4517,13 +4961,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4535,6 +5009,12 @@ msgstr ""
msgid "Median"
msgstr ""
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -4568,6 +5048,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4577,9 +5072,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4589,6 +5081,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4604,6 +5102,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4820,6 +5321,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -4939,6 +5443,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -4948,9 +5458,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -4960,6 +5467,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -4987,6 +5497,9 @@ msgstr ""
msgid "No repository"
msgstr ""
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr ""
@@ -5023,6 +5536,9 @@ msgstr ""
msgid "Not enough data"
msgstr ""
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -5041,6 +5557,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -5113,9 +5641,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5142,9 +5667,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5166,6 +5688,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5190,6 +5715,21 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5256,6 +5796,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5283,13 +5826,13 @@ msgstr ""
msgid "Permissions"
msgstr ""
-msgid "Personal Access Token"
+msgid "Permissions, LFS, 2FA"
msgstr ""
-msgid "Pipeline"
+msgid "Personal Access Token"
msgstr ""
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
+msgid "Pipeline"
msgstr ""
msgid "Pipeline Health"
@@ -5409,15 +5952,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5427,6 +5979,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5454,12 +6012,6 @@ msgstr ""
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5469,12 +6021,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5487,6 +6045,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5499,9 +6060,18 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5547,15 +6117,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5568,39 +6153,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -5610,6 +6276,15 @@ msgstr ""
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5646,6 +6321,9 @@ msgstr ""
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr ""
@@ -5673,6 +6351,9 @@ msgstr ""
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -5700,6 +6381,27 @@ msgstr ""
msgid "ProjectLifecycle|Stage"
msgstr ""
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5742,6 +6444,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5811,9 +6516,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6006,6 +6708,12 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6068,12 +6776,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6083,6 +6800,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6092,18 +6812,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6116,6 +6851,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6149,10 +6887,10 @@ msgstr ""
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6170,9 +6908,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6223,9 +6973,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6235,6 +7000,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6259,6 +7030,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6283,6 +7057,9 @@ msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -6337,15 +7114,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6370,27 +7156,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard"
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6408,9 +7222,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr ""
@@ -6441,6 +7261,9 @@ msgstr ""
msgid "Select target branch"
msgstr ""
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6453,6 +7276,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6477,6 +7303,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6495,7 +7324,10 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
@@ -6507,13 +7339,31 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "Settings"
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
msgstr ""
msgid "Share"
@@ -6525,6 +7375,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6608,12 +7461,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6641,9 +7500,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6656,12 +7521,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -6692,6 +7569,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6722,6 +7602,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6752,6 +7635,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6827,9 +7713,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6842,6 +7740,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6851,6 +7752,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6860,9 +7764,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6875,6 +7785,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -6893,6 +7809,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -6997,6 +7916,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7045,12 +7967,6 @@ msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7099,9 +8015,6 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr ""
@@ -7111,21 +8024,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr ""
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7135,6 +8042,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7144,7 +8054,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7192,10 +8108,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7216,6 +8135,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7255,7 +8177,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7276,6 +8201,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
@@ -7300,6 +8228,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7309,6 +8240,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7336,9 +8273,15 @@ msgstr ""
msgid "Time before an issue starts implementation"
msgstr ""
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr ""
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7529,12 +8472,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7550,6 +8505,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7562,12 +8520,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7577,9 +8538,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7595,6 +8562,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7610,6 +8580,9 @@ msgstr ""
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7619,6 +8592,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7637,24 +8613,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7670,6 +8664,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7703,13 +8703,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7739,15 +8742,15 @@ msgstr ""
msgid "Upload file"
msgstr ""
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr ""
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7775,6 +8778,9 @@ msgstr ""
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7784,10 +8790,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7814,6 +8862,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7847,9 +8904,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7868,6 +8931,36 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -7907,6 +9000,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8057,6 +9156,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8075,9 +9177,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8087,9 +9186,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8111,12 +9207,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8138,9 +9240,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr ""
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8150,6 +9249,12 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr ""
@@ -8216,6 +9321,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8237,16 +9345,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "assign yourself"
msgstr ""
@@ -8274,61 +9372,78 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8361,9 +9476,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8386,6 +9498,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8404,13 +9519,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8419,9 +9528,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8452,9 +9558,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8466,9 +9569,6 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8498,25 +9598,17 @@ msgstr[1] ""
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
-
msgid "disabled"
msgstr ""
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "enabled"
msgstr ""
@@ -8526,6 +9618,12 @@ msgstr ""
msgid "for this project"
msgstr ""
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -8555,6 +9653,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8783,6 +9884,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8801,6 +9905,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr ""
@@ -8829,6 +9936,11 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "remaining"
msgstr ""
@@ -8841,6 +9953,11 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "source"
msgstr ""
@@ -8856,6 +9973,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po
index c0ce98832de..177570cc590 100644
--- a/locale/fr/gitlab.po
+++ b/locale/fr/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: French\n"
"Language: fr_FR\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: fr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:32\n"
+"PO-Revision-Date: 2018-11-19 17:23\n"
msgid " Status"
msgstr " Statut"
@@ -31,6 +31,14 @@ msgid_plural " improved on %d points"
msgstr[0] " amélioré sur %d point"
msgstr[1] " amélioré sur %d points"
+msgid "\"%{query}\" in projects"
+msgstr "« %{query} » dans les projets"
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] "%d ajout"
+msgstr[1] "%d ajouts"
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] "%d fichier modifié"
@@ -46,6 +54,11 @@ msgid_plural "%d commits behind"
msgstr[0] "%d commit de retard"
msgstr[1] "%d commits de retard"
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] "%d supprimé"
+msgstr[1] "%d supprimés"
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d exportateur"
@@ -91,11 +104,6 @@ msgid_plural "%d unstaged changes"
msgstr[0] "%d changement qui ne sera pas validé"
msgstr[1] "%d changements qui ne seront pas validés"
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] "%d vulnérabilité"
-msgstr[1] "%d vulnérabilités"
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] "%s commit supplémentaire a été ignoré afin d’éviter de causer des problèmes de performance."
@@ -104,17 +112,31 @@ msgstr[1] "%s commits supplémentaires ont été ignorés afin d’éviter de ca
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} et %{openOrClose} %{noteable}"
+msgid "%{authorsName}'s discussion"
+msgstr "Discussion de %{authorsName}"
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} a créé %{commit_timeago}"
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr "%{counter_storage} (%{counter_repositories} dépôts, %{counter_build_artifacts} artefacts construits, %{counter_lfs_objects} LFS)"
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] "%{count} participant·e"
msgstr[1] "%{count} participant·e·s"
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] "%{count} commentaire en attente"
+msgstr[1] "%{count} commentaires en attente"
+
msgid "%{filePath} deleted"
msgstr "%{filePath} supprimé"
@@ -124,6 +146,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "Les %{group_docs_link_start}groupes%{group_docs_link_end} vous permettent de gérer plusieurs projets et d’y collaborer. Les membres d’un groupe ont accès à tous ses projets."
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr "%{issuableType} sera supprimé ! Êtesâ€vous sûr ?"
+
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Démarré"
@@ -139,23 +164,12 @@ msgstr "%{nip_domain} peut être utilisé comme alternative à un domaine person
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{number_commits_behind} commits de retard sur %{default_branch}, %{number_commits_ahead} commits d’avance"
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr "%{number_of_failures} sur %{maximum_failures} tentative(s). GitLab va vous permettre d’accéder à la prochaine tentative."
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr "%{number_of_failures} échecs sur %{maximum_failures}. GitLab ne va plus réessayer automatiquement. Réinitialisez les informations de stockage lorsque le problème est résolu."
-
msgid "%{openOrClose} %{noteable}"
msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
msgstr "%{percent} %% effectués"
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] "%{storage_name} : la tentative d’accès au stockage a échoué sur l’hôte :"
-msgstr[1] "%{storage_name} : %{failed_attempts} tentatives d’accès au stockage ont échoué :"
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -167,29 +181,15 @@ msgstr "%{text} est disponible"
msgid "%{title} changes"
msgstr "Changements %{title}"
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] "%{type} a détecté une vulnérabilité corrigée"
-msgstr[1] "%{type} a détecté %{vulnerabilityCount} vulnérabilités corrigées"
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] "%{type} a détecté une nouvelle vulnérabilité"
-msgstr[1] "%{type} a détecté %{vulnerabilityCount} nouvelles vulnérabilités"
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] "%{type} a détecté 1 vulnérabilité"
-msgstr[1] "%{type} a détecté %{vulnerabilityCount} vulnérabilités"
-
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] "%{type} a détecté une vulnérabilité uniquement dans la branche source"
-msgstr[1] "%{type} a détecté %{vulnerabilityCount} vulnérabilités uniquement dans la branche source"
-
msgid "%{unstaged} unstaged and %{staged} staged changes"
msgstr "%{staged} changements prêts à être validés et %{unstaged} autres changements"
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr "%{usage_ping_link_start}En savoir plus%{usage_ping_link_end} sur les informations partagées avec GitLab Inc."
+
+msgid "+ %{count} more"
+msgstr "+ %{count} de plus"
+
msgid "+ %{moreCount} more"
msgstr "+ %{moreCount} de plus"
@@ -291,7 +291,7 @@ msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will ad
msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> ajoutera « Par <a href=\"#\">johnsmith@example.com</a> » à tous les tickets et commentaires créés à l’origine par johnsmith@example.com. Par défaut, l’adresse de courriel ou le nom d’utilisateur est masqué pour garantir la confidentialité de l’utilisateur. Utilisez cette option si vous souhaitez afficher l’adresse de courriel complète."
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
-msgstr ""
+msgstr "<strong>%{changedFilesLength} modifications non indexées</strong> et <strong>%{stagedFilesLength} modifications d’étape</strong>"
msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
msgstr "<strong>%{created_count}</strong> créé(s), <strong>%{accepted_count}</strong> accepté(s)."
@@ -314,6 +314,15 @@ msgstr "Un « exécuteur » est un processus qui exécute une tâche. Vous pou
msgid "A collection of graphs regarding Continuous Integration"
msgstr "Un ensemble de graphiques concernant l’intégration continue (CI)"
+msgid "A default branch cannot be chosen for an empty project."
+msgstr "Une branche par défaut ne peut pas être choisie pour un projet vide."
+
+msgid "A deleted user"
+msgstr "Un utilisateur supprimé"
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr "Un membre de l’équipe de vérification des abus de GitLab examinera votre rapport dès que possible."
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr "Une nouvelle branche sera créée dans votre dépôt divergent (fork) et une nouvelle demande de fusion sera lancée."
@@ -356,15 +365,12 @@ msgstr "Jetons d’accès"
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "Accès refusé ! Veuillez vérifier que vous pouvez ajouter des clefs de déploiement à ce dépôt."
+msgid "Access expiration date"
+msgstr "Date d’expiration de l’accès"
+
msgid "Access to '%{classification_label}' not allowed"
msgstr "Accès à « %{classification_label} » non autorisé"
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr "L’accès aux stockages défaillants a été temporairement désactivé pour permettre la récupération du montage. Réinitialisez les informations de stockage quand le problème sera résolu pour permettre à nouveau l’accès."
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
-msgstr "Accédez à votre jeton d’exécuteur, personnalisez la configuration de votre pipeline et affichez l’état de votre pipeline et le rapport de couverture."
-
msgid "Account"
msgstr "Compte"
@@ -392,27 +398,48 @@ msgstr "Ajouter un guide de contribution"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr "Ajoutez des Webhooks de groupe avec GitLab Enterprise Edition."
+msgid "Add Jaeger URL"
+msgstr "Ajouter une URL Jaeger"
+
msgid "Add Kubernetes cluster"
msgstr "Ajouter une grappe de serveurs Kubernetes"
-msgid "Add License"
-msgstr "Ajouter une licence"
-
msgid "Add Readme"
msgstr "Ajouter un fichier Readme"
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr "Ajoutez une page d’accueil à votre wiki contenant des informations sur votre projet. GitLab l’affichera ici à la place de ce message."
+
+msgid "Add a table"
+msgstr "Ajouter un tableau"
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Ajouter un texte apparaissant dans toutes communications par courriel (%{character_limit} caractères maximum)"
+msgid "Add comment now"
+msgstr "Ajouter un commentaire"
+
+msgid "Add image comment"
+msgstr "Ajouter un commentaire à l’image"
+
+msgid "Add license"
+msgstr "Ajouter une licence"
+
msgid "Add new application"
msgstr "Ajouter une nouvelle application"
msgid "Add new directory"
msgstr "Ajouter un nouveau dossier"
+msgid "Add projects"
+msgstr "Ajouter des projets"
+
msgid "Add reaction"
msgstr "Ajouter une réaction"
+msgid "Add to review"
+msgstr "Ajouter à la revue de code"
+
msgid "Add todo"
msgstr "Ajouter à la liste « à faire »"
@@ -422,6 +449,9 @@ msgstr "Ajouter un ou des utilisateurs au groupe :"
msgid "Add users to group"
msgstr "Ajouter des utilisateurs au groupe"
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr "L’ajout de nouvelles applications est désactivé dans votre instance GitLab. Veuillez contacter votre administrateur GitLab pour en obtenir la permission."
+
msgid "Additional text"
msgstr "Texte supplémentaire"
@@ -455,9 +485,6 @@ msgstr "L’arrêt des tâches a échoué"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "Vous êtes sur le point d’arrêter toutes les tâches. Toutes les tâches en cours seront interrompues."
-msgid "AdminHealthPageLink|health page"
-msgstr "État des services"
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr "Vous êtes sur le point de supprimer définitivement le projet %{projectName}, son dépôt et toutes les ressources qui lui sont liées, y compris les tickets, les demandes de fusion, etc. Après sa confirmation par un clic sur « %{strong_start}supprimer le projet%{strong_end} », l’action ne peut être annulée ni faire l’objet d’une restauration."
@@ -494,12 +521,17 @@ msgstr "Pour confirmer, veuillez saisir %{projectName}"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "Pour confirmer, veuillez saisir %{username}"
-msgid "Advanced"
-msgstr "Paramètres avancés"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr "Autorisations avancées, stockage de fichiers volumineux et paramètres d’authentification à double facteur."
msgid "Advanced settings"
msgstr "Paramètres avancés"
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] "Alerte"
+msgstr[1] "Alertes"
+
msgid "All"
msgstr "Tous"
@@ -515,6 +547,9 @@ msgstr "Tous les utilisateurs"
msgid "Allow commits from members who can merge to the target branch."
msgstr "Autoriser les commits des membres qui peuvent fusionner dans la branche cible."
+msgid "Allow projects within this group to use Git LFS"
+msgstr "Autoriser les projets de ce groupe à utiliser le stockage Git LFS"
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr "Autoriser l’accès public aux pipelines et aux détails des tâches, y compris les journaux de sortie et les artefacts"
@@ -524,6 +559,12 @@ msgstr "Permettre le rendu des diagrammes PlantUML dans les documents Asciidoc."
msgid "Allow requests to the local network from hooks and services."
msgstr "Autoriser les requêtes sur le réseau local à partir de hooks et de services."
+msgid "Allow users to request access"
+msgstr "Autoriser les utilisateurs à demander un accès"
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr "Autoriser les utilisateurs à demander l’accès si la visibilité est publique ou interne."
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Vous permet d’ajouter et de gérer des grappes de serveurs Kubernetes."
@@ -539,6 +580,9 @@ msgstr "Vous pouvez également utiliser un %{personal_access_token_link}. Lorsqu
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr "Vous pouvez également utiliser un %{personal_access_token_link}. Lorsque vous créerez votre jeton d’accès personnel, sélectionnez la portée <code>dépôt</code>, afin de permettre l’affichage d’une liste de vos dépôts publics et privés qui pourront être importés."
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr "Durée (en heures) durant laquelle les utilisateurs sont autorisés à outrepasser la configuration de l’authentification à double facteur obligatoire"
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr "Une paire de clefs SSH sera automatiquement générée après soumission du formulaire. Pour plus d’informations, veuillez vous référer à la documentation."
@@ -560,8 +604,8 @@ msgstr "Une erreur est survenue lors de la création de la nouvelle branche."
msgid "An error occured whilst fetching the job trace."
msgstr "Une erreur est survenue pendant le rapatriement de la trace de la tâche."
-msgid "An error occured whilst fetching the latest pipline."
-msgstr "Une erreur est survenue lors du rapatriement de dernier pipeline."
+msgid "An error occured whilst fetching the latest pipeline."
+msgstr ""
msgid "An error occured whilst loading all the files."
msgstr "Une erreur est survenue lors du chargement de l’ensemble des fichiers."
@@ -584,6 +628,12 @@ msgstr "Une erreur est survenue lors du chargement de la demande de fusion."
msgid "An error occured whilst loading the pipelines jobs."
msgstr "Une erreur est survenue lors du chargement des tâches des pipelines."
+msgid "An error occurred adding a draft to the discussion."
+msgstr "Une erreur est survenue lors de l’ajout d’un brouillon à la discussion."
+
+msgid "An error occurred adding a new draft."
+msgstr "Une erreur est survenue lors de l’ajout d’un nouveau brouillon."
+
msgid "An error occurred previewing the blob"
msgstr "Une erreur s’est produite lors de la prévisualisation du blob"
@@ -596,6 +646,9 @@ msgstr "Une erreur est survenue lors de la mise à jour du poids du ticket"
msgid "An error occurred while adding approver"
msgstr "Une erreur s’est produite lors de l’ajout de l’approba·teur·trice"
+msgid "An error occurred while deleting the comment"
+msgstr "Une erreur est survenue lors de la suppression du commentaire"
+
msgid "An error occurred while detecting host keys"
msgstr "Une erreur est survenue lors de la détection des clefs de l’hôte"
@@ -608,20 +661,23 @@ msgstr "Une erreur s’est produite lors du rejet de la mise en avant de la fonc
msgid "An error occurred while fetching markdown preview"
msgstr "Une erreur s’est produite lors de la prévisualisation markdown"
+msgid "An error occurred while fetching pending comments"
+msgstr "Une erreur est survenue lors de la récupération des commentaires en attente"
+
msgid "An error occurred while fetching sidebar data"
msgstr "Une erreur s’est produite lors de la récupération des données de la barre latérale"
msgid "An error occurred while fetching stages."
-msgstr ""
+msgstr "Une erreur est survenue lors de la récupération des étapes."
msgid "An error occurred while fetching the job log."
-msgstr ""
+msgstr "Une erreur est survenue pendant la récupération du journal de la tâche."
msgid "An error occurred while fetching the job."
-msgstr ""
+msgstr "Une erreur est survenue pendant la récupération de la tâche."
msgid "An error occurred while fetching the jobs."
-msgstr ""
+msgstr "Une erreur est survenue pendant la récupération des tâches."
msgid "An error occurred while fetching the pipeline."
msgstr "Une erreur est survenue pendant la récupération du pipeline."
@@ -635,6 +691,9 @@ msgstr "Une erreur est survenue lors de l’importation du projet : %{details}"
msgid "An error occurred while initializing path locks"
msgstr "Une erreur est survenue lors de l’initialisation des verrous des chemins d’accès"
+msgid "An error occurred while loading chart data"
+msgstr "Une erreur est survenue lors du chargement des données du graphique"
+
msgid "An error occurred while loading commit signatures"
msgstr "Une erreur s’est produite lors du chargement des signatures du commit"
@@ -677,12 +736,18 @@ msgstr "Une erreur est survenue lors de l’abonnement aux notifications."
msgid "An error occurred while unsubscribing to notifications."
msgstr "Une erreur est survenue lors du désabonnement aux notifications."
+msgid "An error occurred while updating the comment"
+msgstr "Une erreur est survenue lors de la mise à jour du commentaire"
+
msgid "An error occurred while validating username"
msgstr "Une erreur s’est produite lors de la validation du nom d’utilisateur"
msgid "An error occurred. Please try again."
msgstr "Une erreur est survenue. Merci de réessayer."
+msgid "Analytics"
+msgstr "Analyse"
+
msgid "Anonymous"
msgstr "Anonyme"
@@ -701,7 +766,7 @@ msgstr "Apparence"
msgid "Application"
msgstr "Application"
-msgid "Application Id"
+msgid "Application ID"
msgstr "Identifiant de l’application"
msgid "Application: %{name}"
@@ -719,9 +784,15 @@ msgstr "avril"
msgid "Archived project! Repository and other project resources are read-only"
msgstr "Projet archivé ! Le dépôt et les autres ressources du projet sont en lecture seule"
+msgid "Archived projects"
+msgstr "Projets archivés"
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Êtesâ€vous sûr·e de vouloir supprimer ce pipeline programmé ?"
+msgid "Are you sure you want to erase this build?"
+msgstr "Êtesâ€vous sûr(e) de vouloir supprimer cette construction ?"
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "Êtesâ€vous vraiment prêt(e) à perdre les modifications non enregistrées ?"
@@ -740,6 +811,9 @@ msgstr "Êtesâ€vous sûr·e de vouloir réinitialiser le jeton d’inscriptionâ
msgid "Are you sure you want to reset the health check token?"
msgstr "Êtesâ€vous sûr·e de vouloir réinitialiser le jeton de bilan de santé ?"
+msgid "Are you sure you want to stop this environment?"
+msgstr "Êtesâ€vous sûr(e) de vouloir arrêter cet environnement ?"
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "Êtesâ€vous sûr·e de vouloir déverrouiller %{path_lock_path} ?"
@@ -878,6 +952,9 @@ msgstr "Auto DevOps va automatiquement construire, tester et déployer votre app
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "Apprenezâ€en davantage en consultant la %{link_to_documentation}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr "Le pipeline Auto DevOps a été activé et sera utilisé si aucun autre fichier de configuration d’intégration continue n’est trouvé. %{more_information_link}"
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr "Vous pouvez automatiquement générer et tester votre application si vous %{link_to_auto_devops_settings} pour ce projet. Vous pouvez aussi la déployer automatiquement, si vous %{link_to_add_kubernetes_cluster}."
@@ -914,11 +991,8 @@ msgstr "Tâches de fond"
msgid "Background color"
msgstr "Couleur d’arrièreâ€plan"
-msgid "Background jobs"
-msgstr "Tâches de fond"
-
msgid "Badges"
-msgstr "Badges"
+msgstr "Badges numériques"
msgid "Badges|A new badge was added."
msgstr "Un nouveau badge a été ajouté."
@@ -954,10 +1028,10 @@ msgid "Badges|No badge image"
msgstr "Pas d’image de badge"
msgid "Badges|No image to preview"
-msgstr "Pas d’image à prévisualiser"
+msgstr "Aucune image à prévisualiser"
msgid "Badges|Please fill in a valid URL"
-msgstr ""
+msgstr "Veuillez saisir une URL valide"
msgid "Badges|Project Badge"
msgstr "Badge de projet"
@@ -990,10 +1064,19 @@ msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot<
msgstr "Vous êtes sur le point de supprimer ce badge. Les badges supprimés <strong>ne peuvent pas</strong> être restaurés."
msgid "Badges|Your badges"
-msgstr "Vos badges"
+msgstr "Vos badges numériques"
msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
+msgstr "p. ex. %{exampleUrl}"
+
+msgid "BatchComments|Delete all pending comments"
+msgstr "Supprimer tous les commentaires en attente"
+
+msgid "BatchComments|Discard review?"
+msgstr "Abandonner la revue de code ?"
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr "Vous êtes sur le point d’abonner votre revue de code, ce qui entraînera la suppression de l’ensemble de vos commentaires en attente. Les commentaires supprimés %{strong_start}ne peuvent pas%{strong_end} être restaurés."
msgid "Begin with the selected commit"
msgstr "Commencer avec le commit sélectionné"
@@ -1285,6 +1368,9 @@ msgstr "Déploiement automatique pour « staging », déploiement manuel pour
msgid "CICD|Continuous deployment to production"
msgstr "Déploiement continu en production"
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr "Déploiement continu en production par sorties incrémentielles programmées"
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr "Pipeline Auto DevOps par défaut"
@@ -1315,9 +1401,6 @@ msgstr "instance activée"
msgid "Callback URL"
msgstr "URL de retour"
-msgid "Callback url"
-msgstr "URL de retour"
-
msgid "Can't find HEAD commit for this branch"
msgstr "Impossible de trouver le dernier commit (HEAD) pour cette branche"
@@ -1372,8 +1455,8 @@ msgstr "Statistiques"
msgid "Chat"
msgstr "Discussion"
-msgid "Check interval"
-msgstr "Intervalle de vérification"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr "Veuillez vérifier la %{docs_link_start}documentation%{docs_link_end}."
msgid "Checking %{text} availability…"
msgstr "Vérification de la disponibilité de %{text}…"
@@ -1399,6 +1482,12 @@ msgstr "Choisir le fichier…"
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr "Choisissez une branche ou une étiquette (par exemple %{master}) ou entrez un commit (par exemple %{sha}) pour voir ce qui a changé ou pour créer une demande de fusion."
+msgid "Choose a template..."
+msgstr "Choisir un modèle…"
+
+msgid "Choose a type..."
+msgstr "Choisir un type…"
+
msgid "Choose any color."
msgstr "Choisissez n’importe quelle couleur."
@@ -1429,8 +1518,11 @@ msgstr "annulé"
msgid "CiStatusLabel|created"
msgstr "créé"
+msgid "CiStatusLabel|delayed"
+msgstr "différé"
+
msgid "CiStatusLabel|failed"
-msgstr "échoué"
+msgstr "en échec"
msgid "CiStatusLabel|manual action"
msgstr "action manuelle"
@@ -1447,6 +1539,9 @@ msgstr "en attente"
msgid "CiStatusLabel|skipped"
msgstr "ignoré"
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr "en attente d’une tâche différée"
+
msgid "CiStatusLabel|waiting for manual action"
msgstr "en attente d’une action manuelle"
@@ -1459,8 +1554,11 @@ msgstr "annulé "
msgid "CiStatusText|created"
msgstr "créé"
+msgid "CiStatusText|delayed"
+msgstr "différé"
+
msgid "CiStatusText|failed"
-msgstr "échoué"
+msgstr "en échec"
msgid "CiStatusText|manual"
msgstr "manuel"
@@ -1505,7 +1603,7 @@ msgid "CiVariable|Protected"
msgstr "Protégée"
msgid "CiVariable|Search environments"
-msgstr ""
+msgstr "Chercher des environnements"
msgid "CiVariable|Toggle protected"
msgstr "Changer l’état de protection"
@@ -1513,12 +1611,12 @@ msgstr "Changer l’état de protection"
msgid "CiVariable|Validation failed"
msgstr "La validation a échoué"
-msgid "CircuitBreakerApiLink|circuitbreaker api"
-msgstr "CircuitBreaker API"
-
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "est indisponible : %{reason}"
+msgid "Clear search"
+msgstr "Effacer la recherche"
+
msgid "Clear search input"
msgstr "Vider le champ de recherche"
@@ -1561,6 +1659,9 @@ msgstr "Cloner le dépôt"
msgid "Close"
msgstr "Fermer"
+msgid "Close epic"
+msgstr "Clore l’épopée"
+
msgid "Closed"
msgstr "Fermé(e)"
@@ -1573,17 +1674,29 @@ msgstr "%{appList} a été installé avec succès sur votre grappe de serveurs K
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr "%{boldNotice} Ceci ajoutera quelques ressources supplémentaires comme un équilibreur de charge, ce qui peut engager des frais supplémentaires selon l’hébergeur de votre grappe de serveurs Kubernetes. Si vous utilisez Google Kubernetes Engine, vous pouvez %{pricingLink}."
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr "Une construction Knative étend Kubernetes en utilisant les primitives Kubernetes existantes pour vous permettre d’exécuter des constructions de conteneurs sur une grappe de serveurs à partir des sources. Par exemple, vous pouvez écrire une construction qui utilise les ressources natives de Kubernetes pour obtenir votre code source à partir d’un dépôt, puis compiler ce code dans une image de conteneur, et enfin exécuter cette image."
+
msgid "ClusterIntegration|API URL"
msgstr "URL de l’API"
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr "Ajouter une grappe de serveurs Kubernetes"
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr "Ajouter une intégration d’une grappe de serveurs Kubernetes"
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr "Une grappe de serveurs Kubernetes ajoutée à votre groupe la rendra automatiquement disponible pour tous vos projets. Vous pourrez utiliser les applications de revue de code, déployer vos applications et exécuter facilement vos pipelines avec tous les projets utilisant la même grappe de serveurs."
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr "Ajouter une intégration à votre groupe rendra la grappe de serveurs disponible pour l’ensemble de vos projets."
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Options avancées concernant l’intégration de cette grappe de serveurs Kubernetes"
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
-msgstr ""
+msgstr "Après avoir installé Ingress, vous devrez faire pointer votre entrée DNS générique (wildcard) vers l’adresse IP externe générée afin que votre application puisse s’afficher après son déploiement. %{ingressHelpLink}"
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr "Une erreur est survenue lors de la tentative de récupération des zones du projet : %{error}"
@@ -1592,10 +1705,10 @@ msgid "ClusterIntegration|An error occured while trying to fetch your projects:
msgstr "Une erreur est survenue lors de la tentative de récupération de vos projets : %{error}"
msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
-msgstr ""
+msgstr "Une erreur est survenue lors de la tentative de récupération des types de machines de la zone : %{error}"
msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
-msgstr ""
+msgstr "Une erreur est survenue lors de la tentative de contact de l’API Google Cloud. Veuillez réessayer plus tard."
msgid "ClusterIntegration|Applications"
msgstr "Applications"
@@ -1609,11 +1722,11 @@ msgstr "Certificat d’autorité de certification"
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "Ensemble de certificats des autorités de certification (format PEM)"
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
-msgstr "Choisissez les environnements de votre projet qui utiliseront cette grappe de serveurs Kubernetes."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr "Choisissez les applications à installer sur votre grappe de serveurs Kubernetes. L’installation de n’importe quelle des applications suivantes nécessite Helm Tiller."
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
-msgstr "Contrôlez l’intégration de votre grappe de serveurs Kubernetes avec GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr "Choisissez lequel de vos environnements utilisera cette grappe de serveurs."
msgid "ClusterIntegration|Copy API URL"
msgstr "Copier l’URL de l’API"
@@ -1639,6 +1752,12 @@ msgstr "Créer une grappe de serveurs Kubernetes"
msgid "ClusterIntegration|Did you know?"
msgstr "Le saviezâ€vous ?"
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr "Activez ou désactivez la connexion de GitLab à votre grappe de serveurs Kubernetes."
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr "Activez ce paramètre si vous utilisez le contrôle d’accès basé sur les rôles (RBAC)."
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr "Entrez les détails de votre grappe de serveurs Kubernetes"
@@ -1664,7 +1783,7 @@ msgid "ClusterIntegration|GitLab Runner"
msgstr "Exécuteur GitLab"
msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
-msgstr ""
+msgstr "GitLab Runner se connecte au dépôt de ce projet et exécute les tâches d’intégration et livraison continues (CI/CD), en renvoyant les résultats et en déployant les applications en production."
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Projet Google Cloud Platform"
@@ -1675,11 +1794,14 @@ msgstr "Google Kubernetes Engine"
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr "Projet Google Kubernetes Engine"
+msgid "ClusterIntegration|Group cluster"
+msgstr "Groupe de la grappe de serveurs"
+
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
+msgstr "Helm rationalise l’installation et la gestion des applications Kubernetes. Tiller s’exécute sur votre grappe de serveurs Kubernetes et gère les publications de vos graphiques."
msgid "ClusterIntegration|Hide"
msgstr "Masquer"
@@ -1697,7 +1819,7 @@ msgid "ClusterIntegration|Ingress IP Address"
msgstr "Adresse IP Ingress"
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
-msgstr ""
+msgstr "Ingress vous permet de router les requêtes vers des services en fonction de l’hôte ou du chemin de la requête, en centralisant un certain nombre de services vers un seul point d’entrée."
msgid "ClusterIntegration|Install"
msgstr "Installer"
@@ -1705,9 +1827,6 @@ msgstr "Installer"
msgid "ClusterIntegration|Install Prometheus"
msgstr "Installer Prometheus"
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr "Installé"
@@ -1727,7 +1846,13 @@ msgid "ClusterIntegration|JupyterHub"
msgstr "JupyterHub"
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
-msgstr ""
+msgstr "JupyterHub est une plaque tournante multiâ€utilisateur qui génère, gère et « proxifie » plusieurs instances du serveur de blocâ€notes monoâ€utilisateur Jupyter notebook. JupyterHub peut être utilisé pour servir des blocâ€notes aux élèves d’une classe, un groupe d’informaticiens d’une entreprise ou un groupe de scientifiques chercheurs."
+
+msgid "ClusterIntegration|Knative"
+msgstr "Knative"
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr "Nom de domaine Knative :"
msgid "ClusterIntegration|Kubernetes cluster"
msgstr "Grappe de serveurs Kubernetes"
@@ -1738,18 +1863,6 @@ msgstr "Détails de la grappe de serveurs Kubernetes"
msgid "ClusterIntegration|Kubernetes cluster health"
msgstr "État de santé de la grappe de serveurs Kubernetes"
-msgid "ClusterIntegration|Kubernetes cluster integration"
-msgstr "Intégration d’une grappe de serveurs Kubernetes"
-
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
-msgstr "L’intégration de la grappe de serveurs Kubernetes est désactivée pour ce projet."
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
-msgstr "L’intégration de la grappe de serveurs Kubernetes est activée pour ce projet."
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
-msgstr "L’intégration d’une grappe de serveurs Kubernetes est activée pour ce projet. La désactivation de cette intégration n’affectera pas votre grappe de serveurs Kubernetes, elle ne désactivera que temporairement sa connexion à GitLab."
-
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
msgstr "La grappe de serveurs Kubernetes est en cours de création sur Google Kubernetes Engine…"
@@ -1759,8 +1872,8 @@ msgstr "Nom de la grappe de serveurs Kubernetes"
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr "La grappe de serveurs Kubernetes a été créée avec succès sur Google Kubernetes Engine. Actualisez la page pour voir les détails de la grappe de serveurs Kubernetes"
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
-msgstr "Les grappes de serveurs Kubernetes vous permettent d’utiliser des applications de révision, de déployer vos applications, d’exécuter vos pipelines et bien plus encore. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr "Les grappes de serveurs Kubernetes vous permettent d’utiliser des applications de revue de code, de déployer vos applications, d’exécuter vos pipelines et bien plus encore, et ce, de manière très simple."
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
msgstr "Les grappes de serveurs Kubernetes peuvent être utilisées pour déployer des applications et fournir des applications de revue Review Apps pour ce projet"
@@ -1768,17 +1881,14 @@ msgstr "Les grappes de serveurs Kubernetes peuvent être utilisées pour déploy
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr "En savoir plus sur les %{help_link_start_machine_type}types de machines%{help_link_end} et la %{help_link_start_pricing}tarification%{help_link_end}."
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr "En savoir plus sur %{help_link_start}Kubernetes%{help_link_end}."
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr "En savoir plus sur %{help_link_start}les zones%{help_link_end}."
-msgid "ClusterIntegration|Learn more about environments"
-msgstr "En savoir plus sur les environnements"
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr "En savoir plus sur Kubernetes"
-msgid "ClusterIntegration|Learn more about security configuration"
-msgstr "En savoir plus sur la configuration de la sécurité"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr "En savoir plus sur les grappes de serveurs Kubernetes de groupe"
msgid "ClusterIntegration|Machine type"
msgstr "Type de machine"
@@ -1795,9 +1905,6 @@ msgstr "Gérez votre grappe de serveurs Kubernetes en visitant %{link_gke}"
msgid "ClusterIntegration|More information"
msgstr "Plus d’informations"
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr "Plusieurs grappes de serveurs Kubernetes sont disponibles dans GitLab Enterprise Edition Premium et Ultimate"
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr "Aucun type de machine ne correspond à votre recherche"
@@ -1823,7 +1930,10 @@ msgid "ClusterIntegration|Please make sure that your Google account meets the fo
msgstr "Veuillez vous assurer que votre compte Google répond aux exigences suivantes :"
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
-msgstr ""
+msgstr "Faites pointer une entrée DNS générique (wildcard) sur cette adresse IP générée afin de pouvoir accéder à votre application après son déploiement."
+
+msgid "ClusterIntegration|Project cluster"
+msgstr "Grappe de serveurs du projet"
msgid "ClusterIntegration|Project namespace"
msgstr "Espace de noms du projet"
@@ -1835,7 +1945,10 @@ msgid "ClusterIntegration|Prometheus"
msgstr "Prometheus"
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
-msgstr ""
+msgstr "Prometheus est un système de supervision libre avec %{gitlabIntegrationLink} permettant de surveiller les applications déployées."
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr "Grappe de serveurs avec contrôle d’accès par rôle"
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr "Lisez notre %{link_to_help_page} sur l’intégration d’une grappe de serveurs Kubernetes."
@@ -1850,7 +1963,7 @@ msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from th
msgstr "Supprimer la configuration de cette grappe de serveurs Kubernetes de ce projet. Cela ne supprimera pas votre grappe de serveurs Kubernetes actuelle."
msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
-msgstr ""
+msgstr "Vous pouvez remplacer ceci par un nom d’hôte personnalisé. Auquel cas, faites pointer ce nom d’hôte vers l’adresse IP d’Ingress ciâ€dessus."
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "La demande de lancement de l’installation a échoué"
@@ -1867,9 +1980,6 @@ msgstr "Rechercher des projets"
msgid "ClusterIntegration|Search zones"
msgstr "Rechercher les zones"
-msgid "ClusterIntegration|Security"
-msgstr "Sécurité"
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "Voir et modifier les détails de votre grappe de serveurs Kubernetes"
@@ -1907,16 +2017,13 @@ msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "Une erreur s’est produite lors de l’installation de %{title}"
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
-msgstr ""
-
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr "La configuration par défaut de la grappe de serveurs permet d’accéder à un large éventail de fonctionnalités nécessaires pour construire et déployer, avec succès, une application conteneurisée."
+msgstr "L’adresse IP est en cours d’affectation. Si cela dure trop longtemps, veuillez vérifier votre grappe de serveurs Kubernetes ou vos quotas sur Google Kubernetes Engine."
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr "Ce compte doit disposer des autorisations pour créer une grappe de serveurs Kubernetes dans le %{link_to_container_project} spécifié ciâ€dessous"
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
-msgstr "Activer la grappe de serveurs Kubernetes"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr "Cette option vous permettra d’installer des applications sur des grappes de serveurs avec contrôle d’accès basé sur le rôle (RBAC)."
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "Activer/désactiver la grappe de serveurs Kubernetes"
@@ -1928,11 +2035,14 @@ msgid "ClusterIntegration|Validating project billing status"
msgstr "Validation de l’état de la facturation du projet"
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
-msgstr ""
+msgstr "Nous n’avons pu vérifier que la facturation de l’un de vos projets sur Google Cloud Platform est bien activée. Veuillez réessayer."
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "Avec une grappe de serveurs Kubernetes associée à ce projet, vous pouvez utiliser des applications de revue, déployer vos applications, exécuter vos pipelines, et bien plus encore."
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr "Vous devez d’abord installer Helm Tiller avant d’installer les applications ciâ€dessous"
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Votre compte doit disposer de %{link_to_kubernetes_engine}"
@@ -1951,9 +2061,6 @@ msgstr "documentation"
msgid "ClusterIntegration|help page"
msgstr "page d’aide"
-msgid "ClusterIntegration|installing applications"
-msgstr "installation des applications"
-
msgid "ClusterIntegration|meets the requirements"
msgstr "répond aux exigences"
@@ -1963,6 +2070,9 @@ msgstr "correctement configuré"
msgid "ClusterIntegration|sign up"
msgstr "s’inscrire"
+msgid "Code owners"
+msgstr "Propriétaires du code"
+
msgid "Cohorts"
msgstr "Cohortes"
@@ -1972,12 +2082,18 @@ msgstr "Réduire"
msgid "Collapse sidebar"
msgstr "Masquer la barre latérale"
+msgid "Comment"
+msgstr "Commentaire"
+
msgid "Comment & resolve discussion"
msgstr "Commenter et marquer la discussion comme résolue"
msgid "Comment & unresolve discussion"
msgstr "Commenter et marquer la discussion comme non résolue"
+msgid "Comment form position"
+msgstr "Position du formulaire de commentaire"
+
msgid "Comments"
msgstr "Commentaires"
@@ -2012,6 +2128,9 @@ msgstr "Commit"
msgid "CommitMessage|Add %{file_name}"
msgstr "Ajout de %{file_name}"
+msgid "CommitWidget|authored"
+msgstr "réalisé"
+
msgid "Commits"
msgstr "Commits"
@@ -2084,8 +2203,8 @@ msgstr "Confidentialité"
msgid "Configure Gitaly timeouts."
msgstr "Configurer les délais d’expiration de Gitaly."
-msgid "Configure Sidekiq job throttling."
-msgstr "Configurer la limitation des tâches Sidekiq."
+msgid "Configure Tracing"
+msgstr "Configurer le traçage"
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr "Configurer les vérifications Git automatiques et la maintenance des dépôts."
@@ -2093,14 +2212,14 @@ msgstr "Configurer les vérifications Git automatiques et la maintenance des dé
msgid "Configure limits for web and API requests."
msgstr "Configurer les limites pour les requêtes Web et d’API."
-msgid "Configure push and pull mirrors."
-msgstr "Configurez les miroirs où récupérer et pousser le code."
+msgid "Configure push mirrors."
+msgstr "Configurez les miroirs où pousser le code."
-msgid "Configure storage path and circuit breaker settings."
-msgstr "Configurez les paramètres du chemin de stockage et du disjoncteur."
+msgid "Configure storage path settings."
+msgstr "Configurez le chemin d’accès au stockage."
msgid "Configure the %{link} integration."
-msgstr "Configurez l’intégration %{link}."
+msgstr "Configurez l’intégration de %{link}."
msgid "Configure the way a user creates a new account."
msgstr "Configurez la manière dont une personne crée un nouveau compte."
@@ -2186,6 +2305,9 @@ msgstr "Contribution"
msgid "Contribution guide"
msgstr "Guide de contribution"
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr "Contributions du <strong>%{calendar_date}</strong>"
+
msgid "Contributions per group member"
msgstr "Contributions par membre du groupe"
@@ -2219,6 +2341,18 @@ msgstr "Contrôle la concurrence maximale des opérations de vérification pour
msgid "ConvDev Index"
msgstr "Index ConvDev"
+msgid "Copy %{protocol} clone URL"
+msgstr "Copier l’URL %{protocol} de clonage"
+
+msgid "Copy HTTPS clone URL"
+msgstr "Copier l’URL HTTPS de clonage"
+
+msgid "Copy ID to clipboard"
+msgstr "Copier l’identifiant dans le presseâ€papiers"
+
+msgid "Copy SSH clone URL"
+msgstr "Copier l’URL SSH de clonage"
+
msgid "Copy SSH public key to clipboard"
msgstr "Copier la clef SSH publique dans le presseâ€papiers"
@@ -2240,15 +2374,27 @@ msgstr "Copier le chemin d’accès du fichier dans le presseâ€papiers"
msgid "Copy incoming email address to clipboard"
msgstr "Copier l’adresse de courriel de l’expéditeur dans le presse-papiers"
+msgid "Copy link"
+msgstr "Copier le lien"
+
+msgid "Copy name to clipboard"
+msgstr "Copier le nom dans le presseâ€papiers"
+
msgid "Copy reference to clipboard"
msgstr "Copier la référence dans le presseâ€papiers"
+msgid "Copy secret to clipboard"
+msgstr "Copier le secret dans le presseâ€papiers"
+
msgid "Copy to clipboard"
msgstr "Copier dans le presseâ€papiers"
msgid "Copy token to clipboard"
msgstr "Copier le jeton dans le presseâ€papiers"
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr "Impossible de récupérer l’état du pipeline. Pour obtenir un dépannage pas à pas, veuillez vous référer à la %{linkStart}documentation%{linkEnd}."
+
msgid "Create"
msgstr "Créer"
@@ -2324,8 +2470,8 @@ msgstr "Créer un nouveau…"
msgid "Create project label"
msgstr "Créer une étiquette de projet"
-msgid "CreateNewFork|Fork"
-msgstr "Créer une divergence"
+msgid "Create your first page"
+msgstr "Créer votre première page"
msgid "CreateTag|Tag"
msgstr "Étiquette"
@@ -2375,6 +2521,9 @@ msgstr "Personnalisé"
msgid "Custom CI config path"
msgstr "Chemin d’accès de la config d’intégration continue personnalisée"
+msgid "Custom hostname (for private commit emails)"
+msgstr "Nom d’hôte personnalisé (pour les courriels de commit privés)"
+
msgid "Custom notification events"
msgstr "Événements de notification personnalisés"
@@ -2393,6 +2542,9 @@ msgstr "Personnalisez la manière dont les adresses de courriel et les noms d’
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr "Personnalisez la manière dont les adresses de courriel et les noms d’utilisateur provenant de Google Code sont importés dans GitLab. À la prochaine étape, vous pourrez sélectionner les projets que vous souhaitez importer."
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr "Personnalisez la configuration de votre pipeline et affichez son état et le rapport de couverture."
+
msgid "Cycle Analytics"
msgstr "Analyse de cycle"
@@ -2444,6 +2596,9 @@ msgstr "décembre"
msgid "Decline and sign out"
msgstr "Refuser et se déconnecter"
+msgid "Default Branch"
+msgstr "Branche par défaut"
+
msgid "Default classification label"
msgstr "Étiquette de classement par défaut"
@@ -2456,6 +2611,21 @@ msgstr "Par défaut : associer un identifiant de compte FogBugz à un nom compl
msgid "Define a custom pattern with cron syntax"
msgstr "Définir un schéma personnalisé avec une syntaxe Cron"
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr "Êtesâ€vous sûr(e) de vouloir exécuter %{jobName} immédiatement ? Dans le cas contraire, cette tâche sera automatiquement exécutée à l’heure programmée."
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr "Êtesâ€vous sûr(e) de vouloir exécuter %{job_name} immédiatement ? Dans le cas contraire, cette tâche sera automatiquement exécutée à l’heure programmée."
+
+msgid "DelayedJobs|Start now"
+msgstr "Commencer maintenant"
+
+msgid "DelayedJobs|Unschedule"
+msgstr "Déprogrammer"
+
+msgid "DelayedJobs|delayed"
+msgstr "différé"
+
msgid "Delete"
msgstr "Supprimer"
@@ -2465,6 +2635,9 @@ msgstr "Supprimer le paquet"
msgid "Delete Snippet"
msgstr "Supprimer L’extrait de code"
+msgid "Delete comment"
+msgstr "Supprimer le commentaire"
+
msgid "Delete list"
msgstr "Supprimer la liste"
@@ -2602,6 +2775,12 @@ msgstr "Votre nouveau jeton de déploiement"
msgid "DeployTokens|Your new project deploy token has been created."
msgstr "Votre nouveau jeton de déploiement pour votre projet a été créé."
+msgid "Deployed to"
+msgstr "Déployé sur"
+
+msgid "Deploying to"
+msgstr "En cours de déploiement sur"
+
msgid "Deprioritize label"
msgstr "Déprioriser l’étiquette"
@@ -2626,6 +2805,12 @@ msgstr "Détails"
msgid "Detect host keys"
msgstr "Détecter les clefs de l’hôte"
+msgid "Diff content limits"
+msgstr "Limites du contenu du diff"
+
+msgid "Diff limits"
+msgstr "Limites du diff"
+
msgid "Diffs|No file name available"
msgstr "Aucun nom de fichier disponible"
@@ -2647,12 +2832,27 @@ msgstr "Désactiver pour ce projet"
msgid "Disable group Runners"
msgstr "Désactiver les exécuteurs de groupe"
+msgid "Discard"
+msgstr "Rejeter"
+
+msgid "Discard all changes"
+msgstr "Rejeter tous les changements"
+
+msgid "Discard all unstaged changes?"
+msgstr "Rejeter toutes les modifications non indexées ?"
+
msgid "Discard changes"
msgstr "Abandonner les modifications"
+msgid "Discard changes to %{path}?"
+msgstr "Rejeter les modifications de %{path} ?"
+
msgid "Discard draft"
msgstr "Abandonner le brouillon"
+msgid "Discard review"
+msgstr "Rejeter la revue de code"
+
msgid "Discover GitLab Geo."
msgstr "Découvrez GitLab Geo."
@@ -2668,6 +2868,9 @@ msgstr "Passer l’introduction à Cycle Analytics"
msgid "Dismiss Merge Request promotion"
msgstr "Rejeter la promotion de la demande de fusion"
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "Voulezâ€vous personnaliser la manière dont les adresses de courriel et les noms d’utilisateurs issus de Google Code sont importés dans GitLab ?"
@@ -2749,8 +2952,8 @@ msgstr "Modifier l’identité de %{user_name}"
msgid "Elasticsearch"
msgstr "Elasticsearch"
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
-msgstr "Intégration d’Elasticsearch. AWS Elasticsearch IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
msgid "Email"
msgstr "Courriel"
@@ -2794,9 +2997,6 @@ msgstr "Activer pour ce projet"
msgid "Enable group Runners"
msgstr "Activer les exécuteurs de groupe"
-msgid "Enable or disable certain group features and choose access levels."
-msgstr "Activer ou désactiver certaines fonctions de groupe et choisir les niveaux d’accès."
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "Activer ou désactiver la collecte de données Pseudonymizer."
@@ -2809,6 +3009,12 @@ msgstr "Activer reCAPTCHA ou Akismet et définir des limites d’adresse IP."
msgid "Enable the Performance Bar for a given group."
msgstr "Activer la barre de performance pour un groupe donné."
+msgid "Enable usage ping"
+msgstr "Activer la collecte des données d’utilisation"
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr "Activez la collecte des données d’utilisation afin d’avoir une vue d’ensemble de la manière dont vous utilisez les fonctionnalités de GitLab."
+
msgid "Enabled"
msgstr "activé"
@@ -2861,7 +3067,7 @@ msgid "Environments|Environments"
msgstr "Environnements"
msgid "Environments|Environments are places where code gets deployed, such as staging or production."
-msgstr ""
+msgstr "Les environnements sont des endroits où le code est déployé, tel que l’étape ou la production."
msgid "Environments|Job"
msgstr "Tâche"
@@ -2911,8 +3117,8 @@ msgstr "Arrêter l’environnement"
msgid "Environments|Updated"
msgstr "Mis à jour"
-msgid "Environments|You don't have any environments right now."
-msgstr "Vous n’avez aucun environnement pour le moment."
+msgid "Environments|You don't have any environments right now"
+msgstr "Vous n’avez pour le moment aucun environnement"
msgid "Environments|protected"
msgstr "protégé"
@@ -2944,11 +3150,11 @@ msgstr "En savoir plus"
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr "Ces dates affectent la manière dont vos épopées apparaissent sur la feuille de route. Les dates des jalons proviennent des jalons attribués aux tickets de l’épopée. Vous pouvez également définir des dates fixes ou les supprimer complètement."
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
-msgstr "fini"
+msgid "Epics|due"
+msgstr "Échéance"
msgid "Epics|start"
msgstr "commence"
@@ -3058,6 +3264,12 @@ msgstr "Tout étendre"
msgid "Expand sidebar"
msgstr "Étendre la barre latérale"
+msgid "Expiration date"
+msgstr "Date d’expiration"
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr "Décrivez le problème. Le cas échéant, fournissez un lien vers un ticket ou un commentaire idoine."
+
msgid "Explore"
msgstr "Explorer"
@@ -3112,6 +3324,12 @@ msgstr "Échec du changement de propriétaire"
msgid "Failed to check related branches."
msgstr "Échec de la vérification des branches liées."
+msgid "Failed to deploy to"
+msgstr "Échec du déploiement sur"
+
+msgid "Failed to load emoji list."
+msgstr "Impossible de charger la liste des émojis."
+
msgid "Failed to remove issue from board, please try again."
msgstr "Impossible de supprimer le ticket du tableau, veuillez réessayer."
@@ -3121,6 +3339,9 @@ msgstr "Impossible de supprimer le miroir."
msgid "Failed to remove the pipeline schedule"
msgstr "Échec de la suppression du pipeline programmé"
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr "Échec de la mise à jour du ticket. Veuillez réessayer."
@@ -3130,6 +3351,81 @@ msgstr "Échec"
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr "Plus rapide parce qu’il réutilise l’espace de travail du projet (faire un clone en solution de secours s’il n’existe pas)"
+msgid "Feature Flags"
+msgstr "Indicateurs de fonctionnalités"
+
+msgid "FeatureFlags|API URL"
+msgstr "URL de l’API"
+
+msgid "FeatureFlags|Active"
+msgstr "Actif"
+
+msgid "FeatureFlags|Application name"
+msgstr "Nom de l’application"
+
+msgid "FeatureFlags|Configure"
+msgstr "Configurer"
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr "Configurer les indicateurs de fonctionnalité"
+
+msgid "FeatureFlags|Create feature flag"
+msgstr "Créer un indicateur de fonctionnalité"
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr "Supprimer %{feature_flag_name} ?"
+
+msgid "FeatureFlags|Description"
+msgstr "Description"
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr "Modifier %{feature_flag_name}"
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr "Modifier l’indicateur de fonctionnalité"
+
+msgid "FeatureFlags|Feature Flag"
+msgstr "Indicateur de fonctionnalité"
+
+msgid "FeatureFlags|Feature flag"
+msgstr "Indicateur de fonctionnalité"
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr "L’indicateur de fonctionnalité %{feature_flag_name} va être supprimé. Êtesâ€vous sûr(e) ?"
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr "Les indicateurs de fonctionnalités vous permettent de configurer votre code de différentes manières en activant dynamiquement ou non certaines fonctionnalités."
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr "Découvrez les indicateurs de fonctionnalité"
+
+msgid "FeatureFlags|Inactive"
+msgstr "Inactif"
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr "Installez une %{docs_link_start}bibliothèque cliente compatible%{docs_link_end} et spécifiez l’URL de l’API, le nom de l’application et l’identifiant d’instance lors de la configuration."
+
+msgid "FeatureFlags|Instance ID"
+msgstr "Identifiant d’instance"
+
+msgid "FeatureFlags|More information"
+msgstr "Plus d’informations"
+
+msgid "FeatureFlags|Name"
+msgstr "Nom"
+
+msgid "FeatureFlags|New"
+msgstr "Nouveau"
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr "Nouvel indicateur de fonctionnalité"
+
+msgid "FeatureFlags|Save changes"
+msgstr "Enregistrer les modifications"
+
+msgid "FeatureFlags|Status"
+msgstr "État"
+
msgid "Feb"
msgstr "févr."
@@ -3139,6 +3435,9 @@ msgstr "février"
msgid "Fields on this page are now uneditable, you can configure"
msgstr "Les champs de cette page sont désormais non modifiables, vous pouvez configurer"
+msgid "File templates"
+msgstr "Modèles de fichiers"
+
msgid "Files"
msgstr "Fichiers"
@@ -3149,11 +3448,20 @@ msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and p
msgstr "Renseignez les champs ciâ€dessous, activez <strong>%{enable_label}</strong> et appuyez sur <strong>%{save_changes}</strong>"
msgid "Filter"
-msgstr ""
+msgstr "Filtrer"
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr "Filtrer sur les tickets de type %{issuable_type} qui sont actuellement fermés."
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr "Filtrer sur les tickets de type %{issuable_type} qui sont actuellement ouverts."
msgid "Filter by commit message"
msgstr "Filtrer par message de commit"
+msgid "Filter..."
+msgstr "Filtrer…"
+
msgid "Find by path"
msgstr "Rechercher par chemin d’accès"
@@ -3169,6 +3477,9 @@ msgstr "Cherchez le fichier <code>Takeout/Google Code Project Hosting/GoogleC
msgid "Fingerprints"
msgstr "Empreintes"
+msgid "Finish review"
+msgstr "Terminer la revue de code"
+
msgid "Finished"
msgstr "Terminé"
@@ -3181,8 +3492,8 @@ msgstr "poussé par"
msgid "Fixed date"
msgstr "Date fixée"
-msgid "Fixed finish date"
-msgstr "Date de fin fixe"
+msgid "Fixed due date"
+msgstr "Date d’échéance fixée"
msgid "Fixed start date"
msgstr "Date de début fixe"
@@ -3220,17 +3531,18 @@ msgstr "Pour les projets internes, tout utilisateur connecté peut afficher les
msgid "For more information, go to the "
msgstr "Pour plus d’informations, consultez "
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr "Pour plus d’informations, veuillez consulter la %{link_start_tag}documentation sur la configuration de Jaeger%{link_end_tag}"
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr "Pour plus d’informations, consultez la documentation sur la %{deactivating_usage_ping_link_start}désactivation de la collecte des données d’utilisation%{deactivating_usage_ping_link_end}."
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr "Pour les projets privés, tout membre (invité ou supérieur) peut afficher les pipelines et accéder aux détails des tâches (journaux de sortie et artefacts)"
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr "Pour les projets publics, tout le monde peut afficher des pipelines et accéder aux détails des tâches (journaux de sortie et artefacts)"
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] "Divergence"
-msgstr[1] "Divergences"
-
msgid "ForkedFromProjectPath|Forked from"
msgstr "Divergence issue de"
@@ -3246,6 +3558,9 @@ msgstr "Format"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr "Erreurs trouvées dans votre fichier .gitlab-ci.yml :"
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr "De %{provider_title}"
@@ -3288,6 +3603,9 @@ msgstr "Pipelines généraux"
msgid "Generate a default set of labels"
msgstr "Générer un jeu d’étiquettes par défaut"
+msgid "Geo"
+msgstr "Geo"
+
msgid "Geo Nodes"
msgstr "NÅ“uds Geo"
@@ -3462,11 +3780,23 @@ msgstr "%{name} est programmé pour la revérification"
msgid "Geo|%{name} is scheduled for re-sync"
msgstr "%{name} est programmé pour la reâ€synchronisation"
+msgid "Geo|All"
+msgstr "Tous"
+
msgid "Geo|All projects"
msgstr "Tous les projets"
-msgid "Geo|Error message"
-msgstr "Indication d’erreur"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr "Tous les projets ont été planifiés pour revérification"
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr "Tous les projets ont été planifiés pour resynchronisation"
+
+msgid "Geo|Batch operations"
+msgstr "Opérations par lot"
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr "Impossible de supprimer l’entrée de suivi d’un projet existant."
msgid "Geo|Failed"
msgstr "En échec"
@@ -3474,6 +3804,9 @@ msgstr "En échec"
msgid "Geo|File sync capacity"
msgstr "Capacité de synchronisation de fichiers"
+msgid "Geo|Geo Status"
+msgstr "État de Geo"
+
msgid "Geo|Groups to synchronize"
msgstr "Groupes à synchroniser"
@@ -3495,8 +3828,8 @@ msgstr "Jamais"
msgid "Geo|Next sync scheduled at"
msgstr "Prochaine synchro programmée à"
-msgid "Geo|No errors"
-msgstr "Aucune erreur"
+msgid "Geo|Not synced yet"
+msgstr "Pas encore synchronisé"
msgid "Geo|Pending"
msgstr "En attente"
@@ -3507,6 +3840,9 @@ msgstr "En attente de synchronisation"
msgid "Geo|Pending verification"
msgstr "En attente de vérification"
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr "Le projet (identifiant : %{project_id}) n’existe plus sur le primaire. Vous pouvez supprimer cette entrée en toute sécurité, car cela ne supprimera aucune donnée sur le disque."
+
msgid "Geo|Projects in certain groups"
msgstr "Projets de certains groupes"
@@ -3516,19 +3852,25 @@ msgstr "Projets dans certains fragments de stockage"
msgid "Geo|Recheck"
msgstr "Revérifier"
+msgid "Geo|Recheck all projects"
+msgstr "Revérifier tous les projets"
+
msgid "Geo|Redownload"
msgstr "Reâ€télécharger"
+msgid "Geo|Remove"
+msgstr "Supprimer"
+
msgid "Geo|Repository sync capacity"
msgstr "Capacité de synchronisation du dépôt"
msgid "Geo|Resync"
msgstr "Reâ€synchroniser"
-msgid "Geo|Retry count"
-msgstr "Nombre de tentatives"
+msgid "Geo|Resync all projects"
+msgstr "Resynchroniser tous les projets"
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr "Nombre de tentatives"
msgid "Geo|Select groups to replicate."
@@ -3546,6 +3888,12 @@ msgstr "Synchronisé"
msgid "Geo|Synchronization failed - %{error}"
msgstr "Synchro en échec — %{error}"
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr "L’entrée de suivi du projet (%{project_id}) a été supprimée avec succès."
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr "L’entrée de suivi va être supprimée. Êtesâ€vous sur(e) ?"
+
msgid "Geo|Unknown state"
msgstr "État inconnu"
@@ -3558,9 +3906,27 @@ msgstr "Vérification en échec — %{error}"
msgid "Geo|Waiting for scheduler"
msgstr "En attente de planification"
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr "Vous êtes sur un nœud Geo secondaire <b>en lecture seule</b>. Si vous voulez apporter des modifications, vous devez le faire depuis cette page sur le %{primary_node}."
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr "Vous êtes sur un nœud Geo secondaire <b>en lecture seule</b>. Nous ne pourrez effectuer que des modifications ou des actions limitées depuis cette page."
+
msgid "Geo|You need a different license to use Geo replication"
msgstr "Il faut une licence différente pour utiliser la réplication géographique"
+msgid "Geo|misconfigured"
+msgstr "mal configuré"
+
+msgid "Geo|primary"
+msgstr "primaire"
+
+msgid "Geo|secondary"
+msgstr "secondaire"
+
+msgid "Get a free instance review"
+msgstr "Obtenez une revue d’instance gratuite"
+
msgid "Git"
msgstr "Git"
@@ -3570,9 +3936,6 @@ msgstr "URL du dépôt Git"
msgid "Git revision"
msgstr "Révision de Git"
-msgid "Git storage health information has been reset"
-msgstr "Les informations sur l’état de santé du stockage Git ont été réinitialisées"
-
msgid "Git strategy for pipelines"
msgstr "Stratégie Git pour les pipelines"
@@ -3639,12 +4002,6 @@ msgstr "Aller vers"
msgid "Go to %{link_to_google_takeout}."
msgstr "Consultez le site de %{link_to_google_takeout}."
-msgid "Go to your fork"
-msgstr "Aller à votre dépôt divergent"
-
-msgid "GoToYourFork|Fork"
-msgstr "Dépôt divergent"
-
msgid "Google Code import"
msgstr "Importation depuis Google Code"
@@ -3675,9 +4032,21 @@ msgstr "Identifiant du groupe"
msgid "Group Runners"
msgstr "Exécuteurs de groupe"
+msgid "Group SAML must be enabled to test"
+msgstr "Le SAML de groupe doit être activé afin de pouvoir tester"
+
+msgid "Group URL"
+msgstr "URL du groupe"
+
msgid "Group avatar"
msgstr "Avatar de groupe"
+msgid "Group description"
+msgstr "Description du groupe"
+
+msgid "Group description (optional)"
+msgstr "Description du groupe (optionnel)"
+
msgid "Group details"
msgstr "Détails du groupe"
@@ -3687,6 +4056,9 @@ msgstr "Informations du groupe :"
msgid "Group maintainers can register group runners in the %{link}"
msgstr "Les responsables de groupe peuvent créer des exécuteurs de groupe via %{link}"
+msgid "Group name"
+msgstr "Nom du groupe"
+
msgid "Group: %{group_name}"
msgstr "Groupe : %{group_name}"
@@ -3705,14 +4077,14 @@ msgstr "Désolé, aucune épopée ne correspond à votre recherche"
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr "La feuille de route affiche la progression de vos épopées dans le temps"
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Pour afficher la feuille de route, ajoutez une date prévisionnelle de début ou de fin à l’une de vos épopées dans ce groupe ou ses sousâ€groupes. Dans la vue multiâ€mensuelle, seules les épopées du mois dernier, du mois courant et des cinq prochains mois sont affichées, du %{startDate} au %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr "Afin d’afficher la feuille de route, ajoutez une date de début ou d’échéance à l’une de vos épopées dans ce groupe ou ses sousâ€groupes. Dans la vue multiâ€mensuelle, seules les épopées du mois dernier, du mois courant et des cinq prochains mois sont affichées, du %{startDate} au %{endDate}."
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Pour afficher la feuille de route, ajoutez une date prévisionnelle de début ou de fin à l’une de vos épopées dans ce groupe ou ses sousâ€groupes. Dans la vue multiâ€trimestrielle, seules les épopées du trimestre dernier, du trimestre courant et des quatre prochains trimestres sont affichées, du %{startDate} au %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr "Pour afficher la feuille de route, ajoutez une date de début ou d’échéance à l’une de vos épopées dans ce groupe ou ses sousâ€groupes. Dans la vue multiâ€trimestrielle, seules les épopées du trimestre dernier, du trimestre courant et des quatre prochains trimestres sont affichées, du %{startDate} au %{endDate}."
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Pour afficher la feuille de route, ajoutez une date prévisionnelle de début ou de fin à l’une de vos épopées dans ce groupe ou ses sousâ€groupes. Dans la vue multiâ€hebdomadaire, seules les épopées de la semaine dernière, de la semaine courante et des quatre prochaines semaines sont affichées, du %{startDate} au %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr "Pour afficher la feuille de route, ajoutez une date de début ou d’échéance à l’une de vos épopées dans ce groupe ou ses sousâ€groupes. Dans la vue multiâ€hebdomadaire, seules les épopées de la semaine dernière, de la semaine courante et des quatre prochaines semaines sont affichées, du %{startDate} au %{endDate}."
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr "Afin d’élargir votre recherche, modifiez ou supprimez des filtres. Dans la vue multiâ€mensuelle, seules les épopées du mois dernier, du mois courant et des cinq prochains mois sont affichées, du %{startDate} au %{endDate}."
@@ -3727,20 +4099,17 @@ msgid "GroupRoadmap|Until %{dateWord}"
msgstr "Jusqu’au %{dateWord}"
msgid "GroupSettings|Badges"
-msgstr ""
+msgstr "Badges numériques"
msgid "GroupSettings|Customize your group badges."
-msgstr ""
+msgstr "Personnalisez vos badges numériques de groupe."
msgid "GroupSettings|Learn more about badges."
-msgstr ""
+msgstr "En savoir plus sur les badges numériques."
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Empêcher le partage d’un projet du groupe %{group} avec d’autres groupes"
-msgid "GroupSettings|Share with group lock"
-msgstr "Partager avec un verrou de groupe"
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "Ce paramètre s’applique au groupe %{ancestor_group} et a été forcé pour ce sousâ€groupe."
@@ -3798,6 +4167,9 @@ msgstr "Aucun groupe trouvé"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Vous pouvez gérer les autorisations des membres de votre groupe et accéder à chacun de ses projets."
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr "Êtes-vous sûr·e de vouloir quitter le groupe « %{fullName} » ?"
+
msgid "GroupsTree|Create a project in this group."
msgstr "Créez un projet dans ce groupe."
@@ -3810,20 +4182,20 @@ msgstr "Modifier le groupe"
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr "Impossible de quitter le groupe. Veuillez vous assurer que vous n’êtes pas seul·e propriétaire."
-msgid "GroupsTree|Filter by name..."
-msgstr "Filtrer par nom…"
-
msgid "GroupsTree|Leave this group"
msgstr "Quitter ce groupe"
msgid "GroupsTree|Loading groups"
msgstr "Chargement des groupes"
-msgid "GroupsTree|Sorry, no groups matched your search"
-msgstr "Désolé, aucun groupe ne correspond à vos critères de recherche"
+msgid "GroupsTree|No groups matched your search"
+msgstr "Aucun groupe ne correspond à votre recherche"
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr "Aucun groupe ni projet ne correspond à votre recherche"
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
-msgstr "Désolé, aucun groupe ni projet ne correspond à vos critères de recherche"
+msgid "GroupsTree|Search by name"
+msgstr "Rechercher par nom"
msgid "Have your users email"
msgstr "Récupérer les adresses de courriel des utilisateurs"
@@ -3864,6 +4236,9 @@ msgstr "Voici la clef SSH publique qui doit être ajoutée sur le serveur distan
msgid "Hide host keys manual input"
msgstr "Masquer la saisie manuelle des clefs d’hôtes"
+msgid "Hide payload"
+msgstr "Masquer la charge utile"
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Masquer la valeur"
@@ -4028,6 +4403,9 @@ msgstr "Améliorez la gestion des tickets grâce à la pondération disponible d
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr "Améliorez vos recherches avec la recherche globale avancée de GitLab Enterprise Edition."
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr "Afin d’activer les statistiques au niveau de l’instance, veuillez demander à un administrateur d’activer la %{usage_ping_link_start}collecte des données d’utilisation%{usage_ping_link_end}."
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr "À la prochaine étape, vous pourrez sélectionner les projets que vous souhaitez importer."
@@ -4064,10 +4442,10 @@ msgstr[0] "Instance"
msgstr[1] "Instances"
msgid "Instance Statistics"
-msgstr ""
+msgstr "Statistiques de l’instance"
msgid "Instance Statistics visibility"
-msgstr ""
+msgstr "Visibilité des statistiques de l’instance"
msgid "Instance does not support multiple Kubernetes clusters"
msgstr "L’instance ne prend pas en charge plusieurs grappes de serveurs Kubernetes"
@@ -4096,6 +4474,12 @@ msgstr "Modèle d’intervalle"
msgid "Introducing Cycle Analytics"
msgstr "Introduction à l’analyseur de cycle"
+msgid "Invite"
+msgstr "Inviter"
+
+msgid "Issue"
+msgstr "Ticket"
+
msgid "Issue Boards"
msgstr "Tableaux des tickets"
@@ -4120,6 +4504,36 @@ msgstr "Les tickets peuvent être des bogues, des tâches ou des sujets de discu
msgid "Issues closed"
msgstr "Tickets clos"
+msgid "Issues, merge requests, pushes and comments."
+msgstr "Tickets, demandes de fusion, poussées Git et commentaires."
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr "Une fois que vous aurez commencé à créer des tickets d’incident en relation avec vos projets, nous pourrons commencer à en effectuer le suivi et afficher des statistiques les concernant"
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr "Tickets créés"
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr "Tickets créés par mois"
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr "Les 12 derniers mois"
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr "Désolé, aucun résultat ne correspond à vos critères de recherche"
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr "Il n’y a aucun ticket concernant les projets de votre groupe"
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr "Afin d’élargir votre recherche, modifiez ou supprimez des critères de recherche dans la barre de filtrage ciâ€dessus"
+
+msgid "Jaeger URL"
+msgstr "URL Jaeger"
+
+msgid "Jaeger tracing"
+msgstr "Traçage de Jaeger"
+
msgid "Jan"
msgstr "janv."
@@ -4135,29 +4549,26 @@ msgstr "La tâche a été supprimée"
msgid "Jobs"
msgstr "Tâches"
-msgid "Job|Are you sure you want to erase this job?"
-msgstr "Êtesâ€vous sûr de vouloir supprimer cette tâche ?"
-
msgid "Job|Browse"
msgstr "Parcourir"
msgid "Job|Complete Raw"
-msgstr ""
+msgstr "Brut complet"
msgid "Job|Download"
msgstr "Télécharger"
msgid "Job|Erase job log"
-msgstr ""
+msgstr "Effacer le journal de la tâche"
msgid "Job|Job artifacts"
-msgstr ""
+msgstr "Artefacts de la tâche"
msgid "Job|Job has been erased"
-msgstr ""
+msgstr "La tâche a été effacée"
msgid "Job|Job has been erased by"
-msgstr ""
+msgstr "La tâche a été supprimée par"
msgid "Job|Keep"
msgstr "Garder"
@@ -4169,16 +4580,16 @@ msgid "Job|Scroll to top"
msgstr "Faire défiler vers le haut"
msgid "Job|Show complete raw"
-msgstr ""
+msgstr "Afficher la version brute"
msgid "Job|The artifacts were removed"
msgstr "Les artefacts ont été supprimés"
-msgid "Job|The artifacts will be removed"
-msgstr "Les artefacts seront supprimés"
+msgid "Job|The artifacts will be removed in"
+msgstr "Les artefacts seront supprimés dans"
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
-msgstr ""
+msgstr "Cette tâche est bloquée, car aucun exécuteur en ligne n’est attribué au projet."
msgid "Jul"
msgstr "juill."
@@ -4192,12 +4603,6 @@ msgstr "juin"
msgid "June"
msgstr "juin"
-msgid "Koding"
-msgstr "Koding"
-
-msgid "Koding Dashboard"
-msgstr "Tableau de bord Koding"
-
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -4268,7 +4673,10 @@ msgid "Labels|Promote Label"
msgstr "Promouvoir l’étiquette"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
-msgstr ""
+msgstr "La promotion de l’étiquette « %{labelTitle} » va la rendre disponible pour tous les projets du groupe %{groupName}. Les étiquettes de projet ayant le même intitulé seront fusionnées. Cette action est irréversible."
+
+msgid "Large File Storage"
+msgstr "Stockage de fichiers volumineux"
msgid "Last %d day"
msgid_plural "Last %d days"
@@ -4281,12 +4689,18 @@ msgstr "Dernier pipeline"
msgid "Last commit"
msgstr "Dernier commit"
+msgid "Last contact"
+msgstr "Dernier contact"
+
msgid "Last edited %{date}"
msgstr "Dernière modification le %{date}"
msgid "Last edited by %{name}"
msgstr "Dernière modification par %{name}"
+msgid "Last reply by"
+msgstr "Dernière réponse de"
+
msgid "Last update"
msgstr "Dernière mise à jour"
@@ -4306,7 +4720,7 @@ msgid "Learn more"
msgstr "En savoir plus"
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
-msgstr ""
+msgstr "En savoir plus sur %{issue_boards_url}, afin de suivre des tickets dans de multiples listes, à l’aide des étiquettes, des personnes assignées et des jalons. Si une fonctionnalité concernant les tableaux des tickets vous manque, veuillez créer un ticket sur %{gitlab_issues_url}."
msgid "Learn more about Kubernetes"
msgstr "En savoir plus sur Kubernetes"
@@ -4335,23 +4749,38 @@ msgstr "Laisser les options « type de fichier » et « mode de livraisonÂ
msgid "License"
msgstr "Licence"
+msgid "LicenseManagement|Add a license"
+msgstr "Ajouter une licence"
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr "Ajouter manuellement des licences afin d’approuver ou mettre sur liste noire"
+
+msgid "LicenseManagement|Approve"
+msgstr "Approuver"
+
msgid "LicenseManagement|Approve license"
-msgstr ""
+msgstr "Approuver la licence"
msgid "LicenseManagement|Approve license?"
-msgstr ""
+msgstr "Approuver la licence ?"
msgid "LicenseManagement|Approved"
-msgstr ""
+msgstr "Approuvée"
+
+msgid "LicenseManagement|Blacklist"
+msgstr "Mettre sur liste noire"
msgid "LicenseManagement|Blacklist license"
-msgstr ""
+msgstr "Mettre la licence en liste noire"
msgid "LicenseManagement|Blacklist license?"
-msgstr ""
+msgstr "Mettre la licence en liste noire ?"
msgid "LicenseManagement|Blacklisted"
-msgstr ""
+msgstr "En liste noire"
+
+msgid "LicenseManagement|Cancel"
+msgstr "Annuler"
msgid "LicenseManagement|License"
msgstr "Licence"
@@ -4362,8 +4791,11 @@ msgstr "Gestion des licences"
msgid "LicenseManagement|License details"
msgstr "Détails de la licence"
+msgid "LicenseManagement|License name"
+msgstr "Nom de la licence"
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
-msgstr ""
+msgstr "Gérez les licences approuvées et sur liste noire pour ce projet."
msgid "LicenseManagement|Packages"
msgstr "Paquets"
@@ -4374,9 +4806,15 @@ msgstr "Supprimer la licence"
msgid "LicenseManagement|Remove license?"
msgstr "Supprimer la licence ?"
+msgid "LicenseManagement|Submit"
+msgstr "Envoyer"
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr "Il n’y a actuellement aucune licence approuvée ou sur liste noire pour ce projet."
+msgid "LicenseManagement|This license already exists in this project."
+msgstr "Cette licence existe déjà pour ce projet."
+
msgid "LicenseManagement|URL"
msgstr "URL"
@@ -4388,8 +4826,8 @@ msgstr "Licences"
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Affichage limité à %d événement maximum"
+msgstr[1] "Affichage limité à %d événements maximum"
msgid "LinkedIn"
msgstr "LinkedIn"
@@ -4403,6 +4841,9 @@ msgstr "Lister vos dépôts Gitea"
msgid "List available repositories"
msgstr "Lister les dépôts disponibles"
+msgid "List view"
+msgstr "Vue en liste"
+
msgid "List your Bitbucket Server repositories"
msgstr "Lister vos dépôts BitBucket Server"
@@ -4431,7 +4872,7 @@ msgid "Lock not found"
msgstr "Verrou non trouvé"
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
-msgstr ""
+msgstr "Verrouiller ce·t·te %{issuableDisplayName} ? Seuls les <strong>membres du projet</strong> seront en mesure de commenter."
msgid "Lock to current projects"
msgstr "Verrouiller aux projets en cours"
@@ -4448,6 +4889,9 @@ msgstr "Verrouillé aux projets en cours"
msgid "Locks give the ability to lock specific file or folder."
msgstr "Les verrous permettent de verrouiller un fichier ou un dossier spécifique."
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr "Journaux"
@@ -4461,7 +4905,7 @@ msgid "Manage Git repositories with fine-grained access controls that keep your
msgstr "Gérez les dépôts Git avec des contrôles d’accès très précis permettant de sécuriser votre code. Effectuez des revues de code et renforcez la collaboration avec les demandes de fusion Git. Chaque projet peut également avoir un système de tickets de suivi et un wiki."
msgid "Manage Web IDE features"
-msgstr ""
+msgstr "Gérer les fonctionnalités de l’EDI Web"
msgid "Manage access"
msgstr "Gestion des accès"
@@ -4517,17 +4961,47 @@ msgstr "Marquer comme fait"
msgid "Markdown enabled"
msgstr "Markdown activé"
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr "Ajouter une liste à puces"
+
+msgid "MarkdownToolbar|Add a link"
+msgstr "Ajouter un lien"
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr "Ajouter une liste numérotée"
+
+msgid "MarkdownToolbar|Add a table"
+msgstr "Ajouter un tableau"
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr "Ajouter une liste de tâches"
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr "Ajouter du texte en gras"
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr "Ajouter du texte en italique"
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr "Afficher en plein écran"
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr "Insérer une citation"
+
+msgid "MarkdownToolbar|Insert code"
+msgstr "Insérer du code"
+
msgid "Maven Metadata"
-msgstr ""
+msgstr "Métadonnées Maven"
msgid "Maven package"
-msgstr ""
+msgstr "Paquet Maven"
-msgid "Maximum git storage failures"
-msgstr "Nombre maximum d’échecs du stockage Git"
+msgid "Max access level"
+msgstr "Niveau d’accès maximum"
msgid "Maximum job timeout"
-msgstr ""
+msgstr "Durée maximale d’exécution de la tâche"
msgid "May"
msgstr "mai"
@@ -4535,6 +5009,12 @@ msgstr "mai"
msgid "Median"
msgstr "Médian"
+msgid "Member lock"
+msgstr "Verrouillage des membres"
+
+msgid "Member since %{date}"
+msgstr "Membre depuis le %{date}"
+
msgid "Members"
msgstr "Membres"
@@ -4568,6 +5048,21 @@ msgstr "Demandes de fusion"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "Les demandes de fusion permettent de proposer les modifications que vous avez apportées à un projet et de discuter de ces modifications avec les autres"
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr "Une erreur est survenue lors de l’enregistrement du brouillon du commentaire."
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr "La discussion reste à l’état « résolu »."
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr "La discussion reste à l’état « non résolu »."
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr "La discussion passera à l’état « résolu »."
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr "La discussion passera à l’état « non résolu »."
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr "Résoudre cette discussion avec un nouveau ticket"
@@ -4577,9 +5072,6 @@ msgstr "L’enregistrement du commentaire a échoué"
msgid "MergeRequests|Toggle comments for this file"
msgstr "Activer/désactiver les commentaires pour ce fichier"
-msgid "MergeRequests|Updating discussions failed"
-msgstr "Échec de la mise à jour des discussions"
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr "Afficher le fichier au commit %{commitId}"
@@ -4587,7 +5079,13 @@ msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr "Afficher le fichier remplacé au commit %{commitId}"
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
-msgstr ""
+msgstr "%{paragraphStart}a changé la description %{descriptionChangedTimes} fois %{timeDifferenceMinutes}%{paragraphEnd}"
+
+msgid "MergeRequest|Filter files"
+msgstr "Filtrer les fichiers"
+
+msgid "MergeRequest|No files found"
+msgstr "Aucun fichier trouvé"
msgid "Merged"
msgstr "Fusionnée"
@@ -4604,8 +5102,11 @@ msgstr "Métriques — Influx"
msgid "Metrics - Prometheus"
msgstr "Métriques — Prometheus"
+msgid "Metrics and profiling"
+msgstr "Statistiques et rapports"
+
msgid "Metrics|Business"
-msgstr ""
+msgstr "Affaires"
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr "Consultez la documentation sur l’intégration et la livraison continues (CI/CD) concernant le déploiement dans un environnement"
@@ -4707,19 +5208,19 @@ msgid "Milestone"
msgstr "Jalon"
msgid "Milestone lists not available with your current license"
-msgstr ""
+msgstr "La liste des jalons n’est pas disponible avec votre licence actuelle"
msgid "Milestone lists show all issues from the selected milestone."
-msgstr ""
+msgstr "Les listes de jalon affichent tous les tickets à partir du jalon sélectionné."
msgid "Milestones"
msgstr "Jalons"
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer définitivement le jalon %{milestoneTitle} et de le supprimer de %{issuesWithCount} et %{mergeRequestsWithCount}. La suppression est irréversible."
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
-msgstr ""
+msgstr "Vous êtes sur le point de supprimer définitivement le jalon %{milestoneTitle}. Ce jalon n’est actuellement référencé par aucun ticket ni aucune demande de fusion."
msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
msgstr "<p>%{milestonePromotion}</p> %{finalWarning}"
@@ -4749,22 +5250,22 @@ msgid "Milestones|This action cannot be reversed."
msgstr "Cette action ne peut pas être annulée."
msgid "Mirror a repository"
-msgstr ""
+msgstr "Créer un miroir de dépôt"
msgid "Mirror direction"
-msgstr ""
+msgstr "Sens du miroir"
msgid "Mirror repository"
msgstr ""
msgid "Mirror user"
-msgstr ""
+msgstr "Utilisateur accédant au miroir"
msgid "Mirrored repositories"
-msgstr ""
+msgstr "Dépôts mis en miroir"
msgid "Mirroring repositories"
-msgstr ""
+msgstr "Dépôts miroir"
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "ajouter une clef SSH"
@@ -4785,7 +5286,7 @@ msgid "More"
msgstr "Plus"
msgid "More actions"
-msgstr "Plus d’actions"
+msgstr "Autres actions"
msgid "More info"
msgstr "En savoir plus"
@@ -4820,6 +5321,9 @@ msgstr "Nommez votre clef personnelle avec un titre"
msgid "Name:"
msgstr "Nom :"
+msgid "Naming, visibility"
+msgstr "Nommage, visibilité"
+
msgid "Nav|Help"
msgstr "Aide"
@@ -4939,6 +5443,12 @@ msgstr "Aucune connexion n’a pu être établie avec un serveur Gitaly, veuille
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr "Aucune image de conteneur stockée pour ce projet. Ajoutezâ€en une en suivant les instructions ciâ€dessous."
+msgid "No contributions were found"
+msgstr "Aucune contribution n’a été trouvée"
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr "Aucune date d’échéance"
@@ -4948,9 +5458,6 @@ msgstr "Aucune estimation ou temps passé"
msgid "No file chosen"
msgstr "Aucun fichier sélectionné"
-msgid "No files found"
-msgstr "Aucun fichier trouvé"
-
msgid "No files found."
msgstr "Aucun fichier trouvé."
@@ -4960,6 +5467,9 @@ msgstr "Aucun ticket pour la période sélectionnée."
msgid "No labels with such name or description"
msgstr "Aucune étiquette avec un tel nom ou une telle description"
+msgid "No license. All rights reserved"
+msgstr "Aucune licence. Tous droits réservés"
+
msgid "No merge requests for the selected time period."
msgstr "Aucune demande de fusion pour la période sélectionnée."
@@ -4987,6 +5497,9 @@ msgstr "Rien n’a été poussé vers GIt durant la période sélectionnée."
msgid "No repository"
msgstr "Aucun dépôt"
+msgid "No runners found"
+msgstr "Aucun exécuteur trouvé"
+
msgid "No schedules"
msgstr "Aucune planification"
@@ -5023,6 +5536,9 @@ msgstr "Pas confidentiel·le"
msgid "Not enough data"
msgstr "Données insuffisantes"
+msgid "Not now"
+msgstr "Pas maintenant"
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr "Notez que la branche principale « master » est automatiquement protégée. %{link_to_protected_branches}"
@@ -5041,6 +5557,18 @@ msgstr "Remarque : Envisagez de demander à votre administra·teur·trice GitLa
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "Souhaitezâ€vous réellement annuler la création de ce commentaire ?"
+msgid "Notes|Collapse replies"
+msgstr "Réduire les réponses"
+
+msgid "Notes|Show all activity"
+msgstr "Afficher toute l’activité"
+
+msgid "Notes|Show comments only"
+msgstr "Afficher uniquement les commentaires"
+
+msgid "Notes|Show history only"
+msgstr "Afficher uniquement l’historique"
+
msgid "Notification events"
msgstr "Événement de notifications"
@@ -5057,7 +5585,7 @@ msgid "NotificationEvent|Merge merge request"
msgstr "Fusionner la demande de fusion"
msgid "NotificationEvent|New epic"
-msgstr ""
+msgstr "Nouvelle épopée"
msgid "NotificationEvent|New issue"
msgstr "Nouveau ticket"
@@ -5113,9 +5641,6 @@ msgstr "nov."
msgid "November"
msgstr "novembre"
-msgid "Number of access attempts"
-msgstr "Nombre de tentatives d’accès"
-
msgid "OK"
msgstr "OK"
@@ -5142,17 +5667,14 @@ msgstr "Un ou plusieurs de vos projets Bitbucket ne peuvent être importés dire
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "Un ou plusieurs de vos projets Google Code ne peuvent être importés directement dans GitLab parce qu’ils utilisent Subversion ou Mercurial comme gestionnaire de versions au lieu de Git."
-msgid "Online IDE integration settings."
-msgstr "Paramètres d’intégration de l’EDI en ligne."
-
msgid "Only admins"
-msgstr ""
+msgstr "Seulement les administrateurs"
msgid "Only comments from the following commit are shown below"
msgstr "Seuls les commentaires du commit suivant sont affichés ciâ€dessous"
msgid "Only mirror protected branches"
-msgstr ""
+msgstr "Ne mettre en miroir que les branches protégées"
msgid "Only project members can comment."
msgstr "Seuls les membres du projet peuvent commenter."
@@ -5166,6 +5688,9 @@ msgstr "Ouvrir"
msgid "Open in Xcode"
msgstr "Ouvrir dans Xcode"
+msgid "Open projects"
+msgstr "Ouvrir des projets"
+
msgid "Open sidebar"
msgstr "Ouvrir la barre latérale"
@@ -5190,6 +5715,21 @@ msgstr "Ouvrir dans une nouvelle fenêtre"
msgid "Operations"
msgstr "Opérations"
+msgid "Operations Dashboard"
+msgstr "Tableau de bord des opérations"
+
+msgid "Operations Settings"
+msgstr "Paramètres des opérations"
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr "Ajouter un projet au tableau de bord"
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr "Le tableau de bord des opérations fournit un résumé de l’état de santé opérationnel de chaque projet, comprenant les états des pipelines et des alertes."
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr "Impossible d’ajouter %{invalidProjects}. Le tableau de bord des opérations n’est disponible que pour les projets avec un abonnement Gold."
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "Vous pouvez éventuellement %{link_to_customize} la manière dont les adresses de courriel et les noms d’utilisateur issus de FogBugz sont importés dans GitLab."
@@ -5218,7 +5758,7 @@ msgid "Overview"
msgstr "Vue d’ensemble"
msgid "Overwrite diverged branches"
-msgstr ""
+msgstr "Écraser les branches divergentes"
msgid "Owner"
msgstr "Propriétaire"
@@ -5256,6 +5796,9 @@ msgstr "Mot de Passe"
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr "Collez votre clef SSH publique, qui est habituellement située dans le fichier « ~/.ssh/id_rsa.pub » et commence par « ssh-rsa ». N’utilisez pas votre clef SSH privée !"
+msgid "Path, transfer, remove"
+msgstr "Chemin d’accès, transfert et suppression"
+
msgid "Path:"
msgstr "Chemin d’accès :"
@@ -5269,7 +5812,7 @@ msgid "Pending"
msgstr "En attente"
msgid "People without permission will never get a notification and won't be able to comment."
-msgstr ""
+msgstr "Les personnes sans autorisation ne recevront jamais de notifications et ne pourront pas commenter."
msgid "Per job. If a job passes this threshold, it will be marked as failed"
msgstr "Par tâche. Si une tâche dépasse ce seuil, elle sera marquée comme ayant échoué"
@@ -5283,15 +5826,15 @@ msgstr "Optimisation des performances"
msgid "Permissions"
msgstr "Droits d’accès"
+msgid "Permissions, LFS, 2FA"
+msgstr "Autorisations, LFS, 2FA"
+
msgid "Personal Access Token"
msgstr "Jeton d’accès personnel"
msgid "Pipeline"
msgstr "Pipeline"
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
-msgstr ""
-
msgid "Pipeline Health"
msgstr "État de santé du pipeline"
@@ -5380,7 +5923,7 @@ msgid "Pipelines|Clear Runner Caches"
msgstr "Vider les caches des exécuteurs"
msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
-msgstr ""
+msgstr "L’intégration continue peut aider à détecter les bogues en exécutant vos tests automatiquement, tandis que la livraison continue peut vous aider à déployer du code dans votre environnement de production."
msgid "Pipelines|Get started with Pipelines"
msgstr "Premiers pas avec les pipelines"
@@ -5404,20 +5947,29 @@ msgid "Pipelines|There are currently no pipelines."
msgstr "Il n’y a actuellement aucun pipeline."
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
-msgstr ""
+msgstr "Une erreur est survenue lors de la récupération des pipelines. Réessayez dans quelques instants ou contactez votre équipe d’assistance."
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "Ce projet n’est actuellement pas configuré pour exécuter des pipelines."
+msgid "Pipeline|Commit"
+msgstr "Commit"
+
msgid "Pipeline|Create for"
msgstr "Créer pour"
msgid "Pipeline|Create pipeline"
msgstr "Créer un pipeline"
+msgid "Pipeline|Duration"
+msgstr "Durée"
+
msgid "Pipeline|Existing branch name or tag"
msgstr "Nom de branche ou d’étiquette existant"
+msgid "Pipeline|Pipeline"
+msgstr "Pipeline"
+
msgid "Pipeline|Run Pipeline"
msgstr "Exécuter le pipeline"
@@ -5427,6 +5979,12 @@ msgstr "Chercher des branches"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr "Spécifier la valeur de la variable à utiliser lors de l’exécution. Les valeurs spécifiées dans %{settings_link} seront utilisées par défaut."
+msgid "Pipeline|Stages"
+msgstr "Étapes"
+
+msgid "Pipeline|Status"
+msgstr "État"
+
msgid "Pipeline|Stop pipeline"
msgstr "Arrêter le pipeline"
@@ -5454,12 +6012,6 @@ msgstr "avec les étapes"
msgid "Plain diff"
msgstr "Diff brut"
-msgid "Planned finish date"
-msgstr "Date de fin prévisionnelle"
-
-msgid "Planned start date"
-msgstr "Date de début prévisionnelle"
-
msgid "PlantUML"
msgstr "PlantUML"
@@ -5469,12 +6021,18 @@ msgstr "Lancer"
msgid "Please accept the Terms of Service before continuing."
msgstr "Veuillez accepter les conditions générales d’utilisation avant de continuer."
+msgid "Please choose a group URL with no special characters."
+msgstr "Veuillez choisir une URL de groupe sans caractères spéciaux."
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr "Veuillez les convertir en %{link_to_git} et repasser par %{link_to_import_flow}."
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr "Veuillez les convertir en dépôts Git sur Google Code et repasser par %{link_to_import_flow}."
+msgid "Please fill in a descriptive name for your group."
+msgstr "Veuillez saisir un nom descriptif pour votre groupe."
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "Veuillez noter que cette application n’est pas fournie par GitLab, vous devriez vérifier son authenticité avant d’autoriser son accès."
@@ -5487,6 +6045,9 @@ msgstr "Veuillez résoudre le reCAPTCHA"
msgid "Please try again"
msgstr "Veuillez réessayer"
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr "Veuillez utiliser ce formulaire pour signaler à GitLab les utilisateurs qui créent des tickets ou des commentaires indésirables, ou qui se comportent de manière inappropriée."
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr "Veuillez patienter pendant la connexion à votre dépôt. Actualisez à votre guise."
@@ -5499,9 +6060,18 @@ msgstr "Préférences"
msgid "Preferences|Navigation theme"
msgstr "Thème de navigation"
+msgid "Press Enter or click to search"
+msgstr "Appuyez sur Entrée ou cliquez pour rechercher"
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr "Empêcher l’ajout de nouveaux membres au projet au sein de ce groupe"
+
msgid "Preview"
msgstr "Aperçu"
+msgid "Preview payload"
+msgstr "Aperçu de la charge utile"
+
msgid "Primary"
msgstr "Principal"
@@ -5547,15 +6117,30 @@ msgstr "Ajouter une clef"
msgid "Profiles|Add status emoji"
msgstr "Ajouter un émoji de statut"
+msgid "Profiles|Avatar cropper"
+msgstr "Rogneur d’avatar"
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr "L’avatar sera supprimé. Êtesâ€vous sûr·e ?"
+
msgid "Profiles|Change username"
msgstr "Changer le nom d’utilisateur·rice"
+msgid "Profiles|Choose file..."
+msgstr "Choisir un fichier…"
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr "Afficher les contributions de projets privés sur votre profil public sans aucune information sur les projets, les dépôts ou les organisations."
+
msgid "Profiles|Clear status"
msgstr "Effacer le statut"
msgid "Profiles|Current path: %{path}"
msgstr "Chemin d’accès actuel : %{path}"
+msgid "Profiles|Current status"
+msgstr "État actuel"
+
msgid "Profiles|Delete Account"
msgstr "Supprimer un compte"
@@ -5568,20 +6153,77 @@ msgstr "Supprimer votre compte ?"
msgid "Profiles|Deleting an account has the following effects:"
msgstr "Supprimer un compte aura les conséquences suivantes :"
+msgid "Profiles|Do not show on profile"
+msgstr "Ne pas montrer sur le profil"
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr "Ne pas afficher les informations personnelles liées à l’activité sur vos profils"
+
+msgid "Profiles|Edit Profile"
+msgstr "Modifier le profil"
+
msgid "Profiles|Invalid password"
msgstr "Mot de passe incorrect"
msgid "Profiles|Invalid username"
msgstr "Nom d’utilisateur incorrect"
+msgid "Profiles|Learn more"
+msgstr "En savoir plus"
+
+msgid "Profiles|Made a private contribution"
+msgstr "a fait une contribution privée"
+
+msgid "Profiles|Main settings"
+msgstr "Paramètres principaux"
+
+msgid "Profiles|No file chosen"
+msgstr "Aucun fichier choisi"
+
msgid "Profiles|Path"
msgstr "Chemin d’accès"
+msgid "Profiles|Position and size your new avatar"
+msgstr "Position et taille de votre nouvel avatar"
+
+msgid "Profiles|Private contributions"
+msgstr "Contributions privées"
+
+msgid "Profiles|Public Avatar"
+msgstr "Avatar public"
+
+msgid "Profiles|Remove avatar"
+msgstr "Supprimer l’avatar"
+
+msgid "Profiles|Set new profile picture"
+msgstr "Définir une nouvelle photo de profil"
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr "Certaines options ne sont pas disponibles pour les comptes LDAP"
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr "Parlezâ€nous de vous en moins de 250 caractères."
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr "La taille de fichier maximale autorisée est de 200 Kio."
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "Ceci ne ressemble pas à une clef SSH publique, êtesâ€vous sûr(e) de vouloir l’ajouter ?"
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr "Cette adresse de courriel sera affichée sur votre profil public."
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr "Cette adresse de courriel sera utilisée pour les opérations Web, telles que les modifications et les fusions. %{learn_more}"
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
-msgstr ""
+msgstr "Cet émoji et ce message apparaîtront sur votre profil et partout dans l’interface."
+
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr "Cette fonctionnalité est expérimentale et les traductions ne sont pas encore complètes."
+
+msgid "Profiles|This information will appear on your profile."
+msgstr "Cette information apparaîtra sur votre profil."
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Saisissez votre %{confirmationValue} pour confirmer :"
@@ -5589,17 +6231,41 @@ msgstr "Saisissez votre %{confirmationValue} pour confirmer :"
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr "Commence généralement par « ssh-rsa […] »"
+msgid "Profiles|Update profile settings"
+msgstr "Mettre à jour les paramètres du profil"
+
msgid "Profiles|Update username"
msgstr "Mettre à jour le nom d’utilisateur"
+msgid "Profiles|Upload new avatar"
+msgstr "Téléverser un nouvel avatar"
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr "Utiliser une adresse de courriel privée — %{email}"
+
msgid "Profiles|Username change failed - %{message}"
msgstr "Le changement de nom d’utilisateur a échoué : %{message}"
msgid "Profiles|Username successfully changed"
msgstr "Changement de nom d’utilisateur effectué"
+msgid "Profiles|Website"
+msgstr "Site Web"
+
msgid "Profiles|What's your status?"
-msgstr ""
+msgstr "Quel est votre statut ?"
+
+msgid "Profiles|You can change your avatar here"
+msgstr "Vous pouvez changer votre avatar ici"
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr "Vous pouvez changer votre avatar ici ou supprimer l’avatar actuel et revenir à %{gravatar_link}"
+
+msgid "Profiles|You can upload your avatar here"
+msgstr "Vous pouvez téléverser votre avatar ici"
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr "Vous pouvez téléverser votre avatar ici ou le changer en %{gravatar_link}"
msgid "Profiles|You don't have access to delete this user."
msgstr "Vous n’avez pas les autorisations suffisantes pour supprimer cet utilisateur ou cette utilisatrice."
@@ -5610,8 +6276,17 @@ msgstr "Vous devez transférer la propriété ou supprimer ces groupes avant de
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "Votre compte est actuellement propriétaire des groupes suivants :"
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr "Votre adresse de courriel a été automatiquement définie en fonction de votre compte %{provider_label}."
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr "Votre localisation a été automatiquement définie en fonction de votre compte %{provider_label}."
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr "Votre nom a été automatiquement défini en fonction de votre compte %{provider_label}, afin que les personnes que vous connaissez puissent vous identifier."
+
msgid "Profiles|Your status"
-msgstr ""
+msgstr "Votre statut"
msgid "Profiles|e.g. My MacBook key"
msgstr "p. ex., Ma clef MacBook"
@@ -5644,7 +6319,10 @@ msgid "Project '%{project_name}' was successfully updated."
msgstr "Mise à jour du projet « %{project_name} » effectuée."
msgid "Project Badges"
-msgstr "Badges de projet"
+msgstr "Badges numériques du projet"
+
+msgid "Project URL"
+msgstr "URL du projet"
msgid "Project access must be granted explicitly to each user."
msgstr "L’accès au projet doit être explicitement accordé à chaque utilisateur."
@@ -5673,6 +6351,9 @@ msgstr "L’exportation du projet a débuté. Un lien de téléchargement sera e
msgid "Project name"
msgstr "Nom du projet"
+msgid "Project slug"
+msgstr "Identifiant « slug » du projet"
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "S’abonner"
@@ -5700,17 +6381,38 @@ msgstr "Jamais"
msgid "ProjectLifecycle|Stage"
msgstr "Étape"
+msgid "ProjectOverview|Fork"
+msgstr "Créer une divergence"
+
+msgid "ProjectOverview|Forks"
+msgstr "Divergences"
+
+msgid "ProjectOverview|Go to your fork"
+msgstr "Aller à votre divergence"
+
+msgid "ProjectOverview|Star"
+msgstr "Mettre une étoile"
+
+msgid "ProjectOverview|Unstar"
+msgstr "Supprimer l’étoile"
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr "Vous avez atteint la limite de votre projet"
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr "Vous devez vous authentifier afin de pouvoir ajouter une étoile à un projet"
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "Identifiant de projet : %{project_id}"
msgid "ProjectSettings|Badges"
-msgstr ""
+msgstr "Badges numériques"
msgid "ProjectSettings|Contact an admin to change this setting."
msgstr "Contactez un administrateur pour modifier ce paramètre."
msgid "ProjectSettings|Customize your project badges."
-msgstr ""
+msgstr "Personnalisez les badges numériques de votre projet."
msgid "ProjectSettings|Failed to protect the tag"
msgstr "Impossible de protéger l’étiquette"
@@ -5719,7 +6421,7 @@ msgid "ProjectSettings|Failed to update tag!"
msgstr "Impossible de mettre à jour l’étiquette !"
msgid "ProjectSettings|Learn more about badges."
-msgstr ""
+msgstr "En savoir plus sur les badges numériques."
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Seuls les commits signés peuvent être poussés sur ce dépôt Git."
@@ -5742,6 +6444,9 @@ msgstr "Projets"
msgid "Projects shared with %{group_name}"
msgstr "Projets partagés avec %{group_name}"
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr "Les projets appartenant à un groupe sont préfixés avec l’espace de noms du groupe. Les projets existants peuvent être déplacés dans un groupe."
+
msgid "ProjectsDropdown|Frequently visited"
msgstr "Les plus consultés"
@@ -5761,7 +6466,7 @@ msgid "ProjectsDropdown|Sorry, no projects matched your search"
msgstr "Désolé, aucun projet ne correspond à votre recherche"
msgid "ProjectsDropdown|This feature requires browser localStorage support"
-msgstr ""
+msgstr "Cette fonctionnalité nécessite un navigateur prenant en charge localStorage"
msgid "PrometheusAlerts|Add alert"
msgstr "Ajouter une alerte"
@@ -5811,9 +6516,6 @@ msgstr "Configuration automatique"
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr "Déployer et configurer automatiquement Prometheus sur vos grappes de serveurs pour surveiller les environnements de vos projets"
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr "Par défaut, Prometheus écoute sur « http://localhost:9090 ». Il n’est pas recommandé de changer l’adresse et le port par défaut car cela pourrait affecter ou entrer en conflit avec d’autres services fonctionnant sur le serveur GitLab."
-
msgid "PrometheusService|Common metrics"
msgstr "Métriques communes"
@@ -5899,49 +6601,49 @@ msgid "Protected"
msgstr "Protégé"
msgid "Protected Environments"
-msgstr ""
+msgstr "Environnements protégés"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
-msgstr ""
+msgstr "%{environment_name} sera accessible en écriture aux développeurs. Êtesâ€vous sûr de vouloir cela ?"
msgid "ProtectedEnvironment|Allowed to deploy"
-msgstr ""
+msgstr "Autorisé à déployer"
msgid "ProtectedEnvironment|Choose who is allowed to deploy"
-msgstr ""
+msgstr "ProtectedEnvironment|Choisissez qui est autorisé à déployer"
msgid "ProtectedEnvironment|Environment"
-msgstr ""
+msgstr "Environnement"
msgid "ProtectedEnvironment|Protect"
-msgstr ""
+msgstr "Protéger"
msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
+msgstr "Protéger les environnements afin de restreindre les déploiements aux personnes autorisées."
msgid "ProtectedEnvironment|Protect an environment"
-msgstr ""
+msgstr "Protéger un environnement"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
-msgstr ""
+msgstr "Environnements protégés (%{protected_environments_count})"
msgid "ProtectedEnvironment|Select an environment"
-msgstr ""
+msgstr "Sélectionner un environnement"
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
-msgstr ""
+msgstr "Il n’y a actuellement aucun environnement protégé, protégezâ€en un avec le formulaire ciâ€dessus."
msgid "ProtectedEnvironment|Unprotect"
-msgstr ""
+msgstr "Déprotéger"
msgid "ProtectedEnvironment|Your environment can't be unprotected"
-msgstr ""
+msgstr "Votre environnement ne peut pas être déprotégé"
msgid "ProtectedEnvironment|Your environment has been protected."
-msgstr ""
+msgstr "Votre environnement a été protégé."
msgid "ProtectedEnvironment|Your environment has been unprotected"
-msgstr ""
+msgstr "Votre environnement a été déprotégé"
msgid "Protip:"
msgstr "Astuce :"
@@ -6006,6 +6708,12 @@ msgstr "LisezMoi"
msgid "Real-time features"
msgstr "Fonctionnalités en temps réel"
+msgid "Recent searches"
+msgstr "Recherches récentes"
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr "Rediriger vers le fournisseur SAML pour tester la configuration"
+
msgid "Reference:"
msgstr "Référence :"
@@ -6014,14 +6722,14 @@ msgstr "Actualiser"
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "L’affichage sera réactualisé dans une seconde avec le statut mis à jour..."
+msgstr[1] "L’affichage sera réactualisé dans %d secondes avec le statut mis à jour…"
msgid "Regenerate key"
-msgstr ""
+msgstr "Régénérer la clef"
msgid "Regex pattern"
-msgstr ""
+msgstr "Expression rationnelle"
msgid "Register / Sign In"
msgstr "Inscription / Connexion"
@@ -6068,20 +6776,32 @@ msgstr "Supprimer l’exécuteur"
msgid "Remove avatar"
msgstr "Supprimer l’avatar"
+msgid "Remove group"
+msgstr "Supprimer le groupe"
+
msgid "Remove priority"
msgstr "Supprimer la priorité"
msgid "Remove project"
msgstr "Supprimer le projet"
+msgid "Removed group can not be restored!"
+msgstr "Un groupe supprimé ne peut être restauré !"
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr "Supprimer le groupe entraînera la suppression de tous les projets et ressources affiliés."
+
msgid "Rename"
-msgstr ""
+msgstr "Renommer"
msgid "Rename file"
-msgstr ""
+msgstr "Renommer le fichier"
msgid "Rename folder"
-msgstr ""
+msgstr "Renommer le dossier"
+
+msgid "Reopen epic"
+msgstr "Rouvrir l’épopée"
msgid "Repair authentication"
msgstr "Réparer l’authentification"
@@ -6092,32 +6812,50 @@ msgstr "Répondez directement à ce courriel ou %{view_it_on_gitlab}."
msgid "Repo by URL"
msgstr "Dépôt par URL"
+msgid "Report abuse to GitLab"
+msgstr "Signaler un abus à GitLab"
+
+msgid "Reporting"
+msgstr "Rapports"
+
msgid "Reports|%{failedString} and %{resolvedString}"
-msgstr ""
+msgstr "%{failedString} et %{resolvedString}"
+
+msgid "Reports|Actions"
+msgstr "Actions"
msgid "Reports|Class"
-msgstr ""
+msgstr "Classe"
+
+msgid "Reports|Confidence"
+msgstr "Confiance"
msgid "Reports|Execution time"
-msgstr ""
+msgstr "Durée d’exécution"
msgid "Reports|Failure"
-msgstr ""
+msgstr "Échec"
+
+msgid "Reports|Severity"
+msgstr "Sévérité"
msgid "Reports|System output"
-msgstr ""
+msgstr "Sortie du système"
msgid "Reports|Test summary"
-msgstr ""
+msgstr "Synthèse des tests"
msgid "Reports|Test summary failed loading results"
-msgstr ""
+msgstr "Échec du chargement des résultats de la synthèse des tests"
msgid "Reports|Test summary results are being parsed"
-msgstr ""
+msgstr "Les résultats de la synthèse des tests sont en cours d’analyse"
+
+msgid "Reports|Vulnerability"
+msgstr "Vulnérabilité"
msgid "Reports|no changed test results"
-msgstr ""
+msgstr "aucun résultat de test modifié"
msgid "Repository"
msgstr "Dépôt"
@@ -6149,12 +6887,12 @@ msgstr "Demander l’accès"
msgid "Requests Profiles"
msgstr "Profils de requêtes"
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr "Exiger de tous les utilisateurs de ce groupe la configuration de l’authentification à double facteur"
+
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "Exiger que tous les utilisateurs acceptent les conditions générales d’utilisation et la politique de confidentialité quand ils accèdent à GitLab."
-msgid "Reset git storage health information"
-msgstr "Réinitialiser les informations de santé du stockage Git"
-
msgid "Reset health check access token"
msgstr "Réinitialiser le jeton d’accès au bilan de santé"
@@ -6170,9 +6908,21 @@ msgstr "Résoudre les conflits sur la branche source"
msgid "Resolve discussion"
msgstr "Résoudre la discussion"
+msgid "Response metrics (AWS ELB)"
+msgstr "Métriques de réponse (AWS ELB)"
+
msgid "Response metrics (Custom)"
msgstr "Métriques de réponse (personnalisées)"
+msgid "Response metrics (HA Proxy)"
+msgstr "Métriques de réponse (HA Proxy)"
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr "Métriques de réponse (nginx Ingress)"
+
+msgid "Response metrics (NGINX)"
+msgstr "Métriques de réponse (nginx)"
+
msgid "Resume"
msgstr "Reprendre"
@@ -6186,7 +6936,7 @@ msgid "Retry verification"
msgstr "Relancer la vérification"
msgid "Reveal Variables"
-msgstr ""
+msgstr "Révéler les variables"
msgid "Reveal value"
msgid_plural "Reveal values"
@@ -6221,11 +6971,26 @@ msgid "Run CI/CD pipelines for external repositories"
msgstr "Exécuter des pipelines CI / CD pour les dépôts externes"
msgid "Run untagged jobs"
-msgstr ""
+msgstr "Exécuter les tâches non étiquetées"
+
+msgid "Runner cannot be assigned to other projects"
+msgstr "L’exécuteur ne peut être affecté à d’autres projets"
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr "L’exécuteur exécute des tâches de tous les projets non attribués"
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr "L’exécuteur exécute des tâches de tous les projets non attribués de son groupe"
+
+msgid "Runner runs jobs from assigned projects"
+msgstr "L’exécuteur exécute des tâches de projets attribués"
msgid "Runner token"
msgstr "Jeton de l’exécuteur"
+msgid "Runner will not receive any new jobs"
+msgstr "L’exécuteur ne recevra aucune nouvelle tâche"
+
msgid "Runners"
msgstr "Exécuteurs"
@@ -6235,14 +7000,20 @@ msgstr "API des exécuteurs"
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr "Les exécuteurs peuvent être placés sur différents utilisateurs et serveurs, voire sur votre machine locale."
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr "Les exécuteurs peuvent fonctionner sur différents serveurs, avec différents comptes d’utilisateur, y compris sur votre machine locale."
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr "Exécuteurs actuellement en ligne : %{active_runners_count}"
+
msgid "Runners page"
-msgstr ""
+msgstr "Page des exécuteurs"
msgid "Runners page."
-msgstr ""
+msgstr "Page des exécuteurs."
msgid "Runners|You have used all your shared Runners pipeline minutes."
-msgstr ""
+msgstr "Vous avez utilisé tout le temps de pipeline partagé de vos exécuteurs."
msgid "Running"
msgstr "En cours d’exécution"
@@ -6259,6 +7030,9 @@ msgstr "Authentification unique SAML"
msgid "SAML Single Sign On Settings"
msgstr "Paramètres d’authentification unique SAML"
+msgid "SAST"
+msgstr "SAST"
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr "Empreinte SHA-1 du certificat de signature de jetons SAML. Obtenezâ€la auprès de votre fournisseur d’identité, parfois sous la dénomination « Thumbprint »."
@@ -6283,6 +7057,9 @@ msgstr "Enregistrer l’application"
msgid "Save changes"
msgstr "Enregistrer les modifications"
+msgid "Save changes before testing"
+msgstr "Enregistrer les modifications avant de tester"
+
msgid "Save pipeline schedule"
msgstr "Sauvegarder la planification du pipeline"
@@ -6337,65 +7114,102 @@ msgstr "Rechercher des demandes de fusion"
msgid "Search milestones"
msgstr "Rechercher des jalons"
+msgid "Search or filter results..."
+msgstr "Rechercher ou filtrer les résultats…"
+
msgid "Search or jump to…"
-msgstr ""
+msgstr "Rechercher ou aller à…"
msgid "Search project"
msgstr "Rechercher des projets"
+msgid "Search projects"
+msgstr "Rechercher des projets"
+
msgid "Search users"
msgstr "Rechercher des utilisateurs et utilisatrices"
+msgid "Search your projects"
+msgstr "Rechercher dans vos projets"
+
msgid "SearchAutocomplete|All GitLab"
-msgstr ""
+msgstr "Dans tout GitLab"
msgid "SearchAutocomplete|Issues I've created"
-msgstr ""
+msgstr "Les tickets que j’ai créés"
msgid "SearchAutocomplete|Issues assigned to me"
-msgstr ""
+msgstr "Les tickets qui me sont assignés"
msgid "SearchAutocomplete|Merge requests I've created"
-msgstr ""
+msgstr "Demandes de fusion que j’ai créées"
msgid "SearchAutocomplete|Merge requests assigned to me"
-msgstr ""
+msgstr "Demandes de fusion qui me sont assignées"
msgid "SearchAutocomplete|in all GitLab"
-msgstr ""
+msgstr "Dans tout GitLab"
msgid "SearchAutocomplete|in this group"
-msgstr ""
+msgstr "Dans ce groupe"
msgid "SearchAutocomplete|in this project"
+msgstr "Dans ce projet"
+
+msgid "Secret"
+msgstr "Secret"
+
+msgid "Security"
+msgstr "Sécurité"
+
+msgid "Security Dashboard"
+msgstr "Tableau de bord de sécurité"
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr "Erreur lors de la récupération des données du tableau de bord. Veuillez vérifier votre connexion réseau puis réessayer."
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr "Erreur lors de la récupération du nombre de vulnérabilités. Veuillez vérifier votre connexion réseau puis réessayer."
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr "Erreur lors de la récupération de la liste des vulnérabilités. Veuillez vérifier votre connexion réseau puis réessayer."
+
+msgid "Security Dashboard|Issue Created"
+msgstr "Ticket créé"
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr "Pour le moment, le tableau de bord de sécurité ne prend uniquement en charge que SAST."
+
+msgid "Security Reports|Create issue"
msgstr ""
-msgid "Seconds before reseting failure information"
-msgstr "Nombre de secondes avant réinitialisation des informations d’échec"
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
-msgid "Seconds to wait for a storage access attempt"
-msgstr "Nombre de secondes d’attente avant une tentative d’accès au stockage"
+msgid "Security Reports|More info"
+msgstr "Plus d’informations"
-msgid "Secret:"
-msgstr "Secret :"
+msgid "Security Reports|Revert dismissal"
+msgstr ""
-msgid "Security"
+msgid "Security Reports|Security dashboard documentation"
msgstr ""
-msgid "Security Dashboard"
-msgstr "Tableau de bord de sécurité"
+msgid "Security Reports|There was an error creating the issue."
+msgstr "Une erreur est survenue lors de la création du ticket."
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr "Une erreur est survenue lors du rejet de la vulnérabilité."
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|There was an error reverting the dismissal."
msgstr ""
-msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr "Le tableau de bord de sécurité affiche le dernier rapport de sécurité. Utilisezâ€le pour rechercher et corriger les vulnérabilités."
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr "Surveiller les vulnérabilités dans votre code"
@@ -6408,9 +7222,15 @@ msgstr "Sélectionner"
msgid "Select Archive Format"
msgstr "Sélectionnez le format de l’archive"
+msgid "Select a group to invite"
+msgstr "Sélectionnez un groupe à inviter"
+
msgid "Select a namespace to fork the project"
msgstr "Sélectionnez un espace de noms afin de créer une divergence du projet"
+msgid "Select a template repository"
+msgstr "Sélectionner un modèle de dépôt"
+
msgid "Select a timezone"
msgstr "Sélectionnez un fuseau horaire"
@@ -6441,8 +7261,11 @@ msgstr "Sélectionner une branche source"
msgid "Select target branch"
msgstr "Sélectionner une branche cible"
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr "Sélectionnez la branche que vous souhaitez définir comme branche par défaut pour ce projet. Toutes les demandes de fusion et les commits seront automatiquement effectués sur cette branche, à moins que vous n’en spécifiez une autre."
+
msgid "Select the custom project template source group."
-msgstr ""
+msgstr "Sélectionnez le groupe source de modèles de projet personnalisés."
msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
msgstr "La sélection d’un utilisateur de GitLab va ajouter un lien vers cet utilisateur dans les descriptions des tickets et des commentaires (p. ex., « Par <a href=\"#\">@johnsmith</a> »). Les tickets et commentaires seront également associés ou assignés à cet utilisateur."
@@ -6453,6 +7276,9 @@ msgstr "Synchronisation sélective"
msgid "Send email"
msgstr "Envoyer un courriel"
+msgid "Send usage data"
+msgstr "Envoyer des données d’utilisation"
+
msgid "Sep"
msgstr "sept."
@@ -6477,11 +7303,14 @@ msgstr "Expiration de la session, restrictions des projets et taille des pièces
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Définissez un mot de passe pour votre compte afin de pouvoir récupérer ou pousser vos modification via %{protocol}."
+msgid "Set a template repository for projects in this group"
+msgstr "Définir un modèle de dépôt pour les projets de ce groupe"
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr "Définissez les valeurs par défaut et restreignez les niveaux de visibilité. Configurez les sources d’importation et le protocole d’accès pour Git."
msgid "Set instance-wide template repository"
-msgstr ""
+msgstr "Définir un dépôt de modèles au niveau de l’instance"
msgid "Set max session time for web terminal."
msgstr "Définissez le temps maximal de la session pour le terminal Web."
@@ -6495,26 +7324,47 @@ msgstr "Définissez les exigences pour la connexion d’un utilisateur. Activez
msgid "Set up CI/CD"
msgstr "Configuration CI/CD"
-msgid "Set up Koding"
-msgstr "Configurer Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr "Configurer manuellement un exécuteur %{type}"
+
+msgid "Set up a specific Runner automatically"
+msgstr "Configurer automatiquement un exécuteur spécifique"
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr "Configure les assertions, attributs et revendications (courriel, prénom et nom), ainsi que le NameID, conformément à %{docsLinkStart}la documentation %{icon}%{docsLinkEnd}"
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
-msgstr ""
+msgstr "Configurez votre projet afin de pouvoir pousser et/ou récupérer automatiquement les modifications vers ou depuis un autre dépôt. Les branches, les étiquetets et les commits seront automatiquement synchronisés."
msgid "SetPasswordToCloneLink|set a password"
msgstr "définir un mot de passe"
-msgid "Settings"
-msgstr "Paramètres"
+msgid "SetStatusModal|Add status emoji"
+msgstr "Ajouter un émoji d’état"
-msgid "Set up a %{type} Runner manually"
-msgstr ""
+msgid "SetStatusModal|Clear status"
+msgstr "Effacer l’état"
-msgid "Set up a specific Runner automatically"
-msgstr "Configurer automatiquement un exécuteur spécifique"
+msgid "SetStatusModal|Edit status"
+msgstr "Modifier l’état"
+
+msgid "SetStatusModal|Remove status"
+msgstr "Supprimer l’état"
+
+msgid "SetStatusModal|Set a status"
+msgstr "Définir un état"
+
+msgid "SetStatusModal|Set status"
+msgstr "Définir l’état"
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr "Désolé, l’état n’a pas pu être défini. Veuillez réessayer ultérieurement."
+
+msgid "SetStatusModal|What's your status?"
+msgstr "Quel est votre état ?"
+
+msgid "Settings"
+msgstr "Paramètres"
msgid "Share"
msgstr "Partager"
@@ -6525,6 +7375,9 @@ msgstr "Partager le <strong>%{sso_label}</strong> avec les membres afin qu’ils
msgid "Shared Runners"
msgstr "Exécuteurs partagés"
+msgid "Shared projects"
+msgstr "Projets partagés"
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr "En réinitialisant le compteur de minutes du pipeline pour cet espace de noms, les minutes actuellement utilisées seront mises à zéro."
@@ -6600,7 +7453,7 @@ msgid "Sign-up restrictions"
msgstr "Restrictions d’inscription"
msgid "Size"
-msgstr ""
+msgstr "Taille"
msgid "Size and domain settings for static websites"
msgstr "Paramètres de taille et de domaine pour les sites Web statiques"
@@ -6608,12 +7461,18 @@ msgstr "Paramètres de taille et de domaine pour les sites Web statiques"
msgid "Slack application"
msgstr "Application Slack"
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
-msgstr ""
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr "L’intégration de Slack permet d’interagir avec GitLab via des commandes slash dans une fenêtre de messagerie instantanée."
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr "Plus lent, mais permet de s’assurer que l’espace de travail du projet est vierge, comme il clone le dépôt à partir de zéro pour chaque tâche"
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr "Extraits de code"
@@ -6627,10 +7486,10 @@ msgid "Something went wrong on our end. Please try again!"
msgstr "Quelque chose s’est mal passé de notre côté. Veuillez réessayer."
msgid "Something went wrong trying to change the confidentiality of this issue"
-msgstr ""
+msgstr "Une erreur est survenue lors de la tentative de modification de la confidentialité de ce ticket"
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
-msgstr ""
+msgstr "Une erreur est survenue lors de la tentative de modification de l’état de verrouillage de ce·t·te %{issuableDisplayName}"
msgid "Something went wrong when toggling the button"
msgstr "Une erreur s’est produite lors du basculement du bouton"
@@ -6639,11 +7498,17 @@ msgid "Something went wrong while closing the %{issuable}. Please try again late
msgstr "Une erreur s’est produite lors de la fermeture du / de la %{issuable}. Veuillez réessayer plus tard"
msgid "Something went wrong while fetching %{listType} list"
-msgstr ""
+msgstr "Une erreur est survenue lors de la récupération de la liste de %{listType}"
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr "Une erreur est survenue lors de la récupération des commentaires. Veuillez réessayer."
msgid "Something went wrong while fetching group member contributions"
msgstr "Une erreur s’est produite lors de la récupération des contributions des membres du groupe"
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr "Une erreur est survenue lors de la récupération des environnements pour cette demande de fusion. Veuillez réessayer."
+
msgid "Something went wrong while fetching the projects."
msgstr "Une erreur s’est produite lors de la récupération des projets."
@@ -6656,12 +7521,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr "Une erreur s’est produite lors de la « résolution » de la discussion. Veuillez réessayer."
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr "Une erreur est survenue, impossible d’ajouter %{project} au tableau de bord"
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr "Une erreur est survenue, impossible d’obtenir des projets d’opérations"
+
+msgid "Something went wrong, unable to remove project"
+msgstr "Une erreur est survenue, impossible de supprimer le projet"
+
msgid "Something went wrong. Please try again."
msgstr "Quelque chose s’est mal passé. Veuillez réessayer."
msgid "Sorry, no epics matched your search"
msgstr "Désolé, aucune épopée ne correspond à votre recherche"
+msgid "Sorry, no projects matched your search"
+msgstr "Désolé, aucun projet ne correspond à votre recherche"
+
msgid "Sort by"
msgstr "Trier par"
@@ -6692,6 +7569,9 @@ msgstr "Taille de groupe"
msgid "SortOptions|Largest repository"
msgstr "Taille de dépôt"
+msgid "SortOptions|Last Contact"
+msgstr "Contact le plus récent"
+
msgid "SortOptions|Last created"
msgstr "Créé récemment"
@@ -6722,6 +7602,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr "Popularité décroissante"
+msgid "SortOptions|Most stars"
+msgstr "Avec le plus d’étoiles"
+
msgid "SortOptions|Name"
msgstr "Nom"
@@ -6752,6 +7635,9 @@ msgstr "Priorité"
msgid "SortOptions|Recent sign in"
msgstr "Date d’inscription décroissante"
+msgid "SortOptions|Start date"
+msgstr "Date de début"
+
msgid "SortOptions|Start later"
msgstr "Commence plus tard"
@@ -6783,7 +7669,7 @@ msgid "Specific Runners"
msgstr "Exécuteurs spécifiques"
msgid "Specify an e-mail address regex pattern to identify default internal users."
-msgstr ""
+msgstr "Spécifiez un motif d’expression rationnelle permettant l’identification des adresses de courriel des utilisateurs internes."
msgid "Specify the following URL during the Runner setup:"
msgstr "Spécifiez l’URL suivante lors de la configuration de l’exécuteur :"
@@ -6827,9 +7713,21 @@ msgstr "Projets favoris"
msgid "Start a %{new_merge_request} with these changes"
msgstr "Créer une %{new_merge_request} avec ces changements"
+msgid "Start a review"
+msgstr "Démarrer une revue de code"
+
+msgid "Start and due date"
+msgstr "Dates de début et d’échéance"
+
+msgid "Start date"
+msgstr "Date de début"
+
msgid "Start the Runner!"
msgstr "Démarrer l’exécuteur !"
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr "Démarré"
@@ -6842,6 +7740,9 @@ msgstr "Énoncez votre message à activer"
msgid "Status"
msgstr "État "
+msgid "Stop environment"
+msgstr "Arrêter l’environnement"
+
msgid "Stop impersonation"
msgstr "Arrêter l’emprunt d’identité"
@@ -6851,6 +7752,9 @@ msgstr "Arrêter cet environnement"
msgid "Stopped"
msgstr "Arrêté"
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr "L’arrêt de cet environnement est actuellement impossible car un déploiement est en cours"
+
msgid "Storage"
msgstr "Stockage"
@@ -6860,9 +7764,15 @@ msgstr "Stockage :"
msgid "Subgroups"
msgstr "Sousâ€groupes"
+msgid "Subgroups and projects"
+msgstr "Sousâ€groupes et projets"
+
msgid "Submit as spam"
msgstr "Soumettre comme indésirable"
+msgid "Submit review"
+msgstr "Envoyer la revue de code"
+
msgid "Submit search"
msgstr "Soumettre la recherche"
@@ -6875,6 +7785,12 @@ msgstr "S’abonner au niveau du groupe"
msgid "Subscribe at project level"
msgstr "S’abonner au niveau du projet"
+msgid "Subscribed"
+msgstr "Abonné"
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr "Résumé des tickets, demandes de fusion, poussages de code et commentaires (fuseau horaire : %{utcFormatted})"
+
msgid "Switch branch/tag"
msgstr "Changer de branche ou d’étiquette"
@@ -6893,6 +7809,9 @@ msgstr "Enâ€tête et pied de page du système :"
msgid "System metrics (Custom)"
msgstr "Métriques du système (personnalisées)"
+msgid "System metrics (Kubernetes)"
+msgstr "Métriques du système (Kubernetes)"
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] "Étiquette (%{tag_count})"
@@ -6902,7 +7821,7 @@ msgid "Tags"
msgstr "Étiquettes"
msgid "Tags feed"
-msgstr ""
+msgstr "Flux d’étiquettes"
msgid "Tags:"
msgstr "Étiquettes :"
@@ -6986,10 +7905,10 @@ msgid "Team"
msgstr "Équipe"
msgid "Template"
-msgstr ""
+msgstr "Modèle"
msgid "Templates"
-msgstr ""
+msgstr "Modèles "
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "Conditions générales d’utilisation et politique de confidentialité"
@@ -6997,6 +7916,9 @@ msgstr "Conditions générales d’utilisation et politique de confidentialité"
msgid "Terms of Service and Privacy Policy"
msgstr "Conditions générales d’utilisation et politique de confidentialité"
+msgid "Test SAML SSO"
+msgstr "Tester l’authentification SAML"
+
msgid "Test coverage parsing"
msgstr "Analyse de la couverture des tests"
@@ -7007,7 +7929,7 @@ msgid "The Advanced Global Search in GitLab is a powerful search service that sa
msgstr "La recherche globale avancée de Gitlab est un outil puissant qui vous fait gagner du temps. Au lieu de perdre du temps à recréer du code existant, vous pouvez maintenant faire des recherches dans le code d’autres équipes afin de vous aider sur votre projet."
msgid "The Git LFS objects will <strong>not</strong> be synced."
-msgstr ""
+msgstr "Les objets Git LFS <strong>ne sont pas</strong> synchronisés."
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
msgstr "Le système de suivi est un endroit où l’on peut ouvrir un ticket pour signaler des choses à améliorer ou des dysfonctionnements à résoudre dans un projet"
@@ -7019,7 +7941,7 @@ msgid "The X509 Certificate to use when mutual TLS is required to communicate wi
msgstr "Le certificat X.509 à utiliser lorsque l’authentification TLS mutuelle est requise pour communiquer avec le service d’autorisation externe. Si ce champ est vide, le certificat du serveur est tout de même validé lors de l’accès via HTTPS."
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
-msgstr ""
+msgstr "Le surligneur de caractères vous aide à garder la longueur de l’objet à %{titleLength} caractères maximum et à faire des renvois à la ligne pour limiter les lignes du corps du message à %{bodyLength} caractères, afin de les rendre lisibles sous Git."
msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
msgstr "Le présentoir de code affiche le temps entre le premier commit et la création de la demande de fusion. Les données seront automatiquement ajoutées ici une fois que vous aurez créé votre première demande de fusion."
@@ -7031,7 +7953,7 @@ msgid "The connection will time out after %{timeout}. For repositories that take
msgstr "La connexion expirera après %{timeout}. Pour les dépôts qui nécessitent plus de temps, utilisez une combinaison de clone et push."
msgid "The deployment of this job to %{environmentLink} did not succeed."
-msgstr ""
+msgstr "Le déploiement de cette tâche sur %{environmentLink} a échoué."
msgid "The fork relationship has been removed."
msgstr "La relation de divergence a été supprimée."
@@ -7045,12 +7967,6 @@ msgstr "Le présentoir des tickets affiche le temps nécessaire entre la créati
msgid "The maximum file size allowed is 200KB."
msgstr "La taille maximale autorisée pour un fichier est de 200 Kio."
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr "Le nombre de tentatives que GitLab va effectuer pour accéder à un stockage."
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr "Nombre d’échecs avant que GitLab n’empêche tout accès au stockage. Ce nombre d’échecs peut être réinitialisé dans l’interface d’administration : %{link_to_health_page} ou en suivant la %{api_documentation_link}."
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "La phrase de passe permettant de déchiffrer la clef privée. Ceci est facultatif et la valeur est chiffrée au repos."
@@ -7061,7 +7977,7 @@ msgid "The phase of the development lifecycle."
msgstr "La phase du cycle de développement."
msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
-msgstr ""
+msgstr "La planification des pipelines permet l’exécution de pipelines programmés, de manière récurrente, pour des branches ou des étiquettes spécifiques. Ces pipelines programmés hériteront d’un accès limité aux projets en fonction de l’utilisateur qui leur est associé."
msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
msgstr "L’étape de planification montre le temps entre l’étape précédente et l’envoi de votre premier commit. Ce temps sera automatiquement ajouté quand vous pousserez votre premier commit."
@@ -7091,7 +8007,7 @@ msgid "The repository must be accessible over <code>http://</code>, <code>https:
msgstr "Le dépôt doit être accessible via <code>http://</code>, <code>https://</code> ou <code>git://</code>."
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
-msgstr ""
+msgstr "Le dépôt doit être accessible via <code>http://</code>, <code>https://</code>, <code>ssh://</code> ou <code>git://</code>."
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "L’étape d’évaluation montre le temps entre la création de la demande de fusion et la fusion effective de celleâ€ci. Ces données seront automatiquement ajoutées après que vous aurez fusionné votre première demande de fusion."
@@ -7099,32 +8015,23 @@ msgstr "L’étape d’évaluation montre le temps entre la création de la dema
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr "La feuille de route affiche la progression de vos épopées dans le temps"
-msgid "The secure token used by the Runner to checkout the project"
-msgstr "Le jeton sécurisé utilisé par l’exécuteur pour vérifier (checkout) le projet"
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "L’étape de pré-production indique le temps entre l’acceptation d’une demande fusion et le déploiement du code dans l’environnent de production. Les données seront automatiquement ajoutées lorsque vous aurez fait votre première mise en production."
msgid "The tabs below will be removed in a future version"
-msgstr ""
+msgstr "Les onglets ciâ€dessous seront supprimés dans une prochaine version"
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr "L’étape de test montre le temps que que met l’intégration continue de GitLab pour exécuter chaque pipeline pour une demande de fusion donnée. Les données seront automatiquement ajoutées après que votre premier pipeline s’achèvera."
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr "Délai en secondes pendant lequel GitLab gardera les informations d’échec. Si aucun échec ne survient pendant ce délai, les informations de ce montage seront réinitialisées."
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr "Temps en secondes pendant lequel GitLab essaiera d’accéder au stockage. Après ce délai, une erreur d’expiration du délai d’attente sera déclenchée."
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr "Intervalle entre deux vérifications du stockage, en secondes. Si une précédente vérification n’est pas encore terminée lorsqu’une nouvelle doit commencer, cette dernière est sautée."
-
msgid "The time taken by each data entry gathered by that stage."
msgstr "Le temps pris par chaque entrée récoltée durant cette étape."
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
-msgstr ""
+msgstr "L’action de mise à jour expirera au bout de %{number_of_minutes} minutes. Pour les gros dépôts, utilisez une combinaison de clone et push."
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr "La collecte des données d’utilisation est désactivée et ne peut pas être configurée par le biais de ce formulaire."
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr "La carte des utilisateurs (<code>user map</code>) est un document JSON qui met en correspondance les utilisateurs de Google Code qui ont participé à vos projets en précisant la manière dont leurs adresses de courriel et leurs noms d’utilisateur sont importés dans GitLab. Vous pouvez y apporter des modifications en changeant la valeur à droite du « <code>:</code> ». Assurezâ€vous de conserver les guillemets droits doubles (<code>\"</code>), les autres signes de ponctuation, ainsi que l’adresse de courriel ou le nom d’utilisateur à gauche du deuxâ€points."
@@ -7135,6 +8042,9 @@ msgstr "La carte des utilisateurs met en correspondance les utilisateurs de FogB
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "La valeur située au point médian d’une série de valeur observée. Par exemple., entre 3, 5 et 9, le médian est 5. Entre 3, 5, 7 et 8, le médian est (5+7)/2 = 6."
+msgid "There are no archived projects yet"
+msgstr "Il n’y a pas encore de projets archivés"
+
msgid "There are no issues to show"
msgstr "Il n’y a aucun ticket à afficher"
@@ -7144,14 +8054,20 @@ msgstr "Il n’y a pas encore d’étiquette"
msgid "There are no merge requests to show"
msgstr "Il n’y a aucune demande de fusion à afficher"
-msgid "There are problems accessing Git storage: "
-msgstr "Il y a des difficultés à accéder aux données Git : "
+msgid "There are no projects shared with this group yet"
+msgstr "Il n’y a pas encore de projets partagés avec ce groupe"
+
+msgid "There are no staged changes"
+msgstr "Il n’y a aucune modification indexée"
+
+msgid "There are no unstaged changes"
+msgstr "Il n’y a aucune modification non indexée"
msgid "There was an error adding a todo."
-msgstr ""
+msgstr "Une erreur est survenue lors de l’ajout d’une tâche à accomplir (todo)."
msgid "There was an error deleting the todo."
-msgstr ""
+msgstr "Une erreur est survenue lors de la suppression de la tâche à accomplir (todo)."
msgid "There was an error loading users activity calendar."
msgstr "Une erreur s’est produite lors du chargement du calendrier d’activité des utilisateurs."
@@ -7190,13 +8106,16 @@ msgid "This board's scope is reduced"
msgstr "La portée de ce tableau est réduite"
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
-msgstr ""
+msgstr "Cette branche a changé depuis que vous y avez apporté des modifications. Souhaitezâ€vous créer une nouvelle branche ?"
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
-msgstr ""
+msgid "This container registry has been scheduled for deletion."
+msgstr "Ce registre de conteneur a été programmé pour suppression."
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
-msgstr ""
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr "Cette date est postérieure à la date d’échéance, cette épopée n’apparaîtra donc pas dans la feuille de route."
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr "Cette date est antérieure à la date de début, cette épopée n’apparaîtra donc pas dans la feuille de route."
msgid "This diff is collapsed."
msgstr "Ce diff est replié."
@@ -7216,6 +8135,9 @@ msgstr "Ce groupe ne fournit pas encore d’exécuteurs de groupe."
msgid "This is a confidential issue."
msgstr "Ce ticket est confidentiel."
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr "Il s’agit d’une tâche différée devant être exécutée dans %{remainingTime}"
+
msgid "This is the author's first Merge Request to this project."
msgstr "C’est la première demande de fusion de cet auteur pour ce projet."
@@ -7250,32 +8172,38 @@ msgid "This job has not started yet"
msgstr "Cette tâche n’a pas encore commencée"
msgid "This job is an out-of-date deployment to %{environmentLink}."
-msgstr ""
+msgstr "Cette tâche est un déploiement obsolète sur %{environmentLink}."
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
-msgstr ""
+msgstr "Cette tâche est un déploiement obsolète sur %{environmentLink}. Afficher le déploiement le plus récent %{deploymentLink}."
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
-msgstr ""
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr "Cette tâche est archivée. Seul le pipeline complet peut faire l’objet d’une nouvelle exécution."
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
+msgstr "Cette tâche va effectuer un déploiement sur %{environmentLink} et écrasera le %{deploymentLink}."
msgid "This job is creating a deployment to %{environmentLink}."
-msgstr ""
+msgstr "Cette tâche va effectuer un déploiement sur %{environmentLink}."
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr "Cette tâche est en attente d’être choisie par un exécuteur"
msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
-msgstr ""
+msgstr "Cette tâche est bloquée parce que vous n’avez aucun exécuteur actif en ligne auquel l’une des étiquettes suivantes est assignée :"
msgid "This job is stuck, because you don't have any active runners that can run this job."
-msgstr ""
+msgstr "Cette tâche est bloquée parce que vous n’avez aucun exécuteur actif pouvant la prendre en charge."
msgid "This job is the most recent deployment to %{link}."
-msgstr ""
+msgstr "Cette tâche est le déploiement le plus récent sur %{link}."
msgid "This job requires a manual action"
msgstr "Cette tâche nécessite une action manuelle"
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr "Cette tâche s’exécutera automatiquement à l’heure programmée. Les tâches programmées sont souvent utilisées pour les déploiements continus dans des environnements de production. Lorsqu’elles sont déprogrammées, elles deviennent des tâches qui peuvent être démarrées manuellement."
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Cela signifie que vous ne pouvez pas pousser du code tant que vous n’avez pas créé un dépôt vide ou que vous n’avez pas importé un dépôt existant."
@@ -7283,7 +8211,7 @@ msgid "This merge request is locked."
msgstr "Cette demande de fusion est verrouillée."
msgid "This option is disabled as you don't have write permissions for the current branch"
-msgstr ""
+msgstr "Cette option est désactivée car vous n’avez pas les droits d’écriture sur la branche actuelle"
msgid "This option is disabled while you still have unstaged changes"
msgstr "Cette option est désactivée tant que vous avez des changements non indexés"
@@ -7300,29 +8228,38 @@ msgstr "Ce projet"
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr "Ce projet n’appartient pas à un groupe et ne peut donc pas faire appel à un exécuteur de groupe."
+msgid "This project does not have a wiki homepage yet"
+msgstr "Ce projet n’a pas encore de page d’accueil de wiki"
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
+msgstr "Ce projet n’a pas de facturation activée. Afin de créer une grappe de serveurs, veuillez <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">activer la facturation<i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> et réessayer."
msgid "This repository"
msgstr "Ce dépôt"
msgid "This runner will only run on pipelines triggered on protected branches"
-msgstr ""
+msgstr "Cet exécuteur ne fonctionnera que sur les pipelines déclenchés sur des branches protégées"
+
+msgid "This setting can be overridden in each project."
+msgstr "Ce paramètre peut être outrepassé pour chacun des projets."
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr "Ce paramètre modifie le nom d’hôte qui est utilisé pour générer des courriels de commit privés. %{learn_more}"
msgid "This source diff could not be displayed because it is too large."
msgstr "Ce diff n’a pas pu être affiché car il est trop grand."
msgid "This timeout will take precedence when lower than Project-defined timeout"
-msgstr ""
+msgstr "Ce délai d’attente aura préséance lorsqu’il est inférieur au délai d’attente défini pour le projet"
msgid "This user has no identities"
msgstr "Cet utilisateur ou cette utilisatrice n’a aucune identité"
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
-msgstr ""
+msgstr "Cet utilisateur sera l’auteur de tous les événements du flux d’activité résultant d’une mise à jour, comme la création de nouvelles branches ou les nouveaux commits poussés vers des branches existantes."
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
-msgstr ""
+msgstr "Cet utilisateur sera l’auteur de tous les événements du flux d’activité résultant d’une mise à jour, comme la création de nouvelles branches ou les nouveaux commits poussés vers des branches existantes. Lors de la création ou lors de la réaffectation, vous ne pouvez assigner que vousâ€même comme utilisateur du miroir."
msgid "This will delete the custom metric, Are you sure?"
msgstr "Ceci va supprimer la métrique personnalisée. Êtesâ€vous sûr(e) ?"
@@ -7336,9 +8273,15 @@ msgstr "Temps avant qu’un ticket ne soit planifié"
msgid "Time before an issue starts implementation"
msgstr "Temps avant que la résolution du ticket ne débute"
+msgid "Time before enforced"
+msgstr "Durée avant mise en application"
+
msgid "Time between merge request creation and merge/close"
msgstr "Temps entre la création d’une demande de fusion et sa fusion/clôture"
+msgid "Time estimate"
+msgstr "Estimation du temps"
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr "Délai d’attente, en secondes, d’une réponse du service externe. Lorsque le service ne répond pas à temps, l’accès sera refusé."
@@ -7527,14 +8470,26 @@ msgid "To connect an SVN repository, check out %{svn_link}."
msgstr "Pour connecter un dépôt SVN, veuillez consulter %{svn_link}."
msgid "To define internal users, first enable new users set to external"
-msgstr ""
+msgstr "Afin de définir les utilisateurs internes, veuillez d’abord activer les nouveaux utilisateurs définis comme externes"
+
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr "Afin d’activer et d’afficher les cohortes d’utilisateurs, consultez les %{application_settings_link_start}paramètres de l’application%{application_settings_link_end}."
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr "Pour commencer, entrez votre URL FogBugz et vos informations de connexion ciâ€dessous. Dans les étapes suivantes, vous pourrez mettre en correspondance les comptes des utilisateurs et sélectionner les projets à importer."
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr "Pour commencer, créez un lien vers cette page sur votre serveur Jaeger, ou bien découvrez comment %{link_start_tag}installer Jaeger%{link_end_tag}"
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr "Pour commencer, entrez l’URL de votre hôte Gitea et un %{link_to_personal_token}."
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr "Afin d’aider à améliorer GitLab et son expérience utilisateur, GitLab va recueillir périodiquement des informations sur son utilisation."
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr "Afin d’aider à améliorer GitLab, nous aimerions recueillir périodiquement des informations sur son utilisation. Vous pourrez modifier ceci à tout moment dans les %{settings_link_start}paramètres%{link_end}. %{info_link_start}Plus d’informations…%{link_end}"
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr "Pour importer les dépôts GitHub, vous pouvez utiliser un %{personal_access_token_link}. Lorsque vous créez votre jeton d’accès, vous devrez sélectionner le champ <code>repo</code>, afin que nous puissions afficher une liste de vos dépôts publics et privés qui sont disponibles pour être importés."
@@ -7550,6 +8505,9 @@ msgstr "Pour déplacer ou copier un projet GitLab entier depuis une autre instal
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr "Pour n’utiliser uniquement que les fonctionnalités d’intégration et livraison continues (CI / CD) pour un dépôt externe, choisissez <strong>Intégration et livraison continues (CI / CD) pour dépôt externe</strong>."
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr "Afin d’ouvrir Jaeger pour visualiser facilement le traçage de GitLab, créez un lien vers la page %{start_tag}Traçage%{end_tag} sur votre serveur"
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr "Pour configurer l’authentification SAML pour votre groupe via un fournisseur d’identité tel qu’Azure, Okta, Onelogin, Ping Identity ou votre fournisseur SAML 2.0 personnalisé :"
@@ -7562,12 +8520,15 @@ msgstr "À cette instance de GitLab"
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr "Pour valider vos configurations GitLab CI, allez dans « CI / CD » → « Pipelines » dans votre projet, et cliquez sur le bouton « CI Lint »."
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
-msgstr "Pour afficher la feuille de route, ajoutez une date de début ou de fin planifiée à l’une de vos épopées dans ce groupe ou ses sousâ€groupes. Seules les épopées des trois derniers mois et des trois prochains mois sont affichées."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr "Afin d’afficher la feuille de route, ajoutez une date de début ou d’échéance à l’une de vos épopées dans ce groupe ou ses sousâ€groupes. Dans la vue multiâ€mensuelle, seules les épopées du mois dernier, du mois courant et des cinq prochains mois sont affichées."
msgid "To widen your search, change or remove filters."
msgstr "Afin d’élargir votre recherche, modifiez ou supprimez des filtres."
+msgid "Today"
+msgstr "Aujourd’hui"
+
msgid "Todo"
msgstr "Tâche"
@@ -7577,9 +8538,15 @@ msgstr "À faire"
msgid "Toggle Sidebar"
msgstr "Afficher/masquer la barre latérale"
+msgid "Toggle commit description"
+msgstr "Afficher ou masquer la description du commit"
+
msgid "Toggle discussion"
msgstr "Basculer la discussion"
+msgid "Toggle file browser"
+msgstr "Afficher/masquer le navigateur de fichiers"
+
msgid "Toggle navigation"
msgstr "Activer/désactiver la navigation"
@@ -7593,7 +8560,10 @@ msgid "ToggleButton|Toggle Status: ON"
msgstr "État du commutateur : Actif"
msgid "Token"
-msgstr ""
+msgstr "Jeton"
+
+msgid "Tomorrow"
+msgstr "Demain"
msgid "Too many changes to show."
msgstr "Trop de changements à afficher."
@@ -7610,6 +8580,9 @@ msgstr "Temps total de test pour tous les commits/fusions"
msgid "Total: %{total}"
msgstr "Total : %{total}"
+msgid "Tracing"
+msgstr "Traçage"
+
msgid "Track activity with Contribution Analytics."
msgstr "Suivre l’activité avec l’analyse des contributions."
@@ -7619,17 +8592,20 @@ msgstr "Suivre les groupes de tickets qui partagent un thème, entre différents
msgid "Track time with quick actions"
msgstr "Suivre le temps estimé/passé avec les actions rapides"
+msgid "Tree view"
+msgstr "Vue arborescente"
+
msgid "Trending"
msgstr "Tendance"
msgid "Trigger"
-msgstr ""
+msgstr "Déclencheur"
msgid "Trigger pipelines for mirror updates"
-msgstr ""
+msgstr "Déclencher des pipelines pour les mises à jour de miroirs"
msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
-msgstr ""
+msgstr "Déclenche les pipelines lorsque les branches ou les étiquettes sont mises à jour sur le dépôt en amont. Selon l’activité du dépôt en amont, cela peut considérablement augmenter la charge de vos exécuteurs d’intégration continue. N’activez ceci que si vous savez qu’ils peuvent tenir la charge."
msgid "Trigger this manual action"
msgstr "Déclencher cette action manuelle"
@@ -7637,24 +8613,42 @@ msgstr "Déclencher cette action manuelle"
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr "Les déclencheurs peuvent forcer la reconstruction pour une branche ou une étiquette spécifique via l’appel à une API. Ces jetons emprunteront l’identité de l’utilisateur auquel ils sont associés, ainsi que ses accès et permissions sur les projets."
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr "Dépanner et surveiller votre application grâce au traçage"
+
msgid "Try again"
msgstr "Veuillez réessayer"
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "Activer le service d’assistance"
msgid "Twitter"
msgstr "Twitter"
+msgid "Two-factor authentication"
+msgstr "Authentification à double facteur"
+
msgid "Type"
-msgstr ""
+msgstr "Type"
msgid "Unable to load the diff. %{button_try_again}"
msgstr "Impossible de charger le diff. %{button_try_again}"
+msgid "Unable to save your changes"
+msgstr "Impossible d’enregistrer les modifications"
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "Impossible de vous connecter au groupe via SAML en raison de « %{reason} »"
+msgid "Unable to update this epic at this time."
+msgstr "Impossible de mettre à jour cette épopée pour le moment."
+
+msgid "Undo"
+msgstr "Annuler"
+
msgid "Unknown"
msgstr "Inconnu"
@@ -7662,7 +8656,7 @@ msgid "Unlock"
msgstr "Déverrouiller"
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
-msgstr ""
+msgstr "Déverrouiller %{issuableDisplayName} ? <strong>Tout le monde</strong> sera en mesure de commenter."
msgid "Unlocked"
msgstr "Déverrouillé"
@@ -7670,6 +8664,12 @@ msgstr "Déverrouillé"
msgid "Unresolve discussion"
msgstr "Marquer la discussion comme non résolue"
+msgid "Unschedule job"
+msgstr "Déprogrammer la tâche"
+
+msgid "Unstage"
+msgstr "Désindexer"
+
msgid "Unstage all changes"
msgstr "Désindexer les changements en étape"
@@ -7703,17 +8703,20 @@ msgstr "Non vérifié"
msgid "Up to date"
msgstr "À jour"
+msgid "Upcoming"
+msgstr "À venir"
+
msgid "Update"
msgstr "Mettre à jour"
msgid "Update now"
-msgstr ""
+msgstr "Mettre à jour maintenant"
-msgid "Update your group name, description, avatar, and other general settings."
-msgstr "Modifiez le nom du groupe, sa description, son logo et d’autres paramètres généraux."
+msgid "Update your group name, description, avatar, and visibility."
+msgstr "Modifiez le nom du groupe, sa description, son avatar et sa visibilité."
msgid "Updating"
-msgstr ""
+msgstr "Mise à jour en cours"
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr "Mettez à niveau votre forfait pour activer la recherche globale avancée."
@@ -7739,15 +8742,15 @@ msgstr "Téléverser un nouveau fichier"
msgid "Upload file"
msgstr "Téléverser un fichier"
-msgid "Upload new avatar"
-msgstr "Importer un nouvel avatar"
-
msgid "UploadLink|click to upload"
msgstr "Cliquez pour envoyer"
msgid "Upvotes"
msgstr "Votes positifs"
+msgid "Usage ping is not enabled"
+msgstr "L’envoi des données d’utilisation est désactivé"
+
msgid "Usage statistics"
msgstr "Statistiques d’utilisation"
@@ -7764,7 +8767,7 @@ msgid "Use one line per URI"
msgstr "Utilisez une ligne par URI"
msgid "Use template"
-msgstr ""
+msgstr "Utiliser un modèle"
msgid "Use the following registration token during setup:"
msgstr "Utiliser le jeton d’inscription suivant pendant l’installation :"
@@ -7775,6 +8778,9 @@ msgstr "Utiliser vos paramètres de notification globaux"
msgid "Used by members to sign in to your group in GitLab"
msgstr "Utilisé par les membres pour se connecter à votre groupe dans GitLab"
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr "Les cohortes d’utilisateurs ne sont affichées que lorsque la %{usage_ping_link_start}collecte des données d’utilisation%{usage_ping_link_end} est activée."
+
msgid "User Settings"
msgstr "Paramètres de l’utilisateur"
@@ -7784,12 +8790,54 @@ msgstr "Limites de l’utilisateur et du débit IP"
msgid "User map"
msgstr "Correspondance entre utilisateurs"
+msgid "UserProfile|Activity"
+msgstr "Activité"
+
+msgid "UserProfile|Already reported for abuse"
+msgstr "Déjà signalé comme abus"
+
+msgid "UserProfile|Contributed projects"
+msgstr "À contribué aux projets"
+
+msgid "UserProfile|Edit profile"
+msgstr "Modifier le profil"
+
+msgid "UserProfile|Groups"
+msgstr "Groupes"
+
+msgid "UserProfile|Most Recent Activity"
+msgstr "Activité la plus récente"
+
+msgid "UserProfile|Overview"
+msgstr "Vue d’ensemble"
+
+msgid "UserProfile|Personal projects"
+msgstr "Projets personnels"
+
+msgid "UserProfile|Recent contributions"
+msgstr "Contributions récentes"
+
+msgid "UserProfile|Report abuse"
+msgstr "Signaler un abus"
+
+msgid "UserProfile|Snippets"
+msgstr "Fragments de code"
+
+msgid "UserProfile|Subscribe"
+msgstr "S’abonner"
+
+msgid "UserProfile|This user has a private profile"
+msgstr "Cet utilisateur a un profil privé"
+
+msgid "UserProfile|View all"
+msgstr "Tout afficher"
+
+msgid "UserProfile|View user in admin area"
+msgstr "Afficher l’utilisateur dans l’espace d’administration"
+
msgid "Users"
msgstr "Utilisateurs et utilisatrices"
-msgid "User|Current status"
-msgstr ""
-
msgid "Variables"
msgstr "Variables"
@@ -7812,7 +8860,16 @@ msgid "Verified"
msgstr "Vérifié"
msgid "Version"
-msgstr ""
+msgstr "Version"
+
+msgid "View %{alerts}"
+msgstr "Afficher les %{alerts}"
+
+msgid "View app"
+msgstr "Voir l’application"
+
+msgid "View documentation"
+msgstr "Voir la documentation"
msgid "View epics list"
msgstr "Afficher la liste des épopées"
@@ -7847,9 +8904,15 @@ msgstr "Afficher les labels de projet"
msgid "View replaced file @ "
msgstr "Voir le fichier remplacé @ "
+msgid "View the documentation"
+msgstr "Afficher la documentation"
+
msgid "Visibility and access controls"
msgstr "Contrôles de visibilité et d’accès"
+msgid "Visibility level"
+msgstr "Niveau de visibilité"
+
msgid "Visibility level:"
msgstr "Niveau de visibilité :"
@@ -7868,6 +8931,36 @@ msgstr "Public"
msgid "VisibilityLevel|Unknown"
msgstr "Inconnu"
+msgid "Vulnerability|Class"
+msgstr "Classe"
+
+msgid "Vulnerability|Confidence"
+msgstr "Confiance"
+
+msgid "Vulnerability|Description"
+msgstr "Description"
+
+msgid "Vulnerability|File"
+msgstr "Fichier"
+
+msgid "Vulnerability|Identifiers"
+msgstr "Identifiants"
+
+msgid "Vulnerability|Instances"
+msgstr "Instances"
+
+msgid "Vulnerability|Links"
+msgstr "Liens"
+
+msgid "Vulnerability|Project"
+msgstr "Projet"
+
+msgid "Vulnerability|Severity"
+msgstr "Gravité"
+
+msgid "Vulnerability|Solution"
+msgstr "Solution"
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Vous voulez voir les données ? Merci de contacter un administrateur pour en obtenir l’accès."
@@ -7907,6 +9000,12 @@ msgstr "Lorsque cette option est activée, les utilisateurs et utilisarices ne p
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "Lorsque vous laissez l’URL vide, des étiquettes de classification peuvent toujours être spécifiées sans désactiver les fonctionnalités interâ€projets ni effectuer de vérifications d’autorisation externes."
+msgid "Who can see this group?"
+msgstr "Qui peut voir ce groupe ?"
+
+msgid "Who will be able to see this group?"
+msgstr "Qui sera en mesure de voir ce groupe ?"
+
msgid "Wiki"
msgstr "Wiki"
@@ -8057,6 +9156,9 @@ msgstr "Oui, l’ajouter"
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr "Oui, permettezâ€moi d’associer les utilisateurs de Google Code aux noms complets ou aux nom d’utilisateurs de GitLab."
+msgid "Yesterday"
+msgstr "Hier"
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr "Vous êtes un administrateur ou une administratrice, ce qui signifie qu’accorder un accès à <strong>%{client_name}</strong> lui permettra d’interagir avec GitLab en tant qu’administrateur également. Faitesâ€le avec prudence."
@@ -8075,9 +9177,6 @@ msgstr "Vous allez transférer %{project_full_name} à un nouveau ou une nouvell
msgid "You are on a read-only GitLab instance."
msgstr "Vous êtes sur une instance GitLab en lecture seule."
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr "Vous êtes sur un nœud Geo secondaire <b>en lecture seule</b>. Si vous voulez apporter des modifications, vous devez le faire depuis cette page sur le %{primary_node}."
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr "Vous pouvez %{linkStart}afficher les données brutes%{linkEnd} à la place."
@@ -8087,9 +9186,6 @@ msgstr "Vous pouvez également créer un projet en ligne de commande."
msgid "You can also star a label to make it a priority label."
msgstr "Vous pouvez marquer un label comme important pour en faire un label prioritaire."
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr "Vous pouvez également tester votre .gitlab-ci.yml avec %{linkStart}Lint%{linkEnd}"
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr "Vous pouvez facilement y contribuer en demandant à rejoindre ces groupes."
@@ -8109,7 +9205,10 @@ msgid "You can resolve the merge conflict using either the Interactive mode, by
msgstr "Vous pouvez résoudre le conflit de fusion Git soit en mode interactif, en cliquant sur les boutons « %{use_ours} » ou « %{use_theirs} », soit en modifiant directement les fichiers. Valider ces modifications dans la branche « %{branch_name} »"
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
-msgstr ""
+msgstr "Vous pouvez configurer des tâches pour n’utiliser des exécuteurs qu’avec des étiquettes spécifiques. Séparez les étiquettes par des virgules."
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr "Vous pouvez tester votre fichier « .gitlab-ci.yml » avec %{linkStart}CI Lint%{linkEnd}."
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr "Vous ne pouvez pas écrire sur une instance GitLab Geo secondaire en lecture seule. Veuillez utiliser le %{link_to_primary_node} à la place."
@@ -8117,6 +9216,9 @@ msgstr "Vous ne pouvez pas écrire sur une instance GitLab Geo secondaire en le
msgid "You cannot write to this read-only GitLab instance."
msgstr "Vous ne pouvez pas écrire sur cette instance GitLab en lecture seule."
+msgid "You do not have any subscriptions yet"
+msgstr "Vous n’avez souscrit à aucun abonnement pour le moment"
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "Vous ne disposez pas des autorisations appropriées pour outrepasser les paramètres de synchronisation du groupe LDAP."
@@ -8138,9 +9240,6 @@ msgstr "Vous devez accepter les conditions générales d’utilisation et la pol
msgid "You must have maintainer access to force delete a lock"
msgstr "Seul un responsable peut forcer la suppression d’un verrou"
-msgid "You must sign in to star a project"
-msgstr "Vous devez vous connecter pour mettre un projet en favori"
-
msgid "You need a different license to enable FileLocks feature"
msgstr "Vous avez besoin d’une licence différente pour activer la fonctionnalité de verrouillage de fichiers FileLocks"
@@ -8150,6 +9249,12 @@ msgstr "Pour aller plus loin, vous devez disposer de git-lfs en version %{min_g
msgid "You need permission."
msgstr "Vous avez besoin d’une autorisation."
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr "Vous allez perdre toutes les modifications apportées à ce fichier. Cette action ne peut pas être annulée."
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr "Vous allez perdre toutes les modifications non indexées que vous avez effectuées sur ce projet. Cette action ne peut pas être annulée."
+
msgid "You will not get any notifications via email"
msgstr "Vous ne recevrez aucune notification par courriel"
@@ -8216,6 +9321,9 @@ msgstr "Vos modifications peuvent être validées sur %{branch_name} car une dem
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr "Vos modifications ont été validées. Commit %{commitId} %{commitStats}"
+msgid "Your changes have been saved"
+msgstr "Vos modifications ont été enregistrées"
+
msgid "Your comment will not be visible to the public."
msgstr "Votre commentaire ne sera pas visible publiquement."
@@ -8229,7 +9337,7 @@ msgid "Your projects"
msgstr "Vos projets"
msgid "a deleted user"
-msgstr ""
+msgstr "un utilisateur supprimé"
msgid "ago"
msgstr "auparavant "
@@ -8237,16 +9345,6 @@ msgstr "auparavant "
msgid "among other things"
msgstr "entre autres choses"
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] "et une vulnérabilité corrigée"
-msgstr[1] "et %d vulnérabilités corrigées"
-
msgid "assign yourself"
msgstr "assignez vous"
@@ -8274,20 +9372,55 @@ msgstr "%{namespace} est affecté par « %{vulnerability} »."
msgid "ciReport|%{remainingPackagesCount} more"
msgstr "%{remainingPackagesCount} restant(s)"
-msgid "ciReport|%{reportName} is loading"
-msgstr "%{reportName} est en cours de chargement"
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] "%{reportType} %{status} a détecté %{fixedCount} vulnérabilité corrigée"
+msgstr[1] "%{reportType} %{status} a détecté %{fixedCount} vulnérabilités corrigées"
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] "%{reportType} %{status} a détecté %{newCount} nouvelle vulnérabilité"
+msgstr[1] "%{reportType} %{status} a détecté %{newCount} nouvelles vulnérabilités"
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr "%{reportType} %{status} a détecté de nouvelles vulnérabilités (%{newCount}) et des vulnérabilités corrigées (%{fixedCount})"
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] "%{reportType} %{status} a détecté %{newCount} vulnérabilité dans la branche source"
+msgstr[1] "%{reportType} %{status} a détecté %{newCount} vulnérabilités dans la branche source"
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr "%{reportType} %{status} n’a détecté aucune nouvelle vulnérabilité"
-msgid "ciReport|%{reportName} resulted in error while loading results"
-msgstr "%{reportName} a provoqué une erreur lors du chargement des résultats"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr "%{reportType} %{status} n’a détecté aucune vulnérabilité"
-msgid "ciReport|%{type} detected no new security vulnerabilities"
-msgstr "%{type} n’a détecté aucune nouvelle vulnérabilité de sécurité"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr "%{reportType} %{status} n’a détecté aucune vulnérabilité dans la branche source"
-msgid "ciReport|%{type} detected no security vulnerabilities"
-msgstr "%{type} n’a détecté aucune vulnérabilité de sécurité"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] "%{reportType} a détecté %{vulnerabilityCount} vulnérabilité"
+msgstr[1] "%{reportType} a détecté %{vulnerabilityCount} vulnérabilités"
-msgid "ciReport|%{type} detected no vulnerabilities"
-msgstr "%{type} n’a détecté aucune vulnérabilité"
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr "%{reportType} n’a détecté aucune vulnérabilité"
+
+msgid "ciReport|%{reportType} is loading"
+msgstr "%{reportType} est en cours de chargement"
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr "%{reportType} : le chargement a généré une erreur"
+
+msgid "ciReport|(errors when loading results)"
+msgstr "(erreurs lors du chargement des résultats)"
+
+msgid "ciReport|(is loading)"
+msgstr "(en cours de chargement)"
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr "(en cours de chargement, erreurs lors du chargement des résultats)"
msgid "ciReport|Class"
msgstr "Classe"
@@ -8298,38 +9431,20 @@ msgstr "Qualité du code"
msgid "ciReport|Confidence"
msgstr "Niveau de confiance"
-msgid "ciReport|Container scanning detected"
-msgstr "Analyse de conteneur détectée"
+msgid "ciReport|Container scanning"
+msgstr "Analyse du conteneur"
msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr "L’analyse des conteneurs permet la détection de vulnérabilités connues dans vos images Docker."
-msgid "ciReport|Container scanning is loading"
-msgstr "Chargement de l’analyse de conteneur en cours"
-
-msgid "ciReport|Container scanning resulted in error while loading results"
-msgstr "L’analyse de conteneur a provoqué une erreur lors du chargement des résultats"
-
-msgid "ciReport|DAST detected"
-msgstr "DAST détecté"
-
-msgid "ciReport|DAST is loading"
-msgstr "DAST en cours de chargement"
-
-msgid "ciReport|DAST resulted in error while loading results"
-msgstr "DAST a provoqué une erreur lors du chargement des résultats"
+msgid "ciReport|DAST"
+msgstr "DAST"
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
-msgstr ""
+msgstr "L’analyse des dépendances a détecté une vulnérabilité connue dans les dépendances de votre code source."
-msgid "ciReport|Dependency scanning detected"
-msgstr "Analyse de dépendances détectée"
-
-msgid "ciReport|Dependency scanning is loading"
-msgstr "Chargement de l’analyse des dépendances en cours"
-
-msgid "ciReport|Dependency scanning resulted in error while loading results"
-msgstr "L’analyse des dépendance a provoqué une erreur lors du chargement des résultats"
+msgid "ciReport|Dependency scanning"
+msgstr "Analyse des dépendances"
msgid "ciReport|Description"
msgstr "Description"
@@ -8361,21 +9476,18 @@ msgstr "Instances"
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr "En savoir plus sur l’interaction avec les rapports de sécurité (alpha)."
-msgid "ciReport|Learn more about whitelisting"
-msgstr "En savoir plus sur la mise en liste blanche"
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Le gestionnaire de licences a détecté %d licence pour la seule branche source"
+msgstr[1] "Le gestionnaire de licences a détecté %d licences pour la seule branche source"
msgid "ciReport|License management detected %d new license"
msgid_plural "ciReport|License management detected %d new licenses"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Le gestionnaire de licences a détecté %d nouvelle licence"
+msgstr[1] "Le gestionnaire de licences a détecté %d nouvelles licences"
msgid "ciReport|License management detected no licenses for the source branch only"
-msgstr ""
+msgstr "Le gestionnaire de licences n’a détecté aucune licence pour la seule branche source"
msgid "ciReport|License management detected no new licenses"
msgstr "Le gestionnaire de licences n’a détecté aucune nouvelle licence"
@@ -8386,6 +9498,9 @@ msgstr "Liens"
msgid "ciReport|Loading %{reportName} report"
msgstr "Chargement du rapport %{reportName}"
+msgid "ciReport|Manage licenses"
+msgstr "Gérer les licences"
+
msgid "ciReport|Method"
msgstr "Méthode"
@@ -8404,14 +9519,8 @@ msgstr "Indicateurs de performance"
msgid "ciReport|Revert dismissal"
msgstr "Annuler le rejet"
-msgid "ciReport|SAST detected"
-msgstr "SAST détecté"
-
-msgid "ciReport|SAST is loading"
-msgstr "Chargement de SAST en cours"
-
-msgid "ciReport|SAST resulted in error while loading results"
-msgstr "SAST a provoqué une erreur lors du chargement des résultats"
+msgid "ciReport|SAST"
+msgstr "SAST"
msgid "ciReport|Security scanning"
msgstr "Analyse de sécurité"
@@ -8419,9 +9528,6 @@ msgstr "Analyse de sécurité"
msgid "ciReport|Security scanning failed loading any results"
msgstr "L’analyse de sécurité n’a pas réussi à charger de résultats"
-msgid "ciReport|Security scanning is loading"
-msgstr "Chargement de l’analyse de sécurité en cours"
-
msgid "ciReport|Severity"
msgstr "Sévérité"
@@ -8452,23 +9558,17 @@ msgstr "Une erreur s’est produite lors du chargement du rapport d’analyse de
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "Une erreur s’est produite lors de l’annulation du rejet. Veuillez réessayer."
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr "Les vulnérabilités non approuvées (en rouge) peuvent être marquées comme approuvées."
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr "Mise à niveau de %{name} de %{version} à %{fixed}."
msgid "ciReport|Used by %{packagesString}"
msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Utilisé par %{packagesString}"
+msgstr[1] "Utilisé par %{packagesString} et %{lastPackage}"
msgid "ciReport|View full report"
msgstr "Voir le rapport complet"
-msgid "ciReport|no vulnerabilities"
-msgstr "aucune vulnérabilité"
-
msgid "ciReport|on pipeline"
msgstr "dans le pipeline"
@@ -8476,10 +9576,10 @@ msgid "command line instructions"
msgstr "instructions en ligne de commande"
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
+msgstr "Vous êtes sur le point de désactiver la confidentialité. Cela signifie que <strong>tout le monde</strong> sera en mesure de voir et de laisser un commentaire sur ce ticket."
msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
+msgstr "Vous êtes sur le point de d’activer la confidentialité. Cela signifie que seuls les membres de l’équipe avec <strong>au moins un accès en tant que rapporteur</strong> seront en mesure de voir et de laisser des commentaires sur le ticket."
msgid "connecting"
msgstr "connexion en cours"
@@ -8498,25 +9598,17 @@ msgstr[1] "jours"
msgid "deploy token"
msgstr "jeton de déploiement"
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] "a détecté %d vulnérabilité corrigée"
-msgstr[1] "a détecté %d vulnérabilités corrigées"
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] "a détecté %d nouvelle vulnérabilité"
-msgstr[1] "a détecté %d nouvelles vulnérabilités"
-
-msgid "detected no vulnerabilities"
-msgstr "n’a détecté aucune vulnérabilité"
-
msgid "disabled"
msgstr "désactivé"
msgid "done"
msgstr "terminé"
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] "brouillon"
+msgstr[1] "brouillons"
+
msgid "enabled"
msgstr "activé"
@@ -8526,11 +9618,17 @@ msgstr "%{slash_command} mettra à jour la durée estimée avec la dernière com
msgid "for this project"
msgstr "pour ce projet"
+msgid "from"
+msgstr "de"
+
+msgid "help"
+msgstr "aide"
+
msgid "here"
msgstr "ici"
msgid "https://your-bitbucket-server"
-msgstr ""
+msgstr "https://votre-serveur-bitbucket"
msgid "import flow"
msgstr "flux d’importation"
@@ -8540,8 +9638,8 @@ msgstr "importation en cours"
msgid "instance completed"
msgid_plural "instances completed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "instance terminée"
+msgstr[1] "instances terminées"
msgid "is invalid because there is downstream lock"
msgstr "n’est pas valide, car il y a un verrou en aval"
@@ -8553,13 +9651,16 @@ msgid "is not a valid X509 certificate."
msgstr "n’est pas un certificat X.509 valide."
msgid "issue boards"
-msgstr ""
+msgstr "tableaux des tickets"
+
+msgid "latest deployment"
+msgstr "dernier déploiement"
msgid "latest version"
msgstr "dernière version"
msgid "license management"
-msgstr ""
+msgstr "gestion des licences"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "verrouillé par %{path_lock_user_name} %{created_at}"
@@ -8591,7 +9692,7 @@ msgid "mrWidget|An error occured while removing your approval."
msgstr "Une erreur est survenue lors de la suppression de votre approbation."
msgid "mrWidget|An error occured while retrieving approval data for this merge request."
-msgstr ""
+msgstr "Une erreur est survenue lors de la récupération des données d’approbation pour cette demande de fusion."
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Une erreur est survenue lors de l’envoi de votre approbation."
@@ -8642,7 +9743,7 @@ msgid "mrWidget|Failed to load deployment statistics"
msgstr "Impossible de charger les statistiques de déploiement"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
-msgstr ""
+msgstr "La fusion rapide fastâ€forward n’est pas possible. Pour réaliser cette fusion, vous devez d’abord effectuer un « git rebase » en local."
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr "Si la branche %{branch} existe dans votre dépôt local, vous pouvez fusionner cette demande de fusion manuellement à l’aide de"
@@ -8684,13 +9785,13 @@ msgid "mrWidget|Open in Web IDE"
msgstr "Ouvrir dans l’EDI Web"
msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
-msgstr ""
+msgstr "Pipeline bloqué. Le pipeline de cette demande de fusion nécessite une action manuelle pour continuer"
msgid "mrWidget|Plain diff"
msgstr "Diff simple"
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
-msgstr ""
+msgstr "Prête à être fusionnée automatiquement. Demandez à quelqu’un ayant un accès en écriture à ce dépôt d’effectuer cette fusionner"
msgid "mrWidget|Refresh"
msgstr "Actualiser"
@@ -8715,19 +9816,19 @@ msgstr "Demande de fusion de"
msgid "mrWidget|Requires 1 more approval"
msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Nécessite encore une approbation"
+msgstr[1] "Nécessite encore %d approbations"
msgid "mrWidget|Requires 1 more approval by"
msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Nécessite encore l’approbation de"
+msgstr[1] "Nécessite encore %d approbations de"
msgid "mrWidget|Resolve conflicts"
msgstr "Résoudre les conflits"
msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
-msgstr ""
+msgstr "Résolvez ces conflits ou demandez à une personne ayant un accès en écriture à ce dépôt d’effectuer la fusion localement"
msgid "mrWidget|Revert"
msgstr "Défaire"
@@ -8748,16 +9849,16 @@ msgid "mrWidget|The changes will be merged into"
msgstr "Les modifications seront fusionnées dans"
msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
-msgstr ""
+msgstr "Le pipeline de cette demande de fusion a échoué. Veuillez réexécutez la tâche ou pousser un nouveau commit pour résoudre le problème"
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
-msgstr ""
+msgstr "La branche source HEAD a changé récemment. Veuillez recharger la page et vérifier les modifications avant d’effectuer la fusion"
msgid "mrWidget|The source branch has been removed"
msgstr "La branche source a été supprimée"
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
-msgstr ""
+msgstr "La branche source est à %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} de la branche cible"
msgid "mrWidget|The source branch is being removed"
msgstr "La branche source est en cours de suppression"
@@ -8783,6 +9884,9 @@ msgstr "Cette demande de fusion est en cours de fusion"
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "Ce projet est archivé, l’accès en écriture a été désactivé"
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr "Vous n’êtes pas autorisé à modifier directement ce projet. Veuillez créer un projet divergent afin d’effectuer des changements."
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr "Vous pouvez fusionner cette demande de fusion manuellement à l’aide de la"
@@ -8801,6 +9905,9 @@ msgstr "dans"
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr "pour être fusionnée automatiquement lorsque le pipeline réussit"
+msgid "n/a"
+msgstr "non disponible"
+
msgid "new merge request"
msgstr "nouvelle demande de fusion"
@@ -8829,6 +9936,11 @@ msgstr "jeton d’accès personnel"
msgid "private key does not match certificate."
msgstr "la clef privée ne correspond pas au certificat."
+msgid "project"
+msgid_plural "projects"
+msgstr[0] "projet"
+msgstr[1] "projets"
+
msgid "remaining"
msgstr "restant"
@@ -8841,6 +9953,11 @@ msgstr "supprimer la date d’échéance"
msgid "remove weight"
msgstr "supprimer le poids"
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] "réponse"
+msgstr[1] "réponses"
+
msgid "source"
msgstr "source"
@@ -8856,6 +9973,9 @@ msgstr "ce document"
msgid "to help your contributors communicate effectively!"
msgstr "pour aider vos contributeurs à communiquer efficacement !"
+msgid "toggle collapse"
+msgstr "déplier ou replier"
+
msgid "username"
msgstr "nom d’utilisateur"
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index bc5d2aeac46..60274d883fa 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -19,6 +19,11 @@ msgstr ""
msgid " Status"
msgstr ""
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -34,6 +39,11 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -93,6 +103,9 @@ msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] ""
@@ -107,6 +120,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -119,23 +135,12 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr ""
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr ""
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -153,6 +158,9 @@ msgstr ""
msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
msgstr ""
+msgid "%{user_name} profile page"
+msgstr ""
+
msgid "+ %{count} more"
msgstr ""
@@ -211,6 +219,9 @@ msgstr[1] ""
msgid "1st contribution!"
msgstr ""
+msgid "2FA"
+msgstr ""
+
msgid "2FA enabled"
msgstr ""
@@ -262,6 +273,9 @@ msgstr ""
msgid "A deleted user"
msgstr ""
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -289,6 +303,9 @@ msgstr ""
msgid "Abuse reports"
msgstr ""
+msgid "Accept invitation"
+msgstr ""
+
msgid "Accept terms"
msgstr ""
@@ -301,12 +318,6 @@ msgstr ""
msgid "Access expiration date"
msgstr ""
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr ""
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
-msgstr ""
-
msgid "Account"
msgstr ""
@@ -334,6 +345,15 @@ msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
msgid "Add license"
msgstr ""
@@ -388,9 +408,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -427,7 +444,7 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
@@ -448,6 +465,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -457,52 +477,37 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
-msgid "Allows you to add and manage Kubernetes clusters."
+msgid "Allow users to request access"
msgstr ""
-msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgid "Allow users to request access if visibility is public or internal."
msgstr ""
-msgid "An application called %{link_to_client} is requesting access to your GitLab account."
-msgstr ""
-
-msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
-msgstr ""
-
-msgid "An error accured whilst committing your changes."
-msgstr ""
-
-msgid "An error has occurred"
-msgstr ""
-
-msgid "An error occured creating the new branch."
-msgstr ""
-
-msgid "An error occured whilst fetching the job trace."
+msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
-msgid "An error occured whilst loading all the files."
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
-msgid "An error occured whilst loading the file content."
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
-msgid "An error occured whilst loading the file."
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr ""
-msgid "An error occured whilst loading the merge request changes."
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An error occured whilst loading the merge request version data."
+msgid "An error accured whilst committing your changes."
msgstr ""
-msgid "An error occured whilst loading the merge request."
+msgid "An error has occurred"
msgstr ""
-msgid "An error occured whilst loading the pipelines jobs."
+msgid "An error occurred creating the new branch."
msgstr ""
msgid "An error occurred previewing the blob"
@@ -511,6 +516,9 @@ msgstr ""
msgid "An error occurred when toggling the notification subscription"
msgstr ""
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
msgid "An error occurred while dismissing the alert. Refresh the page and try again."
msgstr ""
@@ -577,6 +585,33 @@ msgstr ""
msgid "An error occurred while validating username"
msgstr ""
+msgid "An error occurred whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occurred whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occurred whilst loading all the files."
+msgstr ""
+
+msgid "An error occurred whilst loading the file content."
+msgstr ""
+
+msgid "An error occurred whilst loading the file."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occurred whilst loading the merge request."
+msgstr ""
+
+msgid "An error occurred whilst loading the pipelines jobs."
+msgstr ""
+
msgid "An error occurred. Please try again."
msgstr ""
@@ -595,7 +630,7 @@ msgstr ""
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -619,9 +654,15 @@ msgstr ""
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
msgid "Are you sure you want to remove %{group_name}?"
msgstr ""
@@ -634,6 +675,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure?"
msgstr ""
@@ -766,6 +810,9 @@ msgstr ""
msgid "Automatically marked as default internal user"
msgstr ""
+msgid "Automatically resolved"
+msgstr ""
+
msgid "Available"
msgstr ""
@@ -775,6 +822,12 @@ msgstr ""
msgid "Available group Runners : %{runners}."
msgstr ""
+msgid "Available shared Runners:"
+msgstr ""
+
+msgid "Available specific runners"
+msgstr ""
+
msgid "Avatar will be removed. Are you sure?"
msgstr ""
@@ -787,9 +840,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -883,6 +933,9 @@ msgstr ""
msgid "Bitbucket import"
msgstr ""
+msgid "Blocked"
+msgstr ""
+
msgid "Blog"
msgstr ""
@@ -1044,12 +1097,18 @@ msgstr ""
msgid "Business metrics (Custom)"
msgstr ""
+msgid "By %{user_name}"
+msgstr ""
+
msgid "ByAuthor|by"
msgstr ""
msgid "CI / CD"
msgstr ""
+msgid "CI / CD Charts"
+msgstr ""
+
msgid "CI / CD Settings"
msgstr ""
@@ -1074,6 +1133,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1101,9 +1163,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1119,6 +1178,9 @@ msgstr ""
msgid "Cannot modify managed Kubernetes cluster"
msgstr ""
+msgid "Change permissions"
+msgstr ""
+
msgid "Change template"
msgstr ""
@@ -1146,13 +1208,16 @@ msgstr ""
msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
msgstr ""
+msgid "Changes suppressed. Click to show."
+msgstr ""
+
msgid "Charts"
msgstr ""
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1206,6 +1271,9 @@ msgstr ""
msgid "CiStatusLabel|created"
msgstr ""
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr ""
@@ -1224,6 +1292,9 @@ msgstr ""
msgid "CiStatusLabel|skipped"
msgstr ""
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr ""
@@ -1236,6 +1307,9 @@ msgstr ""
msgid "CiStatusText|created"
msgstr ""
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr ""
@@ -1269,7 +1343,7 @@ msgstr ""
msgid "CiVariable|All environments"
msgstr ""
-msgid "CiVariable|Error occured while saving variables"
+msgid "CiVariable|Error occurred while saving variables"
msgstr ""
msgid "CiVariable|Protected"
@@ -1281,7 +1355,7 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1317,6 +1391,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Closed"
+msgstr ""
+
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
msgstr ""
@@ -1329,6 +1406,15 @@ msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1338,13 +1424,13 @@ msgstr ""
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
msgstr ""
-msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgid "ClusterIntegration|An error occurred while trying to fetch your projects: %{error}"
msgstr ""
-msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgid "ClusterIntegration|An error occurred while trying to fetch zone machine types: %{error}"
msgstr ""
msgid "ClusterIntegration|Applications"
@@ -1356,6 +1442,9 @@ msgstr ""
msgid "ClusterIntegration|CA Certificate"
msgstr ""
+msgid "ClusterIntegration|Cert-Manager"
+msgstr ""
+
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
@@ -1377,6 +1466,9 @@ msgstr ""
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
+msgid "ClusterIntegration|Copy Knative IP Address to clipboard"
+msgstr ""
+
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
@@ -1431,6 +1523,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1473,13 +1568,22 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster details"
+msgid "ClusterIntegration|Knative (pronounced kay-nay-tiv) extends Kubernetes to provide a set of middleware components that are essential to build modern, source-centric, and container-based applications that can run anywhere: on premises, in the cloud, or even in a third-party data center."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration"
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Knative IP Address:"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1491,7 +1595,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1500,10 +1604,16 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Let's Encrypt"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1548,6 +1658,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1560,7 +1673,7 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
-msgid "ClusterIntegration|RBAC-enabled cluster (experimental)"
+msgid "ClusterIntegration|RBAC-enabled cluster"
msgstr ""
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
@@ -1632,18 +1745,12 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to many functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
-msgstr ""
-
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr ""
@@ -1671,6 +1778,9 @@ msgstr ""
msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr ""
+msgid "ClusterIntegration|cert-manager is a native Kubernetes certificate management controller that helps with issuing certificates. Installing cert-manager on your cluster will issue a certificate by %{letsEncrypt} and ensure that certificates are valid and up to date."
+msgstr ""
+
msgid "ClusterIntegration|check the pricing here"
msgstr ""
@@ -1698,12 +1808,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -1738,6 +1854,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr ""
@@ -1810,9 +1929,6 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
-msgstr ""
-
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -1822,7 +1938,7 @@ msgstr ""
msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the way a user creates a new account."
@@ -1897,6 +2013,9 @@ msgstr ""
msgid "Contribution"
msgstr ""
+msgid "Contribution Charts"
+msgstr ""
+
msgid "Contribution guide"
msgstr ""
@@ -1930,9 +2049,18 @@ msgstr ""
msgid "Copy HTTPS clone URL"
msgstr ""
+msgid "Copy ID to clipboard"
+msgstr ""
+
msgid "Copy SSH clone URL"
msgstr ""
+msgid "Copy SSH public key"
+msgstr ""
+
+msgid "Copy SSH public key to clipboard"
+msgstr ""
+
msgid "Copy URL to clipboard"
msgstr ""
@@ -1948,15 +2076,24 @@ msgstr ""
msgid "Copy file path to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2026,6 +2163,9 @@ msgstr ""
msgid "Create project label"
msgstr ""
+msgid "Create your first page"
+msgstr ""
+
msgid "CreateTag|Tag"
msgstr ""
@@ -2062,6 +2202,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -2074,6 +2217,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr ""
@@ -2119,6 +2265,9 @@ msgstr ""
msgid "December"
msgstr ""
+msgid "Decline"
+msgstr ""
+
msgid "Decline and sign out"
msgstr ""
@@ -2134,12 +2283,33 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2277,6 +2447,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2292,6 +2468,15 @@ msgstr ""
msgid "Details"
msgstr ""
+msgid "Detect host keys"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2313,6 +2498,12 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Disable shared Runners"
+msgstr ""
+
+msgid "Disabled"
+msgstr ""
+
msgid "Discard"
msgstr ""
@@ -2403,6 +2594,12 @@ msgstr ""
msgid "Edit application"
msgstr ""
+msgid "Edit comment"
+msgstr ""
+
+msgid "Edit environment"
+msgstr ""
+
msgid "Edit files in the editor and commit changes here"
msgstr ""
@@ -2445,15 +2642,15 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable version check and usage ping."
msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr ""
+msgid "Enable shared Runners"
+msgstr ""
+
msgid "Enable the Performance Bar for a given group."
msgstr ""
@@ -2463,6 +2660,9 @@ msgstr ""
msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
msgstr ""
+msgid "Enabled"
+msgstr ""
+
msgid "Ends at (UTC)"
msgstr ""
@@ -2484,6 +2684,9 @@ msgstr ""
msgid "Environments"
msgstr ""
+msgid "Environments allow you to track deployments of your application %{link_to_read_more}."
+msgstr ""
+
msgid "Environments|An error occurred while fetching the environments."
msgstr ""
@@ -2553,10 +2756,16 @@ msgstr ""
msgid "Environments|Stop environment"
msgstr ""
+msgid "Environments|Stopping"
+msgstr ""
+
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Epic"
msgstr ""
msgid "Error"
@@ -2640,6 +2849,9 @@ msgstr ""
msgid "EventFilterBy|Filter by team"
msgstr ""
+msgid "Every %{action} attempt has failed: %{job_error_message}. Please try again."
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -2649,6 +2861,9 @@ msgstr ""
msgid "Every week (Sundays at 4:00am)"
msgstr ""
+msgid "Everyone"
+msgstr ""
+
msgid "Everyone can contribute"
msgstr ""
@@ -2664,6 +2879,12 @@ msgstr ""
msgid "Expiration date"
msgstr ""
+msgid "Expires in %{expires_at}"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -2682,6 +2903,9 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "External URL"
+msgstr ""
+
msgid "Facebook"
msgstr ""
@@ -2697,6 +2921,12 @@ msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -2724,6 +2954,18 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File added"
+msgstr ""
+
+msgid "File deleted"
+msgstr ""
+
+msgid "File mode changed from %{a_mode} to %{b_mode}"
+msgstr ""
+
+msgid "File moved"
+msgstr ""
+
msgid "File templates"
msgstr ""
@@ -2739,6 +2981,9 @@ msgstr ""
msgid "Filter by commit message"
msgstr ""
+msgid "Filter by two-factor authentication"
+msgstr ""
+
msgid "Filter..."
msgstr ""
@@ -2754,6 +2999,9 @@ msgstr ""
msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
msgstr ""
+msgid "Fingerprints"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -2859,9 +3107,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -2880,6 +3125,9 @@ msgstr ""
msgid "GitLab Import"
msgstr ""
+msgid "GitLab Shared Runners execute code of different projects on the same Runner unless you configure GitLab Runner Autoscale with MaxBuilds 1 (which it is on GitLab.com)."
+msgstr ""
+
msgid "GitLab User"
msgstr ""
@@ -2907,6 +3155,9 @@ msgstr ""
msgid "Gitea Import"
msgstr ""
+msgid "Given access %{time_ago}"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -2931,6 +3182,9 @@ msgstr ""
msgid "Got it!"
msgstr ""
+msgid "Grant access"
+msgstr ""
+
msgid "Graph"
msgstr ""
@@ -2949,9 +3203,18 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -2961,6 +3224,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -2976,9 +3242,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3093,6 +3356,12 @@ msgstr ""
msgid "Help page text and support page url."
msgstr ""
+msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
msgid "Hide payload"
msgstr ""
@@ -3110,6 +3379,9 @@ msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
+msgid "However, you are already a member of this %{member_source}. Sign in using a different account to accept the invitation."
+msgstr ""
+
msgid "I accept the %{terms_link}"
msgstr ""
@@ -3185,6 +3457,9 @@ msgstr ""
msgid "ImageDiffViewer|Swipe"
msgstr ""
+msgid "Impersonation has been disabled"
+msgstr ""
+
msgid "Import"
msgstr ""
@@ -3236,6 +3511,9 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Import timed out. Import took longer than %{import_jobs_expiration} seconds"
+msgstr ""
+
msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
msgstr ""
@@ -3257,6 +3535,9 @@ msgstr ""
msgid "Inline"
msgstr ""
+msgid "Input host keys manually"
+msgstr ""
+
msgid "Input your repository URL"
msgstr ""
@@ -3284,6 +3565,9 @@ msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
+msgid "Internal"
+msgstr ""
+
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
msgstr ""
@@ -3299,9 +3583,21 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Invitation"
+msgstr ""
+
msgid "Invite"
msgstr ""
+msgid "Invoke Count"
+msgstr ""
+
+msgid "Invoke Time"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -3317,6 +3613,12 @@ msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "It's you"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -3332,9 +3634,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -3371,10 +3670,10 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
-msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgid "Job|This job is stuck because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
@@ -3389,12 +3688,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -3461,6 +3754,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
@@ -3481,6 +3777,9 @@ msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -3543,6 +3842,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -3642,10 +3944,37 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
-msgid "Max access level"
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -3657,6 +3986,9 @@ msgstr ""
msgid "Median"
msgstr ""
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -3690,18 +4022,33 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr ""
+msgid "MergeRequests|started a discussion"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}an old version of the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on %{linkStart}the diff%{linkEnd}"
+msgstr ""
+
+msgid "MergeRequests|started a discussion on commit %{linkStart}%{commitId}%{linkEnd}"
+msgstr ""
+
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -3720,6 +4067,9 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
+msgid "Metrics for environment"
+msgstr ""
+
msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
msgstr ""
@@ -3729,6 +4079,9 @@ msgstr ""
msgid "Metrics|Learn about environments"
msgstr ""
+msgid "Metrics|No data to display"
+msgstr ""
+
msgid "Metrics|No deployed environments"
msgstr ""
@@ -3837,6 +4190,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -3861,6 +4217,9 @@ msgstr ""
msgid "New Application"
msgstr ""
+msgid "New Environment"
+msgstr ""
+
msgid "New Group"
msgstr ""
@@ -3893,6 +4252,9 @@ msgstr ""
msgid "New directory"
msgstr ""
+msgid "New environment"
+msgstr ""
+
msgid "New file"
msgstr ""
@@ -3962,9 +4324,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -3983,6 +4342,9 @@ msgstr ""
msgid "No other labels with such name or description"
msgstr ""
+msgid "No preview for this file type"
+msgstr ""
+
msgid "No prioritised labels with such name or description"
msgstr ""
@@ -4004,12 +4366,6 @@ msgstr ""
msgid "None"
msgstr ""
-msgid "Not all comments are displayed because you're comparing two versions of the diff."
-msgstr ""
-
-msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
-
msgid "Not allowed to merge"
msgstr ""
@@ -4034,6 +4390,9 @@ msgstr ""
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
+msgid "Note that this invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
+msgstr ""
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
msgstr ""
@@ -4043,6 +4402,21 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Nothing here."
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -4112,9 +4486,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "Oct"
msgstr ""
@@ -4135,15 +4506,9 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
-msgid "Only comments from the following commit are shown below"
-msgstr ""
-
msgid "Only mirror protected branches"
msgstr ""
@@ -4165,6 +4530,9 @@ msgstr ""
msgid "Open source software to collaborate on code"
msgstr ""
+msgid "Opened"
+msgstr ""
+
msgid "OpenedNDaysAgo|Opened"
msgstr ""
@@ -4174,6 +4542,9 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -4225,6 +4596,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -4252,13 +4626,16 @@ msgstr ""
msgid "Permissions"
msgstr ""
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
msgid "Personal Access Token"
msgstr ""
-msgid "Pipeline"
+msgid "Pick a name"
msgstr ""
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
+msgid "Pipeline"
msgstr ""
msgid "Pipeline Health"
@@ -4375,15 +4752,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -4393,6 +4779,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -4429,12 +4821,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -4447,6 +4845,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we import the repository for you. Refresh at will."
msgstr ""
@@ -4477,6 +4878,9 @@ msgstr ""
msgid "Prioritized label"
msgstr ""
+msgid "Private"
+msgstr ""
+
msgid "Private - Project access must be granted explicitly to each user."
msgstr ""
@@ -4498,9 +4902,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
-msgid "Profiles|%{author_name} made a private contribution"
-msgstr ""
-
msgid "Profiles|Account scheduled for removal."
msgstr ""
@@ -4561,6 +4962,12 @@ msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
msgid "Profiles|Main settings"
msgstr ""
@@ -4600,6 +5007,9 @@ msgstr ""
msgid "Profiles|This email will be displayed on your public profile."
msgstr ""
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
@@ -4624,6 +5034,9 @@ msgstr ""
msgid "Profiles|Upload new avatar"
msgstr ""
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
@@ -4786,6 +5199,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -4825,9 +5241,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -4894,6 +5307,9 @@ msgstr ""
msgid "Provider"
msgstr ""
+msgid "Public"
+msgstr ""
+
msgid "Public - The group and any public projects can be viewed without any authentication."
msgstr ""
@@ -4921,6 +5337,9 @@ msgstr ""
msgid "Read more"
msgstr ""
+msgid "Read more about environments"
+msgstr ""
+
msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
@@ -4941,12 +5360,18 @@ msgid_plural "Refreshing in %d seconds to show the updated status..."
msgstr[0] ""
msgstr[1] ""
+msgid "Regenerate key"
+msgstr ""
+
msgid "Regex pattern"
msgstr ""
msgid "Register / Sign In"
msgstr ""
+msgid "Register U2F device"
+msgstr ""
+
msgid "Register and see your runners for this group."
msgstr ""
@@ -4989,12 +5414,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -5007,6 +5441,9 @@ msgstr ""
msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
msgid "Reporting"
msgstr ""
@@ -5058,13 +5495,19 @@ msgstr ""
msgid "Request Access"
msgstr ""
+msgid "Requested %{time_ago}"
+msgstr ""
+
msgid "Requests Profiles"
msgstr ""
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
-msgid "Reset git storage health information"
+msgid "Resend invite"
msgstr ""
msgid "Reset health check access token"
@@ -5082,6 +5525,9 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Resolved"
+msgstr ""
+
msgid "Response metrics (AWS ELB)"
msgstr ""
@@ -5162,6 +5608,9 @@ msgstr ""
msgid "Runners API"
msgstr ""
+msgid "Runners activated for this project"
+msgstr ""
+
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
@@ -5180,6 +5629,12 @@ msgstr ""
msgid "SSH Keys"
msgstr ""
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
msgid "SSL Verification"
msgstr ""
@@ -5279,13 +5734,13 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "See metrics"
msgstr ""
-msgid "Secret:"
+msgid "See the affected projects in the GitLab admin panel"
msgstr ""
msgid "Select"
@@ -5339,6 +5794,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send report"
+msgstr ""
+
msgid "Send usage data"
msgstr ""
@@ -5375,21 +5833,45 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr ""
-
msgid "Set up a %{type} Runner manually"
msgstr ""
msgid "Set up a specific Runner automatically"
msgstr ""
+msgid "Set up new U2F device"
+msgstr ""
+
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
msgid "Settings"
msgstr ""
@@ -5414,9 +5896,6 @@ msgstr ""
msgid "Show latest version"
msgstr ""
-msgid "Show latest version of the diff"
-msgstr ""
-
msgid "Show parent pages"
msgstr ""
@@ -5440,6 +5919,9 @@ msgstr ""
msgid "Sign in / Register"
msgstr ""
+msgid "Sign in via 2FA code"
+msgstr ""
+
msgid "Sign out"
msgstr ""
@@ -5449,6 +5931,9 @@ msgstr ""
msgid "Sign-up restrictions"
msgstr ""
+msgid "Similar issues"
+msgstr ""
+
msgid "Size and domain settings for static websites"
msgstr ""
@@ -5479,6 +5964,12 @@ msgstr ""
msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -5494,6 +5985,9 @@ msgstr ""
msgid "Something went wrong. Please try again."
msgstr ""
+msgid "Sorry, your filter produced no results"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -5602,6 +6096,9 @@ msgstr ""
msgid "Source is not available"
msgstr ""
+msgid "Source project cannot be found."
+msgstr ""
+
msgid "Spam Logs"
msgstr ""
@@ -5656,6 +6153,12 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
@@ -5668,6 +6171,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -5677,6 +6183,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -5704,6 +6213,9 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -5817,6 +6329,9 @@ msgstr ""
msgid "Templates"
msgstr ""
+msgid "Terminal for environment"
+msgstr ""
+
msgid "Terms of Service Agreement and Privacy Policy"
msgstr ""
@@ -5859,12 +6374,6 @@ msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures of after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
msgstr ""
@@ -5901,9 +6410,6 @@ msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr ""
@@ -5913,15 +6419,6 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr ""
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. When a previous check did complete yet, GitLab will skip a check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
@@ -5949,9 +6446,6 @@ msgstr ""
msgid "There are no labels yet"
msgstr ""
-msgid "There are no merge requests to show"
-msgstr ""
-
msgid "There are no projects shared with this group yet"
msgstr ""
@@ -5961,9 +6455,6 @@ msgstr ""
msgid "There are no unstaged changes"
msgstr ""
-msgid "There are problems accessing Git storage: "
-msgstr ""
-
msgid "There was an error loading users activity calendar."
msgstr ""
@@ -5982,12 +6473,18 @@ msgstr ""
msgid "There was an error when unsubscribing from this label."
msgstr ""
+msgid "These existing issues have a similar title. It might be better to comment there instead of creating another similar issue."
+msgstr ""
+
msgid "They can be managed using the %{link}."
msgstr ""
msgid "Third party offers"
msgstr ""
+msgid "This %{viewer} could not be displayed because %{reason}."
+msgstr ""
+
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
msgstr ""
@@ -6006,6 +6503,9 @@ msgstr ""
msgid "This diff is collapsed."
msgstr ""
+msgid "This diff was suppressed by a .gitattributes entry."
+msgstr ""
+
msgid "This directory"
msgstr ""
@@ -6018,6 +6518,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -6057,7 +6560,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -6066,10 +6572,10 @@ msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgid "This job is stuck because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
-msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgid "This job is stuck because you don't have any active runners that can run this job."
msgstr ""
msgid "This job is the most recent deployment to %{link}."
@@ -6078,6 +6584,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after its timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
@@ -6102,6 +6611,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -6111,6 +6623,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -6129,9 +6647,15 @@ msgstr ""
msgid "Time before an issue starts implementation"
msgstr ""
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr ""
+msgid "Time estimate"
+msgstr ""
+
msgid "Time remaining"
msgstr ""
@@ -6337,15 +6861,27 @@ msgstr ""
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
+msgid "To preserve performance only <strong>%{display_size} of ${real_size}</strong> files are displayed."
+msgstr ""
+
msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
+msgid "To start serving your jobs you can either add specific Runners to your project or use shared Runners"
+msgstr ""
+
msgid "To this GitLab instance"
msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
+msgid "To widen your search, change or remove filters above"
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -6355,9 +6891,18 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle comments for this file"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -6373,6 +6918,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -6388,6 +6936,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -6403,9 +6954,18 @@ msgstr ""
msgid "Try again"
msgstr ""
+msgid "Try again?"
+msgstr ""
+
+msgid "Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now."
+msgstr ""
+
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
@@ -6427,6 +6987,9 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
msgid "Unstage"
msgstr ""
@@ -6463,13 +7026,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -6526,9 +7092,54 @@ msgstr ""
msgid "User map"
msgstr ""
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
msgid "Users"
msgstr ""
+msgid "Users requesting access to"
+msgstr ""
+
msgid "Variables"
msgstr ""
@@ -6550,6 +7161,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View app"
+msgstr ""
+
+msgid "View deployment"
+msgstr ""
+
+msgid "View details: %{details_url}"
+msgstr ""
+
msgid "View file @ "
msgstr ""
@@ -6577,9 +7197,18 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
+msgid "Viewing commit"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -6607,6 +7236,9 @@ msgstr ""
msgid "We don't have enough data to show this stage."
msgstr ""
+msgid "We heard back from your U2F device. You have been authenticated."
+msgstr ""
+
msgid "We want to be sure it is you, please confirm you are not a robot."
msgstr ""
@@ -6622,6 +7254,12 @@ msgstr ""
msgid "When enabled, users cannot use GitLab until the terms have been accepted."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -6757,6 +7395,9 @@ msgstr ""
msgid "Wiki|Wiki Pages"
msgstr ""
+msgid "Will deploy to"
+msgstr ""
+
msgid "Withdraw Access Request"
msgstr ""
@@ -6769,6 +7410,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -6787,6 +7431,9 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
+msgid "You are receiving this message because you are a GitLab administrator for %{url}."
+msgstr ""
+
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -6796,9 +7443,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -6814,24 +7458,30 @@ msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""
-msgid "You can reset runners registration token by pressing a button below."
-msgstr ""
-
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You don't have any applications"
msgstr ""
msgid "You don't have any authorized applications"
msgstr ""
+msgid "You don't have any deployments right now."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -6847,6 +7497,9 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You need to register a two-factor authentication app before you can set up a U2F device."
+msgstr ""
+
msgid "You will loose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -6907,12 +7560,18 @@ msgstr ""
msgid "Your Todos"
msgstr ""
+msgid "Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left."
+msgstr ""
+
msgid "Your applications (%{size})"
msgstr ""
msgid "Your authorized applications"
msgstr ""
+msgid "Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer)."
+msgstr ""
+
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
msgstr ""
@@ -6922,6 +7581,9 @@ msgstr ""
msgid "Your comment will not be visible to the public."
msgstr ""
+msgid "Your device was successfully set up! Give it a name and register it with the GitLab server."
+msgstr ""
+
msgid "Your groups"
msgstr ""
@@ -6931,6 +7593,9 @@ msgstr ""
msgid "Your projects"
msgstr ""
+msgid "a deleted user"
+msgstr ""
+
msgid "ago"
msgstr ""
@@ -6963,24 +7628,41 @@ msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
+msgid "deleted"
+msgstr ""
+
msgid "deploy token"
msgstr ""
msgid "disabled"
msgstr ""
+msgid "discussion resolved"
+msgid_plural "discussions resolved"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "done"
msgstr ""
msgid "enabled"
msgstr ""
+msgid "error code:"
+msgstr ""
+
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
msgid "for this project"
msgstr ""
+msgid "from"
+msgstr ""
+
+msgid "group"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -6996,6 +7678,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -7224,12 +7909,20 @@ msgstr ""
msgid "personal access token"
msgstr ""
+msgid "project"
+msgstr ""
+
msgid "remaining"
msgstr ""
msgid "remove due date"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "source"
msgstr ""
@@ -7242,6 +7935,9 @@ msgstr ""
msgid "this document"
msgstr ""
+msgid "updated"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/gl_ES/gitlab.po b/locale/gl_ES/gitlab.po
index 5574ed0613f..035123e629f 100644
--- a/locale/gl_ES/gitlab.po
+++ b/locale/gl_ES/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Galician\n"
"Language: gl_ES\n"
"MIME-Version: 1.0\n"
@@ -13,13 +13,13 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: gl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:32\n"
+"PO-Revision-Date: 2018-11-19 17:23\n"
msgid " Status"
msgstr ""
msgid " and"
-msgstr ""
+msgstr " e"
msgid " degraded on %d point"
msgid_plural " degraded on %d points"
@@ -31,6 +31,14 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -46,6 +54,11 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d exportador"
@@ -91,11 +104,6 @@ msgid_plural "%d unstaged changes"
msgstr[0] ""
msgstr[1] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] ""
@@ -104,17 +112,31 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] ""
msgstr[1] ""
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -124,6 +146,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -139,23 +164,12 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr ""
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr ""
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -167,27 +181,13 @@ msgstr ""
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -314,6 +314,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr ""
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -356,13 +365,10 @@ msgstr ""
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
-msgstr ""
-
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgid "Access expiration date"
msgstr ""
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -392,27 +398,48 @@ msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
+msgid "Add Kubernetes cluster"
msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -422,6 +449,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -455,9 +485,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -494,12 +521,17 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr ""
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "All"
msgstr ""
@@ -515,6 +547,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -524,6 +559,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -539,6 +580,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -560,7 +604,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -584,6 +628,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -596,6 +646,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -608,6 +661,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -635,6 +691,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -677,12 +736,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr ""
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -701,7 +766,7 @@ msgstr ""
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -719,9 +784,15 @@ msgstr ""
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -740,6 +811,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -878,6 +952,9 @@ msgstr ""
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -914,9 +991,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -995,6 +1069,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1285,6 +1368,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1315,9 +1401,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1372,7 +1455,7 @@ msgstr ""
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1399,6 +1482,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1429,6 +1518,9 @@ msgstr ""
msgid "CiStatusLabel|created"
msgstr ""
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr ""
@@ -1447,6 +1539,9 @@ msgstr ""
msgid "CiStatusLabel|skipped"
msgstr ""
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr ""
@@ -1459,6 +1554,9 @@ msgstr ""
msgid "CiStatusText|created"
msgstr ""
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr ""
@@ -1513,10 +1611,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1561,6 +1659,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1573,12 +1674,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1609,10 +1722,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1639,6 +1752,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1675,6 +1794,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1705,9 +1827,6 @@ msgstr ""
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1729,25 +1848,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster details"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster health"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1759,7 +1872,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1768,16 +1881,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1795,9 +1905,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1825,6 +1932,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1837,6 +1947,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1867,9 +1980,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1909,13 +2019,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -1933,6 +2040,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -1951,9 +2061,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -1963,6 +2070,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -1972,12 +2082,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2012,6 +2128,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr ""
@@ -2084,7 +2203,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2093,10 +2212,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2186,6 +2305,9 @@ msgstr ""
msgid "Contribution guide"
msgstr ""
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2219,6 +2341,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2240,15 +2374,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2324,7 +2470,7 @@ msgstr ""
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
+msgid "Create your first page"
msgstr ""
msgid "CreateTag|Tag"
@@ -2375,6 +2521,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -2393,6 +2542,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr ""
@@ -2444,6 +2596,9 @@ msgstr ""
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2456,6 +2611,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr ""
@@ -2465,6 +2635,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2602,6 +2775,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2626,6 +2805,12 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2647,12 +2832,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2668,6 +2868,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2749,7 +2952,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2794,9 +2997,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2809,6 +3009,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2911,7 +3117,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -2944,10 +3150,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3058,6 +3264,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3112,6 +3324,12 @@ msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3121,6 +3339,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3130,6 +3351,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3139,6 +3435,9 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr ""
@@ -3151,9 +3450,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr ""
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr ""
@@ -3169,6 +3477,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3181,7 +3492,7 @@ msgstr ""
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3220,17 +3531,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -3246,6 +3558,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3288,6 +3603,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3462,10 +3780,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3474,6 +3804,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3495,7 +3828,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3507,6 +3840,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3516,19 +3852,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3546,6 +3888,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3558,9 +3906,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3570,9 +3936,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3639,12 +4002,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr ""
-
-msgid "GoToYourFork|Fork"
-msgstr ""
-
msgid "Google Code import"
msgstr ""
@@ -3675,9 +4032,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3687,6 +4056,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3705,13 +4077,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3738,9 +4110,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3798,6 +4167,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3810,19 +4182,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -3864,6 +4236,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4028,6 +4403,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4096,6 +4474,12 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4120,6 +4504,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4135,9 +4549,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4174,7 +4585,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4192,12 +4603,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4270,6 +4675,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
@@ -4281,12 +4689,18 @@ msgstr ""
msgid "Last commit"
msgstr ""
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4335,6 +4749,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4344,6 +4767,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4353,6 +4779,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4362,6 +4791,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4374,9 +4806,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4403,6 +4841,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4448,6 +4889,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4517,13 +4961,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4535,6 +5009,12 @@ msgstr ""
msgid "Median"
msgstr ""
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -4568,6 +5048,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4577,9 +5072,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4589,6 +5081,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4604,6 +5102,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4820,6 +5321,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -4939,6 +5443,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -4948,9 +5458,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -4960,6 +5467,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -4987,6 +5497,9 @@ msgstr ""
msgid "No repository"
msgstr ""
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr ""
@@ -5023,6 +5536,9 @@ msgstr ""
msgid "Not enough data"
msgstr ""
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -5041,6 +5557,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -5113,9 +5641,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5142,9 +5667,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5166,6 +5688,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5190,6 +5715,21 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5256,6 +5796,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5283,13 +5826,13 @@ msgstr ""
msgid "Permissions"
msgstr ""
-msgid "Personal Access Token"
+msgid "Permissions, LFS, 2FA"
msgstr ""
-msgid "Pipeline"
+msgid "Personal Access Token"
msgstr ""
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
+msgid "Pipeline"
msgstr ""
msgid "Pipeline Health"
@@ -5409,15 +5952,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5427,6 +5979,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5454,12 +6012,6 @@ msgstr ""
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5469,12 +6021,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5487,6 +6045,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5499,9 +6060,18 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5547,15 +6117,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5568,39 +6153,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -5610,6 +6276,15 @@ msgstr ""
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5646,6 +6321,9 @@ msgstr ""
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr ""
@@ -5673,6 +6351,9 @@ msgstr ""
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -5700,6 +6381,27 @@ msgstr ""
msgid "ProjectLifecycle|Stage"
msgstr ""
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5742,6 +6444,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5811,9 +6516,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6006,6 +6708,12 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6068,12 +6776,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6083,6 +6800,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6092,18 +6812,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6116,6 +6851,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6149,10 +6887,10 @@ msgstr ""
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6170,9 +6908,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6223,9 +6973,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6235,6 +7000,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6259,6 +7030,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6283,6 +7057,9 @@ msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -6337,15 +7114,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6370,27 +7156,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard"
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6408,9 +7222,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr ""
@@ -6441,6 +7261,9 @@ msgstr ""
msgid "Select target branch"
msgstr ""
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6453,6 +7276,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6477,6 +7303,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6495,7 +7324,10 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
@@ -6507,13 +7339,31 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "Settings"
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
msgstr ""
msgid "Share"
@@ -6525,6 +7375,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6608,12 +7461,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6641,9 +7500,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6656,12 +7521,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -6692,6 +7569,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6722,6 +7602,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6752,6 +7635,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6827,9 +7713,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6842,6 +7740,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6851,6 +7752,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6860,9 +7764,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6875,6 +7785,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -6893,6 +7809,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -6997,6 +7916,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7045,12 +7967,6 @@ msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7099,9 +8015,6 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr ""
@@ -7111,21 +8024,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr ""
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7135,6 +8042,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7144,7 +8054,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7192,10 +8108,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7216,6 +8135,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7255,7 +8177,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7276,6 +8201,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
@@ -7300,6 +8228,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7309,6 +8240,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7336,9 +8273,15 @@ msgstr ""
msgid "Time before an issue starts implementation"
msgstr ""
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr ""
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7529,12 +8472,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7550,6 +8505,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7562,12 +8520,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7577,9 +8538,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7595,6 +8562,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7610,6 +8580,9 @@ msgstr ""
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7619,6 +8592,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7637,24 +8613,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7670,6 +8664,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7703,13 +8703,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7739,15 +8742,15 @@ msgstr ""
msgid "Upload file"
msgstr ""
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr ""
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7775,6 +8778,9 @@ msgstr ""
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7784,10 +8790,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7814,6 +8862,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7847,9 +8904,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7868,6 +8931,36 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -7907,6 +9000,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8057,6 +9156,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8075,9 +9177,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8087,9 +9186,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8111,12 +9207,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8138,9 +9240,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr ""
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8150,6 +9249,12 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr ""
@@ -8216,6 +9321,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8237,16 +9345,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "assign yourself"
msgstr ""
@@ -8274,61 +9372,78 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8361,9 +9476,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8386,6 +9498,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8404,13 +9519,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8419,9 +9528,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8452,9 +9558,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8466,9 +9569,6 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8498,25 +9598,17 @@ msgstr[1] ""
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
-
msgid "disabled"
msgstr ""
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "enabled"
msgstr ""
@@ -8526,6 +9618,12 @@ msgstr ""
msgid "for this project"
msgstr ""
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -8555,6 +9653,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8783,6 +9884,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8801,6 +9905,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr ""
@@ -8829,6 +9936,11 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "remaining"
msgstr ""
@@ -8841,6 +9953,11 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "source"
msgstr ""
@@ -8856,6 +9973,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/he_IL/gitlab.po b/locale/he_IL/gitlab.po
index 4eeac683e67..a7e4fdd134e 100644
--- a/locale/he_IL/gitlab.po
+++ b/locale/he_IL/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Hebrew\n"
"Language: he_IL\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: he\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:31\n"
+"PO-Revision-Date: 2018-11-19 17:22\n"
msgid " Status"
msgstr ""
@@ -35,6 +35,16 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -56,6 +66,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -119,13 +136,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] ""
@@ -136,12 +146,21 @@ msgstr[3] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] ""
@@ -149,6 +168,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -158,6 +184,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -173,25 +202,12 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr ""
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr ""
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -205,35 +221,13 @@ msgstr ""
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -382,6 +376,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr ""
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -424,13 +427,10 @@ msgstr ""
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
+msgid "Access expiration date"
msgstr ""
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr ""
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -460,27 +460,48 @@ msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
+msgid "Add Kubernetes cluster"
msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -490,6 +511,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -523,9 +547,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -562,12 +583,19 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr ""
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "All"
msgstr ""
@@ -583,6 +611,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -592,6 +623,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -607,6 +644,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -628,7 +668,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -652,6 +692,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -664,6 +710,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -676,6 +725,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -703,6 +755,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -745,12 +800,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr ""
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -769,7 +830,7 @@ msgstr ""
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -787,9 +848,15 @@ msgstr ""
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -808,6 +875,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -946,6 +1016,9 @@ msgstr ""
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -982,9 +1055,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -1063,6 +1133,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1355,6 +1434,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1385,9 +1467,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1442,7 +1521,7 @@ msgstr ""
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1469,6 +1548,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1499,6 +1584,9 @@ msgstr ""
msgid "CiStatusLabel|created"
msgstr ""
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr ""
@@ -1517,6 +1605,9 @@ msgstr ""
msgid "CiStatusLabel|skipped"
msgstr ""
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr ""
@@ -1529,6 +1620,9 @@ msgstr ""
msgid "CiStatusText|created"
msgstr ""
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr ""
@@ -1583,10 +1677,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1631,6 +1725,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1643,12 +1740,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1679,10 +1788,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1709,6 +1818,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1745,6 +1860,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1775,9 +1893,6 @@ msgstr ""
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1799,25 +1914,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster details"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster health"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1829,7 +1938,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1838,16 +1947,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1865,9 +1971,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1895,6 +1998,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1907,6 +2013,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1937,9 +2046,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1979,13 +2085,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -2003,6 +2106,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2021,9 +2127,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -2033,6 +2136,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -2042,12 +2148,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2086,6 +2198,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr ""
@@ -2158,7 +2273,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2167,10 +2282,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2260,6 +2375,9 @@ msgstr ""
msgid "Contribution guide"
msgstr ""
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2293,6 +2411,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2314,15 +2444,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2398,7 +2540,7 @@ msgstr ""
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
+msgid "Create your first page"
msgstr ""
msgid "CreateTag|Tag"
@@ -2449,6 +2591,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -2467,6 +2612,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr ""
@@ -2518,6 +2666,9 @@ msgstr ""
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2530,6 +2681,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr ""
@@ -2539,6 +2705,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2678,6 +2847,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2702,6 +2877,12 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2723,12 +2904,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2744,6 +2940,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2825,7 +3024,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2870,9 +3069,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2885,6 +3081,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2987,7 +3189,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -3020,10 +3222,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3134,6 +3336,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3188,6 +3396,12 @@ msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3197,6 +3411,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3206,6 +3423,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3215,6 +3507,9 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr ""
@@ -3227,9 +3522,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr ""
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr ""
@@ -3245,6 +3549,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3257,7 +3564,7 @@ msgstr ""
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3296,19 +3603,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -3324,6 +3630,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3366,6 +3675,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3540,10 +3852,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3552,6 +3876,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3573,7 +3900,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3585,6 +3912,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3594,19 +3924,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3624,6 +3960,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3636,9 +3978,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3648,9 +4008,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3717,12 +4074,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr ""
-
-msgid "GoToYourFork|Fork"
-msgstr ""
-
msgid "Google Code import"
msgstr ""
@@ -3753,9 +4104,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3765,6 +4128,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3783,13 +4149,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3816,9 +4182,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3876,6 +4239,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3888,19 +4254,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -3942,6 +4308,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4108,6 +4477,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4178,6 +4550,12 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4202,6 +4580,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4217,9 +4625,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4256,7 +4661,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4274,12 +4679,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4352,6 +4751,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
@@ -4365,12 +4767,18 @@ msgstr ""
msgid "Last commit"
msgstr ""
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4419,6 +4827,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4428,6 +4845,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4437,6 +4857,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4446,6 +4869,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4458,9 +4884,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4489,6 +4921,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4534,6 +4969,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4603,13 +5041,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4621,6 +5089,12 @@ msgstr ""
msgid "Median"
msgstr ""
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -4654,6 +5128,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4663,9 +5152,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4675,6 +5161,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4690,6 +5182,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4906,6 +5401,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -5027,6 +5525,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -5036,9 +5540,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -5048,6 +5549,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5075,6 +5579,9 @@ msgstr ""
msgid "No repository"
msgstr ""
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr ""
@@ -5111,6 +5618,9 @@ msgstr ""
msgid "Not enough data"
msgstr ""
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -5129,6 +5639,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -5201,9 +5723,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5232,9 +5751,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5256,6 +5772,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5280,6 +5799,21 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5346,6 +5880,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5373,13 +5910,13 @@ msgstr ""
msgid "Permissions"
msgstr ""
-msgid "Personal Access Token"
+msgid "Permissions, LFS, 2FA"
msgstr ""
-msgid "Pipeline"
+msgid "Personal Access Token"
msgstr ""
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
+msgid "Pipeline"
msgstr ""
msgid "Pipeline Health"
@@ -5499,15 +6036,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5517,6 +6063,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5544,12 +6096,6 @@ msgstr ""
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5559,12 +6105,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5577,6 +6129,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5589,9 +6144,18 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5637,15 +6201,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5658,39 +6237,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -5700,6 +6360,15 @@ msgstr ""
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5736,6 +6405,9 @@ msgstr ""
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr ""
@@ -5763,6 +6435,9 @@ msgstr ""
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -5790,6 +6465,27 @@ msgstr ""
msgid "ProjectLifecycle|Stage"
msgstr ""
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5832,6 +6528,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5901,9 +6600,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6096,6 +6792,12 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6160,12 +6862,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6175,6 +6886,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6184,18 +6898,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6208,6 +6937,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6241,10 +6973,10 @@ msgstr ""
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6262,9 +6994,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6317,9 +7061,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6329,6 +7088,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6353,6 +7118,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6377,6 +7145,9 @@ msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -6431,15 +7202,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6464,29 +7244,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard"
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6504,9 +7310,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr ""
@@ -6537,6 +7349,9 @@ msgstr ""
msgid "Select target branch"
msgstr ""
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6549,6 +7364,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6573,6 +7391,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6591,7 +7412,10 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
@@ -6603,13 +7427,31 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "Settings"
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
msgstr ""
msgid "Share"
@@ -6621,6 +7463,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6706,12 +7551,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6739,9 +7590,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6754,12 +7611,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -6790,6 +7659,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6820,6 +7692,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6850,6 +7725,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6925,9 +7803,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6940,6 +7830,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6949,6 +7842,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6958,9 +7854,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6973,6 +7875,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -6991,6 +7899,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -7097,6 +8008,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7145,12 +8059,6 @@ msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7199,9 +8107,6 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr ""
@@ -7211,21 +8116,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr ""
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7235,6 +8134,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7244,7 +8146,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7292,10 +8200,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7316,6 +8227,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7355,7 +8269,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7376,6 +8293,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
@@ -7400,6 +8320,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7409,6 +8332,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7436,9 +8365,15 @@ msgstr ""
msgid "Time before an issue starts implementation"
msgstr ""
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr ""
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7633,12 +8568,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7654,6 +8601,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7666,12 +8616,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7681,9 +8634,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7699,6 +8658,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7714,6 +8676,9 @@ msgstr ""
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7723,6 +8688,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7741,24 +8709,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7774,6 +8760,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7807,13 +8799,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7843,15 +8838,15 @@ msgstr ""
msgid "Upload file"
msgstr ""
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr ""
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7879,6 +8874,9 @@ msgstr ""
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7888,10 +8886,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7918,6 +8958,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7951,9 +9000,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7972,6 +9027,36 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -8011,6 +9096,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8161,6 +9252,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8179,9 +9273,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8191,9 +9282,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8215,12 +9303,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8242,9 +9336,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr ""
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8254,6 +9345,12 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr ""
@@ -8320,6 +9417,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8341,20 +9441,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "assign yourself"
msgstr ""
@@ -8382,61 +9468,86 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8469,9 +9580,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8498,6 +9606,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8516,13 +9627,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8531,9 +9636,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8564,9 +9666,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8580,9 +9679,6 @@ msgstr[3] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8614,36 +9710,32 @@ msgstr[3] ""
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "disabled"
+msgstr ""
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "detected no vulnerabilities"
-msgstr ""
-
-msgid "disabled"
+msgid "enabled"
msgstr ""
-msgid "done"
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
-msgid "enabled"
+msgid "for this project"
msgstr ""
-msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgid "from"
msgstr ""
-msgid "for this project"
+msgid "help"
msgstr ""
msgid "here"
@@ -8677,6 +9769,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8911,6 +10006,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8929,6 +10027,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr ""
@@ -8961,6 +10062,13 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "remaining"
msgstr ""
@@ -8973,6 +10081,13 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "source"
msgstr ""
@@ -8988,6 +10103,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/hu_HU/gitlab.po b/locale/hu_HU/gitlab.po
new file mode 100644
index 00000000000..02eaff28e83
--- /dev/null
+++ b/locale/hu_HU/gitlab.po
@@ -0,0 +1,9995 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
+"Language-Team: Hungarian\n"
+"Language: hu_HU\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: hu\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"PO-Revision-Date: 2018-11-19 17:20\n"
+
+msgid " Status"
+msgstr ""
+
+msgid " and"
+msgstr ""
+
+msgid " degraded on %d point"
+msgid_plural " degraded on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " improved on %d point"
+msgid_plural " improved on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d changed file"
+msgid_plural "%d changed files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d failed test result"
+msgid_plural "%d failed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d staged change"
+msgid_plural "%d staged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unstaged change"
+msgid_plural "%d unstaged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_timeago}"
+msgstr ""
+
+msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgstr ""
+
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{loadingIcon} Started"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+msgid "%{nip_domain} can be used as an alternative to a custom domain."
+msgstr ""
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr ""
+
+msgid "%{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
+
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid "- Runner is active and can process any new jobs"
+msgstr ""
+
+msgid "- Runner is paused and will not receive any new jobs"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "1 %{type} addition"
+msgid_plural "%{count} %{type} additions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 %{type} modification"
+msgid_plural "%{count} %{type} modifications"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed issue"
+msgid_plural "%d closed issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed merge request"
+msgid_plural "%d closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merged merge request"
+msgid_plural "%d merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open merge request"
+msgid_plural "%d open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 user"
+msgid_plural "%d users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "2FA enabled"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get the permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
+msgstr ""
+
+msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
+msgstr ""
+
+msgid "<strong>%{group_name}</strong> group members"
+msgstr ""
+
+msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
+msgstr ""
+
+msgid "<strong>Removes</strong> source branch"
+msgstr ""
+
+msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
+msgstr ""
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
+msgstr ""
+
+msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About GitLab CE"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Accepted MR"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied! Please verify you can add deploy keys to this repository."
+msgstr ""
+
+msgid "Access expiration date"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add Changelog"
+msgstr ""
+
+msgid "Add Contribution guide"
+msgstr ""
+
+msgid "Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add Readme"
+msgstr ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add projects"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add todo"
+msgstr ""
+
+msgid "Add user(s) to the group:"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Admin Area"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "Admin area"
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminProjects|Delete project"
+msgstr ""
+
+msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
+
+msgid "Advanced settings"
+msgstr ""
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "All"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr ""
+
+msgid "All users"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch."
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts"
+msgstr ""
+
+msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
+msgstr ""
+
+msgid "Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An error accured whilst committing your changes."
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error occured creating the new branch."
+msgstr ""
+
+msgid "An error occured whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occured whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occured whilst loading all the files."
+msgstr ""
+
+msgid "An error occured whilst loading the file content."
+msgstr ""
+
+msgid "An error occured whilst loading the file."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request."
+msgstr ""
+
+msgid "An error occured whilst loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
+msgstr ""
+
+msgid "An error occurred while adding approver"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while fetching markdown preview"
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching sidebar data"
+msgstr ""
+
+msgid "An error occurred while fetching stages."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the pipeline."
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while importing project: %{details}"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while removing approver"
+msgstr ""
+
+msgid "An error occurred while rendering KaTeX"
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while retrieving calendar activity"
+msgstr ""
+
+msgid "An error occurred while retrieving diff"
+msgstr ""
+
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
+msgstr ""
+
+msgid "An error occurred while subscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while unsubscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any Label"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read-only"
+msgstr ""
+
+msgid "Archived projects"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Artifact ID"
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer to set up a group Runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned Merge Requests"
+msgstr ""
+
+msgid "Assigned to :name"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assignee"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee lists show all issues assigned to the selected user."
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto DevOps, runners and job artifacts"
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
+msgstr ""
+
+msgid "Auto-cancel redundant, pending pipelines"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
+msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
+msgstr ""
+
+msgid "AutoDevOps|add a Kubernetes cluster"
+msgstr ""
+
+msgid "AutoDevOps|enable Auto DevOps"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available group Runners : %{runners}"
+msgstr ""
+
+msgid "Available group Runners : %{runners}."
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|A new badge was added."
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Delete badge"
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|No badge image"
+msgstr ""
+
+msgid "Badges|No image to preview"
+msgstr ""
+
+msgid "Badges|Please fill in a valid URL"
+msgstr ""
+
+msgid "Badges|Project Badge"
+msgstr ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|The badge was saved."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "Badges|e.g. %{exampleUrl}"
+msgstr ""
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are examples of regex for existing tools:"
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
+msgstr ""
+
+msgid "BillingPlans|Current plan"
+msgstr ""
+
+msgid "BillingPlans|Customer Support"
+msgstr ""
+
+msgid "BillingPlans|Downgrade"
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
+msgstr ""
+
+msgid "BillingPlans|Manage plan"
+msgstr ""
+
+msgid "BillingPlans|Please contact %{customer_support_link} in that case."
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Upgrade"
+msgstr ""
+
+msgid "BillingPlans|You are currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
+msgstr ""
+
+msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
+msgstr ""
+
+msgid "BillingPlans|features"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|paid annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch (%{branch_count})"
+msgid_plural "Branches (%{branch_count})"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch has changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "BranchSwitcherPlaceholder|Search branches"
+msgstr ""
+
+msgid "BranchSwitcherTitle|Switch branch"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cant find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch '%{branch_name}'?"
+msgstr ""
+
+msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+msgstr ""
+
+msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Branches|Only a project maintainer or owner can delete a protected branch"
+msgstr ""
+
+msgid "Branches|Overview"
+msgstr ""
+
+msgid "Branches|Protected branches can be managed in %{project_settings_link}."
+msgstr ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Sort by"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+msgstr ""
+
+msgid "Branches|The default branch cannot be deleted"
+msgstr ""
+
+msgid "Branches|This branch hasn’t been merged into %{default_branch}."
+msgstr ""
+
+msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
+msgid "Branches|To confirm, type %{branch_name_confirmation}:"
+msgstr ""
+
+msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
+msgstr ""
+
+msgid "Branches|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|project settings"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "Built-In"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CI / CD"
+msgstr ""
+
+msgid "CI / CD Settings"
+msgstr ""
+
+msgid "CI will run using the credentials assigned above."
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD for external repo"
+msgstr ""
+
+msgid "CI/CD settings"
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Deployment strategy needs a domain name to work correctly."
+msgstr ""
+
+msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|Learn more about Auto DevOps"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "Callback URL"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Certificate fingerprint"
+msgstr ""
+
+msgid "Change Weight"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates."
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "Changelog"
+msgstr ""
+
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
+msgstr ""
+
+msgid "Choose <strong>Next</strong> at the bottom of the page."
+msgstr ""
+
+msgid "Choose File ..."
+msgstr ""
+
+msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
+msgstr ""
+
+msgid "Choose file..."
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose which groups you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose which repositories you want to import."
+msgstr ""
+
+msgid "Choose which shards you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Error occured while saving variables"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "CiVariable|Validation failed"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
+msgstr ""
+
+msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
+msgstr ""
+
+msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
+msgstr ""
+
+msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
+msgstr ""
+
+msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Client authentication certificate"
+msgstr ""
+
+msgid "Client authentication key"
+msgstr ""
+
+msgid "Client authentication key password"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
+msgstr ""
+
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgstr ""
+
+msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|Applications"
+msgstr ""
+
+msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Token"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Helm Tiller"
+msgstr ""
+
+msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
+msgstr ""
+
+msgid "ClusterIntegration|Hide"
+msgstr ""
+
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|In order to show the health of the cluster, we'll need to provision your cluster with Prometheus to collect the required data."
+msgstr ""
+
+msgid "ClusterIntegration|Ingress"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress IP Address"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
+msgstr ""
+
+msgid "ClusterIntegration|Install"
+msgstr ""
+
+msgid "ClusterIntegration|Install Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Installed"
+msgstr ""
+
+msgid "ClusterIntegration|Installing"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
+msgstr ""
+
+msgid "ClusterIntegration|Integration status"
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster health"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
+msgstr ""
+
+msgid "ClusterIntegration|More information"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Note:"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Service token"
+msgstr ""
+
+msgid "ClusterIntegration|Show"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Token"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|check the pricing here"
+msgstr ""
+
+msgid "ClusterIntegration|documentation"
+msgstr ""
+
+msgid "ClusterIntegration|help page"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|properly configured"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "Code owners"
+msgstr ""
+
+msgid "Cohorts"
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & resolve discussion"
+msgstr ""
+
+msgid "Comment & unresolve discussion"
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit (%{commit_count})"
+msgid_plural "Commits (%{commit_count})"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit duration in minutes for last 30 commits"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|Commit: %{commitText}"
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Commit…"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|Compare"
+msgstr ""
+
+msgid "CompareBranches|Source"
+msgstr ""
+
+msgid "CompareBranches|Target"
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Tracing"
+msgstr ""
+
+msgid "Configure automatic git checks and housekeeping on repositories."
+msgstr ""
+
+msgid "Configure limits for web and API requests."
+msgstr ""
+
+msgid "Configure push mirrors."
+msgstr ""
+
+msgid "Configure storage path settings."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the way a user creates a new account."
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Created"
+msgstr ""
+
+msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
+msgstr ""
+
+msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
+msgstr ""
+
+msgid "ContainerRegistry|How to use the Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Learn more about"
+msgstr ""
+
+msgid "ContainerRegistry|No tags in Container Registry for this container image."
+msgstr ""
+
+msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgstr ""
+
+msgid "ContainerRegistry|Size"
+msgstr ""
+
+msgid "ContainerRegistry|Tag"
+msgstr ""
+
+msgid "ContainerRegistry|Tag ID"
+msgstr ""
+
+msgid "ContainerRegistry|Use different image names"
+msgstr ""
+
+msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
+msgstr ""
+
+msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution guide"
+msgstr ""
+
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "ContributorsPage|%{startDate} – %{endDate}"
+msgstr ""
+
+msgid "ContributorsPage|Building repository graph."
+msgstr ""
+
+msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Control the display of third party offers."
+msgstr ""
+
+msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of repository backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of verification operations for this Geo node"
+msgstr ""
+
+msgid "ConvDev Index"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key to clipboard"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy branch name to clipboard"
+msgstr ""
+
+msgid "Copy command to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Copy file path to clipboard"
+msgstr ""
+
+msgid "Copy incoming email address to clipboard"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
+msgid "Copy reference to clipboard"
+msgstr ""
+
+msgid "Copy secret to clipboard"
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token to clipboard"
+msgstr ""
+
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new branch and merge request"
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create branch"
+msgstr ""
+
+msgid "Create commit"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty repository"
+msgstr ""
+
+msgid "Create epic"
+msgstr ""
+
+msgid "Create file"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created on"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron syntax"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current node"
+msgstr ""
+
+msgid "CurrentUser|Profile"
+msgstr ""
+
+msgid "CurrentUser|Settings"
+msgstr ""
+
+msgid "Custom"
+msgstr ""
+
+msgid "Custom CI config path"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Production"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Default Branch"
+msgstr ""
+
+msgid "Default classification label"
+msgstr ""
+
+msgid "Default: Directly import the Google Code email address or username"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete Package"
+msgstr ""
+
+msgid "Delete Snippet"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete list"
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployKeys|Write access allowed"
+msgstr ""
+
+msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Add a deploy token"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository"
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Copy username to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Deploy Tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|This project has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "DeployTokens|Use this username as a login."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|You are about to revoke"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group Runners"
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "Discard review"
+msgstr ""
+
+msgid "Discover GitLab Geo."
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss Cycle Analytics introduction box"
+msgstr ""
+
+msgid "Dismiss Merge Request promotion"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Each Runner can be in one of the following states:"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Elasticsearch"
+msgstr ""
+
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable SAML authentication for this group"
+msgstr ""
+
+msgid "Enable Sentry for error reporting and logging."
+msgstr ""
+
+msgid "Enable and configure InfluxDB metrics."
+msgstr ""
+
+msgid "Enable and configure Prometheus metrics."
+msgstr ""
+
+msgid "Enable classification control using an external service"
+msgstr ""
+
+msgid "Enable for this project"
+msgstr ""
+
+msgid "Enable group Runners"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable reCAPTCHA or Akismet and set IP limits."
+msgstr ""
+
+msgid "Enable the Performance Bar for a given group."
+msgstr ""
+
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter the issue description"
+msgstr ""
+
+msgid "Enter the issue title"
+msgstr ""
+
+msgid "Enter the merge request description"
+msgstr ""
+
+msgid "Enter the merge request title"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No pod name has been specified"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod logs from"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Read more about environments"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epic will be removed! Are you sure?"
+msgstr ""
+
+msgid "Epics"
+msgstr ""
+
+msgid "Epics Roadmap"
+msgstr ""
+
+msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
+msgstr ""
+
+msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgstr ""
+
+msgid "Epics|How can I solve this?"
+msgstr ""
+
+msgid "Epics|More information"
+msgstr ""
+
+msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+msgstr ""
+
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr ""
+
+msgid "Epics|due"
+msgstr ""
+
+msgid "Epics|start"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Reporting and Logging"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error fetching contributors data."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching usage ping data."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error updating status for all todos."
+msgstr ""
+
+msgid "Error updating todo status."
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "Every day (at 4:00am)"
+msgstr ""
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr ""
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
+msgid "Explore"
+msgstr ""
+
+msgid "Explore GitLab"
+msgstr ""
+
+msgid "Explore Groups"
+msgstr ""
+
+msgid "Explore groups"
+msgstr ""
+
+msgid "Explore projects"
+msgstr ""
+
+msgid "Explore public groups"
+msgstr ""
+
+msgid "External Classification Policy Authorization"
+msgstr ""
+
+msgid "External authentication"
+msgstr ""
+
+msgid "External authorization denied access to this project"
+msgstr ""
+
+msgid "External authorization request timeout"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification Label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to remove issue from board, please try again."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to update issues, please try again."
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fields on this page are now uneditable, you can configure"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Files (%{human_size})"
+msgstr ""
+
+msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
+msgid "Filter by commit message"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Find the downloaded ZIP file and decompress it."
+msgstr ""
+
+msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish review"
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "FirstPushedBy|First"
+msgstr ""
+
+msgid "FirstPushedBy|pushed by"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Follow the steps below to export your Google Code project data."
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Format"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
+msgid "From %{provider_title}"
+msgstr ""
+
+msgid "From Bitbucket"
+msgstr ""
+
+msgid "From Bitbucket Server"
+msgstr ""
+
+msgid "From FogBugz"
+msgstr ""
+
+msgid "From GitLab.com"
+msgstr ""
+
+msgid "From Google Code"
+msgstr ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "From milestones:"
+msgstr ""
+
+msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Nodes"
+msgstr ""
+
+msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is failing or broken."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
+msgstr ""
+
+msgid "GeoNodes|Checksummed"
+msgstr ""
+
+msgid "GeoNodes|Data is out of date from %{timeago}"
+msgstr ""
+
+msgid "GeoNodes|Data replication lag"
+msgstr ""
+
+msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "GeoNodes|Failed"
+msgstr ""
+
+msgid "GeoNodes|Full"
+msgstr ""
+
+msgid "GeoNodes|GitLab version"
+msgstr ""
+
+msgid "GeoNodes|GitLab version does not match the primary node version"
+msgstr ""
+
+msgid "GeoNodes|Health status"
+msgstr ""
+
+msgid "GeoNodes|Last event ID processed by cursor"
+msgstr ""
+
+msgid "GeoNodes|Last event ID seen from primary"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository verification"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki verification"
+msgstr ""
+
+msgid "GeoNodes|Loading nodes"
+msgstr ""
+
+msgid "GeoNodes|Local LFS objects"
+msgstr ""
+
+msgid "GeoNodes|Local attachments"
+msgstr ""
+
+msgid "GeoNodes|Local job artifacts"
+msgstr ""
+
+msgid "GeoNodes|New node"
+msgstr ""
+
+msgid "GeoNodes|Node Authentication was successfully repaired."
+msgstr ""
+
+msgid "GeoNodes|Node was successfully removed."
+msgstr ""
+
+msgid "GeoNodes|Not checksummed"
+msgstr ""
+
+msgid "GeoNodes|Out of sync"
+msgstr ""
+
+msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Replication slot WAL"
+msgstr ""
+
+msgid "GeoNodes|Replication slots"
+msgstr ""
+
+msgid "GeoNodes|Repositories"
+msgstr ""
+
+msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Repositories verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Repository verification progress"
+msgstr ""
+
+msgid "GeoNodes|Selective"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while changing node status"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while fetching nodes"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while removing node"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while repairing node"
+msgstr ""
+
+msgid "GeoNodes|Storage config"
+msgstr ""
+
+msgid "GeoNodes|Sync settings"
+msgstr ""
+
+msgid "GeoNodes|Synced"
+msgstr ""
+
+msgid "GeoNodes|Unused slots"
+msgstr ""
+
+msgid "GeoNodes|Unverified"
+msgstr ""
+
+msgid "GeoNodes|Used slots"
+msgstr ""
+
+msgid "GeoNodes|Verified"
+msgstr ""
+
+msgid "GeoNodes|Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Wiki verification progress"
+msgstr ""
+
+msgid "GeoNodes|Wikis"
+msgstr ""
+
+msgid "GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for forced re-download"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-check"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|All"
+msgstr ""
+
+msgid "Geo|All projects"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|File sync capacity"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Groups to synchronize"
+msgstr ""
+
+msgid "Geo|In sync"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|Not synced yet"
+msgstr ""
+
+msgid "Geo|Pending"
+msgstr ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Recheck"
+msgstr ""
+
+msgid "Geo|Recheck all projects"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Repository sync capacity"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all projects"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Select groups to replicate."
+msgstr ""
+
+msgid "Geo|Shards to synchronize"
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
+msgid "Geo|Unknown state"
+msgstr ""
+
+msgid "Geo|Verification capacity"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|You need a different license to use Geo replication"
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Git"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git strategy for pipelines"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitLab CI Linter has been moved"
+msgstr ""
+
+msgid "GitLab Geo"
+msgstr ""
+
+msgid "GitLab Group Runners can execute code for all the projects in this group."
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab single sign on URL"
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLab’s issue tracker"
+msgstr ""
+
+msgid "Gitaly"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go to"
+msgstr ""
+
+msgid "Go to %{link_to_google_takeout}."
+msgstr ""
+
+msgid "Google Code import"
+msgstr ""
+
+msgid "Google Takeout"
+msgstr ""
+
+msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group CI/CD settings"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group Runners"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group details"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group maintainers can register group runners in the %{link}"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Loading roadmap"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|Until %{dateWord}"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Customize your group badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about badges."
+msgstr ""
+
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+msgstr ""
+
+msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
+msgstr ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Create a project in this group."
+msgstr ""
+
+msgid "GroupsTree|Create a subgroup in this group."
+msgstr ""
+
+msgid "GroupsTree|Edit group"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave this group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Have your users email"
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help page"
+msgstr ""
+
+msgid "Help page text and support page url."
+msgstr ""
+
+msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide whitespace changes"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Client side evaluation"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Open in file view"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "Identity provider single sign on URL"
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr ""
+
+msgid "If disabled, the access level will depend on the user's permissions in the project."
+msgstr ""
+
+msgid "If enabled"
+msgstr ""
+
+msgid "If enabled, access to projects will be validated on an external service using their classification label."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you already have files you can push them using the %{link_to_cli} below."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import all compatible projects"
+msgstr ""
+
+msgid "Import all projects"
+msgstr ""
+
+msgid "Import all repositories"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import projects from Google Code"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "Improve Issue boards with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
+msgid "In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "Incompatible Project"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input your repository URL"
+msgstr ""
+
+msgid "Install GitLab Runner"
+msgstr ""
+
+msgid "Install Runner on Kubernetes"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Instance Statistics"
+msgstr ""
+
+msgid "Instance Statistics visibility"
+msgstr ""
+
+msgid "Instance does not support multiple Kubernetes clusters"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations Settings"
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Cycle Analytics"
+msgstr ""
+
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue board focus mode"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Job"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed in"
+msgstr ""
+
+msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration was not removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes configured"
+msgstr ""
+
+msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label lists show all issues with the selected label."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{name}"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
+msgstr ""
+
+msgid "Learn more about Kubernetes"
+msgstr ""
+
+msgid "Learn more about protected branches"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
+msgid "LicenseManagement|Approve license"
+msgstr ""
+
+msgid "LicenseManagement|Approve license?"
+msgstr ""
+
+msgid "LicenseManagement|Approved"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license?"
+msgstr ""
+
+msgid "LicenseManagement|Blacklisted"
+msgstr ""
+
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
+msgid "LicenseManagement|License"
+msgstr ""
+
+msgid "LicenseManagement|License Management"
+msgstr ""
+
+msgid "LicenseManagement|License details"
+msgstr ""
+
+msgid "LicenseManagement|License name"
+msgstr ""
+
+msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
+msgstr ""
+
+msgid "LicenseManagement|Packages"
+msgstr ""
+
+msgid "LicenseManagement|Remove license"
+msgstr ""
+
+msgid "LicenseManagement|Remove license?"
+msgstr ""
+
+msgid "LicenseManagement|Submit"
+msgstr ""
+
+msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
+msgstr ""
+
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseManagement|URL"
+msgstr ""
+
+msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LinkedIn"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "List Your Gitea Repositories"
+msgstr ""
+
+msgid "List available repositories"
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "List your GitHub repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked to current projects"
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make sure you're logged into the account that owns the projects you'd like to import."
+msgstr ""
+
+msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
+msgstr ""
+
+msgid "Manage Web IDE features"
+msgstr ""
+
+msgid "Manage access"
+msgstr ""
+
+msgid "Manage all notifications"
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a full email address"
+msgstr ""
+
+msgid "Map a Google Code user to a full name"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark todo as done"
+msgstr ""
+
+msgid "Markdown enabled"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
+msgid "Maven Metadata"
+msgstr ""
+
+msgid "Maven package"
+msgstr ""
+
+msgid "Max access level"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Median"
+msgstr ""
+
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Request:"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge requests"
+msgstr ""
+
+msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
+msgid "MergeRequests|Resolve this discussion in a new issue"
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|Toggle comments for this file"
+msgstr ""
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr ""
+
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Influx"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics|Business"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgstr ""
+
+msgid "Metrics|Environment"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgstr ""
+
+msgid "Metrics|Learn about environments"
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|Name"
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|No deployed environments"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|Query"
+msgstr ""
+
+msgid "Metrics|Response"
+msgstr ""
+
+msgid "Metrics|System"
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|Type"
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
+msgid "Milestone"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Mirror a repository"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror user"
+msgstr ""
+
+msgid "Mirrored repositories"
+msgstr ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
+msgid "Modal|Cancel"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More actions"
+msgstr ""
+
+msgid "More info"
+msgstr ""
+
+msgid "More information"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Multiple issue boards"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name your individual key via a title"
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Snippets"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No Label"
+msgstr ""
+
+msgid "No assignee"
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No container images stored for this project. Add one by following the instructions above."
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No issues for the selected time period."
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No merge requests for the selected time period."
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No packages stored for this project."
+msgstr ""
+
+msgid "No prioritised labels with such name or description"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No pushes for the selected time period."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No, directly import the existing email addresses and usernames."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "Not all comments are displayed because you're comparing two versions of the diff."
+msgstr ""
+
+msgid "Not all comments are displayed because you're viewing an old version of the diff."
+msgstr ""
+
+msgid "Not allowed to merge"
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not enough data"
+msgstr ""
+
+msgid "Not now"
+msgstr ""
+
+msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "Only admins"
+msgstr ""
+
+msgid "Only comments from the following commit are shown below"
+msgstr ""
+
+msgid "Only mirror protected branches"
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open in Xcode"
+msgstr ""
+
+msgid "Open projects"
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open source software to collaborate on code"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened MR"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Otherwise it is recommended you start with one of the options below."
+msgstr ""
+
+msgid "Outbound requests"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Package information"
+msgstr ""
+
+msgid "Package was removed"
+msgstr ""
+
+msgid "Packages"
+msgstr ""
+
+msgid "Pages"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
+
+msgid "Path, transfer, remove"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Paused Runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "Per job. If a job passes this threshold, it will be marked as failed"
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, or removing the group."
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline Health"
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline quota"
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines for last month"
+msgstr ""
+
+msgid "Pipelines for last week"
+msgstr ""
+
+msgid "Pipelines for last year"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|CI Lint"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgstr ""
+
+msgid "Pipelines|Get started with Pipelines"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|There are currently no %{scope} pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+msgstr ""
+
+msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Create for"
+msgstr ""
+
+msgid "Pipeline|Create pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Existing branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Search branches"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|all"
+msgstr ""
+
+msgid "Pipeline|success"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Please accept the Terms of Service before continuing."
+msgstr ""
+
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please solve the reCAPTCHA"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences|Navigation theme"
+msgstr ""
+
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Private - Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|Add status emoji"
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
+msgid "Profiles|Clear status"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Delete Account"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Delete your account?"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Website"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project avatar in repository: %{link}"
+msgstr ""
+
+msgid "Project details"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectLifecycle|Stage"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Customize your project badges."
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Learn more about badges."
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
+msgstr ""
+
+msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "PrometheusAlerts|Add alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Edit alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error creating alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error deleting alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error fetching alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error saving alert"
+msgstr ""
+
+msgid "PrometheusAlerts|No alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Operator"
+msgstr ""
+
+msgid "PrometheusAlerts|Threshold"
+msgstr ""
+
+msgid "PrometheusDashboard|Time"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration"
+msgstr ""
+
+msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
+msgstr ""
+
+msgid "PrometheusService|Common metrics"
+msgstr ""
+
+msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
+msgstr ""
+
+msgid "PrometheusService|Custom metrics"
+msgstr ""
+
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr ""
+
+msgid "PrometheusService|Finding custom metrics..."
+msgstr ""
+
+msgid "PrometheusService|Install Prometheus on clusters"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+msgstr ""
+
+msgid "PrometheusService|More information"
+msgstr ""
+
+msgid "PrometheusService|New metric"
+msgstr ""
+
+msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|Time-series monitoring service"
+msgstr ""
+
+msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
+msgstr ""
+
+msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
+msgstr ""
+
+msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote these project milestones into a group milestone."
+msgstr ""
+
+msgid "Promote to Group Milestone"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Environments"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "Protip:"
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Pseudonymizer data collection"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRule|Committer restriction"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
+
+msgid "Readme"
+msgstr ""
+
+msgid "Real-time features"
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Reference:"
+msgstr ""
+
+msgid "Refresh"
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Regenerate key"
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register and see your runners for this group."
+msgstr ""
+
+msgid "Register and see your runners for this project."
+msgstr ""
+
+msgid "Registry"
+msgstr ""
+
+msgid "Related Commits"
+msgstr ""
+
+msgid "Related Deployed Jobs"
+msgstr ""
+
+msgid "Related Issues"
+msgstr ""
+
+msgid "Related Jobs"
+msgstr ""
+
+msgid "Related Merge Requests"
+msgstr ""
+
+msgid "Related Merged Requests"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove Runner"
+msgstr ""
+
+msgid "Remove avatar"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
+msgid "Rename"
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Repair authentication"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{failedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|Class"
+msgstr ""
+
+msgid "Reports|Confidence"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository URL"
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirror"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Requests Profiles"
+msgstr ""
+
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
+msgid "Resolve all discussions in new issue"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve discussion"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal Variables"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
+msgid "Runner token"
+msgstr ""
+
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners API"
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, and even on your local machine."
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|You have used all your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML Single Sign On"
+msgstr ""
+
+msgid "SAML Single Sign On Settings"
+msgstr ""
+
+msgid "SAST"
+msgstr ""
+
+msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save variables"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scoped issue boards"
+msgstr ""
+
+msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or jump to…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in this group"
+msgstr ""
+
+msgid "SearchAutocomplete|in this project"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr ""
+
+msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgstr ""
+
+msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select a group to invite"
+msgstr ""
+
+msgid "Select a namespace to fork the project"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select an existing Kubernetes cluster or create a new one"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select branch/tag"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project and zone to choose machine type"
+msgstr ""
+
+msgid "Select project to choose zone"
+msgstr ""
+
+msgid "Select projects you want to import."
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Select the custom project template source group."
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Selective synchronization"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send usage data"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
+msgstr ""
+
+msgid "Session expiration, projects limit and attachment size."
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set instance-wide template repository"
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Sherlock Transactions"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show latest version of the diff"
+msgstr ""
+
+msgid "Show parent pages"
+msgstr ""
+
+msgid "Show parent subgroups"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|Change weight"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in to %{group_name}"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong when toggling the button"
+msgstr ""
+
+msgid "Something went wrong while closing the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while fetching %{listType} list"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the projects."
+msgstr ""
+
+msgid "Something went wrong while fetching the registry list."
+msgstr ""
+
+msgid "Something went wrong while reopening the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Sorry, no epics matched your search"
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "SortOptions|Access level, ascending"
+msgstr ""
+
+msgid "SortOptions|Access level, descending"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Milestone"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest joined"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source code"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Specific Runners"
+msgstr ""
+
+msgid "Specify an e-mail address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage & Commit"
+msgstr ""
+
+msgid "Stage all changes"
+msgstr ""
+
+msgid "Stage changes"
+msgstr ""
+
+msgid "Staged"
+msgstr ""
+
+msgid "Staged %{type}"
+msgstr ""
+
+msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start the Runner!"
+msgstr ""
+
+msgid "Start your trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Stop environment"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Sync information"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System header and footer:"
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "Tag (%{tag_count})"
+msgid_plural "Tags (%{tag_count})"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release notes"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag."
+msgstr ""
+
+msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Sort by"
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Test SAML SSO"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+msgid "Thanks! Don't show me this again"
+msgstr ""
+
+msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
+msgstr ""
+
+msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr ""
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The deployment of this job to %{environmentLink} did not succeed."
+msgstr ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr ""
+
+msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
+msgstr ""
+
+msgid "The phase of the development lifecycle."
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr ""
+
+msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
+msgstr ""
+
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr ""
+
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
+msgstr ""
+
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The tabs below will be removed in a future version"
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no merge requests to show"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
+
+msgid "There was an error adding a todo."
+msgstr ""
+
+msgid "There was an error deleting the todo."
+msgstr ""
+
+msgid "There was an error loading users activity calendar."
+msgstr ""
+
+msgid "There was an error saving your notification settings."
+msgstr ""
+
+msgid "There was an error subscribing to this label."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "They can be managed using the %{link}."
+msgstr ""
+
+msgid "Third party offers"
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
+msgstr ""
+
+msgid "This application was created by %{link_to_owner}."
+msgstr ""
+
+msgid "This application will be able to:"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This branch has changed since you started editing. Would you like to create a new branch?"
+msgstr ""
+
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This group"
+msgstr ""
+
+msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgstr ""
+
+msgid "This group does not provide any group Runners yet."
+msgstr ""
+
+msgid "This is a confidential issue."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is the author's first Merge Request to this project."
+msgstr ""
+
+msgid "This issue is confidential"
+msgstr ""
+
+msgid "This issue is confidential and locked."
+msgstr ""
+
+msgid "This issue is locked."
+msgstr ""
+
+msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "This job is the most recent deployment to %{link}."
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This option is disabled as you don't have write permissions for the current branch"
+msgstr ""
+
+msgid "This option is disabled while you still have unstaged changes"
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page will be removed in a future release."
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project does not belong to a group and can therefore not make use of group Runners."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "This source diff could not be displayed because it is too large."
+msgstr ""
+
+msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
+msgstr ""
+
+msgid "This will delete the custom metric, Are you sure?"
+msgstr ""
+
+msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time before enforced"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds ago"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip:"
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr ""
+
+msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
+msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr ""
+
+msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
+msgstr ""
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr ""
+
+msgid "To start serving your jobs you can add Runners to your group"
+msgstr ""
+
+msgid "To this GitLab instance"
+msgstr ""
+
+msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
+msgstr ""
+
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
+
+msgid "To widen your search, change or remove filters."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Todo"
+msgstr ""
+
+msgid "Todos"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle discussion"
+msgstr ""
+
+msgid "Toggle file browser"
+msgstr ""
+
+msgid "Toggle navigation"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: OFF"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: ON"
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Time"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track activity with Contribution Analytics."
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trigger"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Turn on Service Desk"
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to save your changes"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unresolve discussion"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
+msgid "Unstage all changes"
+msgstr ""
+
+msgid "Unstage changes"
+msgstr ""
+
+msgid "Unstaged"
+msgstr ""
+
+msgid "Unstaged %{type}"
+msgstr ""
+
+msgid "Unstaged and staged %{type}"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Upgrade your plan to activate Advanced Global Search."
+msgstr ""
+
+msgid "Upgrade your plan to activate Contribution Analytics."
+msgstr ""
+
+msgid "Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Upgrade your plan to activate Issue weight."
+msgstr ""
+
+msgid "Upgrade your plan to improve Issue boards."
+msgstr ""
+
+msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage ping is not enabled"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "Use <code>%{native_redirect_uri}</code> for local tests"
+msgstr ""
+
+msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
+msgstr ""
+
+msgid "Use group milestones to manage issues from multiple projects in the same milestone."
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use the following registration token during setup:"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "Used by members to sign in to your group in GitLab"
+msgstr ""
+
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Variables"
+msgstr ""
+
+msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification information"
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View epics list"
+msgstr ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View group labels"
+msgstr ""
+
+msgid "View issue"
+msgstr ""
+
+msgid "View it on GitLab"
+msgstr ""
+
+msgid "View jobs"
+msgstr ""
+
+msgid "View labels"
+msgstr ""
+
+msgid "View log"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr ""
+
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|It is recommended to install %{markdown} so that GFM features render locally:"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgstr ""
+
+msgid "WikiMarkdownDocs|documentation"
+msgstr ""
+
+msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgstr ""
+
+msgid "WikiNewPagePlaceholder|how-to-setup"
+msgstr ""
+
+msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiNewPageTitle|New Wiki Page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgstr ""
+
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPageConflictMessage|the page"
+msgstr ""
+
+msgid "WikiPageCreate|Create %{page_title}"
+msgstr ""
+
+msgid "WikiPageEdit|Update %{page_title}"
+msgstr ""
+
+msgid "WikiPage|Page slug"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wiki|Create Page"
+msgstr ""
+
+msgid "Wiki|Create page"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|More Pages"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, let me map Google Code users to full names or GitLab users."
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
+msgstr ""
+
+msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You can %{linkStart}view the blob%{linkEnd} instead."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
+msgid "You can only edit files when you are on a branch"
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
+msgstr ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+msgstr ""
+
+msgid "You cannot write to this read-only GitLab instance."
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You must accept our Terms of Service and privacy policy in order to register an account"
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're receiving this email because %{reason}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your Todos"
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your comment will not be visible to the public."
+msgstr ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your projects"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "among other things"
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{namespace} is affected by %{vulnerability}."
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr ""
+
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr ""
+
+msgid "ciReport|(is loading)"
+msgstr ""
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr ""
+
+msgid "ciReport|Class"
+msgstr ""
+
+msgid "ciReport|Code quality"
+msgstr ""
+
+msgid "ciReport|Confidence"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Description"
+msgstr ""
+
+msgid "ciReport|Dismiss vulnerability"
+msgstr ""
+
+msgid "ciReport|Dismissed by"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|File"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Identifiers"
+msgstr ""
+
+msgid "ciReport|Instances"
+msgstr ""
+
+msgid "ciReport|Learn more about interacting with security reports (Alpha)."
+msgstr ""
+
+msgid "ciReport|License management detected %d license for the source branch only"
+msgid_plural "ciReport|License management detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected %d new license"
+msgid_plural "ciReport|License management detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected no licenses for the source branch only"
+msgstr ""
+
+msgid "ciReport|License management detected no new licenses"
+msgstr ""
+
+msgid "ciReport|Links"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|Method"
+msgstr ""
+
+msgid "ciReport|Namespace"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No changes to performance metrics"
+msgstr ""
+
+msgid "ciReport|Performance metrics"
+msgstr ""
+
+msgid "ciReport|Revert dismissal"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Severity"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error loading DAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading SAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading container scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error loading dependency scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "ciReport|on pipeline"
+msgstr ""
+
+msgid "command line instructions"
+msgstr ""
+
+msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgstr ""
+
+msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
+msgstr ""
+
+msgid "connecting"
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "customize"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "deploy token"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "here"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "importing"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "issue boards"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "license management"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|Add approval"
+msgstr ""
+
+msgid "mrWidget|Allows commits from members who can merge to the target branch"
+msgstr ""
+
+msgid "mrWidget|An error occured while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Cancel automatic merge"
+msgstr ""
+
+msgid "mrWidget|Check out branch"
+msgstr ""
+
+msgid "mrWidget|Checking ability to merge automatically"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes"
+msgstr ""
+
+msgid "mrWidget|Create an issue to resolve them later"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mentions"
+msgstr ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge request approved"
+msgstr ""
+
+msgid "mrWidget|Merge request approved; you can approve additionally"
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|No Approval required"
+msgstr ""
+
+msgid "mrWidget|No Approval required; you can still approve"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove Source Branch"
+msgstr ""
+
+msgid "mrWidget|Remove source branch"
+msgstr ""
+
+msgid "mrWidget|Remove your approval"
+msgstr ""
+
+msgid "mrWidget|Request to merge"
+msgstr ""
+
+msgid "mrWidget|Requires 1 more approval"
+msgid_plural "mrWidget|Requires %d more approvals"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Requires 1 more approval by"
+msgid_plural "mrWidget|Requires %d more approvals by"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Set by"
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The changes will be merged into"
+msgstr ""
+
+msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+msgstr ""
+
+msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
+msgstr ""
+
+msgid "mrWidget|The source branch has been removed"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will be removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will not be removed"
+msgstr ""
+
+msgid "mrWidget|There are merge conflicts"
+msgstr ""
+
+msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|This merge request is in the process of being merged"
+msgstr ""
+
+msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr ""
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|You can remove source branch now"
+msgstr ""
+
+msgid "mrWidget|branch does not exist."
+msgstr ""
+
+msgid "mrWidget|command line"
+msgstr ""
+
+msgid "mrWidget|into"
+msgstr ""
+
+msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "notification emails"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "password"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "source"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time spent."
+msgstr ""
+
+msgid "started"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "toggle collapse"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "within %d minute "
+msgid_plural "within %d minutes "
+msgstr[0] ""
+msgstr[1] ""
+
diff --git a/locale/id_ID/gitlab.po b/locale/id_ID/gitlab.po
index e185f4f71b7..265d725424e 100644
--- a/locale/id_ID/gitlab.po
+++ b/locale/id_ID/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Indonesian\n"
"Language: id_ID\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: id\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:31\n"
+"PO-Revision-Date: 2018-11-19 17:18\n"
msgid " Status"
msgstr ""
@@ -29,6 +29,13 @@ msgid " improved on %d point"
msgid_plural " improved on %d points"
msgstr[0] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -41,6 +48,10 @@ msgid "%d commit behind"
msgid_plural "%d commits behind"
msgstr[0] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -77,10 +88,6 @@ msgid "%d unstaged change"
msgid_plural "%d unstaged changes"
msgstr[0] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] ""
@@ -88,16 +95,29 @@ msgstr[0] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] ""
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -107,6 +127,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -122,22 +145,12 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr ""
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr ""
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] ""
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -148,23 +161,13 @@ msgstr ""
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -280,6 +283,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr ""
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -322,13 +334,10 @@ msgstr ""
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
-msgstr ""
-
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgid "Access expiration date"
msgstr ""
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -358,27 +367,48 @@ msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
+msgid "Add Kubernetes cluster"
msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -388,6 +418,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -421,9 +454,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -460,12 +490,16 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr ""
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+
msgid "All"
msgstr ""
@@ -481,6 +515,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -490,6 +527,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -505,6 +548,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -526,7 +572,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -550,6 +596,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -562,6 +614,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -574,6 +629,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -601,6 +659,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -643,12 +704,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr ""
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -667,7 +734,7 @@ msgstr ""
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -685,9 +752,15 @@ msgstr ""
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -706,6 +779,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -844,6 +920,9 @@ msgstr ""
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -880,9 +959,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -961,6 +1037,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1250,6 +1335,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1280,9 +1368,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1337,7 +1422,7 @@ msgstr ""
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1364,6 +1449,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1394,6 +1485,9 @@ msgstr ""
msgid "CiStatusLabel|created"
msgstr ""
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr ""
@@ -1412,6 +1506,9 @@ msgstr ""
msgid "CiStatusLabel|skipped"
msgstr ""
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr ""
@@ -1424,6 +1521,9 @@ msgstr ""
msgid "CiStatusText|created"
msgstr ""
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr ""
@@ -1478,10 +1578,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1526,6 +1626,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1538,12 +1641,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1574,10 +1689,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1604,6 +1719,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1640,6 +1761,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1670,9 +1794,6 @@ msgstr ""
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1694,25 +1815,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster details"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster health"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1724,7 +1839,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1733,16 +1848,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1760,9 +1872,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1790,6 +1899,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1802,6 +1914,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1832,9 +1947,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1874,13 +1986,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -1898,6 +2007,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -1916,9 +2028,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -1928,6 +2037,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -1937,12 +2049,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -1975,6 +2093,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr ""
@@ -2047,7 +2168,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2056,10 +2177,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2149,6 +2270,9 @@ msgstr ""
msgid "Contribution guide"
msgstr ""
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2182,6 +2306,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2203,15 +2339,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2287,7 +2435,7 @@ msgstr ""
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
+msgid "Create your first page"
msgstr ""
msgid "CreateTag|Tag"
@@ -2338,6 +2486,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -2356,6 +2507,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr ""
@@ -2407,6 +2561,9 @@ msgstr ""
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2419,6 +2576,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr ""
@@ -2428,6 +2600,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2564,6 +2739,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2588,6 +2769,12 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2609,12 +2796,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2630,6 +2832,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2711,7 +2916,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2756,9 +2961,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2771,6 +2973,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2873,7 +3081,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -2906,10 +3114,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3020,6 +3228,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3074,6 +3288,12 @@ msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3083,6 +3303,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3092,6 +3315,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3101,6 +3399,9 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr ""
@@ -3113,9 +3414,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr ""
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr ""
@@ -3131,6 +3441,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3143,7 +3456,7 @@ msgstr ""
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3182,16 +3495,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] ""
-
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -3207,6 +3522,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3249,6 +3567,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3423,10 +3744,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3435,6 +3768,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3456,7 +3792,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3468,6 +3804,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3477,19 +3816,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3507,6 +3852,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3519,9 +3870,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3531,9 +3900,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3600,12 +3966,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr ""
-
-msgid "GoToYourFork|Fork"
-msgstr ""
-
msgid "Google Code import"
msgstr ""
@@ -3636,9 +3996,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3648,6 +4020,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3666,13 +4041,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3699,9 +4074,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3759,6 +4131,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3771,19 +4146,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -3825,6 +4200,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -3988,6 +4366,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4055,6 +4436,12 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4079,6 +4466,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4094,9 +4511,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4133,7 +4547,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4151,12 +4565,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4229,6 +4637,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
@@ -4239,12 +4650,18 @@ msgstr ""
msgid "Last commit"
msgstr ""
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4293,6 +4710,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4302,6 +4728,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4311,6 +4740,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4320,6 +4752,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4332,9 +4767,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4360,6 +4801,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4405,6 +4849,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4474,13 +4921,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4492,6 +4969,12 @@ msgstr ""
msgid "Median"
msgstr ""
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -4525,6 +5008,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4534,9 +5032,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4546,6 +5041,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4561,6 +5062,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4777,6 +5281,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -4895,6 +5402,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -4904,9 +5417,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -4916,6 +5426,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -4943,6 +5456,9 @@ msgstr ""
msgid "No repository"
msgstr ""
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr ""
@@ -4979,6 +5495,9 @@ msgstr ""
msgid "Not enough data"
msgstr ""
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -4997,6 +5516,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -5069,9 +5600,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5097,9 +5625,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5121,6 +5646,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5145,6 +5673,21 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5211,6 +5754,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5238,13 +5784,13 @@ msgstr ""
msgid "Permissions"
msgstr ""
-msgid "Personal Access Token"
+msgid "Permissions, LFS, 2FA"
msgstr ""
-msgid "Pipeline"
+msgid "Personal Access Token"
msgstr ""
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
+msgid "Pipeline"
msgstr ""
msgid "Pipeline Health"
@@ -5364,15 +5910,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5382,6 +5937,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5409,12 +5970,6 @@ msgstr ""
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5424,12 +5979,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5442,6 +6003,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5454,9 +6018,18 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5502,15 +6075,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5523,39 +6111,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -5565,6 +6234,15 @@ msgstr ""
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5601,6 +6279,9 @@ msgstr ""
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr ""
@@ -5628,6 +6309,9 @@ msgstr ""
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -5655,6 +6339,27 @@ msgstr ""
msgid "ProjectLifecycle|Stage"
msgstr ""
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5697,6 +6402,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5766,9 +6474,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -5961,6 +6666,12 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6022,12 +6733,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6037,6 +6757,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6046,18 +6769,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6070,6 +6808,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6103,10 +6844,10 @@ msgstr ""
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6124,9 +6865,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6176,9 +6929,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6188,6 +6956,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6212,6 +6986,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6236,6 +7013,9 @@ msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -6290,15 +7070,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6323,26 +7112,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
+msgstr ""
+
+msgid "Security"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security Dashboard"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6360,9 +7178,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr ""
@@ -6393,6 +7217,9 @@ msgstr ""
msgid "Select target branch"
msgstr ""
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6405,6 +7232,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6429,6 +7259,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6447,7 +7280,10 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
@@ -6459,13 +7295,31 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "Settings"
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
msgstr ""
msgid "Share"
@@ -6477,6 +7331,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6559,12 +7416,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6592,9 +7455,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6607,12 +7476,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -6643,6 +7524,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6673,6 +7557,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6703,6 +7590,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6778,9 +7668,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6793,6 +7695,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6802,6 +7707,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6811,9 +7719,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6826,6 +7740,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -6844,6 +7764,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -6947,6 +7870,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -6995,12 +7921,6 @@ msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7049,9 +7969,6 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr ""
@@ -7061,21 +7978,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr ""
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7085,6 +7996,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7094,7 +8008,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7142,10 +8062,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7166,6 +8089,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7205,7 +8131,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7226,6 +8155,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
@@ -7250,6 +8182,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7259,6 +8194,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7286,9 +8227,15 @@ msgstr ""
msgid "Time before an issue starts implementation"
msgstr ""
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr ""
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7477,12 +8424,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7498,6 +8457,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7510,12 +8472,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7525,9 +8490,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7543,6 +8514,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7558,6 +8532,9 @@ msgstr ""
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7567,6 +8544,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7585,24 +8565,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7618,6 +8616,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7651,13 +8655,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7687,15 +8694,15 @@ msgstr ""
msgid "Upload file"
msgstr ""
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr ""
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7723,6 +8730,9 @@ msgstr ""
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7732,10 +8742,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
msgstr ""
-msgid "User|Current status"
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7762,6 +8814,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7795,9 +8856,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7816,6 +8883,36 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -7855,6 +8952,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8005,6 +9108,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8023,9 +9129,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8035,9 +9138,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8059,12 +9159,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8086,9 +9192,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr ""
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8098,6 +9201,12 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr ""
@@ -8164,6 +9273,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8185,14 +9297,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-
msgid "assign yourself"
msgstr ""
@@ -8220,61 +9324,74 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8307,9 +9424,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8330,6 +9444,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8348,13 +9465,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8363,9 +9474,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8396,9 +9504,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8409,9 +9514,6 @@ msgstr[0] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8440,23 +9542,16 @@ msgstr[0] ""
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
-
msgid "disabled"
msgstr ""
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+
msgid "enabled"
msgstr ""
@@ -8466,6 +9561,12 @@ msgstr ""
msgid "for this project"
msgstr ""
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -8494,6 +9595,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8719,6 +9823,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8737,6 +9844,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr ""
@@ -8763,6 +9873,10 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+
msgid "remaining"
msgstr ""
@@ -8775,6 +9889,10 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+
msgid "source"
msgstr ""
@@ -8790,6 +9908,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index a4e20f4fe65..ab967c458d2 100644
--- a/locale/it/gitlab.po
+++ b/locale/it/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Italian\n"
"Language: it_IT\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: it\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:31\n"
+"PO-Revision-Date: 2018-11-19 17:20\n"
msgid " Status"
msgstr ""
@@ -31,6 +31,14 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -46,6 +54,11 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -91,11 +104,6 @@ msgid_plural "%d unstaged changes"
msgstr[0] ""
msgstr[1] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] "%s commit aggiuntivo è stato omesso per evitare degradi di prestazioni negli issues."
@@ -104,17 +112,31 @@ msgstr[1] "%s commit aggiuntivi sono stati omessi per evitare degradi di prestaz
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} fatto %{commit_timeago}"
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] "%{count} partecipante"
msgstr[1] "%{count} partecipanti"
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -124,6 +146,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -139,23 +164,12 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{number_commits_behind} commits precedenti %{default_branch}, %{number_commits_ahead} commits avanti"
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr "%{number_of_failures} di %{maximum_failures} fallimenti. GitLab consentirà l'accesso al prossimo tentativo."
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr "%{number_of_failures} di %{maximum_failures} fallimenti. Gitlab non ritenterà automaticamente. Ripristina l'informazioni d'archiviazione quando il problema è risolto."
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] "%{storage_name}: tentativo d'accesso all'archiviazione fallito da parte dell'host:"
-msgstr[1] "%{storage_name}: %{failed_attempts} tentativi d'accesso all'archiviazione falliti:"
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -167,27 +181,13 @@ msgstr "%{text} è disponibile"
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -314,6 +314,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr "Un insieme di grafici riguardo la Continuous Integration"
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -356,13 +365,10 @@ msgstr "Token di accesso"
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
+msgid "Access expiration date"
msgstr ""
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr "L'accesso agli storages è stato temporaneamente disabilitato per consentire il mount di ripristino. Resetta le info d'archiviazione dopo che l'issue è stato risolto per consentire nuovamente l'accesso."
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -392,27 +398,48 @@ msgstr "Aggiungi Guida per contribuire"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
-msgstr "Aggiungi Licenza"
+msgid "Add Kubernetes cluster"
+msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr "Aggiungi una directory (cartella)"
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -422,6 +449,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -455,9 +485,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr "Pagina di stato"
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -494,12 +521,17 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr "Impostazioni Avanzate"
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "All"
msgstr "Tutto"
@@ -515,6 +547,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -524,6 +559,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -539,6 +580,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -560,7 +604,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -584,6 +628,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -596,6 +646,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -608,6 +661,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Errore durante il recupero dei dati della barra laterale"
@@ -635,6 +691,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -677,12 +736,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr "Si è verificato un errore. Riprova."
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -701,7 +766,7 @@ msgstr "Aspetto"
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -719,9 +784,15 @@ msgstr "Aprile"
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Sei sicuro di voler cancellare questa pipeline programmata?"
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -740,6 +811,9 @@ msgstr "Sei sicuro di voler ripristinare il token di registrazione?"
msgid "Are you sure you want to reset the health check token?"
msgstr "Confermi di voler resettare il token di controllo di stato?"
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -878,6 +952,9 @@ msgstr "Farà automaticamente le build, i test e i rilasci della tua applicazion
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "Approfondisci: %{link_to_documentation}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -914,9 +991,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -995,6 +1069,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1285,6 +1368,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1315,9 +1401,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1372,7 +1455,7 @@ msgstr "Grafici"
msgid "Chat"
msgstr "Chat"
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1399,6 +1482,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1429,6 +1518,9 @@ msgstr "cancellato"
msgid "CiStatusLabel|created"
msgstr "creato"
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr "fallito"
@@ -1447,6 +1539,9 @@ msgstr "in coda"
msgid "CiStatusLabel|skipped"
msgstr "saltata"
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr "in attesa di azione manuale"
@@ -1459,6 +1554,9 @@ msgstr "cancellata"
msgid "CiStatusText|created"
msgstr "creata"
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr "fallita"
@@ -1513,12 +1611,12 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
-msgstr "api circuitbreaker"
-
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear search"
+msgstr ""
+
msgid "Clear search input"
msgstr ""
@@ -1561,6 +1659,9 @@ msgstr "Clona repository"
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1573,12 +1674,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr "API URL"
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1609,10 +1722,10 @@ msgstr "Certificato CA"
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "Certificate Authority bundle (formato PEM)"
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1639,6 +1752,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1675,6 +1794,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
@@ -1705,9 +1827,6 @@ msgstr "Installa"
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr "Installato"
@@ -1729,25 +1848,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster details"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster health"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1759,7 +1872,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1768,16 +1881,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1795,9 +1905,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1825,6 +1932,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1837,6 +1947,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1867,9 +1980,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1909,13 +2019,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -1933,6 +2040,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -1951,9 +2061,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -1963,6 +2070,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -1972,12 +2082,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr "Commenti"
@@ -2012,6 +2128,9 @@ msgstr "Commit"
msgid "CommitMessage|Add %{file_name}"
msgstr "Aggiungi %{file_name}"
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr "Commits"
@@ -2084,7 +2203,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2093,10 +2212,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2186,6 +2305,9 @@ msgstr ""
msgid "Contribution guide"
msgstr "Guida per contribuire"
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2219,6 +2341,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2240,15 +2374,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2324,8 +2470,8 @@ msgstr "Crea nuovo..."
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
-msgstr "Fork"
+msgid "Create your first page"
+msgstr ""
msgid "CreateTag|Tag"
msgstr "Tag"
@@ -2375,6 +2521,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr "Eventi-Notifica personalizzati"
@@ -2393,6 +2542,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr "Statistiche Cicliche"
@@ -2444,6 +2596,9 @@ msgstr "Dicembre"
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2456,6 +2611,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Definisci un patter personalizzato mediante la sintassi cron"
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr "Elimina"
@@ -2465,6 +2635,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2602,6 +2775,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2626,6 +2805,12 @@ msgstr "Dettagli"
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2647,12 +2832,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2668,6 +2868,9 @@ msgstr "Chiudi l'introduzione alle Analisi Cicliche"
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2749,7 +2952,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2794,9 +2997,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2809,6 +3009,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2911,8 +3117,8 @@ msgstr ""
msgid "Environments|Updated"
msgstr "Aggiornato"
-msgid "Environments|You don't have any environments right now."
-msgstr "Attualmente non hai alcun ambiente."
+msgid "Environments|You don't have any environments right now"
+msgstr ""
msgid "Environments|protected"
msgstr ""
@@ -2944,10 +3150,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3058,6 +3264,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3112,6 +3324,12 @@ msgstr "Impossibile cambiare owner"
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3121,6 +3339,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "Impossibile rimuovere la pipeline pianificata"
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3130,6 +3351,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr "Feb"
@@ -3139,6 +3435,9 @@ msgstr "Febbraio"
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr "Files"
@@ -3151,9 +3450,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr "Filtra per messaggio di commit"
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr "Trova in percorso"
@@ -3169,6 +3477,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3181,7 +3492,7 @@ msgstr "Push di"
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3220,17 +3531,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] "Fork"
-msgstr[1] "Forks"
-
msgid "ForkedFromProjectPath|Forked from"
msgstr "Fork da"
@@ -3246,6 +3558,9 @@ msgstr "Formato"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3288,6 +3603,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3462,10 +3780,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3474,6 +3804,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3495,7 +3828,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3507,6 +3840,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3516,19 +3852,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3546,6 +3888,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3558,9 +3906,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3570,9 +3936,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr "Le informazioni sullo stato dell'archiviazione Git è stata ripristinata"
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3639,12 +4002,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr "Vai il tuo fork"
-
-msgid "GoToYourFork|Fork"
-msgstr "Fork"
-
msgid "Google Code import"
msgstr ""
@@ -3675,9 +4032,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3687,6 +4056,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3705,13 +4077,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3738,9 +4110,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Blocca la condivisione di un progetto di %{group} con altri gruppi"
-msgid "GroupSettings|Share with group lock"
-msgstr "Condividi con il gruppo chiuso"
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "Questa modifica è stata applicata su %{ancestor_group} ed è stata ignorata nel sottogruppo."
@@ -3798,6 +4167,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3810,19 +4182,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -3864,6 +4236,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4028,6 +4403,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4096,6 +4474,12 @@ msgstr "Intervallo di Pattern"
msgid "Introducing Cycle Analytics"
msgstr "Introduzione delle Analisi Cicliche"
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4120,6 +4504,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr "Gen"
@@ -4135,9 +4549,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4174,7 +4585,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4192,12 +4603,6 @@ msgstr "Giu"
msgid "June"
msgstr "Giugno"
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4270,6 +4675,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] "L'ultimo %d giorno"
@@ -4281,12 +4689,18 @@ msgstr "Ultima Pipeline"
msgid "Last commit"
msgstr "Ultimo Commit"
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr "Ultima modifica %{date}"
msgid "Last edited by %{name}"
msgstr "Modificato da %{name}"
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr "Ultimo aggiornamento"
@@ -4335,6 +4749,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4344,6 +4767,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4353,6 +4779,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4362,6 +4791,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4374,9 +4806,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4403,6 +4841,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4448,6 +4889,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4517,13 +4961,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4535,6 +5009,12 @@ msgstr ""
msgid "Median"
msgstr "Mediano"
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr "Membri"
@@ -4568,6 +5048,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4577,9 +5072,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4589,6 +5081,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4604,6 +5102,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4820,6 +5321,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -4939,6 +5443,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -4948,9 +5458,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -4960,6 +5467,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -4987,6 +5497,9 @@ msgstr ""
msgid "No repository"
msgstr "Nessuna Repository"
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr "Nessuna pianificazione"
@@ -5023,6 +5536,9 @@ msgstr ""
msgid "Not enough data"
msgstr "Dati insufficienti "
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -5041,6 +5557,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr "Notifica eventi"
@@ -5113,9 +5641,6 @@ msgstr "Nov"
msgid "November"
msgstr "Novembre"
-msgid "Number of access attempts"
-msgstr "Numero di tentativi di accesso raggiunto"
-
msgid "OK"
msgstr ""
@@ -5142,9 +5667,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5166,6 +5688,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5190,6 +5715,21 @@ msgstr "Si apre in una nuova finestra"
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5256,6 +5796,9 @@ msgstr "Password"
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5283,15 +5826,15 @@ msgstr ""
msgid "Permissions"
msgstr ""
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
msgid "Personal Access Token"
msgstr ""
msgid "Pipeline"
msgstr "Pipeline"
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
-msgstr ""
-
msgid "Pipeline Health"
msgstr "Stato della Pipeline"
@@ -5409,15 +5952,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5427,6 +5979,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5454,12 +6012,6 @@ msgstr "con più stadi"
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5469,12 +6021,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5487,6 +6045,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5499,9 +6060,18 @@ msgstr "Preferenze"
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5547,15 +6117,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr "Elimina account"
@@ -5568,39 +6153,120 @@ msgstr "Eliminare il tuo account?"
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr "Password non valida"
msgid "Profiles|Invalid username"
msgstr "Username non valido"
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Inserisci il tuo %{confirmationValue} per confermare:"
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr "Non hai i permessi per eliminare questo utente."
@@ -5610,6 +6276,15 @@ msgstr "Devi trasferire la proprietà o eliminare questi gruppi prima che tu pos
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "Il tuo account è attualmente proprietario in questi gruppi:"
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5646,6 +6321,9 @@ msgstr "Il Progetto '%{project_name}' è stato aggiornato con successo."
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr "L'accesso al progetto dev'esser fornito esplicitamente ad ogni utente"
@@ -5673,6 +6351,9 @@ msgstr "Esportazione del progetto iniziata. Un link di download sarà inviato vi
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "Iscriviti"
@@ -5700,6 +6381,27 @@ msgstr "Mai"
msgid "ProjectLifecycle|Stage"
msgstr "Stadio"
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5742,6 +6444,9 @@ msgstr "Progetti"
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr "Visitati di frequente"
@@ -5811,9 +6516,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr "Di default, Prometheus è in ascolto su ‘http://localhost:9090‘. Non è consigliabile cambiare l'indirizzo e la porta di default in quanto ciò potrebbe influenzare o causare conflitto con altri servizi in esecuzione sul server GitLab."
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6006,6 +6708,12 @@ msgstr "Leggimi"
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6068,12 +6776,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr "Rimuovi progetto"
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6083,6 +6800,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6092,18 +6812,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6116,6 +6851,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6149,10 +6887,10 @@ msgstr "Richiedi accesso"
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6170,9 +6908,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6223,9 +6973,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6235,6 +7000,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6259,6 +7030,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6283,6 +7057,9 @@ msgstr ""
msgid "Save changes"
msgstr "Salva modifiche"
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Salva pianificazione pipeline"
@@ -6337,15 +7114,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6370,27 +7156,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard"
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6408,9 +7222,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr "Seleziona formato d'archivio"
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr "Seleziona una timezone"
@@ -6441,6 +7261,9 @@ msgstr ""
msgid "Select target branch"
msgstr "Seleziona una branch di destinazione"
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6453,6 +7276,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr "Set"
@@ -6477,6 +7303,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Establezca una contraseña en su cuenta para actualizar o enviar a través de %{protocol}."
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6495,8 +7324,11 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr "Configura Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
@@ -6507,15 +7339,33 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "imposta una password"
-msgid "Settings"
-msgstr "Impostazioni"
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
msgstr ""
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr "Impostazioni"
+
msgid "Share"
msgstr ""
@@ -6525,6 +7375,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6608,12 +7461,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr "Snippet"
@@ -6641,9 +7500,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr "Qualcosa è andato storto durante il fetch dei progetti."
@@ -6656,12 +7521,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr "Ordina per"
@@ -6692,6 +7569,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6722,6 +7602,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6752,6 +7635,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6827,9 +7713,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr "inizia una %{new_merge_request} con queste modifiche"
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6842,6 +7740,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6851,6 +7752,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6860,9 +7764,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6875,6 +7785,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Cambia branch/tag"
@@ -6893,6 +7809,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -6997,6 +7916,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7045,12 +7967,6 @@ msgstr "Lo stadio di Issue mostra il tempo che impiega un issue ad esser correla
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7099,9 +8015,6 @@ msgstr "Lo stadio di revisione mostra il tempo tra una richiesta di merge al suo
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "Lo stadio di pre-rilascio mostra il tempo che trascorre da una MR (Richiesta di Merge) completata al suo rilascio in ambiente di produzione. Questa informazione sarà disponibile dal tuo primo rilascio in produzione"
@@ -7111,21 +8024,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr "Lo stadio di test mostra il tempo che ogni Pipeline impiega per essere eseguita in ogni Richiesta di Merge correlata. L'informazione sarà disponibile automaticamente quando la tua prima Pipeline avrà finito d'esser eseguita."
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr "Il tempo aggregato relativo eventi/data entry raccolto in quello stadio."
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7135,6 +8042,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "Il valore falsato nel mezzo di una serie di dati osservati. ES: tra 3,5,9 il mediano è 5. Tra 3,5,7,8 il mediano è (5+7)/2 quindi 6."
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7144,7 +8054,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7192,10 +8108,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7216,6 +8135,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7255,7 +8177,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7276,6 +8201,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Questo significa che non è possibile effettuare push di codice fino a che non crei una repository vuota o ne importi una esistente"
@@ -7300,6 +8228,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7309,6 +8240,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7336,9 +8273,15 @@ msgstr "Il tempo che impiega un issue per esser pianificato"
msgid "Time before an issue starts implementation"
msgstr "Il tempo che impiega un issue per esser implementato"
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr "Il tempo tra la creazione di una richiesta di merge ed il merge/close"
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7529,12 +8472,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7550,6 +8505,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7562,12 +8520,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7577,9 +8538,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7595,6 +8562,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7610,6 +8580,9 @@ msgstr "Tempo totale di test per tutti i commits/merges"
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7619,6 +8592,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7637,24 +8613,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7670,6 +8664,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7703,13 +8703,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7739,15 +8742,15 @@ msgstr "Carica un nuovo file"
msgid "Upload file"
msgstr "Carica file"
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr "clicca per caricare"
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7775,6 +8778,9 @@ msgstr "Usa le tue impostazioni globali "
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7784,10 +8790,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7814,6 +8862,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7847,9 +8904,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7868,6 +8931,36 @@ msgstr "Pubblico"
msgid "VisibilityLevel|Unknown"
msgstr "Sconosciuto"
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Vuoi visualizzare i dati? Richiedi l'accesso ad un amministratore, grazie."
@@ -7907,6 +9000,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8057,6 +9156,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8075,9 +9177,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8087,9 +9186,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8111,12 +9207,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8138,9 +9240,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr "Devi accedere per porre una star al progetto"
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8150,6 +9249,12 @@ msgstr ""
msgid "You need permission."
msgstr "Necessiti del permesso."
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr "Non riceverai alcuna notifica via email"
@@ -8216,6 +9321,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8237,16 +9345,6 @@ msgstr "fa"
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "assign yourself"
msgstr ""
@@ -8274,61 +9372,78 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8361,9 +9476,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8386,6 +9498,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8404,13 +9519,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8419,9 +9528,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8452,9 +9558,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8466,9 +9569,6 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8498,25 +9598,17 @@ msgstr[1] "giorni"
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
-
msgid "disabled"
msgstr ""
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "enabled"
msgstr ""
@@ -8526,6 +9618,12 @@ msgstr ""
msgid "for this project"
msgstr ""
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -8555,6 +9653,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8783,6 +9884,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8801,6 +9905,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr "Nuova richiesta di merge"
@@ -8829,6 +9936,11 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "remaining"
msgstr ""
@@ -8841,6 +9953,11 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "source"
msgstr ""
@@ -8856,6 +9973,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po
index f1d84529a25..26390fb862a 100644
--- a/locale/ja/gitlab.po
+++ b/locale/ja/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Japanese\n"
"Language: ja_JP\n"
"MIME-Version: 1.0\n"
@@ -13,10 +13,10 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ja\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:31\n"
+"PO-Revision-Date: 2018-11-19 17:46\n"
msgid " Status"
-msgstr ""
+msgstr " ステータス"
msgid " and"
msgstr " ã¨"
@@ -29,6 +29,13 @@ msgid " improved on %d point"
msgid_plural " improved on %d points"
msgstr[0] " %dãƒã‚¤ãƒ³ãƒˆã§æ”¹å–„"
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] "%d 個ã®å¤‰æ›´ã•ã‚ŒãŸãƒ•ã‚¡ã‚¤ãƒ«"
@@ -41,6 +48,10 @@ msgid "%d commit behind"
msgid_plural "%d commits behind"
msgstr[0] "%d個ã®ã‚³ãƒŸãƒƒãƒˆå¾…ã¡"
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d exporter"
@@ -77,10 +88,6 @@ msgid "%d unstaged change"
msgid_plural "%d unstaged changes"
msgstr[0] "%d件ã®æœªã‚¹ãƒ†ãƒ¼ã‚¸ã®å¤‰æ›´"
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] "%d ã®è„†å¼±æ€§"
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] "パフォーマンス低下をé¿ã‘ã‚‹ãŸã‚ %s 個ã®ã‚³ãƒŸãƒƒãƒˆã‚’çœç•¥ã—ã¾ã—ãŸã€‚"
@@ -88,16 +95,29 @@ msgstr[0] "パフォーマンス低下をé¿ã‘ã‚‹ãŸã‚ %s 個ã®ã‚³ãƒŸãƒƒãƒˆã‚
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} 㨠%{openOrClose} %{noteable}"
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} ㌠%{commit_timeago} ã«ã‚³ãƒŸãƒƒãƒˆã—ã¾ã—ãŸ"
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] "%{count} 人ã®å‚加者"
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+
msgid "%{filePath} deleted"
msgstr "%{filePath} ãŒå‰Šé™¤ã•ã‚Œã¾ã—ãŸ"
@@ -107,6 +127,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}グループ%{group_docs_link_end}を使用ã™ã‚‹ã¨ã€è¤‡æ•°ã®ãƒ—ロジェクトを管ç†ã—ã¦å…±åŒä½œæ¥­ã‚’è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚グループã®ãƒ¡ãƒ³ãƒãƒ¼ã¯ã€æ‰€å±žã™ã‚‹ãƒ—ロジェクトã®ã™ã¹ã¦ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚"
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} 開始"
@@ -122,25 +145,15 @@ msgstr "%{nip_domain} ã¯ã€ã‚«ã‚¹ã‚¿ãƒ ãƒ‰ãƒ¡ã‚¤ãƒ³ã®ä»£æ›¿ã¨ã—ã¦ä½¿ç”¨ã§ã
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{default_branch} ã‹ã‚‰ %{number_commits_behind} コミットé…ã‚Œã¦ã„ã¦ã€ %{number_commits_ahead} コミット進んã§ã„ã¾ã™ã€‚"
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr "%{maximum_failures}回中 %{number_of_failures}回失敗。次回アクセスå¯èƒ½ã§ã™ã€‚"
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr "%{maximum_failures}回中 %{number_of_failures}回失敗。GitLab ã¯å†è©¦è¡Œã—ã¾ã›ã‚“。å•é¡Œã‚’解決ã—ã¦ã‹ã‚‰ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸æƒ…報をリセットã—ã¦ãã ã•ã„。"
-
msgid "%{openOrClose} %{noteable}"
msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
msgstr "%{percent}%% 完了"
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] "%{storage_name}: 失敗ã—ãŸã‚¢ã‚¯ã‚»ã‚¹ã®è©¦è¡Œå›žæ•° %{failed_attempts}:"
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
-msgstr[0] ""
+msgstr[0] "%{text} %{files} ファイル"
msgid "%{text} is available"
msgstr "%{text} ãŒåˆ©ç”¨ã§ãã¾ã™ã€‚"
@@ -148,25 +161,15 @@ msgstr "%{text} ãŒåˆ©ç”¨ã§ãã¾ã™ã€‚"
msgid "%{title} changes"
msgstr "%{title} ã®å¤‰æ›´"
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] "%{type} ㌠%{vulnerabilityCount} 個ã®è„†å¼±æ€§ã‚’検出ã—ã¾ã—ãŸ"
-
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-
msgid "%{unstaged} unstaged and %{staged} staged changes"
msgstr "%{unstaged} 件ã®æœªã‚¹ãƒ†ãƒ¼ã‚¸ã®å¤‰æ›´ã¨ã€ %{staged} 件ã®ã‚¹ãƒ†ãƒ¼ã‚¸æ¸ˆã¿å¤‰æ›´"
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
msgid "+ %{moreCount} more"
msgstr "+ 他 %{moreCount} 件"
@@ -197,7 +200,7 @@ msgstr[0] "%d件ã®ã‚¯ãƒ­ãƒ¼ã‚ºã•ã‚ŒãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
msgid "1 group"
msgid_plural "%d groups"
-msgstr[0] ""
+msgstr[0] "%dグループ"
msgid "1 merged merge request"
msgid_plural "%d merged merge requests"
@@ -221,7 +224,7 @@ msgstr[0] ""
msgid "1 user"
msgid_plural "%d users"
-msgstr[0] ""
+msgstr[0] "%dユーザー"
msgid "1st contribution!"
msgstr "最åˆã®è²¢çŒ®!"
@@ -245,28 +248,28 @@ msgid "404|Please contact your GitLab administrator if you think this is a mista
msgstr "ã“ã®ãƒšãƒ¼ã‚¸ãŒæ­£ã—ããªã„å ´åˆã€GitLab 管ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> 㯠johnsmith@example.com ã«ã‚ˆã‚‹å…¨ã¦ã®èª²é¡Œã¨ã‚³ãƒ¡ãƒ³ãƒˆã« \"By <a href=\"#\">@johnsmith</a>\" を追加ã—ã¾ã™ã€‚ã¾ãŸã€ <a href=\"#\">@johnsmith</a> を元々 johnsmith@example.com ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã¦ã„ãŸå…¨ã¦ã®èª²é¡Œã®æ‹…当者ã¨ã—ã¦è¨­å®šã—ã¾ã™ã€‚"
msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"John Smith\"</code> ã¯ã€johnsmith@example.com ã«ã‚ˆã£ã¦å…ƒã€…作æˆã•ã‚ŒãŸå…¨ã¦ã®èª²é¡Œã¨ã‚³ãƒ¡ãƒ³ãƒˆã« \"By John Smith\" を追加ã—ã¾ã™ã€‚"
msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> ã¯ã€johnsmith@example.com ãŒä½œæˆã—ãŸå…¨ã¦ã®èª²é¡Œã¨ã‚³ãƒ¡ãƒ³ãƒˆã« \"By johnsm...@example.com\" を追加ã—ã¾ã™ã€‚ã“ã®ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚„ユーザーåã‚’éš ã—ã¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ—ライãƒã‚·ãƒ¼ã‚’ä¿è­·ã•ã‚Œã¾ã™ã€‚"
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> ã¯ã€johnsmith@example.com ãŒä½œæˆã—ãŸå…¨ã¦ã®èª²é¡Œã¨ã‚³ãƒ¡ãƒ³ãƒˆã« \"By <a href=\"#\">johnsmith@example.com</a>\" を追加ã—ã¾ã™ã€‚デフォルトã§ã€ãƒ¡ãƒ¼ãƒ«ã‚¢ãƒ‰ãƒ¬ã‚¹ã‚„ユーザーåã‚’éš ã—ã¦ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ãƒ—ライãƒã‚·ãƒ¼ã‚’ä¿è­·ã•ã‚Œã¾ã™ã€‚メールアドレスを全ã¦è¡¨ç¤ºã—ãŸã„å ´åˆã€ã“ã®æ–¹æ³•ã‚’指定ã—ã¦ãã ã•ã„。"
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
msgstr ""
msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
-msgstr ""
+msgstr "<strong>%{created_count}</strong> を作æˆã€<strong>%{accepted_count}</strong> 個をå—ã‘入れã¾ã—ãŸã€‚"
msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
msgstr "<strong>%{created_count}</strong>を作æˆã€<strong>%{closed_count}</strong>個をクローズã—ã¾ã—ãŸã€‚"
msgid "<strong>%{group_name}</strong> group members"
-msgstr ""
+msgstr "<strong>%{group_name}</strong> グループã®ãƒ¡ãƒ³ãƒãƒ¼"
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr "<strong>%{pushes}</strong>回ã®ãƒ—ッシュã€<strong>%{commits}</strong>回以上ã®ã‚³ãƒŸãƒƒãƒˆãŒè²¢çŒ®è€…<strong>%{people}</strong>ã«ã‚ˆã£ã¦è¡Œã‚ã‚Œã¾ã—ãŸã€‚"
@@ -275,11 +278,20 @@ msgid "<strong>Removes</strong> source branch"
msgstr "ソースブランãƒã‚’<strong>削除</strong>"
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr "「Runnerã€ã¯ã‚¸ãƒ§ãƒ–を実行ã™ã‚‹ãƒ—ロセスã§ã™ã€‚å¿…è¦ãªæ•°ã® Runner ã‚’ä»»æ„ã«ã‚»ãƒƒãƒˆã‚¢ãƒƒãƒ—ã§ãã¾ã™ã€‚"
+msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr "CIã«ã¤ã„ã¦ã®ã‚°ãƒ©ãƒ•"
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr "フォークã«æ–°ã—ã„ブランãƒãŒä½œæˆã•ã‚Œã€æ–°ã—ã„マージリクエストãŒé–‹å§‹ã—ã¾ã™ã€‚"
@@ -287,7 +299,7 @@ msgid "A project is where you house your files (repository), plan your work (iss
msgstr "プロジェクトã¨ã¯ãƒ•ã‚¡ã‚¤ãƒ«ã‚’æ ¼ç´(リãƒã‚¸ãƒˆãƒª) ã—ã€è¨ˆç”»ã‚’ç«‹ã¦(課題)ã€ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’公開(wiki) ã™ã‚‹å ´æ‰€ã§ã™ã€‚ %{among_other_things_link}"
msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
-msgstr ""
+msgstr "ジョブトレースã§ãƒ†ã‚¹ãƒˆã‚«ãƒãƒ¬ãƒƒã‚¸ã®çµæžœã‚’見ã¤ã‘ã‚‹ãŸã‚ã«ä½¿ç”¨ã•ã‚Œã‚‹æ­£è¦è¡¨ç¾ã§ã™ã€‚無効ã«ã™ã‚‹å ´åˆã¯ç©ºç™½ã®ã¾ã¾ã«ã—ã¾ã™ã€‚"
msgid "A user with write access to the source branch selected this option"
msgstr "ã“ã®ã‚ªãƒ—ションをé¸æŠžã—ãŸã‚½ãƒ¼ã‚¹ãƒ–ランãƒã¸ã®æ›¸ãè¾¼ã¿ã‚’許å¯ã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼"
@@ -314,23 +326,20 @@ msgid "Accept terms"
msgstr "利用è¦ç´„ã«åŒæ„ã™ã‚‹"
msgid "Accepted MR"
-msgstr ""
+msgstr "承èªã•ã‚ŒãŸãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
msgid "Access Tokens"
msgstr "アクセス トークン"
msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr ""
+msgstr "アクセスãŒæ‹’å¦ã•ã‚Œã¾ã—ãŸï¼ã“ã®ãƒªãƒã‚¸ãƒˆãƒªã«ãƒ‡ãƒ—ロイキーを追加ã§ãã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
+
+msgid "Access expiration date"
+msgstr "アクセス有効期é™"
msgid "Access to '%{classification_label}' not allowed"
msgstr "'%{classification_label}'ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã¯è¨±å¯ã•ã‚Œã¦ã„ã¾ã›ã‚“"
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr "mount ã«ã‚ˆã£ã¦å¾©æ—§ã§ãるよã†ã«ã€å¤±æ•—ãŒç™ºç”Ÿã—ã¦ã„るストレージã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’一時的ã«æŠ‘æ­¢ã—ã¾ã—ãŸã€‚å†åº¦ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ãŸã‚ã«ã¯ã€å•é¡Œã‚’解決ã—ã¦ã‹ã‚‰ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸æƒ…報をリセットã—ã¦ãã ã•ã„。"
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
-msgstr ""
-
msgid "Account"
msgstr "アカウント"
@@ -358,36 +367,60 @@ msgstr "貢献者å‘ã‘ガイドを追加"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
+msgid "Add Jaeger URL"
+msgstr ""
+
msgid "Add Kubernetes cluster"
msgstr "Kubernetes クラスターを追加"
-msgid "Add License"
-msgstr "ライセンスを追加"
-
msgid "Add Readme"
msgstr "Readmeを追加"
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "ã™ã¹ã¦ã®ãƒ¡ãƒ¼ãƒ«ã«è¡¨ç¤ºã™ã‚‹ãƒ†ã‚­ã‚¹ãƒˆã‚’追加ã—ã¾ã™ã€‚ ãŸã ã—ã€%{character_limit} 文字ã®åˆ¶é™ãŒã‚ã‚Šã¾ã™ã€‚"
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr "ライセンスを追加"
+
msgid "Add new application"
msgstr "æ–°ã—ã„アプリケーションを追加"
msgid "Add new directory"
msgstr "æ–°è¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’追加"
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "リアクションã®è¿½åŠ "
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr "Todoを追加"
msgid "Add user(s) to the group:"
-msgstr ""
+msgstr "グループã«ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’追加:"
msgid "Add users to group"
msgstr "ユーザーをグループã¸è¿½åŠ "
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr "追加テキスト"
@@ -395,7 +428,7 @@ msgid "Admin Area"
msgstr ""
msgid "Admin Overview"
-msgstr ""
+msgstr "管ç†è€…用概è¦"
msgid "Admin area"
msgstr ""
@@ -421,9 +454,6 @@ msgstr "ジョブã®åœæ­¢ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "å…¨ã¦ã®ã‚¸ãƒ§ãƒ–ã‚’åœæ­¢ã—ã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šç¾åœ¨å®Ÿè¡Œä¸­ã®ã‚¸ãƒ§ãƒ–ã¯åœæ­¢ã•ã‚Œã¾ã™ã€‚"
-msgid "AdminHealthPageLink|health page"
-msgstr "ステータスページ"
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -460,12 +490,16 @@ msgstr "確èªã®ãŸã‚ã€%{projectName} を入力ã—ã¦ãã ã•ã„"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "確èªã®ãŸã‚ã€%{username} を入力ã—ã¦ãã ã•ã„"
-msgid "Advanced"
-msgstr "高度ãªè¨­å®š"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
msgid "Advanced settings"
msgstr "高度ãªè¨­å®š"
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+
msgid "All"
msgstr "ã™ã¹ã¦"
@@ -476,11 +510,14 @@ msgid "All features are enabled for blank projects, from templates, or when impo
msgstr "空ã®ãƒ—ロジェクトã€ãƒ†ãƒ³ãƒ—レートã‹ã‚‰ã€ã¾ãŸã¯ã‚¤ãƒ³ãƒãƒ¼ãƒˆæ™‚ã«ã™ã¹ã¦ã®æ©Ÿèƒ½ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ã¾ã™ãŒã€å¾Œã§ãƒ—ロジェクト設定ã§ç„¡åŠ¹ã«ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
msgid "All users"
-msgstr ""
+msgstr "ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼"
msgid "Allow commits from members who can merge to the target branch."
msgstr "ターゲットブランãƒã«ãƒžãƒ¼ã‚¸ã§ãるメンãƒãƒ¼ã‹ã‚‰ã®ã‚³ãƒŸãƒƒãƒˆã‚’許å¯ã—ã¾ã™ã€‚"
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr "パイプラインã«åŠ ãˆã€ãƒ­ã‚°ã‚„æˆæžœç‰©ãªã©ã®ã‚ˆã†ãªã‚¸ãƒ§ãƒ–ã®è©³ç´°ãªæƒ…å ±ã«å¯¾ã—ã¦ã€ãƒ‘ブリックレベルã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ã—ã¾ã™ã€‚"
@@ -490,6 +527,12 @@ msgstr "Asciidocドキュメントã§ã®PlantUML図ã®ãƒ¬ãƒ³ãƒ€ãƒªãƒ³ã‚°ã‚’許å
msgid "Allow requests to the local network from hooks and services."
msgstr "フックãŠã‚ˆã³ã‚µãƒ¼ãƒ“スã‹ã‚‰ã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã¸ã®ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’許å¯ã™ã‚‹ã€‚"
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Kubernetes クラスターを追加ãŠã‚ˆã³ç®¡ç†ã§ãã¾ã™ã€‚"
@@ -505,14 +548,17 @@ msgstr "ã‚ã‚‹ã„ã¯ã€ %{personal_access_token_link} を使用ã™ã‚‹ã“ã¨ã‚‚ã
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr "ã‚ã‚‹ã„ã¯ã€ %{personal_access_token_link} を使用ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚パーソナルアクセストークンを作æˆã™ã‚‹éš›ã«ã€<code>repo</code>スコープをé¸æŠžã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€ã‚¤ãƒ³ãƒãƒ¼ãƒˆã™ã‚‹ã“ã¨ãŒã§ãるパブリックリãƒã‚¸ãƒˆãƒªã¨ãƒ—ライベートリãƒã‚¸ãƒˆãƒªã®ä¸€è¦§ã‚’表示ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
-msgstr ""
+msgstr "アプリケーション㮠%{link_to_client} ãŒã‚ãªãŸã® GitLab アカウントã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’è¦æ±‚ã—ã¦ã„ã¾ã™ã€‚"
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
-msgstr ""
+msgstr "GitLab ユーザフィールドãŒç©ºã®å ´åˆã€ã™ã¹ã¦ã®å•é¡Œã¨ã‚³ãƒ¡ãƒ³ãƒˆã®èª¬æ˜Žã« FogBugz ユーザã®ãƒ•ãƒ«ãƒãƒ¼ãƒ  (例ãˆã°ã€By John Smith)を追加ã—ã¾ã™ã€‚ã¾ãŸã€ã“れらã®å•é¡Œã‚„コメントをプロジェクト作æˆè€…ã«é–¢é€£ä»˜ã‘ã‚‹ã‹ã€ã¾ãŸã¯å‰²ã‚Šå½“ã¦ã¾ã™ã€‚"
msgid "An error accured whilst committing your changes."
msgstr "変更ã®ã‚³ãƒŸãƒƒãƒˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -526,11 +572,11 @@ msgstr "æ–°ã—ã„ブランãƒã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occured whilst fetching the job trace."
msgstr "ジョブトレースã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
-msgid "An error occured whilst fetching the latest pipline."
-msgstr "最新ã®ãƒ‘イプラインã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "An error occured whilst fetching the latest pipeline."
+msgstr ""
msgid "An error occured whilst loading all the files."
-msgstr ""
+msgstr "ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®èª­è¾¼ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occured whilst loading the file content."
msgstr "ファイルã®å†…容を読込中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -550,6 +596,12 @@ msgstr "マージリクエストã®èª­è¾¼ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚
msgid "An error occured whilst loading the pipelines jobs."
msgstr "パイプラインジョブã®èª­è¾¼ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "Blobã®ãƒ—レビュー中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -562,6 +614,9 @@ msgstr "課題ã®ã‚¦ã‚¨ã‚¤ãƒˆæ›´æ–°æ™‚ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while adding approver"
msgstr "承èªè€…ã®è¿½åŠ ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr "ホストキーã®æ¤œå‡ºä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -574,6 +629,9 @@ msgstr "ãƒã‚¤ãƒ©ã‚¤ãƒˆã‚’消去ã—ã¦ã„ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "サイドãƒãƒ¼ã®ãƒ‡ãƒ¼ã‚¿å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -593,17 +651,20 @@ msgid "An error occurred while fetching the pipeline."
msgstr "パイプラインã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while getting projects"
-msgstr ""
+msgstr "プロジェクトã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while importing project: %{details}"
-msgstr ""
+msgstr "プロジェクトã®ã‚¤ãƒ³ãƒãƒ¼ãƒˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ:%{details}"
msgid "An error occurred while initializing path locks"
msgstr "パスロックã®åˆæœŸåŒ–中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
-msgid "An error occurred while loading commit signatures"
+msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading commit signatures"
+msgstr "コミットシグãƒãƒãƒ£ã®èª­è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+
msgid "An error occurred while loading diff"
msgstr "差分ã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -632,7 +693,7 @@ msgid "An error occurred while retrieving diff"
msgstr "差分をå–å¾—ã®éš›ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred while saving LDAP override status. Please try again."
-msgstr ""
+msgstr "LDAP ã®ã‚ªãƒ¼ãƒãƒ¼ãƒ©ã‚¤ãƒ‰çŠ¶æ…‹ã‚’ä¿å­˜ã™ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ãŠè©¦ã—ãã ã•ã„。"
msgid "An error occurred while saving assignees"
msgstr "担当者ã®ç™»éŒ²ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -643,17 +704,23 @@ msgstr "通知ã®è³¼èª­ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "An error occurred while unsubscribing to notifications."
msgstr "通知ã®è³¼èª­ã‚’解除中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr "ユーザåã®æ¤œè¨¼ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "An error occurred. Please try again."
msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚å†åº¦ãŠè©¦ã—ãã ã•ã„。"
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr "匿å"
msgid "Anti-spam verification"
-msgstr ""
+msgstr "スパム対策ã®æ¤œè¨¼"
msgid "Any"
msgstr "ä»»æ„ã®"
@@ -667,11 +734,11 @@ msgstr "外観"
msgid "Application"
msgstr "アプリケーション"
-msgid "Application Id"
-msgstr "アプリケーション ID"
+msgid "Application ID"
+msgstr ""
msgid "Application: %{name}"
-msgstr ""
+msgstr "アプリケーション:%{name}"
msgid "Applications"
msgstr "アプリケーション"
@@ -685,9 +752,15 @@ msgstr "4月"
msgid "Archived project! Repository and other project resources are read-only"
msgstr "ã“ã®ãƒ—ロジェクトã¯ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã•ã‚Œã¦ã„ã¾ã™ã€‚リãƒã‚¸ãƒˆãƒªãŠã‚ˆã³ãã®ä»–ã®ãƒ—ロジェクトリソースã¯èª­ã¿å–り専用ã§ã™"
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "ã“ã®ãƒ‘イプラインスケジュールを削除ã—ã¾ã™ã‹ï¼Ÿ"
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "変更ãŒä¿å­˜ã•ã‚Œã¦ã„ã¾ã›ã‚“ãŒç ´æ£„ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
@@ -706,6 +779,9 @@ msgstr "本当ã«ç™»éŒ²ãƒˆãƒ¼ã‚¯ãƒ³ã‚’リセットã—ã¾ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to reset the health check token?"
msgstr "本当ã«ãƒ˜ãƒ«ã‚¹ãƒã‚§ãƒƒã‚¯ãƒˆãƒ¼ã‚¯ãƒ³ã‚’リセットã—ã¾ã™ã‹ï¼Ÿ"
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "%{path_lock_path} ã®ãƒ­ãƒƒã‚¯ã‚’解除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹ï¼Ÿ"
@@ -755,7 +831,7 @@ msgid "Assignee"
msgstr "担当者"
msgid "Assignee lists not available with your current license"
-msgstr ""
+msgstr "ç¾åœ¨ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ã§ã¯æ‹…当者リストを利用ã§ãã¾ã›ã‚“"
msgid "Assignee lists show all issues assigned to the selected user."
msgstr "担当者一覧ã«ã¯ã€é¸æŠžã—ãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã«å‰²ã‚Šå½“ã¦ã‚‰ã‚Œã¦ã„ã‚‹ã™ã¹ã¦ã®èª²é¡ŒãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
@@ -782,28 +858,28 @@ msgid "Authentication log"
msgstr "èªè¨¼ãƒ­ã‚°"
msgid "Authentication method"
-msgstr ""
+msgstr "èªè¨¼æ–¹æ³•"
msgid "Author"
msgstr "作æˆè€…"
msgid "Authorization code:"
-msgstr ""
+msgstr "èªè¨¼ã‚³ãƒ¼ãƒ‰:"
msgid "Authorization was granted by entering your username and password in the application."
-msgstr ""
+msgstr "ã“ã®ã‚¢ãƒ—リケーションã«ã‚ãªãŸã®ãƒ¦ãƒ¼ã‚¶ãƒ¼åã¨ãƒ‘スワードãŒå…¥åŠ›ã•ã‚ŒãŸã®ã§ã€æ‰¿èªãŒè¨±å¯ã•ã‚Œã¾ã—ãŸã€‚"
msgid "Authorize"
-msgstr ""
+msgstr "承èªã™ã‚‹"
msgid "Authorize %{link_to_client} to use your account?"
-msgstr ""
+msgstr "ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã« %{link_to_client} を承èªã—ã¾ã™ã‹ï¼Ÿ"
msgid "Authorized At"
msgstr ""
msgid "Authorized applications (%{size})"
-msgstr ""
+msgstr "承èªã•ã‚ŒãŸã‚¢ãƒ—リケーション(%{size})"
msgid "Authors: %{authors}"
msgstr "作æˆè€…: %{authors}"
@@ -844,6 +920,9 @@ msgstr "ã‚らã‹ã˜ã‚定義ã•ã‚ŒãŸ CI/CD ã®æ§‹æˆã‚’基ã«è‡ªå‹•çš„ã«ã‚¢ãƒ
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "詳ã—ãã¯ã€ %{link_to_documentation} を見ã¦ãã ã•ã„。"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr "ã“ã®ãƒ—ロジェクト㮠%{link_to_auto_devops_settings} ã‚’ã™ã‚‹å ´åˆã€è‡ªå‹•ãƒ“ルドãŠã‚ˆã³ãƒ†ã‚¹ãƒˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚%{link_to_add_kubernetes_cluster} ã—ãŸå ´åˆã€è‡ªå‹•ãƒ‡ãƒ—ロイã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
@@ -880,9 +959,6 @@ msgstr "ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã‚¸ãƒ§ãƒ–"
msgid "Background color"
msgstr "背景色"
-msgid "Background jobs"
-msgstr "ãƒãƒƒã‚¯ã‚°ãƒ©ã‚¦ãƒ³ãƒ‰ã‚¸ãƒ§ãƒ–"
-
msgid "Badges"
msgstr "ãƒãƒƒã‚¸"
@@ -961,14 +1037,23 @@ msgstr "ãƒãƒƒã‚¸"
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr "é¸æŠžã—ãŸã‚³ãƒŸãƒƒãƒˆã§ã¯ã˜ã‚ã‚‹"
msgid "Below are examples of regex for existing tools:"
-msgstr ""
+msgstr "以下ã®ã‚‚ã®ã¯ã€æ—¢å­˜ã®æ­£è¦è¡¨ç¾ãƒ„ールã®ä¾‹ã§ã™:"
msgid "Below you will find all the groups that are public."
-msgstr ""
+msgstr "以下ã«å…¬é–‹ã•ã‚Œã¦ã„る全グループを表示ã—ã¾ã™ã€‚"
msgid "Billing"
msgstr "請求"
@@ -1025,16 +1110,16 @@ msgid "BillingPlans|features"
msgstr "機能"
msgid "BillingPlans|frequently asked questions"
-msgstr ""
+msgstr "FAQ 集"
msgid "BillingPlans|monthly"
msgstr "月é¡"
msgid "BillingPlans|paid annually at %{price_per_year}"
-msgstr ""
+msgstr "å¹´é¡ %{price_per_year}"
msgid "BillingPlans|per user"
-msgstr ""
+msgstr "1ユーザーã«ã¤ã"
msgid "Bitbucket Server Import"
msgstr ""
@@ -1209,7 +1294,7 @@ msgid "Browse files"
msgstr "ファイルを表示"
msgid "Built-In"
-msgstr ""
+msgstr "ビルトイン"
msgid "Business metrics (Custom)"
msgstr "ビジãƒã‚¹ãƒ¡ãƒˆãƒªã‚¯ã‚¹ï¼ˆã‚«ã‚¹ã‚¿ãƒ ï¼‰"
@@ -1250,6 +1335,9 @@ msgstr "ステージングã¸ã®è‡ªå‹•ãƒ‡ãƒ—ロイã€æœ¬ç•ªç’°å¢ƒã¸ã®æ‰‹å‹•ãƒ‡
msgid "CICD|Continuous deployment to production"
msgstr "本番環境ã¸ã®ç¶™ç¶šçš„デプロイ"
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1275,14 +1363,11 @@ msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and
msgstr "自動 Review Apps ã¨è‡ªå‹•ãƒ‡ãƒ—ロイステージを使用ã—ãŸã„å ´åˆã¯ã€ãƒ‰ãƒ¡ã‚¤ãƒ³ã‚’指定ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
msgid "CICD|instance enabled"
-msgstr ""
+msgstr "インスタンスãŒæœ‰åŠ¹"
msgid "Callback URL"
msgstr "コールãƒãƒƒã‚¯ URL"
-msgid "Callback url"
-msgstr "コールãƒãƒƒã‚¯ URL"
-
msgid "Can't find HEAD commit for this branch"
msgstr "ã“ã®ãƒ–ランãƒã«ã¯ HEAD コミットãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
@@ -1299,13 +1384,13 @@ msgid "Cannot modify managed Kubernetes cluster"
msgstr "管ç†ä¸‹ã® Kubernetes クラスターを変更ã§ãã¾ã›ã‚“"
msgid "Certificate fingerprint"
-msgstr ""
+msgstr "証明書ã®ãƒ•ã‚£ãƒ³ã‚¬ãƒ¼ プリント"
msgid "Change Weight"
msgstr "ウェイトを変更ã™ã‚‹"
msgid "Change template"
-msgstr ""
+msgstr "テンプレートを変更"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "GitLab UI ã®æ›´æ–°é »åº¦ã‚’変更ã™ã‚‹ã«ã¯ã“ã®å€¤ã‚’変更ã—ã¦ãã ã•ã„。"
@@ -1337,8 +1422,8 @@ msgstr "ãƒãƒ£ãƒ¼ãƒˆ"
msgid "Chat"
msgstr "ãƒãƒ£ãƒƒãƒˆ"
-msgid "Check interval"
-msgstr "ãƒã‚§ãƒƒã‚¯ã®é–“éš”"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
msgid "Checking %{text} availability…"
msgstr "%{text} ãŒåˆ©ç”¨å¯èƒ½ã‹ç¢ºèªã—ã¦ã„ã¾ã™â€¦"
@@ -1364,6 +1449,12 @@ msgstr "ファイルをé¸æŠž..."
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr "変更内容を確èªã—ãŸã‚Šãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’作æˆã™ã‚‹ãŸã‚ã«ã€Branch/tag (例: %{master}) ã‚’é¸æŠžã™ã‚‹ã‹ã€ã‚³ãƒŸãƒƒãƒˆID(例: %{sha})を入力ã—ã¦ãã ã•ã„。"
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr "カラーをé¸æŠžã—ã¦ãã ã•ã„。"
@@ -1394,6 +1485,9 @@ msgstr "キャンセル"
msgid "CiStatusLabel|created"
msgstr "作æˆæ¸ˆã¿"
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr "失敗"
@@ -1412,6 +1506,9 @@ msgstr "開始待ã¡"
msgid "CiStatusLabel|skipped"
msgstr "スキップ済ã¿"
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr "手動実行待ã¡"
@@ -1424,6 +1521,9 @@ msgstr "キャンセル"
msgid "CiStatusText|created"
msgstr "作æˆæ¸ˆã¿"
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr "失敗"
@@ -1478,10 +1578,10 @@ msgstr "ä¿è­·ã®åˆ‡ã‚Šæ›¿ãˆ"
msgid "CiVariable|Validation failed"
msgstr "検証ã«å¤±æ•—ã—ã¾ã—ãŸ"
-msgid "CircuitBreakerApiLink|circuitbreaker api"
-msgstr "Circuit Breaker API"
-
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr "使用ã§ãã¾ã›ã‚“:%{reason}"
+
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1503,7 +1603,7 @@ msgid "Click the button below to begin the install process by navigating to the
msgstr "下ã®ãƒœã‚¿ãƒ³ã‚’クリックã™ã‚‹ã¨ã€Kubernetesã®ãƒšãƒ¼ã‚¸ã«é·ç§»ã—ã€ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ãƒ—ロセスを開始ã—ã¾ã™"
msgid "Click to expand it."
-msgstr ""
+msgstr "クリックã—ã¦å±•é–‹ã€‚"
msgid "Click to expand text"
msgstr "クリックã—ã¦ãƒ†ã‚­ã‚¹ãƒˆã‚’展開ã™ã‚‹"
@@ -1524,6 +1624,9 @@ msgid "Clone repository"
msgstr "リãƒã‚¸ãƒˆãƒªã‚’クローン"
msgid "Close"
+msgstr "クローズã™ã‚‹"
+
+msgid "Close epic"
msgstr ""
msgid "Closed"
@@ -1538,12 +1641,24 @@ msgstr "%{appList} ã¯æ­£å¸¸ã« Kubernetes クラスターã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr "API URL"
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr "Kubernetes クラスターを追加"
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "ã“ã® Kubernetes クラスター統åˆã«é–¢ã™ã‚‹è©³ç´°ã‚ªãƒ—ション"
@@ -1574,11 +1689,11 @@ msgstr "CA 証明書"
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "èªè¨¼å±€ãƒãƒ³ãƒ‰ãƒ« (PEMå½¢å¼)"
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
-msgstr "ã©ã®ãƒ—ロジェクト環境ã§ã“ã® Kubernetes クラスターを使ã†ã‹é¸æŠžã—ã¦ãã ã•ã„。"
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
-msgstr "Kubernetes クラスター㨠GitLab ã®çµ±åˆæ–¹æ³•ã®åˆ¶å¾¡"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
msgid "ClusterIntegration|Copy API URL"
msgstr "API URLをコピー"
@@ -1604,6 +1719,12 @@ msgstr "Kubernetes クラスターを作æˆ"
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr "Kubernetes クラスターã®è©³ç´°ã‚’入力ã—ã¦ãã ã•ã„"
@@ -1640,6 +1761,9 @@ msgstr "Google Kubernetes Engine"
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr "Google Kubernetes Engine プロジェクト"
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
@@ -1670,9 +1794,6 @@ msgstr "インストール"
msgid "ClusterIntegration|Install Prometheus"
msgstr "Prometheus をインストール"
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr "インストール済ã¿"
@@ -1694,6 +1815,12 @@ msgstr "JupyterHub"
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr "Kubernetes クラスター"
@@ -1703,18 +1830,6 @@ msgstr "Kubernetes クラスターã®è©³ç´°"
msgid "ClusterIntegration|Kubernetes cluster health"
msgstr "Kubernetes クラスターã®ç¨¼åƒçŠ¶æ…‹"
-msgid "ClusterIntegration|Kubernetes cluster integration"
-msgstr "Kubernetes クラスターã®çµ±åˆ"
-
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
-msgstr "Kubernetes クラスターã®çµ±åˆãŒã“ã®ãƒ—ロジェクトã§ç„¡åŠ¹ã§ã™ã€‚"
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
-msgstr "Kubernetes クラスターã®çµ±åˆãŒã“ã®ãƒ—ロジェクトã§æœ‰åŠ¹ã§ã™ã€‚"
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
-msgstr "Kubernetes クラスターã®çµ±åˆãŒã“ã®ãƒ—ロジェクトã§æœ‰åŠ¹ã§ã™ã€‚ã“ã®çµ±åˆã‚’無効ã«ã—ã¦ã‚‚ Kubernetes クラスターã«ã¯å½±éŸ¿ã›ãšã€GitLab ã¨ã®æŽ¥ç¶šãŒä¸€æ™‚çš„ã«åˆ‡æ–­ã•ã‚Œã‚‹ã ã‘ã§ã™ã€‚"
-
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
msgstr "Kubernetes クラスターを Google Kubernetes Engine 上ã«ä½œæˆã—ã¦ã„ã¾ã™..."
@@ -1724,8 +1839,8 @@ msgstr "Kubernetes クラスターå"
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr "Kubernetes クラスター ã¯æ­£å¸¸ã« Google Kubernetes Engine ã«ä½œæˆã•ã‚Œã¾ã—ãŸã€‚クラスター ã®è©³ç´°ã‚’表示ã™ã‚‹ã«ã¯ãƒšãƒ¼ã‚¸ã‚’æ›´æ–°ã—ã¦ãã ã•ã„。"
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
-msgstr "Kubernetes クラスターを利用ã™ã‚‹ã¨ã€ Review Apps ã®ä½¿ç”¨ã€ã‚¢ãƒ—リケーションã®ãƒ‡ãƒ—ロイã€ãƒ‘イプラインã®å®Ÿè¡Œãªã©ã‚’より簡å˜ã«å®Ÿç¾ã§ãã¾ã™ã€‚%{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
msgstr "Kubernetes クラスターã¯ã€ã“ã®ãƒ—ロジェクトã«ã‚¢ãƒ—リケーションã®ãƒ‡ãƒ—ロイや Review Apps ã®ç’°å¢ƒã‚’æä¾›ã™ã‚‹ã®ã«ä½¿ç”¨ã§ãã¾ã™ã€‚"
@@ -1733,17 +1848,14 @@ msgstr "Kubernetes クラスターã¯ã€ã“ã®ãƒ—ロジェクトã«ã‚¢ãƒ—リケã
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr "%{help_link_start_machine_type}マシンタイプ%{help_link_end}ã¨%{help_link_start_pricing}価格%{help_link_end}ã®è©³ç´°ã€‚"
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr "%{help_link_start}Kubernetes%{help_link_end}ã®è©³ç´°ã€‚"
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr "%{help_link_start}ゾーン%{help_link_end}ã®è©³ç´°ã€‚"
-msgid "ClusterIntegration|Learn more about environments"
-msgstr "環境ã®è©³ç´°"
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
-msgstr "セキュリティ設定ã®è©³ç´°"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
msgid "ClusterIntegration|Machine type"
msgstr "マシンタイプ"
@@ -1760,9 +1872,6 @@ msgstr "%{link_gke} ã«ã‚¢ã‚¯ã‚»ã‚¹ã—㦠Kubernetes クラスターを管ç†"
msgid "ClusterIntegration|More information"
msgstr "詳細情報"
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr "検索æ¡ä»¶ã«ä¸€è‡´ã™ã‚‹ãƒžã‚·ãƒ³ã‚¿ã‚¤ãƒ—ã¯ã‚ã‚Šã¾ã›ã‚“"
@@ -1782,7 +1891,7 @@ msgid "ClusterIntegration|Number of nodes"
msgstr "ノード数"
msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
-msgstr ""
+msgstr "Kubernetes クラスターã®ã‚¢ã‚¯ã‚»ã‚¹æƒ…報を入力ã—ã¦ãã ã•ã„。ä¸æ˜Žç‚¹ã¯ %{link_to_help_page} ã® Kubernetes ã®é …目をã”覧ãã ã•ã„。"
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
msgstr "Google アカウントãŒæ¬¡ã®è¦ä»¶ã‚’満ãŸã—ã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
@@ -1790,6 +1899,9 @@ msgstr "Google アカウントãŒæ¬¡ã®è¦ä»¶ã‚’満ãŸã—ã¦ã„ã‚‹ã“ã¨ã‚’確èª
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr "プロジェクトã®åå‰ç©ºé–“"
@@ -1802,6 +1914,9 @@ msgstr "Prometheus"
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr "Kubernetes クラスターã®çµ±åˆã«ã¤ã„ã¦ã¯ã€%{link_to_help_page} ã‚’ãŠèª­ã¿ãã ã•ã„。"
@@ -1832,9 +1947,6 @@ msgstr "プロジェクトã®æ¤œç´¢"
msgid "ClusterIntegration|Search zones"
msgstr "ゾーンを検索"
-msgid "ClusterIntegration|Security"
-msgstr "セキュリティ"
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "Kubernetes クラスターã®è©³ç´°ã‚’閲覧ã€ç·¨é›†ã™ã‚‹"
@@ -1874,14 +1986,11 @@ msgstr "%{title} ã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr "既定ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¼è¨­å®šã§ã¯ã€ã‚³ãƒ³ãƒ†ãƒŠåŒ–ã•ã‚ŒãŸã‚¢ãƒ—リケーションを正常ã«ãƒ“ルドやデプロイã™ã‚‹ãŸã‚ã«å¿…è¦ãªæ§˜ã€…ãªæ©Ÿèƒ½ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™ã€‚"
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr "ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ %{link_to_container_project} 㧠Kubernetes クラスターを作æˆã™ã‚‹ã®ã«ä»¥ä¸‹ã®æ¨©é™ãŒå¿…è¦ã§ã™"
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
-msgstr "Kubernetes クラスターを切り替ãˆ"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "Kubernetes クラスターを切り替ãˆ"
@@ -1898,6 +2007,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "ã“ã®ãƒ—ロジェクト㫠Kubernetes クラスターを関連付ã‘ã‚‹ã“ã¨ã§ã€Review Apps ã®ä½¿ç”¨ã€ã‚¢ãƒ—リケーションã®ãƒ‡ãƒ—ロイã€ãƒ‘イプラインã®å®Ÿè¡Œãªã©ã‚’ç°¡å˜ã«è¡Œã†ã“ã¨ãŒã§ãã¾ã™ã€‚"
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "アカウント㫠%{link_to_kubernetes_engine} ãŒå¿…è¦ã§ã™ã€‚"
@@ -1916,9 +2028,6 @@ msgstr "ドキュメント"
msgid "ClusterIntegration|help page"
msgstr "ヘルプ ページ"
-msgid "ClusterIntegration|installing applications"
-msgstr "アプリケーションをインストールã—ã¦ã„ã¾ã™"
-
msgid "ClusterIntegration|meets the requirements"
msgstr "å¿…è¦æ¡ä»¶"
@@ -1928,6 +2037,9 @@ msgstr "æ­£ã—ã設定ã•ã‚Œã¦ã„ã‚‹"
msgid "ClusterIntegration|sign up"
msgstr "æ–°è¦ç™»éŒ²"
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -1937,12 +2049,18 @@ msgstr "折りãŸãŸã‚€"
msgid "Collapse sidebar"
msgstr "サイドãƒãƒ¼ã‚’éš ã™"
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr "ã“ã®æ¤œè¨Žã«ã‚³ãƒ¡ãƒ³ãƒˆã—解決ã™ã‚‹"
msgid "Comment & unresolve discussion"
msgstr "ã“ã®æ¤œè¨Žã«ã‚³ãƒ¡ãƒ³ãƒˆã—未解決ã«ã™ã‚‹"
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr "コメント"
@@ -1964,7 +2082,7 @@ msgid "Commit message"
msgstr "コミットメッセージ"
msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
-msgstr ""
+msgstr "%{start_time} ã‹ã‚‰ %{end_time} ã¾ã§ã® %{ref} ブランãƒã®çµ±è¨ˆ"
msgid "Commit to %{branchName} branch"
msgstr "%{branchName} ブランãƒã«ã‚³ãƒŸãƒƒãƒˆ"
@@ -1975,6 +2093,9 @@ msgstr "コミット"
msgid "CommitMessage|Add %{file_name}"
msgstr "%{file_name} を追加"
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr "コミット"
@@ -1982,13 +2103,13 @@ msgid "Commits feed"
msgstr "コミットフィード"
msgid "Commits per day hour (UTC)"
-msgstr ""
+msgstr "時間帯別ã®ã‚³ãƒŸãƒƒãƒˆæ•° (UTC)"
msgid "Commits per day of month"
-msgstr ""
+msgstr "1ヶ月ã”ã¨ã®ã‚³ãƒŸãƒƒãƒˆæ•°"
msgid "Commits per weekday"
-msgstr ""
+msgstr "週ã”ã¨ã®ã‚³ãƒŸãƒƒãƒˆæ•°"
msgid "Commits|An error occurred while fetching merge requests data."
msgstr "マージリクエストデータã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -2006,7 +2127,7 @@ msgid "Committed by"
msgstr "コミット担当者: "
msgid "Commit…"
-msgstr ""
+msgstr "コミット"
msgid "Compare"
msgstr "比較"
@@ -2042,13 +2163,13 @@ msgid "Confidential"
msgstr "éžå…¬é–‹"
msgid "Confidentiality"
-msgstr ""
+msgstr "機密性"
msgid "Configure Gitaly timeouts."
msgstr "Gitaly ã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã‚’設定ã—ã¾ã™ã€‚"
-msgid "Configure Sidekiq job throttling."
-msgstr "Sidekiq job throttling ã®è¨­å®š"
+msgid "Configure Tracing"
+msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr "リãƒã‚¸ãƒˆãƒªã«å¯¾ã—ã¦è‡ªå‹•å®Ÿè¡Œã™ã‚‹ Git ãƒã‚§ãƒƒã‚¯ã¨ãƒã‚¦ã‚¹ã‚­ãƒ¼ãƒ”ングを設定ã—ã¾ã™ã€‚"
@@ -2056,11 +2177,11 @@ msgstr "リãƒã‚¸ãƒˆãƒªã«å¯¾ã—ã¦è‡ªå‹•å®Ÿè¡Œã™ã‚‹ Git ãƒã‚§ãƒƒã‚¯ã¨ãƒã‚¦ã
msgid "Configure limits for web and API requests."
msgstr "ウェブãŠã‚ˆã³APIリクエストã®åˆ¶é™ã‚’設定ã™ã‚‹ã€‚"
-msgid "Configure push and pull mirrors."
-msgstr "プッシュミラーã¨ãƒ—ルミラーを構æˆã—ã¾ã™ã€‚"
+msgid "Configure push mirrors."
+msgstr "プッシュミラーを構æˆã—ã¾ã™ã€‚"
-msgid "Configure storage path and circuit breaker settings."
-msgstr "ストレージã®ãƒ‘スã¨ã‚µãƒ¼ã‚­ãƒƒãƒˆãƒ–レーカーを設定ã™ã‚‹ã€‚"
+msgid "Configure storage path settings."
+msgstr ""
msgid "Configure the %{link} integration."
msgstr ""
@@ -2135,7 +2256,7 @@ msgid "Continue"
msgstr "続行"
msgid "Continue to the next step"
-msgstr ""
+msgstr "次ã®ã‚¹ãƒ†ãƒƒãƒ—ã«é€²ã¿ã¾ã™"
msgid "Continuous Integration and Deployment"
msgstr "継続的インテグレーションã¨ãƒ‡ãƒ—ロイ"
@@ -2149,6 +2270,9 @@ msgstr "貢献度"
msgid "Contribution guide"
msgstr "貢献者å‘ã‘ガイド"
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr "グループメンãƒãƒ¼ã®è²¢çŒ®åº¦"
@@ -2182,6 +2306,18 @@ msgstr "ã“ã® Geo ノードã®æ¤œè¨¼æ“作ã®æœ€å¤§åŒæ™‚実行数を制御ã™ã
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr "SSH 公開éµã‚’クリップボードã«ã‚³ãƒ”ー"
@@ -2201,15 +2337,27 @@ msgid "Copy file path to clipboard"
msgstr "ファイルパスをクリップボードã«ã‚³ãƒ”ーã™ã‚‹"
msgid "Copy incoming email address to clipboard"
+msgstr "å—信用メールアドレスをクリップボードã«ã‚³ãƒ”ーã—ã¾ã™ã€‚"
+
+msgid "Copy link"
+msgstr "リンクをコピー"
+
+msgid "Copy name to clipboard"
msgstr ""
msgid "Copy reference to clipboard"
msgstr "クリップボードã¸ã‚³ãƒ”ー"
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr "クリップボードã«ã‚³ãƒ”ー"
msgid "Copy token to clipboard"
+msgstr "トークンをクリップボードã«ã‚³ãƒ”ーã—ã¾ã™"
+
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
msgstr ""
msgid "Create"
@@ -2249,13 +2397,13 @@ msgid "Create file"
msgstr "ファイルを作æˆ"
msgid "Create group"
-msgstr ""
+msgstr "グループを作æˆ"
msgid "Create group label"
msgstr "グループラベルを作æˆ"
msgid "Create issue"
-msgstr ""
+msgstr "課題を作æˆ"
msgid "Create lists from labels. Issues with that label appear in that list."
msgstr "ラベルã‹ã‚‰ãƒªã‚¹ãƒˆã‚’作æˆã€‚ãã®ãƒ©ãƒ™ãƒ«ã®èª²é¡ŒãŒãƒªã‚¹ãƒˆã«è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
@@ -2276,7 +2424,7 @@ msgid "Create new file"
msgstr "æ–°è¦ãƒ•ã‚¡ã‚¤ãƒ«ä½œæˆ"
msgid "Create new file or directory"
-msgstr ""
+msgstr "æ–°ã—ã„ファイルやディレクトリを作æˆã—ã¾ã™"
msgid "Create new label"
msgstr "ラベルã®æ–°è¦ä½œæˆ"
@@ -2287,8 +2435,8 @@ msgstr "æ–°è¦ä½œæˆ"
msgid "Create project label"
msgstr "プロジェクトラベルを作æˆ"
-msgid "CreateNewFork|Fork"
-msgstr "フォーク"
+msgid "Create your first page"
+msgstr ""
msgid "CreateTag|Tag"
msgstr "ã‚¿ã‚°"
@@ -2309,7 +2457,7 @@ msgid "Created on"
msgstr ""
msgid "Created on:"
-msgstr ""
+msgstr "作æˆæ—¥æ™‚:"
msgid "Creating epic"
msgstr "エピックを作æˆã—ã¦ã„ã¾ã™"
@@ -2321,7 +2469,7 @@ msgid "Cron syntax"
msgstr "Cron ã®æ§‹æ–‡"
msgid "Current Branch"
-msgstr ""
+msgstr "ç¾åœ¨ã®ãƒ–ランãƒ"
msgid "Current node"
msgstr "ç¾åœ¨ã®ãƒŽãƒ¼ãƒ‰"
@@ -2333,11 +2481,14 @@ msgid "CurrentUser|Settings"
msgstr "設定"
msgid "Custom"
-msgstr ""
+msgstr "カスタム"
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr "カスタム通知設定"
@@ -2345,7 +2496,7 @@ msgid "Custom notification levels are the same as participating levels. With cus
msgstr "\"カスタム\" ã®é€šçŸ¥ãƒ¬ãƒ™ãƒ«ã®åŸºæœ¬ã¯ \"å‚加\" ã¨åŒã˜ã§ã™ã€‚ã¾ãŸã€ã‚«ã‚¹ã‚¿ãƒ é€šçŸ¥ã«è¨­å®šã™ã‚‹ã“ã¨ã§é¸æŠžã—ãŸã‚«ã‚¹ã‚¿ãƒ ã‚¤ãƒ™ãƒ³ãƒˆã®é€šçŸ¥ã‚’å—ã‘å–ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚ã‚‚ã£ã¨è©³ã—ã知りãŸã„å ´åˆã¯ %{notification_link} を見ã¦ãã ã•ã„。"
msgid "Custom project templates"
-msgstr ""
+msgstr "カスタムプロジェクトテンプレート"
msgid "Customize colors"
msgstr "カスタムカラー"
@@ -2356,6 +2507,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr "Runner トークンã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã€ãƒ‘イプラインã®è¨­å®šã‚’カスタマイズã€ãã—ã¦ãƒ‘イプラインã®çŠ¶æ…‹ã¨ã‚«ãƒãƒ¬ãƒƒã‚¸ãƒ¬ãƒãƒ¼ãƒˆã‚’閲覧ã—ã¾ã™ã€‚"
+
msgid "Cycle Analytics"
msgstr "サイクル分æž"
@@ -2396,7 +2550,7 @@ msgid "Date picker"
msgstr ""
msgid "Debug"
-msgstr ""
+msgstr "デãƒãƒƒã‚°"
msgid "Dec"
msgstr "12月"
@@ -2407,6 +2561,9 @@ msgstr "12月"
msgid "Decline and sign out"
msgstr "辞退ã—ã¦ã‚µã‚¤ãƒ³ã‚¢ã‚¦ãƒˆ"
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr "デフォルト分類ラベル"
@@ -2419,6 +2576,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Cron 構文ã§ã‚«ã‚¹ã‚¿ãƒ ãªãƒ‘ターンを指定ã™ã‚‹"
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr "削除"
@@ -2428,6 +2600,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr "スニペットを削除"
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr "リストを削除ã™ã‚‹"
@@ -2564,6 +2739,12 @@ msgstr "æ–°è¦ãƒ‡ãƒ—ロイトークン"
msgid "DeployTokens|Your new project deploy token has been created."
msgstr "æ–°ã—ã„プロジェクトデプロイトークンãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr "éžå„ªå…ˆãƒ©ãƒ™ãƒ«"
@@ -2577,7 +2758,7 @@ msgid "Description templates allow you to define context-specific templates for
msgstr "Description テンプレートを使用ã™ã‚‹ã¨ã€ãƒ—ロジェクトã®èª²é¡ŒãŠã‚ˆã³ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆèª¬æ˜Žã«å¯¾ã™ã‚‹ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆå›ºæœ‰ã®ãƒ†ãƒ³ãƒ—レートを定義ã§ãã¾ã™ã€‚"
msgid "Description:"
-msgstr ""
+msgstr "説明:"
msgid "Destroy"
msgstr "破棄"
@@ -2588,6 +2769,12 @@ msgstr "詳細"
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr "使用å¯èƒ½ãªãƒ•ã‚¡ã‚¤ãƒ«åãŒã‚ã‚Šã¾ã›ã‚“"
@@ -2609,12 +2796,27 @@ msgstr "ã“ã®ãƒ—ロジェクトã§ã¯ç„¡åŠ¹ã«ã™ã‚‹"
msgid "Disable group Runners"
msgstr "グループ Runner を無効ã«ã™ã‚‹"
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr "変更を破棄ã™ã‚‹"
+msgid "Discard changes to %{path}?"
+msgstr "%{path} ã®å¤‰æ›´ã‚’破棄ã—ã¾ã™ã‹ï¼Ÿ"
+
msgid "Discard draft"
msgstr "下書ãを破棄"
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr "GitLab Geo ã«ã¤ã„ã¦"
@@ -2630,6 +2832,9 @@ msgstr "サイクル分æžã®ç´¹ä»‹ã‚’é–‰ã˜ã‚‹"
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2682,7 +2887,7 @@ msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use
msgstr "ã“ã®ãƒ—ロセスã®é€”中ã§ã€GitLab å´ã‹ã‚‰ã® URL ã‚’èžã‹ã‚Œã‚‹ã®ã§ã€æ¬¡ã® URL を使用ã—ã¦ãã ã•ã„。"
msgid "Each Runner can be in one of the following states:"
-msgstr ""
+msgstr "å„ Runner ã¯æ¬¡ã®ã„ãšã‚Œã‹ã®çŠ¶æ…‹ã‚’ã¨ã‚Šã¾ã™:"
msgid "Edit"
msgstr "編集"
@@ -2700,7 +2905,7 @@ msgid "Edit application"
msgstr "アプリケーションã®ç·¨é›†"
msgid "Edit files in the editor and commit changes here"
-msgstr ""
+msgstr "エディターã§ãƒ•ã‚¡ã‚¤ãƒ«ã‚’編集ã—ã€ã“ã“ã§å¤‰æ›´ã‚’コミットã—ã¾ã™"
msgid "Edit group: %{group_name}"
msgstr "グループを編集:%{group_name}"
@@ -2711,8 +2916,8 @@ msgstr "%{user_name} ã® ID を編集ã™ã‚‹"
msgid "Elasticsearch"
msgstr "Elasticsearch"
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
-msgstr "Elasticsearch ã®çµ±åˆã€‚Elasticsearch AWS IAM。"
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
msgid "Email"
msgstr "メール"
@@ -2739,7 +2944,7 @@ msgid "Enable SAML authentication for this group"
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã® SAML èªè¨¼ã‚’有効ã«ã™ã‚‹"
msgid "Enable Sentry for error reporting and logging."
-msgstr ""
+msgstr "エラー報告ã¨ãƒ­ã‚°è¨˜éŒ²ã®ãŸã‚ã« Sentry を有効ã«ã™ã‚‹ã€‚"
msgid "Enable and configure InfluxDB metrics."
msgstr "InfluxDB ã®ãƒ¡ãƒˆãƒªã‚¯ã‚¹ã‚’有効ã«ã—ã¦è¨­å®šã™ã‚‹ã€‚"
@@ -2756,9 +2961,6 @@ msgstr "ã“ã®ãƒ—ロジェクトã§ã¯æœ‰åŠ¹ã«ã™ã‚‹"
msgid "Enable group Runners"
msgstr "グループ Runner を有効ã«ã™ã‚‹"
-msgid "Enable or disable certain group features and choose access levels."
-msgstr "特定ã®ã‚°ãƒ«ãƒ¼ãƒ—機能を有効ã¾ãŸã¯ç„¡åŠ¹ã«ã—ã€ã‚¢ã‚¯ã‚»ã‚¹ãƒ¬ãƒ™ãƒ«ã‚’é¸æŠžã—ã¾ã™ã€‚"
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2769,6 +2971,12 @@ msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr "reCAPTCHA ã¾ãŸã¯ Akismet ã®æœ‰åŠ¹ã€ãŠã‚ˆã³ IP 制é™ã‚’設定ã™ã‚‹ã€‚"
msgid "Enable the Performance Bar for a given group."
+msgstr "指定グループã®ãƒ‘フォーマンスãƒãƒ¼ã‚’有効ã«ã™ã‚‹ã€‚"
+
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
msgstr ""
msgid "Enabled"
@@ -2781,7 +2989,7 @@ msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
msgid "Enter the issue description"
-msgstr ""
+msgstr "課題ã®èª¬æ˜Žã‚’入力ã—ã¦ãã ã•ã„"
msgid "Enter the issue title"
msgstr ""
@@ -2856,7 +3064,7 @@ msgid "Environments|Re-deploy to environment"
msgstr ""
msgid "Environments|Read more about environments"
-msgstr ""
+msgstr "環境ã®è©³ç´°ã«ã¤ã„ã¦èª­ã‚€"
msgid "Environments|Rollback environment"
msgstr ""
@@ -2873,7 +3081,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr "更新済ã¿"
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -2906,10 +3114,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -2934,10 +3142,10 @@ msgid "Error fetching network graph."
msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã‚°ãƒ©ãƒ•ã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Error fetching refs"
-msgstr ""
+msgstr "å‚ç…§ã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿ"
msgid "Error fetching usage ping data."
-msgstr ""
+msgstr "Ping データå–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Error loading branch data. Please try again."
msgstr "ブランムデータã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
@@ -3020,6 +3228,12 @@ msgstr "ã™ã¹ã¦å±•é–‹"
msgid "Expand sidebar"
msgstr "サイドãƒãƒ¼ã‚’é–‹ã"
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3074,6 +3288,12 @@ msgstr "オーナーを変更ã§ãã¾ã›ã‚“ã§ã—ãŸ"
msgid "Failed to check related branches."
msgstr "関連ã™ã‚‹ãƒ–ランãƒã®ç¢ºèªã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr "ボードã®èª²é¡Œã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
@@ -3083,6 +3303,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "パイプラインスケジュールを削除ã§ãã¾ã›ã‚“ã§ã—ãŸ"
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr "課題ã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
@@ -3092,6 +3315,81 @@ msgstr "失敗"
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr "2月"
@@ -3101,6 +3399,9 @@ msgstr "2月"
msgid "Fields on this page are now uneditable, you can configure"
msgstr "ã“ã®ãƒšãƒ¼ã‚¸ã®é …ç›®ã¯ç·¨é›†ã§ããªã„設定ã§ã™ã€‚次㮠Kubernetes クラスターを設定ã§ãã¾ã™ã€‚"
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr "ファイル"
@@ -3111,11 +3412,20 @@ msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and p
msgstr "下記項目ã«å¿…è¦äº‹é …を入力ã—〠<strong>%{enable_label}</strong>をオンã«ã—ã¦ã€ <strong>%{save_changes}</strong>を押ã—ã¦ãã ã•ã„。"
msgid "Filter"
+msgstr "フィルター"
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
msgstr ""
msgid "Filter by commit message"
msgstr "コミットメッセージã§çµžã‚Šè¾¼ã¿"
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr "パスã§æ¤œç´¢"
@@ -3131,6 +3441,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr "完了"
@@ -3143,7 +3456,7 @@ msgstr "プッシュã—ãŸäºº"
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3182,16 +3495,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] "フォーク"
-
msgid "ForkedFromProjectPath|Forked from"
msgstr "フォーク元"
@@ -3207,6 +3522,9 @@ msgstr "フォーマット"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ".gitlab-ci.yml ã«ã‚¨ãƒ©ãƒ¼ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ:"
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr "%{provider_title}ã‹ã‚‰"
@@ -3249,6 +3567,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr "åˆæœŸè¨­å®šãƒ©ãƒ™ãƒ«ã‚»ãƒƒãƒˆã‚’生æˆã™ã‚‹"
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3355,10 +3676,10 @@ msgid "GeoNodes|Repositories verified with their counterparts on the Primary nod
msgstr "プライマリノードã®å¯¾å¿œãƒªãƒã‚¸ãƒˆãƒªã¨ã®æ¤œè¨¼ãŒå®Œäº†ã—ãŸãƒªãƒã‚¸ãƒˆãƒª"
msgid "GeoNodes|Repository checksum progress"
-msgstr ""
+msgstr "リãƒã‚¸ãƒˆãƒªãƒã‚§ãƒƒã‚¯ã‚µãƒ ã®é€²è¡ŒçŠ¶æ³"
msgid "GeoNodes|Repository verification progress"
-msgstr ""
+msgstr "リãƒã‚¸ãƒˆãƒªæ¤œè¨¼ã®é€²æ—状æ³"
msgid "GeoNodes|Selective"
msgstr "é¸æŠžçš„"
@@ -3423,10 +3744,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr "ã™ã¹ã¦ã®ãƒ—ロジェクト"
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3435,6 +3768,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr "ファイルåŒæœŸå®¹é‡"
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr "åŒæœŸã‚°ãƒ«ãƒ¼ãƒ—"
@@ -3456,7 +3792,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3468,6 +3804,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr "特定グループã®ãƒ—ロジェクト"
@@ -3477,19 +3816,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr "リãƒã‚¸ãƒˆãƒªåŒæœŸå®¹é‡"
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3507,6 +3852,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3519,9 +3870,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr "Git"
@@ -3531,9 +3900,6 @@ msgstr "Git リãƒã‚¸ãƒˆãƒª URL"
msgid "Git revision"
msgstr "Git リビジョン"
-msgid "Git storage health information has been reset"
-msgstr "git ストレージã®æ­£å¸¸æ€§æƒ…å ±ãŒãƒªã‚»ãƒƒãƒˆã•ã‚Œã¾ã—ãŸ"
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3600,12 +3966,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr "自分ã®ãƒ•ã‚©ãƒ¼ã‚¯ã¸ç§»å‹•"
-
-msgid "GoToYourFork|Fork"
-msgstr "フォーク"
-
msgid "Google Code import"
msgstr ""
@@ -3636,21 +3996,36 @@ msgstr "グループ ID"
msgid "Group Runners"
msgstr "グループ Runner"
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr "グループã®è©³ç´°"
msgid "Group info:"
-msgstr ""
+msgstr "グループ情報:"
msgid "Group maintainers can register group runners in the %{link}"
msgstr "グループ Maintainer 㯠%{link} ã§ã‚°ãƒ«ãƒ¼ãƒ— Runner を登録ã§ãã¾ã™ã€‚"
-msgid "Group: %{group_name}"
+msgid "Group name"
msgstr ""
+msgid "Group: %{group_name}"
+msgstr "グループ:%{group_name}"
+
msgid "GroupRoadmap|From %{dateWord}"
msgstr "%{dateWord} ã‹ã‚‰"
@@ -3666,14 +4041,14 @@ msgstr "申ã—訳ã‚ã‚Šã¾ã›ã‚“ã€æ¤œç´¢ã«ãƒžãƒƒãƒã™ã‚‹ã‚¨ãƒ”ックã¯ã‚ã‚Š
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr "ロードマップã¯æ™‚é–“ã®çµŒéŽã¨ã¨ã‚‚ã«ã‚¨ãƒ”ックã®é€²è¡Œã‚’表示ã—ã¾ã™"
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "ロードマップを表示ã™ã‚‹ã«ã¯ã€äºˆå®šé–‹å§‹æ—¥ã‹äºˆå®šçµ‚了日をã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‹å­ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚¨ãƒ”ックã®1ã¤ã«è¿½åŠ ã—ã¦ãã ã•ã„。月表示ã§ã¯ã€å‰æœˆã€å½“月ã€ã‚‚ã—ãã¯5ヶ月先ã®ã‚¨ãƒ”ックã®ã¿ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ &ndash; %{startDate} 〜 %{endDate}"
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "ロードマップを表示ã™ã‚‹ã«ã¯ã€äºˆå®šé–‹å§‹æ—¥ã‹äºˆå®šçµ‚了日をã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‹å­ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚¨ãƒ”ックã®1ã¤ã«è¿½åŠ ã—ã¦ãã ã•ã„。四åŠæœŸè¡¨ç¤ºã§ã¯ã€å‰å››åŠæœŸã€å½“å››åŠæœŸã€ã‚‚ã—ãã¯4ã¤å…ˆã®å››åŠæœŸã¾ã§ã®ã‚¨ãƒ”ックã®ã¿ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ &ndash; %{startDate} 〜 %{endDate}"
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "ロードマップを表示ã™ã‚‹ã«ã¯ã€äºˆå®šé–‹å§‹æ—¥ã‹äºˆå®šçµ‚了日をã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‹å­ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚¨ãƒ”ックã®1ã¤ã«è¿½åŠ ã—ã¦ãã ã•ã„。週表示ã§ã¯ã€å…ˆé€±ã€ä»Šé€±ã€ã‚‚ã—ãã¯4週先ã¾ã§ã®ã‚¨ãƒ”ックã®ã¿ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ &ndash; %{startDate} 〜 %{endDate}"
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr "検索対象を広ã’ã‚‹ã«ã¯ã€ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã‚’変更ã™ã‚‹ã‹å‰Šé™¤ã—ã¦ãã ã•ã„。月表示ã§ã¯ã€å…ˆæœˆã€ä»Šæœˆã‚‚ã—ãã¯5ヶ月先ã¾ã§ã®ã‚¨ãƒ”ックã®ã¿ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ &ndash; %{startDate} 〜 %{endDate}"
@@ -3699,9 +4074,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "%{group} 内ã®ãƒ—ロジェクトを他ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¨å…±æœ‰ã—ãªã„よã†ã«ã™ã‚‹"
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "ã“ã®è¨­å®šã¯ %{ancestor_group} ã«é©ç”¨ã•ã‚Œã€ã‚µãƒ–グループã§ä¸Šæ›¸ãã•ã‚Œã¾ã™ã€‚"
@@ -3759,6 +4131,9 @@ msgstr "グループã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "グループメンãƒãƒ¼ã®æ¨©é™ç®¡ç†ã€ãŠã‚ˆã³ã‚°ãƒ«ãƒ¼ãƒ—内ã®å„プロジェクトã®ã‚¢ã‚¯ã‚»ã‚¹æ¨©é™ã‚’管ç†ã§ãã¾ã™ã€‚"
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«ãƒ—ロジェクトを作æˆã™ã‚‹ã€‚"
@@ -3771,20 +4146,20 @@ msgstr "グループを編集"
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr "グループã®å”¯ä¸€ã®ã‚ªãƒ¼ãƒŠãƒ¼ã¨ãªã£ã¦ã„ã‚‹ãŸã‚ã€ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‹ã‚‰é›¢è„±ã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。"
-msgid "GroupsTree|Filter by name..."
-msgstr "åå‰ã§çµžã‚Šè¾¼ã¿..."
-
msgid "GroupsTree|Leave this group"
msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã‹ã‚‰é›¢è„±ã™ã‚‹"
msgid "GroupsTree|Loading groups"
msgstr "グループã®èª­ã¿è¾¼ã¿ä¸­"
-msgid "GroupsTree|Sorry, no groups matched your search"
-msgstr "ã™ã¿ã¾ã›ã‚“ã€æ¤œç´¢ã«ä¸€è‡´ã™ã‚‹ã‚°ãƒ«ãƒ¼ãƒ—ãŒå­˜åœ¨ã—ã¾ã›ã‚“"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
-msgstr "ã™ã¿ã¾ã›ã‚“ã€æ¤œç´¢ã«ä¸€è‡´ã™ã‚‹ãƒ—ロジェクトã‹ã‚°ãƒ«ãƒ¼ãƒ—ãŒå­˜åœ¨ã—ã¾ã›ã‚“"
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
msgid "Have your users email"
msgstr "ユーザーã«ãƒ¡ãƒ¼ãƒ«ã‚’é€ä¿¡"
@@ -3825,6 +4200,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "éžè¡¨ç¤º"
@@ -3911,7 +4289,7 @@ msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commit
msgstr "GitHub を使用ã—ã¦ã„ã‚‹å ´åˆã€GitHub 上ã®ã‚³ãƒŸãƒƒãƒˆã‚„プルリクエスã‹ã‚‰ãƒ‘イプラインã®çŠ¶æ…‹ã‚’確èªã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚%{more_info_link}"
msgid "If you already have files you can push them using the %{link_to_cli} below."
-msgstr ""
+msgstr "ã™ã§ã«ãƒ•ã‚¡ã‚¤ãƒ«ãŒå­˜åœ¨ã™ã‚‹ã¨ãã¯ã€æ¬¡ã® %{link_to_cli} を使用ã—ã¦ãƒ•ã‚¡ã‚¤ãƒ«ã‚’プッシュã§ãã¾ã™ã€‚"
msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
msgstr ""
@@ -3988,6 +4366,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4016,32 +4397,32 @@ msgid "Install GitLab Runner"
msgstr ""
msgid "Install Runner on Kubernetes"
-msgstr ""
+msgstr "Kubernetes 㫠Runner をインストール"
msgid "Instance"
msgid_plural "Instances"
msgstr[0] "インスタンス"
msgid "Instance Statistics"
-msgstr ""
+msgstr "インスタンス統計"
msgid "Instance Statistics visibility"
msgstr ""
msgid "Instance does not support multiple Kubernetes clusters"
-msgstr ""
+msgstr "インスタンスã¯ãƒžãƒ«ãƒ Kubernetes クラスターをサãƒãƒ¼ãƒˆã—ã¦ã„ã¾ã›ã‚“"
msgid "Integrations"
-msgstr ""
+msgstr "インテグレーション"
msgid "Integrations Settings"
msgstr ""
msgid "Interested parties can even contribute by pushing commits if they want to."
-msgstr ""
+msgstr "貢献をã—ãŸã„関係者ã¯ã€ã‚³ãƒŸãƒƒãƒˆã‚’プッシュã™ã‚‹ã“ã¨ã§è²¢çŒ®ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
-msgstr ""
+msgstr "内部 - グループãŠã‚ˆã³å†…部プロジェクトã¯ã€ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ã„ã‚‹ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒè¦‹ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
msgid "Internal - The project can be accessed by any logged in user."
msgstr ""
@@ -4055,30 +4436,66 @@ msgstr "é–“éš”ã®ãƒ‘ターン"
msgid "Introducing Cycle Analytics"
msgstr "サイクル分æžã®ã”紹介"
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
msgid "Issue board focus mode"
-msgstr ""
+msgstr "課題ボード フォーカス モード"
msgid "Issue events"
msgstr "課題イベント"
msgid "IssueBoards|Board"
-msgstr ""
+msgstr "ボード"
msgid "IssueBoards|Boards"
-msgstr ""
+msgstr "ボード"
msgid "Issues"
msgstr "課題"
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
-msgstr ""
+msgstr "課題ã¨ã¯ãƒã‚°ã€ã‚¿ã‚¹ã‚¯ã€ã¾ãŸã¯è­°è«–ã®å¿…è¦ãªã‚¢ã‚¤ãƒ‡ã‚¢ã§ã™ã€‚ã¾ãŸã€èª²é¡Œã¯æ¤œç´¢ã‚„フィルター処ç†ãŒå¯èƒ½ã§ã™ã€‚"
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr "1月"
@@ -4094,9 +4511,6 @@ msgstr "ジョブãŒæ¶ˆåŽ»ã•ã‚Œã¾ã—ãŸ"
msgid "Jobs"
msgstr "ジョブ"
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4133,7 +4547,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4151,12 +4565,6 @@ msgstr "6月"
msgid "June"
msgstr "6月"
-msgid "Koding"
-msgstr "Koding"
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -4164,22 +4572,22 @@ msgid "Kubernetes Cluster"
msgstr "Kubernetes クラスター"
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
-msgstr ""
+msgstr "Kubernetes クラスターã®ä½œæˆä¸­ã«ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸ:%{timeout}"
msgid "Kubernetes cluster integration was not removed."
-msgstr ""
+msgstr "Kubernetes クラスターã®çµ±åˆã¯å‰Šé™¤ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸã€‚"
msgid "Kubernetes cluster integration was successfully removed."
-msgstr ""
+msgstr "Kubernetes クラスターã®çµ±åˆã¯æ­£å¸¸ã«å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚"
msgid "Kubernetes cluster was successfully updated."
-msgstr ""
+msgstr "Kubernetes クラスターã¯æ­£å¸¸ã«æ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚"
msgid "Kubernetes configured"
msgstr "Kubernetes 構æˆæ¸ˆã¿"
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
-msgstr ""
+msgstr "Kubernetes サービスã®çµ±åˆã¯å»ƒæ­¢ã•ã‚Œã¾ã—ãŸã€‚%{deprecated_message_content} æ–°ã—ã„<a href=\"%{url}\"/>Kubernetes クラスター</a> ã®ãƒšãƒ¼ã‚¸ã‚’使用ã—ã¦ãã ã•ã„"
msgid "LFS"
msgstr "LFS"
@@ -4215,7 +4623,7 @@ msgid "Labels can be applied to %{features}. Group labels are available for any
msgstr "ラベルを%{features} ã«é©ç”¨ã§ãã¾ã™ã€‚グループラベルã¯ã‚°ãƒ«ãƒ¼ãƒ—内ã®ã™ã¹ã¦ã®ãƒ—ロジェクトã§ä½¿ç”¨ã§ãã¾ã™ã€‚"
msgid "Labels can be applied to issues and merge requests to categorize them."
-msgstr ""
+msgstr "ラベルを使用ã—ã¦ã€èª²é¡Œã‚„マージリクエストを分類ã§ãã¾ã™ã€‚"
msgid "Labels can be applied to issues and merge requests."
msgstr "ラベルã¯èª²é¡Œã¨ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã«é©ç”¨ã§ãã¾ã™ã€‚"
@@ -4229,6 +4637,9 @@ msgstr "ラベルã®æ˜‡æ ¼"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] "éŽåŽ»%d日間"
@@ -4239,12 +4650,18 @@ msgstr "最新パイプライン"
msgid "Last commit"
msgstr "最新コミット"
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr "最終編集日 %{date}"
msgid "Last edited by %{name}"
msgstr "最終編集者 %{name}"
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr "最終更新"
@@ -4261,16 +4678,16 @@ msgid "Latest changes"
msgstr "最新ã®å¤‰æ›´"
msgid "Learn more"
-msgstr ""
+msgstr "詳細"
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
msgid "Learn more about Kubernetes"
-msgstr ""
+msgstr "Kubernetes ã®è©³ç´°"
msgid "Learn more about protected branches"
-msgstr ""
+msgstr "ä¿è­·ã•ã‚ŒãŸãƒ–ランãƒã«ã¤ã„ã¦ã®è©³ç´°"
msgid "Learn more in the"
msgstr "詳ã—ã見る:"
@@ -4293,6 +4710,15 @@ msgstr ""
msgid "License"
msgstr "ライセンス"
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4302,6 +4728,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4311,20 +4740,26 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
-msgid "LicenseManagement|License"
+msgid "LicenseManagement|Cancel"
msgstr ""
+msgid "LicenseManagement|License"
+msgstr "ライセンス"
+
msgid "LicenseManagement|License Management"
msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
msgid "LicenseManagement|Packages"
-msgstr ""
+msgstr "パッケージ"
msgid "LicenseManagement|Remove license"
msgstr ""
@@ -4332,9 +4767,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr "URL"
@@ -4360,6 +4801,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4405,9 +4849,12 @@ msgstr "ç¾åœ¨ã®ãƒ—ロジェクトã¯ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™"
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
-msgid "Logs"
+msgid "Login with smartcard"
msgstr ""
+msgid "Logs"
+msgstr "ログ"
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
@@ -4474,13 +4921,43 @@ msgstr "Todo を完了ã«ã™ã‚‹"
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4492,6 +4969,12 @@ msgstr "5月"
msgid "Median"
msgstr "中央値"
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr "メンãƒãƒ¼"
@@ -4523,6 +5006,21 @@ msgid "Merge requests"
msgstr "マージリクエスト"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr "マージリクエストã¨ã¯ã€ãƒ—ロジェクトã«åŠ ãˆãŸå¤‰æ›´ã‚’æ示ã—ã€ãã®å¤‰æ›´ã«ã¤ã„ã¦ä»–ã®ãƒ¡ãƒ³ãƒãƒ¼ã¨è©±ã—åˆã†ãŸã‚ã®å ´æ‰€ã§ã™"
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
msgstr ""
msgid "MergeRequests|Resolve this discussion in a new issue"
@@ -4534,9 +5032,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr "検討ã®æ›´æ–°ã«å¤±æ•—ã—ã¾ã—ãŸ"
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4546,6 +5041,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr "マージ済ã¿"
@@ -4561,6 +5062,9 @@ msgstr "メトリクス - Influx"
msgid "Metrics - Prometheus"
msgstr "メトリクス - Prometheus"
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr "ビジãƒã‚¹"
@@ -4742,7 +5246,7 @@ msgid "More"
msgstr ""
msgid "More actions"
-msgstr "ãã®ä»–ã®æ“作"
+msgstr ""
msgid "More info"
msgstr ""
@@ -4777,6 +5281,9 @@ msgstr ""
msgid "Name:"
msgstr "åå‰:"
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr "ヘルプ"
@@ -4895,6 +5402,12 @@ msgstr "Gitaly サーãƒãƒ¼ã«æŽ¥ç¶šã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ログを確èªã
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr "期é™ãªã—"
@@ -4904,9 +5417,6 @@ msgstr ""
msgid "No file chosen"
msgstr "ファイルãŒé¸æŠžã•ã‚Œã¦ã„ã¾ã›ã‚“"
-msgid "No files found"
-msgstr "ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ"
-
msgid "No files found."
msgstr "ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。"
@@ -4916,6 +5426,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -4943,6 +5456,9 @@ msgstr ""
msgid "No repository"
msgstr "リãƒã‚¸ãƒˆãƒªãŒã‚ã‚Šã¾ã›ã‚“"
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr "スケジュールãªã—"
@@ -4974,11 +5490,14 @@ msgid "Not available for protected branches"
msgstr "ä¿è­·ã•ã‚ŒãŸãƒ–ランãƒã§ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“"
msgid "Not confidential"
-msgstr ""
+msgstr "機密ã§ã¯ãªã„"
msgid "Not enough data"
msgstr "データä¸è¶³"
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr "マスターブランãƒã¯è‡ªå‹•çš„ã«ä¿è­·ã•ã‚Œã‚‹ã“ã¨ã«ç•™æ„ã—ã¦ãã ã•ã„。%{link_to_protected_branches}"
@@ -4986,17 +5505,29 @@ msgid "Note: As an administrator you may like to configure %{github_integration_
msgstr "注: 管ç†è€…ã¨ã—ã¦%{github_integration_link} を設定ã™ã‚‹ã¨ã€GitHub 経由ã®ãƒ­ã‚°ã‚¤ãƒ³ã‚’許å¯ã—ã€å€‹äººç”¨ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ã‚’生æˆã›ãšã«ãƒªãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
-msgstr ""
+msgstr "注:管ç†è€…ã¨ã—ã¦%{github_integration_link} を設定ã™ã‚‹ã¨ã€GitHub 経由ã®ãƒ­ã‚°ã‚¤ãƒ³ã‚’許å¯ã—ã€å€‹äººç”¨ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ã‚’生æˆã›ãšã«ãƒªãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr "注: GitLab ã®ç®¡ç†è€…ã«%{github_integration_link} を設定ã—ã¦ã€GitHub 経由ã®ãƒ­ã‚°ã‚¤ãƒ³ã‚’許å¯ã—ã€å€‹äººç”¨ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ã‚’生æˆã›ãšã«ãƒªãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã§ããªã„ã‹å•ã„åˆã‚ã›ãã ã•ã„。"
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
-msgstr ""
+msgstr "注: GitLab ã®ç®¡ç†è€…ã«%{github_integration_link} を設定ã—ã¦ã€GitHub 経由ã®ãƒ­ã‚°ã‚¤ãƒ³ãŒè¨±å¯ã—ã€å€‹äººç”¨ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ã‚’生æˆã›ãšã«ãƒªãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆã§ããªã„ã‹å•ã„åˆã‚ã›ãã ã•ã„。"
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr "イベント通知"
@@ -5069,9 +5600,6 @@ msgstr "11月"
msgid "November"
msgstr "11月"
-msgid "Number of access attempts"
-msgstr "アクセス試行回数"
-
msgid "OK"
msgstr "OK"
@@ -5097,9 +5625,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5121,6 +5646,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr "Xcode ã§é–‹ã"
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr "サイドãƒãƒ¼ã‚’é–‹ã"
@@ -5145,6 +5673,21 @@ msgstr "æ–°è¦ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã§é–‹ã"
msgid "Operations"
msgstr "é‹ç”¨"
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5164,7 +5707,7 @@ msgid "Other information"
msgstr "ãã®ä»–ã®æƒ…å ±"
msgid "Otherwise it is recommended you start with one of the options below."
-msgstr ""
+msgstr "ãã†ã§ãªã„å ´åˆã¯ã€æ¬¡ã®ã„ãšã‚Œã‹ã®ã‚ªãƒ—ションã§é–‹å§‹ã™ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™ã€‚"
msgid "Outbound requests"
msgstr ""
@@ -5185,7 +5728,7 @@ msgid "Package was removed"
msgstr ""
msgid "Packages"
-msgstr ""
+msgstr "パッケージ"
msgid "Pages"
msgstr "Pages"
@@ -5194,16 +5737,16 @@ msgid "Pagination|Last »"
msgstr "最後 »"
msgid "Pagination|Next"
-msgstr ""
+msgstr "次ページ"
msgid "Pagination|Prev"
-msgstr ""
+msgstr "å‰ãƒšãƒ¼ã‚¸"
msgid "Pagination|« First"
msgstr "« 最åˆ"
msgid "Part of merge request changes"
-msgstr ""
+msgstr "マージリクエストã§ã®å¤‰æ›´ç®‡æ‰€"
msgid "Password"
msgstr "パスワード"
@@ -5211,11 +5754,14 @@ msgstr "パスワード"
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr "ã‚ãªãŸã® SSH 公開éµã‚’貼り付ã‘ã¾ã™ã€‚ã“ã®éµã¯é€šå¸¸ã€ãƒ•ã‚¡ã‚¤ãƒ« '~/.ssh/id_rsa.pub' 内ã«ã‚ã‚Šã€'ssh-rsa' ã¨ã„ã†æ–‡å­—列ã‹ã‚‰å§‹ã¾ã‚Šã¾ã™ã€‚SSH ã®ç§˜å¯†éµã‚’使用ã—ãªã„よã†ã«ã—ã¦ãã ã•ã„。"
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr "パス:"
msgid "Pause"
-msgstr ""
+msgstr "åœæ­¢"
msgid "Paused Runners don't accept new jobs"
msgstr ""
@@ -5238,15 +5784,15 @@ msgstr "パフォーマンスã®æœ€é©åŒ–"
msgid "Permissions"
msgstr "権é™"
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
msgid "Personal Access Token"
msgstr "個人ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³"
msgid "Pipeline"
msgstr "パイプライン"
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
-msgstr ""
-
msgid "Pipeline Health"
msgstr "パイプラインã®é€²æ—状æ³"
@@ -5338,13 +5884,13 @@ msgid "Pipelines|Continuous Integration can help catch bugs by running your test
msgstr ""
msgid "Pipelines|Get started with Pipelines"
-msgstr ""
+msgstr "パイプラインã®åˆ©ç”¨ã‚’開始ã™ã‚‹"
msgid "Pipelines|Loading Pipelines"
msgstr "パイプラインを読ã¿è¾¼ã¿ä¸­"
msgid "Pipelines|Project cache successfully reset."
-msgstr ""
+msgstr "プロジェクトã®ã‚­ãƒ£ãƒƒã‚·ãƒ¥ã‚’正常ã«ãƒªã‚»ãƒƒãƒˆã—ã¾ã—ãŸã€‚"
msgid "Pipelines|Run Pipeline"
msgstr "パイプライン実行"
@@ -5353,15 +5899,18 @@ msgid "Pipelines|Something went wrong while cleaning runners cache."
msgstr ""
msgid "Pipelines|There are currently no %{scope} pipelines."
-msgstr ""
+msgstr "%{scope} パイプラインã¯ç¾åœ¨ã‚ã‚Šã¾ã›ã‚“。"
msgid "Pipelines|There are currently no pipelines."
-msgstr ""
+msgstr "パイプラインã¯ç¾åœ¨ã‚ã‚Šã¾ã›ã‚“。"
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr "ã“ã®ãƒ—ロジェクトã¯ç¾åœ¨ãƒ‘イプラインを実行ã™ã‚‹ã‚ˆã†ã«è¨­å®šã•ã‚Œã¦ã„ã¾ã›ã‚“。"
+
+msgid "Pipeline|Commit"
msgstr ""
msgid "Pipeline|Create for"
@@ -5370,9 +5919,15 @@ msgstr "実行対象"
msgid "Pipeline|Create pipeline"
msgstr "パイプラインを作æˆ"
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr "パイプラインを実行"
@@ -5382,6 +5937,12 @@ msgstr "ブランãƒã®æ¤œç´¢"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr "ã“ã®å®Ÿè¡Œã§ä½¿ç”¨ã•ã‚Œã‚‹å¤‰æ•°ã®å€¤ã‚’指定ã—ã¾ã™ã€‚ %{settings_link} ã§æŒ‡å®šã•ã‚ŒãŸå€¤ãŒãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚"
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr "パイプラインã®åœæ­¢"
@@ -5409,12 +5970,6 @@ msgstr "ステージã‚ã‚Š"
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr "PlantUML"
@@ -5424,12 +5979,18 @@ msgstr "実行"
msgid "Please accept the Terms of Service before continuing."
msgstr "続ã‘ã‚‹å‰ã«ã€åˆ©ç”¨è¦ç´„ã«åŒæ„ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5442,11 +6003,14 @@ msgstr "reCAPTCHA を解決ã—ã¦ãã ã•ã„"
msgid "Please try again"
msgstr "ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„"
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr "リãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã§ãã‚‹ã¾ã§ã€ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„。完了ã™ã‚‹ã¨ã€ç”»é¢ãŒè‡ªå‹•çš„ã«æ›´æ–°ã•ã‚Œã¾ã™ã€‚"
msgid "Please wait while we import the repository for you. Refresh at will."
-msgstr ""
+msgstr "リãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆã—ã¦ã„ã‚‹ã®ã§ã€ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„。完了ã™ã‚‹ã¨ã€ç”»é¢ãŒè‡ªå‹•çš„ã«æ›´æ–°ã•ã‚Œã¾ã™ã€‚"
msgid "Preferences"
msgstr "基本設定"
@@ -5454,9 +6018,18 @@ msgstr "基本設定"
msgid "Preferences|Navigation theme"
msgstr "ナビゲーションテーマ"
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5473,13 +6046,13 @@ msgid "Prioritized label"
msgstr "優先ラベル"
msgid "Private - Project access must be granted explicitly to each user."
-msgstr ""
+msgstr "プライベート - å„ユーザーã«ãƒ—ロジェクトã®ã‚¢ã‚¯ã‚»ã‚¹æ¨©é™ã‚’明示的ã«è¨±å¯ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
msgid "Private - The group and its projects can only be viewed by members."
msgstr "プライベート - グループã¨ãƒ—ロジェクトã¯ãƒ¡ãƒ³ãƒãƒ¼ã®ã¿ãŒé–²è¦§ã§ãã¾ã™ã€‚"
msgid "Private projects can be created in your personal namespace with:"
-msgstr ""
+msgstr "ã‚ãªãŸå€‹äººã®åå‰ç©ºé–“ã«ãƒ—ライベートプロジェクトを作æˆã§ãã¾ã™:"
msgid "Profile"
msgstr "プロフィール"
@@ -5494,7 +6067,7 @@ msgid "Profiles| You are going to change the username %{currentUsernameBold} to
msgstr ""
msgid "Profiles|Account scheduled for removal."
-msgstr ""
+msgstr "削除予定ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã§ã™ã€‚"
msgid "Profiles|Add key"
msgstr "キーを追加"
@@ -5502,15 +6075,30 @@ msgstr "キーを追加"
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr "ユーザーåã®å¤‰æ›´"
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr "ç¾åœ¨ã®ãƒ‘ス: %{path}"
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr "アカウント削除"
@@ -5523,46 +6111,136 @@ msgstr "ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã‚’削除ã—ã¾ã™ã‹ï¼Ÿ"
msgid "Profiles|Deleting an account has the following effects:"
msgstr "アカウントを削除ã™ã‚‹ã¨æ¬¡ã®ã‚ˆã†ãªå½±éŸ¿ãŒã‚ã‚Šã¾ã™:"
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr "パスワードãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“"
msgid "Profiles|Invalid username"
msgstr "ユーザーåãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“"
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr "パス"
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "確èªã®ãŸã‚ %{confirmationValue} を入力ã—ã¦ãã ã•ã„:"
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr "ユーザーåã‚’æ›´æ–°"
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr "ユーザーåã®å¤‰æ›´ã«å¤±æ•—ã—ã¾ã—㟠- %{message}"
msgid "Profiles|Username successfully changed"
msgstr "ユーザーåã¯æ­£å¸¸ã«å¤‰æ›´ã•ã‚Œã¾ã—ãŸ"
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr "ã“ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã‚’削除ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“"
msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
-msgstr ""
+msgstr "アカウントを削除ã™ã‚‹å‰ã«ã“れらã®ã‚°ãƒ«ãƒ¼ãƒ—を削除ã€ã¾ãŸã¯æ‰€æœ‰æ¨©ã‚’譲渡ã—ã¦ãã ã•ã„。"
msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr "ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ç¾åœ¨ã“れらã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ã‚ªãƒ¼ãƒŠãƒ¼ã§ã™:"
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
msgid "Profiles|Your status"
@@ -5601,6 +6279,9 @@ msgstr "'%{project_name}' プロジェクトã¯æ­£å¸¸ã«æ›´æ–°ã•ã‚Œã¾ã—ãŸã€‚
msgid "Project Badges"
msgstr "プロジェクトãƒãƒƒã‚¸"
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr "ユーザーã”ã¨ã«ãƒ—ロジェクトアクセスã®æ¨©é™ã‚’指定ã—ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
@@ -5628,6 +6309,9 @@ msgstr "プロジェクトã®ã‚¨ã‚¯ã‚¹ãƒãƒ¼ãƒˆã‚’開始ã—ã¾ã—ãŸã€‚ダウン
msgid "Project name"
msgstr "プロジェクトå"
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "講読"
@@ -5655,11 +6339,32 @@ msgstr "記録ãªã—"
msgid "ProjectLifecycle|Stage"
msgstr "ステージ"
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
msgid "ProjectSettings|Badges"
-msgstr ""
+msgstr "ãƒãƒƒã‚¸"
msgid "ProjectSettings|Contact an admin to change this setting."
msgstr "ã“ã®è¨­å®šã‚’変更ã™ã‚‹ã«ã¯ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
@@ -5697,11 +6402,14 @@ msgstr "プロジェクト"
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr "よã使ã†ãƒ—ロジェクト"
msgid "ProjectsDropdown|Loading projects"
-msgstr ""
+msgstr "プロジェクトをロード中"
msgid "ProjectsDropdown|Projects you visit often will appear here"
msgstr "よã使ã†ãƒ—ロジェクトã¯ã“ã“ã«è¡¨ç¤ºã•ã‚Œã¾ã™"
@@ -5710,7 +6418,7 @@ msgid "ProjectsDropdown|Search your projects"
msgstr "プロジェクトを検索"
msgid "ProjectsDropdown|Something went wrong on our end."
-msgstr ""
+msgstr "å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "ProjectsDropdown|Sorry, no projects matched your search"
msgstr "検索æ¡ä»¶ã«ä¸€è‡´ã—ãŸãƒ—ロジェクトã¯ã‚ã‚Šã¾ã›ã‚“ã§ã—ãŸ"
@@ -5755,19 +6463,16 @@ msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr "%{metrics} ã® %{exporters} ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ"
msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
-msgstr ""
+msgstr "<p class=\"text-tertiary\"><a href=\"%{docsUrl}\">共通メトリクス</a>ã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ</p>"
msgid "PrometheusService|Active"
msgstr "アクティブ"
msgid "PrometheusService|Auto configuration"
-msgstr ""
+msgstr "自動設定"
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
-msgstr ""
-
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
+msgstr "プロジェクト環境を監視ã™ã‚‹ãŸã‚ã€ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¼ã« Prometheus を自動的ã«ãƒ‡ãƒ—ロイã—設定ã™ã‚‹"
msgid "PrometheusService|Common metrics"
msgstr "共通メトリクス"
@@ -5794,13 +6499,13 @@ msgid "PrometheusService|Manual configuration"
msgstr "手動構æˆ"
msgid "PrometheusService|Metrics"
-msgstr ""
+msgstr "メトリクス一覧"
msgid "PrometheusService|Missing environment variable"
msgstr "未設定ã®ç’°å¢ƒå¤‰æ•°"
msgid "PrometheusService|More information"
-msgstr ""
+msgstr "詳細情報"
msgid "PrometheusService|New metric"
msgstr "æ–°è¦ãƒ¡ãƒˆãƒªã‚¯ã‚¹"
@@ -5809,19 +6514,19 @@ msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example
msgstr ""
msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
-msgstr ""
+msgstr "Prometheus ã¯ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¼ä¸Šã§è‡ªå‹•çš„ã«ç®¡ç†ã•ã‚Œã¦ã„ã¾ã™"
msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
msgstr ""
msgid "PrometheusService|Time-series monitoring service"
-msgstr ""
+msgstr "時系列監視サービス"
msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
msgstr ""
msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
-msgstr ""
+msgstr "クラスター㫠Prometheus をインストールã™ã‚‹ã«ã¯ã€ä»¥ä¸‹ã®æ‰‹å‹•è¨­å®šã‚’無効ã«ã—ã¦ãã ã•ã„"
msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
msgstr ""
@@ -5830,7 +6535,7 @@ msgid "Promote"
msgstr "昇格"
msgid "Promote these project milestones into a group milestone."
-msgstr ""
+msgstr "ã“れらã®ãƒ—ロジェクトマイルストーンをグループマイルストーンã«æ˜‡æ ¼ã™ã‚‹"
msgid "Promote to Group Milestone"
msgstr "グループマイルストーンã«æ˜‡æ ¼"
@@ -5908,7 +6613,7 @@ msgid "Pseudonymizer data collection"
msgstr ""
msgid "Public - The group and any public projects can be viewed without any authentication."
-msgstr ""
+msgstr "公開- グループãŠã‚ˆã³å…¬é–‹ãƒ—ロジェクトã¯èªè¨¼ç„¡ã—ã§é–²è¦§ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™"
msgid "Public - The project can be accessed without any authentication."
msgstr "公開 - プロジェクトã¯èªè¨¼ç„¡ã—ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™"
@@ -5932,7 +6637,7 @@ msgid "Push project from command line"
msgstr "コマンドラインã‹ã‚‰ãƒ—ロジェクトをプッシュ"
msgid "Push to create a project"
-msgstr ""
+msgstr "プッシュã—ã¦ãƒ—ロジェクトを作æˆã™ã‚‹"
msgid "PushRule|Committer restriction"
msgstr "コミッター制é™"
@@ -5947,7 +6652,7 @@ msgid "Quarters"
msgstr ""
msgid "Quick actions can be used in the issues description and comment boxes."
-msgstr ""
+msgstr "クイックアクションã¯èª²é¡Œã®èª¬æ˜Žã¨ã‚³ãƒ¡ãƒ³ãƒˆæ¬„ã§ä½¿ç”¨ã§ãã¾ã™ã€‚"
msgid "Read more"
msgstr "続ãを読む"
@@ -5961,6 +6666,12 @@ msgstr "Readme"
msgid "Real-time features"
msgstr "リアルタイム機能"
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr "å‚ç…§:"
@@ -5981,7 +6692,7 @@ msgid "Register / Sign In"
msgstr "登録 / サインイン"
msgid "Register and see your runners for this group."
-msgstr ""
+msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã® Runner ã®ç™»éŒ²ã¨ç¢ºèª"
msgid "Register and see your runners for this project."
msgstr ""
@@ -6022,12 +6733,21 @@ msgstr "Runner を削除"
msgid "Remove avatar"
msgstr "ã‚¢ãƒã‚¿ãƒ¼ã‚’削除"
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr "優先度を削除"
msgid "Remove project"
msgstr "プロジェクトを削除"
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6037,6 +6757,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr "èªè¨¼ã®ä¿®å¾©"
@@ -6046,18 +6769,33 @@ msgstr ""
msgid "Repo by URL"
msgstr "リãƒã‚¸ãƒˆãƒª URL"
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6070,6 +6808,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6086,7 +6827,7 @@ msgid "Repository has no locks."
msgstr "リãƒã‚¸ãƒˆãƒªã¯ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã›ã‚“。"
msgid "Repository maintenance"
-msgstr ""
+msgstr "リãƒã‚¸ãƒˆãƒªã®ä¿å®ˆ"
msgid "Repository mirror"
msgstr "リãƒã‚¸ãƒˆãƒªãƒŸãƒ©ãƒ¼"
@@ -6103,12 +6844,12 @@ msgstr "アクセス権é™ã‚’リクエストã™ã‚‹"
msgid "Requests Profiles"
msgstr ""
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "GitLab ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹éš›ã«ã€ã™ã¹ã¦ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒåˆ©ç”¨è¦ç´„ã«åŒæ„ã™ã‚‹ã“ã¨ã‚’è¦æ±‚ã—ã¾ã™ã€‚"
-msgid "Reset git storage health information"
-msgstr "git ストレージã®æ­£å¸¸æ€§æƒ…報をリセット"
-
msgid "Reset health check access token"
msgstr "正常性ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³ã‚’リセット"
@@ -6124,14 +6865,26 @@ msgstr "ソースブランãƒã§ã®ç«¶åˆã‚’解決ã™ã‚‹"
msgid "Resolve discussion"
msgstr "検討を解決"
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr "å†é–‹"
msgid "Retry"
-msgstr ""
+msgstr "å†è©¦è¡Œ"
msgid "Retry this job"
msgstr "ジョブをå†è©¦è¡Œã—ã¦ãã ã•ã„"
@@ -6144,7 +6897,7 @@ msgstr ""
msgid "Reveal value"
msgid_plural "Reveal values"
-msgstr[0] ""
+msgstr[0] "値を表示ã™ã‚‹"
msgid "Revert this commit"
msgstr "ã“ã®ã‚³ãƒŸãƒƒãƒˆã‚’リãƒãƒ¼ãƒˆ"
@@ -6159,7 +6912,7 @@ msgid "Review the process for configuring service providers in your identity pro
msgstr ""
msgid "Reviewing"
-msgstr ""
+msgstr "レビュー中"
msgid "Reviewing (merge request !%{mergeRequestId})"
msgstr ""
@@ -6176,9 +6929,24 @@ msgstr "外部リãƒã‚¸ãƒˆãƒªç”¨ CI/CD パイプラインを実行"
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr "Runner トークン"
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr "Runner"
@@ -6188,6 +6956,12 @@ msgstr "Runner API"
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr "Runner ã¯åˆ¥ã€…ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼ã€ã‚µãƒ¼ãƒãƒ¼ã€ã•ã‚‰ã«ã¯ã‚ãªãŸã®ãƒ­ãƒ¼ã‚«ãƒ«ãƒžã‚·ãƒ¼ãƒ³ã«ã‚‚é…ç½®ã§ãã¾ã™ã€‚"
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6212,6 +6986,9 @@ msgstr "SAML シングル サインオン"
msgid "SAML Single Sign On Settings"
msgstr "SAML シングル サインオンã®è¨­å®š"
+msgid "SAST"
+msgstr "SAST"
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr "SAML トークン㮠SHA1 フィンガープリントã§è¨¼æ˜Žæ›¸ã«ç½²åã—ã¾ã™ã€‚ã“ã‚Œã¯ã‚µãƒ ãƒ—リントã¨å‘¼ã°ã‚Œã‚¢ã‚¤ãƒ‡ãƒ³ãƒ†ã‚£ãƒ†ã‚£ãƒ—ロãƒã‚¤ãƒ€ãƒ¼ã‹ã‚‰å–å¾—ã§ãã¾ã™ã€‚"
@@ -6236,6 +7013,9 @@ msgstr ""
msgid "Save changes"
msgstr "変更をä¿å­˜"
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "パイプラインスケジュールをä¿å­˜"
@@ -6290,15 +7070,24 @@ msgstr "マージリクエストを検索"
msgid "Search milestones"
msgstr "マイルストーンを検索"
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr "プロジェクトを検索"
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr "ユーザーを検索"
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6323,13 +7112,7 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
-msgstr "失敗情報をリセットã™ã‚‹ã¾ã§ã®ç§’æ•°"
-
-msgid "Seconds to wait for a storage access attempt"
-msgstr ""
-
-msgid "Secret:"
+msgid "Secret"
msgstr ""
msgid "Security"
@@ -6338,11 +7121,46 @@ msgstr "セキュリティ"
msgid "Security Dashboard"
msgstr "セキュリティダッシュボード"
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6360,7 +7178,13 @@ msgstr "é¸æŠž"
msgid "Select Archive Format"
msgstr "アーカイブã®ãƒ•ã‚©ãƒ¼ãƒžãƒƒãƒˆã‚’é¸æŠž"
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
+msgstr "プロジェクトをフォークã™ã‚‹åå‰ç©ºé–“ã‚’é¸æŠžã—ã¦ãã ã•ã„"
+
+msgid "Select a template repository"
msgstr ""
msgid "Select a timezone"
@@ -6393,6 +7217,9 @@ msgstr "ソースブランãƒã‚’é¸æŠž"
msgid "Select target branch"
msgstr "ターゲットブランãƒã‚’é¸æŠž"
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6405,6 +7232,9 @@ msgstr ""
msgid "Send email"
msgstr "メールをé€ä¿¡"
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr "9月"
@@ -6424,14 +7254,17 @@ msgid "Service URL"
msgstr "サービス URL"
msgid "Session expiration, projects limit and attachment size."
-msgstr ""
+msgstr "セッションã®æœ‰åŠ¹æœŸé™ã€ãƒ—ロジェクトã®ä¸Šé™ã€æ·»ä»˜ãƒ•ã‚¡ã‚¤ãƒ«ã®ã‚µã‚¤ã‚º"
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "%{protocol} プロコトル経由ã§ãƒ—ルã€ãƒ—ッシュã™ã‚‹ãŸã‚ã«ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ãƒ‘スワードを設定。"
-msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgid "Set a template repository for projects in this group"
msgstr ""
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr "デフォルトを設定ã—ã€å¯è¦–性レベルを制é™ã—ã¾ã™ã€‚インãƒãƒ¼ãƒˆã‚½ãƒ¼ã‚¹ã¨ git アクセスプロトコルを設定ã—ã¾ã™ã€‚"
+
msgid "Set instance-wide template repository"
msgstr ""
@@ -6439,7 +7272,7 @@ msgid "Set max session time for web terminal."
msgstr ""
msgid "Set notification email for abuse reports."
-msgstr ""
+msgstr "迷惑行為レãƒãƒ¼ãƒˆã®é€šçŸ¥ãƒ¡ãƒ¼ãƒ«ã‚’設定ã™ã‚‹ã€‚"
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
msgstr ""
@@ -6447,8 +7280,11 @@ msgstr ""
msgid "Set up CI/CD"
msgstr "CI/CD を設定"
-msgid "Set up Koding"
-msgstr "Koding を設定"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
@@ -6459,15 +7295,33 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "パスワードを設定"
-msgid "Settings"
-msgstr "設定"
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
msgstr ""
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr "設定"
+
msgid "Share"
msgstr "共有"
@@ -6477,6 +7331,9 @@ msgstr "メンãƒãƒ¼ã¨<strong>%{sso_label}</strong>を共有ã™ã‚‹ã¨ã€è‡ªèº«ã
msgid "Shared Runners"
msgstr "共有 Runner"
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6545,7 +7402,7 @@ msgid "Sign out"
msgstr "サインアウト"
msgid "Sign-in restrictions"
-msgstr ""
+msgstr "サインインã®åˆ¶é™"
msgid "Sign-up restrictions"
msgstr "サインアップã®åˆ¶é™"
@@ -6559,12 +7416,18 @@ msgstr "é™çš„ãªã‚¦ã‚§ãƒ–サイトã®ã‚µã‚¤ã‚ºã¨ãƒ‰ãƒ¡ã‚¤ãƒ³ã®è¨­å®š"
msgid "Slack application"
msgstr "Slack アプリケーション"
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr "スニペット"
@@ -6572,7 +7435,7 @@ msgid "Something went wrong on our end"
msgstr ""
msgid "Something went wrong on our end."
-msgstr ""
+msgstr "å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "Something went wrong on our end. Please try again!"
msgstr ""
@@ -6592,9 +7455,15 @@ msgstr "%{issuable} を解決中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚ã¨ã§ã‚‚ã†
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr "グループメンãƒãƒ¼ã®è²¢çŒ®åº¦ã‚’å–得中ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6607,15 +7476,27 @@ msgstr "%{issuable} ã®å†é–‹å‡¦ç†ä¸­ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚ã¨ã§
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr "ã“ã®æ¤œè¨Žã‚’解決ã—ã¦ã„ã‚‹ã¨ãã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
-msgid "Something went wrong. Please try again."
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
msgstr ""
+msgid "Something went wrong. Please try again."
+msgstr "å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚å†è©¦è¡Œã—ã¦ãã ã•ã„。"
+
msgid "Sorry, no epics matched your search"
msgstr "申ã—訳ã‚ã‚Šã¾ã›ã‚“ã€æ¤œç´¢ã«ä¸€è‡´ã™ã‚‹ã‚¨ãƒ”ックã¯ã‚ã‚Šã¾ã›ã‚“"
-msgid "Sort by"
+msgid "Sorry, no projects matched your search"
msgstr ""
+msgid "Sort by"
+msgstr "並ã¹æ›¿ãˆ"
+
msgid "SortOptions|Access level, ascending"
msgstr "アクセスレベル昇順"
@@ -6641,6 +7522,9 @@ msgid "SortOptions|Largest group"
msgstr "グループã®å¤§ãã„é †"
msgid "SortOptions|Largest repository"
+msgstr "リãƒã‚¸ãƒˆãƒªã®å¤§ãã„é †"
+
+msgid "SortOptions|Last Contact"
msgstr ""
msgid "SortOptions|Last created"
@@ -6662,10 +7546,10 @@ msgid "SortOptions|Milestone"
msgstr "マイルストーン順"
msgid "SortOptions|Milestone due later"
-msgstr ""
+msgstr "マイルストーン期é™ã®é…ã„é †"
msgid "SortOptions|Milestone due soon"
-msgstr ""
+msgstr "マイルストーン期é™ã®è¿‘ã„é †"
msgid "SortOptions|More weight"
msgstr "ウエイトãŒå¤§ãã„é †"
@@ -6673,6 +7557,9 @@ msgstr "ウエイトãŒå¤§ãã„é †"
msgid "SortOptions|Most popular"
msgstr "人気順"
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr "åå‰"
@@ -6698,11 +7585,14 @@ msgid "SortOptions|Popularity"
msgstr "人気順"
msgid "SortOptions|Priority"
-msgstr ""
+msgstr "優先度順"
msgid "SortOptions|Recent sign in"
msgstr "最近ã®ã‚µã‚¤ãƒ³ã‚¤ãƒ³é †"
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr "å¤ã„é †"
@@ -6716,7 +7606,7 @@ msgid "Source"
msgstr "ソース"
msgid "Source (branch or tag)"
-msgstr ""
+msgstr "ソース (ブランãƒã‹ã‚¿ã‚°)"
msgid "Source code"
msgstr "ソースコード"
@@ -6773,24 +7663,39 @@ msgid "Starred Projects' Activity"
msgstr "スター付ãプロジェクトã®æ´»å‹•"
msgid "Starred projects"
-msgstr ""
+msgstr "スター付ãプロジェクト"
msgid "Start a %{new_merge_request} with these changes"
msgstr "ã“ã®å¤‰æ›´ã§ %{new_merge_request} を作æˆã™ã‚‹"
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "Runner ã‚’èµ·å‹•!"
-msgid "Started"
+msgid "Start your trial"
msgstr ""
+msgid "Started"
+msgstr "開始済ã¿"
+
msgid "Starts at (UTC)"
-msgstr ""
+msgstr "開始時刻 (UTC)"
msgid "State your message to activate"
msgstr ""
msgid "Status"
+msgstr "状態"
+
+msgid "Stop environment"
msgstr ""
msgid "Stop impersonation"
@@ -6802,6 +7707,9 @@ msgstr "ã“ã®ç’°å¢ƒã‚’åœæ­¢ã™ã‚‹"
msgid "Stopped"
msgstr "åœæ­¢ä¸­"
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr "ストレージ"
@@ -6811,9 +7719,15 @@ msgstr ""
msgid "Subgroups"
msgstr "サブグループ"
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6826,6 +7740,12 @@ msgstr "グループレベルã§è³¼èª­ã™ã‚‹"
msgid "Subscribe at project level"
msgstr "プロジェクトレベルã§è³¼èª­ã™ã‚‹"
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "ブランãƒãƒ»ã‚¿ã‚°åˆ‡ã‚Šæ›¿ãˆ"
@@ -6839,11 +7759,14 @@ msgid "System Info"
msgstr "システム情報"
msgid "System header and footer:"
-msgstr "システムヘッダーã¨ãƒ•ãƒƒã‚¿ãƒ¼ï¼š"
+msgstr "システムヘッダーã¨ãƒ•ãƒƒã‚¿ãƒ¼:"
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] "タグ(%{tag_count})"
@@ -6858,13 +7781,13 @@ msgid "Tags:"
msgstr "ã‚¿ã‚°:"
msgid "TagsPage|Browse commits"
-msgstr ""
+msgstr "コミットを表示"
msgid "TagsPage|Browse files"
-msgstr ""
+msgstr "ファイルを表示"
msgid "TagsPage|Can't find HEAD commit for this tag"
-msgstr ""
+msgstr "ã“ã®ã‚¿ã‚°ã® HEAD コミットãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
msgid "TagsPage|Cancel"
msgstr "キャンセル"
@@ -6876,7 +7799,7 @@ msgid "TagsPage|Delete tag"
msgstr "タグ削除"
msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
-msgstr ""
+msgstr "%{tag_name} ã‚¿ã‚°ã®å‰Šé™¤ã¯ã‚„ã‚Šç›´ã—ãŒã§ãã¾ã›ã‚“。よã‚ã—ã„ã§ã—ょã†ã‹ï¼Ÿ"
msgid "TagsPage|Edit release notes"
msgstr "リリースノートを編集"
@@ -6906,13 +7829,13 @@ msgid "TagsPage|Repository has no tags yet."
msgstr ""
msgid "TagsPage|Sort by"
-msgstr ""
+msgstr "並ã¹æ›¿ãˆ"
msgid "TagsPage|Tags"
msgstr "タグ一覧"
msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
-msgstr ""
+msgstr "ã‚¿ã‚°ã¯ã€å±¥æ­´ã®ç‰¹å®šã®ä½ç½®ã‚’é‡è¦ãªã‚‚ã®ã¨ã—ã¦ãƒžãƒ¼ã‚¯ã™ã‚‹æ©Ÿèƒ½ã‚’æä¾›ã—ã¾ã™"
msgid "TagsPage|This tag has no release notes."
msgstr "ã“ã®ã‚¿ã‚°ã«ã¯ãƒªãƒªãƒ¼ã‚¹ãƒŽãƒ¼ãƒˆãŒã‚ã‚Šã¾ã›ã‚“。"
@@ -6921,10 +7844,10 @@ msgid "TagsPage|Use git tag command to add a new one:"
msgstr ""
msgid "TagsPage|Write your release notes or drag files here…"
-msgstr ""
+msgstr "リリースノートを書ãã‹ã€ã“ã“ã«ãƒ•ã‚¡ã‚¤ãƒ«ã‚’ドラッグ…"
msgid "TagsPage|protected"
-msgstr ""
+msgstr "ä¿è­·"
msgid "Target Branch"
msgstr "ターゲットブランãƒ"
@@ -6947,6 +7870,9 @@ msgstr "利用è¦ç´„ã¨ãƒ—ライãƒã‚·ãƒ¼ãƒãƒªã‚·ãƒ¼"
msgid "Terms of Service and Privacy Policy"
msgstr "利用è¦ç´„ã¨ãƒ—ライãƒã‚·ãƒ¼ãƒãƒªã‚·ãƒ¼"
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -6995,12 +7921,6 @@ msgstr "課題ステージã§ã¯ã€èª²é¡ŒãŒç™»éŒ²ã•ã‚Œã¦ã‹ã‚‰ãƒžã‚¤ãƒ«ã‚¹ãƒˆ
msgid "The maximum file size allowed is 200KB."
msgstr "許å¯ã•ã‚Œã‚‹æœ€å¤§ãƒ•ã‚¡ã‚¤ãƒ«ã‚µã‚¤ã‚ºã¯ 200KB ã§ã™ã€‚"
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr "GitLab ã«ã‚ˆã‚‹ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹è©¦è¡Œå›žæ•°"
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "秘密éµã®å¾©å·ã«å¿…è¦ã¨ãªã‚‹ãƒ‘スフレーズ。ã“ã‚Œã¯ã‚ªãƒ—ションã§ã€å€¤ã¯æš—å·åŒ–ã—ã¦ä¿å­˜ã•ã‚Œã¾ã™ã€‚"
@@ -7038,7 +7958,7 @@ msgid "The repository for this project is empty"
msgstr "ã“ã®ãƒ—ロジェクトã«ãƒªãƒã‚¸ãƒˆãƒªã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
-msgstr ""
+msgstr "リãƒã‚¸ãƒˆãƒªã«ã¯ã€<code>http://</code>〠<code>https://</code> ã¾ãŸã¯ <code>git://</code>ã§æŽ¥ç¶šã§ããªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。"
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
msgstr ""
@@ -7049,9 +7969,6 @@ msgstr "レビューステージã¨ã¯ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’作æˆã—ã¦
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "ステージングステージã§ã¯ã€ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒãƒžãƒ¼ã‚¸ã•ã‚Œã¦ã‹ã‚‰ã‚³ãƒ¼ãƒ‰ãŒãƒ—ロダクション環境ã«ãƒ‡ãƒ—ロイã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã“ã®ãƒ‡ãƒ¼ã‚¿ã¯æœ€åˆã«ãƒ—ロダクションã«ãƒ‡ãƒ—ロイã—ãŸã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
@@ -7061,21 +7978,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr "テスティングステージã§ã¯ã€GitLab CI ãŒé–¢é€£ã™ã‚‹ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®å„パイプラインを実行ã™ã‚‹æ™‚é–“ãŒè¡¨ç¤ºã•ã‚Œã¾ã™ã€‚ã“ã®ãƒ‡ãƒ¼ã‚¿ã¯æœ€åˆã®ãƒ‘イプラインãŒå®Œäº†ã—ãŸã¨ãã«è‡ªå‹•çš„ã«è¿½åŠ ã•ã‚Œã¾ã™ã€‚"
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr "ã“ã®ã‚¹ãƒ†ãƒ¼ã‚¸ã«åŽé›†ã•ã‚ŒãŸãƒ‡ãƒ¼ã‚¿æ¯Žã®æ™‚é–“"
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7085,6 +7996,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "得られãŸä¸€é€£ã®ãƒ‡ãƒ¼ã‚¿ã‚’å°ã•ã„é †ã«ä¸¦ã¹ãŸã¨ãã«ä¸­å¤®ã«ä½ç½®ã™ã‚‹å€¤ã€‚例ãˆã°ã€3, 5, 9 ã®ä¸­å¤®å€¤ã¯ 5。3, 5, 7, 8 ã®ä¸­å¤®å€¤ã¯ (5+7)/2 = 6。"
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr "表示ã™ã‚‹èª²é¡ŒãŒã‚ã‚Šã¾ã›ã‚“"
@@ -7094,8 +8008,14 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr "表示ã™ã‚‹ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆãŒã‚ã‚Šã¾ã›ã‚“"
-msgid "There are problems accessing Git storage: "
-msgstr "Git ストレージã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã«å•é¡ŒãŒã‚ã‚Šã¾ã™: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
msgid "There was an error adding a todo."
msgstr ""
@@ -7119,7 +8039,7 @@ msgid "There was an error when subscribing to this label."
msgstr "ラベルã®è³¼èª­ã™ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "There was an error when unsubscribing from this label."
-msgstr ""
+msgstr "ラベルã®è³¼èª­è§£é™¤ã™ã‚‹ã¨ãã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
msgid "They can be managed using the %{link}."
msgstr "%{link}を使用ã—ã¦ãれらを管ç†ã§ãã¾ã™ã€‚"
@@ -7142,10 +8062,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7166,23 +8089,26 @@ msgstr "ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã¯ã¾ã ã‚°ãƒ«ãƒ¼ãƒ— Runner ã‚’æä¾›ã—ã¦ã„ã¾ã›ã
msgid "This is a confidential issue."
msgstr "ã“ã‚Œã¯éžå…¬é–‹ã®èª²é¡Œã§ã™ã€‚"
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
msgid "This issue is confidential"
-msgstr ""
+msgstr "ã“ã®èª²é¡Œã¯éžå…¬é–‹è¨­å®šã§ã™"
msgid "This issue is confidential and locked."
-msgstr ""
+msgstr "ã“ã®èª²é¡Œã¯éžå…¬é–‹ã§ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™"
msgid "This issue is locked."
msgstr "ã“ã®èª²é¡Œã¯ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã¾ã™ã€‚"
msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
-msgstr ""
+msgstr "ã“ã®ã‚¸ãƒ§ãƒ–ã¯ãƒ—ロセスをトリガーã«ã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ä¾å­˜ã—ã¾ã™ã€‚多ãã®å ´åˆã€æœ¬ç•ªç’°å¢ƒã¸ã‚³ãƒ¼ãƒ‰ã‚’デプロイã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚"
msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
-msgstr ""
+msgstr "ã“ã®ã‚¸ãƒ§ãƒ–ã¯ã€å‰å·¥ç¨‹ã®ã‚¸ãƒ§ãƒ–ãŒæ­£å¸¸çµ‚了ã™ã‚‹ã“ã¨ã§å®Ÿè¡Œã•ã‚Œã¾ã™"
msgid "This job does not have a trace."
msgstr "ã“ã®ã‚¸ãƒ§ãƒ–ã«ã¯ãƒˆãƒ¬ãƒ¼ã‚¹ãŒã‚ã‚Šã¾ã›ã‚“。"
@@ -7205,14 +8131,17 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
msgstr ""
msgid "This job is in pending state and is waiting to be picked by a runner"
-msgstr ""
+msgstr "ã“ã®ã‚¸ãƒ§ãƒ–ã¯ä¿ç•™ä¸­ã§ Runner ãŒå‹•ä½œã™ã‚‹ã®ã‚’å¾…ã£ã¦ã„ã¾ã™ã€‚"
msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
msgstr ""
@@ -7226,6 +8155,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr "ã“ã®ã‚¸ãƒ§ãƒ–ã¯æ‰‹å‹•ã«ã‚ˆã‚‹å®Ÿè¡Œã‚’求ã‚ã¦ã„ã¾ã™"
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
@@ -7250,6 +8182,9 @@ msgstr "プロジェクト"
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr "ã“ã®ãƒ—ロジェクトã¯ã‚°ãƒ«ãƒ¼ãƒ—ã«æ‰€å±žã—ã¦ã„ãªã„ãŸã‚ã€ã‚°ãƒ«ãƒ¼ãƒ— Runner を利用ã§ãã¾ã›ã‚“。"
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7259,6 +8194,12 @@ msgstr "リãƒã‚¸ãƒˆãƒª"
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7286,9 +8227,15 @@ msgstr "課題ãŒè¨ˆç”»ã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“"
msgid "Time before an issue starts implementation"
msgstr "課題ã®å®Ÿè£…ãŒé–‹å§‹ã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“"
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr "マージリクエストãŒä½œæˆã•ã‚Œã¦ã‹ã‚‰ãƒžãƒ¼ã‚¸ã¾ãŸã¯ã‚¯ãƒ­ãƒ¼ã‚ºã•ã‚Œã‚‹ã¾ã§ã®æ™‚é–“"
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr "外部サービスã‹ã‚‰ã®å¿œç­”時間(秒å˜ä½ï¼‰ã‚’設定ã—ã¾ã™ã€‚設定時間内ã«å¿œç­”ãŒç„¡ã„å ´åˆã€ã‚¢ã‚¯ã‚»ã‚¹ãŒæ‹’å¦ã•ã‚Œã¾ã™ã€‚"
@@ -7299,13 +8246,13 @@ msgid "Time spent"
msgstr "経éŽæ™‚é–“"
msgid "Time tracking"
-msgstr ""
+msgstr "タイムトラッキング"
msgid "Time until first merge request"
msgstr "最åˆã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¾ã§ã®æ™‚é–“"
msgid "TimeTrackingEstimated|Est"
-msgstr ""
+msgstr "Est"
msgid "TimeTracking|Estimated:"
msgstr ""
@@ -7320,7 +8267,7 @@ msgid "Timeago|%s days remaining"
msgstr "残り %s日間"
msgid "Timeago|%s hours ago"
-msgstr ""
+msgstr "%s 時間å‰"
msgid "Timeago|%s hours remaining"
msgstr "残り %s時間"
@@ -7469,7 +8416,7 @@ msgid "To connect GitHub repositories, you can use a %{personal_access_token_lin
msgstr ""
msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
-msgstr "GitHub リãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã™ã‚‹ã«ã¯ã€GitLab ãŒã‚ãªãŸã® GitHub リãƒã‚¸ãƒˆãƒªä¸€è¦§ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ã‚’許å¯ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ï¼š"
+msgstr "GitHub リãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã™ã‚‹ã«ã¯ã€GitLab ãŒã‚ãªãŸã® GitHub リãƒã‚¸ãƒˆãƒªä¸€è¦§ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ã‚’許å¯ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™:"
msgid "To connect an SVN repository, check out %{svn_link}."
msgstr "SVN リãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã™ã‚‹ã¨ãã¯ã€%{svn_link} ã‚’ã”確èªãã ã•ã„。"
@@ -7477,18 +8424,30 @@ msgstr "SVN リãƒã‚¸ãƒˆãƒªã«æŽ¥ç¶šã™ã‚‹ã¨ãã¯ã€%{svn_link} ã‚’ã”確èªã
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
-msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
msgstr ""
-msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
msgstr ""
+msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr "GitHub リãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆã™ã‚‹ãŸã‚ã« %{personal_access_token_link} を使用ã§ãã¾ã™ã€‚個人用アクセストークンを作æˆã™ã‚‹éš›ã¯ã€ <code>repo</code> スコープをé¸æŠžã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã‚¤ãƒ³ãƒãƒ¼ãƒˆã§ãる公開・éžå…¬é–‹ãƒªãƒã‚¸ãƒˆãƒªã®ä¸€è¦§ã‚’表示ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
+
+msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr "GitHub リãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ã€GitLab ãŒã‚ãªãŸã® GitHub リãƒã‚¸ãƒˆãƒªä¸€è¦§ã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã“ã¨ã‚’許å¯ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™:"
+
msgid "To import an SVN repository, check out %{svn_link}."
msgstr "SVN リãƒã‚¸ãƒˆãƒªã‚’インãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ã€%{svn_link} ã‚’ã”確èªãã ã•ã„。"
@@ -7498,6 +8457,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7508,12 +8470,15 @@ msgid "To this GitLab instance"
msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
-msgstr ""
+msgstr "GitLab CI ã®è¨­å®šãƒ•ã‚¡ã‚¤ãƒ«ã‚’検証ã™ã‚‹ã«ã¯ã€ãƒ—ロジェクト内ã®ã€ŒCI / CD→Pipelinesã€ã«è¡Œãã€ã€ŒCI Lintã€ãƒœã‚¿ãƒ³ã‚’クリックã—ã¦ãã ã•ã„。"
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
+msgstr "検索範囲を広ã’ã‚‹ã«ã¯ã€ãƒ•ã‚£ãƒ«ã‚¿ãƒ¼ã‚’変更ã¾ãŸã¯å‰Šé™¤ã—ã¾ã™ã€‚"
+
+msgid "Today"
msgstr ""
msgid "Todo"
@@ -7525,9 +8490,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr "サイドãƒãƒ¼ã‚’切り替ãˆ"
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr "検討ã®è¡¨ç¤ºãƒ»éžè¡¨ç¤ºã‚’切り替ãˆã‚‹"
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7543,6 +8514,9 @@ msgstr ""
msgid "Token"
msgstr "トークン"
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7556,7 +8530,10 @@ msgid "Total test time for all commits/merges"
msgstr "ã™ã¹ã¦ã®ã‚³ãƒŸãƒƒãƒˆ/マージã®åˆè¨ˆãƒ†ã‚¹ãƒˆæ™‚é–“"
msgid "Total: %{total}"
-msgstr "åˆè¨ˆ: %{total}"
+msgstr "åˆè¨ˆ:%{total}"
+
+msgid "Tracing"
+msgstr ""
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7565,6 +8542,9 @@ msgid "Track groups of issues that share a theme, across projects and milestones
msgstr ""
msgid "Track time with quick actions"
+msgstr "クイックアクションã§ä½œæ¥­æ™‚間を記録"
+
+msgid "Tree view"
msgstr ""
msgid "Trending"
@@ -7585,24 +8565,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr "å†è©¦è¡Œ"
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr "Twitter"
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7613,11 +8611,17 @@ msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be abl
msgstr ""
msgid "Unlocked"
-msgstr ""
+msgstr "アンロック済ã¿"
msgid "Unresolve discussion"
msgstr "検討を未解決ã«ã™ã‚‹"
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr "ã™ã¹ã¦ã®å¤‰æ›´ã®ã‚¹ãƒ†ãƒ¼ã‚¸ã‚’å–り消ã™"
@@ -7646,19 +8650,22 @@ msgid "Unsubscribe at project level"
msgstr "プロジェクトレベルã§è³¼èª­ã‚’解除"
msgid "Unverified"
-msgstr ""
+msgstr "未検証"
msgid "Up to date"
msgstr "最新"
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr "アップデート"
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
-msgstr "グループåã€èª¬æ˜Žã€ã‚¢ãƒã‚¿ãƒ¼ã€ãã®ä»–ã®ä¸€èˆ¬è¨­å®šã‚’æ›´æ–°ã—ã¾ã™ã€‚"
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
msgid "Updating"
msgstr ""
@@ -7687,15 +8694,15 @@ msgstr "æ–°è¦ãƒ•ã‚¡ã‚¤ãƒ«ã‚’アップロード"
msgid "Upload file"
msgstr "ファイルをアップロード"
-msgid "Upload new avatar"
-msgstr "æ–°ã—ã„ã‚¢ãƒã‚¿ãƒ¼ã‚’アップロード"
-
msgid "UploadLink|click to upload"
msgstr "クリックã—ã¦ã‚¢ãƒƒãƒ—ロード"
msgid "Upvotes"
msgstr "ã„ã„ã­"
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr "使用状æ³ã®çµ±è¨ˆ"
@@ -7706,7 +8713,7 @@ msgid "Use Service Desk to connect with your users (e.g. to offer customer suppo
msgstr "サービスデスクを使用ã—ã¦ã€GitLab 内ã®ãƒ¡ãƒ¼ãƒ«ã§ãƒ¦ãƒ¼ã‚¶ã¨æŽ¥ç¶šï¼ˆä¾‹ï¼šé¡§å®¢ã‚µãƒãƒ¼ãƒˆï¼‰"
msgid "Use group milestones to manage issues from multiple projects in the same milestone."
-msgstr ""
+msgstr "グループマイルストーンを使用ã—ã¦ã€åŒã˜ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³å†…ã®è¤‡æ•°ã®ãƒ—ロジェクトã®èª²é¡Œã‚’管ç†ã—ã¾ã™ã€‚"
msgid "Use one line per URI"
msgstr ""
@@ -7723,6 +8730,9 @@ msgstr "全体通知設定を利用"
msgid "Used by members to sign in to your group in GitLab"
msgstr "メンãƒãƒ¼ãŒ GitLab ã®ã‚°ãƒ«ãƒ¼ãƒ—ã«ã‚µã‚¤ãƒ³ã‚¤ãƒ³ã™ã‚‹ãŸã‚ã«ä½¿ç”¨ã•ã‚Œã¾ã™"
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7732,17 +8742,59 @@ msgstr "ユーザーã¨IPレートã®åˆ¶é™"
msgid "User map"
msgstr ""
-msgid "Users"
-msgstr "ユーザー"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|Personal projects"
msgstr ""
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
+msgstr "ユーザー"
+
msgid "Variables"
msgstr "変数"
msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
-msgstr ""
+msgstr "変数㯠Runner を介ã—ã¦ç’°å¢ƒã«é©ç”¨ã•ã‚Œã¾ã™ã€‚ã¾ãŸã€ä¿è­·ã•ã‚ŒãŸãƒ–ランãƒã‚„ã‚¿ã‚°ã ã‘ã«å¤‰æ•°ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã‚’制é™ã—ã€å¤‰æ•°ã‚’ä¿è­·ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“ã‚Œã«ã‚ˆã‚Šã€ãƒ‘スワードã€ç§˜å¯†éµãªã©ã‚’æ ¼ç´ã™ã‚‹ãŸã‚ã«å¤‰æ•°ã‚’使用ã§ãã¾ã™ã€‚"
msgid "Various container registry settings."
msgstr "å„種コンテナレジストリã®è¨­å®šã€‚"
@@ -7751,7 +8803,7 @@ msgid "Various email settings."
msgstr "å„種メール設定。"
msgid "Various settings that affect GitLab performance."
-msgstr ""
+msgstr "GitLab ã®ãƒ‘フォーマンスã«å½±éŸ¿ã™ã‚‹å„種設定。"
msgid "Verification information"
msgstr ""
@@ -7762,6 +8814,15 @@ msgstr "検証済ã¿"
msgid "Version"
msgstr "ãƒãƒ¼ã‚¸ãƒ§ãƒ³"
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7795,9 +8856,15 @@ msgstr "プロジェクトラベルを表示"
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr "å¯è¦–性ã¨ã‚¢ã‚¯ã‚»ã‚¹åˆ¶å¾¡"
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7816,6 +8883,36 @@ msgstr "パブリック"
msgid "VisibilityLevel|Unknown"
msgstr "ä¸æ˜Ž"
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "ã“ã®ãƒ‡ãƒ¼ã‚¿ã‚’å‚ç…§ã—ãŸã„ã§ã™ã‹ï¼Ÿã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã«ã¯ç®¡ç†è€…ã«å•ã„åˆã‚ã›ã¦ãã ã•ã„。"
@@ -7855,6 +8952,12 @@ msgstr "有効ã«ã—ãŸå ´åˆã€ãƒ¦ãƒ¼ã‚¶ãƒ¼ãŒè¦ç´„ã«åŒæ„ã•ã‚Œã‚‹ã¾ã§ Gi
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr "Wiki"
@@ -7871,7 +8974,7 @@ msgid "WikiClone|It is recommended to install %{markdown} so that GFM features r
msgstr ""
msgid "WikiClone|Start Gollum and edit locally"
-msgstr ""
+msgstr "Gollum ã‚’èµ·å‹•ã—ã¦ãƒ­ãƒ¼ã‚«ãƒ«ã§ç·¨é›†ã™ã‚‹"
msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
msgstr ""
@@ -7880,31 +8983,31 @@ msgid "WikiEdit|There is already a page with the same title in that path."
msgstr ""
msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
-msgstr ""
+msgstr "Wiki ã®æ”¹å–„ã‚’æ案ã™ã‚‹"
msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
-msgstr ""
+msgstr "Wiki ページを追加ã™ã‚‹ã«ã¯ã€ãƒ—ロジェクトメンãƒãƒ¼ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“。ã“ã®ãƒ—ロジェクト㮠Wiki を改善ã™ã‚‹æ–¹æ³•ã®æ案ãŒã‚ã‚‹å ´åˆã¯ã€ %{issues_link} ã§å•é¡Œã‚’é–‹ãã“ã¨ã‚’検討ã—ã¦ãã ã•ã„。"
msgid "WikiEmptyIssueMessage|issue tracker"
msgstr ""
msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
-msgstr ""
+msgstr "Wiki ã¯ãƒ—ロジェクトã«é–¢ã™ã‚‹ã™ã¹ã¦ã®è©³ç´°ã‚’ä¿å­˜ã™ã‚‹å ´æ‰€ã§ã™ã€‚ã“ã‚Œã«ã¯ã€ãƒ—ロジェクトを作æˆã—ãŸç†ç”±ã€ãƒ—ロジェクトã®åŽŸå‰‡ã€ãƒ—ロジェクトã®ä½¿ç”¨æ–¹æ³•ãªã©ãŒå«ã¾ã‚Œã¾ã™ã€‚"
msgid "WikiEmpty|Create your first page"
msgstr "最åˆã®ãƒšãƒ¼ã‚¸ã‚’作æˆ"
msgid "WikiEmpty|Suggest wiki improvement"
-msgstr ""
+msgstr "Wiki ã®æ”¹å–„ã‚’æ案ã™ã‚‹"
msgid "WikiEmpty|The wiki lets you write documentation for your project"
-msgstr ""
+msgstr "Wiki ã§ã¯ã€ãƒ—ロジェクトã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã‚’書ãã“ã¨ãŒã§ãã¾ã™"
msgid "WikiEmpty|This project has no wiki pages"
-msgstr ""
+msgstr "ã“ã®ãƒ—ロジェクト㫠Wiki ページã¯ã‚ã‚Šã¾ã›ã‚“"
msgid "WikiEmpty|You must be a project member in order to add wiki pages."
-msgstr ""
+msgstr "Wiki ページを追加ã™ã‚‹ã«ã¯ã€ãƒ—ロジェクトメンãƒãƒ¼ã§ã‚ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
msgid "WikiHistoricalPage|This is an old version of this page."
msgstr "ã“ã®ãƒšãƒ¼ã‚¸ã®å¤ã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒè¡¨ç¤ºã•ã‚Œã¦ã„ã¾ã™ã€‚"
@@ -8005,6 +9108,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8023,9 +9129,6 @@ msgstr "%{project_full_name} を別ã®ã‚ªãƒ¼ãƒŠãƒ¼ã«å§”è­²ã—よã†ã¨ã—ã¦ã„
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8033,16 +9136,13 @@ msgid "You can also create a project from the command line."
msgstr "コマンドラインã‹ã‚‰ãƒ—ロジェクトを作æˆã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
msgid "You can also star a label to make it a priority label."
-msgstr ""
-
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr "%{linkStart}Lint%{linkEnd}㧠.gitlab-ci.yml をテストã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™"
+msgstr "ラベルã«ã‚¹ã‚¿ãƒ¼ã‚’付ã‘ã¦å„ªå…ˆãƒ©ãƒ™ãƒ«ã«ã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚"
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
-msgstr ""
+msgstr "Kubernetes クラスター㫠Runner ã‚’ç°¡å˜ã«ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«ã§ãã¾ã™ã€‚%{link_to_help_page}"
msgid "You can move around the graph by using the arrow keys."
msgstr ""
@@ -8059,12 +9159,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8075,7 +9181,7 @@ msgid "You don't have any authorized applications"
msgstr ""
msgid "You have no permissions"
-msgstr ""
+msgstr "権é™ãŒã‚ã‚Šã¾ã›ã‚“"
msgid "You have reached your project limit"
msgstr "プロジェクト数ã®ä¸Šé™ã«é”ã—ã¦ã„ã¾ã™"
@@ -8086,9 +9192,6 @@ msgstr "アカウントを登録ã™ã‚‹ã«ã¯ã€åˆ©ç”¨è¦ç´„ã¨ãƒ—ライãƒã‚·ãƒ¼
msgid "You must have maintainer access to force delete a lock"
msgstr "ロックを強制的ã«å‰Šé™¤ã™ã‚‹ã«ã¯ã€Maintainer ã®ã‚¢ã‚¯ã‚»ã‚¹æ¨©ãŒå¿…è¦ã§ã™"
-msgid "You must sign in to star a project"
-msgstr "プロジェクトã«ã‚¹ã‚¿ãƒ¼ã‚’ã¤ã‘ãŸã„å ´åˆã¯ãƒ­ã‚°ã‚¤ãƒ³ã—ã¦ãã ã•ã„"
-
msgid "You need a different license to enable FileLocks feature"
msgstr "ファイルロック機能を有効ã«ã™ã‚‹ã«ã¯åˆ¥ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãŒå¿…è¦ã§ã™"
@@ -8098,6 +9201,12 @@ msgstr ""
msgid "You need permission."
msgstr "権é™ãŒå¿…è¦ã§ã™"
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr "通知メールをé€ä¿¡ã—ã¾ã›ã‚“"
@@ -8120,7 +9229,7 @@ msgid "You won't be able to pull or push project code via SSH until you %{add_ss
msgstr ""
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
-msgstr ""
+msgstr "SSH éµã‚’プロフィールã«è¿½åŠ ã—ãªã„é™ã‚Šã€SSH 経由ã§ãƒ—ロジェクトã®ã‚³ãƒ¼ãƒ‰ã‚’プルã—ãŸã‚Šãƒ—ッシュã™ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“。"
msgid "You'll need to use different branch names to get a valid comparison."
msgstr "有効ãªæ¯”較を行ã†ãŸã‚ã«ã¯ã€ç•°ãªã‚‹ãƒ–ランãƒåを使用ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -8141,7 +9250,7 @@ msgid "Your Groups"
msgstr "所属グループ"
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
-msgstr ""
+msgstr "ã“ã®ãƒšãƒ¼ã‚¸ã® Kubernetes クラスター情報ã¯ç·¨é›†å¯èƒ½ã§ã™ãŒã€ç„¡åŠ¹ã«ã—ã¦å†è¨­å®šã™ã‚‹ã“ã¨ã‚’推奨ã—ã¾ã™"
msgid "Your Projects (default)"
msgstr "プロジェクト(デフォルト)"
@@ -8159,11 +9268,14 @@ msgid "Your authorized applications"
msgstr ""
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
-msgstr ""
+msgstr "マージリクエストãŒé–‹ã„ã¦ã„ã‚‹ãŸã‚ã€å¤‰æ›´ã¯ %{branch_name} ã«ã‚³ãƒŸãƒƒãƒˆã§ãã¾ã™ã€‚"
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr "ã“ã®ã‚³ãƒ¡ãƒ³ãƒˆã¯ä¸€èˆ¬ã«ã¯è¡¨ç¤ºã•ã‚Œã¾ã›ã‚“。"
@@ -8183,15 +9295,7 @@ msgid "ago"
msgstr "å‰"
msgid "among other things"
-msgstr ""
-
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
+msgstr "ãã®ä»–ã®ã‚‚ã®"
msgid "assign yourself"
msgstr "自分ã«å‰²ã‚Šå½“ã¦"
@@ -8220,20 +9324,51 @@ msgstr "%{namespace} 㯠%{vulnerability} ã®å½±éŸ¿ã‚’å—ã‘ã¾ã™ã€‚"
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
-msgstr "%{reportName} çµæžœã®èª­è¾¼ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
-msgstr "%{type} æ–°ãŸãªã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã®è„†å¼±æ€§ã¯æ¤œå‡ºã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
-msgstr "%{type} セキュリティã®è„†å¼±æ€§ã¯æ¤œå‡ºã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
-msgstr "%{type} 脆弱性ã¯æ¤œå‡ºã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr ""
+
+msgid "ciReport|(is loading)"
+msgstr ""
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr ""
msgid "ciReport|Class"
msgstr "クラス"
@@ -8244,38 +9379,20 @@ msgstr ""
msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|Container scanning detected"
-msgstr "コンテナスキャンãŒæ¤œå‡ºã•ã‚Œã¾ã—ãŸ"
+msgid "ciReport|Container scanning"
+msgstr ""
msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr "コンテナスキャンã¯ã€Docker イメージã«å­˜åœ¨ã™ã‚‹æ—¢çŸ¥ã®è„†å¼±æ€§ã‚’検出ã—ã¾ã™ã€‚"
-msgid "ciReport|Container scanning is loading"
-msgstr "コンテナスキャンを読ã¿è¾¼ã¿ä¸­"
-
-msgid "ciReport|Container scanning resulted in error while loading results"
-msgstr "コンテナスキャンã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
-
-msgid "ciReport|DAST detected"
-msgstr "DAST ãŒæ¤œå‡ºã•ã‚Œã¾ã—ãŸ"
-
-msgid "ciReport|DAST is loading"
-msgstr "DAST を読ã¿è¾¼ã¿ä¸­"
-
-msgid "ciReport|DAST resulted in error while loading results"
-msgstr "DAST ã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "ciReport|DAST"
+msgstr ""
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
-msgstr "ä¾å­˜é–¢ä¿‚スキャンãŒæ¤œå‡ºã•ã‚Œã¾ã—ãŸ"
-
-msgid "ciReport|Dependency scanning is loading"
-msgstr "ä¾å­˜æ€§ã‚¹ã‚­ãƒ£ãƒ³ã‚’読ã¿è¾¼ã¿ä¸­"
-
-msgid "ciReport|Dependency scanning resulted in error while loading results"
-msgstr "ä¾å­˜æ€§ã‚¹ã‚­ãƒ£ãƒ³ã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
+msgid "ciReport|Dependency scanning"
+msgstr ""
msgid "ciReport|Description"
msgstr "説明"
@@ -8296,7 +9413,7 @@ msgid "ciReport|File"
msgstr "ファイル"
msgid "ciReport|Fixed:"
-msgstr ""
+msgstr "修正済ã¿:"
msgid "ciReport|Identifiers"
msgstr ""
@@ -8307,9 +9424,6 @@ msgstr "インスタンス"
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr "ホワイトリストã«ã¤ã„ã¦"
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8330,6 +9444,9 @@ msgstr "リンク"
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8348,13 +9465,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8363,11 +9474,8 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr "セキュリティスキャンを読ã¿è¾¼ã¿ä¸­"
-
msgid "ciReport|Severity"
-msgstr ""
+msgstr "é‡è¦åº¦"
msgid "ciReport|Solution"
msgstr ""
@@ -8396,9 +9504,6 @@ msgstr "ä¾å­˜é–¢ä¿‚スキャンレãƒãƒ¼ãƒˆã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™º
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr "未承èªã®è„†å¼±æ€§ï¼ˆèµ¤è‰²ï¼‰ã‚’承èªæ¸ˆã¨ã—ã¦ãƒžãƒ¼ã‚¯ã§ãã¾ã™ã€‚"
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr "%{name} ã‚’ %{version} ã‹ã‚‰ %{fixed} ã¸ã‚¢ãƒƒãƒ—グレードã—ã¦ãã ã•ã„。"
@@ -8409,14 +9514,11 @@ msgstr[0] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr "脆弱性ãªã—"
-
msgid "ciReport|on pipeline"
msgstr ""
msgid "command line instructions"
-msgstr ""
+msgstr "コマンドライン"
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -8440,32 +9542,31 @@ msgstr[0] "æ—¥"
msgid "deploy token"
msgstr "デプロイトークン"
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] "修正ã•ã‚ŒãŸè„†å¼±æ€§ï¼ˆ%d)を検出ã—ã¾ã—ãŸ"
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
-
msgid "disabled"
msgstr "無効"
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+
msgid "enabled"
msgstr "有効"
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
-msgstr ""
+msgstr "%{slash_command} コマンドã§è¦‹ç©æ™‚é–“ã‚’æ›´æ–°ã§ãã¾ã™ã€‚"
msgid "for this project"
msgstr "ã“ã®ãƒ—ロジェクトã§ã¯"
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -8494,6 +9595,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8547,22 +9651,22 @@ msgid "mrWidget|Check out branch"
msgstr "ブランãƒã®ãƒã‚§ãƒƒã‚¯ã‚¢ã‚¦ãƒˆ"
msgid "mrWidget|Checking ability to merge automatically"
-msgstr ""
+msgstr "自動マージ機能ã®æœ‰åŠ¹æ€§ã®ãƒã‚§ãƒƒã‚¯"
msgid "mrWidget|Cherry-pick"
-msgstr ""
+msgstr "ãƒã‚§ãƒªãƒ¼ãƒ”ック"
msgid "mrWidget|Cherry-pick this merge request in a new merge request"
-msgstr ""
+msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’ãƒã‚§ãƒªãƒ¼ãƒ”ックã—ã¦ã€æ–°ã—ã„マージリクエストを作æˆã™ã‚‹"
msgid "mrWidget|Closed"
msgstr ""
msgid "mrWidget|Closed by"
-msgstr ""
+msgstr "クローズ作業者"
msgid "mrWidget|Closes"
-msgstr ""
+msgstr "クローズ"
msgid "mrWidget|Create an issue to resolve them later"
msgstr "ã‚ã¨ã§è§£æ±ºã™ã‚‹ãŸã‚ã«èª²é¡Œã‚’作æˆã™ã‚‹"
@@ -8571,13 +9675,13 @@ msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
msgid "mrWidget|Did not close"
-msgstr ""
+msgstr "クローズã—ãªã‹ã£ãŸ"
msgid "mrWidget|Email patches"
-msgstr ""
+msgstr "メールパッãƒ"
msgid "mrWidget|Failed to load deployment statistics"
-msgstr ""
+msgstr "デプロイ統計ã®ãƒ­ãƒ¼ãƒ‰ã«å¤±æ•—ã—ã¾ã—ãŸ"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
@@ -8586,10 +9690,10 @@ msgid "mrWidget|If the %{branch} branch exists in your local repository, you can
msgstr "%{branch} ブランãƒãŒãƒ­ãƒ¼ã‚«ãƒ«ãƒªãƒã‚¸ãƒˆãƒªã«å­˜åœ¨ã™ã‚‹å ´åˆã¯ã€ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’手動ã§ãƒžãƒ¼ã‚¸ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
-msgstr ""
+msgstr "%{missingBranchName} ブランãƒãŒãƒ­ãƒ¼ã‚«ãƒ«ãƒªãƒã‚¸ãƒˆãƒªã«å­˜åœ¨ã™ã‚‹å ´åˆã¯ã€ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚’使用ã—ã¦ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’手動ã§ãƒžãƒ¼ã‚¸ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚"
msgid "mrWidget|Loading deployment statistics"
-msgstr ""
+msgstr "デプロイ統計を読ã¿è¾¼ã¿ä¸­"
msgid "mrWidget|Mentions"
msgstr "メンション"
@@ -8598,10 +9702,10 @@ msgid "mrWidget|Merge"
msgstr "マージ"
msgid "mrWidget|Merge failed."
-msgstr ""
+msgstr "マージã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
msgid "mrWidget|Merge locally"
-msgstr ""
+msgstr "ローカルã§ãƒžãƒ¼ã‚¸"
msgid "mrWidget|Merge request approved"
msgstr ""
@@ -8640,7 +9744,7 @@ msgid "mrWidget|Refreshing now"
msgstr "更新中"
msgid "mrWidget|Remove Source Branch"
-msgstr ""
+msgstr "ソースブランãƒã‚’削除"
msgid "mrWidget|Remove source branch"
msgstr "ソースブランãƒã‚’削除ã™ã‚‹"
@@ -8675,13 +9779,13 @@ msgid "mrWidget|Set by"
msgstr "設定者"
msgid "mrWidget|The changes were merged into"
-msgstr ""
+msgstr "ã“ã®å¤‰æ›´ã¯æ¬¡ã®ãƒ–ランãƒã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã—ãŸ"
msgid "mrWidget|The changes were not merged into"
-msgstr ""
+msgstr "ã“ã®å¤‰æ›´ã¯æ¬¡ã®ãƒ–ランãƒã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
msgid "mrWidget|The changes will be merged into"
-msgstr ""
+msgstr "ã“ã®å¤‰æ›´ã¯æ¬¡ã®ãƒ–ランãƒã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã™"
msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
msgstr ""
@@ -8705,13 +9809,13 @@ msgid "mrWidget|The source branch will not be removed"
msgstr "ã“ã®ã‚½ãƒ¼ã‚¹ãƒ–ランãƒã¯å‰Šé™¤ã•ã‚Œã¾ã›ã‚“"
msgid "mrWidget|There are merge conflicts"
-msgstr ""
+msgstr "マージã®ç«¶åˆãŒã‚ã‚Šã¾ã™"
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
msgstr "未解決ã®æ¤œè¨ŽãŒã‚ã‚Šã¾ã™ã€‚ã“れらã®æ¤œè¨Žã‚’解決ã—ã¦ãã ã•ã„。"
msgid "mrWidget|This merge request failed to be merged automatically"
-msgstr ""
+msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯è‡ªå‹•çš„ã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã›ã‚“ã§ã—ãŸ"
msgid "mrWidget|This merge request is in the process of being merged"
msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯ãƒžãƒ¼ã‚¸å®Ÿè¡Œä¸­ã§ã™"
@@ -8719,9 +9823,12 @@ msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã¯ãƒžãƒ¼ã‚¸å®Ÿè¡Œä¸­ã§ã™"
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "ã“ã®ãƒ—ロジェクトã¯ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã•ã‚Œã¦ã„ã‚‹ãŸã‚ã€æ›¸ãè¾¼ã¿ã¯ç„¡åŠ¹ã§ã™ã€‚"
-msgid "mrWidget|You can merge this merge request manually using the"
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã‚’手動ã§ãƒžãƒ¼ã‚¸ã§ãã¾ã™"
+
msgid "mrWidget|You can remove source branch now"
msgstr ""
@@ -8737,6 +9844,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr "パイプラインãŒæˆåŠŸã—ãŸã¨ãã¯è‡ªå‹•çš„ã«ãƒžãƒ¼ã‚¸ã•ã‚Œã¾ã™"
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr "æ–°è¦ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
@@ -8763,6 +9873,10 @@ msgstr "個人ã®ã‚¢ã‚¯ã‚»ã‚¹ãƒˆãƒ¼ã‚¯ãƒ³"
msgid "private key does not match certificate."
msgstr "秘密éµãŒè¨¼æ˜Žæ›¸ã¨ä¸€è‡´ã—ã¾ã›ã‚“。"
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+
msgid "remaining"
msgstr "残り"
@@ -8775,6 +9889,10 @@ msgstr "期é™ã‚’削除"
msgid "remove weight"
msgstr "ウェイトを削除"
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+
msgid "source"
msgstr "ソース"
@@ -8790,6 +9908,9 @@ msgstr "ã“ã®ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆ"
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr "ユーザーå"
diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po
index 416e0712a75..22a6ce3b7d8 100644
--- a/locale/ko/gitlab.po
+++ b/locale/ko/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Korean\n"
"Language: ko_KR\n"
"MIME-Version: 1.0\n"
@@ -13,10 +13,10 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ko\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:31\n"
+"PO-Revision-Date: 2018-11-19 17:17\n"
msgid " Status"
-msgstr ""
+msgstr " ìƒíƒœ"
msgid " and"
msgstr " 그리고"
@@ -29,29 +29,40 @@ msgid " improved on %d point"
msgid_plural " improved on %d points"
msgstr[0] " %d í¬ì¸íŠ¸ í–¥ìƒ"
+msgid "\"%{query}\" in projects"
+msgstr "프로ì íŠ¸ì—ì„œ \"%{query}\""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
-msgstr[0] "ë³€ê²½ëœ íŒŒì¼ %dê°œ"
+msgstr[0] "%dê°œì˜ ë³€ê²½ëœ íŒŒì¼"
msgid "%d commit"
msgid_plural "%d commits"
-msgstr[0] "%d 커밋"
+msgstr[0] "%dê°œì˜ ì»¤ë°‹"
msgid "%d commit behind"
msgid_plural "%d commits behind"
msgstr[0] "%d 커밋 behind"
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] "%dê°œ ì‚­ì œë¨"
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d 내보내기"
msgid "%d failed test result"
msgid_plural "%d failed test results"
-msgstr[0] ""
+msgstr[0] "%dê±´ì˜ í…ŒìŠ¤íŠ¸ê°€ 실패하였습니다."
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
-msgstr[0] ""
+msgstr[0] "%dê±´ì˜ í…ŒìŠ¤íŠ¸ 결과를 고쳤습니다."
msgid "%d issue"
msgid_plural "%d issues"
@@ -77,10 +88,6 @@ msgid "%d unstaged change"
msgid_plural "%d unstaged changes"
msgstr[0] "%dê°œì˜ ìŠ¤í…Œì´ì§•ë˜ì§€ ì•Šì€ ë³€ê²½ì‚¬í•­"
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] "ì·¨ì•½ì  %dê°œ"
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] "%s 추가 ì»¤ë°‹ì€ ì„±ëŠ¥ ì´ìŠˆë¥¼ 방지하기 위해 ìƒëžµë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -88,25 +95,41 @@ msgstr[0] "%s 추가 ì»¤ë°‹ì€ ì„±ëŠ¥ ì´ìŠˆë¥¼ 방지하기 위해 ìƒëžµë˜ì—ˆ
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{authorsName}'s discussion"
+msgstr "%{authorsName}ì˜ í† ë¡ "
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_timeago} ì— %{commit_author_link} ë‹˜ì´ ì»¤ë°‹í•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgstr "%{counter_storage} (%{counter_repositories} 저장소, %{counter_build_artifacts} 빌드 아티팩트, %{counter_lfs_objects} LFS)"
+
+msgid "%{count} %{alerts}"
+msgstr "%{count} %{alerts}"
+
+msgid "%{count} more assignees"
msgstr ""
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] "%{count} ëª…ì˜ ì°¸ì—¬ìž"
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] "%{count}ê°œì˜ ëŒ€ê¸°ì¤‘ì¸ ëŒ“ê¸€ "
+
msgid "%{filePath} deleted"
msgstr "%{filePath} ì‚­ì œë¨"
msgid "%{firstLabel} +%{labelCount} more"
-msgstr ""
+msgstr "%{firstLabel} +%{labelCount} ë”보기"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}그룹%{group_docs_link_end}ì„ ì‚¬ìš©í•˜ë©´ 여러 프로ì íŠ¸ë¥¼ 관리하고 ê³µë™ ìž‘ì—…ì„ ìˆ˜í–‰ í•  수 있습니다. 그룹 회ì›ì€ 모든 프로ì íŠ¸ì— 액세스 í•  수 있습니다."
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr "%{issuableType}ì´ ì‚­ì œë©ë‹ˆë‹¤! 확실합니까?"
+
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} 시작ë¨"
@@ -122,25 +145,15 @@ msgstr "%{nip_domain} ì€ ì»¤ìŠ¤í…€ ë„ë©”ì¸ ëŒ€ì‹  사용할 수 있습니다.
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{default_branch} 로부터 %{number_commits_behind} commits behind, %{number_commits_ahead} commits ahead"
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr "%{number_of_failures} / %{maximum_failures} 실패. GitLab ì€ ë‹¤ìŒ ì‹œë„ì—ì„œ 성공하면 ì ‘ê·¼ì„ í—ˆìš©í•  것입니다."
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr "%{number_of_failures} / %{maximum_failures} 실패. GitLab ì€ ìžë™ìœ¼ë¡œ 다시 ì‹œë„하지 않습니다. 문제가 í•´ê²°ë˜ë©´ 저장 공간 정보를 초기화 해주세요. "
-
msgid "%{openOrClose} %{noteable}"
msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
msgstr "%{percent}%% 완료"
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] "%{storage_name}: í˜¸ìŠ¤íŠ¸ì˜ storage ì ‘ê·¼ì— ì‹¤íŒ¨ %{failed_attempts} 회"
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
-msgstr[0] ""
+msgstr[0] "%{text} %{files} 파ì¼"
msgid "%{text} is available"
msgstr "%{text} 사용 가능"
@@ -148,25 +161,15 @@ msgstr "%{text} 사용 가능"
msgid "%{title} changes"
msgstr "%{title} 변경"
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] "%{type} ì—ì„œ ì·¨ì•½ì  %{vulnerabilityCount} 개를 찾았습니다"
-
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-
msgid "%{unstaged} unstaged and %{staged} staged changes"
msgstr "%{unstaged} ê±´ì´ ìŠ¤í…Œì´ì§•ë˜ì§€ 않았고, %{staged} ê±´ì´ ìŠ¤í…Œì´ì§• ë˜ì—ˆìŠµë‹ˆë‹¤."
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr "GitLab Inc와 공유ë˜ëŠ” ì •ë³´ì— ëŒ€í•´ %{usage_ping_link_start}ë” ì•Œì•„ë³´ê¸°%{usage_ping_link_end}"
+
+msgid "+ %{count} more"
+msgstr "+ %{count} ë”보기"
+
msgid "+ %{moreCount} more"
msgstr "+ %{moreCount} ë”"
@@ -197,7 +200,7 @@ msgstr[0] "%dê±´ì˜ ë¨¸ì§€ë¦¬í€˜ìŠ¤íŠ¸ 닫힘"
msgid "1 group"
msgid_plural "%d groups"
-msgstr[0] ""
+msgstr[0] "%d 그룹"
msgid "1 merged merge request"
msgid_plural "%d merged merge requests"
@@ -217,62 +220,62 @@ msgstr[0] "%d 파ì´í”„ë¼ì¸"
msgid "1 role"
msgid_plural "%d roles"
-msgstr[0] ""
+msgstr[0] "%dê°œì˜ ì—­í• "
msgid "1 user"
msgid_plural "%d users"
-msgstr[0] ""
+msgstr[0] "%dëª…ì˜ ì‚¬ìš©ìž"
msgid "1st contribution!"
-msgstr ""
+msgstr "첫번째 기여!"
msgid "2FA enabled"
msgstr "2FA 사용"
msgid "403|Please contact your GitLab administrator to get the permission."
-msgstr "403|ê¶Œí•œì„ ì–»ìœ¼ë ¤ë©´ GitLab 관리ìžì—게 문ì˜í•˜ì‹­ì‹œì˜¤."
+msgstr "ê¶Œí•œì„ ì–»ìœ¼ë ¤ë©´ GitLab 관리ìžì—게 문ì˜í•˜ì‹­ì‹œì˜¤."
msgid "403|You don't have the permission to access this page."
-msgstr "403|ì´ íŽ˜ì´ì§€ì— 대한 액세스 ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤."
+msgstr "ì´ íŽ˜ì´ì§€ì— 대한 액세스 ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤."
msgid "404|Make sure the address is correct and the page hasn't moved."
-msgstr "404|주소가 정확하고 페ì´ì§€ê°€ ì´ë™í•˜ì§€ 않았는지 확ì¸í•˜ì‹­ì‹œì˜¤."
+msgstr "주소가 정확하고 페ì´ì§€ê°€ ì´ë™í•˜ì§€ 않았는지 확ì¸í•˜ì‹­ì‹œì˜¤."
msgid "404|Page Not Found"
-msgstr "404|페ì´ì§€ë¥¼ ì°¾ì„ ìˆ˜ 없습니다"
+msgstr "페ì´ì§€ë¥¼ ì°¾ì„ ìˆ˜ 없습니다"
msgid "404|Please contact your GitLab administrator if you think this is a mistake."
-msgstr "404|ì´ê²ƒì´ ì‹¤ìˆ˜ì— ì˜í•œ 것ì´ë¼ê³  ìƒê°í•œë‹¤ë©´ GitLab 관리ìžì—게 문ì˜í•˜ì„¸ìš”."
+msgstr "ì´ê²ƒì´ ì‹¤ìˆ˜ì— ì˜í•œ 것ì´ë¼ê³  ìƒê°í•œë‹¤ë©´ GitLab 관리ìžì—게 문ì˜í•˜ì„¸ìš”."
msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> ì€ ì›ëž˜ johnsmith@example.comì´ ìƒì„±í•œ 모든 ì´ìŠˆì™€ ì˜ê²¬ì— \"By <a href=\"#\">@johnsmith</a>\"ì„ ì¶”ê°€í•˜ê³  ì›ëž˜ johnsmith@example.comì— í• ë‹¹ëœ ëª¨ë“  ì´ìŠˆì— 양수ì¸ìœ¼ë¡œ <a href=\"#\">@ johnsmith</a> ë¡œ 설정합니다."
msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"John Smith\"</code> ì€ johnsmith@example.comì´ ì²˜ìŒ ìƒì„±í•œ 모든 ì´ìŠˆì™€ 주ì„ì— \"By John Smith\"를 추가합니다."
msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"johnsm... @ example.com\"</code> ì€ ì›ëž˜ johnsmith@example.comì´ ìƒì„±í•œ 모든 ì´ìŠˆì™€ 주ì„ì— \"By johnsm... @ example.com\"ì„ ì¶”ê°€í•©ë‹ˆë‹¤. ì „ìž ë©”ì¼ ì£¼ì†Œ ë˜ëŠ” ì‚¬ìš©ìž ì´ë¦„ì€ ì‚¬ìš©ìžì˜ ê°œì¸ ì •ë³´ë¥¼ 보호하기 위해 마스킹 처리ë©ë‹ˆë‹¤."
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> ì€ ì›ëž˜ johnsmith@example.comì´ ìƒì„±í•œ 모든 ì´ìŠˆì™€ 주ì„ì— \"By <a href=\"#\">johnsmith@example.com</a>\"ì„ ì¶”ê°€í•©ë‹ˆë‹¤. 기본ì ìœ¼ë¡œ ì´ë©”ì¼ ì£¼ì†Œ ë˜ëŠ” ì‚¬ìš©ìž ì´ë¦„ì€ ê°€ë ¤ì ¸ 있어서 사용ìžì˜ ê°œì¸ì •ë³´ë¥¼ 보호합니다. ì „ì²´ ì „ìž ë©”ì¼ ì£¼ì†Œë¥¼ 표시하려면 ì´ ì˜µì…˜ì„ ì‚¬ìš©í•˜ì‹­ì‹œì˜¤."
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
-msgstr ""
+msgstr "<strong>%{changedFilesLength}개가 스테ì´ì§•ë˜ì§€ 않았고, %{stagedFilesLength}개가 스테ì´ì§•</strong>ëœ ë³€ê²½ì‚¬í•­"
msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
-msgstr ""
+msgstr "<strong>%{created_count}</strong> ìƒì„±ë¨, <strong>%{accepted_count}</strong> 허용ë¨."
msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
-msgstr ""
+msgstr "<strong>%{created_count}</strong> ìƒì„±ë¨, <strong>%{closed_count}</strong> 닫힘."
msgid "<strong>%{group_name}</strong> group members"
-msgstr ""
+msgstr "<strong>%{group_name}</strong> 그룹 멤버"
msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
msgstr ""
msgid "<strong>Removes</strong> source branch"
-msgstr ""
+msgstr "소스 브랜치 <strong>제거</strong>"
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
msgstr "'러너(Runner)'는 ìž‘ì—…ì„ ì‹¤í–‰í•˜ëŠ” 프로세스입니다. 필요한 ë§Œí¼ ëŸ¬ë„ˆë¥¼ ì…‹ì—…í•  수 있습니다."
@@ -280,62 +283,68 @@ msgstr "'러너(Runner)'는 ìž‘ì—…ì„ ì‹¤í–‰í•˜ëŠ” 프로세스입니다. í•„ìš”
msgid "A collection of graphs regarding Continuous Integration"
msgstr "지ì†ì ì¸ í†µí•©ì— ê´€í•œ 그래프 모ìŒ"
-msgid "A new branch will be created in your fork and a new merge request will be started."
+msgid "A default branch cannot be chosen for an empty project."
+msgstr "빈 프로ì íŠ¸ì—서는 기본 브랜치를 ì„ íƒí•  수 없습니다."
+
+msgid "A deleted user"
+msgstr "ì‚­ì œëœ ì‚¬ìš©ìž"
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
msgstr ""
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr "í¬í¬ì™€ 새 머지 리퀘스트(MR)ê°€ 시작ë˜ë©´ 새로운 브랜치가 만들어질 것입니다."
+
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr ""
+msgstr "프로ì íŠ¸ëŠ” 파ì¼ì„ 저장하고 (저장소), ìž‘ì—… 계íšì„ 세우며 (ì´ìŠˆ), 문서를 게시하는 ê³³ (위키) 입니다, %{among_other_things_link}."
msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
msgstr ""
msgid "A user with write access to the source branch selected this option"
-msgstr ""
+msgstr "소스 ë¸Œëžœì¹˜ì— ëŒ€í•œ 쓰기 ê¶Œí•œì´ ìžˆëŠ” 사용ìžê°€ ì´ ì˜µì…˜ì„ ì„ íƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "About GitLab"
-msgstr ""
+msgstr "GitLabì— ëŒ€í•˜ì—¬"
msgid "About GitLab CE"
-msgstr ""
+msgstr "GitLab CEì— ëŒ€í•˜ì—¬"
msgid "About auto deploy"
msgstr "ìžë™ ë°°í¬ ì •ë³´"
msgid "About this feature"
-msgstr ""
+msgstr "ì´ ê¸°ëŠ¥ì— ëŒ€í•´ì„œ"
msgid "Abuse Reports"
msgstr "오남용 리í¬íŠ¸"
msgid "Abuse reports"
-msgstr ""
+msgstr "악용 사례 보고서"
msgid "Accept terms"
msgstr "약관ë™ì˜"
msgid "Accepted MR"
-msgstr ""
+msgstr "승ì¸ëœ MR"
msgid "Access Tokens"
msgstr "액세스 토í°"
msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr ""
-
-msgid "Access to '%{classification_label}' not allowed"
-msgstr ""
+msgstr "ì ‘ê·¼ì´ ê±°ë¶€ë˜ì—ˆìŠµë‹ˆë‹¤! ì´ ì €ìž¥ì†Œì— ë°°í¬ í‚¤ë¥¼ 추가 í•  수 있는지 확ì¸í•´ 주세요."
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr "오ë™ìž‘ì¤‘ì¸ ì €ìž¥ê³µê°„ì— ëŒ€í•œ ì ‘ê·¼ì´ ë³µêµ¬ ìž‘ì—…ì„ ìœ„í•´ 마운트할 수 있ë„ë¡ ìž„ì‹œë¡œ 허용ë˜ì—ˆìŠµë‹ˆë‹¤. 문제가 í•´ê²°ëœ í›„ 다시 ì ‘ê·¼ì„ í—ˆìš©í•  수 있게 저장공간 정보를 리셋 해주세요."
+msgid "Access expiration date"
+msgstr "액세스 만료ì¼"
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
-msgstr ""
+msgid "Access to '%{classification_label}' not allowed"
+msgstr "%{classification_label} ì— ëŒ€í•œ 액세스가 허용ë˜ì§€ 않습니다."
msgid "Account"
msgstr "계정"
msgid "Account and limit"
-msgstr ""
+msgstr "계정과 제한"
msgid "Active"
msgstr "활성"
@@ -347,7 +356,7 @@ msgid "Activity"
msgstr "활ë™"
msgid "Add"
-msgstr ""
+msgstr "추가"
msgid "Add Changelog"
msgstr "변경 로그 추가"
@@ -356,131 +365,159 @@ msgid "Add Contribution guide"
msgstr "기여 ê°€ì´ë“œ 추가"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
-msgstr ""
+msgstr "그룹 Webhooks ë° GitLab Enterprise Editionì„ ì¶”ê°€"
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
-msgstr "ë¼ì´ì„ ìŠ¤ 추가"
+msgid "Add Kubernetes cluster"
+msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° 추가"
msgid "Add Readme"
+msgstr "Readme 추가"
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
msgstr ""
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr "모든 ì´ë©”ì¼ì— í‘œì‹œë  í…스트를 추가합니다. %{character_limit} ìž ì œí•œì´ ìžˆìŠµë‹ˆë‹¤."
+
+msgid "Add comment now"
msgstr ""
-msgid "Add new application"
+msgid "Add image comment"
msgstr ""
+msgid "Add license"
+msgstr "ë¼ì´ì„ ìŠ¤ 추가"
+
+msgid "Add new application"
+msgstr "새 애플리케ì´ì…˜ 추가"
+
msgid "Add new directory"
msgstr "새 디렉토리 추가"
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
+msgstr "ë°˜ì‘ ì¶”ê°€"
+
+msgid "Add to review"
msgstr ""
msgid "Add todo"
-msgstr ""
+msgstr "í•  ì¼ ì¶”ê°€"
msgid "Add user(s) to the group:"
-msgstr ""
+msgstr "ê·¸ë£¹ì— ì‚¬ìš©ìž ì¶”ê°€:"
msgid "Add users to group"
-msgstr ""
+msgstr "ê·¸ë£¹ì— ì‚¬ìš©ìž ì¶”ê°€"
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr "GitLab ì¸ìŠ¤í„´ìŠ¤ì— 새 애플리케ì´ì…˜ì„ 추가 í•  수 없습니다. ê¶Œí•œì„ ì–»ìœ¼ë ¤ë©´ GitLab 관리ìžì—게 문ì˜í•˜ì‹­ì‹œì˜¤."
msgid "Additional text"
-msgstr ""
+msgstr "추가 í…스트"
msgid "Admin Area"
-msgstr ""
+msgstr "ê´€ë¦¬ìž ì˜ì—­"
msgid "Admin Overview"
-msgstr ""
+msgstr "ê´€ë¦¬ìž ê°œìš”"
msgid "Admin area"
-msgstr ""
+msgstr "ê´€ë¦¬ìž ì˜ì—­"
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "%{username}ì„ ì˜êµ¬ì ìœ¼ë¡œ 삭제하려고 합니다. ì´ìŠˆ, 머지 리퀘스트(MR) ë° ì—°ê²°ëœ ê·¸ë£¹ì´ \"Ghost-user\"으로 변경ë©ë‹ˆë‹¤. ë°ì´í„° ì†ì‹¤ì„ 방지하기 위해 %{strong_start}차단 사용ìž%{strong_end} ê¸°ëŠ¥ì„ ì‚¬ìš©í•´ë³´ì„¸ìš”. %{strong_start}ì‚¬ìš©ìž ì‚­ì œ%{strong_end}ì‹œ ë˜ëŒë¦¬ê±°ë‚˜, 복구할 수 없습니다."
msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "%{username}ì„ ì˜êµ¬ì ìœ¼ë¡œ 삭제하려고 합니다. ì´ìŠˆ, 머지 리퀘스트(MR) ë° ì—°ê²°ëœ ê·¸ë£¹ì´ ì‚­ì œë©ë‹ˆë‹¤. ë°ì´í„° ì†ì‹¤ì„ 방지하기 위해 %{strong_start}ì‚¬ìš©ìž ì°¨ë‹¨%{strong_end} ê¸°ëŠ¥ì„ ì‚¬ìš©í•´ë³´ì„¸ìš”. %{strong_start}ì‚¬ìš©ìž ì‚­ì œ%{strong_end}ì‹œ ë˜ëŒë¦¬ê±°ë‚˜, 복구할 수 없습니다."
msgid "AdminArea|Stop all jobs"
-msgstr ""
+msgstr "모든 작업 중지"
msgid "AdminArea|Stop all jobs?"
-msgstr ""
+msgstr "모든 ìž‘ì—…ì„ ì¤‘ì§€í•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
msgid "AdminArea|Stop jobs"
-msgstr ""
+msgstr "작업 중지"
msgid "AdminArea|Stopping jobs failed"
-msgstr ""
+msgstr "ìž‘ì—… ì¤‘ì§€ì— ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤."
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
-msgstr ""
-
-msgid "AdminHealthPageLink|health page"
-msgstr "ìƒíƒœ 페ì´ì§€"
+msgstr "모든 ìž‘ì—…ì„ ì¤‘ì§€í•©ë‹ˆë‹¤. 현재 ì‹¤í–‰ì¤‘ì¸ ëª¨ë“  ìž‘ì—…ì´ ì¤‘ì§€ë©ë‹ˆë‹¤."
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "%{projectName}프로ì íŠ¸, 저장소 ë° ë¬¸ì œ, 병합 요청 ë“±ì„ í¬í•¨í•œ 모든 관련 리소스를 ì˜êµ¬ížˆ 삭제하려고합니다. 확ì¸í•˜ê³  %{strong_start}프로ì íŠ¸ ì‚­ì œ%{strong_end}를 누르면 실행 취소 ë˜ëŠ” 복구를 í•  수 없습니다."
msgid "AdminProjects|Delete"
-msgstr ""
+msgstr "삭제"
msgid "AdminProjects|Delete Project %{projectName}?"
-msgstr ""
+msgstr "%{projectName} 프로ì íŠ¸ë¥¼ 삭제하시겠습니까?"
msgid "AdminProjects|Delete project"
-msgstr ""
+msgstr "프로ì íŠ¸ ì‚­ì œ"
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
-msgstr ""
+msgstr "모든 프로ì íŠ¸ì˜ ìžë™ 앱 리뷰 ë° ìžë™ ë°°í¬ ë‹¨ê³„ì—ì„œ 기본ì ìœ¼ë¡œ 사용할 ë„ë©”ì¸ì„ 지정하십시오."
msgid "AdminUsers|Block user"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ì°¨ë‹¨"
msgid "AdminUsers|Delete User %{username} and contributions?"
-msgstr ""
+msgstr " ì‚¬ìš©ìž %{username}와 기여를 삭제하시겠습니까?"
msgid "AdminUsers|Delete User %{username}?"
-msgstr ""
+msgstr " ì‚¬ìš©ìž %{username} (ì„)를 삭제하시겠습니까?"
msgid "AdminUsers|Delete user"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ì‚­ì œ"
msgid "AdminUsers|Delete user and contributions"
-msgstr ""
+msgstr "사용ìžì™€ 기여 ì‚­ì œ"
msgid "AdminUsers|To confirm, type %{projectName}"
-msgstr ""
+msgstr "확ì¸ì„ 위해 %{projectName} 를 입력해주세요."
msgid "AdminUsers|To confirm, type %{username}"
-msgstr ""
+msgstr "확ì¸ì„ 위해 %{username} ì„ ìž…ë ¥í•˜ì„¸ìš”"
-msgid "Advanced"
-msgstr "고급"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
msgid "Advanced settings"
msgstr "고급 설정"
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+
msgid "All"
msgstr "ì „ì²´"
msgid "All changes are committed"
-msgstr ""
+msgstr "모든 ë³€ê²½ì‚¬í•­ì´ ì»¤ë°‹ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr ""
+msgstr "모든 ê¸°ëŠ¥ì€ ë¹„ì–´ìžˆëŠ” 프로ì íŠ¸, 템플릿, 가져올 ë•Œ 사용할 수 있지만 ë‚˜ì¤‘ì— í”„ë¡œì íŠ¸ 설정ì—ì„œ 비활성화 í•  수 있습니다."
msgid "All users"
-msgstr ""
+msgstr "모든 사용ìž"
msgid "Allow commits from members who can merge to the target branch."
msgstr "ëŒ€ìƒ ë¸Œëžœì¹˜ì— ë¨¸ì§€í•  수 있는 ë©¤ë²„ì˜ ì»¤ë°‹ì„ í—ˆìš©í•©ë‹ˆë‹¤."
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -488,11 +525,17 @@ msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
msgstr ""
msgid "Allow requests to the local network from hooks and services."
+msgstr "후í¬ì™€ 서비스ì—ì„œ 로컬 네트워í¬ì— 대한 ìš”ì²­ì„ í—ˆìš©í•©ë‹ˆë‹¤."
+
+msgid "Allow users to request access"
msgstr ""
-msgid "Allows you to add and manage Kubernetes clusters."
+msgid "Allow users to request access if visibility is public or internal."
msgstr ""
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 추가하고 관리 í•  수 ​​있습니다."
+
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
msgstr ""
@@ -500,70 +543,82 @@ msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
-msgstr ""
+msgstr "대신, %{personal_access_token_link} (ì„) 를 사용할 수 있습니다. ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°ì„ ìƒì„±í•  ë•Œ, <code>저장소</code> 범위를 ì„ íƒí•˜ë©´ ì—°ê²°ì´ ê°€ëŠ¥í•œ 공개, 비공개 저장소를 표시할 수 있습니다."
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr "대신, %{personal_access_token_link} (ì„) 를 사용할 수 있습니다. ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°ì„ ìƒì„±í•  ë•Œ, <code>저장소</code> 범위를 ì„ íƒí•´ì•¼ 가져오기가 가능한 공개, 비공개 저장소를 표시할 수 있습니다."
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
-msgstr ""
+msgstr "ì–‘ì‹ì„ 제출하면 SSH 키가 ìžë™ìœ¼ë¡œ ìƒì„±ë©ë‹ˆë‹¤. ìžì„¸í•œ ë‚´ìš©ì€ ë¬¸ì„œë¥¼ 참조하십시오."
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
-msgstr ""
+msgstr "%{link_to_client} ì´ë¼ëŠ” ì‘ìš© í”„ë¡œê·¸ëž¨ì´ GitLab ê³„ì •ì— ëŒ€í•œ 액세스를 요청하고 있습니다."
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
msgid "An error accured whilst committing your changes."
-msgstr ""
+msgstr "변경 커밋 ì¤‘ì— ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error has occurred"
-msgstr ""
+msgstr "ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occured creating the new branch."
-msgstr ""
+msgstr "새 브랜치를 만드는 ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occured whilst fetching the job trace."
-msgstr ""
+msgstr "작업를 가져오는 ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
-msgstr ""
+msgstr "모든 파ì¼ì„ 로드하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occured whilst loading the file content."
-msgstr ""
+msgstr "íŒŒì¼ ë‚´ìš©ì„ ë¡œë“œí•˜ëŠ” ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occured whilst loading the file."
-msgstr ""
+msgstr "파ì¼ì„ 로드하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occured whilst loading the merge request changes."
-msgstr ""
+msgstr "머지 리퀘스트(MR) ë³€ê²½ì‚¬í•­ì„ ê°€ì ¸ì˜¤ëŠ” ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occured whilst loading the merge request version data."
-msgstr ""
+msgstr "머지 리퀘스트(MR) 버전 ë°ì´í„°ë¥¼ 로드하는 ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occured whilst loading the merge request."
-msgstr ""
+msgstr "머지 리퀘스트(MR)를 로드하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occured whilst loading the pipelines jobs."
+msgstr "파ì´í”„ë¼ì¸ ìž‘ì—…ì„ ê°€ì ¸ì˜¤ëŠ” ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+
+msgid "An error occurred adding a draft to the discussion."
msgstr ""
-msgid "An error occurred previewing the blob"
+msgid "An error occurred adding a new draft."
msgstr ""
+msgid "An error occurred previewing the blob"
+msgstr "BLOB 미리보기 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+
msgid "An error occurred when toggling the notification subscription"
-msgstr ""
+msgstr "알림 êµ¬ë… ì—¬ë¶€ 변경 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred when updating the issue weight"
-msgstr ""
+msgstr "ì´ìŠˆ ì¤‘ìš”ë„ ì—…ë°ì´íŠ¸ 중 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while adding approver"
+msgstr "승ì¸ìžë¥¼ ì¶”ê°€í•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
+
+msgid "An error occurred while deleting the comment"
msgstr ""
msgid "An error occurred while detecting host keys"
-msgstr ""
+msgstr "호스트 í‚¤ë“¤ì„ ì‚­ì œí•˜ë˜ ì¤‘ 오류가 ë°œìƒ í–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while dismissing the alert. Refresh the page and try again."
msgstr "Alertì„ í•´ì œí•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 페ì´ì§€ë¥¼ 새로 고친 후 다시 ì‹œë„하십시오."
@@ -572,133 +627,151 @@ msgid "An error occurred while dismissing the feature highlight. Refresh the pag
msgstr "기능 ê°•ì¡° 표시를 해제하는 ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 페ì´ì§€ë¥¼ 새로고침하고, 다시 ì‹œë„해주세요."
msgid "An error occurred while fetching markdown preview"
+msgstr "마í¬ë‹¤ìš´ 미리보기를 가져 오는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+
+msgid "An error occurred while fetching pending comments"
msgstr ""
msgid "An error occurred while fetching sidebar data"
-msgstr ""
+msgstr "사ì´ë“œë°” ë°ì´í„°ë¥¼ 가져오는 중 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while fetching stages."
-msgstr ""
+msgstr "스테ì´ì§€ë¥¼ 가져 오는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while fetching the job log."
-msgstr ""
+msgstr "ìž‘ì—… 로그를 가져 오는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while fetching the job."
-msgstr ""
+msgstr "ìž‘ì—…ì„ ê°€ì ¸ 오는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while fetching the jobs."
-msgstr ""
+msgstr "ìž‘ì—…ì„ ê°€ì ¸ 오는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while fetching the pipeline."
-msgstr ""
+msgstr "파ì´í”„ë¼ì¸ì„ ë°˜ì˜í•˜ë˜ 중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "An error occurred while getting projects"
-msgstr ""
+msgstr "프로ì íŠ¸ë¥¼ 가져오는 ë™ì•ˆ 오류가 ë°œìƒ í–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while importing project: %{details}"
-msgstr ""
+msgstr "프로ì íŠ¸ë¥¼ ê°€ì ¸ì˜¤ë˜ ì¤‘ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤: %{details}"
msgid "An error occurred while initializing path locks"
msgstr ""
-msgid "An error occurred while loading commit signatures"
+msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading commit signatures"
+msgstr "커밋 시그너ì³ë¥¼ 불러오는 ë„ì¤‘ì— ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+
msgid "An error occurred while loading diff"
-msgstr ""
+msgstr "ì°¨ì´ì ì„ 로드하는 ë™ì•ˆ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "An error occurred while loading filenames"
-msgstr ""
+msgstr "íŒŒì¼ ì´ë¦„ì„ ë¡œë“œí•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while loading the file"
-msgstr ""
+msgstr "íŒŒì¼ ë¡œë“œ 중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "An error occurred while making the request."
-msgstr ""
+msgstr "ìš”ì²­ì„ ìƒì„±í•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while removing approver"
msgstr ""
msgid "An error occurred while rendering KaTeX"
-msgstr ""
+msgstr "KaTeX ë Œë”ë§ ë„중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤"
msgid "An error occurred while rendering preview broadcast message"
-msgstr ""
+msgstr "방송 메시지 미리보기를 ë Œë”ë§í•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while retrieving calendar activity"
msgstr "ìº˜ë¦°ë” í™œë™ì„ 가져오는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while retrieving diff"
-msgstr ""
+msgstr "ì°¨ì´ì ì„ 가져오는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while saving LDAP override status. Please try again."
msgstr ""
msgid "An error occurred while saving assignees"
-msgstr ""
+msgstr "담당ìžë¥¼ 저장하는 중 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "An error occurred while subscribing to notifications."
-msgstr ""
+msgstr "ì•Œë¦¼ì„ êµ¬ë…하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while unsubscribing to notifications."
+msgstr "알림 구ë…ì„ í•´ì œí•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+
+msgid "An error occurred while updating the comment"
msgstr ""
msgid "An error occurred while validating username"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ì´ë¦„ì„ í™•ì¸í•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤"
msgid "An error occurred. Please try again."
msgstr "오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„í•´ 주세요."
-msgid "Anonymous"
+msgid "Analytics"
msgstr ""
+msgid "Anonymous"
+msgstr "ìµëª…"
+
msgid "Anti-spam verification"
-msgstr ""
+msgstr "안티 스팸 ê²€ì¦"
msgid "Any"
-msgstr ""
+msgstr "Any"
msgid "Any Label"
-msgstr ""
+msgstr "모든 ë¼ë²¨"
msgid "Appearance"
-msgstr ""
+msgstr "외관"
msgid "Application"
-msgstr ""
+msgstr "어플리케ì´ì…˜"
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
-msgstr ""
+msgstr "애플리케ì´ì…˜: %{name}"
msgid "Applications"
msgstr "어플리케ì´ì…˜"
msgid "Apr"
-msgstr ""
+msgstr "4ì›”"
msgid "April"
-msgstr ""
+msgstr "4ì›”"
msgid "Archived project! Repository and other project resources are read-only"
-msgstr ""
+msgstr "ë³´ê´€ëœ í”„ë¡œì íŠ¸! 저장소 ë° ê¸°íƒ€ 프로ì íŠ¸ 리소스는 ì½ê¸° 전용입니다."
+
+msgid "Archived projects"
+msgstr "ì•„ì¹´ì´ë¸Œëœ 프로ì íŠ¸"
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "ì´ íŒŒì´í”„ë¼ì¸ ìŠ¤ì¼€ì¥´ì„ ì‚­ì œ 하시겠습니까?"
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to erase this build?"
msgstr ""
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr "저장ë˜ì§€ ì•Šì€ ë³€ê²½ì‚¬í•­ì„ ì‚­ì œí•˜ê² ìŠµë‹ˆê¹Œ?"
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr ""
msgid "Are you sure you want to remove %{group_name}?"
-msgstr ""
+msgstr "ì •ë§ë¡œ %{group_name}(ì„)를 ì‚­ì œ 하시겠습니까?"
msgid "Are you sure you want to remove this identity?"
-msgstr ""
+msgstr "ì •ë§ë¡œ 해당 í•­ëª©ì„ ì‚­ì œí•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
msgid "Are you sure you want to reset registration token?"
msgstr "ë“±ë¡ í† í°ì„ 초기화 하시겠습니까?"
@@ -706,9 +779,12 @@ msgstr "ë“±ë¡ í† í°ì„ 초기화 하시겠습니까?"
msgid "Are you sure you want to reset the health check token?"
msgstr "헬스 ì²´í¬ í† í°ì„ 초기화 하시겠습니까?"
-msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgid "Are you sure you want to stop this environment?"
msgstr ""
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr "ì •ë§ë¡œ %{path_lock_path}ì˜ ìž ê¸ˆì„ í•´ì œ 하시겠습니까?"
+
msgid "Are you sure?"
msgstr "확실합니까?"
@@ -716,10 +792,10 @@ msgid "Artifact ID"
msgstr ""
msgid "Artifacts"
-msgstr ""
+msgstr "결과물"
msgid "Ascending"
-msgstr ""
+msgstr "오름차순"
msgid "Ask your group maintainer to set up a group Runner."
msgstr "그룹 관리ìžì—게 그룹 Runner 를 설정하ë„ë¡ ìš”ì²­í•˜ì„¸ìš”"
@@ -728,37 +804,37 @@ msgid "Assertion consumer service URL"
msgstr ""
msgid "Assign custom color like #FF0000"
-msgstr ""
+msgstr "#FF0000ê³¼ ê°™ì´ ë§žì¶¤ ìƒ‰ìƒ ì§€ì •"
msgid "Assign labels"
-msgstr ""
+msgstr "ë¼ë²¨ 지정"
msgid "Assign milestone"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤ 지정"
msgid "Assign to"
msgstr ""
msgid "Assigned Issues"
-msgstr ""
+msgstr "í• ë‹¹ëœ ì´ìŠˆ"
msgid "Assigned Merge Requests"
-msgstr ""
+msgstr "í• ë‹¹ëœ ë¨¸ì§€ 리퀘스트(MR)"
msgid "Assigned to :name"
msgstr ""
msgid "Assigned to me"
-msgstr ""
+msgstr "나ì—게 할당 ë¨"
msgid "Assignee"
-msgstr ""
+msgstr "담당ìž"
msgid "Assignee lists not available with your current license"
-msgstr ""
+msgstr "ë‹´ë‹¹ìž ëª©ë¡ì€ 현재 ë¼ì´ì„¼ìŠ¤ë¡œëŠ” 사용할 수 없습니다."
msgid "Assignee lists show all issues assigned to the selected user."
-msgstr ""
+msgstr "ë‹´ë‹¹ìž ëª©ë¡ì€ ì„ íƒëœ 사용ìžì—게 할당 ëœ ëª¨ë“  ì´ìŠˆê°€ 표시ë©ë‹ˆë‹¤."
msgid "Assignee(s)"
msgstr "담당ìž"
@@ -770,49 +846,49 @@ msgid "Audit Events"
msgstr ""
msgid "Aug"
-msgstr ""
+msgstr "8ì›”"
msgid "August"
-msgstr ""
+msgstr "8ì›”"
msgid "Authentication Log"
-msgstr ""
+msgstr "ì¸ì¦ 로그"
msgid "Authentication log"
-msgstr ""
+msgstr "ì¸ì¦ 로그"
msgid "Authentication method"
-msgstr ""
+msgstr "ì¸ì¦ 방법"
msgid "Author"
-msgstr ""
+msgstr "작성ìž"
msgid "Authorization code:"
-msgstr ""
+msgstr "ì¸ì¦ 코드:"
msgid "Authorization was granted by entering your username and password in the application."
-msgstr ""
+msgstr "ì‘ìš© í”„ë¡œê·¸ëž¨ì— ì‚¬ìš©ìž ì´ë¦„ê³¼ 암호를 입력하여 ê¶Œí•œì´ ë¶€ì—¬ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Authorize"
-msgstr ""
+msgstr "권한 부여"
msgid "Authorize %{link_to_client} to use your account?"
-msgstr ""
+msgstr "%{link_to_client} ì„ ë‚´ 계정으로 ì¸ì¦í•˜ì‹œê² ì–´ìš”?"
msgid "Authorized At"
-msgstr ""
+msgstr "권한 부여ë¨: "
msgid "Authorized applications (%{size})"
-msgstr ""
+msgstr "ì¸ì¦ëœ 애플리케ì´ì…˜ (%{size})"
msgid "Authors: %{authors}"
-msgstr ""
+msgstr "작성ìž: %{authors}"
msgid "Auto DevOps"
-msgstr ""
+msgstr "ìžë™ DevOps"
msgid "Auto DevOps enabled"
-msgstr ""
+msgstr "ìžë™ DevOps 활성화ë¨"
msgid "Auto DevOps, runners and job artifacts"
msgstr "ìžë™ DevOps, Runner ìž‘ì—… artifacts"
@@ -844,20 +920,23 @@ msgstr "애플리케ì´ì…˜ì˜ 빌드, 테스트, ë°°í¬ê°€ ì‚¬ì „ì— ì •ì˜ëœ C
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "ë” ì•Œì•„ë³´ê¸° %{link_to_documentation}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr "Auto DevOps 파ì´í”„ ë¼ì¸ì´ 활성화ë˜ì—ˆìœ¼ë©° 대체 CI 구성 파ì¼ì´ 없는 ê²½ìš°ì— ì‚¬ìš©ë©ë‹ˆë‹¤. %{more_information_link}"
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
-msgstr ""
+msgstr "ì´ í”„ë¡œì íŠ¸ê°€ %{link_to_auto_devops_settings} ì¸ ê²½ìš° 애플리케ì´ì…˜ì„ ìžë™ìœ¼ë¡œ 빌드하고 테스트 í•  수 있습니다. %{link_to_add_kubernetes_cluster} ì¸ ê²½ìš°ì—는 ìžë™ìœ¼ë¡œ ë°°í¬ê¹Œì§€ í•  수 있습니다."
msgid "AutoDevOps|add a Kubernetes cluster"
-msgstr ""
+msgstr "Kubernetes cluster 추가"
msgid "AutoDevOps|enable Auto DevOps"
-msgstr "AutoDevOps | Auto DevOps 활성화"
+msgstr "Auto DevOps 활성화"
msgid "Automatically marked as default internal user"
msgstr ""
msgid "Available"
-msgstr ""
+msgstr "ì´ìš© 가능"
msgid "Available group Runners : %{runners}"
msgstr "사용 가능한 그룹 Runner: %{runners}"
@@ -866,99 +945,105 @@ msgid "Available group Runners : %{runners}."
msgstr "사용 가능한 그룹 Runner: %{runners}."
msgid "Avatar will be removed. Are you sure?"
-msgstr ""
+msgstr "아바타가 ì‚­ì œë©ë‹ˆë‹¤. 확실합니까?"
msgid "Average per day: %{average}"
-msgstr ""
+msgstr "하루 í‰ê· : %{average}"
msgid "Background Color"
-msgstr ""
+msgstr "배경 색"
msgid "Background Jobs"
-msgstr ""
+msgstr "백그ë¼ìš´ë“œ ìž‘ì—…"
msgid "Background color"
-msgstr ""
-
-msgid "Background jobs"
-msgstr ""
+msgstr "배경 색"
msgid "Badges"
-msgstr ""
+msgstr "배지"
msgid "Badges|A new badge was added."
-msgstr ""
+msgstr "새로운 배지가 추가ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Badges|Add badge"
-msgstr ""
+msgstr "배지 추가"
msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
-msgstr ""
+msgstr "배지 추가 실패, 입력한 URLì„ í™•ì¸í•˜ì‹œê³  다시 ì‹œë„하십시오."
msgid "Badges|Badge image URL"
-msgstr ""
+msgstr "배지 ì´ë¯¸ì§€ URL"
msgid "Badges|Badge image preview"
-msgstr ""
+msgstr "배지 ì´ë¯¸ì§€ 미리 보기"
msgid "Badges|Delete badge"
-msgstr ""
+msgstr "배지 삭제"
msgid "Badges|Delete badge?"
-msgstr ""
+msgstr "배지를 삭제할까요?"
msgid "Badges|Deleting the badge failed, please try again."
-msgstr ""
+msgstr "배지 ì‚­ì œ 실패, 다시 ì‹œë„하십시오."
msgid "Badges|Group Badge"
-msgstr ""
+msgstr "그룹 배지"
msgid "Badges|Link"
-msgstr ""
+msgstr "ë§í¬"
msgid "Badges|No badge image"
-msgstr ""
+msgstr "ìž˜ëª»ëœ ë°°ì§€ ì´ë¯¸ì§€"
msgid "Badges|No image to preview"
-msgstr ""
+msgstr "미리 ë³¼ ì´ë¯¸ì§€ê°€ 없습니다"
msgid "Badges|Please fill in a valid URL"
-msgstr ""
+msgstr "유효한 URLì„ ìž…ë ¥í•˜ì‹­ì‹œì˜¤."
msgid "Badges|Project Badge"
-msgstr ""
+msgstr "프로ì íŠ¸ 배지"
msgid "Badges|Reload badge image"
-msgstr ""
+msgstr "배지 ì´ë¯¸ì§€ 다시 ì½ì–´ë“¤ì´ê¸°"
msgid "Badges|Save changes"
-msgstr ""
+msgstr "변경 사항 저장"
msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
-msgstr ""
+msgstr "배지 저장 실패, 입력한 URLì„ í™•ì¸í•˜ì‹œê³  다시 ì‹œë„하십시오."
msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
-msgstr ""
+msgstr "GitLabì´ ì§€ì›í•˜ëŠ” %{docsLinkStart}변수%{docsLinkEnd}: %{placeholders}"
msgid "Badges|The badge was deleted."
-msgstr ""
+msgstr "배지가 ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Badges|The badge was saved."
-msgstr ""
+msgstr "배지를 저장했습니다."
msgid "Badges|This group has no badges"
-msgstr ""
+msgstr "ê·¸ë£¹ì— ë°°ì§€ê°€ 없습니다."
msgid "Badges|This project has no badges"
-msgstr ""
+msgstr "프로ì íŠ¸ì— 배지가 없습니다."
msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr ""
+msgstr "ì´ ë°°ì§€ë¥¼ 삭제하려고합니다. ì‚­ì œ ëœ ë°°ì§€ëŠ” <strong>ë³µì› í•  수 없습니다</strong>."
msgid "Badges|Your badges"
-msgstr ""
+msgstr "내 배지"
msgid "Badges|e.g. %{exampleUrl}"
+msgstr "e.g. %{exampleUrl}"
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
msgstr ""
msgid "Begin with the selected commit"
@@ -971,101 +1056,101 @@ msgid "Below you will find all the groups that are public."
msgstr ""
msgid "Billing"
-msgstr ""
+msgstr "결제"
msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
-msgstr ""
+msgstr "%{group_name}(ì€)는 %{plan_link} í”Œëžœì„ ì‚¬ìš©í•˜ê³  있습니다."
msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
-msgstr ""
+msgstr "ìžë™ 다운그레ì´ë“œ ë˜ëŠ” ì¼ë¶€ í”Œëžœì€ í˜„ìž¬ 사용할 수 없습니다."
msgid "BillingPlans|Current plan"
-msgstr ""
+msgstr "현재 요금제"
msgid "BillingPlans|Customer Support"
-msgstr ""
+msgstr "ê³ ê° ì§€ì›"
msgid "BillingPlans|Downgrade"
-msgstr ""
+msgstr "다운그레ì´ë“œ"
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
-msgstr ""
+msgstr "%{faq_link}ì„ ì½ìŒìœ¼ë¡œì¨ í”Œëžœì— ëŒ€í•´ ë” ìžì„¸ížˆ 알아보거나 GitLab.com Gold 무료 30 ì¼ í‰ê°€íŒì„ 시작하세요."
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
-msgstr ""
+msgstr "%{faq_link} ì„ ì½ì–´ í”Œëžœì— ëŒ€í•´ ìžì„¸ížˆ 알아보십시오."
msgid "BillingPlans|Manage plan"
-msgstr ""
+msgstr "플랜 관리"
msgid "BillingPlans|Please contact %{customer_support_link} in that case."
-msgstr ""
+msgstr "%{customer_support_link}으로 ì—°ë½í•´ì£¼ì„¸ìš”."
msgid "BillingPlans|See all %{plan_name} features"
-msgstr ""
+msgstr "%{plan_name}ì˜ ëª¨ë“  기능 보기"
msgid "BillingPlans|This group uses the plan associated with its parent group."
-msgstr ""
+msgstr "ì´ ê·¸ë£¹ì€ ìƒìœ„ ê·¸ë£¹ì˜ í”Œëžœê³¼ ì—°ê²°ë©ë‹ˆë‹¤."
msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
-msgstr ""
+msgstr "ì´ ê·¸ë£¹ì˜ í”Œëžœì„ ê´€ë¦¬í•˜ë ¤ë©´ %{parent_billing_page_link}ì˜ ê²°ì œ ì„¹ì…˜ì„ ë°©ë¬¸í•˜ì„¸ìš”."
msgid "BillingPlans|Upgrade"
-msgstr ""
+msgstr "업그레ì´ë“œ"
msgid "BillingPlans|You are currently on the %{plan_link} plan."
-msgstr ""
+msgstr "현재 %{plan_link} í”Œëžœì„ ì´ìš©ì¤‘입니다."
msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
-msgstr ""
+msgstr "GitLab.com í‰ê°€íŒì´ %{expiration_date}ì— ë§Œë£Œë˜ì—ˆìŠµë‹ˆë‹¤. %{learn_more_text}"
msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
-msgstr ""
+msgstr "골드 ì²´í—˜íŒì´ <strong>%{expiration_date} í›„ì— ë§Œë£Œë©ë‹ˆë‹¤.</strong>. GitLab.com Goldì— ëŒ€í•œ ìžì„¸í•œ 정보는 %{features_link}ì—ì„œ ì½ì–´ë³¼ 수 있습니다."
msgid "BillingPlans|features"
-msgstr ""
+msgstr "기능"
msgid "BillingPlans|frequently asked questions"
-msgstr ""
+msgstr "ìžì£¼ 묻는 질문"
msgid "BillingPlans|monthly"
-msgstr ""
+msgstr "ì›”"
msgid "BillingPlans|paid annually at %{price_per_year}"
-msgstr ""
+msgstr "매 년마다 %{price_per_year}ì„ ì§€ë¶ˆí•©ë‹ˆë‹¤"
msgid "BillingPlans|per user"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ë‹¹"
msgid "Bitbucket Server Import"
-msgstr ""
+msgstr "Bitbucket 서버ì—ì„œ 가져 오기"
msgid "Bitbucket import"
-msgstr ""
+msgstr "Bitbucketì—ì„œ 가져오기"
msgid "Blog"
-msgstr ""
+msgstr "블로그"
msgid "Boards"
-msgstr ""
+msgstr "보드"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr ""
msgid "Branch (%{branch_count})"
msgid_plural "Branches (%{branch_count})"
-msgstr[0] ""
+msgstr[0] "브랜치 (%{branch_count})"
msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
msgstr "<strong>%{branch_name}</strong> 브랜치가 ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤. ìžë™ ë°°í¬ë¥¼ 설정하려면 GitLab CI Yaml í…œí”Œë¦¿ì„ ì„ íƒí•˜ê³  변경 ì‚¬í•­ì„ ì ìš©í•˜ì‹­ì‹œì˜¤. %{link_to_autodeploy_doc}"
msgid "Branch has changed"
-msgstr ""
+msgstr "브랜치가 변경ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Branch is already taken"
-msgstr ""
+msgstr "해당 브랜치는 ì´ë¯¸ 사용중입니다"
msgid "Branch name"
-msgstr ""
+msgstr "브랜치 ì´ë¦„"
msgid "BranchSwitcherPlaceholder|Search branches"
msgstr "브랜치 검색"
@@ -1077,94 +1162,94 @@ msgid "Branches"
msgstr "브랜치"
msgid "Branches|Active"
-msgstr ""
+msgstr "활성"
msgid "Branches|Active branches"
-msgstr ""
+msgstr "활성 브랜치"
msgid "Branches|All"
-msgstr ""
+msgstr "모ë‘"
msgid "Branches|Cant find HEAD commit for this branch"
-msgstr ""
+msgstr "ì´ ë¸Œëžœì¹˜ì—ì„œ HEAD ì»¤ë°‹ì„ ì°¾ì„ ìˆ˜ ì—†ìŒ"
msgid "Branches|Compare"
-msgstr ""
+msgstr "비êµ"
msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
-msgstr ""
+msgstr "'%{default_branch}'ì— ë³‘í•©ëœ ëª¨ë“  브랜치 지우기"
msgid "Branches|Delete branch"
-msgstr ""
+msgstr "브랜치 지우기"
msgid "Branches|Delete merged branches"
-msgstr ""
+msgstr "ë³‘í•©ëœ ë¸Œëžœì¹˜ 지우기"
msgid "Branches|Delete protected branch"
-msgstr ""
+msgstr "ë³´í˜¸ëœ ë¸Œëžœì¹˜ 지우기"
msgid "Branches|Delete protected branch '%{branch_name}'?"
-msgstr ""
+msgstr "ë³´í˜¸ëœ ë¸Œëžœì¹˜ì¸ '%{branch_name}'ì„(를) 지울까요?"
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
-msgstr ""
+msgstr "'%{branch_name}' 브랜치를 삭제하면 ë˜ëŒë¦´ 수 없습니다. 괜찮습니까?"
msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
-msgstr ""
+msgstr "ë³‘í•©ëœ ë¸Œëžœì¹˜ë¥¼ 삭제하면 ë˜ëŒë¦´ 수 없습니다. 괜찮ì„까요?"
msgid "Branches|Filter by branch name"
-msgstr ""
+msgstr "브랜치 ì´ë¦„으로 í•„í„°ë§"
msgid "Branches|Merged into %{default_branch}"
-msgstr ""
+msgstr "%{default_branch}ì— ë¨¸ì§€ë¨"
msgid "Branches|New branch"
-msgstr ""
+msgstr "새 브랜치"
msgid "Branches|No branches to show"
-msgstr ""
+msgstr "표시할 브랜치 ì—†ìŒ"
msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
-msgstr ""
+msgstr "%{delete_protected_branch}(ì„)를 누른 후ì—는 ì‚­ì œëœ ë¸Œëžœì¹˜ë¥¼ 다시 복구할 수 없습니다."
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
-msgstr ""
+msgstr "프로ì íŠ¸ ê´€ë¦¬ìž ë˜ëŠ” ì†Œìœ ìž ë§Œ 보호 브랜치를 삭제할 수 있습니다."
msgid "Branches|Overview"
-msgstr ""
+msgstr "개요"
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
-msgstr ""
+msgstr "ë³´í˜¸ëœ ë¸Œëžœì¹˜ëŠ” %{project_settings_link} ì—ì„œ 관리할 수 있습니다."
msgid "Branches|Show active branches"
-msgstr ""
+msgstr "í™œì„±ëœ ë¸Œëžœì¹˜ 보기"
msgid "Branches|Show all branches"
-msgstr ""
+msgstr "모든 브랜치 보기"
msgid "Branches|Show more active branches"
-msgstr ""
+msgstr "í™œì„±ëœ ë¸Œëžœì¹˜ ë” ë³´ê¸°"
msgid "Branches|Show more stale branches"
-msgstr ""
+msgstr "ì•ˆì •í™”ëœ ë¸Œëžœì¹˜ ë” ë³´ê¸°"
msgid "Branches|Show overview of the branches"
-msgstr ""
+msgstr "브랜치 개요 보기"
msgid "Branches|Show stale branches"
-msgstr ""
+msgstr "ì•ˆì •í™”ëœ ë¸Œëžœì¹˜ 보기"
msgid "Branches|Sort by"
-msgstr ""
+msgstr "다ìŒìœ¼ë¡œ 정렬하기"
msgid "Branches|Stale"
-msgstr ""
+msgstr "안정"
msgid "Branches|Stale branches"
-msgstr ""
+msgstr "ì•ˆì •í™”ëœ ë¸Œëžœì¹˜"
msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
-msgstr ""
+msgstr "ì´ ë¸Œëžœì¹˜ëŠ” 업스트림ì—ì„œ 분기 중ì´ë¯€ë¡œ ìžë™ìœ¼ë¡œ ì—…ë°ì´íŠ¸í•  수 없습니다."
msgid "Branches|The default branch cannot be deleted"
msgstr "Default 브랜치는 삭제할 수 없습니다."
@@ -1179,22 +1264,22 @@ msgid "Branches|To confirm, type %{branch_name_confirmation}:"
msgstr "확ì¸í•˜ë ¤ë©´, %{branch_name_confirmation} 를 ìž…ë ¥ 합니다."
msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
-msgstr ""
+msgstr "로컬 ë³€ê²½ì‚¬í•­ì„ ì·¨ì†Œí•˜ê³  업스트림 버전으로 브랜치를 ë®ì–´ì“°ë ¤ë©´ 여기서 삭제하고 '지금 ì—…ë°ì´íŠ¸'를 ì„ íƒí•˜ì„¸ìš”."
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr "ë‹¹ì‹ ì€ ë³´í˜¸ëœ %{branch_name} 브랜치를 삭제하려고 합니다."
msgid "Branches|diverged from upstream"
-msgstr ""
+msgstr "업스트림ì—ì„œ 분기ë¨"
msgid "Branches|merged"
-msgstr ""
+msgstr "병합ë¨"
msgid "Branches|project settings"
-msgstr ""
+msgstr "프로ì íŠ¸ 설정"
msgid "Branches|protected"
-msgstr ""
+msgstr "보호ë¨"
msgid "Browse Directory"
msgstr "디렉토리 찾아보기"
@@ -1209,10 +1294,10 @@ msgid "Browse files"
msgstr "íŒŒì¼ ì°¾ì•„ë³´ê¸°"
msgid "Built-In"
-msgstr ""
+msgstr "빌트-ì¸"
msgid "Business metrics (Custom)"
-msgstr ""
+msgstr "비즈니스 지표 (ì‚¬ìš©ìž ì •ì˜)"
msgid "ByAuthor|by"
msgstr "작성ìž"
@@ -1221,94 +1306,94 @@ msgid "CI / CD"
msgstr "CI / CD"
msgid "CI / CD Settings"
-msgstr ""
+msgstr "CI/CD 설정"
msgid "CI will run using the credentials assigned above."
-msgstr ""
+msgstr "ìœ„ì˜ ìžê²© ì¦ëª…ì„ ì‚¬ìš©í•˜ì—¬ CIê°€ 실행ë©ë‹ˆë‹¤."
msgid "CI/CD"
-msgstr ""
+msgstr "CI/CD"
msgid "CI/CD configuration"
-msgstr ""
+msgstr "CI/CD 구성"
msgid "CI/CD for external repo"
-msgstr ""
+msgstr "외부 저장소용 CI/CD"
msgid "CI/CD settings"
msgstr "CI/CD 설정"
msgid "CICD|Auto DevOps"
-msgstr "CICD|Auto DevOps"
+msgstr "Auto DevOps"
msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
-msgstr "CICD|Auto DevOps는 ì‚¬ì „ì— ì •ì˜ëœ Continuous Integrationê³¼ Delivery ì„¤ì •ì„ ë°”íƒ•ìœ¼ë¡œí•˜ì—¬ ìžë™ìœ¼ë¡œ 빌드, 테스트 그리고 ë°°í¬ë¥¼ 수행합니다."
+msgstr "Auto DevOps는 ì‚¬ì „ì— ì •ì˜ëœ Continuous Integrationê³¼ Delivery ì„¤ì •ì„ ë°”íƒ•ìœ¼ë¡œí•˜ì—¬ ìžë™ìœ¼ë¡œ 빌드, 테스트 그리고 ë°°í¬ë¥¼ 수행합니다."
msgid "CICD|Automatic deployment to staging, manual deployment to production"
-msgstr ""
+msgstr "스테ì´ì§• í™˜ê²½ì— ìžë™ ë°°í¬, 프로ë•ì…˜ í™˜ê²½ì— ìˆ˜ë™ ë°°í¬"
msgid "CICD|Continuous deployment to production"
+msgstr "프로ë•ì…˜ í™˜ê²½ì— ì§€ì†ì ì¸ ë°°í¬"
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
msgstr ""
msgid "CICD|Default to Auto DevOps pipeline"
-msgstr ""
+msgstr "Auto DevOps 파ì´í”„ë¼ì¸ì„ 기본으로 사용"
msgid "CICD|Deployment strategy"
-msgstr ""
+msgstr "ë°°í¬ ì „ëžµ"
msgid "CICD|Deployment strategy needs a domain name to work correctly."
-msgstr ""
+msgstr "ë°°í¬ ì „ëžµì´ ì˜¬ë°”ë¥´ê²Œ ìž‘ë™í•˜ë ¤ë©´ ë„ë©”ì¸ ì´ë¦„ì´ í•„ìš”í•©ë‹ˆë‹¤."
msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
-msgstr ""
+msgstr "Auto DevOpsë¡œ 여러 Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 설정하는 경우 ë„ë©”ì¸ì„ 설정하지 마십시오."
msgid "CICD|Jobs"
-msgstr ""
+msgstr "ìž‘ì—…"
msgid "CICD|Learn more about Auto DevOps"
-msgstr "CICD|Auto DevOpsì— ëŒ€í•´ ë” ì•Œì•„ë³´ê¸°"
+msgstr "Auto DevOpsì— ëŒ€í•´ ë” ì•Œì•„ë³´ê¸°"
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
-msgstr ""
+msgstr "대체 CI 구성 파ì¼ì´ì—†ëŠ” 경우 Auto DevOps 파ì´í”„ë¼ì¸ì´ 실행ë©ë‹ˆë‹¤."
msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
msgstr ""
msgid "CICD|instance enabled"
-msgstr ""
+msgstr "ì¸ìŠ¤í„´ìŠ¤ 사용"
msgid "Callback URL"
-msgstr ""
-
-msgid "Callback url"
-msgstr ""
+msgstr "콜백 URL"
msgid "Can't find HEAD commit for this branch"
-msgstr ""
+msgstr "ì´ ë¸Œëžœì¹˜ì—ì„œ HEAD ì»¤ë°‹ì„ ì°¾ì„ ìˆ˜ 없습니다."
msgid "Cancel"
msgstr "취소"
msgid "Cancel this job"
-msgstr ""
+msgstr "ì´ ìž‘ì—… 취소"
msgid "Cannot be merged automatically"
-msgstr ""
+msgstr "ìžë™ìœ¼ë¡œ 병합할 수 없습니다."
msgid "Cannot modify managed Kubernetes cluster"
-msgstr ""
+msgstr "ì´ë¯¸ êµ¬ì„±ëœ Kubernetes í´ëŸ¬ìŠ¤í„°ëŠ” 수정할 수 없습니다"
msgid "Certificate fingerprint"
-msgstr ""
+msgstr "ì¸ì¦ì„œ 지문"
msgid "Change Weight"
-msgstr ""
+msgstr "ì¤‘ìš”ë„ ë³€ê²½"
msgid "Change template"
-msgstr ""
+msgstr "템플릿 변경"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
-msgstr ""
+msgstr "ì´ ê°’ì— ë”°ë¼ GitLab UIì—ì„œ ì—…ë°ì´íŠ¸ë¥¼ 확ì¸í•˜ëŠ” 빈ë„ê°€ 달ë¼ì§‘니다."
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr "브랜치ì—ì„œ Pick"
@@ -1337,14 +1422,14 @@ msgstr "차트"
msgid "Chat"
msgstr "채팅"
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
-msgstr ""
+msgstr "%{text}ì´(ê°€) 사용 가능한지 í™•ì¸ ì¤‘â€¦"
msgid "Checking branch availability..."
-msgstr ""
+msgstr "브랜치가 사용 가능한지 í™•ì¸ ì¤‘..."
msgid "Cherry-pick this commit"
msgstr "ì´ ì»¤ë°‹ì„ Cherry-pick"
@@ -1356,25 +1441,31 @@ msgid "Choose <strong>Create archive</strong> and wait for archiving to complete
msgstr ""
msgid "Choose <strong>Next</strong> at the bottom of the page."
-msgstr ""
+msgstr "페ì´ì§€ì˜ ì•„ëž˜ì˜ <strong>다ìŒ</strong> ì„ íƒ"
msgid "Choose File ..."
-msgstr ""
+msgstr "íŒŒì¼ ì„ íƒ ..."
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr "템플릿 ì„ íƒ..."
+
+msgid "Choose a type..."
+msgstr "ìœ í˜•ì„ ì„ íƒ..."
+
msgid "Choose any color."
-msgstr ""
+msgstr "아무 색ìƒì„ ì„ íƒí•´ 주세요."
msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
msgstr ""
msgid "Choose file..."
-msgstr ""
+msgstr "íŒŒì¼ ì„ íƒâ€¦"
msgid "Choose the top-level group for your repository imports."
-msgstr ""
+msgstr "저장소 ê°€ì ¸ì˜¤ê¸°ì— ëŒ€í•œ 최ìƒìœ„ ê·¸ë£¹ì„ ì„ íƒí•˜ì„¸ìš”."
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr ""
@@ -1383,7 +1474,7 @@ msgid "Choose which repositories you want to connect and run CI/CD pipelines."
msgstr ""
msgid "Choose which repositories you want to import."
-msgstr ""
+msgstr "가져올 저장소를 ì„ íƒí•´ì£¼ì„¸ìš”."
msgid "Choose which shards you wish to synchronize to this secondary node."
msgstr ""
@@ -1394,6 +1485,9 @@ msgstr "취소ë¨"
msgid "CiStatusLabel|created"
msgstr "ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤."
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr "실패"
@@ -1412,6 +1506,9 @@ msgstr "대기"
msgid "CiStatusLabel|skipped"
msgstr "건너 뜀"
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr "ìˆ˜ë™ ì‹¤í–‰ 대기 중"
@@ -1424,6 +1521,9 @@ msgstr "취소ë¨"
msgid "CiStatusText|created"
msgstr "ìƒì„±ë¨"
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr "실패"
@@ -1464,13 +1564,13 @@ msgid "CiVariable|Error occured while saving variables"
msgstr "CiVariable 변수를 저장 하는 중 오류가 ë°œìƒ í–ˆìŠµë‹ˆë‹¤."
msgid "CiVariable|New environment"
-msgstr ""
+msgstr "새로운 환경"
msgid "CiVariable|Protected"
msgstr "보호ë¨"
msgid "CiVariable|Search environments"
-msgstr ""
+msgstr "환경 검색"
msgid "CiVariable|Toggle protected"
msgstr "Toggle 보호ë¨"
@@ -1478,20 +1578,20 @@ msgstr "Toggle 보호ë¨"
msgid "CiVariable|Validation failed"
msgstr "유효성 검사 실패"
-msgid "CircuitBreakerApiLink|circuitbreaker api"
-msgstr "circuitbreaker api"
-
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear search"
+msgstr ""
+
msgid "Clear search input"
msgstr "검색 입력 지우기"
msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
-msgstr ""
+msgstr "아래 프로ì íŠ¸ 목ë¡ì—ì„œ <strong>프로ì íŠ¸ ì´ë¦„</strong>ì„ ëˆŒëŸ¬ 프로ì íŠ¸ 마ì¼ìŠ¤í†¤ì„ 봅니다."
msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
-msgstr ""
+msgstr "<strong>다운로드</strong> ë²„íŠ¼ì„ í´ë¦­í•˜ê³  다운로드가 완료 ë  ë•Œê¹Œì§€ 기다려 주세요."
msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
msgstr ""
@@ -1500,58 +1600,73 @@ msgid "Click the <strong>Select none</strong> button on the right, since we only
msgstr ""
msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
-msgstr ""
+msgstr "Kubernetes 페ì´ì§€ë¡œ ì´ë™í•˜ì—¬ 설치 프로세스를 시작하려면 아래 ë²„íŠ¼ì„ í´ë¦­í•˜ì‹­ì‹œì˜¤."
msgid "Click to expand it."
-msgstr ""
+msgstr "í´ë¦­í•˜ì—¬ 확장하십시오."
msgid "Click to expand text"
msgstr "í…스트를 í´ë¦­í•˜ì—¬ 확장하세요."
msgid "Client authentication certificate"
-msgstr ""
+msgstr "í´ë¼ì´ì–¸íŠ¸ ì¸ì¦ì„œ"
msgid "Client authentication key"
-msgstr ""
+msgstr "í´ë¼ì´ì–¸íŠ¸ ì¸ì¦ 키"
msgid "Client authentication key password"
-msgstr ""
+msgstr "í´ë¼ì´ì–¸íŠ¸ ì¸ì¦ 키 비밀번호"
msgid "Clients"
-msgstr ""
+msgstr "í´ë¼ì´ì–¸íŠ¸"
msgid "Clone repository"
-msgstr ""
+msgstr "저장소 í´ë¡ "
msgid "Close"
-msgstr ""
+msgstr "닫기"
+
+msgid "Close epic"
+msgstr "ì—픽 닫기"
msgid "Closed"
-msgstr ""
+msgstr "닫힘"
msgid "Closed issues"
-msgstr ""
+msgstr "닫힌 ì´ìŠˆ"
msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
-msgstr ""
+msgstr "%{appList}ê°€ Kubernetes í´ëŸ¬ìŠ¤í„°ì— 설치ë˜ì—ˆìŠµë‹ˆë‹¤"
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
-msgid "ClusterIntegration|API URL"
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
msgstr ""
+msgid "ClusterIntegration|API URL"
+msgstr "API URL"
+
msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° 추가"
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
msgstr ""
-msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
msgstr ""
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° í†µí•©ì— ëŒ€í•œ 고급 옵션"
+
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
msgstr ""
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
-msgstr ""
+msgstr "프로ì íŠ¸ ì˜ì—­ì„ 가져 오는 ë™ì•ˆ 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤: %{error}"
msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
msgstr ""
@@ -1563,45 +1678,51 @@ msgid "ClusterIntegration|An error occurred when trying to contact the Google Cl
msgstr ""
msgid "ClusterIntegration|Applications"
-msgstr ""
+msgstr "애플리케ì´ì…˜"
msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
-msgstr ""
+msgstr "ì´ Kubernetes í´ëŸ¬ìŠ¤í„°ì˜ í†µí•©ì„ ì œê±° 하시겠습니까? (실제 Kubernetes í´ëŸ¬ìŠ¤í„°ëŠ” ì‚­ì œë˜ì§€ 않습니다)"
msgid "ClusterIntegration|CA Certificate"
-msgstr ""
+msgstr "CA ì¸ì¦ì„œ"
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
-msgstr ""
+msgstr "ì¸ì¦ 기관 번들 (PEM í¬ë§·)"
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
-msgstr ""
+msgstr "API URL 복사"
msgid "ClusterIntegration|Copy CA Certificate"
-msgstr ""
+msgstr "CA ì¸ì¦ì„œ 복사"
msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
-msgstr ""
+msgstr "Ingress IP 주소를 í´ë¦½ë³´ë“œë¡œ 복사"
msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
msgstr ""
msgid "ClusterIntegration|Copy Kubernetes cluster name"
-msgstr ""
+msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° ì´ë¦„ 복사"
msgid "ClusterIntegration|Copy Token"
-msgstr ""
+msgstr "í† í° ë³µì‚¬"
msgid "ClusterIntegration|Create Kubernetes cluster"
-msgstr ""
+msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° ìƒì„±"
msgid "ClusterIntegration|Did you know?"
+msgstr "알고 계셨나요?"
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
msgstr ""
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
@@ -1617,13 +1738,13 @@ msgid "ClusterIntegration|Fetching machine types"
msgstr ""
msgid "ClusterIntegration|Fetching projects"
-msgstr ""
+msgstr "프로ì íŠ¸ 가져오기"
msgid "ClusterIntegration|Fetching zones"
-msgstr ""
+msgstr "ì˜ì—­ 가져오기"
msgid "ClusterIntegration|GitLab Integration"
-msgstr ""
+msgstr "GitLab 통합"
msgid "ClusterIntegration|GitLab Runner"
msgstr "ClusterIntegration|GitLab Runner"
@@ -1632,12 +1753,15 @@ msgid "ClusterIntegration|GitLab Runner connects to this project's repository an
msgstr ""
msgid "ClusterIntegration|Google Cloud Platform project"
-msgstr ""
+msgstr "Google Cloud Platform 프로ì íŠ¸"
msgid "ClusterIntegration|Google Kubernetes Engine"
-msgstr ""
+msgstr "Google Kubernetes 엔진"
msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr "Google Kubernetes 엔진 프로ì íŠ¸"
+
+msgid "ClusterIntegration|Group cluster"
msgstr ""
msgid "ClusterIntegration|Helm Tiller"
@@ -1647,7 +1771,7 @@ msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes ap
msgstr ""
msgid "ClusterIntegration|Hide"
-msgstr ""
+msgstr "숨기기"
msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
msgstr ""
@@ -1656,37 +1780,34 @@ msgid "ClusterIntegration|In order to show the health of the cluster, we'll need
msgstr ""
msgid "ClusterIntegration|Ingress"
-msgstr ""
+msgstr "Ingress"
msgid "ClusterIntegration|Ingress IP Address"
-msgstr ""
+msgstr "Ingress ì•„ì´í”¼ 주소"
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
msgstr ""
msgid "ClusterIntegration|Install"
-msgstr ""
+msgstr "설치"
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
-msgstr ""
+msgstr "설치ë¨"
msgid "ClusterIntegration|Installing"
-msgstr ""
+msgstr "설치중"
msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° ìžë™í™” 통합"
msgid "ClusterIntegration|Integration status"
-msgstr ""
+msgstr "통합 ìƒíƒœ"
msgid "ClusterIntegration|Jupyter Hostname"
-msgstr ""
+msgstr "Jupyter 호스트 ì´ë¦„"
msgid "ClusterIntegration|JupyterHub"
msgstr ""
@@ -1694,6 +1815,12 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°"
@@ -1701,31 +1828,19 @@ msgid "ClusterIntegration|Kubernetes cluster details"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° ìƒì„¸"
msgid "ClusterIntegration|Kubernetes cluster health"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration"
-msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° 통합"
-
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
-msgstr "ì´ í”„ë¡œì íŠ¸ì— 대해 Kubernetes í´ëŸ¬ìŠ¤í„° í†µí•©ì´ ë¹„í™œì„±í™”ë˜ì–´ìžˆìŠµë‹ˆë‹¤."
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
-msgstr "ì´ í”„ë¡œì íŠ¸ì— 대해 Kubernetes í´ëŸ¬ìŠ¤í„° í†µí•©ì´ í™œì„±í™”ë˜ì–´ìžˆìŠµë‹ˆë‹¤."
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
-msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° í†µí•©ì´ í™œì„±í™”ë˜ì–´ìžˆìŠµë‹ˆë‹¤. ì´ í†µí•©ì„ ë¹„í™œì„±í™”í•´ë„ ê¸°ì¡´ Kubernetes í´ëŸ¬ìŠ¤í„°ì— ì˜í–¥ì„ 주지는 ì•Šê³  GitLabì˜ ì—°ê²°ì„ ì¼ì‹œì ìœ¼ë¡œë§Œ 해제합니다."
+msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° ìƒíƒœ"
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ê°€ Google Kubernetes Engineì—ì„œ ìƒì„± 중입니다..."
msgid "ClusterIntegration|Kubernetes cluster name"
-msgstr ""
+msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° ì´ë¦„"
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
-msgstr ""
+msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ëŠ” Google Kubernetes Engineì—ì„œ 성공ì ìœ¼ë¡œ ìƒì„±ë˜ì—ˆìŠµë‹ˆë‹¤. Kubernetes í´ëŸ¬ìŠ¤í„°ì˜ 세부 정보를 보려면 페ì´ì§€ë¥¼ 새로 고침하십시오."
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
-msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 사용하면 리뷰 ì‘ìš© í”„ë¡œê·¸ëž¨ì„ ì‚¬ìš©í•˜ê³ , ì‘ìš© í”„ë¡œê·¸ëž¨ì„ ë°°í¬í•˜ê³ , 파ì´í”„ ë¼ì¸ì„ 실행하는 ë“±ì˜ ìž‘ì—…ì„ ì†ì‰½ê²Œ 수행 í•  수 있습니다. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ëŠ” 어플리케ì´ì…˜ì„ ë°°í¬í•˜ê³  ì´ í”„ë¡œì íŠ¸ì— 대한 리뷰 어플리케ì´ì…˜ì„ 제공하는 ë° ì‚¬ìš©í•  수 있습니다."
@@ -1733,16 +1848,13 @@ msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ëŠ” 어플리케ì´ì…˜ì„ ë°°í¬í•˜ê³  ì´ í”„ë¡œ
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
-msgstr "í™˜ê²½ì— ëŒ€í•´ ìžì„¸ížˆ 알아보십시오."
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1752,25 +1864,22 @@ msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to crea
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 만들려면 %{link_to_requirements} ë§í¬ì—ì„œ ê³„ì •ì˜ í•„ìˆ˜ì‚¬í•­ì„ í™•ì¸í•˜ì„¸ìš”."
msgid "ClusterIntegration|Manage"
-msgstr ""
+msgstr "관리"
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
-msgstr ""
+msgstr "%{link_gke}ì— ë°©ë¬¸í•˜ì—¬ Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 관리하세요."
msgid "ClusterIntegration|More information"
-msgstr ""
-
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
+msgstr "ë” ë§Žì€ ì •ë³´"
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
msgid "ClusterIntegration|No projects found"
-msgstr ""
+msgstr "프로ì íŠ¸ ì—†ìŒ"
msgid "ClusterIntegration|No projects matched your search"
-msgstr ""
+msgstr "검색과 ì¼ì¹˜í•˜ëŠ” 프로ì íŠ¸ê°€ 없습니다."
msgid "ClusterIntegration|No zones matched your search"
msgstr ""
@@ -1790,9 +1899,12 @@ msgstr "ë‹¹ì‹ ì˜ Google ê³„ì •ì´ ë‹¤ìŒì˜ 요구 ì‚¬í•­ì„ ì¶©ì¡±í•˜ëŠ”ì§€ í™
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
-msgid "ClusterIntegration|Project namespace"
+msgid "ClusterIntegration|Project cluster"
msgstr ""
+msgid "ClusterIntegration|Project namespace"
+msgstr "프로ì íŠ¸ 네임스페ì´ìŠ¤"
+
msgid "ClusterIntegration|Project namespace (optional, unique)"
msgstr "프로ì íŠ¸ 네임 스페ì´ìŠ¤ (optional, unique)"
@@ -1802,6 +1914,9 @@ msgstr "Prometheus"
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° 통합 알아보기 %{link_to_help_page}"
@@ -1827,14 +1942,11 @@ msgid "ClusterIntegration|Search machine types"
msgstr ""
msgid "ClusterIntegration|Search projects"
-msgstr ""
+msgstr "ClusterIntegration|프로ì íŠ¸ 검색"
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ì˜ 세부 ì •ë³´ 보기 ë° ìˆ˜ì •"
@@ -1842,7 +1954,7 @@ msgid "ClusterIntegration|Select machine type"
msgstr ""
msgid "ClusterIntegration|Select project"
-msgstr ""
+msgstr "프로ì íŠ¸ ì„ íƒ"
msgid "ClusterIntegration|Select project and zone to choose machine type"
msgstr ""
@@ -1874,14 +1986,11 @@ msgstr "설치하는 ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. %{title}"
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr "%{link_to_container_project} 프로ì íŠ¸ì— Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 만들기 위해서는 ì´ ê³„ì •ì— ì•„ëž˜ì— ëª…ì‹œëœ ê¶Œí•œì´ í•„ìš”í•©ë‹ˆë‹¤"
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
-msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° 토글"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° 토글"
@@ -1898,6 +2007,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "ì´ í”„ë¡œì íŠ¸ì— ì—°ê²°ëœ Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 통해 어플리케ì´ì…˜ì„ 리뷰, ë°°í¬í•  수 있고, 파ì´í”„ë¼ì¸ì„ 실행할 수 있습니다. ê·¸ 외ì—ë„ ë§Žì€ ì¼ì„ 훨씬 쉬운 방법으로 수행할 수 있습니다."
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -1908,17 +2020,14 @@ msgid "ClusterIntegration|access to Google Kubernetes Engine"
msgstr "구글 Kubernetes 컨테ì´ë„ˆ ì—”ì§„ì— ì—‘ì„¸ìŠ¤"
msgid "ClusterIntegration|check the pricing here"
-msgstr ""
+msgstr "여기서 ê°€ê²©ì„ í™•ì¸í•˜ì„¸ìš”"
msgid "ClusterIntegration|documentation"
-msgstr ""
+msgstr "문서"
msgid "ClusterIntegration|help page"
msgstr "ë„ì›€ë§ íŽ˜ì´ì§€"
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr "요구 ì‚¬í•­ì„ ì¶©ì¡±"
@@ -1928,34 +2037,43 @@ msgstr "ì •ìƒì ìœ¼ë¡œ 구성ë˜ì—ˆìŒ"
msgid "ClusterIntegration|sign up"
msgstr "ClusterIntegration|가입"
+msgid "Code owners"
+msgstr "코드 소유ìž"
+
msgid "Cohorts"
msgstr ""
msgid "Collapse"
-msgstr ""
+msgstr "ê°ì¶”기"
msgid "Collapse sidebar"
msgstr "사ì´ë“œ ë°” 축소"
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
-msgid "Comments"
+msgid "Comment form position"
msgstr ""
+msgid "Comments"
+msgstr "코멘트"
+
msgid "Commit"
msgid_plural "Commits"
msgstr[0] "커밋"
msgid "Commit (%{commit_count})"
msgid_plural "Commits (%{commit_count})"
-msgstr[0] ""
+msgstr[0] "커밋 (%{commit_count})"
msgid "Commit Message"
-msgstr ""
+msgstr "커밋 메시지"
msgid "Commit duration in minutes for last 30 commits"
msgstr "최근 30 ê±´ì˜ ì»¤ë°‹ 소요시간 (분)"
@@ -1964,10 +2082,10 @@ msgid "Commit message"
msgstr "커밋 메시지"
msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
-msgstr ""
+msgstr "%{ref} ì— ëŒ€í•œ 커밋 통계 %{start_time} - %{end_time}"
msgid "Commit to %{branchName} branch"
-msgstr ""
+msgstr "%{branchName} 브랜치로 커밋"
msgid "CommitBoxTitle|Commit"
msgstr "커밋"
@@ -1975,6 +2093,9 @@ msgstr "커밋"
msgid "CommitMessage|Add %{file_name}"
msgstr "%{file_name} 추가"
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr "커밋"
@@ -1982,40 +2103,40 @@ msgid "Commits feed"
msgstr "커밋 피드"
msgid "Commits per day hour (UTC)"
-msgstr ""
+msgstr "ì¼ì¼ 커밋 (UTC)"
msgid "Commits per day of month"
-msgstr ""
+msgstr "월별 커밋"
msgid "Commits per weekday"
-msgstr ""
+msgstr "í‰ì¼ 커밋"
msgid "Commits|An error occurred while fetching merge requests data."
msgstr ""
msgid "Commits|Commit: %{commitText}"
-msgstr ""
+msgstr "커밋: %{commitText}"
msgid "Commits|History"
msgstr "ì´ë ¥"
msgid "Commits|No related merge requests found"
-msgstr ""
+msgstr "ê´€ë ¨ëœ ë¨¸ì§€ 리퀘스트(MR)ê°€ 없습니다."
msgid "Committed by"
msgstr "커밋한 사용ìž"
msgid "Commit…"
-msgstr ""
+msgstr "커밋..."
msgid "Compare"
msgstr "비êµ"
msgid "Compare Git revisions"
-msgstr ""
+msgstr "Git 리비전 비êµ"
msgid "Compare Revisions"
-msgstr ""
+msgstr "리비전 비êµ"
msgid "Compare changes with the last commit"
msgstr ""
@@ -2027,13 +2148,13 @@ msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
msgstr ""
msgid "CompareBranches|Compare"
-msgstr ""
+msgstr "비êµ"
msgid "CompareBranches|Source"
-msgstr ""
+msgstr "소스"
msgid "CompareBranches|Target"
-msgstr ""
+msgstr "대ìƒ"
msgid "CompareBranches|There isn't anything to compare."
msgstr ""
@@ -2047,7 +2168,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2056,32 +2177,32 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
-msgstr ""
+msgid "Configure push mirrors."
+msgstr "푸시 미러를 구성하십시오."
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
msgstr ""
msgid "Configure the way a user creates a new account."
-msgstr ""
+msgstr "사용ìžê°€ 새로운 ê³„ì •ì„ ë§Œë“œëŠ” ë°©ë²•ì„ ì„¤ì •í•©ë‹ˆë‹¤."
msgid "Connect"
-msgstr ""
+msgstr "ì—°ê²°"
msgid "Connect all repositories"
-msgstr ""
+msgstr "모든 저장소 연결"
msgid "Connect repositories from GitHub"
-msgstr ""
+msgstr "GitHub으로부터 저장소 연결"
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr ""
msgid "Connecting..."
-msgstr ""
+msgstr "연결중..."
msgid "Container Registry"
msgstr "컨테ì´ë„ˆ 레지스트리"
@@ -2132,23 +2253,26 @@ msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access
msgstr ""
msgid "Continue"
-msgstr ""
+msgstr "계ì†"
msgid "Continue to the next step"
-msgstr ""
+msgstr "ë‹¤ìŒ ë‹¨ê³„ë¡œ 진행"
msgid "Continuous Integration and Deployment"
-msgstr ""
+msgstr "지ì†ì  통합 ë° ë°°í¬"
msgid "Contribute to GitLab"
-msgstr ""
+msgstr "GitLabì— ê¸°ì—¬í•˜ì„¸ìš”"
msgid "Contribution"
-msgstr ""
+msgstr "기여"
msgid "Contribution guide"
msgstr "ê¸°ì—¬ì— ëŒ€í•œ 안내"
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2156,7 +2280,7 @@ msgid "Contributors"
msgstr "기여해 주신 분들"
msgid "ContributorsPage|%{startDate} – %{endDate}"
-msgstr ""
+msgstr "%{startDate} - %{endDate}"
msgid "ContributorsPage|Building repository graph."
msgstr "저장소 그래프 작성"
@@ -2165,7 +2289,7 @@ msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limi
msgstr ""
msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
-msgstr ""
+msgstr "잠시만 기다려주십시오, ì´ íŽ˜ì´ì§€ëŠ” 준비가 완료ë˜ë©´ ìžë™ìœ¼ë¡œ 새로고침ë©ë‹ˆë‹¤."
msgid "Control the display of third party offers."
msgstr ""
@@ -2182,65 +2306,89 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
-msgid "Copy SSH public key to clipboard"
+msgid "Copy %{protocol} clone URL"
+msgstr "%{protocol} í´ë¡  URL 복사"
+
+msgid "Copy HTTPS clone URL"
+msgstr "HTTPS í´ë¡  URL 복사"
+
+msgid "Copy ID to clipboard"
msgstr ""
+msgid "Copy SSH clone URL"
+msgstr "SSH í´ë¡  URL 복사"
+
+msgid "Copy SSH public key to clipboard"
+msgstr "SSH 공개키를 í´ë¦½ë³´ë“œì— 복사하기"
+
msgid "Copy URL to clipboard"
msgstr "URLì„ í´ë¦½ë³´ë“œì— 복사"
msgid "Copy branch name to clipboard"
-msgstr ""
+msgstr "브랜치 ì´ë¦„ì„ í´ë¦½ë³´ë“œë¡œ 복사"
msgid "Copy command to clipboard"
-msgstr ""
+msgstr "ëª…ë ¹ì„ í´ë¦½ë³´ë“œë¡œ 복사"
msgid "Copy commit SHA to clipboard"
msgstr "ì»¤ë°‹ì˜ SHA를 í´ë¦½ë³´ë“œë¡œ 복사합니다"
msgid "Copy file path to clipboard"
-msgstr ""
+msgstr "íŒŒì¼ ê²½ë¡œë¥¼ í´ë¦½ë³´ë“œì— 복사"
msgid "Copy incoming email address to clipboard"
+msgstr "수신 ì´ë©”ì¼ ì£¼ì†Œë¥¼ í´ë¦½ ë³´ë“œì— ë³µì‚¬"
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
msgstr ""
msgid "Copy reference to clipboard"
msgstr ""
-msgid "Copy to clipboard"
+msgid "Copy secret to clipboard"
msgstr ""
+msgid "Copy to clipboard"
+msgstr "í´ë¦½ë³´ë“œì— 복사"
+
msgid "Copy token to clipboard"
+msgstr "í´ë¦½ë³´ë“œì— í† í° ë³µì‚¬"
+
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
msgstr ""
msgid "Create"
-msgstr ""
+msgstr "만들기"
msgid "Create New Directory"
msgstr "새 디렉토리 만들기"
msgid "Create a new branch"
-msgstr ""
+msgstr "새 브랜치 ìƒì„±"
msgid "Create a new branch and merge request"
-msgstr ""
+msgstr "새 브랜치 ë° ë¨¸ì§€ 리퀘스트(MR) ìƒì„±"
msgid "Create a new issue"
-msgstr ""
+msgstr "새 ì´ìŠˆ 만들기"
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr "%{protocol}ì„ (를) 통해 Pull 하거나 Push í•  ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°ì„ 만드십시오."
msgid "Create branch"
-msgstr ""
+msgstr "브랜치 ìƒì„±"
msgid "Create commit"
-msgstr ""
+msgstr "커밋 ìƒì„±"
msgid "Create directory"
msgstr "디렉토리 만들기"
msgid "Create empty repository"
-msgstr ""
+msgstr "빈 저장소 ìƒì„±"
msgid "Create epic"
msgstr ""
@@ -2249,13 +2397,13 @@ msgid "Create file"
msgstr "íŒŒì¼ ë§Œë“¤ê¸°"
msgid "Create group"
-msgstr ""
+msgstr "그룹 만들기"
msgid "Create group label"
-msgstr ""
+msgstr "새로운 그룹 ë¼ë²¨"
msgid "Create issue"
-msgstr ""
+msgstr "ì´ìŠˆ 만들기"
msgid "Create lists from labels. Issues with that label appear in that list."
msgstr ""
@@ -2267,7 +2415,7 @@ msgid "Create merge request and branch"
msgstr ""
msgid "Create new branch"
-msgstr ""
+msgstr "새 브랜치 ìƒì„±"
msgid "Create new directory"
msgstr "새 디렉토리 만들기"
@@ -2276,19 +2424,19 @@ msgid "Create new file"
msgstr "새 íŒŒì¼ ë§Œë“¤ê¸°"
msgid "Create new file or directory"
-msgstr ""
+msgstr "새 íŒŒì¼ ë˜ëŠ” 디렉토리 만들기"
msgid "Create new label"
-msgstr ""
+msgstr "새 ë¼ë²¨ 만들기"
msgid "Create new..."
msgstr "새로 만들기 ..."
msgid "Create project label"
-msgstr ""
+msgstr "새로운 프로ì íŠ¸ ë¼ë²¨"
-msgid "CreateNewFork|Fork"
-msgstr "í¬í¬"
+msgid "Create your first page"
+msgstr ""
msgid "CreateTag|Tag"
msgstr "태그"
@@ -2300,10 +2448,10 @@ msgid "Created"
msgstr "ìƒì„±ë¨"
msgid "Created At"
-msgstr ""
+msgstr "ìƒì„± 위치"
msgid "Created by me"
-msgstr ""
+msgstr "ë‚˜ì— ì˜í•´ ìƒì„±ë¨"
msgid "Created on"
msgstr ""
@@ -2312,7 +2460,7 @@ msgid "Created on:"
msgstr ""
msgid "Creating epic"
-msgstr ""
+msgstr "ì—픽 ìƒì„± 중"
msgid "Cron Timezone"
msgstr "Cron 시간대"
@@ -2321,21 +2469,24 @@ msgid "Cron syntax"
msgstr "í¬ë¡  구문"
msgid "Current Branch"
-msgstr ""
+msgstr "현재 브랜치"
msgid "Current node"
-msgstr ""
+msgstr "현재 노드"
msgid "CurrentUser|Profile"
-msgstr "CurrentUser|프로파ì¼"
+msgstr "프로파ì¼"
msgid "CurrentUser|Settings"
-msgstr "CurrentUser|설정"
+msgstr "설정"
msgid "Custom"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ì§€ì •"
msgid "Custom CI config path"
+msgstr "ì‚¬ìš©ìž ì§€ì • CI config 경로"
+
+msgid "Custom hostname (for private commit emails)"
msgstr ""
msgid "Custom notification events"
@@ -2345,10 +2496,10 @@ msgid "Custom notification levels are the same as participating levels. With cus
msgstr "ì‚¬ìš©ìž ì •ì˜ ì•Œë¦¼ ìˆ˜ì¤€ì€ ì°¸ì—¬ 수준과 ë™ì¼í•©ë‹ˆë‹¤. 맞춤 알림 ìˆ˜ì¤€ì„ ì‚¬ìš©í•˜ë©´ ì¼ë¶€ ì´ë²¤íŠ¸ì— 대한 ì•Œë¦¼ë„ ë°›ê²Œë©ë‹ˆë‹¤. ìžì„¸í•œ ë‚´ìš©ì€ %{notification_link}ì„ í™•ì¸í•˜ì‹­ì‹œì˜¤."
msgid "Custom project templates"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ì§€ì • 프로ì íŠ¸ 템플릿"
msgid "Customize colors"
-msgstr ""
+msgstr "ìƒ‰ìƒ ë§žì¶¤í™”"
msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -2356,6 +2507,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr "사ì´í´ 분ì„"
@@ -2384,7 +2538,7 @@ msgid "CycleAnalyticsStage|Test"
msgstr "테스트"
msgid "Dashboard"
-msgstr ""
+msgstr "대시보드"
msgid "DashboardProjects|All"
msgstr "모든"
@@ -2393,20 +2547,23 @@ msgid "DashboardProjects|Personal"
msgstr "ê°œì¸"
msgid "Date picker"
-msgstr ""
+msgstr "날짜 ì„ íƒ"
msgid "Debug"
-msgstr ""
+msgstr "디버그"
msgid "Dec"
-msgstr ""
+msgstr "12ì›”"
msgid "December"
-msgstr ""
+msgstr "12ì›”"
msgid "Decline and sign out"
msgstr "취소 ë° ë¡œê·¸ì•„ì›ƒ"
+msgid "Default Branch"
+msgstr "기본 브랜치"
+
msgid "Default classification label"
msgstr ""
@@ -2419,23 +2576,41 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "cron êµ¬ë¬¸ì„ ì‚¬ìš©í•˜ì—¬ ì‚¬ìš©ìž ì •ì˜ íŒ¨í„´ ì •ì˜"
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr "삭제 "
msgid "Delete Package"
-msgstr ""
+msgstr "패키지 삭제"
msgid "Delete Snippet"
+msgstr "스니펫 삭제"
+
+msgid "Delete comment"
msgstr ""
msgid "Delete list"
msgstr ""
msgid "Deleted"
-msgstr ""
+msgstr "ì‚­ì œë¨"
msgid "Deny"
-msgstr ""
+msgstr "거부"
msgid "Deploy"
msgid_plural "Deploys"
@@ -2445,58 +2620,58 @@ msgid "Deploy Keys"
msgstr "ë°°í¬ í‚¤"
msgid "DeployKeys|+%{count} others"
-msgstr "DeployKeys|+%{count} 기타"
+msgstr "+%{count} 기타"
msgid "DeployKeys|Current project"
-msgstr "DeployKeys|현재 프로ì íŠ¸"
+msgstr "현재 프로ì íŠ¸"
msgid "DeployKeys|Deploy key"
-msgstr "DeployKeys|ë°°í¬ í‚¤"
+msgstr "ë°°í¬ í‚¤"
msgid "DeployKeys|Enabled deploy keys"
-msgstr "DeployKeys|í™œì„±í™”ëœ ë°°í¬ í‚¤"
+msgstr "í™œì„±í™”ëœ ë°°í¬ í‚¤"
msgid "DeployKeys|Error enabling deploy key"
-msgstr "DeployKeys|ë°°í¬í‚¤ 사용 오류"
+msgstr "ë°°í¬í‚¤ 사용 오류"
msgid "DeployKeys|Error getting deploy keys"
-msgstr "DeployKeys|ë°°í¬í‚¤ 가져오기 오류"
+msgstr "ë°°í¬í‚¤ 가져오기 오류"
msgid "DeployKeys|Error removing deploy key"
-msgstr "DeployKeys|ë°°í¬í‚¤ 제거 오류"
+msgstr "ë°°í¬í‚¤ 제거 오류"
msgid "DeployKeys|Expand %{count} other projects"
msgstr "DeployKeys|확장 %{count} 기타 프로ì íŠ¸"
msgid "DeployKeys|Loading deploy keys"
-msgstr "DeployKeys|ë°°í¬í‚¤ 로드"
+msgstr "ë°°í¬í‚¤ 로드"
msgid "DeployKeys|No deploy keys found. Create one with the form above."
-msgstr "DeployKeys|ë°°í¬í‚¤ê°€ 존재하지 않습니다. ìœ„ì˜ ì–‘ì‹ì„ ì´ìš©í•´ 만드세요."
+msgstr "ë°°í¬í‚¤ê°€ 존재하지 않습니다. ìœ„ì˜ ì–‘ì‹ì„ ì´ìš©í•´ 만드세요."
msgid "DeployKeys|Privately accessible deploy keys"
-msgstr "DeployKeys|비공개ì ìœ¼ë¡œ 엑세스 가능한 ë°°í¬í‚¤"
+msgstr "비공개ì ìœ¼ë¡œ 엑세스 가능한 ë°°í¬í‚¤"
msgid "DeployKeys|Project usage"
-msgstr "DeployKeys|프로ì íŠ¸ 사용현황"
+msgstr "프로ì íŠ¸ 사용현황"
msgid "DeployKeys|Publicly accessible deploy keys"
-msgstr "DeployKeys|공개ì ìœ¼ë¡œ 엑세스 가능한 ë°°í¬í‚¤"
+msgstr "공개ì ìœ¼ë¡œ 엑세스 가능한 ë°°í¬í‚¤"
msgid "DeployKeys|Read access only"
-msgstr "DeployKeys|ì½ê¸° 엑세스 ì „ìš©"
+msgstr "ì½ê¸° 엑세스 ì „ìš©"
msgid "DeployKeys|Write access allowed"
-msgstr "DeployKeys|쓰기 액세스 허용"
+msgstr "쓰기 액세스 허용"
msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
-msgstr "DeployKeys|ì´ ë°°í¬í‚¤ë¥¼ 제거하려고 합니다. 확실합니까?"
+msgstr "ì´ ë°°í¬í‚¤ë¥¼ 제거하려고 합니다. 확실합니까?"
msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
-msgstr ""
+msgstr "활성 ë°°í¬ í† í° (%{active_tokens})"
msgid "DeployTokens|Add a deploy token"
-msgstr ""
+msgstr "ë°°í¬ í† í° ì¶”ê°€"
msgid "DeployTokens|Allows read-only access to the registry images"
msgstr ""
@@ -2505,70 +2680,76 @@ msgid "DeployTokens|Allows read-only access to the repository"
msgstr ""
msgid "DeployTokens|Copy deploy token to clipboard"
-msgstr ""
+msgstr "ë°°í¬ í† í°ì„ í´ë¦½ë³´ë“œì— 복사"
msgid "DeployTokens|Copy username to clipboard"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ì´ë¦„ì„ í´ë¦½ë³´ë“œì— 복사"
msgid "DeployTokens|Create deploy token"
-msgstr ""
+msgstr "ë°°í¬ í† í° ë§Œë“¤ê¸°"
msgid "DeployTokens|Created"
-msgstr ""
+msgstr "만들어ì§"
msgid "DeployTokens|Deploy Tokens"
-msgstr ""
+msgstr "ë°°í¬ í† í°"
msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
msgstr ""
msgid "DeployTokens|Expires"
-msgstr ""
+msgstr "만료"
msgid "DeployTokens|Name"
-msgstr ""
+msgstr "ì´ë¦„"
msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
msgstr ""
msgid "DeployTokens|Revoke"
-msgstr ""
+msgstr "취소"
msgid "DeployTokens|Revoke %{name}"
-msgstr ""
+msgstr "%{name} 취소"
msgid "DeployTokens|Scopes"
-msgstr ""
+msgstr "범위"
msgid "DeployTokens|This action cannot be undone."
-msgstr ""
+msgstr "ì´ ìž‘ì—…ì€ ë˜ëŒë¦´ 수 없습니다."
msgid "DeployTokens|This project has no active Deploy Tokens."
-msgstr ""
+msgstr "ì´ í”„ë¡œì íŠ¸ì—는 활성 ë°°í¬ í† í°ì´ 없습니다."
msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
-msgstr ""
+msgstr "ì´ í† í°ì„ 암호로 사용합니다. 다시는 확ì¸í•  수 없으므로 토í°ì„ 저장해 ë‘십시오."
msgid "DeployTokens|Use this username as a login."
-msgstr ""
+msgstr "ì´ ì‚¬ìš©ìž ì´ë¦„ì„ ë¡œê·¸ì¸ìœ¼ë¡œ 사용합니다."
msgid "DeployTokens|Username"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ì´ë¦„"
msgid "DeployTokens|You are about to revoke"
-msgstr ""
+msgstr "취소하려고 합니다."
msgid "DeployTokens|Your New Deploy Token"
-msgstr ""
+msgstr "새 ë°°í¬ í† í°"
msgid "DeployTokens|Your new project deploy token has been created."
+msgstr "프로ì íŠ¸ ë°°í¬ í† í°ì„ 새로 만들었습니다."
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
msgstr ""
msgid "Deprioritize label"
msgstr ""
msgid "Descending"
-msgstr ""
+msgstr "내림차순"
msgid "Description"
msgstr "설명"
@@ -2577,31 +2758,37 @@ msgid "Description templates allow you to define context-specific templates for
msgstr ""
msgid "Description:"
-msgstr ""
+msgstr "설명:"
msgid "Destroy"
-msgstr ""
+msgstr "제거"
msgid "Details"
msgstr "ìƒì„¸"
msgid "Detect host keys"
+msgstr "호스트 키 발견"
+
+msgid "Diff content limits"
msgstr ""
-msgid "Diffs|No file name available"
+msgid "Diff limits"
msgstr ""
+msgid "Diffs|No file name available"
+msgstr "사용가능한 íŒŒì¼ ì´ë¦„ì´ ì—†ìŠµë‹ˆë‹¤."
+
msgid "Diffs|Something went wrong while fetching diff lines."
msgstr ""
msgid "Direction"
-msgstr ""
+msgstr "ë°©í–¥"
msgid "Directory name"
msgstr "디렉토리 ì´ë¦„"
msgid "Disable"
-msgstr ""
+msgstr "사용 안 함"
msgid "Disable for this project"
msgstr "ì´ í”„ë¡œì íŠ¸ì— 대해 사용 중지"
@@ -2609,10 +2796,25 @@ msgstr "ì´ í”„ë¡œì íŠ¸ì— 대해 사용 중지"
msgid "Disable group Runners"
msgstr "그룹 Runner 사용 중지"
+msgid "Discard"
+msgstr "취소"
+
+msgid "Discard all changes"
+msgstr "모든 변경 취소"
+
+msgid "Discard all unstaged changes?"
+msgstr "스테ì´ì§•ë˜ì§€ ì•Šì€ ëª¨ë“  ë³€ê²½ì‚¬í•­ì„ ì·¨ì†Œí• ê¹Œìš”?"
+
msgid "Discard changes"
msgstr "변경 ì‚¬í•­ì„ ì·¨ì†Œ"
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
+msgstr "초안 삭제"
+
+msgid "Discard review"
msgstr ""
msgid "Discover GitLab Geo."
@@ -2622,7 +2824,7 @@ msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr ""
msgid "Dismiss"
-msgstr ""
+msgstr "닫기"
msgid "Dismiss Cycle Analytics introduction box"
msgstr "사ì´í´ ë¶„ì„ ì†Œê°œ 박스 제거"
@@ -2630,6 +2832,9 @@ msgstr "사ì´í´ ë¶„ì„ ì†Œê°œ 박스 제거"
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2643,7 +2848,7 @@ msgid "Don't show again"
msgstr "다시 표시하지 ì•ŠìŒ"
msgid "Done"
-msgstr ""
+msgstr "완료"
msgid "Download"
msgstr "다운로드"
@@ -2673,13 +2878,13 @@ msgid "DownloadSource|Download"
msgstr "다운로드"
msgid "Downvotes"
-msgstr ""
+msgstr "비추천"
msgid "Due date"
-msgstr ""
+msgstr "마ê°ì¼"
msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
-msgstr ""
+msgstr "ì´ ê³¼ì •ì—ì„œ GitLabì˜ URLì„ ë¬»ëŠ” 메시지가 나타납니다. 아래 í‘œì‹œëœ URLì„ ì‚¬ìš©í•˜ì‹­ì‹œì˜¤."
msgid "Each Runner can be in one of the following states:"
msgstr "ê° Runner는 ë‹¤ìŒ ìƒíƒœ 중 í•˜ë‚˜ì¼ ìˆ˜ 있습니다."
@@ -2688,34 +2893,34 @@ msgid "Edit"
msgstr "편집"
msgid "Edit Label"
-msgstr ""
+msgstr "ë¼ë²¨ 편집"
msgid "Edit Pipeline Schedule %{id}"
msgstr "파ì´í”„ë¼ì¸ 스케줄 편집 %{id}"
msgid "Edit Snippet"
-msgstr ""
+msgstr "스니펫 편집"
msgid "Edit application"
-msgstr ""
+msgstr "애플리케ì´ì…˜ 수정"
msgid "Edit files in the editor and commit changes here"
-msgstr ""
+msgstr "ì—디터ì—ì„œ 파ì¼ì„ 편집하고 여기서 ë³€ê²½ì‚¬í•­ì„ ì»¤ë°‹í•˜ì„¸ìš”."
msgid "Edit group: %{group_name}"
-msgstr ""
+msgstr "그룹 편집: %{group_name}"
msgid "Edit identity for %{user_name}"
-msgstr ""
+msgstr "%{user_name}ì˜ ì‹ ì› íŽ¸ì§‘"
msgid "Elasticsearch"
-msgstr ""
+msgstr "Elasticsearch"
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
-msgstr ""
+msgstr "ì´ë©”ì¼"
msgid "Email patch"
msgstr ""
@@ -2724,22 +2929,22 @@ msgid "Emails"
msgstr "ì´ë©”ì¼"
msgid "Embed"
-msgstr ""
+msgstr "임베드"
msgid "Enable"
-msgstr ""
+msgstr "사용"
msgid "Enable Auto DevOps"
-msgstr ""
+msgstr "ìžë™ DevOps 활성화"
msgid "Enable Pseudonymizer data collection"
msgstr ""
msgid "Enable SAML authentication for this group"
-msgstr ""
+msgstr "ì´ ê·¸ë£¹ì— SAML ì¸ì¦ 사용"
msgid "Enable Sentry for error reporting and logging."
-msgstr ""
+msgstr "Sentry를 사용해 오류 보고와 ë¡œê¹…ì„ í™œì„±í™”í•©ë‹ˆë””."
msgid "Enable and configure InfluxDB metrics."
msgstr ""
@@ -2756,9 +2961,6 @@ msgstr "ì´ í”„ë¡œì íŠ¸ì— 대해 사용"
msgid "Enable group Runners"
msgstr "그룹 Runner 사용"
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2766,31 +2968,37 @@ msgid "Enable or disable version check and usage ping."
msgstr ""
msgid "Enable reCAPTCHA or Akismet and set IP limits."
-msgstr ""
+msgstr "reCAPTCHA ë˜ëŠ” Akismetì„ í™œì„±í™”í•˜ê³  IP ì œí•œì„ ì„¤ì •í•©ë‹ˆë‹¤."
msgid "Enable the Performance Bar for a given group."
msgstr ""
-msgid "Enabled"
+msgid "Enable usage ping"
msgstr ""
-msgid "Ends at (UTC)"
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
msgstr ""
+msgid "Enabled"
+msgstr "활성화ë¨"
+
+msgid "Ends at (UTC)"
+msgstr "(UTC)ì— ì¢…ë£Œë©ë‹ˆë‹¤"
+
msgid "Enter in your Bitbucket Server URL and personal access token below"
-msgstr ""
+msgstr "아래 Bitbucket Server URL ë° ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°ì„ 입력하십시오."
msgid "Enter the issue description"
-msgstr ""
+msgstr "ì´ìŠˆ 설명 ìž…ë ¥"
msgid "Enter the issue title"
-msgstr ""
+msgstr "ì´ìŠˆ 제목 ìž…ë ¥"
msgid "Enter the merge request description"
-msgstr ""
+msgstr "머지 리퀘스트(MR) ì„¤ëª…ì„ ìž…ë ¥ 해주세요"
msgid "Enter the merge request title"
-msgstr ""
+msgstr "머지 리퀘스트(MR) ì œëª©ì„ ìž…ë ¥ 해주세요"
msgid "Environments"
msgstr "환경"
@@ -2799,7 +3007,7 @@ msgid "Environments|An error occurred while fetching the environments."
msgstr ""
msgid "Environments|An error occurred while making the request."
-msgstr ""
+msgstr "ìš”ì²­ì„ ë§Œë“œëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Environments|An error occurred while stopping the environment, please try again"
msgstr ""
@@ -2808,31 +3016,31 @@ msgid "Environments|Are you sure you want to stop this environment?"
msgstr ""
msgid "Environments|Commit"
-msgstr ""
+msgstr "커밋"
msgid "Environments|Deploy to..."
msgstr ""
msgid "Environments|Deployment"
-msgstr ""
+msgstr "ë°°í¬"
msgid "Environments|Environment"
-msgstr ""
+msgstr "환경"
msgid "Environments|Environments"
-msgstr ""
+msgstr "환경"
msgid "Environments|Environments are places where code gets deployed, such as staging or production."
msgstr ""
msgid "Environments|Job"
-msgstr ""
+msgstr "ìž‘ì—…"
msgid "Environments|Learn more about stopping environments"
msgstr ""
msgid "Environments|New environment"
-msgstr ""
+msgstr "새 환경"
msgid "Environments|No deployments yet"
msgstr ""
@@ -2862,34 +3070,34 @@ msgid "Environments|Rollback environment"
msgstr ""
msgid "Environments|Show all"
-msgstr ""
+msgstr "ëª¨ë‘ ë³´ê¸°"
msgid "Environments|Stop"
-msgstr ""
+msgstr "중지"
msgid "Environments|Stop environment"
-msgstr ""
+msgstr "중지 환경"
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
-msgstr ""
+msgstr "보호ë¨"
msgid "Epic"
-msgstr ""
+msgstr "ì—픽"
msgid "Epic will be removed! Are you sure?"
-msgstr ""
+msgstr "ì—í”½ì´ ì‚­ì œë©ë‹ˆë‹¤! 확실합니까?"
msgid "Epics"
-msgstr ""
+msgstr "ì—픽"
msgid "Epics Roadmap"
-msgstr ""
+msgstr "ì—픽 로드맵"
msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
msgstr ""
@@ -2898,37 +3106,37 @@ msgid "Epics|An error occurred while saving %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
-msgstr ""
+msgstr "ì´ê²ƒì„ 어떻게 í•´ê²°í•  수 있습니까?"
msgid "Epics|More information"
-msgstr ""
+msgstr "ìžì„¸í•œ ë‚´ìš©"
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
-msgstr ""
+msgstr "시작"
msgid "Error"
-msgstr ""
+msgstr "ì—러"
msgid "Error Reporting and Logging"
-msgstr ""
+msgstr "오류 ë³´ê³  ë° ë¡œê¹…"
msgid "Error creating epic"
msgstr ""
msgid "Error fetching contributors data."
-msgstr ""
+msgstr "ê¸°ì—¬ìž ë°ì´í„°ë¥¼ 가져오는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Error fetching labels."
-msgstr ""
+msgstr "ë¼ë²¨ì„ 가져 오는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Error fetching network graph."
msgstr ""
@@ -2943,16 +3151,16 @@ msgid "Error loading branch data. Please try again."
msgstr ""
msgid "Error loading branches."
-msgstr ""
+msgstr "브랜치 로드 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Error loading last commit."
-msgstr ""
+msgstr "마지막 ì»¤ë°‹ì„ ë¡œë“œí•˜ëŠ” 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Error loading markdown preview"
msgstr ""
msgid "Error loading merge requests."
-msgstr ""
+msgstr "머지 리퀘스트(MR)를 로드하는 중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "Error loading project data. Please try again."
msgstr ""
@@ -3009,31 +3217,37 @@ msgid "Every week (Sundays at 4:00am)"
msgstr "매주 (ì¼ìš”ì¼ ì˜¤ì „ 4ì‹œì—)"
msgid "Everyone can contribute"
-msgstr ""
+msgstr "모ë‘ê°€ 기여할 수 있ìŒ."
msgid "Expand"
-msgstr ""
+msgstr "펼치기"
msgid "Expand all"
-msgstr ""
+msgstr "ëª¨ë‘ í™•ìž¥"
msgid "Expand sidebar"
msgstr "사ì´ë“œë°” 확장"
-msgid "Explore"
+msgid "Expiration date"
+msgstr "만료ì¼"
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
msgstr ""
+msgid "Explore"
+msgstr "íƒìƒ‰"
+
msgid "Explore GitLab"
-msgstr ""
+msgstr "GitLab 둘러보기"
msgid "Explore Groups"
-msgstr ""
+msgstr "그룹 둘러보기"
msgid "Explore groups"
-msgstr ""
+msgstr "그룹 찾아보기"
msgid "Explore projects"
-msgstr ""
+msgstr "프로ì íŠ¸ 둘러보기"
msgid "Explore public groups"
msgstr "공개 그룹 íƒìƒ‰"
@@ -3042,10 +3256,10 @@ msgid "External Classification Policy Authorization"
msgstr ""
msgid "External authentication"
-msgstr ""
+msgstr "외부 ì¸ì¦"
msgid "External authorization denied access to this project"
-msgstr ""
+msgstr "외부 ì¸ì¦ì´ ì´ í”„ë¡œì íŠ¸ì— 대한 액세스를 거부했습니다."
msgid "External authorization request timeout"
msgstr ""
@@ -3060,13 +3274,13 @@ msgid "ExternalAuthorizationService|When no classification label is set the defa
msgstr ""
msgid "Facebook"
-msgstr ""
+msgstr "Facebook"
msgid "Failed"
-msgstr ""
+msgstr "실패"
msgid "Failed Jobs"
-msgstr ""
+msgstr "작업 실패"
msgid "Failed to change the owner"
msgstr "소유ìžë¥¼ 변경하지 못했습니다"
@@ -3074,6 +3288,12 @@ msgstr "소유ìžë¥¼ 변경하지 못했습니다"
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3083,39 +3303,129 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "파ì´í”„ë¼ì¸ ìŠ¤ì¼€ì¤„ì„ ì œê±°í•˜ì§€ 못했습니다."
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
msgid "Failure"
-msgstr ""
+msgstr "실패"
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
-msgid "Feb"
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
msgstr ""
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "Feb"
+msgstr "2ì›”"
+
msgid "February"
msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr "íŒŒì¼ í…œí”Œë¦¿"
+
msgid "Files"
msgstr "파ì¼"
msgid "Files (%{human_size})"
-msgstr ""
+msgstr "íŒŒì¼ (%{human_size})"
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr ""
msgid "Filter"
+msgstr "í•„í„°"
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
msgstr ""
msgid "Filter by commit message"
msgstr "커밋 메시지로 필터"
+msgid "Filter..."
+msgstr "í•„í„°..."
+
msgid "Find by path"
msgstr "경로로 찾기"
@@ -3129,10 +3439,13 @@ msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/Google
msgstr ""
msgid "Fingerprints"
+msgstr "지문"
+
+msgid "Finish review"
msgstr ""
msgid "Finished"
-msgstr ""
+msgstr "완료"
msgid "FirstPushedBy|First"
msgstr "처ìŒ"
@@ -3143,35 +3456,35 @@ msgstr "푸시한 사용ìž"
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
msgstr ""
msgid "Fixed:"
-msgstr ""
+msgstr "수정ë¨:"
msgid "FogBugz Email"
-msgstr ""
+msgstr "FogBugz ì´ë©”ì¼"
msgid "FogBugz Import"
-msgstr ""
+msgstr "FogBugz 가져오기"
msgid "FogBugz Password"
-msgstr ""
+msgstr "FogBugz 암호"
msgid "FogBugz URL"
-msgstr ""
+msgstr "FogBugz URL"
msgid "FogBugz import"
-msgstr ""
+msgstr "FogBugz 가져오기"
msgid "Follow the steps below to export your Google Code project data."
msgstr ""
msgid "Font Color"
-msgstr ""
+msgstr "글꼴 색"
msgid "Footer message"
msgstr ""
@@ -3182,48 +3495,53 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] "í¬í¬"
-
msgid "ForkedFromProjectPath|Forked from"
-msgstr "í¬í¬í•œ 사용ìž"
+msgstr "다른 프로ì íŠ¸ì—ì„œ í¬í¬ë¨: "
msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
msgstr "%{project_name} (ì‚­ì œ) ì—ì„œ í¬í¬ë¨"
msgid "Forking in progress"
-msgstr ""
+msgstr "í¬í¬ 진행중"
msgid "Format"
-msgstr ""
+msgstr "í¬ë§·"
msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ".gitlab-ci.ymlì—ì„œ 오류를 발견했습니다:"
+
+msgid "Free Trial of GitLab.com Gold"
msgstr ""
msgid "From %{provider_title}"
-msgstr ""
+msgstr "%{provider_title}ì—ì„œ"
msgid "From Bitbucket"
-msgstr ""
+msgstr "Bitbucketì—ì„œ"
msgid "From Bitbucket Server"
-msgstr ""
+msgstr "Bitbucket 서버ì—ì„œ"
msgid "From FogBugz"
-msgstr ""
+msgstr "FogBugzì—ì„œ"
msgid "From GitLab.com"
-msgstr ""
+msgstr "GitLab.comì—ì„œ"
msgid "From Google Code"
-msgstr ""
+msgstr "Google Codeì—ì„œ"
msgid "From issue creation until deploy to production"
msgstr "ì´ìŠˆ ìƒì„±ì—ì„œ 프로ë•ì…˜ ë°°í¬ê¹Œì§€"
@@ -3249,6 +3567,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3256,7 +3577,7 @@ msgid "Geo allows you to replicate your GitLab instance to other geographical lo
msgstr ""
msgid "GeoNodeSyncStatus|Node is failing or broken."
-msgstr ""
+msgstr "노드가 실패하거나 깨졌습니다."
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr ""
@@ -3423,10 +3744,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3435,6 +3768,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3456,7 +3792,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3468,6 +3804,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3477,19 +3816,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3499,7 +3844,7 @@ msgid "Geo|Shards to synchronize"
msgstr ""
msgid "Geo|Status"
-msgstr ""
+msgstr "ìƒíƒœ"
msgid "Geo|Synced"
msgstr ""
@@ -3507,6 +3852,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3517,49 +3868,64 @@ msgid "Geo|Verification failed - %{error}"
msgstr ""
msgid "Geo|Waiting for scheduler"
+msgstr "스케줄러 대기 중"
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
-msgid "Git"
+msgid "Geo|misconfigured"
msgstr ""
-msgid "Git repository URL"
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
msgstr ""
+msgid "Git"
+msgstr "Git"
+
+msgid "Git repository URL"
+msgstr "Git 저장소 URL"
+
msgid "Git revision"
msgstr "Git 리비전"
-msgid "Git storage health information has been reset"
-msgstr "git storage ìƒíƒœ ì •ë³´ê°€ 초기화ë˜ì—ˆìŠµë‹ˆë‹¤."
-
msgid "Git strategy for pipelines"
msgstr ""
msgid "Git version"
-msgstr ""
+msgstr "Git 버전"
msgid "GitHub import"
-msgstr ""
+msgstr "GitHub 가져오기"
msgid "GitLab CI Linter has been moved"
-msgstr ""
+msgstr "GitLab CI Linterê°€ ì´ë™ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "GitLab Geo"
-msgstr ""
+msgstr "GitLab Geo"
msgid "GitLab Group Runners can execute code for all the projects in this group."
msgstr ""
msgid "GitLab Import"
-msgstr ""
+msgstr "GitLab 가져오기"
msgid "GitLab User"
-msgstr ""
+msgstr "GitLab 사용ìž"
msgid "GitLab project export"
-msgstr ""
+msgstr "GitLab 프로ì íŠ¸ 내보내기"
msgid "GitLab single sign on URL"
msgstr ""
@@ -3568,61 +3934,55 @@ msgid "GitLab will run a background job that will produce pseudonymized CSVs of
msgstr ""
msgid "GitLab.com import"
-msgstr ""
+msgstr "GitLab.com 가져오기"
msgid "GitLab’s issue tracker"
-msgstr ""
+msgstr "GitLabì˜ ì´ìŠˆ 트래커"
msgid "Gitaly"
-msgstr ""
+msgstr "Gitaly"
msgid "Gitaly Servers"
msgstr "Gitaly 서버"
msgid "Gitaly|Address"
-msgstr ""
+msgstr "주소"
msgid "Gitea Host URL"
-msgstr ""
+msgstr "Gitea 호스트 URL"
msgid "Gitea Import"
-msgstr ""
+msgstr "Gitea 가져오기"
msgid "Go Back"
-msgstr ""
+msgstr "ì´ì „으로"
msgid "Go back"
-msgstr ""
+msgstr "뒤로 가기"
msgid "Go to"
msgstr ""
msgid "Go to %{link_to_google_takeout}."
-msgstr ""
-
-msgid "Go to your fork"
-msgstr "ë‹¹ì‹ ì˜ í¬í¬ë¡œ ì´ë™í•˜ì„¸ìš”"
-
-msgid "GoToYourFork|Fork"
-msgstr "í¬í¬"
+msgstr "%{link_to_google_takeout}ë¡œ ì´ë™í•˜ì‹­ì‹œì˜¤."
msgid "Google Code import"
-msgstr ""
+msgstr "Google Code 가져오기"
msgid "Google Takeout"
-msgstr ""
+msgstr "Google Takeout"
msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
msgstr "Google ì¸ì¦ì„ 사용할 수 없습니다. %{link_to_documentation} GitLab 관리ìžì—게 문ì˜í•˜ì„¸ìš”."
msgid "Got it!"
-msgstr ""
+msgstr "확ì¸!"
msgid "Graph"
msgstr "그래프"
msgid "Group"
-msgstr ""
+msgstr "그룹"
msgid "Group CI/CD settings"
msgstr "그룹 CI/CD 설정"
@@ -3636,18 +3996,33 @@ msgstr "그룹 ID"
msgid "Group Runners"
msgstr "그룹 Runner"
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
+msgstr "그룹 아바타"
+
+msgid "Group description"
msgstr ""
-msgid "Group details"
+msgid "Group description (optional)"
msgstr ""
+msgid "Group details"
+msgstr "그룹 세부 정보"
+
msgid "Group info:"
-msgstr ""
+msgstr "그룹 정보:"
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3666,13 +4041,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3688,20 +4063,17 @@ msgid "GroupRoadmap|Until %{dateWord}"
msgstr ""
msgid "GroupSettings|Badges"
-msgstr ""
+msgstr "배지"
msgid "GroupSettings|Customize your group badges."
-msgstr ""
+msgstr "그룹 배지를 ì‚¬ìš©ìž ì •ì˜í•©ë‹ˆë‹¤."
msgid "GroupSettings|Learn more about badges."
-msgstr ""
+msgstr "ë°°ì§€ì— ëŒ€í•´ ìžì„¸ížˆ 알아보세요."
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "%{group} ë‚´ì˜ í”„ë¡œì íŠ¸ë¥¼ 다른 ê·¸ë£¹ì— ê³µìœ í•  수 없게 합니다."
-msgid "GroupSettings|Share with group lock"
-msgstr "그룹 lock ì„ ê³µìœ í•©ë‹ˆë‹¤."
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "ì´ ì„¤ì •ì€ %{ancestor_group} ì— ì ìš©ë˜ê³  ì´ í•˜ìœ„ 그룹ì—ì„œ ìž¬ì •ì˜ ë˜ì—ˆìŠµë‹ˆë‹¤."
@@ -3721,7 +4093,7 @@ msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name
msgstr "%{ancestor_group_name} ì—ì„œ 그룹 lock 공유 제거"
msgid "Groups"
-msgstr ""
+msgstr "그룹들"
msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
msgstr ""
@@ -3754,25 +4126,25 @@ msgid "GroupsEmptyState|If you organize your projects under a group, it works li
msgstr "프로ì íŠ¸ë¥¼ ê·¸ë£¹ì— êµ¬ì„±í•˜ë©´, 마치 í´ë”처럼 ë™ìž‘합니다."
msgid "GroupsEmptyState|No groups found"
-msgstr ""
+msgstr "ê·¸ë£¹ì´ ì—†ìŠµë‹ˆë‹¤."
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
-msgid "GroupsTree|Create a project in this group."
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
msgstr ""
+msgid "GroupsTree|Create a project in this group."
+msgstr "ì´ ê·¸ë£¹ì— í”„ë¡œì íŠ¸ë¥¼ 만듭니다."
+
msgid "GroupsTree|Create a subgroup in this group."
-msgstr ""
+msgstr "ì´ ê·¸ë£¹ì— í•˜ìœ„ ê·¸ë£¹ì„ ë§Œë“­ë‹ˆë‹¤."
msgid "GroupsTree|Edit group"
msgstr "그룹 편집"
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
-msgstr ""
-
-msgid "GroupsTree|Filter by name..."
-msgstr ""
+msgstr "그룹ì—ì„œ 탈퇴 하지 못했습니다. ë‹¹ì‹ ì´ ê·¸ë£¹ì˜ ìœ ì¼í•œ 소유ìžê°€ 아닌지 확ì¸ë°”ëžë‹ˆë‹¤."
msgid "GroupsTree|Leave this group"
msgstr "ì´ ê·¸ë£¹ 떠나기"
@@ -3780,11 +4152,14 @@ msgstr "ì´ ê·¸ë£¹ 떠나기"
msgid "GroupsTree|Loading groups"
msgstr "그룹 로딩중입니다"
-msgid "GroupsTree|Sorry, no groups matched your search"
-msgstr "죄송합니다, 검색과 ì¼ì¹˜í•˜ëŠ” ê·¸ë£¹ì´ ì—†ìŠµë‹ˆë‹¤"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
-msgstr "죄송합니다, 검색과 ì¼ì¹˜í•˜ëŠ” 그룹 í˜¹ì€ í”„ë¡ì íŠ¸ê°€ 없습니다"
+msgid "GroupsTree|Search by name"
+msgstr "ì´ë¦„으로 검색"
msgid "Have your users email"
msgstr ""
@@ -3811,7 +4186,7 @@ msgid "HealthCheck|Unhealthy"
msgstr "비정ìƒ"
msgid "Help"
-msgstr ""
+msgstr "ë„움ë§"
msgid "Help page"
msgstr ""
@@ -3825,9 +4200,12 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
-msgstr[0] ""
+msgstr[0] "값 숨기기"
msgid "Hide whitespace changes"
msgstr ""
@@ -3839,40 +4217,40 @@ msgid "Housekeeping successfully started"
msgstr "Housekeepingì´ ì„±ê³µì ìœ¼ë¡œ 시작ë˜ì—ˆìŠµë‹ˆë‹¤"
msgid "I accept the %{terms_link}"
-msgstr ""
+msgstr "%{terms_link}ì— ë™ì˜í•©ë‹ˆë‹¤."
msgid "I accept the|Terms of Service and Privacy Policy"
-msgstr ""
+msgstr "서비스 약관 ë° ê°œì¸ì •ë³´ 보호 ì •ì±…"
msgid "ID"
-msgstr ""
+msgstr "ID"
msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
msgstr ""
msgid "IDE|Back"
-msgstr ""
+msgstr "뒤로"
msgid "IDE|Client side evaluation"
msgstr ""
msgid "IDE|Commit"
-msgstr "IDE|커밋"
+msgstr "커밋"
msgid "IDE|Edit"
-msgstr "IDE|편집"
+msgstr "편집"
msgid "IDE|Get started with Live Preview"
-msgstr ""
+msgstr "실시간 미리보기 시작하기"
msgid "IDE|Go to project"
-msgstr ""
+msgstr "프로ì íŠ¸ë¡œ ì´ë™"
msgid "IDE|Live Preview"
-msgstr ""
+msgstr "실시간 미리보기"
msgid "IDE|Open in file view"
-msgstr ""
+msgstr "íŒŒì¼ ë·°ì–´ë¡œ 열기"
msgid "IDE|Preview your web application using Web IDE client-side evaluation."
msgstr ""
@@ -3884,7 +4262,7 @@ msgid "IDE|Review"
msgstr "리뷰"
msgid "IP Address"
-msgstr ""
+msgstr "IP 주소"
msgid "Identifier"
msgstr ""
@@ -3902,7 +4280,7 @@ msgid "If disabled, the access level will depend on the user's permissions in th
msgstr ""
msgid "If enabled"
-msgstr ""
+msgstr "만약 활성화 ëœ ê²½ìš°"
msgid "If enabled, access to projects will be validated on an external service using their classification label."
msgstr ""
@@ -3914,7 +4292,7 @@ msgid "If you already have files you can push them using the %{link_to_cli} belo
msgstr ""
msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
-msgstr ""
+msgstr "HTTP 저장소를 공개ì ìœ¼ë¡œ 액세스할 수 없는 경우, URLì— ì¸ì¦ 정보를 추가하십시오:<code>https://username:password@gitlab.company.com/group/project.git</code>."
msgid "ImageDiffViewer|2-up"
msgstr ""
@@ -3926,19 +4304,19 @@ msgid "ImageDiffViewer|Swipe"
msgstr ""
msgid "Import"
-msgstr ""
+msgstr "가져오기"
msgid "Import Projects from Gitea"
msgstr ""
msgid "Import all compatible projects"
-msgstr ""
+msgstr "호환ë˜ëŠ” 모든 프로ì íŠ¸ 가져오기"
msgid "Import all projects"
-msgstr ""
+msgstr "모든 프로ì íŠ¸ 가져오기"
msgid "Import all repositories"
-msgstr ""
+msgstr "모든 저장소 가져오기"
msgid "Import an exported GitLab project"
msgstr ""
@@ -3950,7 +4328,7 @@ msgid "Import multiple repositories by uploading a manifest file."
msgstr ""
msgid "Import project"
-msgstr ""
+msgstr "프로ì íŠ¸ 가져오기"
msgid "Import projects from Bitbucket"
msgstr ""
@@ -3988,6 +4366,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -3998,7 +4379,7 @@ msgid "Include the username in the URL if required: <code>https://username@gitla
msgstr ""
msgid "Incompatible Project"
-msgstr ""
+msgstr "호환ë˜ì§€ 않는 프로ì íŠ¸"
msgid "Indicates whether this runner can pick jobs without tags"
msgstr ""
@@ -4041,13 +4422,13 @@ msgid "Interested parties can even contribute by pushing commits if they want to
msgstr "관심있는 íŒŒí‹°ë“¤ì€ ì›í•˜ëŠ” ê³³ì— ì»¤ë°‹ì„ í‘¸ì‹œí•¨ìœ¼ë¡œì¨ ê¸°ì—¬í•  ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤."
msgid "Internal - The group and any internal projects can be viewed by any logged in user."
-msgstr ""
+msgstr "내부 - 그룹 ë° ëª¨ë“  내부 프로ì íŠ¸ëŠ” 로그ì¸í•œ 사용ìžê°€ ë³¼ 수 있습니다."
msgid "Internal - The project can be accessed by any logged in user."
-msgstr ""
+msgstr "내부 - ì´ í”„ë¡œì íŠ¸ëŠ” ë¡œê·¸ì¸ í•œ 사용ìžë§Œ 액세스 í•  수 있습니다."
msgid "Internal users"
-msgstr ""
+msgstr "내부 사용ìž"
msgid "Interval Pattern"
msgstr "주기 패턴"
@@ -4055,6 +4436,12 @@ msgstr "주기 패턴"
msgid "Introducing Cycle Analytics"
msgstr "Cycle Analytics 소개"
+msgid "Invite"
+msgstr "초대"
+
+msgid "Issue"
+msgstr "ì´ìŠˆ"
+
msgid "Issue Boards"
msgstr ""
@@ -4065,10 +4452,10 @@ msgid "Issue events"
msgstr "ì´ìŠˆ ì´ë²¤íŠ¸"
msgid "IssueBoards|Board"
-msgstr ""
+msgstr "보드"
msgid "IssueBoards|Boards"
-msgstr ""
+msgstr "보드"
msgid "Issues"
msgstr "ì´ìŠˆ"
@@ -4077,43 +4464,70 @@ msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are sear
msgstr "ì´ìŠˆëŠ” 버그, ìž‘ì—… í˜¹ì€ ë…¼ì˜í•  ì•„ì´ë””ì–´ì¼ ìˆ˜ 있습니다. 그리고, ì´ìŠˆëŠ” 검색 ë° í•„í„°ë§ ê°€ëŠ¥í•©ë‹ˆë‹¤."
msgid "Issues closed"
+msgstr "ì´ìŠˆ 닫힘"
+
+msgid "Issues, merge requests, pushes and comments."
msgstr ""
-msgid "Jan"
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
msgstr ""
-msgid "January"
+msgid "IssuesAnalytics|Issues Created"
msgstr ""
-msgid "Job"
+msgid "IssuesAnalytics|Issues created per month"
msgstr ""
-msgid "Job has been erased"
+msgid "IssuesAnalytics|Last 12 months"
msgstr ""
-msgid "Jobs"
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
msgstr ""
-msgid "Job|Browse"
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
msgstr ""
+msgid "Jan"
+msgstr "1ì›”"
+
+msgid "January"
+msgstr "1ì›”"
+
+msgid "Job"
+msgstr "Job"
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Jobs"
+msgstr "Jobs"
+
+msgid "Job|Browse"
+msgstr "íƒìƒ‰"
+
msgid "Job|Complete Raw"
msgstr ""
msgid "Job|Download"
-msgstr ""
+msgstr "다운로드"
msgid "Job|Erase job log"
-msgstr ""
+msgstr "작업 로그 지우기"
msgid "Job|Job artifacts"
msgstr ""
msgid "Job|Job has been erased"
-msgstr ""
+msgstr "ìž‘ì—…ì´ ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤"
msgid "Job|Job has been erased by"
msgstr ""
@@ -4125,7 +4539,7 @@ msgid "Job|Scroll to bottom"
msgstr ""
msgid "Job|Scroll to top"
-msgstr ""
+msgstr "맨 위로 스í¬ë¡¤"
msgid "Job|Show complete raw"
msgstr ""
@@ -4133,35 +4547,29 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
msgstr ""
msgid "Jul"
-msgstr ""
+msgstr "7ì›”"
msgid "July"
-msgstr ""
+msgstr "7ì›”"
msgid "Jun"
-msgstr ""
+msgstr "6ì›”"
msgid "June"
-msgstr ""
-
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
+msgstr "6ì›”"
msgid "Kubernetes"
-msgstr ""
+msgstr "Kubernetes"
msgid "Kubernetes Cluster"
-msgstr ""
+msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°"
msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° ìƒì„± ì‹œê°„ì´ ì´ˆê³¼ë˜ì—ˆìŠµë‹ˆë‹¤. %{timeout}"
@@ -4176,13 +4584,13 @@ msgid "Kubernetes cluster was successfully updated."
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ê°€ 성공ì ìœ¼ë¡œ ì—…ë°ì´íŠ¸ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Kubernetes configured"
-msgstr ""
+msgstr "Kubernetes 설정ë¨"
msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
msgstr "Kubernetes 서비스 í†µí•©ì€ ë” ì´ìƒ 사용ë˜ì§€ 않습니다. %{deprecated_message_content} 새로운 <a href=\"%{url}\"/>Kubernetes í´ëŸ¬ìŠ¤í„°</a> 페ì´ì§€"
msgid "LFS"
-msgstr ""
+msgstr "LFS"
msgid "LFSStatus|Disabled"
msgstr "Disabled"
@@ -4191,19 +4599,19 @@ msgid "LFSStatus|Enabled"
msgstr "Enabled"
msgid "Label"
-msgstr ""
+msgstr "ë¼ë²¨"
msgid "Label actions dropdown"
-msgstr ""
+msgstr "ë¼ë²¨ ìž‘ì—… 드롭 다운"
msgid "Label lists show all issues with the selected label."
msgstr ""
msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
-msgstr ""
+msgstr "%{firstLabelName} +%{remainingLabelCount} ì´ìƒ"
msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
-msgstr ""
+msgstr "%{labelsString}, 그리고 %{remainingLabelCount} ì´ìƒ"
msgid "LabelSelect|Labels"
msgstr ""
@@ -4218,10 +4626,10 @@ msgid "Labels can be applied to issues and merge requests to categorize them."
msgstr "ë¼ë²¨ì€ ì´ìŠˆì™€ 머지 리퀘스트(MR)ì— ì¹´í…Œê³ ë¼ì´ì¦ˆë¥¼ 위해 ì ìš©ê°€ëŠ¥í•©ë‹ˆë‹¤."
msgid "Labels can be applied to issues and merge requests."
-msgstr ""
+msgstr "ë¼ë²¨ì€ ì´ìŠˆì™€ 머지 리퀘스트(MR)ì— ì‚¬ìš©í•  수 있습니다."
msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
-msgstr ""
+msgstr "<span>ë¼ë²¨</span> %{labelTitle} <span>(ì„)를 그룹 ë¼ë²¨ë¡œ 승격하시겠습니까?</span>"
msgid "Labels|Promote Label"
msgstr ""
@@ -4229,6 +4637,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] "최근 %d ì¼"
@@ -4239,17 +4650,23 @@ msgstr "최근 파ì´í”„ë¼ì¸"
msgid "Last commit"
msgstr "최근 커밋"
-msgid "Last edited %{date}"
+msgid "Last contact"
msgstr ""
+msgid "Last edited %{date}"
+msgstr "%{date}ì— ë§ˆì§€ë§‰ 편집ë¨"
+
msgid "Last edited by %{name}"
+msgstr "%{name}가 마지막으로 편집함"
+
+msgid "Last reply by"
msgstr ""
msgid "Last update"
-msgstr ""
+msgstr "최근 ì—…ë°ì´íŠ¸"
msgid "Last updated"
-msgstr ""
+msgstr "최근 ì—…ë°ì´íŠ¸ë¨"
msgid "LastPushEvent|You pushed to"
msgstr "푸쉬: "
@@ -4258,19 +4675,19 @@ msgid "LastPushEvent|at"
msgstr "at"
msgid "Latest changes"
-msgstr ""
+msgstr "최근 변경사항"
msgid "Learn more"
-msgstr ""
+msgstr "ë” ì•Œì•„ë³´ê¸°"
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
msgstr ""
msgid "Learn more about Kubernetes"
-msgstr ""
+msgstr "Kubernetesì— ëŒ€í•´ ë” ì•Œì•„ë³´ê¸°"
msgid "Learn more about protected branches"
-msgstr ""
+msgstr "ë³´í˜¸ëœ ë¸Œëžœì¹˜ë“¤ì— ëŒ€í•´ ë” ì•Œì•„ë³´ê¸°"
msgid "Learn more in the"
msgstr "ë” ìžì„¸ížˆ 알아보기"
@@ -4279,7 +4696,7 @@ msgid "Learn more in the|pipeline schedules documentation"
msgstr "파ì´í”„ë¼ì¸ 스케쥴 문서로부터 ë” ì•Œì•„ë³´ê¸°"
msgid "Leave"
-msgstr ""
+msgstr "나가기"
msgid "Leave group"
msgstr "그룹 떠나기"
@@ -4291,101 +4708,128 @@ msgid "Leave the \"File type\" and \"Delivery method\" options on their default
msgstr ""
msgid "License"
+msgstr "ë¼ì´ì„¼ìŠ¤"
+
+msgid "LicenseManagement|Add a license"
msgstr ""
-msgid "LicenseManagement|Approve license"
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
msgstr ""
-msgid "LicenseManagement|Approve license?"
+msgid "LicenseManagement|Approve"
msgstr ""
+msgid "LicenseManagement|Approve license"
+msgstr "ë¼ì´ì„¼ìŠ¤ 승ì¸"
+
+msgid "LicenseManagement|Approve license?"
+msgstr "ë¼ì´ì„¼ìŠ¤ë¥¼ 승ì¸í•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
+
msgid "LicenseManagement|Approved"
+msgstr "승ì¸ë¨"
+
+msgid "LicenseManagement|Blacklist"
msgstr ""
msgid "LicenseManagement|Blacklist license"
-msgstr ""
+msgstr "블랙리스트 ë¼ì´ì„¼ìŠ¤"
msgid "LicenseManagement|Blacklist license?"
-msgstr ""
+msgstr "블랙리스트 ë¼ì´ì„¼ìŠ¤ë¡œ 등ë¡í•˜ì‹œê² ìŠµë‹ˆê¹Œ?"
msgid "LicenseManagement|Blacklisted"
+msgstr "블랙리스트로 등ë¡ë¨"
+
+msgid "LicenseManagement|Cancel"
msgstr ""
msgid "LicenseManagement|License"
-msgstr ""
+msgstr "ë¼ì´ì„¼ìŠ¤"
msgid "LicenseManagement|License Management"
-msgstr ""
+msgstr "ë¼ì´ì„¼ìŠ¤ 관리"
msgid "LicenseManagement|License details"
+msgstr "ë¼ì´ì„ ìŠ¤ ì •ë³´"
+
+msgid "LicenseManagement|License name"
msgstr ""
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
-msgstr ""
+msgstr "ì´ í”„ë¡œì íŠ¸ì˜ ìŠ¹ì¸ ë° ë¸”ëž™ë¦¬ìŠ¤íŠ¸ ë¼ì´ì„¼ìŠ¤ë¥¼ 관리합니다."
msgid "LicenseManagement|Packages"
-msgstr ""
+msgstr "패키지"
msgid "LicenseManagement|Remove license"
-msgstr ""
+msgstr "ë¼ì´ì„¼ìŠ¤ 제거"
msgid "LicenseManagement|Remove license?"
+msgstr "ë¼ì´ì„¼ìŠ¤ë¥¼ 제거하시겠습니까?"
+
+msgid "LicenseManagement|Submit"
msgstr ""
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
+msgstr "ì´ í”„ë¡œì íŠ¸ì—는 ìŠ¹ì¸ ë˜ëŠ” ë¸”ëž™ë¦¬ìŠ¤íŠ¸ëœ ë¼ì´ì„¼ìŠ¤ê°€ 없습니다."
+
+msgid "LicenseManagement|This license already exists in this project."
msgstr ""
msgid "LicenseManagement|URL"
-msgstr ""
+msgstr "URL"
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
-msgstr ""
+msgstr "ì´ í”„ë¡œì íŠ¸ì—ì„œ ë¼ì´ì„¼ìŠ¤ %{name}(ì„)를 제거하려고합니다."
msgid "Licenses"
-msgstr ""
+msgstr "ë¼ì´ì„¼ìŠ¤"
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
msgstr[0] ""
msgid "LinkedIn"
-msgstr ""
+msgstr "LinkedIn"
msgid "List"
-msgstr ""
+msgstr "목ë¡"
msgid "List Your Gitea Repositories"
-msgstr ""
+msgstr "Gitea 저장소 목ë¡"
msgid "List available repositories"
+msgstr "사용 가능한 저장소 목ë¡"
+
+msgid "List view"
msgstr ""
msgid "List your Bitbucket Server repositories"
-msgstr ""
+msgstr "Bitbucket Server 저장소 목ë¡"
msgid "List your GitHub repositories"
-msgstr ""
+msgstr "GitHub 저장소 목ë¡"
msgid "Live preview"
-msgstr ""
+msgstr "실시간 미리보기"
msgid "Loading contribution stats for group members"
msgstr ""
msgid "Loading the GitLab IDE..."
-msgstr ""
+msgstr "GitLab IDE 로드 중..."
msgid "Loading..."
-msgstr ""
+msgstr "불러오는 중…"
msgid "Lock"
-msgstr ""
+msgstr "잠금"
msgid "Lock %{issuableDisplayName}"
msgstr "%{issuableDisplayName} 잠금"
msgid "Lock not found"
-msgstr ""
+msgstr "ìž ê¸ˆì„ ì°¾ì„ ìˆ˜ 없습니다."
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
msgstr ""
@@ -4394,7 +4838,7 @@ msgid "Lock to current projects"
msgstr ""
msgid "Locked"
-msgstr ""
+msgstr "ìž ê¹€"
msgid "Locked Files"
msgstr ""
@@ -4405,9 +4849,12 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
-msgid "Logs"
+msgid "Login with smartcard"
msgstr ""
+msgid "Logs"
+msgstr "로그"
+
msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
msgstr ""
@@ -4418,13 +4865,13 @@ msgid "Manage Git repositories with fine-grained access controls that keep your
msgstr ""
msgid "Manage Web IDE features"
-msgstr ""
+msgstr "웹 IDE 기능 관리"
msgid "Manage access"
msgstr ""
msgid "Manage all notifications"
-msgstr ""
+msgstr "모든 알림 관리"
msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
msgstr ""
@@ -4439,16 +4886,16 @@ msgid "Manage labels"
msgstr ""
msgid "Manage project labels"
-msgstr ""
+msgstr "프로ì íŠ¸ ë¼ë²¨ 관리"
msgid "Manage your group’s membership while adding another level of security with SAML."
msgstr ""
msgid "Manifest"
-msgstr ""
+msgstr "Manifest"
msgid "Manifest file import"
-msgstr ""
+msgstr "Manifest íŒŒì¼ ê°€ì ¸ì˜¤ê¸°"
msgid "Map a FogBugz account ID to a GitLab user"
msgstr ""
@@ -4463,35 +4910,71 @@ msgid "Map a Google Code user to a full name"
msgstr ""
msgid "Mar"
-msgstr ""
+msgstr "3ì›”"
msgid "March"
-msgstr ""
+msgstr "3ì›”"
msgid "Mark todo as done"
-msgstr ""
+msgstr "í•  ì¼ì„ 완료로 표시"
msgid "Markdown enabled"
+msgstr "마í¬ë‹¤ìš´ 활성화ë¨"
+
+msgid "MarkdownToolbar|Add a bullet list"
msgstr ""
-msgid "Maven Metadata"
+msgid "MarkdownToolbar|Add a link"
msgstr ""
-msgid "Maven package"
+msgid "MarkdownToolbar|Add a numbered list"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "MarkdownToolbar|Add a table"
msgstr ""
-msgid "Maximum job timeout"
+msgid "MarkdownToolbar|Add a task list"
msgstr ""
-msgid "May"
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
msgstr ""
+msgid "Maven Metadata"
+msgstr "Maven 메타 ë°ì´í„°"
+
+msgid "Maven package"
+msgstr "Maven 패키지"
+
+msgid "Max access level"
+msgstr "최대 액세스 수준"
+
+msgid "Maximum job timeout"
+msgstr "최대 작업 시간 초과"
+
+msgid "May"
+msgstr "5ì›”"
+
msgid "Median"
msgstr "중앙값"
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr "회ì›"
@@ -4499,7 +4982,7 @@ msgid "Members will be forwarded here when signing in to your group. Get this fr
msgstr ""
msgid "Merge Request"
-msgstr ""
+msgstr "병합 요청"
msgid "Merge Request:"
msgstr "머지 리퀘스트(MR):"
@@ -4508,47 +4991,65 @@ msgid "Merge Requests"
msgstr "병합 요청"
msgid "Merge Requests created"
-msgstr ""
+msgstr "병합 요청 ìƒì„±ë¨"
msgid "Merge events"
msgstr "머지 ì´ë²¤íŠ¸"
msgid "Merge request"
-msgstr ""
+msgstr "머지 리퀘스트(MR)"
msgid "Merge request approvals"
-msgstr ""
+msgstr "병합 요청 승ì¸"
msgid "Merge requests"
-msgstr ""
+msgstr "머지 리퀘스트(MR)"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "머지 리퀘스트(MR)는 프로ì íŠ¸ì˜ 변경 ì‚¬í•­ì„ ì œì•ˆí•˜ê³  변경 ì‚¬í•­ì„ ë‹¤ë¥¸ 사람들과 ë…¼ì˜ í•˜ëŠ” 곳입니다."
-msgid "MergeRequests|Resolve this discussion in a new issue"
+msgid "MergeRequests|An error occurred while saving the draft comment."
msgstr ""
-msgid "MergeRequests|Saving the comment failed"
+msgid "MergeRequests|Discussion stays resolved."
msgstr ""
-msgid "MergeRequests|Toggle comments for this file"
+msgid "MergeRequests|Discussion stays unresolved."
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
+msgid "MergeRequests|Discussion will be resolved."
msgstr ""
-msgid "MergeRequests|View file @ %{commitId}"
+msgid "MergeRequests|Discussion will be unresolved."
msgstr ""
+msgid "MergeRequests|Resolve this discussion in a new issue"
+msgstr "새로운 ì´ìŠˆì—ì„œ ì´ í† ë¡ ì„ í•´ê²°í•˜ì„¸ìš”."
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr "코멘트 저장 실패"
+
+msgid "MergeRequests|Toggle comments for this file"
+msgstr "ì´ íŒŒì¼ì— 대한 설명 전환"
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr "íŒŒì¼ ë³´ê¸° @ %{commitId}"
+
msgid "MergeRequests|View replaced file @ %{commitId}"
-msgstr ""
+msgstr "êµì²´ëœ íŒŒì¼ ë³´ê¸° @ %{commitId}"
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
-msgid "Merged"
+msgid "MergeRequest|Filter files"
msgstr ""
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "Merged"
+msgstr "머지ë¨"
+
msgid "Messages"
msgstr "메시지"
@@ -4561,6 +5062,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4574,7 +5078,7 @@ msgid "Metrics|Edit metric"
msgstr ""
msgid "Metrics|Environment"
-msgstr ""
+msgstr "환경"
msgid "Metrics|For grouping similar metrics"
msgstr ""
@@ -4592,7 +5096,7 @@ msgid "Metrics|Must be a valid PromQL query."
msgstr ""
msgid "Metrics|Name"
-msgstr ""
+msgstr "ì´ë¦„"
msgid "Metrics|New metric"
msgstr ""
@@ -4607,10 +5111,10 @@ msgid "Metrics|Query"
msgstr ""
msgid "Metrics|Response"
-msgstr ""
+msgstr "ì‘답"
msgid "Metrics|System"
-msgstr ""
+msgstr "시스템"
msgid "Metrics|There was an error fetching the environments data, please try again"
msgstr ""
@@ -4661,19 +5165,19 @@ msgid "Metrics|e.g. req/sec"
msgstr ""
msgid "Milestone"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤"
msgid "Milestone lists not available with your current license"
-msgstr ""
+msgstr "현재 ë¼ì´ì„¼ìŠ¤ì—서는 마ì¼ìŠ¤í†¤ 목ë¡ì„ 사용할 수 없습니다."
msgid "Milestone lists show all issues from the selected milestone."
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤ 목ë¡ì—는 ì„ íƒí•œ 마ì¼ìŠ¤í†¤ì˜ 모든 문제가 표시ë©ë‹ˆë‹¤."
msgid "Milestones"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤"
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤ %{milestoneTitle}(ì„)를 ì˜êµ¬ížˆ 삭제하고 %{issuesWithCount}와 %{mergeRequestsWithCount}ì—ì„œ 제거합니다. ì‚­ì œ ëœ í›„ì—는 실행 취소하거나 복구 í•  수 없습니다."
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
msgstr ""
@@ -4682,91 +5186,91 @@ msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
msgstr ""
msgid "Milestones|Delete milestone"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤ ì‚­ì œ"
msgid "Milestones|Delete milestone %{milestoneTitle}?"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤ ì‚­ì œ %{milestoneTitle}?"
msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤ì„ 삭제하지 못했습니다 %{milestoneTitle}"
msgid "Milestones|Milestone %{milestoneTitle} was not found"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤ %{milestoneTitle}를 ì°¾ì„ ìˆ˜ 없습니다"
msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
-msgstr ""
+msgstr "%{milestoneTitle} ì„(를) 그룹 마ì¼ìŠ¤í†¤ìœ¼ë¡œ 승격하시겠습니까?"
msgid "Milestones|Promote Milestone"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤ 승격"
msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
msgstr ""
msgid "Milestones|This action cannot be reversed."
-msgstr ""
+msgstr "ì´ ë™ìž‘ì€ ë˜ëŒë¦´ 수 없습니다."
msgid "Mirror a repository"
-msgstr ""
+msgstr "저장소 미러하기"
msgid "Mirror direction"
msgstr ""
msgid "Mirror repository"
-msgstr ""
+msgstr "미러 저장소"
msgid "Mirror user"
-msgstr ""
+msgstr "미러 사용ìž"
msgid "Mirrored repositories"
-msgstr ""
+msgstr "미러ë§ëœ 저장소"
msgid "Mirroring repositories"
-msgstr ""
+msgstr "ë¯¸ëŸ¬ë§ ì €ìž¥ì†Œ"
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "SSH 키 추가"
msgid "Modal|Cancel"
-msgstr ""
+msgstr "취소"
msgid "Modal|Close"
-msgstr ""
+msgstr "닫기"
msgid "Monitoring"
msgstr "모니터ë§"
msgid "Months"
-msgstr ""
+msgstr "달"
msgid "More"
-msgstr ""
+msgstr "ë” ë³´ê¸°"
msgid "More actions"
msgstr ""
msgid "More info"
-msgstr ""
+msgstr "ë” ë§Žì€ ì •ë³´"
msgid "More information"
-msgstr ""
+msgstr "ë” ë§Žì€ ì •ë³´"
msgid "More information is available|here"
msgstr "여기"
msgid "Most stars"
-msgstr ""
+msgstr "ë§Žì€ ë³„"
msgid "Move"
-msgstr ""
+msgstr "ì´ë™"
msgid "Move issue"
-msgstr ""
+msgstr "ì´ìŠˆ ì´ë™"
msgid "Multiple issue boards"
-msgstr ""
+msgstr "여러 ì´ìŠˆ ë³´ë“œ"
msgid "Name"
-msgstr ""
+msgstr "ì´ë¦„"
msgid "Name new label"
msgstr "새 ë¼ë²¨ ì´ë¦„ 지정"
@@ -4775,34 +5279,37 @@ msgid "Name your individual key via a title"
msgstr ""
msgid "Name:"
+msgstr "ì´ë¦„:"
+
+msgid "Naming, visibility"
msgstr ""
msgid "Nav|Help"
-msgstr ""
+msgstr "ë„움ë§"
msgid "Nav|Home"
-msgstr ""
+msgstr "홈"
msgid "Nav|Sign In / Register"
-msgstr ""
+msgstr "ë¡œê·¸ì¸ / 등ë¡"
msgid "Nav|Sign out and sign in with a different account"
-msgstr ""
+msgstr "로그아웃하고 다른 계정으로 로그ì¸"
msgid "Network"
-msgstr ""
+msgstr "네트워í¬"
msgid "Never"
msgstr ""
msgid "New"
-msgstr ""
+msgstr "신규"
msgid "New Application"
-msgstr ""
+msgstr "새로운 애플리케ì´ì…˜"
msgid "New Group"
-msgstr ""
+msgstr "새 그룹"
msgid "New Identity"
msgstr ""
@@ -4812,22 +5319,22 @@ msgid_plural "New Issues"
msgstr[0] "새 ì´ìŠˆ"
msgid "New Label"
-msgstr ""
+msgstr "새 ë¼ë²¨"
msgid "New Pipeline Schedule"
msgstr "새로운 파ì´í”„ë¼ì¸ ì¼ì •"
msgid "New Snippet"
-msgstr ""
+msgstr "새 스니펫"
msgid "New Snippets"
-msgstr ""
+msgstr "새 스니펫"
msgid "New branch"
msgstr "새 브랜치"
msgid "New branch unavailable"
-msgstr ""
+msgstr "새로운 브랜치 사용 불가능"
msgid "New directory"
msgstr "새 디렉토리"
@@ -4839,7 +5346,7 @@ msgid "New file"
msgstr "새 파ì¼"
msgid "New group"
-msgstr ""
+msgstr "새 그룹"
msgid "New identity"
msgstr ""
@@ -4848,7 +5355,7 @@ msgid "New issue"
msgstr "새 ì´ìŠˆ"
msgid "New label"
-msgstr ""
+msgstr "새 ë¼ë²¨"
msgid "New merge request"
msgstr "새 머지 리퀘스트(MR)"
@@ -4857,7 +5364,7 @@ msgid "New pipelines will cancel older, pending pipelines on the same branch"
msgstr ""
msgid "New project"
-msgstr ""
+msgstr "새 프로ì íŠ¸"
msgid "New schedule"
msgstr "새 ì¼ì •"
@@ -4866,28 +5373,28 @@ msgid "New snippet"
msgstr "새 스니펫"
msgid "New subgroup"
-msgstr ""
+msgstr "새 서브그룹"
msgid "New tag"
msgstr "새 태그 "
msgid "New..."
-msgstr ""
+msgstr "새로 만들기..."
msgid "No"
-msgstr ""
+msgstr "아니오"
msgid "No Label"
-msgstr ""
+msgstr "ë¼ë²¨ ì—†ìŒ"
msgid "No assignee"
msgstr "ë‹´ë‹¹ìž ì—†ìŒ"
msgid "No branches found"
-msgstr ""
+msgstr "브랜치가 존재하지 않습니다."
msgid "No changes"
-msgstr ""
+msgstr "변경 사항 ì—†ìŒ"
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "Gitaly Serverì— ì—°ê²°í•  수 없습니다. 로그를 확ì¸í•˜ì‹­ì‹œì˜¤!"
@@ -4895,6 +5402,12 @@ msgstr "Gitaly Serverì— ì—°ê²°í•  수 없습니다. 로그를 확ì¸í•˜ì‹­ì‹œì˜
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr "기한 ì—†ìŒ"
@@ -4904,26 +5417,26 @@ msgstr "ì˜ˆìƒ ì‹œê°„ì´ë‚˜ ì†Œë¹„ëœ ì‹œê°„ì´ ì—†ìŠµë‹ˆë‹¤."
msgid "No file chosen"
msgstr "파ì¼ì„ ì„ íƒí•˜ì§€ 않았습니다."
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
-msgstr ""
+msgstr "파ì¼ì„ ì°¾ì„ ìˆ˜ 없습니다."
msgid "No issues for the selected time period."
-msgstr ""
+msgstr "ì„ íƒí•œ 기간 ë™ì•ˆ ì´ìŠˆê°€ 없습니다."
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr "ë¼ì´ì„¼ìŠ¤ê°€ 없습니다. All rights reserved"
+
msgid "No merge requests for the selected time period."
-msgstr ""
+msgstr "ì„ íƒí•œ 기간 ë™ì•ˆ 머지 리퀘스트(MR)ê°€ 없습니다."
msgid "No merge requests found"
-msgstr ""
+msgstr "머지 리퀘스트(MR)를 ì°¾ì„ ìˆ˜ 없습니다."
msgid "No messages were logged"
-msgstr ""
+msgstr "메시지가 기ë¡ë˜ì§€ 않았습니다."
msgid "No other labels with such name or description"
msgstr ""
@@ -4935,7 +5448,7 @@ msgid "No prioritised labels with such name or description"
msgstr ""
msgid "No public groups"
-msgstr ""
+msgstr "공개 ê·¸ë£¹ì´ ì—†ìŠµë‹ˆë‹¤."
msgid "No pushes for the selected time period."
msgstr ""
@@ -4943,6 +5456,9 @@ msgstr ""
msgid "No repository"
msgstr "저장소 ì—†ìŒ"
+msgid "No runners found"
+msgstr "Runners ì—†ìŒ"
+
msgid "No schedules"
msgstr "ì¼ì • ì—†ìŒ"
@@ -4953,7 +5469,7 @@ msgid "Nodes"
msgstr ""
msgid "None"
-msgstr ""
+msgstr "ì—†ìŒ"
msgid "Not all comments are displayed because you're comparing two versions of the diff."
msgstr ""
@@ -4979,24 +5495,39 @@ msgstr "비밀 아님"
msgid "Not enough data"
msgstr "ë°ì´í„°ê°€ 충분하지 않습니다."
-msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
+msgid "Not now"
msgstr ""
+msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
+msgstr "마스터 브랜치는 ìžë™ìœ¼ë¡œ 보호ë©ë‹ˆë‹¤. %{link_to_protected_branches}"
+
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
-msgstr ""
+msgstr "참고: 관리ìžëŠ” %{github_integration_link} (ì„) 를 설정하여, GitHub를 통한 로그ì¸ì„ 허용하고 ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°ì„ ìƒì„±í•˜ì§€ ì•Šê³  저장소 가져오기를 허용할 수 있습니다."
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
msgstr ""
msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
-msgstr ""
+msgstr "참고: 관리ìžì—게 %{github_integration_link} (ì„) 를 설정하여, GitHub를 통한 로그ì¸ì„ 허용하고 ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°ì„ ìƒì„±í•˜ì§€ ì•Šê³  저장소를 가져올 수 있ë„ë¡ í—ˆìš©í•  수 있는지 문ì˜í•˜ì‹­ì‹œì˜¤."
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr "알림 ì´ë²¤íŠ¸"
@@ -5061,35 +5592,32 @@ msgid "Notifications off"
msgstr ""
msgid "Notifications on"
-msgstr ""
+msgstr "알림 켬"
msgid "Nov"
-msgstr ""
+msgstr "11ì›”"
msgid "November"
-msgstr ""
-
-msgid "Number of access attempts"
-msgstr "ì ‘ê·¼ ì‹œë„ íšŸìˆ˜"
+msgstr "11ì›”"
msgid "OK"
-msgstr ""
+msgstr "확ì¸"
msgid "Oct"
-msgstr ""
+msgstr "10ì›”"
msgid "October"
-msgstr ""
+msgstr "10ì›”"
msgid "OfSearchInADropdown|Filter"
msgstr "í•„í„°"
msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
-msgstr ""
+msgstr "가져오기가 완료ë˜ë©´ 저장소를 SSH를 통해 ë¯¸ëŸ¬ë§ í•  수 있습니다. ë” ì•Œì•„ë³´ê¸° %{ssh_link}"
msgid "One more item"
msgid_plural "%d more items"
-msgstr[0] ""
+msgstr[0] "%dê°œì˜ ì¶”ê°€ ì•„ì´í…œ"
msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
@@ -5097,11 +5625,8 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
-msgstr ""
+msgstr "관리ìžë§Œ 가능"
msgid "Only comments from the following commit are shown below"
msgstr ""
@@ -5110,41 +5635,59 @@ msgid "Only mirror protected branches"
msgstr ""
msgid "Only project members can comment."
-msgstr ""
+msgstr "프로ì íŠ¸ 구성ì›ë§Œ ëŒ“ê¸€ì„ ë‹¬ 수 있습니다."
msgid "Oops, are you sure?"
-msgstr ""
+msgstr "ì´ëŸ°, 확실합니까?"
msgid "Open"
-msgstr ""
+msgstr "열기"
msgid "Open in Xcode"
+msgstr "Xcodeì—ì„œ 열기"
+
+msgid "Open projects"
msgstr ""
msgid "Open sidebar"
-msgstr ""
+msgstr "사ì´ë“œë°” 열기"
msgid "Open source software to collaborate on code"
msgstr ""
msgid "Opened"
-msgstr ""
+msgstr "열림"
msgid "Opened MR"
-msgstr ""
+msgstr "열린 MR"
msgid "Opened issues"
-msgstr ""
+msgstr "열린 ì´ìŠˆ"
msgid "OpenedNDaysAgo|Opened"
msgstr "열린"
msgid "Opens in a new window"
-msgstr ""
+msgstr "새 창으로 열기"
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5158,16 +5701,16 @@ msgid "Or you can choose one of the suggested colors below"
msgstr ""
msgid "Other Labels"
-msgstr ""
+msgstr "기타 ë¼ë²¨"
msgid "Other information"
-msgstr ""
+msgstr "다른 정보"
msgid "Otherwise it is recommended you start with one of the options below."
-msgstr ""
+msgstr "그렇지 않다면 아래 옵션 중 하나를 ì„ íƒí•˜ëŠ” ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤."
msgid "Outbound requests"
-msgstr ""
+msgstr "외부로 가는 요청"
msgid "Overview"
msgstr "개요"
@@ -5179,31 +5722,31 @@ msgid "Owner"
msgstr "소유ìž"
msgid "Package information"
-msgstr ""
+msgstr "패키지 정보"
msgid "Package was removed"
-msgstr ""
+msgstr "패키지가 제거ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Packages"
-msgstr ""
+msgstr "패키지"
msgid "Pages"
-msgstr ""
+msgstr "페ì´ì§€"
msgid "Pagination|Last »"
-msgstr ""
+msgstr "마지막 »"
msgid "Pagination|Next"
-msgstr ""
+msgstr "다ìŒ"
msgid "Pagination|Prev"
-msgstr ""
+msgstr "ì´ì „"
msgid "Pagination|« First"
-msgstr ""
+msgstr "« 처ìŒ"
msgid "Part of merge request changes"
-msgstr ""
+msgstr "머지 리퀘스트(MR) 변경 사항 중 ì¼ë¶€"
msgid "Password"
msgstr "패스워드"
@@ -5211,17 +5754,20 @@ msgstr "패스워드"
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
-msgid "Path:"
+msgid "Path, transfer, remove"
msgstr ""
+msgid "Path:"
+msgstr "경로:"
+
msgid "Pause"
-msgstr ""
+msgstr "중지"
msgid "Paused Runners don't accept new jobs"
-msgstr ""
+msgstr "ì¼ì‹œì •ì§€ëœ 러너는 새로운 ìž‘ì—…ì„ í—ˆìš©í•˜ì§€ 않습니다."
msgid "Pending"
-msgstr ""
+msgstr "대기중"
msgid "People without permission will never get a notification and won't be able to comment."
msgstr ""
@@ -5230,23 +5776,23 @@ msgid "Per job. If a job passes this threshold, it will be marked as failed"
msgstr ""
msgid "Perform advanced options such as changing path, transferring, or removing the group."
-msgstr ""
+msgstr "경로 변경, 그룹 전송 ë˜ëŠ” 제거와 ê°™ì€ ê³ ê¸‰ ì˜µì…˜ì„ ìˆ˜í–‰í•©ë‹ˆë‹¤."
msgid "Performance optimization"
-msgstr ""
+msgstr "성능 최ì í™”"
msgid "Permissions"
+msgstr "권한"
+
+msgid "Permissions, LFS, 2FA"
msgstr ""
msgid "Personal Access Token"
-msgstr ""
+msgstr "ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°"
msgid "Pipeline"
msgstr "파ì´í”„ë¼ì¸"
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
-msgstr ""
-
msgid "Pipeline Health"
msgstr "파ì´í”„ë¼ì¸ ìƒíƒœ"
@@ -5257,7 +5803,7 @@ msgid "Pipeline Schedules"
msgstr "파ì´í”„ë¼ì¸ 스케쥴"
msgid "Pipeline quota"
-msgstr ""
+msgstr "파ì´í”„ë¼ì¸ 할당량"
msgid "Pipeline triggers"
msgstr ""
@@ -5326,10 +5872,10 @@ msgid "Pipelines for last year"
msgstr "ì§€ë‚œí•´ì˜ íŒŒì´í”„ë¼ì¸"
msgid "Pipelines|Build with confidence"
-msgstr ""
+msgstr "ìžì‹ ìžˆê²Œ 빌드하세요"
msgid "Pipelines|CI Lint"
-msgstr ""
+msgstr "CI Lint"
msgid "Pipelines|Clear Runner Caches"
msgstr "Runner ìºì‹œ 정리"
@@ -5341,13 +5887,13 @@ msgid "Pipelines|Get started with Pipelines"
msgstr "파ì´í”„ ë¼ì¸ìœ¼ë¡œ 시작하기"
msgid "Pipelines|Loading Pipelines"
-msgstr ""
+msgstr "파ì´í”„ë¼ì¸ 로딩중"
msgid "Pipelines|Project cache successfully reset."
-msgstr ""
+msgstr "프로ì íŠ¸ ìºì‹œê°€ 성공ì ìœ¼ë¡œ 재설정ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Pipelines|Run Pipeline"
-msgstr ""
+msgstr "파ì´í”„ë¼ì¸ 실행"
msgid "Pipelines|Something went wrong while cleaning runners cache."
msgstr "Runnerì˜ ìºì‹œë¥¼ ë¹„ìš°ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
@@ -5364,35 +5910,50 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
+msgstr "파ì´í”„ë¼ì¸ ìƒì„±"
+
+msgid "Pipeline|Duration"
msgstr ""
msgid "Pipeline|Existing branch name or tag"
msgstr ""
-msgid "Pipeline|Run Pipeline"
+msgid "Pipeline|Pipeline"
msgstr ""
+msgid "Pipeline|Run Pipeline"
+msgstr "파ì´í”„ë¼ì¸ 실행"
+
msgid "Pipeline|Search branches"
-msgstr ""
+msgstr "브랜치 검색"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
-msgid "Pipeline|Stop pipeline"
+msgid "Pipeline|Stages"
msgstr ""
-msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgid "Pipeline|Status"
msgstr ""
+msgid "Pipeline|Stop pipeline"
+msgstr "파ì´í”„ë¼ì¸ 중지"
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr "#%{pipelineId} 파ì´í”„ë¼ì¸ì„ 중지하시겠습니까?"
+
msgid "Pipeline|Variables"
-msgstr ""
+msgstr "변수"
msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
-msgstr ""
+msgstr "%{pipelineId} 파ì´í”„ë¼ì¸ì„ 중지하고 있습니다."
msgid "Pipeline|all"
msgstr "모ë‘"
@@ -5409,12 +5970,6 @@ msgstr "스테ì´ì§•"
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5424,12 +5979,18 @@ msgstr "Play"
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5440,6 +6001,9 @@ msgid "Please solve the reCAPTCHA"
msgstr "ReCAPTCHA를 풀어 주십시오."
msgid "Please try again"
+msgstr "다시 ì‹œë„í•´ 주세요."
+
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
msgstr ""
msgid "Please wait while we connect to your repository. Refresh at will."
@@ -5454,23 +6018,32 @@ msgstr "환경 설정"
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
+msgstr "미리보기"
+
+msgid "Preview payload"
msgstr ""
msgid "Primary"
-msgstr ""
+msgstr "주"
msgid "Prioritize"
msgstr ""
msgid "Prioritize label"
-msgstr ""
+msgstr "ë¼ë²¨ ìš°ì„  순위"
msgid "Prioritized Labels"
-msgstr ""
+msgstr "ìš°ì„  순위가 ì§€ì •ëœ ë¼ë²¨"
msgid "Prioritized label"
-msgstr ""
+msgstr "ìš°ì„  순위가 ì§€ì •ëœ ë¼ë²¨"
msgid "Private - Project access must be granted explicitly to each user."
msgstr "Private - 프로ì íŠ¸ ì ‘ê·¼ì€ ê° ì‚¬ìš©ìžë³„ë¡œ 명시ì ìœ¼ë¡œ 허용ë˜ì–´ì•¼ 합니다."
@@ -5482,78 +6055,174 @@ msgid "Private projects can be created in your personal namespace with:"
msgstr ""
msgid "Profile"
-msgstr ""
+msgstr "프로필"
msgid "Profile Settings"
-msgstr ""
+msgstr "프로필 설정"
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
-msgstr ""
+msgstr "%{yourAccount}를 ì˜êµ¬ì ìœ¼ë¡œ 삭제하려고 합니다. ì´ìŠˆ, 머지 리퀘스트(MR), 그리고 ë‚´ ê³„ì •ì— ì—°ê²°ëœ ê·¸ë£¹ê°€ ì‚­ì œë ê²ƒìž…니다. %{deleteAccount}ì„ í™•ì¸í•˜ë©´ ë˜ëŒë¦¬ê±°ë‚˜, 취소할 수 없습니다."
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
-msgstr ""
+msgstr "ì‚¬ìš©ìž ì´ë¦„ì„ %{currentUsernameBold}ì—ì„œ %{newUsernameBold}으로 변경하려고 합니다. 기존 프로필과 프로ì íŠ¸ë“¤ì€ %{newUsername}으로 리디렉션ë˜ì§€ë§Œ, %{currentUsername}ê°€ 다른 유저나 ê·¸ë£¹ì— ì˜í•´ 등ë¡ë˜ë©´ ë” ì´ìƒ 리디렉션ë˜ì§€ 않습니다. ì‚¬ìš©ìž ì´ë¦„ì„ ë³€ê²½í•œ ë’¤ git ì €ìž¥ì†Œì˜ ë¦¬ëª¨íŠ¸ë¥¼ 변경하세요."
msgid "Profiles|Account scheduled for removal."
msgstr "ê³„ì •ì´ ì‚­ì œë  ì˜ˆì •ìž…ë‹ˆë‹¤."
msgid "Profiles|Add key"
-msgstr ""
+msgstr "키 추가"
msgid "Profiles|Add status emoji"
+msgstr "ìƒíƒœ ì´ëª¨í‹°ì½˜ 추가"
+
+msgid "Profiles|Avatar cropper"
msgstr ""
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr "아바타가 ì‚­ì œë©ë‹ˆë‹¤. 확실합니까?"
+
msgid "Profiles|Change username"
+msgstr "사용ìžëª… 변경"
+
+msgid "Profiles|Choose file..."
+msgstr "íŒŒì¼ ì„ íƒ.."
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
msgstr ""
msgid "Profiles|Clear status"
-msgstr ""
+msgstr "ìƒíƒœ 지우기"
msgid "Profiles|Current path: %{path}"
-msgstr ""
+msgstr "현재 경로: %{path}"
+
+msgid "Profiles|Current status"
+msgstr "현재 ìƒíƒœ"
msgid "Profiles|Delete Account"
-msgstr ""
+msgstr "계정 삭제"
msgid "Profiles|Delete account"
-msgstr ""
+msgstr "계정 삭제"
msgid "Profiles|Delete your account?"
-msgstr ""
+msgstr "ê³„ì •ì„ ì‚­ì œí• ê¹Œìš”?"
msgid "Profiles|Deleting an account has the following effects:"
msgstr "ê³„ì •ì„ ì‚­ì œí•˜ë©´ 다ìŒê³¼ ê°™ì€ ì˜í–¥ì´ 있습니다:"
+msgid "Profiles|Do not show on profile"
+msgstr "í”„ë¡œí•„ì— í‘œì‹œí•˜ì§€ ì•ŠìŒ"
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr "프로필 편집"
+
msgid "Profiles|Invalid password"
msgstr "ìž˜ëª»ëœ íŒ¨ìŠ¤ì›Œë“œ"
msgid "Profiles|Invalid username"
msgstr "ìž˜ëª»ëœ ì‚¬ìš©ìžì´ë¦„"
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr "파ì¼ì´ ì„ íƒë˜ì§€ 않았습니다."
+
msgid "Profiles|Path"
+msgstr "경로"
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
msgstr ""
+msgid "Profiles|Public Avatar"
+msgstr "공개 아바타"
+
+msgid "Profiles|Remove avatar"
+msgstr "아바타 제거"
+
+msgid "Profiles|Set new profile picture"
+msgstr "새 프로필 사진 설정"
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr "ì¼ë¶€ ì˜µì…˜ì€ LDAP 계정ì—ì„œ 사용할 수 없습니다."
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr "250ìž ë¯¸ë§Œìœ¼ë¡œ ìžì‹ ì— 대해 알려주세요."
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr "최대 허용ë˜ëŠ” 파ì¼ì˜ í¬ê¸°ëŠ” 200KB입니다."
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
+msgstr "ì´ê²ƒì€ 공개 SSH 키가 아닌것 같습니다. ì •ë§ë¡œ 추가 하시겠어요?"
+
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr "ì´ ì´ë©”ì¼ì€ 공개 í”„ë¡œí•„ì— í‘œì‹œë©ë‹ˆë‹¤."
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
-msgstr ""
+msgstr "ì´ ê·¸ë¦¼ê³¼ 메시지는 프로필과 ì¸í„°íŽ˜ì´ìŠ¤ ì „ì²´ì— ë‚˜íƒ€ë‚©ë‹ˆë‹¤."
+
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr "ì´ ê¸°ëŠ¥ì€ ì‹¤í—˜ì ì´ë©° ë²ˆì—­ì´ ì•„ì§ ì™„ë£Œë˜ì§€ 않았습니다."
+
+msgid "Profiles|This information will appear on your profile."
+msgstr "ì´ ì •ë³´ëŠ” í”„ë¡œí•„ì— í‘œì‹œë©ë‹ˆë‹¤."
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "확ì¸ì„ 위해 %{confirmationValue} 를 입력하세요."
msgid "Profiles|Typically starts with \"ssh-rsa …\""
-msgstr ""
+msgstr "ì¼ë°˜ì ìœ¼ë¡œ \"ssh-rsa ...\"으로 시작합니다."
+
+msgid "Profiles|Update profile settings"
+msgstr "프로필 설정 ì—…ë°ì´íŠ¸"
msgid "Profiles|Update username"
+msgstr "ì‚¬ìš©ìž ì´ë¦„ ì—…ë°ì´íŠ¸"
+
+msgid "Profiles|Upload new avatar"
+msgstr "새 아바타 업로드"
+
+msgid "Profiles|Use a private email - %{email}"
msgstr ""
msgid "Profiles|Username change failed - %{message}"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ì´ë¦„ 바꾸기 실패 - %{message}"
msgid "Profiles|Username successfully changed"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ì´ë¦„ì„ ì„±ê³µì ìœ¼ë¡œ 바꿨습니다"
+
+msgid "Profiles|Website"
+msgstr "웹 사ì´íŠ¸"
msgid "Profiles|What's your status?"
+msgstr "ìƒíƒœëŠ” 어떤가요?"
+
+msgid "Profiles|You can change your avatar here"
+msgstr "여기ì—ì„œ 아바타를 변경할 수 있습니다."
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr "여기ì—ì„œ 아바타를 변경하거나 현재 아바타를 제거하여 %{gravatar_link}ë¡œ ë˜ëŒë¦´ 수 있습니다"
+
+msgid "Profiles|You can upload your avatar here"
+msgstr "여기ì—ì„œ 아바타를 업로드 í•  수 있습니다."
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
msgstr ""
msgid "Profiles|You don't have access to delete this user."
@@ -5565,26 +6234,35 @@ msgstr "ë‹¹ì‹ ì˜ ê³„ì •ì„ ì‚­ì œí•˜ê¸° ì „ì— ì´ ê·¸ë£¹ë“¤ì˜ ì†Œìœ ê¶Œì„ ì
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "ë‹¹ì‹ ì˜ ê³„ì •ì€ í˜„ìž¬ ë‹¤ìŒ ê·¸ë£¹ë“¤ì˜ ì†Œìœ ìžìž…니다:"
-msgid "Profiles|Your status"
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
msgstr ""
-msgid "Profiles|e.g. My MacBook key"
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
msgstr ""
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr "ë‚˜ì˜ ìƒíƒœ"
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr "예: 내 MacBook 키"
+
msgid "Profiles|your account"
msgstr "계정"
msgid "Profiling - Performance bar"
-msgstr ""
+msgstr "프로파ì¼ë§ - 성능 표시줄"
msgid "Programming languages used in this repository"
-msgstr ""
+msgstr "ì´ ì €ìž¥ì†Œì— ì‚¬ìš© ëœ í”„ë¡œê·¸ëž˜ë° ì–¸ì–´"
msgid "Progress"
-msgstr ""
+msgstr "진행률"
msgid "Project"
-msgstr ""
+msgstr "프로ì íŠ¸"
msgid "Project '%{project_name}' is in the process of being deleted."
msgstr "프로ì íŠ¸ '%{project_name}' ì‚­ì œ 중입니다."
@@ -5599,7 +6277,10 @@ msgid "Project '%{project_name}' was successfully updated."
msgstr "'%{project_name}'프로ì íŠ¸ê°€ 성공ì ìœ¼ë¡œ ì—…ë°ì´íŠ¸ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "Project Badges"
-msgstr ""
+msgstr "프로ì íŠ¸ 배지"
+
+msgid "Project URL"
+msgstr "프로ì íŠ¸ URL"
msgid "Project access must be granted explicitly to each user."
msgstr "프로ì íŠ¸ 액세스는 ê° ì‚¬ìš©ìžì—게 명시ì ìœ¼ë¡œ 부여ë˜ì–´ì•¼í•©ë‹ˆë‹¤."
@@ -5626,6 +6307,9 @@ msgid "Project export started. A download link will be sent by email."
msgstr "프로ì íŠ¸ 내보내기가 시작ë˜ì—ˆìŠµë‹ˆë‹¤. 다운로드 ë§í¬ëŠ” ì´ë©”ì¼ë¡œ 전송ë©ë‹ˆë‹¤."
msgid "Project name"
+msgstr "프로ì íŠ¸ ì´ë¦„"
+
+msgid "Project slug"
msgstr ""
msgid "ProjectActivityRSS|Subscribe"
@@ -5655,77 +6339,101 @@ msgstr "Never"
msgid "ProjectLifecycle|Stage"
msgstr "스테ì´ì§•"
-msgid "ProjectPage|Project ID: %{project_id}"
+msgid "ProjectOverview|Fork"
msgstr ""
-msgid "ProjectSettings|Badges"
+msgid "ProjectOverview|Forks"
msgstr ""
-msgid "ProjectSettings|Contact an admin to change this setting."
+msgid "ProjectOverview|Go to your fork"
msgstr ""
-msgid "ProjectSettings|Customize your project badges."
+msgid "ProjectOverview|Star"
msgstr ""
-msgid "ProjectSettings|Failed to protect the tag"
+msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You have reached your project limit"
+msgstr "프로ì íŠ¸ í•œë„ì— ë„달했습니다."
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr "프로ì íŠ¸ì— ë³„ì„ í‘œì‹œí•˜ë ¤ë©´ 로그ì¸í•´ì•¼í•©ë‹ˆë‹¤."
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr "프로ì íŠ¸ ID: %{project_id}"
+
+msgid "ProjectSettings|Badges"
+msgstr "뱃지"
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr "ì´ ì„¤ì •ì„ ë³€ê²½í•˜ë ¤ë©´ 관리ìžì—게 문ì˜í•˜ì„¸ìš”."
+
+msgid "ProjectSettings|Customize your project badges."
+msgstr "프로ì íŠ¸ 뱃지 커스텀마ì´ì§•"
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr "태그 ë³´í˜¸ì— ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤."
+
msgid "ProjectSettings|Failed to update tag!"
-msgstr ""
+msgstr "태그 ì—…ë°ì´íŠ¸ì— 실패했습니다!"
msgid "ProjectSettings|Learn more about badges."
-msgstr ""
+msgstr "ë±ƒì§€ì— ëŒ€í•´ ìžì„¸ížˆ 알아보세요."
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
-msgstr ""
+msgstr "ì´ ì €ìž¥ì†Œì—는 ì„œëª…ëœ ì»¤ë°‹ë§Œ 푸쉬할 수 있습니다."
msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
-msgstr ""
+msgstr "ì´ ì„¤ì •ì€ ì„œë²„ 레벨ì—ì„œ ì ìš©ë˜ì—ˆìœ¼ë©°, 관리ìžì— ì˜í•´ ë³€ê²½ë  ìˆ˜ 있습니다."
msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
-msgstr ""
+msgstr "ì´ ì„¤ì •ì€ ì„œë²„ 레벨ì—ì„œ ì ìš©ë˜ì—ˆìœ¼ë©°, 프로ì íŠ¸ì— ì˜í•´ ë³€ê²½ë  ìˆ˜ 있습니다."
msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
-msgstr ""
+msgstr "관리ìžì— 변경ë˜ì§€ 않는 í•œ, ì´ ì„¤ì •ì€ ëª¨ë“  프로ì íŠ¸ì— ì ìš©ë©ë‹ˆë‹¤."
msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
msgstr ""
msgid "Projects"
-msgstr ""
+msgstr "프로ì íŠ¸"
msgid "Projects shared with %{group_name}"
+msgstr "%{group_name}ê³¼ 공유ë˜ëŠ” 프로ì íŠ¸"
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
msgstr ""
msgid "ProjectsDropdown|Frequently visited"
msgstr "ìžì£¼ 방문"
msgid "ProjectsDropdown|Loading projects"
-msgstr ""
+msgstr "프로ì íŠ¸ 로딩"
msgid "ProjectsDropdown|Projects you visit often will appear here"
msgstr "ìžì£¼ 방문하는 프로ì íŠ¸ëŠ” ì—¬ê¸°ì— í‘œì‹œë©ë‹ˆë‹¤"
msgid "ProjectsDropdown|Search your projects"
-msgstr ""
+msgstr "프로ì íŠ¸ 검색"
msgid "ProjectsDropdown|Something went wrong on our end."
msgstr "문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "ProjectsDropdown|Sorry, no projects matched your search"
-msgstr ""
+msgstr "죄송합니다, 검색과 ì¼ì¹˜í•˜ëŠ” 프로ì íŠ¸ëŠ” 없습니다."
msgid "ProjectsDropdown|This feature requires browser localStorage support"
msgstr ""
msgid "PrometheusAlerts|Add alert"
-msgstr ""
+msgstr "알림 추가"
msgid "PrometheusAlerts|Alert set"
-msgstr ""
+msgstr "알림 설정"
msgid "PrometheusAlerts|Edit alert"
-msgstr ""
+msgstr "알림 수정"
msgid "PrometheusAlerts|Error creating alert"
msgstr ""
@@ -5749,7 +6457,7 @@ msgid "PrometheusAlerts|Threshold"
msgstr ""
msgid "PrometheusDashboard|Time"
-msgstr ""
+msgstr "시간"
msgid "PrometheusService|%{exporters} with %{metrics} were found"
msgstr ""
@@ -5758,17 +6466,14 @@ msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">co
msgstr ""
msgid "PrometheusService|Active"
-msgstr ""
+msgstr "활성"
msgid "PrometheusService|Auto configuration"
-msgstr ""
+msgstr "ìžë™ 설정"
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -5809,7 +6514,7 @@ msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example
msgstr ""
msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
-msgstr ""
+msgstr "ë‹¹ì‹ ì˜ í´ëŸ¬ìŠ¤í„°ì—ì„œ Prometheusê°€ ìžë™ìœ¼ë¡œ 관리ë˜ê³  있습니다."
msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
msgstr ""
@@ -5827,16 +6532,16 @@ msgid "PrometheusService|Waiting for your first deployment to an environment to
msgstr ""
msgid "Promote"
-msgstr ""
+msgstr "승격"
msgid "Promote these project milestones into a group milestone."
-msgstr ""
+msgstr "프로ì íŠ¸ 마ì¼ìŠ¤í†¤ì„ 그룹 마ì¼ìŠ¤í†¤ìœ¼ë¡œ 승격합니다."
msgid "Promote to Group Milestone"
-msgstr ""
+msgstr "그룹 마ì¼ìŠ¤í†¤ìœ¼ë¡œ 승격"
msgid "Promote to group label"
-msgstr ""
+msgstr "그룹 ë¼ë²¨ë¡œ 승격"
msgid "Promotions|Don't show me this again"
msgstr ""
@@ -5851,10 +6556,10 @@ msgid "Promotions|Upgrade plan"
msgstr ""
msgid "Protected"
-msgstr ""
+msgstr "보호ë¨"
msgid "Protected Environments"
-msgstr ""
+msgstr "ë³´í˜¸ëœ í™˜ê²½"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
@@ -5869,7 +6574,7 @@ msgid "ProtectedEnvironment|Environment"
msgstr ""
msgid "ProtectedEnvironment|Protect"
-msgstr ""
+msgstr "보호"
msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
msgstr ""
@@ -5887,7 +6592,7 @@ msgid "ProtectedEnvironment|There are currently no protected environments, prote
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
-msgstr ""
+msgstr "보호 해제"
msgid "ProtectedEnvironment|Your environment can't be unprotected"
msgstr ""
@@ -5902,7 +6607,7 @@ msgid "Protip:"
msgstr "Protip:"
msgid "Provider"
-msgstr ""
+msgstr "공급ìž"
msgid "Pseudonymizer data collection"
msgstr ""
@@ -5917,28 +6622,28 @@ msgid "Public pipelines"
msgstr ""
msgid "Pull"
-msgstr ""
+msgstr "Pull"
msgid "Push"
-msgstr ""
+msgstr "Push"
msgid "Push Rules"
-msgstr ""
+msgstr "Push 규칙"
msgid "Push events"
msgstr "푸쉬 ì´ë²¤íŠ¸"
msgid "Push project from command line"
-msgstr ""
+msgstr "명령줄로 프로ì íŠ¸ 푸쉬"
msgid "Push to create a project"
-msgstr ""
+msgstr "푸쉬해서 프로ì íŠ¸ ìƒì„±"
msgid "PushRule|Committer restriction"
msgstr ""
msgid "Pushed"
-msgstr ""
+msgstr "푸시ë¨"
msgid "Pushes"
msgstr ""
@@ -5956,16 +6661,22 @@ msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
msgstr ""
msgid "Readme"
-msgstr ""
+msgstr "Readme"
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr "최근 검색"
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
msgid "Refresh"
-msgstr ""
+msgstr "새로고침"
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
@@ -5975,7 +6686,7 @@ msgid "Regenerate key"
msgstr ""
msgid "Regex pattern"
-msgstr ""
+msgstr "ì •ê·œ í‘œí˜„ì‹ íŒ¨í„´"
msgid "Register / Sign In"
msgstr "ë“±ë¡ / 로그ì¸"
@@ -5987,7 +6698,7 @@ msgid "Register and see your runners for this project."
msgstr ""
msgid "Registry"
-msgstr ""
+msgstr "레지스트리"
msgid "Related Commits"
msgstr "관련 커밋"
@@ -6008,34 +6719,46 @@ msgid "Related Merged Requests"
msgstr "관련 머지 리퀘스트(MR)"
msgid "Related merge requests"
-msgstr ""
+msgstr "ê´€ë ¨ëœ ë¨¸ì§€ 리퀘스트(MR)"
msgid "Remind later"
msgstr "ë‚˜ì¤‘ì— ë‹¤ì‹œ 알림"
msgid "Remove"
-msgstr ""
+msgstr "삭제"
msgid "Remove Runner"
-msgstr ""
+msgstr "Runner 제거"
msgid "Remove avatar"
+msgstr "아바타 제거"
+
+msgid "Remove group"
msgstr ""
msgid "Remove priority"
-msgstr ""
+msgstr "우선 순위 삭제"
msgid "Remove project"
msgstr "프로ì íŠ¸ ì‚­ì œ"
-msgid "Rename"
+msgid "Removed group can not be restored!"
msgstr ""
-msgid "Rename file"
+msgid "Removing group will cause all child projects and resources to be removed."
msgstr ""
+msgid "Rename"
+msgstr "ì´ë¦„ 바꾸기"
+
+msgid "Rename file"
+msgstr "íŒŒì¼ ì´ë¦„ 바꾸기"
+
msgid "Rename folder"
-msgstr ""
+msgstr "í´ë” ì´ë¦„ 바꾸기"
+
+msgid "Reopen epic"
+msgstr "ì—픽 다시 열기"
msgid "Repair authentication"
msgstr ""
@@ -6044,25 +6767,40 @@ msgid "Reply to this email directly or %{view_it_on_gitlab}."
msgstr ""
msgid "Repo by URL"
+msgstr "저장소 URL"
+
+msgid "Report abuse to GitLab"
msgstr ""
+msgid "Reporting"
+msgstr "ë³´ê³ "
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
-msgid "Reports|Execution time"
+msgid "Reports|Confidence"
msgstr ""
+msgid "Reports|Execution time"
+msgstr "실행 시간"
+
msgid "Reports|Failure"
+msgstr "실패"
+
+msgid "Reports|Severity"
msgstr ""
msgid "Reports|System output"
-msgstr ""
+msgstr "시스템 출력"
msgid "Reports|Test summary"
-msgstr ""
+msgstr "테스트 요약"
msgid "Reports|Test summary failed loading results"
msgstr ""
@@ -6070,29 +6808,32 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
msgid "Repository"
-msgstr ""
+msgstr "저장소"
msgid "Repository Settings"
-msgstr ""
+msgstr "저장소 설정"
msgid "Repository URL"
-msgstr ""
+msgstr "저장소 URL"
msgid "Repository has no locks."
-msgstr ""
+msgstr "ì €ìž¥ì†Œì— ìž ê¸ˆì´ ì—†ìŠµë‹ˆë‹¤."
msgid "Repository maintenance"
-msgstr ""
+msgstr "저장소 유지 보수"
msgid "Repository mirror"
-msgstr ""
+msgstr "저장소 미러"
msgid "Repository storage"
-msgstr ""
+msgstr "ì €ìž¥ì†Œì˜ ì €ìž¥ê³µê°„"
msgid "RepositorySettingsAccessLevel|Select"
msgstr ""
@@ -6103,11 +6844,11 @@ msgstr "액세스 요청"
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
-msgstr "git storage 헬스 정보 초기화"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr "GitLabì— ì•¡ì„¸ìŠ¤ í•  ë•Œ 모든 사용ìžê°€ 서비스 약관 ë° ê°œì¸ ì •ë³´ 취급 ë°©ì¹¨ì— ë™ì˜í•˜ë„ë¡í•˜ì‹­ì‹œì˜¤."
msgid "Reset health check access token"
msgstr "헬스 ì²´í¬ ì ‘ê·¼ í† í° ì´ˆê¸°í™”"
@@ -6124,20 +6865,32 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
-msgid "Resume"
+msgid "Response metrics (HA Proxy)"
msgstr ""
-msgid "Retry"
+msgid "Response metrics (NGINX Ingress)"
msgstr ""
-msgid "Retry this job"
+msgid "Response metrics (NGINX)"
msgstr ""
+msgid "Resume"
+msgstr "재개"
+
+msgid "Retry"
+msgstr "재시ë„"
+
+msgid "Retry this job"
+msgstr "ì´ ìž‘ì—… 재시ë„"
+
msgid "Retry verification"
-msgstr ""
+msgstr "ê²€ì¦ ìž¬ì‹œë„"
msgid "Reveal Variables"
msgstr ""
@@ -6153,22 +6906,22 @@ msgid "Revert this merge request"
msgstr "ì´ ë¨¸ì§€ 리퀘스트(MR) ë˜ëŒë¦¬ê¸°"
msgid "Review"
-msgstr ""
+msgstr "리뷰"
msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
msgstr ""
msgid "Reviewing"
-msgstr ""
+msgstr "검토중"
msgid "Reviewing (merge request !%{mergeRequestId})"
-msgstr ""
+msgstr "검토 중 (머지 리퀘스트(MR) !%{mergeRequestId})"
msgid "Revoke"
-msgstr ""
+msgstr "í기"
msgid "Roadmap"
-msgstr ""
+msgstr "로드맵"
msgid "Run CI/CD pipelines for external repositories"
msgstr ""
@@ -6176,41 +6929,65 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
+msgstr "Runner 토í°"
+
+msgid "Runner will not receive any new jobs"
msgstr ""
msgid "Runners"
msgstr "Runners"
msgid "Runners API"
-msgstr ""
+msgstr "Runners API"
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
-msgid "Runners page"
+msgid "Runners can be placed on separate users, servers, even on your local machine."
msgstr ""
-msgid "Runners page."
+msgid "Runners currently online: %{active_runners_count}"
msgstr ""
+msgid "Runners page"
+msgstr "Runners 페ì´ì§€"
+
+msgid "Runners page."
+msgstr "Runners 페ì´ì§€."
+
msgid "Runners|You have used all your shared Runners pipeline minutes."
-msgstr ""
+msgstr "모든 공유 Runners 파ì´í”„ë¼ì¸ ì‹œê°„ì„ ì‚¬ìš©í–ˆìŠµë‹ˆë‹¤."
msgid "Running"
-msgstr ""
+msgstr "실행중"
msgid "SAML SSO"
-msgstr ""
+msgstr "SAML SSO"
msgid "SAML SSO for %{group_name}"
-msgstr ""
+msgstr "%{group_name}ì˜ SAML SSO"
msgid "SAML Single Sign On"
-msgstr ""
+msgstr "SAML Single Sign On"
msgid "SAML Single Sign On Settings"
-msgstr ""
+msgstr "SAML Single Sign On 설정"
+
+msgid "SAST"
+msgstr "SAST"
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6219,21 +6996,24 @@ msgid "SSH Keys"
msgstr "SSH 키"
msgid "SSH host keys"
-msgstr ""
+msgstr "SSH 호스트 키"
msgid "SSH public key"
-msgstr ""
+msgstr "SSH 공개키"
msgid "SSL Verification"
-msgstr ""
+msgstr "SSL ê²€ì¦"
msgid "Save"
-msgstr ""
+msgstr "저장"
msgid "Save application"
-msgstr ""
+msgstr "애플리케ì´ì…˜ 저장"
msgid "Save changes"
+msgstr "변경사항 저장"
+
+msgid "Save changes before testing"
msgstr ""
msgid "Save pipeline schedule"
@@ -6246,10 +7026,10 @@ msgid "Schedule a new pipeline"
msgstr "새로운 파ì´í”„ë¼ì¸ 스케줄 잡기"
msgid "Scheduled"
-msgstr ""
+msgstr "예정ë¨"
msgid "Schedules"
-msgstr ""
+msgstr "ì¼ì •"
msgid "Scheduling Pipelines"
msgstr "파ì´í”„ë¼ì¸ 스케줄ë§"
@@ -6264,41 +7044,50 @@ msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable th
msgstr ""
msgid "Scroll to bottom"
-msgstr ""
+msgstr "맨 아래로 스í¬ë¡¤"
msgid "Scroll to top"
-msgstr ""
+msgstr "맨 위로 스í¬ë¡¤"
msgid "Search"
-msgstr ""
+msgstr "검색"
msgid "Search branches"
-msgstr ""
+msgstr "브랜치 검색"
msgid "Search branches and tags"
msgstr "브랜치 ë° íƒœê·¸ 검색"
msgid "Search files"
-msgstr ""
+msgstr "íŒŒì¼ ê²€ìƒ‰"
msgid "Search for projects, issues, etc."
-msgstr ""
+msgstr "프로ì íŠ¸, 문제 등 검색"
msgid "Search merge requests"
-msgstr ""
+msgstr "머지 리퀘스트(MR) 검색"
msgid "Search milestones"
+msgstr "마ì¼ìŠ¤í†¤ 검색"
+
+msgid "Search or filter results..."
msgstr ""
msgid "Search or jump to…"
-msgstr ""
+msgstr "검색 ë˜ëŠ” ì´ë™.."
msgid "Search project"
msgstr "프로ì íŠ¸ 검색"
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr "ì‚¬ìš©ìž ê²€ìƒ‰"
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6323,26 +7112,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
-msgstr "실패 정보를 리셋하기까지 ë‚¨ì€ ì‹œê°„(ì´ˆ)"
+msgid "Secret"
+msgstr ""
+
+msgid "Security"
+msgstr "보안"
+
+msgid "Security Dashboard"
+msgstr "보안 대시보드"
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
-msgid "Seconds to wait for a storage access attempt"
-msgstr "저장공간 ì ‘ê·¼ ì‹œë„를 위해 대기할 시간 (ì´ˆ)"
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard|Issue Created"
msgstr ""
-msgid "Security"
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Reports|Create issue"
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6355,28 +7173,34 @@ msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
msgstr ""
msgid "Select"
-msgstr ""
+msgstr "ì„ íƒ"
msgid "Select Archive Format"
msgstr "ì•„ì¹´ì´ë¸Œ í¬ë§· ì„ íƒ"
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr "시간대 ì„ íƒ"
msgid "Select an existing Kubernetes cluster or create a new one"
-msgstr ""
+msgstr "기존 Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ ì„ íƒí•˜ê±°ë‚˜ 새로 만듭니다."
msgid "Select assignee"
msgstr "ë‹´ë‹¹ìž ì„ íƒ"
msgid "Select branch/tag"
-msgstr ""
+msgstr "브랜치/태그 ì„ íƒ"
msgid "Select project"
-msgstr ""
+msgstr "프로ì íŠ¸ ì„ íƒ"
msgid "Select project and zone to choose machine type"
msgstr ""
@@ -6393,6 +7217,9 @@ msgstr ""
msgid "Select target branch"
msgstr "ëŒ€ìƒ ë¸Œëžœì¹˜ ì„ íƒ"
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6403,25 +7230,28 @@ msgid "Selective synchronization"
msgstr ""
msgid "Send email"
-msgstr ""
+msgstr "ì´ë©”ì¼ ì „ì†¡"
+
+msgid "Send usage data"
+msgstr "사용 ë°ì´í„° 보내기"
msgid "Sep"
-msgstr ""
+msgstr "9ì›”"
msgid "September"
-msgstr ""
+msgstr "9ì›”"
msgid "Server version"
-msgstr ""
+msgstr "서버 버전"
msgid "Service Desk"
-msgstr ""
+msgstr "서비스 ë°ìŠ¤í¬"
msgid "Service Templates"
msgstr "서비스 템플릿"
msgid "Service URL"
-msgstr ""
+msgstr "서비스 URL"
msgid "Session expiration, projects limit and attachment size."
msgstr ""
@@ -6429,6 +7259,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "%{protocol} í”„ë¡œí† ì½œì„ í†µí•´ Pull 하거나 Push하려면 ê³„ì •ì— íŒ¨ìŠ¤ì›Œë“œë¥¼ 설정하십시오."
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6436,19 +7269,22 @@ msgid "Set instance-wide template repository"
msgstr ""
msgid "Set max session time for web terminal."
-msgstr ""
+msgstr "웹 터미ë„ì˜ ìµœëŒ€ 세션 ì‹œê°„ì„ ì„¤ì •í•©ë‹ˆë‹¤."
msgid "Set notification email for abuse reports."
-msgstr ""
+msgstr "남용 ë³´ê³ ì„œì— ëŒ€í•œ 알림 ì´ë©”ì¼ì„ 설정합니다."
msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
-msgstr ""
+msgstr "사용ìžì˜ ë¡œê·¸ì¸ ìš”êµ¬ ì‚¬í•­ì„ ì„¤ì •í•©ë‹ˆë‹¤. 반드시 ì´ì¤‘ ì¸ì¦ 하ë„ë¡ ì„¤ì •í•©ë‹ˆë‹¤."
msgid "Set up CI/CD"
+msgstr "CI/CD 설정"
+
+msgid "Set up a %{type} Runner manually"
msgstr ""
-msgid "Set up Koding"
-msgstr "Koding 설정"
+msgid "Set up a specific Runner automatically"
+msgstr "특정 Runner ìžë™ 설정"
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
@@ -6459,23 +7295,44 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "패스워드 설정"
-msgid "Settings"
-msgstr "설정"
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
-msgstr "특정 Runner ìžë™ 설정"
+msgid "SetStatusModal|Edit status"
+msgstr ""
-msgid "Share"
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
msgstr ""
+msgid "Settings"
+msgstr "설정"
+
+msgid "Share"
+msgstr "공유"
+
msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
msgstr ""
msgid "Shared Runners"
-msgstr ""
+msgstr "공용 Runners"
+
+msgid "Shared projects"
+msgstr "ê³µìœ ëœ í”„ë¡œì íŠ¸"
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6490,13 +7347,13 @@ msgid "Sherlock Transactions"
msgstr ""
msgid "Show command"
-msgstr ""
+msgstr "명령 보기"
msgid "Show complete raw log"
-msgstr ""
+msgstr "완료 로그 표시"
msgid "Show latest version"
-msgstr ""
+msgstr "최신 버전 보기"
msgid "Show latest version of the diff"
msgstr ""
@@ -6515,13 +7372,13 @@ msgid_plural "Showing %d events"
msgstr[0] "%d ê°œì˜ ì´ë²¤íŠ¸ 표시 중"
msgid "Side-by-side"
-msgstr ""
+msgstr "나란히"
msgid "Sidebar|Change weight"
msgstr ""
msgid "Sidebar|None"
-msgstr ""
+msgstr "ì—†ìŒ"
msgid "Sidebar|Only numeral characters allowed"
msgstr ""
@@ -6530,41 +7387,47 @@ msgid "Sidebar|Weight"
msgstr ""
msgid "Sign in"
-msgstr ""
+msgstr "로그ì¸"
msgid "Sign in / Register"
-msgstr ""
+msgstr "ë¡œê·¸ì¸ / 등ë¡"
msgid "Sign in to %{group_name}"
-msgstr ""
+msgstr "%{group_name}ì— ë¡œê·¸ì¸"
msgid "Sign in with Single Sign-On"
-msgstr ""
+msgstr "Single Sign-On으로 로그ì¸"
msgid "Sign out"
-msgstr ""
+msgstr "로그아웃"
msgid "Sign-in restrictions"
-msgstr ""
+msgstr "ë¡œê·¸ì¸ ì œí•œ"
msgid "Sign-up restrictions"
-msgstr ""
+msgstr "가입 제한"
msgid "Size"
-msgstr ""
+msgstr "í¬ê¸°"
msgid "Size and domain settings for static websites"
msgstr ""
msgid "Slack application"
-msgstr ""
+msgstr "Slack 어플리케ì´ì…˜"
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr "스니펫"
@@ -6592,9 +7455,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr "프로ì íŠ¸ë¥¼ 가져오는 ë™ì•ˆ 문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -6607,14 +7476,26 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr "문제가 ë°œìƒí–ˆìŠµë‹ˆë‹¤. 다시 ì‹œë„해주세요."
msgid "Sorry, no epics matched your search"
+msgstr "죄송합니다. 검색과 ì¼ì¹˜í•˜ëŠ” ì—í”½ì´ ì—†ìŠµë‹ˆë‹¤."
+
+msgid "Sorry, no projects matched your search"
msgstr ""
msgid "Sort by"
-msgstr ""
+msgstr "다ìŒìœ¼ë¡œ ì •ë ¬"
msgid "SortOptions|Access level, ascending"
msgstr "권한 레벨, 오름차순"
@@ -6623,84 +7504,93 @@ msgid "SortOptions|Access level, descending"
msgstr "권한 레벨, 내림차순"
msgid "SortOptions|Created date"
-msgstr ""
+msgstr "ìƒì„±ì¼"
msgid "SortOptions|Due date"
-msgstr ""
+msgstr "마ê°ì¼"
msgid "SortOptions|Due later"
-msgstr ""
+msgstr "마ê°ì¼ì´ 먼"
msgid "SortOptions|Due soon"
-msgstr ""
+msgstr "마ê°ì¼ì´ 가까운"
msgid "SortOptions|Label priority"
-msgstr ""
+msgstr "ë¼ë²¨ 중요ë„"
msgid "SortOptions|Largest group"
-msgstr ""
+msgstr "í° ê·¸ë£¹"
msgid "SortOptions|Largest repository"
+msgstr "í° ì €ìž¥ì†Œ"
+
+msgid "SortOptions|Last Contact"
msgstr ""
msgid "SortOptions|Last created"
-msgstr ""
+msgstr "ìµœê·¼ì— ìƒì„±ëœ"
msgid "SortOptions|Last joined"
-msgstr ""
+msgstr "ìµœê·¼ì— ì°¸ì—¬í•œ"
msgid "SortOptions|Last updated"
-msgstr ""
+msgstr "ìµœê·¼ì— ì—…ë°ì´íŠ¸ ëœ"
msgid "SortOptions|Least popular"
-msgstr ""
+msgstr "ëœ ì¸ê¸°ìžˆëŠ”"
msgid "SortOptions|Less weight"
msgstr ""
msgid "SortOptions|Milestone"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤"
msgid "SortOptions|Milestone due later"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤ 마ê°ì¼ì´ 먼"
msgid "SortOptions|Milestone due soon"
-msgstr ""
+msgstr "마ì¼ìŠ¤í†¤ 마ê°ì¼ì´ 가까운"
msgid "SortOptions|More weight"
msgstr ""
msgid "SortOptions|Most popular"
+msgstr "ë” ì¸ê¸°ìžˆëŠ”"
+
+msgid "SortOptions|Most stars"
msgstr ""
msgid "SortOptions|Name"
-msgstr ""
+msgstr "ì´ë¦„"
msgid "SortOptions|Name, ascending"
-msgstr ""
+msgstr "ì´ë¦„, 오름차순"
msgid "SortOptions|Name, descending"
-msgstr ""
+msgstr "ì´ë¦„, 내림차순"
msgid "SortOptions|Oldest created"
-msgstr ""
+msgstr "ìƒì„±í•œì§€ 오래ëœ"
msgid "SortOptions|Oldest joined"
-msgstr ""
+msgstr "참여한지 오래ëœ"
msgid "SortOptions|Oldest sign in"
msgstr "ë¡œê·¸ì¸ ìˆœ"
msgid "SortOptions|Oldest updated"
-msgstr ""
+msgstr "ì—…ë°ì´íŠ¸ëœì§€ 오래ëœ"
msgid "SortOptions|Popularity"
-msgstr ""
+msgstr "ì¸ê¸°"
msgid "SortOptions|Priority"
-msgstr ""
+msgstr "우선 순위"
msgid "SortOptions|Recent sign in"
+msgstr "최근 로그ì¸"
+
+msgid "SortOptions|Start date"
msgstr ""
msgid "SortOptions|Start later"
@@ -6716,7 +7606,7 @@ msgid "Source"
msgstr "소스"
msgid "Source (branch or tag)"
-msgstr ""
+msgstr "소스 (브랜치 ë˜ëŠ” 태그)"
msgid "Source code"
msgstr "소스 코드"
@@ -6728,7 +7618,7 @@ msgid "Spam Logs"
msgstr "스팸 로그"
msgid "Spam and Anti-bot Protection"
-msgstr ""
+msgstr "스팸 ë° ì•ˆí‹°ë´‡ 보호"
msgid "Specific Runners"
msgstr ""
@@ -6743,7 +7633,7 @@ msgid "Squash commits"
msgstr ""
msgid "Stage"
-msgstr ""
+msgstr "스테ì´ì§€"
msgid "Stage & Commit"
msgstr ""
@@ -6752,13 +7642,13 @@ msgid "Stage all changes"
msgstr ""
msgid "Stage changes"
-msgstr ""
+msgstr "스테ì´ì§€ 변경사항"
msgid "Staged"
-msgstr ""
+msgstr "스테ì´ì§€"
msgid "Staged %{type}"
-msgstr ""
+msgstr "%{type} 스테ì´ì§€ë¨"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr ""
@@ -6767,10 +7657,10 @@ msgid "StarProject|Star"
msgstr "별표"
msgid "Starred Projects"
-msgstr ""
+msgstr "별표 í‘œì‹œëœ í”„ë¡œì íŠ¸"
msgid "Starred Projects' Activity"
-msgstr ""
+msgstr "별표 í‘œì‹œëœ í”„ë¡œì íŠ¸ 활ë™"
msgid "Starred projects"
msgstr "ë³„í‘œëœ í”„ë¡œì íŠ¸"
@@ -6778,65 +7668,95 @@ msgstr "ë³„í‘œëœ í”„ë¡œì íŠ¸"
msgid "Start a %{new_merge_request} with these changes"
msgstr "ì´ ë³€ê²½ 사항으로 %{new_merge_request} ì„ ì‹œìž‘í•˜ì‹­ì‹œì˜¤."
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr "시작 날짜"
+
msgid "Start the Runner!"
msgstr "Runner 시작!"
-msgid "Started"
+msgid "Start your trial"
msgstr ""
+msgid "Started"
+msgstr "시작ë¨"
+
msgid "Starts at (UTC)"
-msgstr ""
+msgstr "(UTC)ì— ì‹œìž‘"
msgid "State your message to activate"
msgstr ""
msgid "Status"
+msgstr "ìƒíƒœ"
+
+msgid "Stop environment"
msgstr ""
msgid "Stop impersonation"
msgstr ""
msgid "Stop this environment"
-msgstr ""
+msgstr "ì´ í™˜ê²½ 중지"
msgid "Stopped"
msgstr "중지"
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr "스토리지"
msgid "Storage:"
-msgstr ""
+msgstr "저장소:"
msgid "Subgroups"
-msgstr ""
+msgstr "하위 그룹"
+
+msgid "Subgroups and projects"
+msgstr "서브 그룹과 프로ì íŠ¸"
msgid "Submit as spam"
+msgstr "스팸으로 제출"
+
+msgid "Submit review"
msgstr ""
msgid "Submit search"
-msgstr ""
+msgstr "검색 제출"
msgid "Subscribe"
-msgstr ""
+msgstr "구ë…"
msgid "Subscribe at group level"
-msgstr ""
+msgstr "그룹 수준ì—ì„œ 구ë…"
msgid "Subscribe at project level"
+msgstr "프로ì íŠ¸ 수준ì—ì„œ 구ë…"
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
msgstr ""
msgid "Switch branch/tag"
msgstr "스위치 브랜치/태그"
msgid "Sync information"
-msgstr ""
+msgstr "ì •ë³´ ë™ê¸°í™”"
msgid "System Hooks"
msgstr ""
msgid "System Info"
-msgstr ""
+msgstr "시스템 정보"
msgid "System header and footer:"
msgstr ""
@@ -6844,18 +7764,21 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
-msgstr[0] ""
+msgstr[0] "태그 (%{tag_count})"
msgid "Tags"
msgstr "태그 "
msgid "Tags feed"
-msgstr ""
+msgstr "태그 피드"
msgid "Tags:"
-msgstr ""
+msgstr "태그:"
msgid "TagsPage|Browse commits"
msgstr "커밋 찾아보기"
@@ -6897,19 +7820,19 @@ msgid "TagsPage|Optionally, add a message to the tag."
msgstr "ì„ íƒì ìœ¼ë¡œ íƒœê·¸ì— ë©”ì‹œì§€ë¥¼ 추가하십시오."
msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
-msgstr ""
+msgstr "ì„ íƒì ìœ¼ë¡œ, 릴리스 노트를 íƒœê·¸ì— ì¶”ê°€í•˜ì‹­ì‹œì˜¤. GitLab ë°ì´í„°ë² ì´ìŠ¤ì— 저장ë˜ê³  태그 페ì´ì§€ì— í‘œì‹œë  ê²ƒ 입니다."
msgid "TagsPage|Release notes"
-msgstr ""
+msgstr "릴리즈 노트"
msgid "TagsPage|Repository has no tags yet."
msgstr "ì €ìž¥ì†Œì— ì•„ì§ íƒœê·¸ê°€ 없습니다."
msgid "TagsPage|Sort by"
-msgstr ""
+msgstr "정렬 기준"
msgid "TagsPage|Tags"
-msgstr ""
+msgstr "태그"
msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
msgstr "태그는 특정 지ì ì„ 중요하다고 표시하는 기능입니다."
@@ -6918,40 +7841,43 @@ msgid "TagsPage|This tag has no release notes."
msgstr ""
msgid "TagsPage|Use git tag command to add a new one:"
-msgstr ""
+msgstr "git tag ëª…ë ¹ì„ ì‚¬ìš©í•˜ì—¬ 새 태그를 추가하십시오:"
msgid "TagsPage|Write your release notes or drag files here…"
msgstr ""
msgid "TagsPage|protected"
-msgstr ""
+msgstr "보호ë¨"
msgid "Target Branch"
msgstr "ëŒ€ìƒ ë¸Œëžœì¹˜"
msgid "Target branch"
-msgstr ""
+msgstr "ëŒ€ìƒ ë¸Œëžœì¹˜"
msgid "Team"
-msgstr ""
+msgstr "팀"
msgid "Template"
-msgstr ""
+msgstr "템플릿"
msgid "Templates"
-msgstr ""
+msgstr "템플릿"
msgid "Terms of Service Agreement and Privacy Policy"
-msgstr ""
+msgstr "서비스 약관 계약 ë° ê°œì¸ ì •ë³´ 보호 ì •ì±…"
msgid "Terms of Service and Privacy Policy"
+msgstr "서비스 약관 ë° ê°œì¸ ì •ë³´ 보호 ì •ì±…"
+
+msgid "Test SAML SSO"
msgstr ""
msgid "Test coverage parsing"
-msgstr ""
+msgstr "테스트 커버리지 파싱"
msgid "Thanks! Don't show me this again"
-msgstr ""
+msgstr "ê°ì‚¬í•©ë‹ˆë‹¤! 다시 보지 않겠습니다."
msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
msgstr ""
@@ -6960,10 +7886,10 @@ msgid "The Git LFS objects will <strong>not</strong> be synced."
msgstr ""
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
-msgstr ""
+msgstr "ì´ìŠˆ 트래커는 프로ì íŠ¸ì—ì„œ 개선해야하거나 해결해야할 ì‚¬í•­ì„ ì¶”ê°€í•  수 있는 곳입니다."
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
-msgstr ""
+msgstr "ì´ìŠˆ 트래커는 프로ì íŠ¸ì—ì„œ 개선해야하거나 해결해야할 ì‚¬í•­ì„ ì¶”ê°€í•  수 있는 곳입니다. ì´ í”„ë¡œì íŠ¸ì—ì„œ ì´ìŠˆë¥¼ 만들려면 가입하거나 로그ì¸í•˜ì‹­ì‹œì˜¤."
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr ""
@@ -6987,19 +7913,13 @@ msgid "The fork relationship has been removed."
msgstr "í¬í¬ 관계가 제거ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
-msgstr ""
+msgstr "%{timeout} ì´í›„ 가져오기 ì‹œê°„ì´ ì´ˆê³¼ë˜ì—ˆìŠµë‹ˆë‹¤. 저장소가 ëŠë¦° 경우 복제/푸시 ì¡°í•©ì„ ì‚¬ìš©í•©ì‹œì˜¤."
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "ì´ìŠˆ 단계ì—는 ì´ìŠˆë¥¼ 작성하여 마ì¼ìŠ¤í†¤ìœ¼ë¡œ 지정하는 ë° ê±¸ë¦¬ëŠ” 시간 ë˜ëŠ” ì´ìŠˆ ë³´ë“œì˜ ëª©ë¡ì— ì´ìŠˆë¥¼ 추가하는 ì‹œê°„ì´ í‘œì‹œë©ë‹ˆë‹¤. ì´ ë‹¨ê³„ì˜ ë°ì´í„°ë¥¼ 보기 위해서는 ì´ìŠˆë¥¼ 먼저 작성해야 합니다."
msgid "The maximum file size allowed is 200KB."
-msgstr ""
-
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr "ì €ìž¥ê³µê°„ì— ì ‘ê·¼í•˜ê¸° 위해 GitLabì´ ì‹œë„í•  횟수"
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
+msgstr "허용ë˜ëŠ” 최대 íŒŒì¼ í¬ê¸°ëŠ” 200KB입니다."
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7035,10 +7955,10 @@ msgid "The repository for this project does not exist."
msgstr "ì´ í”„ë¡œì íŠ¸ì˜ 저장소가 존재하지 않습니다."
msgid "The repository for this project is empty"
-msgstr ""
+msgstr "ì´ í”„ë¡œì íŠ¸ì˜ 저장소가 비어있습니다."
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
-msgstr ""
+msgstr "저장소를 <code>http://</code>, <code>https://</code> ë˜ëŠ” <code>git://</code> 통해 액세스할 수 있어야 합니다."
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
msgstr ""
@@ -7049,33 +7969,24 @@ msgstr "Review 단계ì—서는 머지 리퀘스트(MR)를 작성한 후 머지í•
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "Staging 단계ì—서는 MR 머지과 프로ë•ì…˜ í™˜ê²½ì— ì½”ë“œ ë°°í¬ ì‚¬ì´ì˜ ì‹œê°„ì„ ë³´ì—¬ì¤ë‹ˆë‹¤. ë°ì´í„°ë¥¼ Production í™˜ê²½ì— ì²˜ìŒ ë°°í¬í•˜ë©´ ë°ì´í„°ê°€ ìžë™ìœ¼ë¡œ 추가ë©ë‹ˆë‹¤."
msgid "The tabs below will be removed in a future version"
-msgstr ""
+msgstr "아래 íƒ­ì€ í–¥í›„ 버전ì—ì„œ 제거 ë  ì˜ˆì •ìž…ë‹ˆë‹¤."
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr "테스트 단계ì—서는 GitLab CIê°€ 관련 머지 리퀘스트(MR)ì„ ìœ„í•´ 모든 파ì´í”„ë¼ì¸ì„ 실행하는 ë° ê±¸ë¦¬ëŠ” ì‹œê°„ì„ ë³´ì—¬ì¤ë‹ˆë‹¤. 첫 번째 파ì´í”„ë¼ì¸ ì‹¤í–‰ì´ ì™„ë£Œë˜ë©´ ë°ì´í„°ê°€ ìžë™ìœ¼ë¡œ 추가ë©ë‹ˆë‹¤."
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr "GitLabì´ ì‹¤íŒ¨ 정보를 보관하는 시간(ì´ˆ). ì´ ì‹œê°„ë™ì•ˆ 실패가 ë°œìƒí•˜ì§€ 않으면 ë§ˆìš´íŠ¸ì— ëŒ€í•œ 정보는 리셋ë©ë‹ˆë‹¤."
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr "GitLabì´ ì €ìž¥ê³µê°„ì— ì ‘ê·¼ì„ ì‹œë„하는 시간(ì´ˆ). ì´ ì‹œê°„ ì´í›„ timeout ì—러가 ë°œìƒí•©ë‹ˆë‹¤."
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr "해당 단계ì—ì„œ 수집 í•œ ê° ë°ì´í„° ìž…ë ¥ì— ì†Œìš” ëœ ì‹œê°„"
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7085,35 +7996,44 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "ê°’ì€ ì¼ë ¨ì˜ 관측 ê°’ 중ì ì— 있습니다. 예를 들어, 3, 5, 9 사ì´ì˜ 중간 ê°’ì€ 5입니다. 3, 5, 7, 8 사ì´ì˜ 중간 ê°’ì€ (5 + 7) / 2 = 6입니다."
-msgid "There are no issues to show"
+msgid "There are no archived projects yet"
msgstr ""
+msgid "There are no issues to show"
+msgstr "표시할 ì´ìŠˆê°€ 없습니다"
+
msgid "There are no labels yet"
-msgstr ""
+msgstr "ì•„ì§ ë¼ë²¨ì´ 없습니다."
msgid "There are no merge requests to show"
+msgstr "표시할 머지 리퀘스트(MR)가 없습니다."
+
+msgid "There are no projects shared with this group yet"
msgstr ""
-msgid "There are problems accessing Git storage: "
-msgstr "git storageì— ì ‘ê·¼í•˜ëŠ”ë° ë¬¸ì œê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤. "
+msgid "There are no staged changes"
+msgstr ""
-msgid "There was an error adding a todo."
+msgid "There are no unstaged changes"
msgstr ""
+msgid "There was an error adding a todo."
+msgstr "í•  ì¼ì„ 추가하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+
msgid "There was an error deleting the todo."
-msgstr ""
+msgstr "í•  ì¼ì„ 삭제하는 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "There was an error loading users activity calendar."
msgstr ""
msgid "There was an error saving your notification settings."
-msgstr ""
+msgstr "알림 ì„¤ì •ì„ ì €ìž¥í•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "There was an error subscribing to this label."
-msgstr ""
+msgstr "ì´ ë¼ë²¨ì„ 구ë…í•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "There was an error when reseting email token."
-msgstr ""
+msgstr "ì´ë©”ì¼ í† í°ì„ ìž¬ì„¤ì •í•˜ë˜ ì¤‘ 오류가 ë°œìƒí•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "There was an error when subscribing to this label."
msgstr ""
@@ -7122,19 +8042,19 @@ msgid "There was an error when unsubscribing from this label."
msgstr ""
msgid "They can be managed using the %{link}."
-msgstr ""
+msgstr "%{link}를 사용하여 관리 할 수 ​​있습니다."
msgid "Third party offers"
msgstr ""
msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
-msgstr ""
+msgstr "ì´ GitLab ì¸ìŠ¤í„´ìŠ¤ëŠ” 공유 Runnersê°€ 제공ë˜ì§€ 않습니다. ì¸ìŠ¤í„´ìŠ¤ 관리ìžëŠ” 관리 ì˜ì—­ì— 공유 Runners를 ë“±ë¡ í•  수 있습니다."
msgid "This application was created by %{link_to_owner}."
msgstr ""
msgid "This application will be able to:"
-msgstr ""
+msgstr "ì´ ì‘ìš© í”„ë¡œê·¸ëž¨ì€ ë‹¤ìŒì„ 수행 í•  수 있습니다."
msgid "This board's scope is reduced"
msgstr ""
@@ -7142,35 +8062,41 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
msgstr ""
msgid "This directory"
-msgstr ""
+msgstr "ì´ ë””ë ‰í† ë¦¬"
msgid "This group"
-msgstr ""
+msgstr "ì´ ê·¸ë£¹"
msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
msgstr ""
msgid "This group does not provide any group Runners yet."
-msgstr ""
+msgstr "ì´ ê·¸ë£¹ì€ ì•„ì§ ê·¸ë£¹ Runners를 제공하지 않습니다."
msgid "This is a confidential issue."
msgstr "비밀 ì´ìŠˆìž…니다."
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr "ì´ ì €ìžì˜ ì´ í”„ë¡œì íŠ¸ì— 대한 첫번째 머지 리퀘스트(MR) 입니다."
msgid "This issue is confidential"
-msgstr ""
+msgstr "ì´ ì´ìŠˆëŠ” 비밀입니다."
msgid "This issue is confidential and locked."
msgstr "ì´ ì´ìŠˆëŠ” confidential ì´ê³  잠금 ìƒíƒœìž…니다."
@@ -7182,22 +8108,22 @@ msgid "This job depends on a user to trigger its process. Often they are used to
msgstr ""
msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
-msgstr ""
+msgstr "ì´ ìž‘ì—…ì„ ì‹œìž‘í•˜ë ¤ë©´ ì—… 스트림 ìž‘ì—…ì˜ ì„±ê³µì„ í•„ìš”ë¡œ 합니다."
msgid "This job does not have a trace."
msgstr ""
msgid "This job has been canceled"
-msgstr ""
+msgstr "ì´ ìž‘ì—…ì€ ì·¨ì†Œë˜ì—ˆìŠµë‹ˆë‹¤"
msgid "This job has been skipped"
-msgstr ""
+msgstr "ì´ ìž‘ì—…ì„ ê±´ë„ˆë›°ì—ˆìŠµë‹ˆë‹¤"
msgid "This job has not been triggered yet"
-msgstr ""
+msgstr "ì´ ìž‘ì—…ì€ ì•„ì§ ì‹¤í–‰ë˜ì§€ 않았습니다."
msgid "This job has not started yet"
-msgstr ""
+msgstr "ì´ ìž‘ì—…ì€ ì•„ì§ ì‹œìž‘ë˜ì§€ 않았습니다."
msgid "This job is an out-of-date deployment to %{environmentLink}."
msgstr ""
@@ -7205,7 +8131,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7221,9 +8150,12 @@ msgid "This job is stuck, because you don't have any active runners that can run
msgstr ""
msgid "This job is the most recent deployment to %{link}."
-msgstr ""
+msgstr "ì´ ìž‘ì—…ì€ %{link}ì— ëŒ€í•œ 가장 ìµœê·¼ì˜ ë°°í¬ìž…니다."
msgid "This job requires a manual action"
+msgstr "ì´ ìž‘ì—…ì—는 ìˆ˜ë™ ìž‘ì—…ì´ í•„ìš”í•©ë‹ˆë‹¤."
+
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
@@ -7242,14 +8174,17 @@ msgid "This page is unavailable because you are not allowed to read information
msgstr ""
msgid "This page will be removed in a future release."
-msgstr ""
+msgstr "ì´ íŽ˜ì´ì§€ëŠ” 앞으로 릴리스ì—ì„œ ì œê±°ë  ì˜ˆì •ìž…ë‹ˆë‹¤."
msgid "This project"
-msgstr ""
+msgstr "ì´ í”„ë¡œì íŠ¸"
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7259,6 +8194,12 @@ msgstr "ì´ ì €ìž¥ì†Œ"
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7266,7 +8207,7 @@ msgid "This timeout will take precedence when lower than Project-defined timeout
msgstr ""
msgid "This user has no identities"
-msgstr ""
+msgstr "ì´ ì‚¬ìš©ìžëŠ” ì‹ ì›ì´ 없습니다."
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
msgstr ""
@@ -7286,20 +8227,26 @@ msgstr "ì´ìŠˆê°€ 스케줄ë˜ê¸° ì „ì˜ ì‹œê°„"
msgid "Time before an issue starts implementation"
msgstr "ì´ìŠˆê°€ 구현ë˜ê¸° ì „ì˜ ì‹œê°„"
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr "머지 리퀘스트(MR) ìƒì„±ê³¼ 머지 / 닫기 사ì´ì˜ 시간"
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
msgid "Time remaining"
-msgstr ""
+msgstr "ë‚¨ì€ ì‹œê°„"
msgid "Time spent"
-msgstr ""
+msgstr "소요 시간"
msgid "Time tracking"
-msgstr ""
+msgstr "시간 추ì "
msgid "Time until first merge request"
msgstr "첫 번째 머지 리퀘스트(MR)ê¹Œì§€ì˜ ì‹œê°„"
@@ -7320,7 +8267,7 @@ msgid "Timeago|%s days remaining"
msgstr "%s ì¼ ë‚¨ìŒ"
msgid "Timeago|%s hours ago"
-msgstr ""
+msgstr "%s시간 전"
msgid "Timeago|%s hours remaining"
msgstr "%s 시간 남ìŒ"
@@ -7338,7 +8285,7 @@ msgid "Timeago|%s months remaining"
msgstr "%s 개월 남ìŒ"
msgid "Timeago|%s seconds ago"
-msgstr ""
+msgstr "%sì´ˆ ì „"
msgid "Timeago|%s seconds remaining"
msgstr "%s ì´ˆ 남ìŒ"
@@ -7356,37 +8303,37 @@ msgid "Timeago|%s years remaining"
msgstr "%s ë…„ 남ìŒ"
msgid "Timeago|1 day ago"
-msgstr ""
+msgstr "1ì¼ ì „"
msgid "Timeago|1 day remaining"
msgstr "1 ì¼ ë‚¨ìŒ"
msgid "Timeago|1 hour ago"
-msgstr ""
+msgstr "1시간 전"
msgid "Timeago|1 hour remaining"
msgstr "1 시간 남ìŒ"
msgid "Timeago|1 minute ago"
-msgstr ""
+msgstr "1분 전"
msgid "Timeago|1 minute remaining"
msgstr "1 분 남ìŒ"
msgid "Timeago|1 month ago"
-msgstr ""
+msgstr "1달 전"
msgid "Timeago|1 month remaining"
msgstr "1 개월 남ìŒ"
msgid "Timeago|1 week ago"
-msgstr ""
+msgstr "1주 전"
msgid "Timeago|1 week remaining"
msgstr "1 주 남ìŒ"
msgid "Timeago|1 year ago"
-msgstr ""
+msgstr "1ë…„ ì „"
msgid "Timeago|1 year remaining"
msgstr "1 ë…„ 남ìŒ"
@@ -7434,13 +8381,13 @@ msgid "Timeago|in 1 year"
msgstr "1 ë…„ ì´ë‚´"
msgid "Timeago|just now"
-msgstr ""
+msgstr "방금 전"
msgid "Timeago|right now"
-msgstr ""
+msgstr "지금"
msgid "Timeout"
-msgstr ""
+msgstr "시간 초과"
msgid "Time|hr"
msgid_plural "Time|hrs"
@@ -7454,22 +8401,22 @@ msgid "Time|s"
msgstr "ì´ˆ"
msgid "Tip:"
-msgstr ""
+msgstr "íŒ:"
msgid "Title"
-msgstr ""
+msgstr "제목"
msgid "To GitLab"
-msgstr ""
+msgstr "GitLab으로"
msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
msgstr ""
msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
-msgstr ""
+msgstr "GitHub 저장소 ì—°ê²°í• ë•Œ, %{personal_access_token_link}ì„ ì‚¬ìš©í•  수 있습니다. ê°œì¸ ì—‘ì„¸ìŠ¤ 토í°ì„ ìƒì„±í• ë•Œ <code>repo</code> scope를 ì„ íƒí•´ì•¼ ì—°ê²°ì— ì‚¬ìš©í•  수 있는 공개, 비공개 저장소가 표시ë˜ì–´ ì—°ê²°í•  수 있게 ë©ë‹ˆë‹¤."
msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
-msgstr ""
+msgstr "GitHub ì €ìž¥ì†Œì— ì—°ê²°í•˜ë ¤ë©´, 먼저 GitHub 저장소 목ë¡ì„ 액세스 í•  수 있ë„ë¡ GitLabì— ì—‘ì„¸ìŠ¤ ê¶Œí•œì„ ë¶€ì—¬í•´ì•¼í•©ë‹ˆë‹¤:"
msgid "To connect an SVN repository, check out %{svn_link}."
msgstr ""
@@ -7477,20 +8424,32 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr "GitLabê³¼ ì‚¬ìš©ìž ê²½í—˜ì„ í–¥ìƒì‹œí‚¤ê¸° 위해 GitLabì€ ì£¼ê¸°ì ìœ¼ë¡œ 사용 정보를 수집합니다."
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr "GitLabì„ ê°œì„ í•˜ëŠ”ë° ë„ì›€ì´ ë˜ë„ë¡ ì£¼ê¸°ì ìœ¼ë¡œ 사용 정보를 수집합니다. ì´ ì„¤ì •ì€ ì–¸ì œë“ ì§€ %{settings_link_start}설정%{link_end}ì—ì„œ 변경할 수 있습니다. %{info_link_start}ë” ë§Žì€ ì •ë³´%{link_end}"
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
-msgstr ""
+msgstr "GitHub저장소ì—ì„œ 가져오려면, %{personal_access_token_link} (ì„) 를 사용할 수 있습니다. ê°œì¸ ì•¡ì„¸ìŠ¤ 토í°ì„ ìƒì„±í•  ë•Œ, <code>저장소</code> 범위를 ì„ íƒí•´ì•¼ 가져오기가 가능한 공개, 비공개 저장소를 표시할 수 있습니다."
msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
-msgstr ""
+msgstr "GitHub 저장소를 가져오려면, 먼저 GitHub 저장소 목ë¡ì„ 액세스 í•  수 있ë„ë¡ GitLabì— ì—‘ì„¸ìŠ¤ ê¶Œí•œì„ ë¶€ì—¬í•´ì•¼í•©ë‹ˆë‹¤:"
msgid "To import an SVN repository, check out %{svn_link}."
-msgstr ""
+msgstr "SVN 저장소ì—ì„œ 가져오려면, %{svn_link}(ì„)를 확ì¸í•˜ì„¸ìš”."
msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
msgstr ""
@@ -7498,6 +8457,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7505,29 +8467,38 @@ msgid "To start serving your jobs you can add Runners to your group"
msgstr ""
msgid "To this GitLab instance"
-msgstr ""
+msgstr "ì´ GitLab ì¸ìŠ¤í„´ìŠ¤ë¡œ"
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
-msgstr ""
+msgstr "GitLab CI êµ¬ì„±ì„ ê²€ì¦í•˜ë ¤ë©´ 프로ì íŠ¸ ë‚´ë¶€ì˜ 'CI/CD → 파ì´í”„ë¼ì¸'으로 ì´ë™í•˜ì—¬ 'CI Lint' ë²„íŠ¼ì„ í´ë¦­í•˜ì‹­ì‹œì˜¤."
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
-msgid "Todo"
+msgid "Today"
msgstr ""
+msgid "Todo"
+msgstr "Todo"
+
msgid "Todos"
-msgstr ""
+msgstr "í• ì¼ë“¤"
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7541,6 +8512,9 @@ msgid "ToggleButton|Toggle Status: ON"
msgstr "토글 ìƒíƒœ: ON"
msgid "Token"
+msgstr "토í°"
+
+msgid "Tomorrow"
msgstr ""
msgid "Too many changes to show."
@@ -7556,6 +8530,9 @@ msgid "Total test time for all commits/merges"
msgstr "모든 커밋 / ë¨¸ì§€ì˜ ì´ í…ŒìŠ¤íŠ¸ 시간"
msgid "Total: %{total}"
+msgstr "합계: %{total}"
+
+msgid "Tracing"
msgstr ""
msgid "Track activity with Contribution Analytics."
@@ -7567,9 +8544,12 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
-msgid "Trending"
+msgid "Tree view"
msgstr ""
+msgid "Trending"
+msgstr "ì¸ê¸°"
+
msgid "Trigger"
msgstr ""
@@ -7580,18 +8560,27 @@ msgid "Trigger pipelines when branches or tags are updated from the upstream rep
msgstr ""
msgid "Trigger this manual action"
-msgstr ""
+msgstr "수ë™ìœ¼ë¡œ 실행해주세요."
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
+msgstr "다시 ì‹œë„하십시오"
+
+msgid "Try all GitLab has to offer for 30 days."
msgstr ""
msgid "Turn on Service Desk"
-msgstr ""
+msgstr "서비스 ë°ìŠ¤í¬ 켜기"
msgid "Twitter"
+msgstr "Twitter"
+
+msgid "Two-factor authentication"
msgstr ""
msgid "Type"
@@ -7600,74 +8589,92 @@ msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr "실행 취소"
+
msgid "Unknown"
msgstr ""
msgid "Unlock"
-msgstr ""
+msgstr "잠금 해제"
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
msgstr ""
msgid "Unlocked"
-msgstr ""
+msgstr "잠금 í•´ì œë¨"
msgid "Unresolve discussion"
+msgstr "í•´ê²°ë˜ì§€ ì•Šì€ í† ë¡ "
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
msgstr ""
msgid "Unstage all changes"
msgstr ""
msgid "Unstage changes"
-msgstr ""
+msgstr "스테ì´ì§•ë˜ì§€ ì•Šì€ ë³€ê²½ì "
msgid "Unstaged"
-msgstr ""
+msgstr "스테ì´ì§• 안ë¨"
msgid "Unstaged %{type}"
-msgstr ""
+msgstr "%{type} 스테ì´ì§• 취소"
msgid "Unstaged and staged %{type}"
-msgstr ""
+msgstr "스테ì´ì§• 취소, 그리고 %{type} 스테ì´ì§•"
msgid "Unstar"
msgstr "별표 제거"
msgid "Unsubscribe"
-msgstr ""
+msgstr "êµ¬ë… ì·¨ì†Œ"
msgid "Unsubscribe at group level"
-msgstr ""
+msgstr "그룹 수준ì—ì„œ êµ¬ë… í•´ì œ"
msgid "Unsubscribe at project level"
-msgstr ""
+msgstr "프로ì íŠ¸ 수준ì—ì„œ êµ¬ë… í•´ì œ"
msgid "Unverified"
-msgstr ""
+msgstr "ê²€ì¦ë˜ì§€ ì•ŠìŒ"
msgid "Up to date"
msgstr "최신 ìƒíƒœìž…니다"
-msgid "Update"
+msgid "Upcoming"
msgstr ""
+msgid "Update"
+msgstr "ì—…ë°ì´íŠ¸"
+
msgid "Update now"
-msgstr ""
+msgstr "지금 ì—…ë°ì´íŠ¸"
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
-msgstr ""
+msgstr "ì—…ë°ì´íŠ¸ì¤‘..."
msgid "Upgrade your plan to activate Advanced Global Search."
-msgstr ""
+msgstr "고급 글로벌 ê²€ìƒ‰ì„ í™œì„±í™”í•˜ê¸° 위해 í”Œëžœì„ ì—…ê·¸ë ˆì´ë“œí•˜ì„¸ìš”."
msgid "Upgrade your plan to activate Contribution Analytics."
-msgstr ""
+msgstr "ì°¸ì—¬ë„ ë¶„ì„ì„ í™œì„±í™”í•˜ê¸° 위해 í”Œëžœì„ ì—…ê·¸ë ˆì´ë“œí•˜ì„¸ìš”."
msgid "Upgrade your plan to activate Group Webhooks."
msgstr ""
@@ -7687,17 +8694,17 @@ msgstr "새 íŒŒì¼ ì—…ë¡œë“œ"
msgid "Upload file"
msgstr "íŒŒì¼ ì—…ë¡œë“œ"
-msgid "Upload new avatar"
-msgstr "새 아바타 업로드"
-
msgid "UploadLink|click to upload"
msgstr "업로드하려면 í´ë¦­í•˜ì‹­ì‹œì˜¤."
msgid "Upvotes"
+msgstr "추천"
+
+msgid "Usage ping is not enabled"
msgstr ""
msgid "Usage statistics"
-msgstr ""
+msgstr "사용 통계"
msgid "Use <code>%{native_redirect_uri}</code> for local tests"
msgstr ""
@@ -7712,7 +8719,7 @@ msgid "Use one line per URI"
msgstr ""
msgid "Use template"
-msgstr ""
+msgstr "템플릿 사용"
msgid "Use the following registration token during setup:"
msgstr "설정 ì¤‘ì— ë‹¤ìŒ ë“±ë¡ í† í° ì´ìš© : "
@@ -7723,81 +8730,141 @@ msgstr "전체 알림 설정 사용"
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
-msgid "User Settings"
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
msgstr ""
+msgid "User Settings"
+msgstr "ì‚¬ìš©ìž ì„¤ì •"
+
msgid "User and IP Rate Limits"
-msgstr ""
+msgstr "ì‚¬ìš©ìž ë° IP ì†ë„ 제한"
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|Already reported for abuse"
msgstr ""
-msgid "Variables"
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
msgstr ""
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
+msgstr "사용ìžë“¤"
+
+msgid "Variables"
+msgstr "변수"
+
msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
msgstr "변수는 runner를 통해 í™˜ê²½ì— ì ìš©ë©ë‹ˆë‹¤. 변수는 ë³´í˜¸ëœ ë¸Œëžœì¹˜ë‚˜ 태그ì—만 노출하여 보호할 수 있습니다. 비밀번호, 암호키, ë˜ëŠ” ì›í•˜ëŠ”대로 변수를 사용할 수 있습니다."
msgid "Various container registry settings."
-msgstr ""
+msgstr "여러가지 컨테ì´ë„ˆ 레지스트리 설정."
msgid "Various email settings."
-msgstr ""
+msgstr "여러가지 ì´ë©”ì¼ ì„¤ì •."
msgid "Various settings that affect GitLab performance."
-msgstr ""
+msgstr "GitLab ì„±ëŠ¥ì— ì˜í–¥ì„ 주는 여러가지 설정."
msgid "Verification information"
-msgstr ""
+msgstr "ì¸ì¦ ì •ë³´"
msgid "Verified"
-msgstr ""
+msgstr "ê²€ì¦ë¨"
msgid "Version"
+msgstr "버전"
+
+msgid "View %{alerts}"
msgstr ""
-msgid "View epics list"
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
msgstr ""
+msgid "View epics list"
+msgstr "ì—픽 ëª©ë¡ ë³´ê¸°"
+
msgid "View file @ "
msgstr ""
msgid "View group labels"
-msgstr ""
+msgstr "그룹 ë¼ë²¨ 보기"
msgid "View issue"
-msgstr ""
+msgstr "ì´ìŠˆ 보기"
msgid "View it on GitLab"
-msgstr ""
+msgstr "GitLabì—ì„œ 보기"
msgid "View jobs"
-msgstr ""
+msgstr "작업 보기"
msgid "View labels"
msgstr "ë¼ë²¨ë³´ê¸°"
msgid "View log"
-msgstr ""
+msgstr "로그 보기"
msgid "View open merge request"
msgstr "열린 머지 리퀘스트(MR)보기"
msgid "View project labels"
-msgstr ""
+msgstr "프로ì íŠ¸ ë¼ë²¨ 보기"
msgid "View replaced file @ "
msgstr "êµì²´ëœ íŒŒì¼ ë³´ê¸° @ "
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7816,29 +8883,59 @@ msgstr "Public"
msgid "VisibilityLevel|Unknown"
msgstr "ì•Œ 수 ì—†ìŒ"
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "ì´ ë°ì´í„°ë¥¼ ë³´ê³  싶ì€ê°€ìš”? 관리ìžì—게 액세스 ê¶Œí•œì„ ìš”ì²­í•˜ì„¸ìš”."
msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
-msgstr ""
+msgstr "%{humanized_resource_name}ì—ì„œ 잠재ì ì¸ ìŠ¤íŒ¸ì„ íƒì§€í–ˆìŠµë‹ˆë‹¤. 계ì†í•˜ë ¤ë©´ reCAPTCHA를 진행하세요."
msgid "We don't have enough data to show this stage."
msgstr "ì´ ë‹¨ê³„ë¥¼ ë³´ì—¬ì£¼ê¸°ì— ì¶©ë¶„í•œ ë°ì´í„°ê°€ 없습니다."
msgid "We want to be sure it is you, please confirm you are not a robot."
-msgstr ""
+msgstr "ì •ë§ ë‹¹ì‹ ì´ ë§žëŠ”ì§€ 확ì¸í•˜ê³  싶습니다, ë‹¹ì‹ ì´ ë¡œë´‡ì´ ì•„ë‹ˆë¼ëŠ” ê²ƒì„ í™•ì¸í•´ì£¼ì‹­ì‹œì˜¤."
msgid "Web IDE"
-msgstr ""
+msgstr "웹 IDE"
msgid "Web terminal"
-msgstr ""
+msgstr "웹 터미ë„"
msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
msgstr ""
msgid "Weeks"
-msgstr ""
+msgstr "주"
msgid "Weight"
msgstr ""
@@ -7847,14 +8944,20 @@ msgid "Weight %{weight}"
msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
-msgstr ""
+msgstr "Runnerê°€ 잠겨 있으면 다른 프로ì íŠ¸ì— 할당 í•  수 없습니다"
msgid "When enabled, users cannot use GitLab until the terms have been accepted."
-msgstr ""
+msgstr "사용 설정ë˜ë©´ 사용ìžëŠ” GitLab ì•½ê´€ì´ ìˆ˜ë½ ë  ë•Œê¹Œì§€ GitLabì„ ì‚¬ìš©í•  수 없습니다."
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr "위키"
@@ -7874,10 +8977,10 @@ msgid "WikiClone|Start Gollum and edit locally"
msgstr "Gollumì„ ì‹œìž‘í•˜ê³  로컬 편집"
msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
-msgstr ""
+msgstr "íŒ: ì œëª©ì˜ ì‹œìž‘ ë¶€ë¶„ì— ê²½ë¡œë¥¼ ì¶”ê°€í•˜ì—¬ì´ íŽ˜ì´ì§€ë¥¼ ì´ë™í•  수 있습니다."
msgid "WikiEdit|There is already a page with the same title in that path."
-msgstr ""
+msgstr "ì œëª©ì˜ ê²½ë¡œì™€ ê°™ì€ ê³³ì— íŽ˜ì´ì§€ê°€ ì´ë¯¸ 존재합니다."
msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
msgstr ""
@@ -7892,7 +8995,7 @@ msgid "WikiEmpty|A wiki is where you can store all the details about your projec
msgstr ""
msgid "WikiEmpty|Create your first page"
-msgstr ""
+msgstr "첫 번째 페ì´ì§€ ìƒì„±í•˜ê¸°"
msgid "WikiEmpty|Suggest wiki improvement"
msgstr ""
@@ -7919,13 +9022,13 @@ msgid "WikiHistoricalPage|most recent version"
msgstr "최신 버전"
msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
-msgstr "ë” ë§Žì€ ì˜ˆì œëŠ” %{docs_link}"
+msgstr "ë” ë§Žì€ ì˜ˆì œëŠ” %{docs_link}를 확ì¸í•˜ì„¸ìš”."
msgid "WikiMarkdownDocs|documentation"
msgstr "문서"
msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
-msgstr "(새로운) 페ì´ì§€ì— ì—°ê²° 하려면, %{link_example} ë§í¬ë¥¼ 입력하세요."
+msgstr "(새로운) 페ì´ì§€ì— ì—°ê²° 하려면, %{link_example}를 입력하세요"
msgid "WikiNewPagePlaceholder|how-to-setup"
msgstr "설정 방법"
@@ -7940,7 +9043,7 @@ msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
msgstr "ì´ íŽ˜ì´ì§€ë¥¼ 삭제하시겠습니까?"
msgid "WikiPageConfirmDelete|Delete page"
-msgstr ""
+msgstr "페ì´ì§€ ì‚­ì œ"
msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
msgstr ""
@@ -7997,12 +9100,15 @@ msgid "Withdraw Access Request"
msgstr "액세스 요청 철회"
msgid "Yes"
-msgstr ""
+msgstr "예"
msgid "Yes, add it"
-msgstr ""
+msgstr "네, 추가합니다."
msgid "Yes, let me map Google Code users to full names or GitLab users."
+msgstr "네, Google code 사용ìžë¥¼ ì´ë¦„ì´ë‚˜ GitLab 사용ìžì— 연결하겠습니다."
+
+msgid "Yesterday"
msgstr ""
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
@@ -8012,31 +9118,25 @@ msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored!
msgstr "%{group_name} ê·¸ë£¹ì„ ì œê±°í•˜ë ¤ê³ í•©ë‹ˆë‹¤. \\\"ì •ë§ë¡œ\\\" 확실합니까?"
msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "%{project_full_name} 프로ì íŠ¸ë¥¼ 삭제하려고 합니다. ì‚­ì œëœ í”„ë¡œì íŠ¸ëŠ” \"절대로\" 복구할 수 없습니다! \"ì •ë§ë¡œ\" 확실합니까?"
msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
msgstr "í¬í¬ 관계를 소스 프로ì íŠ¸ %{forked_from_project}ì— ëŒ€í•´ 제거하려고합니다. \"ì •ë§ë¡œ\" 확실합니까?"
msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
-msgstr ""
+msgstr "%{project_full_name} (ì„) 를 다른 소유ìžì—게 ì´ì „하려고합니다. \"ì •ë§ë¡œ\" 확실합니까?"
msgid "You are on a read-only GitLab instance."
-msgstr ""
-
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
+msgstr "ì½ê¸°ì „ìš© GitLab ì¸ìŠ¤í„´ìŠ¤ë¥¼ 사용중입니다."
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
msgid "You can also create a project from the command line."
-msgstr ""
+msgstr "ëª…ë ¹ì¤„ì„ í†µí•´ 프로ì íŠ¸ë¥¼ ìƒì„±í•  수 있습니다."
msgid "You can also star a label to make it a priority label."
-msgstr ""
-
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
+msgstr "ë¼ë²¨ì— 별표를 붙여 우선순위 ë¼ë²¨ì„ 만들 ìˆ˜ë„ ìžˆìŠµë‹ˆë‹¤."
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8045,13 +9145,13 @@ msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_p
msgstr "Kubernetes í´ëŸ¬ìŠ¤í„°ì— Runner를 쉽게 설치할 수 있습니다. %{link_to_help_page}"
msgid "You can move around the graph by using the arrow keys."
-msgstr ""
+msgstr "화살표 키를 사용하여 그래프를 움ì§ì¼ 수 있습니다."
msgid "You can only add files when you are on a branch"
msgstr "ë¸Œëžœì¹˜ì— ìžˆì„ ë•Œì—만 파ì¼ì„ 추가 í•  수 있습니다."
msgid "You can only edit files when you are on a branch"
-msgstr ""
+msgstr "ë¸Œëžœì¹˜ì— ìžˆì„ ë•Œë§Œ 파ì¼ì„ 편집할 수 있습니다."
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr ""
@@ -8059,35 +9159,38 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr "ì½ê¸° ì „ìš© GitLab ì¸ìŠ¤í„´ìŠ¤ì—는 쓰기가 불가능합니다."
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
msgid "You don't have any applications"
-msgstr ""
+msgstr "ë‹¹ì‹ ì€ ì• í”Œë¦¬ì¼€ì´ì…˜ì„ 가지고 있지 않습니다."
msgid "You don't have any authorized applications"
-msgstr ""
+msgstr "ìŠ¹ì¸ ëœ ì• í”Œë¦¬ì¼€ì´ì…˜ì´ 없습니다."
msgid "You have no permissions"
-msgstr ""
+msgstr "ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤."
msgid "You have reached your project limit"
msgstr "프로ì íŠ¸ ìˆ«ìž í•œë„ì— ë„달했습니다."
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
-msgstr ""
+msgstr "ê³„ì •ì„ ë“±ë¡í•˜ë ¤ë©´ 서비스 약관 ë° ê°œì¸ ì •ë³´ 취급 ë°©ì¹¨ì— ë™ì˜í•´ì•¼í•©ë‹ˆë‹¤."
msgid "You must have maintainer access to force delete a lock"
-msgstr ""
-
-msgid "You must sign in to star a project"
-msgstr "프로ì íŠ¸ì— 별표를 표시하려면 ë¡œê·¸ì¸ í•´ì•¼ 합니다."
+msgstr "강제로 ìž ê¸ˆì„ ì œê±°í•˜ë ¤ë©´ ê´€ë¦¬ìž ê¶Œí•œì´ ìžˆì–´ì•¼í•©ë‹ˆë‹¤."
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8098,6 +9201,12 @@ msgstr ""
msgid "You need permission."
msgstr "ê¶Œí•œì´ í•„ìš”í•©ë‹ˆë‹¤."
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr "ì´ë©”ì¼ë¡œ ì•Œë¦¼ì„ ë°›ì§€ 않습니다."
@@ -8120,10 +9229,10 @@ msgid "You won't be able to pull or push project code via SSH until you %{add_ss
msgstr "ë‹¹ì‹ ì˜ í”„ë¡œí•„ì— %{add_ssh_key_link} 를 하기 ì „ì—는 SSH를 통해 프로ì íŠ¸ 코드를 Pull 하거나 Push í•  수 없습니다"
msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
-msgstr ""
+msgstr "ë‹¹ì‹ ì˜ í”„ë¡œí•„ì— SSH 키를 등ë¡í•˜ê¸° 전까지 SSH를 통해 프로ì íŠ¸ë¥¼ 가져오거나 푸시할 수 없습니다."
msgid "You'll need to use different branch names to get a valid comparison."
-msgstr ""
+msgstr "올바른 ë³€ê²½ì‚¬í•­ì„ ê°€ì ¸ì˜¤ë ¤ë©´ 다른 ì´ë¦„ì˜ ë¸Œëžœì¹˜ë¥¼ 사용해야합니다."
msgid "You're receiving this email because %{reason}."
msgstr ""
@@ -8132,36 +9241,39 @@ msgid "You're receiving this email because of your account on %{host}."
msgstr ""
msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
-msgstr ""
+msgstr "ì´ ì´ë©”ì¼ì„ 받는 ì´ìœ ëŠ” 사용ìžì˜ ê³„ì •ì´ %{host}ì— ìžˆê¸° 때문입니다. %{manage_notifications_link}&middot;%{help_link}"
msgid "YouTube"
-msgstr ""
+msgstr "YouTube"
msgid "Your Groups"
-msgstr ""
+msgstr "ë‹¹ì‹ ì˜ ê·¸ë£¹"
msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
-msgstr ""
+msgstr "ì´ íŽ˜ì´ì§€ì—ì„œ Kubernetes í´ëŸ¬ìŠ¤í„° 정보를 계ì†í•´ì„œ 편집할 수 있지만, 비활성화 하거나 재설정하는 ê²ƒì´ ì¢‹ìŠµë‹ˆë‹¤."
msgid "Your Projects (default)"
-msgstr ""
+msgstr "ë‹¹ì‹ ì˜ í”„ë¡œì íŠ¸ (기본값)"
msgid "Your Projects' Activity"
-msgstr ""
+msgstr "ë‹¹ì‹ ì˜ í”„ë¡œì íŠ¸ 활ë™"
msgid "Your Todos"
-msgstr ""
+msgstr "ë‹¹ì‹ ì˜ í• ì¼"
msgid "Your applications (%{size})"
-msgstr ""
+msgstr "승ì¸ëœ 애플리케ì´ì…˜ (%{size})"
msgid "Your authorized applications"
-msgstr ""
+msgstr "승ì¸ëœ 애플리케ì´ì…˜"
msgid "Your changes can be committed to %{branch_name} because a merge request is open."
-msgstr ""
+msgstr "머지 리퀘스트(MR)ê°€ 열려있기 ë•Œë¬¸ì— ë³€ê²½ì‚¬í•­ì€ %{branch_name}(으)ë¡œ ì»¤ë°‹ë  ìˆ˜ 있습니다."
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr "ë³€ê²½ì‚¬í•­ì´ ì»¤ë°‹ë˜ì—ˆìŠµë‹ˆë‹¤. 커밋 %{commitId} %{commitStats}"
+
+msgid "Your changes have been saved"
msgstr ""
msgid "Your comment will not be visible to the public."
@@ -8174,33 +9286,25 @@ msgid "Your name"
msgstr "ê·€í•˜ì˜ ì´ë¦„"
msgid "Your projects"
-msgstr ""
+msgstr "ë‚´ 프로ì íŠ¸"
msgid "a deleted user"
-msgstr ""
+msgstr "ì‚­ì œëœ ì‚¬ìš©ìž"
msgid "ago"
-msgstr ""
+msgstr "ì „"
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-
msgid "assign yourself"
msgstr "ìžì‹ ì„ 담당ìžë¡œ 지정"
msgid "branch name"
-msgstr ""
+msgstr "브랜치 ì´ë¦„"
msgid "by"
-msgstr ""
+msgstr "by"
msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
msgstr ""
@@ -8220,65 +9324,78 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
-msgstr ""
+msgstr "설명"
msgid "ciReport|Dismiss vulnerability"
msgstr ""
@@ -8307,9 +9424,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8330,6 +9444,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8348,13 +9465,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8363,9 +9474,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8396,9 +9504,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8409,14 +9514,11 @@ msgstr[0] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
msgid "command line instructions"
-msgstr ""
+msgstr "명령줄 지침"
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
msgstr ""
@@ -8425,10 +9527,10 @@ msgid "confidentiality|You are going to turn on the confidentiality. This means
msgstr ""
msgid "connecting"
-msgstr ""
+msgstr "연결중"
msgid "could not read private key, is the passphrase correct?"
-msgstr ""
+msgstr "ê°œì¸ í‚¤ë¥¼ ì½ì„ 수 없습니다. 암호가 맞습니까?"
msgid "customize"
msgstr ""
@@ -8438,27 +9540,20 @@ msgid_plural "days"
msgstr[0] "ì¼"
msgid "deploy token"
-msgstr ""
-
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
+msgstr "ë°°í¬ í† í°"
msgid "disabled"
-msgstr ""
+msgstr "사용 안 함"
msgid "done"
-msgstr ""
+msgstr "완료"
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
msgid "enabled"
-msgstr ""
+msgstr "사용"
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
@@ -8466,17 +9561,23 @@ msgstr ""
msgid "for this project"
msgstr ""
-msgid "here"
+msgid "from"
msgstr ""
-msgid "https://your-bitbucket-server"
+msgid "help"
msgstr ""
+msgid "here"
+msgstr "여기"
+
+msgid "https://your-bitbucket-server"
+msgstr "https://나ì˜-bitbucket-server"
+
msgid "import flow"
msgstr ""
msgid "importing"
-msgstr ""
+msgstr "가져오는중"
msgid "instance completed"
msgid_plural "instances completed"
@@ -8489,35 +9590,38 @@ msgid "is invalid because there is upstream lock"
msgstr ""
msgid "is not a valid X509 certificate."
-msgstr ""
+msgstr "올바른 X509 ì¸ì¦ì„œê°€ 아닙니다."
msgid "issue boards"
+msgstr "ì´ìŠˆ ë³´ë“œ"
+
+msgid "latest deployment"
msgstr ""
msgid "latest version"
-msgstr ""
+msgstr "최신 버전"
msgid "license management"
-msgstr ""
+msgstr "ë¼ì´ì„ ìŠ¤ 관리"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr ""
msgid "merge request"
msgid_plural "merge requests"
-msgstr[0] ""
+msgstr[0] "머지 리퀘스트(MR)"
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
-msgstr ""
+msgstr "브랜치를 ë³µì›í•˜ê±°ë‚˜ 다른 %{missingBranchName} 브랜치를 사용해주세요."
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
-msgstr ""
+msgstr "%{metricsLinkStart} 메모리 사용률 %{metricsLinkEnd} ì´ %{memoryFrom}MB ì—ì„œ %{memoryTo}MB ë¡œ %{emphasisStart} ê°ì†Œí•˜ì˜€ìŠµë‹ˆë‹¤. %{emphasisEnd}"
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
-msgstr ""
+msgstr "%{metricsLinkStart} 메모리 사용률 %{metricsLinkEnd} ì´ %{memoryFrom}MB ì—ì„œ %{memoryTo}MB ë¡œ %{emphasisStart} ì¦ê°€í•˜ì˜€ìŠµë‹ˆë‹¤. %{emphasisEnd}"
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
-msgstr ""
+msgstr "%{metricsLinkStart} 메모리 사용률 %{metricsLinkEnd} ì´ %{memoryFrom}MB ì—ì„œ %{emphasisStart} 변하지 않았습니다. %{emphasisEnd}"
msgid "mrWidget|Add approval"
msgstr ""
@@ -8541,67 +9645,67 @@ msgid "mrWidget|Approved by"
msgstr ""
msgid "mrWidget|Cancel automatic merge"
-msgstr ""
+msgstr "ìžë™ 머지 취소"
msgid "mrWidget|Check out branch"
-msgstr ""
+msgstr "브랜치 ì²´í¬ì•„웃"
msgid "mrWidget|Checking ability to merge automatically"
-msgstr ""
+msgstr "ìžë™ 머지 기능 ì²´í¬"
msgid "mrWidget|Cherry-pick"
-msgstr ""
+msgstr "체리픽"
msgid "mrWidget|Cherry-pick this merge request in a new merge request"
-msgstr ""
+msgstr "새로운 머지 리퀘스트(MR)ì—ì„œ ì´ ë¨¸ì§€ 리퀘스트(MR)으로 체리픽"
msgid "mrWidget|Closed"
-msgstr ""
+msgstr "닫힘"
msgid "mrWidget|Closed by"
-msgstr ""
+msgstr "ë‹«ìŒ:"
msgid "mrWidget|Closes"
-msgstr ""
+msgstr "ë‹«ìŒ"
msgid "mrWidget|Create an issue to resolve them later"
-msgstr ""
+msgstr "ë‚˜ì¤‘ì— í•´ê²°í•  수 있ë„ë¡ ì´ìŠˆë¥¼ 만듭니다"
msgid "mrWidget|Deployment statistics are not available currently"
-msgstr ""
+msgstr "ë°°í¬ í†µê³„ëŠ” ì•„ì§ ì‚¬ìš©í•  수 없습니다."
msgid "mrWidget|Did not close"
-msgstr ""
+msgstr "닫히지 ì•ŠìŒ"
msgid "mrWidget|Email patches"
-msgstr ""
+msgstr "ì´ë©”ì¼ íŒ¨ì¹˜"
msgid "mrWidget|Failed to load deployment statistics"
-msgstr ""
+msgstr "ë°°í¬ í†µê³„ë¥¼ ë¡œë“œí•˜ëŠ”ë° ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
-msgstr "mrWidget %{branch} 브랜치가 로컬 ì €ìž¥ì†Œì— ìžˆìœ¼ë©´ ì´ ë¨¸ì§€ 리퀘스트(MR)를 다ìŒê³¼ ê°™ì´ ìˆ˜ë™ìœ¼ë¡œ 머지할 수 있습니다."
+msgstr ""
msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
-msgstr ""
+msgstr "만약 %{missingBranchName} 브랜치가 ë‹¹ì‹ ì˜ ë¡œì»¬ ì €ìž¥ì†Œì— ì¡´ìž¬í•œë‹¤ë©´, ëª…ë ¹ì¤„ì„ ì‚¬ìš©í•˜ì—¬ 수ë™ìœ¼ë¡œ 머지할 수 있습니다."
msgid "mrWidget|Loading deployment statistics"
-msgstr ""
+msgstr "ë°°í¬ í†µê³„ 로딩중"
msgid "mrWidget|Mentions"
-msgstr ""
+msgstr "멘션"
msgid "mrWidget|Merge"
-msgstr ""
+msgstr "머지"
msgid "mrWidget|Merge failed."
-msgstr ""
+msgstr "머지 실패."
msgid "mrWidget|Merge locally"
-msgstr ""
+msgstr "로컬ì—ì„œ 머지"
msgid "mrWidget|Merge request approved"
msgstr ""
@@ -8610,7 +9714,7 @@ msgid "mrWidget|Merge request approved; you can approve additionally"
msgstr ""
msgid "mrWidget|Merged by"
-msgstr ""
+msgstr "머지:"
msgid "mrWidget|No Approval required"
msgstr ""
@@ -8625,31 +9729,31 @@ msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a
msgstr ""
msgid "mrWidget|Plain diff"
-msgstr ""
+msgstr "Plain diff"
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
msgstr ""
msgid "mrWidget|Refresh"
-msgstr ""
+msgstr "새로고침"
msgid "mrWidget|Refresh now"
-msgstr ""
+msgstr "지금 새로고침"
msgid "mrWidget|Refreshing now"
-msgstr ""
+msgstr "지금 새로고침 중"
msgid "mrWidget|Remove Source Branch"
-msgstr ""
+msgstr "소스 브랜치 삭제"
msgid "mrWidget|Remove source branch"
-msgstr ""
+msgstr "소스 브랜치 삭제"
msgid "mrWidget|Remove your approval"
msgstr ""
msgid "mrWidget|Request to merge"
-msgstr ""
+msgstr "머지 리퀘스트(MR)"
msgid "mrWidget|Requires 1 more approval"
msgid_plural "mrWidget|Requires %d more approvals"
@@ -8660,28 +9764,28 @@ msgid_plural "mrWidget|Requires %d more approvals by"
msgstr[0] ""
msgid "mrWidget|Resolve conflicts"
-msgstr ""
+msgstr "ì¶©ëŒ í•´ê²°"
msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
msgstr ""
msgid "mrWidget|Revert"
-msgstr ""
+msgstr "ë˜ëŒë¦¬ê¸°"
msgid "mrWidget|Revert this merge request in a new merge request"
-msgstr ""
+msgstr "새로운 머지 리퀘스트(MR)ì—ì„œ ì´ ë¨¸ì§€ 리퀘스트(MR)ë¡œ ë˜ëŒë¦¬ê¸°"
msgid "mrWidget|Set by"
-msgstr ""
+msgstr "설정:"
msgid "mrWidget|The changes were merged into"
-msgstr ""
+msgstr "변경 ì‚¬í•­ì´ ë¨¸ì§€ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "mrWidget|The changes were not merged into"
-msgstr ""
+msgstr "변경 ì‚¬í•­ì´ ë¨¸ì§€ë˜ì§€ 않았습니다."
msgid "mrWidget|The changes will be merged into"
-msgstr ""
+msgstr "변경 ì‚¬í•­ì´ ë¨¸ì§€ë  ê²ƒ 입니다."
msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
msgstr ""
@@ -8690,51 +9794,57 @@ msgid "mrWidget|The source branch HEAD has recently changed. Please reload the p
msgstr ""
msgid "mrWidget|The source branch has been removed"
-msgstr ""
+msgstr "소스 브랜치가 제거ë˜ì—ˆìŠµë‹ˆë‹¤."
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
msgstr ""
msgid "mrWidget|The source branch is being removed"
-msgstr ""
+msgstr "소스 브랜치가 제거ë˜ëŠ” 중입니다"
msgid "mrWidget|The source branch will be removed"
-msgstr ""
+msgstr "소스 브랜치가 ì œê±°ë  ê²ƒ 입니다."
msgid "mrWidget|The source branch will not be removed"
-msgstr ""
+msgstr "소스 브랜치가 제거ë˜ì§€ ì•Šì„ ê²ƒ 입니다."
msgid "mrWidget|There are merge conflicts"
-msgstr ""
+msgstr "머지 충ëŒì´ 있습니다."
msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
-msgstr ""
+msgstr "í•´ê²°ë˜ì§€ ì•Šì€ í† ë¡ ì´ ìžˆìŠµë‹ˆë‹¤. ì´ í† ë¡ ì„ í•´ê²°í•˜ì‹­ì‹œì˜¤"
msgid "mrWidget|This merge request failed to be merged automatically"
-msgstr ""
+msgstr "ì´ ë¨¸ì§€ 리퀘스트(MR)를 ìžë™ìœ¼ë¡œ ë¨¸ì§€í•˜ëŠ”ë° ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤."
msgid "mrWidget|This merge request is in the process of being merged"
-msgstr ""
+msgstr "ì´ ë¨¸ì§€ 리퀘스트(MR)를 머지중입니다."
msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr "ì´ í”„ë¡œì íŠ¸ëŠ” ë³´ê´€ë˜ì—ˆê³ , 쓰기 ì ‘ê·¼ì´ ë¹„í™œì„±í™”ë˜ì—ˆìŠµë‹ˆë‹¤."
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
msgstr ""
msgid "mrWidget|You can merge this merge request manually using the"
-msgstr ""
+msgstr "ì´ ë¨¸ì§€ 리퀘스트(MR)를 수ë™ìœ¼ë¡œ 머지할 수 있습니다."
msgid "mrWidget|You can remove source branch now"
-msgstr ""
+msgstr "지금 소스 브랜치를 삭제할 수 있습니다."
msgid "mrWidget|branch does not exist."
-msgstr ""
+msgstr "브랜치가 존재하지 않습니다."
msgid "mrWidget|command line"
-msgstr ""
+msgstr "명령줄"
msgid "mrWidget|into"
-msgstr ""
+msgstr "로"
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr "파ì´í”„ë¼ì¸ì´ 성공하면 ìžë™ìœ¼ë¡œ 머지ë©ë‹ˆë‹¤."
+
+msgid "n/a"
msgstr ""
msgid "new merge request"
@@ -8761,13 +9871,17 @@ msgid "personal access token"
msgstr "ê°œì¸ ì—‘ì„¸ìŠ¤ 토í°"
msgid "private key does not match certificate."
-msgstr ""
+msgstr "ê°œì¸ í‚¤ì™€ ì¸ì¦ì„œê°€ ì¼ì¹˜í•˜ì§€ 않습니다."
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
msgid "remaining"
msgstr ""
msgid "remove"
-msgstr ""
+msgstr "제거"
msgid "remove due date"
msgstr ""
@@ -8775,6 +9889,10 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+
msgid "source"
msgstr "소스"
@@ -8782,14 +9900,17 @@ msgid "spendCommand|%{slash_command} will update the sum of the time spent."
msgstr "%{slash_command} 소요 ëœ ì‹œê°„ì˜ í•©ê³„ë¥¼ ì—…ë°ì´íŠ¸í•©ë‹ˆë‹¤."
msgid "started"
-msgstr ""
+msgstr "시작ë¨"
msgid "this document"
-msgstr ""
+msgstr "ì´ ë¬¸ì„œ"
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr "사용ìžëª…"
@@ -8797,7 +9918,7 @@ msgid "uses Kubernetes clusters to deploy your code!"
msgstr "kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 사용하여 코드를 ë°°í¬í•©ë‹ˆë‹¤!"
msgid "view it on GitLab"
-msgstr ""
+msgstr "GitLabì—ì„œ 보기"
msgid "with %{additions} additions, %{deletions} deletions."
msgstr ""
diff --git a/locale/mn_MN/gitlab.po b/locale/mn_MN/gitlab.po
new file mode 100644
index 00000000000..f6b0a71c3d6
--- /dev/null
+++ b/locale/mn_MN/gitlab.po
@@ -0,0 +1,9995 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
+"Language-Team: Mongolian\n"
+"Language: mn_MN\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: mn\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"PO-Revision-Date: 2018-11-19 17:17\n"
+
+msgid " Status"
+msgstr ""
+
+msgid " and"
+msgstr ""
+
+msgid " degraded on %d point"
+msgid_plural " degraded on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " improved on %d point"
+msgid_plural " improved on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d changed file"
+msgid_plural "%d changed files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d failed test result"
+msgid_plural "%d failed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d staged change"
+msgid_plural "%d staged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unstaged change"
+msgid_plural "%d unstaged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_timeago}"
+msgstr ""
+
+msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgstr ""
+
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{loadingIcon} Started"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+msgid "%{nip_domain} can be used as an alternative to a custom domain."
+msgstr ""
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr ""
+
+msgid "%{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
+
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid "- Runner is active and can process any new jobs"
+msgstr ""
+
+msgid "- Runner is paused and will not receive any new jobs"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "1 %{type} addition"
+msgid_plural "%{count} %{type} additions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 %{type} modification"
+msgid_plural "%{count} %{type} modifications"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed issue"
+msgid_plural "%d closed issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed merge request"
+msgid_plural "%d closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merged merge request"
+msgid_plural "%d merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open merge request"
+msgid_plural "%d open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 user"
+msgid_plural "%d users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "2FA enabled"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get the permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
+msgstr ""
+
+msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
+msgstr ""
+
+msgid "<strong>%{group_name}</strong> group members"
+msgstr ""
+
+msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
+msgstr ""
+
+msgid "<strong>Removes</strong> source branch"
+msgstr ""
+
+msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
+msgstr ""
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
+msgstr ""
+
+msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About GitLab CE"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Accepted MR"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied! Please verify you can add deploy keys to this repository."
+msgstr ""
+
+msgid "Access expiration date"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add Changelog"
+msgstr ""
+
+msgid "Add Contribution guide"
+msgstr ""
+
+msgid "Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add Readme"
+msgstr ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add projects"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add todo"
+msgstr ""
+
+msgid "Add user(s) to the group:"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Admin Area"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "Admin area"
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminProjects|Delete project"
+msgstr ""
+
+msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
+
+msgid "Advanced settings"
+msgstr ""
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "All"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr ""
+
+msgid "All users"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch."
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts"
+msgstr ""
+
+msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
+msgstr ""
+
+msgid "Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An error accured whilst committing your changes."
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error occured creating the new branch."
+msgstr ""
+
+msgid "An error occured whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occured whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occured whilst loading all the files."
+msgstr ""
+
+msgid "An error occured whilst loading the file content."
+msgstr ""
+
+msgid "An error occured whilst loading the file."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request."
+msgstr ""
+
+msgid "An error occured whilst loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
+msgstr ""
+
+msgid "An error occurred while adding approver"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while fetching markdown preview"
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching sidebar data"
+msgstr ""
+
+msgid "An error occurred while fetching stages."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the pipeline."
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while importing project: %{details}"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while removing approver"
+msgstr ""
+
+msgid "An error occurred while rendering KaTeX"
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while retrieving calendar activity"
+msgstr ""
+
+msgid "An error occurred while retrieving diff"
+msgstr ""
+
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
+msgstr ""
+
+msgid "An error occurred while subscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while unsubscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any Label"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read-only"
+msgstr ""
+
+msgid "Archived projects"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Artifact ID"
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer to set up a group Runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned Merge Requests"
+msgstr ""
+
+msgid "Assigned to :name"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assignee"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee lists show all issues assigned to the selected user."
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto DevOps, runners and job artifacts"
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
+msgstr ""
+
+msgid "Auto-cancel redundant, pending pipelines"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
+msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
+msgstr ""
+
+msgid "AutoDevOps|add a Kubernetes cluster"
+msgstr ""
+
+msgid "AutoDevOps|enable Auto DevOps"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available group Runners : %{runners}"
+msgstr ""
+
+msgid "Available group Runners : %{runners}."
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|A new badge was added."
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Delete badge"
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|No badge image"
+msgstr ""
+
+msgid "Badges|No image to preview"
+msgstr ""
+
+msgid "Badges|Please fill in a valid URL"
+msgstr ""
+
+msgid "Badges|Project Badge"
+msgstr ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|The badge was saved."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "Badges|e.g. %{exampleUrl}"
+msgstr ""
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are examples of regex for existing tools:"
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
+msgstr ""
+
+msgid "BillingPlans|Current plan"
+msgstr ""
+
+msgid "BillingPlans|Customer Support"
+msgstr ""
+
+msgid "BillingPlans|Downgrade"
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
+msgstr ""
+
+msgid "BillingPlans|Manage plan"
+msgstr ""
+
+msgid "BillingPlans|Please contact %{customer_support_link} in that case."
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Upgrade"
+msgstr ""
+
+msgid "BillingPlans|You are currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
+msgstr ""
+
+msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
+msgstr ""
+
+msgid "BillingPlans|features"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|paid annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch (%{branch_count})"
+msgid_plural "Branches (%{branch_count})"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch has changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "BranchSwitcherPlaceholder|Search branches"
+msgstr ""
+
+msgid "BranchSwitcherTitle|Switch branch"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cant find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch '%{branch_name}'?"
+msgstr ""
+
+msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+msgstr ""
+
+msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Branches|Only a project maintainer or owner can delete a protected branch"
+msgstr ""
+
+msgid "Branches|Overview"
+msgstr ""
+
+msgid "Branches|Protected branches can be managed in %{project_settings_link}."
+msgstr ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Sort by"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+msgstr ""
+
+msgid "Branches|The default branch cannot be deleted"
+msgstr ""
+
+msgid "Branches|This branch hasn’t been merged into %{default_branch}."
+msgstr ""
+
+msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
+msgid "Branches|To confirm, type %{branch_name_confirmation}:"
+msgstr ""
+
+msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
+msgstr ""
+
+msgid "Branches|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|project settings"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "Built-In"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CI / CD"
+msgstr ""
+
+msgid "CI / CD Settings"
+msgstr ""
+
+msgid "CI will run using the credentials assigned above."
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD for external repo"
+msgstr ""
+
+msgid "CI/CD settings"
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Deployment strategy needs a domain name to work correctly."
+msgstr ""
+
+msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|Learn more about Auto DevOps"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "Callback URL"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Certificate fingerprint"
+msgstr ""
+
+msgid "Change Weight"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates."
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "Changelog"
+msgstr ""
+
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
+msgstr ""
+
+msgid "Choose <strong>Next</strong> at the bottom of the page."
+msgstr ""
+
+msgid "Choose File ..."
+msgstr ""
+
+msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
+msgstr ""
+
+msgid "Choose file..."
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose which groups you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose which repositories you want to import."
+msgstr ""
+
+msgid "Choose which shards you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Error occured while saving variables"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "CiVariable|Validation failed"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
+msgstr ""
+
+msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
+msgstr ""
+
+msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
+msgstr ""
+
+msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
+msgstr ""
+
+msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Client authentication certificate"
+msgstr ""
+
+msgid "Client authentication key"
+msgstr ""
+
+msgid "Client authentication key password"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
+msgstr ""
+
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgstr ""
+
+msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|Applications"
+msgstr ""
+
+msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Token"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Helm Tiller"
+msgstr ""
+
+msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
+msgstr ""
+
+msgid "ClusterIntegration|Hide"
+msgstr ""
+
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|In order to show the health of the cluster, we'll need to provision your cluster with Prometheus to collect the required data."
+msgstr ""
+
+msgid "ClusterIntegration|Ingress"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress IP Address"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
+msgstr ""
+
+msgid "ClusterIntegration|Install"
+msgstr ""
+
+msgid "ClusterIntegration|Install Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Installed"
+msgstr ""
+
+msgid "ClusterIntegration|Installing"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
+msgstr ""
+
+msgid "ClusterIntegration|Integration status"
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster health"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
+msgstr ""
+
+msgid "ClusterIntegration|More information"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Note:"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Service token"
+msgstr ""
+
+msgid "ClusterIntegration|Show"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Token"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|check the pricing here"
+msgstr ""
+
+msgid "ClusterIntegration|documentation"
+msgstr ""
+
+msgid "ClusterIntegration|help page"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|properly configured"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "Code owners"
+msgstr ""
+
+msgid "Cohorts"
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & resolve discussion"
+msgstr ""
+
+msgid "Comment & unresolve discussion"
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit (%{commit_count})"
+msgid_plural "Commits (%{commit_count})"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit duration in minutes for last 30 commits"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|Commit: %{commitText}"
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Commit…"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|Compare"
+msgstr ""
+
+msgid "CompareBranches|Source"
+msgstr ""
+
+msgid "CompareBranches|Target"
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Tracing"
+msgstr ""
+
+msgid "Configure automatic git checks and housekeeping on repositories."
+msgstr ""
+
+msgid "Configure limits for web and API requests."
+msgstr ""
+
+msgid "Configure push mirrors."
+msgstr ""
+
+msgid "Configure storage path settings."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the way a user creates a new account."
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Created"
+msgstr ""
+
+msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
+msgstr ""
+
+msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
+msgstr ""
+
+msgid "ContainerRegistry|How to use the Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Learn more about"
+msgstr ""
+
+msgid "ContainerRegistry|No tags in Container Registry for this container image."
+msgstr ""
+
+msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgstr ""
+
+msgid "ContainerRegistry|Size"
+msgstr ""
+
+msgid "ContainerRegistry|Tag"
+msgstr ""
+
+msgid "ContainerRegistry|Tag ID"
+msgstr ""
+
+msgid "ContainerRegistry|Use different image names"
+msgstr ""
+
+msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
+msgstr ""
+
+msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution guide"
+msgstr ""
+
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "ContributorsPage|%{startDate} – %{endDate}"
+msgstr ""
+
+msgid "ContributorsPage|Building repository graph."
+msgstr ""
+
+msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Control the display of third party offers."
+msgstr ""
+
+msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of repository backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of verification operations for this Geo node"
+msgstr ""
+
+msgid "ConvDev Index"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key to clipboard"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy branch name to clipboard"
+msgstr ""
+
+msgid "Copy command to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Copy file path to clipboard"
+msgstr ""
+
+msgid "Copy incoming email address to clipboard"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
+msgid "Copy reference to clipboard"
+msgstr ""
+
+msgid "Copy secret to clipboard"
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token to clipboard"
+msgstr ""
+
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new branch and merge request"
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create branch"
+msgstr ""
+
+msgid "Create commit"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty repository"
+msgstr ""
+
+msgid "Create epic"
+msgstr ""
+
+msgid "Create file"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created on"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron syntax"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current node"
+msgstr ""
+
+msgid "CurrentUser|Profile"
+msgstr ""
+
+msgid "CurrentUser|Settings"
+msgstr ""
+
+msgid "Custom"
+msgstr ""
+
+msgid "Custom CI config path"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Production"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Default Branch"
+msgstr ""
+
+msgid "Default classification label"
+msgstr ""
+
+msgid "Default: Directly import the Google Code email address or username"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete Package"
+msgstr ""
+
+msgid "Delete Snippet"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete list"
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployKeys|Write access allowed"
+msgstr ""
+
+msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Add a deploy token"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository"
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Copy username to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Deploy Tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|This project has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "DeployTokens|Use this username as a login."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|You are about to revoke"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group Runners"
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "Discard review"
+msgstr ""
+
+msgid "Discover GitLab Geo."
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss Cycle Analytics introduction box"
+msgstr ""
+
+msgid "Dismiss Merge Request promotion"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Each Runner can be in one of the following states:"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Elasticsearch"
+msgstr ""
+
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable SAML authentication for this group"
+msgstr ""
+
+msgid "Enable Sentry for error reporting and logging."
+msgstr ""
+
+msgid "Enable and configure InfluxDB metrics."
+msgstr ""
+
+msgid "Enable and configure Prometheus metrics."
+msgstr ""
+
+msgid "Enable classification control using an external service"
+msgstr ""
+
+msgid "Enable for this project"
+msgstr ""
+
+msgid "Enable group Runners"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable reCAPTCHA or Akismet and set IP limits."
+msgstr ""
+
+msgid "Enable the Performance Bar for a given group."
+msgstr ""
+
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter the issue description"
+msgstr ""
+
+msgid "Enter the issue title"
+msgstr ""
+
+msgid "Enter the merge request description"
+msgstr ""
+
+msgid "Enter the merge request title"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No pod name has been specified"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod logs from"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Read more about environments"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epic will be removed! Are you sure?"
+msgstr ""
+
+msgid "Epics"
+msgstr ""
+
+msgid "Epics Roadmap"
+msgstr ""
+
+msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
+msgstr ""
+
+msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgstr ""
+
+msgid "Epics|How can I solve this?"
+msgstr ""
+
+msgid "Epics|More information"
+msgstr ""
+
+msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+msgstr ""
+
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr ""
+
+msgid "Epics|due"
+msgstr ""
+
+msgid "Epics|start"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Reporting and Logging"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error fetching contributors data."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching usage ping data."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error updating status for all todos."
+msgstr ""
+
+msgid "Error updating todo status."
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "Every day (at 4:00am)"
+msgstr ""
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr ""
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
+msgid "Explore"
+msgstr ""
+
+msgid "Explore GitLab"
+msgstr ""
+
+msgid "Explore Groups"
+msgstr ""
+
+msgid "Explore groups"
+msgstr ""
+
+msgid "Explore projects"
+msgstr ""
+
+msgid "Explore public groups"
+msgstr ""
+
+msgid "External Classification Policy Authorization"
+msgstr ""
+
+msgid "External authentication"
+msgstr ""
+
+msgid "External authorization denied access to this project"
+msgstr ""
+
+msgid "External authorization request timeout"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification Label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to remove issue from board, please try again."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to update issues, please try again."
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fields on this page are now uneditable, you can configure"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Files (%{human_size})"
+msgstr ""
+
+msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
+msgid "Filter by commit message"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Find the downloaded ZIP file and decompress it."
+msgstr ""
+
+msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish review"
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "FirstPushedBy|First"
+msgstr ""
+
+msgid "FirstPushedBy|pushed by"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Follow the steps below to export your Google Code project data."
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Format"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
+msgid "From %{provider_title}"
+msgstr ""
+
+msgid "From Bitbucket"
+msgstr ""
+
+msgid "From Bitbucket Server"
+msgstr ""
+
+msgid "From FogBugz"
+msgstr ""
+
+msgid "From GitLab.com"
+msgstr ""
+
+msgid "From Google Code"
+msgstr ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "From milestones:"
+msgstr ""
+
+msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Nodes"
+msgstr ""
+
+msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is failing or broken."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
+msgstr ""
+
+msgid "GeoNodes|Checksummed"
+msgstr ""
+
+msgid "GeoNodes|Data is out of date from %{timeago}"
+msgstr ""
+
+msgid "GeoNodes|Data replication lag"
+msgstr ""
+
+msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "GeoNodes|Failed"
+msgstr ""
+
+msgid "GeoNodes|Full"
+msgstr ""
+
+msgid "GeoNodes|GitLab version"
+msgstr ""
+
+msgid "GeoNodes|GitLab version does not match the primary node version"
+msgstr ""
+
+msgid "GeoNodes|Health status"
+msgstr ""
+
+msgid "GeoNodes|Last event ID processed by cursor"
+msgstr ""
+
+msgid "GeoNodes|Last event ID seen from primary"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository verification"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki verification"
+msgstr ""
+
+msgid "GeoNodes|Loading nodes"
+msgstr ""
+
+msgid "GeoNodes|Local LFS objects"
+msgstr ""
+
+msgid "GeoNodes|Local attachments"
+msgstr ""
+
+msgid "GeoNodes|Local job artifacts"
+msgstr ""
+
+msgid "GeoNodes|New node"
+msgstr ""
+
+msgid "GeoNodes|Node Authentication was successfully repaired."
+msgstr ""
+
+msgid "GeoNodes|Node was successfully removed."
+msgstr ""
+
+msgid "GeoNodes|Not checksummed"
+msgstr ""
+
+msgid "GeoNodes|Out of sync"
+msgstr ""
+
+msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Replication slot WAL"
+msgstr ""
+
+msgid "GeoNodes|Replication slots"
+msgstr ""
+
+msgid "GeoNodes|Repositories"
+msgstr ""
+
+msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Repositories verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Repository verification progress"
+msgstr ""
+
+msgid "GeoNodes|Selective"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while changing node status"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while fetching nodes"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while removing node"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while repairing node"
+msgstr ""
+
+msgid "GeoNodes|Storage config"
+msgstr ""
+
+msgid "GeoNodes|Sync settings"
+msgstr ""
+
+msgid "GeoNodes|Synced"
+msgstr ""
+
+msgid "GeoNodes|Unused slots"
+msgstr ""
+
+msgid "GeoNodes|Unverified"
+msgstr ""
+
+msgid "GeoNodes|Used slots"
+msgstr ""
+
+msgid "GeoNodes|Verified"
+msgstr ""
+
+msgid "GeoNodes|Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Wiki verification progress"
+msgstr ""
+
+msgid "GeoNodes|Wikis"
+msgstr ""
+
+msgid "GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for forced re-download"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-check"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|All"
+msgstr ""
+
+msgid "Geo|All projects"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|File sync capacity"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Groups to synchronize"
+msgstr ""
+
+msgid "Geo|In sync"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|Not synced yet"
+msgstr ""
+
+msgid "Geo|Pending"
+msgstr ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Recheck"
+msgstr ""
+
+msgid "Geo|Recheck all projects"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Repository sync capacity"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all projects"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Select groups to replicate."
+msgstr ""
+
+msgid "Geo|Shards to synchronize"
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
+msgid "Geo|Unknown state"
+msgstr ""
+
+msgid "Geo|Verification capacity"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|You need a different license to use Geo replication"
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Git"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git strategy for pipelines"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitLab CI Linter has been moved"
+msgstr ""
+
+msgid "GitLab Geo"
+msgstr ""
+
+msgid "GitLab Group Runners can execute code for all the projects in this group."
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab single sign on URL"
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLab’s issue tracker"
+msgstr ""
+
+msgid "Gitaly"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go to"
+msgstr ""
+
+msgid "Go to %{link_to_google_takeout}."
+msgstr ""
+
+msgid "Google Code import"
+msgstr ""
+
+msgid "Google Takeout"
+msgstr ""
+
+msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group CI/CD settings"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group Runners"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group details"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group maintainers can register group runners in the %{link}"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Loading roadmap"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|Until %{dateWord}"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Customize your group badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about badges."
+msgstr ""
+
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+msgstr ""
+
+msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
+msgstr ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Create a project in this group."
+msgstr ""
+
+msgid "GroupsTree|Create a subgroup in this group."
+msgstr ""
+
+msgid "GroupsTree|Edit group"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave this group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Have your users email"
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help page"
+msgstr ""
+
+msgid "Help page text and support page url."
+msgstr ""
+
+msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide whitespace changes"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Client side evaluation"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Open in file view"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "Identity provider single sign on URL"
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr ""
+
+msgid "If disabled, the access level will depend on the user's permissions in the project."
+msgstr ""
+
+msgid "If enabled"
+msgstr ""
+
+msgid "If enabled, access to projects will be validated on an external service using their classification label."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you already have files you can push them using the %{link_to_cli} below."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import all compatible projects"
+msgstr ""
+
+msgid "Import all projects"
+msgstr ""
+
+msgid "Import all repositories"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import projects from Google Code"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "Improve Issue boards with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
+msgid "In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "Incompatible Project"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input your repository URL"
+msgstr ""
+
+msgid "Install GitLab Runner"
+msgstr ""
+
+msgid "Install Runner on Kubernetes"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Instance Statistics"
+msgstr ""
+
+msgid "Instance Statistics visibility"
+msgstr ""
+
+msgid "Instance does not support multiple Kubernetes clusters"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations Settings"
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Cycle Analytics"
+msgstr ""
+
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue board focus mode"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Job"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed in"
+msgstr ""
+
+msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration was not removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes configured"
+msgstr ""
+
+msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label lists show all issues with the selected label."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{name}"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
+msgstr ""
+
+msgid "Learn more about Kubernetes"
+msgstr ""
+
+msgid "Learn more about protected branches"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
+msgid "LicenseManagement|Approve license"
+msgstr ""
+
+msgid "LicenseManagement|Approve license?"
+msgstr ""
+
+msgid "LicenseManagement|Approved"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license?"
+msgstr ""
+
+msgid "LicenseManagement|Blacklisted"
+msgstr ""
+
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
+msgid "LicenseManagement|License"
+msgstr ""
+
+msgid "LicenseManagement|License Management"
+msgstr ""
+
+msgid "LicenseManagement|License details"
+msgstr ""
+
+msgid "LicenseManagement|License name"
+msgstr ""
+
+msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
+msgstr ""
+
+msgid "LicenseManagement|Packages"
+msgstr ""
+
+msgid "LicenseManagement|Remove license"
+msgstr ""
+
+msgid "LicenseManagement|Remove license?"
+msgstr ""
+
+msgid "LicenseManagement|Submit"
+msgstr ""
+
+msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
+msgstr ""
+
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseManagement|URL"
+msgstr ""
+
+msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LinkedIn"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "List Your Gitea Repositories"
+msgstr ""
+
+msgid "List available repositories"
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "List your GitHub repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked to current projects"
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make sure you're logged into the account that owns the projects you'd like to import."
+msgstr ""
+
+msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
+msgstr ""
+
+msgid "Manage Web IDE features"
+msgstr ""
+
+msgid "Manage access"
+msgstr ""
+
+msgid "Manage all notifications"
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a full email address"
+msgstr ""
+
+msgid "Map a Google Code user to a full name"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark todo as done"
+msgstr ""
+
+msgid "Markdown enabled"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
+msgid "Maven Metadata"
+msgstr ""
+
+msgid "Maven package"
+msgstr ""
+
+msgid "Max access level"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Median"
+msgstr ""
+
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Request:"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge requests"
+msgstr ""
+
+msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
+msgid "MergeRequests|Resolve this discussion in a new issue"
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|Toggle comments for this file"
+msgstr ""
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr ""
+
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Influx"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics|Business"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgstr ""
+
+msgid "Metrics|Environment"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgstr ""
+
+msgid "Metrics|Learn about environments"
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|Name"
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|No deployed environments"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|Query"
+msgstr ""
+
+msgid "Metrics|Response"
+msgstr ""
+
+msgid "Metrics|System"
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|Type"
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
+msgid "Milestone"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Mirror a repository"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror user"
+msgstr ""
+
+msgid "Mirrored repositories"
+msgstr ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
+msgid "Modal|Cancel"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More actions"
+msgstr ""
+
+msgid "More info"
+msgstr ""
+
+msgid "More information"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Multiple issue boards"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name your individual key via a title"
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Snippets"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No Label"
+msgstr ""
+
+msgid "No assignee"
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No container images stored for this project. Add one by following the instructions above."
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No issues for the selected time period."
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No merge requests for the selected time period."
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No packages stored for this project."
+msgstr ""
+
+msgid "No prioritised labels with such name or description"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No pushes for the selected time period."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No, directly import the existing email addresses and usernames."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "Not all comments are displayed because you're comparing two versions of the diff."
+msgstr ""
+
+msgid "Not all comments are displayed because you're viewing an old version of the diff."
+msgstr ""
+
+msgid "Not allowed to merge"
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not enough data"
+msgstr ""
+
+msgid "Not now"
+msgstr ""
+
+msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "Only admins"
+msgstr ""
+
+msgid "Only comments from the following commit are shown below"
+msgstr ""
+
+msgid "Only mirror protected branches"
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open in Xcode"
+msgstr ""
+
+msgid "Open projects"
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open source software to collaborate on code"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened MR"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Otherwise it is recommended you start with one of the options below."
+msgstr ""
+
+msgid "Outbound requests"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Package information"
+msgstr ""
+
+msgid "Package was removed"
+msgstr ""
+
+msgid "Packages"
+msgstr ""
+
+msgid "Pages"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
+
+msgid "Path, transfer, remove"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Paused Runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "Per job. If a job passes this threshold, it will be marked as failed"
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, or removing the group."
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline Health"
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline quota"
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines for last month"
+msgstr ""
+
+msgid "Pipelines for last week"
+msgstr ""
+
+msgid "Pipelines for last year"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|CI Lint"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgstr ""
+
+msgid "Pipelines|Get started with Pipelines"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|There are currently no %{scope} pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+msgstr ""
+
+msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Create for"
+msgstr ""
+
+msgid "Pipeline|Create pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Existing branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Search branches"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|all"
+msgstr ""
+
+msgid "Pipeline|success"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Please accept the Terms of Service before continuing."
+msgstr ""
+
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please solve the reCAPTCHA"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences|Navigation theme"
+msgstr ""
+
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Private - Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|Add status emoji"
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
+msgid "Profiles|Clear status"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Delete Account"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Delete your account?"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Website"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project avatar in repository: %{link}"
+msgstr ""
+
+msgid "Project details"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectLifecycle|Stage"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Customize your project badges."
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Learn more about badges."
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
+msgstr ""
+
+msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "PrometheusAlerts|Add alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Edit alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error creating alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error deleting alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error fetching alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error saving alert"
+msgstr ""
+
+msgid "PrometheusAlerts|No alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Operator"
+msgstr ""
+
+msgid "PrometheusAlerts|Threshold"
+msgstr ""
+
+msgid "PrometheusDashboard|Time"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration"
+msgstr ""
+
+msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
+msgstr ""
+
+msgid "PrometheusService|Common metrics"
+msgstr ""
+
+msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
+msgstr ""
+
+msgid "PrometheusService|Custom metrics"
+msgstr ""
+
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr ""
+
+msgid "PrometheusService|Finding custom metrics..."
+msgstr ""
+
+msgid "PrometheusService|Install Prometheus on clusters"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+msgstr ""
+
+msgid "PrometheusService|More information"
+msgstr ""
+
+msgid "PrometheusService|New metric"
+msgstr ""
+
+msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|Time-series monitoring service"
+msgstr ""
+
+msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
+msgstr ""
+
+msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
+msgstr ""
+
+msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote these project milestones into a group milestone."
+msgstr ""
+
+msgid "Promote to Group Milestone"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Environments"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "Protip:"
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Pseudonymizer data collection"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRule|Committer restriction"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
+
+msgid "Readme"
+msgstr ""
+
+msgid "Real-time features"
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Reference:"
+msgstr ""
+
+msgid "Refresh"
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Regenerate key"
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register and see your runners for this group."
+msgstr ""
+
+msgid "Register and see your runners for this project."
+msgstr ""
+
+msgid "Registry"
+msgstr ""
+
+msgid "Related Commits"
+msgstr ""
+
+msgid "Related Deployed Jobs"
+msgstr ""
+
+msgid "Related Issues"
+msgstr ""
+
+msgid "Related Jobs"
+msgstr ""
+
+msgid "Related Merge Requests"
+msgstr ""
+
+msgid "Related Merged Requests"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove Runner"
+msgstr ""
+
+msgid "Remove avatar"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
+msgid "Rename"
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Repair authentication"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{failedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|Class"
+msgstr ""
+
+msgid "Reports|Confidence"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository URL"
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirror"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Requests Profiles"
+msgstr ""
+
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
+msgid "Resolve all discussions in new issue"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve discussion"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal Variables"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
+msgid "Runner token"
+msgstr ""
+
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners API"
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, and even on your local machine."
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|You have used all your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML Single Sign On"
+msgstr ""
+
+msgid "SAML Single Sign On Settings"
+msgstr ""
+
+msgid "SAST"
+msgstr ""
+
+msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save variables"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scoped issue boards"
+msgstr ""
+
+msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or jump to…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in this group"
+msgstr ""
+
+msgid "SearchAutocomplete|in this project"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr ""
+
+msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgstr ""
+
+msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select a group to invite"
+msgstr ""
+
+msgid "Select a namespace to fork the project"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select an existing Kubernetes cluster or create a new one"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select branch/tag"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project and zone to choose machine type"
+msgstr ""
+
+msgid "Select project to choose zone"
+msgstr ""
+
+msgid "Select projects you want to import."
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Select the custom project template source group."
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Selective synchronization"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send usage data"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
+msgstr ""
+
+msgid "Session expiration, projects limit and attachment size."
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set instance-wide template repository"
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Sherlock Transactions"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show latest version of the diff"
+msgstr ""
+
+msgid "Show parent pages"
+msgstr ""
+
+msgid "Show parent subgroups"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|Change weight"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in to %{group_name}"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong when toggling the button"
+msgstr ""
+
+msgid "Something went wrong while closing the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while fetching %{listType} list"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the projects."
+msgstr ""
+
+msgid "Something went wrong while fetching the registry list."
+msgstr ""
+
+msgid "Something went wrong while reopening the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Sorry, no epics matched your search"
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "SortOptions|Access level, ascending"
+msgstr ""
+
+msgid "SortOptions|Access level, descending"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Milestone"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest joined"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source code"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Specific Runners"
+msgstr ""
+
+msgid "Specify an e-mail address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage & Commit"
+msgstr ""
+
+msgid "Stage all changes"
+msgstr ""
+
+msgid "Stage changes"
+msgstr ""
+
+msgid "Staged"
+msgstr ""
+
+msgid "Staged %{type}"
+msgstr ""
+
+msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start the Runner!"
+msgstr ""
+
+msgid "Start your trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Stop environment"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Sync information"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System header and footer:"
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "Tag (%{tag_count})"
+msgid_plural "Tags (%{tag_count})"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release notes"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag."
+msgstr ""
+
+msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Sort by"
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Test SAML SSO"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+msgid "Thanks! Don't show me this again"
+msgstr ""
+
+msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
+msgstr ""
+
+msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr ""
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The deployment of this job to %{environmentLink} did not succeed."
+msgstr ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr ""
+
+msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
+msgstr ""
+
+msgid "The phase of the development lifecycle."
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr ""
+
+msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
+msgstr ""
+
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr ""
+
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
+msgstr ""
+
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The tabs below will be removed in a future version"
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no merge requests to show"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
+
+msgid "There was an error adding a todo."
+msgstr ""
+
+msgid "There was an error deleting the todo."
+msgstr ""
+
+msgid "There was an error loading users activity calendar."
+msgstr ""
+
+msgid "There was an error saving your notification settings."
+msgstr ""
+
+msgid "There was an error subscribing to this label."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "They can be managed using the %{link}."
+msgstr ""
+
+msgid "Third party offers"
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
+msgstr ""
+
+msgid "This application was created by %{link_to_owner}."
+msgstr ""
+
+msgid "This application will be able to:"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This branch has changed since you started editing. Would you like to create a new branch?"
+msgstr ""
+
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This group"
+msgstr ""
+
+msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgstr ""
+
+msgid "This group does not provide any group Runners yet."
+msgstr ""
+
+msgid "This is a confidential issue."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is the author's first Merge Request to this project."
+msgstr ""
+
+msgid "This issue is confidential"
+msgstr ""
+
+msgid "This issue is confidential and locked."
+msgstr ""
+
+msgid "This issue is locked."
+msgstr ""
+
+msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "This job is the most recent deployment to %{link}."
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This option is disabled as you don't have write permissions for the current branch"
+msgstr ""
+
+msgid "This option is disabled while you still have unstaged changes"
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page will be removed in a future release."
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project does not belong to a group and can therefore not make use of group Runners."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "This source diff could not be displayed because it is too large."
+msgstr ""
+
+msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
+msgstr ""
+
+msgid "This will delete the custom metric, Are you sure?"
+msgstr ""
+
+msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time before enforced"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds ago"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip:"
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr ""
+
+msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
+msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr ""
+
+msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
+msgstr ""
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr ""
+
+msgid "To start serving your jobs you can add Runners to your group"
+msgstr ""
+
+msgid "To this GitLab instance"
+msgstr ""
+
+msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
+msgstr ""
+
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
+
+msgid "To widen your search, change or remove filters."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Todo"
+msgstr ""
+
+msgid "Todos"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle discussion"
+msgstr ""
+
+msgid "Toggle file browser"
+msgstr ""
+
+msgid "Toggle navigation"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: OFF"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: ON"
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Time"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track activity with Contribution Analytics."
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trigger"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Turn on Service Desk"
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to save your changes"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unresolve discussion"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
+msgid "Unstage all changes"
+msgstr ""
+
+msgid "Unstage changes"
+msgstr ""
+
+msgid "Unstaged"
+msgstr ""
+
+msgid "Unstaged %{type}"
+msgstr ""
+
+msgid "Unstaged and staged %{type}"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Upgrade your plan to activate Advanced Global Search."
+msgstr ""
+
+msgid "Upgrade your plan to activate Contribution Analytics."
+msgstr ""
+
+msgid "Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Upgrade your plan to activate Issue weight."
+msgstr ""
+
+msgid "Upgrade your plan to improve Issue boards."
+msgstr ""
+
+msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage ping is not enabled"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "Use <code>%{native_redirect_uri}</code> for local tests"
+msgstr ""
+
+msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
+msgstr ""
+
+msgid "Use group milestones to manage issues from multiple projects in the same milestone."
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use the following registration token during setup:"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "Used by members to sign in to your group in GitLab"
+msgstr ""
+
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Variables"
+msgstr ""
+
+msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification information"
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View epics list"
+msgstr ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View group labels"
+msgstr ""
+
+msgid "View issue"
+msgstr ""
+
+msgid "View it on GitLab"
+msgstr ""
+
+msgid "View jobs"
+msgstr ""
+
+msgid "View labels"
+msgstr ""
+
+msgid "View log"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr ""
+
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|It is recommended to install %{markdown} so that GFM features render locally:"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgstr ""
+
+msgid "WikiMarkdownDocs|documentation"
+msgstr ""
+
+msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgstr ""
+
+msgid "WikiNewPagePlaceholder|how-to-setup"
+msgstr ""
+
+msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiNewPageTitle|New Wiki Page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgstr ""
+
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPageConflictMessage|the page"
+msgstr ""
+
+msgid "WikiPageCreate|Create %{page_title}"
+msgstr ""
+
+msgid "WikiPageEdit|Update %{page_title}"
+msgstr ""
+
+msgid "WikiPage|Page slug"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wiki|Create Page"
+msgstr ""
+
+msgid "Wiki|Create page"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|More Pages"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, let me map Google Code users to full names or GitLab users."
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
+msgstr ""
+
+msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You can %{linkStart}view the blob%{linkEnd} instead."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
+msgid "You can only edit files when you are on a branch"
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
+msgstr ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+msgstr ""
+
+msgid "You cannot write to this read-only GitLab instance."
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You must accept our Terms of Service and privacy policy in order to register an account"
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're receiving this email because %{reason}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your Todos"
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your comment will not be visible to the public."
+msgstr ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your projects"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "among other things"
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{namespace} is affected by %{vulnerability}."
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr ""
+
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr ""
+
+msgid "ciReport|(is loading)"
+msgstr ""
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr ""
+
+msgid "ciReport|Class"
+msgstr ""
+
+msgid "ciReport|Code quality"
+msgstr ""
+
+msgid "ciReport|Confidence"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Description"
+msgstr ""
+
+msgid "ciReport|Dismiss vulnerability"
+msgstr ""
+
+msgid "ciReport|Dismissed by"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|File"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Identifiers"
+msgstr ""
+
+msgid "ciReport|Instances"
+msgstr ""
+
+msgid "ciReport|Learn more about interacting with security reports (Alpha)."
+msgstr ""
+
+msgid "ciReport|License management detected %d license for the source branch only"
+msgid_plural "ciReport|License management detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected %d new license"
+msgid_plural "ciReport|License management detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected no licenses for the source branch only"
+msgstr ""
+
+msgid "ciReport|License management detected no new licenses"
+msgstr ""
+
+msgid "ciReport|Links"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|Method"
+msgstr ""
+
+msgid "ciReport|Namespace"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No changes to performance metrics"
+msgstr ""
+
+msgid "ciReport|Performance metrics"
+msgstr ""
+
+msgid "ciReport|Revert dismissal"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Severity"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error loading DAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading SAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading container scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error loading dependency scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "ciReport|on pipeline"
+msgstr ""
+
+msgid "command line instructions"
+msgstr ""
+
+msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgstr ""
+
+msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
+msgstr ""
+
+msgid "connecting"
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "customize"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "deploy token"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "here"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "importing"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "issue boards"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "license management"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|Add approval"
+msgstr ""
+
+msgid "mrWidget|Allows commits from members who can merge to the target branch"
+msgstr ""
+
+msgid "mrWidget|An error occured while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Cancel automatic merge"
+msgstr ""
+
+msgid "mrWidget|Check out branch"
+msgstr ""
+
+msgid "mrWidget|Checking ability to merge automatically"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes"
+msgstr ""
+
+msgid "mrWidget|Create an issue to resolve them later"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mentions"
+msgstr ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge request approved"
+msgstr ""
+
+msgid "mrWidget|Merge request approved; you can approve additionally"
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|No Approval required"
+msgstr ""
+
+msgid "mrWidget|No Approval required; you can still approve"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove Source Branch"
+msgstr ""
+
+msgid "mrWidget|Remove source branch"
+msgstr ""
+
+msgid "mrWidget|Remove your approval"
+msgstr ""
+
+msgid "mrWidget|Request to merge"
+msgstr ""
+
+msgid "mrWidget|Requires 1 more approval"
+msgid_plural "mrWidget|Requires %d more approvals"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Requires 1 more approval by"
+msgid_plural "mrWidget|Requires %d more approvals by"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Set by"
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The changes will be merged into"
+msgstr ""
+
+msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+msgstr ""
+
+msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
+msgstr ""
+
+msgid "mrWidget|The source branch has been removed"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will be removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will not be removed"
+msgstr ""
+
+msgid "mrWidget|There are merge conflicts"
+msgstr ""
+
+msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|This merge request is in the process of being merged"
+msgstr ""
+
+msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr ""
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|You can remove source branch now"
+msgstr ""
+
+msgid "mrWidget|branch does not exist."
+msgstr ""
+
+msgid "mrWidget|command line"
+msgstr ""
+
+msgid "mrWidget|into"
+msgstr ""
+
+msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "notification emails"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "password"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "source"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time spent."
+msgstr ""
+
+msgid "started"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "toggle collapse"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "within %d minute "
+msgid_plural "within %d minutes "
+msgstr[0] ""
+msgstr[1] ""
+
diff --git a/locale/nb_NO/gitlab.po b/locale/nb_NO/gitlab.po
new file mode 100644
index 00000000000..be6ccfe1adc
--- /dev/null
+++ b/locale/nb_NO/gitlab.po
@@ -0,0 +1,9995 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
+"Language-Team: Norwegian Bokmal\n"
+"Language: nb_NO\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: nb\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"PO-Revision-Date: 2018-11-19 17:17\n"
+
+msgid " Status"
+msgstr ""
+
+msgid " and"
+msgstr ""
+
+msgid " degraded on %d point"
+msgid_plural " degraded on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " improved on %d point"
+msgid_plural " improved on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d changed file"
+msgid_plural "%d changed files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d failed test result"
+msgid_plural "%d failed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d staged change"
+msgid_plural "%d staged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unstaged change"
+msgid_plural "%d unstaged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_timeago}"
+msgstr ""
+
+msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgstr ""
+
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{loadingIcon} Started"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+msgid "%{nip_domain} can be used as an alternative to a custom domain."
+msgstr ""
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr ""
+
+msgid "%{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
+
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid "- Runner is active and can process any new jobs"
+msgstr ""
+
+msgid "- Runner is paused and will not receive any new jobs"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "1 %{type} addition"
+msgid_plural "%{count} %{type} additions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 %{type} modification"
+msgid_plural "%{count} %{type} modifications"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed issue"
+msgid_plural "%d closed issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed merge request"
+msgid_plural "%d closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merged merge request"
+msgid_plural "%d merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open merge request"
+msgid_plural "%d open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 user"
+msgid_plural "%d users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "2FA enabled"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get the permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
+msgstr ""
+
+msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
+msgstr ""
+
+msgid "<strong>%{group_name}</strong> group members"
+msgstr ""
+
+msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
+msgstr ""
+
+msgid "<strong>Removes</strong> source branch"
+msgstr ""
+
+msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
+msgstr ""
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
+msgstr ""
+
+msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About GitLab CE"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Accepted MR"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied! Please verify you can add deploy keys to this repository."
+msgstr ""
+
+msgid "Access expiration date"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add Changelog"
+msgstr ""
+
+msgid "Add Contribution guide"
+msgstr ""
+
+msgid "Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add Readme"
+msgstr ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add projects"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add todo"
+msgstr ""
+
+msgid "Add user(s) to the group:"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Admin Area"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "Admin area"
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminProjects|Delete project"
+msgstr ""
+
+msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
+
+msgid "Advanced settings"
+msgstr ""
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "All"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr ""
+
+msgid "All users"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch."
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts"
+msgstr ""
+
+msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
+msgstr ""
+
+msgid "Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An error accured whilst committing your changes."
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error occured creating the new branch."
+msgstr ""
+
+msgid "An error occured whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occured whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occured whilst loading all the files."
+msgstr ""
+
+msgid "An error occured whilst loading the file content."
+msgstr ""
+
+msgid "An error occured whilst loading the file."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request."
+msgstr ""
+
+msgid "An error occured whilst loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
+msgstr ""
+
+msgid "An error occurred while adding approver"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while fetching markdown preview"
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching sidebar data"
+msgstr ""
+
+msgid "An error occurred while fetching stages."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the pipeline."
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while importing project: %{details}"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while removing approver"
+msgstr ""
+
+msgid "An error occurred while rendering KaTeX"
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while retrieving calendar activity"
+msgstr ""
+
+msgid "An error occurred while retrieving diff"
+msgstr ""
+
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
+msgstr ""
+
+msgid "An error occurred while subscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while unsubscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any Label"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read-only"
+msgstr ""
+
+msgid "Archived projects"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Artifact ID"
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer to set up a group Runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned Merge Requests"
+msgstr ""
+
+msgid "Assigned to :name"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assignee"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee lists show all issues assigned to the selected user."
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto DevOps, runners and job artifacts"
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
+msgstr ""
+
+msgid "Auto-cancel redundant, pending pipelines"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
+msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
+msgstr ""
+
+msgid "AutoDevOps|add a Kubernetes cluster"
+msgstr ""
+
+msgid "AutoDevOps|enable Auto DevOps"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available group Runners : %{runners}"
+msgstr ""
+
+msgid "Available group Runners : %{runners}."
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|A new badge was added."
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Delete badge"
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|No badge image"
+msgstr ""
+
+msgid "Badges|No image to preview"
+msgstr ""
+
+msgid "Badges|Please fill in a valid URL"
+msgstr ""
+
+msgid "Badges|Project Badge"
+msgstr ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|The badge was saved."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "Badges|e.g. %{exampleUrl}"
+msgstr ""
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are examples of regex for existing tools:"
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
+msgstr ""
+
+msgid "BillingPlans|Current plan"
+msgstr ""
+
+msgid "BillingPlans|Customer Support"
+msgstr ""
+
+msgid "BillingPlans|Downgrade"
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
+msgstr ""
+
+msgid "BillingPlans|Manage plan"
+msgstr ""
+
+msgid "BillingPlans|Please contact %{customer_support_link} in that case."
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Upgrade"
+msgstr ""
+
+msgid "BillingPlans|You are currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
+msgstr ""
+
+msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
+msgstr ""
+
+msgid "BillingPlans|features"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|paid annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch (%{branch_count})"
+msgid_plural "Branches (%{branch_count})"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch has changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "BranchSwitcherPlaceholder|Search branches"
+msgstr ""
+
+msgid "BranchSwitcherTitle|Switch branch"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cant find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch '%{branch_name}'?"
+msgstr ""
+
+msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+msgstr ""
+
+msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Branches|Only a project maintainer or owner can delete a protected branch"
+msgstr ""
+
+msgid "Branches|Overview"
+msgstr ""
+
+msgid "Branches|Protected branches can be managed in %{project_settings_link}."
+msgstr ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Sort by"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+msgstr ""
+
+msgid "Branches|The default branch cannot be deleted"
+msgstr ""
+
+msgid "Branches|This branch hasn’t been merged into %{default_branch}."
+msgstr ""
+
+msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
+msgid "Branches|To confirm, type %{branch_name_confirmation}:"
+msgstr ""
+
+msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
+msgstr ""
+
+msgid "Branches|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|project settings"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "Built-In"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CI / CD"
+msgstr ""
+
+msgid "CI / CD Settings"
+msgstr ""
+
+msgid "CI will run using the credentials assigned above."
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD for external repo"
+msgstr ""
+
+msgid "CI/CD settings"
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Deployment strategy needs a domain name to work correctly."
+msgstr ""
+
+msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|Learn more about Auto DevOps"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "Callback URL"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Certificate fingerprint"
+msgstr ""
+
+msgid "Change Weight"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates."
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "Changelog"
+msgstr ""
+
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
+msgstr ""
+
+msgid "Choose <strong>Next</strong> at the bottom of the page."
+msgstr ""
+
+msgid "Choose File ..."
+msgstr ""
+
+msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
+msgstr ""
+
+msgid "Choose file..."
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose which groups you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose which repositories you want to import."
+msgstr ""
+
+msgid "Choose which shards you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Error occured while saving variables"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "CiVariable|Validation failed"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
+msgstr ""
+
+msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
+msgstr ""
+
+msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
+msgstr ""
+
+msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
+msgstr ""
+
+msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Client authentication certificate"
+msgstr ""
+
+msgid "Client authentication key"
+msgstr ""
+
+msgid "Client authentication key password"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
+msgstr ""
+
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgstr ""
+
+msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|Applications"
+msgstr ""
+
+msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Token"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Helm Tiller"
+msgstr ""
+
+msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
+msgstr ""
+
+msgid "ClusterIntegration|Hide"
+msgstr ""
+
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|In order to show the health of the cluster, we'll need to provision your cluster with Prometheus to collect the required data."
+msgstr ""
+
+msgid "ClusterIntegration|Ingress"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress IP Address"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
+msgstr ""
+
+msgid "ClusterIntegration|Install"
+msgstr ""
+
+msgid "ClusterIntegration|Install Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Installed"
+msgstr ""
+
+msgid "ClusterIntegration|Installing"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
+msgstr ""
+
+msgid "ClusterIntegration|Integration status"
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster health"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
+msgstr ""
+
+msgid "ClusterIntegration|More information"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Note:"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Service token"
+msgstr ""
+
+msgid "ClusterIntegration|Show"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Token"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|check the pricing here"
+msgstr ""
+
+msgid "ClusterIntegration|documentation"
+msgstr ""
+
+msgid "ClusterIntegration|help page"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|properly configured"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "Code owners"
+msgstr ""
+
+msgid "Cohorts"
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & resolve discussion"
+msgstr ""
+
+msgid "Comment & unresolve discussion"
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit (%{commit_count})"
+msgid_plural "Commits (%{commit_count})"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit duration in minutes for last 30 commits"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|Commit: %{commitText}"
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Commit…"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|Compare"
+msgstr ""
+
+msgid "CompareBranches|Source"
+msgstr ""
+
+msgid "CompareBranches|Target"
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Tracing"
+msgstr ""
+
+msgid "Configure automatic git checks and housekeeping on repositories."
+msgstr ""
+
+msgid "Configure limits for web and API requests."
+msgstr ""
+
+msgid "Configure push mirrors."
+msgstr ""
+
+msgid "Configure storage path settings."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the way a user creates a new account."
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Created"
+msgstr ""
+
+msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
+msgstr ""
+
+msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
+msgstr ""
+
+msgid "ContainerRegistry|How to use the Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Learn more about"
+msgstr ""
+
+msgid "ContainerRegistry|No tags in Container Registry for this container image."
+msgstr ""
+
+msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgstr ""
+
+msgid "ContainerRegistry|Size"
+msgstr ""
+
+msgid "ContainerRegistry|Tag"
+msgstr ""
+
+msgid "ContainerRegistry|Tag ID"
+msgstr ""
+
+msgid "ContainerRegistry|Use different image names"
+msgstr ""
+
+msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
+msgstr ""
+
+msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution guide"
+msgstr ""
+
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "ContributorsPage|%{startDate} – %{endDate}"
+msgstr ""
+
+msgid "ContributorsPage|Building repository graph."
+msgstr ""
+
+msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Control the display of third party offers."
+msgstr ""
+
+msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of repository backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of verification operations for this Geo node"
+msgstr ""
+
+msgid "ConvDev Index"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key to clipboard"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy branch name to clipboard"
+msgstr ""
+
+msgid "Copy command to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Copy file path to clipboard"
+msgstr ""
+
+msgid "Copy incoming email address to clipboard"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
+msgid "Copy reference to clipboard"
+msgstr ""
+
+msgid "Copy secret to clipboard"
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token to clipboard"
+msgstr ""
+
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new branch and merge request"
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create branch"
+msgstr ""
+
+msgid "Create commit"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty repository"
+msgstr ""
+
+msgid "Create epic"
+msgstr ""
+
+msgid "Create file"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created on"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron syntax"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current node"
+msgstr ""
+
+msgid "CurrentUser|Profile"
+msgstr ""
+
+msgid "CurrentUser|Settings"
+msgstr ""
+
+msgid "Custom"
+msgstr ""
+
+msgid "Custom CI config path"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Production"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Default Branch"
+msgstr ""
+
+msgid "Default classification label"
+msgstr ""
+
+msgid "Default: Directly import the Google Code email address or username"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete Package"
+msgstr ""
+
+msgid "Delete Snippet"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete list"
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployKeys|Write access allowed"
+msgstr ""
+
+msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Add a deploy token"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository"
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Copy username to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Deploy Tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|This project has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "DeployTokens|Use this username as a login."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|You are about to revoke"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group Runners"
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "Discard review"
+msgstr ""
+
+msgid "Discover GitLab Geo."
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss Cycle Analytics introduction box"
+msgstr ""
+
+msgid "Dismiss Merge Request promotion"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Each Runner can be in one of the following states:"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Elasticsearch"
+msgstr ""
+
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable SAML authentication for this group"
+msgstr ""
+
+msgid "Enable Sentry for error reporting and logging."
+msgstr ""
+
+msgid "Enable and configure InfluxDB metrics."
+msgstr ""
+
+msgid "Enable and configure Prometheus metrics."
+msgstr ""
+
+msgid "Enable classification control using an external service"
+msgstr ""
+
+msgid "Enable for this project"
+msgstr ""
+
+msgid "Enable group Runners"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable reCAPTCHA or Akismet and set IP limits."
+msgstr ""
+
+msgid "Enable the Performance Bar for a given group."
+msgstr ""
+
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter the issue description"
+msgstr ""
+
+msgid "Enter the issue title"
+msgstr ""
+
+msgid "Enter the merge request description"
+msgstr ""
+
+msgid "Enter the merge request title"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No pod name has been specified"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod logs from"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Read more about environments"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epic will be removed! Are you sure?"
+msgstr ""
+
+msgid "Epics"
+msgstr ""
+
+msgid "Epics Roadmap"
+msgstr ""
+
+msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
+msgstr ""
+
+msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgstr ""
+
+msgid "Epics|How can I solve this?"
+msgstr ""
+
+msgid "Epics|More information"
+msgstr ""
+
+msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+msgstr ""
+
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr ""
+
+msgid "Epics|due"
+msgstr ""
+
+msgid "Epics|start"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Reporting and Logging"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error fetching contributors data."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching usage ping data."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error updating status for all todos."
+msgstr ""
+
+msgid "Error updating todo status."
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "Every day (at 4:00am)"
+msgstr ""
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr ""
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
+msgid "Explore"
+msgstr ""
+
+msgid "Explore GitLab"
+msgstr ""
+
+msgid "Explore Groups"
+msgstr ""
+
+msgid "Explore groups"
+msgstr ""
+
+msgid "Explore projects"
+msgstr ""
+
+msgid "Explore public groups"
+msgstr ""
+
+msgid "External Classification Policy Authorization"
+msgstr ""
+
+msgid "External authentication"
+msgstr ""
+
+msgid "External authorization denied access to this project"
+msgstr ""
+
+msgid "External authorization request timeout"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification Label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to remove issue from board, please try again."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to update issues, please try again."
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fields on this page are now uneditable, you can configure"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Files (%{human_size})"
+msgstr ""
+
+msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
+msgid "Filter by commit message"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Find the downloaded ZIP file and decompress it."
+msgstr ""
+
+msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish review"
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "FirstPushedBy|First"
+msgstr ""
+
+msgid "FirstPushedBy|pushed by"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Follow the steps below to export your Google Code project data."
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Format"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
+msgid "From %{provider_title}"
+msgstr ""
+
+msgid "From Bitbucket"
+msgstr ""
+
+msgid "From Bitbucket Server"
+msgstr ""
+
+msgid "From FogBugz"
+msgstr ""
+
+msgid "From GitLab.com"
+msgstr ""
+
+msgid "From Google Code"
+msgstr ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "From milestones:"
+msgstr ""
+
+msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Nodes"
+msgstr ""
+
+msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is failing or broken."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
+msgstr ""
+
+msgid "GeoNodes|Checksummed"
+msgstr ""
+
+msgid "GeoNodes|Data is out of date from %{timeago}"
+msgstr ""
+
+msgid "GeoNodes|Data replication lag"
+msgstr ""
+
+msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "GeoNodes|Failed"
+msgstr ""
+
+msgid "GeoNodes|Full"
+msgstr ""
+
+msgid "GeoNodes|GitLab version"
+msgstr ""
+
+msgid "GeoNodes|GitLab version does not match the primary node version"
+msgstr ""
+
+msgid "GeoNodes|Health status"
+msgstr ""
+
+msgid "GeoNodes|Last event ID processed by cursor"
+msgstr ""
+
+msgid "GeoNodes|Last event ID seen from primary"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository verification"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki verification"
+msgstr ""
+
+msgid "GeoNodes|Loading nodes"
+msgstr ""
+
+msgid "GeoNodes|Local LFS objects"
+msgstr ""
+
+msgid "GeoNodes|Local attachments"
+msgstr ""
+
+msgid "GeoNodes|Local job artifacts"
+msgstr ""
+
+msgid "GeoNodes|New node"
+msgstr ""
+
+msgid "GeoNodes|Node Authentication was successfully repaired."
+msgstr ""
+
+msgid "GeoNodes|Node was successfully removed."
+msgstr ""
+
+msgid "GeoNodes|Not checksummed"
+msgstr ""
+
+msgid "GeoNodes|Out of sync"
+msgstr ""
+
+msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Replication slot WAL"
+msgstr ""
+
+msgid "GeoNodes|Replication slots"
+msgstr ""
+
+msgid "GeoNodes|Repositories"
+msgstr ""
+
+msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Repositories verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Repository verification progress"
+msgstr ""
+
+msgid "GeoNodes|Selective"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while changing node status"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while fetching nodes"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while removing node"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while repairing node"
+msgstr ""
+
+msgid "GeoNodes|Storage config"
+msgstr ""
+
+msgid "GeoNodes|Sync settings"
+msgstr ""
+
+msgid "GeoNodes|Synced"
+msgstr ""
+
+msgid "GeoNodes|Unused slots"
+msgstr ""
+
+msgid "GeoNodes|Unverified"
+msgstr ""
+
+msgid "GeoNodes|Used slots"
+msgstr ""
+
+msgid "GeoNodes|Verified"
+msgstr ""
+
+msgid "GeoNodes|Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Wiki verification progress"
+msgstr ""
+
+msgid "GeoNodes|Wikis"
+msgstr ""
+
+msgid "GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for forced re-download"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-check"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|All"
+msgstr ""
+
+msgid "Geo|All projects"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|File sync capacity"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Groups to synchronize"
+msgstr ""
+
+msgid "Geo|In sync"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|Not synced yet"
+msgstr ""
+
+msgid "Geo|Pending"
+msgstr ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Recheck"
+msgstr ""
+
+msgid "Geo|Recheck all projects"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Repository sync capacity"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all projects"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Select groups to replicate."
+msgstr ""
+
+msgid "Geo|Shards to synchronize"
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
+msgid "Geo|Unknown state"
+msgstr ""
+
+msgid "Geo|Verification capacity"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|You need a different license to use Geo replication"
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Git"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git strategy for pipelines"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitLab CI Linter has been moved"
+msgstr ""
+
+msgid "GitLab Geo"
+msgstr ""
+
+msgid "GitLab Group Runners can execute code for all the projects in this group."
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab single sign on URL"
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLab’s issue tracker"
+msgstr ""
+
+msgid "Gitaly"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go to"
+msgstr ""
+
+msgid "Go to %{link_to_google_takeout}."
+msgstr ""
+
+msgid "Google Code import"
+msgstr ""
+
+msgid "Google Takeout"
+msgstr ""
+
+msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group CI/CD settings"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group Runners"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group details"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group maintainers can register group runners in the %{link}"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Loading roadmap"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|Until %{dateWord}"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Customize your group badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about badges."
+msgstr ""
+
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+msgstr ""
+
+msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
+msgstr ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Create a project in this group."
+msgstr ""
+
+msgid "GroupsTree|Create a subgroup in this group."
+msgstr ""
+
+msgid "GroupsTree|Edit group"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave this group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Have your users email"
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help page"
+msgstr ""
+
+msgid "Help page text and support page url."
+msgstr ""
+
+msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide whitespace changes"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Client side evaluation"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Open in file view"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "Identity provider single sign on URL"
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr ""
+
+msgid "If disabled, the access level will depend on the user's permissions in the project."
+msgstr ""
+
+msgid "If enabled"
+msgstr ""
+
+msgid "If enabled, access to projects will be validated on an external service using their classification label."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you already have files you can push them using the %{link_to_cli} below."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import all compatible projects"
+msgstr ""
+
+msgid "Import all projects"
+msgstr ""
+
+msgid "Import all repositories"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import projects from Google Code"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "Improve Issue boards with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
+msgid "In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "Incompatible Project"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input your repository URL"
+msgstr ""
+
+msgid "Install GitLab Runner"
+msgstr ""
+
+msgid "Install Runner on Kubernetes"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Instance Statistics"
+msgstr ""
+
+msgid "Instance Statistics visibility"
+msgstr ""
+
+msgid "Instance does not support multiple Kubernetes clusters"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations Settings"
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Cycle Analytics"
+msgstr ""
+
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue board focus mode"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Job"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed in"
+msgstr ""
+
+msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration was not removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes configured"
+msgstr ""
+
+msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label lists show all issues with the selected label."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{name}"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
+msgstr ""
+
+msgid "Learn more about Kubernetes"
+msgstr ""
+
+msgid "Learn more about protected branches"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
+msgid "LicenseManagement|Approve license"
+msgstr ""
+
+msgid "LicenseManagement|Approve license?"
+msgstr ""
+
+msgid "LicenseManagement|Approved"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license?"
+msgstr ""
+
+msgid "LicenseManagement|Blacklisted"
+msgstr ""
+
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
+msgid "LicenseManagement|License"
+msgstr ""
+
+msgid "LicenseManagement|License Management"
+msgstr ""
+
+msgid "LicenseManagement|License details"
+msgstr ""
+
+msgid "LicenseManagement|License name"
+msgstr ""
+
+msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
+msgstr ""
+
+msgid "LicenseManagement|Packages"
+msgstr ""
+
+msgid "LicenseManagement|Remove license"
+msgstr ""
+
+msgid "LicenseManagement|Remove license?"
+msgstr ""
+
+msgid "LicenseManagement|Submit"
+msgstr ""
+
+msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
+msgstr ""
+
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseManagement|URL"
+msgstr ""
+
+msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LinkedIn"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "List Your Gitea Repositories"
+msgstr ""
+
+msgid "List available repositories"
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "List your GitHub repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked to current projects"
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make sure you're logged into the account that owns the projects you'd like to import."
+msgstr ""
+
+msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
+msgstr ""
+
+msgid "Manage Web IDE features"
+msgstr ""
+
+msgid "Manage access"
+msgstr ""
+
+msgid "Manage all notifications"
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a full email address"
+msgstr ""
+
+msgid "Map a Google Code user to a full name"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark todo as done"
+msgstr ""
+
+msgid "Markdown enabled"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
+msgid "Maven Metadata"
+msgstr ""
+
+msgid "Maven package"
+msgstr ""
+
+msgid "Max access level"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Median"
+msgstr ""
+
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Request:"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge requests"
+msgstr ""
+
+msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
+msgid "MergeRequests|Resolve this discussion in a new issue"
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|Toggle comments for this file"
+msgstr ""
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr ""
+
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Influx"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics|Business"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgstr ""
+
+msgid "Metrics|Environment"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgstr ""
+
+msgid "Metrics|Learn about environments"
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|Name"
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|No deployed environments"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|Query"
+msgstr ""
+
+msgid "Metrics|Response"
+msgstr ""
+
+msgid "Metrics|System"
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|Type"
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
+msgid "Milestone"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Mirror a repository"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror user"
+msgstr ""
+
+msgid "Mirrored repositories"
+msgstr ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
+msgid "Modal|Cancel"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More actions"
+msgstr ""
+
+msgid "More info"
+msgstr ""
+
+msgid "More information"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Multiple issue boards"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name your individual key via a title"
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Snippets"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No Label"
+msgstr ""
+
+msgid "No assignee"
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No container images stored for this project. Add one by following the instructions above."
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No issues for the selected time period."
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No merge requests for the selected time period."
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No packages stored for this project."
+msgstr ""
+
+msgid "No prioritised labels with such name or description"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No pushes for the selected time period."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No, directly import the existing email addresses and usernames."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "Not all comments are displayed because you're comparing two versions of the diff."
+msgstr ""
+
+msgid "Not all comments are displayed because you're viewing an old version of the diff."
+msgstr ""
+
+msgid "Not allowed to merge"
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not enough data"
+msgstr ""
+
+msgid "Not now"
+msgstr ""
+
+msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "Only admins"
+msgstr ""
+
+msgid "Only comments from the following commit are shown below"
+msgstr ""
+
+msgid "Only mirror protected branches"
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open in Xcode"
+msgstr ""
+
+msgid "Open projects"
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open source software to collaborate on code"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened MR"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Otherwise it is recommended you start with one of the options below."
+msgstr ""
+
+msgid "Outbound requests"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Package information"
+msgstr ""
+
+msgid "Package was removed"
+msgstr ""
+
+msgid "Packages"
+msgstr ""
+
+msgid "Pages"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
+
+msgid "Path, transfer, remove"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Paused Runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "Per job. If a job passes this threshold, it will be marked as failed"
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, or removing the group."
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline Health"
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline quota"
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines for last month"
+msgstr ""
+
+msgid "Pipelines for last week"
+msgstr ""
+
+msgid "Pipelines for last year"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|CI Lint"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgstr ""
+
+msgid "Pipelines|Get started with Pipelines"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|There are currently no %{scope} pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+msgstr ""
+
+msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Create for"
+msgstr ""
+
+msgid "Pipeline|Create pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Existing branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Search branches"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|all"
+msgstr ""
+
+msgid "Pipeline|success"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Please accept the Terms of Service before continuing."
+msgstr ""
+
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please solve the reCAPTCHA"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences|Navigation theme"
+msgstr ""
+
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Private - Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|Add status emoji"
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
+msgid "Profiles|Clear status"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Delete Account"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Delete your account?"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Website"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project avatar in repository: %{link}"
+msgstr ""
+
+msgid "Project details"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectLifecycle|Stage"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Customize your project badges."
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Learn more about badges."
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
+msgstr ""
+
+msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "PrometheusAlerts|Add alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Edit alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error creating alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error deleting alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error fetching alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error saving alert"
+msgstr ""
+
+msgid "PrometheusAlerts|No alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Operator"
+msgstr ""
+
+msgid "PrometheusAlerts|Threshold"
+msgstr ""
+
+msgid "PrometheusDashboard|Time"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration"
+msgstr ""
+
+msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
+msgstr ""
+
+msgid "PrometheusService|Common metrics"
+msgstr ""
+
+msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
+msgstr ""
+
+msgid "PrometheusService|Custom metrics"
+msgstr ""
+
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr ""
+
+msgid "PrometheusService|Finding custom metrics..."
+msgstr ""
+
+msgid "PrometheusService|Install Prometheus on clusters"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+msgstr ""
+
+msgid "PrometheusService|More information"
+msgstr ""
+
+msgid "PrometheusService|New metric"
+msgstr ""
+
+msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|Time-series monitoring service"
+msgstr ""
+
+msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
+msgstr ""
+
+msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
+msgstr ""
+
+msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote these project milestones into a group milestone."
+msgstr ""
+
+msgid "Promote to Group Milestone"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Environments"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "Protip:"
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Pseudonymizer data collection"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRule|Committer restriction"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
+
+msgid "Readme"
+msgstr ""
+
+msgid "Real-time features"
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Reference:"
+msgstr ""
+
+msgid "Refresh"
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Regenerate key"
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register and see your runners for this group."
+msgstr ""
+
+msgid "Register and see your runners for this project."
+msgstr ""
+
+msgid "Registry"
+msgstr ""
+
+msgid "Related Commits"
+msgstr ""
+
+msgid "Related Deployed Jobs"
+msgstr ""
+
+msgid "Related Issues"
+msgstr ""
+
+msgid "Related Jobs"
+msgstr ""
+
+msgid "Related Merge Requests"
+msgstr ""
+
+msgid "Related Merged Requests"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove Runner"
+msgstr ""
+
+msgid "Remove avatar"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
+msgid "Rename"
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Repair authentication"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{failedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|Class"
+msgstr ""
+
+msgid "Reports|Confidence"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository URL"
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirror"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Requests Profiles"
+msgstr ""
+
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
+msgid "Resolve all discussions in new issue"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve discussion"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal Variables"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
+msgid "Runner token"
+msgstr ""
+
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners API"
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, and even on your local machine."
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|You have used all your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML Single Sign On"
+msgstr ""
+
+msgid "SAML Single Sign On Settings"
+msgstr ""
+
+msgid "SAST"
+msgstr ""
+
+msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save variables"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scoped issue boards"
+msgstr ""
+
+msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or jump to…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in this group"
+msgstr ""
+
+msgid "SearchAutocomplete|in this project"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr ""
+
+msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgstr ""
+
+msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select a group to invite"
+msgstr ""
+
+msgid "Select a namespace to fork the project"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select an existing Kubernetes cluster or create a new one"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select branch/tag"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project and zone to choose machine type"
+msgstr ""
+
+msgid "Select project to choose zone"
+msgstr ""
+
+msgid "Select projects you want to import."
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Select the custom project template source group."
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Selective synchronization"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send usage data"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
+msgstr ""
+
+msgid "Session expiration, projects limit and attachment size."
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set instance-wide template repository"
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Sherlock Transactions"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show latest version of the diff"
+msgstr ""
+
+msgid "Show parent pages"
+msgstr ""
+
+msgid "Show parent subgroups"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|Change weight"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in to %{group_name}"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong when toggling the button"
+msgstr ""
+
+msgid "Something went wrong while closing the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while fetching %{listType} list"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the projects."
+msgstr ""
+
+msgid "Something went wrong while fetching the registry list."
+msgstr ""
+
+msgid "Something went wrong while reopening the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Sorry, no epics matched your search"
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "SortOptions|Access level, ascending"
+msgstr ""
+
+msgid "SortOptions|Access level, descending"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Milestone"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest joined"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source code"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Specific Runners"
+msgstr ""
+
+msgid "Specify an e-mail address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage & Commit"
+msgstr ""
+
+msgid "Stage all changes"
+msgstr ""
+
+msgid "Stage changes"
+msgstr ""
+
+msgid "Staged"
+msgstr ""
+
+msgid "Staged %{type}"
+msgstr ""
+
+msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start the Runner!"
+msgstr ""
+
+msgid "Start your trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Stop environment"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Sync information"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System header and footer:"
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "Tag (%{tag_count})"
+msgid_plural "Tags (%{tag_count})"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release notes"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag."
+msgstr ""
+
+msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Sort by"
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Test SAML SSO"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+msgid "Thanks! Don't show me this again"
+msgstr ""
+
+msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
+msgstr ""
+
+msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr ""
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The deployment of this job to %{environmentLink} did not succeed."
+msgstr ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr ""
+
+msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
+msgstr ""
+
+msgid "The phase of the development lifecycle."
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr ""
+
+msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
+msgstr ""
+
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr ""
+
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
+msgstr ""
+
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The tabs below will be removed in a future version"
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no merge requests to show"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
+
+msgid "There was an error adding a todo."
+msgstr ""
+
+msgid "There was an error deleting the todo."
+msgstr ""
+
+msgid "There was an error loading users activity calendar."
+msgstr ""
+
+msgid "There was an error saving your notification settings."
+msgstr ""
+
+msgid "There was an error subscribing to this label."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "They can be managed using the %{link}."
+msgstr ""
+
+msgid "Third party offers"
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
+msgstr ""
+
+msgid "This application was created by %{link_to_owner}."
+msgstr ""
+
+msgid "This application will be able to:"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This branch has changed since you started editing. Would you like to create a new branch?"
+msgstr ""
+
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This group"
+msgstr ""
+
+msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgstr ""
+
+msgid "This group does not provide any group Runners yet."
+msgstr ""
+
+msgid "This is a confidential issue."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is the author's first Merge Request to this project."
+msgstr ""
+
+msgid "This issue is confidential"
+msgstr ""
+
+msgid "This issue is confidential and locked."
+msgstr ""
+
+msgid "This issue is locked."
+msgstr ""
+
+msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "This job is the most recent deployment to %{link}."
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This option is disabled as you don't have write permissions for the current branch"
+msgstr ""
+
+msgid "This option is disabled while you still have unstaged changes"
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page will be removed in a future release."
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project does not belong to a group and can therefore not make use of group Runners."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "This source diff could not be displayed because it is too large."
+msgstr ""
+
+msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
+msgstr ""
+
+msgid "This will delete the custom metric, Are you sure?"
+msgstr ""
+
+msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time before enforced"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds ago"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip:"
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr ""
+
+msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
+msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr ""
+
+msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
+msgstr ""
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr ""
+
+msgid "To start serving your jobs you can add Runners to your group"
+msgstr ""
+
+msgid "To this GitLab instance"
+msgstr ""
+
+msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
+msgstr ""
+
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
+
+msgid "To widen your search, change or remove filters."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Todo"
+msgstr ""
+
+msgid "Todos"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle discussion"
+msgstr ""
+
+msgid "Toggle file browser"
+msgstr ""
+
+msgid "Toggle navigation"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: OFF"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: ON"
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Time"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track activity with Contribution Analytics."
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trigger"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Turn on Service Desk"
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to save your changes"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unresolve discussion"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
+msgid "Unstage all changes"
+msgstr ""
+
+msgid "Unstage changes"
+msgstr ""
+
+msgid "Unstaged"
+msgstr ""
+
+msgid "Unstaged %{type}"
+msgstr ""
+
+msgid "Unstaged and staged %{type}"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Upgrade your plan to activate Advanced Global Search."
+msgstr ""
+
+msgid "Upgrade your plan to activate Contribution Analytics."
+msgstr ""
+
+msgid "Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Upgrade your plan to activate Issue weight."
+msgstr ""
+
+msgid "Upgrade your plan to improve Issue boards."
+msgstr ""
+
+msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage ping is not enabled"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "Use <code>%{native_redirect_uri}</code> for local tests"
+msgstr ""
+
+msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
+msgstr ""
+
+msgid "Use group milestones to manage issues from multiple projects in the same milestone."
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use the following registration token during setup:"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "Used by members to sign in to your group in GitLab"
+msgstr ""
+
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Variables"
+msgstr ""
+
+msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification information"
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View epics list"
+msgstr ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View group labels"
+msgstr ""
+
+msgid "View issue"
+msgstr ""
+
+msgid "View it on GitLab"
+msgstr ""
+
+msgid "View jobs"
+msgstr ""
+
+msgid "View labels"
+msgstr ""
+
+msgid "View log"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr ""
+
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|It is recommended to install %{markdown} so that GFM features render locally:"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgstr ""
+
+msgid "WikiMarkdownDocs|documentation"
+msgstr ""
+
+msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgstr ""
+
+msgid "WikiNewPagePlaceholder|how-to-setup"
+msgstr ""
+
+msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiNewPageTitle|New Wiki Page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgstr ""
+
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPageConflictMessage|the page"
+msgstr ""
+
+msgid "WikiPageCreate|Create %{page_title}"
+msgstr ""
+
+msgid "WikiPageEdit|Update %{page_title}"
+msgstr ""
+
+msgid "WikiPage|Page slug"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wiki|Create Page"
+msgstr ""
+
+msgid "Wiki|Create page"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|More Pages"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, let me map Google Code users to full names or GitLab users."
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
+msgstr ""
+
+msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You can %{linkStart}view the blob%{linkEnd} instead."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
+msgid "You can only edit files when you are on a branch"
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
+msgstr ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+msgstr ""
+
+msgid "You cannot write to this read-only GitLab instance."
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You must accept our Terms of Service and privacy policy in order to register an account"
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're receiving this email because %{reason}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your Todos"
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your comment will not be visible to the public."
+msgstr ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your projects"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "among other things"
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{namespace} is affected by %{vulnerability}."
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr ""
+
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr ""
+
+msgid "ciReport|(is loading)"
+msgstr ""
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr ""
+
+msgid "ciReport|Class"
+msgstr ""
+
+msgid "ciReport|Code quality"
+msgstr ""
+
+msgid "ciReport|Confidence"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Description"
+msgstr ""
+
+msgid "ciReport|Dismiss vulnerability"
+msgstr ""
+
+msgid "ciReport|Dismissed by"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|File"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Identifiers"
+msgstr ""
+
+msgid "ciReport|Instances"
+msgstr ""
+
+msgid "ciReport|Learn more about interacting with security reports (Alpha)."
+msgstr ""
+
+msgid "ciReport|License management detected %d license for the source branch only"
+msgid_plural "ciReport|License management detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected %d new license"
+msgid_plural "ciReport|License management detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected no licenses for the source branch only"
+msgstr ""
+
+msgid "ciReport|License management detected no new licenses"
+msgstr ""
+
+msgid "ciReport|Links"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|Method"
+msgstr ""
+
+msgid "ciReport|Namespace"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No changes to performance metrics"
+msgstr ""
+
+msgid "ciReport|Performance metrics"
+msgstr ""
+
+msgid "ciReport|Revert dismissal"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Severity"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error loading DAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading SAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading container scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error loading dependency scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "ciReport|on pipeline"
+msgstr ""
+
+msgid "command line instructions"
+msgstr ""
+
+msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgstr ""
+
+msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
+msgstr ""
+
+msgid "connecting"
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "customize"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "deploy token"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "here"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "importing"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "issue boards"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "license management"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|Add approval"
+msgstr ""
+
+msgid "mrWidget|Allows commits from members who can merge to the target branch"
+msgstr ""
+
+msgid "mrWidget|An error occured while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Cancel automatic merge"
+msgstr ""
+
+msgid "mrWidget|Check out branch"
+msgstr ""
+
+msgid "mrWidget|Checking ability to merge automatically"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes"
+msgstr ""
+
+msgid "mrWidget|Create an issue to resolve them later"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mentions"
+msgstr ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge request approved"
+msgstr ""
+
+msgid "mrWidget|Merge request approved; you can approve additionally"
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|No Approval required"
+msgstr ""
+
+msgid "mrWidget|No Approval required; you can still approve"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove Source Branch"
+msgstr ""
+
+msgid "mrWidget|Remove source branch"
+msgstr ""
+
+msgid "mrWidget|Remove your approval"
+msgstr ""
+
+msgid "mrWidget|Request to merge"
+msgstr ""
+
+msgid "mrWidget|Requires 1 more approval"
+msgid_plural "mrWidget|Requires %d more approvals"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Requires 1 more approval by"
+msgid_plural "mrWidget|Requires %d more approvals by"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Set by"
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The changes will be merged into"
+msgstr ""
+
+msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+msgstr ""
+
+msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
+msgstr ""
+
+msgid "mrWidget|The source branch has been removed"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will be removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will not be removed"
+msgstr ""
+
+msgid "mrWidget|There are merge conflicts"
+msgstr ""
+
+msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|This merge request is in the process of being merged"
+msgstr ""
+
+msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr ""
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|You can remove source branch now"
+msgstr ""
+
+msgid "mrWidget|branch does not exist."
+msgstr ""
+
+msgid "mrWidget|command line"
+msgstr ""
+
+msgid "mrWidget|into"
+msgstr ""
+
+msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "notification emails"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "password"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "source"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time spent."
+msgstr ""
+
+msgid "started"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "toggle collapse"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "within %d minute "
+msgid_plural "within %d minutes "
+msgstr[0] ""
+msgstr[1] ""
+
diff --git a/locale/nl_NL/gitlab.po b/locale/nl_NL/gitlab.po
index 8234f120676..6b7e84d0af6 100644
--- a/locale/nl_NL/gitlab.po
+++ b/locale/nl_NL/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Dutch\n"
"Language: nl_NL\n"
"MIME-Version: 1.0\n"
@@ -13,10 +13,10 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: nl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:32\n"
+"PO-Revision-Date: 2018-11-19 17:22\n"
msgid " Status"
-msgstr ""
+msgstr " Status"
msgid " and"
msgstr " en"
@@ -31,6 +31,14 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] "%d gewijzigd bestand"
@@ -46,6 +54,11 @@ msgid_plural "%d commits behind"
msgstr[0] "%d commit achterlopend"
msgstr[1] "%d commits achterlopend"
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d exporter"
@@ -83,18 +96,13 @@ msgstr[1] "%d statistieken"
msgid "%d staged change"
msgid_plural "%d staged changes"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d bepaalde wijziging"
+msgstr[1] "%d bepaalde wijzigingen"
msgid "%d unstaged change"
msgid_plural "%d unstaged changes"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d onbepaalde wijziging"
+msgstr[1] "%d onbepaalde wijzigingen"
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
@@ -104,17 +112,31 @@ msgstr[1] "%s andere commits zijn weggelaten om prestatieproblemen te voorkomen.
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
-msgid "%{commit_author_link} authored %{commit_timeago}"
+msgid "%{authorsName}'s discussion"
msgstr ""
+msgid "%{commit_author_link} authored %{commit_timeago}"
+msgstr "%{commit_author_link} schreef %{commit_timeago}"
+
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] "%{count} deelnemer"
msgstr[1] "%{count} deelnemers"
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{filePath} deleted"
msgstr "%{filePath} verwijderd"
@@ -124,6 +146,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Gestart"
@@ -139,23 +164,12 @@ msgstr "%{nip_domain} kan worden gebruikt als een alternatief voor een eigen dom
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{number_commits_behind} commits achter %{default_branch}, %{number_commits_ahead} commits voor"
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr "%{number_of_failures} van %{maximum_failures} mislukte pogingen. GitLab zal toegang verlenen bij de volgende poging."
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr ""
-
msgid "%{openOrClose} %{noteable}"
msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
msgstr "%{percent}%% compleet"
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -167,27 +181,13 @@ msgstr "%{text} is beschikbaar"
msgid "%{title} changes"
msgstr "%{title} wijzigingen"
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -314,6 +314,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr ""
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -356,13 +365,10 @@ msgstr "Toegangstokens"
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
-msgstr ""
-
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgid "Access expiration date"
msgstr ""
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -392,27 +398,48 @@ msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
-msgstr "Licentie toevoegen"
+msgid "Add Kubernetes cluster"
+msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr "Nieuwe map toevoegen"
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -422,6 +449,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -455,9 +485,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -494,12 +521,17 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr ""
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "All"
msgstr "Alles"
@@ -515,6 +547,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -524,6 +559,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -539,6 +580,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -560,7 +604,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -584,6 +628,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -596,6 +646,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -608,6 +661,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -635,6 +691,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -677,12 +736,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr ""
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -701,7 +766,7 @@ msgstr "Uiterlijk"
msgid "Application"
msgstr "Applicatie"
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -719,9 +784,15 @@ msgstr ""
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -740,6 +811,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -878,6 +952,9 @@ msgstr ""
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -914,9 +991,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -995,6 +1069,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1285,6 +1368,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1315,9 +1401,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1372,7 +1455,7 @@ msgstr "Grafieken"
msgid "Chat"
msgstr "Chat"
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1399,6 +1482,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1429,6 +1518,9 @@ msgstr "geannuleerd"
msgid "CiStatusLabel|created"
msgstr "gemaakt"
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr "mislukt"
@@ -1447,6 +1539,9 @@ msgstr ""
msgid "CiStatusLabel|skipped"
msgstr "overgeslagen"
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr ""
@@ -1459,6 +1554,9 @@ msgstr ""
msgid "CiStatusText|created"
msgstr "gemaakt"
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr ""
@@ -1513,10 +1611,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1561,6 +1659,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1573,12 +1674,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1609,10 +1722,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1639,6 +1752,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1675,6 +1794,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1705,9 +1827,6 @@ msgstr ""
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1729,25 +1848,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster details"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster health"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1759,7 +1872,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1768,16 +1881,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1795,9 +1905,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1825,6 +1932,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1837,6 +1947,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1867,9 +1980,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1909,13 +2019,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -1933,6 +2040,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -1951,9 +2061,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -1963,6 +2070,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -1972,12 +2082,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr "Opmerkingen"
@@ -2012,6 +2128,9 @@ msgstr "Commit"
msgid "CommitMessage|Add %{file_name}"
msgstr "%{file_name} toevoegen"
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr "Commits"
@@ -2084,7 +2203,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2093,10 +2212,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2186,6 +2305,9 @@ msgstr ""
msgid "Contribution guide"
msgstr ""
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2219,6 +2341,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2240,15 +2374,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2324,7 +2470,7 @@ msgstr ""
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
+msgid "Create your first page"
msgstr ""
msgid "CreateTag|Tag"
@@ -2375,6 +2521,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -2393,6 +2542,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr ""
@@ -2444,6 +2596,9 @@ msgstr ""
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2456,6 +2611,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr ""
@@ -2465,6 +2635,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2602,6 +2775,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2626,6 +2805,12 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2647,12 +2832,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2668,6 +2868,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2749,7 +2952,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2794,9 +2997,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2809,6 +3009,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2911,7 +3117,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -2944,10 +3150,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3058,6 +3264,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3112,6 +3324,12 @@ msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3121,6 +3339,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3130,6 +3351,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3139,6 +3435,9 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr ""
@@ -3151,9 +3450,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr ""
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr ""
@@ -3169,6 +3477,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3181,7 +3492,7 @@ msgstr ""
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3220,17 +3531,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -3246,6 +3558,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3288,6 +3603,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3462,10 +3780,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3474,6 +3804,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3495,7 +3828,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3507,6 +3840,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3516,19 +3852,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3546,6 +3888,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3558,9 +3906,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3570,9 +3936,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3639,12 +4002,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr ""
-
-msgid "GoToYourFork|Fork"
-msgstr ""
-
msgid "Google Code import"
msgstr ""
@@ -3675,9 +4032,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3687,6 +4056,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3705,13 +4077,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3738,9 +4110,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3798,6 +4167,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3810,19 +4182,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -3864,6 +4236,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4028,6 +4403,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4096,6 +4474,12 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4120,6 +4504,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4135,9 +4549,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4174,7 +4585,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4192,12 +4603,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4270,6 +4675,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
@@ -4281,12 +4689,18 @@ msgstr ""
msgid "Last commit"
msgstr ""
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4335,6 +4749,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4344,6 +4767,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4353,6 +4779,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4362,6 +4791,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4374,9 +4806,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4403,6 +4841,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4448,6 +4889,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4517,13 +4961,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4535,6 +5009,12 @@ msgstr ""
msgid "Median"
msgstr ""
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -4568,6 +5048,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4577,9 +5072,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4589,6 +5081,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4604,6 +5102,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4820,6 +5321,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -4939,6 +5443,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -4948,9 +5458,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -4960,6 +5467,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -4987,6 +5497,9 @@ msgstr ""
msgid "No repository"
msgstr ""
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr ""
@@ -5023,6 +5536,9 @@ msgstr ""
msgid "Not enough data"
msgstr ""
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -5041,6 +5557,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -5113,9 +5641,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5142,9 +5667,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5166,6 +5688,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5190,6 +5715,21 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5256,6 +5796,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5283,13 +5826,13 @@ msgstr ""
msgid "Permissions"
msgstr ""
-msgid "Personal Access Token"
+msgid "Permissions, LFS, 2FA"
msgstr ""
-msgid "Pipeline"
+msgid "Personal Access Token"
msgstr ""
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
+msgid "Pipeline"
msgstr ""
msgid "Pipeline Health"
@@ -5409,15 +5952,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5427,6 +5979,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5454,12 +6012,6 @@ msgstr ""
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5469,12 +6021,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5487,6 +6045,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5499,9 +6060,18 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5547,15 +6117,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5568,39 +6153,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -5610,6 +6276,15 @@ msgstr ""
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5646,6 +6321,9 @@ msgstr ""
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr ""
@@ -5673,6 +6351,9 @@ msgstr ""
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -5700,6 +6381,27 @@ msgstr ""
msgid "ProjectLifecycle|Stage"
msgstr ""
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5742,6 +6444,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5811,9 +6516,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6006,6 +6708,12 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6068,12 +6776,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6083,6 +6800,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6092,18 +6812,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6116,6 +6851,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6149,10 +6887,10 @@ msgstr ""
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6170,9 +6908,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6223,9 +6973,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6235,6 +7000,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6259,6 +7030,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6283,6 +7057,9 @@ msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -6337,15 +7114,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6370,27 +7156,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard"
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6408,9 +7222,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr ""
@@ -6441,6 +7261,9 @@ msgstr ""
msgid "Select target branch"
msgstr ""
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6453,6 +7276,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6477,6 +7303,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6495,7 +7324,10 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
@@ -6507,13 +7339,31 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "Settings"
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
msgstr ""
msgid "Share"
@@ -6525,6 +7375,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6608,12 +7461,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6641,9 +7500,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6656,12 +7521,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -6692,6 +7569,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6722,6 +7602,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6752,6 +7635,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6827,9 +7713,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6842,6 +7740,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6851,6 +7752,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6860,9 +7764,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6875,6 +7785,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -6893,6 +7809,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -6997,6 +7916,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7045,12 +7967,6 @@ msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7099,9 +8015,6 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr ""
@@ -7111,21 +8024,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr ""
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7135,6 +8042,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7144,7 +8054,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7192,10 +8108,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7216,6 +8135,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7255,7 +8177,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7276,6 +8201,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
@@ -7300,6 +8228,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7309,6 +8240,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7336,9 +8273,15 @@ msgstr ""
msgid "Time before an issue starts implementation"
msgstr ""
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr ""
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7529,12 +8472,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7550,6 +8505,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7562,12 +8520,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7577,9 +8538,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7595,6 +8562,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7610,6 +8580,9 @@ msgstr ""
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7619,6 +8592,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7637,24 +8613,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7670,6 +8664,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7703,13 +8703,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7739,15 +8742,15 @@ msgstr ""
msgid "Upload file"
msgstr ""
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr ""
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7775,6 +8778,9 @@ msgstr ""
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7784,10 +8790,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7814,6 +8862,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7847,9 +8904,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7868,6 +8931,36 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -7907,6 +9000,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8057,6 +9156,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8075,9 +9177,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8087,9 +9186,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8111,12 +9207,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8138,9 +9240,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr ""
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8150,6 +9249,12 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr ""
@@ -8216,6 +9321,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8237,16 +9345,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "assign yourself"
msgstr ""
@@ -8274,61 +9372,78 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8361,9 +9476,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8386,6 +9498,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8404,13 +9519,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8419,9 +9528,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8452,9 +9558,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8466,9 +9569,6 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8498,25 +9598,17 @@ msgstr[1] ""
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
-
msgid "disabled"
msgstr ""
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "enabled"
msgstr ""
@@ -8526,6 +9618,12 @@ msgstr ""
msgid "for this project"
msgstr ""
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -8555,6 +9653,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8783,6 +9884,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8801,6 +9905,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr ""
@@ -8829,6 +9936,11 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "remaining"
msgstr ""
@@ -8841,6 +9953,11 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "source"
msgstr ""
@@ -8856,6 +9973,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/pl_PL/gitlab.po b/locale/pl_PL/gitlab.po
index 6cc1b4472c7..82baa725e8d 100644
--- a/locale/pl_PL/gitlab.po
+++ b/locale/pl_PL/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Polish\n"
"Language: pl_PL\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: pl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:31\n"
+"PO-Revision-Date: 2018-11-19 17:18\n"
msgid " Status"
msgstr ""
@@ -35,6 +35,16 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -56,6 +66,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -119,13 +136,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] ""
@@ -136,12 +146,21 @@ msgstr[3] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] ""
@@ -149,6 +168,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -158,6 +184,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -173,25 +202,12 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr ""
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr ""
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -205,35 +221,13 @@ msgstr ""
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -382,6 +376,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr ""
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -424,13 +427,10 @@ msgstr ""
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
+msgid "Access expiration date"
msgstr ""
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr ""
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -460,27 +460,48 @@ msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
+msgid "Add Kubernetes cluster"
msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -490,6 +511,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -523,9 +547,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -562,12 +583,19 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr ""
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "All"
msgstr ""
@@ -583,6 +611,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -592,6 +623,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -607,6 +644,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -628,7 +668,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -652,6 +692,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -664,6 +710,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -676,6 +725,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -703,6 +755,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -745,12 +800,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr ""
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -769,7 +830,7 @@ msgstr ""
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -787,9 +848,15 @@ msgstr ""
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -808,6 +875,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -946,6 +1016,9 @@ msgstr ""
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -982,9 +1055,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -1063,6 +1133,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1355,6 +1434,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1385,9 +1467,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1442,7 +1521,7 @@ msgstr ""
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1469,6 +1548,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1499,6 +1584,9 @@ msgstr ""
msgid "CiStatusLabel|created"
msgstr ""
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr ""
@@ -1517,6 +1605,9 @@ msgstr ""
msgid "CiStatusLabel|skipped"
msgstr ""
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr ""
@@ -1529,6 +1620,9 @@ msgstr ""
msgid "CiStatusText|created"
msgstr ""
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr ""
@@ -1583,10 +1677,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1631,6 +1725,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1643,12 +1740,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1679,10 +1788,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1709,6 +1818,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1745,6 +1860,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1775,9 +1893,6 @@ msgstr ""
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1799,25 +1914,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster details"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster health"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1829,7 +1938,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1838,16 +1947,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1865,9 +1971,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1895,6 +1998,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1907,6 +2013,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1937,9 +2046,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1979,13 +2085,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -2003,6 +2106,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -2021,9 +2127,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -2033,6 +2136,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -2042,12 +2148,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2086,6 +2198,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr ""
@@ -2158,7 +2273,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2167,10 +2282,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2260,6 +2375,9 @@ msgstr ""
msgid "Contribution guide"
msgstr ""
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2293,6 +2411,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2314,15 +2444,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2398,7 +2540,7 @@ msgstr ""
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
+msgid "Create your first page"
msgstr ""
msgid "CreateTag|Tag"
@@ -2449,6 +2591,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -2467,6 +2612,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr ""
@@ -2518,6 +2666,9 @@ msgstr ""
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2530,6 +2681,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr ""
@@ -2539,6 +2705,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2678,6 +2847,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2702,6 +2877,12 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2723,12 +2904,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2744,6 +2940,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2825,7 +3024,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2870,9 +3069,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2885,6 +3081,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2987,7 +3189,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -3020,10 +3222,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3134,6 +3336,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3188,6 +3396,12 @@ msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3197,6 +3411,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3206,6 +3423,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3215,6 +3507,9 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr ""
@@ -3227,9 +3522,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr ""
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr ""
@@ -3245,6 +3549,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3257,7 +3564,7 @@ msgstr ""
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3296,19 +3603,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -3324,6 +3630,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3366,6 +3675,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3540,10 +3852,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3552,6 +3876,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3573,7 +3900,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3585,6 +3912,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3594,19 +3924,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3624,6 +3960,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3636,9 +3978,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3648,9 +4008,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3717,12 +4074,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr ""
-
-msgid "GoToYourFork|Fork"
-msgstr ""
-
msgid "Google Code import"
msgstr ""
@@ -3753,9 +4104,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3765,6 +4128,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3783,13 +4149,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3816,9 +4182,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3876,6 +4239,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3888,19 +4254,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -3942,6 +4308,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4108,6 +4477,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4178,6 +4550,12 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4202,6 +4580,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4217,9 +4625,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4256,7 +4661,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4274,12 +4679,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4352,6 +4751,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
@@ -4365,12 +4767,18 @@ msgstr ""
msgid "Last commit"
msgstr ""
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4419,6 +4827,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4428,6 +4845,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4437,6 +4857,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4446,6 +4869,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4458,9 +4884,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4489,6 +4921,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4534,6 +4969,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4603,13 +5041,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4621,6 +5089,12 @@ msgstr ""
msgid "Median"
msgstr ""
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -4654,6 +5128,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4663,9 +5152,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4675,6 +5161,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4690,6 +5182,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4906,6 +5401,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -5027,6 +5525,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -5036,9 +5540,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -5048,6 +5549,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5075,6 +5579,9 @@ msgstr ""
msgid "No repository"
msgstr ""
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr ""
@@ -5111,6 +5618,9 @@ msgstr ""
msgid "Not enough data"
msgstr ""
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -5129,6 +5639,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -5201,9 +5723,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5232,9 +5751,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5256,6 +5772,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5280,6 +5799,21 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5346,6 +5880,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5373,13 +5910,13 @@ msgstr ""
msgid "Permissions"
msgstr ""
-msgid "Personal Access Token"
+msgid "Permissions, LFS, 2FA"
msgstr ""
-msgid "Pipeline"
+msgid "Personal Access Token"
msgstr ""
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
+msgid "Pipeline"
msgstr ""
msgid "Pipeline Health"
@@ -5499,15 +6036,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5517,6 +6063,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5544,12 +6096,6 @@ msgstr ""
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5559,12 +6105,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5577,6 +6129,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5589,9 +6144,18 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5637,15 +6201,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5658,39 +6237,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -5700,6 +6360,15 @@ msgstr ""
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5736,6 +6405,9 @@ msgstr ""
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr ""
@@ -5763,6 +6435,9 @@ msgstr ""
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -5790,6 +6465,27 @@ msgstr ""
msgid "ProjectLifecycle|Stage"
msgstr ""
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5832,6 +6528,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5901,9 +6600,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6096,6 +6792,12 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6160,12 +6862,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6175,6 +6886,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6184,18 +6898,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6208,6 +6937,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6241,10 +6973,10 @@ msgstr ""
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6262,9 +6994,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6317,9 +7061,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6329,6 +7088,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6353,6 +7118,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6377,6 +7145,9 @@ msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -6431,15 +7202,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6464,29 +7244,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard"
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6504,9 +7310,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr ""
@@ -6537,6 +7349,9 @@ msgstr ""
msgid "Select target branch"
msgstr ""
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6549,6 +7364,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6573,6 +7391,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6591,7 +7412,10 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
@@ -6603,13 +7427,31 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "Settings"
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
msgstr ""
msgid "Share"
@@ -6621,6 +7463,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6706,12 +7551,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6739,9 +7590,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6754,12 +7611,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -6790,6 +7659,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6820,6 +7692,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6850,6 +7725,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6925,9 +7803,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6940,6 +7830,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6949,6 +7842,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6958,9 +7854,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6973,6 +7875,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -6991,6 +7899,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -7097,6 +8008,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7145,12 +8059,6 @@ msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7199,9 +8107,6 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr ""
@@ -7211,21 +8116,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr ""
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7235,6 +8134,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7244,7 +8146,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7292,10 +8200,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7316,6 +8227,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7355,7 +8269,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7376,6 +8293,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
@@ -7400,6 +8320,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7409,6 +8332,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7436,9 +8365,15 @@ msgstr ""
msgid "Time before an issue starts implementation"
msgstr ""
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr ""
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7633,12 +8568,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7654,6 +8601,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7666,12 +8616,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7681,9 +8634,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7699,6 +8658,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7714,6 +8676,9 @@ msgstr ""
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7723,6 +8688,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7741,24 +8709,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7774,6 +8760,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7807,13 +8799,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7843,15 +8838,15 @@ msgstr ""
msgid "Upload file"
msgstr ""
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr ""
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7879,6 +8874,9 @@ msgstr ""
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7888,10 +8886,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7918,6 +8958,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7951,9 +9000,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7972,6 +9027,36 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -8011,6 +9096,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8161,6 +9252,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8179,9 +9273,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8191,9 +9282,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8215,12 +9303,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8242,9 +9336,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr ""
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8254,6 +9345,12 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr ""
@@ -8320,6 +9417,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8341,20 +9441,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "assign yourself"
msgstr ""
@@ -8382,61 +9468,86 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8469,9 +9580,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8498,6 +9606,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8516,13 +9627,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8531,9 +9636,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8564,9 +9666,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8580,9 +9679,6 @@ msgstr[3] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8614,36 +9710,32 @@ msgstr[3] ""
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "disabled"
+msgstr ""
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "detected no vulnerabilities"
-msgstr ""
-
-msgid "disabled"
+msgid "enabled"
msgstr ""
-msgid "done"
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
msgstr ""
-msgid "enabled"
+msgid "for this project"
msgstr ""
-msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgid "from"
msgstr ""
-msgid "for this project"
+msgid "help"
msgstr ""
msgid "here"
@@ -8677,6 +9769,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8911,6 +10006,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8929,6 +10027,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr ""
@@ -8961,6 +10062,13 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "remaining"
msgstr ""
@@ -8973,6 +10081,13 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "source"
msgstr ""
@@ -8988,6 +10103,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index a0e18f2be2f..dac92fe616e 100644
--- a/locale/pt_BR/gitlab.po
+++ b/locale/pt_BR/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Portuguese, Brazilian\n"
"Language: pt_BR\n"
"MIME-Version: 1.0\n"
@@ -13,10 +13,10 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: pt-BR\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:31\n"
+"PO-Revision-Date: 2018-11-19 17:17\n"
msgid " Status"
-msgstr ""
+msgstr " Status"
msgid " and"
msgstr " e"
@@ -31,6 +31,14 @@ msgid_plural " improved on %d points"
msgstr[0] " melhorado em %d ponto"
msgstr[1] " melhorado em %d pontos"
+msgid "\"%{query}\" in projects"
+msgstr "\"%{query}\" em projetos"
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] "%d adição"
+msgstr[1] "%d adições"
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] "%d arquivo modificado"
@@ -46,6 +54,11 @@ msgid_plural "%d commits behind"
msgstr[0] "%d commit atrás"
msgstr[1] "%d commits atrás"
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] "%d excluído"
+msgstr[1] "%d excluídos"
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d exporter"
@@ -53,13 +66,13 @@ msgstr[1] "%d exporters"
msgid "%d failed test result"
msgid_plural "%d failed test results"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d resultado do teste com falha"
+msgstr[1] "%d resultados do teste com falha"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d resultado do teste corrigido"
+msgstr[1] "%d resultados do teste corrigidos"
msgid "%d issue"
msgid_plural "%d issues"
@@ -91,11 +104,6 @@ msgid_plural "%d unstaged changes"
msgstr[0] "%d mudança fora da lista de commit"
msgstr[1] "%d mudanças fora da lista de commit"
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] "%d vulnerabilidade"
-msgstr[1] "%d vulnerabilidades"
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] "%s commit adicional foi omitido para prevenir problemas de performance."
@@ -104,26 +112,43 @@ msgstr[1] "%s commits adicionais foram omitidos para prevenir problemas de perfo
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{authorsName}'s discussion"
+msgstr "Discussão de %{authorsName}"
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} fez commit %{commit_timeago}"
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr "%{counter_storage} (%{counter_repositories} repositórios, %{counter_build_artifacts} artefatos de build, %{counter_lfs_objects} LFS)"
+msgid "%{count} %{alerts}"
+msgstr "%{count} %{alerts}"
+
+msgid "%{count} more assignees"
+msgstr "mais %{count} responsáveis"
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] "%{count} participante"
msgstr[1] "%{count} participantes"
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] "%{count} comentário pendente"
+msgstr[1] "%{count} comentários pendentes"
+
msgid "%{filePath} deleted"
msgstr "%{filePath} excluído"
msgid "%{firstLabel} +%{labelCount} more"
-msgstr ""
+msgstr "%{firstLabel} +%{labelCount} mais"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}Grupos%{group_docs_link_end} permitem que você gerencie e colabore em vários projetos. Os membros de um grupo têm acesso a todos os seus projetos."
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr "%{issuableType} será removido! Você tem certeza?"
+
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Iniciado"
@@ -139,23 +164,12 @@ msgstr "%{nip_domain} pode ser utilizado como um domínio personalizado."
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{number_commits_behind} commits atrás de %{default_branch}, %{number_commits_ahead} commits à frente"
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr "%{number_of_failures} de %{maximum_failures} falhas. O GitLab permitirá o acesso na próxima tentativa."
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr "%{number_of_failures} de %{maximum_failures} falhas. O GitLab não tentará mais automaticamente. Redefina as informações de storage quando o problema for resolvido."
-
msgid "%{openOrClose} %{noteable}"
msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
msgstr "%{percent}%% completado"
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] "%{storage_name}: falha na tentativa de acesso ao storage no host:"
-msgstr[1] "%{storage_name}: %{failed_attempts} falhas de acesso ao storage:"
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] "%{text} %{files}"
@@ -167,29 +181,15 @@ msgstr "%{text} está disponível"
msgid "%{title} changes"
msgstr "Alterações de %{title}"
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] "%{type} detectou 1 vulnerabilidade"
-msgstr[1] "%{type} detectou %{vulnerabilityCount} vulnerabilidades"
-
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{unstaged} unstaged and %{staged} staged changes"
msgstr "%{unstaged} mudanças fora e %{staged} mudanças dentro da lista de commit"
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr "%{usage_ping_link_start}Saiba mais%{usage_ping_link_end} sobre quais informações são compartilhadas com o GitLab Inc."
+
+msgid "+ %{count} more"
+msgstr "+ %{count} mais"
+
msgid "+ %{moreCount} more"
msgstr "%{moreCount} mais"
@@ -224,8 +224,8 @@ msgstr[1] "%d merge requests fechados"
msgid "1 group"
msgid_plural "%d groups"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 grupo"
+msgstr[1] "%d grupos"
msgid "1 merged merge request"
msgid_plural "%d merged merge requests"
@@ -249,13 +249,13 @@ msgstr[1] "%d pipelines"
msgid "1 role"
msgid_plural "%d roles"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 papel"
+msgstr[1] "%d papéis"
msgid "1 user"
msgid_plural "%d users"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "1 usuário"
+msgstr[1] "%d usuários"
msgid "1st contribution!"
msgstr "1ª contribuição!"
@@ -314,6 +314,15 @@ msgstr "'Runner' é um processo que executa um job. Você pode configurar quanto
msgid "A collection of graphs regarding Continuous Integration"
msgstr "Uma coleção de gráficos sobre Integração Contínua"
+msgid "A default branch cannot be chosen for an empty project."
+msgstr "Um branch padrão não pode ser escolhido para um projeto vazio."
+
+msgid "A deleted user"
+msgstr "Um usuário excluído"
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr "Um membro da equipe de abusos GitLab irá rever a sua avaliação assim que possível."
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr "Um novo \"branch\" será criado no seu \"fork\" e um novo merge request será iniciado."
@@ -356,15 +365,12 @@ msgstr "Tokens de acesso"
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "Acesso negado! Por favor, verifique se você pode adicionar chaves de deploy neste repositório."
+msgid "Access expiration date"
+msgstr "Data de expiração do acesso"
+
msgid "Access to '%{classification_label}' not allowed"
msgstr "Acesso a '%{classification_label}' não permitido"
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr "Os acessos à storages com defeito foram temporariamente desabilitados para permitir a sua remontagem. Redefina as informações de armazenamento depois que o problema foi resolvido para permitir o acesso de novo."
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
-msgstr "Acesse seu runner token, personalize sua configuração de pipeline e visualize o status do seu pipeline e o relatório de coverage."
-
msgid "Account"
msgstr "Conta"
@@ -392,27 +398,48 @@ msgstr "Adicionar Guia de contribuição"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr "Adicione Webhooks de grupo e GitLab Enterprise Edition."
+msgid "Add Jaeger URL"
+msgstr "Adicionar URL Jaeger"
+
msgid "Add Kubernetes cluster"
msgstr "Adicionar cluster Kubernetes"
-msgid "Add License"
-msgstr "Adicionar Licença"
-
msgid "Add Readme"
msgstr "Adicionar leia-me"
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr "Adicione uma homepage ao seu wiki que contenha informações sobre o seu projeto e o GitLab irá exibi-lo aqui ao invés desta mensagem."
+
+msgid "Add a table"
+msgstr "Adicionar uma tabela"
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Coloque um texto adicional para aparecer em todas as comunicações por email. Limite de %{character_limit} caracteres"
+msgid "Add comment now"
+msgstr "Adicionar comentário"
+
+msgid "Add image comment"
+msgstr "Adicionar comentário de imagem"
+
+msgid "Add license"
+msgstr "Adicionar licença"
+
msgid "Add new application"
msgstr "Adicionar novo aplicativo"
msgid "Add new directory"
msgstr "Adicionar novo diretório"
+msgid "Add projects"
+msgstr "Adicionar projetos"
+
msgid "Add reaction"
msgstr "Adicionar reação"
+msgid "Add to review"
+msgstr "Adicionar à revisão"
+
msgid "Add todo"
msgstr "Adicionar tarefa"
@@ -422,6 +449,9 @@ msgstr "Adicionar usuário(s) ao grupo:"
msgid "Add users to group"
msgstr "Adicionar usuários ao grupo"
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr "Texto adicional"
@@ -435,7 +465,7 @@ msgid "Admin area"
msgstr "Ãrea do administrador"
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Você está prestes a excluir permanentemente o usuário %{username}. Issues, merge requests, e grupos vinculados a ele serão transferidos para um \"usuário fantasma\" em todo o sistema. Para evitar a perda de dados, considere o uso do recurso %{strong_start}bloquear usuário%{strong_end}. Depois de %{strong_start}Deletar o usuário%{strong_end}, não será possível desfazer ou recuperá-lo."
msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -455,9 +485,6 @@ msgstr "Erro ao parar processos"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "Você parará todos os processos. Os processos em execução serão abruptamente interrompidos."
-msgid "AdminHealthPageLink|health page"
-msgstr "página de saúde"
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -494,12 +521,17 @@ msgstr "Para confirmar, digite %{projectName}"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "Para confirmar, digite %{username}"
-msgid "Advanced"
-msgstr "Avançado"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
msgid "Advanced settings"
msgstr "Configurações avançadas"
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] "Alerta"
+msgstr[1] "Alertas"
+
msgid "All"
msgstr "Todos"
@@ -510,11 +542,14 @@ msgid "All features are enabled for blank projects, from templates, or when impo
msgstr "Todas as funcionalidades estão habilitadas para projetos em branco, a partir de templates ou ao importar, mas você pode desativá-los posteriormente nas configurações do projeto."
msgid "All users"
-msgstr ""
+msgstr "Todos os usuários"
msgid "Allow commits from members who can merge to the target branch."
msgstr "Permitir commits de membros que podem fazer merge ao branch de destino."
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr "Permitir acesso público aos pipelines e detalhes de trabalho, incluindo logs de saída e artefatos"
@@ -524,6 +559,12 @@ msgstr "Permitir renderização de diagramas PlantUML em documentos Asciidoc."
msgid "Allow requests to the local network from hooks and services."
msgstr "Permitir requisições de hooks e serviços para a rede local."
+msgid "Allow users to request access"
+msgstr "Permitir que os usuários solicitem acesso"
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr "Permitir que os usuários solicitem acesso se a visibilidade for pública ou interna."
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Permite adicionar e gerenciar clusters do Kubernetes."
@@ -539,9 +580,12 @@ msgstr "Alternativamente, você pode usar um %{personal_access_token_link}. Quan
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr "Alternativamente, você pode usar um %{personal_access_token_link}. Quando você cria seu Token de Acesso Pessoal, você precisará selecionar o escopo do <code>repositório</code>, para que possamos exibir uma lista de seus repositórios públicos e privados que estão disponíveis para se importar."
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgstr "Uma chave SSH será gerada automaticamente quando o formulário for enviado. Para mais informações, consulte a documentação."
+
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr "Um aplicativo chamado %{link_to_client} está solicitando acesso à sua conta do GitLab."
@@ -560,8 +604,8 @@ msgstr "Um erro ocorreu ao criar o novo branch."
msgid "An error occured whilst fetching the job trace."
msgstr "Ocorreu um erro ao carregar o rastro da tarefa."
-msgid "An error occured whilst fetching the latest pipline."
-msgstr "Ocorreu um erro ao carregar o último pipeline."
+msgid "An error occured whilst fetching the latest pipeline."
+msgstr ""
msgid "An error occured whilst loading all the files."
msgstr "Um erro ocorreu no carregamento de todos os arquivos."
@@ -584,6 +628,12 @@ msgstr "Ocorreu um erro ao carregar as alterações do merge request."
msgid "An error occured whilst loading the pipelines jobs."
msgstr "Ocorreu um erro ao carregar as tarefas de pipeline."
+msgid "An error occurred adding a draft to the discussion."
+msgstr "Ocorreu um erro ao adicionar um rascunho à discussão."
+
+msgid "An error occurred adding a new draft."
+msgstr "Ocorreu um erro ao adicionar um novo rascunho."
+
msgid "An error occurred previewing the blob"
msgstr "Erro ao pré-visualizar o blob"
@@ -596,6 +646,9 @@ msgstr "Ocorreu um erro ao atualizar o peso do issue"
msgid "An error occurred while adding approver"
msgstr "Ocorreu um erro ao adicionar o aprovador"
+msgid "An error occurred while deleting the comment"
+msgstr "Ocorreu um erro ao remover o comentário"
+
msgid "An error occurred while detecting host keys"
msgstr "Ocorreu um erro ao detectar as chaves do host"
@@ -608,20 +661,23 @@ msgstr "Erro ao remover alerta. Atualize a página e tente novamente."
msgid "An error occurred while fetching markdown preview"
msgstr "Erro ao gerar pré-visualização do markdown"
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Erro ao recuperar informações da barra lateral"
msgid "An error occurred while fetching stages."
-msgstr ""
+msgstr "Ocorreu um erro o enquanto busca estágios."
msgid "An error occurred while fetching the job log."
-msgstr ""
+msgstr "Ocorreu um erro enquanto busca logs do job."
msgid "An error occurred while fetching the job."
-msgstr ""
+msgstr "Ocorreu um erro enquanto busca o trabalho."
msgid "An error occurred while fetching the jobs."
-msgstr ""
+msgstr "Ocorreu um erro enquanto busca os trabalhos."
msgid "An error occurred while fetching the pipeline."
msgstr "Erro ao recuperar informações da pipeline."
@@ -630,11 +686,14 @@ msgid "An error occurred while getting projects"
msgstr "Erro ao recuperar projetos"
msgid "An error occurred while importing project: %{details}"
-msgstr ""
+msgstr "Ocorreu um erro ao importar projeto: %{details}"
msgid "An error occurred while initializing path locks"
msgstr "Ocorreu um erro ao inicializar travas de caminhos"
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "Erro ao carregar as assinaturas de commit"
@@ -677,12 +736,18 @@ msgstr "Ocorreu um erro ao inscrever às notificações."
msgid "An error occurred while unsubscribing to notifications."
msgstr "Ocorreu um erro ao desinscrever às notificações."
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr "Erro ao validar o nome de usuário"
msgid "An error occurred. Please try again."
msgstr "Ocorreu um erro. Tente novamente."
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr "Anônimo"
@@ -701,8 +766,8 @@ msgstr "Aparência"
msgid "Application"
msgstr "Aplicativo"
-msgid "Application Id"
-msgstr "ID do aplicativo"
+msgid "Application ID"
+msgstr ""
msgid "Application: %{name}"
msgstr "Aplicativo: %{name}"
@@ -719,9 +784,15 @@ msgstr "Abril"
msgid "Archived project! Repository and other project resources are read-only"
msgstr "Projeto arquivado! Repositório e outros recursos de projeto são somente leitura"
+msgid "Archived projects"
+msgstr "Projetos arquivados"
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Tem certeza que deseja excluir este agendamento de pipeline?"
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "Você tem certeza de que quer perder as alterações não salvas?"
@@ -740,6 +811,9 @@ msgstr "Você tem certeza que quer recriar o token de registro?"
msgid "Are you sure you want to reset the health check token?"
msgstr "Você tem certeza que quer reiniciar o token de status de saúde?"
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "Você tem certeza que quer destravar %{path_lock_path}?"
@@ -747,7 +821,7 @@ msgid "Are you sure?"
msgstr "Você tem certeza?"
msgid "Artifact ID"
-msgstr ""
+msgstr "ID do artefato"
msgid "Artifacts"
msgstr "Artefatos"
@@ -789,7 +863,7 @@ msgid "Assignee"
msgstr "Responsável"
msgid "Assignee lists not available with your current license"
-msgstr ""
+msgstr "Quadro de responsáveis não disponível com sua licença atual"
msgid "Assignee lists show all issues assigned to the selected user."
msgstr "Listas de responsáveis mostram todas as issues atribuídas ao usuário selecionado."
@@ -816,7 +890,7 @@ msgid "Authentication log"
msgstr "Log de autenticação"
msgid "Authentication method"
-msgstr ""
+msgstr "Método de autenticação"
msgid "Author"
msgstr "Autor"
@@ -878,6 +952,9 @@ msgstr "Ele gerará a build, testará e fará deploy de sua aplicação automati
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "Saiba mais em %{link_to_documentation}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr "Você pode automaticamente construir e testar sua aplicação, se você %{link_to_auto_devops_settings} para este projeto. Você pode também fazer o deploy automaticamente, se você %{link_to_add_kubernetes_cluster}."
@@ -888,7 +965,7 @@ msgid "AutoDevOps|enable Auto DevOps"
msgstr "ativar Auto DevOps"
msgid "Automatically marked as default internal user"
-msgstr ""
+msgstr "Marcado automaticamente como interno de usuário padrão"
msgid "Available"
msgstr "Disponível"
@@ -914,9 +991,6 @@ msgstr "Tarefas em Segundo Plano"
msgid "Background color"
msgstr "Cor do plano de fundo"
-msgid "Background jobs"
-msgstr "Tarefas em segundo plano"
-
msgid "Badges"
msgstr "Selos"
@@ -957,7 +1031,7 @@ msgid "Badges|No image to preview"
msgstr "Sem imagem para pré-visualizar"
msgid "Badges|Please fill in a valid URL"
-msgstr ""
+msgstr "Por favor, preencha um URL válido"
msgid "Badges|Project Badge"
msgstr "Selo de projeto"
@@ -987,12 +1061,21 @@ msgid "Badges|This project has no badges"
msgstr "Esse projeto não tem selos"
msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr ""
+msgstr "Você está prestes a excluir este selo. Selos excluídos <strong>não podem</strong> ser restaurados."
msgid "Badges|Your badges"
msgstr "Seus selos"
msgid "Badges|e.g. %{exampleUrl}"
+msgstr "por exemplo, %{exampleUrl}"
+
+msgid "BatchComments|Delete all pending comments"
+msgstr "Excluir todos os comentários pendentes"
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
msgstr ""
msgid "Begin with the selected commit"
@@ -1023,10 +1106,10 @@ msgid "BillingPlans|Downgrade"
msgstr "Downgrade"
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
-msgstr "Saiba mais sobre cada plano lendo nossa %{faq_link}, ou inicie uma avaliação gratuita de 30 dias do GitLab.com Gold."
+msgstr "Saiba mais sobre cada plano lendo nossas %{faq_link}, ou inicie uma avaliação gratuita de 30 dias do GitLab.com Gold."
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
-msgstr "Saiba mais sobre cada plano lendo nossa %{faq_link}."
+msgstr "Saiba mais sobre cada plano lendo nossas %{faq_link}."
msgid "BillingPlans|Manage plan"
msgstr "Gerenciar plano"
@@ -1059,7 +1142,7 @@ msgid "BillingPlans|features"
msgstr "recursos"
msgid "BillingPlans|frequently asked questions"
-msgstr "Perguntas frequentes"
+msgstr "perguntas frequentes"
msgid "BillingPlans|monthly"
msgstr "mensalmente"
@@ -1071,7 +1154,7 @@ msgid "BillingPlans|per user"
msgstr "por usuário"
msgid "Bitbucket Server Import"
-msgstr ""
+msgstr "Importação de Servidores Bitbucket"
msgid "Bitbucket import"
msgstr "Importar do Bitbucket"
@@ -1080,7 +1163,7 @@ msgid "Blog"
msgstr "Blog"
msgid "Boards"
-msgstr "Boards"
+msgstr "Painéis"
msgid "Branch %{branchName} was not found in this project's repository."
msgstr "O branch %{branchName} não foi encontrado no repositório deste projeto."
@@ -1244,7 +1327,7 @@ msgid "Browse files"
msgstr "Navegar pelos arquivos"
msgid "Built-In"
-msgstr ""
+msgstr "Embutido"
msgid "Business metrics (Custom)"
msgstr "Métricas de negócios (personalizadas)"
@@ -1259,7 +1342,7 @@ msgid "CI / CD Settings"
msgstr "Configurações de CI / CD"
msgid "CI will run using the credentials assigned above."
-msgstr ""
+msgstr "O CI será executado usando as credenciais atribuídas acima."
msgid "CI/CD"
msgstr "CI/CD"
@@ -1285,6 +1368,9 @@ msgstr "Deploy automático para staging, deploy manual para produção"
msgid "CICD|Continuous deployment to production"
msgstr "Deploy contínuo para produção"
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1310,14 +1396,11 @@ msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and
msgstr "Você precisa especificar um domínio se você quiser usar Apps de Revisão Automáticos e Estágios de Deploy automáticos."
msgid "CICD|instance enabled"
-msgstr ""
+msgstr "Instância habilitada"
msgid "Callback URL"
msgstr "URL de Retorno"
-msgid "Callback url"
-msgstr "URL de retorno"
-
msgid "Can't find HEAD commit for this branch"
msgstr "Não é possível encontrar o commit HEAD para este branch"
@@ -1340,7 +1423,7 @@ msgid "Change Weight"
msgstr "Alterar Peso"
msgid "Change template"
-msgstr ""
+msgstr "Mudar modelo"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "Altere esse valor para influenciar com que frequência a interface do usuário do GitLab pesquisa atualizações."
@@ -1372,8 +1455,8 @@ msgstr "Gráficos"
msgid "Chat"
msgstr "Bate-papo"
-msgid "Check interval"
-msgstr "Intervalo de verificação"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
msgid "Checking %{text} availability…"
msgstr "Verificando disponibilidade de %{text}…"
@@ -1399,6 +1482,12 @@ msgstr "Escolha o arquivo ..."
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr "Escolha a branch/tag (ex: %{master}) ou número do commit (ex: %{sha}) para ver o que mudou ou para criar um merge request."
+msgid "Choose a template..."
+msgstr "Escolha um modelo..."
+
+msgid "Choose a type..."
+msgstr "Escolha um tipo..."
+
msgid "Choose any color."
msgstr "Escolha qualquer cor."
@@ -1429,6 +1518,9 @@ msgstr "cancelado"
msgid "CiStatusLabel|created"
msgstr "criado"
+msgid "CiStatusLabel|delayed"
+msgstr "atrasado"
+
msgid "CiStatusLabel|failed"
msgstr "falhou"
@@ -1436,7 +1528,7 @@ msgid "CiStatusLabel|manual action"
msgstr "ação manual"
msgid "CiStatusLabel|passed"
-msgstr "bem sucedido"
+msgstr "passou"
msgid "CiStatusLabel|passed with warnings"
msgstr "bem sucedido com avisos"
@@ -1447,6 +1539,9 @@ msgstr "pendente"
msgid "CiStatusLabel|skipped"
msgstr "ignorado"
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr "aguardando trabalho atrasado"
+
msgid "CiStatusLabel|waiting for manual action"
msgstr "aguardando ação manual"
@@ -1459,6 +1554,9 @@ msgstr "cancelado"
msgid "CiStatusText|created"
msgstr "criado"
+msgid "CiStatusText|delayed"
+msgstr "atrasado"
+
msgid "CiStatusText|failed"
msgstr "falhou"
@@ -1466,7 +1564,7 @@ msgid "CiStatusText|manual"
msgstr "manual"
msgid "CiStatusText|passed"
-msgstr "bem sucedido"
+msgstr "passou"
msgid "CiStatusText|pending"
msgstr "pendente"
@@ -1513,12 +1611,12 @@ msgstr "Alternar proteção"
msgid "CiVariable|Validation failed"
msgstr "Falha na validação"
-msgid "CircuitBreakerApiLink|circuitbreaker api"
-msgstr "interruptor da api"
-
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "está indisponível: %{reason}"
+msgid "Clear search"
+msgstr "Limpar Pesquisa"
+
msgid "Clear search input"
msgstr "Limpar campo de pesquisa"
@@ -1561,6 +1659,9 @@ msgstr "Clonar repositório"
msgid "Close"
msgstr "Fechar"
+msgid "Close epic"
+msgstr "Fechar épico"
+
msgid "Closed"
msgstr "Fechado"
@@ -1573,12 +1674,24 @@ msgstr "%{appList} foi instalado com sucesso no seu cluster Kubernetes"
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr "API URL"
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr "Adicionar cluster Kubernetes"
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Opções avançadas na integração deste cluster Kubernetes"
@@ -1609,11 +1722,11 @@ msgstr "Certificado CA"
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "Pacote de autoridade certificadora (Formato PEM)"
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
-msgstr "Escolha qual dos ambientes do seu projeto usará este cluster Kubernetes."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
-msgstr "Controle como seu cluster Kubernetes se integra com o GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
msgid "ClusterIntegration|Copy API URL"
msgstr "Copiar URL da API"
@@ -1639,6 +1752,12 @@ msgstr "Integração de Clusters | Criar cluster Kubernetes"
msgid "ClusterIntegration|Did you know?"
msgstr "Você sabia?"
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr "Digite detalhes para seu cluster Kubernetes"
@@ -1675,6 +1794,9 @@ msgstr "Google Kubernetes Engine"
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr "Projeto do Google Kubernetes Engine"
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
@@ -1705,9 +1827,6 @@ msgstr "Instalar"
msgid "ClusterIntegration|Install Prometheus"
msgstr "Instalar Prometheus"
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr "Instalado"
@@ -1729,6 +1848,12 @@ msgstr "JupyterHub"
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr "Cluter Kubernetes"
@@ -1738,18 +1863,6 @@ msgstr "Detalhes do cluster Kubernetes"
msgid "ClusterIntegration|Kubernetes cluster health"
msgstr "Saúde do cluster Kubernetes"
-msgid "ClusterIntegration|Kubernetes cluster integration"
-msgstr "Integração com o cluster Kubernetes"
-
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
-msgstr "Integração com o cluster Kubernetes está desabilitada para esse projeto."
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
-msgstr "Integração com o cluster Kubernetes está ativada para esse projeto."
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
-msgstr "Integração com cluster Kubernetes está ativada para esse projeto. Desabilitar essa integração não afetará seu cluster Kubernetes, somente desligará a conexão do GitLab com o mesmo."
-
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
msgstr "O cluster Kubernetes está sendo criado no Google Kubernetes Engine..."
@@ -1759,8 +1872,8 @@ msgstr "Nome do cluster Kubernetes"
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr "Cluster Kubernetes foi criado com sucesso no Google Kubernetes Engine. Atualize a página para ver os detalhes do cluster"
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
-msgstr "Clusters Kubernetes te permitem usar apps de revisão, publicar suas aplicações, executar pipelines e muito mais de um jeito fácil. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
msgstr "Cluster Kubernetes podem ser usados para publicar aplicações e permitir app de revisão para esse projeto"
@@ -1768,17 +1881,14 @@ msgstr "Cluster Kubernetes podem ser usados para publicar aplicações e permiti
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr "Saiba mais sobre os %{help_link_start_machine_type}tipos de máquinas%{help_link_end} e seus %{help_link_start_pricing}preços%{help_link_end}."
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr "Saiba mais sobre os %{help_link_start}Kubernetes%{help_link_end}."
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr "Saiba mais sobre as %{help_link_start}zonas%{help_link_end}."
-msgid "ClusterIntegration|Learn more about environments"
-msgstr "Ler mais sobre ambientes"
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
-msgstr "Ler mais sobre configurações de segurança"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
msgid "ClusterIntegration|Machine type"
msgstr "Tipo de máquina"
@@ -1795,9 +1905,6 @@ msgstr "Gerenciar seu cluster Kubernetes visitando %{link_gke}"
msgid "ClusterIntegration|More information"
msgstr "Mais informações"
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr "Múltiplos clusters Kubernetes estão disponíveis GitLab Enterprise Edition Premium e Ultimate"
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr "Nenhum tipo de máquina corresponde à sua pesquisa"
@@ -1823,6 +1930,9 @@ msgid "ClusterIntegration|Please make sure that your Google account meets the fo
msgstr "Por favor, tenha certeza que sua conta no Google cumpre com os requisitos:"
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
+msgstr "Aponte um DNS curinga para esse endereço IP gerado para acessar sua aplicação depois que ele for lançado."
+
+msgid "ClusterIntegration|Project cluster"
msgstr ""
msgid "ClusterIntegration|Project namespace"
@@ -1835,6 +1945,9 @@ msgid "ClusterIntegration|Prometheus"
msgstr "Prometheus"
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
+msgstr "Prometheus é um sistema de monitoramento de código aberto com %{gitlabIntegrationLink} para monitorar aplicações lançadas."
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
msgstr ""
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
@@ -1850,7 +1963,7 @@ msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from th
msgstr "Remover configuração desse cluster Kubernetes para esse projeto. Isso não apagará seu cluster Kubernetes atual."
msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
-msgstr ""
+msgstr "Substitua isso por seu próprio nome de host, se desejar. Se você fizer isso, aponte o nome do host para o endereço IP de entrada acima."
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "Solicitação para início de instalação falhou"
@@ -1867,9 +1980,6 @@ msgstr "Pesquisar projetos"
msgid "ClusterIntegration|Search zones"
msgstr "Pesquisar zonas"
-msgid "ClusterIntegration|Security"
-msgstr "Segurança"
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "Veja e edite os detalhes de seus cluster Kubernates"
@@ -1907,16 +2017,13 @@ msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "Algo deu errado ao instalar %{title}"
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
-msgstr ""
-
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr "O configuração de cluster padrão permite acesso a uma gama de funcionalidades necessárias para gerar build e publicar aplicações em container."
+msgstr "O endereço IP está em processo de atribuição. Verifique seu cluster ou cotas do Kubernetes no Google Kubernetes Engine se demorar muito."
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr "Essa conta precisa de permissões para criar um cluster Kubernetes no %{link_to_container_project} especificado"
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
-msgstr "Alternar cluster Kubernetes"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "Alternar cluster Kubernetes"
@@ -1928,11 +2035,14 @@ msgid "ClusterIntegration|Validating project billing status"
msgstr "Validando status de faturamento do projeto"
msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
-msgstr ""
+msgstr "Não foi possível verificar se um dos seus projetos no GCP possui o faturamento ativado. Por favor, tente novamente."
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "Com um cluster Kubernetes associado a esse projeto, você pode utilizar apps de revisão, publicar suas aplicações, executar suas pipelines e muito mais de um jeito simples."
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Sua conta precisa de %{link_to_kubernetes_engine}"
@@ -1951,9 +2061,6 @@ msgstr "documentação"
msgid "ClusterIntegration|help page"
msgstr "ajuda"
-msgid "ClusterIntegration|installing applications"
-msgstr "Instalando aplicações"
-
msgid "ClusterIntegration|meets the requirements"
msgstr "atende aos requisitos"
@@ -1963,6 +2070,9 @@ msgstr "configurado corretamente"
msgid "ClusterIntegration|sign up"
msgstr "cadastrar"
+msgid "Code owners"
+msgstr "Proprietários de código"
+
msgid "Cohorts"
msgstr "Cohorts"
@@ -1972,12 +2082,18 @@ msgstr "Recolher"
msgid "Collapse sidebar"
msgstr "Minimizar barra lateral"
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr "Comentar e marcar a discussão como resolvida"
msgid "Comment & unresolve discussion"
msgstr "Comentar e marcar a discussão como não resolvida"
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr "Comentários"
@@ -2012,6 +2128,9 @@ msgstr "Commit"
msgid "CommitMessage|Add %{file_name}"
msgstr "Adicionar %{file_name}"
+msgid "CommitWidget|authored"
+msgstr "Escrito"
+
msgid "Commits"
msgstr "Commits"
@@ -2084,8 +2203,8 @@ msgstr "Confidencialidade"
msgid "Configure Gitaly timeouts."
msgstr "Configurar timeouts do Gitaly."
-msgid "Configure Sidekiq job throttling."
-msgstr "Configurar otimização de jobs no Sidekiq."
+msgid "Configure Tracing"
+msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr "Configurar housekeeping e checagens do git nos repositórios."
@@ -2093,11 +2212,11 @@ msgstr "Configurar housekeeping e checagens do git nos repositórios."
msgid "Configure limits for web and API requests."
msgstr "Configurar limites para web e requisições para API."
-msgid "Configure push and pull mirrors."
-msgstr "Configurar push e pull de espelhamentos."
+msgid "Configure push mirrors."
+msgstr ""
-msgid "Configure storage path and circuit breaker settings."
-msgstr "Configurar caminho de armazenamento e circuit breaker."
+msgid "Configure storage path settings."
+msgstr ""
msgid "Configure the %{link} integration."
msgstr ""
@@ -2186,6 +2305,9 @@ msgstr "Contribuições"
msgid "Contribution guide"
msgstr "Guia de contribuição"
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr "Contribuições por membro do grupo"
@@ -2219,6 +2341,18 @@ msgstr "Controlar a concorrência máxima de operações de verificação para e
msgid "ConvDev Index"
msgstr "Ãndice ConvDev"
+msgid "Copy %{protocol} clone URL"
+msgstr "Copiar URL de Clone do %{protocol}"
+
+msgid "Copy HTTPS clone URL"
+msgstr "Copiar URL de Clone do HTTPS"
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr "Copiar URL de Clone do SSH"
+
msgid "Copy SSH public key to clipboard"
msgstr "Copiar chave pública SSH para área de transferência"
@@ -2240,15 +2374,27 @@ msgstr "Copiar o local do arquivo para a área de transferência"
msgid "Copy incoming email address to clipboard"
msgstr "Copiar endereço de e-mail para a área de transferência"
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr "Copiar referência para área de transferência"
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr "Copiar para área de transferência"
msgid "Copy token to clipboard"
msgstr "Copiar token para a área de transferência"
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr "Criar"
@@ -2324,8 +2470,8 @@ msgstr "Criar novo..."
msgid "Create project label"
msgstr "Criar etiqueta de projeto"
-msgid "CreateNewFork|Fork"
-msgstr "Fork"
+msgid "Create your first page"
+msgstr ""
msgid "CreateTag|Tag"
msgstr "Tag"
@@ -2343,7 +2489,7 @@ msgid "Created by me"
msgstr "Criado por mim"
msgid "Created on"
-msgstr ""
+msgstr "Criado em"
msgid "Created on:"
msgstr "Criado em:"
@@ -2358,7 +2504,7 @@ msgid "Cron syntax"
msgstr "Sintaxe do cron"
msgid "Current Branch"
-msgstr ""
+msgstr "Branch atual"
msgid "Current node"
msgstr "Nó atual"
@@ -2370,11 +2516,14 @@ msgid "CurrentUser|Settings"
msgstr "Configurações"
msgid "Custom"
-msgstr ""
+msgstr "Personalizado"
msgid "Custom CI config path"
msgstr "Caminho de configuração do IC personalizado"
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr "Eventos de notificação personalizados"
@@ -2382,7 +2531,7 @@ msgid "Custom notification levels are the same as participating levels. With cus
msgstr "Níveis de notificação personalizados são equivalentes a níveis de participação. Com níveis de notificação personalizados você também será notificado sobre eventos selecionados. Para mais informações, visite %{notification_link}."
msgid "Custom project templates"
-msgstr ""
+msgstr "Modelos de projetos personalizados"
msgid "Customize colors"
msgstr "Personalizar cores"
@@ -2393,6 +2542,9 @@ msgstr "Personalize como os endereços de e-mail e nomes de usuário do FogBugz
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr "Personalize como os endereços de e-mail e nomes de usuário do Google Code são importados para o GitLab. Na próxima etapa, você poderá selecionar os projetos que deseja importar."
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr "Análise de Ciclo"
@@ -2433,7 +2585,7 @@ msgid "Date picker"
msgstr ""
msgid "Debug"
-msgstr ""
+msgstr "Depurar"
msgid "Dec"
msgstr "Dez"
@@ -2444,6 +2596,9 @@ msgstr "Dezembro"
msgid "Decline and sign out"
msgstr "Recusar e sair"
+msgid "Default Branch"
+msgstr "Branch padrão"
+
msgid "Default classification label"
msgstr "Etiqueta de classificação padrão"
@@ -2456,15 +2611,33 @@ msgstr "Padrão: Mapeie uma ID de conta do FogBugz para um nome completo"
msgid "Define a custom pattern with cron syntax"
msgstr "Defina um padrão personalizado utilizando a sintaxe do cron"
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr "Excluir"
msgid "Delete Package"
-msgstr ""
+msgstr "Excluir pacote"
msgid "Delete Snippet"
msgstr "Excluir Snippet"
+msgid "Delete comment"
+msgstr "Excluir comentário"
+
msgid "Delete list"
msgstr "Excluir lista"
@@ -2602,6 +2775,12 @@ msgstr "Seu novo token de deploy"
msgid "DeployTokens|Your new project deploy token has been created."
msgstr "Seu novo token de deploy de projeto foi criado."
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr "Despriorizar etiqueta"
@@ -2626,6 +2805,12 @@ msgstr "Detalhes"
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr "Nenhum nome de arquivo disponível"
@@ -2647,12 +2832,27 @@ msgstr "Desativar para este projeto"
msgid "Disable group Runners"
msgstr "Desabilitar runners de grupo"
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr "Descartar todas as alterações"
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr "Rejeitar alterações"
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr "Descartar rascunho"
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr "Descubra o GitLab Geo."
@@ -2668,6 +2868,9 @@ msgstr "Ignorar introdução do Cycle Analytics"
msgid "Dismiss Merge Request promotion"
msgstr "Descartar promoção de Merge Request"
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "Deseja personalizar como os endereços de e-mail e nomes de usuário do Google Code são importados para o GitLab?"
@@ -2749,8 +2952,8 @@ msgstr "Editar identidade para %{user_name}"
msgid "Elasticsearch"
msgstr "Elasticsearch"
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
-msgstr "Integração com Elasticsearch. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
msgid "Email"
msgstr "E-mail"
@@ -2794,9 +2997,6 @@ msgstr "Ativar para este projeto"
msgid "Enable group Runners"
msgstr "Ativar grupo de runners"
-msgid "Enable or disable certain group features and choose access levels."
-msgstr "Ative ou desative certos tipos de funcionalidades e escolha os níveis de acesso."
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "Ative ou desative a coleção de dados Pseudonymizer"
@@ -2809,6 +3009,12 @@ msgstr "Ativar reCAPTCHA ou Akismet e definir seus limites de IP."
msgid "Enable the Performance Bar for a given group."
msgstr "Ative a barra de desempenho para um determinado grupo."
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr "Habilitado"
@@ -2819,16 +3025,16 @@ msgid "Enter in your Bitbucket Server URL and personal access token below"
msgstr ""
msgid "Enter the issue description"
-msgstr ""
+msgstr "Digite a descrição da issue"
msgid "Enter the issue title"
-msgstr ""
+msgstr "Digite o título da issue"
msgid "Enter the merge request description"
-msgstr ""
+msgstr "Digite a descrição do merge request"
msgid "Enter the merge request title"
-msgstr ""
+msgstr "Digite o título do merge request"
msgid "Environments"
msgstr "Ambientes"
@@ -2911,11 +3117,11 @@ msgstr "Parar ambiente"
msgid "Environments|Updated"
msgstr "Atualizado"
-msgid "Environments|You don't have any environments right now."
-msgstr "Você não tem nenhum ambiente."
+msgid "Environments|You don't have any environments right now"
+msgstr ""
msgid "Environments|protected"
-msgstr ""
+msgstr "protegido"
msgid "Epic"
msgstr "Epic"
@@ -2936,25 +3142,25 @@ msgid "Epics|An error occurred while saving %{epicDateType} date"
msgstr ""
msgid "Epics|How can I solve this?"
-msgstr ""
+msgstr "Como posso resolver isso?"
msgid "Epics|More information"
-msgstr ""
+msgstr "Mais informações"
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
msgstr ""
msgid "Error"
-msgstr ""
+msgstr "Erro"
msgid "Error Reporting and Logging"
msgstr "Relatório e registro de erros"
@@ -3058,6 +3264,12 @@ msgstr "Expandir tudo"
msgid "Expand sidebar"
msgstr "Expandir barra lateral"
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr "Explorar"
@@ -3112,8 +3324,14 @@ msgstr "Erro ao alterar o proprietário"
msgid "Failed to check related branches."
msgstr "Falha ao procurar por branches relacionadas."
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
-msgstr "Falha ao remover issue do board, por favor, tente novamente."
+msgstr "Falha ao remover issue do painel, por favor, tente novamente."
msgid "Failed to remove mirror."
msgstr ""
@@ -3121,6 +3339,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "Erro ao excluir o agendamento do pipeline"
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr "Falha ao atualizar Issues. Por favor, tente novamente."
@@ -3130,6 +3351,81 @@ msgstr "Falha"
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr "Mais rápido, uma vez que reutiliza o espaço de trabalho do projeto (voltando a clonar, se não existir)"
+msgid "Feature Flags"
+msgstr "Sinalizadores de recurso"
+
+msgid "FeatureFlags|API URL"
+msgstr "URL da API"
+
+msgid "FeatureFlags|Active"
+msgstr "Ativo"
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr "Configurar"
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr "Configurar sinalizadores de recursos"
+
+msgid "FeatureFlags|Create feature flag"
+msgstr "Criar sinalizador de recurso"
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr "Excluir %{feature_flag_name}?"
+
+msgid "FeatureFlags|Description"
+msgstr "Descrição"
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr "Editar %{feature_flag_name}"
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr "Editar sinalizador de recurso"
+
+msgid "FeatureFlags|Feature Flag"
+msgstr "Sinalizador de recurso"
+
+msgid "FeatureFlags|Feature flag"
+msgstr "Sinalizador de recurso"
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr "O sinalizador de recurso %{feature_flag_name} será removido. Você tem certeza?"
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr "Os sinalizadores de recursos permitem que você configure o seu código em diferentes versões alterando dinamicamente determinadas funcionalidades."
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr "Comece a usar os sinalizadores de recursos"
+
+msgid "FeatureFlags|Inactive"
+msgstr "Inativo"
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr "Status"
+
msgid "Feb"
msgstr "Fev"
@@ -3139,6 +3435,9 @@ msgstr "Fevereiro"
msgid "Fields on this page are now uneditable, you can configure"
msgstr "Campos nessa página não são mais editáveis, você pode configurar"
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr "Arquivos"
@@ -3151,9 +3450,18 @@ msgstr "Preencha nos campos abaixo, ative o <strong>%{enable_label}</strong> e p
msgid "Filter"
msgstr "Filtro"
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr "Filtrar por mensagem de commit"
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr "Localizar por caminho"
@@ -3167,6 +3475,9 @@ msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/Google
msgstr "Encontre o arquivo recém-extraído <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code>."
msgid "Fingerprints"
+msgstr "Impressões digitais"
+
+msgid "Finish review"
msgstr ""
msgid "Finished"
@@ -3179,13 +3490,13 @@ msgid "FirstPushedBy|pushed by"
msgstr "publicado por"
msgid "Fixed date"
-msgstr ""
+msgstr "Data fixa"
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
-msgstr ""
+msgstr "Data de início fixa"
msgid "Fixed:"
msgstr ""
@@ -3218,6 +3529,12 @@ msgid "For internal projects, any logged in user can view pipelines and access j
msgstr "Para projetos internos, qualquer usuário conectado pode visualizar pipelines e acessar detalhes do job (logs de saída e artefatos)"
msgid "For more information, go to the "
+msgstr "Para mais informações, vá para o "
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
msgstr ""
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
@@ -3226,11 +3543,6 @@ msgstr "Para projetos privados, qualquer membro (guest ou superior) pode visuali
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr "Para projetos públicos, qualquer pessoa pode visualizar pipelines e acessar detalhes do trabalho (logs de saída e artefatos)"
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] "Fork"
-msgstr[1] "Forks"
-
msgid "ForkedFromProjectPath|Forked from"
msgstr "Fork criado a partir de"
@@ -3246,6 +3558,9 @@ msgstr "Formato"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr "Erros encontrados em seu .gitlab-ci.yml:"
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr "De %{provider_title}"
@@ -3253,7 +3568,7 @@ msgid "From Bitbucket"
msgstr "Do Bitbucket"
msgid "From Bitbucket Server"
-msgstr ""
+msgstr "Do servidor do Bitbucket"
msgid "From FogBugz"
msgstr "Do FogBugz"
@@ -3288,6 +3603,9 @@ msgstr "Pipelines Gerais"
msgid "Generate a default set of labels"
msgstr "Gerar etiquetas padrão"
+msgid "Geo"
+msgstr "Geo"
+
msgid "Geo Nodes"
msgstr "Nós do Geo"
@@ -3462,10 +3780,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr "Todos os projetos"
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3474,11 +3804,14 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr "Capacidade de sincronização de arquivo"
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr "Grupos para sincronizar"
msgid "Geo|In sync"
-msgstr ""
+msgstr "Em sincronia"
msgid "Geo|Last successful sync"
msgstr ""
@@ -3487,24 +3820,27 @@ msgid "Geo|Last sync attempt"
msgstr ""
msgid "Geo|Last time verified"
-msgstr ""
+msgstr "Última vez verificada"
msgid "Geo|Never"
-msgstr ""
+msgstr "Nunca"
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
-msgstr ""
+msgstr "Pendente"
msgid "Geo|Pending synchronization"
-msgstr ""
+msgstr "Sincronização pendente"
msgid "Geo|Pending verification"
+msgstr "Verificação pendente"
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
msgstr ""
msgid "Geo|Projects in certain groups"
@@ -3514,9 +3850,15 @@ msgid "Geo|Projects in certain storage shards"
msgstr "Projetos em certos pedaços de armazenamento"
msgid "Geo|Recheck"
+msgstr "Verificar novamente"
+
+msgid "Geo|Recheck all projects"
msgstr ""
msgid "Geo|Redownload"
+msgstr "Baixar novamente"
+
+msgid "Geo|Remove"
msgstr ""
msgid "Geo|Repository sync capacity"
@@ -3525,10 +3867,10 @@ msgstr "Capacidade de sincronização de repositório"
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3546,6 +3888,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3558,9 +3906,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr "Git"
@@ -3570,9 +3936,6 @@ msgstr "URL do repositório Git"
msgid "Git revision"
msgstr "Revisão do Git"
-msgid "Git storage health information has been reset"
-msgstr "Informações sobre o status de saúde do storage Git foram reiniciadas"
-
msgid "Git strategy for pipelines"
msgstr "Estratégia Git para pipelines"
@@ -3610,7 +3973,7 @@ msgid "GitLab.com import"
msgstr "Importação do GitLab.com"
msgid "GitLab’s issue tracker"
-msgstr ""
+msgstr "Rastreador de issues do GitLab"
msgid "Gitaly"
msgstr "Gitaly"
@@ -3634,17 +3997,11 @@ msgid "Go back"
msgstr "Voltar"
msgid "Go to"
-msgstr ""
+msgstr "Ir para"
msgid "Go to %{link_to_google_takeout}."
msgstr "Ir para %{link_to_google_takeout}."
-msgid "Go to your fork"
-msgstr "Ir para seu fork"
-
-msgid "GoToYourFork|Fork"
-msgstr "Fork"
-
msgid "Google Code import"
msgstr "Importação do Google Code"
@@ -3675,9 +4032,21 @@ msgstr "ID do grupo"
msgid "Group Runners"
msgstr "Group Runners"
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr "Avatar do grupo"
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr "Detalhes do grupo"
@@ -3687,6 +4056,9 @@ msgstr "Info. do grupo:"
msgid "Group maintainers can register group runners in the %{link}"
msgstr "Os mantenedores podem registrar grupos de runners em %{link}"
+msgid "Group name"
+msgstr "Nome do grupo"
+
msgid "Group: %{group_name}"
msgstr "Grupo: %{group_name}"
@@ -3705,14 +4077,14 @@ msgstr "Desculpe, nenhum epic corresponde à sua pesquisa"
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr "O roadmap mostra o progresso de seus epics ao longo de uma linha do tempo"
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Para visualizar o roadmap, adicione uma data de início ou término planejada a um dos seus epics nesse grupo ou em seus subgrupos. Na visão mensal, apenas epics no mês passado, no mês atual e nos próximos 5 meses são exibidos &ndash; de %{startDate} a %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Para visualizar o roadmap, adicione uma data de início ou término planejada a um dos seus epics nesse grupo ou em seus subgrupos. Na visão trimestral, apenas epics no trimestre passado, no trimestre atual e nos próximos 4 trimestres são exibidos &ndash; de %{startDate} a %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Para visualizar o roadmap, adicione uma data de início ou término planejada a um dos seus epics nesse grupo ou em seus subgrupos. Na visão semanal, apenas epics na semana passada, na semana atual e nas próximas 4 semanas são exibidos &ndash; de %{startDate} a %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr "Para ampliar sua pesquisa, alterar ou remover filtros. Na visão mensal, apenas epics no mês passado, no mês atual e nos próximos 5 meses são exibidos &ndash; de %{startDate} a %{endDate}."
@@ -3727,7 +4099,7 @@ msgid "GroupRoadmap|Until %{dateWord}"
msgstr "Até %{dateWord}"
msgid "GroupSettings|Badges"
-msgstr ""
+msgstr "Selos"
msgid "GroupSettings|Customize your group badges."
msgstr ""
@@ -3738,9 +4110,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Bloquear compartilhamento de projetos do grupo %{group} com outros grupos"
-msgid "GroupSettings|Share with group lock"
-msgstr "Travar compartilhamento de grupo"
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "Essa configuração é aplicada no grupo %{ancestor_group} e foi sobrescrita nesse subgrupo."
@@ -3798,6 +4167,9 @@ msgstr "Nenhum grupo encontrado"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Você pode gerenciar permissões de membros e acesso do seu grupo para cada projeto no grupo."
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr "Criar um projeto nesse grupo."
@@ -3810,20 +4182,20 @@ msgstr "Editar grupo"
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr "Falha ao deixar o grupo. Por favor, verifique se você é o único dono."
-msgid "GroupsTree|Filter by name..."
-msgstr "Filtrar por nome..."
-
msgid "GroupsTree|Leave this group"
msgstr "Deixar o grupo"
msgid "GroupsTree|Loading groups"
msgstr "Carregando grupos"
-msgid "GroupsTree|Sorry, no groups matched your search"
-msgstr "Desculpe, nenhum grupo corresponde à sua pesquisa"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
-msgstr "Desculpe, nenhum grupo ou projeto correspondem à sua pesquisa"
+msgid "GroupsTree|Search by name"
+msgstr ""
msgid "Have your users email"
msgstr "Tem o e-mail de seus usuários"
@@ -3864,6 +4236,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Ocultar valor"
@@ -4020,7 +4395,7 @@ msgid "ImportButtons|Connect repositories from"
msgstr "Conectar repositórios de"
msgid "Improve Issue boards with GitLab Enterprise Edition."
-msgstr "Melhore os quadros de issues com GitLab Enterprise Edition."
+msgstr "Melhore os painéis com GitLab Enterprise Edition."
msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
msgstr "Melhore o gerenciamento de issues com o peso de issues e GitLab Enterprise Edition."
@@ -4028,6 +4403,9 @@ msgstr "Melhore o gerenciamento de issues com o peso de issues e GitLab Enterpri
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr "Melhore a pesquisa com Advanced Global Search e GitLab Enterprise Edition."
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr "Na próxima etapa, você poderá selecionar os projetos que deseja importar."
@@ -4088,7 +4466,7 @@ msgid "Internal - The project can be accessed by any logged in user."
msgstr "Interno - O projeto pode ser acessado por qualquer usuário autenticado."
msgid "Internal users"
-msgstr ""
+msgstr "Usuários internos"
msgid "Interval Pattern"
msgstr "Padrão de intervalo"
@@ -4096,20 +4474,26 @@ msgstr "Padrão de intervalo"
msgid "Introducing Cycle Analytics"
msgstr "Apresentando a Análise de Ciclo"
+msgid "Invite"
+msgstr "Convidar"
+
+msgid "Issue"
+msgstr "Issue"
+
msgid "Issue Boards"
-msgstr "Quadros de issues"
+msgstr "Painéis"
msgid "Issue board focus mode"
-msgstr "Modo de foco no quadro de issues"
+msgstr "Modo de foco nos painéis"
msgid "Issue events"
msgstr "Eventos de issue"
msgid "IssueBoards|Board"
-msgstr "Board"
+msgstr "Painel"
msgid "IssueBoards|Boards"
-msgstr "Quadros"
+msgstr "Painéis"
msgid "Issues"
msgstr "Issues"
@@ -4120,6 +4504,36 @@ msgstr "Issues podem ser bugs, tarefas ou ideias a serem discutidas. Além disso
msgid "Issues closed"
msgstr "Issues fechadas"
+msgid "Issues, merge requests, pushes and comments."
+msgstr "Issues, merge requests, pushes e comentários."
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr "Issues criadas"
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr "Issues criadas por mês"
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr "Últimos 12 meses"
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr "Desculpe, mas o seu filtro não produziu resultados"
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr "Não há issues para os projetos no seu grupo"
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr "Para ampliar sua pesquisa, altere ou remova filtros na barra de filtros acima"
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr "Jan"
@@ -4135,46 +4549,43 @@ msgstr "O job foi apagado"
msgid "Jobs"
msgstr "Jobs"
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
-msgstr ""
+msgstr "Navegar"
msgid "Job|Complete Raw"
-msgstr ""
+msgstr "Raw completo"
msgid "Job|Download"
-msgstr ""
+msgstr "Baixar"
msgid "Job|Erase job log"
-msgstr ""
+msgstr "Apagar log da tarefa"
msgid "Job|Job artifacts"
msgstr ""
msgid "Job|Job has been erased"
-msgstr ""
+msgstr "A tarefa foi apagada"
msgid "Job|Job has been erased by"
-msgstr ""
+msgstr "A tarefa foi apagada por"
msgid "Job|Keep"
-msgstr ""
+msgstr "Manter"
msgid "Job|Scroll to bottom"
-msgstr ""
+msgstr "Rolar para baixo"
msgid "Job|Scroll to top"
-msgstr ""
+msgstr "Rolar para o topo"
msgid "Job|Show complete raw"
-msgstr ""
+msgstr "Mostrar raw completo"
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4192,12 +4603,6 @@ msgstr "Jun"
msgid "June"
msgstr "Junho"
-msgid "Koding"
-msgstr "Koding"
-
-msgid "Koding Dashboard"
-msgstr "Painel de controle do Koding"
-
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -4268,6 +4673,9 @@ msgid "Labels|Promote Label"
msgstr "Promover etiqueta"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
+msgstr "Promover %{labelTitle} irá disponibilizá-la para todos os projetos dentro de %{groupName}. Etiquetas de projetos existentes com o mesmo título serão mescladas. Esta ação não pode ser revertida."
+
+msgid "Large File Storage"
msgstr ""
msgid "Last %d day"
@@ -4281,12 +4689,18 @@ msgstr "Último Pipeline"
msgid "Last commit"
msgstr "Último commit"
+msgid "Last contact"
+msgstr "Último contato"
+
msgid "Last edited %{date}"
msgstr "Última edição em %{date}"
msgid "Last edited by %{name}"
msgstr "Última edição por %{name}"
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr "Última atualização"
@@ -4306,7 +4720,7 @@ msgid "Learn more"
msgstr "Saiba mais"
msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
-msgstr ""
+msgstr "Saiba mais sobre %{issue_boards_url}, para acompanhar issues em diversas listas, usando etiquetas, atribuições e milestones. Se você notar algo faltando nos painéis, por favor, crie uma issue em %{gitlab_issues_url}."
msgid "Learn more about Kubernetes"
msgstr "Saiba mais sobre o Kubernetes"
@@ -4335,56 +4749,80 @@ msgstr "Deixe as opções \"Tipo de arquivo\" e \"Método de entrega\" em seus v
msgid "License"
msgstr "Licença"
-msgid "LicenseManagement|Approve license"
+msgid "LicenseManagement|Add a license"
msgstr ""
-msgid "LicenseManagement|Approve license?"
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
msgstr ""
+msgid "LicenseManagement|Approve"
+msgstr ""
+
+msgid "LicenseManagement|Approve license"
+msgstr "Aprovar licença"
+
+msgid "LicenseManagement|Approve license?"
+msgstr "Aprovar licença?"
+
msgid "LicenseManagement|Approved"
+msgstr "Aprovada"
+
+msgid "LicenseManagement|Blacklist"
msgstr ""
msgid "LicenseManagement|Blacklist license"
msgstr ""
msgid "LicenseManagement|Blacklist license?"
-msgstr ""
+msgstr "Adicionar licença à lista negra?"
msgid "LicenseManagement|Blacklisted"
+msgstr "Na lista negra"
+
+msgid "LicenseManagement|Cancel"
msgstr ""
msgid "LicenseManagement|License"
-msgstr ""
+msgstr "Licença"
msgid "LicenseManagement|License Management"
-msgstr ""
+msgstr "Gerenciamento de Licenças"
msgid "LicenseManagement|License details"
+msgstr "Detalhes da licença"
+
+msgid "LicenseManagement|License name"
msgstr ""
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
msgid "LicenseManagement|Packages"
-msgstr ""
+msgstr "Pacotes"
msgid "LicenseManagement|Remove license"
-msgstr ""
+msgstr "Remover licença"
msgid "LicenseManagement|Remove license?"
+msgstr "Remover licença?"
+
+msgid "LicenseManagement|Submit"
msgstr ""
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
-msgid "LicenseManagement|URL"
+msgid "LicenseManagement|This license already exists in this project."
msgstr ""
+msgid "LicenseManagement|URL"
+msgstr "URL"
+
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
msgstr ""
msgid "Licenses"
-msgstr ""
+msgstr "Licenças"
msgid "Limited to showing %d event at most"
msgid_plural "Limited to showing %d events at most"
@@ -4403,6 +4841,9 @@ msgstr "Listar os seus Repositórios do Gitea"
msgid "List available repositories"
msgstr "Listar repositórios disponíveis"
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4410,7 +4851,7 @@ msgid "List your GitHub repositories"
msgstr "Listar os seus repositórios no GitHub"
msgid "Live preview"
-msgstr ""
+msgstr "Pré-visualização ao vivo"
msgid "Loading contribution stats for group members"
msgstr "Carregando estados de contribuição para membros de grupo"
@@ -4448,6 +4889,9 @@ msgstr "Travado para projetos existentes"
msgid "Locks give the ability to lock specific file or folder."
msgstr "Travas possibilitam travar um arquivo ou uma pasta específica."
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr "Logs"
@@ -4461,7 +4905,7 @@ msgid "Manage Git repositories with fine-grained access controls that keep your
msgstr "Gerencie repositórios Git com controles de acesso refinados que mantêm seu código seguro. Realize revisões de código e aprimore a colaboração com merge requests. Cada projeto também pode ter um rastreador de issue e um wiki."
msgid "Manage Web IDE features"
-msgstr ""
+msgstr "Gerenciar recursos do Web IDE"
msgid "Manage access"
msgstr "Gerenciar acesso"
@@ -4517,14 +4961,44 @@ msgstr "Marcar como concluído"
msgid "Markdown enabled"
msgstr "Markdown habilitado"
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
-msgstr "Máximo de falhas do git storage"
+msgid "Max access level"
+msgstr "Nível máximo de acesso"
msgid "Maximum job timeout"
msgstr ""
@@ -4535,6 +5009,12 @@ msgstr "Mai"
msgid "Median"
msgstr "Mediana"
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr "Membro desde %{date}"
+
msgid "Members"
msgstr "Membros"
@@ -4568,6 +5048,21 @@ msgstr "Merge requests"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "A tela de Merge request é um lugar para propor mudanças em um projeto e discutir essas mudanças com outros"
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr "Resolver essa discussão em um novo issue"
@@ -4577,9 +5072,6 @@ msgstr "Falha ao salvar comentário"
msgid "MergeRequests|Toggle comments for this file"
msgstr "Ativar/desativar comentários para este arquivo"
-msgid "MergeRequests|Updating discussions failed"
-msgstr "A atualização de discussões falhou"
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr "Visualizar o arquivo @ %{commitId}"
@@ -4589,6 +5081,12 @@ msgstr "Ver arquivo substituído @ %{commitId}"
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr "Merge realizado"
@@ -4604,6 +5102,9 @@ msgstr "Métricas - Influx"
msgid "Metrics - Prometheus"
msgstr "Métricas - Prometheus"
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr "Negócios"
@@ -4713,7 +5214,7 @@ msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
msgid "Milestones"
-msgstr "Milestones"
+msgstr "Marcos"
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
msgstr ""
@@ -4722,7 +5223,7 @@ msgid "Milestones| You’re about to permanently delete the milestone %{mileston
msgstr ""
msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
+msgstr "<p>%{milestonePromotion}</p> %{finalWarning}"
msgid "Milestones|Delete milestone"
msgstr "Excluir Milestone"
@@ -4743,7 +5244,7 @@ msgid "Milestones|Promote Milestone"
msgstr "Promover Milestone"
msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
-msgstr ""
+msgstr "Promover %{milestone} irá disponibilizá-lo para todos os projetos dentro de %{groupName}. Os milestones de projeto existentes com o mesmo nome serão mesclados. "
msgid "Milestones|This action cannot be reversed."
msgstr "Essa ação não pode ser revertida."
@@ -4806,7 +5307,7 @@ msgid "Move issue"
msgstr "Mover issue"
msgid "Multiple issue boards"
-msgstr "Multiplos issue boards"
+msgstr "Múltiplos painéis"
msgid "Name"
msgstr "Nome"
@@ -4820,6 +5321,9 @@ msgstr "Nomeie sua chave individual por meio de um título"
msgid "Name:"
msgstr "Nome:"
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr "Ajuda"
@@ -4836,7 +5340,7 @@ msgid "Network"
msgstr "Rede"
msgid "Never"
-msgstr ""
+msgstr "Nunca"
msgid "New"
msgstr ""
@@ -4939,6 +5443,12 @@ msgstr "Nenhuma conexão pode ser feita para um servidor Gitaly, por favor check
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr "Sem validade"
@@ -4948,9 +5458,6 @@ msgstr "Sem estimativa de tempo gasto"
msgid "No file chosen"
msgstr "Nenhum arquivo escolhido"
-msgid "No files found"
-msgstr "Nenhum arquivo encontrado"
-
msgid "No files found."
msgstr "Nenhum arquivo encontrado."
@@ -4960,6 +5467,9 @@ msgstr "Sem issues para o período de tempo selecionado."
msgid "No labels with such name or description"
msgstr "Sem etiquetas com esse nome ou descrição"
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr "Sem merge requests para o período de tempo selecionado."
@@ -4987,6 +5497,9 @@ msgstr "Nenhum push para o período de tempo selecionado."
msgid "No repository"
msgstr "Nenhum repositório"
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr "Nenhum agendamento"
@@ -5023,6 +5536,9 @@ msgstr "Não confidencial"
msgid "Not enough data"
msgstr "Dados insuficientes"
+msgid "Not now"
+msgstr "Agora não"
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr "Observe que o branch master é automaticamente protegido. %{link_to_protected_branches}"
@@ -5041,6 +5557,18 @@ msgstr "Nota: Considere pedir ao seu administrador do GitLab para configurar %{g
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "Você tem certeza que quer cancelar a criação deste comentário?"
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr "Eventos de notificação"
@@ -5113,9 +5641,6 @@ msgstr "Nov"
msgid "November"
msgstr "Novembro"
-msgid "Number of access attempts"
-msgstr "Número de tentativas de acesso"
-
msgid "OK"
msgstr "OK"
@@ -5142,9 +5667,6 @@ msgstr "Um ou mais dos seus projetos do Bitbucket não podem ser importados dire
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "Um ou mais dos seus projetos do Google Code não podem ser importados diretamente no GitLab porque eles usam Subversion ou Mercurial para o controle de versão, ao invés de Git."
-msgid "Online IDE integration settings."
-msgstr "Configurações de integração on-line do IDE."
-
msgid "Only admins"
msgstr ""
@@ -5166,6 +5688,9 @@ msgstr "Abrir"
msgid "Open in Xcode"
msgstr "Abrir no Xcode"
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr "Abrir barra lateral"
@@ -5190,6 +5715,21 @@ msgstr "Abrir em nova janela"
msgid "Operations"
msgstr "Operações"
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "Opcionalmente, você pode %{link_to_customize} como os endereços de e-mail e nomes de usuários do FogBugz são importados para o GitLab."
@@ -5224,13 +5764,13 @@ msgid "Owner"
msgstr "Proprietário"
msgid "Package information"
-msgstr ""
+msgstr "Informações do pacote"
msgid "Package was removed"
-msgstr ""
+msgstr "O pacote foi removido"
msgid "Packages"
-msgstr ""
+msgstr "Pacotes"
msgid "Pages"
msgstr "Páginas"
@@ -5256,6 +5796,9 @@ msgstr "Senha"
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr "Cole a sua chave SSH pública, que geralmente é encontrada no arquivo '~/.ssh/id_rsa.pub' e começa com 'ssh-rsa'. Não use a sua chave SSH privada."
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr "Caminho:"
@@ -5283,15 +5826,15 @@ msgstr "Otimização de performance"
msgid "Permissions"
msgstr "Permissões"
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
msgid "Personal Access Token"
msgstr "Token de Acesso Pessoal"
msgid "Pipeline"
msgstr "Pipeline"
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
-msgstr ""
-
msgid "Pipeline Health"
msgstr "Saúde da Pipeline"
@@ -5409,15 +5952,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "Este projeto não está atualmente configurado para executar pipelines."
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr "Criar para"
msgid "Pipeline|Create pipeline"
msgstr "Criar pipeline"
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr "Nome de branch ou tag existente"
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr "Executar Pipeline"
@@ -5427,6 +5979,12 @@ msgstr "Pesquisar branches"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr "Especifique valores de variáveis ​​a serem usados ​​nesta execução. Os valores especificados em %{settings_link} serão usados ​​por padrão."
+msgid "Pipeline|Stages"
+msgstr "Estágios"
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr "Parar pipeline"
@@ -5454,12 +6012,6 @@ msgstr "com etapas"
msgid "Plain diff"
msgstr "Diff simples"
-msgid "Planned finish date"
-msgstr "Data de término planejada"
-
-msgid "Planned start date"
-msgstr "Data de início planejada"
-
msgid "PlantUML"
msgstr "PlantUML"
@@ -5469,12 +6021,18 @@ msgstr "Iniciar"
msgid "Please accept the Terms of Service before continuing."
msgstr "Por favor, aceite os Termos de Serviço antes de continuar."
+msgid "Please choose a group URL with no special characters."
+msgstr "Por favor, escolha um URL de grupo sem caracteres especiais."
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr "Por favor, converta-os para %{link_to_git} e passe pelo %{link_to_import_flow} novamente."
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr "Por favor, converta-os em Git no Google Code e passe pelo %{link_to_import_flow} novamente."
+msgid "Please fill in a descriptive name for your group."
+msgstr "Por favor, preencha um nome descritivo para o seu grupo."
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "Por favor, note que esse aplicativo não é fornecido pelo GitLab e você deve verificar a sua autenticidade antes de permitir o acesso."
@@ -5487,6 +6045,9 @@ msgstr "Por favor, resolva o reCAPTCHA"
msgid "Please try again"
msgstr "Por favor, tente novamente"
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr "Use este formulário para denunciar usuários ao GitLab que criam spam de issues, comentários ou se comportam de maneira inapropriada."
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr "Por favor, aguarde enquanto conectamos ao seu repositório. Atualize à vontade."
@@ -5499,7 +6060,16 @@ msgstr "Preferências"
msgid "Preferences|Navigation theme"
msgstr "Tema de navegação"
+msgid "Press Enter or click to search"
+msgstr "Pressione Enter ou clique para pesquisar"
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
+msgstr "Pré-visualizar"
+
+msgid "Preview payload"
msgstr ""
msgid "Primary"
@@ -5533,10 +6103,10 @@ msgid "Profile Settings"
msgstr "Configurações do perfil"
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Você está prestes a excluir permanentemente a %{yourAccount}, e todas as issues, merge requests e grupos vinculados a sua conta. Depois de confirmar clicando em %{deleteAccount}, isso não poderá ser desfeito ou recuperado."
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
-msgstr ""
+msgstr "Você vai alterar o nome de usuário %{currentUsernameBold} para %{newUsernameBold}. O perfil e os projetos serão redirecionados para %{newUsername} mas esse redirecionamento expirará quando %{currentUsername} for registrado por outro usuário ou grupo. Por favor, atualize seus repositórios remotos Git o mais rápido possível."
msgid "Profiles|Account scheduled for removal."
msgstr "Conta agendada para remoção."
@@ -5545,17 +6115,32 @@ msgid "Profiles|Add key"
msgstr "Adicionar chave"
msgid "Profiles|Add status emoji"
+msgstr "Adicionar emoji de status"
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
msgstr ""
msgid "Profiles|Change username"
msgstr "Alterar nome de usuário"
-msgid "Profiles|Clear status"
+msgid "Profiles|Choose file..."
+msgstr "Escolher arquivo..."
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
msgstr ""
+msgid "Profiles|Clear status"
+msgstr "Limpar status"
+
msgid "Profiles|Current path: %{path}"
msgstr "Caminho atual: %{path}"
+msgid "Profiles|Current status"
+msgstr "Status atual"
+
msgid "Profiles|Delete Account"
msgstr "Excluir conta"
@@ -5568,37 +6153,118 @@ msgstr "Deseja apagar sua conta?"
msgid "Profiles|Deleting an account has the following effects:"
msgstr "Apagando conta tem os seguintes efeitos:"
+msgid "Profiles|Do not show on profile"
+msgstr "Não mostrar no perfil"
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr "Não exibir informações pessoais relacionadas à atividade em seus perfis"
+
+msgid "Profiles|Edit Profile"
+msgstr "Editar perfil"
+
msgid "Profiles|Invalid password"
msgstr "Senha inválida"
msgid "Profiles|Invalid username"
msgstr "Nome de usuário inválido"
+msgid "Profiles|Learn more"
+msgstr "Saiba mais"
+
+msgid "Profiles|Made a private contribution"
+msgstr "Fez uma contribuição privada"
+
+msgid "Profiles|Main settings"
+msgstr "Configurações principais"
+
+msgid "Profiles|No file chosen"
+msgstr "Nenhum arquivo escolhido"
+
msgid "Profiles|Path"
msgstr "Caminho"
+msgid "Profiles|Position and size your new avatar"
+msgstr "Posicione e dimensione seu novo avatar"
+
+msgid "Profiles|Private contributions"
+msgstr "Contribuições privadas"
+
+msgid "Profiles|Public Avatar"
+msgstr "Avatar público"
+
+msgid "Profiles|Remove avatar"
+msgstr "Remover avatar"
+
+msgid "Profiles|Set new profile picture"
+msgstr "Definir nova foto de perfil"
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr "Conte-nos sobre você em menos de 250 caracteres."
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr "O tamanho máximo de arquivo permitido é de 200KB."
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "Isso não se parece com uma chave pública SSH, você tem certeza que gostaria de adicioná-la?"
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr "Este e-mail será exibido no seu perfil público."
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr "Este e-mail será usado para operações baseadas na web, como edições e merges. %{learn_more}"
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr "Este emoji e mensagem aparecerão no seu perfil e em toda a interface."
+
+msgid "Profiles|This feature is experimental and translations are not complete yet."
msgstr ""
+msgid "Profiles|This information will appear on your profile."
+msgstr "Esta informação aparecerá no seu perfil."
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
-msgstr "Escreva %{confirmationValue} para confirmar:"
+msgstr "Escreva sua %{confirmationValue} para confirmar:"
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr "Geralmente se inicia com \"ssh-rsa …\""
+msgid "Profiles|Update profile settings"
+msgstr "Atualizar configurações do perfil"
+
msgid "Profiles|Update username"
msgstr "Atualizar nome de usuário"
+msgid "Profiles|Upload new avatar"
+msgstr "Enviar novo avatar"
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr "Falha na alteração de nome de usuário - %{message}"
msgid "Profiles|Username successfully changed"
msgstr "Alteração de nome de usuário realizada com sucesso"
+msgid "Profiles|Website"
+msgstr "Website"
+
msgid "Profiles|What's your status?"
+msgstr "Qual é o seu status?"
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
msgstr ""
msgid "Profiles|You don't have access to delete this user."
@@ -5610,9 +6276,18 @@ msgstr "Você precisa delegar outro usuário para ser dono ou apagar esses grupo
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "Sua conta é atualmente proprietária dos seguintes grupos:"
-msgid "Profiles|Your status"
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
msgstr ""
+msgid "Profiles|Your status"
+msgstr "Seu status"
+
msgid "Profiles|e.g. My MacBook key"
msgstr "por exemplo, Chave do meu MacBook"
@@ -5646,6 +6321,9 @@ msgstr "Projeto '%{project_name}' atualizado com sucesso."
msgid "Project Badges"
msgstr "Selos de projeto"
+msgid "Project URL"
+msgstr "URL do projeto"
+
msgid "Project access must be granted explicitly to each user."
msgstr "Acesso ao projeto deve ser concedido explicitamente para cada usuário."
@@ -5673,6 +6351,9 @@ msgstr "Exportação do projeto iniciada. Um link para baixá-la será enviado p
msgid "Project name"
msgstr "Nome do projeto"
+msgid "Project slug"
+msgstr "Slug do projeto"
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "Inscreva-se"
@@ -5700,17 +6381,38 @@ msgstr "Nunca"
msgid "ProjectLifecycle|Stage"
msgstr "Etapa"
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr "Marcar como favorito"
+
+msgid "ProjectOverview|Unstar"
+msgstr "Desmarcar como favorito"
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr "Você precisa entrar para marcar um projeto como favorito"
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "ID do Projeto: %{project_id}"
msgid "ProjectSettings|Badges"
-msgstr ""
+msgstr "Selos"
msgid "ProjectSettings|Contact an admin to change this setting."
msgstr "Contate um administrador para alterar essa configuração."
msgid "ProjectSettings|Customize your project badges."
-msgstr ""
+msgstr "Personalize os selos do seu projeto."
msgid "ProjectSettings|Failed to protect the tag"
msgstr "Falha ao proteger a tag"
@@ -5719,7 +6421,7 @@ msgid "ProjectSettings|Failed to update tag!"
msgstr "Falha ao atualizar a tag!"
msgid "ProjectSettings|Learn more about badges."
-msgstr ""
+msgstr "Saiba mais sobre os selos."
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Apenas para commits assinados pode-se fazer push para este repositório."
@@ -5742,6 +6444,9 @@ msgstr "Projetos"
msgid "Projects shared with %{group_name}"
msgstr "Projetos compartilhados com %{group_name}"
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr "Projetos que pertencem a um grupo são prefixados com o namespace do grupo. Projetos existentes podem ser movidos para um grupo."
+
msgid "ProjectsDropdown|Frequently visited"
msgstr "Visitados frequentemente"
@@ -5811,9 +6516,6 @@ msgstr "Configuração automática"
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr "Fazer deploy automático e configurar o Prometheus nos seus clusters para monitorar o ambiente do seu projeto"
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr "Por padrão, Prometheus escuta em 'http://localhost:9090'. Não é recomendado mudar o endereço padrão e sua porta, porque pode conflitar com outros serviços que estão executando no sevidor do Gitlab."
-
msgid "PrometheusService|Common metrics"
msgstr "Métricas comuns"
@@ -5896,10 +6598,10 @@ msgid "Promotions|Upgrade plan"
msgstr "Aprimorar plano"
msgid "Protected"
-msgstr ""
+msgstr "Protegido"
msgid "Protected Environments"
-msgstr ""
+msgstr "Ambientes Protegidos"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
@@ -5911,10 +6613,10 @@ msgid "ProtectedEnvironment|Choose who is allowed to deploy"
msgstr ""
msgid "ProtectedEnvironment|Environment"
-msgstr ""
+msgstr "Ambiente"
msgid "ProtectedEnvironment|Protect"
-msgstr ""
+msgstr "Proteger"
msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
msgstr ""
@@ -5932,7 +6634,7 @@ msgid "ProtectedEnvironment|There are currently no protected environments, prote
msgstr ""
msgid "ProtectedEnvironment|Unprotect"
-msgstr ""
+msgstr "Desproteger"
msgid "ProtectedEnvironment|Your environment can't be unprotected"
msgstr ""
@@ -5962,10 +6664,10 @@ msgid "Public pipelines"
msgstr "Pipelines públicos"
msgid "Pull"
-msgstr ""
+msgstr "Pull"
msgid "Push"
-msgstr ""
+msgstr "Push"
msgid "Push Rules"
msgstr "Regras de push"
@@ -6006,6 +6708,12 @@ msgstr "Leia-me"
msgid "Real-time features"
msgstr "Recursos em tempo real"
+msgid "Recent searches"
+msgstr "Pesquisas recentes"
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr "Referência:"
@@ -6018,7 +6726,7 @@ msgstr[0] ""
msgstr[1] ""
msgid "Regenerate key"
-msgstr ""
+msgstr "Gerar uma nova chave"
msgid "Regex pattern"
msgstr ""
@@ -6068,19 +6776,31 @@ msgstr "Remover Runner"
msgid "Remove avatar"
msgstr "Remover imagem"
+msgid "Remove group"
+msgstr "Remover grupo"
+
msgid "Remove priority"
msgstr "Remover prioridade"
msgid "Remove project"
msgstr "Remover projeto"
+msgid "Removed group can not be restored!"
+msgstr "O grupo removido não pode ser restaurado!"
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr "A remoção do grupo fará com que todos os projetos e recursos filhos sejam removidos."
+
msgid "Rename"
-msgstr ""
+msgstr "Renomear"
msgid "Rename file"
-msgstr ""
+msgstr "Renomear arquivo"
msgid "Rename folder"
+msgstr "Renomear pasta"
+
+msgid "Reopen epic"
msgstr ""
msgid "Repair authentication"
@@ -6092,28 +6812,46 @@ msgstr "Responda a este e-mail diretamente ou %{view_it_on_gitlab}."
msgid "Repo by URL"
msgstr "Repositório por URL"
+msgid "Report abuse to GitLab"
+msgstr "Denunciar abuso ao GitLab"
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
+msgstr "Classe"
+
+msgid "Reports|Confidence"
msgstr ""
msgid "Reports|Execution time"
-msgstr ""
+msgstr "Tempo de execução"
msgid "Reports|Failure"
-msgstr ""
+msgstr "Falha"
+
+msgid "Reports|Severity"
+msgstr "Gravidade"
msgid "Reports|System output"
-msgstr ""
+msgstr "Saída do sistema"
msgid "Reports|Test summary"
-msgstr ""
+msgstr "Resumo do teste"
msgid "Reports|Test summary failed loading results"
-msgstr ""
+msgstr "Resumo do teste falhou ao carregar os resultados"
msgid "Reports|Test summary results are being parsed"
+msgstr "Os resultados do resumo de teste estão sendo analisados"
+
+msgid "Reports|Vulnerability"
msgstr ""
msgid "Reports|no changed test results"
@@ -6149,12 +6887,12 @@ msgstr "Solicitar acesso"
msgid "Requests Profiles"
msgstr "Solicita Perfis"
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "Exija que todos os usuários aceitem Termos de Serviço e Política de Privacidade quando acessarem o GitLab."
-msgid "Reset git storage health information"
-msgstr "Reiniciar informações de status do storage Git"
-
msgid "Reset health check access token"
msgstr "Recriar o token de status de saúde"
@@ -6170,9 +6908,21 @@ msgstr "Resolver conflitos na branch de origem"
msgid "Resolve discussion"
msgstr "Resolver discussão"
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr "Métricas de resposta (personalizadas)"
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr "Continuar"
@@ -6186,7 +6936,7 @@ msgid "Retry verification"
msgstr "Tentar novamente a verificação"
msgid "Reveal Variables"
-msgstr ""
+msgstr "Revelar variáveis"
msgid "Reveal value"
msgid_plural "Reveal values"
@@ -6223,9 +6973,24 @@ msgstr "Executar pipelines CI/CD para repositórios externos"
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr "Token de runner"
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr "Runners"
@@ -6235,12 +7000,18 @@ msgstr "Runners de API"
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr "Os corredores podem ser colocados em usuários, servidores e até mesmo em sua máquina local."
-msgid "Runners page"
+msgid "Runners can be placed on separate users, servers, even on your local machine."
msgstr ""
-msgid "Runners page."
+msgid "Runners currently online: %{active_runners_count}"
msgstr ""
+msgid "Runners page"
+msgstr "Página de runners"
+
+msgid "Runners page."
+msgstr "Página de runners."
+
msgid "Runners|You have used all your shared Runners pipeline minutes."
msgstr ""
@@ -6259,6 +7030,9 @@ msgstr "SAML Single Sign On"
msgid "SAML Single Sign On Settings"
msgstr "Configurações de SAML Single Sign On"
+msgid "SAST"
+msgstr "SAST"
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr "Impressão digital SHA1 do certificado de assinatura de token SAML. Obtenha isso do seu provedor de identidade, onde ele também pode ser chamado de \"Thumbprint\"."
@@ -6269,7 +7043,7 @@ msgid "SSH host keys"
msgstr ""
msgid "SSH public key"
-msgstr ""
+msgstr "Chave SSH pública"
msgid "SSL Verification"
msgstr "Verificação SSL"
@@ -6283,6 +7057,9 @@ msgstr "Salvar aplicativo"
msgid "Save changes"
msgstr "Salvar alterações"
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Salvar agendamento da pipeline"
@@ -6305,7 +7082,7 @@ msgid "Scope"
msgstr "Escopo"
msgid "Scoped issue boards"
-msgstr "Issue boards de escopo"
+msgstr "Painéis de escopo"
msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
msgstr "Role para baixo até <strong>Google Code Project Hosting</strong> e ative a opção à direita."
@@ -6337,18 +7114,27 @@ msgstr "Pesquisar merge requests"
msgid "Search milestones"
msgstr "Pesquisar milestones"
+msgid "Search or filter results..."
+msgstr "Pesquisar ou filtrar resultados..."
+
msgid "Search or jump to…"
-msgstr ""
+msgstr "Pesquise ou pule para…"
msgid "Search project"
msgstr "Procurar projeto"
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr "Procurar usuários"
-msgid "SearchAutocomplete|All GitLab"
+msgid "Search your projects"
msgstr ""
+msgid "SearchAutocomplete|All GitLab"
+msgstr "Todo o GitLab"
+
msgid "SearchAutocomplete|Issues I've created"
msgstr ""
@@ -6356,41 +7142,69 @@ msgid "SearchAutocomplete|Issues assigned to me"
msgstr ""
msgid "SearchAutocomplete|Merge requests I've created"
-msgstr ""
+msgstr "Merge requests que eu criei"
msgid "SearchAutocomplete|Merge requests assigned to me"
-msgstr ""
+msgstr "Merge requests atribuídas a mim"
msgid "SearchAutocomplete|in all GitLab"
-msgstr ""
+msgstr "em todo o GitLab"
msgid "SearchAutocomplete|in this group"
-msgstr ""
+msgstr "neste grupo"
msgid "SearchAutocomplete|in this project"
+msgstr "neste projeto"
+
+msgid "Secret"
+msgstr "Secreto"
+
+msgid "Security"
+msgstr "Segurança"
+
+msgid "Security Dashboard"
+msgstr "Painel de controle de segurança"
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Seconds before reseting failure information"
-msgstr "Segundos antes de redefinir as informações de falha"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
-msgid "Seconds to wait for a storage access attempt"
-msgstr "Segundo de espera para tentativa de acesso ao storage"
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
-msgid "Secret:"
-msgstr "Secreto:"
+msgid "Security Dashboard|Issue Created"
+msgstr ""
-msgid "Security"
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
msgstr ""
-msgid "Security Dashboard"
-msgstr "Painel de controle de segurança"
+msgid "Security Reports|Create issue"
+msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6408,9 +7222,15 @@ msgstr "Selecionar"
msgid "Select Archive Format"
msgstr "Selecionar Formato do Arquivo"
+msgid "Select a group to invite"
+msgstr "Selecione um grupo para convidar"
+
msgid "Select a namespace to fork the project"
msgstr "Selecione um namespace para realizar o fork do projeto"
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr "Selecionar fuso horário"
@@ -6441,6 +7261,9 @@ msgstr "Selecionar branch de origem"
msgid "Select target branch"
msgstr "Selecionar branch de destino"
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6453,6 +7276,9 @@ msgstr "Sincronização seletiva"
msgid "Send email"
msgstr "Enviar e-mail"
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr "Set"
@@ -6477,6 +7303,9 @@ msgstr "Expiração de sessão, limite de projetos e tamanho de anexo."
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Defina uma senha para sua conta para aceitar ou entregar código via %{protocol}."
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr "Definir padrão e restringir os níveis de visibilidade. Configurar fontes de importação e protocolo de acesso git."
@@ -6495,8 +7324,11 @@ msgstr "Definir requisitos para um usuário entrar. Ative a autenticação obrig
msgid "Set up CI/CD"
msgstr "Configurar CI/CD"
-msgid "Set up Koding"
-msgstr "Configurar Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr "Configurar asserções/atributos/alegações (email, first_name, last_name) e NameID de acordo com %{docsLinkStart}a documentação %{icon}%{docsLinkEnd}"
@@ -6507,14 +7339,32 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "defina uma senha"
-msgid "Settings"
-msgstr "Configurações"
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
-msgstr "Configurar um Runner específico automaticamente"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr "Configurações"
msgid "Share"
msgstr "Compartilhar"
@@ -6525,6 +7375,9 @@ msgstr "Compartilhe o <strong>%{sso_label}</strong> com membros de forma que ele
msgid "Shared Runners"
msgstr "Runners Compartilhados"
+msgid "Shared projects"
+msgstr "Projetos compartilhados"
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr "Ao redefinir os minutos de pipeline para esse espaço de nomes, os minutos atualmente usados serão definido para zero."
@@ -6600,7 +7453,7 @@ msgid "Sign-up restrictions"
msgstr "Restrições de cadastro"
msgid "Size"
-msgstr ""
+msgstr "Tamanho"
msgid "Size and domain settings for static websites"
msgstr "Configurações de tamanho e domínio para sites estáticos"
@@ -6608,12 +7461,18 @@ msgstr "Configurações de tamanho e domínio para sites estáticos"
msgid "Slack application"
msgstr "Aplicativo Slack"
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
-msgstr ""
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr "A integração com o Slack permite que você interaja com o GitLab por meio de comandos de barra em uma janela de bate-papo."
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr "Mais lento, mas certifica-se que o espaço de trabalho do projeto está íntegro enquanto clona o repositório do zero para cada tarefa"
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr "Snippets"
@@ -6641,9 +7500,15 @@ msgstr "Algo deu errado ao fechar o %{issuable}. Por favor, tente novamente depo
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr "Algo deu errado ao obter as contribuições de membro do grupo"
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr "Algo deu errado ao recuperar os projetos."
@@ -6656,12 +7521,24 @@ msgstr "Alguma coisa deu errado ao reabrir o %{issuable}. Por favor, tente novam
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr "Algo deu errado ao resolver essa discussão. Por favor, tente novamente."
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr "Algo deu errado. Por favor, tente novamente."
msgid "Sorry, no epics matched your search"
msgstr "Desculpe, nenhum épico corresponde à sua pesquisa"
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr "Ordenar por"
@@ -6692,6 +7569,9 @@ msgstr "Maior grupo"
msgid "SortOptions|Largest repository"
msgstr "Maior repositório"
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr "Últimos criados"
@@ -6722,6 +7602,9 @@ msgstr "Mais peso"
msgid "SortOptions|Most popular"
msgstr "Mais populares"
+msgid "SortOptions|Most stars"
+msgstr "Mais favoritos"
+
msgid "SortOptions|Name"
msgstr "Nome"
@@ -6752,6 +7635,9 @@ msgstr "Prioridade"
msgid "SortOptions|Recent sign in"
msgstr "Assinados mais novos"
+msgid "SortOptions|Start date"
+msgstr "Data de início"
+
msgid "SortOptions|Start later"
msgstr "Iniciar mais tarde"
@@ -6827,9 +7713,21 @@ msgstr "Projetos favoritos"
msgid "Start a %{new_merge_request} with these changes"
msgstr "Iniciar um %{new_merge_request} a partir dessas alterações"
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr "Data de início"
+
msgid "Start the Runner!"
msgstr "Inicie o Runner!"
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr "Iniciado"
@@ -6842,6 +7740,9 @@ msgstr "Regitre sua mensagem para ativar"
msgid "Status"
msgstr "Status"
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr "Parar representação"
@@ -6851,6 +7752,9 @@ msgstr "Parar este ambiente"
msgid "Stopped"
msgstr "Parado"
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr "Armazenamento"
@@ -6860,9 +7764,15 @@ msgstr "Armazenamento:"
msgid "Subgroups"
msgstr "Subgrupos"
+msgid "Subgroups and projects"
+msgstr "Subgrupos e projetos"
+
msgid "Submit as spam"
msgstr "Enviar como spam"
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr "Buscar"
@@ -6875,6 +7785,12 @@ msgstr "Inscrever-se no nível de grupo"
msgid "Subscribe at project level"
msgstr "Inscrever-se no nível do projeto"
+msgid "Subscribed"
+msgstr "Inscrito"
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Trocar branch/tag"
@@ -6893,6 +7809,9 @@ msgstr "Cabeçalho e rodapé de sistema:"
msgid "System metrics (Custom)"
msgstr "Métricas de sistema (Personalizado)"
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] "Tag (%{tag_count})"
@@ -6902,7 +7821,7 @@ msgid "Tags"
msgstr "Tags"
msgid "Tags feed"
-msgstr ""
+msgstr "Feed de tags"
msgid "Tags:"
msgstr "Tags:"
@@ -6986,10 +7905,10 @@ msgid "Team"
msgstr "Equipe"
msgid "Template"
-msgstr ""
+msgstr "Modelo"
msgid "Templates"
-msgstr ""
+msgstr "Modelos"
msgid "Terms of Service Agreement and Privacy Policy"
msgstr "Contrato de Termos de Serviço e Política de Privacidade"
@@ -6997,6 +7916,9 @@ msgstr "Contrato de Termos de Serviço e Política de Privacidade"
msgid "Terms of Service and Privacy Policy"
msgstr "Termos de Serviço e Política de Privacidade"
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "Análise de cobertura de teste"
@@ -7040,17 +7962,11 @@ msgid "The import will time out after %{timeout}. For repositories that take lon
msgstr "A importação expirará após %{timeout}. Para repositórios que demoram mais tempo, use a combinação clone/push."
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
-msgstr "A etapa de planejamento mostra o tempo que se leva desde a criação de uma issue até sua atribuição à um milestone, ou sua adição a uma lista no seu Issue Board. Comece a criar issues para ver dados para esta etapa."
+msgstr "A etapa de planejamento mostra o tempo que se leva desde a criação de uma issue até sua atribuição à um milestone, ou sua adição a uma lista no seu painel. Comece a criar issues para ver dados para esta etapa."
msgid "The maximum file size allowed is 200KB."
msgstr "O tamanho máximo do arquivo é de 200KB."
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr "O número de tentativas que gitlab fará para acessar um storage."
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr "O número de falhas para que GitLab impeça completamente o acesso ao armazenamento. O número de falhas pode ser redefinido na interface do administrador: %{link_to_health_page} ou usando a %{api_documentation_link}."
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "A senha necessária para descriptografar a chave privada. Isso é opcional e o seu valor é criptografado."
@@ -7091,7 +8007,7 @@ msgid "The repository must be accessible over <code>http://</code>, <code>https:
msgstr "O repositório deve ser acessível por <code>http://</code>, <code>https://</code> ou <code>git://</code>."
msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
-msgstr ""
+msgstr "O repositório deve ser acessível por <code>http://</code>, <code>https://</code>, <code>ssh://</code> e <code>git://</code>."
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "A etapa de revisão mostra o tempo de criação de uma solicitação de incorporação até sua aceitação. Os dados serão automaticamente adicionados depois que sua primeira solicitação de incorporação for aceita."
@@ -7099,33 +8015,24 @@ msgstr "A etapa de revisão mostra o tempo de criação de uma solicitação de
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr "O roadmap mostra o progresso de seus epics ao longo de uma linha do tempo"
-msgid "The secure token used by the Runner to checkout the project"
-msgstr "O token seguro usado pelo Runner para fazer checkout do projeto"
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "A etapa de homologação mostra o tempo entre o aceite da solicitação de incorporação e a implantação do código no ambiente de produção. Os dados serão automaticamente adicionados depois que você implantar em produção pela primeira vez."
msgid "The tabs below will be removed in a future version"
-msgstr ""
+msgstr "As guias abaixo serão removidas em uma versão futura"
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr "A etapa de testes mostra o tempo que o GitLab CI leva para executar cada pipeline para a solicitação de incorporação associada. Os dados serão automaticamente adicionados após a conclusão do primeiro pipeline."
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr "Tempo em segundos para o GitLab manter as informações de falha. Se nenhuma falha ocorrer durante este tempo, a informação sobre o ponto de montagem será redefinida."
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr "Tempo em segundos que o GitLab tentará acessar o storage. Depois desse tempo, um erro de tempo excedido será disparado."
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr "O tempo em segundos entre as verificações de armazenamento. Quando uma verificação anterior ainda não tiver sido concluída, o GitLab pulará a próxima verificação."
-
msgid "The time taken by each data entry gathered by that stage."
msgstr "O tempo necessário por cada entrada de dados reunida por essa etapa."
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr "O mapa do usuário é um documento JSON que mapeia os usuários do Google Code que participaram de seus projetos para a maneira como seus endereços de e-mail e nomes de usuários são importados para o GitLab. Você pode mudar isso alterando o valor no lado direito de <code>:</code>. Certifique-se de preservar as aspas duplas adjacentes, outros sinais de pontuação e o endereço de e-mail ou nome de usuário no lado esquerdo."
@@ -7135,6 +8042,9 @@ msgstr "O mapa do usuário é um mapeamento dos usuários do FogBugz que partici
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "O valor situado no ponto médio de uma série de valores observados. Ex., entre 3, 5, 9, a mediana é 5. Entre 3, 5, 7, 8, a mediana é (5+7)/2 = 6."
+msgid "There are no archived projects yet"
+msgstr "Ainda não há projetos arquivados"
+
msgid "There are no issues to show"
msgstr "Não há issues para mostrar"
@@ -7144,8 +8054,14 @@ msgstr "Ainda não há etiquetas"
msgid "There are no merge requests to show"
msgstr "Não há merge requests pra mostrar"
-msgid "There are problems accessing Git storage: "
-msgstr "Há problemas para acessar o storage Git: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
msgid "There was an error adding a todo."
msgstr ""
@@ -7187,15 +8103,18 @@ msgid "This application will be able to:"
msgstr "Esse aplicativo será capaz de:"
msgid "This board's scope is reduced"
-msgstr ""
+msgstr "O escopo deste painel está reduzido"
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7216,6 +8135,9 @@ msgstr "Este grupo não fornece nenhum grupo de Runners ainda."
msgid "This is a confidential issue."
msgstr "Essa issue é confidencial."
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr "Esse é o autor do primeiro merge request desse projeto."
@@ -7255,7 +8177,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7276,6 +8201,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr "Este Job exige uma ação manual"
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Isto significa que você não pode entregar código até que crie um repositório vazio ou importe um existente."
@@ -7300,6 +8228,9 @@ msgstr "Esse projeto"
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr "Este projeto não pertence a um grupo e, portanto, não pode usar os Runners do grupo."
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7309,6 +8240,12 @@ msgstr "Esse repositório"
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr "Esse diff de origem não pôde ser exibido porque é muito grande."
@@ -7336,9 +8273,15 @@ msgstr "Tempo até que uma issue seja agendada"
msgid "Time before an issue starts implementation"
msgstr "Tempo até que uma issue comece a ser implementado"
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr "Tempo entre a criação da solicitação de incorporação e a aceitação/fechamento"
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr "Tempo em segundos o GitLab aguardará uma resposta do serviço externo. Quando o serviço não responder a tempo, o acesso será negado."
@@ -7529,12 +8472,24 @@ msgstr "Para conectar um repositório SVN, confira %{svn_link}."
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr "Para começar, insira seu URL do FogBugz e as informações de login abaixo. Nas próximas etapas, você poderá associar usuários e selecionar os projetos que deseja importar."
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr "Para começar, insira seu URL de Host do Gitea e um %{link_to_personal_token}."
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr "Para ajudar a melhorar o GitLab, gostaríamos de coletar periodicamente informações de uso. Isso pode ser alterado a qualquer momento em %{settings_link_start}Configurações%{link_end}. %{info_link_start}Mais informações%{link_end}"
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr "Para importar repositórios do GitHub, você pode usar um %{personal_access_token_link}. Ao criar seu Token de Acesso Pessoal, você precisará selecionar o escopo <code>repo</code>, para que possamos exibir uma lista de seus repositórios públicos e privados que estão disponíveis para importação."
@@ -7550,6 +8505,9 @@ msgstr "Para mover ou copiar todo um projeto do GitLab de outra instalação do
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr "Para usar apenas recursos CI/CD para um repositório externo, escolha <strong>CI/CD para repo externo</strong>."
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr "Para configurar a autenticação SAML para o seu grupo por meio de um provedor de identidade, como Azure, Okta, Onelogin, Ping Identity ou seu provedor SAML 2.0 personalizado:"
@@ -7562,12 +8520,15 @@ msgstr "Para esta instância do GitLab"
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr "Para validar suas configurações de CI do GitLab, vá para 'CI/CD → Pipelines' dentro do seu projeto e clique no botão 'CI Lint'."
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
-msgstr "Para visualizar o roadmap, adicione uma data de início ou término planejada a um dos seus épicos nesse grupo ou em seus subgrupos. Apenas épicos nos últimos 3 meses e nos próximos 3 meses são mostrados."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
msgid "To widen your search, change or remove filters."
msgstr "Para ampliar sua pesquisa, alterar ou remover filtros."
+msgid "Today"
+msgstr "Hoje"
+
msgid "Todo"
msgstr "Pendente"
@@ -7577,9 +8538,15 @@ msgstr "Afazeres"
msgid "Toggle Sidebar"
msgstr "Alternar barra lateral"
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr "Alternar discussão"
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Alternar navegação"
@@ -7593,7 +8560,10 @@ msgid "ToggleButton|Toggle Status: ON"
msgstr "Mudar Status: Ligado"
msgid "Token"
-msgstr ""
+msgstr "Token"
+
+msgid "Tomorrow"
+msgstr "Amanhã"
msgid "Too many changes to show."
msgstr "Alterações demais para mostrar."
@@ -7610,6 +8580,9 @@ msgstr "Tempo de teste total para todos os commits/merges"
msgid "Total: %{total}"
msgstr "Total: %{total}"
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr "Acompanhe atividades com a Análise de Contribuições."
@@ -7619,6 +8592,9 @@ msgstr "Acompanhe grupos de issues que compartilhem um tema, em projetos e miles
msgid "Track time with quick actions"
msgstr "Acompanhe o tempo com ações rápidas"
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr "Mais populares"
@@ -7637,24 +8613,42 @@ msgstr "Acionar esta ação manual"
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr "Os gatilhos podem forçar uma build numa branch ou tag específica através da API. Esses tokens representarão seu usuário associado, incluindo seu acesso a projetos e suas permissões de projeto."
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr "Tente novamente"
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "Ativar o Balcão de Atendimento"
msgid "Twitter"
msgstr "Twitter"
-msgid "Type"
+msgid "Two-factor authentication"
msgstr ""
+msgid "Type"
+msgstr "Tipo"
+
msgid "Unable to load the diff. %{button_try_again}"
msgstr "Não é possível carregar o diff. %{button_try_again}"
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "Não é possível inscrever você no grupo com SAML devido a \"%{reason}\""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr "Desfazer"
+
msgid "Unknown"
msgstr "Desconhecido"
@@ -7670,6 +8664,12 @@ msgstr "Desbloqueado"
msgid "Unresolve discussion"
msgstr "Reabrir discussão"
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr "Retirar tudo da lista para commit"
@@ -7703,17 +8703,20 @@ msgstr "Não verificado"
msgid "Up to date"
msgstr "Atualizado"
+msgid "Upcoming"
+msgstr "Em breve"
+
msgid "Update"
msgstr "Atualizar"
msgid "Update now"
-msgstr ""
+msgstr "Atualizar agora"
-msgid "Update your group name, description, avatar, and other general settings."
-msgstr "Atualize o nome do seu grupo, descrição, avatar e outras configurações gerais."
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
msgid "Updating"
-msgstr ""
+msgstr "Atualizando"
msgid "Upgrade your plan to activate Advanced Global Search."
msgstr "Aprimore seu plano para ativar a Pesquisa Global Avançada."
@@ -7728,7 +8731,7 @@ msgid "Upgrade your plan to activate Issue weight."
msgstr "Faça upgrade de plano para ativar o peso nas Issues."
msgid "Upgrade your plan to improve Issue boards."
-msgstr "Faça upgrade de plano para melhorar o Issue boards."
+msgstr "Faça upgrade de plano para melhorar os painéis."
msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
msgstr "Envie o <code>GoogleCodeProjectHosting.json</code> aqui:"
@@ -7739,15 +8742,15 @@ msgstr "Enviar Novo Arquivo"
msgid "Upload file"
msgstr "Enviar arquivo"
-msgid "Upload new avatar"
-msgstr "Fazer upload de nova imagem"
-
msgid "UploadLink|click to upload"
msgstr "clique para fazer upload"
msgid "Upvotes"
msgstr "Votos positivos"
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr "Estatísticas de uso"
@@ -7764,7 +8767,7 @@ msgid "Use one line per URI"
msgstr "Use uma linha por URI"
msgid "Use template"
-msgstr ""
+msgstr "Utilizar modelo"
msgid "Use the following registration token during setup:"
msgstr "Use o seguinte token de registro durante a configuração:"
@@ -7775,6 +8778,9 @@ msgstr "Utilizar configuração de notificação global"
msgid "Used by members to sign in to your group in GitLab"
msgstr "Utilizado pelos membros para entrar em seu grupo no GitLab"
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr "Configurações do Usuário"
@@ -7784,12 +8790,54 @@ msgstr "Limites de Taxa de Usuário e IP"
msgid "User map"
msgstr "Mapa do usuário"
-msgid "Users"
-msgstr "Usuários"
+msgid "UserProfile|Activity"
+msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|Already reported for abuse"
msgstr ""
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr "Editar perfil"
+
+msgid "UserProfile|Groups"
+msgstr "Grupos"
+
+msgid "UserProfile|Most Recent Activity"
+msgstr "Atividade mais recente"
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr "Projetos pessoais"
+
+msgid "UserProfile|Recent contributions"
+msgstr "Contribuições recentes"
+
+msgid "UserProfile|Report abuse"
+msgstr "Denunciar abuso"
+
+msgid "UserProfile|Snippets"
+msgstr "Snippets"
+
+msgid "UserProfile|Subscribe"
+msgstr "Inscrever-se"
+
+msgid "UserProfile|This user has a private profile"
+msgstr "Este usuário tem um perfil privado"
+
+msgid "UserProfile|View all"
+msgstr "Ver tudo"
+
+msgid "UserProfile|View user in admin area"
+msgstr "Exibir usuário na área administrativa"
+
+msgid "Users"
+msgstr "Usuários"
+
msgid "Variables"
msgstr "Variáveis"
@@ -7812,8 +8860,17 @@ msgid "Verified"
msgstr "Verificado"
msgid "Version"
+msgstr "Versão"
+
+msgid "View %{alerts}"
+msgstr "Visualizar %{alerts}"
+
+msgid "View app"
msgstr ""
+msgid "View documentation"
+msgstr "Ver documentação"
+
msgid "View epics list"
msgstr "Ve lista de épicos"
@@ -7847,9 +8904,15 @@ msgstr "Ver etiquetas de projeto"
msgid "View replaced file @ "
msgstr "Ver arquivo substituído @ "
+msgid "View the documentation"
+msgstr "Ver a documentação"
+
msgid "Visibility and access controls"
msgstr "Visibilidade e controles de acesso"
+msgid "Visibility level"
+msgstr "Nível de visibilidade"
+
msgid "Visibility level:"
msgstr "Nível de visibilidade:"
@@ -7868,6 +8931,36 @@ msgstr "Público"
msgid "VisibilityLevel|Unknown"
msgstr "Desconhecido"
+msgid "Vulnerability|Class"
+msgstr "Classe"
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr "Descrição"
+
+msgid "Vulnerability|File"
+msgstr "Arquivo"
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr "Projeto"
+
+msgid "Vulnerability|Severity"
+msgstr "Gravidade"
+
+msgid "Vulnerability|Solution"
+msgstr "Solução"
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Precisa visualizar os dados? Solicite acesso ao administrador."
@@ -7907,6 +9000,12 @@ msgstr "Quando ativado, os usuários não podem usar o GitLab até que os termos
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "Ao deixar o URL em branco, a classificação das etiquetas ainda podem ser especificadas sem desativar os recursos do projeto ou executar verificações de autorização externas."
+msgid "Who can see this group?"
+msgstr "Quem pode ver esse grupo?"
+
+msgid "Who will be able to see this group?"
+msgstr "Quem poderá ver esse grupo?"
+
msgid "Wiki"
msgstr "Wiki"
@@ -8057,6 +9156,9 @@ msgstr "Sim, adicionar"
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr "Sim, deixe-me associar usuários do Google Code para nomes completos ou usuários do GitLab."
+msgid "Yesterday"
+msgstr "Ontem"
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr "Você é um administrador, o que significa que conceder acesso a <strong>%{client_name}</strong> permitirá que eles também interajam com o GitLab como administrador. Prossiga com cuidado."
@@ -8075,9 +9177,6 @@ msgstr "Você irá transferir %{project_full_name} para outro proprietário. Tem
msgid "You are on a read-only GitLab instance."
msgstr "Você está em uma instância somente-leitura do GitLab."
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr "Você está em um Geo node <b>somente leitura</b> secundário. Se você quiser fazer alguma alteração, você precisa visitar essa página no %{primary_node}."
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr "Você pode %{linkStart}visualizar o blob%{linkEnd} em vez disso."
@@ -8087,9 +9186,6 @@ msgstr "Você também pode criar um projeto a partir da linha de comando."
msgid "You can also star a label to make it a priority label."
msgstr "Você também pode marcar uma etiqueta para torná-la uma etiqueta de prioridade."
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr "Você também pode testar o seu .gitlab-ci.yml no %{linkStart}Lint%{linkEnd}"
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr "Você pode facilmente contribuir para eles pedindo para se juntar nesses grupos."
@@ -8111,12 +9207,18 @@ msgstr "Você pode resolver o conflito de merge usando o modo Interativo, escolh
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr "Você não pode escrever numa instância secundária de somente leitura do GitLab Geo. Por favor use %{link_to_primary_node} em vez disso."
msgid "You cannot write to this read-only GitLab instance."
msgstr "Você não pode escrever nesta instância somente-leitura do GitLab."
+msgid "You do not have any subscriptions yet"
+msgstr "Você ainda não tem nenhuma inscrição"
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "Você não tem as permissões corretas para substituir as configurações de sincronização do grupo LDAP."
@@ -8138,9 +9240,6 @@ msgstr "Você deve aceitar nossos Termos de Serviço e política de privacidade
msgid "You must have maintainer access to force delete a lock"
msgstr "Você deve ter o acesso de mantenedor para apagar um bloqueio"
-msgid "You must sign in to star a project"
-msgstr "Você deve estar autenticado para marcar um projeto"
-
msgid "You need a different license to enable FileLocks feature"
msgstr "Você precisa de uma licença diferente para ativar o recurso FileLocks"
@@ -8150,6 +9249,12 @@ msgstr "Você precisa do git-lfs na versão %{min_git_lfs_version} (ou maior) pa
msgid "You need permission."
msgstr "Você precisa de permissão."
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr "Você não será notificado por email"
@@ -8216,6 +9321,9 @@ msgstr "Você pode fazer commit de suas alterações para %{branch_name} porque
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr "Commit com suas alterações realizado. Commit %{commitId} %{commitStats}"
+msgid "Your changes have been saved"
+msgstr "Suas alterações foram salvas"
+
msgid "Your comment will not be visible to the public."
msgstr "Seu comentário não estará visível ao público."
@@ -8229,7 +9337,7 @@ msgid "Your projects"
msgstr "Seus projetos"
msgid "a deleted user"
-msgstr ""
+msgstr "um usuário excluído"
msgid "ago"
msgstr "atrás"
@@ -8237,16 +9345,6 @@ msgstr "atrás"
msgid "among other things"
msgstr "entre outras coisas"
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] "e 1 vulnerabilidade corrigida"
-msgstr[1] "e %d vulnerabilidades corrigidas"
-
msgid "assign yourself"
msgstr "atribuir a si mesmo"
@@ -8274,20 +9372,55 @@ msgstr "%{namespace} é afetado por %{vulnerability}."
msgid "ciReport|%{remainingPackagesCount} more"
msgstr "mais %{remainingPackagesCount}"
-msgid "ciReport|%{reportName} is loading"
-msgstr "%{reportName} está carregando"
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
-msgstr "%{reportName} resultou em erro ao carregar os resultados"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] "%{reportType} detectou %{vulnerabilityCount} vulnerabilidade"
+msgstr[1] "%{reportType} detectou %{vulnerabilityCount} vulnerabilidades"
-msgid "ciReport|%{type} detected no new security vulnerabilities"
-msgstr "%{type} não detectou novas vulnerabilidades de segurança"
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr "%{reportType} não detectou vulnerabilidades"
-msgid "ciReport|%{type} detected no security vulnerabilities"
-msgstr "%{type} não detectou vulnerabilidades de segurança"
+msgid "ciReport|%{reportType} is loading"
+msgstr "%{reportType} está carregando"
-msgid "ciReport|%{type} detected no vulnerabilities"
-msgstr "%{type} não detectou vulnerabilidades"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr "(erros ao carregar resultados)"
+
+msgid "ciReport|(is loading)"
+msgstr "(está carregando)"
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr "(está carregando, erros ao carregar resultados)"
msgid "ciReport|Class"
msgstr "Classe"
@@ -8298,38 +9431,20 @@ msgstr "Qualidade do código"
msgid "ciReport|Confidence"
msgstr "Confiança"
-msgid "ciReport|Container scanning detected"
-msgstr "Verificação de contêiner detectada"
+msgid "ciReport|Container scanning"
+msgstr ""
msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr "A varredura de contêiner detectou vulnerabilidades conhecidas em suas imagens docker."
-msgid "ciReport|Container scanning is loading"
-msgstr "A verificação do container está carregando"
-
-msgid "ciReport|Container scanning resulted in error while loading results"
-msgstr "Verificação do container resultou em erro ao carregar os resultados"
-
-msgid "ciReport|DAST detected"
-msgstr "DAST detectado"
-
-msgid "ciReport|DAST is loading"
-msgstr "DAST está carregando"
-
-msgid "ciReport|DAST resulted in error while loading results"
-msgstr "DAST resultou em erro ao carregar os resultados"
+msgid "ciReport|DAST"
+msgstr ""
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
-msgstr "Verificação de dependência detectada"
-
-msgid "ciReport|Dependency scanning is loading"
-msgstr "A verificação de dependência está carregando"
-
-msgid "ciReport|Dependency scanning resulted in error while loading results"
-msgstr "Verificação de dependência resultou em erro ao carregar os resultados"
+msgid "ciReport|Dependency scanning"
+msgstr ""
msgid "ciReport|Description"
msgstr "Descrição"
@@ -8361,9 +9476,6 @@ msgstr "Instâncias"
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr "Saiba mais sobre como interagir com relatórios de segurança (Alpha)."
-msgid "ciReport|Learn more about whitelisting"
-msgstr "Saiba mais sobre whitelist"
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8386,6 +9498,9 @@ msgstr "Links"
msgid "ciReport|Loading %{reportName} report"
msgstr "Carregando relatório %{reportName}"
+msgid "ciReport|Manage licenses"
+msgstr "Gerenciar licenças"
+
msgid "ciReport|Method"
msgstr "Método"
@@ -8404,14 +9519,8 @@ msgstr "Métricas de desempenho"
msgid "ciReport|Revert dismissal"
msgstr "Reverter ignorar"
-msgid "ciReport|SAST detected"
-msgstr "SAST detectado"
-
-msgid "ciReport|SAST is loading"
-msgstr "SAST está carregando"
-
-msgid "ciReport|SAST resulted in error while loading results"
-msgstr "SAST resultou em erro ao carregar os resultados"
+msgid "ciReport|SAST"
+msgstr ""
msgid "ciReport|Security scanning"
msgstr "Verificação de segurança"
@@ -8419,9 +9528,6 @@ msgstr "Verificação de segurança"
msgid "ciReport|Security scanning failed loading any results"
msgstr "A verificação de segurança falhou ao carregar resultados"
-msgid "ciReport|Security scanning is loading"
-msgstr "A verificação de segurança está carregando"
-
msgid "ciReport|Severity"
msgstr "Severidade"
@@ -8452,23 +9558,17 @@ msgstr "Ocorreu um erro ao carregar o relatório de verificação de dependênci
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "Houve um erro ao reverter o descarte. Por favor, tente novamente."
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr "Vulnerabilidades não aprovadas (vermelho) podem ser marcadas como aprovadas."
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr "Atualizar %{name} de %{version} para %{fixed}."
msgid "ciReport|Used by %{packagesString}"
msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Usado por %{packagesString}"
+msgstr[1] "Usado por %{packagesString} e %{lastPackage}"
msgid "ciReport|View full report"
msgstr "Visualizar relatório completo"
-msgid "ciReport|no vulnerabilities"
-msgstr "sem vulnerabilidades"
-
msgid "ciReport|on pipeline"
msgstr "na pipeline"
@@ -8498,25 +9598,17 @@ msgstr[1] "dias"
msgid "deploy token"
msgstr "token de deploy"
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] "detectada %d vulnerabilidade corrigida"
-msgstr[1] "detectada %d vulnerabilidades corrigidas"
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] "detectada %d nova vulnerabilidade"
-msgstr[1] "detectadas %d novas vulnerabilidades"
-
-msgid "detected no vulnerabilities"
-msgstr "nenhuma vulnerabilidade detectada"
-
msgid "disabled"
msgstr "desabilitado"
msgid "done"
msgstr "concluído"
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] "rascunho"
+msgstr[1] "rascunhos"
+
msgid "enabled"
msgstr "habilitado"
@@ -8526,11 +9618,17 @@ msgstr "%{slash_command} irá atualizar o tempo estimado com o último comando."
msgid "for this project"
msgstr "para este projeto"
+msgid "from"
+msgstr "de"
+
+msgid "help"
+msgstr "ajuda"
+
msgid "here"
msgstr "aqui"
msgid "https://your-bitbucket-server"
-msgstr ""
+msgstr "https://seu-servidor-do-bitbucket"
msgid "import flow"
msgstr "fluxo de importação"
@@ -8553,13 +9651,16 @@ msgid "is not a valid X509 certificate."
msgstr "não é um certificado X509 válido."
msgid "issue boards"
+msgstr "painéis"
+
+msgid "latest deployment"
msgstr ""
msgid "latest version"
msgstr "versão mais recente"
msgid "license management"
-msgstr ""
+msgstr "gerenciamento de licenças"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "bloqueador por %{path_lock_user_name} %{created_at}"
@@ -8690,7 +9791,7 @@ msgid "mrWidget|Plain diff"
msgstr "Diff em texto"
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
-msgstr ""
+msgstr "Pronto para ser feito merge automaticamente. Peça a alguém com acesso de gravação a este repositório para dar merge nesse request"
msgid "mrWidget|Refresh"
msgstr "Atualizar"
@@ -8715,13 +9816,13 @@ msgstr "Merge de"
msgid "mrWidget|Requires 1 more approval"
msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Requer mais 1 aprovação"
+msgstr[1] "Requer mais %d aprovações"
msgid "mrWidget|Requires 1 more approval by"
msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Requer mais 1 aprovação por"
+msgstr[1] "Requer mais %d aprovações por"
msgid "mrWidget|Resolve conflicts"
msgstr "Resolver conflitos"
@@ -8783,6 +9884,9 @@ msgstr "Esse merge request está em processamento"
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "Este projeto está arquivado, a escrita foi desativada"
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr "Você pode fazer merge manualmente usando o"
@@ -8801,6 +9905,9 @@ msgstr "para"
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr "para ser realizado merge automaticamente quando o pipeline for bem sucedido"
+msgid "n/a"
+msgstr "n/a"
+
msgid "new merge request"
msgstr "novo merge request"
@@ -8812,8 +9919,8 @@ msgstr "ou"
msgid "out of %d total test"
msgid_plural "out of %d total tests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "de um total de %d teste"
+msgstr[1] "de um total de %d testes"
msgid "parent"
msgid_plural "parents"
@@ -8829,11 +9936,16 @@ msgstr "token de acesso pessoal"
msgid "private key does not match certificate."
msgstr "chave privada não corresponde ao certificado."
+msgid "project"
+msgid_plural "projects"
+msgstr[0] "projeto"
+msgstr[1] "projetos"
+
msgid "remaining"
msgstr "restante"
msgid "remove"
-msgstr ""
+msgstr "remover"
msgid "remove due date"
msgstr "remover a data de vencimento"
@@ -8841,6 +9953,11 @@ msgstr "remover a data de vencimento"
msgid "remove weight"
msgstr "remover peso"
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] "resposta"
+msgstr[1] "respostas"
+
msgid "source"
msgstr "origem"
@@ -8856,6 +9973,9 @@ msgstr "este documento"
msgid "to help your contributors communicate effectively!"
msgstr "para ajudar seus contribuintes à se comunicar de maneira eficaz!"
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr "nome do usuário"
diff --git a/locale/pt_PT/gitlab.po b/locale/pt_PT/gitlab.po
new file mode 100644
index 00000000000..c283bd4de93
--- /dev/null
+++ b/locale/pt_PT/gitlab.po
@@ -0,0 +1,9995 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
+"Language-Team: Portuguese\n"
+"Language: pt_PT\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: pt-PT\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"PO-Revision-Date: 2018-11-19 17:18\n"
+
+msgid " Status"
+msgstr ""
+
+msgid " and"
+msgstr ""
+
+msgid " degraded on %d point"
+msgid_plural " degraded on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid " improved on %d point"
+msgid_plural " improved on %d points"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d changed file"
+msgid_plural "%d changed files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d failed test result"
+msgid_plural "%d failed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d staged change"
+msgid_plural "%d staged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%d unstaged change"
+msgid_plural "%d unstaged changes"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_timeago}"
+msgstr ""
+
+msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgstr ""
+
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{loadingIcon} Started"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+msgid "%{nip_domain} can be used as an alternative to a custom domain."
+msgstr ""
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr ""
+
+msgid "%{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
+
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid "- Runner is active and can process any new jobs"
+msgstr ""
+
+msgid "- Runner is paused and will not receive any new jobs"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "1 %{type} addition"
+msgid_plural "%{count} %{type} additions"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 %{type} modification"
+msgid_plural "%{count} %{type} modifications"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed issue"
+msgid_plural "%d closed issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 closed merge request"
+msgid_plural "%d closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 merged merge request"
+msgid_plural "%d merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 open merge request"
+msgid_plural "%d open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1 user"
+msgid_plural "%d users"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "2FA enabled"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get the permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
+msgstr ""
+
+msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
+msgstr ""
+
+msgid "<strong>%{group_name}</strong> group members"
+msgstr ""
+
+msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
+msgstr ""
+
+msgid "<strong>Removes</strong> source branch"
+msgstr ""
+
+msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
+msgstr ""
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
+msgstr ""
+
+msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About GitLab CE"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Accepted MR"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied! Please verify you can add deploy keys to this repository."
+msgstr ""
+
+msgid "Access expiration date"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add Changelog"
+msgstr ""
+
+msgid "Add Contribution guide"
+msgstr ""
+
+msgid "Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add Readme"
+msgstr ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add projects"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add todo"
+msgstr ""
+
+msgid "Add user(s) to the group:"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Admin Area"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "Admin area"
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminProjects|Delete project"
+msgstr ""
+
+msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
+
+msgid "Advanced settings"
+msgstr ""
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "All"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr ""
+
+msgid "All users"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch."
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts"
+msgstr ""
+
+msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
+msgstr ""
+
+msgid "Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An error accured whilst committing your changes."
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error occured creating the new branch."
+msgstr ""
+
+msgid "An error occured whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occured whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occured whilst loading all the files."
+msgstr ""
+
+msgid "An error occured whilst loading the file content."
+msgstr ""
+
+msgid "An error occured whilst loading the file."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request."
+msgstr ""
+
+msgid "An error occured whilst loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
+msgstr ""
+
+msgid "An error occurred while adding approver"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while fetching markdown preview"
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching sidebar data"
+msgstr ""
+
+msgid "An error occurred while fetching stages."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the pipeline."
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while importing project: %{details}"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while removing approver"
+msgstr ""
+
+msgid "An error occurred while rendering KaTeX"
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while retrieving calendar activity"
+msgstr ""
+
+msgid "An error occurred while retrieving diff"
+msgstr ""
+
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
+msgstr ""
+
+msgid "An error occurred while subscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while unsubscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any Label"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read-only"
+msgstr ""
+
+msgid "Archived projects"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Artifact ID"
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer to set up a group Runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned Merge Requests"
+msgstr ""
+
+msgid "Assigned to :name"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assignee"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee lists show all issues assigned to the selected user."
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto DevOps, runners and job artifacts"
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
+msgstr ""
+
+msgid "Auto-cancel redundant, pending pipelines"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
+msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
+msgstr ""
+
+msgid "AutoDevOps|add a Kubernetes cluster"
+msgstr ""
+
+msgid "AutoDevOps|enable Auto DevOps"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available group Runners : %{runners}"
+msgstr ""
+
+msgid "Available group Runners : %{runners}."
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|A new badge was added."
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Delete badge"
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|No badge image"
+msgstr ""
+
+msgid "Badges|No image to preview"
+msgstr ""
+
+msgid "Badges|Please fill in a valid URL"
+msgstr ""
+
+msgid "Badges|Project Badge"
+msgstr ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|The badge was saved."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "Badges|e.g. %{exampleUrl}"
+msgstr ""
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are examples of regex for existing tools:"
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
+msgstr ""
+
+msgid "BillingPlans|Current plan"
+msgstr ""
+
+msgid "BillingPlans|Customer Support"
+msgstr ""
+
+msgid "BillingPlans|Downgrade"
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
+msgstr ""
+
+msgid "BillingPlans|Manage plan"
+msgstr ""
+
+msgid "BillingPlans|Please contact %{customer_support_link} in that case."
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Upgrade"
+msgstr ""
+
+msgid "BillingPlans|You are currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
+msgstr ""
+
+msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
+msgstr ""
+
+msgid "BillingPlans|features"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|paid annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch (%{branch_count})"
+msgid_plural "Branches (%{branch_count})"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch has changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "BranchSwitcherPlaceholder|Search branches"
+msgstr ""
+
+msgid "BranchSwitcherTitle|Switch branch"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cant find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch '%{branch_name}'?"
+msgstr ""
+
+msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+msgstr ""
+
+msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Branches|Only a project maintainer or owner can delete a protected branch"
+msgstr ""
+
+msgid "Branches|Overview"
+msgstr ""
+
+msgid "Branches|Protected branches can be managed in %{project_settings_link}."
+msgstr ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Sort by"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+msgstr ""
+
+msgid "Branches|The default branch cannot be deleted"
+msgstr ""
+
+msgid "Branches|This branch hasn’t been merged into %{default_branch}."
+msgstr ""
+
+msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
+msgid "Branches|To confirm, type %{branch_name_confirmation}:"
+msgstr ""
+
+msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
+msgstr ""
+
+msgid "Branches|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|project settings"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "Built-In"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CI / CD"
+msgstr ""
+
+msgid "CI / CD Settings"
+msgstr ""
+
+msgid "CI will run using the credentials assigned above."
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD for external repo"
+msgstr ""
+
+msgid "CI/CD settings"
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Deployment strategy needs a domain name to work correctly."
+msgstr ""
+
+msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|Learn more about Auto DevOps"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "Callback URL"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Certificate fingerprint"
+msgstr ""
+
+msgid "Change Weight"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates."
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "Changelog"
+msgstr ""
+
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
+msgstr ""
+
+msgid "Choose <strong>Next</strong> at the bottom of the page."
+msgstr ""
+
+msgid "Choose File ..."
+msgstr ""
+
+msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
+msgstr ""
+
+msgid "Choose file..."
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose which groups you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose which repositories you want to import."
+msgstr ""
+
+msgid "Choose which shards you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Error occured while saving variables"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "CiVariable|Validation failed"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
+msgstr ""
+
+msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
+msgstr ""
+
+msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
+msgstr ""
+
+msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
+msgstr ""
+
+msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Client authentication certificate"
+msgstr ""
+
+msgid "Client authentication key"
+msgstr ""
+
+msgid "Client authentication key password"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
+msgstr ""
+
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgstr ""
+
+msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|Applications"
+msgstr ""
+
+msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Token"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Helm Tiller"
+msgstr ""
+
+msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
+msgstr ""
+
+msgid "ClusterIntegration|Hide"
+msgstr ""
+
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|In order to show the health of the cluster, we'll need to provision your cluster with Prometheus to collect the required data."
+msgstr ""
+
+msgid "ClusterIntegration|Ingress"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress IP Address"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
+msgstr ""
+
+msgid "ClusterIntegration|Install"
+msgstr ""
+
+msgid "ClusterIntegration|Install Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Installed"
+msgstr ""
+
+msgid "ClusterIntegration|Installing"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
+msgstr ""
+
+msgid "ClusterIntegration|Integration status"
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster health"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
+msgstr ""
+
+msgid "ClusterIntegration|More information"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Note:"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Service token"
+msgstr ""
+
+msgid "ClusterIntegration|Show"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Token"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|check the pricing here"
+msgstr ""
+
+msgid "ClusterIntegration|documentation"
+msgstr ""
+
+msgid "ClusterIntegration|help page"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|properly configured"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "Code owners"
+msgstr ""
+
+msgid "Cohorts"
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & resolve discussion"
+msgstr ""
+
+msgid "Comment & unresolve discussion"
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit (%{commit_count})"
+msgid_plural "Commits (%{commit_count})"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit duration in minutes for last 30 commits"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|Commit: %{commitText}"
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Commit…"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|Compare"
+msgstr ""
+
+msgid "CompareBranches|Source"
+msgstr ""
+
+msgid "CompareBranches|Target"
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Tracing"
+msgstr ""
+
+msgid "Configure automatic git checks and housekeeping on repositories."
+msgstr ""
+
+msgid "Configure limits for web and API requests."
+msgstr ""
+
+msgid "Configure push mirrors."
+msgstr ""
+
+msgid "Configure storage path settings."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the way a user creates a new account."
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Created"
+msgstr ""
+
+msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
+msgstr ""
+
+msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
+msgstr ""
+
+msgid "ContainerRegistry|How to use the Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Learn more about"
+msgstr ""
+
+msgid "ContainerRegistry|No tags in Container Registry for this container image."
+msgstr ""
+
+msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgstr ""
+
+msgid "ContainerRegistry|Size"
+msgstr ""
+
+msgid "ContainerRegistry|Tag"
+msgstr ""
+
+msgid "ContainerRegistry|Tag ID"
+msgstr ""
+
+msgid "ContainerRegistry|Use different image names"
+msgstr ""
+
+msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
+msgstr ""
+
+msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution guide"
+msgstr ""
+
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "ContributorsPage|%{startDate} – %{endDate}"
+msgstr ""
+
+msgid "ContributorsPage|Building repository graph."
+msgstr ""
+
+msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Control the display of third party offers."
+msgstr ""
+
+msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of repository backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of verification operations for this Geo node"
+msgstr ""
+
+msgid "ConvDev Index"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key to clipboard"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy branch name to clipboard"
+msgstr ""
+
+msgid "Copy command to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Copy file path to clipboard"
+msgstr ""
+
+msgid "Copy incoming email address to clipboard"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
+msgid "Copy reference to clipboard"
+msgstr ""
+
+msgid "Copy secret to clipboard"
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token to clipboard"
+msgstr ""
+
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new branch and merge request"
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create branch"
+msgstr ""
+
+msgid "Create commit"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty repository"
+msgstr ""
+
+msgid "Create epic"
+msgstr ""
+
+msgid "Create file"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created on"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron syntax"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current node"
+msgstr ""
+
+msgid "CurrentUser|Profile"
+msgstr ""
+
+msgid "CurrentUser|Settings"
+msgstr ""
+
+msgid "Custom"
+msgstr ""
+
+msgid "Custom CI config path"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Production"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Default Branch"
+msgstr ""
+
+msgid "Default classification label"
+msgstr ""
+
+msgid "Default: Directly import the Google Code email address or username"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete Package"
+msgstr ""
+
+msgid "Delete Snippet"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete list"
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployKeys|Write access allowed"
+msgstr ""
+
+msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Add a deploy token"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository"
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Copy username to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Deploy Tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|This project has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "DeployTokens|Use this username as a login."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|You are about to revoke"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group Runners"
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "Discard review"
+msgstr ""
+
+msgid "Discover GitLab Geo."
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss Cycle Analytics introduction box"
+msgstr ""
+
+msgid "Dismiss Merge Request promotion"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Each Runner can be in one of the following states:"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Elasticsearch"
+msgstr ""
+
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable SAML authentication for this group"
+msgstr ""
+
+msgid "Enable Sentry for error reporting and logging."
+msgstr ""
+
+msgid "Enable and configure InfluxDB metrics."
+msgstr ""
+
+msgid "Enable and configure Prometheus metrics."
+msgstr ""
+
+msgid "Enable classification control using an external service"
+msgstr ""
+
+msgid "Enable for this project"
+msgstr ""
+
+msgid "Enable group Runners"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable reCAPTCHA or Akismet and set IP limits."
+msgstr ""
+
+msgid "Enable the Performance Bar for a given group."
+msgstr ""
+
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter the issue description"
+msgstr ""
+
+msgid "Enter the issue title"
+msgstr ""
+
+msgid "Enter the merge request description"
+msgstr ""
+
+msgid "Enter the merge request title"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No pod name has been specified"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod logs from"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Read more about environments"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epic will be removed! Are you sure?"
+msgstr ""
+
+msgid "Epics"
+msgstr ""
+
+msgid "Epics Roadmap"
+msgstr ""
+
+msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
+msgstr ""
+
+msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgstr ""
+
+msgid "Epics|How can I solve this?"
+msgstr ""
+
+msgid "Epics|More information"
+msgstr ""
+
+msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+msgstr ""
+
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr ""
+
+msgid "Epics|due"
+msgstr ""
+
+msgid "Epics|start"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Reporting and Logging"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error fetching contributors data."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching usage ping data."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error updating status for all todos."
+msgstr ""
+
+msgid "Error updating todo status."
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "Every day (at 4:00am)"
+msgstr ""
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr ""
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
+msgid "Explore"
+msgstr ""
+
+msgid "Explore GitLab"
+msgstr ""
+
+msgid "Explore Groups"
+msgstr ""
+
+msgid "Explore groups"
+msgstr ""
+
+msgid "Explore projects"
+msgstr ""
+
+msgid "Explore public groups"
+msgstr ""
+
+msgid "External Classification Policy Authorization"
+msgstr ""
+
+msgid "External authentication"
+msgstr ""
+
+msgid "External authorization denied access to this project"
+msgstr ""
+
+msgid "External authorization request timeout"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification Label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to remove issue from board, please try again."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to update issues, please try again."
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fields on this page are now uneditable, you can configure"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Files (%{human_size})"
+msgstr ""
+
+msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
+msgid "Filter by commit message"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Find the downloaded ZIP file and decompress it."
+msgstr ""
+
+msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish review"
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "FirstPushedBy|First"
+msgstr ""
+
+msgid "FirstPushedBy|pushed by"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Follow the steps below to export your Google Code project data."
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Format"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
+msgid "From %{provider_title}"
+msgstr ""
+
+msgid "From Bitbucket"
+msgstr ""
+
+msgid "From Bitbucket Server"
+msgstr ""
+
+msgid "From FogBugz"
+msgstr ""
+
+msgid "From GitLab.com"
+msgstr ""
+
+msgid "From Google Code"
+msgstr ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "From milestones:"
+msgstr ""
+
+msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Nodes"
+msgstr ""
+
+msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is failing or broken."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
+msgstr ""
+
+msgid "GeoNodes|Checksummed"
+msgstr ""
+
+msgid "GeoNodes|Data is out of date from %{timeago}"
+msgstr ""
+
+msgid "GeoNodes|Data replication lag"
+msgstr ""
+
+msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "GeoNodes|Failed"
+msgstr ""
+
+msgid "GeoNodes|Full"
+msgstr ""
+
+msgid "GeoNodes|GitLab version"
+msgstr ""
+
+msgid "GeoNodes|GitLab version does not match the primary node version"
+msgstr ""
+
+msgid "GeoNodes|Health status"
+msgstr ""
+
+msgid "GeoNodes|Last event ID processed by cursor"
+msgstr ""
+
+msgid "GeoNodes|Last event ID seen from primary"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository verification"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki verification"
+msgstr ""
+
+msgid "GeoNodes|Loading nodes"
+msgstr ""
+
+msgid "GeoNodes|Local LFS objects"
+msgstr ""
+
+msgid "GeoNodes|Local attachments"
+msgstr ""
+
+msgid "GeoNodes|Local job artifacts"
+msgstr ""
+
+msgid "GeoNodes|New node"
+msgstr ""
+
+msgid "GeoNodes|Node Authentication was successfully repaired."
+msgstr ""
+
+msgid "GeoNodes|Node was successfully removed."
+msgstr ""
+
+msgid "GeoNodes|Not checksummed"
+msgstr ""
+
+msgid "GeoNodes|Out of sync"
+msgstr ""
+
+msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Replication slot WAL"
+msgstr ""
+
+msgid "GeoNodes|Replication slots"
+msgstr ""
+
+msgid "GeoNodes|Repositories"
+msgstr ""
+
+msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Repositories verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Repository verification progress"
+msgstr ""
+
+msgid "GeoNodes|Selective"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while changing node status"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while fetching nodes"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while removing node"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while repairing node"
+msgstr ""
+
+msgid "GeoNodes|Storage config"
+msgstr ""
+
+msgid "GeoNodes|Sync settings"
+msgstr ""
+
+msgid "GeoNodes|Synced"
+msgstr ""
+
+msgid "GeoNodes|Unused slots"
+msgstr ""
+
+msgid "GeoNodes|Unverified"
+msgstr ""
+
+msgid "GeoNodes|Used slots"
+msgstr ""
+
+msgid "GeoNodes|Verified"
+msgstr ""
+
+msgid "GeoNodes|Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Wiki verification progress"
+msgstr ""
+
+msgid "GeoNodes|Wikis"
+msgstr ""
+
+msgid "GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for forced re-download"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-check"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|All"
+msgstr ""
+
+msgid "Geo|All projects"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|File sync capacity"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Groups to synchronize"
+msgstr ""
+
+msgid "Geo|In sync"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|Not synced yet"
+msgstr ""
+
+msgid "Geo|Pending"
+msgstr ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Recheck"
+msgstr ""
+
+msgid "Geo|Recheck all projects"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Repository sync capacity"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all projects"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Select groups to replicate."
+msgstr ""
+
+msgid "Geo|Shards to synchronize"
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
+msgid "Geo|Unknown state"
+msgstr ""
+
+msgid "Geo|Verification capacity"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|You need a different license to use Geo replication"
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Git"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git strategy for pipelines"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitLab CI Linter has been moved"
+msgstr ""
+
+msgid "GitLab Geo"
+msgstr ""
+
+msgid "GitLab Group Runners can execute code for all the projects in this group."
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab single sign on URL"
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLab’s issue tracker"
+msgstr ""
+
+msgid "Gitaly"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go to"
+msgstr ""
+
+msgid "Go to %{link_to_google_takeout}."
+msgstr ""
+
+msgid "Google Code import"
+msgstr ""
+
+msgid "Google Takeout"
+msgstr ""
+
+msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group CI/CD settings"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group Runners"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group details"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group maintainers can register group runners in the %{link}"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Loading roadmap"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|Until %{dateWord}"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Customize your group badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about badges."
+msgstr ""
+
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+msgstr ""
+
+msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
+msgstr ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Create a project in this group."
+msgstr ""
+
+msgid "GroupsTree|Create a subgroup in this group."
+msgstr ""
+
+msgid "GroupsTree|Edit group"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave this group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Have your users email"
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help page"
+msgstr ""
+
+msgid "Help page text and support page url."
+msgstr ""
+
+msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Hide whitespace changes"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Client side evaluation"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Open in file view"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "Identity provider single sign on URL"
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr ""
+
+msgid "If disabled, the access level will depend on the user's permissions in the project."
+msgstr ""
+
+msgid "If enabled"
+msgstr ""
+
+msgid "If enabled, access to projects will be validated on an external service using their classification label."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you already have files you can push them using the %{link_to_cli} below."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import all compatible projects"
+msgstr ""
+
+msgid "Import all projects"
+msgstr ""
+
+msgid "Import all repositories"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import projects from Google Code"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "Improve Issue boards with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
+msgid "In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "Incompatible Project"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input your repository URL"
+msgstr ""
+
+msgid "Install GitLab Runner"
+msgstr ""
+
+msgid "Install Runner on Kubernetes"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Instance Statistics"
+msgstr ""
+
+msgid "Instance Statistics visibility"
+msgstr ""
+
+msgid "Instance does not support multiple Kubernetes clusters"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations Settings"
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Cycle Analytics"
+msgstr ""
+
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue board focus mode"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Job"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed in"
+msgstr ""
+
+msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration was not removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes configured"
+msgstr ""
+
+msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label lists show all issues with the selected label."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{name}"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
+msgstr ""
+
+msgid "Learn more about Kubernetes"
+msgstr ""
+
+msgid "Learn more about protected branches"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
+msgid "LicenseManagement|Approve license"
+msgstr ""
+
+msgid "LicenseManagement|Approve license?"
+msgstr ""
+
+msgid "LicenseManagement|Approved"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license?"
+msgstr ""
+
+msgid "LicenseManagement|Blacklisted"
+msgstr ""
+
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
+msgid "LicenseManagement|License"
+msgstr ""
+
+msgid "LicenseManagement|License Management"
+msgstr ""
+
+msgid "LicenseManagement|License details"
+msgstr ""
+
+msgid "LicenseManagement|License name"
+msgstr ""
+
+msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
+msgstr ""
+
+msgid "LicenseManagement|Packages"
+msgstr ""
+
+msgid "LicenseManagement|Remove license"
+msgstr ""
+
+msgid "LicenseManagement|Remove license?"
+msgstr ""
+
+msgid "LicenseManagement|Submit"
+msgstr ""
+
+msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
+msgstr ""
+
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseManagement|URL"
+msgstr ""
+
+msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "LinkedIn"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "List Your Gitea Repositories"
+msgstr ""
+
+msgid "List available repositories"
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "List your GitHub repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked to current projects"
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make sure you're logged into the account that owns the projects you'd like to import."
+msgstr ""
+
+msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
+msgstr ""
+
+msgid "Manage Web IDE features"
+msgstr ""
+
+msgid "Manage access"
+msgstr ""
+
+msgid "Manage all notifications"
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a full email address"
+msgstr ""
+
+msgid "Map a Google Code user to a full name"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark todo as done"
+msgstr ""
+
+msgid "Markdown enabled"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
+msgid "Maven Metadata"
+msgstr ""
+
+msgid "Maven package"
+msgstr ""
+
+msgid "Max access level"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Median"
+msgstr ""
+
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Request:"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge requests"
+msgstr ""
+
+msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
+msgid "MergeRequests|Resolve this discussion in a new issue"
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|Toggle comments for this file"
+msgstr ""
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr ""
+
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Influx"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics|Business"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgstr ""
+
+msgid "Metrics|Environment"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgstr ""
+
+msgid "Metrics|Learn about environments"
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|Name"
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|No deployed environments"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|Query"
+msgstr ""
+
+msgid "Metrics|Response"
+msgstr ""
+
+msgid "Metrics|System"
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|Type"
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
+msgid "Milestone"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Mirror a repository"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror user"
+msgstr ""
+
+msgid "Mirrored repositories"
+msgstr ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
+msgid "Modal|Cancel"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More actions"
+msgstr ""
+
+msgid "More info"
+msgstr ""
+
+msgid "More information"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Multiple issue boards"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name your individual key via a title"
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Snippets"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No Label"
+msgstr ""
+
+msgid "No assignee"
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No container images stored for this project. Add one by following the instructions above."
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No issues for the selected time period."
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No merge requests for the selected time period."
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No packages stored for this project."
+msgstr ""
+
+msgid "No prioritised labels with such name or description"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No pushes for the selected time period."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No, directly import the existing email addresses and usernames."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "Not all comments are displayed because you're comparing two versions of the diff."
+msgstr ""
+
+msgid "Not all comments are displayed because you're viewing an old version of the diff."
+msgstr ""
+
+msgid "Not allowed to merge"
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not enough data"
+msgstr ""
+
+msgid "Not now"
+msgstr ""
+
+msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "Only admins"
+msgstr ""
+
+msgid "Only comments from the following commit are shown below"
+msgstr ""
+
+msgid "Only mirror protected branches"
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open in Xcode"
+msgstr ""
+
+msgid "Open projects"
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open source software to collaborate on code"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened MR"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Otherwise it is recommended you start with one of the options below."
+msgstr ""
+
+msgid "Outbound requests"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Package information"
+msgstr ""
+
+msgid "Package was removed"
+msgstr ""
+
+msgid "Packages"
+msgstr ""
+
+msgid "Pages"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
+
+msgid "Path, transfer, remove"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Paused Runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "Per job. If a job passes this threshold, it will be marked as failed"
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, or removing the group."
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline Health"
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline quota"
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines for last month"
+msgstr ""
+
+msgid "Pipelines for last week"
+msgstr ""
+
+msgid "Pipelines for last year"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|CI Lint"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgstr ""
+
+msgid "Pipelines|Get started with Pipelines"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|There are currently no %{scope} pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+msgstr ""
+
+msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Create for"
+msgstr ""
+
+msgid "Pipeline|Create pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Existing branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Search branches"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|all"
+msgstr ""
+
+msgid "Pipeline|success"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Please accept the Terms of Service before continuing."
+msgstr ""
+
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please solve the reCAPTCHA"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences|Navigation theme"
+msgstr ""
+
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Private - Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|Add status emoji"
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
+msgid "Profiles|Clear status"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Delete Account"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Delete your account?"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Website"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project avatar in repository: %{link}"
+msgstr ""
+
+msgid "Project details"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectLifecycle|Stage"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Customize your project badges."
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Learn more about badges."
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
+msgstr ""
+
+msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "PrometheusAlerts|Add alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Edit alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error creating alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error deleting alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error fetching alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error saving alert"
+msgstr ""
+
+msgid "PrometheusAlerts|No alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Operator"
+msgstr ""
+
+msgid "PrometheusAlerts|Threshold"
+msgstr ""
+
+msgid "PrometheusDashboard|Time"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration"
+msgstr ""
+
+msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
+msgstr ""
+
+msgid "PrometheusService|Common metrics"
+msgstr ""
+
+msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
+msgstr ""
+
+msgid "PrometheusService|Custom metrics"
+msgstr ""
+
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr ""
+
+msgid "PrometheusService|Finding custom metrics..."
+msgstr ""
+
+msgid "PrometheusService|Install Prometheus on clusters"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+msgstr ""
+
+msgid "PrometheusService|More information"
+msgstr ""
+
+msgid "PrometheusService|New metric"
+msgstr ""
+
+msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|Time-series monitoring service"
+msgstr ""
+
+msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
+msgstr ""
+
+msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
+msgstr ""
+
+msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote these project milestones into a group milestone."
+msgstr ""
+
+msgid "Promote to Group Milestone"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Environments"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "Protip:"
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Pseudonymizer data collection"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRule|Committer restriction"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
+
+msgid "Readme"
+msgstr ""
+
+msgid "Real-time features"
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Reference:"
+msgstr ""
+
+msgid "Refresh"
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Regenerate key"
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register and see your runners for this group."
+msgstr ""
+
+msgid "Register and see your runners for this project."
+msgstr ""
+
+msgid "Registry"
+msgstr ""
+
+msgid "Related Commits"
+msgstr ""
+
+msgid "Related Deployed Jobs"
+msgstr ""
+
+msgid "Related Issues"
+msgstr ""
+
+msgid "Related Jobs"
+msgstr ""
+
+msgid "Related Merge Requests"
+msgstr ""
+
+msgid "Related Merged Requests"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove Runner"
+msgstr ""
+
+msgid "Remove avatar"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
+msgid "Rename"
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Repair authentication"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{failedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|Class"
+msgstr ""
+
+msgid "Reports|Confidence"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository URL"
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirror"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Requests Profiles"
+msgstr ""
+
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
+msgid "Resolve all discussions in new issue"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve discussion"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal Variables"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
+msgid "Runner token"
+msgstr ""
+
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners API"
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, and even on your local machine."
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|You have used all your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML Single Sign On"
+msgstr ""
+
+msgid "SAML Single Sign On Settings"
+msgstr ""
+
+msgid "SAST"
+msgstr ""
+
+msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save variables"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scoped issue boards"
+msgstr ""
+
+msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or jump to…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in this group"
+msgstr ""
+
+msgid "SearchAutocomplete|in this project"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr ""
+
+msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgstr ""
+
+msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select a group to invite"
+msgstr ""
+
+msgid "Select a namespace to fork the project"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select an existing Kubernetes cluster or create a new one"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select branch/tag"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project and zone to choose machine type"
+msgstr ""
+
+msgid "Select project to choose zone"
+msgstr ""
+
+msgid "Select projects you want to import."
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Select the custom project template source group."
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Selective synchronization"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send usage data"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
+msgstr ""
+
+msgid "Session expiration, projects limit and attachment size."
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set instance-wide template repository"
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Sherlock Transactions"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show latest version of the diff"
+msgstr ""
+
+msgid "Show parent pages"
+msgstr ""
+
+msgid "Show parent subgroups"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|Change weight"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in to %{group_name}"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong when toggling the button"
+msgstr ""
+
+msgid "Something went wrong while closing the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while fetching %{listType} list"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the projects."
+msgstr ""
+
+msgid "Something went wrong while fetching the registry list."
+msgstr ""
+
+msgid "Something went wrong while reopening the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Sorry, no epics matched your search"
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "SortOptions|Access level, ascending"
+msgstr ""
+
+msgid "SortOptions|Access level, descending"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Milestone"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest joined"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source code"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Specific Runners"
+msgstr ""
+
+msgid "Specify an e-mail address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage & Commit"
+msgstr ""
+
+msgid "Stage all changes"
+msgstr ""
+
+msgid "Stage changes"
+msgstr ""
+
+msgid "Staged"
+msgstr ""
+
+msgid "Staged %{type}"
+msgstr ""
+
+msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start the Runner!"
+msgstr ""
+
+msgid "Start your trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Stop environment"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Sync information"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System header and footer:"
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "Tag (%{tag_count})"
+msgid_plural "Tags (%{tag_count})"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release notes"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag."
+msgstr ""
+
+msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Sort by"
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Test SAML SSO"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+msgid "Thanks! Don't show me this again"
+msgstr ""
+
+msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
+msgstr ""
+
+msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr ""
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The deployment of this job to %{environmentLink} did not succeed."
+msgstr ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr ""
+
+msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
+msgstr ""
+
+msgid "The phase of the development lifecycle."
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr ""
+
+msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
+msgstr ""
+
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr ""
+
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
+msgstr ""
+
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The tabs below will be removed in a future version"
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no merge requests to show"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
+
+msgid "There was an error adding a todo."
+msgstr ""
+
+msgid "There was an error deleting the todo."
+msgstr ""
+
+msgid "There was an error loading users activity calendar."
+msgstr ""
+
+msgid "There was an error saving your notification settings."
+msgstr ""
+
+msgid "There was an error subscribing to this label."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "They can be managed using the %{link}."
+msgstr ""
+
+msgid "Third party offers"
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
+msgstr ""
+
+msgid "This application was created by %{link_to_owner}."
+msgstr ""
+
+msgid "This application will be able to:"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This branch has changed since you started editing. Would you like to create a new branch?"
+msgstr ""
+
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This group"
+msgstr ""
+
+msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgstr ""
+
+msgid "This group does not provide any group Runners yet."
+msgstr ""
+
+msgid "This is a confidential issue."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is the author's first Merge Request to this project."
+msgstr ""
+
+msgid "This issue is confidential"
+msgstr ""
+
+msgid "This issue is confidential and locked."
+msgstr ""
+
+msgid "This issue is locked."
+msgstr ""
+
+msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "This job is the most recent deployment to %{link}."
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This option is disabled as you don't have write permissions for the current branch"
+msgstr ""
+
+msgid "This option is disabled while you still have unstaged changes"
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page will be removed in a future release."
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project does not belong to a group and can therefore not make use of group Runners."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "This source diff could not be displayed because it is too large."
+msgstr ""
+
+msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
+msgstr ""
+
+msgid "This will delete the custom metric, Are you sure?"
+msgstr ""
+
+msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time before enforced"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds ago"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip:"
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr ""
+
+msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
+msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr ""
+
+msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
+msgstr ""
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr ""
+
+msgid "To start serving your jobs you can add Runners to your group"
+msgstr ""
+
+msgid "To this GitLab instance"
+msgstr ""
+
+msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
+msgstr ""
+
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
+
+msgid "To widen your search, change or remove filters."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Todo"
+msgstr ""
+
+msgid "Todos"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle discussion"
+msgstr ""
+
+msgid "Toggle file browser"
+msgstr ""
+
+msgid "Toggle navigation"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: OFF"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: ON"
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Time"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track activity with Contribution Analytics."
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trigger"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Turn on Service Desk"
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to save your changes"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unresolve discussion"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
+msgid "Unstage all changes"
+msgstr ""
+
+msgid "Unstage changes"
+msgstr ""
+
+msgid "Unstaged"
+msgstr ""
+
+msgid "Unstaged %{type}"
+msgstr ""
+
+msgid "Unstaged and staged %{type}"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Upgrade your plan to activate Advanced Global Search."
+msgstr ""
+
+msgid "Upgrade your plan to activate Contribution Analytics."
+msgstr ""
+
+msgid "Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Upgrade your plan to activate Issue weight."
+msgstr ""
+
+msgid "Upgrade your plan to improve Issue boards."
+msgstr ""
+
+msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage ping is not enabled"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "Use <code>%{native_redirect_uri}</code> for local tests"
+msgstr ""
+
+msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
+msgstr ""
+
+msgid "Use group milestones to manage issues from multiple projects in the same milestone."
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use the following registration token during setup:"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "Used by members to sign in to your group in GitLab"
+msgstr ""
+
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Variables"
+msgstr ""
+
+msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification information"
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View epics list"
+msgstr ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View group labels"
+msgstr ""
+
+msgid "View issue"
+msgstr ""
+
+msgid "View it on GitLab"
+msgstr ""
+
+msgid "View jobs"
+msgstr ""
+
+msgid "View labels"
+msgstr ""
+
+msgid "View log"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr ""
+
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|It is recommended to install %{markdown} so that GFM features render locally:"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgstr ""
+
+msgid "WikiMarkdownDocs|documentation"
+msgstr ""
+
+msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgstr ""
+
+msgid "WikiNewPagePlaceholder|how-to-setup"
+msgstr ""
+
+msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiNewPageTitle|New Wiki Page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgstr ""
+
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPageConflictMessage|the page"
+msgstr ""
+
+msgid "WikiPageCreate|Create %{page_title}"
+msgstr ""
+
+msgid "WikiPageEdit|Update %{page_title}"
+msgstr ""
+
+msgid "WikiPage|Page slug"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wiki|Create Page"
+msgstr ""
+
+msgid "Wiki|Create page"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|More Pages"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, let me map Google Code users to full names or GitLab users."
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
+msgstr ""
+
+msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You can %{linkStart}view the blob%{linkEnd} instead."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
+msgid "You can only edit files when you are on a branch"
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
+msgstr ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+msgstr ""
+
+msgid "You cannot write to this read-only GitLab instance."
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You must accept our Terms of Service and privacy policy in order to register an account"
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're receiving this email because %{reason}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your Todos"
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your comment will not be visible to the public."
+msgstr ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your projects"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "among other things"
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{namespace} is affected by %{vulnerability}."
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr ""
+
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr ""
+
+msgid "ciReport|(is loading)"
+msgstr ""
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr ""
+
+msgid "ciReport|Class"
+msgstr ""
+
+msgid "ciReport|Code quality"
+msgstr ""
+
+msgid "ciReport|Confidence"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Description"
+msgstr ""
+
+msgid "ciReport|Dismiss vulnerability"
+msgstr ""
+
+msgid "ciReport|Dismissed by"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|File"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Identifiers"
+msgstr ""
+
+msgid "ciReport|Instances"
+msgstr ""
+
+msgid "ciReport|Learn more about interacting with security reports (Alpha)."
+msgstr ""
+
+msgid "ciReport|License management detected %d license for the source branch only"
+msgid_plural "ciReport|License management detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected %d new license"
+msgid_plural "ciReport|License management detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|License management detected no licenses for the source branch only"
+msgstr ""
+
+msgid "ciReport|License management detected no new licenses"
+msgstr ""
+
+msgid "ciReport|Links"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|Method"
+msgstr ""
+
+msgid "ciReport|Namespace"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No changes to performance metrics"
+msgstr ""
+
+msgid "ciReport|Performance metrics"
+msgstr ""
+
+msgid "ciReport|Revert dismissal"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Severity"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error loading DAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading SAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading container scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error loading dependency scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "ciReport|on pipeline"
+msgstr ""
+
+msgid "command line instructions"
+msgstr ""
+
+msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgstr ""
+
+msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
+msgstr ""
+
+msgid "connecting"
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "customize"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "deploy token"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "here"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "importing"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "issue boards"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "license management"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|Add approval"
+msgstr ""
+
+msgid "mrWidget|Allows commits from members who can merge to the target branch"
+msgstr ""
+
+msgid "mrWidget|An error occured while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Cancel automatic merge"
+msgstr ""
+
+msgid "mrWidget|Check out branch"
+msgstr ""
+
+msgid "mrWidget|Checking ability to merge automatically"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes"
+msgstr ""
+
+msgid "mrWidget|Create an issue to resolve them later"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mentions"
+msgstr ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge request approved"
+msgstr ""
+
+msgid "mrWidget|Merge request approved; you can approve additionally"
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|No Approval required"
+msgstr ""
+
+msgid "mrWidget|No Approval required; you can still approve"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove Source Branch"
+msgstr ""
+
+msgid "mrWidget|Remove source branch"
+msgstr ""
+
+msgid "mrWidget|Remove your approval"
+msgstr ""
+
+msgid "mrWidget|Request to merge"
+msgstr ""
+
+msgid "mrWidget|Requires 1 more approval"
+msgid_plural "mrWidget|Requires %d more approvals"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Requires 1 more approval by"
+msgid_plural "mrWidget|Requires %d more approvals by"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Set by"
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The changes will be merged into"
+msgstr ""
+
+msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+msgstr ""
+
+msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
+msgstr ""
+
+msgid "mrWidget|The source branch has been removed"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will be removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will not be removed"
+msgstr ""
+
+msgid "mrWidget|There are merge conflicts"
+msgstr ""
+
+msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|This merge request is in the process of being merged"
+msgstr ""
+
+msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr ""
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|You can remove source branch now"
+msgstr ""
+
+msgid "mrWidget|branch does not exist."
+msgstr ""
+
+msgid "mrWidget|command line"
+msgstr ""
+
+msgid "mrWidget|into"
+msgstr ""
+
+msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "notification emails"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "password"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "source"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time spent."
+msgstr ""
+
+msgid "started"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "toggle collapse"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "within %d minute "
+msgid_plural "within %d minutes "
+msgstr[0] ""
+msgstr[1] ""
+
diff --git a/locale/ro_RO/gitlab.po b/locale/ro_RO/gitlab.po
index f333a5aeba1..29f15fc9067 100644
--- a/locale/ro_RO/gitlab.po
+++ b/locale/ro_RO/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Romanian\n"
"Language: ro_RO\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ro\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:31\n"
+"PO-Revision-Date: 2018-11-19 17:18\n"
msgid " Status"
msgstr ""
@@ -33,6 +33,15 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -51,6 +60,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -105,12 +120,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] ""
@@ -120,18 +129,33 @@ msgstr[2] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -141,6 +165,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -156,24 +183,12 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr ""
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr ""
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -186,31 +201,13 @@ msgstr ""
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -348,6 +345,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr ""
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -390,13 +396,10 @@ msgstr ""
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
-msgstr ""
-
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgid "Access expiration date"
msgstr ""
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -426,27 +429,48 @@ msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
+msgid "Add Kubernetes cluster"
msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -456,6 +480,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -489,9 +516,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -528,12 +552,18 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr ""
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "All"
msgstr ""
@@ -549,6 +579,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -558,6 +591,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -573,6 +612,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -594,7 +636,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -618,6 +660,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -630,6 +678,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -642,6 +693,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -669,6 +723,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -711,12 +768,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr ""
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -735,7 +798,7 @@ msgstr ""
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -753,9 +816,15 @@ msgstr ""
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -774,6 +843,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -912,6 +984,9 @@ msgstr ""
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -948,9 +1023,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -1029,6 +1101,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1320,6 +1401,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1350,9 +1434,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1407,7 +1488,7 @@ msgstr ""
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1434,6 +1515,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1464,6 +1551,9 @@ msgstr ""
msgid "CiStatusLabel|created"
msgstr ""
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr ""
@@ -1482,6 +1572,9 @@ msgstr ""
msgid "CiStatusLabel|skipped"
msgstr ""
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr ""
@@ -1494,6 +1587,9 @@ msgstr ""
msgid "CiStatusText|created"
msgstr ""
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr ""
@@ -1548,10 +1644,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1596,6 +1692,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1608,12 +1707,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1644,10 +1755,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1674,6 +1785,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1710,6 +1827,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1740,9 +1860,6 @@ msgstr ""
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1764,25 +1881,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster details"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster health"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1794,7 +1905,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1803,16 +1914,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1830,9 +1938,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1860,6 +1965,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1872,6 +1980,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1902,9 +2013,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1944,13 +2052,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -1968,6 +2073,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -1986,9 +2094,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -1998,6 +2103,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -2007,12 +2115,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2049,6 +2163,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr ""
@@ -2121,7 +2238,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2130,10 +2247,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2223,6 +2340,9 @@ msgstr ""
msgid "Contribution guide"
msgstr ""
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2256,6 +2376,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2277,15 +2409,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2361,7 +2505,7 @@ msgstr ""
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
+msgid "Create your first page"
msgstr ""
msgid "CreateTag|Tag"
@@ -2412,6 +2556,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -2430,6 +2577,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr ""
@@ -2481,6 +2631,9 @@ msgstr ""
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2493,6 +2646,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr ""
@@ -2502,6 +2670,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2640,6 +2811,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2664,6 +2841,12 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2685,12 +2868,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2706,6 +2904,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2787,7 +2988,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2832,9 +3033,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2847,6 +3045,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2949,7 +3153,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -2982,10 +3186,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3096,6 +3300,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3150,6 +3360,12 @@ msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3159,6 +3375,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3168,6 +3387,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3177,6 +3471,9 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr ""
@@ -3189,9 +3486,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr ""
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr ""
@@ -3207,6 +3513,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3219,7 +3528,7 @@ msgstr ""
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3258,18 +3567,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -3285,6 +3594,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3327,6 +3639,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3501,10 +3816,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3513,6 +3840,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3534,7 +3864,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3546,6 +3876,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3555,19 +3888,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3585,6 +3924,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3597,9 +3942,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3609,9 +3972,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3678,12 +4038,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr ""
-
-msgid "GoToYourFork|Fork"
-msgstr ""
-
msgid "Google Code import"
msgstr ""
@@ -3714,9 +4068,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3726,6 +4092,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3744,13 +4113,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3777,9 +4146,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3837,6 +4203,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3849,19 +4218,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -3903,6 +4272,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4068,6 +4440,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4137,6 +4512,12 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4161,6 +4542,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4176,9 +4587,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4215,7 +4623,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4233,12 +4641,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4311,6 +4713,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
@@ -4323,12 +4728,18 @@ msgstr ""
msgid "Last commit"
msgstr ""
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4377,6 +4788,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4386,6 +4806,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4395,6 +4818,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4404,6 +4830,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4416,9 +4845,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4446,6 +4881,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4491,6 +4929,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4560,13 +5001,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4578,6 +5049,12 @@ msgstr ""
msgid "Median"
msgstr ""
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -4611,6 +5088,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4620,9 +5112,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4632,6 +5121,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4647,6 +5142,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4863,6 +5361,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -4983,6 +5484,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -4992,9 +5499,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -5004,6 +5508,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5031,6 +5538,9 @@ msgstr ""
msgid "No repository"
msgstr ""
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr ""
@@ -5067,6 +5577,9 @@ msgstr ""
msgid "Not enough data"
msgstr ""
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -5085,6 +5598,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -5157,9 +5682,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5187,9 +5709,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5211,6 +5730,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5235,6 +5757,21 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5301,6 +5838,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5328,13 +5868,13 @@ msgstr ""
msgid "Permissions"
msgstr ""
-msgid "Personal Access Token"
+msgid "Permissions, LFS, 2FA"
msgstr ""
-msgid "Pipeline"
+msgid "Personal Access Token"
msgstr ""
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
+msgid "Pipeline"
msgstr ""
msgid "Pipeline Health"
@@ -5454,15 +5994,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5472,6 +6021,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5499,12 +6054,6 @@ msgstr ""
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5514,12 +6063,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5532,6 +6087,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5544,9 +6102,18 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5592,15 +6159,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5613,39 +6195,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -5655,6 +6318,15 @@ msgstr ""
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5691,6 +6363,9 @@ msgstr ""
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr ""
@@ -5718,6 +6393,9 @@ msgstr ""
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -5745,6 +6423,27 @@ msgstr ""
msgid "ProjectLifecycle|Stage"
msgstr ""
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5787,6 +6486,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5856,9 +6558,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6051,6 +6750,12 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6114,12 +6819,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6129,6 +6843,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6138,18 +6855,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6162,6 +6894,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6195,10 +6930,10 @@ msgstr ""
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6216,9 +6951,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6270,9 +7017,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6282,6 +7044,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6306,6 +7074,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6330,6 +7101,9 @@ msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -6384,15 +7158,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6417,28 +7200,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard"
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6456,9 +7266,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr ""
@@ -6489,6 +7305,9 @@ msgstr ""
msgid "Select target branch"
msgstr ""
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6501,6 +7320,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6525,6 +7347,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6543,7 +7368,10 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
@@ -6555,13 +7383,31 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "Settings"
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
msgstr ""
msgid "Share"
@@ -6573,6 +7419,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6657,12 +7506,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6690,9 +7545,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6705,12 +7566,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -6741,6 +7614,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6771,6 +7647,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6801,6 +7680,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6876,9 +7758,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6891,6 +7785,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6900,6 +7797,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6909,9 +7809,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6924,6 +7830,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -6942,6 +7854,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -7047,6 +7962,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7095,12 +8013,6 @@ msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7149,9 +8061,6 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr ""
@@ -7161,21 +8070,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr ""
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7185,6 +8088,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7194,7 +8100,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7242,10 +8154,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7266,6 +8181,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7305,7 +8223,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7326,6 +8247,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
@@ -7350,6 +8274,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7359,6 +8286,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7386,9 +8319,15 @@ msgstr ""
msgid "Time before an issue starts implementation"
msgstr ""
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr ""
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7581,12 +8520,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7602,6 +8553,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7614,12 +8568,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7629,9 +8586,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7647,6 +8610,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7662,6 +8628,9 @@ msgstr ""
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7671,6 +8640,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7689,24 +8661,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7722,6 +8712,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7755,13 +8751,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7791,15 +8790,15 @@ msgstr ""
msgid "Upload file"
msgstr ""
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr ""
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7827,6 +8826,9 @@ msgstr ""
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7836,10 +8838,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7866,6 +8910,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7899,9 +8952,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7920,6 +8979,36 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -7959,6 +9048,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8109,6 +9204,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8127,9 +9225,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8139,9 +9234,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8163,12 +9255,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8190,9 +9288,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr ""
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8202,6 +9297,12 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr ""
@@ -8268,6 +9369,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8289,18 +9393,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
msgid "assign yourself"
msgstr ""
@@ -8328,61 +9420,82 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8415,9 +9528,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8442,6 +9552,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8460,13 +9573,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8475,9 +9582,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8508,9 +9612,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8523,9 +9624,6 @@ msgstr[2] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8556,27 +9654,18 @@ msgstr[2] ""
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
-
msgid "disabled"
msgstr ""
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "enabled"
msgstr ""
@@ -8586,6 +9675,12 @@ msgstr ""
msgid "for this project"
msgstr ""
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -8616,6 +9711,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8847,6 +9945,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8865,6 +9966,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr ""
@@ -8895,6 +9999,12 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "remaining"
msgstr ""
@@ -8907,6 +10017,12 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "source"
msgstr ""
@@ -8922,6 +10038,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po
index 4b66d59bebd..379e0ce8324 100644
--- a/locale/ru/gitlab.po
+++ b/locale/ru/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Russian\n"
"Language: ru_RU\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: ru\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:31\n"
+"PO-Revision-Date: 2018-11-19 17:18\n"
msgid " Status"
msgstr ""
@@ -35,6 +35,16 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -56,6 +66,13 @@ msgstr[1] "на %d коммита позади"
msgstr[2] "на %d коммитов позади"
msgstr[3] "на %d коммитов позади"
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d ÑкÑпортер"
@@ -114,18 +131,11 @@ msgstr[3] "%d запиÑанных изменений"
msgid "%d unstaged change"
msgid_plural "%d unstaged changes"
-msgstr[0] "%d не запиÑанное изменение"
+msgstr[0] "%d незапиÑанных изменений"
msgstr[1] "%d не запиÑанных изменений"
msgstr[2] "%d не запиÑанных изменений"
msgstr[3] "%d не запиÑанных изменений"
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] "%s дополнительный коммит был пропущен Ð´Ð»Ñ Ð¿Ñ€ÐµÐ´Ð¾Ñ‚Ð²Ñ€Ð°Ñ‰ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼ Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñтью."
@@ -136,12 +146,21 @@ msgstr[3] "%s дополнительных коммитов было пропуÑ
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} Ñоздан %{commit_timeago}"
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] "%{count} учаÑтник"
@@ -149,6 +168,13 @@ msgstr[1] "%{count} учаÑтника"
msgstr[2] "%{count} учаÑтников"
msgstr[3] "%{count} учаÑтников"
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -158,6 +184,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Запущено"
@@ -173,25 +202,12 @@ msgstr "%{nip_domain} может иÑпользоватьÑÑ ÐºÐ°Ðº альтеÑ
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "на %{number_commits_behind} коммитов позади %{default_branch}, на %{number_commits_ahead} коммитов впереди"
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr "%{number_of_failures} из %{maximum_failures} возможных неудачных попыток. GitLab будет доÑтупен поÑле Ñледующей попытки."
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr "%{number_of_failures} из %{maximum_failures} возможных неудачных попыток. GitLab не будет автоматичеÑки повторÑÑ‚ÑŒ попытку. СброÑьте информацию хранилища поÑле уÑÑ‚Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ñ‹."
-
msgid "%{openOrClose} %{noteable}"
msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
msgstr "%{percent}%% выполнено"
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] "%{storage_name}: Ð½ÐµÑƒÐ´Ð°Ñ‡Ð½Ð°Ñ Ð¿Ð¾Ð¿Ñ‹Ñ‚ÐºÐ° доÑтупа к хранилищу на хоÑте:"
-msgstr[1] "%{storage_name}: %{failed_attempts} неудачные попытки доÑтупа к хранилищу:"
-msgstr[2] "%{storage_name}: %{failed_attempts} неудачных попыток доÑтупа к хранилищу:"
-msgstr[3] "%{storage_name}: %{failed_attempts} неудачных попыток доÑтупа к хранилищу:"
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -205,37 +221,15 @@ msgstr "%{text} доÑтупен"
msgid "%{title} changes"
msgstr "Ð˜Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð² %{title}"
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{unstaged} unstaged and %{staged} staged changes"
msgstr "%{unstaged} не зафикÑированных и %{staged} зафикÑированных изменений"
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
msgid "+ %{moreCount} more"
msgstr "+ ещё %{moreCount}"
@@ -377,11 +371,20 @@ msgid "<strong>Removes</strong> source branch"
msgstr "<strong>УдалÑет</strong> иÑходную ветку"
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr "«Runner» - Ñто процеÑÑ, который выполнÑет задание (обработчиков заданий). Ð’Ñ‹ можете наÑтроить Ñтолько таких процеÑÑов, Ñколько вам нужно."
+msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr "Графики непрерывной интеграции (CI)"
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -424,13 +427,10 @@ msgstr "Токены ДоÑтупа"
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
+msgid "Access expiration date"
msgstr ""
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr "ДоÑтуп к вышедшим из ÑÑ‚Ñ€Ð¾Ñ Ñ…Ñ€Ð°Ð½Ð¸Ð»Ð¸Ñ‰Ð°Ð¼ временно отключен Ð´Ð»Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾Ñти Ð¼Ð¾Ð½Ñ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² целÑÑ… воÑÑтановлениÑ. СброÑьте информацию о хранилищах поÑле уÑÑ‚Ñ€Ð°Ð½ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ñ‹, чтобы разрешить доÑтуп."
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -460,27 +460,48 @@ msgstr "Добавить РуководÑтво учаÑтника"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
+msgid "Add Jaeger URL"
+msgstr ""
+
msgid "Add Kubernetes cluster"
msgstr "Добавить Kubernetes клаÑтер"
-msgid "Add License"
-msgstr "Добавить Лицензию"
-
msgid "Add Readme"
msgstr "Добавить Информацию"
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr "Добавить новый каталог"
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr "Добавить реакцию"
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr "Добавить в дела"
@@ -490,6 +511,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -523,9 +547,6 @@ msgstr "ОÑтановка заданий не удалаÑÑŒ"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ оÑтановить вÑе заданиÑ. Это дейÑтвие оÑтановит вÑе текущие заданиÑ, находÑщиеÑÑ Ð² процеÑÑе выполнениÑ."
-msgid "AdminHealthPageLink|health page"
-msgstr "Ñтраница работоÑпоÑобноÑти"
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -562,12 +583,19 @@ msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ, введите %{projectName}"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "Ð”Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ, введите %{username}"
-msgid "Advanced"
-msgstr "РаÑширенный режим"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
msgid "Advanced settings"
msgstr "РаÑширенные наÑтройки"
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "All"
msgstr "Ð’Ñе"
@@ -583,6 +611,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -592,6 +623,12 @@ msgstr "Разрешить рендеринг диаграмм PlantUML в доÐ
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "ПозволÑет добавлÑÑ‚ÑŒ и управлÑÑ‚ÑŒ клаÑтерами Kubernetes."
@@ -607,6 +644,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -628,7 +668,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -652,6 +692,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "Произошла ошибка при предварительном проÑмотре объекта"
@@ -664,6 +710,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -676,6 +725,9 @@ msgstr "Произошла ошибка при отключении уведом
msgid "An error occurred while fetching markdown preview"
msgstr "Произошла ошибка при предварительном проÑмотре markdown"
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Произошла ошибка при получении денег данных Ð´Ð»Ñ Ð±Ð¾ÐºÐ¾Ð²Ð¾Ð¹ панели"
@@ -703,6 +755,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -745,12 +800,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr "Произошла ошибка при проверке имени пользователÑ"
msgid "An error occurred. Please try again."
msgstr "Произошла ошибка. ПожалуйÑта, попробуйте Ñнова."
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -769,7 +830,7 @@ msgstr "Оформление"
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -787,9 +848,15 @@ msgstr "Ðпрель"
msgid "Archived project! Repository and other project resources are read-only"
msgstr "Ðрхивный проект! Репозиторий и другие реÑурÑÑ‹ проекта доÑтупны только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ"
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Ð’Ñ‹ дейÑтвительно хотите удалить Ñто раÑпиÑание Ñборочной линии?"
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -808,6 +875,9 @@ msgstr "Ð’Ñ‹ уверены, что хотите ÑброÑить Ñтот реÐ
msgid "Are you sure you want to reset the health check token?"
msgstr "Ð’Ñ‹ уверены, что хотите ÑброÑить Ñтот токен проверки работоÑпоÑобноÑти?"
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -946,6 +1016,9 @@ msgstr "Ð”Ð»Ñ Ñтого проекта может быть активировÐ
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "Подробнее по ÑÑылке %{link_to_documentation}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr "Ð’Ñ‹ можете автоматичеÑки Ñобирать и теÑтировать Ñвое приложение, еÑли Ð´Ð»Ñ Ñтого проекта %{link_to_auto_devops_settings}. Ð’Ñ‹ также можете автоматичеÑки развернуть Ñвое приложение, еÑли вы %{link_to_add_kubernetes_cluster}."
@@ -982,9 +1055,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr "Фоновые заданиÑ"
-
msgid "Badges"
msgstr "Значки"
@@ -1063,6 +1133,15 @@ msgstr "Ваши значки"
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr "Ðачать Ñ Ð²Ñ‹Ð±Ñ€Ð°Ð½Ð½Ð¾Ð³Ð¾ коммита"
@@ -1355,6 +1434,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1385,9 +1467,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1442,8 +1521,8 @@ msgstr "Диаграммы"
msgid "Chat"
msgstr "Чат"
-msgid "Check interval"
-msgstr "Интервал проверки"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
msgid "Checking %{text} availability…"
msgstr "Проверка доÑтупноÑти %{text} ..."
@@ -1469,6 +1548,12 @@ msgstr "Выберите Файл..."
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr "Выберите ветку/тег (например, %{master}) или введите коммит (например, %{sha}), чтобы увидеть, что изменилоÑÑŒ или Ñоздать Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние."
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr "Выберите любой цвет."
@@ -1499,6 +1584,9 @@ msgstr "отменено"
msgid "CiStatusLabel|created"
msgstr "Ñоздано"
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr "неудачно"
@@ -1517,6 +1605,9 @@ msgstr "в ожидании"
msgid "CiStatusLabel|skipped"
msgstr "пропущено"
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr "ожидание ручных дейÑтвий"
@@ -1529,6 +1620,9 @@ msgstr "отменено"
msgid "CiStatusText|created"
msgstr "Ñоздано"
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr "неудачно"
@@ -1583,12 +1677,12 @@ msgstr "Включить защиту"
msgid "CiVariable|Validation failed"
msgstr "Проверка не удалаÑÑŒ"
-msgid "CircuitBreakerApiLink|circuitbreaker api"
-msgstr "CircuitBreaker API"
-
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
+msgid "Clear search"
+msgstr ""
+
msgid "Clear search input"
msgstr "ОчиÑтить Ñтроку поиÑка"
@@ -1631,6 +1725,9 @@ msgstr "Клонировать репозиторий"
msgid "Close"
msgstr "Закрыть"
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1643,12 +1740,24 @@ msgstr "%{appList} уÑпешно уÑтановлены на вашем клаÑ
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr "ÐÐ´Ñ€ÐµÑ API"
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr "Добавить клаÑтер Kubernetes"
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Дополнительные опции Ð´Ð»Ñ Ñтой интеграции Ñ ÐºÐ»Ð°Ñтером Kubernetes"
@@ -1679,11 +1788,11 @@ msgstr "Сертификат удоÑтоверÑющего центра"
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "Комплект Ñертификатов удоÑтоверÑющего центра (формат PEM)"
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
-msgstr "Выберите, какие Ñреды вашего проекта будут иÑпользовать Ñтот клаÑтер Kubernetes."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
-msgstr "УправлÑйте тем, как ваш клаÑтер Kubernetes интегрируетÑÑ Ñ GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
msgid "ClusterIntegration|Copy API URL"
msgstr "Скопировать Ð°Ð´Ñ€ÐµÑ API"
@@ -1709,6 +1818,12 @@ msgstr "Создать клаÑтер Kubernetes"
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr "Введите ÑÐ²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¾ вашем клаÑтере Kubernetes"
@@ -1745,6 +1860,9 @@ msgstr "Google Kubernetes Engine"
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr "Проект Google Kubernetes Engine"
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
@@ -1775,9 +1893,6 @@ msgstr "УÑтановить"
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr "УÑтановлен"
@@ -1799,6 +1914,12 @@ msgstr "Хаб ÑервиÑа Jupyter"
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr "КлаÑтер Kubernetes"
@@ -1808,18 +1929,6 @@ msgstr "Ð¡Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¾ клаÑтере Kubernetes"
msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration"
-msgstr "Ð˜Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ñ ÐºÐ»Ð°Ñтера Kubernetes"
-
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
-msgstr "Ð˜Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ñ ÐºÐ»Ð°Ñтера Kubernetes Ð´Ð»Ñ Ñтого проекта отключена."
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
-msgstr "Ð˜Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ñ ÐºÐ»Ð°Ñтера Kubernetes Ð´Ð»Ñ Ñтого проекта включена."
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
-msgstr "Ð”Ð»Ñ Ñтого проекта включена Ð¸Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ñ ÐºÐ»Ð°Ñтера Kubernetes. Отключение интеграции не повлиÑет на клаÑтер Kubernetes, но Ñоединение Ñ GitLab будет временно отключено."
-
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
msgstr "КлаÑтер Kubernetes ÑоздаётÑÑ Ð² Google Kubernetes Engine..."
@@ -1829,8 +1938,8 @@ msgstr "Ð˜Ð¼Ñ ÐºÐ»Ð°Ñтера Kubernetes"
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr "КлаÑтер Kubernetes был уÑпешно Ñоздан в Google Kubernetes Engine. Обновите Ñтраницу, чтобы увидеть ÑÐ²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¾ клаÑтере Kubernetes"
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
-msgstr "КлаÑтер Kubernetes позволÑет вам иÑпользовать Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñ€ÐµÐ²ÑŒÑŽ, развёртывать ваши приложениÑ, запуÑкать ваши Ñборочные линии и многое другое более проÑтым ÑпоÑобом. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
msgstr "КлаÑтеры Kubernetes могут иÑпользоватьÑÑ Ð´Ð»Ñ Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ð¹ и предоÑÑ‚Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ð¹ Review Ð´Ð»Ñ Ñтого проекта"
@@ -1838,17 +1947,14 @@ msgstr "КлаÑтеры Kubernetes могут иÑпользоватьÑÑ Ð´Ð»
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
-msgstr "Узнайте больше о Ñредах"
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
-msgstr "Узнайте больше о наÑтройке безопаÑноÑти"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
msgid "ClusterIntegration|Machine type"
msgstr "Тип машины"
@@ -1865,9 +1971,6 @@ msgstr "УправлÑйте вашему клаÑтером Kubernetes, перÐ
msgid "ClusterIntegration|More information"
msgstr "Ð”Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ"
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr "Ðет типов машин, ÑоответÑтвующих вашему поиÑковому запроÑу"
@@ -1895,6 +1998,9 @@ msgstr "ПожалуйÑта, убедитеÑÑŒ, что ваш аккаунт G
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr "ПроÑтранÑтво имён проекта"
@@ -1907,6 +2013,9 @@ msgstr "Prometheus"
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr "Прочтите нашу документацию %{link_to_help_page} по интеграции клаÑтера Kubernetes."
@@ -1937,9 +2046,6 @@ msgstr "ПоиÑк проектов"
msgid "ClusterIntegration|Search zones"
msgstr "ПоиÑк зон"
-msgid "ClusterIntegration|Security"
-msgstr "БезопаÑноÑÑ‚ÑŒ"
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "ПроÑмотр и редактирование информации о вашем клаÑтере Kubernetes"
@@ -1979,14 +2085,11 @@ msgstr "Произошли ошибки во Ð²Ñ€ÐµÐ¼Ñ ÑƒÑтановки %{tit
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr "По умолчанию ÐºÐ¾Ð½Ñ„Ð¸Ð³ÑƒÑ€Ð°Ñ†Ð¸Ñ ÐºÐ»Ð°Ñтера предоÑтавлÑет доÑтуп к широкому набору функциональных возможноÑтей, необходимых Ð´Ð»Ñ ÑƒÑпешного ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¸ Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ð¹ в контейнерах."
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr " У Ñтой учетной запиÑи должны быть Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð½Ð° Ñоздание клаÑтера Kubernetes в %{link_to_container_project} указанных ниже"
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
-msgstr "Переключить КлаÑтер Kubernetes"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "Переключить клаÑтер Kubernetes"
@@ -2003,6 +2106,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "ЕÑли привÑзать клаÑтер Kubernetes к Ñтому проекту, вы Ñ Ð»Ñ‘Ð³ÐºÐ¾Ñтью Ñможете иÑпользовать Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ñ€ÐµÐ²ÑŒÑŽ, развертывать ваши приложениÑ, запуÑкать Ñборочные линии и многое другое."
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Ваша ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ должна иметь %{link_to_kubernetes_engine}"
@@ -2021,9 +2127,6 @@ msgstr "документациÑ"
msgid "ClusterIntegration|help page"
msgstr "Ñтраница Ñправки"
-msgid "ClusterIntegration|installing applications"
-msgstr "ClusterIntegration | уÑтановка приложений"
-
msgid "ClusterIntegration|meets the requirements"
msgstr "отвечает требованиÑм"
@@ -2033,6 +2136,9 @@ msgstr "правильно наÑтроен"
msgid "ClusterIntegration|sign up"
msgstr "зарегиÑтрироватьÑÑ"
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -2042,12 +2148,18 @@ msgstr "Свернуть"
msgid "Collapse sidebar"
msgstr "Свернуть боковую панель"
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr "Комментарии"
@@ -2086,6 +2198,9 @@ msgstr "Коммит"
msgid "CommitMessage|Add %{file_name}"
msgstr "Добавить %{file_name}"
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr "Коммиты"
@@ -2158,8 +2273,8 @@ msgstr "КонфиденциальноÑÑ‚ÑŒ"
msgid "Configure Gitaly timeouts."
msgstr "ÐаÑтройка таймаутов Gitaly."
-msgid "Configure Sidekiq job throttling."
-msgstr "ÐаÑтройте фактор уÑÐºÐ¾Ñ€ÐµÐ½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ очереди иÑполнителей фоновых заданий Sidekiq."
+msgid "Configure Tracing"
+msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr ""
@@ -2167,10 +2282,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr "ÐаÑтройка ограничений Ð´Ð»Ñ Web и API запроÑов."
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2260,6 +2375,9 @@ msgstr "УчаÑтие"
msgid "Contribution guide"
msgstr "РуководÑтво учаÑтника"
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2293,6 +2411,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2314,15 +2444,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr "Скопировать ÑÑылку в буфер обмена"
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr "Скопировать в буфер обмена"
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr "Создать"
@@ -2398,8 +2540,8 @@ msgstr "Ðовый"
msgid "Create project label"
msgstr "Создать метку проекта"
-msgid "CreateNewFork|Fork"
-msgstr "Ответвить"
+msgid "Create your first page"
+msgstr ""
msgid "CreateTag|Tag"
msgstr "Тег"
@@ -2449,6 +2591,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð½Ð°Ñтраиваемых уведомлений"
@@ -2467,6 +2612,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr "Ðналитика Цикла"
@@ -2518,6 +2666,9 @@ msgstr "Декабрь"
msgid "Decline and sign out"
msgstr "Отклонить и выйти"
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2530,6 +2681,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "Определить наÑтраиваемый шаблон Ñ ÑинтакÑиÑом cron"
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr "Удалить"
@@ -2539,6 +2705,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr "Удалить ÑпиÑок"
@@ -2678,6 +2847,12 @@ msgstr "Ваш Ðовый Токен РазвертываниÑ"
msgid "DeployTokens|Your new project deploy token has been created."
msgstr "Создан новый токен Ð´Ð»Ñ Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð°."
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2702,6 +2877,12 @@ msgstr "ÐŸÐ¾Ð´Ñ€Ð¾Ð±Ð½Ð°Ñ Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ"
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr "Ð˜Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð° недоÑтупно"
@@ -2723,12 +2904,27 @@ msgstr "Отключить Ð´Ð»Ñ Ñтого проекта"
msgid "Disable group Runners"
msgstr "Выключить групповые обработчиков заданий"
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr "Отменить изменениÑ"
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr "Удалить черновик"
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2744,6 +2940,9 @@ msgstr "Отключить блок Ð²Ð²ÐµÐ´ÐµÐ½Ð¸Ñ Ð² Ðналитику ЦиÐ
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2825,7 +3024,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2870,9 +3069,6 @@ msgstr "Включить Ð´Ð»Ñ Ñтого проекта"
msgid "Enable group Runners"
msgstr "Включить групповые обработчики заданий"
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2885,6 +3081,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr "Включите панель производительноÑти Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ð¾Ð¹ группы."
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2987,8 +3189,8 @@ msgstr ""
msgid "Environments|Updated"
msgstr "Обновлено"
-msgid "Environments|You don't have any environments right now."
-msgstr "Ð’Ñ‹ пока не наÑтроили ни одного окружениÑ."
+msgid "Environments|You don't have any environments right now"
+msgstr ""
msgid "Environments|protected"
msgstr ""
@@ -3020,10 +3222,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3134,6 +3336,12 @@ msgstr "Развернуть вÑе"
msgid "Expand sidebar"
msgstr "Развернуть боковую панель"
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3188,6 +3396,12 @@ msgstr "Ðе удалоÑÑŒ изменить владельца"
msgid "Failed to check related branches."
msgstr "Ðе удалоÑÑŒ проверить ÑвÑзанные ветки."
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr "Ошибка при удалении обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ñ Ð´Ð¾Ñки, повторите попытку."
@@ -3197,6 +3411,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "Ðе удалоÑÑŒ удалить раÑпиÑание Ñборочной линии"
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr "Ошибка Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¾Ð±Ñуждений, пожалуйÑта, попробуйте Ñнова."
@@ -3206,6 +3423,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr "Фев."
@@ -3215,6 +3507,9 @@ msgstr "Февраль"
msgid "Fields on this page are now uneditable, you can configure"
msgstr "ÐŸÐ¾Ð»Ñ Ð½Ð° Ñтой Ñтранице ÑÐµÐ¹Ñ‡Ð°Ñ Ð½ÐµÐ´Ð¾Ñтупны Ð´Ð»Ñ Ñ€ÐµÐ´Ð°ÐºÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ, вы можете наÑтроить"
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr "Файлы"
@@ -3227,9 +3522,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr "Фильтр по комментариÑми к коммитам"
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr "ПоиÑк по пути"
@@ -3245,6 +3549,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr "Завершено"
@@ -3257,7 +3564,7 @@ msgstr "отправлено автором"
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3296,19 +3603,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] "Ответвление"
-msgstr[1] "ОтветвлениÑ"
-msgstr[2] "Ответвлений"
-msgstr[3] "ОтветвлениÑ"
-
msgid "ForkedFromProjectPath|Forked from"
msgstr "Ответвлено от"
@@ -3324,6 +3630,9 @@ msgstr "Формат"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr "Из %{provider_title}"
@@ -3366,6 +3675,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr "Создать Ñтандартный набор меток"
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3540,10 +3852,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3552,6 +3876,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3573,7 +3900,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3585,6 +3912,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3594,19 +3924,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3624,6 +3960,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3636,9 +3978,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3648,9 +4008,6 @@ msgstr "URL-Ð°Ð´Ñ€ÐµÑ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ Git"
msgid "Git revision"
msgstr "Ð ÐµÐ²Ð¸Ð·Ð¸Ñ git"
-msgid "Git storage health information has been reset"
-msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ ÑтабильноÑти Git хранилища была Ñброшена"
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3717,12 +4074,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr "Перейти к вашему ответвлению"
-
-msgid "GoToYourFork|Fork"
-msgstr "Ответвление"
-
msgid "Google Code import"
msgstr ""
@@ -3753,9 +4104,21 @@ msgstr ""
msgid "Group Runners"
msgstr "Групповые Обработчики Заданий (GitLab Group Runner)"
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3765,6 +4128,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3783,13 +4149,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3816,9 +4182,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Запретить публикацию проектов из %{group} в других группах"
-msgid "GroupSettings|Share with group lock"
-msgstr "Опубликовать Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð¾Ð²Ð¾Ð¹ блокировкой"
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "Эта наÑтройка применена в %{ancestor_group} и была переопределена в Ñтой подгруппе."
@@ -3876,6 +4239,9 @@ msgstr "Группы не найдены"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Ð’Ñ‹ можете управлÑÑ‚ÑŒ правами и доÑтупом учаÑтников вашей группы к каждому проекту в группе."
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr "Создать проект в Ñтой группе."
@@ -3888,20 +4254,20 @@ msgstr "Редактировать группу"
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr "Ðе удалоÑÑŒ покинуть группу. ПожалуйÑта, убедитеÑÑŒ, что вы не единÑтвенный владелец."
-msgid "GroupsTree|Filter by name..."
-msgstr "Фильтр по имени..."
-
msgid "GroupsTree|Leave this group"
msgstr "Покинуть Ñту группу"
msgid "GroupsTree|Loading groups"
msgstr "Загрузка групп"
-msgid "GroupsTree|Sorry, no groups matched your search"
-msgstr "К Ñожалению, по вашему запроÑу групп не найдено"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
-msgstr "К Ñожалению, по вашему запроÑу групп или проектов не найдено"
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
msgid "Have your users email"
msgstr ""
@@ -3942,6 +4308,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "Скрыть значение"
@@ -4108,6 +4477,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4178,6 +4550,12 @@ msgstr "Шаблон интервала"
msgid "Introducing Cycle Analytics"
msgstr "Внедрение Цикла Ðналитик"
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4202,6 +4580,36 @@ msgstr "ОбÑуждениÑми могут быть ошибки, задачи
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr "Янв."
@@ -4217,9 +4625,6 @@ msgstr "Фоновое задание было удалено"
msgid "Jobs"
msgstr "ЗаданиÑ"
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4256,7 +4661,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4274,12 +4679,6 @@ msgstr "Июн."
msgid "June"
msgstr "Июнь"
-msgid "Koding"
-msgstr "Koding"
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -4352,6 +4751,9 @@ msgstr "ПеренеÑти Метку"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] "ПоÑледний %d день"
@@ -4365,12 +4767,18 @@ msgstr "ПоÑледнÑÑ Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð›Ð¸Ð½Ð¸Ñ"
msgid "Last commit"
msgstr "ПоÑледний коммит"
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr "Дата поÑледнего изменениÑ: %{date}"
msgid "Last edited by %{name}"
msgstr "Ðвтор поÑледнего изменениÑ: %{name}"
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr "ПоÑледнее обновление"
@@ -4419,6 +4827,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4428,6 +4845,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4437,6 +4857,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4446,6 +4869,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4458,9 +4884,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4489,6 +4921,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4534,6 +4969,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4603,14 +5041,44 @@ msgstr "Отметить как Ñделанное"
msgid "Markdown enabled"
msgstr "Включен режим Markdown"
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
-msgstr "МакÑимальное количеÑтво Ñбоев хранилища git"
+msgid "Max access level"
+msgstr ""
msgid "Maximum job timeout"
msgstr ""
@@ -4621,6 +5089,12 @@ msgstr "Май"
msgid "Median"
msgstr "Среднее"
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr "УчаÑтники"
@@ -4654,6 +5128,21 @@ msgstr "ЗапроÑÑ‹ на ÑлиÑние"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "ЗапроÑÑ‹ на ÑлиÑние- Ñто меÑто, где можно предлагать Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð²Ð½Ð¾Ñимые в проект, и обÑуждать Ñти Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼Ð¸"
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4663,9 +5152,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4675,6 +5161,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr "Слито"
@@ -4690,6 +5182,9 @@ msgstr "Метрики - Influx"
msgid "Metrics - Prometheus"
msgstr "Метрики - Prometheus"
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4906,6 +5401,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr "Помощь"
@@ -5027,6 +5525,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr "Плановый Ñрок не указан"
@@ -5036,9 +5540,6 @@ msgstr ""
msgid "No file chosen"
msgstr "Файл не выбран"
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr "Файлы не найдены."
@@ -5048,6 +5549,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -5075,6 +5579,9 @@ msgstr ""
msgid "No repository"
msgstr "Ðет репозиториÑ"
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr "Ðет раÑпиÑаний"
@@ -5111,6 +5618,9 @@ msgstr "Ðе конфиденциально"
msgid "Not enough data"
msgstr "ÐедоÑтаточно данных"
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr "Обратите внимание, что маÑтер ветка автоматичеÑки защищена. %{link_to_protected_branches}"
@@ -5129,6 +5639,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr "Ð£Ð²ÐµÐ´Ð¾Ð¼Ð»ÐµÐ½Ð¸Ñ Ð¾ ÑобытиÑÑ…"
@@ -5201,9 +5723,6 @@ msgstr "ÐоÑб."
msgid "November"
msgstr "ÐоÑбрь"
-msgid "Number of access attempts"
-msgstr "КоличеÑтво попыток доÑтупа"
-
msgid "OK"
msgstr ""
@@ -5232,9 +5751,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5256,6 +5772,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr "Открыть в Xcode"
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5280,6 +5799,21 @@ msgstr "ОткроетÑÑ Ð² новом окне"
msgid "Operations"
msgstr "Операции"
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5346,6 +5880,9 @@ msgstr "Пароль"
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5373,15 +5910,15 @@ msgstr "ÐžÐ¿Ñ‚Ð¸Ð¼Ð¸Ð·Ð°Ñ†Ð¸Ñ Ð¿Ñ€Ð¾Ð¸Ð·Ð²Ð¾Ð´Ð¸Ñ‚ÐµÐ»ÑŒÐ½Ð¾Ñти"
msgid "Permissions"
msgstr "Права доÑтупа"
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
msgid "Personal Access Token"
msgstr "ПерÑональный Токен ДоÑтупа"
msgid "Pipeline"
msgstr "Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ"
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
-msgstr ""
-
msgid "Pipeline Health"
msgstr "РаботоÑпоÑобноÑÑ‚ÑŒ Сборочной Линии"
@@ -5499,15 +6036,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "Этот проект в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ Ð½Ðµ наÑтроен Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑка Ñборочных линий."
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr "ЗапуÑтить Ñборочную линию"
@@ -5517,6 +6063,12 @@ msgstr "ПоиÑк веток"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr "ОÑтановить Ñборочную линию"
@@ -5544,12 +6096,6 @@ msgstr "Ñо ÑтадиÑми"
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr "PlantUML"
@@ -5559,12 +6105,18 @@ msgstr "ЗапуÑк"
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5577,6 +6129,9 @@ msgstr "ПожалуйÑта, решите reCAPTCHA"
msgid "Please try again"
msgstr "ПожалуйÑта, попробуйте ещё раз"
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5589,9 +6144,18 @@ msgstr "ПредпочтениÑ"
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5637,15 +6201,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr "Изменить Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr "Текущий путь: %{path}"
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr "Удалить Учетную запиÑÑŒ"
@@ -5658,39 +6237,120 @@ msgstr "Удалить Ñвою учетную запиÑÑŒ?"
msgid "Profiles|Deleting an account has the following effects:"
msgstr "Удаление учетной запиÑи приведет к Ñледующим поÑледÑтвиÑм:"
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr "Ðеверный пароль"
msgid "Profiles|Invalid username"
msgstr "Ðеверное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr "Путь"
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Введите значение %{confirmationValue} Ð´Ð»Ñ Ð¿Ð¾Ð´Ñ‚Ð²ÐµÑ€Ð¶Ð´ÐµÐ½Ð¸Ñ:"
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr "Обновить Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr "Ошибка Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¸Ð¼ÐµÐ½Ð¸ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ - %{message}"
msgid "Profiles|Username successfully changed"
msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ ÑƒÑпешно изменено"
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr "У Ð²Ð°Ñ Ð½ÐµÑ‚ прав на удаление Ñтого пользователÑ."
@@ -5700,6 +6360,15 @@ msgstr "Перед удалением учётной запиÑи, вам нео
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "Ваша ÑƒÑ‡ÐµÑ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ в наÑтоÑщее Ð²Ñ€ÐµÐ¼Ñ ÑвлÑетÑÑ Ð²Ð»Ð°Ð´ÐµÐ»ÑŒÑ†ÐµÐ¼ Ñледующих групп:"
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5736,6 +6405,9 @@ msgstr "Проект '%{project_name}' уÑпешно обновлен."
msgid "Project Badges"
msgstr "Значки Проекта"
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr "ДоÑтуп к проекту должен предоÑтавлÑÑ‚ÑŒÑÑ Ñвно каждому пользователю."
@@ -5763,6 +6435,9 @@ msgstr "Ðачат ÑкÑпорт проекта. СÑылка Ð´Ð»Ñ Ñкачи
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "ПодпиÑатьÑÑ"
@@ -5790,6 +6465,27 @@ msgstr "Ðикогда"
msgid "ProjectLifecycle|Stage"
msgstr "Этап"
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5832,6 +6528,9 @@ msgstr "Проекты"
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr "ЧаÑто поÑещаемые"
@@ -5901,9 +6600,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr "По умолчанию, Prometheus запуÑкаетÑÑ Ð¿Ð¾ адреÑу ‘http://localhost:9090’. Ðе рекомендуетÑÑ Ð¸Ð·Ð¼ÐµÐ½ÑÑ‚ÑŒ Ð°Ð´Ñ€ÐµÑ Ð¸ порт по умолчанию, так как Ñто может привеÑти к конфликту Ñ Ð´Ñ€ÑƒÐ³Ð¸Ð¼ ÑервиÑами запущенными на GitLab Ñервере."
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6096,6 +6792,12 @@ msgstr "ИнÑтрукциÑ"
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr "СÑылка:"
@@ -6160,12 +6862,21 @@ msgstr ""
msgid "Remove avatar"
msgstr "Удалить аватар"
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr "Удалить проект"
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6175,6 +6886,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6184,18 +6898,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6208,6 +6937,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6241,11 +6973,11 @@ msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð´Ð¾Ñтупа"
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
-msgstr "СброÑить информацию о работоÑпоÑобноÑти Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸Ñ git"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
msgid "Reset health check access token"
msgstr "СброÑить ключ доÑтупа проверки работоÑпоÑобноÑти"
@@ -6262,9 +6994,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr "Закрыть диÑкуÑÑию"
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6317,9 +7061,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr "Обработчики заданий"
@@ -6329,6 +7088,12 @@ msgstr "API обработчиков заданий"
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr "Обработчики заданий могут запуÑкатьÑÑ Ñƒ отдельных пользователей, Ñерверах и даже на вашей локальной машине."
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6353,11 +7118,14 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
msgid "SSH Keys"
-msgstr "SSH Ключи"
+msgstr "SSH-ключи"
msgid "SSH host keys"
msgstr ""
@@ -6377,6 +7145,9 @@ msgstr ""
msgid "Save changes"
msgstr "Сохранить изменениÑ"
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Сохранить раÑпиÑание Ñборочной лини"
@@ -6431,15 +7202,24 @@ msgstr ""
msgid "Search milestones"
msgstr "ПоиÑк Ñтапов"
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr "ПоиÑк проекта"
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr "ПоиÑк пользователей"
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6464,13 +7244,7 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
-msgstr "Секунд до очиÑтки информации о ÑбоÑÑ…"
-
-msgid "Seconds to wait for a storage access attempt"
-msgstr "Секунд задержки между попытками доÑтупа к хранилищу"
-
-msgid "Secret:"
+msgid "Secret"
msgstr ""
msgid "Security"
@@ -6479,14 +7253,46 @@ msgstr ""
msgid "Security Dashboard"
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6504,9 +7310,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr "Выбрать формат архива"
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr "Выбор временной зоны"
@@ -6537,6 +7349,9 @@ msgstr ""
msgid "Select target branch"
msgstr "Выбор целевой ветки"
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6549,6 +7364,9 @@ msgstr ""
msgid "Send email"
msgstr "Отправить Ñлектронное пиÑьмо"
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr "Сент."
@@ -6573,6 +7391,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "УÑтановите пароль в Ñвоем аккаунте, чтобы отправлÑÑ‚ÑŒ или получать код через %{protocol}."
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6591,8 +7412,11 @@ msgstr ""
msgid "Set up CI/CD"
msgstr "ÐаÑтройка CI/CD"
-msgid "Set up Koding"
-msgstr "ÐаÑтройка Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
@@ -6603,14 +7427,32 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "уÑтановите пароль"
-msgid "Settings"
-msgstr "ÐаÑтройки"
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
-msgstr "ÐаÑтроить конкретный обработчик заданий автоматичеÑки"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr "ÐаÑтройки"
msgid "Share"
msgstr "ПоделитьÑÑ"
@@ -6621,6 +7463,9 @@ msgstr ""
msgid "Shared Runners"
msgstr "Общие обработчики заданий"
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6706,12 +7551,18 @@ msgstr "ÐаÑтройки размера и доменных имён Ð´Ð»Ñ Ñ
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr "Сниппеты"
@@ -6739,9 +7590,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr "Что-то пошло не так при получении проектов."
@@ -6754,12 +7611,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr "Произошла ошибка. Попробуйте позже."
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr "Сортировать по"
@@ -6790,6 +7659,9 @@ msgstr "ÐšÑ€ÑƒÐ¿Ð½ÐµÐ¹ÑˆÐ°Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð°"
msgid "SortOptions|Largest repository"
msgstr "Крупнейший репозиторий"
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr "ПоÑледние Ñозданные"
@@ -6820,6 +7692,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr "Ðаиболее популÑрный"
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr "ИмÑ"
@@ -6850,6 +7725,9 @@ msgstr "Приоритет"
msgid "SortOptions|Recent sign in"
msgstr "Ðедавно заходившие"
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr "Ðачатые позже"
@@ -6911,7 +7789,7 @@ msgid "Star a label to make it a priority label. Order the prioritized labels to
msgstr ""
msgid "StarProject|Star"
-msgstr "Отметить"
+msgstr "В избранное"
msgid "Starred Projects"
msgstr "Избранные проекты"
@@ -6920,14 +7798,26 @@ msgid "Starred Projects' Activity"
msgstr "ÐктивноÑÑ‚ÑŒ в избранных проектах"
msgid "Starred projects"
-msgstr "Отмеченные проекты"
+msgstr "Избранные проекты"
msgid "Start a %{new_merge_request} with these changes"
msgstr "Ðачать %{new_merge_request} Ñ Ñтих изменений"
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "ЗапуÑтить GitLab Runner!"
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr "Запущен"
@@ -6940,6 +7830,9 @@ msgstr ""
msgid "Status"
msgstr "СтатуÑ"
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6949,6 +7842,9 @@ msgstr "ОÑтановить Ñту Ñреду"
msgid "Stopped"
msgstr "ОÑтановлен"
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr "Хранилище"
@@ -6958,9 +7854,15 @@ msgstr ""
msgid "Subgroups"
msgstr "Подгруппы"
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6973,6 +7875,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Переключить ветка/тег"
@@ -6991,6 +7899,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] "Тег (%{tag_count})"
@@ -7097,6 +8008,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7145,12 +8059,6 @@ msgstr "Ð¡Ñ‚Ð°Ð´Ð¸Ñ Ð¾Ð±ÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¿Ð¾ÐºÐ°Ð·Ñ‹Ð²Ð°ÐµÑ‚ времÑ, коÑ
msgid "The maximum file size allowed is 200KB."
msgstr "МакÑимально допуÑтимый размер файла ÑоÑтавлÑет 200 Кб."
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr "КоличеÑтво попыток, которые GitLab будет предпринимать Ð´Ð»Ñ Ð´Ð¾Ñтупа к хранилищу."
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7199,9 +8107,6 @@ msgstr "Этап обзора показывает Ð²Ñ€ÐµÐ¼Ñ Ð¾Ñ‚ ÑозданÐ
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "Этап поÑтановки показывает Ð²Ñ€ÐµÐ¼Ñ Ð¼ÐµÐ¶Ð´Ñƒ ÑлиÑнием \"MR\" и развертыванием кода в производÑтвенной Ñреде. Данные будут автоматичеÑки добавлены поÑле Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð² производÑтве первый раз."
@@ -7211,21 +8116,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr "Этап теÑÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ÐºÐ°Ð·Ñ‹Ð²Ð°ÐµÑ‚ времÑ, которое GitLab CI занимает Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑка каждой Ñборочной линии Ð´Ð»Ñ ÑоответÑтвующего запроÑа на ÑлиÑние. Данные будут автоматичеÑки добавлены поÑле Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð¸Ñ Ñ€Ð°Ð±Ð¾Ñ‚Ñ‹ вашей первой Ñборочной линии."
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð² Ñекундах, в течение которого GitLab будет хранить информацию о ÑбоÑÑ…. ЕÑли в течение Ñтого времени не было Ñбоев, Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ монтировании очищаетÑÑ."
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð² Ñекундах в течении которого GitLab будет пытатьÑÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð¸Ñ‚ÑŒ доÑтуп к хранилищу. ПоÑле Ñтого времени будет зафикÑирована ошибка Ð¿Ñ€ÐµÐ²Ñ‹ÑˆÐµÐ½Ð¸Ñ Ð²Ñ€ÐµÐ¼ÐµÐ½Ð¸ ожиданиÑ."
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr "ВремÑ, затраченное каждым Ñлементом, Ñобранным на Ñтом Ñтапе."
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7235,6 +8134,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "Среднее значение в Ñ€Ñду. Пример: между 3, 5, 9, Ñреднее 5, между 3, 5, 7, 8, Ñреднее (5+7)/2 = 6."
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr "Ðет обÑуждений, которые можно показать"
@@ -7244,8 +8146,14 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
-msgstr "Проблемы Ñ Ð´Ð¾Ñтупом к Git хранилищу: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
msgid "There was an error adding a todo."
msgstr ""
@@ -7292,10 +8200,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7316,6 +8227,9 @@ msgstr "Эта группа пока не Ñодержит групповых о
msgid "This is a confidential issue."
msgstr "Это конфиденциальное обÑуждение."
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr "Это первый Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние от автора в Ñтот проект."
@@ -7355,7 +8269,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7376,6 +8293,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr "Это фоновое задание требует ручных дейÑтвий"
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Это означает, что вы не можете отправить код, пока не Ñоздадите пуÑтой репозиторий или не импортируете ÑущеÑтвующий."
@@ -7400,6 +8320,9 @@ msgstr "Этот проект"
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr "Этот проект не отноÑитÑÑ Ð½Ð¸ к какой группе и поÑтому не может иÑпользовать групповые обработчики заданий."
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7409,6 +8332,12 @@ msgstr "Этот репозиторий"
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7436,9 +8365,15 @@ msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð´Ð¾ начала Ð¿Ð¾Ð¿Ð°Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±ÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð²
msgid "Time before an issue starts implementation"
msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð´Ð¾ начала работы над обÑуждением"
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð¼ÐµÐ¶Ð´Ñƒ Ñозданием запроÑа ÑлиÑÐ½Ð¸Ñ Ð¸ ÑлиÑнием / закрытием"
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7633,12 +8568,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7654,6 +8601,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7666,12 +8616,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr "Дела"
@@ -7681,9 +8634,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7699,6 +8658,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7714,6 +8676,9 @@ msgstr "Общее Ð²Ñ€ÐµÐ¼Ñ Ñ‚ÐµÑÑ‚Ð¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ñ„Ð¸ÐºÑаций/ÑлиÑ
msgid "Total: %{total}"
msgstr "Ð’Ñего: %{total}"
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7723,6 +8688,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7741,24 +8709,42 @@ msgstr "ЗапуÑтить Ñто дейÑтвие вручную"
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr "Попробовать Ñнова"
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr "Ðе удаетÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·Ð¸Ñ‚ÑŒ отличиÑ. %{button_try_again}"
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7774,6 +8760,12 @@ msgstr "Разблокировано"
msgid "Unresolve discussion"
msgstr "Переоткрыть диÑкуÑÑию"
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7790,7 +8782,7 @@ msgid "Unstaged and staged %{type}"
msgstr ""
msgid "Unstar"
-msgstr "СнÑÑ‚ÑŒ отметку"
+msgstr "Убрать из избранного"
msgid "Unsubscribe"
msgstr ""
@@ -7807,13 +8799,16 @@ msgstr "Ðеподтверждено"
msgid "Up to date"
msgstr "Ðктуальный"
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7843,15 +8838,15 @@ msgstr "Загрузить новый файл"
msgid "Upload file"
msgstr "Загрузить файл"
-msgid "Upload new avatar"
-msgstr "Загрузить аватар"
-
msgid "UploadLink|click to upload"
msgstr "кликните Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸"
msgid "Upvotes"
msgstr "ГолоÑа \"за\""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr "СтатиÑтика иÑпользованиÑ"
@@ -7879,6 +8874,9 @@ msgstr "ИÑпользуютÑÑ Ð³Ð»Ð¾Ð±Ð°Ð»ÑŒÐ½Ñ‹Ð¹ наÑтройки увеÐ
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7888,12 +8886,54 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
-msgstr "Пользователи"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|Subscribe"
msgstr ""
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
+msgstr "Пользователи"
+
msgid "Variables"
msgstr "Переменные"
@@ -7918,6 +8958,15 @@ msgstr "Проверено"
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7951,9 +9000,15 @@ msgstr "ПроÑмотр меток проекта"
msgid "View replaced file @ "
msgstr "ПроÑмотр заменённого файла @ "
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7972,6 +9027,36 @@ msgstr "Публичный"
msgid "VisibilityLevel|Unknown"
msgstr "Ðе определен"
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Хотите увидеть данные? ОбратитеÑÑŒ к админиÑтратору за доÑтупом."
@@ -8011,6 +9096,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr "Wiki"
@@ -8114,7 +9205,7 @@ msgid "WikiPageEdit|Update %{page_title}"
msgstr "Обновить %{page_title}"
msgid "WikiPage|Page slug"
-msgstr "СемантичеÑкий Url Ð´Ð»Ñ Ñтраницы"
+msgstr "URL Ð´Ð»Ñ Ñтраницы"
msgid "WikiPage|Write your content or drag files here…"
msgstr ""
@@ -8161,6 +9252,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8179,9 +9273,6 @@ msgstr "Ð’Ñ‹ ÑобираетеÑÑŒ передать проект %{project_full
msgid "You are on a read-only GitLab instance."
msgstr "Ð’Ñ‹ иÑпользуете GitLab в режиме только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ."
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8191,9 +9282,6 @@ msgstr "Ð’Ñ‹ также можете Ñоздать проект из коман
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8215,12 +9303,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr "Ð’Ñ‹ не можете запиÑывать на Ñтот ÑкземплÑÑ€ \"только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ\" клаÑтера GitLab."
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8242,9 +9336,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr "Ðеобходимо войти, чтобы оценить проект"
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8254,6 +9345,12 @@ msgstr ""
msgid "You need permission."
msgstr "Вам нужно разрешение."
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr "Ð’Ñ‹ не получите никаких уведомлений по Ñлектронной почте"
@@ -8320,6 +9417,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr "Ваши Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð±Ñ‹Ð»Ð¸ зафикÑированы. Коммит %{commitId} %{commitStats}"
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr "Ваш комментарий не будет виден вÑем."
@@ -8341,20 +9441,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "assign yourself"
msgstr "назначить ÑебÑ"
@@ -8382,61 +9468,86 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8469,9 +9580,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8498,6 +9606,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8516,13 +9627,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8531,9 +9636,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8564,9 +9666,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8580,9 +9679,6 @@ msgstr[3] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8614,29 +9710,19 @@ msgstr[3] "дней"
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
-
msgid "disabled"
msgstr "отключено"
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "enabled"
msgstr "включено"
@@ -8646,6 +9732,12 @@ msgstr ""
msgid "for this project"
msgstr ""
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -8677,6 +9769,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8911,6 +10006,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8929,6 +10027,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr "новый Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
@@ -8961,6 +10062,13 @@ msgstr "токен Ð´Ð»Ñ Ð¿ÐµÑ€Ñонального доÑтупа"
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "remaining"
msgstr "оÑталоÑÑŒ"
@@ -8973,6 +10081,13 @@ msgstr "убрать плановый Ñрок"
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "source"
msgstr "иÑходный текÑÑ‚"
@@ -8988,6 +10103,9 @@ msgstr "Ñтот документ"
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr "Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
diff --git a/locale/sk_SK/gitlab.po b/locale/sk_SK/gitlab.po
new file mode 100644
index 00000000000..b8feb7a634b
--- /dev/null
+++ b/locale/sk_SK/gitlab.po
@@ -0,0 +1,10127 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
+"Language-Team: Slovak\n"
+"Language: sk_SK\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 3;\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: sk\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"PO-Revision-Date: 2018-11-19 17:19\n"
+
+msgid " Status"
+msgstr ""
+
+msgid " and"
+msgstr ""
+
+msgid " degraded on %d point"
+msgid_plural " degraded on %d points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid " improved on %d point"
+msgid_plural " improved on %d points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d changed file"
+msgid_plural "%d changed files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d failed test result"
+msgid_plural "%d failed test results"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d staged change"
+msgid_plural "%d staged changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%d unstaged change"
+msgid_plural "%d unstaged changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_timeago}"
+msgstr ""
+
+msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgstr ""
+
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{loadingIcon} Started"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+msgid "%{nip_domain} can be used as an alternative to a custom domain."
+msgstr ""
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr ""
+
+msgid "%{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
+
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid "- Runner is active and can process any new jobs"
+msgstr ""
+
+msgid "- Runner is paused and will not receive any new jobs"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "1 %{type} addition"
+msgid_plural "%{count} %{type} additions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 %{type} modification"
+msgid_plural "%{count} %{type} modifications"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 closed issue"
+msgid_plural "%d closed issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 closed merge request"
+msgid_plural "%d closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 merged merge request"
+msgid_plural "%d merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 open merge request"
+msgid_plural "%d open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1 user"
+msgid_plural "%d users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "2FA enabled"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get the permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
+msgstr ""
+
+msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
+msgstr ""
+
+msgid "<strong>%{group_name}</strong> group members"
+msgstr ""
+
+msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
+msgstr ""
+
+msgid "<strong>Removes</strong> source branch"
+msgstr ""
+
+msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
+msgstr ""
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
+msgstr ""
+
+msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About GitLab CE"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Accepted MR"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied! Please verify you can add deploy keys to this repository."
+msgstr ""
+
+msgid "Access expiration date"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add Changelog"
+msgstr ""
+
+msgid "Add Contribution guide"
+msgstr ""
+
+msgid "Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add Readme"
+msgstr ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add projects"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add todo"
+msgstr ""
+
+msgid "Add user(s) to the group:"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Admin Area"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "Admin area"
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminProjects|Delete project"
+msgstr ""
+
+msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
+
+msgid "Advanced settings"
+msgstr ""
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "All"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr ""
+
+msgid "All users"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch."
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts"
+msgstr ""
+
+msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
+msgstr ""
+
+msgid "Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An error accured whilst committing your changes."
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error occured creating the new branch."
+msgstr ""
+
+msgid "An error occured whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occured whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occured whilst loading all the files."
+msgstr ""
+
+msgid "An error occured whilst loading the file content."
+msgstr ""
+
+msgid "An error occured whilst loading the file."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request."
+msgstr ""
+
+msgid "An error occured whilst loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
+msgstr ""
+
+msgid "An error occurred while adding approver"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while fetching markdown preview"
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching sidebar data"
+msgstr ""
+
+msgid "An error occurred while fetching stages."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the pipeline."
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while importing project: %{details}"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while removing approver"
+msgstr ""
+
+msgid "An error occurred while rendering KaTeX"
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while retrieving calendar activity"
+msgstr ""
+
+msgid "An error occurred while retrieving diff"
+msgstr ""
+
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
+msgstr ""
+
+msgid "An error occurred while subscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while unsubscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any Label"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read-only"
+msgstr ""
+
+msgid "Archived projects"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Artifact ID"
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer to set up a group Runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned Merge Requests"
+msgstr ""
+
+msgid "Assigned to :name"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assignee"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee lists show all issues assigned to the selected user."
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto DevOps, runners and job artifacts"
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
+msgstr ""
+
+msgid "Auto-cancel redundant, pending pipelines"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
+msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
+msgstr ""
+
+msgid "AutoDevOps|add a Kubernetes cluster"
+msgstr ""
+
+msgid "AutoDevOps|enable Auto DevOps"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available group Runners : %{runners}"
+msgstr ""
+
+msgid "Available group Runners : %{runners}."
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|A new badge was added."
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Delete badge"
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|No badge image"
+msgstr ""
+
+msgid "Badges|No image to preview"
+msgstr ""
+
+msgid "Badges|Please fill in a valid URL"
+msgstr ""
+
+msgid "Badges|Project Badge"
+msgstr ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|The badge was saved."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "Badges|e.g. %{exampleUrl}"
+msgstr ""
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are examples of regex for existing tools:"
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
+msgstr ""
+
+msgid "BillingPlans|Current plan"
+msgstr ""
+
+msgid "BillingPlans|Customer Support"
+msgstr ""
+
+msgid "BillingPlans|Downgrade"
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
+msgstr ""
+
+msgid "BillingPlans|Manage plan"
+msgstr ""
+
+msgid "BillingPlans|Please contact %{customer_support_link} in that case."
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Upgrade"
+msgstr ""
+
+msgid "BillingPlans|You are currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
+msgstr ""
+
+msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
+msgstr ""
+
+msgid "BillingPlans|features"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|paid annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch (%{branch_count})"
+msgid_plural "Branches (%{branch_count})"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch has changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "BranchSwitcherPlaceholder|Search branches"
+msgstr ""
+
+msgid "BranchSwitcherTitle|Switch branch"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cant find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch '%{branch_name}'?"
+msgstr ""
+
+msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+msgstr ""
+
+msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Branches|Only a project maintainer or owner can delete a protected branch"
+msgstr ""
+
+msgid "Branches|Overview"
+msgstr ""
+
+msgid "Branches|Protected branches can be managed in %{project_settings_link}."
+msgstr ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Sort by"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+msgstr ""
+
+msgid "Branches|The default branch cannot be deleted"
+msgstr ""
+
+msgid "Branches|This branch hasn’t been merged into %{default_branch}."
+msgstr ""
+
+msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
+msgid "Branches|To confirm, type %{branch_name_confirmation}:"
+msgstr ""
+
+msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
+msgstr ""
+
+msgid "Branches|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|project settings"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "Built-In"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CI / CD"
+msgstr ""
+
+msgid "CI / CD Settings"
+msgstr ""
+
+msgid "CI will run using the credentials assigned above."
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD for external repo"
+msgstr ""
+
+msgid "CI/CD settings"
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Deployment strategy needs a domain name to work correctly."
+msgstr ""
+
+msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|Learn more about Auto DevOps"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "Callback URL"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Certificate fingerprint"
+msgstr ""
+
+msgid "Change Weight"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates."
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "Changelog"
+msgstr ""
+
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
+msgstr ""
+
+msgid "Choose <strong>Next</strong> at the bottom of the page."
+msgstr ""
+
+msgid "Choose File ..."
+msgstr ""
+
+msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
+msgstr ""
+
+msgid "Choose file..."
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose which groups you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose which repositories you want to import."
+msgstr ""
+
+msgid "Choose which shards you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Error occured while saving variables"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "CiVariable|Validation failed"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
+msgstr ""
+
+msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
+msgstr ""
+
+msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
+msgstr ""
+
+msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
+msgstr ""
+
+msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Client authentication certificate"
+msgstr ""
+
+msgid "Client authentication key"
+msgstr ""
+
+msgid "Client authentication key password"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
+msgstr ""
+
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgstr ""
+
+msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|Applications"
+msgstr ""
+
+msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Token"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Helm Tiller"
+msgstr ""
+
+msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
+msgstr ""
+
+msgid "ClusterIntegration|Hide"
+msgstr ""
+
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|In order to show the health of the cluster, we'll need to provision your cluster with Prometheus to collect the required data."
+msgstr ""
+
+msgid "ClusterIntegration|Ingress"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress IP Address"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
+msgstr ""
+
+msgid "ClusterIntegration|Install"
+msgstr ""
+
+msgid "ClusterIntegration|Install Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Installed"
+msgstr ""
+
+msgid "ClusterIntegration|Installing"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
+msgstr ""
+
+msgid "ClusterIntegration|Integration status"
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster health"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
+msgstr ""
+
+msgid "ClusterIntegration|More information"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Note:"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Service token"
+msgstr ""
+
+msgid "ClusterIntegration|Show"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Token"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|check the pricing here"
+msgstr ""
+
+msgid "ClusterIntegration|documentation"
+msgstr ""
+
+msgid "ClusterIntegration|help page"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|properly configured"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "Code owners"
+msgstr ""
+
+msgid "Cohorts"
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & resolve discussion"
+msgstr ""
+
+msgid "Comment & unresolve discussion"
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Commit (%{commit_count})"
+msgid_plural "Commits (%{commit_count})"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit duration in minutes for last 30 commits"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|Commit: %{commitText}"
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Commit…"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|Compare"
+msgstr ""
+
+msgid "CompareBranches|Source"
+msgstr ""
+
+msgid "CompareBranches|Target"
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Tracing"
+msgstr ""
+
+msgid "Configure automatic git checks and housekeeping on repositories."
+msgstr ""
+
+msgid "Configure limits for web and API requests."
+msgstr ""
+
+msgid "Configure push mirrors."
+msgstr ""
+
+msgid "Configure storage path settings."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the way a user creates a new account."
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Created"
+msgstr ""
+
+msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
+msgstr ""
+
+msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
+msgstr ""
+
+msgid "ContainerRegistry|How to use the Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Learn more about"
+msgstr ""
+
+msgid "ContainerRegistry|No tags in Container Registry for this container image."
+msgstr ""
+
+msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgstr ""
+
+msgid "ContainerRegistry|Size"
+msgstr ""
+
+msgid "ContainerRegistry|Tag"
+msgstr ""
+
+msgid "ContainerRegistry|Tag ID"
+msgstr ""
+
+msgid "ContainerRegistry|Use different image names"
+msgstr ""
+
+msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
+msgstr ""
+
+msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution guide"
+msgstr ""
+
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "ContributorsPage|%{startDate} – %{endDate}"
+msgstr ""
+
+msgid "ContributorsPage|Building repository graph."
+msgstr ""
+
+msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Control the display of third party offers."
+msgstr ""
+
+msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of repository backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of verification operations for this Geo node"
+msgstr ""
+
+msgid "ConvDev Index"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key to clipboard"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy branch name to clipboard"
+msgstr ""
+
+msgid "Copy command to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Copy file path to clipboard"
+msgstr ""
+
+msgid "Copy incoming email address to clipboard"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
+msgid "Copy reference to clipboard"
+msgstr ""
+
+msgid "Copy secret to clipboard"
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token to clipboard"
+msgstr ""
+
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new branch and merge request"
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create branch"
+msgstr ""
+
+msgid "Create commit"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty repository"
+msgstr ""
+
+msgid "Create epic"
+msgstr ""
+
+msgid "Create file"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created on"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron syntax"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current node"
+msgstr ""
+
+msgid "CurrentUser|Profile"
+msgstr ""
+
+msgid "CurrentUser|Settings"
+msgstr ""
+
+msgid "Custom"
+msgstr ""
+
+msgid "Custom CI config path"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Production"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Default Branch"
+msgstr ""
+
+msgid "Default classification label"
+msgstr ""
+
+msgid "Default: Directly import the Google Code email address or username"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete Package"
+msgstr ""
+
+msgid "Delete Snippet"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete list"
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployKeys|Write access allowed"
+msgstr ""
+
+msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Add a deploy token"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository"
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Copy username to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Deploy Tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|This project has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "DeployTokens|Use this username as a login."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|You are about to revoke"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group Runners"
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "Discard review"
+msgstr ""
+
+msgid "Discover GitLab Geo."
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss Cycle Analytics introduction box"
+msgstr ""
+
+msgid "Dismiss Merge Request promotion"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Each Runner can be in one of the following states:"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Elasticsearch"
+msgstr ""
+
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable SAML authentication for this group"
+msgstr ""
+
+msgid "Enable Sentry for error reporting and logging."
+msgstr ""
+
+msgid "Enable and configure InfluxDB metrics."
+msgstr ""
+
+msgid "Enable and configure Prometheus metrics."
+msgstr ""
+
+msgid "Enable classification control using an external service"
+msgstr ""
+
+msgid "Enable for this project"
+msgstr ""
+
+msgid "Enable group Runners"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable reCAPTCHA or Akismet and set IP limits."
+msgstr ""
+
+msgid "Enable the Performance Bar for a given group."
+msgstr ""
+
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter the issue description"
+msgstr ""
+
+msgid "Enter the issue title"
+msgstr ""
+
+msgid "Enter the merge request description"
+msgstr ""
+
+msgid "Enter the merge request title"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No pod name has been specified"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod logs from"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Read more about environments"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epic will be removed! Are you sure?"
+msgstr ""
+
+msgid "Epics"
+msgstr ""
+
+msgid "Epics Roadmap"
+msgstr ""
+
+msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
+msgstr ""
+
+msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgstr ""
+
+msgid "Epics|How can I solve this?"
+msgstr ""
+
+msgid "Epics|More information"
+msgstr ""
+
+msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+msgstr ""
+
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr ""
+
+msgid "Epics|due"
+msgstr ""
+
+msgid "Epics|start"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Reporting and Logging"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error fetching contributors data."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching usage ping data."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error updating status for all todos."
+msgstr ""
+
+msgid "Error updating todo status."
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "Every day (at 4:00am)"
+msgstr ""
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr ""
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
+msgid "Explore"
+msgstr ""
+
+msgid "Explore GitLab"
+msgstr ""
+
+msgid "Explore Groups"
+msgstr ""
+
+msgid "Explore groups"
+msgstr ""
+
+msgid "Explore projects"
+msgstr ""
+
+msgid "Explore public groups"
+msgstr ""
+
+msgid "External Classification Policy Authorization"
+msgstr ""
+
+msgid "External authentication"
+msgstr ""
+
+msgid "External authorization denied access to this project"
+msgstr ""
+
+msgid "External authorization request timeout"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification Label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to remove issue from board, please try again."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to update issues, please try again."
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fields on this page are now uneditable, you can configure"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Files (%{human_size})"
+msgstr ""
+
+msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
+msgid "Filter by commit message"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Find the downloaded ZIP file and decompress it."
+msgstr ""
+
+msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish review"
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "FirstPushedBy|First"
+msgstr ""
+
+msgid "FirstPushedBy|pushed by"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Follow the steps below to export your Google Code project data."
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Format"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
+msgid "From %{provider_title}"
+msgstr ""
+
+msgid "From Bitbucket"
+msgstr ""
+
+msgid "From Bitbucket Server"
+msgstr ""
+
+msgid "From FogBugz"
+msgstr ""
+
+msgid "From GitLab.com"
+msgstr ""
+
+msgid "From Google Code"
+msgstr ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "From milestones:"
+msgstr ""
+
+msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Nodes"
+msgstr ""
+
+msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is failing or broken."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
+msgstr ""
+
+msgid "GeoNodes|Checksummed"
+msgstr ""
+
+msgid "GeoNodes|Data is out of date from %{timeago}"
+msgstr ""
+
+msgid "GeoNodes|Data replication lag"
+msgstr ""
+
+msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "GeoNodes|Failed"
+msgstr ""
+
+msgid "GeoNodes|Full"
+msgstr ""
+
+msgid "GeoNodes|GitLab version"
+msgstr ""
+
+msgid "GeoNodes|GitLab version does not match the primary node version"
+msgstr ""
+
+msgid "GeoNodes|Health status"
+msgstr ""
+
+msgid "GeoNodes|Last event ID processed by cursor"
+msgstr ""
+
+msgid "GeoNodes|Last event ID seen from primary"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository verification"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki verification"
+msgstr ""
+
+msgid "GeoNodes|Loading nodes"
+msgstr ""
+
+msgid "GeoNodes|Local LFS objects"
+msgstr ""
+
+msgid "GeoNodes|Local attachments"
+msgstr ""
+
+msgid "GeoNodes|Local job artifacts"
+msgstr ""
+
+msgid "GeoNodes|New node"
+msgstr ""
+
+msgid "GeoNodes|Node Authentication was successfully repaired."
+msgstr ""
+
+msgid "GeoNodes|Node was successfully removed."
+msgstr ""
+
+msgid "GeoNodes|Not checksummed"
+msgstr ""
+
+msgid "GeoNodes|Out of sync"
+msgstr ""
+
+msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Replication slot WAL"
+msgstr ""
+
+msgid "GeoNodes|Replication slots"
+msgstr ""
+
+msgid "GeoNodes|Repositories"
+msgstr ""
+
+msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Repositories verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Repository verification progress"
+msgstr ""
+
+msgid "GeoNodes|Selective"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while changing node status"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while fetching nodes"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while removing node"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while repairing node"
+msgstr ""
+
+msgid "GeoNodes|Storage config"
+msgstr ""
+
+msgid "GeoNodes|Sync settings"
+msgstr ""
+
+msgid "GeoNodes|Synced"
+msgstr ""
+
+msgid "GeoNodes|Unused slots"
+msgstr ""
+
+msgid "GeoNodes|Unverified"
+msgstr ""
+
+msgid "GeoNodes|Used slots"
+msgstr ""
+
+msgid "GeoNodes|Verified"
+msgstr ""
+
+msgid "GeoNodes|Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Wiki verification progress"
+msgstr ""
+
+msgid "GeoNodes|Wikis"
+msgstr ""
+
+msgid "GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for forced re-download"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-check"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|All"
+msgstr ""
+
+msgid "Geo|All projects"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|File sync capacity"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Groups to synchronize"
+msgstr ""
+
+msgid "Geo|In sync"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|Not synced yet"
+msgstr ""
+
+msgid "Geo|Pending"
+msgstr ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Recheck"
+msgstr ""
+
+msgid "Geo|Recheck all projects"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Repository sync capacity"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all projects"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Select groups to replicate."
+msgstr ""
+
+msgid "Geo|Shards to synchronize"
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
+msgid "Geo|Unknown state"
+msgstr ""
+
+msgid "Geo|Verification capacity"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|You need a different license to use Geo replication"
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Git"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git strategy for pipelines"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitLab CI Linter has been moved"
+msgstr ""
+
+msgid "GitLab Geo"
+msgstr ""
+
+msgid "GitLab Group Runners can execute code for all the projects in this group."
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab single sign on URL"
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLab’s issue tracker"
+msgstr ""
+
+msgid "Gitaly"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go to"
+msgstr ""
+
+msgid "Go to %{link_to_google_takeout}."
+msgstr ""
+
+msgid "Google Code import"
+msgstr ""
+
+msgid "Google Takeout"
+msgstr ""
+
+msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group CI/CD settings"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group Runners"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group details"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group maintainers can register group runners in the %{link}"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Loading roadmap"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|Until %{dateWord}"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Customize your group badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about badges."
+msgstr ""
+
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+msgstr ""
+
+msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
+msgstr ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Create a project in this group."
+msgstr ""
+
+msgid "GroupsTree|Create a subgroup in this group."
+msgstr ""
+
+msgid "GroupsTree|Edit group"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave this group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Have your users email"
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help page"
+msgstr ""
+
+msgid "Help page text and support page url."
+msgstr ""
+
+msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Hide whitespace changes"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Client side evaluation"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Open in file view"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "Identity provider single sign on URL"
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr ""
+
+msgid "If disabled, the access level will depend on the user's permissions in the project."
+msgstr ""
+
+msgid "If enabled"
+msgstr ""
+
+msgid "If enabled, access to projects will be validated on an external service using their classification label."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you already have files you can push them using the %{link_to_cli} below."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import all compatible projects"
+msgstr ""
+
+msgid "Import all projects"
+msgstr ""
+
+msgid "Import all repositories"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import projects from Google Code"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "Improve Issue boards with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
+msgid "In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "Incompatible Project"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input your repository URL"
+msgstr ""
+
+msgid "Install GitLab Runner"
+msgstr ""
+
+msgid "Install Runner on Kubernetes"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Instance Statistics"
+msgstr ""
+
+msgid "Instance Statistics visibility"
+msgstr ""
+
+msgid "Instance does not support multiple Kubernetes clusters"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations Settings"
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Cycle Analytics"
+msgstr ""
+
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue board focus mode"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Job"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed in"
+msgstr ""
+
+msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration was not removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes configured"
+msgstr ""
+
+msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label lists show all issues with the selected label."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{name}"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
+msgstr ""
+
+msgid "Learn more about Kubernetes"
+msgstr ""
+
+msgid "Learn more about protected branches"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
+msgid "LicenseManagement|Approve license"
+msgstr ""
+
+msgid "LicenseManagement|Approve license?"
+msgstr ""
+
+msgid "LicenseManagement|Approved"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license?"
+msgstr ""
+
+msgid "LicenseManagement|Blacklisted"
+msgstr ""
+
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
+msgid "LicenseManagement|License"
+msgstr ""
+
+msgid "LicenseManagement|License Management"
+msgstr ""
+
+msgid "LicenseManagement|License details"
+msgstr ""
+
+msgid "LicenseManagement|License name"
+msgstr ""
+
+msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
+msgstr ""
+
+msgid "LicenseManagement|Packages"
+msgstr ""
+
+msgid "LicenseManagement|Remove license"
+msgstr ""
+
+msgid "LicenseManagement|Remove license?"
+msgstr ""
+
+msgid "LicenseManagement|Submit"
+msgstr ""
+
+msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
+msgstr ""
+
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseManagement|URL"
+msgstr ""
+
+msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "LinkedIn"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "List Your Gitea Repositories"
+msgstr ""
+
+msgid "List available repositories"
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "List your GitHub repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked to current projects"
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make sure you're logged into the account that owns the projects you'd like to import."
+msgstr ""
+
+msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
+msgstr ""
+
+msgid "Manage Web IDE features"
+msgstr ""
+
+msgid "Manage access"
+msgstr ""
+
+msgid "Manage all notifications"
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a full email address"
+msgstr ""
+
+msgid "Map a Google Code user to a full name"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark todo as done"
+msgstr ""
+
+msgid "Markdown enabled"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
+msgid "Maven Metadata"
+msgstr ""
+
+msgid "Maven package"
+msgstr ""
+
+msgid "Max access level"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Median"
+msgstr ""
+
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Request:"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge requests"
+msgstr ""
+
+msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
+msgid "MergeRequests|Resolve this discussion in a new issue"
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|Toggle comments for this file"
+msgstr ""
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr ""
+
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Influx"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics|Business"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgstr ""
+
+msgid "Metrics|Environment"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgstr ""
+
+msgid "Metrics|Learn about environments"
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|Name"
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|No deployed environments"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|Query"
+msgstr ""
+
+msgid "Metrics|Response"
+msgstr ""
+
+msgid "Metrics|System"
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|Type"
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
+msgid "Milestone"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Mirror a repository"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror user"
+msgstr ""
+
+msgid "Mirrored repositories"
+msgstr ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
+msgid "Modal|Cancel"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More actions"
+msgstr ""
+
+msgid "More info"
+msgstr ""
+
+msgid "More information"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Multiple issue boards"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name your individual key via a title"
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Snippets"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No Label"
+msgstr ""
+
+msgid "No assignee"
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No container images stored for this project. Add one by following the instructions above."
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No issues for the selected time period."
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No merge requests for the selected time period."
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No packages stored for this project."
+msgstr ""
+
+msgid "No prioritised labels with such name or description"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No pushes for the selected time period."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No, directly import the existing email addresses and usernames."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "Not all comments are displayed because you're comparing two versions of the diff."
+msgstr ""
+
+msgid "Not all comments are displayed because you're viewing an old version of the diff."
+msgstr ""
+
+msgid "Not allowed to merge"
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not enough data"
+msgstr ""
+
+msgid "Not now"
+msgstr ""
+
+msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "Only admins"
+msgstr ""
+
+msgid "Only comments from the following commit are shown below"
+msgstr ""
+
+msgid "Only mirror protected branches"
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open in Xcode"
+msgstr ""
+
+msgid "Open projects"
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open source software to collaborate on code"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened MR"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Otherwise it is recommended you start with one of the options below."
+msgstr ""
+
+msgid "Outbound requests"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Package information"
+msgstr ""
+
+msgid "Package was removed"
+msgstr ""
+
+msgid "Packages"
+msgstr ""
+
+msgid "Pages"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
+
+msgid "Path, transfer, remove"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Paused Runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "Per job. If a job passes this threshold, it will be marked as failed"
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, or removing the group."
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline Health"
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline quota"
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines for last month"
+msgstr ""
+
+msgid "Pipelines for last week"
+msgstr ""
+
+msgid "Pipelines for last year"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|CI Lint"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgstr ""
+
+msgid "Pipelines|Get started with Pipelines"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|There are currently no %{scope} pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+msgstr ""
+
+msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Create for"
+msgstr ""
+
+msgid "Pipeline|Create pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Existing branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Search branches"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|all"
+msgstr ""
+
+msgid "Pipeline|success"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Please accept the Terms of Service before continuing."
+msgstr ""
+
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please solve the reCAPTCHA"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences|Navigation theme"
+msgstr ""
+
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Private - Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|Add status emoji"
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
+msgid "Profiles|Clear status"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Delete Account"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Delete your account?"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Website"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project avatar in repository: %{link}"
+msgstr ""
+
+msgid "Project details"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectLifecycle|Stage"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Customize your project badges."
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Learn more about badges."
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
+msgstr ""
+
+msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "PrometheusAlerts|Add alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Edit alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error creating alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error deleting alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error fetching alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error saving alert"
+msgstr ""
+
+msgid "PrometheusAlerts|No alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Operator"
+msgstr ""
+
+msgid "PrometheusAlerts|Threshold"
+msgstr ""
+
+msgid "PrometheusDashboard|Time"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration"
+msgstr ""
+
+msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
+msgstr ""
+
+msgid "PrometheusService|Common metrics"
+msgstr ""
+
+msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
+msgstr ""
+
+msgid "PrometheusService|Custom metrics"
+msgstr ""
+
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr ""
+
+msgid "PrometheusService|Finding custom metrics..."
+msgstr ""
+
+msgid "PrometheusService|Install Prometheus on clusters"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+msgstr ""
+
+msgid "PrometheusService|More information"
+msgstr ""
+
+msgid "PrometheusService|New metric"
+msgstr ""
+
+msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|Time-series monitoring service"
+msgstr ""
+
+msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
+msgstr ""
+
+msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
+msgstr ""
+
+msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote these project milestones into a group milestone."
+msgstr ""
+
+msgid "Promote to Group Milestone"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Environments"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "Protip:"
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Pseudonymizer data collection"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRule|Committer restriction"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
+
+msgid "Readme"
+msgstr ""
+
+msgid "Real-time features"
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Reference:"
+msgstr ""
+
+msgid "Refresh"
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Regenerate key"
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register and see your runners for this group."
+msgstr ""
+
+msgid "Register and see your runners for this project."
+msgstr ""
+
+msgid "Registry"
+msgstr ""
+
+msgid "Related Commits"
+msgstr ""
+
+msgid "Related Deployed Jobs"
+msgstr ""
+
+msgid "Related Issues"
+msgstr ""
+
+msgid "Related Jobs"
+msgstr ""
+
+msgid "Related Merge Requests"
+msgstr ""
+
+msgid "Related Merged Requests"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove Runner"
+msgstr ""
+
+msgid "Remove avatar"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
+msgid "Rename"
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Repair authentication"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{failedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|Class"
+msgstr ""
+
+msgid "Reports|Confidence"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository URL"
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirror"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Requests Profiles"
+msgstr ""
+
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
+msgid "Resolve all discussions in new issue"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve discussion"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal Variables"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
+msgid "Runner token"
+msgstr ""
+
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners API"
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, and even on your local machine."
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|You have used all your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML Single Sign On"
+msgstr ""
+
+msgid "SAML Single Sign On Settings"
+msgstr ""
+
+msgid "SAST"
+msgstr ""
+
+msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save variables"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scoped issue boards"
+msgstr ""
+
+msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or jump to…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in this group"
+msgstr ""
+
+msgid "SearchAutocomplete|in this project"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr ""
+
+msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgstr ""
+
+msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select a group to invite"
+msgstr ""
+
+msgid "Select a namespace to fork the project"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select an existing Kubernetes cluster or create a new one"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select branch/tag"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project and zone to choose machine type"
+msgstr ""
+
+msgid "Select project to choose zone"
+msgstr ""
+
+msgid "Select projects you want to import."
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Select the custom project template source group."
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Selective synchronization"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send usage data"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
+msgstr ""
+
+msgid "Session expiration, projects limit and attachment size."
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set instance-wide template repository"
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Sherlock Transactions"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show latest version of the diff"
+msgstr ""
+
+msgid "Show parent pages"
+msgstr ""
+
+msgid "Show parent subgroups"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|Change weight"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in to %{group_name}"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong when toggling the button"
+msgstr ""
+
+msgid "Something went wrong while closing the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while fetching %{listType} list"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the projects."
+msgstr ""
+
+msgid "Something went wrong while fetching the registry list."
+msgstr ""
+
+msgid "Something went wrong while reopening the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Sorry, no epics matched your search"
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "SortOptions|Access level, ascending"
+msgstr ""
+
+msgid "SortOptions|Access level, descending"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Milestone"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest joined"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source code"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Specific Runners"
+msgstr ""
+
+msgid "Specify an e-mail address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage & Commit"
+msgstr ""
+
+msgid "Stage all changes"
+msgstr ""
+
+msgid "Stage changes"
+msgstr ""
+
+msgid "Staged"
+msgstr ""
+
+msgid "Staged %{type}"
+msgstr ""
+
+msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start the Runner!"
+msgstr ""
+
+msgid "Start your trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Stop environment"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Sync information"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System header and footer:"
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "Tag (%{tag_count})"
+msgid_plural "Tags (%{tag_count})"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release notes"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag."
+msgstr ""
+
+msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Sort by"
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Test SAML SSO"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+msgid "Thanks! Don't show me this again"
+msgstr ""
+
+msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
+msgstr ""
+
+msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr ""
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The deployment of this job to %{environmentLink} did not succeed."
+msgstr ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr ""
+
+msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
+msgstr ""
+
+msgid "The phase of the development lifecycle."
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr ""
+
+msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
+msgstr ""
+
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr ""
+
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
+msgstr ""
+
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The tabs below will be removed in a future version"
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no merge requests to show"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
+
+msgid "There was an error adding a todo."
+msgstr ""
+
+msgid "There was an error deleting the todo."
+msgstr ""
+
+msgid "There was an error loading users activity calendar."
+msgstr ""
+
+msgid "There was an error saving your notification settings."
+msgstr ""
+
+msgid "There was an error subscribing to this label."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "They can be managed using the %{link}."
+msgstr ""
+
+msgid "Third party offers"
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
+msgstr ""
+
+msgid "This application was created by %{link_to_owner}."
+msgstr ""
+
+msgid "This application will be able to:"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This branch has changed since you started editing. Would you like to create a new branch?"
+msgstr ""
+
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This group"
+msgstr ""
+
+msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgstr ""
+
+msgid "This group does not provide any group Runners yet."
+msgstr ""
+
+msgid "This is a confidential issue."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is the author's first Merge Request to this project."
+msgstr ""
+
+msgid "This issue is confidential"
+msgstr ""
+
+msgid "This issue is confidential and locked."
+msgstr ""
+
+msgid "This issue is locked."
+msgstr ""
+
+msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "This job is the most recent deployment to %{link}."
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This option is disabled as you don't have write permissions for the current branch"
+msgstr ""
+
+msgid "This option is disabled while you still have unstaged changes"
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page will be removed in a future release."
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project does not belong to a group and can therefore not make use of group Runners."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "This source diff could not be displayed because it is too large."
+msgstr ""
+
+msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
+msgstr ""
+
+msgid "This will delete the custom metric, Are you sure?"
+msgstr ""
+
+msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time before enforced"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds ago"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip:"
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr ""
+
+msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
+msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr ""
+
+msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
+msgstr ""
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr ""
+
+msgid "To start serving your jobs you can add Runners to your group"
+msgstr ""
+
+msgid "To this GitLab instance"
+msgstr ""
+
+msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
+msgstr ""
+
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
+
+msgid "To widen your search, change or remove filters."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Todo"
+msgstr ""
+
+msgid "Todos"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle discussion"
+msgstr ""
+
+msgid "Toggle file browser"
+msgstr ""
+
+msgid "Toggle navigation"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: OFF"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: ON"
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Time"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track activity with Contribution Analytics."
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trigger"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Turn on Service Desk"
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to save your changes"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unresolve discussion"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
+msgid "Unstage all changes"
+msgstr ""
+
+msgid "Unstage changes"
+msgstr ""
+
+msgid "Unstaged"
+msgstr ""
+
+msgid "Unstaged %{type}"
+msgstr ""
+
+msgid "Unstaged and staged %{type}"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Upgrade your plan to activate Advanced Global Search."
+msgstr ""
+
+msgid "Upgrade your plan to activate Contribution Analytics."
+msgstr ""
+
+msgid "Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Upgrade your plan to activate Issue weight."
+msgstr ""
+
+msgid "Upgrade your plan to improve Issue boards."
+msgstr ""
+
+msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage ping is not enabled"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "Use <code>%{native_redirect_uri}</code> for local tests"
+msgstr ""
+
+msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
+msgstr ""
+
+msgid "Use group milestones to manage issues from multiple projects in the same milestone."
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use the following registration token during setup:"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "Used by members to sign in to your group in GitLab"
+msgstr ""
+
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Variables"
+msgstr ""
+
+msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification information"
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View epics list"
+msgstr ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View group labels"
+msgstr ""
+
+msgid "View issue"
+msgstr ""
+
+msgid "View it on GitLab"
+msgstr ""
+
+msgid "View jobs"
+msgstr ""
+
+msgid "View labels"
+msgstr ""
+
+msgid "View log"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr ""
+
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|It is recommended to install %{markdown} so that GFM features render locally:"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgstr ""
+
+msgid "WikiMarkdownDocs|documentation"
+msgstr ""
+
+msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgstr ""
+
+msgid "WikiNewPagePlaceholder|how-to-setup"
+msgstr ""
+
+msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiNewPageTitle|New Wiki Page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgstr ""
+
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPageConflictMessage|the page"
+msgstr ""
+
+msgid "WikiPageCreate|Create %{page_title}"
+msgstr ""
+
+msgid "WikiPageEdit|Update %{page_title}"
+msgstr ""
+
+msgid "WikiPage|Page slug"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wiki|Create Page"
+msgstr ""
+
+msgid "Wiki|Create page"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|More Pages"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, let me map Google Code users to full names or GitLab users."
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
+msgstr ""
+
+msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You can %{linkStart}view the blob%{linkEnd} instead."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
+msgid "You can only edit files when you are on a branch"
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
+msgstr ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+msgstr ""
+
+msgid "You cannot write to this read-only GitLab instance."
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You must accept our Terms of Service and privacy policy in order to register an account"
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're receiving this email because %{reason}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your Todos"
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your comment will not be visible to the public."
+msgstr ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your projects"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "among other things"
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{namespace} is affected by %{vulnerability}."
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr ""
+
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr ""
+
+msgid "ciReport|(is loading)"
+msgstr ""
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr ""
+
+msgid "ciReport|Class"
+msgstr ""
+
+msgid "ciReport|Code quality"
+msgstr ""
+
+msgid "ciReport|Confidence"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Description"
+msgstr ""
+
+msgid "ciReport|Dismiss vulnerability"
+msgstr ""
+
+msgid "ciReport|Dismissed by"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|File"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Identifiers"
+msgstr ""
+
+msgid "ciReport|Instances"
+msgstr ""
+
+msgid "ciReport|Learn more about interacting with security reports (Alpha)."
+msgstr ""
+
+msgid "ciReport|License management detected %d license for the source branch only"
+msgid_plural "ciReport|License management detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|License management detected %d new license"
+msgid_plural "ciReport|License management detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|License management detected no licenses for the source branch only"
+msgstr ""
+
+msgid "ciReport|License management detected no new licenses"
+msgstr ""
+
+msgid "ciReport|Links"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|Method"
+msgstr ""
+
+msgid "ciReport|Namespace"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No changes to performance metrics"
+msgstr ""
+
+msgid "ciReport|Performance metrics"
+msgstr ""
+
+msgid "ciReport|Revert dismissal"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Severity"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error loading DAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading SAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading container scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error loading dependency scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "ciReport|on pipeline"
+msgstr ""
+
+msgid "command line instructions"
+msgstr ""
+
+msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgstr ""
+
+msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
+msgstr ""
+
+msgid "connecting"
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "customize"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "deploy token"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "here"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "importing"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "issue boards"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "license management"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|Add approval"
+msgstr ""
+
+msgid "mrWidget|Allows commits from members who can merge to the target branch"
+msgstr ""
+
+msgid "mrWidget|An error occured while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Cancel automatic merge"
+msgstr ""
+
+msgid "mrWidget|Check out branch"
+msgstr ""
+
+msgid "mrWidget|Checking ability to merge automatically"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes"
+msgstr ""
+
+msgid "mrWidget|Create an issue to resolve them later"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mentions"
+msgstr ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge request approved"
+msgstr ""
+
+msgid "mrWidget|Merge request approved; you can approve additionally"
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|No Approval required"
+msgstr ""
+
+msgid "mrWidget|No Approval required; you can still approve"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove Source Branch"
+msgstr ""
+
+msgid "mrWidget|Remove source branch"
+msgstr ""
+
+msgid "mrWidget|Remove your approval"
+msgstr ""
+
+msgid "mrWidget|Request to merge"
+msgstr ""
+
+msgid "mrWidget|Requires 1 more approval"
+msgid_plural "mrWidget|Requires %d more approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "mrWidget|Requires 1 more approval by"
+msgid_plural "mrWidget|Requires %d more approvals by"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Set by"
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The changes will be merged into"
+msgstr ""
+
+msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+msgstr ""
+
+msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
+msgstr ""
+
+msgid "mrWidget|The source branch has been removed"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will be removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will not be removed"
+msgstr ""
+
+msgid "mrWidget|There are merge conflicts"
+msgstr ""
+
+msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|This merge request is in the process of being merged"
+msgstr ""
+
+msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr ""
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|You can remove source branch now"
+msgstr ""
+
+msgid "mrWidget|branch does not exist."
+msgstr ""
+
+msgid "mrWidget|command line"
+msgstr ""
+
+msgid "mrWidget|into"
+msgstr ""
+
+msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "notification emails"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "password"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+msgid "source"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time spent."
+msgstr ""
+
+msgid "started"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "toggle collapse"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "within %d minute "
+msgid_plural "within %d minutes "
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
diff --git a/locale/sq_AL/gitlab.po b/locale/sq_AL/gitlab.po
index 762d4ef53a7..e2282f23bea 100644
--- a/locale/sq_AL/gitlab.po
+++ b/locale/sq_AL/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Albanian\n"
"Language: sq_AL\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: sq\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:30\n"
+"PO-Revision-Date: 2018-11-19 17:17\n"
msgid " Status"
msgstr ""
@@ -31,6 +31,14 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -46,6 +54,11 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -91,11 +104,6 @@ msgid_plural "%d unstaged changes"
msgstr[0] ""
msgstr[1] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] ""
@@ -104,17 +112,31 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] ""
msgstr[1] ""
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -124,6 +146,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -139,23 +164,12 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr ""
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr ""
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -167,27 +181,13 @@ msgstr ""
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -314,6 +314,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr ""
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -356,13 +365,10 @@ msgstr ""
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
+msgid "Access expiration date"
msgstr ""
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr ""
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -392,27 +398,48 @@ msgstr ""
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
+msgid "Add Kubernetes cluster"
msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -422,6 +449,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -455,9 +485,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -494,12 +521,17 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr ""
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "All"
msgstr ""
@@ -515,6 +547,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -524,6 +559,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -539,6 +580,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -560,7 +604,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -584,6 +628,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -596,6 +646,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -608,6 +661,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -635,6 +691,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -677,12 +736,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr ""
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -701,7 +766,7 @@ msgstr ""
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -719,9 +784,15 @@ msgstr ""
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -740,6 +811,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -878,6 +952,9 @@ msgstr ""
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -914,9 +991,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -995,6 +1069,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1285,6 +1368,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1315,9 +1401,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1372,7 +1455,7 @@ msgstr ""
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1399,6 +1482,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1429,6 +1518,9 @@ msgstr ""
msgid "CiStatusLabel|created"
msgstr ""
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr ""
@@ -1447,6 +1539,9 @@ msgstr ""
msgid "CiStatusLabel|skipped"
msgstr ""
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr ""
@@ -1459,6 +1554,9 @@ msgstr ""
msgid "CiStatusText|created"
msgstr ""
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr ""
@@ -1513,10 +1611,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1561,6 +1659,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1573,12 +1674,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1609,10 +1722,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1639,6 +1752,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1675,6 +1794,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1705,9 +1827,6 @@ msgstr ""
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1729,25 +1848,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster details"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster health"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster integration"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1759,7 +1872,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1768,16 +1881,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1795,9 +1905,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1825,6 +1932,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1837,6 +1947,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1867,9 +1980,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1909,13 +2019,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -1933,6 +2040,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -1951,9 +2061,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -1963,6 +2070,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -1972,12 +2082,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2012,6 +2128,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr ""
@@ -2084,7 +2203,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2093,10 +2212,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2186,6 +2305,9 @@ msgstr ""
msgid "Contribution guide"
msgstr ""
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2219,6 +2341,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2240,15 +2374,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2324,7 +2470,7 @@ msgstr ""
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
+msgid "Create your first page"
msgstr ""
msgid "CreateTag|Tag"
@@ -2375,6 +2521,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -2393,6 +2542,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr ""
@@ -2444,6 +2596,9 @@ msgstr ""
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2456,6 +2611,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr ""
@@ -2465,6 +2635,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2602,6 +2775,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2626,6 +2805,12 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2647,12 +2832,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2668,6 +2868,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2749,7 +2952,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2794,9 +2997,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2809,6 +3009,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2911,7 +3117,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -2944,10 +3150,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3058,6 +3264,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3112,6 +3324,12 @@ msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3121,6 +3339,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3130,6 +3351,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3139,6 +3435,9 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr ""
@@ -3151,9 +3450,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr ""
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr ""
@@ -3169,6 +3477,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3181,7 +3492,7 @@ msgstr ""
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3220,17 +3531,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -3246,6 +3558,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3288,6 +3603,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3462,10 +3780,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3474,6 +3804,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3495,7 +3828,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3507,6 +3840,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3516,19 +3852,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3546,6 +3888,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3558,9 +3906,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3570,9 +3936,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3639,12 +4002,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr ""
-
-msgid "GoToYourFork|Fork"
-msgstr ""
-
msgid "Google Code import"
msgstr ""
@@ -3675,9 +4032,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3687,6 +4056,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3705,13 +4077,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3738,9 +4110,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3798,6 +4167,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3810,19 +4182,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -3864,6 +4236,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4028,6 +4403,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4096,6 +4474,12 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4120,6 +4504,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4135,9 +4549,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4174,7 +4585,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4192,12 +4603,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4270,6 +4675,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
@@ -4281,12 +4689,18 @@ msgstr ""
msgid "Last commit"
msgstr ""
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4335,6 +4749,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4344,6 +4767,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4353,6 +4779,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4362,6 +4791,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4374,9 +4806,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4403,6 +4841,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4448,6 +4889,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4517,13 +4961,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4535,6 +5009,12 @@ msgstr ""
msgid "Median"
msgstr ""
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -4568,6 +5048,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4577,9 +5072,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4589,6 +5081,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4604,6 +5102,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4820,6 +5321,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -4939,6 +5443,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -4948,9 +5458,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -4960,6 +5467,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -4987,6 +5497,9 @@ msgstr ""
msgid "No repository"
msgstr ""
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr ""
@@ -5023,6 +5536,9 @@ msgstr ""
msgid "Not enough data"
msgstr ""
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -5041,6 +5557,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -5113,9 +5641,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5142,9 +5667,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5166,6 +5688,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5190,6 +5715,21 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5256,6 +5796,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5283,13 +5826,13 @@ msgstr ""
msgid "Permissions"
msgstr ""
-msgid "Personal Access Token"
+msgid "Permissions, LFS, 2FA"
msgstr ""
-msgid "Pipeline"
+msgid "Personal Access Token"
msgstr ""
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
+msgid "Pipeline"
msgstr ""
msgid "Pipeline Health"
@@ -5409,15 +5952,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5427,6 +5979,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5454,12 +6012,6 @@ msgstr ""
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5469,12 +6021,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5487,6 +6045,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5499,9 +6060,18 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5547,15 +6117,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5568,39 +6153,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -5610,6 +6276,15 @@ msgstr ""
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5646,6 +6321,9 @@ msgstr ""
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr ""
@@ -5673,6 +6351,9 @@ msgstr ""
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -5700,6 +6381,27 @@ msgstr ""
msgid "ProjectLifecycle|Stage"
msgstr ""
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5742,6 +6444,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5811,9 +6516,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6006,6 +6708,12 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6068,12 +6776,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6083,6 +6800,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6092,18 +6812,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6116,6 +6851,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6149,10 +6887,10 @@ msgstr ""
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6170,9 +6908,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6223,9 +6973,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6235,6 +7000,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6259,6 +7030,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6283,6 +7057,9 @@ msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -6337,15 +7114,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6370,27 +7156,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard"
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6408,9 +7222,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr ""
@@ -6441,6 +7261,9 @@ msgstr ""
msgid "Select target branch"
msgstr ""
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6453,6 +7276,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6477,6 +7303,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6495,7 +7324,10 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
@@ -6507,13 +7339,31 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "Settings"
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
msgstr ""
msgid "Share"
@@ -6525,6 +7375,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6608,12 +7461,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6641,9 +7500,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6656,12 +7521,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -6692,6 +7569,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6722,6 +7602,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6752,6 +7635,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6827,9 +7713,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6842,6 +7740,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6851,6 +7752,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6860,9 +7764,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6875,6 +7785,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -6893,6 +7809,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -6997,6 +7916,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7045,12 +7967,6 @@ msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7099,9 +8015,6 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr ""
@@ -7111,21 +8024,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr ""
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7135,6 +8042,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7144,7 +8054,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7192,10 +8108,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7216,6 +8135,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7255,7 +8177,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7276,6 +8201,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
@@ -7300,6 +8228,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7309,6 +8240,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7336,9 +8273,15 @@ msgstr ""
msgid "Time before an issue starts implementation"
msgstr ""
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr ""
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7529,12 +8472,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7550,6 +8505,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7562,12 +8520,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7577,9 +8538,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7595,6 +8562,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7610,6 +8580,9 @@ msgstr ""
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7619,6 +8592,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7637,24 +8613,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7670,6 +8664,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7703,13 +8703,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7739,15 +8742,15 @@ msgstr ""
msgid "Upload file"
msgstr ""
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr ""
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7775,6 +8778,9 @@ msgstr ""
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7784,10 +8790,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7814,6 +8862,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7847,9 +8904,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7868,6 +8931,36 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -7907,6 +9000,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8057,6 +9156,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8075,9 +9177,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8087,9 +9186,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8111,12 +9207,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8138,9 +9240,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr ""
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8150,6 +9249,12 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr ""
@@ -8216,6 +9321,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8237,16 +9345,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "assign yourself"
msgstr ""
@@ -8274,61 +9372,78 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8361,9 +9476,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8386,6 +9498,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8404,13 +9519,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8419,9 +9528,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8452,9 +9558,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8466,9 +9569,6 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8498,25 +9598,17 @@ msgstr[1] ""
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
-
msgid "disabled"
msgstr ""
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "enabled"
msgstr ""
@@ -8526,6 +9618,12 @@ msgstr ""
msgid "for this project"
msgstr ""
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -8555,6 +9653,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8783,6 +9884,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8801,6 +9905,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr ""
@@ -8829,6 +9936,11 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "remaining"
msgstr ""
@@ -8841,6 +9953,11 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "source"
msgstr ""
@@ -8856,6 +9973,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/sr_CS/gitlab.po b/locale/sr_CS/gitlab.po
new file mode 100644
index 00000000000..4a1ed2a3b2c
--- /dev/null
+++ b/locale/sr_CS/gitlab.po
@@ -0,0 +1,10061 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
+"Language-Team: Serbian (Latin)\n"
+"Language: sr_CS\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: sr-CS\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"PO-Revision-Date: 2018-11-19 17:19\n"
+
+msgid " Status"
+msgstr ""
+
+msgid " and"
+msgstr ""
+
+msgid " degraded on %d point"
+msgid_plural " degraded on %d points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid " improved on %d point"
+msgid_plural " improved on %d points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d changed file"
+msgid_plural "%d changed files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d failed test result"
+msgid_plural "%d failed test results"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d staged change"
+msgid_plural "%d staged changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d unstaged change"
+msgid_plural "%d unstaged changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_timeago}"
+msgstr ""
+
+msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgstr ""
+
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{loadingIcon} Started"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+msgid "%{nip_domain} can be used as an alternative to a custom domain."
+msgstr ""
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr ""
+
+msgid "%{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
+
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid "- Runner is active and can process any new jobs"
+msgstr ""
+
+msgid "- Runner is paused and will not receive any new jobs"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "1 %{type} addition"
+msgid_plural "%{count} %{type} additions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 %{type} modification"
+msgid_plural "%{count} %{type} modifications"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 closed issue"
+msgid_plural "%d closed issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 closed merge request"
+msgid_plural "%d closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 merged merge request"
+msgid_plural "%d merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 open merge request"
+msgid_plural "%d open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 user"
+msgid_plural "%d users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "2FA enabled"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get the permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
+msgstr ""
+
+msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
+msgstr ""
+
+msgid "<strong>%{group_name}</strong> group members"
+msgstr ""
+
+msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
+msgstr ""
+
+msgid "<strong>Removes</strong> source branch"
+msgstr ""
+
+msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
+msgstr ""
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
+msgstr ""
+
+msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About GitLab CE"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Accepted MR"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied! Please verify you can add deploy keys to this repository."
+msgstr ""
+
+msgid "Access expiration date"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add Changelog"
+msgstr ""
+
+msgid "Add Contribution guide"
+msgstr ""
+
+msgid "Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add Readme"
+msgstr ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add projects"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add todo"
+msgstr ""
+
+msgid "Add user(s) to the group:"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Admin Area"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "Admin area"
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminProjects|Delete project"
+msgstr ""
+
+msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
+
+msgid "Advanced settings"
+msgstr ""
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "All"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr ""
+
+msgid "All users"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch."
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts"
+msgstr ""
+
+msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
+msgstr ""
+
+msgid "Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An error accured whilst committing your changes."
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error occured creating the new branch."
+msgstr ""
+
+msgid "An error occured whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occured whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occured whilst loading all the files."
+msgstr ""
+
+msgid "An error occured whilst loading the file content."
+msgstr ""
+
+msgid "An error occured whilst loading the file."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request."
+msgstr ""
+
+msgid "An error occured whilst loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
+msgstr ""
+
+msgid "An error occurred while adding approver"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while fetching markdown preview"
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching sidebar data"
+msgstr ""
+
+msgid "An error occurred while fetching stages."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the pipeline."
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while importing project: %{details}"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while removing approver"
+msgstr ""
+
+msgid "An error occurred while rendering KaTeX"
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while retrieving calendar activity"
+msgstr ""
+
+msgid "An error occurred while retrieving diff"
+msgstr ""
+
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
+msgstr ""
+
+msgid "An error occurred while subscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while unsubscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any Label"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read-only"
+msgstr ""
+
+msgid "Archived projects"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Artifact ID"
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer to set up a group Runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned Merge Requests"
+msgstr ""
+
+msgid "Assigned to :name"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assignee"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee lists show all issues assigned to the selected user."
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto DevOps, runners and job artifacts"
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
+msgstr ""
+
+msgid "Auto-cancel redundant, pending pipelines"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
+msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
+msgstr ""
+
+msgid "AutoDevOps|add a Kubernetes cluster"
+msgstr ""
+
+msgid "AutoDevOps|enable Auto DevOps"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available group Runners : %{runners}"
+msgstr ""
+
+msgid "Available group Runners : %{runners}."
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|A new badge was added."
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Delete badge"
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|No badge image"
+msgstr ""
+
+msgid "Badges|No image to preview"
+msgstr ""
+
+msgid "Badges|Please fill in a valid URL"
+msgstr ""
+
+msgid "Badges|Project Badge"
+msgstr ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|The badge was saved."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "Badges|e.g. %{exampleUrl}"
+msgstr ""
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are examples of regex for existing tools:"
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
+msgstr ""
+
+msgid "BillingPlans|Current plan"
+msgstr ""
+
+msgid "BillingPlans|Customer Support"
+msgstr ""
+
+msgid "BillingPlans|Downgrade"
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
+msgstr ""
+
+msgid "BillingPlans|Manage plan"
+msgstr ""
+
+msgid "BillingPlans|Please contact %{customer_support_link} in that case."
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Upgrade"
+msgstr ""
+
+msgid "BillingPlans|You are currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
+msgstr ""
+
+msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
+msgstr ""
+
+msgid "BillingPlans|features"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|paid annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch (%{branch_count})"
+msgid_plural "Branches (%{branch_count})"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch has changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "BranchSwitcherPlaceholder|Search branches"
+msgstr ""
+
+msgid "BranchSwitcherTitle|Switch branch"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cant find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch '%{branch_name}'?"
+msgstr ""
+
+msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+msgstr ""
+
+msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Branches|Only a project maintainer or owner can delete a protected branch"
+msgstr ""
+
+msgid "Branches|Overview"
+msgstr ""
+
+msgid "Branches|Protected branches can be managed in %{project_settings_link}."
+msgstr ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Sort by"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+msgstr ""
+
+msgid "Branches|The default branch cannot be deleted"
+msgstr ""
+
+msgid "Branches|This branch hasn’t been merged into %{default_branch}."
+msgstr ""
+
+msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
+msgid "Branches|To confirm, type %{branch_name_confirmation}:"
+msgstr ""
+
+msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
+msgstr ""
+
+msgid "Branches|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|project settings"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "Built-In"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CI / CD"
+msgstr ""
+
+msgid "CI / CD Settings"
+msgstr ""
+
+msgid "CI will run using the credentials assigned above."
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD for external repo"
+msgstr ""
+
+msgid "CI/CD settings"
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Deployment strategy needs a domain name to work correctly."
+msgstr ""
+
+msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|Learn more about Auto DevOps"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "Callback URL"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Certificate fingerprint"
+msgstr ""
+
+msgid "Change Weight"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates."
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "Changelog"
+msgstr ""
+
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
+msgstr ""
+
+msgid "Choose <strong>Next</strong> at the bottom of the page."
+msgstr ""
+
+msgid "Choose File ..."
+msgstr ""
+
+msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
+msgstr ""
+
+msgid "Choose file..."
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose which groups you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose which repositories you want to import."
+msgstr ""
+
+msgid "Choose which shards you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Error occured while saving variables"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "CiVariable|Validation failed"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
+msgstr ""
+
+msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
+msgstr ""
+
+msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
+msgstr ""
+
+msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
+msgstr ""
+
+msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Client authentication certificate"
+msgstr ""
+
+msgid "Client authentication key"
+msgstr ""
+
+msgid "Client authentication key password"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
+msgstr ""
+
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgstr ""
+
+msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|Applications"
+msgstr ""
+
+msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Token"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Helm Tiller"
+msgstr ""
+
+msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
+msgstr ""
+
+msgid "ClusterIntegration|Hide"
+msgstr ""
+
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|In order to show the health of the cluster, we'll need to provision your cluster with Prometheus to collect the required data."
+msgstr ""
+
+msgid "ClusterIntegration|Ingress"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress IP Address"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
+msgstr ""
+
+msgid "ClusterIntegration|Install"
+msgstr ""
+
+msgid "ClusterIntegration|Install Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Installed"
+msgstr ""
+
+msgid "ClusterIntegration|Installing"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
+msgstr ""
+
+msgid "ClusterIntegration|Integration status"
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster health"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
+msgstr ""
+
+msgid "ClusterIntegration|More information"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Note:"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Service token"
+msgstr ""
+
+msgid "ClusterIntegration|Show"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Token"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|check the pricing here"
+msgstr ""
+
+msgid "ClusterIntegration|documentation"
+msgstr ""
+
+msgid "ClusterIntegration|help page"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|properly configured"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "Code owners"
+msgstr ""
+
+msgid "Cohorts"
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & resolve discussion"
+msgstr ""
+
+msgid "Comment & unresolve discussion"
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Commit (%{commit_count})"
+msgid_plural "Commits (%{commit_count})"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit duration in minutes for last 30 commits"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|Commit: %{commitText}"
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Commit…"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|Compare"
+msgstr ""
+
+msgid "CompareBranches|Source"
+msgstr ""
+
+msgid "CompareBranches|Target"
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Tracing"
+msgstr ""
+
+msgid "Configure automatic git checks and housekeeping on repositories."
+msgstr ""
+
+msgid "Configure limits for web and API requests."
+msgstr ""
+
+msgid "Configure push mirrors."
+msgstr ""
+
+msgid "Configure storage path settings."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the way a user creates a new account."
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Created"
+msgstr ""
+
+msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
+msgstr ""
+
+msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
+msgstr ""
+
+msgid "ContainerRegistry|How to use the Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Learn more about"
+msgstr ""
+
+msgid "ContainerRegistry|No tags in Container Registry for this container image."
+msgstr ""
+
+msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgstr ""
+
+msgid "ContainerRegistry|Size"
+msgstr ""
+
+msgid "ContainerRegistry|Tag"
+msgstr ""
+
+msgid "ContainerRegistry|Tag ID"
+msgstr ""
+
+msgid "ContainerRegistry|Use different image names"
+msgstr ""
+
+msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
+msgstr ""
+
+msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution guide"
+msgstr ""
+
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "ContributorsPage|%{startDate} – %{endDate}"
+msgstr ""
+
+msgid "ContributorsPage|Building repository graph."
+msgstr ""
+
+msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Control the display of third party offers."
+msgstr ""
+
+msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of repository backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of verification operations for this Geo node"
+msgstr ""
+
+msgid "ConvDev Index"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key to clipboard"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy branch name to clipboard"
+msgstr ""
+
+msgid "Copy command to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Copy file path to clipboard"
+msgstr ""
+
+msgid "Copy incoming email address to clipboard"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
+msgid "Copy reference to clipboard"
+msgstr ""
+
+msgid "Copy secret to clipboard"
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token to clipboard"
+msgstr ""
+
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new branch and merge request"
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create branch"
+msgstr ""
+
+msgid "Create commit"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty repository"
+msgstr ""
+
+msgid "Create epic"
+msgstr ""
+
+msgid "Create file"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created on"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron syntax"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current node"
+msgstr ""
+
+msgid "CurrentUser|Profile"
+msgstr ""
+
+msgid "CurrentUser|Settings"
+msgstr ""
+
+msgid "Custom"
+msgstr ""
+
+msgid "Custom CI config path"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Production"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Default Branch"
+msgstr ""
+
+msgid "Default classification label"
+msgstr ""
+
+msgid "Default: Directly import the Google Code email address or username"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete Package"
+msgstr ""
+
+msgid "Delete Snippet"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete list"
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployKeys|Write access allowed"
+msgstr ""
+
+msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Add a deploy token"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository"
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Copy username to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Deploy Tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|This project has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "DeployTokens|Use this username as a login."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|You are about to revoke"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group Runners"
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "Discard review"
+msgstr ""
+
+msgid "Discover GitLab Geo."
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss Cycle Analytics introduction box"
+msgstr ""
+
+msgid "Dismiss Merge Request promotion"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Each Runner can be in one of the following states:"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Elasticsearch"
+msgstr ""
+
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable SAML authentication for this group"
+msgstr ""
+
+msgid "Enable Sentry for error reporting and logging."
+msgstr ""
+
+msgid "Enable and configure InfluxDB metrics."
+msgstr ""
+
+msgid "Enable and configure Prometheus metrics."
+msgstr ""
+
+msgid "Enable classification control using an external service"
+msgstr ""
+
+msgid "Enable for this project"
+msgstr ""
+
+msgid "Enable group Runners"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable reCAPTCHA or Akismet and set IP limits."
+msgstr ""
+
+msgid "Enable the Performance Bar for a given group."
+msgstr ""
+
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter the issue description"
+msgstr ""
+
+msgid "Enter the issue title"
+msgstr ""
+
+msgid "Enter the merge request description"
+msgstr ""
+
+msgid "Enter the merge request title"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No pod name has been specified"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod logs from"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Read more about environments"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epic will be removed! Are you sure?"
+msgstr ""
+
+msgid "Epics"
+msgstr ""
+
+msgid "Epics Roadmap"
+msgstr ""
+
+msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
+msgstr ""
+
+msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgstr ""
+
+msgid "Epics|How can I solve this?"
+msgstr ""
+
+msgid "Epics|More information"
+msgstr ""
+
+msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+msgstr ""
+
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr ""
+
+msgid "Epics|due"
+msgstr ""
+
+msgid "Epics|start"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Reporting and Logging"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error fetching contributors data."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching usage ping data."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error updating status for all todos."
+msgstr ""
+
+msgid "Error updating todo status."
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "Every day (at 4:00am)"
+msgstr ""
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr ""
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
+msgid "Explore"
+msgstr ""
+
+msgid "Explore GitLab"
+msgstr ""
+
+msgid "Explore Groups"
+msgstr ""
+
+msgid "Explore groups"
+msgstr ""
+
+msgid "Explore projects"
+msgstr ""
+
+msgid "Explore public groups"
+msgstr ""
+
+msgid "External Classification Policy Authorization"
+msgstr ""
+
+msgid "External authentication"
+msgstr ""
+
+msgid "External authorization denied access to this project"
+msgstr ""
+
+msgid "External authorization request timeout"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification Label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to remove issue from board, please try again."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to update issues, please try again."
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fields on this page are now uneditable, you can configure"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Files (%{human_size})"
+msgstr ""
+
+msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
+msgid "Filter by commit message"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Find the downloaded ZIP file and decompress it."
+msgstr ""
+
+msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish review"
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "FirstPushedBy|First"
+msgstr ""
+
+msgid "FirstPushedBy|pushed by"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Follow the steps below to export your Google Code project data."
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Format"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
+msgid "From %{provider_title}"
+msgstr ""
+
+msgid "From Bitbucket"
+msgstr ""
+
+msgid "From Bitbucket Server"
+msgstr ""
+
+msgid "From FogBugz"
+msgstr ""
+
+msgid "From GitLab.com"
+msgstr ""
+
+msgid "From Google Code"
+msgstr ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "From milestones:"
+msgstr ""
+
+msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Nodes"
+msgstr ""
+
+msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is failing or broken."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
+msgstr ""
+
+msgid "GeoNodes|Checksummed"
+msgstr ""
+
+msgid "GeoNodes|Data is out of date from %{timeago}"
+msgstr ""
+
+msgid "GeoNodes|Data replication lag"
+msgstr ""
+
+msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "GeoNodes|Failed"
+msgstr ""
+
+msgid "GeoNodes|Full"
+msgstr ""
+
+msgid "GeoNodes|GitLab version"
+msgstr ""
+
+msgid "GeoNodes|GitLab version does not match the primary node version"
+msgstr ""
+
+msgid "GeoNodes|Health status"
+msgstr ""
+
+msgid "GeoNodes|Last event ID processed by cursor"
+msgstr ""
+
+msgid "GeoNodes|Last event ID seen from primary"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository verification"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki verification"
+msgstr ""
+
+msgid "GeoNodes|Loading nodes"
+msgstr ""
+
+msgid "GeoNodes|Local LFS objects"
+msgstr ""
+
+msgid "GeoNodes|Local attachments"
+msgstr ""
+
+msgid "GeoNodes|Local job artifacts"
+msgstr ""
+
+msgid "GeoNodes|New node"
+msgstr ""
+
+msgid "GeoNodes|Node Authentication was successfully repaired."
+msgstr ""
+
+msgid "GeoNodes|Node was successfully removed."
+msgstr ""
+
+msgid "GeoNodes|Not checksummed"
+msgstr ""
+
+msgid "GeoNodes|Out of sync"
+msgstr ""
+
+msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Replication slot WAL"
+msgstr ""
+
+msgid "GeoNodes|Replication slots"
+msgstr ""
+
+msgid "GeoNodes|Repositories"
+msgstr ""
+
+msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Repositories verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Repository verification progress"
+msgstr ""
+
+msgid "GeoNodes|Selective"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while changing node status"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while fetching nodes"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while removing node"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while repairing node"
+msgstr ""
+
+msgid "GeoNodes|Storage config"
+msgstr ""
+
+msgid "GeoNodes|Sync settings"
+msgstr ""
+
+msgid "GeoNodes|Synced"
+msgstr ""
+
+msgid "GeoNodes|Unused slots"
+msgstr ""
+
+msgid "GeoNodes|Unverified"
+msgstr ""
+
+msgid "GeoNodes|Used slots"
+msgstr ""
+
+msgid "GeoNodes|Verified"
+msgstr ""
+
+msgid "GeoNodes|Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Wiki verification progress"
+msgstr ""
+
+msgid "GeoNodes|Wikis"
+msgstr ""
+
+msgid "GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for forced re-download"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-check"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|All"
+msgstr ""
+
+msgid "Geo|All projects"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|File sync capacity"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Groups to synchronize"
+msgstr ""
+
+msgid "Geo|In sync"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|Not synced yet"
+msgstr ""
+
+msgid "Geo|Pending"
+msgstr ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Recheck"
+msgstr ""
+
+msgid "Geo|Recheck all projects"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Repository sync capacity"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all projects"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Select groups to replicate."
+msgstr ""
+
+msgid "Geo|Shards to synchronize"
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
+msgid "Geo|Unknown state"
+msgstr ""
+
+msgid "Geo|Verification capacity"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|You need a different license to use Geo replication"
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Git"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git strategy for pipelines"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitLab CI Linter has been moved"
+msgstr ""
+
+msgid "GitLab Geo"
+msgstr ""
+
+msgid "GitLab Group Runners can execute code for all the projects in this group."
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab single sign on URL"
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLab’s issue tracker"
+msgstr ""
+
+msgid "Gitaly"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go to"
+msgstr ""
+
+msgid "Go to %{link_to_google_takeout}."
+msgstr ""
+
+msgid "Google Code import"
+msgstr ""
+
+msgid "Google Takeout"
+msgstr ""
+
+msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group CI/CD settings"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group Runners"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group details"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group maintainers can register group runners in the %{link}"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Loading roadmap"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|Until %{dateWord}"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Customize your group badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about badges."
+msgstr ""
+
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+msgstr ""
+
+msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
+msgstr ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Create a project in this group."
+msgstr ""
+
+msgid "GroupsTree|Create a subgroup in this group."
+msgstr ""
+
+msgid "GroupsTree|Edit group"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave this group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Have your users email"
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help page"
+msgstr ""
+
+msgid "Help page text and support page url."
+msgstr ""
+
+msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Hide whitespace changes"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Client side evaluation"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Open in file view"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "Identity provider single sign on URL"
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr ""
+
+msgid "If disabled, the access level will depend on the user's permissions in the project."
+msgstr ""
+
+msgid "If enabled"
+msgstr ""
+
+msgid "If enabled, access to projects will be validated on an external service using their classification label."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you already have files you can push them using the %{link_to_cli} below."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import all compatible projects"
+msgstr ""
+
+msgid "Import all projects"
+msgstr ""
+
+msgid "Import all repositories"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import projects from Google Code"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "Improve Issue boards with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
+msgid "In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "Incompatible Project"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input your repository URL"
+msgstr ""
+
+msgid "Install GitLab Runner"
+msgstr ""
+
+msgid "Install Runner on Kubernetes"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Instance Statistics"
+msgstr ""
+
+msgid "Instance Statistics visibility"
+msgstr ""
+
+msgid "Instance does not support multiple Kubernetes clusters"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations Settings"
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Cycle Analytics"
+msgstr ""
+
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue board focus mode"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Job"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed in"
+msgstr ""
+
+msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration was not removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes configured"
+msgstr ""
+
+msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label lists show all issues with the selected label."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{name}"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
+msgstr ""
+
+msgid "Learn more about Kubernetes"
+msgstr ""
+
+msgid "Learn more about protected branches"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
+msgid "LicenseManagement|Approve license"
+msgstr ""
+
+msgid "LicenseManagement|Approve license?"
+msgstr ""
+
+msgid "LicenseManagement|Approved"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license?"
+msgstr ""
+
+msgid "LicenseManagement|Blacklisted"
+msgstr ""
+
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
+msgid "LicenseManagement|License"
+msgstr ""
+
+msgid "LicenseManagement|License Management"
+msgstr ""
+
+msgid "LicenseManagement|License details"
+msgstr ""
+
+msgid "LicenseManagement|License name"
+msgstr ""
+
+msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
+msgstr ""
+
+msgid "LicenseManagement|Packages"
+msgstr ""
+
+msgid "LicenseManagement|Remove license"
+msgstr ""
+
+msgid "LicenseManagement|Remove license?"
+msgstr ""
+
+msgid "LicenseManagement|Submit"
+msgstr ""
+
+msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
+msgstr ""
+
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseManagement|URL"
+msgstr ""
+
+msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "LinkedIn"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "List Your Gitea Repositories"
+msgstr ""
+
+msgid "List available repositories"
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "List your GitHub repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked to current projects"
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make sure you're logged into the account that owns the projects you'd like to import."
+msgstr ""
+
+msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
+msgstr ""
+
+msgid "Manage Web IDE features"
+msgstr ""
+
+msgid "Manage access"
+msgstr ""
+
+msgid "Manage all notifications"
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a full email address"
+msgstr ""
+
+msgid "Map a Google Code user to a full name"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark todo as done"
+msgstr ""
+
+msgid "Markdown enabled"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
+msgid "Maven Metadata"
+msgstr ""
+
+msgid "Maven package"
+msgstr ""
+
+msgid "Max access level"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Median"
+msgstr ""
+
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Request:"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge requests"
+msgstr ""
+
+msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
+msgid "MergeRequests|Resolve this discussion in a new issue"
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|Toggle comments for this file"
+msgstr ""
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr ""
+
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Influx"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics|Business"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgstr ""
+
+msgid "Metrics|Environment"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgstr ""
+
+msgid "Metrics|Learn about environments"
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|Name"
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|No deployed environments"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|Query"
+msgstr ""
+
+msgid "Metrics|Response"
+msgstr ""
+
+msgid "Metrics|System"
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|Type"
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
+msgid "Milestone"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Mirror a repository"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror user"
+msgstr ""
+
+msgid "Mirrored repositories"
+msgstr ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
+msgid "Modal|Cancel"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More actions"
+msgstr ""
+
+msgid "More info"
+msgstr ""
+
+msgid "More information"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Multiple issue boards"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name your individual key via a title"
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Snippets"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No Label"
+msgstr ""
+
+msgid "No assignee"
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No container images stored for this project. Add one by following the instructions above."
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No issues for the selected time period."
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No merge requests for the selected time period."
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No packages stored for this project."
+msgstr ""
+
+msgid "No prioritised labels with such name or description"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No pushes for the selected time period."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No, directly import the existing email addresses and usernames."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "Not all comments are displayed because you're comparing two versions of the diff."
+msgstr ""
+
+msgid "Not all comments are displayed because you're viewing an old version of the diff."
+msgstr ""
+
+msgid "Not allowed to merge"
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not enough data"
+msgstr ""
+
+msgid "Not now"
+msgstr ""
+
+msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "Only admins"
+msgstr ""
+
+msgid "Only comments from the following commit are shown below"
+msgstr ""
+
+msgid "Only mirror protected branches"
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open in Xcode"
+msgstr ""
+
+msgid "Open projects"
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open source software to collaborate on code"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened MR"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Otherwise it is recommended you start with one of the options below."
+msgstr ""
+
+msgid "Outbound requests"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Package information"
+msgstr ""
+
+msgid "Package was removed"
+msgstr ""
+
+msgid "Packages"
+msgstr ""
+
+msgid "Pages"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
+
+msgid "Path, transfer, remove"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Paused Runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "Per job. If a job passes this threshold, it will be marked as failed"
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, or removing the group."
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline Health"
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline quota"
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines for last month"
+msgstr ""
+
+msgid "Pipelines for last week"
+msgstr ""
+
+msgid "Pipelines for last year"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|CI Lint"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgstr ""
+
+msgid "Pipelines|Get started with Pipelines"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|There are currently no %{scope} pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+msgstr ""
+
+msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Create for"
+msgstr ""
+
+msgid "Pipeline|Create pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Existing branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Search branches"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|all"
+msgstr ""
+
+msgid "Pipeline|success"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Please accept the Terms of Service before continuing."
+msgstr ""
+
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please solve the reCAPTCHA"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences|Navigation theme"
+msgstr ""
+
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Private - Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|Add status emoji"
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
+msgid "Profiles|Clear status"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Delete Account"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Delete your account?"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Website"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project avatar in repository: %{link}"
+msgstr ""
+
+msgid "Project details"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectLifecycle|Stage"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Customize your project badges."
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Learn more about badges."
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
+msgstr ""
+
+msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "PrometheusAlerts|Add alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Edit alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error creating alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error deleting alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error fetching alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error saving alert"
+msgstr ""
+
+msgid "PrometheusAlerts|No alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Operator"
+msgstr ""
+
+msgid "PrometheusAlerts|Threshold"
+msgstr ""
+
+msgid "PrometheusDashboard|Time"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration"
+msgstr ""
+
+msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
+msgstr ""
+
+msgid "PrometheusService|Common metrics"
+msgstr ""
+
+msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
+msgstr ""
+
+msgid "PrometheusService|Custom metrics"
+msgstr ""
+
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr ""
+
+msgid "PrometheusService|Finding custom metrics..."
+msgstr ""
+
+msgid "PrometheusService|Install Prometheus on clusters"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+msgstr ""
+
+msgid "PrometheusService|More information"
+msgstr ""
+
+msgid "PrometheusService|New metric"
+msgstr ""
+
+msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|Time-series monitoring service"
+msgstr ""
+
+msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
+msgstr ""
+
+msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
+msgstr ""
+
+msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote these project milestones into a group milestone."
+msgstr ""
+
+msgid "Promote to Group Milestone"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Environments"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "Protip:"
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Pseudonymizer data collection"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRule|Committer restriction"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
+
+msgid "Readme"
+msgstr ""
+
+msgid "Real-time features"
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Reference:"
+msgstr ""
+
+msgid "Refresh"
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Regenerate key"
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register and see your runners for this group."
+msgstr ""
+
+msgid "Register and see your runners for this project."
+msgstr ""
+
+msgid "Registry"
+msgstr ""
+
+msgid "Related Commits"
+msgstr ""
+
+msgid "Related Deployed Jobs"
+msgstr ""
+
+msgid "Related Issues"
+msgstr ""
+
+msgid "Related Jobs"
+msgstr ""
+
+msgid "Related Merge Requests"
+msgstr ""
+
+msgid "Related Merged Requests"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove Runner"
+msgstr ""
+
+msgid "Remove avatar"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
+msgid "Rename"
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Repair authentication"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{failedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|Class"
+msgstr ""
+
+msgid "Reports|Confidence"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository URL"
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirror"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Requests Profiles"
+msgstr ""
+
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
+msgid "Resolve all discussions in new issue"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve discussion"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal Variables"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
+msgid "Runner token"
+msgstr ""
+
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners API"
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, and even on your local machine."
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|You have used all your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML Single Sign On"
+msgstr ""
+
+msgid "SAML Single Sign On Settings"
+msgstr ""
+
+msgid "SAST"
+msgstr ""
+
+msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save variables"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scoped issue boards"
+msgstr ""
+
+msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or jump to…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in this group"
+msgstr ""
+
+msgid "SearchAutocomplete|in this project"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr ""
+
+msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgstr ""
+
+msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select a group to invite"
+msgstr ""
+
+msgid "Select a namespace to fork the project"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select an existing Kubernetes cluster or create a new one"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select branch/tag"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project and zone to choose machine type"
+msgstr ""
+
+msgid "Select project to choose zone"
+msgstr ""
+
+msgid "Select projects you want to import."
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Select the custom project template source group."
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Selective synchronization"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send usage data"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
+msgstr ""
+
+msgid "Session expiration, projects limit and attachment size."
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set instance-wide template repository"
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Sherlock Transactions"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show latest version of the diff"
+msgstr ""
+
+msgid "Show parent pages"
+msgstr ""
+
+msgid "Show parent subgroups"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|Change weight"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in to %{group_name}"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong when toggling the button"
+msgstr ""
+
+msgid "Something went wrong while closing the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while fetching %{listType} list"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the projects."
+msgstr ""
+
+msgid "Something went wrong while fetching the registry list."
+msgstr ""
+
+msgid "Something went wrong while reopening the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Sorry, no epics matched your search"
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "SortOptions|Access level, ascending"
+msgstr ""
+
+msgid "SortOptions|Access level, descending"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Milestone"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest joined"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source code"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Specific Runners"
+msgstr ""
+
+msgid "Specify an e-mail address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage & Commit"
+msgstr ""
+
+msgid "Stage all changes"
+msgstr ""
+
+msgid "Stage changes"
+msgstr ""
+
+msgid "Staged"
+msgstr ""
+
+msgid "Staged %{type}"
+msgstr ""
+
+msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start the Runner!"
+msgstr ""
+
+msgid "Start your trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Stop environment"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Sync information"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System header and footer:"
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "Tag (%{tag_count})"
+msgid_plural "Tags (%{tag_count})"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release notes"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag."
+msgstr ""
+
+msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Sort by"
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Test SAML SSO"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+msgid "Thanks! Don't show me this again"
+msgstr ""
+
+msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
+msgstr ""
+
+msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr ""
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The deployment of this job to %{environmentLink} did not succeed."
+msgstr ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr ""
+
+msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
+msgstr ""
+
+msgid "The phase of the development lifecycle."
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr ""
+
+msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
+msgstr ""
+
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr ""
+
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
+msgstr ""
+
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The tabs below will be removed in a future version"
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no merge requests to show"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
+
+msgid "There was an error adding a todo."
+msgstr ""
+
+msgid "There was an error deleting the todo."
+msgstr ""
+
+msgid "There was an error loading users activity calendar."
+msgstr ""
+
+msgid "There was an error saving your notification settings."
+msgstr ""
+
+msgid "There was an error subscribing to this label."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "They can be managed using the %{link}."
+msgstr ""
+
+msgid "Third party offers"
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
+msgstr ""
+
+msgid "This application was created by %{link_to_owner}."
+msgstr ""
+
+msgid "This application will be able to:"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This branch has changed since you started editing. Would you like to create a new branch?"
+msgstr ""
+
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This group"
+msgstr ""
+
+msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgstr ""
+
+msgid "This group does not provide any group Runners yet."
+msgstr ""
+
+msgid "This is a confidential issue."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is the author's first Merge Request to this project."
+msgstr ""
+
+msgid "This issue is confidential"
+msgstr ""
+
+msgid "This issue is confidential and locked."
+msgstr ""
+
+msgid "This issue is locked."
+msgstr ""
+
+msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "This job is the most recent deployment to %{link}."
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This option is disabled as you don't have write permissions for the current branch"
+msgstr ""
+
+msgid "This option is disabled while you still have unstaged changes"
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page will be removed in a future release."
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project does not belong to a group and can therefore not make use of group Runners."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "This source diff could not be displayed because it is too large."
+msgstr ""
+
+msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
+msgstr ""
+
+msgid "This will delete the custom metric, Are you sure?"
+msgstr ""
+
+msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time before enforced"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds ago"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip:"
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr ""
+
+msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
+msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr ""
+
+msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
+msgstr ""
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr ""
+
+msgid "To start serving your jobs you can add Runners to your group"
+msgstr ""
+
+msgid "To this GitLab instance"
+msgstr ""
+
+msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
+msgstr ""
+
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
+
+msgid "To widen your search, change or remove filters."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Todo"
+msgstr ""
+
+msgid "Todos"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle discussion"
+msgstr ""
+
+msgid "Toggle file browser"
+msgstr ""
+
+msgid "Toggle navigation"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: OFF"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: ON"
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Time"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track activity with Contribution Analytics."
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trigger"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Turn on Service Desk"
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to save your changes"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unresolve discussion"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
+msgid "Unstage all changes"
+msgstr ""
+
+msgid "Unstage changes"
+msgstr ""
+
+msgid "Unstaged"
+msgstr ""
+
+msgid "Unstaged %{type}"
+msgstr ""
+
+msgid "Unstaged and staged %{type}"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Upgrade your plan to activate Advanced Global Search."
+msgstr ""
+
+msgid "Upgrade your plan to activate Contribution Analytics."
+msgstr ""
+
+msgid "Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Upgrade your plan to activate Issue weight."
+msgstr ""
+
+msgid "Upgrade your plan to improve Issue boards."
+msgstr ""
+
+msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage ping is not enabled"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "Use <code>%{native_redirect_uri}</code> for local tests"
+msgstr ""
+
+msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
+msgstr ""
+
+msgid "Use group milestones to manage issues from multiple projects in the same milestone."
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use the following registration token during setup:"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "Used by members to sign in to your group in GitLab"
+msgstr ""
+
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Variables"
+msgstr ""
+
+msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification information"
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View epics list"
+msgstr ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View group labels"
+msgstr ""
+
+msgid "View issue"
+msgstr ""
+
+msgid "View it on GitLab"
+msgstr ""
+
+msgid "View jobs"
+msgstr ""
+
+msgid "View labels"
+msgstr ""
+
+msgid "View log"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr ""
+
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|It is recommended to install %{markdown} so that GFM features render locally:"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgstr ""
+
+msgid "WikiMarkdownDocs|documentation"
+msgstr ""
+
+msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgstr ""
+
+msgid "WikiNewPagePlaceholder|how-to-setup"
+msgstr ""
+
+msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiNewPageTitle|New Wiki Page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgstr ""
+
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPageConflictMessage|the page"
+msgstr ""
+
+msgid "WikiPageCreate|Create %{page_title}"
+msgstr ""
+
+msgid "WikiPageEdit|Update %{page_title}"
+msgstr ""
+
+msgid "WikiPage|Page slug"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wiki|Create Page"
+msgstr ""
+
+msgid "Wiki|Create page"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|More Pages"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, let me map Google Code users to full names or GitLab users."
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
+msgstr ""
+
+msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You can %{linkStart}view the blob%{linkEnd} instead."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
+msgid "You can only edit files when you are on a branch"
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
+msgstr ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+msgstr ""
+
+msgid "You cannot write to this read-only GitLab instance."
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You must accept our Terms of Service and privacy policy in order to register an account"
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're receiving this email because %{reason}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your Todos"
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your comment will not be visible to the public."
+msgstr ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your projects"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "among other things"
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{namespace} is affected by %{vulnerability}."
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr ""
+
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr ""
+
+msgid "ciReport|(is loading)"
+msgstr ""
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr ""
+
+msgid "ciReport|Class"
+msgstr ""
+
+msgid "ciReport|Code quality"
+msgstr ""
+
+msgid "ciReport|Confidence"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Description"
+msgstr ""
+
+msgid "ciReport|Dismiss vulnerability"
+msgstr ""
+
+msgid "ciReport|Dismissed by"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|File"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Identifiers"
+msgstr ""
+
+msgid "ciReport|Instances"
+msgstr ""
+
+msgid "ciReport|Learn more about interacting with security reports (Alpha)."
+msgstr ""
+
+msgid "ciReport|License management detected %d license for the source branch only"
+msgid_plural "ciReport|License management detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|License management detected %d new license"
+msgid_plural "ciReport|License management detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|License management detected no licenses for the source branch only"
+msgstr ""
+
+msgid "ciReport|License management detected no new licenses"
+msgstr ""
+
+msgid "ciReport|Links"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|Method"
+msgstr ""
+
+msgid "ciReport|Namespace"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No changes to performance metrics"
+msgstr ""
+
+msgid "ciReport|Performance metrics"
+msgstr ""
+
+msgid "ciReport|Revert dismissal"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Severity"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error loading DAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading SAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading container scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error loading dependency scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "ciReport|on pipeline"
+msgstr ""
+
+msgid "command line instructions"
+msgstr ""
+
+msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgstr ""
+
+msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
+msgstr ""
+
+msgid "connecting"
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "customize"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "deploy token"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "here"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "importing"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "issue boards"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "license management"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|Add approval"
+msgstr ""
+
+msgid "mrWidget|Allows commits from members who can merge to the target branch"
+msgstr ""
+
+msgid "mrWidget|An error occured while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Cancel automatic merge"
+msgstr ""
+
+msgid "mrWidget|Check out branch"
+msgstr ""
+
+msgid "mrWidget|Checking ability to merge automatically"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes"
+msgstr ""
+
+msgid "mrWidget|Create an issue to resolve them later"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mentions"
+msgstr ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge request approved"
+msgstr ""
+
+msgid "mrWidget|Merge request approved; you can approve additionally"
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|No Approval required"
+msgstr ""
+
+msgid "mrWidget|No Approval required; you can still approve"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove Source Branch"
+msgstr ""
+
+msgid "mrWidget|Remove source branch"
+msgstr ""
+
+msgid "mrWidget|Remove your approval"
+msgstr ""
+
+msgid "mrWidget|Request to merge"
+msgstr ""
+
+msgid "mrWidget|Requires 1 more approval"
+msgid_plural "mrWidget|Requires %d more approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "mrWidget|Requires 1 more approval by"
+msgid_plural "mrWidget|Requires %d more approvals by"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Set by"
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The changes will be merged into"
+msgstr ""
+
+msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+msgstr ""
+
+msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
+msgstr ""
+
+msgid "mrWidget|The source branch has been removed"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will be removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will not be removed"
+msgstr ""
+
+msgid "mrWidget|There are merge conflicts"
+msgstr ""
+
+msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|This merge request is in the process of being merged"
+msgstr ""
+
+msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr ""
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|You can remove source branch now"
+msgstr ""
+
+msgid "mrWidget|branch does not exist."
+msgstr ""
+
+msgid "mrWidget|command line"
+msgstr ""
+
+msgid "mrWidget|into"
+msgstr ""
+
+msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "notification emails"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "password"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "source"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time spent."
+msgstr ""
+
+msgid "started"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "toggle collapse"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "within %d minute "
+msgid_plural "within %d minutes "
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
diff --git a/locale/sr_SP/gitlab.po b/locale/sr_SP/gitlab.po
new file mode 100644
index 00000000000..48a81762e69
--- /dev/null
+++ b/locale/sr_SP/gitlab.po
@@ -0,0 +1,10061 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: gitlab-ee\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
+"Language-Team: Serbian (Cyrillic)\n"
+"Language: sr_SP\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: crowdin.com\n"
+"X-Crowdin-Project: gitlab-ee\n"
+"X-Crowdin-Language: sr\n"
+"X-Crowdin-File: /master/locale/gitlab.pot\n"
+"PO-Revision-Date: 2018-11-19 17:19\n"
+
+msgid " Status"
+msgstr ""
+
+msgid " and"
+msgstr ""
+
+msgid " degraded on %d point"
+msgid_plural " degraded on %d points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid " improved on %d point"
+msgid_plural " improved on %d points"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d changed file"
+msgid_plural "%d changed files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d commit"
+msgid_plural "%d commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d commit behind"
+msgid_plural "%d commits behind"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d exporter"
+msgid_plural "%d exporters"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d failed test result"
+msgid_plural "%d failed test results"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d fixed test result"
+msgid_plural "%d fixed test results"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d issue"
+msgid_plural "%d issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d layer"
+msgid_plural "%d layers"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d merge request"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d metric"
+msgid_plural "%d metrics"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d staged change"
+msgid_plural "%d staged changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%d unstaged change"
+msgid_plural "%d unstaged changes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%s additional commit has been omitted to prevent performance issues."
+msgid_plural "%s additional commits have been omitted to prevent performance issues."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{actionText} & %{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
+msgid "%{commit_author_link} authored %{commit_timeago}"
+msgstr ""
+
+msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
+msgstr ""
+
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
+msgid "%{count} participant"
+msgid_plural "%{count} participants"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{filePath} deleted"
+msgstr ""
+
+msgid "%{firstLabel} +%{labelCount} more"
+msgstr ""
+
+msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
+msgstr ""
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
+msgid "%{loadingIcon} Started"
+msgstr ""
+
+msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
+msgstr ""
+
+msgid "%{name}'s avatar"
+msgstr ""
+
+msgid "%{nip_domain} can be used as an alternative to a custom domain."
+msgstr ""
+
+msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
+msgstr ""
+
+msgid "%{openOrClose} %{noteable}"
+msgstr ""
+
+msgid "%{percent}%% complete"
+msgstr ""
+
+msgid "%{text} %{files}"
+msgid_plural "%{text} %{files} files"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "%{text} is available"
+msgstr ""
+
+msgid "%{title} changes"
+msgstr ""
+
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
+
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
+
+msgid "+ %{count} more"
+msgstr ""
+
+msgid "+ %{moreCount} more"
+msgstr ""
+
+msgid "- Runner is active and can process any new jobs"
+msgstr ""
+
+msgid "- Runner is paused and will not receive any new jobs"
+msgstr ""
+
+msgid "- show less"
+msgstr ""
+
+msgid "1 %{type} addition"
+msgid_plural "%{count} %{type} additions"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 %{type} modification"
+msgid_plural "%{count} %{type} modifications"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 closed issue"
+msgid_plural "%d closed issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 closed merge request"
+msgid_plural "%d closed merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 group"
+msgid_plural "%d groups"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 merged merge request"
+msgid_plural "%d merged merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 open issue"
+msgid_plural "%d open issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 open merge request"
+msgid_plural "%d open merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 pipeline"
+msgid_plural "%d pipelines"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 role"
+msgid_plural "%d roles"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1 user"
+msgid_plural "%d users"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "1st contribution!"
+msgstr ""
+
+msgid "2FA enabled"
+msgstr ""
+
+msgid "403|Please contact your GitLab administrator to get the permission."
+msgstr ""
+
+msgid "403|You don't have the permission to access this page."
+msgstr ""
+
+msgid "404|Make sure the address is correct and the page hasn't moved."
+msgstr ""
+
+msgid "404|Page Not Found"
+msgstr ""
+
+msgid "404|Please contact your GitLab administrator if you think this is a mistake."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
+msgstr ""
+
+msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
+msgstr ""
+
+msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
+msgstr ""
+
+msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
+msgstr ""
+
+msgid "<strong>%{group_name}</strong> group members"
+msgstr ""
+
+msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong> commits by <strong>%{people}</strong> contributors."
+msgstr ""
+
+msgid "<strong>Removes</strong> source branch"
+msgstr ""
+
+msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
+msgstr ""
+
+msgid "A collection of graphs regarding Continuous Integration"
+msgstr ""
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
+msgid "A new branch will be created in your fork and a new merge request will be started."
+msgstr ""
+
+msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
+msgstr ""
+
+msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
+msgstr ""
+
+msgid "A user with write access to the source branch selected this option"
+msgstr ""
+
+msgid "About GitLab"
+msgstr ""
+
+msgid "About GitLab CE"
+msgstr ""
+
+msgid "About auto deploy"
+msgstr ""
+
+msgid "About this feature"
+msgstr ""
+
+msgid "Abuse Reports"
+msgstr ""
+
+msgid "Abuse reports"
+msgstr ""
+
+msgid "Accept terms"
+msgstr ""
+
+msgid "Accepted MR"
+msgstr ""
+
+msgid "Access Tokens"
+msgstr ""
+
+msgid "Access denied! Please verify you can add deploy keys to this repository."
+msgstr ""
+
+msgid "Access expiration date"
+msgstr ""
+
+msgid "Access to '%{classification_label}' not allowed"
+msgstr ""
+
+msgid "Account"
+msgstr ""
+
+msgid "Account and limit"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Active Sessions"
+msgstr ""
+
+msgid "Activity"
+msgstr ""
+
+msgid "Add"
+msgstr ""
+
+msgid "Add Changelog"
+msgstr ""
+
+msgid "Add Contribution guide"
+msgstr ""
+
+msgid "Add Group Webhooks and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Add Jaeger URL"
+msgstr ""
+
+msgid "Add Kubernetes cluster"
+msgstr ""
+
+msgid "Add Readme"
+msgstr ""
+
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
+msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
+msgstr ""
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
+msgid "Add new application"
+msgstr ""
+
+msgid "Add new directory"
+msgstr ""
+
+msgid "Add projects"
+msgstr ""
+
+msgid "Add reaction"
+msgstr ""
+
+msgid "Add to review"
+msgstr ""
+
+msgid "Add todo"
+msgstr ""
+
+msgid "Add user(s) to the group:"
+msgstr ""
+
+msgid "Add users to group"
+msgstr ""
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
+msgid "Additional text"
+msgstr ""
+
+msgid "Admin Area"
+msgstr ""
+
+msgid "Admin Overview"
+msgstr ""
+
+msgid "Admin area"
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminArea|Stop all jobs"
+msgstr ""
+
+msgid "AdminArea|Stop all jobs?"
+msgstr ""
+
+msgid "AdminArea|Stop jobs"
+msgstr ""
+
+msgid "AdminArea|Stopping jobs failed"
+msgstr ""
+
+msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
+msgstr ""
+
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "AdminProjects|Delete"
+msgstr ""
+
+msgid "AdminProjects|Delete Project %{projectName}?"
+msgstr ""
+
+msgid "AdminProjects|Delete project"
+msgstr ""
+
+msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "AdminUsers|Block user"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username} and contributions?"
+msgstr ""
+
+msgid "AdminUsers|Delete User %{username}?"
+msgstr ""
+
+msgid "AdminUsers|Delete user"
+msgstr ""
+
+msgid "AdminUsers|Delete user and contributions"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{projectName}"
+msgstr ""
+
+msgid "AdminUsers|To confirm, type %{username}"
+msgstr ""
+
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
+
+msgid "Advanced settings"
+msgstr ""
+
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "All"
+msgstr ""
+
+msgid "All changes are committed"
+msgstr ""
+
+msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
+msgstr ""
+
+msgid "All users"
+msgstr ""
+
+msgid "Allow commits from members who can merge to the target branch."
+msgstr ""
+
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
+msgid "Allow public access to pipelines and job details, including output logs and artifacts"
+msgstr ""
+
+msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
+msgstr ""
+
+msgid "Allow requests to the local network from hooks and services."
+msgstr ""
+
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
+msgid "Allows you to add and manage Kubernetes clusters."
+msgstr ""
+
+msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
+msgstr ""
+
+msgid "Also called \"Relying party service URL\" or \"Reply URL\""
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "An application called %{link_to_client} is requesting access to your GitLab account."
+msgstr ""
+
+msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
+msgstr ""
+
+msgid "An error accured whilst committing your changes."
+msgstr ""
+
+msgid "An error has occurred"
+msgstr ""
+
+msgid "An error occured creating the new branch."
+msgstr ""
+
+msgid "An error occured whilst fetching the job trace."
+msgstr ""
+
+msgid "An error occured whilst fetching the latest pipeline."
+msgstr ""
+
+msgid "An error occured whilst loading all the files."
+msgstr ""
+
+msgid "An error occured whilst loading the file content."
+msgstr ""
+
+msgid "An error occured whilst loading the file."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request changes."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request version data."
+msgstr ""
+
+msgid "An error occured whilst loading the merge request."
+msgstr ""
+
+msgid "An error occured whilst loading the pipelines jobs."
+msgstr ""
+
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
+msgid "An error occurred previewing the blob"
+msgstr ""
+
+msgid "An error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "An error occurred when updating the issue weight"
+msgstr ""
+
+msgid "An error occurred while adding approver"
+msgstr ""
+
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
+msgid "An error occurred while detecting host keys"
+msgstr ""
+
+msgid "An error occurred while dismissing the alert. Refresh the page and try again."
+msgstr ""
+
+msgid "An error occurred while dismissing the feature highlight. Refresh the page and try dismissing again."
+msgstr ""
+
+msgid "An error occurred while fetching markdown preview"
+msgstr ""
+
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
+msgid "An error occurred while fetching sidebar data"
+msgstr ""
+
+msgid "An error occurred while fetching stages."
+msgstr ""
+
+msgid "An error occurred while fetching the job log."
+msgstr ""
+
+msgid "An error occurred while fetching the job."
+msgstr ""
+
+msgid "An error occurred while fetching the jobs."
+msgstr ""
+
+msgid "An error occurred while fetching the pipeline."
+msgstr ""
+
+msgid "An error occurred while getting projects"
+msgstr ""
+
+msgid "An error occurred while importing project: %{details}"
+msgstr ""
+
+msgid "An error occurred while initializing path locks"
+msgstr ""
+
+msgid "An error occurred while loading chart data"
+msgstr ""
+
+msgid "An error occurred while loading commit signatures"
+msgstr ""
+
+msgid "An error occurred while loading diff"
+msgstr ""
+
+msgid "An error occurred while loading filenames"
+msgstr ""
+
+msgid "An error occurred while loading the file"
+msgstr ""
+
+msgid "An error occurred while making the request."
+msgstr ""
+
+msgid "An error occurred while removing approver"
+msgstr ""
+
+msgid "An error occurred while rendering KaTeX"
+msgstr ""
+
+msgid "An error occurred while rendering preview broadcast message"
+msgstr ""
+
+msgid "An error occurred while retrieving calendar activity"
+msgstr ""
+
+msgid "An error occurred while retrieving diff"
+msgstr ""
+
+msgid "An error occurred while saving LDAP override status. Please try again."
+msgstr ""
+
+msgid "An error occurred while saving assignees"
+msgstr ""
+
+msgid "An error occurred while subscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while unsubscribing to notifications."
+msgstr ""
+
+msgid "An error occurred while updating the comment"
+msgstr ""
+
+msgid "An error occurred while validating username"
+msgstr ""
+
+msgid "An error occurred. Please try again."
+msgstr ""
+
+msgid "Analytics"
+msgstr ""
+
+msgid "Anonymous"
+msgstr ""
+
+msgid "Anti-spam verification"
+msgstr ""
+
+msgid "Any"
+msgstr ""
+
+msgid "Any Label"
+msgstr ""
+
+msgid "Appearance"
+msgstr ""
+
+msgid "Application"
+msgstr ""
+
+msgid "Application ID"
+msgstr ""
+
+msgid "Application: %{name}"
+msgstr ""
+
+msgid "Applications"
+msgstr ""
+
+msgid "Apr"
+msgstr ""
+
+msgid "April"
+msgstr ""
+
+msgid "Archived project! Repository and other project resources are read-only"
+msgstr ""
+
+msgid "Archived projects"
+msgstr ""
+
+msgid "Are you sure you want to delete this pipeline schedule?"
+msgstr ""
+
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr ""
+
+msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
+msgstr ""
+
+msgid "Are you sure you want to remove %{group_name}?"
+msgstr ""
+
+msgid "Are you sure you want to remove this identity?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Are you sure you want to unlock %{path_lock_path}?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
+msgid "Artifact ID"
+msgstr ""
+
+msgid "Artifacts"
+msgstr ""
+
+msgid "Ascending"
+msgstr ""
+
+msgid "Ask your group maintainer to set up a group Runner."
+msgstr ""
+
+msgid "Assertion consumer service URL"
+msgstr ""
+
+msgid "Assign custom color like #FF0000"
+msgstr ""
+
+msgid "Assign labels"
+msgstr ""
+
+msgid "Assign milestone"
+msgstr ""
+
+msgid "Assign to"
+msgstr ""
+
+msgid "Assigned Issues"
+msgstr ""
+
+msgid "Assigned Merge Requests"
+msgstr ""
+
+msgid "Assigned to :name"
+msgstr ""
+
+msgid "Assigned to me"
+msgstr ""
+
+msgid "Assignee"
+msgstr ""
+
+msgid "Assignee lists not available with your current license"
+msgstr ""
+
+msgid "Assignee lists show all issues assigned to the selected user."
+msgstr ""
+
+msgid "Assignee(s)"
+msgstr ""
+
+msgid "Attach a file by drag &amp; drop or %{upload_link}"
+msgstr ""
+
+msgid "Audit Events"
+msgstr ""
+
+msgid "Aug"
+msgstr ""
+
+msgid "August"
+msgstr ""
+
+msgid "Authentication Log"
+msgstr ""
+
+msgid "Authentication log"
+msgstr ""
+
+msgid "Authentication method"
+msgstr ""
+
+msgid "Author"
+msgstr ""
+
+msgid "Authorization code:"
+msgstr ""
+
+msgid "Authorization was granted by entering your username and password in the application."
+msgstr ""
+
+msgid "Authorize"
+msgstr ""
+
+msgid "Authorize %{link_to_client} to use your account?"
+msgstr ""
+
+msgid "Authorized At"
+msgstr ""
+
+msgid "Authorized applications (%{size})"
+msgstr ""
+
+msgid "Authors: %{authors}"
+msgstr ""
+
+msgid "Auto DevOps"
+msgstr ""
+
+msgid "Auto DevOps enabled"
+msgstr ""
+
+msgid "Auto DevOps, runners and job artifacts"
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name and a %{kubernetes} to work correctly."
+msgstr ""
+
+msgid "Auto Review Apps and Auto Deploy need a domain name to work correctly."
+msgstr ""
+
+msgid "Auto-cancel redundant, pending pipelines"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps"
+msgstr ""
+
+msgid "AutoDevOps|Auto DevOps documentation"
+msgstr ""
+
+msgid "AutoDevOps|Enable in settings"
+msgstr ""
+
+msgid "AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration."
+msgstr ""
+
+msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
+msgstr ""
+
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
+msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
+msgstr ""
+
+msgid "AutoDevOps|add a Kubernetes cluster"
+msgstr ""
+
+msgid "AutoDevOps|enable Auto DevOps"
+msgstr ""
+
+msgid "Automatically marked as default internal user"
+msgstr ""
+
+msgid "Available"
+msgstr ""
+
+msgid "Available group Runners : %{runners}"
+msgstr ""
+
+msgid "Available group Runners : %{runners}."
+msgstr ""
+
+msgid "Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Average per day: %{average}"
+msgstr ""
+
+msgid "Background Color"
+msgstr ""
+
+msgid "Background Jobs"
+msgstr ""
+
+msgid "Background color"
+msgstr ""
+
+msgid "Badges"
+msgstr ""
+
+msgid "Badges|A new badge was added."
+msgstr ""
+
+msgid "Badges|Add badge"
+msgstr ""
+
+msgid "Badges|Adding the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|Badge image URL"
+msgstr ""
+
+msgid "Badges|Badge image preview"
+msgstr ""
+
+msgid "Badges|Delete badge"
+msgstr ""
+
+msgid "Badges|Delete badge?"
+msgstr ""
+
+msgid "Badges|Deleting the badge failed, please try again."
+msgstr ""
+
+msgid "Badges|Group Badge"
+msgstr ""
+
+msgid "Badges|Link"
+msgstr ""
+
+msgid "Badges|No badge image"
+msgstr ""
+
+msgid "Badges|No image to preview"
+msgstr ""
+
+msgid "Badges|Please fill in a valid URL"
+msgstr ""
+
+msgid "Badges|Project Badge"
+msgstr ""
+
+msgid "Badges|Reload badge image"
+msgstr ""
+
+msgid "Badges|Save changes"
+msgstr ""
+
+msgid "Badges|Saving the badge failed, please check the entered URLs and try again."
+msgstr ""
+
+msgid "Badges|The %{docsLinkStart}variables%{docsLinkEnd} GitLab supports: %{placeholders}"
+msgstr ""
+
+msgid "Badges|The badge was deleted."
+msgstr ""
+
+msgid "Badges|The badge was saved."
+msgstr ""
+
+msgid "Badges|This group has no badges"
+msgstr ""
+
+msgid "Badges|This project has no badges"
+msgstr ""
+
+msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
+msgstr ""
+
+msgid "Badges|Your badges"
+msgstr ""
+
+msgid "Badges|e.g. %{exampleUrl}"
+msgstr ""
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
+msgid "Begin with the selected commit"
+msgstr ""
+
+msgid "Below are examples of regex for existing tools:"
+msgstr ""
+
+msgid "Below you will find all the groups that are public."
+msgstr ""
+
+msgid "Billing"
+msgstr ""
+
+msgid "BillingPlans|%{group_name} is currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Automatic downgrade and upgrade to some plans is currently not available."
+msgstr ""
+
+msgid "BillingPlans|Current plan"
+msgstr ""
+
+msgid "BillingPlans|Customer Support"
+msgstr ""
+
+msgid "BillingPlans|Downgrade"
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
+msgstr ""
+
+msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
+msgstr ""
+
+msgid "BillingPlans|Manage plan"
+msgstr ""
+
+msgid "BillingPlans|Please contact %{customer_support_link} in that case."
+msgstr ""
+
+msgid "BillingPlans|See all %{plan_name} features"
+msgstr ""
+
+msgid "BillingPlans|This group uses the plan associated with its parent group."
+msgstr ""
+
+msgid "BillingPlans|To manage the plan for this group, visit the billing section of %{parent_billing_page_link}."
+msgstr ""
+
+msgid "BillingPlans|Upgrade"
+msgstr ""
+
+msgid "BillingPlans|You are currently on the %{plan_link} plan."
+msgstr ""
+
+msgid "BillingPlans|Your GitLab.com trial expired on %{expiration_date}. %{learn_more_text}"
+msgstr ""
+
+msgid "BillingPlans|Your Gold trial will <strong>expire after %{expiration_date}</strong>. You can learn more about GitLab.com Gold by reading about our %{features_link}."
+msgstr ""
+
+msgid "BillingPlans|features"
+msgstr ""
+
+msgid "BillingPlans|frequently asked questions"
+msgstr ""
+
+msgid "BillingPlans|monthly"
+msgstr ""
+
+msgid "BillingPlans|paid annually at %{price_per_year}"
+msgstr ""
+
+msgid "BillingPlans|per user"
+msgstr ""
+
+msgid "Bitbucket Server Import"
+msgstr ""
+
+msgid "Bitbucket import"
+msgstr ""
+
+msgid "Blog"
+msgstr ""
+
+msgid "Boards"
+msgstr ""
+
+msgid "Branch %{branchName} was not found in this project's repository."
+msgstr ""
+
+msgid "Branch (%{branch_count})"
+msgid_plural "Branches (%{branch_count})"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Branch <strong>%{branch_name}</strong> was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
+msgstr ""
+
+msgid "Branch has changed"
+msgstr ""
+
+msgid "Branch is already taken"
+msgstr ""
+
+msgid "Branch name"
+msgstr ""
+
+msgid "BranchSwitcherPlaceholder|Search branches"
+msgstr ""
+
+msgid "BranchSwitcherTitle|Switch branch"
+msgstr ""
+
+msgid "Branches"
+msgstr ""
+
+msgid "Branches|Active"
+msgstr ""
+
+msgid "Branches|Active branches"
+msgstr ""
+
+msgid "Branches|All"
+msgstr ""
+
+msgid "Branches|Cant find HEAD commit for this branch"
+msgstr ""
+
+msgid "Branches|Compare"
+msgstr ""
+
+msgid "Branches|Delete all branches that are merged into '%{default_branch}'"
+msgstr ""
+
+msgid "Branches|Delete branch"
+msgstr ""
+
+msgid "Branches|Delete merged branches"
+msgstr ""
+
+msgid "Branches|Delete protected branch"
+msgstr ""
+
+msgid "Branches|Delete protected branch '%{branch_name}'?"
+msgstr ""
+
+msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Deleting the merged branches cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "Branches|Filter by branch name"
+msgstr ""
+
+msgid "Branches|Merged into %{default_branch}"
+msgstr ""
+
+msgid "Branches|New branch"
+msgstr ""
+
+msgid "Branches|No branches to show"
+msgstr ""
+
+msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Branches|Only a project maintainer or owner can delete a protected branch"
+msgstr ""
+
+msgid "Branches|Overview"
+msgstr ""
+
+msgid "Branches|Protected branches can be managed in %{project_settings_link}."
+msgstr ""
+
+msgid "Branches|Show active branches"
+msgstr ""
+
+msgid "Branches|Show all branches"
+msgstr ""
+
+msgid "Branches|Show more active branches"
+msgstr ""
+
+msgid "Branches|Show more stale branches"
+msgstr ""
+
+msgid "Branches|Show overview of the branches"
+msgstr ""
+
+msgid "Branches|Show stale branches"
+msgstr ""
+
+msgid "Branches|Sort by"
+msgstr ""
+
+msgid "Branches|Stale"
+msgstr ""
+
+msgid "Branches|Stale branches"
+msgstr ""
+
+msgid "Branches|The branch could not be updated automatically because it has diverged from its upstream counterpart."
+msgstr ""
+
+msgid "Branches|The default branch cannot be deleted"
+msgstr ""
+
+msgid "Branches|This branch hasn’t been merged into %{default_branch}."
+msgstr ""
+
+msgid "Branches|To avoid data loss, consider merging this branch before deleting it."
+msgstr ""
+
+msgid "Branches|To confirm, type %{branch_name_confirmation}:"
+msgstr ""
+
+msgid "Branches|To discard the local changes and overwrite the branch with the upstream version, delete it here and choose 'Update Now' above."
+msgstr ""
+
+msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
+msgstr ""
+
+msgid "Branches|diverged from upstream"
+msgstr ""
+
+msgid "Branches|merged"
+msgstr ""
+
+msgid "Branches|project settings"
+msgstr ""
+
+msgid "Branches|protected"
+msgstr ""
+
+msgid "Browse Directory"
+msgstr ""
+
+msgid "Browse File"
+msgstr ""
+
+msgid "Browse Files"
+msgstr ""
+
+msgid "Browse files"
+msgstr ""
+
+msgid "Built-In"
+msgstr ""
+
+msgid "Business metrics (Custom)"
+msgstr ""
+
+msgid "ByAuthor|by"
+msgstr ""
+
+msgid "CI / CD"
+msgstr ""
+
+msgid "CI / CD Settings"
+msgstr ""
+
+msgid "CI will run using the credentials assigned above."
+msgstr ""
+
+msgid "CI/CD"
+msgstr ""
+
+msgid "CI/CD configuration"
+msgstr ""
+
+msgid "CI/CD for external repo"
+msgstr ""
+
+msgid "CI/CD settings"
+msgstr ""
+
+msgid "CICD|Auto DevOps"
+msgstr ""
+
+msgid "CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration."
+msgstr ""
+
+msgid "CICD|Automatic deployment to staging, manual deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production"
+msgstr ""
+
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr ""
+
+msgid "CICD|Deployment strategy"
+msgstr ""
+
+msgid "CICD|Deployment strategy needs a domain name to work correctly."
+msgstr ""
+
+msgid "CICD|Do not set up a domain here if you are setting up multiple Kubernetes clusters with Auto DevOps."
+msgstr ""
+
+msgid "CICD|Jobs"
+msgstr ""
+
+msgid "CICD|Learn more about Auto DevOps"
+msgstr ""
+
+msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
+msgstr ""
+
+msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
+msgstr ""
+
+msgid "CICD|instance enabled"
+msgstr ""
+
+msgid "Callback URL"
+msgstr ""
+
+msgid "Can't find HEAD commit for this branch"
+msgstr ""
+
+msgid "Cancel"
+msgstr ""
+
+msgid "Cancel this job"
+msgstr ""
+
+msgid "Cannot be merged automatically"
+msgstr ""
+
+msgid "Cannot modify managed Kubernetes cluster"
+msgstr ""
+
+msgid "Certificate fingerprint"
+msgstr ""
+
+msgid "Change Weight"
+msgstr ""
+
+msgid "Change template"
+msgstr ""
+
+msgid "Change this value to influence how frequently the GitLab UI polls for updates."
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Pick into branch"
+msgstr ""
+
+msgid "ChangeTypeActionLabel|Revert in branch"
+msgstr ""
+
+msgid "ChangeTypeAction|Cherry-pick"
+msgstr ""
+
+msgid "ChangeTypeAction|Revert"
+msgstr ""
+
+msgid "ChangeTypeAction|This will create a new commit in order to revert the existing changes."
+msgstr ""
+
+msgid "Changelog"
+msgstr ""
+
+msgid "Changes are shown as if the <b>source</b> revision was being merged into the <b>target</b> revision."
+msgstr ""
+
+msgid "Charts"
+msgstr ""
+
+msgid "Chat"
+msgstr ""
+
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
+
+msgid "Checking %{text} availability…"
+msgstr ""
+
+msgid "Checking branch availability..."
+msgstr ""
+
+msgid "Cherry-pick this commit"
+msgstr ""
+
+msgid "Cherry-pick this merge request"
+msgstr ""
+
+msgid "Choose <strong>Create archive</strong> and wait for archiving to complete."
+msgstr ""
+
+msgid "Choose <strong>Next</strong> at the bottom of the page."
+msgstr ""
+
+msgid "Choose File ..."
+msgstr ""
+
+msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
+msgstr ""
+
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
+msgid "Choose any color."
+msgstr ""
+
+msgid "Choose between <code>clone</code> or <code>fetch</code> to get the recent application code"
+msgstr ""
+
+msgid "Choose file..."
+msgstr ""
+
+msgid "Choose the top-level group for your repository imports."
+msgstr ""
+
+msgid "Choose which groups you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "Choose which repositories you want to connect and run CI/CD pipelines."
+msgstr ""
+
+msgid "Choose which repositories you want to import."
+msgstr ""
+
+msgid "Choose which shards you wish to synchronize to this secondary node."
+msgstr ""
+
+msgid "CiStatusLabel|canceled"
+msgstr ""
+
+msgid "CiStatusLabel|created"
+msgstr ""
+
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
+msgid "CiStatusLabel|failed"
+msgstr ""
+
+msgid "CiStatusLabel|manual action"
+msgstr ""
+
+msgid "CiStatusLabel|passed"
+msgstr ""
+
+msgid "CiStatusLabel|passed with warnings"
+msgstr ""
+
+msgid "CiStatusLabel|pending"
+msgstr ""
+
+msgid "CiStatusLabel|skipped"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
+msgid "CiStatusLabel|waiting for manual action"
+msgstr ""
+
+msgid "CiStatusText|blocked"
+msgstr ""
+
+msgid "CiStatusText|canceled"
+msgstr ""
+
+msgid "CiStatusText|created"
+msgstr ""
+
+msgid "CiStatusText|delayed"
+msgstr ""
+
+msgid "CiStatusText|failed"
+msgstr ""
+
+msgid "CiStatusText|manual"
+msgstr ""
+
+msgid "CiStatusText|passed"
+msgstr ""
+
+msgid "CiStatusText|pending"
+msgstr ""
+
+msgid "CiStatusText|skipped"
+msgstr ""
+
+msgid "CiStatus|running"
+msgstr ""
+
+msgid "CiVariables|Input variable key"
+msgstr ""
+
+msgid "CiVariables|Input variable value"
+msgstr ""
+
+msgid "CiVariables|Remove variable row"
+msgstr ""
+
+msgid "CiVariable|* (All environments)"
+msgstr ""
+
+msgid "CiVariable|All environments"
+msgstr ""
+
+msgid "CiVariable|Create wildcard"
+msgstr ""
+
+msgid "CiVariable|Error occured while saving variables"
+msgstr ""
+
+msgid "CiVariable|New environment"
+msgstr ""
+
+msgid "CiVariable|Protected"
+msgstr ""
+
+msgid "CiVariable|Search environments"
+msgstr ""
+
+msgid "CiVariable|Toggle protected"
+msgstr ""
+
+msgid "CiVariable|Validation failed"
+msgstr ""
+
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgstr ""
+
+msgid "Clear search"
+msgstr ""
+
+msgid "Clear search input"
+msgstr ""
+
+msgid "Click any <strong>project name</strong> in the project list below to navigate to the project milestone."
+msgstr ""
+
+msgid "Click the <strong>Download</strong> button and wait for downloading to complete."
+msgstr ""
+
+msgid "Click the <strong>Promote</strong> button in the top right corner to promote it to a group milestone."
+msgstr ""
+
+msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
+msgstr ""
+
+msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
+msgstr ""
+
+msgid "Click to expand it."
+msgstr ""
+
+msgid "Click to expand text"
+msgstr ""
+
+msgid "Client authentication certificate"
+msgstr ""
+
+msgid "Client authentication key"
+msgstr ""
+
+msgid "Client authentication key password"
+msgstr ""
+
+msgid "Clients"
+msgstr ""
+
+msgid "Clone repository"
+msgstr ""
+
+msgid "Close"
+msgstr ""
+
+msgid "Close epic"
+msgstr ""
+
+msgid "Closed"
+msgstr ""
+
+msgid "Closed issues"
+msgstr ""
+
+msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
+msgstr ""
+
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
+msgid "ClusterIntegration|API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Add Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
+msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
+msgstr ""
+
+msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch your projects: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
+msgstr ""
+
+msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
+msgstr ""
+
+msgid "ClusterIntegration|Applications"
+msgstr ""
+
+msgid "ClusterIntegration|Are you sure you want to remove this Kubernetes cluster's integration? This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
+msgstr ""
+
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
+
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Copy API URL"
+msgstr ""
+
+msgid "ClusterIntegration|Copy CA Certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Jupyter Hostname to clipboard"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Copy Token"
+msgstr ""
+
+msgid "ClusterIntegration|Create Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Did you know?"
+msgstr ""
+
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
+msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Environment scope"
+msgstr ""
+
+msgid "ClusterIntegration|Every new Google Cloud Platform (GCP) account receives $300 in credit upon %{sign_up_link}. In partnership with Google, GitLab is able to offer an additional $200 for both new and existing GCP accounts to get started with GitLab's Google Kubernetes Engine Integration."
+msgstr ""
+
+msgid "ClusterIntegration|Fetching machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching projects"
+msgstr ""
+
+msgid "ClusterIntegration|Fetching zones"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Integration"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner"
+msgstr ""
+
+msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
+msgstr ""
+
+msgid "ClusterIntegration|Google Cloud Platform project"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Google Kubernetes Engine project"
+msgstr ""
+
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Helm Tiller"
+msgstr ""
+
+msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
+msgstr ""
+
+msgid "ClusterIntegration|Hide"
+msgstr ""
+
+msgid "ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{help_link_start}read this first%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|In order to show the health of the cluster, we'll need to provision your cluster with Prometheus to collect the required data."
+msgstr ""
+
+msgid "ClusterIntegration|Ingress"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress IP Address"
+msgstr ""
+
+msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
+msgstr ""
+
+msgid "ClusterIntegration|Install"
+msgstr ""
+
+msgid "ClusterIntegration|Install Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Installed"
+msgstr ""
+
+msgid "ClusterIntegration|Installing"
+msgstr ""
+
+msgid "ClusterIntegration|Integrate Kubernetes cluster automation"
+msgstr ""
+
+msgid "ClusterIntegration|Integration status"
+msgstr ""
+
+msgid "ClusterIntegration|Jupyter Hostname"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub"
+msgstr ""
+
+msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
+msgstr ""
+
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster health"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster name"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
+msgstr ""
+
+msgid "ClusterIntegration|Manage"
+msgstr ""
+
+msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}"
+msgstr ""
+
+msgid "ClusterIntegration|More information"
+msgstr ""
+
+msgid "ClusterIntegration|No machine types matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No projects found"
+msgstr ""
+
+msgid "ClusterIntegration|No projects matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|No zones matched your search"
+msgstr ""
+
+msgid "ClusterIntegration|Note:"
+msgstr ""
+
+msgid "ClusterIntegration|Number of nodes"
+msgstr ""
+
+msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{link_to_help_page} on Kubernetes"
+msgstr ""
+
+msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
+msgstr ""
+
+msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
+msgstr ""
+
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace"
+msgstr ""
+
+msgid "ClusterIntegration|Project namespace (optional, unique)"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus"
+msgstr ""
+
+msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
+msgstr ""
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
+msgstr ""
+
+msgid "ClusterIntegration|Remove Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove integration"
+msgstr ""
+
+msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from this project. This will not delete your actual Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
+msgstr ""
+
+msgid "ClusterIntegration|Request to begin installing failed"
+msgstr ""
+
+msgid "ClusterIntegration|Save changes"
+msgstr ""
+
+msgid "ClusterIntegration|Search machine types"
+msgstr ""
+
+msgid "ClusterIntegration|Search projects"
+msgstr ""
+
+msgid "ClusterIntegration|Search zones"
+msgstr ""
+
+msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Select machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project"
+msgstr ""
+
+msgid "ClusterIntegration|Select project and zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Select project to choose zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone"
+msgstr ""
+
+msgid "ClusterIntegration|Select zone to choose machine type"
+msgstr ""
+
+msgid "ClusterIntegration|Service token"
+msgstr ""
+
+msgid "ClusterIntegration|Show"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong on our end."
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cluster on Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|Something went wrong while installing %{title}"
+msgstr ""
+
+msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
+msgstr ""
+
+msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
+msgstr ""
+
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
+
+msgid "ClusterIntegration|Toggle Kubernetes cluster"
+msgstr ""
+
+msgid "ClusterIntegration|Token"
+msgstr ""
+
+msgid "ClusterIntegration|Validating project billing status"
+msgstr ""
+
+msgid "ClusterIntegration|We could not verify that one of your projects on GCP has billing enabled. Please try again."
+msgstr ""
+
+msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
+
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
+msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
+msgstr ""
+
+msgid "ClusterIntegration|Zone"
+msgstr ""
+
+msgid "ClusterIntegration|access to Google Kubernetes Engine"
+msgstr ""
+
+msgid "ClusterIntegration|check the pricing here"
+msgstr ""
+
+msgid "ClusterIntegration|documentation"
+msgstr ""
+
+msgid "ClusterIntegration|help page"
+msgstr ""
+
+msgid "ClusterIntegration|meets the requirements"
+msgstr ""
+
+msgid "ClusterIntegration|properly configured"
+msgstr ""
+
+msgid "ClusterIntegration|sign up"
+msgstr ""
+
+msgid "Code owners"
+msgstr ""
+
+msgid "Cohorts"
+msgstr ""
+
+msgid "Collapse"
+msgstr ""
+
+msgid "Collapse sidebar"
+msgstr ""
+
+msgid "Comment"
+msgstr ""
+
+msgid "Comment & resolve discussion"
+msgstr ""
+
+msgid "Comment & unresolve discussion"
+msgstr ""
+
+msgid "Comment form position"
+msgstr ""
+
+msgid "Comments"
+msgstr ""
+
+msgid "Commit"
+msgid_plural "Commits"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Commit (%{commit_count})"
+msgid_plural "Commits (%{commit_count})"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Commit Message"
+msgstr ""
+
+msgid "Commit duration in minutes for last 30 commits"
+msgstr ""
+
+msgid "Commit message"
+msgstr ""
+
+msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
+msgstr ""
+
+msgid "Commit to %{branchName} branch"
+msgstr ""
+
+msgid "CommitBoxTitle|Commit"
+msgstr ""
+
+msgid "CommitMessage|Add %{file_name}"
+msgstr ""
+
+msgid "CommitWidget|authored"
+msgstr ""
+
+msgid "Commits"
+msgstr ""
+
+msgid "Commits feed"
+msgstr ""
+
+msgid "Commits per day hour (UTC)"
+msgstr ""
+
+msgid "Commits per day of month"
+msgstr ""
+
+msgid "Commits per weekday"
+msgstr ""
+
+msgid "Commits|An error occurred while fetching merge requests data."
+msgstr ""
+
+msgid "Commits|Commit: %{commitText}"
+msgstr ""
+
+msgid "Commits|History"
+msgstr ""
+
+msgid "Commits|No related merge requests found"
+msgstr ""
+
+msgid "Committed by"
+msgstr ""
+
+msgid "Commit…"
+msgstr ""
+
+msgid "Compare"
+msgstr ""
+
+msgid "Compare Git revisions"
+msgstr ""
+
+msgid "Compare Revisions"
+msgstr ""
+
+msgid "Compare changes with the last commit"
+msgstr ""
+
+msgid "Compare changes with the merge request target branch"
+msgstr ""
+
+msgid "CompareBranches|%{source_branch} and %{target_branch} are the same."
+msgstr ""
+
+msgid "CompareBranches|Compare"
+msgstr ""
+
+msgid "CompareBranches|Source"
+msgstr ""
+
+msgid "CompareBranches|Target"
+msgstr ""
+
+msgid "CompareBranches|There isn't anything to compare."
+msgstr ""
+
+msgid "Confidential"
+msgstr ""
+
+msgid "Confidentiality"
+msgstr ""
+
+msgid "Configure Gitaly timeouts."
+msgstr ""
+
+msgid "Configure Tracing"
+msgstr ""
+
+msgid "Configure automatic git checks and housekeeping on repositories."
+msgstr ""
+
+msgid "Configure limits for web and API requests."
+msgstr ""
+
+msgid "Configure push mirrors."
+msgstr ""
+
+msgid "Configure storage path settings."
+msgstr ""
+
+msgid "Configure the %{link} integration."
+msgstr ""
+
+msgid "Configure the way a user creates a new account."
+msgstr ""
+
+msgid "Connect"
+msgstr ""
+
+msgid "Connect all repositories"
+msgstr ""
+
+msgid "Connect repositories from GitHub"
+msgstr ""
+
+msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
+msgstr ""
+
+msgid "Connecting..."
+msgstr ""
+
+msgid "Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Created"
+msgstr ""
+
+msgid "ContainerRegistry|First log in to GitLab&rsquo;s Container Registry using your GitLab username and password. If you have %{link_2fa} you need to use a %{link_token}:"
+msgstr ""
+
+msgid "ContainerRegistry|GitLab supports up to 3 levels of image names. The following examples of images are valid for your project:"
+msgstr ""
+
+msgid "ContainerRegistry|How to use the Container Registry"
+msgstr ""
+
+msgid "ContainerRegistry|Learn more about"
+msgstr ""
+
+msgid "ContainerRegistry|No tags in Container Registry for this container image."
+msgstr ""
+
+msgid "ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands"
+msgstr ""
+
+msgid "ContainerRegistry|Remove repository"
+msgstr ""
+
+msgid "ContainerRegistry|Remove tag"
+msgstr ""
+
+msgid "ContainerRegistry|Size"
+msgstr ""
+
+msgid "ContainerRegistry|Tag"
+msgstr ""
+
+msgid "ContainerRegistry|Tag ID"
+msgstr ""
+
+msgid "ContainerRegistry|Use different image names"
+msgstr ""
+
+msgid "ContainerRegistry|With the Docker Container Registry integrated into GitLab, every project can have its own space to store its Docker images."
+msgstr ""
+
+msgid "ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images."
+msgstr ""
+
+msgid "Continue"
+msgstr ""
+
+msgid "Continue to the next step"
+msgstr ""
+
+msgid "Continuous Integration and Deployment"
+msgstr ""
+
+msgid "Contribute to GitLab"
+msgstr ""
+
+msgid "Contribution"
+msgstr ""
+
+msgid "Contribution guide"
+msgstr ""
+
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
+msgid "Contributions per group member"
+msgstr ""
+
+msgid "Contributors"
+msgstr ""
+
+msgid "ContributorsPage|%{startDate} – %{endDate}"
+msgstr ""
+
+msgid "ContributorsPage|Building repository graph."
+msgstr ""
+
+msgid "ContributorsPage|Commits to %{branch_name}, excluding merge commits. Limited to 6,000 commits."
+msgstr ""
+
+msgid "ContributorsPage|Please wait a moment, this page will automatically refresh when ready."
+msgstr ""
+
+msgid "Control the display of third party offers."
+msgstr ""
+
+msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of repository backfill for this secondary node"
+msgstr ""
+
+msgid "Control the maximum concurrency of verification operations for this Geo node"
+msgstr ""
+
+msgid "ConvDev Index"
+msgstr ""
+
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
+msgid "Copy SSH public key to clipboard"
+msgstr ""
+
+msgid "Copy URL to clipboard"
+msgstr ""
+
+msgid "Copy branch name to clipboard"
+msgstr ""
+
+msgid "Copy command to clipboard"
+msgstr ""
+
+msgid "Copy commit SHA to clipboard"
+msgstr ""
+
+msgid "Copy file path to clipboard"
+msgstr ""
+
+msgid "Copy incoming email address to clipboard"
+msgstr ""
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
+msgid "Copy reference to clipboard"
+msgstr ""
+
+msgid "Copy secret to clipboard"
+msgstr ""
+
+msgid "Copy to clipboard"
+msgstr ""
+
+msgid "Copy token to clipboard"
+msgstr ""
+
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
+msgid "Create"
+msgstr ""
+
+msgid "Create New Directory"
+msgstr ""
+
+msgid "Create a new branch"
+msgstr ""
+
+msgid "Create a new branch and merge request"
+msgstr ""
+
+msgid "Create a new issue"
+msgstr ""
+
+msgid "Create a personal access token on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Create branch"
+msgstr ""
+
+msgid "Create commit"
+msgstr ""
+
+msgid "Create directory"
+msgstr ""
+
+msgid "Create empty repository"
+msgstr ""
+
+msgid "Create epic"
+msgstr ""
+
+msgid "Create file"
+msgstr ""
+
+msgid "Create group"
+msgstr ""
+
+msgid "Create group label"
+msgstr ""
+
+msgid "Create issue"
+msgstr ""
+
+msgid "Create lists from labels. Issues with that label appear in that list."
+msgstr ""
+
+msgid "Create merge request"
+msgstr ""
+
+msgid "Create merge request and branch"
+msgstr ""
+
+msgid "Create new branch"
+msgstr ""
+
+msgid "Create new directory"
+msgstr ""
+
+msgid "Create new file"
+msgstr ""
+
+msgid "Create new file or directory"
+msgstr ""
+
+msgid "Create new label"
+msgstr ""
+
+msgid "Create new..."
+msgstr ""
+
+msgid "Create project label"
+msgstr ""
+
+msgid "Create your first page"
+msgstr ""
+
+msgid "CreateTag|Tag"
+msgstr ""
+
+msgid "CreateTokenToCloneLink|create a personal access token"
+msgstr ""
+
+msgid "Created"
+msgstr ""
+
+msgid "Created At"
+msgstr ""
+
+msgid "Created by me"
+msgstr ""
+
+msgid "Created on"
+msgstr ""
+
+msgid "Created on:"
+msgstr ""
+
+msgid "Creating epic"
+msgstr ""
+
+msgid "Cron Timezone"
+msgstr ""
+
+msgid "Cron syntax"
+msgstr ""
+
+msgid "Current Branch"
+msgstr ""
+
+msgid "Current node"
+msgstr ""
+
+msgid "CurrentUser|Profile"
+msgstr ""
+
+msgid "CurrentUser|Settings"
+msgstr ""
+
+msgid "Custom"
+msgstr ""
+
+msgid "Custom CI config path"
+msgstr ""
+
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
+msgid "Custom notification events"
+msgstr ""
+
+msgid "Custom notification levels are the same as participating levels. With custom notification levels you will also receive notifications for select events. To find out more, check out %{notification_link}."
+msgstr ""
+
+msgid "Custom project templates"
+msgstr ""
+
+msgid "Customize colors"
+msgstr ""
+
+msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
+msgid "Cycle Analytics"
+msgstr ""
+
+msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
+msgstr ""
+
+msgid "CycleAnalyticsStage|Code"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Issue"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Plan"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Production"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Review"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Staging"
+msgstr ""
+
+msgid "CycleAnalyticsStage|Test"
+msgstr ""
+
+msgid "Dashboard"
+msgstr ""
+
+msgid "DashboardProjects|All"
+msgstr ""
+
+msgid "DashboardProjects|Personal"
+msgstr ""
+
+msgid "Date picker"
+msgstr ""
+
+msgid "Debug"
+msgstr ""
+
+msgid "Dec"
+msgstr ""
+
+msgid "December"
+msgstr ""
+
+msgid "Decline and sign out"
+msgstr ""
+
+msgid "Default Branch"
+msgstr ""
+
+msgid "Default classification label"
+msgstr ""
+
+msgid "Default: Directly import the Google Code email address or username"
+msgstr ""
+
+msgid "Default: Map a FogBugz account ID to a full name"
+msgstr ""
+
+msgid "Define a custom pattern with cron syntax"
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
+msgid "Delete"
+msgstr ""
+
+msgid "Delete Package"
+msgstr ""
+
+msgid "Delete Snippet"
+msgstr ""
+
+msgid "Delete comment"
+msgstr ""
+
+msgid "Delete list"
+msgstr ""
+
+msgid "Deleted"
+msgstr ""
+
+msgid "Deny"
+msgstr ""
+
+msgid "Deploy"
+msgid_plural "Deploys"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Deploy Keys"
+msgstr ""
+
+msgid "DeployKeys|+%{count} others"
+msgstr ""
+
+msgid "DeployKeys|Current project"
+msgstr ""
+
+msgid "DeployKeys|Deploy key"
+msgstr ""
+
+msgid "DeployKeys|Enabled deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error enabling deploy key"
+msgstr ""
+
+msgid "DeployKeys|Error getting deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Error removing deploy key"
+msgstr ""
+
+msgid "DeployKeys|Expand %{count} other projects"
+msgstr ""
+
+msgid "DeployKeys|Loading deploy keys"
+msgstr ""
+
+msgid "DeployKeys|No deploy keys found. Create one with the form above."
+msgstr ""
+
+msgid "DeployKeys|Privately accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Project usage"
+msgstr ""
+
+msgid "DeployKeys|Publicly accessible deploy keys"
+msgstr ""
+
+msgid "DeployKeys|Read access only"
+msgstr ""
+
+msgid "DeployKeys|Write access allowed"
+msgstr ""
+
+msgid "DeployKeys|You are going to remove this deploy key. Are you sure?"
+msgstr ""
+
+msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
+msgstr ""
+
+msgid "DeployTokens|Add a deploy token"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the registry images"
+msgstr ""
+
+msgid "DeployTokens|Allows read-only access to the repository"
+msgstr ""
+
+msgid "DeployTokens|Copy deploy token to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Copy username to clipboard"
+msgstr ""
+
+msgid "DeployTokens|Create deploy token"
+msgstr ""
+
+msgid "DeployTokens|Created"
+msgstr ""
+
+msgid "DeployTokens|Deploy Tokens"
+msgstr ""
+
+msgid "DeployTokens|Deploy tokens allow read-only access to your repository and registry images."
+msgstr ""
+
+msgid "DeployTokens|Expires"
+msgstr ""
+
+msgid "DeployTokens|Name"
+msgstr ""
+
+msgid "DeployTokens|Pick a name for the application, and we'll give you a unique deploy token."
+msgstr ""
+
+msgid "DeployTokens|Revoke"
+msgstr ""
+
+msgid "DeployTokens|Revoke %{name}"
+msgstr ""
+
+msgid "DeployTokens|Scopes"
+msgstr ""
+
+msgid "DeployTokens|This action cannot be undone."
+msgstr ""
+
+msgid "DeployTokens|This project has no active Deploy Tokens."
+msgstr ""
+
+msgid "DeployTokens|Use this token as a password. Make sure you save it - you won't be able to access it again."
+msgstr ""
+
+msgid "DeployTokens|Use this username as a login."
+msgstr ""
+
+msgid "DeployTokens|Username"
+msgstr ""
+
+msgid "DeployTokens|You are about to revoke"
+msgstr ""
+
+msgid "DeployTokens|Your New Deploy Token"
+msgstr ""
+
+msgid "DeployTokens|Your new project deploy token has been created."
+msgstr ""
+
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
+msgid "Deprioritize label"
+msgstr ""
+
+msgid "Descending"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Description templates allow you to define context-specific templates for issue and merge request description fields for your project."
+msgstr ""
+
+msgid "Description:"
+msgstr ""
+
+msgid "Destroy"
+msgstr ""
+
+msgid "Details"
+msgstr ""
+
+msgid "Detect host keys"
+msgstr ""
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
+msgid "Diffs|No file name available"
+msgstr ""
+
+msgid "Diffs|Something went wrong while fetching diff lines."
+msgstr ""
+
+msgid "Direction"
+msgstr ""
+
+msgid "Directory name"
+msgstr ""
+
+msgid "Disable"
+msgstr ""
+
+msgid "Disable for this project"
+msgstr ""
+
+msgid "Disable group Runners"
+msgstr ""
+
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
+msgid "Discard changes"
+msgstr ""
+
+msgid "Discard changes to %{path}?"
+msgstr ""
+
+msgid "Discard draft"
+msgstr ""
+
+msgid "Discard review"
+msgstr ""
+
+msgid "Discover GitLab Geo."
+msgstr ""
+
+msgid "Discover projects, groups and snippets. Share your projects with others"
+msgstr ""
+
+msgid "Dismiss"
+msgstr ""
+
+msgid "Dismiss Cycle Analytics introduction box"
+msgstr ""
+
+msgid "Dismiss Merge Request promotion"
+msgstr ""
+
+msgid "Dismiss trial promotion"
+msgstr ""
+
+msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
+msgstr ""
+
+msgid "Documentation for popular identity providers"
+msgstr ""
+
+msgid "Domain"
+msgstr ""
+
+msgid "Don't show again"
+msgstr ""
+
+msgid "Done"
+msgstr ""
+
+msgid "Download"
+msgstr ""
+
+msgid "Download tar"
+msgstr ""
+
+msgid "Download tar.bz2"
+msgstr ""
+
+msgid "Download tar.gz"
+msgstr ""
+
+msgid "Download zip"
+msgstr ""
+
+msgid "DownloadArtifacts|Download"
+msgstr ""
+
+msgid "DownloadCommit|Email Patches"
+msgstr ""
+
+msgid "DownloadCommit|Plain Diff"
+msgstr ""
+
+msgid "DownloadSource|Download"
+msgstr ""
+
+msgid "Downvotes"
+msgstr ""
+
+msgid "Due date"
+msgstr ""
+
+msgid "During this process, you’ll be asked for URLs from GitLab’s side. Use the URLs shown below."
+msgstr ""
+
+msgid "Each Runner can be in one of the following states:"
+msgstr ""
+
+msgid "Edit"
+msgstr ""
+
+msgid "Edit Label"
+msgstr ""
+
+msgid "Edit Pipeline Schedule %{id}"
+msgstr ""
+
+msgid "Edit Snippet"
+msgstr ""
+
+msgid "Edit application"
+msgstr ""
+
+msgid "Edit files in the editor and commit changes here"
+msgstr ""
+
+msgid "Edit group: %{group_name}"
+msgstr ""
+
+msgid "Edit identity for %{user_name}"
+msgstr ""
+
+msgid "Elasticsearch"
+msgstr ""
+
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
+
+msgid "Email"
+msgstr ""
+
+msgid "Email patch"
+msgstr ""
+
+msgid "Emails"
+msgstr ""
+
+msgid "Embed"
+msgstr ""
+
+msgid "Enable"
+msgstr ""
+
+msgid "Enable Auto DevOps"
+msgstr ""
+
+msgid "Enable Pseudonymizer data collection"
+msgstr ""
+
+msgid "Enable SAML authentication for this group"
+msgstr ""
+
+msgid "Enable Sentry for error reporting and logging."
+msgstr ""
+
+msgid "Enable and configure InfluxDB metrics."
+msgstr ""
+
+msgid "Enable and configure Prometheus metrics."
+msgstr ""
+
+msgid "Enable classification control using an external service"
+msgstr ""
+
+msgid "Enable for this project"
+msgstr ""
+
+msgid "Enable group Runners"
+msgstr ""
+
+msgid "Enable or disable the Pseudonymizer data collection."
+msgstr ""
+
+msgid "Enable or disable version check and usage ping."
+msgstr ""
+
+msgid "Enable reCAPTCHA or Akismet and set IP limits."
+msgstr ""
+
+msgid "Enable the Performance Bar for a given group."
+msgstr ""
+
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
+msgid "Enabled"
+msgstr ""
+
+msgid "Ends at (UTC)"
+msgstr ""
+
+msgid "Enter in your Bitbucket Server URL and personal access token below"
+msgstr ""
+
+msgid "Enter the issue description"
+msgstr ""
+
+msgid "Enter the issue title"
+msgstr ""
+
+msgid "Enter the merge request description"
+msgstr ""
+
+msgid "Enter the merge request title"
+msgstr ""
+
+msgid "Environments"
+msgstr ""
+
+msgid "Environments|An error occurred while fetching the environments."
+msgstr ""
+
+msgid "Environments|An error occurred while making the request."
+msgstr ""
+
+msgid "Environments|An error occurred while stopping the environment, please try again"
+msgstr ""
+
+msgid "Environments|Are you sure you want to stop this environment?"
+msgstr ""
+
+msgid "Environments|Commit"
+msgstr ""
+
+msgid "Environments|Deploy to..."
+msgstr ""
+
+msgid "Environments|Deployment"
+msgstr ""
+
+msgid "Environments|Environment"
+msgstr ""
+
+msgid "Environments|Environments"
+msgstr ""
+
+msgid "Environments|Environments are places where code gets deployed, such as staging or production."
+msgstr ""
+
+msgid "Environments|Job"
+msgstr ""
+
+msgid "Environments|Learn more about stopping environments"
+msgstr ""
+
+msgid "Environments|New environment"
+msgstr ""
+
+msgid "Environments|No deployments yet"
+msgstr ""
+
+msgid "Environments|No pod name has been specified"
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
+msgstr ""
+
+msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
+msgstr ""
+
+msgid "Environments|Open live environment"
+msgstr ""
+
+msgid "Environments|Pod logs from"
+msgstr ""
+
+msgid "Environments|Re-deploy to environment"
+msgstr ""
+
+msgid "Environments|Read more about environments"
+msgstr ""
+
+msgid "Environments|Rollback environment"
+msgstr ""
+
+msgid "Environments|Show all"
+msgstr ""
+
+msgid "Environments|Stop"
+msgstr ""
+
+msgid "Environments|Stop environment"
+msgstr ""
+
+msgid "Environments|Updated"
+msgstr ""
+
+msgid "Environments|You don't have any environments right now"
+msgstr ""
+
+msgid "Environments|protected"
+msgstr ""
+
+msgid "Epic"
+msgstr ""
+
+msgid "Epic will be removed! Are you sure?"
+msgstr ""
+
+msgid "Epics"
+msgstr ""
+
+msgid "Epics Roadmap"
+msgstr ""
+
+msgid "Epics let you manage your portfolio of projects more efficiently and with less effort"
+msgstr ""
+
+msgid "Epics|An error occurred while saving %{epicDateType} date"
+msgstr ""
+
+msgid "Epics|How can I solve this?"
+msgstr ""
+
+msgid "Epics|More information"
+msgstr ""
+
+msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
+msgstr ""
+
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr ""
+
+msgid "Epics|due"
+msgstr ""
+
+msgid "Epics|start"
+msgstr ""
+
+msgid "Error"
+msgstr ""
+
+msgid "Error Reporting and Logging"
+msgstr ""
+
+msgid "Error creating epic"
+msgstr ""
+
+msgid "Error fetching contributors data."
+msgstr ""
+
+msgid "Error fetching labels."
+msgstr ""
+
+msgid "Error fetching network graph."
+msgstr ""
+
+msgid "Error fetching refs"
+msgstr ""
+
+msgid "Error fetching usage ping data."
+msgstr ""
+
+msgid "Error loading branch data. Please try again."
+msgstr ""
+
+msgid "Error loading branches."
+msgstr ""
+
+msgid "Error loading last commit."
+msgstr ""
+
+msgid "Error loading markdown preview"
+msgstr ""
+
+msgid "Error loading merge requests."
+msgstr ""
+
+msgid "Error loading project data. Please try again."
+msgstr ""
+
+msgid "Error loading template types."
+msgstr ""
+
+msgid "Error loading template."
+msgstr ""
+
+msgid "Error occurred when toggling the notification subscription"
+msgstr ""
+
+msgid "Error saving label update."
+msgstr ""
+
+msgid "Error updating status for all todos."
+msgstr ""
+
+msgid "Error updating todo status."
+msgstr ""
+
+msgid "Error while loading the merge request. Please try again."
+msgstr ""
+
+msgid "Estimated"
+msgstr ""
+
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
+msgid "Every day (at 4:00am)"
+msgstr ""
+
+msgid "Every month (on the 1st at 4:00am)"
+msgstr ""
+
+msgid "Every week (Sundays at 4:00am)"
+msgstr ""
+
+msgid "Everyone can contribute"
+msgstr ""
+
+msgid "Expand"
+msgstr ""
+
+msgid "Expand all"
+msgstr ""
+
+msgid "Expand sidebar"
+msgstr ""
+
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
+msgid "Explore"
+msgstr ""
+
+msgid "Explore GitLab"
+msgstr ""
+
+msgid "Explore Groups"
+msgstr ""
+
+msgid "Explore groups"
+msgstr ""
+
+msgid "Explore projects"
+msgstr ""
+
+msgid "Explore public groups"
+msgstr ""
+
+msgid "External Classification Policy Authorization"
+msgstr ""
+
+msgid "External authentication"
+msgstr ""
+
+msgid "External authorization denied access to this project"
+msgstr ""
+
+msgid "External authorization request timeout"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification Label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|Classification label"
+msgstr ""
+
+msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
+msgstr ""
+
+msgid "Facebook"
+msgstr ""
+
+msgid "Failed"
+msgstr ""
+
+msgid "Failed Jobs"
+msgstr ""
+
+msgid "Failed to change the owner"
+msgstr ""
+
+msgid "Failed to check related branches."
+msgstr ""
+
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
+msgid "Failed to remove issue from board, please try again."
+msgstr ""
+
+msgid "Failed to remove mirror."
+msgstr ""
+
+msgid "Failed to remove the pipeline schedule"
+msgstr ""
+
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
+msgid "Failed to update issues, please try again."
+msgstr ""
+
+msgid "Failure"
+msgstr ""
+
+msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
+msgstr ""
+
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
+msgid "Feb"
+msgstr ""
+
+msgid "February"
+msgstr ""
+
+msgid "Fields on this page are now uneditable, you can configure"
+msgstr ""
+
+msgid "File templates"
+msgstr ""
+
+msgid "Files"
+msgstr ""
+
+msgid "Files (%{human_size})"
+msgstr ""
+
+msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
+msgstr ""
+
+msgid "Filter"
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
+msgid "Filter by commit message"
+msgstr ""
+
+msgid "Filter..."
+msgstr ""
+
+msgid "Find by path"
+msgstr ""
+
+msgid "Find file"
+msgstr ""
+
+msgid "Find the downloaded ZIP file and decompress it."
+msgstr ""
+
+msgid "Find the newly extracted <code>Takeout/Google Code Project Hosting/GoogleCodeProjectHosting.json</code> file."
+msgstr ""
+
+msgid "Fingerprints"
+msgstr ""
+
+msgid "Finish review"
+msgstr ""
+
+msgid "Finished"
+msgstr ""
+
+msgid "FirstPushedBy|First"
+msgstr ""
+
+msgid "FirstPushedBy|pushed by"
+msgstr ""
+
+msgid "Fixed date"
+msgstr ""
+
+msgid "Fixed due date"
+msgstr ""
+
+msgid "Fixed start date"
+msgstr ""
+
+msgid "Fixed:"
+msgstr ""
+
+msgid "FogBugz Email"
+msgstr ""
+
+msgid "FogBugz Import"
+msgstr ""
+
+msgid "FogBugz Password"
+msgstr ""
+
+msgid "FogBugz URL"
+msgstr ""
+
+msgid "FogBugz import"
+msgstr ""
+
+msgid "Follow the steps below to export your Google Code project data."
+msgstr ""
+
+msgid "Font Color"
+msgstr ""
+
+msgid "Footer message"
+msgstr ""
+
+msgid "For internal projects, any logged in user can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For more information, go to the "
+msgstr ""
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
+msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from"
+msgstr ""
+
+msgid "ForkedFromProjectPath|Forked from %{project_name} (deleted)"
+msgstr ""
+
+msgid "Forking in progress"
+msgstr ""
+
+msgid "Format"
+msgstr ""
+
+msgid "Found errors in your .gitlab-ci.yml:"
+msgstr ""
+
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
+msgid "From %{provider_title}"
+msgstr ""
+
+msgid "From Bitbucket"
+msgstr ""
+
+msgid "From Bitbucket Server"
+msgstr ""
+
+msgid "From FogBugz"
+msgstr ""
+
+msgid "From GitLab.com"
+msgstr ""
+
+msgid "From Google Code"
+msgstr ""
+
+msgid "From issue creation until deploy to production"
+msgstr ""
+
+msgid "From merge request merge until deploy to production"
+msgstr ""
+
+msgid "From milestones:"
+msgstr ""
+
+msgid "From the Kubernetes cluster details view, install Runner from the applications list"
+msgstr ""
+
+msgid "GPG Keys"
+msgstr ""
+
+msgid "General"
+msgstr ""
+
+msgid "General pipelines"
+msgstr ""
+
+msgid "Generate a default set of labels"
+msgstr ""
+
+msgid "Geo"
+msgstr ""
+
+msgid "Geo Nodes"
+msgstr ""
+
+msgid "Geo allows you to replicate your GitLab instance to other geographical locations."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is failing or broken."
+msgstr ""
+
+msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
+msgstr ""
+
+msgid "GeoNodes|Checksummed"
+msgstr ""
+
+msgid "GeoNodes|Data is out of date from %{timeago}"
+msgstr ""
+
+msgid "GeoNodes|Data replication lag"
+msgstr ""
+
+msgid "GeoNodes|Disabling a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Does not match the primary storage configuration"
+msgstr ""
+
+msgid "GeoNodes|Failed"
+msgstr ""
+
+msgid "GeoNodes|Full"
+msgstr ""
+
+msgid "GeoNodes|GitLab version"
+msgstr ""
+
+msgid "GeoNodes|GitLab version does not match the primary node version"
+msgstr ""
+
+msgid "GeoNodes|Health status"
+msgstr ""
+
+msgid "GeoNodes|Last event ID processed by cursor"
+msgstr ""
+
+msgid "GeoNodes|Last event ID seen from primary"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Repository verification"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Learn more about Wiki verification"
+msgstr ""
+
+msgid "GeoNodes|Loading nodes"
+msgstr ""
+
+msgid "GeoNodes|Local LFS objects"
+msgstr ""
+
+msgid "GeoNodes|Local attachments"
+msgstr ""
+
+msgid "GeoNodes|Local job artifacts"
+msgstr ""
+
+msgid "GeoNodes|New node"
+msgstr ""
+
+msgid "GeoNodes|Node Authentication was successfully repaired."
+msgstr ""
+
+msgid "GeoNodes|Node was successfully removed."
+msgstr ""
+
+msgid "GeoNodes|Not checksummed"
+msgstr ""
+
+msgid "GeoNodes|Out of sync"
+msgstr ""
+
+msgid "GeoNodes|Removing a node stops the sync process. Are you sure?"
+msgstr ""
+
+msgid "GeoNodes|Replication slot WAL"
+msgstr ""
+
+msgid "GeoNodes|Replication slots"
+msgstr ""
+
+msgid "GeoNodes|Repositories"
+msgstr ""
+
+msgid "GeoNodes|Repositories checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Repositories verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|Repository checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Repository verification progress"
+msgstr ""
+
+msgid "GeoNodes|Selective"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while changing node status"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while fetching nodes"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while removing node"
+msgstr ""
+
+msgid "GeoNodes|Something went wrong while repairing node"
+msgstr ""
+
+msgid "GeoNodes|Storage config"
+msgstr ""
+
+msgid "GeoNodes|Sync settings"
+msgstr ""
+
+msgid "GeoNodes|Synced"
+msgstr ""
+
+msgid "GeoNodes|Unused slots"
+msgstr ""
+
+msgid "GeoNodes|Unverified"
+msgstr ""
+
+msgid "GeoNodes|Used slots"
+msgstr ""
+
+msgid "GeoNodes|Verified"
+msgstr ""
+
+msgid "GeoNodes|Wiki checksum progress"
+msgstr ""
+
+msgid "GeoNodes|Wiki verification progress"
+msgstr ""
+
+msgid "GeoNodes|Wikis"
+msgstr ""
+
+msgid "GeoNodes|Wikis checksummed for verification with their counterparts on Secondary nodes"
+msgstr ""
+
+msgid "GeoNodes|Wikis verified with their counterparts on the Primary node"
+msgstr ""
+
+msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection. We recommend the use of HTTPS."
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for forced re-download"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-check"
+msgstr ""
+
+msgid "Geo|%{name} is scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|All"
+msgstr ""
+
+msgid "Geo|All projects"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
+
+msgid "Geo|Failed"
+msgstr ""
+
+msgid "Geo|File sync capacity"
+msgstr ""
+
+msgid "Geo|Geo Status"
+msgstr ""
+
+msgid "Geo|Groups to synchronize"
+msgstr ""
+
+msgid "Geo|In sync"
+msgstr ""
+
+msgid "Geo|Last successful sync"
+msgstr ""
+
+msgid "Geo|Last sync attempt"
+msgstr ""
+
+msgid "Geo|Last time verified"
+msgstr ""
+
+msgid "Geo|Never"
+msgstr ""
+
+msgid "Geo|Next sync scheduled at"
+msgstr ""
+
+msgid "Geo|Not synced yet"
+msgstr ""
+
+msgid "Geo|Pending"
+msgstr ""
+
+msgid "Geo|Pending synchronization"
+msgstr ""
+
+msgid "Geo|Pending verification"
+msgstr ""
+
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
+msgid "Geo|Projects in certain groups"
+msgstr ""
+
+msgid "Geo|Projects in certain storage shards"
+msgstr ""
+
+msgid "Geo|Recheck"
+msgstr ""
+
+msgid "Geo|Recheck all projects"
+msgstr ""
+
+msgid "Geo|Redownload"
+msgstr ""
+
+msgid "Geo|Remove"
+msgstr ""
+
+msgid "Geo|Repository sync capacity"
+msgstr ""
+
+msgid "Geo|Resync"
+msgstr ""
+
+msgid "Geo|Resync all projects"
+msgstr ""
+
+msgid "Geo|Retry count"
+msgstr ""
+
+msgid "Geo|Select groups to replicate."
+msgstr ""
+
+msgid "Geo|Shards to synchronize"
+msgstr ""
+
+msgid "Geo|Status"
+msgstr ""
+
+msgid "Geo|Synced"
+msgstr ""
+
+msgid "Geo|Synchronization failed - %{error}"
+msgstr ""
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
+msgid "Geo|Unknown state"
+msgstr ""
+
+msgid "Geo|Verification capacity"
+msgstr ""
+
+msgid "Geo|Verification failed - %{error}"
+msgstr ""
+
+msgid "Geo|Waiting for scheduler"
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
+msgid "Geo|You need a different license to use Geo replication"
+msgstr ""
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
+msgid "Git"
+msgstr ""
+
+msgid "Git repository URL"
+msgstr ""
+
+msgid "Git revision"
+msgstr ""
+
+msgid "Git strategy for pipelines"
+msgstr ""
+
+msgid "Git version"
+msgstr ""
+
+msgid "GitHub import"
+msgstr ""
+
+msgid "GitLab CI Linter has been moved"
+msgstr ""
+
+msgid "GitLab Geo"
+msgstr ""
+
+msgid "GitLab Group Runners can execute code for all the projects in this group."
+msgstr ""
+
+msgid "GitLab Import"
+msgstr ""
+
+msgid "GitLab User"
+msgstr ""
+
+msgid "GitLab project export"
+msgstr ""
+
+msgid "GitLab single sign on URL"
+msgstr ""
+
+msgid "GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "GitLab.com import"
+msgstr ""
+
+msgid "GitLab’s issue tracker"
+msgstr ""
+
+msgid "Gitaly"
+msgstr ""
+
+msgid "Gitaly Servers"
+msgstr ""
+
+msgid "Gitaly|Address"
+msgstr ""
+
+msgid "Gitea Host URL"
+msgstr ""
+
+msgid "Gitea Import"
+msgstr ""
+
+msgid "Go Back"
+msgstr ""
+
+msgid "Go back"
+msgstr ""
+
+msgid "Go to"
+msgstr ""
+
+msgid "Go to %{link_to_google_takeout}."
+msgstr ""
+
+msgid "Google Code import"
+msgstr ""
+
+msgid "Google Takeout"
+msgstr ""
+
+msgid "Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service."
+msgstr ""
+
+msgid "Got it!"
+msgstr ""
+
+msgid "Graph"
+msgstr ""
+
+msgid "Group"
+msgstr ""
+
+msgid "Group CI/CD settings"
+msgstr ""
+
+msgid "Group Git LFS status:"
+msgstr ""
+
+msgid "Group ID"
+msgstr ""
+
+msgid "Group Runners"
+msgstr ""
+
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
+msgid "Group avatar"
+msgstr ""
+
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
+msgid "Group details"
+msgstr ""
+
+msgid "Group info:"
+msgstr ""
+
+msgid "Group maintainers can register group runners in the %{link}"
+msgstr ""
+
+msgid "Group name"
+msgstr ""
+
+msgid "Group: %{group_name}"
+msgstr ""
+
+msgid "GroupRoadmap|From %{dateWord}"
+msgstr ""
+
+msgid "GroupRoadmap|Loading roadmap"
+msgstr ""
+
+msgid "GroupRoadmap|Something went wrong while fetching epics"
+msgstr ""
+
+msgid "GroupRoadmap|Sorry, no epics matched your search"
+msgstr ""
+
+msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|To widen your search, change or remove filters. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
+
+msgid "GroupRoadmap|Until %{dateWord}"
+msgstr ""
+
+msgid "GroupSettings|Badges"
+msgstr ""
+
+msgid "GroupSettings|Customize your group badges."
+msgstr ""
+
+msgid "GroupSettings|Learn more about badges."
+msgstr ""
+
+msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. To share projects in this group with another group, ask the owner to override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting is applied on %{ancestor_group}. You can override the setting or %{remove_ancestor_share_with_group_lock}."
+msgstr ""
+
+msgid "GroupSettings|This setting will be applied to all subgroups unless overridden by a group owner. Groups that already have access to the project will continue to have access unless removed manually."
+msgstr ""
+
+msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
+msgstr ""
+
+msgid "GroupSettings|remove the share with group lock from %{ancestor_group_name}"
+msgstr ""
+
+msgid "Groups"
+msgstr ""
+
+msgid "Groups can also be nested by creating %{subgroup_docs_link_start}subgroups%{subgroup_docs_link_end}."
+msgstr ""
+
+msgid "GroupsDropdown|Frequently visited"
+msgstr ""
+
+msgid "GroupsDropdown|Groups you visit often will appear here"
+msgstr ""
+
+msgid "GroupsDropdown|Loading groups"
+msgstr ""
+
+msgid "GroupsDropdown|Search your groups"
+msgstr ""
+
+msgid "GroupsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "GroupsDropdown|Sorry, no groups matched your search"
+msgstr ""
+
+msgid "GroupsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "GroupsEmptyState|A group is a collection of several projects."
+msgstr ""
+
+msgid "GroupsEmptyState|If you organize your projects under a group, it works like a folder."
+msgstr ""
+
+msgid "GroupsEmptyState|No groups found"
+msgstr ""
+
+msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
+msgstr ""
+
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
+msgid "GroupsTree|Create a project in this group."
+msgstr ""
+
+msgid "GroupsTree|Create a subgroup in this group."
+msgstr ""
+
+msgid "GroupsTree|Edit group"
+msgstr ""
+
+msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
+msgstr ""
+
+msgid "GroupsTree|Leave this group"
+msgstr ""
+
+msgid "GroupsTree|Loading groups"
+msgstr ""
+
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
+
+msgid "Have your users email"
+msgstr ""
+
+msgid "Header message"
+msgstr ""
+
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
+msgid "Help"
+msgstr ""
+
+msgid "Help page"
+msgstr ""
+
+msgid "Help page text and support page url."
+msgstr ""
+
+msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
+msgstr ""
+
+msgid "Hide host keys manual input"
+msgstr ""
+
+msgid "Hide payload"
+msgstr ""
+
+msgid "Hide value"
+msgid_plural "Hide values"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Hide whitespace changes"
+msgstr ""
+
+msgid "History"
+msgstr ""
+
+msgid "Housekeeping successfully started"
+msgstr ""
+
+msgid "I accept the %{terms_link}"
+msgstr ""
+
+msgid "I accept the|Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "ID"
+msgstr ""
+
+msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
+msgstr ""
+
+msgid "IDE|Back"
+msgstr ""
+
+msgid "IDE|Client side evaluation"
+msgstr ""
+
+msgid "IDE|Commit"
+msgstr ""
+
+msgid "IDE|Edit"
+msgstr ""
+
+msgid "IDE|Get started with Live Preview"
+msgstr ""
+
+msgid "IDE|Go to project"
+msgstr ""
+
+msgid "IDE|Live Preview"
+msgstr ""
+
+msgid "IDE|Open in file view"
+msgstr ""
+
+msgid "IDE|Preview your web application using Web IDE client-side evaluation."
+msgstr ""
+
+msgid "IDE|Refresh preview"
+msgstr ""
+
+msgid "IDE|Review"
+msgstr ""
+
+msgid "IP Address"
+msgstr ""
+
+msgid "Identifier"
+msgstr ""
+
+msgid "Identities"
+msgstr ""
+
+msgid "Identity provider single sign on URL"
+msgstr ""
+
+msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
+msgstr ""
+
+msgid "If disabled, the access level will depend on the user's permissions in the project."
+msgstr ""
+
+msgid "If enabled"
+msgstr ""
+
+msgid "If enabled, access to projects will be validated on an external service using their classification label."
+msgstr ""
+
+msgid "If using GitHub, you’ll see pipeline statuses on GitHub for your commits and pull requests. %{more_info_link}"
+msgstr ""
+
+msgid "If you already have files you can push them using the %{link_to_cli} below."
+msgstr ""
+
+msgid "If your HTTP repository is not publicly accessible, add authentication information to the URL: <code>https://username:password@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "ImageDiffViewer|2-up"
+msgstr ""
+
+msgid "ImageDiffViewer|Onion skin"
+msgstr ""
+
+msgid "ImageDiffViewer|Swipe"
+msgstr ""
+
+msgid "Import"
+msgstr ""
+
+msgid "Import Projects from Gitea"
+msgstr ""
+
+msgid "Import all compatible projects"
+msgstr ""
+
+msgid "Import all projects"
+msgstr ""
+
+msgid "Import all repositories"
+msgstr ""
+
+msgid "Import an exported GitLab project"
+msgstr ""
+
+msgid "Import in progress"
+msgstr ""
+
+msgid "Import multiple repositories by uploading a manifest file."
+msgstr ""
+
+msgid "Import project"
+msgstr ""
+
+msgid "Import projects from Bitbucket"
+msgstr ""
+
+msgid "Import projects from Bitbucket Server"
+msgstr ""
+
+msgid "Import projects from FogBugz"
+msgstr ""
+
+msgid "Import projects from GitLab.com"
+msgstr ""
+
+msgid "Import projects from Google Code"
+msgstr ""
+
+msgid "Import repositories from Bitbucket Server"
+msgstr ""
+
+msgid "Import repositories from GitHub"
+msgstr ""
+
+msgid "Import repository"
+msgstr ""
+
+msgid "ImportButtons|Connect repositories from"
+msgstr ""
+
+msgid "Improve Issue boards with GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve issues management with Issue weight and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
+msgstr ""
+
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
+msgid "In the next step, you'll be able to select the projects you want to import."
+msgstr ""
+
+msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
+msgstr ""
+
+msgid "Include the username in the URL if required: <code>https://username@gitlab.company.com/group/project.git</code>."
+msgstr ""
+
+msgid "Incompatible Project"
+msgstr ""
+
+msgid "Indicates whether this runner can pick jobs without tags"
+msgstr ""
+
+msgid "Inline"
+msgstr ""
+
+msgid "Input host keys manually"
+msgstr ""
+
+msgid "Input your repository URL"
+msgstr ""
+
+msgid "Install GitLab Runner"
+msgstr ""
+
+msgid "Install Runner on Kubernetes"
+msgstr ""
+
+msgid "Instance"
+msgid_plural "Instances"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Instance Statistics"
+msgstr ""
+
+msgid "Instance Statistics visibility"
+msgstr ""
+
+msgid "Instance does not support multiple Kubernetes clusters"
+msgstr ""
+
+msgid "Integrations"
+msgstr ""
+
+msgid "Integrations Settings"
+msgstr ""
+
+msgid "Interested parties can even contribute by pushing commits if they want to."
+msgstr ""
+
+msgid "Internal - The group and any internal projects can be viewed by any logged in user."
+msgstr ""
+
+msgid "Internal - The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "Internal users"
+msgstr ""
+
+msgid "Interval Pattern"
+msgstr ""
+
+msgid "Introducing Cycle Analytics"
+msgstr ""
+
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
+msgid "Issue Boards"
+msgstr ""
+
+msgid "Issue board focus mode"
+msgstr ""
+
+msgid "Issue events"
+msgstr ""
+
+msgid "IssueBoards|Board"
+msgstr ""
+
+msgid "IssueBoards|Boards"
+msgstr ""
+
+msgid "Issues"
+msgstr ""
+
+msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
+msgstr ""
+
+msgid "Issues closed"
+msgstr ""
+
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
+msgid "Jan"
+msgstr ""
+
+msgid "January"
+msgstr ""
+
+msgid "Job"
+msgstr ""
+
+msgid "Job has been erased"
+msgstr ""
+
+msgid "Jobs"
+msgstr ""
+
+msgid "Job|Browse"
+msgstr ""
+
+msgid "Job|Complete Raw"
+msgstr ""
+
+msgid "Job|Download"
+msgstr ""
+
+msgid "Job|Erase job log"
+msgstr ""
+
+msgid "Job|Job artifacts"
+msgstr ""
+
+msgid "Job|Job has been erased"
+msgstr ""
+
+msgid "Job|Job has been erased by"
+msgstr ""
+
+msgid "Job|Keep"
+msgstr ""
+
+msgid "Job|Scroll to bottom"
+msgstr ""
+
+msgid "Job|Scroll to top"
+msgstr ""
+
+msgid "Job|Show complete raw"
+msgstr ""
+
+msgid "Job|The artifacts were removed"
+msgstr ""
+
+msgid "Job|The artifacts will be removed in"
+msgstr ""
+
+msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
+msgstr ""
+
+msgid "Jul"
+msgstr ""
+
+msgid "July"
+msgstr ""
+
+msgid "Jun"
+msgstr ""
+
+msgid "June"
+msgstr ""
+
+msgid "Kubernetes"
+msgstr ""
+
+msgid "Kubernetes Cluster"
+msgstr ""
+
+msgid "Kubernetes cluster creation time exceeds timeout; %{timeout}"
+msgstr ""
+
+msgid "Kubernetes cluster integration was not removed."
+msgstr ""
+
+msgid "Kubernetes cluster integration was successfully removed."
+msgstr ""
+
+msgid "Kubernetes cluster was successfully updated."
+msgstr ""
+
+msgid "Kubernetes configured"
+msgstr ""
+
+msgid "Kubernetes service integration has been deprecated. %{deprecated_message_content} your Kubernetes clusters using the new <a href=\"%{url}\"/>Kubernetes Clusters</a> page"
+msgstr ""
+
+msgid "LFS"
+msgstr ""
+
+msgid "LFSStatus|Disabled"
+msgstr ""
+
+msgid "LFSStatus|Enabled"
+msgstr ""
+
+msgid "Label"
+msgstr ""
+
+msgid "Label actions dropdown"
+msgstr ""
+
+msgid "Label lists show all issues with the selected label."
+msgstr ""
+
+msgid "LabelSelect|%{firstLabelName} +%{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|%{labelsString}, and %{remainingLabelCount} more"
+msgstr ""
+
+msgid "LabelSelect|Labels"
+msgstr ""
+
+msgid "Labels"
+msgstr ""
+
+msgid "Labels can be applied to %{features}. Group labels are available for any project within the group."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests to categorize them."
+msgstr ""
+
+msgid "Labels can be applied to issues and merge requests."
+msgstr ""
+
+msgid "Labels|<span>Promote label</span> %{labelTitle} <span>to Group Label?</span>"
+msgstr ""
+
+msgid "Labels|Promote Label"
+msgstr ""
+
+msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
+msgstr ""
+
+msgid "Large File Storage"
+msgstr ""
+
+msgid "Last %d day"
+msgid_plural "Last %d days"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Last Pipeline"
+msgstr ""
+
+msgid "Last commit"
+msgstr ""
+
+msgid "Last contact"
+msgstr ""
+
+msgid "Last edited %{date}"
+msgstr ""
+
+msgid "Last edited by %{name}"
+msgstr ""
+
+msgid "Last reply by"
+msgstr ""
+
+msgid "Last update"
+msgstr ""
+
+msgid "Last updated"
+msgstr ""
+
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
+msgid "Latest changes"
+msgstr ""
+
+msgid "Learn more"
+msgstr ""
+
+msgid "Learn more about %{issue_boards_url}, to keep track of issues in multiple lists, using labels, assignees, and milestones. If you’re missing something from issue boards, please create an issue on %{gitlab_issues_url}."
+msgstr ""
+
+msgid "Learn more about Kubernetes"
+msgstr ""
+
+msgid "Learn more about protected branches"
+msgstr ""
+
+msgid "Learn more in the"
+msgstr ""
+
+msgid "Learn more in the|pipeline schedules documentation"
+msgstr ""
+
+msgid "Leave"
+msgstr ""
+
+msgid "Leave group"
+msgstr ""
+
+msgid "Leave project"
+msgstr ""
+
+msgid "Leave the \"File type\" and \"Delivery method\" options on their default values."
+msgstr ""
+
+msgid "License"
+msgstr ""
+
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
+msgid "LicenseManagement|Approve license"
+msgstr ""
+
+msgid "LicenseManagement|Approve license?"
+msgstr ""
+
+msgid "LicenseManagement|Approved"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license"
+msgstr ""
+
+msgid "LicenseManagement|Blacklist license?"
+msgstr ""
+
+msgid "LicenseManagement|Blacklisted"
+msgstr ""
+
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
+msgid "LicenseManagement|License"
+msgstr ""
+
+msgid "LicenseManagement|License Management"
+msgstr ""
+
+msgid "LicenseManagement|License details"
+msgstr ""
+
+msgid "LicenseManagement|License name"
+msgstr ""
+
+msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
+msgstr ""
+
+msgid "LicenseManagement|Packages"
+msgstr ""
+
+msgid "LicenseManagement|Remove license"
+msgstr ""
+
+msgid "LicenseManagement|Remove license?"
+msgstr ""
+
+msgid "LicenseManagement|Submit"
+msgstr ""
+
+msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
+msgstr ""
+
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
+msgid "LicenseManagement|URL"
+msgstr ""
+
+msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
+msgstr ""
+
+msgid "Licenses"
+msgstr ""
+
+msgid "Limited to showing %d event at most"
+msgid_plural "Limited to showing %d events at most"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "LinkedIn"
+msgstr ""
+
+msgid "List"
+msgstr ""
+
+msgid "List Your Gitea Repositories"
+msgstr ""
+
+msgid "List available repositories"
+msgstr ""
+
+msgid "List view"
+msgstr ""
+
+msgid "List your Bitbucket Server repositories"
+msgstr ""
+
+msgid "List your GitHub repositories"
+msgstr ""
+
+msgid "Live preview"
+msgstr ""
+
+msgid "Loading contribution stats for group members"
+msgstr ""
+
+msgid "Loading the GitLab IDE..."
+msgstr ""
+
+msgid "Loading..."
+msgstr ""
+
+msgid "Lock"
+msgstr ""
+
+msgid "Lock %{issuableDisplayName}"
+msgstr ""
+
+msgid "Lock not found"
+msgstr ""
+
+msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
+msgstr ""
+
+msgid "Lock to current projects"
+msgstr ""
+
+msgid "Locked"
+msgstr ""
+
+msgid "Locked Files"
+msgstr ""
+
+msgid "Locked to current projects"
+msgstr ""
+
+msgid "Locks give the ability to lock specific file or folder."
+msgstr ""
+
+msgid "Login with smartcard"
+msgstr ""
+
+msgid "Logs"
+msgstr ""
+
+msgid "Make everyone on your team more productive regardless of their location. GitLab Geo creates read-only mirrors of your GitLab instance so you can reduce the time it takes to clone and fetch large repos."
+msgstr ""
+
+msgid "Make sure you're logged into the account that owns the projects you'd like to import."
+msgstr ""
+
+msgid "Manage Git repositories with fine-grained access controls that keep your code secure. Perform code reviews and enhance collaboration with merge requests. Each project can also have an issue tracker and a wiki."
+msgstr ""
+
+msgid "Manage Web IDE features"
+msgstr ""
+
+msgid "Manage access"
+msgstr ""
+
+msgid "Manage all notifications"
+msgstr ""
+
+msgid "Manage applications that can use GitLab as an OAuth provider, and applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage applications that you've authorized to use your account."
+msgstr ""
+
+msgid "Manage group labels"
+msgstr ""
+
+msgid "Manage labels"
+msgstr ""
+
+msgid "Manage project labels"
+msgstr ""
+
+msgid "Manage your group’s membership while adding another level of security with SAML."
+msgstr ""
+
+msgid "Manifest"
+msgstr ""
+
+msgid "Manifest file import"
+msgstr ""
+
+msgid "Map a FogBugz account ID to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a GitLab user"
+msgstr ""
+
+msgid "Map a Google Code user to a full email address"
+msgstr ""
+
+msgid "Map a Google Code user to a full name"
+msgstr ""
+
+msgid "Mar"
+msgstr ""
+
+msgid "March"
+msgstr ""
+
+msgid "Mark todo as done"
+msgstr ""
+
+msgid "Markdown enabled"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
+msgid "Maven Metadata"
+msgstr ""
+
+msgid "Maven package"
+msgstr ""
+
+msgid "Max access level"
+msgstr ""
+
+msgid "Maximum job timeout"
+msgstr ""
+
+msgid "May"
+msgstr ""
+
+msgid "Median"
+msgstr ""
+
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
+msgid "Members"
+msgstr ""
+
+msgid "Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called \"SSO Service Location\", \"SAML Token Issuance Endpoint\", or \"SAML 2.0/W-Federation URL\"."
+msgstr ""
+
+msgid "Merge Request"
+msgstr ""
+
+msgid "Merge Request:"
+msgstr ""
+
+msgid "Merge Requests"
+msgstr ""
+
+msgid "Merge Requests created"
+msgstr ""
+
+msgid "Merge events"
+msgstr ""
+
+msgid "Merge request"
+msgstr ""
+
+msgid "Merge request approvals"
+msgstr ""
+
+msgid "Merge requests"
+msgstr ""
+
+msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
+msgstr ""
+
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
+msgid "MergeRequests|Resolve this discussion in a new issue"
+msgstr ""
+
+msgid "MergeRequests|Saving the comment failed"
+msgstr ""
+
+msgid "MergeRequests|Toggle comments for this file"
+msgstr ""
+
+msgid "MergeRequests|View file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequests|View replaced file @ %{commitId}"
+msgstr ""
+
+msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr ""
+
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
+msgid "Merged"
+msgstr ""
+
+msgid "Messages"
+msgstr ""
+
+msgid "Metrics"
+msgstr ""
+
+msgid "Metrics - Influx"
+msgstr ""
+
+msgid "Metrics - Prometheus"
+msgstr ""
+
+msgid "Metrics and profiling"
+msgstr ""
+
+msgid "Metrics|Business"
+msgstr ""
+
+msgid "Metrics|Check out the CI/CD documentation on deploying to an environment"
+msgstr ""
+
+msgid "Metrics|Create metric"
+msgstr ""
+
+msgid "Metrics|Edit metric"
+msgstr ""
+
+msgid "Metrics|Environment"
+msgstr ""
+
+msgid "Metrics|For grouping similar metrics"
+msgstr ""
+
+msgid "Metrics|Label of the chart's vertical axis. Usually the type of the unit being charted. The horizontal axis (X-axis) always represents time."
+msgstr ""
+
+msgid "Metrics|Learn about environments"
+msgstr ""
+
+msgid "Metrics|Legend label (optional)"
+msgstr ""
+
+msgid "Metrics|Must be a valid PromQL query."
+msgstr ""
+
+msgid "Metrics|Name"
+msgstr ""
+
+msgid "Metrics|New metric"
+msgstr ""
+
+msgid "Metrics|No deployed environments"
+msgstr ""
+
+msgid "Metrics|Prometheus Query Documentation"
+msgstr ""
+
+msgid "Metrics|Query"
+msgstr ""
+
+msgid "Metrics|Response"
+msgstr ""
+
+msgid "Metrics|System"
+msgstr ""
+
+msgid "Metrics|There was an error fetching the environments data, please try again"
+msgstr ""
+
+msgid "Metrics|There was an error getting deployment information."
+msgstr ""
+
+msgid "Metrics|There was an error getting environments information."
+msgstr ""
+
+msgid "Metrics|There was an error while retrieving metrics"
+msgstr ""
+
+msgid "Metrics|Type"
+msgstr ""
+
+msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
+msgstr ""
+
+msgid "Metrics|Unit label"
+msgstr ""
+
+msgid "Metrics|Used as a title for the chart"
+msgstr ""
+
+msgid "Metrics|Used if the query returns a single series. If it returns multiple series, their legend labels will be picked up from the response."
+msgstr ""
+
+msgid "Metrics|Y-axis label"
+msgstr ""
+
+msgid "Metrics|e.g. HTTP requests"
+msgstr ""
+
+msgid "Metrics|e.g. Requests/second"
+msgstr ""
+
+msgid "Metrics|e.g. Throughput"
+msgstr ""
+
+msgid "Metrics|e.g. rate(http_requests_total[5m])"
+msgstr ""
+
+msgid "Metrics|e.g. req/sec"
+msgstr ""
+
+msgid "Milestone"
+msgstr ""
+
+msgid "Milestone lists not available with your current license"
+msgstr ""
+
+msgid "Milestone lists show all issues from the selected milestone."
+msgstr ""
+
+msgid "Milestones"
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
+msgstr ""
+
+msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
+msgstr ""
+
+msgid "Milestones|Delete milestone"
+msgstr ""
+
+msgid "Milestones|Delete milestone %{milestoneTitle}?"
+msgstr ""
+
+msgid "Milestones|Failed to delete milestone %{milestoneTitle}"
+msgstr ""
+
+msgid "Milestones|Milestone %{milestoneTitle} was not found"
+msgstr ""
+
+msgid "Milestones|Promote %{milestoneTitle} to group milestone?"
+msgstr ""
+
+msgid "Milestones|Promote Milestone"
+msgstr ""
+
+msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
+msgstr ""
+
+msgid "Milestones|This action cannot be reversed."
+msgstr ""
+
+msgid "Mirror a repository"
+msgstr ""
+
+msgid "Mirror direction"
+msgstr ""
+
+msgid "Mirror repository"
+msgstr ""
+
+msgid "Mirror user"
+msgstr ""
+
+msgid "Mirrored repositories"
+msgstr ""
+
+msgid "Mirroring repositories"
+msgstr ""
+
+msgid "MissingSSHKeyWarningLink|add an SSH key"
+msgstr ""
+
+msgid "Modal|Cancel"
+msgstr ""
+
+msgid "Modal|Close"
+msgstr ""
+
+msgid "Monitoring"
+msgstr ""
+
+msgid "Months"
+msgstr ""
+
+msgid "More"
+msgstr ""
+
+msgid "More actions"
+msgstr ""
+
+msgid "More info"
+msgstr ""
+
+msgid "More information"
+msgstr ""
+
+msgid "More information is available|here"
+msgstr ""
+
+msgid "Most stars"
+msgstr ""
+
+msgid "Move"
+msgstr ""
+
+msgid "Move issue"
+msgstr ""
+
+msgid "Multiple issue boards"
+msgstr ""
+
+msgid "Name"
+msgstr ""
+
+msgid "Name new label"
+msgstr ""
+
+msgid "Name your individual key via a title"
+msgstr ""
+
+msgid "Name:"
+msgstr ""
+
+msgid "Naming, visibility"
+msgstr ""
+
+msgid "Nav|Help"
+msgstr ""
+
+msgid "Nav|Home"
+msgstr ""
+
+msgid "Nav|Sign In / Register"
+msgstr ""
+
+msgid "Nav|Sign out and sign in with a different account"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Never"
+msgstr ""
+
+msgid "New"
+msgstr ""
+
+msgid "New Application"
+msgstr ""
+
+msgid "New Group"
+msgstr ""
+
+msgid "New Identity"
+msgstr ""
+
+msgid "New Issue"
+msgid_plural "New Issues"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "New Label"
+msgstr ""
+
+msgid "New Pipeline Schedule"
+msgstr ""
+
+msgid "New Snippet"
+msgstr ""
+
+msgid "New Snippets"
+msgstr ""
+
+msgid "New branch"
+msgstr ""
+
+msgid "New branch unavailable"
+msgstr ""
+
+msgid "New directory"
+msgstr ""
+
+msgid "New epic"
+msgstr ""
+
+msgid "New file"
+msgstr ""
+
+msgid "New group"
+msgstr ""
+
+msgid "New identity"
+msgstr ""
+
+msgid "New issue"
+msgstr ""
+
+msgid "New label"
+msgstr ""
+
+msgid "New merge request"
+msgstr ""
+
+msgid "New pipelines will cancel older, pending pipelines on the same branch"
+msgstr ""
+
+msgid "New project"
+msgstr ""
+
+msgid "New schedule"
+msgstr ""
+
+msgid "New snippet"
+msgstr ""
+
+msgid "New subgroup"
+msgstr ""
+
+msgid "New tag"
+msgstr ""
+
+msgid "New..."
+msgstr ""
+
+msgid "No"
+msgstr ""
+
+msgid "No Label"
+msgstr ""
+
+msgid "No assignee"
+msgstr ""
+
+msgid "No branches found"
+msgstr ""
+
+msgid "No changes"
+msgstr ""
+
+msgid "No connection could be made to a Gitaly Server, please check your logs!"
+msgstr ""
+
+msgid "No container images stored for this project. Add one by following the instructions above."
+msgstr ""
+
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
+msgid "No due date"
+msgstr ""
+
+msgid "No estimate or time spent"
+msgstr ""
+
+msgid "No file chosen"
+msgstr ""
+
+msgid "No files found."
+msgstr ""
+
+msgid "No issues for the selected time period."
+msgstr ""
+
+msgid "No labels with such name or description"
+msgstr ""
+
+msgid "No license. All rights reserved"
+msgstr ""
+
+msgid "No merge requests for the selected time period."
+msgstr ""
+
+msgid "No merge requests found"
+msgstr ""
+
+msgid "No messages were logged"
+msgstr ""
+
+msgid "No other labels with such name or description"
+msgstr ""
+
+msgid "No packages stored for this project."
+msgstr ""
+
+msgid "No prioritised labels with such name or description"
+msgstr ""
+
+msgid "No public groups"
+msgstr ""
+
+msgid "No pushes for the selected time period."
+msgstr ""
+
+msgid "No repository"
+msgstr ""
+
+msgid "No runners found"
+msgstr ""
+
+msgid "No schedules"
+msgstr ""
+
+msgid "No, directly import the existing email addresses and usernames."
+msgstr ""
+
+msgid "Nodes"
+msgstr ""
+
+msgid "None"
+msgstr ""
+
+msgid "Not all comments are displayed because you're comparing two versions of the diff."
+msgstr ""
+
+msgid "Not all comments are displayed because you're viewing an old version of the diff."
+msgstr ""
+
+msgid "Not allowed to merge"
+msgstr ""
+
+msgid "Not available"
+msgstr ""
+
+msgid "Not available for private projects"
+msgstr ""
+
+msgid "Not available for protected branches"
+msgstr ""
+
+msgid "Not confidential"
+msgstr ""
+
+msgid "Not enough data"
+msgstr ""
+
+msgid "Not now"
+msgstr ""
+
+msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: As an administrator you may like to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow connecting repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Note: Consider asking your GitLab administrator to configure %{github_integration_link}, which will allow login via GitHub and allow importing repositories without generating a Personal Access Token."
+msgstr ""
+
+msgid "Notes|Are you sure you want to cancel creating this comment?"
+msgstr ""
+
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
+msgid "Notification events"
+msgstr ""
+
+msgid "NotificationEvent|Close issue"
+msgstr ""
+
+msgid "NotificationEvent|Close merge request"
+msgstr ""
+
+msgid "NotificationEvent|Failed pipeline"
+msgstr ""
+
+msgid "NotificationEvent|Merge merge request"
+msgstr ""
+
+msgid "NotificationEvent|New epic"
+msgstr ""
+
+msgid "NotificationEvent|New issue"
+msgstr ""
+
+msgid "NotificationEvent|New merge request"
+msgstr ""
+
+msgid "NotificationEvent|New note"
+msgstr ""
+
+msgid "NotificationEvent|Reassign issue"
+msgstr ""
+
+msgid "NotificationEvent|Reassign merge request"
+msgstr ""
+
+msgid "NotificationEvent|Reopen issue"
+msgstr ""
+
+msgid "NotificationEvent|Successful pipeline"
+msgstr ""
+
+msgid "NotificationLevel|Custom"
+msgstr ""
+
+msgid "NotificationLevel|Disabled"
+msgstr ""
+
+msgid "NotificationLevel|Global"
+msgstr ""
+
+msgid "NotificationLevel|On mention"
+msgstr ""
+
+msgid "NotificationLevel|Participate"
+msgstr ""
+
+msgid "NotificationLevel|Watch"
+msgstr ""
+
+msgid "Notifications"
+msgstr ""
+
+msgid "Notifications off"
+msgstr ""
+
+msgid "Notifications on"
+msgstr ""
+
+msgid "Nov"
+msgstr ""
+
+msgid "November"
+msgstr ""
+
+msgid "OK"
+msgstr ""
+
+msgid "Oct"
+msgstr ""
+
+msgid "October"
+msgstr ""
+
+msgid "OfSearchInADropdown|Filter"
+msgstr ""
+
+msgid "Once imported, repositories can be mirrored over SSH. Read more %{ssh_link}"
+msgstr ""
+
+msgid "One more item"
+msgid_plural "%d more items"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
+msgstr ""
+
+msgid "Only admins"
+msgstr ""
+
+msgid "Only comments from the following commit are shown below"
+msgstr ""
+
+msgid "Only mirror protected branches"
+msgstr ""
+
+msgid "Only project members can comment."
+msgstr ""
+
+msgid "Oops, are you sure?"
+msgstr ""
+
+msgid "Open"
+msgstr ""
+
+msgid "Open in Xcode"
+msgstr ""
+
+msgid "Open projects"
+msgstr ""
+
+msgid "Open sidebar"
+msgstr ""
+
+msgid "Open source software to collaborate on code"
+msgstr ""
+
+msgid "Opened"
+msgstr ""
+
+msgid "Opened MR"
+msgstr ""
+
+msgid "Opened issues"
+msgstr ""
+
+msgid "OpenedNDaysAgo|Opened"
+msgstr ""
+
+msgid "Opens in a new window"
+msgstr ""
+
+msgid "Operations"
+msgstr ""
+
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Optionally, you can %{link_to_customize} how Google Code email addresses and usernames are imported into GitLab."
+msgstr ""
+
+msgid "Options"
+msgstr ""
+
+msgid "Or you can choose one of the suggested colors below"
+msgstr ""
+
+msgid "Other Labels"
+msgstr ""
+
+msgid "Other information"
+msgstr ""
+
+msgid "Otherwise it is recommended you start with one of the options below."
+msgstr ""
+
+msgid "Outbound requests"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "Overwrite diverged branches"
+msgstr ""
+
+msgid "Owner"
+msgstr ""
+
+msgid "Package information"
+msgstr ""
+
+msgid "Package was removed"
+msgstr ""
+
+msgid "Packages"
+msgstr ""
+
+msgid "Pages"
+msgstr ""
+
+msgid "Pagination|Last »"
+msgstr ""
+
+msgid "Pagination|Next"
+msgstr ""
+
+msgid "Pagination|Prev"
+msgstr ""
+
+msgid "Pagination|« First"
+msgstr ""
+
+msgid "Part of merge request changes"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
+msgstr ""
+
+msgid "Path, transfer, remove"
+msgstr ""
+
+msgid "Path:"
+msgstr ""
+
+msgid "Pause"
+msgstr ""
+
+msgid "Paused Runners don't accept new jobs"
+msgstr ""
+
+msgid "Pending"
+msgstr ""
+
+msgid "People without permission will never get a notification and won't be able to comment."
+msgstr ""
+
+msgid "Per job. If a job passes this threshold, it will be marked as failed"
+msgstr ""
+
+msgid "Perform advanced options such as changing path, transferring, or removing the group."
+msgstr ""
+
+msgid "Performance optimization"
+msgstr ""
+
+msgid "Permissions"
+msgstr ""
+
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
+msgid "Personal Access Token"
+msgstr ""
+
+msgid "Pipeline"
+msgstr ""
+
+msgid "Pipeline Health"
+msgstr ""
+
+msgid "Pipeline Schedule"
+msgstr ""
+
+msgid "Pipeline Schedules"
+msgstr ""
+
+msgid "Pipeline quota"
+msgstr ""
+
+msgid "Pipeline triggers"
+msgstr ""
+
+msgid "PipelineCharts|Failed:"
+msgstr ""
+
+msgid "PipelineCharts|Overall statistics"
+msgstr ""
+
+msgid "PipelineCharts|Success ratio:"
+msgstr ""
+
+msgid "PipelineCharts|Successful:"
+msgstr ""
+
+msgid "PipelineCharts|Total:"
+msgstr ""
+
+msgid "PipelineSchedules|Activated"
+msgstr ""
+
+msgid "PipelineSchedules|Active"
+msgstr ""
+
+msgid "PipelineSchedules|All"
+msgstr ""
+
+msgid "PipelineSchedules|Inactive"
+msgstr ""
+
+msgid "PipelineSchedules|Next Run"
+msgstr ""
+
+msgid "PipelineSchedules|None"
+msgstr ""
+
+msgid "PipelineSchedules|Provide a short description for this pipeline"
+msgstr ""
+
+msgid "PipelineSchedules|Take ownership"
+msgstr ""
+
+msgid "PipelineSchedules|Target"
+msgstr ""
+
+msgid "PipelineSchedules|Variables"
+msgstr ""
+
+msgid "PipelineSheduleIntervalPattern|Custom"
+msgstr ""
+
+msgid "Pipelines"
+msgstr ""
+
+msgid "Pipelines charts"
+msgstr ""
+
+msgid "Pipelines for last month"
+msgstr ""
+
+msgid "Pipelines for last week"
+msgstr ""
+
+msgid "Pipelines for last year"
+msgstr ""
+
+msgid "Pipelines|Build with confidence"
+msgstr ""
+
+msgid "Pipelines|CI Lint"
+msgstr ""
+
+msgid "Pipelines|Clear Runner Caches"
+msgstr ""
+
+msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
+msgstr ""
+
+msgid "Pipelines|Get started with Pipelines"
+msgstr ""
+
+msgid "Pipelines|Loading Pipelines"
+msgstr ""
+
+msgid "Pipelines|Project cache successfully reset."
+msgstr ""
+
+msgid "Pipelines|Run Pipeline"
+msgstr ""
+
+msgid "Pipelines|Something went wrong while cleaning runners cache."
+msgstr ""
+
+msgid "Pipelines|There are currently no %{scope} pipelines."
+msgstr ""
+
+msgid "Pipelines|There are currently no pipelines."
+msgstr ""
+
+msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
+msgstr ""
+
+msgid "Pipelines|This project is not currently set up to run pipelines."
+msgstr ""
+
+msgid "Pipeline|Commit"
+msgstr ""
+
+msgid "Pipeline|Create for"
+msgstr ""
+
+msgid "Pipeline|Create pipeline"
+msgstr ""
+
+msgid "Pipeline|Duration"
+msgstr ""
+
+msgid "Pipeline|Existing branch name or tag"
+msgstr ""
+
+msgid "Pipeline|Pipeline"
+msgstr ""
+
+msgid "Pipeline|Run Pipeline"
+msgstr ""
+
+msgid "Pipeline|Search branches"
+msgstr ""
+
+msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
+msgstr ""
+
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline"
+msgstr ""
+
+msgid "Pipeline|Stop pipeline #%{pipelineId}?"
+msgstr ""
+
+msgid "Pipeline|Variables"
+msgstr ""
+
+msgid "Pipeline|You’re about to stop pipeline %{pipelineId}."
+msgstr ""
+
+msgid "Pipeline|all"
+msgstr ""
+
+msgid "Pipeline|success"
+msgstr ""
+
+msgid "Pipeline|with stage"
+msgstr ""
+
+msgid "Pipeline|with stages"
+msgstr ""
+
+msgid "Plain diff"
+msgstr ""
+
+msgid "PlantUML"
+msgstr ""
+
+msgid "Play"
+msgstr ""
+
+msgid "Please accept the Terms of Service before continuing."
+msgstr ""
+
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
+msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
+msgstr ""
+
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
+msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
+msgstr ""
+
+msgid "Please select at least one filter to see results"
+msgstr ""
+
+msgid "Please solve the reCAPTCHA"
+msgstr ""
+
+msgid "Please try again"
+msgstr ""
+
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
+msgid "Please wait while we connect to your repository. Refresh at will."
+msgstr ""
+
+msgid "Please wait while we import the repository for you. Refresh at will."
+msgstr ""
+
+msgid "Preferences"
+msgstr ""
+
+msgid "Preferences|Navigation theme"
+msgstr ""
+
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
+msgid "Preview"
+msgstr ""
+
+msgid "Preview payload"
+msgstr ""
+
+msgid "Primary"
+msgstr ""
+
+msgid "Prioritize"
+msgstr ""
+
+msgid "Prioritize label"
+msgstr ""
+
+msgid "Prioritized Labels"
+msgstr ""
+
+msgid "Prioritized label"
+msgstr ""
+
+msgid "Private - Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Private - The group and its projects can only be viewed by members."
+msgstr ""
+
+msgid "Private projects can be created in your personal namespace with:"
+msgstr ""
+
+msgid "Profile"
+msgstr ""
+
+msgid "Profile Settings"
+msgstr ""
+
+msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
+msgstr ""
+
+msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
+msgstr ""
+
+msgid "Profiles|Account scheduled for removal."
+msgstr ""
+
+msgid "Profiles|Add key"
+msgstr ""
+
+msgid "Profiles|Add status emoji"
+msgstr ""
+
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
+msgid "Profiles|Change username"
+msgstr ""
+
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
+msgid "Profiles|Clear status"
+msgstr ""
+
+msgid "Profiles|Current path: %{path}"
+msgstr ""
+
+msgid "Profiles|Current status"
+msgstr ""
+
+msgid "Profiles|Delete Account"
+msgstr ""
+
+msgid "Profiles|Delete account"
+msgstr ""
+
+msgid "Profiles|Delete your account?"
+msgstr ""
+
+msgid "Profiles|Deleting an account has the following effects:"
+msgstr ""
+
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
+msgid "Profiles|Invalid password"
+msgstr ""
+
+msgid "Profiles|Invalid username"
+msgstr ""
+
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
+msgid "Profiles|Path"
+msgstr ""
+
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
+msgstr ""
+
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr ""
+
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
+msgid "Profiles|Type your %{confirmationValue} to confirm:"
+msgstr ""
+
+msgid "Profiles|Typically starts with \"ssh-rsa …\""
+msgstr ""
+
+msgid "Profiles|Update profile settings"
+msgstr ""
+
+msgid "Profiles|Update username"
+msgstr ""
+
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
+msgid "Profiles|Username change failed - %{message}"
+msgstr ""
+
+msgid "Profiles|Username successfully changed"
+msgstr ""
+
+msgid "Profiles|Website"
+msgstr ""
+
+msgid "Profiles|What's your status?"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You don't have access to delete this user."
+msgstr ""
+
+msgid "Profiles|You must transfer ownership or delete these groups before you can delete your account."
+msgstr ""
+
+msgid "Profiles|Your account is currently an owner in these groups:"
+msgstr ""
+
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
+msgid "Profiles|Your status"
+msgstr ""
+
+msgid "Profiles|e.g. My MacBook key"
+msgstr ""
+
+msgid "Profiles|your account"
+msgstr ""
+
+msgid "Profiling - Performance bar"
+msgstr ""
+
+msgid "Programming languages used in this repository"
+msgstr ""
+
+msgid "Progress"
+msgstr ""
+
+msgid "Project"
+msgstr ""
+
+msgid "Project '%{project_name}' is in the process of being deleted."
+msgstr ""
+
+msgid "Project '%{project_name}' queued for deletion."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully created."
+msgstr ""
+
+msgid "Project '%{project_name}' was successfully updated."
+msgstr ""
+
+msgid "Project Badges"
+msgstr ""
+
+msgid "Project URL"
+msgstr ""
+
+msgid "Project access must be granted explicitly to each user."
+msgstr ""
+
+msgid "Project avatar"
+msgstr ""
+
+msgid "Project avatar in repository: %{link}"
+msgstr ""
+
+msgid "Project details"
+msgstr ""
+
+msgid "Project export could not be deleted."
+msgstr ""
+
+msgid "Project export has been deleted."
+msgstr ""
+
+msgid "Project export link has expired. Please generate a new export from your project settings."
+msgstr ""
+
+msgid "Project export started. A download link will be sent by email."
+msgstr ""
+
+msgid "Project name"
+msgstr ""
+
+msgid "Project slug"
+msgstr ""
+
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
+msgid "ProjectCreationLevel|Allowed to create projects"
+msgstr ""
+
+msgid "ProjectCreationLevel|Default project creation protection"
+msgstr ""
+
+msgid "ProjectCreationLevel|Developers + Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|Maintainers"
+msgstr ""
+
+msgid "ProjectCreationLevel|No one"
+msgstr ""
+
+msgid "ProjectFileTree|Name"
+msgstr ""
+
+msgid "ProjectLastActivity|Never"
+msgstr ""
+
+msgid "ProjectLifecycle|Stage"
+msgstr ""
+
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
+msgid "ProjectPage|Project ID: %{project_id}"
+msgstr ""
+
+msgid "ProjectSettings|Badges"
+msgstr ""
+
+msgid "ProjectSettings|Contact an admin to change this setting."
+msgstr ""
+
+msgid "ProjectSettings|Customize your project badges."
+msgstr ""
+
+msgid "ProjectSettings|Failed to protect the tag"
+msgstr ""
+
+msgid "ProjectSettings|Failed to update tag!"
+msgstr ""
+
+msgid "ProjectSettings|Learn more about badges."
+msgstr ""
+
+msgid "ProjectSettings|Only signed commits can be pushed to this repository."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level and can be overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|This setting is applied on the server level but has been overridden for this project."
+msgstr ""
+
+msgid "ProjectSettings|This setting will be applied to all projects unless overridden by an admin."
+msgstr ""
+
+msgid "ProjectSettings|Users can only push commits to this repository that were committed with one of their own verified emails."
+msgstr ""
+
+msgid "Projects"
+msgstr ""
+
+msgid "Projects shared with %{group_name}"
+msgstr ""
+
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
+msgid "ProjectsDropdown|Frequently visited"
+msgstr ""
+
+msgid "ProjectsDropdown|Loading projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Projects you visit often will appear here"
+msgstr ""
+
+msgid "ProjectsDropdown|Search your projects"
+msgstr ""
+
+msgid "ProjectsDropdown|Something went wrong on our end."
+msgstr ""
+
+msgid "ProjectsDropdown|Sorry, no projects matched your search"
+msgstr ""
+
+msgid "ProjectsDropdown|This feature requires browser localStorage support"
+msgstr ""
+
+msgid "PrometheusAlerts|Add alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Edit alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error creating alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error deleting alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error fetching alert"
+msgstr ""
+
+msgid "PrometheusAlerts|Error saving alert"
+msgstr ""
+
+msgid "PrometheusAlerts|No alert set"
+msgstr ""
+
+msgid "PrometheusAlerts|Operator"
+msgstr ""
+
+msgid "PrometheusAlerts|Threshold"
+msgstr ""
+
+msgid "PrometheusDashboard|Time"
+msgstr ""
+
+msgid "PrometheusService|%{exporters} with %{metrics} were found"
+msgstr ""
+
+msgid "PrometheusService|<p class=\"text-tertiary\">No <a href=\"%{docsUrl}\">common metrics</a> were found</p>"
+msgstr ""
+
+msgid "PrometheusService|Active"
+msgstr ""
+
+msgid "PrometheusService|Auto configuration"
+msgstr ""
+
+msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
+msgstr ""
+
+msgid "PrometheusService|Common metrics"
+msgstr ""
+
+msgid "PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters."
+msgstr ""
+
+msgid "PrometheusService|Custom metrics"
+msgstr ""
+
+msgid "PrometheusService|Finding and configuring metrics..."
+msgstr ""
+
+msgid "PrometheusService|Finding custom metrics..."
+msgstr ""
+
+msgid "PrometheusService|Install Prometheus on clusters"
+msgstr ""
+
+msgid "PrometheusService|Manage clusters"
+msgstr ""
+
+msgid "PrometheusService|Manual configuration"
+msgstr ""
+
+msgid "PrometheusService|Metrics"
+msgstr ""
+
+msgid "PrometheusService|Missing environment variable"
+msgstr ""
+
+msgid "PrometheusService|More information"
+msgstr ""
+
+msgid "PrometheusService|New metric"
+msgstr ""
+
+msgid "PrometheusService|Prometheus API Base URL, like http://prometheus.example.com/"
+msgstr ""
+
+msgid "PrometheusService|Prometheus is being automatically managed on your clusters"
+msgstr ""
+
+msgid "PrometheusService|These metrics will only be monitored after your first deployment to an environment"
+msgstr ""
+
+msgid "PrometheusService|Time-series monitoring service"
+msgstr ""
+
+msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
+msgstr ""
+
+msgid "PrometheusService|To enable the installation of Prometheus on your clusters, deactivate the manual configuration below"
+msgstr ""
+
+msgid "PrometheusService|Waiting for your first deployment to an environment to find common metrics"
+msgstr ""
+
+msgid "Promote"
+msgstr ""
+
+msgid "Promote these project milestones into a group milestone."
+msgstr ""
+
+msgid "Promote to Group Milestone"
+msgstr ""
+
+msgid "Promote to group label"
+msgstr ""
+
+msgid "Promotions|Don't show me this again"
+msgstr ""
+
+msgid "Promotions|Epics let you manage your portfolio of projects more efficiently and with less effort by tracking groups of issues that share a theme, across projects and milestones."
+msgstr ""
+
+msgid "Promotions|This feature is locked."
+msgstr ""
+
+msgid "Promotions|Upgrade plan"
+msgstr ""
+
+msgid "Protected"
+msgstr ""
+
+msgid "Protected Environments"
+msgstr ""
+
+msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
+msgstr ""
+
+msgid "ProtectedEnvironment|Allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Choose who is allowed to deploy"
+msgstr ""
+
+msgid "ProtectedEnvironment|Environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
+msgstr ""
+
+msgid "ProtectedEnvironment|Protect an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
+msgstr ""
+
+msgid "ProtectedEnvironment|Select an environment"
+msgstr ""
+
+msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
+msgstr ""
+
+msgid "ProtectedEnvironment|Unprotect"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment can't be unprotected"
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been protected."
+msgstr ""
+
+msgid "ProtectedEnvironment|Your environment has been unprotected"
+msgstr ""
+
+msgid "Protip:"
+msgstr ""
+
+msgid "Provider"
+msgstr ""
+
+msgid "Pseudonymizer data collection"
+msgstr ""
+
+msgid "Public - The group and any public projects can be viewed without any authentication."
+msgstr ""
+
+msgid "Public - The project can be accessed without any authentication."
+msgstr ""
+
+msgid "Public pipelines"
+msgstr ""
+
+msgid "Pull"
+msgstr ""
+
+msgid "Push"
+msgstr ""
+
+msgid "Push Rules"
+msgstr ""
+
+msgid "Push events"
+msgstr ""
+
+msgid "Push project from command line"
+msgstr ""
+
+msgid "Push to create a project"
+msgstr ""
+
+msgid "PushRule|Committer restriction"
+msgstr ""
+
+msgid "Pushed"
+msgstr ""
+
+msgid "Pushes"
+msgstr ""
+
+msgid "Quarters"
+msgstr ""
+
+msgid "Quick actions can be used in the issues description and comment boxes."
+msgstr ""
+
+msgid "Read more"
+msgstr ""
+
+msgid "Read more about project permissions <strong>%{link_to_help}</strong>"
+msgstr ""
+
+msgid "Readme"
+msgstr ""
+
+msgid "Real-time features"
+msgstr ""
+
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
+msgid "Reference:"
+msgstr ""
+
+msgid "Refresh"
+msgstr ""
+
+msgid "Refreshing in a second to show the updated status..."
+msgid_plural "Refreshing in %d seconds to show the updated status..."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Regenerate key"
+msgstr ""
+
+msgid "Regex pattern"
+msgstr ""
+
+msgid "Register / Sign In"
+msgstr ""
+
+msgid "Register and see your runners for this group."
+msgstr ""
+
+msgid "Register and see your runners for this project."
+msgstr ""
+
+msgid "Registry"
+msgstr ""
+
+msgid "Related Commits"
+msgstr ""
+
+msgid "Related Deployed Jobs"
+msgstr ""
+
+msgid "Related Issues"
+msgstr ""
+
+msgid "Related Jobs"
+msgstr ""
+
+msgid "Related Merge Requests"
+msgstr ""
+
+msgid "Related Merged Requests"
+msgstr ""
+
+msgid "Related merge requests"
+msgstr ""
+
+msgid "Remind later"
+msgstr ""
+
+msgid "Remove"
+msgstr ""
+
+msgid "Remove Runner"
+msgstr ""
+
+msgid "Remove avatar"
+msgstr ""
+
+msgid "Remove group"
+msgstr ""
+
+msgid "Remove priority"
+msgstr ""
+
+msgid "Remove project"
+msgstr ""
+
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
+msgid "Rename"
+msgstr ""
+
+msgid "Rename file"
+msgstr ""
+
+msgid "Rename folder"
+msgstr ""
+
+msgid "Reopen epic"
+msgstr ""
+
+msgid "Repair authentication"
+msgstr ""
+
+msgid "Reply to this email directly or %{view_it_on_gitlab}."
+msgstr ""
+
+msgid "Repo by URL"
+msgstr ""
+
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
+msgid "Reports|%{failedString} and %{resolvedString}"
+msgstr ""
+
+msgid "Reports|Actions"
+msgstr ""
+
+msgid "Reports|Class"
+msgstr ""
+
+msgid "Reports|Confidence"
+msgstr ""
+
+msgid "Reports|Execution time"
+msgstr ""
+
+msgid "Reports|Failure"
+msgstr ""
+
+msgid "Reports|Severity"
+msgstr ""
+
+msgid "Reports|System output"
+msgstr ""
+
+msgid "Reports|Test summary"
+msgstr ""
+
+msgid "Reports|Test summary failed loading results"
+msgstr ""
+
+msgid "Reports|Test summary results are being parsed"
+msgstr ""
+
+msgid "Reports|Vulnerability"
+msgstr ""
+
+msgid "Reports|no changed test results"
+msgstr ""
+
+msgid "Repository"
+msgstr ""
+
+msgid "Repository Settings"
+msgstr ""
+
+msgid "Repository URL"
+msgstr ""
+
+msgid "Repository has no locks."
+msgstr ""
+
+msgid "Repository maintenance"
+msgstr ""
+
+msgid "Repository mirror"
+msgstr ""
+
+msgid "Repository storage"
+msgstr ""
+
+msgid "RepositorySettingsAccessLevel|Select"
+msgstr ""
+
+msgid "Request Access"
+msgstr ""
+
+msgid "Requests Profiles"
+msgstr ""
+
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
+msgid "Resolve all discussions in new issue"
+msgstr ""
+
+msgid "Resolve conflicts on source branch"
+msgstr ""
+
+msgid "Resolve discussion"
+msgstr ""
+
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
+msgid "Response metrics (Custom)"
+msgstr ""
+
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
+msgid "Resume"
+msgstr ""
+
+msgid "Retry"
+msgstr ""
+
+msgid "Retry this job"
+msgstr ""
+
+msgid "Retry verification"
+msgstr ""
+
+msgid "Reveal Variables"
+msgstr ""
+
+msgid "Reveal value"
+msgid_plural "Reveal values"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Revert this commit"
+msgstr ""
+
+msgid "Revert this merge request"
+msgstr ""
+
+msgid "Review"
+msgstr ""
+
+msgid "Review the process for configuring service providers in your identity provider — in this case, GitLab is the \"service provider\" or \"relying party\"."
+msgstr ""
+
+msgid "Reviewing"
+msgstr ""
+
+msgid "Reviewing (merge request !%{mergeRequestId})"
+msgstr ""
+
+msgid "Revoke"
+msgstr ""
+
+msgid "Roadmap"
+msgstr ""
+
+msgid "Run CI/CD pipelines for external repositories"
+msgstr ""
+
+msgid "Run untagged jobs"
+msgstr ""
+
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
+msgid "Runner token"
+msgstr ""
+
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
+msgid "Runners"
+msgstr ""
+
+msgid "Runners API"
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, and even on your local machine."
+msgstr ""
+
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
+msgid "Runners page"
+msgstr ""
+
+msgid "Runners page."
+msgstr ""
+
+msgid "Runners|You have used all your shared Runners pipeline minutes."
+msgstr ""
+
+msgid "Running"
+msgstr ""
+
+msgid "SAML SSO"
+msgstr ""
+
+msgid "SAML SSO for %{group_name}"
+msgstr ""
+
+msgid "SAML Single Sign On"
+msgstr ""
+
+msgid "SAML Single Sign On Settings"
+msgstr ""
+
+msgid "SAST"
+msgstr ""
+
+msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
+msgstr ""
+
+msgid "SSH Keys"
+msgstr ""
+
+msgid "SSH host keys"
+msgstr ""
+
+msgid "SSH public key"
+msgstr ""
+
+msgid "SSL Verification"
+msgstr ""
+
+msgid "Save"
+msgstr ""
+
+msgid "Save application"
+msgstr ""
+
+msgid "Save changes"
+msgstr ""
+
+msgid "Save changes before testing"
+msgstr ""
+
+msgid "Save pipeline schedule"
+msgstr ""
+
+msgid "Save variables"
+msgstr ""
+
+msgid "Schedule a new pipeline"
+msgstr ""
+
+msgid "Scheduled"
+msgstr ""
+
+msgid "Schedules"
+msgstr ""
+
+msgid "Scheduling Pipelines"
+msgstr ""
+
+msgid "Scope"
+msgstr ""
+
+msgid "Scoped issue boards"
+msgstr ""
+
+msgid "Scroll down to <strong>Google Code Project Hosting</strong> and enable the switch on the right."
+msgstr ""
+
+msgid "Scroll to bottom"
+msgstr ""
+
+msgid "Scroll to top"
+msgstr ""
+
+msgid "Search"
+msgstr ""
+
+msgid "Search branches"
+msgstr ""
+
+msgid "Search branches and tags"
+msgstr ""
+
+msgid "Search files"
+msgstr ""
+
+msgid "Search for projects, issues, etc."
+msgstr ""
+
+msgid "Search merge requests"
+msgstr ""
+
+msgid "Search milestones"
+msgstr ""
+
+msgid "Search or filter results..."
+msgstr ""
+
+msgid "Search or jump to…"
+msgstr ""
+
+msgid "Search project"
+msgstr ""
+
+msgid "Search projects"
+msgstr ""
+
+msgid "Search users"
+msgstr ""
+
+msgid "Search your projects"
+msgstr ""
+
+msgid "SearchAutocomplete|All GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Issues assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests I've created"
+msgstr ""
+
+msgid "SearchAutocomplete|Merge requests assigned to me"
+msgstr ""
+
+msgid "SearchAutocomplete|in all GitLab"
+msgstr ""
+
+msgid "SearchAutocomplete|in this group"
+msgstr ""
+
+msgid "SearchAutocomplete|in this project"
+msgstr ""
+
+msgid "Secret"
+msgstr ""
+
+msgid "Security"
+msgstr ""
+
+msgid "Security Dashboard"
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr ""
+
+msgid "SecurityDashboard|Monitor vulnerabilities in your code"
+msgstr ""
+
+msgid "SecurityDashboard|Pipeline %{pipelineLink} triggered"
+msgstr ""
+
+msgid "Select"
+msgstr ""
+
+msgid "Select Archive Format"
+msgstr ""
+
+msgid "Select a group to invite"
+msgstr ""
+
+msgid "Select a namespace to fork the project"
+msgstr ""
+
+msgid "Select a template repository"
+msgstr ""
+
+msgid "Select a timezone"
+msgstr ""
+
+msgid "Select an existing Kubernetes cluster or create a new one"
+msgstr ""
+
+msgid "Select assignee"
+msgstr ""
+
+msgid "Select branch/tag"
+msgstr ""
+
+msgid "Select project"
+msgstr ""
+
+msgid "Select project and zone to choose machine type"
+msgstr ""
+
+msgid "Select project to choose zone"
+msgstr ""
+
+msgid "Select projects you want to import."
+msgstr ""
+
+msgid "Select source branch"
+msgstr ""
+
+msgid "Select target branch"
+msgstr ""
+
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
+msgid "Select the custom project template source group."
+msgstr ""
+
+msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
+msgstr ""
+
+msgid "Selective synchronization"
+msgstr ""
+
+msgid "Send email"
+msgstr ""
+
+msgid "Send usage data"
+msgstr ""
+
+msgid "Sep"
+msgstr ""
+
+msgid "September"
+msgstr ""
+
+msgid "Server version"
+msgstr ""
+
+msgid "Service Desk"
+msgstr ""
+
+msgid "Service Templates"
+msgstr ""
+
+msgid "Service URL"
+msgstr ""
+
+msgid "Session expiration, projects limit and attachment size."
+msgstr ""
+
+msgid "Set a password on your account to pull or push via %{protocol}."
+msgstr ""
+
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
+msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
+msgstr ""
+
+msgid "Set instance-wide template repository"
+msgstr ""
+
+msgid "Set max session time for web terminal."
+msgstr ""
+
+msgid "Set notification email for abuse reports."
+msgstr ""
+
+msgid "Set requirements for a user to sign-in. Enable mandatory two-factor authentication."
+msgstr ""
+
+msgid "Set up CI/CD"
+msgstr ""
+
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
+
+msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
+msgstr ""
+
+msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
+msgstr ""
+
+msgid "SetPasswordToCloneLink|set a password"
+msgstr ""
+
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
+
+msgid "SetStatusModal|Clear status"
+msgstr ""
+
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr ""
+
+msgid "Share"
+msgstr ""
+
+msgid "Share the <strong>%{sso_label}</strong> with members so they can sign in to your group through your identity provider"
+msgstr ""
+
+msgid "Shared Runners"
+msgstr ""
+
+msgid "Shared projects"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset pipeline minutes"
+msgstr ""
+
+msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
+msgstr ""
+
+msgid "Sherlock Transactions"
+msgstr ""
+
+msgid "Show command"
+msgstr ""
+
+msgid "Show complete raw log"
+msgstr ""
+
+msgid "Show latest version"
+msgstr ""
+
+msgid "Show latest version of the diff"
+msgstr ""
+
+msgid "Show parent pages"
+msgstr ""
+
+msgid "Show parent subgroups"
+msgstr ""
+
+msgid "Show whitespace changes"
+msgstr ""
+
+msgid "Showing %d event"
+msgid_plural "Showing %d events"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Side-by-side"
+msgstr ""
+
+msgid "Sidebar|Change weight"
+msgstr ""
+
+msgid "Sidebar|None"
+msgstr ""
+
+msgid "Sidebar|Only numeral characters allowed"
+msgstr ""
+
+msgid "Sidebar|Weight"
+msgstr ""
+
+msgid "Sign in"
+msgstr ""
+
+msgid "Sign in / Register"
+msgstr ""
+
+msgid "Sign in to %{group_name}"
+msgstr ""
+
+msgid "Sign in with Single Sign-On"
+msgstr ""
+
+msgid "Sign out"
+msgstr ""
+
+msgid "Sign-in restrictions"
+msgstr ""
+
+msgid "Sign-up restrictions"
+msgstr ""
+
+msgid "Size"
+msgstr ""
+
+msgid "Size and domain settings for static websites"
+msgstr ""
+
+msgid "Slack application"
+msgstr ""
+
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr ""
+
+msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
+msgstr ""
+
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
+msgid "Snippets"
+msgstr ""
+
+msgid "Something went wrong on our end"
+msgstr ""
+
+msgid "Something went wrong on our end."
+msgstr ""
+
+msgid "Something went wrong on our end. Please try again!"
+msgstr ""
+
+msgid "Something went wrong trying to change the confidentiality of this issue"
+msgstr ""
+
+msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
+msgstr ""
+
+msgid "Something went wrong when toggling the button"
+msgstr ""
+
+msgid "Something went wrong while closing the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while fetching %{listType} list"
+msgstr ""
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching group member contributions"
+msgstr ""
+
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
+msgid "Something went wrong while fetching the projects."
+msgstr ""
+
+msgid "Something went wrong while fetching the registry list."
+msgstr ""
+
+msgid "Something went wrong while reopening the %{issuable}. Please try again later"
+msgstr ""
+
+msgid "Something went wrong while resolving this discussion. Please try again."
+msgstr ""
+
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
+msgid "Something went wrong. Please try again."
+msgstr ""
+
+msgid "Sorry, no epics matched your search"
+msgstr ""
+
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
+msgid "Sort by"
+msgstr ""
+
+msgid "SortOptions|Access level, ascending"
+msgstr ""
+
+msgid "SortOptions|Access level, descending"
+msgstr ""
+
+msgid "SortOptions|Created date"
+msgstr ""
+
+msgid "SortOptions|Due date"
+msgstr ""
+
+msgid "SortOptions|Due later"
+msgstr ""
+
+msgid "SortOptions|Due soon"
+msgstr ""
+
+msgid "SortOptions|Label priority"
+msgstr ""
+
+msgid "SortOptions|Largest group"
+msgstr ""
+
+msgid "SortOptions|Largest repository"
+msgstr ""
+
+msgid "SortOptions|Last Contact"
+msgstr ""
+
+msgid "SortOptions|Last created"
+msgstr ""
+
+msgid "SortOptions|Last joined"
+msgstr ""
+
+msgid "SortOptions|Last updated"
+msgstr ""
+
+msgid "SortOptions|Least popular"
+msgstr ""
+
+msgid "SortOptions|Less weight"
+msgstr ""
+
+msgid "SortOptions|Milestone"
+msgstr ""
+
+msgid "SortOptions|Milestone due later"
+msgstr ""
+
+msgid "SortOptions|Milestone due soon"
+msgstr ""
+
+msgid "SortOptions|More weight"
+msgstr ""
+
+msgid "SortOptions|Most popular"
+msgstr ""
+
+msgid "SortOptions|Most stars"
+msgstr ""
+
+msgid "SortOptions|Name"
+msgstr ""
+
+msgid "SortOptions|Name, ascending"
+msgstr ""
+
+msgid "SortOptions|Name, descending"
+msgstr ""
+
+msgid "SortOptions|Oldest created"
+msgstr ""
+
+msgid "SortOptions|Oldest joined"
+msgstr ""
+
+msgid "SortOptions|Oldest sign in"
+msgstr ""
+
+msgid "SortOptions|Oldest updated"
+msgstr ""
+
+msgid "SortOptions|Popularity"
+msgstr ""
+
+msgid "SortOptions|Priority"
+msgstr ""
+
+msgid "SortOptions|Recent sign in"
+msgstr ""
+
+msgid "SortOptions|Start date"
+msgstr ""
+
+msgid "SortOptions|Start later"
+msgstr ""
+
+msgid "SortOptions|Start soon"
+msgstr ""
+
+msgid "SortOptions|Weight"
+msgstr ""
+
+msgid "Source"
+msgstr ""
+
+msgid "Source (branch or tag)"
+msgstr ""
+
+msgid "Source code"
+msgstr ""
+
+msgid "Source is not available"
+msgstr ""
+
+msgid "Spam Logs"
+msgstr ""
+
+msgid "Spam and Anti-bot Protection"
+msgstr ""
+
+msgid "Specific Runners"
+msgstr ""
+
+msgid "Specify an e-mail address regex pattern to identify default internal users."
+msgstr ""
+
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
+msgid "Squash commits"
+msgstr ""
+
+msgid "Stage"
+msgstr ""
+
+msgid "Stage & Commit"
+msgstr ""
+
+msgid "Stage all changes"
+msgstr ""
+
+msgid "Stage changes"
+msgstr ""
+
+msgid "Staged"
+msgstr ""
+
+msgid "Staged %{type}"
+msgstr ""
+
+msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
+msgstr ""
+
+msgid "StarProject|Star"
+msgstr ""
+
+msgid "Starred Projects"
+msgstr ""
+
+msgid "Starred Projects' Activity"
+msgstr ""
+
+msgid "Starred projects"
+msgstr ""
+
+msgid "Start a %{new_merge_request} with these changes"
+msgstr ""
+
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
+msgid "Start the Runner!"
+msgstr ""
+
+msgid "Start your trial"
+msgstr ""
+
+msgid "Started"
+msgstr ""
+
+msgid "Starts at (UTC)"
+msgstr ""
+
+msgid "State your message to activate"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "Stop environment"
+msgstr ""
+
+msgid "Stop impersonation"
+msgstr ""
+
+msgid "Stop this environment"
+msgstr ""
+
+msgid "Stopped"
+msgstr ""
+
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
+msgid "Storage"
+msgstr ""
+
+msgid "Storage:"
+msgstr ""
+
+msgid "Subgroups"
+msgstr ""
+
+msgid "Subgroups and projects"
+msgstr ""
+
+msgid "Submit as spam"
+msgstr ""
+
+msgid "Submit review"
+msgstr ""
+
+msgid "Submit search"
+msgstr ""
+
+msgid "Subscribe"
+msgstr ""
+
+msgid "Subscribe at group level"
+msgstr ""
+
+msgid "Subscribe at project level"
+msgstr ""
+
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
+msgid "Switch branch/tag"
+msgstr ""
+
+msgid "Sync information"
+msgstr ""
+
+msgid "System Hooks"
+msgstr ""
+
+msgid "System Info"
+msgstr ""
+
+msgid "System header and footer:"
+msgstr ""
+
+msgid "System metrics (Custom)"
+msgstr ""
+
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
+msgid "Tag (%{tag_count})"
+msgid_plural "Tags (%{tag_count})"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Tags"
+msgstr ""
+
+msgid "Tags feed"
+msgstr ""
+
+msgid "Tags:"
+msgstr ""
+
+msgid "TagsPage|Browse commits"
+msgstr ""
+
+msgid "TagsPage|Browse files"
+msgstr ""
+
+msgid "TagsPage|Can't find HEAD commit for this tag"
+msgstr ""
+
+msgid "TagsPage|Cancel"
+msgstr ""
+
+msgid "TagsPage|Create tag"
+msgstr ""
+
+msgid "TagsPage|Delete tag"
+msgstr ""
+
+msgid "TagsPage|Deleting the %{tag_name} tag cannot be undone. Are you sure?"
+msgstr ""
+
+msgid "TagsPage|Edit release notes"
+msgstr ""
+
+msgid "TagsPage|Existing branch name, tag, or commit SHA"
+msgstr ""
+
+msgid "TagsPage|Filter by tag name"
+msgstr ""
+
+msgid "TagsPage|New Tag"
+msgstr ""
+
+msgid "TagsPage|New tag"
+msgstr ""
+
+msgid "TagsPage|Optionally, add a message to the tag."
+msgstr ""
+
+msgid "TagsPage|Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page."
+msgstr ""
+
+msgid "TagsPage|Release notes"
+msgstr ""
+
+msgid "TagsPage|Repository has no tags yet."
+msgstr ""
+
+msgid "TagsPage|Sort by"
+msgstr ""
+
+msgid "TagsPage|Tags"
+msgstr ""
+
+msgid "TagsPage|Tags give the ability to mark specific points in history as being important"
+msgstr ""
+
+msgid "TagsPage|This tag has no release notes."
+msgstr ""
+
+msgid "TagsPage|Use git tag command to add a new one:"
+msgstr ""
+
+msgid "TagsPage|Write your release notes or drag files here…"
+msgstr ""
+
+msgid "TagsPage|protected"
+msgstr ""
+
+msgid "Target Branch"
+msgstr ""
+
+msgid "Target branch"
+msgstr ""
+
+msgid "Team"
+msgstr ""
+
+msgid "Template"
+msgstr ""
+
+msgid "Templates"
+msgstr ""
+
+msgid "Terms of Service Agreement and Privacy Policy"
+msgstr ""
+
+msgid "Terms of Service and Privacy Policy"
+msgstr ""
+
+msgid "Test SAML SSO"
+msgstr ""
+
+msgid "Test coverage parsing"
+msgstr ""
+
+msgid "Thanks! Don't show me this again"
+msgstr ""
+
+msgid "The Advanced Global Search in GitLab is a powerful search service that saves you time. Instead of creating duplicate code and wasting time, you can now search for code within other teams that can help your own project."
+msgstr ""
+
+msgid "The Git LFS objects will <strong>not</strong> be synced."
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
+msgstr ""
+
+msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project. You can register or sign in to create issues for this project."
+msgstr ""
+
+msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
+msgstr ""
+
+msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
+msgstr ""
+
+msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
+msgstr ""
+
+msgid "The collection of events added to the data gathered for that stage."
+msgstr ""
+
+msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The deployment of this job to %{environmentLink} did not succeed."
+msgstr ""
+
+msgid "The fork relationship has been removed."
+msgstr ""
+
+msgid "The import will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
+msgstr ""
+
+msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
+msgstr ""
+
+msgid "The maximum file size allowed is 200KB."
+msgstr ""
+
+msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
+msgstr ""
+
+msgid "The path to CI config file. Defaults to <code>.gitlab-ci.yml</code>"
+msgstr ""
+
+msgid "The phase of the development lifecycle."
+msgstr ""
+
+msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
+msgstr ""
+
+msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
+msgstr ""
+
+msgid "The private key to use when a client certificate is provided. This value is encrypted at rest."
+msgstr ""
+
+msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
+msgstr ""
+
+msgid "The project can be accessed by any logged in user."
+msgstr ""
+
+msgid "The project can be accessed without any authentication."
+msgstr ""
+
+msgid "The pseudonymizer data collection is disabled. When enabled, GitLab will run a background job that will produce pseudonymized CSVs of the GitLab database that will be uploaded to your configured object storage directory."
+msgstr ""
+
+msgid "The repository for this project does not exist."
+msgstr ""
+
+msgid "The repository for this project is empty"
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code> or <code>git://</code>."
+msgstr ""
+
+msgid "The repository must be accessible over <code>http://</code>, <code>https://</code>, <code>ssh://</code> and <code>git://</code>."
+msgstr ""
+
+msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
+msgstr ""
+
+msgid "The roadmap shows the progress of your epics along a timeline"
+msgstr ""
+
+msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
+msgstr ""
+
+msgid "The tabs below will be removed in a future version"
+msgstr ""
+
+msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
+msgstr ""
+
+msgid "The time taken by each data entry gathered by that stage."
+msgstr ""
+
+msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
+msgstr ""
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
+msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
+msgstr ""
+
+msgid "The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below."
+msgstr ""
+
+msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
+msgstr ""
+
+msgid "There are no archived projects yet"
+msgstr ""
+
+msgid "There are no issues to show"
+msgstr ""
+
+msgid "There are no labels yet"
+msgstr ""
+
+msgid "There are no merge requests to show"
+msgstr ""
+
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
+
+msgid "There was an error adding a todo."
+msgstr ""
+
+msgid "There was an error deleting the todo."
+msgstr ""
+
+msgid "There was an error loading users activity calendar."
+msgstr ""
+
+msgid "There was an error saving your notification settings."
+msgstr ""
+
+msgid "There was an error subscribing to this label."
+msgstr ""
+
+msgid "There was an error when reseting email token."
+msgstr ""
+
+msgid "There was an error when subscribing to this label."
+msgstr ""
+
+msgid "There was an error when unsubscribing from this label."
+msgstr ""
+
+msgid "They can be managed using the %{link}."
+msgstr ""
+
+msgid "Third party offers"
+msgstr ""
+
+msgid "This GitLab instance does not provide any shared Runners yet. Instance administrators can register shared Runners in the admin area."
+msgstr ""
+
+msgid "This application was created by %{link_to_owner}."
+msgstr ""
+
+msgid "This application will be able to:"
+msgstr ""
+
+msgid "This board's scope is reduced"
+msgstr ""
+
+msgid "This branch has changed since you started editing. Would you like to create a new branch?"
+msgstr ""
+
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This diff is collapsed."
+msgstr ""
+
+msgid "This directory"
+msgstr ""
+
+msgid "This group"
+msgstr ""
+
+msgid "This group allows you to sign in with your %{group_name} Single Sign-On account. This will redirect you to an external sign in page."
+msgstr ""
+
+msgid "This group does not provide any group Runners yet."
+msgstr ""
+
+msgid "This is a confidential issue."
+msgstr ""
+
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
+msgid "This is the author's first Merge Request to this project."
+msgstr ""
+
+msgid "This issue is confidential"
+msgstr ""
+
+msgid "This issue is confidential and locked."
+msgstr ""
+
+msgid "This issue is locked."
+msgstr ""
+
+msgid "This job depends on a user to trigger its process. Often they are used to deploy code to production environments"
+msgstr ""
+
+msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
+msgstr ""
+
+msgid "This job does not have a trace."
+msgstr ""
+
+msgid "This job has been canceled"
+msgstr ""
+
+msgid "This job has been skipped"
+msgstr ""
+
+msgid "This job has not been triggered yet"
+msgstr ""
+
+msgid "This job has not started yet"
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
+msgstr ""
+
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink}."
+msgstr ""
+
+msgid "This job is in pending state and is waiting to be picked by a runner"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
+msgstr ""
+
+msgid "This job is stuck, because you don't have any active runners that can run this job."
+msgstr ""
+
+msgid "This job is the most recent deployment to %{link}."
+msgstr ""
+
+msgid "This job requires a manual action"
+msgstr ""
+
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
+msgid "This means you can not push code until you create an empty repository or import existing one."
+msgstr ""
+
+msgid "This merge request is locked."
+msgstr ""
+
+msgid "This option is disabled as you don't have write permissions for the current branch"
+msgstr ""
+
+msgid "This option is disabled while you still have unstaged changes"
+msgstr ""
+
+msgid "This page is unavailable because you are not allowed to read information across multiple projects."
+msgstr ""
+
+msgid "This page will be removed in a future release."
+msgstr ""
+
+msgid "This project"
+msgstr ""
+
+msgid "This project does not belong to a group and can therefore not make use of group Runners."
+msgstr ""
+
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
+msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
+msgstr ""
+
+msgid "This repository"
+msgstr ""
+
+msgid "This runner will only run on pipelines triggered on protected branches"
+msgstr ""
+
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
+msgid "This source diff could not be displayed because it is too large."
+msgstr ""
+
+msgid "This timeout will take precedence when lower than Project-defined timeout"
+msgstr ""
+
+msgid "This user has no identities"
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
+msgstr ""
+
+msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
+msgstr ""
+
+msgid "This will delete the custom metric, Are you sure?"
+msgstr ""
+
+msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
+msgstr ""
+
+msgid "Time before an issue gets scheduled"
+msgstr ""
+
+msgid "Time before an issue starts implementation"
+msgstr ""
+
+msgid "Time before enforced"
+msgstr ""
+
+msgid "Time between merge request creation and merge/close"
+msgstr ""
+
+msgid "Time estimate"
+msgstr ""
+
+msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
+msgstr ""
+
+msgid "Time remaining"
+msgstr ""
+
+msgid "Time spent"
+msgstr ""
+
+msgid "Time tracking"
+msgstr ""
+
+msgid "Time until first merge request"
+msgstr ""
+
+msgid "TimeTrackingEstimated|Est"
+msgstr ""
+
+msgid "TimeTracking|Estimated:"
+msgstr ""
+
+msgid "TimeTracking|Spent"
+msgstr ""
+
+msgid "Timeago|%s days ago"
+msgstr ""
+
+msgid "Timeago|%s days remaining"
+msgstr ""
+
+msgid "Timeago|%s hours ago"
+msgstr ""
+
+msgid "Timeago|%s hours remaining"
+msgstr ""
+
+msgid "Timeago|%s minutes ago"
+msgstr ""
+
+msgid "Timeago|%s minutes remaining"
+msgstr ""
+
+msgid "Timeago|%s months ago"
+msgstr ""
+
+msgid "Timeago|%s months remaining"
+msgstr ""
+
+msgid "Timeago|%s seconds ago"
+msgstr ""
+
+msgid "Timeago|%s seconds remaining"
+msgstr ""
+
+msgid "Timeago|%s weeks ago"
+msgstr ""
+
+msgid "Timeago|%s weeks remaining"
+msgstr ""
+
+msgid "Timeago|%s years ago"
+msgstr ""
+
+msgid "Timeago|%s years remaining"
+msgstr ""
+
+msgid "Timeago|1 day ago"
+msgstr ""
+
+msgid "Timeago|1 day remaining"
+msgstr ""
+
+msgid "Timeago|1 hour ago"
+msgstr ""
+
+msgid "Timeago|1 hour remaining"
+msgstr ""
+
+msgid "Timeago|1 minute ago"
+msgstr ""
+
+msgid "Timeago|1 minute remaining"
+msgstr ""
+
+msgid "Timeago|1 month ago"
+msgstr ""
+
+msgid "Timeago|1 month remaining"
+msgstr ""
+
+msgid "Timeago|1 week ago"
+msgstr ""
+
+msgid "Timeago|1 week remaining"
+msgstr ""
+
+msgid "Timeago|1 year ago"
+msgstr ""
+
+msgid "Timeago|1 year remaining"
+msgstr ""
+
+msgid "Timeago|Past due"
+msgstr ""
+
+msgid "Timeago|in %s days"
+msgstr ""
+
+msgid "Timeago|in %s hours"
+msgstr ""
+
+msgid "Timeago|in %s minutes"
+msgstr ""
+
+msgid "Timeago|in %s months"
+msgstr ""
+
+msgid "Timeago|in %s seconds"
+msgstr ""
+
+msgid "Timeago|in %s weeks"
+msgstr ""
+
+msgid "Timeago|in %s years"
+msgstr ""
+
+msgid "Timeago|in 1 day"
+msgstr ""
+
+msgid "Timeago|in 1 hour"
+msgstr ""
+
+msgid "Timeago|in 1 minute"
+msgstr ""
+
+msgid "Timeago|in 1 month"
+msgstr ""
+
+msgid "Timeago|in 1 week"
+msgstr ""
+
+msgid "Timeago|in 1 year"
+msgstr ""
+
+msgid "Timeago|just now"
+msgstr ""
+
+msgid "Timeago|right now"
+msgstr ""
+
+msgid "Timeout"
+msgstr ""
+
+msgid "Time|hr"
+msgid_plural "Time|hrs"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Time|min"
+msgid_plural "Time|mins"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "Time|s"
+msgstr ""
+
+msgid "Tip:"
+msgstr ""
+
+msgid "Title"
+msgstr ""
+
+msgid "To GitLab"
+msgstr ""
+
+msgid "To add an SSH key you need to %{generate_link_start}generate one%{link_end} or use an %{existing_link_start}existing key%{link_end}."
+msgstr ""
+
+msgid "To connect GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to connect."
+msgstr ""
+
+msgid "To connect GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To connect an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To define internal users, first enable new users set to external"
+msgstr ""
+
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
+msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
+msgstr ""
+
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
+msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
+msgstr ""
+
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
+msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
+msgstr ""
+
+msgid "To import GitHub repositories, you first need to authorize GitLab to access the list of your GitHub repositories:"
+msgstr ""
+
+msgid "To import an SVN repository, check out %{svn_link}."
+msgstr ""
+
+msgid "To move or copy an entire GitLab project from another GitLab installation to this one, navigate to the original project's settings page, generate an export file, and upload it here."
+msgstr ""
+
+msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
+msgstr ""
+
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
+msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
+msgstr ""
+
+msgid "To start serving your jobs you can add Runners to your group"
+msgstr ""
+
+msgid "To this GitLab instance"
+msgstr ""
+
+msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
+msgstr ""
+
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
+
+msgid "To widen your search, change or remove filters."
+msgstr ""
+
+msgid "Today"
+msgstr ""
+
+msgid "Todo"
+msgstr ""
+
+msgid "Todos"
+msgstr ""
+
+msgid "Toggle Sidebar"
+msgstr ""
+
+msgid "Toggle commit description"
+msgstr ""
+
+msgid "Toggle discussion"
+msgstr ""
+
+msgid "Toggle file browser"
+msgstr ""
+
+msgid "Toggle navigation"
+msgstr ""
+
+msgid "Toggle sidebar"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: OFF"
+msgstr ""
+
+msgid "ToggleButton|Toggle Status: ON"
+msgstr ""
+
+msgid "Token"
+msgstr ""
+
+msgid "Tomorrow"
+msgstr ""
+
+msgid "Too many changes to show."
+msgstr ""
+
+msgid "Total Contributions"
+msgstr ""
+
+msgid "Total Time"
+msgstr ""
+
+msgid "Total test time for all commits/merges"
+msgstr ""
+
+msgid "Total: %{total}"
+msgstr ""
+
+msgid "Tracing"
+msgstr ""
+
+msgid "Track activity with Contribution Analytics."
+msgstr ""
+
+msgid "Track groups of issues that share a theme, across projects and milestones"
+msgstr ""
+
+msgid "Track time with quick actions"
+msgstr ""
+
+msgid "Tree view"
+msgstr ""
+
+msgid "Trending"
+msgstr ""
+
+msgid "Trigger"
+msgstr ""
+
+msgid "Trigger pipelines for mirror updates"
+msgstr ""
+
+msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
+msgstr ""
+
+msgid "Trigger this manual action"
+msgstr ""
+
+msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
+msgstr ""
+
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
+msgid "Try again"
+msgstr ""
+
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
+msgid "Turn on Service Desk"
+msgstr ""
+
+msgid "Twitter"
+msgstr ""
+
+msgid "Two-factor authentication"
+msgstr ""
+
+msgid "Type"
+msgstr ""
+
+msgid "Unable to load the diff. %{button_try_again}"
+msgstr ""
+
+msgid "Unable to save your changes"
+msgstr ""
+
+msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
+msgstr ""
+
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
+msgid "Unknown"
+msgstr ""
+
+msgid "Unlock"
+msgstr ""
+
+msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
+msgstr ""
+
+msgid "Unlocked"
+msgstr ""
+
+msgid "Unresolve discussion"
+msgstr ""
+
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
+msgid "Unstage all changes"
+msgstr ""
+
+msgid "Unstage changes"
+msgstr ""
+
+msgid "Unstaged"
+msgstr ""
+
+msgid "Unstaged %{type}"
+msgstr ""
+
+msgid "Unstaged and staged %{type}"
+msgstr ""
+
+msgid "Unstar"
+msgstr ""
+
+msgid "Unsubscribe"
+msgstr ""
+
+msgid "Unsubscribe at group level"
+msgstr ""
+
+msgid "Unsubscribe at project level"
+msgstr ""
+
+msgid "Unverified"
+msgstr ""
+
+msgid "Up to date"
+msgstr ""
+
+msgid "Upcoming"
+msgstr ""
+
+msgid "Update"
+msgstr ""
+
+msgid "Update now"
+msgstr ""
+
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
+
+msgid "Updating"
+msgstr ""
+
+msgid "Upgrade your plan to activate Advanced Global Search."
+msgstr ""
+
+msgid "Upgrade your plan to activate Contribution Analytics."
+msgstr ""
+
+msgid "Upgrade your plan to activate Group Webhooks."
+msgstr ""
+
+msgid "Upgrade your plan to activate Issue weight."
+msgstr ""
+
+msgid "Upgrade your plan to improve Issue boards."
+msgstr ""
+
+msgid "Upload <code>GoogleCodeProjectHosting.json</code> here:"
+msgstr ""
+
+msgid "Upload New File"
+msgstr ""
+
+msgid "Upload file"
+msgstr ""
+
+msgid "UploadLink|click to upload"
+msgstr ""
+
+msgid "Upvotes"
+msgstr ""
+
+msgid "Usage ping is not enabled"
+msgstr ""
+
+msgid "Usage statistics"
+msgstr ""
+
+msgid "Use <code>%{native_redirect_uri}</code> for local tests"
+msgstr ""
+
+msgid "Use Service Desk to connect with your users (e.g. to offer customer support) through email right inside GitLab"
+msgstr ""
+
+msgid "Use group milestones to manage issues from multiple projects in the same milestone."
+msgstr ""
+
+msgid "Use one line per URI"
+msgstr ""
+
+msgid "Use template"
+msgstr ""
+
+msgid "Use the following registration token during setup:"
+msgstr ""
+
+msgid "Use your global notification setting"
+msgstr ""
+
+msgid "Used by members to sign in to your group in GitLab"
+msgstr ""
+
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
+msgid "User Settings"
+msgstr ""
+
+msgid "User and IP Rate Limits"
+msgstr ""
+
+msgid "User map"
+msgstr ""
+
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
+msgstr ""
+
+msgid "Variables"
+msgstr ""
+
+msgid "Variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use variables for passwords, secret keys, or whatever you want."
+msgstr ""
+
+msgid "Various container registry settings."
+msgstr ""
+
+msgid "Various email settings."
+msgstr ""
+
+msgid "Various settings that affect GitLab performance."
+msgstr ""
+
+msgid "Verification information"
+msgstr ""
+
+msgid "Verified"
+msgstr ""
+
+msgid "Version"
+msgstr ""
+
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
+msgid "View epics list"
+msgstr ""
+
+msgid "View file @ "
+msgstr ""
+
+msgid "View group labels"
+msgstr ""
+
+msgid "View issue"
+msgstr ""
+
+msgid "View it on GitLab"
+msgstr ""
+
+msgid "View jobs"
+msgstr ""
+
+msgid "View labels"
+msgstr ""
+
+msgid "View log"
+msgstr ""
+
+msgid "View open merge request"
+msgstr ""
+
+msgid "View project labels"
+msgstr ""
+
+msgid "View replaced file @ "
+msgstr ""
+
+msgid "View the documentation"
+msgstr ""
+
+msgid "Visibility and access controls"
+msgstr ""
+
+msgid "Visibility level"
+msgstr ""
+
+msgid "Visibility level:"
+msgstr ""
+
+msgid "Visibility:"
+msgstr ""
+
+msgid "VisibilityLevel|Internal"
+msgstr ""
+
+msgid "VisibilityLevel|Private"
+msgstr ""
+
+msgid "VisibilityLevel|Public"
+msgstr ""
+
+msgid "VisibilityLevel|Unknown"
+msgstr ""
+
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
+msgid "Want to see the data? Please ask an administrator for access."
+msgstr ""
+
+msgid "We detected potential spam in the %{humanized_resource_name}. Please solve the reCAPTCHA to proceed."
+msgstr ""
+
+msgid "We don't have enough data to show this stage."
+msgstr ""
+
+msgid "We want to be sure it is you, please confirm you are not a robot."
+msgstr ""
+
+msgid "Web IDE"
+msgstr ""
+
+msgid "Web terminal"
+msgstr ""
+
+msgid "Webhooks allow you to trigger a URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. Group webhooks will apply to all projects in a group, allowing you to standardize webhook functionality across your entire group."
+msgstr ""
+
+msgid "Weeks"
+msgstr ""
+
+msgid "Weight"
+msgstr ""
+
+msgid "Weight %{weight}"
+msgstr ""
+
+msgid "When a runner is locked, it cannot be assigned to other projects"
+msgstr ""
+
+msgid "When enabled, users cannot use GitLab until the terms have been accepted."
+msgstr ""
+
+msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
+msgstr ""
+
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
+msgid "Wiki"
+msgstr ""
+
+msgid "WikiClone|Clone your wiki"
+msgstr ""
+
+msgid "WikiClone|Git Access"
+msgstr ""
+
+msgid "WikiClone|Install Gollum"
+msgstr ""
+
+msgid "WikiClone|It is recommended to install %{markdown} so that GFM features render locally:"
+msgstr ""
+
+msgid "WikiClone|Start Gollum and edit locally"
+msgstr ""
+
+msgid "WikiEditPageTip|Tip: You can move this page by adding the path to the beginning of the title."
+msgstr ""
+
+msgid "WikiEdit|There is already a page with the same title in that path."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|You must be a project member in order to add wiki pages. If you have suggestions for how to improve the wiki for this project, consider opening an issue in the %{issues_link}."
+msgstr ""
+
+msgid "WikiEmptyIssueMessage|issue tracker"
+msgstr ""
+
+msgid "WikiEmpty|A wiki is where you can store all the details about your project. This can include why you've created it, its principles, how to use it, and so on."
+msgstr ""
+
+msgid "WikiEmpty|Create your first page"
+msgstr ""
+
+msgid "WikiEmpty|Suggest wiki improvement"
+msgstr ""
+
+msgid "WikiEmpty|The wiki lets you write documentation for your project"
+msgstr ""
+
+msgid "WikiEmpty|This project has no wiki pages"
+msgstr ""
+
+msgid "WikiEmpty|You must be a project member in order to add wiki pages."
+msgstr ""
+
+msgid "WikiHistoricalPage|This is an old version of this page."
+msgstr ""
+
+msgid "WikiHistoricalPage|You can view the %{most_recent_link} or browse the %{history_link}."
+msgstr ""
+
+msgid "WikiHistoricalPage|history"
+msgstr ""
+
+msgid "WikiHistoricalPage|most recent version"
+msgstr ""
+
+msgid "WikiMarkdownDocs|More examples are in the %{docs_link}"
+msgstr ""
+
+msgid "WikiMarkdownDocs|documentation"
+msgstr ""
+
+msgid "WikiMarkdownTip|To link to a (new) page, simply type %{link_example}"
+msgstr ""
+
+msgid "WikiNewPagePlaceholder|how-to-setup"
+msgstr ""
+
+msgid "WikiNewPageTip|Tip: You can specify the full path for the new file. We will automatically create any missing directories."
+msgstr ""
+
+msgid "WikiNewPageTitle|New Wiki Page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Are you sure you want to delete this page?"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page"
+msgstr ""
+
+msgid "WikiPageConfirmDelete|Delete page %{pageTitle}?"
+msgstr ""
+
+msgid "WikiPageConflictMessage|Someone edited the page the same time you did. Please check out %{page_link} and make sure your changes will not unintentionally remove theirs."
+msgstr ""
+
+msgid "WikiPageConflictMessage|the page"
+msgstr ""
+
+msgid "WikiPageCreate|Create %{page_title}"
+msgstr ""
+
+msgid "WikiPageEdit|Update %{page_title}"
+msgstr ""
+
+msgid "WikiPage|Page slug"
+msgstr ""
+
+msgid "WikiPage|Write your content or drag files here…"
+msgstr ""
+
+msgid "Wiki|Create Page"
+msgstr ""
+
+msgid "Wiki|Create page"
+msgstr ""
+
+msgid "Wiki|Edit Page"
+msgstr ""
+
+msgid "Wiki|More Pages"
+msgstr ""
+
+msgid "Wiki|New page"
+msgstr ""
+
+msgid "Wiki|Page history"
+msgstr ""
+
+msgid "Wiki|Page version"
+msgstr ""
+
+msgid "Wiki|Pages"
+msgstr ""
+
+msgid "Wiki|Wiki Pages"
+msgstr ""
+
+msgid "With contribution analytics you can have an overview for the activity of issues, merge requests and push events of your organization and its members."
+msgstr ""
+
+msgid "Withdraw Access Request"
+msgstr ""
+
+msgid "Yes"
+msgstr ""
+
+msgid "Yes, add it"
+msgstr ""
+
+msgid "Yes, let me map Google Code users to full names or GitLab users."
+msgstr ""
+
+msgid "Yesterday"
+msgstr ""
+
+msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
+msgstr ""
+
+msgid "You are going to remove %{group_name}. Removed groups CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove %{project_full_name}. Removed project CANNOT be restored! Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to remove the fork relationship to source project %{forked_from_project}. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are going to transfer %{project_full_name} to another owner. Are you ABSOLUTELY sure?"
+msgstr ""
+
+msgid "You are on a read-only GitLab instance."
+msgstr ""
+
+msgid "You can %{linkStart}view the blob%{linkEnd} instead."
+msgstr ""
+
+msgid "You can also create a project from the command line."
+msgstr ""
+
+msgid "You can also star a label to make it a priority label."
+msgstr ""
+
+msgid "You can easily contribute to them by requesting to join these groups."
+msgstr ""
+
+msgid "You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}"
+msgstr ""
+
+msgid "You can move around the graph by using the arrow keys."
+msgstr ""
+
+msgid "You can only add files when you are on a branch"
+msgstr ""
+
+msgid "You can only edit files when you are on a branch"
+msgstr ""
+
+msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
+msgstr ""
+
+msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
+msgstr ""
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
+msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
+msgstr ""
+
+msgid "You cannot write to this read-only GitLab instance."
+msgstr ""
+
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
+msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
+msgstr ""
+
+msgid "You don't have any applications"
+msgstr ""
+
+msgid "You don't have any authorized applications"
+msgstr ""
+
+msgid "You have no permissions"
+msgstr ""
+
+msgid "You have reached your project limit"
+msgstr ""
+
+msgid "You must accept our Terms of Service and privacy policy in order to register an account"
+msgstr ""
+
+msgid "You must have maintainer access to force delete a lock"
+msgstr ""
+
+msgid "You need a different license to enable FileLocks feature"
+msgstr ""
+
+msgid "You need git-lfs version %{min_git_lfs_version} (or greater) to continue. Please visit https://git-lfs.github.com"
+msgstr ""
+
+msgid "You need permission."
+msgstr ""
+
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
+msgid "You will not get any notifications via email"
+msgstr ""
+
+msgid "You will only receive notifications for the events you choose"
+msgstr ""
+
+msgid "You will only receive notifications for threads you have participated in"
+msgstr ""
+
+msgid "You will receive notifications for any activity"
+msgstr ""
+
+msgid "You will receive notifications only for comments in which you were @mentioned"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via %{protocol} until you %{set_password_link} on your account"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you %{add_ssh_key_link} to your profile"
+msgstr ""
+
+msgid "You won't be able to pull or push project code via SSH until you add an SSH key to your profile"
+msgstr ""
+
+msgid "You'll need to use different branch names to get a valid comparison."
+msgstr ""
+
+msgid "You're receiving this email because %{reason}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}."
+msgstr ""
+
+msgid "You're receiving this email because of your account on %{host}. %{manage_notifications_link} &middot; %{help_link}"
+msgstr ""
+
+msgid "YouTube"
+msgstr ""
+
+msgid "Your Groups"
+msgstr ""
+
+msgid "Your Kubernetes cluster information on this page is still editable, but you are advised to disable and reconfigure"
+msgstr ""
+
+msgid "Your Projects (default)"
+msgstr ""
+
+msgid "Your Projects' Activity"
+msgstr ""
+
+msgid "Your Todos"
+msgstr ""
+
+msgid "Your applications (%{size})"
+msgstr ""
+
+msgid "Your authorized applications"
+msgstr ""
+
+msgid "Your changes can be committed to %{branch_name} because a merge request is open."
+msgstr ""
+
+msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
+msgstr ""
+
+msgid "Your changes have been saved"
+msgstr ""
+
+msgid "Your comment will not be visible to the public."
+msgstr ""
+
+msgid "Your groups"
+msgstr ""
+
+msgid "Your name"
+msgstr ""
+
+msgid "Your projects"
+msgstr ""
+
+msgid "a deleted user"
+msgstr ""
+
+msgid "ago"
+msgstr ""
+
+msgid "among other things"
+msgstr ""
+
+msgid "assign yourself"
+msgstr ""
+
+msgid "branch name"
+msgstr ""
+
+msgid "by"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Container Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about DAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about Dependency Scanning %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{linkStartTag}Learn more about SAST %{linkEndTag}"
+msgstr ""
+
+msgid "ciReport|%{namespace} is affected by %{vulnerability}."
+msgstr ""
+
+msgid "ciReport|%{remainingPackagesCount} more"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr ""
+
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
+
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr ""
+
+msgid "ciReport|(is loading)"
+msgstr ""
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr ""
+
+msgid "ciReport|Class"
+msgstr ""
+
+msgid "ciReport|Code quality"
+msgstr ""
+
+msgid "ciReport|Confidence"
+msgstr ""
+
+msgid "ciReport|Container scanning"
+msgstr ""
+
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgstr ""
+
+msgid "ciReport|DAST"
+msgstr ""
+
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgstr ""
+
+msgid "ciReport|Dependency scanning"
+msgstr ""
+
+msgid "ciReport|Description"
+msgstr ""
+
+msgid "ciReport|Dismiss vulnerability"
+msgstr ""
+
+msgid "ciReport|Dismissed by"
+msgstr ""
+
+msgid "ciReport|Dynamic Application Security Testing (DAST) detects known vulnerabilities in your web application."
+msgstr ""
+
+msgid "ciReport|Failed to load %{reportName} report"
+msgstr ""
+
+msgid "ciReport|File"
+msgstr ""
+
+msgid "ciReport|Fixed:"
+msgstr ""
+
+msgid "ciReport|Identifiers"
+msgstr ""
+
+msgid "ciReport|Instances"
+msgstr ""
+
+msgid "ciReport|Learn more about interacting with security reports (Alpha)."
+msgstr ""
+
+msgid "ciReport|License management detected %d license for the source branch only"
+msgid_plural "ciReport|License management detected %d licenses for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|License management detected %d new license"
+msgid_plural "ciReport|License management detected %d new licenses"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|License management detected no licenses for the source branch only"
+msgstr ""
+
+msgid "ciReport|License management detected no new licenses"
+msgstr ""
+
+msgid "ciReport|Links"
+msgstr ""
+
+msgid "ciReport|Loading %{reportName} report"
+msgstr ""
+
+msgid "ciReport|Manage licenses"
+msgstr ""
+
+msgid "ciReport|Method"
+msgstr ""
+
+msgid "ciReport|Namespace"
+msgstr ""
+
+msgid "ciReport|No changes to code quality"
+msgstr ""
+
+msgid "ciReport|No changes to performance metrics"
+msgstr ""
+
+msgid "ciReport|Performance metrics"
+msgstr ""
+
+msgid "ciReport|Revert dismissal"
+msgstr ""
+
+msgid "ciReport|SAST"
+msgstr ""
+
+msgid "ciReport|Security scanning"
+msgstr ""
+
+msgid "ciReport|Security scanning failed loading any results"
+msgstr ""
+
+msgid "ciReport|Severity"
+msgstr ""
+
+msgid "ciReport|Solution"
+msgstr ""
+
+msgid "ciReport|Static Application Security Testing (SAST) detects known vulnerabilities in your source code."
+msgstr ""
+
+msgid "ciReport|There was an error creating the issue. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error dismissing the vulnerability. Please try again."
+msgstr ""
+
+msgid "ciReport|There was an error loading DAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading SAST report"
+msgstr ""
+
+msgid "ciReport|There was an error loading container scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error loading dependency scanning report"
+msgstr ""
+
+msgid "ciReport|There was an error reverting the dismissal. Please try again."
+msgstr ""
+
+msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
+msgstr ""
+
+msgid "ciReport|Used by %{packagesString}"
+msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "ciReport|View full report"
+msgstr ""
+
+msgid "ciReport|on pipeline"
+msgstr ""
+
+msgid "command line instructions"
+msgstr ""
+
+msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
+msgstr ""
+
+msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
+msgstr ""
+
+msgid "connecting"
+msgstr ""
+
+msgid "could not read private key, is the passphrase correct?"
+msgstr ""
+
+msgid "customize"
+msgstr ""
+
+msgid "day"
+msgid_plural "days"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "deploy token"
+msgstr ""
+
+msgid "disabled"
+msgstr ""
+
+msgid "done"
+msgstr ""
+
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "enabled"
+msgstr ""
+
+msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
+msgstr ""
+
+msgid "for this project"
+msgstr ""
+
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
+msgid "here"
+msgstr ""
+
+msgid "https://your-bitbucket-server"
+msgstr ""
+
+msgid "import flow"
+msgstr ""
+
+msgid "importing"
+msgstr ""
+
+msgid "instance completed"
+msgid_plural "instances completed"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "is invalid because there is downstream lock"
+msgstr ""
+
+msgid "is invalid because there is upstream lock"
+msgstr ""
+
+msgid "is not a valid X509 certificate."
+msgstr ""
+
+msgid "issue boards"
+msgstr ""
+
+msgid "latest deployment"
+msgstr ""
+
+msgid "latest version"
+msgstr ""
+
+msgid "license management"
+msgstr ""
+
+msgid "locked by %{path_lock_user_name} %{created_at}"
+msgstr ""
+
+msgid "merge request"
+msgid_plural "merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} decreased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage %{emphasisStart} increased %{emphasisEnd} from %{memoryFrom}MB to %{memoryTo}MB"
+msgstr ""
+
+msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
+msgstr ""
+
+msgid "mrWidget|Add approval"
+msgstr ""
+
+msgid "mrWidget|Allows commits from members who can merge to the target branch"
+msgstr ""
+
+msgid "mrWidget|An error occured while removing your approval."
+msgstr ""
+
+msgid "mrWidget|An error occured while retrieving approval data for this merge request."
+msgstr ""
+
+msgid "mrWidget|An error occurred while submitting your approval."
+msgstr ""
+
+msgid "mrWidget|Approve"
+msgstr ""
+
+msgid "mrWidget|Approved by"
+msgstr ""
+
+msgid "mrWidget|Cancel automatic merge"
+msgstr ""
+
+msgid "mrWidget|Check out branch"
+msgstr ""
+
+msgid "mrWidget|Checking ability to merge automatically"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick"
+msgstr ""
+
+msgid "mrWidget|Cherry-pick this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Closed"
+msgstr ""
+
+msgid "mrWidget|Closed by"
+msgstr ""
+
+msgid "mrWidget|Closes"
+msgstr ""
+
+msgid "mrWidget|Create an issue to resolve them later"
+msgstr ""
+
+msgid "mrWidget|Deployment statistics are not available currently"
+msgstr ""
+
+msgid "mrWidget|Did not close"
+msgstr ""
+
+msgid "mrWidget|Email patches"
+msgstr ""
+
+msgid "mrWidget|Failed to load deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
+msgstr ""
+
+msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|If the %{missingBranchName} branch exists in your local repository, you can merge this merge request manually using the command line"
+msgstr ""
+
+msgid "mrWidget|Loading deployment statistics"
+msgstr ""
+
+msgid "mrWidget|Mentions"
+msgstr ""
+
+msgid "mrWidget|Merge"
+msgstr ""
+
+msgid "mrWidget|Merge failed."
+msgstr ""
+
+msgid "mrWidget|Merge locally"
+msgstr ""
+
+msgid "mrWidget|Merge request approved"
+msgstr ""
+
+msgid "mrWidget|Merge request approved; you can approve additionally"
+msgstr ""
+
+msgid "mrWidget|Merged by"
+msgstr ""
+
+msgid "mrWidget|No Approval required"
+msgstr ""
+
+msgid "mrWidget|No Approval required; you can still approve"
+msgstr ""
+
+msgid "mrWidget|Open in Web IDE"
+msgstr ""
+
+msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
+msgstr ""
+
+msgid "mrWidget|Plain diff"
+msgstr ""
+
+msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
+msgstr ""
+
+msgid "mrWidget|Refresh"
+msgstr ""
+
+msgid "mrWidget|Refresh now"
+msgstr ""
+
+msgid "mrWidget|Refreshing now"
+msgstr ""
+
+msgid "mrWidget|Remove Source Branch"
+msgstr ""
+
+msgid "mrWidget|Remove source branch"
+msgstr ""
+
+msgid "mrWidget|Remove your approval"
+msgstr ""
+
+msgid "mrWidget|Request to merge"
+msgstr ""
+
+msgid "mrWidget|Requires 1 more approval"
+msgid_plural "mrWidget|Requires %d more approvals"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "mrWidget|Requires 1 more approval by"
+msgid_plural "mrWidget|Requires %d more approvals by"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "mrWidget|Resolve conflicts"
+msgstr ""
+
+msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
+msgstr ""
+
+msgid "mrWidget|Revert"
+msgstr ""
+
+msgid "mrWidget|Revert this merge request in a new merge request"
+msgstr ""
+
+msgid "mrWidget|Set by"
+msgstr ""
+
+msgid "mrWidget|The changes were merged into"
+msgstr ""
+
+msgid "mrWidget|The changes were not merged into"
+msgstr ""
+
+msgid "mrWidget|The changes will be merged into"
+msgstr ""
+
+msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
+msgstr ""
+
+msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
+msgstr ""
+
+msgid "mrWidget|The source branch has been removed"
+msgstr ""
+
+msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
+msgstr ""
+
+msgid "mrWidget|The source branch is being removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will be removed"
+msgstr ""
+
+msgid "mrWidget|The source branch will not be removed"
+msgstr ""
+
+msgid "mrWidget|There are merge conflicts"
+msgstr ""
+
+msgid "mrWidget|There are unresolved discussions. Please resolve these discussions"
+msgstr ""
+
+msgid "mrWidget|This merge request failed to be merged automatically"
+msgstr ""
+
+msgid "mrWidget|This merge request is in the process of being merged"
+msgstr ""
+
+msgid "mrWidget|This project is archived, write access has been disabled"
+msgstr ""
+
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
+msgid "mrWidget|You can merge this merge request manually using the"
+msgstr ""
+
+msgid "mrWidget|You can remove source branch now"
+msgstr ""
+
+msgid "mrWidget|branch does not exist."
+msgstr ""
+
+msgid "mrWidget|command line"
+msgstr ""
+
+msgid "mrWidget|into"
+msgstr ""
+
+msgid "mrWidget|to be merged automatically when the pipeline succeeds"
+msgstr ""
+
+msgid "n/a"
+msgstr ""
+
+msgid "new merge request"
+msgstr ""
+
+msgid "notification emails"
+msgstr ""
+
+msgid "or"
+msgstr ""
+
+msgid "out of %d total test"
+msgid_plural "out of %d total tests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "parent"
+msgid_plural "parents"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "password"
+msgstr ""
+
+msgid "personal access token"
+msgstr ""
+
+msgid "private key does not match certificate."
+msgstr ""
+
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "remaining"
+msgstr ""
+
+msgid "remove"
+msgstr ""
+
+msgid "remove due date"
+msgstr ""
+
+msgid "remove weight"
+msgstr ""
+
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+msgid "source"
+msgstr ""
+
+msgid "spendCommand|%{slash_command} will update the sum of the time spent."
+msgstr ""
+
+msgid "started"
+msgstr ""
+
+msgid "this document"
+msgstr ""
+
+msgid "to help your contributors communicate effectively!"
+msgstr ""
+
+msgid "toggle collapse"
+msgstr ""
+
+msgid "username"
+msgstr ""
+
+msgid "uses Kubernetes clusters to deploy your code!"
+msgstr ""
+
+msgid "view it on GitLab"
+msgstr ""
+
+msgid "with %{additions} additions, %{deletions} deletions."
+msgstr ""
+
+msgid "within %d minute "
+msgid_plural "within %d minutes "
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
diff --git a/locale/tr_TR/gitlab.po b/locale/tr_TR/gitlab.po
index e7e44caf077..8a666a6737d 100644
--- a/locale/tr_TR/gitlab.po
+++ b/locale/tr_TR/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Turkish\n"
"Language: tr_TR\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: tr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:31\n"
+"PO-Revision-Date: 2018-11-19 17:19\n"
msgid " Status"
msgstr ""
@@ -31,6 +31,14 @@ msgid_plural " improved on %d points"
msgstr[0] ""
msgstr[1] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -46,6 +54,11 @@ msgid_plural "%d commits behind"
msgstr[0] ""
msgstr[1] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -91,11 +104,6 @@ msgid_plural "%d unstaged changes"
msgstr[0] ""
msgstr[1] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] ""
@@ -104,17 +112,31 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] "%{count} katılımcı"
msgstr[1] "%{count} katılımcı"
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -124,6 +146,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -139,23 +164,12 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr ""
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr ""
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -167,27 +181,13 @@ msgstr ""
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -314,6 +314,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr ""
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -356,13 +365,10 @@ msgstr "Erişim anahtarları"
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
+msgid "Access expiration date"
msgstr ""
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr ""
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -392,27 +398,48 @@ msgstr "Katkı kılavuzu ekle"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
-msgstr "Lisans Ekle"
+msgid "Add Kubernetes cluster"
+msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr "Yeni dizin ekle"
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr "Yapılacaklara Ekle"
@@ -422,6 +449,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -455,9 +485,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -494,12 +521,17 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr "GeliÅŸmiÅŸ ayarlar"
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "All"
msgstr "Tümü"
@@ -515,6 +547,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -524,6 +559,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "Kubernetes kümelerini eklemeye ve yönetmenize olanak tanır."
@@ -539,6 +580,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -560,7 +604,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -584,6 +628,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -596,6 +646,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -608,6 +661,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr "Markdown ön izlemesi yüklenirken hata oluştu"
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -635,6 +691,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -677,12 +736,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr "Kullanıcı adı doğrulanırken bir hata oluştu"
msgid "An error occurred. Please try again."
msgstr "Bir hata oluştu. Lütfen tekrar deneyin."
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -701,7 +766,7 @@ msgstr "Görünüm"
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -719,9 +784,15 @@ msgstr "Nisan"
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -740,6 +811,9 @@ msgstr ""
msgid "Are you sure you want to reset the health check token?"
msgstr ""
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -878,6 +952,9 @@ msgstr ""
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -914,9 +991,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -995,6 +1069,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1285,6 +1368,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1315,9 +1401,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1372,7 +1455,7 @@ msgstr ""
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1399,6 +1482,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1429,6 +1518,9 @@ msgstr ""
msgid "CiStatusLabel|created"
msgstr ""
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr ""
@@ -1447,6 +1539,9 @@ msgstr ""
msgid "CiStatusLabel|skipped"
msgstr ""
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr ""
@@ -1459,6 +1554,9 @@ msgstr ""
msgid "CiStatusText|created"
msgstr ""
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr ""
@@ -1513,10 +1611,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1561,6 +1659,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1573,12 +1674,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1609,10 +1722,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1639,6 +1752,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1675,6 +1794,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1705,9 +1827,6 @@ msgstr ""
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1729,25 +1848,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster details"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster health"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1759,7 +1872,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1768,16 +1881,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1795,9 +1905,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1825,6 +1932,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1837,6 +1947,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1867,9 +1980,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1909,13 +2019,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -1933,6 +2040,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -1951,9 +2061,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -1963,6 +2070,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -1972,12 +2082,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr ""
@@ -2012,6 +2128,9 @@ msgstr ""
msgid "CommitMessage|Add %{file_name}"
msgstr ""
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr ""
@@ -2084,7 +2203,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2093,10 +2212,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2186,6 +2305,9 @@ msgstr ""
msgid "Contribution guide"
msgstr ""
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2219,6 +2341,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2240,15 +2374,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2324,7 +2470,7 @@ msgstr ""
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
+msgid "Create your first page"
msgstr ""
msgid "CreateTag|Tag"
@@ -2375,6 +2521,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr ""
@@ -2393,6 +2542,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr ""
@@ -2444,6 +2596,9 @@ msgstr ""
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2456,6 +2611,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr ""
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr ""
@@ -2465,6 +2635,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2602,6 +2775,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2626,6 +2805,12 @@ msgstr ""
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2647,12 +2832,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2668,6 +2868,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2749,7 +2952,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2794,9 +2997,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2809,6 +3009,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2911,7 +3117,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -2944,10 +3150,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3058,6 +3264,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3112,6 +3324,12 @@ msgstr ""
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3121,6 +3339,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr ""
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3130,6 +3351,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3139,6 +3435,9 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr ""
@@ -3151,9 +3450,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr ""
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr ""
@@ -3169,6 +3477,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3181,7 +3492,7 @@ msgstr ""
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3220,17 +3531,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "ForkedFromProjectPath|Forked from"
msgstr ""
@@ -3246,6 +3558,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3288,6 +3603,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3462,10 +3780,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3474,6 +3804,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3495,7 +3828,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3507,6 +3840,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3516,19 +3852,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3546,6 +3888,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3558,9 +3906,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3570,9 +3936,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr ""
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3639,12 +4002,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr ""
-
-msgid "GoToYourFork|Fork"
-msgstr ""
-
msgid "Google Code import"
msgstr ""
@@ -3675,9 +4032,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3687,6 +4056,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3705,13 +4077,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3738,9 +4110,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3798,6 +4167,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3810,19 +4182,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -3864,6 +4236,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -4028,6 +4403,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4096,6 +4474,12 @@ msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4120,6 +4504,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4135,9 +4549,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4174,7 +4585,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4192,12 +4603,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4270,6 +4675,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
@@ -4281,12 +4689,18 @@ msgstr ""
msgid "Last commit"
msgstr ""
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4335,6 +4749,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4344,6 +4767,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4353,6 +4779,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4362,6 +4791,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4374,9 +4806,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4403,6 +4841,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4448,6 +4889,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4517,13 +4961,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4535,6 +5009,12 @@ msgstr ""
msgid "Median"
msgstr ""
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -4568,6 +5048,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4577,9 +5072,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4589,6 +5081,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4604,6 +5102,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4820,6 +5321,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -4939,6 +5443,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -4948,9 +5458,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -4960,6 +5467,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -4987,6 +5497,9 @@ msgstr ""
msgid "No repository"
msgstr ""
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr ""
@@ -5023,6 +5536,9 @@ msgstr ""
msgid "Not enough data"
msgstr ""
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -5041,6 +5557,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr ""
@@ -5113,9 +5641,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5142,9 +5667,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5166,6 +5688,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5190,6 +5715,21 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5256,6 +5796,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5283,13 +5826,13 @@ msgstr ""
msgid "Permissions"
msgstr ""
-msgid "Personal Access Token"
+msgid "Permissions, LFS, 2FA"
msgstr ""
-msgid "Pipeline"
+msgid "Personal Access Token"
msgstr ""
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
+msgid "Pipeline"
msgstr ""
msgid "Pipeline Health"
@@ -5409,15 +5952,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5427,6 +5979,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5454,12 +6012,6 @@ msgstr ""
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5469,12 +6021,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5487,6 +6045,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5499,9 +6060,18 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5547,15 +6117,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5568,39 +6153,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -5610,6 +6276,15 @@ msgstr ""
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5646,6 +6321,9 @@ msgstr ""
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr ""
@@ -5673,6 +6351,9 @@ msgstr ""
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr ""
@@ -5700,6 +6381,27 @@ msgstr ""
msgid "ProjectLifecycle|Stage"
msgstr ""
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5742,6 +6444,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5811,9 +6516,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -6006,6 +6708,12 @@ msgstr ""
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6068,12 +6776,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr ""
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6083,6 +6800,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6092,18 +6812,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6116,6 +6851,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6149,10 +6887,10 @@ msgstr ""
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr ""
msgid "Reset health check access token"
@@ -6170,9 +6908,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6223,9 +6973,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6235,6 +7000,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6259,6 +7030,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6283,6 +7057,9 @@ msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr ""
@@ -6337,15 +7114,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6370,27 +7156,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard"
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6408,9 +7222,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr ""
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr ""
@@ -6441,6 +7261,9 @@ msgstr ""
msgid "Select target branch"
msgstr ""
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6453,6 +7276,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6477,6 +7303,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr ""
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6495,7 +7324,10 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
@@ -6507,13 +7339,31 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
-msgid "Settings"
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
msgstr ""
msgid "Share"
@@ -6525,6 +7375,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6608,12 +7461,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6641,9 +7500,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6656,12 +7521,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -6692,6 +7569,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6722,6 +7602,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6752,6 +7635,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6827,9 +7713,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr ""
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6842,6 +7740,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6851,6 +7752,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6860,9 +7764,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6875,6 +7785,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -6893,6 +7809,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -6997,6 +7916,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -7045,12 +7967,6 @@ msgstr ""
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7099,9 +8015,6 @@ msgstr ""
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr ""
@@ -7111,21 +8024,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr ""
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr ""
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7135,6 +8042,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7144,7 +8054,13 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
msgstr ""
msgid "There was an error adding a todo."
@@ -7192,10 +8108,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7216,6 +8135,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7255,7 +8177,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7276,6 +8201,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
@@ -7300,6 +8228,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7309,6 +8240,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7336,9 +8273,15 @@ msgstr ""
msgid "Time before an issue starts implementation"
msgstr ""
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr ""
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7529,12 +8472,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7550,6 +8505,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7562,12 +8520,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7577,9 +8538,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7595,6 +8562,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7610,6 +8580,9 @@ msgstr ""
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7619,6 +8592,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7637,24 +8613,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7670,6 +8664,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7703,13 +8703,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7739,15 +8742,15 @@ msgstr ""
msgid "Upload file"
msgstr ""
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr ""
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7775,6 +8778,9 @@ msgstr ""
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7784,10 +8790,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7814,6 +8862,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7847,9 +8904,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7868,6 +8931,36 @@ msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr ""
@@ -7907,6 +9000,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8057,6 +9156,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8075,9 +9177,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8087,9 +9186,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8111,12 +9207,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8138,9 +9240,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr ""
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8150,6 +9249,12 @@ msgstr ""
msgid "You need permission."
msgstr ""
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr ""
@@ -8216,6 +9321,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8237,16 +9345,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
msgid "assign yourself"
msgstr ""
@@ -8274,61 +9372,78 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8361,9 +9476,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8386,6 +9498,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8404,13 +9519,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8419,9 +9528,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8452,9 +9558,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8466,9 +9569,6 @@ msgstr[1] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8498,25 +9598,17 @@ msgstr[1] ""
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
-
msgid "disabled"
msgstr ""
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "enabled"
msgstr ""
@@ -8526,6 +9618,12 @@ msgstr ""
msgid "for this project"
msgstr ""
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -8555,6 +9653,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8783,6 +9884,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8801,6 +9905,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr ""
@@ -8829,6 +9936,11 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "remaining"
msgstr ""
@@ -8841,6 +9953,11 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "source"
msgstr ""
@@ -8856,6 +9973,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po
index c8f5cf5cae8..b61022903da 100644
--- a/locale/uk/gitlab.po
+++ b/locale/uk/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Ukrainian\n"
"Language: uk_UA\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: uk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:33\n"
+"PO-Revision-Date: 2018-11-19 17:20\n"
msgid " Status"
msgstr " СтатуÑ"
@@ -35,6 +35,16 @@ msgstr[1] " покращилоÑÑ Ð½Ð° %d одиниць"
msgstr[2] " покращилоÑÑ Ð½Ð° %d одиниць"
msgstr[3] " покращилоÑÑ Ð½Ð° %d одиниць"
+msgid "\"%{query}\" in projects"
+msgstr "\"%{query}\" в проектах"
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] "%d доповненнÑ"
+msgstr[1] "%d доповненнÑ"
+msgstr[2] "%d доповнень"
+msgstr[3] "%d доповнень"
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] "%d змінений файл"
@@ -56,6 +66,13 @@ msgstr[1] "%d коміта позаду"
msgstr[2] "%d комітів позаду"
msgstr[3] "%d комітів позаду"
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] "%d видаленнÑ"
+msgstr[1] "%d видаленнÑ"
+msgstr[2] "%d видалень"
+msgstr[3] "%d видалень"
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d екÑпортер"
@@ -65,17 +82,17 @@ msgstr[3] "%d екÑпортерів"
msgid "%d failed test result"
msgid_plural "%d failed test results"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d невдалий результат теÑту"
+msgstr[1] "%d невдалі результати теÑтів"
+msgstr[2] "%d невдалих результатів теÑтів"
+msgstr[3] "%d невдалих результатів теÑтів"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "%d виправлений результат теÑту"
+msgstr[1] "%d виправлені результати теÑту"
+msgstr[2] "%d виправлених результатів теÑту"
+msgstr[3] "%d виправлених результатів теÑту"
msgid "%d issue"
msgid_plural "%d issues"
@@ -119,13 +136,6 @@ msgstr[1] "%d неіндекÑовані зміни"
msgstr[2] "%d неіндекÑованих змін"
msgstr[3] "%d неіндекÑованих змін"
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] "%d вразливіÑÑ‚ÑŒ"
-msgstr[1] "%d вразливоÑтей"
-msgstr[2] "%d вразливоÑтей"
-msgstr[3] "%d вразливоÑтей"
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] "%s доданий коміт був виключений Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð±Ñ–Ð³Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼ із продуктивніÑÑ‚ÑŽ."
@@ -136,12 +146,21 @@ msgstr[3] "%s доданих комітів були виключені Ð´Ð»Ñ Ð
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} Ñ– %{openOrClose} %{noteable}"
+msgid "%{authorsName}'s discussion"
+msgstr "ÐžÐ±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ %{authorsName}"
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "%{commit_author_link} закомітив %{commit_timeago}"
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr "%{counter_storage} (%{counter_repositories} репозиторій, %{counter_build_artifacts} артефактів збірки, %{counter_lfs_objects} LFS)"
+msgid "%{count} %{alerts}"
+msgstr "%{count} %{alerts}"
+
+msgid "%{count} more assignees"
+msgstr "%{count} більше виконавців"
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] "%{count} учаÑтник"
@@ -149,15 +168,25 @@ msgstr[1] "%{count} учаÑтника"
msgstr[2] "%{count} учаÑтників"
msgstr[3] "%{count} учаÑтників"
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{filePath} deleted"
msgstr "%{filePath} видалено"
msgid "%{firstLabel} +%{labelCount} more"
-msgstr ""
+msgstr "%{firstLabel} +%{labelCount} більше"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}Групи%{group_docs_link_end} дозволÑÑŽÑ‚ÑŒ вам керувати Ñ– взаємодіÑти між кількома проектами. Члени групи мають доÑтуп до уÑÑ–Ñ… Ñ—Ñ— проектів."
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr "%{issuableType} буде видалено! Ви впевнені?"
+
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} Початок"
@@ -173,25 +202,12 @@ msgstr "%{nip_domain} може бути викориÑтана Ñк альтер
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "на %{number_commits_behind} комітів позаду %{default_branch}, на %{number_commits_ahead} комітів попереду"
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr "%{number_of_failures} від %{maximum_failures} невдач. GitLab надаÑÑ‚ÑŒ доÑтуп на наÑтупну Ñпробу."
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr "%{number_of_failures} від %{maximum_failures} невдач. GitLab автоматично не повторюватиме Ñпробу. Скиньте інформацію Ñховища при уÑуненні проблеми."
-
msgid "%{openOrClose} %{noteable}"
msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
msgstr "%{percent}%% завершено"
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] "%{storage_name}: Ñпроба невдалого доÑтупу до Ñховища на хоÑÑ‚Ñ–:"
-msgstr[1] "%{storage_name}: %{failed_attempts} невдалі Ñпроби доÑтупу до Ñховища:"
-msgstr[2] "%{storage_name}: %{failed_attempts} невдалих Ñпроб доÑтупу до Ñховища:"
-msgstr[3] "%{storage_name}: %{failed_attempts} невдалих Ñпроб доÑтупу до Ñховища:"
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] "%{text} %{files}"
@@ -205,37 +221,15 @@ msgstr "%{text} доÑтупний"
msgid "%{title} changes"
msgstr "%{title} зміни"
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] "%{type} виÑвило 1 вразливіÑÑ‚ÑŒ"
-msgstr[1] "%{type} виÑвило %{vulnerabilityCount} вразливоÑтей"
-msgstr[2] "%{type} виÑвило %{vulnerabilityCount} вразливоÑтей"
-msgstr[3] "%{type} виÑвило %{vulnerabilityCount} вразливоÑтей"
-
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
-
msgid "%{unstaged} unstaged and %{staged} staged changes"
msgstr "%{unstaged} неіндекÑованих та %{staged} проіндекÑованих змін"
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr "%{usage_ping_link_start}ДовідатиÑÑŒ більше%{usage_ping_link_end} про те, Ñкою інформацією Ви ділитеÑÑŒ із GitLab Inc."
+
+msgid "+ %{count} more"
+msgstr "+ ще %{count}"
+
msgid "+ %{moreCount} more"
msgstr "+ ще %{moreCount}"
@@ -359,7 +353,7 @@ msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will ad
msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> додаÑÑ‚ÑŒ \"<a href=\"#\">johnsmith@example.com</a>\" до вÑÑ–Ñ… проблем та коментарів, Ñкі були Ñтворені johnsmith@example.com. За замовчуваннÑм Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача та його електронна адреÑа заблоковані Ð´Ð»Ñ Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑ‡ÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ñ„Ñ–Ð´ÐµÐ½Ñ†Ñ–Ð¹Ð½Ð¾ÑÑ‚Ñ–. ВикориÑтовуйте цю опцію, Ñкщо ви хочете показувати електронну адреÑу повніÑÑ‚ÑŽ."
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
-msgstr ""
+msgstr "<strong>%{changedFilesLength} неіндекÑованих</strong> та <strong>%{stagedFilesLength} індекÑованих</strong> змін"
msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
msgstr "<strong>%{created_count}</strong> Ñтворено, <strong>%{accepted_count}</strong> прийнÑто."
@@ -382,6 +376,15 @@ msgstr "'Runner' — це процеÑ, Ñкий виконує завданнÑ
msgid "A collection of graphs regarding Continuous Integration"
msgstr "Ðабір графіків відноÑно безперервної інтеграції"
+msgid "A default branch cannot be chosen for an empty project."
+msgstr "Гілку за замовчуваннÑм не може бути обрано Ð´Ð»Ñ Ð¿Ð¾Ñ€Ð¾Ð¶Ð½ÑŒÐ¾Ð³Ð¾ проекту."
+
+msgid "A deleted user"
+msgstr "Видалений кориÑтувач"
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr "У вашому форку буде Ñтворено нову гілку, а також буде ініційований новий запит на злиттÑ."
@@ -424,15 +427,12 @@ msgstr "Токени доÑтупу"
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "ДоÑтуп заборонено! Будь-лаÑка, перевірте, чи ви можете додавати ключі Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾ цього Ñховища."
+msgid "Access expiration date"
+msgstr "Дата Ð¿Ñ€Ð¸Ð¿Ð¸Ð½ÐµÐ½Ð½Ñ Ð´Ð¾Ñтупу"
+
msgid "Access to '%{classification_label}' not allowed"
msgstr "ДоÑтуп до \"%{classification_label}\" заборонено"
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr "ДоÑтуп до Ñховищ, що вийшли з ладу, тимчаÑово прибраний Ð·Ð°Ð´Ð»Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¼Ð¾Ð½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ. ПіÑÐ»Ñ Ð²Ð¸Ñ€Ñ–ÑˆÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð¸ обнуліть інформацію Ñховища Ð´Ð»Ñ Ð²Ñ–Ð´Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ñтупу."
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
-msgstr "Отримайте доÑтуп до Gitlab Runner токену, налаштуйте конфігурацію конвеєра та переглÑньте його ÑтатуÑ, а також звіт про покриттÑ."
-
msgid "Account"
msgstr "Обліковий запиÑ"
@@ -460,27 +460,48 @@ msgstr "Додати керівництво Ð´Ð»Ñ ÑƒÑ‡Ð°Ñників"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr "Додайте групові веб-гуки та GitLab Enterprise Edition."
+msgid "Add Jaeger URL"
+msgstr "Додати URL-Ð°Ð´Ñ€ÐµÑ Jaeger"
+
msgid "Add Kubernetes cluster"
msgstr "Додати Kubernetes-клаÑтер"
-msgid "Add License"
-msgstr "Додати ліцензію"
-
msgid "Add Readme"
msgstr "Додати інÑтрукцію"
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr "Додати домашню Ñторінку в вікі, Ñка міÑтить інформацію про ваш проект, Ñ– GitLab відображатиме його тут заміÑÑ‚ÑŒ цього повідомленнÑ."
+
+msgid "Add a table"
+msgstr "Додати таблицю"
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "Створіть додатковий текÑÑ‚, Ñкий буде приÑутній у вÑÑ–Ñ… повідомленнÑÑ… електронної пошти. МакÑимальна кількіÑÑ‚ÑŒ Ñимволів — %{character_limit}"
+msgid "Add comment now"
+msgstr "Додати коментар"
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr "Додати ліцензію"
+
msgid "Add new application"
msgstr "Додати новий додаток"
msgid "Add new directory"
msgstr "Додати новий каталог"
+msgid "Add projects"
+msgstr "Додати проекти"
+
msgid "Add reaction"
msgstr "Додати реакцію"
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr "Додати задачу"
@@ -490,6 +511,9 @@ msgstr "Додати кориÑтувачів до групу:"
msgid "Add users to group"
msgstr "Додати кориÑтувача до групи"
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð½Ð¾Ð²Ð¸Ñ… проектів Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ інÑтанÑу GitLab заборонено. ЗвернітьÑÑ Ð´Ð¾ Ñвого адмініÑтратора GitLab, щоб отримати дозвіл"
+
msgid "Additional text"
msgstr "Додатковий текÑÑ‚"
@@ -503,10 +527,10 @@ msgid "Admin area"
msgstr "ОблаÑÑ‚ÑŒ адмініÑтратора"
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити кориÑтувача %{username}. Пов’Ñзані з ним проблеми, запити на злиттÑ, Ñ– групи будуть переведені на ÑиÑтемного кориÑтувача \"Ghost-user\". Щоб уникнути втрати даних, розглÑньте можливіÑÑ‚ÑŒ %{strong_start}Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача%{strong_end} заміÑÑ‚ÑŒ видаленнÑ. ПіÑÐ»Ñ %{strong_start}Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача%{strong_end}, його неможливо буде відновити."
msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити кориÑтувача %{username}. Ð¦Ñ Ð´Ñ–Ñ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚ÑŒ уÑÑ– проблеми, запити на злиттÑ, Ñ– пов'Ñзані з ним групи. Щоб уникнути втрати даних, розглÑньте можливіÑÑ‚ÑŒ %{strong_start}Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача%{strong_end} заміÑÑ‚ÑŒ видаленнÑ. ПіÑÐ»Ñ %{strong_start}Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача%{strong_end}, його неможливо буде відновити."
msgid "AdminArea|Stop all jobs"
msgstr "Зупинити вÑÑ– завданнÑ"
@@ -523,11 +547,8 @@ msgstr "Зупинка завдань пройшла невдало"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr "Зараз ви зупинете вÑÑ– завданнÑ. Це обірве уÑÑ– запущені завданнÑ."
-msgid "AdminHealthPageLink|health page"
-msgstr "Ñторінка ÑтатуÑу"
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити проект %{projectName}, його репозиторій та вÑÑ– пов'Ñзані реÑурÑи, включаючи проблеми, запити на злиттÑ, тощо. ПіÑÐ»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ‚Ð° натиÑÐ½ÐµÐ½Ð½Ñ Ð½Ð° кнопку %{strong_start}Видалити проект%{strong_end}, його неможливо буде відновити."
msgid "AdminProjects|Delete"
msgstr "Видалити"
@@ -562,12 +583,19 @@ msgstr "Ð”Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð²ÐµÐ´Ñ–Ñ‚ÑŒ %{projectName}"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "Ð”Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð²ÐµÐ´Ñ–Ñ‚ÑŒ %{username}"
-msgid "Advanced"
-msgstr "Розширений"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
msgid "Advanced settings"
msgstr "Додаткові параметри"
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] "ПопередженнÑ"
+msgstr[1] "ПопередженнÑ"
+msgstr[2] "Попереджень"
+msgstr[3] "Попереджень"
+
msgid "All"
msgstr "Ð’ÑÑ–"
@@ -583,6 +611,9 @@ msgstr "Ð’ÑÑ– кориÑтувачі"
msgid "Allow commits from members who can merge to the target branch."
msgstr "Дозволити коміти від учаÑників, Ñкі можуть зливати в цільову гілку."
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr "Дозволити публічний доÑтуп до конвеєрів Ñ– завдань, включно з логами та артефактами"
@@ -592,6 +623,12 @@ msgstr "Дозволити Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ñ–Ð°Ð³Ñ€Ð°Ð¼ PlantUML в Ð
msgid "Allow requests to the local network from hooks and services."
msgstr "Дозволити запити до локальної мережі із гуків та ÑервіÑів."
+msgid "Allow users to request access"
+msgstr "Дозволити кориÑтувачам запитувати доÑтуп"
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "ДозволÑÑ” додавати та керувати клаÑтерами Kubernetes."
@@ -607,9 +644,12 @@ msgstr "Крім того, ви можете викориÑтовувати %{pe
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr "Крім того, ви можете викориÑтовувати %{personal_access_token_link}. Коли ви Ñтворюватимете Ñвій перÑональний токен доÑтупу, вам потрібно буде вибрати облаÑÑ‚ÑŒ <code>repo</code>, щоб ми могли відобразити ÑпиÑок ваших публічних та приватних репозиторіїв, доÑтупних Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ."
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgstr "ПіÑÐ»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ„Ð¾Ñ€Ð¼Ð¸ буде автоматично згенеровано SSH ключ. Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації, звернітьÑÑ Ð´Ð¾ документіції."
+
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr "Додаток під назвою %{link_to_client} запитує доÑтуп до вашого GitLab аккаунту."
@@ -628,8 +668,8 @@ msgstr "Помилка при Ñтворенні нової гілки."
msgid "An error occured whilst fetching the job trace."
msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні логу завданнÑ."
-msgid "An error occured whilst fetching the latest pipline."
-msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні даних оÑтаннього конвеєра."
+msgid "An error occured whilst fetching the latest pipeline."
+msgstr ""
msgid "An error occured whilst loading all the files."
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при завантаженні вÑÑ–Ñ… файлів."
@@ -652,6 +692,12 @@ msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при завантаженні зап
msgid "An error occured whilst loading the pipelines jobs."
msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при завантаженні завдань конвеєру."
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð½Ð¾Ð²Ð¾Ñ— чернетки."
+
msgid "An error occurred previewing the blob"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду об'єкта"
@@ -664,6 +710,9 @@ msgstr "Збій під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ð°Ð³Ð¸ проблеми"
msgid "An error occurred while adding approver"
msgstr "Помилка при додаванні учаÑника Ð´Ð»Ñ Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ"
+msgid "An error occurred while deleting the comment"
+msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ"
+
msgid "An error occurred while detecting host keys"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при виÑвленні ключів хоÑта"
@@ -676,20 +725,23 @@ msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при відхиленні повідом
msgid "An error occurred while fetching markdown preview"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при попередньому переглÑді markdown"
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… Ð´Ð»Ñ Ð±Ñ–Ñ‡Ð½Ð¾Ñ— панелі"
msgid "An error occurred while fetching stages."
-msgstr ""
+msgstr "Помилка при отриманні Ñтадій."
msgid "An error occurred while fetching the job log."
-msgstr ""
+msgstr "Помилка при отриманні логів завданнÑ."
msgid "An error occurred while fetching the job."
-msgstr ""
+msgstr "Помилка при отриманні завданнÑ."
msgid "An error occurred while fetching the jobs."
-msgstr ""
+msgstr "Помилка при отриманні завдань."
msgid "An error occurred while fetching the pipeline."
msgstr "Помилка при отриманні данних конвеєра."
@@ -703,6 +755,9 @@ msgstr "При імпортуванні проекту ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»
msgid "An error occurred while initializing path locks"
msgstr "Помилка при ініціалізації Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð²Ð¸Ñ… шлÑхів"
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при завантаженні Ñигнатур коміту"
@@ -745,12 +800,18 @@ msgstr "Помилка при підпиÑці на ÑповіщеннÑ."
msgid "An error occurred while unsubscribing to notifications."
msgstr "Помилка при відпиÑці від Ñповіщень."
+msgid "An error occurred while updating the comment"
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
+
msgid "An error occurred while validating username"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ імені кориÑтувача"
msgid "An error occurred. Please try again."
msgstr "СталаÑÑŒ помилка. Спробуйте ще раз."
+msgid "Analytics"
+msgstr "Ðналітика"
+
msgid "Anonymous"
msgstr "Ðнонімно"
@@ -769,8 +830,8 @@ msgstr "Зовнішній виглÑд"
msgid "Application"
msgstr "Додаток"
-msgid "Application Id"
-msgstr "Id додатку"
+msgid "Application ID"
+msgstr ""
msgid "Application: %{name}"
msgstr "Додаток: %{name}"
@@ -787,14 +848,20 @@ msgstr "квітень"
msgid "Archived project! Repository and other project resources are read-only"
msgstr "Ðрхівований проект! Репозиторій та інші реÑурÑи проекту доÑтупні лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ"
+msgid "Archived projects"
+msgstr "Заархівовані проекти"
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "Ви впевнені, що хочете видалити цей розклад Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ð°?"
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "Ви впевнені, що бажаєте втратити незбережені зміни?"
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
-msgstr ""
+msgstr "Ви впевнені, що хочете повторно згенерувати відкритий ключ? Вам доведетьÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ відкритий ключ на віддаленому Ñервері, перш ніж Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÑŽÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ñ€Ð°Ñ†ÑŽÑ” знову."
msgid "Are you sure you want to remove %{group_name}?"
msgstr "Ви впевнені, що хочете видалити %{group_name}?"
@@ -808,6 +875,9 @@ msgstr "Ви впевнені, що бажаєте перегенерувати
msgid "Are you sure you want to reset the health check token?"
msgstr "Ви впевнені, що Ви хочете перегенерувати цей ключ перевірки працездатноÑÑ‚Ñ–?"
+msgid "Are you sure you want to stop this environment?"
+msgstr "Ви впевнені що хочете зупинити це Ñередовище?"
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "Ви впевнені, що хочете розблокувати %{path_lock_path}?"
@@ -824,7 +894,7 @@ msgid "Ascending"
msgstr "За зроÑтаннÑм"
msgid "Ask your group maintainer to set up a group Runner."
-msgstr "ПопроÑÑ–Ñ‚ÑŒ керівника групи, щоб налаштувати груповий Runner."
+msgstr "ЗвернітьÑÑ Ð´Ð¾ керівника групи, щоб налаштувати груповий Runner."
msgid "Assertion consumer service URL"
msgstr "URL-адреÑа Ñлужби обробника тверджень"
@@ -848,7 +918,7 @@ msgid "Assigned Merge Requests"
msgstr "Призначені запити на злиттÑ"
msgid "Assigned to :name"
-msgstr "Призначено :ім'Ñ"
+msgstr "Призначено :name"
msgid "Assigned to me"
msgstr "Призначено мені"
@@ -857,7 +927,7 @@ msgid "Assignee"
msgstr "Виконавець"
msgid "Assignee lists not available with your current license"
-msgstr ""
+msgstr "СпиÑки виконавців не доÑтупні з вашою поточною ліцензією"
msgid "Assignee lists show all issues assigned to the selected user."
msgstr "СпиÑки виконавців показують уÑÑ– проблеми, призначені вибраному кориÑтувачу."
@@ -946,6 +1016,9 @@ msgstr "AutoDevOps буде автоматично збирати, теÑтувÐ
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ в %{link_to_documentation}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr "Конвеєр Auto DevOps увімкнено Ñ– буде викориÑтовуватиÑÑ, Ñкщо не знайдено жодного альтернативного файлу конфігурації CI. %{more_information_link}"
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr "Ви можете автоматично збирати й теÑтувати ваш заÑтоÑунок, Ñкщо %{link_to_auto_devops_settings} Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту. Ви також можете його автоматично розгортати, Ñкщо %{link_to_add_kubernetes_cluster}."
@@ -956,7 +1029,7 @@ msgid "AutoDevOps|enable Auto DevOps"
msgstr "Увімкнути Auto DevOps"
msgid "Automatically marked as default internal user"
-msgstr ""
+msgstr "Ðвтоматично позначено Ñк внутрішній кориÑтувач за замовчуваннÑм"
msgid "Available"
msgstr "ДоÑтупно"
@@ -982,9 +1055,6 @@ msgstr "Фонові завданнÑ"
msgid "Background color"
msgstr "Колір фону"
-msgid "Background jobs"
-msgstr "Фонові завданнÑ"
-
msgid "Badges"
msgstr "Значки"
@@ -1025,7 +1095,7 @@ msgid "Badges|No image to preview"
msgstr "Ðемає Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду"
msgid "Badges|Please fill in a valid URL"
-msgstr ""
+msgstr "Будь лаÑка, введіть дійÑну URL-адреÑу"
msgid "Badges|Project Badge"
msgstr "Значок проекту"
@@ -1055,12 +1125,21 @@ msgid "Badges|This project has no badges"
msgstr "У цього проекту немає значків"
msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr ""
+msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ цей значок. Вилучені значки <strong>не можуть</strong> бути відновлені."
msgid "Badges|Your badges"
msgstr "Ваші значки"
msgid "Badges|e.g. %{exampleUrl}"
+msgstr "напр. %{exampleUrl}"
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
msgstr ""
msgid "Begin with the selected commit"
@@ -1329,7 +1408,7 @@ msgid "CI / CD Settings"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CI/CD"
msgid "CI will run using the credentials assigned above."
-msgstr ""
+msgstr "CI буде працювати з викориÑтаннÑм облікових даних, визначених вище."
msgid "CI/CD"
msgstr "CI/CD"
@@ -1355,9 +1434,12 @@ msgstr "Ðвтоматичне Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° staging, ручне Ñ
msgid "CICD|Continuous deployment to production"
msgstr "Безперервне Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° production"
-msgid "CICD|Default to Auto DevOps pipeline"
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
msgstr ""
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr "За замовчуваннÑм Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ð° Auto DevOps"
+
msgid "CICD|Deployment strategy"
msgstr "Ð¡Ñ‚Ñ€Ð°Ñ‚ÐµÐ³Ñ–Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ"
@@ -1374,20 +1456,17 @@ msgid "CICD|Learn more about Auto DevOps"
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Auto DevOps"
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
-msgstr ""
+msgstr "Конвеєр Auto DevOps буде запущено, Ñкщо не буде знайдено альтернативного файлу конфігуріції CI."
msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
msgstr "Вам потрібно вказати домен, Ñкщо ви хочете викориÑтовувати Auto Review Apps та Auto Deploy."
msgid "CICD|instance enabled"
-msgstr ""
+msgstr "ІнÑÑ‚Ð°Ð½Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð¾"
msgid "Callback URL"
msgstr "URL зворотнього виклику"
-msgid "Callback url"
-msgstr "URL зворотнього виклику"
-
msgid "Can't find HEAD commit for this branch"
msgstr "Ðе можу знайти HEAD-коміт Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— гілки"
@@ -1442,8 +1521,8 @@ msgstr "СтатиÑтика"
msgid "Chat"
msgstr "Чат"
-msgid "Check interval"
-msgstr "Інтервал перевірки"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
msgid "Checking %{text} availability…"
msgstr "Перевірка доÑтупноÑÑ‚Ñ– %{text}…"
@@ -1469,6 +1548,12 @@ msgstr "Виберіть файл ..."
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr "Виберіть гілку чи тег (напр. %{master}) або введіть коміт (напр. %{sha}) Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду змін або Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на злиттÑ."
+msgid "Choose a template..."
+msgstr "Виберіть тему-шаблон..."
+
+msgid "Choose a type..."
+msgstr "Виберіть тип..."
+
msgid "Choose any color."
msgstr "Вибрати будь-Ñкий колір."
@@ -1499,6 +1584,9 @@ msgstr "ÑкаÑовано"
msgid "CiStatusLabel|created"
msgstr "Ñтворено"
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr "невдало"
@@ -1517,6 +1605,9 @@ msgstr "в очікуванні"
msgid "CiStatusLabel|skipped"
msgstr "пропущено"
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr "ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÑƒÑ‡Ð½Ð¸Ñ… дій"
@@ -1529,6 +1620,9 @@ msgstr "ÑкаÑовано"
msgid "CiStatusText|created"
msgstr "Ñтворено"
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr "невдало"
@@ -1583,12 +1677,12 @@ msgstr "Ввімкнути/вимкнути захиÑÑ‚"
msgid "CiVariable|Validation failed"
msgstr "Перевірка невдала"
-msgid "CircuitBreakerApiLink|circuitbreaker api"
-msgstr "circuitbreaker api"
-
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "не доÑтупно: %{reason}"
+msgid "Clear search"
+msgstr "ОчиÑтити пошук"
+
msgid "Clear search input"
msgstr "ОчиÑтити поле вводу"
@@ -1631,6 +1725,9 @@ msgstr "Клонувати репозиторій"
msgid "Close"
msgstr "Закрити"
+msgid "Close epic"
+msgstr "Закрити епік"
+
msgid "Closed"
msgstr "Закрито"
@@ -1641,6 +1738,9 @@ msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernet
msgstr "%{appList} були уÑпішно вÑтановлені на ваш Kubernetes-клаÑтер"
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
+msgstr "%{boldNotice} Це додаÑÑ‚ÑŒ додаткові реÑурÑи, такі Ñк баланÑувальник навантаженнÑ, Ñкий може збільшити витрати в залежноÑÑ‚Ñ– від провайдера хоÑтингу, на Ñкому вÑтановлено клаÑтер Kubernetes. Якщо ви викориÑтовуєте Google Kubernetes Engine, ви можете %{pricingLink}."
+
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
msgstr ""
msgid "ClusterIntegration|API URL"
@@ -1649,11 +1749,20 @@ msgstr "API URL"
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr "Додати Kubernetes клаÑтер"
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr "Додати інтеграцію із клаÑтером Kubernetes"
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Детальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ— із цим Kubernetes-клаÑтером"
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
-msgstr ""
+msgstr "ПіÑÐ»Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ingress, вам необхідно направити Ñвій DNS на згенеровану зовнішню IP-адреÑу, щоб переглÑнути ваш заÑтоÑунок піÑÐ»Ñ Ð¹Ð¾Ð³Ð¾ розгортаннÑ. %{ingressHelpLink}"
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr "Помилка при отриманні зон проекту: %{error}"
@@ -1662,10 +1771,10 @@ msgid "ClusterIntegration|An error occured while trying to fetch your projects:
msgstr "Помилка при отриманні ваших проектів: %{error}"
msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
-msgstr ""
+msgstr "Помилка при отриманні типів машин зони: %{error}"
msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
-msgstr ""
+msgstr "Помилка під Ñ‡Ð°Ñ Ð·'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· Google Cloud API. Будь лаÑка, Ñпробуйте знову пізніше."
msgid "ClusterIntegration|Applications"
msgstr "ЗаÑтоÑунки"
@@ -1679,11 +1788,11 @@ msgstr "Сертифікат центру Ñертифікації"
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "Ðабір Ñертифікатів (формат PEM)"
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
-msgstr "Виберіть Ñкі з Ñередовищ вашого проекту викориÑтовуватимуть цей Kubernetes-клаÑтер."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr "Виберіть, Ñкі заÑтоÑунки необхідно вÑтановити на ваш клаÑтер Kubernetes. Ð”Ð»Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ´ÑŒ-Ñкого з наÑтупних заÑтоÑунків потрібен Helm Tiller."
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
-msgstr "Керуйте ÑпоÑобом інтеграції вашого Kubernetes-клаÑтера з GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr "Виберіть, Ñке із ваших Ñередовищ буде викориÑтовувати цей клаÑтер."
msgid "ClusterIntegration|Copy API URL"
msgstr "Скопіювати API URL"
@@ -1709,6 +1818,12 @@ msgstr "Створити Kubernetes-клаÑтер"
msgid "ClusterIntegration|Did you know?"
msgstr "Чи знаєте ви?"
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr "Увімкніть або вимкніть Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ GitLab до клаÑтера Kubernetes."
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr "Увімкніть цей параметр, Ñкщо викориÑтовуєтьÑÑ Ñ€Ð¾Ð»ÑŒÐ¾Ð²Ðµ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупом (RBAC)."
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr "Введіть параметри вашого Kubernetes-клаÑтера"
@@ -1734,7 +1849,7 @@ msgid "ClusterIntegration|GitLab Runner"
msgstr "GitLab Runner"
msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
-msgstr ""
+msgstr "GitLab Runner з'єднаєтьÑÑ Ð· цим проектом Ñ– виконає CI/CD завданнÑ, відправить результати Ñ– розгорне заÑтоÑунки на production."
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Проект Google Cloud Platform"
@@ -1745,6 +1860,9 @@ msgstr "Google Kubernetes Engine"
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr "проекті Google Kubernetes Engine"
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
@@ -1775,9 +1893,6 @@ msgstr "Ð’Ñтановити"
msgid "ClusterIntegration|Install Prometheus"
msgstr "Ð’Ñтановити Prometheus"
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr "Ð’Ñтановіть заÑтоÑунки у ваш Kubernetes клаÑтер. Докладніше про %{helpLink}"
-
msgid "ClusterIntegration|Installed"
msgstr "Ð’Ñтановлений"
@@ -1799,6 +1914,12 @@ msgstr "JupyterHub"
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
+msgid "ClusterIntegration|Knative"
+msgstr "Knative"
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr "Kubernetes-клаÑтер"
@@ -1808,18 +1929,6 @@ msgstr "Параметри Kubernetes-клаÑтера"
msgid "ClusterIntegration|Kubernetes cluster health"
msgstr "Стан Kubernetes-клаÑтера"
-msgid "ClusterIntegration|Kubernetes cluster integration"
-msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ñ–Ð· Kubernetes-клаÑтером"
-
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
-msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ñ–Ð· Kubernetes-клаÑтером вимкнена Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту."
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
-msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ñ–Ð· Kubernetes-клаÑтером увімкнена Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту."
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
-msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ñ–Ð· Kubernetes-клаÑтером увімкнена Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту. Ð’Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ñ†Ñ–Ñ”Ñ— інтеграції не вплине на клаÑтер, а лише тимчаÑово перерве Ð·â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· GitLab."
-
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
msgstr "Kubernetes-клаÑтер ÑтворюєтьÑÑ Ð½Ð° Google Kubernetes Engine..."
@@ -1829,8 +1938,8 @@ msgstr "Ð†Ð¼â€™Ñ Kubernetes-клаÑтера"
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr "Kubernetes-клаÑтер був уÑпішно Ñтворений на Google Kubernetes Engine. Оновіть Ñторінку, щоб побачити параметри клаÑтера"
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
-msgstr "Kubernetes-клаÑтери дозволÑÑŽÑ‚ÑŒ вам викориÑтовувати Review Apps, розгортати ваші заÑтоÑунки, запуÑкати конвеєри Ñ– багато іншого проÑтим ÑпоÑобом. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
msgstr "Kubernetes-клаÑтери можуть бути викориÑтані Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð·Ð°ÑтоÑунків Ñ– викориÑÑ‚Ð°Ð½Ð½Ñ Review Apps Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту"
@@ -1838,17 +1947,14 @@ msgstr "Kubernetes-клаÑтери можуть бути викориÑтані
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про %{help_link_start_machine_type}типи машин%{help_link_end} та %{help_link_start_pricing}ціни%{help_link_end}."
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про %{help_link_start}Kubernetes%{help_link_end}."
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про %{help_link_start}зони%{help_link_end}."
-msgid "ClusterIntegration|Learn more about environments"
-msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Ñередовища"
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про Kubernetes"
-msgid "ClusterIntegration|Learn more about security configuration"
-msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про конфігурацію безпеки"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
msgid "ClusterIntegration|Machine type"
msgstr "Тип машини"
@@ -1865,9 +1971,6 @@ msgstr "Керуйте вашим Kubernetes-клаÑтером за допомÐ
msgid "ClusterIntegration|More information"
msgstr "Додаткова інформаціÑ"
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr "Декілька Kubernetes-клаÑтерів доÑтупні в GitLab Enterprise Edition Premium та Ultimate"
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr "Жоден тип машин не відповідає вашому пошуку"
@@ -1895,6 +1998,9 @@ msgstr "Будь-лаÑка впевнітьÑÑ, що ваш обліковий
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr "КлаÑтер проекту"
+
msgid "ClusterIntegration|Project namespace"
msgstr "ПроÑÑ‚Ñ–Ñ€ імен проекту"
@@ -1907,6 +2013,9 @@ msgstr "Prometheus"
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr "КлаÑтер з підтримкою RBAC"
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr "ПереглÑньте нашу %{link_to_help_page} про інтеграцію із Kubernetes."
@@ -1937,9 +2046,6 @@ msgstr "Пошук проектів"
msgid "ClusterIntegration|Search zones"
msgstr "Пошук зон"
-msgid "ClusterIntegration|Security"
-msgstr "Безпека"
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "ПереглÑнути та редагувати параметри вашого Kubernetes-клаÑтера"
@@ -1979,14 +2085,11 @@ msgstr "Під Ñ‡Ð°Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ %{title} ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr "Стандартна ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ ÐºÐ»Ð°Ñтера надає доÑтуп до широкого набору функцій, необхідних Ð´Ð»Ñ ÑƒÑпішного ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð° Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð·Ð°ÑтоÑунків-контейнерів."
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr "Цей обліковий Ð·Ð°Ð¿Ð¸Ñ Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ мати наÑтупні права Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Kubernetes-клаÑтера в %{link_to_container_project}"
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
-msgstr "Увімкнути/вимкнути Kubernetes-клаÑтер"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr "Цей параметр дозволить вам вÑтановлювати заÑтоÑунки на клаÑтери RBAC."
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "Увімкнути/вимкнути Kubernetes-клаÑтер"
@@ -2003,6 +2106,9 @@ msgstr "Ми не змогли перевірити, що один із ваши
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "За допомогою підключеного до цього проекту Kubernetes-клаÑтера, ви можете викориÑтовувати Review Apps, розгортати ваші проекти, запуÑкати конвеєри збірки тощо."
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr "Перед вÑтановленнÑм заÑтоÑунків нижче, необхідно вÑтановити Helm Tiller"
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ мати %{link_to_kubernetes_engine}"
@@ -2021,9 +2127,6 @@ msgstr "документації"
msgid "ClusterIntegration|help page"
msgstr "Ñторінка допомоги"
-msgid "ClusterIntegration|installing applications"
-msgstr "вÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð°ÑтоÑунків"
-
msgid "ClusterIntegration|meets the requirements"
msgstr "задовольнÑÑ” вимогам"
@@ -2031,7 +2134,10 @@ msgid "ClusterIntegration|properly configured"
msgstr "правильно налаштований"
msgid "ClusterIntegration|sign up"
-msgstr "зареєÑтрувати"
+msgstr "реєÑтрації"
+
+msgid "Code owners"
+msgstr "ВлаÑники коду"
msgid "Cohorts"
msgstr "Когорти"
@@ -2040,7 +2146,10 @@ msgid "Collapse"
msgstr "Згорнути"
msgid "Collapse sidebar"
-msgstr "Згорнути бокову панель"
+msgstr "Згорнути панель"
+
+msgid "Comment"
+msgstr "Коментар"
msgid "Comment & resolve discussion"
msgstr "Залишити коментар Ñ– завершити обговореннÑ"
@@ -2048,6 +2157,9 @@ msgstr "Залишити коментар і завершити обговоре
msgid "Comment & unresolve discussion"
msgstr "Залишити коментар Ñ– повторно відкрити обговореннÑ"
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr "Коментарі"
@@ -2086,6 +2198,9 @@ msgstr "Коміт"
msgid "CommitMessage|Add %{file_name}"
msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ %{file_name}"
+msgid "CommitWidget|authored"
+msgstr "автор"
+
msgid "Commits"
msgstr "Коміти"
@@ -2158,8 +2273,8 @@ msgstr "КонфіденційніÑÑ‚ÑŒ"
msgid "Configure Gitaly timeouts."
msgstr "Ðалаштувати таймаути Gitaly."
-msgid "Configure Sidekiq job throttling."
-msgstr "Ðалаштувати чаÑтоту завдань Sidekiq."
+msgid "Configure Tracing"
+msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr "Ðалаштувати автоматичні перевірки git Ñ– Ð¾Ñ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð² репозиторіÑÑ…."
@@ -2167,11 +2282,11 @@ msgstr "Ðалаштувати автоматичні перевірки git Ñ–
msgid "Configure limits for web and API requests."
msgstr "Ðалаштуйте Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð²ÐµÐ± та API запитів."
-msgid "Configure push and pull mirrors."
-msgstr "Ðалаштуйте вхідні та вихідні дзеркала."
+msgid "Configure push mirrors."
+msgstr "Ðалаштуйте вихідні дзеркала."
-msgid "Configure storage path and circuit breaker settings."
-msgstr "Ðалаштуйте шлÑÑ… до Ñховищ та circuit breaker."
+msgid "Configure storage path settings."
+msgstr ""
msgid "Configure the %{link} integration."
msgstr ""
@@ -2260,6 +2375,9 @@ msgstr "ВнеÑок"
msgid "Contribution guide"
msgstr "ІнÑÑ‚Ñ€ÑƒÐºÑ†Ñ–Ñ Ð´Ð»Ñ ÑƒÑ‡Ð°Ñників"
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr "ВнеÑки за <strong>%{calendar_date}</strong>"
+
msgid "Contributions per group member"
msgstr "КількіÑÑ‚ÑŒ внеÑків на кожного учаÑника групи"
@@ -2293,6 +2411,18 @@ msgstr "Ð’Ñтановіть макÑимальну кількіÑÑ‚ÑŒ параÐ
msgid "ConvDev Index"
msgstr "Ð†Ð½Ð´ÐµÐºÑ ConvDev"
+msgid "Copy %{protocol} clone URL"
+msgstr "Скопіювати URL Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· %{protocol}"
+
+msgid "Copy HTTPS clone URL"
+msgstr "Скопіювати URL Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· HTTPS"
+
+msgid "Copy ID to clipboard"
+msgstr "Скопіювати ID в буфер обміну"
+
+msgid "Copy SSH clone URL"
+msgstr "Скопіювати URL Ð´Ð»Ñ ÐºÐ»Ð¾Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· SSH"
+
msgid "Copy SSH public key to clipboard"
msgstr "Скопіюйте відкритий SSH-ключ в буфер обміну"
@@ -2314,15 +2444,27 @@ msgstr "Скопіювати шлÑÑ… до файлу в буфер обміну
msgid "Copy incoming email address to clipboard"
msgstr "Копіювати адреÑу електронної пошти у буфер обміну"
+msgid "Copy link"
+msgstr "Скопіювати поÑиланнÑ"
+
+msgid "Copy name to clipboard"
+msgstr "Скопіювати ім'Ñ Ð² буфер обміну"
+
msgid "Copy reference to clipboard"
msgstr "Скопіювати поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð² буфер обміну"
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr "Копіювати в буфер обміну"
msgid "Copy token to clipboard"
msgstr "Скопіювати токен в буфер обміну"
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr "Створити"
@@ -2398,8 +2540,8 @@ msgstr "Створити..."
msgid "Create project label"
msgstr "Створити мітку проекту"
-msgid "CreateNewFork|Fork"
-msgstr "Форк"
+msgid "Create your first page"
+msgstr "Створити вашу першу Ñторінку"
msgid "CreateTag|Tag"
msgstr "Тег"
@@ -2449,6 +2591,9 @@ msgstr "ВлаÑний"
msgid "Custom CI config path"
msgstr "КориÑтувацький шлÑÑ… до CI config"
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr "КориÑтувацькі Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½ÑŒ про події"
@@ -2467,6 +2612,9 @@ msgstr "Ðалаштуйте, Ñк адреÑи електронної поштÐ
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr "Ðалаштуйте, Ñк адреÑи електронної пошти та імена кориÑтувачів Google Code імпортуютьÑÑ Ð² GitLab. Ðа наÑтупному кроці ви зможете вибрати проекти, Ñкі потрібно імпортувати."
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr "Ðналіз циклу"
@@ -2504,7 +2652,7 @@ msgid "DashboardProjects|Personal"
msgstr "ОÑобиÑÑ‚Ñ–"
msgid "Date picker"
-msgstr ""
+msgstr "Вибір дати"
msgid "Debug"
msgstr "Відладка"
@@ -2518,6 +2666,9 @@ msgstr "грудень"
msgid "Decline and sign out"
msgstr "Відхити та вийти"
+msgid "Default Branch"
+msgstr "Гілка за замовчуваннÑм"
+
msgid "Default classification label"
msgstr "Мітка клаÑифікації за замовчуваннÑм"
@@ -2530,15 +2681,33 @@ msgstr "По замовчуванню: викориÑтовувати ідент
msgid "Define a custom pattern with cron syntax"
msgstr "Визначте влаÑний шаблон за допомогою ÑинтакÑиÑу cron"
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr "Почати зараз"
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr "відкладено"
+
msgid "Delete"
msgstr "Видалити"
msgid "Delete Package"
-msgstr ""
+msgstr "Видалити пакет"
msgid "Delete Snippet"
msgstr "Видалити Ñніпет"
+msgid "Delete comment"
+msgstr "Видалити коментар"
+
msgid "Delete list"
msgstr "Видалити ÑпиÑок"
@@ -2592,7 +2761,7 @@ msgid "DeployKeys|Privately accessible deploy keys"
msgstr "Приватні ключі розгортаннÑ"
msgid "DeployKeys|Project usage"
-msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ Ñƒ проектах"
+msgstr "ВикориÑтовуєтьÑÑ Ñƒ проектах"
msgid "DeployKeys|Publicly accessible deploy keys"
msgstr "Публічні колючі розгортаннÑ"
@@ -2678,6 +2847,12 @@ msgstr "Ваш новий токер розгортаннÑ"
msgid "DeployTokens|Your new project deploy token has been created."
msgstr "Створено ваш новий токен Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñƒ."
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr "Зменшити пріоритет мітки"
@@ -2700,6 +2875,12 @@ msgid "Details"
msgstr "Деталі"
msgid "Detect host keys"
+msgstr "ВиÑÐ²Ð»ÐµÐ½Ð½Ñ ÐºÐ»ÑŽÑ‡Ñ–Ð² хоÑта"
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
msgstr ""
msgid "Diffs|No file name available"
@@ -2723,12 +2904,27 @@ msgstr "Вимкнути Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту"
msgid "Disable group Runners"
msgstr "Вимкнути групові Runner'и"
+msgid "Discard"
+msgstr "СкаÑувати"
+
+msgid "Discard all changes"
+msgstr "СкаÑувати вÑÑ– зміни"
+
+msgid "Discard all unstaged changes?"
+msgstr "СкаÑувати вÑÑ– неіндекÑовані зміни?"
+
msgid "Discard changes"
msgstr "Відхилити зміни"
+msgid "Discard changes to %{path}?"
+msgstr "СкаÑувати зміни до %{path}?"
+
msgid "Discard draft"
msgstr "Видалити чернетку"
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr "Відкрийте GitLab Geo."
@@ -2744,6 +2940,9 @@ msgstr "Відхилити блок вÑтупу до Ðналитики ЦикÐ
msgid "Dismiss Merge Request promotion"
msgstr "Видалити Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ запит на злиттÑ"
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "Ви хочете налаштувати, Ñк адреÑи електронної пошти та імена кориÑтувачів будуть імпортовані з Google Code в GitLab?"
@@ -2825,8 +3024,8 @@ msgstr "Редагувати ідентифікацію Ð´Ð»Ñ %{user_name}"
msgid "Elasticsearch"
msgstr "Elasticsearch"
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
-msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ð· Elasticsearch. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
msgid "Email"
msgstr "Електронна пошта"
@@ -2870,9 +3069,6 @@ msgstr "Увімкнути Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту"
msgid "Enable group Runners"
msgstr "Увімкнути групові Runner'и"
-msgid "Enable or disable certain group features and choose access levels."
-msgstr "Увімкніть або вимкніть певні функції групи та виберіть рівні доÑтупу."
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "Увімкнути чи вимкнути збір даних Ð´Ð»Ñ Pseudonymizer."
@@ -2885,6 +3081,12 @@ msgstr "Увімкнути reCAPTCHA або Akismet та вÑтановити о
msgid "Enable the Performance Bar for a given group."
msgstr "Увімкнути панель продуктивноÑÑ‚Ñ– Ð´Ð»Ñ Ð´Ð°Ð½Ð¾Ñ— групи."
+msgid "Enable usage ping"
+msgstr "Увімкнути викориÑÑ‚Ð°Ð½Ð½Ñ ping"
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr "Увімкніть збір даних про викориÑтаннÑ, щоб отримати загальне уÑÐ²Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ те, Ñк ви викориÑтовуєте GitLab з точки зору функціоналу."
+
msgid "Enabled"
msgstr "Увімкнено"
@@ -2892,7 +3094,7 @@ msgid "Ends at (UTC)"
msgstr "ЗавершуєтьÑÑ Ð¾ (за Грінвічем)"
msgid "Enter in your Bitbucket Server URL and personal access token below"
-msgstr ""
+msgstr "Введіть URL-адреÑу вашого Bitbucket Server Ñ– ключ доÑтупу"
msgid "Enter the issue description"
msgstr "Введіть Ð¾Ð¿Ð¸Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð¸"
@@ -2937,7 +3139,7 @@ msgid "Environments|Environments"
msgstr "Середовища"
msgid "Environments|Environments are places where code gets deployed, such as staging or production."
-msgstr ""
+msgstr "Середовища — це міÑцÑ, куди можна розгорнути код, наприклад staging або production."
msgid "Environments|Job"
msgstr "ЗавданнÑ"
@@ -2955,7 +3157,7 @@ msgid "Environments|No pod name has been specified"
msgstr "Ðе вказано Ñ–Ð¼â€™Ñ pod’а"
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
-msgstr ""
+msgstr "Зверніть увагу, що Ñ†Ñ Ð´Ñ–Ñ Ð·ÑƒÐ¿Ð¸Ð½Ð¸Ñ‚ÑŒ Ñередовище, але це %{emphasisStart}не%{emphasisEnd} впливатиме на будь-Ñке Ñ–Ñнуюче Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· відÑутніÑÑ‚ÑŒ операції зупинки в файлі %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd}."
msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
msgstr "Зверніть увагу, що Ñ†Ñ Ð´Ñ–Ñ Ð·ÑƒÐ¿Ð¸Ð½Ð¸Ñ‚ÑŒ Ñередовище, але це %{emphasis_start}не%{emphasis_end} впливатиме на будь-Ñке Ñ–Ñнуюче Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· відÑутніÑÑ‚ÑŒ операції зупинки в файлі %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end}."
@@ -2987,8 +3189,8 @@ msgstr "Зупинити Ñередовище"
msgid "Environments|Updated"
msgstr "Оновлено"
-msgid "Environments|You don't have any environments right now."
-msgstr "Ви поки не налаштували жодного Ñередовища."
+msgid "Environments|You don't have any environments right now"
+msgstr "Ви поки не налаштували жодного Ñередовища"
msgid "Environments|protected"
msgstr "захищені"
@@ -3009,10 +3211,10 @@ msgid "Epics let you manage your portfolio of projects more efficiently and with
msgstr "Епіки дозволÑÑŽÑ‚ÑŒ керувати вашим портфелем проектів ефективніше та з меншими зуÑиллÑми"
msgid "Epics|An error occurred while saving %{epicDateType} date"
-msgstr ""
+msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при збереженні дати %{epicDateType}"
msgid "Epics|How can I solve this?"
-msgstr ""
+msgstr "Як Ñ Ð¼Ð¾Ð¶Ñƒ це вирішити?"
msgid "Epics|More information"
msgstr "Детальніше"
@@ -3020,10 +3222,10 @@ msgstr "Детальніше"
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3072,10 +3274,10 @@ msgid "Error loading project data. Please try again."
msgstr "Помилка при завантаженні даних проекту. Будь лаÑка, Ñпробуйте знову."
msgid "Error loading template types."
-msgstr ""
+msgstr "Помилка при завантаженні типів шаблонів."
msgid "Error loading template."
-msgstr ""
+msgstr "Помилка при завантаженні шаблону."
msgid "Error occurred when toggling the notification subscription"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´Ð¿Ð¸Ñки на ÑповіщеннÑ"
@@ -3090,7 +3292,7 @@ msgid "Error updating todo status."
msgstr "Помилка при оновленні ÑтатуÑу задачі."
msgid "Error while loading the merge request. Please try again."
-msgstr ""
+msgstr "Помилка при завантаженні запита на злиттÑ. Будь лаÑка, Ñпробуйте знову."
msgid "Estimated"
msgstr "За оцінками"
@@ -3134,6 +3336,12 @@ msgstr "Розгорнути вÑе"
msgid "Expand sidebar"
msgstr "Розгорніть бічну панель"
+msgid "Expiration date"
+msgstr "Термін дії"
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr "ОглÑд"
@@ -3188,15 +3396,24 @@ msgstr "Ðе вдалоÑÑ Ð·Ð¼Ñ–Ð½Ð¸Ñ‚Ð¸ влаÑника"
msgid "Failed to check related branches."
msgstr "Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€Ð¸Ñ‚Ð¸ пов’Ñзані гілки."
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ проблему з дошки, будь лаÑка, Ñпробуйте ще раз."
msgid "Failed to remove mirror."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ дзеркало."
msgid "Failed to remove the pipeline schedule"
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ розклад конвеєра"
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ проблеми. Будь лаÑка, Ñпробуйте ще раз."
@@ -3206,6 +3423,81 @@ msgstr "Помилка"
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr "Швидше, бо повтоно викориÑтовує робочу облаÑÑ‚ÑŒ проекту (викориÑтовуючи clone, Ñкщо та відÑутнÑ)"
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr "URL-адреÑа API"
+
+msgid "FeatureFlags|Active"
+msgstr "Ðктивний"
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr "ÐалаштуваннÑ"
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr "ОпиÑ"
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr "Ðеактивний"
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr "Ðазва"
+
+msgid "FeatureFlags|New"
+msgstr "Ðовий"
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr "СтатуÑ"
+
msgid "Feb"
msgstr "лют."
@@ -3215,11 +3507,14 @@ msgstr "лютий"
msgid "Fields on this page are now uneditable, you can configure"
msgstr "ÐŸÐ¾Ð»Ñ Ð½Ð° цій Ñторінці зараз недоÑтупні Ð´Ð»Ñ Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ, ви можете налаштувати"
+msgid "File templates"
+msgstr "Шаблони файлів"
+
msgid "Files"
msgstr "Файли"
msgid "Files (%{human_size})"
-msgstr "Файли (%{human_size})"
+msgstr "Файлів на %{human_size}"
msgid "Fill in the fields below, turn on <strong>%{enable_label}</strong>, and press <strong>%{save_changes}</strong>"
msgstr "Заповніть Ð¿Ð¾Ð»Ñ Ð½Ð¸Ð¶Ñ‡Ðµ, увімкніть <strong>%{enable_label}</strong> та натиÑніть <strong>%{save_changes}</strong>"
@@ -3227,9 +3522,18 @@ msgstr "Заповніть Ð¿Ð¾Ð»Ñ Ð½Ð¸Ð¶Ñ‡Ðµ, увімкніть <strong>%{ena
msgid "Filter"
msgstr "Фільтр"
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr "Фільтрувати закриті за %{issuable_type}."
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr "Фільтрувати відкриті за %{issuable_type}."
+
msgid "Filter by commit message"
msgstr "Фільтрувати за коміт-повідомленнÑм"
+msgid "Filter..."
+msgstr "Фільтр..."
+
msgid "Find by path"
msgstr "Пошук по шлÑху"
@@ -3245,6 +3549,9 @@ msgstr "Знайдіть щойно розпакований <code>Takeout/Googl
msgid "Fingerprints"
msgstr "Відбитки пальців"
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr "Завершено"
@@ -3257,11 +3564,11 @@ msgstr "відправлено"
msgid "Fixed date"
msgstr "Дата виправленнÑ"
-msgid "Fixed finish date"
-msgstr ""
+msgid "Fixed due date"
+msgstr "ФікÑована дата завершеннÑ"
msgid "Fixed start date"
-msgstr ""
+msgstr "Виправлена дата початку"
msgid "Fixed:"
msgstr "Виправлено:"
@@ -3294,21 +3601,20 @@ msgid "For internal projects, any logged in user can view pipelines and access j
msgstr "Ð”Ð»Ñ Ð²Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ–Ñ… проектів будь-Ñкий зареєÑтрований кориÑтувач може переглÑдати конвеєри та отримати доÑтуп до інформації про роботу (логи та артефакти)"
msgid "For more information, go to the "
+msgstr "Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації, відвідайте "
+
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
msgstr ""
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr "Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації, переглÑньте документацію по %{deactivating_usage_ping_link_start}деактивації даних про викориÑтаннÑ%{deactivating_usage_ping_link_end}."
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr "Ð”Ð»Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¸Ñ… проектів будь-Ñкий кориÑтувач (гіÑÑ‚ÑŒ або вище) може переглÑдати конвеєри та отримати доÑтуп до інформації про роботу (логи та артефакти)"
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr "Ð”Ð»Ñ Ð¿ÑƒÐ±Ð»Ñ–Ñ‡Ð½Ð¸Ñ… проектів будь-Ñкий зареєÑтрований кориÑтувач може переглÑдати конвеєри та отримати доÑтуп до інформації про роботу (логи та артефакти)"
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] "Форк"
-msgstr[1] "Форки"
-msgstr[2] "Форків"
-msgstr[3] "Форків"
-
msgid "ForkedFromProjectPath|Forked from"
msgstr "Форк від"
@@ -3324,6 +3630,9 @@ msgstr "Формат"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr "Знайдено помилки у вашому .gitlab-ci.yml:"
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr "З %{provider_title}"
@@ -3331,7 +3640,7 @@ msgid "From Bitbucket"
msgstr "З Bitbucket"
msgid "From Bitbucket Server"
-msgstr ""
+msgstr "З Bitbucket Server"
msgid "From FogBugz"
msgstr "З FogBugz"
@@ -3349,7 +3658,7 @@ msgid "From merge request merge until deploy to production"
msgstr "Від Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð¾ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° production"
msgid "From milestones:"
-msgstr ""
+msgstr "З етапів:"
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr "Із Ñторінки деталей Kubernetes-клаÑтера, вÑтановіть runner зі ÑпиÑку заÑтоÑунків"
@@ -3366,6 +3675,9 @@ msgstr "Загальні конвеєри"
msgid "Generate a default set of labels"
msgstr "Створити Ñтандартний набір міток"
+msgid "Geo"
+msgstr "Geo"
+
msgid "Geo Nodes"
msgstr "Гео-Вузли"
@@ -3532,19 +3844,31 @@ msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection.
msgstr "Ви налаштували Geo-вузли через незахищене HTTP-з’єднаннÑ. Ми рекомендуємо викориÑтовувати HTTPS."
msgid "Geo|%{name} is scheduled for forced re-download"
-msgstr ""
+msgstr "%{name} заплановано Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð¼ÑƒÑового повторного завантаженнÑ"
msgid "Geo|%{name} is scheduled for re-check"
-msgstr ""
+msgstr "%{name} заплановано Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ñ— перевірки"
msgid "Geo|%{name} is scheduled for re-sync"
-msgstr ""
+msgstr "%{name} заплановано Ð´Ð»Ñ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð½Ð¾Ñ— Ñинхронізації"
+
+msgid "Geo|All"
+msgstr "Ð’ÑÑ–"
msgid "Geo|All projects"
msgstr "Ð’ÑÑ– проекти"
-msgid "Geo|Error message"
-msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ помилку"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr ""
msgid "Geo|Failed"
msgstr "Ðевдало"
@@ -3552,6 +3876,9 @@ msgstr "Ðевдало"
msgid "Geo|File sync capacity"
msgstr "ПропуÑкна здатніÑÑ‚ÑŒ Ñинхронізації файлів"
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr "Групи Ð´Ð»Ñ Ñинхронізації"
@@ -3559,22 +3886,22 @@ msgid "Geo|In sync"
msgstr "Синхронізовано"
msgid "Geo|Last successful sync"
-msgstr ""
+msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ ÑƒÑпішна ÑинхронізаціÑ"
msgid "Geo|Last sync attempt"
-msgstr ""
+msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ Ñпроба Ñинхронізації"
msgid "Geo|Last time verified"
-msgstr ""
+msgstr "ОÑтанній Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸"
msgid "Geo|Never"
msgstr "Ðіколи"
msgid "Geo|Next sync scheduled at"
-msgstr ""
+msgstr "ÐаÑтупна ÑÐ¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð·Ð°Ð¿Ð»Ð°Ð½Ð¾Ð²Ð°Ð½Ð° на"
-msgid "Geo|No errors"
-msgstr "Без помилок"
+msgid "Geo|Not synced yet"
+msgstr ""
msgid "Geo|Pending"
msgstr "В очікуванні"
@@ -3585,6 +3912,9 @@ msgstr "ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñинхронізації"
msgid "Geo|Pending verification"
msgstr "ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸"
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr "Проекти в певних групах"
@@ -3592,22 +3922,28 @@ msgid "Geo|Projects in certain storage shards"
msgstr "Проекти в певних Ñегментах Ñховищ"
msgid "Geo|Recheck"
+msgstr "Повторна перевірка"
+
+msgid "Geo|Recheck all projects"
msgstr ""
msgid "Geo|Redownload"
msgstr "Повторне завантаженнÑ"
+msgid "Geo|Remove"
+msgstr "Видалити"
+
msgid "Geo|Repository sync capacity"
msgstr "ПропуÑкна здатніÑÑ‚ÑŒ Ñинхронізації репозиторіїв"
msgid "Geo|Resync"
-msgstr ""
+msgstr "Повторна ÑинхронізаціÑ"
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
-msgstr ""
+msgid "Geo|Retry count"
+msgstr "КількіÑÑ‚ÑŒ Ñпроб"
msgid "Geo|Select groups to replicate."
msgstr "Виберіть групи Ð´Ð»Ñ Ñ€ÐµÐ¿Ð»Ñ–ÐºÐ°Ñ†Ñ–Ñ—."
@@ -3622,21 +3958,45 @@ msgid "Geo|Synced"
msgstr "Синхронізовано"
msgid "Geo|Synchronization failed - %{error}"
+msgstr "Ð¡Ð¸Ð½Ñ…Ñ€Ð¾Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð½ÐµÐ²Ð´Ð°Ð»Ð°: %{error}"
+
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
msgstr ""
-msgid "Geo|Unknown state"
+msgid "Geo|Tracking entry will be removed. Are you sure?"
msgstr ""
+msgid "Geo|Unknown state"
+msgstr "Ðевідомий Ñтан"
+
msgid "Geo|Verification capacity"
msgstr "ПропуÑкна здатніÑÑ‚ÑŒ перевірки"
msgid "Geo|Verification failed - %{error}"
-msgstr ""
+msgstr "Перевірка невдала: %{error}"
msgid "Geo|Waiting for scheduler"
+msgstr "ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð»Ð°Ð½ÑƒÐ²Ð°Ð»ÑŒÐ½Ð¸ÐºÐ°"
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
msgstr ""
msgid "Geo|You need a different license to use Geo replication"
+msgstr "Вам потрібна інша Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñ Ð½Ð° викориÑÑ‚Ð°Ð½Ð½Ñ Ð³ÐµÐ¾Ð³Ñ€Ð°Ñ„Ñ–Ñ‡Ð½Ð¾Ñ— реплікації"
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
msgstr ""
msgid "Git"
@@ -3648,9 +4008,6 @@ msgstr "URL Git-репозиторіÑ"
msgid "Git revision"
msgstr "Git-редакціÑ"
-msgid "Git storage health information has been reset"
-msgstr "Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ ÑÑ‚Ð°Ñ‚ÑƒÑ Ð·Ð±ÐµÑ€Ñ–Ð³Ð°Ð½Ð½Ñ Git була Ñкинута"
-
msgid "Git strategy for pipelines"
msgstr "Git Ñтратегії Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²"
@@ -3717,12 +4074,6 @@ msgstr "Перейти до"
msgid "Go to %{link_to_google_takeout}."
msgstr "Перейти до %{link_to_google_takeout}."
-msgid "Go to your fork"
-msgstr "Перейти до вашого форку"
-
-msgid "GoToYourFork|Fork"
-msgstr "Форк"
-
msgid "Google Code import"
msgstr "Імпорт з Google Code"
@@ -3753,9 +4104,21 @@ msgstr "Ідентифікатор групи"
msgid "Group Runners"
msgstr "Групові Runner'и"
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr "URL-адреÑа групи"
+
msgid "Group avatar"
msgstr "Ðватар групи"
+msgid "Group description"
+msgstr "ÐžÐ¿Ð¸Ñ Ð³Ñ€ÑƒÐ¿Ð¸"
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr "Деталі групи"
@@ -3765,6 +4128,9 @@ msgstr "Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ групу:"
msgid "Group maintainers can register group runners in the %{link}"
msgstr "Керівники групи можуть зареєÑтрувати групові runner'и через %{link}"
+msgid "Group name"
+msgstr "Ðазва групи"
+
msgid "Group: %{group_name}"
msgstr "Група: %{group_name}"
@@ -3783,14 +4149,14 @@ msgstr "Вибачте, жоден епік не задовольнÑÑ” крит
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr "План-графік епіків відображає Ñтан ваших епіків у чаÑÑ–"
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду плану-графіку додайте заплановані дати початку та Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ одного з ваших епіків у цій групі або Ñ—Ñ— підгрупах. При поміÑÑчному переглÑді показуютьÑÑ Ð»Ð¸ÑˆÐµ епіки за попередній, поточний та наÑтупні 5 міÑÑців: від %{startDate} до %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду плану-графіку додайте заплановані дати початку та Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ одного з ваших епіків у цій групі або Ñ—Ñ— підгрупах. При поквартальному переглÑді показуютьÑÑ Ð»Ð¸ÑˆÐµ епіки за попередній, поточний та наÑтупні 4 квартали: від %{startDate} до %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду плану-графіку додайте заплановані дати початку та Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ одного з ваших епіків у цій групі або Ñ—Ñ— підгрупах. При потижневому переглÑді показуютьÑÑ Ð»Ð¸ÑˆÐµ епіки за попередній, поточний та наÑтупні 4 тижні: &ndash; від %{startDate} до %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr "Ð”Ð»Ñ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ змініть або видаліть фільтри. При поміÑÑчному переглÑді показуютьÑÑ ÐµÐ¿Ñ–ÐºÐ¸ лише за попередній, поточний та наÑтупні 5 міÑÑців: &ndash; від %{startDate} до %{endDate}."
@@ -3805,20 +4171,17 @@ msgid "GroupRoadmap|Until %{dateWord}"
msgstr "До %{dateWord}"
msgid "GroupSettings|Badges"
-msgstr ""
+msgstr "Значки"
msgid "GroupSettings|Customize your group badges."
-msgstr ""
+msgstr "Ðалаштувати значки групи."
msgid "GroupSettings|Learn more about badges."
-msgstr ""
+msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про значки."
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "Заборонити Ñпільний доÑтуп до проекту в рамках %{group} з іншими групами"
-msgid "GroupSettings|Share with group lock"
-msgstr "Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñпільного доÑтупу з іншими групами"
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "Цей параметр заÑтоÑовано до %{ancestor_group} Ñ– його було перевизначено в цій підгрупі."
@@ -3876,6 +4239,9 @@ msgstr "Групи не знайдені"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "Ви можете керувати правами доÑтупу членів групи мати доÑтуп до кожного проекту в ній."
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr "Ви впевнені, що хочете залишити групу \"%{fullName}\"?"
+
msgid "GroupsTree|Create a project in this group."
msgstr "Створити проект у групі."
@@ -3888,20 +4254,20 @@ msgstr "Редагувати групу"
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð»Ð¸ÑˆÐ¸Ñ‚Ð¸ групу. Будь-лаÑка впевнітьÑÑ, що ви не єдитий влаÑник."
-msgid "GroupsTree|Filter by name..."
-msgstr "Фільтрувати за іменем…"
-
msgid "GroupsTree|Leave this group"
msgstr "Залишити цю группу"
msgid "GroupsTree|Loading groups"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð³Ñ€ÑƒÐ¿"
-msgid "GroupsTree|Sorry, no groups matched your search"
-msgstr "Ðа жаль жодна группа не задовольнÑÑ” параметрам вашого запиту"
+msgid "GroupsTree|No groups matched your search"
+msgstr "Жодна группа не задовольнÑÑ” параметрам вашого запиту"
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
-msgstr "Ðа жаль жодна группа чи проект не задовольнÑÑ” параметрам вашого запиту"
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr "Жодна группа чи проект не задовольнÑÑ” параметрам вашого запиту"
+
+msgid "GroupsTree|Search by name"
+msgstr "Пошук за іменем"
msgid "Have your users email"
msgstr "Електронна пошта Ð´Ð»Ñ Ð·Ð²ÐµÑ€Ñ‚Ð°Ð½ÑŒ кориÑтувачів"
@@ -3937,10 +4303,13 @@ msgid "Help page text and support page url."
msgstr "ТекÑÑ‚ Ñторінки довідки та url-адреÑа Ñторінки підтримки."
msgid "Here is the public SSH key that needs to be added to the remote server. For more information, please refer to the documentation."
-msgstr ""
+msgstr "Це відкритий (публічний) SSH ключ, Ñкий потрібно додати на віддалений Ñервер. Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð¾Ñ— інформації, звернітьÑÑ Ð´Ð¾ документації."
msgid "Hide host keys manual input"
-msgstr ""
+msgstr "Сховати ввід ключів хоÑта"
+
+msgid "Hide payload"
+msgstr "Приховати кориÑне навантаженнÑ"
msgid "Hide value"
msgid_plural "Hide values"
@@ -3968,13 +4337,13 @@ msgid "ID"
msgstr "ID"
msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
-msgstr ""
+msgstr "Дозволити попередній переглÑд JavaScript-проектів у веб-IDE за допомогою Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð½Ð° клієнті CodeSandbox."
msgid "IDE|Back"
msgstr "Ðазад"
msgid "IDE|Client side evaluation"
-msgstr ""
+msgstr "Ð’Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð½Ð° клієнті"
msgid "IDE|Commit"
msgstr "Коміт"
@@ -3983,7 +4352,7 @@ msgid "IDE|Edit"
msgstr "Редагувати"
msgid "IDE|Get started with Live Preview"
-msgstr ""
+msgstr "Розпочати роботу із попереднім переглÑдом"
msgid "IDE|Go to project"
msgstr "Перейти до проекту"
@@ -3995,10 +4364,10 @@ msgid "IDE|Open in file view"
msgstr "Відкрити Ñк файл"
msgid "IDE|Preview your web application using Web IDE client-side evaluation."
-msgstr ""
+msgstr "Попередній переглÑд вашого веб-заÑтоÑунку, у веб-IDE за допомогою Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð½Ð° клієнті."
msgid "IDE|Refresh preview"
-msgstr ""
+msgstr "Оновити попередній переглÑд"
msgid "IDE|Review"
msgstr "ОглÑд"
@@ -4016,7 +4385,7 @@ msgid "Identity provider single sign on URL"
msgstr "URL єдиного входу провайдера ідентифікації"
msgid "If disabled, a diverged local branch will not be automatically updated with commits from its remote counterpart, to prevent local data loss. If the default branch (%{default_branch}) has diverged and cannot be updated, mirroring will fail. Other diverged branches are silently ignored."
-msgstr ""
+msgstr "Якщо вимкнено, локальна гілка зі змінами не буде автоматично підтÑгувати коміти з віддаленої гілки, щоб уникнути втрати локальних даних. Якщо гілка за замовчуваннÑм (%{default_branch}) міÑтить зміни Ñ– не може бути оновлена, тоді Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÑŽÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ неможливим. Інші гілки зі змінами автоматично ігноруютьÑÑ."
msgid "If disabled, the access level will depend on the user's permissions in the project."
msgstr "Якщо це відключено, то рівень доÑтупу буде залежати від дозволів кориÑтувача в проекті."
@@ -4108,6 +4477,9 @@ msgstr "Покращити ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð°Ð¼Ð¸ з можл
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr "Покращити пошук за допомогою розширеного глобального пошук в верÑÑ–Ñ— GitLab Enterprise Edition."
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr "Ðа наÑтупному кроці ви зможете вибрати проекти, Ñкі хочете імпортувати."
@@ -4121,16 +4493,16 @@ msgid "Incompatible Project"
msgstr "ÐеÑуміÑний проект"
msgid "Indicates whether this runner can pick jobs without tags"
-msgstr ""
+msgstr "Вказує на те, чи може даний runner виконувати Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð±ÐµÐ· тегів"
msgid "Inline"
msgstr "Вбудований"
msgid "Input host keys manually"
-msgstr ""
+msgstr "Введіть ключі хоÑта вручну"
msgid "Input your repository URL"
-msgstr ""
+msgstr "Введіть ваш URL репозиторію"
msgid "Install GitLab Runner"
msgstr "Ð’Ñтановити GitLab Runner"
@@ -4146,7 +4518,7 @@ msgstr[2] "ІнÑтанÑів"
msgstr[3] "ІнÑтанÑів"
msgid "Instance Statistics"
-msgstr ""
+msgstr "СтатиÑтика інÑтанÑа"
msgid "Instance Statistics visibility"
msgstr ""
@@ -4178,6 +4550,12 @@ msgstr "Шаблон інтервалу"
msgid "Introducing Cycle Analytics"
msgstr "ПредÑтавлÑємо аналітику циклу"
+msgid "Invite"
+msgstr "ЗапрошеннÑ"
+
+msgid "Issue"
+msgstr "Проблема"
+
msgid "Issue Boards"
msgstr "Дошки Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼"
@@ -4202,6 +4580,36 @@ msgstr "Проблеми можуть бути помилками, завданÐ
msgid "Issues closed"
msgstr "Проблеми закриті"
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr "ОÑтанні 12 міÑÑців"
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr "Ñіч."
@@ -4217,14 +4625,11 @@ msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾ Ñтерте"
msgid "Jobs"
msgstr "ЗавданнÑ"
-msgid "Job|Are you sure you want to erase this job?"
-msgstr "Ви дійÑно хочете видалити це завданнÑ?"
-
msgid "Job|Browse"
-msgstr ""
+msgstr "ПереглÑнути"
msgid "Job|Complete Raw"
-msgstr ""
+msgstr "Повний неформатований"
msgid "Job|Download"
msgstr "Завантажити"
@@ -4239,10 +4644,10 @@ msgid "Job|Job has been erased"
msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾ Ñтерте"
msgid "Job|Job has been erased by"
-msgstr ""
+msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾ Ñтерте"
msgid "Job|Keep"
-msgstr ""
+msgstr "Залишити"
msgid "Job|Scroll to bottom"
msgstr "Прокрутити вниз"
@@ -4251,16 +4656,16 @@ msgid "Job|Scroll to top"
msgstr "Прокрутити вгору"
msgid "Job|Show complete raw"
-msgstr ""
+msgstr "Показати повний неформатований"
msgid "Job|The artifacts were removed"
-msgstr ""
+msgstr "Ðртефакти були видалені"
-msgid "Job|The artifacts will be removed"
-msgstr ""
+msgid "Job|The artifacts will be removed in"
+msgstr "Ðртефакти будуть видалені в"
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
-msgstr ""
+msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ðµ, тому що цей проект не має жодник runner'ів призначених Ð´Ð»Ñ Ð½ÑŒÐ¾Ð³Ð¾."
msgid "Jul"
msgstr "лип."
@@ -4274,12 +4679,6 @@ msgstr "чер."
msgid "June"
msgstr "червень"
-msgid "Koding"
-msgstr "Koding"
-
-msgid "Koding Dashboard"
-msgstr "Панель ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Koding"
-
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -4352,6 +4751,9 @@ msgstr "ПеренеÑти мітку"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] "ОÑтанній %d день"
@@ -4365,12 +4767,18 @@ msgstr "ОÑтанній Конвеєр"
msgid "Last commit"
msgstr "ОÑтанній коміт"
+msgid "Last contact"
+msgstr "ОÑтанній контакт"
+
msgid "Last edited %{date}"
msgstr "ОÑтанні зміни %{date}"
msgid "Last edited by %{name}"
msgstr "ОÑтанні зміни від %{name}"
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr "ОÑтаннє оновленнÑ"
@@ -4419,23 +4827,38 @@ msgstr "Залиште параметри \"Тип файлу\" та \"МетоÐ
msgid "License"
msgstr "ЛіцензіÑ"
-msgid "LicenseManagement|Approve license"
+msgid "LicenseManagement|Add a license"
msgstr ""
-msgid "LicenseManagement|Approve license?"
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
msgstr ""
+msgid "LicenseManagement|Approve"
+msgstr "Затвердити"
+
+msgid "LicenseManagement|Approve license"
+msgstr "Затвердити ліцензію"
+
+msgid "LicenseManagement|Approve license?"
+msgstr "Затвердити ліцензію?"
+
msgid "LicenseManagement|Approved"
-msgstr ""
+msgstr "Затверджено"
+
+msgid "LicenseManagement|Blacklist"
+msgstr "Чорний ÑпиÑок"
msgid "LicenseManagement|Blacklist license"
-msgstr ""
+msgstr "ЗанеÑти ліцензію в чорний ÑпиÑок"
msgid "LicenseManagement|Blacklist license?"
-msgstr ""
+msgstr "ЗанеÑти ліцензію в чорний ÑпиÑок?"
msgid "LicenseManagement|Blacklisted"
-msgstr ""
+msgstr "Ð’ чорному ÑпиÑку"
+
+msgid "LicenseManagement|Cancel"
+msgstr "СкаÑувати"
msgid "LicenseManagement|License"
msgstr "ЛіцензіÑ"
@@ -4446,11 +4869,14 @@ msgstr "Керувати ЛіцензіÑми"
msgid "LicenseManagement|License details"
msgstr "Деталі ліцензії"
-msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
+msgid "LicenseManagement|License name"
msgstr ""
+msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
+msgstr "Ð£Ð¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð¸Ð¼Ð¸ ліцензіÑми та чорним ÑпиÑком ліцензій Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту."
+
msgid "LicenseManagement|Packages"
-msgstr ""
+msgstr "Пакети"
msgid "LicenseManagement|Remove license"
msgstr "Видалити ліцензію"
@@ -4458,14 +4884,20 @@ msgstr "Видалити ліцензію"
msgid "LicenseManagement|Remove license?"
msgstr "Видалити ліцензію?"
+msgid "LicenseManagement|Submit"
+msgstr "ÐадіÑлати"
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
+msgstr "Ðаразі немає затверджених ліцензій чи ліцензій в чорному ÑпиÑку Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту."
+
+msgid "LicenseManagement|This license already exists in this project."
msgstr ""
msgid "LicenseManagement|URL"
msgstr "URL"
msgid "LicenseManagement|You are about to remove the license, %{name}, from this project."
-msgstr ""
+msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ ліцензію %{name} із цього проекту."
msgid "Licenses"
msgstr "Ліцензії"
@@ -4489,8 +4921,11 @@ msgstr "СпиÑок ваших репозиторіїв Gitea"
msgid "List available repositories"
msgstr "СпиÑок доÑтупних репозиторіїв"
+msgid "List view"
+msgstr "Режим ÑпиÑку"
+
msgid "List your Bitbucket Server repositories"
-msgstr ""
+msgstr "СпиÑко репозиторіїв вашого Bitbucket Server"
msgid "List your GitHub repositories"
msgstr "СпиÑок ваших репозиторіїв GitHub"
@@ -4534,6 +4969,9 @@ msgstr "Закріплено за поточними проектами"
msgid "Locks give the ability to lock specific file or folder."
msgstr "Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¼Ð¾Ð¶Ðµ бути заÑтоÑоване до конкретного файлу або директорії."
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr "Логи"
@@ -4547,7 +4985,7 @@ msgid "Manage Git repositories with fine-grained access controls that keep your
msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñми Git за допомогою детального контролю доÑтупу збереже ваш код в безпеці. Виконуйте переглÑд коду та покращуйте Ñпівпрацю за допомогою запитів на злиттÑ. Кожен проект може також мати трекер проблем та вікі."
msgid "Manage Web IDE features"
-msgstr ""
+msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñми веб-IDE"
msgid "Manage access"
msgstr "Керувати доÑтупом"
@@ -4603,14 +5041,44 @@ msgstr "Відмітити Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð¸Ð¼"
msgid "Markdown enabled"
msgstr "Markdown увімкнено"
-msgid "Maven Metadata"
+msgid "MarkdownToolbar|Add a bullet list"
msgstr ""
-msgid "Maven package"
+msgid "MarkdownToolbar|Add a link"
+msgstr "Додати поÑиланнÑ"
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr "Додати таблицю"
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
msgstr ""
-msgid "Maximum git storage failures"
-msgstr "МакÑимальна кількіÑÑ‚ÑŒ невдач в Ñховищі даних git"
+msgid "Maven Metadata"
+msgstr "Maven-метадані"
+
+msgid "Maven package"
+msgstr "Пакет Maven"
+
+msgid "Max access level"
+msgstr "МакÑимальний рівень доÑтупу"
msgid "Maximum job timeout"
msgstr "МакÑимальний Ñ‡Ð°Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ"
@@ -4621,6 +5089,12 @@ msgstr "травень"
msgid "Median"
msgstr "Медіана"
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr "КориÑтувачі"
@@ -4654,6 +5128,21 @@ msgstr "Запити на злиттÑ"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ â€” це ÑпоÑіб запропонувати Ñвої зміни до проекту Ñ– обговорити Ñ—Ñ… із іншими"
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr "Вирішити це Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð² новій проблемі"
@@ -4663,9 +5152,6 @@ msgstr "Помилка при збереженні коментарÑ"
msgid "MergeRequests|Toggle comments for this file"
msgstr "Увімкнути або вимкнути коментарі Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ файлу"
-msgid "MergeRequests|Updating discussions failed"
-msgstr "Помилка при оновленні обговорень"
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr "ПереглÑнути файл @ %{commitId}"
@@ -4673,6 +5159,12 @@ msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr "ПереглÑнути замінений файл Ñтаном на %{commitId}"
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
+msgstr "%{paragraphStart} Ð¾Ð¿Ð¸Ñ Ð·Ð¼Ñ–Ð½ÐµÐ½Ð¾ %{descriptionChangedTimes} разів %{timeDifferenceMinutes}%{paragraphEnd}"
+
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
msgstr ""
msgid "Merged"
@@ -4690,6 +5182,9 @@ msgstr "Метрики - Influx"
msgid "Metrics - Prometheus"
msgstr "Метрики - Prometheus"
+msgid "Metrics and profiling"
+msgstr "Метрики та профілюваннÑ"
+
msgid "Metrics|Business"
msgstr "БізнеÑ"
@@ -4793,7 +5288,7 @@ msgid "Milestone"
msgstr "Етап"
msgid "Milestone lists not available with your current license"
-msgstr ""
+msgstr "СпиÑки етапів не доÑтупні з вашою поточною ліцензією"
msgid "Milestone lists show all issues from the selected milestone."
msgstr ""
@@ -4802,13 +5297,13 @@ msgid "Milestones"
msgstr "Етапи"
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
-msgstr ""
+msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити етап %{milestoneTitle} Ñ– видалити його із %{issuesWithCount} та %{mergeRequestsWithCount}. Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð½ÐµÐ¼Ð¾Ð¶Ð»Ð¸Ð²Ð¾ буде відмінити."
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
-msgstr ""
+msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити етап %{milestoneTitle}. Ðаразі цей етап не викориÑтовуєтьÑÑ Ð² жодних проблемах або запитах на злиттÑ."
msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
+msgstr "<p>%{milestonePromotion}</p> %{finalWarning}"
msgid "Milestones|Delete milestone"
msgstr "Видалити етап"
@@ -4838,19 +5333,19 @@ msgid "Mirror a repository"
msgstr "Віддзеркалити репозиторій"
msgid "Mirror direction"
-msgstr ""
+msgstr "ÐапрÑмок віддзеркаленнÑ"
msgid "Mirror repository"
msgstr "Віддзеркалити репозиторій"
msgid "Mirror user"
-msgstr ""
+msgstr "КориÑтувач Ð´Ð»Ñ Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ"
msgid "Mirrored repositories"
-msgstr ""
+msgstr "Віддзеркалені репозиторії"
msgid "Mirroring repositories"
-msgstr ""
+msgstr "Ð’Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ—Ð²"
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "не додаÑте SSH ключ"
@@ -4883,7 +5378,7 @@ msgid "More information is available|here"
msgstr "тут"
msgid "Most stars"
-msgstr "Ðайбільше зірок"
+msgstr ""
msgid "Move"
msgstr "ПереміÑтити"
@@ -4906,6 +5401,9 @@ msgstr "Ðазвіть ваш індивідуальний ключ за допÐ
msgid "Name:"
msgstr "Ім’Ñ:"
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr "Допомога"
@@ -5016,7 +5514,7 @@ msgid "No assignee"
msgstr "Ðемає виконавцÑ"
msgid "No branches found"
-msgstr ""
+msgstr "Гілок не знайдено"
msgid "No changes"
msgstr "Ðемає змін"
@@ -5027,6 +5525,12 @@ msgstr "Ðеможливо з'єднатиÑÑŒ із Ñервером Gitaly, бÑ
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr "Ð’ цьому проекті немає жодного образа контейнера. Додайте його за інÑтрукціÑми вище."
+msgid "No contributions were found"
+msgstr "ВнеÑки не знайдено"
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr "Ðемає"
@@ -5036,9 +5540,6 @@ msgstr "Ðемає запланованого або витраченого ча
msgid "No file chosen"
msgstr "Файл не вибрано"
-msgid "No files found"
-msgstr "Ðе знайдено жодного файлу"
-
msgid "No files found."
msgstr "Ðе знайдено жодного файлу."
@@ -5048,6 +5549,9 @@ msgstr "Ðемає проблем за вибраний період чаÑу."
msgid "No labels with such name or description"
msgstr "Ðемає міток з таким іменем або опиÑом"
+msgid "No license. All rights reserved"
+msgstr "Ðемає ліцензії. Ð’ÑÑ– права захищені"
+
msgid "No merge requests for the selected time period."
msgstr "Ðемає запитів на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð° вибраний період чаÑу."
@@ -5061,7 +5565,7 @@ msgid "No other labels with such name or description"
msgstr "Ðемає інших міток з таким іменем або опиÑом"
msgid "No packages stored for this project."
-msgstr ""
+msgstr "В цьому проекті немає пакетів."
msgid "No prioritised labels with such name or description"
msgstr "Ðемає пріоритетних міток з таким іменем або опиÑом"
@@ -5075,6 +5579,9 @@ msgstr "Ðемає відправок (push) за вказаний період
msgid "No repository"
msgstr "Ðемає репозиторію"
+msgid "No runners found"
+msgstr "Runner'ів не знайдено"
+
msgid "No schedules"
msgstr "Ðемає розкладів"
@@ -5111,6 +5618,9 @@ msgstr "Ðе конфіденційно"
msgid "Not enough data"
msgstr "ÐедоÑтатньо даних"
+msgid "Not now"
+msgstr "Пізніше"
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr "Майте на увазі, що гілка master захищена автоматично. %{link_to_protected_branches}"
@@ -5129,6 +5639,18 @@ msgstr "Примітка: звернітьÑÑ Ð´Ð¾ вашого адмініÑÑ
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "Ви впевнені, що хочете ÑкаÑувати цей коментар?"
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ події"
@@ -5145,7 +5667,7 @@ msgid "NotificationEvent|Merge merge request"
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð¾"
msgid "NotificationEvent|New epic"
-msgstr ""
+msgstr "Ðовий епік"
msgid "NotificationEvent|New issue"
msgstr "Ðова проблема"
@@ -5201,9 +5723,6 @@ msgstr "лиÑÑ‚."
msgid "November"
msgstr "лиÑтопад"
-msgid "Number of access attempts"
-msgstr "КількіÑÑ‚ÑŒ Ñпроб доÑтупу"
-
msgid "OK"
msgstr "OK"
@@ -5221,10 +5740,10 @@ msgstr "ПіÑÐ»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ репозиторії можуть бути Ð
msgid "One more item"
msgid_plural "%d more items"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Ще один елемент"
+msgstr[1] "Ще %d елементи"
+msgstr[2] "Ще %d елементів"
+msgstr[3] "Ще %d елементів"
msgid "One or more of your Bitbucket projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "Один або декілька ваших проектів Bitbucket не можна імпортувати безпоÑередньо в GitLab, оÑкільки вони викориÑтовують Subversion або Mercurial Ð´Ð»Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŽ верÑій заміÑÑ‚ÑŒ Git."
@@ -5232,9 +5751,6 @@ msgstr "Один або декілька ваших проектів Bitbucket Ð
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "Один або декілька ваших проектів Google Code не можна імпортувати безпоÑередньо в GitLab, оÑкільки вони викориÑтовують Subversion або Mercurial Ð´Ð»Ñ ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»ÑŽ верÑій заміÑÑ‚ÑŒ Git."
-msgid "Online IDE integration settings."
-msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ— із онлайн IDE."
-
msgid "Only admins"
msgstr "Тільки Ðдміни"
@@ -5242,7 +5758,7 @@ msgid "Only comments from the following commit are shown below"
msgstr "Ðижче наведено лише коментарі з наÑтупного коміту"
msgid "Only mirror protected branches"
-msgstr ""
+msgstr "Віддзеркалювати лише захищені гілки"
msgid "Only project members can comment."
msgstr "Тільки учаÑники проекту можуть залишати коментарі."
@@ -5251,11 +5767,14 @@ msgid "Oops, are you sure?"
msgstr "Ой, а ви впевнені?"
msgid "Open"
-msgstr "Відкрити"
+msgstr "Відкриті"
msgid "Open in Xcode"
msgstr "Відкрити в Xcode"
+msgid "Open projects"
+msgstr "Відкриті проекти"
+
msgid "Open sidebar"
msgstr "Розгорніть бічну панель"
@@ -5280,6 +5799,21 @@ msgstr "ВідкриваєтьÑÑ Ñƒ новому вікні"
msgid "Operations"
msgstr "Операції"
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr "Ðеможливо додати %{invalidProjects}. Панель ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð¿ÐµÑ€Ð°Ñ†Ñ–Ñми доÑтупна Ð´Ð»Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñ–Ð² з Gold підпиÑкою."
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "За необхідноÑÑ‚Ñ– ви можете %{link_to_customize} Ñк адреÑи електронної почти та імена кориÑтувачів FobBugz будуть імпортовані у GitLab."
@@ -5314,13 +5848,13 @@ msgid "Owner"
msgstr "ВлаÑник"
msgid "Package information"
-msgstr ""
+msgstr "Ð†Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ пакет"
msgid "Package was removed"
-msgstr ""
+msgstr "Пакет був видалений"
msgid "Packages"
-msgstr ""
+msgstr "Пакети"
msgid "Pages"
msgstr "Сторінки"
@@ -5346,6 +5880,9 @@ msgstr "Пароль"
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr "Ð’Ñтавте Ñвій відкритий ключ SSH, Ñкий зазвичай знаходитьÑÑ Ñƒ файлі '~/.ssh/id_rsa.pub' Ñ– починаєтьÑÑ Ð· 'ssh-rsa'. Ðе викориÑтовуйте Ñвій приватний ключ SSH."
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr "ШлÑÑ…:"
@@ -5359,7 +5896,7 @@ msgid "Pending"
msgstr "В очікуванні"
msgid "People without permission will never get a notification and won't be able to comment."
-msgstr ""
+msgstr "Люди без дозволу ніколи не отримуватимуть Ñповіщень Ñ– не зможуть коментувати."
msgid "Per job. If a job passes this threshold, it will be marked as failed"
msgstr "За завданнÑ. Якщо воно переходить цей поріг, то Ñтає позначеним Ñк невдале"
@@ -5373,15 +5910,15 @@ msgstr "ÐžÐ¿Ñ‚Ð¸Ð¼Ñ–Ð·Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾Ð´ÑƒÐºÑ‚Ð¸Ð²Ð½Ð¾ÑÑ‚Ñ–"
msgid "Permissions"
msgstr "Права доÑтупу"
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
msgid "Personal Access Token"
msgstr "Токену перÑонального доÑтупу"
msgid "Pipeline"
msgstr "Конвеєр"
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
-msgstr ""
-
msgid "Pipeline Health"
msgstr "Стан Конвеєра"
@@ -5499,15 +6036,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "Цей проект в даний Ñ‡Ð°Ñ Ð½Ðµ налаштований Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку конвеєрів."
+msgid "Pipeline|Commit"
+msgstr "Коміт"
+
msgid "Pipeline|Create for"
msgstr "Створити длÑ"
msgid "Pipeline|Create pipeline"
msgstr "Створити конвеєр"
+msgid "Pipeline|Duration"
+msgstr "ТриваліÑÑ‚ÑŒ"
+
msgid "Pipeline|Existing branch name or tag"
msgstr "ІÑнуюче Ñ–Ð¼â€™Ñ Ð³Ñ–Ð»ÐºÐ¸ або тег"
+msgid "Pipeline|Pipeline"
+msgstr "Конвеєр"
+
msgid "Pipeline|Run Pipeline"
msgstr "ЗапуÑтити Конвеєр"
@@ -5517,6 +6063,12 @@ msgstr "Пошук гілки"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr "Вкажіть Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð¼Ñ–Ð½Ð½Ð¸Ñ…, Ñкі будуть викориÑтані в цьому запуÑку. Інакше будуть викориÑтані значеннÑ, вказані в %{settings_link}."
+msgid "Pipeline|Stages"
+msgstr "Стадії"
+
+msgid "Pipeline|Status"
+msgstr "СтатуÑ"
+
msgid "Pipeline|Stop pipeline"
msgstr "Зупинити конвеєр"
@@ -5544,12 +6096,6 @@ msgstr "зі ÑтадіÑми"
msgid "Plain diff"
msgstr "ПроÑте порівнÑннÑ"
-msgid "Planned finish date"
-msgstr "Запланована дата завершеннÑ"
-
-msgid "Planned start date"
-msgstr "Запланована дата початку"
-
msgid "PlantUML"
msgstr "PlantUML"
@@ -5559,12 +6105,18 @@ msgstr "Відтворити"
msgid "Please accept the Terms of Service before continuing."
msgstr "Будь лаÑка, Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸Ð¹Ð¼Ñ–Ñ‚ÑŒ умови Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг."
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr "Будь лаÑка Ñконвертуйте Ñ—Ñ… в %{link_to_git} Ñ– виконайте знову %{link_to_import_flow}."
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr "Будь лаÑка Ñконвертуйте Ñ—Ñ… в Git на Google Code, Ñ– виконайте знову %{link_to_import_flow}."
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "Зверніть увагу, що Ñ†Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð° не Ñ” чаÑтиною GitLab, Ñ– ви повинні впевнитиÑÑ Ñƒ Ñ—Ñ— безпеці, перш ніж надавати доÑтуп."
@@ -5577,6 +6129,9 @@ msgstr "Будь лаÑка, пройдіть reCAPTCHA"
msgid "Please try again"
msgstr "Будь лаÑка, Ñпробуйте ще раз"
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr "Будь лаÑка, викориÑтовуйте цю форму, щоб повідомлÑти GitLab про кориÑтувачів, Ñкі Ñтворюють Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ– коментарі зі Ñпамом, або поводÑÑ‚ÑŒÑÑ Ð½ÐµÐ²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¾."
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr "Будь лаÑка, почекайте поки ми з’єднуємоÑÑ Ñ–Ð· вашим репозиторієм. Оновлюйте Ñторінку за бажаннÑм."
@@ -5589,9 +6144,18 @@ msgstr "ÐалаштуваннÑ"
msgid "Preferences|Navigation theme"
msgstr "Тема навігації"
+msgid "Press Enter or click to search"
+msgstr "Ð”Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ натиÑніть Enter або клікніть"
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr "Попередній переглÑд"
+msgid "Preview payload"
+msgstr "Попередній переглÑд кориÑного навантаженнÑ"
+
msgid "Primary"
msgstr "Головний"
@@ -5623,10 +6187,10 @@ msgid "Profile Settings"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ„Ñ–Ð»ÑŽ"
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
-msgstr ""
+msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити %{yourAccount}, а також вÑÑ– проблеми, запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° групи, пов'Ñзані з вашим обліковим запиÑом. ПіÑÐ»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ %{deleteAccount}, його неможливо буде відновити."
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
-msgstr ""
+msgstr "Ви збираєтеÑÑ Ð·Ð¼Ñ–Ð½Ð¸Ñ‚Ð¸ ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача %{currentUsernameBold} на %{newUsernameBold}. Профіль та проекти будуть перенаправлÑтиÑÑ Ð½Ð° проÑÑ‚Ñ–Ñ€ імен %{newUsername}, але таке Ð¿ÐµÑ€ÐµÐ½Ð°Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð°ÐºÑ–Ð½Ñ‡Ð¸Ñ‚ÑŒÑÑ, коли проÑÑ‚Ñ–Ñ€ імен %{currentUsername} буде зареєÑтровано на іншого кориÑтувача або групу. Будь лаÑка, оновіть віддалені адреÑи в репозиторіÑÑ… Git Ñкомога швидше."
msgid "Profiles|Account scheduled for removal."
msgstr "Обліковий Ð·Ð°Ð¿Ð¸Ñ Ð·Ð°Ð¿Ð»Ð°Ð½Ð¾Ð²Ð°Ð½Ð¸Ð¹ Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ."
@@ -5635,17 +6199,32 @@ msgid "Profiles|Add key"
msgstr "Додати ключ"
msgid "Profiles|Add status emoji"
-msgstr ""
+msgstr "Додати Ñмайлик-ÑтатуÑ"
+
+msgid "Profiles|Avatar cropper"
+msgstr "Обрізка аватарів"
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr "Ðватар буде видалено. Ви впевнені?"
msgid "Profiles|Change username"
msgstr "Змінити ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
+msgid "Profiles|Choose file..."
+msgstr "Вибрати файл..."
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr "Виберіть Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ñƒ внеÑків до приватних репозиторіїв у вашому публічному профілі без інформації про проекти, репозиторії або організації."
+
msgid "Profiles|Clear status"
msgstr "ОчиÑтити ÑтатуÑ"
msgid "Profiles|Current path: %{path}"
msgstr "Поточний шлÑÑ…: %{path}"
+msgid "Profiles|Current status"
+msgstr "Поточний Ñтан"
+
msgid "Profiles|Delete Account"
msgstr "Видалити обліковий запиÑ"
@@ -5658,39 +6237,120 @@ msgstr "Видалити ваш обліковий запиÑ?"
msgid "Profiles|Deleting an account has the following effects:"
msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу неÑе наÑтупні наÑлідки:"
+msgid "Profiles|Do not show on profile"
+msgstr "Ðе відображати у профілі"
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr "Ðе відображати оÑобиÑту інформацію, пов’Ñзану із активноÑÑ‚Ñми, у ваших профілÑÑ…"
+
+msgid "Profiles|Edit Profile"
+msgstr "Редагувати профіль"
+
msgid "Profiles|Invalid password"
msgstr "Ðеправильний пароль"
msgid "Profiles|Invalid username"
msgstr "Ðеправильне ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
+msgid "Profiles|Learn more"
+msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ"
+
+msgid "Profiles|Made a private contribution"
+msgstr "Cтворив приватний внеÑок"
+
+msgid "Profiles|Main settings"
+msgstr "Головні налаштуваннÑ"
+
+msgid "Profiles|No file chosen"
+msgstr "Файл не вибрано"
+
msgid "Profiles|Path"
msgstr "ШлÑÑ…"
+msgid "Profiles|Position and size your new avatar"
+msgstr "Спозиціонуйте ваш аватар та задайте його розмір"
+
+msgid "Profiles|Private contributions"
+msgstr "Приватні внеÑки"
+
+msgid "Profiles|Public Avatar"
+msgstr "Публічний аватар"
+
+msgid "Profiles|Remove avatar"
+msgstr "Видалити аватар"
+
+msgid "Profiles|Set new profile picture"
+msgstr "Ð’Ñтановити нове Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ„Ñ–Ð»ÑŽ"
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr "ДеÑкі параметри недоÑтупні Ð´Ð»Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¸Ñ… запиÑів LDAP"
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr "Розкажіть про Ñебе в межах 250 Ñимволів."
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr "МакÑимальний розмір файлу 200КБ."
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "Це не Ñхоже на публічниц ключ SSH. Ви впевнені, що хочете його додати?"
-msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr "Ð¦Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð° адреÑа буде відображатиÑÑ Ñƒ вашому публічному профілі."
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
msgstr ""
+msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
+msgstr "Цей Ñмайлик та Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ´ÑƒÑ‚ÑŒ показані у вашому профілі та в інтерфейÑÑ–."
+
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr "Ð¦Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ Ñ” екÑпериментальною Ñ– переклади ще не завершені."
+
+msgid "Profiles|This information will appear on your profile."
+msgstr "Ð¦Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð±ÑƒÐ´Ðµ відображатиÑÑ Ñƒ вашому профілі."
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "Введіть ваш %{confirmationValue} Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ:"
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr "Зазвичай починаєтьÑÑ Ð· \"ssh-rsa ...\""
+msgid "Profiles|Update profile settings"
+msgstr "Оновити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ„Ñ–Ð»ÑŽ"
+
msgid "Profiles|Update username"
msgstr "Оновити ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
+msgid "Profiles|Upload new avatar"
+msgstr "Завантажити новий аватар"
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr "Помилка при збереженні імені кориÑтувача - %{message}"
msgid "Profiles|Username successfully changed"
msgstr "Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача уÑпішно збережено"
+msgid "Profiles|Website"
+msgstr "ВебÑайт"
+
msgid "Profiles|What's your status?"
msgstr "Який ваш ÑтатуÑ?"
+msgid "Profiles|You can change your avatar here"
+msgstr "Тут ви можете змінити Ñвій аватар"
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr "Тут ви можете змінити Ñвій аватар або видалити його та повернутиÑÑ Ð´Ð¾ %{gravatar_link}"
+
+msgid "Profiles|You can upload your avatar here"
+msgstr "Тут ви можете завантажити Ñвій аватар"
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr "Тут ви можете завантажити Ñвій аватар або змінити його на %{gravatar_link}"
+
msgid "Profiles|You don't have access to delete this user."
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” доÑтупу Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ кориÑтувача."
@@ -5700,6 +6360,15 @@ msgstr "Вам необхідно змінити влаÑника або видÐ
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ñ” влаÑником в цих групах:"
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr "Ваша адреÑа електронної пошти була автоматично вÑтановлена на оÑнові вашого облікового запиÑу %{provider_label}."
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr "Ваше міÑÑ†ÐµÐ·Ð½Ð°Ñ…Ð¾Ð´Ð¶ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¾ автоматично вÑтановлено на оÑнові вашого облікового запиÑу %{provider_label}."
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr "Ваше Ñ–Ð¼â€™Ñ Ð±ÑƒÐ»Ð¾ автоматично вÑтановлено на оÑнові вашого облікового запиÑу %{provider_label} щоб люди могли Ð²Ð°Ñ Ð²Ð¿Ñ–Ð·Ð½Ð°Ñ‚Ð¸."
+
msgid "Profiles|Your status"
msgstr "Ваш ÑтатуÑ"
@@ -5736,6 +6405,9 @@ msgstr "Проект '%{project_name}' уÑпішно оновлено."
msgid "Project Badges"
msgstr "Значки проекту"
+msgid "Project URL"
+msgstr "URL-адреÑа проекту"
+
msgid "Project access must be granted explicitly to each user."
msgstr "ДоÑтуп до проекту повинен надаватиÑÑ ÐºÐ¾Ð¶Ð½Ð¾Ð¼Ñƒ кориÑтувачеві."
@@ -5763,6 +6435,9 @@ msgstr "Розпочато екÑпорт проекту. ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð
msgid "Project name"
msgstr "Ðазва проекту"
+msgid "Project slug"
+msgstr "ШлÑÑ… проекту"
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "ПідпиÑатиÑÑ"
@@ -5790,17 +6465,38 @@ msgstr "Ðіколи"
msgid "ProjectLifecycle|Stage"
msgstr "СтадіÑ"
+msgid "ProjectOverview|Fork"
+msgstr "Форк"
+
+msgid "ProjectOverview|Forks"
+msgstr "Форки"
+
+msgid "ProjectOverview|Go to your fork"
+msgstr "Перейти до вашого форку"
+
+msgid "ProjectOverview|Star"
+msgstr "В обрані"
+
+msgid "ProjectOverview|Unstar"
+msgstr "Видалити із обраних"
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr "Ви доÑÑгли Ñвого ліміту по кількоÑÑ‚Ñ– проектів"
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr "Ви повинні увійти, щоб додати проект в обрані"
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "ID проекту: %{project_id}"
msgid "ProjectSettings|Badges"
-msgstr ""
+msgstr "Значки"
msgid "ProjectSettings|Contact an admin to change this setting."
msgstr "ЗвернітьÑÑ Ð´Ð¾ адмініÑтратора, щоб змінити це налаштуваннÑ."
msgid "ProjectSettings|Customize your project badges."
-msgstr ""
+msgstr "Ðалаштувати значки проекту."
msgid "ProjectSettings|Failed to protect the tag"
msgstr "Помилка при захиÑÑ‚Ñ– тегу"
@@ -5809,7 +6505,7 @@ msgid "ProjectSettings|Failed to update tag!"
msgstr "Помилка при оновленні тегу!"
msgid "ProjectSettings|Learn more about badges."
-msgstr ""
+msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про значки."
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "Тільки підпиÑані коміти можуть бути надіÑлані в цей репозиторій."
@@ -5832,6 +6528,9 @@ msgstr "Проекти"
msgid "Projects shared with %{group_name}"
msgstr "Спільні проекти з %{group_name}"
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr "ЧаÑто відвідувані"
@@ -5901,9 +6600,6 @@ msgstr "Ðвтоматична конфігураціÑ"
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr "Ðвтоматично розгортайте та налаштовуйте Prometheus на ваші клаÑтери Ð´Ð»Ñ Ð¼Ð¾Ð½Ñ–Ñ‚Ð¾Ñ€Ð¸Ð½Ð³Ñƒ Ñередовищ проекту"
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr "За замовчуваннÑм, Prometheus запуÑкаєтьÑÑ Ð·Ð° адреÑою ‘http://localhost:9090’. Ðе рекомендуєтьÑÑ Ð·Ð¼Ñ–Ð½ÑŽÐ²Ð°Ñ‚Ð¸ цю адреÑу Ñ– порт, бо це може призвеÑти до конфлікту з іншими ÑервіÑами запущеними на GitLab Ñервері."
-
msgid "PrometheusService|Common metrics"
msgstr "Загальні метрики"
@@ -5992,46 +6688,46 @@ msgid "Protected Environments"
msgstr "Захищені Ñередовища"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
-msgstr ""
+msgstr "%{environment_name} буде доÑупне Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñу Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±Ð½Ð¸ÐºÑ–Ð². Ви впевнені?"
msgid "ProtectedEnvironment|Allowed to deploy"
-msgstr ""
+msgstr "Ð Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÐµÐ½Ð¾"
msgid "ProtectedEnvironment|Choose who is allowed to deploy"
-msgstr ""
+msgstr "Виберіть Ð´Ð»Ñ ÐºÐ¾Ð³Ð¾ доÑтупне розгортаннÑ"
msgid "ProtectedEnvironment|Environment"
-msgstr ""
+msgstr "Середовище"
msgid "ProtectedEnvironment|Protect"
-msgstr ""
+msgstr "ЗахиÑтити"
msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr ""
+msgstr "Захищайте Середовища Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб обмежити коло оÑіб, здатних здійÑнювати розгортаннÑ."
msgid "ProtectedEnvironment|Protect an environment"
-msgstr ""
+msgstr "ЗахиÑити Ñередовище"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
-msgstr ""
+msgstr "ЗахиÑтити Середовище (%{protected_environments_count})"
msgid "ProtectedEnvironment|Select an environment"
-msgstr ""
+msgstr "Виберіть Ñередовище"
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
-msgstr ""
+msgstr "Ðаразі немає захищених Ñередовищ, захиÑÑ‚Ñ–Ñ‚ÑŒ Ñередовище за допомогою форми, що знаходитьÑÑ Ð²Ð¸Ñ‰Ðµ."
msgid "ProtectedEnvironment|Unprotect"
msgstr "ЗнÑти захиÑÑ‚"
msgid "ProtectedEnvironment|Your environment can't be unprotected"
-msgstr ""
+msgstr "Ви не можете знÑти захиÑти із вашого Ñередовища"
msgid "ProtectedEnvironment|Your environment has been protected."
-msgstr ""
+msgstr "Ваше Ñередовище було захищено."
msgid "ProtectedEnvironment|Your environment has been unprotected"
-msgstr ""
+msgstr "ЗахиÑÑ‚ із вашого Ñередовища було знÑто"
msgid "Protip:"
msgstr "Підказка:"
@@ -6052,10 +6748,10 @@ msgid "Public pipelines"
msgstr "Публічні конвеєри"
msgid "Pull"
-msgstr ""
+msgstr "Отримати (pull)"
msgid "Push"
-msgstr ""
+msgstr "Відправити (push)"
msgid "Push Rules"
msgstr "Push-правила"
@@ -6096,6 +6792,12 @@ msgstr "ІнÑтрукціÑ"
msgid "Real-time features"
msgstr "Фунції реального чаÑу"
+msgid "Recent searches"
+msgstr "ОÑтанні пошукові запити"
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr "ПоÑиланнÑ:"
@@ -6104,16 +6806,16 @@ msgstr "Оновити"
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· Ñекунду Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð°ÐºÑ‚ÑƒÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ñтану..."
+msgstr[1] "ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· %d Ñекунди Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð°ÐºÑ‚ÑƒÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ñтану..."
+msgstr[2] "ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· %d Ñекунд Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð°ÐºÑ‚ÑƒÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ñтану..."
+msgstr[3] "ÐžÐ½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· %d Ñекунд Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð°ÐºÑ‚ÑƒÐ°Ð»ÑŒÐ½Ð¾Ð³Ð¾ Ñтану..."
msgid "Regenerate key"
msgstr "Створити ключ заново"
msgid "Regex pattern"
-msgstr ""
+msgstr "Шаблон у виглÑді регулÑрного виразу"
msgid "Register / Sign In"
msgstr "ЗареєÑтруватиÑÑ / Увійти"
@@ -6160,12 +6862,21 @@ msgstr "Видалити Runner"
msgid "Remove avatar"
msgstr "Видалити аватар"
+msgid "Remove group"
+msgstr "Видалити групу"
+
msgid "Remove priority"
msgstr "Видалити пріоритет"
msgid "Remove project"
msgstr "Видалити проект"
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr "Перейменувати"
@@ -6175,6 +6886,9 @@ msgstr "Перейменувати файл"
msgid "Rename folder"
msgstr "Перейменувати папку"
+msgid "Reopen epic"
+msgstr "Повторне Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ñ‚Ñ ÐµÐ¿Ñ–ÐºÑƒ"
+
msgid "Repair authentication"
msgstr "Відновити аутентифікацію"
@@ -6184,32 +6898,50 @@ msgstr "ВідповіÑти на це електронне повідомлен
msgid "Repo by URL"
msgstr "Репозиторії по URL"
+msgid "Report abuse to GitLab"
+msgstr "Повідомити GitLab про порушеннÑ"
+
+msgid "Reporting"
+msgstr "ЗвітуваннÑ"
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr "%{failedString} та %{resolvedString}"
+msgid "Reports|Actions"
+msgstr "Дії"
+
msgid "Reports|Class"
msgstr "КлаÑ"
+msgid "Reports|Confidence"
+msgstr "ВпевненіÑÑ‚ÑŒ"
+
msgid "Reports|Execution time"
msgstr "Ð§Ð°Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ"
msgid "Reports|Failure"
msgstr "Помилка"
+msgid "Reports|Severity"
+msgstr "СерйозніÑÑ‚ÑŒ"
+
msgid "Reports|System output"
-msgstr ""
+msgstr "СиÑтемний вивід"
msgid "Reports|Test summary"
-msgstr ""
+msgstr "ТеÑтовий звіт"
msgid "Reports|Test summary failed loading results"
-msgstr ""
+msgstr "Помилка при завантаженні результатів Ð´Ð»Ñ Ñ‚ÐµÑтового звіту"
msgid "Reports|Test summary results are being parsed"
-msgstr ""
+msgstr "Результати Ð´Ð»Ñ Ñ‚ÐµÑтового звіту оброблÑÑŽÑ‚ÑŒÑÑ"
+
+msgid "Reports|Vulnerability"
+msgstr "ВразливіÑÑ‚ÑŒ"
msgid "Reports|no changed test results"
-msgstr ""
+msgstr "результати теÑтів не змінилиÑÑ"
msgid "Repository"
msgstr "Репозиторій"
@@ -6241,12 +6973,12 @@ msgstr "Запит доÑтупу"
msgid "Requests Profiles"
msgstr "ÐŸÑ€Ð¾Ñ„Ñ–Ð»ÑŽÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñ–Ð²"
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "Вимагати від уÑÑ–Ñ… кориÑтувачів приймати умови Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг та політику конфіденційноÑÑ‚Ñ–, коли вони отримують доÑтуп до GitLab."
-msgid "Reset git storage health information"
-msgstr "Скиньте інформацію про працездатніÑÑ‚ÑŒ Ñховища git"
-
msgid "Reset health check access token"
msgstr "Оновити токен доÑтупу Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ працездатноÑÑ‚Ñ–"
@@ -6262,9 +6994,21 @@ msgstr "Вирішити конфлікти у гілці-джерелі"
msgid "Resolve discussion"
msgstr "Завершити обговореннÑ"
+msgid "Response metrics (AWS ELB)"
+msgstr "Метрики відповідей (AWS ELB)"
+
msgid "Response metrics (Custom)"
msgstr "Метрики відповідей (ВлаÑні)"
+msgid "Response metrics (HA Proxy)"
+msgstr "Метрики відповідей (HA Proxy)"
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr "Метрики відповідей (NGINX Ingress)"
+
+msgid "Response metrics (NGINX)"
+msgstr "Метрики відповідей (NGINX)"
+
msgid "Resume"
msgstr "Продовжити"
@@ -6278,7 +7022,7 @@ msgid "Retry verification"
msgstr "Повторити перевірку"
msgid "Reveal Variables"
-msgstr ""
+msgstr "Відкрити змінні"
msgid "Reveal value"
msgid_plural "Reveal values"
@@ -6315,11 +7059,26 @@ msgid "Run CI/CD pipelines for external repositories"
msgstr "ЗапуÑтити CI/CD конвеєри Ð´Ð»Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½Ñ–Ñ… репозиторіїв"
msgid "Run untagged jobs"
+msgstr "Виконати Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð±ÐµÐ· тегів"
+
+msgid "Runner cannot be assigned to other projects"
+msgstr "Runner не може бути призначено Ð´Ð»Ñ Ñ–Ð½ÑˆÐ¸Ñ… проектів"
+
+msgid "Runner runs jobs from all unassigned projects"
msgstr ""
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr "Runner виконує завданні із призначених проектів"
+
msgid "Runner token"
msgstr "Токен Runner'а"
+msgid "Runner will not receive any new jobs"
+msgstr "Runner не отримуватиме нових завдань"
+
msgid "Runners"
msgstr "Runner'и"
@@ -6329,6 +7088,12 @@ msgstr "API Runner’ів"
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr "Runner’и можуть розміщуватиÑÑ Ñƒ різних кориÑтувачів, на Ñерверах Ñ– навіть на вашій локальній машині."
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr "Runner'и можуть бути вÑтановлені на окремі Ñервери, навіть на ваш локальний комп’ютер."
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr "ДоÑтупні Runner'и: %{active_runners_count}"
+
msgid "Runners page"
msgstr "Сторінка Runner'ів"
@@ -6336,7 +7101,7 @@ msgid "Runners page."
msgstr "Сторінка Runner'ів."
msgid "Runners|You have used all your shared Runners pipeline minutes."
-msgstr ""
+msgstr "Ви викориÑтали уÑÑ– виділенні хвилини Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… Ñпільних runner'ів."
msgid "Running"
msgstr "ВиконуєтьÑÑ"
@@ -6353,6 +7118,9 @@ msgstr "Єдиний вхід SAML"
msgid "SAML Single Sign On Settings"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ”Ð´Ð¸Ð½Ð¾Ð³Ð¾ входу SAML"
+msgid "SAST"
+msgstr "SAST"
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr "Відбиток SHA1 Ñертифікату Ð´Ð»Ñ Ð¿Ñ–Ð´Ð¿Ð¸ÑÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð¾ÐºÐµÐ½Ñ–Ð² SAML. Отримайте його від провайдера ідентифікації, де він також може називатиÑÑ \"Thumbprint\"."
@@ -6360,10 +7128,10 @@ msgid "SSH Keys"
msgstr "Ключі SSH"
msgid "SSH host keys"
-msgstr ""
+msgstr "SSH-ключі хоÑта"
msgid "SSH public key"
-msgstr ""
+msgstr "Відкритий SSH-ключ"
msgid "SSL Verification"
msgstr "Перевірка SSL"
@@ -6377,6 +7145,9 @@ msgstr "Зберегти заÑтоÑунок"
msgid "Save changes"
msgstr "Зберегти зміни"
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "Зберегти розклад конвеєра"
@@ -6431,47 +7202,50 @@ msgstr "Пошук у запитах на злиттÑ"
msgid "Search milestones"
msgstr "Пошук етапів"
+msgid "Search or filter results..."
+msgstr "Шукати чи фільтрувати результати..."
+
msgid "Search or jump to…"
-msgstr ""
+msgstr "Шукати чи перейти до…"
msgid "Search project"
msgstr "Пошук в проекті"
+msgid "Search projects"
+msgstr "Пошук проектів"
+
msgid "Search users"
msgstr "Пошук кориÑтувачів"
-msgid "SearchAutocomplete|All GitLab"
+msgid "Search your projects"
msgstr ""
+msgid "SearchAutocomplete|All GitLab"
+msgstr "ВеÑÑŒ GitLab"
+
msgid "SearchAutocomplete|Issues I've created"
-msgstr ""
+msgstr "Проблеми, Ñтворені мною"
msgid "SearchAutocomplete|Issues assigned to me"
-msgstr ""
+msgstr "Проблеми, призначені мені"
msgid "SearchAutocomplete|Merge requests I've created"
-msgstr ""
+msgstr "Запити на злиттÑ, Ñтворені мною"
msgid "SearchAutocomplete|Merge requests assigned to me"
-msgstr ""
+msgstr "Запити на злиттÑ, призначені мені"
msgid "SearchAutocomplete|in all GitLab"
-msgstr ""
+msgstr "по вÑьому GitLab"
msgid "SearchAutocomplete|in this group"
-msgstr ""
+msgstr "в цій групі"
msgid "SearchAutocomplete|in this project"
-msgstr ""
-
-msgid "Seconds before reseting failure information"
-msgstr "КількіÑÑ‚ÑŒ Ñекунд до ÑÐºÐ¸Ð´Ð°Ð½Ð½Ñ Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ— про збої"
-
-msgid "Seconds to wait for a storage access attempt"
-msgstr "КількіÑÑ‚ÑŒ Ñекунд Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ´ повторною Ñпробою доÑтупу до Ñховища даних"
+msgstr "в цьому проекті"
-msgid "Secret:"
-msgstr "Секрет:"
+msgid "Secret"
+msgstr "Секрет"
msgid "Security"
msgstr "Безпека"
@@ -6479,19 +7253,51 @@ msgstr "Безпека"
msgid "Security Dashboard"
msgstr "Панель безпеки"
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr "Створено проблему"
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr "Детальніше"
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr "Ðа панелі безпеки відображаєтьÑÑ Ð¾Ñтанній звіт про безпеку. ВикориÑтовуйте його Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ та Ð²Ð¸Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð²Ñ€Ð°Ð·Ð»Ð¸Ð²Ð¾Ñтей."
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr "Моніторинг вразливоÑтей у вашому коді"
@@ -6504,9 +7310,15 @@ msgstr "Вибрати"
msgid "Select Archive Format"
msgstr "Виберіть формат архіву"
+msgid "Select a group to invite"
+msgstr "Виберіть групу Ð´Ð»Ñ Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ"
+
msgid "Select a namespace to fork the project"
msgstr "Виберіть проÑÑ‚Ñ–Ñ€ імен Ð´Ð»Ñ Ñ„Ð¾Ñ€ÐºÑƒ проекту"
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr "Вибрати чаÑовий поÑÑ"
@@ -6537,6 +7349,9 @@ msgstr "Виберіть гілку-джерело"
msgid "Select target branch"
msgstr "Вибір цільової гілки"
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr "Виберіть гілку по замовчанню Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту. Ð’ÑÑ– запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° коміти будуть автоматично зроблені в ній, Ñкщо ви тільки не виберете іншу."
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6549,6 +7364,9 @@ msgstr "Вибіркова ÑинхронізаціÑ"
msgid "Send email"
msgstr "ÐадіÑлати лиÑта"
+msgid "Send usage data"
+msgstr "Відправити дані про викориÑтаннÑ"
+
msgid "Sep"
msgstr "вер."
@@ -6573,6 +7391,9 @@ msgstr "Термін дії ÑеÑÑ–Ñ—, проектні ліміти та роÐ
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "Ð’Ñтановіть пароль Ð´Ð»Ñ Ñвого облікового запиÑу, щоб мати можливіÑÑ‚ÑŒ відправлÑти та отримувати через %{protocol}."
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr "Ð’Ñтановіть Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð·Ð° замовчуваннÑм Ñ– обмежте рівні видимоÑÑ‚Ñ–. Ðалаштуйте джерела імпорту Ñ– протокол доÑтупу git."
@@ -6591,26 +7412,47 @@ msgstr "Ð’Ñтановіть вимоги Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ кориÑтувач
msgid "Set up CI/CD"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CI/CD"
-msgid "Set up Koding"
-msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr "Ðалаштуйте %{type} runner вручну"
+
+msgid "Set up a specific Runner automatically"
+msgstr "Ðвтоматично налаштувати Ñпецифічний runner"
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr "Ðалаштуйте твердженнÑ/атрибути (email, ім'Ñ, прізвище) Ñ– NameID відповідно до %{docsLinkStart} документації %{icon}%{docsLinkEnd}"
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
-msgstr ""
+msgstr "Ðалаштуйте Ñвій проект, щоб автоматично відправлÑти/отримувати зміни з іншого репозиторію. Гілки, теги та коміти автоматично будуть ÑинхронізуватиÑÑ."
msgid "SetPasswordToCloneLink|set a password"
msgstr "вÑтановити пароль"
-msgid "Settings"
-msgstr "ÐалаштуваннÑ"
+msgid "SetStatusModal|Add status emoji"
+msgstr "Додати Ñмайлик-ÑтатуÑ"
-msgid "Set up a %{type} Runner manually"
-msgstr ""
+msgid "SetStatusModal|Clear status"
+msgstr "ОчиÑтити ÑтатуÑ"
-msgid "Set up a specific Runner automatically"
-msgstr "Ðвтоматично налаштувати Ñпецифічний runner"
+msgid "SetStatusModal|Edit status"
+msgstr "Змінити ÑтатуÑ"
+
+msgid "SetStatusModal|Remove status"
+msgstr "Видалити ÑтатуÑ"
+
+msgid "SetStatusModal|Set a status"
+msgstr "Ð’Ñтановити ÑтатуÑ"
+
+msgid "SetStatusModal|Set status"
+msgstr "Ð’Ñтановити ÑтатуÑ"
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr "Вибачте, нам не вдалоÑÑ Ð²Ñтановити ваш ÑтатуÑ. Будь лаÑка, Ñпробуйте знову пізніше."
+
+msgid "SetStatusModal|What's your status?"
+msgstr "Який ваш ÑтатуÑ?"
+
+msgid "Settings"
+msgstr "ÐалаштуваннÑ"
msgid "Share"
msgstr "ПоділитиÑÑ"
@@ -6621,6 +7463,9 @@ msgstr "ПоділітьÑÑ <strong>%{sso_label}</strong> із учаÑника
msgid "Shared Runners"
msgstr "Загальні Runner'и"
+msgid "Shared projects"
+msgstr "Спільні проекти"
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr "При обнуленні хвилин конвеєрів Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проÑтору імен, кількіÑÑ‚ÑŒ вже викориÑтаних хвилин буде дорівнювати 0."
@@ -6706,12 +7551,18 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð¾Ð·Ð¼Ñ–Ñ€Ñƒ та домену Ð´Ð»Ñ ÑтаÑ
msgid "Slack application"
msgstr "заÑтоÑунок Slack"
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
-msgstr ""
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr "Slack Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»Ð¸Ñ‚ÑŒ вам взаємодіÑти з GitLab через чат за домогою команд зі Ñлешем ( / )"
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr "Повільніше, але гарантує, що робоча облаÑÑ‚ÑŒ проекту чиÑтою, оÑкільки воно клонує Ñховище з Ð½ÑƒÐ»Ñ Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ завданнÑ"
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr "Сніпети"
@@ -6728,7 +7579,7 @@ msgid "Something went wrong trying to change the confidentiality of this issue"
msgstr "Помилка при зміні конфіденційноÑÑ‚Ñ– цієї проблеми"
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
-msgstr ""
+msgstr "ЩоÑÑŒ пішло не так, при Ñпробі зміни Ñтану Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ %{issuableDisplayName}"
msgid "Something went wrong when toggling the button"
msgstr "Помилка при перемиканні кнопки"
@@ -6737,11 +7588,17 @@ msgid "Something went wrong while closing the %{issuable}. Please try again late
msgstr "Помилка при закритті %{issuable}. Будь лаÑка, Ñпробуйте пізніше"
msgid "Something went wrong while fetching %{listType} list"
-msgstr ""
+msgstr "Помилка при отриманні ÑпиÑку %{listType}"
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr "Проблема при отриманні коментарів. Будь лаÑка, Ñпробуйте знову."
msgid "Something went wrong while fetching group member contributions"
msgstr "Помилка при завантаженні внеÑків учаÑників групи"
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr "Проблема при отриманні Ñередовищ Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиту на злиттÑ. Будь лаÑка, Ñпробуйте знову."
+
msgid "Something went wrong while fetching the projects."
msgstr "ЩоÑÑŒ пішло не так під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ñ–Ð²"
@@ -6754,12 +7611,24 @@ msgstr "Помилка при повторному відкритті %{issuable
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr "Помилка при завершенні обговореннÑ. Будь лаÑка, Ñпробуйте пізніше."
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr "Проблема, не вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ %{project} до панелі керуваннÑ"
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr "Проблема, не вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ проект"
+
msgid "Something went wrong. Please try again."
msgstr "ЩоÑÑŒ пішло не так. Будь лаÑка Ñпробуйте ще раз."
msgid "Sorry, no epics matched your search"
msgstr "Вибачте, жоден епік не задовольнÑÑ” критеріÑм вашого пошуку"
+msgid "Sorry, no projects matched your search"
+msgstr "Ðа жаль жоден проект не задовольнÑÑ” критеріÑм вашого пошуку"
+
msgid "Sort by"
msgstr "Сортувати за"
@@ -6790,6 +7659,9 @@ msgstr "Ðайбільша група"
msgid "SortOptions|Largest repository"
msgstr "Ðайбільший репозиторій"
+msgid "SortOptions|Last Contact"
+msgstr "ОÑтанній контакт"
+
msgid "SortOptions|Last created"
msgstr "ОÑтанній Ñтворений"
@@ -6820,6 +7692,9 @@ msgstr "Більша вага"
msgid "SortOptions|Most popular"
msgstr "Ðайбільш популÑрний"
+msgid "SortOptions|Most stars"
+msgstr "Ðайбільше в обраних"
+
msgid "SortOptions|Name"
msgstr "Ім'Ñ"
@@ -6850,6 +7725,9 @@ msgstr "Пріоритет"
msgid "SortOptions|Recent sign in"
msgstr "Ðещодавно зареєÑтровані"
+msgid "SortOptions|Start date"
+msgstr "Дата початку"
+
msgid "SortOptions|Start later"
msgstr "Розпочатий пізніше"
@@ -6881,7 +7759,7 @@ msgid "Specific Runners"
msgstr "Спеціальні Runner’и"
msgid "Specify an e-mail address regex pattern to identify default internal users."
-msgstr ""
+msgstr "Вкажіть шаблон адреÑи електронної пошти у виглÑді регулÑрного виразу Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб автоматично визначати внутрішніх кориÑтувачів."
msgid "Specify the following URL during the Runner setup:"
msgstr "Зазначте наÑтупний URL під Ñ‡Ð°Ñ Ð²ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Runner-а:"
@@ -6925,9 +7803,21 @@ msgstr "Обрані проекти"
msgid "Start a %{new_merge_request} with these changes"
msgstr "Почати %{new_merge_request} з цими змінами"
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr "Дата початку"
+
msgid "Start the Runner!"
msgstr "ЗапуÑÑ‚Ñ–Ñ‚ÑŒ Runner!"
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr "Запущений"
@@ -6940,6 +7830,9 @@ msgstr "Залиште Ñвоє Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–
msgid "Status"
msgstr "СтатуÑ"
+msgid "Stop environment"
+msgstr "Зупинити Ñередовище"
+
msgid "Stop impersonation"
msgstr "Зупинити уоÑобленнÑ"
@@ -6949,6 +7842,9 @@ msgstr "Зупинити це Ñередовище"
msgid "Stopped"
msgstr "Зупинено"
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr "Зупинка Ñередовища наразі неможлива, тому що відбуваєтьÑÑ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ"
+
msgid "Storage"
msgstr "Сховище"
@@ -6958,9 +7854,15 @@ msgstr "Сховище:"
msgid "Subgroups"
msgstr "Підгрупи"
+msgid "Subgroups and projects"
+msgstr "Підгрупи та проекти"
+
msgid "Submit as spam"
msgstr "Позначити Ñк Ñпам"
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr "ÐадіÑлати пошук"
@@ -6973,6 +7875,12 @@ msgstr "ПідпиÑатиÑÑ Ð½Ð° рівні групи"
msgid "Subscribe at project level"
msgstr "ПідпиÑатиÑÑ Ð½Ð° рівні проекту"
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "Перейти в гілку/тег"
@@ -6991,6 +7899,9 @@ msgstr "Заголовок Ñ– футер ÑиÑтеми:"
msgid "System metrics (Custom)"
msgstr "СиÑтемні метрики (ВлаÑні)"
+msgid "System metrics (Kubernetes)"
+msgstr "СиÑтемні метрики (Kubernetes)"
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] "Тег (%{tag_count})"
@@ -7002,7 +7913,7 @@ msgid "Tags"
msgstr "Теги"
msgid "Tags feed"
-msgstr ""
+msgstr "Канал тегів"
msgid "Tags:"
msgstr "Теги:"
@@ -7097,6 +8008,9 @@ msgstr "Угода про Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг Ñ– політика кон
msgid "Terms of Service and Privacy Policy"
msgstr "Правилами кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑервіÑом Ñ– політика конфіденційноÑÑ‚Ñ–"
+msgid "Test SAML SSO"
+msgstr "ТеÑтувати SAML SSO"
+
msgid "Test coverage parsing"
msgstr "Пошук результатів Ð¿Ð¾ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñ‚ÐµÑтами"
@@ -7107,7 +8021,7 @@ msgid "The Advanced Global Search in GitLab is a powerful search service that sa
msgstr "Розширений глобальний пошук в GitLab — це потужний інÑтрумент Ñкий заощаджує ваш чаÑ. ЗаміÑÑ‚ÑŒ Ð´ÑƒÐ±Ð»ÑŽÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð´Ñƒ Ñ– витрати чаÑу, ви можете шукати код інших команд, Ñкий може допомогти у вашому проекті."
msgid "The Git LFS objects will <strong>not</strong> be synced."
-msgstr ""
+msgstr "Об'єкти Git LFS <strong>не</strong> будуть ÑинхронізуватиÑÑ."
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
msgstr "Трекер проблем — це міÑце, де можна додати речі, Ñкі потрібно покращити або розв’Ñзати в проекті"
@@ -7131,7 +8045,7 @@ msgid "The connection will time out after %{timeout}. For repositories that take
msgstr "Ð—â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ припинено піÑÐ»Ñ %{timeout}. Ð”Ð»Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ—Ð², Ñким потрібно більше чаÑу, викориÑтовуйте комбінацію clone/push."
msgid "The deployment of this job to %{environmentLink} did not succeed."
-msgstr ""
+msgstr "Ð Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð½Ð° %{environmentLink} не уÑпішне."
msgid "The fork relationship has been removed."
msgstr "Зв'Ñзок форку видалено."
@@ -7145,12 +8059,6 @@ msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ ÐŸÑ€Ð¾Ð±Ð»ÐµÐ¼Ð° показує, Ñкільки чаÑу п
msgid "The maximum file size allowed is 200KB."
msgstr "МакÑимальний розмір файлу — 200 Кб."
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr "КількіÑÑ‚ÑŒ Ñпроб, Ñкі зробить GitLab Ð´Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупу до Ñховища даних."
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr "КількіÑÑ‚ÑŒ збоїв піÑÐ»Ñ Ñ‡Ð¾Ð³Ð¾ Gitlab повніÑÑ‚ÑŽ заблокує доÑтуп до Ñховища данних. Лічильник кількоÑÑ‚Ñ– збоїв може бути Ñкинутий в інтерфейÑÑ– адмініÑтратора %{link_to_health_page}, або через %{api_documentation_link}."
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "Пароль, Ñкий потрібен Ð´Ð»Ñ Ð´ÐµÑˆÐ¸Ñ„Ñ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð²Ð°Ñ‚Ð½Ð¾Ð³Ð¾ ключа. Він Ñ” необов’Ñзковим Ñ– зберігаєтьÑÑ Ñƒ зашифрованому виглÑді."
@@ -7199,9 +8107,6 @@ msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ Ð—Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð¿Ð¾ÐºÐ°Ð·ÑƒÑ” Ñ‡Ð°Ñ Ð²Ñ–Ð´ ÑÑ‚Ð
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr "План-графік показує Ñтан ваших епіків у чаÑÑ–"
-msgid "The secure token used by the Runner to checkout the project"
-msgstr "Секретний токен, Ñкий викориÑтовує runner Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, що отримати код проекту"
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ Staging показує Ñ‡Ð°Ñ Ð¼Ñ–Ð¶ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° розгортаннÑм коду у production. Дані автоматично додаютьÑÑ Ð¿Ñ–ÑÐ»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñƒ production вперше."
@@ -7211,21 +8116,15 @@ msgstr "Вкладки нижче будуть видалені в майбутÐ
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr "Ð¡Ñ‚Ð°Ð´Ñ–Ñ Ð¢ÐµÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾ÐºÐ°Ð·ÑƒÑ” чаÑ, Ñкий GitLab CI витрачає Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ конвеєра Ð´Ð»Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¾Ð³Ð¾ запиту злиттÑ. Дані будуть автоматично додані піÑÐ»Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ конвеєра."
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr "КількіÑÑ‚ÑŒ Ñекунд, протÑгом Ñкої GitLab зберігає інформацію про збої. Якщо протÑгом цього періоду жодних збоїв не відбуваєтьÑÑ, Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ точку Ð¼Ð¾Ð½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑкидаєтьÑÑ."
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr "КількіÑÑ‚ÑŒ Ñекунд, протÑгом Ñкої GitLab намагатиметьÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ доÑтуп до Ñховища даних. По завершенню цього періоду буде згенерована помилка про Ð¿ÐµÑ€ÐµÐ²Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð»Ñ–Ð¼Ñ–Ñ‚Ñƒ чаÑу."
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr "Ð§Ð°Ñ Ñƒ Ñекундах між перевірками Ñховища. Якщо Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ° ще на завершена, GitLab пропуÑтить наÑтупну."
-
msgid "The time taken by each data entry gathered by that stage."
msgstr "ЧаÑ, витрачений на кожен елемент, зібраний на цій Ñтадії."
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr "Збір даних про викориÑÑ‚Ð°Ð½Ð½Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð¾, Ñ– це не можна налаштувати через цю форму."
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr "Мапа кориÑтувачів — це JSON-документ, Ñкий задає Ñк адреÑи електронної пошти та імена кориÑтувачів Google Code, що приймали учаÑÑ‚ÑŒ у ваших проектах будуть імпортовані у GitLab. Ви можете змінити його шлÑхом зміни значень, що ÑтоÑÑ‚ÑŒ Ñправа від <code>:</code>. Ðе видалÑйте лапки та інші знаки пунктуації, а також не змінюйте адреÑи електронної пошти чи імена кориÑтувачів зліва."
@@ -7235,6 +8134,9 @@ msgstr "Мапа кориÑтувачів — це правила імпорту
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "Середнє Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð² Ñ€Ñдку. Приклад: між 3, 5, 9, Ñередніми 5, між 3, 5, 7, 8, Ñередніми (5 + 7) / 2 = 6."
+msgid "There are no archived projects yet"
+msgstr "Ðаразі немає жодного архівованого проекту"
+
msgid "There are no issues to show"
msgstr "Ðемає проблем Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ"
@@ -7244,14 +8146,20 @@ msgstr "Тут ще немає міток"
msgid "There are no merge requests to show"
msgstr "Ðемає запитів на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ"
-msgid "There are problems accessing Git storage: "
-msgstr "Є проблеми з доÑтупом до Ñховища git: "
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr "Ðемає індекÑованих змін"
+
+msgid "There are no unstaged changes"
+msgstr "Ðемає неіндекÑованих змін"
msgid "There was an error adding a todo."
-msgstr ""
+msgstr "Помилка при додаванні задачі."
msgid "There was an error deleting the todo."
-msgstr ""
+msgstr "Помилка при видаленні задачі."
msgid "There was an error loading users activity calendar."
msgstr "Помилка при завантаженні ÐºÐ°Ð»ÐµÐ½Ð´Ð°Ñ€Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ð¾ÑÑ‚Ñ– кориÑтувачів."
@@ -7292,10 +8200,13 @@ msgstr "ВидиміÑÑ‚ÑŒ цієї дошки обмежена"
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr "Ð¦Ñ Ð³Ñ–Ð»ÐºÐ° була змінена піÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾ моменту, коли ви почали Ñ—Ñ— редагувати. Ви хотіли б Ñтворити нову?"
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr "Заплановане Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ реєÑтру контейнерів."
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7316,6 +8227,9 @@ msgstr "Ð¦Ñ Ð³Ñ€ÑƒÐ¿Ð° ще не має жодного групового Runne
msgid "This is a confidential issue."
msgstr "Це конфіденційна проблема."
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr "Це перший запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ñ–Ð´ цього автора Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту."
@@ -7350,16 +8264,19 @@ msgid "This job has not started yet"
msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ñ‰Ðµ не запуÑтилоÑÑ"
msgid "This job is an out-of-date deployment to %{environmentLink}."
-msgstr ""
+msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ñ” заÑтарілим розгортаннÑм на %{environmentLink}."
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
+msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ñ” заÑтарілим розгортаннÑм на %{environmentLink}. ПереглÑньте оÑтаннє Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ %{deploymentLink}."
+
+msgid "This job is archived. Only the complete pipeline can be retried."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
-msgstr ""
+msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ñтворює Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° %{environmentLink}."
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ±ÑƒÐ²Ð°Ñ” в Ñтані Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ– чекає на запуÑк Runner"
@@ -7368,14 +8285,17 @@ msgid "This job is stuck, because you don't have any active runners online with
msgstr ""
msgid "This job is stuck, because you don't have any active runners that can run this job."
-msgstr ""
+msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ðµ, тому що немає активних runner'ів, Ñкі могли б його виконати."
msgid "This job is the most recent deployment to %{link}."
-msgstr ""
+msgstr "Це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ñ” оÑтаннім розгортаннÑм на %{link}."
msgid "This job requires a manual action"
msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð²Ð¸Ð¼Ð°Ð³Ð°Ñ” ручних дій"
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "Це означає, що ви не можете відправлÑти код, поки не Ñтворите порожній репозиторій або не імпортуєте Ñ–Ñнуючий."
@@ -7383,7 +8303,7 @@ msgid "This merge request is locked."
msgstr "Цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¾Ð²Ð°Ð½Ð¾."
msgid "This option is disabled as you don't have write permissions for the current branch"
-msgstr ""
+msgstr "Цей параметр вимкнено, тому що у Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” дозволу на Ð·Ð°Ð¿Ð¸Ñ Ñƒ поточну гілку"
msgid "This option is disabled while you still have unstaged changes"
msgstr "Ð¦Ñ Ð¾Ð¿Ñ†Ñ–Ñ Ð½ÐµÐ´Ð¾Ñтупна, поки у Ð²Ð°Ñ Ñ” неіндекÑовані зміни"
@@ -7400,15 +8320,24 @@ msgstr "Цей проект"
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr "Цей проект не входить до жодної групи Ñ– тому не може викориÑтовувати групові Runner’и."
-msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
+msgid "This project does not have a wiki homepage yet"
msgstr ""
+msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
+msgstr "Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту вимкнено білінг. Щоб Ñтворити клаÑтер, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">увімкніть білінг <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> Ñ– Ñпробуйте знову."
+
msgid "This repository"
msgstr "Цей репозиторій"
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr "Ðе вдалоÑÑ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð·Ð¸Ñ‚Ð¸ порівнÑннÑ, оÑкільки воно завелике."
@@ -7422,7 +8351,7 @@ msgid "This user will be the author of all events in the activity feed that are
msgstr ""
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
-msgstr ""
+msgstr "Цей кориÑтувач буде автором вÑÑ–Ñ… подій в каналі активноÑÑ‚Ñ–, Ñкі Ñ” результатом оновленнÑ, наприклад ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¸Ñ… гілок або Ð²Ñ–Ð´Ð¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¸Ñ… комітів до Ñ–Ñнуючих гілок. При Ñтворенні або перепризначенні ви зможете призначити лише Ñебе кориÑтувачем Ð´Ð»Ñ Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ."
msgid "This will delete the custom metric, Are you sure?"
msgstr "Це призведе до Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð²Ð»Ð°Ñної метрики, ви впевнені?"
@@ -7436,9 +8365,15 @@ msgstr "Ð§Ð°Ñ Ð´Ð¾ початку потраплÑÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼Ð¸ в Ð
msgid "Time before an issue starts implementation"
msgstr "Ð§Ð°Ñ Ð´Ð¾ початку роботи над проблемою"
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr "Ð§Ð°Ñ Ð¼Ñ–Ð¶ ÑтвореннÑм запиту Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ– його виконаннÑм або закриттÑм"
+msgid "Time estimate"
+msgstr "Запланований чаÑ"
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr "Ð§Ð°Ñ Ð² Ñекундах, протÑгом Ñкого GitLab чекатиме відповіді від зовнішньої Ñлужби. Якщо вона не відповіÑÑ‚ÑŒ вчаÑно, доÑтуп буде заборонений."
@@ -7542,7 +8477,7 @@ msgid "Timeago|1 year remaining"
msgstr "ЗалишивÑÑ 1 рік"
msgid "Timeago|Past due"
-msgstr "ПроÑтрочені"
+msgstr "ПроÑтрочено"
msgid "Timeago|in %s days"
msgstr "через %s дні(в)"
@@ -7633,12 +8568,24 @@ msgstr "Ð”Ð»Ñ Ð¿Ñ€Ð¸Ñ”Ð´Ð½Ð°Ð½Ð½Ñ SVN-репозиторію, переглÑн
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr "Ð”Ð»Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÑƒ введіть URL-адреÑу FogBugz та параметри входу нижче. Далі ви зможете перенеÑти кориÑтувачів та вибрати проекти Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ."
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr "Спочатку введіть адреÑу Ñервера GÑ–tea Ñ– %{link_to_personal_token}."
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr "Щоб допомогти покращити GitLab та його зручніÑÑ‚ÑŒ викориÑтаннÑ, GitLab буде періодично збирати інформацію про викориÑтаннÑ."
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr "Щоб допомогти покращити GitLab, ми хотіли б періодично збирати інформацію про викориÑтаннÑ. Це можна змінити в будь-Ñкий Ñ‡Ð°Ñ Ð² %{settings_link_start}ÐалаштуваннÑÑ…%{link_end}. %{info_link_start}Додаткова інформаціÑ%{link_end}"
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr "Ð”Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ—Ð² з GitHub, ви можете викориÑтовувати %{personal_access_token_link}. Коли ви Ñтворюватимете ваш перÑональний токен доÑтупу, вам потрібно буде вибрати облаÑÑ‚ÑŒ дії <code>repo</code>, щоб ми могли відобразити ÑпиÑок ваших публічних та приватних репозиторіїв, доÑтупних Ð´Ð»Ñ Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ."
@@ -7654,6 +8601,9 @@ msgstr "Щоб переміÑтити або Ñкопіювати веÑÑŒ прÐ
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr "Щоб викориÑтовувати лише функції CI/CD Ð´Ð»Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾Ð³Ð¾ репозиторію, виберіть <strong>CI/CD Ð´Ð»Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾Ð³Ð¾ репозиторію</strong>."
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr "Щоб налаштувати аутентифікацію SAML Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ñ— групи через провайдера ідентифікації такої Ñк Azure, Okta, Onelogin, Ping Identity або вашого влаÑного поÑтачальника SAML 2.0:"
@@ -7666,12 +8616,15 @@ msgstr "До цього інÑтанÑу GitLab"
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr "Щоб перевірити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ GitLab CI, перейдіть до \"CI / CD → Конвеєри\" у вашому проекті та натиÑніть кнопку \"Перевірка конфігурації (CI Lint)\"."
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
-msgstr "Ð”Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду плану-графіку додайте заплановані дати початку та Ð·Ð°Ð²ÐµÑ€ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ одного з ваших епіків у цій групі або Ñ—Ñ— підгрупах. ВідображаютьÑÑ Ð»Ð¸ÑˆÐµ епіки за попередні та наÑтупні 3 міÑÑці."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
msgid "To widen your search, change or remove filters."
msgstr "Щоб розширити пошук, змініть або видаліть фільтри."
+msgid "Today"
+msgstr "Сьогодні"
+
msgid "Todo"
msgstr "Задача"
@@ -7681,9 +8634,15 @@ msgstr "Задачі"
msgid "Toggle Sidebar"
msgstr "Перемикач бічної панелі"
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr "Перемикач диÑкуÑÑ–Ñ—"
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "Переключити навігацію"
@@ -7699,6 +8658,9 @@ msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿ÐµÑ€ÐµÐ¼Ð¸ÐºÐ°Ñ‡Ð°: УВІМКÐЕÐО"
msgid "Token"
msgstr "Токен"
+msgid "Tomorrow"
+msgstr "Завтра"
+
msgid "Too many changes to show."
msgstr "Забагато змін Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ñƒ."
@@ -7714,6 +8676,9 @@ msgstr "Загальний чаÑ, щоб перевірити вÑÑ– коміт
msgid "Total: %{total}"
msgstr "Ð’Ñього: %{total}"
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr "ВідÑтежувати активніÑÑ‚ÑŒ за допомогою аналітики учаÑників."
@@ -7723,14 +8688,17 @@ msgstr "ВідÑтежуйте групи проблем зі Ñпільною Ñ
msgid "Track time with quick actions"
msgstr "ВідÑтежуйте Ñ‡Ð°Ñ Ð·Ð° допомогою швидких дій"
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr "ПопулÑрні"
msgid "Trigger"
-msgstr ""
+msgstr "Тригер"
msgid "Trigger pipelines for mirror updates"
-msgstr ""
+msgstr "ЗапуÑкати конвеєри Ð´Ð»Ñ Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð¸Ñ… змін"
msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
msgstr ""
@@ -7741,24 +8709,42 @@ msgstr "ЗапуÑтити цю ручну дію"
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr "Тригери можуть примуÑово перезібрати гілку або тег через API. Ці токени дозволÑÑŽÑ‚ÑŒ діÑти від імені кориÑтувача: в тому чиÑлі отримувати доÑтуп до його проектів та проектних прав доÑтупу."
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr "Спробуйте ще раз"
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "Ввімкнути Service Desk"
msgid "Twitter"
msgstr "Twitter"
+msgid "Two-factor authentication"
+msgstr "Двофакторна аутентифікаціÑ"
+
msgid "Type"
msgstr "Тип"
msgid "Unable to load the diff. %{button_try_again}"
msgstr "Ðеможливо завантажити порівнÑÐ½Ð½Ñ (diff). %{button_try_again}"
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "Ðеможливо увійти до групи за допомогою SAML через \"%{reason}\""
+msgid "Unable to update this epic at this time."
+msgstr "Ðеможливо оновити цей епік в даний момент."
+
+msgid "Undo"
+msgstr "СкаÑувати"
+
msgid "Unknown"
msgstr "Ðевідомо"
@@ -7766,7 +8752,7 @@ msgid "Unlock"
msgstr "Розблокувати"
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
-msgstr ""
+msgstr "Розблокувати %{issuableDisplayName}? <strong>Будь-хто</strong> зможе залишати коментарі."
msgid "Unlocked"
msgstr "Розблоковано"
@@ -7774,6 +8760,12 @@ msgstr "Розблоковано"
msgid "Unresolve discussion"
msgstr "Повторно відкрити обговореннÑ"
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr "Ðе індекÑувати"
+
msgid "Unstage all changes"
msgstr "Ðе індекÑувати вÑÑ– зміни"
@@ -7787,7 +8779,7 @@ msgid "Unstaged %{type}"
msgstr "ÐеіндекÑовано %{type}"
msgid "Unstaged and staged %{type}"
-msgstr "ÐеіндекÑовано та проіндекÑовано %{type}"
+msgstr "ÐеіндекÑовані та проіндекÑовані %{type}"
msgid "Unstar"
msgstr "Видалити із обраних"
@@ -7807,14 +8799,17 @@ msgstr "Ðепідтверджено"
msgid "Up to date"
msgstr "Ðктуальний"
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr "Оновити"
msgid "Update now"
msgstr "Оновити зараз"
-msgid "Update your group name, description, avatar, and other general settings."
-msgstr "Оновіть Ñ–Ð¼â€™Ñ Ð³Ñ€ÑƒÐ¿Ð¸, опиÑ, аватар та інші загальні налаштуваннÑ."
+msgid "Update your group name, description, avatar, and visibility."
+msgstr "Оновіть Ñ–Ð¼â€™Ñ Ð³Ñ€ÑƒÐ¿Ð¸, опиÑ, аватар та видиміÑÑ‚ÑŒ."
msgid "Updating"
msgstr "ОновленнÑ"
@@ -7843,15 +8838,15 @@ msgstr "ÐадіÑлати новий файл"
msgid "Upload file"
msgstr "ÐадіÑлати файл"
-msgid "Upload new avatar"
-msgstr "ÐадіÑлати новий аватар"
-
msgid "UploadLink|click to upload"
msgstr "ÐатиÑніть, щоб надіÑлати"
msgid "Upvotes"
msgstr "Лайки"
+msgid "Usage ping is not enabled"
+msgstr "Збір даних про викориÑÑ‚Ð°Ð½Ð½Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð¾"
+
msgid "Usage statistics"
msgstr "СтатиÑтика викориÑтаннÑ"
@@ -7879,6 +8874,9 @@ msgstr "ВикориÑтовуютьÑÑ Ð³Ð»Ð¾Ð±Ð°Ð»ÑŒÐ½Ñ– налаштуван
msgid "Used by members to sign in to your group in GitLab"
msgstr "ВикориÑтовуєтьÑÑ ÑƒÑ‡Ð°Ñниками Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ у вашу групу в GitLab"
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr "Когорти КориÑтувача показуютьÑÑ Ð»Ð¸ÑˆÐµ тоді, коли увімкнено %{usage_ping_link_start}збір даних про викориÑтаннÑ%{usage_ping_link_end}."
+
msgid "User Settings"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
@@ -7888,12 +8886,54 @@ msgstr "Ліміти чаÑтоти Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів та IP"
msgid "User map"
msgstr "Мапа кориÑтувачів"
+msgid "UserProfile|Activity"
+msgstr "ÐктивніÑÑ‚ÑŒ"
+
+msgid "UserProfile|Already reported for abuse"
+msgstr "Вже повідомлено про зловживаннÑ"
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr "Редагувати профіль"
+
+msgid "UserProfile|Groups"
+msgstr "Групи"
+
+msgid "UserProfile|Most Recent Activity"
+msgstr "ОÑÑ‚Ð°Ð½Ð½Ñ Ð°ÐºÑ‚Ð¸Ð²Ð½Ñ–ÑÑ‚ÑŒ"
+
+msgid "UserProfile|Overview"
+msgstr "ОглÑд"
+
+msgid "UserProfile|Personal projects"
+msgstr "ОÑобиÑÑ‚Ñ– проекти"
+
+msgid "UserProfile|Recent contributions"
+msgstr "ОÑтанні внеÑки"
+
+msgid "UserProfile|Report abuse"
+msgstr "Повідомити про зловживаннÑ"
+
+msgid "UserProfile|Snippets"
+msgstr "Сніпети"
+
+msgid "UserProfile|Subscribe"
+msgstr "ПідпиÑатиÑÑ"
+
+msgid "UserProfile|This user has a private profile"
+msgstr "Цей кориÑтувач має приватний профіль"
+
+msgid "UserProfile|View all"
+msgstr "ПереглÑнути вÑе"
+
+msgid "UserProfile|View user in admin area"
+msgstr "ПереглÑнути кориÑтувача в адмінці"
+
msgid "Users"
msgstr "КориÑтувачі"
-msgid "User|Current status"
-msgstr "Поточний ÑтатуÑ"
-
msgid "Variables"
msgstr "Змінні"
@@ -7918,6 +8958,15 @@ msgstr "Підтверджено"
msgid "Version"
msgstr "ВерÑÑ–Ñ"
+msgid "View %{alerts}"
+msgstr "ПереглÑнути %{alerts}"
+
+msgid "View app"
+msgstr "ПереглÑнути заÑтоÑунок"
+
+msgid "View documentation"
+msgstr "ПереглÑнути документацію"
+
msgid "View epics list"
msgstr "ПереглÑнути ÑпиÑок епіків"
@@ -7951,9 +9000,15 @@ msgstr "ПереглÑнути мітки проекту"
msgid "View replaced file @ "
msgstr "ПереглÑд заміненого файлу @ "
+msgid "View the documentation"
+msgstr "ПереглÑнути документацію"
+
msgid "Visibility and access controls"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ð´Ð¸Ð¼Ð¾ÑÑ‚Ñ– та доÑтупу"
+msgid "Visibility level"
+msgstr "Рівень видимоÑÑ‚Ñ–"
+
msgid "Visibility level:"
msgstr "Рівень видимоÑÑ‚Ñ–:"
@@ -7972,6 +9027,36 @@ msgstr "Публічний"
msgid "VisibilityLevel|Unknown"
msgstr "Ðевідомий"
+msgid "Vulnerability|Class"
+msgstr "КлаÑ"
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr "ОпиÑ"
+
+msgid "Vulnerability|File"
+msgstr "Файл"
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr "Проект"
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr "РішеннÑ"
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "Хочете побачити дані? Будь лаÑка, попроÑить у адмініÑтратора доÑтуп."
@@ -8011,6 +9096,12 @@ msgstr "Якщо увімкнено, кориÑтувачі не можуть в
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "Якщо залишити URL порожнім, можна вÑтановлювати мітки клаÑифікації без Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ð¹ проекту та Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾Ñ— авторизації."
+msgid "Who can see this group?"
+msgstr "Хто може бачити цю групу?"
+
+msgid "Who will be able to see this group?"
+msgstr "Хто зможе побачити цю групу?"
+
msgid "Wiki"
msgstr "Вікі"
@@ -8161,6 +9252,9 @@ msgstr "Так, додати це"
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr "Так, дозволити мені зв’Ñзати кориÑтувачів Google Code із повними іменами кориÑтувачів GitLab."
+msgid "Yesterday"
+msgstr "Вчора"
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr "Ви — адмініÑтратор, а це означає, що Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупу Ð´Ð»Ñ <strong>%{client_name}</strong> дозволить їм взаємодіÑти з GitLab Ñк адмініÑтратору. Продовжуйте обережно."
@@ -8179,9 +9273,6 @@ msgstr "Ви збираєтеÑÑ Ð¿ÐµÑ€ÐµÐ´Ð°Ñ‚Ð¸ проект %{project_full_n
msgid "You are on a read-only GitLab instance."
msgstr "Ви знаходитеÑÑ Ð½Ð° інÑтанÑÑ– Gitlab \"тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ\"."
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr "Ви знаходитеÑÑŒ на вторинному <b>лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ</b> Geo-вузлі. Якщо ви хочете внеÑти будь-Ñкі зміни, ви повинні відвідати %{primary_node}."
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr "ЗаміÑÑ‚ÑŒ цього ви можете %{linkStart}переглÑнути бінарні дані%{linkEnd}."
@@ -8191,9 +9282,6 @@ msgstr "Ви також можете Ñтворити проект із кома
msgid "You can also star a label to make it a priority label."
msgstr "Ви можете додати мітку в обрані, щоб зробити її пріоритетною."
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr "Ви також можете перевірити Ñвій .gitlab-ci.yml за допомогою %{linkStart}Lint%{linkEnd}"
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr "Ви можете легко робити внеÑки до них, запроÑивши доÑтуп до цих груп."
@@ -8213,7 +9301,10 @@ msgid "You can resolve the merge conflict using either the Interactive mode, by
msgstr "Ви можете розв’Ñзати цей конфлікт Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð° допомогою інтерактивного режиму (викориÑтовуючи кнопки %{use_ours} та %{use_theirs}), або безпоÑередньо редагуючи файли. Закомітити зміни у %{branch_name}"
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
-msgstr ""
+msgstr "Ви можете налаштувати Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð½Ð° викориÑÑ‚Ð°Ð½Ð½Ñ Runnir'ів з конкретними тегами. РозділÑйте теги комами."
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr "Ви можете перевірити Ñвій .gitlab-ci.yml у %{linkStart}CI Lint%{linkEnd}."
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr "Ви не можете запиÑувати на вторинні інÑтанÑи \"тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ\" GitLab Geo. Будь лаÑка викориÑтовуйте %{link_to_primary_node}."
@@ -8221,6 +9312,9 @@ msgstr "Ви не можете запиÑувати на вторинні інÑ
msgid "You cannot write to this read-only GitLab instance."
msgstr "Ви не можете запиÑувати на цей \"тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ\" інÑÑ‚Ð°Ð½Ñ GitLab."
+msgid "You do not have any subscriptions yet"
+msgstr "У Ð²Ð°Ñ Ñ‰Ðµ немає підпиÑок"
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” необхідних прав доÑтупу, щоб перевизначити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñинхронізації LDAP-груп."
@@ -8234,7 +9328,7 @@ msgid "You have no permissions"
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” прав доÑтупу"
msgid "You have reached your project limit"
-msgstr "Ви доÑÑгли Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð² вашому проекті"
+msgstr "Ви доÑÑгли Ñвого ліміту по кількоÑÑ‚Ñ– проектів"
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr "Ви повинні прийнÑти правила кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑервіÑом Ñ– політику конфіденційноÑÑ‚Ñ– Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾, щоб Ñтворити обліковий запиÑ"
@@ -8242,9 +9336,6 @@ msgstr "Ви повинні прийнÑти правила кориÑтуван
msgid "You must have maintainer access to force delete a lock"
msgstr "Ви повинні мати доÑтуп керівника Ð´Ð»Ñ Ð¿Ñ€Ð¸Ð¼ÑƒÑового Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ "
-msgid "You must sign in to star a project"
-msgstr "Ðеобхідно увійти, щоб оцінити проект"
-
msgid "You need a different license to enable FileLocks feature"
msgstr "Ð”Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ— функції Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¤Ð°Ð¹Ð»Ñ–Ð² вам потрібна інша ліцензіÑ"
@@ -8254,6 +9345,12 @@ msgstr "Вам потрібна верÑÑ–Ñ git-lfs верÑÑ–Ñ— %{min_git_lfs_
msgid "You need permission."
msgstr "Вам потрібен дозвіл"
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr "Ви втратите вÑÑ– зміни, внеÑені вами в цей файл. Цю дію не можна ÑкаÑувати."
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr "Ви втратите вÑÑ– неіндекÑовані зміни, внеÑені вами в цей проект. Цю дію не можна ÑкаÑувати."
+
msgid "You will not get any notifications via email"
msgstr "Ви не отримаєте ніÑких повідомлень по електронній пошті"
@@ -8320,6 +9417,9 @@ msgstr "Ваші зміни можуть бути закомічені до %{br
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr "Ваші зміни закомічено. Коміт %{commitId} %{commitStats}"
+msgid "Your changes have been saved"
+msgstr "Ваші зміни було збережено"
+
msgid "Your comment will not be visible to the public."
msgstr "Ваш коментар не буде видимим Ð´Ð»Ñ Ð²ÑÑ–Ñ…."
@@ -8341,20 +9441,6 @@ msgstr "тому"
msgid "among other things"
msgstr "тощо"
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] "Ñ– %d виправлену вразливіÑÑ‚ÑŒ"
-msgstr[1] "Ñ– %d виправлені вразливоÑÑ‚Ñ–"
-msgstr[2] "Ñ– %d виправлених вразливоÑтей"
-msgstr[3] "Ñ– %d виправлених вразливоÑтей"
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] "та 1 виправлена вразливіÑÑ‚ÑŒ"
-msgstr[1] "Ñ– %d виправлених вразливоÑтей"
-msgstr[2] "Ñ– %d виправлених вразливоÑтей"
-msgstr[3] "Ñ– %d виправлених вразливоÑтей"
-
msgid "assign yourself"
msgstr "призначити Ñебе"
@@ -8382,20 +9468,63 @@ msgstr "%{vulnerability} впливає на %{namespace}."
msgid "ciReport|%{remainingPackagesCount} more"
msgstr "%{remainingPackagesCount} більше"
-msgid "ciReport|%{reportName} is loading"
-msgstr "%{reportName} завантажуєтьÑÑ"
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] "%{reportType} %{status} виÑвив %{fixedCount} виправлену вразливіÑÑ‚ÑŒ"
+msgstr[1] "%{reportType} %{status} виÑвив %{fixedCount} виправлені вразливоÑÑ‚Ñ–"
+msgstr[2] "%{reportType} %{status} виÑвив %{fixedCount} виправлених вразливоÑтей"
+msgstr[3] "%{reportType} %{status} виÑвив %{fixedCount} виправлених вразливоÑтей"
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] "%{reportType} %{status} виÑвив %{newCount} нову вразливіÑÑ‚ÑŒ"
+msgstr[1] "%{reportType} %{status} виÑвив %{newCount} нові вразливоÑÑ‚Ñ–"
+msgstr[2] "%{reportType} %{status} виÑвив %{newCount} нових вразливоÑтей"
+msgstr[3] "%{reportType} %{status} виÑвив %{newCount} нових вразливоÑтей"
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr "%{reportType} %{status} виÑвив %{newCount} нових та %{fixedCount} виправлених вразливоÑтей"
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] "%{reportType} %{status} виÑвив %{newCount} вразливіÑÑ‚ÑŒ лише Ð´Ð»Ñ Ð³Ñ–Ð»ÐºÐ¸-джерела"
+msgstr[1] "%{reportType} %{status} виÑвив %{newCount} вразливоÑÑ‚Ñ– лише Ð´Ð»Ñ Ð³Ñ–Ð»ÐºÐ¸-джерела"
+msgstr[2] "%{reportType} %{status} виÑвив %{newCount} вразливоÑтей лише Ð´Ð»Ñ Ð³Ñ–Ð»ÐºÐ¸-джерела"
+msgstr[3] "%{reportType} %{status} виÑвив %{newCount} вразливоÑтей лише Ð´Ð»Ñ Ð³Ñ–Ð»ÐºÐ¸-джерела"
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr "%{reportType} %{status} не виÑвив нових вразливоÑтей"
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr "%{reportType}%{status} не виÑвив вразливоÑтей"
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr "%{reportType} %{status} не виÑвив нових вразливоÑтей лише Ð´Ð»Ñ Ð³Ñ–Ð»ÐºÐ¸-джерела"
+
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] "%{reportType} виÑвив %{vulnerabilityCount} вразливіÑÑ‚ÑŒ"
+msgstr[1] "%{reportType} виÑвив %{vulnerabilityCount} вразливоÑÑ‚Ñ–"
+msgstr[2] "%{reportType} виÑвив %{vulnerabilityCount} вразливоÑтей"
+msgstr[3] "%{reportType} виÑвив %{vulnerabilityCount} вразливоÑтей"
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr "%{reportType} не виÑвив вразливоÑтей"
+
+msgid "ciReport|%{reportType} is loading"
+msgstr "%{reportType} завантажуєтьÑÑ"
-msgid "ciReport|%{reportName} resulted in error while loading results"
-msgstr "%{reportName} видав помилку при завантаженні результатів"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr "%{reportType}: Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¸Ð·Ð²ÐµÐ»Ð¾ до помилки"
-msgid "ciReport|%{type} detected no new security vulnerabilities"
-msgstr "%{type} не виÑвило нових вразливоÑтей"
+msgid "ciReport|(errors when loading results)"
+msgstr "(помилки під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ñ–Ð²)"
-msgid "ciReport|%{type} detected no security vulnerabilities"
-msgstr "%{type} не виÑвило вразливоÑтей"
+msgid "ciReport|(is loading)"
+msgstr "(завантажуєтьÑÑ)"
-msgid "ciReport|%{type} detected no vulnerabilities"
-msgstr "%{type} не виÑвив вразливоÑтей"
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr "(завантажуєтьÑÑ, помилки під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ€ÐµÐ·ÑƒÐ»ÑŒÑ‚Ð°Ñ‚Ñ–Ð²)"
msgid "ciReport|Class"
msgstr "КлаÑ"
@@ -8406,38 +9535,20 @@ msgstr "ЯкіÑÑ‚ÑŒ коду"
msgid "ciReport|Confidence"
msgstr "ВпевненіÑÑ‚ÑŒ"
-msgid "ciReport|Container scanning detected"
-msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ¹Ð½ÐµÑ€Ñ–Ð² виÑвило"
+msgid "ciReport|Container scanning"
+msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ¹Ð½ÐµÑ€Ð°"
msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ¹Ð½ÐµÑ€Ñ–Ð² виÑвлÑÑ” відомі вразливоÑÑ‚Ñ– у ваших Docker образах."
-msgid "ciReport|Container scanning is loading"
-msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ¹Ð½ÐµÑ€Ñ–Ð² завантажуєтьÑÑ"
-
-msgid "ciReport|Container scanning resulted in error while loading results"
-msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð½Ñ‚ÐµÐ¹Ð½ÐµÑ€Ñ–Ð² видало помилку при завантаженні результатів"
-
-msgid "ciReport|DAST detected"
-msgstr "DAST виÑвив"
-
-msgid "ciReport|DAST is loading"
-msgstr "DAST завантажуєтьÑÑ"
-
-msgid "ciReport|DAST resulted in error while loading results"
-msgstr "DAST видав помилку при завантаженні результатів"
+msgid "ciReport|DAST"
+msgstr "DAST"
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей виÑвлÑÑ” відомі вразливоÑÑ‚Ñ– у залежноÑÑ‚ÑÑ… вашого коду."
-msgid "ciReport|Dependency scanning detected"
-msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей виÑвило"
-
-msgid "ciReport|Dependency scanning is loading"
-msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей завантажуєтьÑÑ"
-
-msgid "ciReport|Dependency scanning resulted in error while loading results"
-msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей видало помилку при завантаженні результатів"
+msgid "ciReport|Dependency scanning"
+msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей"
msgid "ciReport|Description"
msgstr "ОпиÑ"
@@ -8469,22 +9580,19 @@ msgstr "ІнÑтанÑи"
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про взаємодію з звітами безпеки (Ðльфа)."
-msgid "ciReport|Learn more about whitelisting"
-msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про білий ÑпиÑок"
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñми виÑвило %d ліцензію лише Ð´Ð»Ñ Ð³Ñ–Ð»ÐºÐ¸-джерела"
+msgstr[1] "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñми виÑвило %d ліцензії лише Ð´Ð»Ñ Ð³Ñ–Ð»ÐºÐ¸-джерела"
+msgstr[2] "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñми виÑвило %d ліцензій лише Ð´Ð»Ñ Ð³Ñ–Ð»ÐºÐ¸-джерела"
+msgstr[3] "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñми виÑвило %d ліцензій лише Ð´Ð»Ñ Ð³Ñ–Ð»ÐºÐ¸-джерела"
msgid "ciReport|License management detected %d new license"
msgid_plural "ciReport|License management detected %d new licenses"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñми виÑвило %d нову ліцензію"
+msgstr[1] "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñми виÑвило %d нові ліцензії"
+msgstr[2] "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñми виÑвило %d нових ліцензій"
+msgstr[3] "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñми виÑвило %d нових ліцензій"
msgid "ciReport|License management detected no licenses for the source branch only"
msgstr ""
@@ -8498,6 +9606,9 @@ msgstr "ПоÑиланнÑ"
msgid "ciReport|Loading %{reportName} report"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð·Ð²Ñ–Ñ‚Ñƒ %{reportName}"
+msgid "ciReport|Manage licenses"
+msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñми"
+
msgid "ciReport|Method"
msgstr "СпоÑіб"
@@ -8516,14 +9627,8 @@ msgstr "Показники продуктивноÑÑ‚Ñ–"
msgid "ciReport|Revert dismissal"
msgstr "Відмінити відхиленнÑ"
-msgid "ciReport|SAST detected"
-msgstr "SAST виÑвив"
-
-msgid "ciReport|SAST is loading"
-msgstr "SAST завантажуєтьÑÑ"
-
-msgid "ciReport|SAST resulted in error while loading results"
-msgstr "SAST видав помилку при завантаженні результатів"
+msgid "ciReport|SAST"
+msgstr "SAST"
msgid "ciReport|Security scanning"
msgstr "Перевірка безпеки"
@@ -8531,9 +9636,6 @@ msgstr "Перевірка безпеки"
msgid "ciReport|Security scanning failed loading any results"
msgstr "Помилка при завантаженні результатів перевірки безпеки"
-msgid "ciReport|Security scanning is loading"
-msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ завантажуєтьÑÑ"
-
msgid "ciReport|Severity"
msgstr "СерйозніÑÑ‚ÑŒ"
@@ -8564,25 +9666,19 @@ msgstr "Помилка при завантаженні звіту по ÑканÑ
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "Помилка при відміні відхиленнÑ. Будь лаÑка, Ñпробуйте знову."
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr "Ðезатверджені вразливоÑÑ‚Ñ– (червоні) можуть бути відмічені Ñк затверджені."
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr "Оновити %{name} з %{version} до %{fixed}."
msgid "ciReport|Used by %{packagesString}"
msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "ВикориÑтовуєтьÑÑ %{packagesString}"
+msgstr[1] "ВикориÑтовуєтьÑÑ %{packagesString} Ñ– %{lastPackage}"
+msgstr[2] "ВикориÑтовуєтьÑÑ %{packagesString} Ñ– %{lastPackage}"
+msgstr[3] "ВикориÑтовуєтьÑÑ %{packagesString} Ñ– %{lastPackage}"
msgid "ciReport|View full report"
msgstr "ПереглÑнути повний звіт"
-msgid "ciReport|no vulnerabilities"
-msgstr "немає вразливоÑтей"
-
msgid "ciReport|on pipeline"
msgstr "в конвеєрі"
@@ -8593,7 +9689,7 @@ msgid "confidentiality|You are going to turn off the confidentiality. This means
msgstr "Ви вимикаєте конфіденційніÑÑ‚ÑŒ. Це означає, що <strong>будь-хто</strong> зможе бачити Ñ– залишати коментарі Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— проблеми."
msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
+msgstr "Ви вмикаєте конфіденційніÑÑ‚ÑŒ. Це означає що лише члени команди <strong>Ñ€Ñ–Ð²Ð½Ñ Ñ€ÐµÐ¿Ð¾Ñ€Ñ‚ÐµÑ€ або вище</strong> матимуть змогу бачити та залишати коментарі Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— проблеми."
msgid "connecting"
msgstr "з'єднаннÑ"
@@ -8614,38 +9710,34 @@ msgstr[3] "днів"
msgid "deploy token"
msgstr "токен Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ"
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] "виÑвлено %d виправлену вразливіÑÑ‚ÑŒ"
-msgstr[1] "виÑвлено %d виправлених вразливоÑтей"
-msgstr[2] "виÑвлено %d виправлених вразливоÑтей"
-msgstr[3] "виÑвлено %d виправлених вразливоÑтей"
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] "виÑвлено %d нову вразливіÑÑ‚ÑŒ"
-msgstr[1] "виÑвлено %d нових вразливоÑтей"
-msgstr[2] "виÑвлено %d нових вразливоÑтей"
-msgstr[3] "виÑвлено %d нових вразливоÑтей"
-
-msgid "detected no vulnerabilities"
-msgstr "не виÑвило вразливоÑтей"
-
msgid "disabled"
msgstr "вимкнено"
msgid "done"
msgstr "готово"
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] "чернетка"
+msgstr[1] "чернетки"
+msgstr[2] "чернеток"
+msgstr[3] "чернеток"
+
msgid "enabled"
msgstr "увімкнено"
msgid "estimateCommand|%{slash_command} will update the estimated time with the latest command."
-msgstr "%{slash_command} перезезапиÑує запланований Ñ‡Ð°Ñ Ð¾Ñтаннім значеннÑм."
+msgstr "%{slash_command} перезапиÑує запланований Ñ‡Ð°Ñ Ð¾Ñтаннім значеннÑм."
msgid "for this project"
msgstr "Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту"
+msgid "from"
+msgstr "від"
+
+msgid "help"
+msgstr "допомога"
+
msgid "here"
msgstr "тут"
@@ -8660,10 +9752,10 @@ msgstr "імпорт"
msgid "instance completed"
msgid_plural "instances completed"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "завершений інÑтанÑ"
+msgstr[1] "завершені інÑтанÑи"
+msgstr[2] "завершених інÑтанÑів"
+msgstr[3] "завершених інÑтанÑів"
msgid "is invalid because there is downstream lock"
msgstr "неправильний через наÑвніÑÑ‚ÑŒ блокувань на нижчих рівнÑÑ…"
@@ -8677,11 +9769,14 @@ msgstr "не відповідний Ñертифікат X509."
msgid "issue boards"
msgstr "дошки Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼"
+msgid "latest deployment"
+msgstr "оÑтаннє розгортаннÑ"
+
msgid "latest version"
msgstr "оÑÑ‚Ð°Ð½Ð½Ñ Ð²ÐµÑ€ÑÑ–Ñ"
msgid "license management"
-msgstr ""
+msgstr "керувати ліцензіÑми"
msgid "locked by %{path_lock_user_name} %{created_at}"
msgstr "заблоковано %{path_lock_user_name} %{created_at}"
@@ -8715,7 +9810,7 @@ msgid "mrWidget|An error occured while removing your approval."
msgstr "Під Ñ‡Ð°Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°."
msgid "mrWidget|An error occured while retrieving approval data for this merge request."
-msgstr ""
+msgstr "Помилка при отриманні даних про Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиту на злиттÑ."
msgid "mrWidget|An error occurred while submitting your approval."
msgstr "Помилка при обробці вашого затвердженнÑ."
@@ -8766,7 +9861,7 @@ msgid "mrWidget|Failed to load deployment statistics"
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ ÑтатиÑтику розгортаннÑ"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
-msgstr ""
+msgstr "Fast-forward Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð½ÐµÐ¼Ð¾Ð¶Ð»Ð¸Ð²Ðµ. Ð”Ð»Ñ Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиту, Ñпочатку виконайте локальний rebase."
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr "Якщо гілка %{branch} Ñ–Ñнує у вашому локальному репозиторії, то ви можете заÑтоÑувати цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ за допомогою"
@@ -8808,13 +9903,13 @@ msgid "mrWidget|Open in Web IDE"
msgstr "Відкрити у Web IDE"
msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
-msgstr ""
+msgstr "Конвеєр заблоковано. Конвеєр Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиту Ð´Ð»Ñ Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ð¸Ð¼Ð°Ð³Ð°Ñ” ручної операції Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ"
msgid "mrWidget|Plain diff"
msgstr "ПроÑте порівнÑÐ½Ð½Ñ (diff)"
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
-msgstr ""
+msgstr "Можливе автоматичне злиттÑ. ЗвернітьÑÑ Ð´Ð¾ когоÑÑŒ із правами на Ð·Ð°Ð¿Ð¸Ñ Ñƒ цей репозиторій Ð´Ð»Ñ Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ"
msgid "mrWidget|Refresh"
msgstr "Оновити"
@@ -8839,23 +9934,23 @@ msgstr "Запит на злиттÑ"
msgid "mrWidget|Requires 1 more approval"
msgid_plural "mrWidget|Requires %d more approvals"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Ðеобхідне ще 1 ÑхваленнÑ"
+msgstr[1] "Ðеобхідно ще %d ÑхваленнÑ"
+msgstr[2] "Ðеобхідно ще %d Ñхвалень"
+msgstr[3] "Ðеобхідно ще %d Ñхвалень"
msgid "mrWidget|Requires 1 more approval by"
msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Ðеобхідне ще 1 ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´"
+msgstr[1] "Ðеобхідно ще %d ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´"
+msgstr[2] "Ðеобхідно ще %d Ñхвалень від"
+msgstr[3] "Ðеобхідно ще %d Ñхвалень від"
msgid "mrWidget|Resolve conflicts"
msgstr "Вирішити конфлікти"
msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
-msgstr ""
+msgstr "Вирішіть ці конфлікти або звернітьÑÑ Ð´Ð¾ когоÑÑŒ із правом на Ð·Ð°Ð¿Ð¸Ñ Ð´Ð¾ цього репозиторію щоб злити локально"
msgid "mrWidget|Revert"
msgstr "Ðнулювати"
@@ -8876,16 +9971,16 @@ msgid "mrWidget|The changes will be merged into"
msgstr "Зміни будуть злиті в"
msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
-msgstr ""
+msgstr "Конвеєр Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиту на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð·Ð°Ð²ÐµÑ€ÑˆÐ¸Ð²ÑÑ Ð· помилкою. Будь лаÑка перезапуÑÑ‚Ñ–Ñ‚ÑŒ це Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ відправте новий коміт із виправленнÑм помилки"
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
-msgstr ""
+msgstr "HEAD гілки-джерела нещодавно було змінено. Будь лаÑка оновіть Ñторінку Ñ– переглÑньте зміни перед злиттÑм"
msgid "mrWidget|The source branch has been removed"
msgstr "Гілку-джерело видалено"
msgid "mrWidget|The source branch is %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} the target branch"
-msgstr ""
+msgstr "Гілка-джерело на %{commitsBehindLinkStart}%{commitsBehind}%{commitsBehindLinkEnd} цільової гілки"
msgid "mrWidget|The source branch is being removed"
msgstr "Гілка-джерело в процеÑÑ– видаленнÑ"
@@ -8911,6 +10006,9 @@ msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð² процеÑÑ– виконаннÑ"
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "Цей проект заархівований, доÑтуп до запиÑу було відключено"
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr "Ви не можете безпоÑередньо редагувати цей проект. Будь лаÑка, зробіть форк, щоб внеÑти зміни."
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr "Ви можете прийнÑти цей запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ñ€ÑƒÑ‡Ð½Ñƒ за допомогою"
@@ -8929,6 +10027,9 @@ msgstr "в"
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr "буде злито автоматично, коли конвеєр завершитьÑÑ ÑƒÑпішно"
+msgid "n/a"
+msgstr "н/д"
+
msgid "new merge request"
msgstr "Ðовий запит на злиттÑ"
@@ -8940,10 +10041,10 @@ msgstr "або"
msgid "out of %d total test"
msgid_plural "out of %d total tests"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "із %d теÑту"
+msgstr[1] "із %d теÑтів"
+msgstr[2] "із %d теÑтів"
+msgstr[3] "із %d теÑтів"
msgid "parent"
msgid_plural "parents"
@@ -8961,6 +10062,13 @@ msgstr "оÑобиÑтий токен доÑтупу"
msgid "private key does not match certificate."
msgstr "приватний ключ не відповідає Ñертифікату."
+msgid "project"
+msgid_plural "projects"
+msgstr[0] "проект"
+msgstr[1] "проекти"
+msgstr[2] "проектів"
+msgstr[3] "проектів"
+
msgid "remaining"
msgstr "залишилоÑÑŒ"
@@ -8973,6 +10081,13 @@ msgstr "видалити заплановану дату завершеннÑ"
msgid "remove weight"
msgstr "видалити вагу"
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] "відповідь"
+msgstr[1] "відповіді"
+msgstr[2] "відповідей"
+msgstr[3] "відповідей"
+
msgid "source"
msgstr "джерело"
@@ -8988,6 +10103,9 @@ msgstr "цей документ"
msgid "to help your contributors communicate effectively!"
msgstr "щоб допомогти вашим контриб’юторам ефективно ÑпілкуватиÑÑ!"
+msgid "toggle collapse"
+msgstr "згорнути/розгорнути"
+
msgid "username"
msgstr "ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index e93bfd7cfb8..49f27159396 100644
--- a/locale/zh_CN/gitlab.po
+++ b/locale/zh_CN/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Chinese Simplified\n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: zh-CN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:33\n"
+"PO-Revision-Date: 2018-11-19 17:21\n"
msgid " Status"
msgstr "状æ€"
@@ -29,6 +29,13 @@ msgid " improved on %d point"
msgid_plural " improved on %d points"
msgstr[0] " æ高 %d 点"
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] "%d 处新增"
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] "%d 个已更改的文件"
@@ -41,6 +48,10 @@ msgid "%d commit behind"
msgid_plural "%d commits behind"
msgstr[0] "è½åŽ %d 个æ交"
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] "%d 处删除"
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] "%d 导出器"
@@ -77,10 +88,6 @@ msgid "%d unstaged change"
msgid_plural "%d unstaged changes"
msgstr[0] "%d 个未暂存的修改"
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] "%d 个æ¼æ´ž"
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] "为æ高页é¢åŠ è½½é€Ÿåº¦åŠæ€§èƒ½ï¼Œå·²çœç•¥äº† %s 次æ交。"
@@ -88,16 +95,29 @@ msgstr[0] "为æ高页é¢åŠ è½½é€Ÿåº¦åŠæ€§èƒ½ï¼Œå·²çœç•¥äº† %s 次æ交。"
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} 和 %{openOrClose} %{noteable}"
+msgid "%{authorsName}'s discussion"
+msgstr "%{authorsName}的讨论"
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr "ç”± %{commit_author_link} æ交于 %{commit_timeago}"
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr "%{counter_storage} (%{counter_repositories} 个存储库, %{counter_build_artifacts} 个构建产物, %{counter_lfs_objects} 个LFS对象)"
+msgid "%{count} %{alerts}"
+msgstr "%{count}个%{alerts}"
+
+msgid "%{count} more assignees"
+msgstr "åŠå…¶ä»–%{count}å指派人"
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] "%{count} ä½å‚与者"
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] "%{count}个待处ç†çš„评论"
+
msgid "%{filePath} deleted"
msgstr "%{filePath} 已删除"
@@ -107,6 +127,9 @@ msgstr "%{firstLabel} +%{labelCount} 更多"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr "%{group_docs_link_start}群组%{group_docs_link_end} å…许您管ç†ã€å作多个项目。群组的æˆå‘˜å¯ä»¥è®¿é—®ç¾¤ç»„下的所有项目。"
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr "%{issuableType} 将被删除ï¼æ‚¨ç¡®å®šå—?"
+
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} 已开始"
@@ -122,22 +145,12 @@ msgstr "%{nip_domain} å¯ä»¥æ›¿ä»£è‡ªå®šä¹‰åŸŸä½¿ç”¨ã€‚"
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{number_commits_behind} 个è½åŽ %{default_branch} 分支的æ交, %{number_commits_ahead} 个超å‰çš„æ交"
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr "已失败 %{number_of_failures} 次/最多å…许失败失败 %{maximum_failures} 次,GitLab 将继续é‡è¯•ã€‚"
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr "已失败 %{number_of_failures} 次/最多å…许失败 %{maximum_failures} 次,GitLab å°†ä¸å†è‡ªåŠ¨é‡è¯•ã€‚请在问题解决åŽæ‰‹åŠ¨é‡ç½®å­˜å‚¨ç©ºé—´ä¿¡æ¯ã€‚"
-
msgid "%{openOrClose} %{noteable}"
msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
msgstr "å·²å®Œæˆ %{percent}%%"
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] "%{storage_name}:已 %{failed_attempts} 次å°è¯•è®¿é—®å­˜å‚¨å¤±è´¥ï¼š"
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] "%{text}%{files}"
@@ -148,25 +161,15 @@ msgstr "%{text}å¯ç”¨"
msgid "%{title} changes"
msgstr "%{title}更改"
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] "%{type}检测到 %{vulnerabilityCount} 个已修å¤çš„æ¼æ´ž"
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] "%{type}检测到 %{vulnerabilityCount} 个新æ¼æ´ž"
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] "%{type}检测到%{vulnerabilityCount}个æ¼æ´ž"
-
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] "%{type} 检测到æºåˆ†æ”¯çš„ %{vulnerabilityCount} 个æ¼æ´ž"
-
msgid "%{unstaged} unstaged and %{staged} staged changes"
msgstr "%{unstaged}个未暂存的更改åŠ%{staged}个已暂存的更改"
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr "%{usage_ping_link_start}了解更多%{usage_ping_link_end}关于GitLab Inc.的共享信æ¯ã€‚"
+
+msgid "+ %{count} more"
+msgstr "+ 其余 %{count} 项"
+
msgid "+ %{moreCount} more"
msgstr "+ 其余 %{moreCount} 项"
@@ -227,7 +230,7 @@ msgid "1st contribution!"
msgstr "最高贡献"
msgid "2FA enabled"
-msgstr "å¯ç”¨ä¸¤æ­¥éªŒè¯"
+msgstr "å¯ç”¨åŒé‡è®¤è¯"
msgid "403|Please contact your GitLab administrator to get the permission."
msgstr "请è”系您的 GitLab 管ç†å‘˜èŽ·å–访问æƒé™ã€‚"
@@ -257,7 +260,7 @@ msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will ad
msgstr "<code>“johnsmith@example.comâ€ï¼šâ€œ@ johnsmithâ€</code> 将会把“By <a href=\"#\">@johnsmith</a>â€æ·»åŠ åˆ°åŽŸæœ¬ç”±johnsmith@example.com创建的所有议题和评论中。 为ä¿æŠ¤ç”¨æˆ·çš„éšç§ï¼Œç”µå­é‚®ä»¶åœ°å€æˆ–用户å默认将被å±è”½ã€‚如需显示完整邮件地å€ï¼Œå¯ä½¿ç”¨æ­¤é€‰é¡¹ã€‚"
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
-msgstr "<strong>%{changedFilesLength} å–消暂存</strong> å’Œ <strong>%{stagedFilesLength} æš‚å­˜</strong> å˜æ›´å†…容"
+msgstr "<strong>%{changedFilesLength} 未暂存</strong> å’Œ <strong>%{stagedFilesLength} 已暂存</strong> å˜æ›´å†…容"
msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
msgstr "已创建 <strong>%{created_count}</strong> 个, 已关闭 <strong>%{accepted_count}</strong> 个。"
@@ -280,6 +283,15 @@ msgstr "Runner是一个执行任务的进程。您å¯ä»¥æ ¹æ®éœ€è¦é…置任æ„
msgid "A collection of graphs regarding Continuous Integration"
msgstr "æŒç»­é›†æˆæ•°æ®å›¾"
+msgid "A default branch cannot be chosen for an empty project."
+msgstr "无法为空项目选择默认分支。"
+
+msgid "A deleted user"
+msgstr "已删除的用户"
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr "GitLab滥用审查团队将会尽快查看您的报告。"
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr "将在派生(fork)项目中中创建一个新的分支, 并开å¯ä¸€ä¸ªæ–°çš„åˆå¹¶è¯·æ±‚。"
@@ -322,15 +334,12 @@ msgstr "访问令牌"
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr "æ‹’ç»è®¿é—®ï¼è¯·æ ¸æŸ¥æ‚¨æ˜¯å¦æœ‰æƒé™å°†éƒ¨ç½²å¯†é’¥æ·»åŠ åˆ°æ­¤ä»“库。"
+msgid "Access expiration date"
+msgstr "访问到期日期"
+
msgid "Access to '%{classification_label}' not allowed"
msgstr "ä¸å…许访问%{classification_label}"
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr "为方便修å¤æŒ‚载问题,访问故障存储已被暂时ç¦ç”¨ã€‚在问题解决åŽè¯·é‡ç½®å­˜å‚¨è¿è¡ŒçŠ¶å†µä¿¡æ¯ï¼Œä»¥å…许å†æ¬¡è®¿é—®ã€‚"
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
-msgstr "访问您的 runner 令牌,自定义æµæ°´çº¿é…置,以åŠæŸ¥çœ‹æµæ°´çº¿çŠ¶æ€å’Œè¦†ç›–率报告。"
-
msgid "Account"
msgstr "å¸å·"
@@ -358,27 +367,48 @@ msgstr "添加贡献指å—"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr "添加组 Webhooks å’Œ GitLab ä¼ä¸šç‰ˆã€‚"
+msgid "Add Jaeger URL"
+msgstr "增加 Jaeger 地å€"
+
msgid "Add Kubernetes cluster"
msgstr "添加 Kubernetes 集群"
-msgid "Add License"
-msgstr "添加许å¯è¯"
-
msgid "Add Readme"
msgstr "添加自述文件"
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr "在wiki中添加一个主页,其中包å«æœ‰å…³é¡¹ç›®çš„ä¿¡æ¯ï¼ŒGitLab将在此处显示该主页,而ä¸æ˜¯æ­¤æ¶ˆæ¯ã€‚"
+
+msgid "Add a table"
+msgstr "添加表格"
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr "添加包å«åœ¨æ‰€æœ‰ç”µå­é‚®ä»¶ä¸­çš„附加文本。 长度ä¸è¶…过%{character_limit} 字符"
+msgid "Add comment now"
+msgstr "ç«‹å³æ·»åŠ è¯„论"
+
+msgid "Add image comment"
+msgstr "添加图片评论"
+
+msgid "Add license"
+msgstr "添加许å¯è¯"
+
msgid "Add new application"
msgstr "新建应用"
msgid "Add new directory"
msgstr "添加目录"
+msgid "Add projects"
+msgstr "添加项目"
+
msgid "Add reaction"
msgstr "添加回应"
+msgid "Add to review"
+msgstr "添加到评审"
+
msgid "Add todo"
msgstr "添加待办事项"
@@ -388,6 +418,9 @@ msgstr "å‘群组添加用户"
msgid "Add users to group"
msgstr "将用户加入群组"
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr "当å‰GitLab实例ç¦æ­¢æ·»åŠ æ–°åº”用程åºã€‚请è”系您的GitLab管ç†å‘˜ä»¥èŽ·å¾—相关æƒé™ã€‚"
+
msgid "Additional text"
msgstr "附加文本"
@@ -401,10 +434,10 @@ msgid "Admin area"
msgstr "管ç†ä¸­å¿ƒ"
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr "您å³å°†æ°¸ä¹…删除用户 %{username}。该用户的问题ã€åˆå¹¶è¯·æ±‚以åŠé“¾æŽ¥åˆ°è¯¥ç”¨æˆ·çš„群组将被转移到系统的“Ghost用户â€ã€‚为é¿å…æ•°æ®ä¸¢å¤±ï¼Œå»ºè®®æ‚¨ä½¿ç”¨ %{strong_start}ç¦ç”¨ç”¨æˆ·%{strong_end} 功能。一旦您 %{strong_start}删除用户%{strong_end},将无法撤消或æ¢å¤ã€‚"
+msgstr "您å³å°†æ°¸ä¹…删除用户 %{username}。该用户的议题ã€åˆå¹¶è¯·æ±‚以åŠé“¾æŽ¥åˆ°è¯¥ç”¨æˆ·çš„群组将被转移到系统的“Ghost用户â€ã€‚为é¿å…æ•°æ®ä¸¢å¤±ï¼Œå»ºè®®æ‚¨ä½¿ç”¨ %{strong_start}ç¦ç”¨ç”¨æˆ·%{strong_end} 功能。一旦您 %{strong_start}删除用户%{strong_end},将无法撤消或æ¢å¤ã€‚"
msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr "您å³å°†æ°¸ä¹…删除用户 %{username}。此æ“作会删除该用户的所有问题ã€åˆå¹¶è¯·æ±‚以åŠé“¾æŽ¥åˆ°è¯¥ç”¨æˆ·çš„群组。为é¿å…æ•°æ®ä¸¢å¤±ï¼Œå»ºè®®æ‚¨ä½¿ç”¨ %{strong_start}ç¦ç”¨ç”¨æˆ·%{strong_end} 功能。一旦您 %{strong_start}删除用户%{strong_end},将无法撤消或æ¢å¤ã€‚"
+msgstr "您å³å°†æ°¸ä¹…删除用户 %{username}。此æ“作会删除该用户的所有议题ã€åˆå¹¶è¯·æ±‚以åŠé“¾æŽ¥åˆ°è¯¥ç”¨æˆ·çš„群组。为é¿å…æ•°æ®ä¸¢å¤±ï¼Œå»ºè®®æ‚¨ä½¿ç”¨ %{strong_start}ç¦ç”¨ç”¨æˆ·%{strong_end} 功能。一旦您 %{strong_start}删除用户%{strong_end},将无法撤消或æ¢å¤ã€‚"
msgid "AdminArea|Stop all jobs"
msgstr "åœæ­¢æ‰€æœ‰ä½œä¸š"
@@ -419,10 +452,7 @@ msgid "AdminArea|Stopping jobs failed"
msgstr "åœæ­¢ä½œä¸šå¤±è´¥"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
-msgstr "您å³å°†åœæ­¢æ‰€æœ‰ä½œä¸šã€‚所有正在è¿è¡Œçš„都会被åœæ­¢ã€‚"
-
-msgid "AdminHealthPageLink|health page"
-msgstr "è¿è¡ŒçŠ¶å†µé¡µé¢"
+msgstr "您å³å°†åœæ­¢æ‰€æœ‰ä½œä¸šã€‚这会中断并结æŸæ‰€æœ‰æ­£åœ¨è¿è¡Œçš„作业。"
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr "您å³å°†æ°¸ä¹…删除项目 %{projectName},其存储库以åŠæ‰€æœ‰ç›¸å…³èµ„æºï¼ŒåŒ…括问题ã€åˆå¹¶è¯·æ±‚等。一旦确认并点击 %{strong_start}删除项目%{strong_end},将无法撤消或æ¢å¤ã€‚"
@@ -460,12 +490,16 @@ msgstr "请输入 %{projectName} æ¥ç¡®è®¤"
msgid "AdminUsers|To confirm, type %{username}"
msgstr "请输入 %{username} æ¥ç¡®è®¤"
-msgid "Advanced"
-msgstr "高级"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr "高级æƒé™ï¼Œå¤§æ–‡ä»¶å­˜å‚¨å’ŒåŒé‡è®¤è¯è®¾ç½®ã€‚"
msgid "Advanced settings"
msgstr "高级设置"
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] "警报"
+
msgid "All"
msgstr "全部"
@@ -481,6 +515,9 @@ msgstr "所有用户"
msgid "Allow commits from members who can merge to the target branch."
msgstr "具有åˆå¹¶åˆ°ç›®æ ‡åˆ†æ”¯æƒé™çš„æˆå‘˜å…许æ交"
+msgid "Allow projects within this group to use Git LFS"
+msgstr "å…许该群组中的项目使用Git LFS"
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr "å…许所有人访问æµæ°´çº¿å’Œä½œä¸šè¯¦æƒ…,包括输出日志和工件"
@@ -490,6 +527,12 @@ msgstr "å…许在Asciidoc文档中渲染PlantUML图。"
msgid "Allow requests to the local network from hooks and services."
msgstr "å…许æ¥è‡ªé’©å­å’ŒæœåŠ¡çš„对本地网络的请求。"
+msgid "Allow users to request access"
+msgstr "å…许用户请求访问æƒé™"
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr "如果是公开或内部å¯è§æ€§ï¼Œåˆ™å…许用户请求访问æƒé™ã€‚"
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "这里å¯ä»¥æ·»åŠ å’Œç®¡ç† Kubernetes 集群。"
@@ -505,6 +548,9 @@ msgstr "此外,也å¯ä»¥ä½¿ç”¨ %{personal_access_token_link}。创建 Personal
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr "此外,也å¯ä»¥ä½¿ç”¨ %{personal_access_token_link}。创建Personal Access Token时,在范围中需选择 <code>repo</code> ,以便显示å¯ä¾›å¯¼å…¥å…¬å¼€å’Œç§æœ‰çš„仓库列表"
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr "å…许用户跳过强制é…ç½®åŒé‡è®¤è¯çš„时间(以å°æ—¶ä¸ºå•ä½ï¼‰"
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr "在æ交表å•æ—¶å°†è‡ªåŠ¨ç”Ÿæˆ SSH 密钥。有关详细信æ¯, 请å‚阅文档。"
@@ -526,8 +572,8 @@ msgstr "创建分支时å‘生错误。"
msgid "An error occured whilst fetching the job trace."
msgstr "获å–作业日志时å‘生错误。"
-msgid "An error occured whilst fetching the latest pipline."
-msgstr "获å–æµæ°´çº¿æ—¶å‘生错误。"
+msgid "An error occured whilst fetching the latest pipeline."
+msgstr ""
msgid "An error occured whilst loading all the files."
msgstr "加载文件时å‘生错误。"
@@ -550,6 +596,12 @@ msgstr "加载åˆå¹¶è¯·æ±‚æ—¶å‘生错误。"
msgid "An error occured whilst loading the pipelines jobs."
msgstr "加载æµæ°´çº¿ä½œä¸šæ—¶å‘生错误。"
+msgid "An error occurred adding a draft to the discussion."
+msgstr "å‘讨论添加è‰ç¨¿æ—¶å‡ºé”™ã€‚"
+
+msgid "An error occurred adding a new draft."
+msgstr "添加新è‰ç¨¿æ—¶å‡ºé”™ã€‚"
+
msgid "An error occurred previewing the blob"
msgstr "预览 blob 时出错"
@@ -562,6 +614,9 @@ msgstr "更新议题æƒé‡æ—¶å‘生错误"
msgid "An error occurred while adding approver"
msgstr "添加审批者时出错"
+msgid "An error occurred while deleting the comment"
+msgstr "删除评论时å‘生错误"
+
msgid "An error occurred while detecting host keys"
msgstr "检测主机密钥时å‘生错误"
@@ -574,23 +629,26 @@ msgstr "关闭功能çªå‡ºæ˜¾ç¤ºæ—¶å‘生错误。请刷新页é¢å¹¶å†æ¬¡å°è¯•
msgid "An error occurred while fetching markdown preview"
msgstr "èŽ·å– markdown 预览时出错"
+msgid "An error occurred while fetching pending comments"
+msgstr "获å–待处ç†è¯„论时å‘生错误"
+
msgid "An error occurred while fetching sidebar data"
msgstr "获å–侧边æ æ•°æ®æ—¶å‘生错误"
msgid "An error occurred while fetching stages."
-msgstr ""
+msgstr "获å–阶段时å‘生错误"
msgid "An error occurred while fetching the job log."
-msgstr ""
+msgstr "获å–作业日志时å‘生错误。"
msgid "An error occurred while fetching the job."
-msgstr ""
+msgstr "获å–作业详情时å‘生错误"
msgid "An error occurred while fetching the jobs."
-msgstr ""
+msgstr "获å–作业列表时å‘生错误"
msgid "An error occurred while fetching the pipeline."
-msgstr "获å–æµæ°´çº¿æ—¶å‡ºé”™"
+msgstr "获å–æµæ°´çº¿æ—¶å‘生错误"
msgid "An error occurred while getting projects"
msgstr "获å–项目时å‘生错误"
@@ -601,6 +659,9 @@ msgstr "在导入项目时å‘生错误:%{details}"
msgid "An error occurred while initializing path locks"
msgstr "åˆå§‹åŒ–路径é”æ—¶å‘生错误"
+msgid "An error occurred while loading chart data"
+msgstr "加载图表数æ®æ—¶å‘生错误"
+
msgid "An error occurred while loading commit signatures"
msgstr "加载æ交签åæ—¶å‘生错误"
@@ -643,12 +704,18 @@ msgstr "订阅通知时å‘生错误。"
msgid "An error occurred while unsubscribing to notifications."
msgstr "å–消订阅通知时å‘生错误。"
+msgid "An error occurred while updating the comment"
+msgstr "更新评论时å‘生错误"
+
msgid "An error occurred while validating username"
msgstr "验è¯ç”¨æˆ·åæ—¶å‘生错误"
msgid "An error occurred. Please try again."
msgstr "å‘生了错误,请å†è¯•ä¸€æ¬¡ã€‚"
+msgid "Analytics"
+msgstr "分æž"
+
msgid "Anonymous"
msgstr "匿å"
@@ -667,8 +734,8 @@ msgstr "外观"
msgid "Application"
msgstr "应用"
-msgid "Application Id"
-msgstr "应用 ID"
+msgid "Application ID"
+msgstr "应用程åºID"
msgid "Application: %{name}"
msgstr "应用:%{name}"
@@ -685,9 +752,15 @@ msgstr "四月"
msgid "Archived project! Repository and other project resources are read-only"
msgstr "已归档项目ï¼ä»“库和其他项目资æºå‡ä¸ºåªè¯»"
+msgid "Archived projects"
+msgstr "已存档项目"
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "确定è¦åˆ é™¤æ­¤æµæ°´çº¿è®¡åˆ’å—?"
+msgid "Are you sure you want to erase this build?"
+msgstr "您确定è¦åˆ é™¤è¿™ä¸ªæž„建å—?"
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr "确定è¦æ”¾å¼ƒæœªä¿å­˜çš„更改å—?"
@@ -706,6 +779,9 @@ msgstr "确定è¦é‡ç½®æ³¨å†Œä»¤ç‰Œå—?"
msgid "Are you sure you want to reset the health check token?"
msgstr "确定è¦é‡ç½®è¿è¡ŒçŠ¶å†µæ£€æŸ¥ä»¤ç‰Œå—?"
+msgid "Are you sure you want to stop this environment?"
+msgstr "是å¦ç¡®å®šç»ˆæ­¢å½“å‰çŽ¯å¢ƒï¼Ÿ"
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "你确定è¦è§£é” %{path_lock_path} å—?"
@@ -713,7 +789,7 @@ msgid "Are you sure?"
msgstr "确定å—?"
msgid "Artifact ID"
-msgstr ""
+msgstr "作业产物ID"
msgid "Artifacts"
msgstr "产物"
@@ -844,6 +920,9 @@ msgstr "将根æ®é¢„定义的 CI/CD é…置自动构建ã€æµ‹è¯•å’Œéƒ¨ç½²åº”用ç¨
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "想了解更多请访问 %{link_to_documentation}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr "Auto DevOpsæµæ°´çº¿å·²å¯ç”¨ã€‚如果未找到CIé…置文件,将使用该æµæ°´çº¿ã€‚ %{more_information_link}"
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr "如果当å‰é¡¹ç›®%{link_to_auto_devops_settings}, å¯ä»¥è‡ªåŠ¨çš„构建和测试应用。如果已%{link_to_add_kubernetes_cluster},则也å¯ä»¥å®žçŽ°è‡ªåŠ¨éƒ¨ç½²ã€‚"
@@ -880,9 +959,6 @@ msgstr "åŽå°ä½œä¸š"
msgid "Background color"
msgstr "背景颜色"
-msgid "Background jobs"
-msgstr "åŽå°ä½œä¸š"
-
msgid "Badges"
msgstr "徽章"
@@ -923,7 +999,7 @@ msgid "Badges|No image to preview"
msgstr "无图åƒå¯é¢„览"
msgid "Badges|Please fill in a valid URL"
-msgstr ""
+msgstr "请输入正确的 URL"
msgid "Badges|Project Badge"
msgstr "项目徽章"
@@ -959,7 +1035,16 @@ msgid "Badges|Your badges"
msgstr "您的徽章"
msgid "Badges|e.g. %{exampleUrl}"
-msgstr ""
+msgstr "例如 %{exampleUrl}"
+
+msgid "BatchComments|Delete all pending comments"
+msgstr "删除所有待处ç†çš„评论"
+
+msgid "BatchComments|Discard review?"
+msgstr "放弃评审?"
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr "您å³å°†æ”¾å¼ƒæ‚¨çš„评审,该æ“作将删除所有待处ç†çš„评论。请注æ„已删除评论 %{strong_start}ä¸èƒ½%{strong_end} æ¢å¤ã€‚"
msgid "Begin with the selected commit"
msgstr "从选定的æ交开始"
@@ -1233,7 +1318,7 @@ msgid "CI/CD configuration"
msgstr "CI/CD é…ç½®"
msgid "CI/CD for external repo"
-msgstr "为外部仓库设置的æŒç»­é›†æˆ/æŒç»­éƒ¨ç½²"
+msgstr "为外部仓库设置的CI/CD"
msgid "CI/CD settings"
msgstr "CI/CD 设置"
@@ -1250,8 +1335,11 @@ msgstr "自动部署到预å‘布环境,手动部署到生产环境"
msgid "CICD|Continuous deployment to production"
msgstr "æŒç»­éƒ¨ç½²åˆ°ç”Ÿäº§çŽ¯å¢ƒ"
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr "使用已定时的增é‡éƒ¨ç½²è¿›è¡ŒæŒç»­éƒ¨ç½²åˆ°ç”Ÿäº§çŽ¯å¢ƒ"
+
msgid "CICD|Default to Auto DevOps pipeline"
-msgstr ""
+msgstr "默认为Auto DevOpsæµæ°´çº¿"
msgid "CICD|Deployment strategy"
msgstr "部署策略"
@@ -1269,20 +1357,17 @@ msgid "CICD|Learn more about Auto DevOps"
msgstr "了解更多Auto DevOps的相关信æ¯"
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
-msgstr ""
+msgstr "在未找到备用CIé…置文件时使用Auto DevOpsæµæ°´çº¿ã€‚"
msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
msgstr "如需使用自动化应用程åºè¯„审和自动部署,请指定域å。"
msgid "CICD|instance enabled"
-msgstr ""
+msgstr "å·²å¯ç”¨çš„实例"
msgid "Callback URL"
msgstr "回调 URL"
-msgid "Callback url"
-msgstr "回调 URL"
-
msgid "Can't find HEAD commit for this branch"
msgstr "无法找到此分支的 HEAD æ交"
@@ -1337,8 +1422,8 @@ msgstr "统计图"
msgid "Chat"
msgstr "å³æ—¶é€šè®¯"
-msgid "Check interval"
-msgstr "检查间隔"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr "查看%{docs_link_start}文档%{docs_link_end}。"
msgid "Checking %{text} availability…"
msgstr "正在检查%{text}çš„å¯ç”¨æ€§..."
@@ -1364,6 +1449,12 @@ msgstr "选择文件 ……"
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr "选择分支/标签(例如%{master})或输入æ交(例如%{sha})以查看更改内容或创建åˆå¹¶è¯·æ±‚。"
+msgid "Choose a template..."
+msgstr "选择模æ¿..."
+
+msgid "Choose a type..."
+msgstr "选择类型..."
+
msgid "Choose any color."
msgstr "选择任何颜色。"
@@ -1394,6 +1485,9 @@ msgstr "å·²å–消"
msgid "CiStatusLabel|created"
msgstr "已创建"
+msgid "CiStatusLabel|delayed"
+msgstr "已延迟"
+
msgid "CiStatusLabel|failed"
msgstr "已失败"
@@ -1412,6 +1506,9 @@ msgstr "等待中"
msgid "CiStatusLabel|skipped"
msgstr "已跳过"
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr "等待已延迟的作业"
+
msgid "CiStatusLabel|waiting for manual action"
msgstr "等待手动æ“作"
@@ -1424,6 +1521,9 @@ msgstr "å·²å–消"
msgid "CiStatusText|created"
msgstr "已创建"
+msgid "CiStatusText|delayed"
+msgstr "已延迟"
+
msgid "CiStatusText|failed"
msgstr "已失败"
@@ -1478,12 +1578,12 @@ msgstr "开关ä¿æŠ¤çŠ¶æ€"
msgid "CiVariable|Validation failed"
msgstr "验è¯å¤±è´¥"
-msgid "CircuitBreakerApiLink|circuitbreaker api"
-msgstr "断路器 API"
-
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "ä¸å¯ç”¨: %{reason}"
+msgid "Clear search"
+msgstr "清除æœç´¢"
+
msgid "Clear search input"
msgstr "清除æœç´¢è¾“å…¥"
@@ -1526,6 +1626,9 @@ msgstr "克隆仓库"
msgid "Close"
msgstr "关闭"
+msgid "Close epic"
+msgstr "关闭å²è¯—故事"
+
msgid "Closed"
msgstr "已关闭"
@@ -1536,7 +1639,10 @@ msgid "ClusterIntegration|%{appList} was successfully installed on your Kubernet
msgstr "%{appList} å·²æˆåŠŸå®‰è£…到Kubernetes集群上"
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
-msgstr ""
+msgstr "%{boldNotice} 这将添加一些é¢å¤–的资æºï¼Œå¦‚è´Ÿè½½å‡è¡¡å™¨ï¼Œè¿™å¯èƒ½ä¼šäº§ç”Ÿé¢å¤–çš„æˆæœ¬ï¼Œå…·ä½“å–决于您安装Kubernetes集群的托管æœåŠ¡æ供商。如果您使用的是Google Kubernetes Engine,则å¯ä»¥ %{pricingLink}。"
+
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr "Knative构建扩展了Kubernetes,并利用现有的Kubernetes原语为您æ供从æºä»£ç æž„建è¿è¡ŒäºŽç¾¤é›†ä¸Šå®¹å™¨çš„能力。例如,您å¯ä»¥ç¼–写一个构建,该构建使用 Kubernetes原生资æºä»Žå­˜å‚¨åº“中获å–æºä»£ç ï¼Œå°†å…¶æž„建到容器中,然åŽè¿è¡Œè¯¥é•œåƒã€‚"
msgid "ClusterIntegration|API URL"
msgstr "API地å€"
@@ -1544,11 +1650,20 @@ msgstr "API地å€"
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr "添加 Kubernetes 集群"
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr "添加Kubernetes集群集æˆ"
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr "å°†Kubernetes集群添加到群组åŽï¼Œç¾¤ç»„中的所有项目都将共享该集群。您å¯ä»¥åœ¨åŒä¸€é›†ç¾¤ä¸Šä½¿ç”¨è¯„审应用ã€éƒ¨ç½²åº”用以åŠè¿è¡Œç¾¤é›†ä¸­æ‰€æœ‰é¡¹ç›®çš„æµæ°´çº¿ã€‚"
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr "添加集æˆåˆ°ç¾¤ç»„åŽï¼Œå¯ä»¥åœ¨ç¾¤ç»„中的所有项目中共享集群。"
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Kubernetes集群集æˆçš„高级选项"
msgid "ClusterIntegration|After installing Ingress, you will need to point your wildcard DNS at the generated external IP address in order to view your app after it is deployed. %{ingressHelpLink}"
-msgstr ""
+msgstr "安装IngressåŽï¼Œæ‚¨éœ€è¦åœ¨ç”Ÿæˆçš„外部IP地å€ä¸ŠæŒ‡å‘DNS,以便在部署åŽæŸ¥çœ‹æ‚¨çš„应用程åºã€‚ %{ingressHelpLink}"
msgid "ClusterIntegration|An error occured while trying to fetch project zones: %{error}"
msgstr "å°è¯•èŽ·å–项目地域时å‘生错误:%{error}"
@@ -1557,10 +1672,10 @@ msgid "ClusterIntegration|An error occured while trying to fetch your projects:
msgstr "å°è¯•èŽ·å–您的项目时å‘生错误:%{error}"
msgid "ClusterIntegration|An error occured while trying to fetch zone machine types: %{error}"
-msgstr ""
+msgstr "å°è¯•èŽ·å–设备类型时å‘生错误:%{error}"
msgid "ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later."
-msgstr ""
+msgstr "å°è¯•è”ç³»Google Cloud APIæ—¶å‘生错误。请ç¨åŽå†è¯•ã€‚"
msgid "ClusterIntegration|Applications"
msgstr "应用程åº"
@@ -1574,11 +1689,11 @@ msgstr "CAè¯ä¹¦"
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "è¯ä¹¦æŽˆæƒåŒ…(PEMæ ¼å¼)"
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
-msgstr "请选择使用此Kubernetes集群的环境。"
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr "选择è¦åœ¨ Kubernetes 群集上安装的应用程åºã€‚安装以下任何一个应用å‰éœ€è¦å…ˆå®‰è£…Helm Tiller。"
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
-msgstr "控制Kubernetes集群与GitLab集æˆæ–¹å¼"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr "请选择使用此Kubernetes群集的环境。"
msgid "ClusterIntegration|Copy API URL"
msgstr "å¤åˆ¶API地å€"
@@ -1604,6 +1719,12 @@ msgstr "创建Kubernetes集群"
msgid "ClusterIntegration|Did you know?"
msgstr "你是å¦äº†è§£ï¼Ÿ"
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr "å¯ç”¨æˆ–ç¦ç”¨GitLab与Kubernetes群集的连接。"
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr "如果使用基于角色的访问控制(RBAC),请å¯ç”¨æ­¤è®¾ç½®ã€‚"
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr "输入Kubernetes集群的详细信æ¯"
@@ -1629,7 +1750,7 @@ msgid "ClusterIntegration|GitLab Runner"
msgstr "GitLab Runner"
msgid "ClusterIntegration|GitLab Runner connects to this project's repository and executes CI/CD jobs, pushing results back and deploying, applications to production."
-msgstr ""
+msgstr "GitLab Runner连接到该项目的存储库并执行CI / CD作业,将结果推回,并部署应用程åºåˆ°ç”Ÿäº§çŽ¯å¢ƒã€‚"
msgid "ClusterIntegration|Google Cloud Platform project"
msgstr "Google 云平å°é¡¹ç›®"
@@ -1640,11 +1761,14 @@ msgstr "Google Kubernetes Engine"
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr "Google Kubernetes Engine 项目"
+msgid "ClusterIntegration|Group cluster"
+msgstr "群组级集群"
+
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
msgid "ClusterIntegration|Helm streamlines installing and managing Kubernetes applications. Tiller runs inside of your Kubernetes Cluster, and manages releases of your charts."
-msgstr ""
+msgstr "Helm简化了Kubernetes应用程åºçš„安装和管ç†ã€‚ Tiller在您的Kubernetes集群内部è¿è¡Œï¼Œå¹¶ç®¡ç†å›¾è¡¨çš„å‘布。"
msgid "ClusterIntegration|Hide"
msgstr "éšè—"
@@ -1662,7 +1786,7 @@ msgid "ClusterIntegration|Ingress IP Address"
msgstr "Ingress IP地å€"
msgid "ClusterIntegration|Ingress gives you a way to route requests to services based on the request host or path, centralizing a number of services into a single entrypoint."
-msgstr ""
+msgstr "Ingress为您æ供了一ç§åŸºäºŽè¯·æ±‚主机或路径将请求路由到æœåŠ¡çš„方法,将多个æœåŠ¡é›†ä¸­åˆ°ä¸€ä¸ªå…¥å£ç‚¹ã€‚"
msgid "ClusterIntegration|Install"
msgstr "安装"
@@ -1670,9 +1794,6 @@ msgstr "安装"
msgid "ClusterIntegration|Install Prometheus"
msgstr "安装Prometheus"
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr "已安装"
@@ -1692,7 +1813,13 @@ msgid "ClusterIntegration|JupyterHub"
msgstr "JupyterHub"
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
-msgstr ""
+msgstr "JupyterHub是一个多用户Hub,它生æˆï¼Œç®¡ç†å’Œä»£ç†å•ç”¨æˆ· Jupyter笔记本æœåŠ¡å™¨çš„多个实例。 JupyterHubå¯ç”¨äºŽä¸ºä¸€ç±»å­¦ç”Ÿï¼Œä¼ä¸šæ•°æ®ç§‘å­¦å°ç»„或科研å°ç»„æ供笔记本电脑。"
+
+msgid "ClusterIntegration|Knative"
+msgstr "Knative"
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr "Knative域å:"
msgid "ClusterIntegration|Kubernetes cluster"
msgstr "Kubernetes 集群"
@@ -1703,18 +1830,6 @@ msgstr "Kubernetes集群详细信æ¯"
msgid "ClusterIntegration|Kubernetes cluster health"
msgstr "Kubernetes集群è¿è¡ŒçŠ¶å†µ"
-msgid "ClusterIntegration|Kubernetes cluster integration"
-msgstr "Kubernetes集群集æˆ"
-
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
-msgstr "此项目已ç¦ç”¨ Kubernetes 集群集æˆã€‚"
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
-msgstr "此项目已å¯ç”¨ Kubernetes 集群集æˆã€‚"
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
-msgstr "此项目已å¯ç”¨ Kubernetes 集群集æˆã€‚ç¦ç”¨æ­¤é›†æˆä¸ä¼šå½±å“ Kubernetes 集群本身, åªä¼šæš‚时关闭 GitLab 与其连接。"
-
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
msgstr "正在Google Kubernetes Engine上创建Kubernetes集群..."
@@ -1724,8 +1839,8 @@ msgstr "Kubernetes 集群å称"
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr "Kubernetes集群已在Google Kubernetes Engine上æˆåŠŸåˆ›å»ºã€‚刷新页é¢ä»¥æŸ¥çœ‹Kubernetes集群的详细信æ¯"
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
-msgstr "通过Kubernetes 集群集æˆï¼Œå¯ä»¥æ–¹ä¾¿åœ°ä½¿ç”¨å®¡é˜…应用ã€éƒ¨ç½²åº”用程åºã€è¿è¡Œæµæ°´çº¿ç­‰ç­‰ã€‚%{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr "通过Kubernetes群集集æˆï¼Œå¯ä»¥è½»æ¾åœ°ä½¿ç”¨è¯„审应用ã€éƒ¨ç½²åº”用ã€è¿è¡Œæµæ°´çº¿ç­‰ç­‰ã€‚"
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
msgstr "Kubernetes 集群å¯ç”¨äºŽéƒ¨ç½²åº”用程åºå’Œæ供此项目的审阅应用"
@@ -1733,17 +1848,14 @@ msgstr "Kubernetes 集群å¯ç”¨äºŽéƒ¨ç½²åº”用程åºå’Œæ供此项目的审阅å
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr "进一步了解 %{help_link_start_machine_type}实例类型%{help_link_end} å’Œ %{help_link_start_pricing}定价信æ¯%{help_link_end}。"
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr "进一步了解 %{help_link_start}Kubernetes%{help_link_end}。"
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr "进一步了解 %{help_link_start}地域%{help_link_end}。"
-msgid "ClusterIntegration|Learn more about environments"
-msgstr "进一步了解有关环境的信æ¯"
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr "了解更多的Kubernetesä¿¡æ¯"
-msgid "ClusterIntegration|Learn more about security configuration"
-msgstr "进一步了解安全相关é…ç½®"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr "了解更多的群组级Kubernetes集群信æ¯"
msgid "ClusterIntegration|Machine type"
msgstr "机器类型"
@@ -1760,9 +1872,6 @@ msgstr "通过访问 %{link_gke} ç®¡ç† Kubernetes 集群"
msgid "ClusterIntegration|More information"
msgstr "更多信æ¯"
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr "在GitLabä¼ä¸šé«˜çº§å’Œæ——舰版中å¯ä»¥ä½¿ç”¨å¤šä¸ªKubernetes集群"
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr "未找到您æœç´¢çš„实例类型"
@@ -1788,7 +1897,10 @@ msgid "ClusterIntegration|Please make sure that your Google account meets the fo
msgstr "请确ä¿æ‚¨çš„ Google å¸æˆ·ç¬¦åˆä»¥ä¸‹è¦æ±‚:"
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
-msgstr ""
+msgstr "å°†DNS指å‘生æˆçš„这个IP地å€ï¼Œä»¥ä¾¿åœ¨éƒ¨ç½²åŽè®¿é—®æ‚¨çš„应用程åºã€‚"
+
+msgid "ClusterIntegration|Project cluster"
+msgstr "项目级集群"
msgid "ClusterIntegration|Project namespace"
msgstr "项目命å空间"
@@ -1800,7 +1912,10 @@ msgid "ClusterIntegration|Prometheus"
msgstr "Prometheus"
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
-msgstr ""
+msgstr "Prometheus是一个开æºç›‘控系统,其中 %{gitlabIntegrationLink} 用于监控已部署的应用程åºã€‚"
+
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr "å¯ç”¨RBAC的群集"
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr "请阅读关于Kubernetes集群集æˆçš„%{link_to_help_page}。"
@@ -1815,7 +1930,7 @@ msgid "ClusterIntegration|Remove this Kubernetes cluster's configuration from th
msgstr "从当å‰é¡¹ç›®ä¸­åˆ é™¤æ­¤Kubernetes集群的é…置。该æ“作并ä¸ä¼šåˆ é™¤å®žé™…Kubernetes集群。"
msgid "ClusterIntegration|Replace this with your own hostname if you want. If you do so, point hostname to Ingress IP Address from above."
-msgstr ""
+msgstr "如果需è¦ï¼Œå¯å°†å…¶æ›¿æ¢ä¸ºæ‚¨è‡ªå·±çš„主机å。如果这样åšï¼Œè¯·å°†ä¸»æœºå从上级指å‘Ingress IP地å€ã€‚"
msgid "ClusterIntegration|Request to begin installing failed"
msgstr "请求安装失败"
@@ -1832,9 +1947,6 @@ msgstr "æœç´¢é¡¹ç›®"
msgid "ClusterIntegration|Search zones"
msgstr "æœç´¢åœ°åŸŸ"
-msgid "ClusterIntegration|Security"
-msgstr "安全"
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "查看并编辑Kubernetes集群的详细信æ¯"
@@ -1872,16 +1984,13 @@ msgid "ClusterIntegration|Something went wrong while installing %{title}"
msgstr "安装 %{title} æ—¶å‘生故障"
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
-msgstr ""
-
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr "默认集群é…ç½®æ供了æˆåŠŸæž„建和部署容器化应用所需的大é‡ç›¸å…³åŠŸèƒ½ã€‚"
+msgstr "IP地å€æ­£åœ¨åˆ†é…中。如果花费时间过长,请检查您的Kubernetes集群或谷歌Kubernetes引擎(GKE) 上的é…é¢ã€‚"
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr "该å¸æˆ·éœ€å…·å¤‡åœ¨ä¸‹é¢æŒ‡å®šçš„%{link_to_container_project}中创建 Kubernetes集群的æƒé™"
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
-msgstr "开关Kubernetes 集群"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr "此选项å…许您在å¯ç”¨RBAC的群集上安装应用程åºã€‚"
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "开关Kubernetes 集群"
@@ -1898,6 +2007,9 @@ msgstr "无法验è¯æ‚¨åœ¨ GCP 上的æŸä¸ªé¡¹ç›®æ˜¯å¦å¯ç”¨äº†è®¡è´¹ã€‚请é‡è
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "使用与此项目关è”çš„Kubernetes集群,å¯ä»¥æ–¹ä¾¿åœ°ä½¿ç”¨å®¡é˜…应用,部署应用程åºï¼Œè¿è¡Œæµæ°´çº¿ç­‰ç­‰ã€‚"
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr "在安装以下应用程åºä¹‹å‰ï¼Œå¿…须先安装Helm Tiller"
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "您的å¸æˆ·å¿…须拥有%{link_to_kubernetes_engine}"
@@ -1916,9 +2028,6 @@ msgstr "文档"
msgid "ClusterIntegration|help page"
msgstr "帮助页é¢"
-msgid "ClusterIntegration|installing applications"
-msgstr "安装应用程åº"
-
msgid "ClusterIntegration|meets the requirements"
msgstr "符åˆè¦æ±‚"
@@ -1928,21 +2037,30 @@ msgstr "正确é…ç½®"
msgid "ClusterIntegration|sign up"
msgstr "注册"
+msgid "Code owners"
+msgstr "代ç æ‰€æœ‰è€…"
+
msgid "Cohorts"
-msgstr "留存表"
+msgstr "世代表"
msgid "Collapse"
-msgstr "收起"
+msgstr "折å "
msgid "Collapse sidebar"
msgstr "折å ä¾§è¾¹æ "
+msgid "Comment"
+msgstr "评论"
+
msgid "Comment & resolve discussion"
msgstr "评论并解决讨论"
msgid "Comment & unresolve discussion"
msgstr "评论并将讨论å˜ä¸ºæœªå†³"
+msgid "Comment form position"
+msgstr "评论框ä½ç½®"
+
msgid "Comments"
msgstr "评论"
@@ -1975,6 +2093,9 @@ msgstr "æ交"
msgid "CommitMessage|Add %{file_name}"
msgstr "添加 %{file_name}"
+msgid "CommitWidget|authored"
+msgstr "作者"
+
msgid "Commits"
msgstr "æ交"
@@ -2047,8 +2168,8 @@ msgstr "ä¿å¯†æ€§"
msgid "Configure Gitaly timeouts."
msgstr "é…ç½®Gitaly超时时间。"
-msgid "Configure Sidekiq job throttling."
-msgstr "é…ç½® Sidekiq 作业é™åˆ¶ã€‚"
+msgid "Configure Tracing"
+msgstr "é…置跟踪"
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr "在仓库上é…置自动git检查和仓库整ç†ã€‚"
@@ -2056,14 +2177,14 @@ msgstr "在仓库上é…置自动git检查和仓库整ç†ã€‚"
msgid "Configure limits for web and API requests."
msgstr "é…ç½® web å’Œ API 请求é™åˆ¶ã€‚"
-msgid "Configure push and pull mirrors."
-msgstr "é…ç½®PushåŠPullé•œåƒ"
+msgid "Configure push mirrors."
+msgstr "设置推é€çš„é•œåƒã€‚"
-msgid "Configure storage path and circuit breaker settings."
-msgstr "é…置存储路径åŠæ–­è·¯å™¨è®¾ç½®ã€‚"
+msgid "Configure storage path settings."
+msgstr "é…置存储路径设置。"
msgid "Configure the %{link} integration."
-msgstr ""
+msgstr "é…ç½® %{link} 集æˆã€‚"
msgid "Configure the way a user creates a new account."
msgstr "é…置用户创建新å¸æˆ·çš„æ–¹å¼ã€‚"
@@ -2149,6 +2270,9 @@ msgstr "贡献"
msgid "Contribution guide"
msgstr "贡献指å—"
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr "<strong>%{calendar_date}</strong>的贡献"
+
msgid "Contributions per group member"
msgstr "æ¯å群组æˆå‘˜çš„贡献"
@@ -2182,6 +2306,18 @@ msgstr "控制此Geo节点的校验æ“作的最大并å‘性"
msgid "ConvDev Index"
msgstr "ConvDev指数"
+msgid "Copy %{protocol} clone URL"
+msgstr "å¤åˆ¶ %{protocol} 克隆URL"
+
+msgid "Copy HTTPS clone URL"
+msgstr "å¤åˆ¶HTTPS克隆URL"
+
+msgid "Copy ID to clipboard"
+msgstr "å¤åˆ¶ID到剪贴æ¿"
+
+msgid "Copy SSH clone URL"
+msgstr "å¤åˆ¶SSH克隆URL"
+
msgid "Copy SSH public key to clipboard"
msgstr "å°† SSH 公钥å¤åˆ¶åˆ°å‰ªè´´æ¿"
@@ -2203,15 +2339,27 @@ msgstr "将文件路径å¤åˆ¶åˆ°å‰ªè´´æ¿"
msgid "Copy incoming email address to clipboard"
msgstr "将接收邮件地å€å¤åˆ¶åˆ°å‰ªè´´æ¿"
+msgid "Copy link"
+msgstr "å¤åˆ¶é“¾æŽ¥"
+
+msgid "Copy name to clipboard"
+msgstr "å¤åˆ¶å称到剪贴æ¿"
+
msgid "Copy reference to clipboard"
msgstr "将索引å¤åˆ¶åˆ°å‰ªè´´æ¿"
+msgid "Copy secret to clipboard"
+msgstr "å¤åˆ¶å¯†ç åˆ°å‰ªè´´æ¿"
+
msgid "Copy to clipboard"
msgstr "å¤åˆ¶åˆ°å‰ªè´´æ¿"
msgid "Copy token to clipboard"
msgstr "将令牌å¤åˆ¶åˆ°å‰ªè´´æ¿"
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr "无法获å–æµæ°´çº¿çŠ¶æ€ã€‚有关故障排除步骤,请å‚阅 %{linkStart}文档%{linkEnd}。"
+
msgid "Create"
msgstr "创建"
@@ -2287,8 +2435,8 @@ msgstr "创建..."
msgid "Create project label"
msgstr "创建项目标记"
-msgid "CreateNewFork|Fork"
-msgstr "派生"
+msgid "Create your first page"
+msgstr "创建您的第一个页é¢"
msgid "CreateTag|Tag"
msgstr "标签"
@@ -2338,6 +2486,9 @@ msgstr "自定义"
msgid "Custom CI config path"
msgstr "自定义CIé…置路径"
+msgid "Custom hostname (for private commit emails)"
+msgstr "自定义主机å(用于ç§æœ‰æ交电å­é‚®ä»¶ï¼‰"
+
msgid "Custom notification events"
msgstr "自定义通知事件"
@@ -2356,6 +2507,9 @@ msgstr "自定义如何将FogBugz电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·å导入GitLab。ä¸
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr "自定义如何将Google Code电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·å导入GitLab。下一步将选择è¦å¯¼å…¥çš„项目。"
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr "自定义æµæ°´çº¿é…置,查看æµæ°´çº¿çŠ¶æ€å’Œè¦†ç›–率报告。"
+
msgid "Cycle Analytics"
msgstr "周期分æž"
@@ -2407,6 +2561,9 @@ msgstr "å二月"
msgid "Decline and sign out"
msgstr "æ‹’ç»å¹¶é€€å‡º"
+msgid "Default Branch"
+msgstr "默认分支"
+
msgid "Default classification label"
msgstr "默认分类标记"
@@ -2419,6 +2576,21 @@ msgstr "默认:将FogBugzå¸æˆ·ID映射为全å"
msgid "Define a custom pattern with cron syntax"
msgstr "使用 Cron 语法定义自定义模å¼"
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr "您确定è¦ç«‹å³è¿è¡Œ %{jobName} å—?å¦åˆ™çš„è¯ï¼Œè¯¥ä½œä¸šå°†åœ¨è®¡æ—¶ç»“æŸåŽè‡ªåŠ¨è¿è¡Œã€‚"
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr "您确定è¦ç«‹å³è¿è¡Œ %{job_name} å—?该作业将在计时结æŸåŽè‡ªåŠ¨è¿è¡Œã€‚"
+
+msgid "DelayedJobs|Start now"
+msgstr "ç«‹å³å¼€å§‹"
+
+msgid "DelayedJobs|Unschedule"
+msgstr "å–消计划"
+
+msgid "DelayedJobs|delayed"
+msgstr "已延时"
+
msgid "Delete"
msgstr "删除"
@@ -2428,6 +2600,9 @@ msgstr "删除文件包"
msgid "Delete Snippet"
msgstr "删除代ç ç‰‡æ®µ"
+msgid "Delete comment"
+msgstr "删除评论"
+
msgid "Delete list"
msgstr "删除列表"
@@ -2564,6 +2739,12 @@ msgstr "新部署令牌"
msgid "DeployTokens|Your new project deploy token has been created."
msgstr "新项目部署令牌已创建。"
+msgid "Deployed to"
+msgstr "已部署到"
+
+msgid "Deploying to"
+msgstr "正在部署到"
+
msgid "Deprioritize label"
msgstr "å–消优先标记"
@@ -2588,6 +2769,12 @@ msgstr "详情"
msgid "Detect host keys"
msgstr "检测主机密钥"
+msgid "Diff content limits"
+msgstr "差异内容é™åˆ¶"
+
+msgid "Diff limits"
+msgstr "差异é™åˆ¶"
+
msgid "Diffs|No file name available"
msgstr "没有å¯ç”¨çš„文件å"
@@ -2609,12 +2796,27 @@ msgstr "在此项目中ç¦ç”¨"
msgid "Disable group Runners"
msgstr "ç¦ç”¨ç¾¤ç»„Runner"
+msgid "Discard"
+msgstr "放弃"
+
+msgid "Discard all changes"
+msgstr "放弃所有更改"
+
+msgid "Discard all unstaged changes?"
+msgstr "放弃所有未暂存的修改?"
+
msgid "Discard changes"
msgstr "放弃更改"
+msgid "Discard changes to %{path}?"
+msgstr "放弃对 %{path} 的更改å—?"
+
msgid "Discard draft"
msgstr "å–消"
+msgid "Discard review"
+msgstr "放弃评审"
+
msgid "Discover GitLab Geo."
msgstr "å‘现GitLab Geo。"
@@ -2630,6 +2832,9 @@ msgstr "关闭循环分æžä»‹ç»æ¡†"
msgid "Dismiss Merge Request promotion"
msgstr "关闭åˆå¹¶è¯·æ±‚推广"
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr "您想自定义如何将Google Code电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·å导入GitLabå—?"
@@ -2711,8 +2916,8 @@ msgstr "编辑 %{user_name} 的身份信æ¯"
msgid "Elasticsearch"
msgstr "Elasticsearch"
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
-msgstr "Elasticsearch集æˆåŠElasticsearch AWS IAM。"
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
msgid "Email"
msgstr "电å­é‚®ä»¶"
@@ -2756,14 +2961,11 @@ msgstr "在此项目中å¯ç”¨"
msgid "Enable group Runners"
msgstr "å¯ç”¨ç¾¤ç»„Runner"
-msgid "Enable or disable certain group features and choose access levels."
-msgstr "å¯ç”¨æˆ–ç¦ç”¨éƒ¨åˆ†ç¾¤ç»„功能并选择访问等级。"
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "å¯ç”¨æˆ–ç¦ç”¨åŒ¿å化数æ®æ”¶é›†."
msgid "Enable or disable version check and usage ping."
-msgstr "å¯ç”¨æˆ–ç¦ç”¨ç‰ˆæœ¬æ£€æŸ¥åŠä½¿ç”¨ping。"
+msgstr "å¯ç”¨æˆ–ç¦ç”¨ç‰ˆæœ¬æ£€æŸ¥åŠä½¿ç”¨æƒ…况检测(usage ping)。"
msgid "Enable reCAPTCHA or Akismet and set IP limits."
msgstr "å¯ç”¨reCAPTCHA或Akismet并设置IPé™åˆ¶ã€‚"
@@ -2771,6 +2973,12 @@ msgstr "å¯ç”¨reCAPTCHA或Akismet并设置IPé™åˆ¶ã€‚"
msgid "Enable the Performance Bar for a given group."
msgstr "对指定群组å¯ç”¨æ€§èƒ½æ ã€‚"
+msgid "Enable usage ping"
+msgstr "å¯ç”¨ä½¿ç”¨æƒ…况检测(usage ping)"
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr "å¯ç”¨ä½¿ç”¨æƒ…况检测(usage ping)以从功能角度总体上了解您如何使用GitLab。"
+
msgid "Enabled"
msgstr "å·²å¯ç”¨"
@@ -2778,7 +2986,7 @@ msgid "Ends at (UTC)"
msgstr "结æŸäºŽ(UTC)"
msgid "Enter in your Bitbucket Server URL and personal access token below"
-msgstr ""
+msgstr "输入您的BitbucketæœåŠ¡å™¨URL和个人访问令牌"
msgid "Enter the issue description"
msgstr "输入议题æè¿°"
@@ -2841,7 +3049,7 @@ msgid "Environments|No pod name has been specified"
msgstr "未指定podå称"
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
-msgstr ""
+msgstr "注æ„:继续æ“作将终止当å‰çŽ¯å¢ƒï¼ç”±äºŽæœªåœ¨%{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd}文件中定义“终止环境æ“作â€ï¼Œå› æ­¤%{emphasisStart}ä¸ä¼š%{emphasisEnd}å½±å“å·²ç»å­˜åœ¨çš„部署。"
msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
msgstr "注æ„:继续æ“作将终止当å‰çŽ¯å¢ƒï¼ç”±äºŽæœªåœ¨%{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end}文件中定义“终止环境æ“作â€ï¼Œå› æ­¤%{emphasis_start}ä¸ä¼š%{emphasis_end}å½±å“å·²ç»å­˜åœ¨çš„部署。"
@@ -2873,11 +3081,11 @@ msgstr "终止环境"
msgid "Environments|Updated"
msgstr "已更新"
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr "当å‰æœªè®¾ç½®çŽ¯å¢ƒ"
msgid "Environments|protected"
-msgstr ""
+msgstr "å—ä¿æŠ¤çš„"
msgid "Epic"
msgstr "å²è¯—故事"
@@ -2895,7 +3103,7 @@ msgid "Epics let you manage your portfolio of projects more efficiently and with
msgstr "利用å²è¯—故事(Epics),产å“线管ç†ä¼šå˜å¾—æ›´è½»æ¾ä¸”更高效"
msgid "Epics|An error occurred while saving %{epicDateType} date"
-msgstr ""
+msgstr "ä¿å­˜ %{epicDateType} 日期时å‘生错误"
msgid "Epics|How can I solve this?"
msgstr "我该如何解决该问题?"
@@ -2904,13 +3112,13 @@ msgid "Epics|More information"
msgstr "更多信æ¯"
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
-msgstr ""
+msgstr "这些日期会影å“å²è¯—故事在路线图中的显示方å¼ã€‚里程碑日期æ¥è‡ªäºŽå²è¯—故事中的议题所属的里程碑。您还å¯ä»¥è®¾ç½®å›ºå®šæ—¥æœŸæˆ–完全删除它们。"
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
-msgstr ""
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
+msgstr "如需根æ®é‡Œç¨‹ç¢‘æ¥å®‰æŽ’å²è¯—故事的 %{epicDateType} 日期,请为å²è¯—故事中的任一议题指定带有 %{epicDateType} 日期的里程碑。"
-msgid "Epics|finish"
-msgstr "完æˆ"
+msgid "Epics|due"
+msgstr "到期"
msgid "Epics|start"
msgstr "开始"
@@ -2937,7 +3145,7 @@ msgid "Error fetching refs"
msgstr "获å–refs时出错。"
msgid "Error fetching usage ping data."
-msgstr "获å–使用情况(usage ping) æ•°æ®æ—¶å‡ºé”™ã€‚"
+msgstr "获å–使用情况(usage ping)æ•°æ®æ—¶å‡ºé”™ã€‚"
msgid "Error loading branch data. Please try again."
msgstr "加载分支数æ®å¤±è´¥ï¼Œè¯·é‡è¯•ã€‚"
@@ -3020,6 +3228,12 @@ msgstr "展开全部"
msgid "Expand sidebar"
msgstr "展开侧边æ "
+msgid "Expiration date"
+msgstr "到期时间"
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr "请解释此问题。如适用,å¯æ供相关议题或评论的链接。"
+
msgid "Explore"
msgstr "探索"
@@ -3074,6 +3288,12 @@ msgstr "无法å˜æ›´æ‰€æœ‰è€…"
msgid "Failed to check related branches."
msgstr "无法检查相关分支。"
+msgid "Failed to deploy to"
+msgstr "无法部署到"
+
+msgid "Failed to load emoji list."
+msgstr "无法加载表情列表。"
+
msgid "Failed to remove issue from board, please try again."
msgstr "无法从看æ¿ç§»é™¤è®®é¢˜ï¼Œè¯·é‡è¯•ã€‚"
@@ -3083,6 +3303,9 @@ msgstr "删除镜åƒå¤±è´¥ã€‚"
msgid "Failed to remove the pipeline schedule"
msgstr "无法删除æµæ°´çº¿è®¡åˆ’"
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr "更新议题失败, 请é‡è¯•"
@@ -3092,6 +3315,81 @@ msgstr "失败"
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr "速度更快,因其é‡ç”¨äº†é¡¹ç›®çš„工作空间(如果它ä¸å­˜åœ¨ï¼Œå°†å›žé€€åˆ°å…‹éš†ï¼‰"
+msgid "Feature Flags"
+msgstr "功能标志"
+
+msgid "FeatureFlags|API URL"
+msgstr "API URL"
+
+msgid "FeatureFlags|Active"
+msgstr "å·²å¯ç”¨"
+
+msgid "FeatureFlags|Application name"
+msgstr "应用å称"
+
+msgid "FeatureFlags|Configure"
+msgstr "é…ç½®"
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr "é…置功能标志"
+
+msgid "FeatureFlags|Create feature flag"
+msgstr "创建功能标志"
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr "删除 %{feature_flag_name}?"
+
+msgid "FeatureFlags|Description"
+msgstr "æè¿°"
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr "编辑 %{feature_flag_name}"
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr "编辑功能标志"
+
+msgid "FeatureFlags|Feature Flag"
+msgstr "功能标志"
+
+msgid "FeatureFlags|Feature flag"
+msgstr "功能标志"
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr "功能标志 %{feature_flag_name} å³å°†è¢«åˆ é™¤ã€‚确定继续å—?"
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr "功能标志å…许您通过动æ€å¼€å…³æŸäº›åŠŸèƒ½å°†ä»£ç é…置为ä¸åŒçš„特性组åˆã€‚"
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr "功能标志入门"
+
+msgid "FeatureFlags|Inactive"
+msgstr "未å¯ç”¨"
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr "安装 %{docs_link_start}兼容的客户端库%{docs_link_end} ,并在é…置指定API URLã€åº”用å称和实例ID。"
+
+msgid "FeatureFlags|Instance ID"
+msgstr "实例ID"
+
+msgid "FeatureFlags|More information"
+msgstr "更多信æ¯"
+
+msgid "FeatureFlags|Name"
+msgstr "å称"
+
+msgid "FeatureFlags|New"
+msgstr "新建"
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr "新建功能标志"
+
+msgid "FeatureFlags|Save changes"
+msgstr "ä¿å­˜æ›´æ”¹"
+
+msgid "FeatureFlags|Status"
+msgstr "状æ€"
+
msgid "Feb"
msgstr "二"
@@ -3101,6 +3399,9 @@ msgstr "二月"
msgid "Fields on this page are now uneditable, you can configure"
msgstr "当å‰é¡µé¢ä¸Šçš„字段ä¸å¯ç¼–辑,å¯ä»¥é…ç½®"
+msgid "File templates"
+msgstr "文件模æ¿"
+
msgid "Files"
msgstr "文件"
@@ -3113,9 +3414,18 @@ msgstr "填写下é¢çš„字段,å¯ç”¨<strong>%{enable_label}</strong>,然åŽç
msgid "Filter"
msgstr "筛选器"
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr "过滤器%{issuable_type}当å‰å…³é—­ã€‚"
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr "过滤器%{issuable_type}当å‰å¼€å¯ã€‚"
+
msgid "Filter by commit message"
msgstr "按æ交消æ¯è¿‡æ»¤"
+msgid "Filter..."
+msgstr "过滤..."
+
msgid "Find by path"
msgstr "按路径查找"
@@ -3131,6 +3441,9 @@ msgstr "查找新æå–çš„ <code>Takeout/Google Code项目托管/GoogleCodeProje
msgid "Fingerprints"
msgstr "指纹"
+msgid "Finish review"
+msgstr "完æˆè¯„审"
+
msgid "Finished"
msgstr "已完æˆ"
@@ -3143,8 +3456,8 @@ msgstr "推é€è€…:"
msgid "Fixed date"
msgstr "ä¿®å¤æ—¥æœŸ"
-msgid "Fixed finish date"
-msgstr "ä¿®å¤å®Œæˆæ—¥æœŸ"
+msgid "Fixed due date"
+msgstr "固定截止日期"
msgid "Fixed start date"
msgstr "ä¿®å¤å¼€å§‹æ—¥æœŸ"
@@ -3182,16 +3495,18 @@ msgstr "对于内部项目,任何已登录的用户都å¯ä»¥æŸ¥çœ‹æµæ°´çº¿å¹¶
msgid "For more information, go to the "
msgstr "如需了解详细信æ¯ï¼Œè¯·å‚阅"
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr "更多信æ¯è¯·æŸ¥é˜… %{link_start_tag}Jaeger çš„é…置文档%{link_end_tag}"
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr "欲了解更多相关信æ¯ï¼Œè¯·å‚阅 %{deactivating_usage_ping_link_start}使用情况检测(usage ping)%{deactivating_usage_ping_link_end}的文档。"
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr "对于ç§æœ‰é¡¹ç›®ï¼Œä»»ä½•æˆå‘˜ï¼ˆè®¿å®¢æˆ–更高级别)都å¯ä»¥æŸ¥çœ‹æµæ°´çº¿å¹¶è®¿é—®ä½œä¸šè¯¦æƒ…(输出日志和工件)"
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr "对于公共项目,任何人都å¯ä»¥æŸ¥çœ‹æµæ°´çº¿å¹¶è®¿é—®ä½œä¸šè¯¦æƒ…(输出日志和工件)"
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] "派生"
-
msgid "ForkedFromProjectPath|Forked from"
msgstr "派生自"
@@ -3207,6 +3522,9 @@ msgstr "æ ¼å¼"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr "在.gitlab-ci.yml中å‘现错误:"
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr "æ¥è‡ª %{provider_title}"
@@ -3249,6 +3567,9 @@ msgstr "一般æµæ°´çº¿"
msgid "Generate a default set of labels"
msgstr "生æˆä¸€ç»„默认的标记"
+msgid "Geo"
+msgstr "Geo"
+
msgid "Geo Nodes"
msgstr "Geo 节点"
@@ -3415,19 +3736,31 @@ msgid "GeoNodes|You have configured Geo nodes using an insecure HTTP connection.
msgstr "当å‰Geo节点é…置使用ä¸å®‰å…¨çš„HTTP连接, 建议使用HTTPS。"
msgid "Geo|%{name} is scheduled for forced re-download"
-msgstr ""
+msgstr "%{name} 计划强制é‡æ–°ä¸‹è½½"
msgid "Geo|%{name} is scheduled for re-check"
-msgstr ""
+msgstr "%{name} 计划é‡æ–°æ£€æŸ¥"
msgid "Geo|%{name} is scheduled for re-sync"
-msgstr ""
+msgstr "%{name} 已计划é‡æ–°åŒæ­¥"
+
+msgid "Geo|All"
+msgstr "全部"
msgid "Geo|All projects"
msgstr "所有项目"
-msgid "Geo|Error message"
-msgstr "错误消æ¯"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr "正在计划所有项目é‡æ–°æ£€æŸ¥"
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr "正在计划所有项目é‡æ–°åŒæ­¥"
+
+msgid "Geo|Batch operations"
+msgstr "批é‡æ“作"
+
+msgid "Geo|Could not remove tracking entry for an existing project."
+msgstr "无法删除现有项目的跟踪æ¡ç›®ã€‚"
msgid "Geo|Failed"
msgstr "失败"
@@ -3435,11 +3768,14 @@ msgstr "失败"
msgid "Geo|File sync capacity"
msgstr "文件åŒæ­¥å®¹é‡"
+msgid "Geo|Geo Status"
+msgstr "Geo状æ€"
+
msgid "Geo|Groups to synchronize"
msgstr "需åŒæ­¥çš„群组"
msgid "Geo|In sync"
-msgstr ""
+msgstr "å·²åŒæ­¥"
msgid "Geo|Last successful sync"
msgstr "最近一次æˆåŠŸçš„åŒæ­¥"
@@ -3456,8 +3792,8 @@ msgstr "从ä¸"
msgid "Geo|Next sync scheduled at"
msgstr "下一次åŒæ­¥å®‰æŽ’在"
-msgid "Geo|No errors"
-msgstr "无错误"
+msgid "Geo|Not synced yet"
+msgstr "尚未åŒæ­¥"
msgid "Geo|Pending"
msgstr "待定"
@@ -3468,6 +3804,9 @@ msgstr "å¾…åŒæ­¥"
msgid "Geo|Pending verification"
msgstr "待验è¯"
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr "项目(ID: %{project_id})å·²ä¸å†å­˜åœ¨äºŽä¸»èŠ‚点。 当å‰é¡¹å¯ä»¥è¢«å®‰å…¨çš„删除,因为这并ä¸ä¼šåˆ é™¤ä»»ä½•ç£ç›˜ä¸Šçš„有用数æ®ã€‚"
+
msgid "Geo|Projects in certain groups"
msgstr "指定群组中的项目"
@@ -3477,19 +3816,25 @@ msgstr "特定存储片中的项目"
msgid "Geo|Recheck"
msgstr "é‡æ–°æ£€æŸ¥"
+msgid "Geo|Recheck all projects"
+msgstr "é‡æ–°æ£€æŸ¥æ‰€æœ‰é¡¹ç›®"
+
msgid "Geo|Redownload"
msgstr "é‡æ–°ä¸‹è½½"
+msgid "Geo|Remove"
+msgstr "删除"
+
msgid "Geo|Repository sync capacity"
msgstr "仓库åŒæ­¥å®¹é‡"
msgid "Geo|Resync"
msgstr "é‡æ–°åŒæ­¥"
-msgid "Geo|Retry count"
-msgstr "é‡è¯•è®¡æ•°"
+msgid "Geo|Resync all projects"
+msgstr "é‡æ–°åŒæ­¥æ‰€æœ‰é¡¹ç›®"
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr "é‡è¯•è®¡æ•°"
msgid "Geo|Select groups to replicate."
@@ -3507,6 +3852,12 @@ msgstr "åŒæ­¥"
msgid "Geo|Synchronization failed - %{error}"
msgstr "åŒæ­¥å¤±è´¥ - %{error}"
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr "å·²æˆåŠŸåˆ é™¤é¡¹ç›® (%{project_id}) 的跟踪项。"
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr "跟踪项将被删除。 确定继续å—?"
+
msgid "Geo|Unknown state"
msgstr "未知状æ€"
@@ -3519,9 +3870,27 @@ msgstr "验è¯å¤±è´¥ - %{error}"
msgid "Geo|Waiting for scheduler"
msgstr "等待调度"
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
+msgstr "您需è¦ä¸åŒçš„许å¯è¯æ‰èƒ½ä½¿ç”¨ geo å¤åˆ¶"
+
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
msgstr ""
+msgid "Get a free instance review"
+msgstr "获得å…费的实例评估"
+
msgid "Git"
msgstr "Git"
@@ -3531,9 +3900,6 @@ msgstr "Git仓库URL"
msgid "Git revision"
msgstr "Gitæ交版本"
-msgid "Git storage health information has been reset"
-msgstr "Git 存储è¿è¡ŒçŠ¶å†µä¿¡æ¯å·²é‡ç½®"
-
msgid "Git strategy for pipelines"
msgstr "æµæ°´çº¿çš„Gitç­–ç•¥"
@@ -3600,12 +3966,6 @@ msgstr "转到"
msgid "Go to %{link_to_google_takeout}."
msgstr "转至 %{link_to_google_takeout}。"
-msgid "Go to your fork"
-msgstr "跳转到派生项目"
-
-msgid "GoToYourFork|Fork"
-msgstr "跳转到派生项目"
-
msgid "Google Code import"
msgstr "从Google Code导入"
@@ -3636,9 +3996,21 @@ msgstr "群组 ID"
msgid "Group Runners"
msgstr "群组Runner"
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr "群组URL"
+
msgid "Group avatar"
msgstr "群组头åƒ"
+msgid "Group description"
+msgstr "群组æè¿°"
+
+msgid "Group description (optional)"
+msgstr "群组æ述(å¯é€‰ï¼‰"
+
msgid "Group details"
msgstr "群组详细信æ¯"
@@ -3648,6 +4020,9 @@ msgstr "群组信æ¯"
msgid "Group maintainers can register group runners in the %{link}"
msgstr "群组维护者å¯ä»¥åœ¨é€šè¿‡ %{link} 注册群组级 Runner"
+msgid "Group name"
+msgstr "群组å称"
+
msgid "Group: %{group_name}"
msgstr "群组:%{group_name}"
@@ -3666,14 +4041,14 @@ msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰æœç´¢åˆ°ä»»ä½•ç¬¦åˆæ¡ä»¶çš„å²è¯—故事"
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr "路线图显示了å²è¯—故事沿ç€æ—¶é—´çº¿çš„进展情况"
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "如需查看路线图,请将计划的开始或结æŸæ—¥æœŸæ·»åŠ åˆ°å½“å‰ç¾¤ç»„或其å­ç»„中的æŸä¸ªå²è¯—故事。在月视图中,åªæ˜¾ç¤ºä¸Šä¸ªæœˆï¼Œæœ¬æœˆä»¥åŠæŽ¥ä¸‹æ¥5个月的å²è¯—故事&ndash; 从 %{startDate} 至 %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr "如需查看路线图,请将开始或结æŸæ—¥æœŸæ·»åŠ åˆ°å½“å‰ç¾¤ç»„或其å­ç»„中的æŸä¸ªå²è¯—故事。在月视图中,åªæ˜¾ç¤ºä¸Šä¸ªæœˆï¼Œæœ¬æœˆä»¥åŠæŽ¥ä¸‹æ¥5个月的å²è¯—故事&ndash; 从 %{startDate} 至 %{endDate}."
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "如需查看路线图,请将计划的开始或结æŸæ—¥æœŸæ·»åŠ åˆ°å½“å‰ç¾¤ç»„或其å­ç»„中的æŸä¸ªå²è¯—故事。在季度视图中,åªæ˜¾ç¤ºä¸Šä¸ªå­£åº¦ï¼Œæœ¬å­£åº¦ä»¥åŠæŽ¥ä¸‹æ¥4个季度的å²è¯—故事&ndash; 从 %{startDate} 至 %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr "如需查看路线图,请将开始或结æŸæ—¥æœŸæ·»åŠ åˆ°å½“å‰ç¾¤ç»„或其å­ç»„中的æŸä¸ªå²è¯—故事。在季度视图中,åªæ˜¾ç¤ºä¸Šä¸ªå­£åº¦ï¼Œæœ¬å­£åº¦ä»¥åŠæŽ¥ä¸‹æ¥4个季度的å²è¯—故事&ndash; 从 %{startDate} 至 %{endDate}."
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "如需查看路线图,请将计划的开始或结æŸæ—¥æœŸæ·»åŠ åˆ°å½“å‰ç¾¤ç»„或其å­ç»„中的æŸä¸ªå²è¯—故事。在周视图中,åªæ˜¾ç¤ºä¸Šå‘¨ï¼Œæœ¬å‘¨ä»¥åŠæŽ¥ä¸‹æ¥å››å‘¨çš„å²è¯—故事&ndash; 从 %{startDate} 至 %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr "如需查看路线图,请将开始或结æŸæ—¥æœŸæ·»åŠ åˆ°å½“å‰ç¾¤ç»„或其å­ç»„中的æŸä¸ªå²è¯—故事。在周视图中,åªæ˜¾ç¤ºä¸Šå‘¨ï¼Œæœ¬å‘¨ä»¥åŠæŽ¥ä¸‹æ¥å››å‘¨çš„å²è¯—故事&ndash; 从 %{startDate} 至 %{endDate}."
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除过滤器。在月视图中,åªæ˜¾ç¤ºä¸Šæœˆï¼Œæœ¬æœˆå’ŒæŽ¥ä¸‹æ¥çš„四个月的å²è¯—故事 &ndash; 从 %{startDate} 到 %{endDate} 。"
@@ -3688,20 +4063,17 @@ msgid "GroupRoadmap|Until %{dateWord}"
msgstr "直到 %{dateWord}"
msgid "GroupSettings|Badges"
-msgstr ""
+msgstr "徽章"
msgid "GroupSettings|Customize your group badges."
-msgstr ""
+msgstr "自定义群组徽章。"
msgid "GroupSettings|Learn more about badges."
-msgstr ""
+msgstr "了解有关徽章的更多信æ¯ã€‚"
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "ç¦æ­¢ä¸Žå…¶ä»–群组共享 %{group} 中的项目"
-msgid "GroupSettings|Share with group lock"
-msgstr "共享群组é”"
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "此设置已ç»åº”用于 %{ancestor_group},并已覆盖此å­ç»„的设置。"
@@ -3759,6 +4131,9 @@ msgstr "找ä¸åˆ°ç¾¤ç»„"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "您å¯ä»¥ç®¡ç†ç¾¤ç»„æˆå‘˜çš„æƒé™å¹¶è®¿é—®ç¾¤ç»„中的æ¯ä¸ªé¡¹ç›®ã€‚"
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr "您确定è¦é€€å‡ºç¾¤ç»„“%{fullName}â€å—?"
+
msgid "GroupsTree|Create a project in this group."
msgstr "在此群组中创建一个项目。"
@@ -3771,20 +4146,20 @@ msgstr "编辑群组"
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr "无法离开群组。请确ä¿æ‚¨ä¸æ˜¯å”¯ä¸€çš„所有者。"
-msgid "GroupsTree|Filter by name..."
-msgstr "按å称过滤..."
-
msgid "GroupsTree|Leave this group"
msgstr "离开这个群组"
msgid "GroupsTree|Loading groups"
msgstr "加载群组中"
-msgid "GroupsTree|Sorry, no groups matched your search"
-msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰æœç´¢åˆ°ä»»ä½•ç¬¦åˆçš„群组"
+msgid "GroupsTree|No groups matched your search"
+msgstr "没有æœç´¢åˆ°ä»»ä½•ç¬¦åˆçš„群组"
+
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr "没有任何群组或项目符åˆæ‚¨çš„æœç´¢"
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
-msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰ä»»ä½•ç¾¤ç»„或项目符åˆæ‚¨çš„æœç´¢"
+msgid "GroupsTree|Search by name"
+msgstr "按å称æœç´¢"
msgid "Have your users email"
msgstr "请让用户å‘é€ç”µå­é‚®ä»¶è‡³"
@@ -3825,6 +4200,9 @@ msgstr "以下是需è¦æ·»åŠ åˆ°è¿œç¨‹æœåŠ¡å™¨çš„SSH公钥。有关更多信æ¯
msgid "Hide host keys manual input"
msgstr "手工输入éšè—热键"
+msgid "Hide payload"
+msgstr "éšè—有效数æ®"
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "éšè—值"
@@ -3848,13 +4226,13 @@ msgid "ID"
msgstr "ID"
msgid "IDE|Allow live previews of JavaScript projects in the Web IDE using CodeSandbox client side evaluation."
-msgstr ""
+msgstr "å…许Web IDE中的JavaScript项目使用CodeSandbox客户端的实时预览。"
msgid "IDE|Back"
msgstr "返回"
msgid "IDE|Client side evaluation"
-msgstr "客户端评估"
+msgstr "客户端解算"
msgid "IDE|Commit"
msgstr "æ交"
@@ -3875,7 +4253,7 @@ msgid "IDE|Open in file view"
msgstr "在文件视图中打开"
msgid "IDE|Preview your web application using Web IDE client-side evaluation."
-msgstr "IDE|使用Web IDE客户端评估æ¥é¢„览您的web应用。"
+msgstr "使用Web IDE客户端解算æ¥é¢„览您的web应用。"
msgid "IDE|Refresh preview"
msgstr "刷新预览"
@@ -3988,6 +4366,9 @@ msgstr "使用GitLab ä¼ä¸šç‰ˆè®®é¢˜æƒé‡å¸¦æ¥çš„增强议题管ç†åŠŸèƒ½ã€‚"
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr "使用GitLabä¼ä¸šç‰ˆå…¨å±€æœç´¢å¸¦æ¥çš„增强æœç´¢åŠŸèƒ½"
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr "è¦å¯ç”¨å®žä¾‹çº§åˆ†æžï¼Œè¯·è¦æ±‚管ç†å‘˜å¯ç”¨ %{usage_ping_link_start}使用情况检测(usage ping)%{usage_ping_link_end}。"
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr "继续下一步,选择想è¦å¯¼å…¥çš„项目"
@@ -4001,7 +4382,7 @@ msgid "Incompatible Project"
msgstr "ä¸å…¼å®¹çš„项目"
msgid "Indicates whether this runner can pick jobs without tags"
-msgstr ""
+msgstr "指示此runner是å¦å¯ä»¥é€‰æ‹©æ²¡æœ‰æ ‡è®°çš„作业"
msgid "Inline"
msgstr "内è”"
@@ -4026,13 +4407,13 @@ msgid "Instance Statistics"
msgstr "实例统计"
msgid "Instance Statistics visibility"
-msgstr ""
+msgstr "实例统计信æ¯å¯è§æ€§"
msgid "Instance does not support multiple Kubernetes clusters"
msgstr "实例ä¸æ”¯æŒå¤šä¸ªKubernetes集群"
msgid "Integrations"
-msgstr "导入所有仓库"
+msgstr "集æˆ"
msgid "Integrations Settings"
msgstr "集æˆè®¾ç½®"
@@ -4055,6 +4436,12 @@ msgstr "循环周期"
msgid "Introducing Cycle Analytics"
msgstr "周期分æžç®€ä»‹"
+msgid "Invite"
+msgstr "邀请"
+
+msgid "Issue"
+msgstr "议题"
+
msgid "Issue Boards"
msgstr "议题看æ¿"
@@ -4079,6 +4466,36 @@ msgstr "议题å¯ä»¥æ˜¯ç¼ºé™·ï¼Œä»»åŠ¡æˆ–è¦è®¨è®ºçš„想法。此外,å¯ä»¥é€š
msgid "Issues closed"
msgstr "关闭议题"
+msgid "Issues, merge requests, pushes and comments."
+msgstr "议题,åˆå¹¶è¯·æ±‚,推é€å’Œè¯„论。"
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr "在您为项目创建议题åŽï¼Œæˆ‘们就会开始跟踪并显示它们的指标"
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr "创建的议题数"
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr "æ¯æœˆåˆ›å»ºçš„议题"
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr "最近12个月"
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰ç¬¦åˆè¿‡æ»¤å™¨çš„任何结果"
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr "群组中的项目没有任何议题"
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„过滤æ¡ä»¶"
+
+msgid "Jaeger URL"
+msgstr "Jaeger 地å€"
+
+msgid "Jaeger tracing"
+msgstr "Jaeger 跟踪"
+
msgid "Jan"
msgstr "一"
@@ -4094,9 +4511,6 @@ msgstr "作业已被删除"
msgid "Jobs"
msgstr "作业"
-msgid "Job|Are you sure you want to erase this job?"
-msgstr "你确定è¦åˆ é™¤è¯¥ä½œä¸šå—?"
-
msgid "Job|Browse"
msgstr "æµè§ˆ"
@@ -4110,13 +4524,13 @@ msgid "Job|Erase job log"
msgstr "删除作业日志"
msgid "Job|Job artifacts"
-msgstr ""
+msgstr "作业产物"
msgid "Job|Job has been erased"
msgstr "作业已被删除"
msgid "Job|Job has been erased by"
-msgstr ""
+msgstr "作业已被删除"
msgid "Job|Keep"
msgstr "ä¿æŒ"
@@ -4131,13 +4545,13 @@ msgid "Job|Show complete raw"
msgstr "显示完整æº"
msgid "Job|The artifacts were removed"
-msgstr ""
+msgstr "作业产物已被删除"
-msgid "Job|The artifacts will be removed"
-msgstr ""
+msgid "Job|The artifacts will be removed in"
+msgstr "作业产物将被删除于"
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
-msgstr ""
+msgstr "此作业已åœæ­¢ï¼Œå› ä¸ºæ²¡æœ‰ä»»ä½•åœ¨çº¿çš„runner被分é…给该项目。"
msgid "Jul"
msgstr "七"
@@ -4151,12 +4565,6 @@ msgstr "å…­"
msgid "June"
msgstr "六月"
-msgid "Koding"
-msgstr "Koding"
-
-msgid "Koding Dashboard"
-msgstr "Koding仪表æ¿"
-
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -4227,7 +4635,10 @@ msgid "Labels|Promote Label"
msgstr "å‡çº§æ ‡è®°"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
-msgstr ""
+msgstr "æå‡ %{labelTitle} 将使其å¯ç”¨äºŽ %{groupName} 内的所有项目。现有的åŒå项目标记将被åˆå¹¶ã€‚该æ“作ä¸å¯æ’¤é”€ã€‚"
+
+msgid "Large File Storage"
+msgstr "大文件存储"
msgid "Last %d day"
msgid_plural "Last %d days"
@@ -4239,12 +4650,18 @@ msgstr "最新æµæ°´çº¿"
msgid "Last commit"
msgstr "最åŽæ交"
+msgid "Last contact"
+msgstr "最åŽè”ç³»"
+
msgid "Last edited %{date}"
msgstr "最åŽä¿®æ”¹ %{date}"
msgid "Last edited by %{name}"
msgstr "最åŽä¿®æ”¹äºº %{name}"
+msgid "Last reply by"
+msgstr "最åŽå›žå¤è€…"
+
msgid "Last update"
msgstr "最åŽæ›´æ–°"
@@ -4293,6 +4710,15 @@ msgstr "使用默认值设定 \"文件类型\" 和 \"交付方法\""
msgid "License"
msgstr "许å¯è¯"
+msgid "LicenseManagement|Add a license"
+msgstr "添加许å¯è¯"
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr "手动添加许å¯è¯ä»¥æ‰¹å‡†æˆ–加入黑åå•"
+
+msgid "LicenseManagement|Approve"
+msgstr "批准"
+
msgid "LicenseManagement|Approve license"
msgstr "批准许å¯è¯"
@@ -4302,6 +4728,9 @@ msgstr "批准许å¯è¯ï¼Ÿ"
msgid "LicenseManagement|Approved"
msgstr "已批准"
+msgid "LicenseManagement|Blacklist"
+msgstr "黑åå•"
+
msgid "LicenseManagement|Blacklist license"
msgstr "许å¯è¯é»‘åå•"
@@ -4311,6 +4740,9 @@ msgstr "许å¯è¯é»‘åå•ï¼Ÿ"
msgid "LicenseManagement|Blacklisted"
msgstr "黑åå•"
+msgid "LicenseManagement|Cancel"
+msgstr "å–消"
+
msgid "LicenseManagement|License"
msgstr "许å¯è¯"
@@ -4320,8 +4752,11 @@ msgstr "许å¯è¯ç®¡ç†"
msgid "LicenseManagement|License details"
msgstr "许å¯è¯ä¿¡æ¯"
+msgid "LicenseManagement|License name"
+msgstr "许å¯è¯å称"
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
-msgstr ""
+msgstr "管ç†æ­¤é¡¹ç›®çš„已批准和列入黑åå•çš„许å¯è¯ã€‚"
msgid "LicenseManagement|Packages"
msgstr "包"
@@ -4332,8 +4767,14 @@ msgstr "删除许å¯è¯"
msgid "LicenseManagement|Remove license?"
msgstr "删除许å¯è¯ï¼Ÿ"
+msgid "LicenseManagement|Submit"
+msgstr "æ交"
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
-msgstr ""
+msgstr "此项目目å‰æ²¡æœ‰å·²æ‰¹å‡†æˆ–列入黑åå•çš„许å¯è¯ã€‚"
+
+msgid "LicenseManagement|This license already exists in this project."
+msgstr "此许å¯è¯å·²å­˜åœ¨äºŽå½“å‰é¡¹ç›®ä¸­ã€‚"
msgid "LicenseManagement|URL"
msgstr "URL"
@@ -4360,6 +4801,9 @@ msgstr "列出Gitea存储库"
msgid "List available repositories"
msgstr "列出å¯ç”¨å­˜å‚¨åº“"
+msgid "List view"
+msgstr "列表视图"
+
msgid "List your Bitbucket Server repositories"
msgstr "列出您的 Bitbucket 库"
@@ -4388,7 +4832,7 @@ msgid "Lock not found"
msgstr "未找到é”"
msgid "Lock this %{issuableDisplayName}? Only <strong>project members</strong> will be able to comment."
-msgstr ""
+msgstr "é”定%{issuableDisplayName}?åªæœ‰ <strong>项目æˆå‘˜</strong> å¯ä»¥å‘表评论。"
msgid "Lock to current projects"
msgstr "é”定到当å‰é¡¹ç›®"
@@ -4405,6 +4849,9 @@ msgstr "å·²é”定到目å‰çš„项目"
msgid "Locks give the ability to lock specific file or folder."
msgstr "加é”å¯ä»¥é”定特定的文件或文件夹。"
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr "日志"
@@ -4418,7 +4865,7 @@ msgid "Manage Git repositories with fine-grained access controls that keep your
msgstr "通过细粒度的访问控制æ¥ç®¡ç†Git存储库,确ä¿æ‚¨çš„代ç å®‰å…¨ã€‚执行代ç å®¡æŸ¥å¹¶é€šè¿‡åˆå¹¶è¯·æ±‚的实现更紧密的开å‘å作。æ¯ä¸ªé¡¹ç›®è¿˜å¯ä»¥é…置议题跟踪和wiki。"
msgid "Manage Web IDE features"
-msgstr ""
+msgstr "管ç†Web IDE功能"
msgid "Manage access"
msgstr "管ç†æƒé™"
@@ -4474,17 +4921,47 @@ msgstr "标记为已完æˆ"
msgid "Markdown enabled"
msgstr "支æŒMarkdownæ ¼å¼"
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr "添加一个符å·åˆ—表"
+
+msgid "MarkdownToolbar|Add a link"
+msgstr "添加一个链接"
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr "添加一个编å·åˆ—表"
+
+msgid "MarkdownToolbar|Add a table"
+msgstr "添加一个表格"
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr "添加一个任务列表"
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr "添加粗体文本"
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr "添加斜体文本"
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr "å…¨å±æ˜¾ç¤º"
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr "æ’入一个引用"
+
+msgid "MarkdownToolbar|Insert code"
+msgstr "æ’入代ç "
+
msgid "Maven Metadata"
-msgstr ""
+msgstr "Maven 元数æ®"
msgid "Maven package"
-msgstr ""
+msgstr "Maven 包"
-msgid "Maximum git storage failures"
-msgstr "最大 git 存储失败次数"
+msgid "Max access level"
+msgstr "最高访问级别"
msgid "Maximum job timeout"
-msgstr ""
+msgstr "最大作业超时"
msgid "May"
msgstr "五"
@@ -4492,6 +4969,12 @@ msgstr "五"
msgid "Median"
msgstr "中ä½æ•°"
+msgid "Member lock"
+msgstr "æˆå‘˜é”"
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr "æˆå‘˜"
@@ -4525,6 +5008,21 @@ msgstr "åˆå¹¶è¯·æ±‚"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "åˆå¹¶è¯·æ±‚用于æ出对项目的更改与他人讨论"
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr "ä¿å­˜è¯„论è‰ç¨¿æ—¶å‘生错误。"
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr "评论ä¿æŒè§£å†³çŠ¶æ€ã€‚"
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr "评论ä¿æŒæœªè§£å†³çŠ¶æ€"
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr "评论将å˜ä¸ºè§£å†³çŠ¶æ€ã€‚"
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr "评论将å˜ä¸ºæœªè§£å†³çŠ¶æ€ã€‚"
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr "在新议题中解决此讨论"
@@ -4534,9 +5032,6 @@ msgstr "ä¿å­˜è¯„论失败"
msgid "MergeRequests|Toggle comments for this file"
msgstr "切æ¢æ­¤æ–‡ä»¶çš„讨论"
-msgid "MergeRequests|Updating discussions failed"
-msgstr "更新讨论失败"
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr "查看文件 @ %{commitId}"
@@ -4544,7 +5039,13 @@ msgid "MergeRequests|View replaced file @ %{commitId}"
msgstr "查看已替æ¢æ–‡ä»¶ @ %{commitId}"
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
-msgstr ""
+msgstr " %{paragraphStart}å°†æ述更改为 %{descriptionChangedTimes} 次 %{timeDifferenceMinutes}%{paragraphEnd}"
+
+msgid "MergeRequest|Filter files"
+msgstr "过滤文件"
+
+msgid "MergeRequest|No files found"
+msgstr "未找到任何文件"
msgid "Merged"
msgstr "å·²åˆå¹¶"
@@ -4561,6 +5062,9 @@ msgstr "指标 - Influx"
msgid "Metrics - Prometheus"
msgstr "指标 - Prometheus"
+msgid "Metrics and profiling"
+msgstr "指标和分æž"
+
msgid "Metrics|Business"
msgstr "业务"
@@ -4664,22 +5168,22 @@ msgid "Milestone"
msgstr "里程碑"
msgid "Milestone lists not available with your current license"
-msgstr ""
+msgstr "当å‰è®¸å¯è¯æ— æ³•ä½¿ç”¨é‡Œç¨‹ç¢‘列表"
msgid "Milestone lists show all issues from the selected milestone."
-msgstr ""
+msgstr "里程碑列表显示所选里程碑的所有议题。"
msgid "Milestones"
msgstr "里程碑"
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle} and remove it from %{issuesWithCount} and %{mergeRequestsWithCount}. Once deleted, it cannot be undone or recovered."
-msgstr ""
+msgstr "您å³å°†æ°¸ä¹…删除里程碑 %{milestoneTitle} 并将其从 %{issuesWithCount} å’Œ %{mergeRequestsWithCount} 删除。删除åŽï¼Œæ— æ³•æ’¤æ¶ˆæˆ–æ¢å¤ã€‚"
msgid "Milestones| You’re about to permanently delete the milestone %{milestoneTitle}. This milestone is not currently used in any issues or merge requests."
-msgstr ""
+msgstr "您å³å°†æ°¸ä¹…删除里程碑 %{milestoneTitle}。此里程碑当å‰æœªç”¨äºŽä»»ä½•è®®é¢˜æˆ–åˆå¹¶è¯·æ±‚。"
msgid "Milestones|<p>%{milestonePromotion}</p> %{finalWarning}"
-msgstr ""
+msgstr "<p>%{milestonePromotion}</p> %{finalWarning}"
msgid "Milestones|Delete milestone"
msgstr "删除里程碑"
@@ -4700,16 +5204,16 @@ msgid "Milestones|Promote Milestone"
msgstr "å‡çº§é‡Œç¨‹ç¢‘"
msgid "Milestones|Promoting %{milestone} will make it available for all projects inside %{groupName}. Existing project milestones with the same name will be merged. "
-msgstr ""
+msgstr "æå‡ %{milestone} 将使其å¯ç”¨äºŽ %{groupName} 内的所有项目。现有的åŒå项目里程碑将被åˆå¹¶ã€‚ "
msgid "Milestones|This action cannot be reversed."
msgstr "该æ“作无法撤销。"
msgid "Mirror a repository"
-msgstr ""
+msgstr "é•œåƒå­˜å‚¨åº“"
msgid "Mirror direction"
-msgstr ""
+msgstr "é•œåƒæ–¹å‘"
msgid "Mirror repository"
msgstr "é•œåƒå­˜å‚¨åº“"
@@ -4718,10 +5222,10 @@ msgid "Mirror user"
msgstr "é•œåƒç”¨æˆ·"
msgid "Mirrored repositories"
-msgstr ""
+msgstr "é•œåƒçš„存储库"
msgid "Mirroring repositories"
-msgstr ""
+msgstr "é•œåƒå­˜å‚¨åº“"
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr "新建 SSH 公钥"
@@ -4777,6 +5281,9 @@ msgstr "通过标题命å您的个人密钥"
msgid "Name:"
msgstr "å称:"
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr "帮助"
@@ -4895,6 +5402,12 @@ msgstr "无法连接到GitalyæœåŠ¡å™¨ï¼Œè¯·æ£€æŸ¥ç›¸å…³æ—¥å¿—ï¼"
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr "此项目当å‰æœªå­˜å‚¨å®¹å™¨é•œåƒã€‚如需使用,请å‚照上述说明新建容器镜åƒã€‚"
+msgid "No contributions were found"
+msgstr "未找到任何贡献者"
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr "无截止日期"
@@ -4904,9 +5417,6 @@ msgstr "无预计或已用时间"
msgid "No file chosen"
msgstr "未选定任何文件"
-msgid "No files found"
-msgstr "沒有找到文件"
-
msgid "No files found."
msgstr "没有找到文件。"
@@ -4916,6 +5426,9 @@ msgstr "所选时间段没有议题。"
msgid "No labels with such name or description"
msgstr "没有具有此类å称或æ述的标记"
+msgid "No license. All rights reserved"
+msgstr "没有许å¯è¯ã€‚ 所有æƒä¿ç•™"
+
msgid "No merge requests for the selected time period."
msgstr "所选时间段没有åˆå¹¶è¯·æ±‚。"
@@ -4929,7 +5442,7 @@ msgid "No other labels with such name or description"
msgstr "没有其他具有此类å称或æ述的标记"
msgid "No packages stored for this project."
-msgstr ""
+msgstr "没有为此项目存储的包。"
msgid "No prioritised labels with such name or description"
msgstr "没有具有此类å称或æ述的优先标记"
@@ -4943,6 +5456,9 @@ msgstr "所选时间段没有推é€ã€‚"
msgid "No repository"
msgstr "没有仓库"
+msgid "No runners found"
+msgstr "没有å‘现Runner"
+
msgid "No schedules"
msgstr "没有计划"
@@ -4959,7 +5475,7 @@ msgid "Not all comments are displayed because you're comparing two versions of t
msgstr "并éžæ‰€æœ‰æ³¨é‡Šéƒ½ä¼šæ˜¾ç¤ºï¼Œå› ä¸ºæ‚¨æ­£åœ¨æ¯”较两个版本的差异。"
msgid "Not all comments are displayed because you're viewing an old version of the diff."
-msgstr ""
+msgstr "并éžæ‰€æœ‰æ³¨é‡Šéƒ½æ˜¾ç¤ºï¼Œå› ä¸ºæ‚¨æ­£åœ¨æŸ¥çœ‹æ—§ç‰ˆæœ¬çš„差异。"
msgid "Not allowed to merge"
msgstr "ä¸å…许åˆå¹¶"
@@ -4979,6 +5495,9 @@ msgstr "éžæœºå¯†"
msgid "Not enough data"
msgstr "æ•°æ®ä¸è¶³"
+msgid "Not now"
+msgstr "æš‚ä¸"
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr "请注æ„,master分支自动å—ä¿æŠ¤ã€‚%{link_to_protected_branches}"
@@ -4997,6 +5516,18 @@ msgstr "æ示:如GitLab管ç†å‘˜é…ç½® %{github_integration_link},将å…许
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr "确定è¦å–消此评论å—?"
+msgid "Notes|Collapse replies"
+msgstr "折å å›žå¤"
+
+msgid "Notes|Show all activity"
+msgstr "显示所有活动"
+
+msgid "Notes|Show comments only"
+msgstr "仅显示评论"
+
+msgid "Notes|Show history only"
+msgstr "仅显示历å²è®°å½•"
+
msgid "Notification events"
msgstr "通知事件"
@@ -5013,7 +5544,7 @@ msgid "NotificationEvent|Merge merge request"
msgstr "åˆå¹¶è¯·æ±‚被åˆå¹¶"
msgid "NotificationEvent|New epic"
-msgstr ""
+msgstr "新建å²è¯—"
msgid "NotificationEvent|New issue"
msgstr "新建议题"
@@ -5069,9 +5600,6 @@ msgstr "å一"
msgid "November"
msgstr "å一月"
-msgid "Number of access attempts"
-msgstr "å°è¯•è®¿é—®æ¬¡æ•°"
-
msgid "OK"
msgstr "确定"
@@ -5097,9 +5625,6 @@ msgstr "您的一个或多个Bitbucket项目无法直接导入GitLab,因为它
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr "您的一个或多个Google Code项目无法直接导入GitLab,因为它们使用Subversion或Mercurial进行版本控制,而ä¸æ˜¯Git。"
-msgid "Online IDE integration settings."
-msgstr "在线IDE集æˆè®¾ç½®ã€‚"
-
msgid "Only admins"
msgstr "仅管ç†å‘˜"
@@ -5107,7 +5632,7 @@ msgid "Only comments from the following commit are shown below"
msgstr "下é¢ä»…显示æ¥è‡ªä»¥ä¸‹æ交的评论"
msgid "Only mirror protected branches"
-msgstr ""
+msgstr "åªé•œåƒå—ä¿æŠ¤çš„分支"
msgid "Only project members can comment."
msgstr "åªæœ‰é¡¹ç›®æˆå‘˜å¯ä»¥å‘表评论。"
@@ -5116,11 +5641,14 @@ msgid "Oops, are you sure?"
msgstr "å•Š~~, 确定å—?"
msgid "Open"
-msgstr "打开"
+msgstr "展开"
msgid "Open in Xcode"
msgstr "用Xcode打开"
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr "打开侧边æ "
@@ -5145,6 +5673,21 @@ msgstr "打开一个新窗å£"
msgid "Operations"
msgstr "è¿ç»´"
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr "æ“作设置"
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "您å¯ä»¥é€‰æ‹© %{link_to_customize} FogBugz的电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·å如何被导入到GitLab。"
@@ -5185,7 +5728,7 @@ msgid "Package was removed"
msgstr "包已被删除"
msgid "Packages"
-msgstr "包"
+msgstr "软件包"
msgid "Pages"
msgstr "Pages"
@@ -5211,6 +5754,9 @@ msgstr "密ç "
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr "粘贴您的 SSH 公钥,通常包å«åœ¨ '~/.ssh/id_rsa.pub' 文件中,并以 'ssh-rsa' 开头。ä¸è¦ä½¿ç”¨æ‚¨çš„ SSH ç§é’¥ã€‚"
+msgid "Path, transfer, remove"
+msgstr "路径,转移,删除"
+
msgid "Path:"
msgstr "路径:"
@@ -5218,13 +5764,13 @@ msgid "Pause"
msgstr "æš‚åœ"
msgid "Paused Runners don't accept new jobs"
-msgstr ""
+msgstr "æš‚åœçš„ Runner ä¸æŽ¥å—新作业"
msgid "Pending"
msgstr "等待中"
msgid "People without permission will never get a notification and won't be able to comment."
-msgstr ""
+msgstr "未ç»è®¸å¯çš„用户将无法收到通知,也无法评论。"
msgid "Per job. If a job passes this threshold, it will be marked as failed"
msgstr "æ¯ä¸ªä½œä¸šã€‚如果作业超过此阈值,则会将其标记为失败"
@@ -5238,15 +5784,15 @@ msgstr "性能优化"
msgid "Permissions"
msgstr "æƒé™"
+msgid "Permissions, LFS, 2FA"
+msgstr "æƒé™ï¼ŒLFS,2FA"
+
msgid "Personal Access Token"
msgstr "个人访问凭è¯"
msgid "Pipeline"
msgstr "æµæ°´çº¿"
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
-msgstr ""
-
msgid "Pipeline Health"
msgstr "æµæ°´çº¿è¿è¡ŒçŠ¶å†µæŒ‡æ ‡"
@@ -5335,7 +5881,7 @@ msgid "Pipelines|Clear Runner Caches"
msgstr "清除Runner缓存"
msgid "Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment."
-msgstr ""
+msgstr "æŒç»­é›†æˆå¯ä»¥é€šè¿‡è‡ªåŠ¨è¿è¡Œæµ‹è¯•æ¥å¸®åŠ©æ•èŽ·é”™è¯¯ï¼Œè€ŒæŒç»­éƒ¨ç½²å¯ä»¥å¸®åŠ©æ‚¨å‘生产环境交付代ç ã€‚"
msgid "Pipelines|Get started with Pipelines"
msgstr "æµæ°´çº¿å…¥é—¨"
@@ -5359,20 +5905,29 @@ msgid "Pipelines|There are currently no pipelines."
msgstr "当å‰æ²¡æœ‰æµæ°´çº¿ã€‚"
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
-msgstr ""
+msgstr "获å–æµæ°´çº¿æ—¶å‡ºçŽ°é”™è¯¯ã€‚请ç¨åŽé‡è¯•æˆ–å°è¯•è”系您的支æŒå›¢é˜Ÿã€‚"
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "此项目当å‰æœªé…ç½®è¿è¡Œæµæ°´çº¿ã€‚"
+msgid "Pipeline|Commit"
+msgstr "æ交"
+
msgid "Pipeline|Create for"
msgstr "创建于"
msgid "Pipeline|Create pipeline"
msgstr "创建æµæ°´çº¿"
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr "现有分支å称或者标签"
+msgid "Pipeline|Pipeline"
+msgstr "æµæ°´çº¿"
+
msgid "Pipeline|Run Pipeline"
msgstr "è¿è¡Œæµæ°´çº¿"
@@ -5382,6 +5937,12 @@ msgstr "æœç´¢åˆ†æ”¯"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr "指定è¦åœ¨æ­¤æ¬¡è¿è¡Œä¸­ä½¿ç”¨çš„å˜é‡å€¼ã€‚默认情况下将使用 %{settings_link} 中指定的值。"
+msgid "Pipeline|Stages"
+msgstr "阶段"
+
+msgid "Pipeline|Status"
+msgstr "状æ€"
+
msgid "Pipeline|Stop pipeline"
msgstr "åœæ­¢æµæ°´çº¿"
@@ -5409,12 +5970,6 @@ msgstr "于阶段"
msgid "Plain diff"
msgstr "文本差异"
-msgid "Planned finish date"
-msgstr "计划完æˆæ—¥æœŸ"
-
-msgid "Planned start date"
-msgstr "计划开始日期"
-
msgid "PlantUML"
msgstr "PlantUML"
@@ -5424,12 +5979,18 @@ msgstr "è¿è¡Œ"
msgid "Please accept the Terms of Service before continuing."
msgstr "请接å—æœåŠ¡æ¡æ¬¾ä»¥ç»§ç»­ã€‚"
+msgid "Please choose a group URL with no special characters."
+msgstr "请选择没有特殊字符的群组URL。"
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr "请将它们先%{link_to_git}, 然åŽå†æ¬¡ä½¿ç”¨%{link_to_import_flow}。"
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr "请将它们先在Google Code中转为Git, 然åŽå†æ¬¡ä½¿ç”¨%{link_to_import_flow}。"
+msgid "Please fill in a descriptive name for your group."
+msgstr "请为您的群组填写æ述性å称。"
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "请注æ„,GitLabä¸æ供此应用程åºï¼Œæ‚¨åº”该在å…许访问之å‰éªŒè¯å…¶çœŸå®žæ€§ã€‚"
@@ -5442,6 +6003,9 @@ msgstr "请填写验è¯ç ã€‚"
msgid "Please try again"
msgstr "请å†è¯•ä¸€æ¬¡"
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr "请使用此表å•å‘GitLab报告创建垃圾议题ã€è¯„论或有ä¸å½“行为的用户。"
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr "连接代ç ä»“库中,请ç¨å€™ã€‚å¯åœ¨ä»»æ„时刻刷新以获å–当å‰çŠ¶æ€ã€‚"
@@ -5454,9 +6018,18 @@ msgstr "å好设置"
msgid "Preferences|Navigation theme"
msgstr "导航主题"
+msgid "Press Enter or click to search"
+msgstr "按 回车键或å•å‡»ä»¥æœç´¢"
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr "ç¦æ­¢å‘当å‰ç¾¤ç»„添加æˆå‘˜"
+
msgid "Preview"
msgstr "预览"
+msgid "Preview payload"
+msgstr "预览有效负载"
+
msgid "Primary"
msgstr "主è¦"
@@ -5485,10 +6058,10 @@ msgid "Profile"
msgstr "用户资料"
msgid "Profile Settings"
-msgstr "账户设置"
+msgstr "个人资料设置"
msgid "Profiles| You are about to permanently delete %{yourAccount}, and all of the issues, merge requests, and groups linked to your account. Once you confirm %{deleteAccount}, it cannot be undone or recovered."
-msgstr ""
+msgstr "您å³å°†æ°¸ä¹…删除 %{yourAccount},以åŠä¸Žæ‚¨çš„å¸æˆ·å…³è”的所有议题,åˆå¹¶è¯·æ±‚和群组。一旦确认 %{deleteAccount},此æ“作便无法撤销和æ¢å¤ã€‚"
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr "您将更改用户å %{currentUsernameBold} 为 %{newUsernameBold}。é…置文件和项目将é‡å®šå‘到 %{newUsername} 命å空间,但是一旦 %{currentUsername} 命å空间被å¦ä¸€ä¸ªç”¨æˆ·æˆ–组注册,此é‡å®šå‘将过期。请尽快更新您的远端Git仓库。"
@@ -5500,17 +6073,32 @@ msgid "Profiles|Add key"
msgstr "添加密钥"
msgid "Profiles|Add status emoji"
-msgstr ""
+msgstr "在状æ€ä¸­æ·»åŠ è¡¨æƒ…符å·"
+
+msgid "Profiles|Avatar cropper"
+msgstr "头åƒè£å‰ª"
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr "å³å°†åˆ é™¤å¤´åƒã€‚确定继续å—?"
msgid "Profiles|Change username"
msgstr "更改用户å"
+msgid "Profiles|Choose file..."
+msgstr "选择文件..."
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr "选择在公开个人资料中显示ç§æœ‰é¡¹ç›®çš„贡献,但ä¸æ˜¾ç¤ºä»»ä½•é¡¹ç›®ï¼Œå­˜å‚¨åº“或组织信æ¯ã€‚"
+
msgid "Profiles|Clear status"
-msgstr ""
+msgstr "清除状æ€"
msgid "Profiles|Current path: %{path}"
msgstr "当å‰è·¯å¾„: %{path}"
+msgid "Profiles|Current status"
+msgstr "当å‰çŠ¶æ€"
+
msgid "Profiles|Delete Account"
msgstr "删除å¸æˆ·"
@@ -5523,20 +6111,77 @@ msgstr "删除您的å¸æˆ·?"
msgid "Profiles|Deleting an account has the following effects:"
msgstr "删除å¸æˆ·å…·æœ‰ä»¥ä¸‹æ•ˆæžœï¼š"
+msgid "Profiles|Do not show on profile"
+msgstr "ä¸åœ¨ä¸ªäººèµ„料中显示"
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr "ä¸è¦åœ¨ä¸ªäººèµ„料上显示与活动相关的个人信æ¯"
+
+msgid "Profiles|Edit Profile"
+msgstr "编辑个人资料"
+
msgid "Profiles|Invalid password"
msgstr "密ç æ— æ•ˆ"
msgid "Profiles|Invalid username"
msgstr "用户å无效"
+msgid "Profiles|Learn more"
+msgstr "了解更多"
+
+msgid "Profiles|Made a private contribution"
+msgstr "作出了ç§æœ‰è´¡çŒ®"
+
+msgid "Profiles|Main settings"
+msgstr "主è¦è®¾ç½®"
+
+msgid "Profiles|No file chosen"
+msgstr "未选择文件"
+
msgid "Profiles|Path"
msgstr "路径"
+msgid "Profiles|Position and size your new avatar"
+msgstr "您新头åƒçš„ä½ç½®å’Œå¤§å°"
+
+msgid "Profiles|Private contributions"
+msgstr "éžå…¬å¼€è´¡çŒ®"
+
+msgid "Profiles|Public Avatar"
+msgstr "公共头åƒ"
+
+msgid "Profiles|Remove avatar"
+msgstr "删除头åƒ"
+
+msgid "Profiles|Set new profile picture"
+msgstr "设置新个人资料图片"
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr "æŸäº›é€‰é¡¹å¯¹äºŽ LDAP å¸æˆ·ä¸å¯ç”¨"
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr "在少于250个字符的情况下介ç»æ‚¨è‡ªå·±ã€‚"
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr "å…许的最大文件大å°ä¸º200KB。"
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "这看起æ¥ä¸åƒ SSH 公钥,确定è¦æ·»åŠ å®ƒå—?"
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr "此电å­é‚®ä»¶å°†æ˜¾ç¤ºåœ¨æ‚¨çš„公开个人资料中。"
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr "此电å­é‚®ä»¶å°†ç”¨äºŽåŸºäºŽWebçš„æ“作,例如编辑和åˆå¹¶ã€‚ %{learn_more}"
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
-msgstr ""
+msgstr "这个表情符å·å’Œè¿™æ¡æ¶ˆæ¯ä¼šåœ¨æ‚¨çš„个人资料和整个工作界é¢ä¸­å‡ºçŽ°ã€‚"
+
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr "此功能当åˆå¤„于实验阶段,翻译尚未全部完æˆã€‚"
+
+msgid "Profiles|This information will appear on your profile."
+msgstr "此信æ¯å°†æ˜¾ç¤ºåœ¨æ‚¨çš„个人资料中。"
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "键入您的 %{confirmationValue} 以确认:"
@@ -5544,17 +6189,41 @@ msgstr "键入您的 %{confirmationValue} 以确认:"
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr "通常以“ssh-rsa ...â€å¼€å¤´"
+msgid "Profiles|Update profile settings"
+msgstr "更新个人资料设置"
+
msgid "Profiles|Update username"
msgstr "更新用户å"
+msgid "Profiles|Upload new avatar"
+msgstr "上传新头åƒ"
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr "使用ç§äººç”µå­é‚®ä»¶ - %{email}"
+
msgid "Profiles|Username change failed - %{message}"
msgstr "用户å更改失败 - %{message}"
msgid "Profiles|Username successfully changed"
msgstr "用户å更改æˆåŠŸ"
+msgid "Profiles|Website"
+msgstr "网站"
+
msgid "Profiles|What's your status?"
-msgstr "你的状况?"
+msgstr "你当å‰çš„状æ€ï¼Ÿ"
+
+msgid "Profiles|You can change your avatar here"
+msgstr "å¯ä»¥åœ¨è¿™é‡Œä¿®æ”¹æ‚¨çš„头åƒ"
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr "您å¯ä»¥åœ¨è¿™é‡Œä¿®æ”¹å¤´åƒæˆ–删除当å‰å¤´åƒå¹¶æ¢å¤ä¸º %{gravatar_link}"
+
+msgid "Profiles|You can upload your avatar here"
+msgstr "å¯ä»¥åœ¨è¿™é‡Œä¸Šä¼ æ‚¨çš„头åƒ"
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr "å¯ä»¥åœ¨è¿™é‡Œä¸Šä¼ æ‚¨çš„头åƒæˆ–者从 %{gravatar_link} 修改头åƒ"
msgid "Profiles|You don't have access to delete this user."
msgstr "您无æƒåˆ é™¤æ­¤ç”¨æˆ·ã€‚"
@@ -5565,8 +6234,17 @@ msgstr "您必须转移所有æƒæˆ–删除这些群组,然åŽæ‰èƒ½åˆ é™¤æ‚¨çš„
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "您的å¸æˆ·ç›®å‰æ˜¯è¿™äº›ç¾¤ç»„的所有者:"
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr "您的邮件地å€æ˜¯æ ¹æ®æ‚¨çš„ %{provider_label} å¸æˆ·è‡ªåŠ¨è®¾ç½®çš„。"
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr "您的ä½ç½®æ˜¯åŸºäºŽæ‚¨çš„ %{provider_label} å¸æˆ·è‡ªåŠ¨è®¾ç½®çš„。"
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr "您的姓å是根æ®æ‚¨çš„ %{provider_label} å¸æˆ·è‡ªåŠ¨è®¾ç½®çš„,因此您认识的人å¯ä»¥è¯†åˆ«æ‚¨ã€‚"
+
msgid "Profiles|Your status"
-msgstr "你的状况"
+msgstr "你的状æ€"
msgid "Profiles|e.g. My MacBook key"
msgstr "例如: My MacBook Key"
@@ -5601,6 +6279,9 @@ msgstr "项目 '%{project_name}' 已更新完æˆã€‚"
msgid "Project Badges"
msgstr "项目徽章"
+msgid "Project URL"
+msgstr "项目 URL"
+
msgid "Project access must be granted explicitly to each user."
msgstr "项目访问æƒé™å¿…须明确授æƒç»™æ¯ä¸ªç”¨æˆ·ã€‚"
@@ -5628,6 +6309,9 @@ msgstr "项目导出已开始。下载链接将通过电å­é‚®ä»¶å‘é€ã€‚"
msgid "Project name"
msgstr "项目å称"
+msgid "Project slug"
+msgstr "项目标识串"
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "订阅"
@@ -5655,17 +6339,38 @@ msgstr "从未"
msgid "ProjectLifecycle|Stage"
msgstr "阶段"
+msgid "ProjectOverview|Fork"
+msgstr "派生"
+
+msgid "ProjectOverview|Forks"
+msgstr "派生"
+
+msgid "ProjectOverview|Go to your fork"
+msgstr "转至您的派生"
+
+msgid "ProjectOverview|Star"
+msgstr "星标"
+
+msgid "ProjectOverview|Unstar"
+msgstr "å–消星标"
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr "您已达到项目数é‡é™åˆ¶"
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr "登录åŽæ‰èƒ½æ˜Ÿæ ‡é¡¹ç›®"
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr "项目ID:%{project_id}"
msgid "ProjectSettings|Badges"
-msgstr ""
+msgstr "徽章"
msgid "ProjectSettings|Contact an admin to change this setting."
msgstr "è”系管ç†å‘˜æ›´æ”¹æ­¤è®¾ç½®ã€‚"
msgid "ProjectSettings|Customize your project badges."
-msgstr ""
+msgstr "自定义你的项目徽章。"
msgid "ProjectSettings|Failed to protect the tag"
msgstr "ä¿æŠ¤æ ‡ç­¾å¤±è´¥"
@@ -5674,7 +6379,7 @@ msgid "ProjectSettings|Failed to update tag!"
msgstr "更新标签失败ï¼"
msgid "ProjectSettings|Learn more about badges."
-msgstr ""
+msgstr "了解有关徽章的更多信æ¯ã€‚"
msgid "ProjectSettings|Only signed commits can be pushed to this repository."
msgstr "åªæœ‰å·²ç­¾ç½²æ交æ‰å¯ä»¥æŽ¨é€åˆ°æ­¤ä»“库。"
@@ -5697,6 +6402,9 @@ msgstr "项目"
msgid "Projects shared with %{group_name}"
msgstr "与 %{group_name} 共享的项目"
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr "ç»å¸¸è®¿é—®"
@@ -5716,7 +6424,7 @@ msgid "ProjectsDropdown|Sorry, no projects matched your search"
msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰æœç´¢åˆ°ç¬¦åˆæ¡ä»¶çš„项目"
msgid "ProjectsDropdown|This feature requires browser localStorage support"
-msgstr ""
+msgstr "此功能需è¦æµè§ˆå™¨æ”¯æŒæœ¬åœ°å­˜å‚¨"
msgid "PrometheusAlerts|Add alert"
msgstr "添加警报"
@@ -5766,9 +6474,6 @@ msgstr "自动é…ç½®"
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr "自动部署和é…ç½®Prometheus到集群æ¥ç›‘测项目的环境"
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr "默认情况下,Prometheus ä¾¦å¬ â€˜http://localhost:9090’。ä¸å»ºè®®æ›´æ”¹é»˜è®¤åœ°å€å’Œç«¯å£ï¼Œå› ä¸ºè¿™å¯èƒ½ä¼šå½±å“或冲çªåœ¨ GitLab æœåŠ¡å™¨ä¸Šè¿è¡Œçš„其他æœåŠ¡ã€‚"
-
msgid "PrometheusService|Common metrics"
msgstr "常用指标"
@@ -5815,7 +6520,7 @@ msgid "PrometheusService|These metrics will only be monitored after your first d
msgstr "在首次部署到环境之åŽ, 这些指标æ‰ä¼šè¢«ç›‘控"
msgid "PrometheusService|Time-series monitoring service"
-msgstr "时间åºåˆ—监控æœåŠ¡"
+msgstr "以时间为åºçš„监控æœåŠ¡"
msgid "PrometheusService|To enable manual configuration, uninstall Prometheus from your clusters"
msgstr "如需å¯ç”¨æ‰‹åŠ¨é…置,请从群集中å¸è½½Prometheus"
@@ -5857,7 +6562,7 @@ msgid "Protected Environments"
msgstr "å—ä¿æŠ¤çš„环境"
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
-msgstr ""
+msgstr "%{environment_name} 将对开å‘人员å¯å†™ã€‚确定继续å—?"
msgid "ProtectedEnvironment|Allowed to deploy"
msgstr "å…许部署"
@@ -5872,10 +6577,10 @@ msgid "ProtectedEnvironment|Protect"
msgstr "ä¿æŠ¤"
msgid "ProtectedEnvironment|Protect Environments in order to restrict who can execute deployments."
-msgstr "ä¿æŠ¤çŽ¯å¢ƒä»¥é™åˆ¶å¯æ‰§è¡Œéƒ¨ç½²çš„人员。"
+msgstr "ä¿æŠ¤éƒ¨ç½²çŽ¯å¢ƒä»¥é™åˆ¶å¯æ‰§è¡Œéƒ¨ç½²çš„人员身份。"
msgid "ProtectedEnvironment|Protect an environment"
-msgstr "ä¿æŠ¤çŽ¯å¢ƒ"
+msgstr "ä¿æŠ¤éƒ¨ç½²çŽ¯å¢ƒ"
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr "å—ä¿æŠ¤çš„环境 (%{protected_environments_count})"
@@ -5884,19 +6589,19 @@ msgid "ProtectedEnvironment|Select an environment"
msgstr "选择一个环境"
msgid "ProtectedEnvironment|There are currently no protected environments, protect an environment with the form above."
-msgstr ""
+msgstr "ç›®å‰æ²¡æœ‰å—ä¿æŠ¤çš„环境,请使用上述表å•ä¿æŠ¤éƒ¨ç½²çŽ¯å¢ƒã€‚"
msgid "ProtectedEnvironment|Unprotect"
-msgstr ""
+msgstr "å–消ä¿æŠ¤"
msgid "ProtectedEnvironment|Your environment can't be unprotected"
-msgstr ""
+msgstr "您的环境无法å—到ä¿æŠ¤"
msgid "ProtectedEnvironment|Your environment has been protected."
-msgstr ""
+msgstr "您的环境已å—到ä¿æŠ¤ã€‚"
msgid "ProtectedEnvironment|Your environment has been unprotected"
-msgstr ""
+msgstr "环境已ç»ä¸è¢«ä¿æŠ¤"
msgid "Protip:"
msgstr "专家æ示:"
@@ -5961,6 +6666,12 @@ msgstr "自述文件"
msgid "Real-time features"
msgstr "实时功能"
+msgid "Recent searches"
+msgstr "最近的æœç´¢"
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr "引用:"
@@ -5969,7 +6680,7 @@ msgstr "刷新"
msgid "Refreshing in a second to show the updated status..."
msgid_plural "Refreshing in %d seconds to show the updated status..."
-msgstr[0] ""
+msgstr[0] "%d 秒åŽåˆ·æ–°ä»¥æ˜¾ç¤ºæ›´æ–°çŠ¶æ€..."
msgid "Regenerate key"
msgstr "é‡æ–°ç”Ÿæˆå¯†é’¥"
@@ -6022,12 +6733,21 @@ msgstr "移除Runner"
msgid "Remove avatar"
msgstr "删除头åƒ"
+msgid "Remove group"
+msgstr "删除群组"
+
msgid "Remove priority"
msgstr "删除优先级"
msgid "Remove project"
msgstr "删除项目"
+msgid "Removed group can not be restored!"
+msgstr "已删除的群组无法æ¢å¤ï¼"
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr "删除群组将导致所有å­é¡¹ç›®å’Œèµ„æºè¢«åˆ é™¤ã€‚"
+
msgid "Rename"
msgstr "é‡å‘½å"
@@ -6037,6 +6757,9 @@ msgstr "é‡å‘½å文件"
msgid "Rename folder"
msgstr "é‡å‘½å文件夹"
+msgid "Reopen epic"
+msgstr "é‡æ–°å¼€å¯å²è¯—"
+
msgid "Repair authentication"
msgstr "ä¿®å¤è®¤è¯"
@@ -6046,18 +6769,33 @@ msgstr "直接回å¤æ­¤é‚®ä»¶æˆ– %{view_it_on_gitlab}。"
msgid "Repo by URL"
msgstr "从 URL 导入仓库"
+msgid "Report abuse to GitLab"
+msgstr "å‘GitLab举报滥用行为"
+
+msgid "Reporting"
+msgstr "报告"
+
msgid "Reports|%{failedString} and %{resolvedString}"
+msgstr "%{failedString} 和 %{resolvedString}"
+
+msgid "Reports|Actions"
msgstr ""
msgid "Reports|Class"
msgstr "ç±»"
+msgid "Reports|Confidence"
+msgstr "置信水平"
+
msgid "Reports|Execution time"
msgstr "执行时间"
msgid "Reports|Failure"
msgstr "失败"
+msgid "Reports|Severity"
+msgstr "严é‡æ€§"
+
msgid "Reports|System output"
msgstr "系统输出"
@@ -6070,8 +6808,11 @@ msgstr "测试摘è¦åŠ è½½å¤±è´¥"
msgid "Reports|Test summary results are being parsed"
msgstr "正在分æžæµ‹è¯•æ‘˜è¦"
+msgid "Reports|Vulnerability"
+msgstr "æ¼æ´ž"
+
msgid "Reports|no changed test results"
-msgstr ""
+msgstr "测试结果没有å˜åŒ–"
msgid "Repository"
msgstr "仓库"
@@ -6103,12 +6844,12 @@ msgstr "申请æƒé™"
msgid "Requests Profiles"
msgstr "请求分æž"
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr "è¦æ±‚此群组中的所有用户都å¯ç”¨åŒé‡è®¤è¯"
+
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "è¦æ±‚所有用户在访问GitLab时接å—æœåŠ¡æ¡æ¬¾å’Œéšç§æ”¿ç­–。"
-msgid "Reset git storage health information"
-msgstr "é‡ç½® Git 存储的è¿è¡ŒçŠ¶å†µä¿¡æ¯"
-
msgid "Reset health check access token"
msgstr "é‡ç½®è¿è¡ŒçŠ¶å†µæ£€æŸ¥è®¿é—®ä»¤ç‰Œ"
@@ -6124,9 +6865,21 @@ msgstr "在æºåˆ†æ”¯ä¸Šè§£å†³å†²çª"
msgid "Resolve discussion"
msgstr "解决讨论"
+msgid "Response metrics (AWS ELB)"
+msgstr "å“应指标(AWS ELB)"
+
msgid "Response metrics (Custom)"
msgstr "å“应指标(自定义)"
+msgid "Response metrics (HA Proxy)"
+msgstr "å“应指标(HA Proxy)"
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr "å“应指标(NGINX Ingress)"
+
+msgid "Response metrics (NGINX)"
+msgstr "å“应指标(NGINX)"
+
msgid "Resume"
msgstr "æ¢å¤"
@@ -6140,7 +6893,7 @@ msgid "Retry verification"
msgstr "é‡è¯•éªŒè¯"
msgid "Reveal Variables"
-msgstr ""
+msgstr "显示å˜é‡"
msgid "Reveal value"
msgid_plural "Reveal values"
@@ -6174,11 +6927,26 @@ msgid "Run CI/CD pipelines for external repositories"
msgstr "使用外部仓库的CI/CDæµæ°´çº¿"
msgid "Run untagged jobs"
-msgstr ""
+msgstr "è¿è¡Œæœªæ ‡è®°çš„作业"
+
+msgid "Runner cannot be assigned to other projects"
+msgstr "无法将Runner分é…给其他项目"
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr "Runnerå°†è¿è¡Œæ‰€æœ‰æœªæŒ‡å®šçš„项目的作业"
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr "Runnerå°†è¿è¡Œç¾¤ç»„中所有未指定项目的作业"
+
+msgid "Runner runs jobs from assigned projects"
+msgstr "Runnerå°†è¿è¡ŒæŒ‡å®šé¡¹ç›®çš„作业"
msgid "Runner token"
msgstr "Runner 令牌"
+msgid "Runner will not receive any new jobs"
+msgstr "Runnerä¸ä¼šæŽ¥å—新的作业"
+
msgid "Runners"
msgstr "Runner"
@@ -6188,6 +6956,12 @@ msgstr "Runners API"
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr "Runnerå¯ä»¥æ”¾åœ¨ä¸åŒçš„用户ã€æœåŠ¡å™¨ï¼Œç”šè‡³æœ¬åœ°æœºå™¨ä¸Šã€‚"
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr "Runnerå¯ä»¥æ”¾åœ¨ä¸åŒçš„用户ã€æœåŠ¡å™¨ï¼Œç”šè‡³æœ¬åœ°æœºå™¨ä¸Šã€‚"
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr "当å‰åœ¨çº¿Runner: %{active_runners_count}"
+
msgid "Runners page"
msgstr "è¿è¡Œå™¨é¡µé¢"
@@ -6195,7 +6969,7 @@ msgid "Runners page."
msgstr "è¿è¡Œå™¨é¡µé¢ã€‚"
msgid "Runners|You have used all your shared Runners pipeline minutes."
-msgstr ""
+msgstr "您已ç»ä½¿ç”¨äº†æ‰€æœ‰å…±äº«Runnerçš„æµæ°´çº¿æ—¶é—´ã€‚"
msgid "Running"
msgstr "è¿è¡Œä¸­"
@@ -6212,6 +6986,9 @@ msgstr "SAML å•ç‚¹ç™»å½•"
msgid "SAML Single Sign On Settings"
msgstr "SAML å•ç‚¹ç™»å½•è®¾ç½®"
+msgid "SAST"
+msgstr "SAST"
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr "SAML令牌签åè¯ä¹¦çš„SHA1指纹。请从身份验è¯æ供商处获å–(也å¯ä»¥è¢«ç§°ä¸ºâ€œæŒ‡çº¹â€ï¼‰ã€‚"
@@ -6236,6 +7013,9 @@ msgstr "ä¿å­˜åº”用"
msgid "Save changes"
msgstr "ä¿å­˜ä¿®æ”¹"
+msgid "Save changes before testing"
+msgstr "测试å‰ä¿å­˜æ›´æ”¹"
+
msgid "Save pipeline schedule"
msgstr "ä¿å­˜æµæ°´çº¿è®¡åˆ’"
@@ -6249,7 +7029,7 @@ msgid "Scheduled"
msgstr "已加入日程"
msgid "Schedules"
-msgstr "日程"
+msgstr "计划"
msgid "Scheduling Pipelines"
msgstr "æµæ°´çº¿è®¡åˆ’"
@@ -6290,23 +7070,32 @@ msgstr "æœç´¢åˆå¹¶è¯·æ±‚"
msgid "Search milestones"
msgstr "æœç´¢é‡Œç¨‹ç¢‘"
+msgid "Search or filter results..."
+msgstr "æœç´¢æˆ–过滤结果......"
+
msgid "Search or jump to…"
msgstr "æœç´¢æˆ–转到..."
msgid "Search project"
msgstr "æœç´¢é¡¹ç›®"
+msgid "Search projects"
+msgstr "æœç´¢é¡¹ç›®"
+
msgid "Search users"
msgstr "æœç´¢ç”¨æˆ·"
+msgid "Search your projects"
+msgstr "æœç´¢æ‚¨çš„项目"
+
msgid "SearchAutocomplete|All GitLab"
-msgstr "所有GitLab"
+msgstr "在整个 GitLab"
msgid "SearchAutocomplete|Issues I've created"
-msgstr "我创建的问题"
+msgstr "我创建的议题"
msgid "SearchAutocomplete|Issues assigned to me"
-msgstr "分é…给我的问题"
+msgstr "分é…给我的议题"
msgid "SearchAutocomplete|Merge requests I've created"
msgstr "我创建的åˆå¹¶è¯·æ±‚"
@@ -6315,7 +7104,7 @@ msgid "SearchAutocomplete|Merge requests assigned to me"
msgstr "分é…给我的åˆå¹¶è¯·æ±‚"
msgid "SearchAutocomplete|in all GitLab"
-msgstr ""
+msgstr "在整个 GitLab"
msgid "SearchAutocomplete|in this group"
msgstr "在此群组"
@@ -6323,14 +7112,8 @@ msgstr "在此群组"
msgid "SearchAutocomplete|in this project"
msgstr "在此项目"
-msgid "Seconds before reseting failure information"
-msgstr "é‡ç½®å¤±è´¥ä¿¡æ¯ç­‰å¾…时间(秒)"
-
-msgid "Seconds to wait for a storage access attempt"
-msgstr "等待存储访问å°è¯•æ—¶é—´(秒)"
-
-msgid "Secret:"
-msgstr "密ç :"
+msgid "Secret"
+msgstr "密ç "
msgid "Security"
msgstr "安全"
@@ -6338,16 +7121,51 @@ msgstr "安全"
msgid "Security Dashboard"
msgstr "安全仪表盘"
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
msgstr ""
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
+msgstr ""
+
+msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
+msgstr "安全仪表æ¿æ˜¾ç¤ºæœ€æ–°çš„安全报告。用它æ¥æŸ¥æ‰¾å’Œä¿®å¤æ¼æ´žã€‚"
+
msgid "SecurityDashboard|Monitor vulnerabilities in your code"
msgstr "监控代ç ä¸­çš„æ¼æ´ž"
@@ -6360,9 +7178,15 @@ msgstr "选择"
msgid "Select Archive Format"
msgstr "选择下载格å¼"
+msgid "Select a group to invite"
+msgstr "选择è¦é‚€è¯·çš„组"
+
msgid "Select a namespace to fork the project"
msgstr "选择一个命å空间æ¥æ´¾ç”Ÿé¡¹ç›®"
+msgid "Select a template repository"
+msgstr "选择模æ¿ä»“库"
+
msgid "Select a timezone"
msgstr "选择时区"
@@ -6393,8 +7217,11 @@ msgstr "选择æºåˆ†æ”¯"
msgid "Select target branch"
msgstr "选择目标分支"
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr "选择当å‰é¡¹ç›®çš„默认分支。除éžå¦è¡ŒæŒ‡å®šï¼Œå¦åˆ™æ‰€æœ‰åˆå¹¶è¯·æ±‚å’Œæ交都将指å‘此分支。"
+
msgid "Select the custom project template source group."
-msgstr ""
+msgstr "选择自定义项目模æ¿æºç»„。"
msgid "Selecting a GitLab user will add a link to the GitLab user in the descriptions of issues and comments (e.g. \"By <a href=\"#\">@johnsmith</a>\"). It will also associate and/or assign these issues and comments with the selected user."
msgstr "选中GitLab用户将在议题和评论的æ述中加入指å‘该GitLab用户的链接(例如“By <a href=\"#\">@johnsmith</a>â€ï¼‰ã€‚它还将与所选用户关è”å’Œ/或分é…这些议题和评论。"
@@ -6405,6 +7232,9 @@ msgstr "选择性åŒæ­¥"
msgid "Send email"
msgstr "å‘é€ç”µå­é‚®ä»¶"
+msgid "Send usage data"
+msgstr "å‘é€çš„使用情况数æ®"
+
msgid "Sep"
msgstr "ä¹"
@@ -6429,11 +7259,14 @@ msgstr "会è¯æœ‰æ•ˆæœŸï¼Œé¡¹ç›®é™åˆ¶åŠé™„件大å°ã€‚"
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "为账å·åˆ›å»ºä¸€ä¸ªç”¨äºŽæŽ¨é€æˆ–拉å–çš„ %{protocol} 密ç ã€‚"
+msgid "Set a template repository for projects in this group"
+msgstr "为该群组中的项目设置模æ¿ä»“库"
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr "设定缺çœåŠå—é™å¯è§æ€§çº§åˆ«ã€‚é…置导入æ¥æºåŠgit访问å议。"
msgid "Set instance-wide template repository"
-msgstr ""
+msgstr "设置实例范围的模æ¿å­˜å‚¨åº“"
msgid "Set max session time for web terminal."
msgstr "为Web终端设置最长会è¯æ—¶é—´ã€‚"
@@ -6447,26 +7280,47 @@ msgstr "设定用户登录的æ¡ä»¶ã€‚å¯ç”¨å¼ºåˆ¶åŒé‡è®¤è¯ã€‚"
msgid "Set up CI/CD"
msgstr "é…ç½® CI/CD"
-msgid "Set up Koding"
-msgstr "设置 Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr "手动设置%{type}Runner "
+
+msgid "Set up a specific Runner automatically"
+msgstr "自动创建专用Runner"
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr "æ ¹æ®%{docsLinkStart}文档%{icon}%{docsLinkEnd}设置断言/属性/声明(email,first_name,last_name)和NameID"
msgid "Set up your project to automatically push and/or pull changes to/from another repository. Branches, tags, and commits will be synced automatically."
-msgstr ""
+msgstr "设置项目以自动推é€å’Œ/或从å¦ä¸€ä¸ªå­˜å‚¨åº“中æå–更改。分支,标签和æ交将自动åŒæ­¥ã€‚"
msgid "SetPasswordToCloneLink|set a password"
msgstr "设置密ç "
-msgid "Settings"
-msgstr "设置"
+msgid "SetStatusModal|Add status emoji"
+msgstr "添加状æ€è¡¨æƒ…"
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
+msgstr "清除状æ€"
+
+msgid "SetStatusModal|Edit status"
+msgstr "编辑状æ€"
+
+msgid "SetStatusModal|Remove status"
+msgstr "删除状æ€"
+
+msgid "SetStatusModal|Set a status"
+msgstr "设置一个状æ€"
+
+msgid "SetStatusModal|Set status"
+msgstr "设置状æ€"
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
msgstr ""
-msgid "Set up a specific Runner automatically"
-msgstr "自动创建专用Runner"
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr "设置"
msgid "Share"
msgstr "分享"
@@ -6477,6 +7331,9 @@ msgstr "分享<strong>%{sso_label}</strong> 给组员,以便他们å¯ä»¥é€šè¿‡
msgid "Shared Runners"
msgstr "共享Runner"
+msgid "Shared projects"
+msgstr "已分享项目"
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr "通过é‡ç½®æ­¤å‘½å空间的æµæ°´çº¿åˆ†é’Ÿæ•°ï¼Œå½“å‰ä½¿ç”¨çš„分钟数将被归零。"
@@ -6559,12 +7416,18 @@ msgstr "é™æ€ç½‘站的大å°å’ŒåŸŸè®¾ç½®"
msgid "Slack application"
msgstr "Slack应用"
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
-msgstr ""
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
+msgstr "Slack集æˆå…许您通过èŠå¤©çª—å£ä¸­çš„shash命令与GitLab交互。"
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr "更慢,但能确ä¿é¡¹ç›®å·¥ä½œç©ºé—´ä¸ŽåŽŸå§‹ç‰ˆæœ¬ä¸€è‡´ï¼›å› å…¶å¯¹æ¯ä¸ªä½œä¸šå‡ä»Žå¤´å¼€å§‹å…‹éš†ä»“库"
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr "代ç ç‰‡æ®µ"
@@ -6578,10 +7441,10 @@ msgid "Something went wrong on our end. Please try again!"
msgstr "æœåŠ¡å™¨ç«¯å‡ºçŽ°é—®é¢˜ï¼Œè¯·é‡è¯•ã€‚"
msgid "Something went wrong trying to change the confidentiality of this issue"
-msgstr ""
+msgstr "试图改å˜è¿™ä¸ªè®®é¢˜çš„ç§å¯†æ€§æ—¶å‡ºçŽ°é”™è¯¯"
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
-msgstr ""
+msgstr "è¯•å›¾æ”¹å˜ %{issuableDisplayName} çš„é”定状æ€æ—¶å‡ºé”™äº†"
msgid "Something went wrong when toggling the button"
msgstr "点击按钮时出错"
@@ -6590,11 +7453,17 @@ msgid "Something went wrong while closing the %{issuable}. Please try again late
msgstr "关闭 %{issuable} 时出错。请ç¨åŽé‡è¯•"
msgid "Something went wrong while fetching %{listType} list"
-msgstr ""
+msgstr "åœ¨èŽ·å– %{listType} 列表时出错了"
+
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr "获å–评论时出错。请ç¨åŽé‡è¯•ã€‚"
msgid "Something went wrong while fetching group member contributions"
msgstr "获å–群组æˆå‘˜è´¡çŒ®æ—¶å‡ºé”™"
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr "获å–æ­¤åˆå¹¶è¯·æ±‚的环境时出错,请ç¨åŽé‡è¯•ã€‚"
+
msgid "Something went wrong while fetching the projects."
msgstr "拉å–项目时å‘生错误。"
@@ -6607,12 +7476,24 @@ msgstr "é‡æ–°å¼€å¯ %{issuable} 时出错。请ç¨åŽå†è¯•"
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr "解决当å‰è®¨è®ºæ—¶å‡ºé”™ï¼Œè¯·é‡è¯•ã€‚"
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr "将%{project} 添加到仪表盘时出错"
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr "获å–æ“作项目时出错"
+
+msgid "Something went wrong, unable to remove project"
+msgstr "删除项目时出错"
+
msgid "Something went wrong. Please try again."
msgstr "出现错误。请é‡è¯•ã€‚"
msgid "Sorry, no epics matched your search"
msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰æœç´¢åˆ°ä»»ä½•ç¬¦åˆæ¡ä»¶çš„å²è¯—故事"
+msgid "Sorry, no projects matched your search"
+msgstr "对ä¸èµ·ï¼Œæ²¡æœ‰æœç´¢åˆ°ä»»ä½•ç¬¦åˆæ¡ä»¶çš„项目"
+
msgid "Sort by"
msgstr "排åº"
@@ -6643,6 +7524,9 @@ msgstr "最大群组"
msgid "SortOptions|Largest repository"
msgstr "最大仓库"
+msgid "SortOptions|Last Contact"
+msgstr "最åŽè”系人"
+
msgid "SortOptions|Last created"
msgstr "最近创建"
@@ -6673,6 +7557,9 @@ msgstr "增加æƒé‡"
msgid "SortOptions|Most popular"
msgstr "最å—欢迎"
+msgid "SortOptions|Most stars"
+msgstr "最多星标"
+
msgid "SortOptions|Name"
msgstr "å称"
@@ -6703,6 +7590,9 @@ msgstr "优先"
msgid "SortOptions|Recent sign in"
msgstr "最近登录"
+msgid "SortOptions|Start date"
+msgstr "开始日期"
+
msgid "SortOptions|Start later"
msgstr "ç¨åŽå¼€å§‹"
@@ -6734,7 +7624,7 @@ msgid "Specific Runners"
msgstr "专用Runner"
msgid "Specify an e-mail address regex pattern to identify default internal users."
-msgstr ""
+msgstr "指定电å­é‚®ä»¶åœ°å€æ­£åˆ™è¡¨è¾¾å¼æ¨¡å¼ä»¥æ ‡è¯†é»˜è®¤å†…部用户。"
msgid "Specify the following URL during the Runner setup:"
msgstr "在 Runner 设置时指定以下 URL:"
@@ -6778,9 +7668,21 @@ msgstr "已星标项目"
msgid "Start a %{new_merge_request} with these changes"
msgstr "由此更改 %{new_merge_request}"
+msgid "Start a review"
+msgstr "开始一个评审"
+
+msgid "Start and due date"
+msgstr "开始和截止日期"
+
+msgid "Start date"
+msgstr "开始日期"
+
msgid "Start the Runner!"
msgstr "å¯åŠ¨ Runner!"
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr "å·²å¯åŠ¨"
@@ -6793,6 +7695,9 @@ msgstr "输入消æ¯ä»¥æ¿€æ´»"
msgid "Status"
msgstr "状æ€"
+msgid "Stop environment"
+msgstr "终止环境"
+
msgid "Stop impersonation"
msgstr "åœæ­¢èº«ä»½æ¨¡æ‹Ÿ"
@@ -6802,6 +7707,9 @@ msgstr "åœæ­¢å½“å‰çŽ¯å¢ƒ"
msgid "Stopped"
msgstr "å·²åœæ­¢"
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr "由于部署正在进行,目å‰æ— æ³•ç»ˆæ­¢æ­¤çŽ¯å¢ƒ"
+
msgid "Storage"
msgstr "存储"
@@ -6811,9 +7719,15 @@ msgstr "存储:"
msgid "Subgroups"
msgstr "å­ç¾¤ç»„"
+msgid "Subgroups and projects"
+msgstr "å­ç»„和项目"
+
msgid "Submit as spam"
msgstr "垃圾信æ¯ä¸¾æŠ¥"
+msgid "Submit review"
+msgstr "æ交评审"
+
msgid "Submit search"
msgstr "æ交æœç´¢"
@@ -6826,6 +7740,12 @@ msgstr "在群组级别订阅"
msgid "Subscribe at project level"
msgstr "在项目级别订阅"
+msgid "Subscribed"
+msgstr "已订阅"
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "切æ¢åˆ†æ”¯/标签"
@@ -6844,6 +7764,9 @@ msgstr "系统页头和页尾:"
msgid "System metrics (Custom)"
msgstr "系统指标(自定义)"
+msgid "System metrics (Kubernetes)"
+msgstr "系统指标(Kubernetes)"
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] "标签(%{tag_count})"
@@ -6852,7 +7775,7 @@ msgid "Tags"
msgstr "标签"
msgid "Tags feed"
-msgstr ""
+msgstr "标签动æ€"
msgid "Tags:"
msgstr "标签:"
@@ -6947,6 +7870,9 @@ msgstr "æœåŠ¡æ¡æ¬¾å议和éšç§æ”¿ç­–"
msgid "Terms of Service and Privacy Policy"
msgstr "æœåŠ¡æ¡æ¬¾å’Œéšç§æ”¿ç­–"
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "测试覆盖率解æž"
@@ -6957,7 +7883,7 @@ msgid "The Advanced Global Search in GitLab is a powerful search service that sa
msgstr "GitLab 中的高级全局æœç´¢åŠŸèƒ½æ˜¯ä¸€ä¸ªå¼ºå¤§ä¸”节çœæ‚¨çš„时间的æœç´¢æœåŠ¡ã€‚您å¯ä»¥æœç´¢å…¶ä»–团队的代ç ä»¥å¸®åŠ©æ‚¨å®Œå–„自己项目中的代ç ã€‚从而é¿å…创建é‡å¤çš„代ç æˆ–浪费时间。"
msgid "The Git LFS objects will <strong>not</strong> be synced."
-msgstr ""
+msgstr "Git LFS对象将<strong>ä¸ä¼š</strong>被åŒæ­¥ã€‚"
msgid "The Issue Tracker is the place to add things that need to be improved or solved in a project"
msgstr "议题跟踪用于管ç†éœ€æ±‚改进或者解决的问题"
@@ -6969,7 +7895,7 @@ msgid "The X509 Certificate to use when mutual TLS is required to communicate wi
msgstr "在需è¦ç›¸äº’ TLS 与外部授æƒæœåŠ¡é€šä¿¡æ—¶ä½¿ç”¨çš„ X509 è¯ä¹¦ã€‚如果ä¿ç•™ä¸ºç©º, 则在访问 HTTPS æ—¶ä»ç„¶éªŒè¯æœåŠ¡å™¨è¯ä¹¦ã€‚"
msgid "The character highlighter helps you keep the subject line to %{titleLength} characters and wrap the body at %{bodyLength} so they are readable in git."
-msgstr ""
+msgstr "字符çªå‡ºæ˜¾ç¤ºå™¨å¸®åŠ©æ‚¨å°†ä¸»é¢˜è¡Œä¿æŒä¸º %{titleLength} 字符并将正文包装为 %{bodyLength} 以便它们在git中å¯è¯»ã€‚"
msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
msgstr "ç¼–ç é˜¶æ®µæ¦‚述了从第一次æ交到创建åˆå¹¶è¯·æ±‚的时间。创建第一个åˆå¹¶è¯·æ±‚åŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„。"
@@ -6981,7 +7907,7 @@ msgid "The connection will time out after %{timeout}. For repositories that take
msgstr "该连接将在 %{timeout}åŽè¶…时。如仓库导入耗时超过该时间,请使用克隆/推é€ç»„åˆã€‚"
msgid "The deployment of this job to %{environmentLink} did not succeed."
-msgstr ""
+msgstr "将此作业部署为 %{environmentLink} 并未æˆåŠŸã€‚"
msgid "The fork relationship has been removed."
msgstr "派生关系已被删除。"
@@ -6995,12 +7921,6 @@ msgstr "议题阶段概述了从创建议题到将议题添加到里程碑或议
msgid "The maximum file size allowed is 200KB."
msgstr "文件大å°é™åˆ¶ä¸º 200KB。"
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr "GitLab 访问存储的次数。"
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr "访问存储最大失败次数,达到åŽå°†å¯¼è‡´GitLab完全阻止。å¯ä»¥åœ¨ç®¡ç†ç•Œé¢ä¸­é‡ç½®å¤±è´¥æ¬¡æ•°ï¼š %{link_to_health_page} 或使用 %{api_documentation_link} 。"
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "解密ç§é’¥æ‰€éœ€çš„密ç çŸ­è¯­ã€‚该项为å¯é€‰é¡¹, 并且内容被加密存储。"
@@ -7011,7 +7931,7 @@ msgid "The phase of the development lifecycle."
msgstr "项目生命周期中的å„个阶段。"
msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
-msgstr ""
+msgstr "针对特定分支或标签,æµæ°´çº¿è®¡åˆ’将在未æ¥é‡å¤è¿è¡Œæµæ°´çº¿ã€‚这些计划的æµæ°´çº¿å°†ä»Žå…³è”用户继承有é™çš„项目访问æƒé™ã€‚"
msgid "The planning stage shows the time from the previous step to pushing your first commit. This time will be added automatically once you push your first commit."
msgstr "计划阶段概述了从议题添加到日程到推é€é¦–次æ交的时间。当首次推é€æ交åŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„。"
@@ -7049,32 +7969,23 @@ msgstr "审阅阶段概述了从创建åˆå¹¶è¯·æ±‚到被åˆå¹¶çš„时间。当创
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr "路线图显示了å²è¯—故事沿ç€æ—¶é—´çº¿çš„进展情况"
-msgid "The secure token used by the Runner to checkout the project"
-msgstr "Runner用于签出项目的安全令牌"
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "预å‘布阶段概述了从åˆå¹¶è¯·æ±‚被åˆå¹¶åˆ°éƒ¨ç½²è‡³ç”Ÿäº§çŽ¯å¢ƒçš„总时间。首次部署到生产环境åŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„。"
msgid "The tabs below will be removed in a future version"
-msgstr ""
+msgstr "以下选项å¡å°†åœ¨ä»¥åŽçš„版本中删除"
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr "测试阶段概述了 GitLab CI 为相关åˆå¹¶è¯·æ±‚è¿è¡Œæ¯ä¸ªæµæ°´çº¿æ‰€éœ€çš„时间。当第一个æµæ°´çº¿è¿è¡Œå®ŒæˆåŽï¼Œæ•°æ®å°†è‡ªåŠ¨æ·»åŠ åˆ°æ­¤å¤„。"
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr "GitLab å°†ä¿æŒå¤±è´¥ä¿¡æ¯çš„时间(秒)。在此期间ä¸å‘生故障时,有关安装的信æ¯å°†é‡ç½®ã€‚"
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr "GitLab å°†å°è¯•è®¿é—®å­˜å‚¨çš„时间(秒)。在此时间之åŽå°†å¼•å‘超时错误。"
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr "存储检查之间的秒数。如果当å‰æ£€æŸ¥å°šæœªå®Œæˆï¼ŒGitLab将跳过下一次检查。"
-
msgid "The time taken by each data entry gathered by that stage."
msgstr "该阶段æ¯æ¡æ•°æ®æ‰€èŠ±çš„时间"
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
-msgstr ""
+msgstr "æ›´æ–°æ“作将在 %{number_of_minutes} 分钟åŽè¶…时。对于大型存储库,请使用clone/push组åˆã€‚"
+
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr "使用情况检测(usage ping)å·²ç¦ç”¨ï¼Œæ— æ³•é€šè¿‡æ­¤è¡¨å•è¿›è¡Œé…置。"
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr "用户映射是一个JSON文档,将å‚与项目的Google Code用户映射到他们将导入GitLab的电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·åçš„æ–¹å¼ã€‚您å¯ä»¥é€šè¿‡æ›´æ”¹ <code>:</code>å³ä¾§çš„值æ¥æ›´æ”¹æ­¤å€¼ã€‚请务必在左侧ä¿ç•™å‘¨å›´çš„åŒå¼•å·ï¼Œå…¶ä»–标点符å·ä»¥åŠç”µå­é‚®ä»¶åœ°å€æˆ–用户å。"
@@ -7085,6 +7996,9 @@ msgstr "用户映射是å‚与项目的 FogBugz 用户的电å­é‚®ä»¶åœ°å€å’Œç”¨
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "中ä½æ•°æ˜¯ä¸€ä¸ªæ•°åˆ—中最中间的值。例如在 3ã€5ã€9 之间,中ä½æ•°æ˜¯ 5。在 3ã€5ã€7ã€8 之间,中ä½æ•°æ˜¯ (5 + 7)/ 2 = 6。"
+msgid "There are no archived projects yet"
+msgstr "ç›®å‰è¿˜æ²¡æœ‰å·²å½’档的项目"
+
msgid "There are no issues to show"
msgstr "当å‰æ— è®®é¢˜"
@@ -7094,11 +8008,17 @@ msgstr "ç›®å‰è¿˜æ²¡æœ‰æ ‡ç­¾"
msgid "There are no merge requests to show"
msgstr "当å‰æ— åˆå¹¶è¯·æ±‚"
-msgid "There are problems accessing Git storage: "
-msgstr "访问 Git 存储时出现问题:"
+msgid "There are no projects shared with this group yet"
+msgstr "还没有与该群组共享的项目"
+
+msgid "There are no staged changes"
+msgstr "没有已暂存的修改"
+
+msgid "There are no unstaged changes"
+msgstr "没有未暂存的修改"
msgid "There was an error adding a todo."
-msgstr ""
+msgstr "添加待办事项时出现错误"
msgid "There was an error deleting the todo."
msgstr "删除待办事项时出现错误。"
@@ -7142,11 +8062,14 @@ msgstr "此看æ¿èŒƒå›´ç¼©å°äº†"
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr "自您开始编辑åŽ, 此分支已更改。您想创建一个新的分支å—?"
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
-msgstr ""
+msgid "This container registry has been scheduled for deletion."
+msgstr "此容器注册表已安排删除。"
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
-msgstr ""
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr "此日期在截止日期之åŽï¼Œå› æ­¤è¯¥å²è¯—故事ä¸ä¼šå‡ºçŽ°åœ¨è·¯çº¿å›¾ä¸­ã€‚"
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
+msgstr "此日期在开始日期之å‰ï¼Œå› æ­¤è¯¥å²è¯—故事ä¸ä¼šå‡ºçŽ°åœ¨è·¯çº¿å›¾ä¸­ã€‚"
msgid "This diff is collapsed."
msgstr "此差异已折å ã€‚"
@@ -7166,6 +8089,9 @@ msgstr "该群组未æ供任何群组Runner。"
msgid "This is a confidential issue."
msgstr "这是一个机密议题。"
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr "这是一个将在%{remainingTime}åŽè¿è¡Œçš„延时作业。"
+
msgid "This is the author's first Merge Request to this project."
msgstr "这是作者为当å‰é¡¹ç›®è´¡çŒ®çš„第一个åˆå¹¶è¯·æ±‚。"
@@ -7200,32 +8126,38 @@ msgid "This job has not started yet"
msgstr "作业还未开始"
msgid "This job is an out-of-date deployment to %{environmentLink}."
-msgstr ""
+msgstr "此项作业已过时,无法部署到 %{environmentLink}。"
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
-msgstr ""
+msgstr "此项作业已过时,无法部署到 %{environmentLink}。查看最新的部署 %{deploymentLink}。"
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr "这个作业已归档。åªèƒ½é‡è¯•æ•´ä¸ªæµæ°´çº¿ã€‚"
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
-msgstr ""
+msgstr "这项工作正在创建一个 %{environmentLink}的部署。"
msgid "This job is in pending state and is waiting to be picked by a runner"
msgstr "作业挂起中,等待进入队列"
msgid "This job is stuck, because you don't have any active runners online with any of these tags assigned to them:"
-msgstr ""
+msgstr "此作业已åœæ­¢ã€‚因为分é…有如下标签的Runner都ä¸åœ¨çº¿ï¼š"
msgid "This job is stuck, because you don't have any active runners that can run this job."
-msgstr ""
+msgstr "此作业已åœæ­¢ã€‚因为没有活动的Runnerå¯ä»¥å¤„ç†æ­¤é¡¹ä½œä¸šã€‚"
msgid "This job is the most recent deployment to %{link}."
-msgstr ""
+msgstr "此作业最近部署到 %{link}。"
msgid "This job requires a manual action"
msgstr "作业需手工æ“作"
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "在创建一个空的仓库或导入现有仓库之å‰ï¼Œå°†æ— æ³•æŽ¨é€ä»£ç ã€‚"
@@ -7233,7 +8165,7 @@ msgid "This merge request is locked."
msgstr "æ­¤åˆå¹¶è¯·æ±‚å·²é”定。"
msgid "This option is disabled as you don't have write permissions for the current branch"
-msgstr ""
+msgstr "由于您没有当å‰åˆ†æ”¯çš„写入æƒé™ï¼Œå› æ­¤ç¦ç”¨æ­¤é€‰é¡¹"
msgid "This option is disabled while you still have unstaged changes"
msgstr "有未暂存更改时此选项会被ç¦ç”¨ã€‚"
@@ -7250,29 +8182,38 @@ msgstr "当å‰é¡¹ç›®"
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr "该项目ä¸å±žäºŽä»»ä½•ç¾¤ç»„,因此ä¸èƒ½ä½¿ç”¨ç¾¤ç»„Runner。"
+msgid "This project does not have a wiki homepage yet"
+msgstr "该项目还没有wiki主页"
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
-msgstr ""
+msgstr "此项目未å¯ç”¨è´¦å•ã€‚è¦åˆ›å»ºç¾¤é›†ï¼Œè¯· <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">å¯ç”¨è´¦å• <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> 并é‡è¯•ã€‚"
msgid "This repository"
msgstr "当å‰ä»“库"
msgid "This runner will only run on pipelines triggered on protected branches"
-msgstr ""
+msgstr "æ­¤Runner仅在å—ä¿æŠ¤åˆ†æ”¯ä¸Šè§¦å‘çš„æµæ°´çº¿ä¸Šè¿è¡Œ"
+
+msgid "This setting can be overridden in each project."
+msgstr "当å‰è®¾ç½®å¯åœ¨æ¯ä¸ªé¡¹ç›®ä¸­è¿›è¡Œæ›´æ”¹è¦†ç›–。"
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr "此设置将更新用于生æˆç§æœ‰æ交电å­é‚®ä»¶çš„主机å。 %{learn_more}"
msgid "This source diff could not be displayed because it is too large."
msgstr "此代ç å·®å¼‚无法显示,因为它太大了。"
msgid "This timeout will take precedence when lower than Project-defined timeout"
-msgstr ""
+msgstr "当低于项目定义的超时时间时,此超时将优先"
msgid "This user has no identities"
msgstr "该用户没有身份标识"
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches."
-msgstr ""
+msgstr "此用户将æˆä¸ºæ´»åŠ¨æµä¸­æ‰€æœ‰äº‹ä»¶çš„作者,例如创建新分支或者推é€æ–°æ交到现有分支。"
msgid "This user will be the author of all events in the activity feed that are the result of an update, like new branches being created or new commits being pushed to existing branches. Upon creation or when reassigning you can only assign yourself to be the mirror user."
-msgstr ""
+msgstr "此用户将æˆä¸ºæ´»åŠ¨æµä¸­æ‰€æœ‰äº‹ä»¶çš„作者,例如创建新分支或者推é€æ–°æ交到现有分支。在创建或é‡æ–°æŒ‡å®šæ—¶æ‚¨ä»…å¯å°†è‡ªå·±æŒ‡å®šä¸ºé•œåƒç”¨æˆ·ã€‚"
msgid "This will delete the custom metric, Are you sure?"
msgstr "æ­¤æ“作将删除自定义指标,确定继续å—?"
@@ -7286,9 +8227,15 @@ msgstr "议题被列入日程表的时间"
msgid "Time before an issue starts implementation"
msgstr "开始进行编ç å‰çš„时间"
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr "从创建åˆå¹¶è¯·æ±‚到被åˆå¹¶æˆ–关闭的时间"
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr "GitLab等待外部æœåŠ¡çš„å“应时间(秒)。当æœåŠ¡æ²¡æœ‰åŠæ—¶å“应时,访问将被拒ç»ã€‚"
@@ -7475,14 +8422,26 @@ msgid "To connect an SVN repository, check out %{svn_link}."
msgstr "如è¦è¿žæŽ¥SVN仓库,请查看 %{svn_link}。"
msgid "To define internal users, first enable new users set to external"
-msgstr ""
+msgstr "è¦å®šä¹‰å†…部用户,请首先å¯ç”¨è®¾ç½®ä¸ºå¤–部的新用户"
+
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr "è¦å¯ç”¨å®ƒå¹¶æŸ¥çœ‹ç”¨æˆ·ä¸–代表,请访问 %{application_settings_link_start}应用程åºè®¾ç½®%{application_settings_link_end}。"
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr "首先请在下é¢è¾“入您的FogBugz URL和登录信æ¯ã€‚下一步,您将å¯ä»¥æ˜ å°„用户并选择è¦å¯¼å…¥çš„项目。"
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr "首先请将本页é¢ä¸Žæ‚¨çš„ Jaeger æœåŠ¡å™¨è¿žæŽ¥ï¼Œæˆ–者了解一下如何%{link_start_tag}安装 Jaeger%{link_end_tag}"
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr "首先,请您输入您的 Gitea æœåŠ¡å™¨åœ°å€å’Œä¸€ä¸ª %{link_to_personal_token}。"
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr "为了帮助改进 GitLab åŠå…¶ç”¨æˆ·ä½“验, GitLab 将定期收集使用信æ¯ã€‚"
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr "为了帮助改进GitLab,我们希望定期收集使用信æ¯ã€‚è¿™å¯ä»¥é€šè¿‡ %{settings_link_start}设置%{link_end}éšæ—¶æ›´æ”¹ã€‚ %{info_link_start}更多信æ¯%{link_end}"
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr "å¯ä»¥ä½¿ç”¨ %{personal_access_token_link}导入GitHub仓库。当创建个人访问令牌时,需è¦é€‰æ‹© <code>repo</code> 范围,以显示å¯å¯¼å…¥çš„公共和ç§æœ‰çš„仓库列表。"
@@ -7498,6 +8457,9 @@ msgstr "如需将整个GitLab项目从å¦ä¸€ä¸ªGitLabæœåŠ¡å™¨ç§»åŠ¨æˆ–å¤åˆ¶åˆ°
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr "è¦ä»…为外部仓库使用CI / CD功能时,请选择</strong>使用外部仓库è¿è¡ŒCI/CD<strong>。"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr "请将%{start_tag}跟踪%{end_tag}页é¢è¿žæŽ¥åˆ°æ‚¨çš„ Jaeger æœåŠ¡å™¨ï¼Œä»¥ä¾¿åœ¨ GitLab 打开并轻æ¾æŸ¥çœ‹è·Ÿè¸ª"
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr "通过Azure,Okta,Onelogin,Ping Identity或自定义SAML 2.0等身份验è¯ç¨‹åºä¸ºæ‚¨çš„群组设置SAML身份验è¯ï¼š"
@@ -7510,12 +8472,15 @@ msgstr "转至此GitLab实例"
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr "如需验è¯GitLab CI设置,请访问当å‰é¡¹ç›®çš„'CI/CD → æµæ°´çº¿',然åŽç‚¹å‡»'CI Lint'按钮。"
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
-msgstr "如需查看路线图,请将计划的开始或结æŸæ—¥æœŸæ·»åŠ åˆ°å½“å‰ç¾¤ç»„或其å­ç»„中的æŸä¸ªå²è¯—故事。åªæ˜¾ç¤ºè¿‡åŽ»3个月和接下æ¥3个月的å²è¯—故事。"
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr "如需查看路线图,请将计划的开始或结æŸæ—¥æœŸæ·»åŠ åˆ°å½“å‰ç¾¤ç»„或其å­ç»„中的æŸä¸ªå²è¯—故事。在月视图中,åªæ˜¾ç¤ºä¸Šä¸ªæœˆï¼Œæœ¬æœˆä»¥åŠæŽ¥ä¸‹æ¥5个月的å²è¯—故事."
msgid "To widen your search, change or remove filters."
msgstr "需è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–移除过滤æ¡ä»¶ã€‚"
+msgid "Today"
+msgstr "今日"
+
msgid "Todo"
msgstr "待办事项"
@@ -7525,9 +8490,15 @@ msgstr "待办事项"
msgid "Toggle Sidebar"
msgstr "切æ¢ä¾§è¾¹æ "
+msgid "Toggle commit description"
+msgstr "切æ¢æ交æè¿°"
+
msgid "Toggle discussion"
msgstr "开关讨论"
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "切æ¢å¯¼èˆª"
@@ -7543,6 +8514,9 @@ msgstr "切æ¢çŠ¶æ€ï¼šå¼€å¯"
msgid "Token"
msgstr "令牌"
+msgid "Tomorrow"
+msgstr "明日"
+
msgid "Too many changes to show."
msgstr "è¦æ˜¾ç¤ºçš„å˜æ›´å¤ªå¤šã€‚"
@@ -7558,6 +8532,9 @@ msgstr "所有æ交和åˆå¹¶çš„总测试时间"
msgid "Total: %{total}"
msgstr "总计:%{total}"
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr "通过贡献度分æžäº†è§£ç”¨æˆ·æ´»è·ƒåº¦ã€‚"
@@ -7567,6 +8544,9 @@ msgstr "在ä¸åŒé¡¹ç›®å’Œé‡Œç¨‹ç¢‘中跟踪具有åŒä¸€ä¸»é¢˜çš„议题组"
msgid "Track time with quick actions"
msgstr "使用快æ·æ“作æ¥ç»Ÿè®¡å·¥æ—¶"
+msgid "Tree view"
+msgstr "树形视图"
+
msgid "Trending"
msgstr "趋势"
@@ -7574,10 +8554,10 @@ msgid "Trigger"
msgstr "触å‘器"
msgid "Trigger pipelines for mirror updates"
-msgstr ""
+msgstr "触å‘é•œåƒæ›´æ–°çš„æµæ°´çº¿"
msgid "Trigger pipelines when branches or tags are updated from the upstream repository. Depending on the activity of the upstream repository, this may greatly increase the load on your CI runners. Only enable this if you know they can handle the load."
-msgstr ""
+msgstr "从上游存储库更新分支或标记时触å‘æµæ°´çº¿ã€‚如果上游存储库更新频ç¹ï¼Œè¿™å¯èƒ½ä¼šå¤§å¤§å¢žåŠ CI Runnerçš„è´Ÿè·ã€‚åªæœ‰å½“你知é“CI Runner的处ç†èƒ½åŠ›èƒ½å¤Ÿæ‰¿å—这样的负è·æ—¶ï¼Œä½ æ‰åº”å¯ç”¨æ­¤åŠŸèƒ½ã€‚"
msgid "Trigger this manual action"
msgstr "触å‘此手动æ“作"
@@ -7585,24 +8565,42 @@ msgstr "触å‘此手动æ“作"
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr "触å‘器å¯ä»¥é€šè¿‡ API 调用使特定的分支或标记被é‡æ–°æž„建,这些 token å¯ä»£è¡¨ä¸Žå…¶å…³è”的用户(包括该用户对项目的访问æƒé™ï¼‰"
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr "使用跟踪对应用程åºè¿›è¡Œæ•…障排除与监控"
+
msgid "Try again"
msgstr "请é‡è¯•"
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "å¯ç”¨æœåŠ¡å°"
msgid "Twitter"
msgstr "Twitter"
+msgid "Two-factor authentication"
+msgstr "åŒé‡è®¤è¯"
+
msgid "Type"
msgstr "类型"
msgid "Unable to load the diff. %{button_try_again}"
msgstr "无法加载差异。 %{button_try_again}"
+msgid "Unable to save your changes"
+msgstr "无法ä¿å­˜æ›´æ”¹"
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "由于\"%{reason}\"的原因,您暂时ä¸èƒ½è¿›å…¥é…置了SAML 的群组"
+msgid "Unable to update this epic at this time."
+msgstr "当å‰æ— æ³•æ›´æ–°æ­¤å²è¯—故事。"
+
+msgid "Undo"
+msgstr "撤消"
+
msgid "Unknown"
msgstr "未知的"
@@ -7610,7 +8608,7 @@ msgid "Unlock"
msgstr "解é”"
msgid "Unlock this %{issuableDisplayName}? <strong>Everyone</strong> will be able to comment."
-msgstr ""
+msgstr "è§£é” %{issuableDisplayName} ? <strong>所有人</strong> 都将å¯ä»¥å‘表评论。"
msgid "Unlocked"
msgstr "已解é”"
@@ -7618,6 +8616,12 @@ msgstr "已解é”"
msgid "Unresolve discussion"
msgstr "待解决的讨论"
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr "å–消暂存"
+
msgid "Unstage all changes"
msgstr "å–消全部暂存更改"
@@ -7651,14 +8655,17 @@ msgstr "未验è¯"
msgid "Up to date"
msgstr "已是最新"
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr "æ›´æ–°"
msgid "Update now"
msgstr "ç«‹å³æ›´æ–°"
-msgid "Update your group name, description, avatar, and other general settings."
-msgstr "更新您的群组å称ã€è¯´æ˜Žã€å¤´åƒä»¥åŠå…¶å®ƒé€šç”¨è®¾ç½®ã€‚"
+msgid "Update your group name, description, avatar, and visibility."
+msgstr "更新您的群组å称ã€è¯´æ˜Žã€å¤´åƒä»¥åŠå¯è§æ€§ã€‚"
msgid "Updating"
msgstr "更新中"
@@ -7687,15 +8694,15 @@ msgstr "上传新文件"
msgid "Upload file"
msgstr "上传文件"
-msgid "Upload new avatar"
-msgstr "上传新头åƒ"
-
msgid "UploadLink|click to upload"
msgstr "点击上传"
msgid "Upvotes"
msgstr "顶"
+msgid "Usage ping is not enabled"
+msgstr "使用情况检测(usage ping)未å¯ç”¨"
+
msgid "Usage statistics"
msgstr "使用情况统计"
@@ -7723,6 +8730,9 @@ msgstr "使用全局通知设置"
msgid "Used by members to sign in to your group in GitLab"
msgstr "ä¾›æˆå‘˜ç™»å½•æ‚¨çš„GitLab群组"
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr "用户世代表仅在å¯ç”¨ %{usage_ping_link_start}使用情况检测(usage ping)%{usage_ping_link_end} 时显示。"
+
msgid "User Settings"
msgstr "用户设置"
@@ -7732,12 +8742,54 @@ msgstr "用户和IP频率é™åˆ¶"
msgid "User map"
msgstr "用户映射"
+msgid "UserProfile|Activity"
+msgstr "活动"
+
+msgid "UserProfile|Already reported for abuse"
+msgstr "已报告滥用"
+
+msgid "UserProfile|Contributed projects"
+msgstr "å‚与贡献的项目"
+
+msgid "UserProfile|Edit profile"
+msgstr "编辑个人资料"
+
+msgid "UserProfile|Groups"
+msgstr "群组"
+
+msgid "UserProfile|Most Recent Activity"
+msgstr "最新活动"
+
+msgid "UserProfile|Overview"
+msgstr "概览"
+
+msgid "UserProfile|Personal projects"
+msgstr "个人项目"
+
+msgid "UserProfile|Recent contributions"
+msgstr "最新贡献"
+
+msgid "UserProfile|Report abuse"
+msgstr "举报滥用行为"
+
+msgid "UserProfile|Snippets"
+msgstr "片段"
+
+msgid "UserProfile|Subscribe"
+msgstr "关注"
+
+msgid "UserProfile|This user has a private profile"
+msgstr "此用户具有éžå…¬å¼€ä¸ªäººèµ„料设置"
+
+msgid "UserProfile|View all"
+msgstr "查看全部"
+
+msgid "UserProfile|View user in admin area"
+msgstr "在管ç†åŒºåŸŸä¸­æŸ¥çœ‹ç”¨æˆ·"
+
msgid "Users"
msgstr "用户"
-msgid "User|Current status"
-msgstr ""
-
msgid "Variables"
msgstr "å˜é‡"
@@ -7762,6 +8814,15 @@ msgstr "已验è¯"
msgid "Version"
msgstr "版本"
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr "查看文档"
+
msgid "View epics list"
msgstr "查看å²è¯—故事列表"
@@ -7795,9 +8856,15 @@ msgstr "查看项目标记"
msgid "View replaced file @ "
msgstr "查看替æ¢æ–‡ä»¶ @ "
+msgid "View the documentation"
+msgstr "查看文档"
+
msgid "Visibility and access controls"
msgstr "å¯è§æ€§ä¸Žè®¿é—®æŽ§åˆ¶"
+msgid "Visibility level"
+msgstr "å¯è§æ€§çº§åˆ«"
+
msgid "Visibility level:"
msgstr "å¯è§æ€§çº§åˆ«:"
@@ -7816,6 +8883,36 @@ msgstr "公开"
msgid "VisibilityLevel|Unknown"
msgstr "未知"
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "æƒé™ä¸è¶³ã€‚如需查看相关数æ®ï¼Œè¯·å‘管ç†å‘˜ç”³è¯·æƒé™ã€‚"
@@ -7855,6 +8952,12 @@ msgstr "该项å¯ç”¨åŽï¼Œç”¨æˆ·åœ¨æŽ¥å—æ¡æ¬¾è¢«å‰å°†ä¸èƒ½ä½¿ç”¨GitLab。"
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "å°†URLä¿ç•™ä¸ºç©ºç™½æ—¶ï¼Œä»å¯æŒ‡å®šåˆ†ç±»æ ‡ç­¾ï¼Œè€Œæ— éœ€ç¦ç”¨è·¨é¡¹ç›®åŠŸèƒ½æˆ–执行外部授æƒæ£€æŸ¥ã€‚"
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr "Wiki"
@@ -7958,7 +9061,7 @@ msgid "WikiPageEdit|Update %{page_title}"
msgstr "æ›´æ–° %{page_title}"
msgid "WikiPage|Page slug"
-msgstr "页é¢å—"
+msgstr "页é¢æ ‡è¯†ä¸²"
msgid "WikiPage|Write your content or drag files here…"
msgstr "在这里编写您的内容或将文件拖动到此处..."
@@ -8005,6 +9108,9 @@ msgstr "是的,添加它"
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr "是的,让我将Google Code用户映射到全å或GitLab用户。"
+msgid "Yesterday"
+msgstr "昨天"
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr "您是一å管ç†å‘˜ï¼Œè¿™æ„味ç€æŽˆäºˆå¯¹ <strong>%{client_name}</strong> 访问æƒé™å°†å…许他们作为管ç†å‘˜ä¸ŽGitLab进行交互。请谨慎æ“作。"
@@ -8023,9 +9129,6 @@ msgstr "å°†è¦æŠŠ %{project_full_name} 转移给å¦ä¸€ä¸ªæ‰€æœ‰è€…。确定执è¡
msgid "You are on a read-only GitLab instance."
msgstr "当å‰æ­£åœ¨è®¿é—®åªè¯» GitLab 实例。"
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr "当å‰æ­£åœ¨è®¿é—®Geo次è¦(åªè¯») 节点。如需进行任何写入æ“作,必须访问%{primary_node}。"
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr "您å¯ä»¥ %{linkStart}查看BLOB%{linkEnd} 代替。"
@@ -8035,9 +9138,6 @@ msgstr "您也å¯ä»¥é€šè¿‡å‘½ä»¤è¡Œæ¥åˆ›å»ºæ–°é¡¹ç›®ã€‚"
msgid "You can also star a label to make it a priority label."
msgstr "å¯ä»¥é€šè¿‡ä¸ºæ ‡è®°è®¾ç½®æ˜Ÿæ ‡æ¥æ高其优先级。"
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr "您也å¯ä»¥é€šè¿‡%{linkStart}Lint%{linkEnd}测试.gitlab-ci.yml"
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr "您å¯ä»¥è¯·æ±‚加入这些群组,以便为群组项目åšå‡ºè´¡çŒ®ã€‚"
@@ -8057,7 +9157,10 @@ msgid "You can resolve the merge conflict using either the Interactive mode, by
msgstr "您å¯ä»¥ä½¿ç”¨äº¤äº’模å¼ï¼Œé€šè¿‡é€‰æ‹© %{use_ours} 或 %{use_theirs} 按钮æ¥è§£å†³åˆå¹¶å†²çªã€‚也å¯ä»¥é€šè¿‡ç›´æŽ¥ç¼–辑文件æ¥è§£å†³åˆå¹¶å†²çªã€‚然åŽå°†è¿™äº›æ›´æ”¹æ交到 %{branch_name}"
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
-msgstr ""
+msgstr "您å¯ä»¥å°†ä½œä¸šè®¾ç½®ä¸ºä»…使用具有特定标签的Runners。请使用逗å·åˆ†éš”ä¸åŒæ ‡ç­¾ã€‚"
+
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr "您也å¯ä»¥é€šè¿‡%{linkStart}Lint%{linkEnd}测试.gitlab-ci.yml."
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr "您ä¸èƒ½å†™å…¥åªè¯»çš„æ¬¡è¦ GitLab Geo 实例。请改用%{link_to_primary_node}。"
@@ -8065,6 +9168,9 @@ msgstr "您ä¸èƒ½å†™å…¥åªè¯»çš„æ¬¡è¦ GitLab Geo 实例。请改用%{link_to_pr
msgid "You cannot write to this read-only GitLab instance."
msgstr "您ä¸èƒ½å†™å…¥è¿™ä¸ªåªè¯»çš„ GitLab 实例。"
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "您没有正确的æƒé™æ¥æ›´æ”¹LDAP组åŒæ­¥ä¸­çš„设置。"
@@ -8086,9 +9192,6 @@ msgstr "您必须接å—我们的æœåŠ¡æ¡æ¬¾å’Œéšç§æ”¿ç­–æ‰èƒ½æ³¨å†Œå¸æˆ·"
msgid "You must have maintainer access to force delete a lock"
msgstr "必须拥有维护者æƒé™æ‰èƒ½å¼ºåˆ¶åˆ é™¤é”"
-msgid "You must sign in to star a project"
-msgstr "必须登录æ‰èƒ½å¯¹é¡¹ç›®åŠ æ˜Ÿæ ‡"
-
msgid "You need a different license to enable FileLocks feature"
msgstr "需è¦ä½¿ç”¨ä¸Žå½“å‰ä¸åŒçš„许å¯(license) æ‰èƒ½å¯ç”¨FileLocks功能"
@@ -8098,6 +9201,12 @@ msgstr "您需è¦git-lfs版本 %{min_git_lfs_version} (或更高版本)æ‰èƒ
msgid "You need permission."
msgstr "需è¦ç›¸å…³çš„æƒé™ã€‚"
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr "您将丢失对此文件所åšçš„所有更改。此æ“作无法撤消。"
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr "您将丢失在此项目中所åšçš„所有未暂存的修改,此æ“作无法撤消。"
+
msgid "You will not get any notifications via email"
msgstr "ä¸ä¼šæ”¶åˆ°ä»»ä½•é€šçŸ¥é‚®ä»¶"
@@ -8164,6 +9273,9 @@ msgstr "åˆå¹¶è¯·æ±‚已开å¯ï¼Œå¯ä»¥æ交å˜æ›´åˆ°%{branch_name}。"
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr "更改已æ交。æ交 %{commitId} %{commitStats}"
+msgid "Your changes have been saved"
+msgstr "您的更改已ä¿å­˜"
+
msgid "Your comment will not be visible to the public."
msgstr "您的评论将ä¸ä¼šå…¬å¼€æ˜¾ç¤ºã€‚"
@@ -8185,14 +9297,6 @@ msgstr "å‰"
msgid "among other things"
msgstr "åŠå…¶ä»–功能"
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] "å’Œ %d 个已修å¤æ¼æ´ž"
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] "åŠ%d个已修å¤çš„æ¼æ´ž"
-
msgid "assign yourself"
msgstr "分é…给自己"
@@ -8220,20 +9324,51 @@ msgstr "ciReport|%{namespace} å— %{vulnerability} å½±å“。"
msgid "ciReport|%{remainingPackagesCount} more"
msgstr "还有%{remainingPackagesCount} 个"
-msgid "ciReport|%{reportName} is loading"
-msgstr "%{reportName} 加载中"
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] "%{reportType} %{status} 检测到%{fixedCount}个安全æ¼æ´žå·²ä¿®å¤ã€‚"
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] "%{reportType} %{status} 检测到%{newCount}个新的安全æ¼æ´žã€‚"
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr "%{reportType} %{status} 检测到 %{newCount} 新的安全æ¼æ´žå’Œ %{fixedCount} 个已修å¤æ¼æ´ž"
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] "%{reportType} %{status} 检测到æºåˆ†æ”¯æœ‰%{newCount} 个安全æ¼æ´ž"
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr "%{reportType} %{status} 未å‘现新的安全æ¼æ´ž"
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr "%{reportType} %{status} 未å‘现安全æ¼æ´ž"
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr "%{reportType} %{status} 检测到æºåˆ†æ”¯æ²¡æœ‰å®‰å…¨æ¼æ´ž"
-msgid "ciReport|%{reportName} resulted in error while loading results"
-msgstr "加载%{reportName} 时出错"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] "%{reportType}检测到%{vulnerabilityCount}个æ¼æ´ž"
-msgid "ciReport|%{type} detected no new security vulnerabilities"
-msgstr "%{type} 未å‘现新的安全æ¼æ´ž"
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr "%{reportType} 未å‘现安全æ¼æ´ž"
-msgid "ciReport|%{type} detected no security vulnerabilities"
-msgstr "%{type} 未å‘现安全æ¼æ´ž"
+msgid "ciReport|%{reportType} is loading"
+msgstr "%{reportType} 加载中"
-msgid "ciReport|%{type} detected no vulnerabilities"
-msgstr "%{type} 未å‘现安全æ¼æ´ž"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr "%{reportType}:å‘生一个错误"
+
+msgid "ciReport|(errors when loading results)"
+msgstr "(加载结果时出错)"
+
+msgid "ciReport|(is loading)"
+msgstr "(加载中)"
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr "(正在加载,加载结果时出错)"
msgid "ciReport|Class"
msgstr "ç±»"
@@ -8244,38 +9379,20 @@ msgstr "代ç è´¨é‡"
msgid "ciReport|Confidence"
msgstr "置信水平"
-msgid "ciReport|Container scanning detected"
-msgstr "容器安全扫æ检测到"
+msgid "ciReport|Container scanning"
+msgstr "容器安全扫æ"
msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr "容器扫æå¯ä»¥æ£€æµ‹Dockeré•œåƒä¸­ä¸­å·²çŸ¥çš„安全æ¼æ´žã€‚"
-msgid "ciReport|Container scanning is loading"
-msgstr "容器安全扫æ加载中"
-
-msgid "ciReport|Container scanning resulted in error while loading results"
-msgstr "加载容器扫æ结果时出错"
-
-msgid "ciReport|DAST detected"
-msgstr "DAST检测到"
-
-msgid "ciReport|DAST is loading"
-msgstr "DAST加载中"
-
-msgid "ciReport|DAST resulted in error while loading results"
-msgstr "加载DAST结果时出错"
+msgid "ciReport|DAST"
+msgstr "DAST"
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr "ä¾èµ–项扫æå¯ä»¥æ£€æµ‹æºä»£ç ä¾èµ–项中已知的æ¼æ´žã€‚"
-msgid "ciReport|Dependency scanning detected"
-msgstr "ä¾èµ–关系扫æ检测到"
-
-msgid "ciReport|Dependency scanning is loading"
-msgstr "ä¾èµ–项扫æ加载中"
-
-msgid "ciReport|Dependency scanning resulted in error while loading results"
-msgstr "加载ä¾èµ–项扫æ结果时出错"
+msgid "ciReport|Dependency scanning"
+msgstr "ä¾èµ–项扫æ"
msgid "ciReport|Description"
msgstr "说明"
@@ -8307,19 +9424,16 @@ msgstr "实例"
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr "了解有关安全报告(Alpha)的更多信æ¯ã€‚"
-msgid "ciReport|Learn more about whitelisting"
-msgstr "了解更多关于白åå•çš„ä¿¡æ¯"
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
-msgstr[0] ""
+msgstr[0] "许å¯è¯ç®¡ç†ä»…检测到æºåˆ†æ”¯çš„ %d 许å¯è¯"
msgid "ciReport|License management detected %d new license"
msgid_plural "ciReport|License management detected %d new licenses"
msgstr[0] "许å¯è¯ç®¡ç†æ£€æµ‹åˆ° %d 个新的许å¯è¯"
msgid "ciReport|License management detected no licenses for the source branch only"
-msgstr ""
+msgstr "许å¯è¯ç®¡ç†ä»…未检测到æºåˆ†æ”¯ä¸Šçš„许å¯è¯"
msgid "ciReport|License management detected no new licenses"
msgstr "许å¯è¯ç®¡ç†æœªæ£€æµ‹åˆ°æ–°çš„许å¯è¯"
@@ -8330,6 +9444,9 @@ msgstr "链接"
msgid "ciReport|Loading %{reportName} report"
msgstr "载入%{reportName} 报告"
+msgid "ciReport|Manage licenses"
+msgstr "管ç†è®¸å¯"
+
msgid "ciReport|Method"
msgstr "方法"
@@ -8348,14 +9465,8 @@ msgstr "性能指标"
msgid "ciReport|Revert dismissal"
msgstr "å–消忽略"
-msgid "ciReport|SAST detected"
-msgstr "SAST检测到"
-
-msgid "ciReport|SAST is loading"
-msgstr "SAST加载中"
-
-msgid "ciReport|SAST resulted in error while loading results"
-msgstr "加载SAST结果时出错"
+msgid "ciReport|SAST"
+msgstr "SAST"
msgid "ciReport|Security scanning"
msgstr "安全扫æ"
@@ -8363,9 +9474,6 @@ msgstr "安全扫æ"
msgid "ciReport|Security scanning failed loading any results"
msgstr "安全扫æ无法加载任何结果"
-msgid "ciReport|Security scanning is loading"
-msgstr "安全扫æ加载中"
-
msgid "ciReport|Severity"
msgstr "严é‡æ€§"
@@ -8396,22 +9504,16 @@ msgstr "加载ä¾èµ–项扫æ报告时出错"
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "å–消忽略æ“作时å‘生错误。请å†è¯•ä¸€æ¬¡ã€‚"
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr "未批准的æ¼æ´ž (红色) å¯ä»¥æ ‡è®°ä¸ºå·²æ‰¹å‡†ã€‚"
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr "å°† %{name} 从 %{version} å‡çº§åˆ° %{fixed}。"
msgid "ciReport|Used by %{packagesString}"
msgid_plural "ciReport|Used by %{packagesString}, and %{lastPackage}"
-msgstr[0] ""
+msgstr[0] "已用于 %{packagesString} 和 %{lastPackage}"
msgid "ciReport|View full report"
msgstr "查看完整报告"
-msgid "ciReport|no vulnerabilities"
-msgstr "未检测到安全æ¼æ´ž"
-
msgid "ciReport|on pipeline"
msgstr "于æµæ°´çº¿"
@@ -8419,10 +9521,10 @@ msgid "command line instructions"
msgstr "命令行指å—"
msgid "confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue."
-msgstr ""
+msgstr "å³å°†å…³é—­ç§å¯†æ€§ã€‚这将使得 <strong>所有用户</strong>都å¯ä»¥æŸ¥çœ‹å¹¶ä¸”评论当å‰è®®é¢˜ã€‚"
msgid "confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue."
-msgstr ""
+msgstr "å³å°†è®¾ç½®ç§å¯†æ€§ã€‚这将使得 <strong>至少有Reporter以上æƒé™</strong>的团队æˆå‘˜æ‰èƒ½æŸ¥çœ‹å¹¶ä¸”评论当å‰è®®é¢˜ã€‚"
msgid "connecting"
msgstr "连接中"
@@ -8440,23 +9542,16 @@ msgstr[0] "天"
msgid "deploy token"
msgstr "部署令牌"
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] "检测到%d个安全æ¼æ´žå·²ä¿®å¤"
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] "检测到%d个新的安全æ¼æ´ž"
-
-msgid "detected no vulnerabilities"
-msgstr "未检测到安全æ¼æ´ž"
-
msgid "disabled"
msgstr "å·²ç¦ç”¨"
msgid "done"
msgstr "完æˆ"
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] "è‰ç¨¿"
+
msgid "enabled"
msgstr "å·²å¯ç”¨"
@@ -8466,6 +9561,12 @@ msgstr "最åŽä¸€æ¬¡%{slash_command} 命令将更新预计时间。"
msgid "for this project"
msgstr "对于这个项目"
+msgid "from"
+msgstr "æ¥è‡ª"
+
+msgid "help"
+msgstr "帮助"
+
msgid "here"
msgstr "此处"
@@ -8494,6 +9595,9 @@ msgstr "ä¸æ˜¯æœ‰æ•ˆçš„X509è¯ä¹¦ã€‚"
msgid "issue boards"
msgstr "议题看æ¿"
+msgid "latest deployment"
+msgstr "最新部署"
+
msgid "latest version"
msgstr "最新版本"
@@ -8580,7 +9684,7 @@ msgid "mrWidget|Failed to load deployment statistics"
msgstr "无法加载部署统计信æ¯"
msgid "mrWidget|Fast-forward merge is not possible. To merge this request, first rebase locally."
-msgstr ""
+msgstr "无法进行快进åˆå¹¶ã€‚è¦åˆå¹¶æ­¤è¯·æ±‚,请先在本地进行rebase。"
msgid "mrWidget|If the %{branch} branch exists in your local repository, you can merge this merge request manually using the"
msgstr "如果 %{branch} 分支存在于本地仓库中,则å¯ä»¥æ‰‹åŠ¨åˆå¹¶è¯¥åˆå¹¶è¯·æ±‚。需使用"
@@ -8622,13 +9726,13 @@ msgid "mrWidget|Open in Web IDE"
msgstr "在Web IDE中打开"
msgid "mrWidget|Pipeline blocked. The pipeline for this merge request requires a manual action to proceed"
-msgstr ""
+msgstr "æµæ°´çº¿è¢«é˜»æ­¢ã€‚æ­¤åˆå¹¶è¯·æ±‚çš„æµæ°´çº¿éœ€è¦æ‰‹åŠ¨æ“作æ‰èƒ½ç»§ç»­"
msgid "mrWidget|Plain diff"
msgstr "文本差异"
msgid "mrWidget|Ready to be merged automatically. Ask someone with write access to this repository to merge this request"
-msgstr ""
+msgstr "准备自动åˆå¹¶ã€‚询问具有此存储库的写访问æƒé™çš„人æ¥åˆå¹¶æ­¤è¯·æ±‚"
msgid "mrWidget|Refresh"
msgstr "刷新"
@@ -8657,13 +9761,13 @@ msgstr[0] "éœ€è¦ %d 次批准"
msgid "mrWidget|Requires 1 more approval by"
msgid_plural "mrWidget|Requires %d more approvals by"
-msgstr[0] ""
+msgstr[0] "需è¦é¢å¤– %d 个批准"
msgid "mrWidget|Resolve conflicts"
msgstr "解决冲çª"
msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
-msgstr ""
+msgstr "解决这些冲çªæˆ–询问对此存储库具有写入æƒé™çš„人员在本地åˆå¹¶å®ƒ"
msgid "mrWidget|Revert"
msgstr "还原"
@@ -8684,10 +9788,10 @@ msgid "mrWidget|The changes will be merged into"
msgstr "更改将被åˆå¹¶åˆ°"
msgid "mrWidget|The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure"
-msgstr ""
+msgstr "æ­¤åˆå¹¶è¯·æ±‚çš„æµæ°´çº¿å¤±è´¥ã€‚请é‡è¯•è¯¥ä½œä¸šæˆ–推é€æ–°çš„æ交以修å¤å¤±è´¥"
msgid "mrWidget|The source branch HEAD has recently changed. Please reload the page and review the changes before merging"
-msgstr ""
+msgstr "æºåˆ†æ”¯HEAD最近已更改。请在é‡æ–°åˆå¹¶ä¹‹å‰é‡æ–°åŠ è½½é¡µé¢å¹¶æŸ¥çœ‹æ›´æ”¹"
msgid "mrWidget|The source branch has been removed"
msgstr "æºåˆ†æ”¯å·²è¢«åˆ é™¤"
@@ -8719,6 +9823,9 @@ msgstr "该åˆå¹¶è¯·æ±‚正在被åˆå¹¶"
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "该项目已存档,ç¦æ­¢å†™å…¥"
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr "ä¸å…许直接编辑此项目。请派生(fork)åŽè¿›è¡Œæ›´æ”¹ã€‚"
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr "å¯ä»¥æ‰‹åŠ¨åˆå¹¶æ­¤åˆå¹¶è¯·æ±‚,使用以下"
@@ -8737,6 +9844,9 @@ msgstr "å…¥"
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr "æµæ°´çº¿æˆåŠŸæ—¶è‡ªåŠ¨åˆå¹¶"
+msgid "n/a"
+msgstr "ä¸é€‚用"
+
msgid "new merge request"
msgstr "新建åˆå¹¶è¯·æ±‚"
@@ -8748,7 +9858,7 @@ msgstr "或"
msgid "out of %d total test"
msgid_plural "out of %d total tests"
-msgstr[0] ""
+msgstr[0] "总共 %d 次测试中"
msgid "parent"
msgid_plural "parents"
@@ -8763,6 +9873,10 @@ msgstr "个人访问令牌"
msgid "private key does not match certificate."
msgstr "ç§é’¥ä¸Žè¯ä¹¦ä¸åŒ¹é…。"
+msgid "project"
+msgid_plural "projects"
+msgstr[0] "项目"
+
msgid "remaining"
msgstr "剩余"
@@ -8775,6 +9889,10 @@ msgstr "删除截止日期"
msgid "remove weight"
msgstr "移除æƒé‡"
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] "回å¤"
+
msgid "source"
msgstr "æº"
@@ -8790,6 +9908,9 @@ msgstr "此文档"
msgid "to help your contributors communicate effectively!"
msgstr "帮助您的贡献者进行有效沟通ï¼"
+msgid "toggle collapse"
+msgstr "切æ¢æŠ˜å "
+
msgid "username"
msgstr "用户å"
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index 49fbfc224e4..4425bb7be10 100644
--- a/locale/zh_HK/gitlab.po
+++ b/locale/zh_HK/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Chinese Traditional, Hong Kong\n"
"Language: zh_HK\n"
"MIME-Version: 1.0\n"
@@ -13,7 +13,7 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: zh-HK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:32\n"
+"PO-Revision-Date: 2018-11-19 17:21\n"
msgid " Status"
msgstr ""
@@ -29,6 +29,13 @@ msgid " improved on %d point"
msgid_plural " improved on %d points"
msgstr[0] ""
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
msgstr[0] ""
@@ -41,6 +48,10 @@ msgid "%d commit behind"
msgid_plural "%d commits behind"
msgstr[0] ""
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
+
msgid "%d exporter"
msgid_plural "%d exporters"
msgstr[0] ""
@@ -77,10 +88,6 @@ msgid "%d unstaged change"
msgid_plural "%d unstaged changes"
msgstr[0] ""
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] "為æ高é é¢åŠ è¼‰é€Ÿåº¦åŠæ€§èƒ½ï¼Œå·²çœç•¥äº† %s 次æ交。"
@@ -88,16 +95,29 @@ msgstr[0] "為æ高é é¢åŠ è¼‰é€Ÿåº¦åŠæ€§èƒ½ï¼Œå·²çœç•¥äº† %s 次æ交。"
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
msgstr ""
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr ""
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] ""
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+
msgid "%{filePath} deleted"
msgstr ""
@@ -107,6 +127,9 @@ msgstr ""
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr ""
+
msgid "%{loadingIcon} Started"
msgstr ""
@@ -122,22 +145,12 @@ msgstr ""
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr ""
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr "已失敗 %{number_of_failures} 次,最大失敗 %{maximum_failures} 次,GitLab å°‡é‡è©¦ã€‚"
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr "已失敗 %{number_of_failures} 次,最大失敗 %{maximum_failures} 次,GitLabä¸æœƒé‡è©¦ã€‚當å•é¡Œè§£æ±ºæ™‚é‡ç½®å­˜å„²ä¿¡æ¯ã€‚"
-
msgid "%{openOrClose} %{noteable}"
msgstr ""
msgid "%{percent}%% complete"
msgstr ""
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] "%{storage_name}:已訪å•æ­¤ä¸»æ©Ÿå¤±æ•— %{failed_attempts} 次"
-
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
msgstr[0] ""
@@ -148,23 +161,13 @@ msgstr ""
msgid "%{title} changes"
msgstr ""
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] ""
+msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgstr ""
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr ""
-msgid "%{unstaged} unstaged and %{staged} staged changes"
+msgid "+ %{count} more"
msgstr ""
msgid "+ %{moreCount} more"
@@ -280,6 +283,15 @@ msgstr ""
msgid "A collection of graphs regarding Continuous Integration"
msgstr "相關æŒçºŒé›†æˆçš„圖åƒé›†åˆ"
+msgid "A default branch cannot be chosen for an empty project."
+msgstr ""
+
+msgid "A deleted user"
+msgstr ""
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
+
msgid "A new branch will be created in your fork and a new merge request will be started."
msgstr ""
@@ -322,13 +334,10 @@ msgstr ""
msgid "Access denied! Please verify you can add deploy keys to this repository."
msgstr ""
-msgid "Access to '%{classification_label}' not allowed"
+msgid "Access expiration date"
msgstr ""
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr "å› æ¢å¾©å®‰è£ï¼Œè¨ªå•æ•…障存儲已被暫時ç¦ç”¨ã€‚在å•é¡Œè§£æ±ºå¾Œå°‡é‡ç½®å­˜å„²ä¿¡æ¯ï¼Œä»¥ä¾¿å†æ¬¡è¨ªå•ã€‚"
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
+msgid "Access to '%{classification_label}' not allowed"
msgstr ""
msgid "Account"
@@ -358,27 +367,48 @@ msgstr "添加貢ç»æŒ‡å—"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
-msgid "Add Kubernetes cluster"
+msgid "Add Jaeger URL"
msgstr ""
-msgid "Add License"
-msgstr "添加許å¯è­‰"
+msgid "Add Kubernetes cluster"
+msgstr ""
msgid "Add Readme"
msgstr ""
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
msgstr ""
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr ""
+
msgid "Add new application"
msgstr ""
msgid "Add new directory"
msgstr "添加新目錄"
+msgid "Add projects"
+msgstr ""
+
msgid "Add reaction"
msgstr ""
+msgid "Add to review"
+msgstr ""
+
msgid "Add todo"
msgstr ""
@@ -388,6 +418,9 @@ msgstr ""
msgid "Add users to group"
msgstr ""
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr ""
+
msgid "Additional text"
msgstr ""
@@ -421,9 +454,6 @@ msgstr ""
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
msgstr ""
-msgid "AdminHealthPageLink|health page"
-msgstr ""
-
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -460,12 +490,16 @@ msgstr ""
msgid "AdminUsers|To confirm, type %{username}"
msgstr ""
-msgid "Advanced"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
msgstr ""
msgid "Advanced settings"
msgstr ""
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+
msgid "All"
msgstr "全部"
@@ -481,6 +515,9 @@ msgstr ""
msgid "Allow commits from members who can merge to the target branch."
msgstr ""
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr ""
@@ -490,6 +527,12 @@ msgstr ""
msgid "Allow requests to the local network from hooks and services."
msgstr ""
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
+
msgid "Allows you to add and manage Kubernetes clusters."
msgstr ""
@@ -505,6 +548,9 @@ msgstr ""
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
+msgstr ""
+
msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
msgstr ""
@@ -526,7 +572,7 @@ msgstr ""
msgid "An error occured whilst fetching the job trace."
msgstr ""
-msgid "An error occured whilst fetching the latest pipline."
+msgid "An error occured whilst fetching the latest pipeline."
msgstr ""
msgid "An error occured whilst loading all the files."
@@ -550,6 +596,12 @@ msgstr ""
msgid "An error occured whilst loading the pipelines jobs."
msgstr ""
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -562,6 +614,9 @@ msgstr ""
msgid "An error occurred while adding approver"
msgstr ""
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr ""
@@ -574,6 +629,9 @@ msgstr ""
msgid "An error occurred while fetching markdown preview"
msgstr ""
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr ""
@@ -601,6 +659,9 @@ msgstr ""
msgid "An error occurred while initializing path locks"
msgstr ""
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -643,12 +704,18 @@ msgstr ""
msgid "An error occurred while unsubscribing to notifications."
msgstr ""
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr ""
msgid "An error occurred. Please try again."
msgstr ""
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr ""
@@ -667,7 +734,7 @@ msgstr ""
msgid "Application"
msgstr ""
-msgid "Application Id"
+msgid "Application ID"
msgstr ""
msgid "Application: %{name}"
@@ -685,9 +752,15 @@ msgstr ""
msgid "Archived project! Repository and other project resources are read-only"
msgstr ""
+msgid "Archived projects"
+msgstr ""
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "確定è¦åˆªé™¤æ­¤æµæ°´ç·šè¨ˆåŠƒå—Žï¼Ÿ"
+msgid "Are you sure you want to erase this build?"
+msgstr ""
+
msgid "Are you sure you want to lose unsaved changes?"
msgstr ""
@@ -706,6 +779,9 @@ msgstr "確定è¦é‡ç½®è¨»å†Šä»¤ç‰Œå—Žï¼Ÿ"
msgid "Are you sure you want to reset the health check token?"
msgstr "確定è¦é‡ç½®å¥åº·æª¢æŸ¥ä»¤ç‰Œå—Žï¼Ÿ"
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr ""
@@ -844,6 +920,9 @@ msgstr ""
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr ""
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr ""
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr ""
@@ -880,9 +959,6 @@ msgstr ""
msgid "Background color"
msgstr ""
-msgid "Background jobs"
-msgstr ""
-
msgid "Badges"
msgstr ""
@@ -961,6 +1037,15 @@ msgstr ""
msgid "Badges|e.g. %{exampleUrl}"
msgstr ""
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
+msgstr ""
+
msgid "Begin with the selected commit"
msgstr ""
@@ -1250,6 +1335,9 @@ msgstr ""
msgid "CICD|Continuous deployment to production"
msgstr ""
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
+msgstr ""
+
msgid "CICD|Default to Auto DevOps pipeline"
msgstr ""
@@ -1280,9 +1368,6 @@ msgstr ""
msgid "Callback URL"
msgstr ""
-msgid "Callback url"
-msgstr ""
-
msgid "Can't find HEAD commit for this branch"
msgstr ""
@@ -1337,7 +1422,7 @@ msgstr "統計圖"
msgid "Chat"
msgstr ""
-msgid "Check interval"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
msgstr ""
msgid "Checking %{text} availability…"
@@ -1364,6 +1449,12 @@ msgstr ""
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr ""
+msgid "Choose a template..."
+msgstr ""
+
+msgid "Choose a type..."
+msgstr ""
+
msgid "Choose any color."
msgstr ""
@@ -1394,6 +1485,9 @@ msgstr "å·²å–消"
msgid "CiStatusLabel|created"
msgstr "已創建"
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr "已失敗"
@@ -1412,6 +1506,9 @@ msgstr "等待中"
msgid "CiStatusLabel|skipped"
msgstr "已跳éŽ"
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr "等待手動æ“作"
@@ -1424,6 +1521,9 @@ msgstr "å·²å–消"
msgid "CiStatusText|created"
msgstr "已創建"
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr "已失敗"
@@ -1478,10 +1578,10 @@ msgstr ""
msgid "CiVariable|Validation failed"
msgstr ""
-msgid "CircuitBreakerApiLink|circuitbreaker api"
+msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr ""
-msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
+msgid "Clear search"
msgstr ""
msgid "Clear search input"
@@ -1526,6 +1626,9 @@ msgstr ""
msgid "Close"
msgstr ""
+msgid "Close epic"
+msgstr ""
+
msgid "Closed"
msgstr ""
@@ -1538,12 +1641,24 @@ msgstr ""
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr ""
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr ""
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr ""
@@ -1574,10 +1689,10 @@ msgstr ""
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr ""
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
msgstr ""
msgid "ClusterIntegration|Copy API URL"
@@ -1604,6 +1719,12 @@ msgstr ""
msgid "ClusterIntegration|Did you know?"
msgstr ""
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr ""
@@ -1640,6 +1761,9 @@ msgstr ""
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr ""
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr ""
@@ -1670,9 +1794,6 @@ msgstr ""
msgid "ClusterIntegration|Install Prometheus"
msgstr ""
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr ""
@@ -1694,25 +1815,19 @@ msgstr ""
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster details"
-msgstr ""
-
-msgid "ClusterIntegration|Kubernetes cluster health"
+msgid "ClusterIntegration|Knative"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration"
+msgid "ClusterIntegration|Knative Domain Name:"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
+msgid "ClusterIntegration|Kubernetes cluster details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
+msgid "ClusterIntegration|Kubernetes cluster health"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
@@ -1724,7 +1839,7 @@ msgstr ""
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr ""
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
@@ -1733,16 +1848,13 @@ msgstr ""
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr ""
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr ""
-msgid "ClusterIntegration|Learn more about environments"
+msgid "ClusterIntegration|Learn more about Kubernetes"
msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Machine type"
@@ -1760,9 +1872,6 @@ msgstr ""
msgid "ClusterIntegration|More information"
msgstr ""
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr ""
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr ""
@@ -1790,6 +1899,9 @@ msgstr ""
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr ""
@@ -1802,6 +1914,9 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr ""
@@ -1832,9 +1947,6 @@ msgstr ""
msgid "ClusterIntegration|Search zones"
msgstr ""
-msgid "ClusterIntegration|Security"
-msgstr ""
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
@@ -1874,13 +1986,10 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr ""
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
@@ -1898,6 +2007,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr ""
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr ""
@@ -1916,9 +2028,6 @@ msgstr ""
msgid "ClusterIntegration|help page"
msgstr ""
-msgid "ClusterIntegration|installing applications"
-msgstr ""
-
msgid "ClusterIntegration|meets the requirements"
msgstr ""
@@ -1928,6 +2037,9 @@ msgstr ""
msgid "ClusterIntegration|sign up"
msgstr ""
+msgid "Code owners"
+msgstr ""
+
msgid "Cohorts"
msgstr ""
@@ -1937,12 +2049,18 @@ msgstr ""
msgid "Collapse sidebar"
msgstr ""
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr ""
msgid "Comment & unresolve discussion"
msgstr ""
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr "è©•è«–"
@@ -1975,6 +2093,9 @@ msgstr "æ交"
msgid "CommitMessage|Add %{file_name}"
msgstr "添加 %{file_name}"
+msgid "CommitWidget|authored"
+msgstr ""
+
msgid "Commits"
msgstr "æ交"
@@ -2047,7 +2168,7 @@ msgstr ""
msgid "Configure Gitaly timeouts."
msgstr ""
-msgid "Configure Sidekiq job throttling."
+msgid "Configure Tracing"
msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
@@ -2056,10 +2177,10 @@ msgstr ""
msgid "Configure limits for web and API requests."
msgstr ""
-msgid "Configure push and pull mirrors."
+msgid "Configure push mirrors."
msgstr ""
-msgid "Configure storage path and circuit breaker settings."
+msgid "Configure storage path settings."
msgstr ""
msgid "Configure the %{link} integration."
@@ -2149,6 +2270,9 @@ msgstr ""
msgid "Contribution guide"
msgstr "è²¢ç»æŒ‡å—"
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr ""
+
msgid "Contributions per group member"
msgstr ""
@@ -2182,6 +2306,18 @@ msgstr ""
msgid "ConvDev Index"
msgstr ""
+msgid "Copy %{protocol} clone URL"
+msgstr ""
+
+msgid "Copy HTTPS clone URL"
+msgstr ""
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr ""
+
msgid "Copy SSH public key to clipboard"
msgstr ""
@@ -2203,15 +2339,27 @@ msgstr ""
msgid "Copy incoming email address to clipboard"
msgstr ""
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
+msgstr ""
+
msgid "Copy reference to clipboard"
msgstr ""
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr ""
msgid "Copy token to clipboard"
msgstr ""
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr ""
@@ -2287,8 +2435,8 @@ msgstr "創建..."
msgid "Create project label"
msgstr ""
-msgid "CreateNewFork|Fork"
-msgstr "派生"
+msgid "Create your first page"
+msgstr ""
msgid "CreateTag|Tag"
msgstr "標籤"
@@ -2338,6 +2486,9 @@ msgstr ""
msgid "Custom CI config path"
msgstr ""
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr "自定義通知事件"
@@ -2356,6 +2507,9 @@ msgstr ""
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
msgstr ""
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
+msgstr ""
+
msgid "Cycle Analytics"
msgstr "週期分æž"
@@ -2407,6 +2561,9 @@ msgstr ""
msgid "Decline and sign out"
msgstr ""
+msgid "Default Branch"
+msgstr ""
+
msgid "Default classification label"
msgstr ""
@@ -2419,6 +2576,21 @@ msgstr ""
msgid "Define a custom pattern with cron syntax"
msgstr "使用 Cron 語法定義自定義模å¼"
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr "刪除"
@@ -2428,6 +2600,9 @@ msgstr ""
msgid "Delete Snippet"
msgstr ""
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr ""
@@ -2564,6 +2739,12 @@ msgstr ""
msgid "DeployTokens|Your new project deploy token has been created."
msgstr ""
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr ""
@@ -2588,6 +2769,12 @@ msgstr "詳情"
msgid "Detect host keys"
msgstr ""
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
+msgstr ""
+
msgid "Diffs|No file name available"
msgstr ""
@@ -2609,12 +2796,27 @@ msgstr ""
msgid "Disable group Runners"
msgstr ""
+msgid "Discard"
+msgstr ""
+
+msgid "Discard all changes"
+msgstr ""
+
+msgid "Discard all unstaged changes?"
+msgstr ""
+
msgid "Discard changes"
msgstr ""
+msgid "Discard changes to %{path}?"
+msgstr ""
+
msgid "Discard draft"
msgstr ""
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr ""
@@ -2630,6 +2832,9 @@ msgstr ""
msgid "Dismiss Merge Request promotion"
msgstr ""
+msgid "Dismiss trial promotion"
+msgstr ""
+
msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
msgstr ""
@@ -2711,7 +2916,7 @@ msgstr ""
msgid "Elasticsearch"
msgstr ""
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
msgstr ""
msgid "Email"
@@ -2756,9 +2961,6 @@ msgstr ""
msgid "Enable group Runners"
msgstr ""
-msgid "Enable or disable certain group features and choose access levels."
-msgstr ""
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -2771,6 +2973,12 @@ msgstr ""
msgid "Enable the Performance Bar for a given group."
msgstr ""
+msgid "Enable usage ping"
+msgstr ""
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr ""
+
msgid "Enabled"
msgstr ""
@@ -2873,7 +3081,7 @@ msgstr ""
msgid "Environments|Updated"
msgstr ""
-msgid "Environments|You don't have any environments right now."
+msgid "Environments|You don't have any environments right now"
msgstr ""
msgid "Environments|protected"
@@ -2906,10 +3114,10 @@ msgstr ""
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
+msgid "Epics|due"
msgstr ""
msgid "Epics|start"
@@ -3020,6 +3228,12 @@ msgstr ""
msgid "Expand sidebar"
msgstr ""
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr ""
@@ -3074,6 +3288,12 @@ msgstr "無法變更所有者"
msgid "Failed to check related branches."
msgstr ""
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
@@ -3083,6 +3303,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "無法刪除æµæ°´ç·šè¨ˆåŠƒ"
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr ""
@@ -3092,6 +3315,81 @@ msgstr ""
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr ""
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr ""
@@ -3101,6 +3399,9 @@ msgstr ""
msgid "Fields on this page are now uneditable, you can configure"
msgstr ""
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr "文件"
@@ -3113,9 +3414,18 @@ msgstr ""
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr "按æ交消æ¯éŽæ¿¾"
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr "按路徑查找"
@@ -3131,6 +3441,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr ""
@@ -3143,7 +3456,7 @@ msgstr "推é€è€…:"
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3182,16 +3495,18 @@ msgstr ""
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr ""
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr ""
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] "派生"
-
msgid "ForkedFromProjectPath|Forked from"
msgstr "派生自"
@@ -3207,6 +3522,9 @@ msgstr ""
msgid "Found errors in your .gitlab-ci.yml:"
msgstr ""
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr ""
@@ -3249,6 +3567,9 @@ msgstr ""
msgid "Generate a default set of labels"
msgstr ""
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr ""
@@ -3423,10 +3744,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr ""
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3435,6 +3768,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr ""
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr ""
@@ -3456,7 +3792,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3468,6 +3804,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr ""
@@ -3477,19 +3816,25 @@ msgstr ""
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr ""
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3507,6 +3852,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3519,9 +3870,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr ""
@@ -3531,9 +3900,6 @@ msgstr ""
msgid "Git revision"
msgstr ""
-msgid "Git storage health information has been reset"
-msgstr "Git 存儲å¥åº·ä¿¡æ¯å·²é‡ç½®"
-
msgid "Git strategy for pipelines"
msgstr ""
@@ -3600,12 +3966,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr "跳轉到派生項目"
-
-msgid "GoToYourFork|Fork"
-msgstr "跳轉到派生項目"
-
msgid "Google Code import"
msgstr ""
@@ -3636,9 +3996,21 @@ msgstr ""
msgid "Group Runners"
msgstr ""
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr ""
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr ""
@@ -3648,6 +4020,9 @@ msgstr ""
msgid "Group maintainers can register group runners in the %{link}"
msgstr ""
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -3666,13 +4041,13 @@ msgstr ""
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
@@ -3699,9 +4074,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr ""
-msgid "GroupSettings|Share with group lock"
-msgstr ""
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr ""
@@ -3759,6 +4131,9 @@ msgstr ""
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr ""
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr ""
@@ -3771,19 +4146,19 @@ msgstr ""
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr ""
-msgid "GroupsTree|Filter by name..."
-msgstr ""
-
msgid "GroupsTree|Leave this group"
msgstr ""
msgid "GroupsTree|Loading groups"
msgstr ""
-msgid "GroupsTree|Sorry, no groups matched your search"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
+
+msgid "GroupsTree|No groups or projects matched your search"
msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
+msgid "GroupsTree|Search by name"
msgstr ""
msgid "Have your users email"
@@ -3825,6 +4200,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] ""
@@ -3988,6 +4366,9 @@ msgstr ""
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr ""
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4055,6 +4436,12 @@ msgstr "循環週期"
msgid "Introducing Cycle Analytics"
msgstr "週期分æžç°¡ä»‹"
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr ""
@@ -4079,6 +4466,36 @@ msgstr ""
msgid "Issues closed"
msgstr ""
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr ""
@@ -4094,9 +4511,6 @@ msgstr ""
msgid "Jobs"
msgstr ""
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4133,7 +4547,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4151,12 +4565,6 @@ msgstr ""
msgid "June"
msgstr ""
-msgid "Koding"
-msgstr ""
-
-msgid "Koding Dashboard"
-msgstr ""
-
msgid "Kubernetes"
msgstr ""
@@ -4229,6 +4637,9 @@ msgstr ""
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] "最近 %d 天"
@@ -4239,12 +4650,18 @@ msgstr "最新æµæ°´ç·š"
msgid "Last commit"
msgstr "最後æ交"
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr ""
msgid "Last edited by %{name}"
msgstr ""
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr ""
@@ -4293,6 +4710,15 @@ msgstr ""
msgid "License"
msgstr ""
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4302,6 +4728,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4311,6 +4740,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4320,6 +4752,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4332,9 +4767,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4360,6 +4801,9 @@ msgstr ""
msgid "List available repositories"
msgstr ""
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4405,6 +4849,9 @@ msgstr ""
msgid "Locks give the ability to lock specific file or folder."
msgstr ""
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr ""
@@ -4474,13 +4921,43 @@ msgstr ""
msgid "Markdown enabled"
msgstr ""
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
+msgid "Max access level"
msgstr ""
msgid "Maximum job timeout"
@@ -4492,6 +4969,12 @@ msgstr ""
msgid "Median"
msgstr "中ä½æ•¸"
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr ""
@@ -4525,6 +5008,21 @@ msgstr ""
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr ""
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr ""
@@ -4534,9 +5032,6 @@ msgstr ""
msgid "MergeRequests|Toggle comments for this file"
msgstr ""
-msgid "MergeRequests|Updating discussions failed"
-msgstr ""
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr ""
@@ -4546,6 +5041,12 @@ msgstr ""
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr ""
@@ -4561,6 +5062,9 @@ msgstr ""
msgid "Metrics - Prometheus"
msgstr ""
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr ""
@@ -4777,6 +5281,9 @@ msgstr ""
msgid "Name:"
msgstr ""
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -4895,6 +5402,12 @@ msgstr ""
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr ""
@@ -4904,9 +5417,6 @@ msgstr ""
msgid "No file chosen"
msgstr ""
-msgid "No files found"
-msgstr ""
-
msgid "No files found."
msgstr ""
@@ -4916,6 +5426,9 @@ msgstr ""
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr ""
@@ -4943,6 +5456,9 @@ msgstr ""
msgid "No repository"
msgstr "沒有存儲庫"
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr "沒有計劃"
@@ -4979,6 +5495,9 @@ msgstr ""
msgid "Not enough data"
msgstr "數據ä¸è¶³"
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr ""
@@ -4997,6 +5516,18 @@ msgstr ""
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr "通知事件"
@@ -5069,9 +5600,6 @@ msgstr ""
msgid "November"
msgstr ""
-msgid "Number of access attempts"
-msgstr ""
-
msgid "OK"
msgstr ""
@@ -5097,9 +5625,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr ""
-
msgid "Only admins"
msgstr ""
@@ -5121,6 +5646,9 @@ msgstr ""
msgid "Open in Xcode"
msgstr ""
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr ""
@@ -5145,6 +5673,21 @@ msgstr ""
msgid "Operations"
msgstr ""
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5211,6 +5754,9 @@ msgstr ""
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr ""
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr ""
@@ -5238,15 +5784,15 @@ msgstr ""
msgid "Permissions"
msgstr ""
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
msgid "Personal Access Token"
msgstr ""
msgid "Pipeline"
msgstr "æµæ°´ç·š"
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
-msgstr ""
-
msgid "Pipeline Health"
msgstr "æµæ°´ç·šå¥åº·æŒ‡æ¨™"
@@ -5364,15 +5910,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr ""
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr ""
msgid "Pipeline|Create pipeline"
msgstr ""
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr ""
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr ""
@@ -5382,6 +5937,12 @@ msgstr ""
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr ""
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr ""
@@ -5409,12 +5970,6 @@ msgstr "於階段"
msgid "Plain diff"
msgstr ""
-msgid "Planned finish date"
-msgstr ""
-
-msgid "Planned start date"
-msgstr ""
-
msgid "PlantUML"
msgstr ""
@@ -5424,12 +5979,18 @@ msgstr ""
msgid "Please accept the Terms of Service before continuing."
msgstr ""
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5442,6 +6003,9 @@ msgstr ""
msgid "Please try again"
msgstr ""
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr ""
@@ -5454,9 +6018,18 @@ msgstr ""
msgid "Preferences|Navigation theme"
msgstr ""
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr ""
@@ -5502,15 +6075,30 @@ msgstr ""
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr ""
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr ""
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr ""
@@ -5523,39 +6111,120 @@ msgstr ""
msgid "Profiles|Deleting an account has the following effects:"
msgstr ""
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr ""
msgid "Profiles|Invalid username"
msgstr ""
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr ""
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr ""
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr ""
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr ""
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr ""
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr ""
msgid "Profiles|Username successfully changed"
msgstr ""
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr ""
@@ -5565,6 +6234,15 @@ msgstr ""
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr ""
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5601,6 +6279,9 @@ msgstr "é …ç›® '%{project_name}' 已更新完æˆã€‚"
msgid "Project Badges"
msgstr ""
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr "項目訪å•æ¬Šé™å¿…須明確授權給æ¯å€‹ç”¨æˆ¶ã€‚"
@@ -5628,6 +6309,9 @@ msgstr "項目導出已開始。下載éˆæŽ¥å°‡é€šéŽé›»å­éƒµä»¶ç™¼é€ã€‚"
msgid "Project name"
msgstr ""
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "訂閱"
@@ -5655,6 +6339,27 @@ msgstr "從未"
msgid "ProjectLifecycle|Stage"
msgstr "階段"
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5697,6 +6402,9 @@ msgstr ""
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr ""
@@ -5766,9 +6474,6 @@ msgstr ""
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr ""
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr ""
-
msgid "PrometheusService|Common metrics"
msgstr ""
@@ -5961,6 +6666,12 @@ msgstr "自述文件"
msgid "Real-time features"
msgstr ""
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr ""
@@ -6022,12 +6733,21 @@ msgstr ""
msgid "Remove avatar"
msgstr ""
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr ""
msgid "Remove project"
msgstr "刪除項目"
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6037,6 +6757,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr ""
@@ -6046,18 +6769,33 @@ msgstr ""
msgid "Repo by URL"
msgstr ""
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6070,6 +6808,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6103,11 +6844,11 @@ msgstr "申請權é™"
msgid "Requests Profiles"
msgstr ""
-msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgid "Require all users in this group to setup Two-factor authentication"
msgstr ""
-msgid "Reset git storage health information"
-msgstr "é‡ç½® Git 存儲的å¥åº·ä¿¡æ¯"
+msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
+msgstr ""
msgid "Reset health check access token"
msgstr "é‡ç½®å¥åº·æª¢æŸ¥è¨ªå•ä»¤ç‰Œ"
@@ -6124,9 +6865,21 @@ msgstr ""
msgid "Resolve discussion"
msgstr ""
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr ""
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr ""
@@ -6176,9 +6929,24 @@ msgstr ""
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr ""
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr ""
@@ -6188,6 +6956,12 @@ msgstr ""
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr ""
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6212,6 +6986,9 @@ msgstr ""
msgid "SAML Single Sign On Settings"
msgstr ""
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr ""
@@ -6236,6 +7013,9 @@ msgstr ""
msgid "Save changes"
msgstr ""
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "ä¿å­˜æµæ°´ç·šè¨ˆåŠƒ"
@@ -6290,15 +7070,24 @@ msgstr ""
msgid "Search milestones"
msgstr ""
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr ""
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr ""
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6323,26 +7112,55 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
+msgid "Secret"
msgstr ""
-msgid "Seconds to wait for a storage access attempt"
+msgid "Security"
msgstr ""
-msgid "Secret:"
+msgid "Security Dashboard"
msgstr ""
-msgid "Security"
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
msgstr ""
-msgid "Security Dashboard"
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
msgstr ""
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
+
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6360,9 +7178,15 @@ msgstr ""
msgid "Select Archive Format"
msgstr "é¸æ“‡ä¸‹è¼‰æ ¼å¼"
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr ""
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr "é¸æ“‡æ™‚å€"
@@ -6393,6 +7217,9 @@ msgstr ""
msgid "Select target branch"
msgstr "é¸æ“‡ç›®æ¨™åˆ†æ”¯"
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6405,6 +7232,9 @@ msgstr ""
msgid "Send email"
msgstr ""
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr ""
@@ -6429,6 +7259,9 @@ msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "為賬號添加壹個用於推é€æˆ–拉å–çš„ %{protocol} 密碼。"
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr ""
@@ -6447,8 +7280,11 @@ msgstr ""
msgid "Set up CI/CD"
msgstr ""
-msgid "Set up Koding"
-msgstr "設置 Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr ""
@@ -6459,13 +7295,31 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "設置密碼"
-msgid "Settings"
+msgid "SetStatusModal|Add status emoji"
msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
msgstr ""
msgid "Share"
@@ -6477,6 +7331,9 @@ msgstr ""
msgid "Shared Runners"
msgstr ""
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr ""
@@ -6559,12 +7416,18 @@ msgstr ""
msgid "Slack application"
msgstr ""
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr ""
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr ""
@@ -6592,9 +7455,15 @@ msgstr ""
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr ""
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr ""
@@ -6607,12 +7476,24 @@ msgstr ""
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr ""
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr ""
msgid "Sorry, no epics matched your search"
msgstr ""
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr ""
@@ -6643,6 +7524,9 @@ msgstr ""
msgid "SortOptions|Largest repository"
msgstr ""
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr ""
@@ -6673,6 +7557,9 @@ msgstr ""
msgid "SortOptions|Most popular"
msgstr ""
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr ""
@@ -6703,6 +7590,9 @@ msgstr ""
msgid "SortOptions|Recent sign in"
msgstr ""
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr ""
@@ -6778,9 +7668,21 @@ msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr "由此更改 %{new_merge_request}"
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "é‹ä½œ Runner!"
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr ""
@@ -6793,6 +7695,9 @@ msgstr ""
msgid "Status"
msgstr ""
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr ""
@@ -6802,6 +7707,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr ""
@@ -6811,9 +7719,15 @@ msgstr ""
msgid "Subgroups"
msgstr ""
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr ""
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6826,6 +7740,12 @@ msgstr ""
msgid "Subscribe at project level"
msgstr ""
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "切æ›åˆ†æ”¯/標籤"
@@ -6844,6 +7764,9 @@ msgstr ""
msgid "System metrics (Custom)"
msgstr ""
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] ""
@@ -6947,6 +7870,9 @@ msgstr ""
msgid "Terms of Service and Privacy Policy"
msgstr ""
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr ""
@@ -6995,12 +7921,6 @@ msgstr "議題階段概述了從創建議題到將議題添加到è£ç¨‹ç¢‘或議
msgid "The maximum file size allowed is 200KB."
msgstr ""
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr ""
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr ""
@@ -7049,9 +7969,6 @@ msgstr "評審階段概述了從創建åˆä½µè«‹æ±‚到åˆä½µçš„時間。當創建
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr ""
-msgid "The secure token used by the Runner to checkout the project"
-msgstr ""
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "é ç™¼å¸ƒéšŽæ®µæ¦‚述了åˆä½µè«‹æ±‚çš„åˆä½µåˆ°éƒ¨ç½²ä»£ç¢¼åˆ°ç”Ÿç”¢ç’°å¢ƒçš„總時間。當首次部署到生產環境後,數據將自動添加到此處。"
@@ -7061,21 +7978,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr "測試階段概述了 GitLab CI 為相關åˆä½µè«‹æ±‚é‹è¡Œæ¯å€‹æµæ°´ç·šæ‰€éœ€çš„時間。當第壹個æµæ°´ç·šé‹è¡Œå®Œæˆå¾Œï¼Œæ•¸æ“šå°‡è‡ªå‹•æ·»åŠ åˆ°æ­¤è™•ã€‚"
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr ""
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr ""
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr "該階段æ¯æ¢æ•¸æ“šæ‰€èŠ±çš„時間"
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7085,6 +7996,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "中ä½æ•¸æ˜¯å£¹å€‹æ•¸åˆ—中最中間的值。例如在 3ã€5ã€9 之間,中ä½æ•¸æ˜¯ 5。在 3ã€5ã€7ã€8 之間,中ä½æ•¸æ˜¯ (5 + 7)/ 2 = 6。"
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr ""
@@ -7094,8 +8008,14 @@ msgstr ""
msgid "There are no merge requests to show"
msgstr ""
-msgid "There are problems accessing Git storage: "
-msgstr "è¨ªå• Git 存儲時出ç¾å•é¡Œï¼š"
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
msgid "There was an error adding a todo."
msgstr ""
@@ -7142,10 +8062,13 @@ msgstr ""
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
+msgstr ""
+
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7166,6 +8089,9 @@ msgstr ""
msgid "This is a confidential issue."
msgstr ""
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr ""
@@ -7205,7 +8131,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7226,6 +8155,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr ""
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "在創建壹個空的存儲庫或導入ç¾æœ‰å­˜å„²åº«ä¹‹å‰ï¼Œæ‚¨å°‡ç„¡æ³•æŽ¨é€ä»£ç¢¼ã€‚"
@@ -7250,6 +8182,9 @@ msgstr ""
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr ""
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7259,6 +8194,12 @@ msgstr ""
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr ""
@@ -7286,9 +8227,15 @@ msgstr "議題被列入日程表的時間"
msgid "Time before an issue starts implementation"
msgstr "開始進行編碼å‰çš„時間"
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr "從創建åˆä½µè«‹æ±‚到被åˆä½µæˆ–關閉的時間"
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr ""
@@ -7477,12 +8424,24 @@ msgstr ""
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr ""
@@ -7498,6 +8457,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr ""
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr ""
@@ -7510,12 +8472,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr ""
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""
msgid "To widen your search, change or remove filters."
msgstr ""
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr ""
@@ -7525,9 +8490,15 @@ msgstr ""
msgid "Toggle Sidebar"
msgstr ""
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr ""
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr ""
@@ -7543,6 +8514,9 @@ msgstr ""
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr ""
@@ -7558,6 +8532,9 @@ msgstr "所有æ交和åˆä½µçš„總測試時間"
msgid "Total: %{total}"
msgstr ""
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr ""
@@ -7567,6 +8544,9 @@ msgstr ""
msgid "Track time with quick actions"
msgstr ""
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr ""
@@ -7585,24 +8565,42 @@ msgstr ""
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr ""
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr ""
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr ""
msgid "Twitter"
msgstr ""
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr ""
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr ""
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr ""
@@ -7618,6 +8616,12 @@ msgstr ""
msgid "Unresolve discussion"
msgstr ""
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr ""
@@ -7651,13 +8655,16 @@ msgstr ""
msgid "Up to date"
msgstr ""
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr ""
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
+msgid "Update your group name, description, avatar, and visibility."
msgstr ""
msgid "Updating"
@@ -7687,15 +8694,15 @@ msgstr "上傳新文件"
msgid "Upload file"
msgstr "上傳文件"
-msgid "Upload new avatar"
-msgstr ""
-
msgid "UploadLink|click to upload"
msgstr "點擊上傳"
msgid "Upvotes"
msgstr ""
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr ""
@@ -7723,6 +8730,9 @@ msgstr "使用全局通知設置"
msgid "Used by members to sign in to your group in GitLab"
msgstr ""
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr ""
@@ -7732,10 +8742,52 @@ msgstr ""
msgid "User map"
msgstr ""
-msgid "Users"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
+
+msgid "UserProfile|Most Recent Activity"
+msgstr ""
+
+msgid "UserProfile|Overview"
msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
msgstr ""
msgid "Variables"
@@ -7762,6 +8814,15 @@ msgstr ""
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr ""
@@ -7795,9 +8856,15 @@ msgstr ""
msgid "View replaced file @ "
msgstr ""
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr ""
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7816,6 +8883,36 @@ msgstr "公開"
msgid "VisibilityLevel|Unknown"
msgstr "未知"
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "權é™ä¸è¶³ã€‚如需查看相關數據,請å‘管ç†å“¡ç”³è«‹æ¬Šé™ã€‚"
@@ -7855,6 +8952,12 @@ msgstr ""
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr ""
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr ""
@@ -8005,6 +9108,9 @@ msgstr ""
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8023,9 +9129,6 @@ msgstr ""
msgid "You are on a read-only GitLab instance."
msgstr ""
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr ""
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr ""
@@ -8035,9 +9138,6 @@ msgstr ""
msgid "You can also star a label to make it a priority label."
msgstr ""
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr ""
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8059,12 +9159,18 @@ msgstr ""
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr ""
msgid "You cannot write to this read-only GitLab instance."
msgstr ""
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr ""
@@ -8086,9 +9192,6 @@ msgstr ""
msgid "You must have maintainer access to force delete a lock"
msgstr ""
-msgid "You must sign in to star a project"
-msgstr "必須登錄æ‰èƒ½å°é …目加星標"
-
msgid "You need a different license to enable FileLocks feature"
msgstr ""
@@ -8098,6 +9201,12 @@ msgstr ""
msgid "You need permission."
msgstr "需è¦ç›¸é—œçš„權é™ã€‚"
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr "ä¸æœƒæ”¶åˆ°ä»»ä½•é€šçŸ¥éƒµä»¶"
@@ -8164,6 +9273,9 @@ msgstr ""
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr ""
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr ""
@@ -8185,14 +9297,6 @@ msgstr ""
msgid "among other things"
msgstr ""
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-
msgid "assign yourself"
msgstr ""
@@ -8220,61 +9324,74 @@ msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
msgstr ""
-msgid "ciReport|%{reportName} is loading"
-msgstr ""
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
msgstr ""
-msgid "ciReport|Class"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
+
+msgid "ciReport|%{reportType} detected no vulnerabilities"
msgstr ""
-msgid "ciReport|Code quality"
+msgid "ciReport|%{reportType} is loading"
msgstr ""
-msgid "ciReport|Confidence"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
msgstr ""
-msgid "ciReport|Container scanning detected"
+msgid "ciReport|(errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
+msgid "ciReport|(is loading)"
msgstr ""
-msgid "ciReport|Container scanning is loading"
+msgid "ciReport|(is loading, errors when loading results)"
msgstr ""
-msgid "ciReport|Container scanning resulted in error while loading results"
+msgid "ciReport|Class"
msgstr ""
-msgid "ciReport|DAST detected"
+msgid "ciReport|Code quality"
msgstr ""
-msgid "ciReport|DAST is loading"
+msgid "ciReport|Confidence"
msgstr ""
-msgid "ciReport|DAST resulted in error while loading results"
+msgid "ciReport|Container scanning"
msgstr ""
-msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
+msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
+msgid "ciReport|DAST"
msgstr ""
-msgid "ciReport|Dependency scanning is loading"
+msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning resulted in error while loading results"
+msgid "ciReport|Dependency scanning"
msgstr ""
msgid "ciReport|Description"
@@ -8307,9 +9424,6 @@ msgstr ""
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr ""
-msgid "ciReport|Learn more about whitelisting"
-msgstr ""
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8330,6 +9444,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr ""
@@ -8348,13 +9465,7 @@ msgstr ""
msgid "ciReport|Revert dismissal"
msgstr ""
-msgid "ciReport|SAST detected"
-msgstr ""
-
-msgid "ciReport|SAST is loading"
-msgstr ""
-
-msgid "ciReport|SAST resulted in error while loading results"
+msgid "ciReport|SAST"
msgstr ""
msgid "ciReport|Security scanning"
@@ -8363,9 +9474,6 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
-msgid "ciReport|Security scanning is loading"
-msgstr ""
-
msgid "ciReport|Severity"
msgstr ""
@@ -8396,9 +9504,6 @@ msgstr ""
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr ""
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr ""
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr ""
@@ -8409,9 +9514,6 @@ msgstr[0] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr ""
-
msgid "ciReport|on pipeline"
msgstr ""
@@ -8440,23 +9542,16 @@ msgstr[0] "天"
msgid "deploy token"
msgstr ""
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] ""
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] ""
-
-msgid "detected no vulnerabilities"
-msgstr ""
-
msgid "disabled"
msgstr ""
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+
msgid "enabled"
msgstr ""
@@ -8466,6 +9561,12 @@ msgstr ""
msgid "for this project"
msgstr ""
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr ""
@@ -8494,6 +9595,9 @@ msgstr ""
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr ""
@@ -8719,6 +9823,9 @@ msgstr ""
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr ""
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr ""
@@ -8737,6 +9844,9 @@ msgstr ""
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr ""
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr "新建åˆä½µè«‹æ±‚"
@@ -8763,6 +9873,10 @@ msgstr ""
msgid "private key does not match certificate."
msgstr ""
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+
msgid "remaining"
msgstr ""
@@ -8775,6 +9889,10 @@ msgstr ""
msgid "remove weight"
msgstr ""
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+
msgid "source"
msgstr ""
@@ -8790,6 +9908,9 @@ msgstr ""
msgid "to help your contributors communicate effectively!"
msgstr ""
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr ""
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index 5c9746ad6b4..47646afb0a9 100644
--- a/locale/zh_TW/gitlab.po
+++ b/locale/zh_TW/gitlab.po
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab-ee\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: gitlab <mbartlett+crowdin@gitlab.com>\n"
+"Last-Translator: gitlab <community@gitlab.com>\n"
"Language-Team: Chinese Traditional\n"
"Language: zh_TW\n"
"MIME-Version: 1.0\n"
@@ -13,10 +13,10 @@ msgstr ""
"X-Crowdin-Project: gitlab-ee\n"
"X-Crowdin-Language: zh-TW\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
-"PO-Revision-Date: 2018-09-04 07:32\n"
+"PO-Revision-Date: 2018-11-19 17:21\n"
msgid " Status"
-msgstr ""
+msgstr " 狀態"
msgid " and"
msgstr " 和"
@@ -29,29 +29,40 @@ msgid " improved on %d point"
msgid_plural " improved on %d points"
msgstr[0] " 在 %d 點上改善"
+msgid "\"%{query}\" in projects"
+msgstr ""
+
+msgid "%d addition"
+msgid_plural "%d additions"
+msgstr[0] ""
+
msgid "%d changed file"
msgid_plural "%d changed files"
-msgstr[0] "%d 個變更的檔案"
+msgstr[0] "%d 個已變更檔案"
msgid "%d commit"
msgid_plural "%d commits"
-msgstr[0] "%d 個更動"
+msgstr[0] "%d 個æ交紀錄"
msgid "%d commit behind"
msgid_plural "%d commits behind"
-msgstr[0] "è½å¾Œ %d 個更動紀錄"
+msgstr[0] "è½å¾Œ %d 個æ交紀錄"
+
+msgid "%d deleted"
+msgid_plural "%d deletions"
+msgstr[0] ""
msgid "%d exporter"
msgid_plural "%d exporters"
-msgstr[0] "%d 導出"
+msgstr[0] "%d 個匯出工具"
msgid "%d failed test result"
msgid_plural "%d failed test results"
-msgstr[0] ""
+msgstr[0] "%d 個失敗的測試çµæžœ"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
-msgstr[0] ""
+msgstr[0] "%d 個修復的測試çµæžœ"
msgid "%d issue"
msgid_plural "%d issues"
@@ -59,7 +70,7 @@ msgstr[0] "%d 個議題"
msgid "%d layer"
msgid_plural "%d layers"
-msgstr[0] "%d 個圖層"
+msgstr[0] "%d 個介層"
msgid "%d merge request"
msgid_plural "%d merge requests"
@@ -67,7 +78,7 @@ msgstr[0] "%d 個åˆä½µè«‹æ±‚"
msgid "%d metric"
msgid_plural "%d metrics"
-msgstr[0] "%d 指標"
+msgstr[0] "%d 個指標"
msgid "%d staged change"
msgid_plural "%d staged changes"
@@ -77,10 +88,6 @@ msgid "%d unstaged change"
msgid_plural "%d unstaged changes"
msgstr[0] "%d 個未暫存變更"
-msgid "%d vulnerability"
-msgid_plural "%d vulnerabilities"
-msgstr[0] "%d 個æ¼æ´ž"
-
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
msgstr[0] "因效能考é‡ï¼Œå·²éš±è— %s 個更動 (commit)。"
@@ -88,59 +95,65 @@ msgstr[0] "因效能考é‡ï¼Œå·²éš±è— %s 個更動 (commit)。"
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} 和 %{openOrClose} %{noteable}"
+msgid "%{authorsName}'s discussion"
+msgstr ""
+
msgid "%{commit_author_link} authored %{commit_timeago}"
-msgstr "ç”± %{commit_author_link} æ交於 %{commit_timeago}"
+msgstr "%{commit_author_link} æ–¼ %{commit_timeago} æ交"
msgid "%{counter_storage} (%{counter_repositories} repositories, %{counter_build_artifacts} build artifacts, %{counter_lfs_objects} LFS)"
msgstr "%{counter_storage} (%{counter_repositories} 個版本庫ã€%{counter_build_artifacts} 個編譯產物ã€å’Œ %{counter_lfs_objects} 個 LFS)"
+msgid "%{count} %{alerts}"
+msgstr ""
+
+msgid "%{count} more assignees"
+msgstr ""
+
msgid "%{count} participant"
msgid_plural "%{count} participants"
msgstr[0] "%{count} åƒèˆ‡è€…"
+msgid "%{count} pending comment"
+msgid_plural "%{count} pending comments"
+msgstr[0] ""
+
msgid "%{filePath} deleted"
msgstr "已刪除 %{filePath}"
msgid "%{firstLabel} +%{labelCount} more"
-msgstr ""
+msgstr "%{firstLabel} +%{labelCount} 更多"
msgid "%{group_docs_link_start}Groups%{group_docs_link_end} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr "%{group_docs_link_start}群組%{group_docs_link_end} å…許您管ç†ã€å”作多個專案。群組的æˆå“¡å¯ä»¥è¨ªå•ç¾¤çµ„下的所有專案。"
+msgstr "%{group_docs_link_start}群組%{group_docs_link_end} å…許您管ç†ã€å”作多個專案。群組的æˆå“¡å¯ä»¥å­˜å–群組下的所有專案。"
+
+msgid "%{issuableType} will be removed! Are you sure?"
+msgstr "將會移除 %{issuableType}ï¼ç¢ºå®šï¼Ÿ"
msgid "%{loadingIcon} Started"
msgstr "%{loadingIcon} 開始"
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
-msgstr "%{lock_path} 被使用者 %{lock_user_id} 鎖定"
+msgstr "%{lock_path} 被 GitLab 使用者 %{lock_user_id} 鎖定"
msgid "%{name}'s avatar"
msgstr "%{name} çš„é ­è²¼"
msgid "%{nip_domain} can be used as an alternative to a custom domain."
-msgstr "%{nip_domain} å¯ä»¥ä½¿ç”¨ç‚ºè‡ªè¨‚網域的替代方案。"
+msgstr "%{nip_domain} å¯ä»¥ç•¶ä½œè‡ªè¨‚網域的替代方案。"
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
-msgstr "%{number_commits_behind} 個è½å¾Œ %{default_branch} 分支的修訂版æ交,%{number_commits_ahead} 個超å‰çš„修訂版更動"
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
-msgstr "ç›®å‰å·²å¤±æ•— %{number_of_failures} 次。GitLab å…許在 %{maximum_failures} 次之內å¯å†å˜—è©¦è®€å– ã€‚"
-
-msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
-msgstr "已失敗 %{number_of_failures} / %{maximum_failures} 次,GitLab å°‡ä¸å†è‡ªå‹•é‡è©¦ã€‚請在確èªå•é¡Œè§£æ±ºå¾Œæ‰‹å‹•é‡ç½®å„²å­˜ç©ºé–“資訊。"
+msgstr "%{number_commits_behind} 個è½å¾Œ %{default_branch} 分支的æ交記錄,%{number_commits_ahead} 個超å‰çš„æ交記錄"
msgid "%{openOrClose} %{noteable}"
msgstr "%{openOrClose} %{noteable}"
msgid "%{percent}%% complete"
-msgstr "%{percent}%% 完æˆ"
-
-msgid "%{storage_name}: failed storage access attempt on host:"
-msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
-msgstr[0] "%{storage_name}:已存å–此主機失敗 %{failed_attempts} 次"
+msgstr "å®Œæˆ %{percent}%%"
msgid "%{text} %{files}"
msgid_plural "%{text} %{files} files"
-msgstr[0] "%{text} %{files} 檔案"
+msgstr[0] "%{text} %{files} 個檔案"
msgid "%{text} is available"
msgstr "%{text} å¯ç”¨"
@@ -148,48 +161,38 @@ msgstr "%{text} å¯ç”¨"
msgid "%{title} changes"
msgstr "%{title} 變更"
-msgid "%{type} detected 1 fixed vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} fixed vulnerabilities"
-msgstr[0] ""
-
-msgid "%{type} detected 1 new vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} new vulnerabilities"
-msgstr[0] ""
-
-msgid "%{type} detected 1 vulnerability"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities"
-msgstr[0] "%{type} åµæ¸¬åˆ° %{vulnerabilityCount} 個æ¼æ´ž"
-
-msgid "%{type} detected 1 vulnerability for the source branch only"
-msgid_plural "%{type} detected %{vulnerabilityCount} vulnerabilities for the source branch only"
-msgstr[0] ""
-
msgid "%{unstaged} unstaged and %{staged} staged changes"
msgstr "%{unstaged} 個未暫存和 %{staged} 個已暫存變更"
+msgid "%{usage_ping_link_start}Learn more%{usage_ping_link_end} about what information is shared with GitLab Inc."
+msgstr "%{usage_ping_link_start}了解更多%{usage_ping_link_end}會與 GitLab å…¬å¸åˆ†äº«çš„資料。"
+
+msgid "+ %{count} more"
+msgstr "+ %{count} 更多"
+
msgid "+ %{moreCount} more"
msgstr "+ %{moreCount} 更多"
msgid "- Runner is active and can process any new jobs"
-msgstr "- Runner 為啟用狀態,並且å¯ä»¥è™•ç†ä»»ä½•æ–°çš„工作。"
+msgstr "- Runner 為啟用狀態,並且å¯ä»¥è™•ç†ä»»ä½•æ–°çš„工作"
msgid "- Runner is paused and will not receive any new jobs"
msgstr "- Runner 為暫åœç‹€æ…‹ï¼Œä¸”å°‡ä¸æœƒæŽ¥å—任何新的工作"
msgid "- show less"
-msgstr "顯示較少"
+msgstr "- 顯示較少"
msgid "1 %{type} addition"
msgid_plural "%{count} %{type} additions"
-msgstr[0] "%{count}%{type} 個附加"
+msgstr[0] "%{count}%{type} 個附加項目"
msgid "1 %{type} modification"
msgid_plural "%{count} %{type} modifications"
-msgstr[0] "%{count}%{type} 個變更"
+msgstr[0] "%{count}%{type} 個變更項目"
msgid "1 closed issue"
msgid_plural "%d closed issues"
-msgstr[0] "%d 個關閉的議題"
+msgstr[0] "%d 個關閉議題"
msgid "1 closed merge request"
msgid_plural "%d closed merge requests"
@@ -197,7 +200,7 @@ msgstr[0] "%d 個關閉的åˆä½µè«‹æ±‚"
msgid "1 group"
msgid_plural "%d groups"
-msgstr[0] ""
+msgstr[0] "%d 個群組"
msgid "1 merged merge request"
msgid_plural "%d merged merge requests"
@@ -205,11 +208,11 @@ msgstr[0] "%d 個已åˆä½µçš„åˆä½µè«‹æ±‚"
msgid "1 open issue"
msgid_plural "%d open issues"
-msgstr[0] "%d 個進行中的議題"
+msgstr[0] "%d 個開放中的議題"
msgid "1 open merge request"
msgid_plural "%d open merge requests"
-msgstr[0] "%d 個進行中的åˆä½µè«‹æ±‚"
+msgstr[0] "%d 個開放中åˆä½µè«‹æ±‚"
msgid "1 pipeline"
msgid_plural "%d pipelines"
@@ -217,53 +220,53 @@ msgstr[0] "%d æ¢æµæ°´ç·š"
msgid "1 role"
msgid_plural "%d roles"
-msgstr[0] ""
+msgstr[0] "%d 個角色"
msgid "1 user"
msgid_plural "%d users"
-msgstr[0] ""
+msgstr[0] "%d ä½ä½¿ç”¨è€…"
msgid "1st contribution!"
-msgstr "第一次å”作"
+msgstr "第一次å”作ï¼"
msgid "2FA enabled"
msgstr "已啟用雙é‡èªè­‰"
msgid "403|Please contact your GitLab administrator to get the permission."
-msgstr "403 |è«‹è¯ç¹«æ‚¨çš„GitLab管ç†å“¡ä»¥ç²å–權é™ã€‚"
+msgstr "è«‹è¯çµ¡æ‚¨çš„ GitLab 管ç†å“¡ä»¥å–得權é™ã€‚"
msgid "403|You don't have the permission to access this page."
-msgstr "您無權使用這個é é¢ã€‚"
+msgstr "您無權使用此é é¢ã€‚"
msgid "404|Make sure the address is correct and the page hasn't moved."
-msgstr "404 |請確ä¿ç¶²å€æ­£ç¢ºä¸”網é ä½ç½®æ²’有被更改。"
+msgstr "請確ä¿ç¶²å€æ­£ç¢ºä¸”網é æ²’被移動。"
msgid "404|Page Not Found"
-msgstr "無法找到網é "
+msgstr "找ä¸åˆ°ç¶²é "
msgid "404|Please contact your GitLab administrator if you think this is a mistake."
-msgstr "404 |如果您èªç‚ºé€™æ˜¯éŒ¯èª¤ï¼Œè«‹è¯ç¹«æ‚¨çš„GitLab管ç†å“¡ã€‚"
+msgstr "如果您èªç‚ºé€™æ˜¯å€‹éŒ¯èª¤ï¼Œè«‹è¯çµ¡æ‚¨çš„ GitLab 管ç†å“¡ã€‚"
msgid "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> will add \"By <a href=\"#\">@johnsmith</a>\" to all issues and comments originally created by johnsmith@example.com, and will set <a href=\"#\">@johnsmith</a> as the assignee on all issues originally assigned to johnsmith@example.com."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"@johnsmith\"</code> 將會在所有原本由 johnsmith@example.com 建立的議題和留言中加上「來自 <a href=\"#\">@johnsmith</a>ã€ä¸¦å°‡åŽŸæœ¬åˆ†é…給 johnsmith@example.com 的所有議題設定 <a href=\"#\">@johnsmith</a> 為å—讓人。"
msgid "<code>\"johnsmith@example.com\": \"John Smith\"</code> will add \"By John Smith\" to all issues and comments originally created by johnsmith@example.com."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"John Smith\"</code> 將會在所有原本由 johnsmith@example.com 建立的議題和留言中加上「來自 John Smithã€ã€‚"
msgid "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> will add \"By johnsm...@example.com\" to all issues and comments originally created by johnsmith@example.com. The email address or username is masked to ensure the user's privacy."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"johnsm...@example.com\"</code> 將會在所有原本由 johnsmith@example.com 建立的議題和留言中加上「來自 johnsm...@example.comã€ã€‚é›»å­ä¿¡ç®±ä½å€æˆ–使用者å稱將被é®è”½ï¼Œä»¥ä¿è­·ä½¿ç”¨è€…çš„éš±ç§å®‰å…¨ã€‚"
msgid "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> will add \"By <a href=\"#\">johnsmith@example.com</a>\" to all issues and comments originally created by johnsmith@example.com. By default, the email address or username is masked to ensure the user's privacy. Use this option if you want to show the full email address."
-msgstr ""
+msgstr "<code>\"johnsmith@example.com\": \"johnsmith@example.com\"</code> 將會在所有原本由 johnsmith@example.com 建立的議題和留言中加上「來自 <a href=\"#\">johnsmith@example.com</a>ã€ã€‚é è¨­ç‹€æ…‹é›»å­ä¿¡ç®±ä½å€æˆ–使用者å稱將被é®è”½ä»¥ä¿è­·ä½¿ç”¨è€…çš„éš±ç§å®‰å…¨ï¼Œå¦‚果您想è¦é¡¯ç¤ºå®Œæ•´çš„é›»å­ä¿¡ç®±ä½å€ï¼Œè«‹ä½¿ç”¨æ­¤é¸é …。"
msgid "<strong>%{changedFilesLength} unstaged</strong> and <strong>%{stagedFilesLength} staged</strong> changes"
-msgstr ""
+msgstr "<strong>%{changedFilesLength} 個未暫存</strong>和 <strong>%{stagedFilesLength} 個已暫存</strong> 變更"
msgid "<strong>%{created_count}</strong> created, <strong>%{accepted_count}</strong> accepted."
-msgstr "建立 <strong>%{created_count}</strong> 個,åŒæ„ <strong>%{accepted_count}</strong> 個。"
+msgstr "已建立 <strong>%{created_count}</strong> 個和åŒæ„ <strong>%{accepted_count}</strong> 個。"
msgid "<strong>%{created_count}</strong> created, <strong>%{closed_count}</strong> closed."
-msgstr "建立 <strong>%{created_count}</strong> 個,關閉 <strong>%{closed_count}</strong> 個。"
+msgstr "建立 <strong>%{created_count}</strong> 個和關閉 <strong>%{closed_count}</strong> 個。"
msgid "<strong>%{group_name}</strong> group members"
msgstr "<strong>%{group_name}</strong> 群組æˆå“¡"
@@ -272,25 +275,34 @@ msgid "<strong>%{pushes}</strong> pushes, more than <strong>%{commits}</strong>
msgstr "æŽ¨é€ <strong>%{pushes}</strong> 個,<strong>%{people}</strong> 個貢ç»è€…æäº¤äº†è¶…éŽ <strong>%{commits}</strong> 個æ交。"
msgid "<strong>Removes</strong> source branch"
-msgstr "<strong>刪除</strong>來æºåˆ†æ”¯"
+msgstr "<strong>移除</strong>來æºåˆ†æ”¯"
msgid "A 'Runner' is a process which runs a job. You can set up as many Runners as you need."
-msgstr "一個「執行器ã€æ˜¯ä¸€å€‹åŸ·è¡Œå·¥ä½œçš„進程。你å¯ä»¥å®‰è£ä½ éœ€è¦çš„多個執行器。"
+msgstr "一個「執行器ã€æ˜¯ä¸€å€‹åŸ·è¡Œå·¥ä½œçš„程åºã€‚ä½ å¯ä»¥è¨­å®šä½ æ‰€éœ€çš„執行器數é‡ã€‚"
msgid "A collection of graphs regarding Continuous Integration"
-msgstr "æŒçºŒæ•´åˆç›¸é—œçš„圖表"
+msgstr "Continuous æ•´åˆç›¸é—œåœ–表"
+
+msgid "A default branch cannot be chosen for an empty project."
+msgstr "無法å°ä¸€å€‹ç©ºå°ˆæ¡ˆé¸å®šé è¨­åˆ†æ”¯ã€‚"
+
+msgid "A deleted user"
+msgstr "已刪除的使用者"
+
+msgid "A member of GitLab's abuse team will review your report as soon as possible."
+msgstr ""
msgid "A new branch will be created in your fork and a new merge request will be started."
-msgstr "將會å†å‰µå»ºä¸€å€‹æ–°çš„分支,並建立一個新的åˆä½µè«‹æ±‚。"
+msgstr "將會在您的分支中建立一個新的分支,並建立一個新的åˆä½µè«‹æ±‚。"
msgid "A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), %{among_other_things_link}."
-msgstr "一個專案æ供了以下功能,存放你的文件(存儲庫),計劃你的工作(è­°é¡Œ),並發布你的文件(維基), %{among_other_things_link}。"
+msgstr "專案å¯ä»¥è®“你存放您的檔案(版本庫)ã€è¨ˆåŠƒæ‚¨çš„工作(議題)與發佈文件(Wiki),還有 %{among_other_things_link}。"
msgid "A regular expression that will be used to find the test coverage output in the job trace. Leave blank to disable"
-msgstr "正則表é”å¼ï¼Œå°‡ç”¨æ–¼åœ¨ä½œæ¥­è·Ÿè¸ªä¸­æŸ¥æ‰¾æ¸¬è©¦è¦†è“‹çŽ‡çš„輸出。留空時åœç”¨æ­¤åŠŸèƒ½"
+msgstr "æ­£è¦è¡¨é”å¼å°‡æœƒç”¨ä¾†å°‹æ‰¾å·¥ä½œè¿½è¹¤ä¸­çš„測試覆蓋輸出。留白以åœç”¨"
msgid "A user with write access to the source branch selected this option"
-msgstr "一個有存å–原始分支權é™çš„使用者,é¸æ“‡äº†æ­¤é …ç›®"
+msgstr "一個有來æºåˆ†æ”¯å¯«å…¥æ¬Šé™çš„使用者é¸æ“‡äº†é€™å€‹é¸é …"
msgid "About GitLab"
msgstr "關於 GitLab"
@@ -305,10 +317,10 @@ msgid "About this feature"
msgstr "關於此功能"
msgid "Abuse Reports"
-msgstr "濫用報告"
+msgstr "回報濫用"
msgid "Abuse reports"
-msgstr "濫用報告"
+msgstr "回報濫用"
msgid "Accept terms"
msgstr "接å—æ¢æ¬¾"
@@ -320,28 +332,25 @@ msgid "Access Tokens"
msgstr "å­˜å–憑證"
msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "å­˜å–被拒ï¼è«‹é©—證您是å¦å¯ä»¥åœ¨æ­¤ç‰ˆæœ¬åº«éƒ¨å±¬é‡‘鑰。"
+msgstr "å­˜å–被拒ï¼è«‹ç¢ºèªæ‚¨æ˜¯å¦å¯ä»¥åœ¨æ­¤ç‰ˆæœ¬åº«éƒ¨å±¬é‡‘鑰。"
+
+msgid "Access expiration date"
+msgstr "å­˜å–éŽæœŸæ—¥æœŸ"
msgid "Access to '%{classification_label}' not allowed"
msgstr "ä¸å…許存å–「%{classification_label}ã€"
-msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
-msgstr "已暫時åœç”¨å¤±æ•—çš„ Git 儲存空間。當儲存空間æ¢å¾©æ­£å¸¸å¾Œï¼Œè«‹é‡ç½®å„²å­˜ç©ºé–“å¥åº·æŒ‡æ•¸ã€‚"
-
-msgid "Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report."
-msgstr "å­˜å–您執行器憑證,自定義您的æµæ°´ç·šé…置,並查看你的æµæ°´ç¾ç‹€æ…‹åŠæ¸¬è©¦æ¶µè“‹çŽ‡å ±å‘Šã€‚"
-
msgid "Account"
msgstr "帳號"
msgid "Account and limit"
-msgstr "帳戶和é™åˆ¶"
+msgstr "帳戶與é™åˆ¶"
msgid "Active"
msgstr "啟用"
msgid "Active Sessions"
-msgstr "連線中的è£ç½®"
+msgstr "連線階段"
msgid "Activity"
msgstr "活動"
@@ -350,43 +359,67 @@ msgid "Add"
msgstr "新增"
msgid "Add Changelog"
-msgstr "新增更新日誌"
+msgstr "新增變更記錄"
msgid "Add Contribution guide"
-msgstr "新增å”作指å—"
+msgstr "新增貢ç»æŒ‡å—"
msgid "Add Group Webhooks and GitLab Enterprise Edition."
msgstr "新增群組 Webhook å’Œ GitLab ä¼æ¥­ç‰ˆæœ¬ã€‚"
+msgid "Add Jaeger URL"
+msgstr ""
+
msgid "Add Kubernetes cluster"
msgstr "增加 Kubernetes å¢é›†"
-msgid "Add License"
-msgstr "新增授權æ¢æ¬¾"
-
msgid "Add Readme"
msgstr "增加說明檔案"
+msgid "Add a homepage to your wiki that contains information about your project and GitLab will display it here instead of this message."
+msgstr ""
+
+msgid "Add a table"
+msgstr ""
+
msgid "Add additional text to appear in all email communications. %{character_limit} character limit"
-msgstr "增加顯示於所有電å­éƒµä»¶å°è©±çš„附加文字。最多 %{character_limit} 個字。"
+msgstr "增加顯示於所有電å­éƒµä»¶å°è©±çš„附加文字。最多 %{character_limit} 個字元。"
+
+msgid "Add comment now"
+msgstr ""
+
+msgid "Add image comment"
+msgstr ""
+
+msgid "Add license"
+msgstr "新增授權"
msgid "Add new application"
msgstr "建立新應用程å¼"
msgid "Add new directory"
-msgstr "新增目錄"
+msgstr "建立新目錄"
+
+msgid "Add projects"
+msgstr ""
msgid "Add reaction"
-msgstr "添加回應"
+msgstr "建立回應"
+
+msgid "Add to review"
+msgstr ""
msgid "Add todo"
-msgstr "增加待辦事項"
+msgstr "建立待辦事項"
msgid "Add user(s) to the group:"
-msgstr "加入使用者至群組:"
+msgstr "將使用者加到群組:"
msgid "Add users to group"
-msgstr "加入使用者到群組"
+msgstr "將使用者加到群組"
+
+msgid "Adding new applications is disabled in your GitLab instance. Please contact your GitLab administrator to get the permission"
+msgstr "您的 GitLab 實例已經åœç”¨ã€Œå»ºç«‹æ–°æ‡‰ç”¨ç¨‹å¼ã€åŠŸèƒ½ã€‚è«‹è¯çµ¡æ‚¨çš„ GitLab 管ç†å“¡ä»¥å–得此權é™"
msgid "Additional text"
msgstr "附加文字"
@@ -395,16 +428,16 @@ msgid "Admin Area"
msgstr "管ç†å€å¡Š"
msgid "Admin Overview"
-msgstr "管ç†å“¡æ¦‚覽"
+msgstr "管ç†æ¦‚覽"
msgid "Admin area"
msgstr "管ç†å€å¡Š"
msgid "AdminArea| You are about to permanently delete the user %{username}. Issues, merge requests, and groups linked to them will be transferred to a system-wide \"Ghost-user\". To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "您正打算永久刪除 %{username} 使用者。連çµä»–們的議題ã€åˆä½µè«‹æ±‚與群組將會移轉到系統全域的一ä½ä½¿ç”¨è€…「Ghost-userã€ã€‚è‹¥è¦é¿å…資料éºå¤±ï¼Œè«‹è€ƒæ…®æ”¹ç”¨%{strong_start}å°éŽ–使用者%{strong_end}功能。當你執行了%{strong_start}刪除使用者%{strong_end},則該動作將無法復原。"
msgid "AdminArea| You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "您正打算永久刪除 %{username} 使用者。這將會刪除連çµä»–們的議題ã€åˆä½µè«‹æ±‚與群組。若è¦é¿å…資料éºå¤±ï¼Œè«‹è€ƒæ…®æ”¹ç”¨%{strong_start}å°éŽ–使用者%{strong_end}功能。當你執行了%{strong_start}刪除使用者%{strong_end},則該動作將無法復原。"
msgid "AdminArea|Stop all jobs"
msgstr "åœæ­¢æ‰€æœ‰ä»»å‹™"
@@ -419,13 +452,10 @@ msgid "AdminArea|Stopping jobs failed"
msgstr "åœæ­¢ä»»å‹™å¤±æ•—"
msgid "AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running."
-msgstr "您將åœæ­¢æ‰€æœ‰ä»»å‹™ï¼Œé€™å°‡æœƒæš«åœæ‰€æœ‰æ­£åœ¨é‹è¡Œçš„任務。"
-
-msgid "AdminHealthPageLink|health page"
-msgstr "系統狀態"
+msgstr "您打算è¦åœæ­¢æ‰€æœ‰ä»»å‹™ï¼Œé€™å°‡æœƒæš«åœæ‰€æœ‰æ­£åœ¨åŸ·è¡Œä¸­çš„任務。"
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources including issues, merge requests, etc.. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
-msgstr ""
+msgstr "您正打算永久刪除 %{projectName} 專案ã€èˆ‡å…¶ç‰ˆæœ¬åº«ã€å’Œæ‰€æœ‰ç›¸é—œçš„資æºï¼Œä¾‹å¦‚è­°é¡Œã€åˆä½µè«‹æ±‚等等…當您確èªä¸¦æŒ‰ä¸‹%{strong_start}刪除專案%{strong_end},該動作將無法復原。"
msgid "AdminProjects|Delete"
msgstr "刪除"
@@ -437,7 +467,7 @@ msgid "AdminProjects|Delete project"
msgstr "刪除專案"
msgid "AdminSettings|Specify a domain to use by default for every project's Auto Review Apps and Auto Deploy stages."
-msgstr "為æ¯å€‹å°ˆæ¡ˆçš„自動複閱應用åŠè‡ªå‹•éƒ¨ç½²æŒ‡å®šä¸€å€‹é è¨­çš„網域"
+msgstr "為æ¯å€‹å°ˆæ¡ˆçš„自動審閱應用程å¼åŠè‡ªå‹•éƒ¨ç½²éšŽæ®µæŒ‡å®šä¸€å€‹é è¨­çš„網域"
msgid "AdminUsers|Block user"
msgstr "å°éŽ–使用者"
@@ -455,46 +485,59 @@ msgid "AdminUsers|Delete user and contributions"
msgstr "刪除使用者åŠå…¶è²¢ç»"
msgid "AdminUsers|To confirm, type %{projectName}"
-msgstr "請輸入 %{projectName} 以進行確èª"
+msgstr "請輸入 %{projectName} 進行確èª"
msgid "AdminUsers|To confirm, type %{username}"
-msgstr "請輸入 %{username} 以進行確èª"
+msgstr "請輸入 %{username} 進行確èª"
-msgid "Advanced"
-msgstr "進階"
+msgid "Advanced permissions, Large File Storage and Two-Factor authentication settings."
+msgstr ""
msgid "Advanced settings"
msgstr "進階設定"
+msgid "Alert"
+msgid_plural "Alerts"
+msgstr[0] ""
+
msgid "All"
msgstr "全部"
msgid "All changes are committed"
-msgstr "所有改變都已經æ交"
+msgstr "所有變更都已經æ交"
msgid "All features are enabled for blank projects, from templates, or when importing, but you can disable them afterward in the project settings."
-msgstr "從模æ¿å»ºç«‹æˆ–導入專案時將啟用所有功能,您å¯ä»¥åœ¨å°ˆæ¡ˆè¨­ç½®ä¸­å°‡å…¶é—œé–‰ã€‚"
+msgstr "已經å°ç©ºç™½ã€ä¾†è‡ªæ¨¡æ¿æˆ–匯入的專案啟用了所有功能,但你能在之後於專案設定åœç”¨å®ƒå€‘。"
msgid "All users"
-msgstr ""
+msgstr "所有使用者"
msgid "Allow commits from members who can merge to the target branch."
msgstr "å…許å¯ä»¥åˆä½µè‡³ç›®æ¨™åˆ†æ”¯çš„æˆå“¡æ交"
+msgid "Allow projects within this group to use Git LFS"
+msgstr ""
+
msgid "Allow public access to pipelines and job details, including output logs and artifacts"
msgstr "å…許公開存å–æµæ°´ç·šå’Œä»»å‹™è©³ç´°è³‡è¨Šï¼ŒåŒ…å«è¼¸å‡ºæ—¥èªŒå’Œç”¢ç‰©"
msgid "Allow rendering of PlantUML diagrams in Asciidoc documents."
-msgstr "å…許在 Asciidoc 文件中渲染 PlantUML64"
+msgstr "å…許在 Asciidoc 文件中繪製 PlantUML64 圖。"
msgid "Allow requests to the local network from hooks and services."
-msgstr "å…許來自鉤å­å’Œæœå‹™çš„å°æœ¬åœ°ç¶²çµ¡çš„請求。"
+msgstr "å…許來自觸發器和æœå‹™å°æœ¬æ©Ÿç¶²è·¯çš„請求。"
+
+msgid "Allow users to request access"
+msgstr ""
+
+msgid "Allow users to request access if visibility is public or internal."
+msgstr ""
msgid "Allows you to add and manage Kubernetes clusters."
-msgstr "å…許您增加和管ç†Kuberneteså¢é›†ã€‚"
+msgstr "å…è¨±æ‚¨å¢žåŠ å’Œç®¡ç† Kubernetes å¢é›†ã€‚"
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
-msgstr "也被稱為「議題æ“有者ã€æˆ–「ä¾è³´æ–¹ä¿¡ä»»æ¨™è­˜æ¨™ç±¤ã€"
+msgstr "也被稱為「議題æ“有者ã€æˆ–「ä¾è³´æ–¹ä¿¡ä»»èº«ä»½è­˜åˆ¥ã€"
msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr "也稱為「ä¾è³´æ–¹æœå‹™ URLã€æˆ–「回覆 URLã€"
@@ -503,16 +546,19 @@ msgid "Alternatively, you can use a %{personal_access_token_link}. When you crea
msgstr "或者,你å¯ä»¥ä½¿ç”¨ %{personal_access_token_link}。當你建立你的個人存å–憑證時,你將需è¦é¸æ“‡<code>版本庫</code>範åœï¼Œæ‰€ä»¥æˆ‘們å¯ä»¥é¡¯ç¤ºä½ å¯ä»¥é€£ç·šä¹‹å…¬é–‹åŠç§å¯†çš„版本庫清單。"
msgid "Alternatively, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
-msgstr "或者,你å¯ä»¥ä½¿ç”¨ %{personal_access_token_link}。當你建立你的個人存å–權æ–時,你將需è¦é¸æ“‡<code>檔案庫</code>範åœï¼Œæ‰€ä»¥æˆ‘們將會顯示你公開åŠç§äººçš„檔案庫清單進行匯入。"
+msgstr "或者,你å¯ä»¥ä½¿ç”¨ %{personal_access_token_link}。當你建立你的個人存å–憑證時,你將需è¦é¸æ“‡<code>版本庫</code>範åœï¼Œæ‰€ä»¥æˆ‘們將會顯示能匯入的公開åŠç§å¯†çš„版本庫清單。"
-msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgid "Amount of time (in hours) that users are allowed to skip forced configuration of two-factor authentication"
msgstr ""
+msgid "An SSH key will be automatically generated when the form is submitted. For more information, please refer to the documentation."
+msgstr "æ交此表單時將會自動產生 SSH 金鑰。若須更多資訊請åƒè€ƒæ–‡ä»¶ã€‚"
+
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr "一個自稱 %{link_to_client} 的應用程å¼è«‹æ±‚您 GitLab 帳號的存å–權。"
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
-msgstr ""
+msgstr "空的 GitLab 使用者欄ä½å°‡æœƒåœ¨æ‰€æœ‰è­°é¡Œèˆ‡èªªæ˜Žçš„說明欄增加 FogBugz 使用者的完整å稱 (例如:「來自 John Smithã€)。其也將與專案建立者關è¯ä¸¦ (或) 分é…這些議題以åŠç•™è¨€ã€‚"
msgid "An error accured whilst committing your changes."
msgstr "æ交您的變更時發生錯誤"
@@ -526,8 +572,8 @@ msgstr "創建新分支時發生錯誤。"
msgid "An error occured whilst fetching the job trace."
msgstr "å–得工作追蹤資訊時發生錯誤"
-msgid "An error occured whilst fetching the latest pipline."
-msgstr "å–得最新æµæ°´ç·šæ™‚發生錯誤"
+msgid "An error occured whilst fetching the latest pipeline."
+msgstr ""
msgid "An error occured whilst loading all the files."
msgstr "讀å–檔案時發生錯誤。"
@@ -550,6 +596,12 @@ msgstr "讀å–åˆä½µè«‹æ±‚時發生錯誤。"
msgid "An error occured whilst loading the pipelines jobs."
msgstr "載入æµæ°´ç·šå·¥ä½œçš„åŒæ™‚發生了錯誤"
+msgid "An error occurred adding a draft to the discussion."
+msgstr ""
+
+msgid "An error occurred adding a new draft."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "é è¦½ blob 檔案時發生錯誤"
@@ -562,6 +614,9 @@ msgstr "æ›´æ–°å•é¡Œæ¬Šé‡æ™‚發生錯誤"
msgid "An error occurred while adding approver"
msgstr "增加審核者時發生錯誤"
+msgid "An error occurred while deleting the comment"
+msgstr ""
+
msgid "An error occurred while detecting host keys"
msgstr "åµæ¸¬ä¸»æ©Ÿé‡‘鑰時發生錯誤"
@@ -574,20 +629,23 @@ msgstr "解除亮高顯示時發生錯誤,請é‡æ–°æ•´ç†é é¢å†æ¬¡å˜—試。
msgid "An error occurred while fetching markdown preview"
msgstr "è®€å– markdown é è¦½æ™‚發生錯誤"
+msgid "An error occurred while fetching pending comments"
+msgstr ""
+
msgid "An error occurred while fetching sidebar data"
msgstr "讀å–å´é‚Šæ¬„資料時發生錯誤"
msgid "An error occurred while fetching stages."
-msgstr ""
+msgstr "抓å–狀態時發生錯誤。"
msgid "An error occurred while fetching the job log."
-msgstr ""
+msgstr "抓å–工作日誌時發生錯誤。"
msgid "An error occurred while fetching the job."
-msgstr ""
+msgstr "抓å–工作時發生錯誤。"
msgid "An error occurred while fetching the jobs."
-msgstr ""
+msgstr "抓å–工作時發生錯誤。"
msgid "An error occurred while fetching the pipeline."
msgstr "讀å–æµæ°´ç·šæ™‚發生錯誤"
@@ -596,11 +654,14 @@ msgid "An error occurred while getting projects"
msgstr "讀å–專案時發生錯誤"
msgid "An error occurred while importing project: %{details}"
-msgstr ""
+msgstr "匯入專案時發生錯誤:%{details}"
msgid "An error occurred while initializing path locks"
msgstr "åˆå§‹åŒ–路徑鎖時發生錯誤"
+msgid "An error occurred while loading chart data"
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "載入æ交簽å時發生錯誤"
@@ -643,12 +704,18 @@ msgstr "訂閱通知時發生錯誤。"
msgid "An error occurred while unsubscribing to notifications."
msgstr "當å–消訂閱通知時發生錯誤"
+msgid "An error occurred while updating the comment"
+msgstr ""
+
msgid "An error occurred while validating username"
msgstr "驗證使用者å稱時發生錯誤"
msgid "An error occurred. Please try again."
msgstr "發生錯誤,請å†è©¦ä¸€æ¬¡ã€‚"
+msgid "Analytics"
+msgstr ""
+
msgid "Anonymous"
msgstr "匿å"
@@ -667,8 +734,8 @@ msgstr "外觀"
msgid "Application"
msgstr "應用程å¼"
-msgid "Application Id"
-msgstr "æ‡‰ç”¨ç¨‹å¼ ID"
+msgid "Application ID"
+msgstr ""
msgid "Application: %{name}"
msgstr "應用程å¼ï¼š%{name}"
@@ -685,14 +752,20 @@ msgstr "四月"
msgid "Archived project! Repository and other project resources are read-only"
msgstr "這是個已經å°å­˜çš„專案ï¼å…¶æª”案庫與其其他專案資æºç‚ºå”¯è®€ç‹€æ…‹ã€‚"
+msgid "Archived projects"
+msgstr "å·²å°å­˜çš„專案"
+
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr "確定è¦åˆªé™¤æ­¤æµæ°´ç·šæŽ’程嗎?"
-msgid "Are you sure you want to lose unsaved changes?"
+msgid "Are you sure you want to erase this build?"
msgstr ""
+msgid "Are you sure you want to lose unsaved changes?"
+msgstr "您確定è¦æ”¾æ£„未儲存的變更嗎?"
+
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
-msgstr ""
+msgstr "確èªé‡æ–°ç”¢ç”Ÿå…¬é‘°ï¼Ÿæ‚¨å°‡éœ€è¦åœ¨é‡æ–°é‹ä½œé¡åƒå‰ï¼Œæ›´æ–°é ç«¯ä¼ºæœå™¨ä¸Šçš„公鑰。"
msgid "Are you sure you want to remove %{group_name}?"
msgstr "確定移除 %{group_name}?"
@@ -706,6 +779,9 @@ msgstr "確定è¦é‡ç½®è¨»å†Šæ†‘證嗎?"
msgid "Are you sure you want to reset the health check token?"
msgstr "確定è¦é‡ç½®å¥åº·æª¢æŸ¥å­˜å–憑證嗎?"
+msgid "Are you sure you want to stop this environment?"
+msgstr ""
+
msgid "Are you sure you want to unlock %{path_lock_path}?"
msgstr "你確定è¦è§£éŽ– %{path_lock_path} ?"
@@ -713,7 +789,7 @@ msgid "Are you sure?"
msgstr "確定嗎?"
msgid "Artifact ID"
-msgstr ""
+msgstr "æˆå“ ID"
msgid "Artifacts"
msgstr "產物"
@@ -755,7 +831,7 @@ msgid "Assignee"
msgstr "指派人"
msgid "Assignee lists not available with your current license"
-msgstr ""
+msgstr "被指派者åå–®ä¸æ”¯æ´æ‚¨ç›®å‰çš„授權"
msgid "Assignee lists show all issues assigned to the selected user."
msgstr "指派列表顯示了分é…給é¸å®šä½¿ç”¨è€…的所有議題"
@@ -782,7 +858,7 @@ msgid "Authentication log"
msgstr "èªè­‰è¨˜éŒ„"
msgid "Authentication method"
-msgstr ""
+msgstr "èªè­‰æ–¹æ³•"
msgid "Author"
msgstr "作者"
@@ -844,6 +920,9 @@ msgstr "將根據設定的的 CI / CD æµç¨‹è‡ªå‹•å»ºæ§‹ã€æ¸¬è©¦å’Œéƒ¨ç½²æ‡‰ç”¨
msgid "AutoDevOps|Learn more in the %{link_to_documentation}"
msgstr "了解更多於 %{link_to_documentation}"
+msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}"
+msgstr "自動 DevOps æµæ°´ç·šå·²ç¶“啟用,且會在沒有替代 CI 組態檔案å¯ç”¨çš„情æ³ä¸‹ä½¿ç”¨ã€‚%{more_information_link}"
+
msgid "AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}."
msgstr "如果 %{link_to_auto_devops_settings} 這個專案,您å¯ä»¥è‡ªå‹•å»ºç½®å’Œæ¸¬è©¦ä½ çš„æ‡‰ç”¨ç¨‹å¼ %{link_to_add_kubernetes_cluster} 則å¯ä»¥è®“你自動部署"
@@ -854,7 +933,7 @@ msgid "AutoDevOps|enable Auto DevOps"
msgstr "啟用自動 DevOps"
msgid "Automatically marked as default internal user"
-msgstr ""
+msgstr "自動標記為é è¨­æœ¬æ©Ÿä½¿ç”¨è€…"
msgid "Available"
msgstr "能é‹åšçš„"
@@ -880,9 +959,6 @@ msgstr "背景作業"
msgid "Background color"
msgstr "背景é¡è‰²"
-msgid "Background jobs"
-msgstr "背景工作"
-
msgid "Badges"
msgstr "徽章"
@@ -923,7 +999,7 @@ msgid "Badges|No image to preview"
msgstr "沒有圖片å¯ä»¥é è¦½"
msgid "Badges|Please fill in a valid URL"
-msgstr ""
+msgstr "請填寫有效 URL"
msgid "Badges|Project Badge"
msgstr "專案徽章"
@@ -953,12 +1029,21 @@ msgid "Badges|This project has no badges"
msgstr "此專案無徽章"
msgid "Badges|You are going to delete this badge. Deleted badges <strong>cannot</strong> be restored."
-msgstr ""
+msgstr "您打算刪除此徵章。刪除的徵章將<strong>ä¸èƒ½</strong>復原。"
msgid "Badges|Your badges"
msgstr "您的徽章"
msgid "Badges|e.g. %{exampleUrl}"
+msgstr "例如 %{exampleUrl}"
+
+msgid "BatchComments|Delete all pending comments"
+msgstr ""
+
+msgid "BatchComments|Discard review?"
+msgstr ""
+
+msgid "BatchComments|You're about to discard your review which will delete all of your pending comments. The deleted comments %{strong_start}cannot%{strong_end} be restored."
msgstr ""
msgid "Begin with the selected commit"
@@ -989,7 +1074,7 @@ msgid "BillingPlans|Downgrade"
msgstr "é™ç´š"
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Gold."
-msgstr ""
+msgstr "閱讀我們的 %{faq_link} 連çµï¼Œä¾†å¾—知關於æ¯å€‹æ–¹æ¡ˆçš„資訊,或是開始 30 天å…費的 GitLab.com Gold 試用版。"
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}."
msgstr "é€éŽé–±è®€ %{faq_link} 了解更多我們的æ¯å€‹æ–¹æ¡ˆ"
@@ -1037,7 +1122,7 @@ msgid "BillingPlans|per user"
msgstr "æ¯ä½ä½¿ç”¨è€…"
msgid "Bitbucket Server Import"
-msgstr ""
+msgstr "匯入 BitBucket 伺æœå™¨"
msgid "Bitbucket import"
msgstr "匯入 Bitbucket"
@@ -1209,7 +1294,7 @@ msgid "Browse files"
msgstr "ç€è¦½æª”案"
msgid "Built-In"
-msgstr ""
+msgstr "内建"
msgid "Business metrics (Custom)"
msgstr "ä¼æ¥­æŒ‡æ¨™ï¼ˆè‡ªè¨‚)"
@@ -1224,7 +1309,7 @@ msgid "CI / CD Settings"
msgstr "CI / CD 設定"
msgid "CI will run using the credentials assigned above."
-msgstr ""
+msgstr "CI 將會使用底下指定的憑證執行。"
msgid "CI/CD"
msgstr "CI / CD"
@@ -1250,9 +1335,12 @@ msgstr "至動部屬到模擬環境,手動部屬到正å¼ç’°å¢ƒ"
msgid "CICD|Continuous deployment to production"
msgstr "æŒçºŒéƒ¨å±¬åˆ°æ­£å¼ç’°å¢ƒ"
-msgid "CICD|Default to Auto DevOps pipeline"
+msgid "CICD|Continuous deployment to production using timed incremental rollout"
msgstr ""
+msgid "CICD|Default to Auto DevOps pipeline"
+msgstr "é è¨­ä½¿ç”¨è‡ªå‹• DevOps æµæ°´ç·š"
+
msgid "CICD|Deployment strategy"
msgstr "部屬策略"
@@ -1269,20 +1357,17 @@ msgid "CICD|Learn more about Auto DevOps"
msgstr "學習更多關於 Auto DevOps 的相關訊æ¯"
msgid "CICD|The Auto DevOps pipeline will run if no alternative CI configuration file is found."
-msgstr ""
+msgstr "自動 DevOps æµæ°´ç·šå°‡æœƒåœ¨æ²’有替代 CI 組態檔案的情æ³ä¸‹åŸ·è¡Œã€‚"
msgid "CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages."
msgstr "如果你想è¦ä½¿ç”¨è‡ªå‹•è¤‡é–±ç¨‹å¼åŠè‡ªå‹•éƒ¨ç½²ï¼Œè«‹æŒ‡å®šç¶²åŸŸã€‚"
msgid "CICD|instance enabled"
-msgstr ""
+msgstr "已啟用實例"
msgid "Callback URL"
msgstr "回呼 URL"
-msgid "Callback url"
-msgstr "回呼 url"
-
msgid "Can't find HEAD commit for this branch"
msgstr "找ä¸åˆ°æ­¤åˆ†æ”¯çš„ HEAD 更動。"
@@ -1305,7 +1390,7 @@ msgid "Change Weight"
msgstr "變更權é‡"
msgid "Change template"
-msgstr ""
+msgstr "變更模æ¿"
msgid "Change this value to influence how frequently the GitLab UI polls for updates."
msgstr "更改此數值將影響到 GitLab UI 拉å–更新的頻率。"
@@ -1337,8 +1422,8 @@ msgstr "統計圖"
msgid "Chat"
msgstr "å³æ™‚通訊"
-msgid "Check interval"
-msgstr "檢查間隔"
+msgid "Check the %{docs_link_start}documentation%{docs_link_end}."
+msgstr ""
msgid "Checking %{text} availability…"
msgstr "正在檢查%{text} å¯ç”¨æ€§.."
@@ -1364,6 +1449,12 @@ msgstr "é¸æ“‡æª”案⋯"
msgid "Choose a branch/tag (e.g. %{master}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
msgstr "é¸æ“‡åˆ†æ”¯/標籤(例如:%{master})或者輸入更動紀錄(例如:%{sha})以查看更改內容或建立åˆä½µè«‹æ±‚。"
+msgid "Choose a template..."
+msgstr "é¸æ“‡æ¨¡æ¿â€¦"
+
+msgid "Choose a type..."
+msgstr "é¸æ“‡é¡žåž‹â€¦"
+
msgid "Choose any color."
msgstr "é¸å–é¡è‰²ã€‚"
@@ -1374,7 +1465,7 @@ msgid "Choose file..."
msgstr "é¸æ“‡æª”案⋯"
msgid "Choose the top-level group for your repository imports."
-msgstr ""
+msgstr "é¸æ“‡æ‚¨ç‰ˆæœ¬åº«åŒ¯å…¥é …目的頂級群組。"
msgid "Choose which groups you wish to synchronize to this secondary node."
msgstr "é¸æ“‡æ‚¨å¸Œæœ›èˆ‡é€™å€‹æ¬¡è¦ç¯€é»žåŒæ­¥çš„群組"
@@ -1394,6 +1485,9 @@ msgstr "å·²å–消"
msgid "CiStatusLabel|created"
msgstr "已建立"
+msgid "CiStatusLabel|delayed"
+msgstr ""
+
msgid "CiStatusLabel|failed"
msgstr "失敗"
@@ -1412,6 +1506,9 @@ msgstr "等待中"
msgid "CiStatusLabel|skipped"
msgstr "已略éŽ"
+msgid "CiStatusLabel|waiting for delayed job"
+msgstr ""
+
msgid "CiStatusLabel|waiting for manual action"
msgstr "等待手動æ“作"
@@ -1424,6 +1521,9 @@ msgstr "å·²å–消"
msgid "CiStatusText|created"
msgstr "已建立"
+msgid "CiStatusText|delayed"
+msgstr ""
+
msgid "CiStatusText|failed"
msgstr "失敗"
@@ -1478,12 +1578,12 @@ msgstr "切æ›ç‚ºä¿è­·ç‹€æ…‹"
msgid "CiVariable|Validation failed"
msgstr "驗證失敗"
-msgid "CircuitBreakerApiLink|circuitbreaker api"
-msgstr "斷路器 Api"
-
msgid "ClassificationLabelUnavailable|is unavailable: %{reason}"
msgstr "無法使用:%{reason}"
+msgid "Clear search"
+msgstr ""
+
msgid "Clear search input"
msgstr "清除æœå°‹ç´€éŒ„"
@@ -1497,7 +1597,7 @@ msgid "Click the <strong>Promote</strong> button in the top right corner to prom
msgstr "點擊左上角的<strong>å‡ç´š</strong>按鈕,將æå‡è‡³ç¾¤çµ„里程碑。"
msgid "Click the <strong>Select none</strong> button on the right, since we only need \"Google Code Project Hosting\"."
-msgstr ""
+msgstr "點擊å³å´çš„ <strong>ä¸é¸æ“‡</strong> 按鈕,因為我們åªéœ€è¦ã€ŒGoogle Code 專案寄存ã€ã€‚"
msgid "Click the button below to begin the install process by navigating to the Kubernetes page"
msgstr "點擊下é¢çš„按鈕,連çµåˆ° Kubernetes é é¢é–‹å§‹å®‰è£ã€‚"
@@ -1526,6 +1626,9 @@ msgstr "複製檔案庫"
msgid "Close"
msgstr "關閉"
+msgid "Close epic"
+msgstr "關閉 Epic"
+
msgid "Closed"
msgstr "已關閉"
@@ -1538,12 +1641,24 @@ msgstr "%{appList} 已經æˆåŠŸå®‰è£åˆ°æ‚¨çš„ Kubernetes å¢é›†"
msgid "ClusterIntegration|%{boldNotice} This will add some extra resources like a load balancer, which may incur additional costs depending on the hosting provider your Kubernetes cluster is installed on. If you are using Google Kubernetes Engine, you can %{pricingLink}."
msgstr ""
+msgid "ClusterIntegration|A Knative build extends Kubernetes and utilizes existing Kubernetes primitives to provide you with the ability to run on-cluster container builds from source. For example, you can write a build that uses Kubernetes-native resources to obtain your source code from a repository, build it into container a image, and then run that image."
+msgstr ""
+
msgid "ClusterIntegration|API URL"
msgstr "Api 網å€"
msgid "ClusterIntegration|Add Kubernetes cluster"
msgstr "增加 Kubernetes å¢é›†"
+msgid "ClusterIntegration|Add a Kubernetes cluster integration"
+msgstr ""
+
+msgid "ClusterIntegration|Adding a Kubernetes cluster to your group will automatically share the cluster across all your projects. Use review apps, deploy your applications, and easily run your pipelines for all projects using the same cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Adding an integration to your group will share the cluster across all your projects."
+msgstr ""
+
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster's integration"
msgstr "Kubernetes å¢é›†æ•´åˆçš„進階設定"
@@ -1574,11 +1689,11 @@ msgstr "CAèªè­‰"
msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "憑證 (PEMæ ¼å¼)"
-msgid "ClusterIntegration|Choose which of your project's environments will use this Kubernetes cluster."
-msgstr "é¸æ“‡æ‚¨è¦ä½¿ç”¨æ­¤ Kubernetes å¢é›†çš„專案環境"
+msgid "ClusterIntegration|Choose which applications to install on your Kubernetes cluster. Helm Tiller is required to install any of the following applications."
+msgstr ""
-msgid "ClusterIntegration|Control how your Kubernetes cluster integrates with GitLab"
-msgstr "控制 Kubernetes å¢é›†å¦‚何與 GitLab æ•´åˆ"
+msgid "ClusterIntegration|Choose which of your environments will use this cluster."
+msgstr ""
msgid "ClusterIntegration|Copy API URL"
msgstr "複製 API 連çµ"
@@ -1604,6 +1719,12 @@ msgstr "建立 Kubernetes å¢é›†"
msgid "ClusterIntegration|Did you know?"
msgstr "你知é“嗎?"
+msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
+msgstr ""
+
+msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
+msgstr ""
+
msgid "ClusterIntegration|Enter the details for your Kubernetes cluster"
msgstr "輸入您的 Kubernetes å¢é›†è©³ç´°è³‡è¨Š"
@@ -1640,6 +1761,9 @@ msgstr "Google Kubernetes Engine"
msgid "ClusterIntegration|Google Kubernetes Engine project"
msgstr "Google Kubernetes Engine 專案"
+msgid "ClusterIntegration|Group cluster"
+msgstr ""
+
msgid "ClusterIntegration|Helm Tiller"
msgstr "Helm Tiller"
@@ -1670,9 +1794,6 @@ msgstr "安è£"
msgid "ClusterIntegration|Install Prometheus"
msgstr "å®‰è£ Prometheus"
-msgid "ClusterIntegration|Install applications on your Kubernetes cluster. Read more about %{helpLink}"
-msgstr ""
-
msgid "ClusterIntegration|Installed"
msgstr "已安è£"
@@ -1694,6 +1815,12 @@ msgstr "JupyterHub"
msgid "ClusterIntegration|JupyterHub, a multi-user Hub, spawns, manages, and proxies multiple instances of the single-user Jupyter notebook server. JupyterHub can be used to serve notebooks to a class of students, a corporate data science group, or a scientific research group."
msgstr ""
+msgid "ClusterIntegration|Knative"
+msgstr ""
+
+msgid "ClusterIntegration|Knative Domain Name:"
+msgstr ""
+
msgid "ClusterIntegration|Kubernetes cluster"
msgstr "Kubernetes å¢é›†"
@@ -1703,18 +1830,6 @@ msgstr "Kubernetes å¢é›†è©³ç´°è³‡è¨Š"
msgid "ClusterIntegration|Kubernetes cluster health"
msgstr "Kubernetes å¢é›†å¥åº·ç¨‹åº¦"
-msgid "ClusterIntegration|Kubernetes cluster integration"
-msgstr "Kubernetes å¢é›†æ•´åˆ"
-
-msgid "ClusterIntegration|Kubernetes cluster integration is disabled for this project."
-msgstr "此專案ç¦ç”¨ Kubernetes å¢é›†æ•´åˆ"
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project."
-msgstr "此專案已啟用 Kubernetes å¢é›†æ•´åˆ"
-
-msgid "ClusterIntegration|Kubernetes cluster integration is enabled for this project. Disabling this integration will not affect your Kubernetes cluster, it will only temporarily turn off GitLab's connection to it."
-msgstr "此專案已經啟用 Kubernetes å¢é›†æ•´åˆã€‚關閉此整åˆä¸¦ä¸æœƒå¼•éŸ¿æ‚¨çš„ Kubernetes å¢é›†ï¼Œä»–åªæœƒæš«æ™‚性的關閉 GitLab 與它的連çµã€‚"
-
msgid "ClusterIntegration|Kubernetes cluster is being created on Google Kubernetes Engine..."
msgstr "Kubernetes å¢é›†å·²ç¶“在 Google Kubernetes Engine 上被建立"
@@ -1724,8 +1839,8 @@ msgstr "Kubernetes å¢é›†å稱"
msgid "ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details"
msgstr "Kubernetes å¢é›†å·²ç¶“æˆåŠŸè¢«å»ºç«‹æ–¼ Google Kubernetes Engine,é‡æ–°æ•´ç†æ­¤é é¢æ‚¨å°‡æœƒçœ‹åˆ° Kubernetes å¢é›†çš„詳細資訊"
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way. %{link_to_help_page}"
-msgstr "å¢é›†è®“你用簡單的方å¼å¯©æŸ¥ã€éƒ¨ç½²æ‡‰ç”¨ç¨‹å¼ï¼Œé‹è¡Œæµæ°´ç·šç­‰åŠŸèƒ½ã€‚詳情請閱:%{link_to_help_page}"
+msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
+msgstr ""
msgid "ClusterIntegration|Kubernetes clusters can be used to deploy applications and to provide Review Apps for this project"
msgstr "Kubernetes å¢é›†å¯ä»¥ç”¨æ–¼éƒ¨ç½²æ‡‰ç”¨ç¨‹å¼ä»¥åŠç‚ºæ­¤å°ˆæ¡ˆæ供代碼審查工具"
@@ -1733,17 +1848,14 @@ msgstr "Kubernetes å¢é›†å¯ä»¥ç”¨æ–¼éƒ¨ç½²æ‡‰ç”¨ç¨‹å¼ä»¥åŠç‚ºæ­¤å°ˆæ¡ˆæä¾›ä
msgid "ClusterIntegration|Learn more about %{help_link_start_machine_type}machine types%{help_link_end} and %{help_link_start_pricing}pricing%{help_link_end}."
msgstr "瞭解有關 %{help_link_start_machine_type}機器類型%{help_link_end} 和 %{help_link_start_pricing}定價%{help_link_end} 的詳細資訊。"
-msgid "ClusterIntegration|Learn more about %{help_link_start}Kubernetes%{help_link_end}."
-msgstr "瞭解有關 %{help_link_start}Kubernetes%{help_link_end} 的詳細資訊。"
-
msgid "ClusterIntegration|Learn more about %{help_link_start}zones%{help_link_end}."
msgstr "瞭解有關 %{help_link_start}å€åŸŸ%{help_link_end} 的詳細資訊。"
-msgid "ClusterIntegration|Learn more about environments"
-msgstr "了解關於環境的更多資訊"
+msgid "ClusterIntegration|Learn more about Kubernetes"
+msgstr ""
-msgid "ClusterIntegration|Learn more about security configuration"
-msgstr "了解更多安全性設定"
+msgid "ClusterIntegration|Learn more about group Kubernetes clusters"
+msgstr ""
msgid "ClusterIntegration|Machine type"
msgstr "機器型別"
@@ -1760,9 +1872,6 @@ msgstr "請至 %{link_gke} 管ç†æ‚¨çš„ Kubernetes å¢é›†"
msgid "ClusterIntegration|More information"
msgstr "詳細資料"
-msgid "ClusterIntegration|Multiple Kubernetes clusters are available in GitLab Enterprise Edition Premium and Ultimate"
-msgstr "多個 Kubernetes å¢é›†æ–¼ GitLab ä¼æ¥­ç‰ˆæœ¬ Premium å’Œ Ultimate 中支æ´"
-
msgid "ClusterIntegration|No machine types matched your search"
msgstr "沒有機器類型符åˆæ‚¨çš„æœå°‹"
@@ -1790,6 +1899,9 @@ msgstr "請確èªä½ çš„ Google 帳號是å¦ç¬¦åˆé€™äº›æ¢ä»¶"
msgid "ClusterIntegration|Point a wildcard DNS to this generated IP address in order to access your application after it has been deployed."
msgstr ""
+msgid "ClusterIntegration|Project cluster"
+msgstr ""
+
msgid "ClusterIntegration|Project namespace"
msgstr "專案命å空間"
@@ -1802,6 +1914,9 @@ msgstr "Prometheus"
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
+msgid "ClusterIntegration|RBAC-enabled cluster"
+msgstr ""
+
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
msgstr "閱讀我們關於 Kubernetes å¢é›†æ•´åˆçš„ %{link_to_help_page}。"
@@ -1832,9 +1947,6 @@ msgstr "æœå°‹å°ˆæ¡ˆ"
msgid "ClusterIntegration|Search zones"
msgstr "æœå°‹å€åŸŸ"
-msgid "ClusterIntegration|Security"
-msgstr "安全"
-
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "查看與編輯您的 Kubernetes å¢é›†è©³ç´°è³‡è¨Š"
@@ -1874,14 +1986,11 @@ msgstr "å®‰è£ %{title} 時發生錯誤"
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
-msgid "ClusterIntegration|The default cluster configuration grants access to a wide set of functionalities needed to successfully build and deploy a containerised application."
-msgstr "é è¨­çš„å¢é›†è¨­å®šï¼Œå…許存å–廣泛的功能,用以建置和部署å¯ä»¥ä½¿ç”¨å®¹å™¨æŠ€è¡“擴充的應用程å¼ã€‚"
-
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr "此帳戶必須æ“有在 %{link_to_container_project} 中建立 Kubernetes å¢é›†çš„權é™"
-msgid "ClusterIntegration|Toggle Kubernetes Cluster"
-msgstr "åˆ‡æ› Kubernetes å¢é›†"
+msgid "ClusterIntegration|This option will allow you to install applications on RBAC clusters."
+msgstr ""
msgid "ClusterIntegration|Toggle Kubernetes cluster"
msgstr "åˆ‡æ› Kubernetes å¢é›†"
@@ -1898,6 +2007,9 @@ msgstr ""
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "當å¢é›†é€£çµåˆ°æ­¤å°ˆæ¡ˆï¼Œä½ å¯ä»¥ä½¿ç”¨è¤‡é–±æ‡‰ç”¨ï¼Œéƒ¨ç½²ä½ çš„應用程å¼ï¼ŒåŸ·è¡Œä½ çš„æµæ°´ç·šï¼Œé‚„有更多容易上手的方å¼å¯ä»¥ä½¿ç”¨ã€‚"
+msgid "ClusterIntegration|You must first install Helm Tiller before installing the applications below"
+msgstr ""
+
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "您的帳號必須有 %{link_to_kubernetes_engine}"
@@ -1916,9 +2028,6 @@ msgstr "文件"
msgid "ClusterIntegration|help page"
msgstr "說明é é¢"
-msgid "ClusterIntegration|installing applications"
-msgstr "安è£æ‡‰ç”¨ç¨‹åº"
-
msgid "ClusterIntegration|meets the requirements"
msgstr "符åˆéœ€æ±‚"
@@ -1928,6 +2037,9 @@ msgstr "設定正確"
msgid "ClusterIntegration|sign up"
msgstr "註冊"
+msgid "Code owners"
+msgstr "代碼所有者"
+
msgid "Cohorts"
msgstr "Cohorts"
@@ -1937,12 +2049,18 @@ msgstr "收起"
msgid "Collapse sidebar"
msgstr "收起å´é‚Šæ¬„"
+msgid "Comment"
+msgstr ""
+
msgid "Comment & resolve discussion"
msgstr "評論並關閉討論"
msgid "Comment & unresolve discussion"
msgstr "評論並é‡æ–°è¨Žè«–"
+msgid "Comment form position"
+msgstr ""
+
msgid "Comments"
msgstr "留言"
@@ -1975,6 +2093,9 @@ msgstr "é€äº¤"
msgid "CommitMessage|Add %{file_name}"
msgstr "建立 %{file_name}"
+msgid "CommitWidget|authored"
+msgstr "創作"
+
msgid "Commits"
msgstr "更動記錄"
@@ -2047,8 +2168,8 @@ msgstr "機密的"
msgid "Configure Gitaly timeouts."
msgstr "設定 Gitaly 延é²éŽä¹…。"
-msgid "Configure Sidekiq job throttling."
-msgstr "設定 Sidekiq 工作é™åˆ¶ã€‚"
+msgid "Configure Tracing"
+msgstr ""
msgid "Configure automatic git checks and housekeeping on repositories."
msgstr "於檔案庫上設定自動 Git 檢查與內務管ç†"
@@ -2056,11 +2177,11 @@ msgstr "於檔案庫上設定自動 Git 檢查與內務管ç†"
msgid "Configure limits for web and API requests."
msgstr "為網路與 API 請求設定é™åˆ¶ã€‚"
-msgid "Configure push and pull mirrors."
-msgstr "設定推é€å’Œæå–çš„é¡åƒã€‚"
+msgid "Configure push mirrors."
+msgstr "設定推é€é¡åƒã€‚"
-msgid "Configure storage path and circuit breaker settings."
-msgstr "設定儲存路徑與斷路器設定。"
+msgid "Configure storage path settings."
+msgstr ""
msgid "Configure the %{link} integration."
msgstr ""
@@ -2149,6 +2270,9 @@ msgstr "è²¢ç»"
msgid "Contribution guide"
msgstr "å”作指å—"
+msgid "Contributions for <strong>%{calendar_date}</strong>"
+msgstr "<strong>%{calendar_date}</strong> çš„è²¢ç»ç´€éŒ„"
+
msgid "Contributions per group member"
msgstr "æ¯å€‹ç¾¤çµ„æˆå“¡çš„è²¢ç»"
@@ -2168,7 +2292,7 @@ msgid "ContributorsPage|Please wait a moment, this page will automatically refre
msgstr "è«‹ç¨ç­‰ç‰‡åˆ»ï¼Œé€™å€‹é é¢æœƒæº–備好時自動刷新。"
msgid "Control the display of third party offers."
-msgstr ""
+msgstr "控制第三方æ供的顯示方å¼ã€‚"
msgid "Control the maximum concurrency of LFS/attachment backfill for this secondary node"
msgstr "控制此次è¦ç¯€é»žçš„ LFS 和附加檔案的最大併發é‡"
@@ -2182,6 +2306,18 @@ msgstr "控制此 Geo 節點驗證æ“作的最大並行é‡"
msgid "ConvDev Index"
msgstr "ConvDev 索引"
+msgid "Copy %{protocol} clone URL"
+msgstr "複製 %{protocol} 的複製 (clone) URL"
+
+msgid "Copy HTTPS clone URL"
+msgstr "複製 HTTPS 的複製 (clone) URL"
+
+msgid "Copy ID to clipboard"
+msgstr ""
+
+msgid "Copy SSH clone URL"
+msgstr "複製 SSH 的複製 (clone) URL"
+
msgid "Copy SSH public key to clipboard"
msgstr "複製 SSH 公鑰到剪貼簿"
@@ -2201,17 +2337,29 @@ msgid "Copy file path to clipboard"
msgstr "複製檔案路徑到剪貼簿"
msgid "Copy incoming email address to clipboard"
+msgstr "複製接收到的電å­ä¿¡ç®±ä½å€åˆ°å‰ªè²¼ç°¿"
+
+msgid "Copy link"
+msgstr ""
+
+msgid "Copy name to clipboard"
msgstr ""
msgid "Copy reference to clipboard"
msgstr "複製連çµ"
+msgid "Copy secret to clipboard"
+msgstr ""
+
msgid "Copy to clipboard"
msgstr "複製至剪貼簿"
msgid "Copy token to clipboard"
msgstr "複製憑證到剪貼簿"
+msgid "Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}"
+msgstr ""
+
msgid "Create"
msgstr "建立"
@@ -2287,8 +2435,8 @@ msgstr "建立..."
msgid "Create project label"
msgstr "建立專案標籤"
-msgid "CreateNewFork|Fork"
-msgstr "分支"
+msgid "Create your first page"
+msgstr ""
msgid "CreateTag|Tag"
msgstr "建立標籤"
@@ -2306,7 +2454,7 @@ msgid "Created by me"
msgstr "由我創建"
msgid "Created on"
-msgstr ""
+msgstr "建立於"
msgid "Created on:"
msgstr "建立於:"
@@ -2321,7 +2469,7 @@ msgid "Cron syntax"
msgstr "Cron 語法"
msgid "Current Branch"
-msgstr ""
+msgstr "ç›®å‰åˆ†æ”¯"
msgid "Current node"
msgstr "ç›®å‰ç¯€é»ž"
@@ -2333,11 +2481,14 @@ msgid "CurrentUser|Settings"
msgstr "設定"
msgid "Custom"
-msgstr ""
+msgstr "自訂"
msgid "Custom CI config path"
msgstr "自定義 CI é…置路徑"
+msgid "Custom hostname (for private commit emails)"
+msgstr ""
+
msgid "Custom notification events"
msgstr "自訂事件通知"
@@ -2345,22 +2496,25 @@ msgid "Custom notification levels are the same as participating levels. With cus
msgstr "自訂通知的等級與åƒèˆ‡åº¦è¨­å®šç›¸åŒã€‚使用自訂通知讓你åªæ”¶åˆ°ç‰¹å®šçš„事件通知。想了解更多資訊,請查閱 %{notification_link} 。"
msgid "Custom project templates"
-msgstr ""
+msgstr "自訂專案模æ¿"
msgid "Customize colors"
msgstr "自訂é¡è‰²"
msgid "Customize how FogBugz email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
-msgstr ""
+msgstr "自訂把 FogBugz é›»å­ä¿¡ç®±ç¶²å€å’Œä½¿ç”¨è€…å稱匯入到 GitLab çš„æ–¹å¼ã€‚下個步驟中,您將å¯ä»¥é¸æ“‡æ¬²åŒ¯å…¥çš„專案。"
msgid "Customize how Google Code email addresses and usernames are imported into GitLab. In the next step, you'll be able to select the projects you want to import."
+msgstr "自訂把 Google Code çš„é›»å­ä¿¡ç®±ç¶²å€å’Œä½¿ç”¨è€…å稱匯入到 GitLab çš„æ–¹å¼ã€‚下個步驟中,您將å¯ä»¥é¸æ“‡æ¬²åŒ¯å…¥çš„專案。"
+
+msgid "Customize your pipeline configuration, view your pipeline status and coverage report."
msgstr ""
msgid "Cycle Analytics"
msgstr "週期分æž"
msgid "Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project."
-msgstr ""
+msgstr "「週期統計ã€æ供了您專案從想法到生產環境所花費時間的概覽"
msgid "CycleAnalyticsStage|Code"
msgstr "程å¼é–‹ç™¼"
@@ -2393,10 +2547,10 @@ msgid "DashboardProjects|Personal"
msgstr "個人"
msgid "Date picker"
-msgstr ""
+msgstr "日期é¸æ“‡å™¨"
msgid "Debug"
-msgstr ""
+msgstr "除錯"
msgid "Dec"
msgstr "å二月"
@@ -2407,27 +2561,48 @@ msgstr "å二月"
msgid "Decline and sign out"
msgstr "拒絕並登出"
+msgid "Default Branch"
+msgstr "é è¨­åˆ†æ”¯"
+
msgid "Default classification label"
msgstr "é è¨­åˆ†é¡žæ¨™ç±¤"
msgid "Default: Directly import the Google Code email address or username"
-msgstr ""
+msgstr "é è¨­å€¼ï¼šç›´æŽ¥åŒ¯å…¥ Google Code çš„é›»å­éƒµä»¶åœ°å€æˆ–使用者å稱"
msgid "Default: Map a FogBugz account ID to a full name"
-msgstr ""
+msgstr "é è¨­å€¼ï¼šå°‡ FogBugz 的帳號å°æ‡‰ç‚ºå…¨å"
msgid "Define a custom pattern with cron syntax"
msgstr "使用 Cron 語法自訂排程"
+msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after it's timer finishes."
+msgstr ""
+
+msgid "DelayedJobs|Start now"
+msgstr ""
+
+msgid "DelayedJobs|Unschedule"
+msgstr ""
+
+msgid "DelayedJobs|delayed"
+msgstr ""
+
msgid "Delete"
msgstr "刪除"
msgid "Delete Package"
-msgstr ""
+msgstr "刪除套件"
msgid "Delete Snippet"
msgstr "刪除片段"
+msgid "Delete comment"
+msgstr ""
+
msgid "Delete list"
msgstr "刪除清單"
@@ -2564,6 +2739,12 @@ msgstr "您的新部屬憑證"
msgid "DeployTokens|Your new project deploy token has been created."
msgstr "您的新專案部屬憑證已經建立。"
+msgid "Deployed to"
+msgstr ""
+
+msgid "Deploying to"
+msgstr ""
+
msgid "Deprioritize label"
msgstr "優先標籤"
@@ -2586,6 +2767,12 @@ msgid "Details"
msgstr "細節"
msgid "Detect host keys"
+msgstr "åµæ¸¬ä¸»æ©Ÿé‡‘é‘°"
+
+msgid "Diff content limits"
+msgstr ""
+
+msgid "Diff limits"
msgstr ""
msgid "Diffs|No file name available"
@@ -2595,7 +2782,7 @@ msgid "Diffs|Something went wrong while fetching diff lines."
msgstr "讀å–差異檔時發生了一些錯誤."
msgid "Direction"
-msgstr ""
+msgstr "æ–¹å‘"
msgid "Directory name"
msgstr "目錄å稱"
@@ -2609,17 +2796,32 @@ msgstr "為此專案åœç”¨"
msgid "Disable group Runners"
msgstr "åœç”¨ç¾¤çµ„執行器"
+msgid "Discard"
+msgstr "æ¨æ£„"
+
+msgid "Discard all changes"
+msgstr "æ¨æ£„所有變更"
+
+msgid "Discard all unstaged changes?"
+msgstr "æ¨æ£„所有未暫存變更?"
+
msgid "Discard changes"
msgstr "撤銷變更"
+msgid "Discard changes to %{path}?"
+msgstr "æ¨æ£„ %{path} 的變更?"
+
msgid "Discard draft"
msgstr "放棄è‰ç¨¿"
+msgid "Discard review"
+msgstr ""
+
msgid "Discover GitLab Geo."
msgstr "探索 GitLab Geo。"
msgid "Discover projects, groups and snippets. Share your projects with others"
-msgstr ""
+msgstr "探索專案,群組和程å¼ç¢¼ç‰‡æ®µã€‚與他人分享您的專案"
msgid "Dismiss"
msgstr "忽略"
@@ -2630,9 +2832,12 @@ msgstr "關閉循環分æžä»‹ç´¹è¦–窗"
msgid "Dismiss Merge Request promotion"
msgstr "忽略åˆä½µè«‹æ±‚的促銷廣告"
-msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
+msgid "Dismiss trial promotion"
msgstr ""
+msgid "Do you want to customize how Google Code email addresses and usernames are imported into GitLab?"
+msgstr "是å¦è¦è‡ªè¨‚å°‡ Google Code çš„é›»å­ä¿¡ç®±ä½å€å’Œä½¿ç”¨è€…å稱匯入到 GitLab çš„æ–¹å¼ï¼Ÿ"
+
msgid "Documentation for popular identity providers"
msgstr "知å身份æ供商的文件"
@@ -2711,8 +2916,8 @@ msgstr "編輯 %{user_name} 的身份"
msgid "Elasticsearch"
msgstr "Elasticsearch"
-msgid "Elasticsearch intergration. Elasticsearch AWS IAM."
-msgstr "Elasticsearch æ•´åˆã€‚ Elasticsearch AWS IAM。"
+msgid "Elasticsearch integration. Elasticsearch AWS IAM."
+msgstr ""
msgid "Email"
msgstr "é›»å­ä¿¡ç®±"
@@ -2756,9 +2961,6 @@ msgstr "為此專案啟用"
msgid "Enable group Runners"
msgstr "啟用群組執行器"
-msgid "Enable or disable certain group features and choose access levels."
-msgstr "啟用或åœç”¨æŸäº›ç¾¤çµ„功能,並é¸æ“‡å­˜å–等級。"
-
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "啟用或åœç”¨ Pseudonymizer 的資料收集。"
@@ -2771,6 +2973,12 @@ msgstr "啟用 reCAPTCHA 或 Akismet 並設定 IP 上é™ã€‚"
msgid "Enable the Performance Bar for a given group."
msgstr "啟用æ供群組的效能桿。"
+msgid "Enable usage ping"
+msgstr "å•Ÿç”¨ä½¿ç”¨æƒ…æ³ Ping"
+
+msgid "Enable usage ping to get an overview of how you are using GitLab from a feature perspective."
+msgstr "å•Ÿç”¨ä½¿ç”¨æƒ…æ³ Ping 以從功能角度來看您 GitLab 的使用情形概覽"
+
msgid "Enabled"
msgstr "已啟用"
@@ -2778,19 +2986,19 @@ msgid "Ends at (UTC)"
msgstr "æ–¼ (UTC) çµæŸ"
msgid "Enter in your Bitbucket Server URL and personal access token below"
-msgstr ""
+msgstr "在底下輸入您的 BitBucket 伺æœå™¨ URL 和個人存å–權æ–"
msgid "Enter the issue description"
-msgstr ""
+msgstr "請輸入å•é¡Œèªªæ˜Ž"
msgid "Enter the issue title"
-msgstr ""
+msgstr "請輸入å•é¡Œæ¨™é¡Œ"
msgid "Enter the merge request description"
-msgstr ""
+msgstr "請輸入åˆä½µè«‹æ±‚說明"
msgid "Enter the merge request title"
-msgstr ""
+msgstr "請請輸入åˆä½µè«‹æ±‚標題"
msgid "Environments"
msgstr "環境"
@@ -2802,10 +3010,10 @@ msgid "Environments|An error occurred while making the request."
msgstr "發é€è«‹æ±‚時發生錯誤"
msgid "Environments|An error occurred while stopping the environment, please try again"
-msgstr ""
+msgstr "åœæ­¢ç’°å¢ƒæ™‚發生錯誤,請é‡è©¦"
msgid "Environments|Are you sure you want to stop this environment?"
-msgstr ""
+msgstr "確定è¦åœæ­¢æ­¤ç’°å¢ƒå—Žï¼Ÿ"
msgid "Environments|Commit"
msgstr "æ›´å‹•"
@@ -2823,13 +3031,13 @@ msgid "Environments|Environments"
msgstr "環境"
msgid "Environments|Environments are places where code gets deployed, such as staging or production."
-msgstr ""
+msgstr "《環境》是部署代碼的ä½ç½®ï¼Œä¾‹å¦‚階段或生產環境。"
msgid "Environments|Job"
msgstr "任務"
msgid "Environments|Learn more about stopping environments"
-msgstr ""
+msgstr "了解有關åœæ­¢ç’°å¢ƒçš„更多資訊"
msgid "Environments|New environment"
msgstr "新建環境"
@@ -2841,25 +3049,25 @@ msgid "Environments|No pod name has been specified"
msgstr "沒有指定 pod å稱"
msgid "Environments|Note that this action will stop the environment, but it will %{emphasisStart}not%{emphasisEnd} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} file."
-msgstr ""
+msgstr "注æ„,此動作將會åœæ­¢è©²ç’°å¢ƒï¼ä½†å› å°šæœªåœ¨ %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd} 檔案中定義「åœæ­¢ç’°å¢ƒå‹•ä½œã€ï¼Œå› æ­¤%{emphasisStart}ä¸æœƒ%{emphasisEnd}影響ç¾æœ‰çš„佈署。"
msgid "Environments|Note that this action will stop the environment, but it will %{emphasis_start}not%{emphasis_end} have an effect on any existing deployment due to no “stop environment action†being defined in the %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} file."
-msgstr ""
+msgstr "注æ„,此æ“作將會åœæ­¢è©²ç’°å¢ƒï¼Œä½†å› ç‚ºå°šæœªåœ¨ %{ci_config_link_start}.gitlab-ci.yml%{ci_config_link_end} 檔案中定義「åœæ­¢ç’°å¢ƒå‹•ä½œã€ï¼Œå› æ­¤%{emphasis_start}ä¸æœƒ%{emphasis_end}影響ç¾æœ‰çš„佈署。"
msgid "Environments|Open live environment"
-msgstr ""
+msgstr "打開實æ³ç’°å¢ƒ"
msgid "Environments|Pod logs from"
msgstr "Pod 日誌由"
msgid "Environments|Re-deploy to environment"
-msgstr ""
+msgstr "é‡æ–°éƒ¨å±¬ç’°å¢ƒ"
msgid "Environments|Read more about environments"
msgstr "了解有關環境的更多訊æ¯"
msgid "Environments|Rollback environment"
-msgstr ""
+msgstr "回退環境"
msgid "Environments|Show all"
msgstr "顯示全部"
@@ -2873,11 +3081,11 @@ msgstr "åœæ­¢ç’°å¢ƒ"
msgid "Environments|Updated"
msgstr "已更新"
-msgid "Environments|You don't have any environments right now."
-msgstr "你還沒有設置環境"
+msgid "Environments|You don't have any environments right now"
+msgstr ""
msgid "Environments|protected"
-msgstr ""
+msgstr "å—ä¿è­·çš„"
msgid "Epic"
msgstr "Epic"
@@ -2895,28 +3103,28 @@ msgid "Epics let you manage your portfolio of projects more efficiently and with
msgstr "Epics 讓你能更有效率且花費更少功夫的管ç†æ‚¨å°ˆæ¡ˆçš„組åˆã€‚"
msgid "Epics|An error occurred while saving %{epicDateType} date"
-msgstr ""
+msgstr "儲存 %{epicDateType} 日期時出錯"
msgid "Epics|How can I solve this?"
-msgstr ""
+msgstr "該怎麼解決這個?"
msgid "Epics|More information"
-msgstr ""
+msgstr "更多資訊"
msgid "Epics|These dates affect how your epics appear in the roadmap. Dates from milestones come from the milestones assigned to issues in the epic. You can also set fixed dates or remove them entirely."
msgstr ""
-msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a due date to any issue in the epic."
+msgid "Epics|To schedule your epic's %{epicDateType} date based on milestones, assign a milestone with a %{epicDateType} date to any issue in the epic."
msgstr ""
-msgid "Epics|finish"
-msgstr ""
+msgid "Epics|due"
+msgstr "截止"
msgid "Epics|start"
-msgstr ""
+msgstr "開始"
msgid "Error"
-msgstr ""
+msgstr "錯誤"
msgid "Error Reporting and Logging"
msgstr "錯誤報告與日誌"
@@ -2943,7 +3151,7 @@ msgid "Error loading branch data. Please try again."
msgstr "載入分支資料時錯誤,請é‡è©¦ã€‚"
msgid "Error loading branches."
-msgstr ""
+msgstr "載入分支時發生錯誤。"
msgid "Error loading last commit."
msgstr "載入最新更動紀錄時失敗。"
@@ -3020,6 +3228,12 @@ msgstr "展開全部"
msgid "Expand sidebar"
msgstr "展開å´é‚Šæ¬„"
+msgid "Expiration date"
+msgstr ""
+
+msgid "Explain the problem. If appropriate, provide a link to the relevant issue or comment."
+msgstr ""
+
msgid "Explore"
msgstr "ç€è¦½"
@@ -3074,6 +3288,12 @@ msgstr "無法變更所有權"
msgid "Failed to check related branches."
msgstr "檢查相關分支失敗。"
+msgid "Failed to deploy to"
+msgstr ""
+
+msgid "Failed to load emoji list."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr "從看æ¿åˆªé™¤è­°é¡Œæ™‚發生錯誤,請ç¨å€™é‡è©¦"
@@ -3083,6 +3303,9 @@ msgstr ""
msgid "Failed to remove the pipeline schedule"
msgstr "無法刪除æµæ°´ç·šæŽ’程"
+msgid "Failed to signing using smartcard authentication"
+msgstr ""
+
msgid "Failed to update issues, please try again."
msgstr "更新議題時發生錯誤,請ç¨å¾Œé‡è©¦ã€‚"
@@ -3092,6 +3315,81 @@ msgstr "失敗"
msgid "Faster as it re-uses the project workspace (falling back to clone if it doesn't exist)"
msgstr "較快,因為它å†æ¬¡ä½¿ç”¨å°ˆæ¡ˆå·¥ä½œç©ºé–“ (如果它ä¸å­˜åœ¨ï¼Œå‰‡è¿”回到複製)"
+msgid "Feature Flags"
+msgstr ""
+
+msgid "FeatureFlags|API URL"
+msgstr ""
+
+msgid "FeatureFlags|Active"
+msgstr ""
+
+msgid "FeatureFlags|Application name"
+msgstr ""
+
+msgid "FeatureFlags|Configure"
+msgstr ""
+
+msgid "FeatureFlags|Configure feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Create feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Delete %{feature_flag_name}?"
+msgstr ""
+
+msgid "FeatureFlags|Description"
+msgstr ""
+
+msgid "FeatureFlags|Edit %{feature_flag_name}"
+msgstr ""
+
+msgid "FeatureFlags|Edit Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag"
+msgstr ""
+
+msgid "FeatureFlags|Feature flag %{feature_flag_name} will be removed. Are you sure?"
+msgstr ""
+
+msgid "FeatureFlags|Feature flags allow you to configure your code into different flavors by dynamically toggling certain functionality."
+msgstr ""
+
+msgid "FeatureFlags|Get started with feature flags"
+msgstr ""
+
+msgid "FeatureFlags|Inactive"
+msgstr ""
+
+msgid "FeatureFlags|Install a %{docs_link_start}compatible client library%{docs_link_end} and specify the API URL, application name, and instance ID during the configuration setup."
+msgstr ""
+
+msgid "FeatureFlags|Instance ID"
+msgstr ""
+
+msgid "FeatureFlags|More information"
+msgstr ""
+
+msgid "FeatureFlags|Name"
+msgstr ""
+
+msgid "FeatureFlags|New"
+msgstr ""
+
+msgid "FeatureFlags|New Feature Flag"
+msgstr ""
+
+msgid "FeatureFlags|Save changes"
+msgstr ""
+
+msgid "FeatureFlags|Status"
+msgstr ""
+
msgid "Feb"
msgstr "二月"
@@ -3101,6 +3399,9 @@ msgstr "二月"
msgid "Fields on this page are now uneditable, you can configure"
msgstr "æ­¤é é¢æ¬„ä½ç¾åœ¨ç„¡æ³•ç·¨è¼¯ï¼Œä½ å¯ä»¥è¨­ç½®"
+msgid "File templates"
+msgstr ""
+
msgid "Files"
msgstr "檔案"
@@ -3113,9 +3414,18 @@ msgstr "填寫以下的欄ä½ï¼Œé–‹å•Ÿ <strong>%{enable_label}</strong> 後按ä¸
msgid "Filter"
msgstr ""
+msgid "Filter by %{issuable_type} that are currently closed."
+msgstr ""
+
+msgid "Filter by %{issuable_type} that are currently opened."
+msgstr ""
+
msgid "Filter by commit message"
msgstr "以更動說明篩é¸"
+msgid "Filter..."
+msgstr ""
+
msgid "Find by path"
msgstr "以路徑æœå°‹"
@@ -3131,6 +3441,9 @@ msgstr ""
msgid "Fingerprints"
msgstr ""
+msgid "Finish review"
+msgstr ""
+
msgid "Finished"
msgstr "已完æˆ"
@@ -3143,7 +3456,7 @@ msgstr "推é€è€…:"
msgid "Fixed date"
msgstr ""
-msgid "Fixed finish date"
+msgid "Fixed due date"
msgstr ""
msgid "Fixed start date"
@@ -3182,16 +3495,18 @@ msgstr "å°æ–¼å…§éƒ¨å°ˆæ¡ˆï¼Œä»»ä½•ç™»éŒ„的使用者都å¯ä»¥æŸ¥çœ‹æµæ°´ç·šä¸¦
msgid "For more information, go to the "
msgstr ""
+msgid "For more information, please review %{link_start_tag}Jaeger's configuration doc%{link_end_tag}"
+msgstr ""
+
+msgid "For more information, see the documentation on %{deactivating_usage_ping_link_start}deactivating the usage ping%{deactivating_usage_ping_link_end}."
+msgstr ""
+
msgid "For private projects, any member (guest or higher) can view pipelines and access job details (output logs and artifacts)"
msgstr "å°æ–¼ç§äººå°ˆæ¡ˆï¼Œä»»ä½•æˆå“¡ (訪客或以上) 都å¯ä»¥æŸ¥çœ‹æµæ°´ç·šä¸¦å­˜å–工作詳細資訊 (輸出日誌和產物)"
msgid "For public projects, anyone can view pipelines and access job details (output logs and artifacts)"
msgstr "å°æ–¼å…¬é–‹å°ˆæ¡ˆï¼Œä»»ä½•äººéƒ½å¯ä»¥æŸ¥çœ‹æµæ°´ç·šä¸¦å­˜å–工作詳細資訊 (輸出日誌和產物)"
-msgid "Fork"
-msgid_plural "Forks"
-msgstr[0] "分支"
-
msgid "ForkedFromProjectPath|Forked from"
msgstr "分支自"
@@ -3207,6 +3522,9 @@ msgstr "æ ¼å¼"
msgid "Found errors in your .gitlab-ci.yml:"
msgstr "在您的 .gitlab-ci.yml 中找到錯誤:"
+msgid "Free Trial of GitLab.com Gold"
+msgstr ""
+
msgid "From %{provider_title}"
msgstr "來自 %{provider_title}"
@@ -3249,6 +3567,9 @@ msgstr "一般æµæ°´ç·š"
msgid "Generate a default set of labels"
msgstr "產生é è¨­çš„標籤"
+msgid "Geo"
+msgstr ""
+
msgid "Geo Nodes"
msgstr "Geo 節點"
@@ -3423,10 +3744,22 @@ msgstr ""
msgid "Geo|%{name} is scheduled for re-sync"
msgstr ""
+msgid "Geo|All"
+msgstr ""
+
msgid "Geo|All projects"
msgstr "所有專案"
-msgid "Geo|Error message"
+msgid "Geo|All projects are being scheduled for re-check"
+msgstr ""
+
+msgid "Geo|All projects are being scheduled for re-sync"
+msgstr ""
+
+msgid "Geo|Batch operations"
+msgstr ""
+
+msgid "Geo|Could not remove tracking entry for an existing project."
msgstr ""
msgid "Geo|Failed"
@@ -3435,6 +3768,9 @@ msgstr ""
msgid "Geo|File sync capacity"
msgstr "檔案åŒæ­¥é‡"
+msgid "Geo|Geo Status"
+msgstr ""
+
msgid "Geo|Groups to synchronize"
msgstr "è¦åŒæ­¥çš„群組"
@@ -3456,7 +3792,7 @@ msgstr ""
msgid "Geo|Next sync scheduled at"
msgstr ""
-msgid "Geo|No errors"
+msgid "Geo|Not synced yet"
msgstr ""
msgid "Geo|Pending"
@@ -3468,6 +3804,9 @@ msgstr ""
msgid "Geo|Pending verification"
msgstr ""
+msgid "Geo|Project (ID: %{project_id}) no longer exists on the primary. It is safe to remove this entry, as this will not remove any data on disk."
+msgstr ""
+
msgid "Geo|Projects in certain groups"
msgstr "æŸäº›ç¾¤çµ„中的專案"
@@ -3477,19 +3816,25 @@ msgstr "æŸäº›å„²å­˜ç©ºé–“碎片中的專案"
msgid "Geo|Recheck"
msgstr ""
+msgid "Geo|Recheck all projects"
+msgstr ""
+
msgid "Geo|Redownload"
msgstr ""
+msgid "Geo|Remove"
+msgstr ""
+
msgid "Geo|Repository sync capacity"
msgstr "版本庫åŒæ­¥é‡"
msgid "Geo|Resync"
msgstr ""
-msgid "Geo|Retry count"
+msgid "Geo|Resync all projects"
msgstr ""
-msgid "Geo|Retry counts"
+msgid "Geo|Retry count"
msgstr ""
msgid "Geo|Select groups to replicate."
@@ -3507,6 +3852,12 @@ msgstr ""
msgid "Geo|Synchronization failed - %{error}"
msgstr ""
+msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
+msgstr ""
+
+msgid "Geo|Tracking entry will be removed. Are you sure?"
+msgstr ""
+
msgid "Geo|Unknown state"
msgstr ""
@@ -3519,9 +3870,27 @@ msgstr ""
msgid "Geo|Waiting for scheduler"
msgstr ""
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
+msgstr ""
+
+msgid "Geo|You are on a secondary, <b>read-only</b> Geo node. You may be able to make a limited amount of changes or perform a limited amount of actions on this page."
+msgstr ""
+
msgid "Geo|You need a different license to use Geo replication"
msgstr ""
+msgid "Geo|misconfigured"
+msgstr ""
+
+msgid "Geo|primary"
+msgstr ""
+
+msgid "Geo|secondary"
+msgstr ""
+
+msgid "Get a free instance review"
+msgstr ""
+
msgid "Git"
msgstr "Git"
@@ -3531,9 +3900,6 @@ msgstr "Git 檔案庫網å€"
msgid "Git revision"
msgstr "Git 修訂版本"
-msgid "Git storage health information has been reset"
-msgstr "Git 儲存空間å¥åº·æŒ‡æ•¸å·²é‡ç½®"
-
msgid "Git strategy for pipelines"
msgstr "Git æµæ°´ç·šç­–ç•¥"
@@ -3600,12 +3966,6 @@ msgstr ""
msgid "Go to %{link_to_google_takeout}."
msgstr ""
-msgid "Go to your fork"
-msgstr "å‰å¾€æ‚¨çš„分支"
-
-msgid "GoToYourFork|Fork"
-msgstr "å‰å¾€æ‚¨çš„分支"
-
msgid "Google Code import"
msgstr "匯入 Google Code"
@@ -3636,9 +3996,21 @@ msgstr "群組 ID"
msgid "Group Runners"
msgstr "群組執行器"
+msgid "Group SAML must be enabled to test"
+msgstr ""
+
+msgid "Group URL"
+msgstr ""
+
msgid "Group avatar"
msgstr "群組頭åƒ"
+msgid "Group description"
+msgstr ""
+
+msgid "Group description (optional)"
+msgstr ""
+
msgid "Group details"
msgstr "群組詳細資訊"
@@ -3648,6 +4020,9 @@ msgstr "群組資訊:"
msgid "Group maintainers can register group runners in the %{link}"
msgstr "群組維護者å¯ä»¥åœ¨ %{link} 註冊群組執行器"
+msgid "Group name"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr "群組:%{group_name}"
@@ -3666,14 +4041,14 @@ msgstr "抱歉,沒有任何 Epic 符åˆæ‚¨çš„æœå°‹ã€‚"
msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timeline"
msgstr "開發è—圖顯示時間軸上您的 Epic 進度"
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "è‹¥è¦æª¢è¦–開發è—圖,請新增這個群組或其å­ç¾¤çµ„中一個 Epic 的計畫開始與完æˆæ—¥æœŸã€‚月檢視中,åªæœƒé¡¯ç¤ºä¸Šå€‹æœˆã€é€™å€‹æœˆã€å’ŒæŽ¥ä¸‹ä¾†äº”個月的 Epic &ndash; 從 %{startDate} 到 %{endDate}。"
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "è‹¥è¦æª¢è¦–開發è—圖,請新增這個群組或其å­ç¾¤çµ„中一個 Epic 的計畫開始與完æˆæ—¥æœŸã€‚季度檢視中,åªæœƒé¡¯ç¤ºä¸Šå€‹å­£åº¦ã€é€™å€‹å­£åº¦ã€å’ŒæŽ¥ä¸‹ä¾†å››å€‹å­£åº¦çš„ Epic &ndash; 從 %{startDate} 到 %{endDate}。"
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the quarters view, only epics in the past quarter, current quarter, and next 4 quarters are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
-msgid "GroupRoadmap|To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
-msgstr "è‹¥è¦æª¢è¦–開發è—圖,請新增這個群組或其å­ç¾¤çµ„中一個 Epic 的計畫開始與完æˆæ—¥æœŸã€‚週檢視中,åªæœƒé¡¯ç¤ºä¸Šé€±ã€é€™é€±ã€å’ŒæŽ¥ä¸‹ä¾†å››é€±çš„ Epic &ndash; 從 %{startDate} 到 %{endDate}。"
+msgid "GroupRoadmap|To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the weeks view, only epics in the past week, current week, and next 4 weeks are shown &ndash; from %{startDate} to %{endDate}."
+msgstr ""
msgid "GroupRoadmap|To widen your search, change or remove filters. In the months view, only epics in the past month, current month, and next 5 months are shown &ndash; from %{startDate} to %{endDate}."
msgstr "è‹¥è¦æ“´å¤§æ‚¨çš„æœå°‹ï¼Œè«‹å˜—試修改或移除篩é¸å™¨ã€‚月檢視中,åªæœƒé¡¯ç¤ºä¸Šå€‹æœˆã€é€™å€‹æœˆã€å’ŒæŽ¥ä¸‹ä¾†äº”個月的 Epic &ndash; 從 %{startDate} 到 %{endDate}。"
@@ -3699,9 +4074,6 @@ msgstr ""
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
msgstr "ç¦æ­¢èˆ‡å…¶ä»–群組共享 %{group} 中的專案"
-msgid "GroupSettings|Share with group lock"
-msgstr "分享群組鎖"
-
msgid "GroupSettings|This setting is applied on %{ancestor_group} and has been overridden on this subgroup."
msgstr "這個設定已經套用至 %{ancestor_group},並覆蓋了它的å­ç¾¤çµ„設定。"
@@ -3759,6 +4131,9 @@ msgstr "找ä¸åˆ°ç¾¤çµ„"
msgid "GroupsEmptyState|You can manage your group member’s permissions and access to each project in the group."
msgstr "ä½ å¯ä»¥ç®¡ç†ç¾¤çµ„內所有æˆå“¡çš„æ¯å€‹å°ˆæ¡ˆçš„å­˜å–權é™"
+msgid "GroupsTree|Are you sure you want to leave the \"%{fullName}\" group?"
+msgstr ""
+
msgid "GroupsTree|Create a project in this group."
msgstr "在此群組建立新的專案"
@@ -3771,20 +4146,20 @@ msgstr "編輯群組"
msgid "GroupsTree|Failed to leave the group. Please make sure you are not the only owner."
msgstr "無法離開群組,請確ä¿æ‚¨ä¸æ˜¯å”¯ä¸€çš„æ“有者。"
-msgid "GroupsTree|Filter by name..."
-msgstr "以å稱篩é¸â‹¯"
-
msgid "GroupsTree|Leave this group"
msgstr "離開此群組"
msgid "GroupsTree|Loading groups"
msgstr "群組讀å–中"
-msgid "GroupsTree|Sorry, no groups matched your search"
-msgstr "ä¸å¥½æ„æ€ï¼Œæ²’有æœå°‹åˆ°ä»»ä½•ç¬¦åˆæ¢ä»¶çš„群組"
+msgid "GroupsTree|No groups matched your search"
+msgstr ""
-msgid "GroupsTree|Sorry, no groups or projects matched your search"
-msgstr "ä¸å¥½æ„æ€ï¼Œæ²’有æœå°‹åˆ°ä»»ä½•ç¬¦åˆæ¢ä»¶çš„群組或專案"
+msgid "GroupsTree|No groups or projects matched your search"
+msgstr ""
+
+msgid "GroupsTree|Search by name"
+msgstr ""
msgid "Have your users email"
msgstr "有來自您使用者的信件"
@@ -3825,6 +4200,9 @@ msgstr ""
msgid "Hide host keys manual input"
msgstr ""
+msgid "Hide payload"
+msgstr ""
+
msgid "Hide value"
msgid_plural "Hide values"
msgstr[0] "éš±è—資料"
@@ -3988,6 +4366,9 @@ msgstr "é€éŽè­°é¡Œæ¬Šé‡å’Œ GitLab ä¼æ¥­ç‰ˆæœ¬æ”¹å–„議題管ç†ã€‚"
msgid "Improve search with Advanced Global Search and GitLab Enterprise Edition."
msgstr "使用進階全域æœå°‹å’Œ GitLab ä¼æ¥­ç‰ˆæœ¬ä¾†æ”¹é€²æœå°‹ã€‚"
+msgid "In order to enable instance-level analytics, please ask an admin to enable %{usage_ping_link_start}usage ping%{usage_ping_link_end}."
+msgstr ""
+
msgid "In the next step, you'll be able to select the projects you want to import."
msgstr ""
@@ -4013,7 +4394,7 @@ msgid "Input your repository URL"
msgstr ""
msgid "Install GitLab Runner"
-msgstr "å®‰è£ GitHub 執行器"
+msgstr "å®‰è£ GitLab 執行器"
msgid "Install Runner on Kubernetes"
msgstr "在 Kubernetes 上安è£é‹è¡Œå™¨"
@@ -4055,6 +4436,12 @@ msgstr "循環週期"
msgid "Introducing Cycle Analytics"
msgstr "週期分æžç°¡ä»‹"
+msgid "Invite"
+msgstr ""
+
+msgid "Issue"
+msgstr ""
+
msgid "Issue Boards"
msgstr "議題看æ¿"
@@ -4079,6 +4466,36 @@ msgstr "è­°é¡Œå¯ä»¥æ˜¯bug,任務或想法來討論。此外,å•é¡Œæ˜¯å¯æœ
msgid "Issues closed"
msgstr "議題已關閉"
+msgid "Issues, merge requests, pushes and comments."
+msgstr ""
+
+msgid "IssuesAnalytics|After you begin creating issues for your projects, we can start tracking and displaying metrics for them"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues Created"
+msgstr ""
+
+msgid "IssuesAnalytics|Issues created per month"
+msgstr ""
+
+msgid "IssuesAnalytics|Last 12 months"
+msgstr ""
+
+msgid "IssuesAnalytics|Sorry, your filter produced no results"
+msgstr ""
+
+msgid "IssuesAnalytics|There are no issues for the projects in your group"
+msgstr ""
+
+msgid "IssuesAnalytics|To widen your search, change or remove filters in the filter bar above"
+msgstr ""
+
+msgid "Jaeger URL"
+msgstr ""
+
+msgid "Jaeger tracing"
+msgstr ""
+
msgid "Jan"
msgstr "一月"
@@ -4094,9 +4511,6 @@ msgstr "工作已被抹除"
msgid "Jobs"
msgstr "任務"
-msgid "Job|Are you sure you want to erase this job?"
-msgstr ""
-
msgid "Job|Browse"
msgstr ""
@@ -4133,7 +4547,7 @@ msgstr ""
msgid "Job|The artifacts were removed"
msgstr ""
-msgid "Job|The artifacts will be removed"
+msgid "Job|The artifacts will be removed in"
msgstr ""
msgid "Job|This job is stuck, because the project doesn't have any runners online assigned to it."
@@ -4151,12 +4565,6 @@ msgstr "六月"
msgid "June"
msgstr "六月"
-msgid "Koding"
-msgstr "Koding"
-
-msgid "Koding Dashboard"
-msgstr "Koding 控制é¢æ¿"
-
msgid "Kubernetes"
msgstr "Kubernetes"
@@ -4229,6 +4637,9 @@ msgstr "æå‡æ¨™ç±¤"
msgid "Labels|Promoting %{labelTitle} will make it available for all projects inside %{groupName}. Existing project labels with the same title will be merged. This action cannot be reversed."
msgstr ""
+msgid "Large File Storage"
+msgstr ""
+
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] "最近 %d 天"
@@ -4239,12 +4650,18 @@ msgstr "最新æµæ°´ç·š"
msgid "Last commit"
msgstr "最後更動記錄"
+msgid "Last contact"
+msgstr ""
+
msgid "Last edited %{date}"
msgstr "最後編輯於 %{date}"
msgid "Last edited by %{name}"
msgstr "最後由 %{name} 編輯"
+msgid "Last reply by"
+msgstr ""
+
msgid "Last update"
msgstr "上次更新"
@@ -4293,6 +4710,15 @@ msgstr ""
msgid "License"
msgstr "授權"
+msgid "LicenseManagement|Add a license"
+msgstr ""
+
+msgid "LicenseManagement|Add licenses manually to approve or blacklist"
+msgstr ""
+
+msgid "LicenseManagement|Approve"
+msgstr ""
+
msgid "LicenseManagement|Approve license"
msgstr ""
@@ -4302,6 +4728,9 @@ msgstr ""
msgid "LicenseManagement|Approved"
msgstr ""
+msgid "LicenseManagement|Blacklist"
+msgstr ""
+
msgid "LicenseManagement|Blacklist license"
msgstr ""
@@ -4311,6 +4740,9 @@ msgstr ""
msgid "LicenseManagement|Blacklisted"
msgstr ""
+msgid "LicenseManagement|Cancel"
+msgstr ""
+
msgid "LicenseManagement|License"
msgstr ""
@@ -4320,6 +4752,9 @@ msgstr ""
msgid "LicenseManagement|License details"
msgstr ""
+msgid "LicenseManagement|License name"
+msgstr ""
+
msgid "LicenseManagement|Manage approved and blacklisted licenses for this project."
msgstr ""
@@ -4332,9 +4767,15 @@ msgstr ""
msgid "LicenseManagement|Remove license?"
msgstr ""
+msgid "LicenseManagement|Submit"
+msgstr ""
+
msgid "LicenseManagement|There are currently no approved or blacklisted licenses in this project."
msgstr ""
+msgid "LicenseManagement|This license already exists in this project."
+msgstr ""
+
msgid "LicenseManagement|URL"
msgstr ""
@@ -4360,6 +4801,9 @@ msgstr "列出您的 Gitea 版本庫"
msgid "List available repositories"
msgstr "列出å¯ç”¨çš„版本庫"
+msgid "List view"
+msgstr ""
+
msgid "List your Bitbucket Server repositories"
msgstr ""
@@ -4405,6 +4849,9 @@ msgstr "已鎖定目å‰å°ˆæ¡ˆ"
msgid "Locks give the ability to lock specific file or folder."
msgstr "《鎖定》æ供了鎖定特定檔案或資料夾的能力。"
+msgid "Login with smartcard"
+msgstr ""
+
msgid "Logs"
msgstr "記錄檔"
@@ -4474,14 +4921,44 @@ msgstr "標記「å³å°‡å®Œæˆã€ç‚ºå®Œæˆã€‚"
msgid "Markdown enabled"
msgstr "已啟用 Markdown"
+msgid "MarkdownToolbar|Add a bullet list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a link"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a numbered list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a table"
+msgstr ""
+
+msgid "MarkdownToolbar|Add a task list"
+msgstr ""
+
+msgid "MarkdownToolbar|Add bold text"
+msgstr ""
+
+msgid "MarkdownToolbar|Add italic text"
+msgstr ""
+
+msgid "MarkdownToolbar|Go full screen"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert a quote"
+msgstr ""
+
+msgid "MarkdownToolbar|Insert code"
+msgstr ""
+
msgid "Maven Metadata"
msgstr ""
msgid "Maven package"
msgstr ""
-msgid "Maximum git storage failures"
-msgstr "最大 git 儲存失敗"
+msgid "Max access level"
+msgstr ""
msgid "Maximum job timeout"
msgstr ""
@@ -4492,6 +4969,12 @@ msgstr "五月"
msgid "Median"
msgstr "中ä½æ•¸"
+msgid "Member lock"
+msgstr ""
+
+msgid "Member since %{date}"
+msgstr ""
+
msgid "Members"
msgstr "æˆå“¡"
@@ -4525,6 +5008,21 @@ msgstr "åˆä½µè«‹æ±‚"
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "åˆä½µè«‹æ±‚是一個讓其他人æ出更改建議並討論的地方"
+msgid "MergeRequests|An error occurred while saving the draft comment."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion stays unresolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be resolved."
+msgstr ""
+
+msgid "MergeRequests|Discussion will be unresolved."
+msgstr ""
+
msgid "MergeRequests|Resolve this discussion in a new issue"
msgstr "在新議題中解決此討論"
@@ -4534,9 +5032,6 @@ msgstr "儲存評論失敗"
msgid "MergeRequests|Toggle comments for this file"
msgstr "切æ›æ­¤æ–‡ä»¶çš„註釋"
-msgid "MergeRequests|Updating discussions failed"
-msgstr "更新討論失敗"
-
msgid "MergeRequests|View file @ %{commitId}"
msgstr "查看文件@ %{commitId}"
@@ -4546,6 +5041,12 @@ msgstr "查看替æ›æ–‡ä»¶@ %{commitId}"
msgid "MergeRequest| %{paragraphStart}changed the description %{descriptionChangedTimes} times %{timeDifferenceMinutes}%{paragraphEnd}"
msgstr ""
+msgid "MergeRequest|Filter files"
+msgstr ""
+
+msgid "MergeRequest|No files found"
+msgstr ""
+
msgid "Merged"
msgstr "å·²åˆä½µ"
@@ -4561,6 +5062,9 @@ msgstr "指標 - Influx"
msgid "Metrics - Prometheus"
msgstr "指標 - Prometheus"
+msgid "Metrics and profiling"
+msgstr ""
+
msgid "Metrics|Business"
msgstr "ä¼æ¥­"
@@ -4742,7 +5246,7 @@ msgid "More"
msgstr "更多"
msgid "More actions"
-msgstr "更多動作"
+msgstr ""
msgid "More info"
msgstr "更多資訊"
@@ -4777,6 +5281,9 @@ msgstr "é€éŽæ¨™é¡Œç‚ºæ‚¨çš„個人密鑰命å"
msgid "Name:"
msgstr "å稱:"
+msgid "Naming, visibility"
+msgstr ""
+
msgid "Nav|Help"
msgstr "幫助"
@@ -4895,6 +5402,12 @@ msgstr "無法連接到 Gitaly 伺æœå™¨ï¼Œè«‹æª¢æŸ¥æ‚¨çš„日誌ï¼"
msgid "No container images stored for this project. Add one by following the instructions above."
msgstr ""
+msgid "No contributions were found"
+msgstr ""
+
+msgid "No credit card required."
+msgstr ""
+
msgid "No due date"
msgstr "沒有到期日"
@@ -4904,9 +5417,6 @@ msgstr "沒有é ä¼°æˆ–花費時間"
msgid "No file chosen"
msgstr "未é¸æ“‡ä»»ä½•æª”案"
-msgid "No files found"
-msgstr "找ä¸åˆ°ä»»ä½•æª”案"
-
msgid "No files found."
msgstr "找ä¸åˆ°ä»»ä½•æª”案"
@@ -4916,6 +5426,9 @@ msgstr "é¸å–的時間範åœä¸­æ²’有議題。"
msgid "No labels with such name or description"
msgstr ""
+msgid "No license. All rights reserved"
+msgstr ""
+
msgid "No merge requests for the selected time period."
msgstr "é¸å–的時間範åœä¸­æ²’有åˆä½µè«‹æ±‚。"
@@ -4943,6 +5456,9 @@ msgstr "é¸å–的時間範åœä¸­æ²’有推é€ã€‚"
msgid "No repository"
msgstr "找ä¸åˆ°æª”案庫"
+msgid "No runners found"
+msgstr ""
+
msgid "No schedules"
msgstr "沒有排程"
@@ -4979,6 +5495,9 @@ msgstr "éžæ©Ÿå¯†"
msgid "Not enough data"
msgstr "資料ä¸è¶³"
+msgid "Not now"
+msgstr ""
+
msgid "Note that the master branch is automatically protected. %{link_to_protected_branches}"
msgstr "請注æ„,master 分支é è¨­ç‚ºå—ä¿è­·çš„。 %{link_to_protected_branches}"
@@ -4997,6 +5516,18 @@ msgstr "注æ„:請考慮讓您的 GitLab 管ç†å“¡è¨­å®š %{github_integration_
msgid "Notes|Are you sure you want to cancel creating this comment?"
msgstr ""
+msgid "Notes|Collapse replies"
+msgstr ""
+
+msgid "Notes|Show all activity"
+msgstr ""
+
+msgid "Notes|Show comments only"
+msgstr ""
+
+msgid "Notes|Show history only"
+msgstr ""
+
msgid "Notification events"
msgstr "事件通知"
@@ -5069,9 +5600,6 @@ msgstr "å一月"
msgid "November"
msgstr "å一月"
-msgid "Number of access attempts"
-msgstr "嘗試存å–的次數"
-
msgid "OK"
msgstr "確定"
@@ -5097,9 +5625,6 @@ msgstr ""
msgid "One or more of your Google Code projects cannot be imported into GitLab directly because they use Subversion or Mercurial for version control, rather than Git."
msgstr ""
-msgid "Online IDE integration settings."
-msgstr "線上 IDE æ•´åˆè¨­å®šã€‚"
-
msgid "Only admins"
msgstr ""
@@ -5121,6 +5646,9 @@ msgstr "é–‹å•Ÿ"
msgid "Open in Xcode"
msgstr "在 Xcode 開啟"
+msgid "Open projects"
+msgstr ""
+
msgid "Open sidebar"
msgstr "é–‹å•Ÿå´é‚Šæ¬„"
@@ -5145,6 +5673,21 @@ msgstr "於新視窗開啟"
msgid "Operations"
msgstr "動作"
+msgid "Operations Dashboard"
+msgstr ""
+
+msgid "Operations Settings"
+msgstr ""
+
+msgid "OperationsDashboard|Add a project to the dashboard"
+msgstr ""
+
+msgid "OperationsDashboard|The operations dashboard provides a summary of each project's operational health, including pipeline and alert statuses."
+msgstr ""
+
+msgid "OperationsDashboard|Unable to add %{invalidProjects}. The Operations Dashboard is available for projects with a Gold subscription."
+msgstr ""
+
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr ""
@@ -5211,6 +5754,9 @@ msgstr "密碼"
msgid "Paste your public SSH key, which is usually contained in the file '~/.ssh/id_rsa.pub' and begins with 'ssh-rsa'. Don't use your private SSH key."
msgstr "貼上您的SSH公鑰,通常放置在 '~/.ssh/id_rsa.pub',並以 'ssh-rsa' 開頭。ä¸è¦ä½¿ç”¨æ‚¨çš„SSHç§é‘°ã€‚"
+msgid "Path, transfer, remove"
+msgstr ""
+
msgid "Path:"
msgstr "ä½ç½®ï¼š"
@@ -5238,15 +5784,15 @@ msgstr "效能最佳化"
msgid "Permissions"
msgstr "權é™"
+msgid "Permissions, LFS, 2FA"
+msgstr ""
+
msgid "Personal Access Token"
msgstr "個人訪å•æ†‘è­‰"
msgid "Pipeline"
msgstr "æµæ°´ç·š"
-msgid "Pipeline %{pipelineLinkStart} #%{pipelineId} %{pipelineLinkEnd} from %{pipelineLinkRefStart} %{pipelineRef} %{pipelineLinkRefEnd}"
-msgstr ""
-
msgid "Pipeline Health"
msgstr "æµæ°´ç·šå¥åº·æŒ‡æ•¸"
@@ -5364,15 +5910,24 @@ msgstr ""
msgid "Pipelines|This project is not currently set up to run pipelines."
msgstr "這個專案目å‰é‚„沒設定æµæ°´ç·šã€‚"
+msgid "Pipeline|Commit"
+msgstr ""
+
msgid "Pipeline|Create for"
msgstr "建立"
msgid "Pipeline|Create pipeline"
msgstr "建立æµæ°´ç·š"
+msgid "Pipeline|Duration"
+msgstr ""
+
msgid "Pipeline|Existing branch name or tag"
msgstr "存在的分支å稱或標籤"
+msgid "Pipeline|Pipeline"
+msgstr ""
+
msgid "Pipeline|Run Pipeline"
msgstr "執行æµæ°´ç·š"
@@ -5382,6 +5937,12 @@ msgstr "æœå°‹åˆ†æ”¯"
msgid "Pipeline|Specify variable values to be used in this run. The values specified in %{settings_link} will be used by default."
msgstr "指定è¦ä½¿ç”¨åœ¨æ­¤æ¬¡åŸ·è¡Œçš„變數值。%{settings_link} 中指定的值將會使用為é è¨­å€¼ã€‚"
+msgid "Pipeline|Stages"
+msgstr ""
+
+msgid "Pipeline|Status"
+msgstr ""
+
msgid "Pipeline|Stop pipeline"
msgstr "åœæ­¢æµæ°´ç·š"
@@ -5409,12 +5970,6 @@ msgstr "於階段"
msgid "Plain diff"
msgstr "本文差異"
-msgid "Planned finish date"
-msgstr "計畫完æˆæ—¥æœŸ"
-
-msgid "Planned start date"
-msgstr "計畫開始日期"
-
msgid "PlantUML"
msgstr "PlantUML"
@@ -5424,12 +5979,18 @@ msgstr "執行"
msgid "Please accept the Terms of Service before continuing."
msgstr "在繼續之å‰ï¼Œè«‹åŒæ„æœå‹™æ¢æ¬¾"
+msgid "Please choose a group URL with no special characters."
+msgstr ""
+
msgid "Please convert them to %{link_to_git}, and go through the %{link_to_import_flow} again."
msgstr ""
msgid "Please convert them to Git on Google Code, and go through the %{link_to_import_flow} again."
msgstr ""
+msgid "Please fill in a descriptive name for your group."
+msgstr ""
+
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
@@ -5442,6 +6003,9 @@ msgstr "請填寫驗證碼"
msgid "Please try again"
msgstr "è«‹å†è©¦ä¸€æ¬¡"
+msgid "Please use this form to report users to GitLab who create spam issues, comments or behave inappropriately."
+msgstr ""
+
msgid "Please wait while we connect to your repository. Refresh at will."
msgstr "è«‹ç¨å€™ï¼Œæˆ‘們正在連çµåˆ°æ‚¨çš„版本庫,ç¨å¾Œè«‹é‡æ–°æ•´ç†ã€‚"
@@ -5454,9 +6018,18 @@ msgstr "å好設定"
msgid "Preferences|Navigation theme"
msgstr "導航主題"
+msgid "Press Enter or click to search"
+msgstr ""
+
+msgid "Prevent adding new members to project membership within this group"
+msgstr ""
+
msgid "Preview"
msgstr ""
+msgid "Preview payload"
+msgstr ""
+
msgid "Primary"
msgstr "主è¦"
@@ -5502,15 +6075,30 @@ msgstr "新增金鑰"
msgid "Profiles|Add status emoji"
msgstr ""
+msgid "Profiles|Avatar cropper"
+msgstr ""
+
+msgid "Profiles|Avatar will be removed. Are you sure?"
+msgstr ""
+
msgid "Profiles|Change username"
msgstr "變更使用者å稱"
+msgid "Profiles|Choose file..."
+msgstr ""
+
+msgid "Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information."
+msgstr ""
+
msgid "Profiles|Clear status"
msgstr ""
msgid "Profiles|Current path: %{path}"
msgstr "ç›®å‰è·¯å¾‘:%{path}"
+msgid "Profiles|Current status"
+msgstr ""
+
msgid "Profiles|Delete Account"
msgstr "刪除帳號"
@@ -5523,39 +6111,120 @@ msgstr "刪除您的帳號?"
msgid "Profiles|Deleting an account has the following effects:"
msgstr "刪除帳號將會造æˆä»¥ä¸‹å½±éŸ¿ï¼š"
+msgid "Profiles|Do not show on profile"
+msgstr ""
+
+msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgstr ""
+
+msgid "Profiles|Edit Profile"
+msgstr ""
+
msgid "Profiles|Invalid password"
msgstr "無效的密碼"
msgid "Profiles|Invalid username"
msgstr "無效的使用者å稱"
+msgid "Profiles|Learn more"
+msgstr ""
+
+msgid "Profiles|Made a private contribution"
+msgstr ""
+
+msgid "Profiles|Main settings"
+msgstr ""
+
+msgid "Profiles|No file chosen"
+msgstr ""
+
msgid "Profiles|Path"
msgstr "ä½ç½®"
+msgid "Profiles|Position and size your new avatar"
+msgstr ""
+
+msgid "Profiles|Private contributions"
+msgstr ""
+
+msgid "Profiles|Public Avatar"
+msgstr ""
+
+msgid "Profiles|Remove avatar"
+msgstr ""
+
+msgid "Profiles|Set new profile picture"
+msgstr ""
+
+msgid "Profiles|Some options are unavailable for LDAP accounts"
+msgstr ""
+
+msgid "Profiles|Tell us about yourself in fewer than 250 characters."
+msgstr ""
+
+msgid "Profiles|The maximum file size allowed is 200KB."
+msgstr ""
+
msgid "Profiles|This doesn't look like a public SSH key, are you sure you want to add it?"
msgstr "這看起來ä¸åƒæ˜¯ SSH 公鑰,您確定è¦å¢žåŠ å®ƒå—Žï¼Ÿ"
+msgid "Profiles|This email will be displayed on your public profile."
+msgstr ""
+
+msgid "Profiles|This email will be used for web based operations, such as edits and merges. %{learn_more}"
+msgstr ""
+
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
msgstr ""
+msgid "Profiles|This feature is experimental and translations are not complete yet."
+msgstr ""
+
+msgid "Profiles|This information will appear on your profile."
+msgstr ""
+
msgid "Profiles|Type your %{confirmationValue} to confirm:"
msgstr "輸入您的 %{confirmationValue} 以確èªï¼š"
msgid "Profiles|Typically starts with \"ssh-rsa …\""
msgstr "通常以 \"ssh-rsa …\" 起頭"
+msgid "Profiles|Update profile settings"
+msgstr ""
+
msgid "Profiles|Update username"
msgstr "更新使用者å稱"
+msgid "Profiles|Upload new avatar"
+msgstr ""
+
+msgid "Profiles|Use a private email - %{email}"
+msgstr ""
+
msgid "Profiles|Username change failed - %{message}"
msgstr "使用者å稱更改失敗 - %{message}"
msgid "Profiles|Username successfully changed"
msgstr "使用者å稱順利變更"
+msgid "Profiles|Website"
+msgstr ""
+
msgid "Profiles|What's your status?"
msgstr ""
+msgid "Profiles|You can change your avatar here"
+msgstr ""
+
+msgid "Profiles|You can change your avatar here or remove the current avatar to revert to %{gravatar_link}"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here"
+msgstr ""
+
+msgid "Profiles|You can upload your avatar here or change it at %{gravatar_link}"
+msgstr ""
+
msgid "Profiles|You don't have access to delete this user."
msgstr "您沒有權é™åˆªé™¤æ­¤å¸³è™Ÿ"
@@ -5565,6 +6234,15 @@ msgstr "你必須轉æ›ä½ çš„所有權或在你刪除你帳號å‰åˆªé™¤é€™äº›ç¾¤
msgid "Profiles|Your account is currently an owner in these groups:"
msgstr "你的帳號目å‰æ“有這些群組:"
+msgid "Profiles|Your email address was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your location was automatically set based on your %{provider_label} account."
+msgstr ""
+
+msgid "Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you."
+msgstr ""
+
msgid "Profiles|Your status"
msgstr ""
@@ -5601,6 +6279,9 @@ msgstr "專案 '%{project_name}' 更新完æˆã€‚"
msgid "Project Badges"
msgstr "專案徽章"
+msgid "Project URL"
+msgstr ""
+
msgid "Project access must be granted explicitly to each user."
msgstr "專案權é™å¿…須一一指派給æ¯å€‹ä½¿ç”¨è€…。"
@@ -5628,6 +6309,9 @@ msgstr "專案導出已開始。完æˆå¾Œä¸‹è¼‰é€£çµæœƒé€åˆ°æ‚¨çš„信箱。"
msgid "Project name"
msgstr "專案å稱"
+msgid "Project slug"
+msgstr ""
+
msgid "ProjectActivityRSS|Subscribe"
msgstr "訂閱"
@@ -5655,6 +6339,27 @@ msgstr "從未"
msgid "ProjectLifecycle|Stage"
msgstr "階段"
+msgid "ProjectOverview|Fork"
+msgstr ""
+
+msgid "ProjectOverview|Forks"
+msgstr ""
+
+msgid "ProjectOverview|Go to your fork"
+msgstr ""
+
+msgid "ProjectOverview|Star"
+msgstr ""
+
+msgid "ProjectOverview|Unstar"
+msgstr ""
+
+msgid "ProjectOverview|You have reached your project limit"
+msgstr ""
+
+msgid "ProjectOverview|You must sign in to star a project"
+msgstr ""
+
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
@@ -5697,6 +6402,9 @@ msgstr "專案"
msgid "Projects shared with %{group_name}"
msgstr ""
+msgid "Projects that belong to a group are prefixed with the group namespace. Existing projects may be moved into a group."
+msgstr ""
+
msgid "ProjectsDropdown|Frequently visited"
msgstr "經常使用"
@@ -5766,9 +6474,6 @@ msgstr "自動設定"
msgid "PrometheusService|Automatically deploy and configure Prometheus on your clusters to monitor your project’s environments"
msgstr "在你的群集上自動部署和é…ç½® Prometheus 以監控您的專案環境"
-msgid "PrometheusService|By default, Prometheus listens on ‘http://localhost:9090’. It’s not recommended to change the default address and port as this might affect or conflict with other services running on the GitLab server."
-msgstr "é è¨­ Prometheus ç›£è½ â€˜http://localhost:9090’。ä¸å»ºè­°æ›´æ”¹é è¨­çš„網å€å’Œç›£è½åŸ ï¼Œå› ç‚ºé€™å¯èƒ½æœƒå¼•éŸ¿åˆ° GitLab 伺æœå™¨ä¸Šé‹è¡Œçš„其他æœå‹™ã€‚"
-
msgid "PrometheusService|Common metrics"
msgstr "常見指標"
@@ -5961,6 +6666,12 @@ msgstr "說明檔"
msgid "Real-time features"
msgstr "å³æ™‚功能"
+msgid "Recent searches"
+msgstr ""
+
+msgid "Redirect to SAML provider to test configuration"
+msgstr ""
+
msgid "Reference:"
msgstr "åƒè€ƒä¾†æº:"
@@ -6022,12 +6733,21 @@ msgstr "移除執行器"
msgid "Remove avatar"
msgstr "刪除大頭貼"
+msgid "Remove group"
+msgstr ""
+
msgid "Remove priority"
msgstr "刪除優先權"
msgid "Remove project"
msgstr "刪除專案"
+msgid "Removed group can not be restored!"
+msgstr ""
+
+msgid "Removing group will cause all child projects and resources to be removed."
+msgstr ""
+
msgid "Rename"
msgstr ""
@@ -6037,6 +6757,9 @@ msgstr ""
msgid "Rename folder"
msgstr ""
+msgid "Reopen epic"
+msgstr ""
+
msgid "Repair authentication"
msgstr "修復èªè­‰"
@@ -6046,18 +6769,33 @@ msgstr ""
msgid "Repo by URL"
msgstr "來自 URL 的版本庫"
+msgid "Report abuse to GitLab"
+msgstr ""
+
+msgid "Reporting"
+msgstr ""
+
msgid "Reports|%{failedString} and %{resolvedString}"
msgstr ""
+msgid "Reports|Actions"
+msgstr ""
+
msgid "Reports|Class"
msgstr ""
+msgid "Reports|Confidence"
+msgstr ""
+
msgid "Reports|Execution time"
msgstr ""
msgid "Reports|Failure"
msgstr ""
+msgid "Reports|Severity"
+msgstr ""
+
msgid "Reports|System output"
msgstr ""
@@ -6070,6 +6808,9 @@ msgstr ""
msgid "Reports|Test summary results are being parsed"
msgstr ""
+msgid "Reports|Vulnerability"
+msgstr ""
+
msgid "Reports|no changed test results"
msgstr ""
@@ -6103,12 +6844,12 @@ msgstr "申請權é™"
msgid "Requests Profiles"
msgstr "請求個人資料"
+msgid "Require all users in this group to setup Two-factor authentication"
+msgstr ""
+
msgid "Require all users to accept Terms of Service and Privacy Policy when they access GitLab."
msgstr "è¦æ±‚所有用戶在訪å•GitLab時接å—æœå‹™æ¢æ¬¾å’Œéš±ç§æ”¿ç­–。"
-msgid "Reset git storage health information"
-msgstr "é‡ç½® Git 儲存空間å¥åº·æŒ‡æ•¸"
-
msgid "Reset health check access token"
msgstr "é‡ç½®å¥åº·æª¢æŸ¥å­˜å–憑證"
@@ -6124,9 +6865,21 @@ msgstr "解決來æºåˆ†æ”¯ä¸Šçš„è¡çª"
msgid "Resolve discussion"
msgstr "關閉討論"
+msgid "Response metrics (AWS ELB)"
+msgstr ""
+
msgid "Response metrics (Custom)"
msgstr "接收指標 (自訂)"
+msgid "Response metrics (HA Proxy)"
+msgstr ""
+
+msgid "Response metrics (NGINX Ingress)"
+msgstr ""
+
+msgid "Response metrics (NGINX)"
+msgstr ""
+
msgid "Resume"
msgstr "繼續"
@@ -6176,9 +6929,24 @@ msgstr "執行外部版本庫的 CI / CD æµæ°´ç·šã€‚"
msgid "Run untagged jobs"
msgstr ""
+msgid "Runner cannot be assigned to other projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects"
+msgstr ""
+
+msgid "Runner runs jobs from all unassigned projects in its group"
+msgstr ""
+
+msgid "Runner runs jobs from assigned projects"
+msgstr ""
+
msgid "Runner token"
msgstr "執行器憑證"
+msgid "Runner will not receive any new jobs"
+msgstr ""
+
msgid "Runners"
msgstr "執行器"
@@ -6188,6 +6956,12 @@ msgstr "執行器 API"
msgid "Runners can be placed on separate users, servers, and even on your local machine."
msgstr "執行器å¯æ”¾ç½®æ–¼ä¸åŒçš„使用者ã€ä¼ºæœå™¨ï¼Œç”šè‡³åœ¨æ‚¨çš„本地機器上。"
+msgid "Runners can be placed on separate users, servers, even on your local machine."
+msgstr ""
+
+msgid "Runners currently online: %{active_runners_count}"
+msgstr ""
+
msgid "Runners page"
msgstr ""
@@ -6212,6 +6986,9 @@ msgstr "SAML 單一登入"
msgid "SAML Single Sign On Settings"
msgstr "SAML 單一登入設定"
+msgid "SAST"
+msgstr ""
+
msgid "SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
msgstr "SAML 憑證登入憑證的 SHA1 指紋。從您的身份æ供者å–得這個指紋 -- 它å¯èƒ½è¢«ç¨±ç‚ºã€ŒThumbprintã€"
@@ -6236,6 +7013,9 @@ msgstr "儲存應用程å¼"
msgid "Save changes"
msgstr "儲存變更"
+msgid "Save changes before testing"
+msgstr ""
+
msgid "Save pipeline schedule"
msgstr "儲存æµæ°´ç·šæŽ’程"
@@ -6290,15 +7070,24 @@ msgstr "æœå°‹åˆä½µè«‹æ±‚"
msgid "Search milestones"
msgstr "æœå°‹é‡Œç¨‹ç¢‘"
+msgid "Search or filter results..."
+msgstr ""
+
msgid "Search or jump to…"
msgstr ""
msgid "Search project"
msgstr "æœå°‹å°ˆæ¡ˆ"
+msgid "Search projects"
+msgstr ""
+
msgid "Search users"
msgstr "æœå°‹ä½¿ç”¨è€…"
+msgid "Search your projects"
+msgstr ""
+
msgid "SearchAutocomplete|All GitLab"
msgstr ""
@@ -6323,14 +7112,8 @@ msgstr ""
msgid "SearchAutocomplete|in this project"
msgstr ""
-msgid "Seconds before reseting failure information"
-msgstr "é‡ç½®å¤±æ•—訊æ¯ç­‰å¾…時間(秒)"
-
-msgid "Seconds to wait for a storage access attempt"
-msgstr "等待存å–儲存空間的嘗試時間(秒)"
-
-msgid "Secret:"
-msgstr "金鑰:"
+msgid "Secret"
+msgstr ""
msgid "Security"
msgstr ""
@@ -6338,11 +7121,46 @@ msgstr ""
msgid "Security Dashboard"
msgstr "安全儀表æ¿"
-msgid "Security scanning detected %d vulnerability for the source branch only"
-msgid_plural "Security scanning detected %d vulnerabilities for the source branch only"
-msgstr[0] ""
+msgid "Security Dashboard|Error fetching the dashboard data. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability counts. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Error fetching the vulnerability list. Please check your network connection and try again."
+msgstr ""
+
+msgid "Security Dashboard|Issue Created"
+msgstr ""
+
+msgid "Security Reports|At this time, the security dashboard only supports SAST."
+msgstr ""
+
+msgid "Security Reports|Create issue"
+msgstr ""
+
+msgid "Security Reports|Dismiss vulnerability"
+msgstr ""
-msgid "Security scanning detected no vulnerabilities for the source branch only"
+msgid "Security Reports|More info"
+msgstr ""
+
+msgid "Security Reports|Revert dismissal"
+msgstr ""
+
+msgid "Security Reports|Security dashboard documentation"
+msgstr ""
+
+msgid "Security Reports|There was an error creating the issue."
+msgstr ""
+
+msgid "Security Reports|There was an error dismissing the vulnerability."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting the dismissal."
+msgstr ""
+
+msgid "Security Reports|There was an error reverting this dismissal."
msgstr ""
msgid "SecurityDashboard| The security dashboard displays the latest security report. Use it to find and fix vulnerabilities."
@@ -6360,9 +7178,15 @@ msgstr "é¸æ“‡"
msgid "Select Archive Format"
msgstr "é¸æ“‡ä¸‹è¼‰æ ¼å¼"
+msgid "Select a group to invite"
+msgstr ""
+
msgid "Select a namespace to fork the project"
msgstr "é¸æ“‡ä¸€å€‹å‘½å空間,以複製這個專案"
+msgid "Select a template repository"
+msgstr ""
+
msgid "Select a timezone"
msgstr "é¸æ“‡æ™‚å€"
@@ -6393,6 +7217,9 @@ msgstr "é¸æ“‡ä¾†æºåˆ†æ”¯"
msgid "Select target branch"
msgstr "é¸æ“‡ç›®æ¨™åˆ†æ”¯"
+msgid "Select the branch you want to set as the default for this project. All merge requests and commits will automatically be made against this branch unless you specify a different one."
+msgstr ""
+
msgid "Select the custom project template source group."
msgstr ""
@@ -6405,6 +7232,9 @@ msgstr "é¸æ“‡æ€§åŒæ­¥"
msgid "Send email"
msgstr "傳é€é›»å­éƒµä»¶"
+msgid "Send usage data"
+msgstr ""
+
msgid "Sep"
msgstr "ä¹æœˆ"
@@ -6429,6 +7259,9 @@ msgstr "éŽæœŸå·¥ä½œéšŽæ®µã€å°ˆæ¡ˆä¸Šé™èˆ‡é™„件大å°ã€‚"
msgid "Set a password on your account to pull or push via %{protocol}."
msgstr "請先設定密碼,æ‰èƒ½ä½¿ç”¨ %{protocol} 來上傳或下載。"
+msgid "Set a template repository for projects in this group"
+msgstr ""
+
msgid "Set default and restrict visibility levels. Configure import sources and git access protocol."
msgstr "設定為é è¨­å€¼ï¼Œä¸¦é™åˆ¶å¯è¦‹ç­‰ç´šã€‚設定匯入來æºå’Œ git å­˜å–連接å”定。"
@@ -6447,8 +7280,11 @@ msgstr "設定使用者登入的需求。啟用強制性的兩步驟驗證。"
msgid "Set up CI/CD"
msgstr "設定 CI/CD"
-msgid "Set up Koding"
-msgstr "設定 Koding"
+msgid "Set up a %{type} Runner manually"
+msgstr ""
+
+msgid "Set up a specific Runner automatically"
+msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
msgstr "根據 %{docsLinkStart}這個文件%{icon}%{docsLinkEnd} 設定斷言 / 屬性 / è²æ˜Ž (email, first_name, last_name) å’Œ NameID"
@@ -6459,14 +7295,32 @@ msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr "設定密碼"
-msgid "Settings"
-msgstr "設定"
+msgid "SetStatusModal|Add status emoji"
+msgstr ""
-msgid "Set up a %{type} Runner manually"
+msgid "SetStatusModal|Clear status"
msgstr ""
-msgid "Set up a specific Runner automatically"
-msgstr "自動設置特定的執行器"
+msgid "SetStatusModal|Edit status"
+msgstr ""
+
+msgid "SetStatusModal|Remove status"
+msgstr ""
+
+msgid "SetStatusModal|Set a status"
+msgstr ""
+
+msgid "SetStatusModal|Set status"
+msgstr ""
+
+msgid "SetStatusModal|Sorry, we weren't able to set your status. Please try again later."
+msgstr ""
+
+msgid "SetStatusModal|What's your status?"
+msgstr ""
+
+msgid "Settings"
+msgstr "設定"
msgid "Share"
msgstr "分享"
@@ -6477,6 +7331,9 @@ msgstr "與æˆå“¡åˆ†äº« <strong>%{sso_label}</strong>,使他們能é€éŽæ‚¨çš„
msgid "Shared Runners"
msgstr "分享的執行器"
+msgid "Shared projects"
+msgstr ""
+
msgid "SharedRunnersMinutesSettings|By resetting the pipeline minutes for this namespace, the currently used minutes will be set to zero."
msgstr "通éŽé‡è¨­æ­¤å‘½å空間的æµæ°´ç·šåŸ·è¡Œæ™‚間,目å‰ä½¿ç”¨çš„執行時間將會被歸零。"
@@ -6559,12 +7416,18 @@ msgstr "為éœæ…‹ç¶²ç«™çš„大å°èˆ‡ç¶²åŸŸè¨­å®š"
msgid "Slack application"
msgstr "Slack 應用程å¼"
-msgid "Slack integration allows you to interact with GitLab via shash commands in a chat window."
+msgid "Slack integration allows you to interact with GitLab via slash commands in a chat window."
msgstr ""
msgid "Slower but makes sure the project workspace is pristine as it clones the repository from scratch for every job"
msgstr "速度較慢,但確ä¿é …目工作空間是原始的,因為它為æ¯é …工作從頭開始複製檔案庫"
+msgid "Smartcard"
+msgstr ""
+
+msgid "Smartcard authentication failed: client certificate header is missing."
+msgstr ""
+
msgid "Snippets"
msgstr "程å¼ç¢¼ç‰‡æ®µ"
@@ -6592,9 +7455,15 @@ msgstr "在關閉議題 %{issuable} 時出ç¾å•é¡Œï¼Œè«‹ç¨å¾Œå†è©¦"
msgid "Something went wrong while fetching %{listType} list"
msgstr ""
+msgid "Something went wrong while fetching comments. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching group member contributions"
msgstr "å–得群組æˆå“¡è²¢ç»æ™‚發生錯誤。"
+msgid "Something went wrong while fetching the environments for this merge request. Please try again."
+msgstr ""
+
msgid "Something went wrong while fetching the projects."
msgstr "讀å–專案時發生錯誤。"
@@ -6607,12 +7476,24 @@ msgstr "é‡æ–°é–‹å•Ÿ %{issuable} 議題時發生錯誤。請ç¨å¾Œå†è©¦"
msgid "Something went wrong while resolving this discussion. Please try again."
msgstr "解決此議題時出ç¾å•é¡Œã€‚è«‹å†è©¦ä¸€æ¬¡ã€‚"
+msgid "Something went wrong, unable to add %{project} to dashboard"
+msgstr ""
+
+msgid "Something went wrong, unable to get operations projects"
+msgstr ""
+
+msgid "Something went wrong, unable to remove project"
+msgstr ""
+
msgid "Something went wrong. Please try again."
msgstr "發生了未知的錯誤,請ç¨å¾Œå†è©¦"
msgid "Sorry, no epics matched your search"
msgstr "抱歉,沒有符åˆæ‚¨æœå°‹çš„ Epic"
+msgid "Sorry, no projects matched your search"
+msgstr ""
+
msgid "Sort by"
msgstr "排åº"
@@ -6643,6 +7524,9 @@ msgstr "最大群組"
msgid "SortOptions|Largest repository"
msgstr "最大儲存庫"
+msgid "SortOptions|Last Contact"
+msgstr ""
+
msgid "SortOptions|Last created"
msgstr "最近建立"
@@ -6673,6 +7557,9 @@ msgstr "加大權é‡"
msgid "SortOptions|Most popular"
msgstr "最å—æ­¡è¿Ž"
+msgid "SortOptions|Most stars"
+msgstr ""
+
msgid "SortOptions|Name"
msgstr "å稱"
@@ -6703,6 +7590,9 @@ msgstr "優先"
msgid "SortOptions|Recent sign in"
msgstr "最近登入"
+msgid "SortOptions|Start date"
+msgstr ""
+
msgid "SortOptions|Start later"
msgstr "ç¨å¾Œé–‹å§‹"
@@ -6778,9 +7668,21 @@ msgstr "星標項目"
msgid "Start a %{new_merge_request} with these changes"
msgstr "以這些改動建立一個新的 %{new_merge_request} "
+msgid "Start a review"
+msgstr ""
+
+msgid "Start and due date"
+msgstr ""
+
+msgid "Start date"
+msgstr ""
+
msgid "Start the Runner!"
msgstr "å•Ÿå‹• Runner!"
+msgid "Start your trial"
+msgstr ""
+
msgid "Started"
msgstr "已開始"
@@ -6793,6 +7695,9 @@ msgstr "暫存您的訊æ¯ä»¥å•Ÿç”¨"
msgid "Status"
msgstr "狀態"
+msgid "Stop environment"
+msgstr ""
+
msgid "Stop impersonation"
msgstr "åœæ­¢æ¨¡æ“¬"
@@ -6802,6 +7707,9 @@ msgstr "åœæ­¢æ­¤ç’°å¢ƒ"
msgid "Stopped"
msgstr "å·²åœæ­¢"
+msgid "Stopping this environment is currently not possible as a deployment is in progress"
+msgstr ""
+
msgid "Storage"
msgstr "儲存"
@@ -6811,9 +7719,15 @@ msgstr "儲存空間:"
msgid "Subgroups"
msgstr "å­ç¾¤çµ„"
+msgid "Subgroups and projects"
+msgstr ""
+
msgid "Submit as spam"
msgstr "以垃圾訊æ¯æ交"
+msgid "Submit review"
+msgstr ""
+
msgid "Submit search"
msgstr ""
@@ -6826,6 +7740,12 @@ msgstr "訂閱群組"
msgid "Subscribe at project level"
msgstr "訂閱專案"
+msgid "Subscribed"
+msgstr ""
+
+msgid "Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr "切æ›åˆ†æ”¯/標籤"
@@ -6844,6 +7764,9 @@ msgstr "系統標頭與尾端:"
msgid "System metrics (Custom)"
msgstr "系統指標 (自訂)"
+msgid "System metrics (Kubernetes)"
+msgstr ""
+
msgid "Tag (%{tag_count})"
msgid_plural "Tags (%{tag_count})"
msgstr[0] "標籤(%{tag_count})"
@@ -6947,6 +7870,9 @@ msgstr "æœå‹™æ¢æ¬¾å”議和隱ç§æ”¿ç­–"
msgid "Terms of Service and Privacy Policy"
msgstr "æœå‹™æ¢æ¬¾å’Œéš±ç§æ”¿ç­–"
+msgid "Test SAML SSO"
+msgstr ""
+
msgid "Test coverage parsing"
msgstr "測試覆蓋率分æž"
@@ -6995,12 +7921,6 @@ msgstr "議題階段顯示從議題建立到設定里程碑所花的時間,或
msgid "The maximum file size allowed is 200KB."
msgstr "最大檔案大å°ç‚º 200KB"
-msgid "The number of attempts GitLab will make to access a storage."
-msgstr "GitLab å­˜å–儲存空間的嘗試次數。"
-
-msgid "The number of failures after which GitLab will completely prevent access to the storage. The number of failures can be reset in the admin interface: %{link_to_health_page} or using the %{api_documentation_link}."
-msgstr ""
-
msgid "The passphrase required to decrypt the private key. This is optional and the value is encrypted at rest."
msgstr "解密ç§é‘°æ‰€éœ€çš„密碼。這是é¸ç”¨ä¸”該值將會被加密儲存。"
@@ -7049,9 +7969,6 @@ msgstr "複閱階段顯示從åˆä½µè«‹æ±‚建立後至被åˆä½µçš„時間。當建
msgid "The roadmap shows the progress of your epics along a timeline"
msgstr "開發è—圖顯示了時間軸上您的 Epic 的進度"
-msgid "The secure token used by the Runner to checkout the project"
-msgstr "此安全憑證使用於執行器簽出專案"
-
msgid "The staging stage shows the time between merging the MR and deploying code to the production environment. The data will be automatically added once you deploy to production for the first time."
msgstr "試營é‹æ®µé¡¯ç¤ºå¾žåˆä½µè«‹æ±‚被åˆä½µå¾Œè‡³éƒ¨ç½²ç‡Ÿé‹çš„時間。當第一次部署營é‹å¾Œï¼Œè³‡æ–™å°‡è‡ªå‹•å¡«å…¥"
@@ -7061,21 +7978,15 @@ msgstr ""
msgid "The testing stage shows the time GitLab CI takes to run every pipeline for the related merge request. The data will automatically be added after your first pipeline finishes running."
msgstr "測試階段顯示相關åˆä½µè«‹æ±‚çš„æµæ°´ç·šæ‰€èŠ±çš„時間。當第一個æµæ°´ç·šåŸ·è¡Œå®Œç•¢å¾Œï¼Œè³‡æ–™å°‡è‡ªå‹•å¡«å…¥ã€‚"
-msgid "The time in seconds GitLab will keep failure information. When no failures occur during this time, information about the mount is reset."
-msgstr "GitLab ä¿å­˜å¤±æ•—訊æ¯çš„時間(秒)。在此時間內若沒有發生錯誤,失敗訊æ¯å°‡æœƒè¢«é‡ç½®"
-
-msgid "The time in seconds GitLab will try to access storage. After this time a timeout error will be raised."
-msgstr "GitLab 嘗試存å–檔案庫的時間 (秒)。超éŽæ­¤æ™‚間將會引發逾時錯誤。"
-
-msgid "The time in seconds between storage checks. If a check did not complete yet, GitLab will skip the next check."
-msgstr ""
-
msgid "The time taken by each data entry gathered by that stage."
msgstr "該階段中æ¯ä¸€å€‹è³‡æ–™é …目所花的時間。"
msgid "The update action will time out after %{number_of_minutes} minutes. For big repositories, use a clone/push combination."
msgstr ""
+msgid "The usage ping is disabled, and cannot be configured through this form."
+msgstr ""
+
msgid "The user map is a JSON document mapping the Google Code users that participated on your projects to the way their email addresses and usernames will be imported into GitLab. You can change this by changing the value on the right hand side of <code>:</code>. Be sure to preserve the surrounding double quotes, other punctuation and the email address or username on the left hand side."
msgstr ""
@@ -7085,6 +7996,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "中ä½æ•¸æ˜¯ä¸€å€‹æ•¸åˆ—中最中間的值。例如在 3ã€5ã€9 之間,中ä½æ•¸æ˜¯ 5。在 3ã€5ã€7ã€8 之間,中ä½æ•¸æ˜¯ (5 + 7)/ 2 = 6。"
+msgid "There are no archived projects yet"
+msgstr ""
+
msgid "There are no issues to show"
msgstr "沒有å¯ä»¥é¡¯ç¤ºçš„è­°é¡Œ"
@@ -7094,8 +8008,14 @@ msgstr "ç›®å‰é‚„沒有標籤"
msgid "There are no merge requests to show"
msgstr "沒有任何的åˆä½µè«‹æ±‚"
-msgid "There are problems accessing Git storage: "
-msgstr "å­˜å– Git 儲存空間時出ç¾å•é¡Œï¼š"
+msgid "There are no projects shared with this group yet"
+msgstr ""
+
+msgid "There are no staged changes"
+msgstr ""
+
+msgid "There are no unstaged changes"
+msgstr ""
msgid "There was an error adding a todo."
msgstr ""
@@ -7142,10 +8062,13 @@ msgstr "已縮å°æ­¤çœ‹æ¿ç¯„åœ"
msgid "This branch has changed since you started editing. Would you like to create a new branch?"
msgstr ""
-msgid "This date is after the planned finish date, so this epic won't appear in the roadmap."
+msgid "This container registry has been scheduled for deletion."
msgstr ""
-msgid "This date is before the planned start date, so this epic won't appear in the roadmap."
+msgid "This date is after the due date, so this epic won't appear in the roadmap."
+msgstr ""
+
+msgid "This date is before the start date, so this epic won't appear in the roadmap."
msgstr ""
msgid "This diff is collapsed."
@@ -7166,6 +8089,9 @@ msgstr "這群組尚未æ供任何群組執行器。"
msgid "This is a confidential issue."
msgstr "這是個隱密å•é¡Œã€‚"
+msgid "This is a delayed job to run in %{remainingTime}"
+msgstr ""
+
msgid "This is the author's first Merge Request to this project."
msgstr "這是作者第一次åˆä½µè«‹æ±‚至本專案。"
@@ -7205,7 +8131,10 @@ msgstr ""
msgid "This job is an out-of-date deployment to %{environmentLink}. View the most recent deployment %{deploymentLink}."
msgstr ""
-msgid "This job is creating a deployment to %{environmentLink} and will overwrite the last %{deploymentLink}."
+msgid "This job is archived. Only the complete pipeline can be retried."
+msgstr ""
+
+msgid "This job is creating a deployment to %{environmentLink} and will overwrite the %{deploymentLink}."
msgstr ""
msgid "This job is creating a deployment to %{environmentLink}."
@@ -7226,6 +8155,9 @@ msgstr ""
msgid "This job requires a manual action"
msgstr "這份任務需è¦æ‰‹å‹•åŸ·è¡Œ"
+msgid "This job will automatically run after it's timer finishes. Often they are used for incremental roll-out deploys to production environments. When unscheduled it converts into a manual action."
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr "這代表在您建立一個空的檔案庫或是匯入一個ç¾å­˜çš„檔案庫之å‰ï¼Œæ‚¨å°‡ç„¡æ³•ä¸Šå‚³æ›´æ–°ã€‚"
@@ -7250,6 +8182,9 @@ msgstr "這個專案"
msgid "This project does not belong to a group and can therefore not make use of group Runners."
msgstr "此專案ä¸å±¬æ–¼ä¸€å€‹ç¾¤çµ„,因此ä¸èƒ½ä½¿ç”¨ç¾¤çµ„執行器。"
+msgid "This project does not have a wiki homepage yet"
+msgstr ""
+
msgid "This project does not have billing enabled. To create a cluster, <a href=%{linkToBilling} target=\"_blank\" rel=\"noopener noreferrer\">enable billing <i class=\"fa fa-external-link\" aria-hidden=\"true\"></i></a> and try again."
msgstr ""
@@ -7259,6 +8194,12 @@ msgstr "這個檔案庫"
msgid "This runner will only run on pipelines triggered on protected branches"
msgstr ""
+msgid "This setting can be overridden in each project."
+msgstr ""
+
+msgid "This setting will update the hostname that is used to generate private commit emails. %{learn_more}"
+msgstr ""
+
msgid "This source diff could not be displayed because it is too large."
msgstr "此原始碼差異無法顯示,因為它太大。"
@@ -7286,9 +8227,15 @@ msgstr "議題被列入日程表的時間"
msgid "Time before an issue starts implementation"
msgstr "議題等待開始實作的時間"
+msgid "Time before enforced"
+msgstr ""
+
msgid "Time between merge request creation and merge/close"
msgstr "åˆä½µè«‹æ±‚從建立到被åˆä½µæˆ–是關閉的時間"
+msgid "Time estimate"
+msgstr ""
+
msgid "Time in seconds GitLab will wait for a response from the external service. When the service does not respond in time, access will be denied."
msgstr "GitLab 等待外部æœå‹™çš„回應時間(秒)。當æœå‹™æ²’有在時間內回應時,存å–將被拒絕。"
@@ -7477,12 +8424,24 @@ msgstr "è‹¥è¦é€£æŽ¥åˆ°ä¸€å€‹ SVN 版本庫,請åƒé–± %{svn_link}。"
msgid "To define internal users, first enable new users set to external"
msgstr ""
+msgid "To enable it and see User Cohorts, visit %{application_settings_link_start}application settings%{application_settings_link_end}."
+msgstr ""
+
msgid "To get started you enter your FogBugz URL and login information below. In the next steps, you'll be able to map users and select the projects you want to import."
msgstr ""
+msgid "To get started, link this page to your Jaeger server, or find out how to %{link_start_tag}install Jaeger%{link_end_tag}"
+msgstr ""
+
msgid "To get started, please enter your Gitea Host URL and a %{link_to_personal_token}."
msgstr ""
+msgid "To help improve GitLab and its user experience, GitLab will periodically collect usage information."
+msgstr ""
+
+msgid "To help improve GitLab, we would like to periodically collect usage information. This can be changed at any time in %{settings_link_start}Settings%{link_end}. %{info_link_start}More Information%{link_end}"
+msgstr ""
+
msgid "To import GitHub repositories, you can use a %{personal_access_token_link}. When you create your Personal Access Token, you will need to select the <code>repo</code> scope, so we can display a list of your public and private repositories which are available to import."
msgstr "è¦åŒ¯å…¥ GitHub 存儲庫,你å¯ä»¥ä½¿ç”¨ %{personal_access_token_link}。當你建立你的個人存å–權æ–時,你將需è¦é¸æ“‡<code>檔案庫</code>範åœï¼Œæ‰€ä»¥æˆ‘們將會顯示你公開åŠç§äººçš„檔案庫清單進行匯入。"
@@ -7498,6 +8457,9 @@ msgstr ""
msgid "To only use CI/CD features for an external repository, choose <strong>CI/CD for external repo</strong>."
msgstr "è‹¥è¦åªå°å¤–部版本庫使用 CI / CD 功能,請é¸æ“‡ <strong>為外部版本庫的 CI/CD</strong>"
+msgid "To open Jaeger and easily view tracing from GitLab, link the %{start_tag}Tracing%{end_tag} page to your server"
+msgstr ""
+
msgid "To set up SAML authentication for your group through an identity provider like Azure, Okta, Onelogin, Ping Identity, or your custom SAML 2.0 provider:"
msgstr "è‹¥è¦é€éŽèº«ä»½æ供者(例如 Azureã€Oktaã€Oneloginã€Ping Identity 或您自訂的 SAML 2.0 æ供者)設定 SAML èªè­‰ï¼š"
@@ -7510,12 +8472,15 @@ msgstr ""
msgid "To validate your GitLab CI configurations, go to 'CI/CD → Pipelines' inside your project, and click on the 'CI Lint' button."
msgstr "è‹¥è¦é©—證您的 GitLab CI 設定,請å‰å¾€æ‚¨å°ˆæ¡ˆå…§çš„「CI/CD → æµæ°´ç·šã€ï¼Œä¸¦æŒ‰ä¸‹ã€ŒCI Lintã€æŒ‰éˆ•ã€‚"
-msgid "To view the roadmap, add a planned start or finish date to one of your epics in this group or its subgroups. Only epics in the past 3 months and the next 3 months are shown."
-msgstr "è‹¥è¦æª¢è¦–開發è—圖,請在您群組或å­ç¾¤çµ„中的其中一個 Epic 中增加計畫開始或完æˆæ™‚間。åªæœƒé¡¯ç¤ºæœ€è¿‘三個月或接下來三個月的 Epic。"
+msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
+msgstr ""
msgid "To widen your search, change or remove filters."
msgstr "è‹¥è¦æ“´å¤§æœå°‹ç¯„åœï¼Œè«‹è®Šæ›´æˆ–移除篩é¸å™¨ã€‚"
+msgid "Today"
+msgstr ""
+
msgid "Todo"
msgstr "待辦事項"
@@ -7525,9 +8490,15 @@ msgstr "待辦事項"
msgid "Toggle Sidebar"
msgstr "展開 / 收起å´é‚Šæ¬„"
+msgid "Toggle commit description"
+msgstr ""
+
msgid "Toggle discussion"
msgstr "切æ›è¨Žè«–"
+msgid "Toggle file browser"
+msgstr ""
+
msgid "Toggle navigation"
msgstr "切æ›å°Žèˆªæ¬„"
@@ -7543,6 +8514,9 @@ msgstr "切æ›ç‹€æ…‹ï¼šé–‹å•Ÿ"
msgid "Token"
msgstr ""
+msgid "Tomorrow"
+msgstr ""
+
msgid "Too many changes to show."
msgstr "太多的更改。"
@@ -7558,6 +8532,9 @@ msgstr "åˆä½µ/更動記錄的總測試時間"
msgid "Total: %{total}"
msgstr "總計: %{total}"
+msgid "Tracing"
+msgstr ""
+
msgid "Track activity with Contribution Analytics."
msgstr "追蹤貢ç»åˆ†æžçš„相關動態"
@@ -7567,6 +8544,9 @@ msgstr "跟蹤共通主題ã€è·¨å°ˆæ¡ˆå’Œé‡Œç¨‹ç¢‘的議題群組"
msgid "Track time with quick actions"
msgstr "快速使用時間追蹤工具"
+msgid "Tree view"
+msgstr ""
+
msgid "Trending"
msgstr "趨勢分æž"
@@ -7585,24 +8565,42 @@ msgstr "啟動此任務"
msgid "Triggers can force a specific branch or tag to get rebuilt with an API call. These tokens will impersonate their associated user including their access to projects and their project permissions."
msgstr "觸發器å¯ä»¥å¼·åˆ¶ä½¿ç”¨API​​調用é‡å»ºç‰¹å®šçš„分支或標記。這些令牌將模仿他們的關è¯ç”¨æˆ¶ï¼ŒåŒ…括他們å°é …目的訪å•æ¬Šé™ã€‚"
+msgid "Troubleshoot and monitor your application with tracing"
+msgstr ""
+
msgid "Try again"
msgstr "é‡è©¦"
+msgid "Try all GitLab has to offer for 30 days."
+msgstr ""
+
msgid "Turn on Service Desk"
msgstr "é–‹å•Ÿæœå‹™å€"
msgid "Twitter"
msgstr "Twitter"
+msgid "Two-factor authentication"
+msgstr ""
+
msgid "Type"
msgstr ""
msgid "Unable to load the diff. %{button_try_again}"
msgstr "無法載入差異。%{button_try_again}"
+msgid "Unable to save your changes"
+msgstr ""
+
msgid "Unable to sign you in to the group with SAML due to \"%{reason}\""
msgstr "因為「%{reason}ã€ï¼Œæ‰€ä»¥ç„¡æ³•è®“ä½ é€éŽ SAML 登入這個群組。"
+msgid "Unable to update this epic at this time."
+msgstr ""
+
+msgid "Undo"
+msgstr ""
+
msgid "Unknown"
msgstr "未知"
@@ -7618,6 +8616,12 @@ msgstr "已解鎖"
msgid "Unresolve discussion"
msgstr "é‡æ–°è¨Žè«–"
+msgid "Unschedule job"
+msgstr ""
+
+msgid "Unstage"
+msgstr ""
+
msgid "Unstage all changes"
msgstr "å–消暫存所有變更"
@@ -7651,14 +8655,17 @@ msgstr "未驗證"
msgid "Up to date"
msgstr "已經是最新"
+msgid "Upcoming"
+msgstr ""
+
msgid "Update"
msgstr "æ›´æ–°"
msgid "Update now"
msgstr ""
-msgid "Update your group name, description, avatar, and other general settings."
-msgstr "更新您的群組å稱ã€èªªæ˜Žã€é ­åƒèˆ‡å…¶ä»–一般設定。"
+msgid "Update your group name, description, avatar, and visibility."
+msgstr ""
msgid "Updating"
msgstr ""
@@ -7687,15 +8694,15 @@ msgstr "上傳新檔案"
msgid "Upload file"
msgstr "上傳檔案"
-msgid "Upload new avatar"
-msgstr "上傳大頭貼"
-
msgid "UploadLink|click to upload"
msgstr "點擊上傳"
msgid "Upvotes"
msgstr "讚"
+msgid "Usage ping is not enabled"
+msgstr ""
+
msgid "Usage statistics"
msgstr "使用情形統計資料"
@@ -7723,6 +8730,9 @@ msgstr "使用全域通知設定"
msgid "Used by members to sign in to your group in GitLab"
msgstr "用來讓æˆå“¡ç™»å…¥æ‚¨åœ¨ GitLab 的群組"
+msgid "User Cohorts are only shown when the %{usage_ping_link_start}usage ping%{usage_ping_link_end} is enabled."
+msgstr ""
+
msgid "User Settings"
msgstr "使用者設定"
@@ -7732,12 +8742,54 @@ msgstr "使用者與 IP 速率é™åˆ¶"
msgid "User map"
msgstr ""
-msgid "Users"
-msgstr "使用者"
+msgid "UserProfile|Activity"
+msgstr ""
+
+msgid "UserProfile|Already reported for abuse"
+msgstr ""
+
+msgid "UserProfile|Contributed projects"
+msgstr ""
+
+msgid "UserProfile|Edit profile"
+msgstr ""
+
+msgid "UserProfile|Groups"
+msgstr ""
-msgid "User|Current status"
+msgid "UserProfile|Most Recent Activity"
msgstr ""
+msgid "UserProfile|Overview"
+msgstr ""
+
+msgid "UserProfile|Personal projects"
+msgstr ""
+
+msgid "UserProfile|Recent contributions"
+msgstr ""
+
+msgid "UserProfile|Report abuse"
+msgstr ""
+
+msgid "UserProfile|Snippets"
+msgstr ""
+
+msgid "UserProfile|Subscribe"
+msgstr ""
+
+msgid "UserProfile|This user has a private profile"
+msgstr ""
+
+msgid "UserProfile|View all"
+msgstr ""
+
+msgid "UserProfile|View user in admin area"
+msgstr ""
+
+msgid "Users"
+msgstr "使用者"
+
msgid "Variables"
msgstr "變數"
@@ -7762,6 +8814,15 @@ msgstr "已驗證"
msgid "Version"
msgstr ""
+msgid "View %{alerts}"
+msgstr ""
+
+msgid "View app"
+msgstr ""
+
+msgid "View documentation"
+msgstr ""
+
msgid "View epics list"
msgstr "檢視 Epic 列表"
@@ -7795,9 +8856,15 @@ msgstr "查看專案標籤"
msgid "View replaced file @ "
msgstr "ç€è¦½å·²æ›¿æ›æª”案 @ "
+msgid "View the documentation"
+msgstr ""
+
msgid "Visibility and access controls"
msgstr "å¯è¦‹æ€§èˆ‡å­˜å–控制"
+msgid "Visibility level"
+msgstr ""
+
msgid "Visibility level:"
msgstr ""
@@ -7816,6 +8883,36 @@ msgstr "公開"
msgid "VisibilityLevel|Unknown"
msgstr "ä¸æ˜Ž"
+msgid "Vulnerability|Class"
+msgstr ""
+
+msgid "Vulnerability|Confidence"
+msgstr ""
+
+msgid "Vulnerability|Description"
+msgstr ""
+
+msgid "Vulnerability|File"
+msgstr ""
+
+msgid "Vulnerability|Identifiers"
+msgstr ""
+
+msgid "Vulnerability|Instances"
+msgstr ""
+
+msgid "Vulnerability|Links"
+msgstr ""
+
+msgid "Vulnerability|Project"
+msgstr ""
+
+msgid "Vulnerability|Severity"
+msgstr ""
+
+msgid "Vulnerability|Solution"
+msgstr ""
+
msgid "Want to see the data? Please ask an administrator for access."
msgstr "權é™ä¸è¶³ã€‚如需查看相關資料,請å‘管ç†å“¡ç”³è«‹æ¬Šé™ã€‚"
@@ -7855,6 +8952,12 @@ msgstr "當啟用,使用者在接å—æ¢æ¬¾ä¹‹å‰éƒ½ä¸èƒ½ä½¿ç”¨ GitLab。"
msgid "When leaving the URL blank, classification labels can still be specified without disabling cross project features or performing external authorization checks."
msgstr "當 URL 留空時,還是å¯ä»¥æŒ‡å®šåˆ†é¡žæ¨™ç±¤ï¼Œè€Œä¸”ä¸å¿…åœç”¨è·¨å°ˆæ¡ˆåŠŸèƒ½æˆ–執行外部授權檢查。"
+msgid "Who can see this group?"
+msgstr ""
+
+msgid "Who will be able to see this group?"
+msgstr ""
+
msgid "Wiki"
msgstr "Wiki"
@@ -8005,6 +9108,9 @@ msgstr "是的,新增它"
msgid "Yes, let me map Google Code users to full names or GitLab users."
msgstr ""
+msgid "Yesterday"
+msgstr ""
+
msgid "You are an admin, which means granting access to <strong>%{client_name}</strong> will allow them to interact with GitLab as an admin as well. Proceed with caution."
msgstr ""
@@ -8023,9 +9129,6 @@ msgstr "å°‡è¦æŠŠ %{project_full_name} 的所有權轉移給å¦ä¸€å€‹äººã€‚真çš
msgid "You are on a read-only GitLab instance."
msgstr "您在唯讀的 GitLab 主機上。"
-msgid "You are on a secondary, <b>read-only</b> Geo node. If you want to make changes, you must visit this page on the %{primary_node}."
-msgstr "您在次è¦ä¸”<b>唯讀</b>çš„ Geo 節點上。若您想è¦é€²è¡Œè®Šæ›´ï¼Œæ‚¨å¿…é ˆç€è¦½ %{primary_node} 的這個é é¢"
-
msgid "You can %{linkStart}view the blob%{linkEnd} instead."
msgstr "您å¯ä»¥ %{linkStart}查看BLOB%{linkEnd} 。"
@@ -8035,9 +9138,6 @@ msgstr "您也å¯ä»¥å¾žæŒ‡ä»¤æ–°å¢žä¸€å€‹å°ˆæ¡ˆã€‚"
msgid "You can also star a label to make it a priority label."
msgstr "您還å¯ä»¥ç‚ºæŸå€‹æ¨™ç±¤åŠ ä¸Šæ˜Ÿæ˜Ÿï¼Œä½¿å…¶æˆç‚ºå„ªå…ˆæ¨™ç±¤ã€‚"
-msgid "You can also test your .gitlab-ci.yml in the %{linkStart}Lint%{linkEnd}"
-msgstr "您也å¯ä»¥åœ¨ %{linkStart}Lint%{linkEnd} 測試您的 .gitlab-ci.yml"
-
msgid "You can easily contribute to them by requesting to join these groups."
msgstr ""
@@ -8059,12 +9159,18 @@ msgstr "您å¯ä»¥é€éŽä½¿ç”¨äº’動模å¼é¸æ“‡ %{use_ours} 或 %{use_theirs} æŒ
msgid "You can set up jobs to only use Runners with specific tags. Separate tags with commas."
msgstr ""
+msgid "You can test your .gitlab-ci.yml in %{linkStart}CI Lint%{linkEnd}."
+msgstr ""
+
msgid "You cannot write to a read-only secondary GitLab Geo instance. Please use %{link_to_primary_node} instead."
msgstr "您ä¸èƒ½å¯«å…¥åˆ°å”¯è®€çš„æ¬¡è¦ GitLab Geo 主機。請改用 %{link_to_primary_node}。"
msgid "You cannot write to this read-only GitLab instance."
msgstr "您ä¸èƒ½ä¿®æ”¹é€™å€‹å”¯è®€çš„ GitLab 主機。"
+msgid "You do not have any subscriptions yet"
+msgstr ""
+
msgid "You do not have the correct permissions to override the settings from the LDAP group sync."
msgstr "您沒有權é™ä¾†è¦†è“‹ LDAP 群組åŒæ­¥è¨­å®šã€‚"
@@ -8086,9 +9192,6 @@ msgstr "您必須接å—我們的æœå‹™æ¢æ¬¾å’Œéš±ç§æ”¿ç­–æ‰èƒ½è¨»å†Šå¸³æˆ¶"
msgid "You must have maintainer access to force delete a lock"
msgstr "您必須æ“有維護者存å–æ‰èƒ½å¼·åˆ¶ç§»é™¤éŽ–定"
-msgid "You must sign in to star a project"
-msgstr "必須登入æ‰èƒ½æ”¶è—專案"
-
msgid "You need a different license to enable FileLocks feature"
msgstr "您需è¦ä½¿ç”¨ä¸åŒçš„授權以啟用 FileLocks 功能"
@@ -8098,6 +9201,12 @@ msgstr "æ‚¨éœ€è¦ git-lfs 版本 %{min_git_lfs_version} (或更高版本) æ‰èƒ½
msgid "You need permission."
msgstr "需è¦æ¬Šé™æ‰èƒ½é€™éº¼åšã€‚"
+msgid "You will loose all changes you've made to this file. This action cannot be undone."
+msgstr ""
+
+msgid "You will loose all the unstaged changes you've made in this project. This action cannot be undone."
+msgstr ""
+
msgid "You will not get any notifications via email"
msgstr "ä¸æœƒæ”¶åˆ°ä»»ä½•é€šçŸ¥éƒµä»¶"
@@ -8164,6 +9273,9 @@ msgstr "你的更改將å¯ä»¥æ交到 %{branch_name} 因為åˆä½µè«‹æ±‚已打é–
msgid "Your changes have been committed. Commit %{commitId} %{commitStats}"
msgstr "您的更改已被æ交。更動紀錄 %{commitId} %{commitStats}"
+msgid "Your changes have been saved"
+msgstr ""
+
msgid "Your comment will not be visible to the public."
msgstr "你的留言將ä¸æœƒè¢«å…¬é–‹ã€‚"
@@ -8185,14 +9297,6 @@ msgstr "之å‰"
msgid "among other things"
msgstr "除了其他事情"
-msgid "and %d fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] ""
-
-msgid "and 1 fixed vulnerability"
-msgid_plural "and %d fixed vulnerabilities"
-msgstr[0] "å’Œ %d 個已經修復的æ¼æ´ž"
-
msgid "assign yourself"
msgstr "指派給自己"
@@ -8220,20 +9324,51 @@ msgstr "%{namespace} 被 %{vulnerability} 影響"
msgid "ciReport|%{remainingPackagesCount} more"
msgstr "%{remainingPackagesCount} 更多"
-msgid "ciReport|%{reportName} is loading"
-msgstr "正在載入 %{reportName}"
+msgid "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{fixedCount} fixed vulnerabilities"
+msgstr[0] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new vulnerability"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} new vulnerabilities"
+msgstr[0] ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} new, and %{fixedCount} fixed vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected %{newCount} vulnerability for the source branch only"
+msgid_plural "ciReport|%{reportType} %{status} detected %{newCount} vulnerabilities for the source branch only"
+msgstr[0] ""
+
+msgid "ciReport|%{reportType} %{status} detected no new vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities"
+msgstr ""
+
+msgid "ciReport|%{reportType} %{status} detected no vulnerabilities for the source branch only"
+msgstr ""
-msgid "ciReport|%{reportName} resulted in error while loading results"
-msgstr "載入çµæžœæ™‚å›  %{reportName} 而導致錯誤"
+msgid "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerability"
+msgid_plural "ciReport|%{reportType} detected %{vulnerabilityCount} vulnerabilities"
+msgstr[0] ""
-msgid "ciReport|%{type} detected no new security vulnerabilities"
-msgstr "%{type} 未åµæ¸¬åˆ°æ–°çš„安全性æ¼æ´ž"
+msgid "ciReport|%{reportType} detected no vulnerabilities"
+msgstr ""
-msgid "ciReport|%{type} detected no security vulnerabilities"
-msgstr "%{type} 未åµæ¸¬åˆ°å®‰å…¨æ€§æ¼æ´ž"
+msgid "ciReport|%{reportType} is loading"
+msgstr ""
-msgid "ciReport|%{type} detected no vulnerabilities"
-msgstr "%{type} 未åµæ¸¬åˆ°æ¼æ´ž"
+msgid "ciReport|%{reportType}: Loading resulted in an error"
+msgstr ""
+
+msgid "ciReport|(errors when loading results)"
+msgstr ""
+
+msgid "ciReport|(is loading)"
+msgstr ""
+
+msgid "ciReport|(is loading, errors when loading results)"
+msgstr ""
msgid "ciReport|Class"
msgstr "類別"
@@ -8244,38 +9379,20 @@ msgstr "程å¼ç¢¼å“質"
msgid "ciReport|Confidence"
msgstr "ä¿¡ä»»"
-msgid "ciReport|Container scanning detected"
-msgstr "åµæ¸¬åˆ°å®¹å™¨æŽƒæ"
+msgid "ciReport|Container scanning"
+msgstr ""
msgid "ciReport|Container scanning detects known vulnerabilities in your docker images."
msgstr "容器掃æåµæ¸¬åœ¨æ‚¨çš„ Docker 映åƒä¸­çš„已知æ¼æ´žã€‚"
-msgid "ciReport|Container scanning is loading"
-msgstr "正在載入容器掃æ"
-
-msgid "ciReport|Container scanning resulted in error while loading results"
-msgstr "當載入çµæžœæ™‚,因容器掃æ而導致錯誤"
-
-msgid "ciReport|DAST detected"
-msgstr "åµæ¸¬åˆ° DAST"
-
-msgid "ciReport|DAST is loading"
-msgstr "正在載入 DAST"
-
-msgid "ciReport|DAST resulted in error while loading results"
-msgstr "載入çµæžœæ™‚,因 DAST 而導致錯誤"
+msgid "ciReport|DAST"
+msgstr ""
msgid "ciReport|Dependency Scanning detects known vulnerabilities in your source code's dependencies."
msgstr ""
-msgid "ciReport|Dependency scanning detected"
-msgstr "åµæ¸¬åˆ°ç›¸ä¾æ€§æŽƒæ"
-
-msgid "ciReport|Dependency scanning is loading"
-msgstr "正在載入相ä¾æ€§æŽƒæ"
-
-msgid "ciReport|Dependency scanning resulted in error while loading results"
-msgstr "當載入çµæžœæ™‚因相ä¾æ€§æŽƒæ而導致錯誤"
+msgid "ciReport|Dependency scanning"
+msgstr ""
msgid "ciReport|Description"
msgstr "說明"
@@ -8307,9 +9424,6 @@ msgstr "實例"
msgid "ciReport|Learn more about interacting with security reports (Alpha)."
msgstr "了解關於和安全性報告 (Alpha) 互動的更多資訊。"
-msgid "ciReport|Learn more about whitelisting"
-msgstr "了解關於白å單的更多資訊"
-
msgid "ciReport|License management detected %d license for the source branch only"
msgid_plural "ciReport|License management detected %d licenses for the source branch only"
msgstr[0] ""
@@ -8330,6 +9444,9 @@ msgstr "連çµ"
msgid "ciReport|Loading %{reportName} report"
msgstr "正在載入 %{reportName} 報告"
+msgid "ciReport|Manage licenses"
+msgstr ""
+
msgid "ciReport|Method"
msgstr "方法"
@@ -8348,14 +9465,8 @@ msgstr "效能指標"
msgid "ciReport|Revert dismissal"
msgstr "撤回忽略"
-msgid "ciReport|SAST detected"
-msgstr "åµæ¸¬åˆ° SAST"
-
-msgid "ciReport|SAST is loading"
-msgstr "正在載入 SAST"
-
-msgid "ciReport|SAST resulted in error while loading results"
-msgstr "當載入çµæžœæ™‚,因 SAST 而導致錯誤"
+msgid "ciReport|SAST"
+msgstr ""
msgid "ciReport|Security scanning"
msgstr "安全性掃æ"
@@ -8363,9 +9474,6 @@ msgstr "安全性掃æ"
msgid "ciReport|Security scanning failed loading any results"
msgstr "安全性掃æ無法載入任何çµæžœ"
-msgid "ciReport|Security scanning is loading"
-msgstr "正在載入安全掃æ"
-
msgid "ciReport|Severity"
msgstr "åš´é‡æ€§"
@@ -8396,9 +9504,6 @@ msgstr "載入相ä¾æ€§æŽƒæ報告時發生錯誤。"
msgid "ciReport|There was an error reverting the dismissal. Please try again."
msgstr "撤回é§å›žæ™‚發生錯誤。請é‡è©¦ã€‚"
-msgid "ciReport|Unapproved vulnerabilities (red) can be marked as approved."
-msgstr "未批准的æ¼æ´ž (紅色) å¯ä»¥æ¨™è¨˜ç‚ºå·²æ‰¹å‡†ã€‚"
-
msgid "ciReport|Upgrade %{name} from %{version} to %{fixed}."
msgstr "å°‡ %{name} 從 %{version} å‡ç´šåˆ° %{fixed}。"
@@ -8409,9 +9514,6 @@ msgstr[0] ""
msgid "ciReport|View full report"
msgstr ""
-msgid "ciReport|no vulnerabilities"
-msgstr "沒有æ¼æ´ž"
-
msgid "ciReport|on pipeline"
msgstr "æµæ°´ç·šä¸Š"
@@ -8440,23 +9542,16 @@ msgstr[0] "æ—¥"
msgid "deploy token"
msgstr "部署憑證"
-msgid "detected %d fixed vulnerability"
-msgid_plural "detected %d fixed vulnerabilities"
-msgstr[0] "åµæ¸¬åˆ° %d 個已修復æ¼æ´ž"
-
-msgid "detected %d new vulnerability"
-msgid_plural "detected %d new vulnerabilities"
-msgstr[0] "åµæ¸¬åˆ° %d 個新æ¼æ´ž"
-
-msgid "detected no vulnerabilities"
-msgstr "未åµæ¸¬åˆ°æ¼æ´ž"
-
msgid "disabled"
msgstr "å·²åœç”¨"
msgid "done"
msgstr ""
+msgid "draft"
+msgid_plural "drafts"
+msgstr[0] ""
+
msgid "enabled"
msgstr "已啟用"
@@ -8466,6 +9561,12 @@ msgstr "%{slash_command} 將更新é ä¼°èŠ±è²»æ™‚間。"
msgid "for this project"
msgstr "為此專案"
+msgid "from"
+msgstr ""
+
+msgid "help"
+msgstr ""
+
msgid "here"
msgstr "這裡"
@@ -8494,6 +9595,9 @@ msgstr "éžæœ‰æ•ˆ X509 憑證。"
msgid "issue boards"
msgstr ""
+msgid "latest deployment"
+msgstr ""
+
msgid "latest version"
msgstr "最新版本"
@@ -8719,6 +9823,9 @@ msgstr "æ­¤åˆä½µè«‹æ±‚正在被åˆä½µ"
msgid "mrWidget|This project is archived, write access has been disabled"
msgstr "這個專案已經被打包,無法寫入"
+msgid "mrWidget|You are not allowed to edit this project directly. Please fork to make changes."
+msgstr ""
+
msgid "mrWidget|You can merge this merge request manually using the"
msgstr "ä½ å¯ä»¥æ‰‹å‹•åˆä½µé€™å€‹åˆä½µè«‹æ±‚,藉由"
@@ -8737,6 +9844,9 @@ msgstr "進入"
msgid "mrWidget|to be merged automatically when the pipeline succeeds"
msgstr "當æµæ°´ç·šå®Œæˆæ™‚將會被自動åˆä½µ"
+msgid "n/a"
+msgstr ""
+
msgid "new merge request"
msgstr "建立åˆä½µè«‹æ±‚"
@@ -8763,6 +9873,10 @@ msgstr "ç§äººå­˜å–憑證"
msgid "private key does not match certificate."
msgstr "ç§é‘°ä¸ç¬¦åˆæ†‘證。"
+msgid "project"
+msgid_plural "projects"
+msgstr[0] ""
+
msgid "remaining"
msgstr "剩餘"
@@ -8775,6 +9889,10 @@ msgstr "刪除截止日期"
msgid "remove weight"
msgstr "移除權é‡"
+msgid "reply"
+msgid_plural "replies"
+msgstr[0] ""
+
msgid "source"
msgstr "來æº"
@@ -8790,6 +9908,9 @@ msgstr "這份文件"
msgid "to help your contributors communicate effectively!"
msgstr "å”助你的貢ç»è€…進行有效的æºé€šï¼"
+msgid "toggle collapse"
+msgstr ""
+
msgid "username"
msgstr "使用者å稱"
diff --git a/package.json b/package.json
index 4a479b6fb2a..520d7c620c2 100644
--- a/package.json
+++ b/package.json
@@ -10,7 +10,7 @@
"karma-coverage": "BABEL_ENV=coverage karma start --single-run true config/karma.config.js",
"karma-start": "BABEL_ENV=karma karma start config/karma.config.js",
"postinstall": "node ./scripts/frontend/postinstall.js",
- "prettier-staged": "node ./scripts/frontend/prettier.js",
+ "prettier-staged": "node ./scripts/frontend/prettier.js check",
"prettier-staged-save": "node ./scripts/frontend/prettier.js save",
"prettier-all": "node ./scripts/frontend/prettier.js check-all",
"prettier-all-save": "node ./scripts/frontend/prettier.js save-all",
@@ -18,28 +18,31 @@
"webpack-prod": "NODE_ENV=production webpack --config config/webpack.config.js"
},
"dependencies": {
- "@gitlab-org/gitlab-svgs": "^1.29.0",
- "@gitlab-org/gitlab-ui": "^1.5.0",
+ "@babel/core": "^7.1.2",
+ "@babel/plugin-proposal-class-properties": "^7.1.0",
+ "@babel/plugin-proposal-json-strings": "^7.0.0",
+ "@babel/plugin-syntax-dynamic-import": "^7.0.0",
+ "@babel/plugin-syntax-import-meta": "^7.0.0",
+ "@babel/preset-env": "^7.1.0",
+ "@gitlab/svgs": "^1.40.0",
+ "@gitlab/ui": "^1.11.0",
+ "apollo-boost": "^0.1.20",
+ "apollo-client": "^2.4.5",
"autosize": "^4.0.0",
"axios": "^0.17.1",
- "babel-core": "^6.26.3",
- "babel-loader": "^7.1.5",
- "babel-plugin-transform-define": "^1.3.0",
- "babel-preset-latest": "^6.24.1",
- "babel-preset-stage-2": "^6.24.1",
- "blackst0ne-mermaid": "^7.1.0-fixed",
- "bootstrap": "4.1.1",
+ "babel-loader": "^8.0.4",
+ "bootstrap": "4.1.3",
"brace-expansion": "^1.1.8",
"cache-loader": "^1.2.2",
"chart.js": "1.0.2",
"classlist-polyfill": "^1.2.0",
"clipboard": "^1.7.1",
- "codesandbox-api": "^0.0.18",
- "compression-webpack-plugin": "^1.1.11",
+ "codesandbox-api": "^0.0.20",
+ "compression-webpack-plugin": "^2.0.0",
"core-js": "^2.4.1",
"cropper": "^2.3.0",
"css-loader": "^1.0.0",
- "d3": "4.12.2",
+ "d3": "^4.13.0",
"d3-array": "^1.2.1",
"d3-axis": "^1.0.8",
"d3-brush": "^1.0.4",
@@ -55,10 +58,11 @@
"dropzone": "^4.2.0",
"emoji-unicode-version": "^0.2.1",
"exports-loader": "^0.7.0",
- "file-loader": "^1.1.11",
+ "file-loader": "^2.0.0",
"formdata-polyfill": "^3.0.11",
"fuzzaldrin-plus": "^0.5.0",
"glob": "^7.1.2",
+ "graphql": "^14.0.2",
"imports-loader": "^0.8.0",
"jed": "^1.1.1",
"jquery": "^3.2.1",
@@ -69,8 +73,9 @@
"jszip-utils": "^0.0.2",
"katex": "^0.9.0",
"marked": "^0.3.12",
+ "mermaid": "^8.0.0-rc.8",
"monaco-editor": "^0.14.3",
- "monaco-editor-webpack-plugin": "^1.5.2",
+ "monaco-editor-webpack-plugin": "^1.5.4",
"mousetrap": "^1.4.6",
"pikaday": "^1.6.1",
"popper.js": "^1.14.3",
@@ -81,68 +86,66 @@
"sanitize-html": "^1.16.1",
"select2": "3.5.2-browserify",
"sha1": "^1.1.1",
- "smooshpack": "^0.0.48",
+ "smooshpack": "^0.0.53",
"sortablejs": "^1.7.0",
"sql.js": "^0.4.0",
"stickyfilljs": "^2.0.5",
- "style-loader": "^0.21.0",
+ "style-loader": "^0.23.0",
"svg4everybody": "2.1.9",
"three": "^0.84.0",
"three-orbit-controls": "^82.1.0",
"three-stl-loader": "^1.0.4",
"timeago.js": "^3.0.2",
"underscore": "^1.9.0",
- "url-loader": "^1.0.1",
+ "url-loader": "^1.1.1",
"visibilityjs": "^1.2.4",
- "vue": "^2.5.16",
- "vue-loader": "^15.2.4",
+ "vue": "^2.5.17",
+ "vue-apollo": "^3.0.0-beta.25",
+ "vue-loader": "^15.4.2",
"vue-resource": "^1.5.0",
"vue-router": "^3.0.1",
- "vue-template-compiler": "^2.5.16",
+ "vue-template-compiler": "^2.5.17",
"vue-virtual-scroll-list": "^1.2.5",
"vuex": "^3.0.1",
- "webpack": "^4.16.0",
- "webpack-bundle-analyzer": "^2.13.1",
- "webpack-cli": "^3.0.8",
+ "webpack": "^4.19.1",
+ "webpack-bundle-analyzer": "^3.0.2",
+ "webpack-cli": "^3.1.0",
"webpack-stats-plugin": "^0.2.1",
"worker-loader": "^2.0.0",
"xterm": "^3.5.0"
},
"devDependencies": {
+ "@gitlab/eslint-config": "^1.2.0",
+ "@vue/test-utils": "^1.0.0-beta.25",
"axios-mock-adapter": "^1.15.0",
- "babel-eslint": "^8.2.3",
- "babel-plugin-istanbul": "^4.1.6",
- "babel-plugin-rewire": "^1.1.0",
+ "babel-plugin-istanbul": "^5.1.0",
+ "babel-plugin-rewire": "^1.2.0",
"babel-template": "^6.26.0",
"babel-types": "^6.26.0",
"chalk": "^2.4.1",
- "commander": "^2.15.1",
- "eslint": "~4.12.1",
- "eslint-config-airbnb-base": "^12.1.0",
- "eslint-import-resolver-webpack": "^0.10.0",
- "eslint-plugin-filenames": "^1.2.0",
- "eslint-plugin-html": "4.0.3",
- "eslint-plugin-import": "^2.12.0",
- "eslint-plugin-jasmine": "^2.1.0",
- "eslint-plugin-promise": "^3.8.0",
- "eslint-plugin-vue": "^4.5.0",
+ "commander": "^2.18.0",
+ "eslint": "~5.6.0",
+ "eslint-import-resolver-webpack": "^0.10.1",
+ "eslint-plugin-html": "4.0.5",
+ "eslint-plugin-import": "^2.14.0",
+ "eslint-plugin-jasmine": "^2.10.1",
"gettext-extractor": "^3.3.2",
"gettext-extractor-vue": "^4.0.1",
- "ignore": "^3.3.7",
+ "graphql-tag": "^2.10.0",
"istanbul": "^0.4.5",
"jasmine-core": "^2.9.0",
"jasmine-diff": "^0.1.3",
"jasmine-jquery": "^2.1.1",
"karma": "^3.0.0",
"karma-chrome-launcher": "^2.2.0",
- "karma-coverage-istanbul-reporter": "^1.4.2",
+ "karma-coverage-istanbul-reporter": "^2.0.4",
"karma-jasmine": "^1.1.2",
"karma-junit-reporter": "^1.2.0",
"karma-mocha-reporter": "^2.2.5",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^4.0.0-beta.0",
- "nodemon": "^1.18.2",
- "prettier": "1.12.1",
- "webpack-dev-server": "^3.1.4"
+ "nodemon": "^1.18.4",
+ "prettier": "1.15.2",
+ "webpack-dev-server": "^3.1.10"
}
}
diff --git a/public/robots.txt b/public/robots.txt
index ea931e1a223..7908297564e 100644
--- a/public/robots.txt
+++ b/public/robots.txt
@@ -70,3 +70,5 @@ Disallow: /*/*/hooks
Disallow: /*/*/services
Disallow: /*/*/protected_branches
Disallow: /*/*/uploads/
+Disallow: /*/-/group_members
+Disallow: /*/project_members
diff --git a/qa/Dockerfile b/qa/Dockerfile
index abf2184e1e2..9956ced0ef6 100644
--- a/qa/Dockerfile
+++ b/qa/Dockerfile
@@ -3,10 +3,20 @@ LABEL maintainer "Grzegorz Bizon <grzegorz@gitlab.com>"
ENV DEBIAN_FRONTEND noninteractive
##
+# Add support for stretch-backports
+#
+RUN echo "deb http://ftp.debian.org/debian stretch-backports main" >> /etc/apt/sources.list
+
+##
# Update APT sources and install some dependencies
#
RUN sed -i "s/httpredir.debian.org/ftp.us.debian.org/" /etc/apt/sources.list
-RUN apt-get update && apt-get install -y wget git unzip xvfb
+RUN apt-get update && apt-get install -y wget unzip xvfb
+
+##
+# Install some packages from backports
+#
+RUN apt-get -y -t stretch-backports install git git-lfs
##
# Install Docker
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index 8d28fcacc05..d61ecf8fbb5 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -56,7 +56,7 @@ GEM
byebug (~> 9.1)
pry (~> 0.10)
public_suffix (3.0.1)
- rack (2.0.3)
+ rack (2.0.6)
rack-test (0.8.2)
rack (>= 1.0, < 3)
rake (12.3.0)
@@ -103,4 +103,4 @@ DEPENDENCIES
selenium-webdriver (~> 3.8.0)
BUNDLED WITH
- 1.16.4
+ 1.17.1
diff --git a/qa/README.md b/qa/README.md
index 746bd5cf94b..08ba59e117d 100644
--- a/qa/README.md
+++ b/qa/README.md
@@ -80,6 +80,15 @@ GITLAB_USERNAME=jsmith GITLAB_PASSWORD=password GITLAB_SANDBOX_NAME=jsmith-qa-sa
All [supported environment variables are here](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#supported-environment-variables).
+### Sending additional cookies
+
+The environment variable `QA_COOKIES` can be set to send additional cookies
+on every request. This is necessary on gitlab.com to direct traffic to the
+canary fleet. To do this set `QA_COOKIES="gitlab_canary=true"`.
+
+To set multiple cookies, separate them with the `;` character, for example: `QA_COOKIES="cookie1=value;cookie2=value2"`
+
+
### Building a Docker image to test
Once you have made changes to the CE/EE repositories, you may want to build a
diff --git a/qa/qa.rb b/qa/qa.rb
index 952084085d5..aa0b78b37e8 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -16,6 +16,9 @@ module QA
autoload :Browser, 'qa/runtime/browser'
autoload :Env, 'qa/runtime/env'
autoload :Address, 'qa/runtime/address'
+ autoload :Path, 'qa/runtime/path'
+ autoload :Fixtures, 'qa/runtime/fixtures'
+ autoload :Logger, 'qa/runtime/logger'
module API
autoload :Client, 'qa/runtime/api/client'
@@ -33,41 +36,40 @@ module QA
##
# GitLab QA fabrication mechanisms
#
- module Factory
- autoload :Base, 'qa/factory/base'
- autoload :Dependency, 'qa/factory/dependency'
- autoload :Product, 'qa/factory/product'
-
- module Resource
- autoload :Sandbox, 'qa/factory/resource/sandbox'
- autoload :Group, 'qa/factory/resource/group'
- autoload :Issue, 'qa/factory/resource/issue'
- autoload :Project, 'qa/factory/resource/project'
- autoload :MergeRequest, 'qa/factory/resource/merge_request'
- autoload :ProjectImportedFromGithub, 'qa/factory/resource/project_imported_from_github'
- autoload :MergeRequestFromFork, 'qa/factory/resource/merge_request_from_fork'
- autoload :DeployKey, 'qa/factory/resource/deploy_key'
- autoload :Branch, 'qa/factory/resource/branch'
- autoload :SecretVariable, 'qa/factory/resource/secret_variable'
- autoload :Runner, 'qa/factory/resource/runner'
- autoload :PersonalAccessToken, 'qa/factory/resource/personal_access_token'
- autoload :KubernetesCluster, 'qa/factory/resource/kubernetes_cluster'
- autoload :User, 'qa/factory/resource/user'
- autoload :ProjectMilestone, 'qa/factory/resource/project_milestone'
- autoload :Wiki, 'qa/factory/resource/wiki'
- autoload :File, 'qa/factory/resource/file'
- autoload :Fork, 'qa/factory/resource/fork'
- autoload :SSHKey, 'qa/factory/resource/ssh_key'
- end
+ module Resource
+ autoload :ApiFabricator, 'qa/resource/api_fabricator'
+ autoload :Base, 'qa/resource/base'
+
+ autoload :Sandbox, 'qa/resource/sandbox'
+ autoload :Group, 'qa/resource/group'
+ autoload :Issue, 'qa/resource/issue'
+ autoload :Project, 'qa/resource/project'
+ autoload :Label, 'qa/resource/label'
+ autoload :MergeRequest, 'qa/resource/merge_request'
+ autoload :ProjectImportedFromGithub, 'qa/resource/project_imported_from_github'
+ autoload :MergeRequestFromFork, 'qa/resource/merge_request_from_fork'
+ autoload :DeployKey, 'qa/resource/deploy_key'
+ autoload :DeployToken, 'qa/resource/deploy_token'
+ autoload :Branch, 'qa/resource/branch'
+ autoload :CiVariable, 'qa/resource/ci_variable'
+ autoload :Runner, 'qa/resource/runner'
+ autoload :PersonalAccessToken, 'qa/resource/personal_access_token'
+ autoload :KubernetesCluster, 'qa/resource/kubernetes_cluster'
+ autoload :User, 'qa/resource/user'
+ autoload :ProjectMilestone, 'qa/resource/project_milestone'
+ autoload :Wiki, 'qa/resource/wiki'
+ autoload :File, 'qa/resource/file'
+ autoload :Fork, 'qa/resource/fork'
+ autoload :SSHKey, 'qa/resource/ssh_key'
module Repository
- autoload :Push, 'qa/factory/repository/push'
- autoload :ProjectPush, 'qa/factory/repository/project_push'
- autoload :WikiPush, 'qa/factory/repository/wiki_push'
+ autoload :Push, 'qa/resource/repository/push'
+ autoload :ProjectPush, 'qa/resource/repository/project_push'
+ autoload :WikiPush, 'qa/resource/repository/wiki_push'
end
module Settings
- autoload :HashedStorage, 'qa/factory/settings/hashed_storage'
+ autoload :HashedStorage, 'qa/resource/settings/hashed_storage'
end
end
@@ -94,7 +96,9 @@ module QA
module Integration
autoload :Github, 'qa/scenario/test/integration/github'
- autoload :LDAP, 'qa/scenario/test/integration/ldap'
+ autoload :LDAPNoTLS, 'qa/scenario/test/integration/ldap_no_tls'
+ autoload :LDAPTLS, 'qa/scenario/test/integration/ldap_tls'
+ autoload :InstanceSAML, 'qa/scenario/test/integration/instance_saml'
autoload :Kubernetes, 'qa/scenario/test/integration/kubernetes'
autoload :Mattermost, 'qa/scenario/test/integration/mattermost'
autoload :ObjectStorage, 'qa/scenario/test/integration/object_storage'
@@ -120,6 +124,7 @@ module QA
module Main
autoload :Login, 'qa/page/main/login'
+ autoload :Menu, 'qa/page/main/menu'
autoload :OAuth, 'qa/page/main/oauth'
autoload :SignUp, 'qa/page/main/sign_up'
end
@@ -128,13 +133,6 @@ module QA
autoload :Common, 'qa/page/settings/common'
end
- module Menu
- autoload :Main, 'qa/page/menu/main'
- autoload :Side, 'qa/page/menu/side'
- autoload :Admin, 'qa/page/menu/admin'
- autoload :Profile, 'qa/page/menu/profile'
- end
-
module Dashboard
autoload :Projects, 'qa/page/dashboard/projects'
autoload :Groups, 'qa/page/dashboard/groups'
@@ -158,6 +156,7 @@ module QA
autoload :New, 'qa/page/project/new'
autoload :Show, 'qa/page/project/show'
autoload :Activity, 'qa/page/project/activity'
+ autoload :Menu, 'qa/page/project/menu'
module Import
autoload :Github, 'qa/page/project/import/github'
@@ -179,10 +178,12 @@ module QA
autoload :Repository, 'qa/page/project/settings/repository'
autoload :CICD, 'qa/page/project/settings/ci_cd'
autoload :DeployKeys, 'qa/page/project/settings/deploy_keys'
+ autoload :DeployTokens, 'qa/page/project/settings/deploy_tokens'
autoload :ProtectedBranches, 'qa/page/project/settings/protected_branches'
- autoload :SecretVariables, 'qa/page/project/settings/secret_variables'
+ autoload :CiVariables, 'qa/page/project/settings/ci_variables'
autoload :Runners, 'qa/page/project/settings/runners'
autoload :MergeRequest, 'qa/page/project/settings/merge_request'
+ autoload :Members, 'qa/page/project/settings/members'
end
module Issue
@@ -201,6 +202,11 @@ module QA
end
module Operations
+ module Environments
+ autoload :Index, 'qa/page/project/operations/environments/index'
+ autoload :Show, 'qa/page/project/operations/environments/show'
+ end
+
module Kubernetes
autoload :Index, 'qa/page/project/operations/kubernetes/index'
autoload :Add, 'qa/page/project/operations/kubernetes/add'
@@ -214,9 +220,14 @@ module QA
autoload :New, 'qa/page/project/wiki/new'
autoload :Show, 'qa/page/project/wiki/show'
end
+
+ module WebIDE
+ autoload :Edit, 'qa/page/project/web_ide/edit'
+ end
end
module Profile
+ autoload :Menu, 'qa/page/profile/menu'
autoload :PersonalAccessTokens, 'qa/page/profile/personal_access_tokens'
autoload :SSHKeys, 'qa/page/profile/ssh_keys'
end
@@ -229,15 +240,25 @@ module QA
autoload :Banner, 'qa/page/layout/banner'
end
+ module Label
+ autoload :New, 'qa/page/label/new'
+ autoload :Index, 'qa/page/label/index'
+ end
+
module MergeRequest
autoload :New, 'qa/page/merge_request/new'
autoload :Show, 'qa/page/merge_request/show'
end
module Admin
+ autoload :Menu, 'qa/page/admin/menu'
+
module Settings
- autoload :RepositoryStorage, 'qa/page/admin/settings/repository_storage'
- autoload :Main, 'qa/page/admin/settings/main'
+ autoload :Repository, 'qa/page/admin/settings/repository'
+
+ module Component
+ autoload :RepositoryStorage, 'qa/page/admin/settings/component/repository_storage'
+ end
end
end
@@ -254,6 +275,12 @@ module QA
autoload :Dropzone, 'qa/page/component/dropzone'
autoload :GroupsFilter, 'qa/page/component/groups_filter'
autoload :Select2, 'qa/page/component/select2'
+ autoload :DropdownFilter, 'qa/page/component/dropdown_filter'
+ autoload :UsersSelect, 'qa/page/component/users_select'
+
+ module Issuable
+ autoload :Common, 'qa/page/component/issuable/common'
+ end
end
end
@@ -283,6 +310,27 @@ module QA
autoload :Config, 'qa/specs/config'
autoload :Runner, 'qa/specs/runner'
end
+
+ ##
+ # Classes that describe the structure of vendor/third party application pages
+ #
+ module Vendor
+ module SAMLIdp
+ module Page
+ autoload :Base, 'qa/vendor/saml_idp/page/base'
+ autoload :Login, 'qa/vendor/saml_idp/page/login'
+ end
+ end
+ end
+
+ # Classes that provide support to other parts of the framework.
+ #
+ module Support
+ module Page
+ autoload :Logging, 'qa/support/page/logging'
+ end
+ autoload :Api, 'qa/support/api'
+ end
end
QA::Runtime::Release.extend_autoloads!
diff --git a/qa/qa/factory/base.rb b/qa/qa/factory/base.rb
deleted file mode 100644
index 7a532ce534b..00000000000
--- a/qa/qa/factory/base.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-require 'forwardable'
-
-module QA
- module Factory
- class Base
- extend SingleForwardable
-
- def_delegators :evaluator, :dependency, :dependencies
- def_delegators :evaluator, :product, :attributes
-
- def fabricate!(*_args)
- raise NotImplementedError
- end
-
- def self.fabricate!(*args)
- new.tap do |factory|
- yield factory if block_given?
-
- dependencies.each do |name, signature|
- Factory::Dependency.new(name, factory, signature).build!
- end
-
- factory.fabricate!(*args)
-
- break Factory::Product.populate!(factory)
- end
- end
-
- def self.evaluator
- @evaluator ||= Factory::Base::DSL.new(self)
- end
-
- class DSL
- attr_reader :dependencies, :attributes
-
- def initialize(base)
- @base = base
- @dependencies = {}
- @attributes = {}
- end
-
- def dependency(factory, as:, &block)
- as.tap do |name|
- @base.class_eval { attr_accessor name }
-
- Dependency::Signature.new(factory, block).tap do |signature|
- @dependencies.store(name, signature)
- end
- end
- end
-
- def product(attribute, &block)
- Product::Attribute.new(attribute, block).tap do |signature|
- @attributes.store(attribute, signature)
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/dependency.rb b/qa/qa/factory/dependency.rb
deleted file mode 100644
index fc5dc82ce29..00000000000
--- a/qa/qa/factory/dependency.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-module QA
- module Factory
- class Dependency
- Signature = Struct.new(:factory, :block)
-
- def initialize(name, factory, signature)
- @name = name
- @factory = factory
- @signature = signature
- end
-
- def overridden?
- !!@factory.public_send(@name)
- end
-
- def build!
- return if overridden?
-
- Builder.new(@signature, @factory).fabricate!.tap do |product|
- @factory.public_send("#{@name}=", product)
- end
- end
-
- class Builder
- def initialize(signature, caller_factory)
- @factory = signature.factory
- @block = signature.block
- @caller_factory = caller_factory
- end
-
- def fabricate!
- @factory.fabricate! do |factory|
- @block&.call(factory, @caller_factory)
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/product.rb b/qa/qa/factory/product.rb
deleted file mode 100644
index 996b7f14f61..00000000000
--- a/qa/qa/factory/product.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-require 'capybara/dsl'
-
-module QA
- module Factory
- class Product
- include Capybara::DSL
-
- Attribute = Struct.new(:name, :block)
-
- def initialize
- @location = current_url
- end
-
- def visit!
- visit @location
- end
-
- def self.populate!(factory)
- new.tap do |product|
- factory.class.attributes.each_value do |attribute|
- product.instance_exec(factory, attribute.block) do |factory, block|
- value = block.call(factory)
- product.define_singleton_method(attribute.name) { value }
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/repository/project_push.rb b/qa/qa/factory/repository/project_push.rb
deleted file mode 100644
index 167f47c9141..00000000000
--- a/qa/qa/factory/repository/project_push.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-module QA
- module Factory
- module Repository
- class ProjectPush < Factory::Repository::Push
- dependency Factory::Resource::Project, as: :project do |project|
- project.name = 'project-with-code'
- project.description = 'Project with repository'
- end
-
- product :output do |factory|
- factory.output
- end
-
- product :project do |factory|
- factory.project
- end
-
- def initialize
- @file_name = 'file.txt'
- @file_content = '# This is test project'
- @commit_message = "This is a test commit"
- @branch_name = 'master'
- @new_branch = true
- end
-
- def repository_http_uri
- @repository_http_uri ||= begin
- project.visit!
- Page::Project::Show.act do
- choose_repository_clone_http
- repository_location.uri
- end
- end
- end
-
- def repository_ssh_uri
- @repository_ssh_uri ||= begin
- project.visit!
- Page::Project::Show.act do
- choose_repository_clone_ssh
- repository_location.uri
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/repository/push.rb b/qa/qa/factory/repository/push.rb
deleted file mode 100644
index 6c5088f1da5..00000000000
--- a/qa/qa/factory/repository/push.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-require 'pathname'
-
-module QA
- module Factory
- module Repository
- class Push < Factory::Base
- attr_accessor :file_name, :file_content, :commit_message,
- :branch_name, :new_branch, :output, :repository_http_uri,
- :repository_ssh_uri, :ssh_key, :user
-
- attr_writer :remote_branch
-
- def initialize
- @file_name = 'file.txt'
- @file_content = '# This is test file'
- @commit_message = "This is a test commit"
- @branch_name = 'master'
- @new_branch = true
- @repository_http_uri = ""
- @ssh_key = nil
- end
-
- def remote_branch
- @remote_branch ||= branch_name
- end
-
- def directory=(dir)
- raise "Must set directory as a Pathname" unless dir.is_a?(Pathname)
-
- @directory = dir
- end
-
- def fabricate!
- Git::Repository.perform do |repository|
- if ssh_key
- repository.uri = repository_ssh_uri
- repository.use_ssh_key(ssh_key)
- else
- repository.uri = repository_http_uri
- repository.use_default_credentials
- end
-
- username = 'GitLab QA'
- email = 'root@gitlab.com'
-
- if user
- repository.username = user.username
- repository.password = user.password
- username = user.name
- email = user.email
- end
-
- repository.clone
- repository.configure_identity(username, email)
-
- if new_branch
- repository.checkout_new_branch(branch_name)
- else
- repository.checkout(branch_name)
- end
-
- if @directory
- @directory.each_child do |f|
- repository.add_file(f.basename, f.read) if f.file?
- end
- else
- repository.add_file(file_name, file_content)
- end
-
- repository.commit(commit_message)
- @output = repository.push_changes("#{branch_name}:#{remote_branch}")
-
- repository.delete_ssh_key
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/repository/wiki_push.rb b/qa/qa/factory/repository/wiki_push.rb
deleted file mode 100644
index ecc6cc18c88..00000000000
--- a/qa/qa/factory/repository/wiki_push.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-module QA
- module Factory
- module Repository
- class WikiPush < Factory::Repository::Push
- dependency Factory::Resource::Wiki, as: :wiki do |wiki|
- wiki.title = 'Home'
- wiki.content = '# My First Wiki Content'
- wiki.message = 'Update home'
- end
-
- def initialize
- @file_name = 'Home.md'
- @file_content = '# Welcome to My Wiki'
- @commit_message = 'Updating Home Page'
- @branch_name = 'master'
- @new_branch = false
- end
-
- def repository_http_uri
- @repository_http_uri ||= begin
- wiki.visit!
- Page::Project::Wiki::Show.act do
- go_to_clone_repository
- choose_repository_clone_http
- repository_location.uri
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/branch.rb b/qa/qa/factory/resource/branch.rb
deleted file mode 100644
index 60539992073..00000000000
--- a/qa/qa/factory/resource/branch.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-module QA
- module Factory
- module Resource
- class Branch < Factory::Base
- attr_accessor :project, :branch_name,
- :allow_to_push, :allow_to_merge, :protected
-
- dependency Factory::Resource::Project, as: :project do |project|
- project.name = 'protected-branch-project'
- end
-
- def initialize
- @branch_name = 'test/branch'
- @allow_to_push = true
- @allow_to_merge = true
- @protected = false
- end
-
- def fabricate!
- project.visit!
-
- Factory::Repository::ProjectPush.fabricate! do |resource|
- resource.project = project
- resource.file_name = 'kick-off.txt'
- resource.commit_message = 'First commit'
- end
-
- branch = Factory::Repository::ProjectPush.fabricate! do |resource|
- resource.project = project
- resource.file_name = 'README.md'
- resource.commit_message = 'Add readme'
- resource.branch_name = 'master'
- resource.new_branch = false
- resource.remote_branch = @branch_name
- end
-
- Page::Project::Show.perform do |page|
- page.wait { page.has_content?(branch_name) }
- end
-
- # The upcoming process will make it access the Protected Branches page,
- # select the already created branch and protect it according
- # to `allow_to_push` variable.
- return branch unless @protected
-
- Page::Menu::Side.act do
- click_repository_settings
- end
-
- Page::Project::Settings::Repository.perform do |setting|
- setting.expand_protected_branches do |page|
- page.select_branch(branch_name)
-
- if allow_to_push
- page.allow_devs_and_maintainers_to_push
- else
- page.allow_no_one_to_push
- end
-
- if allow_to_merge
- page.allow_devs_and_maintainers_to_merge
- else
- page.allow_no_one_to_merge
- end
-
- page.wait(reload: false) do
- !page.first('.btn-success').disabled?
- end
-
- page.protect_branch
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/deploy_key.rb b/qa/qa/factory/resource/deploy_key.rb
deleted file mode 100644
index ea8a3ad687d..00000000000
--- a/qa/qa/factory/resource/deploy_key.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-module QA
- module Factory
- module Resource
- class DeployKey < Factory::Base
- attr_accessor :title, :key
-
- product :fingerprint do |resource|
- Page::Project::Settings::Repository.act do
- expand_deploy_keys do |key|
- key_offset = key.key_titles.index do |title|
- title.text == resource.title
- end
-
- key.key_fingerprints[key_offset].text
- end
- end
- end
-
- dependency Factory::Resource::Project, as: :project do |project|
- project.name = 'project-to-deploy'
- project.description = 'project for adding deploy key test'
- end
-
- def fabricate!
- project.visit!
-
- Page::Menu::Side.act do
- click_repository_settings
- end
-
- Page::Project::Settings::Repository.perform do |setting|
- setting.expand_deploy_keys do |page|
- page.fill_key_title(title)
- page.fill_key_value(key)
-
- page.add_key
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/file.rb b/qa/qa/factory/resource/file.rb
deleted file mode 100644
index 2016d10ddae..00000000000
--- a/qa/qa/factory/resource/file.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-module QA
- module Factory
- module Resource
- class File < Factory::Base
- attr_accessor :name,
- :content,
- :commit_message
-
- dependency Factory::Resource::Project, as: :project do |project|
- project.name = 'project-with-new-file'
- end
-
- def initialize
- @name = 'QA Test - File name'
- @content = 'QA Test - File content'
- @commit_message = 'QA Test - Commit message'
- end
-
- def fabricate!
- project.visit!
-
- Page::Project::Show.act { go_to_new_file! }
-
- Page::File::Form.perform do |page|
- page.add_name(@name)
- page.add_content(@content)
- page.add_commit_message(@commit_message)
- page.commit_changes
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/fork.rb b/qa/qa/factory/resource/fork.rb
deleted file mode 100644
index 01969c31438..00000000000
--- a/qa/qa/factory/resource/fork.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-module QA
- module Factory
- module Resource
- class Fork < Factory::Base
- dependency Factory::Repository::ProjectPush, as: :push
-
- dependency Factory::Resource::User, as: :user do |user|
- if Runtime::Env.forker?
- user.username = Runtime::Env.forker_username
- user.password = Runtime::Env.forker_password
- end
- end
-
- product(:user) { |factory| factory.user }
-
- def fabricate!
- push.project.visit!
- Page::Project::Show.act { fork_project }
-
- Page::Project::Fork::New.perform do |fork_new|
- fork_new.choose_namespace(user.name)
- end
-
- Page::Layout::Banner.act { has_notice?('The project was successfully forked.') }
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/group.rb b/qa/qa/factory/resource/group.rb
deleted file mode 100644
index 033fc48c08f..00000000000
--- a/qa/qa/factory/resource/group.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-module QA
- module Factory
- module Resource
- class Group < Factory::Base
- attr_accessor :path, :description
-
- dependency Factory::Resource::Sandbox, as: :sandbox
-
- def initialize
- @path = Runtime::Namespace.name
- @description = "QA test run at #{Runtime::Namespace.time}"
- end
-
- def fabricate!
- sandbox.visit!
-
- Page::Group::Show.perform do |group_show|
- if group_show.has_subgroup?(path)
- group_show.go_to_subgroup(path)
- else
- group_show.go_to_new_subgroup
-
- Page::Group::New.perform do |group_new|
- group_new.set_path(path)
- group_new.set_description(description)
- group_new.set_visibility('Public')
- group_new.create
- end
-
- # Ensure that the group was actually created
- group_show.wait(time: 1) do
- group_show.has_text?(path) &&
- group_show.has_new_project_or_subgroup_dropdown?
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/issue.rb b/qa/qa/factory/resource/issue.rb
deleted file mode 100644
index 95f48e20b3e..00000000000
--- a/qa/qa/factory/resource/issue.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-module QA
- module Factory
- module Resource
- class Issue < Factory::Base
- attr_writer :title, :description, :project
-
- dependency Factory::Resource::Project, as: :project do |project|
- project.name = 'project-for-issues'
- project.description = 'project for adding issues'
- end
-
- product :title do
- Page::Project::Issue::Show.act { issue_title }
- end
-
- def fabricate!
- project.visit!
-
- Page::Project::Show.act do
- go_to_new_issue
- end
-
- Page::Project::Issue::New.perform do |page|
- page.add_title(@title)
- page.add_description(@description)
- page.create_new_issue
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/kubernetes_cluster.rb b/qa/qa/factory/resource/kubernetes_cluster.rb
deleted file mode 100644
index 94d7df7128b..00000000000
--- a/qa/qa/factory/resource/kubernetes_cluster.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-require 'securerandom'
-
-module QA
- module Factory
- module Resource
- class KubernetesCluster < Factory::Base
- attr_writer :project, :cluster,
- :install_helm_tiller, :install_ingress, :install_prometheus, :install_runner
-
- product :ingress_ip do
- Page::Project::Operations::Kubernetes::Show.perform do |page|
- page.ingress_ip
- end
- end
-
- def fabricate!
- @project.visit!
-
- Page::Menu::Side.act { click_operations_kubernetes }
-
- Page::Project::Operations::Kubernetes::Index.perform do |page|
- page.add_kubernetes_cluster
- end
-
- Page::Project::Operations::Kubernetes::Add.perform do |page|
- page.add_existing_cluster
- end
-
- Page::Project::Operations::Kubernetes::AddExisting.perform do |page|
- page.set_cluster_name(@cluster.cluster_name)
- page.set_api_url(@cluster.api_url)
- page.set_ca_certificate(@cluster.ca_certificate)
- page.set_token(@cluster.token)
- page.add_cluster!
- end
-
- if @install_helm_tiller
- Page::Project::Operations::Kubernetes::Show.perform do |page|
- # We must wait a few seconds for permissions to be set up correctly for new cluster
- sleep 10
-
- # Helm must be installed before everything else
- page.install!(:helm)
- page.await_installed(:helm)
-
- page.install!(:ingress) if @install_ingress
- page.install!(:prometheus) if @install_prometheus
- page.install!(:runner) if @install_runner
-
- page.await_installed(:ingress) if @install_ingress
- page.await_installed(:prometheus) if @install_prometheus
- page.await_installed(:runner) if @install_runner
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/merge_request.rb b/qa/qa/factory/resource/merge_request.rb
deleted file mode 100644
index ddb62bd0a68..00000000000
--- a/qa/qa/factory/resource/merge_request.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-require 'securerandom'
-
-module QA
- module Factory
- module Resource
- class MergeRequest < Factory::Base
- attr_accessor :title,
- :description,
- :source_branch,
- :target_branch,
- :assignee,
- :milestone,
- :labels
-
- product :project do |factory|
- factory.project
- end
-
- product :source_branch do |factory|
- factory.source_branch
- end
-
- dependency Factory::Resource::Project, as: :project do |project|
- project.name = 'project-with-merge-request'
- end
-
- dependency Factory::Repository::ProjectPush, as: :target do |push, factory|
- factory.project.visit!
- push.project = factory.project
- push.branch_name = 'master'
- push.remote_branch = factory.target_branch
- end
-
- dependency Factory::Repository::ProjectPush, as: :source do |push, factory|
- push.project = factory.project
- push.branch_name = factory.target_branch
- push.remote_branch = factory.source_branch
- push.file_name = "added_file.txt"
- push.file_content = "File Added"
- end
-
- def initialize
- @title = 'QA test - merge request'
- @description = 'This is a test merge request'
- @source_branch = "qa-test-feature-#{SecureRandom.hex(8)}"
- @target_branch = "master"
- @assignee = nil
- @milestone = nil
- @labels = []
- end
-
- def fabricate!
- project.visit!
- Page::Project::Show.act { new_merge_request }
- Page::MergeRequest::New.perform do |page|
- page.fill_title(@title)
- page.fill_description(@description)
- page.choose_milestone(@milestone) if @milestone
- page.create_merge_request
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/merge_request_from_fork.rb b/qa/qa/factory/resource/merge_request_from_fork.rb
deleted file mode 100644
index 6caaf65f673..00000000000
--- a/qa/qa/factory/resource/merge_request_from_fork.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-module QA
- module Factory
- module Resource
- class MergeRequestFromFork < MergeRequest
- attr_accessor :fork_branch
-
- dependency Factory::Resource::Fork, as: :fork
-
- dependency Factory::Repository::ProjectPush, as: :push do |push, factory|
- push.project = factory.fork
- push.branch_name = factory.fork_branch
- push.file_name = 'file2.txt'
- push.user = factory.fork.user
- end
-
- def fabricate!
- fork.visit!
- Page::Project::Show.act { new_merge_request }
- Page::MergeRequest::New.act { create_merge_request }
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/personal_access_token.rb b/qa/qa/factory/resource/personal_access_token.rb
deleted file mode 100644
index 514e3615d18..00000000000
--- a/qa/qa/factory/resource/personal_access_token.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-module QA
- module Factory
- module Resource
- ##
- # Create a personal access token that can be used by the api
- #
- class PersonalAccessToken < Factory::Base
- attr_accessor :name
-
- product :access_token do
- Page::Profile::PersonalAccessTokens.act { created_access_token }
- end
-
- def fabricate!
- Page::Menu::Main.act { go_to_profile_settings }
- Page::Menu::Profile.act { click_access_tokens }
-
- Page::Profile::PersonalAccessTokens.perform do |page|
- page.fill_token_name(name || 'api-test-token')
- page.check_api
- page.create_token
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/project.rb b/qa/qa/factory/resource/project.rb
deleted file mode 100644
index 90db26ab3ab..00000000000
--- a/qa/qa/factory/resource/project.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-require 'securerandom'
-
-module QA
- module Factory
- module Resource
- class Project < Factory::Base
- attr_writer :description
- attr_reader :name
-
- dependency Factory::Resource::Group, as: :group
-
- product :name do |factory|
- factory.name
- end
-
- product :repository_ssh_location do
- Page::Project::Show.act do
- choose_repository_clone_ssh
- repository_location
- end
- end
-
- product :repository_http_location do
- Page::Project::Show.act do
- choose_repository_clone_http
- repository_location
- end
- end
-
- def initialize
- @description = 'My awesome project'
- end
-
- def name=(raw_name)
- @name = "#{raw_name}-#{SecureRandom.hex(8)}"
- end
-
- def fabricate!
- group.visit!
-
- Page::Group::Show.act { go_to_new_project }
-
- Page::Project::New.perform do |page|
- page.choose_test_namespace
- page.choose_name(@name)
- page.add_description(@description)
- page.set_visibility('Public')
- page.create_new_project
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/project_imported_from_github.rb b/qa/qa/factory/resource/project_imported_from_github.rb
deleted file mode 100644
index df2a3340d60..00000000000
--- a/qa/qa/factory/resource/project_imported_from_github.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require 'securerandom'
-
-module QA
- module Factory
- module Resource
- class ProjectImportedFromGithub < Resource::Project
- attr_writer :personal_access_token, :github_repository_path
-
- dependency Factory::Resource::Group, as: :group
-
- product :name do |factory|
- factory.name
- end
-
- def fabricate!
- group.visit!
-
- Page::Group::Show.act { go_to_new_project }
-
- Page::Project::New.perform do |page|
- page.go_to_import_project
- end
-
- Page::Project::New.perform do |page|
- page.go_to_github_import
- end
-
- Page::Project::Import::Github.perform do |page|
- page.add_personal_access_token(@personal_access_token)
- page.list_repos
- page.import!(@github_repository_path, @name)
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/project_milestone.rb b/qa/qa/factory/resource/project_milestone.rb
deleted file mode 100644
index 47a5e74204f..00000000000
--- a/qa/qa/factory/resource/project_milestone.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-module QA
- module Factory
- module Resource
- class ProjectMilestone < Factory::Base
- attr_accessor :description
- attr_reader :title
-
- dependency Factory::Resource::Project, as: :project
-
- product(:title) { |factory| factory.title }
-
- def title=(title)
- @title = "#{title}-#{SecureRandom.hex(4)}"
- @description = 'A milestone'
- end
-
- def fabricate!
- project.visit!
-
- Page::Menu::Side.act do
- click_issues
- click_milestones
- end
-
- Page::Project::Milestone::Index.act { click_new_milestone }
-
- Page::Project::Milestone::New.perform do |milestone_new|
- milestone_new.set_title(@title)
- milestone_new.set_description(@description)
- milestone_new.create_new_milestone
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/runner.rb b/qa/qa/factory/resource/runner.rb
deleted file mode 100644
index 03b69eb1bdf..00000000000
--- a/qa/qa/factory/resource/runner.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-require 'securerandom'
-
-module QA
- module Factory
- module Resource
- class Runner < Factory::Base
- attr_writer :name, :tags, :image
-
- dependency Factory::Resource::Project, as: :project do |project|
- project.name = 'project-with-ci-cd'
- project.description = 'Project with CI/CD Pipelines'
- end
-
- def name
- @name || "qa-runner-#{SecureRandom.hex(4)}"
- end
-
- def tags
- @tags || %w[qa e2e]
- end
-
- def image
- @image || 'gitlab/gitlab-runner:alpine'
- end
-
- def fabricate!
- project.visit!
-
- Page::Menu::Side.act { click_ci_cd_settings }
-
- Service::Runner.new(name).tap do |runner|
- Page::Project::Settings::CICD.perform do |settings|
- settings.expand_runners_settings do |runners|
- runner.pull
- runner.token = runners.registration_token
- runner.address = runners.coordinator_address
- runner.tags = tags
- runner.image = image
- runner.register!
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/sandbox.rb b/qa/qa/factory/resource/sandbox.rb
deleted file mode 100644
index 4f6039f300f..00000000000
--- a/qa/qa/factory/resource/sandbox.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-module QA
- module Factory
- module Resource
- ##
- # Ensure we're in our sandbox namespace, either by navigating to it or by
- # creating it if it doesn't yet exist.
- #
- class Sandbox < Factory::Base
- def initialize
- @name = Runtime::Namespace.sandbox_name
- end
-
- def fabricate!
- Page::Menu::Main.act { go_to_groups }
-
- Page::Dashboard::Groups.perform do |page|
- if page.has_group?(@name)
- page.go_to_group(@name)
- else
- page.go_to_new_group
-
- Page::Group::New.perform do |group|
- group.set_path(@name)
- group.set_description('GitLab QA Sandbox Group')
- group.set_visibility('Public')
- group.create
- end
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/secret_variable.rb b/qa/qa/factory/resource/secret_variable.rb
deleted file mode 100644
index 12a830da116..00000000000
--- a/qa/qa/factory/resource/secret_variable.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-module QA
- module Factory
- module Resource
- class SecretVariable < Factory::Base
- attr_accessor :key, :value
-
- dependency Factory::Resource::Project, as: :project do |project|
- project.name = 'project-with-secret-variables'
- project.description = 'project for adding secret variable test'
- end
-
- def fabricate!
- project.visit!
-
- Page::Menu::Side.act { click_ci_cd_settings }
-
- Page::Project::Settings::CICD.perform do |setting|
- setting.expand_secret_variables do |page|
- page.fill_variable(key, value)
-
- page.save_variables
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/ssh_key.rb b/qa/qa/factory/resource/ssh_key.rb
deleted file mode 100644
index 6c872f32d16..00000000000
--- a/qa/qa/factory/resource/ssh_key.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Factory
- module Resource
- class SSHKey < Factory::Base
- extend Forwardable
-
- attr_accessor :title
- attr_reader :private_key, :public_key, :fingerprint
- def_delegators :key, :private_key, :public_key, :fingerprint
-
- product :private_key do |factory|
- factory.private_key
- end
-
- product :title do |factory|
- factory.title
- end
-
- product :fingerprint do |factory|
- factory.fingerprint
- end
-
- def key
- @key ||= Runtime::Key::RSA.new
- end
-
- def fabricate!
- Page::Menu::Main.act { go_to_profile_settings }
- Page::Menu::Profile.act { click_ssh_keys }
-
- Page::Profile::SSHKeys.perform do |page|
- page.add_key(public_key, title)
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/user.rb b/qa/qa/factory/resource/user.rb
deleted file mode 100644
index eac2a873bd5..00000000000
--- a/qa/qa/factory/resource/user.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-require 'securerandom'
-
-module QA
- module Factory
- module Resource
- class User < Factory::Base
- attr_reader :unique_id
- attr_writer :username, :password, :name, :email
-
- def initialize
- @unique_id = SecureRandom.hex(8)
- end
-
- def username
- @username ||= "qa-user-#{unique_id}"
- end
-
- def password
- @password ||= 'password'
- end
-
- def name
- @name ||= username
- end
-
- def email
- @email ||= "#{username}@example.com"
- end
-
- def credentials_given?
- defined?(@username) && defined?(@password)
- end
-
- product(:name) { |factory| factory.name }
- product(:username) { |factory| factory.username }
- product(:email) { |factory| factory.email }
- product(:password) { |factory| factory.password }
-
- def fabricate!
- Page::Menu::Main.perform { |main| main.sign_out }
-
- if credentials_given?
- Page::Main::Login.perform do |login|
- login.sign_in_using_credentials(self)
- end
- else
- Page::Main::Login.perform do |login|
- login.switch_to_register_tab
- end
- Page::Main::SignUp.perform do |signup|
- signup.sign_up!(self)
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/resource/wiki.rb b/qa/qa/factory/resource/wiki.rb
deleted file mode 100644
index cc200a512d5..00000000000
--- a/qa/qa/factory/resource/wiki.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-module QA
- module Factory
- module Resource
- class Wiki < Factory::Base
- attr_accessor :title, :content, :message
-
- dependency Factory::Resource::Project, as: :project do |project|
- project.name = 'project-for-wikis'
- project.description = 'project for adding wikis'
- end
-
- def fabricate!
- Page::Menu::Side.act { click_wiki }
- Page::Project::Wiki::New.perform do |page|
- page.go_to_create_first_page
- page.set_title(@title)
- page.set_content(@content)
- page.set_message(@message)
- page.create_new_page
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/factory/settings/hashed_storage.rb b/qa/qa/factory/settings/hashed_storage.rb
deleted file mode 100644
index c69ebed3c6b..00000000000
--- a/qa/qa/factory/settings/hashed_storage.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-module QA
- module Factory
- module Settings
- class HashedStorage < Factory::Base
- def fabricate!(*traits)
- raise ArgumentError unless traits.include?(:enabled)
-
- Page::Main::Login.act { sign_in_using_credentials }
- Page::Menu::Main.act { go_to_admin_area }
- Page::Menu::Admin.act { go_to_settings }
-
- Page::Admin::Settings::Main.perform do |setting|
- setting.expand_repository_storage do |page|
- page.enable_hashed_storage
- page.save_settings
- end
- end
-
- QA::Page::Menu::Main.act { sign_out }
- end
- end
- end
- end
-end
diff --git a/qa/qa/fixtures/auto_devops_rack/Gemfile.lock b/qa/qa/fixtures/auto_devops_rack/Gemfile.lock
index 09cf72c48ac..d44ccbb5e69 100644
--- a/qa/qa/fixtures/auto_devops_rack/Gemfile.lock
+++ b/qa/qa/fixtures/auto_devops_rack/Gemfile.lock
@@ -1,7 +1,7 @@
GEM
remote: https://rubygems.org/
specs:
- rack (2.0.4)
+ rack (2.0.6)
rake (12.3.0)
PLATFORMS
@@ -12,4 +12,4 @@ DEPENDENCIES
rake
BUNDLED WITH
- 1.16.1
+ 1.17.1
diff --git a/qa/qa/git/repository.rb b/qa/qa/git/repository.rb
index 14cb8125fdb..7f959441dac 100644
--- a/qa/qa/git/repository.rb
+++ b/qa/qa/git/repository.rb
@@ -1,14 +1,24 @@
+# frozen_string_literal: true
+
require 'cgi'
require 'uri'
require 'open3'
+require 'fileutils'
+require 'tmpdir'
module QA
module Git
class Repository
include Scenario::Actable
+ attr_writer :password
+ attr_accessor :env_vars
+
def initialize
- @ssh_cmd = ""
+ # We set HOME to the current working directory (which is a
+ # temporary directory created in .perform()) so the temporarily dropped
+ # .netrc can be utilised
+ self.env_vars = [%Q{HOME="#{File.dirname(netrc_file_path)}"}]
end
def self.perform(*args)
@@ -21,36 +31,27 @@ module QA
@uri = URI(address)
end
- def username=(name)
- @username = name
- @uri.user = name
- end
-
- def password=(pass)
- @password = pass
- @uri.password = CGI.escape(pass).gsub('+', '%20')
+ def username=(username)
+ @username = username
+ @uri.user = username
end
def use_default_credentials
- if ::QA::Runtime::User.ldap_user?
- self.username = Runtime::User.ldap_username
- self.password = Runtime::User.ldap_password
- else
- self.username = Runtime::User.username
- self.password = Runtime::User.password
- end
+ self.username, self.password = default_credentials
+
+ add_credentials_to_netrc unless ssh_key_set?
end
def clone(opts = '')
- run_and_redact_credentials(build_git_command("git clone #{opts} #{@uri} ./"))
+ run("git clone #{opts} #{uri} ./")
end
def checkout(branch_name)
- `git checkout "#{branch_name}"`
+ run(%Q{git checkout "#{branch_name}"})
end
def checkout_new_branch(branch_name)
- `git checkout -b "#{branch_name}"`
+ run(%Q{git checkout -b "#{branch_name}"})
end
def shallow_clone
@@ -58,12 +59,10 @@ module QA
end
def configure_identity(name, email)
- `git config user.name #{name}`
- `git config user.email #{email}`
- end
+ run(%Q{git config user.name #{name}})
+ run(%Q{git config user.email #{email}})
- def configure_ssh_command(command)
- @ssh_cmd = "GIT_SSH_COMMAND='#{command}'"
+ add_credentials_to_netrc
end
def commit_file(name, contents, message)
@@ -74,54 +73,121 @@ module QA
def add_file(name, contents)
::File.write(name, contents)
- `git add #{name}`
+ run(%Q{git add #{name}})
end
def commit(message)
- `git commit -m "#{message}"`
+ run(%Q{git commit -m "#{message}"})
end
def push_changes(branch = 'master')
- output, _ = run_and_redact_credentials(build_git_command("git push #{@uri} #{branch}"))
-
- output
+ run("git push #{uri} #{branch}")
end
def commits
- `git log --oneline`.split("\n")
+ run('git log --oneline').split("\n")
end
def use_ssh_key(key)
@private_key_file = Tempfile.new("id_#{SecureRandom.hex(8)}")
- File.binwrite(@private_key_file, key.private_key)
- File.chmod(0700, @private_key_file)
+ File.binwrite(private_key_file, key.private_key)
+ File.chmod(0700, private_key_file)
@known_hosts_file = Tempfile.new("known_hosts_#{SecureRandom.hex(8)}")
keyscan_params = ['-H']
- keyscan_params << "-p #{@uri.port}" if @uri.port
- keyscan_params << @uri.host
- run_and_redact_credentials("ssh-keyscan #{keyscan_params.join(' ')} >> #{@known_hosts_file.path}")
+ keyscan_params << "-p #{uri.port}" if uri.port
+ keyscan_params << uri.host
+ run("ssh-keyscan #{keyscan_params.join(' ')} >> #{known_hosts_file.path}")
- configure_ssh_command("ssh -i #{@private_key_file.path} -o UserKnownHostsFile=#{@known_hosts_file.path}")
+ self.env_vars << %Q{GIT_SSH_COMMAND="ssh -i #{private_key_file.path} -o UserKnownHostsFile=#{known_hosts_file.path}"}
end
def delete_ssh_key
- return unless @private_key_file
+ return unless ssh_key_set?
+
+ private_key_file.close(true)
+ known_hosts_file.close(true)
+ end
+
+ def push_with_git_protocol(version, file_name, file_content, commit_message = 'Initial commit')
+ self.git_protocol = version
+ add_file(file_name, file_content)
+ commit(commit_message)
+ push_changes
+
+ fetch_supported_git_protocol
+ end
+
+ def git_protocol=(value)
+ raise ArgumentError, "Please specify the protocol you would like to use: 0, 1, or 2" unless %w[0 1 2].include?(value.to_s)
- @private_key_file.close(true)
- @known_hosts_file.close(true)
+ run("git config protocol.version #{value}")
end
- def build_git_command(command_str)
- [@ssh_cmd, command_str].compact.join(' ')
+ def fetch_supported_git_protocol
+ # ls-remote is one command known to respond to Git protocol v2 so we use
+ # it to get output including the version reported via Git tracing
+ output = run("git ls-remote #{uri}", "GIT_TRACE_PACKET=1")
+ output[/git< version (\d+)/, 1] || 'unknown'
end
private
- # Since the remote URL contains the credentials, and git occasionally
- # outputs the URL. Note that stderr is redirected to stdout.
- def run_and_redact_credentials(command)
- Open3.capture2("#{command} 2>&1 | sed -E 's#://[^@]+@#://****@#g'")
+ attr_reader :uri, :username, :password, :known_hosts_file, :private_key_file
+
+ def ssh_key_set?
+ !private_key_file.nil?
+ end
+
+ def run(command_str, *extra_env)
+ command = [env_vars, *extra_env, command_str, '2>&1'].compact.join(' ')
+ Runtime::Logger.debug "Git: command=[#{command}]"
+
+ output, _ = Open3.capture2(command)
+ output = output.chomp.gsub(/\s+$/, '')
+ Runtime::Logger.debug "Git: output=[#{output}]"
+
+ output
+ end
+
+ def default_credentials
+ if ::QA::Runtime::User.ldap_user?
+ [Runtime::User.ldap_username, Runtime::User.ldap_password]
+ else
+ [Runtime::User.username, Runtime::User.password]
+ end
+ end
+
+ def tmp_netrc_directory
+ @tmp_netrc_directory ||= File.join(Dir.tmpdir, "qa-netrc-credentials", $$.to_s)
+ end
+
+ def netrc_file_path
+ @netrc_file_path ||= File.join(tmp_netrc_directory, '.netrc')
+ end
+
+ def netrc_content
+ "machine #{uri.host} login #{username} password #{password}"
+ end
+
+ def netrc_already_contains_content?
+ File.exist?(netrc_file_path) &&
+ File.readlines(netrc_file_path).grep(/^#{netrc_content}$/).any?
+ end
+
+ def add_credentials_to_netrc
+ # Despite libcurl supporting a custom .netrc location through the
+ # CURLOPT_NETRC_FILE environment variable, git does not support it :(
+ # Info: https://curl.haxx.se/libcurl/c/CURLOPT_NETRC_FILE.html
+ #
+ # This will create a .netrc in the correct working directory, which is
+ # a temporary directory created in .perform()
+ #
+ return if netrc_already_contains_content?
+
+ FileUtils.mkdir_p(tmp_netrc_directory)
+ File.open(netrc_file_path, 'a') { |file| file.puts(netrc_content) }
+ File.chmod(0600, netrc_file_path)
end
end
end
diff --git a/qa/qa/page/README.md b/qa/qa/page/README.md
index 2dbc59846e7..d0de33892c4 100644
--- a/qa/qa/page/README.md
+++ b/qa/qa/page/README.md
@@ -70,15 +70,15 @@ module Page
module Main
class Login < Page::Base
view 'app/views/devise/passwords/edit.html.haml' do
- element :password_field, 'password_field :password'
- element :password_confirmation, 'password_field :password_confirmation'
- element :change_password_button, 'submit "Change your password"'
+ element :password_field
+ element :password_confirmation
+ element :change_password_button
end
view 'app/views/devise/sessions/_new_base.html.haml' do
- element :login_field, 'text_field :login'
- element :password_field, 'password_field :password'
- element :sign_in_button, 'submit "Sign in"'
+ element :login_field
+ element :password_field
+ element :sign_in_button
end
# ...
@@ -86,20 +86,32 @@ module Page
end
```
-It is possible to use `element` DSL method without value, with a String value
-or with a Regexp.
+The `view` DSL method declares the filename of the view where an
+`element` is implemented.
+
+The `element` DSL method in turn declares an element for which a corresponding
+`qa-element-name-dasherized` CSS class need to be added to the view file.
+
+You can also define a value (String or Regexp) to match to the actual view
+code but **this is deprecated** in favor of the above method for two reasons:
+
+- Consistency: there is only one way to define an element
+- Separation of concerns: QA uses dedicated CSS classes instead of reusing code
+ or classes used by other components (e.g. `js-*` classes etc.)
```ruby
view 'app/views/my/view.html.haml' do
+ # Implicitly require `.qa-logout-button` CSS class to be present in the view
+ element :logout_button
+
+ ## This is deprecated and forbidden by the `QA/ElementWithPattern` RuboCop cop.
# Require `f.submit "Sign in"` to be present in `my/view.html.haml
- element :my_button, 'f.submit "Sign in"'
+ element :my_button, 'f.submit "Sign in"' # rubocop:disable QA/ElementWithPattern
+ ## This is deprecated and forbidden by the `QA/ElementWithPattern` RuboCop cop.
# Match every line in `my/view.html.haml` against
# `/link_to .* "My Profile"/` regexp.
- element :profile_link, /link_to .* "My Profile"/
-
- # Implicitly require `.qa-logout-button` CSS class to be present in the view
- element :logout_button
+ element :profile_link, /link_to .* "My Profile"/ # rubocop:disable QA/ElementWithPattern
end
```
@@ -119,4 +131,4 @@ If you need more information, ask for help on `#quality` channel on Slack
(internal, GitLab Team only).
If you are not a Team Member, and you still need help to contribute, please
-open an issue in GitLab QA issue tracker.
+open an issue in GitLab CE issue tracker with the `~QA` label.
diff --git a/qa/qa/page/admin/menu.rb b/qa/qa/page/admin/menu.rb
new file mode 100644
index 00000000000..e8c7d274966
--- /dev/null
+++ b/qa/qa/page/admin/menu.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Admin
+ class Menu < Page::Base
+ view 'app/views/layouts/nav/sidebar/_admin.html.haml' do
+ element :admin_sidebar
+ element :admin_sidebar_submenu
+ element :admin_settings_item
+ element :admin_settings_repository_item
+ end
+
+ def go_to_repository_settings
+ hover_settings do
+ within_submenu do
+ click_element :admin_settings_repository_item
+ end
+ end
+ end
+
+ private
+
+ def hover_settings
+ within_sidebar do
+ scroll_to_element(:admin_settings_item)
+ find_element(:admin_settings_item).hover
+
+ yield
+ end
+ end
+
+ def within_sidebar
+ within_element(:admin_sidebar) do
+ yield
+ end
+ end
+
+ def within_submenu
+ within_element(:admin_sidebar_submenu) do
+ yield
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/admin/settings/component/repository_storage.rb b/qa/qa/page/admin/settings/component/repository_storage.rb
new file mode 100644
index 00000000000..2ed0cd73aa3
--- /dev/null
+++ b/qa/qa/page/admin/settings/component/repository_storage.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Admin
+ module Settings
+ module Component
+ class RepositoryStorage < Page::Base
+ view 'app/views/admin/application_settings/_repository_storage.html.haml' do
+ element :hashed_storage_checkbox
+ element :save_changes_button
+ end
+
+ def enable_hashed_storage
+ check_element :hashed_storage_checkbox
+ end
+
+ def save_settings
+ click_element :save_changes_button
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/admin/settings/main.rb b/qa/qa/page/admin/settings/main.rb
deleted file mode 100644
index 73034ffe0d8..00000000000
--- a/qa/qa/page/admin/settings/main.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-module QA
- module Page
- module Admin
- module Settings
- class Main < Page::Base
- include QA::Page::Settings::Common
-
- view 'app/views/admin/application_settings/show.html.haml' do
- element :terms_settings
- end
-
- def expand_repository_storage(&block)
- expand_section(:terms_settings) do
- RepositoryStorage.perform(&block)
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/admin/settings/repository.rb b/qa/qa/page/admin/settings/repository.rb
new file mode 100644
index 00000000000..b7f1deb21bd
--- /dev/null
+++ b/qa/qa/page/admin/settings/repository.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Admin
+ module Settings
+ class Repository < Page::Base
+ include QA::Page::Settings::Common
+
+ view 'app/views/admin/application_settings/repository.html.haml' do
+ element :repository_storage_settings
+ end
+
+ def expand_repository_storage(&block)
+ expand_section(:repository_storage_settings) do
+ Component::RepositoryStorage.perform(&block)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/admin/settings/repository_storage.rb b/qa/qa/page/admin/settings/repository_storage.rb
deleted file mode 100644
index 68dd23a41e1..00000000000
--- a/qa/qa/page/admin/settings/repository_storage.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-module QA
- module Page
- module Admin
- module Settings
- class RepositoryStorage < Page::Base
- view 'app/views/admin/application_settings/_repository_storage.html.haml' do
- element :submit, "submit 'Save changes'"
- element :hashed_storage,
- 'Use hashed storage paths for newly created and renamed projects'
- end
-
- def enable_hashed_storage
- check 'Use hashed storage paths for newly created and renamed projects'
- end
-
- def save_settings
- click_button 'Save changes'
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb
index 30e35bf7abb..91e229c4c8c 100644
--- a/qa/qa/page/base.rb
+++ b/qa/qa/page/base.rb
@@ -1,12 +1,17 @@
+# frozen_string_literal: true
+
require 'capybara/dsl'
module QA
module Page
class Base
+ prepend Support::Page::Logging if Runtime::Env.debug?
include Capybara::DSL
include Scenario::Actable
extend SingleForwardable
+ ElementNotFound = Class.new(RuntimeError)
+
def_delegators :evaluator, :view, :views
def refresh
@@ -28,6 +33,21 @@ module QA
false
end
+ def with_retry(max_attempts: 3, reload: false)
+ attempts = 0
+
+ while attempts < max_attempts
+ result = yield
+ return result if result
+
+ refresh if reload
+
+ attempts += 1
+ end
+
+ false
+ end
+
def scroll_to(selector, text: nil)
page.execute_script <<~JS
var elements = Array.from(document.querySelectorAll('#{selector}'));
@@ -68,6 +88,10 @@ module QA
all(element_selector_css(name))
end
+ def check_element(name)
+ find_element(name).set(true)
+ end
+
def click_element(name)
find_element(name).click
end
@@ -76,12 +100,20 @@ module QA
find_element(name).set(content)
end
+ def has_element?(name)
+ has_css?(element_selector_css(name))
+ end
+
def within_element(name)
page.within(element_selector_css(name)) do
yield
end
end
+ def scroll_to_element(name, *args)
+ scroll_to(element_selector_css(name), *args)
+ end
+
def element_selector_css(name)
Page::Element.new(name).selector_css
end
diff --git a/qa/qa/page/component/clone_panel.rb b/qa/qa/page/component/clone_panel.rb
index 8e8ff4e3bb0..94e761b0e0c 100644
--- a/qa/qa/page/component/clone_panel.rb
+++ b/qa/qa/page/component/clone_panel.rb
@@ -7,8 +7,8 @@ module QA
def self.included(base)
base.view 'app/views/shared/_clone_panel.html.haml' do
element :clone_dropdown
- element :clone_options_dropdown, '.clone-options-dropdown'
- element :project_repository_location, 'text_field_tag :project_clone'
+ element :clone_options_dropdown, '.clone-options-dropdown' # rubocop:disable QA/ElementWithPattern
+ element :project_repository_location, 'text_field_tag :project_clone' # rubocop:disable QA/ElementWithPattern
end
end
diff --git a/qa/qa/page/component/dropdown_filter.rb b/qa/qa/page/component/dropdown_filter.rb
new file mode 100644
index 00000000000..e896c382779
--- /dev/null
+++ b/qa/qa/page/component/dropdown_filter.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Component
+ module DropdownFilter
+ def filter_and_select(item)
+ wait(reload: false) do
+ page.has_css?('.dropdown-input-field')
+ end
+
+ find('.dropdown-input-field').set(item)
+ click_link item
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/component/groups_filter.rb b/qa/qa/page/component/groups_filter.rb
index e647d368f0f..cc50bb439b4 100644
--- a/qa/qa/page/component/groups_filter.rb
+++ b/qa/qa/page/component/groups_filter.rb
@@ -6,12 +6,7 @@ module QA
module GroupsFilter
def self.included(base)
base.view 'app/views/shared/groups/_search_form.html.haml' do
- element :groups_filter, 'search_field_tag :filter'
- element :groups_filter_placeholder, 'Search by name'
- end
-
- base.view 'app/views/shared/groups/_empty_state.html.haml' do
- element :groups_empty_state
+ element :groups_filter
end
base.view 'app/assets/javascripts/groups/components/groups.vue' do
@@ -21,13 +16,22 @@ module QA
private
- def filter_by_name(name)
+ def has_filtered_group?(name)
+ # Filter and submit to reload the page and only retrieve the filtered results
+ find_element(:groups_filter).set(name).send_keys(:return)
+
+ # Since we submitted after filtering, the presence of
+ # groups_list_tree_container means we have the complete filtered list
+ # of groups
wait(reload: false) do
- page.has_css?(element_selector_css(:groups_empty_state)) ||
- page.has_css?(element_selector_css(:groups_list_tree_container))
+ page.has_css?(element_selector_css(:groups_list_tree_container))
end
- fill_in 'Search by name', with: name
+ # If there are no groups we'll know immediately because we filtered the list
+ return false if page.has_text?('No groups or projects matched your search', wait: 0)
+
+ # The name will be present as filter input so we check for a link, not text
+ page.has_link?(name, wait: 0)
end
end
end
diff --git a/qa/qa/page/component/issuable/common.rb b/qa/qa/page/component/issuable/common.rb
new file mode 100644
index 00000000000..cfd8ac1e7c8
--- /dev/null
+++ b/qa/qa/page/component/issuable/common.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Component
+ module Issuable
+ module Common
+ def self.included(base)
+ base.view 'app/assets/javascripts/issue_show/components/title.vue' do
+ element :edit_button
+ end
+
+ base.view 'app/assets/javascripts/issue_show/components/fields/title.vue' do
+ element :title_input
+ end
+
+ base.view 'app/assets/javascripts/issue_show/components/fields/description.vue' do
+ element :description_textarea
+ end
+
+ base.view 'app/assets/javascripts/issue_show/components/edit_actions.vue' do
+ element :save_button
+ element :delete_button
+ end
+
+ base.view 'app/assets/javascripts/issue_show/components/edit_actions.vue' do
+ element :save_button
+ element :delete_button
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/component/select2.rb b/qa/qa/page/component/select2.rb
index 30829eb0221..6d07d5a10e6 100644
--- a/qa/qa/page/component/select2.rb
+++ b/qa/qa/page/component/select2.rb
@@ -3,7 +3,12 @@ module QA
module Component
module Select2
def select_item(item_text)
- find('ul.select2-result-sub > li', text: item_text).click
+ find('.select2-result-label', text: item_text).click
+ end
+
+ def search_and_select(item_text)
+ find('.select2-input').set(item_text)
+ select_item(item_text)
end
end
end
diff --git a/qa/qa/page/component/users_select.rb b/qa/qa/page/component/users_select.rb
new file mode 100644
index 00000000000..f88d6450a33
--- /dev/null
+++ b/qa/qa/page/component/users_select.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Component
+ module UsersSelect
+ def select_user(element, username)
+ find("#{element_selector_css(element)} input").set(username)
+ find('.ajax-users-dropdown .user-username', text: "@#{username}").click
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/dashboard/groups.rb b/qa/qa/page/dashboard/groups.rb
index 70c5f996ff8..7a07515de62 100644
--- a/qa/qa/page/dashboard/groups.rb
+++ b/qa/qa/page/dashboard/groups.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module QA
module Page
module Dashboard
@@ -5,18 +7,16 @@ module QA
include Page::Component::GroupsFilter
view 'app/views/shared/groups/_search_form.html.haml' do
- element :groups_filter, 'search_field_tag :filter'
- element :groups_filter_placeholder, 'Search by name'
+ element :groups_filter, 'search_field_tag :filter' # rubocop:disable QA/ElementWithPattern
+ element :groups_filter_placeholder, 'Search by name' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/dashboard/_groups_head.html.haml' do
- element :new_group_button, 'link_to _("New group")'
+ element :new_group_button, 'link_to _("New group")' # rubocop:disable QA/ElementWithPattern
end
def has_group?(name)
- filter_by_name(name)
-
- page.has_link?(name)
+ has_filtered_group?(name)
end
def go_to_group(name)
diff --git a/qa/qa/page/dashboard/projects.rb b/qa/qa/page/dashboard/projects.rb
index 5b2827c089c..0f434577b3b 100644
--- a/qa/qa/page/dashboard/projects.rb
+++ b/qa/qa/page/dashboard/projects.rb
@@ -5,7 +5,7 @@ module QA
view 'app/views/dashboard/projects/index.html.haml'
view 'app/views/shared/projects/_search_form.html.haml' do
- element :form_filter_by_name, /form_tag.+id: 'project-filter-form'/
+ element :form_filter_by_name, /form_tag.+id: 'project-filter-form'/ # rubocop:disable QA/ElementWithPattern
end
def go_to_project(name)
diff --git a/qa/qa/page/file/form.rb b/qa/qa/page/file/form.rb
index f6e502f500b..a1534231691 100644
--- a/qa/qa/page/file/form.rb
+++ b/qa/qa/page/file/form.rb
@@ -3,14 +3,23 @@ module QA
module File
class Form < Page::Base
include Shared::CommitMessage
+ include Page::Component::DropdownFilter
view 'app/views/projects/blob/_editor.html.haml' do
- element :file_name, "text_field_tag 'file_name'"
- element :editor, '#editor'
+ element :file_name, "text_field_tag 'file_name'" # rubocop:disable QA/ElementWithPattern
+ element :editor, '#editor' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/projects/_commit_button.html.haml' do
- element :commit_changes, "button_tag 'Commit changes'"
+ element :commit_changes, "button_tag 'Commit changes'" # rubocop:disable QA/ElementWithPattern
+ end
+
+ view 'app/views/projects/blob/_template_selectors.html.haml' do
+ element :template_type_dropdown
+ element :gitignore_dropdown
+ element :gitlab_ci_yml_dropdown
+ element :dockerfile_dropdown
+ element :license_dropdown
end
def add_name(name)
@@ -29,6 +38,25 @@ module QA
click_on 'Commit changes'
end
+ def select_template(template_type, template)
+ click_element :template_type_dropdown
+ click_link template_type
+
+ case template_type
+ when '.gitignore'
+ click_element :gitignore_dropdown
+ when '.gitlab-ci.yml'
+ click_element :gitlab_ci_yml_dropdown
+ when 'Dockerfile'
+ click_element :dockerfile_dropdown
+ when 'LICENSE'
+ click_element :license_dropdown
+ else
+ raise %Q(Unsupported template_type "#{template_type}". Please confirm that it is a valid option.)
+ end
+ filter_and_select template
+ end
+
private
def text_area
diff --git a/qa/qa/page/file/shared/commit_message.rb b/qa/qa/page/file/shared/commit_message.rb
index 5af1a55e2ef..aa1bb081cd3 100644
--- a/qa/qa/page/file/shared/commit_message.rb
+++ b/qa/qa/page/file/shared/commit_message.rb
@@ -5,7 +5,7 @@ module QA
module CommitMessage
def self.included(base)
base.view 'app/views/shared/_commit_message_container.html.haml' do
- element :commit_message, "text_area_tag 'commit_message'"
+ element :commit_message, "text_area_tag 'commit_message'" # rubocop:disable QA/ElementWithPattern
end
end
diff --git a/qa/qa/page/file/show.rb b/qa/qa/page/file/show.rb
index 99f5924b67f..abd8ebb089f 100644
--- a/qa/qa/page/file/show.rb
+++ b/qa/qa/page/file/show.rb
@@ -5,12 +5,12 @@ module QA
include Shared::CommitMessage
view 'app/helpers/blob_helper.rb' do
- element :edit_button, "_('Edit')"
- element :delete_button, /label:\s+"Delete"/
+ element :edit_button, "_('Edit')" # rubocop:disable QA/ElementWithPattern
+ element :delete_button, /label:\s+"Delete"/ # rubocop:disable QA/ElementWithPattern
end
view 'app/views/projects/blob/_remove.html.haml' do
- element :delete_file_button, "button_tag 'Delete file'"
+ element :delete_file_button, "button_tag 'Delete file'" # rubocop:disable QA/ElementWithPattern
end
def click_edit
diff --git a/qa/qa/page/group/new.rb b/qa/qa/page/group/new.rb
index 48b71a7c883..39584daf334 100644
--- a/qa/qa/page/group/new.rb
+++ b/qa/qa/page/group/new.rb
@@ -3,14 +3,14 @@ module QA
module Group
class New < Page::Base
view 'app/views/shared/_group_form.html.haml' do
- element :group_path_field, 'text_field :path'
- element :group_name_field, 'text_field :name'
- element :group_description_field, 'text_area :description'
+ element :group_path_field, 'text_field :path' # rubocop:disable QA/ElementWithPattern
+ element :group_name_field, 'text_field :name' # rubocop:disable QA/ElementWithPattern
+ element :group_description_field, 'text_area :description' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/groups/new.html.haml' do
- element :create_group_button, "submit 'Create group'"
- element :visibility_radios, 'visibility_level:'
+ element :create_group_button, "submit 'Create group'" # rubocop:disable QA/ElementWithPattern
+ element :visibility_radios, 'visibility_level:' # rubocop:disable QA/ElementWithPattern
end
def set_path(path)
diff --git a/qa/qa/page/group/show.rb b/qa/qa/page/group/show.rb
index 6747f7f10b6..0f0ab81a4ef 100644
--- a/qa/qa/page/group/show.rb
+++ b/qa/qa/page/group/show.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module QA
module Page
module Group
@@ -5,18 +7,15 @@ module QA
include Page::Component::GroupsFilter
view 'app/views/groups/show.html.haml' do
- element :new_project_or_subgroup_dropdown, '.new-project-subgroup'
- element :new_project_or_subgroup_dropdown_toggle, '.dropdown-toggle'
- element :new_project_option, /%li.*data:.*value: "new-project"/
- element :new_project_button, /%input.*data:.*action: "new-project"/
- element :new_subgroup_option, /%li.*data:.*value: "new-subgroup"/
-
- # data-value and data-action get modified by JS for subgroup
- element :new_subgroup_button, /%input.*\.js-new-group-child/
+ element :new_project_or_subgroup_dropdown
+ element :new_project_or_subgroup_dropdown_toggle
+ element :new_project_option
+ element :new_subgroup_option
+ element :new_in_group_button
end
view 'app/assets/javascripts/groups/constants.js' do
- element :no_result_text, 'No groups or projects matched your search'
+ element :no_result_text, 'No groups or projects matched your search' # rubocop:disable QA/ElementWithPattern
end
def go_to_subgroup(name)
@@ -24,43 +23,37 @@ module QA
end
def has_new_project_or_subgroup_dropdown?
- page.has_css?(element_selector_css(:new_project_or_subgroup_dropdown))
+ has_element?(:new_project_or_subgroup_dropdown)
end
def has_subgroup?(name)
- filter_by_name(name)
-
- page.has_text?(/#{name}|No groups or projects matched your search/, wait: 60)
-
- page.has_text?(name, wait: 0)
+ has_filtered_group?(name)
end
def go_to_new_subgroup
- click_new('subgroup')
+ select_kind :new_subgroup_option
- find("input[data-action='new-subgroup']").click
+ click_element :new_in_group_button
end
def go_to_new_project
- click_new('project')
+ select_kind :new_project_option
- find("input[data-action='new-project']").click
+ click_element :new_in_group_button
end
private
- def click_new(kind)
- within '.new-project-subgroup' do
- css = "li[data-value='new-#{kind}']"
-
+ def select_kind(kind)
+ within_element(:new_project_or_subgroup_dropdown) do
# May need to click again because it is possible to click the button quicker than the JS is bound
wait(reload: false) do
- find('.dropdown-toggle').click
+ click_element :new_project_or_subgroup_dropdown_toggle
- page.has_css?(css)
+ has_element?(kind)
end
- find(css).click
+ click_element kind
end
end
end
diff --git a/qa/qa/page/issuable/sidebar.rb b/qa/qa/page/issuable/sidebar.rb
index f207264e24f..d3751b712c9 100644
--- a/qa/qa/page/issuable/sidebar.rb
+++ b/qa/qa/page/issuable/sidebar.rb
@@ -3,8 +3,8 @@ module QA
module Issuable
class Sidebar < Page::Base
view 'app/views/shared/issuable/_sidebar.html.haml' do
- element :labels_block, ".issuable-show-labels"
- element :milestones_block, '.block.milestone'
+ element :labels_block, ".issuable-show-labels" # rubocop:disable QA/ElementWithPattern
+ element :milestones_block, '.block.milestone' # rubocop:disable QA/ElementWithPattern
end
def has_label?(label)
diff --git a/qa/qa/page/label/index.rb b/qa/qa/page/label/index.rb
new file mode 100644
index 00000000000..323acd57743
--- /dev/null
+++ b/qa/qa/page/label/index.rb
@@ -0,0 +1,15 @@
+module QA
+ module Page
+ module Label
+ class Index < Page::Base
+ view 'app/views/projects/labels/index.html.haml' do
+ element :label_create_new
+ end
+
+ def go_to_new_label
+ click_element :label_create_new
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/label/new.rb b/qa/qa/page/label/new.rb
new file mode 100644
index 00000000000..b5422dc9400
--- /dev/null
+++ b/qa/qa/page/label/new.rb
@@ -0,0 +1,30 @@
+module QA
+ module Page
+ module Label
+ class New < Page::Base
+ view 'app/views/shared/labels/_form.html.haml' do
+ element :label_title
+ element :label_description
+ element :label_color
+ element :label_create_button
+ end
+
+ def create_label
+ click_element :label_create_button
+ end
+
+ def fill_title(title)
+ fill_element :label_title, title
+ end
+
+ def fill_description(description)
+ fill_element :label_description, description
+ end
+
+ def fill_color(color)
+ fill_element :label_color, color
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/layout/banner.rb b/qa/qa/page/layout/banner.rb
index e7654bdafc9..2223f2adec8 100644
--- a/qa/qa/page/layout/banner.rb
+++ b/qa/qa/page/layout/banner.rb
@@ -3,7 +3,7 @@ module QA
module Layout
class Banner < Page::Base
view 'app/views/layouts/header/_read_only_banner.html.haml' do
- element :flash_notice, ".flash-notice"
+ element :flash_notice, ".flash-notice" # rubocop:disable QA/ElementWithPattern
end
def has_notice?(message)
diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb
index e9e49964e63..97ffe0e5716 100644
--- a/qa/qa/page/main/login.rb
+++ b/qa/qa/page/main/login.rb
@@ -23,6 +23,7 @@ module QA
view 'app/views/devise/shared/_tabs_ldap.html.haml' do
element :ldap_tab
element :standard_tab
+ element :register_tab
end
view 'app/views/devise/shared/_tabs_normal.html.haml' do
@@ -30,19 +31,23 @@ module QA
element :register_tab
end
+ view 'app/views/devise/shared/_omniauth_box.html.haml' do
+ element :saml_login_button
+ end
+
def initialize
# The login page is usually the entry point for all the scenarios so
# we need to wait for the instance to start. That said, in some cases
# we are already logged-in so we check both cases here.
wait(max: 500) do
- page.has_css?('.login-page') ||
- Page::Menu::Main.act { has_personal_area?(wait: 0) }
+ has_css?('.login-page') ||
+ Page::Main::Menu.act { has_personal_area?(wait: 0) }
end
end
def sign_in_using_credentials(user = nil)
# Don't try to log-in if we're already logged-in
- return if Page::Menu::Main.act { has_personal_area?(wait: 0) }
+ return if Page::Main::Menu.act { has_personal_area?(wait: 0) }
using_wait_time 0 do
set_initial_password_if_present
@@ -56,11 +61,11 @@ module QA
end
end
- Page::Menu::Main.act { has_personal_area? }
+ Page::Main::Menu.act { has_personal_area? }
end
def sign_in_using_admin_credentials
- admin = QA::Factory::Resource::User.new.tap do |user|
+ admin = QA::Resource::User.new.tap do |user|
user.username = QA::Runtime::User.admin_username
user.password = QA::Runtime::User.admin_password
end
@@ -71,19 +76,35 @@ module QA
sign_in_using_gitlab_credentials(admin)
end
- Page::Menu::Main.act { has_personal_area? }
+ Page::Main::Menu.act { has_personal_area? }
end
def self.path
'/users/sign_in'
end
+ def has_sign_in_tab?
+ has_element?(:sign_in_tab)
+ end
+
+ def has_ldap_tab?
+ has_element?(:ldap_tab)
+ end
+
+ def has_standard_tab?
+ has_element?(:standard_tab)
+ end
+
def sign_in_tab?
- page.has_button?('Sign in')
+ has_css?(".active", text: 'Sign in')
end
def ldap_tab?
- page.has_link?('LDAP')
+ has_css?(".active", text: 'LDAP')
+ end
+
+ def standard_tab?
+ has_css?(".active", text: 'Standard')
end
def switch_to_sign_in_tab
@@ -91,6 +112,7 @@ module QA
end
def switch_to_register_tab
+ set_initial_password_if_present
click_element :register_tab
end
@@ -112,9 +134,14 @@ module QA
click_element :sign_in_button
end
+ def sign_in_with_saml
+ set_initial_password_if_present
+ click_element :saml_login_button
+ end
+
def sign_in_using_gitlab_credentials(user)
- switch_to_sign_in_tab unless sign_in_tab?
- switch_to_standard_tab if ldap_tab?
+ switch_to_sign_in_tab if has_sign_in_tab?
+ switch_to_standard_tab if has_standard_tab?
fill_element :login_field, user.username
fill_element :password_field, user.password
@@ -122,7 +149,7 @@ module QA
end
def set_initial_password_if_present
- return unless page.has_content?('Change your password')
+ return unless has_content?('Change your password')
fill_element :password_field, Runtime::User.password
fill_element :password_confirmation, Runtime::User.password
diff --git a/qa/qa/page/main/menu.rb b/qa/qa/page/main/menu.rb
new file mode 100644
index 00000000000..cc2724618e9
--- /dev/null
+++ b/qa/qa/page/main/menu.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Main
+ class Menu < Page::Base
+ view 'app/views/layouts/header/_current_user_dropdown.html.haml' do
+ element :user_sign_out_link, 'link_to _("Sign out")' # rubocop:disable QA/ElementWithPattern
+ element :settings_link, 'link_to s_("CurrentUser|Settings")' # rubocop:disable QA/ElementWithPattern
+ end
+
+ view 'app/views/layouts/header/_default.html.haml' do
+ element :navbar
+ element :user_avatar
+ element :user_menu, '.dropdown-menu' # rubocop:disable QA/ElementWithPattern
+ end
+
+ view 'app/views/layouts/nav/_dashboard.html.haml' do
+ element :admin_area_link
+ element :projects_dropdown
+ element :groups_dropdown
+ end
+
+ view 'app/views/layouts/nav/projects_dropdown/_show.html.haml' do
+ element :projects_dropdown_sidebar
+ element :your_projects_link
+ end
+
+ def go_to_groups
+ within_top_menu do
+ click_element :groups_dropdown
+ end
+
+ page.within('.qa-groups-dropdown-sidebar') do
+ click_element :your_groups_link
+ end
+ end
+
+ def go_to_projects
+ within_top_menu do
+ click_element :projects_dropdown
+ end
+
+ page.within('.qa-projects-dropdown-sidebar') do
+ click_element :your_projects_link
+ end
+ end
+
+ def go_to_admin_area
+ within_top_menu { click_element :admin_area_link }
+ end
+
+ def sign_out
+ within_user_menu do
+ click_link 'Sign out'
+ end
+ end
+
+ def go_to_profile_settings
+ within_user_menu do
+ click_link 'Settings'
+ end
+ end
+
+ def has_personal_area?(wait: Capybara.default_max_wait_time)
+ using_wait_time(wait) do
+ page.has_selector?(element_selector_css(:user_avatar))
+ end
+ end
+
+ def has_admin_area_link?(wait: Capybara.default_max_wait_time)
+ using_wait_time(wait) do
+ page.has_selector?(element_selector_css(:admin_area_link))
+ end
+ end
+
+ private
+
+ def within_top_menu
+ page.within('.qa-navbar') do
+ yield
+ end
+ end
+
+ def within_user_menu
+ within_top_menu do
+ click_element :user_avatar
+
+ page.within('.dropdown-menu') do
+ yield
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/main/oauth.rb b/qa/qa/page/main/oauth.rb
index 618f114e058..bc44d274314 100644
--- a/qa/qa/page/main/oauth.rb
+++ b/qa/qa/page/main/oauth.rb
@@ -3,7 +3,7 @@ module QA
module Main
class OAuth < Page::Base
view 'app/views/doorkeeper/authorizations/new.html.haml' do
- element :authorization_button, 'submit_tag _("Authorize")'
+ element :authorization_button, 'submit_tag _("Authorize")' # rubocop:disable QA/ElementWithPattern
end
def needs_authorization?
diff --git a/qa/qa/page/main/sign_up.rb b/qa/qa/page/main/sign_up.rb
index 33ab56236f4..9ca498012eb 100644
--- a/qa/qa/page/main/sign_up.rb
+++ b/qa/qa/page/main/sign_up.rb
@@ -1,25 +1,35 @@
+# frozen_string_literal: true
+
module QA
module Page
module Main
class SignUp < Page::Base
view 'app/views/devise/shared/_signup_box.html.haml' do
- element :name, 'text_field :name'
- element :username, 'text_field :username'
- element :email_field, 'email_field :email'
- element :email_confirmation, 'email_field :email_confirmation'
- element :password, 'password_field :password'
- element :register_button, 'submit "Register"'
+ element :new_user_name
+ element :new_user_username
+ element :new_user_email
+ element :new_user_email_confirmation
+ element :new_user_password
+ element :new_user_register_button
+ element :new_user_accept_terms
end
def sign_up!(user)
- fill_in :new_user_name, with: user.name
- fill_in :new_user_username, with: user.username
- fill_in :new_user_email, with: user.email
- fill_in :new_user_email_confirmation, with: user.email
- fill_in :new_user_password, with: user.password
- click_button 'Register'
+ fill_element :new_user_name, user.name
+ fill_element :new_user_username, user.username
+ fill_element :new_user_email, user.email
+ fill_element :new_user_email_confirmation, user.email
+ fill_element :new_user_password, user.password
+
+ check_element :new_user_accept_terms if has_element?(:new_user_accept_terms)
+
+ signed_in = with_retry do
+ click_element :new_user_register_button
+
+ Page::Main::Menu.act { has_personal_area? }
+ end
- Page::Menu::Main.act { has_personal_area? }
+ raise "Failed to register and sign in" unless signed_in
end
end
end
diff --git a/qa/qa/page/menu/admin.rb b/qa/qa/page/menu/admin.rb
deleted file mode 100644
index 573b98f7386..00000000000
--- a/qa/qa/page/menu/admin.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-module QA
- module Page
- module Menu
- class Admin < Page::Base
- view 'app/views/layouts/nav/sidebar/_admin.html.haml' do
- element :settings, "_('Settings')"
- end
-
- def go_to_settings
- click_link 'Settings'
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/menu/main.rb b/qa/qa/page/menu/main.rb
deleted file mode 100644
index 36e7285f7b7..00000000000
--- a/qa/qa/page/menu/main.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-module QA
- module Page
- module Menu
- class Main < Page::Base
- view 'app/views/layouts/header/_current_user_dropdown.html.haml' do
- element :user_sign_out_link, 'link_to _("Sign out")'
- element :settings_link, 'link_to s_("CurrentUser|Settings")'
- end
-
- view 'app/views/layouts/header/_default.html.haml' do
- element :navbar
- element :user_avatar
- element :user_menu, '.dropdown-menu'
- end
-
- view 'app/views/layouts/nav/_dashboard.html.haml' do
- element :admin_area_link
- element :projects_dropdown
- element :groups_dropdown
- end
-
- view 'app/views/layouts/nav/projects_dropdown/_show.html.haml' do
- element :projects_dropdown_sidebar
- element :your_projects_link
- end
-
- def go_to_groups
- within_top_menu do
- click_element :groups_dropdown
- end
-
- page.within('.qa-groups-dropdown-sidebar') do
- click_element :your_groups_link
- end
- end
-
- def go_to_projects
- within_top_menu do
- click_element :projects_dropdown
- end
-
- page.within('.qa-projects-dropdown-sidebar') do
- click_element :your_projects_link
- end
- end
-
- def go_to_admin_area
- within_top_menu { click_element :admin_area_link }
- end
-
- def sign_out
- within_user_menu do
- click_link 'Sign out'
- end
- end
-
- def go_to_profile_settings
- within_user_menu do
- click_link 'Settings'
- end
- end
-
- def has_personal_area?(wait: Capybara.default_max_wait_time)
- # No need to wait, either we're logged-in, or not.
- using_wait_time(wait) { page.has_selector?('.qa-user-avatar') }
- end
-
- private
-
- def within_top_menu
- page.within('.qa-navbar') do
- yield
- end
- end
-
- def within_user_menu
- within_top_menu do
- click_element :user_avatar
-
- page.within('.dropdown-menu') do
- yield
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/menu/profile.rb b/qa/qa/page/menu/profile.rb
deleted file mode 100644
index 7e24fa85c33..00000000000
--- a/qa/qa/page/menu/profile.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-module QA
- module Page
- module Menu
- class Profile < Page::Base
- view 'app/views/layouts/nav/sidebar/_profile.html.haml' do
- element :access_token_link, 'link_to profile_personal_access_tokens_path'
- element :access_token_title, 'Access Tokens'
- element :top_level_items, '.sidebar-top-level-items'
- element :ssh_keys, 'SSH Keys'
- end
-
- def click_access_tokens
- within_sidebar do
- click_link('Access Tokens')
- end
- end
-
- def click_ssh_keys
- within_sidebar do
- click_link('SSH Keys')
- end
- end
-
- private
-
- def within_sidebar
- page.within('.sidebar-top-level-items') do
- yield
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/menu/side.rb b/qa/qa/page/menu/side.rb
deleted file mode 100644
index a1eedfea42e..00000000000
--- a/qa/qa/page/menu/side.rb
+++ /dev/null
@@ -1,125 +0,0 @@
-module QA
- module Page
- module Menu
- class Side < Page::Base
- view 'app/views/layouts/nav/sidebar/_project.html.haml' do
- element :settings_item
- element :settings_link, 'link_to edit_project_path'
- element :repository_link, "title: _('Repository')"
- element :link_pipelines
- element :pipelines_settings_link, "title: _('CI / CD')"
- element :operations_kubernetes_link, "title: _('Kubernetes')"
- element :issues_link, /link_to.*shortcuts-issues/
- element :issues_link_text, "Issues"
- element :merge_requests_link, /link_to.*shortcuts-merge_requests/
- element :merge_requests_link_text, "Merge Requests"
- element :top_level_items, '.sidebar-top-level-items'
- element :operations_section, "class: 'shortcuts-operations'"
- element :activity_link, "title: _('Activity')"
- element :wiki_link_text, "Wiki"
- element :milestones_link
- end
-
- view 'app/assets/javascripts/fly_out_nav.js' do
- element :fly_out, "classList.add('fly-out-list')"
- end
-
- def click_repository_settings
- hover_settings do
- within_submenu do
- click_link('Repository')
- end
- end
- end
-
- def click_ci_cd_settings
- hover_settings do
- within_submenu do
- click_link('CI / CD')
- end
- end
- end
-
- def click_operations_kubernetes
- hover_operations do
- within_submenu do
- click_link('Kubernetes')
- end
- end
- end
-
- def click_ci_cd_pipelines
- within_sidebar do
- click_element :link_pipelines
- end
- end
-
- def go_to_settings
- within_sidebar do
- click_on 'Settings'
- end
- end
-
- def click_issues
- within_sidebar do
- click_link('Issues')
- end
- end
-
- def click_merge_requests
- within_sidebar do
- click_link('Merge Requests')
- end
- end
-
- def click_milestones
- within_sidebar do
- click_element :milestones_link
- end
- end
-
- def click_wiki
- within_sidebar do
- click_link('Wiki')
- end
- end
-
- private
-
- def hover_settings
- within_sidebar do
- find('.qa-settings-item').hover
-
- yield
- end
- end
-
- def hover_operations
- within_sidebar do
- find('.shortcuts-operations').hover
-
- yield
- end
- end
-
- def within_sidebar
- page.within('.sidebar-top-level-items') do
- yield
- end
- end
-
- def go_to_activity
- within_sidebar do
- click_on 'Activity'
- end
- end
-
- def within_submenu
- page.within('.fly-out-list') do
- yield
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/merge_request/new.rb b/qa/qa/page/merge_request/new.rb
index 83cc4bbbace..1f8f1fbca8e 100644
--- a/qa/qa/page/merge_request/new.rb
+++ b/qa/qa/page/merge_request/new.rb
@@ -22,6 +22,10 @@ module QA
element :issuable_dropdown_menu_milestone
end
+ view 'app/views/shared/issuable/_label_dropdown.html.haml' do
+ element :issuable_label
+ end
+
def create_merge_request
click_element :issuable_create_button
end
@@ -40,6 +44,12 @@ module QA
click_on milestone.title
end
end
+
+ def select_label(label)
+ click_element :issuable_label
+
+ click_link label.title
+ end
end
end
end
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index befb7c1809a..2fd30e15ffb 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -1,28 +1,64 @@
+# frozen_string_literal: true
+
module QA
module Page
module MergeRequest
class Show < Page::Base
view 'app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue' do
element :merge_button
- element :fast_forward_message, 'Fast-forward merge without a merge commit'
+ element :fast_forward_message, 'Fast-forward merge without a merge commit' # rubocop:disable QA/ElementWithPattern
element :merge_moment_dropdown
element :merge_when_pipeline_succeeds_option
element :merge_immediately_option
end
view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do
- element :merged_status, 'The changes were merged into'
+ element :merged_status, 'The changes were merged into' # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue' do
element :mr_rebase_button
- element :no_fast_forward_message, 'Fast-forward merge is not possible'
+ element :no_fast_forward_message, 'Fast-forward merge is not possible' # rubocop:disable QA/ElementWithPattern
end
- view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_squash_before_merge.vue' do
+ view 'app/assets/javascripts/vue_merge_request_widget/components/states/squash_before_merge.vue' do
element :squash_checkbox
end
+ view 'app/views/projects/merge_requests/show.html.haml' do
+ element :notes_tab
+ element :diffs_tab
+ end
+
+ view 'app/assets/javascripts/diffs/components/diff_line_gutter_content.vue' do
+ element :diff_comment
+ end
+
+ view 'app/assets/javascripts/notes/components/comment_form.vue' do
+ element :note_dropdown
+ element :discussion_option
+ end
+
+ view 'app/assets/javascripts/notes/components/note_form.vue' do
+ element :reply_input
+ end
+
+ view 'app/assets/javascripts/notes/components/noteable_discussion.vue' do
+ element :discussion_reply
+ end
+
+ view 'app/assets/javascripts/diffs/components/inline_diff_table_row.vue' do
+ element :new_diff_line
+ end
+
+ view 'app/views/shared/issuable/_sidebar.html.haml' do
+ element :labels_block
+ end
+
+ view 'app/views/projects/merge_requests/_mr_title.html.haml' do
+ element :edit_button
+ end
+
def fast_forward_possible?
!has_text?('Fast-forward merge is not possible')
end
@@ -64,6 +100,13 @@ module QA
end
end
+ def has_label?(label)
+ page.within(element_selector_css(:labels_block)) do
+ element = find('span', text: label)
+ !element.nil?
+ end
+ end
+
def merge!
# The merge button is disabled on load
wait do
@@ -95,6 +138,39 @@ module QA
click_element :squash_checkbox
end
+
+ def go_to_discussions_tab
+ click_element :notes_tab
+ end
+
+ def go_to_diffs_tab
+ click_element :diffs_tab
+ end
+
+ def add_comment_to_diff(text)
+ wait(time: 5) do
+ page.has_text?("No newline at end of file")
+ end
+ all_elements(:new_diff_line).first.hover
+ click_element :diff_comment
+ fill_element :reply_input, text
+ end
+
+ def start_discussion(text)
+ fill_element :comment_input, text
+ click_element :note_dropdown
+ click_element :discussion_option
+ click_element :comment_button
+ end
+
+ def reply_to_discussion(reply_text)
+ all_elements(:discussion_reply).last.click
+ fill_element :reply_input, reply_text
+ end
+
+ def edit!
+ click_element :edit_button
+ end
end
end
end
diff --git a/qa/qa/page/profile/menu.rb b/qa/qa/page/profile/menu.rb
new file mode 100644
index 00000000000..2d503499e13
--- /dev/null
+++ b/qa/qa/page/profile/menu.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Profile
+ class Menu < Page::Base
+ view 'app/views/layouts/nav/sidebar/_profile.html.haml' do
+ element :access_token_link, 'link_to profile_personal_access_tokens_path' # rubocop:disable QA/ElementWithPattern
+ element :access_token_title, 'Access Tokens' # rubocop:disable QA/ElementWithPattern
+ element :top_level_items, '.sidebar-top-level-items' # rubocop:disable QA/ElementWithPattern
+ element :ssh_keys, 'SSH Keys' # rubocop:disable QA/ElementWithPattern
+ end
+
+ def click_access_tokens
+ within_sidebar do
+ click_link('Access Tokens')
+ end
+ end
+
+ def click_ssh_keys
+ within_sidebar do
+ click_link('SSH Keys')
+ end
+ end
+
+ private
+
+ def within_sidebar
+ page.within('.sidebar-top-level-items') do
+ yield
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/profile/personal_access_tokens.rb b/qa/qa/page/profile/personal_access_tokens.rb
index f5ae47dadd0..9191dbe9cf3 100644
--- a/qa/qa/page/profile/personal_access_tokens.rb
+++ b/qa/qa/page/profile/personal_access_tokens.rb
@@ -3,13 +3,13 @@ module QA
module Profile
class PersonalAccessTokens < Page::Base
view 'app/views/shared/_personal_access_tokens_form.html.haml' do
- element :personal_access_token_name_field, 'text_field :name'
- element :create_token_button, 'submit "Create #{type} token"' # rubocop:disable Lint/InterpolationCheck
- element :scopes_api_radios, "label :scopes"
+ element :personal_access_token_name_field, 'text_field :name' # rubocop:disable QA/ElementWithPattern
+ element :create_token_button, 'submit "Create #{type} token"' # rubocop:disable QA/ElementWithPattern, Lint/InterpolationCheck
+ element :scopes_api_radios, "label :scopes" # rubocop:disable QA/ElementWithPattern
end
- view 'app/views/profiles/personal_access_tokens/index.html.haml' do
- element :create_token_field, "text_field_tag 'created-personal-access-token'"
+ view 'app/views/shared/_personal_access_tokens_created_container.html.haml' do
+ element :create_token_field, "text_field_tag 'created-personal-access-token'" # rubocop:disable QA/ElementWithPattern
end
def fill_token_name(name)
diff --git a/qa/qa/page/project/activity.rb b/qa/qa/page/project/activity.rb
index 0196922c889..56fbaa90790 100644
--- a/qa/qa/page/project/activity.rb
+++ b/qa/qa/page/project/activity.rb
@@ -3,7 +3,7 @@ module QA
module Project
class Activity < Page::Base
view 'app/views/shared/_event_filter.html.haml' do
- element :push_events, "event_filter_link EventFilter.push, _('Push events')"
+ element :push_events, "event_filter_link EventFilter::PUSH, _('Push events')" # rubocop:disable QA/ElementWithPattern
end
def go_to_push_events
diff --git a/qa/qa/page/project/fork/new.rb b/qa/qa/page/project/fork/new.rb
index ed92df956bf..140c004b458 100644
--- a/qa/qa/page/project/fork/new.rb
+++ b/qa/qa/page/project/fork/new.rb
@@ -4,7 +4,7 @@ module QA
module Fork
class New < Page::Base
view 'app/views/projects/forks/_fork_button.html.haml' do
- element :namespace, 'link_to project_forks_path'
+ element :namespace, 'link_to project_forks_path' # rubocop:disable QA/ElementWithPattern
end
def choose_namespace(namespace = Runtime::Namespace.path)
diff --git a/qa/qa/page/project/import/github.rb b/qa/qa/page/project/import/github.rb
index 1a410a0f8a5..a3cde73d3f2 100644
--- a/qa/qa/page/project/import/github.rb
+++ b/qa/qa/page/project/import/github.rb
@@ -6,16 +6,16 @@ module QA
include Page::Component::Select2
view 'app/views/import/github/new.html.haml' do
- element :personal_access_token_field, 'text_field_tag :personal_access_token'
- element :list_repos_button, "submit_tag _('List your GitHub repositories')"
+ element :personal_access_token_field, 'text_field_tag :personal_access_token' # rubocop:disable QA/ElementWithPattern
+ element :list_repos_button, "submit_tag _('List your GitHub repositories')" # rubocop:disable QA/ElementWithPattern
end
view 'app/views/import/_githubish_status.html.haml' do
- element :project_import_row, 'data: { qa: { repo_path: repo.full_name } }'
+ element :project_import_row, 'data: { qa: { repo_path: repo.full_name } }' # rubocop:disable QA/ElementWithPattern
element :project_namespace_select
- element :project_namespace_field, 'select_tag :namespace_id'
- element :project_path_field, 'text_field_tag :path, sanitize_project_name(repo.name)'
- element :import_button, "_('Import')"
+ element :project_namespace_field, 'select_tag :namespace_id' # rubocop:disable QA/ElementWithPattern
+ element :project_path_field, 'text_field_tag :path, sanitize_project_name(repo.name)' # rubocop:disable QA/ElementWithPattern
+ element :import_button, "_('Import')" # rubocop:disable QA/ElementWithPattern
end
def add_personal_access_token(personal_access_token)
diff --git a/qa/qa/page/project/issue/index.rb b/qa/qa/page/project/issue/index.rb
index b5903f536a4..1035bf74a43 100644
--- a/qa/qa/page/project/issue/index.rb
+++ b/qa/qa/page/project/issue/index.rb
@@ -4,7 +4,7 @@ module QA
module Issue
class Index < Page::Base
view 'app/views/projects/issues/_issue.html.haml' do
- element :issue_link, 'link_to issue.title'
+ element :issue_link, 'link_to issue.title' # rubocop:disable QA/ElementWithPattern
end
def go_to_issue(title)
diff --git a/qa/qa/page/project/issue/new.rb b/qa/qa/page/project/issue/new.rb
index 7fc581da1ed..03b605ab24b 100644
--- a/qa/qa/page/project/issue/new.rb
+++ b/qa/qa/page/project/issue/new.rb
@@ -4,15 +4,15 @@ module QA
module Issue
class New < Page::Base
view 'app/views/shared/issuable/_form.html.haml' do
- element :submit_issue_button, 'form.submit "Submit'
+ element :submit_issue_button, 'form.submit "Submit' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/shared/issuable/form/_title.html.haml' do
- element :issue_title_textbox, 'form.text_field :title'
+ element :issue_title_textbox, 'form.text_field :title' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/shared/form_elements/_description.html.haml' do
- element :issue_description_textarea, "render 'projects/zen', f: form, attr: :description"
+ element :issue_description_textarea, "render 'projects/zen', f: form, attr: :description" # rubocop:disable QA/ElementWithPattern
end
def add_title(title)
diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb
index 587a02163b9..23def93c7dd 100644
--- a/qa/qa/page/project/issue/show.rb
+++ b/qa/qa/page/project/issue/show.rb
@@ -5,35 +5,49 @@ module QA
module Project
module Issue
class Show < Page::Base
- view 'app/views/projects/issues/show.html.haml' do
- element :issue_details, '.issue-details'
- element :title, '.title'
- end
+ include Page::Component::Issuable::Common
view 'app/views/shared/notes/_form.html.haml' do
- element :new_note_form, 'new-note'
- element :new_note_form, 'attr: :note'
+ element :new_note_form, 'new-note' # rubocop:disable QA/ElementWithPattern
+ element :new_note_form, 'attr: :note' # rubocop:disable QA/ElementWithPattern
end
- view 'app/views/shared/notes/_comment_button.html.haml' do
- element :comment_button, '%strong Comment'
+ view 'app/assets/javascripts/notes/components/comment_form.vue' do
+ element :comment_button
+ element :comment_input
end
- def issue_title
- find('.issue-details .title').text
+ view 'app/assets/javascripts/notes/components/discussion_filter.vue' do
+ element :discussion_filter
+ element :filter_options
end
# Adds a comment to an issue
# attachment option should be an absolute path
def comment(text, attachment: nil)
- fill_in(with: text, name: 'note[note]')
+ fill_element :comment_input, text
unless attachment.nil?
QA::Page::Component::Dropzone.new(self, '.new-note')
.attach_file(attachment)
end
- click_on 'Comment'
+ click_element :comment_button
+ end
+
+ def select_comments_only_filter
+ click_element :discussion_filter
+ all_elements(:filter_options)[1].click
+ end
+
+ def select_history_only_filter
+ click_element :discussion_filter
+ all_elements(:filter_options).last.click
+ end
+
+ def select_all_activities_filter
+ click_element :discussion_filter
+ all_elements(:filter_options).first.click
end
end
end
diff --git a/qa/qa/page/project/job/show.rb b/qa/qa/page/project/job/show.rb
index 228ffd9d381..d688f15914c 100644
--- a/qa/qa/page/project/job/show.rb
+++ b/qa/qa/page/project/job/show.rb
@@ -4,30 +4,39 @@ module QA::Page
COMPLETED_STATUSES = %w[passed failed canceled blocked skipped manual].freeze # excludes created, pending, running
PASSED_STATUS = 'passed'.freeze
- view 'app/views/shared/builds/_build_output.html.haml' do
- element :build_output, '.js-build-output'
- element :loading_animation, '.js-build-refresh'
+ view 'app/assets/javascripts/jobs/components/job_app.vue' do
+ element :loading_animation
+ end
+
+ view 'app/assets/javascripts/jobs/components/job_log.vue' do
+ element :build_trace
end
view 'app/assets/javascripts/vue_shared/components/ci_badge_link.vue' do
- element :status_badge, 'ci-status'
+ element :status_badge
end
def completed?
- COMPLETED_STATUSES.include? find('.ci-status').text
+ COMPLETED_STATUSES.include?(status_badge)
end
def passed?
- find('.ci-status').text == PASSED_STATUS
+ status_badge == PASSED_STATUS
end
def trace_loading?
- has_css?('.js-build-refresh')
+ has_element?(:loading_animation)
end
# Reminder: You may wish to wait for a particular job status before checking output
def output
- find('.js-build-output').text
+ find_element(:build_trace).text
+ end
+
+ private
+
+ def status_badge
+ find_element(:status_badge).text
end
end
end
diff --git a/qa/qa/page/project/menu.rb b/qa/qa/page/project/menu.rb
new file mode 100644
index 00000000000..cb4a10e1b6a
--- /dev/null
+++ b/qa/qa/page/project/menu.rb
@@ -0,0 +1,168 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ class Menu < Page::Base
+ view 'app/views/layouts/nav/sidebar/_project.html.haml' do
+ element :settings_item
+ element :settings_link, 'link_to edit_project_path' # rubocop:disable QA/ElementWithPattern
+ element :repository_link, "title: _('Repository')" # rubocop:disable QA/ElementWithPattern
+ element :link_pipelines
+ element :link_members_settings
+ element :pipelines_settings_link, "title: _('CI / CD')" # rubocop:disable QA/ElementWithPattern
+ element :operations_kubernetes_link, "title: _('Kubernetes')" # rubocop:disable QA/ElementWithPattern
+ element :operations_environments_link
+ element :issues_link, /link_to.*shortcuts-issues/ # rubocop:disable QA/ElementWithPattern
+ element :issues_link_text, "Issues" # rubocop:disable QA/ElementWithPattern
+ element :merge_requests_link, /link_to.*shortcuts-merge_requests/ # rubocop:disable QA/ElementWithPattern
+ element :merge_requests_link_text, "Merge Requests" # rubocop:disable QA/ElementWithPattern
+ element :top_level_items, '.sidebar-top-level-items' # rubocop:disable QA/ElementWithPattern
+ element :operations_section, "class: 'shortcuts-operations'" # rubocop:disable QA/ElementWithPattern
+ element :activity_link, "title: _('Activity')" # rubocop:disable QA/ElementWithPattern
+ element :wiki_link_text, "Wiki" # rubocop:disable QA/ElementWithPattern
+ element :milestones_link
+ element :labels_link
+ end
+
+ view 'app/assets/javascripts/fly_out_nav.js' do
+ element :fly_out, "classList.add('fly-out-list')" # rubocop:disable QA/ElementWithPattern
+ end
+
+ def click_repository_settings
+ hover_settings do
+ within_submenu do
+ click_link('Repository')
+ end
+ end
+ end
+
+ def click_ci_cd_settings
+ hover_settings do
+ within_submenu do
+ click_link('CI / CD')
+ end
+ end
+ end
+
+ def click_operations_environments
+ hover_operations do
+ within_submenu do
+ click_element(:operations_environments_link)
+ end
+ end
+ end
+
+ def click_members_settings
+ hover_settings do
+ within_submenu do
+ click_element :link_members_settings
+ end
+ end
+ end
+
+ def click_operations_kubernetes
+ hover_operations do
+ within_submenu do
+ click_link('Kubernetes')
+ end
+ end
+ end
+
+ def click_ci_cd_pipelines
+ within_sidebar do
+ click_element :link_pipelines
+ end
+ end
+
+ def go_to_settings
+ within_sidebar do
+ click_on 'Settings'
+ end
+ end
+
+ def click_issues
+ within_sidebar do
+ click_link('Issues')
+ end
+ end
+
+ def go_to_labels
+ hover_issues do
+ within_submenu do
+ click_element(:labels_link)
+ end
+ end
+ end
+
+ def click_merge_requests
+ within_sidebar do
+ click_link('Merge Requests')
+ end
+ end
+
+ def click_milestones
+ within_sidebar do
+ click_element :milestones_link
+ end
+ end
+
+ def click_wiki
+ within_sidebar do
+ click_link('Wiki')
+ end
+ end
+
+ def click_repository
+ within_sidebar do
+ click_link('Repository')
+ end
+ end
+
+ private
+
+ def hover_issues
+ within_sidebar do
+ find_element(:issues_item).hover
+
+ yield
+ end
+ end
+
+ def hover_settings
+ within_sidebar do
+ find('.qa-settings-item').hover
+
+ yield
+ end
+ end
+
+ def hover_operations
+ within_sidebar do
+ find('.shortcuts-operations').hover
+
+ yield
+ end
+ end
+
+ def within_sidebar
+ page.within('.sidebar-top-level-items') do
+ yield
+ end
+ end
+
+ def go_to_activity
+ within_sidebar do
+ click_on 'Activity'
+ end
+ end
+
+ def within_submenu
+ page.within('.fly-out-list') do
+ yield
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/new.rb b/qa/qa/page/project/new.rb
index 0766c98da6f..6acc413b586 100644
--- a/qa/qa/page/project/new.rb
+++ b/qa/qa/page/project/new.rb
@@ -5,21 +5,21 @@ module QA
include Page::Component::Select2
view 'app/views/projects/new.html.haml' do
- element :import_project_tab, "Import project"
+ element :import_project_tab, "Import project" # rubocop:disable QA/ElementWithPattern
end
view 'app/views/projects/_new_project_fields.html.haml' do
element :project_namespace_select
- element :project_namespace_field, 'namespaces_options'
- element :project_name, 'text_field :name'
- element :project_path, 'text_field :path'
- element :project_description, 'text_area :description'
- element :project_create_button, "submit 'Create project'"
- element :visibility_radios, 'visibility_level:'
+ element :project_namespace_field, 'namespaces_options' # rubocop:disable QA/ElementWithPattern
+ element :project_name, 'text_field :name' # rubocop:disable QA/ElementWithPattern
+ element :project_path, 'text_field :path' # rubocop:disable QA/ElementWithPattern
+ element :project_description, 'text_area :description' # rubocop:disable QA/ElementWithPattern
+ element :project_create_button, "submit 'Create project'" # rubocop:disable QA/ElementWithPattern
+ element :visibility_radios, 'visibility_level:' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/projects/_import_project_pane.html.haml' do
- element :import_github, "icon('github', text: 'GitHub')"
+ element :import_github, "icon('github', text: 'GitHub')" # rubocop:disable QA/ElementWithPattern
end
def choose_test_namespace
diff --git a/qa/qa/page/project/operations/environments/index.rb b/qa/qa/page/project/operations/environments/index.rb
new file mode 100644
index 00000000000..63965a57edd
--- /dev/null
+++ b/qa/qa/page/project/operations/environments/index.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Operations
+ module Environments
+ class Index < Page::Base
+ view 'app/assets/javascripts/environments/components/environment_item.vue' do
+ element :environment_link
+ end
+
+ def go_to_environment(environment_name)
+ wait(reload: false) do
+ find(element_selector_css(:environment_link), text: environment_name).click
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/operations/environments/show.rb b/qa/qa/page/project/operations/environments/show.rb
new file mode 100644
index 00000000000..aa88c218c89
--- /dev/null
+++ b/qa/qa/page/project/operations/environments/show.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Operations
+ module Environments
+ class Show < Page::Base
+ view 'app/views/projects/environments/_external_url.html.haml' do
+ element :view_deployment
+ end
+
+ def view_deployment(&block)
+ new_window = window_opened_by { click_element(:view_deployment) }
+
+ within_window(new_window, &block) if block
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/operations/kubernetes/add.rb b/qa/qa/page/project/operations/kubernetes/add.rb
index 11ebe10fb18..939f912ea85 100644
--- a/qa/qa/page/project/operations/kubernetes/add.rb
+++ b/qa/qa/page/project/operations/kubernetes/add.rb
@@ -4,8 +4,8 @@ module QA
module Operations
module Kubernetes
class Add < Page::Base
- view 'app/views/projects/clusters/new.html.haml' do
- element :add_existing_cluster_button, "Add existing cluster"
+ view 'app/views/clusters/clusters/new.html.haml' do
+ element :add_existing_cluster_button, "Add existing cluster" # rubocop:disable QA/ElementWithPattern
end
def add_existing_cluster
diff --git a/qa/qa/page/project/operations/kubernetes/add_existing.rb b/qa/qa/page/project/operations/kubernetes/add_existing.rb
index eef82b5f329..f3ab636ecc1 100644
--- a/qa/qa/page/project/operations/kubernetes/add_existing.rb
+++ b/qa/qa/page/project/operations/kubernetes/add_existing.rb
@@ -4,12 +4,13 @@ module QA
module Operations
module Kubernetes
class AddExisting < Page::Base
- view 'app/views/projects/clusters/user/_form.html.haml' do
- element :cluster_name, 'text_field :name'
- element :api_url, 'text_field :api_url'
- element :ca_certificate, 'text_area :ca_cert'
- element :token, 'text_field :token'
- element :add_cluster_button, "submit s_('ClusterIntegration|Add Kubernetes cluster')"
+ view 'app/views/clusters/clusters/user/_form.html.haml' do
+ element :cluster_name, 'text_field :name' # rubocop:disable QA/ElementWithPattern
+ element :api_url, 'text_field :api_url' # rubocop:disable QA/ElementWithPattern
+ element :ca_certificate, 'text_area :ca_cert' # rubocop:disable QA/ElementWithPattern
+ element :token, 'text_field :token' # rubocop:disable QA/ElementWithPattern
+ element :add_cluster_button, "submit s_('ClusterIntegration|Add Kubernetes cluster')" # rubocop:disable QA/ElementWithPattern
+ element :rbac_checkbox
end
def set_cluster_name(name)
@@ -31,6 +32,10 @@ module QA
def add_cluster!
click_on 'Add Kubernetes cluster'
end
+
+ def check_rbac!
+ check_element :rbac_checkbox
+ end
end
end
end
diff --git a/qa/qa/page/project/operations/kubernetes/index.rb b/qa/qa/page/project/operations/kubernetes/index.rb
index 7261b5645da..67a74af1cd2 100644
--- a/qa/qa/page/project/operations/kubernetes/index.rb
+++ b/qa/qa/page/project/operations/kubernetes/index.rb
@@ -4,8 +4,8 @@ module QA
module Operations
module Kubernetes
class Index < Page::Base
- view 'app/views/projects/clusters/_empty_state.html.haml' do
- element :add_kubernetes_cluster_button, "link_to s_('ClusterIntegration|Add Kubernetes cluster')"
+ view 'app/views/clusters/clusters/_empty_state.html.haml' do
+ element :add_kubernetes_cluster_button, "link_to s_('ClusterIntegration|Add Kubernetes cluster')" # rubocop:disable QA/ElementWithPattern
end
def add_kubernetes_cluster
diff --git a/qa/qa/page/project/operations/kubernetes/show.rb b/qa/qa/page/project/operations/kubernetes/show.rb
index e831edeb89e..9e8f9ba79d7 100644
--- a/qa/qa/page/project/operations/kubernetes/show.rb
+++ b/qa/qa/page/project/operations/kubernetes/show.rb
@@ -5,13 +5,13 @@ module QA
module Kubernetes
class Show < Page::Base
view 'app/assets/javascripts/clusters/components/application_row.vue' do
- element :application_row, 'js-cluster-application-row-${this.id}'
- element :install_button, "s__('ClusterIntegration|Install')"
- element :installed_button, "s__('ClusterIntegration|Installed')"
+ element :application_row, 'js-cluster-application-row-${this.id}' # rubocop:disable QA/ElementWithPattern
+ element :install_button, "s__('ClusterIntegration|Install')" # rubocop:disable QA/ElementWithPattern
+ element :installed_button, "s__('ClusterIntegration|Installed')" # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/clusters/components/applications.vue' do
- element :ingress_ip_address, 'id="ingress-ip-address"'
+ element :ingress_ip_address, 'id="ingress-ip-address"' # rubocop:disable QA/ElementWithPattern
end
def install!(application_name)
diff --git a/qa/qa/page/project/pipeline/index.rb b/qa/qa/page/project/pipeline/index.rb
index ce430a2a6ee..19d83ecc4f4 100644
--- a/qa/qa/page/project/pipeline/index.rb
+++ b/qa/qa/page/project/pipeline/index.rb
@@ -2,7 +2,7 @@ module QA::Page
module Project::Pipeline
class Index < QA::Page::Base
view 'app/assets/javascripts/pipelines/components/pipeline_url.vue' do
- element :pipeline_link, 'class="js-pipeline-url-link"'
+ element :pipeline_link, 'class="js-pipeline-url-link"' # rubocop:disable QA/ElementWithPattern
end
def go_to_latest_pipeline
diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb
index babc0079f3f..b22396fd67a 100644
--- a/qa/qa/page/project/pipeline/show.rb
+++ b/qa/qa/page/project/pipeline/show.rb
@@ -2,20 +2,20 @@ module QA::Page
module Project::Pipeline
class Show < QA::Page::Base
view 'app/assets/javascripts/vue_shared/components/header_ci_component.vue' do
- element :pipeline_header, /header class.*ci-header-container.*/
+ element :pipeline_header, /header class.*ci-header-container.*/ # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/pipelines/components/graph/graph_component.vue' do
- element :pipeline_graph, /class.*pipeline-graph.*/
+ element :pipeline_graph, /class.*pipeline-graph.*/ # rubocop:disable QA/ElementWithPattern
end
- view 'app/assets/javascripts/pipelines/components/graph/job_component.vue' do
- element :job_component, /class.*ci-job-component.*/
- element :job_link, /class.*js-pipeline-graph-job-link.*/
+ view 'app/assets/javascripts/pipelines/components/graph/job_item.vue' do
+ element :job_component, /class.*ci-job-component.*/ # rubocop:disable QA/ElementWithPattern
+ element :job_link, /class.*js-pipeline-graph-job-link.*/ # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/vue_shared/components/ci_icon.vue' do
- element :status_icon, 'ci-status-icon-${status}'
+ element :status_icon, 'ci-status-icon-${status}' # rubocop:disable QA/ElementWithPattern
end
def running?
diff --git a/qa/qa/page/project/settings/advanced.rb b/qa/qa/page/project/settings/advanced.rb
index d7b2b66b587..578f097e2dc 100644
--- a/qa/qa/page/project/settings/advanced.rb
+++ b/qa/qa/page/project/settings/advanced.rb
@@ -4,9 +4,9 @@ module QA
module Settings
class Advanced < Page::Base
view 'app/views/projects/edit.html.haml' do
- element :project_path_field, 'text_field :path'
- element :project_name_field, 'text_field :name'
- element :rename_project_button, "submit 'Rename project'"
+ element :project_path_field, 'text_field :path' # rubocop:disable QA/ElementWithPattern
+ element :project_name_field, 'text_field :name' # rubocop:disable QA/ElementWithPattern
+ element :rename_project_button, "submit 'Rename project'" # rubocop:disable QA/ElementWithPattern
end
def rename_to(path)
diff --git a/qa/qa/page/project/settings/ci_cd.rb b/qa/qa/page/project/settings/ci_cd.rb
index 752d3d93407..12c2409a5a7 100644
--- a/qa/qa/page/project/settings/ci_cd.rb
+++ b/qa/qa/page/project/settings/ci_cd.rb
@@ -12,11 +12,11 @@ module QA # rubocop:disable Naming/FileName
end
view 'app/views/projects/settings/ci_cd/_autodevops_form.html.haml' do
- element :enable_auto_devops_field, 'check_box :enabled'
- element :domain_field, 'text_field :domain'
- element :enable_auto_devops_button, "%strong= s_('CICD|Default to Auto DevOps pipeline')"
- element :domain_input, "%strong= _('Domain')"
- element :save_changes_button, "submit _('Save changes')"
+ element :enable_auto_devops_field, 'check_box :enabled' # rubocop:disable QA/ElementWithPattern
+ element :domain_field, 'text_field :domain' # rubocop:disable QA/ElementWithPattern
+ element :enable_auto_devops_button, "%strong= s_('CICD|Default to Auto DevOps pipeline')" # rubocop:disable QA/ElementWithPattern
+ element :domain_input, "%strong= _('Domain')" # rubocop:disable QA/ElementWithPattern
+ element :save_changes_button, "submit _('Save changes')" # rubocop:disable QA/ElementWithPattern
end
def expand_runners_settings(&block)
@@ -25,9 +25,9 @@ module QA # rubocop:disable Naming/FileName
end
end
- def expand_secret_variables(&block)
+ def expand_ci_variables(&block)
expand_section(:variables_settings) do
- Settings::SecretVariables.perform(&block)
+ Settings::CiVariables.perform(&block)
end
end
diff --git a/qa/qa/page/project/settings/ci_variables.rb b/qa/qa/page/project/settings/ci_variables.rb
new file mode 100644
index 00000000000..e7a6e4bf628
--- /dev/null
+++ b/qa/qa/page/project/settings/ci_variables.rb
@@ -0,0 +1,52 @@
+module QA
+ module Page
+ module Project
+ module Settings
+ class CiVariables < Page::Base
+ include Common
+
+ view 'app/views/ci/variables/_variable_row.html.haml' do
+ element :variable_row, '.ci-variable-row-body' # rubocop:disable QA/ElementWithPattern
+ element :variable_key, '.qa-ci-variable-input-key' # rubocop:disable QA/ElementWithPattern
+ element :variable_value, '.qa-ci-variable-input-value' # rubocop:disable QA/ElementWithPattern
+ end
+
+ view 'app/views/ci/variables/_index.html.haml' do
+ element :save_variables, '.js-ci-variables-save-button' # rubocop:disable QA/ElementWithPattern
+ element :reveal_values, '.js-secret-value-reveal-button' # rubocop:disable QA/ElementWithPattern
+ end
+
+ def fill_variable(key, value)
+ keys = all_elements(:ci_variable_input_key)
+ index = keys.size - 1
+
+ # After we fill the key, JS would generate another field so
+ # we need to use the same index to find the corresponding one.
+ keys[index].set(key)
+ node = all_elements(:ci_variable_input_value)[index]
+
+ # Simply run `node.set(value)` is too slow for long text here,
+ # so we need to run JavaScript directly to set the value.
+ # The code was inspired from:
+ # https://github.com/teamcapybara/capybara/blob/679548cea10773d45e32808f4d964377cfe5e892/lib/capybara/selenium/node.rb#L217
+ execute_script("arguments[0].value = #{value.to_json}", node)
+ end
+
+ def save_variables
+ find('.js-ci-variables-save-button').click
+ end
+
+ def reveal_variables
+ find('.js-secret-value-reveal-button').click
+ end
+
+ def variable_value(key)
+ within('.ci-variable-row-body', text: key) do
+ find('.qa-ci-variable-input-value').value
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/settings/common.rb b/qa/qa/page/project/settings/common.rb
index 874fb381554..f3b217677f2 100644
--- a/qa/qa/page/project/settings/common.rb
+++ b/qa/qa/page/project/settings/common.rb
@@ -8,7 +8,7 @@ module QA
def self.included(base)
base.class_eval do
view 'app/views/projects/edit.html.haml' do
- element :advanced_settings_expand, "= expanded ? 'Collapse' : 'Expand'"
+ element :advanced_settings_expand, "= expanded ? 'Collapse' : 'Expand'" # rubocop:disable QA/ElementWithPattern
end
end
end
diff --git a/qa/qa/page/project/settings/deploy_keys.rb b/qa/qa/page/project/settings/deploy_keys.rb
index 90a0e7092bd..3c8c0cbdf7c 100644
--- a/qa/qa/page/project/settings/deploy_keys.rb
+++ b/qa/qa/page/project/settings/deploy_keys.rb
@@ -4,18 +4,18 @@ module QA
module Settings
class DeployKeys < Page::Base
view 'app/views/projects/deploy_keys/_form.html.haml' do
- element :deploy_key_title, 'text_field :title'
- element :deploy_key_key, 'text_area :key'
+ element :deploy_key_title, 'text_field :title' # rubocop:disable QA/ElementWithPattern
+ element :deploy_key_key, 'text_area :key' # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/deploy_keys/components/app.vue' do
- element :deploy_keys_section, /class=".*deploy\-keys.*"/
- element :project_deploy_keys, 'class="qa-project-deploy-keys"'
+ element :deploy_keys_section, /class=".*deploy\-keys.*"/ # rubocop:disable QA/ElementWithPattern
+ element :project_deploy_keys, 'class="qa-project-deploy-keys"' # rubocop:disable QA/ElementWithPattern
end
view 'app/assets/javascripts/deploy_keys/components/key.vue' do
- element :key_title, /class=".*qa-key-title.*"/
- element :key_fingerprint, /class=".*qa-key-fingerprint.*"/
+ element :key_title, /class=".*qa-key-title.*"/ # rubocop:disable QA/ElementWithPattern
+ element :key_fingerprint, /class=".*qa-key-fingerprint.*"/ # rubocop:disable QA/ElementWithPattern
end
def fill_key_title(title)
diff --git a/qa/qa/page/project/settings/deploy_tokens.rb b/qa/qa/page/project/settings/deploy_tokens.rb
new file mode 100644
index 00000000000..2d42372cbc5
--- /dev/null
+++ b/qa/qa/page/project/settings/deploy_tokens.rb
@@ -0,0 +1,64 @@
+module QA
+ module Page
+ module Project
+ module Settings
+ class DeployTokens < Page::Base
+ view 'app/views/projects/deploy_tokens/_form.html.haml' do
+ element :deploy_token_name
+ element :deploy_token_expires_at
+ element :deploy_token_read_repository
+ element :deploy_token_read_registry
+ element :create_deploy_token
+ end
+
+ view 'app/views/projects/deploy_tokens/_new_deploy_token.html.haml' do
+ element :created_deploy_token_section
+ element :deploy_token_user
+ element :deploy_token
+ end
+
+ def fill_token_name(name)
+ fill_element :deploy_token_name, name
+ end
+
+ def fill_token_expires_at(expires_at)
+ fill_element :deploy_token_expires_at, expires_at.to_s + "\n"
+ end
+
+ def fill_scopes(read_repository:, read_registry:)
+ check_element :deploy_token_read_repository if read_repository
+ check_element :deploy_token_read_registry if read_registry
+ end
+
+ def add_token
+ click_element :create_deploy_token
+ end
+
+ def token_username
+ within_new_project_deploy_token do
+ find_element(:deploy_token_user).value
+ end
+ end
+
+ def token_password
+ within_new_project_deploy_token do
+ find_element(:deploy_token).value
+ end
+ end
+
+ private
+
+ def within_new_project_deploy_token
+ wait(reload: false) do
+ has_css?(element_selector_css(:created_deploy_token_section))
+ end
+
+ within_element(:created_deploy_token_section) do
+ yield
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/settings/members.rb b/qa/qa/page/project/settings/members.rb
new file mode 100644
index 00000000000..7fed93ca83f
--- /dev/null
+++ b/qa/qa/page/project/settings/members.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module Settings
+ class Members < Page::Base
+ include Page::Component::UsersSelect
+
+ view 'app/views/projects/project_members/_new_project_member.html.haml' do
+ element :member_select_input
+ element :add_member_button
+ end
+
+ view 'app/views/projects/project_members/_team.html.haml' do
+ element :members_list
+ end
+
+ def add_member(username)
+ select_user :member_select_input, username
+ click_element :add_member_button
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/settings/repository.rb b/qa/qa/page/project/settings/repository.rb
index 1ed5f455a85..53ebe28970b 100644
--- a/qa/qa/page/project/settings/repository.rb
+++ b/qa/qa/page/project/settings/repository.rb
@@ -24,6 +24,12 @@ module QA
ProtectedBranches.perform(&block)
end
end
+
+ def expand_deploy_tokens(&block)
+ expand_section(:deploy_tokens_settings) do
+ DeployTokens.perform(&block)
+ end
+ end
end
end
end
diff --git a/qa/qa/page/project/settings/runners.rb b/qa/qa/page/project/settings/runners.rb
index b41668c94cd..ac930f5385a 100644
--- a/qa/qa/page/project/settings/runners.rb
+++ b/qa/qa/page/project/settings/runners.rb
@@ -4,8 +4,8 @@ module QA
module Settings
class Runners < Page::Base
view 'app/views/ci/runner/_how_to_setup_runner.html.haml' do
- element :registration_token, '%code#registration_token'
- element :coordinator_address, '%code#coordinator_address'
+ element :registration_token, '%code#registration_token' # rubocop:disable QA/ElementWithPattern
+ element :coordinator_address, '%code#coordinator_address' # rubocop:disable QA/ElementWithPattern
end
##
@@ -13,7 +13,7 @@ module QA
#
view 'app/helpers/runners_helper.rb' do
# rubocop:disable Lint/InterpolationCheck
- element :runner_status, 'runner-status-#{status}'
+ element :runner_status, 'runner-status-#{status}' # rubocop:disable QA/ElementWithPattern
# rubocop:enable Lint/InterpolationCheck
end
diff --git a/qa/qa/page/project/settings/secret_variables.rb b/qa/qa/page/project/settings/secret_variables.rb
deleted file mode 100644
index 937ae6797c8..00000000000
--- a/qa/qa/page/project/settings/secret_variables.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-module QA
- module Page
- module Project
- module Settings
- class SecretVariables < Page::Base
- include Common
-
- view 'app/views/ci/variables/_variable_row.html.haml' do
- element :variable_row, '.ci-variable-row-body'
- element :variable_key, '.qa-ci-variable-input-key'
- element :variable_value, '.qa-ci-variable-input-value'
- end
-
- view 'app/views/ci/variables/_index.html.haml' do
- element :save_variables, '.js-secret-variables-save-button'
- element :reveal_values, '.js-secret-value-reveal-button'
- end
-
- def fill_variable(key, value)
- keys = all_elements(:ci_variable_input_key)
- index = keys.size - 1
-
- # After we fill the key, JS would generate another field so
- # we need to use the same index to find the corresponding one.
- keys[index].set(key)
- node = all_elements(:ci_variable_input_value)[index]
-
- # Simply run `node.set(value)` is too slow for long text here,
- # so we need to run JavaScript directly to set the value.
- # The code was inspired from:
- # https://github.com/teamcapybara/capybara/blob/679548cea10773d45e32808f4d964377cfe5e892/lib/capybara/selenium/node.rb#L217
- execute_script("arguments[0].value = #{value.to_json}", node)
- end
-
- def save_variables
- find('.js-secret-variables-save-button').click
- end
-
- def reveal_variables
- find('.js-secret-value-reveal-button').click
- end
-
- def variable_value(key)
- within('.ci-variable-row-body', text: key) do
- find('.qa-ci-variable-input-value').value
- end
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index 267e7bbc249..d6dddf03ffb 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module QA
module Page
module Project
@@ -14,7 +16,7 @@ module QA
view 'app/views/layouts/header/_new_dropdown.haml' do
element :new_menu_toggle
- element :new_issue_link, "link_to _('New issue'), new_project_issue_path(@project)"
+ element :new_issue_link, "link_to _('New issue'), new_project_issue_path(@project)" # rubocop:disable QA/ElementWithPattern
end
view 'app/views/shared/_ref_switcher.html.haml' do
@@ -23,24 +25,40 @@ module QA
end
view 'app/views/projects/buttons/_fork.html.haml' do
- element :fork_label, "%span= s_('ProjectOverview|Fork')"
- element :fork_link, "link_to new_project_fork_path(@project)"
+ element :fork_label, "%span= s_('ProjectOverview|Fork')" # rubocop:disable QA/ElementWithPattern
+ element :fork_link, "link_to new_project_fork_path(@project)" # rubocop:disable QA/ElementWithPattern
end
view 'app/views/projects/_files.html.haml' do
- element :tree_holder, '.tree-holder'
+ element :tree_holder, '.tree-holder' # rubocop:disable QA/ElementWithPattern
+ end
+
+ view 'app/views/projects/buttons/_dropdown.html.haml' do
+ element :create_new_dropdown
+ element :new_file_option
+ end
+
+ view 'app/views/projects/tree/_tree_header.html.haml' do
+ element :web_ide_button
end
- view 'app/presenters/project_presenter.rb' do
- element :new_file_button, "_('New file'),"
+ view 'app/views/projects/tree/_tree_content.html.haml' do
+ element :file_tree
end
def project_name
find('.qa-project-name').text
end
- def go_to_new_file!
- click_on 'New file'
+ def create_new_file!
+ click_element :create_new_dropdown
+ click_element :new_file_option
+ end
+
+ def go_to_file(filename)
+ within_element(:file_tree) do
+ click_on filename
+ end
end
def switch_to_branch(branch_name)
@@ -78,6 +96,10 @@ module QA
def fork_project
click_on 'Fork'
end
+
+ def open_web_ide!
+ click_element :web_ide_button
+ end
end
end
end
diff --git a/qa/qa/page/project/web_ide/edit.rb b/qa/qa/page/project/web_ide/edit.rb
new file mode 100644
index 00000000000..23e580b81b6
--- /dev/null
+++ b/qa/qa/page/project/web_ide/edit.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Project
+ module WebIDE
+ class Edit < Page::Base
+ include Page::Component::DropdownFilter
+
+ view 'app/assets/javascripts/ide/components/ide_tree.vue' do
+ element :new_file
+ end
+
+ view 'app/assets/javascripts/ide/components/ide_tree_list.vue' do
+ element :file_list
+ end
+
+ view 'app/assets/javascripts/ide/components/new_dropdown/modal.vue' do
+ element :full_file_path
+ element :template_list
+ end
+
+ view 'app/assets/javascripts/ide/components/file_templates/bar.vue' do
+ element :file_templates_bar
+ element :file_template_dropdown
+ end
+
+ view 'app/assets/javascripts/ide/components/file_templates/dropdown.vue' do
+ element :dropdown_filter_input
+ end
+
+ view 'app/assets/javascripts/ide/components/commit_sidebar/form.vue' do
+ element :begin_commit_button
+ element :commit_button
+ end
+
+ def has_file?(file_name)
+ within_element(:file_list) do
+ page.has_content? file_name
+ end
+ end
+
+ def create_new_file_from_template(file_name, template)
+ click_element :new_file
+ within_element(:template_list) do
+ begin
+ click_on file_name
+ rescue Capybara::ElementNotFound
+ raise ElementNotFound, %Q(Couldn't find file template named "#{file_name}". Please confirm that it is a valid option.)
+ end
+ end
+
+ wait(reload: false) do
+ within_element(:file_templates_bar) do
+ click_element :file_template_dropdown
+ fill_element :dropdown_filter_input, template
+
+ begin
+ click_on template
+ rescue Capybara::ElementNotFound
+ raise ElementNotFound, %Q(Couldn't find template "#{template}" for #{file_name}. Please confirm that it exists in the list of templates.)
+ end
+ end
+ end
+ end
+
+ def commit_changes
+ click_element :begin_commit_button
+ click_element :commit_button
+
+ wait(reload: false) do
+ page.has_content?('Your changes have been committed')
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/project/wiki/edit.rb b/qa/qa/page/project/wiki/edit.rb
index 6fa45569cc0..8d0eafa1818 100644
--- a/qa/qa/page/project/wiki/edit.rb
+++ b/qa/qa/page/project/wiki/edit.rb
@@ -4,9 +4,9 @@ module QA
module Wiki
class Edit < Page::Base
view 'app/views/projects/wikis/_main_links.html.haml' do
- element :new_page_link, 'New page'
- element :page_history_link, 'Page history'
- element :edit_page_link, 'Edit'
+ element :new_page_link, 'New page' # rubocop:disable QA/ElementWithPattern
+ element :page_history_link, 'Page history' # rubocop:disable QA/ElementWithPattern
+ element :edit_page_link, 'Edit' # rubocop:disable QA/ElementWithPattern
end
def go_to_new_page
diff --git a/qa/qa/page/project/wiki/new.rb b/qa/qa/page/project/wiki/new.rb
index 415b3835538..2498af8600c 100644
--- a/qa/qa/page/project/wiki/new.rb
+++ b/qa/qa/page/project/wiki/new.rb
@@ -4,15 +4,15 @@ module QA
module Wiki
class New < Page::Base
view 'app/views/projects/wikis/_form.html.haml' do
- element :wiki_title_textbox, 'text_field :title'
- element :wiki_content_textarea, "render 'projects/zen', f: f, attr: :content"
- element :wiki_message_textbox, 'text_field :message'
- element :save_changes_button, 'submit _("Save changes")'
- element :create_page_button, 'submit s_("Wiki|Create page")'
+ element :wiki_title_textbox, 'text_field :title' # rubocop:disable QA/ElementWithPattern
+ element :wiki_content_textarea, "render 'projects/zen', f: f, attr: :content" # rubocop:disable QA/ElementWithPattern
+ element :wiki_message_textbox, 'text_field :message' # rubocop:disable QA/ElementWithPattern
+ element :save_changes_button, 'submit _("Save changes")' # rubocop:disable QA/ElementWithPattern
+ element :create_page_button, 'submit s_("Wiki|Create page")' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/shared/empty_states/_wikis.html.haml' do
- element :create_link, 'Create your first page'
+ element :create_link, 'Create your first page' # rubocop:disable QA/ElementWithPattern
end
def go_to_create_first_page
diff --git a/qa/qa/page/project/wiki/show.rb b/qa/qa/page/project/wiki/show.rb
index c47a715687f..a7c4455d080 100644
--- a/qa/qa/page/project/wiki/show.rb
+++ b/qa/qa/page/project/wiki/show.rb
@@ -8,7 +8,7 @@ module QA
include Page::Component::ClonePanel
view 'app/views/projects/wikis/pages.html.haml' do
- element :clone_repository_link, 'Clone repository'
+ element :clone_repository_link, 'Clone repository' # rubocop:disable QA/ElementWithPattern
end
def go_to_clone_repository
diff --git a/qa/qa/resource/README.md b/qa/qa/resource/README.md
new file mode 100644
index 00000000000..4cdeb3f42a2
--- /dev/null
+++ b/qa/qa/resource/README.md
@@ -0,0 +1,392 @@
+# Resource class in GitLab QA
+
+Resources are primarily created using Browser UI steps, but can also
+be created via the API.
+
+## How to properly implement a resource class?
+
+All resource classes should inherit from [`Resource::Base`](./base.rb).
+
+There is only one mandatory method to implement to define a resource class.
+This is the `#fabricate!` method, which is used to build the resource via the
+browser UI. Note that you should only use [Page objects](../page/README.md) to
+interact with a Web page in this method.
+
+Here is an imaginary example:
+
+```ruby
+module QA
+ module Resource
+ class Shirt < Base
+ attr_accessor :name
+
+ def fabricate!
+ Page::Dashboard::Index.perform do |dashboard_index|
+ dashboard_index.go_to_new_shirt
+ end
+
+ Page::Shirt::New.perform do |shirt_new|
+ shirt_new.set_name(name)
+ shirt_new.create_shirt!
+ end
+ end
+ end
+ end
+end
+```
+
+### Define API implementation
+
+A resource class may also implement the three following methods to be able to
+create the resource via the public GitLab API:
+
+- `#api_get_path`: The `GET` path to fetch an existing resource.
+- `#api_post_path`: The `POST` path to create a new resource.
+- `#api_post_body`: The `POST` body (as a Ruby hash) to create a new resource.
+
+Let's take the `Shirt` resource class, and add these three API methods:
+
+```ruby
+module QA
+ module Resource
+ class Shirt < Base
+ attr_accessor :name
+
+ def fabricate!
+ # ... same as before
+ end
+
+ def api_get_path
+ "/shirt/#{name}"
+ end
+
+ def api_post_path
+ "/shirts"
+ end
+
+ def api_post_body
+ {
+ name: name
+ }
+ end
+ end
+ end
+end
+```
+
+The [`Project` resource](./project.rb) is a good real example of Browser
+UI and API implementations.
+
+#### Resource attributes
+
+A resource may need another resource to exist first. For instance, a project
+needs a group to be created in.
+
+To define a resource attribute, you can use the `attribute` method with a
+block using the other resource class to fabricate the resource.
+
+That will allow access to the other resource from your resource object's
+methods. You would usually use it in `#fabricate!`, `#api_get_path`,
+`#api_post_path`, `#api_post_body`.
+
+Let's take the `Shirt` resource class, and add a `project` attribute to it:
+
+```ruby
+module QA
+ module Resource
+ class Shirt < Base
+ attr_accessor :name
+
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-to-create-a-shirt'
+ end
+ end
+
+ def fabricate!
+ project.visit!
+
+ Page::Project::Show.perform do |project_show|
+ project_show.go_to_new_shirt
+ end
+
+ Page::Shirt::New.perform do |shirt_new|
+ shirt_new.set_name(name)
+ shirt_new.create_shirt!
+ end
+ end
+
+ def api_get_path
+ "/project/#{project.path}/shirt/#{name}"
+ end
+
+ def api_post_path
+ "/project/#{project.path}/shirts"
+ end
+
+ def api_post_body
+ {
+ name: name
+ }
+ end
+ end
+ end
+end
+```
+
+**Note that all the attributes are lazily constructed. This means if you want
+a specific attribute to be fabricated first, you'll need to call the
+attribute method first even if you're not using it.**
+
+#### Product data attributes
+
+Once created, you may want to populate a resource with attributes that can be
+found in the Web page, or in the API response.
+For instance, once you create a project, you may want to store its repository
+SSH URL as an attribute.
+
+Again we could use the `attribute` method with a block, using a page object
+to retrieve the data on the page.
+
+Let's take the `Shirt` resource class, and define a `:brand` attribute:
+
+```ruby
+module QA
+ module Resource
+ class Shirt < Base
+ attr_accessor :name
+
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-to-create-a-shirt'
+ end
+ end
+
+ # Attribute populated from the Browser UI (using the block)
+ attribute :brand do
+ Page::Shirt::Show.perform do |shirt_show|
+ shirt_show.fetch_brand_from_page
+ end
+ end
+
+ # ... same as before
+ end
+ end
+end
+```
+
+**Note again that all the attributes are lazily constructed. This means if
+you call `shirt.brand` after moving to the other page, it'll not properly
+retrieve the data because we're no longer on the expected page.**
+
+Consider this:
+
+```ruby
+shirt =
+ QA::Resource::Shirt.fabricate! do |resource|
+ resource.name = "GitLab QA"
+ end
+
+shirt.project.visit!
+
+shirt.brand # => FAIL!
+```
+
+The above example will fail because now we're on the project page, trying to
+construct the brand data from the shirt page, however we moved to the project
+page already. There are two ways to solve this, one is that we could try to
+retrieve the brand before visiting the project again:
+
+```ruby
+shirt =
+ QA::Resource::Shirt.fabricate! do |resource|
+ resource.name = "GitLab QA"
+ end
+
+shirt.brand # => OK!
+
+shirt.project.visit!
+
+shirt.brand # => OK!
+```
+
+The attribute will be stored in the instance therefore all the following calls
+will be fine, using the data previously constructed. If we think that this
+might be too brittle, we could eagerly construct the data right before
+ending fabrication:
+
+```ruby
+module QA
+ module Resource
+ class Shirt < Base
+ # ... same as before
+
+ def fabricate!
+ project.visit!
+
+ Page::Project::Show.perform do |project_show|
+ project_show.go_to_new_shirt
+ end
+
+ Page::Shirt::New.perform do |shirt_new|
+ shirt_new.set_name(name)
+ shirt_new.create_shirt!
+ end
+
+ populate(:brand) # Eagerly construct the data
+ end
+ end
+ end
+end
+```
+
+The `populate` method will iterate through its arguments and call each
+attribute respectively. Here `populate(:brand)` has the same effect as
+just `brand`. Using the populate method makes the intention clearer.
+
+With this, it will make sure we construct the data right after we create the
+shirt. The drawback is that this will always construct the data when the
+resource is fabricated even if we don't need to use the data.
+
+Alternatively, we could just make sure we're on the right page before
+constructing the brand data:
+
+```ruby
+module QA
+ module Resource
+ class Shirt < Base
+ attr_accessor :name
+
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-to-create-a-shirt'
+ end
+ end
+
+ # Attribute populated from the Browser UI (using the block)
+ attribute :brand do
+ back_url = current_url
+ visit!
+
+ Page::Shirt::Show.perform do |shirt_show|
+ shirt_show.fetch_brand_from_page
+ end
+
+ visit(back_url)
+ end
+
+ # ... same as before
+ end
+ end
+end
+```
+
+This will make sure it's on the shirt page before constructing brand, and
+move back to the previous page to avoid breaking the state.
+
+#### Define an attribute based on an API response
+
+Sometimes, you want to define a resource attribute based on the API response
+from its `GET` or `POST` request. For instance, if the creation of a shirt via
+the API returns
+
+```ruby
+{
+ brand: 'a-brand-new-brand',
+ style: 't-shirt',
+ materials: [[:cotton, 80], [:polyamide, 20]]
+}
+```
+
+you may want to store `style` as-is in the resource, and fetch the first value
+of the first `materials` item in a `main_fabric` attribute.
+
+Let's take the `Shirt` resource class, and define a `:style` and a
+`:main_fabric` attributes:
+
+```ruby
+module QA
+ module Resource
+ class Shirt < Base
+ # ... same as before
+
+ # @style from the instance if present,
+ # or fetched from the API response if present,
+ # or a QA::Resource::Base::NoValueError is raised otherwise
+ attribute :style
+
+ # If @main_fabric is not present,
+ # and if the API does not contain this field, this block will be
+ # used to construct the value based on the API response, and
+ # store the result in @main_fabric
+ attribute :main_fabric do
+ api_response.&dig(:materials, 0, 0)
+ end
+
+ # ... same as before
+ end
+ end
+end
+```
+
+**Notes on attributes precedence:**
+
+- resource instance variables have the highest precedence
+- attributes from the API response take precedence over attributes from the
+ block (usually from Browser UI)
+- attributes without a value will raise a `QA::Resource::Base::NoValueError` error
+
+## Creating resources in your tests
+
+To create a resource in your tests, you can call the `.fabricate!` method on
+the resource class.
+Note that if the resource class supports API fabrication, this will use this
+fabrication by default.
+
+Here is an example that will use the API fabrication method under the hood
+since it's supported by the `Shirt` resource class:
+
+```ruby
+my_shirt = Resource::Shirt.fabricate! do |shirt|
+ shirt.name = 'my-shirt'
+end
+
+expect(page).to have_text(my_shirt.name) # => "my-shirt" from the resource's instance variable
+expect(page).to have_text(my_shirt.brand) # => "a-brand-new-brand" from the API response
+expect(page).to have_text(my_shirt.style) # => "t-shirt" from the API response
+expect(page).to have_text(my_shirt.main_fabric) # => "cotton" from the API response via the block
+```
+
+If you explicitly want to use the Browser UI fabrication method, you can call
+the `.fabricate_via_browser_ui!` method instead:
+
+```ruby
+my_shirt = Resource::Shirt.fabricate_via_browser_ui! do |shirt|
+ shirt.name = 'my-shirt'
+end
+
+expect(page).to have_text(my_shirt.name) # => "my-shirt" from the resource's instance variable
+expect(page).to have_text(my_shirt.brand) # => the brand name fetched from the `Page::Shirt::Show` page via the block
+expect(page).to have_text(my_shirt.style) # => QA::Resource::Base::NoValueError will be raised because no API response nor a block is provided
+expect(page).to have_text(my_shirt.main_fabric) # => QA::Resource::Base::NoValueError will be raised because no API response and the block didn't provide a value (because it's also based on the API response)
+```
+
+You can also explicitly use the API fabrication method, by calling the
+`.fabricate_via_api!` method:
+
+```ruby
+my_shirt = Resource::Shirt.fabricate_via_api! do |shirt|
+ shirt.name = 'my-shirt'
+end
+```
+
+In this case, the result will be similar to calling
+`Resource::Shirt.fabricate!`.
+
+## Where to ask for help?
+
+If you need more information, ask for help on `#quality` channel on Slack
+(internal, GitLab Team only).
+
+If you are not a Team Member, and you still need help to contribute, please
+open an issue in GitLab CE issue tracker with the `~QA` label.
diff --git a/qa/qa/resource/api_fabricator.rb b/qa/qa/resource/api_fabricator.rb
new file mode 100644
index 00000000000..98eebac0880
--- /dev/null
+++ b/qa/qa/resource/api_fabricator.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+require 'active_support/core_ext/object/deep_dup'
+require 'capybara/dsl'
+
+module QA
+ module Resource
+ module ApiFabricator
+ include Capybara::DSL
+
+ HTTP_STATUS_OK = 200
+ HTTP_STATUS_CREATED = 201
+
+ ResourceNotFoundError = Class.new(RuntimeError)
+ ResourceFabricationFailedError = Class.new(RuntimeError)
+ ResourceURLMissingError = Class.new(RuntimeError)
+
+ attr_reader :api_resource, :api_response
+
+ def api_support?
+ respond_to?(:api_get_path) &&
+ respond_to?(:api_post_path) &&
+ respond_to?(:api_post_body)
+ end
+
+ def fabricate_via_api!
+ unless api_support?
+ raise NotImplementedError, "Resource #{self.class.name} does not support fabrication via the API!"
+ end
+
+ resource_web_url(api_post)
+ end
+
+ def eager_load_api_client!
+ api_client.tap do |client|
+ # Eager-load the API client so that the personal token creation isn't
+ # taken in account in the actual resource creation timing.
+ client.personal_access_token
+ end
+ end
+
+ private
+
+ include Support::Api
+ attr_writer :api_resource, :api_response
+
+ def resource_web_url(resource)
+ resource.fetch(:web_url) do
+ raise ResourceURLMissingError, "API resource for #{self.class.name} does not expose a `web_url` property: `#{resource}`."
+ end
+ end
+
+ def api_get
+ process_api_response(parse_body(api_get_from(api_get_path)))
+ end
+
+ def api_get_from(get_path)
+ url = Runtime::API::Request.new(api_client, get_path).url
+ response = get(url)
+
+ unless response.code == HTTP_STATUS_OK
+ raise ResourceNotFoundError, "Resource at #{url} could not be found (#{response.code}): `#{response}`."
+ end
+
+ response
+ end
+
+ def api_post
+ response = post(
+ Runtime::API::Request.new(api_client, api_post_path).url,
+ api_post_body)
+
+ unless response.code == HTTP_STATUS_CREATED
+ raise ResourceFabricationFailedError, "Fabrication of #{self.class.name} using the API failed (#{response.code}) with `#{response}`."
+ end
+
+ process_api_response(parse_body(response))
+ end
+
+ def api_client
+ @api_client ||= begin
+ Runtime::API::Client.new(:gitlab, is_new_session: !current_url.start_with?('http'))
+ end
+ end
+
+ def process_api_response(parsed_response)
+ self.api_response = parsed_response
+ self.api_resource = transform_api_resource(parsed_response.deep_dup)
+ end
+
+ def transform_api_resource(api_resource)
+ api_resource
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/base.rb b/qa/qa/resource/base.rb
new file mode 100644
index 00000000000..dcea144ab74
--- /dev/null
+++ b/qa/qa/resource/base.rb
@@ -0,0 +1,155 @@
+# frozen_string_literal: true
+
+require 'forwardable'
+require 'capybara/dsl'
+require 'active_support/core_ext/array/extract_options'
+
+module QA
+ module Resource
+ class Base
+ extend SingleForwardable
+ include ApiFabricator
+ extend Capybara::DSL
+
+ NoValueError = Class.new(RuntimeError)
+
+ def_delegators :evaluator, :attribute
+
+ def fabricate!(*_args)
+ raise NotImplementedError
+ end
+
+ def visit!
+ visit(web_url)
+ end
+
+ def populate(*attributes)
+ attributes.each(&method(:public_send))
+ end
+
+ private
+
+ def populate_attribute(name, block)
+ value = attribute_value(name, block)
+
+ raise NoValueError, "No value was computed for #{name} of #{self.class.name}." unless value
+
+ value
+ end
+
+ def attribute_value(name, block)
+ api_value = api_resource&.dig(name)
+
+ if api_value && block
+ log_having_both_api_result_and_block(name, api_value)
+ end
+
+ api_value || (block && instance_exec(&block))
+ end
+
+ def log_having_both_api_result_and_block(name, api_value)
+ QA::Runtime::Logger.info "<#{self.class}> Attribute #{name.inspect} has both API response `#{api_value}` and a block. API response will be picked. Block will be ignored."
+ end
+
+ def self.fabricate!(*args, &prepare_block)
+ fabricate_via_api!(*args, &prepare_block)
+ rescue NotImplementedError
+ fabricate_via_browser_ui!(*args, &prepare_block)
+ end
+
+ def self.fabricate_via_browser_ui!(*args, &prepare_block)
+ options = args.extract_options!
+ resource = options.fetch(:resource) { new }
+ parents = options.fetch(:parents) { [] }
+
+ do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do
+ log_fabrication(:browser_ui, resource, parents, args) { resource.fabricate!(*args) }
+
+ current_url
+ end
+ end
+
+ def self.fabricate_via_api!(*args, &prepare_block)
+ options = args.extract_options!
+ resource = options.fetch(:resource) { new }
+ parents = options.fetch(:parents) { [] }
+
+ raise NotImplementedError unless resource.api_support?
+
+ resource.eager_load_api_client!
+
+ do_fabricate!(resource: resource, prepare_block: prepare_block, parents: parents) do
+ log_fabrication(:api, resource, parents, args) { resource.fabricate_via_api! }
+ end
+ end
+
+ def self.do_fabricate!(resource:, prepare_block:, parents: [])
+ prepare_block.call(resource) if prepare_block
+
+ resource_web_url = yield
+ resource.web_url = resource_web_url
+
+ resource
+ end
+ private_class_method :do_fabricate!
+
+ def self.log_fabrication(method, resource, parents, args)
+ return yield unless Runtime::Env.debug?
+
+ start = Time.now
+ prefix = "==#{'=' * parents.size}>"
+ msg = [prefix]
+ msg << "Built a #{name}"
+ msg << "as a dependency of #{parents.last}" if parents.any?
+ msg << "via #{method}"
+
+ yield.tap do
+ msg << "in #{Time.now - start} seconds"
+ puts msg.join(' ')
+ puts if parents.empty?
+ end
+ end
+ private_class_method :log_fabrication
+
+ def self.evaluator
+ @evaluator ||= Base::DSL.new(self)
+ end
+ private_class_method :evaluator
+
+ def self.dynamic_attributes
+ const_get(:DynamicAttributes)
+ rescue NameError
+ mod = const_set(:DynamicAttributes, Module.new)
+
+ include mod
+
+ mod
+ end
+
+ def self.attributes_names
+ dynamic_attributes.instance_methods(false).sort.grep_v(/=$/)
+ end
+
+ class DSL
+ def initialize(base)
+ @base = base
+ end
+
+ def attribute(name, &block)
+ @base.dynamic_attributes.module_eval do
+ attr_writer(name)
+
+ define_method(name) do
+ instance_variable_get("@#{name}") ||
+ instance_variable_set(
+ "@#{name}",
+ populate_attribute(name, block))
+ end
+ end
+ end
+ end
+
+ attribute :web_url
+ end
+ end
+end
diff --git a/qa/qa/resource/branch.rb b/qa/qa/resource/branch.rb
new file mode 100644
index 00000000000..bd52c4abe02
--- /dev/null
+++ b/qa/qa/resource/branch.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class Branch < Base
+ attr_accessor :project, :branch_name,
+ :allow_to_push, :allow_to_merge, :protected
+
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'protected-branch-project'
+ end
+ end
+
+ def initialize
+ @branch_name = 'test/branch'
+ @allow_to_push = true
+ @allow_to_merge = true
+ @protected = false
+ end
+
+ def fabricate!
+ project.visit!
+
+ Repository::ProjectPush.fabricate! do |resource|
+ resource.project = project
+ resource.file_name = 'kick-off.txt'
+ resource.commit_message = 'First commit'
+ end
+
+ branch = Repository::ProjectPush.fabricate! do |resource|
+ resource.project = project
+ resource.file_name = 'README.md'
+ resource.commit_message = 'Add readme'
+ resource.branch_name = 'master'
+ resource.new_branch = false
+ resource.remote_branch = @branch_name
+ end
+
+ Page::Project::Show.perform do |page|
+ page.wait { page.has_content?(branch_name) }
+ end
+
+ # The upcoming process will make it access the Protected Branches page,
+ # select the already created branch and protect it according
+ # to `allow_to_push` variable.
+ return branch unless @protected
+
+ Page::Project::Menu.perform(&:click_repository_settings)
+
+ Page::Project::Settings::Repository.perform do |setting|
+ setting.expand_protected_branches do |page|
+ page.select_branch(branch_name)
+
+ if allow_to_push
+ page.allow_devs_and_maintainers_to_push
+ else
+ page.allow_no_one_to_push
+ end
+
+ if allow_to_merge
+ page.allow_devs_and_maintainers_to_merge
+ else
+ page.allow_no_one_to_merge
+ end
+
+ page.wait(reload: false) do
+ !page.first('.btn-success').disabled?
+ end
+
+ page.protect_branch
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/ci_variable.rb b/qa/qa/resource/ci_variable.rb
new file mode 100644
index 00000000000..0570c47d41c
--- /dev/null
+++ b/qa/qa/resource/ci_variable.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class CiVariable < Base
+ attr_accessor :key, :value
+
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-with-ci-variables'
+ resource.description = 'project for adding CI variable test'
+ end
+ end
+
+ def fabricate!
+ project.visit!
+
+ Page::Project::Menu.perform(&:click_ci_cd_settings)
+
+ Page::Project::Settings::CICD.perform do |setting|
+ setting.expand_ci_variables do |page|
+ page.fill_variable(key, value)
+
+ page.save_variables
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/deploy_key.rb b/qa/qa/resource/deploy_key.rb
new file mode 100644
index 00000000000..9ed8fb7726e
--- /dev/null
+++ b/qa/qa/resource/deploy_key.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class DeployKey < Base
+ attr_accessor :title, :key
+
+ attribute :fingerprint do
+ Page::Project::Settings::Repository.perform do |setting|
+ setting.expand_deploy_keys do |key|
+ key_offset = key.key_titles.index do |key_title|
+ key_title.text == title
+ end
+
+ key.key_fingerprints[key_offset].text
+ end
+ end
+ end
+
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-to-deploy'
+ resource.description = 'project for adding deploy key test'
+ end
+ end
+
+ def fabricate!
+ project.visit!
+
+ Page::Project::Menu.perform(&:click_repository_settings)
+
+ Page::Project::Settings::Repository.perform do |setting|
+ setting.expand_deploy_keys do |page|
+ page.fill_key_title(title)
+ page.fill_key_value(key)
+
+ page.add_key
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/deploy_token.rb b/qa/qa/resource/deploy_token.rb
new file mode 100644
index 00000000000..cee4422f6b4
--- /dev/null
+++ b/qa/qa/resource/deploy_token.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class DeployToken < Base
+ attr_accessor :name, :expires_at
+
+ attribute :username do
+ Page::Project::Settings::Repository.perform do |page|
+ page.expand_deploy_tokens do |token|
+ token.token_username
+ end
+ end
+ end
+
+ attribute :password do
+ Page::Project::Settings::Repository.perform do |page|
+ page.expand_deploy_tokens do |token|
+ token.token_password
+ end
+ end
+ end
+
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-to-deploy'
+ resource.description = 'project for adding deploy token test'
+ end
+ end
+
+ def fabricate!
+ project.visit!
+
+ Page::Project::Menu.act do
+ click_repository_settings
+ end
+
+ Page::Project::Settings::Repository.perform do |setting|
+ setting.expand_deploy_tokens do |page|
+ page.fill_token_name(name)
+ page.fill_token_expires_at(expires_at)
+ page.fill_scopes(read_repository: true, read_registry: false)
+
+ page.add_token
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/file.rb b/qa/qa/resource/file.rb
new file mode 100644
index 00000000000..effc5a7940b
--- /dev/null
+++ b/qa/qa/resource/file.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class File < Base
+ attr_accessor :name,
+ :content,
+ :commit_message
+
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-with-new-file'
+ end
+ end
+
+ def initialize
+ @name = 'QA Test - File name'
+ @content = 'QA Test - File content'
+ @commit_message = 'QA Test - Commit message'
+ end
+
+ def fabricate!
+ project.visit!
+
+ Page::Project::Show.perform(&:create_new_file!)
+
+ Page::File::Form.perform do |page|
+ page.add_name(@name)
+ page.add_content(@content)
+ page.add_commit_message(@commit_message)
+ page.commit_changes
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/fork.rb b/qa/qa/resource/fork.rb
new file mode 100644
index 00000000000..9fd66f3a36a
--- /dev/null
+++ b/qa/qa/resource/fork.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class Fork < Base
+ attribute :push do
+ Repository::ProjectPush.fabricate!
+ end
+
+ attribute :user do
+ User.fabricate! do |resource|
+ if Runtime::Env.forker?
+ resource.username = Runtime::Env.forker_username
+ resource.password = Runtime::Env.forker_password
+ end
+ end
+ end
+
+ def fabricate!
+ populate(:push, :user)
+
+ # Sign out as admin and sign is as the fork user
+ Page::Main::Menu.perform(&:sign_out)
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform do |login|
+ login.sign_in_using_credentials(user)
+ end
+
+ push.project.visit!
+
+ Page::Project::Show.perform(&:fork_project)
+
+ Page::Project::Fork::New.perform do |fork_new|
+ fork_new.choose_namespace(user.name)
+ end
+
+ Page::Layout::Banner.perform do |page|
+ page.has_notice?('The project was successfully forked.')
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/group.rb b/qa/qa/resource/group.rb
new file mode 100644
index 00000000000..a7a6f931e28
--- /dev/null
+++ b/qa/qa/resource/group.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class Group < Base
+ attr_accessor :path, :description
+
+ attribute :sandbox do
+ Sandbox.fabricate!
+ end
+
+ attribute :id
+
+ def initialize
+ @path = Runtime::Namespace.name
+ @description = "QA test run at #{Runtime::Namespace.time}"
+ end
+
+ def fabricate!
+ sandbox.visit!
+
+ Page::Group::Show.perform do |group_show|
+ if group_show.has_subgroup?(path)
+ group_show.go_to_subgroup(path)
+ else
+ group_show.go_to_new_subgroup
+
+ Page::Group::New.perform do |group_new|
+ group_new.set_path(path)
+ group_new.set_description(description)
+ group_new.set_visibility('Public')
+ group_new.create
+ end
+
+ # Ensure that the group was actually created
+ group_show.wait(time: 1) do
+ group_show.has_text?(path) &&
+ group_show.has_new_project_or_subgroup_dropdown?
+ end
+ end
+ end
+ end
+
+ def fabricate_via_api!
+ resource_web_url(api_get)
+ rescue ResourceNotFoundError
+ super
+ end
+
+ def api_get_path
+ "/groups/#{CGI.escape("#{sandbox.path}/#{path}")}"
+ end
+
+ def api_members_path
+ "#{api_get_path}/members"
+ end
+
+ def api_post_path
+ '/groups'
+ end
+
+ def api_post_body
+ {
+ parent_id: sandbox.id,
+ path: path,
+ name: path,
+ visibility: 'public'
+ }
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/issue.rb b/qa/qa/resource/issue.rb
new file mode 100644
index 00000000000..2c2f27fe231
--- /dev/null
+++ b/qa/qa/resource/issue.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class Issue < Base
+ attr_writer :description
+
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-for-issues'
+ resource.description = 'project for adding issues'
+ end
+ end
+
+ attribute :title
+
+ def fabricate!
+ project.visit!
+
+ Page::Project::Show.perform(&:go_to_new_issue)
+
+ Page::Project::Issue::New.perform do |page|
+ page.add_title(@title)
+ page.add_description(@description)
+ page.create_new_issue
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/kubernetes_cluster.rb b/qa/qa/resource/kubernetes_cluster.rb
new file mode 100644
index 00000000000..96c8843fb99
--- /dev/null
+++ b/qa/qa/resource/kubernetes_cluster.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'securerandom'
+
+module QA
+ module Resource
+ class KubernetesCluster < Base
+ attr_writer :project, :cluster,
+ :install_helm_tiller, :install_ingress, :install_prometheus, :install_runner
+
+ attribute :ingress_ip do
+ Page::Project::Operations::Kubernetes::Show.perform(&:ingress_ip)
+ end
+
+ def fabricate!
+ @project.visit!
+
+ Page::Project::Menu.perform(
+ &:click_operations_kubernetes)
+
+ Page::Project::Operations::Kubernetes::Index.perform(
+ &:add_kubernetes_cluster)
+
+ Page::Project::Operations::Kubernetes::Add.perform(
+ &:add_existing_cluster)
+
+ Page::Project::Operations::Kubernetes::AddExisting.perform do |page|
+ page.set_cluster_name(@cluster.cluster_name)
+ page.set_api_url(@cluster.api_url)
+ page.set_ca_certificate(@cluster.ca_certificate)
+ page.set_token(@cluster.token)
+ page.check_rbac! if @cluster.rbac
+ page.add_cluster!
+ end
+
+ if @install_helm_tiller
+ Page::Project::Operations::Kubernetes::Show.perform do |page|
+ # We must wait a few seconds for permissions to be set up correctly for new cluster
+ sleep 10
+
+ # Helm must be installed before everything else
+ page.install!(:helm)
+ page.await_installed(:helm)
+
+ page.install!(:ingress) if @install_ingress
+ page.install!(:prometheus) if @install_prometheus
+ page.install!(:runner) if @install_runner
+
+ page.await_installed(:ingress) if @install_ingress
+ page.await_installed(:prometheus) if @install_prometheus
+ page.await_installed(:runner) if @install_runner
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/label.rb b/qa/qa/resource/label.rb
new file mode 100644
index 00000000000..c0869cb1f2a
--- /dev/null
+++ b/qa/qa/resource/label.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'securerandom'
+
+module QA
+ module Resource
+ class Label < Base
+ attr_accessor :description, :color
+
+ attribute :title
+
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-with-label'
+ end
+ end
+
+ def initialize
+ @title = "qa-test-#{SecureRandom.hex(8)}"
+ @description = 'This is a test label'
+ @color = '#0033CC'
+ end
+
+ def fabricate!
+ project.visit!
+
+ Page::Project::Menu.perform(&:go_to_labels)
+ Page::Label::Index.perform(&:go_to_new_label)
+
+ Page::Label::New.perform do |page|
+ page.fill_title(@title)
+ page.fill_description(@description)
+ page.fill_color(@color)
+ page.create_label
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/merge_request.rb b/qa/qa/resource/merge_request.rb
new file mode 100644
index 00000000000..77afb3cfcba
--- /dev/null
+++ b/qa/qa/resource/merge_request.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'securerandom'
+
+module QA
+ module Resource
+ class MergeRequest < Base
+ attr_accessor :title,
+ :description,
+ :source_branch,
+ :target_branch,
+ :assignee,
+ :milestone,
+ :labels,
+ :file_name,
+ :file_content
+
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-with-merge-request'
+ end
+ end
+
+ attribute :target do
+ project.visit!
+
+ Repository::ProjectPush.fabricate! do |resource|
+ resource.project = project
+ resource.branch_name = 'master'
+ resource.remote_branch = target_branch
+ end
+ end
+
+ attribute :source do
+ Repository::ProjectPush.fabricate! do |resource|
+ resource.project = project
+ resource.branch_name = target_branch
+ resource.remote_branch = source_branch
+ resource.new_branch = false
+ resource.file_name = file_name
+ resource.file_content = file_content
+ end
+ end
+
+ def initialize
+ @title = 'QA test - merge request'
+ @description = 'This is a test merge request'
+ @source_branch = "qa-test-feature-#{SecureRandom.hex(8)}"
+ @target_branch = "master"
+ @assignee = nil
+ @milestone = nil
+ @labels = []
+ @file_name = "added_file.txt"
+ @file_content = "File Added"
+ end
+
+ def fabricate!
+ populate(:target, :source)
+
+ project.visit!
+ Page::Project::Show.perform(&:new_merge_request)
+ Page::MergeRequest::New.perform do |page|
+ page.fill_title(@title)
+ page.fill_description(@description)
+ page.choose_milestone(@milestone) if @milestone
+ labels.each do |label|
+ page.select_label(label)
+ end
+
+ page.create_merge_request
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/merge_request_from_fork.rb b/qa/qa/resource/merge_request_from_fork.rb
new file mode 100644
index 00000000000..f91ae299d76
--- /dev/null
+++ b/qa/qa/resource/merge_request_from_fork.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class MergeRequestFromFork < MergeRequest
+ attr_accessor :fork_branch
+
+ attribute :fork do
+ Fork.fabricate!
+ end
+
+ attribute :push do
+ Repository::ProjectPush.fabricate! do |resource|
+ resource.project = fork
+ resource.branch_name = fork_branch
+ resource.file_name = 'file2.txt'
+ resource.user = fork.user
+ end
+ end
+
+ def fabricate!
+ populate(:push)
+
+ fork.visit!
+
+ Page::Project::Show.perform(&:new_merge_request)
+ Page::MergeRequest::New.perform(&:create_merge_request)
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/personal_access_token.rb b/qa/qa/resource/personal_access_token.rb
new file mode 100644
index 00000000000..b8dd0a3562f
--- /dev/null
+++ b/qa/qa/resource/personal_access_token.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ ##
+ # Create a personal access token that can be used by the api
+ #
+ class PersonalAccessToken < Base
+ attr_accessor :name
+
+ attribute :access_token do
+ Page::Profile::PersonalAccessTokens.perform(&:created_access_token)
+ end
+
+ def fabricate!
+ Page::Main::Menu.perform(&:go_to_profile_settings)
+ Page::Profile::Menu.perform(&:click_access_tokens)
+
+ Page::Profile::PersonalAccessTokens.perform do |page|
+ page.fill_token_name(name || 'api-test-token')
+ page.check_api
+ page.create_token
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
new file mode 100644
index 00000000000..7fdf69278f9
--- /dev/null
+++ b/qa/qa/resource/project.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require 'securerandom'
+
+module QA
+ module Resource
+ class Project < Base
+ attribute :name
+ attribute :description
+
+ attribute :group do
+ Group.fabricate!
+ end
+
+ attribute :repository_ssh_location do
+ Page::Project::Show.perform do |page|
+ page.choose_repository_clone_ssh
+ page.repository_location
+ end
+ end
+
+ attribute :repository_http_location do
+ Page::Project::Show.perform do |page|
+ page.choose_repository_clone_http
+ page.repository_location
+ end
+ end
+
+ def initialize
+ @description = 'My awesome project'
+ end
+
+ def name=(raw_name)
+ @name = "#{raw_name}-#{SecureRandom.hex(8)}"
+ end
+
+ def fabricate!
+ group.visit!
+
+ Page::Group::Show.perform(&:go_to_new_project)
+
+ Page::Project::New.perform do |page|
+ page.choose_test_namespace
+ page.choose_name(@name)
+ page.add_description(@description)
+ page.set_visibility('Public')
+ page.create_new_project
+ end
+ end
+
+ def api_get_path
+ "/projects/#{name}"
+ end
+
+ def api_post_path
+ '/projects'
+ end
+
+ def api_post_body
+ {
+ namespace_id: group.id,
+ path: name,
+ name: name,
+ description: description,
+ visibility: 'public'
+ }
+ end
+
+ private
+
+ def transform_api_resource(api_resource)
+ api_resource[:repository_ssh_location] =
+ Git::Location.new(api_resource[:ssh_url_to_repo])
+ api_resource[:repository_http_location] =
+ Git::Location.new(api_resource[:http_url_to_repo])
+ api_resource
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/project_imported_from_github.rb b/qa/qa/resource/project_imported_from_github.rb
new file mode 100644
index 00000000000..3f02fe885a9
--- /dev/null
+++ b/qa/qa/resource/project_imported_from_github.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'securerandom'
+
+module QA
+ module Resource
+ class ProjectImportedFromGithub < Project
+ attr_accessor :name
+ attr_writer :personal_access_token, :github_repository_path
+
+ attribute :group do
+ Group.fabricate!
+ end
+
+ def fabricate!
+ group.visit!
+
+ Page::Group::Show.perform(&:go_to_new_project)
+
+ Page::Project::New.perform do |page|
+ page.go_to_import_project
+ end
+
+ Page::Project::New.perform do |page|
+ page.go_to_github_import
+ end
+
+ Page::Project::Import::Github.perform do |page|
+ page.add_personal_access_token(@personal_access_token)
+ page.list_repos
+ page.import!(@github_repository_path, @name)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/project_milestone.rb b/qa/qa/resource/project_milestone.rb
new file mode 100644
index 00000000000..a4d6657caff
--- /dev/null
+++ b/qa/qa/resource/project_milestone.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class ProjectMilestone < Base
+ attr_reader :title
+ attr_accessor :description
+
+ attribute :project do
+ Project.fabricate!
+ end
+
+ def title=(title)
+ @title = "#{title}-#{SecureRandom.hex(4)}"
+ @description = 'A milestone'
+ end
+
+ def fabricate!
+ project.visit!
+
+ Page::Project::Menu.perform do |page|
+ page.click_issues
+ page.click_milestones
+ end
+
+ Page::Project::Milestone::Index.perform(&:click_new_milestone)
+
+ Page::Project::Milestone::New.perform do |milestone_new|
+ milestone_new.set_title(@title)
+ milestone_new.set_description(@description)
+ milestone_new.create_new_milestone
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/repository/project_push.rb b/qa/qa/resource/repository/project_push.rb
new file mode 100644
index 00000000000..c9fafe3419f
--- /dev/null
+++ b/qa/qa/resource/repository/project_push.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ module Repository
+ class ProjectPush < Repository::Push
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-with-code'
+ resource.description = 'Project with repository'
+ end
+ end
+
+ def initialize
+ @file_name = 'file.txt'
+ @file_content = '# This is test project'
+ @commit_message = "This is a test commit"
+ @branch_name = 'master'
+ @new_branch = true
+ end
+
+ def repository_http_uri
+ @repository_http_uri ||= begin
+ project.visit!
+ Page::Project::Show.act do
+ choose_repository_clone_http
+ repository_location.uri
+ end
+ end
+ end
+
+ def repository_ssh_uri
+ @repository_ssh_uri ||= begin
+ project.visit!
+ Page::Project::Show.act do
+ choose_repository_clone_ssh
+ repository_location.uri
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/repository/push.rb b/qa/qa/resource/repository/push.rb
new file mode 100644
index 00000000000..c14d97ff7fb
--- /dev/null
+++ b/qa/qa/resource/repository/push.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require 'pathname'
+
+module QA
+ module Resource
+ module Repository
+ class Push < Base
+ attr_accessor :file_name, :file_content, :commit_message,
+ :branch_name, :new_branch, :output, :repository_http_uri,
+ :repository_ssh_uri, :ssh_key, :user
+
+ attr_writer :remote_branch
+
+ def initialize
+ @file_name = 'file.txt'
+ @file_content = '# This is test file'
+ @commit_message = "This is a test commit"
+ @branch_name = 'master'
+ @new_branch = true
+ @repository_http_uri = ""
+ @ssh_key = nil
+ end
+
+ def remote_branch
+ @remote_branch ||= branch_name
+ end
+
+ def directory=(dir)
+ raise "Must set directory as a Pathname" unless dir.is_a?(Pathname)
+
+ @directory = dir
+ end
+
+ def files=(files)
+ if !files.is_a?(Array) || files.empty?
+ raise ArgumentError, "Please provide an array of hashes e.g.: [{name: 'file1', content: 'foo'}]"
+ end
+
+ @files = files
+ end
+
+ def fabricate!
+ Git::Repository.perform do |repository|
+ if ssh_key
+ repository.uri = repository_ssh_uri
+ repository.use_ssh_key(ssh_key)
+ else
+ repository.uri = repository_http_uri
+ repository.use_default_credentials unless user
+ end
+
+ username = 'GitLab QA'
+ email = 'root@gitlab.com'
+
+ if user
+ repository.username = user.username
+ repository.password = user.password
+ username = user.name
+ email = user.email
+ end
+
+ repository.clone
+ repository.configure_identity(username, email)
+
+ if new_branch
+ repository.checkout_new_branch(branch_name)
+ else
+ repository.checkout(branch_name)
+ end
+
+ if @directory
+ @directory.each_child do |f|
+ repository.add_file(f.basename, f.read) if f.file?
+ end
+ elsif @files
+ @files.each do |f|
+ repository.add_file(f[:name], f[:content])
+ end
+ else
+ repository.add_file(file_name, file_content)
+ end
+
+ repository.commit(commit_message)
+ @output = repository.push_changes("#{branch_name}:#{remote_branch}")
+
+ repository.delete_ssh_key
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/repository/wiki_push.rb b/qa/qa/resource/repository/wiki_push.rb
new file mode 100644
index 00000000000..f1c39d507fe
--- /dev/null
+++ b/qa/qa/resource/repository/wiki_push.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ module Repository
+ class WikiPush < Repository::Push
+ attribute :wiki do
+ Wiki.fabricate! do |resource|
+ resource.title = 'Home'
+ resource.content = '# My First Wiki Content'
+ resource.message = 'Update home'
+ end
+ end
+
+ def initialize
+ @file_name = 'Home.md'
+ @file_content = '# Welcome to My Wiki'
+ @commit_message = 'Updating Home Page'
+ @branch_name = 'master'
+ @new_branch = false
+ end
+
+ def repository_http_uri
+ @repository_http_uri ||= begin
+ wiki.visit!
+ Page::Project::Wiki::Show.act do
+ go_to_clone_repository
+ choose_repository_clone_http
+ repository_location.uri
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/runner.rb b/qa/qa/resource/runner.rb
new file mode 100644
index 00000000000..08ae3f22117
--- /dev/null
+++ b/qa/qa/resource/runner.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'securerandom'
+
+module QA
+ module Resource
+ class Runner < Base
+ attr_writer :name, :tags, :image
+
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-with-ci-cd'
+ resource.description = 'Project with CI/CD Pipelines'
+ end
+ end
+
+ def name
+ @name || "qa-runner-#{SecureRandom.hex(4)}"
+ end
+
+ def tags
+ @tags || %w[qa e2e]
+ end
+
+ def image
+ @image || 'gitlab/gitlab-runner:alpine'
+ end
+
+ def fabricate!
+ project.visit!
+
+ Page::Project::Menu.perform(&:click_ci_cd_settings)
+
+ Service::Runner.new(name).tap do |runner|
+ Page::Project::Settings::CICD.perform do |settings|
+ settings.expand_runners_settings do |runners|
+ runner.pull
+ runner.token = runners.registration_token
+ runner.address = runners.coordinator_address
+ runner.tags = tags
+ runner.image = image
+ runner.register!
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/sandbox.rb b/qa/qa/resource/sandbox.rb
new file mode 100644
index 00000000000..41ce857a8b8
--- /dev/null
+++ b/qa/qa/resource/sandbox.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ ##
+ # Ensure we're in our sandbox namespace, either by navigating to it or by
+ # creating it if it doesn't yet exist.
+ #
+ class Sandbox < Base
+ attr_reader :path
+
+ attribute :id
+
+ def initialize
+ @path = Runtime::Namespace.sandbox_name
+ end
+
+ def fabricate!
+ Page::Main::Menu.perform(&:go_to_groups)
+
+ Page::Dashboard::Groups.perform do |page|
+ if page.has_group?(path)
+ page.go_to_group(path)
+ else
+ page.go_to_new_group
+
+ Page::Group::New.perform do |group|
+ group.set_path(path)
+ group.set_description('GitLab QA Sandbox Group')
+ group.set_visibility('Public')
+ group.create
+ end
+ end
+ end
+ end
+
+ def fabricate_via_api!
+ resource_web_url(api_get)
+ rescue ResourceNotFoundError
+ super
+ end
+
+ def api_get_path
+ "/groups/#{path}"
+ end
+
+ def api_post_path
+ '/groups'
+ end
+
+ def api_post_body
+ {
+ path: path,
+ name: path,
+ visibility: 'public'
+ }
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/settings/hashed_storage.rb b/qa/qa/resource/settings/hashed_storage.rb
new file mode 100644
index 00000000000..40c06768ffe
--- /dev/null
+++ b/qa/qa/resource/settings/hashed_storage.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ module Settings
+ class HashedStorage < Base
+ def fabricate!(*traits)
+ raise ArgumentError unless traits.include?(:enabled)
+
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+ Page::Main::Menu.perform(&:go_to_admin_area)
+ Page::Admin::Menu.perform(&:go_to_repository_settings)
+
+ Page::Admin::Settings::Repository.perform do |setting|
+ setting.expand_repository_storage do |page|
+ page.enable_hashed_storage
+ page.save_settings
+ end
+ end
+
+ QA::Page::Main::Menu.perform(&:sign_out)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/ssh_key.rb b/qa/qa/resource/ssh_key.rb
new file mode 100644
index 00000000000..c6c97c8532f
--- /dev/null
+++ b/qa/qa/resource/ssh_key.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class SSHKey < Base
+ extend Forwardable
+
+ attr_accessor :title
+
+ def_delegators :key, :private_key, :public_key, :fingerprint
+
+ def key
+ @key ||= Runtime::Key::RSA.new
+ end
+
+ def fabricate!
+ Page::Main::Menu.perform(&:go_to_profile_settings)
+ Page::Profile::Menu.perform(&:click_ssh_keys)
+
+ Page::Profile::SSHKeys.perform do |page|
+ page.add_key(public_key, title)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/user.rb b/qa/qa/resource/user.rb
new file mode 100644
index 00000000000..c26f0c84a1f
--- /dev/null
+++ b/qa/qa/resource/user.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+require 'securerandom'
+
+module QA
+ module Resource
+ class User < Base
+ attr_reader :unique_id
+ attr_writer :username, :password, :name, :email
+ attr_accessor :provider, :extern_uid
+
+ def initialize
+ @unique_id = SecureRandom.hex(8)
+ end
+
+ def username
+ @username ||= "qa-user-#{unique_id}"
+ end
+
+ def password
+ @password ||= 'password'
+ end
+
+ def name
+ @name ||= username
+ end
+
+ def email
+ @email ||= "#{username}@example.com"
+ end
+
+ def credentials_given?
+ defined?(@username) && defined?(@password)
+ end
+
+ def fabricate!
+ # Don't try to log-out if we're not logged-in
+ if Page::Main::Menu.perform { |p| p.has_personal_area?(wait: 0) }
+ Page::Main::Menu.perform { |main| main.sign_out }
+ end
+
+ if credentials_given?
+ Page::Main::Login.perform do |login|
+ login.sign_in_using_credentials(self)
+ end
+ else
+ Page::Main::Login.perform do |login|
+ login.switch_to_register_tab
+ end
+ Page::Main::SignUp.perform do |signup|
+ signup.sign_up!(self)
+ end
+ end
+ end
+
+ def fabricate_via_api!
+ resource_web_url(api_get)
+ rescue ResourceNotFoundError
+ super
+ end
+
+ def api_get_path
+ "/users/#{fetch_id(username)}"
+ end
+
+ def api_post_path
+ '/users'
+ end
+
+ def api_post_body
+ {
+ email: email,
+ password: password,
+ username: username,
+ name: name,
+ skip_confirmation: true
+ }.merge(ldap_post_body)
+ end
+
+ def self.fabricate_or_use(username, password)
+ if Runtime::Env.signup_disabled?
+ self.new.tap do |user|
+ user.username = username
+ user.password = password
+ end
+ else
+ self.fabricate!
+ end
+ end
+
+ private
+
+ def ldap_post_body
+ return {} unless extern_uid && provider
+
+ {
+ extern_uid: extern_uid,
+ provider: provider
+ }
+ end
+
+ def fetch_id(username)
+ users = parse_body(api_get_from("/users?username=#{username}"))
+
+ unless users.size == 1 && users.first[:username] == username
+ raise ResourceNotFoundError, "Expected one user with username #{username} but found: `#{users}`."
+ end
+
+ users.first[:id]
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/wiki.rb b/qa/qa/resource/wiki.rb
new file mode 100644
index 00000000000..e942e9718a0
--- /dev/null
+++ b/qa/qa/resource/wiki.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class Wiki < Base
+ attr_accessor :title, :content, :message
+
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-for-wikis'
+ resource.description = 'project for adding wikis'
+ end
+ end
+
+ def fabricate!
+ project.visit!
+
+ Page::Project::Menu.perform { |menu_side| menu_side.click_wiki }
+
+ Page::Project::Wiki::New.perform do |wiki_new|
+ wiki_new.go_to_create_first_page
+ wiki_new.set_title(@title)
+ wiki_new.set_content(@content)
+ wiki_new.set_message(@message)
+ wiki_new.create_new_page
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/runtime/api/client.rb b/qa/qa/runtime/api/client.rb
index 02015e23ad8..aff84c89f0e 100644
--- a/qa/qa/runtime/api/client.rb
+++ b/qa/qa/runtime/api/client.rb
@@ -6,33 +6,34 @@ module QA
class Client
attr_reader :address
- def initialize(address = :gitlab, personal_access_token: nil)
+ def initialize(address = :gitlab, personal_access_token: nil, is_new_session: true)
@address = address
@personal_access_token = personal_access_token
+ @is_new_session = is_new_session
end
def personal_access_token
- @personal_access_token ||= get_personal_access_token
- end
-
- def get_personal_access_token
- # you can set the environment variable PERSONAL_ACCESS_TOKEN
- # to use a specific access token rather than create one from the UI
- if Runtime::Env.personal_access_token
- Runtime::Env.personal_access_token
- else
- create_personal_access_token
+ @personal_access_token ||= begin
+ # you can set the environment variable PERSONAL_ACCESS_TOKEN
+ # to use a specific access token rather than create one from the UI
+ Runtime::Env.personal_access_token ||= create_personal_access_token
end
end
private
def create_personal_access_token
- Runtime::Browser.visit(@address, Page::Main::Login) do
- Page::Main::Login.act { sign_in_using_credentials }
- Factory::Resource::PersonalAccessToken.fabricate!.access_token
+ if @is_new_session
+ Runtime::Browser.visit(@address, Page::Main::Login) { do_create_personal_access_token }
+ else
+ do_create_personal_access_token
end
end
+
+ def do_create_personal_access_token
+ Page::Main::Login.act { sign_in_using_credentials }
+ Resource::PersonalAccessToken.fabricate!.access_token
+ end
end
end
end
diff --git a/qa/qa/runtime/browser.rb b/qa/qa/runtime/browser.rb
index 4c64270ce92..7fd2ba25527 100644
--- a/qa/qa/runtime/browser.rb
+++ b/qa/qa/runtime/browser.rb
@@ -51,6 +51,10 @@ module QA
}
)
+ if QA::Runtime::Env.accept_insecure_certs?
+ capabilities['acceptInsecureCerts'] = true
+ end
+
options = Selenium::WebDriver::Chrome::Options.new
options.add_argument("window-size=1240,1680")
@@ -113,6 +117,15 @@ module QA
def perform(&block)
visit(url)
+ if QA::Runtime::Env.qa_cookies
+ browser = Capybara.current_session.driver.browser
+ QA::Runtime::Env.qa_cookies.each do |cookie|
+ name, value = cookie.split("=")
+ value ||= ""
+ browser.manage.add_cookie name: name, value: value
+ end
+ end
+
yield.tap { clear! } if block_given?
end
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index 27ba915961d..3bc2b44ccd8 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -1,20 +1,54 @@
+# frozen_string_literal: true
+
module QA
module Runtime
module Env
extend self
+ attr_writer :personal_access_token, :ldap_username, :ldap_password
+
+ # The environment variables used to indicate if the environment under test
+ # supports the given feature
+ SUPPORTED_FEATURES = {
+ git_protocol_v2: 'QA_CAN_TEST_GIT_PROTOCOL_V2'
+ }.freeze
+
+ def supported_features
+ SUPPORTED_FEATURES
+ end
+
+ def debug?
+ enabled?(ENV['QA_DEBUG'], default: false)
+ end
+
+ def log_destination
+ ENV['QA_LOG_PATH'] || $stdout
+ end
+
# set to 'false' to have Chrome run visibly instead of headless
def chrome_headless?
- (ENV['CHROME_HEADLESS'] =~ /^(false|no|0)$/i) != 0
+ enabled?(ENV['CHROME_HEADLESS'])
+ end
+
+ def accept_insecure_certs?
+ enabled?(ENV['ACCEPT_INSECURE_CERTS'])
end
def running_in_ci?
ENV['CI'] || ENV['CI_SERVER']
end
+ def qa_cookies
+ ENV['QA_COOKIES'] && ENV['QA_COOKIES'].split(';')
+ end
+
+ def signup_disabled?
+ enabled?(ENV['SIGNUP_DISABLED'], default: false)
+ end
+
# specifies token that can be used for the api
def personal_access_token
- ENV['PERSONAL_ACCESS_TOKEN']
+ @personal_access_token ||= ENV['PERSONAL_ACCESS_TOKEN']
end
def user_username
@@ -34,7 +68,7 @@ module QA
end
def forker?
- forker_username && forker_password
+ !!(forker_username && forker_password)
end
def forker_username
@@ -45,18 +79,42 @@ module QA
ENV['GITLAB_FORKER_PASSWORD']
end
+ def gitlab_qa_username_1
+ ENV['GITLAB_QA_USERNAME_1'] || 'gitlab-qa-user1'
+ end
+
+ def gitlab_qa_password_1
+ ENV['GITLAB_QA_PASSWORD_1']
+ end
+
+ def gitlab_qa_username_2
+ ENV['GITLAB_QA_USERNAME_2'] || 'gitlab-qa-user2'
+ end
+
+ def gitlab_qa_password_2
+ ENV['GITLAB_QA_PASSWORD_2']
+ end
+
def ldap_username
- ENV['GITLAB_LDAP_USERNAME']
+ @ldap_username ||= ENV['GITLAB_LDAP_USERNAME']
end
def ldap_password
- ENV['GITLAB_LDAP_PASSWORD']
+ @ldap_password ||= ENV['GITLAB_LDAP_PASSWORD']
end
def sandbox_name
ENV['GITLAB_SANDBOX_NAME']
end
+ def namespace_name
+ ENV['GITLAB_NAMESPACE_NAME']
+ end
+
+ def auto_devops_project_name
+ ENV['GITLAB_AUTO_DEVOPS_PROJECT_NAME']
+ end
+
def gcloud_account_key
ENV.fetch("GCLOUD_ACCOUNT_KEY")
end
@@ -83,6 +141,23 @@ module QA
raise ArgumentError, "Please provide GITHUB_ACCESS_TOKEN"
end
+
+ # Returns true if there is an environment variable that indicates that
+ # the feature is supported in the environment under test.
+ # All features are supported by default.
+ def can_test?(feature)
+ raise ArgumentError, %Q(Unknown feature "#{feature}") unless SUPPORTED_FEATURES.include? feature
+
+ enabled?(ENV[SUPPORTED_FEATURES[feature]], default: true)
+ end
+
+ private
+
+ def enabled?(value, default: true)
+ return default if value.nil?
+
+ (value =~ /^(false|no|0)$/i) != 0
+ end
end
end
end
diff --git a/qa/qa/runtime/fixtures.rb b/qa/qa/runtime/fixtures.rb
new file mode 100644
index 00000000000..72004d5b00a
--- /dev/null
+++ b/qa/qa/runtime/fixtures.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module QA
+ module Runtime
+ module Fixtures
+ def fetch_template_from_api(api_path, key)
+ request = Runtime::API::Request.new(api_client, "/templates/#{api_path}/#{key}")
+ get request.url
+ json_body[:content]
+ end
+
+ private
+
+ def api_client
+ @api_client ||= Runtime::API::Client.new(:gitlab)
+ end
+ end
+ end
+end
diff --git a/qa/qa/runtime/logger.rb b/qa/qa/runtime/logger.rb
new file mode 100644
index 00000000000..bd5c4fe5bf5
--- /dev/null
+++ b/qa/qa/runtime/logger.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'logger'
+
+module QA
+ module Runtime
+ module Logger
+ extend SingleForwardable
+
+ def_delegators :logger, :debug, :info, :warn, :error, :fatal, :unknown
+
+ singleton_class.module_eval do
+ attr_writer :logger
+
+ def logger
+ return @logger if @logger
+
+ @logger = ::Logger.new Runtime::Env.log_destination
+ @logger.level = Runtime::Env.debug? ? ::Logger::DEBUG : ::Logger::ERROR
+ @logger
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/runtime/namespace.rb b/qa/qa/runtime/namespace.rb
index f1c8ef11f94..704c65467e0 100644
--- a/qa/qa/runtime/namespace.rb
+++ b/qa/qa/runtime/namespace.rb
@@ -8,7 +8,7 @@ module QA
end
def name
- "qa-test-#{time.strftime('%Y-%m-%d-%H-%M-%S')}"
+ Runtime::Env.namespace_name || "qa-test-#{time.strftime('%Y-%m-%d-%H-%M-%S')}"
end
def path
diff --git a/qa/qa/runtime/path.rb b/qa/qa/runtime/path.rb
new file mode 100644
index 00000000000..3169c5dd743
--- /dev/null
+++ b/qa/qa/runtime/path.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module QA
+ module Runtime
+ module Path
+ extend self
+
+ def qa_root
+ ::File.expand_path('../../', __dir__)
+ end
+ end
+ end
+end
diff --git a/qa/qa/scenario/test/integration/instance_saml.rb b/qa/qa/scenario/test/integration/instance_saml.rb
new file mode 100644
index 00000000000..0697d0c2a0e
--- /dev/null
+++ b/qa/qa/scenario/test/integration/instance_saml.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module QA
+ module Scenario
+ module Test
+ module Integration
+ class InstanceSAML < Test::Instance::All
+ tags :instance_saml
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/scenario/test/integration/ldap.rb b/qa/qa/scenario/test/integration/ldap.rb
deleted file mode 100644
index 769fa389785..00000000000
--- a/qa/qa/scenario/test/integration/ldap.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-module QA
- module Scenario
- module Test
- module Integration
- class LDAP < Test::Instance::All
- tags :ldap
- end
- end
- end
- end
-end
diff --git a/qa/qa/scenario/test/integration/ldap_no_tls.rb b/qa/qa/scenario/test/integration/ldap_no_tls.rb
new file mode 100644
index 00000000000..bbf4c847f33
--- /dev/null
+++ b/qa/qa/scenario/test/integration/ldap_no_tls.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module QA
+ module Scenario
+ module Test
+ module Integration
+ class LDAPNoTLS < Test::Instance::All
+ tags :ldap_no_tls
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/scenario/test/integration/ldap_tls.rb b/qa/qa/scenario/test/integration/ldap_tls.rb
new file mode 100644
index 00000000000..2a767e57bc6
--- /dev/null
+++ b/qa/qa/scenario/test/integration/ldap_tls.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module QA
+ module Scenario
+ module Test
+ module Integration
+ class LDAPTLS < Test::Instance::All
+ tags :ldap_tls
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/service/kubernetes_cluster.rb b/qa/qa/service/kubernetes_cluster.rb
index abd9d53554f..c5f12255d72 100644
--- a/qa/qa/service/kubernetes_cluster.rb
+++ b/qa/qa/service/kubernetes_cluster.rb
@@ -1,12 +1,17 @@
require 'securerandom'
require 'mkmf'
+require 'pathname'
module QA
module Service
class KubernetesCluster
include Service::Shellout
- attr_reader :api_url, :ca_certificate, :token
+ attr_reader :api_url, :ca_certificate, :token, :rbac
+
+ def initialize(rbac: false)
+ @rbac = rbac
+ end
def cluster_name
@cluster_name ||= "qa-cluster-#{SecureRandom.hex(4)}-#{Time.now.utc.strftime("%Y%m%d%H%M%S")}"
@@ -19,7 +24,8 @@ module QA
shell <<~CMD.tr("\n", ' ')
gcloud container clusters
create #{cluster_name}
- --enable-legacy-authorization
+ #{auth_options}
+ --enable-basic-auth
--zone #{Runtime::Env.gcloud_zone}
&& gcloud container clusters
get-credentials
@@ -28,8 +34,30 @@ module QA
CMD
@api_url = `kubectl config view --minify -o jsonpath='{.clusters[].cluster.server}'`
- @ca_certificate = Base64.decode64(`kubectl get secrets -o jsonpath="{.items[0].data['ca\\.crt']}"`)
- @token = Base64.decode64(`kubectl get secrets -o jsonpath='{.items[0].data.token}'`)
+
+ @admin_user = "#{cluster_name}-admin"
+ master_auth = JSON.parse(`gcloud container clusters describe #{cluster_name} --zone #{Runtime::Env.gcloud_zone} --format 'json(masterAuth.username, masterAuth.password)'`)
+ shell <<~CMD.tr("\n", ' ')
+ kubectl config set-credentials #{@admin_user}
+ --username #{master_auth['masterAuth']['username']}
+ --password #{master_auth['masterAuth']['password']}
+ CMD
+
+ if rbac
+ create_service_account
+
+ secrets = JSON.parse(`kubectl get secrets -o json`)
+ gitlab_account = secrets['items'].find do |item|
+ item['metadata']['annotations']['kubernetes.io/service-account.name'] == 'gitlab-account'
+ end
+
+ @ca_certificate = Base64.decode64(gitlab_account['data']['ca.crt'])
+ @token = Base64.decode64(gitlab_account['data']['token'])
+ else
+ @ca_certificate = Base64.decode64(`kubectl get secrets -o jsonpath="{.items[0].data['ca\\.crt']}"`)
+ @token = Base64.decode64(`kubectl get secrets -o jsonpath='{.items[0].data.token}'`)
+ end
+
self
end
@@ -44,6 +72,42 @@ module QA
private
+ def create_service_account
+ shell('kubectl create -f -', stdin_data: service_account)
+ shell("kubectl --user #{@admin_user} create -f -", stdin_data: service_account_role_binding)
+ end
+
+ def service_account
+ <<~YAML
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+ name: gitlab-account
+ namespace: default
+ YAML
+ end
+
+ def service_account_role_binding
+ <<~YAML
+ kind: ClusterRoleBinding
+ apiVersion: rbac.authorization.k8s.io/v1
+ metadata:
+ name: gitlab-account-binding
+ subjects:
+ - kind: ServiceAccount
+ name: gitlab-account
+ namespace: default
+ roleRef:
+ kind: ClusterRole
+ name: cluster-admin
+ apiGroup: rbac.authorization.k8s.io
+ YAML
+ end
+
+ def auth_options
+ "--enable-legacy-authorization" unless rbac
+ end
+
def validate_dependencies
find_executable('gcloud') || raise("You must first install `gcloud` executable to run these tests.")
find_executable('kubectl') || raise("You must first install `kubectl` executable to run these tests.")
diff --git a/qa/qa/service/shellout.rb b/qa/qa/service/shellout.rb
index 1ca9504bb33..43dc0851571 100644
--- a/qa/qa/service/shellout.rb
+++ b/qa/qa/service/shellout.rb
@@ -11,10 +11,12 @@ module QA
# TODO, make it possible to use generic QA framework classes
# as a library - gitlab-org/gitlab-qa#94
#
- def shell(command)
+ def shell(command, stdin_data: nil)
puts "Executing `#{command}`"
- Open3.popen2e(*command) do |_in, out, wait|
+ Open3.popen2e(*command) do |stdin, out, wait|
+ stdin.puts(stdin_data) if stdin_data
+ stdin.close if stdin_data
out.each { |line| puts line }
if wait.value.exited? && wait.value.exitstatus.nonzero?
diff --git a/qa/qa/specs/features/api/1_manage/users_spec.rb b/qa/qa/specs/features/api/1_manage/users_spec.rb
index 3e3c9e859aa..ba1ba204d24 100644
--- a/qa/qa/specs/features/api/1_manage/users_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/users_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context :manage do
+ context 'Manage' do
describe 'Users API' do
before(:context) do
@api_client = Runtime::API::Client.new(:gitlab)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
index 1c7da930567..dae2a9e0236 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
@@ -1,5 +1,5 @@
module QA
- context :manage, :smoke do
+ context 'Manage', :smoke do
describe 'basic user login' do
it 'user logs in using basic credentials' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
@@ -8,7 +8,7 @@ module QA
# TODO, since `Signed in successfully` message was removed
# this is the only way to tell if user is signed in correctly.
#
- Page::Menu::Main.perform do |menu|
+ Page::Main::Menu.perform do |menu|
expect(menu).to have_personal_area
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
index c296296def6..a397df03bd2 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context :manage, :orchestrated, :ldap do
+ context 'Manage', :orchestrated, :ldap_no_tls, :ldap_tls do
describe 'LDAP login' do
it 'user logs into GitLab using LDAP credentials' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
@@ -10,7 +10,7 @@ module QA
# TODO, since `Signed in successfully` message was removed
# this is the only way to tell if user is signed in correctly.
#
- Page::Menu::Main.perform do |menu|
+ Page::Main::Menu.perform do |menu|
expect(menu).to have_personal_area
end
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb
index 6eda2c750d4..b1d641b507f 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context :manage, :orchestrated, :mattermost do
+ context 'Manage', :orchestrated, :mattermost do
describe 'Mattermost login' do
it 'user logs into Mattermost using GitLab OAuth' do
Runtime::Browser.visit(:gitlab, Page::Main::Login) do
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb
new file mode 100644
index 00000000000..87f0e9030d2
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Manage', :orchestrated, :instance_saml do
+ describe 'Instance wide SAML SSO' do
+ it 'User logs in to gitlab with SAML SSO' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+
+ Page::Main::Login.act { sign_in_with_saml }
+
+ Vendor::SAMLIdp::Page::Login.act { login }
+
+ expect(page).to have_content('Welcome to GitLab')
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb
new file mode 100644
index 00000000000..185837edacf
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module QA
+ shared_examples 'registration and login' do
+ it 'user registers and logs in' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+
+ Resource::User.fabricate_via_browser_ui!
+
+ # TODO, since `Signed in successfully` message was removed
+ # this is the only way to tell if user is signed in correctly.
+ #
+ Page::Main::Menu.perform do |menu|
+ expect(menu).to have_personal_area
+ end
+ end
+ end
+
+ context 'Manage', :skip_signup_disabled do
+ describe 'standard' do
+ it_behaves_like 'registration and login'
+ end
+ end
+
+ context 'Manage', :orchestrated, :ldap_no_tls, :skip_signup_disabled do
+ describe 'while LDAP is enabled' do
+ it_behaves_like 'registration and login'
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
new file mode 100644
index 00000000000..4070a225260
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Manage' do
+ describe 'Add project member' do
+ it 'user adds project member' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+
+ user = Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
+
+ project = Resource::Project.fabricate! do |resource|
+ resource.name = 'add-member-project'
+ end
+ project.visit!
+
+ Page::Project::Menu.perform(&:click_members_settings)
+ Page::Project::Settings::Members.perform do |page|
+ page.add_member(user.username)
+ end
+
+ expect(page).to have_content("#{user.name} @#{user.username} Given access")
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb
index bb1f3ab26d1..6632c2977ef 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb
@@ -1,23 +1,21 @@
# frozen_string_literal: true
module QA
- context :manage, :smoke do
+ context 'Manage', :smoke do
describe 'Project creation' do
it 'user creates a new project' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- created_project = Factory::Resource::Project.fabricate! do |project|
+ created_project = Resource::Project.fabricate_via_browser_ui! do |project|
project.name = 'awesome-project'
project.description = 'create awesome project test'
end
- expect(created_project.name).to match /^awesome-project-\h{16}$/
-
+ expect(page).to have_content(created_project.name)
expect(page).to have_content(
/Project \S?awesome-project\S+ was successfully created/
)
-
expect(page).to have_content('create awesome project test')
expect(page).to have_content('The repository for this project is empty')
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
index 2ef8de61441..3ce48de2c25 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
@@ -1,10 +1,10 @@
# frozen_string_literal: true
module QA
- context :manage, :orchestrated, :github do
+ context 'Manage', :orchestrated, :github do
describe 'Project import from GitHub' do
let(:imported_project) do
- Factory::Resource::ProjectImportedFromGithub.fabricate! do |project|
+ Resource::ProjectImportedFromGithub.fabricate! do |project|
project.name = 'imported-project'
project.personal_access_token = Runtime::Env.github_access_token
project.github_repository_path = 'gitlab-qa/test-project'
@@ -27,7 +27,7 @@ module QA
imported_project # import the project
- Page::Menu::Main.act { go_to_projects }
+ Page::Main::Menu.act { go_to_projects }
Page::Dashboard::Projects.perform do |dashboard|
dashboard.go_to_project(imported_project.name)
end
@@ -48,7 +48,7 @@ module QA
end
def verify_issues_import
- Page::Menu::Side.act { click_issues }
+ Page::Project::Menu.act { click_issues }
expect(page).to have_content('This is a sample issue')
click_link 'This is a sample issue'
@@ -66,7 +66,7 @@ module QA
end
def verify_merge_requests_import
- Page::Menu::Side.act { click_merge_requests }
+ Page::Project::Menu.act { click_merge_requests }
expect(page).to have_content('Improve README.md')
click_link 'Improve README.md'
@@ -101,7 +101,7 @@ module QA
end
def verify_wiki_import
- Page::Menu::Side.act { click_wiki }
+ Page::Project::Menu.act { click_wiki }
expect(page).to have_content('Welcome to the test-project wiki!')
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb
index 34bb6f1c197..275de3d332c 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb
@@ -1,19 +1,19 @@
# frozen_string_literal: true
module QA
- context :manage do
+ context 'Manage' do
describe 'Project activity' do
it 'user creates an event in the activity page upon Git push' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- Factory::Repository::ProjectPush.fabricate! do |push|
+ Resource::Repository::ProjectPush.fabricate! do |push|
push.file_name = 'README.md'
push.file_content = '# This is a test project'
push.commit_message = 'Add README.md'
end
- Page::Menu::Side.act { go_to_activity }
+ Page::Project::Menu.act { go_to_activity }
Page::Project::Activity.act { go_to_push_events }
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
index 542f532a629..7145b950b6c 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context :plan, :smoke do
+ context 'Plan', :smoke do
describe 'Issue creation' do
let(:issue_title) { 'issue title' }
@@ -9,7 +9,7 @@ module QA
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- Factory::Resource::Issue.fabricate! do |issue|
+ Resource::Issue.fabricate! do |issue|
issue.title = issue_title
end
end
@@ -17,7 +17,7 @@ module QA
it 'user creates an issue' do
create_issue
- Page::Menu::Side.act { click_issues }
+ Page::Project::Menu.act { click_issues }
expect(page).to have_content(issue_title)
end
@@ -31,6 +31,7 @@ module QA
create_issue
Page::Project::Issue::Show.perform do |show|
+ show.select_all_activities_filter
show.comment('See attached banana for scale', attachment: file_to_attach)
show.refresh
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb
new file mode 100644
index 00000000000..ac34f72bb8f
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Plan' do
+ describe 'filter issue comments activities' do
+ let(:issue_title) { 'issue title' }
+
+ it 'user filters comments and activites in an issue' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.act { sign_in_using_credentials }
+
+ Resource::Issue.fabricate! do |issue|
+ issue.title = issue_title
+ end
+
+ expect(page).to have_content(issue_title)
+
+ Page::Project::Issue::Show.perform do |show_page|
+ show_page.select_comments_only_filter
+ show_page.comment('/confidential')
+ show_page.comment('My own comment')
+
+ expect(show_page).not_to have_content("made the issue confidential")
+ expect(show_page).to have_content("My own comment")
+
+ show_page.select_all_activities_filter
+
+ expect(show_page).to have_content("made the issue confidential")
+ expect(show_page).to have_content("My own comment")
+
+ show_page.select_history_only_filter
+
+ expect(show_page).to have_content("made the issue confidential")
+ expect(show_page).not_to have_content("My own comment")
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
index bcf55a02a61..d33947f41da 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
@@ -1,31 +1,41 @@
# frozen_string_literal: true
module QA
- context :create do
+ context 'Create' do
describe 'Merge request creation' do
it 'user creates a new merge request' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- current_project = Factory::Resource::Project.fabricate! do |project|
+ current_project = Resource::Project.fabricate! do |project|
project.name = 'project-with-merge-request-and-milestone'
end
- current_milestone = Factory::Resource::ProjectMilestone.fabricate! do |milestone|
+ current_milestone = Resource::ProjectMilestone.fabricate! do |milestone|
milestone.title = 'unique-milestone'
milestone.project = current_project
end
- Factory::Resource::MergeRequest.fabricate! do |merge_request|
+ new_label = Resource::Label.fabricate! do |label|
+ label.project = current_project
+ label.title = 'qa-mr-test-label'
+ label.description = 'Merge Request label'
+ end
+
+ Resource::MergeRequest.fabricate! do |merge_request|
merge_request.title = 'This is a merge request with a milestone'
merge_request.description = 'Great feature with milestone'
merge_request.project = current_project
merge_request.milestone = current_milestone
+ merge_request.labels.push(new_label)
end
- expect(page).to have_content('This is a merge request with a milestone')
- expect(page).to have_content('Great feature with milestone')
- expect(page).to have_content(/Opened [\w\s]+ ago/)
+ Page::MergeRequest::Show.perform do |merge_request|
+ expect(merge_request).to have_content('This is a merge request with a milestone')
+ expect(merge_request).to have_content('Great feature with milestone')
+ expect(merge_request).to have_content(/Opened [\w\s]+ ago/)
+ expect(merge_request).to have_label(new_label.title)
+ end
Page::Issuable::Sidebar.perform do |sidebar|
expect(sidebar).to have_milestone(current_milestone.title)
@@ -39,11 +49,11 @@ module QA
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- current_project = Factory::Resource::Project.fabricate! do |project|
+ current_project = Resource::Project.fabricate! do |project|
project.name = 'project-with-merge-request'
end
- Factory::Resource::MergeRequest.fabricate! do |merge_request|
+ Resource::MergeRequest.fabricate! do |merge_request|
merge_request.title = 'This is a merge request'
merge_request.description = 'Great feature'
merge_request.project = current_project
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
index 407a15800ab..6dcd74471fe 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb
@@ -1,17 +1,17 @@
# frozen_string_literal: true
module QA
- context :create do
+ context 'Create' do
describe 'Merge request creation from fork' do
it 'user forks a project, submits a merge request and maintainer merges it' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- merge_request = Factory::Resource::MergeRequestFromFork.fabricate! do |merge_request|
+ merge_request = Resource::MergeRequestFromFork.fabricate! do |merge_request|
merge_request.fork_branch = 'feature-branch'
end
- Page::Menu::Main.perform { |main| main.sign_out }
+ Page::Main::Menu.perform { |main| main.sign_out }
Page::Main::Login.perform { |login| login.sign_in_using_credentials }
merge_request.visit!
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
index ddcbc94b1b1..e2d639fd150 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
@@ -1,25 +1,26 @@
# frozen_string_literal: true
module QA
- context :create do
+ context 'Create' do
describe 'Merge request rebasing' do
it 'user rebases source branch of merge request' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- project = Factory::Resource::Project.fabricate! do |project|
+ project = Resource::Project.fabricate! do |project|
project.name = "only-fast-forward"
end
+ project.visit!
- Page::Menu::Side.act { go_to_settings }
+ Page::Project::Menu.act { go_to_settings }
Page::Project::Settings::MergeRequest.act { enable_ff_only }
- merge_request = Factory::Resource::MergeRequest.fabricate! do |merge_request|
+ merge_request = Resource::MergeRequest.fabricate! do |merge_request|
merge_request.project = project
merge_request.title = 'Needs rebasing'
end
- Factory::Repository::ProjectPush.fabricate! do |push|
+ Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.file_name = "other.txt"
push.file_content = "New file added!"
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb
index b5b8855a35d..6ff7360c413 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb
@@ -1,22 +1,22 @@
# frozen_string_literal: true
module QA
- context :create do
+ context 'Create' do
describe 'Merge request squashing' do
it 'user squashes commits while merging' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- project = Factory::Resource::Project.fabricate! do |project|
+ project = Resource::Project.fabricate! do |project|
project.name = "squash-before-merge"
end
- merge_request = Factory::Resource::MergeRequest.fabricate! do |merge_request|
+ merge_request = Resource::MergeRequest.fabricate! do |merge_request|
merge_request.project = project
merge_request.title = 'Squashing commits'
end
- Factory::Repository::ProjectPush.fabricate! do |push|
+ Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.commit_message = 'to be squashed'
push.branch_name = merge_request.source_branch
@@ -25,6 +25,7 @@ module QA
push.file_content = "Test with unicode characters â¤âœ“€â„"
end
+ Page::Project::Show.perform(&:wait_for_push)
merge_request.visit!
expect(page).to have_text('to be squashed')
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb
new file mode 100644
index 00000000000..297485dd81e
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_file_template_spec.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Create' do
+ describe 'File templates' do
+ include Runtime::Fixtures
+
+ def login
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.act { sign_in_using_credentials }
+ end
+
+ before(:all) do
+ login
+
+ @project = Resource::Project.fabricate! do |project|
+ project.name = 'file-template-project'
+ project.description = 'Add file templates via the Files view'
+ end
+
+ Page::Main::Menu.act { sign_out }
+ end
+
+ templates = [
+ {
+ file_name: '.gitignore',
+ name: 'Android',
+ api_path: 'gitignores',
+ api_key: 'Android'
+ },
+ {
+ file_name: '.gitlab-ci.yml',
+ name: 'Julia',
+ api_path: 'gitlab_ci_ymls',
+ api_key: 'Julia'
+ },
+ {
+ file_name: 'Dockerfile',
+ name: 'Python',
+ api_path: 'dockerfiles',
+ api_key: 'Python'
+ },
+ {
+ file_name: 'LICENSE',
+ name: 'Mozilla Public License 2.0',
+ api_path: 'licenses',
+ api_key: 'mpl-2.0'
+ }
+ ]
+
+ templates.each do |template|
+ it "user adds #{template[:file_name]} via file template #{template[:name]}" do
+ content = fetch_template_from_api(template[:api_path], template[:api_key])
+
+ login
+ @project.visit!
+
+ Page::Project::Show.act { create_new_file! }
+ Page::File::Form.perform do |page|
+ page.select_template template[:file_name], template[:name]
+ end
+
+ expect(page).to have_content('Template applied')
+ expect(page).to have_button('Undo')
+ expect(page).to have_content(content[0..100])
+
+ Page::File::Form.perform(&:commit_changes)
+
+ expect(page).to have_content('The file has been successfully created.')
+ expect(page).to have_content(template[:file_name])
+ expect(page).to have_content('Add new file')
+ expect(page).to have_content(content[0..100])
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_ssh_key_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_ssh_key_spec.rb
index 84f663c4866..ff879fdeb16 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/add_ssh_key_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_ssh_key_spec.rb
@@ -1,23 +1,23 @@
# frozen_string_literal: true
module QA
- context :create do
+ context 'Create' do
describe 'SSH keys support' do
let(:key_title) { "key for ssh tests #{Time.now.to_f}" }
- it 'user adds and then removes an SSH key' do
+ it 'user adds and then removes an SSH key', :smoke do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- key = Factory::Resource::SSHKey.fabricate! do |resource|
+ key = Resource::SSHKey.fabricate! do |resource|
resource.title = key_title
end
expect(page).to have_content("Title: #{key_title}")
expect(page).to have_content(key.fingerprint)
- Page::Menu::Main.act { go_to_profile_settings }
- Page::Menu::Profile.act { click_ssh_keys }
+ Page::Main::Menu.act { go_to_profile_settings }
+ Page::Profile::Menu.act { click_ssh_keys }
Page::Profile::SSHKeys.perform do |ssh_keys|
ssh_keys.remove_key(key_title)
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb
index 0dcdc6639d1..6a0add56fe0 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
module QA
- context :create do
- describe 'Git clone over HTTP', :ldap do
+ context 'Create' do
+ describe 'Git clone over HTTP', :ldap_no_tls do
let(:location) do
Page::Project::Show.act do
choose_repository_clone_http
@@ -14,10 +14,11 @@ module QA
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- Factory::Resource::Project.fabricate! do |scenario|
+ project = Resource::Project.fabricate! do |scenario|
scenario.name = 'project-with-code'
scenario.description = 'project for git clone tests'
end
+ project.visit!
Git::Repository.perform do |repository|
repository.uri = location.uri
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb
index 82d635065a0..46346d1b984 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context :create do
+ context 'Create' do
describe 'Files management' do
it 'user creates, edits and deletes a file via the Web' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
@@ -12,7 +12,7 @@ module QA
file_content = 'QA Test - File content'
commit_message_for_create = 'QA Test - Create new file'
- Factory::Resource::File.fabricate! do |file|
+ Resource::File.fabricate! do |file|
file.name = file_name
file.content = file_content
file.commit_message = commit_message_for_create
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb
new file mode 100644
index 00000000000..43894372cf5
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Create' do
+ describe 'Push over HTTP using Git protocol version 2', :requires_git_protocol_v2 do
+ it 'user pushes to the repository' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+
+ # Create a project to push to
+ project = Resource::Project.fabricate! do |project|
+ project.name = 'git-protocol-project'
+ end
+
+ file_name = 'README.md'
+ file_content = 'Test Git protocol v2'
+ git_protocol = '2'
+ git_protocol_reported = nil
+
+ # Use Git to clone the project, push a file to it, and then check the
+ # supported Git protocol
+ Git::Repository.perform do |repository|
+ username = 'GitLab QA'
+ email = 'root@gitlab.com'
+
+ repository.uri = project.repository_http_location.uri
+ repository.use_default_credentials
+ repository.clone
+ repository.configure_identity(username, email)
+
+ git_protocol_reported = repository.push_with_git_protocol(
+ git_protocol,
+ file_name,
+ file_content)
+ end
+
+ project.visit!
+ Page::Project::Show.perform(&:wait_for_push)
+
+ # Check that the push worked
+ expect(page).to have_content(file_name)
+ expect(page).to have_content(file_content)
+
+ # And check that the correct Git protocol was used
+ expect(git_protocol_reported).to eq(git_protocol)
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
new file mode 100644
index 00000000000..135925c007f
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Create' do
+ describe 'Push over SSH using Git protocol version 2', :requires_git_protocol_v2 do
+ # Note: If you run this test against GDK make sure you've enabled sshd and
+ # enabled setting the Git protocol by adding `AcceptEnv GIT_PROTOCOL` to
+ # `sshd_config`
+ # See: https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/run_qa_against_gdk.md
+
+ let(:key_title) { "key for ssh tests #{Time.now.to_f}" }
+ let(:ssh_key) do
+ Resource::SSHKey.fabricate! do |resource|
+ resource.title = key_title
+ end
+ end
+
+ def login
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+ end
+
+ around do |example|
+ # Create an SSH key to be used with Git
+ login
+ ssh_key
+
+ example.run
+
+ # Remove the SSH key
+ login
+ Page::Main::Menu.perform(&:go_to_profile_settings)
+ Page::Profile::Menu.perform(&:click_ssh_keys)
+ Page::Profile::SSHKeys.perform do |ssh_keys|
+ ssh_keys.remove_key(key_title)
+ end
+ end
+
+ it 'user pushes to the repository' do
+ # Create a project to push to
+ project = Resource::Project.fabricate! do |project|
+ project.name = 'git-protocol-project'
+ end
+
+ file_name = 'README.md'
+ file_content = 'Test Git protocol v2'
+ git_protocol = '2'
+ git_protocol_reported = nil
+
+ # Use Git to clone the project, push a file to it, and then check the
+ # supported Git protocol
+ Git::Repository.perform do |repository|
+ username = 'GitLab QA'
+ email = 'root@gitlab.com'
+
+ repository.uri = project.repository_ssh_location.uri
+
+ begin
+ repository.use_ssh_key(ssh_key)
+ repository.clone
+ repository.configure_identity(username, email)
+
+ git_protocol_reported = repository.push_with_git_protocol(
+ git_protocol,
+ file_name,
+ file_content)
+ ensure
+ repository.delete_ssh_key
+ end
+ end
+
+ project.visit!
+ Page::Project::Show.perform(&:wait_for_push)
+
+ # Check that the push worked
+ expect(page).to have_content(file_name)
+ expect(page).to have_content(file_content)
+
+ # And check that the correct Git protocol was used
+ expect(git_protocol_reported).to eq(git_protocol)
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
new file mode 100644
index 00000000000..a63b7dce8d6
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Create' do
+ describe 'Git push over HTTP', :ldap_no_tls do
+ it 'user using a personal access token pushes code to the repository' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+
+ access_token = Resource::PersonalAccessToken.fabricate!.access_token
+
+ user = Resource::User.new.tap do |user|
+ user.username = Runtime::User.username
+ user.password = access_token
+ end
+
+ push = Resource::Repository::ProjectPush.fabricate! do |push|
+ push.user = user
+ push.file_name = 'README.md'
+ push.file_content = '# This is a test project'
+ push.commit_message = 'Add README.md'
+ end
+
+ push.project.visit!
+ Page::Project::Show.perform(&:wait_for_push)
+
+ expect(page).to have_content('README.md')
+ expect(page).to have_content('This is a test project')
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb
index bf32569b6cb..92f596a44d9 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb
@@ -1,13 +1,13 @@
# frozen_string_literal: true
module QA
- context :create do
- describe 'Git push over HTTP', :ldap do
+ context 'Create' do
+ describe 'Git push over HTTP', :ldap_no_tls do
it 'user pushes code to the repository' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- Factory::Repository::ProjectPush.fabricate! do |push|
+ Resource::Repository::ProjectPush.fabricate! do |push|
push.file_name = 'README.md'
push.file_content = '# This is a test project'
push.commit_message = 'Add README.md'
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb
index b2da685c477..73a3dc14a65 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb
@@ -1,12 +1,12 @@
# frozen_string_literal: true
module QA
- context :create do
- describe 'Protected branch support', :ldap do
+ context 'Create' do
+ describe 'Protected branch support', :ldap_no_tls do
let(:branch_name) { 'protected-branch' }
let(:commit_message) { 'Protected push commit message' }
let(:project) do
- Factory::Resource::Project.fabricate! do |resource|
+ Resource::Project.fabricate! do |resource|
resource.name = 'protected-branch-project'
end
end
@@ -47,7 +47,7 @@ module QA
end
def create_protected_branch(allow_to_push:)
- Factory::Resource::Branch.fabricate! do |resource|
+ Resource::Branch.fabricate! do |resource|
resource.branch_name = branch_name
resource.project = project
resource.allow_to_push = allow_to_push
@@ -56,7 +56,7 @@ module QA
end
def push_new_file(branch)
- Factory::Repository::ProjectPush.fabricate! do |resource|
+ Resource::Repository::ProjectPush.fabricate! do |resource|
resource.project = project
resource.file_name = 'new_file.md'
resource.file_content = '# This is a new file'
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb
index 7c989bfd8cc..9c764424129 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context :create do
+ context 'Create' do
describe 'SSH key support' do
# Note: If you run this test against GDK make sure you've enabled sshd
# See: https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/run_qa_against_gdk.md
@@ -12,11 +12,11 @@ module QA
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- key = Factory::Resource::SSHKey.fabricate! do |resource|
+ key = Resource::SSHKey.fabricate! do |resource|
resource.title = key_title
end
- Factory::Repository::ProjectPush.fabricate! do |push|
+ Resource::Repository::ProjectPush.fabricate! do |push|
push.ssh_key = key
push.file_name = 'README.md'
push.file_content = '# Test Use SSH Key'
@@ -28,8 +28,8 @@ module QA
expect(page).to have_content('README.md')
expect(page).to have_content('Test Use SSH Key')
- Page::Menu::Main.act { go_to_profile_settings }
- Page::Menu::Profile.act { click_ssh_keys }
+ Page::Main::Menu.act { go_to_profile_settings }
+ Page::Profile::Menu.act { click_ssh_keys }
Page::Profile::SSHKeys.perform do |ssh_keys|
ssh_keys.remove_key(key_title)
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb
new file mode 100644
index 00000000000..e7374377104
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/add_file_template_spec.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Create' do
+ describe 'Web IDE file templates' do
+ include Runtime::Fixtures
+
+ def login
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.act { sign_in_using_credentials }
+ end
+
+ before(:all) do
+ login
+
+ @project = Resource::Project.fabricate! do |project|
+ project.name = 'file-template-project'
+ project.description = 'Add file templates via the Web IDE'
+ end
+ @project.visit!
+
+ # Add a file via the regular Files view because the Web IDE isn't
+ # available unless there is a file present
+ Page::Project::Show.act { create_new_file! }
+ Page::File::Form.perform do |page|
+ page.add_name('dummy')
+ page.add_content('Enable the Web IDE')
+ page.commit_changes
+ end
+
+ Page::Main::Menu.act { sign_out }
+ end
+
+ templates = [
+ {
+ file_name: '.gitignore',
+ name: 'Android',
+ api_path: 'gitignores',
+ api_key: 'Android'
+ },
+ {
+ file_name: '.gitlab-ci.yml',
+ name: 'Julia',
+ api_path: 'gitlab_ci_ymls',
+ api_key: 'Julia'
+ },
+ {
+ file_name: 'Dockerfile',
+ name: 'Python',
+ api_path: 'dockerfiles',
+ api_key: 'Python'
+ },
+ {
+ file_name: 'LICENSE',
+ name: 'Mozilla Public License 2.0',
+ api_path: 'licenses',
+ api_key: 'mpl-2.0'
+ }
+ ]
+
+ templates.each do |template|
+ it "user adds #{template[:file_name]} via file template #{template[:name]}" do
+ content = fetch_template_from_api(template[:api_path], template[:api_key])
+
+ login
+ @project.visit!
+
+ Page::Project::Show.act { open_web_ide! }
+ Page::Project::WebIDE::Edit.perform do |page|
+ page.create_new_file_from_template template[:file_name], template[:name]
+
+ expect(page.has_file?(template[:file_name])).to be_truthy
+ end
+
+ expect(page).to have_button('Undo')
+ expect(page).to have_content(content[0..100])
+
+ Page::Project::WebIDE::Edit.perform do |page|
+ page.commit_changes
+ end
+
+ expect(page).to have_content(template[:file_name])
+ expect(page).to have_content(content[0..100])
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb
index 8009b9e8609..210271705d9 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context :create do
+ context 'Create' do
describe 'Wiki management' do
def login
Runtime::Browser.visit(:gitlab, Page::Main::Login)
@@ -18,7 +18,7 @@ module QA
end
it 'user creates, edits, clones, and pushes to the wiki' do
- wiki = Factory::Resource::Wiki.fabricate! do |resource|
+ wiki = Resource::Wiki.fabricate! do |resource|
resource.title = 'Home'
resource.content = '# My First Wiki Content'
resource.message = 'Update home'
@@ -34,13 +34,13 @@ module QA
validate_content('My Second Wiki Content')
- Factory::Repository::WikiPush.fabricate! do |push|
+ Resource::Repository::WikiPush.fabricate! do |push|
push.wiki = wiki
push.file_name = 'Home.md'
push.file_content = '# My Third Wiki Content'
push.commit_message = 'Update Home.md'
end
- Page::Menu::Side.act { click_wiki }
+ Page::Project::Menu.act { click_wiki }
expect(page).to have_content('My Third Wiki Content')
end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_ci_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_ci_variable_spec.rb
new file mode 100644
index 00000000000..0837b720df1
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_ci_variable_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Verify' do
+ describe 'CI variable support' do
+ it 'user adds a CI variable' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.act { sign_in_using_credentials }
+
+ Resource::CiVariable.fabricate! do |resource|
+ resource.key = 'VARIABLE_KEY'
+ resource.value = 'some CI variable'
+ end
+
+ Page::Project::Settings::CICD.perform do |settings|
+ settings.expand_ci_variables do |page|
+ expect(page).to have_field(with: 'VARIABLE_KEY')
+ expect(page).not_to have_field(with: 'some CI variable')
+
+ page.reveal_variables
+
+ expect(page).to have_field(with: 'some CI variable')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
index cdfe9b90e15..25cbe41c684 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context :verify, :orchestrated, :docker do
+ context 'Verify', :orchestrated, :docker do
describe 'Pipeline creation and processing' do
let(:executor) { "qa-runner-#{Time.now.to_i}" }
@@ -13,18 +13,18 @@ module QA
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- project = Factory::Resource::Project.fabricate! do |project|
+ project = Resource::Project.fabricate! do |project|
project.name = 'project-with-pipelines'
project.description = 'Project with CI/CD Pipelines.'
end
- Factory::Resource::Runner.fabricate! do |runner|
+ Resource::Runner.fabricate! do |runner|
runner.project = project
runner.name = executor
runner.tags = %w[qa test]
end
- Factory::Repository::ProjectPush.fabricate! do |push|
+ Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.file_name = '.gitlab-ci.yml'
push.commit_message = 'Add .gitlab-ci.yml'
@@ -64,7 +64,7 @@ module QA
expect(page).to have_content('Add .gitlab-ci.yml')
- Page::Menu::Side.act { click_ci_cd_pipelines }
+ Page::Project::Menu.act { click_ci_cd_pipelines }
expect(page).to have_content('All 1')
expect(page).to have_content('Add .gitlab-ci.yml')
diff --git a/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb
index 8d83a20f5bf..3af7db751e7 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context :verify, :docker do
+ context 'Verify', :docker do
describe 'Runner registration' do
let(:executor) { "qa-runner-#{Time.now.to_i}" }
@@ -13,7 +13,7 @@ module QA
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- Factory::Resource::Runner.fabricate! do |runner|
+ Resource::Runner.fabricate! do |runner|
runner.name = executor
end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/secret_variable/add_secret_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/secret_variable/add_secret_variable_spec.rb
deleted file mode 100644
index 08a87df5837..00000000000
--- a/qa/qa/specs/features/browser_ui/4_verify/secret_variable/add_secret_variable_spec.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- context :verify do
- describe 'Secret variable support' do
- it 'user adds a secret variable' do
- Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.act { sign_in_using_credentials }
-
- Factory::Resource::SecretVariable.fabricate! do |resource|
- resource.key = 'VARIABLE_KEY'
- resource.value = 'some secret variable'
- end
-
- Page::Project::Settings::CICD.perform do |settings|
- settings.expand_secret_variables do |page|
- expect(page).to have_field(with: 'VARIABLE_KEY')
- expect(page).not_to have_field(with: 'some secret variable')
-
- page.reveal_variables
-
- expect(page).to have_field(with: 'some secret variable')
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb
index 17dfa887434..84757f25379 100644
--- a/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module QA
- context :release do
+ context 'Release' do
describe 'Deploy key creation' do
it 'user adds a deploy key' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
@@ -11,7 +11,7 @@ module QA
deploy_key_title = 'deploy key title'
deploy_key_value = key.public_key
- deploy_key = Factory::Resource::DeployKey.fabricate! do |resource|
+ deploy_key = Resource::DeployKey.fabricate! do |resource|
resource.title = deploy_key_title
resource.key = deploy_key_value
end
diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
index 8352d13b06d..e2320c92343 100644
--- a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb
@@ -3,7 +3,7 @@
require 'digest/sha1'
module QA
- context :release, :docker do
+ context 'Release', :docker do
describe 'Git clone using a deploy key' do
def login
Runtime::Browser.visit(:gitlab, Page::Main::Login)
@@ -15,20 +15,20 @@ module QA
@runner_name = "qa-runner-#{Time.now.to_i}"
- @project = Factory::Resource::Project.fabricate! do |resource|
+ @project = Resource::Project.fabricate! do |resource|
resource.name = 'deploy-key-clone-project'
end
@repository_location = @project.repository_ssh_location
- Factory::Resource::Runner.fabricate! do |resource|
+ Resource::Runner.fabricate! do |resource|
resource.project = @project
resource.name = @runner_name
resource.tags = %w[qa docker]
resource.image = 'gitlab/gitlab-runner:ubuntu'
end
- Page::Menu::Main.act { sign_out }
+ Page::Main::Menu.act { sign_out }
end
after(:all) do
@@ -47,7 +47,7 @@ module QA
login
- Factory::Resource::DeployKey.fabricate! do |resource|
+ Resource::DeployKey.fabricate! do |resource|
resource.project = @project
resource.title = "deploy key #{key.name}(#{key.bits})"
resource.key = key.public_key
@@ -55,7 +55,7 @@ module QA
deploy_key_name = "DEPLOY_KEY_#{key.name}_#{key.bits}"
- Factory::Resource::SecretVariable.fabricate! do |resource|
+ Resource::CiVariable.fabricate! do |resource|
resource.project = @project
resource.key = deploy_key_name
resource.value = key.private_key
@@ -78,7 +78,7 @@ module QA
- docker
YAML
- Factory::Repository::ProjectPush.fabricate! do |resource|
+ Resource::Repository::ProjectPush.fabricate! do |resource|
resource.project = @project
resource.file_name = '.gitlab-ci.yml'
resource.commit_message = 'Add .gitlab-ci.yml'
@@ -90,7 +90,7 @@ module QA
sha1sum = Digest::SHA1.hexdigest(gitlab_ci)
Page::Project::Show.act { wait_for_push }
- Page::Menu::Side.act { click_ci_cd_pipelines }
+ Page::Project::Menu.act { click_ci_cd_pipelines }
Page::Project::Pipeline::Index.act { go_to_latest_pipeline }
Page::Project::Pipeline::Show.act { go_to_first_job }
diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb
new file mode 100644
index 00000000000..9f34e4218c1
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Release' do
+ describe 'Deploy token creation' do
+ it 'user adds a deploy token' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.act { sign_in_using_credentials }
+
+ deploy_token_name = 'deploy token name'
+ deploy_token_expires_at = Date.today + 7 # 1 Week from now
+
+ deploy_token = Resource::DeployToken.fabricate! do |resource|
+ resource.name = deploy_token_name
+ resource.expires_at = deploy_token_expires_at
+ end
+
+ expect(deploy_token.username.length).to be > 0
+ expect(deploy_token.password.length).to be > 0
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
index 844cc1236c7..b0c277a48c3 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
@@ -3,65 +3,81 @@
require 'pathname'
module QA
- context :configure, :orchestrated, :kubernetes do
+ context 'Configure', :orchestrated, :kubernetes do
describe 'Auto DevOps support' do
after do
@cluster&.remove!
end
- it 'user creates a new project and runs auto devops' do
- Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.act { sign_in_using_credentials }
+ [true, false].each do |rbac|
+ context "when rbac is #{rbac ? 'enabled' : 'disabled'}" do
+ it 'user creates a new project and runs auto devops' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.act { sign_in_using_credentials }
- project = Factory::Resource::Project.fabricate! do |p|
- p.name = 'project-with-autodevops'
- p.description = 'Project with Auto Devops'
- end
+ project = Resource::Project.fabricate! do |p|
+ p.name = Runtime::Env.auto_devops_project_name || 'project-with-autodevops'
+ p.description = 'Project with Auto Devops'
+ end
- # Disable code_quality check in Auto DevOps pipeline as it takes
- # too long and times out the test
- Factory::Resource::SecretVariable.fabricate! do |resource|
- resource.project = project
- resource.key = 'CODE_QUALITY_DISABLED'
- resource.value = '1'
- end
+ # Disable code_quality check in Auto DevOps pipeline as it takes
+ # too long and times out the test
+ Resource::CiVariable.fabricate! do |resource|
+ resource.project = project
+ resource.key = 'CODE_QUALITY_DISABLED'
+ resource.value = '1'
+ end
- # Create Auto Devops compatible repo
- Factory::Repository::ProjectPush.fabricate! do |push|
- push.project = project
- push.directory = Pathname
- .new(__dir__)
- .join('../../../../../fixtures/auto_devops_rack')
- push.commit_message = 'Create Auto DevOps compatible rack application'
- end
+ # Create Auto Devops compatible repo
+ Resource::Repository::ProjectPush.fabricate! do |push|
+ push.project = project
+ push.directory = Pathname
+ .new(__dir__)
+ .join('../../../../../fixtures/auto_devops_rack')
+ push.commit_message = 'Create Auto DevOps compatible rack application'
+ end
- Page::Project::Show.act { wait_for_push }
+ Page::Project::Show.act { wait_for_push }
- # Create and connect K8s cluster
- @cluster = Service::KubernetesCluster.new.create!
- kubernetes_cluster = Factory::Resource::KubernetesCluster.fabricate! do |cluster|
- cluster.project = project
- cluster.cluster = @cluster
- cluster.install_helm_tiller = true
- cluster.install_ingress = true
- cluster.install_prometheus = true
- cluster.install_runner = true
- end
+ # Create and connect K8s cluster
+ @cluster = Service::KubernetesCluster.new(rbac: rbac).create!
+ kubernetes_cluster = Resource::KubernetesCluster.fabricate! do |cluster|
+ cluster.project = project
+ cluster.cluster = @cluster
+ cluster.install_helm_tiller = true
+ cluster.install_ingress = true
+ cluster.install_prometheus = true
+ cluster.install_runner = true
+ end
+ kubernetes_cluster.populate(:ingress_ip)
- project.visit!
- Page::Menu::Side.act { click_ci_cd_settings }
- Page::Project::Settings::CICD.perform do |p|
- p.enable_auto_devops_with_domain("#{kubernetes_cluster.ingress_ip}.nip.io")
- end
+ project.visit!
+ Page::Project::Menu.act { click_ci_cd_settings }
+ Page::Project::Settings::CICD.perform do |p|
+ p.enable_auto_devops_with_domain(
+ "#{kubernetes_cluster.ingress_ip}.nip.io")
+ end
+
+ project.visit!
+ Page::Project::Menu.act { click_ci_cd_pipelines }
+ Page::Project::Pipeline::Index.act { go_to_latest_pipeline }
- project.visit!
- Page::Menu::Side.act { click_ci_cd_pipelines }
- Page::Project::Pipeline::Index.act { go_to_latest_pipeline }
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ expect(pipeline).to have_build('build', status: :success, wait: 600)
+ expect(pipeline).to have_build('test', status: :success, wait: 600)
+ expect(pipeline).to have_build('production', status: :success, wait: 1200)
+ end
- Page::Project::Pipeline::Show.perform do |pipeline|
- expect(pipeline).to have_build('build', status: :success, wait: 600)
- expect(pipeline).to have_build('test', status: :success, wait: 600)
- expect(pipeline).to have_build('production', status: :success, wait: 1200)
+ Page::Project::Menu.act { click_operations_environments }
+ Page::Project::Operations::Environments::Index.perform do |index|
+ index.go_to_environment('production')
+ end
+ Page::Project::Operations::Environments::Show.perform do |show|
+ show.view_deployment do
+ expect(page).to have_content('Hello World!')
+ end
+ end
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/7_configure/mattermost/create_group_with_mattermost_team_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/mattermost/create_group_with_mattermost_team_spec.rb
index 6ffdc55538a..7096864e011 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/mattermost/create_group_with_mattermost_team_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/mattermost/create_group_with_mattermost_team_spec.rb
@@ -1,12 +1,12 @@
# frozen_string_literal: true
module QA
- context :configure, :orchestrated, :mattermost do
+ context 'Configure', :orchestrated, :mattermost do
describe 'Mattermost support' do
it 'user creates a group with a mattermost team' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
- Page::Menu::Main.act { go_to_groups }
+ Page::Main::Menu.act { go_to_groups }
Page::Dashboard::Groups.perform do |page|
page.go_to_new_group
diff --git a/qa/qa/specs/features/sanity/framework_spec.rb b/qa/qa/specs/features/sanity/framework_spec.rb
index ee9d068eb3a..aae0f0ade71 100644
--- a/qa/qa/specs/features/sanity/framework_spec.rb
+++ b/qa/qa/specs/features/sanity/framework_spec.rb
@@ -6,9 +6,7 @@ module QA
it 'succeeds' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.perform do |main_login|
- expect(main_login.sign_in_tab?).to be(true)
- end
+ expect(page).to have_text('Open source software to collaborate on code')
end
end
diff --git a/qa/qa/specs/runner.rb b/qa/qa/specs/runner.rb
index fea0ef94df3..1bd8101c36d 100644
--- a/qa/qa/specs/runner.rb
+++ b/qa/qa/specs/runner.rb
@@ -23,6 +23,12 @@ module QA
args.push(%w[--tag ~orchestrated]) unless (%w[-t --tag] & options).any?
end
+ args.push(%w[--tag ~skip_signup_disabled]) if QA::Runtime::Env.signup_disabled?
+
+ QA::Runtime::Env.supported_features.each_key do |key|
+ args.push(["--tag", "~requires_#{key}"]) unless QA::Runtime::Env.can_test? key
+ end
+
args.push(options)
args.push(DEFAULT_TEST_PATH_ARGS) unless options.any? { |opt| opt =~ %r{/features/} }
diff --git a/qa/qa/support/api.rb b/qa/qa/support/api.rb
new file mode 100644
index 00000000000..1107d43161e
--- /dev/null
+++ b/qa/qa/support/api.rb
@@ -0,0 +1,28 @@
+module QA
+ module Support
+ module Api
+ def post(url, payload)
+ RestClient::Request.execute(
+ method: :post,
+ url: url,
+ payload: payload,
+ verify_ssl: false)
+ rescue RestClient::ExceptionWithResponse => e
+ e.response
+ end
+
+ def get(url)
+ RestClient::Request.execute(
+ method: :get,
+ url: url,
+ verify_ssl: false)
+ rescue RestClient::ExceptionWithResponse => e
+ e.response
+ end
+
+ def parse_body(response)
+ JSON.parse(response.body, symbolize_names: true)
+ end
+ end
+ end
+end
diff --git a/qa/qa/support/page/logging.rb b/qa/qa/support/page/logging.rb
new file mode 100644
index 00000000000..cf5cd3a79f8
--- /dev/null
+++ b/qa/qa/support/page/logging.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+module QA
+ module Support
+ module Page
+ module Logging
+ def refresh
+ log("refreshing #{current_url}")
+
+ super
+ end
+
+ def wait(max: 60, time: 0.1, reload: true)
+ log("with wait: max #{max}; time #{time}; reload #{reload}")
+ now = Time.now
+
+ element = super
+
+ log("ended wait after #{Time.now - now} seconds")
+
+ element
+ end
+
+ def scroll_to(selector, text: nil)
+ msg = "scrolling to :#{selector}"
+ msg += " with text: #{text}" if text
+ log(msg)
+
+ super
+ end
+
+ def asset_exists?(url)
+ exists = super
+
+ log("asset_exists? #{url} returned #{exists}")
+
+ exists
+ end
+
+ def find_element(name)
+ log("finding :#{name}")
+
+ element = super
+
+ log("found :#{name}") if element
+
+ element
+ end
+
+ def all_elements(name)
+ log("finding all :#{name}")
+
+ elements = super
+
+ log("found #{elements.size} :#{name}") if elements
+
+ elements
+ end
+
+ def click_element(name)
+ log("clicking :#{name}")
+
+ super
+ end
+
+ def fill_element(name, content)
+ masked_content = name.to_s.include?('password') ? '*****' : content
+
+ log(%Q(filling :#{name} with "#{masked_content}"))
+
+ super
+ end
+
+ def has_element?(name)
+ found = super
+
+ log("has_element? :#{name} returned #{found}")
+
+ found
+ end
+
+ def within_element(name)
+ log("within element :#{name}")
+
+ element = super
+
+ log("end within element :#{name}")
+
+ element
+ end
+
+ private
+
+ def log(msg)
+ QA::Runtime::Logger.debug(msg)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/vendor/saml_idp/page/base.rb b/qa/qa/vendor/saml_idp/page/base.rb
new file mode 100644
index 00000000000..286cb0a8cd8
--- /dev/null
+++ b/qa/qa/vendor/saml_idp/page/base.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module QA
+ module Vendor
+ module SAMLIdp
+ module Page
+ class Base
+ include Capybara::DSL
+ include Scenario::Actable
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/vendor/saml_idp/page/login.rb b/qa/qa/vendor/saml_idp/page/login.rb
new file mode 100644
index 00000000000..9c1f9904a7a
--- /dev/null
+++ b/qa/qa/vendor/saml_idp/page/login.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'capybara/dsl'
+
+module QA
+ module Vendor
+ module SAMLIdp
+ module Page
+ class Login < Page::Base
+ def login
+ fill_in 'username', with: 'user1'
+ fill_in 'password', with: 'user1pass'
+ click_on 'Login'
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/spec/factory/base_spec.rb b/qa/spec/factory/base_spec.rb
deleted file mode 100644
index 04e04886699..00000000000
--- a/qa/spec/factory/base_spec.rb
+++ /dev/null
@@ -1,132 +0,0 @@
-describe QA::Factory::Base do
- let(:factory) { spy('factory') }
- let(:product) { spy('product') }
-
- describe '.fabricate!' do
- subject { Class.new(described_class) }
-
- before do
- allow(QA::Factory::Product).to receive(:new).and_return(product)
- allow(QA::Factory::Product).to receive(:populate!).and_return(product)
- end
-
- it 'instantiates the factory and calls factory method' do
- expect(subject).to receive(:new).and_return(factory)
-
- subject.fabricate!('something')
-
- expect(factory).to have_received(:fabricate!).with('something')
- end
-
- it 'returns fabrication product' do
- allow(subject).to receive(:new).and_return(factory)
-
- result = subject.fabricate!('something')
-
- expect(result).to eq product
- end
-
- it 'yields factory before calling factory method' do
- allow(subject).to receive(:new).and_return(factory)
-
- subject.fabricate! do |factory|
- factory.something!
- end
-
- expect(factory).to have_received(:something!).ordered
- expect(factory).to have_received(:fabricate!).ordered
- end
- end
-
- describe '.dependency' do
- let(:dependency) { spy('dependency') }
-
- before do
- stub_const('Some::MyDependency', dependency)
- end
-
- subject do
- Class.new(described_class) do
- dependency Some::MyDependency, as: :mydep do |factory|
- factory.something!
- end
- end
- end
-
- it 'appends a new dependency and accessors' do
- expect(subject.dependencies).to be_one
- end
-
- it 'defines dependency accessors' do
- expect(subject.new).to respond_to :mydep, :mydep=
- end
-
- describe 'dependencies fabrication' do
- let(:dependency) { double('dependency') }
- let(:instance) { spy('instance') }
-
- subject do
- Class.new(described_class) do
- dependency Some::MyDependency, as: :mydep
- end
- end
-
- before do
- stub_const('Some::MyDependency', dependency)
-
- allow(subject).to receive(:new).and_return(instance)
- allow(instance).to receive(:mydep).and_return(nil)
- allow(QA::Factory::Product).to receive(:new)
- allow(QA::Factory::Product).to receive(:populate!)
- end
-
- it 'builds all dependencies first' do
- expect(dependency).to receive(:fabricate!).once
-
- subject.fabricate!
- end
- end
- end
-
- describe '.product' do
- subject do
- Class.new(described_class) do
- def fabricate!
- "any"
- end
-
- # Defined only to be stubbed
- def self.find_page
- end
-
- product :token do
- find_page.do_something_on_page!
- 'resulting value'
- end
- end
- end
-
- it 'appends new product attribute' do
- expect(subject.attributes).to be_one
- expect(subject.attributes).to have_key(:token)
- end
-
- describe 'populating fabrication product with data' do
- let(:page) { spy('page') }
-
- before do
- allow(factory).to receive(:class).and_return(subject)
- allow(QA::Factory::Product).to receive(:new).and_return(product)
- allow(product).to receive(:page).and_return(page)
- allow(subject).to receive(:find_page).and_return(page)
- end
-
- it 'populates product after fabrication' do
- subject.fabricate!
-
- expect(product.token).to eq 'resulting value'
- expect(page).to have_received(:do_something_on_page!)
- end
- end
- end
-end
diff --git a/qa/spec/factory/dependency_spec.rb b/qa/spec/factory/dependency_spec.rb
deleted file mode 100644
index 8aaa6665a18..00000000000
--- a/qa/spec/factory/dependency_spec.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-describe QA::Factory::Dependency do
- let(:dependency) { spy('dependency' ) }
- let(:factory) { spy('factory') }
- let(:block) { spy('block') }
-
- let(:signature) do
- double('signature', factory: dependency, block: block)
- end
-
- subject do
- described_class.new(:mydep, factory, signature)
- end
-
- describe '#overridden?' do
- it 'returns true if factory has overridden dependency' do
- allow(factory).to receive(:mydep).and_return('something')
-
- expect(subject).to be_overridden
- end
-
- it 'returns false if dependency has not been overridden' do
- allow(factory).to receive(:mydep).and_return(nil)
-
- expect(subject).not_to be_overridden
- end
- end
-
- describe '#build!' do
- context 'when dependency has been overridden' do
- before do
- allow(subject).to receive(:overridden?).and_return(true)
- end
-
- it 'does not fabricate dependency' do
- subject.build!
-
- expect(dependency).not_to have_received(:fabricate!)
- end
- end
-
- context 'when dependency has not been overridden' do
- before do
- allow(subject).to receive(:overridden?).and_return(false)
- end
-
- it 'fabricates dependency' do
- subject.build!
-
- expect(dependency).to have_received(:fabricate!)
- end
-
- it 'sets product in the factory' do
- subject.build!
-
- expect(factory).to have_received(:mydep=).with(dependency)
- end
-
- context 'when receives a caller factory as block argument' do
- let(:dependency) { QA::Factory::Base }
-
- it 'calls given block with dependency factory and caller factory' do
- allow_any_instance_of(QA::Factory::Base).to receive(:fabricate!).and_return(factory)
- allow(QA::Factory::Product).to receive(:populate!).and_return(spy('any'))
-
- subject.build!
-
- expect(block).to have_received(:call).with(an_instance_of(QA::Factory::Base), factory)
- end
- end
- end
- end
-end
diff --git a/qa/spec/factory/product_spec.rb b/qa/spec/factory/product_spec.rb
deleted file mode 100644
index f245aabbf43..00000000000
--- a/qa/spec/factory/product_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-describe QA::Factory::Product do
- let(:factory) do
- QA::Factory::Base.new
- end
-
- let(:attributes) do
- { test: QA::Factory::Product::Attribute.new(:test, proc { 'returned' }) }
- end
-
- let(:product) { spy('product') }
-
- before do
- allow(QA::Factory::Base).to receive(:attributes).and_return(attributes)
- end
-
- describe '.populate!' do
- it 'returns a fabrication product and define factory attributes as its methods' do
- expect(described_class).to receive(:new).and_return(product)
-
- result = described_class.populate!(factory) do |instance|
- instance.something = 'string'
- end
-
- expect(result).to be product
- expect(result.test).to eq('returned')
- end
- end
-
- describe '.visit!' do
- it 'makes it possible to visit fabrication product' do
- allow_any_instance_of(described_class)
- .to receive(:current_url).and_return('some url')
- allow_any_instance_of(described_class)
- .to receive(:visit).and_return('visited some url')
-
- expect(subject.visit!).to eq 'visited some url'
- end
- end
-end
diff --git a/qa/spec/factory/resource/user_spec.rb b/qa/spec/factory/resource/user_spec.rb
new file mode 100644
index 00000000000..820c506b715
--- /dev/null
+++ b/qa/spec/factory/resource/user_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+describe QA::Resource::User do
+ describe "#fabricate_via_api!" do
+ Response = Struct.new(:code, :body)
+
+ it 'fetches an existing user' do
+ existing_users = [
+ {
+ id: '0',
+ name: 'name',
+ username: 'name',
+ web_url: ''
+ }
+ ]
+ users_response = Response.new('200', JSON.dump(existing_users))
+ single_user_response = Response.new('200', JSON.dump(existing_users.first))
+
+ expect(subject).to receive(:api_get_from).with("/users?username=name").and_return(users_response)
+ expect(subject).to receive(:api_get_from).with("/users/0").and_return(single_user_response)
+
+ subject.username = 'name'
+ subject.fabricate_via_api!
+
+ expect(subject.api_response).to eq(existing_users.first)
+ end
+
+ it 'tries to create a user if it does not exist' do
+ expect(subject).to receive(:api_get_from).with("/users?username=foo").and_return(Response.new('200', '[]'))
+ expect(subject).to receive(:api_post).and_return({ web_url: '' })
+
+ subject.username = 'foo'
+ subject.fabricate_via_api!
+ end
+ end
+end
diff --git a/qa/spec/git/repository_spec.rb b/qa/spec/git/repository_spec.rb
index 53bff3bf0b3..faa154c78da 100644
--- a/qa/spec/git/repository_spec.rb
+++ b/qa/spec/git/repository_spec.rb
@@ -1,17 +1,18 @@
describe QA::Git::Repository do
+ include Support::StubENV
+
let(:repository) { described_class.new }
before do
+ stub_env('GITLAB_USERNAME', 'root')
cd_empty_temp_directory
set_bad_uri
repository.use_default_credentials
end
describe '#clone' do
- it 'redacts credentials from the URI in output' do
- output, _ = repository.clone
-
- expect(output).to include("fatal: unable to access 'http://****@foo/bar.git/'")
+ it 'is unable to resolve host' do
+ expect(repository.clone).to include("fatal: unable to access 'http://root@foo/bar.git/'")
end
end
@@ -20,10 +21,38 @@ describe QA::Git::Repository do
`git init` # need a repo to push from
end
- it 'redacts credentials from the URI in output' do
- output, _ = repository.push_changes
+ it 'fails to push changes' do
+ expect(repository.push_changes).to include("error: failed to push some refs to 'http://root@foo/bar.git'")
+ end
+ end
+
+ describe '#git_protocol=' do
+ [0, 1, 2].each do |version|
+ it "configures git to use protocol version #{version}" do
+ expect(repository).to receive(:run).with("git config protocol.version #{version}")
+ repository.git_protocol = version
+ end
+ end
+
+ it 'raises an error if the version is unsupported' do
+ expect { repository.git_protocol = 'foo' }.to raise_error(ArgumentError, "Please specify the protocol you would like to use: 0, 1, or 2")
+ end
+ end
+
+ describe '#fetch_supported_git_protocol' do
+ it "reports the detected version" do
+ expect(repository).to receive(:run).and_return("packet: git< version 2")
+ expect(repository.fetch_supported_git_protocol).to eq('2')
+ end
+
+ it 'reports unknown if version is unknown' do
+ expect(repository).to receive(:run).and_return("packet: git< version -1")
+ expect(repository.fetch_supported_git_protocol).to eq('unknown')
+ end
- expect(output).to include("error: failed to push some refs to 'http://****@foo/bar.git'")
+ it 'reports unknown if content does not identify a version' do
+ expect(repository).to receive(:run).and_return("foo")
+ expect(repository.fetch_supported_git_protocol).to eq('unknown')
end
end
diff --git a/qa/spec/page/base_spec.rb b/qa/spec/page/base_spec.rb
index 52daa9697ee..076a8087db5 100644
--- a/qa/spec/page/base_spec.rb
+++ b/qa/spec/page/base_spec.rb
@@ -9,12 +9,12 @@ describe QA::Page::Base do
subject do
Class.new(described_class) do
view 'path/to/some/view.html.haml' do
- element :something, 'string pattern'
- element :something_else, /regexp pattern/
+ element :something, 'string pattern' # rubocop:disable QA/ElementWithPattern
+ element :something_else, /regexp pattern/ # rubocop:disable QA/ElementWithPattern
end
view 'path/to/some/_partial.html.haml' do
- element :another_element, 'string pattern'
+ element :another_element, 'string pattern' # rubocop:disable QA/ElementWithPattern
end
end
end
diff --git a/qa/spec/page/logging_spec.rb b/qa/spec/page/logging_spec.rb
new file mode 100644
index 00000000000..9d56353062b
--- /dev/null
+++ b/qa/spec/page/logging_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'capybara/dsl'
+
+describe QA::Support::Page::Logging do
+ include Support::StubENV
+
+ let(:page) { double().as_null_object }
+
+ before do
+ logger = Logger.new $stdout
+ logger.level = ::Logger::DEBUG
+ QA::Runtime::Logger.logger = logger
+
+ allow(Capybara).to receive(:current_session).and_return(page)
+ allow(page).to receive(:current_url).and_return('http://current-url')
+ allow(page).to receive(:has_css?).with(any_args).and_return(true)
+ end
+
+ subject do
+ Class.new(QA::Page::Base) do
+ prepend QA::Support::Page::Logging
+ end.new
+ end
+
+ it 'logs refresh' do
+ expect { subject.refresh }
+ .to output(%r{refreshing http://current-url}).to_stdout_from_any_process
+ end
+
+ it 'logs wait' do
+ expect { subject.wait(max: 0) {} }
+ .to output(/with wait/).to_stdout_from_any_process
+ expect { subject.wait(max: 0) {} }
+ .to output(/ended wait after .* seconds$/).to_stdout_from_any_process
+ end
+
+ it 'logs scroll_to' do
+ expect { subject.scroll_to(:element) }
+ .to output(/scrolling to :element/).to_stdout_from_any_process
+ end
+
+ it 'logs asset_exists?' do
+ expect { subject.asset_exists?('http://asset-url') }
+ .to output(%r{asset_exists\? http://asset-url returned false}).to_stdout_from_any_process
+ end
+
+ it 'logs find_element' do
+ expect { subject.find_element(:element) }
+ .to output(/found :element/).to_stdout_from_any_process
+ end
+
+ it 'logs click_element' do
+ expect { subject.click_element(:element) }
+ .to output(/clicking :element/).to_stdout_from_any_process
+ end
+
+ it 'logs fill_element' do
+ expect { subject.fill_element(:element, 'foo') }
+ .to output(/filling :element with "foo"/).to_stdout_from_any_process
+ end
+
+ it 'logs has_element?' do
+ expect { subject.has_element?(:element) }
+ .to output(/has_element\? :element returned true/).to_stdout_from_any_process
+ end
+
+ it 'logs within_element' do
+ expect { subject.within_element(:element) }
+ .to output(/within element :element/).to_stdout_from_any_process
+ expect { subject.within_element(:element) }
+ .to output(/end within element :element/).to_stdout_from_any_process
+ end
+
+ context 'all_elements' do
+ it 'logs the number of elements found' do
+ allow(page).to receive(:all).and_return([1, 2])
+
+ expect { subject.all_elements(:element) }
+ .to output(/finding all :element/).to_stdout_from_any_process
+ expect { subject.all_elements(:element) }
+ .to output(/found 2 :element/).to_stdout_from_any_process
+ end
+
+ it 'logs 0 if no elements are found' do
+ allow(page).to receive(:all).and_return([])
+
+ expect { subject.all_elements(:element) }
+ .to output(/finding all :element/).to_stdout_from_any_process
+ expect { subject.all_elements(:element) }
+ .not_to output(/found 0 :elements/).to_stdout_from_any_process
+ end
+ end
+end
diff --git a/qa/spec/page/validator_spec.rb b/qa/spec/page/validator_spec.rb
index 55957649904..0ae6e66d767 100644
--- a/qa/spec/page/validator_spec.rb
+++ b/qa/spec/page/validator_spec.rb
@@ -30,7 +30,7 @@ describe QA::Page::Validator do
let(:view) { spy('view') }
before do
- allow(QA::Page::Admin::Settings::Main)
+ allow(QA::Page::Admin::Settings::Repository)
.to receive(:views).and_return([view])
end
diff --git a/qa/spec/page/view_spec.rb b/qa/spec/page/view_spec.rb
index 34d2ff11447..d7b3ccd316d 100644
--- a/qa/spec/page/view_spec.rb
+++ b/qa/spec/page/view_spec.rb
@@ -8,8 +8,8 @@ describe QA::Page::View do
describe '.evaluate' do
it 'evaluates a block and returns a DSL object' do
results = described_class.evaluate do
- element :something, 'my pattern'
- element :something_else, /another pattern/
+ element :something
+ element :something_else
end
expect(results.elements.size).to eq 2
diff --git a/qa/spec/resource/api_fabricator_spec.rb b/qa/spec/resource/api_fabricator_spec.rb
new file mode 100644
index 00000000000..a5ed4422f6e
--- /dev/null
+++ b/qa/spec/resource/api_fabricator_spec.rb
@@ -0,0 +1,161 @@
+# frozen_string_literal: true
+
+describe QA::Resource::ApiFabricator do
+ let(:resource_without_api_support) do
+ Class.new do
+ def self.name
+ 'FooBarResource'
+ end
+ end
+ end
+
+ let(:resource_with_api_support) do
+ Class.new do
+ def self.name
+ 'FooBarResource'
+ end
+
+ def api_get_path
+ '/foo'
+ end
+
+ def api_post_path
+ '/bar'
+ end
+
+ def api_post_body
+ { name: 'John Doe' }
+ end
+ end
+ end
+
+ before do
+ allow(subject).to receive(:current_url).and_return('')
+ end
+
+ subject { resource.tap { |f| f.include(described_class) }.new }
+
+ describe '#api_support?' do
+ let(:api_client) { spy('Runtime::API::Client') }
+ let(:api_client_instance) { double('API Client') }
+
+ context 'when resource does not support fabrication via the API' do
+ let(:resource) { resource_without_api_support }
+
+ it 'returns false' do
+ expect(subject).not_to be_api_support
+ end
+ end
+
+ context 'when resource supports fabrication via the API' do
+ let(:resource) { resource_with_api_support }
+
+ it 'returns false' do
+ expect(subject).to be_api_support
+ end
+ end
+ end
+
+ describe '#fabricate_via_api!' do
+ let(:api_client) { spy('Runtime::API::Client') }
+ let(:api_client_instance) { double('API Client') }
+
+ before do
+ stub_const('QA::Runtime::API::Client', api_client)
+
+ allow(api_client).to receive(:new).and_return(api_client_instance)
+ allow(api_client_instance).to receive(:personal_access_token).and_return('foo')
+ end
+
+ context 'when resource does not support fabrication via the API' do
+ let(:resource) { resource_without_api_support }
+
+ it 'raises a NotImplementedError exception' do
+ expect { subject.fabricate_via_api! }.to raise_error(NotImplementedError, "Resource FooBarResource does not support fabrication via the API!")
+ end
+ end
+
+ context 'when resource supports fabrication via the API' do
+ let(:resource) { resource_with_api_support }
+ let(:api_request) { spy('Runtime::API::Request') }
+ let(:resource_web_url) { 'http://example.org/api/v4/foo' }
+ let(:response) { { id: 1, name: 'John Doe', web_url: resource_web_url } }
+ let(:raw_post) { double('Raw POST response', code: 201, body: response.to_json) }
+
+ before do
+ stub_const('QA::Runtime::API::Request', api_request)
+
+ allow(api_request).to receive(:new).and_return(double(url: resource_web_url))
+ end
+
+ context 'when creating a resource' do
+ before do
+ allow(subject).to receive(:post).with(resource_web_url, subject.api_post_body).and_return(raw_post)
+ end
+
+ it 'returns the resource URL' do
+ expect(api_request).to receive(:new).with(api_client_instance, subject.api_post_path).and_return(double(url: resource_web_url))
+ expect(subject).to receive(:post).with(resource_web_url, subject.api_post_body).and_return(raw_post)
+
+ expect(subject.fabricate_via_api!).to eq(resource_web_url)
+ end
+
+ it 'populates api_resource with the resource' do
+ subject.fabricate_via_api!
+
+ expect(subject.api_resource).to eq(response)
+ end
+
+ context 'when the POST fails' do
+ let(:post_response) { { error: "Name already taken." } }
+ let(:raw_post) { double('Raw POST response', code: 400, body: post_response.to_json) }
+
+ it 'raises a ResourceFabricationFailedError exception' do
+ expect(api_request).to receive(:new).with(api_client_instance, subject.api_post_path).and_return(double(url: resource_web_url))
+ expect(subject).to receive(:post).with(resource_web_url, subject.api_post_body).and_return(raw_post)
+
+ expect { subject.fabricate_via_api! }.to raise_error(described_class::ResourceFabricationFailedError, "Fabrication of FooBarResource using the API failed (400) with `#{raw_post}`.")
+ expect(subject.api_resource).to be_nil
+ end
+ end
+ end
+
+ context '#transform_api_resource' do
+ let(:resource) do
+ Class.new do
+ def self.name
+ 'FooBarResource'
+ end
+
+ def api_get_path
+ '/foo'
+ end
+
+ def api_post_path
+ '/bar'
+ end
+
+ def api_post_body
+ { name: 'John Doe' }
+ end
+
+ def transform_api_resource(resource)
+ resource[:new] = 'foobar'
+ resource
+ end
+ end
+ end
+
+ let(:response) { { existing: 'foo', web_url: resource_web_url } }
+ let(:transformed_resource) { { existing: 'foo', new: 'foobar', web_url: resource_web_url } }
+
+ it 'transforms the resource' do
+ expect(subject).to receive(:post).with(resource_web_url, subject.api_post_body).and_return(raw_post)
+ expect(subject).to receive(:transform_api_resource).with(response).and_return(transformed_resource)
+
+ subject.fabricate_via_api!
+ end
+ end
+ end
+ end
+end
diff --git a/qa/spec/resource/base_spec.rb b/qa/spec/resource/base_spec.rb
new file mode 100644
index 00000000000..dc9e16792d3
--- /dev/null
+++ b/qa/spec/resource/base_spec.rb
@@ -0,0 +1,246 @@
+# frozen_string_literal: true
+
+describe QA::Resource::Base do
+ include Support::StubENV
+
+ let(:resource) { spy('resource') }
+ let(:location) { 'http://location' }
+
+ shared_context 'fabrication context' do
+ subject do
+ Class.new(described_class) do
+ def self.name
+ 'MyResource'
+ end
+ end
+ end
+
+ before do
+ allow(subject).to receive(:current_url).and_return(location)
+ allow(subject).to receive(:new).and_return(resource)
+ end
+ end
+
+ shared_examples 'fabrication method' do |fabrication_method_called, actual_fabrication_method = nil|
+ let(:fabrication_method_used) { actual_fabrication_method || fabrication_method_called }
+
+ it 'yields resource before calling resource method' do
+ expect(resource).to receive(:something!).ordered
+ expect(resource).to receive(fabrication_method_used).ordered.and_return(location)
+
+ subject.public_send(fabrication_method_called, resource: resource) do |resource|
+ resource.something!
+ end
+ end
+
+ it 'does not log the resource and build method when QA_DEBUG=false' do
+ stub_env('QA_DEBUG', 'false')
+ expect(resource).to receive(fabrication_method_used).and_return(location)
+
+ expect { subject.public_send(fabrication_method_called, 'something', resource: resource) }
+ .not_to output.to_stdout
+ end
+ end
+
+ describe '.fabricate!' do
+ context 'when resource does not support fabrication via the API' do
+ before do
+ expect(described_class).to receive(:fabricate_via_api!).and_raise(NotImplementedError)
+ end
+
+ it 'calls .fabricate_via_browser_ui!' do
+ expect(described_class).to receive(:fabricate_via_browser_ui!)
+
+ described_class.fabricate!
+ end
+ end
+
+ context 'when resource supports fabrication via the API' do
+ it 'calls .fabricate_via_browser_ui!' do
+ expect(described_class).to receive(:fabricate_via_api!)
+
+ described_class.fabricate!
+ end
+ end
+ end
+
+ describe '.fabricate_via_api!' do
+ include_context 'fabrication context'
+
+ it_behaves_like 'fabrication method', :fabricate_via_api!
+
+ it 'instantiates the resource, calls resource method returns the resource' do
+ expect(resource).to receive(:fabricate_via_api!).and_return(location)
+
+ result = subject.fabricate_via_api!(resource: resource, parents: [])
+
+ expect(result).to eq(resource)
+ end
+
+ it 'logs the resource and build method when QA_DEBUG=true' do
+ stub_env('QA_DEBUG', 'true')
+ expect(resource).to receive(:fabricate_via_api!).and_return(location)
+
+ expect { subject.fabricate_via_api!('something', resource: resource, parents: []) }
+ .to output(/==> Built a MyResource via api in [\d\.\-e]+ seconds+/)
+ .to_stdout
+ end
+ end
+
+ describe '.fabricate_via_browser_ui!' do
+ include_context 'fabrication context'
+
+ it_behaves_like 'fabrication method', :fabricate_via_browser_ui!, :fabricate!
+
+ it 'instantiates the resource and calls resource method' do
+ subject.fabricate_via_browser_ui!('something', resource: resource, parents: [])
+
+ expect(resource).to have_received(:fabricate!).with('something')
+ end
+
+ it 'returns fabrication resource' do
+ result = subject.fabricate_via_browser_ui!('something', resource: resource, parents: [])
+
+ expect(result).to eq(resource)
+ end
+
+ it 'logs the resource and build method when QA_DEBUG=true' do
+ stub_env('QA_DEBUG', 'true')
+
+ expect { subject.fabricate_via_browser_ui!('something', resource: resource, parents: []) }
+ .to output(/==> Built a MyResource via browser_ui in [\d\.\-e]+ seconds+/)
+ .to_stdout
+ end
+ end
+
+ shared_context 'simple resource' do
+ subject do
+ Class.new(QA::Resource::Base) do
+ attribute :test do
+ 'block'
+ end
+
+ attribute :no_block
+
+ def fabricate!
+ 'any'
+ end
+
+ def self.current_url
+ 'http://stub'
+ end
+ end
+ end
+
+ let(:resource) { subject.new }
+ end
+
+ describe '.attribute' do
+ include_context 'simple resource'
+
+ it 'appends new attribute' do
+ expect(subject.attributes_names).to eq([:no_block, :test, :web_url])
+ end
+
+ context 'when the attribute is populated via a block' do
+ it 'returns value from the block' do
+ result = subject.fabricate!(resource: resource)
+
+ expect(result).to be_a(described_class)
+ expect(result.test).to eq('block')
+ end
+ end
+
+ context 'when the attribute is populated via the api' do
+ let(:api_resource) { { no_block: 'api' } }
+
+ before do
+ expect(resource).to receive(:api_resource).and_return(api_resource)
+ end
+
+ it 'returns value from api' do
+ result = subject.fabricate!(resource: resource)
+
+ expect(result).to be_a(described_class)
+ expect(result.no_block).to eq('api')
+ end
+
+ context 'when the attribute also has a block' do
+ let(:api_resource) { { test: 'api_with_block' } }
+
+ before do
+ allow(QA::Runtime::Logger).to receive(:info)
+ end
+
+ it 'returns value from api and emits an INFO log entry' do
+ result = subject.fabricate!(resource: resource)
+
+ expect(result).to be_a(described_class)
+ expect(result.test).to eq('api_with_block')
+ expect(QA::Runtime::Logger)
+ .to have_received(:info).with(/api_with_block/)
+ end
+ end
+ end
+
+ context 'when the attribute is populated via direct assignment' do
+ before do
+ resource.test = 'value'
+ end
+
+ it 'returns value from the assignment' do
+ result = subject.fabricate!(resource: resource)
+
+ expect(result).to be_a(described_class)
+ expect(result.test).to eq('value')
+ end
+
+ context 'when the api also has such response' do
+ before do
+ allow(resource).to receive(:api_resource).and_return({ test: 'api' })
+ end
+
+ it 'returns value from the assignment' do
+ result = subject.fabricate!(resource: resource)
+
+ expect(result).to be_a(described_class)
+ expect(result.test).to eq('value')
+ end
+ end
+ end
+
+ context 'when the attribute has no value' do
+ it 'raises an error because no values could be found' do
+ result = subject.fabricate!(resource: resource)
+
+ expect { result.no_block }
+ .to raise_error(described_class::NoValueError, "No value was computed for no_block of #{resource.class.name}.")
+ end
+ end
+ end
+
+ describe '#web_url' do
+ include_context 'simple resource'
+
+ it 'sets #web_url to #current_url after fabrication' do
+ subject.fabricate!(resource: resource)
+
+ expect(resource.web_url).to eq(subject.current_url)
+ end
+ end
+
+ describe '#visit!' do
+ include_context 'simple resource'
+
+ before do
+ allow(resource).to receive(:visit)
+ end
+
+ it 'calls #visit with the underlying #web_url' do
+ resource.web_url = subject.current_url
+ resource.visit!
+
+ expect(resource).to have_received(:visit).with(subject.current_url)
+ end
+ end
+end
diff --git a/qa/spec/resource/repository/push_spec.rb b/qa/spec/resource/repository/push_spec.rb
new file mode 100644
index 00000000000..bf3ebce0cfe
--- /dev/null
+++ b/qa/spec/resource/repository/push_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+describe QA::Resource::Repository::Push do
+ describe '.files=' do
+ let(:files) do
+ [
+ {
+ name: 'file.txt',
+ content: 'foo'
+ }
+ ]
+ end
+
+ it 'raises an error if files is not an array' do
+ expect { subject.files = '' }.to raise_error(ArgumentError)
+ end
+
+ it 'raises an error if files is an empty array' do
+ expect { subject.files = [] }.to raise_error(ArgumentError)
+ end
+
+ it 'does not raise if files is an array' do
+ expect { subject.files = files }.not_to raise_error
+ end
+ end
+end
diff --git a/qa/spec/runtime/api/client_spec.rb b/qa/spec/runtime/api/client_spec.rb
index d497d8839b8..975586b505f 100644
--- a/qa/spec/runtime/api/client_spec.rb
+++ b/qa/spec/runtime/api/client_spec.rb
@@ -13,18 +13,27 @@ describe QA::Runtime::API::Client do
end
end
- describe '#get_personal_access_token' do
- it 'returns specified token from env' do
- stub_env('PERSONAL_ACCESS_TOKEN', 'a_token')
+ describe '#personal_access_token' do
+ context 'when QA::Runtime::Env.personal_access_token is present' do
+ before do
+ allow(QA::Runtime::Env).to receive(:personal_access_token).and_return('a_token')
+ end
- expect(described_class.new.get_personal_access_token).to eq 'a_token'
+ it 'returns specified token from env' do
+ expect(described_class.new.personal_access_token).to eq 'a_token'
+ end
end
- it 'returns a created token' do
- allow_any_instance_of(described_class)
- .to receive(:create_personal_access_token).and_return('created_token')
+ context 'when QA::Runtime::Env.personal_access_token is nil' do
+ before do
+ allow(QA::Runtime::Env).to receive(:personal_access_token).and_return(nil)
+ end
- expect(described_class.new.get_personal_access_token).to eq 'created_token'
+ it 'returns a created token' do
+ expect(subject).to receive(:create_personal_access_token).and_return('created_token')
+
+ expect(subject.personal_access_token).to eq 'created_token'
+ end
end
end
end
diff --git a/qa/spec/runtime/api/request_spec.rb b/qa/spec/runtime/api/request_spec.rb
index 80e3149f32d..08233e3c1d6 100644
--- a/qa/spec/runtime/api/request_spec.rb
+++ b/qa/spec/runtime/api/request_spec.rb
@@ -1,17 +1,23 @@
describe QA::Runtime::API::Request do
- include Support::StubENV
+ let(:client) { QA::Runtime::API::Client.new('http://example.com') }
+ let(:request) { described_class.new(client, '/users') }
before do
- stub_env('PERSONAL_ACCESS_TOKEN', 'a_token')
+ allow(client).to receive(:personal_access_token).and_return('a_token')
end
- let(:client) { QA::Runtime::API::Client.new('http://example.com') }
- let(:request) { described_class.new(client, '/users') }
-
describe '#url' do
- it 'returns the full api request url' do
+ it 'returns the full API request url' do
expect(request.url).to eq 'http://example.com/api/v4/users?private_token=a_token'
end
+
+ context 'when oauth_access_token is passed in the query string' do
+ let(:request) { described_class.new(client, '/users', { oauth_access_token: 'foo' }) }
+
+ it 'does not adds a private_token query string' do
+ expect(request.url).to eq 'http://example.com/api/v4/users?oauth_access_token=foo'
+ end
+ end
end
describe '#request_path' do
diff --git a/qa/spec/runtime/api_request_spec.rb b/qa/spec/runtime/api_request_spec.rb
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/qa/spec/runtime/api_request_spec.rb
+++ /dev/null
diff --git a/qa/spec/runtime/env_spec.rb b/qa/spec/runtime/env_spec.rb
index d889d185a45..ded51d5bb7c 100644
--- a/qa/spec/runtime/env_spec.rb
+++ b/qa/spec/runtime/env_spec.rb
@@ -1,39 +1,66 @@
+# frozen_string_literal: true
+
describe QA::Runtime::Env do
include Support::StubENV
- describe '.chrome_headless?' do
+ shared_examples 'boolean method' do |**kwargs|
+ it_behaves_like 'boolean method with parameter', kwargs
+ end
+
+ shared_examples 'boolean method with parameter' do |method:, param: nil, env_key:, default:|
context 'when there is an env variable set' do
it 'returns false when falsey values specified' do
- stub_env('CHROME_HEADLESS', 'false')
- expect(described_class.chrome_headless?).to be_falsey
+ stub_env(env_key, 'false')
+ expect(described_class.public_send(method, *param)).to be_falsey
- stub_env('CHROME_HEADLESS', 'no')
- expect(described_class.chrome_headless?).to be_falsey
+ stub_env(env_key, 'no')
+ expect(described_class.public_send(method, *param)).to be_falsey
- stub_env('CHROME_HEADLESS', '0')
- expect(described_class.chrome_headless?).to be_falsey
+ stub_env(env_key, '0')
+ expect(described_class.public_send(method, *param)).to be_falsey
end
it 'returns true when anything else specified' do
- stub_env('CHROME_HEADLESS', 'true')
- expect(described_class.chrome_headless?).to be_truthy
+ stub_env(env_key, 'true')
+ expect(described_class.public_send(method, *param)).to be_truthy
- stub_env('CHROME_HEADLESS', '1')
- expect(described_class.chrome_headless?).to be_truthy
+ stub_env(env_key, '1')
+ expect(described_class.public_send(method, *param)).to be_truthy
- stub_env('CHROME_HEADLESS', 'anything')
- expect(described_class.chrome_headless?).to be_truthy
+ stub_env(env_key, 'anything')
+ expect(described_class.public_send(method, *param)).to be_truthy
end
end
context 'when there is no env variable set' do
- it 'returns the default, true' do
- stub_env('CHROME_HEADLESS', nil)
- expect(described_class.chrome_headless?).to be_truthy
+ it "returns the default, #{default}" do
+ stub_env(env_key, nil)
+ expect(described_class.public_send(method, *param)).to be(default)
end
end
end
+ describe '.signup_disabled?' do
+ it_behaves_like 'boolean method',
+ method: :signup_disabled?,
+ env_key: 'SIGNUP_DISABLED',
+ default: false
+ end
+
+ describe '.debug?' do
+ it_behaves_like 'boolean method',
+ method: :debug?,
+ env_key: 'QA_DEBUG',
+ default: false
+ end
+
+ describe '.chrome_headless?' do
+ it_behaves_like 'boolean method',
+ method: :chrome_headless?,
+ env_key: 'CHROME_HEADLESS',
+ default: true
+ end
+
describe '.running_in_ci?' do
context 'when there is an env variable set' do
it 'returns true if CI' do
@@ -56,7 +83,54 @@ describe QA::Runtime::Env do
end
end
+ describe '.personal_access_token' do
+ around do |example|
+ described_class.instance_variable_set(:@personal_access_token, nil)
+ example.run
+ described_class.instance_variable_set(:@personal_access_token, nil)
+ end
+
+ context 'when PERSONAL_ACCESS_TOKEN is set' do
+ before do
+ stub_env('PERSONAL_ACCESS_TOKEN', 'a_token')
+ end
+
+ it 'returns specified token from env' do
+ expect(described_class.personal_access_token).to eq 'a_token'
+ end
+ end
+
+ context 'when @personal_access_token is set' do
+ before do
+ described_class.personal_access_token = 'another_token'
+ end
+
+ it 'returns the instance variable value' do
+ expect(described_class.personal_access_token).to eq 'another_token'
+ end
+ end
+ end
+
+ describe '.personal_access_token=' do
+ around do |example|
+ described_class.instance_variable_set(:@personal_access_token, nil)
+ example.run
+ described_class.instance_variable_set(:@personal_access_token, nil)
+ end
+
+ it 'saves the token' do
+ described_class.personal_access_token = 'a_token'
+
+ expect(described_class.personal_access_token).to eq 'a_token'
+ end
+ end
+
describe '.forker?' do
+ before do
+ stub_env('GITLAB_FORKER_USERNAME', nil)
+ stub_env('GITLAB_FORKER_PASSWORD', nil)
+ end
+
it 'returns false if no forker credentials are defined' do
expect(described_class).not_to be_forker
end
@@ -107,4 +181,30 @@ describe QA::Runtime::Env do
expect { described_class.require_github_access_token! }.not_to raise_error
end
end
+
+ describe '.log_destination' do
+ it 'returns $stdout if QA_LOG_PATH is not defined' do
+ stub_env('QA_LOG_PATH', nil)
+
+ expect(described_class.log_destination).to eq($stdout)
+ end
+
+ it 'returns the path if QA_LOG_PATH is defined' do
+ stub_env('QA_LOG_PATH', 'path/to_file')
+
+ expect(described_class.log_destination).to eq('path/to_file')
+ end
+ end
+
+ describe '.can_test?' do
+ it_behaves_like 'boolean method with parameter',
+ method: :can_test?,
+ param: :git_protocol_v2,
+ env_key: 'QA_CAN_TEST_GIT_PROTOCOL_V2',
+ default: true
+
+ it 'raises ArgumentError if feature is unknown' do
+ expect { described_class.can_test? :foo }.to raise_error(ArgumentError, 'Unknown feature "foo"')
+ end
+ end
end
diff --git a/qa/spec/runtime/logger_spec.rb b/qa/spec/runtime/logger_spec.rb
new file mode 100644
index 00000000000..44be3381bff
--- /dev/null
+++ b/qa/spec/runtime/logger_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+describe QA::Runtime::Logger do
+ before do
+ logger = Logger.new $stdout
+ logger.level = ::Logger::DEBUG
+ described_class.logger = logger
+ end
+
+ it 'logs debug' do
+ expect { described_class.debug('test') }.to output(/DEBUG -- : test/).to_stdout_from_any_process
+ end
+
+ it 'logs info' do
+ expect { described_class.info('test') }.to output(/INFO -- : test/).to_stdout_from_any_process
+ end
+
+ it 'logs warn' do
+ expect { described_class.warn('test') }.to output(/WARN -- : test/).to_stdout_from_any_process
+ end
+
+ it 'logs error' do
+ expect { described_class.error('test') }.to output(/ERROR -- : test/).to_stdout_from_any_process
+ end
+
+ it 'logs fatal' do
+ expect { described_class.fatal('test') }.to output(/FATAL -- : test/).to_stdout_from_any_process
+ end
+
+ it 'logs unknown' do
+ expect { described_class.unknown('test') }.to output(/ANY -- : test/).to_stdout_from_any_process
+ end
+end
diff --git a/qa/spec/scenario/test/integration/instance_saml_spec.rb b/qa/spec/scenario/test/integration/instance_saml_spec.rb
new file mode 100644
index 00000000000..cb8a6a630cc
--- /dev/null
+++ b/qa/spec/scenario/test/integration/instance_saml_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+describe QA::Scenario::Test::Integration::InstanceSAML do
+ context '#perform' do
+ it_behaves_like 'a QA scenario class' do
+ let(:tags) { [:instance_saml] }
+ end
+ end
+end
diff --git a/qa/spec/scenario/test/integration/ldap_spec.rb b/qa/spec/scenario/test/integration/ldap_spec.rb
index 198856aec3f..b6d798bf504 100644
--- a/qa/spec/scenario/test/integration/ldap_spec.rb
+++ b/qa/spec/scenario/test/integration/ldap_spec.rb
@@ -1,9 +1,17 @@
# frozen_string_literal: true
-describe QA::Scenario::Test::Integration::LDAP do
+describe QA::Scenario::Test::Integration::LDAPNoTLS do
context '#perform' do
it_behaves_like 'a QA scenario class' do
- let(:tags) { [:ldap] }
+ let(:tags) { [:ldap_no_tls] }
+ end
+ end
+end
+
+describe QA::Scenario::Test::Integration::LDAPTLS do
+ context '#perform' do
+ it_behaves_like 'a QA scenario class' do
+ let(:tags) { [:ldap_tls] }
end
end
end
diff --git a/qa/spec/spec_helper.rb b/qa/spec/spec_helper.rb
index 8e6613cd688..8e01da01340 100644
--- a/qa/spec/spec_helper.rb
+++ b/qa/spec/spec_helper.rb
@@ -3,6 +3,10 @@ require_relative '../qa'
Dir[::File.join(__dir__, 'support', '**', '*.rb')].each { |f| require f }
RSpec.configure do |config|
+ config.before do |example|
+ QA::Runtime::Logger.debug("Starting test: #{example.full_description}") if QA::Runtime::Env.debug?
+ end
+
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
diff --git a/qa/spec/specs/runner_spec.rb b/qa/spec/specs/runner_spec.rb
index cf22d1c9395..741821ddf8c 100644
--- a/qa/spec/specs/runner_spec.rb
+++ b/qa/spec/specs/runner_spec.rb
@@ -62,6 +62,34 @@ describe QA::Specs::Runner do
end
end
+ context 'when SIGNUP_DISABLED is true' do
+ before do
+ allow(QA::Runtime::Env).to receive(:signup_disabled?).and_return(true)
+ end
+
+ subject { described_class.new }
+
+ it 'it includes default args and excludes the skip_signup_disabled tag' do
+ expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~skip_signup_disabled', *described_class::DEFAULT_TEST_PATH_ARGS])
+
+ subject.perform
+ end
+ end
+
+ context 'when git protocol v2 is not supported' do
+ before do
+ allow(QA::Runtime::Env).to receive(:can_test?).with(:git_protocol_v2).and_return(false)
+ end
+
+ subject { described_class.new }
+
+ it 'it includes default args and excludes the requires_git_protocol_v2 tag' do
+ expect_rspec_runner_arguments(['--tag', '~orchestrated', '--tag', '~requires_git_protocol_v2', *described_class::DEFAULT_TEST_PATH_ARGS])
+
+ subject.perform
+ end
+ end
+
def expect_rspec_runner_arguments(arguments)
expect(RSpec::Core::Runner).to receive(:run)
.with(arguments, $stderr, $stdout)
diff --git a/rubocop/cop/code_reuse/active_record.rb b/rubocop/cop/code_reuse/active_record.rb
index d25e8548fd0..2be8f7c11aa 100644
--- a/rubocop/cop/code_reuse/active_record.rb
+++ b/rubocop/cop/code_reuse/active_record.rb
@@ -49,7 +49,6 @@ module RuboCop
limit: true,
lock: false,
many?: false,
- none: false,
offset: true,
order: true,
pluck: true,
diff --git a/rubocop/cop/group_public_or_visible_to_user.rb b/rubocop/cop/group_public_or_visible_to_user.rb
new file mode 100644
index 00000000000..beda0b7f8ba
--- /dev/null
+++ b/rubocop/cop/group_public_or_visible_to_user.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+#
+module RuboCop
+ module Cop
+ # Cop that blacklists the usage of Group.public_or_visible_to_user
+ class GroupPublicOrVisibleToUser < RuboCop::Cop::Cop
+ MSG = '`Group.public_or_visible_to_user` should be used with extreme care. ' \
+ 'Please ensure that you are not using it on its own and that the amount ' \
+ 'of rows being filtered is reasonable.'
+
+ def_node_matcher :public_or_visible_to_user?, <<~PATTERN
+ (send (const nil? :Group) :public_or_visible_to_user ...)
+ PATTERN
+
+ def on_send(node)
+ return unless public_or_visible_to_user?(node)
+
+ add_offense(node, location: :expression)
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/migration/add_reference.rb b/rubocop/cop/migration/add_reference.rb
index 4b67270c97a..1d471b9797e 100644
--- a/rubocop/cop/migration/add_reference.rb
+++ b/rubocop/cop/migration/add_reference.rb
@@ -8,7 +8,7 @@ module RuboCop
class AddReference < RuboCop::Cop::Cop
include MigrationHelpers
- MSG = '`add_reference` requires `index: true`'
+ MSG = '`add_reference` requires `index: true` or `index: { options... }`'
def on_send(node)
return unless in_migration?(node)
@@ -33,7 +33,12 @@ module RuboCop
private
def index_enabled?(pair)
- hash_key_type(pair) == :sym && hash_key_name(pair) == :index && pair.children[1].true_type?
+ return unless hash_key_type(pair) == :sym
+ return unless hash_key_name(pair) == :index
+
+ index = pair.children[1]
+
+ index.true_type? || index.hash_type?
end
def hash_key_type(pair)
diff --git a/rubocop/cop/qa/element_with_pattern.rb b/rubocop/cop/qa/element_with_pattern.rb
new file mode 100644
index 00000000000..9d80946f1ba
--- /dev/null
+++ b/rubocop/cop/qa/element_with_pattern.rb
@@ -0,0 +1,39 @@
+require_relative '../../qa_helpers'
+
+module RuboCop
+ module Cop
+ module QA
+ # This cop checks for the usage of factories in migration specs
+ #
+ # @example
+ #
+ # # bad
+ # let(:user) { create(:user) }
+ #
+ # # good
+ # let(:users) { table(:users) }
+ # let(:user) { users.create!(name: 'User 1', username: 'user1') }
+ class ElementWithPattern < RuboCop::Cop::Cop
+ include QAHelpers
+
+ MESSAGE = "Don't use a pattern for element, create a corresponding `%s` instead.".freeze
+
+ def on_send(node)
+ return unless in_qa_file?(node)
+ return unless method_name(node).to_s == 'element'
+
+ element_name, pattern = node.arguments
+ return unless pattern
+
+ add_offense(node, location: pattern.source_range, message: MESSAGE % "qa-#{element_name.value.to_s.tr('_', '-')}")
+ end
+
+ private
+
+ def method_name(node)
+ node.children[1]
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/safe_params.rb b/rubocop/cop/safe_params.rb
new file mode 100644
index 00000000000..250c16232e4
--- /dev/null
+++ b/rubocop/cop/safe_params.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module RuboCop
+ module Cop
+ class SafeParams < RuboCop::Cop::Cop
+ MSG = 'Use `safe_params` instead of `params` in url_for.'.freeze
+
+ METHOD_NAME_PATTERN = :url_for
+ UNSAFE_PARAM = :params
+
+ def on_send(node)
+ return unless method_name(node) == METHOD_NAME_PATTERN
+
+ add_offense(node, location: :expression) unless safe_params?(node)
+ end
+
+ private
+
+ def safe_params?(node)
+ node.descendants.each do |param_node|
+ next unless param_node.descendants.empty?
+
+ return false if method_name(param_node) == UNSAFE_PARAM
+ end
+
+ true
+ end
+
+ def method_name(node)
+ node.children[1]
+ end
+ end
+ end
+end
diff --git a/rubocop/qa_helpers.rb b/rubocop/qa_helpers.rb
new file mode 100644
index 00000000000..f4adf7f4e9f
--- /dev/null
+++ b/rubocop/qa_helpers.rb
@@ -0,0 +1,11 @@
+module RuboCop
+ # Module containing helper methods for writing QA cops.
+ module QAHelpers
+ # Returns true if the given node originated from the qa/ directory.
+ def in_qa_file?(node)
+ path = node.location.expression.source_buffer.name
+
+ path.start_with?(File.join(Dir.pwd, 'qa'))
+ end
+ end
+end
diff --git a/rubocop/rubocop.rb b/rubocop/rubocop.rb
index ff929c7b6ce..4489159f422 100644
--- a/rubocop/rubocop.rb
+++ b/rubocop/rubocop.rb
@@ -5,6 +5,7 @@ require_relative 'cop/gitlab/httparty'
require_relative 'cop/gitlab/finder_with_find_by'
require_relative 'cop/gitlab/union'
require_relative 'cop/include_sidekiq_worker'
+require_relative 'cop/safe_params'
require_relative 'cop/avoid_return_from_blocks'
require_relative 'cop/avoid_break_from_strong_memoize'
require_relative 'cop/avoid_route_redirect_leading_slash'
@@ -29,6 +30,7 @@ require_relative 'cop/migration/update_large_table'
require_relative 'cop/project_path_helper'
require_relative 'cop/rspec/env_assignment'
require_relative 'cop/rspec/factories_in_migration_specs'
+require_relative 'cop/qa/element_with_pattern'
require_relative 'cop/sidekiq_options_queue'
require_relative 'cop/destroy_all'
require_relative 'cop/ruby_interpolation_in_translation'
@@ -38,3 +40,4 @@ require_relative 'cop/code_reuse/service_class'
require_relative 'cop/code_reuse/presenter'
require_relative 'cop/code_reuse/serializer'
require_relative 'cop/code_reuse/active_record'
+require_relative 'cop/group_public_or_visible_to_user'
diff --git a/scripts/build_assets_image b/scripts/build_assets_image
new file mode 100755
index 00000000000..4e5ef977161
--- /dev/null
+++ b/scripts/build_assets_image
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# Exit early if we don't want to build the image
+if [[ "${BUILD_ASSETS_IMAGE}" != "true" ]]
+then
+ exit 0
+fi
+
+# Generate the image name based on the project this is being run in
+ASSETS_IMAGE_NAME=$(echo ${CI_PROJECT_NAME} |
+ awk '{
+ split($1, p, "-");
+ interim = sprintf("%s-assets-%s", p[1], p[2]);
+ sub(/-$/, "", interim);
+ print interim
+ }'
+)
+
+ASSETS_IMAGE_PATH=${CI_REGISTRY}/${CI_PROJECT_PATH}/${ASSETS_IMAGE_NAME}
+
+mkdir -p assets_container.build/public
+cp -r public/assets assets_container.build/public/
+cp Dockerfile.assets assets_container.build/
+docker build -t ${ASSETS_IMAGE_PATH}:${CI_COMMIT_REF_SLUG} -f assets_container.build/Dockerfile.assets assets_container.build/
+docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY}
+docker push ${ASSETS_IMAGE_PATH}
+
diff --git a/scripts/frontend/frontend_script_utils.js b/scripts/frontend/frontend_script_utils.js
index e42b912d359..e3d357b4a40 100644
--- a/scripts/frontend/frontend_script_utils.js
+++ b/scripts/frontend/frontend_script_utils.js
@@ -13,7 +13,8 @@ const execGitCmd = args =>
exec('git', args)
.trim()
.toString()
- .split('\n');
+ .split('\n')
+ .filter(Boolean);
module.exports = {
getStagedFiles: fileExtensionFilter => {
diff --git a/scripts/frontend/prettier.js b/scripts/frontend/prettier.js
index b66ba885701..ffb09ea9779 100644
--- a/scripts/frontend/prettier.js
+++ b/scripts/frontend/prettier.js
@@ -1,126 +1,116 @@
const glob = require('glob');
const prettier = require('prettier');
const fs = require('fs');
-const path = require('path');
-const prettierIgnore = require('ignore')();
+const { getStagedFiles } = require('./frontend_script_utils');
-const getStagedFiles = require('./frontend_script_utils').getStagedFiles;
+const matchExtensions = ['js', 'vue'];
+
+// This will improve glob performance by excluding certain directories.
+// The .prettierignore file will also be respected, but after the glob has executed.
+const globIgnore = ['**/node_modules/**', 'vendor/**', 'public/**'];
+
+const readFileAsync = (file, options) =>
+ new Promise((resolve, reject) => {
+ fs.readFile(file, options, function(err, data) {
+ if (err) reject(err);
+ else resolve(data);
+ });
+ });
+
+const writeFileAsync = (file, data, options) =>
+ new Promise((resolve, reject) => {
+ fs.writeFile(file, data, options, function(err) {
+ if (err) reject(err);
+ else resolve();
+ });
+ });
const mode = process.argv[2] || 'check';
const shouldSave = mode === 'save' || mode === 'save-all';
const allFiles = mode === 'check-all' || mode === 'save-all';
-let dirPath = process.argv[3] || '';
-if (dirPath && dirPath.charAt(dirPath.length - 1) !== '/') dirPath += '/';
-
-const config = {
- patterns: ['**/*.js', '**/*.vue', '**/*.scss'],
- /*
- * The ignore patterns below are just to reduce search time with glob, as it includes the
- * folders with the most ignored assets, the actual `.prettierignore` will be used later on
- */
- ignore: ['**/node_modules/**', '**/vendor/**', '**/public/**'],
- parsers: {
- js: 'babylon',
- vue: 'vue',
- scss: 'css',
- },
-};
+let globDir = process.argv[3] || '';
+if (globDir && globDir.charAt(globDir.length - 1) !== '/') globDir += '/';
-/*
- * Unfortunately the prettier API does not expose support for `.prettierignore` files, they however
- * use the ignore package, so we do the same. We simply cannot use the glob package, because
- * gitignore style is not compatible with globs ignore style.
- */
-prettierIgnore.add(
- fs
- .readFileSync(path.join(__dirname, '../../', '.prettierignore'))
- .toString()
- .trim()
- .split(/\r?\n/)
+console.log(
+ `Loading all ${allFiles ? '' : 'staged '}files ${globDir ? `within ${globDir} ` : ''}...`
);
-const availableExtensions = Object.keys(config.parsers);
-
-console.log(`Loading ${allFiles ? 'All' : 'Selected'} Files ...`);
+const globPatterns = matchExtensions.map(ext => `${globDir}**/*.${ext}`);
+const matchedFiles = allFiles
+ ? glob.sync(`{${globPatterns.join(',')}}`, { ignore: globIgnore })
+ : getStagedFiles(globPatterns);
+const matchedCount = matchedFiles.length;
-const stagedFiles =
- allFiles || dirPath ? null : getStagedFiles(availableExtensions.map(ext => `*.${ext}`));
-
-if (stagedFiles) {
- if (!stagedFiles.length || (stagedFiles.length === 1 && !stagedFiles[0])) {
- console.log('No matching staged files.');
- process.exit(1);
- }
- console.log(`Matching staged Files : ${stagedFiles.length}`);
+if (!matchedCount) {
+ console.log('No files found to process with prettier');
+ process.exit(0);
}
let didWarn = false;
-let didError = false;
-
-let files;
-if (allFiles) {
- const ignore = config.ignore;
- const patterns = config.patterns;
- const globPattern = patterns.length > 1 ? `{${patterns.join(',')}}` : `${patterns.join(',')}`;
- files = glob.sync(globPattern, { ignore }).filter(f => allFiles || stagedFiles.includes(f));
-} else if (dirPath) {
- const ignore = config.ignore;
- const patterns = config.patterns.map(item => {
- return dirPath + item;
- });
- const globPattern = patterns.length > 1 ? `{${patterns.join(',')}}` : `${patterns.join(',')}`;
- files = glob.sync(globPattern, { ignore });
-} else {
- files = stagedFiles.filter(f => availableExtensions.includes(f.split('.').pop()));
-}
-
-files = prettierIgnore.filter(files);
-
-if (!files.length) {
- console.log('No Files found to process with Prettier');
- process.exit(1);
-}
-
-console.log(`${shouldSave ? 'Updating' : 'Checking'} ${files.length} file(s)`);
-
-files.forEach(file => {
- try {
- prettier
- .resolveConfig(file)
- .then(options => {
- const fileExtension = file.split('.').pop();
- Object.assign(options, {
- parser: config.parsers[fileExtension],
+let passedCount = 0;
+let failedCount = 0;
+let ignoredCount = 0;
+
+console.log(`${shouldSave ? 'Updating' : 'Checking'} ${matchedCount} file(s)`);
+
+const fixCommand = `yarn prettier-${allFiles ? 'all' : 'staged'}-save`;
+const warningMessage = `
+===============================
+GitLab uses Prettier to format all JavaScript code.
+Please format each file listed below or run "${fixCommand}"
+===============================
+`;
+
+const checkFileWithOptions = (filePath, options) =>
+ readFileAsync(filePath, 'utf8').then(input => {
+ if (shouldSave) {
+ const output = prettier.format(input, options);
+ if (input === output) {
+ passedCount += 1;
+ } else {
+ return writeFileAsync(filePath, output, 'utf8').then(() => {
+ console.log(`Prettified : ${filePath}`);
+ failedCount += 1;
});
-
- const input = fs.readFileSync(file, 'utf8');
-
- if (shouldSave) {
- const output = prettier.format(input, options);
- if (output !== input) {
- fs.writeFileSync(file, output, 'utf8');
- console.log(`Prettified : ${file}`);
- }
- } else if (!prettier.check(input, options)) {
- if (!didWarn) {
- console.log(
- '\n===============================\nGitLab uses Prettier to format all JavaScript code.\nPlease format each file listed below or run "yarn prettier-staged-save"\n===============================\n'
- );
- didWarn = true;
- }
- console.log(`Prettify Manually : ${file}`);
+ }
+ } else {
+ if (prettier.check(input, options)) {
+ passedCount += 1;
+ } else {
+ if (!didWarn) {
+ console.log(warningMessage);
+ didWarn = true;
}
- })
- .catch(e => {
- console.log(`Error on loading the Config File: ${e.message}`);
- process.exit(1);
- });
- } catch (error) {
- didError = true;
- console.log(`\n\nError with ${file}: ${error.message}`);
- }
-});
+ console.log(`Prettify Manually : ${filePath}`);
+ failedCount += 1;
+ }
+ }
+ });
-if (didWarn || didError) {
- process.exit(1);
-}
+const checkFileWithPrettierConfig = filePath =>
+ prettier
+ .getFileInfo(filePath, { ignorePath: '.prettierignore' })
+ .then(({ ignored, inferredParser }) => {
+ if (ignored || !inferredParser) {
+ ignoredCount += 1;
+ return;
+ }
+ return prettier.resolveConfig(filePath).then(fileOptions => {
+ const options = { ...fileOptions, parser: inferredParser };
+ return checkFileWithOptions(filePath, options);
+ });
+ });
+
+Promise.all(matchedFiles.map(checkFileWithPrettierConfig))
+ .then(() => {
+ const failAction = shouldSave ? 'fixed' : 'failed';
+ console.log(
+ `\nSummary:\n ${matchedCount} files processed (${passedCount} passed, ${failedCount} ${failAction}, ${ignoredCount} ignored)\n`
+ );
+
+ if (didWarn) process.exit(1);
+ })
+ .catch(e => {
+ console.log(`\nAn error occurred while processing files with prettier: ${e.message}\n`);
+ process.exit(1);
+ });
diff --git a/scripts/lint-rugged b/scripts/lint-rugged
index d0c2c544c47..22e3e1f1505 100755
--- a/scripts/lint-rugged
+++ b/scripts/lint-rugged
@@ -1,21 +1,9 @@
#!/usr/bin/env ruby
ALLOWED = [
- # Can be fixed once Rugged is no longer used in production. Doesn't make Rugged calls.
- 'config/initializers/8_metrics.rb',
-
- # Can be deleted once wiki's are fully (mandatory) migrated
- 'config/initializers/gollum.rb',
-
- # Needs to be migrated, https://gitlab.com/gitlab-org/gitaly/issues/953
+ # Needed to handle repositories that are not in any storage
'lib/gitlab/bare_repository_import/repository.rb',
- # Needs to be migrated, https://gitlab.com/gitlab-org/gitaly/issues/954
- 'lib/tasks/gitlab/cleanup.rake',
-
- # The only place where Rugged code is still allowed in production
- 'lib/gitlab/git/',
-
# Needed to avoid using the git binary to validate a branch name
'lib/gitlab/git_ref_validator.rb'
].freeze
diff --git a/scripts/rails4-gemfile-lock-check b/scripts/rails4-gemfile-lock-check
new file mode 100755
index 00000000000..a74a49874e1
--- /dev/null
+++ b/scripts/rails4-gemfile-lock-check
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+
+echo -e "=> Checking if Gemfile.rails4.lock is up-to-date...\\n"
+
+cp Gemfile.rails4.lock Gemfile.rails4.lock.orig
+BUNDLE_GEMFILE=Gemfile.rails4 bundle install "$BUNDLE_INSTALL_FLAGS"
+diff -u Gemfile.rails4.lock.orig Gemfile.rails4.lock >/dev/null 2>&1
+
+if [ $? == 1 ]
+then
+ diff -u Gemfile.rails4.lock.orig Gemfile.rails4.lock
+
+ echo -e "\\n✖ ERROR: Gemfile.rails4.lock is not up-to-date!
+ Please run 'BUNDLE_GEMFILE=Gemfile.rails4 bundle install'\\n" >&2
+ exit 1
+fi
+
+echo "✔ Gemfile.rails4.lock is up-to-date"
+exit 0
diff --git a/scripts/rails5-gemfile-lock-check b/scripts/rails5-gemfile-lock-check
deleted file mode 100755
index da6f1b7145e..00000000000
--- a/scripts/rails5-gemfile-lock-check
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env bash
-
-echo -e "=> Checking if Gemfile.rails5.lock is up-to-date...\\n"
-
-cp Gemfile.rails5.lock Gemfile.rails5.lock.orig
-BUNDLE_GEMFILE=Gemfile.rails5 bundle install "$BUNDLE_INSTALL_FLAGS"
-diff -u Gemfile.rails5.lock.orig Gemfile.rails5.lock >/dev/null 2>&1
-
-if [ $? == 1 ]
-then
- diff -u Gemfile.rails5.lock.orig Gemfile.rails5.lock
-
- echo -e "\\n✖ ERROR: Gemfile.rails5.lock is not up-to-date!
- Please run 'BUNDLE_GEMFILE=Gemfile.rails5 bundle install'\\n" >&2
- exit 1
-fi
-
-echo "✔ Gemfile.rails5.lock is up-to-date"
-exit 0
diff --git a/scripts/review_apps/automated_cleanup.rb b/scripts/review_apps/automated_cleanup.rb
new file mode 100755
index 00000000000..4166070f7cd
--- /dev/null
+++ b/scripts/review_apps/automated_cleanup.rb
@@ -0,0 +1,161 @@
+# frozen_string_literal: true
+
+require 'gitlab'
+require_relative File.expand_path('../../lib/quality/helm_client.rb', __dir__)
+require_relative File.expand_path('../../lib/quality/kubernetes_client.rb', __dir__)
+
+class AutomatedCleanup
+ attr_reader :project_path, :gitlab_token
+
+ DEPLOYMENTS_PER_PAGE = 100
+ HELM_RELEASES_BATCH_SIZE = 5
+ IGNORED_HELM_ERRORS = [
+ 'transport is closing',
+ 'error upgrading connection'
+ ].freeze
+ IGNORED_KUBERNETES_ERRORS = [
+ 'NotFound'
+ ].freeze
+
+ def self.ee?
+ ENV['CI_PROJECT_NAME'] == 'gitlab-ee' || File.exist?('CHANGELOG-EE.md')
+ end
+
+ def initialize(project_path: ENV['CI_PROJECT_PATH'], gitlab_token: ENV['GITLAB_BOT_REVIEW_APPS_CLEANUP_TOKEN'])
+ @project_path = project_path
+ @gitlab_token = gitlab_token
+ ENV['TILLER_NAMESPACE'] ||= review_apps_namespace
+ end
+
+ def gitlab
+ @gitlab ||= begin
+ Gitlab.configure do |config|
+ config.endpoint = 'https://gitlab.com/api/v4'
+ # gitlab-bot's token "GitLab review apps cleanup"
+ config.private_token = gitlab_token
+ end
+
+ Gitlab
+ end
+ end
+
+ def review_apps_namespace
+ self.class.ee? ? 'review-apps-ee' : 'review-apps-ce'
+ end
+
+ def helm
+ @helm ||= Quality::HelmClient.new(namespace: review_apps_namespace)
+ end
+
+ def kubernetes
+ @kubernetes ||= Quality::KubernetesClient.new(namespace: review_apps_namespace)
+ end
+
+ def perform_gitlab_environment_cleanup!(days_for_stop:, days_for_delete:)
+ puts "Checking for review apps not updated in the last #{days_for_stop} days..."
+
+ checked_environments = []
+ delete_threshold = threshold_time(days: days_for_delete)
+ stop_threshold = threshold_time(days: days_for_stop)
+
+ gitlab.deployments(project_path, per_page: DEPLOYMENTS_PER_PAGE).auto_paginate do |deployment|
+ environment = deployment.environment
+
+ next unless environment.name.start_with?('review/')
+ next if checked_environments.include?(environment.slug)
+
+ last_deploy = deployment.created_at
+ deployed_at = Time.parse(last_deploy)
+
+ if deployed_at < delete_threshold
+ delete_environment(environment, deployment)
+ release = Quality::HelmClient::Release.new(environment.slug, 1, deployed_at.to_s, nil, nil, review_apps_namespace)
+ delete_helm_release(release)
+ elsif deployed_at < stop_threshold
+ stop_environment(environment, deployment)
+ else
+ print_release_state(subject: 'Review app', release_name: environment.slug, release_date: last_deploy, action: 'leaving')
+ end
+
+ checked_environments << environment.slug
+ end
+ end
+
+ def perform_helm_releases_cleanup!(days:)
+ puts "Checking for Helm releases not updated in the last #{days} days..."
+
+ threshold_day = threshold_time(days: days)
+
+ helm_releases.each do |release|
+ if release.status == 'FAILED' || release.last_update < threshold_day
+ delete_helm_release(release)
+ else
+ print_release_state(subject: 'Release', release_name: release.name, release_date: release.last_update, action: 'leaving')
+ end
+ end
+ end
+
+ private
+
+ def delete_environment(environment, deployment)
+ print_release_state(subject: 'Review app', release_name: environment.slug, release_date: deployment.created_at, action: 'deleting')
+ gitlab.delete_environment(project_path, environment.id)
+ end
+
+ def stop_environment(environment, deployment)
+ print_release_state(subject: 'Review app', release_name: environment.slug, release_date: deployment.created_at, action: 'stopping')
+ gitlab.stop_environment(project_path, environment.id)
+ end
+
+ def helm_releases
+ args = ['--all', '--date', "--max #{HELM_RELEASES_BATCH_SIZE}"]
+
+ helm.releases(args: args)
+ end
+
+ def delete_helm_release(release)
+ print_release_state(subject: 'Release', release_name: release.name, release_status: release.status, release_date: release.last_update, action: 'cleaning')
+ helm.delete(release_name: release.name)
+ kubernetes.cleanup(release_name: release.name)
+ rescue Quality::HelmClient::CommandFailedError => ex
+ raise ex unless ignore_exception?(ex.message, IGNORED_HELM_ERRORS)
+
+ puts "Ignoring the following Helm error:\n#{ex}\n"
+ rescue Quality::KubernetesClient::CommandFailedError => ex
+ raise ex unless ignore_exception?(ex.message, IGNORED_KUBERNETES_ERRORS)
+
+ puts "Ignoring the following Kubernetes error:\n#{ex}\n"
+ end
+
+ def threshold_time(days:)
+ Time.now - days * 24 * 3600
+ end
+
+ def ignore_exception?(exception_message, exceptions_ignored)
+ exception_message.match?(/(#{exceptions_ignored})/)
+ end
+
+ def print_release_state(subject:, release_name:, release_date:, action:, release_status: nil)
+ puts "\n#{subject} '#{release_name}' #{"(#{release_status}) " if release_status}was last deployed on #{release_date}: #{action} it.\n"
+ end
+end
+
+def timed(task)
+ start = Time.now
+ yield(self)
+ puts "#{task} finished in #{Time.now - start} seconds.\n"
+end
+
+automated_cleanup = AutomatedCleanup.new
+
+timed('Review apps cleanup') do
+ automated_cleanup.perform_gitlab_environment_cleanup!(days_for_stop: 2, days_for_delete: 3)
+end
+
+puts
+
+timed('Helm releases cleanup') do
+ automated_cleanup.perform_helm_releases_cleanup!(days: 3)
+end
+
+exit(0)
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
new file mode 100755
index 00000000000..f3f788e0217
--- /dev/null
+++ b/scripts/review_apps/review-apps.sh
@@ -0,0 +1,350 @@
+[[ "$TRACE" ]] && set -x
+export TILLER_NAMESPACE="$KUBE_NAMESPACE"
+
+function echoerr() { printf "\033[0;31m%s\n\033[0m" "$*" >&2; }
+
+function check_kube_domain() {
+ if [ -z ${REVIEW_APPS_DOMAIN+x} ]; then
+ echo "In order to deploy or use Review Apps, REVIEW_APPS_DOMAIN variable must be set"
+ echo "You can do it in Auto DevOps project settings or defining a variable at group or project level"
+ echo "You can also manually add it in .gitlab-ci.yml"
+ false
+ else
+ true
+ fi
+}
+
+function download_gitlab_chart() {
+ curl -o gitlab.tar.bz2 https://gitlab.com/charts/gitlab/-/archive/$GITLAB_HELM_CHART_REF/gitlab-$GITLAB_HELM_CHART_REF.tar.bz2
+ tar -xjf gitlab.tar.bz2
+ cd gitlab-$GITLAB_HELM_CHART_REF
+
+ helm init --client-only
+ helm repo add gitlab https://charts.gitlab.io
+ helm dependency update
+ helm dependency build
+}
+
+function ensure_namespace() {
+ kubectl describe namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE"
+}
+
+function install_tiller() {
+ echo "Checking Tiller..."
+ helm init --upgrade
+ kubectl rollout status -n "$TILLER_NAMESPACE" -w "deployment/tiller-deploy"
+ if ! helm version --debug; then
+ echo "Failed to init Tiller."
+ return 1
+ fi
+ echo ""
+}
+
+function create_secret() {
+ echo "Create secret..."
+
+ kubectl create secret generic -n "$KUBE_NAMESPACE" \
+ $CI_ENVIRONMENT_SLUG-gitlab-initial-root-password \
+ --from-literal=password=$REVIEW_APPS_ROOT_PASSWORD \
+ --dry-run -o json | kubectl apply -f -
+}
+
+function deployExists() {
+ local namespace="${1}"
+ local deploy="${2}"
+ helm status --tiller-namespace "${namespace}" "${deploy}" >/dev/null 2>&1
+ return $?
+}
+
+function previousDeployFailed() {
+ set +e
+ deploy="${1}"
+ echo "Checking for previous deployment of ${deploy}"
+ deployment_status=$(helm status ${deploy} >/dev/null 2>&1)
+ status=$?
+ # if `status` is `0`, deployment exists, has a status
+ if [ $status -eq 0 ]; then
+ echo "Previous deployment found, checking status"
+ deployment_status=$(helm status ${deploy} | grep ^STATUS | cut -d' ' -f2)
+ echo "Previous deployment state: $deployment_status"
+ if [[ "$deployment_status" == "FAILED" || "$deployment_status" == "PENDING_UPGRADE" || "$deployment_status" == "PENDING_INSTALL" ]]; then
+ status=0;
+ else
+ status=1;
+ fi
+ else
+ echo "Previous deployment NOT found."
+ fi
+ set -e
+ return $status
+}
+
+function deploy() {
+ track="${1-stable}"
+ name="$CI_ENVIRONMENT_SLUG"
+
+ if [[ "$track" != "stable" ]]; then
+ name="$name-$track"
+ fi
+
+ replicas="1"
+ service_enabled="false"
+ postgres_enabled="$POSTGRES_ENABLED"
+
+ IMAGE_REPOSITORY="registry.gitlab.com/gitlab-org/build/cng-mirror"
+ IMAGE_VERSION="${CI_PROJECT_NAME#gitlab-}"
+ gitlab_migrations_image_repository="${IMAGE_REPOSITORY}/gitlab-rails-${IMAGE_VERSION}"
+ gitlab_sidekiq_image_repository="${IMAGE_REPOSITORY}/gitlab-sidekiq-${IMAGE_VERSION}"
+ gitlab_unicorn_image_repository="${IMAGE_REPOSITORY}/gitlab-unicorn-${IMAGE_VERSION}"
+ gitlab_task_runner_image_repository="${IMAGE_REPOSITORY}/gitlab-task-runner-${IMAGE_VERSION}"
+ gitlab_gitaly_image_repository="${IMAGE_REPOSITORY}/gitaly"
+ gitlab_shell_image_repository="${IMAGE_REPOSITORY}/gitlab-shell"
+ gitlab_workhorse_image_repository="${IMAGE_REPOSITORY}/gitlab-workhorse-${IMAGE_VERSION}"
+
+ # canary uses stable db
+ [[ "$track" == "canary" ]] && postgres_enabled="false"
+
+ env_track=$( echo $track | tr -s '[:lower:]' '[:upper:]' )
+ env_slug=$( echo ${CI_ENVIRONMENT_SLUG//-/_} | tr -s '[:lower:]' '[:upper:]' )
+
+ if [[ "$track" == "stable" ]]; then
+ # for stable track get number of replicas from `PRODUCTION_REPLICAS`
+ eval new_replicas=\$${env_slug}_REPLICAS
+ service_enabled="true"
+ else
+ # for all tracks get number of replicas from `CANARY_PRODUCTION_REPLICAS`
+ eval new_replicas=\$${env_track}_${env_slug}_REPLICAS
+ fi
+ if [[ -n "$new_replicas" ]]; then
+ replicas="$new_replicas"
+ fi
+
+ # Cleanup and previous installs, as FAILED and PENDING_UPGRADE will cause errors with `upgrade`
+ if [ "$CI_ENVIRONMENT_SLUG" != "production" ] && previousDeployFailed "$CI_ENVIRONMENT_SLUG" ; then
+ echo "Deployment in bad state, cleaning up $CI_ENVIRONMENT_SLUG"
+ delete
+ cleanup
+ fi
+
+ create_secret
+
+ helm repo add gitlab https://charts.gitlab.io/
+ helm dep update .
+
+HELM_CMD=$(cat << EOF
+ helm upgrade --install \
+ --wait \
+ --timeout 600 \
+ --set global.appConfig.enableUsagePing=false \
+ --set releaseOverride="$CI_ENVIRONMENT_SLUG" \
+ --set global.hosts.hostSuffix="$HOST_SUFFIX" \
+ --set global.hosts.domain="$REVIEW_APPS_DOMAIN" \
+ --set certmanager.install=false \
+ --set global.ingress.configureCertmanager=false \
+ --set global.ingress.tls.secretName=tls-cert \
+ --set global.ingress.annotations."external-dns\.alpha\.kubernetes\.io/ttl"="10"
+ --set gitlab.unicorn.resources.requests.cpu=200m \
+ --set gitlab.sidekiq.resources.requests.cpu=100m \
+ --set gitlab.gitlab-shell.resources.requests.cpu=100m \
+ --set redis.resources.requests.cpu=100m \
+ --set minio.resources.requests.cpu=100m \
+ --set gitlab.migrations.image.repository="$gitlab_migrations_image_repository" \
+ --set gitlab.migrations.image.tag="$CI_COMMIT_REF_NAME" \
+ --set gitlab.sidekiq.image.repository="$gitlab_sidekiq_image_repository" \
+ --set gitlab.sidekiq.image.tag="$CI_COMMIT_REF_NAME" \
+ --set gitlab.unicorn.image.repository="$gitlab_unicorn_image_repository" \
+ --set gitlab.unicorn.image.tag="$CI_COMMIT_REF_NAME" \
+ --set gitlab.task-runner.image.repository="$gitlab_task_runner_image_repository" \
+ --set gitlab.task-runner.image.tag="$CI_COMMIT_REF_NAME" \
+ --set gitlab.gitaly.image.repository="registry.gitlab.com/gitlab-org/build/cng-mirror/gitaly" \
+ --set gitlab.gitaly.image.tag="v$GITALY_VERSION" \
+ --set gitlab.gitlab-shell.image.repository="registry.gitlab.com/gitlab-org/build/cng-mirror/gitlab-shell" \
+ --set gitlab.gitlab-shell.image.tag="v$GITLAB_SHELL_VERSION" \
+ --set gitlab.unicorn.workhorse.image="$gitlab_workhorse_image_repository" \
+ --set gitlab.unicorn.workhorse.tag="$CI_COMMIT_REF_NAME" \
+ --set nginx-ingress.controller.config.ssl-ciphers="ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4" \
+ --namespace="$KUBE_NAMESPACE" \
+ --version="$CI_PIPELINE_ID-$CI_JOB_ID" \
+ "$name" \
+ .
+EOF
+)
+
+ echo "Deploying with:"
+ echo $HELM_CMD
+
+ eval $HELM_CMD
+}
+
+function delete() {
+ track="${1-stable}"
+ name="$CI_ENVIRONMENT_SLUG"
+
+ if [ -z "$CI_ENVIRONMENT_SLUG" ]; then
+ echo "No release given, aborting the delete!"
+ return
+ fi
+
+ if [[ "$track" != "stable" ]]; then
+ name="$name-$track"
+ fi
+
+ if ! deployExists "${KUBE_NAMESPACE}" "${name}"; then
+ echo "The release $name doesn't exist, aborting the cleanup!"
+ return
+ fi
+
+ echo "Deleting release '$name'..."
+ helm delete --purge "$name" || true
+}
+
+function cleanup() {
+ if [ -z "$CI_ENVIRONMENT_SLUG" ]; then
+ echo "No release given, aborting the delete!"
+ return
+ fi
+
+ echo "Cleaning up '$CI_ENVIRONMENT_SLUG'..."
+ kubectl -n "$KUBE_NAMESPACE" delete \
+ ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa \
+ -l release="$CI_ENVIRONMENT_SLUG" \
+ || true
+}
+
+function install_external_dns() {
+ local release_name="dns-gitlab-review-app"
+ local domain=$(echo "${REVIEW_APPS_DOMAIN}" | awk -F. '{printf "%s.%s", $(NF-1), $NF}')
+
+ if ! deployExists "${KUBE_NAMESPACE}" "${release_name}" || previousDeployFailed "${release_name}" ; then
+ echo "Installing external-dns helm chart"
+ helm repo update
+ helm install stable/external-dns \
+ -n "${release_name}" \
+ --namespace "${KUBE_NAMESPACE}" \
+ --set provider="aws" \
+ --set aws.secretKey="${REVIEW_APPS_AWS_SECRET_KEY}" \
+ --set aws.accessKey="${REVIEW_APPS_AWS_ACCESS_KEY}" \
+ --set aws.zoneType="public" \
+ --set domainFilters[0]="${domain}" \
+ --set txtOwnerId="${KUBE_NAMESPACE}" \
+ --set rbac.create="true"
+ fi
+}
+
+function get_pod() {
+ local app_name="${1}"
+ local status="${2-Running}"
+ get_pod_cmd="kubectl get pods -n ${KUBE_NAMESPACE} --field-selector=status.phase=${status} -lapp=${app_name},release=${CI_ENVIRONMENT_SLUG} --no-headers -o=custom-columns=NAME:.metadata.name"
+ echoerr "Running '${get_pod_cmd}'"
+
+ while true; do
+ local pod_name="$(eval $get_pod_cmd)"
+ [[ "${pod_name}" == "" ]] || break
+
+ echoerr "Waiting till '${app_name}' pod is ready";
+ sleep 5;
+ done
+
+ echoerr "The pod name is '${pod_name}'."
+ echo "${pod_name}"
+}
+
+function add_license() {
+ if [ -z "${REVIEW_APPS_EE_LICENSE}" ]; then echo "License not found" && return; fi
+
+ task_runner_pod=$(get_pod "task-runner");
+ if [ -z "${task_runner_pod}" ]; then echo "Task runner pod not found" && return; fi
+
+ echo "${REVIEW_APPS_EE_LICENSE}" > /tmp/license.gitlab
+ kubectl -n "$KUBE_NAMESPACE" cp /tmp/license.gitlab ${task_runner_pod}:/tmp/license.gitlab
+ rm /tmp/license.gitlab
+
+ kubectl -n "$KUBE_NAMESPACE" exec -it ${task_runner_pod} -- /srv/gitlab/bin/rails runner -e production \
+ '
+ content = File.read("/tmp/license.gitlab").strip;
+ FileUtils.rm_f("/tmp/license.gitlab");
+
+ unless License.where(data:content).empty?
+ puts "License already exists";
+ Kernel.exit 0;
+ end
+
+ unless License.new(data: content).save
+ puts "Could not add license";
+ Kernel.exit 0;
+ end
+
+ puts "License added";
+ '
+}
+
+function get_job_id() {
+ local job_name="${1}"
+ local query_string="${2:+&${2}}"
+
+ local max_page=3
+ local page=1
+
+ while true; do
+ local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/pipelines/${CI_PIPELINE_ID}/jobs?per_page=100&page=${page}${query_string}"
+ echoerr "GET ${url}"
+
+ local job_id=$(curl --silent --show-error --header "PRIVATE-TOKEN: ${API_TOKEN}" "${url}" | jq ".[] | select(.name == \"${job_name}\") | .id")
+ [[ "${job_id}" == "" && "${page}" -lt "$max_page" ]] || break
+
+ ((page++))
+ done
+
+ if [[ "${job_id}" == "" ]]; then
+ echoerr "The '${job_name}' job ID couldn't be retrieved!"
+ else
+ echoerr "The '${job_name}' job ID is ${job_id}"
+ echo "${job_id}"
+ fi
+}
+
+function play_job() {
+ local job_name="${1}"
+ local job_id=$(get_job_id "${job_name}" "scope=manual");
+ if [ -z "${job_id}" ]; then return; fi
+
+ local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/${job_id}/play"
+ echoerr "POST ${url}"
+
+ local job_url=$(curl --silent --show-error --request POST --header "PRIVATE-TOKEN: ${API_TOKEN}" "${url}" | jq ".web_url")
+ echo "Manual job '${job_name}' started at: ${job_url}"
+}
+
+function wait_for_job_to_be_done() {
+ local job_name="${1}"
+ local query_string="${2}"
+ local job_id=$(get_job_id "${job_name}" "${query_string}");
+ if [ -z "${job_id}" ]; then return; fi
+
+ echoerr "Waiting for the '${job_name}' job to finish..."
+
+ local url="https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/jobs/${job_id}"
+ echo "GET ${url}"
+
+ # In case the job hasn't finished yet. Keep trying until the job times out.
+ local interval=30
+ local elapsed=0
+ while true; do
+ local job_status=$(curl --silent --show-error --header "PRIVATE-TOKEN: ${API_TOKEN}" "${url}" | jq ".status" | sed -e s/\"//g)
+ [[ "${job_status}" == "pending" || "${job_status}" == "running" ]] || break
+
+ printf "."
+ ((elapsed+=$interval))
+ sleep ${interval}
+ done
+
+ echoerr "Waited '${job_name}' for ${elapsed} seconds."
+
+ if [[ "${job_status}" == "failed" ]]; then
+ echo "The '${job_name}' failed."
+ elif [[ "${job_status}" == "manual" ]]; then
+ echo "The '${job_name}' is manual."
+ else
+ echo "The '${job_name}' passed."
+ fi
+}
diff --git a/scripts/static-analysis b/scripts/static-analysis
index 0e67eabfec1..25ba7ec6c8e 100755
--- a/scripts/static-analysis
+++ b/scripts/static-analysis
@@ -29,6 +29,7 @@ tasks = [
%w[bin/rake lint:all],
%w[bundle exec license_finder],
%w[yarn run eslint],
+ %w[yarn run prettier-all],
%w[bundle exec rubocop --parallel],
%w[scripts/lint-conflicts.sh],
%w[scripts/lint-rugged]
diff --git a/scripts/trigger-build b/scripts/trigger-build
index 798bf1e82b7..14af3281106 100755
--- a/scripts/trigger-build
+++ b/scripts/trigger-build
@@ -1,122 +1,176 @@
#!/usr/bin/env ruby
+# frozen_string_literal: true
-require 'net/http'
-require 'json'
-require 'cgi'
+require 'gitlab'
-module Trigger
- OMNIBUS_PROJECT_PATH = 'gitlab-org/omnibus-gitlab'.freeze
- CNG_PROJECT_PATH = 'gitlab-org/build/CNG'.freeze
- TOKEN = ENV['BUILD_TRIGGER_TOKEN']
+#
+# Configure credentials to be used with gitlab gem
+#
+Gitlab.configure do |config|
+ config.endpoint = 'https://gitlab.com/api/v4'
+end
+module Trigger
def self.ee?
ENV['CI_PROJECT_NAME'] == 'gitlab-ee' || File.exist?('CHANGELOG-EE.md')
end
- class Omnibus
- def initialize
- @uri = URI("https://gitlab.com/api/v4/projects/#{CGI.escape(Trigger::OMNIBUS_PROJECT_PATH)}/trigger/pipeline")
- @params = env_params.merge(file_params).merge(token: Trigger::TOKEN)
+ class Base
+ def invoke!(post_comment: false)
+ pipeline = Gitlab.run_trigger(
+ downstream_project_path,
+ trigger_token,
+ ref,
+ variables)
+
+ puts "Triggered downstream pipeline: #{pipeline.web_url}\n"
+ puts "Waiting for downstream pipeline status"
+
+ Trigger::CommitComment.post!(pipeline, access_token) if post_comment
+ Trigger::Pipeline.new(downstream_project_path, pipeline.id, access_token)
end
- def invoke!
- res = Net::HTTP.post_form(@uri, @params)
- id = JSON.parse(res.body)['id']
- project = Trigger::OMNIBUS_PROJECT_PATH
+ private
- if id
- puts "Triggered https://gitlab.com/#{project}/pipelines/#{id}"
- puts "Waiting for downstream pipeline status"
- else
- raise "Trigger failed! The response from the trigger is: #{res.body}"
- end
+ # Must be overridden
+ def downstream_project_path
+ raise NotImplementedError
+ end
- Trigger::Pipeline.new(project, id)
+ # Must be overridden
+ def ref
+ raise NotImplementedError
end
- private
+ # Must be overridden
+ def trigger_token
+ raise NotImplementedError
+ end
+
+ # Must be overridden
+ def access_token
+ raise NotImplementedError
+ end
+
+ # Can be overridden
+ def extra_variables
+ {}
+ end
+
+ # Can be overridden
+ def version_param_value(version_file)
+ File.read(version_file).strip
+ end
+
+ def variables
+ base_variables.merge(extra_variables).merge(version_file_variables)
+ end
- def env_params
+ def base_variables
{
- "ref" => ENV["OMNIBUS_BRANCH"] || "master",
- "variables[GITLAB_VERSION]" => ENV["CI_COMMIT_SHA"],
- "variables[ALTERNATIVE_SOURCES]" => true,
- "variables[ee]" => Trigger.ee? ? 'true' : 'false',
- "variables[TRIGGERED_USER]" => ENV["GITLAB_USER_NAME"],
- "variables[TRIGGER_SOURCE]" => "https://gitlab.com/gitlab-org/#{ENV['CI_PROJECT_NAME']}/-/jobs/#{ENV['CI_JOB_ID']}"
+ 'GITLAB_REF_SLUG' => ref_slug,
+ 'TRIGGERED_USER' => ENV['TRIGGERED_USER'] || ENV['GITLAB_USER_NAME'],
+ 'TRIGGER_SOURCE' => ENV['CI_JOB_URL'],
+ 'TOP_UPSTREAM_SOURCE_PROJECT' => ENV['CI_PROJECT_PATH'],
+ 'TOP_UPSTREAM_SOURCE_JOB' => ENV['CI_JOB_URL'],
+ 'TOP_UPSTREAM_SOURCE_SHA' => ENV['CI_COMMIT_SHA']
}
end
- def file_params
- Hash.new.tap do |params|
- Dir.glob("*_VERSION").each do |version_file|
- params["variables[#{version_file}]"] = File.read(version_file).strip
- end
+ def ref_slug
+ return 'master' if ENV['CI_COMMIT_REF_SLUG'] =~ %r{(\Aqa[/-]|-qa\z)}
+
+ ENV['CI_COMMIT_REF_SLUG']
+ end
+
+ # Read version files from all components
+ def version_file_variables
+ Dir.glob("*_VERSION").each_with_object({}) do |version_file, params|
+ params[version_file] = version_param_value(version_file)
end
end
end
- class CNG
- def initialize
- @uri = URI("https://gitlab.com/api/v4/projects/#{CGI.escape(Trigger::CNG_PROJECT_PATH)}/trigger/pipeline")
- @ref_name = ENV['CI_COMMIT_REF_NAME']
- @username = ENV['GITLAB_USER_NAME']
- @project_name = ENV['CI_PROJECT_NAME']
- @job_id = ENV['CI_JOB_ID']
- @params = env_params.merge(file_params).merge(token: Trigger::TOKEN)
- end
-
- #
- # Trigger a pipeline
- #
- def invoke!
- res = Net::HTTP.post_form(@uri, @params)
- id = JSON.parse(res.body)['id']
- project = Trigger::CNG_PROJECT_PATH
-
- if id
- puts "Triggered https://gitlab.com/#{project}/pipelines/#{id}"
- puts "Waiting for downstream pipeline status"
- else
- raise "Trigger failed! The response from the trigger is: #{res.body}"
- end
+ class Omnibus < Base
+ private
+
+ def downstream_project_path
+ 'gitlab-org/omnibus-gitlab'
+ end
+
+ def ref
+ ENV['OMNIBUS_BRANCH'] || 'master'
+ end
- Trigger::Pipeline.new(project, id)
+ def trigger_token
+ ENV['BUILD_TRIGGER_TOKEN']
end
+ def access_token
+ ENV['GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN']
+ end
+
+ def extra_variables
+ {
+ 'GITLAB_VERSION' => ENV['CI_COMMIT_SHA'],
+ 'ALTERNATIVE_SOURCES' => 'true',
+ 'ee' => Trigger.ee? ? 'true' : 'false',
+ 'QA_BRANCH' => ENV['QA_BRANCH'] || 'master'
+ }
+ end
+ end
+
+ class CNG < Base
private
- def env_params
- params = {
- "ref" => ENV["CNG_BRANCH"] || "master",
- "variables[TRIGGERED_USER]" => @username,
- "variables[TRIGGER_SOURCE]" => "https://gitlab.com/gitlab-org/#{@project_name}/-/jobs/#{@job_id}"
+ def downstream_project_path
+ ENV['CNG_PROJECT_PATH'] || 'gitlab-org/build/CNG-mirror'
+ end
+
+ def ref
+ ENV['CNG_BRANCH'] || 'master'
+ end
+
+ def trigger_token
+ ENV['BUILD_TRIGGER_TOKEN']
+ end
+
+ def access_token
+ ENV['GITLAB_BOT_MULTI_PROJECT_PIPELINE_POLLING_TOKEN']
+ end
+
+ def extra_variables
+ edition = Trigger.ee? ? 'EE' : 'CE'
+
+ {
+ "GITLAB_#{edition}_VERSION" => ENV['CI_COMMIT_REF_NAME'],
+ "#{edition}_PIPELINE" => 'true'
}
+ end
- if Trigger.ee?
- params["variables[GITLAB_EE_VERSION]"] = @ref_name
- params["variables[EE_PIPELINE]"] = 'true'
+ def version_param_value(_version_file)
+ raw_version = super
+
+ # if the version matches semver format, treat it as a tag and prepend `v`
+ if raw_version =~ Regexp.compile(/^\d+\.\d+\.\d+(-rc\d+)?(-ee)?$/)
+ "v#{raw_version}"
else
- params["variables[GITLAB_CE_VERSION]"] = @ref_name
- params["variables[CE_PIPELINE]"] = 'true'
+ raw_version
end
-
- params
end
+ end
- # Read version files from all components
- def file_params
- Dir.glob("*_VERSION").each_with_object({}) do |version_file, params|
- raw_version = File.read(version_file).strip
- # if the version matches semver format, treat it as a tag and prepend `v`
- version = if raw_version =~ Regexp.compile(/^\d+\.\d+\.\d+(-rc\d+)?(-ee)?$/)
- "v#{raw_version}"
- else
- raw_version
- end
-
- params["variables[#{version_file}]"] = version
- end
+ class CommitComment
+ def self.post!(downstream_pipeline, access_token)
+ Gitlab.private_token = access_token
+
+ Gitlab.create_commit_comment(
+ ENV['CI_PROJECT_PATH'],
+ ENV['CI_COMMIT_SHA'],
+ "The [`#{ENV['CI_JOB_NAME']}`](#{ENV['CI_JOB_URL']}) job from pipeline #{ENV['CI_PIPELINE_URL']} triggered #{downstream_pipeline.web_url} downstream.")
+
+ rescue Gitlab::Error::Error => error
+ puts "Ignoring the following error: #{error}"
end
end
@@ -124,9 +178,16 @@ module Trigger
INTERVAL = 60 # seconds
MAX_DURATION = 3600 * 3 # 3 hours
- def initialize(project, id)
+ attr_reader :project, :id, :api_token
+
+ def initialize(project, id, api_token)
+ @project = project
+ @id = id
+ @api_token = api_token
@start = Time.now.to_i
- @uri = URI("https://gitlab.com/api/v4/projects/#{CGI.escape(project)}/pipelines/#{id}")
+
+ # gitlab-bot's token "GitLab multi-project pipeline polling"
+ Gitlab.private_token = api_token
end
def wait!
@@ -157,15 +218,9 @@ module Trigger
end
def status
- req = Net::HTTP::Get.new(@uri)
- req['PRIVATE-TOKEN'] = ENV['GITLAB_QA_ACCESS_TOKEN']
-
- res = Net::HTTP.start(@uri.hostname, @uri.port, use_ssl: true) do |http|
- http.request(req)
- end
-
- JSON.parse(res.body)['status'].to_s.to_sym
- rescue JSON::ParserError
+ Gitlab.pipeline(project, id).status.to_sym
+ rescue Gitlab::Error::Error => error
+ puts "Ignoring the following error: #{error}"
# Ignore GitLab API hiccups. If GitLab is really down, we'll hit the job
# timeout anyway.
:running
@@ -175,7 +230,7 @@ end
case ARGV[0]
when 'omnibus'
- Trigger::Omnibus.new.invoke!.wait!
+ Trigger::Omnibus.new.invoke!(post_comment: true).wait!
when 'cng'
Trigger::CNG.new.invoke!.wait!
else
diff --git a/scripts/trigger-build-docs b/scripts/trigger-build-docs
index 9ee35684509..dfc8ee6050a 100755
--- a/scripts/trigger-build-docs
+++ b/scripts/trigger-build-docs
@@ -6,8 +6,8 @@ require 'gitlab'
# Configure credentials to be used with gitlab gem
#
Gitlab.configure do |config|
- config.endpoint = 'https://gitlab.com/api/v4'
- config.private_token = ENV["DOCS_API_TOKEN"] # GitLab Docs bot access token with Developer access to gitlab-docs
+ config.endpoint = 'https://gitlab.com/api/v4'
+ config.private_token = ENV["DOCS_API_TOKEN"] # GitLab Docs bot access token with Developer access to gitlab-docs
end
#
@@ -99,7 +99,7 @@ def trigger_pipeline
puts "=> Follow the status of the triggered pipeline:"
puts ""
- puts "https://gitlab.com/gitlab-com/gitlab-docs/pipelines/#{pipeline.id}"
+ puts pipeline.web_url
puts ""
puts "=> In a few minutes, you will be able to preview your changes under the following URL:"
puts ""
diff --git a/spec/bin/storage_check_spec.rb b/spec/bin/storage_check_spec.rb
deleted file mode 100644
index 02f6fcb6e3a..00000000000
--- a/spec/bin/storage_check_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-require 'spec_helper'
-
-describe 'bin/storage_check' do
- it 'is executable' do
- command = %w[bin/storage_check -t unix://the/path/to/a/unix-socket.sock -i 10 -d]
- expected_output = 'Checking unix://the/path/to/a/unix-socket.sock every 10 seconds'
-
- output, status = Gitlab::Popen.popen(command, Rails.root.to_s)
-
- expect(status).to eq(0)
- expect(output).to include(expected_output)
- end
-end
diff --git a/spec/controllers/admin/application_settings_controller_spec.rb b/spec/controllers/admin/application_settings_controller_spec.rb
index 10e1bfc30f9..2e0f79cd313 100644
--- a/spec/controllers/admin/application_settings_controller_spec.rb
+++ b/spec/controllers/admin/application_settings_controller_spec.rb
@@ -86,4 +86,22 @@ describe Admin::ApplicationSettingsController do
expect(ApplicationSetting.current.receive_max_input_size).to eq(1024)
end
end
+
+ describe 'PUT #reset_registration_token' do
+ before do
+ sign_in(admin)
+ end
+
+ subject { put :reset_registration_token }
+
+ it 'resets runner registration token' do
+ expect { subject }.to change { ApplicationSetting.current.runners_registration_token }
+ end
+
+ it 'redirects the user to admin runners page' do
+ subject
+
+ expect(response).to redirect_to(admin_runners_path)
+ end
+ end
end
diff --git a/spec/controllers/admin/health_check_controller_spec.rb b/spec/controllers/admin/health_check_controller_spec.rb
index d15ee0021d9..e13401fc06b 100644
--- a/spec/controllers/admin/health_check_controller_spec.rb
+++ b/spec/controllers/admin/health_check_controller_spec.rb
@@ -8,18 +8,10 @@ describe Admin::HealthCheckController do
end
describe 'GET show' do
- it 'loads the git storage health information' do
+ it 'loads the health information' do
get :show
- expect(assigns[:failing_storage_statuses]).not_to be_nil
- end
- end
-
- describe 'POST reset_storage_health' do
- it 'resets all storage health information' do
- expect(Gitlab::Git::Storage::FailureInfo).to receive(:reset_all!)
-
- post :reset_storage_health
+ expect(assigns[:errors]).not_to be_nil
end
end
end
diff --git a/spec/controllers/admin/projects_controller_spec.rb b/spec/controllers/admin/projects_controller_spec.rb
index cc200b9fed9..ee1aff09bdf 100644
--- a/spec/controllers/admin/projects_controller_spec.rb
+++ b/spec/controllers/admin/projects_controller_spec.rb
@@ -42,4 +42,15 @@ describe Admin::ProjectsController do
expect { get :index }.not_to exceed_query_limit(control_count)
end
end
+
+ describe 'GET /projects/:id' do
+ render_views
+
+ it 'renders show page' do
+ get :show, namespace_id: project.namespace.path, id: project.path
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response.body).to match(project.name)
+ end
+ end
end
diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb
index f350641a643..3dd0b2623ac 100644
--- a/spec/controllers/admin/users_controller_spec.rb
+++ b/spec/controllers/admin/users_controller_spec.rb
@@ -264,5 +264,17 @@ describe Admin::UsersController do
expect(flash[:alert]).to eq("You are now impersonating #{user.username}")
end
end
+
+ context "when impersonation is disabled" do
+ before do
+ stub_config_setting(impersonation_enabled: false)
+ end
+
+ it "shows error page" do
+ post :impersonate, id: user.username
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
end
end
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index fbf116e533b..ac92b2ca657 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -107,59 +107,6 @@ describe ApplicationController do
end
end
- describe "#authenticate_user_from_personal_access_token!" do
- before do
- stub_authentication_activity_metrics(debug: false)
- end
-
- controller(described_class) do
- def index
- render text: 'authenticated'
- end
- end
-
- let(:personal_access_token) { create(:personal_access_token, user: user) }
-
- context "when the 'personal_access_token' param is populated with the personal access token" do
- it "logs the user in" do
- expect(authentication_metrics)
- .to increment(:user_authenticated_counter)
- .and increment(:user_session_override_counter)
- .and increment(:user_sessionless_authentication_counter)
-
- get :index, private_token: personal_access_token.token
-
- expect(response).to have_gitlab_http_status(200)
- expect(response.body).to eq('authenticated')
- end
- end
-
- context "when the 'PERSONAL_ACCESS_TOKEN' header is populated with the personal access token" do
- it "logs the user in" do
- expect(authentication_metrics)
- .to increment(:user_authenticated_counter)
- .and increment(:user_session_override_counter)
- .and increment(:user_sessionless_authentication_counter)
-
- @request.headers["PRIVATE-TOKEN"] = personal_access_token.token
- get :index
-
- expect(response).to have_gitlab_http_status(200)
- expect(response.body).to eq('authenticated')
- end
- end
-
- it "doesn't log the user in otherwise" do
- expect(authentication_metrics)
- .to increment(:user_unauthenticated_counter)
-
- get :index, private_token: "token"
-
- expect(response.status).not_to eq(200)
- expect(response.body).not_to eq('authenticated')
- end
- end
-
describe 'session expiration' do
controller(described_class) do
# The anonymous controller will report 401 and fail to run any actions.
@@ -167,7 +114,7 @@ describe ApplicationController do
skip_before_action :authenticate_user!, only: :index
def index
- render text: 'authenticated'
+ render html: 'authenticated'
end
end
@@ -190,30 +137,6 @@ describe ApplicationController do
end
end
- describe 'rescue from Gitlab::Git::Storage::Inaccessible' do
- controller(described_class) do
- def index
- raise Gitlab::Git::Storage::Inaccessible.new('broken', 100)
- end
- end
-
- it 'renders a 503 when storage is not available' do
- sign_in(create(:user))
-
- get :index
-
- expect(response.status).to eq(503)
- end
-
- it 'renders includes a Retry-After header' do
- sign_in(create(:user))
-
- get :index
-
- expect(response.headers['Retry-After']).to eq(100)
- end
- end
-
describe 'response format' do
controller(described_class) do
def index
@@ -248,74 +171,6 @@ describe ApplicationController do
end
end
- describe '#authenticate_sessionless_user!' do
- before do
- stub_authentication_activity_metrics(debug: false)
- end
-
- describe 'authenticating a user from a feed token' do
- controller(described_class) do
- def index
- render text: 'authenticated'
- end
- end
-
- context "when the 'feed_token' param is populated with the feed token" do
- context 'when the request format is atom' do
- it "logs the user in" do
- expect(authentication_metrics)
- .to increment(:user_authenticated_counter)
- .and increment(:user_session_override_counter)
- .and increment(:user_sessionless_authentication_counter)
-
- get :index, feed_token: user.feed_token, format: :atom
-
- expect(response).to have_gitlab_http_status 200
- expect(response.body).to eq 'authenticated'
- end
- end
-
- context 'when the request format is ics' do
- it "logs the user in" do
- expect(authentication_metrics)
- .to increment(:user_authenticated_counter)
- .and increment(:user_session_override_counter)
- .and increment(:user_sessionless_authentication_counter)
-
- get :index, feed_token: user.feed_token, format: :ics
-
- expect(response).to have_gitlab_http_status 200
- expect(response.body).to eq 'authenticated'
- end
- end
-
- context 'when the request format is neither atom nor ics' do
- it "doesn't log the user in" do
- expect(authentication_metrics)
- .to increment(:user_unauthenticated_counter)
-
- get :index, feed_token: user.feed_token
-
- expect(response.status).not_to have_gitlab_http_status 200
- expect(response.body).not_to eq 'authenticated'
- end
- end
- end
-
- context "when the 'feed_token' param is populated with an invalid feed token" do
- it "doesn't log the user" do
- expect(authentication_metrics)
- .to increment(:user_unauthenticated_counter)
-
- get :index, feed_token: 'token', format: :atom
-
- expect(response.status).not_to eq 200
- expect(response.body).not_to eq 'authenticated'
- end
- end
- end
- end
-
describe '#route_not_found' do
it 'renders 404 if authenticated' do
allow(controller).to receive(:current_user).and_return(user)
@@ -546,7 +401,7 @@ describe ApplicationController do
context 'terms' do
controller(described_class) do
def index
- render text: 'authenticated'
+ render html: 'authenticated'
end
end
@@ -581,36 +436,6 @@ describe ApplicationController do
expect(response).to have_gitlab_http_status(200)
end
-
- context 'for sessionless users' do
- render_views
-
- before do
- sign_out user
- end
-
- it 'renders a 403 when the sessionless user did not accept the terms' do
- get :index, feed_token: user.feed_token, format: :atom
-
- expect(response).to have_gitlab_http_status(403)
- end
-
- it 'renders the error message when the format was html' do
- get :index,
- private_token: create(:personal_access_token, user: user).token,
- format: :html
-
- expect(response.body).to have_content /accept the terms of service/i
- end
-
- it 'renders a 200 when the sessionless user accepted the terms' do
- accept_terms(user)
-
- get :index, feed_token: user.feed_token, format: :atom
-
- expect(response).to have_gitlab_http_status(200)
- end
- end
end
end
@@ -619,7 +444,7 @@ describe ApplicationController do
attr_reader :last_payload
def index
- render text: 'authenticated'
+ render html: 'authenticated'
end
def append_info_to_payload(payload)
@@ -674,7 +499,7 @@ describe ApplicationController do
describe '#access_denied' do
controller(described_class) do
def index
- access_denied!(params[:message])
+ access_denied!(params[:message], params[:status])
end
end
@@ -693,5 +518,159 @@ describe ApplicationController do
expect(response).to have_gitlab_http_status(403)
end
+
+ it 'renders a status passed to access denied' do
+ get :index, status: 401
+
+ expect(response).to have_gitlab_http_status(401)
+ end
+ end
+
+ context 'when invalid UTF-8 parameters are received' do
+ controller(described_class) do
+ def index
+ params[:text].split(' ')
+
+ render json: :ok
+ end
+ end
+
+ before do
+ sign_in user
+ end
+
+ context 'html' do
+ subject { get :index, text: "hi \255" }
+
+ it 'renders 412' do
+ if Gitlab.rails5?
+ expect { subject }.to raise_error(ActionController::BadRequest)
+ else
+ subject
+
+ expect(response).to have_gitlab_http_status(412)
+ expect(response).to render_template :precondition_failed
+ end
+ end
+ end
+
+ context 'js' do
+ subject { get :index, text: "hi \255", format: :js }
+
+ it 'renders 412' do
+ if Gitlab.rails5?
+ expect { subject }.to raise_error(ActionController::BadRequest)
+ else
+ subject
+
+ json_response = JSON.parse(response.body)
+
+ expect(response).to have_gitlab_http_status(412)
+ expect(json_response['error']).to eq('Invalid UTF-8')
+ end
+ end
+ end
+ end
+
+ context 'X-GitLab-Custom-Error header' do
+ before do
+ sign_in user
+ end
+
+ context 'given a 422 error page' do
+ controller do
+ def index
+ render 'errors/omniauth_error', layout: 'errors', status: 422
+ end
+ end
+
+ it 'sets a custom header' do
+ get :index
+
+ expect(response.headers['X-GitLab-Custom-Error']).to eq '1'
+ end
+ end
+
+ context 'given a 500 error page' do
+ controller do
+ def index
+ render 'errors/omniauth_error', layout: 'errors', status: 500
+ end
+ end
+
+ it 'sets a custom header' do
+ get :index
+
+ expect(response.headers['X-GitLab-Custom-Error']).to eq '1'
+ end
+ end
+
+ context 'given a 200 success page' do
+ controller do
+ def index
+ render 'errors/omniauth_error', layout: 'errors', status: 200
+ end
+ end
+
+ it 'does not set a custom header' do
+ get :index
+
+ expect(response.headers['X-GitLab-Custom-Error']).to be_nil
+ end
+ end
+
+ context 'given a json response' do
+ controller do
+ def index
+ render json: {}, status: :unprocessable_entity
+ end
+ end
+
+ it 'does not set a custom header' do
+ get :index, format: :json
+
+ expect(response.headers['X-GitLab-Custom-Error']).to be_nil
+ end
+ end
+
+ context 'given a json response for an html request' do
+ controller do
+ def index
+ render json: {}, status: :unprocessable_entity
+ end
+ end
+
+ it 'does not set a custom header' do
+ get :index
+
+ expect(response.headers['X-GitLab-Custom-Error']).to be_nil
+ end
+ end
+ end
+
+ context 'control headers' do
+ controller(described_class) do
+ def index
+ render json: :ok
+ end
+ end
+
+ context 'user not logged in' do
+ it 'sets the default headers' do
+ get :index
+
+ expect(response.headers['Cache-Control']).to be_nil
+ end
+ end
+
+ context 'user logged in' do
+ it 'sets the default headers' do
+ sign_in(user)
+
+ get :index
+
+ expect(response.headers['Cache-Control']).to eq 'max-age=0, private, must-revalidate, no-store'
+ end
+ end
end
end
diff --git a/spec/controllers/boards/issues_controller_spec.rb b/spec/controllers/boards/issues_controller_spec.rb
index d98e6ff0df8..98946e4287b 100644
--- a/spec/controllers/boards/issues_controller_spec.rb
+++ b/spec/controllers/boards/issues_controller_spec.rb
@@ -30,6 +30,15 @@ describe Boards::IssuesController do
context 'when list id is present' do
context 'with valid list id' do
+ let(:group) { create(:group, :private, projects: [project]) }
+ let(:group_board) { create(:board, group: group) }
+ let!(:list3) { create(:list, board: group_board, label: development, position: 2) }
+ let(:sub_group_1) { create(:group, :private, parent: group) }
+
+ before do
+ group.add_maintainer(user)
+ end
+
it 'returns issues that have the list label applied' do
issue = create(:labeled_issue, project: project, labels: [planning])
create(:labeled_issue, project: project, labels: [planning])
@@ -56,6 +65,39 @@ describe Boards::IssuesController do
expect { list_issues(user: user, board: board, list: list2) }.not_to exceed_query_limit(control_count)
end
+
+ it 'avoids N+1 database queries when adding a project', :request_store do
+ create(:labeled_issue, project: project, labels: [development])
+ control_count = ActiveRecord::QueryRecorder.new { list_issues(user: user, board: group_board, list: list3) }.count
+
+ 2.times do
+ p = create(:project, group: group)
+ create(:labeled_issue, project: p, labels: [development])
+ end
+
+ project_2 = create(:project, group: group)
+ create(:labeled_issue, project: project_2, labels: [development], assignees: [johndoe])
+
+ # because each issue without relative_position must be updated with
+ # a different value, we have 8 extra queries per issue
+ expect { list_issues(user: user, board: group_board, list: list3) }.not_to exceed_query_limit(control_count + (2 * 8 - 1))
+ end
+
+ it 'avoids N+1 database queries when adding a subgroup, project, and issue', :nested_groups do
+ create(:project, group: sub_group_1)
+ create(:labeled_issue, project: project, labels: [development])
+ control_count = ActiveRecord::QueryRecorder.new { list_issues(user: user, board: group_board, list: list3) }.count
+ project_2 = create(:project, group: group)
+
+ 2.times do
+ p = create(:project, group: sub_group_1)
+ create(:labeled_issue, project: p, labels: [development])
+ end
+
+ create(:labeled_issue, project: project_2, labels: [development], assignees: [johndoe])
+
+ expect { list_issues(user: user, board: group_board, list: list3) }.not_to exceed_query_limit(control_count + (2 * 8 - 1))
+ end
end
context 'with invalid list id' do
@@ -102,12 +144,15 @@ describe Boards::IssuesController do
sign_in(user)
params = {
- namespace_id: project.namespace.to_param,
- project_id: project,
board_id: board.to_param,
list_id: list.try(:to_param)
}
+ unless board.try(:parent)&.is_a?(Group)
+ params[:namespace_id] = project.namespace.to_param
+ params[:project_id] = project
+ end
+
get :index, params.compact
end
end
@@ -163,11 +208,22 @@ describe Boards::IssuesController do
end
end
- context 'with unauthorized user' do
- it 'returns a forbidden 403 response' do
- create_issue user: guest, board: board, list: list1, title: 'New issue'
+ context 'with guest user' do
+ context 'in open list' do
+ it 'returns a successful 200 response' do
+ open_list = board.lists.create(list_type: :backlog)
+ create_issue user: guest, board: board, list: open_list, title: 'New issue'
- expect(response).to have_gitlab_http_status(403)
+ expect(response).to have_gitlab_http_status(200)
+ end
+ end
+
+ context 'in label list' do
+ it 'returns a forbidden 403 response' do
+ create_issue user: guest, board: board, list: list1, title: 'New issue'
+
+ expect(response).to have_gitlab_http_status(403)
+ end
end
end
diff --git a/spec/controllers/concerns/controller_with_cross_project_access_check_spec.rb b/spec/controllers/concerns/controller_with_cross_project_access_check_spec.rb
index d20471ef603..3c9452cc42a 100644
--- a/spec/controllers/concerns/controller_with_cross_project_access_check_spec.rb
+++ b/spec/controllers/concerns/controller_with_cross_project_access_check_spec.rb
@@ -27,11 +27,11 @@ describe ControllerWithCrossProjectAccessCheck do
if: -> { if_condition }
def index
- render nothing: true
+ head :ok
end
def show
- render nothing: true
+ head :ok
end
def unless_condition
@@ -88,15 +88,15 @@ describe ControllerWithCrossProjectAccessCheck do
if: -> { if_condition }
def index
- render nothing: true
+ head :ok
end
def show
- render nothing: true
+ head :ok
end
def edit
- render nothing: true
+ head :ok
end
def unless_condition
diff --git a/spec/controllers/concerns/issuable_collections_spec.rb b/spec/controllers/concerns/issuable_collections_spec.rb
index d16a3464495..e93c923fd39 100644
--- a/spec/controllers/concerns/issuable_collections_spec.rb
+++ b/spec/controllers/concerns/issuable_collections_spec.rb
@@ -60,7 +60,7 @@ describe IssuableCollections do
end
end
- describe '#filter_params' do
+ describe '#finder_options' do
let(:params) do
{
assignee_id: '1',
@@ -84,25 +84,20 @@ describe IssuableCollections do
}
end
- it 'filters params' do
+ it 'only allows whitelisted params' do
allow(controller).to receive(:cookies).and_return({})
- filtered_params = controller.send(:filter_params)
+ finder_options = controller.send(:finder_options)
- expect(filtered_params).to eq({
+ expect(finder_options).to eq({
'assignee_id' => '1',
'assignee_username' => 'user1',
'author_id' => '2',
'author_username' => 'user2',
- 'authorized_only' => 'true',
- 'due_date' => '2017-01-01',
- 'group_id' => '3',
- 'iids' => '4',
'label_name' => 'foo',
'milestone_title' => 'bar',
'my_reaction_emoji' => 'thumbsup',
- 'non_archived' => 'true',
- 'project_id' => '5',
+ 'due_date' => '2017-01-01',
'scope' => 'all',
'search' => 'baz',
'sort' => 'priority',
diff --git a/spec/controllers/concerns/lfs_request_spec.rb b/spec/controllers/concerns/lfs_request_spec.rb
index 33b23db302a..76c878ec5d7 100644
--- a/spec/controllers/concerns/lfs_request_spec.rb
+++ b/spec/controllers/concerns/lfs_request_spec.rb
@@ -10,7 +10,7 @@ describe LfsRequest do
def show
storage_project
- render nothing: true
+ head :ok
end
def project
diff --git a/spec/controllers/concerns/send_file_upload_spec.rb b/spec/controllers/concerns/send_file_upload_spec.rb
index 767fba7fd58..379b2d6b935 100644
--- a/spec/controllers/concerns/send_file_upload_spec.rb
+++ b/spec/controllers/concerns/send_file_upload_spec.rb
@@ -28,8 +28,9 @@ describe SendFileUpload do
describe '#send_upload' do
let(:controller) { controller_class.new }
let(:temp_file) { Tempfile.new('test') }
+ let(:params) { {} }
- subject { controller.send_upload(uploader) }
+ subject { controller.send_upload(uploader, **params) }
before do
FileUtils.touch(temp_file)
@@ -52,7 +53,7 @@ describe SendFileUpload do
end
context 'with attachment' do
- let(:send_attachment) { controller.send_upload(uploader, attachment: 'test.js') }
+ let(:params) { { attachment: 'test.js' } }
it 'sends a file with content-type of text/plain' do
expected_params = {
@@ -62,7 +63,7 @@ describe SendFileUpload do
}
expect(controller).to receive(:send_file).with(uploader.path, expected_params)
- send_attachment
+ subject
end
context 'with a proxied file in object storage' do
@@ -75,7 +76,7 @@ describe SendFileUpload do
it 'sends a file with a custom type' do
headers = double
- expected_headers = %r(response-content-disposition=attachment%3Bfilename%3D%22test.js%22&response-content-type=application/javascript)
+ expected_headers = %r(response-content-disposition=attachment%3Bfilename%3D%22test.js%22&response-content-type=application/ecmascript)
expect(Gitlab::Workhorse).to receive(:send_url).with(expected_headers).and_call_original
expect(headers).to receive(:store).with(Gitlab::Workhorse::SEND_DATA_HEADER, /^send-url:/)
@@ -83,7 +84,7 @@ describe SendFileUpload do
expect(controller).to receive(:headers) { headers }
expect(controller).to receive(:head).with(:ok)
- send_attachment
+ subject
end
end
end
@@ -95,11 +96,7 @@ describe SendFileUpload do
uploader.store!(temp_file)
end
- context 'and proxying is enabled' do
- before do
- allow(Gitlab.config.uploads.object_store).to receive(:proxy_download) { true }
- end
-
+ shared_examples 'proxied file' do
it 'sends a file' do
headers = double
expect(Gitlab::Workhorse).not_to receive(:send_url).with(/response-content-disposition/)
@@ -115,6 +112,14 @@ describe SendFileUpload do
end
end
+ context 'and proxying is enabled' do
+ before do
+ allow(Gitlab.config.uploads.object_store).to receive(:proxy_download) { true }
+ end
+
+ it_behaves_like 'proxied file'
+ end
+
context 'and proxying is disabled' do
before do
allow(Gitlab.config.uploads.object_store).to receive(:proxy_download) { false }
@@ -125,6 +130,12 @@ describe SendFileUpload do
subject
end
+
+ context 'with proxy requested' do
+ let(:params) { { proxy: true } }
+
+ it_behaves_like 'proxied file'
+ end
end
end
end
diff --git a/spec/controllers/dashboard/milestones_controller_spec.rb b/spec/controllers/dashboard/milestones_controller_spec.rb
index 56047c0c8d2..278b980b6d8 100644
--- a/spec/controllers/dashboard/milestones_controller_spec.rb
+++ b/spec/controllers/dashboard/milestones_controller_spec.rb
@@ -45,6 +45,8 @@ describe Dashboard::MilestonesController do
end
describe "#index" do
+ render_views
+
it 'returns group and project milestones to which the user belongs' do
get :index, format: :json
@@ -53,5 +55,12 @@ describe Dashboard::MilestonesController do
expect(json_response.map { |i| i["first_milestone"]["id"] }).to match_array([group_milestone.id, project_milestone.id])
expect(json_response.map { |i| i["group_name"] }.compact).to match_array(group.name)
end
+
+ it 'should contain group and project milestones to which the user belongs to' do
+ get :index
+
+ expect(response.body).to include("Open\n<span class=\"badge badge-pill\">3</span>")
+ expect(response.body).to include("Closed\n<span class=\"badge badge-pill\">0</span>")
+ end
end
end
diff --git a/spec/controllers/dashboard/projects_controller_spec.rb b/spec/controllers/dashboard/projects_controller_spec.rb
new file mode 100644
index 00000000000..2975205e09c
--- /dev/null
+++ b/spec/controllers/dashboard/projects_controller_spec.rb
@@ -0,0 +1,5 @@
+require 'spec_helper'
+
+describe Dashboard::ProjectsController do
+ it_behaves_like 'authenticates sessionless user', :index, :atom
+end
diff --git a/spec/controllers/dashboard/todos_controller_spec.rb b/spec/controllers/dashboard/todos_controller_spec.rb
index b4a731fd3a3..e2c799f5205 100644
--- a/spec/controllers/dashboard/todos_controller_spec.rb
+++ b/spec/controllers/dashboard/todos_controller_spec.rb
@@ -42,6 +42,16 @@ describe Dashboard::TodosController do
end
end
+ context 'group authorization' do
+ it 'renders 404 when user does not have read access on given group' do
+ unauthorized_group = create(:group, :private)
+
+ get :index, group_id: unauthorized_group.id
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
context 'when using pagination' do
let(:last_page) { user.todos.page.total_pages }
let!(:issues) { create_list(:issue, 3, project: project, assignees: [user]) }
diff --git a/spec/controllers/dashboard_controller_spec.rb b/spec/controllers/dashboard_controller_spec.rb
index 187542ba30c..c857a78d5e8 100644
--- a/spec/controllers/dashboard_controller_spec.rb
+++ b/spec/controllers/dashboard_controller_spec.rb
@@ -1,21 +1,26 @@
require 'spec_helper'
describe DashboardController do
- let(:user) { create(:user) }
- let(:project) { create(:project) }
+ context 'signed in' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+ end
- describe 'GET issues' do
- it_behaves_like 'issuables list meta-data', :issue, :issues
- it_behaves_like 'issuables requiring filter', :issues
- end
+ describe 'GET issues' do
+ it_behaves_like 'issuables list meta-data', :issue, :issues
+ it_behaves_like 'issuables requiring filter', :issues
+ end
- describe 'GET merge requests' do
- it_behaves_like 'issuables list meta-data', :merge_request, :merge_requests
- it_behaves_like 'issuables requiring filter', :merge_requests
+ describe 'GET merge requests' do
+ it_behaves_like 'issuables list meta-data', :merge_request, :merge_requests
+ it_behaves_like 'issuables requiring filter', :merge_requests
+ end
end
+
+ it_behaves_like 'authenticates sessionless user', :issues, :atom, author_id: User.first
+ it_behaves_like 'authenticates sessionless user', :issues_calendar, :ics
end
diff --git a/spec/controllers/graphql_controller_spec.rb b/spec/controllers/graphql_controller_spec.rb
index 1449036e148..949ad532365 100644
--- a/spec/controllers/graphql_controller_spec.rb
+++ b/spec/controllers/graphql_controller_spec.rb
@@ -52,15 +52,58 @@ describe GraphqlController do
end
end
+ context 'token authentication' do
+ before do
+ stub_authentication_activity_metrics(debug: false)
+ end
+
+ let(:user) { create(:user, username: 'Simon') }
+ let(:personal_access_token) { create(:personal_access_token, user: user) }
+
+ context "when the 'personal_access_token' param is populated with the personal access token" do
+ it 'logs the user in' do
+ expect(authentication_metrics)
+ .to increment(:user_authenticated_counter)
+ .and increment(:user_session_override_counter)
+ .and increment(:user_sessionless_authentication_counter)
+
+ run_test_query!(private_token: personal_access_token.token)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(query_response).to eq('echo' => '"Simon" says: test success')
+ end
+ end
+
+ context 'when the personal access token has no api scope' do
+ it 'does not log the user in' do
+ personal_access_token.update(scopes: [:read_user])
+
+ run_test_query!(private_token: personal_access_token.token)
+
+ expect(response).to have_gitlab_http_status(200)
+
+ expect(query_response).to eq('echo' => 'nil says: test success')
+ end
+ end
+
+ context 'without token' do
+ it 'shows public data' do
+ run_test_query!
+
+ expect(query_response).to eq('echo' => 'nil says: test success')
+ end
+ end
+ end
+
# Chosen to exercise all the moving parts in GraphqlController#execute
- def run_test_query!(variables: { 'text' => 'test success' })
+ def run_test_query!(variables: { 'text' => 'test success' }, private_token: nil)
query = <<~QUERY
query Echo($text: String) {
echo(text: $text)
}
QUERY
- post :execute, query: query, operationName: 'Echo', variables: variables
+ post :execute, query: query, operationName: 'Echo', variables: variables, private_token: private_token
end
def query_response
diff --git a/spec/controllers/groups/boards_controller_spec.rb b/spec/controllers/groups/boards_controller_spec.rb
index bf41aa0706f..99429c93b82 100644
--- a/spec/controllers/groups/boards_controller_spec.rb
+++ b/spec/controllers/groups/boards_controller_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Groups::BoardsController do
let(:group) { create(:group) }
- let(:user) { create(:user) }
+ let(:user) { create(:user) }
before do
group.add_maintainer(user)
@@ -22,6 +22,28 @@ describe Groups::BoardsController do
expect(response.content_type).to eq 'text/html'
end
+ it 'redirects to latest visited board' do
+ board = create(:board, group: group)
+ create(:board_group_recent_visit, group: board.group, board: board, user: user)
+
+ list_boards
+
+ expect(response).to redirect_to(group_board_path(id: board.id))
+ end
+
+ it 'renders template if visited board is not found' do
+ temporary_board = create(:board, group: group)
+ visited = create(:board_group_recent_visit, group: temporary_board.group, board: temporary_board, user: user)
+ temporary_board.delete
+
+ allow_any_instance_of(Boards::Visits::LatestService).to receive(:execute).and_return(visited)
+
+ list_boards
+
+ expect(response).to render_template :index
+ expect(response.content_type).to eq 'text/html'
+ end
+
context 'with unauthorized user' do
before do
allow(Ability).to receive(:allowed?).with(user, :read_cross_project, :global).and_return(true)
@@ -35,12 +57,30 @@ describe Groups::BoardsController do
expect(response.content_type).to eq 'text/html'
end
end
+
+ context 'when user is signed out' do
+ let(:group) { create(:group, :public) }
+
+ it 'renders template' do
+ sign_out(user)
+
+ board = create(:board, group: group)
+ create(:board_group_recent_visit, group: board.group, board: board, user: user)
+
+ list_boards
+
+ expect(response).to render_template :index
+ expect(response.content_type).to eq 'text/html'
+ end
+ end
end
context 'when format is JSON' do
it 'return an array with one group board' do
create(:board, group: group)
+ expect(Boards::Visits::LatestService).not_to receive(:new)
+
list_boards format: :json
parsed_response = JSON.parse(response.body)
@@ -74,7 +114,7 @@ describe Groups::BoardsController do
context 'when format is HTML' do
it 'renders template' do
- read_board board: board
+ expect { read_board board: board }.to change(BoardGroupRecentVisit, :count).by(1)
expect(response).to render_template :show
expect(response.content_type).to eq 'text/html'
@@ -93,10 +133,25 @@ describe Groups::BoardsController do
expect(response.content_type).to eq 'text/html'
end
end
+
+ context 'when user is signed out' do
+ let(:group) { create(:group, :public) }
+
+ it 'does not save visit' do
+ sign_out(user)
+
+ expect { read_board board: board }.to change(BoardGroupRecentVisit, :count).by(0)
+
+ expect(response).to render_template :show
+ expect(response.content_type).to eq 'text/html'
+ end
+ end
end
context 'when format is JSON' do
it 'returns project board' do
+ expect(Boards::Visits::CreateService).not_to receive(:new)
+
read_board board: board, format: :json
expect(response).to match_response_schema('board')
diff --git a/spec/controllers/groups/clusters/applications_controller_spec.rb b/spec/controllers/groups/clusters/applications_controller_spec.rb
new file mode 100644
index 00000000000..68a798542b6
--- /dev/null
+++ b/spec/controllers/groups/clusters/applications_controller_spec.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Groups::Clusters::ApplicationsController do
+ include AccessMatchersForController
+
+ def current_application
+ Clusters::Cluster::APPLICATIONS[application]
+ end
+
+ describe 'POST create' do
+ let(:cluster) { create(:cluster, :group, :provided_by_gcp) }
+ let(:group) { cluster.group }
+ let(:application) { 'helm' }
+ let(:params) { { application: application, id: cluster.id } }
+
+ describe 'functionality' do
+ let(:user) { create(:user) }
+
+ before do
+ group.add_maintainer(user)
+ sign_in(user)
+ end
+
+ it 'schedule an application installation' do
+ expect(ClusterInstallAppWorker).to receive(:perform_async).with(application, anything).once
+
+ expect { go }.to change { current_application.count }
+ expect(response).to have_http_status(:no_content)
+ expect(cluster.application_helm).to be_scheduled
+ end
+
+ context 'when cluster do not exists' do
+ before do
+ cluster.destroy!
+ end
+
+ it 'return 404' do
+ expect { go }.not_to change { current_application.count }
+ expect(response).to have_http_status(:not_found)
+ end
+ end
+
+ context 'when application is unknown' do
+ let(:application) { 'unkwnown-app' }
+
+ it 'return 404' do
+ go
+
+ expect(response).to have_http_status(:not_found)
+ end
+ end
+
+ context 'when application is already installing' do
+ before do
+ create(:clusters_applications_helm, :installing, cluster: cluster)
+ end
+
+ it 'returns 400' do
+ go
+
+ expect(response).to have_http_status(:bad_request)
+ end
+ end
+ end
+
+ describe 'security' do
+ before do
+ allow(ClusterInstallAppWorker).to receive(:perform_async)
+ end
+
+ it { expect { go }.to be_allowed_for(:admin) }
+ it { expect { go }.to be_allowed_for(:owner).of(group) }
+ it { expect { go }.to be_allowed_for(:maintainer).of(group) }
+ it { expect { go }.to be_denied_for(:developer).of(group) }
+ it { expect { go }.to be_denied_for(:reporter).of(group) }
+ it { expect { go }.to be_denied_for(:guest).of(group) }
+ it { expect { go }.to be_denied_for(:user) }
+ it { expect { go }.to be_denied_for(:external) }
+ end
+
+ def go
+ post :create, params.merge(group_id: group)
+ end
+ end
+end
diff --git a/spec/controllers/groups/clusters_controller_spec.rb b/spec/controllers/groups/clusters_controller_spec.rb
new file mode 100644
index 00000000000..6e130f830a2
--- /dev/null
+++ b/spec/controllers/groups/clusters_controller_spec.rb
@@ -0,0 +1,574 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Groups::ClustersController do
+ include AccessMatchersForController
+ include GoogleApi::CloudPlatformHelpers
+
+ set(:group) { create(:group) }
+
+ let(:user) { create(:user) }
+
+ before do
+ group.add_maintainer(user)
+ sign_in(user)
+ end
+
+ describe 'GET index' do
+ def go(params = {})
+ get :index, params.reverse_merge(group_id: group)
+ end
+
+ context 'when feature flag is not enabled' do
+ before do
+ stub_feature_flags(group_clusters: false)
+ end
+
+ it 'renders 404' do
+ go
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'when feature flag is enabled' do
+ before do
+ stub_feature_flags(group_clusters: true)
+ end
+
+ describe 'functionality' do
+ context 'when group has one or more clusters' do
+ let(:group) { create(:group) }
+
+ let!(:enabled_cluster) do
+ create(:cluster, :provided_by_gcp, cluster_type: :group_type, groups: [group])
+ end
+
+ let!(:disabled_cluster) do
+ create(:cluster, :disabled, :provided_by_gcp, :production_environment, cluster_type: :group_type, groups: [group])
+ end
+
+ it 'lists available clusters' do
+ go
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:index)
+ expect(assigns(:clusters)).to match_array([enabled_cluster, disabled_cluster])
+ end
+
+ context 'when page is specified' do
+ let(:last_page) { group.clusters.page.total_pages }
+
+ before do
+ allow(Clusters::Cluster).to receive(:paginates_per).and_return(1)
+ create_list(:cluster, 2, :provided_by_gcp, :production_environment, cluster_type: :group_type, groups: [group])
+ end
+
+ it 'redirects to the page' do
+ go(page: last_page)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(assigns(:clusters).current_page).to eq(last_page)
+ end
+ end
+ end
+
+ context 'when group does not have a cluster' do
+ let(:group) { create(:group) }
+
+ it 'returns an empty state page' do
+ go
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:index, partial: :empty_state)
+ expect(assigns(:clusters)).to eq([])
+ end
+ end
+ end
+ end
+
+ describe 'security' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, cluster_type: :group_type, groups: [group]) }
+
+ it { expect { go }.to be_allowed_for(:admin) }
+ it { expect { go }.to be_allowed_for(:owner).of(group) }
+ it { expect { go }.to be_allowed_for(:maintainer).of(group) }
+ it { expect { go }.to be_denied_for(:developer).of(group) }
+ it { expect { go }.to be_denied_for(:reporter).of(group) }
+ it { expect { go }.to be_denied_for(:guest).of(group) }
+ it { expect { go }.to be_denied_for(:user) }
+ it { expect { go }.to be_denied_for(:external) }
+ end
+ end
+
+ describe 'GET new' do
+ def go
+ get :new, group_id: group
+ end
+
+ describe 'functionality for new cluster' do
+ context 'when omniauth has been configured' do
+ let(:key) { 'secret-key' }
+ let(:session_key_for_redirect_uri) do
+ GoogleApi::CloudPlatform::Client.session_key_for_redirect_uri(key)
+ end
+
+ before do
+ allow(SecureRandom).to receive(:hex).and_return(key)
+ end
+
+ it 'has authorize_url' do
+ go
+
+ expect(assigns(:authorize_url)).to include(key)
+ expect(session[session_key_for_redirect_uri]).to eq(new_group_cluster_path(group))
+ end
+ end
+
+ context 'when omniauth has not configured' do
+ before do
+ stub_omniauth_setting(providers: [])
+ end
+
+ it 'does not have authorize_url' do
+ go
+
+ expect(assigns(:authorize_url)).to be_nil
+ end
+ end
+
+ context 'when access token is valid' do
+ before do
+ stub_google_api_validate_token
+ end
+
+ it 'has new object' do
+ go
+
+ expect(assigns(:gcp_cluster)).to be_an_instance_of(Clusters::ClusterPresenter)
+ end
+ end
+
+ context 'when access token is expired' do
+ before do
+ stub_google_api_expired_token
+ end
+
+ it { expect(@valid_gcp_token).to be_falsey }
+ end
+
+ context 'when access token is not stored in session' do
+ it { expect(@valid_gcp_token).to be_falsey }
+ end
+ end
+
+ describe 'functionality for existing cluster' do
+ it 'has new object' do
+ go
+
+ expect(assigns(:user_cluster)).to be_an_instance_of(Clusters::ClusterPresenter)
+ end
+ end
+
+ describe 'security' do
+ it { expect { go }.to be_allowed_for(:admin) }
+ it { expect { go }.to be_allowed_for(:owner).of(group) }
+ it { expect { go }.to be_allowed_for(:maintainer).of(group) }
+ it { expect { go }.to be_denied_for(:developer).of(group) }
+ it { expect { go }.to be_denied_for(:reporter).of(group) }
+ it { expect { go }.to be_denied_for(:guest).of(group) }
+ it { expect { go }.to be_denied_for(:user) }
+ it { expect { go }.to be_denied_for(:external) }
+ end
+ end
+
+ describe 'POST create for new cluster' do
+ let(:legacy_abac_param) { 'true' }
+ let(:params) do
+ {
+ cluster: {
+ name: 'new-cluster',
+ provider_gcp_attributes: {
+ gcp_project_id: 'gcp-project-12345',
+ legacy_abac: legacy_abac_param
+ }
+ }
+ }
+ end
+
+ def go
+ post :create_gcp, params.merge(group_id: group)
+ end
+
+ describe 'functionality' do
+ context 'when access token is valid' do
+ before do
+ stub_google_api_validate_token
+ end
+
+ it 'creates a new cluster' do
+ expect(ClusterProvisionWorker).to receive(:perform_async)
+ expect { go }.to change { Clusters::Cluster.count }
+ .and change { Clusters::Providers::Gcp.count }
+
+ cluster = group.clusters.first
+
+ expect(response).to redirect_to(group_cluster_path(group, cluster))
+ expect(cluster).to be_gcp
+ expect(cluster).to be_kubernetes
+ expect(cluster.provider_gcp).to be_legacy_abac
+ end
+
+ context 'when legacy_abac param is false' do
+ let(:legacy_abac_param) { 'false' }
+
+ it 'creates a new cluster with legacy_abac_disabled' do
+ expect(ClusterProvisionWorker).to receive(:perform_async)
+ expect { go }.to change { Clusters::Cluster.count }
+ .and change { Clusters::Providers::Gcp.count }
+ expect(group.clusters.first.provider_gcp).not_to be_legacy_abac
+ end
+ end
+ end
+
+ context 'when access token is expired' do
+ before do
+ stub_google_api_expired_token
+ end
+
+ it { expect(@valid_gcp_token).to be_falsey }
+ end
+
+ context 'when access token is not stored in session' do
+ it { expect(@valid_gcp_token).to be_falsey }
+ end
+ end
+
+ describe 'security' do
+ before do
+ allow_any_instance_of(described_class)
+ .to receive(:token_in_session).and_return('token')
+ allow_any_instance_of(described_class)
+ .to receive(:expires_at_in_session).and_return(1.hour.since.to_i.to_s)
+ allow_any_instance_of(GoogleApi::CloudPlatform::Client)
+ .to receive(:projects_zones_clusters_create) do
+ OpenStruct.new(
+ self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123',
+ status: 'RUNNING'
+ )
+ end
+
+ allow(WaitForClusterCreationWorker).to receive(:perform_in).and_return(nil)
+ end
+
+ it { expect { go }.to be_allowed_for(:admin) }
+ it { expect { go }.to be_allowed_for(:owner).of(group) }
+ it { expect { go }.to be_allowed_for(:maintainer).of(group) }
+ it { expect { go }.to be_denied_for(:developer).of(group) }
+ it { expect { go }.to be_denied_for(:reporter).of(group) }
+ it { expect { go }.to be_denied_for(:guest).of(group) }
+ it { expect { go }.to be_denied_for(:user) }
+ it { expect { go }.to be_denied_for(:external) }
+ end
+ end
+
+ describe 'POST create for existing cluster' do
+ let(:params) do
+ {
+ cluster: {
+ name: 'new-cluster',
+ platform_kubernetes_attributes: {
+ api_url: 'http://my-url',
+ token: 'test'
+ }
+ }
+ }
+ end
+
+ def go
+ post :create_user, params.merge(group_id: group)
+ end
+
+ describe 'functionality' do
+ context 'when creates a cluster' do
+ it 'creates a new cluster' do
+ expect(ClusterProvisionWorker).to receive(:perform_async)
+
+ expect { go }.to change { Clusters::Cluster.count }
+ .and change { Clusters::Platforms::Kubernetes.count }
+
+ cluster = group.clusters.first
+
+ expect(response).to redirect_to(group_cluster_path(group, cluster))
+ expect(cluster).to be_user
+ expect(cluster).to be_kubernetes
+ end
+ end
+
+ context 'when creates a RBAC-enabled cluster' do
+ let(:params) do
+ {
+ cluster: {
+ name: 'new-cluster',
+ platform_kubernetes_attributes: {
+ api_url: 'http://my-url',
+ token: 'test',
+ authorization_type: 'rbac'
+ }
+ }
+ }
+ end
+
+ it 'creates a new cluster' do
+ expect(ClusterProvisionWorker).to receive(:perform_async)
+
+ expect { go }.to change { Clusters::Cluster.count }
+ .and change { Clusters::Platforms::Kubernetes.count }
+
+ cluster = group.clusters.first
+
+ expect(response).to redirect_to(group_cluster_path(group, cluster))
+ expect(cluster).to be_user
+ expect(cluster).to be_kubernetes
+ expect(cluster).to be_platform_kubernetes_rbac
+ end
+ end
+ end
+
+ describe 'security' do
+ it { expect { go }.to be_allowed_for(:admin) }
+ it { expect { go }.to be_allowed_for(:owner).of(group) }
+ it { expect { go }.to be_allowed_for(:maintainer).of(group) }
+ it { expect { go }.to be_denied_for(:developer).of(group) }
+ it { expect { go }.to be_denied_for(:reporter).of(group) }
+ it { expect { go }.to be_denied_for(:guest).of(group) }
+ it { expect { go }.to be_denied_for(:user) }
+ it { expect { go }.to be_denied_for(:external) }
+ end
+ end
+
+ describe 'GET cluster_status' do
+ let(:cluster) { create(:cluster, :providing_by_gcp, cluster_type: :group_type, groups: [group]) }
+
+ def go
+ get :cluster_status,
+ group_id: group.to_param,
+ id: cluster,
+ format: :json
+ end
+
+ describe 'functionality' do
+ it 'responds with matching schema' do
+ go
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('cluster_status')
+ end
+
+ it 'invokes schedule_status_update on each application' do
+ expect_any_instance_of(Clusters::Applications::Ingress).to receive(:schedule_status_update)
+
+ go
+ end
+ end
+
+ describe 'security' do
+ it { expect { go }.to be_allowed_for(:admin) }
+ it { expect { go }.to be_allowed_for(:owner).of(group) }
+ it { expect { go }.to be_allowed_for(:maintainer).of(group) }
+ it { expect { go }.to be_denied_for(:developer).of(group) }
+ it { expect { go }.to be_denied_for(:reporter).of(group) }
+ it { expect { go }.to be_denied_for(:guest).of(group) }
+ it { expect { go }.to be_denied_for(:user) }
+ it { expect { go }.to be_denied_for(:external) }
+ end
+ end
+
+ describe 'GET show' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, cluster_type: :group_type, groups: [group]) }
+
+ def go
+ get :show,
+ group_id: group,
+ id: cluster
+ end
+
+ describe 'functionality' do
+ it 'renders view' do
+ go
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(assigns(:cluster)).to eq(cluster)
+ end
+ end
+
+ describe 'security' do
+ it { expect { go }.to be_allowed_for(:admin) }
+ it { expect { go }.to be_allowed_for(:owner).of(group) }
+ it { expect { go }.to be_allowed_for(:maintainer).of(group) }
+ it { expect { go }.to be_denied_for(:developer).of(group) }
+ it { expect { go }.to be_denied_for(:reporter).of(group) }
+ it { expect { go }.to be_denied_for(:guest).of(group) }
+ it { expect { go }.to be_denied_for(:user) }
+ it { expect { go }.to be_denied_for(:external) }
+ end
+ end
+
+ describe 'PUT update' do
+ def go(format: :html)
+ put :update, params.merge(
+ group_id: group.to_param,
+ id: cluster,
+ format: format
+ )
+ end
+
+ let(:cluster) { create(:cluster, :provided_by_user, cluster_type: :group_type, groups: [group]) }
+
+ let(:params) do
+ {
+ cluster: {
+ enabled: false,
+ name: 'my-new-cluster-name'
+ }
+ }
+ end
+
+ it 'updates and redirects back to show page' do
+ go
+
+ cluster.reload
+ expect(response).to redirect_to(group_cluster_path(group, cluster))
+ expect(flash[:notice]).to eq('Kubernetes cluster was successfully updated.')
+ expect(cluster.enabled).to be_falsey
+ expect(cluster.name).to eq('my-new-cluster-name')
+ end
+
+ context 'when format is json' do
+ context 'when changing parameters' do
+ context 'when valid parameters are used' do
+ let(:params) do
+ {
+ cluster: {
+ enabled: false,
+ name: 'my-new-cluster-name'
+ }
+ }
+ end
+
+ it 'updates and redirects back to show page' do
+ go(format: :json)
+
+ cluster.reload
+ expect(response).to have_http_status(:no_content)
+ expect(cluster.enabled).to be_falsey
+ expect(cluster.name).to eq('my-new-cluster-name')
+ end
+ end
+
+ context 'when invalid parameters are used' do
+ let(:params) do
+ {
+ cluster: {
+ enabled: false,
+ name: ''
+ }
+ }
+ end
+
+ it 'rejects changes' do
+ go(format: :json)
+
+ expect(response).to have_http_status(:bad_request)
+ end
+ end
+ end
+ end
+
+ describe 'security' do
+ set(:cluster) { create(:cluster, :provided_by_gcp, cluster_type: :group_type, groups: [group]) }
+
+ it { expect { go }.to be_allowed_for(:admin) }
+ it { expect { go }.to be_allowed_for(:owner).of(group) }
+ it { expect { go }.to be_allowed_for(:maintainer).of(group) }
+ it { expect { go }.to be_denied_for(:developer).of(group) }
+ it { expect { go }.to be_denied_for(:reporter).of(group) }
+ it { expect { go }.to be_denied_for(:guest).of(group) }
+ it { expect { go }.to be_denied_for(:user) }
+ it { expect { go }.to be_denied_for(:external) }
+ end
+ end
+
+ describe 'DELETE destroy' do
+ let!(:cluster) { create(:cluster, :provided_by_gcp, :production_environment, cluster_type: :group_type, groups: [group]) }
+
+ def go
+ delete :destroy,
+ group_id: group,
+ id: cluster
+ end
+
+ describe 'functionality' do
+ context 'when cluster is provided by GCP' do
+ context 'when cluster is created' do
+ it 'destroys and redirects back to clusters list' do
+ expect { go }
+ .to change { Clusters::Cluster.count }.by(-1)
+ .and change { Clusters::Platforms::Kubernetes.count }.by(-1)
+ .and change { Clusters::Providers::Gcp.count }.by(-1)
+
+ expect(response).to redirect_to(group_clusters_path(group))
+ expect(flash[:notice]).to eq('Kubernetes cluster integration was successfully removed.')
+ end
+ end
+
+ context 'when cluster is being created' do
+ let!(:cluster) { create(:cluster, :providing_by_gcp, :production_environment, cluster_type: :group_type, groups: [group]) }
+
+ it 'destroys and redirects back to clusters list' do
+ expect { go }
+ .to change { Clusters::Cluster.count }.by(-1)
+ .and change { Clusters::Providers::Gcp.count }.by(-1)
+
+ expect(response).to redirect_to(group_clusters_path(group))
+ expect(flash[:notice]).to eq('Kubernetes cluster integration was successfully removed.')
+ end
+ end
+ end
+
+ context 'when cluster is provided by user' do
+ let!(:cluster) { create(:cluster, :provided_by_user, :production_environment, cluster_type: :group_type, groups: [group]) }
+
+ it 'destroys and redirects back to clusters list' do
+ expect { go }
+ .to change { Clusters::Cluster.count }.by(-1)
+ .and change { Clusters::Platforms::Kubernetes.count }.by(-1)
+ .and change { Clusters::Providers::Gcp.count }.by(0)
+
+ expect(response).to redirect_to(group_clusters_path(group))
+ expect(flash[:notice]).to eq('Kubernetes cluster integration was successfully removed.')
+ end
+ end
+ end
+
+ describe 'security' do
+ set(:cluster) { create(:cluster, :provided_by_gcp, :production_environment, cluster_type: :group_type, groups: [group]) }
+
+ it { expect { go }.to be_allowed_for(:admin) }
+ it { expect { go }.to be_allowed_for(:owner).of(group) }
+ it { expect { go }.to be_allowed_for(:maintainer).of(group) }
+ it { expect { go }.to be_denied_for(:developer).of(group) }
+ it { expect { go }.to be_denied_for(:reporter).of(group) }
+ it { expect { go }.to be_denied_for(:guest).of(group) }
+ it { expect { go }.to be_denied_for(:user) }
+ it { expect { go }.to be_denied_for(:external) }
+ end
+ end
+
+ context 'no group_id param' do
+ it 'does not respond to any action without group_id param' do
+ expect { get :index }.to raise_error(ActionController::UrlGenerationError)
+ end
+ end
+end
diff --git a/spec/controllers/groups/milestones_controller_spec.rb b/spec/controllers/groups/milestones_controller_spec.rb
index 465f3499703..42723bb3820 100644
--- a/spec/controllers/groups/milestones_controller_spec.rb
+++ b/spec/controllers/groups/milestones_controller_spec.rb
@@ -63,7 +63,7 @@ describe Groups::MilestonesController do
let(:group_milestone) { create(:milestone, group: group) }
context 'when there is a title parameter' do
- it 'searchs for a legacy group milestone' do
+ it 'searches for a legacy group milestone' do
expect(GlobalMilestone).to receive(:build)
expect(Milestone).not_to receive(:find_by_iid)
@@ -72,7 +72,7 @@ describe Groups::MilestonesController do
end
context 'when there is not a title parameter' do
- it 'searchs for a group milestone' do
+ it 'searches for a group milestone' do
expect(GlobalMilestone).not_to receive(:build)
expect(Milestone).to receive(:find_by_iid)
diff --git a/spec/controllers/groups/settings/ci_cd_controller_spec.rb b/spec/controllers/groups/settings/ci_cd_controller_spec.rb
index ea18122e0c3..06ccace8242 100644
--- a/spec/controllers/groups/settings/ci_cd_controller_spec.rb
+++ b/spec/controllers/groups/settings/ci_cd_controller_spec.rb
@@ -17,4 +17,18 @@ describe Groups::Settings::CiCdController do
expect(response).to render_template(:show)
end
end
+
+ describe 'PUT #reset_registration_token' do
+ subject { put :reset_registration_token, group_id: group }
+
+ it 'resets runner registration token' do
+ expect { subject }.to change { group.reload.runners_token }
+ end
+
+ it 'redirects the user to admin runners page' do
+ subject
+
+ expect(response).to redirect_to(group_settings_ci_cd_path)
+ end
+ end
end
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index 65d6cd1a295..f6c85102830 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -202,8 +202,8 @@ describe GroupsController do
end
describe 'GET #issues' do
- let(:issue_1) { create(:issue, project: project) }
- let(:issue_2) { create(:issue, project: project) }
+ let(:issue_1) { create(:issue, project: project, title: 'foo') }
+ let(:issue_2) { create(:issue, project: project, title: 'bar') }
before do
create_list(:award_emoji, 3, awardable: issue_2)
@@ -224,6 +224,31 @@ describe GroupsController do
expect(assigns(:issues)).to eq [issue_2, issue_1]
end
end
+
+ context 'searching' do
+ # Remove as part of https://gitlab.com/gitlab-org/gitlab-ce/issues/52271
+ before do
+ stub_feature_flags(use_cte_for_group_issues_search: false)
+ end
+
+ it 'works with popularity sort' do
+ get :issues, id: group.to_param, search: 'foo', sort: 'popularity'
+
+ expect(assigns(:issues)).to eq([issue_1])
+ end
+
+ it 'works with priority sort' do
+ get :issues, id: group.to_param, search: 'foo', sort: 'priority'
+
+ expect(assigns(:issues)).to eq([issue_1])
+ end
+
+ it 'works with label priority sort' do
+ get :issues, id: group.to_param, search: 'foo', sort: 'label_priority'
+
+ expect(assigns(:issues)).to eq([issue_1])
+ end
+ end
end
describe 'GET #merge_requests' do
@@ -504,7 +529,7 @@ describe GroupsController do
sign_in(user)
end
- context 'when transfering to a subgroup goes right' do
+ context 'when transferring to a subgroup goes right' do
let(:new_parent_group) { create(:group, :public) }
let!(:group_member) { create(:group_member, :owner, group: group, user: user) }
let!(:new_parent_group_member) { create(:group_member, :owner, group: new_parent_group, user: user) }
@@ -581,4 +606,24 @@ describe GroupsController do
end
end
end
+
+ context 'token authentication' do
+ it_behaves_like 'authenticates sessionless user', :show, :atom, public: true do
+ before do
+ default_params.merge!(id: group)
+ end
+ end
+
+ it_behaves_like 'authenticates sessionless user', :issues, :atom, public: true do
+ before do
+ default_params.merge!(id: group, author_id: user.id)
+ end
+ end
+
+ it_behaves_like 'authenticates sessionless user', :issues_calendar, :ics, public: true do
+ before do
+ default_params.merge!(id: group)
+ end
+ end
+ end
end
diff --git a/spec/controllers/health_controller_spec.rb b/spec/controllers/health_controller_spec.rb
index d800ad7c187..ec73c89cb11 100644
--- a/spec/controllers/health_controller_spec.rb
+++ b/spec/controllers/health_controller_spec.rb
@@ -14,48 +14,6 @@ describe HealthController do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
end
- describe '#storage_check' do
- before do
- allow(Gitlab::RequestContext).to receive(:client_ip).and_return(whitelisted_ip)
- end
-
- subject { post :storage_check }
-
- it 'checks all the configured storages' do
- expect(Gitlab::Git::Storage::Checker).to receive(:check_all).and_call_original
-
- subject
- end
-
- it 'returns the check interval' do
- stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'true')
- stub_application_setting(circuitbreaker_check_interval: 10)
-
- subject
-
- expect(json_response['check_interval']).to eq(10)
- end
-
- context 'with failing storages', :broken_storage do
- before do
- stub_storage_settings(
- broken: { path: 'tmp/tests/non-existent-repositories' }
- )
- end
-
- it 'includes the failure information' do
- subject
-
- expected_results = [
- { 'storage' => 'broken', 'success' => false },
- { 'storage' => 'default', 'success' => true }
- ]
-
- expect(json_response['results']).to eq(expected_results)
- end
- end
- end
-
describe '#readiness' do
shared_context 'endpoint responding with readiness data' do
let(:request_params) { {} }
diff --git a/spec/controllers/import/bitbucket_server_controller_spec.rb b/spec/controllers/import/bitbucket_server_controller_spec.rb
index 5024ef71771..db912641894 100644
--- a/spec/controllers/import/bitbucket_server_controller_spec.rb
+++ b/spec/controllers/import/bitbucket_server_controller_spec.rb
@@ -121,12 +121,19 @@ describe Import::BitbucketServerController do
@repo = double(slug: 'vim', project_key: 'asd', full_name: 'asd/vim', "valid?" => true, project_name: 'asd', browse_url: 'http://test', name: 'vim')
@invalid_repo = double(slug: 'invalid', project_key: 'foobar', full_name: 'asd/foobar', "valid?" => false, browse_url: 'http://bad-repo')
+ @created_repo = double(slug: 'created', project_key: 'existing', full_name: 'group/created', "valid?" => true, browse_url: 'http://existing')
assign_session_tokens
end
it 'assigns repository categories' do
- created_project = create(:project, import_type: 'bitbucket_server', creator_id: user.id, import_source: 'foo/bar', import_status: 'finished')
- expect(client).to receive(:repos).and_return([@repo, @invalid_repo])
+ created_project = create(:project, :import_finished, import_type: 'bitbucket_server', creator_id: user.id, import_source: @created_repo.browse_url)
+ repos = instance_double(BitbucketServer::Collection)
+
+ expect(repos).to receive(:partition).and_return([[@repo, @created_repo], [@invalid_repo]])
+ expect(repos).to receive(:current_page).and_return(1)
+ expect(repos).to receive(:next_page).and_return(2)
+ expect(repos).to receive(:prev_page).and_return(nil)
+ expect(client).to receive(:repos).and_return(repos)
get :status
diff --git a/spec/controllers/oauth/applications_controller_spec.rb b/spec/controllers/oauth/applications_controller_spec.rb
index ace8a954e92..b4219856fc0 100644
--- a/spec/controllers/oauth/applications_controller_spec.rb
+++ b/spec/controllers/oauth/applications_controller_spec.rb
@@ -40,6 +40,23 @@ describe Oauth::ApplicationsController do
expect(response).to have_gitlab_http_status(302)
expect(response).to redirect_to(profile_path)
end
+
+ context 'redirect_uri' do
+ render_views
+
+ it 'shows an error for a forbidden URI' do
+ invalid_uri_params = {
+ doorkeeper_application: {
+ name: 'foo',
+ redirect_uri: 'javascript://alert()'
+ }
+ }
+
+ post :create, invalid_uri_params
+
+ expect(response.body).to include 'Redirect URI is forbidden by the server'
+ end
+ end
end
end
diff --git a/spec/controllers/profiles/keys_controller_spec.rb b/spec/controllers/profiles/keys_controller_spec.rb
index 363ed410bc0..685db8488f0 100644
--- a/spec/controllers/profiles/keys_controller_spec.rb
+++ b/spec/controllers/profiles/keys_controller_spec.rb
@@ -4,7 +4,7 @@ describe Profiles::KeysController do
let(:user) { create(:user) }
describe "#get_keys" do
- describe "non existant user" do
+ describe "non existent user" do
it "does not generally work" do
get :get_keys, username: 'not-existent'
@@ -62,8 +62,15 @@ describe Profiles::KeysController do
it "responds with text/plain content type" do
get :get_keys, username: user.username
+
expect(response.content_type).to eq("text/plain")
end
+
+ it "responds with attachment content disposition" do
+ get :get_keys, username: user.username
+
+ expect(response.headers['Content-Disposition']).to eq('attachment')
+ end
end
end
end
diff --git a/spec/controllers/profiles/personal_access_tokens_controller_spec.rb b/spec/controllers/profiles/personal_access_tokens_controller_spec.rb
index ed08a4c1bf2..f5860d4296b 100644
--- a/spec/controllers/profiles/personal_access_tokens_controller_spec.rb
+++ b/spec/controllers/profiles/personal_access_tokens_controller_spec.rb
@@ -39,8 +39,10 @@ describe Profiles::PersonalAccessTokensController do
let!(:active_personal_access_token) { create(:personal_access_token, user: user) }
let!(:inactive_personal_access_token) { create(:personal_access_token, :revoked, user: user) }
let!(:impersonation_personal_access_token) { create(:personal_access_token, :impersonation, user: user) }
+ let(:token_value) { 's3cr3t' }
before do
+ PersonalAccessToken.redis_store!(user.id, token_value)
get :index
end
@@ -56,5 +58,9 @@ describe Profiles::PersonalAccessTokensController do
expect(assigns(:active_personal_access_tokens)).not_to include(impersonation_personal_access_token)
expect(assigns(:inactive_personal_access_tokens)).not_to include(impersonation_personal_access_token)
end
+
+ it "retrieves newly created personal access token value" do
+ expect(assigns(:new_personal_access_token)).to eql(token_value)
+ end
end
end
diff --git a/spec/controllers/projects/artifacts_controller_spec.rb b/spec/controllers/projects/artifacts_controller_spec.rb
index 4ea6f869aa3..b3c8d6a954e 100644
--- a/spec/controllers/projects/artifacts_controller_spec.rb
+++ b/spec/controllers/projects/artifacts_controller_spec.rb
@@ -19,10 +19,67 @@ describe Projects::ArtifactsController do
end
describe 'GET download' do
- it 'sends the artifacts file' do
- expect(controller).to receive(:send_file).with(job.artifacts_file.path, hash_including(disposition: 'attachment')).and_call_original
+ def download_artifact(extra_params = {})
+ params = { namespace_id: project.namespace, project_id: project, job_id: job }.merge(extra_params)
- get :download, namespace_id: project.namespace, project_id: project, job_id: job
+ get :download, params
+ end
+
+ context 'when no file type is supplied' do
+ it 'sends the artifacts file' do
+ expect(controller).to receive(:send_file).with(job.artifacts_file.path, hash_including(disposition: 'attachment')).and_call_original
+
+ download_artifact
+ end
+ end
+
+ context 'when a file type is supplied' do
+ context 'when an invalid file type is supplied' do
+ let(:file_type) { 'invalid' }
+
+ it 'returns 404' do
+ download_artifact(file_type: file_type)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'when codequality file type is supplied' do
+ let(:file_type) { 'codequality' }
+
+ context 'when file is stored locally' do
+ before do
+ create(:ci_job_artifact, :codequality, job: job)
+ end
+
+ it 'sends the codequality report' do
+ expect(controller).to receive(:send_file).with(job.job_artifacts_codequality.file.path, hash_including(disposition: 'attachment')).and_call_original
+
+ download_artifact(file_type: file_type)
+ end
+ end
+
+ context 'when file is stored remotely' do
+ before do
+ stub_artifacts_object_storage
+ create(:ci_job_artifact, :remote_store, :codequality, job: job)
+ end
+
+ it 'sends the codequality report' do
+ expect(controller).to receive(:redirect_to).and_call_original
+
+ download_artifact(file_type: file_type)
+ end
+
+ context 'when proxied' do
+ it 'sends the codequality report' do
+ expect(Gitlab::Workhorse).to receive(:send_url).and_call_original
+
+ download_artifact(file_type: file_type, proxy: true)
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/controllers/projects/blob_controller_spec.rb b/spec/controllers/projects/blob_controller_spec.rb
index 32cd7c6e70a..9fc6af6a045 100644
--- a/spec/controllers/projects/blob_controller_spec.rb
+++ b/spec/controllers/projects/blob_controller_spec.rb
@@ -35,6 +35,11 @@ describe Projects::BlobController do
let(:id) { 'binary-encoding/encoding/binary-1.bin' }
it { is_expected.to respond_with(:success) }
end
+
+ context "Markdown file" do
+ let(:id) { 'master/README.md' }
+ it { is_expected.to respond_with(:success) }
+ end
end
context 'with file path and JSON format' do
@@ -152,12 +157,12 @@ describe Projects::BlobController do
expect(match_line['meta_data']).to have_key('new_pos')
end
- it 'does not add top match line when when "since" is equal 1' do
+ it 'does not add top match line when "since" is equal 1' do
do_get(since: 1, to: 10, offset: 10, from_merge_request: true)
match_line = JSON.parse(response.body).first
- expect(match_line['type']).to eq('context')
+ expect(match_line['type']).to be_nil
end
it 'adds bottom match line when "t"o is less than blob size' do
@@ -177,7 +182,7 @@ describe Projects::BlobController do
match_line = JSON.parse(response.body).last
- expect(match_line['type']).to eq('context')
+ expect(match_line['type']).to be_nil
end
end
end
@@ -343,4 +348,76 @@ describe Projects::BlobController do
end
end
end
+
+ describe 'DELETE destroy' do
+ let(:user) { create(:user) }
+ let(:project_root_path) { project_tree_path(project, 'master') }
+
+ before do
+ project.add_maintainer(user)
+
+ sign_in(user)
+ end
+
+ context 'for a file in a subdirectory' do
+ let(:default_params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: 'master/files/whitespace',
+ original_branch: 'master',
+ branch_name: 'master',
+ commit_message: 'Delete whitespace'
+ }
+ end
+
+ let(:after_delete_path) { project_tree_path(project, 'master/files') }
+
+ it 'redirects to the sub directory' do
+ delete :destroy, default_params
+
+ expect(response).to redirect_to(after_delete_path)
+ end
+ end
+
+ context 'if deleted file is the last one in a subdirectory' do
+ let(:default_params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: 'master/bar/branch-test.txt',
+ original_branch: 'master',
+ branch_name: 'master',
+ commit_message: 'Delete whitespace'
+ }
+ end
+
+ it 'redirects to the project root' do
+ delete :destroy, default_params
+
+ expect(response).to redirect_to(project_root_path)
+ end
+
+ context 'when deleting a file in a branch other than master' do
+ let(:default_params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: 'binary-encoding/foo/bar/.gitkeep',
+ original_branch: 'binary-encoding',
+ branch_name: 'binary-encoding',
+ commit_message: 'Delete whitespace'
+ }
+ end
+
+ let(:after_delete_path) { project_tree_path(project, 'binary-encoding') }
+
+ it 'redirects to the project root of the branch' do
+ delete :destroy, default_params
+
+ expect(response).to redirect_to(after_delete_path)
+ end
+ end
+ end
+ end
end
diff --git a/spec/controllers/projects/boards_controller_spec.rb b/spec/controllers/projects/boards_controller_spec.rb
index 096efc1c7b2..8d503f6ad32 100644
--- a/spec/controllers/projects/boards_controller_spec.rb
+++ b/spec/controllers/projects/boards_controller_spec.rb
@@ -28,6 +28,28 @@ describe Projects::BoardsController do
expect(response.content_type).to eq 'text/html'
end
+ it 'redirects to latest visited board' do
+ board = create(:board, project: project)
+ create(:board_project_recent_visit, project: board.project, board: board, user: user)
+
+ list_boards
+
+ expect(response).to redirect_to(namespace_project_board_path(id: board.id))
+ end
+
+ it 'renders template if visited board is not found' do
+ temporary_board = create(:board, project: project)
+ visited = create(:board_project_recent_visit, project: temporary_board.project, board: temporary_board, user: user)
+ temporary_board.delete
+
+ allow_any_instance_of(Boards::Visits::LatestService).to receive(:execute).and_return(visited)
+
+ list_boards
+
+ expect(response).to render_template :index
+ expect(response.content_type).to eq 'text/html'
+ end
+
context 'with unauthorized user' do
before do
allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(true)
@@ -41,12 +63,30 @@ describe Projects::BoardsController do
expect(response.content_type).to eq 'text/html'
end
end
+
+ context 'when user is signed out' do
+ let(:project) { create(:project, :public) }
+
+ it 'renders template' do
+ sign_out(user)
+
+ board = create(:board, project: project)
+ create(:board_project_recent_visit, project: board.project, board: board, user: user)
+
+ list_boards
+
+ expect(response).to render_template :index
+ expect(response.content_type).to eq 'text/html'
+ end
+ end
end
context 'when format is JSON' do
it 'returns a list of project boards' do
create_list(:board, 2, project: project)
+ expect(Boards::Visits::LatestService).not_to receive(:new)
+
list_boards format: :json
parsed_response = JSON.parse(response.body)
@@ -98,7 +138,7 @@ describe Projects::BoardsController do
context 'when format is HTML' do
it 'renders template' do
- read_board board: board
+ expect { read_board board: board }.to change(BoardProjectRecentVisit, :count).by(1)
expect(response).to render_template :show
expect(response.content_type).to eq 'text/html'
@@ -117,10 +157,25 @@ describe Projects::BoardsController do
expect(response.content_type).to eq 'text/html'
end
end
+
+ context 'when user is signed out' do
+ let(:project) { create(:project, :public) }
+
+ it 'does not save visit' do
+ sign_out(user)
+
+ expect { read_board board: board }.to change(BoardProjectRecentVisit, :count).by(0)
+
+ expect(response).to render_template :show
+ expect(response.content_type).to eq 'text/html'
+ end
+ end
end
context 'when format is JSON' do
it 'returns project board' do
+ expect(Boards::Visits::CreateService).not_to receive(:new)
+
read_board board: board, format: :json
expect(response).to match_response_schema('board')
diff --git a/spec/controllers/projects/clusters/applications_controller_spec.rb b/spec/controllers/projects/clusters/applications_controller_spec.rb
index 9e17e392d3d..8106453a775 100644
--- a/spec/controllers/projects/clusters/applications_controller_spec.rb
+++ b/spec/controllers/projects/clusters/applications_controller_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Projects::Clusters::ApplicationsController do
diff --git a/spec/controllers/projects/clusters_controller_spec.rb b/spec/controllers/projects/clusters_controller_spec.rb
index 97ac11fd171..483222363bb 100644
--- a/spec/controllers/projects/clusters_controller_spec.rb
+++ b/spec/controllers/projects/clusters_controller_spec.rb
@@ -1,20 +1,27 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Projects::ClustersController do
include AccessMatchersForController
include GoogleApi::CloudPlatformHelpers
+ include KubernetesHelpers
set(:project) { create(:project) }
- describe 'GET index' do
- describe 'functionality' do
- let(:user) { create(:user) }
+ let(:user) { create(:user) }
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+ end
+ describe 'GET index' do
+ def go(params = {})
+ get :index, params.reverse_merge(namespace_id: project.namespace.to_param, project_id: project)
+ end
+
+ describe 'functionality' do
context 'when project has one or more clusters' do
let(:project) { create(:project) }
let!(:enabled_cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
@@ -33,10 +40,11 @@ describe Projects::ClustersController do
before do
allow(Clusters::Cluster).to receive(:paginates_per).and_return(1)
create_list(:cluster, 2, :provided_by_gcp, :production_environment, projects: [project])
- get :index, namespace_id: project.namespace, project_id: project, page: last_page
end
it 'redirects to the page' do
+ go(page: last_page)
+
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:clusters).current_page).to eq(last_page)
end
@@ -68,21 +76,14 @@ describe Projects::ClustersController do
it { expect { go }.to be_denied_for(:user) }
it { expect { go }.to be_denied_for(:external) }
end
+ end
+ describe 'GET new' do
def go
- get :index, namespace_id: project.namespace.to_param, project_id: project
+ get :new, namespace_id: project.namespace, project_id: project
end
- end
- describe 'GET new' do
describe 'functionality for new cluster' do
- let(:user) { create(:user) }
-
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
-
context 'when omniauth has been configured' do
let(:key) { 'secret-key' }
let(:session_key_for_redirect_uri) do
@@ -121,7 +122,7 @@ describe Projects::ClustersController do
it 'has new object' do
go
- expect(assigns(:gcp_cluster)).to be_an_instance_of(Clusters::Cluster)
+ expect(assigns(:gcp_cluster)).to be_an_instance_of(Clusters::ClusterPresenter)
end
end
@@ -139,17 +140,10 @@ describe Projects::ClustersController do
end
describe 'functionality for existing cluster' do
- let(:user) { create(:user) }
-
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
-
it 'has new object' do
go
- expect(assigns(:user_cluster)).to be_an_instance_of(Clusters::Cluster)
+ expect(assigns(:user_cluster)).to be_an_instance_of(Clusters::ClusterPresenter)
end
end
@@ -163,10 +157,6 @@ describe Projects::ClustersController do
it { expect { go }.to be_denied_for(:user) }
it { expect { go }.to be_denied_for(:external) }
end
-
- def go
- get :new, namespace_id: project.namespace, project_id: project
- end
end
describe 'POST create for new cluster' do
@@ -183,14 +173,11 @@ describe Projects::ClustersController do
}
end
- describe 'functionality' do
- let(:user) { create(:user) }
-
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
+ def go
+ post :create_gcp, params.merge(namespace_id: project.namespace, project_id: project)
+ end
+ describe 'functionality' do
context 'when access token is valid' do
before do
stub_google_api_validate_token
@@ -234,9 +221,9 @@ describe Projects::ClustersController do
describe 'security' do
before do
allow_any_instance_of(described_class)
- .to receive(:token_in_session).and_return('token')
+ .to receive(:token_in_session).and_return('token')
allow_any_instance_of(described_class)
- .to receive(:expires_at_in_session).and_return(1.hour.since.to_i.to_s)
+ .to receive(:expires_at_in_session).and_return(1.hour.since.to_i.to_s)
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
.to receive(:projects_zones_clusters_create) do
OpenStruct.new(
@@ -257,10 +244,6 @@ describe Projects::ClustersController do
it { expect { go }.to be_denied_for(:user) }
it { expect { go }.to be_denied_for(:external) }
end
-
- def go
- post :create_gcp, params.merge(namespace_id: project.namespace, project_id: project)
- end
end
describe 'POST create for existing cluster' do
@@ -277,14 +260,11 @@ describe Projects::ClustersController do
}
end
- describe 'functionality' do
- let(:user) { create(:user) }
-
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
+ def go
+ post :create_user, params.merge(namespace_id: project.namespace, project_id: project)
+ end
+ describe 'functionality' do
context 'when creates a cluster' do
it 'creates a new cluster' do
expect(ClusterProvisionWorker).to receive(:perform_async)
@@ -330,6 +310,11 @@ describe Projects::ClustersController do
end
describe 'security' do
+ before do
+ allow(ClusterPlatformConfigureWorker).to receive(:perform_async)
+ stub_kubeclient_get_namespace('https://kubernetes.example.com', namespace: 'my-namespace')
+ end
+
it { expect { go }.to be_allowed_for(:admin) }
it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:maintainer).of(project) }
@@ -339,23 +324,20 @@ describe Projects::ClustersController do
it { expect { go }.to be_denied_for(:user) }
it { expect { go }.to be_denied_for(:external) }
end
-
- def go
- post :create_user, params.merge(namespace_id: project.namespace, project_id: project)
- end
end
- describe 'GET status' do
+ describe 'GET cluster_status' do
let(:cluster) { create(:cluster, :providing_by_gcp, projects: [project]) }
- describe 'functionality' do
- let(:user) { create(:user) }
-
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
+ def go
+ get :cluster_status,
+ namespace_id: project.namespace.to_param,
+ project_id: project.to_param,
+ id: cluster,
+ format: :json
+ end
+ describe 'functionality' do
it "responds with matching schema" do
go
@@ -380,26 +362,19 @@ describe Projects::ClustersController do
it { expect { go }.to be_denied_for(:user) }
it { expect { go }.to be_denied_for(:external) }
end
-
- def go
- get :status, namespace_id: project.namespace,
- project_id: project,
- id: cluster,
- format: :json
- end
end
describe 'GET show' do
let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
- describe 'functionality' do
- let(:user) { create(:user) }
-
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
+ def go
+ get :show,
+ namespace_id: project.namespace,
+ project_id: project,
+ id: cluster
+ end
+ describe 'functionality' do
it "renders view" do
go
@@ -418,145 +393,89 @@ describe Projects::ClustersController do
it { expect { go }.to be_denied_for(:user) }
it { expect { go }.to be_denied_for(:external) }
end
-
- def go
- get :show, namespace_id: project.namespace,
- project_id: project,
- id: cluster
- end
end
describe 'PUT update' do
- context 'when cluster is provided by GCP' do
- let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
- let(:user) { create(:user) }
-
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
-
- context 'when changing parameters' do
- let(:params) do
- {
- cluster: {
- enabled: false,
- name: 'my-new-cluster-name',
- platform_kubernetes_attributes: {
- namespace: 'my-namespace'
- }
- }
- }
- end
-
- it "updates and redirects back to show page" do
- go
-
- cluster.reload
- expect(response).to redirect_to(project_cluster_path(project, cluster))
- expect(flash[:notice]).to eq('Kubernetes cluster was successfully updated.')
- expect(cluster.enabled).to be_falsey
- end
-
- it "does not change cluster name" do
- go
-
- expect(cluster.name).to eq('test-cluster')
- end
+ def go(format: :html)
+ put :update, params.merge(namespace_id: project.namespace.to_param,
+ project_id: project.to_param,
+ id: cluster,
+ format: format
+ )
+ end
- context 'when cluster is being created' do
- let(:cluster) { create(:cluster, :providing_by_gcp, projects: [project]) }
+ before do
+ allow(ClusterPlatformConfigureWorker).to receive(:perform_async)
+ stub_kubeclient_get_namespace('https://kubernetes.example.com', namespace: 'my-namespace')
+ end
- it "rejects changes" do
- go
+ let(:cluster) { create(:cluster, :provided_by_user, projects: [project]) }
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to render_template(:show)
- expect(cluster.enabled).to be_truthy
- end
- end
- end
+ let(:params) do
+ {
+ cluster: {
+ enabled: false,
+ name: 'my-new-cluster-name',
+ platform_kubernetes_attributes: {
+ namespace: 'my-namespace'
+ }
+ }
+ }
end
- context 'when cluster is provided by user' do
- let(:cluster) { create(:cluster, :provided_by_user, projects: [project]) }
- let(:user) { create(:user) }
+ it "updates and redirects back to show page" do
+ go
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
+ cluster.reload
+ expect(response).to redirect_to(project_cluster_path(project, cluster))
+ expect(flash[:notice]).to eq('Kubernetes cluster was successfully updated.')
+ expect(cluster.enabled).to be_falsey
+ expect(cluster.name).to eq('my-new-cluster-name')
+ expect(cluster.platform_kubernetes.namespace).to eq('my-namespace')
+ end
- context 'when format is json' do
- context 'when changing parameters' do
- context 'when valid parameters are used' do
- let(:params) do
- {
- cluster: {
- enabled: false,
- name: 'my-new-cluster-name',
- platform_kubernetes_attributes: {
- namespace: 'my-namespace'
- }
+ context 'when format is json' do
+ context 'when changing parameters' do
+ context 'when valid parameters are used' do
+ let(:params) do
+ {
+ cluster: {
+ enabled: false,
+ name: 'my-new-cluster-name',
+ platform_kubernetes_attributes: {
+ namespace: 'my-namespace'
}
}
- end
-
- it "updates and redirects back to show page" do
- go_json
-
- cluster.reload
- expect(response).to have_http_status(:no_content)
- expect(cluster.enabled).to be_falsey
- expect(cluster.name).to eq('my-new-cluster-name')
- expect(cluster.platform_kubernetes.namespace).to eq('my-namespace')
- end
+ }
end
- context 'when invalid parameters are used' do
- let(:params) do
- {
- cluster: {
- enabled: false,
- platform_kubernetes_attributes: {
- namespace: 'my invalid namespace #@'
- }
- }
- }
- end
-
- it "rejects changes" do
- go_json
+ it "updates and redirects back to show page" do
+ go(format: :json)
- expect(response).to have_http_status(:bad_request)
- end
+ cluster.reload
+ expect(response).to have_http_status(:no_content)
+ expect(cluster.enabled).to be_falsey
+ expect(cluster.name).to eq('my-new-cluster-name')
+ expect(cluster.platform_kubernetes.namespace).to eq('my-namespace')
end
end
- end
- context 'when format is html' do
- context 'when update enabled' do
+ context 'when invalid parameters are used' do
let(:params) do
{
cluster: {
enabled: false,
- name: 'my-new-cluster-name',
platform_kubernetes_attributes: {
- namespace: 'my-namespace'
+ namespace: 'my invalid namespace #@'
}
}
}
end
- it "updates and redirects back to show page" do
- go
+ it "rejects changes" do
+ go(format: :json)
- cluster.reload
- expect(response).to redirect_to(project_cluster_path(project, cluster))
- expect(flash[:notice]).to eq('Kubernetes cluster was successfully updated.')
- expect(cluster.enabled).to be_falsey
- expect(cluster.name).to eq('my-new-cluster-name')
- expect(cluster.platform_kubernetes.namespace).to eq('my-namespace')
+ expect(response).to have_http_status(:bad_request)
end
end
end
@@ -565,10 +484,6 @@ describe Projects::ClustersController do
describe 'security' do
set(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
- let(:params) do
- { cluster: { enabled: false } }
- end
-
it { expect { go }.to be_allowed_for(:admin) }
it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:maintainer).of(project) }
@@ -578,34 +493,21 @@ describe Projects::ClustersController do
it { expect { go }.to be_denied_for(:user) }
it { expect { go }.to be_denied_for(:external) }
end
-
- def go
- put :update, params.merge(namespace_id: project.namespace,
- project_id: project,
- id: cluster)
- end
-
- def go_json
- put :update, params.merge(namespace_id: project.namespace,
- project_id: project,
- id: cluster,
- format: :json)
- end
end
describe 'DELETE destroy' do
- describe 'functionality' do
- let(:user) { create(:user) }
+ let!(:cluster) { create(:cluster, :provided_by_gcp, :production_environment, projects: [project]) }
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
+ def go
+ delete :destroy,
+ namespace_id: project.namespace,
+ project_id: project,
+ id: cluster
+ end
+ describe 'functionality' do
context 'when cluster is provided by GCP' do
context 'when cluster is created' do
- let!(:cluster) { create(:cluster, :provided_by_gcp, :production_environment, projects: [project]) }
-
it "destroys and redirects back to clusters list" do
expect { go }
.to change { Clusters::Cluster.count }.by(-1)
@@ -658,11 +560,11 @@ describe Projects::ClustersController do
it { expect { go }.to be_denied_for(:user) }
it { expect { go }.to be_denied_for(:external) }
end
+ end
- def go
- delete :destroy, namespace_id: project.namespace,
- project_id: project,
- id: cluster
+ context 'no project_id param' do
+ it 'does not respond to any action without project_id param' do
+ expect { get :index }.to raise_error(ActionController::UrlGenerationError)
end
end
end
diff --git a/spec/controllers/projects/commit_controller_spec.rb b/spec/controllers/projects/commit_controller_spec.rb
index 9e149bc4c3c..e34fdee62d6 100644
--- a/spec/controllers/projects/commit_controller_spec.rb
+++ b/spec/controllers/projects/commit_controller_spec.rb
@@ -356,6 +356,7 @@ describe Projects::CommitController do
expect(response).to be_ok
expect(JSON.parse(response.body)['pipelines']).not_to be_empty
expect(JSON.parse(response.body)['count']['all']).to eq 1
+ expect(response).to include_pagination_headers
end
end
end
diff --git a/spec/controllers/projects/commits_controller_spec.rb b/spec/controllers/projects/commits_controller_spec.rb
index a43bdd3ea80..5c72dab698c 100644
--- a/spec/controllers/projects/commits_controller_spec.rb
+++ b/spec/controllers/projects/commits_controller_spec.rb
@@ -5,87 +5,115 @@ describe Projects::CommitsController do
let(:user) { create(:user) }
before do
- sign_in(user)
project.add_maintainer(user)
end
- describe "GET commits_root" do
- context "no ref is provided" do
- it 'should redirect to the default branch of the project' do
- get(:commits_root,
- namespace_id: project.namespace,
- project_id: project)
+ context 'signed in' do
+ before do
+ sign_in(user)
+ end
+
+ describe "GET commits_root" do
+ context "no ref is provided" do
+ it 'should redirect to the default branch of the project' do
+ get(:commits_root,
+ namespace_id: project.namespace,
+ project_id: project)
- expect(response).to redirect_to project_commits_path(project)
+ expect(response).to redirect_to project_commits_path(project)
+ end
end
end
- end
- describe "GET show" do
- render_views
+ describe "GET show" do
+ render_views
- context 'with file path' do
- before do
- get(:show,
- namespace_id: project.namespace,
- project_id: project,
- id: id)
- end
+ context 'with file path' do
+ before do
+ get(:show,
+ namespace_id: project.namespace,
+ project_id: project,
+ id: id)
+ end
- context "valid branch, valid file" do
- let(:id) { 'master/README.md' }
+ context "valid branch, valid file" do
+ let(:id) { 'master/README.md' }
- it { is_expected.to respond_with(:success) }
- end
+ it { is_expected.to respond_with(:success) }
+ end
- context "valid branch, invalid file" do
- let(:id) { 'master/invalid-path.rb' }
+ context "valid branch, invalid file" do
+ let(:id) { 'master/invalid-path.rb' }
- it { is_expected.to respond_with(:not_found) }
- end
+ it { is_expected.to respond_with(:not_found) }
+ end
- context "invalid branch, valid file" do
- let(:id) { 'invalid-branch/README.md' }
+ context "invalid branch, valid file" do
+ let(:id) { 'invalid-branch/README.md' }
- it { is_expected.to respond_with(:not_found) }
+ it { is_expected.to respond_with(:not_found) }
+ end
end
- end
- context "when the ref name ends in .atom" do
- context "when the ref does not exist with the suffix" do
- before do
- get(:show,
- namespace_id: project.namespace,
- project_id: project,
- id: "master.atom")
+ context "when the ref name ends in .atom" do
+ context "when the ref does not exist with the suffix" do
+ before do
+ get(:show,
+ namespace_id: project.namespace,
+ project_id: project,
+ id: "master.atom")
+ end
+
+ it "renders as atom" do
+ expect(response).to be_success
+ expect(response.content_type).to eq('application/atom+xml')
+ end
+
+ it 'renders summary with type=html' do
+ expect(response.body).to include('<summary type="html">')
+ end
end
- it "renders as atom" do
- expect(response).to be_success
- expect(response.content_type).to eq('application/atom+xml')
- end
+ context "when the ref exists with the suffix" do
+ before do
+ commit = project.repository.commit('master')
- it 'renders summary with type=html' do
- expect(response.body).to include('<summary type="html">')
+ allow_any_instance_of(Repository).to receive(:commit).and_call_original
+ allow_any_instance_of(Repository).to receive(:commit).with('master.atom').and_return(commit)
+
+ get(:show,
+ namespace_id: project.namespace,
+ project_id: project,
+ id: "master.atom")
+ end
+
+ it "renders as HTML" do
+ expect(response).to be_success
+ expect(response.content_type).to eq('text/html')
+ end
end
end
+ end
+ end
- context "when the ref exists with the suffix" do
+ context 'token authentication' do
+ context 'public project' do
+ it_behaves_like 'authenticates sessionless user', :show, :atom, public: true do
before do
- commit = project.repository.commit('master')
+ public_project = create(:project, :repository, :public)
- allow_any_instance_of(Repository).to receive(:commit).and_call_original
- allow_any_instance_of(Repository).to receive(:commit).with('master.atom').and_return(commit)
-
- get(:show,
- namespace_id: project.namespace,
- project_id: project,
- id: "master.atom")
+ default_params.merge!(namespace_id: public_project.namespace, project_id: public_project, id: "master.atom")
end
+ end
+ end
+
+ context 'private project' do
+ it_behaves_like 'authenticates sessionless user', :show, :atom, public: false do
+ before do
+ private_project = create(:project, :repository, :private)
+ private_project.add_maintainer(user)
- it "renders as HTML" do
- expect(response).to be_success
- expect(response.content_type).to eq('text/html')
+ default_params.merge!(namespace_id: private_project.namespace, project_id: private_project, id: "master.atom")
end
end
end
diff --git a/spec/controllers/projects/compare_controller_spec.rb b/spec/controllers/projects/compare_controller_spec.rb
index 8695aa826bb..17883d0fadd 100644
--- a/spec/controllers/projects/compare_controller_spec.rb
+++ b/spec/controllers/projects/compare_controller_spec.rb
@@ -97,6 +97,30 @@ describe Projects::CompareController do
expect(assigns(:commits)).to eq([])
end
end
+
+ context 'when the target ref is invalid' do
+ let(:target_ref) { "master%' AND 2554=4423 AND '%'='" }
+ let(:source_ref) { "improve%2Fawesome" }
+
+ it 'shows a flash message and redirects' do
+ show_request
+
+ expect(flash[:alert]).to eq('Invalid branch name')
+ expect(response).to have_http_status(302)
+ end
+ end
+
+ context 'when the source ref is invalid' do
+ let(:source_ref) { "master%' AND 2554=4423 AND '%'='" }
+ let(:target_ref) { "improve%2Fawesome" }
+
+ it 'shows a flash message and redirects' do
+ show_request
+
+ expect(flash[:alert]).to eq('Invalid branch name')
+ expect(response).to have_http_status(302)
+ end
+ end
end
describe 'GET diff_for_path' do
diff --git a/spec/controllers/projects/deploy_keys_controller_spec.rb b/spec/controllers/projects/deploy_keys_controller_spec.rb
index 73bf169085f..4567a51b88e 100644
--- a/spec/controllers/projects/deploy_keys_controller_spec.rb
+++ b/spec/controllers/projects/deploy_keys_controller_spec.rb
@@ -27,12 +27,8 @@ describe Projects::DeployKeysController do
let(:project2) { create(:project, :internal)}
let(:project_private) { create(:project, :private)}
- let(:deploy_key_internal) do
- create(:deploy_key, key: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCdMHEHyhRjbhEZVddFn6lTWdgEy5Q6Bz4nwGB76xWZI5YT/1WJOMEW+sL5zYd31kk7sd3FJ5L9ft8zWMWrr/iWXQikC2cqZK24H1xy+ZUmrRuJD4qGAaIVoyyzBL+avL+lF8J5lg6YSw8gwJY/lX64/vnJHUlWw2n5BF8IFOWhiw== dummy@gitlab.com')
- end
- let(:deploy_key_actual) do
- create(:deploy_key, key: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDNd/UJWhPrpb+b/G5oL109y57yKuCxE+WUGJGYaj7WQKsYRJmLYh1mgjrl+KVyfsWpq4ylOxIfFSnN9xBBFN8mlb0Fma5DC7YsSsibJr3MZ19ZNBprwNcdogET7aW9I0In7Wu5f2KqI6e5W/spJHCy4JVxzVMUvk6Myab0LnJ2iQ== dummy@gitlab.com')
- end
+ let(:deploy_key_internal) { create(:deploy_key) }
+ let(:deploy_key_actual) { create(:deploy_key) }
let!(:deploy_key_public) { create(:deploy_key, public: true) }
let!(:deploy_keys_project_internal) do
@@ -63,4 +59,145 @@ describe Projects::DeployKeysController do
end
end
end
+
+ describe '/enable/:id' do
+ let(:deploy_key) { create(:deploy_key) }
+ let(:project2) { create(:project) }
+ let!(:deploy_keys_project_internal) do
+ create(:deploy_keys_project, project: project2, deploy_key: deploy_key)
+ end
+
+ context 'with anonymous user' do
+ before do
+ sign_out(:user)
+ end
+
+ it 'redirects to login' do
+ expect do
+ put :enable, id: deploy_key.id, namespace_id: project.namespace, project_id: project
+ end.not_to change { DeployKeysProject.count }
+
+ expect(response).to have_http_status(302)
+ expect(response).to redirect_to(new_user_session_path)
+ end
+ end
+
+ context 'with user with no permission' do
+ before do
+ sign_in(create(:user))
+ end
+
+ it 'returns 404' do
+ expect do
+ put :enable, id: deploy_key.id, namespace_id: project.namespace, project_id: project
+ end.not_to change { DeployKeysProject.count }
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'with user with permission' do
+ before do
+ project2.add_maintainer(user)
+ end
+
+ it 'returns 302' do
+ expect do
+ put :enable, id: deploy_key.id, namespace_id: project.namespace, project_id: project
+ end.to change { DeployKeysProject.count }.by(1)
+
+ expect(DeployKeysProject.where(project_id: project.id, deploy_key_id: deploy_key.id).count).to eq(1)
+ expect(response).to have_http_status(302)
+ expect(response).to redirect_to(namespace_project_settings_repository_path(anchor: 'js-deploy-keys-settings'))
+ end
+
+ it 'returns 404' do
+ put :enable, id: 0, namespace_id: project.namespace, project_id: project
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'with admin' do
+ before do
+ sign_in(create(:admin))
+ end
+
+ it 'returns 302' do
+ expect do
+ put :enable, id: deploy_key.id, namespace_id: project.namespace, project_id: project
+ end.to change { DeployKeysProject.count }.by(1)
+
+ expect(DeployKeysProject.where(project_id: project.id, deploy_key_id: deploy_key.id).count).to eq(1)
+ expect(response).to have_http_status(302)
+ expect(response).to redirect_to(namespace_project_settings_repository_path(anchor: 'js-deploy-keys-settings'))
+ end
+ end
+ end
+
+ describe '/disable/:id' do
+ let(:deploy_key) { create(:deploy_key) }
+ let!(:deploy_key_project) { create(:deploy_keys_project, project: project, deploy_key: deploy_key) }
+
+ context 'with anonymous user' do
+ before do
+ sign_out(:user)
+ end
+
+ it 'redirects to login' do
+ put :disable, id: deploy_key.id, namespace_id: project.namespace, project_id: project
+
+ expect(response).to have_http_status(302)
+ expect(response).to redirect_to(new_user_session_path)
+ expect(DeployKey.find(deploy_key.id)).to eq(deploy_key)
+ end
+ end
+
+ context 'with user with no permission' do
+ before do
+ sign_in(create(:user))
+ end
+
+ it 'returns 404' do
+ put :disable, id: deploy_key.id, namespace_id: project.namespace, project_id: project
+
+ expect(response).to have_http_status(404)
+ expect(DeployKey.find(deploy_key.id)).to eq(deploy_key)
+ end
+ end
+
+ context 'with user with permission' do
+ it 'returns 302' do
+ put :disable, id: deploy_key.id, namespace_id: project.namespace, project_id: project
+
+ expect(response).to have_http_status(302)
+ expect(response).to redirect_to(namespace_project_settings_repository_path(anchor: 'js-deploy-keys-settings'))
+
+ expect { DeployKey.find(deploy_key.id) }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+
+ it 'returns 404' do
+ put :disable, id: 0, namespace_id: project.namespace, project_id: project
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'with admin' do
+ before do
+ sign_in(create(:admin))
+ end
+
+ it 'returns 302' do
+ expect do
+ put :disable, id: deploy_key.id, namespace_id: project.namespace, project_id: project
+ end.to change { DeployKey.count }.by(-1)
+
+ expect(response).to have_http_status(302)
+ expect(response).to redirect_to(namespace_project_settings_repository_path(anchor: 'js-deploy-keys-settings'))
+
+ expect { DeployKey.find(deploy_key.id) }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+ end
end
diff --git a/spec/controllers/projects/deployments_controller_spec.rb b/spec/controllers/projects/deployments_controller_spec.rb
index d1c960e895d..5b7da81b6a1 100644
--- a/spec/controllers/projects/deployments_controller_spec.rb
+++ b/spec/controllers/projects/deployments_controller_spec.rb
@@ -15,9 +15,9 @@ describe Projects::DeploymentsController do
describe 'GET #index' do
it 'returns list of deployments from last 8 hours' do
- create(:deployment, environment: environment, created_at: 9.hours.ago)
- create(:deployment, environment: environment, created_at: 7.hours.ago)
- create(:deployment, environment: environment)
+ create(:deployment, :success, environment: environment, created_at: 9.hours.ago)
+ create(:deployment, :success, environment: environment, created_at: 7.hours.ago)
+ create(:deployment, :success, environment: environment)
get :index, deployment_params(after: 8.hours.ago)
@@ -27,7 +27,7 @@ describe Projects::DeploymentsController do
end
it 'returns a list with deployments information' do
- create(:deployment, environment: environment)
+ create(:deployment, :success, environment: environment)
get :index, deployment_params
@@ -37,7 +37,7 @@ describe Projects::DeploymentsController do
end
describe 'GET #metrics' do
- let(:deployment) { create(:deployment, project: project, environment: environment) }
+ let(:deployment) { create(:deployment, :success, project: project, environment: environment) }
before do
allow(controller).to receive(:deployment).and_return(deployment)
@@ -110,7 +110,7 @@ describe Projects::DeploymentsController do
end
describe 'GET #additional_metrics' do
- let(:deployment) { create(:deployment, project: project, environment: environment) }
+ let(:deployment) { create(:deployment, :success, project: project, environment: environment) }
before do
allow(controller).to receive(:deployment).and_return(deployment)
diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb
index b86029a4baf..5fa0488014f 100644
--- a/spec/controllers/projects/environments_controller_spec.rb
+++ b/spec/controllers/projects/environments_controller_spec.rb
@@ -216,8 +216,11 @@ describe Projects::EnvironmentsController do
expect(response).to have_gitlab_http_status(200)
end
- it 'loads the terminals for the enviroment' do
- expect_any_instance_of(Environment).to receive(:terminals)
+ it 'loads the terminals for the environment' do
+ # In EE we have to stub EE::Environment since it overwrites the
+ # "terminals" method.
+ expect_any_instance_of(defined?(EE) ? EE::Environment : Environment)
+ .to receive(:terminals)
get :terminal, environment_params
end
@@ -240,7 +243,9 @@ describe Projects::EnvironmentsController do
context 'and valid id' do
it 'returns the first terminal for the environment' do
- expect_any_instance_of(Environment)
+ # In EE we have to stub EE::Environment since it overwrites the
+ # "terminals" method.
+ expect_any_instance_of(defined?(EE) ? EE::Environment : Environment)
.to receive(:terminals)
.and_return([:fake_terminal])
diff --git a/spec/controllers/projects/imports_controller_spec.rb b/spec/controllers/projects/imports_controller_spec.rb
index adf3c78ae51..cdc63f5aab3 100644
--- a/spec/controllers/projects/imports_controller_spec.rb
+++ b/spec/controllers/projects/imports_controller_spec.rb
@@ -26,10 +26,11 @@ describe Projects::ImportsController do
context 'when repository exists' do
let(:project) { create(:project_empty_repo, import_url: 'https://github.com/vim/vim.git') }
+ let(:import_state) { project.import_state }
context 'when import is in progress' do
before do
- project.update(import_status: :started)
+ import_state.update(status: :started)
end
it 'renders template' do
@@ -47,7 +48,7 @@ describe Projects::ImportsController do
context 'when import failed' do
before do
- project.update(import_status: :failed)
+ import_state.update(status: :failed)
end
it 'redirects to new_namespace_project_import_path' do
@@ -59,7 +60,7 @@ describe Projects::ImportsController do
context 'when import finished' do
before do
- project.update(import_status: :finished)
+ import_state.update(status: :finished)
end
context 'when project is a fork' do
@@ -108,7 +109,7 @@ describe Projects::ImportsController do
context 'when import never happened' do
before do
- project.update(import_status: :none)
+ import_state.update(status: :none)
end
it 'redirects to namespace_project_path' do
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index 5b347b1109a..02930edbf72 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -637,6 +637,18 @@ describe Projects::IssuesController do
project_id: project,
id: id
end
+
+ it 'avoids (most) N+1s loading labels', :request_store do
+ label = create(:label, project: project).to_reference
+ labels = create_list(:label, 10, project: project).map(&:to_reference)
+ issue = create(:issue, project: project, description: 'Test issue')
+
+ control_count = ActiveRecord::QueryRecorder.new { issue.update(description: [issue.description, label].join(' ')) }.count
+
+ # Follow-up to get rid of this `2 * label.count` requirement: https://gitlab.com/gitlab-org/gitlab-ce/issues/52230
+ expect { issue.update(description: [issue.description, labels].join(' ')) }
+ .not_to exceed_query_limit(control_count + 2 * labels.count)
+ end
end
describe 'GET #realtime_changes' do
@@ -1016,6 +1028,13 @@ describe Projects::IssuesController do
.not_to exceed_query_limit(control)
end
+ context 'when user is setting notes filters' do
+ let(:issuable) { issue }
+ let!(:discussion_note) { create(:discussion_note_on_issue, :system, noteable: issuable, project: project) }
+
+ it_behaves_like 'issuable notes filter'
+ end
+
context 'with cross-reference system note', :request_store do
let(:new_issue) { create(:issue) }
let(:cross_reference) { "mentioned in #{new_issue.to_reference(issue.project)}" }
@@ -1049,4 +1068,40 @@ describe Projects::IssuesController do
end
end
end
+
+ context 'private project with token authentication' do
+ let(:private_project) { create(:project, :private) }
+
+ it_behaves_like 'authenticates sessionless user', :index, :atom do
+ before do
+ default_params.merge!(project_id: private_project, namespace_id: private_project.namespace)
+
+ private_project.add_maintainer(user)
+ end
+ end
+
+ it_behaves_like 'authenticates sessionless user', :calendar, :ics do
+ before do
+ default_params.merge!(project_id: private_project, namespace_id: private_project.namespace)
+
+ private_project.add_maintainer(user)
+ end
+ end
+ end
+
+ context 'public project with token authentication' do
+ let(:public_project) { create(:project, :public) }
+
+ it_behaves_like 'authenticates sessionless user', :index, :atom, public: true do
+ before do
+ default_params.merge!(project_id: public_project, namespace_id: public_project.namespace)
+ end
+ end
+
+ it_behaves_like 'authenticates sessionless user', :calendar, :ics, public: true do
+ before do
+ default_params.merge!(project_id: public_project, namespace_id: public_project.namespace)
+ end
+ end
+ end
end
diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb
index c82c85970dc..da3d658d061 100644
--- a/spec/controllers/projects/jobs_controller_spec.rb
+++ b/spec/controllers/projects/jobs_controller_spec.rb
@@ -152,11 +152,33 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('job/job_details')
expect(json_response['raw_path']).to match(%r{jobs/\d+/raw\z})
- expect(json_response.dig('merge_request', 'path')).to match(%r{merge_requests/\d+\z})
+ expect(json_response['merge_request']['path']).to match(%r{merge_requests/\d+\z})
expect(json_response['new_issue_path']).to include('/issues/new')
end
end
+ context 'when job is running' do
+ context 'job is cancelable' do
+ let(:job) { create(:ci_build, :running, pipeline: pipeline) }
+
+ it 'cancel_path is present with correct redirect' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('job/job_details')
+ expect(json_response['cancel_path']).to include(CGI.escape(json_response['build_path']))
+ end
+ end
+
+ context 'with web terminal' do
+ let(:job) { create(:ci_build, :running, :with_runner_session, pipeline: pipeline) }
+
+ it 'exposes the terminal path' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('job/job_details')
+ expect(json_response['terminal_path']).to match(%r{/terminal})
+ end
+ end
+ end
+
context 'when job has artifacts' do
context 'with not expiry date' do
let(:job) { create(:ci_build, :success, :artifacts, pipeline: pipeline) }
@@ -185,16 +207,6 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
end
- context 'when job has terminal' do
- let(:job) { create(:ci_build, :running, :with_runner_session, pipeline: pipeline) }
-
- it 'exposes the terminal path' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to match_response_schema('job/job_details')
- expect(json_response['terminal_path']).to match(%r{/terminal})
- end
- end
-
context 'when job passed with no trace' do
let(:job) { create(:ci_build, :success, :artifacts, pipeline: pipeline) }
@@ -219,13 +231,12 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
context 'with deployment' do
let(:merge_request) { create(:merge_request, source_project: project) }
let(:environment) { create(:environment, project: project, name: 'staging', state: :available) }
- let(:job) { create(:ci_build, :success, environment: environment.name, pipeline: pipeline) }
+ let(:job) { create(:ci_build, :running, environment: environment.name, pipeline: pipeline) }
it 'exposes the deployment information' do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to match_schema('job/job_details')
expect(json_response['deployment_status']["status"]).to eq 'creating'
- expect(json_response['deployment_status']["icon"]).to eq 'passed'
expect(json_response['deployment_status']["environment"]).not_to be_nil
end
end
@@ -298,6 +309,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
expect(response).to match_response_schema('job/job_details')
expect(json_response['runners']['online']).to be false
expect(json_response['runners']['available']).to be false
+ expect(json_response['stuck']).to be true
end
end
@@ -310,6 +322,7 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
expect(response).to match_response_schema('job/job_details')
expect(json_response['runners']['online']).to be false
expect(json_response['runners']['available']).to be true
+ expect(json_response['stuck']).to be true
end
end
@@ -337,6 +350,26 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
end
end
+
+ context 'when no trace is available' do
+ it 'has_trace is false' do
+ expect(response).to match_response_schema('job/job_details')
+ expect(json_response['has_trace']).to be false
+ end
+ end
+
+ context 'when job has trace' do
+ let(:job) { create(:ci_build, :running, :trace_live, pipeline: pipeline) }
+
+ it "has_trace is true" do
+ expect(response).to match_response_schema('job/job_details')
+ expect(json_response['has_trace']).to be true
+ end
+ end
+
+ it 'exposes the stage the job belongs to' do
+ expect(json_response['stage']).to eq('test')
+ end
end
context 'when requesting JSON job is triggered' do
@@ -584,35 +617,108 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
before do
project.add_developer(user)
sign_in(user)
-
- post_cancel
end
- context 'when job is cancelable' do
+ context 'when continue url is present' do
let(:job) { create(:ci_build, :cancelable, pipeline: pipeline) }
- it 'redirects to the canceled job page' do
+ context 'when continue to is a safe url' do
+ let(:url) { '/test' }
+
+ before do
+ post_cancel(continue: { to: url })
+ end
+
+ it 'redirects to the continue url' do
+ expect(response).to have_gitlab_http_status(:found)
+ expect(response).to redirect_to(url)
+ end
+
+ it 'transits to canceled' do
+ expect(job.reload).to be_canceled
+ end
+ end
+
+ context 'when continue to is not a safe url' do
+ let(:url) { 'http://example.com' }
+
+ it 'raises an error' do
+ expect { cancel_with_redirect(url) }.to raise_error
+ end
+ end
+ end
+
+ context 'when continue url is not present' do
+ before do
+ post_cancel
+ end
+
+ context 'when job is cancelable' do
+ let(:job) { create(:ci_build, :cancelable, pipeline: pipeline) }
+
+ it 'redirects to the builds page' do
+ expect(response).to have_gitlab_http_status(:found)
+ expect(response).to redirect_to(builds_namespace_project_pipeline_path(id: pipeline.id))
+ end
+
+ it 'transits to canceled' do
+ expect(job.reload).to be_canceled
+ end
+ end
+
+ context 'when job is not cancelable' do
+ let(:job) { create(:ci_build, :canceled, pipeline: pipeline) }
+
+ it 'returns unprocessable_entity' do
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
+ end
+ end
+
+ def post_cancel(additional_params = {})
+ post :cancel, { namespace_id: project.namespace,
+ project_id: project,
+ id: job.id }.merge(additional_params)
+ end
+ end
+
+ describe 'POST unschedule' do
+ before do
+ project.add_developer(user)
+
+ create(:protected_branch, :developers_can_merge,
+ name: 'master', project: project)
+
+ sign_in(user)
+
+ post_unschedule
+ end
+
+ context 'when job is scheduled' do
+ let(:job) { create(:ci_build, :scheduled, pipeline: pipeline) }
+
+ it 'redirects to the unscheduled job page' do
expect(response).to have_gitlab_http_status(:found)
expect(response).to redirect_to(namespace_project_job_path(id: job.id))
end
- it 'transits to canceled' do
- expect(job.reload).to be_canceled
+ it 'transits to manual' do
+ expect(job.reload).to be_manual
end
end
- context 'when job is not cancelable' do
- let(:job) { create(:ci_build, :canceled, pipeline: pipeline) }
+ context 'when job is not scheduled' do
+ let(:job) { create(:ci_build, pipeline: pipeline) }
- it 'returns unprocessable_entity' do
+ it 'renders unprocessable_entity' do
expect(response).to have_gitlab_http_status(:unprocessable_entity)
end
end
- def post_cancel
- post :cancel, namespace_id: project.namespace,
- project_id: project,
- id: job.id
+ def post_unschedule
+ post :unschedule, namespace_id: project.namespace,
+ project_id: project,
+ id: job.id
end
end
diff --git a/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb b/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb
index 397cc79bde4..1e1ea9a7144 100644
--- a/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/conflicts_controller_spec.rb
@@ -150,7 +150,6 @@ describe Projects::MergeRequests::ConflictsController do
'new_path' => path,
'blob_icon' => 'file-text-o',
'blob_path' => a_string_ending_with(path),
- 'blob_ace_mode' => 'ruby',
'content' => content)
end
end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 7446e0650f7..e62523c65c9 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -76,28 +76,6 @@ describe Projects::MergeRequestsController do
expect(response).to be_success
end
- context "loads notes" do
- let(:first_contributor) { create(:user) }
- let(:contributor) { create(:user) }
- let(:merge_request) { create(:merge_request, author: first_contributor, target_project: project, source_project: project) }
- let(:contributor_merge_request) { create(:merge_request, :merged, author: contributor, target_project: project, source_project: project) }
- # the order here is important
- # as the controller reloads these from DB, references doesn't correspond after
- let!(:first_contributor_note) { create(:note, author: first_contributor, noteable: merge_request, project: project) }
- let!(:contributor_note) { create(:note, author: contributor, noteable: merge_request, project: project) }
- let!(:owner_note) { create(:note, author: user, noteable: merge_request, project: project) }
-
- it "with special_role FIRST_TIME_CONTRIBUTOR" do
- go(format: :html)
-
- notes = assigns(:notes)
- expect(notes).to match(a_collection_containing_exactly(an_object_having_attributes(special_role: Note::SpecialRole::FIRST_TIME_CONTRIBUTOR),
- an_object_having_attributes(special_role: nil),
- an_object_having_attributes(special_role: nil)
- ))
- end
- end
-
context "that is invalid" do
let(:merge_request) { create(:invalid_merge_request, target_project: project, source_project: project) }
@@ -109,6 +87,14 @@ describe Projects::MergeRequestsController do
end
end
+ context 'when user is setting notes filters' do
+ let(:issuable) { merge_request }
+ let!(:discussion_note) { create(:discussion_note_on_merge_request, :system, noteable: issuable, project: project) }
+ let!(:discussion_comment) { create(:discussion_note_on_merge_request, noteable: issuable, project: project) }
+
+ it_behaves_like 'issuable notes filter'
+ end
+
describe 'as json' do
context 'with basic serializer param' do
it 'renders basic MR entity as json' do
@@ -577,6 +563,7 @@ describe Projects::MergeRequestsController do
it 'responds with serialized pipelines' do
expect(json_response['pipelines']).not_to be_empty
expect(json_response['count']['all']).to eq 1
+ expect(response).to include_pagination_headers
end
end
@@ -763,24 +750,69 @@ describe Projects::MergeRequestsController do
describe 'GET ci_environments_status' do
context 'the environment is from a forked project' do
- let!(:forked) { fork_project(project, user, repository: true) }
- let!(:environment) { create(:environment, project: forked) }
- let!(:deployment) { create(:deployment, environment: environment, sha: forked.commit.id, ref: 'master') }
- let(:admin) { create(:admin) }
+ let(:forked) { fork_project(project, user, repository: true) }
+ let(:sha) { forked.commit.sha }
+ let(:environment) { create(:environment, project: forked) }
+ let(:pipeline) { create(:ci_pipeline, sha: sha, project: forked) }
+ let(:build) { create(:ci_build, pipeline: pipeline) }
+ let!(:deployment) { create(:deployment, :succeed, environment: environment, sha: sha, ref: 'master', deployable: build) }
let(:merge_request) do
- create(:merge_request, source_project: forked, target_project: project)
+ create(:merge_request, source_project: forked, target_project: project, target_branch: 'master', head_pipeline: pipeline)
end
- before do
- get :ci_environments_status,
+ it 'links to the environment on that project' do
+ get_ci_environments_status
+
+ expect(json_response.first['url']).to match /#{forked.full_path}/
+ end
+
+ context "when environment_target is 'merge_commit'" do
+ it 'returns nothing' do
+ get_ci_environments_status(environment_target: 'merge_commit')
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_empty
+ end
+
+ context 'when is merged' do
+ let(:source_environment) { create(:environment, project: project) }
+ let(:merge_commit_sha) { project.repository.merge(user, forked.commit.id, merge_request, "merged in test") }
+ let(:post_merge_pipeline) { create(:ci_pipeline, sha: merge_commit_sha, project: project) }
+ let(:post_merge_build) { create(:ci_build, pipeline: post_merge_pipeline) }
+ let!(:source_deployment) { create(:deployment, :succeed, environment: source_environment, sha: merge_commit_sha, ref: 'master', deployable: post_merge_build) }
+
+ before do
+ merge_request.update!(merge_commit_sha: merge_commit_sha)
+ merge_request.mark_as_merged!
+ end
+
+ it 'returns the environment on the source project' do
+ get_ci_environments_status(environment_target: 'merge_commit')
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response.first['url']).to match /#{project.full_path}/
+ end
+ end
+ end
+
+ # we're trying to reduce the overall number of queries for this method.
+ # set a hard limit for now. https://gitlab.com/gitlab-org/gitlab-ce/issues/52287
+ it 'keeps queries in check' do
+ control_count = ActiveRecord::QueryRecorder.new { get_ci_environments_status }.count
+
+ expect(control_count).to be <= 137
+ end
+
+ def get_ci_environments_status(extra_params = {})
+ params = {
namespace_id: merge_request.project.namespace.to_param,
project_id: merge_request.project,
- id: merge_request.iid, format: 'json'
- end
+ id: merge_request.iid,
+ format: 'json'
+ }
- it 'links to the environment on that project' do
- expect(json_response.first['url']).to match /#{forked.full_path}/
+ get :ci_environments_status, params.merge(extra_params)
end
end
end
@@ -850,12 +882,14 @@ describe Projects::MergeRequestsController do
end
context 'with a forked project' do
- let(:fork_project) { create(:project, :repository, forked_from_project: project) }
- let(:fork_owner) { fork_project.owner }
+ let(:forked_project) { fork_project(project, fork_owner, repository: true) }
+ let(:fork_owner) { create(:user) }
before do
- merge_request.update!(source_project: fork_project)
- fork_project.add_reporter(user)
+ project.add_developer(fork_owner)
+
+ merge_request.update!(source_project: forked_project)
+ forked_project.add_reporter(user)
end
context 'user cannot push to source branch' do
diff --git a/spec/controllers/projects/milestones_controller_spec.rb b/spec/controllers/projects/milestones_controller_spec.rb
index 3190f1ce9d4..658aa2a6738 100644
--- a/spec/controllers/projects/milestones_controller_spec.rb
+++ b/spec/controllers/projects/milestones_controller_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Projects::MilestonesController do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:user) { create(:user) }
let(:milestone) { create(:milestone, project: project) }
let(:issue) { create(:issue, project: project, milestone: milestone) }
@@ -143,11 +143,27 @@ describe Projects::MilestonesController do
end
describe '#promote' do
+ let(:group) { create(:group) }
+
+ before do
+ project.update(namespace: group)
+ end
+
+ context 'when user does not have permission to promote milestone' do
+ before do
+ group.add_guest(user)
+ end
+
+ it 'renders 404' do
+ post :promote, namespace_id: project.namespace.id, project_id: project.id, id: milestone.iid
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
context 'promotion succeeds' do
before do
- group = create(:group)
group.add_developer(user)
- milestone.project.update(namespace: group)
end
it 'shows group milestone' do
@@ -166,12 +182,17 @@ describe Projects::MilestonesController do
end
end
- context 'promotion fails' do
- it 'shows project milestone' do
+ context 'when user cannot admin group milestones' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'renders 404' do
+ project.update(namespace: user.namespace)
+
post :promote, namespace_id: project.namespace.id, project_id: project.id, id: milestone.iid
- expect(response).to redirect_to(project_milestone_path(project, milestone))
- expect(flash[:alert]).to eq('Promotion failed - Project does not belong to a group.')
+ expect(response).to have_gitlab_http_status(404)
end
end
end
diff --git a/spec/controllers/projects/mirrors_controller_spec.rb b/spec/controllers/projects/mirrors_controller_spec.rb
index 6114eef7003..976f480930c 100644
--- a/spec/controllers/projects/mirrors_controller_spec.rb
+++ b/spec/controllers/projects/mirrors_controller_spec.rb
@@ -15,6 +15,31 @@ describe Projects::MirrorsController do
end.to change { RemoteMirror.count }.to(1)
end
end
+
+ context 'setting up SSH public-key authentication' do
+ let(:ssh_mirror_attributes) do
+ {
+ 'auth_method' => 'ssh_public_key',
+ 'url' => 'ssh://git@example.com',
+ 'ssh_known_hosts' => 'test'
+ }
+ end
+
+ it 'processes a successful update' do
+ sign_in(project.owner)
+ do_put(project, remote_mirrors_attributes: { '0' => ssh_mirror_attributes })
+
+ expect(response).to redirect_to(project_settings_repository_path(project, anchor: 'js-push-remote-settings'))
+
+ expect(RemoteMirror.count).to eq(1)
+ expect(RemoteMirror.first).to have_attributes(
+ auth_method: 'ssh_public_key',
+ url: 'ssh://git@example.com',
+ ssh_public_key: match(/\Assh-rsa /),
+ ssh_known_hosts: 'test'
+ )
+ end
+ end
end
describe '#update' do
@@ -63,6 +88,69 @@ describe Projects::MirrorsController do
end
end
+ describe '#ssh_host_keys', :use_clean_rails_memory_store_caching do
+ let(:project) { create(:project) }
+ let(:cache) { SshHostKey.new(project: project, url: "ssh://example.com:22") }
+
+ before do
+ sign_in(project.owner)
+ end
+
+ context 'invalid URLs' do
+ %w[
+ INVALID
+ git@example.com:foo/bar.git
+ ssh://git@example.com:foo/bar.git
+ ].each do |url|
+ it "returns an error with a 400 response for URL #{url.inspect}" do
+ do_get(project, url)
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response).to eq('message' => 'Invalid URL')
+ end
+ end
+ end
+
+ context 'no data in cache' do
+ it 'requests the cache to be filled and returns a 204 response' do
+ expect(ReactiveCachingWorker).to receive(:perform_async).with(cache.class, cache.id).at_least(:once)
+
+ do_get(project)
+
+ expect(response).to have_gitlab_http_status(204)
+ end
+ end
+
+ context 'error in the cache' do
+ it 'returns the error with a 400 response' do
+ stub_reactive_cache(cache, error: 'An error')
+
+ do_get(project)
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response).to eq('message' => 'An error')
+ end
+ end
+
+ context 'data in the cache' do
+ let(:ssh_key) { 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf' }
+ let(:ssh_fp) { { type: 'ed25519', bits: 256, fingerprint: '2e:65:6a:c8:cf:bf:b2:8b:9a:bd:6d:9f:11:5c:12:16', index: 0 } }
+
+ it 'returns the data with a 200 response' do
+ stub_reactive_cache(cache, known_hosts: ssh_key)
+
+ do_get(project)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to eq('known_hosts' => ssh_key, 'fingerprints' => [ssh_fp.stringify_keys], 'host_keys_changed' => true)
+ end
+ end
+
+ def do_get(project, url = 'ssh://example.com')
+ get :ssh_host_keys, namespace_id: project.namespace, project_id: project, ssh_url: url
+ end
+ end
+
def do_put(project, options, extra_attrs = {})
attrs = extra_attrs.merge(namespace_id: project.namespace.to_param, project_id: project.to_param)
attrs[:project] = options
diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb
index 81badaac76b..d2a26068362 100644
--- a/spec/controllers/projects/notes_controller_spec.rb
+++ b/spec/controllers/projects/notes_controller_spec.rb
@@ -47,6 +47,37 @@ describe Projects::NotesController do
get :index, request_params
end
+ context 'when user notes_filter is present' do
+ let(:notes_json) { parsed_response[:notes] }
+ let!(:comment) { create(:note, noteable: issue, project: project) }
+ let!(:system_note) { create(:note, noteable: issue, project: project, system: true) }
+
+ it 'filters system notes by comments' do
+ user.set_notes_filter(UserPreference::NOTES_FILTERS[:only_comments], issue)
+
+ get :index, request_params
+
+ expect(notes_json.count).to eq(1)
+ expect(notes_json.first[:id].to_i).to eq(comment.id)
+ end
+
+ it 'returns all notes' do
+ user.set_notes_filter(UserPreference::NOTES_FILTERS[:all_notes], issue)
+
+ get :index, request_params
+
+ expect(notes_json.map { |note| note[:id].to_i }).to contain_exactly(comment.id, system_note.id)
+ end
+
+ it 'does not merge label event notes' do
+ user.set_notes_filter(UserPreference::NOTES_FILTERS[:only_comments], issue)
+
+ expect(ResourceEvents::MergeIntoNotesService).not_to receive(:new)
+
+ get :index, request_params
+ end
+ end
+
context 'for a discussion note' do
let(:project) { create(:project, :repository) }
let!(:note) { create(:discussion_note_on_merge_request, project: project) }
@@ -207,6 +238,14 @@ describe Projects::NotesController do
expect(response).to have_gitlab_http_status(200)
end
+ it 'returns discussion JSON when the return_discussion param is set' do
+ post :create, request_params.merge(format: :json, return_discussion: 'true')
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to have_key 'discussion'
+ expect(json_response['discussion']['notes'][0]['note']).to eq(request_params[:note][:note])
+ end
+
context 'when merge_request_diff_head_sha present' do
before do
service_params = {
@@ -244,14 +283,14 @@ describe Projects::NotesController do
def post_create(extra_params = {})
post :create, {
- note: { note: 'some other note' },
- namespace_id: project.namespace,
- project_id: project,
- target_type: 'merge_request',
- target_id: merge_request.id,
- note_project_id: forked_project.id,
- in_reply_to_discussion_id: existing_comment.discussion_id
- }.merge(extra_params)
+ note: { note: 'some other note', noteable_id: merge_request.id },
+ namespace_id: project.namespace,
+ project_id: project,
+ target_type: 'merge_request',
+ target_id: merge_request.id,
+ note_project_id: forked_project.id,
+ in_reply_to_discussion_id: existing_comment.discussion_id
+ }.merge(extra_params)
end
context 'when the note_project_id is not correct' do
@@ -285,6 +324,30 @@ describe Projects::NotesController do
end
end
+ context 'when target_id and noteable_id do not match' do
+ let(:locked_issue) { create(:issue, :locked, project: project) }
+ let(:issue) {create(:issue, project: project)}
+
+ before do
+ project.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PUBLIC)
+ project.project_member(user).destroy
+ end
+
+ it 'uses target_id and ignores noteable_id' do
+ request_params = {
+ note: { note: 'some note', noteable_type: 'Issue', noteable_id: locked_issue.id },
+ target_type: 'issue',
+ target_id: issue.id,
+ project_id: project,
+ namespace_id: project.namespace
+ }
+
+ expect { post :create, request_params }.to change { issue.notes.count }.by(1)
+ .and change { locked_issue.notes.count }.by(0)
+ expect(response).to have_gitlab_http_status(302)
+ end
+ end
+
context 'when the merge request discussion is locked' do
before do
project.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PUBLIC)
@@ -337,35 +400,60 @@ describe Projects::NotesController do
end
describe 'PUT update' do
- let(:request_params) do
- {
- namespace_id: project.namespace,
- project_id: project,
- id: note,
- format: :json,
- note: {
- note: "New comment"
+ context "should update the note with a valid issue" do
+ let(:request_params) do
+ {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: note,
+ format: :json,
+ note: {
+ note: "New comment"
+ }
}
- }
- end
+ end
- before do
- sign_in(note.author)
- project.add_developer(note.author)
+ before do
+ sign_in(note.author)
+ project.add_developer(note.author)
+ end
+
+ it "updates the note" do
+ expect { put :update, request_params }.to change { note.reload.note }
+ end
end
+ context "doesnt update the note" do
+ let(:issue) { create(:issue, :confidential, project: project) }
+ let(:note) { create(:note, noteable: issue, project: project) }
- it "updates the note" do
- expect { put :update, request_params }.to change { note.reload.note }
+ before do
+ sign_in(user)
+ project.add_guest(user)
+ end
+
+ it "disallows edits when the issue is confidential and the user has guest permissions" do
+ request_params = {
+ namespace_id: project.namespace,
+ project_id: project,
+ id: note,
+ format: :json,
+ note: {
+ note: "New comment"
+ }
+ }
+ expect { put :update, request_params }.not_to change { note.reload.note }
+ expect(response).to have_gitlab_http_status(404)
+ end
end
end
describe 'DELETE destroy' do
let(:request_params) do
{
- namespace_id: project.namespace,
- project_id: project,
- id: note,
- format: :js
+ namespace_id: project.namespace,
+ project_id: project,
+ id: note,
+ format: :js
}
end
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index 0d49033c691..5c7415a318d 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -90,6 +90,11 @@ describe Projects::PipelinesController do
context 'when performing gitaly calls', :request_store do
it 'limits the Gitaly requests' do
+ # Isolate from test preparation (Repository#exists? is also cached in RequestStore)
+ RequestStore.end!
+ RequestStore.clear!
+ RequestStore.begin!
+
expect { get_pipelines_index_json }
.to change { Gitlab::GitalyClient.get_request_count }.by(2)
end
diff --git a/spec/controllers/projects/settings/ci_cd_controller_spec.rb b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
index 1f14a0cc381..4629929f9af 100644
--- a/spec/controllers/projects/settings/ci_cd_controller_spec.rb
+++ b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
@@ -74,6 +74,19 @@ describe Projects::Settings::CiCdController do
end
end
+ describe 'PUT #reset_registration_token' do
+ subject { put :reset_registration_token, namespace_id: project.namespace, project_id: project }
+ it 'resets runner registration token' do
+ expect { subject }.to change { project.reload.runners_token }
+ end
+
+ it 'redirects the user to admin runners page' do
+ subject
+
+ expect(response).to redirect_to(namespace_project_settings_ci_cd_path)
+ end
+ end
+
describe 'PATCH update' do
let(:params) { { ci_config_path: '' } }
diff --git a/spec/controllers/projects/tags_controller_spec.rb b/spec/controllers/projects/tags_controller_spec.rb
index c48f41ca12e..6fbf75d0259 100644
--- a/spec/controllers/projects/tags_controller_spec.rb
+++ b/spec/controllers/projects/tags_controller_spec.rb
@@ -35,4 +35,26 @@ describe Projects::TagsController do
it { is_expected.to respond_with(:not_found) }
end
end
+
+ context 'private project with token authentication' do
+ let(:private_project) { create(:project, :repository, :private) }
+
+ it_behaves_like 'authenticates sessionless user', :index, :atom do
+ before do
+ default_params.merge!(project_id: private_project, namespace_id: private_project.namespace)
+
+ private_project.add_maintainer(user)
+ end
+ end
+ end
+
+ context 'public project with token authentication' do
+ let(:public_project) { create(:project, :repository, :public) }
+
+ it_behaves_like 'authenticates sessionless user', :index, :atom, public: true do
+ before do
+ default_params.merge!(project_id: public_project, namespace_id: public_project.namespace)
+ end
+ end
+ end
end
diff --git a/spec/controllers/projects/wikis_controller_spec.rb b/spec/controllers/projects/wikis_controller_spec.rb
index 30623b6cb3d..6d75152857b 100644
--- a/spec/controllers/projects/wikis_controller_spec.rb
+++ b/spec/controllers/projects/wikis_controller_spec.rb
@@ -22,20 +22,18 @@ describe Projects::WikisController do
subject { get :show, namespace_id: project.namespace, project_id: project, id: wiki_title }
- context 'when page content encoding is invalid' do
- it 'limits the retrieved pages for the sidebar' do
- expect(controller).to receive(:load_wiki).and_return(project_wiki)
+ it 'limits the retrieved pages for the sidebar' do
+ expect(controller).to receive(:load_wiki).and_return(project_wiki)
- # empty? call
- expect(project_wiki).to receive(:pages).with(limit: 1).and_call_original
- # Sidebar entries
- expect(project_wiki).to receive(:pages).with(limit: 15).and_call_original
+ # empty? call
+ expect(project_wiki).to receive(:pages).with(limit: 1).and_call_original
+ # Sidebar entries
+ expect(project_wiki).to receive(:pages).with(limit: 15).and_call_original
- subject
+ subject
- expect(response).to have_http_status(:ok)
- expect(response.body).to include(wiki_title)
- end
+ expect(response).to have_http_status(:ok)
+ expect(response.body).to include(wiki_title)
end
context 'when page content encoding is invalid' do
@@ -48,6 +46,42 @@ describe Projects::WikisController do
expect(flash[:notice]).to eq 'The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository.'
end
end
+
+ context 'when page is a file' do
+ include WikiHelpers
+
+ let(:path) { upload_file_to_wiki(project, user, file_name) }
+
+ before do
+ subject
+ end
+
+ subject { get :show, namespace_id: project.namespace, project_id: project, id: path }
+
+ context 'when file is an image' do
+ let(:file_name) { 'dk.png' }
+
+ it 'renders the content inline' do
+ expect(response.headers['Content-Disposition']).to match(/^inline/)
+ end
+
+ context 'when file is a svg' do
+ let(:file_name) { 'unsanitized.svg' }
+
+ it 'renders the content as an attachment' do
+ expect(response.headers['Content-Disposition']).to match(/^attachment/)
+ end
+ end
+ end
+
+ context 'when file is a pdf' do
+ let(:file_name) { 'git-cheat-sheet.pdf' }
+
+ it 'sets the content type to application/octet-stream' do
+ expect(response.headers['Content-Type']).to eq 'application/octet-stream'
+ end
+ end
+ end
end
describe 'POST #preview_markdown' do
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index 3bc9cbe64c5..7849bec4762 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -882,6 +882,28 @@ describe ProjectsController do
end
end
+ context 'private project with token authentication' do
+ let(:private_project) { create(:project, :private) }
+
+ it_behaves_like 'authenticates sessionless user', :show, :atom do
+ before do
+ default_params.merge!(id: private_project, namespace_id: private_project.namespace)
+
+ private_project.add_maintainer(user)
+ end
+ end
+ end
+
+ context 'public project with token authentication' do
+ let(:public_project) { create(:project, :public) }
+
+ it_behaves_like 'authenticates sessionless user', :show, :atom, public: true do
+ before do
+ default_params.merge!(id: public_project, namespace_id: public_project.namespace)
+ end
+ end
+ end
+
def project_moved_message(redirect_route, project)
"Project '#{redirect_route.path}' was moved to '#{project.full_path}'. Please update any links and bookmarks that may still have the old path."
end
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index 898f3863008..d334a2ff566 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -49,7 +49,7 @@ describe RegistrationsController do
end
it 'displays an error when the reCAPTCHA is not solved' do
- # Without this, `verify_recaptcha` arbitraily returns true in test env
+ # Without this, `verify_recaptcha` arbitrarily returns true in test env
Recaptcha.configuration.skip_verify_env.delete('test')
post(:create, user_params)
diff --git a/spec/controllers/root_controller_spec.rb b/spec/controllers/root_controller_spec.rb
index 7688538a468..995f803d757 100644
--- a/spec/controllers/root_controller_spec.rb
+++ b/spec/controllers/root_controller_spec.rb
@@ -98,7 +98,7 @@ describe RootController do
it 'redirects to their assigned issues' do
get :index
- expect(response).to redirect_to issues_dashboard_path(assignee_id: user.id)
+ expect(response).to redirect_to issues_dashboard_path(assignee_username: user.username)
end
end
@@ -110,7 +110,7 @@ describe RootController do
it 'redirects to their assigned merge requests' do
get :index
- expect(response).to redirect_to merge_requests_dashboard_path(assignee_id: user.id)
+ expect(response).to redirect_to merge_requests_dashboard_path(assignee_username: user.username)
end
end
diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb
index 8e25b61e2f1..c691b3f478b 100644
--- a/spec/controllers/sessions_controller_spec.rb
+++ b/spec/controllers/sessions_controller_spec.rb
@@ -89,7 +89,7 @@ describe SessionsController do
end
it 'displays an error when the reCAPTCHA is not solved' do
- # Without this, `verify_recaptcha` arbitraily returns true in test env
+ # Without this, `verify_recaptcha` arbitrarily returns true in test env
Recaptcha.configuration.skip_verify_env.delete('test')
counter = double(:counter)
diff --git a/spec/controllers/uploads_controller_spec.rb b/spec/controllers/uploads_controller_spec.rb
index bcf289f36a9..6420b70a54f 100644
--- a/spec/controllers/uploads_controller_spec.rb
+++ b/spec/controllers/uploads_controller_spec.rb
@@ -5,6 +5,17 @@ shared_examples 'content not cached without revalidation' do
end
end
+shared_examples 'content not cached without revalidation and no-store' do
+ it 'ensures content will not be cached without revalidation' do
+ # Fixed in newer versions of ActivePack, it will only output a single `private`.
+ if Gitlab.rails5?
+ expect(subject['Cache-Control']).to eq('max-age=0, private, must-revalidate, no-store')
+ else
+ expect(subject['Cache-Control']).to eq('max-age=0, private, must-revalidate, private, no-store')
+ end
+ end
+end
+
describe UploadsController do
let!(:user) { create(:user, avatar: fixture_file_upload("spec/fixtures/dk.png", "image/png")) }
@@ -177,7 +188,7 @@ describe UploadsController do
expect(response).to have_gitlab_http_status(200)
end
- it_behaves_like 'content not cached without revalidation' do
+ it_behaves_like 'content not cached without revalidation and no-store' do
subject do
get :show, model: 'user', mounted_as: 'avatar', id: user.id, filename: 'dk.png'
@@ -239,7 +250,7 @@ describe UploadsController do
expect(response).to have_gitlab_http_status(200)
end
- it_behaves_like 'content not cached without revalidation' do
+ it_behaves_like 'content not cached without revalidation and no-store' do
subject do
get :show, model: 'project', mounted_as: 'avatar', id: project.id, filename: 'dk.png'
@@ -292,7 +303,7 @@ describe UploadsController do
expect(response).to have_gitlab_http_status(200)
end
- it_behaves_like 'content not cached without revalidation' do
+ it_behaves_like 'content not cached without revalidation and no-store' do
subject do
get :show, model: 'project', mounted_as: 'avatar', id: project.id, filename: 'dk.png'
@@ -344,7 +355,7 @@ describe UploadsController do
expect(response).to have_gitlab_http_status(200)
end
- it_behaves_like 'content not cached without revalidation' do
+ it_behaves_like 'content not cached without revalidation and no-store' do
subject do
get :show, model: 'group', mounted_as: 'avatar', id: group.id, filename: 'dk.png'
@@ -388,7 +399,7 @@ describe UploadsController do
expect(response).to have_gitlab_http_status(200)
end
- it_behaves_like 'content not cached without revalidation' do
+ it_behaves_like 'content not cached without revalidation and no-store' do
subject do
get :show, model: 'group', mounted_as: 'avatar', id: group.id, filename: 'dk.png'
@@ -445,7 +456,7 @@ describe UploadsController do
expect(response).to have_gitlab_http_status(200)
end
- it_behaves_like 'content not cached without revalidation' do
+ it_behaves_like 'content not cached without revalidation and no-store' do
subject do
get :show, model: 'note', mounted_as: 'attachment', id: note.id, filename: 'dk.png'
@@ -498,7 +509,7 @@ describe UploadsController do
expect(response).to have_gitlab_http_status(200)
end
- it_behaves_like 'content not cached without revalidation' do
+ it_behaves_like 'content not cached without revalidation and no-store' do
subject do
get :show, model: 'note', mounted_as: 'attachment', id: note.id, filename: 'dk.png'
diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb
index 071f96a729e..fe438e71e9e 100644
--- a/spec/controllers/users_controller_spec.rb
+++ b/spec/controllers/users_controller_spec.rb
@@ -395,6 +395,14 @@ describe UsersController do
end
end
+ context 'token authentication' do
+ it_behaves_like 'authenticates sessionless user', :show, :atom, public: true do
+ before do
+ default_params.merge!(username: user.username)
+ end
+ end
+ end
+
def user_moved_message(redirect_route, user)
"User '#{redirect_route.path}' was moved to '#{user.full_path}'. Please update any links and bookmarks that may still have the old path."
end
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
new file mode 100644
index 00000000000..e8584846b56
--- /dev/null
+++ b/spec/db/schema_spec.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Database schema' do
+ let(:connection) { ActiveRecord::Base.connection }
+ let(:tables) { connection.tables }
+
+ # Use if you are certain that this column should not have a foreign key
+ IGNORED_FK_COLUMNS = {
+ abuse_reports: %w[reporter_id user_id],
+ application_settings: %w[performance_bar_allowed_group_id],
+ audit_events: %w[author_id entity_id],
+ award_emoji: %w[awardable_id user_id],
+ chat_names: %w[chat_id service_id team_id user_id],
+ chat_teams: %w[team_id],
+ ci_builds: %w[erased_by_id runner_id trigger_request_id user_id],
+ ci_pipelines: %w[user_id],
+ ci_runner_projects: %w[runner_id],
+ ci_trigger_requests: %w[commit_id],
+ cluster_providers_gcp: %w[gcp_project_id operation_id],
+ deploy_keys_projects: %w[deploy_key_id],
+ deployments: %w[deployable_id environment_id user_id],
+ emails: %w[user_id],
+ events: %w[target_id],
+ forked_project_links: %w[forked_from_project_id],
+ identities: %w[user_id],
+ issues: %w[last_edited_by_id],
+ keys: %w[user_id],
+ label_links: %w[target_id],
+ lfs_objects_projects: %w[lfs_object_id project_id],
+ members: %w[source_id created_by_id],
+ merge_requests: %w[last_edited_by_id],
+ namespaces: %w[owner_id parent_id],
+ notes: %w[author_id commit_id noteable_id updated_by_id resolved_by_id discussion_id],
+ notification_settings: %w[source_id],
+ oauth_access_grants: %w[resource_owner_id application_id],
+ oauth_access_tokens: %w[resource_owner_id application_id],
+ oauth_applications: %w[owner_id],
+ project_group_links: %w[group_id],
+ project_statistics: %w[namespace_id],
+ projects: %w[creator_id namespace_id ci_id],
+ redirect_routes: %w[source_id],
+ repository_languages: %w[programming_language_id],
+ routes: %w[source_id],
+ sent_notifications: %w[project_id noteable_id recipient_id commit_id in_reply_to_discussion_id],
+ snippets: %w[author_id],
+ spam_logs: %w[user_id],
+ subscriptions: %w[user_id subscribable_id],
+ taggings: %w[tag_id taggable_id tagger_id],
+ timelogs: %w[user_id],
+ todos: %w[target_id commit_id],
+ uploads: %w[model_id],
+ user_agent_details: %w[subject_id],
+ users: %w[color_scheme_id created_by_id theme_id],
+ users_star_projects: %w[user_id],
+ web_hooks: %w[service_id]
+ }.with_indifferent_access.freeze
+
+ context 'for table' do
+ ActiveRecord::Base.connection.tables.sort.each do |table|
+ describe table do
+ let(:indexes) { connection.indexes(table) }
+ let(:columns) { connection.columns(table) }
+ let(:foreign_keys) { connection.foreign_keys(table) }
+
+ context 'all foreign keys' do
+ # for index to be effective, the FK constraint has to be at first place
+ it 'are indexed' do
+ first_indexed_column = indexes.map(&:columns).map(&:first)
+ foreign_keys_columns = foreign_keys.map(&:column)
+
+ expect(first_indexed_column.uniq).to include(*foreign_keys_columns)
+ end
+ end
+
+ context 'columns ending with _id' do
+ let(:column_names) { columns.map(&:name) }
+ let(:column_names_with_id) { column_names.select { |column_name| column_name.ends_with?('_id') } }
+ let(:foreign_keys_columns) { foreign_keys.map(&:column) }
+ let(:ignored_columns) { ignored_fk_columns(table) }
+
+ it 'do have the foreign keys' do
+ expect(column_names_with_id - ignored_columns).to contain_exactly(*foreign_keys_columns)
+ end
+ end
+ end
+ end
+ end
+
+ private
+
+ def ignored_fk_columns(column)
+ IGNORED_FK_COLUMNS.fetch(column, [])
+ end
+end
diff --git a/spec/factories/board_group_recent_visit.rb b/spec/factories/board_group_recent_visit.rb
new file mode 100644
index 00000000000..97ad5d6d068
--- /dev/null
+++ b/spec/factories/board_group_recent_visit.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :board_group_recent_visit do
+ user
+ group
+ board
+ end
+end
diff --git a/spec/factories/board_project_recent_visit.rb b/spec/factories/board_project_recent_visit.rb
new file mode 100644
index 00000000000..49ae4d7b391
--- /dev/null
+++ b/spec/factories/board_project_recent_visit.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :board_project_recent_visit do
+ user
+ project
+ board
+ end
+end
diff --git a/spec/factories/broadcast_messages.rb b/spec/factories/broadcast_messages.rb
index 9a65e7f8a3f..1a2be5e9552 100644
--- a/spec/factories/broadcast_messages.rb
+++ b/spec/factories/broadcast_messages.rb
@@ -1,17 +1,17 @@
FactoryBot.define do
factory :broadcast_message do
message "MyText"
- starts_at 1.day.ago
- ends_at 1.day.from_now
+ starts_at { 1.day.ago }
+ ends_at { 1.day.from_now }
trait :expired do
- starts_at 5.days.ago
- ends_at 3.days.ago
+ starts_at { 5.days.ago }
+ ends_at { 3.days.ago }
end
trait :future do
- starts_at 5.days.from_now
- ends_at 6.days.from_now
+ starts_at { 5.days.from_now }
+ ends_at { 6.days.from_now }
end
end
end
diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb
index 9813190925b..07c1fc31152 100644
--- a/spec/factories/ci/builds.rb
+++ b/spec/factories/ci/builds.rb
@@ -27,6 +27,12 @@ FactoryBot.define do
pipeline factory: :ci_pipeline
+ trait :degenerated do
+ commands nil
+ options nil
+ yaml_variables nil
+ end
+
trait :started do
started_at 'Di 29. Okt 09:51:28 CET 2013'
end
@@ -70,6 +76,18 @@ FactoryBot.define do
status 'created'
end
+ trait :scheduled do
+ schedulable
+ status 'scheduled'
+ scheduled_at { 1.minute.since }
+ end
+
+ trait :expired_scheduled do
+ schedulable
+ status 'scheduled'
+ scheduled_at { 1.minute.ago }
+ end
+
trait :manual do
status 'manual'
self.when 'manual'
@@ -82,6 +100,30 @@ FactoryBot.define do
url: 'http://staging.example.com/$CI_JOB_NAME' }
end
+ trait :deploy_to_production do
+ environment 'production'
+
+ options environment: { name: 'production',
+ url: 'http://prd.example.com/$CI_JOB_NAME' }
+ end
+
+ trait :start_review_app do
+ environment 'review/$CI_COMMIT_REF_NAME'
+
+ options environment: { name: 'review/$CI_COMMIT_REF_NAME',
+ url: 'http://staging.example.com/$CI_JOB_NAME',
+ on_stop: 'stop_review_app' }
+ end
+
+ trait :stop_review_app do
+ name 'stop_review_app'
+ environment 'review/$CI_COMMIT_REF_NAME'
+
+ options environment: { name: 'review/$CI_COMMIT_REF_NAME',
+ url: 'http://staging.example.com/$CI_JOB_NAME',
+ action: 'stop' }
+ end
+
trait :allowed_to_fail do
allow_failure true
end
@@ -98,6 +140,15 @@ FactoryBot.define do
success
end
+ trait :schedulable do
+ self.when 'delayed'
+ options start_in: '1 minute'
+ end
+
+ trait :actionable do
+ self.when 'manual'
+ end
+
trait :retried do
retried true
end
@@ -159,12 +210,12 @@ FactoryBot.define do
end
trait :erased do
- erased_at Time.now
+ erased_at { Time.now }
erased_by factory: :user
end
trait :queued do
- queued_at Time.now
+ queued_at { Time.now }
runner factory: :ci_runner
end
@@ -194,7 +245,7 @@ FactoryBot.define do
end
trait :expired do
- artifacts_expire_at 1.minute.ago
+ artifacts_expire_at { 1.minute.ago }
end
trait :with_commit do
@@ -257,7 +308,7 @@ FactoryBot.define do
trait :with_runner_session do
after(:build) do |build|
- build.build_runner_session(url: 'ws://localhost')
+ build.build_runner_session(url: 'https://localhost')
end
end
end
diff --git a/spec/factories/ci/job_artifacts.rb b/spec/factories/ci/job_artifacts.rb
index f028803ca74..2c76c22ba69 100644
--- a/spec/factories/ci/job_artifacts.rb
+++ b/spec/factories/ci/job_artifacts.rb
@@ -14,6 +14,33 @@ FactoryBot.define do
artifact.project ||= artifact.job.project
end
+ trait :raw do
+ file_format :raw
+
+ after(:build) do |artifact, _|
+ artifact.file = fixture_file_upload(
+ Rails.root.join('spec/fixtures/trace/sample_trace'), 'text/plain')
+ end
+ end
+
+ trait :zip do
+ file_format :zip
+
+ after(:build) do |artifact, _|
+ artifact.file = fixture_file_upload(
+ Rails.root.join('spec/fixtures/ci_build_artifacts.zip'), 'application/zip')
+ end
+ end
+
+ trait :gzip do
+ file_format :gzip
+
+ after(:build) do |artifact, _|
+ artifact.file = fixture_file_upload(
+ Rails.root.join('spec/fixtures/ci_build_artifacts_metadata.gz'), 'application/x-gzip')
+ end
+ end
+
trait :archive do
file_type :archive
file_format :zip
@@ -90,6 +117,16 @@ FactoryBot.define do
end
end
+ trait :codequality do
+ file_type :codequality
+ file_format :raw
+
+ after(:build) do |artifact, evaluator|
+ artifact.file = fixture_file_upload(
+ Rails.root.join('spec/fixtures/codequality/codequality.json'), 'application/json')
+ end
+ end
+
trait :correct_checksum do
after(:build) do |artifact, evaluator|
artifact.file_sha256 = Digest::SHA256.file(artifact.file.path).hexdigest
diff --git a/spec/factories/ci/pipelines.rb b/spec/factories/ci/pipelines.rb
index 9fef424e425..8a44ce52849 100644
--- a/spec/factories/ci/pipelines.rb
+++ b/spec/factories/ci/pipelines.rb
@@ -54,6 +54,10 @@ FactoryBot.define do
status :manual
end
+ trait :scheduled do
+ status :scheduled
+ end
+
trait :success do
status :success
end
diff --git a/spec/factories/ci/runners.rb b/spec/factories/ci/runners.rb
index 347e4f433e2..24e70913b87 100644
--- a/spec/factories/ci/runners.rb
+++ b/spec/factories/ci/runners.rb
@@ -9,7 +9,7 @@ FactoryBot.define do
runner_type :instance_type
trait :online do
- contacted_at Time.now
+ contacted_at { Time.now }
end
trait :instance do
@@ -47,5 +47,15 @@ FactoryBot.define do
trait :ref_protected do
access_level :ref_protected
end
+
+ trait :tagged_only do
+ run_untagged false
+
+ tag_list %w(tag1 tag2)
+ end
+
+ trait :locked do
+ locked true
+ end
end
end
diff --git a/spec/factories/clusters/applications/helm.rb b/spec/factories/clusters/applications/helm.rb
index c13b0249d94..fe56ac5b71d 100644
--- a/spec/factories/clusters/applications/helm.rb
+++ b/spec/factories/clusters/applications/helm.rb
@@ -22,25 +22,49 @@ FactoryBot.define do
status 3
end
+ trait :updating do
+ status 4
+ end
+
+ trait :updated do
+ status 5
+ end
+
trait :errored do
status(-1)
status_reason 'something went wrong'
end
+ trait :update_errored do
+ status(6)
+ status_reason 'something went wrong'
+ end
+
trait :timeouted do
installing
- updated_at ClusterWaitForAppInstallationWorker::TIMEOUT.ago
+ updated_at { ClusterWaitForAppInstallationWorker::TIMEOUT.ago }
end
factory :clusters_applications_ingress, class: Clusters::Applications::Ingress do
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
end
+ factory :clusters_applications_cert_managers, class: Clusters::Applications::CertManager do
+ email 'admin@example.com'
+ cluster factory: %i(cluster with_installed_helm provided_by_gcp)
+ end
+
factory :clusters_applications_prometheus, class: Clusters::Applications::Prometheus do
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
end
factory :clusters_applications_runner, class: Clusters::Applications::Runner do
+ runner factory: %i(ci_runner)
+ cluster factory: %i(cluster with_installed_helm provided_by_gcp)
+ end
+
+ factory :clusters_applications_knative, class: Clusters::Applications::Knative do
+ hostname 'example.com'
cluster factory: %i(cluster with_installed_helm provided_by_gcp)
end
diff --git a/spec/factories/clusters/clusters.rb b/spec/factories/clusters/clusters.rb
index bbeba8ce8b9..c9f5d0a813e 100644
--- a/spec/factories/clusters/clusters.rb
+++ b/spec/factories/clusters/clusters.rb
@@ -2,13 +2,28 @@ FactoryBot.define do
factory :cluster, class: Clusters::Cluster do
user
name 'test-cluster'
+ cluster_type :project_type
+
+ trait :instance do
+ cluster_type { Clusters::Cluster.cluster_types[:instance_type] }
+ end
trait :project do
+ cluster_type { Clusters::Cluster.cluster_types[:project_type] }
+
before(:create) do |cluster, evaluator|
cluster.projects << create(:project, :repository)
end
end
+ trait :group do
+ cluster_type { Clusters::Cluster.cluster_types[:group_type] }
+
+ before(:create) do |cluster, evalutor|
+ cluster.groups << create(:group)
+ end
+ end
+
trait :provided_by_user do
provider_type :user
platform_type :kubernetes
diff --git a/spec/factories/clusters/kubernetes_namespaces.rb b/spec/factories/clusters/kubernetes_namespaces.rb
new file mode 100644
index 00000000000..3b50a57433f
--- /dev/null
+++ b/spec/factories/clusters/kubernetes_namespaces.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :cluster_kubernetes_namespace, class: Clusters::KubernetesNamespace do
+ association :cluster, :project, :provided_by_gcp
+
+ after(:build) do |kubernetes_namespace|
+ if kubernetes_namespace.cluster.project_type?
+ cluster_project = kubernetes_namespace.cluster.cluster_project
+
+ kubernetes_namespace.project = cluster_project.project
+ kubernetes_namespace.cluster_project = cluster_project
+ end
+ end
+
+ trait :with_token do
+ service_account_token { FFaker::Lorem.characters(10) }
+ end
+ end
+end
diff --git a/spec/factories/clusters/platforms/kubernetes.rb b/spec/factories/clusters/platforms/kubernetes.rb
index 36ac2372204..8169c457ab7 100644
--- a/spec/factories/clusters/platforms/kubernetes.rb
+++ b/spec/factories/clusters/platforms/kubernetes.rb
@@ -3,15 +3,14 @@ FactoryBot.define do
cluster
namespace nil
api_url 'https://kubernetes.example.com'
- token 'a' * 40
+ token { 'a' * 40 }
trait :configured do
api_url 'https://kubernetes.example.com'
- token 'a' * 40
username 'xxxxxx'
password 'xxxxxx'
- after(:create) do |platform_kubernetes, evaluator|
+ before(:create) do |platform_kubernetes, evaluator|
pem_file = File.expand_path(Rails.root.join('spec/fixtures/clusters/sample_cert.pem'))
platform_kubernetes.ca_cert = File.read(pem_file)
end
diff --git a/spec/factories/clusters/projects.rb b/spec/factories/clusters/projects.rb
new file mode 100644
index 00000000000..6cda77c6f85
--- /dev/null
+++ b/spec/factories/clusters/projects.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :cluster_project, class: Clusters::Project do
+ cluster
+ project
+ end
+end
diff --git a/spec/factories/commit_statuses.rb b/spec/factories/commit_statuses.rb
index 53368c64e10..381bf07f6a0 100644
--- a/spec/factories/commit_statuses.rb
+++ b/spec/factories/commit_statuses.rb
@@ -41,6 +41,10 @@ FactoryBot.define do
status 'manual'
end
+ trait :scheduled do
+ status 'scheduled'
+ end
+
after(:build) do |build, evaluator|
build.project = build.pipeline.project
end
diff --git a/spec/factories/deployments.rb b/spec/factories/deployments.rb
index cac56695319..011c98599a3 100644
--- a/spec/factories/deployments.rb
+++ b/spec/factories/deployments.rb
@@ -16,5 +16,36 @@ FactoryBot.define do
allow(deployment.project.repository).to receive(:create_ref)
end
end
+
+ trait :review_app do
+ sha { TestEnv::BRANCH_SHA['pages-deploy'] }
+ ref 'pages-deploy'
+ end
+
+ trait :running do
+ status :running
+ end
+
+ trait :success do
+ status :success
+ finished_at { Time.now }
+ end
+
+ trait :failed do
+ status :failed
+ finished_at { Time.now }
+ end
+
+ trait :canceled do
+ status :canceled
+ finished_at { Time.now }
+ end
+
+ # This trait hooks the state maechine's events
+ trait :succeed do
+ after(:create) do |deployment, evaluator|
+ deployment.succeed!
+ end
+ end
end
end
diff --git a/spec/factories/emails.rb b/spec/factories/emails.rb
index d23ddf9d79b..feacd5ccf15 100644
--- a/spec/factories/emails.rb
+++ b/spec/factories/emails.rb
@@ -3,7 +3,7 @@ FactoryBot.define do
user
email { generate(:email_alias) }
- trait(:confirmed) { confirmed_at Time.now }
+ trait(:confirmed) { confirmed_at { Time.now } }
trait(:skip_validate) { to_create {|instance| instance.save(validate: false) } }
end
end
diff --git a/spec/factories/environments.rb b/spec/factories/environments.rb
index b5db57d5148..9d9e3d693b8 100644
--- a/spec/factories/environments.rb
+++ b/spec/factories/environments.rb
@@ -22,6 +22,7 @@ FactoryBot.define do
pipeline: pipeline)
deployment = create(:deployment,
+ :success,
environment: environment,
project: environment.project,
deployable: deployable,
diff --git a/spec/factories/events.rb b/spec/factories/events.rb
index 5798b81ecad..bf8411b1894 100644
--- a/spec/factories/events.rb
+++ b/spec/factories/events.rb
@@ -24,7 +24,7 @@ FactoryBot.define do
factory :push_event, class: PushEvent do
project factory: :project_empty_repo
- author factory: :user
+ author(factory: :user) { project.creator }
action Event::PUSHED
end
diff --git a/spec/factories/forked_project_links.rb b/spec/factories/forked_project_links.rb
deleted file mode 100644
index bc59fea81ec..00000000000
--- a/spec/factories/forked_project_links.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-FactoryBot.define do
- factory :forked_project_link do
- association :forked_to_project, factory: [:project, :repository]
- association :forked_from_project, factory: [:project, :repository]
-
- after(:create) do |link|
- link.forked_from_project.reload
- link.forked_to_project.reload
- end
-
- trait :forked_to_empty_project do
- association :forked_to_project, factory: [:project, :repository]
- end
- end
-end
diff --git a/spec/factories/gpg_keys.rb b/spec/factories/gpg_keys.rb
index 51b8ddc9934..3c0f43cc1b6 100644
--- a/spec/factories/gpg_keys.rb
+++ b/spec/factories/gpg_keys.rb
@@ -2,11 +2,11 @@ require_relative '../support/helpers/gpg_helpers'
FactoryBot.define do
factory :gpg_key do
- key GpgHelpers::User1.public_key
+ key { GpgHelpers::User1.public_key }
user
factory :gpg_key_with_subkeys do
- key GpgHelpers::User1.public_key_with_extra_signing_key
+ key { GpgHelpers::User1.public_key_with_extra_signing_key }
end
end
end
diff --git a/spec/factories/group_members.rb b/spec/factories/group_members.rb
index 47036560b9d..12be63e5d92 100644
--- a/spec/factories/group_members.rb
+++ b/spec/factories/group_members.rb
@@ -9,7 +9,7 @@ FactoryBot.define do
trait(:developer) { access_level GroupMember::DEVELOPER }
trait(:maintainer) { access_level GroupMember::MAINTAINER }
trait(:owner) { access_level GroupMember::OWNER }
- trait(:access_request) { requested_at Time.now }
+ trait(:access_request) { requested_at { Time.now } }
trait(:invited) do
user_id nil
diff --git a/spec/factories/import_state.rb b/spec/factories/import_state.rb
index 15d0a9d466a..d6de26dccbc 100644
--- a/spec/factories/import_state.rb
+++ b/spec/factories/import_state.rb
@@ -5,6 +5,7 @@ FactoryBot.define do
transient do
import_url { generate(:url) }
+ import_type nil
end
trait :repository do
@@ -32,7 +33,11 @@ FactoryBot.define do
end
after(:create) do |import_state, evaluator|
- import_state.project.update_columns(import_url: evaluator.import_url)
+ columns = {}
+ columns[:import_url] = evaluator.import_url unless evaluator.import_url.blank?
+ columns[:import_type] = evaluator.import_type unless evaluator.import_type.blank?
+
+ import_state.project.update_columns(columns)
end
end
end
diff --git a/spec/factories/issues.rb b/spec/factories/issues.rb
index 4d4f74e101e..ab27fee33dc 100644
--- a/spec/factories/issues.rb
+++ b/spec/factories/issues.rb
@@ -13,6 +13,10 @@ FactoryBot.define do
state :opened
end
+ trait :locked do
+ discussion_locked true
+ end
+
trait :closed do
state :closed
closed_at { Time.now }
diff --git a/spec/factories/merge_request_diff_files.rb b/spec/factories/merge_request_diff_files.rb
new file mode 100644
index 00000000000..469a7a0ac8d
--- /dev/null
+++ b/spec/factories/merge_request_diff_files.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :merge_request_diff_file do
+ association :merge_request_diff
+
+ relative_order 0
+ new_file true
+ renamed_file false
+ deleted_file false
+ too_large false
+ a_mode 0
+ b_mode 100644
+ new_path 'foo'
+ old_path 'foo'
+ diff ''
+ binary false
+
+ trait :new_file do
+ relative_order 0
+ new_file true
+ renamed_file false
+ deleted_file false
+ too_large false
+ a_mode 0
+ b_mode 100644
+ new_path 'foo'
+ old_path 'foo'
+ diff ''
+ binary false
+ end
+
+ trait :renamed_file do
+ relative_order 662
+ new_file false
+ renamed_file true
+ deleted_file false
+ too_large false
+ a_mode 100644
+ b_mode 100644
+ new_path 'bar'
+ old_path 'baz'
+ diff ''
+ binary false
+ end
+ end
+end
diff --git a/spec/factories/merge_request_diffs.rb b/spec/factories/merge_request_diffs.rb
new file mode 100644
index 00000000000..e7b51189538
--- /dev/null
+++ b/spec/factories/merge_request_diffs.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :merge_request_diff do
+ association :merge_request
+ state :collected
+ commits_count 1
+
+ base_commit_sha { Digest::SHA1.hexdigest(SecureRandom.hex) }
+ head_commit_sha { Digest::SHA1.hexdigest(SecureRandom.hex) }
+ start_commit_sha { Digest::SHA1.hexdigest(SecureRandom.hex) }
+ end
+end
diff --git a/spec/factories/merge_requests.rb b/spec/factories/merge_requests.rb
index b8b089b069b..2392bfc4a53 100644
--- a/spec/factories/merge_requests.rb
+++ b/spec/factories/merge_requests.rb
@@ -80,7 +80,7 @@ FactoryBot.define do
trait :merge_when_pipeline_succeeds do
merge_when_pipeline_succeeds true
- merge_user author
+ merge_user { author }
end
trait :remove_source_branch do
@@ -101,6 +101,20 @@ FactoryBot.define do
end
end
+ trait :deployed_review_app do
+ target_branch 'pages-deploy-target'
+
+ transient do
+ deployment { create(:deployment, :review_app) }
+ end
+
+ after(:build) do |merge_request, evaluator|
+ merge_request.source_branch = evaluator.deployment.ref
+ merge_request.source_project = evaluator.deployment.project
+ merge_request.target_project = evaluator.deployment.project
+ end
+ end
+
after(:build) do |merge_request|
target_project = merge_request.target_project
source_project = merge_request.source_project
diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb
index 6844ed8aa4a..2d1f48bf249 100644
--- a/spec/factories/notes.rb
+++ b/spec/factories/notes.rb
@@ -90,7 +90,7 @@ FactoryBot.define do
noteable nil
noteable_type 'Commit'
noteable_id nil
- commit_id RepoHelpers.sample_commit.id
+ commit_id { RepoHelpers.sample_commit.id }
end
trait :legacy_diff_note do
diff --git a/spec/factories/oauth_access_grants.rb b/spec/factories/oauth_access_grants.rb
index 9e6af24c4eb..02c51cd9899 100644
--- a/spec/factories/oauth_access_grants.rb
+++ b/spec/factories/oauth_access_grants.rb
@@ -3,7 +3,7 @@ FactoryBot.define do
resource_owner_id { create(:user).id }
application
token { Doorkeeper::OAuth::Helpers::UniqueToken.generate }
- expires_in 2.hours
+ expires_in { 2.hours }
redirect_uri { application.redirect_uri }
scopes { application.scopes }
diff --git a/spec/factories/pool_repositories.rb b/spec/factories/pool_repositories.rb
new file mode 100644
index 00000000000..2ed0844ed47
--- /dev/null
+++ b/spec/factories/pool_repositories.rb
@@ -0,0 +1,5 @@
+FactoryBot.define do
+ factory :pool_repository do
+ shard
+ end
+end
diff --git a/spec/factories/project_auto_devops.rb b/spec/factories/project_auto_devops.rb
index b77f702f9e1..75ac7cc7687 100644
--- a/spec/factories/project_auto_devops.rb
+++ b/spec/factories/project_auto_devops.rb
@@ -5,8 +5,16 @@ FactoryBot.define do
domain "example.com"
deploy_strategy :continuous
- trait :manual do
- deploy_strategy :manual
+ trait :continuous_deployment do
+ deploy_strategy ProjectAutoDevops.deploy_strategies[:continuous] # rubocop:disable FactoryBot/DynamicAttributeDefinedStatically
+ end
+
+ trait :manual_deployment do
+ deploy_strategy ProjectAutoDevops.deploy_strategies[:manual] # rubocop:disable FactoryBot/DynamicAttributeDefinedStatically
+ end
+
+ trait :timed_incremental_deployment do
+ deploy_strategy ProjectAutoDevops.deploy_strategies[:timed_incremental] # rubocop:disable FactoryBot/DynamicAttributeDefinedStatically
end
trait :disabled do
diff --git a/spec/factories/project_members.rb b/spec/factories/project_members.rb
index 22a8085ea45..c72e0487895 100644
--- a/spec/factories/project_members.rb
+++ b/spec/factories/project_members.rb
@@ -8,7 +8,7 @@ FactoryBot.define do
trait(:reporter) { access_level ProjectMember::REPORTER }
trait(:developer) { access_level ProjectMember::DEVELOPER }
trait(:maintainer) { access_level ProjectMember::MAINTAINER }
- trait(:access_request) { requested_at Time.now }
+ trait(:access_request) { requested_at { Time.now } }
trait(:invited) do
user_id nil
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 80801eb1082..1906c06a211 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -1,6 +1,8 @@
require_relative '../support/helpers/test_env'
FactoryBot.define do
+ PAGES_ACCESS_LEVEL_SCHEMA_VERSION = 20180423204600
+
# Project without repository
#
# Project does not have bare repository.
@@ -23,10 +25,13 @@ FactoryBot.define do
issues_access_level ProjectFeature::ENABLED
merge_requests_access_level ProjectFeature::ENABLED
repository_access_level ProjectFeature::ENABLED
+ pages_access_level ProjectFeature::ENABLED
# we can't assign the delegated `#ci_cd_settings` attributes directly, as the
# `#ci_cd_settings` relation needs to be created first
group_runners_enabled nil
+ import_status nil
+ import_jid nil
end
after(:create) do |project, evaluator|
@@ -34,13 +39,20 @@ FactoryBot.define do
builds_access_level = [evaluator.builds_access_level, evaluator.repository_access_level].min
merge_requests_access_level = [evaluator.merge_requests_access_level, evaluator.repository_access_level].min
- project.project_feature.update(
+ hash = {
wiki_access_level: evaluator.wiki_access_level,
builds_access_level: builds_access_level,
snippets_access_level: evaluator.snippets_access_level,
issues_access_level: evaluator.issues_access_level,
merge_requests_access_level: merge_requests_access_level,
- repository_access_level: evaluator.repository_access_level)
+ repository_access_level: evaluator.repository_access_level
+ }
+
+ if ActiveRecord::Migrator.current_version >= PAGES_ACCESS_LEVEL_SCHEMA_VERSION
+ hash.store("pages_access_level", evaluator.pages_access_level)
+ end
+
+ project.project_feature.update(hash)
# Normally the class Projects::CreateService is used for creating
# projects, and this class takes care of making sure the owner and current
@@ -54,6 +66,13 @@ FactoryBot.define do
# assign the delegated `#ci_cd_settings` attributes after create
project.reload.group_runners_enabled = evaluator.group_runners_enabled unless evaluator.group_runners_enabled.nil?
+
+ if evaluator.import_status
+ import_state = project.import_state || project.build_import_state
+ import_state.status = evaluator.import_status
+ import_state.jid = evaluator.import_jid
+ import_state.save
+ end
end
trait :public do
@@ -244,6 +263,10 @@ FactoryBot.define do
trait(:repository_enabled) { repository_access_level ProjectFeature::ENABLED }
trait(:repository_disabled) { repository_access_level ProjectFeature::DISABLED }
trait(:repository_private) { repository_access_level ProjectFeature::PRIVATE }
+ trait(:pages_public) { pages_access_level ProjectFeature::PUBLIC }
+ trait(:pages_enabled) { pages_access_level ProjectFeature::ENABLED }
+ trait(:pages_disabled) { pages_access_level ProjectFeature::DISABLED }
+ trait(:pages_private) { pages_access_level ProjectFeature::PRIVATE }
trait :auto_devops do
association :auto_devops, factory: :project_auto_devops
diff --git a/spec/factories/services.rb b/spec/factories/services.rb
index 0d4fd49bf3a..5be56a49903 100644
--- a/spec/factories/services.rb
+++ b/spec/factories/services.rb
@@ -46,6 +46,17 @@ FactoryBot.define do
)
end
+ factory :jira_cloud_service, class: JiraService do
+ project
+ active true
+ properties(
+ url: 'https://mysite.atlassian.net',
+ username: 'jira_user',
+ password: 'my-secret-password',
+ project_key: 'jira-key'
+ )
+ end
+
factory :hipchat_service do
project
type 'HipchatService'
diff --git a/spec/factories/shards.rb b/spec/factories/shards.rb
new file mode 100644
index 00000000000..c095fa5f0a0
--- /dev/null
+++ b/spec/factories/shards.rb
@@ -0,0 +1,5 @@
+FactoryBot.define do
+ factory :shard do
+ name "default"
+ end
+end
diff --git a/spec/factories/site_statistics.rb b/spec/factories/site_statistics.rb
deleted file mode 100644
index dd8c795515a..00000000000
--- a/spec/factories/site_statistics.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-FactoryBot.define do
- factory :site_statistics, class: 'SiteStatistic' do
- id 1
- repositories_count 999
- wikis_count 555
- end
-end
diff --git a/spec/factories/todos.rb b/spec/factories/todos.rb
index 14486c80341..ed3d87eb76b 100644
--- a/spec/factories/todos.rb
+++ b/spec/factories/todos.rb
@@ -49,7 +49,7 @@ FactoryBot.define do
author
user
action { Todo::ASSIGNED }
- commit_id RepoHelpers.sample_commit.id
+ commit_id { RepoHelpers.sample_commit.id }
target_type "Commit"
end
end
diff --git a/spec/factories/uploads.rb b/spec/factories/uploads.rb
index 81c485fba1a..7256f785e1f 100644
--- a/spec/factories/uploads.rb
+++ b/spec/factories/uploads.rb
@@ -1,7 +1,7 @@
FactoryBot.define do
factory :upload do
model { build(:project) }
- size 100.kilobytes
+ size { 100.kilobytes }
uploader "AvatarUploader"
mount_point :avatar
secret nil
@@ -19,13 +19,13 @@ FactoryBot.define do
uploader "PersonalFileUploader"
path { File.join(secret, filename) }
model { build(:personal_snippet) }
- secret SecureRandom.hex
+ secret { SecureRandom.hex }
end
trait :issuable_upload do
uploader "FileUploader"
path { File.join(secret, filename) }
- secret SecureRandom.hex
+ secret { SecureRandom.hex }
end
trait :with_file do
@@ -43,14 +43,14 @@ FactoryBot.define do
model { build(:group) }
path { File.join(secret, filename) }
uploader "NamespaceFileUploader"
- secret SecureRandom.hex
+ secret { SecureRandom.hex }
end
trait :favicon_upload do
model { build(:appearance) }
path { File.join(secret, filename) }
uploader "FaviconUploader"
- secret SecureRandom.hex
+ secret { SecureRandom.hex }
end
trait :attachment_upload do
diff --git a/spec/factories/user_preferences.rb b/spec/factories/user_preferences.rb
new file mode 100644
index 00000000000..19059a93625
--- /dev/null
+++ b/spec/factories/user_preferences.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :user_preference do
+ user
+
+ trait :only_comments do
+ issue_notes_filter { UserPreference::NOTES_FILTERS[:only_comments] }
+ merge_request_notes_filter { UserPreference::NOTE_FILTERS[:only_comments] }
+ end
+ end
+end
diff --git a/spec/fast_spec_helper.rb b/spec/fast_spec_helper.rb
index 134eb25e4b1..0b5ab16ad71 100644
--- a/spec/fast_spec_helper.rb
+++ b/spec/fast_spec_helper.rb
@@ -8,3 +8,5 @@ require_relative 'support/rspec'
require 'active_support/all'
ActiveSupport::Dependencies.autoload_paths << 'lib'
+ActiveSupport::Dependencies.autoload_paths << 'ee/lib'
+ActiveSupport::XmlMini.backend = 'Nokogiri'
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index 96dfde2e08c..735ca60f7da 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -53,13 +53,33 @@ describe 'Admin Groups' do
expect_selected_visibility(internal)
end
- it 'when entered in group path, it auto filled the group name', :js do
+ it 'when entered in group name, it auto filled the group path', :js do
visit admin_groups_path
click_link "New group"
- group_path = 'gitlab'
+ group_name = 'gitlab'
+ fill_in 'group_name', with: group_name
+ path_field = find('input#group_path')
+ expect(path_field.value).to eq group_name
+ end
+
+ it 'auto populates the group path with the group name', :js do
+ visit admin_groups_path
+ click_link "New group"
+ group_name = 'my gitlab project'
+ fill_in 'group_name', with: group_name
+ path_field = find('input#group_path')
+ expect(path_field.value).to eq 'my-gitlab-project'
+ end
+
+ it 'when entering in group path, group name does not change anymore', :js do
+ visit admin_groups_path
+ click_link "New group"
+ group_path = 'my-gitlab-project'
+ group_name = 'My modified gitlab project'
fill_in 'group_path', with: group_path
- name_field = find('input#group_name')
- expect(name_field.value).to eq group_path
+ fill_in 'group_name', with: group_name
+ path_field = find('input#group_path')
+ expect(path_field.value).to eq 'my-gitlab-project'
end
end
diff --git a/spec/features/admin/admin_health_check_spec.rb b/spec/features/admin/admin_health_check_spec.rb
index aaa3e8dc821..790051dd933 100644
--- a/spec/features/admin/admin_health_check_spec.rb
+++ b/spec/features/admin/admin_health_check_spec.rb
@@ -2,10 +2,11 @@ require 'spec_helper'
describe "Admin Health Check", :feature do
include StubENV
+ set(:admin) { create(:admin) }
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
- sign_in(create(:admin))
+ sign_in(admin)
end
describe '#show' do
@@ -56,27 +57,4 @@ describe "Admin Health Check", :feature do
expect(page).to have_content('The server is on fire')
end
end
-
- context 'with repository storage failures', :broken_storage do
- before do
- visit admin_health_check_path
- end
-
- it 'shows storage failure information' do
- hostname = Gitlab::Environment.hostname
- maximum_failures = Gitlab::CurrentSettings.current_application_settings
- .circuitbreaker_failure_count_threshold
- number_of_failures = maximum_failures + 1
-
- expect(page).to have_content("broken: #{number_of_failures} failed storage access attempts:")
- expect(page).to have_content("#{hostname}: #{number_of_failures} of #{maximum_failures} failures.")
- end
-
- it 'allows resetting storage failures' do
- click_button 'Reset git storage health information'
-
- expect(page).to have_content('Git storage health information has been reset')
- expect(page).not_to have_content('failed storage access attempt')
- end
- end
end
diff --git a/spec/features/admin/admin_manage_applications_spec.rb b/spec/features/admin/admin_manage_applications_spec.rb
index f979d2f6090..a4904272706 100644
--- a/spec/features/admin/admin_manage_applications_spec.rb
+++ b/spec/features/admin/admin_manage_applications_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe 'admin manage applications' do
check :doorkeeper_application_trusted
click_on 'Submit'
expect(page).to have_content('Application: test')
- expect(page).to have_content('Application Id')
+ expect(page).to have_content('Application ID')
expect(page).to have_content('Secret')
expect(page).to have_content('Trusted Y')
@@ -28,7 +28,7 @@ RSpec.describe 'admin manage applications' do
click_on 'Submit'
expect(page).to have_content('test_changed')
- expect(page).to have_content('Application Id')
+ expect(page).to have_content('Application ID')
expect(page).to have_content('Secret')
expect(page).to have_content('Trusted N')
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index a6ab6a5696a..ed9c0ea9ac0 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -73,24 +73,72 @@ describe "Admin Runners" do
expect(page).to have_text 'No runners found'
end
+
+ it 'shows correct runner when status is selected and search term is entered' do
+ create(:ci_runner, description: 'runner-a-1', active: true)
+ create(:ci_runner, description: 'runner-a-2', active: false)
+ create(:ci_runner, description: 'runner-b-1', active: true)
+
+ visit admin_runners_path
+
+ input_filtered_search_keys('status:active')
+ expect(page).to have_content 'runner-a-1'
+ expect(page).to have_content 'runner-b-1'
+ expect(page).not_to have_content 'runner-a-2'
+
+ input_filtered_search_keys('status:active runner-a')
+ expect(page).to have_content 'runner-a-1'
+ expect(page).not_to have_content 'runner-b-1'
+ expect(page).not_to have_content 'runner-a-2'
+ end
end
- it 'shows correct runner when status is selected and search term is entered', :js do
- create(:ci_runner, description: 'runner-a-1', active: true)
- create(:ci_runner, description: 'runner-a-2', active: false)
- create(:ci_runner, description: 'runner-b-1', active: true)
+ describe 'filter by type', :js do
+ it 'shows correct runner when type matches' do
+ create :ci_runner, :project, description: 'runner-project'
+ create :ci_runner, :group, description: 'runner-group'
- visit admin_runners_path
+ visit admin_runners_path
+
+ expect(page).to have_content 'runner-project'
+ expect(page).to have_content 'runner-group'
- input_filtered_search_keys('status:active')
- expect(page).to have_content 'runner-a-1'
- expect(page).to have_content 'runner-b-1'
- expect(page).not_to have_content 'runner-a-2'
+ input_filtered_search_keys('type:project_type')
+ expect(page).to have_content 'runner-project'
+ expect(page).not_to have_content 'runner-group'
+ end
+
+ it 'shows no runner when type does not match' do
+ create :ci_runner, :project, description: 'runner-project'
+ create :ci_runner, :group, description: 'runner-group'
- input_filtered_search_keys('status:active runner-a')
- expect(page).to have_content 'runner-a-1'
- expect(page).not_to have_content 'runner-b-1'
- expect(page).not_to have_content 'runner-a-2'
+ visit admin_runners_path
+
+ input_filtered_search_keys('type:instance_type')
+
+ expect(page).not_to have_content 'runner-project'
+ expect(page).not_to have_content 'runner-group'
+
+ expect(page).to have_text 'No runners found'
+ end
+
+ it 'shows correct runner when type is selected and search term is entered' do
+ create :ci_runner, :project, description: 'runner-a-1'
+ create :ci_runner, :instance, description: 'runner-a-2'
+ create :ci_runner, :project, description: 'runner-b-1'
+
+ visit admin_runners_path
+
+ input_filtered_search_keys('type:project_type')
+ expect(page).to have_content 'runner-a-1'
+ expect(page).to have_content 'runner-b-1'
+ expect(page).not_to have_content 'runner-a-2'
+
+ input_filtered_search_keys('type:project_type runner-a')
+ expect(page).to have_content 'runner-a-1'
+ expect(page).not_to have_content 'runner-b-1'
+ expect(page).not_to have_content 'runner-a-2'
+ end
end
it 'sorts by last contact date', :js do
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 3fb818af8f0..0a69a26eb3e 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -368,16 +368,6 @@ describe 'Admin updates settings' do
expect(Gitlab::CurrentSettings.pages_domain_verification_enabled?).to be_truthy
expect(page).to have_content "Application settings saved successfully"
end
-
- it 'Change Background jobs settings' do
- page.within('.as-background') do
- fill_in 'Throttling Factor', with: 1
- click_button 'Save changes'
- end
-
- expect(Gitlab::CurrentSettings.sidekiq_throttling_factor).to eq(1)
- expect(page).to have_content "Application settings saved successfully"
- end
end
def check_all_events
diff --git a/spec/features/admin/admin_users_impersonation_tokens_spec.rb b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
index e16eae219a4..c7860bebb06 100644
--- a/spec/features/admin/admin_users_impersonation_tokens_spec.rb
+++ b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
@@ -12,6 +12,10 @@ describe 'Admin > Users > Impersonation Tokens', :js do
find(".settings-message")
end
+ def created_impersonation_token
+ find("#created-personal-access-token").value
+ end
+
before do
sign_in(admin)
end
@@ -39,6 +43,7 @@ describe 'Admin > Users > Impersonation Tokens', :js do
expect(active_impersonation_tokens).to have_text('api')
expect(active_impersonation_tokens).to have_text('read_user')
expect(PersonalAccessTokensFinder.new(impersonation: true).execute.count).to equal(1)
+ expect(created_impersonation_token).not_to be_empty
end
end
diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb
index d32f33ca1e2..d5516b334b9 100644
--- a/spec/features/admin/admin_users_spec.rb
+++ b/spec/features/admin/admin_users_spec.rb
@@ -130,7 +130,7 @@ describe "Admin::Users" do
context 'with regex to match internal user email address set', :js do
before do
stub_application_setting(user_default_external: true)
- stub_application_setting(user_default_internal_regex: '.internal@')
+ stub_application_setting(user_default_internal_regex: '\.internal@')
visit new_admin_user_path
end
@@ -169,6 +169,22 @@ describe "Admin::Users" do
expects_warning_to_be_hidden
end
+
+ it 'creates an internal user' do
+ user_name = 'tester1'
+ fill_in 'user_email', with: 'test.internal@domain.ch'
+ fill_in 'user_name', with: 'tester1 name'
+ fill_in 'user_username', with: user_name
+
+ expects_external_to_be_unchecked
+ expects_warning_to_be_shown
+
+ click_button 'Create user'
+
+ new_user = User.find_by(username: user_name)
+
+ expect(new_user.external).to be_falsy
+ end
end
end
end
@@ -189,75 +205,118 @@ describe "Admin::Users" do
describe 'Impersonation' do
let(:another_user) { create(:user) }
- before do
- visit admin_user_path(another_user)
- end
-
context 'before impersonating' do
- it 'shows impersonate button for other users' do
- expect(page).to have_content('Impersonate')
+ subject { visit admin_user_path(user_to_visit) }
+
+ let(:user_to_visit) { another_user }
+
+ context 'for other users' do
+ it 'shows impersonate button for other users' do
+ subject
+
+ expect(page).to have_content('Impersonate')
+ end
end
- it 'does not show impersonate button for admin itself' do
- visit admin_user_path(current_user)
+ context 'for admin itself' do
+ let(:user_to_visit) { current_user }
+
+ it 'does not show impersonate button for admin itself' do
+ subject
- expect(page).not_to have_content('Impersonate')
+ expect(page).not_to have_content('Impersonate')
+ end
end
- it 'does not show impersonate button for blocked user' do
- another_user.block
+ context 'for blocked user' do
+ before do
+ another_user.block
+ end
- visit admin_user_path(another_user)
+ it 'does not show impersonate button for blocked user' do
+ subject
+
+ expect(page).not_to have_content('Impersonate')
+ end
+ end
- expect(page).not_to have_content('Impersonate')
+ context 'when impersonation is disabled' do
+ before do
+ stub_config_setting(impersonation_enabled: false)
+ end
- another_user.activate
+ it 'does not show impersonate button' do
+ subject
+
+ expect(page).not_to have_content('Impersonate')
+ end
end
end
context 'when impersonating' do
+ subject { click_link 'Impersonate' }
+
before do
- click_link 'Impersonate'
+ visit admin_user_path(another_user)
end
it 'logs in as the user when impersonate is clicked' do
+ subject
+
expect(page.find(:css, '.header-user .profile-link')['data-user']).to eql(another_user.username)
end
it 'sees impersonation log out icon' do
- icon = first('.fa.fa-user-secret')
+ subject
+ icon = first('.fa.fa-user-secret')
expect(icon).not_to be nil
end
- it 'logs out of impersonated user back to original user' do
- find(:css, 'li.impersonation a').click
+ context 'a user with an expired password' do
+ before do
+ another_user.update(password_expires_at: Time.now - 5.minutes)
+ end
- expect(page.find(:css, '.header-user .profile-link')['data-user']).to eq(current_user.username)
- end
-
- it 'is redirected back to the impersonated users page in the admin after stopping' do
- find(:css, 'li.impersonation a').click
+ it 'does not redirect to password change page' do
+ subject
- expect(current_path).to eq("/admin/users/#{another_user.username}")
+ expect(current_path).to eq('/')
+ end
end
end
- context 'when impersonating a user with an expired password' do
+ context 'ending impersonation' do
+ subject { find(:css, 'li.impersonation a').click }
+
before do
- another_user.update(password_expires_at: Time.now - 5.minutes)
+ visit admin_user_path(another_user)
click_link 'Impersonate'
end
- it 'does not redirect to password change page' do
- expect(current_path).to eq('/')
+ it 'logs out of impersonated user back to original user' do
+ subject
+
+ expect(page.find(:css, '.header-user .profile-link')['data-user']).to eq(current_user.username)
end
it 'is redirected back to the impersonated users page in the admin after stopping' do
- find(:css, 'li.impersonation a').click
+ subject
expect(current_path).to eq("/admin/users/#{another_user.username}")
end
+
+ context 'a user with an expired password' do
+ before do
+ another_user.update(password_expires_at: Time.now - 5.minutes)
+ end
+
+ it 'is redirected back to the impersonated users page in the admin after stopping' do
+ subject
+
+ expect(current_path).to eq("/admin/users/#{another_user.username}")
+ end
+ end
end
end
diff --git a/spec/features/admin/dashboard_spec.rb b/spec/features/admin/dashboard_spec.rb
new file mode 100644
index 00000000000..a6ca0803469
--- /dev/null
+++ b/spec/features/admin/dashboard_spec.rb
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+describe 'admin visits dashboard' do
+ include ProjectForksHelper
+
+ before do
+ sign_in(create(:admin))
+ end
+
+ context 'counting forks' do
+ it 'correctly counts 2 forks of a project' do
+ project = create(:project)
+ project_fork = fork_project(project)
+ fork_project(project_fork)
+
+ # Make sure the fork_networks & fork_networks reltuples have been updated
+ # to get a correct count on postgresql
+ if Gitlab::Database.postgresql?
+ ActiveRecord::Base.connection.execute('ANALYZE fork_networks')
+ ActiveRecord::Base.connection.execute('ANALYZE fork_network_members')
+ end
+
+ visit admin_root_path
+
+ expect(page).to have_content('Forks 2')
+ end
+ end
+end
diff --git a/spec/features/atom/dashboard_issues_spec.rb b/spec/features/atom/dashboard_issues_spec.rb
index bd4c00d97b1..5fa1a26f1a6 100644
--- a/spec/features/atom/dashboard_issues_spec.rb
+++ b/spec/features/atom/dashboard_issues_spec.rb
@@ -25,35 +25,35 @@ describe "Dashboard Issues Feed" do
it "renders atom feed via personal access token" do
personal_access_token = create(:personal_access_token, user: user)
- visit issues_dashboard_path(:atom, private_token: personal_access_token.token, assignee_id: user.id)
+ visit issues_dashboard_path(:atom, private_token: personal_access_token.token, assignee_username: user.username)
expect(response_headers['Content-Type']).to have_content('application/atom+xml')
expect(body).to have_selector('title', text: "#{user.name} issues")
end
it "renders atom feed via feed token" do
- visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_id: user.id)
+ visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_username: user.username)
expect(response_headers['Content-Type']).to have_content('application/atom+xml')
expect(body).to have_selector('title', text: "#{user.name} issues")
end
it "renders atom feed with url parameters" do
- visit issues_dashboard_path(:atom, feed_token: user.feed_token, state: 'opened', assignee_id: user.id)
+ visit issues_dashboard_path(:atom, feed_token: user.feed_token, state: 'opened', assignee_username: user.username)
link = find('link[type="application/atom+xml"]')
params = CGI.parse(URI.parse(link[:href]).query)
expect(params).to include('feed_token' => [user.feed_token])
expect(params).to include('state' => ['opened'])
- expect(params).to include('assignee_id' => [user.id.to_s])
+ expect(params).to include('assignee_username' => [user.username.to_s])
end
context "issue with basic fields" do
let!(:issue2) { create(:issue, author: user, assignees: [assignee], project: project2, description: 'test desc') }
it "renders issue fields" do
- visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_id: assignee.id)
+ visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_username: assignee.username)
entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue2.title}')]")
@@ -76,7 +76,7 @@ describe "Dashboard Issues Feed" do
end
it "renders issue label and milestone info" do
- visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_id: assignee.id)
+ visit issues_dashboard_path(:atom, feed_token: user.feed_token, assignee_username: assignee.username)
entry = find(:xpath, "//feed/entry[contains(summary/text(),'#{issue1.title}')]")
diff --git a/spec/features/boards/add_issues_modal_spec.rb b/spec/features/boards/add_issues_modal_spec.rb
index eebc987499d..030993462b5 100644
--- a/spec/features/boards/add_issues_modal_spec.rb
+++ b/spec/features/boards/add_issues_modal_spec.rb
@@ -160,7 +160,7 @@ describe 'Issue Boards add issue modal', :js do
it 'changes button text with plural' do
page.within('.add-issues-modal') do
- all('.board-card .board-card-number').each do |el|
+ all('.board-card .js-board-card-number-container').each do |el|
el.click
end
diff --git a/spec/features/boards/issue_ordering_spec.rb b/spec/features/boards/issue_ordering_spec.rb
index ec0ca21450a..21779336559 100644
--- a/spec/features/boards/issue_ordering_spec.rb
+++ b/spec/features/boards/issue_ordering_spec.rb
@@ -78,7 +78,7 @@ describe 'Issue Boards', :js do
end
it 'moves from bottom to top' do
- drag(from_index: 2, to_index: 0)
+ drag(from_index: 2, to_index: 0, duration: 1020)
wait_for_requests
@@ -130,7 +130,7 @@ describe 'Issue Boards', :js do
end
it 'moves to bottom of another list' do
- drag(list_from_index: 1, list_to_index: 2, to_index: 2)
+ drag(list_from_index: 1, list_to_index: 2, to_index: 2, duration: 1020)
wait_for_requests
diff --git a/spec/features/boards/modal_filter_spec.rb b/spec/features/boards/modal_filter_spec.rb
index 615223a2a88..d96707e55fd 100644
--- a/spec/features/boards/modal_filter_spec.rb
+++ b/spec/features/boards/modal_filter_spec.rb
@@ -106,7 +106,7 @@ describe 'Issue Boards add issue modal filtering', :js do
it 'filters by unassigned' do
set_filter('assignee')
- click_filter_link('No Assignee')
+ click_filter_link('None')
submit_filter
page.within('.add-issues-modal') do
@@ -176,7 +176,7 @@ describe 'Issue Boards add issue modal filtering', :js do
it 'filters by no label' do
set_filter('label')
- click_filter_link('No Label')
+ click_filter_link('None')
submit_filter
page.within('.add-issues-modal') do
diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb
index 0bf1ecbc433..164442a47f5 100644
--- a/spec/features/boards/new_issue_spec.rb
+++ b/spec/features/boards/new_issue_spec.rb
@@ -94,8 +94,14 @@ describe 'Issue Boards new issue', :js do
wait_for_requests
end
- it 'does not display new issue button' do
- expect(page).to have_selector('.issue-count-badge-add-button', count: 0)
+ it 'displays new issue button in open list' do
+ expect(first('.board')).to have_selector('.issue-count-badge-add-button', count: 1)
+ end
+
+ it 'does not display new issue button in label list' do
+ page.within('.board:nth-child(2)') do
+ expect(page).not_to have_selector('.issue-count-badge-add-button')
+ end
end
end
end
diff --git a/spec/features/boards/reload_boards_on_browser_back_spec.rb b/spec/features/boards/reload_boards_on_browser_back_spec.rb
new file mode 100644
index 00000000000..4b4bd705a77
--- /dev/null
+++ b/spec/features/boards/reload_boards_on_browser_back_spec.rb
@@ -0,0 +1,48 @@
+require 'rails_helper'
+
+describe 'Ensure Boards do not show stale data on browser back', :js do
+ let(:project) {create(:project, :public)}
+ let(:board) {create(:board, project: project)}
+ let(:user) {create(:user)}
+
+ context 'authorized user' do
+ before do
+ project.add_maintainer(user)
+
+ sign_in(user)
+
+ visit project_board_path(project, board)
+ wait_for_requests
+
+ page.within(first('.board .issue-count-badge-count')) do
+ expect(page).to have_content('0')
+ end
+ end
+
+ it 'created issue is listed on board' do
+ visit new_project_issue_path(project)
+ wait_for_requests
+
+ fill_in 'issue_title', with: 'issue should be shown'
+
+ click_button 'Submit issue'
+
+ page.go_back
+ wait_for_requests
+
+ page.go_back
+ wait_for_requests
+
+ page.within(first('.board .issue-count-badge-count')) do
+ expect(page).to have_content('1')
+ end
+
+ page.within(first('.board-card')) do
+ issue = project.issues.find_by_title('issue should be shown')
+
+ expect(page).to have_content(issue.to_reference)
+ expect(page).to have_link(issue.title, href: issue_path(issue))
+ end
+ end
+ end
+end
diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb
index f08946b0593..8cb9b57a049 100644
--- a/spec/features/calendar_spec.rb
+++ b/spec/features/calendar_spec.rb
@@ -64,7 +64,7 @@ describe 'Contributions Calendar', :js do
end
def selected_day_activities(visible: true)
- find('.user-calendar-activities', visible: visible).text
+ find('#js-overview .user-calendar-activities', visible: visible).text
end
before do
@@ -74,15 +74,16 @@ describe 'Contributions Calendar', :js do
describe 'calendar day selection' do
before do
visit user.username
+ page.find('.js-overview-tab a').click
wait_for_requests
end
it 'displays calendar' do
- expect(page).to have_css('.js-contrib-calendar')
+ expect(find('#js-overview')).to have_css('.js-contrib-calendar')
end
describe 'select calendar day' do
- let(:cells) { page.all('.user-contrib-cell') }
+ let(:cells) { page.all('#js-overview .user-contrib-cell') }
before do
cells[0].click
@@ -108,6 +109,7 @@ describe 'Contributions Calendar', :js do
describe 'deselect calendar day' do
before do
cells[0].click
+ page.find('.js-overview-tab a').click
wait_for_requests
end
@@ -122,6 +124,7 @@ describe 'Contributions Calendar', :js do
shared_context 'visit user page' do
before do
visit user.username
+ page.find('.js-overview-tab a').click
wait_for_requests
end
end
@@ -130,12 +133,12 @@ describe 'Contributions Calendar', :js do
include_context 'visit user page'
it 'displays calendar activity square color for 1 contribution' do
- expect(page).to have_selector(get_cell_color_selector(contribution_count), count: 1)
+ expect(find('#js-overview')).to have_selector(get_cell_color_selector(contribution_count), count: 1)
end
it 'displays calendar activity square on the correct date' do
today = Date.today.strftime(date_format)
- expect(page).to have_selector(get_cell_date_selector(contribution_count, today), count: 1)
+ expect(find('#js-overview')).to have_selector(get_cell_date_selector(contribution_count, today), count: 1)
end
end
@@ -150,7 +153,7 @@ describe 'Contributions Calendar', :js do
include_context 'visit user page'
it 'displays calendar activity log' do
- expect(find('.content_list .event-note')).to have_content issue_title
+ expect(find('#js-overview .overview-content-list .event-target-title')).to have_content issue_title
end
end
end
@@ -182,17 +185,17 @@ describe 'Contributions Calendar', :js do
include_context 'visit user page'
it 'displays calendar activity squares for both days' do
- expect(page).to have_selector(get_cell_color_selector(1), count: 2)
+ expect(find('#js-overview')).to have_selector(get_cell_color_selector(1), count: 2)
end
it 'displays calendar activity square for yesterday' do
yesterday = Date.yesterday.strftime(date_format)
- expect(page).to have_selector(get_cell_date_selector(1, yesterday), count: 1)
+ expect(find('#js-overview')).to have_selector(get_cell_date_selector(1, yesterday), count: 1)
end
it 'displays calendar activity square for today' do
today = Date.today.strftime(date_format)
- expect(page).to have_selector(get_cell_date_selector(1, today), count: 1)
+ expect(find('#js-overview')).to have_selector(get_cell_date_selector(1, today), count: 1)
end
end
end
diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb
index 8989b2051bb..5c6c1c4fd15 100644
--- a/spec/features/commits_spec.rb
+++ b/spec/features/commits_spec.rb
@@ -114,33 +114,6 @@ describe 'Commits' do
expect(page).to have_content 'canceled'
end
end
-
- describe '.gitlab-ci.yml not found warning' do
- context 'ci builds enabled' do
- it "does not show warning" do
- visit pipeline_path(pipeline)
- expect(page).not_to have_content '.gitlab-ci.yml not found in this commit'
- end
-
- it 'shows warning' do
- stub_ci_pipeline_yaml_file(nil)
- visit pipeline_path(pipeline)
- expect(page).to have_content '.gitlab-ci.yml not found in this commit'
- end
- end
-
- context 'ci builds disabled' do
- before do
- stub_ci_builds_disabled
- stub_ci_pipeline_yaml_file(nil)
- visit pipeline_path(pipeline)
- end
-
- it 'does not show warning' do
- expect(page).not_to have_content '.gitlab-ci.yml not found in this commit'
- end
- end
- end
end
context "when logged as reporter" do
@@ -182,6 +155,39 @@ describe 'Commits' do
end
end
end
+
+ describe '.gitlab-ci.yml not found warning' do
+ before do
+ project.add_reporter(user)
+ end
+
+ context 'ci builds enabled' do
+ it 'does not show warning' do
+ visit pipeline_path(pipeline)
+
+ expect(page).not_to have_content '.gitlab-ci.yml not found in this commit'
+ end
+
+ it 'shows warning' do
+ stub_ci_pipeline_yaml_file(nil)
+
+ visit pipeline_path(pipeline)
+
+ expect(page).to have_content '.gitlab-ci.yml not found in this commit'
+ end
+ end
+
+ context 'ci builds disabled' do
+ it 'does not show warning' do
+ stub_ci_builds_disabled
+ stub_ci_pipeline_yaml_file(nil)
+
+ visit pipeline_path(pipeline)
+
+ expect(page).not_to have_content '.gitlab-ci.yml not found in this commit'
+ end
+ end
+ end
end
context 'viewing commits for a branch' do
diff --git a/spec/features/dashboard/archived_projects_spec.rb b/spec/features/dashboard/archived_projects_spec.rb
index 6a0cd848345..d31df322d10 100644
--- a/spec/features/dashboard/archived_projects_spec.rb
+++ b/spec/features/dashboard/archived_projects_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe 'Dashboard Archived Project' do
expect(page).not_to have_content(project.name)
end
- it 'searchs archived projects', :js do
+ it 'searches archived projects', :js do
click_button 'Last updated'
click_link 'Show archived projects'
diff --git a/spec/features/dashboard/datetime_on_tooltips_spec.rb b/spec/features/dashboard/datetime_on_tooltips_spec.rb
index d7234158fa1..0db8093411b 100644
--- a/spec/features/dashboard/datetime_on_tooltips_spec.rb
+++ b/spec/features/dashboard/datetime_on_tooltips_spec.rb
@@ -14,7 +14,7 @@ describe 'Tooltips on .timeago dates', :js do
updated_at: created_date, created_at: created_date)
sign_in user
- visit user_path(user)
+ visit user_activity_path(user)
wait_for_requests()
page.find('.js-timeago').hover
diff --git a/spec/features/dashboard/group_spec.rb b/spec/features/dashboard/group_spec.rb
index e57fcde8b2c..259f220c68b 100644
--- a/spec/features/dashboard/group_spec.rb
+++ b/spec/features/dashboard/group_spec.rb
@@ -14,15 +14,15 @@ RSpec.describe 'Dashboard Group' do
it 'creates new group', :js do
visit dashboard_groups_path
find('.btn-success').click
- new_path = 'Samurai'
+ new_name = 'Samurai'
new_description = 'Tokugawa Shogunate'
- fill_in 'group_path', with: new_path
+ fill_in 'group_name', with: new_name
fill_in 'group_description', with: new_description
click_button 'Create group'
- expect(current_path).to eq group_path(Group.find_by(name: new_path))
- expect(page).to have_content(new_path)
+ expect(current_path).to eq group_path(Group.find_by(name: new_name))
+ expect(page).to have_content(new_name)
expect(page).to have_content(new_description)
end
end
diff --git a/spec/features/dashboard/issuables_counter_spec.rb b/spec/features/dashboard/issuables_counter_spec.rb
index b431f72fcc9..fbc2e5cc3d3 100644
--- a/spec/features/dashboard/issuables_counter_spec.rb
+++ b/spec/features/dashboard/issuables_counter_spec.rb
@@ -45,11 +45,11 @@ describe 'Navigation bar counter', :use_clean_rails_memory_store_caching do
end
def issues_path
- issues_dashboard_path(assignee_id: user.id)
+ issues_dashboard_path(assignee_username: user.username)
end
def merge_requests_path
- merge_requests_dashboard_path(assignee_id: user.id)
+ merge_requests_dashboard_path(assignee_username: user.username)
end
def expect_counters(issuable_type, count)
diff --git a/spec/features/dashboard/issues_filter_spec.rb b/spec/features/dashboard/issues_filter_spec.rb
index 95e2610dd4a..c0434f767bb 100644
--- a/spec/features/dashboard/issues_filter_spec.rb
+++ b/spec/features/dashboard/issues_filter_spec.rb
@@ -2,6 +2,7 @@ require 'spec_helper'
describe 'Dashboard Issues filtering', :js do
include Spec::Support::Helpers::Features::SortingHelpers
+ include FilteredSearchHelpers
let(:user) { create(:user) }
let(:project) { create(:project) }
@@ -25,27 +26,21 @@ describe 'Dashboard Issues filtering', :js do
context 'filtering by milestone' do
it 'shows all issues with no milestone' do
- show_milestone_dropdown
-
- click_link 'No Milestone'
+ input_filtered_search("milestone:none")
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
expect(page).to have_selector('.issue', count: 1)
end
it 'shows all issues with the selected milestone' do
- show_milestone_dropdown
-
- page.within '.dropdown-content' do
- click_link milestone.title
- end
+ input_filtered_search("milestone:%\"#{milestone.title}\"")
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
expect(page).to have_selector('.issue', count: 1)
end
it 'updates atom feed link' do
- visit_issues(milestone_title: '', assignee_id: user.id)
+ visit_issues(milestone_title: '', assignee_username: user.username)
link = find('.nav-controls a[title="Subscribe to RSS feed"]')
params = CGI.parse(URI.parse(link[:href]).query)
@@ -54,10 +49,10 @@ describe 'Dashboard Issues filtering', :js do
expect(params).to include('feed_token' => [user.feed_token])
expect(params).to include('milestone_title' => [''])
- expect(params).to include('assignee_id' => [user.id.to_s])
+ expect(params).to include('assignee_username' => [user.username.to_s])
expect(auto_discovery_params).to include('feed_token' => [user.feed_token])
expect(auto_discovery_params).to include('milestone_title' => [''])
- expect(auto_discovery_params).to include('assignee_id' => [user.id.to_s])
+ expect(auto_discovery_params).to include('assignee_username' => [user.username.to_s])
end
end
@@ -66,10 +61,7 @@ describe 'Dashboard Issues filtering', :js do
let!(:label_link) { create(:label_link, label: label, target: issue) }
it 'shows all issues with the selected label' do
- page.within '.labels-filter' do
- find('.dropdown').click
- click_link label.title
- end
+ input_filtered_search("label:~#{label.title}")
page.within 'ul.content-list' do
expect(page).to have_content issue.title
@@ -80,12 +72,12 @@ describe 'Dashboard Issues filtering', :js do
context 'sorting' do
before do
- visit_issues(assignee_id: user.id)
+ visit_issues(assignee_username: user.username)
end
it 'remembers last sorting value' do
sort_by('Created date')
- visit_issues(assignee_id: user.id)
+ visit_issues(assignee_username: user.username)
expect(find('.issues-filters')).to have_content('Created date')
end
@@ -98,11 +90,6 @@ describe 'Dashboard Issues filtering', :js do
end
end
- def show_milestone_dropdown
- click_button 'Milestone'
- expect(page).to have_selector('.dropdown-content', visible: true)
- end
-
def visit_issues(*args)
visit issues_dashboard_path(*args)
end
diff --git a/spec/features/dashboard/issues_spec.rb b/spec/features/dashboard/issues_spec.rb
index 4ae062f242a..9957bec0f0b 100644
--- a/spec/features/dashboard/issues_spec.rb
+++ b/spec/features/dashboard/issues_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
RSpec.describe 'Dashboard Issues' do
+ include FilteredSearchHelpers
+
let(:current_user) { create :user }
let(:user) { current_user } # Shared examples depend on this being available
let!(:public_project) { create(:project, :public) }
@@ -14,7 +16,7 @@ RSpec.describe 'Dashboard Issues' do
before do
[project, project_with_issues_disabled].each { |project| project.add_maintainer(current_user) }
sign_in(current_user)
- visit issues_dashboard_path(assignee_id: current_user.id)
+ visit issues_dashboard_path(assignee_username: current_user.username)
end
describe 'issues' do
@@ -24,26 +26,9 @@ RSpec.describe 'Dashboard Issues' do
expect(page).not_to have_content(other_issue.title)
end
- it 'shows checkmark when unassigned is selected for assignee', :js do
- find('.js-assignee-search').click
- find('li', text: 'Unassigned').click
- find('.js-assignee-search').click
-
- expect(find('li[data-user-id="0"] a.is-active')).to be_visible
- end
-
it 'shows issues when current user is author', :js do
- execute_script("document.querySelector('#assignee_id').value=''")
- find('.js-author-search', match: :first).click
-
- expect(find('li[data-user-id="null"] a.is-active')).to be_visible
-
- find('.dropdown-menu-author li a', match: :first, text: current_user.to_reference).click
- find('.js-author-search', match: :first).click
-
- page.within '.dropdown-menu-user' do
- expect(find('.dropdown-menu-author li a.is-active', match: :first, text: current_user.to_reference)).to be_visible
- end
+ reset_filters
+ input_filtered_search("author:#{current_user.to_reference}")
expect(page).to have_content(authored_issue.title)
expect(page).to have_content(authored_issue_on_public_project.title)
@@ -53,7 +38,7 @@ RSpec.describe 'Dashboard Issues' do
it 'state filter tabs work' do
find('#state-closed').click
- expect(page).to have_current_path(issues_dashboard_url(assignee_id: current_user.id, state: 'closed'), url: true)
+ expect(page).to have_current_path(issues_dashboard_url(assignee_username: current_user.username, state: 'closed'), url: true)
end
it_behaves_like "it has an RSS button with current_user's feed token"
diff --git a/spec/features/dashboard/label_filter_spec.rb b/spec/features/dashboard/label_filter_spec.rb
index 6802974c2ee..2d4659d380f 100644
--- a/spec/features/dashboard/label_filter_spec.rb
+++ b/spec/features/dashboard/label_filter_spec.rb
@@ -1,6 +1,11 @@
require 'spec_helper'
describe 'Dashboard > label filter', :js do
+ include FilteredSearchHelpers
+
+ let(:filtered_search) { find('.filtered-search') }
+ let(:filter_dropdown) { find("#js-dropdown-label .filter-dropdown") }
+
let(:user) { create(:user) }
let(:project) { create(:project, name: 'test', namespace: user.namespace) }
let(:project2) { create(:project, name: 'test2', path: 'test2', namespace: user.namespace) }
@@ -13,17 +18,15 @@ describe 'Dashboard > label filter', :js do
sign_in(user)
visit issues_dashboard_path
+
+ init_label_search
end
context 'duplicate labels' do
it 'removes duplicate labels' do
- page.within('.labels-filter') do
- click_button 'Label'
- end
+ filtered_search.send_keys('bu')
- page.within('.dropdown-menu-labels') do
- expect(page).to have_selector('.dropdown-content a', text: 'bug', count: 1)
- end
+ expect(filter_dropdown).to have_selector('.filter-dropdown-item', text: 'bug', count: 1)
end
end
end
diff --git a/spec/features/dashboard/merge_requests_spec.rb b/spec/features/dashboard/merge_requests_spec.rb
index f51142f5790..9ffa75aee47 100644
--- a/spec/features/dashboard/merge_requests_spec.rb
+++ b/spec/features/dashboard/merge_requests_spec.rb
@@ -2,10 +2,11 @@ require 'spec_helper'
describe 'Dashboard Merge Requests' do
include Spec::Support::Helpers::Features::SortingHelpers
- include FilterItemSelectHelper
+ include FilteredSearchHelpers
include ProjectForksHelper
let(:current_user) { create :user }
+ let(:user) { current_user }
let(:project) { create(:project) }
let(:public_project) { create(:project, :public, :repository) }
@@ -36,7 +37,7 @@ describe 'Dashboard Merge Requests' do
context 'no merge requests exist' do
it 'shows an empty state' do
- visit merge_requests_dashboard_path(assignee_id: current_user.id)
+ visit merge_requests_dashboard_path(assignee_username: current_user.username)
expect(page).to have_selector('.empty-state')
end
@@ -79,7 +80,7 @@ describe 'Dashboard Merge Requests' do
end
before do
- visit merge_requests_dashboard_path(assignee_id: current_user.id)
+ visit merge_requests_dashboard_path(assignee_username: current_user.username)
end
it 'shows assigned merge requests' do
@@ -92,8 +93,8 @@ describe 'Dashboard Merge Requests' do
end
it 'shows authored merge requests', :js do
- filter_item_select('Any Assignee', '.js-assignee-search')
- filter_item_select(current_user.to_reference, '.js-author-search')
+ reset_filters
+ input_filtered_search("author:#{current_user.to_reference}")
expect(page).to have_content(authored_merge_request.title)
expect(page).to have_content(authored_merge_request_from_fork.title)
@@ -104,8 +105,7 @@ describe 'Dashboard Merge Requests' do
end
it 'shows error message without filter', :js do
- filter_item_select('Any Assignee', '.js-assignee-search')
- filter_item_select('Any Author', '.js-author-search')
+ reset_filters
expect(page).to have_content('Please select at least one filter to see results')
end
@@ -113,7 +113,7 @@ describe 'Dashboard Merge Requests' do
it 'shows sorted merge requests' do
sort_by('Created date')
- visit merge_requests_dashboard_path(assignee_id: current_user.id)
+ visit merge_requests_dashboard_path(assignee_username: current_user.username)
expect(find('.issues-filters')).to have_content('Created date')
end
diff --git a/spec/features/dashboard/milestone_filter_spec.rb b/spec/features/dashboard/milestone_filter_spec.rb
deleted file mode 100644
index 00373050aeb..00000000000
--- a/spec/features/dashboard/milestone_filter_spec.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-require 'spec_helper'
-
-describe 'Dashboard > milestone filter', :js do
- include FilterItemSelectHelper
-
- let(:user) { create(:user) }
- let(:project) { create(:project, name: 'test', namespace: user.namespace) }
- let(:milestone) { create(:milestone, title: 'v1.0', project: project) }
- let(:milestone2) { create(:milestone, title: 'v2.0', project: project) }
- let!(:issue) { create :issue, author: user, project: project, milestone: milestone }
- let!(:issue2) { create :issue, author: user, project: project, milestone: milestone2 }
-
- dropdown_toggle_button = '.js-milestone-select'
-
- before do
- sign_in(user)
- end
-
- context 'default state' do
- it 'shows issues with Any Milestone' do
- visit issues_dashboard_path(author_id: user.id)
-
- page.all('.issue-info').each do |issue_info|
- expect(issue_info.text).to match(/v\d.0/)
- end
- end
- end
-
- context 'filtering by milestone' do
- before do
- visit issues_dashboard_path(author_id: user.id)
- filter_item_select('v1.0', dropdown_toggle_button)
- find(dropdown_toggle_button).click
- wait_for_requests
- end
-
- it 'shows issues with Milestone v1.0' do
- expect(find('.issues-list')).to have_selector('.issue', count: 1)
- expect(find('.milestone-filter .dropdown-content')).to have_selector('a.is-active', count: 1)
- end
-
- it 'should not change active Milestone unless clicked' do
- page.within '.milestone-filter' do
- expect(find('.dropdown-content')).to have_selector('a.is-active', count: 1)
-
- find('.dropdown-menu-close').click
-
- expect(page).not_to have_selector('.dropdown.open')
-
- find(dropdown_toggle_button).click
-
- expect(find('.dropdown-content')).to have_selector('a.is-active', count: 1)
- expect(find('.dropdown-content a.is-active')).to have_content('v1.0')
- end
- end
- end
-
- context 'with milestone filter in URL' do
- before do
- visit issues_dashboard_path(author_id: user.id, milestone_title: milestone.title)
- find(dropdown_toggle_button).click
- wait_for_requests
- end
-
- it 'has milestone selected' do
- expect(find('.milestone-filter .dropdown-content')).to have_css('.is-active', text: milestone.title)
- end
-
- it 'removes milestone filter from URL after clicking "Any Milestone"' do
- expect(current_url).to include("milestone_title=#{milestone.title}")
-
- find('.milestone-filter .dropdown-content li', text: 'Any Milestone').click
-
- expect(current_url).not_to include('milestone_title')
- end
- end
-end
diff --git a/spec/features/dashboard/project_member_activity_index_spec.rb b/spec/features/dashboard/project_member_activity_index_spec.rb
index 498775acff3..16919fe63ad 100644
--- a/spec/features/dashboard/project_member_activity_index_spec.rb
+++ b/spec/features/dashboard/project_member_activity_index_spec.rb
@@ -14,14 +14,15 @@ describe 'Project member activity', :js do
wait_for_requests
end
- subject { page.find(".event-title").text }
-
context 'when a user joins the project' do
before do
visit_activities_and_wait_with_event(Event::JOINED)
end
- it { is_expected.to eq("#{user.name} joined project") }
+ it "presents the correct message" do
+ expect(page.find('.event-user-info').text).to eq("#{user.name} #{user.to_reference}")
+ expect(page.find('.event-title').text).to eq("joined project")
+ end
end
context 'when a user leaves the project' do
@@ -29,7 +30,10 @@ describe 'Project member activity', :js do
visit_activities_and_wait_with_event(Event::LEFT)
end
- it { is_expected.to eq("#{user.name} left project") }
+ it "presents the correct message" do
+ expect(page.find('.event-user-info').text).to eq("#{user.name} #{user.to_reference}")
+ expect(page.find('.event-title').text).to eq("left project")
+ end
end
context 'when a users membership expires for the project' do
@@ -38,8 +42,8 @@ describe 'Project member activity', :js do
end
it "presents the correct message" do
- message = "#{user.name} removed due to membership expiration from project"
- is_expected.to eq(message)
+ expect(page.find('.event-user-info').text).to eq("#{user.name} #{user.to_reference}")
+ expect(page.find('.event-title').text).to eq("removed due to membership expiration from project")
end
end
end
diff --git a/spec/features/dashboard/shortcuts_spec.rb b/spec/features/dashboard/shortcuts_spec.rb
index e5c5ab9c039..31a1dcf826d 100644
--- a/spec/features/dashboard/shortcuts_spec.rb
+++ b/spec/features/dashboard/shortcuts_spec.rb
@@ -2,8 +2,12 @@ require 'spec_helper'
describe 'Dashboard shortcuts', :js do
context 'logged in' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+
before do
- sign_in(create(:user))
+ project.add_developer(user)
+ sign_in(user)
visit root_dashboard_path
end
@@ -50,6 +54,6 @@ describe 'Dashboard shortcuts', :js do
end
def check_page_title(title)
- expect(find('.breadcrumbs-sub-title')).to have_content(title)
+ expect(find('.page-title')).to have_content(title)
end
end
diff --git a/spec/features/explore/new_menu_spec.rb b/spec/features/explore/new_menu_spec.rb
deleted file mode 100644
index 11f05b6d220..00000000000
--- a/spec/features/explore/new_menu_spec.rb
+++ /dev/null
@@ -1,167 +0,0 @@
-require 'spec_helper'
-
-describe 'Top Plus Menu', :js do
- let(:user) { create(:user) }
- let(:group) { create(:group) }
- let(:project) { create(:project, :repository, creator: user, namespace: user.namespace) }
- let(:public_project) { create(:project, :public) }
-
- before do
- group.add_owner(user)
- end
-
- context 'used by full user' do
- before do
- sign_in(user)
- end
-
- it 'click on New project shows new project page' do
- visit root_dashboard_path
-
- click_topmenuitem("New project")
-
- expect(page).to have_content('Project URL')
- expect(page).to have_content('Project name')
- end
-
- it 'click on New group shows new group page' do
- visit root_dashboard_path
-
- click_topmenuitem("New group")
-
- expect(page).to have_content('Group path')
- expect(page).to have_content('Group name')
- end
-
- it 'click on New snippet shows new snippet page' do
- visit root_dashboard_path
-
- click_topmenuitem("New snippet")
-
- expect(page).to have_content('New Snippet')
- expect(page).to have_content('Title')
- end
-
- it 'click on New issue shows new issue page' do
- visit project_path(project)
-
- click_topmenuitem("New issue")
-
- expect(page).to have_content('New Issue')
- expect(page).to have_content('Title')
- end
-
- it 'click on New merge request shows new merge request page' do
- visit project_path(project)
-
- click_topmenuitem("New merge request")
-
- expect(page).to have_content('New Merge Request')
- expect(page).to have_content('Source branch')
- expect(page).to have_content('Target branch')
- end
-
- it 'click on New project snippet shows new snippet page' do
- visit project_path(project)
-
- page.within '.header-content' do
- find('.header-new-dropdown-toggle').click
- expect(page).to have_selector('.header-new.dropdown.show', count: 1)
- find('.header-new-project-snippet a').click
- end
-
- expect(page).to have_content('New Snippet')
- expect(page).to have_content('Title')
- end
-
- it 'Click on New subgroup shows new group page', :nested_groups do
- visit group_path(group)
-
- click_topmenuitem("New subgroup")
-
- expect(page).to have_content('Group path')
- expect(page).to have_content('Group name')
- end
-
- it 'Click on New project in group shows new project page' do
- visit group_path(group)
-
- page.within '.header-content' do
- find('.header-new-dropdown-toggle').click
- expect(page).to have_selector('.header-new.dropdown.show', count: 1)
- find('.header-new-group-project a').click
- end
-
- expect(page).to have_content('Project URL')
- expect(page).to have_content('Project name')
- end
- end
-
- context 'used by guest user' do
- let(:guest_user) { create(:user) }
-
- before do
- group.add_guest(guest_user)
- project.add_guest(guest_user)
-
- sign_in(guest_user)
- end
-
- it 'click on New issue shows new issue page' do
- visit project_path(project)
-
- click_topmenuitem("New issue")
-
- expect(page).to have_content('New Issue')
- expect(page).to have_content('Title')
- end
-
- it 'has no New merge request menu item' do
- visit project_path(project)
-
- hasnot_topmenuitem("New merge request")
- end
-
- it 'has no New project snippet menu item' do
- visit project_path(project)
-
- expect(find('.header-new.dropdown')).not_to have_selector('.header-new-project-snippet')
- end
-
- it 'public project has no New merge request menu item' do
- visit project_path(public_project)
-
- hasnot_topmenuitem("New merge request")
- end
-
- it 'public project has no New project snippet menu item' do
- visit project_path(public_project)
-
- expect(find('.header-new.dropdown')).not_to have_selector('.header-new-project-snippet')
- end
-
- it 'has no New subgroup menu item' do
- visit group_path(group)
-
- hasnot_topmenuitem("New subgroup")
- end
-
- it 'has no New project for group menu item' do
- visit group_path(group)
-
- expect(find('.header-new.dropdown')).not_to have_selector('.header-new-group-project')
- end
- end
-
- def click_topmenuitem(item_name)
- page.within '.header-content' do
- find('.header-new-dropdown-toggle').click
- expect(page).to have_selector('.header-new.dropdown.show', count: 1)
- click_link item_name
- end
- end
-
- def hasnot_topmenuitem(item_name)
- expect(find('.header-new.dropdown')).not_to have_content(item_name)
- end
-end
diff --git a/spec/features/groups/board_sidebar_spec.rb b/spec/features/groups/board_sidebar_spec.rb
new file mode 100644
index 00000000000..9f597efa7b7
--- /dev/null
+++ b/spec/features/groups/board_sidebar_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'Group Issue Boards', :js do
+ include BoardHelpers
+
+ let(:group) { create(:group) }
+ let(:user) { create(:group_member, user: create(:user), group: group ).user }
+ let!(:project_1) { create(:project, :public, group: group) }
+ let!(:project_2) { create(:project, :public, group: group) }
+ let!(:project_1_label) { create(:label, project: project_1, name: 'Development 1') }
+ let!(:project_2_label) { create(:label, project: project_2, name: 'Development 2') }
+ let!(:group_label) { create(:group_label, title: 'Bug', description: 'Fusce consequat', group: group) }
+ let!(:issue_1) { create(:labeled_issue, project: project_1, relative_position: 1) }
+ let!(:issue_2) { create(:labeled_issue, project: project_2, relative_position: 2) }
+ let(:board) { create(:board, group: group) }
+ let!(:list) { create(:list, board: board, label: project_1_label, position: 0) }
+ let(:card) { find('.board:nth-child(1)').first('.board-card') }
+
+ before do
+ sign_in(user)
+
+ visit group_board_path(group, board)
+ wait_for_requests
+ end
+
+ context 'labels' do
+ it 'only shows valid labels for the issue project and group' do
+ click_card(card)
+
+ page.within('.labels') do
+ click_link 'Edit'
+
+ wait_for_requests
+
+ page.within('.selectbox') do
+ expect(page).to have_content(project_1_label.title)
+ expect(page).to have_content(group_label.title)
+ expect(page).not_to have_content(project_2_label.title)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/groups/group_settings_spec.rb b/spec/features/groups/group_settings_spec.rb
index 59254ecc982..2cdbdcffbc3 100644
--- a/spec/features/groups/group_settings_spec.rb
+++ b/spec/features/groups/group_settings_spec.rb
@@ -98,6 +98,22 @@ describe 'Edit group settings' do
end
end
+ describe 'edit group path' do
+ it 'has a root URL label for top-level group' do
+ visit edit_group_path(group)
+
+ expect(find(:css, '.group-root-path').text).to eq(root_url)
+ end
+
+ it 'has a parent group URL label for a subgroup group', :postgresql do
+ subgroup = create(:group, parent: group)
+
+ visit edit_group_path(subgroup)
+
+ expect(find(:css, '.group-root-path').text).to eq(group_url(subgroup.parent) + '/')
+ end
+ end
+
def update_path(new_group_path)
visit edit_group_path(group)
@@ -109,7 +125,7 @@ describe 'Edit group settings' do
def save_group
page.within('.gs-general') do
- click_button 'Save group'
+ click_button 'Save changes'
end
end
end
diff --git a/spec/features/groups/labels/subscription_spec.rb b/spec/features/groups/labels/subscription_spec.rb
index d9543bfa97f..22b51b297a6 100644
--- a/spec/features/groups/labels/subscription_spec.rb
+++ b/spec/features/groups/labels/subscription_spec.rb
@@ -3,7 +3,8 @@ require 'spec_helper'
describe 'Labels subscription' do
let(:user) { create(:user) }
let(:group) { create(:group) }
- let!(:feature) { create(:group_label, group: group, title: 'feature') }
+ let!(:label1) { create(:group_label, group: group, title: 'foo') }
+ let!(:label2) { create(:group_label, group: group, title: 'bar') }
context 'when signed in' do
before do
@@ -14,9 +15,9 @@ describe 'Labels subscription' do
it 'users can subscribe/unsubscribe to group labels', :js do
visit group_labels_path(group)
- expect(page).to have_content('feature')
+ expect(page).to have_content(label1.title)
- within "#group_label_#{feature.id}" do
+ within "#group_label_#{label1.id}" do
expect(page).not_to have_button 'Unsubscribe'
click_button 'Subscribe'
@@ -30,15 +31,48 @@ describe 'Labels subscription' do
expect(page).not_to have_button 'Unsubscribe'
end
end
+
+ context 'subscription filter' do
+ before do
+ visit group_labels_path(group)
+ end
+
+ it 'shows only subscribed labels' do
+ label1.subscribe(user)
+
+ click_subscribed_tab
+
+ page.within('.labels-container') do
+ expect(page).to have_content label1.title
+ end
+ end
+
+ it 'shows no subscribed labels message' do
+ click_subscribed_tab
+
+ page.within('.labels-container') do
+ expect(page).not_to have_content label1.title
+ expect(page).to have_content('You do not have any subscriptions yet')
+ end
+ end
+ end
end
context 'when not signed in' do
- it 'users can not subscribe/unsubscribe to labels' do
+ before do
visit group_labels_path(group)
+ end
- expect(page).to have_content 'feature'
+ it 'users can not subscribe/unsubscribe to labels' do
+ expect(page).to have_content label1.title
expect(page).not_to have_button('Subscribe')
end
+
+ it 'does not show subscribed tab' do
+ page.within('.nav-tabs') do
+ expect(page).not_to have_link 'Subscribed'
+ end
+ end
end
def click_link_on_dropdown(text)
@@ -48,4 +82,10 @@ describe 'Labels subscription' do
find('a.js-subscribe-button', text: text).click
end
end
+
+ def click_subscribed_tab
+ page.within('.nav-tabs') do
+ click_link 'Subscribed'
+ end
+ end
end
diff --git a/spec/features/groups/milestone_spec.rb b/spec/features/groups/milestone_spec.rb
index 80df0618a6a..174840794ed 100644
--- a/spec/features/groups/milestone_spec.rb
+++ b/spec/features/groups/milestone_spec.rb
@@ -23,17 +23,17 @@ describe 'Group milestones' do
description.native.send_keys('')
- click_link('Preview')
+ click_button('Preview')
preview = find('.js-md-preview')
expect(preview).to have_content('Nothing to preview.')
- click_link('Write')
+ click_button('Write')
description.native.send_keys(':+1: Nice')
- click_link('Preview')
+ click_button('Preview')
expect(preview).to have_css('gl-emoji')
expect(find('#milestone_description', visible: false)).not_to be_visible
@@ -95,9 +95,9 @@ describe 'Group milestones' do
end
it 'counts milestones correctly' do
- expect(find('.top-area .active .badge').text).to eq("2")
- expect(find('.top-area .closed .badge').text).to eq("2")
- expect(find('.top-area .all .badge').text).to eq("4")
+ expect(find('.top-area .active .badge').text).to eq("3")
+ expect(find('.top-area .closed .badge').text).to eq("3")
+ expect(find('.top-area .all .badge').text).to eq("6")
end
it 'lists legacy group milestones and group milestones' do
diff --git a/spec/features/groups/settings/ci_cd_spec.rb b/spec/features/groups/settings/ci_cd_spec.rb
new file mode 100644
index 00000000000..d422fd18346
--- /dev/null
+++ b/spec/features/groups/settings/ci_cd_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Group CI/CD settings' do
+ include WaitForRequests
+
+ let(:user) {create(:user)}
+ let(:group) {create(:group)}
+
+ before do
+ group.add_owner(user)
+ sign_in(user)
+ end
+
+ describe 'runners registration token' do
+ let!(:token) { group.runners_token }
+
+ before do
+ visit group_settings_ci_cd_path(group)
+ end
+
+ it 'has a registration token' do
+ expect(page.find('#registration_token')).to have_content(token)
+ end
+
+ describe 'reload registration token' do
+ let(:page_token) { find('#registration_token').text }
+
+ before do
+ click_button 'Reset runners registration token'
+ end
+
+ it 'changes registration token' do
+ expect(page_token).not_to eq token
+ end
+ end
+ end
+end
diff --git a/spec/features/groups/share_lock_spec.rb b/spec/features/groups/share_lock_spec.rb
index 5bbe77019ca..704d9f12888 100644
--- a/spec/features/groups/share_lock_spec.rb
+++ b/spec/features/groups/share_lock_spec.rb
@@ -60,14 +60,14 @@ describe 'Group share with group lock' do
def enable_group_lock
page.within('.gs-permissions') do
check 'group_share_with_group_lock'
- click_on 'Save group'
+ click_on 'Save changes'
end
end
def disable_group_lock
page.within('.gs-permissions') do
uncheck 'group_share_with_group_lock'
- click_on 'Save group'
+ click_on 'Save changes'
end
end
end
diff --git a/spec/features/groups/show_spec.rb b/spec/features/groups/show_spec.rb
index ac961e98a61..4e6f73ef58a 100644
--- a/spec/features/groups/show_spec.rb
+++ b/spec/features/groups/show_spec.rb
@@ -101,4 +101,25 @@ describe 'Group show page' do
expect(page).to have_emoji('smile')
end
end
+
+ context 'where group has projects' do
+ let(:user) { create(:user) }
+
+ before do
+ group.add_owner(user)
+ sign_in(user)
+ end
+
+ it 'allows users to sorts projects by most stars', :js do
+ project1 = create(:project, namespace: group, star_count: 2)
+ project2 = create(:project, namespace: group, star_count: 3)
+ project3 = create(:project, namespace: group, star_count: 0)
+
+ visit group_path(group, sort: :stars_desc)
+
+ expect(find('.group-row:nth-child(1) .namespace-title > a')).to have_content(project2.title)
+ expect(find('.group-row:nth-child(2) .namespace-title > a')).to have_content(project1.title)
+ expect(find('.group-row:nth-child(3) .namespace-title > a')).to have_content(project3.title)
+ end
+ end
end
diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb
index e62bd6f8187..d01fc04311a 100644
--- a/spec/features/groups_spec.rb
+++ b/spec/features/groups_spec.rb
@@ -1,13 +1,15 @@
require 'spec_helper'
describe 'Group' do
+ let(:user) { create(:admin) }
+
before do
- sign_in(create(:admin))
+ sign_in(user)
end
matcher :have_namespace_error_message do
match do |page|
- page.has_content?("Path can contain only letters, digits, '_', '-' and '.'. Cannot start with '-' or end in '.', '.git' or '.atom'.")
+ page.has_content?("Group URL can contain only letters, digits, '_', '-' and '.'. Cannot start with '-' or end in '.', '.git' or '.atom'.")
end
end
@@ -16,9 +18,27 @@ describe 'Group' do
visit new_group_path
end
+ describe 'as a non-admin' do
+ let(:user) { create(:user) }
+
+ it 'creates a group and persists visibility radio selection', :js do
+ stub_application_setting(default_group_visibility: :private)
+
+ fill_in 'Group name', with: 'test-group'
+ find("input[name='group[visibility_level]'][value='#{Gitlab::VisibilityLevel::PUBLIC}']").click
+ click_button 'Create group'
+
+ group = Group.find_by(name: 'test-group')
+
+ expect(group.visibility_level).to eq(Gitlab::VisibilityLevel::PUBLIC)
+ expect(current_path).to eq(group_path(group))
+ expect(page).to have_selector '.visibility-icon .fa-globe'
+ end
+ end
+
describe 'with space in group path' do
it 'renders new group form with validation errors' do
- fill_in 'Group path', with: 'space group'
+ fill_in 'Group URL', with: 'space group'
click_button 'Create group'
expect(current_path).to eq(groups_path)
@@ -28,7 +48,7 @@ describe 'Group' do
describe 'with .atom at end of group path' do
it 'renders new group form with validation errors' do
- fill_in 'Group path', with: 'atom_group.atom'
+ fill_in 'Group URL', with: 'atom_group.atom'
click_button 'Create group'
expect(current_path).to eq(groups_path)
@@ -38,7 +58,7 @@ describe 'Group' do
describe 'with .git at end of group path' do
it 'renders new group form with validation errors' do
- fill_in 'Group path', with: 'git_group.git'
+ fill_in 'Group URL', with: 'git_group.git'
click_button 'Create group'
expect(current_path).to eq(groups_path)
@@ -94,7 +114,8 @@ describe 'Group' do
end
it 'creates a nested group' do
- fill_in 'Group path', with: 'bar'
+ fill_in 'Group name', with: 'bar'
+ fill_in 'Group URL', with: 'bar'
click_button 'Create group'
expect(current_path).to eq(group_path('foo/bar'))
@@ -112,7 +133,8 @@ describe 'Group' do
visit new_group_path(group, parent_id: group.id)
- fill_in 'Group path', with: 'bar'
+ fill_in 'Group name', with: 'bar'
+ fill_in 'Group URL', with: 'bar'
click_button 'Create group'
expect(current_path).to eq(group_path('foo/bar'))
@@ -140,10 +162,13 @@ describe 'Group' do
visit path
end
+ it_behaves_like 'dirty submit form', [{ form: '.js-general-settings-form', input: 'input[name="group[name]"]' },
+ { form: '.js-general-permissions-form', input: 'input[name="group[two_factor_grace_period]"]' }]
+
it 'saves new settings' do
page.within('.gs-general') do
fill_in 'group_name', with: new_name
- click_button 'Save group'
+ click_button 'Save changes'
end
expect(page).to have_content 'successfully updated'
diff --git a/spec/features/help_pages_spec.rb b/spec/features/help_pages_spec.rb
index 0d04ed612c2..c29dfb01381 100644
--- a/spec/features/help_pages_spec.rb
+++ b/spec/features/help_pages_spec.rb
@@ -4,7 +4,7 @@ describe 'Help Pages' do
describe 'Get the main help page' do
shared_examples_for 'help page' do |prefix: ''|
it 'prefixes links correctly' do
- expect(page).to have_selector(%(div.documentation-index > ul a[href="#{prefix}/help/api/README.md"]))
+ expect(page).to have_selector(%(div.documentation-index > table tbody tr td a[href="#{prefix}/help/api/README.md"]))
end
end
diff --git a/spec/features/import/manifest_import_spec.rb b/spec/features/import/manifest_import_spec.rb
index e381d073804..a90cdd8d920 100644
--- a/spec/features/import/manifest_import_spec.rb
+++ b/spec/features/import/manifest_import_spec.rb
@@ -22,7 +22,7 @@ describe 'Import multiple repositories by uploading a manifest file', :js, :post
expect(page).to have_content('https://android-review.googlesource.com/platform/build/blueprint')
end
- it 'imports succesfully imports a project' do
+ it 'imports successfully imports a project' do
visit new_import_manifest_path
attach_file('manifest', Rails.root.join('spec/fixtures/aosp_manifest.xml'))
diff --git a/spec/features/issuables/close_reopen_report_toggle_spec.rb b/spec/features/issuables/close_reopen_report_toggle_spec.rb
index de6f5fe1560..26c44baeb21 100644
--- a/spec/features/issuables/close_reopen_report_toggle_spec.rb
+++ b/spec/features/issuables/close_reopen_report_toggle_spec.rb
@@ -56,6 +56,24 @@ describe 'Issuables Close/Reopen/Report toggle' do
end
it_behaves_like 'an issuable close/reopen/report toggle'
+
+ context 'when the issue is closed and locked' do
+ let(:issuable) { create(:issue, :closed, :locked, project: project) }
+
+ it 'hides the reopen button' do
+ expect(page).not_to have_link('Reopen issue')
+ end
+
+ context 'when the issue author is the current user' do
+ before do
+ issuable.update(author: user)
+ end
+
+ it 'hides the reopen button' do
+ expect(page).not_to have_link('Reopen issue')
+ end
+ end
+ end
end
context 'when user doesnt have permission to update' do
@@ -93,6 +111,28 @@ describe 'Issuables Close/Reopen/Report toggle' do
end
it_behaves_like 'an issuable close/reopen/report toggle'
+
+ context 'when the merge request is merged' do
+ let(:issuable) { create(:merge_request, :merged, source_project: project) }
+
+ it 'shows only the `Report abuse` and `Edit` button' do
+ expect(page).to have_link('Report abuse')
+ expect(page).to have_link('Edit')
+ expect(page).not_to have_link('Close merge request')
+ expect(page).not_to have_link('Reopen merge request')
+ end
+
+ context 'when the merge request author is the current user' do
+ let(:issuable) { create(:merge_request, :merged, source_project: project, author: user) }
+
+ it 'shows only the `Edit` button' do
+ expect(page).to have_link('Edit')
+ expect(page).not_to have_link('Report abuse')
+ expect(page).not_to have_link('Close merge request')
+ expect(page).not_to have_link('Reopen merge request')
+ end
+ end
+ end
end
context 'when user doesnt have permission to update' do
diff --git a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
index d011d2545bb..e910fb54d23 100644
--- a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
@@ -156,13 +156,21 @@ describe 'Dropdown assignee', :js do
expect_filtered_search_input_empty
end
- it 'selects `no assignee`' do
- find('#js-dropdown-assignee .filter-dropdown-item', text: 'No Assignee').click
+ it 'selects `None`' do
+ find('#js-dropdown-assignee .filter-dropdown-item', text: 'None').click
expect(page).to have_css(js_dropdown_assignee, visible: false)
expect_tokens([assignee_token('none')])
expect_filtered_search_input_empty
end
+
+ it 'selects `Any`' do
+ find('#js-dropdown-assignee .filter-dropdown-item', text: 'Any').click
+
+ expect(page).to have_css(js_dropdown_assignee, visible: false)
+ expect_tokens([assignee_token('any')])
+ expect_filtered_search_input_empty
+ end
end
describe 'selecting from dropdown without Ajax call' do
diff --git a/spec/features/issues/filtered_search/dropdown_emoji_spec.rb b/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
index be229e8aa7d..97dd0afd002 100644
--- a/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_emoji_spec.rb
@@ -20,7 +20,7 @@ describe 'Dropdown emoji', :js do
end
def dropdown_emoji_size
- page.all('#js-dropdown-my-reaction .filter-dropdown .filter-dropdown-item').size
+ all('gl-emoji[data-name]').size
end
def click_emoji(text)
@@ -92,7 +92,7 @@ describe 'Dropdown emoji', :js do
it 'shows the most populated emoji at top of dropdown' do
send_keys_to_filtered_search('my-reaction:')
- expect(first('#js-dropdown-my-reaction li')).to have_content(award_emoji_star.name)
+ expect(first('#js-dropdown-my-reaction .filter-dropdown li')).to have_content(award_emoji_star.name)
end
end
@@ -121,13 +121,29 @@ describe 'Dropdown emoji', :js do
send_keys_to_filtered_search(':')
end
+ it 'selects `None`' do
+ find('#js-dropdown-my-reaction .filter-dropdown-item', text: 'None').click
+
+ expect(page).to have_css(js_dropdown_emoji, visible: false)
+ expect_tokens([reaction_token('none', false)])
+ expect_filtered_search_input_empty
+ end
+
+ it 'selects `Any`' do
+ find('#js-dropdown-my-reaction .filter-dropdown-item', text: 'Any').click
+
+ expect(page).to have_css(js_dropdown_emoji, visible: false)
+ expect_tokens([reaction_token('any', false)])
+ expect_filtered_search_input_empty
+ end
+
it 'fills in the my-reaction name' do
click_emoji('thumbsup')
wait_for_requests
expect(page).to have_css(js_dropdown_emoji, visible: false)
- expect_tokens([emoji_token('thumbsup')])
+ expect_tokens([reaction_token('thumbsup')])
expect_filtered_search_input_empty
end
end
diff --git a/spec/features/issues/filtered_search/dropdown_hint_spec.rb b/spec/features/issues/filtered_search/dropdown_hint_spec.rb
index b99c5a7f4e3..0e296ab2109 100644
--- a/spec/features/issues/filtered_search/dropdown_hint_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_hint_spec.rb
@@ -15,6 +15,7 @@ describe 'Dropdown hint', :js do
before do
project.add_maintainer(user)
create(:issue, project: project)
+ create(:merge_request, source_project: project, target_project: project)
end
context 'when user not logged in' do
@@ -224,4 +225,21 @@ describe 'Dropdown hint', :js do
end
end
end
+
+ context 'merge request page' do
+ before do
+ sign_in(user)
+ visit project_merge_requests_path(project)
+ filtered_search.click
+ end
+
+ it 'shows the WIP menu item and opens the WIP options dropdown' do
+ click_hint('wip')
+
+ expect(page).to have_css(js_dropdown_hint, visible: false)
+ expect(page).to have_css('#js-dropdown-wip', visible: true)
+ expect_tokens([{ name: 'wip' }])
+ expect_filtered_search_input_empty
+ end
+ end
end
diff --git a/spec/features/issues/filtered_search/dropdown_label_spec.rb b/spec/features/issues/filtered_search/dropdown_label_spec.rb
index ca5d506ab04..b25b1514d62 100644
--- a/spec/features/issues/filtered_search/dropdown_label_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_label_spec.rb
@@ -45,7 +45,8 @@ describe 'Dropdown label', :js do
bug_label = create(:label, project: project, title: 'bug-label')
init_label_search
- filtered_search.native.send_keys(:down, :down, :enter)
+ # navigate to the bug_label option and selects it
+ filtered_search.native.send_keys(:down, :down, :down, :enter)
expect_tokens([label_token(bug_label.title)])
expect_filtered_search_input_empty
@@ -234,12 +235,20 @@ describe 'Dropdown label', :js do
end
it 'selects `no label`' do
- find("#{js_dropdown_label} .filter-dropdown-item", text: 'No Label').click
+ find("#{js_dropdown_label} .filter-dropdown-item", text: 'None').click
expect(page).not_to have_css(js_dropdown_label)
expect_tokens([label_token('none', false)])
expect_filtered_search_input_empty
end
+
+ it 'selects `any label`' do
+ find("#{js_dropdown_label} .filter-dropdown-item", text: 'Any').click
+
+ expect(page).not_to have_css(js_dropdown_label)
+ expect_tokens([label_token('any', false)])
+ expect_filtered_search_input_empty
+ end
end
describe 'input has existing content' do
diff --git a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
index f76d30056da..ef5801e61e8 100644
--- a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
@@ -189,13 +189,21 @@ describe 'Dropdown milestone', :js do
end
it 'selects `no milestone`' do
- click_static_milestone('No Milestone')
+ click_static_milestone('None')
expect(page).to have_css(js_dropdown_milestone, visible: false)
expect_tokens([milestone_token('none', false)])
expect_filtered_search_input_empty
end
+ it 'selects `any milestone`' do
+ click_static_milestone('Any')
+
+ expect(page).to have_css(js_dropdown_milestone, visible: false)
+ expect_tokens([milestone_token('any', false)])
+ expect_filtered_search_input_empty
+ end
+
it 'selects `upcoming milestone`' do
click_static_milestone('Upcoming')
diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb
index 35d57b3896d..4d9b8262f21 100644
--- a/spec/features/issues/filtered_search/filter_issues_spec.rb
+++ b/spec/features/issues/filtered_search/filter_issues_spec.rb
@@ -430,10 +430,10 @@ describe 'Filter issues', :js do
expect_issues_list_count(2)
- sort_toggle = find('.filtered-search-wrapper .dropdown-toggle')
+ sort_toggle = find('.filter-dropdown-container .dropdown-menu-toggle')
sort_toggle.click
- find('.filtered-search-wrapper .dropdown-menu li a', text: 'Created date').click
+ find('.filter-dropdown-container .dropdown-menu li a', text: 'Created date').click
wait_for_requests
expect(find('.issues-list .issue:first-of-type .issue-title-text a')).to have_content(new_issue.title)
diff --git a/spec/features/issues/filtered_search/visual_tokens_spec.rb b/spec/features/issues/filtered_search/visual_tokens_spec.rb
index 6ac7ccd00f7..1e1dd5691ab 100644
--- a/spec/features/issues/filtered_search/visual_tokens_spec.rb
+++ b/spec/features/issues/filtered_search/visual_tokens_spec.rb
@@ -118,7 +118,7 @@ describe 'Visual tokens', :js do
describe 'selecting static option from dropdown' do
before do
- find("#js-dropdown-assignee").find('.filter-dropdown-item', text: 'No Assignee').click
+ find("#js-dropdown-assignee").find('.filter-dropdown-item', text: 'None').click
end
it 'changes value in visual token' do
diff --git a/spec/features/issues/form_spec.rb b/spec/features/issues/form_spec.rb
index 1456a2f0375..f2e4c5779df 100644
--- a/spec/features/issues/form_spec.rb
+++ b/spec/features/issues/form_spec.rb
@@ -27,7 +27,7 @@ describe 'New/edit issue', :js do
before do
# Using `allow_any_instance_of`/`and_wrap_original`, `original` would
# somehow refer to the very block we defined to _wrap_ that method, instead of
- # the original method, resulting in infinite recurison when called.
+ # the original method, resulting in infinite recursion when called.
# This is likely a bug with helper modules included into dynamically generated view classes.
# To work around this, we have to hold on to and call to the original implementation manually.
original_issue_dropdown_options = FormHelper.instance_method(:issue_assignees_dropdown_options)
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index 98e37d8011a..d7531d5fcd9 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -1,6 +1,10 @@
require 'rails_helper'
describe 'GFM autocomplete', :js do
+ let(:issue_xss_title) { 'This will execute alert<img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;' }
+ let(:user_xss_title) { 'eve <img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;' }
+
+ let(:user_xss) { create(:user, name: user_xss_title, username: 'xss.user') }
let(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') }
let(:project) { create(:project) }
let(:label) { create(:label, project: project, title: 'special+') }
@@ -8,13 +12,15 @@ describe 'GFM autocomplete', :js do
before do
project.add_maintainer(user)
+ project.add_maintainer(user_xss)
+
sign_in(user)
visit project_issue_path(project, issue)
wait_for_requests
end
- it 'updates issue descripton with GFM reference' do
+ it 'updates issue description with GFM reference' do
find('.js-issuable-edit').click
simulate_input('#issue-description', "@#{user.name[0...3]}")
@@ -34,6 +40,32 @@ describe 'GFM autocomplete', :js do
expect(page).to have_selector('.atwho-container')
end
+ it 'opens autocomplete menu for Issues when field starts with text with item escaping HTML characters' do
+ create(:issue, project: project, title: issue_xss_title)
+
+ page.within '.timeline-content-form' do
+ find('#note-body').native.send_keys('#')
+ end
+
+ expect(page).to have_selector('.atwho-container')
+
+ page.within '.atwho-container #at-view-issues' do
+ expect(page.all('li').first.text).to include(issue_xss_title)
+ end
+ end
+
+ it 'opens autocomplete menu for Username when field starts with text with item escaping HTML characters' do
+ page.within '.timeline-content-form' do
+ find('#note-body').native.send_keys('@ev')
+ end
+
+ expect(page).to have_selector('.atwho-container')
+
+ page.within '.atwho-container #at-view-users' do
+ expect(find('li').text).to have_content(user_xss.username)
+ end
+ end
+
it 'doesnt open autocomplete menu character is prefixed with text' do
page.within '.timeline-content-form' do
find('#note-body').native.send_keys('testing')
@@ -91,7 +123,7 @@ describe 'GFM autocomplete', :js do
wait_for_requests
- expect(find('#at-view-64')).to have_selector('.cur:first-of-type')
+ expect(find('#at-view-users')).to have_selector('.cur:first-of-type')
end
it 'includes items for assignee dropdowns with non-ASCII characters in name' do
@@ -104,7 +136,7 @@ describe 'GFM autocomplete', :js do
wait_for_requests
- expect(find('#at-view-64')).to have_content(user.name)
+ expect(find('#at-view-users')).to have_content(user.name)
end
it 'selects the first item for non-assignee dropdowns if a query is entered' do
@@ -301,6 +333,57 @@ describe 'GFM autocomplete', :js do
end
end
+ shared_examples 'autocomplete suggestions' do
+ it 'suggests objects correctly' do
+ page.within '.timeline-content-form' do
+ find('#note-body').native.send_keys(object.class.reference_prefix)
+ end
+
+ page.within '.atwho-container' do
+ expect(page).to have_content(object.title)
+
+ find('ul li').click
+ end
+
+ expect(find('.new-note #note-body').value).to include(expected_body)
+ end
+ end
+
+ context 'issues' do
+ let(:object) { issue }
+ let(:expected_body) { object.to_reference }
+
+ it_behaves_like 'autocomplete suggestions'
+ end
+
+ context 'merge requests' do
+ let(:object) { create(:merge_request, source_project: project) }
+ let(:expected_body) { object.to_reference }
+
+ it_behaves_like 'autocomplete suggestions'
+ end
+
+ context 'project snippets' do
+ let!(:object) { create(:project_snippet, project: project, title: 'code snippet') }
+ let(:expected_body) { object.to_reference }
+
+ it_behaves_like 'autocomplete suggestions'
+ end
+
+ context 'label' do
+ let!(:object) { label }
+ let(:expected_body) { object.title }
+
+ it_behaves_like 'autocomplete suggestions'
+ end
+
+ context 'milestone' do
+ let!(:object) { create(:milestone, project: project) }
+ let(:expected_body) { object.to_reference }
+
+ it_behaves_like 'autocomplete suggestions'
+ end
+
private
def expect_to_wrap(should_wrap, item, note, value)
diff --git a/spec/features/issues/issue_detail_spec.rb b/spec/features/issues/issue_detail_spec.rb
index 088ab114df3..76bc93e9766 100644
--- a/spec/features/issues/issue_detail_spec.rb
+++ b/spec/features/issues/issue_detail_spec.rb
@@ -18,6 +18,23 @@ describe 'Issue Detail', :js do
end
end
+ context 'when issue description has xss snippet' do
+ before do
+ issue.update!(description: '![xss" onload=alert(1);//](a)')
+ sign_in(user)
+ visit project_issue_path(project, issue)
+ wait_for_requests
+ end
+
+ it 'should encode the description to prevent xss issues' do
+ page.within('.issuable-details .detail-page-description') do
+ expect(page).to have_selector('img', count: 1)
+ expect(find('img')['onerror']).to be_nil
+ expect(find('img')['src']).to end_with('/a')
+ end
+ end
+ end
+
context 'when edited by a user who is later deleted' do
before do
sign_in(user)
diff --git a/spec/features/issues/notes_on_issues_spec.rb b/spec/features/issues/notes_on_issues_spec.rb
index f08c73f947c..fed77453cbb 100644
--- a/spec/features/issues/notes_on_issues_spec.rb
+++ b/spec/features/issues/notes_on_issues_spec.rb
@@ -3,6 +3,12 @@ require 'spec_helper'
describe 'Create notes on issues', :js do
let(:user) { create(:user) }
+ def submit_comment(text)
+ fill_in 'note[note]', with: text
+ click_button 'Comment'
+ wait_for_requests
+ end
+
shared_examples 'notes with reference' do
let(:issue) { create(:issue, project: project) }
let(:note_text) { "Check #{mention.to_reference}" }
@@ -12,10 +18,7 @@ describe 'Create notes on issues', :js do
sign_in(user)
visit project_issue_path(project, issue)
- fill_in 'note[note]', with: note_text
- click_button 'Comment'
-
- wait_for_requests
+ submit_comment(note_text)
end
it 'creates a note with reference and cross references the issue' do
@@ -74,4 +77,16 @@ describe 'Create notes on issues', :js do
let(:mention) { create(:merge_request, source_project: project) }
end
end
+
+ it 'highlights the current user in a comment' do
+ project = create(:project)
+ issue = create(:issue, project: project)
+ project.add_developer(user)
+ sign_in(user)
+
+ visit project_issue_path(project, issue)
+ submit_comment("@#{user.username} note to self")
+
+ expect(page).to have_selector '.gfm-project_member.current-user', text: user.username
+ end
end
diff --git a/spec/features/issues/resource_label_events_spec.rb b/spec/features/issues/resource_label_events_spec.rb
index 40c452c991a..b0764db7751 100644
--- a/spec/features/issues/resource_label_events_spec.rb
+++ b/spec/features/issues/resource_label_events_spec.rb
@@ -7,6 +7,7 @@ describe 'List issue resource label events', :js do
let(:project) { create(:project, :public) }
let(:issue) { create(:issue, project: project, author: user) }
let!(:label) { create(:label, project: project, title: 'foo') }
+ let!(:user_status) { create(:user_status, user: user) }
context 'when user displays the issue' do
let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue, note: 'some note') }
@@ -23,6 +24,12 @@ describe 'List issue resource label events', :js do
expect(find("#note_#{event.discussion_id}")).to have_content 'added foo label'
end
end
+
+ it 'shows the user status on the system note for the label' do
+ page.within("#note_#{event.discussion_id}") do
+ expect(page).to show_user_status user_status
+ end
+ end
end
context 'when user adds label to the issue' do
diff --git a/spec/features/issues/user_comments_on_issue_spec.rb b/spec/features/issues/user_comments_on_issue_spec.rb
index ba5b80ed04b..b4b9a589ba3 100644
--- a/spec/features/issues/user_comments_on_issue_spec.rb
+++ b/spec/features/issues/user_comments_on_issue_spec.rb
@@ -40,6 +40,18 @@ describe "User comments on issue", :js do
expect(page.find('pre code').text).to eq code_block_content
end
+
+ it "does not render html content in mermaid" do
+ html_content = "<img onerror=location=`javascript\\u003aalert\\u0028document.domain\\u0029` src=x>"
+ mermaid_content = "graph LR\n B-->D(#{html_content});"
+ comment = "```mermaid\n#{mermaid_content}\n```"
+
+ add_note(comment)
+
+ wait_for_requests
+
+ expect(page.find('svg.mermaid')).to have_content html_content
+ end
end
context "when editing comments" do
diff --git a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
index 3dfcbc2fcb8..32bc851f00f 100644
--- a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
+++ b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
@@ -55,11 +55,11 @@ describe 'User creates branch and merge request on issue page', :js do
test_branch_name_checking(input_branch_name)
test_source_checking(input_source)
- # The button inside dropdown should be disabled if any errors occured.
+ # The button inside dropdown should be disabled if any errors occurred.
expect(page).to have_button('Create branch', disabled: true)
end
- # The top level button should be disabled if any errors occured.
+ # The top level button should be disabled if any errors occurred.
expect(page).to have_button('Create branch', disabled: true)
end
@@ -76,7 +76,7 @@ describe 'User creates branch and merge request on issue page', :js do
visit project_issue_path(project, issue)
- expect(page).to have_content('created branch 1-cherry-coloured-funk')
+ expect(page).to have_content("created merge request !1 to address this issue")
expect(page).to have_content('mentioned in merge request !1')
end
@@ -106,7 +106,7 @@ describe 'User creates branch and merge request on issue page', :js do
visit project_issue_path(project, issue)
- expect(page).to have_content('created branch custom-branch-name')
+ expect(page).to have_content("created merge request !1 to address this issue")
expect(page).to have_content('mentioned in merge request !1')
end
diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb
index 5e8662100c5..687a6f1eafc 100644
--- a/spec/features/issues/user_creates_issue_spec.rb
+++ b/spec/features/issues/user_creates_issue_spec.rb
@@ -47,15 +47,15 @@ describe "User creates issue" do
textarea = first(".gfm-form textarea")
page.within(form) do
- click_link("Preview")
+ click_button("Preview")
preview = find(".js-md-preview") # this element is findable only when the "Preview" link is clicked.
expect(preview).to have_content("Nothing to preview.")
- click_link("Write")
+ click_button("Write")
fill_in("Description", with: "Bug fixed :smile:")
- click_link("Preview")
+ click_button("Preview")
expect(preview).to have_css("gl-emoji")
expect(textarea).not_to be_visible
diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb
index 1d9c3abc20f..60b88ef4bdf 100644
--- a/spec/features/issues/user_edits_issue_spec.rb
+++ b/spec/features/issues/user_edits_issue_spec.rb
@@ -17,9 +17,9 @@ describe "User edits issue", :js do
page.within(form) do
fill_in("Description", with: "Bug fixed :smile:")
- click_link("Preview")
+ click_button("Preview")
end
- expect(form).to have_link("Write")
+ expect(form).to have_button("Write")
end
end
diff --git a/spec/features/issues/user_sees_breadcrumb_links_spec.rb b/spec/features/issues/user_sees_breadcrumb_links_spec.rb
index ca234321235..43369f7609f 100644
--- a/spec/features/issues/user_sees_breadcrumb_links_spec.rb
+++ b/spec/features/issues/user_sees_breadcrumb_links_spec.rb
@@ -1,15 +1,15 @@
require 'rails_helper'
-describe 'New issue breadcrumbs' do
+describe 'New issue breadcrumb' do
let(:project) { create(:project) }
- let(:user) { project.creator }
+ let(:user) { project.creator }
before do
sign_in(user)
- visit new_project_issue_path(project)
+ visit(new_project_issue_path(project))
end
- it 'display a link to project issues and new issue pages' do
+ it 'displays link to project issues and new issue' do
page.within '.breadcrumbs' do
expect(find_link('Issues')[:href]).to end_with(project_issues_path(project))
expect(find_link('New')[:href]).to end_with(new_project_issue_path(project))
diff --git a/spec/features/issues/user_sorts_issues_spec.rb b/spec/features/issues/user_sorts_issues_spec.rb
index 7d261ec7dae..3bc93933183 100644
--- a/spec/features/issues/user_sorts_issues_spec.rb
+++ b/spec/features/issues/user_sorts_issues_spec.rb
@@ -20,13 +20,13 @@ describe "User sorts issues" do
end
it 'keeps the sort option' do
- find('button.dropdown-toggle').click
+ find('.filter-dropdown-container button.dropdown-menu-toggle').click
page.within('.content ul.dropdown-menu.dropdown-menu-right li') do
click_link('Milestone')
end
- visit(issues_dashboard_path(assignee_id: user.id))
+ visit(issues_dashboard_path(assignee_username: user.username))
expect(find('.issues-filters a.is-active')).to have_content('Milestone')
@@ -40,7 +40,7 @@ describe "User sorts issues" do
end
it "sorts by popularity" do
- find("button.dropdown-toggle").click
+ find(".filter-dropdown-container button.dropdown-menu-toggle").click
page.within(".content ul.dropdown-menu.dropdown-menu-right li") do
click_link("Popularity")
diff --git a/spec/features/issues/user_uses_quick_actions_spec.rb b/spec/features/issues/user_uses_quick_actions_spec.rb
index 5926e442f24..27cffdc5f8b 100644
--- a/spec/features/issues/user_uses_quick_actions_spec.rb
+++ b/spec/features/issues/user_uses_quick_actions_spec.rb
@@ -303,5 +303,63 @@ describe 'Issues > User uses quick actions', :js do
end
end
end
+
+ describe 'create a merge request starting from an issue' do
+ let(:project) { create(:project, :public, :repository) }
+ let(:issue) { create(:issue, project: project) }
+
+ def expect_mr_quickaction(success)
+ expect(page).to have_content 'Commands applied'
+
+ if success
+ expect(page).to have_content 'created merge request'
+ else
+ expect(page).not_to have_content 'created merge request'
+ end
+ end
+
+ it "doesn't create a merge request when the branch name is invalid" do
+ add_note("/create_merge_request invalid branch name")
+
+ wait_for_requests
+
+ expect_mr_quickaction(false)
+ end
+
+ it "doesn't create a merge request when a branch with that name already exists" do
+ add_note("/create_merge_request feature")
+
+ wait_for_requests
+
+ expect_mr_quickaction(false)
+ end
+
+ it 'creates a new merge request using issue iid and title as branch name when the branch name is empty' do
+ add_note("/create_merge_request")
+
+ wait_for_requests
+
+ expect_mr_quickaction(true)
+
+ created_mr = project.merge_requests.last
+ expect(created_mr.source_branch).to eq(issue.to_branch_name)
+
+ visit project_merge_request_path(project, created_mr)
+ expect(page).to have_content %{WIP: Resolve "#{issue.title}"}
+ end
+
+ it 'creates a merge request using the given branch name' do
+ branch_name = '1-feature'
+ add_note("/create_merge_request #{branch_name}")
+
+ expect_mr_quickaction(true)
+
+ created_mr = project.merge_requests.last
+ expect(created_mr.source_branch).to eq(branch_name)
+
+ visit project_merge_request_path(project, created_mr)
+ expect(page).to have_content %{WIP: Resolve "#{issue.title}"}
+ end
+ end
end
end
diff --git a/spec/features/issues/user_views_issue_spec.rb b/spec/features/issues/user_views_issue_spec.rb
index 117e5986f29..330b6f0e77a 100644
--- a/spec/features/issues/user_views_issue_spec.rb
+++ b/spec/features/issues/user_views_issue_spec.rb
@@ -1,9 +1,9 @@
require "spec_helper"
describe "User views issue" do
- set(:project) { create(:project_empty_repo, :public) }
- set(:user) { create(:user) }
- set(:issue) { create(:issue, project: project, description: "# Description header", author: user) }
+ let(:project) { create(:project_empty_repo, :public) }
+ let(:user) { create(:user) }
+ let(:issue) { create(:issue, project: project, description: "# Description header", author: user) }
before do
project.add_developer(user)
diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb
index 4d9b8a10e04..406e80e91aa 100644
--- a/spec/features/issues_spec.rb
+++ b/spec/features/issues_spec.rb
@@ -8,6 +8,17 @@ describe 'Issues' do
let(:user) { create(:user) }
let(:project) { create(:project, :public) }
+ shared_examples_for 'empty state with filters' do
+ it 'user sees empty state with filters' do
+ create(:issue, author: user, project: project)
+
+ visit project_issues_path(project, milestone_title: "1.0")
+
+ expect(page).to have_content('Sorry, your filter produced no results')
+ expect(page).to have_content('To widen your search, change or remove filters above')
+ end
+ end
+
describe 'while user is signed out' do
describe 'empty state' do
it 'user sees empty state' do
@@ -17,6 +28,8 @@ describe 'Issues' do
expect(page).to have_content('The Issue Tracker is the place to add things that need to be improved or solved in a project.')
expect(page).to have_content('You can register or sign in to create issues for this project.')
end
+
+ it_behaves_like 'empty state with filters'
end
end
@@ -37,6 +50,8 @@ describe 'Issues' do
expect(page).to have_content('Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable.')
expect(page).to have_content('New issue')
end
+
+ it_behaves_like 'empty state with filters'
end
describe 'Edit issue' do
@@ -667,6 +682,18 @@ describe 'Issues' do
expect(find('.js-issuable-selector .dropdown-toggle-text')).to have_content('bug')
end
end
+
+ context 'suggestions', :js do
+ it 'displays list of related issues' do
+ create(:issue, project: project, title: 'test issue')
+
+ visit new_project_issue_path(project)
+
+ fill_in 'issue_title', with: issue.title
+
+ expect(page).to have_selector('.suggestion-item', count: 1)
+ end
+ end
end
describe 'new issue by email' do
diff --git a/spec/features/markdown/markdown_spec.rb b/spec/features/markdown/markdown_spec.rb
index cac8a5068ec..3b37ede8579 100644
--- a/spec/features/markdown/markdown_spec.rb
+++ b/spec/features/markdown/markdown_spec.rb
@@ -264,9 +264,9 @@ describe 'GitLab Markdown', :aggregate_failures do
@project_wiki = @feat.project_wiki
@project_wiki_page = @feat.project_wiki_page
- file = Gollum::File.new(@project_wiki.wiki)
- expect(file).to receive(:path).and_return('images/example.jpg')
- expect(@project_wiki).to receive(:find_file).with('images/example.jpg').and_return(file)
+ path = 'images/example.jpg'
+ gitaly_wiki_file = Gitlab::GitalyClient::WikiFile.new(path: path)
+ expect(@project_wiki).to receive(:find_file).with(path).and_return(Gitlab::Git::WikiFile.new(gitaly_wiki_file))
allow(@project_wiki).to receive(:wiki_base_path) { '/namespace1/gitlabhq/wikis' }
@html = markdown(@feat.raw_markdown, { pipeline: :wiki, project_wiki: @project_wiki, page_slug: @project_wiki_page.slug })
diff --git a/spec/features/markdown/mermaid_spec.rb b/spec/features/markdown/mermaid_spec.rb
index a25d701ee35..7008b361394 100644
--- a/spec/features/markdown/mermaid_spec.rb
+++ b/spec/features/markdown/mermaid_spec.rb
@@ -18,7 +18,7 @@ describe 'Mermaid rendering', :js do
visit project_issue_path(project, issue)
%w[A B C D].each do |label|
- expect(page).to have_selector('svg foreignObject', text: label)
+ expect(page).to have_selector('svg text', text: label)
end
end
end
diff --git a/spec/features/merge_request/user_assigns_themselves_spec.rb b/spec/features/merge_request/user_assigns_themselves_spec.rb
index b6b38186a22..41cc7cef777 100644
--- a/spec/features/merge_request/user_assigns_themselves_spec.rb
+++ b/spec/features/merge_request/user_assigns_themselves_spec.rb
@@ -42,7 +42,7 @@ describe 'Merge request > User assigns themselves' do
visit project_merge_request_path(project, merge_request)
end
- it 'does not not show assignment link' do
+ it 'does not show assignment link' do
expect(page).not_to have_content 'Assign yourself'
end
end
diff --git a/spec/features/merge_request/user_comments_on_diff_spec.rb b/spec/features/merge_request/user_comments_on_diff_spec.rb
index 441b080bee5..00cf368e8c9 100644
--- a/spec/features/merge_request/user_comments_on_diff_spec.rb
+++ b/spec/features/merge_request/user_comments_on_diff_spec.rb
@@ -28,7 +28,7 @@ describe 'User comments on a diff', :js do
click_button('Comment')
end
- page.within('.files > div:nth-child(3)') do
+ page.within('.diff-files-holder > div:nth-child(3)') do
expect(page).to have_content('Line is wrong')
find('.js-btn-vue-toggle-comments').click
@@ -49,7 +49,7 @@ describe 'User comments on a diff', :js do
wait_for_requests
- page.within('.files > div:nth-child(2) .note-body > .note-text') do
+ page.within('.diff-files-holder > div:nth-child(2) .note-body > .note-text') do
expect(page).to have_content('Line is correct')
end
@@ -63,7 +63,7 @@ describe 'User comments on a diff', :js do
wait_for_requests
# Hide the comment.
- page.within('.files > div:nth-child(3)') do
+ page.within('.diff-files-holder > div:nth-child(3)') do
find('.js-btn-vue-toggle-comments').click
expect(page).not_to have_content('Line is wrong')
@@ -71,21 +71,21 @@ describe 'User comments on a diff', :js do
# At this moment a user should see only one comment.
# The other one should be hidden.
- page.within('.files > div:nth-child(2) .note-body > .note-text') do
+ page.within('.diff-files-holder > div:nth-child(2) .note-body > .note-text') do
expect(page).to have_content('Line is correct')
end
# Show the comment.
- page.within('.files > div:nth-child(3)') do
+ page.within('.diff-files-holder > div:nth-child(3)') do
find('.js-btn-vue-toggle-comments').click
end
# Now both the comments should be shown.
- page.within('.files > div:nth-child(3) .note-body > .note-text') do
+ page.within('.diff-files-holder > div:nth-child(3) .note-body > .note-text') do
expect(page).to have_content('Line is wrong')
end
- page.within('.files > div:nth-child(2) .note-body > .note-text') do
+ page.within('.diff-files-holder > div:nth-child(2) .note-body > .note-text') do
expect(page).to have_content('Line is correct')
end
@@ -95,11 +95,11 @@ describe 'User comments on a diff', :js do
wait_for_requests
- page.within('.files > div:nth-child(3) .parallel .note-body > .note-text') do
+ page.within('.diff-files-holder > div:nth-child(3) .parallel .note-body > .note-text') do
expect(page).to have_content('Line is wrong')
end
- page.within('.files > div:nth-child(2) .parallel .note-body > .note-text') do
+ page.within('.diff-files-holder > div:nth-child(2) .parallel .note-body > .note-text') do
expect(page).to have_content('Line is correct')
end
end
diff --git a/spec/features/merge_request/user_creates_image_diff_notes_spec.rb b/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
index f0d38dc6a0c..d790bdc82ce 100644
--- a/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_creates_image_diff_notes_spec.rb
@@ -114,10 +114,9 @@ describe 'Merge request > User creates image diff notes', :js do
create_image_diff_note
end
- # TODO: https://gitlab.com/gitlab-org/gitlab-ce/issues/48034
- xit 'shows indicator and avatar badges, and allows collapsing/expanding the discussion notes' do
+ it 'shows indicator and avatar badges, and allows collapsing/expanding the discussion notes' do
indicator = find('.js-image-badge', match: :first)
- badge = find('.image-diff-avatar-link .badge', match: :first)
+ badge = find('.user-avatar-link .badge', match: :first)
expect(indicator).to have_content('1')
expect(badge).to have_content('1')
@@ -157,8 +156,7 @@ describe 'Merge request > User creates image diff notes', :js do
visit project_merge_request_path(project, merge_request)
end
- # TODO: https://gitlab.com/gitlab-org/gitlab-ce/issues/48034
- xit 'render diff indicators within the image frame' do
+ it 'render diff indicators within the image frame' do
diff_note = create(:diff_note_on_merge_request, project: project, noteable: merge_request, position: position)
wait_for_requests
@@ -200,7 +198,6 @@ describe 'Merge request > User creates image diff notes', :js do
def create_image_diff_note
find('.js-add-image-diff-note-button', match: :first).click
- page.all('.js-add-image-diff-note-button')[0].click
find('.diff-content .note-textarea').native.send_keys('image diff test comment')
click_button 'Comment'
wait_for_requests
diff --git a/spec/features/merge_request/user_creates_mr_spec.rb b/spec/features/merge_request/user_creates_mr_spec.rb
index 1ac31de62cb..9d2a94a4a41 100644
--- a/spec/features/merge_request/user_creates_mr_spec.rb
+++ b/spec/features/merge_request/user_creates_mr_spec.rb
@@ -28,4 +28,29 @@ describe 'Merge request > User creates MR' do
it_behaves_like 'a creatable merge request'
end
end
+
+ context 'source project', :js do
+ let(:user) { create(:user) }
+ let(:target_project) { create(:project, :public, :repository) }
+ let(:source_project) { target_project }
+
+ before do
+ source_project.add_maintainer(user)
+
+ sign_in(user)
+ visit project_new_merge_request_path(
+ target_project,
+ merge_request: {
+ source_project_id: source_project.id,
+ target_project_id: target_project.id
+ })
+ end
+
+ it 'filters source project' do
+ find('.js-source-project').click
+ find('.dropdown-source-project input').set('source')
+
+ expect(find('.dropdown-source-project .dropdown-content')).not_to have_content(source_project.name)
+ end
+ end
end
diff --git a/spec/features/merge_request/user_edits_mr_spec.rb b/spec/features/merge_request/user_edits_mr_spec.rb
index 8c9e782aa76..3152707136c 100644
--- a/spec/features/merge_request/user_edits_mr_spec.rb
+++ b/spec/features/merge_request/user_edits_mr_spec.rb
@@ -1,11 +1,13 @@
require 'rails_helper'
describe 'Merge request > User edits MR' do
+ include ProjectForksHelper
+
it_behaves_like 'an editable merge request'
context 'for a forked project' do
it_behaves_like 'an editable merge request' do
- let(:source_project) { create(:project, :repository, forked_from_project: target_project) }
+ let(:source_project) { fork_project(target_project, nil, repository: true) }
end
end
end
diff --git a/spec/features/merge_request/user_posts_diff_notes_spec.rb b/spec/features/merge_request/user_posts_diff_notes_spec.rb
index fa148715855..51b78d3e7d1 100644
--- a/spec/features/merge_request/user_posts_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb
@@ -85,12 +85,13 @@ describe 'Merge request > User posts diff notes', :js do
# `.line_holder` will be an unfolded line.
let(:line_holder) { first('#a5cc2925ca8258af241be7e5b0381edf30266302 .line_holder') }
- it 'does not allow commenting on the left side' do
- should_not_allow_commenting(line_holder, 'left')
+ it 'allows commenting on the left side' do
+ should_allow_commenting(line_holder, 'left')
end
- it 'does not allow commenting on the right side' do
- should_not_allow_commenting(line_holder, 'right')
+ it 'allows commenting on the right side' do
+ # Automatically shifts comment box to left side.
+ should_allow_commenting(line_holder, 'right')
end
end
end
@@ -147,8 +148,8 @@ describe 'Merge request > User posts diff notes', :js do
# `.line_holder` will be an unfolded line.
let(:line_holder) { first('.line_holder[id="a5cc2925ca8258af241be7e5b0381edf30266302_1_1"]') }
- it 'does not allow commenting' do
- should_not_allow_commenting line_holder
+ it 'allows commenting' do
+ should_allow_commenting line_holder
end
end
diff --git a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
index 2d268ecab58..328f96e6ed7 100644
--- a/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
+++ b/spec/features/merge_request/user_resolves_diff_notes_and_discussions_resolve_spec.rb
@@ -50,7 +50,7 @@ describe 'Merge request > User resolves diff notes and discussions', :js do
find('.line-resolve-btn').click
expect(page).to have_selector('.line-resolve-btn.is-active')
- expect(find('.line-resolve-btn')['data-original-title']).to eq("Resolved by #{user.name}")
+ expect(find('.line-resolve-btn')['aria-label']).to eq("Resolved by #{user.name}")
end
page.within '.diff-content' do
@@ -139,44 +139,64 @@ describe 'Merge request > User resolves diff notes and discussions', :js do
expect(find('.diffs .diff-file .notes_holder')).to be_visible
end
end
- end
- it 'allows user to resolve from reply form without a comment' do
- page.within '.diff-content' do
- click_button 'Reply...'
+ describe 'reply form' do
+ before do
+ click_button 'Toggle discussion'
- click_button 'Resolve discussion'
- end
+ page.within '.diff-content' do
+ click_button 'Reply...'
+ end
+ end
- page.within '.line-resolve-all-container' do
- expect(page).to have_content('1/1 discussion resolved')
- expect(page).to have_selector('.line-resolve-btn.is-active')
- end
- end
+ it 'allows user to comment' do
+ page.within '.diff-content' do
+ find('.js-note-text').set 'testing'
- it 'allows user to unresolve from reply form without a comment' do
- page.within '.diff-content' do
- click_button 'Resolve discussion'
- sleep 1
+ click_button 'Comment'
- click_button 'Reply...'
+ wait_for_requests
+ end
- click_button 'Unresolve discussion'
- end
+ page.within '.line-resolve-all-container' do
+ expect(page).to have_content('1/1 discussion resolved')
+ end
+ end
- page.within '.line-resolve-all-container' do
- expect(page).to have_content('0/1 discussion resolved')
- expect(page).not_to have_selector('.line-resolve-btn.is-active')
+ it 'allows user to unresolve from reply form without a comment' do
+ page.within '.diff-content' do
+ click_button 'Unresolve discussion'
+
+ wait_for_requests
+ end
+
+ page.within '.line-resolve-all-container' do
+ expect(page).to have_content('0/1 discussion resolved')
+ expect(page).not_to have_selector('.line-resolve-btn.is-active')
+ end
+ end
+
+ it 'allows user to comment & unresolve discussion' do
+ page.within '.diff-content' do
+ find('.js-note-text').set 'testing'
+
+ click_button 'Comment & unresolve discussion'
+
+ wait_for_requests
+ end
+
+ page.within '.line-resolve-all-container' do
+ expect(page).to have_content('0/1 discussion resolved')
+ end
+ end
end
end
- it 'allows user to comment & resolve discussion' do
+ it 'allows user to resolve from reply form without a comment' do
page.within '.diff-content' do
click_button 'Reply...'
- find('.js-note-text').set 'testing'
-
- click_button 'Comment & resolve discussion'
+ click_button 'Resolve discussion'
end
page.within '.line-resolve-all-container' do
@@ -185,19 +205,18 @@ describe 'Merge request > User resolves diff notes and discussions', :js do
end
end
- it 'allows user to comment & unresolve discussion' do
+ it 'allows user to comment & resolve discussion' do
page.within '.diff-content' do
- click_button 'Resolve discussion'
-
click_button 'Reply...'
find('.js-note-text').set 'testing'
- click_button 'Comment & unresolve discussion'
+ click_button 'Comment & resolve discussion'
end
page.within '.line-resolve-all-container' do
- expect(page).to have_content('0/1 discussion resolved')
+ expect(page).to have_content('1/1 discussion resolved')
+ expect(page).to have_selector('.line-resolve-btn.is-active')
end
end
@@ -224,7 +243,7 @@ describe 'Merge request > User resolves diff notes and discussions', :js do
resolve_button.click
wait_for_requests
- expect(resolve_button['data-original-title']).to eq("Resolved by #{user.name}")
+ expect(resolve_button['aria-label']).to eq("Resolved by #{user.name}")
end
end
@@ -247,7 +266,7 @@ describe 'Merge request > User resolves diff notes and discussions', :js do
wait_for_requests
- expect(first('.line-resolve-btn')['data-original-title']).to eq("Resolved by #{user.name}")
+ expect(first('.line-resolve-btn')['aria-label']).to eq("Resolved by #{user.name}")
end
expect(page).to have_content('Last updated')
@@ -266,7 +285,7 @@ describe 'Merge request > User resolves diff notes and discussions', :js do
wait_for_requests
resolve_buttons.each do |button|
- expect(button['data-original-title']).to eq("Resolved by #{user.name}")
+ expect(button['aria-label']).to eq("Resolved by #{user.name}")
end
page.within '.line-resolve-all-container' do
@@ -306,7 +325,7 @@ describe 'Merge request > User resolves diff notes and discussions', :js do
end
end
- it 'allows user user to mark all discussions as resolved' do
+ it 'allows user to mark all discussions as resolved' do
page.all('.discussion-reply-holder', count: 2).each do |reply_holder|
page.within reply_holder do
click_button 'Resolve discussion'
@@ -338,13 +357,12 @@ describe 'Merge request > User resolves diff notes and discussions', :js do
resolve_button.click
wait_for_requests
- expect(resolve_button['data-original-title']).to eq("Resolved by #{user.name}")
+ expect(resolve_button['aria-label']).to eq("Resolved by #{user.name}")
end
end
- it 'shows jump to next discussion button, apart from the last one' do
- expect(page).to have_selector('.discussion-reply-holder', count: 2)
- expect(page).to have_selector('.discussion-reply-holder .discussion-next-btn', count: 1)
+ it 'shows jump to next discussion button' do
+ expect(page.all('.discussion-reply-holder', count: 2)).to all(have_selector('.discussion-next-btn'))
end
it 'displays next discussion even if hidden' do
diff --git a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
index 428eb414274..b58c433bbfe 100644
--- a/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_sees_avatar_on_diff_notes_spec.rb
@@ -81,22 +81,25 @@ describe 'Merge request > User sees avatars on diff notes', :js do
visit diffs_project_merge_request_path(project, merge_request, view: view)
wait_for_requests
+
+ find('.js-toggle-tree-list').click
end
it 'shows note avatar' do
page.within find_line(position.line_code(project.repository)) do
find('.diff-notes-collapse').send_keys(:return)
- expect(page).to have_selector('img.js-diff-comment-avatar', count: 1)
+ expect(page).to have_selector('.js-diff-comment-avatar img', count: 1)
end
end
it 'shows comment on note avatar' do
page.within find_line(position.line_code(project.repository)) do
find('.diff-notes-collapse').send_keys(:return)
-
- expect(first('img.js-diff-comment-avatar')["data-original-title"]).to eq("#{note.author.name}: #{note.note.truncate(17)}")
+ first('.js-diff-comment-avatar img').hover
end
+
+ expect(page).to have_content "#{note.author.name}: #{note.note.truncate(17)}"
end
it 'toggles comments when clicking avatar' do
@@ -107,7 +110,7 @@ describe 'Merge request > User sees avatars on diff notes', :js do
expect(page).not_to have_selector('.notes_holder')
page.within find_line(position.line_code(project.repository)) do
- first('img.js-diff-comment-avatar').click
+ first('.js-diff-comment-avatar img').click
end
expect(page).to have_selector('.notes_holder')
@@ -123,7 +126,7 @@ describe 'Merge request > User sees avatars on diff notes', :js do
wait_for_requests
page.within find_line(position.line_code(project.repository)) do
- expect(page).not_to have_selector('img.js-diff-comment-avatar')
+ expect(page).not_to have_selector('.js-diff-comment-avatar img')
end
end
@@ -141,7 +144,7 @@ describe 'Merge request > User sees avatars on diff notes', :js do
page.within find_line(position.line_code(project.repository)) do
find('.diff-notes-collapse').send_keys(:return)
- expect(page).to have_selector('img.js-diff-comment-avatar', count: 2)
+ expect(page).to have_selector('.js-diff-comment-avatar img', count: 2)
end
end
@@ -160,7 +163,7 @@ describe 'Merge request > User sees avatars on diff notes', :js do
page.within find_line(position.line_code(project.repository)) do
find('.diff-notes-collapse').send_keys(:return)
- expect(page).to have_selector('img.js-diff-comment-avatar', count: 3)
+ expect(page).to have_selector('.js-diff-comment-avatar img', count: 3)
expect(find('.diff-comments-more-count')).to have_content '+1'
end
end
diff --git a/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb b/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb
index f17acb35a5a..18d204da17a 100644
--- a/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb
+++ b/spec/features/merge_request/user_sees_breadcrumb_links_spec.rb
@@ -1,15 +1,15 @@
require 'rails_helper'
-describe 'New merge request breadcrumbs' do
+describe 'New merge request breadcrumb' do
let(:project) { create(:project, :repository) }
- let(:user) { project.creator }
+ let(:user) { project.creator }
before do
sign_in(user)
- visit project_new_merge_request_path(project)
+ visit(project_new_merge_request_path(project))
end
- it 'display a link to project merge requests and new merge request pages' do
+ it 'displays link to project merge requests and new merge request' do
page.within '.breadcrumbs' do
expect(find_link('Merge Requests')[:href]).to end_with(project_merge_requests_path(project))
expect(find_link('New')[:href]).to end_with(project_new_merge_request_path(project))
diff --git a/spec/features/merge_request/user_sees_deployment_widget_spec.rb b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
index f744d7941f5..fe8e0b07d39 100644
--- a/spec/features/merge_request/user_sees_deployment_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
@@ -1,45 +1,117 @@
require 'rails_helper'
describe 'Merge request > User sees deployment widget', :js do
- describe 'when deployed to an environment' do
+ describe 'when merge request has associated environments' do
let(:user) { create(:user) }
- let(:project) { merge_request.target_project }
- let(:merge_request) { create(:merge_request, :merged) }
+ let(:project) { create(:project, :repository) }
+ let(:merge_request) { create(:merge_request, :merged, source_project: project) }
let(:environment) { create(:environment, project: project) }
let(:role) { :developer }
- let(:sha) { project.commit('master').id }
- let!(:deployment) { create(:deployment, environment: environment, sha: sha) }
+ let(:ref) { merge_request.target_branch }
+ let(:sha) { project.commit(ref).id }
+ let(:pipeline) { create(:ci_pipeline_without_jobs, sha: sha, project: project, ref: ref) }
let!(:manual) { }
before do
+ merge_request.update!(merge_commit_sha: sha)
project.add_user(user, role)
sign_in(user)
- visit project_merge_request_path(project, merge_request)
- wait_for_requests
end
- it 'displays that the environment is deployed' do
- wait_for_requests
+ context 'when deployment succeeded' do
+ let(:build) { create(:ci_build, :success, pipeline: pipeline) }
+ let!(:deployment) { create(:deployment, :succeed, environment: environment, sha: sha, ref: ref, deployable: build) }
- expect(page).to have_content("Deployed to #{environment.name}")
- expect(find('.js-deploy-time')['data-original-title']).to eq(deployment.created_at.to_time.in_time_zone.to_s(:medium))
+ it 'displays that the environment is deployed' do
+ visit project_merge_request_path(project, merge_request)
+ wait_for_requests
+
+ expect(page).to have_content("Deployed to #{environment.name}")
+ expect(find('.js-deploy-time')['data-original-title']).to eq(deployment.created_at.to_time.in_time_zone.to_s(:medium))
+ end
+
+ context 'when a user created a new merge request with the same SHA' do
+ let(:pipeline2) { create(:ci_pipeline_without_jobs, sha: sha, project: project, ref: 'new-patch-1') }
+ let(:build2) { create(:ci_build, :success, pipeline: pipeline2) }
+ let(:environment2) { create(:environment, project: project) }
+ let!(:deployment2) { create(:deployment, environment: environment2, sha: sha, ref: 'new-patch-1', deployable: build2) }
+
+ it 'displays one environment which is related to the pipeline' do
+ visit project_merge_request_path(project, merge_request)
+ wait_for_requests
+
+ expect(page).to have_selector('.js-deployment-info', count: 1)
+ expect(page).to have_content("#{environment.name}")
+ expect(page).not_to have_content("#{environment2.name}")
+ end
+ end
+ end
+
+ context 'when deployment failed' do
+ let(:build) { create(:ci_build, :failed, pipeline: pipeline) }
+ let!(:deployment) { create(:deployment, :failed, environment: environment, sha: sha, ref: ref, deployable: build) }
+
+ it 'displays that the deployment failed' do
+ visit project_merge_request_path(project, merge_request)
+ wait_for_requests
+
+ expect(page).to have_content("Failed to deploy to #{environment.name}")
+ expect(page).not_to have_css('.js-deploy-time')
+ end
+ end
+
+ context 'when deployment running' do
+ let(:build) { create(:ci_build, :running, pipeline: pipeline) }
+ let!(:deployment) { create(:deployment, :running, environment: environment, sha: sha, ref: ref, deployable: build) }
+
+ it 'displays that the running deployment' do
+ visit project_merge_request_path(project, merge_request)
+ wait_for_requests
+
+ expect(page).to have_content("Deploying to #{environment.name}")
+ expect(page).not_to have_css('.js-deploy-time')
+ end
+ end
+
+ context 'when deployment will happen' do
+ let(:build) { create(:ci_build, :created, pipeline: pipeline) }
+ let!(:deployment) { create(:deployment, environment: environment, sha: sha, ref: ref, deployable: build) }
+
+ it 'displays that the environment name' do
+ visit project_merge_request_path(project, merge_request)
+ wait_for_requests
+
+ expect(page).to have_content("Will deploy to #{environment.name}")
+ expect(page).not_to have_css('.js-deploy-time')
+ end
+ end
+
+ context 'when deployment was cancelled' do
+ let(:build) { create(:ci_build, :canceled, pipeline: pipeline) }
+ let!(:deployment) { create(:deployment, :canceled, environment: environment, sha: sha, ref: ref, deployable: build) }
+
+ it 'displays that the environment name' do
+ visit project_merge_request_path(project, merge_request)
+ wait_for_requests
+
+ expect(page).to have_content("Failed to deploy to #{environment.name}")
+ expect(page).not_to have_css('.js-deploy-time')
+ end
end
context 'with stop action' do
- let(:pipeline) { create(:ci_pipeline, project: project) }
- let(:build) { create(:ci_build, pipeline: pipeline) }
+ let(:build) { create(:ci_build, :success, pipeline: pipeline) }
+ let!(:deployment) { create(:deployment, :succeed, environment: environment, sha: sha, ref: ref, deployable: build) }
let(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'close_app') }
- let(:deployment) do
- create(:deployment, environment: environment, ref: merge_request.target_branch,
- sha: sha, deployable: build, on_stop: 'close_app')
- end
before do
+ deployment.update!(on_stop: manual.name)
+ visit project_merge_request_path(project, merge_request)
wait_for_requests
end
it 'does start build when stop button clicked' do
- accept_confirm { click_button('Stop environment') }
+ accept_confirm { find('.js-stop-env').click }
expect(page).to have_content('close_app')
end
@@ -48,7 +120,7 @@ describe 'Merge request > User sees deployment widget', :js do
let(:role) { :reporter }
it 'does not show stop button' do
- expect(page).not_to have_button('Stop environment')
+ expect(page).not_to have_selector('.js-stop-env')
end
end
end
diff --git a/spec/features/merge_request/user_sees_discussions_spec.rb b/spec/features/merge_request/user_sees_discussions_spec.rb
index 7b8c3bacfe2..4ab9a87ad4b 100644
--- a/spec/features/merge_request/user_sees_discussions_spec.rb
+++ b/spec/features/merge_request/user_sees_discussions_spec.rb
@@ -53,13 +53,11 @@ describe 'Merge request > User sees discussions', :js do
shared_examples 'a functional discussion' do
let(:discussion_id) { note.discussion_id(merge_request) }
- # TODO: https://gitlab.com/gitlab-org/gitlab-ce/issues/48034
- xit 'is displayed' do
+ it 'is displayed' do
expect(page).to have_css(".discussion[data-discussion-id='#{discussion_id}']")
end
- # TODO: https://gitlab.com/gitlab-org/gitlab-ce/issues/48034
- xit 'can be replied to' do
+ it 'can be replied to' do
within(".discussion[data-discussion-id='#{discussion_id}']") do
click_button 'Reply...'
fill_in 'note[note]', with: 'Test!'
@@ -74,16 +72,21 @@ describe 'Merge request > User sees discussions', :js do
visit project_merge_request_path(project, merge_request)
end
- context 'a regular commit comment' do
- let(:note) { create(:note_on_commit, project: project) }
-
- it_behaves_like 'a functional discussion'
- end
+ # TODO: https://gitlab.com/gitlab-org/gitlab-ce/issues/48034
+ # context 'a regular commit comment' do
+ # let(:note) { create(:note_on_commit, project: project) }
+ #
+ # it_behaves_like 'a functional discussion'
+ # end
context 'a commit diff comment' do
let(:note) { create(:diff_note_on_commit, project: project) }
it_behaves_like 'a functional discussion'
+
+ it 'displays correct header' do
+ expect(page).to have_content "started a discussion on commit #{note.commit_id[0...7]}"
+ end
end
end
end
diff --git a/spec/features/merge_request/user_sees_empty_state_spec.rb b/spec/features/merge_request/user_sees_empty_state_spec.rb
index 482f31b02d4..012bfd6e458 100644
--- a/spec/features/merge_request/user_sees_empty_state_spec.rb
+++ b/spec/features/merge_request/user_sees_empty_state_spec.rb
@@ -19,12 +19,20 @@ describe 'Merge request > User sees empty state' do
context 'if there are merge requests' do
before do
create(:merge_request, source_project: project)
-
- visit project_merge_requests_path(project)
end
it 'does not show an empty state' do
+ visit project_merge_requests_path(project)
+
expect(page).not_to have_selector('.empty-state')
end
+
+ it 'shows empty state when filter results empty' do
+ visit project_merge_requests_path(project, milestone_title: "1.0")
+
+ expect(page).to have_selector('.empty-state')
+ expect(page).to have_content('Sorry, your filter produced no results')
+ expect(page).to have_content('To widen your search, change or remove filters above')
+ end
end
end
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index a5dc9017699..d8ebd3c92af 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -40,21 +40,27 @@ describe 'Merge request > User sees merge widget', :js do
context 'view merge request' do
let!(:environment) { create(:environment, project: project) }
+ let(:sha) { project.commit(merge_request.source_branch).sha }
+ let(:pipeline) { create(:ci_pipeline_without_jobs, status: 'success', sha: sha, project: project, ref: merge_request.source_branch) }
+ let(:build) { create(:ci_build, :success, pipeline: pipeline) }
let!(:deployment) do
- create(:deployment, environment: environment,
- ref: 'feature',
- sha: merge_request.diff_head_sha)
+ create(:deployment, :succeed,
+ environment: environment,
+ ref: merge_request.source_branch,
+ deployable: build,
+ sha: sha)
end
before do
+ merge_request.update!(head_pipeline: pipeline)
visit project_merge_request_path(project, merge_request)
end
it 'shows environments link' do
wait_for_requests
- page.within('.mr-widget-heading') do
+ page.within('.js-pre-deployment') do
expect(page).to have_content("Deployed to #{environment.name}")
expect(find('.js-deploy-url')[:href]).to include(environment.formatted_external_url)
end
@@ -174,7 +180,7 @@ describe 'Merge request > User sees merge widget', :js do
# Wait for the `ci_status` and `merge_check` requests
wait_for_requests
- expect(page).to have_text('Could not connect to the CI server. Please check your settings and try again')
+ expect(page).to have_text("Could not retrieve the pipeline status. For troubleshooting steps, read the documentation.")
end
end
@@ -423,7 +429,7 @@ describe 'Merge request > User sees merge widget', :js do
end
it 'shows test reports summary which includes the new failure' do
- within(".mr-section-container") do
+ within(".js-reports-container") do
click_button 'Expand'
expect(page).to have_content('Test summary contained 1 failed test result out of 2 total tests')
@@ -438,7 +444,7 @@ describe 'Merge request > User sees merge widget', :js do
context 'when user clicks the new failure' do
it 'shows the test report detail' do
- within(".mr-section-container") do
+ within(".js-reports-container") do
click_button 'Expand'
within(".js-report-section-container") do
@@ -468,7 +474,7 @@ describe 'Merge request > User sees merge widget', :js do
end
it 'shows test reports summary which includes the existing failure' do
- within(".mr-section-container") do
+ within(".js-reports-container") do
click_button 'Expand'
expect(page).to have_content('Test summary contained 1 failed test result out of 2 total tests')
@@ -483,7 +489,7 @@ describe 'Merge request > User sees merge widget', :js do
context 'when user clicks the existing failure' do
it 'shows test report detail of it' do
- within(".mr-section-container") do
+ within(".js-reports-container") do
click_button 'Expand'
within(".js-report-section-container") do
@@ -519,7 +525,7 @@ describe 'Merge request > User sees merge widget', :js do
end
it 'shows test reports summary which includes the resolved failure' do
- within(".mr-section-container") do
+ within(".js-reports-container") do
click_button 'Expand'
expect(page).to have_content('Test summary contained 1 fixed test result out of 2 total tests')
@@ -533,7 +539,7 @@ describe 'Merge request > User sees merge widget', :js do
context 'when user clicks the resolved failure' do
it 'shows test report detail of it' do
- within(".mr-section-container") do
+ within(".js-reports-container") do
click_button 'Expand'
within(".js-report-section-container") do
diff --git a/spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb b/spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb
index 029b66b5e8e..fc4a188d4a7 100644
--- a/spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb
+++ b/spec/features/merge_request/user_sees_mr_from_deleted_forked_project_spec.rb
@@ -1,18 +1,20 @@
require 'rails_helper'
describe 'Merge request > User sees MR from deleted forked project', :js do
+ include ProjectForksHelper
+
let(:project) { create(:project, :public, :repository) }
let(:user) { project.creator }
- let(:fork_project) { create(:project, :public, :repository, forked_from_project: project) }
+ let(:forked_project) { fork_project(project, nil, repository: true) }
let!(:merge_request) do
- create(:merge_request_with_diffs, source_project: fork_project,
+ create(:merge_request_with_diffs, source_project: forked_project,
target_project: project,
description: 'Test merge request')
end
before do
MergeRequests::MergeService.new(project, user).execute(merge_request)
- fork_project.destroy!
+ forked_project.destroy!
sign_in(user)
visit project_merge_request_path(project, merge_request)
end
diff --git a/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb b/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb
index d4ad0b0a377..a6118453540 100644
--- a/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb
+++ b/spec/features/merge_request/user_sees_notes_from_forked_project_spec.rb
@@ -1,18 +1,20 @@
require 'rails_helper'
describe 'Merge request > User sees notes from forked project', :js do
+ include ProjectForksHelper
+
let(:project) { create(:project, :public, :repository) }
let(:user) { project.creator }
- let(:fork_project) { create(:project, :public, :repository, forked_from_project: project) }
+ let(:forked_project) { fork_project(project, nil, repository: true) }
let!(:merge_request) do
- create(:merge_request_with_diffs, source_project: fork_project,
+ create(:merge_request_with_diffs, source_project: forked_project,
target_project: project,
description: 'Test merge request')
end
before do
create(:note_on_commit, note: 'A commit comment',
- project: fork_project,
+ project: forked_project,
commit_id: merge_request.commit_shas.first)
sign_in(user)
end
diff --git a/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb b/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb
index d30dcefc6aa..97093bbc2f6 100644
--- a/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb
+++ b/spec/features/merge_request/user_sees_pipelines_from_forked_project_spec.rb
@@ -1,17 +1,19 @@
require 'rails_helper'
describe 'Merge request > User sees pipelines from forked project', :js do
+ include ProjectForksHelper
+
let(:target_project) { create(:project, :public, :repository) }
let(:user) { target_project.creator }
- let(:fork_project) { create(:project, :repository, forked_from_project: target_project) }
+ let(:forked_project) { fork_project(target_project, nil, repository: true) }
let!(:merge_request) do
- create(:merge_request_with_diffs, source_project: fork_project,
+ create(:merge_request_with_diffs, source_project: forked_project,
target_project: target_project,
description: 'Test merge request')
end
let(:pipeline) do
create(:ci_pipeline,
- project: fork_project,
+ project: forked_project,
sha: merge_request.diff_head_sha,
ref: merge_request.source_branch)
end
diff --git a/spec/features/merge_request/user_sees_pipelines_spec.rb b/spec/features/merge_request/user_sees_pipelines_spec.rb
index 45cccbee63e..8faddee4daa 100644
--- a/spec/features/merge_request/user_sees_pipelines_spec.rb
+++ b/spec/features/merge_request/user_sees_pipelines_spec.rb
@@ -41,8 +41,7 @@ describe 'Merge request > User sees pipelines', :js do
visit project_merge_request_path(project, merge_request)
wait_for_requests
- expect(page.find('.ci-widget')).to have_content(
- 'Could not connect to the CI server. Please check your settings and try again')
+ expect(page.find('.ci-widget')).to have_text("Could not retrieve the pipeline status. For troubleshooting steps, read the documentation.")
end
end
diff --git a/spec/features/merge_request/user_sees_versions_spec.rb b/spec/features/merge_request/user_sees_versions_spec.rb
index f42b4dcbb47..f7512294bef 100644
--- a/spec/features/merge_request/user_sees_versions_spec.rb
+++ b/spec/features/merge_request/user_sees_versions_spec.rb
@@ -66,7 +66,6 @@ describe 'Merge request > User sees versions', :js do
it 'shows comments that were last relevant at that version' do
expect(page).to have_content '5 changed files'
- expect(page).to have_content 'Not all comments are displayed'
position = Gitlab::Diff::Position.new(
old_path: ".gitmodules",
@@ -110,8 +109,8 @@ describe 'Merge request > User sees versions', :js do
diff_id: merge_request_diff3.id,
start_sha: '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9'
)
- expect(page).to have_content '4 changed files with 15 additions and 6 deletions'
- expect(page).to have_content 'Not all comments are displayed'
+ expect(page).to have_content '4 changed files'
+ expect(page).to have_content '15 additions 6 deletions'
position = Gitlab::Diff::Position.new(
old_path: ".gitmodules",
@@ -131,7 +130,8 @@ describe 'Merge request > User sees versions', :js do
end
it 'show diff between new and old version' do
- expect(page).to have_content '4 changed files with 15 additions and 6 deletions'
+ expect(page).to have_content '4 changed files'
+ expect(page).to have_content '15 additions 6 deletions'
end
it 'returns to latest version when "Show latest version" button is clicked' do
@@ -158,7 +158,7 @@ describe 'Merge request > User sees versions', :js do
it 'has 0 chages between versions' do
page.within '.mr-version-compare-dropdown' do
- expect(find('.dropdown-toggle')).to have_content 'version 1'
+ expect(find('.dropdown-menu-toggle')).to have_content 'version 1'
end
page.within '.mr-version-dropdown' do
@@ -179,7 +179,7 @@ describe 'Merge request > User sees versions', :js do
it 'sets the compared versions to be the same' do
page.within '.mr-version-compare-dropdown' do
- expect(find('.dropdown-toggle')).to have_content 'version 2'
+ expect(find('.dropdown-menu-toggle')).to have_content 'version 2'
end
page.within '.mr-version-dropdown' do
diff --git a/spec/features/merge_request/user_views_diffs_spec.rb b/spec/features/merge_request/user_views_diffs_spec.rb
index b1bfe9e5de3..7f95a1282f9 100644
--- a/spec/features/merge_request/user_views_diffs_spec.rb
+++ b/spec/features/merge_request/user_views_diffs_spec.rb
@@ -10,6 +10,8 @@ describe 'User views diffs', :js do
visit(diffs_project_merge_request_path(project, merge_request))
wait_for_requests
+
+ find('.js-toggle-tree-list').click
end
shared_examples 'unfold diffs' do
diff --git a/spec/features/merge_request/user_views_open_merge_request_spec.rb b/spec/features/merge_request/user_views_open_merge_request_spec.rb
index 6ac495aa03d..71022c6bb08 100644
--- a/spec/features/merge_request/user_views_open_merge_request_spec.rb
+++ b/spec/features/merge_request/user_views_open_merge_request_spec.rb
@@ -41,7 +41,7 @@ describe 'User views an open merge request' do
find('.gfm-form').fill_in(:merge_request_description, with: '')
page.within('.gfm-form') do
- click_link('Preview')
+ click_button('Preview')
expect(find('.js-md-preview')).to have_content('Nothing to preview.')
end
@@ -51,12 +51,12 @@ describe 'User views an open merge request' do
find('.gfm-form').fill_in(:merge_request_description, with: ':+1: Nice')
page.within('.gfm-form') do
- click_link('Preview')
+ click_button('Preview')
expect(find('.js-md-preview')).to have_css('gl-emoji')
end
- expect(find('.gfm-form')).to have_css('.js-md-preview').and have_link('Write')
+ expect(find('.gfm-form')).to have_css('.js-md-preview').and have_button('Write')
expect(find('#merge_request_description', visible: false)).not_to be_visible
end
end
diff --git a/spec/features/merge_requests/user_sorts_merge_requests_spec.rb b/spec/features/merge_requests/user_sorts_merge_requests_spec.rb
index 82cfe600d52..61e8f1c4662 100644
--- a/spec/features/merge_requests/user_sorts_merge_requests_spec.rb
+++ b/spec/features/merge_requests/user_sorts_merge_requests_spec.rb
@@ -19,13 +19,13 @@ describe 'User sorts merge requests' do
end
it 'keeps the sort option' do
- find('button.dropdown-toggle').click
+ find('.filter-dropdown-container button.dropdown-menu-toggle').click
page.within('.content ul.dropdown-menu.dropdown-menu-right li') do
click_link('Milestone')
end
- visit(merge_requests_dashboard_path(assignee_id: user.id))
+ visit(merge_requests_dashboard_path(assignee_username: user.username))
expect(find('.issues-filters a.is-active')).to have_content('Milestone')
@@ -41,7 +41,7 @@ describe 'User sorts merge requests' do
it 'fallbacks to issuable_sort cookie key when remembering the sorting option' do
set_cookie('issuable_sort', 'milestone')
- visit(merge_requests_dashboard_path(assignee_id: user.id))
+ visit(merge_requests_dashboard_path(assignee_username: user.username))
expect(find('.issues-filters a.is-active')).to have_content('Milestone')
end
@@ -49,7 +49,7 @@ describe 'User sorts merge requests' do
it 'separates remember sorting with issues' do
create(:issue, project: project)
- find('button.dropdown-toggle').click
+ find('.filter-dropdown-container button.dropdown-menu-toggle').click
page.within('.content ul.dropdown-menu.dropdown-menu-right li') do
click_link('Milestone')
@@ -70,7 +70,7 @@ describe 'User sorts merge requests' do
end
it 'sorts by popularity' do
- find('button.dropdown-toggle').click
+ find('.filter-dropdown-container button.dropdown-menu-toggle').click
page.within('.content ul.dropdown-menu.dropdown-menu-right li') do
click_link('Popularity')
diff --git a/spec/features/milestones/user_creates_milestone_spec.rb b/spec/features/milestones/user_creates_milestone_spec.rb
index 8fd057d587c..5de0c381cdf 100644
--- a/spec/features/milestones/user_creates_milestone_spec.rb
+++ b/spec/features/milestones/user_creates_milestone_spec.rb
@@ -24,6 +24,6 @@ describe "User creates milestone", :js do
visit(activity_project_path(project))
- expect(page).to have_content("#{user.name} opened milestone")
+ expect(page).to have_content("#{user.name} #{user.to_reference} opened milestone")
end
end
diff --git a/spec/features/milestones/user_deletes_milestone_spec.rb b/spec/features/milestones/user_deletes_milestone_spec.rb
index a8c296b4cd2..f68ed1cde07 100644
--- a/spec/features/milestones/user_deletes_milestone_spec.rb
+++ b/spec/features/milestones/user_deletes_milestone_spec.rb
@@ -23,7 +23,7 @@ describe "User deletes milestone", :js do
visit(activity_project_path(project))
- expect(page).to have_content("#{user.name} destroyed milestone")
+ expect(page).to have_content("#{user.name} #{user.to_reference} destroyed milestone")
end
end
diff --git a/spec/features/milestones/user_promotes_milestone_spec.rb b/spec/features/milestones/user_promotes_milestone_spec.rb
new file mode 100644
index 00000000000..df1bc502134
--- /dev/null
+++ b/spec/features/milestones/user_promotes_milestone_spec.rb
@@ -0,0 +1,32 @@
+require 'rails_helper'
+
+describe 'User promotes milestone' do
+ set(:group) { create(:group) }
+ set(:user) { create(:user) }
+ set(:project) { create(:project, namespace: group) }
+ set(:milestone) { create(:milestone, project: project) }
+
+ context 'when user can admin group milestones' do
+ before do
+ group.add_developer(user)
+ sign_in(user)
+ visit(project_milestones_path(project))
+ end
+
+ it "shows milestone promote button" do
+ expect(page).to have_selector('.js-promote-project-milestone-button')
+ end
+ end
+
+ context 'when user cannot admin group milestones' do
+ before do
+ project.add_developer(user)
+ sign_in(user)
+ visit(project_milestones_path(project))
+ end
+
+ it "does not show milestone promote button" do
+ expect(page).not_to have_selector('.js-promote-project-milestone-button')
+ end
+ end
+end
diff --git a/spec/features/milestones/user_sees_breadcrumb_links_spec.rb b/spec/features/milestones/user_sees_breadcrumb_links_spec.rb
new file mode 100644
index 00000000000..d3906ea73bd
--- /dev/null
+++ b/spec/features/milestones/user_sees_breadcrumb_links_spec.rb
@@ -0,0 +1,19 @@
+require 'rails_helper'
+
+describe 'New project milestone breadcrumb' do
+ let(:project) { create(:project) }
+ let(:milestone) { create(:milestone, project: project) }
+ let(:user) { project.creator }
+
+ before do
+ sign_in(user)
+ visit(new_project_milestone_path(project))
+ end
+
+ it 'displays link to project milestones and new project milestone' do
+ page.within '.breadcrumbs' do
+ expect(find_link('Milestones')[:href]).to end_with(project_milestones_path(project))
+ expect(find_link('New')[:href]).to end_with(new_project_milestone_path(project))
+ end
+ end
+end
diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb
index 8461cd0027c..dee213a11d4 100644
--- a/spec/features/profiles/personal_access_tokens_spec.rb
+++ b/spec/features/profiles/personal_access_tokens_spec.rb
@@ -43,10 +43,12 @@ describe 'Profile > Personal Access Tokens', :js do
check "read_user"
click_on "Create personal access token"
+
expect(active_personal_access_tokens).to have_text(name)
expect(active_personal_access_tokens).to have_text('In')
expect(active_personal_access_tokens).to have_text('api')
expect(active_personal_access_tokens).to have_text('read_user')
+ expect(created_personal_access_token).not_to be_empty
end
context "when creation fails" do
@@ -57,6 +59,7 @@ describe 'Profile > Personal Access Tokens', :js do
expect { click_on "Create personal access token" }.not_to change { PersonalAccessToken.count }
expect(page).to have_content("Name cannot be nil")
+ expect(page).not_to have_selector("#created-personal-access-token")
end
end
end
diff --git a/spec/features/profiles/user_edit_profile_spec.rb b/spec/features/profiles/user_edit_profile_spec.rb
index 206a3a4fe9a..5e0434c1c2c 100644
--- a/spec/features/profiles/user_edit_profile_spec.rb
+++ b/spec/features/profiles/user_edit_profile_spec.rb
@@ -61,83 +61,231 @@ describe 'User edit profile' do
end
context 'user status', :js do
- def select_emoji(emoji_name)
+ def select_emoji(emoji_name, is_modal = false)
+ emoji_menu_class = is_modal ? '.js-modal-status-emoji-menu' : '.js-status-emoji-menu'
toggle_button = find('.js-toggle-emoji-menu')
toggle_button.click
- emoji_button = find(%Q{.js-status-emoji-menu .js-emoji-btn gl-emoji[data-name="#{emoji_name}"]})
+ emoji_button = find(%Q{#{emoji_menu_class} .js-emoji-btn gl-emoji[data-name="#{emoji_name}"]})
emoji_button.click
end
- it 'shows the user status form' do
- visit(profile_path)
+ context 'profile edit form' do
+ it 'shows the user status form' do
+ visit(profile_path)
- expect(page).to have_content('Current status')
- end
+ expect(page).to have_content('Current status')
+ end
- it 'adds emoji to user status' do
- emoji = 'biohazard'
- visit(profile_path)
- select_emoji(emoji)
- submit_settings
+ it 'adds emoji to user status' do
+ emoji = 'biohazard'
+ visit(profile_path)
+ select_emoji(emoji)
+ submit_settings
- visit user_path(user)
- within('.cover-status') do
- expect(page).to have_emoji(emoji)
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji(emoji)
+ end
end
- end
- it 'adds message to user status' do
- message = 'I have something to say'
- visit(profile_path)
- fill_in 'js-status-message-field', with: message
- submit_settings
+ it 'adds message to user status' do
+ message = 'I have something to say'
+ visit(profile_path)
+ fill_in 'js-status-message-field', with: message
+ submit_settings
- visit user_path(user)
- within('.cover-status') do
- expect(page).to have_emoji('speech_balloon')
- expect(page).to have_content message
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji('speech_balloon')
+ expect(page).to have_content message
+ end
end
- end
- it 'adds message and emoji to user status' do
- emoji = 'tanabata_tree'
- message = 'Playing outside'
- visit(profile_path)
- select_emoji(emoji)
- fill_in 'js-status-message-field', with: message
- submit_settings
+ it 'adds message and emoji to user status' do
+ emoji = 'tanabata_tree'
+ message = 'Playing outside'
+ visit(profile_path)
+ select_emoji(emoji)
+ fill_in 'js-status-message-field', with: message
+ submit_settings
- visit user_path(user)
- within('.cover-status') do
- expect(page).to have_emoji(emoji)
- expect(page).to have_content message
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji(emoji)
+ expect(page).to have_content message
+ end
end
- end
- it 'clears the user status' do
- user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread')
+ it 'clears the user status' do
+ user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread')
+
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji(user_status.emoji)
+ expect(page).to have_content user_status.message
+ end
+
+ visit(profile_path)
+ click_button 'js-clear-user-status-button'
+ submit_settings
+
+ wait_for_requests
- visit user_path(user)
- within('.cover-status') do
- expect(page).to have_emoji(user_status.emoji)
- expect(page).to have_content user_status.message
+ visit user_path(user)
+ expect(page).not_to have_selector '.cover-status'
end
- visit(profile_path)
- click_button 'js-clear-user-status-button'
- submit_settings
+ it 'displays a default emoji if only message is entered' do
+ message = 'a status without emoji'
+ visit(profile_path)
+ fill_in 'js-status-message-field', with: message
- visit user_path(user)
- expect(page).not_to have_selector '.cover-status'
+ within('.js-toggle-emoji-menu') do
+ expect(page).to have_emoji('speech_balloon')
+ end
+ end
end
- it 'displays a default emoji if only message is entered' do
- message = 'a status without emoji'
- visit(profile_path)
- fill_in 'js-status-message-field', with: message
+ context 'user menu' do
+ def open_user_status_modal
+ find('.header-user-dropdown-toggle').click
+
+ page.within ".header-user" do
+ click_button 'Set status'
+ end
+ end
+
+ def set_user_status_in_modal
+ page.within "#set-user-status-modal" do
+ click_button 'Set status'
+ end
+ end
+
+ before do
+ visit root_path(user)
+ end
+
+ it 'shows the "Set status" menu item in the user menu' do
+ find('.header-user-dropdown-toggle').click
+
+ page.within ".header-user" do
+ expect(page).to have_content('Set status')
+ end
+ end
+
+ it 'shows the "Edit status" menu item in the user menu' do
+ user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread')
+ visit root_path(user)
+
+ find('.header-user-dropdown-toggle').click
+
+ page.within ".header-user" do
+ expect(page).to have_emoji(user_status.emoji)
+ expect(page).to have_content user_status.message
+ expect(page).to have_content('Edit status')
+ end
+ end
+
+ it 'shows user status modal' do
+ open_user_status_modal
+
+ expect(page.find('#set-user-status-modal')).to be_visible
+ expect(page).to have_content('Set a status')
+ end
+
+ it 'adds emoji to user status' do
+ emoji = 'biohazard'
+ open_user_status_modal
+ select_emoji(emoji, true)
+ set_user_status_in_modal
+
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji(emoji)
+ end
+ end
+
+ it 'adds message to user status' do
+ message = 'I have something to say'
+ open_user_status_modal
+ find('.js-status-message-field').native.send_keys(message)
+ set_user_status_in_modal
+
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji('speech_balloon')
+ expect(page).to have_content message
+ end
+ end
+
+ it 'adds message and emoji to user status' do
+ emoji = 'tanabata_tree'
+ message = 'Playing outside'
+ open_user_status_modal
+ select_emoji(emoji, true)
+ find('.js-status-message-field').native.send_keys(message)
+ set_user_status_in_modal
+
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji(emoji)
+ expect(page).to have_content message
+ end
+ end
+
+ it 'clears the user status with the "X" button' do
+ user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread')
+
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji(user_status.emoji)
+ expect(page).to have_content user_status.message
+ end
+
+ find('.header-user-dropdown-toggle').click
+
+ page.within ".header-user" do
+ click_button 'Edit status'
+ end
+
+ find('.js-clear-user-status-button').click
+ set_user_status_in_modal
+
+ visit user_path(user)
+ expect(page).not_to have_selector '.cover-status'
+ end
+
+ it 'clears the user status with the "Remove status" button' do
+ user_status = create(:user_status, user: user, message: 'Eating bread', emoji: 'stuffed_flatbread')
+
+ visit user_path(user)
+ within('.cover-status') do
+ expect(page).to have_emoji(user_status.emoji)
+ expect(page).to have_content user_status.message
+ end
+
+ find('.header-user-dropdown-toggle').click
+
+ page.within ".header-user" do
+ click_button 'Edit status'
+ end
+
+ page.within "#set-user-status-modal" do
+ click_button 'Remove status'
+ end
+
+ visit user_path(user)
+ expect(page).not_to have_selector '.cover-status'
+ end
+
+ it 'displays a default emoji if only message is entered' do
+ message = 'a status without emoji'
+ open_user_status_modal
+ find('.js-status-message-field').native.send_keys(message)
- within('.js-toggle-emoji-menu') do
- expect(page).to have_emoji('speech_balloon')
+ within('.js-toggle-emoji-menu') do
+ expect(page).to have_emoji('speech_balloon')
+ end
end
end
end
diff --git a/spec/features/profiles/user_manages_applications_spec.rb b/spec/features/profiles/user_manages_applications_spec.rb
index 387584fef62..34aaab240cc 100644
--- a/spec/features/profiles/user_manages_applications_spec.rb
+++ b/spec/features/profiles/user_manages_applications_spec.rb
@@ -16,7 +16,7 @@ describe 'User manages applications' do
click_on 'Save application'
expect(page).to have_content 'Application: test'
- expect(page).to have_content 'Application Id'
+ expect(page).to have_content 'Application ID'
expect(page).to have_content 'Secret'
click_on 'Edit'
@@ -26,7 +26,7 @@ describe 'User manages applications' do
click_on 'Save application'
expect(page).to have_content 'test_changed'
- expect(page).to have_content 'Application Id'
+ expect(page).to have_content 'Application ID'
expect(page).to have_content 'Secret'
visit applications_profile_path
diff --git a/spec/features/projects/activity/user_sees_activity_spec.rb b/spec/features/projects/activity/user_sees_activity_spec.rb
index e0248911b5f..bb4b2abc3c7 100644
--- a/spec/features/projects/activity/user_sees_activity_spec.rb
+++ b/spec/features/projects/activity/user_sees_activity_spec.rb
@@ -3,8 +3,10 @@ require 'spec_helper'
describe 'Projects > Activity > User sees activity' do
let(:project) { create(:project, :repository, :public) }
let(:user) { project.creator }
+ let(:issue) { create(:issue, project: project) }
before do
+ create(:event, :created, project: project, target: issue, author: user)
event = create(:push_event, project: project, author: user)
create(:push_event_payload,
event: event,
@@ -12,10 +14,18 @@ describe 'Projects > Activity > User sees activity' do
commit_to: '6d394385cf567f80a8fd85055db1ab4c5295806f',
ref: 'fix',
commit_count: 1)
- visit activity_project_path(project)
end
it 'shows the last push in the activity page', :js do
- expect(page).to have_content "#{user.name} pushed new branch fix"
+ visit activity_project_path(project)
+
+ expect(page).to have_content "#{user.name} #{user.to_reference} pushed new branch fix"
+ end
+
+ it 'allows to filter event with the "event_filter=issue" URL param', :js do
+ visit activity_project_path(project, event_filter: 'issue')
+
+ expect(page).not_to have_content "#{user.name} #{user.to_reference} pushed new branch fix"
+ expect(page).to have_content "#{user.name} #{user.to_reference} opened issue #{issue.to_reference}"
end
end
diff --git a/spec/features/projects/activity/user_sees_private_activity_spec.rb b/spec/features/projects/activity/user_sees_private_activity_spec.rb
index d7dc0a6712a..61ec2ce9d29 100644
--- a/spec/features/projects/activity/user_sees_private_activity_spec.rb
+++ b/spec/features/projects/activity/user_sees_private_activity_spec.rb
@@ -5,7 +5,7 @@ describe 'Project > Activity > User sees private activity', :js do
let(:author) { create(:user) }
let(:user) { create(:user) }
let(:issue) { create(:issue, :confidential, project: project, author: author) }
- let(:message) { "#{author.name} opened issue #{issue.to_reference}" }
+ let(:message) { "#{author.name} #{author.to_reference} opened issue #{issue.to_reference}" }
before do
project.add_developer(author)
diff --git a/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb b/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb
index 67ed2f18d76..554f0b49052 100644
--- a/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb
+++ b/spec/features/projects/artifacts/user_downloads_artifacts_spec.rb
@@ -20,23 +20,13 @@ describe "User downloads artifacts" do
end
context "via job id" do
- set(:url) { download_project_job_artifacts_path(project, job) }
+ let(:url) { download_project_job_artifacts_path(project, job) }
it_behaves_like "downloading"
end
context "via branch name and job name" do
- set(:url) { latest_succeeded_project_artifacts_path(project, "#{pipeline.ref}/download", job: job.name) }
-
- it_behaves_like "downloading"
- end
-
- context "via clicking the `Download` button" do
- set(:url) { project_job_path(project, job) }
-
- before do
- click_link("Download")
- end
+ let(:url) { latest_succeeded_project_artifacts_path(project, "#{pipeline.ref}/download", job: job.name) }
it_behaves_like "downloading"
end
diff --git a/spec/features/projects/badges/pipeline_badge_spec.rb b/spec/features/projects/badges/pipeline_badge_spec.rb
index 8c4488b2ca6..dee81898928 100644
--- a/spec/features/projects/badges/pipeline_badge_spec.rb
+++ b/spec/features/projects/badges/pipeline_badge_spec.rb
@@ -19,7 +19,7 @@ describe 'Pipeline Badge' do
let!(:pipeline) { create(:ci_empty_pipeline, project: project, ref: ref, sha: project.commit(ref).sha) }
let!(:job) { create(:ci_build, pipeline: pipeline) }
- context 'when the pipeline was successfull' do
+ context 'when the pipeline was successful' do
it 'displays so on the badge' do
job.success
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index edc763ad0ad..3d17eb3a73a 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -84,10 +84,8 @@ describe 'Gcp Cluster', :js do
it_behaves_like 'valid cluster gcp form'
- context 'rbac_clusters feature flag is enabled' do
+ context 'RBAC is enabled for the cluster' do
before do
- stub_feature_flags(rbac_clusters: true)
-
check 'cluster_provider_gcp_attributes_legacy_abac'
end
@@ -132,6 +130,7 @@ describe 'Gcp Cluster', :js do
context 'when user changes cluster parameters' do
before do
+ allow(ClusterPlatformConfigureWorker).to receive(:perform_async)
fill_in 'cluster_platform_kubernetes_attributes_namespace', with: 'my-namespace'
page.within('#js-cluster-details') { click_button 'Save changes' }
end
diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb
index 2b4998ed5ac..250c964cc32 100644
--- a/spec/features/projects/clusters/user_spec.rb
+++ b/spec/features/projects/clusters/user_spec.rb
@@ -9,7 +9,9 @@ describe 'User Cluster', :js do
before do
project.add_maintainer(user)
gitlab_sign_in(user)
+
allow(Projects::ClustersController).to receive(:STATUS_POLLING_INTERVAL) { 100 }
+ allow_any_instance_of(Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService).to receive(:execute)
end
context 'when user does not have a cluster and visits cluster index page' do
@@ -44,10 +46,8 @@ describe 'User Cluster', :js do
it_behaves_like 'valid cluster user form'
- context 'rbac_clusters feature flag is enabled' do
+ context 'RBAC is enabled for the cluster' do
before do
- stub_feature_flags(rbac_clusters: true)
-
check 'cluster_platform_kubernetes_attributes_authorization_type'
end
diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb
index 91eac9c8278..a85e7333ba8 100644
--- a/spec/features/projects/clusters_spec.rb
+++ b/spec/features/projects/clusters_spec.rb
@@ -35,37 +35,6 @@ describe 'Clusters', :js do
expect(page).to have_selector('.gl-responsive-table-row', count: 2)
end
- context 'inline update of cluster' do
- it 'user can update cluster' do
- expect(page).to have_selector('.js-project-feature-toggle')
- end
-
- context 'with sucessfull request' do
- it 'user sees updated cluster' do
- expect do
- page.find('.js-project-feature-toggle').click
- wait_for_requests
- end.to change { cluster.reload.enabled }
-
- expect(page).not_to have_selector('.is-checked')
- expect(cluster.reload).not_to be_enabled
- end
- end
-
- context 'with failed request' do
- it 'user sees not update cluster and error message' do
- expect_any_instance_of(Clusters::UpdateService).to receive(:execute).and_call_original
- allow_any_instance_of(Clusters::Cluster).to receive(:valid?) { false }
-
- page.find('.js-project-feature-toggle').click
-
- expect(page).to have_content('Something went wrong on our end.')
- expect(page).to have_selector('.is-checked')
- expect(cluster.reload).to be_enabled
- end
- end
- end
-
context 'when user clicks on a cluster' do
before do
click_link cluster.name
diff --git a/spec/features/projects/commit/comments/user_adds_comment_spec.rb b/spec/features/projects/commit/comments/user_adds_comment_spec.rb
index 6397df086a7..29442a58ea4 100644
--- a/spec/features/projects/commit/comments/user_adds_comment_spec.rb
+++ b/spec/features/projects/commit/comments/user_adds_comment_spec.rb
@@ -28,19 +28,19 @@ describe "User adds a comment on a commit", :js do
fill_in("note[note]", with: "#{comment_text} #{emoji}")
# Check on `Preview` tab
- click_link("Preview")
+ click_button("Preview")
expect(find(".js-md-preview")).to have_content(comment_text).and have_css("gl-emoji")
expect(page).not_to have_css(".js-note-text")
# Check on the `Write` tab
- click_link("Write")
+ click_button("Write")
expect(page).to have_field("note[note]", with: "#{comment_text} #{emoji}")
# Submit comment from the `Preview` tab to get rid of a separate `it` block
# which would specially tests if everything gets cleared from the note form.
- click_link("Preview")
+ click_button("Preview")
click_button("Comment")
end
@@ -88,13 +88,13 @@ describe "User adds a comment on a commit", :js do
# Test Preview feature for both forms.
page.within("form[data-line-code='#{sample_commit.line_code}']") do
- click_link("Preview")
+ click_button("Preview")
end
page.within("form[data-line-code='#{sample_commit.del_line_code}']") do
fill_in("note[note]", with: another_comment_text)
- click_link("Preview")
+ click_button("Preview")
end
expect(page).to have_css(".js-md-preview", visible: true, count: 2)
diff --git a/spec/features/projects/commit/user_comments_on_commit_spec.rb b/spec/features/projects/commit/user_comments_on_commit_spec.rb
index 6397a8ad845..73ce8d2b996 100644
--- a/spec/features/projects/commit/user_comments_on_commit_spec.rb
+++ b/spec/features/projects/commit/user_comments_on_commit_spec.rb
@@ -25,19 +25,19 @@ describe "User comments on commit", :js do
fill_in("note[note]", with: "#{comment_text} #{emoji_code}")
# Check on `Preview` tab
- click_link("Preview")
+ click_button("Preview")
expect(find(".js-md-preview")).to have_content(comment_text).and have_css("gl-emoji")
expect(page).not_to have_css(".js-note-text")
# Check on `Write` tab
- click_link("Write")
+ click_button("Write")
expect(page).to have_field("note[note]", with: "#{comment_text} #{emoji_code}")
# Submit comment from the `Preview` tab to get rid of a separate `it` block
# which would specially tests if everything gets cleared from the note form.
- click_link("Preview")
+ click_button("Preview")
click_button("Comment")
end
diff --git a/spec/features/projects/commits/user_browses_commits_spec.rb b/spec/features/projects/commits/user_browses_commits_spec.rb
index 534cfe1eb12..2159adf49fc 100644
--- a/spec/features/projects/commits/user_browses_commits_spec.rb
+++ b/spec/features/projects/commits/user_browses_commits_spec.rb
@@ -4,10 +4,9 @@ describe 'User browses commits' do
include RepoHelpers
let(:user) { create(:user) }
- let(:project) { create(:project, :repository, namespace: user.namespace) }
+ let(:project) { create(:project, :public, :repository, namespace: user.namespace) }
before do
- project.add_maintainer(user)
sign_in(user)
end
@@ -127,6 +126,26 @@ describe 'User browses commits' do
.and have_selector('entry summary', text: commit.description[0..10].delete("\r\n"))
end
+ context 'when a commit links to a confidential issue' do
+ let(:confidential_issue) { create(:issue, confidential: true, title: 'Secret issue!', project: project) }
+
+ before do
+ project.repository.create_file(user, 'dummy-file', 'dummy content',
+ branch_name: 'feature',
+ message: "Linking #{confidential_issue.to_reference}")
+ end
+
+ context 'when the user cannot see confidential issues but was cached with a link', :use_clean_rails_memory_store_fragment_caching do
+ it 'does not render the confidential issue' do
+ visit project_commits_path(project, 'feature')
+ sign_in(create(:user))
+ visit project_commits_path(project, 'feature')
+
+ expect(page).not_to have_link(href: project_issue_path(project, confidential_issue))
+ end
+ end
+ end
+
context 'master branch' do
before do
visit_commits_page
diff --git a/spec/features/projects/environments/environment_spec.rb b/spec/features/projects/environments/environment_spec.rb
index 4c5dda29fee..a8a3b6910fb 100644
--- a/spec/features/projects/environments/environment_spec.rb
+++ b/spec/features/projects/environments/environment_spec.rb
@@ -25,7 +25,7 @@ describe 'Environment' do
end
context 'without deployments' do
- it 'does show no deployments' do
+ it 'does not show deployments' do
expect(page).to have_content('You don\'t have any deployments right now.')
end
end
@@ -33,7 +33,7 @@ describe 'Environment' do
context 'with deployments' do
context 'when there is no related deployable' do
let(:deployment) do
- create(:deployment, environment: environment, deployable: nil)
+ create(:deployment, :success, environment: environment, deployable: nil)
end
it 'does show deployment SHA' do
@@ -43,24 +43,74 @@ describe 'Environment' do
end
end
+ context 'when there is a successful deployment' do
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:build) { create(:ci_build, :success, pipeline: pipeline) }
+
+ let(:deployment) do
+ create(:deployment, :success, environment: environment, deployable: build)
+ end
+
+ it 'does show deployments' do
+ expect(page).to have_link("#{build.name} (##{build.id})")
+ end
+ end
+
+ context 'when there is a running deployment' do
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:build) { create(:ci_build, pipeline: pipeline) }
+
+ let(:deployment) do
+ create(:deployment, :running, environment: environment, deployable: build)
+ end
+
+ it 'does not show deployments' do
+ expect(page).to have_content('You don\'t have any deployments right now.')
+ end
+ end
+
+ context 'when there is a failed deployment' do
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:build) { create(:ci_build, pipeline: pipeline) }
+
+ let(:deployment) do
+ create(:deployment, :failed, environment: environment, deployable: build)
+ end
+
+ it 'does not show deployments' do
+ expect(page).to have_content('You don\'t have any deployments right now.')
+ end
+ end
+
context 'with related deployable present' do
let(:pipeline) { create(:ci_pipeline, project: project) }
let(:build) { create(:ci_build, pipeline: pipeline) }
let(:deployment) do
- create(:deployment, environment: environment, deployable: build)
+ create(:deployment, :success, environment: environment, deployable: build)
end
it 'does show build name' do
expect(page).to have_link("#{build.name} (##{build.id})")
- expect(page).to have_link('Re-deploy')
+ expect(page).not_to have_link('Re-deploy')
expect(page).not_to have_terminal_button
end
+ context 'when user has ability to re-deploy' do
+ let(:permissions) do
+ create(:protected_branch, :developers_can_merge,
+ name: build.ref, project: project)
+ end
+
+ it 'does show re-deploy' do
+ expect(page).to have_link('Re-deploy')
+ end
+ end
+
context 'with manual action' do
let(:action) do
create(:ci_build, :manual, pipeline: pipeline,
- name: 'deploy to production')
+ name: 'deploy to production', environment: environment.name)
end
context 'when user has ability to trigger deployment' do
@@ -73,12 +123,16 @@ describe 'Environment' do
expect(page).to have_link(action.name.humanize)
end
- it 'does allow to play manual action' do
+ it 'does allow to play manual action', :js do
expect(action).to be_manual
+ find('button.dropdown').click
+
expect { click_link(action.name.humanize) }
.not_to change { Ci::Pipeline.count }
+ wait_for_all_requests
+
expect(page).to have_content(action.name)
expect(action.reload).to be_pending
end
@@ -93,7 +147,7 @@ describe 'Environment' do
context 'with external_url' do
let(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') }
let(:build) { create(:ci_build, pipeline: pipeline) }
- let(:deployment) { create(:deployment, environment: environment, deployable: build) }
+ let(:deployment) { create(:deployment, :success, environment: environment, deployable: build) }
it 'does show an external link button' do
expect(page).to have_link(nil, href: environment.external_url)
@@ -111,8 +165,14 @@ describe 'Environment' do
context 'web terminal', :js do
before do
- # Stub #terminals as it causes js-enabled feature specs to render the page incorrectly
- allow_any_instance_of(Environment).to receive(:terminals) { nil }
+ # Stub #terminals as it causes js-enabled feature specs to
+ # render the page incorrectly
+ #
+ # In EE we have to stub EE::Environment since it overwrites
+ # the "terminals" method.
+ allow_any_instance_of(defined?(EE) ? EE::Environment : Environment)
+ .to receive(:terminals) { nil }
+
visit terminal_project_environment_path(project, environment)
end
@@ -154,7 +214,8 @@ describe 'Environment' do
end
let(:deployment) do
- create(:deployment, environment: environment,
+ create(:deployment, :success,
+ environment: environment,
deployable: build,
on_stop: 'close_app')
end
@@ -165,10 +226,10 @@ describe 'Environment' do
name: action.ref, project: project)
end
- it 'allows to stop environment' do
+ it 'allows to stop environment', :js do
click_button('Stop')
click_button('Stop environment') # confirm modal
-
+ wait_for_all_requests
expect(page).to have_content('close_app')
end
end
diff --git a/spec/features/projects/environments/environments_spec.rb b/spec/features/projects/environments/environments_spec.rb
index f0890018286..89954d35f91 100644
--- a/spec/features/projects/environments/environments_spec.rb
+++ b/spec/features/projects/environments/environments_spec.rb
@@ -95,7 +95,7 @@ describe 'Environments page', :js do
end
it 'does not show environments and counters are set to zero' do
- expect(page).to have_content('You don\'t have any environments right now.')
+ expect(page).to have_content('You don\'t have any environments right now')
expect(page.find('.js-environments-tab-available .badge').text).to eq('0')
expect(page.find('.js-environments-tab-stopped .badge').text).to eq('0')
@@ -128,11 +128,12 @@ describe 'Environments page', :js do
end
end
- context 'when there are deployments' do
+ context 'when there are successful deployments' do
let(:project) { create(:project, :repository) }
let!(:deployment) do
- create(:deployment, environment: environment,
+ create(:deployment, :success,
+ environment: environment,
sha: project.commit.id)
end
@@ -152,7 +153,8 @@ describe 'Environments page', :js do
end
let!(:deployment) do
- create(:deployment, environment: environment,
+ create(:deployment, :success,
+ environment: environment,
deployable: build,
sha: project.commit.id)
end
@@ -162,7 +164,7 @@ describe 'Environments page', :js do
end
it 'shows a play button' do
- find('.js-dropdown-play-icon-container').click
+ find('.js-environment-actions-dropdown').click
expect(page).to have_content(action.name.humanize)
end
@@ -170,7 +172,7 @@ describe 'Environments page', :js do
it 'allows to play a manual action', :js do
expect(action).to be_manual
- find('.js-dropdown-play-icon-container').click
+ find('.js-environment-actions-dropdown').click
expect(page).to have_content(action.name.humanize)
expect { find('.js-manual-action-link').click }
@@ -196,7 +198,7 @@ describe 'Environments page', :js do
context 'with external_url' do
let(:environment) { create(:environment, project: project, external_url: 'https://git.gitlab.com') }
let(:build) { create(:ci_build, pipeline: pipeline) }
- let(:deployment) { create(:deployment, environment: environment, deployable: build) }
+ let(:deployment) { create(:deployment, :success, environment: environment, deployable: build) }
it 'shows an external link button' do
expect(page).to have_link(nil, href: environment.external_url)
@@ -209,7 +211,8 @@ describe 'Environments page', :js do
end
let(:deployment) do
- create(:deployment, environment: environment,
+ create(:deployment, :success,
+ environment: environment,
deployable: build,
on_stop: 'close_app')
end
@@ -260,6 +263,86 @@ describe 'Environments page', :js do
end
end
end
+
+ context 'when there is a delayed job' do
+ let!(:pipeline) { create(:ci_pipeline, project: project) }
+ let!(:build) { create(:ci_build, pipeline: pipeline) }
+
+ let!(:delayed_job) do
+ create(:ci_build, :scheduled,
+ pipeline: pipeline,
+ name: 'delayed job',
+ stage: 'test',
+ commands: 'test')
+ end
+
+ let!(:deployment) do
+ create(:deployment,
+ :success,
+ environment: environment,
+ deployable: build,
+ sha: project.commit.id)
+ end
+
+ before do
+ visit_environments(project)
+ end
+
+ it 'has a dropdown for actionable jobs' do
+ expect(page).to have_selector('.dropdown-new.btn.btn-default .ic-play')
+ end
+
+ it "has link to the delayed job's action" do
+ find('.js-environment-actions-dropdown').click
+
+ expect(page).to have_button('Delayed job')
+ expect(page).to have_content(/\d{2}:\d{2}:\d{2}/)
+ end
+
+ context 'when delayed job is expired already' do
+ let!(:delayed_job) do
+ create(:ci_build, :expired_scheduled,
+ pipeline: pipeline,
+ name: 'delayed job',
+ stage: 'test',
+ commands: 'test')
+ end
+
+ it "shows 00:00:00 as the remaining time" do
+ find('.js-environment-actions-dropdown').click
+
+ expect(page).to have_content("00:00:00")
+ end
+ end
+
+ context 'when user played a delayed job immediately' do
+ before do
+ find('.js-environment-actions-dropdown').click
+ page.accept_confirm { click_button('Delayed job') }
+ wait_for_requests
+ end
+
+ it 'enqueues the delayed job', :js do
+ expect(delayed_job.reload).to be_pending
+ end
+ end
+ end
+ end
+
+ context 'when there is a failed deployment' do
+ let(:project) { create(:project, :repository) }
+
+ let!(:deployment) do
+ create(:deployment, :failed,
+ environment: environment,
+ sha: project.commit.id)
+ end
+
+ it 'does not show deployments' do
+ visit_environments(project)
+
+ expect(page).to have_content('No deployments yet')
+ end
end
end
diff --git a/spec/features/projects/files/user_creates_files_spec.rb b/spec/features/projects/files/user_creates_files_spec.rb
index d4dda43c823..a4f94b7a76d 100644
--- a/spec/features/projects/files/user_creates_files_spec.rb
+++ b/spec/features/projects/files/user_creates_files_spec.rb
@@ -16,7 +16,7 @@ describe 'Projects > Files > User creates files' do
sign_in(user)
end
- context 'without commiting a new file' do
+ context 'without committing a new file' do
context 'when an user has write access' do
before do
visit(project_tree_path_root_ref)
@@ -49,7 +49,7 @@ describe 'Projects > Files > User creates files' do
end
end
- context 'with commiting a new file' do
+ context 'with committing a new file' do
context 'when an user has write access' do
before do
visit(project_tree_path_root_ref)
diff --git a/spec/features/projects/files/user_deletes_files_spec.rb b/spec/features/projects/files/user_deletes_files_spec.rb
index dcb7b947c61..614b11fa5c8 100644
--- a/spec/features/projects/files/user_deletes_files_spec.rb
+++ b/spec/features/projects/files/user_deletes_files_spec.rb
@@ -31,7 +31,7 @@ describe 'Projects > Files > User deletes files', :js do
fill_in(:commit_message, with: 'New commit message', visible: true)
click_button('Delete file')
- expect(current_path).to eq(project_tree_path(project, 'master'))
+ expect(current_path).to eq(project_tree_path(project, 'master/'))
expect(page).not_to have_content('.gitignore')
end
end
diff --git a/spec/features/projects/fork_spec.rb b/spec/features/projects/fork_spec.rb
index cd5fef8238e..7c71b4c52e0 100644
--- a/spec/features/projects/fork_spec.rb
+++ b/spec/features/projects/fork_spec.rb
@@ -53,6 +53,18 @@ describe 'Project fork' do
expect(current_path).to have_content(/#{user.namespace.name}/i)
end
+ it 'shows avatars when Gravatar is disabled' do
+ stub_application_setting(gravatar_enabled: false)
+
+ visit project_path(project)
+
+ click_link 'Fork'
+
+ page.within('.fork-thumbnail-container') do
+ expect(page).to have_css('div.identicon')
+ end
+ end
+
it 'shows the forked project on the list' do
visit project_path(project)
diff --git a/spec/features/projects/import_export/export_file_spec.rb b/spec/features/projects/import_export/export_file_spec.rb
index a2b96514d64..f76f9ba7577 100644
--- a/spec/features/projects/import_export/export_file_spec.rb
+++ b/spec/features/projects/import_export/export_file_spec.rb
@@ -12,7 +12,7 @@ describe 'Import/Export - project export integration test', :js do
let(:export_path) { "#{Dir.tmpdir}/import_file_spec" }
let(:config_hash) { YAML.load_file(Gitlab::ImportExport.config_file).deep_stringify_keys }
- let(:sensitive_words) { %w[pass secret token key] }
+ let(:sensitive_words) { %w[pass secret token key encrypted] }
let(:safe_list) do
{
token: [ProjectHook, Ci::Trigger, CommitStatus],
diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb
index 65c68277167..28ae90bc0de 100644
--- a/spec/features/projects/import_export/import_file_spec.rb
+++ b/spec/features/projects/import_export/import_file_spec.rb
@@ -21,8 +21,9 @@ describe 'Import/Export - project import integration test', :js do
context 'when selecting the namespace' do
let(:user) { create(:admin) }
let!(:namespace) { user.namespace }
- let(:project_name) { 'Test Project Name' + SecureRandom.hex }
- let(:project_path) { 'test-project-path' + SecureRandom.hex }
+ let(:randomHex) { SecureRandom.hex }
+ let(:project_name) { 'Test Project Name' + randomHex }
+ let(:project_path) { 'test-project-name' + randomHex }
context 'prefilled the path' do
it 'user imports an exported project successfully' do
@@ -30,7 +31,6 @@ describe 'Import/Export - project import integration test', :js do
select2(namespace.id, from: '#project_namespace_id')
fill_in :project_name, with: project_name, visible: true
- fill_in :project_path, with: project_path, visible: true
click_import_project_tab
click_link 'GitLab export'
@@ -79,7 +79,6 @@ describe 'Import/Export - project import integration test', :js do
select2(user.namespace.id, from: '#project_namespace_id')
fill_in :project_name, with: project.name, visible: true
- fill_in :project_path, with: project.path, visible: true
click_import_project_tab
click_link 'GitLab export'
attach_file('file', file)
diff --git a/spec/features/projects/jobs/permissions_spec.rb b/spec/features/projects/jobs/permissions_spec.rb
index e639f0cf82e..6ce37297a7e 100644
--- a/spec/features/projects/jobs/permissions_spec.rb
+++ b/spec/features/projects/jobs/permissions_spec.rb
@@ -67,7 +67,7 @@ describe 'Project Jobs Permissions' do
it_behaves_like 'recent job page details responds with status', 200 do
it 'renders job details', :js do
expect(page).to have_content "Job ##{job.id}"
- expect(page).to have_css '#build-trace'
+ expect(page).to have_css '.js-build-trace'
end
end
diff --git a/spec/features/projects/jobs/user_browses_job_spec.rb b/spec/features/projects/jobs/user_browses_job_spec.rb
index 2d791947ee9..908c616f2fc 100644
--- a/spec/features/projects/jobs/user_browses_job_spec.rb
+++ b/spec/features/projects/jobs/user_browses_job_spec.rb
@@ -16,9 +16,11 @@ describe 'User browses a job', :js do
visit(project_job_path(project, build))
end
- it 'erases the job log' do
+ it 'erases the job log', :js do
+ wait_for_requests
+
expect(page).to have_content("Job ##{build.id}")
- expect(page).to have_css('#build-trace')
+ expect(page).to have_css('.js-build-trace')
# scroll to the top of the page first
execute_script "window.scrollTo(0,0)"
@@ -29,18 +31,17 @@ describe 'User browses a job', :js do
expect(build.artifacts_file.exists?).to be_falsy
expect(build.artifacts_metadata.exists?).to be_falsy
- page.within('.erased') do
- expect(page).to have_content('Job has been erased')
- end
+ expect(page).to have_content('Job has been erased')
end
context 'with a failed job' do
let!(:build) { create(:ci_build, :failed, :trace_artifact, pipeline: pipeline) }
it 'displays the failure reason' do
+ wait_for_all_requests
within('.builds-container') do
build_link = first('.build-job > a')
- expect(build_link['data-title']).to eq('test - failed - (unknown failure)')
+ expect(build_link['data-original-title']).to eq('test - failed - (unknown failure)')
end
end
end
@@ -49,9 +50,10 @@ describe 'User browses a job', :js do
let!(:build) { create(:ci_build, :failed, :retried, :trace_artifact, pipeline: pipeline) }
it 'displays the failure reason and retried label' do
+ wait_for_all_requests
within('.builds-container') do
build_link = first('.build-job > a')
- expect(build_link['data-title']).to eq('test - failed - (unknown failure) (retried)')
+ expect(build_link['data-original-title']).to eq('test - failed - (unknown failure) (retried)')
end
end
end
diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb
index 83293c0ca7d..d7c4abffddd 100644
--- a/spec/features/projects/jobs_spec.rb
+++ b/spec/features/projects/jobs_spec.rb
@@ -5,7 +5,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
let(:user) { create(:user) }
let(:user_access_level) { :developer }
let(:project) { create(:project, :repository) }
- let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:pipeline) { create(:ci_pipeline, project: project, sha: project.commit('HEAD').sha) }
let(:job) { create(:ci_build, :trace_live, pipeline: pipeline) }
let(:job2) { create(:ci_build) }
@@ -20,7 +20,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
describe "GET /:project/jobs" do
- let!(:job) { create(:ci_build, pipeline: pipeline) }
+ let!(:job) { create(:ci_build, pipeline: pipeline) }
context "Pending scope" do
before do
@@ -115,37 +115,44 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
context "Job from project" do
let(:job) { create(:ci_build, :success, :trace_live, pipeline: pipeline) }
- before do
+ it 'shows status name', :js do
visit project_job_path(project, job)
- end
- it 'shows status name', :js do
+ wait_for_requests
+
expect(page).to have_css('.ci-status.ci-success', text: 'passed')
end
- it 'shows commit`s data' do
- expect(page.status_code).to eq(200)
+ it 'shows commit`s data', :js do
+ requests = inspect_requests() do
+ visit project_job_path(project, job)
+ end
+
+ wait_for_requests
+ expect(requests.first.status_code).to eq(200)
expect(page).to have_content pipeline.sha[0..7]
- expect(page).to have_content pipeline.git_commit_message
- expect(page).to have_content pipeline.git_author_name
+ expect(page).to have_content pipeline.commit.title
end
- it 'shows active job' do
+ it 'shows active job', :js do
+ visit project_job_path(project, job)
+
+ wait_for_requests
expect(page).to have_selector('.build-job.active')
end
end
- context 'sidebar' do
+ context 'sidebar', :js do
let(:job) { create(:ci_build, :success, :trace_live, pipeline: pipeline, name: '<img src=x onerror=alert(document.domain)>') }
before do
visit project_job_path(project, job)
+ wait_for_requests
end
it 'renders escaped tooltip name' do
- page.within('aside.right-sidebar') do
- expect(find('.active.build-job a')['data-title']).to eq('<img src="x"> - passed')
- end
+ page.find('.active.build-job a').hover
+ expect(page).to have_content('<img src=x onerror=alert(document.domain)> - passed')
end
end
@@ -191,6 +198,24 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
end
+ context 'when job is running', :js do
+ let(:job) { create(:ci_build, :running, pipeline: pipeline) }
+ let(:job_url) { project_job_path(project, job) }
+
+ before do
+ visit job_url
+ wait_for_requests
+ end
+
+ context 'job is cancelable' do
+ it 'shows cancel button' do
+ click_link 'Cancel'
+
+ expect(page.current_path).to eq(job_url)
+ end
+ end
+ end
+
context "Job from other project" do
before do
visit project_job_path(project, job2)
@@ -199,7 +224,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
it { expect(page.status_code).to eq(404) }
end
- context "Download artifacts" do
+ context "Download artifacts", :js do
before do
job.update(legacy_artifacts_file: artifacts_file)
visit project_job_path(project, job)
@@ -208,9 +233,22 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
it 'has button to download artifacts' do
expect(page).to have_content 'Download'
end
+
+ it 'downloads the zip file when user clicks the download button' do
+ requests = inspect_requests() do
+ click_link 'Download'
+ end
+
+ artifact_request = requests.find { |req| req.url.match(%r{artifacts/download}) }
+
+ expect(artifact_request.response_headers["Content-Disposition"]).to eq(%Q{attachment; filename="#{job.artifacts_file.filename}"})
+ expect(artifact_request.response_headers['Content-Transfer-Encoding']).to eq("binary")
+ expect(artifact_request.response_headers['Content-Type']).to eq("image/gif")
+ expect(artifact_request.body).to eq(job.artifacts_file.file.read.b)
+ end
end
- context 'Artifacts expire date' do
+ context 'Artifacts expire date', :js do
before do
job.update(legacy_artifacts_file: artifacts_file,
artifacts_expire_at: expire_at)
@@ -231,12 +269,12 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
context 'when user has ability to update job' do
it 'keeps artifacts when keep button is clicked' do
- expect(page).to have_content 'The artifacts will be removed'
+ expect(page).to have_content 'The artifacts will be removed in'
click_link 'Keep'
expect(page).to have_no_link 'Keep'
- expect(page).to have_no_content 'The artifacts will be removed'
+ expect(page).to have_no_content 'The artifacts will be removed in'
end
end
@@ -273,7 +311,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
end
- describe 'Raw trace' do
+ describe 'Raw trace', :js do
before do
job.run!
@@ -281,7 +319,8 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
it do
- expect(page).to have_css('.js-raw-link')
+ wait_for_all_requests
+ expect(page).to have_css('.js-raw-link-controller')
end
end
@@ -314,6 +353,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
shared_examples 'expected variables behavior' do
it 'shows variable key and value after click', :js do
+ expect(page).to have_content('Token')
expect(page).to have_css('.js-reveal-variables')
expect(page).not_to have_css('.js-build-variable')
expect(page).not_to have_css('.js-build-value')
@@ -347,39 +387,176 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
end
- context 'when job starts environment' do
- let(:environment) { create(:environment, project: project) }
- let(:pipeline) { create(:ci_pipeline, project: project) }
+ context 'when job starts environment', :js do
+ let(:environment) { create(:environment, name: 'production', project: project) }
+
+ before do
+ visit project_job_path(project, build)
+ wait_for_requests
+ end
- context 'job is successfull and has deployment' do
- let(:deployment) { create(:deployment) }
- let(:job) { create(:ci_build, :success, :trace_artifact, environment: environment.name, deployments: [deployment], pipeline: pipeline) }
+ context 'job is successful and has deployment' do
+ let(:build) { create(:ci_build, :success, :trace_live, environment: environment.name, pipeline: pipeline, deployment: deployment) }
+ let(:deployment) { create(:deployment, :success, environment: environment, project: environment.project) }
it 'shows a link for the job' do
- visit project_job_path(project, job)
-
expect(page).to have_link environment.name
end
+
+ it 'shows deployment message' do
+ expect(page).to have_content 'This job is the most recent deployment'
+ expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}")
+ end
end
context 'job is complete and not successful' do
- let(:job) { create(:ci_build, :failed, :trace_artifact, environment: environment.name, pipeline: pipeline) }
+ let(:build) { create(:ci_build, :failed, :trace_artifact, environment: environment.name, pipeline: pipeline) }
it 'shows a link for the job' do
- visit project_job_path(project, job)
-
expect(page).to have_link environment.name
+ expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}")
end
end
- context 'job creates a new deployment' do
- let!(:deployment) { create(:deployment, environment: environment, sha: project.commit.id) }
- let(:job) { create(:ci_build, :success, :trace_artifact, environment: environment.name, pipeline: pipeline) }
+ context 'deployment still not finished' do
+ let(:build) { create(:ci_build, :running, environment: environment.name, pipeline: pipeline) }
it 'shows a link to latest deployment' do
- visit project_job_path(project, job)
+ expect(page).to have_link environment.name
+ expect(page).to have_content 'This job is creating a deployment'
+ expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}")
+ end
+ end
+ end
+
+ context 'when job stops environment', :js do
+ let(:environment) { create(:environment, name: 'production', project: project) }
+ let(:build) do
+ create(
+ :ci_build,
+ :success,
+ :trace_live,
+ environment: environment.name,
+ pipeline: pipeline,
+ options: { environment: { action: 'stop' } }
+ )
+ end
+
+ before do
+ visit project_job_path(project, build)
+ wait_for_requests
+ end
+
+ it 'does not show environment information banner' do
+ expect(page).not_to have_selector('.js-environment-container')
+ expect(page).not_to have_selector('.environment-information')
+ expect(page).not_to have_text(environment.name)
+ end
+ end
+
+ describe 'environment info in job view', :js do
+ before do
+ allow_any_instance_of(Ci::Build).to receive(:create_deployment)
+
+ visit project_job_path(project, job)
+ wait_for_requests
+ end
+
+ context 'job with outdated deployment' do
+ let(:job) { create(:ci_build, :success, :trace_artifact, environment: 'staging', pipeline: pipeline) }
+ let(:second_build) { create(:ci_build, :success, :trace_artifact, environment: 'staging', pipeline: pipeline) }
+ let(:environment) { create(:environment, name: 'staging', project: project) }
+ let!(:first_deployment) { create(:deployment, :success, environment: environment, deployable: job) }
+ let!(:second_deployment) { create(:deployment, :success, environment: environment, deployable: second_build) }
+
+ it 'shows deployment message' do
+ expected_text = 'This job is an out-of-date deployment ' \
+ "to staging. View the most recent deployment ##{second_deployment.iid}."
+
+ expect(page).to have_css('.environment-information', text: expected_text)
+ end
+
+ it 'renders a link to the most recent deployment' do
+ expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}")
+ expect(find('.js-job-deployment-link')['href']).to include(second_deployment.deployable.project.path, second_deployment.deployable_id.to_s)
+ end
+ end
+
+ context 'job failed to deploy' do
+ let(:job) { create(:ci_build, :failed, :trace_artifact, environment: 'staging', pipeline: pipeline) }
+ let!(:environment) { create(:environment, name: 'staging', project: project) }
+
+ it 'shows deployment message' do
+ expected_text = 'The deployment of this job to staging did not succeed.'
+
+ expect(page).to have_css('.environment-information', text: expected_text)
+ end
+ end
+
+ context 'job will deploy' do
+ let(:job) { create(:ci_build, :running, :trace_live, environment: 'staging', pipeline: pipeline) }
+
+ context 'when environment exists' do
+ let!(:environment) { create(:environment, name: 'staging', project: project) }
+
+ it 'shows deployment message' do
+ expected_text = 'This job is creating a deployment to staging'
+
+ expect(page).to have_css('.environment-information', text: expected_text)
+ expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}")
+ end
+
+ context 'when it has deployment' do
+ let!(:deployment) { create(:deployment, :success, environment: environment) }
+
+ it 'shows that deployment will be overwritten' do
+ expected_text = 'This job is creating a deployment to staging'
- expect(page).to have_link('latest deployment')
+ expect(page).to have_css('.environment-information', text: expected_text)
+ expect(page).to have_css('.environment-information', text: 'latest deployment')
+ expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}")
+ end
+ end
+ end
+
+ context 'when environment does not exist' do
+ let!(:environment) { create(:environment, name: 'staging', project: project) }
+
+ it 'shows deployment message' do
+ expected_text = 'This job is creating a deployment to staging'
+
+ expect(page).to have_css(
+ '.environment-information', text: expected_text)
+ expect(page).not_to have_css(
+ '.environment-information', text: 'latest deployment')
+ expect(find('.js-environment-link')['href']).to match("environments/#{environment.id}")
+ end
+ end
+ end
+
+ context 'job that failed to deploy and environment has not been created' do
+ let(:job) { create(:ci_build, :failed, :trace_artifact, environment: 'staging', pipeline: pipeline) }
+ let!(:environment) { create(:environment, name: 'staging', project: project) }
+
+ it 'shows deployment message' do
+ expected_text = 'The deployment of this job to staging did not succeed'
+
+ expect(page).to have_css(
+ '.environment-information', text: expected_text)
+ end
+ end
+
+ context 'job that will deploy and environment has not been created' do
+ let(:job) { create(:ci_build, :running, :trace_live, environment: 'staging', pipeline: pipeline) }
+ let!(:environment) { create(:environment, name: 'staging', project: project) }
+
+ it 'shows deployment message' do
+ expected_text = 'This job is creating a deployment to staging'
+
+ expect(page).to have_css(
+ '.environment-information', text: expected_text)
+ expect(page).not_to have_css(
+ '.environment-information', text: 'latest deployment')
end
end
end
@@ -392,7 +569,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
visit project_job_path(project, job)
end
- it 'shows manual action empty state' do
+ it 'shows manual action empty state', :js do
expect(page).to have_content(job.detailed_status(user).illustration[:title])
expect(page).to have_content('This job requires a manual action')
expect(page).to have_content('This job depends on a user to trigger its process. Often they are used to deploy code to production environments')
@@ -409,6 +586,30 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
end
+ context 'Delayed job' do
+ let(:job) { create(:ci_build, :scheduled, pipeline: pipeline) }
+
+ before do
+ project.add_developer(user)
+ visit project_job_path(project, job)
+ end
+
+ it 'shows delayed job', :js do
+ expect(page).to have_content('This is a delayed job to run in')
+ expect(page).to have_content("This job will automatically run after its timer finishes.")
+ expect(page).to have_link('Unschedule job')
+ end
+
+ it 'unschedules delayed job and shows manual action', :js do
+ click_link 'Unschedule job'
+
+ wait_for_requests
+ expect(page).to have_content('This job requires a manual action')
+ expect(page).to have_content('This job depends on a user to trigger its process. Often they are used to deploy code to production environments')
+ expect(page).to have_link('Trigger this manual action')
+ end
+ end
+
context 'Non triggered job' do
let(:job) { create(:ci_build, :created, pipeline: pipeline) }
@@ -416,14 +617,14 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
visit project_job_path(project, job)
end
- it 'shows empty state' do
+ it 'shows empty state', :js do
expect(page).to have_content(job.detailed_status(user).illustration[:title])
expect(page).to have_content('This job has not been triggered yet')
expect(page).to have_content('This job depends on upstream jobs that need to succeed in order for this job to be triggered')
end
end
- context 'Pending job' do
+ context 'Pending job', :js do
let(:job) { create(:ci_build, :pending, pipeline: pipeline) }
before do
@@ -437,7 +638,7 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
end
- context 'Canceled job' do
+ context 'Canceled job', :js do
context 'with log' do
let(:job) { create(:ci_build, :canceled, :trace_artifact, pipeline: pipeline) }
@@ -446,11 +647,12 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
it 'renders job log' do
- expect(page).to have_selector('.js-build-output')
+ wait_for_all_requests
+ expect(page).to have_selector('.js-build-trace')
end
end
- context 'without log' do
+ context 'without log', :js do
let(:job) { create(:ci_build, :canceled, pipeline: pipeline) }
before do
@@ -459,13 +661,13 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
it 'renders empty state' do
expect(page).to have_content(job.detailed_status(user).illustration[:title])
- expect(page).not_to have_selector('.js-build-output')
+ expect(page).not_to have_selector('.js-build-trace')
expect(page).to have_content('This job has been canceled')
end
end
end
- context 'Skipped job' do
+ context 'Skipped job', :js do
let(:job) { create(:ci_build, :skipped, pipeline: pipeline) }
before do
@@ -474,12 +676,12 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
it 'renders empty state' do
expect(page).to have_content(job.detailed_status(user).illustration[:title])
- expect(page).not_to have_selector('.js-build-output')
+ expect(page).not_to have_selector('.js-build-trace')
expect(page).to have_content('This job has been skipped')
end
end
- context 'when job is failed but has no trace' do
+ context 'when job is failed but has no trace', :js do
let(:job) { create(:ci_build, :failed, pipeline: pipeline) }
it 'renders empty state' do
@@ -489,6 +691,112 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
expect(page).to have_content('This job does not have a trace.')
end
end
+
+ context 'with erased job', :js do
+ let(:job) { create(:ci_build, :erased, pipeline: pipeline) }
+
+ it 'renders erased job warning' do
+ visit project_job_path(project, job)
+ wait_for_requests
+
+ page.within('.js-job-erased-block') do
+ expect(page).to have_content('Job has been erased')
+ end
+ end
+ end
+
+ context 'without erased job', :js do
+ let(:job) { create(:ci_build, pipeline: pipeline) }
+
+ it 'does not render erased job warning' do
+ visit project_job_path(project, job)
+ wait_for_requests
+
+ expect(page).not_to have_css('.js-job-erased-block')
+ end
+ end
+
+ context 'on mobile', :js do
+ let(:job) { create(:ci_build, pipeline: pipeline) }
+
+ it 'renders collapsed sidebar' do
+ page.current_window.resize_to(600, 800)
+
+ visit project_job_path(project, job)
+ wait_for_requests
+
+ expect(page).to have_css('.js-job-sidebar.right-sidebar-collapsed', visible: false)
+ expect(page).not_to have_css('.js-job-sidebar.right-sidebar-expanded', visible: false)
+ end
+ end
+
+ context 'on desktop', :js do
+ let(:job) { create(:ci_build, pipeline: pipeline) }
+
+ it 'renders expanded sidebar' do
+ visit project_job_path(project, job)
+ wait_for_requests
+
+ expect(page).to have_css('.js-job-sidebar.right-sidebar-expanded')
+ expect(page).not_to have_css('.js-job-sidebar.right-sidebar-collapsed')
+ end
+ end
+
+ context 'stuck', :js do
+ before do
+ visit project_job_path(project, job)
+ wait_for_requests
+ end
+
+ context 'without active runners available' do
+ let(:runner) { create(:ci_runner, :instance, active: false) }
+ let(:job) { create(:ci_build, :pending, pipeline: pipeline, runner: runner) }
+
+ it 'renders message about job being stuck because no runners are active' do
+ expect(page).to have_css('.js-stuck-no-active-runner')
+ expect(page).to have_content("This job is stuck because you don't have any active runners that can run this job.")
+ end
+ end
+
+ context 'when available runners can not run specified tag' do
+ let(:runner) { create(:ci_runner, :instance, active: false) }
+ let(:job) { create(:ci_build, :pending, pipeline: pipeline, runner: runner, tag_list: %w(docker linux)) }
+
+ it 'renders message about job being stuck because of no runners with the specified tags' do
+ expect(page).to have_css('.js-stuck-with-tags')
+ expect(page).to have_content("This job is stuck because you don't have any active runners online with any of these tags assigned to them:")
+ end
+ end
+
+ context 'when runners are offline and build has tags' do
+ let(:runner) { create(:ci_runner, :instance, active: true) }
+ let(:job) { create(:ci_build, :pending, pipeline: pipeline, runner: runner, tag_list: %w(docker linux)) }
+
+ it 'renders message about job being stuck because of no runners with the specified tags' do
+ expect(page).to have_css('.js-stuck-with-tags')
+ expect(page).to have_content("This job is stuck because you don't have any active runners online with any of these tags assigned to them:")
+ end
+ end
+
+ context 'without any runners available' do
+ let(:job) { create(:ci_build, :pending, pipeline: pipeline) }
+
+ it 'renders message about job being stuck because not runners are available' do
+ expect(page).to have_css('.js-stuck-no-active-runner')
+ expect(page).to have_content("This job is stuck because you don't have any active runners that can run this job.")
+ end
+ end
+
+ context 'without available runners online' do
+ let(:runner) { create(:ci_runner, :instance, active: true) }
+ let(:job) { create(:ci_build, :pending, pipeline: pipeline, runner: runner) }
+
+ it 'renders message about job being stuck because runners are offline' do
+ expect(page).to have_css('.js-stuck-no-runners')
+ expect(page).to have_content("This job is stuck because the project doesn't have any runners online assigned to it.")
+ end
+ end
+ end
end
describe "POST /:project/jobs/:id/cancel", :js do
@@ -542,20 +850,26 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
end
end
- describe "GET /:project/jobs/:id/download" do
+ describe "GET /:project/jobs/:id/download", :js do
before do
job.update(legacy_artifacts_file: artifacts_file)
visit project_job_path(project, job)
+
click_link 'Download'
end
context "Build from other project" do
before do
job2.update(legacy_artifacts_file: artifacts_file)
- visit download_project_job_artifacts_path(project, job2)
end
- it { expect(page.status_code).to eq(404) }
+ it do
+ requests = inspect_requests() do
+ visit download_project_job_artifacts_path(project, job2)
+ end
+
+ expect(requests.first.status_code).to eq(404)
+ end
end
end
diff --git a/spec/features/projects/labels/issues_sorted_by_priority_spec.rb b/spec/features/projects/labels/issues_sorted_by_priority_spec.rb
index 6178f11ded7..b778c72bc76 100644
--- a/spec/features/projects/labels/issues_sorted_by_priority_spec.rb
+++ b/spec/features/projects/labels/issues_sorted_by_priority_spec.rb
@@ -32,7 +32,7 @@ describe 'Issue prioritization' do
visit project_issues_path(project, sort: 'label_priority')
# Ensure we are indicating that issues are sorted by priority
- expect(page).to have_selector('.dropdown-toggle', text: 'Label priority')
+ expect(page).to have_selector('.dropdown-menu-toggle', text: 'Label priority')
page.within('.issues-holder') do
issue_titles = all('.issues-list .issue-title-text').map(&:text)
@@ -70,7 +70,7 @@ describe 'Issue prioritization' do
sign_in user
visit project_issues_path(project, sort: 'label_priority')
- expect(page).to have_selector('.dropdown-toggle', text: 'Label priority')
+ expect(page).to have_selector('.dropdown-menu-toggle', text: 'Label priority')
page.within('.issues-holder') do
issue_titles = all('.issues-list .issue-title-text').map(&:text)
diff --git a/spec/features/projects/labels/user_sees_breadcrumb_links_spec.rb b/spec/features/projects/labels/user_sees_breadcrumb_links_spec.rb
new file mode 100644
index 00000000000..0c0501f438a
--- /dev/null
+++ b/spec/features/projects/labels/user_sees_breadcrumb_links_spec.rb
@@ -0,0 +1,17 @@
+require 'rails_helper'
+
+describe 'New project label breadcrumb' do
+ let(:project) { create(:project) }
+ let(:user) { project.creator }
+
+ before do
+ sign_in(user)
+ visit(project_labels_path(project))
+ end
+
+ it 'displays link to project labels and new project label' do
+ page.within '.breadcrumbs' do
+ expect(find_link('Labels')[:href]).to end_with(project_labels_path(project))
+ end
+ end
+end
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index 603503a531c..049bbca958f 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -31,6 +31,11 @@ describe 'Pipeline', :js do
pipeline: pipeline, stage: 'deploy', name: 'manual-build')
end
+ let!(:build_scheduled) do
+ create(:ci_build, :scheduled,
+ pipeline: pipeline, stage: 'deploy', name: 'delayed-job')
+ end
+
let!(:build_external) do
create(:generic_commit_status, status: 'success',
pipeline: pipeline,
@@ -63,6 +68,10 @@ describe 'Pipeline', :js do
expect(page).to have_css('#js-tab-pipeline.active')
end
+ it 'shows link to the pipeline ref' do
+ expect(page).to have_link(pipeline.ref)
+ end
+
it_behaves_like 'showing user status' do
let(:user_with_status) { pipeline.user }
@@ -79,10 +88,12 @@ describe 'Pipeline', :js do
end
end
- it 'should be possible to cancel the running build' do
+ it 'cancels the running build and shows retry button' do
find('#ci-badge-deploy .ci-action-icon-container').click
- expect(page).not_to have_content('Cancel running')
+ page.within('#ci-badge-deploy') do
+ expect(page).to have_css('.js-icon-retry')
+ end
end
end
@@ -105,6 +116,27 @@ describe 'Pipeline', :js do
end
end
+ context 'when pipeline has a delayed job' do
+ it 'shows the scheduled icon and an unschedule action for the delayed job' do
+ page.within('#ci-badge-delayed-job') do
+ expect(page).to have_selector('.js-ci-status-icon-scheduled')
+ expect(page).to have_content('delayed-job')
+ end
+
+ page.within('#ci-badge-delayed-job .ci-action-icon-container.js-icon-time-out') do
+ expect(page).to have_selector('svg')
+ end
+ end
+
+ it 'unschedules the delayed job and shows play button as a manual job' do
+ find('#ci-badge-delayed-job .ci-action-icon-container').click
+
+ page.within('#ci-badge-delayed-job') do
+ expect(page).to have_css('.js-icon-play')
+ end
+ end
+ end
+
context 'when pipeline has failed builds' do
it 'shows the failed icon and a retry action for the failed build' do
page.within('#ci-badge-test') do
@@ -208,6 +240,20 @@ describe 'Pipeline', :js do
it { expect(page).not_to have_content('Cancel running') }
end
end
+
+ context 'when pipeline ref does not exist in repository anymore' do
+ let(:pipeline) do
+ create(:ci_empty_pipeline, project: project,
+ ref: 'non-existent',
+ sha: project.commit.id,
+ user: user)
+ end
+
+ it 'does not render link to the pipeline ref' do
+ expect(page).not_to have_link(pipeline.ref)
+ expect(page).to have_content(pipeline.ref)
+ end
+ end
end
context 'when user does not have access to read jobs' do
@@ -315,6 +361,18 @@ describe 'Pipeline', :js do
it { expect(build_manual.reload).to be_pending }
end
+ context 'when user unschedules a delayed job' do
+ before do
+ within '.pipeline-holder' do
+ click_link('Unschedule')
+ end
+ end
+
+ it 'unschedules the delayed job and shows play button as a manual job' do
+ expect(page).to have_content('Trigger this manual action')
+ end
+ end
+
context 'failed jobs' do
it 'displays a tooltip with the failure reason' do
page.within('.ci-table') do
@@ -330,54 +388,83 @@ describe 'Pipeline', :js do
let(:pipeline_failures_page) { failures_project_pipeline_path(project, pipeline) }
let!(:failed_build) { create(:ci_build, :failed, pipeline: pipeline) }
+ subject { visit pipeline_failures_page }
+
context 'with failed build' do
before do
failed_build.trace.set('4 examples, 1 failure')
-
- visit pipeline_failures_page
end
it 'shows jobs tab pane as active' do
+ subject
+
expect(page).to have_content('Failed Jobs')
expect(page).to have_css('#js-tab-failures.active')
end
it 'lists failed builds' do
+ subject
+
expect(page).to have_content(failed_build.name)
expect(page).to have_content(failed_build.stage)
end
it 'shows build failure logs' do
+ subject
+
expect(page).to have_content('4 examples, 1 failure')
end
it 'shows the failure reason' do
+ subject
+
expect(page).to have_content('There is an unknown failure, please try again')
end
- it 'shows retry button for failed build' do
- page.within(find('.build-failures', match: :first)) do
- expect(page).to have_link('Retry')
+ context 'when user does not have permission to retry build' do
+ it 'shows retry button for failed build' do
+ subject
+
+ page.within(find('.build-failures', match: :first)) do
+ expect(page).not_to have_link('Retry')
+ end
end
end
- end
- context 'when missing build logs' do
- before do
- visit pipeline_failures_page
+ context 'when user does have permission to retry build' do
+ before do
+ create(:protected_branch, :developers_can_merge,
+ name: pipeline.ref, project: project)
+ end
+
+ it 'shows retry button for failed build' do
+ subject
+
+ page.within(find('.build-failures', match: :first)) do
+ expect(page).to have_link('Retry')
+ end
+ end
end
+ end
+ context 'when missing build logs' do
it 'shows jobs tab pane as active' do
+ subject
+
expect(page).to have_content('Failed Jobs')
expect(page).to have_css('#js-tab-failures.active')
end
it 'lists failed builds' do
+ subject
+
expect(page).to have_content(failed_build.name)
expect(page).to have_content(failed_build.stage)
end
it 'does not show trace' do
+ subject
+
expect(page).to have_content('No job trace')
end
end
@@ -390,11 +477,9 @@ describe 'Pipeline', :js do
end
context 'when accessing failed jobs page' do
- before do
- visit pipeline_failures_page
- end
-
it 'fails to access the page' do
+ subject
+
expect(page).to have_title('Access Denied')
end
end
@@ -403,11 +488,11 @@ describe 'Pipeline', :js do
context 'without failures' do
before do
failed_build.update!(status: :success)
-
- visit pipeline_failures_page
end
it 'displays the pipeline graph' do
+ subject
+
expect(current_path).to eq(pipeline_path(pipeline))
expect(page).not_to have_content('Failed Jobs')
expect(page).to have_selector('.pipeline-visualization')
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index 41822babbc9..17772a35779 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -232,6 +232,60 @@ describe 'Pipelines', :js do
end
end
+ context 'when there is a delayed job' do
+ let!(:delayed_job) do
+ create(:ci_build, :scheduled,
+ pipeline: pipeline,
+ name: 'delayed job',
+ stage: 'test',
+ commands: 'test')
+ end
+
+ before do
+ visit_project_pipelines
+ end
+
+ it 'has a dropdown for actionable jobs' do
+ expect(page).to have_selector('.dropdown-new.btn.btn-default .icon-play')
+ end
+
+ it "has link to the delayed job's action" do
+ find('.js-pipeline-dropdown-manual-actions').click
+
+ time_diff = [0, delayed_job.scheduled_at - Time.now].max
+ expect(page).to have_button('delayed job')
+ expect(page).to have_content(Time.at(time_diff).utc.strftime("%H:%M:%S"))
+ end
+
+ context 'when delayed job is expired already' do
+ let!(:delayed_job) do
+ create(:ci_build, :expired_scheduled,
+ pipeline: pipeline,
+ name: 'delayed job',
+ stage: 'test',
+ commands: 'test')
+ end
+
+ it "shows 00:00:00 as the remaining time" do
+ find('.js-pipeline-dropdown-manual-actions').click
+
+ expect(page).to have_content("00:00:00")
+ end
+ end
+
+ context 'when user played a delayed job immediately' do
+ before do
+ find('.js-pipeline-dropdown-manual-actions').click
+ page.accept_confirm { click_button('delayed job') }
+ wait_for_requests
+ end
+
+ it 'enqueues the delayed job', :js do
+ expect(delayed_job.reload).to be_pending
+ end
+ end
+ end
+
context 'for generic statuses' do
context 'when running' do
let!(:running) do
diff --git a/spec/features/projects/settings/pipelines_settings_spec.rb b/spec/features/projects/settings/pipelines_settings_spec.rb
index 30b0a5578ea..6f8ec0015ad 100644
--- a/spec/features/projects/settings/pipelines_settings_spec.rb
+++ b/spec/features/projects/settings/pipelines_settings_spec.rb
@@ -137,5 +137,29 @@ describe "Projects > Settings > Pipelines settings" do
end
end
end
+
+ describe 'runners registration token' do
+ let!(:token) { project.runners_token }
+
+ before do
+ visit project_settings_ci_cd_path(project)
+ end
+
+ it 'has a registration token' do
+ expect(page.find('#registration_token')).to have_content(token)
+ end
+
+ describe 'reload registration token' do
+ let(:page_token) { find('#registration_token').text }
+
+ before do
+ click_button 'Reset runners registration token'
+ end
+
+ it 'changes registration token' do
+ expect(page_token).not_to eq token
+ end
+ end
+ end
end
end
diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb
index 377a75cbcb3..b7a22316d26 100644
--- a/spec/features/projects/settings/repository_settings_spec.rb
+++ b/spec/features/projects/settings/repository_settings_spec.rb
@@ -132,6 +132,69 @@ describe 'Projects > Settings > Repository settings' do
it 'shows push mirror settings', :js do
expect(page).to have_selector('#mirror_direction')
end
+
+ it 'creates a push mirror that mirrors all branches', :js do
+ expect(find('.js-mirror-protected-hidden', visible: false).value).to eq('0')
+
+ fill_in 'url', with: 'ssh://user@localhost/project.git'
+ select 'SSH public key', from: 'Authentication method'
+
+ select_direction
+
+ Sidekiq::Testing.fake! do
+ click_button 'Mirror repository'
+ end
+
+ project.reload
+
+ expect(page).to have_content('Mirroring settings were successfully updated')
+ expect(project.remote_mirrors.first.only_protected_branches).to eq(false)
+ end
+
+ it 'creates a push mirror that only mirrors protected branches', :js do
+ find('#only_protected_branches').click
+
+ expect(find('.js-mirror-protected-hidden', visible: false).value).to eq('1')
+
+ fill_in 'url', with: 'ssh://user@localhost/project.git'
+ select 'SSH public key', from: 'Authentication method'
+
+ select_direction
+
+ Sidekiq::Testing.fake! do
+ click_button 'Mirror repository'
+ end
+
+ project.reload
+
+ expect(page).to have_content('Mirroring settings were successfully updated')
+ expect(project.remote_mirrors.first.only_protected_branches).to eq(true)
+ end
+
+ it 'generates an SSH public key on submission', :js do
+ fill_in 'url', with: 'ssh://user@localhost/project.git'
+ select 'SSH public key', from: 'Authentication method'
+
+ select_direction
+
+ Sidekiq::Testing.fake! do
+ click_button 'Mirror repository'
+ end
+
+ expect(page).to have_content('Mirroring settings were successfully updated')
+ expect(page).to have_selector('[title="Copy SSH public key"]')
+ end
+
+ def select_direction(direction = 'push')
+ direction_select = find('#mirror_direction')
+
+ # In CE, this select box is disabled, but in EE, it is enabled
+ if direction_select.disabled?
+ expect(direction_select.value).to eq(direction)
+ else
+ direction_select.select(direction.capitalize)
+ end
+ end
end
end
end
diff --git a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
index b6e65fcbda1..84de6858d5f 100644
--- a/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
+++ b/spec/features/projects/settings/user_manages_merge_requests_settings_spec.rb
@@ -10,19 +10,19 @@ describe 'Projects > Settings > User manages merge request settings' do
end
it 'shows "Merge commit" strategy' do
- page.within '.merge-requests-feature' do
+ page.within '#js-merge-request-settings' do
expect(page).to have_content 'Merge commit'
end
end
it 'shows "Merge commit with semi-linear history " strategy' do
- page.within '.merge-requests-feature' do
+ page.within '#js-merge-request-settings' do
expect(page).to have_content 'Merge commit with semi-linear history'
end
end
it 'shows "Fast-forward merge" strategy' do
- page.within '.merge-requests-feature' do
+ page.within '#js-merge-request-settings' do
expect(page).to have_content 'Fast-forward merge'
end
end
diff --git a/spec/features/projects/settings/user_tags_project_spec.rb b/spec/features/projects/settings/user_tags_project_spec.rb
index 57b4b1287fa..9357215ae6f 100644
--- a/spec/features/projects/settings/user_tags_project_spec.rb
+++ b/spec/features/projects/settings/user_tags_project_spec.rb
@@ -9,15 +9,13 @@ describe 'Projects > Settings > User tags a project' do
visit edit_project_path(project)
end
- context 'when a project is archived' do
- it 'unarchives a project' do
- fill_in 'Tags', with: 'tag1, tag2'
+ it 'sets project tags' do
+ fill_in 'Tags', with: 'tag1, tag2'
- page.within '.general-settings' do
- click_button 'Save changes'
- end
-
- expect(find_field('Tags').value).to eq 'tag1, tag2'
+ page.within '.general-settings' do
+ click_button 'Save changes'
end
+
+ expect(find_field('Tags').value).to eq 'tag1, tag2'
end
end
diff --git a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
index 6fe21579e8e..df2b492ae6b 100644
--- a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
+++ b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
@@ -350,41 +350,6 @@ describe 'Projects > Show > User sees setup shortcut buttons' do
end
end
end
-
- describe '"Set up Koding" button' do
- it 'no "Set up Koding" button if Koding disabled' do
- stub_application_setting(koding_enabled?: false)
-
- visit project_path(project)
-
- page.within('.project-stats') do
- expect(page).not_to have_link('Set up Koding')
- end
- end
-
- it 'no "Set up Koding" button if the project already has a .koding.yml' do
- stub_application_setting(koding_enabled?: true)
- allow(Gitlab::CurrentSettings.current_application_settings).to receive(:koding_url).and_return('http://koding.example.com')
- expect(project.repository.changelog).not_to be_nil
- allow_any_instance_of(Repository).to receive(:koding_yml).and_return(project.repository.changelog)
-
- visit project_path(project)
-
- page.within('.project-stats') do
- expect(page).not_to have_link('Set up Koding')
- end
- end
-
- it '"Set up Koding" button linked to new file populated for a .koding.yml' do
- stub_application_setting(koding_enabled?: true)
-
- visit project_path(project)
-
- page.within('.project-stats') do
- expect(page).to have_link('Set up Koding', href: presenter.add_koding_stack_path)
- end
- end
- end
end
end
end
diff --git a/spec/features/projects/tree/create_directory_spec.rb b/spec/features/projects/tree/create_directory_spec.rb
index 9e58280b868..2cb2a23b7be 100644
--- a/spec/features/projects/tree/create_directory_spec.rb
+++ b/spec/features/projects/tree/create_directory_spec.rb
@@ -43,7 +43,7 @@ describe 'Multi-file editor new directory', :js do
find('.js-ide-commit-mode').click
find('.multi-file-commit-list-item').hover
- first('.multi-file-discard-btn .btn').click
+ click_button 'Stage'
fill_in('commit-message', with: 'commit message ide')
diff --git a/spec/features/projects/tree/create_file_spec.rb b/spec/features/projects/tree/create_file_spec.rb
index a04d3566a7e..9f5524da8e9 100644
--- a/spec/features/projects/tree/create_file_spec.rb
+++ b/spec/features/projects/tree/create_file_spec.rb
@@ -35,7 +35,7 @@ describe 'Multi-file editor new file', :js do
find('.js-ide-commit-mode').click
find('.multi-file-commit-list-item').hover
- first('.multi-file-discard-btn .btn').click
+ click_button 'Stage'
fill_in('commit-message', with: 'commit message ide')
diff --git a/spec/features/projects/view_on_env_spec.rb b/spec/features/projects/view_on_env_spec.rb
index a48ad94e9fa..7bfcd46713e 100644
--- a/spec/features/projects/view_on_env_spec.rb
+++ b/spec/features/projects/view_on_env_spec.rb
@@ -44,7 +44,7 @@ describe 'View on environment', :js do
context 'and an active deployment' do
let(:sha) { project.commit(branch_name).sha }
let(:environment) { create(:environment, project: project, name: 'review/feature', external_url: 'http://feature.review.example.com') }
- let!(:deployment) { create(:deployment, environment: environment, ref: branch_name, sha: sha) }
+ let!(:deployment) { create(:deployment, :success, environment: environment, ref: branch_name, sha: sha) }
context 'when visiting the diff of a merge request for the branch' do
let(:merge_request) { create(:merge_request, :simple, source_project: project, source_branch: branch_name) }
diff --git a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
index b30286e4446..48a0d675f2d 100644
--- a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
@@ -85,7 +85,7 @@ describe "User creates wiki page" do
expect(current_path).to eq(project_wiki_path(project, "test"))
page.within(:css, ".nav-text") do
- expect(page).to have_content("Test").and have_content("Create Page")
+ expect(page).to have_content("test").and have_content("Create Page")
end
click_link("Home")
@@ -97,7 +97,7 @@ describe "User creates wiki page" do
expect(current_path).to eq(project_wiki_path(project, "api"))
page.within(:css, ".nav-text") do
- expect(page).to have_content("Create").and have_content("Api")
+ expect(page).to have_content("Create").and have_content("api")
end
click_link("Home")
@@ -109,7 +109,7 @@ describe "User creates wiki page" do
expect(current_path).to eq(project_wiki_path(project, "raketasks"))
page.within(:css, ".nav-text") do
- expect(page).to have_content("Create").and have_content("Rake")
+ expect(page).to have_content("Create").and have_content("rake")
end
end
@@ -157,7 +157,7 @@ describe "User creates wiki page" do
expect(page).to have_field("wiki[message]", with: "Create home")
end
- it "creates a page from from the home page" do
+ it "creates a page from the home page" do
page.within(".wiki-form") do
fill_in(:wiki_content, with: "My awesome wiki!")
@@ -200,7 +200,7 @@ describe "User creates wiki page" do
click_button("Create page")
end
- expect(page).to have_content("Foo")
+ expect(page).to have_content("foo")
.and have_content("Last edited by #{user.name}")
.and have_content("My awesome wiki!")
end
@@ -215,7 +215,7 @@ describe "User creates wiki page" do
end
# Commit message field should have correct value.
- expect(page).to have_field("wiki[message]", with: "Create spaces in the name")
+ expect(page).to have_field("wiki[message]", with: "Create Spaces in the name")
page.within(".wiki-form") do
fill_in(:wiki_content, with: "My awesome wiki!")
@@ -246,7 +246,7 @@ describe "User creates wiki page" do
click_button("Create page")
end
- expect(page).to have_content("Hyphens in the name")
+ expect(page).to have_content("hyphens in the name")
.and have_content("Last edited by #{user.name}")
.and have_content("My awesome wiki!")
end
@@ -293,7 +293,7 @@ describe "User creates wiki page" do
click_button("Create page")
end
- expect(page).to have_content("Foo")
+ expect(page).to have_content("foo")
.and have_content("Last edited by #{user.name}")
.and have_content("My awesome wiki!")
end
@@ -311,7 +311,7 @@ describe "User creates wiki page" do
it 'renders a default sidebar when there is no customized sidebar' do
visit(project_wikis_path(project))
- expect(page).to have_content('Another')
+ expect(page).to have_content('another')
expect(page).to have_content('More Pages')
end
diff --git a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
index 2ce5ee0e87d..f76e577b0d6 100644
--- a/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_updates_wiki_page_spec.rb
@@ -1,233 +1,223 @@
require 'spec_helper'
describe 'User updates wiki page' do
- shared_examples 'wiki page user update' do
- let(:user) { create(:user) }
+ let(:user) { create(:user) }
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+ end
+
+ context 'when wiki is empty' do
before do
- project.add_maintainer(user)
- sign_in(user)
+ visit(project_wikis_path(project))
+ click_link "Create your first page"
end
- context 'when wiki is empty' do
- before do
- visit(project_wikis_path(project))
- click_link "Create your first page"
- end
-
- context 'in a user namespace' do
- let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
+ context 'in a user namespace' do
+ let(:project) { create(:project, :wiki_repo) }
- it 'redirects back to the home edit page' do
- page.within(:css, '.wiki-form .form-actions') do
- click_on('Cancel')
- end
-
- expect(current_path).to eq project_wiki_path(project, :home)
+ it 'redirects back to the home edit page' do
+ page.within(:css, '.wiki-form .form-actions') do
+ click_on('Cancel')
end
- it 'updates a page that has a path', :js do
- click_on('New page')
+ expect(current_path).to eq project_wiki_path(project, :home)
+ end
- page.within('#modal-new-wiki') do
- fill_in(:new_wiki_path, with: 'one/two/three-test')
- click_on('Create page')
- end
+ it 'updates a page that has a path', :js do
+ click_on('New page')
- page.within '.wiki-form' do
- fill_in(:wiki_content, with: 'wiki content')
- click_on('Create page')
- end
+ page.within('#modal-new-wiki') do
+ fill_in(:new_wiki_path, with: 'one/two/three-test')
+ click_on('Create page')
+ end
- expect(current_path).to include('one/two/three-test')
- expect(find('.wiki-pages')).to have_content('Three')
+ page.within '.wiki-form' do
+ fill_in(:wiki_content, with: 'wiki content')
+ click_on('Create page')
+ end
- first(:link, text: 'Three').click
+ expect(current_path).to include('one/two/three-test')
+ expect(find('.wiki-pages')).to have_content('three')
- expect(find('.nav-text')).to have_content('Three')
+ first(:link, text: 'three').click
- click_on('Edit')
+ expect(find('.nav-text')).to have_content('three')
- expect(current_path).to include('one/two/three-test')
- expect(page).to have_content('Edit Page')
+ click_on('Edit')
- fill_in('Content', with: 'Updated Wiki Content')
- click_on('Save changes')
+ expect(current_path).to include('one/two/three-test')
+ expect(page).to have_content('Edit Page')
- expect(page).to have_content('Updated Wiki Content')
- end
+ fill_in('Content', with: 'Updated Wiki Content')
+ click_on('Save changes')
- it_behaves_like 'wiki file attachments'
+ expect(page).to have_content('Updated Wiki Content')
end
- end
- context 'when wiki is not empty' do
- let(:project_wiki) { create(:project_wiki, project: project, user: project.creator) }
- let!(:wiki_page) { create(:wiki_page, wiki: project_wiki, attrs: { title: 'home', content: 'Home page' }) }
+ it_behaves_like 'wiki file attachments'
+ end
+ end
- before do
- visit(project_wikis_path(project))
+ context 'when wiki is not empty' do
+ let(:project_wiki) { create(:project_wiki, project: project, user: project.creator) }
+ let!(:wiki_page) { create(:wiki_page, wiki: project_wiki, attrs: { title: 'home', content: 'Home page' }) }
- click_link('Edit')
- end
+ before do
+ visit(project_wikis_path(project))
- context 'in a user namespace' do
- let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
+ click_link('Edit')
+ end
- it 'updates a page' do
- # Commit message field should have correct value.
- expect(page).to have_field('wiki[message]', with: 'Update home')
+ context 'in a user namespace' do
+ let(:project) { create(:project, :wiki_repo) }
- fill_in(:wiki_content, with: 'My awesome wiki!')
- click_button('Save changes')
+ it 'updates a page' do
+ # Commit message field should have correct value.
+ expect(page).to have_field('wiki[message]', with: 'Update home')
- expect(page).to have_content('Home')
- expect(page).to have_content("Last edited by #{user.name}")
- expect(page).to have_content('My awesome wiki!')
- end
+ fill_in(:wiki_content, with: 'My awesome wiki!')
+ click_button('Save changes')
- it 'shows a validation error message' do
- fill_in(:wiki_content, with: '')
- click_button('Save changes')
+ expect(page).to have_content('Home')
+ expect(page).to have_content("Last edited by #{user.name}")
+ expect(page).to have_content('My awesome wiki!')
+ end
- expect(page).to have_selector('.wiki-form')
- expect(page).to have_content('Edit Page')
- expect(page).to have_content('The form contains the following error:')
- expect(page).to have_content("Content can't be blank")
- expect(find('textarea#wiki_content').value).to eq('')
- end
+ it 'shows a validation error message' do
+ fill_in(:wiki_content, with: '')
+ click_button('Save changes')
- it 'shows the emoji autocompletion dropdown', :js do
- find('#wiki_content').native.send_keys('')
- fill_in(:wiki_content, with: ':')
+ expect(page).to have_selector('.wiki-form')
+ expect(page).to have_content('Edit Page')
+ expect(page).to have_content('The form contains the following error:')
+ expect(page).to have_content("Content can't be blank")
+ expect(find('textarea#wiki_content').value).to eq('')
+ end
- expect(page).to have_selector('.atwho-view')
- end
+ it 'shows the emoji autocompletion dropdown', :js do
+ find('#wiki_content').native.send_keys('')
+ fill_in(:wiki_content, with: ':')
- it 'shows the error message' do
- wiki_page.update(content: 'Update')
+ expect(page).to have_selector('.atwho-view')
+ end
- click_button('Save changes')
+ it 'shows the error message' do
+ wiki_page.update(content: 'Update')
- expect(page).to have_content('Someone edited the page the same time you did.')
- end
+ click_button('Save changes')
- it 'updates a page' do
- fill_in('Content', with: 'Updated Wiki Content')
- click_on('Save changes')
+ expect(page).to have_content('Someone edited the page the same time you did.')
+ end
- expect(page).to have_content('Updated Wiki Content')
- end
+ it 'updates a page' do
+ fill_in('Content', with: 'Updated Wiki Content')
+ click_on('Save changes')
- it 'cancels editing of a page' do
- page.within(:css, '.wiki-form .form-actions') do
- click_on('Cancel')
- end
+ expect(page).to have_content('Updated Wiki Content')
+ end
- expect(current_path).to eq(project_wiki_path(project, wiki_page))
+ it 'cancels editing of a page' do
+ page.within(:css, '.wiki-form .form-actions') do
+ click_on('Cancel')
end
- it_behaves_like 'wiki file attachments'
+ expect(current_path).to eq(project_wiki_path(project, wiki_page))
end
- context 'in a group namespace' do
- let(:project) { create(:project, :wiki_repo, namespace: create(:group, :public)) }
+ it_behaves_like 'wiki file attachments'
+ end
- it 'updates a page' do
- # Commit message field should have correct value.
- expect(page).to have_field('wiki[message]', with: 'Update home')
+ context 'in a group namespace' do
+ let(:project) { create(:project, :wiki_repo, namespace: create(:group, :public)) }
- fill_in(:wiki_content, with: 'My awesome wiki!')
+ it 'updates a page' do
+ # Commit message field should have correct value.
+ expect(page).to have_field('wiki[message]', with: 'Update home')
- click_button('Save changes')
+ fill_in(:wiki_content, with: 'My awesome wiki!')
- expect(page).to have_content('Home')
- expect(page).to have_content("Last edited by #{user.name}")
- expect(page).to have_content('My awesome wiki!')
- end
+ click_button('Save changes')
- it_behaves_like 'wiki file attachments'
+ expect(page).to have_content('Home')
+ expect(page).to have_content("Last edited by #{user.name}")
+ expect(page).to have_content('My awesome wiki!')
end
- end
- context 'when the page is in a subdir' do
- let!(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
- let(:project_wiki) { create(:project_wiki, project: project, user: project.creator) }
- let(:page_name) { 'page_name' }
- let(:page_dir) { "foo/bar/#{page_name}" }
- let!(:wiki_page) { create(:wiki_page, wiki: project_wiki, attrs: { title: page_dir, content: 'Home page' }) }
+ it_behaves_like 'wiki file attachments'
+ end
+ end
- before do
- visit(project_wiki_edit_path(project, wiki_page))
- end
+ context 'when the page is in a subdir' do
+ let!(:project) { create(:project, :wiki_repo) }
+ let(:project_wiki) { create(:project_wiki, project: project, user: project.creator) }
+ let(:page_name) { 'page_name' }
+ let(:page_dir) { "foo/bar/#{page_name}" }
+ let!(:wiki_page) { create(:wiki_page, wiki: project_wiki, attrs: { title: page_dir, content: 'Home page' }) }
- it 'moves the page to the root folder', :skip_gitaly_mock do
- fill_in(:wiki_title, with: "/#{page_name}")
+ before do
+ visit(project_wiki_edit_path(project, wiki_page))
+ end
- click_button('Save changes')
+ it 'moves the page to the root folder' do
+ fill_in(:wiki_title, with: "/#{page_name}")
- expect(current_path).to eq(project_wiki_path(project, page_name))
- end
+ click_button('Save changes')
- it 'moves the page to other dir' do
- new_page_dir = "foo1/bar1/#{page_name}"
+ expect(current_path).to eq(project_wiki_path(project, page_name))
+ end
- fill_in(:wiki_title, with: new_page_dir)
+ it 'moves the page to other dir' do
+ new_page_dir = "foo1/bar1/#{page_name}"
- click_button('Save changes')
+ fill_in(:wiki_title, with: new_page_dir)
- expect(current_path).to eq(project_wiki_path(project, new_page_dir))
- end
+ click_button('Save changes')
- it 'remains in the same place if title has not changed' do
- original_path = project_wiki_path(project, wiki_page)
+ expect(current_path).to eq(project_wiki_path(project, new_page_dir))
+ end
- fill_in(:wiki_title, with: page_name)
+ it 'remains in the same place if title has not changed' do
+ original_path = project_wiki_path(project, wiki_page)
- click_button('Save changes')
+ fill_in(:wiki_title, with: page_name)
- expect(current_path).to eq(original_path)
- end
+ click_button('Save changes')
- it 'can be moved to a different dir with a different name' do
- new_page_dir = "foo1/bar1/new_page_name"
+ expect(current_path).to eq(original_path)
+ end
- fill_in(:wiki_title, with: new_page_dir)
+ it 'can be moved to a different dir with a different name' do
+ new_page_dir = "foo1/bar1/new_page_name"
- click_button('Save changes')
+ fill_in(:wiki_title, with: new_page_dir)
- expect(current_path).to eq(project_wiki_path(project, new_page_dir))
- end
+ click_button('Save changes')
- it 'can be renamed and moved to the root folder' do
- new_name = 'new_page_name'
+ expect(current_path).to eq(project_wiki_path(project, new_page_dir))
+ end
- fill_in(:wiki_title, with: "/#{new_name}")
+ it 'can be renamed and moved to the root folder' do
+ new_name = 'new_page_name'
- click_button('Save changes')
+ fill_in(:wiki_title, with: "/#{new_name}")
- expect(current_path).to eq(project_wiki_path(project, new_name))
- end
+ click_button('Save changes')
- it 'squishes the title before creating the page' do
- new_page_dir = " foo1 / bar1 / #{page_name} "
+ expect(current_path).to eq(project_wiki_path(project, new_name))
+ end
- fill_in(:wiki_title, with: new_page_dir)
+ it 'squishes the title before creating the page' do
+ new_page_dir = " foo1 / bar1 / #{page_name} "
- click_button('Save changes')
+ fill_in(:wiki_title, with: new_page_dir)
- expect(current_path).to eq(project_wiki_path(project, "foo1/bar1/#{page_name}"))
- end
+ click_button('Save changes')
- it_behaves_like 'wiki file attachments'
+ expect(current_path).to eq(project_wiki_path(project, "foo1/bar1/#{page_name}"))
end
- end
-
- context 'when Gitaly is enabled' do
- it_behaves_like 'wiki page user update'
- end
- context 'when Gitaly is disabled', :skip_gitaly_mock do
- it_behaves_like 'wiki page user update'
+ it_behaves_like 'wiki file attachments'
end
end
diff --git a/spec/features/projects/wiki/user_views_wiki_empty_spec.rb b/spec/features/projects/wiki/user_views_wiki_empty_spec.rb
index 83ffbb4a94e..e94b3a9432b 100644
--- a/spec/features/projects/wiki/user_views_wiki_empty_spec.rb
+++ b/spec/features/projects/wiki/user_views_wiki_empty_spec.rb
@@ -54,7 +54,7 @@ describe 'User views empty wiki' do
it_behaves_like 'empty wiki and non-accessible issues'
end
- context 'when user is logged in and a memeber' do
+ context 'when user is logged in and a member' do
let(:project) { create(:project, :public, :wiki_repo) }
before do
diff --git a/spec/features/projects/wiki/user_views_wiki_page_spec.rb b/spec/features/projects/wiki/user_views_wiki_page_spec.rb
index 747406efc8b..d4691b669c1 100644
--- a/spec/features/projects/wiki/user_views_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_views_wiki_page_spec.rb
@@ -1,177 +1,164 @@
require 'spec_helper'
describe 'User views a wiki page' do
- shared_examples 'wiki page user view' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
- let(:wiki_page) do
- create(:wiki_page,
- wiki: project.wiki,
- attrs: { title: 'home', content: 'Look at this [image](image.jpg)\n\n ![alt text](image.jpg)' })
- end
+ include WikiHelpers
+
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
+ let(:path) { 'image.png' }
+ let(:wiki_page) do
+ create(:wiki_page,
+ wiki: project.wiki,
+ attrs: { title: 'home', content: "Look at this [image](#{path})\n\n ![alt text](#{path})" })
+ end
- before do
- project.add_maintainer(user)
- sign_in(user)
- end
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+ end
- context 'when wiki is empty' do
- before do
- visit(project_wikis_path(project))
- click_link "Create your first page"
+ context 'when wiki is empty' do
+ before do
+ visit(project_wikis_path(project))
+ click_link "Create your first page"
- click_on('New page')
+ click_on('New page')
- page.within('#modal-new-wiki') do
- fill_in(:new_wiki_path, with: 'one/two/three-test')
- click_on('Create page')
- end
+ page.within('#modal-new-wiki') do
+ fill_in(:new_wiki_path, with: 'one/two/three-test')
+ click_on('Create page')
+ end
- page.within('.wiki-form') do
- fill_in(:wiki_content, with: 'wiki content')
- click_on('Create page')
- end
+ page.within('.wiki-form') do
+ fill_in(:wiki_content, with: 'wiki content')
+ click_on('Create page')
end
+ end
- it 'shows the history of a page that has a path', :js do
- expect(current_path).to include('one/two/three-test')
+ it 'shows the history of a page that has a path', :js do
+ expect(current_path).to include('one/two/three-test')
- first(:link, text: 'Three').click
- click_on('Page history')
+ first(:link, text: 'three').click
+ click_on('Page history')
- expect(current_path).to include('one/two/three-test')
+ expect(current_path).to include('one/two/three-test')
- page.within(:css, '.nav-text') do
- expect(page).to have_content('History')
- end
+ page.within(:css, '.nav-text') do
+ expect(page).to have_content('History')
end
+ end
- it 'shows an old version of a page', :js do
- expect(current_path).to include('one/two/three-test')
- expect(find('.wiki-pages')).to have_content('Three')
-
- first(:link, text: 'Three').click
+ it 'shows an old version of a page', :js do
+ expect(current_path).to include('one/two/three-test')
+ expect(find('.wiki-pages')).to have_content('three')
- expect(find('.nav-text')).to have_content('Three')
+ first(:link, text: 'three').click
- click_on('Edit')
+ expect(find('.nav-text')).to have_content('three')
- expect(current_path).to include('one/two/three-test')
- expect(page).to have_content('Edit Page')
+ click_on('Edit')
- fill_in('Content', with: 'Updated Wiki Content')
+ expect(current_path).to include('one/two/three-test')
+ expect(page).to have_content('Edit Page')
- click_on('Save changes')
- click_on('Page history')
+ fill_in('Content', with: 'Updated Wiki Content')
- page.within(:css, '.nav-text') do
- expect(page).to have_content('History')
- end
+ click_on('Save changes')
+ click_on('Page history')
- find('a[href*="?version_id"]')
+ page.within(:css, '.nav-text') do
+ expect(page).to have_content('History')
end
- end
- context 'when a page does not have history' do
- before do
- visit(project_wiki_path(project, wiki_page))
- end
+ find('a[href*="?version_id"]')
+ end
+ end
- it 'shows all the pages' do
- expect(page).to have_content(user.name)
- expect(find('.wiki-pages')).to have_content(wiki_page.title.capitalize)
- end
+ context 'when a page does not have history' do
+ before do
+ visit(project_wiki_path(project, wiki_page))
+ end
- it 'shows a file stored in a page' do
- gollum_file_double = double('Gollum::File',
- mime_type: 'image/jpeg',
- name: 'images/image.jpg',
- path: 'images/image.jpg',
- raw_data: '')
- wiki_file = Gitlab::Git::WikiFile.new(gollum_file_double)
+ it 'shows all the pages' do
+ expect(page).to have_content(user.name)
+ expect(find('.wiki-pages')).to have_content(wiki_page.title.capitalize)
+ end
- allow(wiki_file).to receive(:mime_type).and_return('image/jpeg')
- allow_any_instance_of(ProjectWiki).to receive(:find_file).with('image.jpg', nil).and_return(wiki_file)
+ context 'shows a file stored in a page' do
+ let(:path) { upload_file_to_wiki(project, user, 'dk.png') }
- expect(page).to have_xpath("//img[@data-src='#{project.wiki.wiki_base_path}/image.jpg']")
- expect(page).to have_link('image', href: "#{project.wiki.wiki_base_path}/image.jpg")
+ it do
+ expect(page).to have_xpath("//img[@data-src='#{project.wiki.wiki_base_path}/#{path}']")
+ expect(page).to have_link('image', href: "#{project.wiki.wiki_base_path}/#{path}")
click_on('image')
- expect(current_path).to match('wikis/image.jpg')
+ expect(current_path).to match("wikis/#{path}")
expect(page).not_to have_xpath('/html') # Page should render the image which means there is no html involved
end
+ end
- it 'shows the creation page if file does not exist' do
- expect(page).to have_link('image', href: "#{project.wiki.wiki_base_path}/image.jpg")
+ it 'shows the creation page if file does not exist' do
+ expect(page).to have_link('image', href: "#{project.wiki.wiki_base_path}/#{path}")
- click_on('image')
+ click_on('image')
- expect(current_path).to match('wikis/image.jpg')
- expect(page).to have_content('New Wiki Page')
- expect(page).to have_content('Create page')
- end
+ expect(current_path).to match("wikis/#{path}")
+ expect(page).to have_content('New Wiki Page')
+ expect(page).to have_content('Create page')
end
+ end
- context 'when a page has history' do
- before do
- wiki_page.update(message: 'updated home', content: 'updated [some link](other-page)')
- end
+ context 'when a page has history' do
+ before do
+ wiki_page.update(message: 'updated home', content: 'updated [some link](other-page)')
+ end
- it 'shows the page history' do
- visit(project_wiki_path(project, wiki_page))
+ it 'shows the page history' do
+ visit(project_wiki_path(project, wiki_page))
- expect(page).to have_selector('a.btn', text: 'Edit')
+ expect(page).to have_selector('a.btn', text: 'Edit')
- click_on('Page history')
+ click_on('Page history')
- expect(page).to have_content(user.name)
- expect(page).to have_content("#{user.username} created page: home")
- expect(page).to have_content('updated home')
- end
+ expect(page).to have_content(user.name)
+ expect(page).to have_content("#{user.username} created page: home")
+ expect(page).to have_content('updated home')
+ end
- it 'does not show the "Edit" button' do
- visit(project_wiki_path(project, wiki_page, version_id: wiki_page.versions.last.id))
+ it 'does not show the "Edit" button' do
+ visit(project_wiki_path(project, wiki_page, version_id: wiki_page.versions.last.id))
- expect(page).not_to have_selector('a.btn', text: 'Edit')
- end
+ expect(page).not_to have_selector('a.btn', text: 'Edit')
end
+ end
- context 'when page has invalid content encoding' do
- let(:content) { 'whatever'.force_encoding('ISO-8859-1') }
-
- before do
- allow(Gitlab::EncodingHelper).to receive(:encode!).and_return(content)
+ context 'when page has invalid content encoding' do
+ let(:content) { 'whatever'.force_encoding('ISO-8859-1') }
- visit(project_wiki_path(project, wiki_page))
- end
-
- it 'does not show "Edit" button' do
- expect(page).not_to have_selector('a.btn', text: 'Edit')
- end
+ before do
+ allow(Gitlab::EncodingHelper).to receive(:encode!).and_return(content)
- it 'shows error' do
- page.within(:css, '.flash-notice') do
- expect(page).to have_content('The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository.')
- end
- end
+ visit(project_wiki_path(project, wiki_page))
end
- it 'opens a default wiki page', :js do
- visit(project_path(project))
-
- find('.shortcuts-wiki').click
- click_link "Create your first page"
+ it 'does not show "Edit" button' do
+ expect(page).not_to have_selector('a.btn', text: 'Edit')
+ end
- expect(page).to have_content('Home · Create Page')
+ it 'shows error' do
+ page.within(:css, '.flash-notice') do
+ expect(page).to have_content('The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository.')
+ end
end
end
- context 'when Gitaly is enabled' do
- it_behaves_like 'wiki page user view'
- end
+ it 'opens a default wiki page', :js do
+ visit(project_path(project))
+
+ find('.shortcuts-wiki').click
+ click_link "Create your first page"
- context 'when Gitaly is disabled', :skip_gitaly_mock do
- it_behaves_like 'wiki page user view'
+ expect(page).to have_content('Home · Create Page')
end
end
diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb
index 8e310f38a8c..0add129dde2 100644
--- a/spec/features/projects_spec.rb
+++ b/spec/features/projects_spec.rb
@@ -193,6 +193,23 @@ describe 'Project' do
end
end
+ describe 'when the project repository is disabled', :js do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository_disabled, :repository, namespace: user.namespace) }
+
+ before do
+ sign_in(user)
+ project.add_maintainer(user)
+ visit project_path(project)
+ end
+
+ it 'does not show an error' do
+ wait_for_requests
+
+ expect(page).not_to have_selector('.flash-alert')
+ end
+ end
+
describe 'removal', :js do
let(:user) { create(:user) }
let(:project) { create(:project, namespace: user.namespace) }
@@ -305,6 +322,22 @@ describe 'Project' do
end
end
+ context 'content is not cached after signing out', :js do
+ let(:user) { create(:user, project_view: 'activity') }
+ let(:project) { create(:project, :repository) }
+
+ it 'does not load activity', :js do
+ project.add_maintainer(user)
+ sign_in(user)
+ visit project_path(project)
+ sign_out(user)
+
+ page.evaluate_script('window.history.back()')
+
+ expect(page).not_to have_selector('.event-item')
+ end
+ end
+
def remove_with_confirm(button_text, confirm_with)
click_button button_text
fill_in 'confirm_name_input', with: confirm_with
diff --git a/spec/features/search/user_searches_for_wiki_pages_spec.rb b/spec/features/search/user_searches_for_wiki_pages_spec.rb
index 3ee753b7d23..7225ca65492 100644
--- a/spec/features/search/user_searches_for_wiki_pages_spec.rb
+++ b/spec/features/search/user_searches_for_wiki_pages_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe 'User searches for wiki pages', :js do
let(:user) { create(:user) }
- let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
+ let(:project) { create(:project, :repository, :wiki_repo, namespace: user.namespace) }
let!(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: { title: 'test_wiki', content: 'Some Wiki content' }) }
before do
diff --git a/spec/features/search/user_uses_header_search_field_spec.rb b/spec/features/search/user_uses_header_search_field_spec.rb
index af38f77c0c6..444de26733f 100644
--- a/spec/features/search/user_uses_header_search_field_spec.rb
+++ b/spec/features/search/user_uses_header_search_field_spec.rb
@@ -21,13 +21,17 @@ describe 'User uses header search field' do
it 'shows assigned issues' do
find('.search-input-container .dropdown-menu').click_link('Issues assigned to me')
- expect(find('.js-assignee-search')).to have_content(user.name)
+ expect(page).to have_selector('.filtered-search')
+ expect_tokens([assignee_token(user.name)])
+ expect_filtered_search_input_empty
end
it 'shows created issues' do
find('.search-input-container .dropdown-menu').click_link("Issues I've created")
- expect(find('.js-author-search')).to have_content(user.name)
+ expect(page).to have_selector('.filtered-search')
+ expect_tokens([author_token(user.name)])
+ expect_filtered_search_input_empty
end
end
@@ -37,13 +41,17 @@ describe 'User uses header search field' do
it 'shows assigned merge requests' do
find('.search-input-container .dropdown-menu').click_link('Merge requests assigned to me')
- expect(find('.js-assignee-search')).to have_content(user.name)
+ expect(page).to have_selector('.filtered-search')
+ expect_tokens([assignee_token(user.name)])
+ expect_filtered_search_input_empty
end
it 'shows created merge requests' do
find('.search-input-container .dropdown-menu').click_link("Merge requests I've created")
- expect(find('.js-author-search')).to have_content(user.name)
+ expect(page).to have_selector('.filtered-search')
+ expect_tokens([author_token(user.name)])
+ expect_filtered_search_input_empty
end
end
end
diff --git a/spec/features/search/user_uses_search_filters_spec.rb b/spec/features/search/user_uses_search_filters_spec.rb
index 66afe163447..0725ff178ac 100644
--- a/spec/features/search/user_uses_search_filters_spec.rb
+++ b/spec/features/search/user_uses_search_filters_spec.rb
@@ -14,7 +14,7 @@ describe 'User uses search filters', :js do
visit(search_path)
end
- context' when filtering by group' do
+ context 'when filtering by group' do
it 'shows group projects' do
find('.js-search-group-dropdown').click
@@ -36,7 +36,7 @@ describe 'User uses search filters', :js do
end
end
- context' when filtering by project' do
+ context 'when filtering by project' do
it 'shows a project' do
page.within('.project-filter') do
find('.js-search-project-dropdown').click
diff --git a/spec/features/security/dashboard_access_spec.rb b/spec/features/security/dashboard_access_spec.rb
index 149bd32e736..0c893e65d9c 100644
--- a/spec/features/security/dashboard_access_spec.rb
+++ b/spec/features/security/dashboard_access_spec.rb
@@ -43,20 +43,6 @@ describe "Dashboard access" do
it { is_expected.to be_allowed_for :visitor }
end
- describe "GET /koding" do
- subject { koding_path }
-
- context 'with Koding enabled' do
- before do
- stub_application_setting(koding_enabled?: true)
- end
-
- it { is_expected.to be_allowed_for :admin }
- it { is_expected.to be_allowed_for :user }
- it { is_expected.to be_denied_for :visitor }
- end
- end
-
describe "GET /projects/new" do
it { expect(new_project_path).to be_allowed_for :admin }
it { expect(new_project_path).to be_allowed_for :user }
diff --git a/spec/features/signed_commits_spec.rb b/spec/features/signed_commits_spec.rb
index ef0e55a1468..e2b3444272e 100644
--- a/spec/features/signed_commits_spec.rb
+++ b/spec/features/signed_commits_spec.rb
@@ -1,25 +1,22 @@
+# frozen_string_literal: true
+
require 'spec_helper'
-describe 'GPG signed commits', :js do
- set(:ref) { :'2d1096e3a0ecf1d2baf6dee036cc80775d4940ba' }
- let(:project) { create(:project, :repository) }
+describe 'GPG signed commits' do
+ let(:project) { create(:project, :public, :repository) }
it 'changes from unverified to verified when the user changes his email to match the gpg key' do
- user = create :user, email: 'unrelated.user@example.org'
- project.add_maintainer(user)
+ ref = GpgHelpers::SIGNED_AND_AUTHORED_SHA
+ user = create(:user, email: 'unrelated.user@example.org')
perform_enqueued_jobs do
create :gpg_key, key: GpgHelpers::User1.public_key, user: user
end
- sign_in(user)
-
- visit project_commits_path(project, ref)
+ visit project_commit_path(project, ref)
- within '#commits-list' do
- expect(page).to have_content 'Unverified'
- expect(page).not_to have_content 'Verified'
- end
+ expect(page).to have_link 'Unverified'
+ expect(page).not_to have_link 'Verified'
# user changes his email which makes the gpg key verified
perform_enqueued_jobs do
@@ -27,41 +24,33 @@ describe 'GPG signed commits', :js do
user.update!(email: GpgHelpers::User1.emails.first)
end
- visit project_commits_path(project, ref)
+ visit project_commit_path(project, ref)
- within '#commits-list' do
- expect(page).to have_content 'Unverified'
- expect(page).to have_content 'Verified'
- end
+ expect(page).not_to have_link 'Unverified'
+ expect(page).to have_link 'Verified'
end
it 'changes from unverified to verified when the user adds the missing gpg key' do
- user = create :user, email: GpgHelpers::User1.emails.first
- project.add_maintainer(user)
+ ref = GpgHelpers::SIGNED_AND_AUTHORED_SHA
+ user = create(:user, email: GpgHelpers::User1.emails.first)
- sign_in(user)
+ visit project_commit_path(project, ref)
- visit project_commits_path(project, ref)
-
- within '#commits-list' do
- expect(page).to have_content 'Unverified'
- expect(page).not_to have_content 'Verified'
- end
+ expect(page).to have_link 'Unverified'
+ expect(page).not_to have_link 'Verified'
# user adds the gpg key which makes the signature valid
perform_enqueued_jobs do
create :gpg_key, key: GpgHelpers::User1.public_key, user: user
end
- visit project_commits_path(project, ref)
+ visit project_commit_path(project, ref)
- within '#commits-list' do
- expect(page).to have_content 'Unverified'
- expect(page).to have_content 'Verified'
- end
+ expect(page).not_to have_link 'Unverified'
+ expect(page).to have_link 'Verified'
end
- context 'shows popover badges' do
+ context 'shows popover badges', :js do
let(:user_1) do
create :user, email: GpgHelpers::User1.emails.first, username: 'nannie.bernhard', name: 'Nannie Bernhard'
end
@@ -85,19 +74,10 @@ describe 'GPG signed commits', :js do
end
end
- before do
- user = create :user
- project.add_maintainer(user)
-
- sign_in(user)
- end
-
it 'unverified signature' do
- visit project_commits_path(project, ref)
+ visit project_commit_path(project, GpgHelpers::SIGNED_COMMIT_SHA)
- within(find('.commit', text: 'signed commit by bette cartwright')) do
- click_on 'Unverified'
- end
+ click_on 'Unverified'
within '.popover' do
expect(page).to have_content 'This commit was signed with an unverified signature.'
@@ -108,11 +88,9 @@ describe 'GPG signed commits', :js do
it 'unverified signature: user email does not match the committer email, but is the same user' do
user_2_key
- visit project_commits_path(project, ref)
+ visit project_commit_path(project, GpgHelpers::DIFFERING_EMAIL_SHA)
- within(find('.commit', text: 'signed and authored commit by bette cartwright, different email')) do
- click_on 'Unverified'
- end
+ click_on 'Unverified'
within '.popover' do
expect(page).to have_content 'This commit was signed with a verified signature, but the committer email is not verified to belong to the same user.'
@@ -125,11 +103,9 @@ describe 'GPG signed commits', :js do
it 'unverified signature: user email does not match the committer email' do
user_2_key
- visit project_commits_path(project, ref)
+ visit project_commit_path(project, GpgHelpers::SIGNED_COMMIT_SHA)
- within(find('.commit', text: 'signed commit by bette cartwright')) do
- click_on 'Unverified'
- end
+ click_on 'Unverified'
within '.popover' do
expect(page).to have_content "This commit was signed with a different user's verified signature."
@@ -142,11 +118,9 @@ describe 'GPG signed commits', :js do
it 'verified and the gpg user has a gitlab profile' do
user_1_key
- visit project_commits_path(project, ref)
+ visit project_commit_path(project, GpgHelpers::SIGNED_AND_AUTHORED_SHA)
- within(find('.commit', text: 'signed and authored commit by nannie bernhard')) do
- click_on 'Verified'
- end
+ click_on 'Verified'
within '.popover' do
expect(page).to have_content 'This commit was signed with a verified signature and the committer email is verified to belong to the same user.'
@@ -159,20 +133,16 @@ describe 'GPG signed commits', :js do
it "verified and the gpg user's profile doesn't exist anymore" do
user_1_key
- visit project_commits_path(project, ref)
+ visit project_commit_path(project, GpgHelpers::SIGNED_AND_AUTHORED_SHA)
# wait for the signature to get generated
- within(find('.commit', text: 'signed and authored commit by nannie bernhard')) do
- expect(page).to have_content 'Verified'
- end
+ expect(page).to have_link 'Verified'
user_1.destroy!
refresh
- within(find('.commit', text: 'signed and authored commit by nannie bernhard')) do
- click_on 'Verified'
- end
+ click_on 'Verified'
within '.popover' do
expect(page).to have_content 'This commit was signed with a verified signature and the committer email is verified to belong to the same user.'
diff --git a/spec/features/snippets/user_sees_breadcrumb_links.rb b/spec/features/snippets/user_sees_breadcrumb_links.rb
new file mode 100644
index 00000000000..696f2b93390
--- /dev/null
+++ b/spec/features/snippets/user_sees_breadcrumb_links.rb
@@ -0,0 +1,17 @@
+require 'rails_helper'
+
+describe 'New user snippet breadcrumbs' do
+ let(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ visit new_snippet_path
+ end
+
+ it 'display a link to user snippets and new user snippet pages' do
+ page.within '.breadcrumbs' do
+ expect(find_link('Snippets')[:href]).to end_with(dashboard_snippets_path)
+ expect(find_link('New')[:href]).to end_with(new_snippet_path)
+ end
+ end
+end
diff --git a/spec/features/u2f_spec.rb b/spec/features/u2f_spec.rb
index f1192f48b86..ae9b65d1a39 100644
--- a/spec/features/u2f_spec.rb
+++ b/spec/features/u2f_spec.rb
@@ -42,7 +42,7 @@ describe 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do
it 'allows registering a new device with a name' do
visit profile_account_path
manage_two_factor_authentication
- expect(page).to have_content("You've already enabled two-factor authentication using mobile")
+ expect(page).to have_content("You've already enabled two-factor authentication using one time password authenticators")
u2f_device = register_u2f_device
@@ -70,7 +70,7 @@ describe 'Using U2F (Universal 2nd Factor) Devices for Authentication', :js do
it 'allows deleting a device' do
visit profile_account_path
manage_two_factor_authentication
- expect(page).to have_content("You've already enabled two-factor authentication using mobile")
+ expect(page).to have_content("You've already enabled two-factor authentication using one time password authenticators")
first_u2f_device = register_u2f_device
second_u2f_device = register_u2f_device(name: 'My other device')
diff --git a/spec/features/uploads/user_uploads_avatar_to_group_spec.rb b/spec/features/uploads/user_uploads_avatar_to_group_spec.rb
index a07edc42eae..72b53bae46a 100644
--- a/spec/features/uploads/user_uploads_avatar_to_group_spec.rb
+++ b/spec/features/uploads/user_uploads_avatar_to_group_spec.rb
@@ -15,7 +15,7 @@ describe 'User uploads avatar to group' do
)
page.within('.gs-general') do
- click_button 'Save group'
+ click_button 'Save changes'
end
visit group_path(group)
diff --git a/spec/features/user_sorts_things_spec.rb b/spec/features/user_sorts_things_spec.rb
index 69ebdddaeec..0295f588326 100644
--- a/spec/features/user_sorts_things_spec.rb
+++ b/spec/features/user_sorts_things_spec.rb
@@ -6,7 +6,7 @@ require "spec_helper"
# All those specs are moved out to this spec intentionally to keep them all in one place.
describe "User sorts things" do
include Spec::Support::Helpers::Features::SortingHelpers
- include Helpers::DashboardHelper
+ include DashboardHelper
set(:project) { create(:project_empty_repo, :public) }
set(:current_user) { create(:user) } # Using `current_user` instead of just `user` because of the hardoced call in `assigned_mrs_dashboard_path` which is used below.
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index 44758f862a8..ad856bd062e 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -2,6 +2,7 @@ require 'spec_helper'
describe 'Login' do
include TermsHelper
+ include UserLoginHelper
before do
stub_authentication_activity_metrics(debug: true)
@@ -546,29 +547,6 @@ describe 'Login' do
ensure_tab_pane_correctness(false)
end
end
-
- def ensure_tab_pane_correctness(visit_path = true)
- if visit_path
- visit new_user_session_path
- end
-
- ensure_tab_pane_counts
- ensure_one_active_tab
- ensure_one_active_pane
- end
-
- def ensure_tab_pane_counts
- tabs_count = page.all('[role="tab"]').size
- expect(page).to have_selector('[role="tabpanel"]', count: tabs_count)
- end
-
- def ensure_one_active_tab
- expect(page).to have_selector('ul.new-session-tabs > li > a.active', count: 1)
- end
-
- def ensure_one_active_pane
- expect(page).to have_selector('.tab-pane.active', count: 1)
- end
end
context 'when terms are enforced' do
diff --git a/spec/features/users/overview_spec.rb b/spec/features/users/overview_spec.rb
new file mode 100644
index 00000000000..34ed771340f
--- /dev/null
+++ b/spec/features/users/overview_spec.rb
@@ -0,0 +1,150 @@
+require 'spec_helper'
+
+describe 'Overview tab on a user profile', :js do
+ let(:user) { create(:user) }
+ let(:contributed_project) { create(:project, :public, :repository) }
+
+ def push_code_contribution
+ event = create(:push_event, project: contributed_project, author: user)
+
+ create(:push_event_payload,
+ event: event,
+ commit_from: '11f9ac0a48b62cef25eedede4c1819964f08d5ce',
+ commit_to: '1cf19a015df3523caf0a1f9d40c98a267d6a2fc2',
+ commit_count: 3,
+ ref: 'master')
+ end
+
+ before do
+ sign_in user
+ end
+
+ describe 'activities section' do
+ shared_context 'visit overview tab' do
+ before do
+ visit user.username
+ page.find('.js-overview-tab a').click
+ wait_for_requests
+ end
+ end
+
+ describe 'user has no activities' do
+ include_context 'visit overview tab'
+
+ it 'does not show any entries in the list of activities' do
+ page.within('.activities-block') do
+ expect(page).not_to have_selector('.event-item')
+ end
+ end
+
+ it 'does not show a link to the activity list' do
+ expect(find('#js-overview .activities-block')).to have_selector('.js-view-all', visible: false)
+ end
+ end
+
+ describe 'user has 3 activities' do
+ before do
+ 3.times { push_code_contribution }
+ end
+
+ include_context 'visit overview tab'
+
+ it 'display 3 entries in the list of activities' do
+ expect(find('#js-overview')).to have_selector('.event-item', count: 3)
+ end
+ end
+
+ describe 'user has 11 activities' do
+ before do
+ 11.times { push_code_contribution }
+ end
+
+ include_context 'visit overview tab'
+
+ it 'displays 10 entries in the list of activities' do
+ expect(find('#js-overview')).to have_selector('.event-item', count: 10)
+ end
+
+ it 'shows a link to the activity list' do
+ expect(find('#js-overview .activities-block')).to have_selector('.js-view-all', visible: true)
+ end
+
+ it 'links to the activity tab' do
+ page.within('.activities-block') do
+ find('.js-view-all').click
+ wait_for_requests
+ expect(URI.parse(current_url).path).to eq("/users/#{user.username}/activity")
+ end
+ end
+ end
+ end
+
+ describe 'projects section' do
+ shared_context 'visit overview tab' do
+ before do
+ visit user.username
+ page.find('.js-overview-tab a').click
+ wait_for_requests
+ end
+ end
+
+ describe 'user has no personal projects' do
+ include_context 'visit overview tab'
+
+ it 'it shows an empty project list with an info message' do
+ page.within('.projects-block') do
+ expect(page).to have_content('No projects found')
+ expect(page).not_to have_selector('.project-row')
+ end
+ end
+
+ it 'does not show a link to the project list' do
+ expect(find('#js-overview .projects-block')).to have_selector('.js-view-all', visible: false)
+ end
+ end
+
+ describe 'user has a personal project' do
+ before do
+ create(:project, :private, namespace: user.namespace, creator: user) { |p| p.add_maintainer(user) }
+ end
+
+ include_context 'visit overview tab'
+
+ it 'it shows one entry in the list of projects' do
+ page.within('.projects-block') do
+ expect(page).to have_selector('.project-row', count: 1)
+ end
+ end
+
+ it 'shows a link to the project list' do
+ expect(find('#js-overview .projects-block')).to have_selector('.js-view-all', visible: true)
+ end
+ end
+
+ describe 'user has more than ten personal projects' do
+ before do
+ create_list(:project, 11, :private, namespace: user.namespace, creator: user) do |project|
+ project.add_maintainer(user)
+ end
+ end
+
+ include_context 'visit overview tab'
+
+ it 'it shows max. ten entries in the list of projects' do
+ page.within('.projects-block') do
+ expect(page).to have_selector('.project-row', count: 10)
+ end
+ end
+
+ it 'shows a link to the project list' do
+ expect(find('#js-overview .projects-block')).to have_selector('.js-view-all', visible: true)
+ end
+
+ it 'does not show pagination' do
+ page.within('.projects-block') do
+ expect(page).not_to have_selector('.gl-pagination')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/users/show_spec.rb b/spec/features/users/show_spec.rb
index bc07ab48c39..86379164cf0 100644
--- a/spec/features/users/show_spec.rb
+++ b/spec/features/users/show_spec.rb
@@ -8,6 +8,7 @@ describe 'User page' do
visit(user_path(user))
page.within '.nav-links' do
+ expect(page).to have_link('Overview')
expect(page).to have_link('Activity')
expect(page).to have_link('Groups')
expect(page).to have_link('Contributed projects')
@@ -44,6 +45,7 @@ describe 'User page' do
visit(user_path(user))
page.within '.nav-links' do
+ expect(page).to have_link('Overview')
expect(page).to have_link('Activity')
expect(page).to have_link('Groups')
expect(page).to have_link('Contributed projects')
diff --git a/spec/finders/admin/runners_finder_spec.rb b/spec/finders/admin/runners_finder_spec.rb
index 1e9793a5e0a..0b2325cc7ca 100644
--- a/spec/finders/admin/runners_finder_spec.rb
+++ b/spec/finders/admin/runners_finder_spec.rb
@@ -29,6 +29,14 @@ describe Admin::RunnersFinder do
end
end
+ context 'filter by runner type' do
+ it 'calls the corresponding scope on Ci::Runner' do
+ expect(Ci::Runner).to receive(:project_type).and_call_original
+
+ described_class.new(params: { type_type: 'project_type' }).execute
+ end
+ end
+
context 'sort' do
context 'without sort param' do
it 'sorts by created_at' do
diff --git a/spec/finders/applications_finder_spec.rb b/spec/finders/applications_finder_spec.rb
new file mode 100644
index 00000000000..14d6b35cc27
--- /dev/null
+++ b/spec/finders/applications_finder_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ApplicationsFinder do
+ let(:application1) { create(:application, name: 'some_application', owner: nil, redirect_uri: 'http://some_application.url', scopes: '') }
+ let(:application2) { create(:application, name: 'another_application', owner: nil, redirect_uri: 'http://other_application.url', scopes: '') }
+
+ describe '#execute' do
+ it 'returns an array of applications' do
+ found = described_class.new.execute
+
+ expect(found).to match_array([application1, application2])
+ end
+ it 'returns the application by id' do
+ params = { id: application1.id }
+ found = described_class.new(params).execute
+
+ expect(found).to match(application1)
+ end
+ end
+end
diff --git a/spec/finders/branches_finder_spec.rb b/spec/finders/branches_finder_spec.rb
index 9e3f2c69606..7d164539d9a 100644
--- a/spec/finders/branches_finder_spec.rb
+++ b/spec/finders/branches_finder_spec.rb
@@ -66,7 +66,7 @@ describe BranchesFinder do
context 'filter and sort' do
it 'filters branches by name and sorts by recently_updated' do
- params = { sort: 'updated_desc', search: 'feature' }
+ params = { sort: 'updated_desc', search: 'feat' }
branches_finder = described_class.new(repository, params)
result = branches_finder.execute
@@ -75,6 +75,17 @@ describe BranchesFinder do
expect(result.count).to eq(2)
end
+ it 'filters branches by name and sorts by recently_updated, with exact matches first' do
+ params = { sort: 'updated_desc', search: 'feature' }
+ branches_finder = described_class.new(repository, params)
+
+ result = branches_finder.execute
+
+ expect(result.first.name).to eq('feature')
+ expect(result.second.name).to eq('feature_conflict')
+ expect(result.count).to eq(2)
+ end
+
it 'filters branches by name and sorts by last_updated' do
params = { sort: 'updated_asc', search: 'feature' }
branches_finder = described_class.new(repository, params)
@@ -84,6 +95,26 @@ describe BranchesFinder do
expect(result.first.name).to eq('feature')
expect(result.count).to eq(2)
end
+
+ it 'filters branches by name that begins with' do
+ params = { search: '^feature_' }
+ branches_finder = described_class.new(repository, params)
+
+ result = branches_finder.execute
+
+ expect(result.first.name).to eq('feature_conflict')
+ expect(result.count).to eq(1)
+ end
+
+ it 'filters branches by name that ends with' do
+ params = { search: 'feature$' }
+ branches_finder = described_class.new(repository, params)
+
+ result = branches_finder.execute
+
+ expect(result.first.name).to eq('feature')
+ expect(result.count).to eq(1)
+ end
end
end
end
diff --git a/spec/finders/environments_finder_spec.rb b/spec/finders/environments_finder_spec.rb
index 3cd421f22eb..25835bb4d94 100644
--- a/spec/finders/environments_finder_spec.rb
+++ b/spec/finders/environments_finder_spec.rb
@@ -12,7 +12,7 @@ describe EnvironmentsFinder do
context 'tagged deployment' do
before do
- create(:deployment, environment: environment, ref: 'v1.1.0', tag: true, sha: project.commit.id)
+ create(:deployment, :success, environment: environment, ref: 'v1.1.0', tag: true, sha: project.commit.id)
end
it 'returns environment when with_tags is set' do
@@ -33,7 +33,7 @@ describe EnvironmentsFinder do
context 'branch deployment' do
before do
- create(:deployment, environment: environment, ref: 'master', sha: project.commit.id)
+ create(:deployment, :success, environment: environment, ref: 'master', sha: project.commit.id)
end
it 'returns environment when ref is set' do
@@ -59,7 +59,7 @@ describe EnvironmentsFinder do
context 'commit deployment' do
before do
- create(:deployment, environment: environment, ref: 'master', sha: project.commit.id)
+ create(:deployment, :success, environment: environment, ref: 'master', sha: project.commit.id)
end
it 'returns environment' do
@@ -71,7 +71,7 @@ describe EnvironmentsFinder do
context 'recently updated' do
context 'when last deployment to environment is the most recent one' do
before do
- create(:deployment, environment: environment, ref: 'feature')
+ create(:deployment, :success, environment: environment, ref: 'feature')
end
it 'finds recently updated environment' do
@@ -82,8 +82,8 @@ describe EnvironmentsFinder do
context 'when last deployment to environment is not the most recent' do
before do
- create(:deployment, environment: environment, ref: 'feature')
- create(:deployment, environment: environment, ref: 'master')
+ create(:deployment, :success, environment: environment, ref: 'feature')
+ create(:deployment, :success, environment: environment, ref: 'master')
end
it 'does not find environment' do
@@ -96,8 +96,8 @@ describe EnvironmentsFinder do
let(:second_environment) { create(:environment, project: project) }
before do
- create(:deployment, environment: environment, ref: 'feature')
- create(:deployment, environment: second_environment, ref: 'feature')
+ create(:deployment, :success, environment: environment, ref: 'feature')
+ create(:deployment, :success, environment: second_environment, ref: 'feature')
end
it 'finds both environments' do
diff --git a/spec/finders/fork_projects_finder_spec.rb b/spec/finders/fork_projects_finder_spec.rb
index f0cef7ea406..b3fdffc3331 100644
--- a/spec/finders/fork_projects_finder_spec.rb
+++ b/spec/finders/fork_projects_finder_spec.rb
@@ -1,20 +1,21 @@
require 'spec_helper'
describe ForkProjectsFinder do
- let(:source_project) { create(:project, :empty_repo) }
- let(:private_fork) { create(:project, :private, :empty_repo, name: 'A') }
- let(:internal_fork) { create(:project, :internal, :empty_repo, name: 'B') }
- let(:public_fork) { create(:project, :public, :empty_repo, name: 'C') }
+ include ProjectForksHelper
+
+ let(:source_project) { create(:project, :public, :empty_repo) }
+ let(:private_fork) { fork_project(source_project, nil, name: 'A') }
+ let(:internal_fork) { fork_project(source_project, nil, name: 'B') }
+ let(:public_fork) { fork_project(source_project, nil, name: 'C') }
let(:non_member) { create(:user) }
let(:private_fork_member) { create(:user) }
before do
+ private_fork.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
private_fork.add_developer(private_fork_member)
- source_project.forks << private_fork
- source_project.forks << internal_fork
- source_project.forks << public_fork
+ internal_fork.update!(visibility_level: Gitlab::VisibilityLevel::INTERNAL)
end
describe '#execute' do
diff --git a/spec/finders/group_descendants_finder_spec.rb b/spec/finders/group_descendants_finder_spec.rb
index c64abdc3619..c28fd7cad11 100644
--- a/spec/finders/group_descendants_finder_spec.rb
+++ b/spec/finders/group_descendants_finder_spec.rb
@@ -74,6 +74,13 @@ describe GroupDescendantsFinder do
end
end
+ it 'sorts elements by latest created as default' do
+ project1 = create(:project, namespace: group, created_at: 1.hour.ago)
+ project2 = create(:project, namespace: group)
+
+ expect(subject.execute).to eq([project2, project1])
+ end
+
context 'sorting by name' do
let!(:project1) { create(:project, namespace: group, name: 'a', path: 'project-a') }
let!(:project2) { create(:project, namespace: group, name: 'z', path: 'project-z') }
diff --git a/spec/finders/group_labels_finder_spec.rb b/spec/finders/group_labels_finder_spec.rb
new file mode 100644
index 00000000000..7bdd312eff0
--- /dev/null
+++ b/spec/finders/group_labels_finder_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe GroupLabelsFinder, '#execute' do
+ let!(:group) { create(:group) }
+ let!(:user) { create(:user) }
+ let!(:label1) { create(:group_label, title: 'Foo', description: 'Lorem ipsum', group: group) }
+ let!(:label2) { create(:group_label, title: 'Bar', description: 'Fusce consequat', group: group) }
+
+ it 'returns all group labels sorted by name if no params' do
+ result = described_class.new(user, group).execute
+
+ expect(result.to_a).to match_array([label2, label1])
+ end
+
+ it 'returns all group labels sorted by name desc' do
+ result = described_class.new(user, group, sort: 'name_desc').execute
+
+ expect(result.to_a).to match_array([label2, label1])
+ end
+
+ it 'returns group labels that match search' do
+ result = described_class.new(user, group, search: 'Foo').execute
+
+ expect(result.to_a).to match_array([label1])
+ end
+
+ it 'returns group labels user subscribed to' do
+ label2.subscribe(user)
+
+ result = described_class.new(user, group, subscribed: 'true').execute
+
+ expect(result.to_a).to match_array([label2])
+ end
+
+ it 'returns second page of labels' do
+ result = described_class.new(user, group, page: '2').execute
+
+ expect(result.to_a).to match_array([])
+ end
+end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index 07a2fa86dd7..515f6f70b99 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -56,6 +56,40 @@ describe IssuesFinder do
end
end
+ context 'filtering by no assignee' do
+ let(:params) { { assignee_id: 'None' } }
+
+ it 'returns issues not assigned to any assignee' do
+ expect(issues).to contain_exactly(issue4)
+ end
+
+ it 'returns issues not assigned to any assignee' do
+ params[:assignee_id] = 0
+
+ expect(issues).to contain_exactly(issue4)
+ end
+
+ it 'returns issues not assigned to any assignee' do
+ params[:assignee_id] = 'none'
+
+ expect(issues).to contain_exactly(issue4)
+ end
+ end
+
+ context 'filtering by any assignee' do
+ let(:params) { { assignee_id: 'Any' } }
+
+ it 'returns issues assigned to any assignee' do
+ expect(issues).to contain_exactly(issue1, issue2, issue3)
+ end
+
+ it 'returns issues assigned to any assignee' do
+ params[:assignee_id] = 'any'
+
+ expect(issues).to contain_exactly(issue1, issue2, issue3)
+ end
+ end
+
context 'filtering by group_id' do
let(:params) { { group_id: group.id } }
@@ -110,11 +144,31 @@ describe IssuesFinder do
end
context 'filtering by no milestone' do
- let(:params) { { milestone_title: Milestone::None.title } }
+ let(:params) { { milestone_title: 'None' } }
it 'returns issues with no milestone' do
expect(issues).to contain_exactly(issue2, issue3, issue4)
end
+
+ it 'returns issues with no milestone (deprecated)' do
+ params[:milestone_title] = Milestone::None.title
+
+ expect(issues).to contain_exactly(issue2, issue3, issue4)
+ end
+ end
+
+ context 'filtering by any milestone' do
+ let(:params) { { milestone_title: 'Any' } }
+
+ it 'returns issues with any assigned milestone' do
+ expect(issues).to contain_exactly(issue1)
+ end
+
+ it 'returns issues with any assigned milestone (deprecated)' do
+ params[:milestone_title] = Milestone::Any.title
+
+ expect(issues).to contain_exactly(issue1)
+ end
end
context 'filtering by upcoming milestone' do
@@ -202,19 +256,51 @@ describe IssuesFinder do
create(:label_link, label: label2, target: issue2)
end
- it 'returns the unique issues with any of those labels' do
+ it 'returns the unique issues with all those labels' do
+ expect(issues).to contain_exactly(issue2)
+ end
+ end
+
+ context 'filtering by a label that includes any or none in the title' do
+ let(:params) { { label_name: [label.title, label2.title].join(',') } }
+ let(:label) { create(:label, title: 'any foo', project: project2) }
+ let(:label2) { create(:label, title: 'bar none', project: project2) }
+
+ it 'returns the unique issues with all those labels' do
+ create(:label_link, label: label2, target: issue2)
+
expect(issues).to contain_exactly(issue2)
end
end
context 'filtering by no label' do
- let(:params) { { label_name: Label::None.title } }
+ let(:params) { { label_name: described_class::FILTER_NONE } }
it 'returns issues with no labels' do
expect(issues).to contain_exactly(issue1, issue3, issue4)
end
end
+ context 'filtering by legacy No+Label' do
+ let(:params) { { label_name: Label::NONE } }
+
+ it 'returns issues with no labels' do
+ expect(issues).to contain_exactly(issue1, issue3, issue4)
+ end
+ end
+
+ context 'filtering by any label' do
+ let(:params) { { label_name: described_class::FILTER_ANY } }
+
+ it 'returns issues that have one or more label' do
+ 2.times do
+ create(:label_link, label: create(:label, project: project2), target: issue3)
+ end
+
+ expect(issues).to contain_exactly(issue2, issue3)
+ end
+ end
+
context 'filtering by issue term' do
let(:params) { { search: 'git' } }
@@ -318,6 +404,22 @@ describe IssuesFinder do
end
context 'filtering by reaction name' do
+ context 'user searches by no reaction' do
+ let(:params) { { my_reaction_emoji: 'None' } }
+
+ it 'returns issues that the user did not react to' do
+ expect(issues).to contain_exactly(issue2, issue4)
+ end
+ end
+
+ context 'user searches by any reaction' do
+ let(:params) { { my_reaction_emoji: 'Any' } }
+
+ it 'returns issues that the user reacted to' do
+ expect(issues).to contain_exactly(issue1, issue3)
+ end
+ end
+
context 'user searches by "thumbsup" reaction' do
let(:params) { { my_reaction_emoji: 'thumbsup' } }
diff --git a/spec/finders/labels_finder_spec.rb b/spec/finders/labels_finder_spec.rb
index f5cec8e349a..9abc52aa664 100644
--- a/spec/finders/labels_finder_spec.rb
+++ b/spec/finders/labels_finder_spec.rb
@@ -210,5 +210,15 @@ describe LabelsFinder do
expect(finder.execute).to eq [project_label_1]
end
end
+
+ context 'filter by subscription' do
+ it 'returns labels user subscribed to' do
+ project_label_1.subscribe(user)
+
+ finder = described_class.new(user, subscribed: 'true')
+
+ expect(finder.execute).to eq [project_label_1]
+ end
+ end
end
end
diff --git a/spec/finders/license_template_finder_spec.rb b/spec/finders/license_template_finder_spec.rb
index a97903103c9..f6f40bf33cc 100644
--- a/spec/finders/license_template_finder_spec.rb
+++ b/spec/finders/license_template_finder_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe LicenseTemplateFinder do
describe '#execute' do
- subject(:result) { described_class.new(params).execute }
+ subject(:result) { described_class.new(nil, params).execute }
let(:categories) { categorised_licenses.keys }
let(:categorised_licenses) { result.group_by(&:category) }
@@ -31,7 +31,7 @@ describe LicenseTemplateFinder do
it 'returns all licenses known by the Licensee gem' do
from_licensee = Licensee::License.all.map { |l| l.key }
- expect(result.map(&:id)).to match_array(from_licensee)
+ expect(result.map(&:key)).to match_array(from_licensee)
end
it 'correctly copies all attributes' do
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index 35d0eeda8f6..ff4c6b8dd42 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -3,25 +3,47 @@ require 'spec_helper'
describe MergeRequestsFinder do
include ProjectForksHelper
+ # We need to explicitly permit Gitaly N+1s because of the specs that use
+ # :request_store. Gitaly N+1 detection is only enabled when :request_store is,
+ # but we don't care about potential N+1s when we're just creating several
+ # projects in the setup phase.
+ def create_project_without_n_plus_1(*args)
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ create(:project, :public, *args)
+ end
+ end
+
let(:user) { create :user }
let(:user2) { create :user }
let(:group) { create(:group) }
let(:subgroup) { create(:group, parent: group) }
- let(:project1) { create(:project, :public, group: group) }
- let(:project2) { fork_project(project1, user) }
+ let(:project1) { create_project_without_n_plus_1(group: group) }
+ let(:project2) do
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ fork_project(project1, user)
+ end
+ end
let(:project3) do
- p = fork_project(project1, user)
- p.update!(archived: true)
- p
+ Gitlab::GitalyClient.allow_n_plus_1_calls do
+ p = fork_project(project1, user)
+ p.update!(archived: true)
+ p
+ end
end
- let(:project4) { create(:project, :public, group: subgroup) }
+ let(:project4) { create_project_without_n_plus_1(group: subgroup) }
+ let(:project5) { create_project_without_n_plus_1(group: subgroup) }
+ let(:project6) { create_project_without_n_plus_1(group: subgroup) }
let!(:merge_request1) { create(:merge_request, :simple, author: user, source_project: project2, target_project: project1) }
let!(:merge_request2) { create(:merge_request, :conflict, author: user, source_project: project2, target_project: project1, state: 'closed') }
- let!(:merge_request3) { create(:merge_request, :simple, author: user, source_project: project2, target_project: project2, state: 'locked') }
- let!(:merge_request4) { create(:merge_request, :simple, author: user, source_project: project3, target_project: project3) }
- let!(:merge_request5) { create(:merge_request, :simple, author: user, source_project: project4, target_project: project4) }
+ let!(:merge_request3) { create(:merge_request, :simple, author: user, source_project: project2, target_project: project2, state: 'locked', title: 'thing WIP thing') }
+ let!(:merge_request4) { create(:merge_request, :simple, author: user, source_project: project3, target_project: project3, title: 'WIP thing') }
+ let!(:merge_request5) { create(:merge_request, :simple, author: user, source_project: project4, target_project: project4, title: '[WIP]') }
+ let!(:merge_request6) { create(:merge_request, :simple, author: user, source_project: project5, target_project: project5, title: 'WIP: thing') }
+ let!(:merge_request7) { create(:merge_request, :simple, author: user, source_project: project6, target_project: project6, title: 'wip thing') }
+ let!(:merge_request8) { create(:merge_request, :simple, author: user, source_project: project1, target_project: project1, title: '[wip] thing') }
+ let!(:merge_request9) { create(:merge_request, :simple, author: user, source_project: project1, target_project: project2, title: 'wip: thing') }
before do
project1.add_maintainer(user)
@@ -29,19 +51,21 @@ describe MergeRequestsFinder do
project3.add_developer(user)
project2.add_developer(user2)
project4.add_developer(user)
+ project5.add_developer(user)
+ project6.add_developer(user)
end
describe "#execute" do
it 'filters by scope' do
params = { scope: 'authored', state: 'opened' }
merge_requests = described_class.new(user, params).execute
- expect(merge_requests.size).to eq(3)
+ expect(merge_requests.size).to eq(7)
end
it 'filters by project' do
params = { project_id: project1.id, scope: 'authored', state: 'opened' }
merge_requests = described_class.new(user, params).execute
- expect(merge_requests.size).to eq(1)
+ expect(merge_requests.size).to eq(2)
end
it 'filters by group' do
@@ -49,7 +73,7 @@ describe MergeRequestsFinder do
merge_requests = described_class.new(user, params).execute
- expect(merge_requests.size).to eq(2)
+ expect(merge_requests.size).to eq(3)
end
it 'filters by group including subgroups', :nested_groups do
@@ -57,13 +81,13 @@ describe MergeRequestsFinder do
merge_requests = described_class.new(user, params).execute
- expect(merge_requests.size).to eq(3)
+ expect(merge_requests.size).to eq(6)
end
it 'filters by non_archived' do
params = { non_archived: true }
merge_requests = described_class.new(user, params).execute
- expect(merge_requests.size).to eq(4)
+ expect(merge_requests.size).to eq(8)
end
it 'filters by iid' do
@@ -98,6 +122,36 @@ describe MergeRequestsFinder do
expect(merge_requests).to contain_exactly(merge_request3)
end
+ it 'filters by wip' do
+ params = { wip: 'yes' }
+
+ merge_requests = described_class.new(user, params).execute
+
+ expect(merge_requests).to contain_exactly(merge_request4, merge_request5, merge_request6, merge_request7, merge_request8, merge_request9)
+ end
+
+ it 'filters by not wip' do
+ params = { wip: 'no' }
+
+ merge_requests = described_class.new(user, params).execute
+
+ expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3)
+ end
+
+ it 'returns all items if no valid wip param exists' do
+ params = { wip: '' }
+
+ merge_requests = described_class.new(user, params).execute
+
+ expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3, merge_request4, merge_request5, merge_request6, merge_request7, merge_request8, merge_request9)
+ end
+
+ it 'adds wip to scalar params' do
+ scalar_params = described_class.scalar_params
+
+ expect(scalar_params).to include(:wip, :assignee_id)
+ end
+
context 'filtering by group milestone' do
let!(:group) { create(:group, :public) }
let(:group_milestone) { create(:milestone, group: group) }
@@ -207,7 +261,7 @@ describe MergeRequestsFinder do
it 'returns the number of rows for the default state' do
finder = described_class.new(user)
- expect(finder.row_count).to eq(3)
+ expect(finder.row_count).to eq(7)
end
it 'returns the number of rows for a given state' do
diff --git a/spec/finders/notes_finder_spec.rb b/spec/finders/notes_finder_spec.rb
index b776e9d856a..b51f1955ac4 100644
--- a/spec/finders/notes_finder_spec.rb
+++ b/spec/finders/notes_finder_spec.rb
@@ -9,6 +9,35 @@ describe NotesFinder do
end
describe '#execute' do
+ context 'when notes filter is present' do
+ let!(:comment) { create(:note_on_issue, project: project) }
+ let!(:system_note) { create(:note_on_issue, project: project, system: true) }
+
+ it 'returns only user notes when using only_comments filter' do
+ finder = described_class.new(project, user, notes_filter: UserPreference::NOTES_FILTERS[:only_comments])
+
+ notes = finder.execute
+
+ expect(notes).to match_array(comment)
+ end
+
+ it 'returns only system notes when using only_activity filters' do
+ finder = described_class.new(project, user, notes_filter: UserPreference::NOTES_FILTERS[:only_activity])
+
+ notes = finder.execute
+
+ expect(notes).to match_array(system_note)
+ end
+
+ it 'gets all notes' do
+ finder = described_class.new(project, user, notes_filter: UserPreference::NOTES_FILTERS[:all_activity])
+
+ notes = finder.execute
+
+ expect(notes).to match_array([comment, system_note])
+ end
+ end
+
it 'finds notes on merge requests' do
create(:note_on_merge_request, project: project)
diff --git a/spec/finders/pending_todos_finder_spec.rb b/spec/finders/pending_todos_finder_spec.rb
new file mode 100644
index 00000000000..b41b1b46a93
--- /dev/null
+++ b/spec/finders/pending_todos_finder_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe PendingTodosFinder do
+ let(:user) { create(:user) }
+
+ describe '#execute' do
+ it 'returns only pending todos' do
+ create(:todo, :done, user: user)
+
+ todo = create(:todo, :pending, user: user)
+ todos = described_class.new(user).execute
+
+ expect(todos).to eq([todo])
+ end
+
+ it 'supports retrieving of todos for a specific project' do
+ project1 = create(:project)
+ project2 = create(:project)
+
+ create(:todo, :pending, user: user, project: project2)
+
+ todo = create(:todo, :pending, user: user, project: project1)
+ todos = described_class.new(user, project_id: project1.id).execute
+
+ expect(todos).to eq([todo])
+ end
+
+ it 'supports retrieving of todos for a specific todo target' do
+ issue = create(:issue)
+ note = create(:note)
+ todo = create(:todo, :pending, user: user, target: issue)
+
+ create(:todo, :pending, user: user, target: note)
+
+ todos = described_class.new(user, target_id: issue.id).execute
+
+ expect(todos).to eq([todo])
+ end
+
+ it 'supports retrieving of todos for a specific target type' do
+ issue = create(:issue)
+ note = create(:note)
+ todo = create(:todo, :pending, user: user, target: issue)
+
+ create(:todo, :pending, user: user, target: note)
+
+ todos = described_class.new(user, target_type: issue.class.name).execute
+
+ expect(todos).to eq([todo])
+ end
+
+ it 'supports retrieving of todos for a specific commit ID' do
+ create(:todo, :pending, user: user, commit_id: '456')
+
+ todo = create(:todo, :pending, user: user, commit_id: '123')
+ todos = described_class.new(user, commit_id: '123').execute
+
+ expect(todos).to eq([todo])
+ end
+ end
+end
diff --git a/spec/finders/personal_access_tokens_finder_spec.rb b/spec/finders/personal_access_tokens_finder_spec.rb
index 3f22b3a253d..3e849c9a644 100644
--- a/spec/finders/personal_access_tokens_finder_spec.rb
+++ b/spec/finders/personal_access_tokens_finder_spec.rb
@@ -92,7 +92,7 @@ describe PersonalAccessTokensFinder do
end
describe 'with id' do
- subject { finder(params).find_by(id: active_personal_access_token.id) }
+ subject { finder(params).find_by_id(active_personal_access_token.id) }
it { is_expected.to eq(active_personal_access_token) }
@@ -106,7 +106,7 @@ describe PersonalAccessTokensFinder do
end
describe 'with token' do
- subject { finder(params).find_by(token: active_personal_access_token.token) }
+ subject { finder(params).find_by_token(active_personal_access_token.token) }
it { is_expected.to eq(active_personal_access_token) }
@@ -207,7 +207,7 @@ describe PersonalAccessTokensFinder do
end
describe 'with id' do
- subject { finder(params).find_by(id: active_personal_access_token.id) }
+ subject { finder(params).find_by_id(active_personal_access_token.id) }
it { is_expected.to eq(active_personal_access_token) }
@@ -221,7 +221,7 @@ describe PersonalAccessTokensFinder do
end
describe 'with token' do
- subject { finder(params).find_by(token: active_personal_access_token.token) }
+ subject { finder(params).find_by_token(active_personal_access_token.token) }
it { is_expected.to eq(active_personal_access_token) }
diff --git a/spec/finders/pipeline_schedules_finder_spec.rb b/spec/finders/pipeline_schedules_finder_spec.rb
index b9538649b3f..2fefa0280d1 100644
--- a/spec/finders/pipeline_schedules_finder_spec.rb
+++ b/spec/finders/pipeline_schedules_finder_spec.rb
@@ -12,7 +12,7 @@ describe PipelineSchedulesFinder do
context 'when the scope is nil' do
let(:params) { { scope: nil } }
- it 'selects all pipeline pipeline schedules' do
+ it 'selects all pipeline schedules' do
expect(subject.count).to be(2)
expect(subject).to include(active_schedule, inactive_schedule)
end
diff --git a/spec/finders/pipelines_finder_spec.rb b/spec/finders/pipelines_finder_spec.rb
index c6e832ad69b..c2c304589c9 100644
--- a/spec/finders/pipelines_finder_spec.rb
+++ b/spec/finders/pipelines_finder_spec.rb
@@ -225,7 +225,7 @@ describe PipelinesFinder do
end
end
- context 'when the project has limited access to piplines' do
+ context 'when the project has limited access to pipelines' do
let(:project) { create(:project, :private, :repository) }
let(:current_user) { create(:user) }
let!(:pipelines) { create_list(:ci_pipeline, 2, project: project) }
diff --git a/spec/finders/snippets_finder_spec.rb b/spec/finders/snippets_finder_spec.rb
index 1ae0bd988f2..dfeeb3040c6 100644
--- a/spec/finders/snippets_finder_spec.rb
+++ b/spec/finders/snippets_finder_spec.rb
@@ -4,16 +4,13 @@ describe SnippetsFinder do
include Gitlab::Allowable
using RSpec::Parameterized::TableSyntax
- context 'filter by visibility' do
- let!(:snippet1) { create(:personal_snippet, :private) }
- let!(:snippet2) { create(:personal_snippet, :internal) }
- let!(:snippet3) { create(:personal_snippet, :public) }
+ describe '#initialize' do
+ it 'raises ArgumentError when a project and author are given' do
+ user = build(:user)
+ project = build(:project)
- it "returns public snippets when visibility is PUBLIC" do
- snippets = described_class.new(nil, visibility: Snippet::PUBLIC).execute
-
- expect(snippets).to include(snippet3)
- expect(snippets).not_to include(snippet1, snippet2)
+ expect { described_class.new(user, author: user, project: project) }
+ .to raise_error(ArgumentError)
end
end
@@ -66,21 +63,21 @@ describe SnippetsFinder do
end
it "returns internal snippets" do
- snippets = described_class.new(user, author: user, visibility: Snippet::INTERNAL).execute
+ snippets = described_class.new(user, author: user, scope: :are_internal).execute
expect(snippets).to include(snippet2)
expect(snippets).not_to include(snippet1, snippet3)
end
it "returns private snippets" do
- snippets = described_class.new(user, author: user, visibility: Snippet::PRIVATE).execute
+ snippets = described_class.new(user, author: user, scope: :are_private).execute
expect(snippets).to include(snippet1)
expect(snippets).not_to include(snippet2, snippet3)
end
it "returns public snippets" do
- snippets = described_class.new(user, author: user, visibility: Snippet::PUBLIC).execute
+ snippets = described_class.new(user, author: user, scope: :are_public).execute
expect(snippets).to include(snippet3)
expect(snippets).not_to include(snippet1, snippet2)
@@ -98,6 +95,13 @@ describe SnippetsFinder do
expect(snippets).to include(snippet3)
expect(snippets).not_to include(snippet2, snippet1)
end
+
+ it 'returns all snippets for an admin' do
+ admin = create(:user, :admin)
+ snippets = described_class.new(admin, author: user).execute
+
+ expect(snippets).to include(snippet1, snippet2, snippet3)
+ end
end
context 'filter by project' do
@@ -126,21 +130,21 @@ describe SnippetsFinder do
end
it "returns public snippets for non project members" do
- snippets = described_class.new(user, project: project1, visibility: Snippet::PUBLIC).execute
+ snippets = described_class.new(user, project: project1, scope: :are_public).execute
expect(snippets).to include(@snippet3)
expect(snippets).not_to include(@snippet1, @snippet2)
end
it "returns internal snippets for non project members" do
- snippets = described_class.new(user, project: project1, visibility: Snippet::INTERNAL).execute
+ snippets = described_class.new(user, project: project1, scope: :are_internal).execute
expect(snippets).to include(@snippet2)
expect(snippets).not_to include(@snippet1, @snippet3)
end
it "does not return private snippets for non project members" do
- snippets = described_class.new(user, project: project1, visibility: Snippet::PRIVATE).execute
+ snippets = described_class.new(user, project: project1, scope: :are_private).execute
expect(snippets).not_to include(@snippet1, @snippet2, @snippet3)
end
@@ -156,10 +160,17 @@ describe SnippetsFinder do
it "returns private snippets for project members" do
project1.add_developer(user)
- snippets = described_class.new(user, project: project1, visibility: Snippet::PRIVATE).execute
+ snippets = described_class.new(user, project: project1, scope: :are_private).execute
expect(snippets).to include(@snippet1)
end
+
+ it 'returns all snippets for an admin' do
+ admin = create(:user, :admin)
+ snippets = described_class.new(admin, project: project1).execute
+
+ expect(snippets).to include(@snippet1, @snippet2, @snippet3)
+ end
end
describe '#execute' do
@@ -184,4 +195,6 @@ describe SnippetsFinder do
end
end
end
+
+ it_behaves_like 'snippet visibility'
end
diff --git a/spec/finders/template_finder_spec.rb b/spec/finders/template_finder_spec.rb
index 1d399e8194f..114af9461e0 100644
--- a/spec/finders/template_finder_spec.rb
+++ b/spec/finders/template_finder_spec.rb
@@ -4,6 +4,8 @@ describe TemplateFinder do
using RSpec::Parameterized::TableSyntax
describe '#build' do
+ let(:project) { build_stubbed(:project) }
+
where(:type, :expected_class) do
:dockerfiles | described_class
:gitignores | described_class
@@ -12,9 +14,10 @@ describe TemplateFinder do
end
with_them do
- subject { described_class.build(type) }
+ subject(:finder) { described_class.build(type, project) }
it { is_expected.to be_a(expected_class) }
+ it { expect(finder.project).to eq(project) }
end
end
@@ -27,19 +30,19 @@ describe TemplateFinder do
with_them do
it 'returns all vendored templates when no name is specified' do
- result = described_class.new(type).execute
+ result = described_class.new(type, nil).execute
expect(result).to include(have_attributes(name: vendored_name))
end
it 'returns only the specified vendored template when a name is specified' do
- result = described_class.new(type, name: vendored_name).execute
+ result = described_class.new(type, nil, name: vendored_name).execute
expect(result).to have_attributes(name: vendored_name)
end
it 'returns nil when an unknown name is specified' do
- result = described_class.new(type, name: 'unknown').execute
+ result = described_class.new(type, nil, name: 'unknown').execute
expect(result).to be_nil
end
diff --git a/spec/finders/todos_finder_spec.rb b/spec/finders/todos_finder_spec.rb
index 7f7cfb2cb98..d4ed41d54f0 100644
--- a/spec/finders/todos_finder_spec.rb
+++ b/spec/finders/todos_finder_spec.rb
@@ -105,9 +105,24 @@ describe TodosFinder do
todos = finder.new(user, { sort: 'priority' }).execute
- puts todos.to_sql
expect(todos).to eq([todo_3, todo_5, todo_4, todo_2, todo_1])
end
end
end
+
+ describe '#any_for_target?' do
+ it 'returns true if there are any todos for the given target' do
+ todo = create(:todo, :pending)
+ finder = described_class.new(todo.user)
+
+ expect(finder.any_for_target?(todo.target)).to eq(true)
+ end
+
+ it 'returns false if there are no todos for the given target' do
+ issue = create(:issue)
+ finder = described_class.new(issue.author)
+
+ expect(finder.any_for_target?(issue)).to eq(false)
+ end
+ end
end
diff --git a/spec/finders/user_finder_spec.rb b/spec/finders/user_finder_spec.rb
index e53aa50dd33..4771b878b8e 100644
--- a/spec/finders/user_finder_spec.rb
+++ b/spec/finders/user_finder_spec.rb
@@ -3,40 +3,176 @@
require 'spec_helper'
describe UserFinder do
- describe '#execute' do
+ set(:user) { create(:user) }
+
+ describe '#find_by_id' do
+ context 'when the user exists' do
+ it 'returns the user' do
+ found = described_class.new(user.id).find_by_id
+
+ expect(found).to eq(user)
+ end
+ end
+
+ context 'when the user exists (id as string)' do
+ it 'returns the user' do
+ found = described_class.new(user.id.to_s).find_by_id
+
+ expect(found).to eq(user)
+ end
+ end
+
+ context 'when the user does not exist' do
+ it 'returns nil' do
+ found = described_class.new(1).find_by_id
+
+ expect(found).to be_nil
+ end
+ end
+ end
+
+ describe '#find_by_username' do
context 'when the user exists' do
it 'returns the user' do
- user = create(:user)
- found = described_class.new(id: user.id).execute
+ found = described_class.new(user.username).find_by_username
+
+ expect(found).to eq(user)
+ end
+ end
+
+ context 'when the user does not exist' do
+ it 'returns nil' do
+ found = described_class.new("non_existent_username").find_by_username
+
+ expect(found).to be_nil
+ end
+ end
+ end
+
+ describe '#find_by_id_or_username' do
+ context 'when the user exists (id)' do
+ it 'returns the user' do
+ found = described_class.new(user.id).find_by_id_or_username
+
+ expect(found).to eq(user)
+ end
+ end
+
+ context 'when the user exists (id as string)' do
+ it 'returns the user' do
+ found = described_class.new(user.id.to_s).find_by_id_or_username
expect(found).to eq(user)
end
end
+ context 'when the user exists (username)' do
+ it 'returns the user' do
+ found = described_class.new(user.username).find_by_id_or_username
+
+ expect(found).to eq(user)
+ end
+ end
+
+ context 'when the user does not exist (username)' do
+ it 'returns nil' do
+ found = described_class.new("non_existent_username").find_by_id_or_username
+
+ expect(found).to be_nil
+ end
+ end
+
context 'when the user does not exist' do
it 'returns nil' do
- found = described_class.new(id: 1).execute
+ found = described_class.new(1).find_by_id_or_username
expect(found).to be_nil
end
end
end
- describe '#execute!' do
+ describe '#find_by_id!' do
+ context 'when the user exists' do
+ it 'returns the user' do
+ found = described_class.new(user.id).find_by_id!
+
+ expect(found).to eq(user)
+ end
+ end
+
+ context 'when the user exists (id as string)' do
+ it 'returns the user' do
+ found = described_class.new(user.id.to_s).find_by_id!
+
+ expect(found).to eq(user)
+ end
+ end
+
+ context 'when the user does not exist' do
+ it 'raises ActiveRecord::RecordNotFound' do
+ finder = described_class.new(1)
+
+ expect { finder.find_by_id! }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+ end
+
+ describe '#find_by_username!' do
context 'when the user exists' do
it 'returns the user' do
- user = create(:user)
- found = described_class.new(id: user.id).execute!
+ found = described_class.new(user.username).find_by_username!
+
+ expect(found).to eq(user)
+ end
+ end
+
+ context 'when the user does not exist' do
+ it 'raises ActiveRecord::RecordNotFound' do
+ finder = described_class.new("non_existent_username")
+
+ expect { finder.find_by_username! }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+ end
+
+ describe '#find_by_id_or_username!' do
+ context 'when the user exists (id)' do
+ it 'returns the user' do
+ found = described_class.new(user.id).find_by_id_or_username!
+
+ expect(found).to eq(user)
+ end
+ end
+
+ context 'when the user exists (id as string)' do
+ it 'returns the user' do
+ found = described_class.new(user.id.to_s).find_by_id_or_username!
expect(found).to eq(user)
end
end
+ context 'when the user exists (username)' do
+ it 'returns the user' do
+ found = described_class.new(user.username).find_by_id_or_username!
+
+ expect(found).to eq(user)
+ end
+ end
+
+ context 'when the user does not exist (username)' do
+ it 'raises ActiveRecord::RecordNotFound' do
+ finder = described_class.new("non_existent_username")
+
+ expect { finder.find_by_id_or_username! }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+
context 'when the user does not exist' do
it 'raises ActiveRecord::RecordNotFound' do
- finder = described_class.new(id: 1)
+ finder = described_class.new(1)
- expect { finder.execute! }.to raise_error(ActiveRecord::RecordNotFound)
+ expect { finder.find_by_id_or_username! }.to raise_error(ActiveRecord::RecordNotFound)
end
end
end
diff --git a/spec/finders/users_finder_spec.rb b/spec/finders/users_finder_spec.rb
index 4249c52c481..fecf97dc641 100644
--- a/spec/finders/users_finder_spec.rb
+++ b/spec/finders/users_finder_spec.rb
@@ -22,6 +22,12 @@ describe UsersFinder do
expect(users).to contain_exactly(user1)
end
+ it 'filters by username (case insensitive)' do
+ users = described_class.new(user, username: 'joHNdoE').execute
+
+ expect(users).to contain_exactly(user1)
+ end
+
it 'filters by search' do
users = described_class.new(user, search: 'orando').execute
diff --git a/spec/finders/users_with_pending_todos_finder_spec.rb b/spec/finders/users_with_pending_todos_finder_spec.rb
new file mode 100644
index 00000000000..fa15355531c
--- /dev/null
+++ b/spec/finders/users_with_pending_todos_finder_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe UsersWithPendingTodosFinder do
+ describe '#execute' do
+ it 'returns the users for all pending todos of a target' do
+ issue = create(:issue)
+ note = create(:note)
+ todo = create(:todo, :pending, target: issue)
+
+ create(:todo, :pending, target: note)
+
+ users = described_class.new(issue).execute
+
+ expect(users).to eq([todo.user])
+ end
+ end
+end
diff --git a/spec/fixtures/api/schemas/deployment.json b/spec/fixtures/api/schemas/deployment.json
index 8c8cdf8bcb2..0828f113495 100644
--- a/spec/fixtures/api/schemas/deployment.json
+++ b/spec/fixtures/api/schemas/deployment.json
@@ -20,12 +20,39 @@
"name"
],
"properties": {
- "name": { "type": "string" }
+ "name": { "type": "string" },
+ "ref_path": { "type": "string" }
},
"additionalProperties": false
},
"sha": { "type": "string" },
- "tag": { "type": "boolean" }
+ "tag": { "type": "boolean" },
+ "user": {
+ "oneOf": [
+ { "type": "null" },
+ { "$ref": "entities/user.json" }
+ ]
+ },
+ "commit": {
+ "oneOf": [
+ { "type": "null" },
+ { "$ref": "entities/commit.json" }
+ ]
+ },
+ "deployable": {
+ "oneOf": [
+ { "type": "null" },
+ { "$ref": "job/job.json" }
+ ]
+ },
+ "manual_actions": {
+ "type": "array",
+ "items": { "$ref": "job/job.json" }
+ },
+ "scheduled_actions": {
+ "type": "array",
+ "items": { "$ref": "job/job.json" }
+ }
},
"additionalProperties": false
}
diff --git a/spec/fixtures/api/schemas/entities/commit.json b/spec/fixtures/api/schemas/entities/commit.json
index 686d29c97d2..324702e3f94 100644
--- a/spec/fixtures/api/schemas/entities/commit.json
+++ b/spec/fixtures/api/schemas/entities/commit.json
@@ -17,11 +17,10 @@
"author": {
"oneOf": [
{ "type": "null" },
- { "type": "user.json" }
+ { "$ref": "user.json" }
]
}
- },
- "additionalProperties": false
+ }
}
]
}
diff --git a/spec/fixtures/api/schemas/entities/diff_viewer.json b/spec/fixtures/api/schemas/entities/diff_viewer.json
new file mode 100644
index 00000000000..19780f49a88
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/diff_viewer.json
@@ -0,0 +1,8 @@
+{
+ "type": "object",
+ "required": ["name"],
+ "properties": {
+ "name": { "type": ["string"] }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/entities/issue_board.json b/spec/fixtures/api/schemas/entities/issue_board.json
new file mode 100644
index 00000000000..3e252ddd13c
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/issue_board.json
@@ -0,0 +1,39 @@
+{
+ "type": "object",
+ "properties" : {
+ "id": { "type": "integer" },
+ "iid": { "type": "integer" },
+ "title": { "type": "string" },
+ "confidential": { "type": "boolean" },
+ "due_date": { "type": "date" },
+ "project_id": { "type": "integer" },
+ "relative_position": { "type": ["integer", "null"] },
+ "time_estimate": { "type": "integer" },
+ "weight": { "type": "integer" },
+ "project": {
+ "type": "object",
+ "properties": {
+ "id": { "type": "integer" },
+ "path": { "type": "string" }
+ }
+ },
+ "milestone": {
+ "type": "object",
+ "properties": {
+ "id": { "type": "integer" },
+ "title": { "type": "string" }
+ }
+ },
+ "assignees": { "type": ["array", "null"] },
+ "labels": {
+ "type": "array",
+ "items": { "$ref": "label.json" }
+ },
+ "reference_path": { "type": "string" },
+ "real_path": { "type": "string" },
+ "issue_sidebar_endpoint": { "type": "string" },
+ "toggle_subscription_endpoint": { "type": "string" },
+ "assignable_labels_endpoint": { "type": "string" }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/entities/merge_request_widget.json b/spec/fixtures/api/schemas/entities/merge_request_widget.json
index c40977bc4ee..35971d564d5 100644
--- a/spec/fixtures/api/schemas/entities/merge_request_widget.json
+++ b/spec/fixtures/api/schemas/entities/merge_request_widget.json
@@ -46,6 +46,7 @@
"diff_head_commit_short_id": { "type": ["string", "null"] },
"merge_commit_message": { "type": ["string", "null"] },
"pipeline": { "type": ["object", "null"] },
+ "merge_pipeline": { "type": ["object", "null"] },
"work_in_progress": { "type": "boolean" },
"source_branch_exists": { "type": "boolean" },
"mergeable_discussions_state": { "type": "boolean" },
diff --git a/spec/fixtures/api/schemas/entities/note_user_entity.json b/spec/fixtures/api/schemas/entities/note_user_entity.json
new file mode 100644
index 00000000000..9b838054563
--- /dev/null
+++ b/spec/fixtures/api/schemas/entities/note_user_entity.json
@@ -0,0 +1,21 @@
+{
+ "type": "object",
+ "required": [
+ "id",
+ "state",
+ "avatar_url",
+ "path",
+ "name",
+ "username"
+ ],
+ "properties": {
+ "id": { "type": "integer" },
+ "state": { "type": "string" },
+ "avatar_url": { "type": "string" },
+ "path": { "type": "string" },
+ "name": { "type": "string" },
+ "username": { "type": "string" },
+ "status_tooltip_html": { "$ref": "../types/nullable_string.json" }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/issue.json b/spec/fixtures/api/schemas/issue.json
index 8833825e3fb..a83ec55cede 100644
--- a/spec/fixtures/api/schemas/issue.json
+++ b/spec/fixtures/api/schemas/issue.json
@@ -13,8 +13,10 @@
"confidential": { "type": "boolean" },
"due_date": { "type": ["date", "null"] },
"relative_position": { "type": "integer" },
+ "time_estimate": { "type": "integer" },
"issue_sidebar_endpoint": { "type": "string" },
"toggle_subscription_endpoint": { "type": "string" },
+ "assignable_labels_endpoint": { "type": "string" },
"reference_path": { "type": "string" },
"real_path": { "type": "string" },
"project": {
diff --git a/spec/fixtures/api/schemas/job/deployment_status.json b/spec/fixtures/api/schemas/job/deployment_status.json
index a90b8b35654..83b1899fdf3 100644
--- a/spec/fixtures/api/schemas/job/deployment_status.json
+++ b/spec/fixtures/api/schemas/job/deployment_status.json
@@ -2,7 +2,6 @@
"type": "object",
"required": [
"status",
- "icon",
"environment"
],
"properties": {
@@ -20,7 +19,6 @@
{ "type": "null" }
]
},
- "icon": { "type": "string" },
"environment": { "$ref": "../environment.json" }
},
"additionalProperties": false
diff --git a/spec/fixtures/api/schemas/job/job.json b/spec/fixtures/api/schemas/job/job.json
index 734c535ef70..f3d5e9b038a 100644
--- a/spec/fixtures/api/schemas/job/job.json
+++ b/spec/fixtures/api/schemas/job/job.json
@@ -9,7 +9,8 @@
"playable",
"created_at",
"updated_at",
- "status"
+ "status",
+ "archived"
],
"properties": {
"id": { "type": "integer" },
@@ -27,7 +28,8 @@
"updated_at": { "type": "string" },
"status": { "$ref": "../status/ci_detailed_status.json" },
"callout_message": { "type": "string" },
- "recoverable": { "type": "boolean" }
+ "recoverable": { "type": "boolean" },
+ "archived": { "type": "boolean" }
},
"additionalProperties": true
}
diff --git a/spec/fixtures/api/schemas/job/job_details.json b/spec/fixtures/api/schemas/job/job_details.json
index cd67d3e4160..cdf7b049ab6 100644
--- a/spec/fixtures/api/schemas/job/job_details.json
+++ b/spec/fixtures/api/schemas/job/job_details.json
@@ -3,12 +3,22 @@
{ "$ref": "job.json" }
],
"description": "An extension of job.json with more detailed information",
+ "required": [
+ "artifact",
+ "runner",
+ "runners",
+ "has_trace",
+ "stage"
+ ],
"properties": {
"artifact": { "$ref": "artifact.json" },
"terminal_path": { "type": "string" },
"trigger": { "$ref": "trigger.json" },
"deployment_status": { "$ref": "deployment_status.json" },
"runner": { "$ref": "runner.json" },
- "runners": { "type": "runners.json" }
+ "runners": { "$ref": "runners.json" },
+ "has_trace": { "type": "boolean" },
+ "stage": { "type": "string" },
+ "stuck": { "type": "boolean" }
}
}
diff --git a/spec/fixtures/api/schemas/job/runners.json b/spec/fixtures/api/schemas/job/runners.json
index bebb0c88652..646bfd3a82d 100644
--- a/spec/fixtures/api/schemas/job/runners.json
+++ b/spec/fixtures/api/schemas/job/runners.json
@@ -8,6 +8,5 @@
"online": { "type": "boolean" },
"available": { "type": "boolean" },
"settings_path": { "type": "string" }
- },
- "additionalProperties": false
+ }
}
diff --git a/spec/fixtures/api/schemas/public_api/v4/license.json b/spec/fixtures/api/schemas/public_api/v4/license.json
new file mode 100644
index 00000000000..38c8c3e9192
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/license.json
@@ -0,0 +1,30 @@
+{
+ "type": "object",
+ "required": [
+ "key",
+ "name",
+ "nickname",
+ "popular",
+ "html_url",
+ "source_url",
+ "description",
+ "conditions",
+ "permissions",
+ "limitations",
+ "content"
+ ],
+ "properties": {
+ "key": { "type": "string" },
+ "name": { "type": "string" },
+ "nickname": { "type": ["null", "string"] },
+ "popular": { "type": "boolean" },
+ "html_url": { "type": ["null", "string"] },
+ "source_url": { "type": ["null", "string"] },
+ "description": { "type": ["null", "string"] },
+ "conditions": { "type": "array", "items": { "type": "string" } },
+ "permissions": { "type": "array", "items": { "type": "string" } },
+ "limitations": { "type": "array", "items": { "type": "string" } },
+ "content": { "type": "string" }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/merge_requests.json b/spec/fixtures/api/schemas/public_api/v4/merge_requests.json
index f7adc4e0b91..6df27bf32b9 100644
--- a/spec/fixtures/api/schemas/public_api/v4/merge_requests.json
+++ b/spec/fixtures/api/schemas/public_api/v4/merge_requests.json
@@ -9,6 +9,32 @@
"title": { "type": "string" },
"description": { "type": ["string", "null"] },
"state": { "type": "string" },
+ "merged_by": {
+ "type": ["object", "null"],
+ "properties": {
+ "name": { "type": "string" },
+ "username": { "type": "string" },
+ "id": { "type": "integer" },
+ "state": { "type": "string" },
+ "avatar_url": { "type": "uri" },
+ "web_url": { "type": "uri" }
+ },
+ "additionalProperties": false
+ },
+ "merged_at": { "type": ["date", "null"] },
+ "closed_by": {
+ "type": ["object", "null"],
+ "properties": {
+ "name": { "type": "string" },
+ "username": { "type": "string" },
+ "id": { "type": "integer" },
+ "state": { "type": "string" },
+ "avatar_url": { "type": "uri" },
+ "web_url": { "type": "uri" }
+ },
+ "additionalProperties": false
+ },
+ "closed_at": { "type": ["date", "null"] },
"created_at": { "type": "date" },
"updated_at": { "type": "date" },
"target_branch": { "type": "string" },
diff --git a/spec/fixtures/api/schemas/public_api/v4/template.json b/spec/fixtures/api/schemas/public_api/v4/template.json
new file mode 100644
index 00000000000..38601aa6b45
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/template.json
@@ -0,0 +1,12 @@
+{
+ "type": "object",
+ "required": [
+ "name",
+ "content"
+ ],
+ "properties": {
+ "name": { "type": "string" },
+ "content": { "type": "string" }
+ },
+ "additionalProperties": false
+}
diff --git a/spec/fixtures/api/schemas/public_api/v4/template_list.json b/spec/fixtures/api/schemas/public_api/v4/template_list.json
new file mode 100644
index 00000000000..2336dafb17b
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/template_list.json
@@ -0,0 +1,15 @@
+{
+ "type": "array",
+ "items": {
+ "type": "object",
+ "required": [
+ "key",
+ "name"
+ ],
+ "properties": {
+ "key": { "type": "string" },
+ "name": { "type": "string" }
+ },
+ "additionalProperties": false
+ }
+}
diff --git a/spec/fixtures/authentication/saml2_response.xml b/spec/fixtures/authentication/saml2_response.xml
new file mode 100644
index 00000000000..67dea7209e9
--- /dev/null
+++ b/spec/fixtures/authentication/saml2_response.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xs="http://www.w3.org/2001/XMLSchema" Destination="https://example.hello.com/access/saml" ID="jVFQbyEpSfUwqhZtJtarIaGoshwuAQMDwLoiMhzJXsv" InResponseTo="cfeooghajnhofcmogakmlhpkohnmikicnfhdnjlc" IssueInstant="2011-06-21T13:54:38.661Z" Version="2.0">
+ <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://idm.orademo.com</saml2:Issuer>
+ <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+ <ds:SignedInfo>
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
+ <ds:Reference URI="#jVFQbyEpSfUwqhZtJtarIaGoshwuAQMDwLoiMhzJXsv">
+ <ds:Transforms>
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
+ <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xs"/>
+ </ds:Transform>
+ </ds:Transforms>
+ <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
+ <ds:DigestValue>uHuSry39P16Yh7srS32xESmj4Lw=</ds:DigestValue>
+ </ds:Reference>
+ </ds:SignedInfo>
+ <ds:SignatureValue>fdghdfggfd=</ds:SignatureValue>
+ <ds:KeyInfo>
+ <ds:X509Data>
+ <ds:X509Certificate>dfghjkl</ds:X509Certificate>
+ </ds:X509Data>
+ </ds:KeyInfo>
+ </ds:Signature>
+ <saml2p:Status>
+ <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
+ </saml2p:Status>
+ <saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="emmCjammnYdAbMWDuMAJeZvQIMBayeeYqqwvQoDclKE" IssueInstant="2011-06-21T13:54:38.676Z" Version="2.0">
+ <saml2:Issuer>https://idm.orademo.com</saml2:Issuer>
+ <saml2:Subject>
+ <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" NameQualifier="idp.example.org">someone@example.org</saml2:NameID>
+ <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
+ <saml2:SubjectConfirmationData InResponseTo="cfeooghajnhofcmogakmlhpkohnmikicnfhdnjlc" NotOnOrAfter="2011-06-21T14:09:38.676Z" Recipient="https://example.hello.com/access/saml"/>
+ </saml2:SubjectConfirmation>
+ </saml2:Subject>
+ <saml2:Conditions NotBefore="2011-06-21T13:54:38.683Z" NotOnOrAfter="2011-06-21T14:09:38.683Z">
+ <saml2:AudienceRestriction>
+ <saml2:Audience>hello.com</saml2:Audience>
+ </saml2:AudienceRestriction>
+ </saml2:Conditions>
+ <saml2:AuthnStatement AuthnInstant="2011-06-21T13:54:38.685Z" SessionIndex="perdkjfskdjfksdiertusfsdfsddeurtherukjdfgkdffg">
+ <saml2:AuthnContext>
+ <saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml2:AuthnContextClassRef>
+ </saml2:AuthnContext>
+ </saml2:AuthnStatement>
+ <saml2:AttributeStatement>
+ <saml2:Attribute Name="FirstName">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Someone</saml2:AttributeValue>
+ </saml2:Attribute>
+ <saml2:Attribute Name="LastName">
+ <saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">Special</saml2:AttributeValue>
+ </saml2:Attribute>
+ </saml2:AttributeStatement>
+ </saml2:Assertion>
+</saml2p:Response>
diff --git a/spec/fixtures/codequality/codequality.json b/spec/fixtures/codequality/codequality.json
new file mode 100644
index 00000000000..89cc4b46521
--- /dev/null
+++ b/spec/fixtures/codequality/codequality.json
@@ -0,0 +1 @@
+[{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `simulateDrag` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a995a617b0ce0599b6d0a5649a308a8e","location":{"path":"app/assets/javascripts/test_utils/simulate_drag.js","lines":{"begin":75,"end":137}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `simulateEvent` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"e50b54fce33185efbb17d1c0d210b439","location":{"path":"app/assets/javascripts/test_utils/simulate_drag.js","lines":{"begin":1,"end":37}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `simulateDrag` has 51 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"75ffb8892dac22a9d50822bc69339ab2","location":{"path":"app/assets/javascripts/test_utils/simulate_drag.js","lines":{"begin":75,"end":137}},"other_locations":[],"remediation_points":1224000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"40f188d222bd1f110e8c11f08ec77c3f","location":{"path":"app/assets/javascripts/blob/3d_viewer/index.js","lines":{"begin":10,"end":47}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 60 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"95b71f07d08eb9e2368568c6d872f677","location":{"path":"app/assets/javascripts/blob/blob_file_dropzone.js","lines":{"begin":21,"end":88}},"other_locations":[],"remediation_points":1440000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"`FileTemplateMediator` has 29 functions (exceeds 20 allowed). Consider refactoring.","fingerprint":"02a64abfacf06440f6504888503fe571","location":{"path":"app/assets/javascripts/blob/file_template_mediator.js","lines":{"begin":11,"end":246}},"other_locations":[],"remediation_points":2100000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 34 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"ede6d8c5878fbfdda2348d1c6a808f4b","location":{"path":"app/assets/javascripts/issuable_form.js","lines":{"begin":14,"end":57}},"other_locations":[],"remediation_points":816000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `initTargetBranchDropdown` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"748b8a39304544f015c0abcbee9b929c","location":{"path":"app/assets/javascripts/issuable_form.js","lines":{"begin":116,"end":147}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `start` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b0272210e1d618fe95522ee47f652308","location":{"path":"app/assets/javascripts/smart_interval.js","lines":{"begin":44,"end":65}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `render` has 38 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"ceb92ce0f43dbe13431f1f07d5787aff","location":{"path":"app/assets/javascripts/vue_shared/components/tabs/tabs.js","lines":{"begin":35,"end":75}},"other_locations":[],"remediation_points":912000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `file_icon_map.js` has 587 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"33d443c482c7a34a3a721ef8677a9b9b","location":{"path":"app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js","lines":{"begin":1,"end":590}},"other_locations":[],"remediation_points":6052800,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `gl_dropdown.js` has 935 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"144655d5e2aa528a6e4d63861c3bc2f1","location":{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":1,"end":1111}},"other_locations":[],"remediation_points":11064000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `GitLabDropdownInput` has 41 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"4679297a043d89d437946bd083443d13","location":{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":14,"end":58}},"other_locations":[],"remediation_points":984000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `GitLabDropdownFilter` has 55 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"0c2b6bfd5d744ae2f9724aae0a60a765","location":{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":76,"end":136}},"other_locations":[],"remediation_points":1320000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `filter` has 53 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"3be214723bb15219db661db421dccba1","location":{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":142,"end":213}},"other_locations":[],"remediation_points":1272000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `GitLabDropdown` has 172 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"45e3d28c25ef43db19fcd1f8bf7a52dc","location":{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":296,"end":481}},"other_locations":[],"remediation_points":4128000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `parseData` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"5a6929b08a7efc020e932267316a1ce4","location":{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":505,"end":538}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `opened` has 36 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"b32257d5ff71fd022c46be4ff3f196b6","location":{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":580,"end":627}},"other_locations":[],"remediation_points":864000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `renderItem` has 77 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"119c9b263aba3cc2173646b63b83d58d","location":{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":698,"end":793}},"other_locations":[],"remediation_points":1848000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `rowClicked` has 75 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"e37288d65d5701c4b7d06560d3eb6910","location":{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":820,"end":904}},"other_locations":[],"remediation_points":1800000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `addArrowKeyEvent` has 39 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"4ccf81453af86fd4e7f521423adbf28e","location":{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":971,"end":1015}},"other_locations":[],"remediation_points":936000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `highlightRowAtIndex` has 36 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"a0b5b8a75d9f5726f8a559a3068bbfd9","location":{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":1026,"end":1073}},"other_locations":[],"remediation_points":864000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"nested_control_flow","content":{"body":""},"description":"Avoid deeply nested control flow statements.","location":{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":174,"end":184}},"other_locations":[],"remediation_points":450000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"603368a717652923897a9efd4f494784"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `onOptionClick` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a1ead8da9cc948075715df57538a53fb","location":{"path":"app/assets/javascripts/groups/groups_filterable_list.js","lines":{"begin":76,"end":122}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `onOptionClick` has 32 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"aa9f5f9cb36f5307a7db44c29b5f3a4c","location":{"path":"app/assets/javascripts/groups/groups_filterable_list.js","lines":{"begin":76,"end":122}},"other_locations":[],"remediation_points":768000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `setSearchedGroups` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4116f1bf48693b8dbc3a19233c167489","location":{"path":"app/assets/javascripts/groups/store/groups_store.js","lines":{"begin":19,"end":33}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `formatGroupItem` has 31 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"97209b6e238a05d220f90d1e1fcf7c78","location":{"path":"app/assets/javascripts/groups/store/groups_store.js","lines":{"begin":63,"end":96}},"other_locations":[],"remediation_points":744000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `getGroups` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4f9fc97d0941125a5eb91818b85ac955","location":{"path":"app/assets/javascripts/groups/service/groups_service.js","lines":{"begin":9,"end":34}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 47 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"1cc8f54fcedff8d025db690e89c4d3bc","location":{"path":"app/assets/javascripts/clusters/clusters_bundle.js","lines":{"begin":24,"end":78}},"other_locations":[],"remediation_points":1128000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 45 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"d34e04056341d2986626e42b9927e829","location":{"path":"app/assets/javascripts/clusters/stores/clusters_store.js","lines":{"begin":5,"end":51}},"other_locations":[],"remediation_points":1080000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `initLayoutNav` has 30 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"858063cf6c5a28edd5390360940941f1","location":{"path":"app/assets/javascripts/layout_nav.js","lines":{"begin":12,"end":52}},"other_locations":[],"remediation_points":720000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `sidebarToggleClicked` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e95063093263d654532b1bda2499ae09","location":{"path":"app/assets/javascripts/right_sidebar.js","lines":{"begin":44,"end":69}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `toggleSidebar` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b4667aa48f617e84611c658bd9e6fd42","location":{"path":"app/assets/javascripts/right_sidebar.js","lines":{"begin":201,"end":218}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `message` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f561803cb2a47ffaeed70a1f967105da","location":{"path":"app/assets/javascripts/u2f/error.js","lines":{"begin":9,"end":21}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Function `issueTemplate` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"36dc94ada0224320b48f9dcddf971dd3","location":{"path":"app/assets/javascripts/api.js","lines":{"begin":223,"end":223}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"`Api` has 24 functions (exceeds 20 allowed). Consider refactoring.","fingerprint":"62c9c1d73c6c2f6f294b2c13a5c92e49","location":{"path":"app/assets/javascripts/api.js","lines":{"begin":5,"end":282}},"other_locations":[],"remediation_points":1600000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `validate` has 39 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"8b07c343f7afe957592fac79043c9586","location":{"path":"app/assets/javascripts/new_branch_form.js","lines":{"begin":53,"end":94}},"other_locations":[],"remediation_points":936000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `labels_select.js` has 444 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"34830d2a928eacedb749d5c66c3637e9","location":{"path":"app/assets/javascripts/labels_select.js","lines":{"begin":1,"end":517}},"other_locations":[],"remediation_points":3993600,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `setDropdownData` has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring.","fingerprint":"99aee27c164d2c53ee3386f64239ebc9","location":{"path":"app/assets/javascripts/labels_select.js","lines":{"begin":466,"end":507}},"other_locations":[],"remediation_points":1050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 369 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"ca542a5aefb3dbadb5e0a0100a94b863","location":{"path":"app/assets/javascripts/labels_select.js","lines":{"begin":16,"end":429}},"other_locations":[],"remediation_points":8856000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `data` has 41 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"00d06b2fdc398a9031e900f76184076f","location":{"path":"app/assets/javascripts/labels_select.js","lines":{"begin":133,"end":176}},"other_locations":[],"remediation_points":984000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `renderRow` has 50 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"ef4d877e54496d7ad4da0e0a0b96d9aa","location":{"path":"app/assets/javascripts/labels_select.js","lines":{"begin":177,"end":235}},"other_locations":[],"remediation_points":1200000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `toggleLabel` has 31 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"35ba5b5dab8a50aa713a5ba60e1db7a1","location":{"path":"app/assets/javascripts/labels_select.js","lines":{"begin":242,"end":278}},"other_locations":[],"remediation_points":744000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `hidden` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"2dc1a005647c9e7e9f81e0eabeb9563d","location":{"path":"app/assets/javascripts/labels_select.js","lines":{"begin":294,"end":324}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `clicked` has 75 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"f7fb23f1a88e5dc4c8430529946de3dc","location":{"path":"app/assets/javascripts/labels_select.js","lines":{"begin":327,"end":414}},"other_locations":[],"remediation_points":1800000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `setDropdownData` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"955ed39a38f4f36c3ae0d23199b6b90d","location":{"path":"app/assets/javascripts/labels_select.js","lines":{"begin":466,"end":507}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"nested_control_flow","content":{"body":""},"description":"Avoid deeply nested control flow statements.","location":{"path":"app/assets/javascripts/labels_select.js","lines":{"begin":407,"end":412}},"other_locations":[],"remediation_points":450000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"cefdca8d12fc08aff6e7a861750e99d9"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/labels_select.js","lines":{"begin":377,"end":377}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"1d311ac9ae722bf786749b2125e5cf47"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/labels_select.js","lines":{"begin":411,"end":411}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"7d42a3bbce082d2bbdc96d5eaa747454"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `storeEnvironments` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"70cce4c4dfcfa9c7fb820fc6dea68e9c","location":{"path":"app/assets/javascripts/environments/stores/environments_store.js","lines":{"begin":36,"end":71}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `storeEnvironments` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"f5b13b9d301832978862f37bcc22708f","location":{"path":"app/assets/javascripts/environments/stores/environments_store.js","lines":{"begin":36,"end":71}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `created` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"139fddb1aa522eb2c141871eab765fc3","location":{"path":"app/assets/javascripts/environments/mixins/environments_mixin.js","lines":{"begin":142,"end":175}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 37 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"b4d0a598693b87337ee6b071a35c6da2","location":{"path":"app/assets/javascripts/issuable_context.js","lines":{"begin":7,"end":51}},"other_locations":[],"remediation_points":888000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `dropzoneInput` has 210 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"96984c8a7930ad755604f49c3edf6a2b","location":{"path":"app/assets/javascripts/dropzone_input.js","lines":{"begin":23,"end":290}},"other_locations":[],"remediation_points":5040000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"1ec26d8ddc2c55de770d1f8038f590f4","location":{"path":"app/assets/javascripts/zen_mode.js","lines":{"begin":39,"end":67}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `types.ADD_NEW_NOTE` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"026945d2d3de0e3f478ec55a7bb820f5","location":{"path":"app/assets/javascripts/notes/stores/mutations.js","lines":{"begin":7,"end":31}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `types.REMOVE_PLACEHOLDER_NOTES` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"26efdceb93879d8478e3c8a4f549bc22","location":{"path":"app/assets/javascripts/notes/stores/mutations.js","lines":{"begin":66,"end":85}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"`` has 22 functions (exceeds 20 allowed). Consider refactoring.","fingerprint":"75cd5c2d207814d4a7c7fbf69c709fd6","location":{"path":"app/assets/javascripts/notes/stores/mutations.js","lines":{"begin":6,"end":224}},"other_locations":[],"remediation_points":1400000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `actions.js` has 271 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"9e2580af22da5d9875ac924fda6d0551","location":{"path":"app/assets/javascripts/notes/stores/actions.js","lines":{"begin":1,"end":337}},"other_locations":[],"remediation_points":1502400,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `saveNote` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9dbdac686defafb20b3397ccb7105ba3","location":{"path":"app/assets/javascripts/notes/stores/actions.js","lines":{"begin":151,"end":226}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `getQuickActionText` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3019b0611c6febc7b696f0615d561d1b","location":{"path":"app/assets/javascripts/notes/stores/utils.js","lines":{"begin":7,"end":26}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `collapseSystemNotes` has 33 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"757d82e7c89224872a7bd7b269ed55c5","location":{"path":"app/assets/javascripts/notes/stores/collapse_utils.js","lines":{"begin":57,"end":105}},"other_locations":[],"remediation_points":792000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `unresolvedDiscussionsIdsByDiff` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"250bf3d3615586b7cdaecad2c187e0a0","location":{"path":"app/assets/javascripts/notes/stores/getters.js","lines":{"begin":117,"end":139}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `jumpToDiscussion` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ebbd3b5d75f27f2372eb1a56ca4d9206","location":{"path":"app/assets/javascripts/notes/mixins/discussion_navigation.js","lines":{"begin":5,"end":27}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `keydown` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1977a74c9fba9606480c93a63cb0d5c0","location":{"path":"app/assets/javascripts/droplab/plugins/filter.js","lines":{"begin":4,"end":47}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `keydown` has 33 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"6356352d7ef34cfddc4738ed0c5ebdbf","location":{"path":"app/assets/javascripts/droplab/plugins/filter.js","lines":{"begin":4,"end":47}},"other_locations":[],"remediation_points":792000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `trigger` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3ad4384530fc0032f4fafe9d12e7dc70","location":{"path":"app/assets/javascripts/droplab/plugins/ajax_filter.js","lines":{"begin":35,"end":71}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `_loadData` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"357b7070736cef3f382a2c3439a40d89","location":{"path":"app/assets/javascripts/droplab/plugins/ajax_filter.js","lines":{"begin":73,"end":92}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `trigger` has 35 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"bc97a87fa8ec1b132731256b23616434","location":{"path":"app/assets/javascripts/droplab/plugins/ajax_filter.js","lines":{"begin":35,"end":71}},"other_locations":[],"remediation_points":840000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `Keyboard` has a Cognitive Complexity of 49 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6b1d8f0930c09b5318307d0788ffca30","location":{"path":"app/assets/javascripts/droplab/keyboard.js","lines":{"begin":5,"end":111}},"other_locations":[],"remediation_points":4550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `Keyboard` has 96 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"a812687f4ed1c53045b473f0d6aa5cb9","location":{"path":"app/assets/javascripts/droplab/keyboard.js","lines":{"begin":5,"end":111}},"other_locations":[],"remediation_points":2304000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `keydown` has 35 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"e7cbff360ff21f798bf424a899291302","location":{"path":"app/assets/javascripts/droplab/keyboard.js","lines":{"begin":70,"end":107}},"other_locations":[],"remediation_points":840000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `highlightHash` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2bd33253a3ff30d380e94d478d49a6e7","location":{"path":"app/assets/javascripts/line_highlighter.js","lines":{"begin":59,"end":82}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `highlightRange` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4258948c78c182b6db020222636c12bb","location":{"path":"app/assets/javascripts/line_highlighter.js","lines":{"begin":144,"end":157}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `checkElementsInView` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"08e5457bd1bcf2aa36f67185fb5ab932","location":{"path":"app/assets/javascripts/lazy_loader.js","lines":{"begin":53,"end":75}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `loadImage` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1e063810e532be97a06efabd3c56e4db","location":{"path":"app/assets/javascripts/lazy_loader.js","lines":{"begin":76,"end":94}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `constructor` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a3ef386977d1577238533b8b5352a499","location":{"path":"app/assets/javascripts/diff.js","lines":{"begin":14,"end":43}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `handleClickUnfold` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"f82a7cc93be5e64d548469363a77a2fb","location":{"path":"app/assets/javascripts/diff.js","lines":{"begin":45,"end":79}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `initMergeConflicts` has 81 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"dd259a46f5e703e8f722acdac619ad79","location":{"path":"app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js","lines":{"begin":12,"end":100}},"other_locations":[],"remediation_points":1944000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `merge_conflict_store.js` has 357 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"131a2e61cbfe7efc49cced2ffab3568b","location":{"path":"app/assets/javascripts/merge_conflicts/merge_conflict_store.js","lines":{"begin":1,"end":436}},"other_locations":[],"remediation_points":2740800,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `setParallelLine` has 30 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"f005034ab86d552698a2211ae91ae99a","location":{"path":"app/assets/javascripts/merge_conflicts/merge_conflict_store.js","lines":{"begin":101,"end":139}},"other_locations":[],"remediation_points":720000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `isReadyToCommit` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"184e70a4c8de2226d5a4b197c147f2e8","location":{"path":"app/assets/javascripts/merge_conflicts/merge_conflict_store.js","lines":{"begin":315,"end":351}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"nested_control_flow","content":{"body":""},"description":"Avoid deeply nested control flow statements.","location":{"path":"app/assets/javascripts/merge_conflicts/merge_conflict_store.js","lines":{"begin":331,"end":333}},"other_locations":[],"remediation_points":450000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"78a238497c0c8acd6ddefbb67176f033"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `init` has 216 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"0c8af9cd2b45c1c2e6e24c4678a9c6fc","location":{"path":"app/assets/javascripts/milestone_select.js","lines":{"begin":23,"end":253}},"other_locations":[],"remediation_points":5184000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `clicked` has 91 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"c5e3838b8db3f11da2f72d9acaf52a17","location":{"path":"app/assets/javascripts/milestone_select.js","lines":{"begin":150,"end":250}},"other_locations":[],"remediation_points":2184000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/milestone_select.js","lines":{"begin":187,"end":187}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"9265cc21e5d1eb1bebd044e85db1bf79"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/milestone_select.js","lines":{"begin":220,"end":248}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"36ba0880a027f4448128be161cf33b26"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Function `createFlash` has 6 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"d8f8d96fc8578fb3f7f7bf875e0668a0","location":{"path":"app/assets/javascripts/flash.js","lines":{"begin":64,"end":69}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `textBuilder` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"877ac84192b385c963c08bb4ef960d3b","location":{"path":"app/assets/javascripts/reports/store/utils.js","lines":{"begin":10,"end":37}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 36 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"e2f702de12038884b25d0ef63861bd2b","location":{"path":"app/assets/javascripts/ref_select_dropdown.js","lines":{"begin":4,"end":46}},"other_locations":[],"remediation_points":864000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `setConfig` has 35 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"33b2d4c912bf8eb7a3c4b9c2d3302729","location":{"path":"app/assets/javascripts/close_reopen_report_toggle.js","lines":{"begin":57,"end":94}},"other_locations":[],"remediation_points":840000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `notes.js` has 1338 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"515dff155804bebfe20a78b3935600eb","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":1,"end":1859}},"other_locations":[],"remediation_points":16867200,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `keydownNoteText` has a Cognitive Complexity of 24 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4a28bd8f572a9cb26ff49edf77e2d3a3","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":226,"end":278}},"other_locations":[],"remediation_points":2050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `renderNote` has a Cognitive Complexity of 19 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bc0dc1a78ad18f837b6cead5d11a5ac2","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":403,"end":462}},"other_locations":[],"remediation_points":1550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `renderDiscussionNote` has a Cognitive Complexity of 17 (exceeds 5 allowed). Consider refactoring.","fingerprint":"dbb0fd84250020e115dbb0554f3dfc2a","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":471,"end":538}},"other_locations":[],"remediation_points":1350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `toggleDiffNote` has a Cognitive Complexity of 17 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ddb3cba4008791217e07933b09a14951","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":1054,"end":1124}},"other_locations":[],"remediation_points":1350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `updateTargetButtons` has a Cognitive Complexity of 22 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4ea9fe607edc9cf98ef50a17584952c2","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":1196,"end":1241}},"other_locations":[],"remediation_points":1850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `postComment` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"cc8dd67d9f1598e83dc132f50b7f0726","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":1604,"end":1796}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"`Notes` has 74 functions (exceeds 20 allowed). Consider refactoring.","fingerprint":"5363864915c583936ec6c63c5ed96689","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":48,"end":1856}},"other_locations":[],"remediation_points":6600000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 54 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"25812d53d4eb0f340c33a5a5ddca467a","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":59,"end":121}},"other_locations":[],"remediation_points":1296000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `addBinding` has 33 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"9b40ee2b94454885b3fd51a8bc139c1c","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":127,"end":180}},"other_locations":[],"remediation_points":792000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `keydownNoteText` has 48 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"85df701d158d32b25dca1c2039b6a3be","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":226,"end":278}},"other_locations":[],"remediation_points":1152000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `renderNote` has 50 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"8dfb4b9b4d144d82422186651b46b3e4","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":403,"end":462}},"other_locations":[],"remediation_points":1200000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `renderDiscussionNote` has 53 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"52b66ad02e73c9b1c8848bd1affad7fc","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":471,"end":538}},"other_locations":[],"remediation_points":1272000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `removeNote` has 45 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"8c1e3976ef9bdf79365857e0b8bcb5d8","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":848,"end":911}},"other_locations":[],"remediation_points":1080000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `setupDiscussionNoteForm` has 35 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"d1b7947a88bd1e4b3519e282320fbb38","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":956,"end":1009}},"other_locations":[],"remediation_points":840000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `toggleDiffNote` has 61 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"60ae737d4dc10fe0af6e670d2d4bc7e2","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":1054,"end":1124}},"other_locations":[],"remediation_points":1464000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `updateTargetButtons` has 43 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"8ccd0067a20bb8afcaf3317b434b1ece","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":1196,"end":1241}},"other_locations":[],"remediation_points":1032000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `createPlaceholderNote` has 30 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"ddcd3bc4735c7d763b0fe5da55217278","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":1526,"end":1566}},"other_locations":[],"remediation_points":720000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `postComment` has 143 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"fcdd1766ceaaa90c770bddfe75d120cd","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":1604,"end":1796}},"other_locations":[],"remediation_points":3432000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `updateComment` has 30 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"7c508bf1571f9f4d795de4cb8ef1930a","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":1811,"end":1855}},"other_locations":[],"remediation_points":720000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":264,"end":264}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"cd548cc7c1ebbb2263b1d2ecdb94a5dd"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":272,"end":272}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"cd548cc7c1ebbb2263b1d2ecdb94a5dd"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":275,"end":275}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"25fb735695be215146eaf2300412aae0"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `itemClicked` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.","fingerprint":"86a06125a02d35c7e121952daf7f0f08","location":{"path":"app/assets/javascripts/filtered_search/dropdown_hint.js","lines":{"begin":23,"end":60}},"other_locations":[],"remediation_points":850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `itemClicked` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"e7751795d821a7afa57ab25dbd658ee4","location":{"path":"app/assets/javascripts/filtered_search/dropdown_hint.js","lines":{"begin":23,"end":60}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `filterHint` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"22102abbd93e4d53a0798ecf7e058512","location":{"path":"app/assets/javascripts/filtered_search/dropdown_utils.js","lines":{"begin":117,"end":140}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `getSearchQuery` has 40 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"26e123d9f4a95bfa34a59f42db0ae260","location":{"path":"app/assets/javascripts/filtered_search/dropdown_utils.js","lines":{"begin":164,"end":213}},"other_locations":[],"remediation_points":960000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `processTokens` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"28cb3a1b7fa1a51cd968e9016415efea","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_tokenizer.js","lines":{"begin":4,"end":51}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `processTokens` has 36 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"287e8c4963cc8869358280d31e4d4005","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_tokenizer.js","lines":{"begin":4,"end":51}},"other_locations":[],"remediation_points":864000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `loadDropdown` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"31af8cc264fa78512d238c04106208fe","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js","lines":{"begin":202,"end":219}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `setDropdown` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6dda613591636a58b06a298d0980498f","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js","lines":{"begin":221,"end":243}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `setupMapping` has 55 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"f12b787fff78b0b8986506eb90b1997c","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js","lines":{"begin":50,"end":108}},"other_locations":[],"remediation_points":1320000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `load` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"90c65f9cea258055f67defcb61f63abb","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js","lines":{"begin":165,"end":200}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `filtered_search_manager.js` has 514 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"45105bf38088a343a5a9c0e1ca76840e","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":1,"end":645}},"other_locations":[],"remediation_points":5001600,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `setup` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8c08d2326cb1eb811c4329b3ee92fc04","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":58,"end":106}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `checkForEnter` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2056e10cb965de92a331a6181618ff7f","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":236,"end":265}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `handleInputVisualToken` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3ef6573dc182d159eb13ddd70be42653","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":398,"end":438}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"`FilteredSearchManager` has 32 functions (exceeds 20 allowed). Consider refactoring.","fingerprint":"dee04c9127382346c9edead8ceb49788","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":20,"end":644}},"other_locations":[],"remediation_points":2400000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `setup` has 38 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"fc525f4373639fe1e5e079259d587918","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":58,"end":106}},"other_locations":[],"remediation_points":912000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `bindEvents` has 34 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"0036874f7fdfa7b481bccec4adce2fd9","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":145,"end":182}},"other_locations":[],"remediation_points":816000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `handleInputVisualToken` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"105fd464c05f365ea496107488c4d048","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":398,"end":438}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `loadSearchParamsFromURL` has 63 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"dc0a70cc2480e01d46d52df00f42980b","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":463,"end":543}},"other_locations":[],"remediation_points":1512000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `search` has 36 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"8d31d46c10a7c7b27cba3e79c2c7e684","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":558,"end":607}},"other_locations":[],"remediation_points":864000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"nested_control_flow","content":{"body":""},"description":"Avoid deeply nested control flow statements.","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":524,"end":529}},"other_locations":[],"remediation_points":450000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"b4fcaa9a90b83251c167ce6bd363ead0"},{"categories":["Complexity"],"check_name":"nested_control_flow","content":{"body":""},"description":"Avoid deeply nested control flow statements.","location":{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":530,"end":533}},"other_locations":[],"remediation_points":450000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"b9acc2eaf5ae1dd8b6f24ac70e97ace6"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `users_select.js` has 594 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"9e6ca5bcc402f0dae9a9869dd46e4e77","location":{"path":"app/assets/javascripts/users_select.js","lines":{"begin":1,"end":701}},"other_locations":[],"remediation_points":6153600,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `UsersSelect` has 524 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"b4438d98e020e34865089e812790a72e","location":{"path":"app/assets/javascripts/users_select.js","lines":{"begin":14,"end":628}},"other_locations":[],"remediation_points":12576000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `processData` has 88 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"9e7c9e224218cce1f434b0a0ff4616c4","location":{"path":"app/assets/javascripts/users_select.js","lines":{"begin":221,"end":327}},"other_locations":[],"remediation_points":2112000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `clicked` has 64 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"19cb3539002fa7a4aa2abf730fc550bc","location":{"path":"app/assets/javascripts/users_select.js","lines":{"begin":381,"end":468}},"other_locations":[],"remediation_points":1536000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `renderRow` has 31 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"b67cb57917ef04a8b05e4be075bf6c0b","location":{"path":"app/assets/javascripts/users_select.js","lines":{"begin":493,"end":531}},"other_locations":[],"remediation_points":744000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `query` has 48 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"447defa81cda25e0ae3f708d8cb7f927","location":{"path":"app/assets/javascripts/users_select.js","lines":{"begin":553,"end":604}},"other_locations":[],"remediation_points":1152000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `toggleCollapsed` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"01ddc746dbdfa4103552d4d09bda67bd","location":{"path":"app/assets/javascripts/image_diff/helpers/dom_helper.js","lines":{"begin":27,"end":45}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `addBadge` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"5cb8fbd4ee1e42eb778a29cd02efc8f5","location":{"path":"app/assets/javascripts/image_diff/image_diff.js","lines":{"begin":84,"end":116}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 45 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"1579b1a9e97ea98e6348df70287ccd85","location":{"path":"app/assets/javascripts/job.js","lines":{"begin":13,"end":70}},"other_locations":[],"remediation_points":1080000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `getBuildTrace` has 55 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"0990625843278c1e0d27866b6e51ec9b","location":{"path":"app/assets/javascripts/job.js","lines":{"begin":96,"end":163}},"other_locations":[],"remediation_points":1320000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `setVisibilityOptions` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"bd793c0b96469cb6904241d8beea60c0","location":{"path":"app/assets/javascripts/project_visibility.js","lines":{"begin":3,"end":35}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `restore` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ebd9e5c02ce67b5fecb0e9a610fa01a3","location":{"path":"app/assets/javascripts/autosave.js","lines":{"begin":19,"end":37}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `populateActiveMetrics` has 33 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"0808d7392776f800f01eb00247cb49fc","location":{"path":"app/assets/javascripts/prometheus_metrics/prometheus_metrics.js","lines":{"begin":63,"end":100}},"other_locations":[],"remediation_points":792000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `loadActiveMetrics` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"d2f56d70d330df4e004e4e730ec9bd7d","location":{"path":"app/assets/javascripts/prometheus_metrics/prometheus_metrics.js","lines":{"begin":102,"end":130}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `adminInit` has 37 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"cb6b998e81923ba316eb986d14f16ef7","location":{"path":"app/assets/javascripts/pages/admin/admin.js","lines":{"begin":14,"end":60}},"other_locations":[],"remediation_points":888000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `renderState` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d23e829e807e7cfa7fa60a5bd8bd2a4f","location":{"path":"app/assets/javascripts/pages/sessions/new/username_validator.js","lines":{"begin":49,"end":72}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/pages/sessions/new/username_validator.js","lines":{"begin":70,"end":70}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"59ee4d34d9113510c329a2b264aae308"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `showTab` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2db6bb70760f9a2493d374e830395ef3","location":{"path":"app/assets/javascripts/pages/sessions/new/signin_tabs_memoizer.js","lines":{"begin":34,"end":47}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 52 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"364739acddb57495be3b94860555f2ae","location":{"path":"app/assets/javascripts/pages/projects/project.js","lines":{"begin":13,"end":72}},"other_locations":[],"remediation_points":1248000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `initRefSwitcher` has 63 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"e62a2b92cc28ef2e2c5cc5e391c1b3c1","location":{"path":"app/assets/javascripts/pages/projects/project.js","lines":{"begin":83,"end":155}},"other_locations":[],"remediation_points":1512000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `initLabelIndex` has 72 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"d6cbf4de48d122212aa6790bce385c52","location":{"path":"app/assets/javascripts/pages/projects/labels/index/index.js","lines":{"begin":9,"end":91}},"other_locations":[],"remediation_points":1728000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `stat_graph_contributors_graph.js` has 260 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"d70980224b971643c65164d7599d8306","location":{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":1,"end":315}},"other_locations":[],"remediation_points":1344000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `ContributorsGraph` has 68 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"c5ffd1e9b7f7eb20d76540029db76ea5","location":{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":19,"end":107}},"other_locations":[],"remediation_points":1632000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `ContributorsMasterGraph` has 98 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"c90cea5a64860bd8ebc11adfe43f966f","location":{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":109,"end":225}},"other_locations":[],"remediation_points":2352000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `ContributorsAuthorGraph` has 75 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"cb2ba67ac3c7b0319408d414f7ab4a89","location":{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":227,"end":314}},"other_locations":[],"remediation_points":1800000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `parse_log` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"54a68f13ca92482f197897caa4dde8c6","location":{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js","lines":{"begin":5,"end":31}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `renderSidebar` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7a8652d503fb546ee9566f5bf3f473ac","location":{"path":"app/assets/javascripts/pages/projects/wikis/wikis.js","lines":{"begin":54,"end":66}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `activity_calendar.js` has 257 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"c8cf6370baf6d39528465c33a636bdaa","location":{"path":"app/assets/javascripts/pages/users/activity_calendar.js","lines":{"begin":1,"end":300}},"other_locations":[],"remediation_points":1300800,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `constructor` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"12e8c60549aefe50a5602474054d85e9","location":{"path":"app/assets/javascripts/pages/users/activity_calendar.js","lines":{"begin":46,"end":115}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 49 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"70826affaa552c98140c396bd20b2321","location":{"path":"app/assets/javascripts/pages/users/activity_calendar.js","lines":{"begin":46,"end":115}},"other_locations":[],"remediation_points":1176000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `renderDays` has 37 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"b25511a5a67d72f5494bf518b57f8945","location":{"path":"app/assets/javascripts/pages/users/activity_calendar.js","lines":{"begin":144,"end":182}},"other_locations":[],"remediation_points":888000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `renderKey` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"f239dc6410f68cc561519c650b54fe79","location":{"path":"app/assets/javascripts/pages/users/activity_calendar.js","lines":{"begin":226,"end":257}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 65 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"910e3f36c66a265e42a8eaf26a167c4b","location":{"path":"app/assets/javascripts/pages/search/show/search.js","lines":{"begin":6,"end":77}},"other_locations":[],"remediation_points":1560000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `showPreview` has 30 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"1721f777313e23b7b202fa7491480968","location":{"path":"app/assets/javascripts/behaviors/preview_markdown.js","lines":{"begin":29,"end":64}},"other_locations":[],"remediation_points":720000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `copy_as_gfm.js` has 400 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"ac03b65c923edc62a2698fa8d47bed20","location":{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":1,"end":510}},"other_locations":[],"remediation_points":3360000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `transformCodeSelection` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c2c7d04215c2bd2989380d4ec16d2fdd","location":{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":392,"end":428}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `nodeToGFM` has a Cognitive Complexity of 20 (exceeds 5 allowed). Consider refactoring.","fingerprint":"203624a0d90ac2910cd61598bd1ba9c4","location":{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":430,"end":473}},"other_locations":[],"remediation_points":1650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"`gfmRules` has 23 functions (exceeds 20 allowed). Consider refactoring.","fingerprint":"4cef7679aa1f25cb0fb0333b4dfea466","location":{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":169,"end":306}},"other_locations":[],"remediation_points":1500000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `transformCodeSelection` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"cc79eaa8e95f40163769d11480f6ca8c","location":{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":392,"end":428}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `nodeToGFM` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"abacf74acfb9ae1429676cb952d5250f","location":{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":430,"end":473}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":472,"end":472}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"4dc32f63393b2dba3bb2b4186a5a9d3c"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `initPageShortcuts` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"7e91b97abbe33722ed743c916435f0ab","location":{"path":"app/assets/javascripts/behaviors/shortcuts.js","lines":{"begin":3,"end":35}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"3992dd4b39964f74489f5037465f0968","location":{"path":"app/assets/javascripts/behaviors/shortcuts/shortcuts.js","lines":{"begin":18,"end":51}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `updateTopState` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4115079d252dabe584b1839baffa5696","location":{"path":"app/assets/javascripts/issue.js","lines":{"begin":46,"end":74}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `bindEvents` has 99 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"d911289330106e823f8b66a27a6de9a8","location":{"path":"app/assets/javascripts/projects/project_new.js","lines":{"begin":38,"end":154}},"other_locations":[],"remediation_points":2376000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `chooseTemplate` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"38d61f9d4b3748a9e5ab863d54f4ccf8","location":{"path":"app/assets/javascripts/projects/project_new.js","lines":{"begin":98,"end":130}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `search_autocomplete.js` has 417 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"92cc9af55c3a4ab73da8e1f0d3edd029","location":{"path":"app/assets/javascripts/search_autocomplete.js","lines":{"begin":1,"end":506}},"other_locations":[],"remediation_points":3604800,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `getData` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"fc8158cb371adf854571129bd363b7ef","location":{"path":"app/assets/javascripts/search_autocomplete.js","lines":{"begin":149,"end":251}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `getCategoryContents` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d8c7fe125446a794240cdecc04543593","location":{"path":"app/assets/javascripts/search_autocomplete.js","lines":{"begin":253,"end":305}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `onSearchInputKeyUp` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4f647cc28b710d6de8a6b35f3f79f3ce","location":{"path":"app/assets/javascripts/search_autocomplete.js","lines":{"begin":348,"end":382}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `onClick` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b118715fdcf7b3e7ac25f69bb1baa423","location":{"path":"app/assets/javascripts/search_autocomplete.js","lines":{"begin":445,"end":458}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"`SearchAutocomplete` has 28 functions (exceeds 20 allowed). Consider refactoring.","fingerprint":"4afabdab2d1c2b911d6a1c563638e8e6","location":{"path":"app/assets/javascripts/search_autocomplete.js","lines":{"begin":71,"end":501}},"other_locations":[],"remediation_points":2000000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `setSearchOptions` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"ba3145218ad79282dc1d42a52ae16802","location":{"path":"app/assets/javascripts/search_autocomplete.js","lines":{"begin":32,"end":69}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"27f6673ed668afd5ac9f3fd3c02a5e40","location":{"path":"app/assets/javascripts/search_autocomplete.js","lines":{"begin":72,"end":103}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `getData` has 86 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"a21aceb13c361e2e3e0299baa560bed5","location":{"path":"app/assets/javascripts/search_autocomplete.js","lines":{"begin":149,"end":251}},"other_locations":[],"remediation_points":2064000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `getCategoryContents` has 45 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"415e6e1a246f7b01199ed828bdebb278","location":{"path":"app/assets/javascripts/search_autocomplete.js","lines":{"begin":253,"end":305}},"other_locations":[],"remediation_points":1080000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `onSearchInputKeyUp` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"438f5589be7d3c9865113320e8a85fc4","location":{"path":"app/assets/javascripts/search_autocomplete.js","lines":{"begin":348,"end":382}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `highlighter` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"034f805c8a510c0c46e35c2e4fb8d329","location":{"path":"app/assets/javascripts/project_find_file.js","lines":{"begin":10,"end":32}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `selectRow` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b2917d9725004429f0a4319beac0822e","location":{"path":"app/assets/javascripts/project_find_file.js","lines":{"begin":123,"end":143}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `constructor` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1b590709d469cb1c8c28f467e53d2154","location":{"path":"app/assets/javascripts/namespace_select.js","lines":{"begin":8,"end":58}},"other_locations":[],"remediation_points":850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 48 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"af0c07eddd69b8e22c3e13c7474122a1","location":{"path":"app/assets/javascripts/namespace_select.js","lines":{"begin":8,"end":58}},"other_locations":[],"remediation_points":1152000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `toggleDiff` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"098b6e689349244e7adddfcad90974a3","location":{"path":"app/assets/javascripts/single_file_diff.js","lines":{"begin":41,"end":62}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `onSaveClicked` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"18922f177ff6315e508e19e5d7a6cd4d","location":{"path":"app/assets/javascripts/ci_variable_list/ajax_variable_list.js","lines":{"begin":53,"end":90}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 34 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"cf8b6d0bf24fc15e2c0e87e1c6b6a636","location":{"path":"app/assets/javascripts/ci_variable_list/ci_variable_list.js","lines":{"begin":19,"end":62}},"other_locations":[],"remediation_points":816000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `jumpToNextUnresolvedDiscussion` has a Cognitive Complexity of 54 (exceeds 5 allowed). Consider refactoring.","fingerprint":"792eaacd2770c50c0a42bce535c7bee9","location":{"path":"app/assets/javascripts/diff_notes/components/jump_to_discussion.js","lines":{"begin":61,"end":208}},"other_locations":[],"remediation_points":5050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `jumpToNextUnresolvedDiscussion` has 102 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"784d361fd1ec4da2fc3be0e85d1e354e","location":{"path":"app/assets/javascripts/diff_notes/components/jump_to_discussion.js","lines":{"begin":61,"end":208}},"other_locations":[],"remediation_points":2448000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `buttonText` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5b0d7c1b1146fa7930c3c14fef72db27","location":{"path":"app/assets/javascripts/diff_notes/components/comment_resolve_btn.js","lines":{"begin":31,"end":45}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `diffNotesCompileComponents` has 30 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"ec443ad0f520ec34248990713c0f0b5a","location":{"path":"app/assets/javascripts/diff_notes/diff_notes_bundle.js","lines":{"begin":30,"end":68}},"other_locations":[],"remediation_points":720000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Function `queryTimeSeries` has 7 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"01a425e5bd2ad64d006f35854f477ad0","location":{"path":"app/assets/javascripts/monitoring/utils/multiple_time_series.js","lines":{"begin":33,"end":33}},"other_locations":[],"remediation_points":525000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `queryTimeSeries` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f1015e96e281a9a77bdaeeba619aa36b","location":{"path":"app/assets/javascripts/monitoring/utils/multiple_time_series.js","lines":{"begin":33,"end":165}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `queryTimeSeries` has 110 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"c99f8cbe0230e2f1d48ff4478f2117c4","location":{"path":"app/assets/javascripts/monitoring/utils/multiple_time_series.js","lines":{"begin":33,"end":165}},"other_locations":[],"remediation_points":2640000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `timeScaleFormat` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f52e997312984f599f152d3260bf8654","location":{"path":"app/assets/javascripts/monitoring/utils/date_time_formatters.js","lines":{"begin":22,"end":42}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"complex_logic","content":{"body":""},"description":"Consider simplifying this complex logical expression.","location":{"path":"app/assets/javascripts/diffs/store/mutations.js","lines":{"begin":95,"end":134}},"other_locations":[],"remediation_points":800000,"severity":"critical","type":"issue","engine_name":"structure","fingerprint":"531fa4647bfb14d1172613e86257dd28"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `types.SET_LINE_DISCUSSIONS_FOR_FILE` has a Cognitive Complexity of 16 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f6d1e6ad89a6aec9b87ec051dfa0099d","location":{"path":"app/assets/javascripts/diffs/store/mutations.js","lines":{"begin":88,"end":135}},"other_locations":[],"remediation_points":1250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `types.REMOVE_LINE_DISCUSSIONS_FOR_FILE` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"967d987657c3659898f377b3d07be15b","location":{"path":"app/assets/javascripts/diffs/store/mutations.js","lines":{"begin":137,"end":165}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `types.SET_LINE_DISCUSSIONS_FOR_FILE` has 43 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"08263cf95339fef038c9b82b56e70844","location":{"path":"app/assets/javascripts/diffs/store/mutations.js","lines":{"begin":88,"end":135}},"other_locations":[],"remediation_points":1032000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `startRenderDiffsQueue` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9d28a6db58513b7ea1157b081952903c","location":{"path":"app/assets/javascripts/diffs/store/actions.js","lines":{"begin":58,"end":83}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `addLineReferences` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.","fingerprint":"782481c579d96128e5d0793c04d6113b","location":{"path":"app/assets/javascripts/diffs/store/utils.js","lines":{"begin":110,"end":145}},"other_locations":[],"remediation_points":850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `prepareDiffData` has a Cognitive Complexity of 20 (exceeds 5 allowed). Consider refactoring.","fingerprint":"69f60a55e02467d84573c99a4caa96e1","location":{"path":"app/assets/javascripts/diffs/store/utils.js","lines":{"begin":191,"end":224}},"other_locations":[],"remediation_points":1650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `getNoteFormData` has 45 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"2408381b663271af2ce36e4cfec0ef64","location":{"path":"app/assets/javascripts/diffs/store/utils.js","lines":{"begin":28,"end":77}},"other_locations":[],"remediation_points":1080000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `addLineReferences` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"9e04f00e197ce4b77a3fa65c55e66cb1","location":{"path":"app/assets/javascripts/diffs/store/utils.js","lines":{"begin":110,"end":145}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `prepareDiffData` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"4fa4b2e2a939b7a261a1e47aea3b124e","location":{"path":"app/assets/javascripts/diffs/store/utils.js","lines":{"begin":191,"end":224}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `shouldRenderParallelCommentRow` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.","fingerprint":"cf200732380b3f0a2a2993c8cb3d3a71","location":{"path":"app/assets/javascripts/diffs/store/getters.js","lines":{"begin":75,"end":97}},"other_locations":[],"remediation_points":850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `initDiffsApp` has 33 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"37689c9906180d81c8f636a1285361fa","location":{"path":"app/assets/javascripts/diffs/index.js","lines":{"begin":6,"end":41}},"other_locations":[],"remediation_points":792000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `create_merge_request_dropdown.js` has 391 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"efe0e6e60956f829c50aea15ff89a81c","location":{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":1,"end":489}},"other_locations":[],"remediation_points":3230400,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `onChangeInput` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"51e3d7e3f8979e2acacf219907cfae33","location":{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":278,"end":322}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `updateInputState` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"15a5141561c69faaf772cc24838b9882","location":{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":433,"end":472}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"`CreateMergeRequestDropdown` has 32 functions (exceeds 20 allowed). Consider refactoring.","fingerprint":"6d33b610bd5704267ec05a9b7b5e44e0","location":{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":15,"end":488}},"other_locations":[],"remediation_points":2400000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 38 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"9408c08016dc994d8ab6445d06b9e1ba","location":{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":16,"end":61}},"other_locations":[],"remediation_points":912000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `onChangeInput` has 33 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"e5627e01c10e2d6e1299f91b38024a0a","location":{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":278,"end":322}},"other_locations":[],"remediation_points":792000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `updateInputState` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"5126386129e905b8737efa7b7aadb02e","location":{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":433,"end":472}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":321,"end":321}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"8643526d248036a3735dc9a6e2e57920"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `addToImport` has 48 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"f5c4a1a17a8903f8c6dd885142d0e5a7","location":{"path":"app/assets/javascripts/importer_status.js","lines":{"begin":33,"end":92}},"other_locations":[],"remediation_points":1152000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `autoUpdate` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"86f5ee9b3a803d7476f4c94f06eeb20f","location":{"path":"app/assets/javascripts/importer_status.js","lines":{"begin":94,"end":123}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `deviseState` has a Cognitive Complexity of 17 (exceeds 5 allowed). Consider refactoring.","fingerprint":"cc96fa07083c1de787a6bff9f39300d8","location":{"path":"app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js","lines":{"begin":3,"end":34}},"other_locations":[],"remediation_points":1350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `deviseState` has 30 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"b9fdc968681b9a4d1a00bdaebcf5513e","location":{"path":"app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js","lines":{"begin":3,"end":34}},"other_locations":[],"remediation_points":720000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js","lines":{"begin":13,"end":13}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"7e01335e6a48fbcffe9b977a5893e0c1"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js","lines":{"begin":15,"end":15}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"06b18956af744e4ba0818ef408ae519a"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js","lines":{"begin":17,"end":17}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"b6db36d200c40a47864a6c82d74ecdd9"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js","lines":{"begin":19,"end":19}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"94cbbf89dae775243077f30c7139777f"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js","lines":{"begin":21,"end":21}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"407c4389388a40459b3a50e566ec4695"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js","lines":{"begin":23,"end":23}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"c9317c489fdab4a76a50dbc5cebcfa17"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js","lines":{"begin":25,"end":25}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"d69b63a794f4784245d6a949c148e1c8"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js","lines":{"begin":27,"end":27}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"766dbcf000fa7d4e2636539267ea8cee"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js","lines":{"begin":29,"end":29}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"9c3dd1c5c99c0b2e367eaf0f6c483688"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js","lines":{"begin":31,"end":31}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"9735ac3532df3e31eea793eb471bcd3e"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js","lines":{"begin":33,"end":33}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"6a3a4a85c8ee79ec2d8e4ea2cf165674"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `setData` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c334ad6c327b60fc52e19d4b1a441be0","location":{"path":"app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js","lines":{"begin":14,"end":114}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `setData` has 88 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"590c6f1bfea578d864bdc64a2fa9a1da","location":{"path":"app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js","lines":{"begin":14,"end":114}},"other_locations":[],"remediation_points":2112000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `groupsSelect` has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6d30e631abef41c7858e8c2b472ab41b","location":{"path":"app/assets/javascripts/groups_select.js","lines":{"begin":6,"end":88}},"other_locations":[],"remediation_points":1050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `groupsSelect` has 74 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"ced5ccd57fcd0e841cc27868cc850186","location":{"path":"app/assets/javascripts/groups_select.js","lines":{"begin":6,"end":88}},"other_locations":[],"remediation_points":1776000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `setAjaxGroupsSelect2` has 71 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"cb6c68e362058d81fc462714f431d13d","location":{"path":"app/assets/javascripts/groups_select.js","lines":{"begin":9,"end":87}},"other_locations":[],"remediation_points":1704000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `setConfig` has 31 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"93dedf1db90bd5e014f609731004784e","location":{"path":"app/assets/javascripts/comment_type_toggle.js","lines":{"begin":25,"end":60}},"other_locations":[],"remediation_points":744000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `memberExpirationDate` has 33 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"93c026069e6f3fae025e1bf3bf480e0b","location":{"path":"app/assets/javascripts/member_expiration_date.js","lines":{"begin":10,"end":54}},"other_locations":[],"remediation_points":792000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `merge_request_tabs.js` has 311 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"91dcee71900ea33c229c8f115d145f57","location":{"path":"app/assets/javascripts/merge_request_tabs.js","lines":{"begin":1,"end":477}},"other_locations":[],"remediation_points":2078400,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `constructor` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2c515fc51ceabbbd6bcacbadf7b409c8","location":{"path":"app/assets/javascripts/merge_request_tabs.js","lines":{"begin":71,"end":122}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `tabShown` has a Cognitive Complexity of 29 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ca9c966746914ecd639f907aed00306a","location":{"path":"app/assets/javascripts/merge_request_tabs.js","lines":{"begin":159,"end":223}},"other_locations":[],"remediation_points":2550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 43 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"5e286159c60ca68824ec344d5dec0145","location":{"path":"app/assets/javascripts/merge_request_tabs.js","lines":{"begin":71,"end":122}},"other_locations":[],"remediation_points":1032000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `tabShown` has 56 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"5752347dcb1fd9940bd4bc3d21abd442","location":{"path":"app/assets/javascripts/merge_request_tabs.js","lines":{"begin":159,"end":223}},"other_locations":[],"remediation_points":1344000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `loadDiff` has 52 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"3eedd69a3c93529e5939b19ecf1b3e32","location":{"path":"app/assets/javascripts/merge_request_tabs.js","lines":{"begin":331,"end":401}},"other_locations":[],"remediation_points":1248000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `toggleLabelPriority` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"17bb8b4767aa6ee7a9db29cd4297dfd1","location":{"path":"app/assets/javascripts/label_manager.js","lines":{"begin":53,"end":94}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `toggleLabelPriority` has 34 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"ac24663bc55eac3c9635bccf3a68dc5a","location":{"path":"app/assets/javascripts/label_manager.js","lines":{"begin":53,"end":94}},"other_locations":[],"remediation_points":816000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 30 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"4cd0496900d30272b32ee2e3adf188ae","location":{"path":"app/assets/javascripts/boards/models/issue.js","lines":{"begin":11,"end":46}},"other_locations":[],"remediation_points":720000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `addIssue` has a Cognitive Complexity of 19 (exceeds 5 allowed). Consider refactoring.","fingerprint":"70f0f8ea0547b7001e920932e4980ddc","location":{"path":"app/assets/javascripts/boards/models/list.js","lines":{"begin":164,"end":200}},"other_locations":[],"remediation_points":1550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `addIssue` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"7f1eced6b6dca9d960756de9b56ac3c4","location":{"path":"app/assets/javascripts/boards/models/list.js","lines":{"begin":164,"end":200}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Function `moveIssueInList` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"3726eea384e1d9e6d6d8eebb989b0a55","location":{"path":"app/assets/javascripts/boards/stores/boards_store.js","lines":{"begin":152,"end":152}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `moveIssueToList` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"cc191b6dd17cde39e7dd162fd47e19c7","location":{"path":"app/assets/javascripts/boards/stores/boards_store.js","lines":{"begin":100,"end":144}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `moveIssueToList` has 38 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"0501fa18f105e7c808db7348aee50cb4","location":{"path":"app/assets/javascripts/boards/stores/boards_store.js","lines":{"begin":100,"end":144}},"other_locations":[],"remediation_points":912000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `newListDropdownInit` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8f897d86e7796b5b3d49f700124b5adb","location":{"path":"app/assets/javascripts/boards/components/new_list_dropdown.js","lines":{"begin":26,"end":82}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `newListDropdownInit` has 51 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"f73b08dfbb16f388d03764aefc71b663","location":{"path":"app/assets/javascripts/boards/components/new_list_dropdown.js","lines":{"begin":26,"end":82}},"other_locations":[],"remediation_points":1224000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `projectSelect` has 74 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"8ccd46aac4a6745374730b2c4f0f1a7f","location":{"path":"app/assets/javascripts/project_select.js","lines":{"begin":7,"end":87}},"other_locations":[],"remediation_points":1776000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `query` has 36 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"8facf3a4b06c65c72b401a6ae241812e","location":{"path":"app/assets/javascripts/project_select.js","lines":{"begin":27,"end":64}},"other_locations":[],"remediation_points":864000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `swipe` has 30 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"cd344682f57e11e94307c0ae71e31b21","location":{"path":"app/assets/javascripts/commit/image_file.js","lines":{"begin":118,"end":153}},"other_locations":[],"remediation_points":720000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `onion-skin` has 34 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"d98db2ac5d0ba5352c5501d8e616908a","location":{"path":"app/assets/javascripts/commit/image_file.js","lines":{"begin":154,"end":193}},"other_locations":[],"remediation_points":816000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `mergeUrlParams` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9586f62e5526e65ea5dea846d2d34814","location":{"path":"app/assets/javascripts/lib/utils/url_utility.js","lines":{"begin":19,"end":41}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `common_utils.js` has 421 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"5b2e1f175792cddc3122cb26f6f2901b","location":{"path":"app/assets/javascripts/lib/utils/common_utils.js","lines":{"begin":1,"end":647}},"other_locations":[],"remediation_points":3662400,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `handleLocationHash` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"73cd83cbd5164515c6be6e51ced09b94","location":{"path":"app/assets/javascripts/lib/utils/common_utils.js","lines":{"begin":79,"end":112}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `urlParamsToObject` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"87d0167946e02e230645b1a8b4416926","location":{"path":"app/assets/javascripts/lib/utils/common_utils.js","lines":{"begin":152,"end":175}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `createOverlayIcon` has 40 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"1195653ae898b98df0d276acb1429b55","location":{"path":"app/assets/javascripts/lib/utils/common_utils.js","lines":{"begin":458,"end":505}},"other_locations":[],"remediation_points":960000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `onload` has 34 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"d3e5a07a00d95bb2f853dee0c1c50e98","location":{"path":"app/assets/javascripts/lib/utils/common_utils.js","lines":{"begin":462,"end":502}},"other_locations":[],"remediation_points":816000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `isSticky` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b5704d88401ccd1910b07573165064f6","location":{"path":"app/assets/javascripts/lib/utils/sticky.js","lines":{"begin":10,"end":31}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Function `insertMarkdownText` has 6 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"1ff368be1929703177fe923eb38be8a2","location":{"path":"app/assets/javascripts/lib/utils/text_markdown.js","lines":{"begin":54,"end":54}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `moveCursor` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"78da0046365fa4a2a913735a7884c4fe","location":{"path":"app/assets/javascripts/lib/utils/text_markdown.js","lines":{"begin":34,"end":52}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `insertMarkdownText` has a Cognitive Complexity of 18 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9c17d7ff9d0dfd043e0ac8b46e612742","location":{"path":"app/assets/javascripts/lib/utils/text_markdown.js","lines":{"begin":54,"end":111}},"other_locations":[],"remediation_points":1450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `insertMarkdownText` has 43 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"f38a0d7dccba49d8195065ab71f8ef39","location":{"path":"app/assets/javascripts/lib/utils/text_markdown.js","lines":{"begin":54,"end":111}},"other_locations":[],"remediation_points":1032000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `toggleScroll` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a1904c8e94b053af5f2371dece57951f","location":{"path":"app/assets/javascripts/lib/utils/logoutput_behaviours.js","lines":{"begin":14,"end":41}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `getMonthNames` has 30 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"5630d70a3018ea651454e11d959c7e26","location":{"path":"app/assets/javascripts/lib/utils/datetime_utility.js","lines":{"begin":16,"end":47}},"other_locations":[],"remediation_points":720000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `getTimeago` has 42 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"915cddbb51190cedb7c5488e6d3f715a","location":{"path":"app/assets/javascripts/lib/utils/datetime_utility.js","lines":{"begin":77,"end":122}},"other_locations":[],"remediation_points":1008000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `dateInWords` has 36 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"35c8c58c18a9af9c0ee997ae5d4b8e48","location":{"path":"app/assets/javascripts/lib/utils/datetime_utility.js","lines":{"begin":201,"end":243}},"other_locations":[],"remediation_points":864000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `initKeyNav` has 37 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"90bcaab65ebc8665cd94e8e6286ad7d3","location":{"path":"app/assets/javascripts/tree.js","lines":{"begin":28,"end":66}},"other_locations":[],"remediation_points":888000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `generateUnicodeSupportMap` has 47 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"3235c3b88f6c553ff280eac9faec19fa","location":{"path":"app/assets/javascripts/emoji/support/unicode_support_map.js","lines":{"begin":77,"end":141}},"other_locations":[],"remediation_points":1128000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `getUnicodeSupportMap` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"d9342f9326c59d8e19277db8a2cb8500","location":{"path":"app/assets/javascripts/emoji/support/unicode_support_map.js","lines":{"begin":143,"end":178}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `glEmojiTag` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"580f88e3583b6c310ded6fbad9390305","location":{"path":"app/assets/javascripts/emoji/index.js","lines":{"begin":69,"end":102}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `initDropdown` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"301e9b71ddb9969243fc57daa227b33b","location":{"path":"app/assets/javascripts/sidebar/lib/sidebar_move_issue.js","lines":{"begin":27,"end":59}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `branch_graph.js` has 307 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"8f961e52cddbca0cb2dd3290c7063853","location":{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":1,"end":352}},"other_locations":[],"remediation_points":2020800,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `buildGraph` has 30 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"18ed687a5ecc08e272ec3f5a1e45ba85","location":{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":103,"end":139}},"other_locations":[],"remediation_points":720000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `renderPartialGraph` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"790548e7db64ebbadd07868d6c20245b","location":{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":141,"end":171}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `appendLabel` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"918265d9fa262a2ea6ddda4b96f04407","location":{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":211,"end":246}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `drawLines` has 39 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"df364db884043c3c81e753fb9a58ee90","location":{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":286,"end":333}},"other_locations":[],"remediation_points":936000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `testWrap` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"65093271e08f9838db54de85e17d7c79","location":{"path":"app/assets/javascripts/network/raphael.js","lines":{"begin":37,"end":72}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `commitTooltip` has 31 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"c2753572072946d03cae221981b2a147","location":{"path":"app/assets/javascripts/network/raphael.js","lines":{"begin":3,"end":35}},"other_locations":[],"remediation_points":744000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `testWrap` has 34 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"3ac8fefe6574f998844a591c4dff399c","location":{"path":"app/assets/javascripts/network/raphael.js","lines":{"begin":37,"end":72}},"other_locations":[],"remediation_points":816000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `types.TOGGLE_LOADING` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"41230e2a140c3c519f16d17067a948c0","location":{"path":"app/assets/javascripts/ide/stores/mutations.js","lines":{"begin":14,"end":24}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `types.RENAME_ENTRY` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"65c7f9e9aa2de7fa4e24860dbded9820","location":{"path":"app/assets/javascripts/ide/stores/mutations.js","lines":{"begin":214,"end":263}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"`` has 26 functions (exceeds 20 allowed). Consider refactoring.","fingerprint":"ee3f6d8624f678d9741d386c4252f0fc","location":{"path":"app/assets/javascripts/ide/stores/mutations.js","lines":{"begin":10,"end":269}},"other_locations":[],"remediation_points":1800000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `types.RENAME_ENTRY` has 40 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"98f116d65b4aa0e565234027efee827f","location":{"path":"app/assets/javascripts/ide/stores/mutations.js","lines":{"begin":214,"end":263}},"other_locations":[],"remediation_points":960000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `types.SET_FILE_RAW_DATA` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6460bb9792e8eedb0b1e558f229e6ffa","location":{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":53,"end":75}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `types.DISCARD_FILE_CHANGES` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"aa62953384fc873bd8bddabed1341a3a","location":{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":128,"end":154}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `closeFile` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ca626095e258a497e9cf9c1fa4b7537e","location":{"path":"app/assets/javascripts/ide/stores/actions/file.js","lines":{"begin":10,"end":40}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `createCommitPayload` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ead12c6a7c7c105251c94c6af2fda7b0","location":{"path":"app/assets/javascripts/ide/stores/utils.js","lines":{"begin":133,"end":145}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `decorateData` has 44 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"f8abacda37ac495ce54d8ce69e488724","location":{"path":"app/assets/javascripts/ide/stores/utils.js","lines":{"begin":55,"end":101}},"other_locations":[],"remediation_points":1056000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this function.","location":{"path":"app/assets/javascripts/ide/stores/utils.js","lines":{"begin":158,"end":158}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"75e7e39f5b8ea0aadff2470a9b44ca68"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `entries` has 67 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"1a9caa4d3fce207f88b2afafe14a1df0","location":{"path":"app/assets/javascripts/ide/stores/workers/files_decorator_worker.js","lines":{"begin":11,"end":91}},"other_locations":[],"remediation_points":1608000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Function `types.RECEIVE_LASTEST_PIPELINE_SUCCESS` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ac7ea082c786419244a234de0970ebc9","location":{"path":"app/assets/javascripts/ide/stores/modules/pipelines/mutations.js","lines":{"begin":11,"end":39}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `types.RECEIVE_LASTEST_PIPELINE_SUCCESS` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"0883c6639137c6b51cad4b57c0dd1c38","location":{"path":"app/assets/javascripts/ide/stores/modules/pipelines/mutations.js","lines":{"begin":11,"end":39}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 32 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"0d98be7e83cb9dbc1ca8775da0aa7d19","location":{"path":"app/assets/javascripts/ide/lib/common/model.js","lines":{"begin":6,"end":43}},"other_locations":[],"remediation_points":768000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `initIde` has 31 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"34f27cc8f1c849369b0095674a48c531","location":{"path":"app/assets/javascripts/ide/index.js","lines":{"begin":11,"end":44}},"other_locations":[],"remediation_points":744000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Function `init` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"0c6f3babcfd2a42ae88ffe4cc05028dc","location":{"path":"app/assets/javascripts/pager.js","lines":{"begin":10,"end":10}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `constructor` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"f19d7f17b74ab07e9651e12680b14b9d","location":{"path":"app/assets/javascripts/profile/gl_crop.js","lines":{"begin":12,"end":40}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `onModalShow` has 30 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"c0421daee7918d81456c8580b8878457","location":{"path":"app/assets/javascripts/profile/gl_crop.js","lines":{"begin":69,"end":101}},"other_locations":[],"remediation_points":720000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Function `initMrNotes` has 74 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"4dd3a8bed3022600ffaa03ba5cc77fe6","location":{"path":"app/assets/javascripts/mr_notes/index.js","lines":{"begin":10,"end":92}},"other_locations":[],"remediation_points":1776000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"`` has 24 functions (exceeds 20 allowed). Consider refactoring.","fingerprint":"815b15d961f84ea742e6dce8eb3f8a4d","location":{"path":"app/assets/javascripts/badges/store/actions.js","lines":{"begin":14,"end":167}},"other_locations":[],"remediation_points":1600000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate_each` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"cbc52cfd6436c771188ac8f4e355cb9b","location":{"path":"app/validators/branch_filter_validator.rb","lines":{"begin":16,"end":30}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate_each` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a8179f4c2dfe625c27616c834d37a930","location":{"path":"app/validators/js_regex_validator.rb","lines":{"begin":4,"end":16}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate_each` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0d1ca6a4b7e3294fdc110a8e0ea47f92","location":{"path":"app/validators/cluster_name_validator.rb","lines":{"begin":7,"end":25}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate_each` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d62539a99ae9fabba3cd2cc96713cf09","location":{"path":"app/validators/abstract_path_validator.rb","lines":{"begin":23,"end":35}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `ProjectTeam` has 27 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"ce2cc10520ba3b4b7205e61120d67315","location":{"path":"app/models/project_team.rb","lines":{"begin":3,"end":194}},"other_locations":[],"remediation_points":1900000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `build_kube_client!` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e929847f530fa79a8a58054b9aa3fb8e","location":{"path":"app/models/clusters/platforms/kubernetes.rb","lines":{"begin":125,"end":140}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `note.rb` has 325 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"5f0768574ccb05a5f08cf2e994799fa2","location":{"path":"app/models/note.rb","lines":{"begin":6,"end":474}},"other_locations":[],"remediation_points":2280000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `grouped_diff_discussions` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3e55577fec2bb70f0e880e0e8d0f42ec","location":{"path":"app/models/note.rb","lines":{"begin":150,"end":168}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `in_reply_to?` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a17100ec3750af84df807aff92514aa5","location":{"path":"app/models/note.rb","lines":{"begin":367,"end":382}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Note` has 56 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"5d5c3b8714fe08a2c7df66bc4bfdc538","location":{"path":"app/models/note.rb","lines":{"begin":6,"end":474}},"other_locations":[],"remediation_points":4800000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `track_greatest` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"ee586dc1932745869e3f752d180242c9","location":{"path":"app/models/internal_id.rb","lines":{"begin":55,"end":55}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `rename_descendants` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"41d2108d52e96b7975591b300d3b2e60","location":{"path":"app/models/route.rb","lines":{"begin":23,"end":51}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"complex_logic","content":{"body":""},"description":"Consider simplifying this complex logical expression.","location":{"path":"app/models/issue.rb","lines":{"begin":306,"end":313}},"other_locations":[],"remediation_points":400000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"1cd63fdd17237f7c081abfa37690a7fe"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `as_json` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"430a48264a7379f4d248d672bb16fe44","location":{"path":"app/models/issue.rb","lines":{"begin":250,"end":273}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `readable_by?` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"05cd07a39aaac900028cc3b49079c531","location":{"path":"app/models/issue.rb","lines":{"begin":301,"end":315}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Issue` has 30 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"9619613b02f7bb8841b9e19c688f5251","location":{"path":"app/models/issue.rb","lines":{"begin":5,"end":326}},"other_locations":[],"remediation_points":2200000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `cached_attr_reader` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2a0b7bc4cebaa36fff63efc3ada11817","location":{"path":"app/models/concerns/redis_cacheable.rb","lines":{"begin":10,"end":20}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `move_dir` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a75dea312f0b07cc41974f687ba6fc64","location":{"path":"app/models/concerns/storage/legacy_namespace.rb","lines":{"begin":7,"end":41}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `expand_hierarchy_for_child` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f5222419d454a07f66c83180e4789d18","location":{"path":"app/models/concerns/group_descendant.rb","lines":{"begin":37,"end":70}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `expand_hierarchy_for_child` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"5cd85b2e5055a268df55df99d4d5a94e","location":{"path":"app/models/concerns/group_descendant.rb","lines":{"begin":37,"end":70}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `avatar_path` has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b6177dbe195b50f7a5b10734fbc4a8d2","location":{"path":"app/models/concerns/avatarable.rb","lines":{"begin":45,"end":72}},"other_locations":[],"remediation_points":1050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `with_reactive_cache` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a8e8f8a2e9ccd006ae8f61ca9db92d0c","location":{"path":"app/models/concerns/reactive_caching.rb","lines":{"begin":69,"end":84}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `exclusively_update_reactive_cache!` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2811b2ef3d5196f0b89cec43f1f2b465","location":{"path":"app/models/concerns/reactive_caching.rb","lines":{"begin":91,"end":103}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate_binary_column_exists!` has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring.","fingerprint":"23444612f22a67bddc69d4fb3d9ab40a","location":{"path":"app/models/concerns/sha_attribute.rb","lines":{"begin":18,"end":37}},"other_locations":[],"remediation_points":1050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `current` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"37517b27e64777d7506564ebffc2a9fa","location":{"path":"app/models/concerns/cacheable_attributes.rb","lines":{"begin":44,"end":57}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `chronic_duration_attr_writer` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8acb577138f44873e03ae5712c65f31d","location":{"path":"app/models/concerns/chronic_duration_attribute.rb","lines":{"begin":13,"end":28}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `truncated_diff_lines` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8bade7fdd3ab51990a34487352c56728","location":{"path":"app/models/concerns/discussion_on_diff.rb","lines":{"begin":41,"end":59}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `calculate_reactive_cache` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ff34ec3cc17426f2d12b615f23171aad","location":{"path":"app/models/concerns/prometheus_adapter.rb","lines":{"begin":36,"end":47}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `position_between` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0f9f931c8a1748472719ac1b03432d6c","location":{"path":"app/models/concerns/relative_positioning.rb","lines":{"begin":119,"end":139}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `status_sql` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"46850ccc347015917b7f7d5813dfbb20","location":{"path":"app/models/concerns/has_status.rb","lines":{"begin":19,"end":46}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `has_internal_id` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1753643cebf17fe9b88665c4895f0bc6","location":{"path":"app/models/concerns/atomic_internal_id.rb","lines":{"begin":30,"end":56}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find_by_full_path` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9de369584b4bc5dcd50146b7967ef3b0","location":{"path":"app/models/concerns/routable.rb","lines":{"begin":35,"end":60}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `where_full_path_in` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1d7711a695fff8bdfaa49dc578b0132c","location":{"path":"app/models/concerns/routable.rb","lines":{"begin":69,"end":91}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `manual_inverse_association` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"53ad262470fd01998ef23cb50fac0495","location":{"path":"app/models/concerns/manual_inverse_association.rb","lines":{"begin":7,"end":17}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `raw_participants` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"014b735c6a47b089e8ef4112c427cdf6","location":{"path":"app/models/concerns/participable.rb","lines":{"begin":72,"end":104}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `each_batch` has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5ca9b6fe345855869ed62b41036772f6","location":{"path":"app/models/concerns/each_batch.rb","lines":{"begin":42,"end":81}},"other_locations":[],"remediation_points":1050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `each_batch` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"e56746932db5150f690993cd09ec2c5a","location":{"path":"app/models/concerns/each_batch.rb","lines":{"begin":42,"end":81}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `add_authentication_token_field` has a Cognitive Complexity of 19 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9ffe8c5e6736ff7519d2b0ad210f55dd","location":{"path":"app/models/concerns/token_authenticatable.rb","lines":{"begin":31,"end":60}},"other_locations":[],"remediation_points":1550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `to_hook_data` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"651dd445a68aa882af831870aac09fe6","location":{"path":"app/models/concerns/issuable.rb","lines":{"begin":264,"end":290}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `notes_with_associations` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"edf734b8128847bcceb4300c584ab8e9","location":{"path":"app/models/concerns/issuable.rb","lines":{"begin":318,"end":334}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `max_member_access_for_resource_ids` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9a3525a1273d674a7a5dd1b4599a6b80","location":{"path":"app/models/concerns/bulk_member_access_load.rb","lines":{"begin":12,"end":40}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `enum_with_nil` has a Cognitive Complexity of 20 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d195530dc1d564b6a5a2361310657dd7","location":{"path":"app/models/concerns/enum_with_nil.rb","lines":{"begin":7,"end":33}},"other_locations":[],"remediation_points":1650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `labels_str` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bf445c84a1f8ebfebacc811382517d81","location":{"path":"app/models/label_note.rb","lines":{"begin":77,"end":90}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `notifiable?` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"76278bc24d3f0c41a172b68e2f632daa","location":{"path":"app/models/notification_recipient.rb","lines":{"begin":31,"end":46}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `has_access?` has a Cognitive Complexity of 22 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4264d898878128898c4e12b32b905f8a","location":{"path":"app/models/notification_recipient.rb","lines":{"begin":88,"end":101}},"other_locations":[],"remediation_points":1850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find_notification_setting` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"cf0f0817b180212c8e825cbbed40b752","location":{"path":"app/models/notification_recipient.rb","lines":{"begin":144,"end":154}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `closest_non_global_group_notification_settting` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9f65343a59de0315d68462b18f90defe","location":{"path":"app/models/notification_recipient.rb","lines":{"begin":157,"end":169}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this method.","location":{"path":"app/models/notification_recipient.rb","lines":{"begin":43,"end":43}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"d25d7135d797df677ee520a8a97ae9a6"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `find_commits_by_message` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"0c28ee46d93aa21d37eeb5b2a26d394f","location":{"path":"app/models/repository.rb","lines":{"begin":161,"end":161}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `repository.rb` has 758 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"849ce5e0e3a20d8ed78311435ce5fce9","location":{"path":"app/models/repository.rb","lines":{"begin":3,"end":1058}},"other_locations":[],"remediation_points":8515200,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `keep_around` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8ffb83b66ddf0a719303059ae40ce506","location":{"path":"app/models/repository.rb","lines":{"begin":249,"end":262}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `tree` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"38d273d7d1372c09c7a5c165e170a642","location":{"path":"app/models/repository.rb","lines":{"begin":647,"end":659}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `next_branch` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"53a66b748f45002bcdd585986f4f828f","location":{"path":"app/models/repository.rb","lines":{"begin":684,"end":697}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Repository` has 128 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"1ffa67f7557cad6dc009a3331141e757","location":{"path":"app/models/repository.rb","lines":{"begin":5,"end":1058}},"other_locations":[],"remediation_points":12000000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `enabled` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"38454ee90e05a227558719509fe5ec29","location":{"path":"app/models/remote_mirror.rb","lines":{"begin":104,"end":111}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `RemoteMirror` has 24 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"24334db25a09b73ccd711bb06c29a822","location":{"path":"app/models/remote_mirror.rb","lines":{"begin":3,"end":229}},"other_locations":[],"remediation_points":1600000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `initialize` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9c206e4584e2321188004de82f54d910","location":{"path":"app/models/commit_range.rb","lines":{"begin":62,"end":82}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `user.rb` has 1050 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"11e77959335527c9cb28992c10d37866","location":{"path":"app/models/user.rb","lines":{"begin":3,"end":1502}},"other_locations":[],"remediation_points":12720000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `increment_failed_attempts!` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"51accad62fa466380528844722430a98","location":{"path":"app/models/user.rb","lines":{"begin":1253,"end":1264}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `ensure_user_rights_and_limits` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c7a575c65331c7b917638baa8941d41c","location":{"path":"app/models/user.rb","lines":{"begin":1405,"end":1414}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `signup_domain_valid?` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a9b5f7bc9d9c55cfe5d888bed2fb420a","location":{"path":"app/models/user.rb","lines":{"begin":1416,"end":1441}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `User` has 178 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"f685bcbb6f822884dec234767db1861a","location":{"path":"app/models/user.rb","lines":{"begin":5,"end":1502}},"other_locations":[],"remediation_points":17000000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `project.rb` has 1664 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"531155f760c7355b54c66683855d1397","location":{"path":"app/models/project.rb","lines":{"begin":3,"end":2277}},"other_locations":[],"remediation_points":21561600,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create_or_update_import_data` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"669b48913bc191fe053ef3cf863c7b51","location":{"path":"app/models/project.rb","lines":{"begin":691,"end":706}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `ensure_import_state` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c647270223f46682704c8933072ea030","location":{"path":"app/models/project.rb","lines":{"begin":732,"end":745}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `check_limit` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"238a83e94e0d19d7e5bf774e737f1856","location":{"path":"app/models/project.rb","lines":{"begin":887,"end":899}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find_or_initialize_services` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b5c439340a2145fd43e3c155a46b8084","location":{"path":"app/models/project.rb","lines":{"begin":1084,"end":1110}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `check_repository_path_availability` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"84ad9cf46f3288017a0f4b6db6438a6c","location":{"path":"app/models/project.rb","lines":{"begin":1302,"end":1316}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `after_create_default_branch` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2a2d29b10f840adb402e27183b8afb0e","location":{"path":"app/models/project.rb","lines":{"begin":1685,"end":1704}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `container_registry_variables` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"22330faec24429812d37099efaf8566b","location":{"path":"app/models/project.rb","lines":{"begin":1811,"end":1821}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `handle_update_attribute_error` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"103e8043443b236e57b2b71b4071ed2a","location":{"path":"app/models/project.rb","lines":{"begin":2240,"end":2250}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `fetch_branch_allows_collaboration?` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0a44b195efa5fdd8f8a133a9382fe540","location":{"path":"app/models/project.rb","lines":{"begin":2252,"end":2276}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Project` has 258 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"64039fbe3749f7d87b4ba7e85868d7fc","location":{"path":"app/models/project.rb","lines":{"begin":5,"end":2277}},"other_locations":[],"remediation_points":25000000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `service.rb` has 261 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"f45455ad20cdb5129a3bfb9eebb6498b","location":{"path":"app/models/service.rb","lines":{"begin":5,"end":346}},"other_locations":[],"remediation_points":1358400,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Service` has 40 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"96ce9f4a9d59b553ec55116c8a3be7ae","location":{"path":"app/models/service.rb","lines":{"begin":5,"end":346}},"other_locations":[],"remediation_points":3200000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `available_services_names` has 34 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"f2ec9d5c5ae446fb75d746688a3a72fe","location":{"path":"app/models/service.rb","lines":{"begin":247,"end":284}},"other_locations":[],"remediation_points":816000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `raw_binary?` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0ae3aeb7a760efb26099272499cfbade","location":{"path":"app/models/blob.rb","lines":{"begin":161,"end":175}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Blob` has 27 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"a44f4d9e927f1b91399b8e17fb943f6d","location":{"path":"app/models/blob.rb","lines":{"begin":4,"end":254}},"other_locations":[],"remediation_points":1900000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `event.rb` has 309 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"6850b538f65ad91cf5c5ef2e7148924e","location":{"path":"app/models/event.rb","lines":{"begin":3,"end":410}},"other_locations":[],"remediation_points":2049600,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `visible_to_user?` has a Cognitive Complexity of 15 (exceeds 5 allowed). Consider refactoring.","fingerprint":"29269e08d03641e18bd2ba7cd22a0d3f","location":{"path":"app/models/event.rb","lines":{"begin":151,"end":167}},"other_locations":[],"remediation_points":1150000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `action_name` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f28caae33540f5326e5ce2d58a03d771","location":{"path":"app/models/event.rb","lines":{"begin":265,"end":287}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Event` has 50 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"613c580b618dad28f34b389f766efe2e","location":{"path":"app/models/event.rb","lines":{"begin":3,"end":410}},"other_locations":[],"remediation_points":4200000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `different_group` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2ac2c358921313bb5981e964133c5ecf","location":{"path":"app/models/project_group_link.rb","lines":{"begin":38,"end":49}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `merge_request_version_params` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8d1a8357abf058d725c59df9cca495bf","location":{"path":"app/models/diff_discussion.rb","lines":{"begin":25,"end":36}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `active?` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"772f6211e69bcffb4fbc411c5d7d31c3","location":{"path":"app/models/legacy_diff_note.rb","lines":{"begin":57,"end":75}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this method.","location":{"path":"app/models/legacy_diff_note.rb","lines":{"begin":62,"end":62}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"4e0039e61f3fd67caeb1b978db868447"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `group.rb` has 290 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"d9e231fdbc15e514e21e1596b5e2d930","location":{"path":"app/models/group.rb","lines":{"begin":3,"end":403}},"other_locations":[],"remediation_points":1776000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Group` has 53 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"f82613684deaaf389431887bc5a62c74","location":{"path":"app/models/group.rb","lines":{"begin":5,"end":403}},"other_locations":[],"remediation_points":4500000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Label` has 25 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"9660fb59aa00ace0b608078c78c611a4","location":{"path":"app/models/label.rb","lines":{"begin":3,"end":244}},"other_locations":[],"remediation_points":1700000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `has_intermediates?` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"fc033b957f3fcb1bd690b7edb50aa441","location":{"path":"app/models/pages_domain.rb","lines":{"begin":79,"end":98}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `PagesDomain` has 24 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"389a0c10cffbc7cd770d8d67a31e61ba","location":{"path":"app/models/pages_domain.rb","lines":{"begin":3,"end":201}},"other_locations":[],"remediation_points":1600000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `generate_slug` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0d507615693230a051c9d4ae397fe5d2","location":{"path":"app/models/environment.rb","lines":{"begin":178,"end":203}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Environment` has 27 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"4140683d4224f01a7fe2fad0da3d11c6","location":{"path":"app/models/environment.rb","lines":{"begin":3,"end":243}},"other_locations":[],"remediation_points":1900000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `ProjectWiki` has 29 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"a7ff4b093a326a93bf1e0887a36ba898","location":{"path":"app/models/project_wiki.rb","lines":{"begin":3,"end":203}},"other_locations":[],"remediation_points":2100000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `track` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d55ffd71690c0e606bcb1fa48074affd","location":{"path":"app/models/user_interacted_project.rb","lines":{"begin":16,"end":41}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `update` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8737f9bae4ea49696d911b5b162784ef","location":{"path":"app/models/wiki_page.rb","lines":{"begin":215,"end":244}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `process_title` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"43c91a5205fef35946442db85ab54267","location":{"path":"app/models/wiki_page.rb","lines":{"begin":283,"end":295}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `WikiPage` has 35 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"35e7d7ce82a5641563ba1029c54645bc","location":{"path":"app/models/wiki_page.rb","lines":{"begin":4,"end":326}},"other_locations":[],"remediation_points":2700000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `update_position` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"fa4f67c27ab14379e44af70d58264c1a","location":{"path":"app/models/diff_note.rb","lines":{"begin":152,"end":173}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `append` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d527adfd814d095e55079d7a898a3fc3","location":{"path":"app/models/ci/build_trace_chunk.rb","lines":{"begin":74,"end":84}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `pipeline.rb` has 488 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"cee8532683fbbb22a3b807c5714c49c7","location":{"path":"app/models/ci/pipeline.rb","lines":{"begin":3,"end":671}},"other_locations":[],"remediation_points":4627200,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `ci_yaml_from_repo` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f19177ae4080cc2c9d81a39383b45922","location":{"path":"app/models/ci/pipeline.rb","lines":{"begin":632,"end":639}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Pipeline` has 68 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"af1e8c39d8b166628ae043bce72269a5","location":{"path":"app/models/ci/pipeline.rb","lines":{"begin":4,"end":670}},"other_locations":[],"remediation_points":6000000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `build.rb` has 604 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"7967fd1fb861d27e33c208d88261cd76","location":{"path":"app/models/ci/build.rb","lines":{"begin":3,"end":809}},"other_locations":[],"remediation_points":6297600,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `scoped_variables` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e310e4c57a2e9123f26a1cbcec9809eb","location":{"path":"app/models/ci/build.rb","lines":{"begin":312,"end":327}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `predefined_variables` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"13282d4d569e2daa02632e5249568733","location":{"path":"app/models/ci/build.rb","lines":{"begin":726,"end":745}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `legacy_variables` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"81e2fd25bb2dd91faed640216e965698","location":{"path":"app/models/ci/build.rb","lines":{"begin":747,"end":759}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `persisted_environment_variables` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"67327cbc303019830fbd1d6586dcde3e","location":{"path":"app/models/ci/build.rb","lines":{"begin":761,"end":772}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Build` has 100 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"736c24725c78f957ee4538a1ef73cab0","location":{"path":"app/models/ci/build.rb","lines":{"begin":4,"end":808}},"other_locations":[],"remediation_points":9200000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `status` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c700cdde3d0b6292dd18227b3e90cf8d","location":{"path":"app/models/ci/runner.rb","lines":{"begin":179,"end":187}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Runner` has 31 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"a9c3d8a2409fd9c5506a846374c16d42","location":{"path":"app/models/ci/runner.rb","lines":{"begin":4,"end":320}},"other_locations":[],"remediation_points":2300000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Discussion` has 23 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"21189089f43b68ee94981dbac970d566","location":{"path":"app/models/discussion.rb","lines":{"begin":6,"end":138}},"other_locations":[],"remediation_points":1500000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `milestone_format_reference` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0e735e47b6b8a533b9ff579e13b277c9","location":{"path":"app/models/milestone.rb","lines":{"begin":261,"end":273}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Milestone` has 26 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"283d777de6e0e7974ccbb1e316f5fd1a","location":{"path":"app/models/milestone.rb","lines":{"begin":3,"end":288}},"other_locations":[],"remediation_points":1800000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0d0fba50527ad864dc4649245f95f1bf","location":{"path":"app/models/project_services/drone_ci_service.rb","lines":{"begin":22,"end":31}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `calculate_reactive_cache` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"aa74471515edc43c1ab5339ddf68e505","location":{"path":"app/models/project_services/drone_ci_service.rb","lines":{"begin":53,"end":74}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0a0446e31eb4d865b34fe5938f53bbad","location":{"path":"app/models/project_services/chat_notification_service.rb","lines":{"begin":52,"end":79}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `get_message` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"07a9999f0d84368d5983e08e2891f237","location":{"path":"app/models/project_services/chat_notification_service.rb","lines":{"begin":111,"end":126}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `notify_for_ref?` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6a030ca161112b5f434986ab0ae88c0f","location":{"path":"app/models/project_services/chat_notification_service.rb","lines":{"begin":159,"end":171}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `ChatNotificationService` has 23 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"5d159cd60a69a3f1a1b5beb530264825","location":{"path":"app/models/project_services/chat_notification_service.rb","lines":{"begin":5,"end":183}},"other_locations":[],"remediation_points":1500000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `read_commit_status` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"69dbb9ff98b20cc8db3a809b7e239e5f","location":{"path":"app/models/project_services/mock_ci_service.rb","lines":{"begin":70,"end":84}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `KubernetesService` has 25 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"2e6c7a0448e9bb4e799cb7efe0846fc7","location":{"path":"app/models/project_services/kubernetes_service.rb","lines":{"begin":8,"end":251}},"other_locations":[],"remediation_points":1700000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `read_commit_status` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8fb7749a6cc98bccd8d5712c1d499494","location":{"path":"app/models/project_services/teamcity_service.rb","lines":{"begin":112,"end":132}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `initialize_properties` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a965dd277aee3504a57790eb7271cadb","location":{"path":"app/models/project_services/issue_tracker_service.rb","lines":{"begin":52,"end":69}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `buildkite_endpoint` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"161d47385d79643f9414ed2ad67502a9","location":{"path":"app/models/project_services/buildkite_service.rb","lines":{"begin":106,"end":119}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"42914696303830e3d209925e13650d83","location":{"path":"app/models/project_services/pushover_service.rb","lines":{"begin":67,"end":104}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `fields` has 39 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"773d8cd6842c7b74f60e9ab8003ad977","location":{"path":"app/models/project_services/pushover_service.rb","lines":{"begin":21,"end":61}},"other_locations":[],"remediation_points":936000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `execute` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"7b760b5c22532a27dbd776328b7db9a6","location":{"path":"app/models/project_services/pushover_service.rb","lines":{"begin":67,"end":104}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"802d66c5bd557b6f1bdd32240846e4c2","location":{"path":"app/models/project_services/pipelines_email_service.rb","lines":{"begin":28,"end":38}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `jira_service.rb` has 261 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"c5f438f6b31722193eb4e10b389655b6","location":{"path":"app/models/project_services/jira_service.rb","lines":{"begin":3,"end":344}},"other_locations":[],"remediation_points":1358400,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `close_issue` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f74475ea9bd04b9ed8ff7ddcc5c29633","location":{"path":"app/models/project_services/jira_service.rb","lines":{"begin":117,"end":135}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create_cross_reference_note` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6c27b1c9b77bd4f2d2f11a294e90cf36","location":{"path":"app/models/project_services/jira_service.rb","lines":{"begin":137,"end":167}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `JiraService` has 35 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"2d0643b626f1ad53bf43aadedd954eae","location":{"path":"app/models/project_services/jira_service.rb","lines":{"begin":3,"end":344}},"other_locations":[],"remediation_points":2700000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `read_commit_status` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f2f5469088e256c3b81eccc8ecaf967b","location":{"path":"app/models/project_services/bamboo_service.rb","lines":{"begin":94,"end":112}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create_message` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"fcb9db20f4fe6adda5925e7da947a943","location":{"path":"app/models/project_services/hipchat_service.rb","lines":{"begin":85,"end":100}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create_push_message` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7f972562d25c4198e75c8dac6931a928","location":{"path":"app/models/project_services/hipchat_service.rb","lines":{"begin":106,"end":138}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `HipchatService` has 27 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"bb12852ed6419e4dea808d1d873302a1","location":{"path":"app/models/project_services/hipchat_service.rb","lines":{"begin":3,"end":311}},"other_locations":[],"remediation_points":1900000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `create_note_message` has 39 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"96500251c9498d9f1e9c7da0c8384528","location":{"path":"app/models/project_services/hipchat_service.rb","lines":{"begin":200,"end":244}},"other_locations":[],"remediation_points":936000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `format_channel` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e064d1923f5ef24f603e3c03af81644f","location":{"path":"app/models/project_services/irker_service.rb","lines":{"begin":93,"end":112}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `check_commit` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d6ee148a09cf8c383948472d577bfb74","location":{"path":"app/models/project_services/asana_service.rb","lines":{"begin":81,"end":108}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Namespace` has 34 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"411d817f1a6db72f360bb2cb93e055ec","location":{"path":"app/models/namespace.rb","lines":{"begin":3,"end":302}},"other_locations":[],"remediation_points":2600000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `application_setting.rb` has 387 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"50270695e6d7c5163050078e7cf65e18","location":{"path":"app/models/application_setting.rb","lines":{"begin":3,"end":489}},"other_locations":[],"remediation_points":3172800,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `ApplicationSetting` has 38 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"02be76880912851331582ab14ef56dd4","location":{"path":"app/models/application_setting.rb","lines":{"begin":3,"end":489}},"other_locations":[],"remediation_points":3000000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `defaults` has 76 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"4a5e7733302a5f59e7878ab40f6b9f82","location":{"path":"app/models/application_setting.rb","lines":{"begin":232,"end":309}},"other_locations":[],"remediation_points":1824000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `base_commit_sha` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"70d6880ba8e52f184e9eaf896119e352","location":{"path":"app/models/compare.rb","lines":{"begin":50,"end":56}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `commit.rb` has 355 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"c361e4106ded93f757f69964f420b067","location":{"path":"app/models/commit.rb","lines":{"begin":4,"end":508}},"other_locations":[],"remediation_points":2712000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `order_by` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8c4e54c836dbfddf9329a85f83378cb5","location":{"path":"app/models/commit.rb","lines":{"begin":63,"end":75}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `uri_type` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ac39422eaa05c0e3880afe76c6341f18","location":{"path":"app/models/commit.rb","lines":{"begin":425,"end":435}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Commit` has 68 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"e2175bec55ffd09f5d7b2352b5c5dcad","location":{"path":"app/models/commit.rb","lines":{"begin":4,"end":508}},"other_locations":[],"remediation_points":6000000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `merge_request.rb` has 897 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"59d143493fc6a1f49dd6ff46bba4459f","location":{"path":"app/models/merge_request.rb","lines":{"begin":3,"end":1238}},"other_locations":[],"remediation_points":10516800,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate_branches` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"95d0d3fa4206c77bab101daf5035ee18","location":{"path":"app/models/merge_request.rb","lines":{"begin":511,"end":524}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate_fork` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"68cf8c7f9bbbebf2133c22434d2bcae9","location":{"path":"app/models/merge_request.rb","lines":{"begin":532,"end":539}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `mergeable_state?` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bdc249b8456dc07607ba4fe001ff1261","location":{"path":"app/models/merge_request.rb","lines":{"begin":677,"end":685}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `cache_merge_request_closes_issues!` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bcd9dc4beba740e5c019b9c760cacdd3","location":{"path":"app/models/merge_request.rb","lines":{"begin":769,"end":782}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `compare_test_reports` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b662bb8a5b01a77feb8b7b0a9ffefdb2","location":{"path":"app/models/merge_request.rb","lines":{"begin":1041,"end":1054}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `mergeable_with_quick_action?` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"74fd9deeffa5589190ba744e4af78384","location":{"path":"app/models/merge_request.rb","lines":{"begin":1177,"end":1187}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `MergeRequest` has 137 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"417a10e5eb9495ae2d250b8c195971f7","location":{"path":"app/models/merge_request.rb","lines":{"begin":3,"end":1238}},"other_locations":[],"remediation_points":12900000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this method.","location":{"path":"app/models/merge_request.rb","lines":{"begin":682,"end":682}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"ac1600795e5aff84e3d4e9243b88bdbc"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this method.","location":{"path":"app/models/merge_request.rb","lines":{"begin":1184,"end":1184}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"4cc86fde220f02f2e1c1443c9c96fe93"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `member.rb` has 297 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"ead9a1c0eaecbe741f755dd85ef04b38","location":{"path":"app/models/member.rb","lines":{"begin":3,"end":419}},"other_locations":[],"remediation_points":1876800,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `retrieve_member` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9cf98664280114d55fe07fc00a2931f4","location":{"path":"app/models/member.rb","lines":{"begin":236,"end":248}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Member` has 41 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"5c62b78b2bb4b49f04e64fa24a5e7525","location":{"path":"app/models/member.rb","lines":{"begin":3,"end":419}},"other_locations":[],"remediation_points":3300000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `set` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"8869fa571b5fb7a617adc0197c7ac362","location":{"path":"app/models/active_session.rb","lines":{"begin":20,"end":50}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `count_to_display_commit_in_center` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b411aa7c155fd11004316e7fd39fd0f0","location":{"path":"app/models/network/graph.rb","lines":{"begin":79,"end":107}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `place_chain` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"177c4e2e8eb1351747941148b8c5841f","location":{"path":"app/models/network/graph.rb","lines":{"begin":180,"end":216}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `take_left_leaves` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"07eb1c8a024e1084d5249e442c56ead6","location":{"path":"app/models/network/graph.rb","lines":{"begin":263,"end":277}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `place_chain` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"d89c4cb61eca0dac9322942ca4b87aff","location":{"path":"app/models/network/graph.rb","lines":{"begin":180,"end":216}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `save_diffs` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c6b7ee6cba58c9eb3d9ad5eed75d6ec3","location":{"path":"app/models/merge_request_diff.rb","lines":{"begin":272,"end":296}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `MergeRequestDiff` has 33 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"d7a32bf8ffc7cc2cb0b417114258fc44","location":{"path":"app/models/merge_request_diff.rb","lines":{"begin":3,"end":322}},"other_locations":[],"remediation_points":2500000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `object_storage.rb` has 315 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"86494fa0d557a4aa389e5171896783dc","location":{"path":"app/uploaders/object_storage.rb","lines":{"begin":3,"end":458}},"other_locations":[],"remediation_points":2136000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `changed_mounts` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.","fingerprint":"fd0a4f3d9448639f581ace634e78fb9f","location":{"path":"app/uploaders/object_storage.rb","lines":{"begin":113,"end":124}},"other_locations":[],"remediation_points":850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `workhorse_remote_upload_options` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e022c746daf5a42b94b0696cad68db33","location":{"path":"app/uploaders/object_storage.rb","lines":{"begin":191,"end":201}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `unsafe_migrate!` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1684da513e48bc7fed9d7d05f006f4f3","location":{"path":"app/uploaders/object_storage.rb","lines":{"begin":415,"end":442}},"other_locations":[],"remediation_points":850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `record_upload` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7714f01e58a6f57d5612758293fdcd98","location":{"path":"app/uploaders/records_uploads.rb","lines":{"begin":22,"end":32}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `open` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e3420c6ebb4c5709171dfe0ad626a693","location":{"path":"app/uploaders/gitlab_uploader.rb","lines":{"begin":78,"end":94}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `FileUploader` has 25 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"377d9736f93da216ab2620478b97b6a7","location":{"path":"app/uploaders/file_uploader.rb","lines":{"begin":11,"end":200}},"other_locations":[],"remediation_points":1700000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `ci_status` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0ecf5e5baa621e39be46cda7a6b7e79a","location":{"path":"app/presenters/merge_request_presenter.rb","lines":{"begin":13,"end":23}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `MergeRequestPresenter` has 29 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"8382c7b1054d55cea9b796fc549636ad","location":{"path":"app/presenters/merge_request_presenter.rb","lines":{"begin":3,"end":231}},"other_locations":[],"remediation_points":2100000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `cards` has 79 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"56c716082acebaebac8f5817c4770ff3","location":{"path":"app/presenters/conversational_development_index/metric_presenter.rb","lines":{"begin":5,"end":85}},"other_locations":[],"remediation_points":1896000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `idea_to_production_steps` has 52 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"3ec38351e7aae7c1eb1bbf782da34f4f","location":{"path":"app/presenters/conversational_development_index/metric_presenter.rb","lines":{"begin":87,"end":140}},"other_locations":[],"remediation_points":1248000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `project_presenter.rb` has 312 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"d892daae824d8e78fe2a0b68c288acda","location":{"path":"app/presenters/project_presenter.rb","lines":{"begin":3,"end":370}},"other_locations":[],"remediation_points":2092800,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `default_view` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d66dbcb27efcacaf84388d8cfc5f690f","location":{"path":"app/presenters/project_presenter.rb","lines":{"begin":64,"end":80}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `readme_anchor_data` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c40df23b551a8abe9f2d5830edfbf472","location":{"path":"app/presenters/project_presenter.rb","lines":{"begin":221,"end":231}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `autodevops_anchor_data` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3e4902e11edd6de01b81f9a61f5d9d7b","location":{"path":"app/presenters/project_presenter.rb","lines":{"begin":275,"end":285}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `kubernetes_cluster_anchor_data` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"119e536f7905363201fb67bbdcd65824","location":{"path":"app/presenters/project_presenter.rb","lines":{"begin":287,"end":299}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `ProjectPresenter` has 40 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"174173017516e33835d52eb7c5513209","location":{"path":"app/presenters/project_presenter.rb","lines":{"begin":3,"end":370}},"other_locations":[],"remediation_points":3200000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `notification_service.rb` has 356 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"69e4d6c40c4449fefd31aa10ca6d0d74","location":{"path":"app/services/notification_service.rb","lines":{"begin":18,"end":550}},"other_locations":[],"remediation_points":2726400,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `NotificationService` has 57 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"f69a1b203ea4d5900672119cebb81b66","location":{"path":"app/services/notification_service.rb","lines":{"begin":18,"end":550}},"other_locations":[],"remediation_points":4900000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"40698d762fba8b2aa8a60c141d6d8790","location":{"path":"app/services/groups/create_service.rb","lines":{"begin":10,"end":29}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `can_create_group?` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b75b73bf2d690e5a17c2abe284491440","location":{"path":"app/services/groups/create_service.rb","lines":{"begin":37,"end":54}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `ensure_allowed_transfer` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b1a41885cc0a6ac544248d54c07e1636","location":{"path":"app/services/groups/transfer_service.rb","lines":{"begin":41,"end":47}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4bb4279e0d059ae00152e8bdf1ea798d","location":{"path":"app/services/groups/update_service.rb","lines":{"begin":7,"end":25}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `get_operation_id` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e02445fcf7469e25e1790f6de102578e","location":{"path":"app/services/clusters/gcp/provision_service.rb","lines":{"begin":24,"end":48}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ee86b571c5fd71a16cf372ae35959a1d","location":{"path":"app/services/clusters/applications/check_installation_progress_service.rb","lines":{"begin":6,"end":19}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c7bf557578299a5ba915c32a04c77757","location":{"path":"app/services/gravatar_service.rb","lines":{"begin":4,"end":18}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `valid_visibility_level_change?` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5663649284b422de3ee165079f02580a","location":{"path":"app/services/concerns/update_visibility_level.rb","lines":{"begin":4,"end":16}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1e2214a2c7403de3b6b130ef6a8ae0e7","location":{"path":"app/services/labels/transfer_service.rb","lines":{"begin":15,"end":29}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"889d22762e16d3366a67e51333a2ca58","location":{"path":"app/services/labels/promote_service.rb","lines":{"begin":8,"end":30}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"83f2800751c8e1fc38441feba44838e9","location":{"path":"app/services/notes/create_service.rb","lines":{"begin":5,"end":53}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `execute` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"64400ce10f6b24c336dc2c14dc7631e5","location":{"path":"app/services/notes/create_service.rb","lines":{"begin":5,"end":53}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `project` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"55c1155f35f19aeab86111aa747bcdef","location":{"path":"app/services/search_service.rb","lines":{"begin":12,"end":22}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `group` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9350f7f8937ed59a3c058c18876a72fc","location":{"path":"app/services/search_service.rb","lines":{"begin":26,"end":36}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `add_commits` has 6 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"eb5157bfd09a812f4b9e9e59faa9bd43","location":{"path":"app/services/system_note_service.rb","lines":{"begin":22,"end":22}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `change_status` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"1b2b9c2adcef9eef8232ca3fabba5213","location":{"path":"app/services/system_note_service.rb","lines":{"begin":214,"end":214}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `change_branch` has 6 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"d01b8c3144cf8ecd33ca899268167ba5","location":{"path":"app/services/system_note_service.rb","lines":{"begin":370,"end":370}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `change_branch_presence` has 6 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"dcdc7164fbd2b97a6ffca4f6dc2e0e44","location":{"path":"app/services/system_note_service.rb","lines":{"begin":390,"end":390}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `system_note_service.rb` has 269 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"9d114264549f2dceede46ea914a3550c","location":{"path":"app/services/system_note_service.rb","lines":{"begin":7,"end":679}},"other_locations":[],"remediation_points":1473600,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `change_time_spent` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5c81cb9f69e1de7b23d6f18ba82533d3","location":{"path":"app/services/system_note_service.rb","lines":{"begin":181,"end":197}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `cross_reference_disallowed?` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"cf012be1a6a2e48dd333008fe9d0d152","location":{"path":"app/services/system_note_service.rb","lines":{"begin":455,"end":461}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `existing_commit_summary` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9e510f603309baf5e0cb54ad77970a75","location":{"path":"app/services/system_note_service.rb","lines":{"begin":637,"end":659}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `create_mention_todos` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"8a610af9d7608ea64f58ba654367d763","location":{"path":"app/services/todo_service.rb","lines":{"begin":273,"end":273}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `attributes_for_todo` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"22c5b886bc2bcef31fd1446dabf42446","location":{"path":"app/services/todo_service.rb","lines":{"begin":310,"end":310}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `TodoService` has 43 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"888b933ca386de89d1c664deed0728bd","location":{"path":"app/services/todo_service.rb","lines":{"begin":10,"end":357}},"other_locations":[],"remediation_points":3500000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bcfd0e3ea01c9694d57bfccaa03838e6","location":{"path":"app/services/verify_pages_domain_service.rb","lines":{"begin":18,"end":28}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d473aafcb22747b52b1f62e820f2074d","location":{"path":"app/services/create_branch_service.rb","lines":{"begin":4,"end":21}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9a39c0c805730f76077d4c41f5a49ab0","location":{"path":"app/services/todos/destroy/entity_leave_service.rb","lines":{"begin":21,"end":35}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"dd806bba9fb1ffe1bffc98d5b313f431","location":{"path":"app/services/todos/destroy/private_features_service.rb","lines":{"begin":14,"end":25}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"669e705b9b727535b65aa70c23908b8a","location":{"path":"app/services/issuable/bulk_update_service.rb","lines":{"begin":6,"end":31}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"fa059d9d5e3d40934b6d454456a29e17","location":{"path":"app/services/issuable/common_system_notes_service.rb","lines":{"begin":7,"end":21}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `process_registry_access` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0a9f93af474354f18c131c4a6f33ce74","location":{"path":"app/services/auth/container_registry_authentication_service.rb","lines":{"begin":71,"end":77}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `process_repository_access` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d2612abf7127bdfa9f619c175cf5d2cc","location":{"path":"app/services/auth/container_registry_authentication_service.rb","lines":{"begin":79,"end":97}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7189b60fb2402fbb02818934986a95e8","location":{"path":"app/services/projects/overwrite_project_service.rb","lines":{"begin":5,"end":26}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 26 (exceeds 5 allowed). Consider refactoring.","fingerprint":"961ae326b78bf20ee97acef0cec52327","location":{"path":"app/services/projects/create_service.rb","lines":{"begin":11,"end":74}},"other_locations":[],"remediation_points":2250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `after_create_actions` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e38e4c0872ce60d2ba85c11448b4522b","location":{"path":"app/services/projects/create_service.rb","lines":{"begin":98,"end":114}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `save_project_and_import_data` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"49a616d751623502896fe1bf01ddc263","location":{"path":"app/services/projects/create_service.rb","lines":{"begin":143,"end":158}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `execute` has 41 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"175fda5eebf084d959ea97dbc7ddba89","location":{"path":"app/services/projects/create_service.rb","lines":{"begin":11,"end":74}},"other_locations":[],"remediation_points":984000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this method.","location":{"path":"app/services/projects/create_service.rb","lines":{"begin":53,"end":53}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"4406c9c51c68a677aea6fc1c46031379"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `propagate_projects_with_template` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"293ec445efe1987a7ed4d749d241b1c9","location":{"path":"app/services/projects/propagate_service_template.rb","lines":{"begin":25,"end":33}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2a2218c0712e897508cb29f687ddbb15","location":{"path":"app/services/projects/destroy_service.rb","lines":{"begin":17,"end":49}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `attempt_repositories_rollback` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"06f3aaf8a1f066c4e7933483e129d710","location":{"path":"app/services/projects/destroy_service.rb","lines":{"begin":51,"end":63}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `add_repository_to_project` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0129f188de75c26a852812d70994f671","location":{"path":"app/services/projects/import_service.rb","lines":{"begin":33,"end":52}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `import_repository` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a7dc266875c644d2161df4f52854509a","location":{"path":"app/services/projects/import_service.rb","lines":{"begin":60,"end":78}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `download_lfs_objects` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e22b343575e9881c97f2271bcd97f948","location":{"path":"app/services/projects/import_service.rb","lines":{"begin":80,"end":99}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `import_data` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7bc52f032ae36171f9038ca564b8725f","location":{"path":"app/services/projects/import_service.rb","lines":{"begin":101,"end":109}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 15 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d3753f60f8dc5d9fdb996971cbdec0ee","location":{"path":"app/services/projects/update_pages_service.rb","lines":{"begin":18,"end":47}},"other_locations":[],"remediation_points":1150000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `extract_zip_archive!` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"fe7709a469edc64e95ec098c80aa4d9e","location":{"path":"app/services/projects/update_pages_service.rb","lines":{"begin":84,"end":104}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `UpdatePagesService` has 23 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"d7d865dc59fc4a03d279c1c19c89a168","location":{"path":"app/services/projects/update_pages_service.rb","lines":{"begin":4,"end":191}},"other_locations":[],"remediation_points":1500000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `labels_as_hash` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"78f7382b2da989274c44cca4dd67b726","location":{"path":"app/services/projects/autocomplete_service.rb","lines":{"begin":25,"end":47}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ecc06d47c5ab14de0497085a390276e9","location":{"path":"app/services/projects/update_remote_mirror_service.rb","lines":{"begin":7,"end":31}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f166c36283c89cda2c2d1b400fc83d9c","location":{"path":"app/services/projects/transfer_service.rb","lines":{"begin":16,"end":36}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8619477bd476b8e6c20c420edaafa603","location":{"path":"app/services/projects/update_service.rb","lines":{"begin":10,"end":29}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate!` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"eab5a0a1e19f69711efa955efe37831a","location":{"path":"app/services/projects/update_service.rb","lines":{"begin":40,"end":52}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `after_update` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a1014f2a5df19a7195983026335ef76c","location":{"path":"app/services/projects/update_service.rb","lines":{"begin":54,"end":76}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"23b22fd0746b04d1cdb84c038d084b5b","location":{"path":"app/services/projects/hashed_storage/migrate_repository_service.rb","lines":{"begin":18,"end":46}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0543ffb09bae340f0c5077ae46b7cdcc","location":{"path":"app/services/projects/lfs_pointers/lfs_download_service.rb","lines":{"begin":8,"end":23}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"896cabbb6ed77bf3c709bb312f23a6fb","location":{"path":"app/services/projects/lfs_pointers/lfs_import_service.rb","lines":{"begin":17,"end":32}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `lfsconfig_endpoint_uri` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ab48443c563d169a420e80faa5c91bf8","location":{"path":"app/services/projects/lfs_pointers/lfs_import_service.rb","lines":{"begin":56,"end":72}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0d7377f3f82a92babb9d1d653fb3a6c0","location":{"path":"app/services/projects/unlink_fork_service.rb","lines":{"begin":6,"end":29}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `notification_recipient_service.rb` has 261 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"04116f97d81f75dc8b45ce0a5811fa81","location":{"path":"app/services/notification_recipient_service.rb","lines":{"begin":6,"end":384}},"other_locations":[],"remediation_points":1358400,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `build!` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bc4e88abd84c5b4832ac272b050f5372","location":{"path":"app/services/notification_recipient_service.rb","lines":{"begin":257,"end":295}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Base` has 28 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"27695a9b55119263d5fc023bfb91d6e3","location":{"path":"app/services/notification_recipient_service.rb","lines":{"begin":28,"end":238}},"other_locations":[],"remediation_points":2000000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6cc1d79d478940cb6d6b9ceed02cb6e6","location":{"path":"app/services/users/destroy_service.rb","lines":{"begin":26,"end":64}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute_without_lease` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"67cb8ef6b0457ad00d8347bcbe3ff3f7","location":{"path":"app/services/users/refresh_authorized_projects_service.rb","lines":{"begin":50,"end":71}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `update_authorizations` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6e70e1ba1ea2f084af1fff74047fe8d9","location":{"path":"app/services/users/refresh_authorized_projects_service.rb","lines":{"begin":77,"end":88}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d9165689bde9f912aa84f6f518e598da","location":{"path":"app/services/users/build_service.rb","lines":{"begin":14,"end":36}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `build_user_params` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"830b5807353157bd5e183aad25f2b282","location":{"path":"app/services/users/build_service.rb","lines":{"begin":88,"end":111}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `admin_create_params` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"fe5ddceb25aafe04827303d1f6d564b4","location":{"path":"app/services/users/build_service.rb","lines":{"begin":45,"end":74}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5bc79f55d7e462657e85385bf64c461b","location":{"path":"app/services/submit_usage_ping_service.rb","lines":{"begin":16,"end":34}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"eff6af7a39548e896b0c36625e41edfa","location":{"path":"app/services/validate_new_branch_service.rb","lines":{"begin":6,"end":20}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f26b8395f9bebcbbe601568ab87f1dac","location":{"path":"app/services/tags/create_service.rb","lines":{"begin":5,"end":32}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"009acc0cc8f2cad1eb48f996869cd8b3","location":{"path":"app/services/tags/destroy_service.rb","lines":{"begin":6,"end":29}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `close_issue` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"268f126190d57eeaaded69cfb25897c3","location":{"path":"app/services/issues/close_service.rb","lines":{"begin":20,"end":39}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `handle_changes` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ff12a5753d6bee667c95cfbc92416e03","location":{"path":"app/services/issues/update_service.rb","lines":{"begin":18,"end":56}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `handle_changes` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"8b14e45d1c64f39d6eedb20d84843741","location":{"path":"app/services/issues/update_service.rb","lines":{"begin":18,"end":56}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `filter_assignee` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5691687cb00f6fd194e603429807185a","location":{"path":"app/services/issues/base_service.rb","lines":{"begin":35,"end":51}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `execute` has 32 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"1a9702d3dc815e8d64756d8fb212f9b3","location":{"path":"app/services/web_hook_service.rb","lines":{"begin":24,"end":62}},"other_locations":[],"remediation_points":768000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `execute` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"4d9ca5643eb0d67f71faf5371f5ae764","location":{"path":"app/services/ci/create_pipeline_service.rb","lines":{"begin":15,"end":48}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b8c02fe4ca7afa344ed38920cbc647e3","location":{"path":"app/services/ci/retry_pipeline_service.rb","lines":{"begin":7,"end":28}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bc2e58626fb38ae2a635ad7504d1369f","location":{"path":"app/services/ci/stop_environments_service.rb","lines":{"begin":7,"end":18}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"617800a52fa424a1bcea1ed6a62b6793","location":{"path":"app/services/ci/register_job_service.rb","lines":{"begin":19,"end":66}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `execute` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"3c427dfa0dd24ca8d0170b6247260b87","location":{"path":"app/services/ci/register_job_service.rb","lines":{"begin":19,"end":66}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `process_label_ids` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d322faf3023b3e313c8abe2020cf59af","location":{"path":"app/services/issuable_base_service.rb","lines":{"begin":96,"end":111}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `update` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"139f887d96d46ca70a22e378422f8bc7","location":{"path":"app/services/issuable_base_service.rb","lines":{"begin":172,"end":224}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `IssuableBaseService` has 30 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"906133099e33d0679f4b8c65cc1eef9b","location":{"path":"app/services/issuable_base_service.rb","lines":{"begin":3,"end":319}},"other_locations":[],"remediation_points":2200000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `update` has 37 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"009042d6d3df2763254c61f2b3d8536c","location":{"path":"app/services/issuable_base_service.rb","lines":{"begin":172,"end":224}},"other_locations":[],"remediation_points":888000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `build_event_data` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"181f03475858936500cb1903a2981922","location":{"path":"app/services/system_hooks_service.rb","lines":{"begin":22,"end":70}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `build_event_name` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"58fb30a590bb73d7a7c014c15cff2f61","location":{"path":"app/services/system_hooks_service.rb","lines":{"begin":72,"end":83}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `build_event_data` has 41 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"cb1f235466d69ba0f51ae5082e6ccd1b","location":{"path":"app/services/system_hooks_service.rb","lines":{"begin":22,"end":70}},"other_locations":[],"remediation_points":984000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `include_any_scope?` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c3b269346955ff77f7af249761778c5f","location":{"path":"app/services/access_token_validation_service.rb","lines":{"begin":33,"end":48}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b944cb228f06d17cfab396e042f46404","location":{"path":"app/services/create_deployment_service.rb","lines":{"begin":15,"end":29}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2a911c4e00c978f2c3dee8a80d2b123c","location":{"path":"app/services/members/destroy_service.rb","lines":{"begin":5,"end":23}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3e17107f5166483e06d9a3aa43ce4057","location":{"path":"app/services/delete_branch_service.rb","lines":{"begin":4,"end":23}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `can_be_resolved_in_ui?` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"303b72ed1619302f77225ae41471638d","location":{"path":"app/services/merge_requests/conflicts/list_service.rb","lines":{"begin":15,"end":23}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `reload_merge_requests` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a105139484033c8e7ced10c6ce36e8db","location":{"path":"app/services/merge_requests/refresh_service.rb","lines":{"begin":80,"end":106}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find_new_commits` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"851ed172a4510d8303c8caf10c7c09e1","location":{"path":"app/services/merge_requests/refresh_service.rb","lines":{"begin":119,"end":141}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `trigger` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8627834675a31ad536bf412edaafd7e7","location":{"path":"app/services/merge_requests/merge_when_pipeline_succeeds_service.rb","lines":{"begin":24,"end":33}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4cd7f00168c6c916f0dc7075f0ca3349","location":{"path":"app/services/merge_requests/merge_service.rb","lines":{"begin":17,"end":37}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"35e1a81d921bd211a80412b3021d8f1f","location":{"path":"app/services/merge_requests/create_from_issue_service.rb","lines":{"begin":16,"end":31}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate_branches` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"629d86725d56fa929caf501972ac7cf2","location":{"path":"app/services/merge_requests/build_service.rb","lines":{"begin":92,"end":97}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `BuildService` has 22 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"0955c9bbce7bc1720631a8dc579bbf5f","location":{"path":"app/services/merge_requests/build_service.rb","lines":{"begin":4,"end":208}},"other_locations":[],"remediation_points":1400000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `get_branches` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7e605b474bb1fb7b66f5bfbaf51d3c6d","location":{"path":"app/services/merge_requests/get_urls_service.rb","lines":{"begin":33,"end":50}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `handle_changes` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"cefad5ecb48fbecc8f4fa6ba026659f8","location":{"path":"app/services/merge_requests/update_service.rb","lines":{"begin":27,"end":78}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `handle_changes` has 42 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"db391ef0b97408393fd716be0c7356dd","location":{"path":"app/services/merge_requests/update_service.rb","lines":{"begin":27,"end":78}},"other_locations":[],"remediation_points":1008000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `commit_status_merge_requests` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"784a58094574fa35608fca082c2548e7","location":{"path":"app/services/merge_requests/base_service.rb","lines":{"begin":76,"end":85}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `interpret_service.rb` has 596 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"83735b0b7c1f8d22c40f49e709c57e70","location":{"path":"app/services/quick_actions/interpret_service.rb","lines":{"begin":3,"end":700}},"other_locations":[],"remediation_points":6182400,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b08fd2ee935cfed15e0505bb9af417b4","location":{"path":"app/services/discussions/update_diff_position_service.rb","lines":{"begin":5,"end":34}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"dcb90a6db168562206b2356716e752b6","location":{"path":"app/services/git_push_service.rb","lines":{"begin":24,"end":65}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `index` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8b2781e6841d5d63745094c685fcd1e8","location":{"path":"app/controllers/groups/children_controller.rb","lines":{"begin":6,"end":29}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `index` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3169a6c4ee72f03a1318dedbed6b40ff","location":{"path":"app/controllers/groups/group_members_controller.rb","lines":{"begin":17,"end":39}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `failure_message` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e3605869f669f4cb85ba66bdd5b04c7a","location":{"path":"app/controllers/omniauth_callbacks_controller.rb","lines":{"begin":30,"end":38}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `omniauth_flow` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8cf6a8a0fd40eb5ff273cc6dba558403","location":{"path":"app/controllers/omniauth_callbacks_controller.rb","lines":{"begin":77,"end":95}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `sign_in_user_flow` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e780968a46460e3b3fe11a34ddfc0c00","location":{"path":"app/controllers/omniauth_callbacks_controller.rb","lines":{"begin":115,"end":136}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `OmniauthCallbacksController` has 22 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"af6b190bf330da08acbe854817a6812f","location":{"path":"app/controllers/omniauth_callbacks_controller.rb","lines":{"begin":3,"end":192}},"other_locations":[],"remediation_points":1400000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `impersonate` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f01a1ec9614ccf1b226a3e42206b203b","location":{"path":"app/controllers/admin/users_controller.rb","lines":{"begin":33,"end":56}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `update` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"af47e69f6ee053a6f226de336934f214","location":{"path":"app/controllers/admin/users_controller.rb","lines":{"begin":118,"end":147}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `UsersController` has 23 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"bb3ecebd549737d88ffb4ea7b2d02d16","location":{"path":"app/controllers/admin/users_controller.rb","lines":{"begin":3,"end":230}},"other_locations":[],"remediation_points":1500000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `show` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4d5e93c6a88076ccc249e69590f05f53","location":{"path":"app/controllers/admin/system_info_controller.rb","lines":{"begin":34,"end":57}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `show` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6c80ea5d1d0a024abdc38fba56cb8435","location":{"path":"app/controllers/concerns/uploads_actions.rb","lines":{"begin":35,"end":48}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `send_blob` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"cfa9da0619389a51f42df3b51bf5c65c","location":{"path":"app/controllers/concerns/sends_blob.rb","lines":{"begin":11,"end":25}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `leave` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1f6860cf601d992df6f0af95d95748a0","location":{"path":"app/controllers/concerns/membership_actions.rb","lines":{"begin":63,"end":82}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `set_issuables_index` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f415a6c750063cabd8f90d48e98e5eb0","location":{"path":"app/controllers/concerns/issuable_collections.rb","lines":{"begin":17,"end":38}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `authenticate_with_two_factor` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"36f3a297fab9a3ef0e526b7f851741b2","location":{"path":"app/controllers/concerns/authenticates_with_two_factor.rb","lines":{"begin":43,"end":54}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `safe_redirect_path` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"36420be74fc50045ef291eb40a71bb77","location":{"path":"app/controllers/concerns/internal_redirect.rb","lines":{"begin":6,"end":17}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `safe_redirect_path_for_url` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d5b751dbd9dd362815b574f1cb52225a","location":{"path":"app/controllers/concerns/internal_redirect.rb","lines":{"begin":19,"end":26}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `note_json` has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring.","fingerprint":"273ea02f6c72cced154034c12207d3f1","location":{"path":"app/controllers/concerns/notes_actions.rb","lines":{"begin":104,"end":146}},"other_locations":[],"remediation_points":1050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `diff_discussion_html` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"62bc37c3eb9f037889edcbe39ef53aa6","location":{"path":"app/controllers/concerns/notes_actions.rb","lines":{"begin":148,"end":174}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `note_project` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"573f594e00ed6b29987ce9e763457833","location":{"path":"app/controllers/concerns/notes_actions.rb","lines":{"begin":239,"end":256}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `note_json` has 34 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"2572ca1fa7eb27c9668322b7a098f02a","location":{"path":"app/controllers/concerns/notes_actions.rb","lines":{"begin":104,"end":146}},"other_locations":[],"remediation_points":816000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `recaptcha_check_with_fallback` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f5ab9c6deb983a187870f912e14afaea","location":{"path":"app/controllers/concerns/spammable_actions.rb","lines":{"begin":29,"end":54}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create_commit` has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring.","fingerprint":"832aa36f617c6cce4927e6c8b561ce98","location":{"path":"app/controllers/concerns/creates_commit.rb","lines":{"begin":8,"end":51}},"other_locations":[],"remediation_points":1050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `update_flash_notice` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"89030f5b74776bb2425f95279fdd5b7d","location":{"path":"app/controllers/concerns/creates_commit.rb","lines":{"begin":62,"end":73}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `final_success_path` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"afb1305c0c32730e0b027be235b174a0","location":{"path":"app/controllers/concerns/creates_commit.rb","lines":{"begin":75,"end":83}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `create_commit` has 35 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"eaa2bdf0bf7bb61da1f37f4031392e35","location":{"path":"app/controllers/concerns/creates_commit.rb","lines":{"begin":8,"end":51}},"other_locations":[],"remediation_points":840000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `send_upload` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"cfa021a786ee32f97584fecedce60cde","location":{"path":"app/controllers/concerns/send_file_upload.rb","lines":{"begin":4,"end":26}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `lfs_check_access!` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"46d5167d71a5e6a69a9a236086347aed","location":{"path":"app/controllers/concerns/lfs_request.rb","lines":{"begin":36,"end":45}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"905d81937e68b3931dad7416dc6ef9a6","location":{"path":"app/controllers/import/bitbucket_controller.rb","lines":{"begin":37,"end":65}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"20b781fcddc55e961f42441c445d70d8","location":{"path":"app/controllers/import/github_controller.rb","lines":{"begin":39,"end":58}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `GithubController` has 22 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"ab20d51ced6ac78aa49e0f6de0af0ac0","location":{"path":"app/controllers/import/github_controller.rb","lines":{"begin":1,"end":132}},"other_locations":[],"remediation_points":1400000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find_or_create_namespace` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2f80525d40e648a6d7ea2229b2cb74ae","location":{"path":"app/controllers/import/base_controller.rb","lines":{"begin":19,"end":31}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4d4ab07c39a5534d15b7443e37a7a235","location":{"path":"app/controllers/import/bitbucket_server_controller.rb","lines":{"begin":21,"end":45}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate_import_params` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"da2d51f606c44590f847c4640444ac5b","location":{"path":"app/controllers/import/bitbucket_server_controller.rb","lines":{"begin":82,"end":90}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `callback` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3c9e710a6531242212414756cccfe915","location":{"path":"app/controllers/import/google_code_controller.rb","lines":{"begin":8,"end":33}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `check_captcha` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"de5a9e305854d86a525c3be0d27eaf6d","location":{"path":"app/controllers/sessions_controller.rb","lines":{"begin":62,"end":78}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `auto_sign_in_with_provider` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f619928e9105c1311e52540b45817001","location":{"path":"app/controllers/sessions_controller.rb","lines":{"begin":167,"end":186}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `SessionsController` has 23 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"ca547cff8dfcb4f2bb32febd07c3a8b9","location":{"path":"app/controllers/sessions_controller.rb","lines":{"begin":3,"end":221}},"other_locations":[],"remediation_points":1500000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"44af899cceadececa5fb2d6343c42fb8","location":{"path":"app/controllers/registrations_controller.rb","lines":{"begin":16,"end":36}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `index` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"07120d763a5a37d3563d108da7618fc2","location":{"path":"app/controllers/snippets_controller.rb","lines":{"begin":30,"end":43}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `show` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"19fe68118b5b1cf2a9c1bfef20064546","location":{"path":"app/controllers/projects/wikis_controller.rb","lines":{"begin":20,"end":44}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `update` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4754ebccd6eb3ba307dee978dd12dde8","location":{"path":"app/controllers/projects/wikis_controller.rb","lines":{"begin":49,"end":65}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `merge_requests_controller.rb` has 265 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"ed0fbac1699084d99f2798b9ff54b642","location":{"path":"app/controllers/projects/merge_requests_controller.rb","lines":{"begin":1,"end":354}},"other_locations":[],"remediation_points":1416000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `show` has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f6d989eecff0a311d8a4126b524b3d54","location":{"path":"app/controllers/projects/merge_requests_controller.rb","lines":{"begin":30,"end":76}},"other_locations":[],"remediation_points":1050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `update` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"043aac3b7446fd75e17405d975137865","location":{"path":"app/controllers/projects/merge_requests_controller.rb","lines":{"begin":123,"end":145}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `ci_environments_status` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"46e544b6af20509fb22aa245f36e853b","location":{"path":"app/controllers/projects/merge_requests_controller.rb","lines":{"begin":204,"end":242}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `merge!` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5c7d0579b3b6ee7f277ab6932678009d","location":{"path":"app/controllers/projects/merge_requests_controller.rb","lines":{"begin":285,"end":319}},"other_locations":[],"remediation_points":850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `MergeRequestsController` has 28 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"b062a438177acc72625495d3cbfaa77c","location":{"path":"app/controllers/projects/merge_requests_controller.rb","lines":{"begin":1,"end":354}},"other_locations":[],"remediation_points":2000000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `show` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"e3c966096d2b12e85a670db7911707b8","location":{"path":"app/controllers/projects/merge_requests_controller.rb","lines":{"begin":30,"end":76}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `ci_environments_status` has 32 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"e5b7f8ffd1531062cbb97dd163687759","location":{"path":"app/controllers/projects/merge_requests_controller.rb","lines":{"begin":204,"end":242}},"other_locations":[],"remediation_points":768000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `set_commits` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e6d95cec8ea5cbbfb499acf2d8c47bb9","location":{"path":"app/controllers/projects/commits_controller.rb","lines":{"begin":55,"end":69}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `archive` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"24b42f263d62dd73163666f08a5dab84","location":{"path":"app/controllers/projects/repositories_controller.rb","lines":{"begin":16,"end":28}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create` has a Cognitive Complexity of 17 (exceeds 5 allowed). Consider refactoring.","fingerprint":"48f2140ee4baa6d602990f3cd3a4e3bd","location":{"path":"app/controllers/projects/branches_controller.rb","lines":{"begin":52,"end":91}},"other_locations":[],"remediation_points":1350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `create` has 32 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"7b53414d925313d554a03dbde87a17b1","location":{"path":"app/controllers/projects/branches_controller.rb","lines":{"begin":52,"end":91}},"other_locations":[],"remediation_points":768000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `authenticate_user` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"aeab90a0370c820e728a3abfbc25b413","location":{"path":"app/controllers/projects/git_http_client_controller.rb","lines":{"begin":30,"end":59}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `update` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"59245dcb34ab6bc8f9698502300494c2","location":{"path":"app/controllers/projects/mirrors_controller.rb","lines":{"begin":15,"end":34}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `resolve` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"43486b045d4b1186318cfc251852d98f","location":{"path":"app/controllers/projects/notes_controller.rb","lines":{"begin":21,"end":36}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `unresolve` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"687318ee4eb16a33452c1f37b2c881a0","location":{"path":"app/controllers/projects/notes_controller.rb","lines":{"begin":38,"end":52}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"31c48fb29d257a60073d2b38d6e1cb4d","location":{"path":"app/controllers/projects/forks_controller.rb","lines":{"begin":39,"end":60}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `index` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"a118caadbf010e6edb81311d4382716d","location":{"path":"app/controllers/projects/pipelines_controller.rb","lines":{"begin":12,"end":44}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `show` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3abec97b27020fca915a84ac93bc67d6","location":{"path":"app/controllers/projects/imports_controller.rb","lines":{"begin":23,"end":39}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4da2f2dd27d4fd213b9f9f2f1a5cd41f","location":{"path":"app/controllers/projects/group_links_controller.rb","lines":{"begin":10,"end":22}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `service_test_response` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bca34a40fb26a815c60df6fd1e7dba51","location":{"path":"app/controllers/projects/services_controller.rb","lines":{"begin":36,"end":51}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `metrics` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"519adc463f2dd3de5cb94580d7f50383","location":{"path":"app/controllers/projects/deployments_controller.rb","lines":{"begin":15,"end":26}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `additional_metrics` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8c4f6fc892643a150dc844973ad4d976","location":{"path":"app/controllers/projects/deployments_controller.rb","lines":{"begin":28,"end":42}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `add_match_line` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"07c854b446b4087e5ee7892172f74ee7","location":{"path":"app/controllers/projects/blob_controller.rb","lines":{"begin":133,"end":149}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `blob` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b6f7a07f247048d784135038dce26244","location":{"path":"app/controllers/projects/blob_controller.rb","lines":{"begin":151,"end":165}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `editor_variables` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"cfcc7b49429c64315cf6da835ec8bede","location":{"path":"app/controllers/projects/blob_controller.rb","lines":{"begin":192,"end":221}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `BlobController` has 21 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"c1e63be99f08c204815ffecf3dd4b66c","location":{"path":"app/controllers/projects/blob_controller.rb","lines":{"begin":2,"end":284}},"other_locations":[],"remediation_points":1300000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `show` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"979438a3332d8f5f08717dc86472299b","location":{"path":"app/controllers/projects/tree_controller.rb","lines":{"begin":13,"end":47}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `show` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"806fa8153a8d1eb022e92afcd4601d91","location":{"path":"app/controllers/projects/tree_controller.rb","lines":{"begin":13,"end":47}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `raw` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e4f02dd301b3eeb842d85c37f20bae2e","location":{"path":"app/controllers/projects/jobs_controller.rb","lines":{"begin":126,"end":140}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `JobsController` has 21 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"6f969a368940183e4fce1acd28147f56","location":{"path":"app/controllers/projects/jobs_controller.rb","lines":{"begin":1,"end":189}},"other_locations":[],"remediation_points":1300000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find_merge_request_diff_compare` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"91ff93d1ec72c5ce3a260ca7bb0355a1","location":{"path":"app/controllers/projects/merge_requests/diffs_controller.rb","lines":{"begin":47,"end":73}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `download_objects!` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b7b7331d3cec46b88359e5648ed2f9a2","location":{"path":"app/controllers/projects/lfs_api_controller.rb","lines":{"begin":52,"end":68}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `ClustersController` has 22 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"964ab09026b9448f413a95a5f6094e09","location":{"path":"app/controllers/projects/clusters_controller.rb","lines":{"begin":1,"end":222}},"other_locations":[],"remediation_points":1400000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `move` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ae70ac550f5ace969dc34ad430e1a506","location":{"path":"app/controllers/projects/issues_controller.rb","lines":{"begin":95,"end":113}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `IssuesController` has 21 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"09358857b8d0a59b5b0f1efabe1eb312","location":{"path":"app/controllers/projects/issues_controller.rb","lines":{"begin":1,"end":251}},"other_locations":[],"remediation_points":1300000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `ensure_root_container_repository!` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a31d8c82827ad31ea06cbe929b5bcb9e","location":{"path":"app/controllers/projects/registry/repositories_controller.rb","lines":{"begin":39,"end":47}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `get_keys` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e98b2fc794e033c8a48c3ee0becb6ada","location":{"path":"app/controllers/profiles/keys_controller.rb","lines":{"begin":36,"end":51}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `show` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7fac5d70e69bf9664ceb8d865c808fa2","location":{"path":"app/controllers/profiles/two_factor_auths_controller.rb","lines":{"begin":4,"end":40}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `show` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"053f896df50c58d1c5a7f874e0cf72c3","location":{"path":"app/controllers/profiles/two_factor_auths_controller.rb","lines":{"begin":4,"end":40}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `new` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"17c6af74d7968b2ff43b8ab9795a3e8a","location":{"path":"app/controllers/oauth/authorizations_controller.rb","lines":{"begin":6,"end":18}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `projects_controller.rb` has 328 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"ed6bb55f0c75667bbb0ec51d3c2664cf","location":{"path":"app/controllers/projects_controller.rb","lines":{"begin":3,"end":436}},"other_locations":[],"remediation_points":2323200,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `refs` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4477c3a607082b3d28aae895558786dd","location":{"path":"app/controllers/projects_controller.rb","lines":{"begin":241,"end":274}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `render_landing_page` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"278be4b0b74df103253b6e3205fb8a62","location":{"path":"app/controllers/projects_controller.rb","lines":{"begin":281,"end":298}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `ProjectsController` has 37 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"8090aa2673614a81e71589f7753eff30","location":{"path":"app/controllers/projects_controller.rb","lines":{"begin":3,"end":436}},"other_locations":[],"remediation_points":2900000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `project_params_attributes` has 37 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"2fdc2a483f87578ca62a61a751d113d7","location":{"path":"app/controllers/projects_controller.rb","lines":{"begin":331,"end":370}},"other_locations":[],"remediation_points":888000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `render_check_results` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ba1563517e02434643d39267194f528e","location":{"path":"app/controllers/health_controller.rb","lines":{"begin":39,"end":56}},"other_locations":[],"remediation_points":850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `show` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f7c994d83ef228aa163c05179f06d2fd","location":{"path":"app/controllers/help_controller.rb","lines":{"begin":23,"end":57}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `clean_path_info` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5db34152511808356524914b64cf554b","location":{"path":"app/controllers/help_controller.rb","lines":{"begin":82,"end":107}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `application_controller.rb` has 341 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"f029769395ddcac92c2b8d2ca3b05b28","location":{"path":"app/controllers/application_controller.rb","lines":{"begin":3,"end":465}},"other_locations":[],"remediation_points":2510400,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `ldap_security_check` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"523cc3bb278c788d5848949c8c3dead7","location":{"path":"app/controllers/application_controller.rb","lines":{"begin":262,"end":272}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `enforce_terms!` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d14876e741b595110a644395f1230e14","location":{"path":"app/controllers/application_controller.rb","lines":{"begin":318,"end":339}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `ApplicationController` has 53 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"d63945970dce3ed1ef2b7634b214a4e9","location":{"path":"app/controllers/application_controller.rb","lines":{"begin":6,"end":465}},"other_locations":[],"remediation_points":4500000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `users_select_tag` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a108342e6dd48ba76731363b84661eaf","location":{"path":"app/helpers/selects_helper.rb","lines":{"begin":4,"end":26}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `users_select_data_attributes` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a8bad651f6dba343e0468fd0003dd784","location":{"path":"app/helpers/selects_helper.rb","lines":{"begin":74,"end":85}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `show_last_push_widget?` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2f5475afeb1122f3cfa25ac5955cbb27","location":{"path":"app/helpers/application_helper.rb","lines":{"begin":70,"end":86}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `visible_attributes` has 119 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"17f189b8fca7fc3b1f8a420a4bcbda19","location":{"path":"app/helpers/application_settings_helper.rb","lines":{"begin":146,"end":266}},"other_locations":[],"remediation_points":2856000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `toggle_award_url` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d69f1bff0994f6e3441f85f3f11d5bbe","location":{"path":"app/helpers/award_emoji_helper.rb","lines":{"begin":4,"end":17}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `page_gutter_class` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e65e525a4333beebdf83e031e767ef28","location":{"path":"app/helpers/nav_helper.rb","lines":{"begin":21,"end":39}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `get_header_links` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f16a544d112fad89ba71d21c6d5db6a3","location":{"path":"app/helpers/nav_helper.rb","lines":{"begin":55,"end":75}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `diff_match_line` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b869dd8c4eaef5740ed1f255a8f1fbf1","location":{"path":"app/helpers/diff_helper.rb","lines":{"begin":37,"end":57}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `parallel_diff_discussions` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8ca093d3db0a23030593eb120a3b43fd","location":{"path":"app/helpers/diff_helper.rb","lines":{"begin":69,"end":85}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `active_nav_link?` has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a16ad6a8f13c9288d42920124805df7f","location":{"path":"app/helpers/tab_helper.rb","lines":{"begin":75,"end":104}},"other_locations":[],"remediation_points":1050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `user_status` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1c1f76f6143eff8d1d22a334a235fd12","location":{"path":"app/helpers/users_helper.rb","lines":{"begin":55,"end":71}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `namespaces_options` has a Cognitive Complexity of 20 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7abb679aa0b2ea21e01c24880d3bf77c","location":{"path":"app/helpers/namespaces_helper.rb","lines":{"begin":9,"end":45}},"other_locations":[],"remediation_points":1650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `options_for_group` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1e8e66fbb82bdafdc25047aa1524869b","location":{"path":"app/helpers/namespaces_helper.rb","lines":{"begin":71,"end":86}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `namespaces_options` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"d1da7571d4cd35e4edcc84ea6e21ec17","location":{"path":"app/helpers/namespaces_helper.rb","lines":{"begin":9,"end":45}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `submodule_links` has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring.","fingerprint":"592e98a3099ca8bf38ff5b45bcb0dffb","location":{"path":"app/helpers/submodule_helper.rb","lines":{"begin":9,"end":47}},"other_locations":[],"remediation_points":1050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `submodule_links` has 32 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"c06e0c3ec596b1cdfd2de6f634cd6b86","location":{"path":"app/helpers/submodule_helper.rb","lines":{"begin":9,"end":47}},"other_locations":[],"remediation_points":768000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `remove_member_message` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bba34164517c03c61579ce09b9d98bb9","location":{"path":"app/helpers/members_helper.rb","lines":{"begin":4,"end":22}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `chunk_snippet` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"de18ceb549965f7ea862a8c0dc960bea","location":{"path":"app/helpers/snippets_helper.rb","lines":{"begin":64,"end":105}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `labels_filter_path` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9d39f54cf4cda251c101014a6f4c7244","location":{"path":"app/helpers/labels_helper.rb","lines":{"begin":134,"end":149}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `label_status_tooltip` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"64c9182b39df4fa2de87d8d55c2d2cbc","location":{"path":"app/helpers/labels_helper.rb","lines":{"begin":216,"end":222}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `event_feed_title` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0ae609cca64a854e8b692dd72db01e13","location":{"path":"app/helpers/events_helper.rb","lines":{"begin":78,"end":102}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `event_feed_url` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f99a06ad5d757ef02870ca23d95676bc","location":{"path":"app/helpers/events_helper.rb","lines":{"begin":104,"end":122}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `push_event_feed_url` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0a4c5fb26657f91ff277b7ef0d13c32d","location":{"path":"app/helpers/events_helper.rb","lines":{"begin":124,"end":138}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `discussion_path` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f8fcc6a280f6df449c018435d3f92438","location":{"path":"app/helpers/notes_helper.rb","lines":{"begin":77,"end":92}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `clipboard_button` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c29991b281e121dc435a356a600e4e1e","location":{"path":"app/helpers/button_helper.rb","lines":{"begin":22,"end":59}},"other_locations":[],"remediation_points":850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `dropdown_item_with_description` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8d5076e20cc132338854d62653cd1df8","location":{"path":"app/helpers/button_helper.rb","lines":{"begin":88,"end":97}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `clipboard_button` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"97e66a0f68fa32b384f734ea55e5e044","location":{"path":"app/helpers/button_helper.rb","lines":{"begin":22,"end":59}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `dropdown_tag` has a Cognitive Complexity of 26 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4267997c227f431d5c46888b32748d75","location":{"path":"app/helpers/dropdowns_helper.rb","lines":{"begin":4,"end":41}},"other_locations":[],"remediation_points":2250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `dropdown_toggle` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7a5dbb87125de6801bd8e3f421ea8d82","location":{"path":"app/helpers/dropdowns_helper.rb","lines":{"begin":43,"end":50}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `dropdown_tag` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"5365287d8861b3ecac3eb84417018a2b","location":{"path":"app/helpers/dropdowns_helper.rb","lines":{"begin":4,"end":41}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `sprite_icon` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b288e014419e55f1aa86631629c79889","location":{"path":"app/helpers/icons_helper.rb","lines":{"begin":44,"end":56}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `file_type_icon_class` has 37 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"2ddea2c28588a85667f5b5399507ff46","location":{"path":"app/helpers/icons_helper.rb","lines":{"begin":109,"end":151}},"other_locations":[],"remediation_points":888000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `commit_action_link` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8657821ad7a6c0ec4e6398a6aee36f9c","location":{"path":"app/helpers/commits_helper.rb","lines":{"begin":161,"end":181}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `todo_target_path` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d03a4561eaff01e66db146018ad0c969","location":{"path":"app/helpers/todos_helper.rb","lines":{"begin":39,"end":54}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `todo_due_date` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"db4163fb6bc594c0c7f5188d10a94d61","location":{"path":"app/helpers/todos_helper.rb","lines":{"begin":141,"end":160}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `url_for_issue` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b77357907fc65f32d6adebdec5c99e74","location":{"path":"app/helpers/issues_helper.rb","lines":{"begin":18,"end":32}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `path_breadcrumbs` has a Cognitive Complexity of 15 (exceeds 5 allowed). Consider refactoring.","fingerprint":"309df9fc4689b2f5fb71f6534a5efd03","location":{"path":"app/helpers/tree_helper.rb","lines":{"begin":105,"end":121}},"other_locations":[],"remediation_points":1150000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `edit_fork_button_tag` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"2b6c57301b36358581b2491652866c44","location":{"path":"app/helpers/blob_helper.rb","lines":{"begin":302,"end":302}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `edit_button_tag` has 6 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"723d5e25e5499349ff424fa5046927f1","location":{"path":"app/helpers/blob_helper.rb","lines":{"begin":318,"end":318}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `modify_file_button` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4b6850840a5430937e584328e518311d","location":{"path":"app/helpers/blob_helper.rb","lines":{"begin":51,"end":69}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `blob_raw_url` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b8466fa1a816b27c99638fe228016597","location":{"path":"app/helpers/blob_helper.rb","lines":{"begin":119,"end":131}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `edit_button_tag` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"93c71a130633cfcebe91bcda32798413","location":{"path":"app/helpers/blob_helper.rb","lines":{"begin":318,"end":327}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `projects_helper.rb` has 438 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"a3d8d9970bc1e29fb6cf0845a8963a35","location":{"path":"app/helpers/projects_helper.rb","lines":{"begin":3,"end":555}},"other_locations":[],"remediation_points":3907200,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `link_to_member` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"92e14b6f78cd2026911faaf78829ba53","location":{"path":"app/helpers/projects_helper.rb","lines":{"begin":49,"end":73}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `project_title` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2ebe86c74e8aaea024bada46109f4e9a","location":{"path":"app/helpers/projects_helper.rb","lines":{"begin":75,"end":93}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `get_project_nav_tabs` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8c4c2cc0402179e15ec7cff7acf71f67","location":{"path":"app/helpers/projects_helper.rb","lines":{"begin":266,"end":300}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `disallowed_project_visibility_level_description` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"cde9c43b6e33582ebc01be9dcc6b0cc6","location":{"path":"app/helpers/visibility_level_helper.rb","lines":{"begin":84,"end":102}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `disallowed_group_visibility_level_description` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c964b53a81590235d500b10d64921ffc","location":{"path":"app/helpers/visibility_level_helper.rb","lines":{"begin":106,"end":128}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `webpack_controller_bundle_tags` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d1915400e4cdf8101f80cf09fcaa41a8","location":{"path":"app/helpers/webpack_helper.rb","lines":{"begin":8,"end":34}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `webpack_entrypoint_paths` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2059057b0a4c8c172104d3a69b6d33a1","location":{"path":"app/helpers/webpack_helper.rb","lines":{"begin":36,"end":57}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `webpack_public_host` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5187936b625c537cc83fe49f935245ac","location":{"path":"app/helpers/webpack_helper.rb","lines":{"begin":59,"end":68}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `milestone_class_for_state` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9f98077e679dcc8bdc4adbc9fc03e111","location":{"path":"app/helpers/milestones_helper.rb","lines":{"begin":71,"end":79}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `milestone_time_for` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7e9f0e967afa3a497b80340cf11b095e","location":{"path":"app/helpers/milestones_helper.rb","lines":{"begin":122,"end":144}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `milestone_date_range` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4843496f3de8ac4a890951c97d469064","location":{"path":"app/helpers/milestones_helper.rb","lines":{"begin":181,"end":197}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `share_with_group_lock_help_text` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ff00375205d66e384de0e3f33ec7d0d7","location":{"path":"app/helpers/groups_helper.rb","lines":{"begin":96,"end":108}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `group_title_link` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"98657f045e5336754e6eae56e789418f","location":{"path":"app/helpers/groups_helper.rb","lines":{"begin":141,"end":146}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `ci_icon_for_status` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"7c3efeba2a30134025307449a05b2f77","location":{"path":"app/helpers/ci_status_helper.rb","lines":{"begin":61,"end":91}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `sorting_helper.rb` has 302 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"01923968066dde38b1a1f78557e3aa84","location":{"path":"app/helpers/sorting_helper.rb","lines":{"begin":3,"end":382}},"other_locations":[],"remediation_points":1948800,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `link_to_html` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7a4d4827db929df3ce6e16fb4d0b9522","location":{"path":"app/helpers/markup_helper.rb","lines":{"begin":45,"end":69}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `first_line_in_markdown` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a45a636cd6cfd627a9b9cb575482d665","location":{"path":"app/helpers/markup_helper.rb","lines":{"begin":75,"end":92}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `render_wiki_content` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f59f576a0875d3e1b3150c35d4244f1f","location":{"path":"app/helpers/markup_helper.rb","lines":{"begin":124,"end":148}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `markup_unsafe` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0f734634b0f84e17e369619da7591cc9","location":{"path":"app/helpers/markup_helper.rb","lines":{"begin":150,"end":166}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `truncate_visible` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7de1befc5006684b8aac21b36b5a2eee","location":{"path":"app/helpers/markup_helper.rb","lines":{"begin":198,"end":229}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `truncate_if_block` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c65f7114f8bc0ff0c40ba17a721dc4e7","location":{"path":"app/helpers/markup_helper.rb","lines":{"begin":234,"end":243}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `issuables_helper.rb` has 354 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"b0534175d956cb265e089add14a703e9","location":{"path":"app/helpers/issuables_helper.rb","lines":{"begin":3,"end":436}},"other_locations":[],"remediation_points":2697600,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `multi_label_name` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f6f2aa839b3380e86377b58408fcfa15","location":{"path":"app/helpers/issuables_helper.rb","lines":{"begin":40,"end":51}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `issuable_labels_tooltip` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6ed7317a98ede04c4a1cde7f6af1871c","location":{"path":"app/helpers/issuables_helper.rb","lines":{"begin":208,"end":219}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `issuable_todo_button_data` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"382bc77616cd06810f3d2112c8460240","location":{"path":"app/helpers/issuables_helper.rb","lines":{"begin":381,"end":395}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `project_policy.rb` has 333 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"61f7a144aa6cdf7e965d3130c52aacc3","location":{"path":"app/policies/project_policy.rb","lines":{"begin":3,"end":434}},"other_locations":[],"remediation_points":2395200,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `remaining_days_in_words` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"db6e21e4091f24644db9efa04f03f5f2","location":{"path":"app/serializers/entity_date_helper.rb","lines":{"begin":47,"end":70}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `build_metrics` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"fe3dd187f741789f765000b6e08c77bf","location":{"path":"app/serializers/merge_request_widget_entity.rb","lines":{"begin":252,"end":260}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `reassigned_issue_email` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"3e2a4c8e9b4b5584a258cdc21bf1779b","location":{"path":"app/mailers/emails/issues.rb","lines":{"begin":23,"end":23}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `relabeled_issue_email` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"eccd65b7da076099478491ce5ffd1bcd","location":{"path":"app/mailers/emails/issues.rb","lines":{"begin":40,"end":40}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `issue_status_changed_email` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"8d347450b4f4fa27b8d847a4e282b8f2","location":{"path":"app/mailers/emails/issues.rb","lines":{"begin":48,"end":48}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `issue_moved_email` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"a1fb6126b5a4051ae7af19c5fd1ea1ef","location":{"path":"app/mailers/emails/issues.rb","lines":{"begin":56,"end":56}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `reassigned_merge_request_email` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"8bd5f4e62d9db3075aa99840c56f1dc3","location":{"path":"app/mailers/emails/merge_requests.rb","lines":{"begin":26,"end":26}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `relabeled_merge_request_email` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"e4fbe646413819b74d51d11132d24f75","location":{"path":"app/mailers/emails/merge_requests.rb","lines":{"begin":34,"end":34}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `merge_request_status_email` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"c39ada600f20e34ac7bc271aaa17a489","location":{"path":"app/mailers/emails/merge_requests.rb","lines":{"begin":55,"end":55}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `NotifyPreview` has 26 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"0ad28a90a453e7f0892e2fa27ca7dd74","location":{"path":"app/mailers/previews/notify_preview.rb","lines":{"begin":3,"end":176}},"other_locations":[],"remediation_points":1800000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `perform` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"ae09aa8f81cc51243569392f706dea8b","location":{"path":"app/workers/irker_worker.rb","lines":{"begin":9,"end":9}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `send_branch_updates` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"2efa6a64aab186fa6e22c887b82c2da8","location":{"path":"app/workers/irker_worker.rb","lines":{"begin":61,"end":61}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `send_commits` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"bda830a07ed575bd9c98deb67e6efa84","location":{"path":"app/workers/irker_worker.rb","lines":{"begin":84,"end":84}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `send_commits_count` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"fe8fcb808f2da3f31174330b3b8e8d2f","location":{"path":"app/workers/irker_worker.rb","lines":{"begin":113,"end":113}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `process_commit_message` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"0cbd58f4d824762ee08cbe8394a955be","location":{"path":"app/workers/process_commit_worker.rb","lines":{"begin":36,"end":36}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `close_issues` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"0ddd5587d752e08728eca56e8b842057","location":{"path":"app/workers/process_commit_worker.rb","lines":{"begin":45,"end":45}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `perform` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"00fda5cf89ca2d06f32e73e5948d2d96","location":{"path":"app/workers/process_commit_worker.rb","lines":{"begin":18,"end":33}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `perform` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b2d21175bd49ce0560d00b41a5d4b105","location":{"path":"app/workers/emails_on_push_worker.rb","lines":{"begin":8,"end":78}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `perform` has 58 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"21b177b9c8aab67c1dd18ac4736d07e0","location":{"path":"app/workers/emails_on_push_worker.rb","lines":{"begin":8,"end":78}},"other_locations":[],"remediation_points":1392000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `perform` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bc6bfd63748977ec6b13ad1bcd32f3e0","location":{"path":"app/workers/repository_import_worker.rb","lines":{"begin":9,"end":30}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `perform` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"ac08a8c45d58e80f3f9f0e821af8c678","location":{"path":"app/workers/create_pipeline_worker.rb","lines":{"begin":9,"end":9}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `sanity_check!` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1e3c40adf8befa842892c33a2ef33ef6","location":{"path":"app/workers/object_storage/migrate_uploads_worker.rb","lines":{"begin":71,"end":81}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `perform` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5767377fdd633dc52d45bb5edaf792ad","location":{"path":"app/workers/object_storage/background_move_worker.rb","lines":{"begin":10,"end":21}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `perform` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"873b9f464ca14204612b7168bd6cd51a","location":{"path":"app/workers/repository_update_remote_mirror_worker.rb","lines":{"begin":18,"end":42}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `perform_repository_checks` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c569f618db6dab9061d1c9a4fbd00161","location":{"path":"app/workers/repository_check/batch_worker.rb","lines":{"begin":34,"end":49}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `perform` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"fb73a85eb279eea1e916d045d1752c0b","location":{"path":"app/workers/update_merge_requests_worker.rb","lines":{"begin":9,"end":9}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `perform` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9c731770fbe34f3e5817178bf1c1c9c2","location":{"path":"app/workers/post_receive.rb","lines":{"begin":6,"end":25}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `process_project_changes` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"dcfa21f106c7ddc7d59ef6a69ed225a5","location":{"path":"app/workers/post_receive.rb","lines":{"begin":29,"end":52}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `perform` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"90ee5638594e38ee879df3d7b6670837","location":{"path":"app/workers/git_garbage_collect_worker.rb","lines":{"begin":11,"end":36}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `perform` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c91f311ed659a5cf472f55294f93721e","location":{"path":"app/workers/project_migrate_hashed_storage_worker.rb","lines":{"begin":9,"end":22}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `handle_failure` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"ea43d53b1207bf05223f6e3378b7622f","location":{"path":"app/workers/email_receiver_worker.rb","lines":{"begin":18,"end":51}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `perform` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"fb063b327d5645323a0adeb4a475ab88","location":{"path":"app/workers/create_gpg_signature_worker.rb","lines":{"begin":7,"end":29}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"90474c7bc130abea03bc8b0c1a6d72e3","location":{"path":"app/finders/concerns/finder_with_cross_project_access.rb","lines":{"begin":20,"end":32}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `by_due_date` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a7cd7e8d0b5f825ced9cce3fd0921f8b","location":{"path":"app/finders/issues_finder.rb","lines":{"begin":74,"end":90}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `all_groups` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9450c1e48d60393e153d88597dff24f6","location":{"path":"app/finders/groups_finder.rb","lines":{"begin":44,"end":54}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"be7b1d323697075c6c41a353ae096f3b","location":{"path":"app/finders/environments_finder.rb","lines":{"begin":11,"end":47}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `execute` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"caa84d8a4abdc89470c9734cc20f668b","location":{"path":"app/finders/environments_finder.rb","lines":{"begin":11,"end":47}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `issuable_finder.rb` has 326 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"a0da380c5a294186d2f8b47c7dbbefc2","location":{"path":"app/finders/issuable_finder.rb","lines":{"begin":30,"end":487}},"other_locations":[],"remediation_points":2294400,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `milestones` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"10f2a889ce05a62411b22bd93f5cc5fb","location":{"path":"app/finders/issuable_finder.rb","lines":{"begin":195,"end":214}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `by_milestone` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4b5705f5f9e383902a98d61545a61a9f","location":{"path":"app/finders/issuable_finder.rb","lines":{"begin":432,"end":447}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `IssuableFinder` has 47 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"863953770234ecee39c26f4a376fd96f","location":{"path":"app/finders/issuable_finder.rb","lines":{"begin":30,"end":487}},"other_locations":[],"remediation_points":3900000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `target` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"10931dd4f683d88c8163ae49517c9ab8","location":{"path":"app/finders/notes_finder.rb","lines":{"begin":30,"end":46}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `by_archived` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8a0163155f7d44abda52664f1aeec277","location":{"path":"app/finders/projects_finder.rb","lines":{"begin":153,"end":167}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `label_ids` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8efea533e852a1ae66e134916ddee3ed","location":{"path":"app/finders/labels_finder.rb","lines":{"begin":30,"end":59}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `project` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"dcae9d4bea82b824bf3281aee3585c28","location":{"path":"app/finders/labels_finder.rb","lines":{"begin":138,"end":149}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1b10747a7f6c51031eb2aec28a84ab64","location":{"path":"app/finders/autocomplete/users_finder.rb","lines":{"begin":27,"end":40}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `distinct_on` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"684bb4005fc7ad31c75a6725f7cc9bb4","location":{"path":"app/finders/members_finder.rb","lines":{"begin":38,"end":71}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `TodosFinder` has 23 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"bda816f835a5b1d9557e5018542c8d40","location":{"path":"app/finders/todos_finder.rb","lines":{"begin":17,"end":195}},"other_locations":[],"remediation_points":1500000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_block` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2764263922dc65629ac261e7b22a4aaa","location":{"path":"rubocop/cop/avoid_break_from_strong_memoize.rb","lines":{"begin":26,"end":37}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_send` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d3d826dd296b41ed52a3d279711f08c1","location":{"path":"rubocop/cop/migration/reversible_add_column_with_default.rb","lines":{"begin":22,"end":31}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_send` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7c2b352ab3b2b95bfd273eed48b0abde","location":{"path":"rubocop/cop/migration/update_column_in_batches.rb","lines":{"begin":14,"end":23}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_send` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1ca44c40f4350122f1d014c4832b0903","location":{"path":"rubocop/cop/migration/update_large_table.rb","lines":{"begin":52,"end":64}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_send` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"259f2282957271f68f06320d6e9c9304","location":{"path":"rubocop/cop/migration/add_reference.rb","lines":{"begin":13,"end":31}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_def` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1eade1345b7999362c94ffdd69c9abe5","location":{"path":"rubocop/cop/migration/add_index.rb","lines":{"begin":12,"end":32}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_send` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2957b0117eb58305df4d1c4f628f6e22","location":{"path":"rubocop/cop/migration/add_concurrent_index.rb","lines":{"begin":14,"end":26}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_send` has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a265e4d95fda1c51004e6b280d4faa62","location":{"path":"rubocop/cop/migration/hash_index.rb","lines":{"begin":16,"end":35}},"other_locations":[],"remediation_points":1050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_send` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4642fe2fb8caa127e076b834679b38c7","location":{"path":"rubocop/cop/migration/add_column.rb","lines":{"begin":16,"end":35}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_send` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"53f08cb9ea1aded1c4867d5ec20513e1","location":{"path":"rubocop/cop/migration/datetime.rb","lines":{"begin":26,"end":38}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_def` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"33c826c076b3d604191dc285ae1c197f","location":{"path":"rubocop/cop/migration/remove_column.rb","lines":{"begin":13,"end":26}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_send` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5f6ab7199493398668d2f7fb4ae05a45","location":{"path":"rubocop/cop/migration/safer_boolean_column.rb","lines":{"begin":34,"end":58}},"other_locations":[],"remediation_points":850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_send` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5d3a133fdd5733e12d588c313215673c","location":{"path":"rubocop/cop/migration/remove_concurrent_index.rb","lines":{"begin":14,"end":21}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_block` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"60e29c1a431f0815adefc57a3daa815a","location":{"path":"rubocop/cop/avoid_return_from_blocks.rb","lines":{"begin":28,"end":39}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `parent_blocks` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bf710c1583fafaba0fb4a8d7507199ca","location":{"path":"rubocop/cop/avoid_return_from_blocks.rb","lines":{"begin":55,"end":65}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_class` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ac6a847fc937c343670c7deedadaa245","location":{"path":"rubocop/cop/code_reuse/presenter.rb","lines":{"begin":20,"end":37}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `check_all_send_nodes` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"86036271965f234231993a45bdebb14d","location":{"path":"rubocop/cop/code_reuse/worker.rb","lines":{"begin":31,"end":46}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_class` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3468ff5bbfe02d60179b461cee64dcd2","location":{"path":"rubocop/cop/code_reuse/serializer.rb","lines":{"begin":20,"end":37}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_send` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f6cd42fcfb267a05384d5c43432583d9","location":{"path":"rubocop/cop/code_reuse/active_record.rb","lines":{"begin":91,"end":107}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_if` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c31d398a0e65e6ad5bf772ffbe612d27","location":{"path":"rubocop/cop/line_break_around_conditional_block.rb","lines":{"begin":50,"end":58}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `autocorrect` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6790fd3dafb4732df58459faaaee4a86","location":{"path":"rubocop/cop/line_break_around_conditional_block.rb","lines":{"begin":60,"end":71}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `on_send` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"83f3ce0952418f2d18756e7f01d3f37e","location":{"path":"rubocop/cop/project_path_helper.rb","lines":{"begin":10,"end":21}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this method.","location":{"path":"rubocop/cop/project_path_helper.rb","lines":{"begin":18,"end":18}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"16132947f8a9d308be379b39b9a5d3e6"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `perform` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"00f629cf63f892026e01afc3ea1f7651","location":{"path":"qa/qa/scenario/test/sanity/selectors.rb","lines":{"begin":10,"end":49}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `configure!` has 44 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"024a3eec035772b027f91725d6217728","location":{"path":"qa/qa/runtime/browser.rb","lines":{"begin":34,"end":100}},"other_locations":[],"remediation_points":1056000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `perform` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b5bc236abe446161666817def77f8ddf","location":{"path":"qa/qa/specs/runner.rb","lines":{"begin":16,"end":34}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `fabricate!` has a Cognitive Complexity of 15 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d6f04a78d84c195424103bc166feb302","location":{"path":"qa/qa/factory/repository/push.rb","lines":{"begin":33,"end":75}},"other_locations":[],"remediation_points":1150000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `fabricate!` has 34 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"0619d32fe486fa8cd5d32a978dbba114","location":{"path":"qa/qa/factory/repository/push.rb","lines":{"begin":33,"end":75}},"other_locations":[],"remediation_points":816000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `fabricate!` has a Cognitive Complexity of 19 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3806fbbd18c151ecd8c0b6a777c6eafd","location":{"path":"qa/qa/factory/resource/kubernetes_cluster.rb","lines":{"begin":16,"end":55}},"other_locations":[],"remediation_points":1550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `fabricate!` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"9a68225ad27f7d73dc48ba5138c97cc4","location":{"path":"qa/qa/factory/resource/kubernetes_cluster.rb","lines":{"begin":16,"end":55}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `fabricate!` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"455a528019b993508c00252ac2356d13","location":{"path":"qa/qa/factory/resource/branch.rb","lines":{"begin":19,"end":73}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `fabricate!` has 40 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"8c20ae555f1495416940ef8126556a4b","location":{"path":"qa/qa/factory/resource/branch.rb","lines":{"begin":19,"end":73}},"other_locations":[],"remediation_points":960000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `sign_in_using_credentials` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"cf2fda789a392298297395e24cd69833","location":{"path":"qa/qa/page/main/login.rb","lines":{"begin":43,"end":60}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `expand_section` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"403c8764d8456908ed9eeef4e0044633","location":{"path":"qa/qa/page/settings/common.rb","lines":{"begin":8,"end":19}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Repository` has 21 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"1f47da27b9c8ebadc35daab5ecdfacbd","location":{"path":"qa/qa/git/repository.rb","lines":{"begin":7,"end":126}},"other_locations":[],"remediation_points":1300000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Base` has 36 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"e990b96533b4c82f0e6c7290f79ea42e","location":{"path":"lib/declarative_policy/base.rb","lines":{"begin":2,"end":330}},"other_locations":[],"remediation_points":2800000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"return_statements","content":{"body":""},"description":"Avoid too many `return` statements within this method.","location":{"path":"lib/declarative_policy/condition.rb","lines":{"begin":72,"end":72}},"other_locations":[],"remediation_points":300000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"453a21507c9d4e6b09338d4ea74a2cb6"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `run` has a Cognitive Complexity of 29 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9109da1712e5180769d6dee88e01ab4b","location":{"path":"lib/declarative_policy/runner.rb","lines":{"begin":76,"end":108}},"other_locations":[],"remediation_points":2550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `steps_by_score` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c728761c8bd550bb676d5ac29cc54f2c","location":{"path":"lib/declarative_policy/runner.rb","lines":{"begin":130,"end":179}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `steps_by_score` has 32 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"fda7518f9492e598aeaa14084a16fcad","location":{"path":"lib/declarative_policy/runner.rb","lines":{"begin":130,"end":179}},"other_locations":[],"remediation_points":768000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `flattened` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"938e199f4acb9d23e67b122acf7df125","location":{"path":"lib/declarative_policy/step.rb","lines":{"begin":51,"end":76}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e8ff80c1013b45a887d5b05aebda0a6d","location":{"path":"lib/mattermost/session.rb","lines":{"begin":100,"end":112}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Session` has 21 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"b6bc576e4f2b4e33eeb24fbd9a4756e0","location":{"path":"lib/mattermost/session.rb","lines":{"begin":23,"end":185}},"other_locations":[],"remediation_points":1300000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `from_params` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8708d87b45e03dda5cf801ba3c8b4ae8","location":{"path":"lib/uploaded_file.rb","lines":{"begin":31,"end":50}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `object_link_commit` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4d75625eef2a0bac64c81e6a99b470c7","location":{"path":"lib/banzai/filter/merge_request_reference_filter.rb","lines":{"begin":66,"end":77}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `call` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e4a7914b17bf2c4568c886ae0510580a","location":{"path":"lib/banzai/filter/issuable_state_filter.rb","lines":{"begin":13,"end":29}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `call` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c21517ccaabda5807f34857c92c02c20","location":{"path":"lib/banzai/filter/emoji_filter.rb","lines":{"begin":11,"end":26}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `call` has a Cognitive Complexity of 15 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5b2ff3f6e59ccd27a3e8df6e92792289","location":{"path":"lib/banzai/filter/gollum_tags_filter.rb","lines":{"begin":64,"end":87}},"other_locations":[],"remediation_points":1150000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `build_relative_path` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1fc007ca58af10483040ad6c3acafc7b","location":{"path":"lib/banzai/filter/relative_link_filter.rb","lines":{"begin":124,"end":140}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `call` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0d11bc0fb07cb93de54e50ca187a470c","location":{"path":"lib/banzai/filter/inline_diff_filter.rb","lines":{"begin":8,"end":20}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `call` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"229de514760543ff1eae907b8931ae4a","location":{"path":"lib/banzai/filter/spaced_link_filter.rb","lines":{"begin":44,"end":60}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `call` has a Cognitive Complexity of 28 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f2adb2780e68c3edecbf3243959331bc","location":{"path":"lib/banzai/filter/abstract_reference_filter.rb","lines":{"begin":99,"end":148}},"other_locations":[],"remediation_points":2450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `object_link_filter` has a Cognitive Complexity of 19 (exceeds 5 allowed). Consider refactoring.","fingerprint":"756d39528c96fdea1b53fc02cd2f1b54","location":{"path":"lib/banzai/filter/abstract_reference_filter.rb","lines":{"begin":161,"end":204}},"other_locations":[],"remediation_points":1550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `AbstractReferenceFilter` has 31 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"bf8591fc0f7db3df80a7dd6204670584","location":{"path":"lib/banzai/filter/abstract_reference_filter.rb","lines":{"begin":7,"end":359}},"other_locations":[],"remediation_points":2300000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `call` has 36 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"158c3e7c7c151f7461c460b58c8eb7fb","location":{"path":"lib/banzai/filter/abstract_reference_filter.rb","lines":{"begin":99,"end":148}},"other_locations":[],"remediation_points":864000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `object_link_filter` has 35 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"cce139d64bf42a05629c35156d98c24b","location":{"path":"lib/banzai/filter/abstract_reference_filter.rb","lines":{"begin":161,"end":204}},"other_locations":[],"remediation_points":840000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `call` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f009def1da08a1c0910203aacb888646","location":{"path":"lib/banzai/filter/external_issue_reference_filter.rb","lines":{"begin":30,"end":55}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `call` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e19e0b6d7127e7778817e23a5c2202a6","location":{"path":"lib/banzai/filter/external_link_filter.rb","lines":{"begin":9,"end":23}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `highlight_node` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9dc3f1809c63dc39b3c7b301b2c8b0a8","location":{"path":"lib/banzai/filter/syntax_highlight_filter.rb","lines":{"begin":19,"end":53}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `call` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0228be52a5d55a59f39144f901ba3de8","location":{"path":"lib/banzai/filter/user_reference_filter.rb","lines":{"begin":28,"end":51}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `user_link_filter` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e1a29dd5f3f29173136fead3b7feacff","location":{"path":"lib/banzai/filter/user_reference_filter.rb","lines":{"begin":61,"end":75}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `call` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c56c41f7c09938431d527c9d84ee464c","location":{"path":"lib/banzai/filter/project_reference_filter.rb","lines":{"begin":26,"end":47}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `call` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"23c5be476e6cfabb3f50b8995a21481e","location":{"path":"lib/banzai/filter/autolink_filter.rb","lines":{"begin":51,"end":67}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `autolink_match` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"63ef57bb6d5d4556a6d292a19e1eb7aa","location":{"path":"lib/banzai/filter/autolink_filter.rb","lines":{"begin":79,"end":116}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `remove_unsafe_links` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"578c89c0c495a9f9912ae5425a9baf35","location":{"path":"lib/banzai/filter/sanitization_filter.rb","lines":{"begin":64,"end":91}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `remove_unsafe_table_style` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"66ae1f700aade40e1b93928de1809522","location":{"path":"lib/banzai/filter/sanitization_filter.rb","lines":{"begin":101,"end":114}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `process_link_attr` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"fe0e7a59ae612e2391ff8956ece5a37e","location":{"path":"lib/banzai/filter/absolute_link_filter.rb","lines":{"begin":21,"end":29}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `call` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"91ceeacf382258ddf799f7e8df323086","location":{"path":"lib/banzai/filter/commit_trailers_filter.rb","lines":{"begin":29,"end":43}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `link_to_user` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"2cae91969679378626a39ee56d06c378","location":{"path":"lib/banzai/filter/commit_trailers_filter.rb","lines":{"begin":81,"end":115}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"complex_logic","content":{"body":""},"description":"Consider simplifying this complex logical expression.","location":{"path":"lib/banzai/filter/math_filter.rb","lines":{"begin":27,"end":36}},"other_locations":[],"remediation_points":400000,"severity":"major","type":"issue","engine_name":"structure","fingerprint":"c132e79b1733f1ef2e4fba2f07f29935"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `call` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"88347949c1ff362bde8f0c3f4fe03dc2","location":{"path":"lib/banzai/filter/table_of_contents_filter.rb","lines":{"begin":21,"end":52}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find_parent` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b3d0438ee7565d4ad0316ba6f05a9baf","location":{"path":"lib/banzai/filter/table_of_contents_filter.rb","lines":{"begin":102,"end":115}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `nodes_visible_to_user` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c851d1fc927d9308df218d02f42fde99","location":{"path":"lib/banzai/reference_parser/user_parser.rb","lines":{"begin":25,"end":48}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `nodes_user_can_reference` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bfa5e9970213f7ef43f0e22780710fb3","location":{"path":"lib/banzai/reference_parser/user_parser.rb","lines":{"begin":64,"end":87}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `grouped_objects_for_nodes` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"56d2576cd012b6e37a94c3cac839a5fd","location":{"path":"lib/banzai/reference_parser/base_parser.rb","lines":{"begin":134,"end":147}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `BaseParser` has 21 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"3b65d4312cddf7542466b907246e6568","location":{"path":"lib/banzai/reference_parser/base_parser.rb","lines":{"begin":34,"end":255}},"other_locations":[],"remediation_points":1300000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `cache_collection_render` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"86955f7d246e45efcedaab9abac1b39e","location":{"path":"lib/banzai/renderer.rb","lines":{"begin":76,"end":103}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `filter_nodes_at_beginning` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"575e435b81c0cb589731931503f3f7ef","location":{"path":"lib/banzai/querying.rb","lines":{"begin":45,"end":64}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `initialize` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a1435f7fb2485ddc0076596fa851b5e1","location":{"path":"lib/file_size_validator.rb","lines":{"begin":8,"end":17}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `check_validity!` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4c0eea681bcd3ea73ab99bdeb9992c52","location":{"path":"lib/file_size_validator.rb","lines":{"begin":19,"end":33}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate_each` has a Cognitive Complexity of 19 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4ad97d789c0a7bb2c49b85af370fa1cb","location":{"path":"lib/file_size_validator.rb","lines":{"begin":36,"end":65}},"other_locations":[],"remediation_points":1550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `projects.rb` has 419 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"de2195ccf1e60f3a00e250b69809f314","location":{"path":"lib/api/projects.rb","lines":{"begin":1,"end":513}},"other_locations":[],"remediation_points":3633600,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `apply_filters` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3d37733ec13b40a7294cb95cca30d7c0","location":{"path":"lib/api/projects.rb","lines":{"begin":21,"end":27}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `entities.rb` has 1174 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"14ca44a7292f309674c3e6bf5668d68a","location":{"path":"lib/api/entities.rb","lines":{"begin":1,"end":1469}},"other_locations":[],"remediation_points":14505600,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create_note` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5bdd6d096b03346b779bae1a47c5df19","location":{"path":"lib/api/helpers/notes_helpers.rb","lines":{"begin":89,"end":101}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate_job!` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9c2df515fd3e4e567e5c43ce34122ebc","location":{"path":"lib/api/helpers/runner.rb","lines":{"begin":34,"end":42}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `filter_runners` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8fe97bd7f7ff40f6f347505c5401de55","location":{"path":"lib/api/runners.rb","lines":{"begin":163,"end":176}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `authenticate_show_runner!` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"678c4afecdf242daef2608fb52f16121","location":{"path":"lib/api/runners.rb","lines":{"begin":184,"end":188}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `authenticate_delete_runner!` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"229dc324c7b4cd0754d3f429d0efa489","location":{"path":"lib/api/runners.rb","lines":{"begin":196,"end":201}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `authenticate_enable_runner!` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"fdde7223cb136c51a33619a48b7e10e9","location":{"path":"lib/api/runners.rb","lines":{"begin":203,"end":210}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `issues.rb` has 266 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"49d5eae8f5a9b7ef20af4a226580c9fb","location":{"path":"lib/api/issues.rb","lines":{"begin":1,"end":332}},"other_locations":[],"remediation_points":1430400,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `filter_builds` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b03e3d209e73511af90d54684b559d3a","location":{"path":"lib/api/jobs.rb","lines":{"begin":176,"end":185}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `list_milestones_for` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8e051bd18be2af43510bfc934382e630","location":{"path":"lib/api/milestone_responses.rb","lines":{"begin":30,"end":37}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `assign_file_vars!` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4be22423f2ecad963ae6b37b42f43510","location":{"path":"lib/api/files.rb","lines":{"begin":25,"end":36}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `assign_blob_vars!` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e73cbaada1130cabaf0dfa4c08f70656","location":{"path":"lib/api/repositories.rb","lines":{"begin":22,"end":35}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `services.rb` has 836 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"68db3252fd8eaa9d286783dcd5099377","location":{"path":"lib/api/services.rb","lines":{"begin":2,"end":864}},"other_locations":[],"remediation_points":9638400,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `runner.rb` has 266 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"1e11149dffed6dc2e322c584638327bf","location":{"path":"lib/api/runner.rb","lines":{"begin":1,"end":316}},"other_locations":[],"remediation_points":1430400,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `merge_requests.rb` has 322 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"3de9fe3d6f81552276ac816a0f052fb7","location":{"path":"lib/api/merge_requests.rb","lines":{"begin":1,"end":398}},"other_locations":[],"remediation_points":2236800,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `handle_merge_request_errors!` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4b0820e7ae582cfc463b18401dc7dfd6","location":{"path":"lib/api/merge_requests.rb","lines":{"begin":145,"end":159}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `helpers.rb` has 381 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"5db68c679d275d3963e0f9660988e103","location":{"path":"lib/api/helpers.rb","lines":{"begin":1,"end":533}},"other_locations":[],"remediation_points":3086400,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `attributes_for_keys` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"63712b203f7a63b38bcb9eea53c3001d","location":{"path":"lib/api/helpers.rb","lines":{"begin":289,"end":299}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `project_finder_params` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"268f87eb93bd855d1807610fcddd6efe","location":{"path":"lib/api/helpers.rb","lines":{"begin":408,"end":420}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `present_carrierwave_file!` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"360f85bdb8a06a280a62224143731f15","location":{"path":"lib/api/helpers.rb","lines":{"begin":440,"end":452}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `sudo!` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ddabeb34a3b3e3067c6b88323ce10dcc","location":{"path":"lib/api/helpers.rb","lines":{"begin":468,"end":487}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `users.rb` has 652 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"da0cb2b4e7ad1056fa1e4f7a0fc774d7","location":{"path":"lib/api/users.rb","lines":{"begin":1,"end":837}},"other_locations":[],"remediation_points":6988800,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find_groups` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"eea17dfbc1a8fa0837c83d51e2708400","location":{"path":"lib/api/groups.rb","lines":{"begin":42,"end":56}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `inject_rblineprof` has a Cognitive Complexity of 49 (exceeds 5 allowed). Consider refactoring.","fingerprint":"16157b2c336822ada397c30b37d0e63b","location":{"path":"lib/peek/rblineprof/custom_controller_helpers.rb","lines":{"begin":17,"end":100}},"other_locations":[],"remediation_points":4550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `inject_rblineprof` has 62 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"9665938c091b2575d937990fbc609dac","location":{"path":"lib/peek/rblineprof/custom_controller_helpers.rb","lines":{"begin":17,"end":100}},"other_locations":[],"remediation_points":1488000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `flatten_comments` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3acab7e81bc6f21925b3944dc13c9d25","location":{"path":"lib/bitbucket_server/representation/comment.rb","lines":{"begin":87,"end":111}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `check_errors!` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5656af648a8148a4747d9750b93c8a0c","location":{"path":"lib/bitbucket_server/connection.rb","lines":{"begin":62,"end":74}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `extract_ref` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8b8bde6183c235753993662c791c5f50","location":{"path":"lib/extracts_path.rb","lines":{"begin":40,"end":74}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `assign_ref_vars` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"994b000ce7697f00c9d2fdef6d5f219c","location":{"path":"lib/extracts_path.rb","lines":{"begin":108,"end":133}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `gitaly_configuration_toml` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7ce1b00e1e01659ed25ab9357f9d47d7","location":{"path":"lib/gitlab/setup_helper.rb","lines":{"begin":14,"end":43}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find_with_user_password` has a Cognitive Complexity of 15 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0212b6bdb5ef9f95aaaad8df3d25a15a","location":{"path":"lib/gitlab/auth.rb","lines":{"begin":47,"end":83}},"other_locations":[],"remediation_points":1150000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `rate_limit!` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"18c084f7a7640dd9934777afe795d6e1","location":{"path":"lib/gitlab/auth.rb","lines":{"begin":85,"end":104}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `service_request_check` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"fcdcb167117e9fbdc60bcccfa8c52ce9","location":{"path":"lib/gitlab/auth.rb","lines":{"begin":112,"end":128}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `deploy_token_check` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3349988ec83e4933b92c3a7e3824cc58","location":{"path":"lib/gitlab/auth.rb","lines":{"begin":185,"end":199}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `lfs_token_check` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4f1a1535569de597558d429c01457d5e","location":{"path":"lib/gitlab/auth.rb","lines":{"begin":202,"end":228}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `build_access_token_check` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1e8fcdca34d7247788de08e6051143d2","location":{"path":"lib/gitlab/auth.rb","lines":{"begin":230,"end":245}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `setup_subscribers` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"85ca5972d830d83ef927532dcf66122f","location":{"path":"lib/gitlab/performance_bar/peek_query_tracker.rb","lines":{"begin":17,"end":36}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `fields` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"dbfd2a1c630915fc2b4befaca081c456","location":{"path":"lib/gitlab/slash_commands/presenters/issue_base.rb","lines":{"begin":21,"end":39}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `format_response` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"57bd6ed972d21a41e82e376f51d7a76e","location":{"path":"lib/gitlab/slash_commands/presenters/base.rb","lines":{"begin":47,"end":58}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `text` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0fea0819cd1d628d704dab5f9f56ae5c","location":{"path":"lib/gitlab/slash_commands/presenters/issue_show.rb","lines":{"begin":40,"end":53}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `file.rb` has 255 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"bcd7afc2511311acf93e48f89b257ee8","location":{"path":"lib/gitlab/diff/file.rb","lines":{"begin":1,"end":356}},"other_locations":[],"remediation_points":1272000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `simple_viewer_class` has a Cognitive Complexity of 17 (exceeds 5 allowed). Consider refactoring.","fingerprint":"455a703cf96823be99c475db08de0c9f","location":{"path":"lib/gitlab/diff/file.rb","lines":{"begin":311,"end":339}},"other_locations":[],"remediation_points":1350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `viewer_class_from` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"cae1cebb92d35a5859ef229108d1e4c1","location":{"path":"lib/gitlab/diff/file.rb","lines":{"begin":345,"end":353}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `File` has 54 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"4872155d7a8ab149e4dbfdd0a34d314f","location":{"path":"lib/gitlab/diff/file.rb","lines":{"begin":3,"end":354}},"other_locations":[],"remediation_points":4600000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `simple_viewer_class` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"c663249a7eb69d79d53815c02da1287e","location":{"path":"lib/gitlab/diff/file.rb","lines":{"begin":311,"end":339}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `initialize` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"62d56326c2f46a050e8a9f1219488e25","location":{"path":"lib/gitlab/diff/line.rb","lines":{"begin":10,"end":10}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Position` has 22 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"44aef8e9a5055d83b7605ef01a8ffcd5","location":{"path":"lib/gitlab/diff/position.rb","lines":{"begin":5,"end":150}},"other_locations":[],"remediation_points":1400000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `highlight` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"922e6aee35a311a79f1043b07ee7064d","location":{"path":"lib/gitlab/diff/highlight.rb","lines":{"begin":21,"end":44}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `highlight_line` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b41f2627f4109bdc5b74287cf3ba0d21","location":{"path":"lib/gitlab/diff/highlight.rb","lines":{"begin":48,"end":64}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `parallelize` has a Cognitive Complexity of 15 (exceeds 5 allowed). Consider refactoring.","fingerprint":"631e96ad1ef01b07245ee2a542d76275","location":{"path":"lib/gitlab/diff/parallel_diff.rb","lines":{"begin":10,"end":58}},"other_locations":[],"remediation_points":1150000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `parallelize` has 35 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"c801b9d4ce1a0b15a92b13570e4b4a73","location":{"path":"lib/gitlab/diff/parallel_diff.rb","lines":{"begin":10,"end":58}},"other_locations":[],"remediation_points":840000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `diff_stats_collection` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d1edfc550eecbd5daa471adab0ab3385","location":{"path":"lib/gitlab/diff/file_collection/base.rb","lines":{"begin":50,"end":59}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `parse` has a Cognitive Complexity of 29 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bfc88a6b4fdafecdb4881ebd0a709e90","location":{"path":"lib/gitlab/diff/parser.rb","lines":{"begin":6,"end":63}},"other_locations":[],"remediation_points":2550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `parse` has 42 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"6d81f9668924e2328ae1d3b978012b2e","location":{"path":"lib/gitlab/diff/parser.rb","lines":{"begin":6,"end":63}},"other_locations":[],"remediation_points":1008000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `trace` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"678e46609976cce578070c879cdeaa09","location":{"path":"lib/gitlab/diff/position_tracer.rb","lines":{"begin":18,"end":86}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `trace_added_line` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3d3253565d5f52fdc8e227a610a4ba02","location":{"path":"lib/gitlab/diff/position_tracer.rb","lines":{"begin":90,"end":127}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `trace_removed_line` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7a2345cd4720ceb59ce0efdf2c931d70","location":{"path":"lib/gitlab/diff/position_tracer.rb","lines":{"begin":129,"end":158}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `trace_unchanged_line` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"68d033636c672cf93801ba4a440a9b10","location":{"path":"lib/gitlab/diff/position_tracer.rb","lines":{"begin":160,"end":199}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `map_line_number` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"dc329e8839fe1c0b24ddd3dbaa5b8485","location":{"path":"lib/gitlab/diff/line_mapper.rb","lines":{"begin":30,"end":61}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `popen_with_detail` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1f3016518aa9a963248a02cac889fd75","location":{"path":"lib/gitlab/popen.rb","lines":{"begin":18,"end":51}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `request_cache` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c7f577fa9ce2f42e5f27aac8db514fe3","location":{"path":"lib/gitlab/cache/request_cache.rb","lines":{"begin":23,"end":58}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `store_in_cache_if_needed` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"baa77c71d04626f49bd5c1e57a0e2ca9","location":{"path":"lib/gitlab/cache/ci/project_pipeline_status.rb","lines":{"begin":92,"end":100}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `aggregate_rblineprof` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5c969b511dec60cc5ae82a493581e987","location":{"path":"lib/gitlab/sherlock/line_profiler.rb","lines":{"begin":59,"end":85}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `subscribe_to_active_record` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"cb47c9a23a0a444f0c02f2ce82101c23","location":{"path":"lib/gitlab/sherlock/transaction.rb","lines":{"begin":88,"end":96}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `remove_keys_not_found_in_db` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"110e16cf8bc4b13203ae16707be71f9e","location":{"path":"lib/gitlab/shell.rb","lines":{"begin":229,"end":246}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Shell` has 37 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"9bb914cee67608b26add7bcc4f81b00b","location":{"path":"lib/gitlab/shell.rb","lines":{"begin":6,"end":445}},"other_locations":[],"remediation_points":2900000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `bulk_insert` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"46738c8e24da7d644d4613d9605d7262","location":{"path":"lib/gitlab/database.rb","lines":{"begin":167,"end":197}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `each` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f71d3611436ba9323475933db3b224e0","location":{"path":"lib/gitlab/gitaly_client/conflict_files_stitcher.rb","lines":{"begin":10,"end":26}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `each` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a4899ef1be9285a53b4a3412a311ee1f","location":{"path":"lib/gitlab/gitaly_client/blobs_stitcher.rb","lines":{"begin":10,"end":29}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `update_page` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"5e1fe756db8adf0384ead3d7ca4d40bb","location":{"path":"lib/gitlab/gitaly_client/wiki_service.rb","lines":{"begin":41,"end":41}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find_file` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f2ac95cd9282cf75ce51181ba7bcf087","location":{"path":"lib/gitlab/gitaly_client/wiki_service.rb","lines":{"begin":128,"end":152}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `wiki_page_from_iterator` has a Cognitive Complexity of 17 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8d18749d8e89aa853f84d5b8ab2fa1e0","location":{"path":"lib/gitlab/gitaly_client/wiki_service.rb","lines":{"begin":171,"end":192}},"other_locations":[],"remediation_points":1350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `commit_service.rb` has 334 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"459baf31c3d4b57e8c9df845211d85c9","location":{"path":"lib/gitlab/gitaly_client/commit_service.rb","lines":{"begin":1,"end":431}},"other_locations":[],"remediation_points":2409600,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `diff` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6776fdb83e8edfae5378441fd52a4925","location":{"path":"lib/gitlab/gitaly_client/commit_service.rb","lines":{"begin":33,"end":63}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `tree_entry` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"00baf604adba61e863f7d154a8dee72b","location":{"path":"lib/gitlab/gitaly_client/commit_service.rb","lines":{"begin":78,"end":109}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find_commit` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"186f0eba8b7425edc8cc3c73c38cd40a","location":{"path":"lib/gitlab/gitaly_client/commit_service.rb","lines":{"begin":242,"end":262}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `CommitService` has 31 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"49c846fd451fa9152c64a84b18cea747","location":{"path":"lib/gitlab/gitaly_client/commit_service.rb","lines":{"begin":3,"end":429}},"other_locations":[],"remediation_points":2300000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `ref_service.rb` has 252 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"eb1efcba78462f496979baf4cb6cd2ad","location":{"path":"lib/gitlab/gitaly_client/ref_service.rb","lines":{"begin":1,"end":327}},"other_locations":[],"remediation_points":1228800,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `RefService` has 31 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"00c5cfab9191c2db4747039325616652","location":{"path":"lib/gitlab/gitaly_client/ref_service.rb","lines":{"begin":3,"end":325}},"other_locations":[],"remediation_points":2300000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `repository_service.rb` has 323 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"493989beb71c8d830c2b79d5553c6147","location":{"path":"lib/gitlab/gitaly_client/repository_service.rb","lines":{"begin":1,"end":396}},"other_locations":[],"remediation_points":2251200,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `fetch_remote` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f3aee0aba331f59ab18ffef3792b052a","location":{"path":"lib/gitlab/gitaly_client/repository_service.rb","lines":{"begin":64,"end":81}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `RepositoryService` has 35 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"6ca9b3950e1ce99211058bd24b696cd9","location":{"path":"lib/gitlab/gitaly_client/repository_service.rb","lines":{"begin":3,"end":394}},"other_locations":[],"remediation_points":2700000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `user_squash` has 7 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"3244c060b29a67dfaca14f5fd90c0c69","location":{"path":"lib/gitlab/gitaly_client/operation_service.rb","lines":{"begin":207,"end":207}},"other_locations":[],"remediation_points":525000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `user_commit_files` has 8 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"e11b9bf00977dfd40d466849a02aad7e","location":{"path":"lib/gitlab/gitaly_client/operation_service.rb","lines":{"begin":234,"end":235}},"other_locations":[],"remediation_points":600000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `user_commit_files_request_header` has 8 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"74f8cedbd2e30f093d96c68640b17e2f","location":{"path":"lib/gitlab/gitaly_client/operation_service.rb","lines":{"begin":316,"end":317}},"other_locations":[],"remediation_points":600000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `operation_service.rb` has 284 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"e9b10e91d8aa4aecb2dd40e2ff73151e","location":{"path":"lib/gitlab/gitaly_client/operation_service.rb","lines":{"begin":1,"end":343}},"other_locations":[],"remediation_points":1689600,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `user_create_branch` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f83bdf53147b9d2930979ca6a622f44f","location":{"path":"lib/gitlab/gitaly_client/operation_service.rb","lines":{"begin":48,"end":69}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `user_merge_branch` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"96dce6cec3c6d464fe3b164bf05adf61","location":{"path":"lib/gitlab/gitaly_client/operation_service.rb","lines":{"begin":101,"end":137}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `user_commit_files` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"b324bd9e25781ee4f45ebe63530654b5","location":{"path":"lib/gitlab/gitaly_client/operation_service.rb","lines":{"begin":233,"end":274}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `define_predicate_methods` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1748406e1b1a3efed8bbdbc2f7310efb","location":{"path":"lib/gitlab/fake_application_settings.rb","lines":{"begin":9,"end":19}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `read` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"306bfd1a5668c64b46f9a50ffcb84761","location":{"path":"lib/gitlab/http_io.rb","lines":{"begin":76,"end":100}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `get_chunk` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"718a1c6197d9172beada51e8fb725aa8","location":{"path":"lib/gitlab/http_io.rb","lines":{"begin":147,"end":173}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `HttpIO` has 21 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"f90f3bbe0002c0551d2c102e8d6cc2bb","location":{"path":"lib/gitlab/http_io.rb","lines":{"begin":5,"end":192}},"other_locations":[],"remediation_points":1300000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `system_usage_data` has 49 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"e44de166e4765b13674da7e6f1adbb03","location":{"path":"lib/gitlab/usage_data.rb","lines":{"begin":35,"end":85}},"other_locations":[],"remediation_points":1176000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `print_methods` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"74e543934a1cb0119b1cb9bc2bef6f4a","location":{"path":"lib/gitlab/profiler/total_time_flat_printer.rb","lines":{"begin":13,"end":36}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `format_issue_comment_body` has 6 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"4b9885935625732368d27f4d57c09a6b","location":{"path":"lib/gitlab/google_code_import/importer.rb","lines":{"begin":327,"end":327}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `importer.rb` has 283 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"1456110a9f0cea86dbda2fdc6ff8b006","location":{"path":"lib/gitlab/google_code_import/importer.rb","lines":{"begin":1,"end":371}},"other_locations":[],"remediation_points":1675200,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `import_issues` has a Cognitive Complexity of 15 (exceeds 5 allowed). Consider refactoring.","fingerprint":"fda606a33fed0d051037b3e7ec312764","location":{"path":"lib/gitlab/google_code_import/importer.rb","lines":{"begin":82,"end":126}},"other_locations":[],"remediation_points":1150000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `import_issue_comments` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e40d64a7ad3fca74d9f0603fcdfde073","location":{"path":"lib/gitlab/google_code_import/importer.rb","lines":{"begin":146,"end":179}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `format_updates` has a Cognitive Complexity of 19 (exceeds 5 allowed). Consider refactoring.","fingerprint":"627781504f289b64edb3cae5ded46686","location":{"path":"lib/gitlab/google_code_import/importer.rb","lines":{"begin":237,"end":293}},"other_locations":[],"remediation_points":1550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `format_attachments` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3eae70f0804e77646cf183b658337852","location":{"path":"lib/gitlab/google_code_import/importer.rb","lines":{"begin":312,"end":325}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `import_issues` has 33 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"140622e56443443be6d89cf7f8134759","location":{"path":"lib/gitlab/google_code_import/importer.rb","lines":{"begin":82,"end":126}},"other_locations":[],"remediation_points":792000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `import_issue_comments` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"81d77c1a0b5ebc4248e39438a9b784c1","location":{"path":"lib/gitlab/google_code_import/importer.rb","lines":{"begin":146,"end":179}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `format_updates` has 43 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"9b843b25138348d8d9e7cf6df7a2f0ed","location":{"path":"lib/gitlab/google_code_import/importer.rb","lines":{"begin":237,"end":293}},"other_locations":[],"remediation_points":1032000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `full_path` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"200d2aea21e0c3f34efb9b3a8051a82f","location":{"path":"lib/gitlab/database/rename_reserved_paths_migration/v1/migration_classes.rb","lines":{"begin":7,"end":15}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `rank_rows` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"dc13ef2bef6a33cc8bc4e67b71564878","location":{"path":"lib/gitlab/database/median.rb","lines":{"begin":140,"end":174}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `migration_helpers.rb` has 543 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"01e21ae134d30a14bd512652b7a940ab","location":{"path":"lib/gitlab/database/migration_helpers.rb","lines":{"begin":1,"end":1078}},"other_locations":[],"remediation_points":5419200,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `add_timestamps_with_timezone` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c59bbcc4bf6935d5c169f128844c4c91","location":{"path":"lib/gitlab/database/migration_helpers.rb","lines":{"begin":17,"end":40}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `add_concurrent_foreign_key` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ce151ede627cdfdf31c565ade50905ea","location":{"path":"lib/gitlab/database/migration_helpers.rb","lines":{"begin":152,"end":206}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `disable_statement_timeout` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"31b96e31df6242d18aba1d4abf07f1f9","location":{"path":"lib/gitlab/database/migration_helpers.rb","lines":{"begin":240,"end":272}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `update_column_in_batches` has a Cognitive Complexity of 15 (exceeds 5 allowed). Consider refactoring.","fingerprint":"21d13cfd466605197c31d8958201310c","location":{"path":"lib/gitlab/database/migration_helpers.rb","lines":{"begin":323,"end":380}},"other_locations":[],"remediation_points":1150000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `add_column_with_default` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"009915036d7d7932903bc6f766511a5e","location":{"path":"lib/gitlab/database/migration_helpers.rb","lines":{"begin":406,"end":438}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `copy_indexes` has a Cognitive Complexity of 17 (exceeds 5 allowed). Consider refactoring.","fingerprint":"60d019b8234aa4a0d7d445a95ee1e8ae","location":{"path":"lib/gitlab/database/migration_helpers.rb","lines":{"begin":817,"end":859}},"other_locations":[],"remediation_points":1350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `bulk_queue_background_migration_jobs_by_range` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"128bc9f2059885db7d254bdb6a31d4b3","location":{"path":"lib/gitlab/database/migration_helpers.rb","lines":{"begin":972,"end":993}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `add_concurrent_foreign_key` has 32 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"f6243b1ac45a70775392f6137b36e35f","location":{"path":"lib/gitlab/database/migration_helpers.rb","lines":{"begin":152,"end":206}},"other_locations":[],"remediation_points":768000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `update_column_in_batches` has 37 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"6dc99342ecbf79855eb8044b9e00cbdd","location":{"path":"lib/gitlab/database/migration_helpers.rb","lines":{"begin":323,"end":380}},"other_locations":[],"remediation_points":888000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `change_column_type_using_background_migration` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"39133c1e5a2502598dbf0ec8dc0af798","location":{"path":"lib/gitlab/database/migration_helpers.rb","lines":{"begin":593,"end":640}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `rename_column_using_background_migration` has 32 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"fc89feb63b650bd5547ac2ba44210012","location":{"path":"lib/gitlab/database/migration_helpers.rb","lines":{"begin":670,"end":731}},"other_locations":[],"remediation_points":768000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `copy_indexes` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"8b98ee08501009b6bf421b8064689b30","location":{"path":"lib/gitlab/database/migration_helpers.rb","lines":{"begin":817,"end":859}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `fetch_config` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4b3b0f6bd727a62eae22091574b81015","location":{"path":"lib/gitlab/mail_room.rb","lines":{"begin":31,"end":49}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `note_url` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"59ca4f1b16f978d96a1c7e36f7e69d62","location":{"path":"lib/gitlab/url_builder.rb","lines":{"begin":52,"end":71}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `rewrite` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f45f6ba5c50a0ab576b49cf1b282a615","location":{"path":"lib/gitlab/gfm/uploads_rewriter.rb","lines":{"begin":19,"end":29}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `unfold_reference` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"be381321436537b6ec6941dcff14d0b9","location":{"path":"lib/gitlab/gfm/reference_rewriter.rb","lines":{"begin":56,"end":72}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `sections` has a Cognitive Complexity of 24 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0f6b50ef494458ae4f54e52a28568869","location":{"path":"lib/gitlab/conflict/file.rb","lines":{"begin":49,"end":110}},"other_locations":[],"remediation_points":2050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find_match_line_header` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4fef2b9774e94d0bd02f1158378f701c","location":{"path":"lib/gitlab/conflict/file.rb","lines":{"begin":123,"end":137}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `as_json` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ed7b03c5a2c2d110a9a9db9e00f3d8d0","location":{"path":"lib/gitlab/conflict/file.rb","lines":{"begin":150,"end":168}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `sections` has 36 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"629b80d357b767eb9b1f37185affacd4","location":{"path":"lib/gitlab/conflict/file.rb","lines":{"begin":49,"end":110}},"other_locations":[],"remediation_points":864000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `which` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"565d3b45775f71100b9c7277076be0f6","location":{"path":"lib/gitlab/utils.rb","lines":{"begin":63,"end":74}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `render_go_doc` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e0fac0dd89237b115b26def1d32171a6","location":{"path":"lib/gitlab/middleware/go.rb","lines":{"begin":22,"end":33}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `with_open_files` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"83c9d42c4a44fe57eeee2a2b269ddb60","location":{"path":"lib/gitlab/middleware/multipart.rb","lines":{"begin":38,"end":57}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `decorate_params_value` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"32d0634549f8a039069852514c0c4e20","location":{"path":"lib/gitlab/middleware/multipart.rb","lines":{"begin":60,"end":82}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `initialize` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"100b77808e789566083b5722f853d491","location":{"path":"lib/gitlab/legacy_github_import/project_creator.rb","lines":{"begin":6,"end":6}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `import_issues` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3bfd1976bd1c3f5b63ad73183773103c","location":{"path":"lib/gitlab/legacy_github_import/importer.rb","lines":{"begin":117,"end":136}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `import_pull_requests` has a Cognitive Complexity of 19 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d3b76e6c4972600af102835c1739459a","location":{"path":"lib/gitlab/legacy_github_import/importer.rb","lines":{"begin":139,"end":165}},"other_locations":[],"remediation_points":1550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create_comments` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8131d9fa54052fb8688da41fca5b29ff","location":{"path":"lib/gitlab/legacy_github_import/importer.rb","lines":{"begin":222,"end":245}},"other_locations":[],"remediation_points":850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `import_wiki` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c9017489731af795ba61fdc442e91922","location":{"path":"lib/gitlab/legacy_github_import/importer.rb","lines":{"begin":266,"end":278}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `import_releases` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6cf70c97f808766cb57657e58420cb89","location":{"path":"lib/gitlab/legacy_github_import/importer.rb","lines":{"begin":280,"end":291}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Importer` has 27 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"564493c4d63110500702ce8552822c02","location":{"path":"lib/gitlab/legacy_github_import/importer.rb","lines":{"begin":3,"end":339}},"other_locations":[],"remediation_points":1900000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `each_object_to_import` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1c46822af079d421dee8173b07f3b80a","location":{"path":"lib/gitlab/github_import/parallel_scheduling.rb","lines":{"begin":78,"end":106}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `each_page` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d8e73017cc50cf5ae0ff94ea436d3ced","location":{"path":"lib/gitlab/github_import/client.rb","lines":{"begin":91,"end":112}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `with_rate_limit` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f8e67dd27500a710187cc201ddc1dded","location":{"path":"lib/gitlab/github_import/client.rb","lines":{"begin":133,"end":149}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Client` has 22 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"8c409ff9cd79515f70c131a687a58c2d","location":{"path":"lib/gitlab/github_import/client.rb","lines":{"begin":16,"end":216}},"other_locations":[],"remediation_points":1400000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create_sub_relations` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"de78150728d4deb7bbd23ae848875928","location":{"path":"lib/gitlab/import_export/project_tree_restorer.rb","lines":{"begin":134,"end":159}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `process_sub_relation` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"357889b554818506acea0dfc8f000afc","location":{"path":"lib/gitlab/import_export/project_tree_restorer.rb","lines":{"begin":161,"end":171}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e960e3648215aee14c4e5443b5f897b0","location":{"path":"lib/gitlab/import_export/after_export_strategies/base_after_export_strategy.rb","lines":{"begin":27,"end":49}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `build!` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1dd9f4457d861e5b12020c99ef408fe4","location":{"path":"lib/gitlab/import_export/after_export_strategy_builder.rb","lines":{"begin":6,"end":17}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `parse!` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"343742e2d2dc60bd360734eccf276cc8","location":{"path":"lib/gitlab/import_export/merge_request_parser.rb","lines":{"begin":13,"end":22}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `copy_project_uploads` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d141822a7e49c9987620bcbcaf7749c0","location":{"path":"lib/gitlab/import_export/uploads_manager.rb","lines":{"begin":44,"end":56}},"other_locations":[],"remediation_points":850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Importer` has 21 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"9b57d9528846dda6448ed9d3a49747c3","location":{"path":"lib/gitlab/import_export/importer.rb","lines":{"begin":3,"end":129}},"other_locations":[],"remediation_points":1300000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `imported_object` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7150a66352dfbd84b82e4bfa60942b90","location":{"path":"lib/gitlab/import_export/relation_factory.rb","lines":{"begin":198,"end":209}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `RelationFactory` has 30 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"4f17a460cbd29b77fbb38f05dd3866a4","location":{"path":"lib/gitlab/import_export/relation_factory.rb","lines":{"begin":3,"end":281}},"other_locations":[],"remediation_points":2200000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `project_attributes` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"80346e71805b8ddd466c6b77a8f2e1e6","location":{"path":"lib/gitlab/import_export/group_project_object_builder.rb","lines":{"begin":49,"end":62}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `build` has 7 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"34c8251c050af78b0e432e62b3bf6eaf","location":{"path":"lib/gitlab/data_builder/push.rb","lines":{"begin":56,"end":56}},"other_locations":[],"remediation_points":525000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `build` has 29 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"e5d84ee4338c67ad951b6130bf67d21a","location":{"path":"lib/gitlab/data_builder/push.rb","lines":{"begin":56,"end":98}},"other_locations":[],"remediation_points":696000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `build` has 49 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"ac9809b4ea4dd090261cab4784070118","location":{"path":"lib/gitlab/data_builder/build.rb","lines":{"begin":6,"end":68}},"other_locations":[],"remediation_points":1176000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `absolute_image_urls` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b291bb28522abd9dde68b0387000c263","location":{"path":"lib/gitlab/hook_data/base_builder.rb","lines":{"begin":22,"end":35}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `safe_hook_attributes` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"682e99b5b83244042ccc251929255272","location":{"path":"lib/gitlab/hook_data/merge_request_builder.rb","lines":{"begin":4,"end":32}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `gitaly_client.rb` has 321 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"aa680293a25a35a2aacd0db231b38fc3","location":{"path":"lib/gitlab/gitaly_client.rb","lines":{"begin":1,"end":484}},"other_locations":[],"remediation_points":2222400,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `call` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"96a0315d42972363e3be0faaf33fcff8","location":{"path":"lib/gitlab/gitaly_client.rb","lines":{"begin":124,"end":149}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `request_kwargs` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"62070bc24b2fd5133e0a7beab00d9b77","location":{"path":"lib/gitlab/gitaly_client.rb","lines":{"begin":197,"end":221}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `feature_enabled?` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"731633ec642f522eb73bf54d30cc752d","location":{"path":"lib/gitlab/gitaly_client.rb","lines":{"begin":239,"end":269}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `enforce_gitaly_request_limits` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a75016ab6541606469d82939c599b4ad","location":{"path":"lib/gitlab/gitaly_client.rb","lines":{"begin":317,"end":340}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `issues` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"625fb557175f1173f5275a5c774ad3d6","location":{"path":"lib/gitlab/reference_extractor.rb","lines":{"begin":34,"end":45}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `metrics` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"77acda463966e33d89aa2e8120528ca8","location":{"path":"lib/gitlab/health_checks/simple_abstract_check.rb","lines":{"begin":17,"end":25}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `profile` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"fee59aefc8f7079890f207651b7981f0","location":{"path":"lib/gitlab/profiler.rb","lines":{"begin":38,"end":79}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `debug` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"fdc82615456346012b61b614b718e980","location":{"path":"lib/gitlab/profiler.rb","lines":{"begin":91,"end":109}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `protected_branch_push_checks` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"32eb78f0c97e724ad8a8d5553b542d3f","location":{"path":"lib/gitlab/checks/change_access.rb","lines":{"begin":89,"end":99}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `protected_tag_checks` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"06f719f8ef5751a719db79c5e8c24be7","location":{"path":"lib/gitlab/checks/change_access.rb","lines":{"begin":111,"end":120}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `ChangeAccess` has 25 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"c155eb2e64ad1ed777bca59ce76dbaef","location":{"path":"lib/gitlab/checks/change_access.rb","lines":{"begin":3,"end":214}},"other_locations":[],"remediation_points":1700000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8ee7f543cac7d3fb2d03c2cf82f45f09","location":{"path":"lib/gitlab/checks/commit_check.rb","lines":{"begin":16,"end":28}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `stop` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0578d528100ce788878962a15cbeec2a","location":{"path":"lib/gitlab/daemon.rb","lines":{"begin":39,"end":51}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `verification_status` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"278e4598e8040e0a02ba62435277a8b2","location":{"path":"lib/gitlab/gpg/commit.rb","lines":{"begin":100,"end":112}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `initialize` has 7 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"26ed72f706cbd880946abd65775661b1","location":{"path":"lib/gitlab/bitbucket_server_import/project_creator.rb","lines":{"begin":6,"end":6}},"other_locations":[],"remediation_points":525000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `importer.rb` has 275 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"144e11b64a9050685cd582324f4c5650","location":{"path":"lib/gitlab/bitbucket_server_import/importer.rb","lines":{"begin":3,"end":388}},"other_locations":[],"remediation_points":1560000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Importer` has 28 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"fe99b8de0e4e755d01efc8644f28aa32","location":{"path":"lib/gitlab/bitbucket_server_import/importer.rb","lines":{"begin":5,"end":386}},"other_locations":[],"remediation_points":2000000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `ensure_hash` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"32c1c4d58157c12dafbd9c492c51a5aa","location":{"path":"lib/gitlab/graphql/variables.rb","lines":{"begin":17,"end":34}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `instrument` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d95b586a43aa6e99b3f767263ce65d16","location":{"path":"lib/gitlab/graphql/present/instrumentation.rb","lines":{"begin":5,"end":32}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `instrument` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7b1d8edac9e190461296777cc29e22e5","location":{"path":"lib/gitlab/graphql/authorize/instrumentation.rb","lines":{"begin":10,"end":31}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `instrument_methods` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d1438aadd557c25b108eea0106855664","location":{"path":"lib/gitlab/metrics/instrumentation.rb","lines":{"begin":70,"end":81}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `instrument_instance_methods` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"eb2114fa42977c795cf347169a0f542c","location":{"path":"lib/gitlab/metrics/instrumentation.rb","lines":{"begin":88,"end":99}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `instrument` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bca595f2e9128a833295cec69e8c1e4e","location":{"path":"lib/gitlab/metrics/instrumentation.rb","lines":{"begin":118,"end":167}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `instrument` has 34 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"46dbb1e9f69c06f7d078548fc6061570","location":{"path":"lib/gitlab/metrics/instrumentation.rb","lines":{"begin":118,"end":167}},"other_locations":[],"remediation_points":816000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `submit` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b4ef0ec3fde55c4188a9f170e0f50760","location":{"path":"lib/gitlab/metrics/transaction.rb","lines":{"begin":114,"end":129}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `submit_metrics` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9b54961b8f59db3e5122c4208ded0a04","location":{"path":"lib/gitlab/metrics/influx_db.rb","lines":{"begin":48,"end":62}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `pool` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"85d4413ec95715375e2c5ed3923bf252","location":{"path":"lib/gitlab/metrics/influx_db.rb","lines":{"begin":165,"end":181}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `measure` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"9ce1cb49fa0e90749c14924f01742eab","location":{"path":"lib/gitlab/metrics/influx_db.rb","lines":{"begin":95,"end":133}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `initialize` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"04b6cf203bf783b43e1ac1b54b888441","location":{"path":"lib/gitlab/fogbugz_import/project_creator.rb","lines":{"begin":6,"end":6}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `format_issue_comment_body` has 6 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"1ec61e94902238cc9befa5a1daf367e9","location":{"path":"lib/gitlab/fogbugz_import/importer.rb","lines":{"begin":279,"end":279}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `import_cases` has a Cognitive Complexity of 16 (exceeds 5 allowed). Consider refactoring.","fingerprint":"deff1dce2bf92e8e8a73a7dad5c4c5c9","location":{"path":"lib/gitlab/fogbugz_import/importer.rb","lines":{"begin":102,"end":146}},"other_locations":[],"remediation_points":1250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `import_issue_comments` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3399ad65a3497aa307eaeb32cb5e83e6","location":{"path":"lib/gitlab/fogbugz_import/importer.rb","lines":{"begin":158,"end":196}},"other_locations":[],"remediation_points":850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `import_cases` has 34 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"cdbe17ce063af3997de1ea4bb7b62f8b","location":{"path":"lib/gitlab/fogbugz_import/importer.rb","lines":{"begin":102,"end":146}},"other_locations":[],"remediation_points":816000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `import_issue_comments` has 30 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"a350dd17c12b659d965d2849ad05d077","location":{"path":"lib/gitlab/fogbugz_import/importer.rb","lines":{"begin":158,"end":196}},"other_locations":[],"remediation_points":720000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `git_access.rb` has 288 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"217b36994b7bc085e2426b68d5ae12da","location":{"path":"lib/gitlab/git_access.rb","lines":{"begin":3,"end":372}},"other_locations":[],"remediation_points":1747200,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `check_authentication_abilities!` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"12742436ece459400a3eaf9d0a1bb60c","location":{"path":"lib/gitlab/git_access.rb","lines":{"begin":128,"end":139}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `ensure_project_on_push!` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"96a9f1789e7e7f1f1ba2da1e54b194c6","location":{"path":"lib/gitlab/git_access.rb","lines":{"begin":189,"end":213}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `check_push_access!` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3ea1e3ce0a376bfea8bcf0212ff90809","location":{"path":"lib/gitlab/git_access.rb","lines":{"begin":233,"end":251}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `GitAccess` has 41 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"8b604fd91125836b6b7febd9f9706b53","location":{"path":"lib/gitlab/git_access.rb","lines":{"begin":4,"end":371}},"other_locations":[],"remediation_points":3300000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create_service_account` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ede2112edc62f1c1aaab207b4d2d3bb8","location":{"path":"lib/gitlab/kubernetes/helm/api.rb","lines":{"begin":49,"end":59}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `create_cluster_role_binding` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"35fbb979c3d0eb66f9ca187bb5295521","location":{"path":"lib/gitlab/kubernetes/helm/api.rb","lines":{"begin":61,"end":71}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `initialize` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"a6788548613abbede0f945c93f499e01","location":{"path":"lib/gitlab/bitbucket_import/project_creator.rb","lines":{"begin":6,"end":6}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `import_issues` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.","fingerprint":"dc7e6d5a30b4b296140a3b3ef8f0e44a","location":{"path":"lib/gitlab/bitbucket_import/importer.rb","lines":{"begin":74,"end":106}},"other_locations":[],"remediation_points":850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `import_issue_comments` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a48dbffa8fed1a096624520d3125343e","location":{"path":"lib/gitlab/bitbucket_import/importer.rb","lines":{"begin":109,"end":134}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `import_pull_requests` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5a484ad1bd84dce7a3bef35405340b71","location":{"path":"lib/gitlab/bitbucket_import/importer.rb","lines":{"begin":147,"end":183}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `import_pull_requests` has 31 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"bb107ec4ecd65c38b8c57821b432e1bd","location":{"path":"lib/gitlab/bitbucket_import/importer.rb","lines":{"begin":147,"end":183}},"other_locations":[],"remediation_points":744000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `get_info` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9ccb0c18a6f37f110aadd6045933f910","location":{"path":"lib/gitlab/auth/ldap/auth_hash.rb","lines":{"begin":19,"end":36}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `tls_options` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"f8cf4abbbf7c74ebb10433a1b19d6e25","location":{"path":"lib/gitlab/auth/ldap/config.rb","lines":{"begin":210,"end":227}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Config` has 38 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"d8bf80e499225a5522c5bf02c2b5de50","location":{"path":"lib/gitlab/auth/ldap/config.rb","lines":{"begin":5,"end":248}},"other_locations":[],"remediation_points":3000000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `allowed?` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1b6717c2575d1b9634403637d926a53e","location":{"path":"lib/gitlab/auth/ldap/access.rb","lines":{"begin":17,"end":32}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `allowed?` has a Cognitive Complexity of 20 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1b6717c2575d1b9634403637d926a53e","location":{"path":"lib/gitlab/auth/ldap/access.rb","lines":{"begin":41,"end":63}},"other_locations":[],"remediation_points":1650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `ldap_search` has a Cognitive Complexity of 15 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5d595594b703b1d9783bd955a198807f","location":{"path":"lib/gitlab/auth/ldap/adapter.rb","lines":{"begin":52,"end":83}},"other_locations":[],"remediation_points":1150000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `each_pair` has a Cognitive Complexity of 43 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0b175175ba20f21bb15cdf8c88896cd1","location":{"path":"lib/gitlab/auth/ldap/dn.rb","lines":{"begin":58,"end":194}},"other_locations":[],"remediation_points":3950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `initialize_array` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d6d33eb81193471d4408113ca113deac","location":{"path":"lib/gitlab/auth/ldap/dn.rb","lines":{"begin":267,"end":281}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `each_pair` has 131 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"648c4eb09b87d49a1d79f5d0a77de3ea","location":{"path":"lib/gitlab/auth/ldap/dn.rb","lines":{"begin":58,"end":194}},"other_locations":[],"remediation_points":3144000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `login` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c350e7d285ce68091161b324ed9ca293","location":{"path":"lib/gitlab/auth/ldap/authentication.rb","lines":{"begin":11,"end":20}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `save` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5b220e2f520a6fff2f90c05ba11999ba","location":{"path":"lib/gitlab/auth/o_auth/user.rb","lines":{"begin":37,"end":52}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find_user` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7a4874f3ff061cb0b1aeef04800ada15","location":{"path":"lib/gitlab/auth/o_auth/user.rb","lines":{"begin":60,"end":69}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `update_profile` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"38ded984fa19d27580db26e0540ac53f","location":{"path":"lib/gitlab/auth/o_auth/user.rb","lines":{"begin":229,"end":253}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `User` has 32 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"e416592e77f689818995fceca5f571bc","location":{"path":"lib/gitlab/auth/o_auth/user.rb","lines":{"begin":9,"end":268}},"other_locations":[],"remediation_points":2400000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find_user` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ba2b8382483d9be5260822909fe26d56","location":{"path":"lib/gitlab/auth/saml/user.rb","lines":{"begin":16,"end":28}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `cache_method_output` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"173a260b95048ce7cfc5164ebeeaa45c","location":{"path":"lib/gitlab/repository_cache_adapter.rb","lines":{"begin":44,"end":70}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `expire_method_caches` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6938667a593219bc8d59f8046973c533","location":{"path":"lib/gitlab/repository_cache_adapter.rb","lines":{"begin":73,"end":86}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `mark` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7f23977dd6af02c109c5ecaf6ec88e79","location":{"path":"lib/gitlab/string_range_marker.rb","lines":{"begin":16,"end":45}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `position_mapping` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"75e44855c1190acfa386bf060fe0c79c","location":{"path":"lib/gitlab/string_range_marker.rb","lines":{"begin":50,"end":88}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `log_response` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7bd641d0b563cc47dc64d5b378494dd5","location":{"path":"lib/gitlab/storage_check/cli.rb","lines":{"begin":49,"end":68}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate_permission!` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"596d8f0ed603043a25830a78af0b7870","location":{"path":"lib/gitlab/email/handler/reply_processing.rb","lines":{"begin":38,"end":47}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6fac16f8fc80d183ffc78d03d2d0245d","location":{"path":"lib/gitlab/email/handler/unsubscribe_handler.rb","lines":{"begin":15,"end":23}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `select_body` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"74ea18f19435d9abee264cd1facce76a","location":{"path":"lib/gitlab/email/reply_parser.rb","lines":{"begin":36,"end":58}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `fix_charset` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bbfbab207f44913ec99bdb0f738ef744","location":{"path":"lib/gitlab/email/reply_parser.rb","lines":{"begin":61,"end":71}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `target_url` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"587a65f54b3a9d4006c9fb8e97881295","location":{"path":"lib/gitlab/email/message/repository_push.rb","lines":{"begin":96,"end":108}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `subject` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"304068a60d47ba6b4d63d0770a3e66e0","location":{"path":"lib/gitlab/email/message/repository_push.rb","lines":{"begin":118,"end":137}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `run!` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"06bf786acefc4467f3887ce0b97790b0","location":{"path":"lib/gitlab/cleanup/remote_uploads.rb","lines":{"begin":13,"end":32}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `steal` has a Cognitive Complexity of 16 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bcfc4aae2401e33076da306af1be4a91","location":{"path":"lib/gitlab/background_migration.rb","lines":{"begin":17,"end":38}},"other_locations":[],"remediation_points":1250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate!` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7f4a6a0b5a98750c352c1646b1b3f685","location":{"path":"lib/gitlab/url_blocker.rb","lines":{"begin":8,"end":37}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `redis_store_options` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8e3b7658d5f2da0b6cfe80e375fba17a","location":{"path":"lib/gitlab/redis/wrapper.rb","lines":{"begin":94,"end":116}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `calculate` has 30 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"027f65d9b15a5a20ac32b7746317815a","location":{"path":"lib/gitlab/project_authorizations/with_nested_groups.rb","lines":{"begin":16,"end":57}},"other_locations":[],"remediation_points":720000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `allowed?` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5ffe0c3e3d42265eae2251a019292113","location":{"path":"lib/gitlab/user_access.rb","lines":{"begin":30,"end":38}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `can_push_to_branch?` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"303070bb63eb58bcb7a05b3b95932900","location":{"path":"lib/gitlab/user_access.rb","lines":{"begin":64,"end":75}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `sanitize` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ce964ef0b84100c7c6ad7cb863485dc1","location":{"path":"lib/gitlab/ssh_public_key.rb","lines":{"begin":24,"end":38}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8bb3319e6987280746e3bc73708c56f0","location":{"path":"lib/gitlab/bare_repository_import/importer.rb","lines":{"begin":6,"end":27}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `to_kubeconfig` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"b447110ec4376566b0f143ec7955f597","location":{"path":"lib/gitlab/kubernetes.rb","lines":{"begin":85,"end":115}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `extract_filters` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"52f2917ff84bcee853228888bc9d4f20","location":{"path":"lib/gitlab/search/query.rb","lines":{"begin":28,"end":48}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `encode!` has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5023e6a2cc1fe373219230a4ada29baa","location":{"path":"lib/gitlab/encoding_helper.rb","lines":{"begin":16,"end":36}},"other_locations":[],"remediation_points":1050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `encode_utf8` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c7dee9a09179a88f06945225a2a221af","location":{"path":"lib/gitlab/encoding_helper.rb","lines":{"begin":51,"end":69}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `handle_exception_response` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"0c36580ef2976c77eabf04d27eda6e0b","location":{"path":"lib/gitlab/prometheus_client.rb","lines":{"begin":78,"end":87}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `generate_full_url` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6347a85ed559890640d3146272847334","location":{"path":"lib/gitlab/url_sanitizer.rb","lines":{"begin":71,"end":78}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `convert` has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring.","fingerprint":"427e98fa770dd0ce1ed98ef15ec75fd5","location":{"path":"lib/gitlab/ci/ansi2html.rb","lines":{"begin":136,"end":189}},"other_locations":[],"remediation_points":1050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `open_new_tag` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"3d7e5bd9e7a6c35c9d687fc490695bed","location":{"path":"lib/gitlab/ci/ansi2html.rb","lines":{"begin":232,"end":256}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `get_xterm_color_class` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4936b554b5287229c74930b44325b20c","location":{"path":"lib/gitlab/ci/ansi2html.rb","lines":{"begin":329,"end":341}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Converter` has 69 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"61a0cb2a3f0303ed57f185452426b79a","location":{"path":"lib/gitlab/ci/ansi2html.rb","lines":{"begin":31,"end":346}},"other_locations":[],"remediation_points":6100000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `convert` has 43 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"dd13e7297553d67e7801e8ccc8eed932","location":{"path":"lib/gitlab/ci/ansi2html.rb","lines":{"begin":136,"end":189}},"other_locations":[],"remediation_points":1032000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `matches_pattern?` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ebde1954a4f6fc95ac088dde003d1f7c","location":{"path":"lib/gitlab/ci/build/policy/refs.rb","lines":{"begin":27,"end":38}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `match_entries` has a Cognitive Complexity of 18 (exceeds 5 allowed). Consider refactoring.","fingerprint":"12277d192b4e56c2980eae35423fc226","location":{"path":"lib/gitlab/ci/build/artifacts/metadata.rb","lines":{"begin":54,"end":76}},"other_locations":[],"remediation_points":1450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `read_version` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c8c5a0217b6a28198bd8cb92d0e82b00","location":{"path":"lib/gitlab/ci/build/artifacts/metadata.rb","lines":{"begin":78,"end":92}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Entry` has 21 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"a996c8f128cfc7543769dd21dd5de815","location":{"path":"lib/gitlab/ci/build/artifacts/metadata/entry.rb","lines":{"begin":15,"end":130}},"other_locations":[],"remediation_points":1300000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `to_s` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6710c7eee920701d15361f52dbe4bd3d","location":{"path":"lib/gitlab/ci/build/artifacts/path.rb","lines":{"begin":26,"end":36}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `read` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"481c8d08e5e47d4a4d4be68d0d06fe4b","location":{"path":"lib/gitlab/ci/trace/chunked_io.rb","lines":{"begin":69,"end":93}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `chunk_slice_from_offset` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"60dbbad2af42b5e9d17acf1180b8e0d6","location":{"path":"lib/gitlab/ci/trace/chunked_io.rb","lines":{"begin":178,"end":189}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `ChunkedIO` has 26 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"3f6175d5d4d29675f68a7afb44b51fb3","location":{"path":"lib/gitlab/ci/trace/chunked_io.rb","lines":{"begin":7,"end":236}},"other_locations":[],"remediation_points":1800000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `extract_coverage` has a Cognitive Complexity of 19 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a126d9b81c791cb0bd1b8cd455422f3b","location":{"path":"lib/gitlab/ci/trace/stream.rb","lines":{"begin":79,"end":102}},"other_locations":[],"remediation_points":1550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `handle_line` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"6e13932e33f438288cd2d7a23cca7b04","location":{"path":"lib/gitlab/ci/trace/section_parser.rb","lines":{"begin":56,"end":56}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find_next_marker` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7b78b80d610593251ebbeb9bb18f6246","location":{"path":"lib/gitlab/ci/trace/section_parser.rb","lines":{"begin":78,"end":93}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate_string_or_regexp` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a99d0cd045678d388fd755c238f7757f","location":{"path":"lib/gitlab/ci/config/entry/legacy_validation_helpers.rb","lines":{"begin":43,"end":52}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `to_hash` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bc0685829f332ba16f511159006c4cf9","location":{"path":"lib/gitlab/ci/config/entry/job.rb","lines":{"begin":136,"end":155}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `variables_expressions_syntax` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"736e4fd1de9745ba1bb433fcb5443516","location":{"path":"lib/gitlab/ci/config/entry/policy.rb","lines":{"begin":41,"end":53}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `attributes` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"69c16e006586bdd7ac4cb17f7ede9848","location":{"path":"lib/gitlab/ci/config/entry/attributable.rb","lines":{"begin":9,"end":21}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `helpers` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2d39bb63c3e71381a6cfd8d51654bee4","location":{"path":"lib/gitlab/ci/config/entry/configurable.rb","lines":{"begin":63,"end":75}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `extend!` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4fa7fe12ebb0fe9c7eed89e17ece5daf","location":{"path":"lib/gitlab/ci/config/extendable/entry.rb","lines":{"begin":48,"end":72}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `write` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4254fbcc9b1008e1fd6a644e17f14b44","location":{"path":"lib/gitlab/ci/trace.rb","lines":{"begin":83,"end":101}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `unsafe_archive!` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"b90c223da9c451bd90087645954fe5ee","location":{"path":"lib/gitlab/ci/trace.rb","lines":{"begin":125,"end":145}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Trace` has 26 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"d9e217fe03ddebc9f270b441d4194d76","location":{"path":"lib/gitlab/ci/trace.rb","lines":{"begin":3,"end":237}},"other_locations":[],"remediation_points":1800000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `perform!` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"56ff592ebb6677c3a386b683db2b6821","location":{"path":"lib/gitlab/ci/pipeline/chain/validate/config.rb","lines":{"begin":9,"end":21}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `tokenize` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"60a6e3ebf3ba798ac11eca1daba671b8","location":{"path":"lib/gitlab/ci/pipeline/expression/lexer.rb","lines":{"begin":36,"end":56}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `tree` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"494fb3f15182110d4c2051f9a07b9ddc","location":{"path":"lib/gitlab/ci/pipeline/expression/parser.rb","lines":{"begin":16,"end":31}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `all_cases` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4f41f387d6f9c748719d97b454bbe92f","location":{"path":"lib/gitlab/ci/parsers/junit.rb","lines":{"begin":22,"end":37}},"other_locations":[],"remediation_points":950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate_job_dependencies!` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"97a1046ed696c51fb2ce1bf34f0b7293","location":{"path":"lib/gitlab/ci/yaml_processor.rb","lines":{"begin":139,"end":151}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate_on_stop_job!` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"06fcc3fed9dc213e5669186830670f59","location":{"path":"lib/gitlab/ci/yaml_processor.rb","lines":{"begin":161,"end":180}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `check` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"5f09e73f4a1aa8458ce984db4f5fce37","location":{"path":"lib/gitlab/downtime_check.rb","lines":{"begin":16,"end":40}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `parse_entry` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4f46e2835f32393dfdf07c66c0f704d0","location":{"path":"lib/gitlab/route_map.rb","lines":{"begin":30,"end":52}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `execute` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e2058f84cad6a346389ce944d7c1c76e","location":{"path":"lib/gitlab/upgrader.rb","lines":{"begin":3,"end":25}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `fuzzy_arel_match` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"44164fac144fbfeea45df1508dfe02db","location":{"path":"lib/gitlab/sql/pattern.rb","lines":{"begin":32,"end":51}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `lazy_page_iterator` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"6ef599b3dc4f1b639d3197c028e40b71","location":{"path":"lib/gitlab/gitlab_import/client.rb","lines":{"begin":59,"end":76}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `merge_hash_tree` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"e6ac0be8cece82ccc2e82ff8dd59e20e","location":{"path":"lib/gitlab/utils/merge_hash.rb","lines":{"begin":58,"end":97}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `listing` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7b99984bc28e1e4cbc4903a72d7ac663","location":{"path":"lib/gitlab/hashed_storage/rake_helper.rb","lines":{"begin":72,"end":87}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `ee_compat_check.rb` has 312 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"2103307f841e293ce32cd4161da95965","location":{"path":"lib/gitlab/ee_compat_check.rb","lines":{"begin":2,"end":440}},"other_locations":[],"remediation_points":2092800,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `generate_patch` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d35820a437b86e532f50e32d127b5ab0","location":{"path":"lib/gitlab/ee_compat_check.rb","lines":{"begin":115,"end":130}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `check_patch` has a Cognitive Complexity of 16 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2b66236ad0f63db5144a0820b94228b9","location":{"path":"lib/gitlab/ee_compat_check.rb","lines":{"begin":178,"end":211}},"other_locations":[],"remediation_points":1250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `EeCompatCheck` has 33 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"36de6fe216cdb6efd396cb08cb43cee5","location":{"path":"lib/gitlab/ee_compat_check.rb","lines":{"begin":4,"end":439}},"other_locations":[],"remediation_points":2500000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `ce_branch_doesnt_apply_cleanly_and_no_ee_branch_msg` has 45 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"e819c9434d1b44e764eb37a75eb1f24c","location":{"path":"lib/gitlab/ee_compat_check.rb","lines":{"begin":336,"end":412}},"other_locations":[],"remediation_points":1080000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `scrub` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7d4324ffa269ec245847b9dd62388202","location":{"path":"lib/gitlab/sanitizers/svg.rb","lines":{"begin":12,"end":33}},"other_locations":[],"remediation_points":850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `<=>` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.","fingerprint":"07c5403aa1fb1c5999cd6138fc8be4c8","location":{"path":"lib/gitlab/version_info.rb","lines":{"begin":21,"end":40}},"other_locations":[],"remediation_points":850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `perform_substitutions` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d72ee6aae32c9c1901f52bf269676a8b","location":{"path":"lib/gitlab/quick_actions/extractor.rb","lines":{"begin":115,"end":134}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `commands_regex` has 30 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"1bf5c2a5cbd5a2d9489e4fefc15a284e","location":{"path":"lib/gitlab/quick_actions/extractor.rb","lines":{"begin":63,"end":113}},"other_locations":[],"remediation_points":720000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `to_h` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a75d7faca54c18a6777848a3850d38cc","location":{"path":"lib/gitlab/quick_actions/command_definition.rb","lines":{"begin":49,"end":66}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `wait` has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bf93e6de620ccd0324ee0deae40e9661","location":{"path":"lib/gitlab/job_waiter.rb","lines":{"begin":44,"end":72}},"other_locations":[],"remediation_points":1050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `validate_number_of_plurals` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"ca29b997f9707951ab1c16832eac75dd","location":{"path":"lib/gitlab/i18n/po_linter.rb","lines":{"begin":86,"end":94}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `fill_in_variables` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7baf89f0f9dd60c092411c5d3c85f5c4","location":{"path":"lib/gitlab/i18n/po_linter.rb","lines":{"begin":222,"end":236}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `PoLinter` has 22 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"befcb8a3c9cdc94613a938be76c2abf4","location":{"path":"lib/gitlab/i18n/po_linter.rb","lines":{"begin":3,"end":276}},"other_locations":[],"remediation_points":1400000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `missing_members?` has 26 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"a92dd0b78adf6408e1bb1362dfd52ac0","location":{"path":"lib/gitlab/background_migration/create_fork_network_memberships_range.rb","lines":{"begin":48,"end":78}},"other_locations":[],"remediation_points":624000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `migrate_stage_index_sql` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"17594a98741c619d81f5982d56852229","location":{"path":"lib/gitlab/background_migration/migrate_stage_index.rb","lines":{"begin":15,"end":44}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `remove_restricted_features_todos` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2f6311086002a50283e8edb15d2db097","location":{"path":"lib/gitlab/background_migration/remove_restricted_todos.rb","lines":{"begin":80,"end":94}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `perform` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"3b81cbbe6df91a033cc8895bc63aa0e7","location":{"path":"lib/gitlab/background_migration/copy_column.rb","lines":{"begin":17,"end":17}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `each_pair` has a Cognitive Complexity of 43 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d8eeaa32395230adf97a240f222c4203","location":{"path":"lib/gitlab/background_migration/normalize_ldap_extern_uids_range.rb","lines":{"begin":53,"end":189}},"other_locations":[],"remediation_points":3950000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `initialize_array` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7098a1e02746bd3280879e695e913e37","location":{"path":"lib/gitlab/background_migration/normalize_ldap_extern_uids_range.rb","lines":{"begin":262,"end":276}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `perform` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bb5327ee9231b73596539ad7b2c167fa","location":{"path":"lib/gitlab/background_migration/normalize_ldap_extern_uids_range.rb","lines":{"begin":300,"end":314}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `each_pair` has 131 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"d03740b18e02c4d6c12a846688367eb2","location":{"path":"lib/gitlab/background_migration/normalize_ldap_extern_uids_range.rb","lines":{"begin":53,"end":189}},"other_locations":[],"remediation_points":3144000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `single_diff_rows` has a Cognitive Complexity of 11 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8c44e90db62947f73461b513d8b2bf71","location":{"path":"lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb","lines":{"begin":86,"end":129}},"other_locations":[],"remediation_points":750000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `single_diff_rows` has 32 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"bc4293178ed4b9812cc3752d52c4c2ae","location":{"path":"lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb","lines":{"begin":86,"end":129}},"other_locations":[],"remediation_points":768000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `median` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8131f9850b467befa49f83c8893e074e","location":{"path":"lib/gitlab/cycle_analytics/base_stage.rb","lines":{"begin":23,"end":46}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `first_time_reference_commit` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"57863573b761b600f6f37177c4bdcc2c","location":{"path":"lib/gitlab/cycle_analytics/plan_event_fetcher.rb","lines":{"begin":40,"end":52}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `groups` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"bb94f91ea8ea9bfebe88077bde7c9c70","location":{"path":"lib/gitlab/blame.rb","lines":{"begin":10,"end":34}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `issuable_meta_data` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"a722790729116e77942fe04c5ea5c2fe","location":{"path":"lib/gitlab/issuable_metadata.rb","lines":{"begin":3,"end":42}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `issuable_meta_data` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"654ad0544dd20bd2a0fa2b2222724814","location":{"path":"lib/gitlab/issuable_metadata.rb","lines":{"begin":3,"end":42}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find_id_by_path` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"249edd9d3a49a4634c75d7f66eddf0d3","location":{"path":"lib/gitlab/git/tree.rb","lines":{"begin":36,"end":52}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `get_submodules_by_name` has a Cognitive Complexity of 16 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1779cdd505003a594a0ec1e401b49750","location":{"path":"lib/gitlab/git/gitmodules_parser.rb","lines":{"begin":45,"end":66}},"other_locations":[],"remediation_points":1250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `merge` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"14d8d23268624da10eee3aa315d71171","location":{"path":"lib/gitlab/git/repository.rb","lines":{"begin":552,"end":552}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `find_commits_by_message` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"03db09f73721e8dc853a0e8d5c5b586a","location":{"path":"lib/gitlab/git/repository.rb","lines":{"begin":948,"end":948}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `repository.rb` has 724 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"4fd0011d1b240dc0bd3776dada53d992","location":{"path":"lib/gitlab/git/repository.rb","lines":{"begin":1,"end":1045}},"other_locations":[],"remediation_points":8025600,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `refs_hash` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"1b3b8f358aa6754b1127fcaf1fc63eab","location":{"path":"lib/gitlab/git/repository.rb","lines":{"begin":461,"end":473}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `process_count_commits_options` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d7dfc3dabbbd3403a850821e31ef9869","location":{"path":"lib/gitlab/git/repository.rb","lines":{"begin":987,"end":1005}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Repository` has 117 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"7e5d4a5ee3414c57e7d1ae875324fab4","location":{"path":"lib/gitlab/git/repository.rb","lines":{"begin":7,"end":1043}},"other_locations":[],"remediation_points":10900000,"severity":"major","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `resolve_lines` has a Cognitive Complexity of 17 (exceeds 5 allowed). Consider refactoring.","fingerprint":"2a9fd4db8c8cf162f378aa963d6765b0","location":{"path":"lib/gitlab/git/conflict/file.rb","lines":{"begin":64,"end":86}},"other_locations":[],"remediation_points":1350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `parse` has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring.","fingerprint":"244c77bd66325eb47245517103368219","location":{"path":"lib/gitlab/git/conflict/parser.rb","lines":{"begin":15,"end":70}},"other_locations":[],"remediation_points":1050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `parse` has 44 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"bf9628db17f21b3c6afe90328a37f6d0","location":{"path":"lib/gitlab/git/conflict/parser.rb","lines":{"begin":15,"end":70}},"other_locations":[],"remediation_points":1056000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8c678916b00a357376bbd89e7d450a28","location":{"path":"lib/gitlab/git/blob.rb","lines":{"begin":24,"end":50}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `parse_attributes` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"4edbf1e31d321135c7006513a4035f15","location":{"path":"lib/gitlab/git/attributes_parser.rb","lines":{"begin":41,"end":77}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `parse_data` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"19a8edffd98f8988b199c80f6919a68a","location":{"path":"lib/gitlab/git/attributes_parser.rb","lines":{"begin":91,"end":108}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `update_page` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"cc6e53b3d35661118499e22b31c33048","location":{"path":"lib/gitlab/git/wiki.rb","lines":{"begin":41,"end":41}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `gitaly_update_page` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"29ae202c7d73dff34ed176c4c489e03c","location":{"path":"lib/gitlab/git/wiki.rb","lines":{"begin":139,"end":139}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Wiki` has 25 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"16108ddc899f6bed5535bed2d4dbd403","location":{"path":"lib/gitlab/git/wiki.rb","lines":{"begin":3,"end":166}},"other_locations":[],"remediation_points":1700000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `initialize` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"992ce430fa1cfa75fffb04b791835530","location":{"path":"lib/gitlab/git/compare.rb","lines":{"begin":8,"end":22}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"file_lines","content":{"body":""},"description":"File `commit.rb` has 261 lines of code (exceeds 250 allowed). Consider refactoring.","fingerprint":"b0e8a3e8bec1d1e4d61a4ca6961eee37","location":{"path":"lib/gitlab/git/commit.rb","lines":{"begin":2,"end":421}},"other_locations":[],"remediation_points":1358400,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `find` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d2501d4f37da4c3f3bfc13d8ddefb8b1","location":{"path":"lib/gitlab/git/commit.rb","lines":{"begin":52,"end":72}},"other_locations":[],"remediation_points":650000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Commit` has 48 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"5c05f17b105a544fbb7b1e653e4e9622","location":{"path":"lib/gitlab/git/commit.rb","lines":{"begin":4,"end":419}},"other_locations":[],"remediation_points":4000000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `each_serialized_patch` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring.","fingerprint":"489c6b7588d70b32aa203aa6c41632df","location":{"path":"lib/gitlab/git/diff_collection.rb","lines":{"begin":120,"end":152}},"other_locations":[],"remediation_points":850000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"argument_count","content":{"body":""},"description":"Method `between` has 5 arguments (exceeds 4 allowed). Consider refactoring.","fingerprint":"4c22ec0e0d894fff0c7dd7383e7e90f2","location":{"path":"lib/gitlab/git/diff.rb","lines":{"begin":31,"end":31}},"other_locations":[],"remediation_points":375000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `process_raw_blame` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"c5cb9f5c58bb1d9925a29d6754967c20","location":{"path":"lib/gitlab/git/blame.rb","lines":{"begin":30,"end":56}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `in_lock` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"68b34982cd05d58d79738b15c96f20f7","location":{"path":"lib/gitlab/exclusive_lease_helpers.rb","lines":{"begin":12,"end":27}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `run_check` has a Cognitive Complexity of 18 (exceeds 5 allowed). Consider refactoring.","fingerprint":"d86f72edc80623f2c31df045a73c54a3","location":{"path":"lib/system_check/simple_executor.rb","lines":{"begin":45,"end":82}},"other_locations":[],"remediation_points":1450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `run_check` has 27 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"32ee25468fc9ba9255e373bf8565a409","location":{"path":"lib/system_check/simple_executor.rb","lines":{"begin":45,"end":82}},"other_locations":[],"remediation_points":648000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `dump` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"90c4b195bc0f9e6e440c936a49f66db4","location":{"path":"lib/backup/database.rb","lines":{"begin":14,"end":48}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `dump` has 28 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"e224fd061ebe87897322d771a18ed4f9","location":{"path":"lib/backup/database.rb","lines":{"begin":14,"end":48}},"other_locations":[],"remediation_points":672000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `dump` has a Cognitive Complexity of 9 (exceeds 5 allowed). Consider refactoring.","fingerprint":"7e1d28a077c128dd08f453c105fdd9df","location":{"path":"lib/backup/repository.rb","lines":{"begin":11,"end":39}},"other_locations":[],"remediation_points":550000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `restore` has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring.","fingerprint":"8c618e2d28195eb4c364400e1b377f3f","location":{"path":"lib/backup/repository.rb","lines":{"begin":74,"end":119}},"other_locations":[],"remediation_points":1050000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `restore` has 38 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"dce1e21850a52796bdc54dd0352fef39","location":{"path":"lib/backup/repository.rb","lines":{"begin":74,"end":119}},"other_locations":[],"remediation_points":912000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `cleanup` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.","fingerprint":"df1565e2084a026c19a57df20f8c1dab","location":{"path":"lib/backup/manager.rb","lines":{"begin":59,"end":72}},"other_locations":[],"remediation_points":350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `remove_old` has a Cognitive Complexity of 17 (exceeds 5 allowed). Consider refactoring.","fingerprint":"25cd2cf6fbb64afd366f3be6ab9d89fd","location":{"path":"lib/backup/manager.rb","lines":{"begin":74,"end":107}},"other_locations":[],"remediation_points":1350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `unpack` has a Cognitive Complexity of 17 (exceeds 5 allowed). Consider refactoring.","fingerprint":"67d7ec9e6873944629ee60ae0c82b98f","location":{"path":"lib/backup/manager.rb","lines":{"begin":110,"end":161}},"other_locations":[],"remediation_points":1350000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_count","content":{"body":""},"description":"Class `Manager` has 21 methods (exceeds 20 allowed). Consider refactoring.","fingerprint":"c011f3bde58a57c5c1b310f99fdde1e8","location":{"path":"lib/backup/manager.rb","lines":{"begin":2,"end":247}},"other_locations":[],"remediation_points":1300000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_lines","content":{"body":""},"description":"Method `unpack` has 41 lines of code (exceeds 25 allowed). Consider refactoring.","fingerprint":"0f4697ee5870ab55f0f0482a90f0aafe","location":{"path":"lib/backup/manager.rb","lines":{"begin":110,"end":161}},"other_locations":[],"remediation_points":984000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `decoded` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"9d399e9cd55ad1c8999c18172266e16d","location":{"path":"lib/omni_auth/strategies/jwt.rb","lines":{"begin":37,"end":51}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `class_for_class` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring.","fingerprint":"44146c776b1d2705ab1e91d14f931ca6","location":{"path":"lib/declarative_policy.rb","lines":{"begin":62,"end":74}},"other_locations":[],"remediation_points":250000,"severity":"minor","type":"issue","engine_name":"structure"},{"categories":["Complexity"],"check_name":"method_complexity","content":{"body":"# Cognitive Complexity\nCognitive Complexity is a measure of how difficult a unit of code is to intuitively understand. Unlike Cyclomatic Complexity, which determines how difficult your code will be to test, Cognitive Complexity tells you how difficult your code will be to read and comprehend.\n\n### A method's cognitive complexity is based on a few simple rules:\n* Code is not considered more complex when it uses shorthand that the language provides for collapsing multiple statements into one\n* Code is considered more complex for each \"break in the linear flow of the code\"\n* Code is considered more complex when \"flow breaking structures are nested\"\n\n### Further reading\n* [Cognitive Complexity docs](https://docs.codeclimate.com/v1.0/docs/cognitive-complexity)\n* [Cognitive Complexity: A new way of measuring understandability](https://www.sonarsource.com/docs/CognitiveComplexity.pdf)\n"},"description":"Method `compute_class_for_class` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring.","fingerprint":"504ef7ee6e8fa9917bb219a3ce5a6531","location":{"path":"lib/declarative_policy.rb","lines":{"begin":76,"end":93}},"other_locations":[],"remediation_points":450000,"severity":"minor","type":"issue","engine_name":"structure"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/auth/ldap/dn.rb","lines":{"begin":23,"end":298}},"remediation_points":14090000,"other_locations":[{"path":"lib/gitlab/background_migration/normalize_ldap_extern_uids_range.rb","lines":{"begin":18,"end":293}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 722**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"1672855f6e5f2e5e61f5f47620f50c44","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/background_migration/normalize_ldap_extern_uids_range.rb","lines":{"begin":18,"end":293}},"remediation_points":14090000,"other_locations":[{"path":"lib/gitlab/auth/ldap/dn.rb","lines":{"begin":23,"end":298}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 722**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"08b04488cb6c1d433518d22f9fd7ac22","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 6 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":8,"end":20}},"remediation_points":1270000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":38,"end":38}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":45,"end":45}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":65,"end":65}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":73,"end":73}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":96,"end":96}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 81**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d3612d232382cae9828e7733da5a69ff","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 6 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":38,"end":38}},"remediation_points":1270000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":8,"end":20}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":45,"end":45}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":65,"end":65}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":73,"end":73}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":96,"end":96}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 81**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d3612d232382cae9828e7733da5a69ff","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 6 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":45,"end":45}},"remediation_points":1270000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":8,"end":20}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":38,"end":38}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":65,"end":65}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":73,"end":73}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":96,"end":96}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 81**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d3612d232382cae9828e7733da5a69ff","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 6 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":65,"end":65}},"remediation_points":1270000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":8,"end":20}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":38,"end":38}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":45,"end":45}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":73,"end":73}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":96,"end":96}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 81**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d3612d232382cae9828e7733da5a69ff","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 6 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":73,"end":73}},"remediation_points":1270000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":8,"end":20}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":38,"end":38}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":45,"end":45}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":65,"end":65}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":96,"end":96}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 81**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d3612d232382cae9828e7733da5a69ff","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 6 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":96,"end":96}},"remediation_points":1270000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":8,"end":20}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":38,"end":38}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":45,"end":45}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":65,"end":65}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":73,"end":73}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 81**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d3612d232382cae9828e7733da5a69ff","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 5 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":47,"end":47}},"remediation_points":1170000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":61,"end":61}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":64,"end":64}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":74,"end":74}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":81,"end":81}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 76**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9d3f720528b273e90fa0c600a4007367","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 5 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":61,"end":61}},"remediation_points":1170000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":47,"end":47}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":64,"end":64}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":74,"end":74}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":81,"end":81}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 76**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9d3f720528b273e90fa0c600a4007367","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 5 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":64,"end":64}},"remediation_points":1170000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":47,"end":47}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":61,"end":61}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":74,"end":74}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":81,"end":81}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 76**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9d3f720528b273e90fa0c600a4007367","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 5 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":74,"end":74}},"remediation_points":1170000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":47,"end":47}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":61,"end":61}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":64,"end":64}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":81,"end":81}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 76**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9d3f720528b273e90fa0c600a4007367","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 5 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":81,"end":81}},"remediation_points":1170000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":47,"end":47}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":61,"end":61}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":64,"end":64}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":74,"end":74}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 76**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9d3f720528b273e90fa0c600a4007367","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":87,"end":87}},"remediation_points":1290000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":88,"end":88}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 82**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"3bfe7daee55e5a8099dd7a73db3a63a6","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":88,"end":88}},"remediation_points":1290000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":87,"end":87}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 82**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"3bfe7daee55e5a8099dd7a73db3a63a6","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":41,"end":41}},"remediation_points":1130000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":42,"end":42}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":58,"end":58}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":59,"end":59}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 74**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8f8e7cbf1a02ae8fa5ae5397530797b7","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":42,"end":42}},"remediation_points":1130000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":41,"end":41}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":58,"end":58}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":59,"end":59}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 74**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8f8e7cbf1a02ae8fa5ae5397530797b7","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":58,"end":58}},"remediation_points":1130000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":41,"end":41}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":42,"end":42}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":59,"end":59}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 74**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8f8e7cbf1a02ae8fa5ae5397530797b7","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":59,"end":59}},"remediation_points":1130000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":41,"end":41}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":42,"end":42}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":58,"end":58}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 74**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8f8e7cbf1a02ae8fa5ae5397530797b7","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":30,"end":30}},"remediation_points":1610000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":31,"end":31}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":95,"end":95}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 98**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"22a2073b162b635650c424f759625ae1","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":31,"end":31}},"remediation_points":1610000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":30,"end":30}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":95,"end":95}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 98**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"22a2073b162b635650c424f759625ae1","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":95,"end":95}},"remediation_points":1610000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":30,"end":30}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":31,"end":31}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 98**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"22a2073b162b635650c424f759625ae1","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/clusters/platforms/kubernetes.rb","lines":{"begin":65,"end":78}},"remediation_points":930000,"other_locations":[{"path":"app/models/project_services/kubernetes_service.rb","lines":{"begin":107,"end":120}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 64**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"4b2ec9ed4e92599e6bbba9a4a97ebeb0","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/project_services/kubernetes_service.rb","lines":{"begin":107,"end":120}},"remediation_points":930000,"other_locations":[{"path":"app/models/clusters/platforms/kubernetes.rb","lines":{"begin":65,"end":78}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 64**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"0c7ce0e1a2c6b9abe1956a85bf8e6e52","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":40,"end":40}},"remediation_points":1350000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":72,"end":72}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":78,"end":78}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 85**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2f55aade2bccc69344fa093ec61a30db","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":72,"end":72}},"remediation_points":1350000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":40,"end":40}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":78,"end":78}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 85**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2f55aade2bccc69344fa093ec61a30db","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":78,"end":78}},"remediation_points":1350000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":40,"end":40}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":72,"end":72}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 85**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2f55aade2bccc69344fa093ec61a30db","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":75,"end":75}},"remediation_points":1230000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":79,"end":79}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":97,"end":97}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 79**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9473b40c2cb0f7afc9308169cf2dced6","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":79,"end":79}},"remediation_points":1230000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":75,"end":75}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":97,"end":97}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 79**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9473b40c2cb0f7afc9308169cf2dced6","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":97,"end":97}},"remediation_points":1230000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":75,"end":75}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":79,"end":79}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 79**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9473b40c2cb0f7afc9308169cf2dced6","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":35,"end":35}},"remediation_points":1090000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":43,"end":43}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":63,"end":63}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 72**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6149a95705035fa65fb27a491aa16e7d","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":43,"end":43}},"remediation_points":1090000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":35,"end":35}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":63,"end":63}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 72**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6149a95705035fa65fb27a491aa16e7d","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":63,"end":63}},"remediation_points":1090000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":35,"end":35}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":43,"end":43}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 72**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6149a95705035fa65fb27a491aa16e7d","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":49,"end":49}},"remediation_points":1070000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":56,"end":56}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":83,"end":83}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 71**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"123ff3d56c152101a1c911f1a95326be","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":56,"end":56}},"remediation_points":1070000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":49,"end":49}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":83,"end":83}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 71**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"123ff3d56c152101a1c911f1a95326be","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":83,"end":83}},"remediation_points":1070000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":49,"end":49}},{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":56,"end":56}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 71**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"123ff3d56c152101a1c911f1a95326be","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/services.rb","lines":{"begin":198,"end":227}},"remediation_points":570000,"other_locations":[{"path":"lib/api/services.rb","lines":{"begin":270,"end":299}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 46**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"672d4e588f6155fa74bf7ca34fedabb2","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/services.rb","lines":{"begin":270,"end":299}},"remediation_points":570000,"other_locations":[{"path":"lib/api/services.rb","lines":{"begin":198,"end":227}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 46**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"672d4e588f6155fa74bf7ca34fedabb2","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":101,"end":101}},"remediation_points":1490000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":103,"end":103}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 92**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"633c7fa21c24339ba725403293231a75","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":103,"end":103}},"remediation_points":1490000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":101,"end":101}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 92**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"633c7fa21c24339ba725403293231a75","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":90,"end":90}},"remediation_points":1390000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":102,"end":102}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 87**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"925e4b3663b9cd9937ee7db7f882dfbc","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":102,"end":102}},"remediation_points":1390000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":90,"end":90}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 87**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"925e4b3663b9cd9937ee7db7f882dfbc","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":55,"end":55}},"remediation_points":1250000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":89,"end":89}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 80**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b931145ce6d6777daae248a043f04d6d","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":89,"end":89}},"remediation_points":1250000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":55,"end":55}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 80**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b931145ce6d6777daae248a043f04d6d","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/bitbucket/collection.rb","lines":{"begin":2,"end":18}},"remediation_points":410000,"other_locations":[{"path":"lib/bitbucket_server/collection.rb","lines":{"begin":4,"end":20}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 38**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9daf3a24f43b64dd40b3841c26c29df5","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/bitbucket_server/collection.rb","lines":{"begin":4,"end":20}},"remediation_points":410000,"other_locations":[{"path":"lib/bitbucket/collection.rb","lines":{"begin":2,"end":18}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 38**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ebc02a5c26ee206388b48b53d93e24a1","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/services.rb","lines":{"begin":40,"end":89}},"remediation_points":1150000,"other_locations":[{"path":"lib/api/services.rb","lines":{"begin":91,"end":140}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 75**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6778d05c8ddc9f6653765ac7ae623751","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/services.rb","lines":{"begin":91,"end":140}},"remediation_points":1150000,"other_locations":[{"path":"lib/api/services.rb","lines":{"begin":40,"end":89}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 75**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6778d05c8ddc9f6653765ac7ae623751","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/git/tag.rb","lines":{"begin":14,"end":24}},"remediation_points":650000,"other_locations":[{"path":"lib/gitlab/git/commit.rb","lines":{"begin":159,"end":169}},{"path":"lib/gitlab/git/commit.rb","lines":{"begin":179,"end":189}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 50**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d27c41bdaed8bbbc1c91788baad098b2","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/git/commit.rb","lines":{"begin":159,"end":169}},"remediation_points":650000,"other_locations":[{"path":"lib/gitlab/git/commit.rb","lines":{"begin":179,"end":189}},{"path":"lib/gitlab/git/tag.rb","lines":{"begin":14,"end":24}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 50**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e87685897f699d56f0c9bba98c92c792","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/git/commit.rb","lines":{"begin":179,"end":189}},"remediation_points":650000,"other_locations":[{"path":"lib/gitlab/git/commit.rb","lines":{"begin":159,"end":169}},{"path":"lib/gitlab/git/tag.rb","lines":{"begin":14,"end":24}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 50**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e87685897f699d56f0c9bba98c92c792","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":46,"end":46}},"remediation_points":1150000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":80,"end":80}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 75**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"482f209ad35861d8a59e5e60275568d2","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":80,"end":80}},"remediation_points":1150000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":46,"end":46}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 75**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"482f209ad35861d8a59e5e60275568d2","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"qa/spec/git/location_spec.rb","lines":{"begin":3,"end":24}},"remediation_points":1130000,"other_locations":[{"path":"qa/spec/git/location_spec.rb","lines":{"begin":29,"end":50}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 74**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"dd9851dda741bf04f8f991425e6b4fa8","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"qa/spec/git/location_spec.rb","lines":{"begin":29,"end":50}},"remediation_points":1130000,"other_locations":[{"path":"qa/spec/git/location_spec.rb","lines":{"begin":3,"end":24}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 74**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"dd9851dda741bf04f8f991425e6b4fa8","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":54,"end":54}},"remediation_points":1110000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":66,"end":66}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 73**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"62cf424fda0f778b3dcc5914fc2096b6","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":66,"end":66}},"remediation_points":1110000,"other_locations":[{"path":"lib/gitlab/sanitizers/svg/whitelist.rb","lines":{"begin":54,"end":54}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 73**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"62cf424fda0f778b3dcc5914fc2096b6","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/system_hooks.rb","lines":{"begin":24,"end":31}},"remediation_points":550000,"other_locations":[{"path":"lib/api/broadcast_messages.rb","lines":{"begin":66,"end":73}},{"path":"lib/api/pipeline_schedules.rb","lines":{"begin":66,"end":73}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"dc8d377ac78b1e411b24adff2bb25ac8","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/broadcast_messages.rb","lines":{"begin":66,"end":73}},"remediation_points":550000,"other_locations":[{"path":"lib/api/pipeline_schedules.rb","lines":{"begin":66,"end":73}},{"path":"lib/api/system_hooks.rb","lines":{"begin":24,"end":31}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d6ed9adeccc2432c442bb7e3b2de77ca","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/pipeline_schedules.rb","lines":{"begin":66,"end":73}},"remediation_points":550000,"other_locations":[{"path":"lib/api/broadcast_messages.rb","lines":{"begin":66,"end":73}},{"path":"lib/api/system_hooks.rb","lines":{"begin":24,"end":31}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e53239021b533bc772fd7c38fd9fbf32","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/http_io.rb","lines":{"begin":76,"end":99}},"remediation_points":930000,"other_locations":[{"path":"lib/gitlab/ci/trace/chunked_io.rb","lines":{"begin":69,"end":92}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 64**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"06b83fddd1854f4cbb5ee692f2b3c479","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/ci/trace/chunked_io.rb","lines":{"begin":69,"end":92}},"remediation_points":930000,"other_locations":[{"path":"lib/gitlab/http_io.rb","lines":{"begin":76,"end":99}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 64**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"fa155c048bfa229583a4b14cba8ef368","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/controllers/projects/commits_controller.rb","lines":{"begin":38,"end":49}},"remediation_points":270000,"other_locations":[{"path":"app/controllers/projects/compare_controller.rb","lines":{"begin":47,"end":58}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 31**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"25a210eb00ee75fb3a27aef364105444","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/controllers/projects/compare_controller.rb","lines":{"begin":47,"end":58}},"remediation_points":270000,"other_locations":[{"path":"app/controllers/projects/commits_controller.rb","lines":{"begin":38,"end":49}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 31**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"3331c85dad0745b1770318b847052656","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/clusters/platforms/kubernetes.rb","lines":{"begin":87,"end":91}},"remediation_points":270000,"other_locations":[{"path":"app/models/project_services/kubernetes_service.rb","lines":{"begin":129,"end":133}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 31**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"a485030c77dac9d4720e17783248f6f2","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/project_services/kubernetes_service.rb","lines":{"begin":129,"end":133}},"remediation_points":270000,"other_locations":[{"path":"app/models/clusters/platforms/kubernetes.rb","lines":{"begin":87,"end":91}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 31**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"70c3aa57163e28d9e2b8cf58b891e37a","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/clusters/platforms/kubernetes.rb","lines":{"begin":153,"end":161}},"remediation_points":230000,"other_locations":[{"path":"app/models/project_services/kubernetes_service.rb","lines":{"begin":209,"end":217}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 29**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"c29d81ebf7e5c4008896a514ac05cd90","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/project_services/kubernetes_service.rb","lines":{"begin":209,"end":217}},"remediation_points":230000,"other_locations":[{"path":"app/models/clusters/platforms/kubernetes.rb","lines":{"begin":153,"end":161}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 29**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"562f28dc8f9527c3acb9451bb9905421","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"rubocop/cop/code_reuse/presenter.rb","lines":{"begin":5,"end":36}},"remediation_points":770000,"other_locations":[{"path":"rubocop/cop/code_reuse/serializer.rb","lines":{"begin":5,"end":36}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 56**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ee8707c802bad394fc157d1bd785ea38","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"rubocop/cop/code_reuse/serializer.rb","lines":{"begin":5,"end":36}},"remediation_points":770000,"other_locations":[{"path":"rubocop/cop/code_reuse/presenter.rb","lines":{"begin":5,"end":36}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 56**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"999d054331f9bf60e9fac34f362dfa33","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/gitaly_client/commit_service.rb","lines":{"begin":363,"end":376}},"remediation_points":730000,"other_locations":[{"path":"lib/gitlab/gitaly_client/ref_service.rb","lines":{"begin":217,"end":230}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 54**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6d5fdcb9f4e92bdc8de77ce0d327e38d","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/gitaly_client/ref_service.rb","lines":{"begin":217,"end":230}},"remediation_points":730000,"other_locations":[{"path":"lib/gitlab/gitaly_client/commit_service.rb","lines":{"begin":363,"end":376}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 54**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b9094b2f402bdf758fbd32cced243c48","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/clusters/platforms/kubernetes.rb","lines":{"begin":143,"end":151}},"remediation_points":170000,"other_locations":[{"path":"app/models/project_services/kubernetes_service.rb","lines":{"begin":199,"end":207}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9cdba14c6ea64993cb19a2d65e8cf92c","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/project_services/kubernetes_service.rb","lines":{"begin":199,"end":207}},"remediation_points":170000,"other_locations":[{"path":"app/models/clusters/platforms/kubernetes.rb","lines":{"begin":143,"end":151}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"a53ce766f9ff3869e29a216c2dd49425","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/controllers/users_controller.rb","lines":{"begin":37,"end":46}},"remediation_points":150000,"other_locations":[{"path":"app/controllers/users_controller.rb","lines":{"begin":50,"end":59}},{"path":"app/controllers/users_controller.rb","lines":{"begin":63,"end":72}},{"path":"app/controllers/users_controller.rb","lines":{"begin":76,"end":85}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"7de6970da5143bb219d1d73c65245a18","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/controllers/users_controller.rb","lines":{"begin":50,"end":59}},"remediation_points":150000,"other_locations":[{"path":"app/controllers/users_controller.rb","lines":{"begin":37,"end":46}},{"path":"app/controllers/users_controller.rb","lines":{"begin":63,"end":72}},{"path":"app/controllers/users_controller.rb","lines":{"begin":76,"end":85}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"7de6970da5143bb219d1d73c65245a18","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/controllers/users_controller.rb","lines":{"begin":63,"end":72}},"remediation_points":150000,"other_locations":[{"path":"app/controllers/users_controller.rb","lines":{"begin":37,"end":46}},{"path":"app/controllers/users_controller.rb","lines":{"begin":50,"end":59}},{"path":"app/controllers/users_controller.rb","lines":{"begin":76,"end":85}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"7de6970da5143bb219d1d73c65245a18","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/controllers/users_controller.rb","lines":{"begin":76,"end":85}},"remediation_points":150000,"other_locations":[{"path":"app/controllers/users_controller.rb","lines":{"begin":37,"end":46}},{"path":"app/controllers/users_controller.rb","lines":{"begin":50,"end":59}},{"path":"app/controllers/users_controller.rb","lines":{"begin":63,"end":72}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"7de6970da5143bb219d1d73c65245a18","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/serializers/note_entity.rb","lines":{"begin":67,"end":68}},"remediation_points":150000,"other_locations":[{"path":"app/serializers/project_note_entity.rb","lines":{"begin":20,"end":21}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"3177b0cd54cd809575f1d61e0a65ac25","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/serializers/project_note_entity.rb","lines":{"begin":20,"end":21}},"remediation_points":150000,"other_locations":[{"path":"app/serializers/note_entity.rb","lines":{"begin":67,"end":68}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"bc28db1513fbf8f22f0e63c12ccb87bb","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/project_hooks.rb","lines":{"begin":66,"end":69}},"remediation_points":150000,"other_locations":[{"path":"lib/api/project_hooks.rb","lines":{"begin":88,"end":91}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"cd274943b0a85d56266ca30e0dc9e6ce","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/project_hooks.rb","lines":{"begin":88,"end":91}},"remediation_points":150000,"other_locations":[{"path":"lib/api/project_hooks.rb","lines":{"begin":66,"end":69}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"cd274943b0a85d56266ca30e0dc9e6ce","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/settings.rb","lines":{"begin":76,"end":83}},"remediation_points":650000,"other_locations":[{"path":"lib/api/runner.rb","lines":{"begin":86,"end":93}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 50**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ad9527e40decd629ae978623c4e6dbb3","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/runner.rb","lines":{"begin":86,"end":93}},"remediation_points":650000,"other_locations":[{"path":"lib/api/settings.rb","lines":{"begin":76,"end":83}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 50**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5a97fc139bd16e6c2c1ebb387c258035","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/commits.rb","lines":{"begin":28,"end":36}},"remediation_points":590000,"other_locations":[{"path":"lib/api/users.rb","lines":{"begin":182,"end":190}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 47**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"4a0f4dd71fe015ff3e29d7ce0c5f5aa0","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/users.rb","lines":{"begin":182,"end":190}},"remediation_points":590000,"other_locations":[{"path":"lib/api/commits.rb","lines":{"begin":28,"end":36}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 47**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"656c922dc9f4dab2a9d07fc10e49f190","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/health_checks/redis/queues_check.rb","lines":{"begin":2,"end":25}},"remediation_points":270000,"other_locations":[{"path":"lib/gitlab/health_checks/redis/cache_check.rb","lines":{"begin":2,"end":25}},{"path":"lib/gitlab/health_checks/redis/shared_state_check.rb","lines":{"begin":2,"end":25}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 31**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"a52f4db116344fb82ae762dfb265af18","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/health_checks/redis/cache_check.rb","lines":{"begin":2,"end":25}},"remediation_points":270000,"other_locations":[{"path":"lib/gitlab/health_checks/redis/queues_check.rb","lines":{"begin":2,"end":25}},{"path":"lib/gitlab/health_checks/redis/shared_state_check.rb","lines":{"begin":2,"end":25}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 31**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"31c92fe357e3684090c3440aef2d0b29","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/health_checks/redis/shared_state_check.rb","lines":{"begin":2,"end":25}},"remediation_points":270000,"other_locations":[{"path":"lib/gitlab/health_checks/redis/cache_check.rb","lines":{"begin":2,"end":25}},{"path":"lib/gitlab/health_checks/redis/queues_check.rb","lines":{"begin":2,"end":25}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 31**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"fed5fac4efc814d8bd6d479976af387a","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/helpers/milestones_helper.rb","lines":{"begin":199,"end":206}},"remediation_points":250000,"other_locations":[{"path":"app/helpers/milestones_helper.rb","lines":{"begin":209,"end":216}},{"path":"app/helpers/milestones_helper.rb","lines":{"begin":219,"end":226}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 30**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9bdbae2675861886dd810a67f252ae76","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/helpers/milestones_helper.rb","lines":{"begin":209,"end":216}},"remediation_points":250000,"other_locations":[{"path":"app/helpers/milestones_helper.rb","lines":{"begin":199,"end":206}},{"path":"app/helpers/milestones_helper.rb","lines":{"begin":219,"end":226}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 30**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9bdbae2675861886dd810a67f252ae76","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/helpers/milestones_helper.rb","lines":{"begin":219,"end":226}},"remediation_points":250000,"other_locations":[{"path":"app/helpers/milestones_helper.rb","lines":{"begin":199,"end":206}},{"path":"app/helpers/milestones_helper.rb","lines":{"begin":209,"end":216}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 30**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9bdbae2675861886dd810a67f252ae76","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/policies/project_policy.rb","lines":{"begin":217,"end":236}},"remediation_points":510000,"other_locations":[{"path":"app/policies/project_policy.rb","lines":{"begin":330,"end":351}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 43**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6f53dee2e0dbe6e42301dfabd181bed2","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/policies/project_policy.rb","lines":{"begin":330,"end":351}},"remediation_points":510000,"other_locations":[{"path":"app/policies/project_policy.rb","lines":{"begin":217,"end":236}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 43**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6f53dee2e0dbe6e42301dfabd181bed2","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/services.rb","lines":{"begin":5,"end":22}},"remediation_points":210000,"other_locations":[{"path":"lib/api/services.rb","lines":{"begin":250,"end":267}},{"path":"lib/api/services.rb","lines":{"begin":322,"end":339}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 28**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"14eeea8dcc69e4efb8f98042eb7ee62c","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/services.rb","lines":{"begin":250,"end":267}},"remediation_points":210000,"other_locations":[{"path":"lib/api/services.rb","lines":{"begin":5,"end":22}},{"path":"lib/api/services.rb","lines":{"begin":322,"end":339}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 28**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"14eeea8dcc69e4efb8f98042eb7ee62c","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/services.rb","lines":{"begin":322,"end":339}},"remediation_points":210000,"other_locations":[{"path":"lib/api/services.rb","lines":{"begin":5,"end":22}},{"path":"lib/api/services.rb","lines":{"begin":250,"end":267}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 28**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"14eeea8dcc69e4efb8f98042eb7ee62c","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/services.rb","lines":{"begin":230,"end":247}},"remediation_points":210000,"other_locations":[{"path":"lib/api/services.rb","lines":{"begin":302,"end":319}},{"path":"lib/api/services.rb","lines":{"begin":511,"end":528}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 28**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"14eeea8dcc69e4efb8f98042eb7ee62c","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/services.rb","lines":{"begin":302,"end":319}},"remediation_points":210000,"other_locations":[{"path":"lib/api/services.rb","lines":{"begin":230,"end":247}},{"path":"lib/api/services.rb","lines":{"begin":511,"end":528}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 28**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"14eeea8dcc69e4efb8f98042eb7ee62c","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/services.rb","lines":{"begin":511,"end":528}},"remediation_points":210000,"other_locations":[{"path":"lib/api/services.rb","lines":{"begin":230,"end":247}},{"path":"lib/api/services.rb","lines":{"begin":302,"end":319}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 28**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"14eeea8dcc69e4efb8f98042eb7ee62c","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/http_io.rb","lines":{"begin":102,"end":119}},"remediation_points":490000,"other_locations":[{"path":"lib/gitlab/ci/trace/chunked_io.rb","lines":{"begin":95,"end":112}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 42**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9fcdc086aaa42b293828e5799976b36c","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/ci/trace/chunked_io.rb","lines":{"begin":95,"end":112}},"remediation_points":490000,"other_locations":[{"path":"lib/gitlab/http_io.rb","lines":{"begin":102,"end":119}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 42**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"0aa489542536e966d0d4ee9d92b86de3","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/policies/project_policy.rb","lines":{"begin":152,"end":170}},"remediation_points":470000,"other_locations":[{"path":"app/policies/project_policy.rb","lines":{"begin":177,"end":195}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 41**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"3960d89aa99311987411af9a2ce4316a","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/policies/project_policy.rb","lines":{"begin":177,"end":195}},"remediation_points":470000,"other_locations":[{"path":"app/policies/project_policy.rb","lines":{"begin":152,"end":170}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 41**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"3960d89aa99311987411af9a2ce4316a","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/tags.rb","lines":{"begin":95,"end":104}},"remediation_points":470000,"other_locations":[{"path":"lib/api/tags.rb","lines":{"begin":115,"end":124}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 41**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"04627bf7d430fe80b4f7d86af94fb085","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/tags.rb","lines":{"begin":115,"end":124}},"remediation_points":470000,"other_locations":[{"path":"lib/api/tags.rb","lines":{"begin":95,"end":104}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 41**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"04627bf7d430fe80b4f7d86af94fb085","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/issues.rb","lines":{"begin":159,"end":171}},"remediation_points":450000,"other_locations":[{"path":"lib/api/commit_statuses.rb","lines":{"begin":16,"end":23}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 40**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"72cad3326805b4987fbe6343ebb3d0fd","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/commit_statuses.rb","lines":{"begin":16,"end":23}},"remediation_points":450000,"other_locations":[{"path":"lib/api/issues.rb","lines":{"begin":159,"end":171}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 40**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"69ab1e3ccd645591451e705830d55186","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/discussions.rb","lines":{"begin":159,"end":163}},"remediation_points":170000,"other_locations":[{"path":"lib/api/discussions.rb","lines":{"begin":194,"end":198}},{"path":"lib/api/discussions.rb","lines":{"begin":209,"end":213}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"94185a2a13c6fd98f5095f170db11d97","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/discussions.rb","lines":{"begin":194,"end":198}},"remediation_points":170000,"other_locations":[{"path":"lib/api/discussions.rb","lines":{"begin":159,"end":163}},{"path":"lib/api/discussions.rb","lines":{"begin":209,"end":213}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"94185a2a13c6fd98f5095f170db11d97","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/discussions.rb","lines":{"begin":209,"end":213}},"remediation_points":170000,"other_locations":[{"path":"lib/api/discussions.rb","lines":{"begin":159,"end":163}},{"path":"lib/api/discussions.rb","lines":{"begin":194,"end":198}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"94185a2a13c6fd98f5095f170db11d97","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"rubocop/cop/migration/timestamps.rb","lines":{"begin":3,"end":22}},"remediation_points":430000,"other_locations":[{"path":"rubocop/cop/migration/remove_index.rb","lines":{"begin":3,"end":21}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 39**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"c7a34cb081b464faf300442c9a9c35d6","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"rubocop/cop/migration/remove_index.rb","lines":{"begin":3,"end":21}},"remediation_points":430000,"other_locations":[{"path":"rubocop/cop/migration/timestamps.rb","lines":{"begin":3,"end":22}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 39**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"1c3d38d7fee5df958c3e432d1dd17b38","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/users.rb","lines":{"begin":265,"end":272}},"remediation_points":150000,"other_locations":[{"path":"lib/api/users.rb","lines":{"begin":330,"end":337}},{"path":"lib/api/users.rb","lines":{"begin":417,"end":423}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b090709c230c91d97c8733ac43a69eb2","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/users.rb","lines":{"begin":330,"end":337}},"remediation_points":150000,"other_locations":[{"path":"lib/api/users.rb","lines":{"begin":265,"end":272}},{"path":"lib/api/users.rb","lines":{"begin":417,"end":423}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b090709c230c91d97c8733ac43a69eb2","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/users.rb","lines":{"begin":417,"end":423}},"remediation_points":150000,"other_locations":[{"path":"lib/api/users.rb","lines":{"begin":265,"end":272}},{"path":"lib/api/users.rb","lines":{"begin":330,"end":337}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b090709c230c91d97c8733ac43a69eb2","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/services.rb","lines":{"begin":172,"end":195}},"remediation_points":390000,"other_locations":[{"path":"lib/api/services.rb","lines":{"begin":645,"end":668}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 37**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ef781c60f85295b7fcab51d2c5fa6dbf","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/services.rb","lines":{"begin":645,"end":668}},"remediation_points":390000,"other_locations":[{"path":"lib/api/services.rb","lines":{"begin":172,"end":195}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 37**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ef781c60f85295b7fcab51d2c5fa6dbf","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/services.rb","lines":{"begin":469,"end":492}},"remediation_points":390000,"other_locations":[{"path":"lib/api/services.rb","lines":{"begin":599,"end":622}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 37**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ef781c60f85295b7fcab51d2c5fa6dbf","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/services.rb","lines":{"begin":599,"end":622}},"remediation_points":390000,"other_locations":[{"path":"lib/api/services.rb","lines":{"begin":469,"end":492}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 37**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ef781c60f85295b7fcab51d2c5fa6dbf","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/variables.rb","lines":{"begin":70,"end":80}},"remediation_points":390000,"other_locations":[{"path":"lib/api/group_variables.rb","lines":{"begin":70,"end":80}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 37**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b710502de22d6ac75887584b4089f55d","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/group_variables.rb","lines":{"begin":70,"end":80}},"remediation_points":390000,"other_locations":[{"path":"lib/api/variables.rb","lines":{"begin":70,"end":80}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 37**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5ed54d7e9dec3ef5264c44b21ab42f3b","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/concerns/relative_positioning.rb","lines":{"begin":63,"end":75}},"remediation_points":370000,"other_locations":[{"path":"app/models/concerns/relative_positioning.rb","lines":{"begin":78,"end":90}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 36**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6a6be26fc5b134ababae60c5b17185e7","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/concerns/relative_positioning.rb","lines":{"begin":78,"end":90}},"remediation_points":370000,"other_locations":[{"path":"app/models/concerns/relative_positioning.rb","lines":{"begin":63,"end":75}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 36**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6a6be26fc5b134ababae60c5b17185e7","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/users.rb","lines":{"begin":241,"end":252}},"remediation_points":370000,"other_locations":[{"path":"lib/api/users.rb","lines":{"begin":305,"end":316}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 36**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b03582b4029701d34f64ca56f039ff3c","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/users.rb","lines":{"begin":305,"end":316}},"remediation_points":370000,"other_locations":[{"path":"lib/api/users.rb","lines":{"begin":241,"end":252}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 36**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b03582b4029701d34f64ca56f039ff3c","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/database/migration_helpers.rb","lines":{"begin":615,"end":622}},"remediation_points":370000,"other_locations":[{"path":"lib/gitlab/database/migration_helpers.rb","lines":{"begin":706,"end":713}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 36**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6613d45047514c566568cdc6b20a1433","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/database/migration_helpers.rb","lines":{"begin":706,"end":713}},"remediation_points":370000,"other_locations":[{"path":"lib/gitlab/database/migration_helpers.rb","lines":{"begin":615,"end":622}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 36**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6613d45047514c566568cdc6b20a1433","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/banzai/filter/user_reference_filter.rb","lines":{"begin":34,"end":47}},"remediation_points":330000,"other_locations":[{"path":"lib/banzai/filter/project_reference_filter.rb","lines":{"begin":30,"end":43}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 34**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e03c415d22f94144c8a11a51bf75449a","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/banzai/filter/project_reference_filter.rb","lines":{"begin":30,"end":43}},"remediation_points":330000,"other_locations":[{"path":"lib/banzai/filter/user_reference_filter.rb","lines":{"begin":34,"end":47}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 34**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8a3a69b8619d932aa827e537f3525e47","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/cycle_analytics/code_stage.rb","lines":{"begin":2,"end":25}},"remediation_points":330000,"other_locations":[{"path":"lib/gitlab/cycle_analytics/review_stage.rb","lines":{"begin":2,"end":25}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 34**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9c27f17bb5883c88a2dcf096a1e3eb10","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/cycle_analytics/review_stage.rb","lines":{"begin":2,"end":25}},"remediation_points":330000,"other_locations":[{"path":"lib/gitlab/cycle_analytics/code_stage.rb","lines":{"begin":2,"end":25}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 34**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"1a85a78111fd009c906af5e3e2e5c1b3","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/project_services/teamcity_service.rb","lines":{"begin":52,"end":61}},"remediation_points":310000,"other_locations":[{"path":"app/models/project_services/bamboo_service.rb","lines":{"begin":49,"end":58}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 33**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"043f75067c16ff3e5d772bc2d1ae6742","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/project_services/bamboo_service.rb","lines":{"begin":49,"end":58}},"remediation_points":310000,"other_locations":[{"path":"app/models/project_services/teamcity_service.rb","lines":{"begin":52,"end":61}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 33**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"3bc437123bd781d63ac2e5f1e2ee6eb3","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/background_migration/set_confidential_note_events_on_webhooks.rb","lines":{"begin":5,"end":22}},"remediation_points":310000,"other_locations":[{"path":"lib/gitlab/background_migration/set_confidential_note_events_on_services.rb","lines":{"begin":5,"end":22}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 33**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"3ed85e9f30996e6d2ccc2e0700c1902e","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/background_migration/set_confidential_note_events_on_services.rb","lines":{"begin":5,"end":22}},"remediation_points":310000,"other_locations":[{"path":"lib/gitlab/background_migration/set_confidential_note_events_on_webhooks.rb","lines":{"begin":5,"end":22}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 33**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"7ea2c375fc2078d33f6958933228ed7c","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/backup/database.rb","lines":{"begin":23,"end":27}},"remediation_points":290000,"other_locations":[{"path":"lib/backup/database.rb","lines":{"begin":57,"end":61}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 32**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"eb17727d02a7c074c3154590d6ac3890","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/backup/database.rb","lines":{"begin":57,"end":61}},"remediation_points":290000,"other_locations":[{"path":"lib/backup/database.rb","lines":{"begin":23,"end":27}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 32**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"eb17727d02a7c074c3154590d6ac3890","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/banzai/filter/user_reference_filter.rb","lines":{"begin":130,"end":135}},"remediation_points":290000,"other_locations":[{"path":"lib/banzai/filter/user_reference_filter.rb","lines":{"begin":138,"end":143}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 32**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"c728f05ae3efb5098c029de0b3280f52","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/banzai/filter/user_reference_filter.rb","lines":{"begin":138,"end":143}},"remediation_points":290000,"other_locations":[{"path":"lib/banzai/filter/user_reference_filter.rb","lines":{"begin":130,"end":135}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 32**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"c728f05ae3efb5098c029de0b3280f52","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/concerns/updated_at_filterable.rb","lines":{"begin":6,"end":11}},"remediation_points":270000,"other_locations":[{"path":"app/models/concerns/created_at_filterable.rb","lines":{"begin":6,"end":11}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 31**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"cf343522a426e7b5b70965cafd123e2d","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/concerns/created_at_filterable.rb","lines":{"begin":6,"end":11}},"remediation_points":270000,"other_locations":[{"path":"app/models/concerns/updated_at_filterable.rb","lines":{"begin":6,"end":11}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 31**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"83ce9e73df4d8e3e8128ba7268e47c86","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/user.rb","lines":{"begin":1183,"end":1185}},"remediation_points":270000,"other_locations":[{"path":"app/models/user.rb","lines":{"begin":1189,"end":1191}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 31**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5c5665e3faea9b14f82119a1c414984d","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/user.rb","lines":{"begin":1189,"end":1191}},"remediation_points":270000,"other_locations":[{"path":"app/models/user.rb","lines":{"begin":1183,"end":1185}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 31**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5c5665e3faea9b14f82119a1c414984d","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/legacy_github_import/importer.rb","lines":{"begin":90,"end":96}},"remediation_points":270000,"other_locations":[{"path":"lib/gitlab/legacy_github_import/importer.rb","lines":{"begin":105,"end":111}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 31**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"fb529d437944a41ecb389c07d4f4b95c","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/legacy_github_import/importer.rb","lines":{"begin":105,"end":111}},"remediation_points":270000,"other_locations":[{"path":"lib/gitlab/legacy_github_import/importer.rb","lines":{"begin":90,"end":96}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 31**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"fb529d437944a41ecb389c07d4f4b95c","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/system_check/app/tmp_writable_check.rb","lines":{"begin":2,"end":24}},"remediation_points":270000,"other_locations":[{"path":"lib/system_check/app/log_writable_check.rb","lines":{"begin":2,"end":24}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 31**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5873e0223d34261535ea9380a655f530","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/system_check/app/log_writable_check.rb","lines":{"begin":2,"end":24}},"remediation_points":270000,"other_locations":[{"path":"lib/system_check/app/tmp_writable_check.rb","lines":{"begin":2,"end":24}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 31**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f5f6516f48de36202ed1fb08b864850e","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/services/search_service.rb","lines":{"begin":12,"end":20}},"remediation_points":250000,"other_locations":[{"path":"app/services/search_service.rb","lines":{"begin":26,"end":34}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 30**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"71865084b25bec6d7d5ead8d752fb091","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/services/search_service.rb","lines":{"begin":26,"end":34}},"remediation_points":250000,"other_locations":[{"path":"app/services/search_service.rb","lines":{"begin":12,"end":20}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 30**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"71865084b25bec6d7d5ead8d752fb091","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/gitaly_client/ref_service.rb","lines":{"begin":192,"end":201}},"remediation_points":250000,"other_locations":[{"path":"lib/gitlab/gitaly_client/ref_service.rb","lines":{"begin":205,"end":214}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 30**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"87efcabb3c142197252756a6564676fa","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/gitaly_client/ref_service.rb","lines":{"begin":205,"end":214}},"remediation_points":250000,"other_locations":[{"path":"lib/gitlab/gitaly_client/ref_service.rb","lines":{"begin":192,"end":201}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 30**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"87efcabb3c142197252756a6564676fa","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb","lines":{"begin":3,"end":12}},"remediation_points":250000,"other_locations":[{"path":"qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb","lines":{"begin":5,"end":14}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 30**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"0022a6eabe051cdbca1e39ad3d0616a0","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb","lines":{"begin":5,"end":14}},"remediation_points":250000,"other_locations":[{"path":"qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb","lines":{"begin":3,"end":12}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 30**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b769bd2ad86996248bc0cb9e9909ad48","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/controllers/admin/impersonation_tokens_controller.rb","lines":{"begin":21,"end":30}},"remediation_points":230000,"other_locations":[{"path":"app/controllers/profiles/personal_access_tokens_controller.rb","lines":{"begin":19,"end":28}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 29**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d66178654f9f4136765d0ea5d8b3e694","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/controllers/profiles/personal_access_tokens_controller.rb","lines":{"begin":19,"end":28}},"remediation_points":230000,"other_locations":[{"path":"app/controllers/admin/impersonation_tokens_controller.rb","lines":{"begin":21,"end":30}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 29**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"7450a990959a14aea730f2b6be2c03b2","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/controllers/projects/clusters_controller.rb","lines":{"begin":72,"end":85}},"remediation_points":230000,"other_locations":[{"path":"app/controllers/projects/clusters_controller.rb","lines":{"begin":88,"end":101}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 29**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9983d989b521b3d7814b329e7276929a","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/controllers/projects/clusters_controller.rb","lines":{"begin":88,"end":101}},"remediation_points":230000,"other_locations":[{"path":"app/controllers/projects/clusters_controller.rb","lines":{"begin":72,"end":85}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 29**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9983d989b521b3d7814b329e7276929a","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/blob_viewer/podspec.rb","lines":{"begin":4,"end":26}},"remediation_points":230000,"other_locations":[{"path":"app/models/blob_viewer/gemspec.rb","lines":{"begin":4,"end":26}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 29**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"bff03fdced6cbae88ff2946f20dc10e3","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/blob_viewer/gemspec.rb","lines":{"begin":4,"end":26}},"remediation_points":230000,"other_locations":[{"path":"app/models/blob_viewer/podspec.rb","lines":{"begin":4,"end":26}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 29**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"51fdccc6768efcdd38f19730ffe72a7c","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/ci/stage.rb","lines":{"begin":96,"end":103}},"remediation_points":230000,"other_locations":[{"path":"app/models/ci/pipeline.rb","lines":{"begin":442,"end":449}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 29**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"25c1e443e5b07fc0b45f399a084137f7","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/ci/pipeline.rb","lines":{"begin":442,"end":449}},"remediation_points":230000,"other_locations":[{"path":"app/models/ci/stage.rb","lines":{"begin":96,"end":103}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 29**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"577c618e98095b86078d36b2ac019b73","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/settings.rb","lines":{"begin":59,"end":63}},"remediation_points":230000,"other_locations":[{"path":"lib/api/tags.rb","lines":{"begin":46,"end":50}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 29**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"34d52e18accbf89e1d40ad4efe71140e","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/tags.rb","lines":{"begin":46,"end":50}},"remediation_points":230000,"other_locations":[{"path":"lib/api/settings.rb","lines":{"begin":59,"end":63}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 29**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"7249b946ecaa77a923de68a038829979","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/finders/group_members_finder.rb","lines":{"begin":18,"end":22}},"remediation_points":210000,"other_locations":[{"path":"app/finders/group_members_finder.rb","lines":{"begin":26,"end":30}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 28**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b855af99fe41d98222cc7d488606c72e","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/finders/group_members_finder.rb","lines":{"begin":26,"end":30}},"remediation_points":210000,"other_locations":[{"path":"app/finders/group_members_finder.rb","lines":{"begin":18,"end":22}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 28**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b855af99fe41d98222cc7d488606c72e","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/members.rb","lines":{"begin":132,"end":137}},"remediation_points":210000,"other_locations":[{"path":"lib/api/access_requests.rb","lines":{"begin":76,"end":81}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 28**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"74eeab655880b068d73bfa1508e15e08","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/access_requests.rb","lines":{"begin":76,"end":81}},"remediation_points":210000,"other_locations":[{"path":"lib/api/members.rb","lines":{"begin":132,"end":137}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 28**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"89dd703acaf685f87aef279f54d3c31a","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/database.rb","lines":{"begin":98,"end":109}},"remediation_points":210000,"other_locations":[{"path":"lib/gitlab/database.rb","lines":{"begin":112,"end":123}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 28**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2b8f3ea2a51c54532c43041c348ab5c3","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/database.rb","lines":{"begin":112,"end":123}},"remediation_points":210000,"other_locations":[{"path":"lib/gitlab/database.rb","lines":{"begin":98,"end":109}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 28**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2b8f3ea2a51c54532c43041c348ab5c3","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/gitaly_client/ref_service.rb","lines":{"begin":44,"end":47}},"remediation_points":210000,"other_locations":[{"path":"lib/gitlab/gitaly_client/ref_service.rb","lines":{"begin":50,"end":53}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 28**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e02e496b4b6107134a36720421ac55a9","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/gitaly_client/ref_service.rb","lines":{"begin":50,"end":53}},"remediation_points":210000,"other_locations":[{"path":"lib/gitlab/gitaly_client/ref_service.rb","lines":{"begin":44,"end":47}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 28**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e02e496b4b6107134a36720421ac55a9","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"qa/spec/runtime/env_spec.rb","lines":{"begin":6,"end":14}},"remediation_points":210000,"other_locations":[{"path":"qa/spec/runtime/env_spec.rb","lines":{"begin":17,"end":25}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 28**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d4456b6f43cef6bfbf9b6d039f749cdc","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"qa/spec/runtime/env_spec.rb","lines":{"begin":17,"end":25}},"remediation_points":210000,"other_locations":[{"path":"qa/spec/runtime/env_spec.rb","lines":{"begin":6,"end":14}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 28**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d4456b6f43cef6bfbf9b6d039f749cdc","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/finders/issuable_finder.rb","lines":{"begin":252,"end":262}},"remediation_points":190000,"other_locations":[{"path":"app/finders/issuable_finder.rb","lines":{"begin":280,"end":290}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 27**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d67c2bf9c225577fade90666e5dfc6e3","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/finders/issuable_finder.rb","lines":{"begin":280,"end":290}},"remediation_points":190000,"other_locations":[{"path":"app/finders/issuable_finder.rb","lines":{"begin":252,"end":262}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 27**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d67c2bf9c225577fade90666e5dfc6e3","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/finders/issuable_finder.rb","lines":{"begin":396,"end":405}},"remediation_points":190000,"other_locations":[{"path":"app/finders/issuable_finder.rb","lines":{"begin":410,"end":419}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 27**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d67c2bf9c225577fade90666e5dfc6e3","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/finders/issuable_finder.rb","lines":{"begin":410,"end":419}},"remediation_points":190000,"other_locations":[{"path":"app/finders/issuable_finder.rb","lines":{"begin":396,"end":405}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 27**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d67c2bf9c225577fade90666e5dfc6e3","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/background_migration/migrate_legacy_artifacts.rb","lines":{"begin":24,"end":61}},"remediation_points":190000,"other_locations":[{"path":"lib/gitlab/background_migration/migrate_legacy_artifacts.rb","lines":{"begin":66,"end":104}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 27**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f75f6fbbc7064f4fdca08c087adf39c3","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/background_migration/migrate_legacy_artifacts.rb","lines":{"begin":66,"end":104}},"remediation_points":190000,"other_locations":[{"path":"lib/gitlab/background_migration/migrate_legacy_artifacts.rb","lines":{"begin":24,"end":61}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 27**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f75f6fbbc7064f4fdca08c087adf39c3","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/checks/change_access.rb","lines":{"begin":4,"end":17}},"remediation_points":190000,"other_locations":[{"path":"lib/gitlab/git_access.rb","lines":{"begin":12,"end":25}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 27**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ef81133143dac9759b71c4ff2fbf45ed","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/git_access.rb","lines":{"begin":12,"end":25}},"remediation_points":190000,"other_locations":[{"path":"lib/gitlab/checks/change_access.rb","lines":{"begin":4,"end":17}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 27**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"26fd0da9b8c1ef08c93581298c4ae63a","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/git/repository.rb","lines":{"begin":564,"end":575}},"remediation_points":190000,"other_locations":[{"path":"lib/gitlab/git/repository.rb","lines":{"begin":579,"end":590}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 27**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"7853b1dd44bd6645b11dfd03b93082d6","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/git/repository.rb","lines":{"begin":579,"end":590}},"remediation_points":190000,"other_locations":[{"path":"lib/gitlab/git/repository.rb","lines":{"begin":564,"end":575}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 27**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"7853b1dd44bd6645b11dfd03b93082d6","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/google_code_import/importer.rb","lines":{"begin":211,"end":225}},"remediation_points":190000,"other_locations":[{"path":"lib/gitlab/fogbugz_import/importer.rb","lines":{"begin":204,"end":210}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 27**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"85278ceed072f59d95f4d59bb38349cd","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/fogbugz_import/importer.rb","lines":{"begin":204,"end":210}},"remediation_points":190000,"other_locations":[{"path":"lib/gitlab/google_code_import/importer.rb","lines":{"begin":211,"end":225}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 27**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"84267e4195b1ef161585bb368ab56cb4","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/mailers/emails/profile.rb","lines":{"begin":13,"end":20}},"remediation_points":170000,"other_locations":[{"path":"app/mailers/emails/profile.rb","lines":{"begin":25,"end":32}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"08b3c569353eb654d48c0f3d5dfd5507","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/mailers/emails/profile.rb","lines":{"begin":25,"end":32}},"remediation_points":170000,"other_locations":[{"path":"app/mailers/emails/profile.rb","lines":{"begin":13,"end":20}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"08b3c569353eb654d48c0f3d5dfd5507","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/prometheus_metric.rb","lines":{"begin":31,"end":43}},"remediation_points":170000,"other_locations":[{"path":"app/helpers/preferences_helper.rb","lines":{"begin":13,"end":22}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"84368938cf4e38b28be7f2494ab7dded","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/helpers/preferences_helper.rb","lines":{"begin":13,"end":22}},"remediation_points":170000,"other_locations":[{"path":"app/models/prometheus_metric.rb","lines":{"begin":31,"end":43}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"60bfb34cb2ceca3dea92da73de2720d1","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/repository.rb","lines":{"begin":826,"end":838}},"remediation_points":170000,"other_locations":[{"path":"app/models/repository.rb","lines":{"begin":842,"end":854}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f850bbad5c6c0dbf53dcda181b0fe2ef","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/repository.rb","lines":{"begin":842,"end":854}},"remediation_points":170000,"other_locations":[{"path":"app/models/repository.rb","lines":{"begin":826,"end":838}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f850bbad5c6c0dbf53dcda181b0fe2ef","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/user.rb","lines":{"begin":1195,"end":1197}},"remediation_points":170000,"other_locations":[{"path":"app/models/user.rb","lines":{"begin":1201,"end":1203}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"79536c6f949eba9317227c4e88951f1f","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/user.rb","lines":{"begin":1201,"end":1203}},"remediation_points":170000,"other_locations":[{"path":"app/models/user.rb","lines":{"begin":1195,"end":1197}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"79536c6f949eba9317227c4e88951f1f","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/presenters/project_presenter.rb","lines":{"begin":233,"end":242}},"remediation_points":170000,"other_locations":[{"path":"app/presenters/project_presenter.rb","lines":{"begin":263,"end":272}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"c2d74780d6448543b93af9ac07770eb6","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/presenters/project_presenter.rb","lines":{"begin":263,"end":272}},"remediation_points":170000,"other_locations":[{"path":"app/presenters/project_presenter.rb","lines":{"begin":233,"end":242}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"c2d74780d6448543b93af9ac07770eb6","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/services/protected_branches/legacy_api_update_service.rb","lines":{"begin":18,"end":22}},"remediation_points":170000,"other_locations":[{"path":"app/services/protected_branches/legacy_api_update_service.rb","lines":{"begin":25,"end":29}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2a21c2dc3f646e0e31fff25ee48b9b44","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/services/protected_branches/legacy_api_update_service.rb","lines":{"begin":25,"end":29}},"remediation_points":170000,"other_locations":[{"path":"app/services/protected_branches/legacy_api_update_service.rb","lines":{"begin":18,"end":22}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2a21c2dc3f646e0e31fff25ee48b9b44","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/services/quick_actions/interpret_service.rb","lines":{"begin":222,"end":229}},"remediation_points":170000,"other_locations":[{"path":"app/services/quick_actions/interpret_service.rb","lines":{"begin":276,"end":283}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"c5f1ca2a225a96cfa3b4fc88b12b03b0","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/services/quick_actions/interpret_service.rb","lines":{"begin":276,"end":283}},"remediation_points":170000,"other_locations":[{"path":"app/services/quick_actions/interpret_service.rb","lines":{"begin":222,"end":229}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"c5f1ca2a225a96cfa3b4fc88b12b03b0","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/branches.rb","lines":{"begin":71,"end":75}},"remediation_points":170000,"other_locations":[{"path":"lib/api/triggers.rb","lines":{"begin":12,"end":16}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6da3752f53f9199ec80a8ad0d2b565c1","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/triggers.rb","lines":{"begin":12,"end":16}},"remediation_points":170000,"other_locations":[{"path":"lib/api/branches.rb","lines":{"begin":71,"end":75}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2a596f82671816ebb68812ebe7bf8287","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/variables.rb","lines":{"begin":31,"end":38}},"remediation_points":170000,"other_locations":[{"path":"lib/api/group_variables.rb","lines":{"begin":31,"end":38}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9c68d19fac636a233c57119e7465aae0","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/group_variables.rb","lines":{"begin":31,"end":38}},"remediation_points":170000,"other_locations":[{"path":"lib/api/variables.rb","lines":{"begin":31,"end":38}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"fb90f649add7621cd688c8cf825bd6ac","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/banzai/filter/spaced_link_filter.rb","lines":{"begin":47,"end":56}},"remediation_points":170000,"other_locations":[{"path":"lib/banzai/filter/autolink_filter.rb","lines":{"begin":54,"end":63}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"bde5f678a848776d31606c1f7b9474fa","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/banzai/filter/autolink_filter.rb","lines":{"begin":54,"end":63}},"remediation_points":170000,"other_locations":[{"path":"lib/banzai/filter/spaced_link_filter.rb","lines":{"begin":47,"end":56}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"37daabf17a192f4d7be1f8b27c2260a6","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/background_migration/fill_file_store_job_artifact.rb","lines":{"begin":5,"end":15}},"remediation_points":170000,"other_locations":[{"path":"lib/gitlab/background_migration/fill_file_store_lfs_object.rb","lines":{"begin":5,"end":15}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8744b4f4833ad7e9ac1e28093ac9f90e","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/background_migration/fill_file_store_lfs_object.rb","lines":{"begin":5,"end":15}},"remediation_points":170000,"other_locations":[{"path":"lib/gitlab/background_migration/fill_file_store_job_artifact.rb","lines":{"begin":5,"end":15}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"7504dbd080f799a40cd6f4e9f9588e2e","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/gitaly_client/commit_service.rb","lines":{"begin":419,"end":427}},"remediation_points":170000,"other_locations":[{"path":"lib/gitlab/gitaly_client/blob_service.rb","lines":{"begin":93,"end":101}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"63af7969c300adefbe9421c884f45ddf","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/gitaly_client/blob_service.rb","lines":{"begin":93,"end":101}},"remediation_points":170000,"other_locations":[{"path":"lib/gitlab/gitaly_client/commit_service.rb","lines":{"begin":419,"end":427}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"037891a3606e1c8a2fffd32f88e7cede","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/metrics/samplers/unicorn_sampler.rb","lines":{"begin":23,"end":25}},"remediation_points":170000,"other_locations":[{"path":"lib/gitlab/metrics/samplers/unicorn_sampler.rb","lines":{"begin":28,"end":30}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8a65a519016a876bba37ba5a3c7a819f","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/metrics/samplers/unicorn_sampler.rb","lines":{"begin":28,"end":30}},"remediation_points":170000,"other_locations":[{"path":"lib/gitlab/metrics/samplers/unicorn_sampler.rb","lines":{"begin":23,"end":25}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8a65a519016a876bba37ba5a3c7a819f","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/system_check/orphans/repository_check.rb","lines":{"begin":25,"end":32}},"remediation_points":170000,"other_locations":[{"path":"lib/system_check/orphans/namespace_check.rb","lines":{"begin":23,"end":30}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6d29fff75b609f46ded82f4a44c12b3e","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/system_check/orphans/namespace_check.rb","lines":{"begin":23,"end":30}},"remediation_points":170000,"other_locations":[{"path":"lib/system_check/orphans/repository_check.rb","lines":{"begin":25,"end":32}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 26**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f5b93c21edd90205b8238e3ade31ae23","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/finders/concerns/created_at_filter.rb","lines":{"begin":4,"end":8}},"remediation_points":150000,"other_locations":[{"path":"app/finders/issuable_finder.rb","lines":{"begin":315,"end":319}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"4781409b61d0fe8557e646dde62af4ee","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/finders/issuable_finder.rb","lines":{"begin":315,"end":319}},"remediation_points":150000,"other_locations":[{"path":"app/finders/concerns/created_at_filter.rb","lines":{"begin":4,"end":8}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"99f151d4d58ba006fbb17af802305432","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/ci/pipeline.rb","lines":{"begin":572,"end":575}},"remediation_points":150000,"other_locations":[{"path":"app/models/ci/runner.rb","lines":{"begin":220,"end":223}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"3c0fb0db7a1fa6852c67bd50857aa448","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/models/ci/runner.rb","lines":{"begin":220,"end":223}},"remediation_points":150000,"other_locations":[{"path":"app/models/ci/pipeline.rb","lines":{"begin":572,"end":575}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"44cfa492a10b5b72b394efe01cd9e29d","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/variables.rb","lines":{"begin":49,"end":57}},"remediation_points":150000,"other_locations":[{"path":"lib/api/group_variables.rb","lines":{"begin":49,"end":57}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"320c3b54951e69257faaca3316f72058","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/api/group_variables.rb","lines":{"begin":49,"end":57}},"remediation_points":150000,"other_locations":[{"path":"lib/api/variables.rb","lines":{"begin":49,"end":57}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"fa689b5b4bab39de500b86b3d6814963","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/background_migration/fix_cross_project_label_links.rb","lines":{"begin":65,"end":75}},"remediation_points":150000,"other_locations":[{"path":"lib/gitlab/background_migration/fix_cross_project_label_links.rb","lines":{"begin":81,"end":91}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"26a19237576df2b97ff121c3b0cd2342","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/background_migration/fix_cross_project_label_links.rb","lines":{"begin":81,"end":91}},"remediation_points":150000,"other_locations":[{"path":"lib/gitlab/background_migration/fix_cross_project_label_links.rb","lines":{"begin":65,"end":75}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"26a19237576df2b97ff121c3b0cd2342","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/gitaly_client/repository_service.rb","lines":{"begin":136,"end":150}},"remediation_points":150000,"other_locations":[{"path":"lib/gitlab/gitaly_client/repository_service.rb","lines":{"begin":153,"end":167}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"fc526fdd6733948898ee897d1eef487e","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/gitaly_client/repository_service.rb","lines":{"begin":153,"end":167}},"remediation_points":150000,"other_locations":[{"path":"lib/gitlab/gitaly_client/repository_service.rb","lines":{"begin":136,"end":150}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"fc526fdd6733948898ee897d1eef487e","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/redis/shared_state.rb","lines":{"begin":13,"end":29}},"remediation_points":150000,"other_locations":[{"path":"lib/gitlab/redis/queues.rb","lines":{"begin":12,"end":28}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"077a90f16d3842a49d8095f339e2187f","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/redis/queues.rb","lines":{"begin":12,"end":28}},"remediation_points":150000,"other_locations":[{"path":"lib/gitlab/redis/shared_state.rb","lines":{"begin":13,"end":29}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f48114ce0a7710485f176b1b75c08e79","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/template/issue_template.rb","lines":{"begin":2,"end":14}},"remediation_points":150000,"other_locations":[{"path":"lib/gitlab/template/merge_request_template.rb","lines":{"begin":2,"end":14}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"685a5435dac10b7fc45977c34f30aba3","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"lib/gitlab/template/merge_request_template.rb","lines":{"begin":2,"end":14}},"remediation_points":150000,"other_locations":[{"path":"lib/gitlab/template/issue_template.rb","lines":{"begin":2,"end":14}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 25**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"bc65c6ec010926daa88fbdcb539ddeea","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/environments/mixins/environments_mixin.js","lines":{"begin":164,"end":170}},"remediation_points":870000,"other_locations":[{"path":"app/assets/javascripts/jobs/job_details_mediator.js","lines":{"begin":41,"end":47}},{"path":"app/assets/javascripts/pipelines/mixins/pipelines.js","lines":{"begin":45,"end":51}},{"path":"app/assets/javascripts/pipelines/pipeline_details_mediator.js","lines":{"begin":33,"end":39}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 64**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2d6588749bb4b05d1e583e13b9a75e39","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pipelines/pipeline_details_mediator.js","lines":{"begin":33,"end":39}},"remediation_points":870000,"other_locations":[{"path":"app/assets/javascripts/environments/mixins/environments_mixin.js","lines":{"begin":164,"end":170}},{"path":"app/assets/javascripts/jobs/job_details_mediator.js","lines":{"begin":41,"end":47}},{"path":"app/assets/javascripts/pipelines/mixins/pipelines.js","lines":{"begin":45,"end":51}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 64**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e1b42460d85ed0074c2f1fbd38bf2631","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pipelines/mixins/pipelines.js","lines":{"begin":45,"end":51}},"remediation_points":870000,"other_locations":[{"path":"app/assets/javascripts/environments/mixins/environments_mixin.js","lines":{"begin":164,"end":170}},{"path":"app/assets/javascripts/jobs/job_details_mediator.js","lines":{"begin":41,"end":47}},{"path":"app/assets/javascripts/pipelines/pipeline_details_mediator.js","lines":{"begin":33,"end":39}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 64**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f4d765094c9218d5390de58501e17b93","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/jobs/job_details_mediator.js","lines":{"begin":41,"end":47}},"remediation_points":870000,"other_locations":[{"path":"app/assets/javascripts/environments/mixins/environments_mixin.js","lines":{"begin":164,"end":170}},{"path":"app/assets/javascripts/pipelines/mixins/pipelines.js","lines":{"begin":45,"end":51}},{"path":"app/assets/javascripts/pipelines/pipeline_details_mediator.js","lines":{"begin":33,"end":39}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 64**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"caa789e408f667bb83169e9a6e4f54bb","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/mutations.js","lines":{"begin":198,"end":200}},"remediation_points":690000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":142,"end":144}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":148,"end":150}},{"path":"app/assets/javascripts/ide/stores/mutations/tree.js","lines":{"begin":42,"end":44}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 58**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"7b7e24c67302a04433b92238befc3cf1","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/mutations/tree.js","lines":{"begin":42,"end":44}},"remediation_points":690000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/mutations.js","lines":{"begin":198,"end":200}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":142,"end":144}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":148,"end":150}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 58**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"935ca74221c521771d96150adf2278fe","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":142,"end":144}},"remediation_points":690000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/mutations.js","lines":{"begin":198,"end":200}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":148,"end":150}},{"path":"app/assets/javascripts/ide/stores/mutations/tree.js","lines":{"begin":42,"end":44}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 58**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"db86386cff8c19e24cbadfb75750f1d9","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":148,"end":150}},"remediation_points":690000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/mutations.js","lines":{"begin":198,"end":200}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":142,"end":144}},{"path":"app/assets/javascripts/ide/stores/mutations/tree.js","lines":{"begin":42,"end":44}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 58**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"db86386cff8c19e24cbadfb75750f1d9","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":7,"end":41}},"remediation_points":960000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":43,"end":74}},{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":76,"end":108}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 67**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"37429fdf41dd049c7cec6890f8e50c82","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":43,"end":74}},"remediation_points":960000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":7,"end":41}},{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":76,"end":108}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 67**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"37429fdf41dd049c7cec6890f8e50c82","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":76,"end":108}},"remediation_points":960000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":7,"end":41}},{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":43,"end":74}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 67**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"37429fdf41dd049c7cec6890f8e50c82","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/lib/utils/datetime_utility.js","lines":{"begin":79,"end":96}},"remediation_points":4710000,"other_locations":[{"path":"app/assets/javascripts/lib/utils/datetime_utility.js","lines":{"begin":97,"end":114}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 192**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"860f8a405f1b26af1f14049631bd7aa9","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/lib/utils/datetime_utility.js","lines":{"begin":97,"end":114}},"remediation_points":4710000,"other_locations":[{"path":"app/assets/javascripts/lib/utils/datetime_utility.js","lines":{"begin":79,"end":96}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 192**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"860f8a405f1b26af1f14049631bd7aa9","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/subscription_select.js","lines":{"begin":3,"end":26}},"remediation_points":4710000,"other_locations":[{"path":"app/assets/javascripts/issue_status_select.js","lines":{"begin":3,"end":25}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 192**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d440b0e1b0cca3d485fda9e0c4aaee09","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/issue_status_select.js","lines":{"begin":3,"end":25}},"remediation_points":4710000,"other_locations":[{"path":"app/assets/javascripts/subscription_select.js","lines":{"begin":3,"end":26}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 192**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d85cea2030ab41431ddc90787eb11389","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js","lines":{"begin":5,"end":32}},"remediation_points":4620000,"other_locations":[{"path":"app/assets/javascripts/blob/template_selectors/dockerfile_selector.js","lines":{"begin":5,"end":32}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 189**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"4a9d91d82457a2a845b5366d5f0ce5b4","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/blob/template_selectors/dockerfile_selector.js","lines":{"begin":5,"end":32}},"remediation_points":4620000,"other_locations":[{"path":"app/assets/javascripts/blob/template_selectors/ci_yaml_selector.js","lines":{"begin":5,"end":32}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 189**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9a6d28971082883e9748dd3bac2a6695","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/merge_request_tabs.js","lines":{"begin":316,"end":324}},"remediation_points":1470000,"other_locations":[{"path":"app/assets/javascripts/commit/pipelines/pipelines_bundle.js","lines":{"begin":34,"end":42}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 84**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5595f472c12029fb0da2e625d62d94d6","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/commit/pipelines/pipelines_bundle.js","lines":{"begin":34,"end":42}},"remediation_points":1470000,"other_locations":[{"path":"app/assets/javascripts/merge_request_tabs.js","lines":{"begin":316,"end":324}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 84**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"30d9e8739fb74a1a2a7618b85b5e6f7a","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":1204,"end":1222}},"remediation_points":3990000,"other_locations":[{"path":"app/assets/javascripts/notes.js","lines":{"begin":1222,"end":1240}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 168**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"4725f16bae793b141b64c0921a6539b7","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":1222,"end":1240}},"remediation_points":3990000,"other_locations":[{"path":"app/assets/javascripts/notes.js","lines":{"begin":1204,"end":1222}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 168**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"4725f16bae793b141b64c0921a6539b7","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":13,"end":37}},"remediation_points":2280000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":49,"end":70}},{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":82,"end":104}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 111**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"bc78d02c62558d8dc38d2567eaf302a7","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":49,"end":70}},"remediation_points":2280000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":13,"end":37}},{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":82,"end":104}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 111**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"bc78d02c62558d8dc38d2567eaf302a7","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":82,"end":104}},"remediation_points":2280000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":13,"end":37}},{"path":"app/assets/javascripts/ide/stores/actions/merge_request.js","lines":{"begin":49,"end":70}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 111**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"bc78d02c62558d8dc38d2567eaf302a7","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/group_avatar.js","lines":{"begin":3,"end":14}},"remediation_points":3810000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/shared/project_avatar.js","lines":{"begin":3,"end":15}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 162**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"90682f4af3abe93c6405cd6eb215e9c6","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/shared/project_avatar.js","lines":{"begin":3,"end":15}},"remediation_points":3810000,"other_locations":[{"path":"app/assets/javascripts/group_avatar.js","lines":{"begin":3,"end":14}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 162**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"67e63301cd433971695d7cc16ff752b2","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/boards/components/new_list_dropdown.js","lines":{"begin":14,"end":23}},"remediation_points":1350000,"other_locations":[{"path":"app/assets/javascripts/boards/components/new_list_dropdown.js","lines":{"begin":66,"end":75}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 80**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"272dee8d71a4ab9c8d815e23c04c7742","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/boards/components/new_list_dropdown.js","lines":{"begin":66,"end":75}},"remediation_points":1350000,"other_locations":[{"path":"app/assets/javascripts/boards/components/new_list_dropdown.js","lines":{"begin":14,"end":23}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 80**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"272dee8d71a4ab9c8d815e23c04c7742","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 5 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":76,"end":80}},"remediation_points":780000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":91,"end":95}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":96,"end":100}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":123,"end":127}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":217,"end":221}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 61**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b1e5c7e2317fc81ce11cbdb1bfee15df","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 5 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":91,"end":95}},"remediation_points":780000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":76,"end":80}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":96,"end":100}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":123,"end":127}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":217,"end":221}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 61**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b1e5c7e2317fc81ce11cbdb1bfee15df","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 5 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":96,"end":100}},"remediation_points":780000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":76,"end":80}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":91,"end":95}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":123,"end":127}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":217,"end":221}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 61**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b1e5c7e2317fc81ce11cbdb1bfee15df","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 5 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":123,"end":127}},"remediation_points":780000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":76,"end":80}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":91,"end":95}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":96,"end":100}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":217,"end":221}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 61**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b1e5c7e2317fc81ce11cbdb1bfee15df","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 5 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":217,"end":221}},"remediation_points":780000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":76,"end":80}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":91,"end":95}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":96,"end":100}},{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":123,"end":127}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 61**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b1e5c7e2317fc81ce11cbdb1bfee15df","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/u2f/register.js","lines":{"begin":55,"end":59}},"remediation_points":1050000,"other_locations":[{"path":"app/assets/javascripts/u2f/authenticate.js","lines":{"begin":70,"end":74}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 70**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2f1257b0729020dbf8c1e761c6b423db","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/u2f/authenticate.js","lines":{"begin":70,"end":74}},"remediation_points":1050000,"other_locations":[{"path":"app/assets/javascripts/u2f/register.js","lines":{"begin":55,"end":59}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 70**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"39bdab25a792c5662feb840979099a97","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/commons/polyfills/element.js","lines":{"begin":14,"end":19}},"remediation_points":1020000,"other_locations":[{"path":"app/assets/javascripts/lib/utils/common_utils.js","lines":{"begin":278,"end":283}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 69**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b95252006271b6a23d2d59296a0e5778","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/lib/utils/common_utils.js","lines":{"begin":278,"end":283}},"remediation_points":1020000,"other_locations":[{"path":"app/assets/javascripts/commons/polyfills/element.js","lines":{"begin":14,"end":19}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 69**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"67ee0da8e9d2d3b183449d9e8d462f44","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":37,"end":57}},"remediation_points":960000,"other_locations":[{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":99,"end":135}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 67**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6e9b85292de8771601751d3ed0d9dc18","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":99,"end":135}},"remediation_points":960000,"other_locations":[{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":37,"end":57}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 67**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6e9b85292de8771601751d3ed0d9dc18","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/notes/stores/actions.js","lines":{"begin":105,"end":115}},"remediation_points":2700000,"other_locations":[{"path":"app/assets/javascripts/notes/stores/actions.js","lines":{"begin":117,"end":127}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 125**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"0fee1b42ff17f6df3a6f14e35f13cf18","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/notes/stores/actions.js","lines":{"begin":117,"end":127}},"remediation_points":2700000,"other_locations":[{"path":"app/assets/javascripts/notes/stores/actions.js","lines":{"begin":105,"end":115}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 125**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"0fee1b42ff17f6df3a6f14e35f13cf18","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":183,"end":186}},"remediation_points":750000,"other_locations":[{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":188,"end":191}},{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":193,"end":196}},{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":198,"end":201}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 60**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8fc9b42e2195587e4e8d777e75ad89d8","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":188,"end":191}},"remediation_points":750000,"other_locations":[{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":183,"end":186}},{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":193,"end":196}},{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":198,"end":201}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 60**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8fc9b42e2195587e4e8d777e75ad89d8","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":193,"end":196}},"remediation_points":750000,"other_locations":[{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":183,"end":186}},{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":188,"end":191}},{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":198,"end":201}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 60**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8fc9b42e2195587e4e8d777e75ad89d8","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 4 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":198,"end":201}},"remediation_points":750000,"other_locations":[{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":183,"end":186}},{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":188,"end":191}},{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":193,"end":196}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 60**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8fc9b42e2195587e4e8d777e75ad89d8","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/snippets/show/index.js","lines":{"begin":7,"end":13}},"remediation_points":720000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/snippets/show/index.js","lines":{"begin":7,"end":13}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 59**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"15c8237c5ef3dd70061ce1d44bd5d199","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/snippets/show/index.js","lines":{"begin":7,"end":13}},"remediation_points":720000,"other_locations":[{"path":"app/assets/javascripts/pages/snippets/show/index.js","lines":{"begin":7,"end":13}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 59**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8ae282c95da75609356442ee0da6e6fc","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/groups/new_group_child.js","lines":{"begin":28,"end":36}},"remediation_points":660000,"other_locations":[{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":253,"end":262}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 57**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"611a498e9c5e5d8f256a05631ef5ac51","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":253,"end":262}},"remediation_points":660000,"other_locations":[{"path":"app/assets/javascripts/groups/new_group_child.js","lines":{"begin":28,"end":36}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 57**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"37087f35974839e5e79033d561c840a6","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/issuable_bulk_update_actions.js","lines":{"begin":110,"end":117}},"remediation_points":2310000,"other_locations":[{"path":"app/assets/javascripts/issuable_bulk_update_actions.js","lines":{"begin":120,"end":126}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 112**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"0e6b703c746c94d22e3a02f1993665ce","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/issuable_bulk_update_actions.js","lines":{"begin":120,"end":126}},"remediation_points":2310000,"other_locations":[{"path":"app/assets/javascripts/issuable_bulk_update_actions.js","lines":{"begin":110,"end":117}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 112**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"0e6b703c746c94d22e3a02f1993665ce","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"scripts/frontend/prettier.js","lines":{"begin":64,"end":64}},"remediation_points":600000,"other_locations":[{"path":"scripts/frontend/prettier.js","lines":{"begin":71,"end":71}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 55**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ef21ab3df8b01ca7e22d4d8804157d7a","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"scripts/frontend/prettier.js","lines":{"begin":71,"end":71}},"remediation_points":600000,"other_locations":[{"path":"scripts/frontend/prettier.js","lines":{"begin":64,"end":64}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 55**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ef21ab3df8b01ca7e22d4d8804157d7a","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/api.js","lines":{"begin":208,"end":211}},"remediation_points":1140000,"other_locations":[{"path":"app/assets/javascripts/api.js","lines":{"begin":213,"end":216}},{"path":"app/assets/javascripts/api.js","lines":{"begin":218,"end":221}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 73**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8774a69c35e7469e5831f013a372ab41","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/api.js","lines":{"begin":213,"end":216}},"remediation_points":1140000,"other_locations":[{"path":"app/assets/javascripts/api.js","lines":{"begin":208,"end":211}},{"path":"app/assets/javascripts/api.js","lines":{"begin":218,"end":221}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 73**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8774a69c35e7469e5831f013a372ab41","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/api.js","lines":{"begin":218,"end":221}},"remediation_points":1140000,"other_locations":[{"path":"app/assets/javascripts/api.js","lines":{"begin":208,"end":211}},{"path":"app/assets/javascripts/api.js","lines":{"begin":213,"end":216}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 73**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8774a69c35e7469e5831f013a372ab41","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pipelines/mixins/pipelines.js","lines":{"begin":58,"end":63}},"remediation_points":1110000,"other_locations":[{"path":"app/assets/javascripts/boards/components/board_sidebar.js","lines":{"begin":95,"end":100}},{"path":"app/assets/javascripts/boards/index.js","lines":{"begin":84,"end":89}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 72**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6b694c569da1307b1f359dff7c2ba96a","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/boards/components/board_sidebar.js","lines":{"begin":95,"end":100}},"remediation_points":1110000,"other_locations":[{"path":"app/assets/javascripts/boards/index.js","lines":{"begin":84,"end":89}},{"path":"app/assets/javascripts/pipelines/mixins/pipelines.js","lines":{"begin":58,"end":63}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 72**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"3334e14e9af8a36a250b2eeea4a85929","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/boards/index.js","lines":{"begin":84,"end":89}},"remediation_points":1110000,"other_locations":[{"path":"app/assets/javascripts/boards/components/board_sidebar.js","lines":{"begin":95,"end":100}},{"path":"app/assets/javascripts/pipelines/mixins/pipelines.js","lines":{"begin":58,"end":63}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 72**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"7f09eaadb7107879ce06fbd895c6dfd2","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/issue.js","lines":{"begin":133,"end":142}},"remediation_points":2130000,"other_locations":[{"path":"app/assets/javascripts/issue.js","lines":{"begin":144,"end":153}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 106**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"316f57fc6559be3f06b67e902431d4f3","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/issue.js","lines":{"begin":144,"end":153}},"remediation_points":2130000,"other_locations":[{"path":"app/assets/javascripts/issue.js","lines":{"begin":133,"end":142}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 106**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"316f57fc6559be3f06b67e902431d4f3","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js","lines":{"begin":10,"end":15}},"remediation_points":480000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js","lines":{"begin":19,"end":24}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 51**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"7d9d7ed069d90637ae3219e74dfc3a6a","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js","lines":{"begin":19,"end":24}},"remediation_points":480000,"other_locations":[{"path":"app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js","lines":{"begin":10,"end":15}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 51**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"de8d186c2d499f4864bd5be7db1ddad4","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/u2f/register.js","lines":{"begin":44,"end":53}},"remediation_points":2010000,"other_locations":[{"path":"app/assets/javascripts/u2f/authenticate.js","lines":{"begin":59,"end":68}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 102**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"c1e5733385780c688efc3db1ad11f746","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/u2f/authenticate.js","lines":{"begin":59,"end":68}},"remediation_points":2010000,"other_locations":[{"path":"app/assets/javascripts/u2f/register.js","lines":{"begin":44,"end":53}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 102**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8de13799b826a6e485d4019569e6c278","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":112,"end":122}},"remediation_points":1980000,"other_locations":[{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":124,"end":134}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 101**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"762a1afa922792a6981db079fca70fa7","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":124,"end":134}},"remediation_points":1980000,"other_locations":[{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":112,"end":122}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 101**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"762a1afa922792a6981db079fca70fa7","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/projects_list.js","lines":{"begin":7,"end":18}},"remediation_points":1980000,"other_locations":[{"path":"app/assets/javascripts/groups_list.js","lines":{"begin":7,"end":18}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 101**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"23431c5334e56a528fc4eb179e3607ec","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/groups_list.js","lines":{"begin":7,"end":18}},"remediation_points":1980000,"other_locations":[{"path":"app/assets/javascripts/projects_list.js","lines":{"begin":7,"end":18}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 101**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"1c7090c499a2a96d464475ad7f818f11","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/users_select.js","lines":{"begin":605,"end":609}},"remediation_points":960000,"other_locations":[{"path":"app/assets/javascripts/users_select.js","lines":{"begin":610,"end":614}},{"path":"app/assets/javascripts/users_select.js","lines":{"begin":615,"end":619}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 67**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"448aadd60c1a014f7e3ec3eed8404a65","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/users_select.js","lines":{"begin":610,"end":614}},"remediation_points":960000,"other_locations":[{"path":"app/assets/javascripts/users_select.js","lines":{"begin":605,"end":609}},{"path":"app/assets/javascripts/users_select.js","lines":{"begin":615,"end":619}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 67**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"448aadd60c1a014f7e3ec3eed8404a65","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/users_select.js","lines":{"begin":615,"end":619}},"remediation_points":960000,"other_locations":[{"path":"app/assets/javascripts/users_select.js","lines":{"begin":605,"end":609}},{"path":"app/assets/javascripts/users_select.js","lines":{"begin":610,"end":614}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 67**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"448aadd60c1a014f7e3ec3eed8404a65","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/droplab/plugins/filter.js","lines":{"begin":84,"end":90}},"remediation_points":1890000,"other_locations":[{"path":"app/assets/javascripts/droplab/plugins/ajax_filter.js","lines":{"begin":102,"end":108}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 98**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"38d9afeb8b320571be87977725fdcafe","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/droplab/plugins/ajax_filter.js","lines":{"begin":102,"end":108}},"remediation_points":1890000,"other_locations":[{"path":"app/assets/javascripts/droplab/plugins/filter.js","lines":{"begin":84,"end":90}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 98**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8f8bc2a8aade90176f81a992ae00dd6e","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js","lines":{"begin":1,"end":21}},"remediation_points":1860000,"other_locations":[{"path":"app/assets/javascripts/badges/store/mutation_types.js","lines":{"begin":1,"end":21}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 97**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"7a9bae0109305e0b1d43de56513651bb","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/badges/store/mutation_types.js","lines":{"begin":1,"end":21}},"remediation_points":1860000,"other_locations":[{"path":"app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js","lines":{"begin":1,"end":21}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 97**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"500922ffefee136d140bb5e95d7a3653","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/protected_tags/protected_tag_edit_list.js","lines":{"begin":6,"end":19}},"remediation_points":1830000,"other_locations":[{"path":"app/assets/javascripts/protected_branches/protected_branch_edit_list.js","lines":{"begin":6,"end":19}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 96**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"746b71495fe41db39299682caa93445c","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/protected_branches/protected_branch_edit_list.js","lines":{"begin":6,"end":19}},"remediation_points":1830000,"other_locations":[{"path":"app/assets/javascripts/protected_tags/protected_tag_edit_list.js","lines":{"begin":6,"end":19}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 96**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f5f6ce24443dd76a3e1d0f7521a36be5","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/settings_panels.js","lines":{"begin":7,"end":10}},"remediation_points":390000,"other_locations":[{"path":"app/assets/javascripts/settings_panels.js","lines":{"begin":17,"end":20}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 48**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e788e65abb5a4f6fb80e4e6628fb6d10","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/settings_panels.js","lines":{"begin":17,"end":20}},"remediation_points":390000,"other_locations":[{"path":"app/assets/javascripts/settings_panels.js","lines":{"begin":7,"end":10}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 48**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e788e65abb5a4f6fb80e4e6628fb6d10","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/test_utils/simulate_drag.js","lines":{"begin":40,"end":40}},"remediation_points":360000,"other_locations":[{"path":"app/assets/javascripts/test_utils/simulate_drag.js","lines":{"begin":47,"end":47}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 47**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"3f756c21d7aebceedb361afbef2d4a17","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/test_utils/simulate_drag.js","lines":{"begin":47,"end":47}},"remediation_points":360000,"other_locations":[{"path":"app/assets/javascripts/test_utils/simulate_drag.js","lines":{"begin":40,"end":40}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 47**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"3f756c21d7aebceedb361afbef2d4a17","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":32,"end":34}},"remediation_points":330000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":243,"end":245}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 46**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"50b54b3d38d73c256194eed3de425376","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"identical-code","description":"Identical blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":243,"end":245}},"remediation_points":330000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/mutations/file.js","lines":{"begin":32,"end":34}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 46**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"50b54b3d38d73c256194eed3de425376","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/merge_request.js","lines":{"begin":96,"end":103}},"remediation_points":1680000,"other_locations":[{"path":"app/assets/javascripts/merge_request.js","lines":{"begin":105,"end":112}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 91**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d3d4aa6b1ed1ed8586dbb1479749be92","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/merge_request.js","lines":{"begin":105,"end":112}},"remediation_points":1680000,"other_locations":[{"path":"app/assets/javascripts/merge_request.js","lines":{"begin":96,"end":103}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 91**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d3d4aa6b1ed1ed8586dbb1479749be92","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/sidebar/mount_sidebar.js","lines":{"begin":75,"end":92}},"remediation_points":1680000,"other_locations":[{"path":"app/assets/javascripts/sidebar/mount_sidebar.js","lines":{"begin":94,"end":111}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 91**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"961bf4d63d82bd0547b50951a7db6c69","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/sidebar/mount_sidebar.js","lines":{"begin":94,"end":111}},"remediation_points":1680000,"other_locations":[{"path":"app/assets/javascripts/sidebar/mount_sidebar.js","lines":{"begin":75,"end":92}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 91**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"961bf4d63d82bd0547b50951a7db6c69","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":514,"end":533}},"remediation_points":1650000,"other_locations":[{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":522,"end":533}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 90**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e69530c757a3f18db186fc48d529606d","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":522,"end":533}},"remediation_points":1650000,"other_locations":[{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":514,"end":533}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 90**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e69530c757a3f18db186fc48d529606d","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/badges/store/mutations.js","lines":{"begin":85,"end":99}},"remediation_points":1620000,"other_locations":[{"path":"app/assets/javascripts/badges/store/mutations.js","lines":{"begin":100,"end":114}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 89**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"0407713555d3e0c75813d9f23089bcfd","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/badges/store/mutations.js","lines":{"begin":100,"end":114}},"remediation_points":1620000,"other_locations":[{"path":"app/assets/javascripts/badges/store/mutations.js","lines":{"begin":85,"end":99}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 89**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"0407713555d3e0c75813d9f23089bcfd","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/monitoring/services/monitoring_service.js","lines":{"begin":34,"end":41}},"remediation_points":1620000,"other_locations":[{"path":"app/assets/javascripts/monitoring/services/monitoring_service.js","lines":{"begin":48,"end":55}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 89**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d4a3e547360e709e6f65d844f47d2578","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/monitoring/services/monitoring_service.js","lines":{"begin":48,"end":55}},"remediation_points":1620000,"other_locations":[{"path":"app/assets/javascripts/monitoring/services/monitoring_service.js","lines":{"begin":34,"end":41}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 89**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d4a3e547360e709e6f65d844f47d2578","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/cycle_analytics/default_event_objects.js","lines":{"begin":2,"end":14}},"remediation_points":690000,"other_locations":[{"path":"app/assets/javascripts/cycle_analytics/default_event_objects.js","lines":{"begin":27,"end":39}},{"path":"app/assets/javascripts/cycle_analytics/default_event_objects.js","lines":{"begin":85,"end":97}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 58**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ac500b1ccac9075c6ed2fffbc9b3961c","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/cycle_analytics/default_event_objects.js","lines":{"begin":27,"end":39}},"remediation_points":690000,"other_locations":[{"path":"app/assets/javascripts/cycle_analytics/default_event_objects.js","lines":{"begin":2,"end":14}},{"path":"app/assets/javascripts/cycle_analytics/default_event_objects.js","lines":{"begin":85,"end":97}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 58**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ac500b1ccac9075c6ed2fffbc9b3961c","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/cycle_analytics/default_event_objects.js","lines":{"begin":85,"end":97}},"remediation_points":690000,"other_locations":[{"path":"app/assets/javascripts/cycle_analytics/default_event_objects.js","lines":{"begin":2,"end":14}},{"path":"app/assets/javascripts/cycle_analytics/default_event_objects.js","lines":{"begin":27,"end":39}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 58**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ac500b1ccac9075c6ed2fffbc9b3961c","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/groups/store/groups_store.js","lines":{"begin":46,"end":57}},"remediation_points":1530000,"other_locations":[{"path":"app/assets/javascripts/pipelines/stores/pipelines_store.js","lines":{"begin":20,"end":31}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 86**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ac70092b1281d03613501e7bff10586e","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pipelines/stores/pipelines_store.js","lines":{"begin":20,"end":31}},"remediation_points":1530000,"other_locations":[{"path":"app/assets/javascripts/groups/store/groups_store.js","lines":{"begin":46,"end":57}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 86**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d99660a2eda83bcadef8b0ab894abe34","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/badges/store/actions.js","lines":{"begin":28,"end":39}},"remediation_points":1500000,"other_locations":[{"path":"app/assets/javascripts/badges/store/actions.js","lines":{"begin":142,"end":153}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 85**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2d5915d3ead3c5d344920b58d2d29398","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/badges/store/actions.js","lines":{"begin":142,"end":153}},"remediation_points":1500000,"other_locations":[{"path":"app/assets/javascripts/badges/store/actions.js","lines":{"begin":28,"end":39}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 85**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2d5915d3ead3c5d344920b58d2d29398","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/boards/models/issue.js","lines":{"begin":58,"end":62}},"remediation_points":600000,"other_locations":[{"path":"app/assets/javascripts/boards/models/issue.js","lines":{"begin":78,"end":82}},{"path":"app/assets/javascripts/sidebar/stores/sidebar_store.js","lines":{"begin":77,"end":81}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 55**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6bca973f7e7c682a30bc1ec4bf9bd764","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/boards/models/issue.js","lines":{"begin":78,"end":82}},"remediation_points":600000,"other_locations":[{"path":"app/assets/javascripts/boards/models/issue.js","lines":{"begin":58,"end":62}},{"path":"app/assets/javascripts/sidebar/stores/sidebar_store.js","lines":{"begin":77,"end":81}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 55**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6bca973f7e7c682a30bc1ec4bf9bd764","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/sidebar/stores/sidebar_store.js","lines":{"begin":77,"end":81}},"remediation_points":600000,"other_locations":[{"path":"app/assets/javascripts/boards/models/issue.js","lines":{"begin":58,"end":62}},{"path":"app/assets/javascripts/boards/models/issue.js","lines":{"begin":78,"end":82}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 55**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"0eb61104cf3e71a06f399141f9b4fa0d","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/jobs/store/actions.js","lines":{"begin":50,"end":53}},"remediation_points":600000,"other_locations":[{"path":"app/assets/javascripts/jobs/store/actions.js","lines":{"begin":139,"end":142}},{"path":"app/assets/javascripts/jobs/store/actions.js","lines":{"begin":162,"end":165}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 55**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ab644c43df256102910e1758c76cc0b5","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/jobs/store/actions.js","lines":{"begin":139,"end":142}},"remediation_points":600000,"other_locations":[{"path":"app/assets/javascripts/jobs/store/actions.js","lines":{"begin":50,"end":53}},{"path":"app/assets/javascripts/jobs/store/actions.js","lines":{"begin":162,"end":165}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 55**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ab644c43df256102910e1758c76cc0b5","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/jobs/store/actions.js","lines":{"begin":162,"end":165}},"remediation_points":600000,"other_locations":[{"path":"app/assets/javascripts/jobs/store/actions.js","lines":{"begin":50,"end":53}},{"path":"app/assets/javascripts/jobs/store/actions.js","lines":{"begin":139,"end":142}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 55**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ab644c43df256102910e1758c76cc0b5","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":22,"end":35}},"remediation_points":1410000,"other_locations":[{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":83,"end":96}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 82**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"25ff43fa592634a300a75d479e7131a7","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":83,"end":96}},"remediation_points":1410000,"other_locations":[{"path":"app/assets/javascripts/gl_dropdown.js","lines":{"begin":22,"end":35}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 82**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"25ff43fa592634a300a75d479e7131a7","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/diffs/store/actions.js","lines":{"begin":85,"end":91}},"remediation_points":1380000,"other_locations":[{"path":"app/assets/javascripts/diffs/store/actions.js","lines":{"begin":93,"end":99}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 81**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8761bbf2f2e7182d15c059e6eda61093","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/diffs/store/actions.js","lines":{"begin":93,"end":99}},"remediation_points":1380000,"other_locations":[{"path":"app/assets/javascripts/diffs/store/actions.js","lines":{"begin":85,"end":91}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 81**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"8761bbf2f2e7182d15c059e6eda61093","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/blob/show/index.js","lines":{"begin":13,"end":29}},"remediation_points":1380000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/tree/show/index.js","lines":{"begin":24,"end":40}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 81**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"10512ee694664bf38a3b98f1983d771f","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/tree/show/index.js","lines":{"begin":24,"end":40}},"remediation_points":1380000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/blob/show/index.js","lines":{"begin":13,"end":29}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 81**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"cacb4070042747bc39f22b6ed696d288","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":45,"end":51}},"remediation_points":1380000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":59,"end":65}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 81**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"14f5cdeb3ea2bd6b45456111559d4372","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":59,"end":65}},"remediation_points":1380000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":45,"end":51}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 81**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"14f5cdeb3ea2bd6b45456111559d4372","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/actions/file.js","lines":{"begin":150,"end":154}},"remediation_points":1350000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/actions/file.js","lines":{"begin":156,"end":160}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 80**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2c9b1f08a21d96ed70ae569a5f20147b","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/actions/file.js","lines":{"begin":156,"end":160}},"remediation_points":1350000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/actions/file.js","lines":{"begin":150,"end":154}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 80**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2c9b1f08a21d96ed70ae569a5f20147b","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":377,"end":382}},"remediation_points":1320000,"other_locations":[{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":382,"end":387}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 79**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f7da63bef0b10cc1b2852a187aa6da7a","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":382,"end":387}},"remediation_points":1320000,"other_locations":[{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":377,"end":382}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 79**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f7da63bef0b10cc1b2852a187aa6da7a","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":14,"end":14}},"remediation_points":1290000,"other_locations":[{"path":"app/assets/javascripts/monitoring/utils/multiple_time_series.js","lines":{"begin":8,"end":19}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 78**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"c151b6404d32d859c90476abc53a459a","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/monitoring/utils/multiple_time_series.js","lines":{"begin":8,"end":19}},"remediation_points":1290000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":14,"end":14}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 78**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2e1258cb46a94d486ff0c217b7ee506b","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/actions/tree.js","lines":{"begin":78,"end":84}},"remediation_points":1260000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/actions/file.js","lines":{"begin":81,"end":87}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 77**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5801c2247d4ab393293432462fbf849b","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/actions/file.js","lines":{"begin":81,"end":87}},"remediation_points":1260000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/actions/tree.js","lines":{"begin":78,"end":84}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 77**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"0b9486994211d1c4a0385b3c9ac7339f","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/droplab/hook_input.js","lines":{"begin":4,"end":14}},"remediation_points":1230000,"other_locations":[{"path":"app/assets/javascripts/droplab/hook_button.js","lines":{"begin":4,"end":14}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 76**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ce9535c497280ac0f885dd216908adc4","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/droplab/hook_button.js","lines":{"begin":4,"end":14}},"remediation_points":1230000,"other_locations":[{"path":"app/assets/javascripts/droplab/hook_input.js","lines":{"begin":4,"end":14}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 76**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5ee1687cc7901d1085a41d0b7d5b3730","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/modules/pipelines/actions.js","lines":{"begin":84,"end":96}},"remediation_points":1230000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/modules/file_templates/actions.js","lines":{"begin":53,"end":65}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 76**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"0d9f79efa645b760bbea0b48922a8231","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/modules/file_templates/actions.js","lines":{"begin":53,"end":65}},"remediation_points":1230000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/modules/pipelines/actions.js","lines":{"begin":84,"end":96}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 76**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9033fca3ba0465c4cc79203ac97a67c6","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/behaviors/preview_markdown.js","lines":{"begin":197,"end":202}},"remediation_points":1200000,"other_locations":[{"path":"app/assets/javascripts/behaviors/preview_markdown.js","lines":{"begin":204,"end":209}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 75**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"46e2ef5ccb0e3676b035d790303474f6","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/behaviors/preview_markdown.js","lines":{"begin":204,"end":209}},"remediation_points":1200000,"other_locations":[{"path":"app/assets/javascripts/behaviors/preview_markdown.js","lines":{"begin":197,"end":202}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 75**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"46e2ef5ccb0e3676b035d790303474f6","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/reports/store/actions.js","lines":{"begin":61,"end":67}},"remediation_points":450000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/modules/pipelines/actions.js","lines":{"begin":73,"end":79}},{"path":"app/assets/javascripts/jobs/store/actions.js","lines":{"begin":56,"end":62}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 50**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f6738e3ca61bc9141c14aca35a4ece63","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/jobs/store/actions.js","lines":{"begin":56,"end":62}},"remediation_points":450000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/modules/pipelines/actions.js","lines":{"begin":73,"end":79}},{"path":"app/assets/javascripts/reports/store/actions.js","lines":{"begin":61,"end":67}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 50**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b0ce2389e2ef7f95bdab6dd30392133a","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/modules/pipelines/actions.js","lines":{"begin":73,"end":79}},"remediation_points":450000,"other_locations":[{"path":"app/assets/javascripts/jobs/store/actions.js","lines":{"begin":56,"end":62}},{"path":"app/assets/javascripts/reports/store/actions.js","lines":{"begin":61,"end":67}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 50**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e577605dea8912ffd5b82ee2e188ec76","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/modules/pipelines/actions.js","lines":{"begin":28,"end":40}},"remediation_points":1170000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/modules/pipelines/actions.js","lines":{"begin":123,"end":133}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 74**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"1825ad84d47a08c46a9dd2a4386db970","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/modules/pipelines/actions.js","lines":{"begin":123,"end":133}},"remediation_points":1170000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/modules/pipelines/actions.js","lines":{"begin":28,"end":40}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 74**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"1825ad84d47a08c46a9dd2a4386db970","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js","lines":{"begin":61,"end":67}},"remediation_points":1140000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js","lines":{"begin":68,"end":74}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 73**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"40924a71c4587ae28cb080829b65871c","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js","lines":{"begin":68,"end":74}},"remediation_points":1140000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js","lines":{"begin":61,"end":67}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 73**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"40924a71c4587ae28cb080829b65871c","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/test_utils/simulate_drag.js","lines":{"begin":7,"end":9}},"remediation_points":1140000,"other_locations":[{"path":"app/assets/javascripts/test_utils/simulate_drag.js","lines":{"begin":13,"end":15}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 73**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ca3e7297c2c42380a6b34e26f5faa025","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/test_utils/simulate_drag.js","lines":{"begin":13,"end":15}},"remediation_points":1140000,"other_locations":[{"path":"app/assets/javascripts/test_utils/simulate_drag.js","lines":{"begin":7,"end":9}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 73**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ca3e7297c2c42380a6b34e26f5faa025","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/mutations/merge_request.js","lines":{"begin":22,"end":26}},"remediation_points":1110000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/mutations/branch.js","lines":{"begin":26,"end":30}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 72**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5b01e7cc1ccdb5b45e44117d01906827","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/mutations/branch.js","lines":{"begin":26,"end":30}},"remediation_points":1110000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/mutations/merge_request.js","lines":{"begin":22,"end":26}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 72**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e8265ff476562ddb4bd141410d88ad2f","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/labels/index/index.js","lines":{"begin":12,"end":18}},"remediation_points":1110000,"other_locations":[{"path":"app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js","lines":{"begin":9,"end":15}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 72**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"33bcc15ccc0be1f4e4787d8882ad36e2","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js","lines":{"begin":9,"end":15}},"remediation_points":1110000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/labels/index/index.js","lines":{"begin":12,"end":18}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 72**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"931ead2443e997ee26d698667339fb06","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/actions/file.js","lines":{"begin":222,"end":229}},"remediation_points":1080000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/actions/file.js","lines":{"begin":237,"end":244}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 71**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"36bae5f12de5a60023e0fd8fc19f1842","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/actions/file.js","lines":{"begin":237,"end":244}},"remediation_points":1080000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/actions/file.js","lines":{"begin":222,"end":229}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 71**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"36bae5f12de5a60023e0fd8fc19f1842","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/u2f/register.js","lines":{"begin":71,"end":77}},"remediation_points":1080000,"other_locations":[{"path":"app/assets/javascripts/u2f/authenticate.js","lines":{"begin":81,"end":87}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 71**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"47474e924fc42a7e0f1319c7a8ae13d3","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/u2f/authenticate.js","lines":{"begin":81,"end":87}},"remediation_points":1080000,"other_locations":[{"path":"app/assets/javascripts/u2f/register.js","lines":{"begin":71,"end":77}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 71**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"aade96d11a83331446e70683959d49ec","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":381,"end":385}},"remediation_points":1050000,"other_locations":[{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":418,"end":422}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 70**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"fdc3dab0afea85797bddfc16706a3869","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":418,"end":422}},"remediation_points":1050000,"other_locations":[{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":381,"end":385}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 70**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"fdc3dab0afea85797bddfc16706a3869","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/diffs/store/getters.js","lines":{"begin":80,"end":83}},"remediation_points":1020000,"other_locations":[{"path":"app/assets/javascripts/diffs/store/getters.js","lines":{"begin":84,"end":87}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 69**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"85e1a20133858d47a7f4a64e49080aef","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/diffs/store/getters.js","lines":{"begin":84,"end":87}},"remediation_points":1020000,"other_locations":[{"path":"app/assets/javascripts/diffs/store/getters.js","lines":{"begin":80,"end":83}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 69**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"85e1a20133858d47a7f4a64e49080aef","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/frequent_items/constants.js","lines":{"begin":18,"end":28}},"remediation_points":1020000,"other_locations":[{"path":"app/assets/javascripts/frequent_items/constants.js","lines":{"begin":29,"end":37}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 69**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2c7c7576a99db4f904055a712b428b46","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/frequent_items/constants.js","lines":{"begin":29,"end":37}},"remediation_points":1020000,"other_locations":[{"path":"app/assets/javascripts/frequent_items/constants.js","lines":{"begin":18,"end":28}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 69**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2c7c7576a99db4f904055a712b428b46","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/groups/index.js","lines":{"begin":79,"end":89}},"remediation_points":1020000,"other_locations":[{"path":"app/assets/javascripts/environments/folder/environments_folder_bundle.js","lines":{"begin":24,"end":34}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 69**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b80cd93182a7ed27e84c9e59840d8f01","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/environments/folder/environments_folder_bundle.js","lines":{"begin":24,"end":34}},"remediation_points":1020000,"other_locations":[{"path":"app/assets/javascripts/groups/index.js","lines":{"begin":79,"end":89}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 69**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2beaf3990d7c635f7339eb68a668c3a8","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/modules/file_templates/actions.js","lines":{"begin":9,"end":20}},"remediation_points":1020000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/modules/commit/actions.js","lines":{"begin":202,"end":213}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 69**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9441eb5a1202300a1a6bfdd0f0275a31","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/modules/commit/actions.js","lines":{"begin":202,"end":213}},"remediation_points":1020000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/modules/file_templates/actions.js","lines":{"begin":9,"end":20}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 69**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f657ac30a9ca0e466c504f33ae3363a1","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/merge_conflicts/merge_conflict_store.js","lines":{"begin":259,"end":264}},"remediation_points":1020000,"other_locations":[{"path":"app/assets/javascripts/merge_conflicts/merge_conflict_store.js","lines":{"begin":264,"end":269}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 69**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"40a4102731fea710642a925d4403b398","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/merge_conflicts/merge_conflict_store.js","lines":{"begin":264,"end":269}},"remediation_points":1020000,"other_locations":[{"path":"app/assets/javascripts/merge_conflicts/merge_conflict_store.js","lines":{"begin":259,"end":264}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 69**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"40a4102731fea710642a925d4403b398","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/diff_notes/services/resolve.js","lines":{"begin":56,"end":68}},"remediation_points":990000,"other_locations":[{"path":"app/assets/javascripts/diff_notes/services/resolve.js","lines":{"begin":70,"end":82}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 68**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f5c966c3b72bce8578a3e8c47c412d39","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/diff_notes/services/resolve.js","lines":{"begin":70,"end":82}},"remediation_points":990000,"other_locations":[{"path":"app/assets/javascripts/diff_notes/services/resolve.js","lines":{"begin":56,"end":68}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 68**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f5c966c3b72bce8578a3e8c47c412d39","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/modules/pipelines/mutations.js","lines":{"begin":40,"end":45}},"remediation_points":990000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/modules/pipelines/mutations.js","lines":{"begin":46,"end":51}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 68**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5aa5f88f636432f3381edff9ce5eb33c","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/modules/pipelines/mutations.js","lines":{"begin":46,"end":51}},"remediation_points":990000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/modules/pipelines/mutations.js","lines":{"begin":40,"end":45}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 68**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5aa5f88f636432f3381edff9ce5eb33c","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/lib/utils/datetime_utility.js","lines":{"begin":207,"end":220}},"remediation_points":990000,"other_locations":[{"path":"app/assets/javascripts/lib/utils/datetime_utility.js","lines":{"begin":221,"end":234}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 68**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"c3008559d14ec2056a4514ffdfd5d04b","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/lib/utils/datetime_utility.js","lines":{"begin":221,"end":234}},"remediation_points":990000,"other_locations":[{"path":"app/assets/javascripts/lib/utils/datetime_utility.js","lines":{"begin":207,"end":220}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 68**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"c3008559d14ec2056a4514ffdfd5d04b","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/notes/stores/utils.js","lines":{"begin":16,"end":23}},"remediation_points":990000,"other_locations":[{"path":"app/assets/javascripts/notes.js","lines":{"begin":1506,"end":1515}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 68**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"37585e488e2d24ae8b8b99880ff76099","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":1506,"end":1515}},"remediation_points":990000,"other_locations":[{"path":"app/assets/javascripts/notes/stores/utils.js","lines":{"begin":16,"end":23}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 68**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ea9f3aa39779bc4f5ead96ecdcd5e87c","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":1526,"end":1566}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/modules/commit/actions.js","lines":{"begin":103,"end":219}},{"path":"app/assets/javascripts/pages/search/init_filtered_search.js","lines":{"begin":3,"end":23}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5306c1b3e6d8ac0ac9bed008b527b8a7","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/search/init_filtered_search.js","lines":{"begin":3,"end":23}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/modules/commit/actions.js","lines":{"begin":103,"end":219}},{"path":"app/assets/javascripts/notes.js","lines":{"begin":1526,"end":1566}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"4dfd0fcaf710a6337c5924d7c4fa91ea","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/modules/commit/actions.js","lines":{"begin":103,"end":219}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/notes.js","lines":{"begin":1526,"end":1566}},{"path":"app/assets/javascripts/pages/search/init_filtered_search.js","lines":{"begin":3,"end":23}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"71749d080c69b950423ce3e73b3671d6","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/labels/index/index.js","lines":{"begin":44,"end":48}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js","lines":{"begin":44,"end":48}},{"path":"app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js","lines":{"begin":39,"end":43}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"80bd962a66c5ba8f3bb261204e0e8404","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js","lines":{"begin":44,"end":48}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js","lines":{"begin":39,"end":43}},{"path":"app/assets/javascripts/pages/projects/labels/index/index.js","lines":{"begin":44,"end":48}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"4dccfbb8118720c67894021eefaeb04f","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 3 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js","lines":{"begin":39,"end":43}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js","lines":{"begin":44,"end":48}},{"path":"app/assets/javascripts/pages/projects/labels/index/index.js","lines":{"begin":44,"end":48}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"594be23bc97d64731abf2df62520ccd3","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/clusters/services/clusters_service.js","lines":{"begin":6,"end":12}},"remediation_points":960000,"other_locations":[{"path":"app/assets/javascripts/clusters/clusters_bundle.js","lines":{"begin":96,"end":102}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 67**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5b85961f2c362ae642ccf393b8352fcb","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/clusters/clusters_bundle.js","lines":{"begin":96,"end":102}},"remediation_points":960000,"other_locations":[{"path":"app/assets/javascripts/clusters/services/clusters_service.js","lines":{"begin":6,"end":12}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 67**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"cad81c7468728ba369f9f23c8a1271bc","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/actions/file.js","lines":{"begin":91,"end":93}},"remediation_points":960000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/actions/file.js","lines":{"begin":172,"end":174}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 67**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"beda25571cf3ea070a68d9cdfae91c8d","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/actions/file.js","lines":{"begin":172,"end":174}},"remediation_points":960000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/actions/file.js","lines":{"begin":91,"end":93}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 67**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"beda25571cf3ea070a68d9cdfae91c8d","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js","lines":{"begin":48,"end":53}},"remediation_points":960000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js","lines":{"begin":63,"end":67}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 67**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"575f1444e3c2fec5a4f47d049cbd87c0","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js","lines":{"begin":63,"end":67}},"remediation_points":960000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js","lines":{"begin":48,"end":53}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 67**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5e4303b5381a6be7bcaade373d766f34","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/u2f/register.js","lines":{"begin":35,"end":42}},"remediation_points":960000,"other_locations":[{"path":"app/assets/javascripts/u2f/authenticate.js","lines":{"begin":50,"end":57}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 67**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"1d8b266328571b1177e922384e474eb5","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/u2f/authenticate.js","lines":{"begin":50,"end":57}},"remediation_points":960000,"other_locations":[{"path":"app/assets/javascripts/u2f/register.js","lines":{"begin":35,"end":42}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 67**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"334a900ffecf98fb6a951456c58236a1","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":181,"end":183}},"remediation_points":930000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":290,"end":292}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 66**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"32fbc7cab878611e7f156798ae3d2bca","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":290,"end":292}},"remediation_points":930000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":181,"end":183}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 66**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"32fbc7cab878611e7f156798ae3d2bca","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/project.js","lines":{"begin":50,"end":56}},"remediation_points":930000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/project.js","lines":{"begin":57,"end":63}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 66**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2c14eefb5c2db69bb969956efd4384de","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/project.js","lines":{"begin":57,"end":63}},"remediation_points":930000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/project.js","lines":{"begin":50,"end":56}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 66**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2c14eefb5c2db69bb969956efd4384de","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/search_autocomplete.js","lines":{"begin":277,"end":286}},"remediation_points":930000,"other_locations":[{"path":"app/assets/javascripts/search_autocomplete.js","lines":{"begin":287,"end":296}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 66**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"923d82c4da880c23e929c2402aedd37e","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/search_autocomplete.js","lines":{"begin":287,"end":296}},"remediation_points":930000,"other_locations":[{"path":"app/assets/javascripts/search_autocomplete.js","lines":{"begin":277,"end":286}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 66**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"923d82c4da880c23e929c2402aedd37e","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/blob/blob_fork_suggestion.js","lines":{"begin":31,"end":34}},"remediation_points":870000,"other_locations":[{"path":"app/assets/javascripts/blob/blob_fork_suggestion.js","lines":{"begin":56,"end":59}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 64**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"938856cdef6ef5aa2933db645ea96362","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/blob/blob_fork_suggestion.js","lines":{"begin":56,"end":59}},"remediation_points":870000,"other_locations":[{"path":"app/assets/javascripts/blob/blob_fork_suggestion.js","lines":{"begin":31,"end":34}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 64**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"938856cdef6ef5aa2933db645ea96362","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/diffs/index.js","lines":{"begin":30,"end":39}},"remediation_points":870000,"other_locations":[{"path":"app/assets/javascripts/mr_notes/index.js","lines":{"begin":66,"end":75}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 64**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b35237501aeed21f2d38aef31627b97e","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/mr_notes/index.js","lines":{"begin":66,"end":75}},"remediation_points":870000,"other_locations":[{"path":"app/assets/javascripts/diffs/index.js","lines":{"begin":30,"end":39}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 64**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"17da47f3678555baddd89ae6622e441f","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/lib/utils/datetime_utility.js","lines":{"begin":18,"end":31}},"remediation_points":870000,"other_locations":[{"path":"app/assets/javascripts/lib/utils/datetime_utility.js","lines":{"begin":33,"end":46}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 64**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"a93d28498cd20f4d35a3f8dbbc0a7a35","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/lib/utils/datetime_utility.js","lines":{"begin":33,"end":46}},"remediation_points":870000,"other_locations":[{"path":"app/assets/javascripts/lib/utils/datetime_utility.js","lines":{"begin":18,"end":31}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 64**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"a93d28498cd20f4d35a3f8dbbc0a7a35","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":237,"end":241}},"remediation_points":870000,"other_locations":[{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":340,"end":344}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 64**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"785078efeabfa8c98aa5bf0804b2619d","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":340,"end":344}},"remediation_points":870000,"other_locations":[{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":237,"end":241}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 64**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"785078efeabfa8c98aa5bf0804b2619d","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/utils.js","lines":{"begin":112,"end":122}},"remediation_points":840000,"other_locations":[{"path":"app/assets/javascripts/ide/lib/diff/controller.js","lines":{"begin":6,"end":16}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 63**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"09d7d5a8cacd9d95c32bc8b4e6b53930","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/lib/diff/controller.js","lines":{"begin":6,"end":16}},"remediation_points":840000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/utils.js","lines":{"begin":112,"end":122}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 63**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f94a7934b1c80152deb5b61a0c5db3d4","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/api.js","lines":{"begin":118,"end":124}},"remediation_points":810000,"other_locations":[{"path":"app/assets/javascripts/api.js","lines":{"begin":126,"end":132}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 62**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"104c7ee7f9a45a32c42bacfaa5a5f1bc","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/api.js","lines":{"begin":126,"end":132}},"remediation_points":810000,"other_locations":[{"path":"app/assets/javascripts/api.js","lines":{"begin":118,"end":124}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 62**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"104c7ee7f9a45a32c42bacfaa5a5f1bc","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/comment_type_toggle.js","lines":{"begin":37,"end":46}},"remediation_points":810000,"other_locations":[{"path":"app/assets/javascripts/comment_type_toggle.js","lines":{"begin":48,"end":57}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 62**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"1f17e867f83499d67ff9ed50b8097db5","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/comment_type_toggle.js","lines":{"begin":48,"end":57}},"remediation_points":810000,"other_locations":[{"path":"app/assets/javascripts/comment_type_toggle.js","lines":{"begin":37,"end":46}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 62**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"1f17e867f83499d67ff9ed50b8097db5","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pipelines/pipeline_details_bundle.js","lines":{"begin":77,"end":84}},"remediation_points":810000,"other_locations":[{"path":"app/assets/javascripts/jobs/job_details_bundle.js","lines":{"begin":27,"end":34}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 62**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"c4a434df3787893bc1f6d897464a8227","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/jobs/job_details_bundle.js","lines":{"begin":27,"end":34}},"remediation_points":810000,"other_locations":[{"path":"app/assets/javascripts/pipelines/pipeline_details_bundle.js","lines":{"begin":77,"end":84}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 62**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5c1f719b9039c86ffdc704317d783449","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/labels/index/index.js","lines":{"begin":20,"end":24}},"remediation_points":780000,"other_locations":[{"path":"app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js","lines":{"begin":17,"end":21}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 61**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ab079e1e6bc28e1fc184b520beb34531","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js","lines":{"begin":17,"end":21}},"remediation_points":780000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/labels/index/index.js","lines":{"begin":20,"end":24}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 61**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e7369e08c5971c04639cff93271173af","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/notes/stores/mutations.js","lines":{"begin":56,"end":59}},"remediation_points":750000,"other_locations":[{"path":"app/assets/javascripts/notes/stores/mutations.js","lines":{"begin":61,"end":64}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 60**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"1ad13a005d315ccf15cfe0584579158f","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/notes/stores/mutations.js","lines":{"begin":61,"end":64}},"remediation_points":750000,"other_locations":[{"path":"app/assets/javascripts/notes/stores/mutations.js","lines":{"begin":56,"end":59}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 60**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"1ad13a005d315ccf15cfe0584579158f","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/sessions/new/username_validator.js","lines":{"begin":107,"end":111}},"remediation_points":750000,"other_locations":[{"path":"app/assets/javascripts/pages/sessions/new/username_validator.js","lines":{"begin":113,"end":117}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 60**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"c9228663eecdf0fc1a8dbd811c863e38","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/sessions/new/username_validator.js","lines":{"begin":113,"end":117}},"remediation_points":750000,"other_locations":[{"path":"app/assets/javascripts/pages/sessions/new/username_validator.js","lines":{"begin":107,"end":111}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 60**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"c9228663eecdf0fc1a8dbd811c863e38","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/droplab/hook_button.js","lines":{"begin":33,"end":36}},"remediation_points":720000,"other_locations":[{"path":"app/assets/javascripts/landing.js","lines":{"begin":18,"end":21}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 59**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"0cdcc38394199ec6567937ce812cb5a5","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/landing.js","lines":{"begin":18,"end":21}},"remediation_points":720000,"other_locations":[{"path":"app/assets/javascripts/droplab/hook_button.js","lines":{"begin":33,"end":36}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 59**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6b06657bea1bfe588af0efba4a2bf57e","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pipelines/pipeline_details_mediator.js","lines":{"begin":26,"end":31}},"remediation_points":720000,"other_locations":[{"path":"app/assets/javascripts/jobs/job_details_mediator.js","lines":{"begin":34,"end":39}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 59**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"1f5e585cdfd268a3748dbdd584f69df8","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/jobs/job_details_mediator.js","lines":{"begin":34,"end":39}},"remediation_points":720000,"other_locations":[{"path":"app/assets/javascripts/pipelines/pipeline_details_mediator.js","lines":{"begin":26,"end":31}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 59**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"67d77d7b888d52cac1d666c6a95ba502","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/tree.js","lines":{"begin":38,"end":46}},"remediation_points":720000,"other_locations":[{"path":"app/assets/javascripts/tree.js","lines":{"begin":49,"end":57}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 59**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"16eb34236a934fb101dbe1e8b6ab4af1","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/tree.js","lines":{"begin":49,"end":57}},"remediation_points":720000,"other_locations":[{"path":"app/assets/javascripts/tree.js","lines":{"begin":38,"end":46}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 59**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"16eb34236a934fb101dbe1e8b6ab4af1","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/merge_conflicts/merge_conflict_store.js","lines":{"begin":191,"end":203}},"remediation_points":690000,"other_locations":[{"path":"app/assets/javascripts/merge_conflicts/merge_conflict_store.js","lines":{"begin":236,"end":248}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 58**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"13f117af1725bb929e7aa63491a25429","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/merge_conflicts/merge_conflict_store.js","lines":{"begin":236,"end":248}},"remediation_points":690000,"other_locations":[{"path":"app/assets/javascripts/merge_conflicts/merge_conflict_store.js","lines":{"begin":191,"end":203}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 58**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"13f117af1725bb929e7aa63491a25429","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/groups/groups_filterable_list.js","lines":{"begin":7,"end":16}},"remediation_points":660000,"other_locations":[{"path":"app/assets/javascripts/diffs/store/utils.js","lines":{"begin":238,"end":247}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 57**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2a553868b7fea8b08596f9a95a22d484","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/diffs/store/utils.js","lines":{"begin":238,"end":247}},"remediation_points":660000,"other_locations":[{"path":"app/assets/javascripts/groups/groups_filterable_list.js","lines":{"begin":7,"end":16}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 57**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"12bd1fc0fd53a6c025f6ed5d690be133","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/admin/application_settings/usage_ping_payload.js","lines":{"begin":45,"end":49}},"remediation_points":660000,"other_locations":[{"path":"app/assets/javascripts/pages/admin/application_settings/usage_ping_payload.js","lines":{"begin":51,"end":55}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 57**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e7e7f0899a668845138c08c503e337fe","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/admin/application_settings/usage_ping_payload.js","lines":{"begin":51,"end":55}},"remediation_points":660000,"other_locations":[{"path":"app/assets/javascripts/pages/admin/application_settings/usage_ping_payload.js","lines":{"begin":45,"end":49}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 57**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e7e7f0899a668845138c08c503e337fe","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js","lines":{"begin":8,"end":11}},"remediation_points":660000,"other_locations":[{"path":"app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js","lines":{"begin":13,"end":16}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 57**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"21bb124a570e4088d0684442dade767f","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js","lines":{"begin":13,"end":16}},"remediation_points":660000,"other_locations":[{"path":"app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js","lines":{"begin":8,"end":11}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 57**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"21bb124a570e4088d0684442dade767f","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/namespace_select.js","lines":{"begin":20,"end":26}},"remediation_points":630000,"other_locations":[{"path":"app/assets/javascripts/namespace_select.js","lines":{"begin":40,"end":46}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 56**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d22f4f9ddac4d361d9f6721a25ded899","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/namespace_select.js","lines":{"begin":40,"end":46}},"remediation_points":630000,"other_locations":[{"path":"app/assets/javascripts/namespace_select.js","lines":{"begin":20,"end":26}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 56**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d22f4f9ddac4d361d9f6721a25ded899","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/projects/project_new.js","lines":{"begin":103,"end":116}},"remediation_points":630000,"other_locations":[{"path":"app/assets/javascripts/ide/constants.js","lines":{"begin":43,"end":56}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 56**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"d9ad4d62a2c7b3a5ee02495f81a78cd8","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/constants.js","lines":{"begin":43,"end":56}},"remediation_points":630000,"other_locations":[{"path":"app/assets/javascripts/projects/project_new.js","lines":{"begin":103,"end":116}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 56**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"b9bd1f7a0fafe178e70f6a652d6fd8be","severity":"major","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/merge_conflicts/components/diff_file_editor.js","lines":{"begin":13,"end":26}},"remediation_points":570000,"other_locations":[{"path":"app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js","lines":{"begin":8,"end":21}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 54**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"423d5a0cc874e941bd22657b325446b4","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js","lines":{"begin":8,"end":21}},"remediation_points":570000,"other_locations":[{"path":"app/assets/javascripts/merge_conflicts/components/diff_file_editor.js","lines":{"begin":13,"end":26}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 54**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"716df5a6c1cbc00338163aa638130bca","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/merge_request_tabs.js","lines":{"begin":436,"end":441}},"remediation_points":570000,"other_locations":[{"path":"app/assets/javascripts/merge_request_tabs.js","lines":{"begin":452,"end":457}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 54**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5a2cd4548ee8c0362f69cc88ee5982c0","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/merge_request_tabs.js","lines":{"begin":452,"end":457}},"remediation_points":570000,"other_locations":[{"path":"app/assets/javascripts/merge_request_tabs.js","lines":{"begin":436,"end":441}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 54**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5a2cd4548ee8c0362f69cc88ee5982c0","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":214,"end":221}},"remediation_points":570000,"other_locations":[{"path":"app/assets/javascripts/pages/search/init_filtered_search.js","lines":{"begin":13,"end":20}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 54**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e71451918dac542ee62e859e4a694a23","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/search/init_filtered_search.js","lines":{"begin":13,"end":20}},"remediation_points":570000,"other_locations":[{"path":"app/assets/javascripts/notes.js","lines":{"begin":214,"end":221}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 54**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6696916f5ca830f21733956d3dc83b22","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/prometheus_metrics/prometheus_metrics.js","lines":{"begin":45,"end":49}},"remediation_points":570000,"other_locations":[{"path":"app/assets/javascripts/prometheus_metrics/prometheus_metrics.js","lines":{"begin":50,"end":54}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 54**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"723e924a871cea3a66a3ccd49f2f4407","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/prometheus_metrics/prometheus_metrics.js","lines":{"begin":50,"end":54}},"remediation_points":570000,"other_locations":[{"path":"app/assets/javascripts/prometheus_metrics/prometheus_metrics.js","lines":{"begin":45,"end":49}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 54**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"723e924a871cea3a66a3ccd49f2f4407","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":97,"end":102}},"remediation_points":540000,"other_locations":[{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":103,"end":108}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 53**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"38cb87a7a94d43c42903f71cfd248953","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":103,"end":108}},"remediation_points":540000,"other_locations":[{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":97,"end":102}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 53**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"38cb87a7a94d43c42903f71cfd248953","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/projects/project_new.js","lines":{"begin":125,"end":129}},"remediation_points":540000,"other_locations":[{"path":"app/assets/javascripts/projects/project_new.js","lines":{"begin":150,"end":153}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 53**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"77fe9230b5c1c681ca23dd48b5bde881","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/projects/project_new.js","lines":{"begin":150,"end":153}},"remediation_points":540000,"other_locations":[{"path":"app/assets/javascripts/projects/project_new.js","lines":{"begin":125,"end":129}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 53**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"77fe9230b5c1c681ca23dd48b5bde881","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/reports/store/utils.js","lines":{"begin":39,"end":42}},"remediation_points":540000,"other_locations":[{"path":"app/assets/javascripts/reports/store/utils.js","lines":{"begin":44,"end":47}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 53**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6369d3d651e38cbbac285afad5297e9d","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/reports/store/utils.js","lines":{"begin":44,"end":47}},"remediation_points":540000,"other_locations":[{"path":"app/assets/javascripts/reports/store/utils.js","lines":{"begin":39,"end":42}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 53**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"6369d3d651e38cbbac285afad5297e9d","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/clusters/clusters_bundle.js","lines":{"begin":108,"end":111}},"remediation_points":510000,"other_locations":[{"path":"app/assets/javascripts/clusters/clusters_bundle.js","lines":{"begin":113,"end":116}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 52**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2b8d07121aa08a0ef9af946ea4e5d60d","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/clusters/clusters_bundle.js","lines":{"begin":113,"end":116}},"remediation_points":510000,"other_locations":[{"path":"app/assets/javascripts/clusters/clusters_bundle.js","lines":{"begin":108,"end":111}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 52**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2b8d07121aa08a0ef9af946ea4e5d60d","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/zen_mode.js","lines":{"begin":42,"end":45}},"remediation_points":510000,"other_locations":[{"path":"app/assets/javascripts/zen_mode.js","lines":{"begin":46,"end":49}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 52**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"1c224ff513833f281d7bb58fb1280314","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/zen_mode.js","lines":{"begin":46,"end":49}},"remediation_points":510000,"other_locations":[{"path":"app/assets/javascripts/zen_mode.js","lines":{"begin":42,"end":45}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 52**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"1c224ff513833f281d7bb58fb1280314","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/actions.js","lines":{"begin":133,"end":136}},"remediation_points":480000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/actions.js","lines":{"begin":144,"end":147}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 51**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5e09ce34a63a712c502dfcaa775c5a8e","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/ide/stores/actions.js","lines":{"begin":144,"end":147}},"remediation_points":480000,"other_locations":[{"path":"app/assets/javascripts/ide/stores/actions.js","lines":{"begin":133,"end":136}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 51**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5e09ce34a63a712c502dfcaa775c5a8e","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":120,"end":123}},"remediation_points":480000,"other_locations":[{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":128,"end":131}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 51**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5dcf5b9ed09acddcf34d9b99f4f7d4e0","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":128,"end":131}},"remediation_points":480000,"other_locations":[{"path":"app/assets/javascripts/network/branch_graph.js","lines":{"begin":120,"end":123}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 51**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5dcf5b9ed09acddcf34d9b99f4f7d4e0","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/projects/tree/services/commit_pipeline_service.js","lines":{"begin":3,"end":11}},"remediation_points":480000,"other_locations":[{"path":"app/assets/javascripts/jobs/services/job_service.js","lines":{"begin":3,"end":11}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 51**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"020d87eef79dcc6d4979a4877f795e88","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/jobs/services/job_service.js","lines":{"begin":3,"end":11}},"remediation_points":480000,"other_locations":[{"path":"app/assets/javascripts/projects/tree/services/commit_pipeline_service.js","lines":{"begin":3,"end":11}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 51**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"7f3c54ba927268843f9fe397b30c4541","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/star.js","lines":{"begin":19,"end":23}},"remediation_points":480000,"other_locations":[{"path":"app/assets/javascripts/star.js","lines":{"begin":23,"end":27}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 51**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"cc2a5b7fe6f4a900c4690f4960b1d2ce","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/star.js","lines":{"begin":23,"end":27}},"remediation_points":480000,"other_locations":[{"path":"app/assets/javascripts/star.js","lines":{"begin":19,"end":23}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 51**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"cc2a5b7fe6f4a900c4690f4960b1d2ce","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/groups/store/groups_store.js","lines":{"begin":102,"end":104}},"remediation_points":450000,"other_locations":[{"path":"app/assets/javascripts/boards/stores/modal_store.js","lines":{"begin":71,"end":74}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 50**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"e9ffa7b55a2d3d697297bb9c77d9e0c8","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/boards/stores/modal_store.js","lines":{"begin":71,"end":74}},"remediation_points":450000,"other_locations":[{"path":"app/assets/javascripts/groups/store/groups_store.js","lines":{"begin":102,"end":104}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 50**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"cae962d929e29ddbbe69117801f17860","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/groups/issues/index.js","lines":{"begin":6,"end":13}},"remediation_points":450000,"other_locations":[{"path":"app/assets/javascripts/pages/groups/merge_requests/index.js","lines":{"begin":6,"end":13}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 50**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"65a33b3fe4ae20436c9fb46d65d9db04","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/groups/merge_requests/index.js","lines":{"begin":6,"end":13}},"remediation_points":450000,"other_locations":[{"path":"app/assets/javascripts/pages/groups/issues/index.js","lines":{"begin":6,"end":13}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 50**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"1b0f3dfb819efd869e74a58517390763","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pipelines/pipeline_details_mediator.js","lines":{"begin":55,"end":58}},"remediation_points":450000,"other_locations":[{"path":"app/assets/javascripts/jobs/job_details_mediator.js","lines":{"begin":51,"end":54}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 50**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ed657cc5e6969316c8bd1d2be6204668","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/jobs/job_details_mediator.js","lines":{"begin":51,"end":54}},"remediation_points":450000,"other_locations":[{"path":"app/assets/javascripts/pipelines/pipeline_details_mediator.js","lines":{"begin":55,"end":58}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 50**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"3da1a06772dc32dbbb550900c97f6cbd","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":125,"end":130}},"remediation_points":420000,"other_locations":[{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":154,"end":159}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 49**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f6c22427e43838beefc533b33cde9955","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":154,"end":159}},"remediation_points":420000,"other_locations":[{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":125,"end":130}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 49**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"f6c22427e43838beefc533b33cde9955","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/deploy_keys/service/index.js","lines":{"begin":15,"end":18}},"remediation_points":420000,"other_locations":[{"path":"app/assets/javascripts/deploy_keys/service/index.js","lines":{"begin":20,"end":23}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 49**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5eaf7d9cd8339dca959f74f384e02906","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/deploy_keys/service/index.js","lines":{"begin":20,"end":23}},"remediation_points":420000,"other_locations":[{"path":"app/assets/javascripts/deploy_keys/service/index.js","lines":{"begin":15,"end":18}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 49**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5eaf7d9cd8339dca959f74f384e02906","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":146,"end":148}},"remediation_points":420000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":250,"end":252}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 49**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"70155684217b5724087f40626f7766bc","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":250,"end":252}},"remediation_points":420000,"other_locations":[{"path":"app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js","lines":{"begin":146,"end":148}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 49**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"70155684217b5724087f40626f7766bc","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":134,"end":137}},"remediation_points":390000,"other_locations":[{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":138,"end":141}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 48**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"180e35eb524273ddfc92de366020a611","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":138,"end":141}},"remediation_points":390000,"other_locations":[{"path":"app/assets/javascripts/behaviors/markdown/copy_as_gfm.js","lines":{"begin":134,"end":137}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 48**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"180e35eb524273ddfc92de366020a611","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/issuable_bulk_update_sidebar.js","lines":{"begin":100,"end":106}},"remediation_points":390000,"other_locations":[{"path":"app/assets/javascripts/issuable_bulk_update_sidebar.js","lines":{"begin":117,"end":123}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 48**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"672a79b04a463defdd46c0086474fd52","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/issuable_bulk_update_sidebar.js","lines":{"begin":117,"end":123}},"remediation_points":390000,"other_locations":[{"path":"app/assets/javascripts/issuable_bulk_update_sidebar.js","lines":{"begin":100,"end":106}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 48**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"672a79b04a463defdd46c0086474fd52","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/jobs/store/actions.js","lines":{"begin":66,"end":69}},"remediation_points":390000,"other_locations":[{"path":"app/assets/javascripts/jobs/store/actions.js","lines":{"begin":146,"end":149}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 48**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"4ebfab6abe3fb873067f7b37190c9136","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/jobs/store/actions.js","lines":{"begin":146,"end":149}},"remediation_points":390000,"other_locations":[{"path":"app/assets/javascripts/jobs/store/actions.js","lines":{"begin":66,"end":69}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 48**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"4ebfab6abe3fb873067f7b37190c9136","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/droplab/hook_input.js","lines":{"begin":46,"end":53}},"remediation_points":360000,"other_locations":[{"path":"app/assets/javascripts/droplab/hook_input.js","lines":{"begin":60,"end":67}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 47**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"10bdf4c525726570be1c10982443983e","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/droplab/hook_input.js","lines":{"begin":60,"end":67}},"remediation_points":360000,"other_locations":[{"path":"app/assets/javascripts/droplab/hook_input.js","lines":{"begin":46,"end":53}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 47**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"10bdf4c525726570be1c10982443983e","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/filtered_search/dropdown_hint.js","lines":{"begin":75,"end":77}},"remediation_points":360000,"other_locations":[{"path":"app/assets/javascripts/filtered_search/dropdown_user.js","lines":{"begin":78,"end":80}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 47**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"223d4160dbc2f173c7019bf4258bf71a","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/filtered_search/dropdown_user.js","lines":{"begin":78,"end":80}},"remediation_points":360000,"other_locations":[{"path":"app/assets/javascripts/filtered_search/dropdown_hint.js","lines":{"begin":75,"end":77}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 47**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2f69c39865bb0c31ba27242592efb90a","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":1451,"end":1457}},"remediation_points":360000,"other_locations":[{"path":"app/assets/javascripts/notes.js","lines":{"begin":1459,"end":1465}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 47**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"06432a7535afbcbc307fe2c2fad49f03","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/notes.js","lines":{"begin":1459,"end":1465}},"remediation_points":360000,"other_locations":[{"path":"app/assets/javascripts/notes.js","lines":{"begin":1451,"end":1457}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 47**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"06432a7535afbcbc307fe2c2fad49f03","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":63,"end":66}},"remediation_points":330000,"other_locations":[{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":423,"end":426}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 46**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"3cf8b42abcd81551bbf1d4b6a86a23ec","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":423,"end":426}},"remediation_points":330000,"other_locations":[{"path":"app/assets/javascripts/create_merge_request_dropdown.js","lines":{"begin":63,"end":66}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 46**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"3cf8b42abcd81551bbf1d4b6a86a23ec","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js","lines":{"begin":223,"end":224}},"remediation_points":330000,"other_locations":[{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":564,"end":565}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 46**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9b59a169ec24710bb17e53176d9f6484","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/filtered_search/filtered_search_manager.js","lines":{"begin":564,"end":565}},"remediation_points":330000,"other_locations":[{"path":"app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js","lines":{"begin":223,"end":224}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 46**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"629f61554a8bb6a8eb033206d609a01e","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/gl_form.js","lines":{"begin":93,"end":95}},"remediation_points":330000,"other_locations":[{"path":"app/assets/javascripts/gl_form.js","lines":{"begin":96,"end":98}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 46**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"a37da012d8b9134f9c2c07cbe6e5df45","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/gl_form.js","lines":{"begin":96,"end":98}},"remediation_points":330000,"other_locations":[{"path":"app/assets/javascripts/gl_form.js","lines":{"begin":93,"end":95}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 46**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"a37da012d8b9134f9c2c07cbe6e5df45","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/boards/models/issue.js","lines":{"begin":48,"end":52}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/boards/models/issue.js","lines":{"begin":68,"end":72}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ad4849cc4103d257a75a53f533f93f88","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/boards/models/issue.js","lines":{"begin":68,"end":72}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/boards/models/issue.js","lines":{"begin":48,"end":52}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"ad4849cc4103d257a75a53f533f93f88","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/boards/models/project.js","lines":{"begin":1,"end":6}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/boards/models/milestone.js","lines":{"begin":1,"end":6}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"63e808e699724c7876463b889a910d69","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/boards/models/milestone.js","lines":{"begin":1,"end":6}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/boards/models/project.js","lines":{"begin":1,"end":6}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2d888235869b541141524699d46a10fe","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/diffs/store/mutations.js","lines":{"begin":142,"end":143}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/diffs/store/actions.js","lines":{"begin":139,"end":139}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"a5d03fc520fddde3ecc4ff06b86c9a0d","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/diffs/store/actions.js","lines":{"begin":139,"end":139}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/diffs/store/mutations.js","lines":{"begin":142,"end":143}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"5a0bd2adf62a695699f94e1cef624dd7","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/merge_request_tabs.js","lines":{"begin":73,"end":76}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/merge_request_tabs.js","lines":{"begin":78,"end":81}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"1dc35d639071fed3c333a47b9c544d56","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/merge_request_tabs.js","lines":{"begin":78,"end":81}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/merge_request_tabs.js","lines":{"begin":73,"end":76}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"1dc35d639071fed3c333a47b9c544d56","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/users/activity_calendar.js","lines":{"begin":234,"end":240}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/pages/users/activity_calendar.js","lines":{"begin":260,"end":266}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"c9f4b3f70b4ef899508948c84a381a89","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/pages/users/activity_calendar.js","lines":{"begin":260,"end":266}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/pages/users/activity_calendar.js","lines":{"begin":234,"end":240}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"c9f4b3f70b4ef899508948c84a381a89","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/protected_tags/protected_tag_edit.js","lines":{"begin":16,"end":20}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/protected_branches/protected_branch_edit.js","lines":{"begin":24,"end":28}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"2d44f8e3653f3f06777c422f4151a7d3","severity":"minor","engine_name":"duplication"},{"type":"issue","check_name":"similar-code","description":"Similar blocks of code found in 2 locations. Consider refactoring.","categories":["Duplication"],"location":{"path":"app/assets/javascripts/protected_branches/protected_branch_edit.js","lines":{"begin":24,"end":28}},"remediation_points":300000,"other_locations":[{"path":"app/assets/javascripts/protected_tags/protected_tag_edit.js","lines":{"begin":16,"end":20}}],"content":{"body":"## Duplicated Code\n\nDuplicated code can lead to software that is hard to understand and difficult to change. The Don't Repeat Yourself (DRY) principle states:\n\n> Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.\n\nWhen you violate DRY, bugs and maintenance problems are sure to follow. Duplicated code has a tendency to both continue to replicate and also to diverge (leaving bugs as two similar implementations differ in subtle ways).\n\n## Tuning\n\n**This issue has a mass of 45**.\n\nWe set useful threshold defaults for the languages we support but you may want to adjust these settings based on your project guidelines.\n\nThe threshold configuration represents the minimum [mass](https://docs.codeclimate.com/docs/duplication#mass) a code block must have to be analyzed for duplication. The lower the threshold, the more fine-grained the comparison.\n\nIf the engine is too easily reporting duplication, try raising the threshold. If you suspect that the engine isn't catching enough duplication, try lowering the threshold. The best setting tends to differ from language to language.\n\nSee [`codeclimate-duplication`'s documentation](https://docs.codeclimate.com/docs/duplication) for more information about tuning the mass threshold in your `.codeclimate.yml`.\n\n## Refactorings\n\n* [Extract Method](http://sourcemaking.com/refactoring/extract-method)\n* [Extract Class](http://sourcemaking.com/refactoring/extract-class)\n* [Form Template Method](http://sourcemaking.com/refactoring/form-template-method)\n* [Introduce Null Object](http://sourcemaking.com/refactoring/introduce-null-object)\n* [Pull Up Method](http://sourcemaking.com/refactoring/pull-up-method)\n* [Pull Up Field](http://sourcemaking.com/refactoring/pull-up-field)\n* [Substitute Algorithm](http://sourcemaking.com/refactoring/substitute-algorithm)\n\n## Further Reading\n\n* [Don't Repeat Yourself](http://c2.com/cgi/wiki?DontRepeatYourself) on the C2 Wiki\n* [Duplicated Code](http://sourcemaking.com/refactoring/duplicated-code) on SourceMaking\n* [Refactoring: Improving the Design of Existing Code](http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672) by Martin Fowler. _Duplicated Code_, p76\n"},"fingerprint":"9ff0344a1b63248724d8413b03573b43","severity":"minor","engine_name":"duplication"},{"categories":["Security"],"check_name":"Insecure Dependency","content":{"body":"**Advisory**: CVE-2018-1000211\n\n**URL**: https://blog.justinbull.ca/cve-2018-1000211-public-apps-cant-revoke-tokens-in-doorkeeper/\n\n**Solution**: upgrade to >= 4.4.0, >= 5.0.0.rc2"},"description":"Doorkeeper gem does not revoke token for public clients","location":{"path":"Gemfile.lock","lines":{"begin":173,"end":173}},"remediation_points":5000000,"severity":"minor","type":"Issue","fingerprint":"13e50c564110ecb5eba441004fe52261","engine_name":"bundler-audit"},{"categories":["Security"],"check_name":"Insecure Dependency","content":{"body":"**Advisory**: CVE-2018-3769\n\n**URL**: https://github.com/ruby-grape/grape/issues/1762\n\n**Solution**: upgrade to >= 1.1.0"},"description":"ruby-grape Gem has XSS via \"format\" parameter","location":{"path":"Gemfile.lock","lines":{"begin":346,"end":346}},"remediation_points":5000000,"severity":"minor","type":"Issue","fingerprint":"ac6d981abbf80f299374d5a1081c7d66","engine_name":"bundler-audit"}]
diff --git a/spec/fixtures/codequality/codequality.json.gz b/spec/fixtures/codequality/codequality.json.gz
new file mode 100644
index 00000000000..f04ec0065b4
--- /dev/null
+++ b/spec/fixtures/codequality/codequality.json.gz
Binary files differ
diff --git a/spec/fixtures/emails/merge_request_multiple_patches.eml b/spec/fixtures/emails/merge_request_multiple_patches.eml
new file mode 100644
index 00000000000..311b99a525d
--- /dev/null
+++ b/spec/fixtures/emails/merge_request_multiple_patches.eml
@@ -0,0 +1,181 @@
+From: "Jake the Dog" <jake@adventuretime.ooo>
+To: incoming+gitlabhq/gitlabhq+merge-request+auth_token@appmail.adventuretime.ooo
+Subject: new-branch-with-a-patch
+Date: Wed, 31 Oct 2018 17:27:52 +0100
+X-Mailer: MailMate (1.12r5523)
+Message-ID: <7BE7C2E6-F0D9-4C85-9F55-B2A4BA01BFEC@gitlab.com>
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_="
+
+
+--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
+
+This applies nicely to a branch freshly created from the root-ref
+
+The other attachments in this email are ignored
+
+--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
+Content-Disposition: attachment;
+ filename=0002-This-does-not-apply-to-the-feature-branch.patch
+Content-Transfer-Encoding: quoted-printable
+
+=46rom 00c68c2b4f954370ce82a1162bc29c13f524897e Mon Sep 17 00:00:00 2001
+From: Patch user <patchuser@gitlab.org>
+Date: Mon, 22 Oct 2018 11:05:48 +0200
+Subject: [PATCH] This does not apply to the `feature` branch
+
+---
+ files/ruby/feature.rb | 5 +++++
+ 1 file changed, 5 insertions(+)
+ create mode 100644 files/ruby/feature.rb
+
+diff --git a/files/ruby/feature.rb b/files/ruby/feature.rb
+new file mode 100644
+index 0000000..fef26e4
+--- /dev/null
++++ b/files/ruby/feature.rb
+@@ -0,0 +1,5 @@
++class Feature
++ def bar
++ puts 'foo'
++ end
++end
+-- =
+
+2.19.1
+
+--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
+Content-Disposition: attachment; filename=0001-A-commit-from-a-patch.patch
+Content-Transfer-Encoding: quoted-printable
+
+=46rom 3fee0042e610fb3563e4379e316704cb1210f3de Mon Sep 17 00:00:00 2001
+From: Patch user <patchuser@gitlab.org>
+Date: Thu, 18 Oct 2018 13:40:35 +0200
+Subject: [PATCH] A commit from a patch
+
+---
+ README | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/README b/README
+index 3742e48..e40a3b9 100644
+--- a/README
++++ b/README
+@@ -1 +1,3 @@
+ Sample repo for testing gitlab features
++
++This was applied in a patch!
+-- =
+
+2.19.1
+
+
+--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
+Content-Disposition: attachment; filename=really-not-a-patch.png
+Content-Type: image/png
+Content-Transfer-Encoding: base64
+
+iVBORw0KGgoAAAANSUhEUgAAAjMAAAAfCAYAAAASo0ymAAABfGlDQ1BJQ0MgUHJvZmlsZQAAKJFj
+YGAqSSwoyGFhYGDIzSspCnJ3UoiIjFJgv8PAzcDDIMRgxSCemFxc4BgQ4MOAE3y7xsAIoi/rgsxK
+8/x506a1fP4WNq+ZclYlOrj1gQF3SmpxMgMDIweQnZxSnJwLZOcA2TrJBUUlQPYMIFu3vKQAxD4B
+ZIsUAR0IZN8BsdMh7A8gdhKYzcQCVhMS5AxkSwDZAkkQtgaInQ5hW4DYyRmJKUC2B8guiBvAgNPD
+RcHcwFLXkYC7SQa5OaUwO0ChxZOaFxoMcgcQyzB4MLgwKDCYMxgwWDLoMjiWpFaUgBQ65xdUFmWm
+Z5QoOAJDNlXBOT+3oLQktUhHwTMvWU9HwcjA0ACkDhRnEKM/B4FNZxQ7jxDLX8jAYKnMwMDcgxBL
+msbAsH0PA4PEKYSYyjwGBn5rBoZt5woSixLhDmf8xkKIX5xmbARh8zgxMLDe+///sxoDA/skBoa/
+E////73o//+/i4H2A+PsQA4AJHdp4IxrEg8AAAGcaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8
+eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA1LjQu
+MCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1y
+ZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAg
+ICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAg
+ICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjU2MzwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAg
+ICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4zMTwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAg
+IDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpZ5vHZAAAS+ElE
+QVR4Ae2cC1QUV5rH/xnA1uZli02MiEHQqBMdTGB8ZIniA5xgfCTRycb1rBmdTHJGJ+toPBtzzGg2
+Rs3LdVTOYhKMcDgmDNHVNXKiGKJINCoqiXpUEFdB0CDKCtrSYp/Zr6q7muqmu+pWd7XgnFtH6Xrc
++h6/+92qr+69VQ9dqrvxd/CFE+AEOAFOgBPgBDiBB5TALx5Qu7nZnAAnwAlwApwAJ8AJiAR4MsMD
+gRPgBDgBToAT4AQeaAI8mXmgq48bzwlwApwAJ8AJcAI8meExwAlwApwAJ8AJcAIPNAGezDzQ1ceN
+5wQ4AU6AE+AEOIFgTwiamls87eb7OAFOgBPgBDgBToAT0I1ARHhXXWTxnhldMHIhnAAnwAlwApwA
+J9BRBIL+vOjfl7srt969577L63Zj1VGU/liHHn1j0I0xNbI1X8TRo5V4yNQLEQbGk7xawH6go/Sy
+W8hLBoqAL3EaKFtY5doaz6PkwCk8FN0H3f1oJx0d93r5wcpN13K2RhzbX4KKn4FH+vSAx65sXRX+
+YwgTYq5k72FUXqzChaoq1DQGI7Z3dwT6ai/oPbj/OJoNDyM6IsRvmL74odTe9LbPbwc7gQCDQZ9W
+5VFK0co52FKp7OW0N9di6sAI1B//G7YU3kHvEb+Gyah8jnTUWncYWdm7kf7GWrz0eIS0O+C/HaVX
+P8dsqPphL07dicFvxg6BQT/BnVSSfv76EqcdDcVafww5X1A7iRmGR/1oJ+pxrx9nT8z08sOT7IDv
+s9YiPzcf10InImlkfy9tLrD8Au5jABRY6w8j56vdbZIFfslxCG/bE5A1Idazqc2EpUVj/cwhfuvw
+xQ+l9qa3fX47eN8EWFC4cj4KKgdjadZiJATg5uUxUQ6JiEGYOQpm8X9bhiLtC4MRIcH2PCg4RBjv
+Mml7YgkOFRFGhnrMpQKHt6P06ubRbZzIy8f2radxVzeZnVmQfv76FKcdjSa4i2hBiL/NRDXu9ePs
+EZlefngUHuCdQcF0daOlRxcEeVUVYH5e9XbeA8aEF/HZZ5vw2Zo/wSyYqchPRz8csdbD70Zjt8kn
+P5Tam8726Ugu4KJaxam4TWixBUaVx8tk6vx3kSrps57HqtdWosI8Ge9/8BylMV4WR0u32WwICvLe
+7IWzjQnP4vPPn/UiKHC7O0qvfh4ZYOxB0lpCYb/N6Se5c0oKgL8a4rRjmNhATUhsQwblZsRsnnrc
+B4Az9PeD2eH7XjAQ/O67E7orFG8Dxm5iMnhNd+n3T6BWP9Tb2/2zvTNpkgb9PCYdOhjKINcxf4Y6
+YJQSquoTxdiVl4eTtwWrYjDzzYVIGyg+0zjNrC3NQ27JFUREGGC1Av/04qsY0ad9f1PD6d3IzdmJ
+k9cs4rlh5niMmTIL01PinLK0rHSE3trSTfikBMhIj8P3m5W5NJwrxqfr81AhsgP6Jk3GnDnP4VEp
+c7ReRM7H2agjpytqBM+/wZqPz0CA2NJiQMYfX8eIXu05KjFqvnwCuwv34shPZ3DNofexpIl4/l+m
+Y6BJ+13U7u9djEg0YR91L4sXL/MwzF/4KpJktjHp1eyvFee+244tW3ejWvTFiMeSnsZvZ09HQrir
+LyxxqsRNOsbkBxXWEgdV1D7WZhfjlqAkNgWzUyRtvv2qxr1mzmx2sPqhGvcOdZarJ1CwaQv2VV4X
+94TFDsfLf/ydS1wJB1iuG1rqw6He+0+A+Kn5a71cgjXritB7yh8oRmJl9jWh6JN1KL07DAvmP2vv
+UaKjavIEAbpykVnEssoaB6zl3HU2nP4auTsO42ZECt6YPzFgQ12q7c3dMMe2N/tY6s2LSI+7Wfhp
+iQO97fNotIadHoeZvJ3veluQSgk30Vps2ZiHq/1SkJ4UY99enYlz9lxEKmj/peLW+gqcPFWOmtuU
+0bgttqvFWPxRPiUyQHLaRExKG47elgvYlV2KZreymjbvs96WhjpUV5YiK1OZS/PpfCxebU9kho4Z
+h6eGRKH62E4sn7cOl5x4gtDFEEFJYATCRKe7wWAwiNuRkeHahvgc0Kr3rseuQ5QQ9R6MVOKcOiQG
+Fcd2Y/XCNahy6mUnbPf3CAookemWNA6TxsQD18qxYckK/CirODa9Wvy1onTDIqzOFRKZKKRmTEb6
+mEdFX0ovOLI00Q2NcariOpsf1InGGAe1peuwQkxkYpA+dSKG3iil+TKlKlYwHFaMey2cGXRREVY/
+2OKebsRVuzFvyXoxkXlsFF0PxgzGrZojFFeLcLih7fGK9brBWh/tvPX4tQr9+bH4a+gRjZZrtdj3
+5X40ygy1XS7DlkMXUA26Vjj2s8gTivrMRabfl1XWOGAt525D7Q+b6H6yDScrDXj+n1MDlsg49Sq2
+N2cp54o3+1jrzSlIZYWVH2sc6G2fivlMhxl6ZpjkIPmltzAvvb9Y+Fdb3sZHRRdwsqYJA2mSsLTE
+pMzCEnratF38Gr9/Z5u02+XXevOmuJ3+xgc0OdjRNTHzFTQ3W30OxI7SKziizMWC4vzdor8zaEJ1
+hshqFp7c/DY27C/H1oM1WDiWnrwMsXhp0WIqZ0PhX15BQcsYzKMnL+H27OvSf+p7WPVCNHo5ey5e
+xIQ9H2LpF2dw4mITEmT1pkVH34w/4Z0ZT4in/Lr3Oiz/ohyFJeeROMkeG0x6NfhrOVeI7GOUNZvH
+YcWqWYhxZNy/faEGV++1J6RcH+yeMvkhE6es9woKs8updBTmf/guknrS6uSn8Om/LcNBeT4mk8ey
+qhr3Gjiz6ANY/WCMe+rf2/Gf+aQ6CnNXrUZKL3vlPjehGAvezkPWl98jef5ocS6L1uuGcn3IvDUM
+wpLPN8l2yFZ158for3EQpowyYsOhYpRdnoE0R+/22ZLvROOmpSU75vcwypO5xMxFdo7vq6xxwFqu
+zZKudOuoKs2iB4QjQOhwLP/gtbae7rZiuq6ptjeZNmX7tNebTLSHVe38lOPAP/vY35X24IrCLt2S
+mcRf9XOq6ZtIs8iLahHipc/Aamt1lm2/Yp/auicnE5HPP4PEuBiYzCaEh0tjLu3PYN3TEXoVuViq
+cbyGrDdPxNOy5CHp2QyE7f8UNxvc72RW2Mm1ihOA29+qWUlQfmR6BIaLJ1D4zQn878+30KVLF9xt
+qGcX0K6k0J1jRMYEeyIjHH40JR19KZmpOHwSFkpmhBrUplfd35qfjguqkD57ijOREbaDwmNpsLP9
+olgf7Yt73aPND0BRr+UmLguaaHhxmJDICEtQLMZNiMfBHRfs2378VY57QbA6Zyb1rH6wxr3lOs6K
+TeA6DnyTgzN37deGLtRHKw7FVV+B0Plrf0NG23VDsT6YnJUX0osfu79Dxv8GOLQNRSWVSBPe2rHV
+YB9dc4HhGDHQca3UxM/uj75c5Iw8rDPHgdbrJA3Hf/UBVogqB2P5XymR8Tys4MEo/3eptzcV+3yo
+N0WrWTnLhCjGgT/2hfbDw/7fymWWtq3qkMwIN7EYmGXzLIK62qentkJ7Dmbsn46Zo05Rd+kZFGyk
+/w5bU//1Lcwa21/hjYI2p3xZ018vAxdqYOK3D4mXS1sLN6M3OVFRXUe3mUEuPTDSJCqX8j44fLqA
+es8KhYsf5VKx8TCRIS3/d8cHSfJTTOguD1RbM3V5uy5a9ar5GxxiT+mMXdVCmaE+XE1V3GL3g0Gv
+ozLND0e7xMG9VuHc+7OocWaygtUPKscU91KQmyktratDg8yIoQPiYe1pdvJib78M9SHTw7qqJz8w
++GtIGIHU0G2UwBSjlpIZ0/mDKCNj+05NRS/JaA38hIRWz+u4ZILir4Y4YIoXj8rOYN/RK5g98hGP
+Rzt+pwf7NNUbgwesnEVRDHHgo33ig7jR5P0lIgZXlIqo3QGUznU91jZ87bpf61aQCWl/eBfjZjXh
+Wn0dzh7dg62F5diXuxHJIz6ENPKkVaxq+UDpVeJCx8ShePfx+LvN4li4uW9vl0SmzYe7NODkx0Jv
+qP2PkMiEplD36xxn96u16r/x2oqdfghuQYvwgCx1GXUJx2O0WUH+ifb6rNe7v9INv5U1b/YLnAON
+L34o6XUcu3NbNrmIVAUbJZAOvQH/8c6ZSTWrH1SOKe4lZt3HYslb45RN0Np+JdnKUjUe1YcfWPyl
+F55TnomnyfblKKtqRJ/9B8hWI9JGDmizWfKRSZ7jNOmcNin+rZE898ubU6B0zL2A+/WPtZxTMBA2
+6hW8P6Mr3l9I8602voeEuL86hyllxdhXJRvYz1AsqWgf6RIXLfWmpE2yXY2zXIZkg3yftC4d02Sf
+EVP/YxOmSjIC8KtpArBe+g1B9ueYkGAPF2ubVbzxBRkj0CtuEFJnvI7X0qJItZib+2VCR+n1arQx
+CoNC6ei1gzgpe+y8VLJXfBvIZHTPNe/Zh5munUKdkED7utju2S8w/eKciQxNtcS3+d/6KpHOE+ry
+OkrLapwyGs+WoYK2zMMG2IcCNOtV9ze6n314c9fXB8QhB6dyetK0WKVW17ZXlzXNfqhoNXRFNBW5
+tX+fbPJ1E04d9n+ISdCsGPeiaeqcxWJqf1j9YI17Q6jIBZXf4Uf5TFfRDrf6DeB1Q81tUA+0+NTp
+b7vU4i8ZlTBivPhCwPaNK7H5EA24xY7Hk455RaLNGuWp++lDCWNvDDXTeTdui30/LhJY44C1nEx4
+j2jqATA9gQULhCTYguwlmaj153Kg5IdMr7Cq3t7osztK9uldbz7wc3PJddMn+yy4dO4sTp87j0Z/
+7l2ulrhsud8tXQ66bFBW508s2JrP40BJFVqNIWi9Qm/R0HL820JEVhthae2G4eNHoyd1X53bthSr
+C7siffpY/DLOhObKE8gvEl7JHIwwD7mPKEjhT0fpVTBJdsiM0S8Mw57ccmQtXoHrr05ExNVjyN4h
+8IlCxuj+srLCagT6D6LErqYWGz7OwoRkupHTNWzI+AntXkF2O9F10xGM1afykEnjeKm/DMdPO3Kw
+p1KYgeDfUpa7DDmWlzHIeAVbc4tFYRmjHU+LmvWq+2tKfg6TzKXYdSof81bWYm76UIS0/Izvs7ch
+ir4wPduPL+d6JaHZD6+S7AeC4jBhagzKqN5XvJeFuVOScP2Hv2F7W16oIqD9Yda4t5+pzrm9Bg97
+mP1gjHuaN/Tiqyko21iKtQsXY9JLk9GPPlF/4+oZFO0oxZ0xC7H+ZZovQove1w0P3ins0osfu7+i
+MT0T8UwsUFBzXZxDlJw+0rULXwM/Bef8PBSKfv1p7JkmK/9l5S2MGRBGHUiPY/KkJ+jxhzEOmMvJ
+TBWzS/qca+IsLEg7h7VF5Vi6thhZi8Y5O45lpRlWlfygeyPj/c2pSMk+3euNlbPTOuUVX+yjN5Iz
+V68BvaQcsC//sycz3UOc49OungoZhudUSz4B2Fp/kj5v7TqEUX1oJ3IOCdKiaLIoJTMU85GxifS0
+UYw9X+Vhj6QoNB6z//x7nyZxdZRee0+FOpeYsfPwhiUTH1F3ccHG/3J4HI+5y15Hon1mo0RB/H38
+hdcx7cYn2H7sCLZXHrEfG/o0JTPyySoup7TfoGD83bKXUf/OZpQV5tF/oUg80tMM2FN0hiZu+76Y
+B0RR1/dm7HOImDTvPaRK3xLyQa+6vyZMX/U+IrPX0TyrUmTT6/D2JQZzI+XZL1ucOk5W/tHkB5ve
+gdMWY279h8g+dATZmUK9RuGpUTQBmF61lb62rWyU61HWuJfOUucslVT+ZfWDNe57jpyDVcEmrMnc
+iV1fbG5THhqDaU887Nxmv26w1YdTMOOKXvxY/bWbZcTwKSkoyBRiPh4TnnyknbXs8gLDhWayI2nu
+Msy4uw4FdM3aVUkmmkORQcmMsLDGAWu5IMfVq6usVztx5kJMOruIHnjy8GXZUMxOFrqKtC7KfrC2
+N1b72OuNzQ9Wfqz3Lc32Ob6kLSQzkarzG9l8ci/10KW6G39339nU7D645l4i0Ns2WCy36UuoNljv
+BcFkivCSSOltR0fppcze0kTdb9T3Rf/Ce5p8fHrQysOKxkZ7b4zR5J/Oqu1vY8UOA5Z+thRx5EvT
+PRvN+aC30IRrZLtFP71y0VZLI+gNfhho+NJIyR119AV40d8PS2Oj+GhgECbKeWQXYJd0Es/qB3vc
+E+uGJqpcA4KDDAj3CKfj2q9O2GRiWPyVFVdd1VueqkJNBVjjgLWcJuWdurC+9aY/P//tiwj3fwqJ
+UIWdNJnp1NHFjfNAwJ7MAG9mvgvpzVAPxfguToAT4AQ4AU7ASUCvZIZ9mMmpmq9wAu0J3Gu1z9Bk
+famovQS+hxPgBDgBToAT8I0A75nxjRs/y42ApaEGV24Go08CfYzP7Rjf5AQ4AU6AE+AEPBHQq2fG
+YzLjSSHfxwlwApwAJ8AJcAKcQGck8IvOaBS3iRPgBDgBToAT4AQ4AVYCPJlhJcXLcQKcACfACXAC
+nECnJMCTmU5ZLdwoToAT4AQ4AU6AE2AlwJMZVlK8HCfACXACnAAnwAl0SgI8memU1cKN4gQ4AU6A
+E+AEOAFWAv8PxvdR0yK8jugAAAAASUVORK5CYII=
+
+--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=--
diff --git a/spec/fixtures/emails/merge_request_with_conflicting_patch.eml b/spec/fixtures/emails/merge_request_with_conflicting_patch.eml
new file mode 100644
index 00000000000..ddfdfe9e24a
--- /dev/null
+++ b/spec/fixtures/emails/merge_request_with_conflicting_patch.eml
@@ -0,0 +1,45 @@
+From: "Jake the Dog" <jake@adventuretime.ooo>
+To: incoming+gitlabhq/gitlabhq+merge-request+auth_token@appmail.adventuretime.ooo
+Subject: feature
+Date: Wed, 31 Oct 2018 17:27:52 +0100
+X-Mailer: MailMate (1.12r5523)
+Message-ID: <7BE7C2E6-F0D9-4C85-9F55-B2A4BA01BFEC@gitlab.com>
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_="
+
+--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
+
+This does not apply
+
+--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
+Content-Disposition: attachment;
+ filename=0002-This-does-not-apply-to-the-feature-branch.patch
+Content-Transfer-Encoding: quoted-printable
+
+=46rom 00c68c2b4f954370ce82a1162bc29c13f524897e Mon Sep 17 00:00:00 2001
+From: Patch user <patchuser@gitlab.org>
+Date: Mon, 22 Oct 2018 11:05:48 +0200
+Subject: [PATCH] This does not apply to the `feature` branch
+
+---
+ files/ruby/feature.rb | 5 +++++
+ 1 file changed, 5 insertions(+)
+ create mode 100644 files/ruby/feature.rb
+
+diff --git a/files/ruby/feature.rb b/files/ruby/feature.rb
+new file mode 100644
+index 0000000..fef26e4
+--- /dev/null
++++ b/files/ruby/feature.rb
+@@ -0,0 +1,5 @@
++class Feature
++ def bar
++ puts 'foo'
++ end
++end
+-- =
+
+2.19.1
+
+--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=--
diff --git a/spec/fixtures/emails/merge_request_with_patch_and_target_branch.eml b/spec/fixtures/emails/merge_request_with_patch_and_target_branch.eml
new file mode 100644
index 00000000000..965658721cd
--- /dev/null
+++ b/spec/fixtures/emails/merge_request_with_patch_and_target_branch.eml
@@ -0,0 +1,44 @@
+From: "Jake the Dog" <jake@adventuretime.ooo>
+To: incoming+gitlabhq/gitlabhq+merge-request+auth_token@appmail.adventuretime.ooo
+Subject: new-branch-with-a-patch
+Date: Wed, 24 Oct 2018 16:39:49 +0200
+X-Mailer: MailMate (1.12r5523)
+Message-ID: <F1F36291-728D-4E8F-AFEB-C398B8D9BB4E@gitlab.com>
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_="
+
+
+--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
+
+This applies nicely to a branch freshly created from the root-ref
+
+The other attachments in this email are ignored
+
+/target_branch with-codeowners
+
+
+--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
+Content-Disposition: attachment; filename=0001-A-commit-from-a-patch.patch
+Content-Transfer-Encoding: quoted-printable
+
+=46rom 3fee0042e610fb3563e4379e316704cb1210f3de Mon Sep 17 00:00:00 2001
+From: Patch user <patchuser@gitlab.org>
+Date: Thu, 18 Oct 2018 13:40:35 +0200
+Subject: [PATCH] A commit from a patch
+
+---
+ README | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/README b/README
+index 3742e48..e40a3b9 100644
+--- a/README
++++ b/README
+@@ -1 +1,3 @@
+ Sample repo for testing gitlab features
++
++This was applied in a patch!
+-- =
+
+2.19.1
diff --git a/spec/fixtures/emails/paragraphs.eml b/spec/fixtures/emails/paragraphs.eml
index 2d5b5283f7e..6ab319fa83a 100644
--- a/spec/fixtures/emails/paragraphs.eml
+++ b/spec/fixtures/emails/paragraphs.eml
@@ -17,7 +17,7 @@ X-Received: by 10.0.0.1 with SMTP id n7mr11234144ipb.85.1371157428600; Thu,
13 Jun 2013 14:03:48 -0700 (PDT)
X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1
-Is there any reason the *old* candy can't be be kept in silos while the new candy
+Is there any reason the *old* candy can't be kept in silos while the new candy
is imported into *new* silos?
The thing about candy is it stays delicious for a long time -- we can just keep
diff --git a/spec/fixtures/emails/valid_merge_request_with_patch.eml b/spec/fixtures/emails/valid_merge_request_with_patch.eml
new file mode 100644
index 00000000000..143fa77d1fa
--- /dev/null
+++ b/spec/fixtures/emails/valid_merge_request_with_patch.eml
@@ -0,0 +1,151 @@
+From: "Jake the Dog" <jake@adventuretime.ooo>
+To: incoming+gitlabhq/gitlabhq+merge-request+auth_token@appmail.adventuretime.ooo
+Subject: new-branch-with-a-patch
+Date: Wed, 24 Oct 2018 16:39:49 +0200
+X-Mailer: MailMate (1.12r5523)
+Message-ID: <F1F36291-728D-4E8F-AFEB-C398B8D9BB4E@gitlab.com>
+MIME-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_="
+
+
+--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
+
+This applies nicely to a branch freshly created from the root-ref
+
+The other attachments in this email are ignored
+
+
+--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
+Content-Disposition: attachment; filename=0001-A-commit-from-a-patch.patch
+Content-Transfer-Encoding: quoted-printable
+
+=46rom 3fee0042e610fb3563e4379e316704cb1210f3de Mon Sep 17 00:00:00 2001
+From: Patch user <patchuser@gitlab.org>
+Date: Thu, 18 Oct 2018 13:40:35 +0200
+Subject: [PATCH] A commit from a patch
+
+---
+ README | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/README b/README
+index 3742e48..e40a3b9 100644
+--- a/README
++++ b/README
+@@ -1 +1,3 @@
+ Sample repo for testing gitlab features
++
++This was applied in a patch!
+-- =
+
+2.19.1
+
+
+--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
+Content-Disposition: attachment; filename=really-not-a-patch.png
+Content-Type: image/png
+Content-Transfer-Encoding: base64
+
+iVBORw0KGgoAAAANSUhEUgAAAjMAAAAfCAYAAAASo0ymAAABfGlDQ1BJQ0MgUHJvZmlsZQAAKJFj
+YGAqSSwoyGFhYGDIzSspCnJ3UoiIjFJgv8PAzcDDIMRgxSCemFxc4BgQ4MOAE3y7xsAIoi/rgsxK
+8/x506a1fP4WNq+ZclYlOrj1gQF3SmpxMgMDIweQnZxSnJwLZOcA2TrJBUUlQPYMIFu3vKQAxD4B
+ZIsUAR0IZN8BsdMh7A8gdhKYzcQCVhMS5AxkSwDZAkkQtgaInQ5hW4DYyRmJKUC2B8guiBvAgNPD
+RcHcwFLXkYC7SQa5OaUwO0ChxZOaFxoMcgcQyzB4MLgwKDCYMxgwWDLoMjiWpFaUgBQ65xdUFmWm
+Z5QoOAJDNlXBOT+3oLQktUhHwTMvWU9HwcjA0ACkDhRnEKM/B4FNZxQ7jxDLX8jAYKnMwMDcgxBL
+msbAsH0PA4PEKYSYyjwGBn5rBoZt5woSixLhDmf8xkKIX5xmbARh8zgxMLDe+///sxoDA/skBoa/
+E////73o//+/i4H2A+PsQA4AJHdp4IxrEg8AAAGcaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8
+eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA1LjQu
+MCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1y
+ZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAg
+ICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAg
+ICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjU2MzwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAg
+ICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4zMTwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAg
+IDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpZ5vHZAAAS+ElE
+QVR4Ae2cC1QUV5rH/xnA1uZli02MiEHQqBMdTGB8ZIniA5xgfCTRycb1rBmdTHJGJ+toPBtzzGg2
+Rs3LdVTOYhKMcDgmDNHVNXKiGKJINCoqiXpUEFdB0CDKCtrSYp/Zr6q7muqmu+pWd7XgnFtH6Xrc
++h6/+92qr+69VQ9dqrvxd/CFE+AEOAFOgBPgBDiBB5TALx5Qu7nZnAAnwAlwApwAJ8AJiAR4MsMD
+gRPgBDgBToAT4AQeaAI8mXmgq48bzwlwApwAJ8AJcAI8meExwAlwApwAJ8AJcAIPNAGezDzQ1ceN
+5wQ4AU6AE+AEOIFgTwiamls87eb7OAFOgBPgBDgBToAT0I1ARHhXXWTxnhldMHIhnAAnwAlwApwA
+J9BRBIL+vOjfl7srt969577L63Zj1VGU/liHHn1j0I0xNbI1X8TRo5V4yNQLEQbGk7xawH6go/Sy
+W8hLBoqAL3EaKFtY5doaz6PkwCk8FN0H3f1oJx0d93r5wcpN13K2RhzbX4KKn4FH+vSAx65sXRX+
+YwgTYq5k72FUXqzChaoq1DQGI7Z3dwT6ai/oPbj/OJoNDyM6IsRvmL74odTe9LbPbwc7gQCDQZ9W
+5VFK0co52FKp7OW0N9di6sAI1B//G7YU3kHvEb+Gyah8jnTUWncYWdm7kf7GWrz0eIS0O+C/HaVX
+P8dsqPphL07dicFvxg6BQT/BnVSSfv76EqcdDcVafww5X1A7iRmGR/1oJ+pxrx9nT8z08sOT7IDv
+s9YiPzcf10InImlkfy9tLrD8Au5jABRY6w8j56vdbZIFfslxCG/bE5A1Idazqc2EpUVj/cwhfuvw
+xQ+l9qa3fX47eN8EWFC4cj4KKgdjadZiJATg5uUxUQ6JiEGYOQpm8X9bhiLtC4MRIcH2PCg4RBjv
+Mml7YgkOFRFGhnrMpQKHt6P06ubRbZzIy8f2radxVzeZnVmQfv76FKcdjSa4i2hBiL/NRDXu9ePs
+EZlefngUHuCdQcF0daOlRxcEeVUVYH5e9XbeA8aEF/HZZ5vw2Zo/wSyYqchPRz8csdbD70Zjt8kn
+P5Tam8726Ugu4KJaxam4TWixBUaVx8tk6vx3kSrps57HqtdWosI8Ge9/8BylMV4WR0u32WwICvLe
+7IWzjQnP4vPPn/UiKHC7O0qvfh4ZYOxB0lpCYb/N6Se5c0oKgL8a4rRjmNhATUhsQwblZsRsnnrc
+B4Az9PeD2eH7XjAQ/O67E7orFG8Dxm5iMnhNd+n3T6BWP9Tb2/2zvTNpkgb9PCYdOhjKINcxf4Y6
+YJQSquoTxdiVl4eTtwWrYjDzzYVIGyg+0zjNrC3NQ27JFUREGGC1Av/04qsY0ad9f1PD6d3IzdmJ
+k9cs4rlh5niMmTIL01PinLK0rHSE3trSTfikBMhIj8P3m5W5NJwrxqfr81AhsgP6Jk3GnDnP4VEp
+c7ReRM7H2agjpytqBM+/wZqPz0CA2NJiQMYfX8eIXu05KjFqvnwCuwv34shPZ3DNofexpIl4/l+m
+Y6BJ+13U7u9djEg0YR91L4sXL/MwzF/4KpJktjHp1eyvFee+244tW3ejWvTFiMeSnsZvZ09HQrir
+LyxxqsRNOsbkBxXWEgdV1D7WZhfjlqAkNgWzUyRtvv2qxr1mzmx2sPqhGvcOdZarJ1CwaQv2VV4X
+94TFDsfLf/ydS1wJB1iuG1rqw6He+0+A+Kn5a71cgjXritB7yh8oRmJl9jWh6JN1KL07DAvmP2vv
+UaKjavIEAbpykVnEssoaB6zl3HU2nP4auTsO42ZECt6YPzFgQ12q7c3dMMe2N/tY6s2LSI+7Wfhp
+iQO97fNotIadHoeZvJ3veluQSgk30Vps2ZiHq/1SkJ4UY99enYlz9lxEKmj/peLW+gqcPFWOmtuU
+0bgttqvFWPxRPiUyQHLaRExKG47elgvYlV2KZreymjbvs96WhjpUV5YiK1OZS/PpfCxebU9kho4Z
+h6eGRKH62E4sn7cOl5x4gtDFEEFJYATCRKe7wWAwiNuRkeHahvgc0Kr3rseuQ5QQ9R6MVOKcOiQG
+Fcd2Y/XCNahy6mUnbPf3CAookemWNA6TxsQD18qxYckK/CirODa9Wvy1onTDIqzOFRKZKKRmTEb6
+mEdFX0ovOLI00Q2NcariOpsf1InGGAe1peuwQkxkYpA+dSKG3iil+TKlKlYwHFaMey2cGXRREVY/
+2OKebsRVuzFvyXoxkXlsFF0PxgzGrZojFFeLcLih7fGK9brBWh/tvPX4tQr9+bH4a+gRjZZrtdj3
+5X40ygy1XS7DlkMXUA26Vjj2s8gTivrMRabfl1XWOGAt525D7Q+b6H6yDScrDXj+n1MDlsg49Sq2
+N2cp54o3+1jrzSlIZYWVH2sc6G2fivlMhxl6ZpjkIPmltzAvvb9Y+Fdb3sZHRRdwsqYJA2mSsLTE
+pMzCEnratF38Gr9/Z5u02+XXevOmuJ3+xgc0OdjRNTHzFTQ3W30OxI7SKziizMWC4vzdor8zaEJ1
+hshqFp7c/DY27C/H1oM1WDiWnrwMsXhp0WIqZ0PhX15BQcsYzKMnL+H27OvSf+p7WPVCNHo5ey5e
+xIQ9H2LpF2dw4mITEmT1pkVH34w/4Z0ZT4in/Lr3Oiz/ohyFJeeROMkeG0x6NfhrOVeI7GOUNZvH
+YcWqWYhxZNy/faEGV++1J6RcH+yeMvkhE6es9woKs8updBTmf/guknrS6uSn8Om/LcNBeT4mk8ey
+qhr3Gjiz6ANY/WCMe+rf2/Gf+aQ6CnNXrUZKL3vlPjehGAvezkPWl98jef5ocS6L1uuGcn3IvDUM
+wpLPN8l2yFZ158for3EQpowyYsOhYpRdnoE0R+/22ZLvROOmpSU75vcwypO5xMxFdo7vq6xxwFqu
+zZKudOuoKs2iB4QjQOhwLP/gtbae7rZiuq6ptjeZNmX7tNebTLSHVe38lOPAP/vY35X24IrCLt2S
+mcRf9XOq6ZtIs8iLahHipc/Aamt1lm2/Yp/auicnE5HPP4PEuBiYzCaEh0tjLu3PYN3TEXoVuViq
+cbyGrDdPxNOy5CHp2QyE7f8UNxvc72RW2Mm1ihOA29+qWUlQfmR6BIaLJ1D4zQn878+30KVLF9xt
+qGcX0K6k0J1jRMYEeyIjHH40JR19KZmpOHwSFkpmhBrUplfd35qfjguqkD57ijOREbaDwmNpsLP9
+olgf7Yt73aPND0BRr+UmLguaaHhxmJDICEtQLMZNiMfBHRfs2378VY57QbA6Zyb1rH6wxr3lOs6K
+TeA6DnyTgzN37deGLtRHKw7FVV+B0Plrf0NG23VDsT6YnJUX0osfu79Dxv8GOLQNRSWVSBPe2rHV
+YB9dc4HhGDHQca3UxM/uj75c5Iw8rDPHgdbrJA3Hf/UBVogqB2P5XymR8Tys4MEo/3eptzcV+3yo
+N0WrWTnLhCjGgT/2hfbDw/7fymWWtq3qkMwIN7EYmGXzLIK62qentkJ7Dmbsn46Zo05Rd+kZFGyk
+/w5bU//1Lcwa21/hjYI2p3xZ018vAxdqYOK3D4mXS1sLN6M3OVFRXUe3mUEuPTDSJCqX8j44fLqA
+es8KhYsf5VKx8TCRIS3/d8cHSfJTTOguD1RbM3V5uy5a9ar5GxxiT+mMXdVCmaE+XE1V3GL3g0Gv
+ozLND0e7xMG9VuHc+7OocWaygtUPKscU91KQmyktratDg8yIoQPiYe1pdvJib78M9SHTw7qqJz8w
++GtIGIHU0G2UwBSjlpIZ0/mDKCNj+05NRS/JaA38hIRWz+u4ZILir4Y4YIoXj8rOYN/RK5g98hGP
+Rzt+pwf7NNUbgwesnEVRDHHgo33ig7jR5P0lIgZXlIqo3QGUznU91jZ87bpf61aQCWl/eBfjZjXh
+Wn0dzh7dg62F5diXuxHJIz6ENPKkVaxq+UDpVeJCx8ShePfx+LvN4li4uW9vl0SmzYe7NODkx0Jv
+qP2PkMiEplD36xxn96u16r/x2oqdfghuQYvwgCx1GXUJx2O0WUH+ifb6rNe7v9INv5U1b/YLnAON
+L34o6XUcu3NbNrmIVAUbJZAOvQH/8c6ZSTWrH1SOKe4lZt3HYslb45RN0Np+JdnKUjUe1YcfWPyl
+F55TnomnyfblKKtqRJ/9B8hWI9JGDmizWfKRSZ7jNOmcNin+rZE898ubU6B0zL2A+/WPtZxTMBA2
+6hW8P6Mr3l9I8602voeEuL86hyllxdhXJRvYz1AsqWgf6RIXLfWmpE2yXY2zXIZkg3yftC4d02Sf
+EVP/YxOmSjIC8KtpArBe+g1B9ueYkGAPF2ubVbzxBRkj0CtuEFJnvI7X0qJItZib+2VCR+n1arQx
+CoNC6ei1gzgpe+y8VLJXfBvIZHTPNe/Zh5munUKdkED7utju2S8w/eKciQxNtcS3+d/6KpHOE+ry
+OkrLapwyGs+WoYK2zMMG2IcCNOtV9ze6n314c9fXB8QhB6dyetK0WKVW17ZXlzXNfqhoNXRFNBW5
+tX+fbPJ1E04d9n+ISdCsGPeiaeqcxWJqf1j9YI17Q6jIBZXf4Uf5TFfRDrf6DeB1Q81tUA+0+NTp
+b7vU4i8ZlTBivPhCwPaNK7H5EA24xY7Hk455RaLNGuWp++lDCWNvDDXTeTdui30/LhJY44C1nEx4
+j2jqATA9gQULhCTYguwlmaj153Kg5IdMr7Cq3t7osztK9uldbz7wc3PJddMn+yy4dO4sTp87j0Z/
+7l2ulrhsud8tXQ66bFBW508s2JrP40BJFVqNIWi9Qm/R0HL820JEVhthae2G4eNHoyd1X53bthSr
+C7siffpY/DLOhObKE8gvEl7JHIwwD7mPKEjhT0fpVTBJdsiM0S8Mw57ccmQtXoHrr05ExNVjyN4h
+8IlCxuj+srLCagT6D6LErqYWGz7OwoRkupHTNWzI+AntXkF2O9F10xGM1afykEnjeKm/DMdPO3Kw
+p1KYgeDfUpa7DDmWlzHIeAVbc4tFYRmjHU+LmvWq+2tKfg6TzKXYdSof81bWYm76UIS0/Izvs7ch
+ir4wPduPL+d6JaHZD6+S7AeC4jBhagzKqN5XvJeFuVOScP2Hv2F7W16oIqD9Yda4t5+pzrm9Bg97
+mP1gjHuaN/Tiqyko21iKtQsXY9JLk9GPPlF/4+oZFO0oxZ0xC7H+ZZovQove1w0P3ins0osfu7+i
+MT0T8UwsUFBzXZxDlJw+0rULXwM/Bef8PBSKfv1p7JkmK/9l5S2MGRBGHUiPY/KkJ+jxhzEOmMvJ
+TBWzS/qca+IsLEg7h7VF5Vi6thhZi8Y5O45lpRlWlfygeyPj/c2pSMk+3euNlbPTOuUVX+yjN5Iz
+V68BvaQcsC//sycz3UOc49OungoZhudUSz4B2Fp/kj5v7TqEUX1oJ3IOCdKiaLIoJTMU85GxifS0
+UYw9X+Vhj6QoNB6z//x7nyZxdZRee0+FOpeYsfPwhiUTH1F3ccHG/3J4HI+5y15Hon1mo0RB/H38
+hdcx7cYn2H7sCLZXHrEfG/o0JTPyySoup7TfoGD83bKXUf/OZpQV5tF/oUg80tMM2FN0hiZu+76Y
+B0RR1/dm7HOImDTvPaRK3xLyQa+6vyZMX/U+IrPX0TyrUmTT6/D2JQZzI+XZL1ucOk5W/tHkB5ve
+gdMWY279h8g+dATZmUK9RuGpUTQBmF61lb62rWyU61HWuJfOUucslVT+ZfWDNe57jpyDVcEmrMnc
+iV1fbG5THhqDaU887Nxmv26w1YdTMOOKXvxY/bWbZcTwKSkoyBRiPh4TnnyknbXs8gLDhWayI2nu
+Msy4uw4FdM3aVUkmmkORQcmMsLDGAWu5IMfVq6usVztx5kJMOruIHnjy8GXZUMxOFrqKtC7KfrC2
+N1b72OuNzQ9Wfqz3Lc32Ob6kLSQzkarzG9l8ci/10KW6G39339nU7D645l4i0Ns2WCy36UuoNljv
+BcFkivCSSOltR0fppcze0kTdb9T3Rf/Ce5p8fHrQysOKxkZ7b4zR5J/Oqu1vY8UOA5Z+thRx5EvT
+PRvN+aC30IRrZLtFP71y0VZLI+gNfhho+NJIyR119AV40d8PS2Oj+GhgECbKeWQXYJd0Es/qB3vc
+E+uGJqpcA4KDDAj3CKfj2q9O2GRiWPyVFVdd1VueqkJNBVjjgLWcJuWdurC+9aY/P//tiwj3fwqJ
+UIWdNJnp1NHFjfNAwJ7MAG9mvgvpzVAPxfguToAT4AQ4AU7ASUCvZIZ9mMmpmq9wAu0J3Gu1z9Bk
+famovQS+hxPgBDgBToAT8I0A75nxjRs/y42ApaEGV24Go08CfYzP7Rjf5AQ4AU6AE+AEPBHQq2fG
+YzLjSSHfxwlwApwAJ8AJcAKcQGck8IvOaBS3iRPgBDgBToAT4AQ4AVYCPJlhJcXLcQKcACfACXAC
+nECnJMCTmU5ZLdwoToAT4AQ4AU6AE2AlwJMZVlK8HCfACXACnAAnwAl0SgI8memU1cKN4gQ4AU6A
+E+AEOAFWAv8PxvdR0yK8jugAAAAASUVORK5CYII=
+--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=--
diff --git a/spec/fixtures/git-cheat-sheet.pdf b/spec/fixtures/git-cheat-sheet.pdf
new file mode 100644
index 00000000000..da38c840fd3
--- /dev/null
+++ b/spec/fixtures/git-cheat-sheet.pdf
@@ -0,0 +1,130423 @@
+%PDF-1.5 %âãÏÓ
+1 0 obj <</Metadata 2 0 R/OCProperties<</D<</ON[5 0 R]/Order 6 0 R/RBGroups[]>>/OCGs[5 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <</Length 52318/Subtype/XML/Type/Metadata>>stream
+<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
+<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.6-c132 79.159284, 2016/04/19-13:13:40 ">
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description rdf:about=""
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:xmp="http://ns.adobe.com/xap/1.0/"
+ xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/"
+ xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/"
+ xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#"
+ xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#"
+ xmlns:illustrator="http://ns.adobe.com/illustrator/1.0/"
+ xmlns:xmpTPg="http://ns.adobe.com/xap/1.0/t/pg/"
+ xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#"
+ xmlns:xmpG="http://ns.adobe.com/xap/1.0/g/"
+ xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
+ <dc:format>application/pdf</dc:format>
+ <dc:title>
+ <rdf:Alt>
+ <rdf:li xml:lang="x-default">Untitled-2</rdf:li>
+ </rdf:Alt>
+ </dc:title>
+ <xmp:MetadataDate>2016-10-31T17:24:20Z</xmp:MetadataDate>
+ <xmp:ModifyDate>2016-10-31T17:24:20Z</xmp:ModifyDate>
+ <xmp:CreateDate>2016-10-31T17:24:20Z</xmp:CreateDate>
+ <xmp:CreatorTool>Adobe Illustrator CC 2015.3 (Macintosh)</xmp:CreatorTool>
+ <xmp:Thumbnails>
+ <rdf:Alt>
+ <rdf:li rdf:parseType="Resource">
+ <xmpGImg:width>256</xmpGImg:width>
+ <xmpGImg:height>92</xmpGImg:height>
+ <xmpGImg:format>JPEG</xmpGImg:format>
+ <xmpGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA&#xA;AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK&#xA;DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f&#xA;Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAXAEAAwER&#xA;AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA&#xA;AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB&#xA;UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE&#xA;1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ&#xA;qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy&#xA;obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp&#xA;0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo&#xA;+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8AgedEzdirsVdirsVdirsV&#xA;dirsVdirsVdirsVdir07/nHj/lPn/wCYGb/iceYmt+j4oL6XzUMXYq+aP+ch/wDlPk/5gYf+JyZt&#xA;9F9HxZB5jmWl2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2Kpr5b0qTU9RMMfAmONpeD9GpQUHv8Vc1H&#xA;berODTmQuyQLHT8U7PsnFCecce8RvSaab5Qnnu54AymgKVcfZB/arQ9Bml1XtF6ImIINgnz8vi7n&#xA;F2LDFxGZ4oyiRHvF9feFfSvy+F9ollqbah6P1u4a3ZBEHSPixTeQSCrkivAL0INd86o596p5M7FV&#xA;sPys1q9kISQRIxRIGljkQyNJbmdWC0P7v4Speu3U4y1ACsLYFWINKg02II+8ZerWKuxVug8cVb4j&#xA;FWuPviq6ib1Py/zpiq0ih9uxxVxBBoRQ+BxVxBHUUxV6b/zjx/ynz/8AMDN/xOPMTW/R8UF9L5qG&#xA;LsVfNH/OQ/8Aynyf8wMP/E5M2+i+j4sgxyXR/LqQS3q3gNm0PGJ6AsZKUCiP7XMbV+/Ocx6zXHIM&#xA;Rj6hKz/Vv+dy4e75eT088WjGI5R1jw150N658Silj5DeK3/3I3cUjLH9ZZ4wQrHj6nBVVuVPipVh&#xA;2zqbn3PMpJqSael9KunSPLZg/uZJQFcigrUDwO1e/gOmWRut1Qwwqu+Gm9MVbFO3H5HFW/TiqKyA&#xA;VPuaD6MValRUYBWDAiuxr/TFUXoTaYuqRHUwrWdJA3PnwDmNhEX9P4+Ik4luO9MjO62VP7688kPd&#xA;28NnbxparJKWndJxt9UjEPqDk7cPrRcuFq3Ed9q1gTrf8b/qVXSb8u5JJU4CGNjCDKwnPwCOL1vR&#xA;ULIQ/IScQ7Ur+0Bgqaof655Jk1tK2yR6SIpmoROHDyOzRo/FizGOOiihAJ/aH2ganXmqOt7r8ufR&#xA;taQRq4a8+si4NySeQk+q0McTjiDwr3G2zb5Eif3KxXXbnT7i9R7CGOCBYIFZYg4Uy+kpmPxkn+9L&#xA;U9sugCBuqBillhkWWJzHIhqjqSCCO4IxnASBjIWCmMiDY5ppfeaNVu7YwO4jEn+9Lxji0ppT46dq&#xA;dhtmr0vYunw5OOIs9L34fd+tzs/aWXLAQJ2H2pro3lbQrvSrW9utTSKSZ40lhEkauvqXQgPwsP2I&#xA;/wB6T4H9nqdhLIQaAcBrRvLGg6jbwTT6ktiJipZ5ZIyqcroQ+kyr+85rF+85cOO4rxG+MshHS1Vp&#xA;PKXl+KJ5W1NX4N8MKSoGaNYebSVZBT94yIFAP7XxGmDxJdyrbXyhoM2lWN3LrEdvPccfVgd0J3SR&#xA;zxC8uNCij4jT3DfDhOQ2RSqWq+W9CsbKSZLwXEot5ZUSOYH94l2LdEIaFK1jb1dt6A7AUOMZknl+&#xA;KVi1R4ZcrYYeH+f34q7kPD9eKt81I3Ar47n+OKr1liAoyBh/LuPxrirvrPx8zGvI03q1dvA1wUrc&#xA;0sTpsDz2oTXYb16s3iMVej/848f8p8//ADAzf8TjzF1v0fFBfS+ahi7FUDe6BoV/N699p1rdTUC+&#xA;rPDHI3EdByZSab5ITkORV4ALzzoQCLbyoQQSDXStwFVift/yup+RGbDxMX86X2skXpcXn6/umig0&#xA;3y5dLbsgvFtU0uWSNWJG6h9ieLU5eGJyYv50vtVlsOg6iLI+tocRvuDcSlpooiL78agyFuPSuVHJ&#xA;G+e3vktqiaFdFk56CiqVPOltohIaq8QPiFRx5V6dsHiD+d/ulSvzRZ6vpuiRT22m6Ja3El9JHG2p&#xA;RaZCWtvTT0wfi9LnzLbK3hkoZIXuTy81tKtJ0/8AMK9QXP6H0G4sXST0prSHTJAzqCFAblx48xRj&#xA;23yZyYukj9qspm0C4ED+joqtcUPp87PRFStDTlSVj1plQyDv+2S26bQbmi+joaE8zy52miD93xNK&#xA;Uc/Fyp9GIyDv+2S2irLy8X1G1Q6HCbdnT12uLTSFXjy+PaB3k+z0p3wHIK5/bJbYnN5Y/N/1X9Py&#xA;3ofp8jw/0aw+zXbvl/iYv50vtW0+g8seZKf6R5cgr6nWO10enp8W7FvtcuH0V9sqOSP87/dLarB5&#xA;X1v1AJ/L0fpfHVo7TRuX2/g2L/ydd+uJyR7/ALZLaAnXS47n0zb2USRLItwkkXl/1FlHHiKeuKAf&#xA;Fyrv0yQvz/2Sst8peV7Cexnl1bRbBg8wawkNrZcntzDGQx+r+pHvKXpRvs0yjLkIOxP2oJSb8wfJ&#xA;2m6To0Nz5X8oabqOoPcrHLBLbc1EJRyz0RojUMqjr3yeHKZH1SICh5/9X88f+W20f/pCf/sozKuH&#xA;88/P9iUXpun+Z57gJf8AkHSbODkoaVNNkmIUmjEKLpKkeFcjKUekz8/2KnMOgIyVl8s2MblmHEaA&#xA;7AKCeLE/pAdcgZ/0v9l+xWpNAYep6XlfT5WUViU6HJGHNDRSxvm4VNBWh648f9I/6b9ipf5m0vzH&#xA;Za9e2ukfl9pN1pkMpW1uHs2ZnTsSVmQfhkscomIJmb96pZ9X88f+W20f/pCf/soydw/nn5/sVOLL&#xA;RtSktfVvPJ+mW8/EEW8ejyy/ETQjkbyMbda5WZi9pH/TfsVEjQjzUf4WsQhZgzfoF6hQGIan6Q3q&#xA;QopXv7YOP+l/sv2Kp65pq6b5fuL6LyppE12t1FDb/WbA2avG0cjyH03uZCSvAb8/HbGMwTRka9/7&#xA;FYedf1QR+ofJnloR/wA/pLx6V6/WvAZbcP55+f7FRFnq2oTTIs/lDy5BFKsnpyi39QF0X4VAF1Ug&#xA;yFVYj7Neh6YCYfzz8/2Knkdz5WeBJ/qOh+jKwjhlGkgo8oJDorfpKhKkEZXx/wBI/wCm/Yqx5dJS&#xA;ykuG0fQqqjtHTSz6TFR8I9Rr9aVagJ47YeMfzj/pv2K9l0ryf5W0i6N3pelW1nclShmhjVG4mhIq&#xA;O22YUsspCiWKcZWrsVdirwjXNAul1e5FzaTiV5nLx2K601rG7woQ8DwWUyceZoQrUH30KUvt7bVb&#xA;azeW2h1WG+mZPVAi8wJVeG5Yrp55EMx/aoN+Na7lUfI2rvqKpO+txaYgUO8K+YGmKghSy8bFQZK7&#xA;0O3vT4iFTuKPQlLK195sJmcKeVrrJ4ANUUK2tAO1a1od/EKGQ39xd2nkvT7jTrA6vbpIPUj1a2vZ&#xA;rwKX2ZoEt5Lgup/mj6AGvfFUpg86+YYI0jh0CKGECfkiaTrqqJOTNGQFsPsvyVmNP5u+KoOT86NP&#xA;0rUI7fzK+n6cio0t4rWmqxzJGwb0nEc9pHszLT4qe2NKiX/5yD/KgMETVIpJCQBGtpdBtzQfaiX5&#xA;40qF8i+dPy71XzvFb6J5l1DUNRufVeOwne7Nsw4NI3FJ4lVeAU8dx9OKo/zBpVxZeckuW1PldSM1&#xA;/FblY4UEUbqqK0srxxBq+FSaE065mQlcOXkyZnovm6y1O8hsDE0F/La/XPT5Ryx8FZEcLLEzKSrS&#xA;LsaHvTMaWIgWilC/8+aDa313YSB5JbMhLgfulWrKG4r6rxl9m/ZB8MlHDIgFaebaF5D1DW3m+oam&#xA;sENtN9Xu0kDerFQ81UBB6cv7p1NQ4FajsDmVLMI8wm3r2gaSNI0e2071jcG3UhpmHEuxYsxpU03P&#xA;jmDOXEbYoPzdprahpscK6PY63SUMbTUnEcK/A6+oCYbj4qtx+z9kt/qmKvIPMcOm3bahbw+ULTT5&#xA;7W4YTT2GnzXAuHWQq/rPcaDdoVX7YeIPU0+LcVKpK+nB40ki0+QvGIx8OlAgFCQFc/4UYoEptsKe&#xA;2Kr7eKe0vFubGykVopne0uzpwhuatUNKgj8rfCSo5Eqx8K4VZr5Z1jUZL60j1XV9aju3uljWyk04&#xA;m2kBI4pJPJomnsgb9rcUH7XfAqP88eRNQ1vU5JbXQtIQ81Mt88tn61ynKtJhdaVqFOA3AU/tHfFU&#xA;j0u81yyefS9V1DWdNWz4wWn6OsEvYeK/DxEi6BBAoQBQOBdd+u2Ko+TV0NJh5i8zrD8VVXQq+4rX&#xA;RyQBy/V71VWpqqLGS3mbzS2+/LQ0DCgpTiNGB3+WKqPmvTYfMXkE2v6Uv7tl1OKRJtSs47SfkkLM&#xA;I442OgLQjdX5HfxA+FVhWh/lj5ZgnuJfMGk3moUVPQNm9nZRKIgrSQy+tq96snIso/Z35bnqDap/&#xA;pn5d/k/canwm0e905VgDstzqFm1uWJEKqyw3U5aQ8OVaUruTypgtUw/5UV+S6IFKXIWImgbUHIUk&#xA;VOxelaLX/M42qvB+Sf5PSTJbxxSzzN6hWL62HY8l9MlVrUce3HoaeAxtL2HAh2KuxV2KvHdd0nyH&#xA;Jcwg6Je+X+cUipBFpejUcJGtTS6guX+MBYuoX4QNhuSqNMUsnl9X0DzfdW10I1FpaXiaMsMVCP3U&#xA;gt7NuIRPh4r7YqkjW35ncyq+eLLlRgB/oH2qgrVfqJP2evxYpWJb/mkIiW882BdWpJtY0ANK7/Ut&#xA;iN6AjwxVl8cepN5O01dYudT1TUBcP6l55ecKXImNOZhW1T01X4DVex3J3xQhr63c6XCtvD5u9ZQ4&#xA;i/enmH9STi059SrKp9zVOPXFUiu/J35lW0T3VxrqQASIfXmvtSVFBYqF3dVHIuB89sbSm4178wVY&#xA;iXVPLqgDl/eXNQBQt1cdjWvyxVNPLer+cJ9es7fUL3RpbRg5nis5Z2uDRW4mNXJWlePKvauKGVar&#xA;omiaqySXtr6s0SlY5CsqkAnoSnAkV7VycZyjyVj2gaBdWDJepCtprJgmgiSVZJIQryIxDBZJOnpI&#xA;w4v/ADA9qWZJg+5JR19odnqFnKKSQ6veRuHvIVmiSOZAIzMIeciVRqEKeXIjc98iJke5VtnbapoC&#xA;tMFjvLaWQPdRWVlcfWGPEIGMk13KTxoo+ydh26gkiX9v7FT3SdT/AEjbNP8AVZ7Ti5T07lPTc0AP&#xA;IDfbfKpRooY/+Zmt+U9H0GC58z6c2p6e90sUcCRxykStFIQ3GRoxTgrKd++Tw4jM0FDzN/zI/Ih2&#xA;kZvJ7kzNzm/0GzAdg3Lk49ajGvc5kfkZ94TSIPmT8pdcsmj0jy+ml3Z4Rw6g1npCtEIHSQKFuZeF&#xA;CKBaj3G67RlpJjr9/wCpaVY9Rh0vT47bT9cnsrOKqR29pD5eVUPEyMRGs3EcjVthux8TkRpyfwf1&#xA;JpGReaTZ3Md5c69e3NpAY5ZrbhobLKnQopgn9T4qfskkVxGml+L/AFLSH/M/ynLHql5rM+n2slvd&#xA;TwrbN6FpcuXCsaFF0PU7hd058ndviOxGwzHDFh1zYaK9k1xHatNfMT+kA+kQbAtsoY+Wecpb4SQU&#xA;X59yVZpaazo8EEdpZeZ9fggtkWKGCPRYUiWNSI1VFGjqvFduPHantgVVHmLT/TD/AOLPMRUP9oaP&#xA;HU96UGj9Nuo+/FUJ5uuvLmo/l4zapLrvmOxTVYwD9USzvEcQMQvpmytVaLqORj3LU5dsQrzaO08k&#xA;RwzKfKHmQxxyEyoTBJIXBJDhfqxqaAitenjhSmehp+X+nXrahB5K13UWgVDNYX8EE0Mvq8Y6uhgo&#xA;xRpCakj4h74qn8nn78v1VWl/KUlpfiqNMt3AYV5F6Q8tj3oa9saQibX8yPKVleLcW35VywXFrIzw&#xA;3Ftp8QeOQBWd1cQrxJkk4hgd9ySMFK95wK7FXYq7FXz/AOYvMHlvVLyzWw8yPrvoBnYajCEkVUQc&#xA;lAGh33OPghZt13+LwIyfyuQdPu/Wmk5S5DFZG8oaU8n2kItNVGw+JyG/Qrd9/p9t4eDLy+Y/Wrf1&#xA;qMstfJulcAfSX/RtVJ5V3Qf7gx49MfBl5fMfrVtpQrIqeS9L/lCG11UGnGhVf9wZ6Db5D7h4R8vm&#xA;P1qiPMHmLXrDyhp50C90zyrcRXcsF9bTlLWBSQrokY1G1s2qwkVzSIfa6nrlmKMIn1/j5KxRvPP5&#xA;oojSP550FUVzGzm70oAOOqk8Ovtl96fu+9dkwtPOOp3tnPaeZPNmmahGq1ubeG+0L0gUk6yJNbzb&#xA;K3HqNmyuRxdB9/612RGm6ZZa2Gm0b6lqccLenPJbP5duOKcCY0LR2LcTyNd+1cF4/L/ZfrXZkPl/&#xA;yvqdnrVhdRWaQyxSr605j0gUjIKOFNtZwzAmM8fhcfdtkZHHR/b+tXouqTXUOnXEtqjSXCIWiRQG&#xA;YkeCkivyyiIF7oYNbz+cdfkbSdYtJ7Ozm3W9jg9MxslXWQMz/CwZRTr92ZE4wAsHdKLk8p+QNNu4&#xA;YLq/itbmPi8UJmt7Sb4vhVleFYZxUr1VhWmR8Schy+9bS6P8wZLU3t39QDTrK0dta3GrRhpI6rQ+&#xA;mxaKJh4PxYd9ya2HBdC/sTTP9Jvv0hpVnf8ApmH63BFP6RIYp6qB+PJdjStKjMWQokMWO/mbqdjp&#xA;nlsXt7PfW8Mc6qG01bZpmaRHQLS7DRU+Ku/cDAFeAj81vMckdVttRSd3L0W+0srQ0PFVbTHoqsvw&#xA;+zbk5KyqY6R+c/mGCWV20CbUfUarQXd9ZKIIkrvG0Nlb9eVKtyrQbim7Z71R5/PzUeE1fJ0cckXV&#xA;WvomHwmjD4IWJY0Ow6dyemNnvSm/lD839Q1vzDpul3PleO1iv5vSN2LqNuA6giP0uTHf8Ovg2e9W&#xA;U+dNM8r3GqPING1FNTgnhnn1C001roTBHLBAzKyN8W5I3GRQwXQdE/NPSWvNP0WWz0vT4bkusl7C&#xA;1sk4BK8t7DhydI1rxY7DbClP/wBG/ngyFk1XSynMEN6g6cR8Ff0fTf7Xjv4YNlbfSPzxiKt+l9OY&#xA;KfjErKoNAxP2dPBFVo3Xanhjsqtr2n+bY/y7Ca/qmkfpVdQ9Vb7UhavZiEQuKKZ7WKMPTlv6daV+&#xA;Km2W4ZRErkrA49O1oSGFPMHk0yqfTMfDSSwJ+HjT6tWvXbM38xj/AKXzP602zzy55W8/aRG7R3Vn&#xA;aXEyqsx06LTbVWKuxqSLBiw4EUB6Gu++1M8uOX7b/WhkCQee+fx6vdFO4Eumg0p4/o898r4sfd9/&#xA;61Up7f8AMU2kwt9YmW7Ik9B5JNOaMGp9LmosFZhSnKjD2xEsd8vv/Wr0PMZDsVdirsVeJalpug6b&#xA;DBc2N75av7l5PTS2sLO0juJAyIf3TXWp28dQGqfiPwuPh75d48+8ptT0fzNpduZZNW02ymjkI9EW&#xA;zaNZiMoP3jOz61c+pVZEHw0409xg8WXetskhntJ4Uli8kXcluwEsMqSaOyMGHIMhXUTWtdjg8WXe&#xA;tuX6uCgHkG9XckfFo9AevbUcPiy71tMNasJpPKCJY6HdwPPK01xBa366dcWzBOHqyy2twFk4rvwE&#xA;pBoPDaBkTzQ8Lk1a9IedPO96xqwEQ1lVBFD8dPru2/QbHptilM9NudNuYrgah+ZV3pjRSA25bVZZ&#xA;C8KrTkOF2djt9qreO++KExaPRFjEkn5szhCjK4N5cqXG7niBdhg3E7cN6Upilk35c2umR+bbR7b8&#xA;wJ/MDgNx0uS7mmVxJCzgsrzyqSq/EPh7eOAoZ9qXnDUodSaztNFupoNlGomC5MaMdiWjEIZgp3+A&#xA;/EOh8LY4gRdhNIGDytrlk1uLGeadBamGedp47P1TJGAeSi3lmSjKGDci6+P2uUjkBG/P8ea2g7Hz&#xA;Jrk5sbWGMypDfCGaLjLPzj9c27GS5kYl/S5eqaKPsUqBXJGEefkqdaz5e1mfy+tnatbi9W7+t/u0&#xA;9KLkZjcc+LGQFxN+8B/m3675XCUeLfkqd6HBqEGlW0Woyepeqv79+RcFq/zHK5kE7ckJN+YOuWOj&#xA;aLDdXusXOiRPcLEt3aQxzuzNHIeBWWKdaUUtXj1A7VBljxmZoK8gvvzY1MXc6WXmmV7IyMYZpZIk&#xA;m9PfiPTGhui9ehdv9brW/wDJ5O5NIjSfzp1a2Mhnv4NSeZIVihuruZfTdQwcq1tosNTIeJNaiv2e&#xA;I2I/J5O5aZda/mB54uU9SLy+rR8nQMs2pMOUZKkbaVT7S0/zplZwkdR8wtICPV7aTzNFrWveULO3&#xA;uLb45tdEFzPewelHswaXTYG4qXVamUUBr7Y+Ae8fNaRHnfzBqtnrt9Hp/mu0s7aKISXEFzqtvaSw&#xA;FS7PxgfStQPHiuxMldtgN8qQstrzzH5p0WKOTTfLfmPTrdkVJLrVp7oGaNeLO9dI4CXg5rRRSp27&#xA;YqsPkiZ6rJ5F8ntDQUT6wx7VpvpFPtE9sVQOqaBqlq0Yh/LPy1fuqmQSQXcXBWDEhQZdNiblWjV4&#xA;0xVO7K0EfkS+jmsdM/L4zXlXUTmOF1jQOkpmsX0t1duHxAPuilTVTiqR/o+wadoYvzF0lpIixeP9&#xA;JauXRIwSeQGuVPED4q07nFUXbNo02oSWVmdU12/tYoZbiXS/MTehIWRZfUjgl1hZkj5txAkUV/yl&#xA;3xVX/RxO58u+ahSo/wCO+f2jQ7DWd+lf1Yqr2OmNHe2oGgeZI1+sJIZ59cEsMZ5A85UOryl41pUo&#xA;Eav8prir1PArsVdirsVeA+avNOozXMdobaBPqlxJ6N1pUFxEJHEKiN0lhuEDIeQff9mnSnLJJSzS&#xA;9Y0VxN+nYdRf1aywmya4QBaK78/UuJO6pTj8j1xVk0d9prxqILHzc0Kf3TRyXQjKqoZShEwDKwPw&#xA;02OBVRr+0KN/oHnAAIAKPdVIBUbfvup7nr1OKsm/x9YeWtI0uKa0vZlvFkMP1uQLcrxZiRObhg1a&#xA;DarHbLsWEzWkfpX5k2+ppE8GnTLHLJLGJJGQIDC5RyziqgVHWuGWnrqtJnqV5bahaS2Go2Ftc2s6&#xA;/vraa4hZHVSD8StsR0yvg/FISNvKn5fgFW8n6EAoqQYrDYHf+TvjwKmeieWfLdtenU9L8t6ZYX0V&#xA;YhdQJDHJRlBNHhi7g06+2AgBWKW35xeZp7qSA+S7iBY+RE0006o3E0242jbntmUdLGvq/HzTSM17&#xA;zXrd/pvpnTUT4uYS0vb2OYlQaLybTuABPi1MjDEAef2D/ilpfovmfWNMsI7OHToZI6syme7vmdeX&#xA;xEEjTB+1+PtjPGCbv7B/xSohvzD18NGBoluecrRf703vwhQx9Rj+jqcDx277jbI+BHv+79a0yPyv&#xA;rt5rFtdy3Vl9Se2uTbpxeR0lURxyeojSxW78ayFfsdRlWSAieaGI/n3fyWHkiK7js1v3jvYwLZo4&#xA;pK8opVLD1op1XgG5149vCoIhIg7FWJ6D5KurrV4ZNS0U2tm9JJY/qWivaAU5emssUklyQfs8uHXf&#xA;YZPx595TbN/8EeTf+rHYf9I8X/NODx595VWHlPywOmk2g3r/AHKdfuweNPvK22vlPyvy/wCOTabk&#xA;V/cx7/hj40+8raU+er6zupL/AE27876XpEUZRzA4mt7uBgxK/v7W+s5d+NKDrvWvTIIVNP8AJfkX&#xA;VLWSSy1u8v4iTBcy2ut6s8ZkU1dW4XjUYFtwTXfAqhq/lDTLKaNLW28wapDMHMr2mu3yCNif2kud&#xA;St615E1WuKpauhwL6qJ5d81Kk1WNNeZakksems/DU/y+OFU3ZY9M8iau82mapDbrKzSJqGr+pchF&#xA;QcZY7ua6vPSVmAXj6g77b7qvPZ/PnlD64YDeaoRHIsfI+YkEZVeVHryIDKVGzEHeu5GGkplpnmX8&#xA;ub2znM3mO90iaItHCH1p5AUHCk37tgoBc7qGFab4FS9pNJc/vPzVkoTUcJp0pzAaikXPcL8INfbq&#xA;cKpp5auNFfXNNMP5iNqZ9eF4rAzzfvxI4KwvyuGBLl1WjL7UwK91wIdirsVdirzDVbDU9Ikt5rry&#xA;noUyv6p52Nhd3jqwiWm1vayFOT9z+yKCpwq87n8o6g7zyQ2EkIcFz/uJ1NqepIrHiraU/wAXEd69&#xA;BXClk+hR3dvpwg1C68xpJbsDFBYadqPo+kCAsYMunxkcaU4rRePTvgVNpfqcvOU6r5qACxq0a6Xq&#xA;CV4KE+EDTlNW4gsR332qaqGvM3krWPMlroTaXPPIun/vJ5r0yWN46OXX4leBGVjxIPKIbZlafKIA&#xA;31SCq6Z+XGtw2Ho3EcSyetcSji/qALNM0gHLlDUhSP2euSlnjabRn+AdVFSFQmROEpapNaEAqfWF&#xA;Ou+Dxwtpbcw6N5d1OH/EnqLEKMgEMrpKUowXmWkjYLQVXJAmY9Ksj0T8xvJMkrWljLIrSuzQWkNr&#xA;OzUSMV4xxRtX7BNFynJhmBZRSYaFrnmjU9EstRWwsXF1Cspb63NEPiFT8H1eXjvX9o5GcIiRFn5f&#xA;tVCXy+a79r11i+oMbZY7WeymacErIrlv3sdtuQGWgB2777GPCPmqEsdP/MCyE076jLdzLQrbSwxt&#xA;EyMaUDCTkrildgae+SkYGtqVkuq6tq0CRnStKbU3JImQzR2xjoKivq7mvsMqjEdTSozT9RhvoXki&#xA;WRDFI8MqSo0bB424sPiAqPBhsRuDkCKQwz86V8xv5Qji0C0lvLqS7iWaOGN5WEIR2LcEDVHIKNwc&#xA;QrzXSPL/AOf2r2Mtwtx9TLK8YjuDPaOHI5AiOQhlAErKCu2y/wAu52SmD+U/+chTcSulxaiFm5CB&#xA;rpyN52lAV1IZfh4oe1OgwbK6Tyh/zkGwHG9t1DxxRsBck8CjqWcV4lmKp4gGprjsqK0Hyl+ecfmf&#xA;TptUvUOkRXET3SrcK1YUcB0YGvqF4+9BvXpjsr0PzDoHnTU0vLa11ixtLK5BSMfU7tbhAT/y0W99&#xA;bOGp3Tif1YEMWl/Lq80xQLhNZ19pS/ptpur6jaiFI1HBZRe6wOTMT8LR7VFSF2OFUJc+XZFiUSeW&#xA;PODjkoTjr7u3KnIH4daNOJNKnb8MVXHy08UI4eWfNzx1UIo19yRtRSA2sgr9r2p1NKVxVkWnaNr/&#xA;APhnUItGj1TQ9Ua4MkSapfR3Ukh4AErPM2tpHFQ1VVX7S/ZArUKlf6J/OgCZRe1aRWEbtqNmRGxN&#xA;QwA0RSaDYcq+/jhVMdMX82rOFYrm1tNS5MGNxc6oElQMBVeNvpcEbBd6GlTiqtdan+aFvZzXP6As&#xA;pTCjuYItUleRuHI0RRYfEWoOI679MVYfpk91feadNmn/AC2t7W5nuEnn1t4JRLbyvJyeX1G09GLg&#xA;sW5cwCerDrir2fArsVdirsVS7VNNZ9OuF02G2jvyhFs8sYKB+xYAHJxlvvyV5RbXX5rCVo7nTnZe&#xA;QHqNZxKqb0r+5iLMN+wOZpGLv+1ls3cnWXsJ5b9bpEiDl2igvo02FOLN6UdCW/2I/DCKvb9CpJGn&#xA;p3kR0lLs3fJmVLGSO9LAUr6iJLP08CN8s6b/AKkvQfKtp+ZD3tvcXc0cGkSqDcwXEMMNwRuDRYEV&#xA;lbw5N/TMTIcdbc2JpNU0TztFcJEmqQyWS8VNxMZWuCoABZlUpHyPXamQE4Vy3VkkFoVhjWWR5JVU&#xA;CSQM6hmA3YLyNKntXKSUL/q0fi//ACMf/mrG1Y/rvl/V2vFv9EFgLugVmvUn9ToQXE8UnL7NAF4/&#xA;TlsMgqpWm0qS21rR7GNNRtrjUZioiSw0p5xaxRqSOQY0YuQR8LGm22TsSOxr30qiPNGpX7y2Gl6T&#xA;fJqDQOsD3lzNDFzRSalgG+Pw6AnaoG+E4wNyRS0ym70e7nsCLe8mtL1kX4vVkdA6g9ix2JO9D2yk&#xA;TAPLZDHGtvM9netdamNQubSAkhdN4lpafCqspnaQoeXKiqDUdRuDbcSKFfH+xLJfL0U6w3U8ttJa&#xA;/Wrhpo4ZuJlCFEQFyry7nhXc1HSmUzPJD490nWL/AEm4a4sjEJXQxN60MNwvFiCfgmSRe3Wlc3so&#xA;iXNmmI876+IDCfqbIS5+KwsWI9RmdqEw1A5OT7dsj4UfP5lWx568wiN4x9SCyVD006wBNdzuIK4P&#xA;Bj5/Mqtt/O2vW8EUEX1MJDGsSFtPsXcogoOTvCzMadyanvhOKJ7/AJlV0/nnzBMgRxZBQhjXjp9i&#xA;rKrCh4sIOSn3BriMUfP5lWP5YrsVdirsVdirsVdirsVRFlePaTiZI4pSBThPGsqf8C4IwEWr0b/n&#xA;Hj/lPn/5gZv+Jx5i636PigvpfNQxdir5o/5yH/5T5P8AmBh/4nJm30X0fFkGHv5212ScTSLYu3D0&#xA;iradYFChKndPQ4k/AtDSoy/wh5/MpWr5w1dZPUWDTg3Uf7i9OoOnQfV6fs4+EPP5n9auXzlrS3M9&#xA;xwsTLcBPV5adYMtYyxVghg4K3xmrAVPfoMfCHn8yqp/jnXeMg9PT/wB7/ef7jNO3+f7jB4MfP5n9&#xA;apRf39xfXBuJ1iVyAvGCGK3jAHhHCsaD6BlgFKhsKuxV2KuxV2KuxV2KuxV2Ksq/5Bb/ANrz/p0y&#xA;n95/R+1Xf8gt/wC15/06Y/vP6P2q7/kFv/a8/wCnTH95/R+1Xf8AILf+15/06Y/vP6P2q7/kFv8A&#xA;2vP+nTH95/R+1Xf8gt/7Xn/Tpj+8/o/arv8AkFv/AGvP+nTH95/R+1Xf8gt/7Xn/AE6Y/vP6P2q7&#xA;/kFv/a8/6dMf3n9H7Vd/yC3/ALXn/Tpj+8/o/arv+QW/9rz/AKdMf3n9H7Vd/wAgt/7Xn/Tpj+8/&#xA;o/arv+QW/wDa8/6dMf3n9H7Vd/yC3/tef9OmP7z+j9qvQPyR/wAE/wCM3/Qv6S+ufVJa/XPQ9Lhy&#xA;Sv8Ad/FXpmNq+Pg3pBe95rGLsVeHfnL/AMq1/wAXr/iP9M/pD6rFT9HfVfR9Pk/H+++LlWtc2Ol8&#xA;Tg9PDXnbIMF/5Af/AN/N/wBy/Mn99/R+1d3f8gP/AO/m/wC5fj++/o/au7v+QH/9/N/3L8f339H7&#xA;V3d/yA//AL+b/uX4/vv6P2ru7/kB/wD383/cvx/ff0ftXd3/ACA//v5v+5fj++/o/au7v+QH/wDf&#xA;zf8Acvx/ff0ftXd3/ID/APv5v+5fj++/o/au7v8AkB//AH83/cvx/ff0ftXd3/ID/wDv5v8AuX4/&#xA;vv6P2ru7/kB//fzf9y/H99/R+1d3f8gP/wC/m/7l+P77+j9q7u/5Af8A9/N/3L8f339H7V3d/wAg&#xA;P/7+b/uX4/vv6P2ru//Z</xmpGImg:image>
+ </rdf:li>
+ </rdf:Alt>
+ </xmp:Thumbnails>
+ <xmpMM:InstanceID>uuid:9ceda8ff-23f0-3d4d-bee2-d129ed5be150</xmpMM:InstanceID>
+ <xmpMM:DocumentID>xmp.did:6e0ad609-63ba-4487-8c26-1d3d45c1e92e</xmpMM:DocumentID>
+ <xmpMM:OriginalDocumentID>uuid:5D20892493BFDB11914A8590D31508C8</xmpMM:OriginalDocumentID>
+ <xmpMM:RenditionClass>proof:pdf</xmpMM:RenditionClass>
+ <xmpMM:DerivedFrom rdf:parseType="Resource">
+ <stRef:instanceID>uuid:1429a63f-381b-4bbe-b610-dcd92ca51b5b</stRef:instanceID>
+ <stRef:documentID>xmp.did:d92220c8-81e6-9646-85ef-ad1bfcf188fa</stRef:documentID>
+ <stRef:originalDocumentID>uuid:5D20892493BFDB11914A8590D31508C8</stRef:originalDocumentID>
+ <stRef:renditionClass>proof:pdf</stRef:renditionClass>
+ </xmpMM:DerivedFrom>
+ <xmpMM:History>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <stEvt:action>saved</stEvt:action>
+ <stEvt:instanceID>xmp.iid:6e0ad609-63ba-4487-8c26-1d3d45c1e92e</stEvt:instanceID>
+ <stEvt:when>2016-10-31T17:23:56Z</stEvt:when>
+ <stEvt:softwareAgent>Adobe Illustrator CC 2015.3 (Macintosh)</stEvt:softwareAgent>
+ <stEvt:changed>/</stEvt:changed>
+ </rdf:li>
+ </rdf:Seq>
+ </xmpMM:History>
+ <illustrator:StartupProfile>Print</illustrator:StartupProfile>
+ <xmpTPg:HasVisibleOverprint>False</xmpTPg:HasVisibleOverprint>
+ <xmpTPg:HasVisibleTransparency>True</xmpTPg:HasVisibleTransparency>
+ <xmpTPg:NPages>1</xmpTPg:NPages>
+ <xmpTPg:MaxPageSize rdf:parseType="Resource">
+ <stDim:w>11.000000</stDim:w>
+ <stDim:h>8.500000</stDim:h>
+ <stDim:unit>Inches</stDim:unit>
+ </xmpTPg:MaxPageSize>
+ <xmpTPg:PlateNames>
+ <rdf:Seq>
+ <rdf:li>Cyan</rdf:li>
+ <rdf:li>Magenta</rdf:li>
+ <rdf:li>Yellow</rdf:li>
+ <rdf:li>Black</rdf:li>
+ </rdf:Seq>
+ </xmpTPg:PlateNames>
+ <xmpTPg:SwatchGroups>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:groupName>Default Swatch Group</xmpG:groupName>
+ <xmpG:groupType>0</xmpG:groupType>
+ <xmpG:Colorants>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>White</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>Black</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>100.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>CMYK Red</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>CMYK Yellow</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>CMYK Green</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>100.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>CMYK Cyan</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>100.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>CMYK Blue</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>100.000000</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>CMYK Magenta</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=15 M=100 Y=90 K=10</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>15.000000</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>90.000000</xmpG:yellow>
+ <xmpG:black>10.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=90 Y=85 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>90.000000</xmpG:magenta>
+ <xmpG:yellow>85.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=80 Y=95 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>80.000000</xmpG:magenta>
+ <xmpG:yellow>95.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=50 Y=100 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>50.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=35 Y=85 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>35.000000</xmpG:magenta>
+ <xmpG:yellow>85.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=5 M=0 Y=90 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>5.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>90.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=20 M=0 Y=100 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>20.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=50 M=0 Y=100 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>50.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=75 M=0 Y=100 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>75.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=85 M=10 Y=100 K=10</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>85.000000</xmpG:cyan>
+ <xmpG:magenta>10.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>10.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=90 M=30 Y=95 K=30</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>90.000000</xmpG:cyan>
+ <xmpG:magenta>30.000000</xmpG:magenta>
+ <xmpG:yellow>95.000000</xmpG:yellow>
+ <xmpG:black>30.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=75 M=0 Y=75 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>75.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>75.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=80 M=10 Y=45 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>80.000000</xmpG:cyan>
+ <xmpG:magenta>10.000000</xmpG:magenta>
+ <xmpG:yellow>45.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=70 M=15 Y=0 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>70.000000</xmpG:cyan>
+ <xmpG:magenta>15.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=85 M=50 Y=0 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>85.000000</xmpG:cyan>
+ <xmpG:magenta>50.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=100 M=95 Y=5 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>100.000000</xmpG:cyan>
+ <xmpG:magenta>95.000000</xmpG:magenta>
+ <xmpG:yellow>5.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=100 M=100 Y=25 K=25</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>100.000000</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>25.000000</xmpG:yellow>
+ <xmpG:black>25.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=75 M=100 Y=0 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>75.000000</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=50 M=100 Y=0 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>50.000000</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=35 M=100 Y=35 K=10</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>35.000000</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>35.000000</xmpG:yellow>
+ <xmpG:black>10.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=10 M=100 Y=50 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>10.000000</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>50.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=95 Y=20 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>95.000000</xmpG:magenta>
+ <xmpG:yellow>20.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=25 M=25 Y=40 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>25.000000</xmpG:cyan>
+ <xmpG:magenta>25.000000</xmpG:magenta>
+ <xmpG:yellow>40.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=40 M=45 Y=50 K=5</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>40.000000</xmpG:cyan>
+ <xmpG:magenta>45.000000</xmpG:magenta>
+ <xmpG:yellow>50.000000</xmpG:yellow>
+ <xmpG:black>5.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=50 M=50 Y=60 K=25</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>50.000000</xmpG:cyan>
+ <xmpG:magenta>50.000000</xmpG:magenta>
+ <xmpG:yellow>60.000000</xmpG:yellow>
+ <xmpG:black>25.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=55 M=60 Y=65 K=40</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>55.000000</xmpG:cyan>
+ <xmpG:magenta>60.000000</xmpG:magenta>
+ <xmpG:yellow>65.000000</xmpG:yellow>
+ <xmpG:black>40.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=25 M=40 Y=65 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>25.000000</xmpG:cyan>
+ <xmpG:magenta>40.000000</xmpG:magenta>
+ <xmpG:yellow>65.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=30 M=50 Y=75 K=10</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>30.000000</xmpG:cyan>
+ <xmpG:magenta>50.000000</xmpG:magenta>
+ <xmpG:yellow>75.000000</xmpG:yellow>
+ <xmpG:black>10.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=35 M=60 Y=80 K=25</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>35.000000</xmpG:cyan>
+ <xmpG:magenta>60.000000</xmpG:magenta>
+ <xmpG:yellow>80.000000</xmpG:yellow>
+ <xmpG:black>25.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=40 M=65 Y=90 K=35</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>40.000000</xmpG:cyan>
+ <xmpG:magenta>65.000000</xmpG:magenta>
+ <xmpG:yellow>90.000000</xmpG:yellow>
+ <xmpG:black>35.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=40 M=70 Y=100 K=50</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>40.000000</xmpG:cyan>
+ <xmpG:magenta>70.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>50.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=50 M=70 Y=80 K=70</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>50.000000</xmpG:cyan>
+ <xmpG:magenta>70.000000</xmpG:magenta>
+ <xmpG:yellow>80.000000</xmpG:yellow>
+ <xmpG:black>70.000000</xmpG:black>
+ </rdf:li>
+ </rdf:Seq>
+ </xmpG:Colorants>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:groupName>Grays</xmpG:groupName>
+ <xmpG:groupType>1</xmpG:groupType>
+ <xmpG:Colorants>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=0 Y=0 K=100</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>100.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=0 Y=0 K=90</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>89.999400</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=0 Y=0 K=80</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>79.998800</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=0 Y=0 K=70</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>69.999700</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=0 Y=0 K=60</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>59.999100</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=0 Y=0 K=50</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>50.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=0 Y=0 K=40</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>39.999400</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=0 Y=0 K=30</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>29.998800</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=0 Y=0 K=20</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>19.999700</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=0 Y=0 K=10</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>9.999100</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=0 Y=0 K=5</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>0.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>4.998800</xmpG:black>
+ </rdf:li>
+ </rdf:Seq>
+ </xmpG:Colorants>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:groupName>Brights</xmpG:groupName>
+ <xmpG:groupType>1</xmpG:groupType>
+ <xmpG:Colorants>
+ <rdf:Seq>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=100 Y=100 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>100.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=75 Y=100 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>75.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=0 M=10 Y=95 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>0.000000</xmpG:cyan>
+ <xmpG:magenta>10.000000</xmpG:magenta>
+ <xmpG:yellow>95.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=85 M=10 Y=100 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>85.000000</xmpG:cyan>
+ <xmpG:magenta>10.000000</xmpG:magenta>
+ <xmpG:yellow>100.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=100 M=90 Y=0 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>100.000000</xmpG:cyan>
+ <xmpG:magenta>90.000000</xmpG:magenta>
+ <xmpG:yellow>0.000000</xmpG:yellow>
+ <xmpG:black>0.000000</xmpG:black>
+ </rdf:li>
+ <rdf:li rdf:parseType="Resource">
+ <xmpG:swatchName>C=60 M=90 Y=0 K=0</xmpG:swatchName>
+ <xmpG:mode>CMYK</xmpG:mode>
+ <xmpG:type>PROCESS</xmpG:type>
+ <xmpG:cyan>60.000000</xmpG:cyan>
+ <xmpG:magenta>90.000000</xmpG:magenta>
+ <xmpG:yellow>0.003100</xmpG:yellow>
+ <xmpG:black>0.003100</xmpG:black>
+ </rdf:li>
+ </rdf:Seq>
+ </xmpG:Colorants>
+ </rdf:li>
+ </rdf:Seq>
+ </xmpTPg:SwatchGroups>
+ <pdf:Producer>Adobe PDF library 15.00</pdf:Producer>
+ </rdf:Description>
+ </rdf:RDF>
+</x:xmpmeta>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<?xpacket end="w"?> endstream endobj 3 0 obj <</Count 2/Kids[7 0 R 8 0 R]/Type/Pages>> endobj 7 0 obj <</ArtBox[9.0 9.0 801.0 621.0]/BleedBox[0.0 0.0 810.0 630.0]/Contents 9 0 R/Group 10 0 R/LastModified(D:20161031172420Z)/MediaBox[0.0 0.0 810.0 630.0]/Parent 3 0 R/PieceInfo<</Illustrator 11 0 R>>/Resources<</ExtGState<</GS0 12 0 R>>/Properties<</MC0 5 0 R>>/XObject<</Fm0 13 0 R>>>>/Thumb 14 0 R/TrimBox[9.0 9.0 801.0 621.0]/Type/Page>> endobj 8 0 obj <</ArtBox[9.0 9.0 801.0 621.0]/BleedBox[0.0 0.0 810.0 630.0]/Contents 15 0 R/Group 16 0 R/LastModified(D:20161031172420Z)/MediaBox[0.0 0.0 810.0 630.0]/Parent 3 0 R/PieceInfo<</Illustrator 11 0 R>>/Resources<</ExtGState<</GS0 12 0 R>>/Properties<</MC0 5 0 R>>/XObject<</Fm0 17 0 R>>>>/Thumb 18 0 R/TrimBox[9.0 9.0 801.0 621.0]/Type/Page>> endobj 15 0 obj <</Filter/FlateDecode/Length 74>>stream
+H‰Ò÷wVÐ÷u6PprqVà*ä2P036P°04PÐ1ŠR¹Âò€âúîÁ
+éÅ@ù}·\—|®@.W_ ¦@.€
+8;Z,'9pXNV$mt_*&*&q$Q^LQqM6=FYXa>kGj/ck9Fc%GnKFj5?R_77h@jVCad\dU!
+!@o_jlu@L%GWqGb9DU0#r%F![m'CIIL+eng%_hma##WkB(D#8`gtokLpXBs3)T[]P
+aS.3->!%A_T&_MJ,.&D(*L5Edr1-s#*Od-"j0Mi3,pO$DiV>V\g<)I+Z1a:?3'!"[
+,E099(b'^6ZSm'GOo6<8kT`ZX*hT,FC^<44q*l4X_u'_.`Qg#05&SD*+".%fD61.H
+R3,5+c1C>:Q`[@B;L74hfr_AP(eMi`mgk?e"PoS0\N%H-D5T74Kt?Ne'YAX&%haHu
+P_QqYYRpg=_9lFk2c2P&U81d_M.nn`,7i-VSHhbY]-AD+,^:i2@Ps=TT$<4M+hb&0
+1ad[Z.E!U&()-Sl?c^U4S*59e(go7lo&#+bq6I3pA,6YCMQYQ$jp8M?hGn2Rf@qKE
+O;X+!e@p\Dq"3iaqO,*W76BMFBCbG<5>kBq[[**iM@5@RdPoGr2R<Ka1(MP&.5G@s
+CjsQb`[@+3'5Ma&:e/^ns)nF7iJOBbYS5QMN8`V<Z^8>.!%X(VM'%%CXt5D=K88^U
+A5PjHofbFW8*?AjCs7^-AA;:^@)W]T#"r6%;SJgZ^htOc6TX`OFo,Lq:^s9]_c?9m
+oR%+FcUm#3ChlpHATYp8hgauV=NRL]JA<tDnj)@OSSo.(PX$L'M54K;L%if51>$rp
+:=oT7;hT@-Q0a#TENIMp$k$ohE)'FaP;p*G$(`5WN]D-E9o,XIAQ!_t]*a?=$],97
+]8g$nlRo3>0LXRJoJ_.mZ(d?t'dU$&'Lsd\loEhPFS5T0'Aju;@L`r:P,Vt.q<\'n
+[<6!\'mG%DPnK(i3iT/pf(<W,DWNZ%IT0K.Oe@i$`[>"]bKqF2Djj_$I]22]I.HH;
+&gn4GDaA%SD4eK()fLpnaiTm!ol;7#Z8:7IVIpulM7Ol(0^A&$=<Tar\`CKE(3a5=
+Z^c<E>oQ?KL:YTRZFFH@4KR"af:8PTLqe7[Gq8(QF<=YlR)Fe:0XaS'<[RW*5LDJ,
+B>MXR==NO+:52b`%n08C`ot099)<O:-n3BMGWXDnl.K3%)bR?Rq\:ZiZq?8T/R1W]
+0*]a#[b`XKMUS3P#)$X9C[nFM-]M?si(b^ZWj]5LoGFjkq;rMWE*=36_=ES@Oqd&k
+bHXok9NT;OH">-<<4'5B+G:Mj-r6@8Bc#iW8s>7%Kc1'=)5=O9Q@fl5`ll*c&2>$C
+HCC:$.mFi2(9d>$,RgouR/$79a$FJ3]Jpki*3)-UbWOAs[IQL,Y8P[,o!c7qm]SnH
+&k7<\!;*UBg&~> endstream endobj 19 0 obj [/Indexed/DeviceRGB 255 20 0 R] endobj 20 0 obj <</Filter[/ASCII85Decode/FlateDecode]/Length 428>>stream
+8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0
+b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup`
+E1r!/,*0[*9.aFIR2&b-C#s<Xl5FH@[<=!#6V)uDBXnIr.F>oRZ7Dl%MLY\.?d>Mn
+6%Q2oYfNRF$$+ON<+]RUJmC0I<jlL.oXisZ;SYU[/7#<&37rclQKqeJe#,UF7Rgb1
+VNWFKf>nDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j<etJICj7e7nPMb=O6S7UOH<
+PO7r\I.Hu&e0d&E<.')fERr/l+*W,)q^D*ai5<uuLX.7g/>$XKrcYp0n+Xl_nU*O(
+l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 17 0 obj <</BBox[0.0 630.0 810.0 0.332611]/Group 21 0 R/Length 1521589/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R/GS1 22 0 R/GS2 23 0 R/GS3 24 0 R/GS4 25 0 R/GS5 26 0 R/GS6 27 0 R>>/XObject<</Fm0 28 0 R/Fm1 29 0 R/Fm10 30 0 R/Fm11 31 0 R/Fm12 32 0 R/Fm13 33 0 R/Fm14 34 0 R/Fm15 35 0 R/Fm16 36 0 R/Fm17 37 0 R/Fm18 38 0 R/Fm19 39 0 R/Fm2 40 0 R/Fm20 41 0 R/Fm21 42 0 R/Fm22 43 0 R/Fm23 44 0 R/Fm24 45 0 R/Fm25 46 0 R/Fm26 47 0 R/Fm27 48 0 R/Fm28 49 0 R/Fm29 50 0 R/Fm3 51 0 R/Fm30 52 0 R/Fm31 53 0 R/Fm32 54 0 R/Fm33 55 0 R/Fm34 56 0 R/Fm4 57 0 R/Fm5 58 0 R/Fm6 59 0 R/Fm7 60 0 R/Fm8 61 0 R/Fm9 62 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+0 630 810 -114.999 re
+f
+0 75 810 -74.667 re
+f
+q
+273.583 568.502 m
+272.764 568.502 272.076 567.939 271.892 567.175 c
+245.324 567.175 l
+245.232 567.175 245.159 567.061 245.166 566.97 c
+245.174 566.877 245.265 566.796 245.361 566.796 c
+271.834 566.796 l
+271.834 566.763 l
+271.834 565.801 272.621 565.025 273.583 565.025 c
+274.516 565.025 275.266 565.761 275.306 566.683 c
+278.83 566.191 280.818 564.192 282.861 562.148 c
+284.872 560.138 286.941 558.087 290.472 557.532 c
+290.568 556.662 291.288 555.989 292.184 555.989 c
+293.03 555.989 293.728 556.585 293.886 557.381 c
+300.581 557.381 l
+300.739 556.585 301.441 555.989 302.287 555.989 c
+303.132 555.989 303.83 556.585 303.988 557.381 c
+311.257 557.381 l
+316.026 557.381 318.452 559.793 320.807 562.148 c
+322.916 564.257 324.971 566.311 328.715 566.719 c
+328.738 565.779 329.516 565.025 330.465 565.025 c
+331.423 565.025 332.199 565.801 332.199 566.763 c
+332.199 566.796 l
+347.328 566.796 l
+347.328 566.763 l
+347.328 565.801 348.104 565.025 349.066 565.025 c
+350.003 565.025 350.764 565.763 350.801 566.694 c
+354.542 566.293 357.463 564.695 359.977 562.434 c
+362.895 559.807 365.253 556.286 367.609 552.755 c
+369.965 549.223 372.32 545.678 375.289 543.01 c
+377.454 541.062 379.945 539.588 382.977 538.931 c
+369.38 538.931 l
+369.222 539.729 368.524 540.334 367.679 540.334 c
+366.834 540.334 366.121 539.729 365.963 538.931 c
+350.779 538.931 l
+350.621 539.729 349.912 540.334 349.066 540.334 c
+348.254 540.334 347.578 539.773 347.387 539.019 c
+343.745 539.471 341.717 541.503 339.637 543.579 c
+337.561 545.659 335.418 547.783 331.662 548.253 c
+331.612 549.169 330.854 549.9 329.925 549.9 c
+329.028 549.9 328.308 549.217 328.212 548.346 c
+322.611 548.346 l
+322.52 549.217 321.785 549.9 320.888 549.9 c
+319.992 549.9 319.267 549.217 319.172 548.346 c
+314.295 548.346 l
+317.177 549.11 319.014 550.94 320.807 552.733 c
+322.829 554.754 324.802 556.735 328.256 557.256 c
+328.462 556.522 329.127 555.989 329.925 555.989 c
+330.773 555.989 331.486 556.588 331.641 557.393 c
+347.361 557.393 l
+347.516 556.588 348.217 555.989 349.066 555.989 c
+350.026 555.989 350.812 556.764 350.812 557.724 c
+350.812 558.686 350.026 559.461 349.066 559.461 c
+348.115 559.461 347.346 558.705 347.328 557.761 c
+331.674 557.761 l
+331.655 558.705 330.876 559.461 329.925 559.461 c
+328.965 559.461 328.19 558.686 328.19 557.724 c
+328.19 557.69 328.198 557.657 328.201 557.624 c
+324.637 557.08 322.553 555.016 320.531 552.994 c
+318.253 550.712 316.049 548.481 311.69 548.346 c
+303.473 548.346 l
+303.463 548.456 303.436 548.558 303.403 548.666 c
+303.374 548.764 303.338 548.86 303.29 548.948 c
+303.242 549.047 303.187 549.14 303.12 549.223 c
+303.069 549.29 303.01 549.349 302.948 549.408 c
+302.933 549.418 302.929 549.441 302.915 549.452 c
+302.893 549.47 302.867 549.481 302.845 549.499 c
+302.786 549.547 302.727 549.595 302.661 549.635 c
+302.577 549.691 302.485 549.734 302.389 549.771 c
+302.191 549.848 301.974 549.9 301.75 549.9 c
+301.632 549.9 301.514 549.886 301.404 549.863 c
+301.291 549.841 301.18 549.805 301.074 549.761 c
+300.978 549.72 300.876 549.668 300.787 549.613 c
+300.783 549.61 300.78 549.603 300.776 549.603 c
+300.685 549.539 300.604 549.462 300.527 549.385 c
+300.456 549.312 300.39 549.238 300.332 549.154 c
+300.295 549.103 300.261 549.044 300.228 548.985 c
+300.207 548.945 300.178 548.911 300.159 548.871 c
+300.155 548.86 300.155 548.845 300.148 548.834 c
+300.107 548.735 300.082 548.635 300.056 548.525 c
+300.049 548.481 300.041 548.437 300.034 548.39 c
+300.026 548.334 300.012 548.276 300.012 548.217 c
+296.411 547.688 294.32 545.612 292.288 543.579 c
+291.983 543.274 291.681 542.977 291.372 542.675 c
+289.866 544.288 288.874 546.247 287.878 548.242 c
+286.698 550.594 285.504 552.98 283.409 554.777 c
+281.568 556.353 279.036 557.455 275.241 557.701 c
+275.019 558.414 274.366 558.937 273.583 558.937 c
+272.819 558.937 272.172 558.444 271.937 557.761 c
+226.7 557.761 l
+226.642 557.761 l
+226.546 557.746 226.469 557.639 226.484 557.543 c
+226.494 557.445 226.601 557.371 226.7 557.381 c
+271.856 557.381 l
+271.852 557.319 271.834 557.264 271.834 557.198 c
+271.834 556.239 272.621 555.453 273.583 555.453 c
+274.545 555.453 275.321 556.239 275.321 557.198 c
+275.321 557.242 275.31 557.283 275.306 557.327 c
+278.985 557.069 281.41 555.989 283.17 554.478 c
+285.195 552.745 286.356 550.426 287.532 548.07 c
+288.528 546.078 289.535 544.064 291.089 542.403 c
+289.429 540.831 287.602 539.478 284.813 539.067 c
+284.607 539.794 283.942 540.334 283.145 540.334 c
+282.3 540.334 281.601 539.729 281.443 538.927 c
+275.285 538.927 l
+275.127 539.729 274.428 540.334 273.583 540.334 c
+272.738 540.334 272.029 539.729 271.867 538.927 c
+226.484 538.927 l
+226.476 538.931 198.221 538.931 198.214 538.927 c
+198.114 538.923 198.027 538.824 198.033 538.725 c
+198.037 538.622 198.125 538.538 198.225 538.541 c
+271.834 538.541 l
+271.86 537.601 272.635 536.851 273.583 536.851 c
+274.527 536.851 275.295 537.601 275.321 538.541 c
+281.41 538.541 l
+281.432 537.601 282.2 536.851 283.145 536.851 c
+284.093 536.851 284.857 537.601 284.883 538.541 c
+300.012 538.541 l
+300.037 537.601 300.802 536.851 301.75 536.851 c
+302.694 536.851 303.473 537.601 303.496 538.541 c
+308.217 538.541 l
+305.337 537.77 303.496 535.947 301.703 534.154 c
+299.7 532.147 297.734 530.192 294.335 529.652 c
+294.081 530.299 293.449 530.759 292.71 530.759 c
+291.92 530.759 291.266 530.225 291.052 529.502 c
+275.241 529.502 l
+275.027 530.225 274.373 530.759 273.583 530.759 c
+272.793 530.759 272.128 530.225 271.915 529.502 c
+235.898 529.502 l
+235.792 529.516 235.693 529.425 235.693 529.317 c
+235.693 529.211 235.792 529.123 235.898 529.138 c
+271.844 529.138 l
+271.844 529.097 271.834 529.064 271.834 529.024 c
+271.834 528.061 272.621 527.274 273.583 527.274 c
+274.545 527.274 275.321 528.061 275.321 529.024 c
+275.321 529.064 275.31 529.097 275.306 529.138 c
+290.987 529.138 l
+290.983 529.097 290.972 529.064 290.972 529.024 c
+290.972 528.061 291.748 527.274 292.71 527.274 c
+293.672 527.274 294.459 528.061 294.459 529.024 c
+294.459 529.119 294.452 529.203 294.437 529.296 c
+297.917 529.869 299.972 531.894 301.967 533.889 c
+304.021 535.947 306.031 537.961 309.599 538.439 c
+309.676 537.545 310.411 536.851 311.323 536.851 c
+312.271 536.851 313.036 537.601 313.061 538.541 c
+319.15 538.541 l
+319.176 537.601 319.94 536.851 320.888 536.851 c
+321.833 536.851 322.611 537.601 322.638 538.541 c
+330.086 538.541 l
+334.731 538.541 337.021 536.245 339.376 533.889 c
+341.455 531.813 343.595 529.696 347.35 529.23 c
+347.343 529.159 347.328 529.093 347.328 529.024 c
+347.328 528.061 348.104 527.274 349.066 527.274 c
+350.026 527.274 350.812 528.061 350.812 529.024 c
+350.812 529.064 350.804 529.097 350.801 529.138 c
+356.904 529.138 l
+356.9 529.097 356.894 529.064 356.894 529.024 c
+356.894 528.061 357.68 527.274 358.639 527.274 c
+359.602 527.274 360.377 528.061 360.377 529.024 c
+360.377 529.064 360.37 529.097 360.366 529.138 c
+375.517 529.138 l
+375.514 529.097 375.506 529.064 375.506 529.024 c
+375.506 528.061 376.282 527.274 377.244 527.274 c
+378.204 527.274 378.979 528.061 378.979 529.024 c
+378.979 529.101 378.967 529.174 378.957 529.252 c
+382.595 529.766 384.697 531.846 386.74 533.889 c
+388.75 535.899 390.713 537.857 394.13 538.391 c
+394.229 537.523 394.95 536.851 395.846 536.851 c
+396.791 536.851 397.57 537.601 397.591 538.541 c
+414.859 538.541 l
+419.504 538.541 421.782 536.245 424.138 533.889 c
+426.17 531.856 428.265 529.788 431.874 529.263 c
+431.862 529.182 431.851 529.108 431.851 529.024 c
+431.851 528.061 432.634 527.274 433.597 527.274 c
+434.559 527.274 435.335 528.061 435.335 529.024 c
+435.335 529.064 435.324 529.097 435.324 529.138 c
+441.435 529.138 l
+441.435 529.097 441.424 529.064 441.424 529.024 c
+441.424 528.061 442.199 527.274 443.163 527.274 c
+444.125 527.274 444.911 528.061 444.911 529.024 c
+444.911 529.982 444.125 530.759 443.163 530.759 c
+442.369 530.759 441.718 530.225 441.505 529.502 c
+435.254 529.502 l
+435.041 530.225 434.391 530.759 433.597 530.759 c
+432.847 530.759 432.208 530.281 431.965 529.616 c
+428.441 530.111 426.453 532.11 424.41 534.154 c
+422.617 535.947 420.779 537.77 417.898 538.541 c
+431.851 538.541 l
+431.874 537.601 432.653 536.851 433.597 536.851 c
+434.559 536.851 435.335 537.622 435.335 538.586 c
+435.335 539.548 434.559 540.334 433.597 540.334 c
+432.751 540.334 432.042 539.729 431.884 538.927 c
+408.473 538.927 l
+411.353 539.698 413.191 541.51 414.985 543.303 c
+416.98 545.302 418.938 547.258 422.319 547.809 c
+422.48 547.016 423.182 546.412 424.024 546.412 c
+424.917 546.412 425.652 547.096 425.748 547.967 c
+431.874 547.967 l
+431.969 547.096 432.704 546.412 433.597 546.412 c
+434.559 546.412 435.335 547.199 435.335 548.162 c
+435.335 549.125 434.559 549.9 433.597 549.9 c
+432.701 549.9 431.969 549.217 431.874 548.346 c
+425.748 548.346 l
+425.652 549.217 424.921 549.9 424.024 549.9 c
+423.068 549.9 422.297 549.136 422.286 548.184 c
+418.784 547.618 416.722 545.582 414.723 543.579 c
+412.367 541.224 410.079 538.927 405.433 538.927 c
+397.558 538.927 l
+397.4 539.729 396.691 540.334 395.846 540.334 c
+395 540.334 394.302 539.729 394.141 538.927 c
+388.522 538.927 l
+388.515 538.96 388.507 538.99 388.496 539.019 c
+388.478 539.104 388.452 539.181 388.419 539.262 c
+388.386 539.339 388.349 539.416 388.305 539.49 c
+388.284 539.526 388.257 539.559 388.236 539.592 c
+388.176 539.673 388.11 539.75 388.041 539.82 c
+387.971 539.89 387.904 539.956 387.824 540.015 c
+387.813 540.022 387.802 540.03 387.791 540.037 c
+387.784 540.045 387.773 540.045 387.765 540.048 c
+387.681 540.107 387.589 540.155 387.493 540.199 c
+387.287 540.284 387.056 540.334 386.817 540.334 c
+386.696 540.334 386.582 540.313 386.464 540.286 c
+386.376 540.268 386.284 540.253 386.2 540.221 c
+386.141 540.199 386.086 540.169 386.03 540.14 c
+385.994 540.122 385.961 540.103 385.928 540.085 c
+385.876 540.051 385.824 540.026 385.777 539.993 c
+385.726 539.952 385.678 539.897 385.63 539.853 c
+385.612 539.839 385.589 539.827 385.571 539.809 c
+385.494 539.732 385.428 539.648 385.365 539.555 c
+385.307 539.467 385.252 539.372 385.207 539.272 c
+385.207 539.262 l
+385.171 539.174 385.138 539.089 385.116 538.997 c
+381.184 539.324 378.141 540.941 375.539 543.282 c
+372.621 545.909 370.273 549.429 367.917 552.961 c
+365.566 556.492 363.21 560.046 360.241 562.717 c
+357.673 565.033 354.633 566.683 350.779 567.083 c
+350.631 567.891 349.919 568.502 349.066 568.502 c
+348.247 568.502 347.57 567.936 347.387 567.175 c
+332.144 567.175 l
+331.957 567.936 331.284 568.502 330.465 568.502 c
+329.619 568.502 328.907 567.906 328.749 567.105 c
+324.846 566.701 322.656 564.533 320.535 562.409 c
+318.18 560.057 315.901 557.761 311.257 557.761 c
+304.024 557.761 l
+304.006 558.705 303.238 559.461 302.287 559.461 c
+301.335 559.461 300.567 558.705 300.548 557.761 c
+293.923 557.761 l
+293.905 558.705 293.136 559.461 292.184 559.461 c
+291.288 559.461 290.568 558.789 290.472 557.919 c
+287.084 558.466 285.122 560.41 283.123 562.409 c
+281.068 564.467 278.967 566.573 275.285 567.072 c
+275.141 567.888 274.439 568.502 273.583 568.502 c
+271.639 551.054 m
+271.639 545.329 l
+273.55 542.459 l
+275.457 545.329 l
+275.457 551.054 l
+h
+394.086 551.054 m
+394.086 545.329 l
+395.993 542.459 l
+397.9 545.329 l
+397.9 551.054 l
+h
+303.473 547.967 m
+319.172 547.967 l
+319.271 547.096 319.992 546.412 320.888 546.412 c
+321.785 546.412 322.516 547.096 322.611 547.967 c
+328.212 547.967 l
+328.308 547.096 329.031 546.412 329.925 546.412 c
+330.791 546.412 331.516 547.048 331.652 547.875 c
+335.275 547.419 337.303 545.38 339.376 543.303 c
+341.169 541.51 343.007 539.698 345.887 538.931 c
+341.202 538.931 l
+341.044 539.729 340.346 540.334 339.501 540.334 c
+338.656 540.334 337.946 539.729 337.788 538.931 c
+322.6 538.931 l
+322.443 539.729 321.734 540.334 320.888 540.334 c
+320.043 540.334 319.345 539.729 319.187 538.931 c
+313.028 538.931 l
+312.87 539.729 312.168 540.334 311.323 540.334 c
+310.478 540.334 309.78 539.729 309.622 538.931 c
+303.463 538.931 l
+303.305 539.729 302.595 540.334 301.75 540.334 c
+300.93 540.334 300.255 539.761 300.067 538.997 c
+296.411 539.254 293.996 540.316 292.243 541.819 c
+292.026 542.003 291.821 542.208 291.626 542.403 c
+291.939 542.705 292.243 542.999 292.552 543.303 c
+294.58 545.333 296.565 547.328 300.045 547.842 c
+300.063 547.754 300.085 547.662 300.115 547.577 c
+300.118 547.563 300.122 547.548 300.126 547.534 c
+300.155 547.457 300.199 547.386 300.24 547.317 c
+300.247 547.302 300.255 547.284 300.261 547.269 c
+300.295 547.214 300.328 547.162 300.365 547.111 c
+300.416 547.045 300.467 546.986 300.527 546.927 c
+300.589 546.865 300.651 546.81 300.721 546.754 c
+300.754 546.732 300.787 546.711 300.824 546.688 c
+300.872 546.659 300.92 546.634 300.971 546.607 c
+301.022 546.582 301.074 546.549 301.133 546.526 c
+301.217 546.493 301.313 546.468 301.404 546.449 c
+301.518 546.424 301.628 546.412 301.75 546.412 c
+301.974 546.412 302.18 546.46 302.378 546.538 c
+302.478 546.578 302.573 546.622 302.661 546.677 c
+302.727 546.717 302.786 546.765 302.845 546.813 c
+302.867 546.831 302.893 546.839 302.915 546.857 c
+302.937 546.879 302.959 546.905 302.981 546.927 c
+303.11 547.056 303.209 547.203 303.29 547.361 c
+303.338 547.453 303.374 547.548 303.403 547.648 c
+303.436 547.75 303.463 547.857 303.473 547.967 c
+291.351 542.139 m
+291.556 541.933 291.773 541.731 292.001 541.533 c
+293.397 540.338 295.195 539.416 297.634 538.931 c
+286.036 538.931 l
+288.286 539.53 289.899 540.768 291.351 542.139 c
+441.174 540.687 m
+441.174 534.966 l
+443.082 532.107 l
+444.988 534.966 l
+444.988 540.687 l
+h
+333.125 538.541 m
+337.752 538.541 l
+337.777 537.601 338.556 536.851 339.501 536.851 c
+340.449 536.851 341.214 537.601 341.239 538.541 c
+347.328 538.541 l
+347.354 537.601 348.118 536.851 349.066 536.851 c
+350.01 536.851 350.789 537.601 350.812 538.541 c
+365.93 538.541 l
+365.955 537.601 366.731 536.851 367.679 536.851 c
+368.623 536.851 369.392 537.601 369.417 538.541 c
+385.068 538.541 l
+385.072 538.497 385.076 538.457 385.079 538.416 c
+385.09 538.343 385.097 538.269 385.116 538.2 c
+385.138 538.096 385.167 538.005 385.207 537.913 c
+385.23 537.861 385.259 537.814 385.284 537.762 c
+385.365 537.616 385.465 537.472 385.583 537.35 c
+385.604 537.332 385.63 537.314 385.652 537.296 c
+385.795 537.167 385.953 537.064 386.134 536.987 c
+386.144 536.987 l
+386.244 536.943 386.354 536.906 386.464 536.884 c
+386.475 536.884 l
+386.586 536.862 386.699 536.851 386.817 536.851 c
+386.938 536.851 387.048 536.862 387.158 536.884 c
+387.332 536.917 387.49 536.987 387.64 537.068 c
+387.688 537.094 387.744 537.115 387.787 537.145 c
+387.875 537.204 387.952 537.269 388.03 537.34 c
+388.041 537.35 l
+388.052 537.365 388.062 537.383 388.074 537.398 c
+388.137 537.464 388.206 537.538 388.257 537.616 c
+388.313 537.699 388.364 537.784 388.405 537.876 c
+388.411 537.888 388.411 537.902 388.415 537.913 c
+388.456 538.005 388.486 538.1 388.507 538.2 c
+388.526 538.269 388.537 538.343 388.544 538.416 c
+388.548 538.457 388.552 538.497 388.555 538.541 c
+392.976 538.541 l
+390.095 537.77 388.257 535.947 386.464 534.154 c
+384.413 532.103 382.418 530.104 378.876 529.616 c
+378.63 530.281 377.994 530.759 377.241 530.759 c
+376.451 530.759 375.796 530.225 375.587 529.502 c
+360.297 529.502 l
+360.083 530.225 359.433 530.759 358.639 530.759 c
+357.849 530.759 357.184 530.225 356.971 529.502 c
+350.735 529.502 l
+350.521 530.225 349.856 530.759 349.066 530.759 c
+348.306 530.759 347.67 530.269 347.431 529.593 c
+343.764 530.03 341.724 532.066 339.637 534.154 c
+337.844 535.947 336.006 537.77 333.125 538.541 c
+320.866 535.079 m
+318.955 532.221 l
+318.955 526.485 l
+322.773 526.485 l
+322.773 532.221 l
+h
+W n
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+/GS1 gs
+0 TL/Fm0 Do
+Q
+Q
+0 0 0 0 k
+q 1 0 0 1 40.6324 64.7361 cm
+0 0 m
+-0.276 -0.306 -0.632 -0.541 -1.073 -0.706 c
+-1.507 -0.871 -1.97 -0.948 -2.469 -0.941 c
+-2.911 -0.941 -3.293 -0.846 -3.616 -0.662 c
+-3.939 -0.467 -4.189 -0.188 -4.366 0.176 c
+-4.542 0.536 -4.642 0.955 -4.659 1.425 c
+-4.671 1.679 -4.656 1.944 -4.615 2.219 c
+-4.439 3.424 l
+-4.285 4.453 -3.95 5.247 -3.439 5.805 c
+-2.932 6.364 -2.263 6.632 -1.44 6.614 c
+-0.735 6.603 -0.206 6.393 0.147 5.982 c
+0.5 5.57 0.68 4.968 0.69 4.174 c
+-0.721 4.174 l
+-0.735 4.586 l
+-0.775 5.104 -1.037 5.373 -1.514 5.394 c
+-2.213 5.423 -2.668 4.961 -2.881 4.012 c
+-2.955 3.63 l
+-3.16 2.219 l
+-3.2 1.896 -3.215 1.616 -3.204 1.381 c
+-3.197 1.007 -3.113 0.735 -2.955 0.558 c
+-2.801 0.389 -2.583 0.301 -2.308 0.294 c
+-2.043 0.294 -1.749 0.382 -1.426 0.558 c
+-1.176 1.911 l
+-2.19 1.911 l
+-1.984 3.027 l
+0.47 3.027 l
+h
+2.095 -0.838 m
+0.698 -0.838 l
+1.639 4.629 l
+3.05 4.629 l
+h
+1.83 6.011 m
+1.83 6.247 1.903 6.437 2.051 6.585 c
+2.198 6.732 2.373 6.805 2.579 6.805 c
+2.793 6.813 2.977 6.746 3.123 6.599 c
+3.271 6.46 3.344 6.283 3.344 6.071 c
+3.344 5.835 3.271 5.644 3.123 5.497 c
+2.977 5.35 2.793 5.277 2.579 5.277 c
+2.363 5.265 2.183 5.328 2.036 5.468 c
+1.897 5.614 1.83 5.795 1.83 6.011 c
+5.945 5.967 m
+5.71 4.629 l
+6.416 4.629 l
+6.24 3.557 l
+5.534 3.557 l
+5.064 0.793 l
+5.049 0.631 l
+5.038 0.404 5.13 0.294 5.328 0.294 c
+5.388 0.282 5.505 0.286 5.681 0.309 c
+5.548 -0.809 l
+5.343 -0.897 5.097 -0.941 4.814 -0.941 c
+4.409 -0.93 4.108 -0.786 3.902 -0.5 c
+3.697 -0.206 3.616 0.183 3.667 0.675 c
+4.137 3.557 l
+3.52 3.557 l
+3.697 4.629 l
+4.314 4.629 l
+4.549 5.967 l
+h
+7.915 0.396 m
+10.444 0.396 l
+10.238 -0.838 l
+6.254 -0.838 l
+7.533 6.526 l
+8.974 6.526 l
+h
+13.498 -0.838 m
+13.475 -0.721 13.468 -0.581 13.468 -0.412 c
+13.152 -0.765 12.796 -0.941 12.395 -0.941 c
+11.973 -0.941 11.634 -0.79 11.381 -0.485 c
+11.135 -0.184 11.021 0.195 11.042 0.646 c
+11.072 1.234 11.296 1.69 11.719 2.013 c
+12.137 2.344 12.704 2.513 13.409 2.513 c
+13.82 2.513 l
+13.88 2.954 l
+13.895 3.175 l
+13.895 3.469 13.777 3.615 13.542 3.615 c
+13.218 3.623 13.02 3.417 12.954 2.998 c
+11.557 2.983 l
+11.586 3.501 11.8 3.924 12.204 4.247 c
+12.604 4.579 13.093 4.74 13.674 4.733 c
+14.21 4.722 14.622 4.549 14.909 4.218 c
+15.202 3.895 15.324 3.461 15.276 2.925 c
+14.82 0.147 l
+14.805 -0.133 l
+14.795 -0.368 14.82 -0.574 14.879 -0.75 c
+14.865 -0.838 l
+h
+12.792 0.176 m
+13.034 0.165 13.263 0.272 13.468 0.5 c
+13.718 1.646 l
+13.409 1.646 l
+13.145 1.635 12.928 1.547 12.762 1.381 c
+12.594 1.213 12.498 1.003 12.469 0.749 c
+12.469 0.558 l
+12.469 0.448 12.49 0.357 12.542 0.278 c
+12.601 0.209 12.681 0.176 12.792 0.176 c
+18.057 -0.941 m
+17.595 -0.919 17.249 -0.706 17.014 -0.294 c
+16.837 -0.838 l
+15.53 -0.838 l
+16.882 6.923 l
+18.279 6.923 l
+17.749 4.174 l
+18.061 4.556 18.418 4.74 18.822 4.733 c
+19.3 4.722 19.66 4.542 19.895 4.189 c
+20.13 3.844 20.233 3.34 20.204 2.675 c
+20.182 1.899 20.087 1.227 19.91 0.661 c
+19.74 0.091 19.502 -0.324 19.189 -0.588 c
+18.874 -0.842 18.499 -0.96 18.057 -0.941 c
+18.836 2.66 m
+18.844 2.973 18.807 3.193 18.719 3.322 c
+18.639 3.457 18.506 3.528 18.323 3.528 c
+18.065 3.534 17.83 3.403 17.617 3.131 c
+17.19 0.617 l
+17.286 0.382 17.477 0.253 17.764 0.235 c
+18.282 0.205 18.591 0.577 18.69 1.352 c
+18.734 1.72 l
+h
+25.672 1.72 m
+23.262 1.72 l
+23.482 2.91 l
+25.878 2.91 l
+h
+32.933 2.352 m
+30.684 2.352 l
+30.346 0.396 l
+33.007 0.396 l
+32.787 -0.838 l
+28.685 -0.838 l
+29.964 6.526 l
+34.065 6.526 l
+33.845 5.277 l
+31.199 5.277 l
+30.89 3.542 l
+33.139 3.542 l
+h
+35.424 1.205 m
+36.63 4.629 l
+38.115 4.629 l
+35.807 -0.838 l
+34.484 -0.838 l
+33.867 4.629 l
+35.293 4.629 l
+h
+39.966 -0.941 m
+39.526 -0.941 39.147 -0.834 38.835 -0.618 c
+38.53 -0.405 38.31 -0.103 38.173 0.278 c
+38.034 0.661 37.99 1.095 38.041 1.587 c
+38.085 1.955 l
+38.202 2.865 38.474 3.561 38.908 4.041 c
+39.349 4.519 39.912 4.751 40.599 4.733 c
+41.098 4.71 41.488 4.556 41.774 4.262 c
+42.058 3.968 42.223 3.549 42.274 3.013 c
+42.293 2.69 42.282 2.373 42.245 2.072 c
+42.157 1.411 l
+39.423 1.411 l
+39.401 1.271 39.397 1.135 39.409 0.999 c
+39.438 0.507 39.677 0.257 40.128 0.249 c
+40.548 0.239 40.955 0.4 41.348 0.735 c
+41.819 -0.133 l
+41.631 -0.389 41.371 -0.588 41.04 -0.736 c
+40.706 -0.882 40.349 -0.948 39.966 -0.941 c
+40.467 3.557 m
+40.062 3.564 39.783 3.307 39.629 2.778 c
+39.526 2.41 l
+40.907 2.41 l
+40.944 2.605 40.966 2.763 40.966 2.881 c
+40.974 3.31 40.808 3.534 40.467 3.557 c
+45.799 3.248 m
+45.358 3.307 l
+44.982 3.314 44.681 3.138 44.446 2.778 c
+43.814 -0.838 l
+42.418 -0.838 l
+43.373 4.629 l
+44.681 4.629 l
+44.564 4.027 l
+44.729 4.292 44.891 4.475 45.049 4.586 c
+45.203 4.692 45.376 4.747 45.564 4.747 c
+45.67 4.747 45.813 4.722 45.99 4.674 c
+h
+47.897 1.572 m
+49.146 4.629 l
+50.661 4.629 l
+47.853 -1.661 l
+47.647 -2.151 47.405 -2.503 47.133 -2.72 c
+46.857 -2.944 46.537 -3.057 46.177 -3.057 c
+46.037 -3.057 45.832 -3.021 45.56 -2.955 c
+45.692 -1.838 l
+45.839 -1.852 l
+46.221 -1.852 46.501 -1.68 46.677 -1.338 c
+46.912 -0.823 l
+46.339 4.629 l
+47.808 4.629 l
+h
+52.997 4.733 m
+53.556 4.71 53.986 4.519 54.291 4.159 c
+54.603 3.806 54.776 3.326 54.806 2.719 c
+54.806 2.366 l
+54.754 1.308 54.501 0.484 54.041 -0.103 c
+53.578 -0.684 52.976 -0.96 52.233 -0.941 c
+51.8 -0.93 51.443 -0.817 51.16 -0.588 c
+50.873 -0.364 50.667 -0.056 50.543 0.338 c
+50.426 0.738 50.389 1.198 50.44 1.72 c
+50.469 1.984 l
+50.565 2.844 50.84 3.52 51.292 4.012 c
+51.741 4.512 52.31 4.751 52.997 4.733 c
+51.822 1.146 m
+51.822 0.558 51.997 0.253 52.35 0.235 c
+52.839 0.205 53.159 0.577 53.306 1.352 c
+53.35 1.72 l
+53.398 2.198 53.424 2.506 53.424 2.645 c
+53.424 3.222 53.24 3.528 52.88 3.557 c
+52.604 3.564 52.38 3.439 52.204 3.175 c
+52.035 2.917 51.928 2.547 51.88 2.057 c
+51.839 1.565 51.822 1.263 51.822 1.146 c
+57.246 4.629 m
+57.142 4.086 l
+57.532 4.534 57.958 4.751 58.422 4.733 c
+58.804 4.722 59.091 4.575 59.288 4.292 c
+59.494 4.016 59.598 3.619 59.598 3.101 c
+59.568 2.645 l
+58.98 -0.838 l
+57.584 -0.838 l
+58.157 2.645 l
+58.187 2.94 l
+58.204 3.34 58.058 3.542 57.745 3.542 c
+57.599 3.542 57.47 3.501 57.363 3.424 c
+57.264 3.343 57.175 3.252 57.098 3.145 c
+56.393 -0.838 l
+54.997 -0.838 l
+55.952 4.629 l
+h
+62.141 -0.941 m
+61.699 -0.941 61.321 -0.834 61.009 -0.618 c
+60.703 -0.405 60.483 -0.103 60.347 0.278 c
+60.207 0.661 60.163 1.095 60.215 1.587 c
+60.259 1.955 l
+60.377 2.865 60.649 3.561 61.082 4.041 c
+61.522 4.519 62.085 4.751 62.773 4.733 c
+63.272 4.71 63.662 4.556 63.949 4.262 c
+64.231 3.968 64.396 3.549 64.448 3.013 c
+64.466 2.69 64.456 2.373 64.419 2.072 c
+64.331 1.411 l
+61.597 1.411 l
+61.574 1.271 61.57 1.135 61.582 0.999 c
+61.611 0.507 61.85 0.257 62.302 0.249 c
+62.721 0.239 63.128 0.4 63.522 0.735 c
+63.992 -0.133 l
+63.805 -0.389 63.544 -0.588 63.213 -0.736 c
+62.879 -0.882 62.522 -0.948 62.141 -0.941 c
+62.64 3.557 m
+62.236 3.564 61.956 3.307 61.802 2.778 c
+61.699 2.41 l
+63.081 2.41 l
+63.118 2.605 63.14 2.763 63.14 2.881 c
+63.147 3.31 62.982 3.534 62.64 3.557 c
+69.034 0.235 m
+69.416 0.224 69.655 0.5 69.754 1.058 c
+71.063 1.058 l
+71.004 0.448 70.776 -0.04 70.386 -0.412 c
+69.993 -0.786 69.519 -0.96 68.961 -0.941 c
+68.45 -0.93 68.042 -0.78 67.741 -0.485 c
+67.436 -0.192 67.255 0.213 67.197 0.735 c
+67.145 1.153 67.171 1.664 67.27 2.263 c
+67.365 2.869 67.554 3.373 67.829 3.777 c
+68.269 4.432 68.894 4.751 69.711 4.733 c
+70.258 4.71 70.681 4.512 70.974 4.13 c
+71.269 3.748 71.4 3.233 71.371 2.587 c
+70.048 2.587 l
+70.048 2.896 l
+70.037 3.314 69.875 3.534 69.563 3.557 c
+69.063 3.575 68.77 3.189 68.682 2.395 c
+68.578 1.484 l
+68.538 1.209 68.523 0.984 68.535 0.808 c
+68.564 0.434 68.729 0.242 69.034 0.235 c
+74.028 -0.838 m
+74.006 -0.721 73.999 -0.581 73.999 -0.412 c
+73.682 -0.765 73.326 -0.941 72.926 -0.941 c
+72.503 -0.941 72.165 -0.79 71.911 -0.485 c
+71.666 -0.184 71.552 0.195 71.573 0.646 c
+71.602 1.234 71.827 1.69 72.25 2.013 c
+72.668 2.344 73.235 2.513 73.94 2.513 c
+74.351 2.513 l
+74.411 2.954 l
+74.425 3.175 l
+74.425 3.469 74.307 3.615 74.072 3.615 c
+73.749 3.623 73.551 3.417 73.484 2.998 c
+72.088 2.983 l
+72.117 3.501 72.331 3.924 72.734 4.247 c
+73.135 4.579 73.624 4.74 74.205 4.733 c
+74.741 4.722 75.153 4.549 75.439 4.218 c
+75.733 3.895 75.855 3.461 75.807 2.925 c
+75.351 0.147 l
+75.336 -0.133 l
+75.325 -0.368 75.351 -0.574 75.41 -0.75 c
+75.396 -0.838 l
+h
+73.322 0.176 m
+73.565 0.165 73.793 0.272 73.999 0.5 c
+74.249 1.646 l
+73.94 1.646 l
+73.675 1.635 73.459 1.547 73.293 1.381 c
+73.124 1.213 73.029 1.003 72.999 0.749 c
+72.999 0.558 l
+72.999 0.448 73.021 0.357 73.073 0.278 c
+73.131 0.209 73.212 0.176 73.322 0.176 c
+78.28 4.629 m
+78.177 4.086 l
+78.567 4.534 78.993 4.751 79.456 4.733 c
+79.838 4.722 80.125 4.575 80.323 4.292 c
+80.529 4.016 80.632 3.619 80.632 3.101 c
+80.603 2.645 l
+80.015 -0.838 l
+78.618 -0.838 l
+79.191 2.645 l
+79.221 2.94 l
+79.238 3.34 79.092 3.542 78.779 3.542 c
+78.633 3.542 78.504 3.501 78.397 3.424 c
+78.298 3.343 78.21 3.252 78.133 3.145 c
+77.428 -0.838 l
+76.031 -0.838 l
+76.986 4.629 l
+h
+85.357 0.235 m
+85.74 0.224 85.979 0.5 86.078 1.058 c
+87.386 1.058 l
+87.327 0.448 87.099 -0.04 86.71 -0.412 c
+86.317 -0.786 85.842 -0.96 85.284 -0.941 c
+84.773 -0.93 84.366 -0.78 84.064 -0.485 c
+83.759 -0.192 83.579 0.213 83.52 0.735 c
+83.469 1.153 83.494 1.664 83.593 2.263 c
+83.689 2.869 83.876 3.373 84.152 3.777 c
+84.593 4.432 85.218 4.751 86.033 4.733 c
+86.581 4.71 87.003 4.512 87.298 4.13 c
+87.591 3.748 87.724 3.233 87.695 2.587 c
+86.372 2.587 l
+86.372 2.896 l
+86.361 3.314 86.199 3.534 85.887 3.557 c
+85.387 3.575 85.093 3.189 85.004 2.395 c
+84.902 1.484 l
+84.861 1.209 84.846 0.984 84.858 0.808 c
+84.887 0.434 85.052 0.242 85.357 0.235 c
+90.627 4.733 m
+91.186 4.71 91.616 4.519 91.921 4.159 c
+92.233 3.806 92.406 3.326 92.435 2.719 c
+92.435 2.366 l
+92.383 1.308 92.13 0.484 91.67 -0.103 c
+91.208 -0.684 90.605 -0.96 89.862 -0.941 c
+89.43 -0.93 89.073 -0.817 88.79 -0.588 c
+88.503 -0.364 88.297 -0.056 88.173 0.338 c
+88.055 0.738 88.018 1.198 88.069 1.72 c
+88.098 1.984 l
+88.194 2.844 88.47 3.52 88.921 4.012 c
+89.37 4.512 89.939 4.751 90.627 4.733 c
+89.451 1.146 m
+89.451 0.558 89.627 0.253 89.98 0.235 c
+90.469 0.205 90.789 0.577 90.936 1.352 c
+90.98 1.72 l
+91.028 2.198 91.053 2.506 91.053 2.645 c
+91.053 3.222 90.87 3.528 90.509 3.557 c
+90.234 3.564 90.01 3.439 89.833 3.175 c
+89.665 2.917 89.557 2.547 89.509 2.057 c
+89.469 1.565 89.451 1.263 89.451 1.146 c
+94.878 4.629 m
+94.776 4.086 l
+95.165 4.534 95.591 4.751 96.054 4.733 c
+96.437 4.722 96.723 4.575 96.922 4.292 c
+97.128 4.016 97.23 3.619 97.23 3.101 c
+97.201 2.645 l
+96.613 -0.838 l
+95.217 -0.838 l
+95.79 2.645 l
+95.819 2.94 l
+95.838 3.34 95.691 3.542 95.379 3.542 c
+95.231 3.542 95.103 3.501 94.996 3.424 c
+94.897 3.343 94.809 3.252 94.732 3.145 c
+94.026 -0.838 l
+92.63 -0.838 l
+93.585 4.629 l
+h
+100.318 5.967 m
+100.082 4.629 l
+100.788 4.629 l
+100.611 3.557 l
+99.906 3.557 l
+99.435 0.793 l
+99.421 0.631 l
+99.41 0.404 99.502 0.294 99.7 0.294 c
+99.759 0.282 99.876 0.286 100.052 0.309 c
+99.921 -0.809 l
+99.715 -0.897 99.468 -0.941 99.186 -0.941 c
+98.781 -0.93 98.48 -0.786 98.274 -0.5 c
+98.068 -0.206 97.987 0.183 98.039 0.675 c
+98.51 3.557 l
+97.892 3.557 l
+98.068 4.629 l
+98.685 4.629 l
+98.921 5.967 l
+h
+103.933 3.248 m
+103.493 3.307 l
+103.117 3.314 102.816 3.138 102.581 2.778 c
+101.949 -0.838 l
+100.553 -0.838 l
+101.508 4.629 l
+102.816 4.629 l
+102.699 4.027 l
+102.864 4.292 103.026 4.475 103.184 4.586 c
+103.338 4.692 103.51 4.747 103.698 4.747 c
+103.805 4.747 103.948 4.722 104.125 4.674 c
+h
+105.304 -0.838 m
+103.907 -0.838 l
+104.848 4.629 l
+106.259 4.629 l
+h
+105.039 6.011 m
+105.039 6.247 105.113 6.437 105.26 6.585 c
+105.407 6.732 105.583 6.805 105.789 6.805 c
+106.003 6.813 106.186 6.746 106.333 6.599 c
+106.479 6.46 106.554 6.283 106.554 6.071 c
+106.554 5.835 106.479 5.644 106.333 5.497 c
+106.186 5.35 106.003 5.277 105.789 5.277 c
+105.573 5.265 105.392 5.328 105.245 5.468 c
+105.106 5.614 105.039 5.795 105.039 6.011 c
+108.876 -0.941 m
+108.413 -0.919 108.067 -0.706 107.832 -0.294 c
+107.655 -0.838 l
+106.348 -0.838 l
+107.7 6.923 l
+109.097 6.923 l
+108.567 4.174 l
+108.879 4.556 109.236 4.74 109.64 4.733 c
+110.118 4.722 110.478 4.542 110.713 4.189 c
+110.948 3.844 111.051 3.34 111.022 2.675 c
+111 1.899 110.905 1.227 110.728 0.661 c
+110.559 0.091 110.32 -0.324 110.007 -0.588 c
+109.692 -0.842 109.317 -0.96 108.876 -0.941 c
+109.655 2.66 m
+109.662 2.973 109.625 3.193 109.537 3.322 c
+109.457 3.457 109.324 3.528 109.141 3.528 c
+108.883 3.534 108.648 3.403 108.435 3.131 c
+108.009 0.617 l
+108.104 0.382 108.295 0.253 108.582 0.235 c
+109.1 0.205 109.409 0.577 109.508 1.352 c
+109.552 1.72 l
+h
+114.003 -0.339 m
+113.656 -0.75 113.257 -0.948 112.797 -0.941 c
+112.433 -0.941 112.143 -0.823 111.929 -0.588 c
+111.713 -0.346 111.591 -0.015 111.562 0.396 c
+111.54 0.631 111.54 0.86 111.562 1.087 c
+112.164 4.629 l
+113.546 4.629 l
+112.958 1.072 l
+112.944 0.823 l
+112.933 0.654 112.958 0.517 113.018 0.411 c
+113.076 0.312 113.168 0.257 113.297 0.249 c
+113.569 0.239 113.826 0.382 114.061 0.675 c
+114.751 4.629 l
+116.148 4.629 l
+115.208 -0.838 l
+113.899 -0.838 l
+h
+118.897 5.967 m
+118.662 4.629 l
+119.368 4.629 l
+119.191 3.557 l
+118.485 3.557 l
+118.015 0.793 l
+118.001 0.631 l
+117.989 0.404 118.082 0.294 118.279 0.294 c
+118.338 0.282 118.456 0.286 118.632 0.309 c
+118.5 -0.809 l
+118.294 -0.897 118.048 -0.941 117.766 -0.941 c
+117.361 -0.93 117.06 -0.786 116.854 -0.5 c
+116.648 -0.206 116.567 0.183 116.619 0.675 c
+117.089 3.557 l
+116.472 3.557 l
+116.648 4.629 l
+117.265 4.629 l
+117.5 5.967 l
+h
+121.396 -0.941 m
+120.955 -0.941 120.576 -0.834 120.264 -0.618 c
+119.959 -0.405 119.738 -0.103 119.603 0.278 c
+119.463 0.661 119.418 1.095 119.47 1.587 c
+119.514 1.955 l
+119.632 2.865 119.904 3.561 120.337 4.041 c
+120.779 4.519 121.34 4.751 122.028 4.733 c
+122.528 4.71 122.917 4.556 123.204 4.262 c
+123.487 3.968 123.652 3.549 123.703 3.013 c
+123.722 2.69 123.711 2.373 123.674 2.072 c
+123.586 1.411 l
+120.852 1.411 l
+120.829 1.271 120.826 1.135 120.837 0.999 c
+120.866 0.507 121.105 0.257 121.558 0.249 c
+121.976 0.239 122.385 0.4 122.778 0.735 c
+123.248 -0.133 l
+123.061 -0.389 122.799 -0.588 122.469 -0.736 c
+122.134 -0.882 121.778 -0.948 121.396 -0.941 c
+121.895 3.557 m
+121.492 3.564 121.212 3.307 121.058 2.778 c
+120.955 2.41 l
+122.337 2.41 l
+122.373 2.605 122.395 2.763 122.395 2.881 c
+122.402 3.31 122.237 3.534 121.895 3.557 c
+135.212 4.145 m
+135.565 4.546 135.948 4.74 136.359 4.733 c
+136.76 4.722 137.065 4.571 137.271 4.277 c
+137.484 3.991 137.594 3.594 137.594 3.087 c
+137.579 2.601 l
+136.991 -0.838 l
+135.595 -0.838 l
+136.168 2.616 l
+136.197 2.91 l
+136.205 3.322 136.058 3.528 135.757 3.528 c
+135.529 3.534 135.316 3.417 135.11 3.175 c
+134.404 -0.838 l
+133.008 -0.838 l
+134.36 6.923 l
+135.757 6.923 l
+h
+140.696 5.967 m
+140.461 4.629 l
+141.166 4.629 l
+140.99 3.557 l
+140.284 3.557 l
+139.814 0.793 l
+139.799 0.631 l
+139.788 0.404 139.879 0.294 140.078 0.294 c
+140.137 0.282 140.255 0.286 140.431 0.309 c
+140.299 -0.809 l
+140.093 -0.897 139.847 -0.941 139.563 -0.941 c
+139.16 -0.93 138.858 -0.786 138.653 -0.5 c
+138.447 -0.206 138.366 0.183 138.418 0.675 c
+138.888 3.557 l
+138.27 3.557 l
+138.447 4.629 l
+139.064 4.629 l
+139.299 5.967 l
+h
+143.742 5.967 m
+143.507 4.629 l
+144.213 4.629 l
+144.036 3.557 l
+143.33 3.557 l
+142.86 0.793 l
+142.846 0.631 l
+142.834 0.404 142.927 0.294 143.125 0.294 c
+143.183 0.282 143.301 0.286 143.478 0.309 c
+143.345 -0.809 l
+143.139 -0.897 142.894 -0.941 142.61 -0.941 c
+142.206 -0.93 141.905 -0.786 141.699 -0.5 c
+141.493 -0.206 141.412 0.183 141.464 0.675 c
+141.934 3.557 l
+141.317 3.557 l
+141.493 4.629 l
+142.111 4.629 l
+142.346 5.967 l
+h
+146.491 -0.941 m
+146.069 -0.93 145.734 -0.746 145.491 -0.383 c
+145.007 -2.94 l
+143.625 -2.94 l
+144.933 4.629 l
+146.212 4.629 l
+146.123 4.13 l
+146.454 4.542 146.836 4.74 147.27 4.733 c
+147.748 4.722 148.107 4.542 148.342 4.189 c
+148.578 3.836 148.681 3.326 148.652 2.66 c
+148.629 1.866 148.534 1.194 148.357 0.646 c
+148.182 0.106 147.931 -0.302 147.608 -0.574 c
+147.292 -0.838 146.921 -0.96 146.491 -0.941 c
+147.27 2.675 m
+147.27 2.987 147.226 3.208 147.137 3.336 c
+147.056 3.461 146.931 3.532 146.755 3.542 c
+146.509 3.542 146.285 3.417 146.079 3.175 c
+145.624 0.588 l
+145.73 0.371 145.921 0.257 146.197 0.249 c
+146.704 0.22 147.023 0.621 147.152 1.454 c
+147.255 2.484 l
+h
+151.499 0.661 m
+151.536 0.897 151.356 1.105 150.956 1.294 c
+150.551 1.477 150.25 1.65 150.044 1.807 c
+149.846 1.973 149.699 2.153 149.603 2.352 c
+149.515 2.557 149.475 2.786 149.485 3.042 c
+149.515 3.532 149.721 3.939 150.103 4.262 c
+150.485 4.586 150.948 4.74 151.499 4.733 c
+152.047 4.722 152.477 4.56 152.793 4.247 c
+153.105 3.931 153.256 3.52 153.248 3.013 c
+151.852 3.013 l
+151.86 3.248 151.831 3.414 151.764 3.513 c
+151.694 3.619 151.58 3.675 151.426 3.675 c
+151.257 3.675 151.118 3.615 151 3.498 c
+150.89 3.388 150.827 3.256 150.809 3.101 c
+150.757 2.884 150.927 2.69 151.309 2.513 c
+151.698 2.344 151.977 2.204 152.146 2.087 c
+152.646 1.753 152.874 1.297 152.837 0.72 c
+152.815 0.386 152.712 0.091 152.529 -0.162 c
+152.34 -0.42 152.087 -0.614 151.764 -0.75 c
+151.448 -0.886 151.106 -0.948 150.735 -0.941 c
+150.195 -0.93 149.757 -0.761 149.427 -0.427 c
+149.092 -0.085 148.928 0.345 148.928 0.866 c
+150.264 0.852 l
+150.254 0.588 150.294 0.396 150.382 0.278 c
+150.478 0.168 150.625 0.118 150.823 0.118 c
+151 0.118 151.147 0.161 151.264 0.249 c
+151.389 0.345 151.47 0.484 151.499 0.661 c
+153.595 -0.148 m
+153.595 0.095 153.668 0.294 153.815 0.44 c
+153.969 0.595 154.167 0.675 154.403 0.675 c
+154.638 0.675 154.829 0.602 154.976 0.455 c
+155.13 0.316 155.211 0.139 155.211 -0.074 c
+155.211 -0.32 155.126 -0.522 154.961 -0.676 c
+154.803 -0.823 154.612 -0.897 154.388 -0.897 c
+154.152 -0.897 153.961 -0.831 153.815 -0.691 c
+153.668 -0.545 153.595 -0.364 153.595 -0.148 c
+154.535 3.615 m
+154.535 3.858 154.609 4.056 154.755 4.203 c
+154.91 4.357 155.108 4.438 155.343 4.438 c
+155.579 4.438 155.77 4.365 155.916 4.218 c
+156.071 4.079 156.151 3.902 156.151 3.689 c
+156.151 3.443 156.067 3.241 155.902 3.087 c
+155.744 2.94 155.553 2.865 155.328 2.865 c
+155.093 2.865 154.902 2.932 154.755 3.072 c
+154.609 3.218 154.535 3.399 154.535 3.615 c
+156.5 -1.47 m
+155.442 -1.47 l
+158.97 6.526 l
+160.028 6.526 l
+h
+158.566 -1.47 m
+157.508 -1.47 l
+161.036 6.526 l
+162.094 6.526 l
+h
+164.02 -0.838 m
+163.997 -0.721 163.99 -0.581 163.99 -0.412 c
+163.674 -0.765 163.317 -0.941 162.917 -0.941 c
+162.494 -0.941 162.156 -0.79 161.903 -0.485 c
+161.657 -0.184 161.543 0.195 161.564 0.646 c
+161.594 1.234 161.818 1.69 162.241 2.013 c
+162.659 2.344 163.226 2.513 163.931 2.513 c
+164.342 2.513 l
+164.402 2.954 l
+164.416 3.175 l
+164.416 3.469 164.298 3.615 164.063 3.615 c
+163.74 3.623 163.542 3.417 163.475 2.998 c
+162.079 2.983 l
+162.108 3.501 162.322 3.924 162.726 4.247 c
+163.126 4.579 163.615 4.74 164.196 4.733 c
+164.732 4.722 165.144 4.549 165.431 4.218 c
+165.724 3.895 165.846 3.461 165.798 2.925 c
+165.342 0.147 l
+165.327 -0.133 l
+165.316 -0.368 165.342 -0.574 165.401 -0.75 c
+165.387 -0.838 l
+h
+163.314 0.176 m
+163.556 0.165 163.785 0.272 163.99 0.5 c
+164.24 1.646 l
+163.931 1.646 l
+163.667 1.635 163.45 1.547 163.284 1.381 c
+163.116 1.213 163.02 1.003 162.991 0.749 c
+162.991 0.558 l
+162.991 0.448 163.012 0.357 163.064 0.278 c
+163.122 0.209 163.203 0.176 163.314 0.176 c
+168.58 -0.941 m
+168.117 -0.919 167.771 -0.706 167.536 -0.294 c
+167.359 -0.838 l
+166.052 -0.838 l
+167.404 6.923 l
+168.801 6.923 l
+168.271 4.174 l
+168.583 4.556 168.94 4.74 169.344 4.733 c
+169.822 4.722 170.182 4.542 170.417 4.189 c
+170.652 3.844 170.755 3.34 170.725 2.675 c
+170.704 1.899 170.608 1.227 170.432 0.661 c
+170.263 0.091 170.024 -0.324 169.711 -0.588 c
+169.395 -0.842 169.021 -0.96 168.58 -0.941 c
+169.358 2.66 m
+169.366 2.973 169.329 3.193 169.241 3.322 c
+169.16 3.457 169.028 3.528 168.844 3.528 c
+168.587 3.534 168.352 3.403 168.138 3.131 c
+167.712 0.617 l
+167.808 0.382 167.999 0.253 168.286 0.235 c
+168.803 0.205 169.113 0.577 169.212 1.352 c
+169.256 1.72 l
+h
+173.823 4.733 m
+174.382 4.71 174.812 4.519 175.117 4.159 c
+175.429 3.806 175.602 3.326 175.631 2.719 c
+175.631 2.366 l
+175.581 1.308 175.327 0.484 174.867 -0.103 c
+174.405 -0.684 173.802 -0.96 173.059 -0.941 c
+172.626 -0.93 172.269 -0.817 171.986 -0.588 c
+171.7 -0.364 171.494 -0.056 171.369 0.338 c
+171.251 0.738 171.215 1.198 171.266 1.72 c
+171.295 1.984 l
+171.39 2.844 171.666 3.52 172.119 4.012 c
+172.566 4.512 173.136 4.751 173.823 4.733 c
+172.647 1.146 m
+172.647 0.558 172.824 0.253 173.177 0.235 c
+173.665 0.205 173.985 0.577 174.133 1.352 c
+174.176 1.72 l
+174.224 2.198 174.25 2.506 174.25 2.645 c
+174.25 3.222 174.066 3.528 173.706 3.557 c
+173.43 3.564 173.206 3.439 173.03 3.175 c
+172.861 2.917 172.755 2.547 172.707 2.057 c
+172.666 1.565 172.647 1.263 172.647 1.146 c
+178.615 -0.339 m
+178.27 -0.75 177.869 -0.948 177.41 -0.941 c
+177.046 -0.941 176.756 -0.823 176.543 -0.588 c
+176.327 -0.346 176.205 -0.015 176.175 0.396 c
+176.153 0.631 176.153 0.86 176.175 1.087 c
+176.778 4.629 l
+178.16 4.629 l
+177.572 1.072 l
+177.557 0.823 l
+177.546 0.654 177.572 0.517 177.63 0.411 c
+177.69 0.312 177.781 0.257 177.91 0.249 c
+178.182 0.239 178.439 0.382 178.675 0.675 c
+179.365 4.629 l
+180.761 4.629 l
+179.82 -0.838 l
+178.513 -0.838 l
+h
+183.514 5.967 m
+183.279 4.629 l
+183.984 4.629 l
+183.808 3.557 l
+183.103 3.557 l
+182.632 0.793 l
+182.617 0.631 l
+182.606 0.404 182.698 0.294 182.897 0.294 c
+182.955 0.282 183.073 0.286 183.249 0.309 c
+183.117 -0.809 l
+182.912 -0.897 182.665 -0.941 182.382 -0.941 c
+181.978 -0.93 181.677 -0.786 181.47 -0.5 c
+181.265 -0.206 181.185 0.183 181.235 0.675 c
+181.706 3.557 l
+181.089 3.557 l
+181.265 4.629 l
+181.883 4.629 l
+182.118 5.967 l
+h
+183.999 -0.148 m
+183.999 0.095 184.073 0.294 184.219 0.44 c
+184.374 0.595 184.572 0.675 184.807 0.675 c
+185.042 0.675 185.233 0.602 185.381 0.455 c
+185.535 0.316 185.616 0.139 185.616 -0.074 c
+185.616 -0.32 185.532 -0.522 185.366 -0.676 c
+185.208 -0.823 185.017 -0.897 184.793 -0.897 c
+184.558 -0.897 184.366 -0.831 184.219 -0.691 c
+184.073 -0.545 183.999 -0.364 183.999 -0.148 c
+189.137 4.733 m
+189.614 4.71 189.967 4.512 190.195 4.13 c
+190.371 4.629 l
+191.635 4.629 l
+190.71 -0.838 l
+190.61 -1.551 190.334 -2.095 189.886 -2.469 c
+189.445 -2.841 188.886 -3.017 188.21 -2.999 c
+187.916 -2.988 187.622 -2.926 187.328 -2.808 c
+187.034 -2.698 186.792 -2.544 186.608 -2.338 c
+187.167 -1.353 l
+187.45 -1.676 187.803 -1.841 188.225 -1.852 c
+188.82 -1.881 189.187 -1.548 189.328 -0.853 c
+189.43 -0.397 l
+189.107 -0.761 188.743 -0.941 188.343 -0.941 c
+187.872 -0.941 187.512 -0.761 187.269 -0.397 c
+187.024 -0.037 186.906 0.47 186.916 1.117 c
+186.916 1.506 186.953 1.929 187.034 2.381 c
+187.111 2.84 187.226 3.226 187.373 3.542 c
+187.755 4.355 188.343 4.751 189.137 4.733 c
+188.284 1.132 m
+188.284 0.551 188.468 0.257 188.842 0.249 c
+189.085 0.249 189.316 0.357 189.534 0.573 c
+190.004 3.189 l
+189.875 3.414 189.688 3.532 189.445 3.542 c
+188.857 3.571 188.497 3.09 188.372 2.102 c
+188.313 1.631 188.284 1.308 188.284 1.132 c
+193.054 -0.838 m
+191.657 -0.838 l
+192.598 4.629 l
+194.009 4.629 l
+h
+192.789 6.011 m
+192.789 6.247 192.863 6.437 193.01 6.585 c
+193.156 6.732 193.333 6.805 193.538 6.805 c
+193.752 6.813 193.935 6.746 194.083 6.599 c
+194.23 6.46 194.303 6.283 194.303 6.071 c
+194.303 5.835 194.23 5.644 194.083 5.497 c
+193.935 5.35 193.752 5.277 193.538 5.277 c
+193.322 5.265 193.142 5.328 192.995 5.468 c
+192.855 5.614 192.789 5.795 192.789 6.011 c
+196.909 5.967 m
+196.674 4.629 l
+197.379 4.629 l
+197.202 3.557 l
+196.497 3.557 l
+196.027 0.793 l
+196.012 0.631 l
+196.001 0.404 196.092 0.294 196.291 0.294 c
+196.35 0.282 196.468 0.286 196.644 0.309 c
+196.512 -0.809 l
+196.306 -0.897 196.059 -0.941 195.776 -0.941 c
+195.373 -0.93 195.071 -0.786 194.866 -0.5 c
+194.66 -0.206 194.579 0.183 194.631 0.675 c
+195.101 3.557 l
+194.483 3.557 l
+194.66 4.629 l
+195.277 4.629 l
+195.512 5.967 l
+h
+198.614 -0.838 m
+197.218 -0.838 l
+198.555 6.923 l
+199.966 6.923 l
+h
+202.259 -0.838 m
+202.237 -0.721 202.23 -0.581 202.23 -0.412 c
+201.914 -0.765 201.557 -0.941 201.156 -0.941 c
+200.734 -0.941 200.396 -0.79 200.142 -0.485 c
+199.896 -0.184 199.782 0.195 199.805 0.646 c
+199.834 1.234 200.058 1.69 200.48 2.013 c
+200.9 2.344 201.465 2.513 202.171 2.513 c
+202.583 2.513 l
+202.641 2.954 l
+202.656 3.175 l
+202.656 3.469 202.538 3.615 202.303 3.615 c
+201.98 3.623 201.781 3.417 201.715 2.998 c
+200.318 2.983 l
+200.348 3.501 200.561 3.924 200.965 4.247 c
+201.366 4.579 201.854 4.74 202.435 4.733 c
+202.972 4.722 203.383 4.549 203.67 4.218 c
+203.965 3.895 204.085 3.461 204.038 2.925 c
+203.582 0.147 l
+203.568 -0.133 l
+203.556 -0.368 203.582 -0.574 203.641 -0.75 c
+203.626 -0.838 l
+h
+201.553 0.176 m
+201.796 0.165 202.024 0.272 202.23 0.5 c
+202.479 1.646 l
+202.171 1.646 l
+201.906 1.635 201.69 1.547 201.524 1.381 c
+201.355 1.213 201.259 1.003 201.23 0.749 c
+201.23 0.558 l
+201.23 0.448 201.252 0.357 201.303 0.278 c
+201.362 0.209 201.443 0.176 201.553 0.176 c
+206.82 -0.941 m
+206.356 -0.919 206.011 -0.706 205.775 -0.294 c
+205.6 -0.838 l
+204.291 -0.838 l
+205.644 6.923 l
+207.04 6.923 l
+206.511 4.174 l
+206.823 4.556 207.179 4.74 207.584 4.733 c
+208.061 4.722 208.422 4.542 208.657 4.189 c
+208.892 3.844 208.995 3.34 208.965 2.675 c
+208.943 1.899 208.848 1.227 208.671 0.661 c
+208.503 0.091 208.264 -0.324 207.951 -0.588 c
+207.635 -0.842 207.26 -0.96 206.82 -0.941 c
+207.599 2.66 m
+207.606 2.973 207.569 3.193 207.481 3.322 c
+207.4 3.457 207.267 3.528 207.084 3.528 c
+206.826 3.534 206.591 3.403 206.378 3.131 c
+205.952 0.617 l
+206.047 0.382 206.238 0.253 206.525 0.235 c
+207.044 0.205 207.352 0.577 207.452 1.352 c
+207.495 1.72 l
+h
+209.432 -0.148 m
+209.432 0.095 209.505 0.294 209.652 0.44 c
+209.807 0.595 210.005 0.675 210.24 0.675 c
+210.475 0.675 210.666 0.602 210.814 0.455 c
+210.968 0.316 211.049 0.139 211.049 -0.074 c
+211.049 -0.32 210.965 -0.522 210.799 -0.676 c
+210.641 -0.823 210.45 -0.897 210.226 -0.897 c
+209.991 -0.897 209.8 -0.831 209.652 -0.691 c
+209.505 -0.545 209.432 -0.364 209.432 -0.148 c
+214.217 0.235 m
+214.599 0.224 214.838 0.5 214.937 1.058 c
+216.245 1.058 l
+216.187 0.448 215.959 -0.04 215.569 -0.412 c
+215.175 -0.786 214.702 -0.96 214.143 -0.941 c
+213.632 -0.93 213.224 -0.78 212.923 -0.485 c
+212.618 -0.192 212.438 0.213 212.379 0.735 c
+212.328 1.153 212.353 1.664 212.453 2.263 c
+212.548 2.869 212.736 3.373 213.012 3.777 c
+213.452 4.432 214.077 4.751 214.893 4.733 c
+215.441 4.71 215.863 4.512 216.157 4.13 c
+216.451 3.748 216.584 3.233 216.553 2.587 c
+215.231 2.587 l
+215.231 2.896 l
+215.22 3.314 215.058 3.534 214.745 3.557 c
+214.246 3.575 213.952 3.189 213.864 2.395 c
+213.761 1.484 l
+213.721 1.209 213.706 0.984 213.717 0.808 c
+213.746 0.434 213.912 0.242 214.217 0.235 c
+219.49 4.733 m
+220.048 4.71 220.478 4.519 220.783 4.159 c
+221.095 3.806 221.268 3.326 221.298 2.719 c
+221.298 2.366 l
+221.247 1.308 220.993 0.484 220.534 -0.103 c
+220.071 -0.684 219.468 -0.96 218.726 -0.941 c
+218.292 -0.93 217.935 -0.817 217.652 -0.588 c
+217.366 -0.364 217.16 -0.056 217.035 0.338 c
+216.918 0.738 216.881 1.198 216.933 1.72 c
+216.962 1.984 l
+217.057 2.844 217.332 3.52 217.785 4.012 c
+218.233 4.512 218.803 4.751 219.49 4.733 c
+218.314 1.146 m
+218.314 0.558 218.49 0.253 218.843 0.235 c
+219.331 0.205 219.651 0.577 219.799 1.352 c
+219.842 1.72 l
+219.89 2.198 219.917 2.506 219.917 2.645 c
+219.917 3.222 219.732 3.528 219.372 3.557 c
+219.096 3.564 218.872 3.439 218.696 3.175 c
+218.527 2.917 218.421 2.547 218.373 2.057 c
+218.332 1.565 218.314 1.263 218.314 1.146 c
+223.767 4.629 m
+223.68 4.116 l
+224.062 4.534 224.491 4.74 224.973 4.733 c
+225.491 4.71 225.829 4.469 225.987 3.998 c
+226.398 4.498 226.857 4.74 227.368 4.733 c
+227.758 4.722 228.052 4.575 228.251 4.292 c
+228.457 4.016 228.559 3.619 228.559 3.101 c
+228.53 2.645 l
+227.956 -0.838 l
+226.56 -0.838 l
+227.133 2.645 l
+227.163 2.925 l
+227.192 3.336 227.052 3.542 226.751 3.542 c
+226.516 3.542 226.3 3.373 226.105 3.042 c
+226.075 2.807 l
+225.443 -0.838 l
+224.046 -0.838 l
+224.62 2.645 l
+224.649 2.925 l
+224.679 3.336 224.546 3.542 224.252 3.542 c
+224.106 3.542 223.981 3.501 223.885 3.424 c
+223.786 3.343 223.697 3.252 223.62 3.145 c
+222.93 -0.838 l
+221.533 -0.838 l
+222.474 4.629 l
+h
+229.232 -1.47 m
+228.174 -1.47 l
+231.701 6.526 l
+232.76 6.526 l
+h
+f
+Q
+q 1 0 0 1 127.5482 553.4567 cm
+0 0 m
+-2.23 0 l
+-2.224 -16.602 l
+6.802 -16.602 l
+6.802 -14.548 l
+0.007 -14.548 l
+h
+f
+Q
+q 1 0 0 1 142.9453 539.769 cm
+0 0 m
+-0.559 -0.584 -1.496 -1.166 -2.764 -1.166 c
+-4.461 -1.166 -5.145 -0.331 -5.145 0.76 c
+-5.145 2.406 -4.006 3.193 -1.573 3.193 c
+-1.114 3.193 -0.379 3.141 0 3.068 c
+h
+-2.308 10.065 m
+-4.108 10.065 -5.762 9.425 -7.052 8.363 c
+-6.262 6.996 l
+-5.351 7.53 -4.233 8.062 -2.635 8.062 c
+-0.812 8.062 0 7.121 0 5.552 c
+0 4.74 l
+-0.357 4.818 -1.091 4.868 -1.548 4.868 c
+-5.45 4.868 -7.427 3.498 -7.427 0.635 c
+-7.427 -1.926 -5.858 -3.219 -3.473 -3.219 c
+-1.867 -3.219 -0.331 -2.484 0.202 -1.294 c
+0.61 -2.914 l
+2.179 -2.914 l
+2.179 5.578 l
+2.179 8.264 1.014 10.065 -2.308 10.065 c
+f
+Q
+q 1 0 0 1 152.3235 538.5263 cm
+0 0 m
+-0.834 0 -1.569 0.103 -2.128 0.357 c
+-2.128 8.037 l
+-1.368 8.669 -0.43 9.125 0.76 9.125 c
+2.917 9.125 3.752 7.603 3.752 5.145 c
+3.752 1.646 2.41 0 0 0 c
+0.937 11.308 m
+-1.056 11.308 -2.128 9.948 y
+-2.128 12.09 l
+-2.135 14.93 l
+-4.314 14.93 l
+-4.31 -1.267 l
+-3.219 -1.724 -1.723 -1.977 -0.1 -1.977 c
+4.056 -1.977 6.059 0.684 6.059 5.274 c
+6.059 8.896 4.207 11.308 0.937 11.308 c
+f
+Q
+q 1 0 0 1 103.2978 551.6561 cm
+0 0 m
+1.977 0 3.246 -0.658 4.083 -1.319 c
+5.042 0.342 l
+3.734 1.488 1.977 2.106 0.1 2.106 c
+-4.641 2.106 -7.96 -0.786 -7.96 -6.614 c
+-7.96 -12.725 -4.376 -15.106 -0.279 -15.106 c
+1.775 -15.106 3.524 -14.626 4.663 -14.144 c
+4.619 -7.617 l
+4.619 -5.564 l
+-1.466 -5.564 l
+-1.466 -7.617 l
+2.411 -7.617 l
+2.459 -12.571 l
+1.951 -12.824 1.066 -13.026 -0.128 -13.026 c
+-3.424 -13.026 -5.629 -10.954 -5.629 -6.589 c
+-5.629 -2.153 -3.347 0 0 0 c
+f
+Q
+q 1 0 0 1 118.9894 553.4567 cm
+0 0 m
+-2.183 0 l
+-2.176 -2.788 l
+-2.176 -12.421 l
+-2.176 -15.106 -1.01 -16.907 2.311 -16.907 c
+2.77 -16.907 3.219 -16.867 3.657 -16.786 c
+3.657 -14.827 l
+3.341 -14.875 3.002 -14.904 2.643 -14.904 c
+0.816 -14.904 0.004 -13.967 0.004 -12.394 c
+0.004 -5.755 l
+3.657 -5.755 l
+3.657 -3.928 l
+0.004 -3.928 l
+h
+f
+Q
+111.276 549.529 2.179 -12.675 re
+f
+111.276 553.457 2.179 -2.179 re
+f
+0 0.672 0.855 0 k
+q 1 0 0 1 85.9054 541.8301 cm
+0 0 m
+-2.815 8.665 l
+-8.397 25.841 l
+-8.683 26.723 -9.936 26.723 -10.223 25.841 c
+-15.805 8.665 l
+-34.341 8.665 l
+-39.923 25.841 l
+-40.209 26.723 -41.458 26.723 -41.745 25.841 c
+-47.328 8.665 l
+-50.146 0 l
+-50.403 -0.794 -50.12 -1.658 -49.447 -2.146 c
+-25.073 -19.854 l
+-0.698 -2.146 l
+-0.025 -1.658 0.257 -0.794 0 0 c
+f
+Q
+0.031 0.844 0.875 0.004 k
+q 1 0 0 1 60.8329 521.9758 cm
+0 0 m
+9.267 28.519 l
+-9.268 28.519 l
+h
+f
+Q
+0 0.672 0.855 0 k
+q 1 0 0 1 60.8329 521.9758 cm
+0 0 m
+-9.268 28.519 l
+-22.255 28.519 l
+h
+f
+Q
+0 0.43 0.871 0 k
+q 1 0 0 1 38.5778 550.4952 cm
+0 0 m
+-2.818 -8.665 l
+-3.075 -9.459 -2.792 -10.323 -2.119 -10.811 c
+22.255 -28.517 l
+h
+f
+Q
+0.031 0.844 0.875 0.004 k
+q 1 0 0 1 38.5778 550.4952 cm
+0 0 m
+12.987 0 l
+7.405 17.176 l
+7.119 18.058 5.869 18.058 5.582 17.176 c
+h
+f
+Q
+0 0.672 0.855 0 k
+q 1 0 0 1 60.8329 521.9758 cm
+0 0 m
+9.267 28.519 l
+22.258 28.519 l
+h
+f
+Q
+0 0.43 0.871 0 k
+q 1 0 0 1 83.0908 550.4952 cm
+0 0 m
+2.815 -8.665 l
+3.072 -9.459 2.789 -10.323 2.117 -10.811 c
+-22.258 -28.517 l
+h
+f
+Q
+0.031 0.844 0.875 0.004 k
+q 1 0 0 1 83.0908 550.4952 cm
+0 0 m
+-12.991 0 l
+-7.408 17.176 l
+-7.121 18.058 -5.868 18.058 -5.582 17.176 c
+h
+f
+Q
+0 0 0 0 k
+q 1 0 0 1 537.4641 538.8828 cm
+0 0 m
+-0.559 -0.706 l
+-2.168 -2.58 -4.513 -3.513 -7.599 -3.513 c
+-10.356 -3.513 -12.517 -2.601 -14.082 -0.779 c
+-15.64 1.044 -16.441 3.62 -16.478 6.953 c
+-16.478 11.936 l
+-16.478 15.501 -15.769 18.172 -14.346 19.946 c
+-12.917 21.718 -10.782 22.607 -7.938 22.607 c
+-5.519 22.607 -3.628 21.931 -2.263 20.579 c
+-0.893 19.227 -0.14 17.301 0 14.802 c
+-3.19 14.802 l
+-3.318 16.378 -3.759 17.613 -4.513 18.506 c
+-5.259 19.395 -6.394 19.844 -7.923 19.844 c
+-9.745 19.844 -11.083 19.245 -11.936 18.051 c
+-12.788 16.864 -13.23 14.963 -13.259 12.347 c
+-13.259 7.159 l
+-13.259 4.601 -12.773 2.635 -11.803 1.264 c
+-10.826 -0.099 -9.419 -0.779 -7.585 -0.779 c
+-5.872 -0.779 -4.565 -0.363 -3.66 0.47 c
+-3.19 0.912 l
+-3.19 6.776 l
+-7.834 6.776 l
+-7.834 9.496 l
+0 9.496 l
+h
+8.673 -3.16 -3.19 25.414 re
+28.677 19.491 m
+21.99 19.491 l
+21.99 -3.16 l
+18.8 -3.16 l
+18.8 19.491 l
+12.127 19.491 l
+12.127 22.254 l
+28.677 22.254 l
+h
+55.982 4.91 m
+55.834 2.183 55.062 0.096 53.674 -1.352 c
+52.292 -2.793 50.33 -3.513 47.794 -3.513 c
+45.244 -3.513 43.215 -2.543 41.709 -0.602 c
+40.209 1.338 39.459 3.961 39.459 7.277 c
+39.459 11.892 l
+39.459 15.192 40.228 17.804 41.767 19.726 c
+43.314 21.644 45.42 22.607 48.088 22.607 c
+50.536 22.607 52.431 21.865 53.776 20.388 c
+55.128 18.918 55.864 16.816 55.982 14.082 c
+52.747 14.082 l
+52.608 16.158 52.174 17.639 51.44 18.521 c
+50.704 19.403 49.587 19.844 48.088 19.844 c
+46.353 19.844 45.019 19.16 44.09 17.801 c
+43.156 16.449 42.694 14.464 42.694 11.848 c
+42.694 7.188 l
+42.694 4.619 43.123 2.65 43.987 1.279 c
+44.858 -0.095 46.125 -0.779 47.794 -0.779 c
+49.458 -0.779 50.653 -0.367 51.38 0.456 c
+52.115 1.279 52.571 2.764 52.747 4.91 c
+h
+77 -3.16 m
+73.796 -3.16 l
+73.796 8.584 l
+63.566 8.584 l
+63.566 -3.16 l
+60.362 -3.16 l
+60.362 22.254 l
+63.566 22.254 l
+63.566 11.333 l
+73.796 11.333 l
+73.796 22.254 l
+77 22.254 l
+h
+94.838 8.584 m
+85.858 8.584 l
+85.858 -0.426 l
+96.323 -0.426 l
+96.323 -3.16 l
+82.652 -3.16 l
+82.652 22.254 l
+96.146 22.254 l
+96.146 19.491 l
+85.858 19.491 l
+85.858 11.333 l
+94.838 11.333 l
+h
+112.319 3.469 m
+103.734 3.469 l
+101.75 -3.16 l
+98.473 -3.16 l
+106.66 22.254 l
+109.394 22.254 l
+117.61 -3.16 l
+114.318 -3.16 l
+h
+104.573 6.232 m
+111.495 6.232 l
+108.027 17.786 l
+h
+133.754 19.491 m
+127.066 19.491 l
+127.066 -3.16 l
+123.877 -3.16 l
+123.877 19.491 l
+117.203 19.491 l
+117.203 22.254 l
+133.754 22.254 l
+h
+156.221 3.263 m
+156.221 4.528 155.876 5.498 155.193 6.174 c
+154.505 6.849 153.267 7.504 151.474 8.143 c
+149.68 8.79 148.306 9.467 147.358 10.172 c
+146.406 10.878 145.697 11.678 145.227 12.582 c
+144.756 13.483 144.521 14.512 144.521 15.669 c
+144.521 17.687 145.19 19.348 146.535 20.652 c
+147.876 21.953 149.636 22.607 151.812 22.607 c
+153.3 22.607 154.626 22.269 155.795 21.593 c
+156.96 20.924 157.857 19.998 158.485 18.815 c
+159.11 17.628 159.426 16.324 159.426 14.905 c
+156.221 14.905 l
+156.221 16.47 155.839 17.687 155.075 18.55 c
+154.318 19.41 153.23 19.844 151.812 19.844 c
+150.526 19.844 149.526 19.48 148.813 18.756 c
+148.107 18.04 147.754 17.029 147.754 15.728 c
+147.754 14.659 148.137 13.762 148.901 13.039 c
+149.673 12.31 150.86 11.664 152.458 11.098 c
+154.964 10.275 156.754 9.253 157.824 8.04 c
+158.9 6.835 159.44 5.251 159.44 3.293 c
+159.44 1.235 158.768 -0.419 157.427 -1.66 c
+156.093 -2.896 154.274 -3.513 151.974 -3.513 c
+150.493 -3.513 149.125 -3.189 147.872 -2.543 c
+146.626 -1.896 145.645 -0.992 144.932 0.177 c
+144.216 1.353 143.86 2.694 143.86 4.204 c
+147.064 4.204 l
+147.064 2.635 147.505 1.415 148.387 0.544 c
+149.269 -0.33 150.463 -0.764 151.974 -0.764 c
+153.385 -0.764 154.443 -0.407 155.149 0.309 c
+155.862 1.033 156.221 2.018 156.221 3.263 c
+180.325 -3.16 m
+177.12 -3.16 l
+177.12 8.584 l
+166.889 8.584 l
+166.889 -3.16 l
+163.685 -3.16 l
+163.685 22.254 l
+166.889 22.254 l
+166.889 11.333 l
+177.12 11.333 l
+177.12 22.254 l
+180.325 22.254 l
+h
+198.161 8.584 m
+189.181 8.584 l
+189.181 -0.426 l
+199.646 -0.426 l
+199.646 -3.16 l
+185.976 -3.16 l
+185.976 22.254 l
+199.47 22.254 l
+199.47 19.491 l
+189.181 19.491 l
+189.181 11.333 l
+198.161 11.333 l
+h
+215.969 8.584 m
+206.988 8.584 l
+206.988 -0.426 l
+217.454 -0.426 l
+217.454 -3.16 l
+203.784 -3.16 l
+203.784 22.254 l
+217.278 22.254 l
+217.278 19.491 l
+206.988 19.491 l
+206.988 11.333 l
+215.969 11.333 l
+h
+236.798 19.491 m
+230.11 19.491 l
+230.11 -3.16 l
+226.92 -3.16 l
+226.92 19.491 l
+220.247 19.491 l
+220.247 22.254 l
+236.798 22.254 l
+h
+f
+Q
+0.793 0.801 0.129 0.016 k
+35.668 501.669 238.665 -21.46 re
+f
+0 0 0 0 k
+q 1 0 0 1 142.3903 490.78 cm
+0 0 m
+0.47 4.763 l
+4.997 4.763 l
+4.997 3.205 l
+1.955 3.205 l
+1.793 1.206 l
+2.146 1.441 2.506 1.559 2.881 1.559 c
+3.653 1.559 4.248 1.283 4.659 0.736 c
+5.078 0.184 5.292 -0.595 5.292 -1.602 c
+5.292 -2.535 5.041 -3.289 4.542 -3.865 c
+4.042 -4.446 3.381 -4.733 2.558 -4.733 c
+2.057 -4.733 1.595 -4.615 1.176 -4.38 c
+0.754 -4.145 0.419 -3.821 0.176 -3.41 c
+-0.059 -2.991 -0.177 -2.513 -0.177 -1.984 c
+1.617 -1.984 l
+1.646 -2.377 1.738 -2.682 1.897 -2.896 c
+2.061 -3.112 2.278 -3.218 2.543 -3.218 c
+2.837 -3.218 3.065 -3.079 3.233 -2.792 c
+3.399 -2.499 3.484 -2.065 3.484 -1.484 c
+3.484 -0.947 3.385 -0.54 3.19 -0.264 c
+2.992 0.008 2.72 0.148 2.367 0.148 c
+2.021 0.148 1.756 0.03 1.573 -0.205 c
+1.455 -0.367 l
+h
+6.868 -3.674 m
+6.868 -3.38 6.963 -3.141 7.162 -2.954 c
+7.357 -2.77 7.611 -2.675 7.927 -2.675 c
+8.228 -2.675 8.478 -2.77 8.676 -2.954 c
+8.882 -3.141 8.985 -3.38 8.985 -3.674 c
+8.985 -3.979 8.882 -4.226 8.676 -4.409 c
+8.478 -4.586 8.228 -4.674 7.927 -4.674 c
+7.622 -4.674 7.368 -4.582 7.162 -4.394 c
+6.963 -4.211 6.868 -3.968 6.868 -3.674 c
+16.709 -1.176 m
+15.769 -1.176 l
+15.769 -4.6 l
+13.887 -4.6 l
+13.887 4.763 l
+16.9 4.763 l
+17.849 4.763 18.58 4.516 19.09 4.028 c
+19.609 3.535 19.869 2.841 19.869 1.941 c
+19.869 0.695 19.418 -0.176 18.518 -0.675 c
+20.149 -4.512 l
+20.149 -4.6 l
+18.121 -4.6 l
+h
+15.769 0.397 m
+16.841 0.397 l
+17.224 0.397 17.506 0.518 17.694 0.765 c
+17.878 1.018 17.973 1.357 17.973 1.779 c
+17.973 2.72 17.61 3.19 16.885 3.19 c
+15.769 3.19 l
+h
+26.223 -0.544 m
+23.283 -0.544 l
+23.283 -3.027 l
+26.767 -3.027 l
+26.767 -4.6 l
+21.387 -4.6 l
+21.387 4.763 l
+26.752 4.763 l
+26.752 3.19 l
+23.283 3.19 l
+23.283 0.971 l
+26.223 0.971 l
+h
+31.085 -2.028 m
+32.658 4.763 l
+34.759 4.763 l
+32.07 -4.6 l
+30.1 -4.6 l
+27.41 4.763 l
+29.512 4.763 l
+h
+37.846 -4.6 -1.896 9.363 re
+44.373 -0.544 m
+41.433 -0.544 l
+41.433 -3.027 l
+44.917 -3.027 l
+44.917 -4.6 l
+39.536 -4.6 l
+39.536 4.763 l
+44.901 4.763 l
+44.901 3.19 l
+41.433 3.19 l
+41.433 0.971 l
+44.373 0.971 l
+h
+52.267 -1.117 m
+53.148 4.763 l
+55.029 4.763 l
+53.354 -4.6 l
+51.458 -4.6 l
+50.37 0.912 l
+49.297 -4.6 l
+47.386 -4.6 l
+45.711 4.763 l
+47.592 4.763 l
+48.473 -1.117 l
+49.576 4.763 l
+51.164 4.763 l
+h
+62.284 0.559 m
+63.695 4.763 l
+65.753 4.763 l
+63.239 -1.205 l
+63.239 -4.6 l
+61.328 -4.6 l
+61.328 -1.205 l
+58.814 4.763 l
+60.872 4.763 l
+h
+73.231 -0.764 m
+73.231 -2.021 72.929 -2.994 72.334 -3.689 c
+71.735 -4.388 70.912 -4.733 69.865 -4.733 c
+68.813 -4.733 67.986 -4.391 67.38 -3.704 c
+66.781 -3.009 66.476 -2.042 66.469 -0.808 c
+66.469 0.794 l
+66.469 2.076 66.767 3.08 67.365 3.807 c
+67.961 4.532 68.792 4.896 69.85 4.896 c
+70.887 4.896 71.706 4.535 72.304 3.822 c
+72.911 3.117 73.22 2.12 73.231 0.838 c
+h
+71.334 0.809 m
+71.334 1.65 71.209 2.278 70.967 2.691 c
+70.731 3.102 70.357 3.308 69.85 3.308 c
+69.35 3.308 68.975 3.105 68.732 2.705 c
+68.497 2.311 68.373 1.713 68.365 0.912 c
+68.365 -0.764 l
+68.365 -1.579 68.487 -2.182 68.732 -2.572 c
+68.975 -2.965 69.354 -3.16 69.865 -3.16 c
+70.353 -3.16 70.717 -2.969 70.952 -2.587 c
+71.195 -2.204 71.323 -1.616 71.334 -0.823 c
+h
+80.907 4.763 m
+80.907 -1.72 l
+80.896 -2.69 80.628 -3.436 80.099 -3.954 c
+79.57 -4.475 78.809 -4.733 77.821 -4.733 c
+76.821 -4.733 76.057 -4.475 75.527 -3.954 c
+74.999 -3.424 74.733 -2.668 74.733 -1.675 c
+74.733 4.763 l
+76.63 4.763 l
+76.63 -1.675 l
+76.63 -2.215 76.711 -2.597 76.88 -2.822 c
+77.056 -3.05 77.368 -3.16 77.821 -3.16 c
+78.269 -3.16 78.577 -3.05 78.746 -2.822 c
+78.912 -2.597 79 -2.23 79.011 -1.72 c
+79.011 4.763 l
+h
+85.398 -1.176 m
+84.457 -1.176 l
+84.457 -4.6 l
+82.575 -4.6 l
+82.575 4.763 l
+85.588 4.763 l
+86.537 4.763 87.269 4.516 87.779 4.028 c
+88.297 3.535 88.558 2.841 88.558 1.941 c
+88.558 0.695 88.106 -0.176 87.206 -0.675 c
+88.838 -4.512 l
+88.838 -4.6 l
+86.809 -4.6 l
+h
+84.457 0.397 m
+85.53 0.397 l
+85.912 0.397 86.195 0.518 86.382 0.765 c
+86.566 1.018 86.662 1.357 86.662 1.779 c
+86.662 2.72 86.298 3.19 85.574 3.19 c
+84.457 3.19 l
+h
+99.281 -1.117 m
+100.163 4.763 l
+102.045 4.763 l
+100.368 -4.6 l
+98.473 -4.6 l
+97.384 0.912 l
+96.312 -4.6 l
+94.401 -4.6 l
+92.725 4.763 l
+94.606 4.763 l
+95.489 -1.117 l
+96.591 4.763 l
+98.178 4.763 l
+h
+109.956 -0.764 m
+109.956 -2.021 109.654 -2.994 109.06 -3.689 c
+108.461 -4.388 107.638 -4.733 106.59 -4.733 c
+105.539 -4.733 104.713 -4.391 104.106 -3.704 c
+103.507 -3.009 103.202 -2.042 103.194 -0.808 c
+103.194 0.794 l
+103.194 2.076 103.493 3.08 104.091 3.807 c
+104.686 4.532 105.517 4.896 106.575 4.896 c
+107.612 4.896 108.431 4.535 109.03 3.822 c
+109.637 3.117 109.945 2.12 109.956 0.838 c
+h
+108.06 0.809 m
+108.06 1.65 107.935 2.278 107.693 2.691 c
+107.458 3.102 107.082 3.308 106.575 3.308 c
+106.076 3.308 105.701 3.105 105.459 2.705 c
+105.224 2.311 105.098 1.713 105.091 0.912 c
+105.091 -0.764 l
+105.091 -1.579 105.212 -2.182 105.459 -2.572 c
+105.701 -2.965 106.08 -3.16 106.59 -3.16 c
+107.079 -3.16 107.443 -2.969 107.678 -2.587 c
+107.921 -2.204 108.049 -1.616 108.06 -0.823 c
+h
+114.369 -1.176 m
+113.429 -1.176 l
+113.429 -4.6 l
+111.547 -4.6 l
+111.547 4.763 l
+114.56 4.763 l
+115.509 4.763 116.24 4.516 116.75 4.028 c
+117.269 3.535 117.53 2.841 117.53 1.941 c
+117.53 0.695 117.078 -0.176 116.178 -0.675 c
+117.809 -4.512 l
+117.809 -4.6 l
+115.781 -4.6 l
+h
+113.429 0.397 m
+114.502 0.397 l
+114.884 0.397 115.167 0.518 115.354 0.765 c
+115.538 1.018 115.634 1.357 115.634 1.779 c
+115.634 2.72 115.27 3.19 114.546 3.19 c
+113.429 3.19 l
+h
+121.689 -0.984 m
+120.94 -1.925 l
+120.94 -4.6 l
+119.044 -4.6 l
+119.044 4.763 l
+120.94 4.763 l
+120.94 0.676 l
+121.543 1.69 l
+123.277 4.763 l
+125.6 4.763 l
+122.909 0.647 l
+125.644 -4.6 l
+123.395 -4.6 l
+h
+f
+Q
+0.113 0.082 0.09 0 k
+35.668 471.367 238.665 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 40.8563 464.5277 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.771 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.279 -3.219 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.985 c
+-3.322 2.18 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.003 -2.469 3.043 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.182 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.455 c
+-2.26 2.425 -2.319 2.385 -2.366 2.338 c
+-2.406 2.297 -2.437 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.44 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.014 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.147 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.596 4.935 -0.411 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.632 5.137 1.779 c
+5.245 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.152 2.22 c
+8.004 2.22 l
+7.993 2.139 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.871 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.279 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.279 5.835 1.162 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.22 l
+13.644 2.22 l
+13.924 3.117 l
+14.497 3.117 l
+14.497 2.22 l
+15.732 2.22 l
+15.732 1.602 l
+14.497 1.602 l
+14.497 -0.103 l
+14.497 -0.324 l
+14.504 -0.393 14.527 -0.455 14.556 -0.515 c
+14.593 -0.565 14.648 -0.61 14.718 -0.646 c
+14.795 -0.676 14.909 -0.691 15.056 -0.691 c
+15.192 -0.691 15.327 -0.687 15.468 -0.676 c
+15.603 -0.658 15.736 -0.632 15.865 -0.602 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.23 15.629 -1.249 c
+15.549 -1.261 15.471 -1.267 15.394 -1.278 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.041 -1.301 14.942 -1.308 14.835 -1.308 c
+14.648 -1.308 14.486 -1.294 14.35 -1.264 c
+14.221 -1.228 14.107 -1.183 14.012 -1.132 c
+13.924 -1.084 13.85 -1.025 13.791 -0.955 c
+13.733 -0.878 13.689 -0.801 13.66 -0.72 c
+13.63 -0.632 13.608 -0.544 13.6 -0.455 c
+13.59 -0.36 13.586 -0.264 13.586 -0.176 c
+h
+23.221 -0.646 m
+24.353 -0.646 l
+24.353 -1.264 l
+21.045 -1.264 l
+21.045 -0.646 l
+22.31 -0.646 l
+22.31 2.896 l
+21.384 2.896 l
+21.384 3.514 l
+23.221 3.514 l
+h
+28.384 0.485 m
+28.384 0.21 28.347 -0.04 28.281 -0.264 c
+28.212 -0.482 28.108 -0.669 27.973 -0.823 c
+27.833 -0.981 27.657 -1.103 27.443 -1.19 c
+27.227 -1.278 26.973 -1.323 26.679 -1.323 c
+26.404 -1.323 26.157 -1.278 25.944 -1.19 c
+25.739 -1.103 25.566 -0.981 25.43 -0.823 c
+25.29 -0.669 25.187 -0.482 25.121 -0.264 c
+25.051 -0.04 25.018 0.21 25.018 0.485 c
+25.018 0.738 25.047 0.974 25.106 1.191 c
+25.172 1.415 25.275 1.606 25.415 1.764 c
+25.55 1.929 25.727 2.058 25.944 2.146 c
+26.157 2.234 26.414 2.278 26.709 2.278 c
+27.021 2.278 27.281 2.234 27.487 2.146 c
+27.701 2.058 27.873 1.929 28.002 1.764 c
+28.138 1.606 28.237 1.415 28.296 1.191 c
+28.355 0.974 28.384 0.738 28.384 0.485 c
+27.429 0.485 m
+27.429 0.691 27.414 0.867 27.385 1.014 c
+27.362 1.162 27.326 1.282 27.267 1.382 c
+27.208 1.477 27.135 1.548 27.046 1.588 c
+26.959 1.635 26.848 1.661 26.724 1.661 c
+26.458 1.661 26.267 1.562 26.15 1.367 c
+26.032 1.18 25.974 0.886 25.974 0.485 c
+25.974 0.063 26.032 -0.243 26.15 -0.426 c
+26.267 -0.613 26.444 -0.706 26.679 -0.706 c
+26.804 -0.706 26.918 -0.687 27.017 -0.646 c
+27.113 -0.599 27.194 -0.525 27.252 -0.426 c
+27.318 -0.33 27.362 -0.206 27.385 -0.058 c
+27.414 0.088 27.429 0.268 27.429 0.485 c
+30.769 -2.66 m
+30.552 -2.66 30.361 -2.635 30.196 -2.587 c
+30.027 -2.547 29.887 -2.484 29.77 -2.396 c
+29.652 -2.315 29.552 -2.219 29.475 -2.102 c
+29.406 -1.984 29.358 -1.855 29.328 -1.72 c
+30.225 -1.617 l
+30.262 -1.753 30.331 -1.859 30.431 -1.94 c
+30.526 -2.028 30.651 -2.072 30.799 -2.072 c
+30.886 -2.072 30.967 -2.057 31.048 -2.028 c
+31.125 -1.999 31.195 -1.944 31.254 -1.866 c
+31.313 -1.797 31.357 -1.705 31.387 -1.587 c
+31.424 -1.469 31.445 -1.323 31.445 -1.147 c
+31.445 -0.955 l
+31.445 -0.889 31.449 -0.831 31.46 -0.779 c
+31.46 -0.588 l
+31.445 -0.588 l
+31.346 -0.816 31.202 -0.977 31.019 -1.072 c
+30.832 -1.172 30.626 -1.22 30.402 -1.22 c
+30.196 -1.22 30.012 -1.183 29.858 -1.103 c
+29.71 -1.014 29.582 -0.897 29.475 -0.75 c
+29.376 -0.596 29.303 -0.411 29.255 -0.206 c
+29.203 0.008 29.182 0.243 29.182 0.5 c
+29.182 0.771 29.203 1.018 29.255 1.235 c
+29.313 1.448 29.394 1.632 29.505 1.779 c
+29.612 1.933 29.743 2.051 29.901 2.132 c
+30.056 2.22 30.244 2.263 30.46 2.263 c
+30.556 2.263 30.655 2.253 30.755 2.234 c
+30.85 2.213 30.938 2.18 31.019 2.132 c
+31.107 2.08 31.185 2.018 31.254 1.941 c
+31.331 1.86 31.393 1.768 31.445 1.661 c
+31.46 1.661 l
+31.46 1.808 l
+31.467 1.867 31.474 1.918 31.474 1.97 c
+31.482 2.028 31.489 2.076 31.489 2.117 c
+31.497 2.165 31.507 2.198 31.519 2.22 c
+32.371 2.22 l
+32.36 2.139 32.349 2.028 32.342 1.881 c
+32.342 1.411 l
+32.342 -1.161 l
+32.342 -1.415 32.305 -1.635 32.239 -1.822 c
+32.17 -2.007 32.066 -2.161 31.931 -2.279 c
+31.79 -2.404 31.625 -2.499 31.43 -2.558 c
+31.232 -2.624 31.011 -2.66 30.769 -2.66 c
+31.46 0.53 m
+31.46 0.742 31.434 0.919 31.387 1.058 c
+31.346 1.205 31.291 1.323 31.225 1.411 c
+31.166 1.5 31.096 1.558 31.019 1.588 c
+30.938 1.625 30.861 1.646 30.784 1.646 c
+30.684 1.646 30.593 1.621 30.504 1.573 c
+30.424 1.532 30.358 1.463 30.298 1.367 c
+30.248 1.279 30.203 1.162 30.167 1.014 c
+30.137 0.875 30.122 0.706 30.122 0.5 c
+30.122 0.125 30.181 -0.154 30.298 -0.338 c
+30.416 -0.515 30.578 -0.602 30.784 -0.602 c
+30.85 -0.602 30.923 -0.588 31.004 -0.559 c
+31.092 -0.522 31.166 -0.463 31.225 -0.382 c
+31.291 -0.294 31.346 -0.176 31.387 -0.029 c
+31.434 0.118 31.46 0.301 31.46 0.53 c
+38.115 -2.631 m
+38.115 3.514 l
+40.041 3.514 l
+40.041 2.896 l
+38.967 2.896 l
+38.967 -2.013 l
+40.041 -2.013 l
+40.041 -2.631 l
+h
+42.013 0.838 1.867 -0.794 re
+42.013 0.044 m
+47.677 -1.264 m
+47.677 0.721 l
+47.677 1.022 47.632 1.242 47.544 1.382 c
+47.463 1.529 47.328 1.602 47.133 1.602 c
+47.023 1.602 46.919 1.577 46.824 1.529 c
+46.736 1.477 46.655 1.411 46.589 1.323 c
+46.53 1.235 46.479 1.124 46.441 1 c
+46.412 0.882 46.398 0.75 46.398 0.603 c
+46.398 -1.264 l
+45.487 -1.264 l
+45.487 1.44 l
+45.487 1.661 l
+45.487 1.75 45.479 1.827 45.472 1.897 c
+45.472 2.087 l
+45.472 2.22 l
+46.324 2.22 l
+46.331 2.19 46.339 2.146 46.339 2.087 c
+46.339 1.897 l
+46.346 1.827 46.354 1.756 46.354 1.691 c
+46.362 1.621 46.368 1.565 46.368 1.529 c
+46.383 1.529 l
+46.501 1.793 46.651 1.985 46.838 2.103 c
+47.023 2.22 47.243 2.278 47.5 2.278 c
+47.684 2.278 47.846 2.249 47.985 2.19 c
+48.122 2.132 48.235 2.043 48.323 1.926 c
+48.411 1.808 48.474 1.665 48.515 1.5 c
+48.562 1.341 48.588 1.154 48.588 0.941 c
+48.588 -1.264 l
+h
+55.17 -1.323 m
+54.883 -1.323 54.64 -1.282 54.435 -1.205 c
+54.229 -1.117 54.056 -0.995 53.92 -0.837 c
+53.78 -0.683 53.678 -0.496 53.612 -0.279 c
+53.541 -0.055 53.508 0.191 53.508 0.456 c
+53.508 0.75 53.541 1.007 53.612 1.235 c
+53.689 1.459 53.795 1.646 53.934 1.793 c
+54.082 1.947 54.258 2.065 54.464 2.146 c
+54.67 2.234 54.905 2.278 55.17 2.278 c
+55.394 2.278 55.596 2.249 55.772 2.19 c
+55.949 2.132 56.099 2.047 56.228 1.941 c
+56.353 1.841 56.456 1.72 56.537 1.573 c
+56.614 1.434 56.669 1.282 56.698 1.118 c
+55.787 1.073 l
+55.758 1.249 55.688 1.389 55.581 1.5 c
+55.482 1.606 55.339 1.661 55.155 1.661 c
+54.908 1.661 54.732 1.558 54.626 1.353 c
+54.515 1.154 54.464 0.867 54.464 0.485 c
+54.464 -0.309 54.699 -0.706 55.17 -0.706 c
+55.335 -0.706 55.478 -0.654 55.596 -0.544 c
+55.713 -0.437 55.787 -0.276 55.816 -0.058 c
+56.728 -0.103 l
+56.698 -0.272 56.643 -0.426 56.566 -0.573 c
+56.496 -0.72 56.394 -0.852 56.257 -0.97 c
+56.128 -1.08 55.97 -1.168 55.787 -1.234 c
+55.611 -1.294 55.405 -1.323 55.17 -1.323 c
+60.876 0.485 m
+60.876 0.21 60.839 -0.04 60.774 -0.264 c
+60.704 -0.482 60.601 -0.669 60.465 -0.823 c
+60.325 -0.981 60.149 -1.103 59.935 -1.19 c
+59.719 -1.278 59.465 -1.323 59.172 -1.323 c
+58.896 -1.323 58.649 -1.278 58.436 -1.19 c
+58.231 -1.103 58.058 -0.981 57.922 -0.823 c
+57.782 -0.669 57.68 -0.482 57.613 -0.264 c
+57.543 -0.04 57.51 0.21 57.51 0.485 c
+57.51 0.738 57.539 0.974 57.599 1.191 c
+57.665 1.415 57.768 1.606 57.907 1.764 c
+58.043 1.929 58.22 2.058 58.436 2.146 c
+58.649 2.234 58.906 2.278 59.201 2.278 c
+59.513 2.278 59.774 2.234 59.98 2.146 c
+60.193 2.058 60.365 1.929 60.494 1.764 c
+60.63 1.606 60.729 1.415 60.788 1.191 c
+60.847 0.974 60.876 0.738 60.876 0.485 c
+59.921 0.485 m
+59.921 0.691 59.906 0.867 59.877 1.014 c
+59.855 1.162 59.818 1.282 59.76 1.382 c
+59.7 1.477 59.627 1.548 59.538 1.588 c
+59.451 1.635 59.34 1.661 59.216 1.661 c
+58.95 1.661 58.76 1.562 58.642 1.367 c
+58.524 1.18 58.466 0.886 58.466 0.485 c
+58.466 0.063 58.524 -0.243 58.642 -0.426 c
+58.76 -0.613 58.936 -0.706 59.172 -0.706 c
+59.297 -0.706 59.411 -0.687 59.509 -0.646 c
+59.605 -0.599 59.686 -0.525 59.744 -0.426 c
+59.81 -0.33 59.855 -0.206 59.877 -0.058 c
+59.906 0.088 59.921 0.268 59.921 0.485 c
+62.615 2.22 m
+62.615 0.264 l
+62.615 0.125 62.622 0 62.644 -0.118 c
+62.663 -0.228 62.696 -0.32 62.746 -0.397 c
+62.794 -0.478 62.854 -0.54 62.923 -0.588 c
+62.989 -0.628 63.074 -0.646 63.173 -0.646 c
+63.261 -0.646 63.342 -0.628 63.423 -0.588 c
+63.511 -0.54 63.585 -0.47 63.644 -0.382 c
+63.702 -0.287 63.746 -0.176 63.776 -0.058 c
+63.812 0.066 63.835 0.206 63.835 0.353 c
+63.835 2.22 l
+64.731 2.22 l
+64.731 -0.484 l
+64.731 -0.72 l
+64.739 -0.801 64.746 -0.878 64.746 -0.955 c
+64.746 -1.147 l
+64.753 -1.198 64.76 -1.234 64.76 -1.264 c
+63.908 -1.264 l
+63.897 -1.234 63.886 -1.198 63.879 -1.147 c
+63.879 -0.955 l
+63.879 -0.889 63.872 -0.819 63.864 -0.75 c
+63.864 -0.573 l
+63.849 -0.573 l
+63.731 -0.837 63.577 -1.029 63.394 -1.147 c
+63.217 -1.264 63.015 -1.323 62.791 -1.323 c
+62.586 -1.323 62.412 -1.286 62.276 -1.22 c
+62.137 -1.153 62.027 -1.058 61.938 -0.941 c
+61.857 -0.823 61.799 -0.687 61.762 -0.529 c
+61.732 -0.364 61.718 -0.187 61.718 0 c
+61.718 2.22 l
+h
+67.983 -1.264 m
+67.983 0.721 l
+67.983 1.022 67.939 1.242 67.851 1.382 c
+67.77 1.529 67.634 1.602 67.44 1.602 c
+67.33 1.602 67.226 1.577 67.131 1.529 c
+67.043 1.477 66.962 1.411 66.896 1.323 c
+66.837 1.235 66.785 1.124 66.748 1 c
+66.719 0.882 66.705 0.75 66.705 0.603 c
+66.705 -1.264 l
+65.793 -1.264 l
+65.793 1.44 l
+65.793 1.661 l
+65.793 1.75 65.786 1.827 65.778 1.897 c
+65.778 2.087 l
+65.778 2.22 l
+66.631 2.22 l
+66.638 2.19 66.646 2.146 66.646 2.087 c
+66.646 1.897 l
+66.653 1.827 66.661 1.756 66.661 1.691 c
+66.667 1.621 66.675 1.565 66.675 1.529 c
+66.69 1.529 l
+66.808 1.793 66.958 1.985 67.145 2.103 c
+67.33 2.22 67.55 2.278 67.807 2.278 c
+67.991 2.278 68.153 2.249 68.292 2.19 c
+68.428 2.132 68.542 2.043 68.63 1.926 c
+68.718 1.808 68.781 1.665 68.822 1.5 c
+68.869 1.341 68.895 1.154 68.895 0.941 c
+68.895 -1.264 l
+h
+70.457 1.602 m
+69.913 1.602 l
+69.913 2.22 l
+70.501 2.22 l
+70.78 3.117 l
+71.353 3.117 l
+71.353 2.22 l
+72.587 2.22 l
+72.587 1.602 l
+71.353 1.602 l
+71.353 -0.103 l
+71.353 -0.324 l
+71.361 -0.393 71.382 -0.455 71.412 -0.515 c
+71.448 -0.565 71.504 -0.61 71.573 -0.646 c
+71.65 -0.676 71.764 -0.691 71.912 -0.691 c
+72.047 -0.691 72.184 -0.687 72.323 -0.676 c
+72.46 -0.658 72.591 -0.632 72.72 -0.602 c
+72.72 -1.205 l
+72.639 -1.216 72.562 -1.23 72.485 -1.249 c
+72.404 -1.261 72.327 -1.267 72.25 -1.278 c
+72.169 -1.286 72.08 -1.294 71.985 -1.294 c
+71.897 -1.301 71.798 -1.308 71.691 -1.308 c
+71.504 -1.308 71.342 -1.294 71.206 -1.264 c
+71.078 -1.228 70.964 -1.183 70.868 -1.132 c
+70.78 -1.084 70.706 -1.025 70.648 -0.955 c
+70.588 -0.878 70.545 -0.801 70.515 -0.72 c
+70.486 -0.632 70.464 -0.544 70.457 -0.455 c
+70.445 -0.36 70.442 -0.264 70.442 -0.176 c
+h
+74.285 -2.631 m
+74.285 -2.013 l
+75.359 -2.013 l
+75.359 2.896 l
+74.285 2.896 l
+74.285 3.514 l
+76.211 3.514 l
+76.211 -2.631 l
+h
+f
+Q
+q 1 0 0 1 47.3793 448.9472 cm
+0 0 m
+2.102 0 l
+2.102 -0.574 l
+-0.676 -0.574 l
+-0.676 4.777 l
+0 4.777 l
+h
+3.513 -0.574 -0.646 3.984 re
+3.557 4.453 m
+3.557 4.343 3.528 4.251 3.469 4.174 c
+3.41 4.104 3.314 4.072 3.19 4.072 c
+3.072 4.072 2.977 4.104 2.911 4.174 c
+2.851 4.251 2.822 4.343 2.822 4.453 c
+2.822 4.571 2.851 4.663 2.911 4.733 c
+2.977 4.81 3.072 4.85 3.19 4.85 c
+3.314 4.85 3.41 4.81 3.469 4.733 c
+3.528 4.652 3.557 4.56 3.557 4.453 c
+6.468 0.44 m
+6.468 0.588 6.412 0.709 6.306 0.808 c
+6.196 0.904 5.99 1.022 5.689 1.161 c
+5.343 1.308 5.101 1.429 4.953 1.529 c
+4.806 1.635 4.696 1.753 4.63 1.881 c
+4.561 2.006 4.527 2.164 4.527 2.352 c
+4.527 2.674 4.644 2.944 4.88 3.16 c
+5.115 3.374 5.417 3.484 5.791 3.484 c
+6.173 3.484 6.483 3.37 6.718 3.145 c
+6.953 2.917 7.07 2.631 7.07 2.278 c
+6.423 2.278 l
+6.423 2.454 6.364 2.605 6.247 2.734 c
+6.129 2.859 5.975 2.925 5.791 2.925 c
+5.593 2.925 5.442 2.869 5.336 2.763 c
+5.226 2.664 5.174 2.532 5.174 2.366 c
+5.174 2.238 5.211 2.131 5.292 2.043 c
+5.369 1.962 5.56 1.859 5.865 1.734 c
+6.342 1.547 6.674 1.359 6.85 1.176 c
+7.026 0.999 7.114 0.771 7.114 0.5 c
+7.114 0.147 6.99 -0.133 6.747 -0.339 c
+6.512 -0.544 6.196 -0.647 5.806 -0.647 c
+5.384 -0.647 5.045 -0.53 4.792 -0.294 c
+4.534 -0.052 4.409 0.253 4.409 0.617 c
+5.056 0.617 l
+5.064 0.389 5.134 0.213 5.262 0.087 c
+5.387 -0.03 5.571 -0.088 5.806 -0.088 c
+6.019 -0.088 6.181 -0.04 6.291 0.058 c
+6.408 0.154 6.468 0.282 6.468 0.44 c
+8.804 4.365 m
+8.804 3.41 l
+9.407 3.41 l
+9.407 2.881 l
+8.804 2.881 l
+8.804 0.411 l
+8.804 0.253 8.827 0.135 8.878 0.058 c
+8.937 -0.023 9.025 -0.059 9.143 -0.059 c
+9.231 -0.059 9.319 -0.044 9.407 -0.015 c
+9.407 -0.574 l
+9.261 -0.621 9.106 -0.647 8.951 -0.647 c
+8.694 -0.647 8.5 -0.555 8.364 -0.368 c
+8.224 -0.184 8.158 0.077 8.158 0.411 c
+8.158 2.881 l
+7.555 2.881 l
+7.555 3.41 l
+8.158 3.41 l
+8.158 4.365 l
+h
+13.273 -0.088 m
+13.486 -0.088 13.659 -0.026 13.787 0.103 c
+13.924 0.239 13.997 0.43 14.009 0.675 c
+14.626 0.675 l
+14.603 0.294 14.468 -0.026 14.214 -0.279 c
+13.957 -0.526 13.644 -0.647 13.273 -0.647 c
+12.781 -0.647 12.406 -0.497 12.141 -0.191 c
+11.884 0.121 11.759 0.588 11.759 1.205 c
+11.759 1.646 l
+11.759 2.241 11.884 2.697 12.141 3.013 c
+12.406 3.326 12.781 3.484 13.273 3.484 c
+13.674 3.484 13.993 3.351 14.229 3.087 c
+14.471 2.829 14.603 2.484 14.626 2.043 c
+14.009 2.043 l
+13.986 2.337 13.913 2.557 13.787 2.705 c
+13.67 2.851 13.498 2.925 13.273 2.925 c
+12.979 2.925 12.762 2.826 12.627 2.631 c
+12.486 2.443 12.413 2.135 12.406 1.705 c
+12.406 1.19 l
+12.406 0.72 12.472 0.386 12.612 0.191 c
+12.758 0.004 12.979 -0.088 13.273 -0.088 c
+15.243 1.602 m
+15.243 2.179 15.379 2.634 15.655 2.969 c
+15.937 3.31 16.309 3.484 16.771 3.484 c
+17.231 3.484 17.598 3.314 17.874 2.984 c
+18.157 2.66 18.304 2.212 18.315 1.646 c
+18.315 1.22 l
+18.315 0.65 18.171 0.195 17.888 -0.148 c
+17.613 -0.482 17.246 -0.647 16.787 -0.647 c
+16.323 -0.647 15.952 -0.485 15.669 -0.162 c
+15.393 0.168 15.25 0.61 15.243 1.161 c
+h
+15.89 1.22 m
+15.89 0.816 15.967 0.5 16.125 0.264 c
+16.29 0.029 16.511 -0.088 16.787 -0.088 c
+17.352 -0.088 17.646 0.323 17.668 1.146 c
+17.668 1.602 l
+17.668 2.003 17.583 2.322 17.418 2.557 c
+17.261 2.8 17.043 2.925 16.771 2.925 c
+16.507 2.925 16.29 2.8 16.125 2.557 c
+15.967 2.322 15.89 2.003 15.89 1.602 c
+h
+19.77 3.41 m
+19.785 3.042 l
+20.027 3.337 20.347 3.484 20.74 3.484 c
+21.181 3.484 21.49 3.285 21.666 2.896 c
+21.92 3.285 22.269 3.484 22.71 3.484 c
+23.445 3.484 23.82 3.021 23.842 2.102 c
+23.842 -0.574 l
+23.195 -0.574 l
+23.195 2.043 l
+23.195 2.337 23.14 2.55 23.033 2.69 c
+22.934 2.826 22.761 2.896 22.518 2.896 c
+22.32 2.896 22.159 2.815 22.034 2.66 c
+21.916 2.514 21.847 2.322 21.828 2.087 c
+21.828 -0.574 l
+21.167 -0.574 l
+21.167 2.072 l
+21.167 2.62 20.946 2.896 20.505 2.896 c
+20.17 2.896 19.935 2.734 19.8 2.41 c
+19.8 -0.574 l
+19.153 -0.574 l
+19.153 3.41 l
+h
+25.429 3.41 m
+25.444 3.042 l
+25.687 3.337 26.006 3.484 26.399 3.484 c
+26.84 3.484 27.149 3.285 27.326 2.896 c
+27.579 3.285 27.928 3.484 28.369 3.484 c
+29.104 3.484 29.479 3.021 29.501 2.102 c
+29.501 -0.574 l
+28.854 -0.574 l
+28.854 2.043 l
+28.854 2.337 28.799 2.55 28.693 2.69 c
+28.593 2.826 28.421 2.896 28.178 2.896 c
+27.979 2.896 27.818 2.815 27.693 2.66 c
+27.575 2.514 27.505 2.322 27.487 2.087 c
+27.487 -0.574 l
+26.825 -0.574 l
+26.825 2.072 l
+26.825 2.62 26.605 2.896 26.164 2.896 c
+25.83 2.896 25.595 2.734 25.458 2.41 c
+25.458 -0.574 l
+24.812 -0.574 l
+24.812 3.41 l
+h
+31.177 -0.574 -0.647 3.984 re
+31.22 4.453 m
+31.22 4.343 31.191 4.251 31.133 4.174 c
+31.074 4.104 30.979 4.072 30.853 4.072 c
+30.736 4.072 30.64 4.104 30.574 4.174 c
+30.515 4.251 30.486 4.343 30.486 4.453 c
+30.486 4.571 30.515 4.663 30.574 4.733 c
+30.64 4.81 30.736 4.85 30.853 4.85 c
+30.979 4.85 31.074 4.81 31.133 4.733 c
+31.191 4.652 31.22 4.56 31.22 4.453 c
+33.043 4.365 m
+33.043 3.41 l
+33.646 3.41 l
+33.646 2.881 l
+33.043 2.881 l
+33.043 0.411 l
+33.043 0.253 33.065 0.135 33.117 0.058 c
+33.175 -0.023 33.264 -0.059 33.381 -0.059 c
+33.47 -0.059 33.558 -0.044 33.646 -0.015 c
+33.646 -0.574 l
+33.499 -0.621 33.344 -0.647 33.19 -0.647 c
+32.933 -0.647 32.739 -0.555 32.602 -0.368 c
+32.463 -0.184 32.396 0.077 32.396 0.411 c
+32.396 2.881 l
+31.794 2.881 l
+31.794 3.41 l
+32.396 3.41 l
+32.396 4.365 l
+h
+36.777 2.998 m
+37.03 3.322 37.35 3.484 37.732 3.484 c
+38.438 3.484 38.794 3.013 38.805 2.072 c
+38.805 -0.574 l
+38.158 -0.574 l
+38.158 2.043 l
+38.158 2.356 38.104 2.576 37.997 2.705 c
+37.886 2.829 37.732 2.896 37.527 2.896 c
+37.369 2.896 37.221 2.84 37.086 2.734 c
+36.957 2.624 36.854 2.487 36.777 2.322 c
+36.777 -0.574 l
+36.13 -0.574 l
+36.13 5.071 l
+36.777 5.071 l
+h
+40.466 -0.574 -0.646 3.984 re
+40.51 4.453 m
+40.51 4.343 40.481 4.251 40.423 4.174 c
+40.363 4.104 40.268 4.072 40.143 4.072 c
+40.026 4.072 39.93 4.104 39.864 4.174 c
+39.805 4.251 39.775 4.343 39.775 4.453 c
+39.775 4.571 39.805 4.663 39.864 4.733 c
+39.93 4.81 40.026 4.85 40.143 4.85 c
+40.268 4.85 40.363 4.81 40.423 4.733 c
+40.481 4.652 40.51 4.56 40.51 4.453 c
+43.421 0.44 m
+43.421 0.588 43.366 0.709 43.259 0.808 c
+43.149 0.904 42.943 1.022 42.642 1.161 c
+42.297 1.308 42.054 1.429 41.907 1.529 c
+41.76 1.635 41.649 1.753 41.583 1.881 c
+41.514 2.006 41.481 2.164 41.481 2.352 c
+41.481 2.674 41.599 2.944 41.834 3.16 c
+42.069 3.374 42.37 3.484 42.744 3.484 c
+43.127 3.484 43.436 3.37 43.671 3.145 c
+43.906 2.917 44.024 2.631 44.024 2.278 c
+43.377 2.278 l
+43.377 2.454 43.318 2.605 43.201 2.734 c
+43.083 2.859 42.929 2.925 42.744 2.925 c
+42.546 2.925 42.395 2.869 42.289 2.763 c
+42.179 2.664 42.127 2.532 42.127 2.366 c
+42.127 2.238 42.164 2.131 42.245 2.043 c
+42.322 1.962 42.513 1.859 42.818 1.734 c
+43.296 1.547 43.627 1.359 43.803 1.176 c
+43.98 0.999 44.068 0.771 44.068 0.5 c
+44.068 0.147 43.943 -0.133 43.7 -0.339 c
+43.465 -0.544 43.149 -0.647 42.759 -0.647 c
+42.337 -0.647 41.998 -0.53 41.745 -0.294 c
+41.488 -0.052 41.363 0.253 41.363 0.617 c
+42.01 0.617 l
+42.017 0.389 42.087 0.213 42.216 0.087 c
+42.341 -0.03 42.524 -0.088 42.759 -0.088 c
+42.973 -0.088 43.134 -0.04 43.245 0.058 c
+43.362 0.154 43.421 0.282 43.421 0.44 c
+45.758 4.365 m
+45.758 3.41 l
+46.361 3.41 l
+46.361 2.881 l
+45.758 2.881 l
+45.758 0.411 l
+45.758 0.253 45.78 0.135 45.832 0.058 c
+45.89 -0.023 45.979 -0.059 46.096 -0.059 c
+46.185 -0.059 46.272 -0.044 46.361 -0.015 c
+46.361 -0.574 l
+46.214 -0.621 46.06 -0.647 45.905 -0.647 c
+45.647 -0.647 45.453 -0.555 45.317 -0.368 c
+45.177 -0.184 45.111 0.077 45.111 0.411 c
+45.111 2.881 l
+44.508 2.881 l
+44.508 3.41 l
+45.111 3.41 l
+45.111 4.365 l
+h
+46.919 1.602 m
+46.919 2.179 47.055 2.634 47.33 2.969 c
+47.614 3.31 47.985 3.484 48.448 3.484 c
+48.907 3.484 49.275 3.314 49.551 2.984 c
+49.834 2.66 49.981 2.212 49.992 1.646 c
+49.992 1.22 l
+49.992 0.65 49.848 0.195 49.565 -0.148 c
+49.289 -0.482 48.922 -0.647 48.462 -0.647 c
+47.999 -0.647 47.629 -0.485 47.346 -0.162 c
+47.07 0.168 46.927 0.61 46.919 1.161 c
+h
+47.566 1.22 m
+47.566 0.816 47.643 0.5 47.801 0.264 c
+47.966 0.029 48.187 -0.088 48.462 -0.088 c
+49.029 -0.088 49.323 0.323 49.345 1.146 c
+49.345 1.602 l
+49.345 2.003 49.26 2.322 49.094 2.557 c
+48.936 2.8 48.72 2.925 48.448 2.925 c
+48.184 2.925 47.966 2.8 47.801 2.557 c
+47.643 2.322 47.566 2.003 47.566 1.602 c
+h
+52.475 2.792 m
+52.387 2.811 52.288 2.822 52.182 2.822 c
+51.847 2.822 51.612 2.638 51.476 2.278 c
+51.476 -0.574 l
+50.829 -0.574 l
+50.829 3.41 l
+51.461 3.41 l
+51.476 2.998 l
+51.652 3.322 51.895 3.484 52.211 3.484 c
+52.317 3.484 52.406 3.461 52.475 3.424 c
+h
+54.283 0.515 m
+55.004 3.41 l
+55.695 3.41 l
+54.401 -1.132 l
+54.302 -1.474 54.158 -1.735 53.975 -1.912 c
+53.798 -2.087 53.597 -2.176 53.372 -2.176 c
+53.284 -2.176 53.17 -2.153 53.034 -2.117 c
+53.034 -1.573 l
+53.181 -1.588 l
+53.364 -1.588 53.512 -1.544 53.622 -1.455 c
+53.728 -1.367 53.817 -1.209 53.886 -0.985 c
+54.004 -0.544 l
+52.843 3.41 l
+53.549 3.41 l
+h
+57.914 1.602 m
+57.914 2.179 58.05 2.634 58.326 2.969 c
+58.609 3.31 58.98 3.484 59.443 3.484 c
+59.903 3.484 60.269 3.314 60.545 2.984 c
+60.828 2.66 60.975 2.212 60.986 1.646 c
+60.986 1.22 l
+60.986 0.65 60.843 0.195 60.56 -0.148 c
+60.284 -0.482 59.917 -0.647 59.458 -0.647 c
+58.995 -0.647 58.623 -0.485 58.34 -0.162 c
+58.065 0.168 57.921 0.61 57.914 1.161 c
+h
+58.561 1.22 m
+58.561 0.816 58.638 0.5 58.796 0.264 c
+58.962 0.029 59.182 -0.088 59.458 -0.088 c
+60.024 -0.088 60.317 0.323 60.34 1.146 c
+60.34 1.602 l
+60.34 2.003 60.255 2.322 60.09 2.557 c
+59.932 2.8 59.714 2.925 59.443 2.925 c
+59.178 2.925 58.962 2.8 58.796 2.557 c
+58.638 2.322 58.561 2.003 58.561 1.602 c
+h
+62.118 -0.574 m
+62.118 2.881 l
+61.589 2.881 l
+61.589 3.41 l
+62.118 3.41 l
+62.118 3.866 l
+62.118 4.266 62.214 4.579 62.412 4.806 c
+62.617 5.03 62.897 5.144 63.25 5.144 c
+63.386 5.144 63.518 5.122 63.647 5.086 c
+63.617 4.542 l
+63.518 4.56 63.419 4.571 63.323 4.571 c
+62.949 4.571 62.765 4.307 62.765 3.777 c
+62.765 3.41 l
+63.441 3.41 l
+63.441 2.881 l
+62.765 2.881 l
+62.765 -0.574 l
+h
+67.307 -0.088 m
+67.52 -0.088 67.693 -0.026 67.822 0.103 c
+67.957 0.239 68.031 0.43 68.042 0.675 c
+68.659 0.675 l
+68.637 0.294 68.501 -0.026 68.248 -0.279 c
+67.99 -0.526 67.678 -0.647 67.307 -0.647 c
+66.814 -0.647 66.44 -0.497 66.175 -0.191 c
+65.918 0.121 65.792 0.588 65.792 1.205 c
+65.792 1.646 l
+65.792 2.241 65.918 2.697 66.175 3.013 c
+66.44 3.326 66.814 3.484 67.307 3.484 c
+67.708 3.484 68.027 3.351 68.262 3.087 c
+68.505 2.829 68.637 2.484 68.659 2.043 c
+68.042 2.043 l
+68.02 2.337 67.946 2.557 67.822 2.705 c
+67.704 2.851 67.531 2.925 67.307 2.925 c
+67.013 2.925 66.796 2.826 66.66 2.631 c
+66.521 2.443 66.447 2.135 66.44 1.705 c
+66.44 1.19 l
+66.44 0.72 66.506 0.386 66.646 0.191 c
+66.792 0.004 67.013 -0.088 67.307 -0.088 c
+71.437 -0.221 m
+71.221 -0.507 70.908 -0.647 70.496 -0.647 c
+70.133 -0.647 69.857 -0.526 69.673 -0.279 c
+69.497 -0.026 69.401 0.338 69.394 0.808 c
+69.394 3.41 l
+70.041 3.41 l
+70.041 0.867 l
+70.041 0.239 70.224 -0.073 70.6 -0.073 c
+71 -0.073 71.275 0.103 71.423 0.455 c
+71.423 3.41 l
+72.069 3.41 l
+72.069 -0.574 l
+71.452 -0.574 l
+h
+74.7 2.792 m
+74.612 2.811 74.513 2.822 74.407 2.822 c
+74.072 2.822 73.837 2.638 73.701 2.278 c
+73.701 -0.574 l
+73.054 -0.574 l
+73.054 3.41 l
+73.686 3.41 l
+73.701 2.998 l
+73.877 3.322 74.12 3.484 74.436 3.484 c
+74.542 3.484 74.631 3.461 74.7 3.424 c
+h
+76.994 2.792 m
+76.905 2.811 76.806 2.822 76.699 2.822 c
+76.365 2.822 76.13 2.638 75.994 2.278 c
+75.994 -0.574 l
+75.348 -0.574 l
+75.348 3.41 l
+75.979 3.41 l
+75.994 2.998 l
+76.171 3.322 76.412 3.484 76.729 3.484 c
+76.836 3.484 76.923 3.461 76.994 3.424 c
+h
+78.993 -0.647 m
+78.492 -0.647 78.111 -0.5 77.846 -0.206 c
+77.582 0.087 77.449 0.521 77.449 1.103 c
+77.449 1.573 l
+77.449 2.167 77.574 2.634 77.831 2.969 c
+78.095 3.31 78.456 3.484 78.92 3.484 c
+79.379 3.484 79.72 3.329 79.948 3.027 c
+80.183 2.734 80.304 2.271 80.316 1.646 c
+80.316 1.22 l
+78.095 1.22 l
+78.095 1.132 l
+78.095 0.698 78.174 0.386 78.331 0.191 c
+78.496 0.004 78.728 -0.088 79.022 -0.088 c
+79.217 -0.088 79.39 -0.055 79.537 0.014 c
+79.683 0.091 79.82 0.209 79.948 0.367 c
+80.286 -0.044 l
+80 -0.449 79.57 -0.647 78.993 -0.647 c
+78.92 2.925 m
+78.644 2.925 78.442 2.829 78.317 2.645 c
+78.188 2.458 78.114 2.167 78.095 1.778 c
+79.668 1.778 l
+79.668 1.866 l
+79.647 2.248 79.581 2.516 79.463 2.674 c
+79.346 2.84 79.161 2.925 78.92 2.925 c
+81.712 3.41 m
+81.727 2.969 l
+81.98 3.31 82.303 3.484 82.697 3.484 c
+83.402 3.484 83.759 3.013 83.77 2.072 c
+83.77 -0.574 l
+83.123 -0.574 l
+83.123 2.043 l
+83.123 2.356 83.068 2.576 82.961 2.705 c
+82.851 2.829 82.697 2.896 82.491 2.896 c
+82.333 2.896 82.186 2.84 82.05 2.734 c
+81.921 2.624 81.819 2.487 81.742 2.322 c
+81.742 -0.574 l
+81.095 -0.574 l
+81.095 3.41 l
+h
+85.592 4.365 m
+85.592 3.41 l
+86.195 3.41 l
+86.195 2.881 l
+85.592 2.881 l
+85.592 0.411 l
+85.592 0.253 85.615 0.135 85.666 0.058 c
+85.725 -0.023 85.813 -0.059 85.931 -0.059 c
+86.018 -0.059 86.107 -0.044 86.195 -0.015 c
+86.195 -0.574 l
+86.048 -0.621 85.894 -0.647 85.74 -0.647 c
+85.482 -0.647 85.287 -0.555 85.151 -0.368 c
+85.012 -0.184 84.946 0.077 84.946 0.411 c
+84.946 2.881 l
+84.343 2.881 l
+84.343 3.41 l
+84.946 3.41 l
+84.946 4.365 l
+h
+91.56 1.22 m
+91.56 0.602 91.446 0.135 91.223 -0.177 c
+91.005 -0.493 90.682 -0.647 90.252 -0.647 c
+89.829 -0.647 89.517 -0.467 89.311 -0.103 c
+89.282 -0.574 l
+88.679 -0.574 l
+88.679 5.071 l
+89.326 5.071 l
+89.326 2.969 l
+89.54 3.31 89.848 3.484 90.252 3.484 c
+90.682 3.484 91.005 3.326 91.223 3.013 c
+91.446 2.708 91.56 2.241 91.56 1.616 c
+h
+90.914 1.602 m
+90.914 2.072 90.843 2.403 90.708 2.601 c
+90.579 2.796 90.369 2.896 90.076 2.896 c
+89.741 2.896 89.492 2.711 89.326 2.352 c
+89.326 0.47 l
+89.492 0.106 89.745 -0.073 90.09 -0.073 c
+90.384 -0.073 90.594 0.029 90.722 0.235 c
+90.847 0.44 90.914 0.756 90.914 1.19 c
+h
+94.045 2.792 m
+93.956 2.811 93.857 2.822 93.75 2.822 c
+93.416 2.822 93.181 2.638 93.045 2.278 c
+93.045 -0.574 l
+92.398 -0.574 l
+92.398 3.41 l
+93.031 3.41 l
+93.045 2.998 l
+93.222 3.322 93.463 3.484 93.779 3.484 c
+93.887 3.484 93.974 3.461 94.045 3.424 c
+h
+96.588 -0.574 m
+96.547 -0.485 96.521 -0.339 96.514 -0.133 c
+96.279 -0.478 95.985 -0.647 95.632 -0.647 c
+95.268 -0.647 94.986 -0.551 94.779 -0.353 c
+94.581 -0.148 94.485 0.139 94.485 0.515 c
+94.485 0.914 94.621 1.234 94.897 1.469 c
+95.169 1.712 95.543 1.837 96.014 1.837 c
+96.499 1.837 l
+96.499 2.263 l
+96.499 2.499 96.444 2.664 96.337 2.763 c
+96.227 2.869 96.065 2.925 95.853 2.925 c
+95.654 2.925 95.493 2.866 95.367 2.749 c
+95.25 2.631 95.191 2.484 95.191 2.308 c
+94.544 2.308 l
+94.544 2.502 94.603 2.693 94.72 2.881 c
+94.845 3.064 95.007 3.212 95.206 3.322 c
+95.412 3.428 95.639 3.484 95.896 3.484 c
+96.297 3.484 96.602 3.38 96.808 3.175 c
+97.021 2.969 97.135 2.674 97.145 2.293 c
+97.145 0.279 l
+97.145 -0.026 97.183 -0.291 97.264 -0.515 c
+97.264 -0.574 l
+h
+95.72 -0.059 m
+95.886 -0.059 96.036 -0.015 96.176 0.073 c
+96.323 0.162 96.43 0.272 96.499 0.411 c
+96.499 1.352 l
+96.131 1.352 l
+95.815 1.352 95.573 1.282 95.397 1.146 c
+95.221 1.018 95.132 0.83 95.132 0.588 c
+95.132 0.359 95.176 0.195 95.264 0.087 c
+95.352 -0.011 95.503 -0.059 95.72 -0.059 c
+98.763 3.41 m
+98.778 2.969 l
+99.031 3.31 99.354 3.484 99.748 3.484 c
+100.453 3.484 100.81 3.013 100.821 2.072 c
+100.821 -0.574 l
+100.174 -0.574 l
+100.174 2.043 l
+100.174 2.356 100.119 2.576 100.012 2.705 c
+99.902 2.829 99.748 2.896 99.542 2.896 c
+99.383 2.896 99.237 2.84 99.101 2.734 c
+98.972 2.624 98.87 2.487 98.792 2.322 c
+98.792 -0.574 l
+98.145 -0.574 l
+98.145 3.41 l
+h
+103.173 -0.088 m
+103.385 -0.088 103.558 -0.026 103.687 0.103 c
+103.823 0.239 103.896 0.43 103.907 0.675 c
+104.525 0.675 l
+104.503 0.294 104.367 -0.026 104.113 -0.279 c
+103.856 -0.526 103.543 -0.647 103.173 -0.647 c
+102.68 -0.647 102.305 -0.497 102.041 -0.191 c
+101.783 0.121 101.658 0.588 101.658 1.205 c
+101.658 1.646 l
+101.658 2.241 101.783 2.697 102.041 3.013 c
+102.305 3.326 102.68 3.484 103.173 3.484 c
+103.574 3.484 103.892 3.351 104.128 3.087 c
+104.37 2.829 104.503 2.484 104.525 2.043 c
+103.907 2.043 l
+103.886 2.337 103.812 2.557 103.687 2.705 c
+103.57 2.851 103.397 2.925 103.173 2.925 c
+102.878 2.925 102.662 2.826 102.526 2.631 c
+102.386 2.443 102.313 2.135 102.305 1.705 c
+102.305 1.19 l
+102.305 0.72 102.371 0.386 102.511 0.191 c
+102.658 0.004 102.878 -0.088 103.173 -0.088 c
+105.922 2.998 m
+106.175 3.322 106.495 3.484 106.876 3.484 c
+107.582 3.484 107.939 3.013 107.95 2.072 c
+107.95 -0.574 l
+107.303 -0.574 l
+107.303 2.043 l
+107.303 2.356 107.248 2.576 107.142 2.705 c
+107.031 2.829 106.876 2.896 106.671 2.896 c
+106.513 2.896 106.366 2.84 106.23 2.734 c
+106.101 2.624 105.999 2.487 105.922 2.322 c
+105.922 -0.574 l
+105.274 -0.574 l
+105.274 5.071 l
+105.922 5.071 l
+h
+108.949 -0.221 m
+108.949 -0.103 108.983 -0.008 109.052 0.073 c
+109.118 0.151 109.221 0.191 109.361 0.191 c
+109.508 0.191 109.614 0.151 109.685 0.073 c
+109.762 -0.008 109.802 -0.103 109.802 -0.221 c
+109.802 -0.331 109.762 -0.423 109.685 -0.5 c
+109.614 -0.578 109.508 -0.618 109.361 -0.618 c
+109.221 -0.618 109.118 -0.578 109.052 -0.5 c
+108.983 -0.423 108.949 -0.331 108.949 -0.221 c
+f
+Q
+161.753 450.241 -1.793 0.867 re
+163.575 452.357 m
+163.605 451.96 l
+163.84 452.273 164.141 452.431 164.516 452.431 c
+165.199 452.431 165.552 451.949 165.575 450.99 c
+165.575 448.373 l
+164.531 448.373 l
+164.531 450.916 l
+164.531 451.141 164.494 451.303 164.428 451.402 c
+164.358 451.498 164.241 451.548 164.075 451.548 c
+163.888 451.548 163.74 451.453 163.634 451.269 c
+163.634 448.373 l
+162.591 448.373 l
+162.591 452.357 l
+h
+169.499 449.167 m
+169.793 449.167 169.944 449.362 169.955 449.755 c
+170.925 449.755 l
+170.925 449.322 170.792 448.969 170.528 448.697 c
+170.263 448.433 169.925 448.3 169.514 448.3 c
+169.003 448.3 168.61 448.454 168.338 448.77 c
+168.073 449.094 167.933 449.564 167.927 450.181 c
+167.927 450.505 l
+167.927 451.13 168.058 451.608 168.323 451.931 c
+168.595 452.261 168.992 452.431 169.514 452.431 c
+169.944 452.431 170.285 452.291 170.543 452.019 c
+170.796 451.743 170.925 451.361 170.925 450.873 c
+169.955 450.873 l
+169.955 451.085 169.914 451.255 169.837 451.372 c
+169.768 451.498 169.65 451.563 169.484 451.563 c
+169.308 451.563 169.18 451.498 169.103 451.372 c
+169.022 451.244 168.977 450.993 168.97 450.623 c
+168.97 450.211 l
+168.97 449.888 168.984 449.659 169.014 449.535 c
+169.051 449.406 169.105 449.314 169.176 449.256 c
+169.253 449.196 169.359 449.167 169.499 449.167 c
+171.41 450.49 m
+171.41 451.097 171.549 451.571 171.836 451.916 c
+172.12 452.258 172.512 452.431 173.012 452.431 c
+173.519 452.431 173.916 452.258 174.202 451.916 c
+174.485 451.571 174.628 451.097 174.628 450.49 c
+174.628 450.226 l
+174.628 449.626 174.485 449.156 174.202 448.815 c
+173.916 448.469 173.519 448.3 173.012 448.3 c
+172.501 448.3 172.104 448.469 171.821 448.815 c
+171.546 449.156 171.41 449.63 171.41 450.241 c
+h
+172.453 450.226 m
+172.453 449.52 172.637 449.167 173.012 449.167 c
+173.365 449.167 173.556 449.462 173.585 450.05 c
+173.585 450.49 l
+173.585 450.85 173.533 451.122 173.438 451.299 c
+173.339 451.475 173.196 451.563 173.012 451.563 c
+172.835 451.563 172.696 451.475 172.6 451.299 c
+172.501 451.122 172.453 450.85 172.453 450.49 c
+h
+177.231 448.741 m
+177.014 448.447 176.723 448.3 176.363 448.3 c
+176 448.3 175.721 448.421 175.526 448.668 c
+175.338 448.921 175.247 449.289 175.247 449.77 c
+175.247 452.357 l
+176.29 452.357 l
+176.29 449.755 l
+176.29 449.362 176.415 449.167 176.672 449.167 c
+176.907 449.167 177.076 449.27 177.186 449.476 c
+177.186 452.357 l
+178.231 452.357 l
+178.231 448.373 l
+177.26 448.373 l
+h
+179.935 452.357 m
+179.964 451.96 l
+180.2 452.273 180.501 452.431 180.876 452.431 c
+181.56 452.431 181.913 451.949 181.934 450.99 c
+181.934 448.373 l
+180.891 448.373 l
+180.891 450.916 l
+180.891 451.141 180.854 451.303 180.787 451.402 c
+180.718 451.498 180.6 451.548 180.435 451.548 c
+180.247 451.548 180.101 451.453 179.994 451.269 c
+179.994 448.373 l
+178.95 448.373 l
+178.95 452.357 l
+h
+183.889 453.327 m
+183.889 452.357 l
+184.419 452.357 l
+184.419 451.563 l
+183.889 451.563 l
+183.889 449.593 l
+183.889 449.435 183.908 449.329 183.948 449.27 c
+183.996 449.212 184.08 449.182 184.198 449.182 c
+184.305 449.182 184.39 449.189 184.448 449.212 c
+184.448 448.403 l
+184.271 448.337 184.08 448.3 183.875 448.3 c
+183.199 448.3 182.853 448.686 182.846 449.462 c
+182.846 451.563 l
+182.39 451.563 l
+182.39 452.357 l
+182.846 452.357 l
+182.846 453.327 l
+h
+f
+187.52 448.373 -0.647 5.644 re
+189.24 448.373 -0.647 3.984 re
+189.284 453.401 m
+189.284 453.291 189.254 453.198 189.196 453.121 c
+189.137 453.052 189.042 453.019 188.916 453.019 c
+188.799 453.019 188.703 453.052 188.637 453.121 c
+188.579 453.198 188.549 453.291 188.549 453.401 c
+188.549 453.518 188.579 453.61 188.637 453.68 c
+188.703 453.757 188.799 453.798 188.916 453.798 c
+189.042 453.798 189.137 453.757 189.196 453.68 c
+189.254 453.599 189.284 453.507 189.284 453.401 c
+190.871 452.357 m
+190.886 451.99 l
+191.129 452.284 191.448 452.431 191.841 452.431 c
+192.282 452.431 192.591 452.232 192.768 451.843 c
+193.021 452.232 193.37 452.431 193.811 452.431 c
+194.546 452.431 194.921 451.968 194.943 451.049 c
+194.943 448.373 l
+194.296 448.373 l
+194.296 450.99 l
+194.296 451.284 194.241 451.498 194.135 451.637 c
+194.035 451.773 193.863 451.843 193.62 451.843 c
+193.422 451.843 193.26 451.762 193.135 451.608 c
+193.017 451.461 192.947 451.269 192.93 451.034 c
+192.93 448.373 l
+192.267 448.373 l
+192.267 451.02 l
+192.267 451.567 192.047 451.843 191.606 451.843 c
+191.272 451.843 191.037 451.681 190.9 451.357 c
+190.9 448.373 l
+190.254 448.373 l
+190.254 452.357 l
+h
+196.619 448.373 -0.647 3.984 re
+196.662 453.401 m
+196.662 453.291 196.633 453.198 196.575 453.121 c
+196.516 453.052 196.421 453.019 196.296 453.019 c
+196.178 453.019 196.082 453.052 196.016 453.121 c
+195.957 453.198 195.928 453.291 195.928 453.401 c
+195.928 453.518 195.957 453.61 196.016 453.68 c
+196.082 453.757 196.178 453.798 196.296 453.798 c
+196.421 453.798 196.516 453.757 196.575 453.68 c
+196.633 453.599 196.662 453.507 196.662 453.401 c
+198.486 453.312 m
+198.486 452.357 l
+199.088 452.357 l
+199.088 451.828 l
+198.486 451.828 l
+198.486 449.358 l
+198.486 449.2 198.507 449.083 198.559 449.006 c
+198.617 448.925 198.706 448.888 198.823 448.888 c
+198.912 448.888 199 448.903 199.088 448.932 c
+199.088 448.373 l
+198.941 448.326 198.787 448.3 198.632 448.3 c
+198.376 448.3 198.181 448.392 198.044 448.579 c
+197.905 448.763 197.838 449.024 197.838 449.358 c
+197.838 451.828 l
+197.236 451.828 l
+197.236 452.357 l
+197.838 452.357 l
+197.838 453.312 l
+h
+201.793 449.387 m
+201.793 449.535 201.738 449.656 201.631 449.755 c
+201.52 449.851 201.315 449.969 201.013 450.108 c
+200.668 450.255 200.425 450.376 200.279 450.476 c
+200.132 450.582 200.022 450.7 199.955 450.829 c
+199.885 450.953 199.852 451.111 199.852 451.299 c
+199.852 451.622 199.97 451.891 200.205 452.107 c
+200.44 452.321 200.742 452.431 201.117 452.431 c
+201.499 452.431 201.807 452.317 202.043 452.092 c
+202.278 451.864 202.395 451.578 202.395 451.226 c
+201.749 451.226 l
+201.749 451.402 201.69 451.552 201.572 451.681 c
+201.455 451.806 201.3 451.872 201.117 451.872 c
+200.918 451.872 200.768 451.816 200.661 451.71 c
+200.551 451.611 200.499 451.479 200.499 451.313 c
+200.499 451.185 200.536 451.078 200.617 450.99 c
+200.694 450.91 200.885 450.806 201.19 450.681 c
+201.668 450.494 201.998 450.307 202.175 450.123 c
+202.351 449.946 202.44 449.719 202.44 449.447 c
+202.44 449.094 202.314 448.815 202.072 448.608 c
+201.837 448.403 201.52 448.3 201.131 448.3 c
+200.709 448.3 200.371 448.418 200.117 448.653 c
+199.86 448.895 199.735 449.2 199.735 449.564 c
+200.382 449.564 l
+200.389 449.337 200.459 449.16 200.587 449.035 c
+200.712 448.917 200.896 448.859 201.131 448.859 c
+201.345 448.859 201.506 448.907 201.616 449.006 c
+201.734 449.101 201.793 449.229 201.793 449.387 c
+205.703 448.373 -0.647 5.644 re
+207.423 448.373 -0.647 3.984 re
+207.467 453.401 m
+207.467 453.291 207.438 453.198 207.378 453.121 c
+207.319 453.052 207.224 453.019 207.099 453.019 c
+206.981 453.019 206.886 453.052 206.82 453.121 c
+206.761 453.198 206.732 453.291 206.732 453.401 c
+206.732 453.518 206.761 453.61 206.82 453.68 c
+206.886 453.757 206.981 453.798 207.099 453.798 c
+207.224 453.798 207.319 453.757 207.378 453.68 c
+207.438 453.599 207.467 453.507 207.467 453.401 c
+210.377 449.387 m
+210.377 449.535 210.322 449.656 210.216 449.755 c
+210.105 449.851 209.9 449.969 209.598 450.108 c
+209.252 450.255 209.01 450.376 208.863 450.476 c
+208.716 450.582 208.606 450.7 208.539 450.829 c
+208.47 450.953 208.437 451.111 208.437 451.299 c
+208.437 451.622 208.554 451.891 208.79 452.107 c
+209.025 452.321 209.326 452.431 209.701 452.431 c
+210.083 452.431 210.392 452.317 210.627 452.092 c
+210.862 451.864 210.98 451.578 210.98 451.226 c
+210.333 451.226 l
+210.333 451.402 210.274 451.552 210.156 451.681 c
+210.039 451.806 209.885 451.872 209.701 451.872 c
+209.503 451.872 209.352 451.816 209.245 451.71 c
+209.135 451.611 209.084 451.479 209.084 451.313 c
+209.084 451.185 209.121 451.078 209.201 450.99 c
+209.279 450.91 209.47 450.806 209.774 450.681 c
+210.252 450.494 210.583 450.307 210.759 450.123 c
+210.935 449.946 211.024 449.719 211.024 449.447 c
+211.024 449.094 210.899 448.815 210.656 448.608 c
+210.421 448.403 210.105 448.3 209.715 448.3 c
+209.293 448.3 208.955 448.418 208.701 448.653 c
+208.444 448.895 208.319 449.2 208.319 449.564 c
+208.965 449.564 l
+208.973 449.337 209.044 449.16 209.171 449.035 c
+209.297 448.917 209.48 448.859 209.715 448.859 c
+209.929 448.859 210.091 448.907 210.201 449.006 c
+210.318 449.101 210.377 449.229 210.377 449.387 c
+212.714 453.312 m
+212.714 452.357 l
+213.317 452.357 l
+213.317 451.828 l
+212.714 451.828 l
+212.714 449.358 l
+212.714 449.2 212.736 449.083 212.788 449.006 c
+212.847 448.925 212.934 448.888 213.052 448.888 c
+213.14 448.888 213.229 448.903 213.317 448.932 c
+213.317 448.373 l
+213.17 448.326 213.015 448.3 212.861 448.3 c
+212.604 448.3 212.41 448.392 212.273 448.579 c
+212.134 448.763 212.067 449.024 212.067 449.358 c
+212.067 451.828 l
+211.465 451.828 l
+211.465 452.357 l
+212.067 452.357 l
+212.067 453.312 l
+h
+216.653 453.312 m
+216.653 452.357 l
+217.256 452.357 l
+217.256 451.828 l
+216.653 451.828 l
+216.653 449.358 l
+216.653 449.2 216.676 449.083 216.727 449.006 c
+216.786 448.925 216.874 448.888 216.992 448.888 c
+217.08 448.888 217.168 448.903 217.256 448.932 c
+217.256 448.373 l
+217.109 448.326 216.955 448.3 216.801 448.3 c
+216.543 448.3 216.348 448.392 216.213 448.579 c
+216.073 448.763 216.007 449.024 216.007 449.358 c
+216.007 451.828 l
+215.404 451.828 l
+215.404 452.357 l
+216.007 452.357 l
+216.007 453.312 l
+h
+217.815 450.549 m
+217.815 451.126 217.95 451.581 218.226 451.916 c
+218.509 452.258 218.881 452.431 219.344 452.431 c
+219.803 452.431 220.171 452.261 220.446 451.931 c
+220.728 451.608 220.876 451.159 220.886 450.593 c
+220.886 450.167 l
+220.886 449.597 220.743 449.142 220.46 448.799 c
+220.185 448.466 219.818 448.3 219.358 448.3 c
+218.895 448.3 218.524 448.462 218.241 448.785 c
+217.965 449.116 217.823 449.557 217.815 450.108 c
+h
+218.461 450.167 m
+218.461 449.763 218.538 449.447 218.696 449.212 c
+218.862 448.976 219.082 448.859 219.358 448.859 c
+219.924 448.859 220.218 449.27 220.24 450.093 c
+220.24 450.549 l
+220.24 450.95 220.156 451.269 219.99 451.504 c
+219.832 451.747 219.616 451.872 219.344 451.872 c
+219.078 451.872 218.862 451.747 218.696 451.504 c
+218.538 451.269 218.461 450.95 218.461 450.549 c
+h
+224.15 448.373 -0.646 5.644 re
+227.207 448.373 m
+227.167 448.462 227.141 448.608 227.134 448.815 c
+226.899 448.469 226.604 448.3 226.252 448.3 c
+225.888 448.3 225.605 448.396 225.399 448.594 c
+225.201 448.799 225.106 449.086 225.106 449.462 c
+225.106 449.862 225.241 450.181 225.517 450.417 c
+225.789 450.659 226.164 450.784 226.634 450.784 c
+227.119 450.784 l
+227.119 451.211 l
+227.119 451.446 227.064 451.611 226.958 451.71 c
+226.847 451.816 226.685 451.872 226.473 451.872 c
+226.274 451.872 226.112 451.814 225.987 451.696 c
+225.87 451.578 225.811 451.431 225.811 451.255 c
+225.164 451.255 l
+225.164 451.45 225.223 451.641 225.341 451.828 c
+225.466 452.011 225.627 452.159 225.825 452.269 c
+226.031 452.375 226.259 452.431 226.517 452.431 c
+226.918 452.431 227.222 452.327 227.428 452.122 c
+227.641 451.916 227.755 451.622 227.766 451.24 c
+227.766 449.227 l
+227.766 448.921 227.803 448.656 227.884 448.433 c
+227.884 448.373 l
+h
+226.34 448.888 m
+226.506 448.888 226.656 448.932 226.796 449.021 c
+226.943 449.109 227.049 449.219 227.119 449.358 c
+227.119 450.299 l
+226.752 450.299 l
+226.436 450.299 226.193 450.229 226.017 450.093 c
+225.84 449.965 225.752 449.777 225.752 449.535 c
+225.752 449.307 225.796 449.142 225.885 449.035 c
+225.973 448.936 226.124 448.888 226.34 448.888 c
+230.706 449.387 m
+230.706 449.535 230.65 449.656 230.544 449.755 c
+230.434 449.851 230.228 449.969 229.927 450.108 c
+229.582 450.255 229.339 450.376 229.191 450.476 c
+229.045 450.582 228.935 450.7 228.869 450.829 c
+228.799 450.953 228.765 451.111 228.765 451.299 c
+228.765 451.622 228.883 451.891 229.118 452.107 c
+229.353 452.321 229.655 452.431 230.03 452.431 c
+230.411 452.431 230.721 452.317 230.956 452.092 c
+231.191 451.864 231.308 451.578 231.308 451.226 c
+230.662 451.226 l
+230.662 451.402 230.602 451.552 230.486 451.681 c
+230.367 451.806 230.213 451.872 230.03 451.872 c
+229.831 451.872 229.681 451.816 229.574 451.71 c
+229.464 451.611 229.412 451.479 229.412 451.313 c
+229.412 451.185 229.449 451.078 229.53 450.99 c
+229.607 450.91 229.798 450.806 230.103 450.681 c
+230.581 450.494 230.912 450.307 231.088 450.123 c
+231.265 449.946 231.352 449.719 231.352 449.447 c
+231.352 449.094 231.228 448.815 230.985 448.608 c
+230.75 448.403 230.434 448.3 230.045 448.3 c
+229.622 448.3 229.284 448.418 229.03 448.653 c
+228.773 448.895 228.648 449.2 228.648 449.564 c
+229.295 449.564 l
+229.302 449.337 229.372 449.16 229.501 449.035 c
+229.625 448.917 229.809 448.859 230.045 448.859 c
+230.257 448.859 230.419 448.907 230.529 449.006 c
+230.647 449.101 230.706 449.229 230.706 449.387 c
+233.043 453.312 m
+233.043 452.357 l
+233.646 452.357 l
+233.646 451.828 l
+233.043 451.828 l
+233.043 449.358 l
+233.043 449.2 233.065 449.083 233.116 449.006 c
+233.175 448.925 233.264 448.888 233.381 448.888 c
+233.469 448.888 233.557 448.903 233.646 448.932 c
+233.646 448.373 l
+233.499 448.326 233.345 448.3 233.189 448.3 c
+232.933 448.3 232.738 448.392 232.602 448.579 c
+232.462 448.763 232.396 449.024 232.396 449.358 c
+232.396 451.828 l
+231.793 451.828 l
+231.793 452.357 l
+232.396 452.357 l
+232.396 453.312 l
+h
+f
+q 1 0 0 1 236.9825 452.3574 cm
+0 0 m
+0.029 -0.397 l
+0.264 -0.085 0.565 0.073 0.941 0.073 c
+1.624 0.073 1.977 -0.408 1.999 -1.367 c
+1.999 -3.984 l
+0.955 -3.984 l
+0.955 -1.441 l
+0.955 -1.216 0.918 -1.055 0.852 -0.956 c
+0.783 -0.86 0.665 -0.809 0.5 -0.809 c
+0.312 -0.809 0.166 -0.904 0.058 -1.088 c
+0.058 -3.984 l
+-0.985 -3.984 l
+-0.985 0 l
+h
+f
+Q
+q 1 0 0 1 242.9355 448.8588 cm
+0 0 m
+0.213 0 0.386 0.062 0.515 0.191 c
+0.65 0.327 0.723 0.518 0.735 0.764 c
+1.352 0.764 l
+1.33 0.382 1.194 0.062 0.941 -0.191 c
+0.683 -0.437 0.371 -0.559 0 -0.559 c
+-0.493 -0.559 -0.867 -0.408 -1.132 -0.103 c
+-1.389 0.21 -1.515 0.676 -1.515 1.294 c
+-1.515 1.735 l
+-1.515 2.329 -1.389 2.786 -1.132 3.102 c
+-0.867 3.414 -0.493 3.572 0 3.572 c
+0.401 3.572 0.721 3.439 0.956 3.175 c
+1.198 2.917 1.33 2.572 1.352 2.132 c
+0.735 2.132 l
+0.713 2.425 0.64 2.645 0.515 2.793 c
+0.397 2.94 0.224 3.013 0 3.013 c
+-0.294 3.013 -0.511 2.914 -0.647 2.72 c
+-0.786 2.531 -0.86 2.223 -0.867 1.793 c
+-0.867 1.278 l
+-0.867 0.808 -0.801 0.474 -0.661 0.279 c
+-0.515 0.092 -0.294 0 0 0 c
+1.97 1.69 m
+1.97 2.267 2.105 2.722 2.381 3.057 c
+2.664 3.399 3.035 3.572 3.499 3.572 c
+3.958 3.572 4.326 3.403 4.6 3.072 c
+4.883 2.749 5.031 2.3 5.041 1.735 c
+5.041 1.309 l
+5.041 0.738 4.898 0.283 4.615 -0.059 c
+4.34 -0.393 3.973 -0.559 3.513 -0.559 c
+3.05 -0.559 2.679 -0.397 2.396 -0.073 c
+2.12 0.257 1.977 0.698 1.97 1.249 c
+h
+2.616 1.309 m
+2.616 0.904 2.693 0.588 2.851 0.353 c
+3.017 0.118 3.237 0 3.513 0 c
+4.079 0 4.373 0.411 4.395 1.234 c
+4.395 1.69 l
+4.395 2.091 4.31 2.41 4.145 2.645 c
+3.987 2.888 3.77 3.013 3.499 3.013 c
+3.233 3.013 3.017 2.888 2.851 2.645 c
+2.693 2.41 2.616 2.091 2.616 1.69 c
+h
+6.497 3.499 m
+6.512 3.131 l
+6.755 3.425 7.073 3.572 7.467 3.572 c
+7.908 3.572 8.216 3.373 8.393 2.984 c
+8.646 3.373 8.995 3.572 9.437 3.572 c
+10.171 3.572 10.547 3.109 10.568 2.19 c
+10.568 -0.485 l
+9.922 -0.485 l
+9.922 2.132 l
+9.922 2.425 9.866 2.639 9.76 2.778 c
+9.66 2.914 9.488 2.984 9.246 2.984 c
+9.047 2.984 8.885 2.903 8.76 2.749 c
+8.643 2.602 8.573 2.41 8.555 2.175 c
+8.555 -0.485 l
+7.893 -0.485 l
+7.893 2.161 l
+7.893 2.708 7.673 2.984 7.231 2.984 c
+6.898 2.984 6.662 2.822 6.526 2.499 c
+6.526 -0.485 l
+5.88 -0.485 l
+5.88 3.499 l
+h
+12.156 3.499 m
+12.17 3.131 l
+12.413 3.425 12.733 3.572 13.126 3.572 c
+13.567 3.572 13.876 3.373 14.052 2.984 c
+14.306 3.373 14.655 3.572 15.096 3.572 c
+15.831 3.572 16.205 3.109 16.228 2.19 c
+16.228 -0.485 l
+15.581 -0.485 l
+15.581 2.132 l
+15.581 2.425 15.526 2.639 15.419 2.778 c
+15.32 2.914 15.147 2.984 14.905 2.984 c
+14.707 2.984 14.545 2.903 14.42 2.749 c
+14.302 2.602 14.232 2.41 14.214 2.175 c
+14.214 -0.485 l
+13.552 -0.485 l
+13.552 2.161 l
+13.552 2.708 13.332 2.984 12.891 2.984 c
+12.557 2.984 12.322 2.822 12.185 2.499 c
+12.185 -0.485 l
+11.539 -0.485 l
+11.539 3.499 l
+h
+17.903 -0.485 -0.646 3.984 re
+17.947 4.542 m
+17.947 4.432 17.918 4.34 17.859 4.262 c
+17.801 4.193 17.705 4.16 17.58 4.16 c
+17.462 4.16 17.367 4.193 17.3 4.262 c
+17.242 4.34 17.213 4.432 17.213 4.542 c
+17.213 4.659 17.242 4.752 17.3 4.821 c
+17.367 4.898 17.462 4.939 17.58 4.939 c
+17.705 4.939 17.801 4.898 17.859 4.821 c
+17.918 4.74 17.947 4.648 17.947 4.542 c
+19.771 4.453 m
+19.771 3.499 l
+20.373 3.499 l
+20.373 2.969 l
+19.771 2.969 l
+19.771 0.5 l
+19.771 0.341 19.792 0.224 19.844 0.147 c
+19.902 0.066 19.991 0.029 20.108 0.029 c
+20.197 0.029 20.284 0.044 20.373 0.073 c
+20.373 -0.485 l
+20.226 -0.532 20.072 -0.559 19.917 -0.559 c
+19.66 -0.559 19.465 -0.467 19.329 -0.279 c
+19.189 -0.096 19.123 0.166 19.123 0.5 c
+19.123 2.969 l
+18.52 2.969 l
+18.52 3.499 l
+19.123 3.499 l
+19.123 4.453 l
+h
+23.077 0.529 m
+23.077 0.676 23.023 0.798 22.915 0.897 c
+22.805 0.992 22.599 1.11 22.298 1.249 c
+21.953 1.396 21.71 1.517 21.564 1.617 c
+21.417 1.723 21.306 1.841 21.24 1.97 c
+21.17 2.094 21.137 2.252 21.137 2.44 c
+21.137 2.763 21.255 3.032 21.49 3.248 c
+21.725 3.462 22.026 3.572 22.401 3.572 c
+22.784 3.572 23.092 3.458 23.328 3.233 c
+23.563 3.006 23.68 2.72 23.68 2.367 c
+23.033 2.367 l
+23.033 2.543 22.975 2.693 22.857 2.822 c
+22.74 2.947 22.585 3.013 22.401 3.013 c
+22.202 3.013 22.052 2.958 21.946 2.851 c
+21.835 2.753 21.784 2.62 21.784 2.454 c
+21.784 2.326 21.82 2.219 21.901 2.132 c
+21.979 2.051 22.169 1.947 22.474 1.822 c
+22.952 1.635 23.283 1.448 23.459 1.264 c
+23.636 1.087 23.725 0.86 23.725 0.588 c
+23.725 0.235 23.599 -0.044 23.357 -0.25 c
+23.122 -0.455 22.805 -0.559 22.416 -0.559 c
+21.994 -0.559 21.655 -0.441 21.402 -0.206 c
+21.144 0.037 21.02 0.341 21.02 0.706 c
+21.666 0.706 l
+21.674 0.478 21.743 0.301 21.872 0.176 c
+21.997 0.058 22.181 0 22.416 0 c
+22.629 0 22.79 0.048 22.901 0.147 c
+23.019 0.243 23.077 0.371 23.077 0.529 c
+24.606 -0.133 m
+24.606 -0.015 24.639 0.081 24.709 0.162 c
+24.775 0.239 24.878 0.279 25.018 0.279 c
+25.165 0.279 25.271 0.239 25.341 0.162 c
+25.418 0.081 25.458 -0.015 25.458 -0.133 c
+25.458 -0.243 25.418 -0.335 25.341 -0.412 c
+25.271 -0.489 25.165 -0.53 25.018 -0.53 c
+24.878 -0.53 24.775 -0.489 24.709 -0.412 c
+24.639 -0.335 24.606 -0.243 24.606 -0.133 c
+f
+Q
+0.113 0.082 0.09 0 k
+35.668 441.263 238.665 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 40.8563 434.424 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.69 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.771 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.279 -3.219 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.985 c
+-3.322 2.18 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.003 -2.469 3.043 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.182 -0.103 1.999 c
+-0.941 1.882 l
+-1.01 2.253 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.455 c
+-2.26 2.425 -2.319 2.385 -2.366 2.338 c
+-2.406 2.297 -2.437 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.44 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.014 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.147 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.411 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.632 5.137 1.779 c
+5.245 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.152 2.22 c
+8.004 2.22 l
+7.993 2.139 7.982 2.028 7.975 1.882 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.871 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.279 5.835 1.162 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.22 l
+13.644 2.22 l
+13.924 3.117 l
+14.497 3.117 l
+14.497 2.22 l
+15.732 2.22 l
+15.732 1.602 l
+14.497 1.602 l
+14.497 -0.103 l
+14.497 -0.324 l
+14.504 -0.393 14.527 -0.455 14.556 -0.515 c
+14.593 -0.565 14.648 -0.61 14.718 -0.646 c
+14.795 -0.676 14.909 -0.69 15.056 -0.69 c
+15.192 -0.69 15.327 -0.687 15.468 -0.676 c
+15.603 -0.658 15.736 -0.632 15.865 -0.602 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.23 15.629 -1.249 c
+15.549 -1.261 15.471 -1.267 15.394 -1.278 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.041 -1.301 14.942 -1.308 14.835 -1.308 c
+14.648 -1.308 14.486 -1.294 14.35 -1.264 c
+14.221 -1.228 14.107 -1.183 14.012 -1.132 c
+13.924 -1.084 13.85 -1.025 13.791 -0.955 c
+13.733 -0.878 13.689 -0.801 13.66 -0.72 c
+13.63 -0.632 13.608 -0.544 13.6 -0.455 c
+13.59 -0.36 13.586 -0.264 13.586 -0.176 c
+h
+23.221 -0.646 m
+24.353 -0.646 l
+24.353 -1.264 l
+21.045 -1.264 l
+21.045 -0.646 l
+22.31 -0.646 l
+22.31 2.896 l
+21.384 2.896 l
+21.384 3.514 l
+23.221 3.514 l
+h
+28.384 0.485 m
+28.384 0.21 28.347 -0.04 28.281 -0.264 c
+28.212 -0.482 28.108 -0.669 27.973 -0.823 c
+27.833 -0.981 27.657 -1.103 27.443 -1.19 c
+27.227 -1.278 26.973 -1.323 26.679 -1.323 c
+26.404 -1.323 26.157 -1.278 25.944 -1.19 c
+25.739 -1.103 25.566 -0.981 25.43 -0.823 c
+25.29 -0.669 25.187 -0.482 25.121 -0.264 c
+25.051 -0.04 25.018 0.21 25.018 0.485 c
+25.018 0.738 25.047 0.974 25.106 1.191 c
+25.172 1.415 25.275 1.606 25.415 1.764 c
+25.55 1.929 25.727 2.058 25.944 2.146 c
+26.157 2.234 26.414 2.278 26.709 2.278 c
+27.021 2.278 27.281 2.234 27.487 2.146 c
+27.701 2.058 27.873 1.929 28.002 1.764 c
+28.138 1.606 28.237 1.415 28.296 1.191 c
+28.355 0.974 28.384 0.738 28.384 0.485 c
+27.429 0.485 m
+27.429 0.691 27.414 0.867 27.385 1.014 c
+27.362 1.162 27.326 1.282 27.267 1.382 c
+27.208 1.477 27.135 1.548 27.046 1.588 c
+26.959 1.635 26.848 1.661 26.724 1.661 c
+26.458 1.661 26.267 1.562 26.15 1.367 c
+26.032 1.18 25.974 0.886 25.974 0.485 c
+25.974 0.063 26.032 -0.243 26.15 -0.426 c
+26.267 -0.613 26.444 -0.706 26.679 -0.706 c
+26.804 -0.706 26.918 -0.687 27.017 -0.646 c
+27.113 -0.599 27.194 -0.525 27.252 -0.426 c
+27.318 -0.33 27.362 -0.206 27.385 -0.058 c
+27.414 0.088 27.429 0.268 27.429 0.485 c
+30.769 -2.66 m
+30.552 -2.66 30.361 -2.635 30.196 -2.587 c
+30.027 -2.547 29.887 -2.484 29.77 -2.396 c
+29.652 -2.315 29.552 -2.219 29.475 -2.102 c
+29.406 -1.984 29.358 -1.855 29.328 -1.72 c
+30.225 -1.617 l
+30.262 -1.753 30.331 -1.859 30.431 -1.94 c
+30.526 -2.028 30.651 -2.072 30.799 -2.072 c
+30.886 -2.072 30.967 -2.057 31.048 -2.028 c
+31.125 -1.999 31.195 -1.944 31.254 -1.866 c
+31.313 -1.797 31.357 -1.705 31.387 -1.587 c
+31.424 -1.469 31.445 -1.323 31.445 -1.147 c
+31.445 -0.955 l
+31.445 -0.889 31.449 -0.831 31.46 -0.779 c
+31.46 -0.588 l
+31.445 -0.588 l
+31.346 -0.816 31.202 -0.977 31.019 -1.072 c
+30.832 -1.172 30.626 -1.22 30.402 -1.22 c
+30.196 -1.22 30.012 -1.183 29.858 -1.103 c
+29.71 -1.014 29.582 -0.897 29.475 -0.75 c
+29.376 -0.595 29.303 -0.411 29.255 -0.206 c
+29.203 0.008 29.182 0.243 29.182 0.5 c
+29.182 0.771 29.203 1.018 29.255 1.235 c
+29.313 1.448 29.394 1.632 29.505 1.779 c
+29.612 1.933 29.743 2.051 29.901 2.132 c
+30.056 2.22 30.244 2.263 30.46 2.263 c
+30.556 2.263 30.655 2.253 30.755 2.234 c
+30.85 2.213 30.938 2.18 31.019 2.132 c
+31.107 2.08 31.185 2.018 31.254 1.941 c
+31.331 1.86 31.393 1.768 31.445 1.661 c
+31.46 1.661 l
+31.46 1.808 l
+31.467 1.867 31.474 1.918 31.474 1.97 c
+31.482 2.028 31.489 2.076 31.489 2.117 c
+31.497 2.165 31.507 2.198 31.519 2.22 c
+32.371 2.22 l
+32.36 2.139 32.349 2.028 32.342 1.882 c
+32.342 1.411 l
+32.342 -1.161 l
+32.342 -1.415 32.305 -1.635 32.239 -1.822 c
+32.17 -2.007 32.066 -2.161 31.931 -2.278 c
+31.79 -2.404 31.625 -2.499 31.43 -2.558 c
+31.232 -2.624 31.011 -2.66 30.769 -2.66 c
+31.46 0.53 m
+31.46 0.742 31.434 0.919 31.387 1.058 c
+31.346 1.205 31.291 1.323 31.225 1.411 c
+31.166 1.5 31.096 1.558 31.019 1.588 c
+30.938 1.625 30.861 1.646 30.784 1.646 c
+30.684 1.646 30.593 1.621 30.504 1.573 c
+30.424 1.532 30.358 1.463 30.298 1.367 c
+30.248 1.279 30.203 1.162 30.167 1.014 c
+30.137 0.875 30.122 0.706 30.122 0.5 c
+30.122 0.125 30.181 -0.154 30.298 -0.338 c
+30.416 -0.515 30.578 -0.602 30.784 -0.602 c
+30.85 -0.602 30.923 -0.588 31.004 -0.559 c
+31.092 -0.522 31.166 -0.463 31.225 -0.382 c
+31.291 -0.294 31.346 -0.176 31.387 -0.029 c
+31.434 0.118 31.46 0.301 31.46 0.53 c
+37.953 0.838 1.866 -0.794 re
+37.953 0.044 m
+42.013 0.838 1.867 -0.794 re
+42.013 0.044 m
+48.691 0.485 m
+48.691 0.21 48.654 -0.04 48.588 -0.264 c
+48.519 -0.482 48.415 -0.669 48.28 -0.823 c
+48.14 -0.981 47.964 -1.103 47.75 -1.19 c
+47.534 -1.278 47.28 -1.323 46.986 -1.323 c
+46.711 -1.323 46.464 -1.278 46.251 -1.19 c
+46.045 -1.103 45.872 -0.981 45.736 -0.823 c
+45.597 -0.669 45.494 -0.482 45.427 -0.264 c
+45.358 -0.04 45.325 0.21 45.325 0.485 c
+45.325 0.738 45.354 0.974 45.413 1.191 c
+45.479 1.415 45.582 1.606 45.722 1.764 c
+45.857 1.929 46.034 2.058 46.251 2.146 c
+46.464 2.234 46.721 2.278 47.015 2.278 c
+47.328 2.278 47.588 2.234 47.794 2.146 c
+48.008 2.058 48.18 1.929 48.309 1.764 c
+48.444 1.606 48.544 1.415 48.602 1.191 c
+48.662 0.974 48.691 0.738 48.691 0.485 c
+47.735 0.485 m
+47.735 0.691 47.721 0.867 47.692 1.014 c
+47.669 1.162 47.632 1.282 47.574 1.382 c
+47.515 1.477 47.441 1.548 47.353 1.588 c
+47.265 1.635 47.155 1.661 47.029 1.661 c
+46.765 1.661 46.574 1.562 46.457 1.367 c
+46.339 1.18 46.281 0.886 46.281 0.485 c
+46.281 0.063 46.339 -0.243 46.457 -0.426 c
+46.574 -0.613 46.751 -0.706 46.986 -0.706 c
+47.11 -0.706 47.224 -0.687 47.324 -0.646 c
+47.42 -0.599 47.5 -0.525 47.559 -0.426 c
+47.625 -0.33 47.669 -0.206 47.692 -0.058 c
+47.721 0.088 47.735 0.268 47.735 0.485 c
+51.737 -1.264 m
+51.737 0.721 l
+51.737 1.022 51.693 1.242 51.605 1.382 c
+51.524 1.529 51.388 1.602 51.193 1.602 c
+51.083 1.602 50.981 1.577 50.885 1.529 c
+50.796 1.477 50.715 1.411 50.649 1.323 c
+50.591 1.235 50.539 1.124 50.503 1 c
+50.473 0.882 50.458 0.75 50.458 0.603 c
+50.458 -1.264 l
+49.547 -1.264 l
+49.547 1.44 l
+49.547 1.661 l
+49.547 1.75 49.539 1.827 49.533 1.897 c
+49.533 2.087 l
+49.533 2.22 l
+50.385 2.22 l
+50.393 2.19 50.4 2.146 50.4 2.087 c
+50.4 1.897 l
+50.407 1.827 50.414 1.756 50.414 1.691 c
+50.422 1.621 50.429 1.565 50.429 1.529 c
+50.443 1.529 l
+50.561 1.793 50.712 1.985 50.9 2.103 c
+51.083 2.22 51.303 2.278 51.561 2.278 c
+51.744 2.278 51.906 2.249 52.046 2.19 c
+52.182 2.132 52.296 2.043 52.384 1.926 c
+52.473 1.808 52.535 1.665 52.575 1.5 c
+52.623 1.341 52.648 1.154 52.648 0.941 c
+52.648 -1.264 l
+h
+55.17 -1.323 m
+54.912 -1.323 54.684 -1.286 54.478 -1.22 c
+54.273 -1.143 54.096 -1.029 53.95 -0.881 c
+53.803 -0.727 53.685 -0.536 53.597 -0.309 c
+53.516 -0.085 53.479 0.181 53.479 0.485 c
+53.479 0.816 53.523 1.095 53.612 1.323 c
+53.707 1.558 53.836 1.742 53.994 1.882 c
+54.159 2.018 54.347 2.117 54.553 2.176 c
+54.758 2.242 54.967 2.278 55.184 2.278 c
+55.456 2.278 55.691 2.227 55.889 2.132 c
+56.095 2.043 56.261 1.911 56.39 1.735 c
+56.525 1.565 56.625 1.359 56.683 1.118 c
+56.75 0.882 56.787 0.617 56.787 0.324 c
+56.787 0.309 l
+54.42 0.309 l
+54.42 0.162 54.435 0.023 54.464 -0.103 c
+54.501 -0.231 54.555 -0.345 54.626 -0.441 c
+54.692 -0.529 54.776 -0.599 54.875 -0.646 c
+54.971 -0.698 55.085 -0.72 55.214 -0.72 c
+55.368 -0.72 55.507 -0.687 55.625 -0.617 c
+55.75 -0.551 55.839 -0.448 55.889 -0.309 c
+56.728 -0.382 l
+56.698 -0.482 56.643 -0.588 56.566 -0.706 c
+56.485 -0.816 56.382 -0.918 56.257 -1.014 c
+56.14 -1.103 55.985 -1.176 55.802 -1.234 c
+55.625 -1.294 55.412 -1.323 55.17 -1.323 c
+55.17 1.706 m
+55.081 1.706 54.993 1.691 54.905 1.661 c
+54.817 1.632 54.736 1.58 54.67 1.515 c
+54.6 1.444 54.541 1.357 54.493 1.249 c
+54.453 1.139 54.435 1.014 54.435 0.867 c
+55.904 0.867 l
+55.904 1.004 55.879 1.124 55.831 1.235 c
+55.791 1.341 55.735 1.43 55.669 1.5 c
+55.611 1.565 55.537 1.617 55.449 1.646 c
+55.361 1.683 55.265 1.706 55.17 1.706 c
+59.774 -0.646 m
+60.905 -0.646 l
+60.905 -1.264 l
+57.599 -1.264 l
+57.599 -0.646 l
+58.863 -0.646 l
+58.863 2.896 l
+57.936 2.896 l
+57.936 3.514 l
+59.774 3.514 l
+h
+63.835 -0.646 m
+64.967 -0.646 l
+64.967 -1.264 l
+61.659 -1.264 l
+61.659 -0.646 l
+62.923 -0.646 l
+62.923 1.602 l
+61.998 1.602 l
+61.998 2.22 l
+63.835 2.22 l
+h
+62.923 3.514 0.912 -0.676 re
+62.923 2.837 m
+67.983 -1.264 m
+67.983 0.721 l
+67.983 1.022 67.939 1.242 67.851 1.382 c
+67.77 1.529 67.634 1.602 67.44 1.602 c
+67.33 1.602 67.226 1.577 67.131 1.529 c
+67.043 1.477 66.962 1.411 66.896 1.323 c
+66.837 1.235 66.785 1.124 66.748 1 c
+66.719 0.882 66.705 0.75 66.705 0.603 c
+66.705 -1.264 l
+65.793 -1.264 l
+65.793 1.44 l
+65.793 1.661 l
+65.793 1.75 65.786 1.827 65.778 1.897 c
+65.778 2.087 l
+65.778 2.22 l
+66.631 2.22 l
+66.638 2.19 66.646 2.146 66.646 2.087 c
+66.646 1.897 l
+66.653 1.827 66.661 1.756 66.661 1.691 c
+66.667 1.621 66.675 1.565 66.675 1.529 c
+66.69 1.529 l
+66.808 1.793 66.958 1.985 67.145 2.103 c
+67.33 2.22 67.55 2.278 67.807 2.278 c
+67.991 2.278 68.153 2.249 68.292 2.19 c
+68.428 2.132 68.542 2.043 68.63 1.926 c
+68.718 1.808 68.781 1.665 68.822 1.5 c
+68.869 1.341 68.895 1.154 68.895 0.941 c
+68.895 -1.264 l
+h
+71.412 -1.323 m
+71.155 -1.323 70.927 -1.286 70.721 -1.22 c
+70.515 -1.143 70.339 -1.029 70.192 -0.881 c
+70.045 -0.727 69.927 -0.536 69.84 -0.309 c
+69.759 -0.085 69.722 0.181 69.722 0.485 c
+69.722 0.816 69.765 1.095 69.854 1.323 c
+69.95 1.558 70.078 1.742 70.236 1.882 c
+70.401 2.018 70.588 2.117 70.794 2.176 c
+71 2.242 71.21 2.278 71.427 2.278 c
+71.698 2.278 71.934 2.227 72.132 2.132 c
+72.338 2.043 72.504 1.911 72.632 1.735 c
+72.768 1.565 72.867 1.359 72.926 1.118 c
+72.992 0.882 73.029 0.617 73.029 0.324 c
+73.029 0.309 l
+70.663 0.309 l
+70.663 0.162 70.677 0.023 70.706 -0.103 c
+70.743 -0.231 70.798 -0.345 70.868 -0.441 c
+70.935 -0.529 71.018 -0.599 71.118 -0.646 c
+71.213 -0.698 71.328 -0.72 71.456 -0.72 c
+71.61 -0.72 71.75 -0.687 71.868 -0.617 c
+71.993 -0.551 72.08 -0.448 72.132 -0.309 c
+72.97 -0.382 l
+72.94 -0.482 72.886 -0.588 72.809 -0.706 c
+72.728 -0.816 72.624 -0.918 72.5 -1.014 c
+72.382 -1.103 72.228 -1.176 72.044 -1.234 c
+71.868 -1.294 71.654 -1.323 71.412 -1.323 c
+71.412 1.706 m
+71.324 1.706 71.236 1.691 71.147 1.661 c
+71.059 1.632 70.978 1.58 70.912 1.515 c
+70.842 1.444 70.783 1.357 70.736 1.249 c
+70.696 1.139 70.677 1.014 70.677 0.867 c
+72.147 0.867 l
+72.147 1.004 72.121 1.124 72.074 1.235 c
+72.033 1.341 71.978 1.43 71.912 1.5 c
+71.853 1.565 71.779 1.617 71.691 1.646 c
+71.603 1.683 71.507 1.706 71.412 1.706 c
+78.567 0.838 1.866 -0.794 re
+78.567 0.044 m
+82.627 0.838 1.867 -0.794 re
+82.627 0.044 m
+87.629 -2.66 m
+87.412 -2.66 87.221 -2.635 87.055 -2.587 c
+86.887 -2.547 86.747 -2.484 86.629 -2.396 c
+86.511 -2.315 86.413 -2.219 86.335 -2.102 c
+86.265 -1.984 86.218 -1.855 86.188 -1.72 c
+87.085 -1.617 l
+87.122 -1.753 87.191 -1.859 87.29 -1.94 c
+87.386 -2.028 87.511 -2.072 87.658 -2.072 c
+87.747 -2.072 87.827 -2.057 87.908 -2.028 c
+87.985 -1.999 88.055 -1.944 88.113 -1.866 c
+88.173 -1.797 88.217 -1.705 88.246 -1.587 c
+88.283 -1.469 88.304 -1.323 88.304 -1.147 c
+88.304 -0.955 l
+88.304 -0.889 88.308 -0.831 88.319 -0.779 c
+88.319 -0.588 l
+88.304 -0.588 l
+88.206 -0.816 88.063 -0.977 87.878 -1.072 c
+87.691 -1.172 87.485 -1.22 87.261 -1.22 c
+87.055 -1.22 86.872 -1.183 86.717 -1.103 c
+86.571 -1.014 86.442 -0.897 86.335 -0.75 c
+86.236 -0.595 86.162 -0.411 86.114 -0.206 c
+86.064 0.008 86.041 0.243 86.041 0.5 c
+86.041 0.771 86.064 1.018 86.114 1.235 c
+86.174 1.448 86.255 1.632 86.365 1.779 c
+86.471 1.933 86.604 2.051 86.762 2.132 c
+86.916 2.22 87.103 2.263 87.32 2.263 c
+87.415 2.263 87.515 2.253 87.614 2.234 c
+87.71 2.213 87.797 2.18 87.878 2.132 c
+87.967 2.08 88.044 2.018 88.113 1.941 c
+88.191 1.86 88.254 1.768 88.304 1.661 c
+88.319 1.661 l
+88.319 1.808 l
+88.327 1.867 88.334 1.918 88.334 1.97 c
+88.342 2.028 88.349 2.076 88.349 2.117 c
+88.356 2.165 88.367 2.198 88.379 2.22 c
+89.231 2.22 l
+89.22 2.139 89.208 2.028 89.202 1.882 c
+89.202 1.411 l
+89.202 -1.161 l
+89.202 -1.415 89.165 -1.635 89.098 -1.822 c
+89.029 -2.007 88.926 -2.161 88.79 -2.278 c
+88.651 -2.404 88.485 -2.499 88.29 -2.558 c
+88.092 -2.624 87.872 -2.66 87.629 -2.66 c
+88.319 0.53 m
+88.319 0.742 88.294 0.919 88.246 1.058 c
+88.206 1.205 88.15 1.323 88.084 1.411 c
+88.026 1.5 87.955 1.558 87.878 1.588 c
+87.797 1.625 87.72 1.646 87.643 1.646 c
+87.544 1.646 87.452 1.621 87.364 1.573 c
+87.284 1.532 87.217 1.463 87.159 1.367 c
+87.107 1.279 87.063 1.162 87.026 1.014 c
+86.997 0.875 86.982 0.706 86.982 0.5 c
+86.982 0.125 87.041 -0.154 87.159 -0.338 c
+87.276 -0.515 87.438 -0.602 87.643 -0.602 c
+87.71 -0.602 87.783 -0.588 87.864 -0.559 c
+87.952 -0.522 88.026 -0.463 88.084 -0.382 c
+88.15 -0.294 88.206 -0.176 88.246 -0.029 c
+88.294 0.118 88.319 0.301 88.319 0.53 c
+93.174 1.47 m
+93.075 1.477 92.971 1.488 92.865 1.5 c
+92.755 1.517 92.634 1.529 92.498 1.529 c
+92.321 1.529 92.163 1.488 92.028 1.411 c
+91.888 1.341 91.77 1.242 91.674 1.118 c
+91.587 0.989 91.517 0.842 91.469 0.676 c
+91.429 0.507 91.41 0.331 91.41 0.147 c
+91.41 -1.264 l
+90.513 -1.264 l
+90.513 0.985 l
+90.513 1.11 90.502 1.235 90.484 1.353 c
+90.473 1.477 90.459 1.595 90.44 1.706 c
+90.429 1.823 90.414 1.918 90.396 1.999 c
+90.374 2.087 90.355 2.161 90.337 2.22 c
+91.219 2.22 l
+91.226 2.168 91.238 2.117 91.248 2.058 c
+91.267 1.999 91.282 1.933 91.292 1.867 c
+91.311 1.808 91.325 1.742 91.336 1.675 c
+91.344 1.606 91.355 1.544 91.366 1.484 c
+91.381 1.484 l
+91.417 1.602 91.469 1.709 91.527 1.808 c
+91.594 1.904 91.674 1.988 91.763 2.058 c
+91.851 2.124 91.954 2.18 92.071 2.22 c
+92.196 2.257 92.343 2.278 92.512 2.278 c
+92.637 2.278 92.755 2.271 92.865 2.263 c
+92.983 2.253 93.085 2.238 93.174 2.22 c
+h
+95.18 -1.323 m
+95.011 -1.323 94.86 -1.301 94.725 -1.264 c
+94.596 -1.216 94.482 -1.147 94.386 -1.058 c
+94.299 -0.97 94.228 -0.864 94.181 -0.735 c
+94.129 -0.599 94.107 -0.448 94.107 -0.279 c
+94.107 -0.073 94.141 0.096 94.21 0.235 c
+94.276 0.382 94.372 0.493 94.49 0.574 c
+94.615 0.661 94.758 0.724 94.916 0.765 c
+95.081 0.802 95.257 0.827 95.445 0.838 c
+96.165 0.852 l
+96.165 1.029 l
+96.165 1.147 96.154 1.249 96.136 1.338 c
+96.113 1.426 96.081 1.492 96.033 1.544 c
+95.992 1.602 95.945 1.639 95.886 1.661 c
+95.827 1.679 95.761 1.691 95.695 1.691 c
+95.625 1.691 95.562 1.679 95.504 1.661 c
+95.452 1.65 95.404 1.625 95.357 1.588 c
+95.317 1.558 95.283 1.507 95.254 1.44 c
+95.232 1.382 95.217 1.301 95.209 1.205 c
+94.269 1.249 l
+94.299 1.397 94.342 1.532 94.401 1.661 c
+94.467 1.786 94.563 1.897 94.681 1.985 c
+94.798 2.08 94.938 2.153 95.107 2.205 c
+95.283 2.253 95.489 2.278 95.724 2.278 c
+96.165 2.278 96.496 2.168 96.724 1.955 c
+96.959 1.75 97.077 1.44 97.077 1.029 c
+97.077 -0.235 l
+97.077 -0.455 l
+97.083 -0.515 97.098 -0.569 97.121 -0.617 c
+97.139 -0.658 97.168 -0.69 97.208 -0.72 c
+97.245 -0.742 97.297 -0.75 97.356 -0.75 c
+97.422 -0.75 97.492 -0.746 97.561 -0.735 c
+97.561 -1.22 l
+97.503 -1.23 97.447 -1.242 97.399 -1.249 c
+97.359 -1.261 97.319 -1.267 97.282 -1.278 c
+97.241 -1.286 97.198 -1.294 97.15 -1.294 c
+97.098 -1.301 97.04 -1.308 96.973 -1.308 c
+96.746 -1.308 96.58 -1.257 96.474 -1.147 c
+96.364 -1.029 96.301 -0.864 96.283 -0.646 c
+96.268 -0.646 l
+96.198 -0.757 96.129 -0.852 96.063 -0.941 c
+95.992 -1.022 95.915 -1.087 95.827 -1.147 c
+95.739 -1.205 95.639 -1.249 95.533 -1.278 c
+95.434 -1.308 95.317 -1.323 95.18 -1.323 c
+96.165 0.353 m
+95.739 0.339 l
+95.639 0.339 95.548 0.331 95.46 0.324 c
+95.379 0.312 95.313 0.287 95.254 0.25 c
+95.195 0.21 95.144 0.151 95.107 0.073 c
+95.066 0.004 95.048 -0.088 95.048 -0.206 c
+95.048 -0.374 95.081 -0.496 95.151 -0.573 c
+95.217 -0.654 95.317 -0.69 95.445 -0.69 c
+95.552 -0.69 95.651 -0.669 95.739 -0.617 c
+95.834 -0.569 95.915 -0.507 95.974 -0.426 c
+96.04 -0.349 96.092 -0.261 96.121 -0.162 c
+96.15 -0.055 96.165 0.059 96.165 0.177 c
+h
+99.153 2.22 m
+99.161 2.198 99.167 2.165 99.167 2.117 c
+99.175 2.076 99.182 2.028 99.182 1.97 c
+99.19 1.918 99.197 1.867 99.197 1.808 c
+99.197 1.646 l
+99.211 1.646 l
+99.271 1.764 99.336 1.86 99.417 1.941 c
+99.494 2.018 99.579 2.08 99.668 2.132 c
+99.755 2.19 99.843 2.227 99.932 2.249 c
+100.027 2.267 100.127 2.278 100.225 2.278 c
+100.431 2.278 100.611 2.234 100.769 2.146 c
+100.924 2.058 101.052 1.929 101.152 1.764 c
+101.258 1.606 101.335 1.415 101.387 1.191 c
+101.446 0.974 101.475 0.738 101.475 0.485 c
+101.475 0.221 101.446 -0.025 101.387 -0.249 c
+101.335 -0.467 101.258 -0.658 101.152 -0.823 c
+101.052 -0.981 100.921 -1.103 100.755 -1.19 c
+100.597 -1.278 100.41 -1.323 100.196 -1.323 c
+100.097 -1.323 99.998 -1.311 99.903 -1.294 c
+99.803 -1.271 99.711 -1.242 99.623 -1.19 c
+99.542 -1.143 99.465 -1.08 99.388 -0.999 c
+99.319 -0.922 99.259 -0.831 99.211 -0.72 c
+99.197 -0.72 l
+99.197 -0.808 l
+99.204 -0.849 99.211 -0.897 99.211 -0.955 c
+99.211 -1.117 l
+99.211 -1.294 l
+99.211 -2.631 l
+98.3 -2.631 l
+98.3 1.455 l
+98.3 1.621 98.293 1.768 98.286 1.897 c
+98.286 2.22 l
+h
+99.197 0.456 m
+99.197 0.228 99.215 0.037 99.256 -0.118 c
+99.303 -0.264 99.358 -0.382 99.417 -0.47 c
+99.483 -0.559 99.557 -0.625 99.637 -0.661 c
+99.715 -0.702 99.792 -0.72 99.873 -0.72 c
+99.969 -0.72 100.057 -0.698 100.138 -0.646 c
+100.225 -0.599 100.292 -0.529 100.343 -0.441 c
+100.402 -0.345 100.446 -0.22 100.476 -0.073 c
+100.512 0.081 100.534 0.268 100.534 0.485 c
+100.534 0.875 100.476 1.168 100.358 1.367 c
+100.248 1.562 100.094 1.661 99.888 1.661 c
+99.807 1.661 99.73 1.639 99.653 1.602 c
+99.572 1.562 99.498 1.5 99.432 1.411 c
+99.362 1.323 99.303 1.198 99.256 1.044 c
+99.215 0.886 99.197 0.691 99.197 0.456 c
+103.242 1.515 m
+103.36 1.786 103.511 1.985 103.699 2.103 c
+103.882 2.22 104.102 2.278 104.36 2.278 c
+104.566 2.278 104.734 2.242 104.875 2.176 c
+105.021 2.105 105.131 2.014 105.212 1.897 c
+105.301 1.779 105.359 1.635 105.389 1.47 c
+105.426 1.301 105.447 1.124 105.447 0.941 c
+105.447 -1.264 l
+104.536 -1.264 l
+104.536 0.735 l
+104.536 0.871 104.526 0.992 104.507 1.103 c
+104.495 1.209 104.47 1.297 104.433 1.367 c
+104.393 1.444 104.335 1.503 104.257 1.544 c
+104.187 1.58 104.096 1.602 103.978 1.602 c
+103.867 1.602 103.772 1.577 103.684 1.529 c
+103.595 1.477 103.514 1.411 103.448 1.323 c
+103.39 1.235 103.338 1.124 103.302 1 c
+103.272 0.882 103.257 0.75 103.257 0.603 c
+103.257 -1.264 l
+102.346 -1.264 l
+102.346 3.514 l
+103.257 3.514 l
+103.257 2.205 l
+103.257 2.135 103.25 2.065 103.242 1.999 c
+103.242 1.793 l
+103.242 1.735 103.236 1.679 103.228 1.632 c
+103.228 1.515 l
+h
+111.055 0.838 1.866 -0.794 re
+111.055 0.044 m
+115.119 0.838 1.867 -0.794 re
+115.119 0.044 m
+120.767 -1.264 m
+120.757 -1.246 120.746 -1.216 120.738 -1.176 c
+120.738 -1.128 120.731 -1.08 120.723 -1.029 c
+120.723 -0.97 120.717 -0.912 120.709 -0.852 c
+120.709 -0.69 l
+120.591 -0.926 120.448 -1.095 120.283 -1.19 c
+120.114 -1.278 119.915 -1.323 119.68 -1.323 c
+119.481 -1.323 119.306 -1.278 119.151 -1.19 c
+118.993 -1.103 118.861 -0.981 118.754 -0.823 c
+118.655 -0.658 118.577 -0.467 118.519 -0.249 c
+118.467 -0.037 118.446 0.206 118.446 0.47 c
+118.446 0.735 118.467 0.974 118.519 1.191 c
+118.577 1.415 118.655 1.606 118.754 1.764 c
+118.861 1.918 118.993 2.043 119.151 2.132 c
+119.316 2.227 119.507 2.278 119.724 2.278 c
+119.819 2.278 119.915 2.263 120.004 2.234 c
+120.099 2.213 120.195 2.18 120.283 2.132 c
+120.37 2.08 120.448 2.018 120.518 1.941 c
+120.595 1.86 120.657 1.768 120.709 1.661 c
+120.709 1.75 l
+120.709 1.897 l
+120.709 2.058 l
+120.709 2.234 l
+120.709 3.514 l
+121.606 3.514 l
+121.606 -0.5 l
+121.606 -0.676 121.609 -0.834 121.621 -0.97 c
+121.627 -1.099 121.635 -1.198 121.635 -1.264 c
+h
+120.723 0.485 m
+120.723 0.721 120.698 0.912 120.65 1.058 c
+120.609 1.213 120.555 1.338 120.488 1.426 c
+120.43 1.515 120.36 1.573 120.283 1.602 c
+120.202 1.639 120.125 1.661 120.048 1.661 c
+119.948 1.661 119.857 1.635 119.768 1.588 c
+119.687 1.548 119.622 1.477 119.562 1.382 c
+119.511 1.282 119.466 1.162 119.43 1.014 c
+119.401 0.867 119.386 0.684 119.386 0.47 c
+119.386 0.077 119.437 -0.216 119.547 -0.411 c
+119.665 -0.61 119.827 -0.706 120.033 -0.706 c
+120.11 -0.706 120.187 -0.687 120.268 -0.646 c
+120.345 -0.61 120.418 -0.544 120.488 -0.455 c
+120.555 -0.367 120.609 -0.246 120.65 -0.088 c
+120.698 0.066 120.723 0.258 120.723 0.485 c
+124.211 -1.323 m
+123.954 -1.323 123.726 -1.286 123.52 -1.22 c
+123.314 -1.143 123.138 -1.029 122.991 -0.881 c
+122.844 -0.727 122.726 -0.536 122.639 -0.309 c
+122.558 -0.085 122.521 0.181 122.521 0.485 c
+122.521 0.816 122.564 1.095 122.653 1.323 c
+122.749 1.558 122.877 1.742 123.035 1.882 c
+123.2 2.018 123.387 2.117 123.593 2.176 c
+123.799 2.242 124.009 2.278 124.226 2.278 c
+124.497 2.278 124.733 2.227 124.931 2.132 c
+125.137 2.043 125.303 1.911 125.431 1.735 c
+125.567 1.565 125.666 1.359 125.725 1.118 c
+125.791 0.882 125.828 0.617 125.828 0.324 c
+125.828 0.309 l
+123.462 0.309 l
+123.462 0.162 123.476 0.023 123.505 -0.103 c
+123.543 -0.231 123.597 -0.345 123.667 -0.441 c
+123.734 -0.529 123.817 -0.599 123.917 -0.646 c
+124.013 -0.698 124.127 -0.72 124.255 -0.72 c
+124.409 -0.72 124.549 -0.687 124.667 -0.617 c
+124.792 -0.551 124.879 -0.448 124.931 -0.309 c
+125.769 -0.382 l
+125.739 -0.482 125.685 -0.588 125.608 -0.706 c
+125.527 -0.816 125.424 -0.918 125.299 -1.014 c
+125.181 -1.103 125.027 -1.176 124.843 -1.234 c
+124.667 -1.294 124.453 -1.323 124.211 -1.323 c
+124.211 1.706 m
+124.123 1.706 124.035 1.691 123.946 1.661 c
+123.858 1.632 123.778 1.58 123.711 1.515 c
+123.641 1.444 123.582 1.357 123.535 1.249 c
+123.495 1.139 123.476 1.014 123.476 0.867 c
+124.946 0.867 l
+124.946 1.004 124.92 1.124 124.873 1.235 c
+124.832 1.341 124.777 1.43 124.711 1.5 c
+124.652 1.565 124.578 1.617 124.49 1.646 c
+124.402 1.683 124.306 1.706 124.211 1.706 c
+128.272 -1.323 m
+127.985 -1.323 127.742 -1.282 127.537 -1.205 c
+127.331 -1.117 127.158 -0.995 127.022 -0.837 c
+126.882 -0.683 126.78 -0.496 126.714 -0.279 c
+126.643 -0.055 126.61 0.191 126.61 0.456 c
+126.61 0.75 126.643 1.007 126.714 1.235 c
+126.791 1.459 126.897 1.646 127.036 1.793 c
+127.184 1.947 127.36 2.065 127.566 2.146 c
+127.772 2.234 128.007 2.278 128.272 2.278 c
+128.496 2.278 128.698 2.249 128.874 2.19 c
+129.051 2.132 129.201 2.047 129.33 1.941 c
+129.455 1.841 129.558 1.72 129.639 1.573 c
+129.716 1.434 129.771 1.282 129.8 1.118 c
+128.889 1.073 l
+128.86 1.249 128.79 1.389 128.683 1.5 c
+128.584 1.606 128.441 1.661 128.257 1.661 c
+128.011 1.661 127.834 1.558 127.728 1.353 c
+127.618 1.154 127.566 0.867 127.566 0.485 c
+127.566 -0.309 127.801 -0.706 128.272 -0.706 c
+128.437 -0.706 128.58 -0.654 128.698 -0.544 c
+128.815 -0.437 128.889 -0.276 128.918 -0.058 c
+129.83 -0.103 l
+129.8 -0.272 129.745 -0.426 129.668 -0.573 c
+129.598 -0.72 129.496 -0.852 129.359 -0.97 c
+129.23 -1.08 129.072 -1.168 128.889 -1.234 c
+128.713 -1.294 128.507 -1.323 128.272 -1.323 c
+133.978 0.485 m
+133.978 0.21 133.942 -0.04 133.876 -0.264 c
+133.806 -0.482 133.703 -0.669 133.567 -0.823 c
+133.427 -0.981 133.251 -1.103 133.037 -1.19 c
+132.821 -1.278 132.567 -1.323 132.274 -1.323 c
+131.998 -1.323 131.751 -1.278 131.539 -1.19 c
+131.333 -1.103 131.16 -0.981 131.024 -0.823 c
+130.884 -0.669 130.782 -0.482 130.715 -0.264 c
+130.645 -0.04 130.612 0.21 130.612 0.485 c
+130.612 0.738 130.641 0.974 130.701 1.191 c
+130.767 1.415 130.87 1.606 131.009 1.764 c
+131.146 1.929 131.322 2.058 131.539 2.146 c
+131.751 2.234 132.009 2.278 132.303 2.278 c
+132.615 2.278 132.876 2.234 133.082 2.146 c
+133.295 2.058 133.467 1.929 133.596 1.764 c
+133.733 1.606 133.831 1.415 133.891 1.191 c
+133.949 0.974 133.978 0.738 133.978 0.485 c
+133.023 0.485 m
+133.023 0.691 133.008 0.867 132.979 1.014 c
+132.957 1.162 132.92 1.282 132.862 1.382 c
+132.802 1.477 132.729 1.548 132.64 1.588 c
+132.553 1.635 132.442 1.661 132.318 1.661 c
+132.053 1.661 131.862 1.562 131.744 1.367 c
+131.626 1.18 131.568 0.886 131.568 0.485 c
+131.568 0.063 131.626 -0.243 131.744 -0.426 c
+131.862 -0.613 132.038 -0.706 132.274 -0.706 c
+132.399 -0.706 132.513 -0.687 132.611 -0.646 c
+132.707 -0.599 132.788 -0.525 132.847 -0.426 c
+132.912 -0.33 132.957 -0.206 132.979 -0.058 c
+133.008 0.088 133.023 0.268 133.023 0.485 c
+137.851 1.47 m
+137.752 1.477 137.65 1.488 137.543 1.5 c
+137.433 1.517 137.311 1.529 137.176 1.529 c
+136.999 1.529 136.841 1.488 136.705 1.411 c
+136.565 1.341 136.448 1.242 136.353 1.118 c
+136.264 0.989 136.195 0.842 136.147 0.676 c
+136.106 0.507 136.087 0.331 136.087 0.147 c
+136.087 -1.264 l
+135.191 -1.264 l
+135.191 0.985 l
+135.191 1.11 135.18 1.235 135.162 1.353 c
+135.15 1.477 135.136 1.595 135.117 1.706 c
+135.106 1.823 135.092 1.918 135.073 1.999 c
+135.052 2.087 135.033 2.161 135.015 2.22 c
+135.896 2.22 l
+135.904 2.168 135.915 2.117 135.926 2.058 c
+135.944 1.999 135.959 1.933 135.97 1.867 c
+135.989 1.808 136.004 1.742 136.014 1.675 c
+136.021 1.606 136.033 1.544 136.044 1.484 c
+136.058 1.484 l
+136.095 1.602 136.147 1.709 136.205 1.808 c
+136.272 1.904 136.353 1.988 136.44 2.058 c
+136.529 2.124 136.632 2.18 136.75 2.22 c
+136.874 2.257 137.022 2.278 137.19 2.278 c
+137.315 2.278 137.433 2.271 137.543 2.263 c
+137.66 2.253 137.764 2.238 137.851 2.22 c
+h
+139.854 -1.323 m
+139.686 -1.323 139.535 -1.301 139.399 -1.264 c
+139.27 -1.216 139.156 -1.147 139.061 -1.058 c
+138.973 -0.97 138.903 -0.864 138.855 -0.735 c
+138.803 -0.599 138.782 -0.448 138.782 -0.279 c
+138.782 -0.073 138.815 0.096 138.884 0.235 c
+138.95 0.382 139.046 0.493 139.164 0.574 c
+139.289 0.661 139.432 0.724 139.59 0.765 c
+139.755 0.802 139.931 0.827 140.119 0.838 c
+140.839 0.852 l
+140.839 1.029 l
+140.839 1.147 140.828 1.249 140.81 1.338 c
+140.788 1.426 140.754 1.492 140.707 1.544 c
+140.667 1.602 140.619 1.639 140.56 1.661 c
+140.501 1.679 140.435 1.691 140.369 1.691 c
+140.299 1.691 140.237 1.679 140.178 1.661 c
+140.126 1.65 140.079 1.625 140.031 1.588 c
+139.99 1.558 139.958 1.507 139.927 1.44 c
+139.906 1.382 139.891 1.301 139.884 1.205 c
+138.943 1.249 l
+138.973 1.397 139.017 1.532 139.075 1.661 c
+139.142 1.786 139.237 1.897 139.355 1.985 c
+139.472 2.08 139.612 2.153 139.781 2.205 c
+139.958 2.253 140.163 2.278 140.398 2.278 c
+140.839 2.278 141.17 2.168 141.398 1.955 c
+141.633 1.75 141.751 1.44 141.751 1.029 c
+141.751 -0.235 l
+141.751 -0.455 l
+141.758 -0.515 141.772 -0.569 141.795 -0.617 c
+141.813 -0.658 141.843 -0.69 141.883 -0.72 c
+141.92 -0.742 141.971 -0.75 142.03 -0.75 c
+142.096 -0.75 142.165 -0.746 142.236 -0.735 c
+142.236 -1.22 l
+142.177 -1.23 142.122 -1.242 142.074 -1.249 c
+142.034 -1.261 141.993 -1.267 141.957 -1.278 c
+141.916 -1.286 141.872 -1.294 141.824 -1.294 c
+141.772 -1.301 141.714 -1.308 141.648 -1.308 c
+141.419 -1.308 141.255 -1.257 141.148 -1.147 c
+141.038 -1.029 140.975 -0.864 140.957 -0.646 c
+140.943 -0.646 l
+140.872 -0.757 140.802 -0.852 140.736 -0.941 c
+140.667 -1.022 140.59 -1.087 140.501 -1.147 c
+140.413 -1.205 140.314 -1.249 140.207 -1.278 c
+140.108 -1.308 139.99 -1.323 139.854 -1.323 c
+140.839 0.353 m
+140.413 0.339 l
+140.314 0.339 140.222 0.331 140.133 0.324 c
+140.053 0.312 139.987 0.287 139.927 0.25 c
+139.869 0.21 139.817 0.151 139.781 0.073 c
+139.74 0.004 139.722 -0.088 139.722 -0.206 c
+139.722 -0.374 139.755 -0.496 139.825 -0.573 c
+139.891 -0.654 139.99 -0.69 140.119 -0.69 c
+140.226 -0.69 140.324 -0.669 140.413 -0.617 c
+140.509 -0.569 140.59 -0.507 140.648 -0.426 c
+140.714 -0.349 140.766 -0.261 140.795 -0.162 c
+140.825 -0.055 140.839 0.059 140.839 0.177 c
+h
+143.562 1.602 m
+143.019 1.602 l
+143.019 2.22 l
+143.607 2.22 l
+143.885 3.117 l
+144.459 3.117 l
+144.459 2.22 l
+145.693 2.22 l
+145.693 1.602 l
+144.459 1.602 l
+144.459 -0.103 l
+144.459 -0.324 l
+144.467 -0.393 144.488 -0.455 144.517 -0.515 c
+144.554 -0.565 144.61 -0.61 144.679 -0.646 c
+144.756 -0.676 144.87 -0.69 145.018 -0.69 c
+145.153 -0.69 145.29 -0.687 145.429 -0.676 c
+145.565 -0.658 145.697 -0.632 145.826 -0.602 c
+145.826 -1.205 l
+145.745 -1.216 145.668 -1.23 145.591 -1.249 c
+145.51 -1.261 145.433 -1.267 145.356 -1.278 c
+145.275 -1.286 145.186 -1.294 145.091 -1.294 c
+145.003 -1.301 144.904 -1.308 144.797 -1.308 c
+144.61 -1.308 144.448 -1.294 144.312 -1.264 c
+144.183 -1.228 144.07 -1.183 143.974 -1.132 c
+143.885 -1.084 143.812 -1.025 143.753 -0.955 c
+143.694 -0.878 143.65 -0.801 143.621 -0.72 c
+143.592 -0.632 143.57 -0.544 143.562 -0.455 c
+143.551 -0.36 143.547 -0.264 143.547 -0.176 c
+h
+148.578 -1.323 m
+148.321 -1.323 148.093 -1.286 147.887 -1.22 c
+147.682 -1.143 147.505 -1.029 147.358 -0.881 c
+147.212 -0.727 147.094 -0.536 147.006 -0.309 c
+146.925 -0.085 146.888 0.181 146.888 0.485 c
+146.888 0.816 146.932 1.095 147.021 1.323 c
+147.116 1.558 147.245 1.742 147.403 1.882 c
+147.568 2.018 147.755 2.117 147.961 2.176 c
+148.166 2.242 148.376 2.278 148.593 2.278 c
+148.864 2.278 149.1 2.227 149.298 2.132 c
+149.504 2.043 149.67 1.911 149.799 1.735 c
+149.934 1.565 150.034 1.359 150.092 1.118 c
+150.158 0.882 150.196 0.617 150.196 0.324 c
+150.196 0.309 l
+147.829 0.309 l
+147.829 0.162 147.844 0.023 147.873 -0.103 c
+147.91 -0.231 147.964 -0.345 148.035 -0.441 c
+148.101 -0.529 148.185 -0.599 148.284 -0.646 c
+148.38 -0.698 148.494 -0.72 148.623 -0.72 c
+148.777 -0.72 148.916 -0.687 149.034 -0.617 c
+149.159 -0.551 149.247 -0.448 149.298 -0.309 c
+150.136 -0.382 l
+150.107 -0.482 150.052 -0.588 149.975 -0.706 c
+149.894 -0.816 149.791 -0.918 149.666 -1.014 c
+149.548 -1.103 149.394 -1.176 149.211 -1.234 c
+149.034 -1.294 148.821 -1.323 148.578 -1.323 c
+148.578 1.706 m
+148.49 1.706 148.402 1.691 148.314 1.661 c
+148.226 1.632 148.145 1.58 148.079 1.515 c
+148.008 1.444 147.95 1.357 147.902 1.249 c
+147.862 1.139 147.844 1.014 147.844 0.867 c
+149.313 0.867 l
+149.313 1.004 149.288 1.124 149.24 1.235 c
+149.199 1.341 149.144 1.43 149.078 1.5 c
+149.02 1.565 148.945 1.617 148.858 1.646 c
+148.769 1.683 148.673 1.706 148.578 1.706 c
+f
+Q
+q 1 0 0 1 51.1272 419.6667 cm
+0 0 m
+-1.808 0 l
+-2.219 -1.397 l
+-2.91 -1.397 l
+-1.19 3.954 l
+-0.617 3.954 l
+1.118 -1.397 l
+0.426 -1.397 l
+h
+-1.631 0.588 m
+-0.176 0.588 l
+-0.897 3.013 l
+h
+2.367 2.587 m
+2.381 2.146 l
+2.635 2.487 2.959 2.66 3.352 2.66 c
+4.057 2.66 4.414 2.19 4.424 1.249 c
+4.424 -1.397 l
+3.778 -1.397 l
+3.778 1.22 l
+3.778 1.532 3.723 1.753 3.616 1.882 c
+3.506 2.006 3.352 2.072 3.146 2.072 c
+2.988 2.072 2.841 2.017 2.705 1.911 c
+2.577 1.801 2.473 1.664 2.396 1.499 c
+2.396 -1.397 l
+1.75 -1.397 l
+1.75 2.587 l
+h
+6.982 0.779 m
+6.982 1.356 7.119 1.811 7.394 2.146 c
+7.676 2.487 8.048 2.66 8.511 2.66 c
+8.97 2.66 9.338 2.491 9.613 2.161 c
+9.897 1.837 10.043 1.389 10.055 0.823 c
+10.055 0.397 l
+10.055 -0.173 9.911 -0.628 9.628 -0.971 c
+9.353 -1.305 8.985 -1.47 8.526 -1.47 c
+8.063 -1.47 7.691 -1.309 7.408 -0.985 c
+7.133 -0.655 6.99 -0.214 6.982 0.338 c
+h
+7.629 0.397 m
+7.629 -0.008 7.707 -0.324 7.865 -0.559 c
+8.029 -0.794 8.25 -0.912 8.526 -0.912 c
+9.091 -0.912 9.386 -0.5 9.407 0.323 c
+9.407 0.779 l
+9.407 1.18 9.323 1.499 9.158 1.734 c
+9 1.976 8.783 2.102 8.511 2.102 c
+8.247 2.102 8.029 1.976 7.865 1.734 c
+7.707 1.499 7.629 1.18 7.629 0.779 c
+h
+11.965 -0.412 m
+12.715 2.587 l
+13.376 2.587 l
+12.2 -1.397 l
+11.715 -1.397 l
+10.525 2.587 l
+11.186 2.587 l
+h
+15.435 -1.47 m
+14.934 -1.47 14.552 -1.324 14.288 -1.029 c
+14.024 -0.736 13.891 -0.302 13.891 0.279 c
+13.891 0.75 l
+13.891 1.344 14.016 1.811 14.273 2.146 c
+14.537 2.487 14.898 2.66 15.36 2.66 c
+15.82 2.66 16.162 2.506 16.39 2.204 c
+16.625 1.911 16.746 1.448 16.757 0.823 c
+16.757 0.397 l
+14.537 0.397 l
+14.537 0.309 l
+14.537 -0.125 14.614 -0.437 14.772 -0.632 c
+14.938 -0.819 15.169 -0.912 15.464 -0.912 c
+15.659 -0.912 15.831 -0.879 15.978 -0.809 c
+16.125 -0.732 16.261 -0.614 16.39 -0.456 c
+16.727 -0.867 l
+16.441 -1.272 16.011 -1.47 15.435 -1.47 c
+15.36 2.102 m
+15.085 2.102 14.883 2.006 14.758 1.822 c
+14.629 1.635 14.556 1.344 14.537 0.955 c
+16.11 0.955 l
+16.11 1.043 l
+16.089 1.425 16.022 1.693 15.905 1.851 c
+15.787 2.017 15.603 2.102 15.36 2.102 c
+19.183 1.969 m
+19.094 1.988 18.995 1.999 18.888 1.999 c
+18.554 1.999 18.319 1.815 18.183 1.455 c
+18.183 -1.397 l
+17.536 -1.397 l
+17.536 2.587 l
+18.169 2.587 l
+18.183 2.175 l
+18.359 2.499 18.602 2.66 18.918 2.66 c
+19.025 2.66 19.113 2.638 19.183 2.601 c
+h
+21.035 -0.412 m
+21.785 2.587 l
+22.446 2.587 l
+21.27 -1.397 l
+20.785 -1.397 l
+19.594 2.587 l
+20.255 2.587 l
+h
+23.827 -1.397 -0.646 3.984 re
+23.871 3.63 m
+23.871 3.52 23.842 3.428 23.783 3.351 c
+23.725 3.281 23.629 3.248 23.504 3.248 c
+23.387 3.248 23.291 3.281 23.225 3.351 c
+23.166 3.428 23.137 3.52 23.137 3.63 c
+23.137 3.748 23.166 3.84 23.225 3.91 c
+23.291 3.987 23.387 4.027 23.504 4.027 c
+23.629 4.027 23.725 3.987 23.783 3.91 c
+23.842 3.829 23.871 3.737 23.871 3.63 c
+26.267 -1.47 m
+25.768 -1.47 25.386 -1.324 25.121 -1.029 c
+24.856 -0.736 24.724 -0.302 24.724 0.279 c
+24.724 0.75 l
+24.724 1.344 24.849 1.811 25.106 2.146 c
+25.371 2.487 25.731 2.66 26.194 2.66 c
+26.653 2.66 26.995 2.506 27.223 2.204 c
+27.458 1.911 27.58 1.448 27.59 0.823 c
+27.59 0.397 l
+25.371 0.397 l
+25.371 0.309 l
+25.371 -0.125 25.448 -0.437 25.606 -0.632 c
+25.772 -0.819 26.003 -0.912 26.296 -0.912 c
+26.491 -0.912 26.664 -0.879 26.811 -0.809 c
+26.959 -0.732 27.094 -0.614 27.223 -0.456 c
+27.561 -0.867 l
+27.274 -1.272 26.844 -1.47 26.267 -1.47 c
+26.194 2.102 m
+25.918 2.102 25.716 2.006 25.591 1.822 c
+25.463 1.635 25.39 1.344 25.371 0.955 c
+26.944 0.955 l
+26.944 1.043 l
+26.921 1.425 26.855 1.693 26.738 1.851 c
+26.62 2.017 26.437 2.102 26.194 2.102 c
+31.339 -0.25 m
+31.941 2.587 l
+32.588 2.587 l
+31.603 -1.397 l
+31.089 -1.397 l
+30.31 1.455 l
+29.56 -1.397 l
+29.031 -1.397 l
+28.075 2.587 l
+28.708 2.587 l
+29.325 -0.177 l
+30.059 2.587 l
+30.574 2.587 l
+h
+37.953 -0.25 m
+38.556 2.587 l
+39.202 2.587 l
+38.218 -1.397 l
+37.703 -1.397 l
+36.924 1.455 l
+36.174 -1.397 l
+35.646 -1.397 l
+34.69 2.587 l
+35.322 2.587 l
+35.939 -0.177 l
+36.675 2.587 l
+37.188 2.587 l
+h
+40.584 -1.397 -0.647 3.984 re
+40.629 3.63 m
+40.629 3.52 40.6 3.428 40.54 3.351 c
+40.481 3.281 40.386 3.248 40.261 3.248 c
+40.143 3.248 40.048 3.281 39.981 3.351 c
+39.923 3.428 39.894 3.52 39.894 3.63 c
+39.894 3.748 39.923 3.84 39.981 3.91 c
+40.048 3.987 40.143 4.027 40.261 4.027 c
+40.386 4.027 40.481 3.987 40.54 3.91 c
+40.6 3.829 40.629 3.737 40.629 3.63 c
+42.451 3.542 m
+42.451 2.587 l
+43.054 2.587 l
+43.054 2.057 l
+42.451 2.057 l
+42.451 -0.412 l
+42.451 -0.57 42.473 -0.688 42.524 -0.765 c
+42.584 -0.846 42.672 -0.882 42.79 -0.882 c
+42.877 -0.882 42.965 -0.867 43.054 -0.838 c
+43.054 -1.397 l
+42.907 -1.444 42.753 -1.47 42.598 -1.47 c
+42.341 -1.47 42.146 -1.378 42.011 -1.191 c
+41.87 -1.008 41.805 -0.746 41.805 -0.412 c
+41.805 2.057 l
+41.202 2.057 l
+41.202 2.587 l
+41.805 2.587 l
+41.805 3.542 l
+h
+44.465 2.175 m
+44.718 2.499 45.038 2.66 45.42 2.66 c
+46.125 2.66 46.482 2.19 46.493 1.249 c
+46.493 -1.397 l
+45.847 -1.397 l
+45.847 1.22 l
+45.847 1.532 45.791 1.753 45.685 1.882 c
+45.575 2.006 45.42 2.072 45.215 2.072 c
+45.057 2.072 44.91 2.017 44.774 1.911 c
+44.645 1.801 44.542 1.664 44.465 1.499 c
+44.465 -1.397 l
+43.818 -1.397 l
+43.818 4.247 l
+44.465 4.247 l
+h
+50.815 1.969 m
+50.727 1.988 50.628 1.999 50.521 1.999 c
+50.187 1.999 49.951 1.815 49.815 1.455 c
+49.815 -1.397 l
+49.169 -1.397 l
+49.169 2.587 l
+49.801 2.587 l
+49.815 2.175 l
+49.992 2.499 50.235 2.66 50.551 2.66 c
+50.657 2.66 50.745 2.638 50.815 2.601 c
+h
+52.814 -1.47 m
+52.315 -1.47 51.932 -1.324 51.667 -1.029 c
+51.403 -0.736 51.27 -0.302 51.27 0.279 c
+51.27 0.75 l
+51.27 1.344 51.395 1.811 51.653 2.146 c
+51.918 2.487 52.278 2.66 52.741 2.66 c
+53.2 2.66 53.541 2.506 53.77 2.204 c
+54.005 1.911 54.125 1.448 54.137 0.823 c
+54.137 0.397 l
+51.918 0.397 l
+51.918 0.309 l
+51.918 -0.125 51.995 -0.437 52.153 -0.632 c
+52.318 -0.819 52.55 -0.912 52.843 -0.912 c
+53.038 -0.912 53.211 -0.879 53.358 -0.809 c
+53.505 -0.732 53.641 -0.614 53.77 -0.456 c
+54.108 -0.867 l
+53.821 -1.272 53.391 -1.47 52.814 -1.47 c
+52.741 2.102 m
+52.465 2.102 52.263 2.006 52.138 1.822 c
+52.009 1.635 51.935 1.344 51.918 0.955 c
+53.49 0.955 l
+53.49 1.043 l
+53.468 1.425 53.402 1.693 53.284 1.851 c
+53.167 2.017 52.983 2.102 52.741 2.102 c
+55.21 -1.397 m
+55.21 2.057 l
+54.68 2.057 l
+54.68 2.587 l
+55.21 2.587 l
+55.21 3.042 l
+55.21 3.443 55.305 3.755 55.504 3.983 c
+55.71 4.207 55.989 4.321 56.342 4.321 c
+56.477 4.321 56.61 4.299 56.739 4.263 c
+56.709 3.719 l
+56.61 3.737 56.511 3.748 56.415 3.748 c
+56.041 3.748 55.856 3.484 55.856 2.954 c
+55.856 2.587 l
+56.533 2.587 l
+56.533 2.057 l
+55.856 2.057 l
+55.856 -1.397 l
+h
+58.634 -1.47 m
+58.135 -1.47 57.753 -1.324 57.489 -1.029 c
+57.223 -0.736 57.092 -0.302 57.092 0.279 c
+57.092 0.75 l
+57.092 1.344 57.217 1.811 57.474 2.146 c
+57.738 2.487 58.098 2.66 58.561 2.66 c
+59.021 2.66 59.363 2.506 59.59 2.204 c
+59.825 1.911 59.947 1.448 59.958 0.823 c
+59.958 0.397 l
+57.738 0.397 l
+57.738 0.309 l
+57.738 -0.125 57.815 -0.437 57.973 -0.632 c
+58.139 -0.819 58.37 -0.912 58.665 -0.912 c
+58.859 -0.912 59.031 -0.879 59.179 -0.809 c
+59.326 -0.732 59.461 -0.614 59.59 -0.456 c
+59.928 -0.867 l
+59.642 -1.272 59.212 -1.47 58.634 -1.47 c
+58.561 2.102 m
+58.285 2.102 58.083 2.006 57.959 1.822 c
+57.83 1.635 57.757 1.344 57.738 0.955 c
+59.311 0.955 l
+59.311 1.043 l
+59.289 1.425 59.222 1.693 59.105 1.851 c
+58.987 2.017 58.804 2.102 58.561 2.102 c
+62.383 1.969 m
+62.295 1.988 62.196 1.999 62.089 1.999 c
+61.755 1.999 61.52 1.815 61.383 1.455 c
+61.383 -1.397 l
+60.737 -1.397 l
+60.737 2.587 l
+61.369 2.587 l
+61.383 2.175 l
+61.56 2.499 61.803 2.66 62.118 2.66 c
+62.225 2.66 62.314 2.638 62.383 2.601 c
+h
+64.382 -1.47 m
+63.883 -1.47 63.5 -1.324 63.236 -1.029 c
+62.971 -0.736 62.839 -0.302 62.839 0.279 c
+62.839 0.75 l
+62.839 1.344 62.964 1.811 63.221 2.146 c
+63.486 2.487 63.845 2.66 64.309 2.66 c
+64.768 2.66 65.11 2.506 65.337 2.204 c
+65.572 1.911 65.694 1.448 65.705 0.823 c
+65.705 0.397 l
+63.486 0.397 l
+63.486 0.309 l
+63.486 -0.125 63.563 -0.437 63.721 -0.632 c
+63.886 -0.819 64.118 -0.912 64.411 -0.912 c
+64.606 -0.912 64.779 -0.879 64.926 -0.809 c
+65.073 -0.732 65.209 -0.614 65.337 -0.456 c
+65.676 -0.867 l
+65.389 -1.272 64.959 -1.47 64.382 -1.47 c
+64.309 2.102 m
+64.033 2.102 63.831 2.006 63.706 1.822 c
+63.577 1.635 63.504 1.344 63.486 0.955 c
+65.059 0.955 l
+65.059 1.043 l
+65.036 1.425 64.97 1.693 64.853 1.851 c
+64.735 2.017 64.551 2.102 64.309 2.102 c
+67.101 2.587 m
+67.116 2.146 l
+67.37 2.487 67.693 2.66 68.086 2.66 c
+68.792 2.66 69.148 2.19 69.159 1.249 c
+69.159 -1.397 l
+68.512 -1.397 l
+68.512 1.22 l
+68.512 1.532 68.458 1.753 68.351 1.882 c
+68.24 2.006 68.086 2.072 67.881 2.072 c
+67.723 2.072 67.575 2.017 67.44 1.911 c
+67.311 1.801 67.208 1.664 67.131 1.499 c
+67.131 -1.397 l
+66.484 -1.397 l
+66.484 2.587 l
+h
+71.511 -0.912 m
+71.724 -0.912 71.897 -0.849 72.026 -0.721 c
+72.161 -0.584 72.235 -0.393 72.246 -0.148 c
+72.863 -0.148 l
+72.841 -0.53 72.705 -0.849 72.452 -1.103 c
+72.194 -1.349 71.882 -1.47 71.511 -1.47 c
+71.018 -1.47 70.644 -1.32 70.38 -1.014 c
+70.122 -0.702 69.998 -0.235 69.998 0.382 c
+69.998 0.823 l
+69.998 1.418 70.122 1.874 70.38 2.19 c
+70.644 2.502 71.018 2.66 71.511 2.66 c
+71.912 2.66 72.231 2.528 72.466 2.263 c
+72.709 2.006 72.841 1.66 72.863 1.22 c
+72.246 1.22 l
+72.224 1.514 72.151 1.734 72.026 1.882 c
+71.908 2.028 71.735 2.102 71.511 2.102 c
+71.217 2.102 71 2.003 70.864 1.808 c
+70.725 1.62 70.651 1.311 70.644 0.882 c
+70.644 0.367 l
+70.644 -0.103 70.71 -0.437 70.85 -0.632 c
+70.997 -0.819 71.217 -0.912 71.511 -0.912 c
+75.039 -1.47 m
+74.539 -1.47 74.157 -1.324 73.892 -1.029 c
+73.628 -0.736 73.495 -0.302 73.495 0.279 c
+73.495 0.75 l
+73.495 1.344 73.62 1.811 73.877 2.146 c
+74.143 2.487 74.503 2.66 74.966 2.66 c
+75.425 2.66 75.766 2.506 75.994 2.204 c
+76.229 1.911 76.35 1.448 76.362 0.823 c
+76.362 0.397 l
+74.143 0.397 l
+74.143 0.309 l
+74.143 -0.125 74.22 -0.437 74.378 -0.632 c
+74.543 -0.819 74.775 -0.912 75.068 -0.912 c
+75.263 -0.912 75.436 -0.879 75.583 -0.809 c
+75.73 -0.732 75.866 -0.614 75.994 -0.456 c
+76.333 -0.867 l
+76.046 -1.272 75.616 -1.47 75.039 -1.47 c
+74.966 2.102 m
+74.69 2.102 74.488 2.006 74.363 1.822 c
+74.234 1.635 74.16 1.344 74.143 0.955 c
+75.715 0.955 l
+75.715 1.043 l
+75.693 1.425 75.627 1.693 75.509 1.851 c
+75.392 2.017 75.208 2.102 74.966 2.102 c
+79.081 -0.383 m
+79.081 -0.235 79.026 -0.114 78.92 -0.015 c
+78.809 0.081 78.603 0.199 78.302 0.338 c
+77.956 0.484 77.714 0.606 77.567 0.706 c
+77.42 0.812 77.31 0.929 77.244 1.058 c
+77.174 1.182 77.141 1.341 77.141 1.529 c
+77.141 1.851 77.258 2.12 77.493 2.337 c
+77.729 2.55 78.031 2.66 78.405 2.66 c
+78.787 2.66 79.095 2.547 79.331 2.322 c
+79.566 2.094 79.683 1.808 79.683 1.455 c
+79.037 1.455 l
+79.037 1.631 78.978 1.782 78.86 1.911 c
+78.743 2.036 78.588 2.102 78.405 2.102 c
+78.206 2.102 78.056 2.046 77.95 1.94 c
+77.839 1.841 77.788 1.708 77.788 1.543 c
+77.788 1.415 77.825 1.308 77.905 1.22 c
+77.983 1.139 78.174 1.036 78.478 0.911 c
+78.956 0.723 79.286 0.536 79.463 0.353 c
+79.64 0.176 79.728 -0.052 79.728 -0.324 c
+79.728 -0.676 79.603 -0.956 79.361 -1.162 c
+79.126 -1.367 78.809 -1.47 78.42 -1.47 c
+77.997 -1.47 77.659 -1.353 77.405 -1.118 c
+77.148 -0.875 77.023 -0.57 77.023 -0.206 c
+77.67 -0.206 l
+77.678 -0.434 77.747 -0.611 77.875 -0.736 c
+78 -0.853 78.185 -0.912 78.42 -0.912 c
+78.633 -0.912 78.794 -0.864 78.905 -0.765 c
+79.022 -0.669 79.081 -0.541 79.081 -0.383 c
+82.991 -1.397 -0.647 5.644 re
+86.048 -1.397 m
+86.008 -1.309 85.983 -1.162 85.975 -0.956 c
+85.74 -1.301 85.445 -1.47 85.093 -1.47 c
+84.73 -1.47 84.446 -1.374 84.24 -1.176 c
+84.042 -0.971 83.947 -0.684 83.947 -0.309 c
+83.947 0.091 84.082 0.411 84.358 0.646 c
+84.63 0.889 85.005 1.014 85.476 1.014 c
+85.96 1.014 l
+85.96 1.44 l
+85.96 1.675 85.906 1.841 85.798 1.94 c
+85.688 2.046 85.526 2.102 85.314 2.102 c
+85.115 2.102 84.953 2.043 84.828 1.926 c
+84.711 1.808 84.652 1.66 84.652 1.484 c
+84.005 1.484 l
+84.005 1.679 84.064 1.87 84.182 2.057 c
+84.306 2.241 84.468 2.389 84.667 2.499 c
+84.873 2.605 85.1 2.66 85.358 2.66 c
+85.758 2.66 86.064 2.557 86.269 2.352 c
+86.482 2.146 86.596 1.851 86.607 1.469 c
+86.607 -0.544 l
+86.607 -0.849 86.644 -1.114 86.725 -1.338 c
+86.725 -1.397 l
+h
+85.181 -0.882 m
+85.347 -0.882 85.497 -0.838 85.636 -0.75 c
+85.784 -0.661 85.89 -0.551 85.96 -0.412 c
+85.96 0.529 l
+85.593 0.529 l
+85.277 0.529 85.034 0.459 84.858 0.323 c
+84.682 0.195 84.593 0.007 84.593 -0.235 c
+84.593 -0.464 84.637 -0.628 84.726 -0.736 c
+84.814 -0.834 84.965 -0.882 85.181 -0.882 c
+90.488 0.397 m
+90.488 -0.221 90.374 -0.688 90.149 -1 c
+89.933 -1.316 89.609 -1.47 89.179 -1.47 c
+88.757 -1.47 88.445 -1.29 88.239 -0.927 c
+88.209 -1.397 l
+87.606 -1.397 l
+87.606 4.247 l
+88.254 4.247 l
+88.254 2.146 l
+88.466 2.487 88.775 2.66 89.179 2.66 c
+89.609 2.66 89.933 2.502 90.149 2.19 c
+90.374 1.885 90.488 1.418 90.488 0.793 c
+h
+89.841 0.779 m
+89.841 1.249 89.771 1.579 89.635 1.778 c
+89.507 1.973 89.297 2.072 89.003 2.072 c
+88.668 2.072 88.419 1.888 88.254 1.529 c
+88.254 -0.353 l
+88.419 -0.717 88.672 -0.897 89.017 -0.897 c
+89.312 -0.897 89.521 -0.794 89.65 -0.588 c
+89.775 -0.383 89.841 -0.067 89.841 0.367 c
+h
+92.751 -1.47 m
+92.252 -1.47 91.87 -1.324 91.605 -1.029 c
+91.34 -0.736 91.208 -0.302 91.208 0.279 c
+91.208 0.75 l
+91.208 1.344 91.333 1.811 91.59 2.146 c
+91.855 2.487 92.215 2.66 92.678 2.66 c
+93.137 2.66 93.478 2.506 93.707 2.204 c
+93.942 1.911 94.064 1.448 94.074 0.823 c
+94.074 0.397 l
+91.855 0.397 l
+91.855 0.309 l
+91.855 -0.125 91.932 -0.437 92.09 -0.632 c
+92.256 -0.819 92.487 -0.912 92.78 -0.912 c
+92.975 -0.912 93.148 -0.879 93.295 -0.809 c
+93.442 -0.732 93.578 -0.614 93.707 -0.456 c
+94.045 -0.867 l
+93.758 -1.272 93.328 -1.47 92.751 -1.47 c
+92.678 2.102 m
+92.402 2.102 92.2 2.006 92.075 1.822 c
+91.947 1.635 91.873 1.344 91.855 0.955 c
+93.428 0.955 l
+93.428 1.043 l
+93.405 1.425 93.339 1.693 93.222 1.851 c
+93.104 2.017 92.921 2.102 92.678 2.102 c
+95.558 -1.397 -0.646 5.644 re
+98.513 -0.383 m
+98.513 -0.235 98.458 -0.114 98.351 -0.015 c
+98.241 0.081 98.035 0.199 97.734 0.338 c
+97.389 0.484 97.146 0.606 97 0.706 c
+96.852 0.812 96.742 0.929 96.676 1.058 c
+96.606 1.182 96.573 1.341 96.573 1.529 c
+96.573 1.851 96.69 2.12 96.925 2.337 c
+97.161 2.55 97.462 2.66 97.837 2.66 c
+98.22 2.66 98.528 2.547 98.764 2.322 c
+98.999 2.094 99.116 1.808 99.116 1.455 c
+98.469 1.455 l
+98.469 1.631 98.411 1.782 98.293 1.911 c
+98.176 2.036 98.021 2.102 97.837 2.102 c
+97.638 2.102 97.488 2.046 97.382 1.94 c
+97.272 1.841 97.22 1.708 97.22 1.543 c
+97.22 1.415 97.256 1.308 97.337 1.22 c
+97.415 1.139 97.605 1.036 97.91 0.911 c
+98.388 0.723 98.719 0.536 98.895 0.353 c
+99.072 0.176 99.161 -0.052 99.161 -0.324 c
+99.161 -0.676 99.035 -0.956 98.793 -1.162 c
+98.558 -1.367 98.241 -1.47 97.852 -1.47 c
+97.43 -1.47 97.091 -1.353 96.838 -1.118 c
+96.58 -0.875 96.455 -0.57 96.455 -0.206 c
+97.102 -0.206 l
+97.11 -0.434 97.179 -0.611 97.308 -0.736 c
+97.433 -0.853 97.617 -0.912 97.852 -0.912 c
+98.065 -0.912 98.226 -0.864 98.336 -0.765 c
+98.455 -0.669 98.513 -0.541 98.513 -0.383 c
+103.761 -1.397 m
+103.72 -1.309 103.695 -1.162 103.687 -0.956 c
+103.452 -1.301 103.159 -1.47 102.805 -1.47 c
+102.442 -1.47 102.159 -1.374 101.953 -1.176 c
+101.754 -0.971 101.659 -0.684 101.659 -0.309 c
+101.659 0.091 101.795 0.411 102.07 0.646 c
+102.342 0.889 102.717 1.014 103.188 1.014 c
+103.672 1.014 l
+103.672 1.44 l
+103.672 1.675 103.618 1.841 103.51 1.94 c
+103.4 2.046 103.239 2.102 103.026 2.102 c
+102.828 2.102 102.666 2.043 102.541 1.926 c
+102.423 1.808 102.365 1.66 102.365 1.484 c
+101.717 1.484 l
+101.717 1.679 101.777 1.87 101.894 2.057 c
+102.019 2.241 102.18 2.389 102.379 2.499 c
+102.585 2.605 102.812 2.66 103.07 2.66 c
+103.471 2.66 103.776 2.557 103.981 2.352 c
+104.194 2.146 104.308 1.851 104.32 1.469 c
+104.32 -0.544 l
+104.32 -0.849 104.356 -1.114 104.437 -1.338 c
+104.437 -1.397 l
+h
+102.893 -0.882 m
+103.059 -0.882 103.209 -0.838 103.35 -0.75 c
+103.496 -0.661 103.603 -0.551 103.672 -0.412 c
+103.672 0.529 l
+103.305 0.529 l
+102.989 0.529 102.747 0.459 102.57 0.323 c
+102.394 0.195 102.305 0.007 102.305 -0.235 c
+102.305 -0.464 102.35 -0.628 102.438 -0.736 c
+102.526 -0.834 102.677 -0.882 102.893 -0.882 c
+105.937 2.587 m
+105.951 2.146 l
+106.205 2.487 106.528 2.66 106.922 2.66 c
+107.627 2.66 107.983 2.19 107.994 1.249 c
+107.994 -1.397 l
+107.348 -1.397 l
+107.348 1.22 l
+107.348 1.532 107.292 1.753 107.186 1.882 c
+107.076 2.006 106.922 2.072 106.716 2.072 c
+106.558 2.072 106.411 2.017 106.274 1.911 c
+106.146 1.801 106.043 1.664 105.966 1.499 c
+105.966 -1.397 l
+105.319 -1.397 l
+105.319 2.587 l
+h
+108.832 0.779 m
+108.832 1.385 108.942 1.851 109.17 2.175 c
+109.405 2.499 109.733 2.66 110.155 2.66 c
+110.537 2.66 110.835 2.502 111.051 2.19 c
+111.051 4.247 l
+111.699 4.247 l
+111.699 -1.397 l
+111.111 -1.397 l
+111.067 -0.971 l
+110.861 -1.305 110.556 -1.47 110.155 -1.47 c
+109.744 -1.47 109.42 -1.316 109.185 -1 c
+108.95 -0.676 108.832 -0.221 108.832 0.367 c
+h
+109.479 0.397 m
+109.479 -0.044 109.542 -0.375 109.67 -0.588 c
+109.806 -0.794 110.026 -0.897 110.331 -0.897 c
+110.654 -0.897 110.893 -0.736 111.051 -0.412 c
+111.051 1.602 l
+110.882 1.914 110.644 2.072 110.331 2.072 c
+110.026 2.072 109.806 1.969 109.67 1.764 c
+109.542 1.558 109.479 1.234 109.479 0.793 c
+h
+115.065 2.175 m
+115.318 2.499 115.638 2.66 116.02 2.66 c
+116.725 2.66 117.082 2.19 117.093 1.249 c
+117.093 -1.397 l
+116.446 -1.397 l
+116.446 1.22 l
+116.446 1.532 116.391 1.753 116.285 1.882 c
+116.174 2.006 116.02 2.072 115.814 2.072 c
+115.656 2.072 115.509 2.017 115.373 1.911 c
+115.244 1.801 115.142 1.664 115.065 1.499 c
+115.065 -1.397 l
+114.417 -1.397 l
+114.417 4.247 l
+115.065 4.247 l
+h
+118.754 -1.397 -0.647 3.984 re
+118.798 3.63 m
+118.798 3.52 118.768 3.428 118.71 3.351 c
+118.651 3.281 118.556 3.248 118.431 3.248 c
+118.313 3.248 118.217 3.281 118.151 3.351 c
+118.092 3.428 118.063 3.52 118.063 3.63 c
+118.063 3.748 118.092 3.84 118.151 3.91 c
+118.217 3.987 118.313 4.027 118.431 4.027 c
+118.556 4.027 118.651 3.987 118.71 3.91 c
+118.768 3.829 118.798 3.737 118.798 3.63 c
+121.708 -0.383 m
+121.708 -0.235 121.654 -0.114 121.546 -0.015 c
+121.436 0.081 121.23 0.199 120.929 0.338 c
+120.584 0.484 120.341 0.606 120.195 0.706 c
+120.048 0.812 119.937 0.929 119.871 1.058 c
+119.801 1.182 119.768 1.341 119.768 1.529 c
+119.768 1.851 119.886 2.12 120.121 2.337 c
+120.356 2.55 120.657 2.66 121.033 2.66 c
+121.415 2.66 121.723 2.547 121.958 2.322 c
+122.194 2.094 122.311 1.808 122.311 1.455 c
+121.664 1.455 l
+121.664 1.631 121.606 1.782 121.488 1.911 c
+121.37 2.036 121.216 2.102 121.033 2.102 c
+120.834 2.102 120.683 2.046 120.576 1.94 c
+120.466 1.841 120.415 1.708 120.415 1.543 c
+120.415 1.415 120.451 1.308 120.532 1.22 c
+120.609 1.139 120.8 1.036 121.106 0.911 c
+121.583 0.723 121.914 0.536 122.09 0.353 c
+122.267 0.176 122.355 -0.052 122.355 -0.324 c
+122.355 -0.676 122.23 -0.956 121.988 -1.162 c
+121.752 -1.367 121.436 -1.47 121.047 -1.47 c
+120.624 -1.47 120.287 -1.353 120.033 -1.118 c
+119.776 -0.875 119.651 -0.57 119.651 -0.206 c
+120.297 -0.206 l
+120.305 -0.434 120.374 -0.611 120.503 -0.736 c
+120.628 -0.853 120.812 -0.912 121.047 -0.912 c
+121.26 -0.912 121.422 -0.864 121.532 -0.765 c
+121.65 -0.669 121.708 -0.541 121.708 -0.383 c
+124.046 3.542 m
+124.046 2.587 l
+124.648 2.587 l
+124.648 2.057 l
+124.046 2.057 l
+124.046 -0.412 l
+124.046 -0.57 124.068 -0.688 124.119 -0.765 c
+124.178 -0.846 124.266 -0.882 124.384 -0.882 c
+124.472 -0.882 124.56 -0.867 124.648 -0.838 c
+124.648 -1.397 l
+124.501 -1.444 124.347 -1.47 124.193 -1.47 c
+123.935 -1.47 123.74 -1.378 123.605 -1.191 c
+123.465 -1.008 123.399 -0.746 123.399 -0.412 c
+123.399 2.057 l
+122.796 2.057 l
+122.796 2.587 l
+123.399 2.587 l
+123.399 3.542 l
+h
+125.207 0.779 m
+125.207 1.356 125.343 1.811 125.618 2.146 c
+125.901 2.487 126.273 2.66 126.735 2.66 c
+127.195 2.66 127.562 2.491 127.838 2.161 c
+128.121 1.837 128.268 1.389 128.279 0.823 c
+128.279 0.397 l
+128.279 -0.173 128.135 -0.628 127.853 -0.971 c
+127.577 -1.305 127.21 -1.47 126.751 -1.47 c
+126.287 -1.47 125.916 -1.309 125.633 -0.985 c
+125.357 -0.655 125.214 -0.214 125.207 0.338 c
+h
+125.853 0.397 m
+125.853 -0.008 125.931 -0.324 126.088 -0.559 c
+126.254 -0.794 126.475 -0.912 126.751 -0.912 c
+127.316 -0.912 127.61 -0.5 127.632 0.323 c
+127.632 0.779 l
+127.632 1.18 127.547 1.499 127.383 1.734 c
+127.225 1.976 127.007 2.102 126.735 2.102 c
+126.471 2.102 126.254 1.976 126.088 1.734 c
+125.931 1.499 125.853 1.18 125.853 0.779 c
+h
+130.763 1.969 m
+130.675 1.988 130.576 1.999 130.469 1.999 c
+130.134 1.999 129.899 1.815 129.764 1.455 c
+129.764 -1.397 l
+129.116 -1.397 l
+129.116 2.587 l
+129.749 2.587 l
+129.764 2.175 l
+129.94 2.499 130.182 2.66 130.498 2.66 c
+130.605 2.66 130.693 2.638 130.763 2.601 c
+h
+132.571 -0.309 m
+133.291 2.587 l
+133.982 2.587 l
+132.688 -1.955 l
+132.59 -2.297 132.446 -2.558 132.262 -2.735 c
+132.086 -2.911 131.884 -2.999 131.659 -2.999 c
+131.572 -2.999 131.458 -2.977 131.322 -2.94 c
+131.322 -2.396 l
+131.468 -2.411 l
+131.653 -2.411 131.799 -2.367 131.91 -2.278 c
+132.016 -2.19 132.104 -2.032 132.174 -1.808 c
+132.291 -1.367 l
+131.131 2.587 l
+131.836 2.587 l
+h
+136.201 0.779 m
+136.201 1.396 136.312 1.859 136.54 2.175 c
+136.764 2.499 137.099 2.66 137.539 2.66 c
+137.94 2.66 138.244 2.484 138.451 2.131 c
+138.495 2.587 l
+139.083 2.587 l
+139.083 -1.441 l
+139.083 -1.929 138.954 -2.308 138.701 -2.573 c
+138.443 -2.837 138.09 -2.97 137.642 -2.97 c
+137.444 -2.97 137.223 -2.918 136.981 -2.822 c
+136.735 -2.723 136.555 -2.602 136.436 -2.455 c
+136.702 -2.014 l
+136.966 -2.278 137.263 -2.411 137.598 -2.411 c
+138.134 -2.411 138.41 -2.117 138.421 -1.529 c
+138.421 -1 l
+138.215 -1.316 137.914 -1.47 137.525 -1.47 c
+137.113 -1.47 136.79 -1.32 136.555 -1.014 c
+136.326 -0.702 136.209 -0.25 136.201 0.338 c
+h
+136.863 0.397 m
+136.863 -0.044 136.926 -0.375 137.054 -0.588 c
+137.18 -0.794 137.396 -0.897 137.701 -0.897 c
+138.024 -0.897 138.263 -0.732 138.421 -0.397 c
+138.421 1.587 l
+138.252 1.911 138.013 2.072 137.701 2.072 c
+137.407 2.072 137.19 1.969 137.054 1.764 c
+136.926 1.558 136.863 1.234 136.863 0.793 c
+h
+141.685 1.969 m
+141.596 1.988 141.497 1.999 141.39 1.999 c
+141.056 1.999 140.821 1.815 140.685 1.455 c
+140.685 -1.397 l
+140.038 -1.397 l
+140.038 2.587 l
+140.67 2.587 l
+140.685 2.175 l
+140.862 2.499 141.103 2.66 141.419 2.66 c
+141.527 2.66 141.614 2.638 141.685 2.601 c
+h
+144.228 -1.397 m
+144.187 -1.309 144.161 -1.162 144.154 -0.956 c
+143.919 -1.301 143.625 -1.47 143.272 -1.47 c
+142.908 -1.47 142.626 -1.374 142.419 -1.176 c
+142.221 -0.971 142.125 -0.684 142.125 -0.309 c
+142.125 0.091 142.261 0.411 142.537 0.646 c
+142.809 0.889 143.183 1.014 143.654 1.014 c
+144.139 1.014 l
+144.139 1.44 l
+144.139 1.675 144.084 1.841 143.977 1.94 c
+143.867 2.046 143.705 2.102 143.492 2.102 c
+143.294 2.102 143.133 2.043 143.007 1.926 c
+142.89 1.808 142.831 1.66 142.831 1.484 c
+142.184 1.484 l
+142.184 1.679 142.243 1.87 142.36 2.057 c
+142.485 2.241 142.647 2.389 142.846 2.499 c
+143.052 2.605 143.279 2.66 143.536 2.66 c
+143.937 2.66 144.242 2.557 144.448 2.352 c
+144.661 2.146 144.775 1.851 144.786 1.469 c
+144.786 -0.544 l
+144.786 -0.849 144.823 -1.114 144.903 -1.338 c
+144.903 -1.397 l
+h
+143.36 -0.882 m
+143.526 -0.882 143.676 -0.838 143.816 -0.75 c
+143.962 -0.661 144.07 -0.551 144.139 -0.412 c
+144.139 0.529 l
+143.771 0.529 l
+143.455 0.529 143.213 0.459 143.037 0.323 c
+142.861 0.195 142.772 0.007 142.772 -0.235 c
+142.772 -0.464 142.816 -0.628 142.905 -0.736 c
+142.992 -0.834 143.143 -0.882 143.36 -0.882 c
+148.666 0.397 m
+148.666 -0.231 148.549 -0.702 148.314 -1.014 c
+148.086 -1.32 147.769 -1.47 147.358 -1.47 c
+146.954 -1.47 146.645 -1.32 146.433 -1.014 c
+146.433 -2.926 l
+145.785 -2.926 l
+145.785 2.587 l
+146.373 2.587 l
+146.418 2.146 l
+146.63 2.487 146.94 2.66 147.343 2.66 c
+147.785 2.66 148.112 2.506 148.328 2.204 c
+148.542 1.899 148.656 1.444 148.666 0.837 c
+h
+148.02 0.779 m
+148.02 1.22 147.95 1.543 147.814 1.749 c
+147.674 1.962 147.453 2.072 147.152 2.072 c
+146.836 2.072 146.597 1.918 146.433 1.616 c
+146.433 -0.456 l
+146.597 -0.761 146.836 -0.912 147.152 -0.912 c
+147.447 -0.912 147.659 -0.809 147.8 -0.603 c
+147.935 -0.389 148.008 -0.059 148.02 0.382 c
+h
+150.151 2.175 m
+150.404 2.499 150.724 2.66 151.106 2.66 c
+151.812 2.66 152.168 2.19 152.18 1.249 c
+152.18 -1.397 l
+151.532 -1.397 l
+151.532 1.22 l
+151.532 1.532 151.478 1.753 151.372 1.882 c
+151.261 2.006 151.106 2.072 150.901 2.072 c
+150.743 2.072 150.595 2.017 150.46 1.911 c
+150.331 1.801 150.229 1.664 150.151 1.499 c
+150.151 -1.397 l
+149.504 -1.397 l
+149.504 4.247 l
+150.151 4.247 l
+h
+153.179 -1.044 m
+153.179 -0.927 153.213 -0.831 153.282 -0.75 c
+153.348 -0.673 153.451 -0.632 153.591 -0.632 c
+153.738 -0.632 153.844 -0.673 153.914 -0.75 c
+153.992 -0.831 154.032 -0.927 154.032 -1.044 c
+154.032 -1.154 153.992 -1.246 153.914 -1.324 c
+153.844 -1.401 153.738 -1.441 153.591 -1.441 c
+153.451 -1.441 153.348 -1.401 153.282 -1.324 c
+153.213 -1.246 153.179 -1.154 153.179 -1.044 c
+160.411 0.808 m
+160.411 0.081 160.253 -0.482 159.941 -0.882 c
+159.636 -1.276 159.195 -1.47 158.618 -1.47 c
+158.067 -1.47 157.633 -1.279 157.31 -0.897 c
+156.993 -0.515 156.828 0.029 156.81 0.735 c
+156.81 1.734 l
+156.81 2.447 156.964 3.006 157.28 3.41 c
+157.603 3.821 158.048 4.027 158.618 4.027 c
+159.176 4.027 159.61 3.829 159.926 3.439 c
+160.238 3.057 160.4 2.502 160.411 1.778 c
+h
+159.735 1.749 m
+159.735 2.315 159.64 2.738 159.455 3.013 c
+159.279 3.285 159 3.424 158.618 3.424 c
+158.243 3.424 157.96 3.281 157.765 2.998 c
+157.578 2.723 157.486 2.311 157.486 1.764 c
+157.486 0.808 l
+157.486 0.257 157.578 -0.158 157.765 -0.441 c
+157.96 -0.728 158.243 -0.867 158.618 -0.867 c
+159 -0.867 159.279 -0.736 159.455 -0.47 c
+159.64 -0.206 159.735 0.199 159.735 0.75 c
+h
+161.984 2.587 m
+161.998 2.146 l
+162.252 2.487 162.576 2.66 162.969 2.66 c
+163.675 2.66 164.031 2.19 164.041 1.249 c
+164.041 -1.397 l
+163.395 -1.397 l
+163.395 1.22 l
+163.395 1.532 163.34 1.753 163.233 1.882 c
+163.123 2.006 162.969 2.072 162.763 2.072 c
+162.605 2.072 162.458 2.017 162.322 1.911 c
+162.193 1.801 162.09 1.664 162.013 1.499 c
+162.013 -1.397 l
+161.366 -1.397 l
+161.366 2.587 l
+h
+166.437 -1.47 m
+165.938 -1.47 165.556 -1.324 165.291 -1.029 c
+165.026 -0.736 164.894 -0.302 164.894 0.279 c
+164.894 0.75 l
+164.894 1.344 165.019 1.811 165.277 2.146 c
+165.541 2.487 165.901 2.66 166.364 2.66 c
+166.823 2.66 167.166 2.506 167.393 2.204 c
+167.628 1.911 167.75 1.448 167.76 0.823 c
+167.76 0.397 l
+165.541 0.397 l
+165.541 0.309 l
+165.541 -0.125 165.618 -0.437 165.776 -0.632 c
+165.942 -0.819 166.173 -0.912 166.467 -0.912 c
+166.661 -0.912 166.834 -0.879 166.981 -0.809 c
+167.129 -0.732 167.264 -0.614 167.393 -0.456 c
+167.731 -0.867 l
+167.444 -1.272 167.014 -1.47 166.437 -1.47 c
+166.364 2.102 m
+166.088 2.102 165.886 2.006 165.761 1.822 c
+165.633 1.635 165.56 1.344 165.541 0.955 c
+167.114 0.955 l
+167.114 1.043 l
+167.091 1.425 167.025 1.693 166.908 1.851 c
+166.79 2.017 166.607 2.102 166.364 2.102 c
+171.641 -0.912 m
+171.854 -0.912 172.027 -0.849 172.155 -0.721 c
+172.292 -0.584 172.365 -0.393 172.376 -0.148 c
+172.993 -0.148 l
+172.971 -0.53 172.835 -0.849 172.581 -1.103 c
+172.325 -1.349 172.012 -1.47 171.641 -1.47 c
+171.149 -1.47 170.773 -1.32 170.509 -1.014 c
+170.252 -0.702 170.127 -0.235 170.127 0.382 c
+170.127 0.823 l
+170.127 1.418 170.252 1.874 170.509 2.19 c
+170.773 2.502 171.149 2.66 171.641 2.66 c
+172.041 2.66 172.361 2.528 172.597 2.263 c
+172.839 2.006 172.971 1.66 172.993 1.22 c
+172.376 1.22 l
+172.354 1.514 172.28 1.734 172.155 1.882 c
+172.038 2.028 171.866 2.102 171.641 2.102 c
+171.347 2.102 171.13 2.003 170.994 1.808 c
+170.854 1.62 170.781 1.311 170.773 0.882 c
+170.773 0.367 l
+170.773 -0.103 170.84 -0.437 170.979 -0.632 c
+171.127 -0.819 171.347 -0.912 171.641 -0.912 c
+173.611 0.779 m
+173.611 1.356 173.747 1.811 174.023 2.146 c
+174.305 2.487 174.676 2.66 175.139 2.66 c
+175.598 2.66 175.966 2.491 176.242 2.161 c
+176.525 1.837 176.672 1.389 176.683 0.823 c
+176.683 0.397 l
+176.683 -0.173 176.539 -0.628 176.257 -0.971 c
+175.981 -1.305 175.613 -1.47 175.154 -1.47 c
+174.692 -1.47 174.32 -1.309 174.037 -0.985 c
+173.761 -0.655 173.618 -0.214 173.611 0.338 c
+h
+174.258 0.397 m
+174.258 -0.008 174.335 -0.324 174.493 -0.559 c
+174.658 -0.794 174.879 -0.912 175.154 -0.912 c
+175.72 -0.912 176.014 -0.5 176.036 0.323 c
+176.036 0.779 l
+176.036 1.18 175.951 1.499 175.787 1.734 c
+175.629 1.976 175.411 2.102 175.139 2.102 c
+174.875 2.102 174.658 1.976 174.493 1.734 c
+174.335 1.499 174.258 1.18 174.258 0.779 c
+h
+178.138 2.587 m
+178.153 2.219 l
+178.395 2.514 178.715 2.66 179.108 2.66 c
+179.55 2.66 179.858 2.462 180.034 2.072 c
+180.288 2.462 180.637 2.66 181.078 2.66 c
+181.813 2.66 182.187 2.198 182.21 1.278 c
+182.21 -1.397 l
+181.563 -1.397 l
+181.563 1.22 l
+181.563 1.514 181.508 1.727 181.401 1.866 c
+181.302 2.003 181.129 2.072 180.886 2.072 c
+180.689 2.072 180.527 1.992 180.402 1.837 c
+180.284 1.691 180.215 1.499 180.196 1.263 c
+180.196 -1.397 l
+179.534 -1.397 l
+179.534 1.249 l
+179.534 1.797 179.314 2.072 178.873 2.072 c
+178.538 2.072 178.303 1.911 178.168 1.587 c
+178.168 -1.397 l
+177.52 -1.397 l
+177.52 2.587 l
+h
+183.797 2.587 m
+183.812 2.219 l
+184.055 2.514 184.375 2.66 184.768 2.66 c
+185.208 2.66 185.517 2.462 185.693 2.072 c
+185.947 2.462 186.296 2.66 186.737 2.66 c
+187.471 2.66 187.847 2.198 187.868 1.278 c
+187.868 -1.397 l
+187.222 -1.397 l
+187.222 1.22 l
+187.222 1.514 187.167 1.727 187.06 1.866 c
+186.962 2.003 186.789 2.072 186.546 2.072 c
+186.347 2.072 186.186 1.992 186.06 1.837 c
+185.944 1.691 185.873 1.499 185.855 1.263 c
+185.855 -1.397 l
+185.194 -1.397 l
+185.194 1.249 l
+185.194 1.797 184.973 2.072 184.533 2.072 c
+184.198 2.072 183.963 1.911 183.827 1.587 c
+183.827 -1.397 l
+183.18 -1.397 l
+183.18 2.587 l
+h
+189.545 -1.397 -0.647 3.984 re
+189.588 3.63 m
+189.588 3.52 189.559 3.428 189.501 3.351 c
+189.441 3.281 189.346 3.248 189.221 3.248 c
+189.104 3.248 189.008 3.281 188.942 3.351 c
+188.883 3.428 188.853 3.52 188.853 3.63 c
+188.853 3.748 188.883 3.84 188.942 3.91 c
+189.008 3.987 189.104 4.027 189.221 4.027 c
+189.346 4.027 189.441 3.987 189.501 3.91 c
+189.559 3.829 189.588 3.737 189.588 3.63 c
+191.411 3.542 m
+191.411 2.587 l
+192.014 2.587 l
+192.014 2.057 l
+191.411 2.057 l
+191.411 -0.412 l
+191.411 -0.57 191.433 -0.688 191.485 -0.765 c
+191.544 -0.846 191.631 -0.882 191.749 -0.882 c
+191.837 -0.882 191.926 -0.867 192.014 -0.838 c
+192.014 -1.397 l
+191.867 -1.444 191.712 -1.47 191.558 -1.47 c
+191.301 -1.47 191.107 -1.378 190.97 -1.191 c
+190.831 -1.008 190.764 -0.746 190.764 -0.412 c
+190.764 2.057 l
+190.162 2.057 l
+190.162 2.587 l
+190.764 2.587 l
+190.764 3.542 l
+h
+197.379 0.397 m
+197.379 -0.231 197.262 -0.702 197.027 -1.014 c
+196.799 -1.32 196.483 -1.47 196.071 -1.47 c
+195.666 -1.47 195.358 -1.32 195.145 -1.014 c
+195.145 -2.926 l
+194.498 -2.926 l
+194.498 2.587 l
+195.086 2.587 l
+195.13 2.146 l
+195.344 2.487 195.652 2.66 196.057 2.66 c
+196.497 2.66 196.824 2.506 197.041 2.204 c
+197.254 1.899 197.368 1.444 197.379 0.837 c
+h
+196.732 0.779 m
+196.732 1.22 196.663 1.543 196.527 1.749 c
+196.387 1.962 196.167 2.072 195.865 2.072 c
+195.549 2.072 195.311 1.918 195.145 1.616 c
+195.145 -0.456 l
+195.311 -0.761 195.549 -0.912 195.865 -0.912 c
+196.159 -0.912 196.372 -0.809 196.512 -0.603 c
+196.647 -0.389 196.722 -0.059 196.732 0.382 c
+h
+199.643 -1.47 m
+199.143 -1.47 198.76 -1.324 198.496 -1.029 c
+198.232 -0.736 198.099 -0.302 198.099 0.279 c
+198.099 0.75 l
+198.099 1.344 198.224 1.811 198.482 2.146 c
+198.746 2.487 199.107 2.66 199.569 2.66 c
+200.028 2.66 200.37 2.506 200.599 2.204 c
+200.834 1.911 200.955 1.448 200.965 0.823 c
+200.965 0.397 l
+198.746 0.397 l
+198.746 0.309 l
+198.746 -0.125 198.823 -0.437 198.981 -0.632 c
+199.147 -0.819 199.378 -0.912 199.672 -0.912 c
+199.867 -0.912 200.04 -0.879 200.187 -0.809 c
+200.333 -0.732 200.47 -0.614 200.599 -0.456 c
+200.936 -0.867 l
+200.649 -1.272 200.219 -1.47 199.643 -1.47 c
+199.569 2.102 m
+199.294 2.102 199.092 2.006 198.966 1.822 c
+198.838 1.635 198.764 1.344 198.746 0.955 c
+200.319 0.955 l
+200.319 1.043 l
+200.297 1.425 200.231 1.693 200.113 1.851 c
+199.996 2.017 199.812 2.102 199.569 2.102 c
+203.391 1.969 m
+203.303 1.988 203.203 1.999 203.097 1.999 c
+202.762 1.999 202.527 1.815 202.392 1.455 c
+202.392 -1.397 l
+201.744 -1.397 l
+201.744 2.587 l
+202.377 2.587 l
+202.392 2.175 l
+202.568 2.499 202.81 2.66 203.126 2.66 c
+203.233 2.66 203.321 2.638 203.391 2.601 c
+h
+206.463 -1.397 -0.647 5.644 re
+208.183 -1.397 -0.646 3.984 re
+208.227 3.63 m
+208.227 3.52 208.198 3.428 208.139 3.351 c
+208.08 3.281 207.984 3.248 207.859 3.248 c
+207.742 3.248 207.647 3.281 207.581 3.351 c
+207.521 3.428 207.492 3.52 207.492 3.63 c
+207.492 3.748 207.521 3.84 207.581 3.91 c
+207.647 3.987 207.742 4.027 207.859 4.027 c
+207.984 4.027 208.08 3.987 208.139 3.91 c
+208.198 3.829 208.227 3.737 208.227 3.63 c
+209.814 2.587 m
+209.829 2.146 l
+210.083 2.487 210.406 2.66 210.799 2.66 c
+211.505 2.66 211.861 2.19 211.872 1.249 c
+211.872 -1.397 l
+211.225 -1.397 l
+211.225 1.22 l
+211.225 1.532 211.171 1.753 211.064 1.882 c
+210.953 2.006 210.799 2.072 210.594 2.072 c
+210.436 2.072 210.288 2.017 210.153 1.911 c
+210.024 1.801 209.921 1.664 209.844 1.499 c
+209.844 -1.397 l
+209.197 -1.397 l
+209.197 2.587 l
+h
+214.268 -1.47 m
+213.769 -1.47 213.386 -1.324 213.122 -1.029 c
+212.857 -0.736 212.725 -0.302 212.725 0.279 c
+212.725 0.75 l
+212.725 1.344 212.85 1.811 213.107 2.146 c
+213.372 2.487 213.732 2.66 214.195 2.66 c
+214.654 2.66 214.996 2.506 215.223 2.204 c
+215.459 1.911 215.58 1.448 215.591 0.823 c
+215.591 0.397 l
+213.372 0.397 l
+213.372 0.309 l
+213.372 -0.125 213.449 -0.437 213.607 -0.632 c
+213.773 -0.819 214.004 -0.912 214.298 -0.912 c
+214.492 -0.912 214.665 -0.879 214.812 -0.809 c
+214.959 -0.732 215.095 -0.614 215.223 -0.456 c
+215.562 -0.867 l
+215.275 -1.272 214.845 -1.47 214.268 -1.47 c
+214.195 2.102 m
+213.919 2.102 213.717 2.006 213.592 1.822 c
+213.463 1.635 213.39 1.344 213.372 0.955 c
+214.945 0.955 l
+214.945 1.043 l
+214.922 1.425 214.856 1.693 214.739 1.851 c
+214.621 2.017 214.438 2.102 214.195 2.102 c
+216.414 -1.044 m
+216.414 -0.927 216.447 -0.831 216.518 -0.75 c
+216.584 -0.673 216.686 -0.632 216.826 -0.632 c
+216.973 -0.632 217.079 -0.673 217.149 -0.75 c
+217.226 -0.831 217.267 -0.927 217.267 -1.044 c
+217.267 -1.154 217.226 -1.246 217.149 -1.324 c
+217.079 -1.401 216.973 -1.441 216.826 -1.441 c
+216.686 -1.441 216.584 -1.401 216.518 -1.324 c
+216.447 -1.246 216.414 -1.154 216.414 -1.044 c
+f
+Q
+0.113 0.082 0.09 0 k
+35.668 411.16 238.665 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 40.8563 404.3204 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.882 c
+-0.496 -0.993 -0.658 -1.08 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.771 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.279 -3.219 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.985 c
+-3.322 2.18 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.003 -2.469 3.043 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.182 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.455 c
+-2.26 2.425 -2.319 2.385 -2.366 2.338 c
+-2.406 2.297 -2.437 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.44 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.014 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.147 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.596 4.935 -0.411 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.632 5.137 1.779 c
+5.245 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.152 2.22 c
+8.004 2.22 l
+7.993 2.139 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.871 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.279 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.279 5.835 1.162 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.22 l
+13.644 2.22 l
+13.924 3.117 l
+14.497 3.117 l
+14.497 2.22 l
+15.732 2.22 l
+15.732 1.602 l
+14.497 1.602 l
+14.497 -0.103 l
+14.497 -0.324 l
+14.504 -0.393 14.527 -0.455 14.556 -0.515 c
+14.593 -0.565 14.648 -0.61 14.718 -0.646 c
+14.795 -0.676 14.909 -0.691 15.056 -0.691 c
+15.192 -0.691 15.327 -0.687 15.468 -0.676 c
+15.603 -0.658 15.736 -0.632 15.865 -0.602 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.23 15.629 -1.249 c
+15.549 -1.261 15.471 -1.267 15.394 -1.278 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.041 -1.301 14.942 -1.308 14.835 -1.308 c
+14.648 -1.308 14.486 -1.294 14.35 -1.264 c
+14.221 -1.228 14.107 -1.183 14.012 -1.132 c
+13.924 -1.084 13.85 -1.025 13.791 -0.955 c
+13.733 -0.878 13.689 -0.801 13.66 -0.72 c
+13.63 -0.632 13.608 -0.544 13.6 -0.455 c
+13.59 -0.36 13.586 -0.264 13.586 -0.176 c
+h
+23.221 -0.646 m
+24.353 -0.646 l
+24.353 -1.264 l
+21.045 -1.264 l
+21.045 -0.646 l
+22.31 -0.646 l
+22.31 2.896 l
+21.384 2.896 l
+21.384 3.514 l
+23.221 3.514 l
+h
+28.384 0.485 m
+28.384 0.21 28.347 -0.04 28.281 -0.264 c
+28.212 -0.482 28.108 -0.669 27.973 -0.823 c
+27.833 -0.981 27.657 -1.103 27.443 -1.19 c
+27.227 -1.278 26.973 -1.323 26.679 -1.323 c
+26.404 -1.323 26.157 -1.278 25.944 -1.19 c
+25.739 -1.103 25.566 -0.981 25.43 -0.823 c
+25.29 -0.669 25.187 -0.482 25.121 -0.264 c
+25.051 -0.04 25.018 0.21 25.018 0.485 c
+25.018 0.738 25.047 0.974 25.106 1.191 c
+25.172 1.415 25.275 1.606 25.415 1.764 c
+25.55 1.929 25.727 2.058 25.944 2.146 c
+26.157 2.234 26.414 2.278 26.709 2.278 c
+27.021 2.278 27.281 2.234 27.487 2.146 c
+27.701 2.058 27.873 1.929 28.002 1.764 c
+28.138 1.606 28.237 1.415 28.296 1.191 c
+28.355 0.974 28.384 0.738 28.384 0.485 c
+27.429 0.485 m
+27.429 0.691 27.414 0.867 27.385 1.014 c
+27.362 1.162 27.326 1.282 27.267 1.382 c
+27.208 1.477 27.135 1.547 27.046 1.588 c
+26.959 1.635 26.848 1.661 26.724 1.661 c
+26.458 1.661 26.267 1.562 26.15 1.367 c
+26.032 1.18 25.974 0.886 25.974 0.485 c
+25.974 0.063 26.032 -0.243 26.15 -0.426 c
+26.267 -0.613 26.444 -0.706 26.679 -0.706 c
+26.804 -0.706 26.918 -0.687 27.017 -0.646 c
+27.113 -0.599 27.194 -0.525 27.252 -0.426 c
+27.318 -0.33 27.362 -0.206 27.385 -0.058 c
+27.414 0.088 27.429 0.268 27.429 0.485 c
+30.769 -2.66 m
+30.552 -2.66 30.361 -2.635 30.196 -2.587 c
+30.027 -2.547 29.887 -2.484 29.77 -2.396 c
+29.652 -2.315 29.552 -2.219 29.475 -2.102 c
+29.406 -1.984 29.358 -1.855 29.328 -1.72 c
+30.225 -1.617 l
+30.262 -1.753 30.331 -1.859 30.431 -1.94 c
+30.526 -2.028 30.651 -2.072 30.799 -2.072 c
+30.886 -2.072 30.967 -2.057 31.048 -2.028 c
+31.125 -1.999 31.195 -1.944 31.254 -1.866 c
+31.313 -1.797 31.357 -1.705 31.387 -1.587 c
+31.424 -1.469 31.445 -1.323 31.445 -1.147 c
+31.445 -0.955 l
+31.445 -0.889 31.449 -0.831 31.46 -0.779 c
+31.46 -0.588 l
+31.445 -0.588 l
+31.346 -0.816 31.202 -0.977 31.019 -1.072 c
+30.832 -1.172 30.626 -1.22 30.402 -1.22 c
+30.196 -1.22 30.012 -1.183 29.858 -1.103 c
+29.71 -1.014 29.582 -0.897 29.475 -0.75 c
+29.376 -0.596 29.303 -0.411 29.255 -0.206 c
+29.203 0.008 29.182 0.243 29.182 0.5 c
+29.182 0.771 29.203 1.018 29.255 1.235 c
+29.313 1.448 29.394 1.632 29.505 1.779 c
+29.612 1.933 29.743 2.051 29.901 2.132 c
+30.056 2.22 30.244 2.263 30.46 2.263 c
+30.556 2.263 30.655 2.253 30.755 2.234 c
+30.85 2.213 30.938 2.18 31.019 2.132 c
+31.107 2.08 31.185 2.018 31.254 1.941 c
+31.331 1.86 31.393 1.768 31.445 1.661 c
+31.46 1.661 l
+31.46 1.808 l
+31.467 1.867 31.474 1.918 31.474 1.97 c
+31.482 2.028 31.489 2.076 31.489 2.117 c
+31.497 2.165 31.507 2.198 31.519 2.22 c
+32.371 2.22 l
+32.36 2.139 32.349 2.028 32.342 1.881 c
+32.342 1.411 l
+32.342 -1.161 l
+32.342 -1.415 32.305 -1.635 32.239 -1.822 c
+32.17 -2.007 32.066 -2.161 31.931 -2.279 c
+31.79 -2.404 31.625 -2.499 31.43 -2.558 c
+31.232 -2.624 31.011 -2.66 30.769 -2.66 c
+31.46 0.53 m
+31.46 0.742 31.434 0.919 31.387 1.058 c
+31.346 1.205 31.291 1.323 31.225 1.411 c
+31.166 1.5 31.096 1.558 31.019 1.588 c
+30.938 1.625 30.861 1.646 30.784 1.646 c
+30.684 1.646 30.593 1.621 30.504 1.573 c
+30.424 1.532 30.358 1.463 30.298 1.367 c
+30.248 1.279 30.203 1.162 30.167 1.014 c
+30.137 0.875 30.122 0.706 30.122 0.5 c
+30.122 0.125 30.181 -0.154 30.298 -0.338 c
+30.416 -0.515 30.578 -0.602 30.784 -0.602 c
+30.85 -0.602 30.923 -0.588 31.004 -0.559 c
+31.092 -0.522 31.166 -0.463 31.225 -0.382 c
+31.291 -0.294 31.346 -0.176 31.387 -0.029 c
+31.434 0.118 31.46 0.301 31.46 0.53 c
+40.378 1.47 m
+40.28 1.477 40.176 1.488 40.07 1.5 c
+39.96 1.517 39.838 1.529 39.702 1.529 c
+39.526 1.529 39.368 1.488 39.232 1.411 c
+39.092 1.341 38.975 1.242 38.879 1.118 c
+38.791 0.989 38.721 0.842 38.674 0.676 c
+38.633 0.507 38.615 0.331 38.615 0.147 c
+38.615 -1.264 l
+37.718 -1.264 l
+37.718 0.985 l
+37.718 1.11 37.707 1.235 37.689 1.353 c
+37.678 1.477 37.663 1.595 37.645 1.706 c
+37.633 1.823 37.619 1.918 37.6 1.999 c
+37.579 2.087 37.56 2.161 37.542 2.22 c
+38.424 2.22 l
+38.431 2.168 38.442 2.117 38.453 2.058 c
+38.472 1.999 38.486 1.933 38.497 1.867 c
+38.516 1.808 38.53 1.742 38.541 1.675 c
+38.549 1.606 38.56 1.544 38.57 1.484 c
+38.585 1.484 l
+38.622 1.602 38.674 1.709 38.732 1.808 c
+38.798 1.904 38.879 1.988 38.967 2.058 c
+39.056 2.124 39.158 2.18 39.276 2.22 c
+39.401 2.257 39.548 2.278 39.717 2.278 c
+39.842 2.278 39.96 2.271 40.07 2.263 c
+40.187 2.253 40.29 2.238 40.378 2.22 c
+h
+42.984 -1.323 m
+42.727 -1.323 42.499 -1.286 42.293 -1.22 c
+42.088 -1.143 41.911 -1.029 41.764 -0.882 c
+41.617 -0.727 41.5 -0.536 41.411 -0.309 c
+41.33 -0.085 41.294 0.181 41.294 0.485 c
+41.294 0.816 41.338 1.095 41.425 1.323 c
+41.521 1.558 41.65 1.742 41.808 1.881 c
+41.973 2.018 42.161 2.117 42.366 2.176 c
+42.572 2.242 42.782 2.278 42.998 2.278 c
+43.27 2.278 43.505 2.227 43.704 2.132 c
+43.91 2.043 44.076 1.911 44.204 1.735 c
+44.34 1.565 44.44 1.359 44.498 1.118 c
+44.564 0.882 44.6 0.617 44.6 0.324 c
+44.6 0.309 l
+42.234 0.309 l
+42.234 0.162 42.249 0.023 42.279 -0.103 c
+42.315 -0.231 42.37 -0.345 42.441 -0.441 c
+42.506 -0.529 42.591 -0.599 42.69 -0.646 c
+42.786 -0.698 42.9 -0.72 43.028 -0.72 c
+43.183 -0.72 43.322 -0.687 43.44 -0.617 c
+43.565 -0.551 43.653 -0.448 43.704 -0.309 c
+44.542 -0.382 l
+44.513 -0.482 44.457 -0.588 44.38 -0.706 c
+44.299 -0.816 44.197 -0.918 44.072 -1.014 c
+43.954 -1.103 43.8 -1.176 43.616 -1.234 c
+43.44 -1.294 43.226 -1.323 42.984 -1.323 c
+42.984 1.706 m
+42.896 1.706 42.807 1.69 42.719 1.661 c
+42.631 1.632 42.551 1.58 42.484 1.515 c
+42.414 1.444 42.356 1.357 42.308 1.249 c
+42.267 1.139 42.249 1.014 42.249 0.867 c
+43.719 0.867 l
+43.719 1.004 43.694 1.124 43.646 1.235 c
+43.605 1.341 43.55 1.43 43.484 1.5 c
+43.425 1.565 43.351 1.617 43.264 1.646 c
+43.175 1.683 43.079 1.706 42.984 1.706 c
+47.133 1.602 m
+47.133 -1.264 l
+46.236 -1.264 l
+46.236 1.602 l
+45.413 1.602 l
+45.413 2.22 l
+46.236 2.22 l
+46.236 2.484 l
+46.236 2.61 46.251 2.741 46.281 2.881 c
+46.317 3.017 46.387 3.134 46.486 3.234 c
+46.593 3.341 46.736 3.429 46.912 3.499 c
+47.089 3.564 47.313 3.601 47.588 3.601 c
+47.802 3.601 48 3.591 48.176 3.572 c
+48.353 3.55 48.504 3.532 48.632 3.514 c
+48.632 2.926 l
+48.504 2.944 48.361 2.959 48.205 2.969 c
+48.048 2.976 47.897 2.984 47.75 2.984 c
+47.621 2.984 47.519 2.969 47.441 2.94 c
+47.361 2.911 47.298 2.87 47.251 2.822 c
+47.199 2.77 47.166 2.708 47.147 2.631 c
+47.137 2.562 47.133 2.484 47.133 2.396 c
+47.133 2.22 l
+48.558 2.22 l
+48.558 1.602 l
+h
+50.605 -0.279 0.927 -0.985 re
+50.605 -1.264 m
+54.67 -0.279 0.926 -0.985 re
+54.67 -1.264 m
+f
+Q
+q 1 0 0 1 58.4255 388.7399 cm
+0 0 m
+2.102 0 l
+2.102 -0.574 l
+-0.676 -0.574 l
+-0.676 4.777 l
+0 4.777 l
+h
+3.513 -0.574 -0.646 3.984 re
+3.557 4.453 m
+3.557 4.343 3.528 4.251 3.469 4.174 c
+3.41 4.104 3.314 4.072 3.19 4.072 c
+3.072 4.072 2.977 4.104 2.911 4.174 c
+2.851 4.251 2.822 4.343 2.822 4.453 c
+2.822 4.571 2.851 4.663 2.911 4.733 c
+2.977 4.81 3.072 4.85 3.19 4.85 c
+3.314 4.85 3.41 4.81 3.469 4.733 c
+3.528 4.652 3.557 4.56 3.557 4.453 c
+6.468 0.44 m
+6.468 0.588 6.412 0.709 6.306 0.808 c
+6.196 0.904 5.99 1.022 5.689 1.161 c
+5.343 1.308 5.101 1.429 4.954 1.529 c
+4.806 1.635 4.696 1.753 4.63 1.881 c
+4.561 2.006 4.528 2.164 4.528 2.352 c
+4.528 2.674 4.645 2.944 4.881 3.16 c
+5.116 3.373 5.417 3.484 5.791 3.484 c
+6.174 3.484 6.483 3.37 6.718 3.145 c
+6.953 2.917 7.071 2.631 7.071 2.278 c
+6.423 2.278 l
+6.423 2.454 6.365 2.605 6.247 2.734 c
+6.13 2.859 5.976 2.925 5.791 2.925 c
+5.593 2.925 5.442 2.869 5.336 2.763 c
+5.226 2.664 5.174 2.532 5.174 2.366 c
+5.174 2.238 5.211 2.131 5.292 2.043 c
+5.369 1.962 5.56 1.859 5.865 1.734 c
+6.342 1.547 6.674 1.359 6.85 1.176 c
+7.026 0.999 7.115 0.771 7.115 0.5 c
+7.115 0.147 6.99 -0.133 6.747 -0.339 c
+6.512 -0.544 6.196 -0.647 5.806 -0.647 c
+5.384 -0.647 5.045 -0.53 4.792 -0.294 c
+4.534 -0.052 4.41 0.253 4.41 0.617 c
+5.056 0.617 l
+5.064 0.389 5.134 0.213 5.262 0.087 c
+5.388 -0.03 5.571 -0.088 5.806 -0.088 c
+6.02 -0.088 6.181 -0.04 6.292 0.058 c
+6.409 0.154 6.468 0.282 6.468 0.44 c
+8.804 4.365 m
+8.804 3.41 l
+9.407 3.41 l
+9.407 2.881 l
+8.804 2.881 l
+8.804 0.411 l
+8.804 0.253 8.827 0.135 8.879 0.058 c
+8.937 -0.023 9.025 -0.059 9.143 -0.059 c
+9.231 -0.059 9.319 -0.044 9.407 -0.015 c
+9.407 -0.574 l
+9.261 -0.621 9.106 -0.647 8.952 -0.647 c
+8.694 -0.647 8.5 -0.555 8.364 -0.368 c
+8.224 -0.184 8.158 0.077 8.158 0.411 c
+8.158 2.881 l
+7.555 2.881 l
+7.555 3.41 l
+8.158 3.41 l
+8.158 4.365 l
+h
+13.273 -0.088 m
+13.486 -0.088 13.66 -0.026 13.787 0.103 c
+13.924 0.239 13.997 0.43 14.009 0.675 c
+14.626 0.675 l
+14.603 0.294 14.468 -0.026 14.214 -0.279 c
+13.957 -0.526 13.644 -0.647 13.273 -0.647 c
+12.781 -0.647 12.406 -0.497 12.141 -0.191 c
+11.884 0.121 11.759 0.588 11.759 1.205 c
+11.759 1.646 l
+11.759 2.241 11.884 2.697 12.141 3.013 c
+12.406 3.326 12.781 3.484 13.273 3.484 c
+13.674 3.484 13.993 3.351 14.229 3.087 c
+14.471 2.829 14.603 2.484 14.626 2.043 c
+14.009 2.043 l
+13.986 2.337 13.913 2.557 13.787 2.705 c
+13.67 2.851 13.498 2.925 13.273 2.925 c
+12.979 2.925 12.762 2.826 12.627 2.631 c
+12.486 2.443 12.413 2.135 12.406 1.705 c
+12.406 1.19 l
+12.406 0.72 12.472 0.386 12.612 0.191 c
+12.759 0.004 12.979 -0.088 13.273 -0.088 c
+15.243 1.602 m
+15.243 2.179 15.379 2.634 15.655 2.969 c
+15.937 3.31 16.309 3.484 16.771 3.484 c
+17.231 3.484 17.598 3.314 17.874 2.984 c
+18.157 2.66 18.304 2.212 18.315 1.646 c
+18.315 1.22 l
+18.315 0.65 18.171 0.195 17.889 -0.148 c
+17.613 -0.482 17.246 -0.647 16.787 -0.647 c
+16.324 -0.647 15.952 -0.485 15.669 -0.162 c
+15.393 0.168 15.25 0.61 15.243 1.161 c
+h
+15.89 1.22 m
+15.89 0.816 15.967 0.5 16.125 0.264 c
+16.29 0.029 16.511 -0.088 16.787 -0.088 c
+17.352 -0.088 17.646 0.323 17.668 1.146 c
+17.668 1.602 l
+17.668 2.003 17.583 2.322 17.419 2.557 c
+17.261 2.8 17.043 2.925 16.771 2.925 c
+16.507 2.925 16.29 2.8 16.125 2.557 c
+15.967 2.322 15.89 2.003 15.89 1.602 c
+h
+19.771 3.41 m
+19.785 3.042 l
+20.027 3.337 20.347 3.484 20.74 3.484 c
+21.182 3.484 21.49 3.285 21.666 2.896 c
+21.92 3.285 22.269 3.484 22.71 3.484 c
+23.445 3.484 23.82 3.021 23.842 2.102 c
+23.842 -0.574 l
+23.195 -0.574 l
+23.195 2.043 l
+23.195 2.337 23.14 2.55 23.033 2.69 c
+22.934 2.826 22.761 2.896 22.519 2.896 c
+22.321 2.896 22.159 2.815 22.034 2.66 c
+21.916 2.514 21.847 2.322 21.828 2.087 c
+21.828 -0.574 l
+21.167 -0.574 l
+21.167 2.072 l
+21.167 2.62 20.947 2.896 20.505 2.896 c
+20.17 2.896 19.935 2.734 19.8 2.41 c
+19.8 -0.574 l
+19.153 -0.574 l
+19.153 3.41 l
+h
+25.429 3.41 m
+25.444 3.042 l
+25.687 3.337 26.007 3.484 26.4 3.484 c
+26.84 3.484 27.149 3.285 27.326 2.896 c
+27.579 3.285 27.929 3.484 28.369 3.484 c
+29.105 3.484 29.479 3.021 29.501 2.102 c
+29.501 -0.574 l
+28.854 -0.574 l
+28.854 2.043 l
+28.854 2.337 28.799 2.55 28.693 2.69 c
+28.594 2.826 28.421 2.896 28.178 2.896 c
+27.979 2.896 27.818 2.815 27.693 2.66 c
+27.576 2.514 27.505 2.322 27.487 2.087 c
+27.487 -0.574 l
+26.826 -0.574 l
+26.826 2.072 l
+26.826 2.62 26.605 2.896 26.165 2.896 c
+25.83 2.896 25.595 2.734 25.459 2.41 c
+25.459 -0.574 l
+24.812 -0.574 l
+24.812 3.41 l
+h
+31.177 -0.574 -0.647 3.984 re
+31.221 4.453 m
+31.221 4.343 31.191 4.251 31.133 4.174 c
+31.074 4.104 30.979 4.072 30.853 4.072 c
+30.736 4.072 30.64 4.104 30.574 4.174 c
+30.516 4.251 30.486 4.343 30.486 4.453 c
+30.486 4.571 30.516 4.663 30.574 4.733 c
+30.64 4.81 30.736 4.85 30.853 4.85 c
+30.979 4.85 31.074 4.81 31.133 4.733 c
+31.191 4.652 31.221 4.56 31.221 4.453 c
+33.043 4.365 m
+33.043 3.41 l
+33.646 3.41 l
+33.646 2.881 l
+33.043 2.881 l
+33.043 0.411 l
+33.043 0.253 33.066 0.135 33.117 0.058 c
+33.176 -0.023 33.264 -0.059 33.381 -0.059 c
+33.47 -0.059 33.558 -0.044 33.646 -0.015 c
+33.646 -0.574 l
+33.499 -0.621 33.345 -0.647 33.19 -0.647 c
+32.933 -0.647 32.739 -0.555 32.602 -0.368 c
+32.463 -0.184 32.397 0.077 32.397 0.411 c
+32.397 2.881 l
+31.794 2.881 l
+31.794 3.41 l
+32.397 3.41 l
+32.397 4.365 l
+h
+36.351 0.44 m
+36.351 0.588 36.296 0.709 36.189 0.808 c
+36.079 0.904 35.873 1.022 35.572 1.161 c
+35.226 1.308 34.984 1.429 34.837 1.529 c
+34.69 1.635 34.58 1.753 34.514 1.881 c
+34.443 2.006 34.41 2.164 34.41 2.352 c
+34.41 2.674 34.528 2.944 34.763 3.16 c
+34.998 3.373 35.299 3.484 35.675 3.484 c
+36.057 3.484 36.365 3.37 36.6 3.145 c
+36.836 2.917 36.953 2.631 36.953 2.278 c
+36.307 2.278 l
+36.307 2.454 36.248 2.605 36.13 2.734 c
+36.012 2.859 35.858 2.925 35.675 2.925 c
+35.476 2.925 35.326 2.869 35.219 2.763 c
+35.108 2.664 35.058 2.532 35.058 2.366 c
+35.058 2.238 35.094 2.131 35.175 2.043 c
+35.252 1.962 35.443 1.859 35.748 1.734 c
+36.226 1.547 36.556 1.359 36.733 1.176 c
+36.909 0.999 36.997 0.771 36.997 0.5 c
+36.997 0.147 36.872 -0.133 36.631 -0.339 c
+36.395 -0.544 36.079 -0.647 35.69 -0.647 c
+35.266 -0.647 34.929 -0.53 34.675 -0.294 c
+34.418 -0.052 34.293 0.253 34.293 0.617 c
+34.94 0.617 l
+34.948 0.389 35.017 0.213 35.145 0.087 c
+35.27 -0.03 35.455 -0.088 35.69 -0.088 c
+35.902 -0.088 36.064 -0.04 36.174 0.058 c
+36.292 0.154 36.351 0.282 36.351 0.44 c
+40.408 4.365 m
+40.408 3.41 l
+41.011 3.41 l
+41.011 2.881 l
+40.408 2.881 l
+40.408 0.411 l
+40.408 0.253 40.43 0.135 40.481 0.058 c
+40.54 -0.023 40.629 -0.059 40.746 -0.059 c
+40.834 -0.059 40.922 -0.044 41.011 -0.015 c
+41.011 -0.574 l
+40.864 -0.621 40.709 -0.647 40.554 -0.647 c
+40.298 -0.647 40.103 -0.555 39.966 -0.368 c
+39.827 -0.184 39.761 0.077 39.761 0.411 c
+39.761 2.881 l
+39.158 2.881 l
+39.158 3.41 l
+39.761 3.41 l
+39.761 4.365 l
+h
+42.422 2.998 m
+42.675 3.322 42.995 3.484 43.377 3.484 c
+44.082 3.484 44.439 3.013 44.45 2.072 c
+44.45 -0.574 l
+43.804 -0.574 l
+43.804 2.043 l
+43.804 2.356 43.748 2.576 43.642 2.705 c
+43.531 2.829 43.377 2.896 43.171 2.896 c
+43.013 2.896 42.866 2.84 42.73 2.734 c
+42.601 2.624 42.499 2.487 42.422 2.322 c
+42.422 -0.574 l
+41.774 -0.574 l
+41.774 5.071 l
+42.422 5.071 l
+h
+47.449 -0.574 m
+47.409 -0.485 47.382 -0.339 47.375 -0.133 c
+47.14 -0.478 46.846 -0.647 46.493 -0.647 c
+46.129 -0.647 45.846 -0.551 45.641 -0.353 c
+45.442 -0.148 45.346 0.139 45.346 0.515 c
+45.346 0.914 45.483 1.234 45.759 1.469 c
+46.03 1.712 46.405 1.837 46.875 1.837 c
+47.361 1.837 l
+47.361 2.263 l
+47.361 2.499 47.305 2.664 47.199 2.763 c
+47.089 2.869 46.927 2.925 46.713 2.925 c
+46.515 2.925 46.353 2.866 46.229 2.749 c
+46.111 2.631 46.052 2.484 46.052 2.308 c
+45.406 2.308 l
+45.406 2.502 45.464 2.693 45.582 2.881 c
+45.707 3.064 45.869 3.212 46.067 3.322 c
+46.273 3.428 46.501 3.484 46.758 3.484 c
+47.158 3.484 47.463 3.38 47.669 3.175 c
+47.883 2.969 47.997 2.674 48.007 2.293 c
+48.007 0.279 l
+48.007 -0.026 48.044 -0.291 48.124 -0.515 c
+48.124 -0.574 l
+h
+46.582 -0.059 m
+46.746 -0.059 46.898 -0.015 47.037 0.073 c
+47.184 0.162 47.291 0.272 47.361 0.411 c
+47.361 1.352 l
+46.993 1.352 l
+46.677 1.352 46.434 1.282 46.258 1.146 c
+46.081 1.018 45.994 0.83 45.994 0.588 c
+45.994 0.359 46.038 0.195 46.125 0.087 c
+46.214 -0.011 46.364 -0.059 46.582 -0.059 c
+49.859 4.365 m
+49.859 3.41 l
+50.462 3.41 l
+50.462 2.881 l
+49.859 2.881 l
+49.859 0.411 l
+49.859 0.253 49.881 0.135 49.933 0.058 c
+49.992 -0.023 50.079 -0.059 50.197 -0.059 c
+50.285 -0.059 50.374 -0.044 50.462 -0.015 c
+50.462 -0.574 l
+50.315 -0.621 50.16 -0.647 50.006 -0.647 c
+49.749 -0.647 49.554 -0.555 49.418 -0.368 c
+49.279 -0.184 49.213 0.077 49.213 0.411 c
+49.213 2.881 l
+48.61 2.881 l
+48.61 3.41 l
+49.213 3.41 l
+49.213 4.365 l
+h
+54.989 -0.574 m
+54.949 -0.485 54.923 -0.339 54.916 -0.133 c
+54.68 -0.478 54.387 -0.647 54.034 -0.647 c
+53.67 -0.647 53.387 -0.551 53.181 -0.353 c
+52.982 -0.148 52.887 0.139 52.887 0.515 c
+52.887 0.914 53.023 1.234 53.299 1.469 c
+53.57 1.712 53.946 1.837 54.416 1.837 c
+54.901 1.837 l
+54.901 2.263 l
+54.901 2.499 54.846 2.664 54.74 2.763 c
+54.629 2.869 54.468 2.925 54.254 2.925 c
+54.056 2.925 53.894 2.866 53.769 2.749 c
+53.651 2.631 53.593 2.484 53.593 2.308 c
+52.946 2.308 l
+52.946 2.502 53.005 2.693 53.123 2.881 c
+53.248 3.064 53.409 3.212 53.607 3.322 c
+53.813 3.428 54.041 3.484 54.299 3.484 c
+54.699 3.484 55.004 3.38 55.21 3.175 c
+55.423 2.969 55.537 2.674 55.548 2.293 c
+55.548 0.279 l
+55.548 -0.026 55.585 -0.291 55.665 -0.515 c
+55.665 -0.574 l
+h
+54.122 -0.059 m
+54.287 -0.059 54.438 -0.015 54.578 0.073 c
+54.725 0.162 54.831 0.272 54.901 0.411 c
+54.901 1.352 l
+54.534 1.352 l
+54.218 1.352 53.975 1.282 53.799 1.146 c
+53.622 1.018 53.534 0.83 53.534 0.588 c
+53.534 0.359 53.578 0.195 53.666 0.087 c
+53.755 -0.011 53.905 -0.059 54.122 -0.059 c
+58.193 2.792 m
+58.106 2.811 58.006 2.822 57.9 2.822 c
+57.565 2.822 57.33 2.638 57.194 2.278 c
+57.194 -0.574 l
+56.547 -0.574 l
+56.547 3.41 l
+57.179 3.41 l
+57.194 2.998 l
+57.37 3.322 57.613 3.484 57.929 3.484 c
+58.035 3.484 58.124 3.461 58.193 3.424 c
+h
+60.192 -0.647 m
+59.693 -0.647 59.311 -0.5 59.046 -0.206 c
+58.781 0.087 58.649 0.521 58.649 1.103 c
+58.649 1.573 l
+58.649 2.167 58.775 2.634 59.031 2.969 c
+59.296 3.31 59.656 3.484 60.119 3.484 c
+60.579 3.484 60.92 3.329 61.148 3.027 c
+61.383 2.734 61.505 2.271 61.516 1.646 c
+61.516 1.22 l
+59.296 1.22 l
+59.296 1.132 l
+59.296 0.698 59.373 0.386 59.531 0.191 c
+59.697 0.004 59.928 -0.088 60.222 -0.088 c
+60.417 -0.088 60.589 -0.056 60.737 0.014 c
+60.884 0.091 61.019 0.209 61.148 0.367 c
+61.486 -0.044 l
+61.2 -0.449 60.77 -0.647 60.192 -0.647 c
+60.119 2.925 m
+59.843 2.925 59.642 2.829 59.517 2.645 c
+59.388 2.458 59.315 2.167 59.296 1.778 c
+60.869 1.778 l
+60.869 1.866 l
+60.847 2.248 60.78 2.516 60.663 2.674 c
+60.545 2.84 60.362 2.925 60.119 2.925 c
+66.895 1.22 m
+66.895 0.592 66.777 0.121 66.542 -0.191 c
+66.315 -0.497 65.999 -0.647 65.587 -0.647 c
+65.183 -0.647 64.874 -0.497 64.661 -0.191 c
+64.661 -2.103 l
+64.014 -2.103 l
+64.014 3.41 l
+64.602 3.41 l
+64.647 2.969 l
+64.859 3.31 65.168 3.484 65.572 3.484 c
+66.014 3.484 66.341 3.329 66.557 3.027 c
+66.771 2.722 66.885 2.267 66.895 1.66 c
+h
+66.249 1.602 m
+66.249 2.043 66.179 2.366 66.043 2.572 c
+65.904 2.786 65.682 2.896 65.381 2.896 c
+65.065 2.896 64.826 2.741 64.661 2.439 c
+64.661 0.367 l
+64.826 0.062 65.065 -0.088 65.381 -0.088 c
+65.676 -0.088 65.888 0.014 66.029 0.22 c
+66.164 0.434 66.237 0.764 66.249 1.205 c
+h
+69.38 2.792 m
+69.291 2.811 69.192 2.822 69.086 2.822 c
+68.751 2.822 68.516 2.638 68.38 2.278 c
+68.38 -0.574 l
+67.733 -0.574 l
+67.733 3.41 l
+68.365 3.41 l
+68.38 2.998 l
+68.556 3.322 68.799 3.484 69.115 3.484 c
+69.221 3.484 69.31 3.461 69.38 3.424 c
+h
+71.379 -0.647 m
+70.879 -0.647 70.497 -0.5 70.232 -0.206 c
+69.967 0.087 69.835 0.521 69.835 1.103 c
+69.835 1.573 l
+69.835 2.167 69.96 2.634 70.218 2.969 c
+70.482 3.31 70.842 3.484 71.305 3.484 c
+71.764 3.484 72.107 3.329 72.334 3.027 c
+72.57 2.734 72.691 2.271 72.701 1.646 c
+72.701 1.22 l
+70.482 1.22 l
+70.482 1.132 l
+70.482 0.698 70.559 0.386 70.717 0.191 c
+70.883 0.004 71.114 -0.088 71.408 -0.088 c
+71.602 -0.088 71.776 -0.056 71.922 0.014 c
+72.069 0.091 72.206 0.209 72.334 0.367 c
+72.672 -0.044 l
+72.385 -0.449 71.955 -0.647 71.379 -0.647 c
+71.305 2.925 m
+71.03 2.925 70.827 2.829 70.702 2.645 c
+70.574 2.458 70.5 2.167 70.482 1.778 c
+72.055 1.778 l
+72.055 1.866 l
+72.032 2.248 71.967 2.516 71.849 2.674 c
+71.731 2.84 71.548 2.925 71.305 2.925 c
+75.421 0.44 m
+75.421 0.588 75.365 0.709 75.259 0.808 c
+75.149 0.904 74.943 1.022 74.642 1.161 c
+74.297 1.308 74.054 1.429 73.907 1.529 c
+73.76 1.635 73.65 1.753 73.584 1.881 c
+73.514 2.006 73.48 2.164 73.48 2.352 c
+73.48 2.674 73.598 2.944 73.833 3.16 c
+74.068 3.373 74.37 3.484 74.745 3.484 c
+75.126 3.484 75.436 3.37 75.671 3.145 c
+75.906 2.917 76.024 2.631 76.024 2.278 c
+75.377 2.278 l
+75.377 2.454 75.318 2.605 75.201 2.734 c
+75.083 2.859 74.929 2.925 74.745 2.925 c
+74.546 2.925 74.396 2.869 74.289 2.763 c
+74.179 2.664 74.127 2.532 74.127 2.366 c
+74.127 2.238 74.164 2.131 74.245 2.043 c
+74.322 1.962 74.513 1.859 74.818 1.734 c
+75.296 1.547 75.627 1.359 75.803 1.176 c
+75.98 0.999 76.067 0.771 76.067 0.5 c
+76.067 0.147 75.943 -0.133 75.7 -0.339 c
+75.465 -0.544 75.149 -0.647 74.76 -0.647 c
+74.337 -0.647 73.999 -0.53 73.745 -0.294 c
+73.488 -0.052 73.363 0.253 73.363 0.617 c
+74.01 0.617 l
+74.017 0.389 74.087 0.213 74.216 0.087 c
+74.34 -0.03 74.524 -0.088 74.76 -0.088 c
+74.972 -0.088 75.134 -0.04 75.244 0.058 c
+75.362 0.154 75.421 0.282 75.421 0.44 c
+78.332 -0.647 m
+77.831 -0.647 77.449 -0.5 77.185 -0.206 c
+76.92 0.087 76.788 0.521 76.788 1.103 c
+76.788 1.573 l
+76.788 2.167 76.913 2.634 77.17 2.969 c
+77.435 3.31 77.794 3.484 78.258 3.484 c
+78.717 3.484 79.059 3.329 79.286 3.027 c
+79.522 2.734 79.643 2.271 79.654 1.646 c
+79.654 1.22 l
+77.435 1.22 l
+77.435 1.132 l
+77.435 0.698 77.512 0.386 77.67 0.191 c
+77.835 0.004 78.066 -0.088 78.361 -0.088 c
+78.555 -0.088 78.729 -0.056 78.875 0.014 c
+79.022 0.091 79.159 0.209 79.286 0.367 c
+79.625 -0.044 l
+79.338 -0.449 78.908 -0.647 78.332 -0.647 c
+78.258 2.925 m
+77.983 2.925 77.78 2.829 77.655 2.645 c
+77.526 2.458 77.453 2.167 77.435 1.778 c
+79.007 1.778 l
+79.007 1.866 l
+78.985 2.248 78.92 2.516 78.802 2.674 c
+78.684 2.84 78.5 2.925 78.258 2.925 c
+81.05 3.41 m
+81.065 2.969 l
+81.318 3.31 81.642 3.484 82.035 3.484 c
+82.741 3.484 83.097 3.013 83.109 2.072 c
+83.109 -0.574 l
+82.461 -0.574 l
+82.461 2.043 l
+82.461 2.356 82.407 2.576 82.3 2.705 c
+82.19 2.829 82.035 2.896 81.829 2.896 c
+81.671 2.896 81.524 2.84 81.389 2.734 c
+81.26 2.624 81.158 2.487 81.08 2.322 c
+81.08 -0.574 l
+80.433 -0.574 l
+80.433 3.41 l
+h
+84.931 4.365 m
+84.931 3.41 l
+85.534 3.41 l
+85.534 2.881 l
+84.931 2.881 l
+84.931 0.411 l
+84.931 0.253 84.953 0.135 85.004 0.058 c
+85.064 -0.023 85.152 -0.059 85.27 -0.059 c
+85.357 -0.059 85.445 -0.044 85.534 -0.015 c
+85.534 -0.574 l
+85.387 -0.621 85.233 -0.647 85.079 -0.647 c
+84.821 -0.647 84.626 -0.555 84.491 -0.368 c
+84.35 -0.184 84.285 0.077 84.285 0.411 c
+84.285 2.881 l
+83.682 2.881 l
+83.682 3.41 l
+84.285 3.41 l
+84.285 4.365 l
+h
+87.886 1.602 m
+87.886 2.179 88.021 2.634 88.297 2.969 c
+88.58 3.31 88.952 3.484 89.414 3.484 c
+89.874 3.484 90.241 3.314 90.517 2.984 c
+90.8 2.66 90.947 2.212 90.958 1.646 c
+90.958 1.22 l
+90.958 0.65 90.814 0.195 90.531 -0.148 c
+90.255 -0.482 89.889 -0.647 89.43 -0.647 c
+88.966 -0.647 88.595 -0.485 88.312 -0.162 c
+88.036 0.168 87.893 0.61 87.886 1.161 c
+h
+88.532 1.22 m
+88.532 0.816 88.609 0.5 88.767 0.264 c
+88.933 0.029 89.154 -0.088 89.43 -0.088 c
+89.995 -0.088 90.289 0.323 90.311 1.146 c
+90.311 1.602 l
+90.311 2.003 90.226 2.322 90.061 2.557 c
+89.903 2.8 89.686 2.925 89.414 2.925 c
+89.15 2.925 88.933 2.8 88.767 2.557 c
+88.609 2.322 88.532 2.003 88.532 1.602 c
+h
+92.413 3.41 m
+92.428 2.969 l
+92.682 3.31 93.004 3.484 93.398 3.484 c
+94.103 3.484 94.46 3.013 94.471 2.072 c
+94.471 -0.574 l
+93.824 -0.574 l
+93.824 2.043 l
+93.824 2.356 93.769 2.576 93.663 2.705 c
+93.552 2.829 93.398 2.896 93.192 2.896 c
+93.034 2.896 92.887 2.84 92.751 2.734 c
+92.622 2.624 92.52 2.487 92.443 2.322 c
+92.443 -0.574 l
+91.795 -0.574 l
+91.795 3.41 l
+h
+98.542 -0.088 m
+98.756 -0.088 98.928 -0.026 99.057 0.103 c
+99.192 0.239 99.267 0.43 99.277 0.675 c
+99.895 0.675 l
+99.873 0.294 99.737 -0.026 99.483 -0.279 c
+99.226 -0.526 98.914 -0.647 98.542 -0.647 c
+98.05 -0.647 97.675 -0.497 97.411 -0.191 c
+97.153 0.121 97.029 0.588 97.029 1.205 c
+97.029 1.646 l
+97.029 2.241 97.153 2.697 97.411 3.013 c
+97.675 3.326 98.05 3.484 98.542 3.484 c
+98.943 3.484 99.263 3.351 99.498 3.087 c
+99.74 2.829 99.873 2.484 99.895 2.043 c
+99.277 2.043 l
+99.256 2.337 99.182 2.557 99.057 2.705 c
+98.939 2.851 98.766 2.925 98.542 2.925 c
+98.249 2.925 98.032 2.826 97.896 2.631 c
+97.756 2.443 97.683 2.135 97.675 1.705 c
+97.675 1.19 l
+97.675 0.72 97.742 0.386 97.881 0.191 c
+98.028 0.004 98.249 -0.088 98.542 -0.088 c
+102.673 -0.221 m
+102.456 -0.507 102.144 -0.647 101.732 -0.647 c
+101.368 -0.647 101.093 -0.526 100.909 -0.279 c
+100.732 -0.026 100.637 0.338 100.63 0.808 c
+100.63 3.41 l
+101.276 3.41 l
+101.276 0.867 l
+101.276 0.239 101.461 -0.073 101.835 -0.073 c
+102.236 -0.073 102.511 0.103 102.658 0.455 c
+102.658 3.41 l
+103.305 3.41 l
+103.305 -0.574 l
+102.687 -0.574 l
+h
+105.936 2.792 m
+105.848 2.811 105.749 2.822 105.642 2.822 c
+105.307 2.822 105.072 2.638 104.937 2.278 c
+104.937 -0.574 l
+104.289 -0.574 l
+104.289 3.41 l
+104.922 3.41 l
+104.937 2.998 l
+105.113 3.322 105.355 3.484 105.671 3.484 c
+105.778 3.484 105.866 3.461 105.936 3.424 c
+h
+108.229 2.792 m
+108.141 2.811 108.042 2.822 107.935 2.822 c
+107.601 2.822 107.366 2.638 107.229 2.278 c
+107.229 -0.574 l
+106.583 -0.574 l
+106.583 3.41 l
+107.215 3.41 l
+107.229 2.998 l
+107.406 3.322 107.649 3.484 107.965 3.484 c
+108.071 3.484 108.16 3.461 108.229 3.424 c
+h
+110.228 -0.647 m
+109.729 -0.647 109.346 -0.5 109.082 -0.206 c
+108.817 0.087 108.685 0.521 108.685 1.103 c
+108.685 1.573 l
+108.685 2.167 108.81 2.634 109.067 2.969 c
+109.332 3.31 109.692 3.484 110.155 3.484 c
+110.614 3.484 110.956 3.329 111.184 3.027 c
+111.419 2.734 111.54 2.271 111.551 1.646 c
+111.551 1.22 l
+109.332 1.22 l
+109.332 1.132 l
+109.332 0.698 109.409 0.386 109.567 0.191 c
+109.733 0.004 109.964 -0.088 110.257 -0.088 c
+110.452 -0.088 110.625 -0.056 110.772 0.014 c
+110.919 0.091 111.055 0.209 111.184 0.367 c
+111.522 -0.044 l
+111.235 -0.449 110.805 -0.647 110.228 -0.647 c
+110.155 2.925 m
+109.879 2.925 109.677 2.829 109.552 2.645 c
+109.423 2.458 109.35 2.167 109.332 1.778 c
+110.905 1.778 l
+110.905 1.866 l
+110.882 2.248 110.816 2.516 110.699 2.674 c
+110.581 2.84 110.398 2.925 110.155 2.925 c
+112.948 3.41 m
+112.962 2.969 l
+113.216 3.31 113.539 3.484 113.932 3.484 c
+114.638 3.484 114.994 3.013 115.005 2.072 c
+115.005 -0.574 l
+114.359 -0.574 l
+114.359 2.043 l
+114.359 2.356 114.304 2.576 114.197 2.705 c
+114.086 2.829 113.932 2.896 113.727 2.896 c
+113.569 2.896 113.421 2.84 113.286 2.734 c
+113.157 2.624 113.054 2.487 112.977 2.322 c
+112.977 -0.574 l
+112.33 -0.574 l
+112.33 3.41 l
+h
+116.829 4.365 m
+116.829 3.41 l
+117.431 3.41 l
+117.431 2.881 l
+116.829 2.881 l
+116.829 0.411 l
+116.829 0.253 116.85 0.135 116.902 0.058 c
+116.96 -0.023 117.049 -0.059 117.166 -0.059 c
+117.255 -0.059 117.342 -0.044 117.431 -0.015 c
+117.431 -0.574 l
+117.284 -0.621 117.13 -0.647 116.975 -0.647 c
+116.718 -0.647 116.523 -0.555 116.387 -0.368 c
+116.247 -0.184 116.181 0.077 116.181 0.411 c
+116.181 2.881 l
+115.578 2.881 l
+115.578 3.41 l
+116.181 3.41 l
+116.181 4.365 l
+h
+122.796 1.22 m
+122.796 0.602 122.682 0.135 122.458 -0.177 c
+122.241 -0.493 121.918 -0.647 121.488 -0.647 c
+121.065 -0.647 120.752 -0.467 120.547 -0.104 c
+120.517 -0.574 l
+119.915 -0.574 l
+119.915 5.071 l
+120.561 5.071 l
+120.561 2.969 l
+120.775 3.31 121.084 3.484 121.488 3.484 c
+121.918 3.484 122.241 3.326 122.458 3.013 c
+122.682 2.708 122.796 2.241 122.796 1.616 c
+h
+122.149 1.602 m
+122.149 2.072 122.08 2.403 121.943 2.601 c
+121.814 2.796 121.606 2.896 121.311 2.896 c
+120.977 2.896 120.727 2.711 120.561 2.352 c
+120.561 0.47 l
+120.727 0.106 120.981 -0.073 121.326 -0.073 c
+121.62 -0.073 121.83 0.029 121.958 0.235 c
+122.083 0.44 122.149 0.756 122.149 1.19 c
+h
+125.28 2.792 m
+125.192 2.811 125.093 2.822 124.986 2.822 c
+124.652 2.822 124.417 2.638 124.28 2.278 c
+124.28 -0.574 l
+123.634 -0.574 l
+123.634 3.41 l
+124.266 3.41 l
+124.28 2.998 l
+124.457 3.322 124.7 3.484 125.016 3.484 c
+125.122 3.484 125.211 3.461 125.28 3.424 c
+h
+127.823 -0.574 m
+127.783 -0.485 127.757 -0.339 127.75 -0.133 c
+127.514 -0.478 127.22 -0.647 126.867 -0.647 c
+126.504 -0.647 126.221 -0.551 126.015 -0.353 c
+125.816 -0.148 125.721 0.139 125.721 0.515 c
+125.721 0.914 125.857 1.234 126.132 1.469 c
+126.404 1.712 126.78 1.837 127.25 1.837 c
+127.735 1.837 l
+127.735 2.263 l
+127.735 2.499 127.68 2.664 127.573 2.763 c
+127.463 2.869 127.301 2.925 127.088 2.925 c
+126.89 2.925 126.728 2.866 126.603 2.749 c
+126.485 2.631 126.427 2.484 126.427 2.308 c
+125.78 2.308 l
+125.78 2.502 125.839 2.693 125.957 2.881 c
+126.081 3.064 126.243 3.212 126.441 3.322 c
+126.647 3.428 126.875 3.484 127.132 3.484 c
+127.532 3.484 127.838 3.38 128.043 3.175 c
+128.257 2.969 128.37 2.674 128.382 2.293 c
+128.382 0.279 l
+128.382 -0.026 128.418 -0.291 128.499 -0.515 c
+128.499 -0.574 l
+h
+126.956 -0.059 m
+127.121 -0.059 127.272 -0.015 127.412 0.073 c
+127.559 0.162 127.665 0.272 127.735 0.411 c
+127.735 1.352 l
+127.368 1.352 l
+127.052 1.352 126.809 1.282 126.632 1.146 c
+126.456 1.018 126.368 0.83 126.368 0.588 c
+126.368 0.359 126.412 0.195 126.5 0.087 c
+126.589 -0.011 126.739 -0.059 126.956 -0.059 c
+129.999 3.41 m
+130.013 2.969 l
+130.267 3.31 130.59 3.484 130.983 3.484 c
+131.688 3.484 132.045 3.013 132.056 2.072 c
+132.056 -0.574 l
+131.41 -0.574 l
+131.41 2.043 l
+131.41 2.356 131.354 2.576 131.248 2.705 c
+131.138 2.829 130.983 2.896 130.778 2.896 c
+130.62 2.896 130.472 2.84 130.337 2.734 c
+130.208 2.624 130.105 2.487 130.028 2.322 c
+130.028 -0.574 l
+129.381 -0.574 l
+129.381 3.41 l
+h
+134.408 -0.088 m
+134.622 -0.088 134.794 -0.026 134.923 0.103 c
+135.058 0.239 135.133 0.43 135.143 0.675 c
+135.761 0.675 l
+135.738 0.294 135.603 -0.026 135.349 -0.279 c
+135.092 -0.526 134.78 -0.647 134.408 -0.647 c
+133.916 -0.647 133.541 -0.497 133.276 -0.191 c
+133.02 0.121 132.894 0.588 132.894 1.205 c
+132.894 1.646 l
+132.894 2.241 133.02 2.697 133.276 3.013 c
+133.541 3.326 133.916 3.484 134.408 3.484 c
+134.809 3.484 135.129 3.351 135.364 3.087 c
+135.607 2.829 135.738 2.484 135.761 2.043 c
+135.143 2.043 l
+135.121 2.337 135.048 2.557 134.923 2.705 c
+134.805 2.851 134.632 2.925 134.408 2.925 c
+134.115 2.925 133.897 2.826 133.762 2.631 c
+133.622 2.443 133.548 2.135 133.541 1.705 c
+133.541 1.19 l
+133.541 0.72 133.607 0.386 133.747 0.191 c
+133.894 0.004 134.115 -0.088 134.408 -0.088 c
+137.157 2.998 m
+137.41 3.322 137.73 3.484 138.113 3.484 c
+138.818 3.484 139.174 3.013 139.185 2.072 c
+139.185 -0.574 l
+138.539 -0.574 l
+138.539 2.043 l
+138.539 2.356 138.483 2.576 138.377 2.705 c
+138.267 2.829 138.113 2.896 137.907 2.896 c
+137.749 2.896 137.602 2.84 137.466 2.734 c
+137.337 2.624 137.234 2.487 137.157 2.322 c
+137.157 -0.574 l
+136.51 -0.574 l
+136.51 5.071 l
+137.157 5.071 l
+h
+143.904 -0.574 m
+143.864 -0.485 143.838 -0.339 143.831 -0.133 c
+143.595 -0.478 143.301 -0.647 142.948 -0.647 c
+142.584 -0.647 142.302 -0.551 142.096 -0.353 c
+141.897 -0.148 141.801 0.139 141.801 0.515 c
+141.801 0.914 141.938 1.234 142.213 1.469 c
+142.485 1.712 142.86 1.837 143.33 1.837 c
+143.816 1.837 l
+143.816 2.263 l
+143.816 2.499 143.76 2.664 143.654 2.763 c
+143.544 2.869 143.382 2.925 143.169 2.925 c
+142.971 2.925 142.809 2.866 142.684 2.749 c
+142.566 2.631 142.507 2.484 142.507 2.308 c
+141.861 2.308 l
+141.861 2.502 141.919 2.693 142.037 2.881 c
+142.162 3.064 142.324 3.212 142.522 3.322 c
+142.728 3.428 142.956 3.484 143.213 3.484 c
+143.613 3.484 143.918 3.38 144.124 3.175 c
+144.338 2.969 144.451 2.674 144.463 2.293 c
+144.463 0.279 l
+144.463 -0.026 144.499 -0.291 144.58 -0.515 c
+144.58 -0.574 l
+h
+143.037 -0.059 m
+143.202 -0.059 143.353 -0.015 143.492 0.073 c
+143.64 0.162 143.746 0.272 143.816 0.411 c
+143.816 1.352 l
+143.448 1.352 l
+143.133 1.352 142.89 1.282 142.713 1.146 c
+142.537 1.018 142.449 0.83 142.449 0.588 c
+142.449 0.359 142.493 0.195 142.581 0.087 c
+142.669 -0.011 142.819 -0.059 143.037 -0.059 c
+146.079 3.41 m
+146.094 2.969 l
+146.347 3.31 146.671 3.484 147.064 3.484 c
+147.769 3.484 148.126 3.013 148.137 2.072 c
+148.137 -0.574 l
+147.49 -0.574 l
+147.49 2.043 l
+147.49 2.356 147.435 2.576 147.328 2.705 c
+147.218 2.829 147.064 2.896 146.858 2.896 c
+146.7 2.896 146.553 2.84 146.418 2.734 c
+146.289 2.624 146.186 2.487 146.109 2.322 c
+146.109 -0.574 l
+145.462 -0.574 l
+145.462 3.41 l
+h
+148.975 1.602 m
+148.975 2.208 149.086 2.674 149.313 2.998 c
+149.548 3.322 149.875 3.484 150.298 3.484 c
+150.68 3.484 150.977 3.326 151.195 3.013 c
+151.195 5.071 l
+151.841 5.071 l
+151.841 -0.574 l
+151.253 -0.574 l
+151.209 -0.148 l
+151.004 -0.482 150.698 -0.647 150.298 -0.647 c
+149.886 -0.647 149.562 -0.493 149.327 -0.177 c
+149.092 0.147 148.975 0.602 148.975 1.19 c
+h
+149.622 1.22 m
+149.622 0.779 149.684 0.448 149.813 0.235 c
+149.949 0.029 150.169 -0.073 150.474 -0.073 c
+150.798 -0.073 151.037 0.087 151.195 0.411 c
+151.195 2.425 l
+151.025 2.738 150.786 2.896 150.474 2.896 c
+150.169 2.896 149.949 2.792 149.813 2.587 c
+149.684 2.381 149.622 2.057 149.622 1.616 c
+h
+155.178 3.41 m
+155.193 2.969 l
+155.446 3.31 155.77 3.484 156.163 3.484 c
+156.868 3.484 157.225 3.013 157.236 2.072 c
+157.236 -0.574 l
+156.589 -0.574 l
+156.589 2.043 l
+156.589 2.356 156.534 2.576 156.427 2.705 c
+156.317 2.829 156.163 2.896 155.957 2.896 c
+155.799 2.896 155.652 2.84 155.516 2.734 c
+155.388 2.624 155.284 2.487 155.207 2.322 c
+155.207 -0.574 l
+154.561 -0.574 l
+154.561 3.41 l
+h
+158.073 1.602 m
+158.073 2.179 158.21 2.634 158.485 2.969 c
+158.769 3.31 159.139 3.484 159.602 3.484 c
+160.062 3.484 160.429 3.314 160.705 2.984 c
+160.988 2.66 161.135 2.212 161.146 1.646 c
+161.146 1.22 l
+161.146 0.65 161.003 0.195 160.72 -0.148 c
+160.444 -0.482 160.076 -0.647 159.617 -0.647 c
+159.154 -0.647 158.783 -0.485 158.5 -0.162 c
+158.224 0.168 158.081 0.61 158.073 1.161 c
+h
+158.721 1.22 m
+158.721 0.816 158.798 0.5 158.956 0.264 c
+159.121 0.029 159.341 -0.088 159.617 -0.088 c
+160.183 -0.088 160.477 0.323 160.499 1.146 c
+160.499 1.602 l
+160.499 2.003 160.415 2.322 160.249 2.557 c
+160.091 2.8 159.874 2.925 159.602 2.925 c
+159.338 2.925 159.121 2.8 158.956 2.557 c
+158.798 2.322 158.721 2.003 158.721 1.602 c
+h
+162.836 4.365 m
+162.836 3.41 l
+163.438 3.41 l
+163.438 2.881 l
+162.836 2.881 l
+162.836 0.411 l
+162.836 0.253 162.858 0.135 162.91 0.058 c
+162.968 -0.023 163.056 -0.059 163.174 -0.059 c
+163.262 -0.059 163.351 -0.044 163.438 -0.015 c
+163.438 -0.574 l
+163.292 -0.621 163.137 -0.647 162.983 -0.647 c
+162.726 -0.647 162.532 -0.555 162.395 -0.368 c
+162.256 -0.184 162.189 0.077 162.189 0.411 c
+162.189 2.881 l
+161.587 2.881 l
+161.587 3.41 l
+162.189 3.41 l
+162.189 4.365 l
+h
+166.54 3.41 m
+166.555 3.042 l
+166.798 3.337 167.118 3.484 167.511 3.484 c
+167.951 3.484 168.26 3.285 168.437 2.896 c
+168.69 3.285 169.04 3.484 169.48 3.484 c
+170.215 3.484 170.59 3.021 170.612 2.102 c
+170.612 -0.574 l
+169.965 -0.574 l
+169.965 2.043 l
+169.965 2.337 169.91 2.55 169.803 2.69 c
+169.705 2.826 169.532 2.896 169.289 2.896 c
+169.09 2.896 168.929 2.815 168.804 2.66 c
+168.687 2.514 168.616 2.322 168.598 2.087 c
+168.598 -0.574 l
+167.937 -0.574 l
+167.937 2.072 l
+167.937 2.62 167.716 2.896 167.276 2.896 c
+166.941 2.896 166.706 2.734 166.57 2.41 c
+166.57 -0.574 l
+165.923 -0.574 l
+165.923 3.41 l
+h
+173.008 -0.647 m
+172.508 -0.647 172.126 -0.5 171.862 -0.206 c
+171.597 0.087 171.465 0.521 171.465 1.103 c
+171.465 1.573 l
+171.465 2.167 171.59 2.634 171.847 2.969 c
+172.111 3.31 172.471 3.484 172.934 3.484 c
+173.393 3.484 173.736 3.329 173.963 3.027 c
+174.199 2.734 174.32 2.271 174.331 1.646 c
+174.331 1.22 l
+172.111 1.22 l
+172.111 1.132 l
+172.111 0.698 172.188 0.386 172.346 0.191 c
+172.512 0.004 172.743 -0.088 173.038 -0.088 c
+173.232 -0.088 173.405 -0.056 173.551 0.014 c
+173.699 0.091 173.835 0.209 173.963 0.367 c
+174.301 -0.044 l
+174.015 -0.449 173.585 -0.647 173.008 -0.647 c
+172.934 2.925 m
+172.659 2.925 172.456 2.829 172.332 2.645 c
+172.203 2.458 172.13 2.167 172.111 1.778 c
+173.684 1.778 l
+173.684 1.866 l
+173.662 2.248 173.596 2.516 173.478 2.674 c
+173.36 2.84 173.177 2.925 172.934 2.925 c
+176.756 2.792 m
+176.668 2.811 176.568 2.822 176.462 2.822 c
+176.128 2.822 175.893 2.638 175.756 2.278 c
+175.756 -0.574 l
+175.11 -0.574 l
+175.11 3.41 l
+175.742 3.41 l
+175.756 2.998 l
+175.933 3.322 176.175 3.484 176.491 3.484 c
+176.598 3.484 176.686 3.461 176.756 3.424 c
+h
+177.197 1.602 m
+177.197 2.219 177.308 2.682 177.535 2.998 c
+177.759 3.322 178.094 3.484 178.534 3.484 c
+178.935 3.484 179.24 3.307 179.446 2.954 c
+179.49 3.41 l
+180.078 3.41 l
+180.078 -0.618 l
+180.078 -1.106 179.949 -1.484 179.696 -1.75 c
+179.439 -2.014 179.086 -2.147 178.638 -2.147 c
+178.439 -2.147 178.218 -2.095 177.977 -1.999 c
+177.73 -1.9 177.549 -1.779 177.432 -1.632 c
+177.697 -1.191 l
+177.962 -1.455 178.259 -1.588 178.594 -1.588 c
+179.13 -1.588 179.406 -1.294 179.417 -0.706 c
+179.417 -0.177 l
+179.211 -0.493 178.91 -0.647 178.52 -0.647 c
+178.108 -0.647 177.785 -0.497 177.549 -0.191 c
+177.322 0.121 177.204 0.573 177.197 1.161 c
+h
+177.859 1.22 m
+177.859 0.779 177.921 0.448 178.05 0.235 c
+178.175 0.029 178.391 -0.073 178.696 -0.073 c
+179.02 -0.073 179.259 0.091 179.417 0.426 c
+179.417 2.41 l
+179.248 2.734 179.009 2.896 178.696 2.896 c
+178.403 2.896 178.185 2.792 178.05 2.587 c
+177.921 2.381 177.859 2.057 177.859 1.616 c
+h
+182.459 -0.647 m
+181.96 -0.647 181.578 -0.5 181.312 -0.206 c
+181.048 0.087 180.916 0.521 180.916 1.103 c
+180.916 1.573 l
+180.916 2.167 181.041 2.634 181.298 2.969 c
+181.563 3.31 181.923 3.484 182.386 3.484 c
+182.845 3.484 183.187 3.329 183.415 3.027 c
+183.65 2.734 183.772 2.271 183.782 1.646 c
+183.782 1.22 l
+181.563 1.22 l
+181.563 1.132 l
+181.563 0.698 181.64 0.386 181.798 0.191 c
+181.963 0.004 182.195 -0.088 182.488 -0.088 c
+182.683 -0.088 182.856 -0.056 183.003 0.014 c
+183.151 0.091 183.286 0.209 183.415 0.367 c
+183.753 -0.044 l
+183.466 -0.449 183.036 -0.647 182.459 -0.647 c
+182.386 2.925 m
+182.11 2.925 181.908 2.829 181.783 2.645 c
+181.655 2.458 181.582 2.167 181.563 1.778 c
+183.136 1.778 l
+183.136 1.866 l
+183.114 2.248 183.047 2.516 182.93 2.674 c
+182.812 2.84 182.629 2.925 182.386 2.925 c
+184.429 1.602 m
+184.429 2.208 184.539 2.674 184.767 2.998 c
+185.002 3.322 185.329 3.484 185.752 3.484 c
+186.134 3.484 186.432 3.326 186.648 3.013 c
+186.648 5.071 l
+187.296 5.071 l
+187.296 -0.574 l
+186.708 -0.574 l
+186.663 -0.148 l
+186.457 -0.482 186.153 -0.647 185.752 -0.647 c
+185.341 -0.647 185.017 -0.493 184.782 -0.177 c
+184.547 0.147 184.429 0.602 184.429 1.19 c
+h
+185.075 1.22 m
+185.075 0.779 185.138 0.448 185.267 0.235 c
+185.403 0.029 185.623 -0.073 185.929 -0.073 c
+186.251 -0.073 186.49 0.087 186.648 0.411 c
+186.648 2.425 l
+186.48 2.738 186.241 2.896 185.929 2.896 c
+185.623 2.896 185.403 2.792 185.267 2.587 c
+185.138 2.381 185.075 2.057 185.075 1.616 c
+h
+190.72 -0.574 -0.646 3.984 re
+190.764 4.453 m
+190.764 4.343 190.735 4.251 190.677 4.174 c
+190.617 4.104 190.521 4.072 190.397 4.072 c
+190.28 4.072 190.184 4.104 190.118 4.174 c
+190.059 4.251 190.029 4.343 190.029 4.453 c
+190.029 4.571 190.059 4.663 190.118 4.733 c
+190.184 4.81 190.28 4.85 190.397 4.85 c
+190.521 4.85 190.617 4.81 190.677 4.733 c
+190.735 4.652 190.764 4.56 190.764 4.453 c
+192.352 3.41 m
+192.366 2.969 l
+192.62 3.31 192.944 3.484 193.337 3.484 c
+194.043 3.484 194.399 3.013 194.409 2.072 c
+194.409 -0.574 l
+193.763 -0.574 l
+193.763 2.043 l
+193.763 2.356 193.708 2.576 193.601 2.705 c
+193.491 2.829 193.337 2.896 193.131 2.896 c
+192.973 2.896 192.826 2.84 192.69 2.734 c
+192.561 2.624 192.458 2.487 192.381 2.322 c
+192.381 -0.574 l
+191.735 -0.574 l
+191.735 3.41 l
+h
+196.233 4.365 m
+196.233 3.41 l
+196.835 3.41 l
+196.835 2.881 l
+196.233 2.881 l
+196.233 0.411 l
+196.233 0.253 196.254 0.135 196.306 0.058 c
+196.364 -0.023 196.453 -0.059 196.57 -0.059 c
+196.659 -0.059 196.747 -0.044 196.835 -0.015 c
+196.835 -0.574 l
+196.688 -0.621 196.534 -0.647 196.379 -0.647 c
+196.123 -0.647 195.928 -0.555 195.791 -0.368 c
+195.652 -0.184 195.585 0.077 195.585 0.411 c
+195.585 2.881 l
+194.983 2.881 l
+194.983 3.41 l
+195.585 3.41 l
+195.585 4.365 l
+h
+197.393 1.602 m
+197.393 2.179 197.53 2.634 197.806 2.969 c
+198.088 3.31 198.459 3.484 198.922 3.484 c
+199.381 3.484 199.749 3.314 200.025 2.984 c
+200.308 2.66 200.455 2.212 200.466 1.646 c
+200.466 1.22 l
+200.466 0.65 200.322 0.195 200.04 -0.148 c
+199.764 -0.482 199.396 -0.647 198.937 -0.647 c
+198.474 -0.647 198.103 -0.485 197.82 -0.162 c
+197.544 0.168 197.401 0.61 197.393 1.161 c
+h
+198.041 1.22 m
+198.041 0.816 198.118 0.5 198.276 0.264 c
+198.441 0.029 198.662 -0.088 198.937 -0.088 c
+199.503 -0.088 199.797 0.323 199.819 1.146 c
+199.819 1.602 l
+199.819 2.003 199.734 2.322 199.569 2.557 c
+199.411 2.8 199.194 2.925 198.922 2.925 c
+198.658 2.925 198.441 2.8 198.276 2.557 c
+198.118 2.322 198.041 2.003 198.041 1.602 c
+h
+f
+Q
+q 1 0 0 1 263.3007 391.1359 cm
+0 0 m
+-0.338 0.029 l
+-0.625 0.029 -0.816 -0.096 -0.911 -0.339 c
+-0.911 -2.97 l
+-1.955 -2.97 l
+-1.955 1.014 l
+-0.985 1.014 l
+-0.955 0.573 l
+-0.79 0.914 -0.558 1.087 -0.264 1.087 c
+-0.147 1.087 -0.055 1.065 0.015 1.028 c
+h
+2.072 -3.043 m
+1.544 -3.043 1.125 -2.889 0.823 -2.573 c
+0.53 -2.249 0.383 -1.79 0.383 -1.191 c
+0.383 -0.882 l
+0.383 -0.258 0.518 0.228 0.794 0.573 c
+1.066 0.914 1.459 1.087 1.97 1.087 c
+2.469 1.087 2.841 0.926 3.087 0.602 c
+3.341 0.278 3.473 -0.199 3.484 -0.823 c
+3.484 -1.324 l
+1.411 -1.324 l
+1.43 -1.617 1.492 -1.834 1.602 -1.97 c
+1.72 -2.11 1.9 -2.176 2.147 -2.176 c
+2.488 -2.176 2.778 -2.058 3.013 -1.823 c
+3.425 -2.455 l
+3.296 -2.631 3.109 -2.775 2.866 -2.881 c
+2.62 -2.988 2.356 -3.043 2.072 -3.043 c
+1.426 -0.603 m
+2.455 -0.603 l
+2.455 -0.5 l
+2.455 -0.265 2.415 -0.088 2.338 0.029 c
+2.267 0.154 2.139 0.22 1.955 0.22 c
+1.779 0.22 1.646 0.151 1.559 0.014 c
+1.478 -0.115 1.434 -0.32 1.426 -0.603 c
+4.307 -2.97 m
+4.307 0.22 l
+3.822 0.22 l
+3.822 1.014 l
+4.307 1.014 l
+4.307 1.367 l
+4.307 1.807 4.418 2.146 4.645 2.381 c
+4.881 2.624 5.197 2.748 5.6 2.748 c
+5.725 2.748 5.883 2.723 6.071 2.674 c
+6.071 1.851 l
+6.001 1.87 5.916 1.881 5.821 1.881 c
+5.505 1.881 5.351 1.697 5.351 1.337 c
+5.351 1.014 l
+5.968 1.014 l
+5.968 0.22 l
+5.351 0.22 l
+5.351 -2.97 l
+h
+f
+Q
+q 1 0 0 1 269.9893 388.5188 cm
+0 0 m
+0 0.118 0.033 0.214 0.103 0.294 c
+0.168 0.372 0.272 0.412 0.411 0.412 c
+0.558 0.412 0.665 0.372 0.735 0.294 c
+0.812 0.214 0.852 0.118 0.852 0 c
+0.852 -0.11 0.812 -0.202 0.735 -0.279 c
+0.665 -0.357 0.558 -0.397 0.411 -0.397 c
+0.272 -0.397 0.168 -0.357 0.103 -0.279 c
+0.033 -0.202 0 -0.11 0 0 c
+f
+Q
+q 1 0 0 1 135.7129 380.1556 cm
+0 0 m
+-1.808 0 l
+-2.219 -1.397 l
+-2.91 -1.397 l
+-1.19 3.954 l
+-0.617 3.954 l
+1.118 -1.397 l
+0.426 -1.397 l
+h
+-1.631 0.588 m
+-0.176 0.588 l
+-0.897 3.013 l
+h
+f
+Q
+q 1 0 0 1 141.0347 381.7285 cm
+0 0 m
+-0.339 0.029 l
+-0.625 0.029 -0.817 -0.096 -0.912 -0.339 c
+-0.912 -2.97 l
+-1.956 -2.97 l
+-1.956 1.014 l
+-0.985 1.014 l
+-0.956 0.573 l
+-0.79 0.914 -0.559 1.087 -0.265 1.087 c
+-0.148 1.087 -0.056 1.065 0.014 1.028 c
+h
+2.072 -3.043 m
+1.543 -3.043 1.124 -2.889 0.823 -2.573 c
+0.529 -2.249 0.382 -1.79 0.382 -1.191 c
+0.382 -0.882 l
+0.382 -0.258 0.517 0.228 0.793 0.573 c
+1.065 0.914 1.458 1.087 1.969 1.087 c
+2.469 1.087 2.84 0.926 3.087 0.602 c
+3.34 0.278 3.472 -0.198 3.484 -0.823 c
+3.484 -1.324 l
+1.411 -1.324 l
+1.429 -1.617 1.492 -1.834 1.602 -1.97 c
+1.72 -2.11 1.899 -2.176 2.146 -2.176 c
+2.487 -2.176 2.778 -2.058 3.013 -1.823 c
+3.424 -2.455 l
+3.295 -2.631 3.108 -2.775 2.865 -2.881 c
+2.62 -2.988 2.355 -3.043 2.072 -3.043 c
+1.425 -0.603 m
+2.454 -0.603 l
+2.454 -0.5 l
+2.454 -0.265 2.414 -0.088 2.337 0.029 c
+2.267 0.154 2.138 0.22 1.955 0.22 c
+1.778 0.22 1.646 0.151 1.558 0.014 c
+1.477 -0.115 1.433 -0.32 1.425 -0.603 c
+4.307 -2.97 m
+4.307 0.22 l
+3.821 0.22 l
+3.821 1.014 l
+4.307 1.014 l
+4.307 1.367 l
+4.307 1.807 4.417 2.146 4.644 2.381 c
+4.88 2.624 5.196 2.748 5.6 2.748 c
+5.725 2.748 5.882 2.723 6.071 2.675 c
+6.071 1.851 l
+6 1.87 5.916 1.882 5.82 1.882 c
+5.504 1.882 5.35 1.697 5.35 1.337 c
+5.35 1.014 l
+5.967 1.014 l
+5.967 0.22 l
+5.35 0.22 l
+5.35 -2.97 l
+h
+f
+Q
+q 1 0 0 1 150.7798 379.244 cm
+0 0 m
+0.214 0 0.386 0.062 0.515 0.191 c
+0.65 0.327 0.723 0.518 0.735 0.764 c
+1.352 0.764 l
+1.33 0.382 1.194 0.062 0.941 -0.191 c
+0.684 -0.437 0.371 -0.559 0 -0.559 c
+-0.492 -0.559 -0.867 -0.408 -1.132 -0.103 c
+-1.389 0.21 -1.514 0.676 -1.514 1.294 c
+-1.514 1.735 l
+-1.514 2.329 -1.389 2.786 -1.132 3.102 c
+-0.867 3.414 -0.492 3.572 0 3.572 c
+0.401 3.572 0.721 3.439 0.956 3.175 c
+1.198 2.917 1.33 2.572 1.352 2.132 c
+0.735 2.132 l
+0.713 2.425 0.64 2.645 0.515 2.793 c
+0.397 2.94 0.224 3.013 0 3.013 c
+-0.294 3.013 -0.511 2.914 -0.647 2.72 c
+-0.786 2.531 -0.86 2.223 -0.867 1.793 c
+-0.867 1.278 l
+-0.867 0.808 -0.802 0.474 -0.661 0.279 c
+-0.515 0.092 -0.294 0 0 0 c
+4.145 -0.485 m
+4.104 -0.397 4.079 -0.25 4.072 -0.044 c
+3.836 -0.389 3.543 -0.559 3.19 -0.559 c
+2.826 -0.559 2.543 -0.463 2.337 -0.264 c
+2.138 -0.059 2.043 0.228 2.043 0.603 c
+2.043 1.003 2.179 1.323 2.454 1.558 c
+2.726 1.801 3.102 1.926 3.572 1.926 c
+4.056 1.926 l
+4.056 2.352 l
+4.056 2.587 4.002 2.753 3.896 2.851 c
+3.785 2.958 3.623 3.013 3.41 3.013 c
+3.212 3.013 3.05 2.955 2.925 2.837 c
+2.807 2.72 2.749 2.572 2.749 2.396 c
+2.102 2.396 l
+2.102 2.591 2.161 2.782 2.278 2.969 c
+2.404 3.152 2.565 3.3 2.763 3.41 c
+2.969 3.516 3.197 3.572 3.454 3.572 c
+3.855 3.572 4.16 3.468 4.366 3.263 c
+4.579 3.057 4.692 2.763 4.704 2.381 c
+4.704 0.368 l
+4.704 0.062 4.74 -0.202 4.821 -0.426 c
+4.821 -0.485 l
+h
+3.278 0.029 m
+3.443 0.029 3.594 0.073 3.734 0.162 c
+3.881 0.25 3.987 0.36 4.056 0.5 c
+4.056 1.44 l
+3.69 1.44 l
+3.373 1.44 3.131 1.371 2.955 1.234 c
+2.778 1.106 2.69 0.918 2.69 0.676 c
+2.69 0.448 2.734 0.283 2.822 0.176 c
+2.911 0.077 3.061 0.029 3.278 0.029 c
+6.321 3.499 m
+6.335 3.057 l
+6.589 3.399 6.913 3.572 7.306 3.572 c
+8.011 3.572 8.367 3.102 8.378 2.161 c
+8.378 -0.485 l
+7.732 -0.485 l
+7.732 2.132 l
+7.732 2.444 7.676 2.664 7.57 2.793 c
+7.46 2.917 7.306 2.984 7.1 2.984 c
+6.942 2.984 6.795 2.928 6.659 2.822 c
+6.53 2.712 6.427 2.576 6.35 2.41 c
+6.35 -0.485 l
+5.703 -0.485 l
+5.703 3.499 l
+h
+13.949 1.309 m
+13.949 0.69 13.835 0.224 13.612 -0.088 c
+13.394 -0.405 13.071 -0.559 12.641 -0.559 c
+12.218 -0.559 11.906 -0.378 11.7 -0.015 c
+11.671 -0.485 l
+11.069 -0.485 l
+11.069 5.159 l
+11.715 5.159 l
+11.715 3.057 l
+11.929 3.399 12.237 3.572 12.641 3.572 c
+13.071 3.572 13.394 3.414 13.612 3.102 c
+13.835 2.797 13.949 2.329 13.949 1.705 c
+h
+13.303 1.69 m
+13.303 2.161 13.232 2.491 13.097 2.69 c
+12.968 2.884 12.758 2.984 12.465 2.984 c
+12.13 2.984 11.881 2.8 11.715 2.44 c
+11.715 0.559 l
+11.881 0.195 12.134 0.015 12.48 0.015 c
+12.773 0.015 12.983 0.118 13.111 0.324 c
+13.236 0.529 13.303 0.845 13.303 1.278 c
+h
+16.213 -0.559 m
+15.713 -0.559 15.331 -0.412 15.067 -0.118 c
+14.802 0.176 14.67 0.61 14.67 1.191 c
+14.67 1.661 l
+14.67 2.256 14.795 2.722 15.052 3.057 c
+15.316 3.399 15.676 3.572 16.139 3.572 c
+16.598 3.572 16.941 3.418 17.168 3.116 c
+17.404 2.822 17.525 2.359 17.536 1.735 c
+17.536 1.309 l
+15.316 1.309 l
+15.316 1.22 l
+15.316 0.786 15.393 0.474 15.551 0.279 c
+15.717 0.092 15.948 0 16.243 0 c
+16.438 0 16.61 0.033 16.756 0.103 c
+16.904 0.18 17.04 0.297 17.168 0.455 c
+17.506 0.044 l
+17.22 -0.36 16.79 -0.559 16.213 -0.559 c
+16.139 3.013 m
+15.864 3.013 15.661 2.917 15.537 2.734 c
+15.408 2.547 15.335 2.256 15.316 1.866 c
+16.889 1.866 l
+16.889 1.955 l
+16.867 2.337 16.801 2.605 16.683 2.763 c
+16.565 2.928 16.382 3.013 16.139 3.013 c
+21.46 -0.559 m
+20.961 -0.559 20.579 -0.412 20.314 -0.118 c
+20.049 0.176 19.917 0.61 19.917 1.191 c
+19.917 1.661 l
+19.917 2.256 20.042 2.722 20.299 3.057 c
+20.564 3.399 20.924 3.572 21.387 3.572 c
+21.847 3.572 22.188 3.418 22.416 3.116 c
+22.651 2.822 22.772 2.359 22.784 1.735 c
+22.784 1.309 l
+20.564 1.309 l
+20.564 1.22 l
+20.564 0.786 20.641 0.474 20.799 0.279 c
+20.964 0.092 21.196 0 21.49 0 c
+21.685 0 21.857 0.033 22.005 0.103 c
+22.152 0.18 22.287 0.297 22.416 0.455 c
+22.754 0.044 l
+22.468 -0.36 22.038 -0.559 21.46 -0.559 c
+21.387 3.013 m
+21.111 3.013 20.91 2.917 20.785 2.734 c
+20.656 2.547 20.582 2.256 20.564 1.866 c
+22.137 1.866 l
+22.137 1.955 l
+22.115 2.337 22.048 2.605 21.931 2.763 c
+21.813 2.928 21.629 3.013 21.387 3.013 c
+23.607 -0.133 m
+23.607 -0.015 23.64 0.081 23.709 0.162 c
+23.775 0.239 23.879 0.279 24.018 0.279 c
+24.165 0.279 24.272 0.239 24.342 0.162 c
+24.419 0.081 24.459 -0.015 24.459 -0.133 c
+24.459 -0.243 24.419 -0.335 24.342 -0.412 c
+24.272 -0.489 24.165 -0.53 24.018 -0.53 c
+23.879 -0.53 23.775 -0.489 23.709 -0.412 c
+23.64 -0.335 23.607 -0.243 23.607 -0.133 c
+25.415 1.69 m
+25.415 2.308 25.525 2.77 25.753 3.087 c
+25.977 3.41 26.312 3.572 26.752 3.572 c
+27.153 3.572 27.457 3.395 27.663 3.042 c
+27.708 3.499 l
+28.296 3.499 l
+28.296 -0.53 l
+28.296 -1.018 28.167 -1.396 27.914 -1.661 c
+27.656 -1.926 27.303 -2.058 26.855 -2.058 c
+26.657 -2.058 26.436 -2.007 26.194 -1.911 c
+25.947 -1.812 25.768 -1.691 25.65 -1.544 c
+25.915 -1.103 l
+26.179 -1.367 26.476 -1.5 26.811 -1.5 c
+27.347 -1.5 27.623 -1.205 27.634 -0.617 c
+27.634 -0.088 l
+27.428 -0.405 27.127 -0.559 26.738 -0.559 c
+26.326 -0.559 26.003 -0.408 25.768 -0.103 c
+25.539 0.21 25.422 0.661 25.415 1.249 c
+h
+26.076 1.309 m
+26.076 0.867 26.138 0.536 26.267 0.324 c
+26.392 0.118 26.609 0.015 26.914 0.015 c
+27.237 0.015 27.476 0.18 27.634 0.515 c
+27.634 2.499 l
+27.465 2.822 27.226 2.984 26.914 2.984 c
+26.62 2.984 26.403 2.881 26.267 2.675 c
+26.138 2.469 26.076 2.146 26.076 1.705 c
+h
+29.296 -0.133 m
+29.296 -0.015 29.328 0.081 29.398 0.162 c
+29.464 0.239 29.567 0.279 29.707 0.279 c
+29.853 0.279 29.961 0.239 30.03 0.162 c
+30.107 0.081 30.148 -0.015 30.148 -0.133 c
+30.148 -0.243 30.107 -0.335 30.03 -0.412 c
+29.961 -0.489 29.853 -0.53 29.707 -0.53 c
+29.567 -0.53 29.464 -0.489 29.398 -0.412 c
+29.328 -0.335 29.296 -0.243 29.296 -0.133 c
+34.998 -0.485 m
+34.958 -0.397 34.932 -0.25 34.925 -0.044 c
+34.69 -0.389 34.395 -0.559 34.043 -0.559 c
+33.679 -0.559 33.396 -0.463 33.19 -0.264 c
+32.992 -0.059 32.897 0.228 32.897 0.603 c
+32.897 1.003 33.032 1.323 33.308 1.558 c
+33.58 1.801 33.955 1.926 34.425 1.926 c
+34.91 1.926 l
+34.91 2.352 l
+34.91 2.587 34.855 2.753 34.748 2.851 c
+34.638 2.958 34.476 3.013 34.264 3.013 c
+34.065 3.013 33.903 2.955 33.778 2.837 c
+33.661 2.72 33.602 2.572 33.602 2.396 c
+32.955 2.396 l
+32.955 2.591 33.014 2.782 33.132 2.969 c
+33.256 3.152 33.418 3.3 33.616 3.41 c
+33.822 3.516 34.05 3.572 34.308 3.572 c
+34.708 3.572 35.013 3.468 35.218 3.263 c
+35.432 3.057 35.546 2.763 35.557 2.381 c
+35.557 0.368 l
+35.557 0.062 35.594 -0.202 35.675 -0.426 c
+35.675 -0.485 l
+h
+34.131 0.029 m
+34.297 0.029 34.447 0.073 34.587 0.162 c
+34.734 0.25 34.84 0.36 34.91 0.5 c
+34.91 1.44 l
+34.543 1.44 l
+34.227 1.44 33.984 1.371 33.807 1.234 c
+33.631 1.106 33.543 0.918 33.543 0.676 c
+33.543 0.448 33.587 0.283 33.676 0.176 c
+33.764 0.077 33.915 0.029 34.131 0.029 c
+41.157 1.309 m
+41.157 0.69 41.044 0.224 40.82 -0.088 c
+40.602 -0.405 40.279 -0.559 39.849 -0.559 c
+39.426 -0.559 39.114 -0.378 38.908 -0.015 c
+38.879 -0.485 l
+38.276 -0.485 l
+38.276 5.159 l
+38.923 5.159 l
+38.923 3.057 l
+39.136 3.399 39.445 3.572 39.849 3.572 c
+40.279 3.572 40.602 3.414 40.82 3.102 c
+41.044 2.797 41.157 2.329 41.157 1.705 c
+h
+40.51 1.69 m
+40.51 2.161 40.441 2.491 40.305 2.69 c
+40.176 2.884 39.966 2.984 39.673 2.984 c
+39.338 2.984 39.089 2.8 38.923 2.44 c
+38.923 0.559 l
+39.089 0.195 39.342 0.015 39.687 0.015 c
+39.981 0.015 40.191 0.118 40.319 0.324 c
+40.444 0.529 40.51 0.845 40.51 1.278 c
+h
+43.642 2.881 m
+43.553 2.899 43.454 2.911 43.347 2.911 c
+43.013 2.911 42.778 2.726 42.642 2.367 c
+42.642 -0.485 l
+41.996 -0.485 l
+41.996 3.499 l
+42.627 3.499 l
+42.642 3.087 l
+42.819 3.41 43.06 3.572 43.377 3.572 c
+43.484 3.572 43.571 3.549 43.642 3.513 c
+h
+46.185 -0.485 m
+46.144 -0.397 46.118 -0.25 46.111 -0.044 c
+45.876 -0.389 45.582 -0.559 45.229 -0.559 c
+44.865 -0.559 44.583 -0.463 44.377 -0.264 c
+44.178 -0.059 44.082 0.228 44.082 0.603 c
+44.082 1.003 44.219 1.323 44.494 1.558 c
+44.766 1.801 45.14 1.926 45.611 1.926 c
+46.096 1.926 l
+46.096 2.352 l
+46.096 2.587 46.041 2.753 45.934 2.851 c
+45.824 2.958 45.663 3.013 45.449 3.013 c
+45.251 3.013 45.09 2.955 44.965 2.837 c
+44.847 2.72 44.788 2.572 44.788 2.396 c
+44.141 2.396 l
+44.141 2.591 44.2 2.782 44.317 2.969 c
+44.442 3.152 44.604 3.3 44.803 3.41 c
+45.009 3.516 45.236 3.572 45.493 3.572 c
+45.894 3.572 46.199 3.468 46.405 3.263 c
+46.618 3.057 46.732 2.763 46.743 2.381 c
+46.743 0.368 l
+46.743 0.062 46.78 -0.202 46.86 -0.426 c
+46.86 -0.485 l
+h
+45.317 0.029 m
+45.483 0.029 45.633 0.073 45.773 0.162 c
+45.919 0.25 46.027 0.36 46.096 0.5 c
+46.096 1.44 l
+45.728 1.44 l
+45.412 1.44 45.171 1.371 44.994 1.234 c
+44.818 1.106 44.729 0.918 44.729 0.676 c
+44.729 0.448 44.774 0.283 44.861 0.176 c
+44.949 0.077 45.1 0.029 45.317 0.029 c
+48.36 3.499 m
+48.375 3.057 l
+48.628 3.399 48.951 3.572 49.345 3.572 c
+50.05 3.572 50.407 3.102 50.418 2.161 c
+50.418 -0.485 l
+49.771 -0.485 l
+49.771 2.132 l
+49.771 2.444 49.716 2.664 49.609 2.793 c
+49.499 2.917 49.345 2.984 49.139 2.984 c
+48.981 2.984 48.834 2.928 48.698 2.822 c
+48.569 2.712 48.466 2.576 48.389 2.41 c
+48.389 -0.485 l
+47.743 -0.485 l
+47.743 3.499 l
+h
+52.77 0 m
+52.982 0 53.156 0.062 53.284 0.191 c
+53.42 0.327 53.493 0.518 53.505 0.764 c
+54.122 0.764 l
+54.1 0.382 53.964 0.062 53.711 -0.191 c
+53.453 -0.437 53.14 -0.559 52.77 -0.559 c
+52.277 -0.559 51.902 -0.408 51.638 -0.103 c
+51.38 0.21 51.255 0.676 51.255 1.294 c
+51.255 1.735 l
+51.255 2.329 51.38 2.786 51.638 3.102 c
+51.902 3.414 52.277 3.572 52.77 3.572 c
+53.17 3.572 53.49 3.439 53.725 3.175 c
+53.967 2.917 54.1 2.572 54.122 2.132 c
+53.505 2.132 l
+53.482 2.425 53.409 2.645 53.284 2.793 c
+53.167 2.94 52.994 3.013 52.77 3.013 c
+52.475 3.013 52.259 2.914 52.123 2.72 c
+51.983 2.531 51.91 2.223 51.902 1.793 c
+51.902 1.278 l
+51.902 0.808 51.968 0.474 52.109 0.279 c
+52.255 0.092 52.475 0 52.77 0 c
+55.519 3.087 m
+55.772 3.41 56.092 3.572 56.474 3.572 c
+57.179 3.572 57.536 3.102 57.547 2.161 c
+57.547 -0.485 l
+56.9 -0.485 l
+56.9 2.132 l
+56.9 2.444 56.845 2.664 56.738 2.793 c
+56.628 2.917 56.474 2.984 56.268 2.984 c
+56.109 2.984 55.963 2.928 55.827 2.822 c
+55.698 2.712 55.596 2.576 55.519 2.41 c
+55.519 -0.485 l
+54.871 -0.485 l
+54.871 5.159 l
+55.519 5.159 l
+h
+60.839 3.499 m
+60.854 3.057 l
+61.108 3.399 61.431 3.572 61.824 3.572 c
+62.53 3.572 62.887 3.102 62.897 2.161 c
+62.897 -0.485 l
+62.251 -0.485 l
+62.251 2.132 l
+62.251 2.444 62.195 2.664 62.089 2.793 c
+61.979 2.917 61.824 2.984 61.618 2.984 c
+61.46 2.984 61.314 2.928 61.177 2.822 c
+61.048 2.712 60.946 2.576 60.869 2.41 c
+60.869 -0.485 l
+60.222 -0.485 l
+60.222 3.499 l
+h
+65.91 -0.485 m
+65.87 -0.397 65.844 -0.25 65.837 -0.044 c
+65.602 -0.389 65.308 -0.559 64.955 -0.559 c
+64.591 -0.559 64.308 -0.463 64.103 -0.264 c
+63.904 -0.059 63.808 0.228 63.808 0.603 c
+63.808 1.003 63.945 1.323 64.221 1.558 c
+64.492 1.801 64.867 1.926 65.337 1.926 c
+65.823 1.926 l
+65.823 2.352 l
+65.823 2.587 65.767 2.753 65.661 2.851 c
+65.551 2.958 65.389 3.013 65.175 3.013 c
+64.977 3.013 64.815 2.955 64.691 2.837 c
+64.573 2.72 64.514 2.572 64.514 2.396 c
+63.868 2.396 l
+63.868 2.591 63.926 2.782 64.044 2.969 c
+64.169 3.152 64.331 3.3 64.529 3.41 c
+64.734 3.516 64.963 3.572 65.22 3.572 c
+65.62 3.572 65.925 3.468 66.131 3.263 c
+66.344 3.057 66.458 2.763 66.469 2.381 c
+66.469 0.368 l
+66.469 0.062 66.506 -0.202 66.586 -0.426 c
+66.586 -0.485 l
+h
+65.044 0.029 m
+65.208 0.029 65.36 0.073 65.499 0.162 c
+65.646 0.25 65.752 0.36 65.823 0.5 c
+65.823 1.44 l
+65.455 1.44 l
+65.139 1.44 64.896 1.371 64.72 1.234 c
+64.543 1.106 64.456 0.918 64.456 0.676 c
+64.456 0.448 64.499 0.283 64.587 0.176 c
+64.676 0.077 64.826 0.029 65.044 0.029 c
+68.086 3.499 m
+68.101 3.131 l
+68.343 3.425 68.663 3.572 69.056 3.572 c
+69.497 3.572 69.806 3.373 69.983 2.984 c
+70.236 3.373 70.585 3.572 71.026 3.572 c
+71.761 3.572 72.136 3.109 72.158 2.19 c
+72.158 -0.485 l
+71.511 -0.485 l
+71.511 2.132 l
+71.511 2.425 71.456 2.639 71.349 2.778 c
+71.25 2.914 71.078 2.984 70.835 2.984 c
+70.636 2.984 70.475 2.903 70.349 2.749 c
+70.232 2.602 70.162 2.41 70.143 2.175 c
+70.143 -0.485 l
+69.482 -0.485 l
+69.482 2.161 l
+69.482 2.708 69.262 2.984 68.821 2.984 c
+68.487 2.984 68.252 2.822 68.115 2.499 c
+68.115 -0.485 l
+67.469 -0.485 l
+67.469 3.499 l
+h
+74.554 -0.559 m
+74.054 -0.559 73.671 -0.412 73.407 -0.118 c
+73.142 0.176 73.01 0.61 73.01 1.191 c
+73.01 1.661 l
+73.01 2.256 73.135 2.722 73.393 3.057 c
+73.657 3.399 74.017 3.572 74.48 3.572 c
+74.939 3.572 75.281 3.418 75.509 3.116 c
+75.745 2.822 75.865 2.359 75.876 1.735 c
+75.876 1.309 l
+73.657 1.309 l
+73.657 1.22 l
+73.657 0.786 73.734 0.474 73.892 0.279 c
+74.058 0.092 74.289 0 74.583 0 c
+74.777 0 74.951 0.033 75.097 0.103 c
+75.244 0.18 75.381 0.297 75.509 0.455 c
+75.847 0.044 l
+75.56 -0.36 75.13 -0.559 74.554 -0.559 c
+74.48 3.013 m
+74.205 3.013 74.002 2.917 73.877 2.734 c
+73.748 2.547 73.675 2.256 73.657 1.866 c
+75.23 1.866 l
+75.23 1.955 l
+75.207 2.337 75.142 2.605 75.024 2.763 c
+74.906 2.928 74.723 3.013 74.48 3.013 c
+78.243 1.69 m
+78.243 2.267 78.379 2.722 78.654 3.057 c
+78.937 3.399 79.309 3.572 79.772 3.572 c
+80.231 3.572 80.599 3.403 80.874 3.072 c
+81.157 2.749 81.304 2.3 81.315 1.735 c
+81.315 1.309 l
+81.315 0.738 81.172 0.283 80.889 -0.059 c
+80.613 -0.393 80.246 -0.559 79.786 -0.559 c
+79.323 -0.559 78.952 -0.397 78.669 -0.073 c
+78.394 0.257 78.251 0.698 78.243 1.249 c
+h
+78.889 1.309 m
+78.889 0.904 78.967 0.588 79.125 0.353 c
+79.29 0.118 79.51 0 79.786 0 c
+80.352 0 80.647 0.411 80.668 1.234 c
+80.668 1.69 l
+80.668 2.091 80.584 2.41 80.418 2.645 c
+80.26 2.888 80.044 3.013 79.772 3.013 c
+79.508 3.013 79.29 2.888 79.125 2.645 c
+78.967 2.41 78.889 2.091 78.889 1.69 c
+h
+83.799 2.881 m
+83.711 2.899 83.612 2.911 83.506 2.911 c
+83.171 2.911 82.936 2.726 82.8 2.367 c
+82.8 -0.485 l
+82.153 -0.485 l
+82.153 3.499 l
+82.785 3.499 l
+82.8 3.087 l
+82.976 3.41 83.219 3.572 83.535 3.572 c
+83.641 3.572 83.73 3.549 83.799 3.513 c
+h
+88.209 -0.485 m
+88.169 -0.397 88.143 -0.25 88.135 -0.044 c
+87.9 -0.389 87.606 -0.559 87.254 -0.559 c
+86.89 -0.559 86.606 -0.463 86.401 -0.264 c
+86.203 -0.059 86.107 0.228 86.107 0.603 c
+86.107 1.003 86.243 1.323 86.519 1.558 c
+86.791 1.801 87.165 1.926 87.636 1.926 c
+88.121 1.926 l
+88.121 2.352 l
+88.121 2.587 88.065 2.753 87.959 2.851 c
+87.849 2.958 87.687 3.013 87.474 3.013 c
+87.275 3.013 87.113 2.955 86.989 2.837 c
+86.872 2.72 86.812 2.572 86.812 2.396 c
+86.166 2.396 l
+86.166 2.591 86.224 2.782 86.342 2.969 c
+86.467 3.152 86.629 3.3 86.827 3.41 c
+87.033 3.516 87.261 3.572 87.518 3.572 c
+87.919 3.572 88.223 3.468 88.43 3.263 c
+88.643 3.057 88.757 2.763 88.767 2.381 c
+88.767 0.368 l
+88.767 0.062 88.804 -0.202 88.885 -0.426 c
+88.885 -0.485 l
+h
+87.342 0.029 m
+87.507 0.029 87.658 0.073 87.797 0.162 c
+87.944 0.25 88.051 0.36 88.121 0.5 c
+88.121 1.44 l
+87.753 1.44 l
+87.437 1.44 87.194 1.371 87.018 1.234 c
+86.842 1.106 86.754 0.918 86.754 0.676 c
+86.754 0.448 86.798 0.283 86.886 0.176 c
+86.974 0.077 87.125 0.029 87.342 0.029 c
+92.339 4.453 m
+92.339 3.499 l
+92.942 3.499 l
+92.942 2.969 l
+92.339 2.969 l
+92.339 0.5 l
+92.339 0.341 92.362 0.224 92.413 0.147 c
+92.472 0.066 92.56 0.029 92.678 0.029 c
+92.765 0.029 92.854 0.044 92.942 0.073 c
+92.942 -0.485 l
+92.795 -0.532 92.641 -0.559 92.486 -0.559 c
+92.229 -0.559 92.034 -0.467 91.898 -0.279 c
+91.759 -0.096 91.693 0.166 91.693 0.5 c
+91.693 2.969 l
+91.09 2.969 l
+91.09 3.499 l
+91.693 3.499 l
+91.693 4.453 l
+h
+95.749 -0.485 m
+95.709 -0.397 95.684 -0.25 95.676 -0.044 c
+95.441 -0.389 95.147 -0.559 94.795 -0.559 c
+94.43 -0.559 94.147 -0.463 93.941 -0.264 c
+93.743 -0.059 93.648 0.228 93.648 0.603 c
+93.648 1.003 93.783 1.323 94.059 1.558 c
+94.331 1.801 94.706 1.926 95.176 1.926 c
+95.661 1.926 l
+95.661 2.352 l
+95.661 2.587 95.606 2.753 95.5 2.851 c
+95.389 2.958 95.228 3.013 95.015 3.013 c
+94.816 3.013 94.654 2.955 94.529 2.837 c
+94.412 2.72 94.353 2.572 94.353 2.396 c
+93.706 2.396 l
+93.706 2.591 93.765 2.782 93.883 2.969 c
+94.008 3.152 94.169 3.3 94.367 3.41 c
+94.573 3.516 94.801 3.572 95.059 3.572 c
+95.46 3.572 95.764 3.468 95.97 3.263 c
+96.183 3.057 96.297 2.763 96.308 2.381 c
+96.308 0.368 l
+96.308 0.062 96.345 -0.202 96.426 -0.426 c
+96.426 -0.485 l
+h
+94.882 0.029 m
+95.048 0.029 95.198 0.073 95.338 0.162 c
+95.485 0.25 95.591 0.36 95.661 0.5 c
+95.661 1.44 l
+95.294 1.44 l
+94.978 1.44 94.735 1.371 94.559 1.234 c
+94.383 1.106 94.294 0.918 94.294 0.676 c
+94.294 0.448 94.338 0.283 94.427 0.176 c
+94.515 0.077 94.666 0.029 94.882 0.029 c
+97.176 1.69 m
+97.176 2.308 97.286 2.77 97.513 3.087 c
+97.737 3.41 98.072 3.572 98.513 3.572 c
+98.913 3.572 99.219 3.395 99.424 3.042 c
+99.468 3.499 l
+100.056 3.499 l
+100.056 -0.53 l
+100.056 -1.018 99.928 -1.396 99.674 -1.661 c
+99.417 -1.926 99.065 -2.058 98.616 -2.058 c
+98.417 -2.058 98.197 -2.007 97.954 -1.911 c
+97.708 -1.812 97.528 -1.691 97.411 -1.544 c
+97.675 -1.103 l
+97.939 -1.367 98.238 -1.5 98.572 -1.5 c
+99.108 -1.5 99.383 -1.205 99.395 -0.617 c
+99.395 -0.088 l
+99.189 -0.405 98.888 -0.559 98.498 -0.559 c
+98.087 -0.559 97.764 -0.408 97.528 -0.103 c
+97.301 0.21 97.183 0.661 97.176 1.249 c
+h
+97.837 1.309 m
+97.837 0.867 97.899 0.536 98.028 0.324 c
+98.153 0.118 98.369 0.015 98.675 0.015 c
+98.998 0.015 99.237 0.18 99.395 0.515 c
+99.395 2.499 l
+99.226 2.822 98.987 2.984 98.675 2.984 c
+98.381 2.984 98.164 2.881 98.028 2.675 c
+97.899 2.469 97.837 2.146 97.837 1.705 c
+h
+103.349 3.499 m
+103.364 3.057 l
+103.617 3.399 103.94 3.572 104.334 3.572 c
+105.039 3.572 105.396 3.102 105.407 2.161 c
+105.407 -0.485 l
+104.76 -0.485 l
+104.76 2.132 l
+104.76 2.444 104.705 2.664 104.598 2.793 c
+104.488 2.917 104.334 2.984 104.128 2.984 c
+103.97 2.984 103.823 2.928 103.687 2.822 c
+103.558 2.712 103.456 2.576 103.379 2.41 c
+103.379 -0.485 l
+102.732 -0.485 l
+102.732 3.499 l
+h
+108.42 -0.485 m
+108.38 -0.397 108.354 -0.25 108.347 -0.044 c
+108.112 -0.389 107.817 -0.559 107.464 -0.559 c
+107.101 -0.559 106.818 -0.463 106.612 -0.264 c
+106.414 -0.059 106.319 0.228 106.319 0.603 c
+106.319 1.003 106.454 1.323 106.73 1.558 c
+107.002 1.801 107.377 1.926 107.847 1.926 c
+108.332 1.926 l
+108.332 2.352 l
+108.332 2.587 108.277 2.753 108.17 2.851 c
+108.06 2.958 107.898 3.013 107.686 3.013 c
+107.487 3.013 107.325 2.955 107.2 2.837 c
+107.082 2.72 107.024 2.572 107.024 2.396 c
+106.377 2.396 l
+106.377 2.591 106.436 2.782 106.554 2.969 c
+106.678 3.152 106.84 3.3 107.038 3.41 c
+107.244 3.516 107.472 3.572 107.73 3.572 c
+108.13 3.572 108.435 3.468 108.64 3.263 c
+108.854 3.057 108.968 2.763 108.979 2.381 c
+108.979 0.368 l
+108.979 0.062 109.016 -0.202 109.097 -0.426 c
+109.097 -0.485 l
+h
+107.553 0.029 m
+107.718 0.029 107.869 0.073 108.008 0.162 c
+108.156 0.25 108.262 0.36 108.332 0.5 c
+108.332 1.44 l
+107.965 1.44 l
+107.649 1.44 107.406 1.371 107.229 1.234 c
+107.053 1.106 106.965 0.918 106.965 0.676 c
+106.965 0.448 107.009 0.283 107.098 0.176 c
+107.185 0.077 107.336 0.029 107.553 0.029 c
+110.595 3.499 m
+110.61 3.131 l
+110.853 3.425 111.173 3.572 111.566 3.572 c
+112.006 3.572 112.316 3.373 112.492 2.984 c
+112.746 3.373 113.095 3.572 113.535 3.572 c
+114.271 3.572 114.645 3.109 114.668 2.19 c
+114.668 -0.485 l
+114.02 -0.485 l
+114.02 2.132 l
+114.02 2.425 113.965 2.639 113.859 2.778 c
+113.76 2.914 113.587 2.984 113.344 2.984 c
+113.146 2.984 112.984 2.903 112.86 2.749 c
+112.742 2.602 112.671 2.41 112.654 2.175 c
+112.654 -0.485 l
+111.992 -0.485 l
+111.992 2.161 l
+111.992 2.708 111.771 2.984 111.331 2.984 c
+110.996 2.984 110.761 2.822 110.625 2.499 c
+110.625 -0.485 l
+109.978 -0.485 l
+109.978 3.499 l
+h
+117.063 -0.559 m
+116.563 -0.559 116.181 -0.412 115.917 -0.118 c
+115.652 0.176 115.52 0.61 115.52 1.191 c
+115.52 1.661 l
+115.52 2.256 115.645 2.722 115.902 3.057 c
+116.166 3.399 116.527 3.572 116.989 3.572 c
+117.449 3.572 117.791 3.418 118.019 3.116 c
+118.254 2.822 118.375 2.359 118.386 1.735 c
+118.386 1.309 l
+116.166 1.309 l
+116.166 1.22 l
+116.166 0.786 116.243 0.474 116.401 0.279 c
+116.567 0.092 116.798 0 117.093 0 c
+117.288 0 117.46 0.033 117.607 0.103 c
+117.754 0.18 117.89 0.297 118.019 0.455 c
+118.356 0.044 l
+118.07 -0.36 117.64 -0.559 117.063 -0.559 c
+116.989 3.013 m
+116.714 3.013 116.512 2.917 116.387 2.734 c
+116.258 2.547 116.185 2.256 116.166 1.866 c
+117.739 1.866 l
+117.739 1.955 l
+117.718 2.337 117.651 2.605 117.533 2.763 c
+117.416 2.928 117.232 3.013 116.989 3.013 c
+119.21 -0.133 m
+119.21 -0.015 119.242 0.081 119.312 0.162 c
+119.378 0.239 119.481 0.279 119.621 0.279 c
+119.767 0.279 119.875 0.239 119.944 0.162 c
+120.021 0.081 120.062 -0.015 120.062 -0.133 c
+120.062 -0.243 120.021 -0.335 119.944 -0.412 c
+119.875 -0.489 119.767 -0.53 119.621 -0.53 c
+119.481 -0.53 119.378 -0.489 119.312 -0.412 c
+119.242 -0.335 119.21 -0.243 119.21 -0.133 c
+f
+Q
+0.113 0.082 0.09 0 k
+35.668 373.53 238.665 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 40.8563 366.6908 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.882 c
+-0.496 -0.993 -0.658 -1.08 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.771 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.279 -3.219 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.985 c
+-3.322 2.18 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.003 -2.469 3.043 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.182 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.455 c
+-2.26 2.425 -2.319 2.385 -2.366 2.338 c
+-2.406 2.297 -2.437 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.44 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.014 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.147 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.596 4.935 -0.411 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.632 5.137 1.779 c
+5.245 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.152 2.22 c
+8.004 2.22 l
+7.993 2.139 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.871 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.279 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.279 5.835 1.162 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.22 l
+13.644 2.22 l
+13.924 3.117 l
+14.497 3.117 l
+14.497 2.22 l
+15.732 2.22 l
+15.732 1.602 l
+14.497 1.602 l
+14.497 -0.103 l
+14.497 -0.324 l
+14.504 -0.393 14.527 -0.455 14.556 -0.515 c
+14.593 -0.565 14.648 -0.61 14.718 -0.646 c
+14.795 -0.676 14.909 -0.691 15.056 -0.691 c
+15.192 -0.691 15.327 -0.687 15.468 -0.676 c
+15.603 -0.658 15.736 -0.632 15.865 -0.602 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.23 15.629 -1.249 c
+15.549 -1.261 15.471 -1.267 15.394 -1.278 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.041 -1.301 14.942 -1.308 14.835 -1.308 c
+14.648 -1.308 14.486 -1.294 14.35 -1.264 c
+14.221 -1.228 14.107 -1.183 14.012 -1.132 c
+13.924 -1.084 13.85 -1.025 13.791 -0.955 c
+13.733 -0.878 13.689 -0.801 13.66 -0.72 c
+13.63 -0.632 13.608 -0.544 13.6 -0.455 c
+13.59 -0.36 13.586 -0.264 13.586 -0.176 c
+h
+23.221 -0.646 m
+24.353 -0.646 l
+24.353 -1.264 l
+21.045 -1.264 l
+21.045 -0.646 l
+22.31 -0.646 l
+22.31 2.896 l
+21.384 2.896 l
+21.384 3.514 l
+23.221 3.514 l
+h
+28.384 0.485 m
+28.384 0.21 28.347 -0.04 28.281 -0.264 c
+28.212 -0.482 28.108 -0.669 27.973 -0.823 c
+27.833 -0.981 27.657 -1.103 27.443 -1.19 c
+27.227 -1.278 26.973 -1.323 26.679 -1.323 c
+26.404 -1.323 26.157 -1.278 25.944 -1.19 c
+25.739 -1.103 25.566 -0.981 25.43 -0.823 c
+25.29 -0.669 25.187 -0.482 25.121 -0.264 c
+25.051 -0.04 25.018 0.21 25.018 0.485 c
+25.018 0.738 25.047 0.974 25.106 1.191 c
+25.172 1.415 25.275 1.606 25.415 1.764 c
+25.55 1.929 25.727 2.058 25.944 2.146 c
+26.157 2.234 26.414 2.278 26.709 2.278 c
+27.021 2.278 27.281 2.234 27.487 2.146 c
+27.701 2.058 27.873 1.929 28.002 1.764 c
+28.138 1.606 28.237 1.415 28.296 1.191 c
+28.355 0.974 28.384 0.738 28.384 0.485 c
+27.429 0.485 m
+27.429 0.691 27.414 0.867 27.385 1.014 c
+27.362 1.162 27.326 1.282 27.267 1.382 c
+27.208 1.477 27.135 1.547 27.046 1.588 c
+26.959 1.635 26.848 1.661 26.724 1.661 c
+26.458 1.661 26.267 1.562 26.15 1.367 c
+26.032 1.18 25.974 0.886 25.974 0.485 c
+25.974 0.063 26.032 -0.243 26.15 -0.426 c
+26.267 -0.613 26.444 -0.706 26.679 -0.706 c
+26.804 -0.706 26.918 -0.687 27.017 -0.646 c
+27.113 -0.599 27.194 -0.525 27.252 -0.426 c
+27.318 -0.33 27.362 -0.206 27.385 -0.058 c
+27.414 0.088 27.429 0.268 27.429 0.485 c
+30.769 -2.66 m
+30.552 -2.66 30.361 -2.635 30.196 -2.587 c
+30.027 -2.547 29.887 -2.484 29.77 -2.396 c
+29.652 -2.315 29.552 -2.219 29.475 -2.102 c
+29.406 -1.984 29.358 -1.855 29.328 -1.72 c
+30.225 -1.617 l
+30.262 -1.753 30.331 -1.859 30.431 -1.94 c
+30.526 -2.028 30.651 -2.072 30.799 -2.072 c
+30.886 -2.072 30.967 -2.057 31.048 -2.028 c
+31.125 -1.999 31.195 -1.944 31.254 -1.866 c
+31.313 -1.797 31.357 -1.705 31.387 -1.587 c
+31.424 -1.469 31.445 -1.323 31.445 -1.147 c
+31.445 -0.955 l
+31.445 -0.889 31.449 -0.831 31.46 -0.779 c
+31.46 -0.588 l
+31.445 -0.588 l
+31.346 -0.816 31.202 -0.977 31.019 -1.072 c
+30.832 -1.172 30.626 -1.22 30.402 -1.22 c
+30.196 -1.22 30.012 -1.183 29.858 -1.103 c
+29.71 -1.014 29.582 -0.897 29.475 -0.75 c
+29.376 -0.596 29.303 -0.411 29.255 -0.206 c
+29.203 0.008 29.182 0.243 29.182 0.5 c
+29.182 0.771 29.203 1.018 29.255 1.235 c
+29.313 1.448 29.394 1.632 29.505 1.779 c
+29.612 1.933 29.743 2.051 29.901 2.132 c
+30.056 2.22 30.244 2.263 30.46 2.263 c
+30.556 2.263 30.655 2.253 30.755 2.234 c
+30.85 2.213 30.938 2.18 31.019 2.132 c
+31.107 2.08 31.185 2.018 31.254 1.941 c
+31.331 1.86 31.393 1.768 31.445 1.661 c
+31.46 1.661 l
+31.46 1.808 l
+31.467 1.867 31.474 1.918 31.474 1.97 c
+31.482 2.028 31.489 2.076 31.489 2.117 c
+31.497 2.165 31.507 2.198 31.519 2.22 c
+32.371 2.22 l
+32.36 2.139 32.349 2.028 32.342 1.881 c
+32.342 1.411 l
+32.342 -1.161 l
+32.342 -1.415 32.305 -1.635 32.239 -1.822 c
+32.17 -2.007 32.066 -2.161 31.931 -2.279 c
+31.79 -2.404 31.625 -2.499 31.43 -2.558 c
+31.232 -2.624 31.011 -2.66 30.769 -2.66 c
+31.46 0.53 m
+31.46 0.742 31.434 0.919 31.387 1.058 c
+31.346 1.205 31.291 1.323 31.225 1.411 c
+31.166 1.5 31.096 1.558 31.019 1.588 c
+30.938 1.625 30.861 1.646 30.784 1.646 c
+30.684 1.646 30.593 1.621 30.504 1.573 c
+30.424 1.532 30.358 1.463 30.298 1.367 c
+30.248 1.279 30.203 1.162 30.167 1.014 c
+30.137 0.875 30.122 0.706 30.122 0.5 c
+30.122 0.125 30.181 -0.154 30.298 -0.338 c
+30.416 -0.515 30.578 -0.602 30.784 -0.602 c
+30.85 -0.602 30.923 -0.588 31.004 -0.559 c
+31.092 -0.522 31.166 -0.463 31.225 -0.382 c
+31.291 -0.294 31.346 -0.176 31.387 -0.029 c
+31.434 0.118 31.46 0.301 31.46 0.53 c
+38.424 -0.279 0.926 -0.985 re
+38.424 -1.264 m
+42.484 -0.279 0.927 -0.985 re
+42.484 -1.264 m
+48.5 1.47 m
+48.4 1.477 48.298 1.488 48.191 1.5 c
+48.081 1.517 47.96 1.529 47.823 1.529 c
+47.648 1.529 47.489 1.488 47.353 1.411 c
+47.214 1.341 47.096 1.242 47 1.118 c
+46.912 0.989 46.842 0.842 46.794 0.676 c
+46.754 0.507 46.736 0.331 46.736 0.147 c
+46.736 -1.264 l
+45.839 -1.264 l
+45.839 0.985 l
+45.839 1.11 45.828 1.235 45.81 1.353 c
+45.799 1.477 45.784 1.595 45.766 1.706 c
+45.755 1.823 45.74 1.918 45.722 1.999 c
+45.699 2.087 45.681 2.161 45.663 2.22 c
+46.545 2.22 l
+46.552 2.168 46.563 2.117 46.574 2.058 c
+46.593 1.999 46.607 1.933 46.618 1.867 c
+46.637 1.808 46.651 1.742 46.663 1.675 c
+46.67 1.606 46.68 1.544 46.692 1.484 c
+46.707 1.484 l
+46.743 1.602 46.794 1.709 46.854 1.808 c
+46.919 1.904 47 1.988 47.089 2.058 c
+47.177 2.124 47.28 2.18 47.397 2.22 c
+47.522 2.257 47.669 2.278 47.838 2.278 c
+47.964 2.278 48.081 2.271 48.191 2.263 c
+48.309 2.253 48.411 2.238 48.5 2.22 c
+h
+51.106 -1.323 m
+50.848 -1.323 50.62 -1.286 50.414 -1.22 c
+50.208 -1.143 50.032 -1.029 49.886 -0.882 c
+49.738 -0.727 49.62 -0.536 49.533 -0.309 c
+49.452 -0.085 49.415 0.181 49.415 0.485 c
+49.415 0.816 49.459 1.095 49.547 1.323 c
+49.643 1.558 49.772 1.742 49.93 1.881 c
+50.094 2.018 50.282 2.117 50.488 2.176 c
+50.694 2.242 50.903 2.278 51.12 2.278 c
+51.392 2.278 51.627 2.227 51.825 2.132 c
+52.031 2.043 52.197 1.911 52.325 1.735 c
+52.461 1.565 52.56 1.359 52.619 1.118 c
+52.685 0.882 52.722 0.617 52.722 0.324 c
+52.722 0.309 l
+50.356 0.309 l
+50.356 0.162 50.37 0.023 50.4 -0.103 c
+50.437 -0.231 50.491 -0.345 50.561 -0.441 c
+50.628 -0.529 50.712 -0.599 50.811 -0.646 c
+50.907 -0.698 51.021 -0.72 51.149 -0.72 c
+51.303 -0.72 51.443 -0.687 51.561 -0.617 c
+51.686 -0.551 51.774 -0.448 51.825 -0.309 c
+52.664 -0.382 l
+52.633 -0.482 52.579 -0.588 52.502 -0.706 c
+52.421 -0.816 52.318 -0.918 52.193 -1.014 c
+52.076 -1.103 51.921 -1.176 51.737 -1.234 c
+51.561 -1.294 51.347 -1.323 51.106 -1.323 c
+51.106 1.706 m
+51.017 1.706 50.929 1.69 50.84 1.661 c
+50.752 1.632 50.672 1.58 50.605 1.515 c
+50.536 1.444 50.477 1.357 50.429 1.249 c
+50.389 1.139 50.37 1.014 50.37 0.867 c
+51.84 0.867 l
+51.84 1.004 51.814 1.124 51.767 1.235 c
+51.727 1.341 51.671 1.43 51.605 1.5 c
+51.546 1.565 51.473 1.617 51.384 1.646 c
+51.297 1.683 51.201 1.706 51.106 1.706 c
+55.258 1.602 m
+55.258 -1.264 l
+54.361 -1.264 l
+54.361 1.602 l
+53.537 1.602 l
+53.537 2.22 l
+54.361 2.22 l
+54.361 2.484 l
+54.361 2.61 54.376 2.741 54.405 2.881 c
+54.442 3.017 54.512 3.135 54.611 3.234 c
+54.717 3.341 54.861 3.429 55.037 3.499 c
+55.214 3.564 55.438 3.601 55.713 3.601 c
+55.926 3.601 56.125 3.591 56.301 3.572 c
+56.477 3.55 56.629 3.532 56.757 3.514 c
+56.757 2.926 l
+56.629 2.944 56.485 2.959 56.331 2.969 c
+56.172 2.976 56.022 2.984 55.875 2.984 c
+55.746 2.984 55.644 2.969 55.567 2.94 c
+55.486 2.911 55.423 2.87 55.376 2.822 c
+55.324 2.77 55.291 2.708 55.272 2.631 c
+55.261 2.562 55.258 2.484 55.258 2.396 c
+55.258 2.22 l
+56.683 2.22 l
+56.683 1.602 l
+h
+f
+Q
+q 1 0 0 1 60.3663 351.1103 cm
+0 0 m
+2.102 0 l
+2.102 -0.574 l
+-0.676 -0.574 l
+-0.676 4.777 l
+0 4.777 l
+h
+3.513 -0.574 -0.647 3.984 re
+3.557 4.453 m
+3.557 4.343 3.528 4.251 3.469 4.174 c
+3.41 4.104 3.314 4.072 3.189 4.072 c
+3.072 4.072 2.977 4.104 2.91 4.174 c
+2.851 4.251 2.822 4.343 2.822 4.453 c
+2.822 4.571 2.851 4.663 2.91 4.733 c
+2.977 4.81 3.072 4.85 3.189 4.85 c
+3.314 4.85 3.41 4.81 3.469 4.733 c
+3.528 4.652 3.557 4.56 3.557 4.453 c
+6.468 0.44 m
+6.468 0.588 6.412 0.709 6.306 0.808 c
+6.196 0.904 5.99 1.022 5.688 1.161 c
+5.342 1.308 5.1 1.429 4.953 1.529 c
+4.806 1.635 4.696 1.753 4.629 1.881 c
+4.56 2.006 4.527 2.164 4.527 2.352 c
+4.527 2.674 4.644 2.944 4.88 3.16 c
+5.115 3.373 5.416 3.484 5.791 3.484 c
+6.173 3.484 6.482 3.37 6.717 3.145 c
+6.952 2.917 7.07 2.631 7.07 2.278 c
+6.423 2.278 l
+6.423 2.454 6.364 2.605 6.247 2.734 c
+6.129 2.859 5.975 2.925 5.791 2.925 c
+5.593 2.925 5.442 2.869 5.335 2.763 c
+5.225 2.664 5.174 2.532 5.174 2.366 c
+5.174 2.238 5.211 2.131 5.292 2.043 c
+5.369 1.962 5.56 1.859 5.865 1.734 c
+6.342 1.547 6.673 1.359 6.85 1.176 c
+7.025 0.999 7.114 0.771 7.114 0.5 c
+7.114 0.147 6.989 -0.133 6.746 -0.339 c
+6.511 -0.544 6.196 -0.647 5.805 -0.647 c
+5.383 -0.647 5.045 -0.53 4.791 -0.294 c
+4.534 -0.052 4.409 0.253 4.409 0.617 c
+5.056 0.617 l
+5.063 0.389 5.134 0.213 5.262 0.087 c
+5.387 -0.03 5.57 -0.088 5.805 -0.088 c
+6.019 -0.088 6.181 -0.04 6.291 0.058 c
+6.408 0.154 6.468 0.282 6.468 0.44 c
+8.804 4.365 m
+8.804 3.41 l
+9.407 3.41 l
+9.407 2.881 l
+8.804 2.881 l
+8.804 0.411 l
+8.804 0.253 8.826 0.135 8.878 0.058 c
+8.937 -0.023 9.025 -0.059 9.142 -0.059 c
+9.231 -0.059 9.319 -0.044 9.407 -0.015 c
+9.407 -0.574 l
+9.26 -0.621 9.105 -0.647 8.951 -0.647 c
+8.694 -0.647 8.5 -0.555 8.363 -0.368 c
+8.224 -0.184 8.157 0.077 8.157 0.411 c
+8.157 2.881 l
+7.555 2.881 l
+7.555 3.41 l
+8.157 3.41 l
+8.157 4.365 l
+h
+13.273 -0.088 m
+13.486 -0.088 13.659 -0.026 13.787 0.103 c
+13.923 0.239 13.996 0.43 14.008 0.675 c
+14.625 0.675 l
+14.603 0.294 14.467 -0.026 14.214 -0.279 c
+13.957 -0.526 13.644 -0.647 13.273 -0.647 c
+12.781 -0.647 12.406 -0.497 12.141 -0.191 c
+11.883 0.121 11.759 0.588 11.759 1.205 c
+11.759 1.646 l
+11.759 2.241 11.883 2.697 12.141 3.013 c
+12.406 3.326 12.781 3.484 13.273 3.484 c
+13.674 3.484 13.993 3.351 14.229 3.087 c
+14.47 2.829 14.603 2.484 14.625 2.043 c
+14.008 2.043 l
+13.986 2.337 13.913 2.557 13.787 2.705 c
+13.67 2.851 13.497 2.925 13.273 2.925 c
+12.978 2.925 12.762 2.826 12.626 2.631 c
+12.486 2.443 12.413 2.135 12.406 1.705 c
+12.406 1.19 l
+12.406 0.72 12.471 0.386 12.612 0.191 c
+12.758 0.004 12.978 -0.088 13.273 -0.088 c
+15.243 1.602 m
+15.243 2.179 15.378 2.634 15.654 2.969 c
+15.937 3.31 16.309 3.484 16.771 3.484 c
+17.231 3.484 17.598 3.314 17.874 2.984 c
+18.156 2.66 18.304 2.212 18.314 1.646 c
+18.314 1.22 l
+18.314 0.65 18.171 0.195 17.888 -0.148 c
+17.613 -0.482 17.246 -0.647 16.786 -0.647 c
+16.323 -0.647 15.952 -0.485 15.669 -0.162 c
+15.393 0.168 15.249 0.61 15.243 1.161 c
+h
+15.889 1.22 m
+15.889 0.816 15.966 0.5 16.124 0.264 c
+16.29 0.029 16.51 -0.088 16.786 -0.088 c
+17.352 -0.088 17.645 0.323 17.668 1.146 c
+17.668 1.602 l
+17.668 2.003 17.583 2.322 17.418 2.557 c
+17.26 2.8 17.043 2.925 16.771 2.925 c
+16.506 2.925 16.29 2.8 16.124 2.557 c
+15.966 2.322 15.889 2.003 15.889 1.602 c
+h
+19.77 3.41 m
+19.785 3.042 l
+20.027 3.337 20.346 3.484 20.74 3.484 c
+21.181 3.484 21.489 3.285 21.666 2.896 c
+21.919 3.285 22.268 3.484 22.709 3.484 c
+23.444 3.484 23.82 3.021 23.841 2.102 c
+23.841 -0.574 l
+23.195 -0.574 l
+23.195 2.043 l
+23.195 2.337 23.139 2.55 23.033 2.69 c
+22.933 2.826 22.761 2.896 22.518 2.896 c
+22.32 2.896 22.158 2.815 22.033 2.66 c
+21.915 2.514 21.846 2.322 21.828 2.087 c
+21.828 -0.574 l
+21.167 -0.574 l
+21.167 2.072 l
+21.167 2.62 20.946 2.896 20.504 2.896 c
+20.17 2.896 19.935 2.734 19.799 2.41 c
+19.799 -0.574 l
+19.153 -0.574 l
+19.153 3.41 l
+h
+25.429 3.41 m
+25.443 3.042 l
+25.686 3.337 26.006 3.484 26.399 3.484 c
+26.84 3.484 27.149 3.285 27.325 2.896 c
+27.579 3.285 27.928 3.484 28.369 3.484 c
+29.104 3.484 29.479 3.021 29.501 2.102 c
+29.501 -0.574 l
+28.853 -0.574 l
+28.853 2.043 l
+28.853 2.337 28.799 2.55 28.693 2.69 c
+28.593 2.826 28.42 2.896 28.178 2.896 c
+27.979 2.896 27.818 2.815 27.693 2.66 c
+27.575 2.514 27.505 2.322 27.487 2.087 c
+27.487 -0.574 l
+26.825 -0.574 l
+26.825 2.072 l
+26.825 2.62 26.605 2.896 26.164 2.896 c
+25.83 2.896 25.595 2.734 25.458 2.41 c
+25.458 -0.574 l
+24.812 -0.574 l
+24.812 3.41 l
+h
+31.176 -0.574 -0.646 3.984 re
+31.22 4.453 m
+31.22 4.343 31.191 4.251 31.132 4.174 c
+31.074 4.104 30.978 4.072 30.852 4.072 c
+30.735 4.072 30.64 4.104 30.574 4.174 c
+30.515 4.251 30.486 4.343 30.486 4.453 c
+30.486 4.571 30.515 4.663 30.574 4.733 c
+30.64 4.81 30.735 4.85 30.852 4.85 c
+30.978 4.85 31.074 4.81 31.132 4.733 c
+31.191 4.652 31.22 4.56 31.22 4.453 c
+33.043 4.365 m
+33.043 3.41 l
+33.646 3.41 l
+33.646 2.881 l
+33.043 2.881 l
+33.043 0.411 l
+33.043 0.253 33.065 0.135 33.117 0.058 c
+33.175 -0.023 33.264 -0.059 33.381 -0.059 c
+33.47 -0.059 33.557 -0.044 33.646 -0.015 c
+33.646 -0.574 l
+33.499 -0.621 33.344 -0.647 33.19 -0.647 c
+32.932 -0.647 32.738 -0.555 32.602 -0.368 c
+32.462 -0.184 32.396 0.077 32.396 0.411 c
+32.396 2.881 l
+31.793 2.881 l
+31.793 3.41 l
+32.396 3.41 l
+32.396 4.365 l
+h
+34.424 -1.646 m
+34.027 -1.382 l
+34.263 -1.058 34.384 -0.724 34.395 -0.383 c
+34.395 0.235 l
+35.057 0.235 l
+35.057 -0.294 l
+35.057 -0.551 34.991 -0.798 34.866 -1.044 c
+34.748 -1.287 34.601 -1.488 34.424 -1.646 c
+38.467 4.365 m
+38.467 3.41 l
+39.07 3.41 l
+39.07 2.881 l
+38.467 2.881 l
+38.467 0.411 l
+38.467 0.253 38.489 0.135 38.54 0.058 c
+38.599 -0.023 38.688 -0.059 38.805 -0.059 c
+38.893 -0.059 38.981 -0.044 39.07 -0.015 c
+39.07 -0.574 l
+38.923 -0.621 38.768 -0.647 38.614 -0.647 c
+38.357 -0.647 38.162 -0.555 38.026 -0.368 c
+37.886 -0.184 37.821 0.077 37.821 0.411 c
+37.821 2.881 l
+37.218 2.881 l
+37.218 3.41 l
+37.821 3.41 l
+37.821 4.365 l
+h
+40.481 2.998 m
+40.734 3.322 41.054 3.484 41.436 3.484 c
+42.141 3.484 42.498 3.013 42.509 2.072 c
+42.509 -0.574 l
+41.863 -0.574 l
+41.863 2.043 l
+41.863 2.356 41.807 2.576 41.701 2.705 c
+41.59 2.829 41.436 2.896 41.231 2.896 c
+41.073 2.896 40.925 2.84 40.79 2.734 c
+40.661 2.624 40.558 2.487 40.481 2.322 c
+40.481 -0.574 l
+39.834 -0.574 l
+39.834 5.071 l
+40.481 5.071 l
+h
+45.508 -0.574 m
+45.468 -0.485 45.441 -0.339 45.434 -0.133 c
+45.199 -0.478 44.905 -0.647 44.552 -0.647 c
+44.188 -0.647 43.905 -0.551 43.7 -0.353 c
+43.502 -0.148 43.406 0.139 43.406 0.515 c
+43.406 0.914 43.542 1.234 43.818 1.469 c
+44.09 1.712 44.464 1.837 44.934 1.837 c
+45.42 1.837 l
+45.42 2.263 l
+45.42 2.499 45.364 2.664 45.258 2.763 c
+45.148 2.869 44.986 2.925 44.773 2.925 c
+44.574 2.925 44.412 2.866 44.288 2.749 c
+44.171 2.631 44.111 2.484 44.111 2.308 c
+43.465 2.308 l
+43.465 2.502 43.523 2.693 43.641 2.881 c
+43.766 3.064 43.928 3.212 44.126 3.322 c
+44.332 3.428 44.56 3.484 44.817 3.484 c
+45.218 3.484 45.522 3.38 45.728 3.175 c
+45.942 2.969 46.056 2.674 46.066 2.293 c
+46.066 0.279 l
+46.066 -0.026 46.103 -0.291 46.184 -0.515 c
+46.184 -0.574 l
+h
+44.641 -0.059 m
+44.806 -0.059 44.957 -0.015 45.096 0.073 c
+45.243 0.162 45.35 0.272 45.42 0.411 c
+45.42 1.352 l
+45.052 1.352 l
+44.736 1.352 44.493 1.282 44.317 1.146 c
+44.14 1.018 44.053 0.83 44.053 0.588 c
+44.053 0.359 44.097 0.195 44.185 0.087 c
+44.273 -0.011 44.424 -0.059 44.641 -0.059 c
+47.918 4.365 m
+47.918 3.41 l
+48.521 3.41 l
+48.521 2.881 l
+47.918 2.881 l
+47.918 0.411 l
+47.918 0.253 47.94 0.135 47.992 0.058 c
+48.051 -0.023 48.139 -0.059 48.256 -0.059 c
+48.345 -0.059 48.433 -0.044 48.521 -0.015 c
+48.521 -0.574 l
+48.374 -0.621 48.219 -0.647 48.065 -0.647 c
+47.808 -0.647 47.614 -0.555 47.477 -0.368 c
+47.338 -0.184 47.272 0.077 47.272 0.411 c
+47.272 2.881 l
+46.669 2.881 l
+46.669 3.41 l
+47.272 3.41 l
+47.272 4.365 l
+h
+53.048 -0.574 m
+53.008 -0.485 52.982 -0.339 52.975 -0.133 c
+52.74 -0.478 52.446 -0.647 52.093 -0.647 c
+51.729 -0.647 51.446 -0.551 51.24 -0.353 c
+51.042 -0.148 50.947 0.139 50.947 0.515 c
+50.947 0.914 51.082 1.234 51.358 1.469 c
+51.63 1.712 52.005 1.837 52.475 1.837 c
+52.96 1.837 l
+52.96 2.263 l
+52.96 2.499 52.905 2.664 52.799 2.763 c
+52.688 2.869 52.527 2.925 52.314 2.925 c
+52.115 2.925 51.953 2.866 51.828 2.749 c
+51.711 2.631 51.652 2.484 51.652 2.308 c
+51.005 2.308 l
+51.005 2.502 51.064 2.693 51.182 2.881 c
+51.307 3.064 51.468 3.212 51.666 3.322 c
+51.872 3.428 52.1 3.484 52.358 3.484 c
+52.759 3.484 53.063 3.38 53.269 3.175 c
+53.482 2.969 53.596 2.674 53.607 2.293 c
+53.607 0.279 l
+53.607 -0.026 53.644 -0.291 53.725 -0.515 c
+53.725 -0.574 l
+h
+52.181 -0.059 m
+52.346 -0.059 52.497 -0.015 52.637 0.073 c
+52.784 0.162 52.89 0.272 52.96 0.411 c
+52.96 1.352 l
+52.593 1.352 l
+52.277 1.352 52.034 1.282 51.858 1.146 c
+51.681 1.018 51.593 0.83 51.593 0.588 c
+51.593 0.359 51.637 0.195 51.726 0.087 c
+51.814 -0.011 51.965 -0.059 52.181 -0.059 c
+56.252 2.792 m
+56.165 2.811 56.065 2.822 55.959 2.822 c
+55.624 2.822 55.389 2.638 55.253 2.278 c
+55.253 -0.574 l
+54.606 -0.574 l
+54.606 3.41 l
+55.238 3.41 l
+55.253 2.998 l
+55.429 3.322 55.672 3.484 55.988 3.484 c
+56.094 3.484 56.183 3.461 56.252 3.424 c
+h
+58.252 -0.647 m
+57.752 -0.647 57.37 -0.5 57.106 -0.206 c
+56.84 0.087 56.709 0.521 56.709 1.103 c
+56.709 1.573 l
+56.709 2.167 56.834 2.634 57.091 2.969 c
+57.355 3.31 57.715 3.484 58.178 3.484 c
+58.638 3.484 58.98 3.329 59.207 3.027 c
+59.443 2.734 59.564 2.271 59.575 1.646 c
+59.575 1.22 l
+57.355 1.22 l
+57.355 1.132 l
+57.355 0.698 57.432 0.386 57.59 0.191 c
+57.756 0.004 57.987 -0.088 58.282 -0.088 c
+58.476 -0.088 58.649 -0.056 58.796 0.014 c
+58.943 0.091 59.078 0.209 59.207 0.367 c
+59.545 -0.044 l
+59.259 -0.449 58.829 -0.647 58.252 -0.647 c
+58.178 2.925 m
+57.903 2.925 57.701 2.829 57.576 2.645 c
+57.447 2.458 57.374 2.167 57.355 1.778 c
+58.928 1.778 l
+58.928 1.866 l
+58.906 2.248 58.839 2.516 58.722 2.674 c
+58.604 2.84 58.421 2.925 58.178 2.925 c
+64.954 1.22 m
+64.954 0.592 64.837 0.121 64.602 -0.191 c
+64.374 -0.497 64.058 -0.647 63.647 -0.647 c
+63.242 -0.647 62.934 -0.497 62.72 -0.191 c
+62.72 -2.103 l
+62.074 -2.103 l
+62.074 3.41 l
+62.662 3.41 l
+62.706 2.969 l
+62.919 3.31 63.227 3.484 63.632 3.484 c
+64.073 3.484 64.4 3.329 64.617 3.027 c
+64.83 2.722 64.944 2.267 64.954 1.66 c
+h
+64.308 1.602 m
+64.308 2.043 64.238 2.366 64.102 2.572 c
+63.963 2.786 63.742 2.896 63.441 2.896 c
+63.125 2.896 62.886 2.741 62.72 2.439 c
+62.72 0.367 l
+62.886 0.062 63.125 -0.088 63.441 -0.088 c
+63.735 -0.088 63.948 0.014 64.088 0.22 c
+64.223 0.434 64.297 0.764 64.308 1.205 c
+h
+67.439 2.792 m
+67.35 2.811 67.252 2.822 67.145 2.822 c
+66.81 2.822 66.575 2.638 66.44 2.278 c
+66.44 -0.574 l
+65.792 -0.574 l
+65.792 3.41 l
+66.425 3.41 l
+66.44 2.998 l
+66.616 3.322 66.858 3.484 67.174 3.484 c
+67.281 3.484 67.369 3.461 67.439 3.424 c
+h
+69.438 -0.647 m
+68.938 -0.647 68.556 -0.5 68.291 -0.206 c
+68.027 0.087 67.894 0.521 67.894 1.103 c
+67.894 1.573 l
+67.894 2.167 68.019 2.634 68.277 2.969 c
+68.541 3.31 68.902 3.484 69.364 3.484 c
+69.824 3.484 70.166 3.329 70.394 3.027 c
+70.629 2.734 70.75 2.271 70.761 1.646 c
+70.761 1.22 l
+68.541 1.22 l
+68.541 1.132 l
+68.541 0.698 68.618 0.386 68.777 0.191 c
+68.942 0.004 69.173 -0.088 69.467 -0.088 c
+69.662 -0.088 69.835 -0.056 69.982 0.014 c
+70.128 0.091 70.265 0.209 70.394 0.367 c
+70.731 -0.044 l
+70.444 -0.449 70.015 -0.647 69.438 -0.647 c
+69.364 2.925 m
+69.089 2.925 68.887 2.829 68.761 2.645 c
+68.634 2.458 68.559 2.167 68.541 1.778 c
+70.114 1.778 l
+70.114 1.866 l
+70.092 2.248 70.026 2.516 69.908 2.674 c
+69.791 2.84 69.607 2.925 69.364 2.925 c
+73.48 0.44 m
+73.48 0.588 73.425 0.709 73.318 0.808 c
+73.208 0.904 73.002 1.022 72.701 1.161 c
+72.356 1.308 72.113 1.429 71.967 1.529 c
+71.819 1.635 71.709 1.753 71.643 1.881 c
+71.573 2.006 71.539 2.164 71.539 2.352 c
+71.539 2.674 71.657 2.944 71.892 3.16 c
+72.127 3.373 72.429 3.484 72.804 3.484 c
+73.186 3.484 73.495 3.37 73.73 3.145 c
+73.966 2.917 74.083 2.631 74.083 2.278 c
+73.436 2.278 l
+73.436 2.454 73.378 2.605 73.26 2.734 c
+73.142 2.859 72.988 2.925 72.804 2.925 c
+72.605 2.925 72.455 2.869 72.348 2.763 c
+72.238 2.664 72.187 2.532 72.187 2.366 c
+72.187 2.238 72.223 2.131 72.304 2.043 c
+72.381 1.962 72.572 1.859 72.877 1.734 c
+73.355 1.547 73.686 1.359 73.862 1.176 c
+74.039 0.999 74.126 0.771 74.126 0.5 c
+74.126 0.147 74.002 -0.133 73.76 -0.339 c
+73.524 -0.544 73.208 -0.647 72.819 -0.647 c
+72.396 -0.647 72.058 -0.53 71.805 -0.294 c
+71.547 -0.052 71.422 0.253 71.422 0.617 c
+72.069 0.617 l
+72.077 0.389 72.146 0.213 72.275 0.087 c
+72.399 -0.03 72.584 -0.088 72.819 -0.088 c
+73.031 -0.088 73.193 -0.04 73.303 0.058 c
+73.421 0.154 73.48 0.282 73.48 0.44 c
+76.391 -0.647 m
+75.89 -0.647 75.508 -0.5 75.244 -0.206 c
+74.98 0.087 74.847 0.521 74.847 1.103 c
+74.847 1.573 l
+74.847 2.167 74.972 2.634 75.229 2.969 c
+75.494 3.31 75.854 3.484 76.317 3.484 c
+76.777 3.484 77.118 3.329 77.346 3.027 c
+77.581 2.734 77.702 2.271 77.714 1.646 c
+77.714 1.22 l
+75.494 1.22 l
+75.494 1.132 l
+75.494 0.698 75.571 0.386 75.73 0.191 c
+75.894 0.004 76.126 -0.088 76.42 -0.088 c
+76.615 -0.088 76.788 -0.056 76.935 0.014 c
+77.081 0.091 77.218 0.209 77.346 0.367 c
+77.684 -0.044 l
+77.397 -0.449 76.968 -0.647 76.391 -0.647 c
+76.317 2.925 m
+76.042 2.925 75.84 2.829 75.714 2.645 c
+75.586 2.458 75.512 2.167 75.494 1.778 c
+77.066 1.778 l
+77.066 1.866 l
+77.045 2.248 76.979 2.516 76.861 2.674 c
+76.744 2.84 76.559 2.925 76.317 2.925 c
+79.11 3.41 m
+79.125 2.969 l
+79.378 3.31 79.701 3.484 80.095 3.484 c
+80.8 3.484 81.157 3.013 81.168 2.072 c
+81.168 -0.574 l
+80.521 -0.574 l
+80.521 2.043 l
+80.521 2.356 80.466 2.576 80.359 2.705 c
+80.249 2.829 80.095 2.896 79.889 2.896 c
+79.73 2.896 79.584 2.84 79.448 2.734 c
+79.319 2.624 79.217 2.487 79.14 2.322 c
+79.14 -0.574 l
+78.492 -0.574 l
+78.492 3.41 l
+h
+82.99 4.365 m
+82.99 3.41 l
+83.593 3.41 l
+83.593 2.881 l
+82.99 2.881 l
+82.99 0.411 l
+82.99 0.253 83.013 0.135 83.064 0.058 c
+83.123 -0.023 83.211 -0.059 83.329 -0.059 c
+83.416 -0.059 83.505 -0.044 83.593 -0.015 c
+83.593 -0.574 l
+83.446 -0.621 83.292 -0.647 83.138 -0.647 c
+82.88 -0.647 82.685 -0.555 82.55 -0.368 c
+82.41 -0.184 82.344 0.077 82.344 0.411 c
+82.344 2.881 l
+81.741 2.881 l
+81.741 3.41 l
+82.344 3.41 l
+82.344 4.365 l
+h
+85.945 1.602 m
+85.945 2.179 86.08 2.634 86.356 2.969 c
+86.639 3.31 87.011 3.484 87.474 3.484 c
+87.933 3.484 88.301 3.314 88.576 2.984 c
+88.859 2.66 89.006 2.212 89.017 1.646 c
+89.017 1.22 l
+89.017 0.65 88.874 0.195 88.59 -0.148 c
+88.315 -0.482 87.948 -0.647 87.489 -0.647 c
+87.025 -0.647 86.654 -0.485 86.371 -0.162 c
+86.096 0.168 85.953 0.61 85.945 1.161 c
+h
+86.591 1.22 m
+86.591 0.816 86.668 0.5 86.826 0.264 c
+86.992 0.029 87.213 -0.088 87.489 -0.088 c
+88.054 -0.088 88.349 0.323 88.37 1.146 c
+88.37 1.602 l
+88.37 2.003 88.286 2.322 88.12 2.557 c
+87.962 2.8 87.746 2.925 87.474 2.925 c
+87.209 2.925 86.992 2.8 86.826 2.557 c
+86.668 2.322 86.591 2.003 86.591 1.602 c
+h
+90.472 3.41 m
+90.487 2.969 l
+90.741 3.31 91.064 3.484 91.457 3.484 c
+92.162 3.484 92.519 3.013 92.53 2.072 c
+92.53 -0.574 l
+91.883 -0.574 l
+91.883 2.043 l
+91.883 2.356 91.828 2.576 91.722 2.705 c
+91.611 2.829 91.457 2.896 91.252 2.896 c
+91.094 2.896 90.946 2.84 90.811 2.734 c
+90.682 2.624 90.579 2.487 90.502 2.322 c
+90.502 -0.574 l
+89.855 -0.574 l
+89.855 3.41 l
+h
+f
+Q
+q 1 0 0 1 157.4383 353.5063 cm
+0 0 m
+-0.338 0.029 l
+-0.625 0.029 -0.816 -0.096 -0.912 -0.339 c
+-0.912 -2.97 l
+-1.955 -2.97 l
+-1.955 1.014 l
+-0.985 1.014 l
+-0.956 0.573 l
+-0.79 0.914 -0.559 1.087 -0.264 1.087 c
+-0.147 1.087 -0.056 1.065 0.015 1.028 c
+h
+2.072 -3.043 m
+1.544 -3.043 1.124 -2.889 0.823 -2.573 c
+0.53 -2.249 0.382 -1.79 0.382 -1.191 c
+0.382 -0.882 l
+0.382 -0.258 0.518 0.228 0.794 0.573 c
+1.066 0.914 1.459 1.087 1.97 1.087 c
+2.469 1.087 2.841 0.926 3.087 0.602 c
+3.341 0.278 3.472 -0.198 3.484 -0.823 c
+3.484 -1.324 l
+1.411 -1.324 l
+1.43 -1.617 1.492 -1.834 1.602 -1.97 c
+1.72 -2.11 1.9 -2.176 2.146 -2.176 c
+2.488 -2.176 2.778 -2.058 3.013 -1.823 c
+3.425 -2.455 l
+3.296 -2.631 3.109 -2.775 2.866 -2.881 c
+2.62 -2.988 2.356 -3.043 2.072 -3.043 c
+1.426 -0.603 m
+2.454 -0.603 l
+2.454 -0.5 l
+2.454 -0.265 2.414 -0.088 2.337 0.029 c
+2.267 0.154 2.138 0.22 1.955 0.22 c
+1.779 0.22 1.646 0.151 1.558 0.014 c
+1.477 -0.115 1.433 -0.32 1.426 -0.603 c
+4.307 -2.97 m
+4.307 0.22 l
+3.822 0.22 l
+3.822 1.014 l
+4.307 1.014 l
+4.307 1.367 l
+4.307 1.807 4.417 2.146 4.645 2.381 c
+4.881 2.624 5.196 2.748 5.6 2.748 c
+5.725 2.748 5.883 2.723 6.071 2.674 c
+6.071 1.851 l
+6.001 1.87 5.916 1.881 5.821 1.881 c
+5.505 1.881 5.351 1.697 5.351 1.337 c
+5.351 1.014 l
+5.968 1.014 l
+5.968 0.22 l
+5.351 0.22 l
+5.351 -2.97 l
+h
+f
+Q
+q 1 0 0 1 167.8457 350.5364 cm
+0 0 m
+-0.04 0.088 -0.067 0.235 -0.074 0.441 c
+-0.31 0.096 -0.603 -0.073 -0.956 -0.073 c
+-1.32 -0.073 -1.603 0.023 -1.808 0.221 c
+-2.007 0.426 -2.103 0.713 -2.103 1.088 c
+-2.103 1.488 -1.966 1.808 -1.691 2.043 c
+-1.419 2.286 -1.044 2.411 -0.574 2.411 c
+-0.088 2.411 l
+-0.088 2.837 l
+-0.088 3.072 -0.144 3.238 -0.25 3.337 c
+-0.36 3.443 -0.522 3.499 -0.736 3.499 c
+-0.934 3.499 -1.095 3.44 -1.22 3.323 c
+-1.338 3.205 -1.397 3.057 -1.397 2.882 c
+-2.043 2.882 l
+-2.043 3.076 -1.985 3.267 -1.867 3.454 c
+-1.742 3.638 -1.58 3.786 -1.382 3.896 c
+-1.176 4.002 -0.948 4.057 -0.691 4.057 c
+-0.291 4.057 0.014 3.954 0.22 3.749 c
+0.433 3.543 0.548 3.248 0.558 2.866 c
+0.558 0.853 l
+0.558 0.548 0.595 0.283 0.675 0.059 c
+0.675 0 l
+h
+-0.867 0.515 m
+-0.703 0.515 -0.551 0.559 -0.412 0.647 c
+-0.265 0.736 -0.158 0.846 -0.088 0.985 c
+-0.088 1.926 l
+-0.456 1.926 l
+-0.772 1.926 -1.015 1.856 -1.191 1.72 c
+-1.368 1.592 -1.455 1.404 -1.455 1.162 c
+-1.455 0.933 -1.411 0.769 -1.324 0.661 c
+-1.235 0.563 -1.085 0.515 -0.867 0.515 c
+2.175 3.984 m
+2.19 3.543 l
+2.443 3.884 2.767 4.057 3.16 4.057 c
+3.865 4.057 4.222 3.587 4.233 2.646 c
+4.233 0 l
+3.586 0 l
+3.586 2.617 l
+3.586 2.929 3.531 3.15 3.424 3.279 c
+3.314 3.403 3.16 3.469 2.954 3.469 c
+2.796 3.469 2.649 3.414 2.513 3.308 c
+2.385 3.198 2.281 3.061 2.204 2.896 c
+2.204 0 l
+1.558 0 l
+1.558 3.984 l
+h
+5.071 2.176 m
+5.071 2.782 5.181 3.248 5.409 3.572 c
+5.644 3.896 5.971 4.057 6.393 4.057 c
+6.776 4.057 7.073 3.899 7.291 3.587 c
+7.291 5.644 l
+7.937 5.644 l
+7.937 0 l
+7.349 0 l
+7.305 0.426 l
+7.099 0.092 6.794 -0.073 6.393 -0.073 c
+5.982 -0.073 5.659 0.081 5.423 0.397 c
+5.188 0.721 5.071 1.176 5.071 1.764 c
+h
+5.718 1.794 m
+5.718 1.353 5.78 1.022 5.909 0.809 c
+6.044 0.603 6.265 0.5 6.57 0.5 c
+6.894 0.5 7.133 0.661 7.291 0.985 c
+7.291 2.999 l
+7.121 3.311 6.882 3.469 6.57 3.469 c
+6.265 3.469 6.044 3.366 5.909 3.161 c
+5.78 2.955 5.718 2.631 5.718 2.19 c
+h
+11.274 3.984 m
+11.289 3.543 l
+11.542 3.884 11.866 4.057 12.259 4.057 c
+12.964 4.057 13.321 3.587 13.331 2.646 c
+13.331 0 l
+12.685 0 l
+12.685 2.617 l
+12.685 2.929 12.629 3.15 12.523 3.279 c
+12.413 3.403 12.259 3.469 12.053 3.469 c
+11.895 3.469 11.748 3.414 11.612 3.308 c
+11.484 3.198 11.38 3.061 11.303 2.896 c
+11.303 0 l
+10.657 0 l
+10.657 3.984 l
+h
+14.169 2.176 m
+14.169 2.753 14.306 3.208 14.581 3.543 c
+14.864 3.884 15.235 4.057 15.698 4.057 c
+16.157 4.057 16.525 3.888 16.801 3.558 c
+17.084 3.234 17.231 2.786 17.242 2.22 c
+17.242 1.794 l
+17.242 1.224 17.098 0.769 16.816 0.426 c
+16.54 0.092 16.172 -0.073 15.713 -0.073 c
+15.249 -0.073 14.879 0.088 14.596 0.412 c
+14.32 0.742 14.177 1.183 14.169 1.735 c
+h
+14.817 1.794 m
+14.817 1.389 14.894 1.073 15.052 0.838 c
+15.216 0.603 15.438 0.485 15.713 0.485 c
+16.279 0.485 16.573 0.897 16.595 1.72 c
+16.595 2.176 l
+16.595 2.577 16.51 2.896 16.345 3.131 c
+16.187 3.374 15.97 3.499 15.698 3.499 c
+15.434 3.499 15.216 3.374 15.052 3.131 c
+14.894 2.896 14.817 2.577 14.817 2.176 c
+h
+18.932 4.939 m
+18.932 3.984 l
+19.534 3.984 l
+19.534 3.454 l
+18.932 3.454 l
+18.932 0.985 l
+18.932 0.827 18.954 0.709 19.006 0.632 c
+19.064 0.551 19.152 0.515 19.27 0.515 c
+19.359 0.515 19.446 0.53 19.534 0.559 c
+19.534 0 l
+19.388 -0.047 19.233 -0.073 19.079 -0.073 c
+18.821 -0.073 18.627 0.019 18.491 0.206 c
+18.351 0.389 18.285 0.651 18.285 0.985 c
+18.285 3.454 l
+17.682 3.454 l
+17.682 3.984 l
+18.285 3.984 l
+18.285 4.939 l
+h
+22.636 3.984 m
+22.651 3.616 l
+22.894 3.911 23.213 4.057 23.606 4.057 c
+24.047 4.057 24.356 3.859 24.533 3.469 c
+24.786 3.859 25.135 4.057 25.576 4.057 c
+26.311 4.057 26.686 3.595 26.708 2.676 c
+26.708 0 l
+26.061 0 l
+26.061 2.617 l
+26.061 2.911 26.006 3.124 25.899 3.263 c
+25.8 3.4 25.628 3.469 25.385 3.469 c
+25.186 3.469 25.025 3.389 24.899 3.234 c
+24.782 3.088 24.712 2.896 24.694 2.66 c
+24.694 0 l
+24.032 0 l
+24.032 2.646 l
+24.032 3.194 23.812 3.469 23.371 3.469 c
+23.037 3.469 22.802 3.308 22.665 2.984 c
+22.665 0 l
+22.019 0 l
+22.019 3.984 l
+h
+29.104 -0.073 m
+28.604 -0.073 28.222 0.073 27.957 0.368 c
+27.693 0.661 27.56 1.095 27.56 1.676 c
+27.56 2.147 l
+27.56 2.741 27.685 3.208 27.943 3.543 c
+28.207 3.884 28.567 4.057 29.03 4.057 c
+29.489 4.057 29.831 3.903 30.059 3.601 c
+30.295 3.308 30.416 2.845 30.426 2.22 c
+30.426 1.794 l
+28.207 1.794 l
+28.207 1.706 l
+28.207 1.272 28.284 0.96 28.442 0.765 c
+28.608 0.578 28.839 0.485 29.133 0.485 c
+29.328 0.485 29.501 0.518 29.647 0.588 c
+29.794 0.665 29.931 0.783 30.059 0.941 c
+30.397 0.53 l
+30.11 0.125 29.68 -0.073 29.104 -0.073 c
+29.03 3.499 m
+28.755 3.499 28.552 3.403 28.427 3.219 c
+28.299 3.032 28.225 2.741 28.207 2.352 c
+29.78 2.352 l
+29.78 2.44 l
+29.757 2.822 29.692 3.09 29.574 3.248 c
+29.456 3.414 29.273 3.499 29.03 3.499 c
+32.852 3.366 m
+32.764 3.385 32.664 3.396 32.558 3.396 c
+32.223 3.396 31.988 3.212 31.852 2.852 c
+31.852 0 l
+31.205 0 l
+31.205 3.984 l
+31.837 3.984 l
+31.852 3.572 l
+32.028 3.896 32.271 4.057 32.587 4.057 c
+32.693 4.057 32.782 4.035 32.852 3.998 c
+h
+33.293 2.176 m
+33.293 2.793 33.403 3.256 33.631 3.572 c
+33.855 3.896 34.189 4.057 34.63 4.057 c
+35.031 4.057 35.336 3.881 35.542 3.528 c
+35.586 3.984 l
+36.174 3.984 l
+36.174 -0.044 l
+36.174 -0.532 36.045 -0.911 35.791 -1.176 c
+35.535 -1.44 35.182 -1.573 34.733 -1.573 c
+34.535 -1.573 34.314 -1.521 34.072 -1.425 c
+33.826 -1.326 33.646 -1.205 33.528 -1.058 c
+33.792 -0.617 l
+34.058 -0.881 34.355 -1.014 34.69 -1.014 c
+35.226 -1.014 35.502 -0.72 35.513 -0.132 c
+35.513 0.397 l
+35.307 0.081 35.005 -0.073 34.615 -0.073 c
+34.204 -0.073 33.881 0.077 33.646 0.383 c
+33.418 0.695 33.3 1.147 33.293 1.735 c
+h
+33.954 1.794 m
+33.954 1.353 34.017 1.022 34.145 0.809 c
+34.27 0.603 34.487 0.5 34.792 0.5 c
+35.116 0.5 35.355 0.665 35.513 1 c
+35.513 2.984 l
+35.344 3.308 35.105 3.469 34.792 3.469 c
+34.498 3.469 34.281 3.366 34.145 3.161 c
+34.017 2.955 33.954 2.631 33.954 2.19 c
+h
+38.555 -0.073 m
+38.056 -0.073 37.673 0.073 37.408 0.368 c
+37.144 0.661 37.012 1.095 37.012 1.676 c
+37.012 2.147 l
+37.012 2.741 37.137 3.208 37.394 3.543 c
+37.659 3.884 38.019 4.057 38.482 4.057 c
+38.941 4.057 39.282 3.903 39.511 3.601 c
+39.746 3.308 39.867 2.845 39.878 2.22 c
+39.878 1.794 l
+37.659 1.794 l
+37.659 1.706 l
+37.659 1.272 37.736 0.96 37.894 0.765 c
+38.059 0.578 38.291 0.485 38.584 0.485 c
+38.779 0.485 38.952 0.518 39.099 0.588 c
+39.246 0.665 39.382 0.783 39.511 0.941 c
+39.849 0.53 l
+39.562 0.125 39.132 -0.073 38.555 -0.073 c
+38.482 3.499 m
+38.206 3.499 38.004 3.403 37.879 3.219 c
+37.75 3.032 37.677 2.741 37.659 2.352 c
+39.232 2.352 l
+39.232 2.44 l
+39.209 2.822 39.143 3.09 39.026 3.248 c
+38.908 3.414 38.725 3.499 38.482 3.499 c
+40.525 2.176 m
+40.525 2.782 40.635 3.248 40.863 3.572 c
+41.098 3.896 41.425 4.057 41.848 4.057 c
+42.23 4.057 42.528 3.899 42.744 3.587 c
+42.744 5.644 l
+43.392 5.644 l
+43.392 0 l
+42.804 0 l
+42.759 0.426 l
+42.553 0.092 42.249 -0.073 41.848 -0.073 c
+41.436 -0.073 41.113 0.081 40.878 0.397 c
+40.643 0.721 40.525 1.176 40.525 1.764 c
+h
+41.171 1.794 m
+41.171 1.353 41.234 1.022 41.362 0.809 c
+41.499 0.603 41.719 0.5 42.024 0.5 c
+42.347 0.5 42.586 0.661 42.744 0.985 c
+42.744 2.999 l
+42.575 3.311 42.336 3.469 42.024 3.469 c
+41.719 3.469 41.499 3.366 41.362 3.161 c
+41.234 2.955 41.171 2.631 41.171 2.19 c
+h
+46.816 0 -0.646 3.984 re
+46.86 5.027 m
+46.86 4.917 46.831 4.825 46.772 4.748 c
+46.713 4.678 46.617 4.645 46.492 4.645 c
+46.375 4.645 46.28 4.678 46.214 4.748 c
+46.155 4.825 46.125 4.917 46.125 5.027 c
+46.125 5.145 46.155 5.237 46.214 5.307 c
+46.28 5.384 46.375 5.424 46.492 5.424 c
+46.617 5.424 46.713 5.384 46.772 5.307 c
+46.831 5.226 46.86 5.134 46.86 5.027 c
+48.448 3.984 m
+48.462 3.543 l
+48.716 3.884 49.039 4.057 49.432 4.057 c
+50.138 4.057 50.494 3.587 50.505 2.646 c
+50.505 0 l
+49.859 0 l
+49.859 2.617 l
+49.859 2.929 49.804 3.15 49.697 3.279 c
+49.586 3.403 49.432 3.469 49.227 3.469 c
+49.069 3.469 48.921 3.414 48.786 3.308 c
+48.657 3.198 48.554 3.061 48.477 2.896 c
+48.477 0 l
+47.83 0 l
+47.83 3.984 l
+h
+52.329 4.939 m
+52.329 3.984 l
+52.931 3.984 l
+52.931 3.454 l
+52.329 3.454 l
+52.329 0.985 l
+52.329 0.827 52.35 0.709 52.402 0.632 c
+52.46 0.551 52.549 0.515 52.666 0.515 c
+52.755 0.515 52.842 0.53 52.931 0.559 c
+52.931 0 l
+52.784 -0.047 52.63 -0.073 52.475 -0.073 c
+52.218 -0.073 52.023 0.019 51.887 0.206 c
+51.747 0.389 51.681 0.651 51.681 0.985 c
+51.681 3.454 l
+51.078 3.454 l
+51.078 3.984 l
+51.681 3.984 l
+51.681 4.939 l
+h
+53.489 2.176 m
+53.489 2.753 53.625 3.208 53.901 3.543 c
+54.184 3.884 54.555 4.057 55.018 4.057 c
+55.477 4.057 55.845 3.888 56.121 3.558 c
+56.404 3.234 56.551 2.786 56.562 2.22 c
+56.562 1.794 l
+56.562 1.224 56.418 0.769 56.135 0.426 c
+55.859 0.092 55.492 -0.073 55.033 -0.073 c
+54.569 -0.073 54.199 0.088 53.916 0.412 c
+53.64 0.742 53.497 1.183 53.489 1.735 c
+h
+54.136 1.794 m
+54.136 1.389 54.213 1.073 54.371 0.838 c
+54.537 0.603 54.758 0.485 55.033 0.485 c
+55.599 0.485 55.893 0.897 55.915 1.72 c
+55.915 2.176 l
+55.915 2.577 55.83 2.896 55.664 3.131 c
+55.506 3.374 55.29 3.499 55.018 3.499 c
+54.754 3.499 54.537 3.374 54.371 3.131 c
+54.213 2.896 54.136 2.577 54.136 2.176 c
+h
+60.501 0.485 m
+60.714 0.485 60.887 0.548 61.015 0.676 c
+61.151 0.813 61.225 1.004 61.236 1.249 c
+61.854 1.249 l
+61.831 0.867 61.696 0.548 61.442 0.294 c
+61.185 0.048 60.872 -0.073 60.501 -0.073 c
+60.009 -0.073 59.633 0.077 59.369 0.383 c
+59.112 0.695 58.987 1.162 58.987 1.779 c
+58.987 2.22 l
+58.987 2.815 59.112 3.271 59.369 3.587 c
+59.633 3.899 60.009 4.057 60.501 4.057 c
+60.902 4.057 61.221 3.925 61.457 3.66 c
+61.699 3.403 61.831 3.057 61.854 2.617 c
+61.236 2.617 l
+61.214 2.911 61.141 3.131 61.015 3.279 c
+60.898 3.425 60.725 3.499 60.501 3.499 c
+60.207 3.499 59.99 3.4 59.855 3.205 c
+59.714 3.017 59.641 2.708 59.633 2.279 c
+59.633 1.764 l
+59.633 1.294 59.699 0.96 59.839 0.765 c
+59.986 0.578 60.207 0.485 60.501 0.485 c
+64.632 0.353 m
+64.414 0.067 64.102 -0.073 63.691 -0.073 c
+63.327 -0.073 63.051 0.048 62.868 0.294 c
+62.691 0.548 62.596 0.912 62.588 1.382 c
+62.588 3.984 l
+63.235 3.984 l
+63.235 1.441 l
+63.235 0.813 63.419 0.5 63.793 0.5 c
+64.194 0.5 64.47 0.676 64.617 1.029 c
+64.617 3.984 l
+65.264 3.984 l
+65.264 0 l
+64.646 0 l
+h
+67.894 3.366 m
+67.807 3.385 67.707 3.396 67.601 3.396 c
+67.266 3.396 67.03 3.212 66.895 2.852 c
+66.895 0 l
+66.248 0 l
+66.248 3.984 l
+66.88 3.984 l
+66.895 3.572 l
+67.071 3.896 67.314 4.057 67.63 4.057 c
+67.736 4.057 67.824 4.035 67.894 3.998 c
+h
+70.188 3.366 m
+70.099 3.385 70 3.396 69.893 3.396 c
+69.559 3.396 69.324 3.212 69.188 2.852 c
+69.188 0 l
+68.541 0 l
+68.541 3.984 l
+69.173 3.984 l
+69.188 3.572 l
+69.364 3.896 69.607 4.057 69.923 4.057 c
+70.03 4.057 70.118 4.035 70.188 3.998 c
+h
+72.187 -0.073 m
+71.687 -0.073 71.304 0.073 71.04 0.368 c
+70.776 0.661 70.643 1.095 70.643 1.676 c
+70.643 2.147 l
+70.643 2.741 70.768 3.208 71.026 3.543 c
+71.29 3.884 71.65 4.057 72.113 4.057 c
+72.572 4.057 72.914 3.903 73.142 3.601 c
+73.378 3.308 73.498 2.845 73.509 2.22 c
+73.509 1.794 l
+71.29 1.794 l
+71.29 1.706 l
+71.29 1.272 71.367 0.96 71.525 0.765 c
+71.691 0.578 71.922 0.485 72.216 0.485 c
+72.411 0.485 72.584 0.518 72.73 0.588 c
+72.877 0.665 73.014 0.783 73.142 0.941 c
+73.48 0.53 l
+73.193 0.125 72.763 -0.073 72.187 -0.073 c
+72.113 3.499 m
+71.838 3.499 71.635 3.403 71.51 3.219 c
+71.381 3.032 71.308 2.741 71.29 2.352 c
+72.863 2.352 l
+72.863 2.44 l
+72.84 2.822 72.775 3.09 72.657 3.248 c
+72.539 3.414 72.356 3.499 72.113 3.499 c
+74.906 3.984 m
+74.92 3.543 l
+75.174 3.884 75.497 4.057 75.89 4.057 c
+76.596 4.057 76.952 3.587 76.964 2.646 c
+76.964 0 l
+76.317 0 l
+76.317 2.617 l
+76.317 2.929 76.262 3.15 76.156 3.279 c
+76.046 3.403 75.89 3.469 75.685 3.469 c
+75.527 3.469 75.38 3.414 75.244 3.308 c
+75.115 3.198 75.013 3.061 74.936 2.896 c
+74.936 0 l
+74.288 0 l
+74.288 3.984 l
+h
+78.787 4.939 m
+78.787 3.984 l
+79.389 3.984 l
+79.389 3.454 l
+78.787 3.454 l
+78.787 0.985 l
+78.787 0.827 78.809 0.709 78.86 0.632 c
+78.919 0.551 79.007 0.515 79.125 0.515 c
+79.213 0.515 79.301 0.53 79.389 0.559 c
+79.389 0 l
+79.242 -0.047 79.088 -0.073 78.934 -0.073 c
+78.676 -0.073 78.481 0.019 78.346 0.206 c
+78.206 0.389 78.14 0.651 78.14 0.985 c
+78.14 3.454 l
+77.537 3.454 l
+77.537 3.984 l
+78.14 3.984 l
+78.14 4.939 l
+h
+84.754 1.794 m
+84.754 1.176 84.64 0.709 84.416 0.397 c
+84.199 0.081 83.876 -0.073 83.446 -0.073 c
+83.023 -0.073 82.711 0.107 82.506 0.47 c
+82.476 0 l
+81.873 0 l
+81.873 5.644 l
+82.52 5.644 l
+82.52 3.543 l
+82.733 3.884 83.042 4.057 83.446 4.057 c
+83.876 4.057 84.199 3.899 84.416 3.587 c
+84.64 3.282 84.754 2.815 84.754 2.19 c
+h
+84.108 2.176 m
+84.108 2.646 84.038 2.977 83.902 3.175 c
+83.773 3.37 83.564 3.469 83.27 3.469 c
+82.936 3.469 82.685 3.285 82.52 2.926 c
+82.52 1.044 l
+82.685 0.68 82.939 0.5 83.285 0.5 c
+83.578 0.5 83.788 0.603 83.917 0.809 c
+84.042 1.014 84.108 1.33 84.108 1.764 c
+h
+87.239 3.366 m
+87.15 3.385 87.051 3.396 86.944 3.396 c
+86.61 3.396 86.375 3.212 86.239 2.852 c
+86.239 0 l
+85.592 0 l
+85.592 3.984 l
+86.224 3.984 l
+86.239 3.572 l
+86.415 3.896 86.658 4.057 86.974 4.057 c
+87.08 4.057 87.169 4.035 87.239 3.998 c
+h
+89.781 0 m
+89.741 0.088 89.715 0.235 89.708 0.441 c
+89.473 0.096 89.178 -0.073 88.826 -0.073 c
+88.462 -0.073 88.179 0.023 87.973 0.221 c
+87.775 0.426 87.68 0.713 87.68 1.088 c
+87.68 1.488 87.815 1.808 88.091 2.043 c
+88.363 2.286 88.738 2.411 89.208 2.411 c
+89.693 2.411 l
+89.693 2.837 l
+89.693 3.072 89.638 3.238 89.531 3.337 c
+89.421 3.443 89.259 3.499 89.047 3.499 c
+88.848 3.499 88.686 3.44 88.561 3.323 c
+88.444 3.205 88.385 3.057 88.385 2.882 c
+87.738 2.882 l
+87.738 3.076 87.797 3.267 87.915 3.454 c
+88.04 3.638 88.201 3.786 88.399 3.896 c
+88.605 4.002 88.833 4.057 89.091 4.057 c
+89.491 4.057 89.796 3.954 90.001 3.749 c
+90.215 3.543 90.329 3.248 90.34 2.866 c
+90.34 0.853 l
+90.34 0.548 90.377 0.283 90.458 0.059 c
+90.458 0 l
+h
+88.914 0.515 m
+89.08 0.515 89.23 0.559 89.37 0.647 c
+89.517 0.736 89.623 0.846 89.693 0.985 c
+89.693 1.926 l
+89.326 1.926 l
+89.01 1.926 88.767 1.856 88.59 1.72 c
+88.414 1.592 88.326 1.404 88.326 1.162 c
+88.326 0.933 88.37 0.769 88.459 0.661 c
+88.547 0.563 88.698 0.515 88.914 0.515 c
+91.957 3.984 m
+91.971 3.543 l
+92.225 3.884 92.548 4.057 92.941 4.057 c
+93.647 4.057 94.003 3.587 94.015 2.646 c
+94.015 0 l
+93.368 0 l
+93.368 2.617 l
+93.368 2.929 93.313 3.15 93.207 3.279 c
+93.096 3.403 92.941 3.469 92.736 3.469 c
+92.578 3.469 92.43 3.414 92.295 3.308 c
+92.166 3.198 92.064 3.061 91.986 2.896 c
+91.986 0 l
+91.339 0 l
+91.339 3.984 l
+h
+96.367 0.485 m
+96.58 0.485 96.752 0.548 96.881 0.676 c
+97.017 0.813 97.091 1.004 97.101 1.249 c
+97.719 1.249 l
+97.697 0.867 97.561 0.548 97.307 0.294 c
+97.05 0.048 96.738 -0.073 96.367 -0.073 c
+95.874 -0.073 95.499 0.077 95.235 0.383 c
+94.977 0.695 94.853 1.162 94.853 1.779 c
+94.853 2.22 l
+94.853 2.815 94.977 3.271 95.235 3.587 c
+95.499 3.899 95.874 4.057 96.367 4.057 c
+96.767 4.057 97.087 3.925 97.322 3.66 c
+97.564 3.403 97.697 3.057 97.719 2.617 c
+97.101 2.617 l
+97.08 2.911 97.006 3.131 96.881 3.279 c
+96.763 3.425 96.59 3.499 96.367 3.499 c
+96.073 3.499 95.856 3.4 95.72 3.205 c
+95.58 3.017 95.507 2.708 95.499 2.279 c
+95.499 1.764 l
+95.499 1.294 95.566 0.96 95.705 0.765 c
+95.852 0.578 96.073 0.485 96.367 0.485 c
+99.115 3.572 m
+99.368 3.896 99.688 4.057 100.071 4.057 c
+100.777 4.057 101.132 3.587 101.144 2.646 c
+101.144 0 l
+100.497 0 l
+100.497 2.617 l
+100.497 2.929 100.442 3.15 100.335 3.279 c
+100.225 3.403 100.071 3.469 99.865 3.469 c
+99.707 3.469 99.56 3.414 99.424 3.308 c
+99.295 3.198 99.192 3.061 99.115 2.896 c
+99.115 0 l
+98.468 0 l
+98.468 5.644 l
+99.115 5.644 l
+h
+102.144 0.353 m
+102.144 0.47 102.177 0.566 102.246 0.647 c
+102.312 0.724 102.415 0.765 102.555 0.765 c
+102.701 0.765 102.809 0.724 102.878 0.647 c
+102.955 0.566 102.996 0.47 102.996 0.353 c
+102.996 0.243 102.955 0.151 102.878 0.073 c
+102.809 -0.004 102.701 -0.044 102.555 -0.044 c
+102.415 -0.044 102.312 -0.004 102.246 0.073 c
+102.177 0.151 102.144 0.243 102.144 0.353 c
+f
+Q
+0.113 0.082 0.09 0 k
+35.668 343.426 238.665 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 40.8563 336.5872 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.771 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.279 -3.219 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.985 c
+-3.322 2.18 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.003 -2.469 3.043 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.182 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.455 c
+-2.26 2.425 -2.319 2.385 -2.366 2.338 c
+-2.406 2.297 -2.437 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.44 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.014 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.147 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.596 4.935 -0.411 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.632 5.137 1.779 c
+5.245 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.152 2.22 c
+8.004 2.22 l
+7.993 2.139 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.871 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.279 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.279 5.835 1.162 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.22 l
+13.644 2.22 l
+13.924 3.117 l
+14.497 3.117 l
+14.497 2.22 l
+15.732 2.22 l
+15.732 1.602 l
+14.497 1.602 l
+14.497 -0.103 l
+14.497 -0.324 l
+14.504 -0.393 14.527 -0.455 14.556 -0.515 c
+14.593 -0.565 14.648 -0.61 14.718 -0.646 c
+14.795 -0.676 14.909 -0.691 15.056 -0.691 c
+15.192 -0.691 15.327 -0.687 15.468 -0.676 c
+15.603 -0.658 15.736 -0.632 15.865 -0.602 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.23 15.629 -1.249 c
+15.549 -1.261 15.471 -1.267 15.394 -1.278 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.041 -1.301 14.942 -1.308 14.835 -1.308 c
+14.648 -1.308 14.486 -1.294 14.35 -1.264 c
+14.221 -1.228 14.107 -1.183 14.012 -1.132 c
+13.924 -1.084 13.85 -1.025 13.791 -0.955 c
+13.733 -0.878 13.689 -0.801 13.66 -0.72 c
+13.63 -0.632 13.608 -0.544 13.6 -0.455 c
+13.59 -0.36 13.586 -0.264 13.586 -0.176 c
+h
+24.133 1.47 m
+24.033 1.477 23.931 1.488 23.824 1.5 c
+23.713 1.517 23.592 1.529 23.456 1.529 c
+23.28 1.529 23.121 1.488 22.986 1.411 c
+22.846 1.341 22.728 1.242 22.633 1.118 c
+22.545 0.989 22.475 0.842 22.427 0.676 c
+22.387 0.507 22.369 0.331 22.369 0.147 c
+22.369 -1.264 l
+21.472 -1.264 l
+21.472 0.985 l
+21.472 1.11 21.461 1.235 21.442 1.353 c
+21.432 1.477 21.417 1.595 21.398 1.706 c
+21.388 1.823 21.373 1.918 21.354 1.999 c
+21.332 2.087 21.314 2.161 21.296 2.22 c
+22.178 2.22 l
+22.185 2.168 22.196 2.117 22.207 2.058 c
+22.225 1.999 22.24 1.933 22.251 1.867 c
+22.269 1.808 22.284 1.742 22.295 1.675 c
+22.302 1.606 22.313 1.544 22.325 1.484 c
+22.339 1.484 l
+22.375 1.602 22.427 1.709 22.486 1.808 c
+22.552 1.904 22.633 1.988 22.722 2.058 c
+22.809 2.124 22.913 2.18 23.03 2.22 c
+23.155 2.257 23.302 2.278 23.471 2.278 c
+23.596 2.278 23.713 2.271 23.824 2.263 c
+23.941 2.253 24.044 2.238 24.133 2.22 c
+h
+26.738 -1.323 m
+26.481 -1.323 26.253 -1.286 26.047 -1.22 c
+25.841 -1.143 25.665 -1.029 25.518 -0.881 c
+25.371 -0.727 25.253 -0.536 25.165 -0.309 c
+25.084 -0.085 25.047 0.181 25.047 0.485 c
+25.047 0.816 25.091 1.095 25.18 1.323 c
+25.275 1.558 25.404 1.742 25.562 1.881 c
+25.727 2.018 25.915 2.117 26.121 2.176 c
+26.327 2.242 26.535 2.278 26.753 2.278 c
+27.025 2.278 27.26 2.227 27.458 2.132 c
+27.664 2.043 27.829 1.911 27.958 1.735 c
+28.094 1.565 28.193 1.359 28.252 1.118 c
+28.318 0.882 28.355 0.617 28.355 0.324 c
+28.355 0.309 l
+25.988 0.309 l
+25.988 0.162 26.003 0.023 26.032 -0.103 c
+26.069 -0.231 26.124 -0.345 26.194 -0.441 c
+26.26 -0.529 26.344 -0.599 26.444 -0.646 c
+26.539 -0.698 26.653 -0.72 26.782 -0.72 c
+26.936 -0.72 27.076 -0.687 27.194 -0.617 c
+27.318 -0.551 27.407 -0.448 27.458 -0.309 c
+28.296 -0.382 l
+28.266 -0.482 28.212 -0.588 28.135 -0.706 c
+28.054 -0.816 27.95 -0.918 27.825 -1.014 c
+27.708 -1.103 27.553 -1.176 27.37 -1.234 c
+27.194 -1.294 26.98 -1.323 26.738 -1.323 c
+26.738 1.706 m
+26.649 1.706 26.562 1.691 26.473 1.661 c
+26.385 1.632 26.304 1.58 26.238 1.515 c
+26.169 1.444 26.109 1.357 26.061 1.249 c
+26.021 1.139 26.003 1.014 26.003 0.867 c
+27.472 0.867 l
+27.472 1.004 27.447 1.124 27.399 1.235 c
+27.359 1.341 27.304 1.43 27.237 1.5 c
+27.179 1.565 27.106 1.617 27.017 1.646 c
+26.929 1.683 26.834 1.706 26.738 1.706 c
+30.886 1.602 m
+30.886 -1.264 l
+29.99 -1.264 l
+29.99 1.602 l
+29.167 1.602 l
+29.167 2.22 l
+29.99 2.22 l
+29.99 2.484 l
+29.99 2.61 30.005 2.741 30.034 2.881 c
+30.071 3.017 30.14 3.135 30.24 3.234 c
+30.346 3.341 30.489 3.429 30.666 3.499 c
+30.842 3.564 31.067 3.601 31.343 3.601 c
+31.555 3.601 31.754 3.591 31.931 3.572 c
+32.106 3.55 32.257 3.532 32.386 3.514 c
+32.386 2.926 l
+32.257 2.944 32.114 2.959 31.96 2.969 c
+31.802 2.976 31.651 2.984 31.504 2.984 c
+31.376 2.984 31.272 2.969 31.195 2.94 c
+31.115 2.911 31.052 2.87 31.004 2.822 c
+30.953 2.77 30.919 2.708 30.901 2.631 c
+30.89 2.562 30.886 2.484 30.886 2.396 c
+30.886 2.22 l
+32.313 2.22 l
+32.313 1.602 l
+h
+35.407 -0.646 m
+36.538 -0.646 l
+36.538 -1.264 l
+33.232 -1.264 l
+33.232 -0.646 l
+34.495 -0.646 l
+34.495 2.896 l
+33.569 2.896 l
+33.569 3.514 l
+35.407 3.514 l
+h
+40.569 0.485 m
+40.569 0.21 40.533 -0.04 40.467 -0.264 c
+40.397 -0.482 40.294 -0.669 40.158 -0.823 c
+40.018 -0.981 39.842 -1.103 39.629 -1.19 c
+39.412 -1.278 39.158 -1.323 38.865 -1.323 c
+38.589 -1.323 38.343 -1.278 38.13 -1.19 c
+37.924 -1.103 37.751 -0.981 37.615 -0.823 c
+37.475 -0.669 37.373 -0.482 37.307 -0.264 c
+37.236 -0.04 37.203 0.21 37.203 0.485 c
+37.203 0.738 37.233 0.974 37.292 1.191 c
+37.358 1.415 37.461 1.606 37.6 1.764 c
+37.737 1.929 37.913 2.058 38.13 2.146 c
+38.343 2.234 38.6 2.278 38.894 2.278 c
+39.206 2.278 39.467 2.234 39.673 2.146 c
+39.886 2.058 40.059 1.929 40.187 1.764 c
+40.324 1.606 40.423 1.415 40.482 1.191 c
+40.54 0.974 40.569 0.738 40.569 0.485 c
+39.615 0.485 m
+39.615 0.691 39.599 0.867 39.57 1.014 c
+39.548 1.162 39.511 1.282 39.453 1.382 c
+39.393 1.477 39.32 1.548 39.232 1.588 c
+39.144 1.635 39.033 1.661 38.909 1.661 c
+38.644 1.661 38.453 1.562 38.335 1.367 c
+38.218 1.18 38.159 0.886 38.159 0.485 c
+38.159 0.063 38.218 -0.243 38.335 -0.426 c
+38.453 -0.613 38.63 -0.706 38.865 -0.706 c
+38.99 -0.706 39.104 -0.687 39.202 -0.646 c
+39.298 -0.599 39.379 -0.525 39.438 -0.426 c
+39.504 -0.33 39.548 -0.206 39.57 -0.058 c
+39.599 0.088 39.615 0.268 39.615 0.485 c
+42.954 -2.66 m
+42.738 -2.66 42.547 -2.635 42.381 -2.587 c
+42.212 -2.547 42.073 -2.484 41.955 -2.396 c
+41.837 -2.315 41.738 -2.219 41.661 -2.102 c
+41.591 -1.984 41.543 -1.855 41.514 -1.72 c
+42.41 -1.617 l
+42.447 -1.753 42.518 -1.859 42.616 -1.94 c
+42.712 -2.028 42.837 -2.072 42.984 -2.072 c
+43.072 -2.072 43.153 -2.057 43.234 -2.028 c
+43.311 -1.999 43.381 -1.944 43.44 -1.866 c
+43.499 -1.797 43.542 -1.705 43.572 -1.587 c
+43.609 -1.469 43.631 -1.323 43.631 -1.147 c
+43.631 -0.955 l
+43.631 -0.889 43.634 -0.831 43.646 -0.779 c
+43.646 -0.588 l
+43.631 -0.588 l
+43.532 -0.816 43.388 -0.977 43.204 -1.072 c
+43.017 -1.172 42.811 -1.22 42.587 -1.22 c
+42.381 -1.22 42.198 -1.183 42.044 -1.103 c
+41.896 -1.014 41.768 -0.897 41.661 -0.75 c
+41.562 -0.596 41.488 -0.411 41.441 -0.206 c
+41.389 0.008 41.367 0.243 41.367 0.5 c
+41.367 0.771 41.389 1.018 41.441 1.235 c
+41.5 1.448 41.58 1.632 41.691 1.779 c
+41.797 1.933 41.93 2.051 42.088 2.132 c
+42.242 2.22 42.429 2.263 42.646 2.263 c
+42.742 2.263 42.84 2.253 42.94 2.234 c
+43.035 2.213 43.123 2.18 43.204 2.132 c
+43.293 2.08 43.37 2.018 43.44 1.941 c
+43.517 1.86 43.58 1.768 43.631 1.661 c
+43.646 1.661 l
+43.646 1.808 l
+43.653 1.867 43.66 1.918 43.66 1.97 c
+43.667 2.028 43.675 2.076 43.675 2.117 c
+43.682 2.165 43.694 2.198 43.704 2.22 c
+44.557 2.22 l
+44.546 2.139 44.535 2.028 44.527 1.881 c
+44.527 1.411 l
+44.527 -1.161 l
+44.527 -1.415 44.49 -1.635 44.425 -1.822 c
+44.355 -2.007 44.251 -2.161 44.116 -2.279 c
+43.976 -2.404 43.811 -2.499 43.616 -2.558 c
+43.418 -2.624 43.197 -2.66 42.954 -2.66 c
+43.646 0.53 m
+43.646 0.742 43.619 0.919 43.572 1.058 c
+43.532 1.205 43.476 1.323 43.41 1.411 c
+43.351 1.5 43.282 1.558 43.204 1.588 c
+43.123 1.625 43.046 1.646 42.969 1.646 c
+42.87 1.646 42.778 1.621 42.69 1.573 c
+42.609 1.532 42.543 1.463 42.484 1.367 c
+42.433 1.279 42.389 1.162 42.352 1.014 c
+42.323 0.875 42.308 0.706 42.308 0.5 c
+42.308 0.125 42.366 -0.154 42.484 -0.338 c
+42.601 -0.515 42.763 -0.602 42.969 -0.602 c
+43.035 -0.602 43.109 -0.588 43.189 -0.559 c
+43.278 -0.522 43.351 -0.463 43.41 -0.382 c
+43.476 -0.294 43.532 -0.176 43.572 -0.029 c
+43.619 0.118 43.646 0.301 43.646 0.53 c
+f
+Q
+q 1 0 0 1 60.7924 321.0066 cm
+0 0 m
+2.102 0 l
+2.102 -0.574 l
+-0.676 -0.574 l
+-0.676 4.777 l
+0 4.777 l
+h
+3.513 -0.574 -0.646 3.984 re
+3.557 4.453 m
+3.557 4.343 3.528 4.251 3.469 4.174 c
+3.41 4.104 3.314 4.072 3.189 4.072 c
+3.072 4.072 2.977 4.104 2.91 4.174 c
+2.851 4.251 2.822 4.343 2.822 4.453 c
+2.822 4.571 2.851 4.663 2.91 4.733 c
+2.977 4.81 3.072 4.85 3.189 4.85 c
+3.314 4.85 3.41 4.81 3.469 4.733 c
+3.528 4.652 3.557 4.56 3.557 4.453 c
+6.468 0.44 m
+6.468 0.588 6.412 0.709 6.306 0.808 c
+6.196 0.904 5.99 1.022 5.689 1.161 c
+5.342 1.308 5.101 1.429 4.953 1.529 c
+4.806 1.635 4.696 1.753 4.63 1.881 c
+4.56 2.006 4.527 2.164 4.527 2.352 c
+4.527 2.674 4.644 2.944 4.88 3.16 c
+5.115 3.374 5.416 3.484 5.791 3.484 c
+6.173 3.484 6.482 3.37 6.717 3.145 c
+6.952 2.917 7.07 2.631 7.07 2.278 c
+6.423 2.278 l
+6.423 2.454 6.364 2.605 6.247 2.734 c
+6.129 2.859 5.975 2.925 5.791 2.925 c
+5.593 2.925 5.442 2.869 5.336 2.763 c
+5.225 2.664 5.174 2.532 5.174 2.366 c
+5.174 2.238 5.211 2.131 5.292 2.043 c
+5.369 1.962 5.56 1.859 5.865 1.734 c
+6.342 1.547 6.673 1.359 6.85 1.176 c
+7.025 0.999 7.114 0.771 7.114 0.5 c
+7.114 0.147 6.989 -0.133 6.747 -0.339 c
+6.512 -0.544 6.196 -0.647 5.806 -0.647 c
+5.383 -0.647 5.045 -0.53 4.791 -0.294 c
+4.534 -0.052 4.409 0.253 4.409 0.617 c
+5.056 0.617 l
+5.064 0.389 5.134 0.213 5.262 0.087 c
+5.387 -0.03 5.571 -0.088 5.806 -0.088 c
+6.019 -0.088 6.181 -0.04 6.291 0.058 c
+6.408 0.154 6.468 0.282 6.468 0.44 c
+8.804 4.365 m
+8.804 3.41 l
+9.407 3.41 l
+9.407 2.881 l
+8.804 2.881 l
+8.804 0.411 l
+8.804 0.253 8.827 0.135 8.878 0.058 c
+8.937 -0.023 9.025 -0.059 9.142 -0.059 c
+9.231 -0.059 9.319 -0.044 9.407 -0.015 c
+9.407 -0.574 l
+9.26 -0.621 9.105 -0.647 8.951 -0.647 c
+8.694 -0.647 8.5 -0.555 8.363 -0.368 c
+8.224 -0.184 8.158 0.077 8.158 0.411 c
+8.158 2.881 l
+7.555 2.881 l
+7.555 3.41 l
+8.158 3.41 l
+8.158 4.365 l
+h
+11.759 1.602 m
+11.759 2.179 11.895 2.634 12.17 2.969 c
+12.454 3.31 12.825 3.484 13.288 3.484 c
+13.747 3.484 14.115 3.314 14.39 2.984 c
+14.673 2.66 14.82 2.212 14.831 1.646 c
+14.831 1.22 l
+14.831 0.65 14.688 0.195 14.405 -0.148 c
+14.129 -0.482 13.762 -0.647 13.302 -0.647 c
+12.839 -0.647 12.469 -0.485 12.185 -0.162 c
+11.91 0.168 11.766 0.61 11.759 1.161 c
+h
+12.406 1.22 m
+12.406 0.816 12.483 0.5 12.641 0.264 c
+12.806 0.029 13.026 -0.088 13.302 -0.088 c
+13.868 -0.088 14.162 0.323 14.184 1.146 c
+14.184 1.602 l
+14.184 2.003 14.1 2.322 13.934 2.557 c
+13.776 2.8 13.56 2.925 13.288 2.925 c
+13.023 2.925 12.806 2.8 12.641 2.557 c
+12.483 2.322 12.406 2.003 12.406 1.602 c
+h
+18.549 1.22 m
+18.549 0.592 18.432 0.121 18.197 -0.191 c
+17.969 -0.497 17.653 -0.647 17.242 -0.647 c
+16.837 -0.647 16.529 -0.497 16.315 -0.191 c
+16.315 -2.103 l
+15.669 -2.103 l
+15.669 3.41 l
+16.257 3.41 l
+16.301 2.969 l
+16.514 3.31 16.823 3.484 17.227 3.484 c
+17.668 3.484 17.995 3.329 18.212 3.027 c
+18.425 2.722 18.539 2.267 18.549 1.66 c
+h
+17.903 1.602 m
+17.903 2.043 17.834 2.366 17.697 2.572 c
+17.558 2.786 17.337 2.896 17.036 2.896 c
+16.72 2.896 16.481 2.741 16.315 2.439 c
+16.315 0.367 l
+16.481 0.062 16.72 -0.088 17.036 -0.088 c
+17.33 -0.088 17.543 0.014 17.683 0.22 c
+17.819 0.434 17.892 0.764 17.903 1.205 c
+h
+20.814 -0.647 m
+20.313 -0.647 19.931 -0.5 19.667 -0.206 c
+19.403 0.087 19.27 0.521 19.27 1.103 c
+19.27 1.573 l
+19.27 2.167 19.395 2.634 19.652 2.969 c
+19.917 3.31 20.277 3.484 20.74 3.484 c
+21.2 3.484 21.541 3.329 21.769 3.027 c
+22.004 2.734 22.125 2.271 22.137 1.646 c
+22.137 1.22 l
+19.917 1.22 l
+19.917 1.132 l
+19.917 0.698 19.994 0.386 20.153 0.191 c
+20.317 0.004 20.549 -0.088 20.843 -0.088 c
+21.038 -0.088 21.211 -0.055 21.358 0.014 c
+21.504 0.091 21.641 0.209 21.769 0.367 c
+22.107 -0.044 l
+21.82 -0.449 21.391 -0.647 20.814 -0.647 c
+20.74 2.925 m
+20.465 2.925 20.263 2.829 20.137 2.645 c
+20.009 2.458 19.935 2.167 19.917 1.778 c
+21.489 1.778 l
+21.489 1.866 l
+21.468 2.248 21.402 2.516 21.284 2.674 c
+21.167 2.84 20.982 2.925 20.74 2.925 c
+24.562 2.792 m
+24.473 2.811 24.375 2.822 24.268 2.822 c
+23.933 2.822 23.698 2.638 23.563 2.278 c
+23.563 -0.574 l
+22.915 -0.574 l
+22.915 3.41 l
+23.548 3.41 l
+23.563 2.998 l
+23.739 3.322 23.981 3.484 24.297 3.484 c
+24.404 3.484 24.492 3.461 24.562 3.424 c
+h
+27.105 -0.574 m
+27.064 -0.485 27.039 -0.339 27.031 -0.133 c
+26.796 -0.478 26.503 -0.647 26.15 -0.647 c
+25.786 -0.647 25.503 -0.551 25.296 -0.353 c
+25.098 -0.148 25.003 0.139 25.003 0.515 c
+25.003 0.914 25.138 1.234 25.414 1.469 c
+25.686 1.712 26.061 1.837 26.532 1.837 c
+27.016 1.837 l
+27.016 2.263 l
+27.016 2.499 26.962 2.664 26.855 2.763 c
+26.744 2.869 26.582 2.925 26.37 2.925 c
+26.171 2.925 26.01 2.866 25.884 2.749 c
+25.767 2.631 25.709 2.484 25.709 2.308 c
+25.061 2.308 l
+25.061 2.502 25.121 2.693 25.238 2.881 c
+25.363 3.064 25.525 3.212 25.723 3.322 c
+25.929 3.428 26.156 3.484 26.414 3.484 c
+26.815 3.484 27.12 3.38 27.326 3.175 c
+27.538 2.969 27.652 2.674 27.663 2.293 c
+27.663 0.279 l
+27.663 -0.026 27.7 -0.291 27.781 -0.515 c
+27.781 -0.574 l
+h
+26.237 -0.059 m
+26.403 -0.059 26.553 -0.015 26.693 0.073 c
+26.84 0.162 26.947 0.272 27.016 0.411 c
+27.016 1.352 l
+26.649 1.352 l
+26.333 1.352 26.09 1.282 25.915 1.146 c
+25.738 1.018 25.649 0.83 25.649 0.588 c
+25.649 0.359 25.693 0.195 25.782 0.087 c
+25.87 -0.011 26.021 -0.059 26.237 -0.059 c
+29.516 4.365 m
+29.516 3.41 l
+30.118 3.41 l
+30.118 2.881 l
+29.516 2.881 l
+29.516 0.411 l
+29.516 0.253 29.537 0.135 29.589 0.058 c
+29.647 -0.023 29.736 -0.059 29.853 -0.059 c
+29.942 -0.059 30.03 -0.044 30.118 -0.015 c
+30.118 -0.574 l
+29.971 -0.621 29.817 -0.647 29.662 -0.647 c
+29.405 -0.647 29.21 -0.555 29.074 -0.368 c
+28.934 -0.184 28.868 0.077 28.868 0.411 c
+28.868 2.881 l
+28.266 2.881 l
+28.266 3.41 l
+28.868 3.41 l
+28.868 4.365 l
+h
+31.588 -0.574 -0.647 3.984 re
+31.632 4.453 m
+31.632 4.343 31.602 4.251 31.544 4.174 c
+31.485 4.104 31.39 4.072 31.265 4.072 c
+31.147 4.072 31.051 4.104 30.985 4.174 c
+30.927 4.251 30.897 4.343 30.897 4.453 c
+30.897 4.571 30.927 4.663 30.985 4.733 c
+31.051 4.81 31.147 4.85 31.265 4.85 c
+31.39 4.85 31.485 4.81 31.544 4.733 c
+31.602 4.652 31.632 4.56 31.632 4.453 c
+32.47 1.602 m
+32.47 2.179 32.606 2.634 32.882 2.969 c
+33.165 3.31 33.535 3.484 33.998 3.484 c
+34.458 3.484 34.825 3.314 35.101 2.984 c
+35.384 2.66 35.531 2.212 35.542 1.646 c
+35.542 1.22 l
+35.542 0.65 35.399 0.195 35.116 -0.148 c
+34.84 -0.482 34.472 -0.647 34.013 -0.647 c
+33.551 -0.647 33.179 -0.485 32.896 -0.162 c
+32.62 0.168 32.477 0.61 32.47 1.161 c
+h
+33.117 1.22 m
+33.117 0.816 33.194 0.5 33.352 0.264 c
+33.518 0.029 33.738 -0.088 34.013 -0.088 c
+34.579 -0.088 34.873 0.323 34.895 1.146 c
+34.895 1.602 l
+34.895 2.003 34.811 2.322 34.646 2.557 c
+34.488 2.8 34.27 2.925 33.998 2.925 c
+33.734 2.925 33.518 2.8 33.352 2.557 c
+33.194 2.322 33.117 2.003 33.117 1.602 c
+h
+36.997 3.41 m
+37.012 2.969 l
+37.266 3.31 37.589 3.484 37.982 3.484 c
+38.688 3.484 39.044 3.013 39.055 2.072 c
+39.055 -0.574 l
+38.409 -0.574 l
+38.409 2.043 l
+38.409 2.356 38.353 2.576 38.247 2.705 c
+38.137 2.829 37.982 2.896 37.776 2.896 c
+37.618 2.896 37.472 2.84 37.335 2.734 c
+37.206 2.624 37.104 2.487 37.027 2.322 c
+37.027 -0.574 l
+36.38 -0.574 l
+36.38 3.41 l
+h
+41.965 0.44 m
+41.965 0.588 41.91 0.709 41.804 0.808 c
+41.694 0.904 41.488 1.022 41.187 1.161 c
+40.841 1.308 40.599 1.429 40.452 1.529 c
+40.304 1.635 40.194 1.753 40.128 1.881 c
+40.059 2.006 40.026 2.164 40.026 2.352 c
+40.026 2.674 40.143 2.944 40.378 3.16 c
+40.614 3.374 40.915 3.484 41.289 3.484 c
+41.672 3.484 41.98 3.37 42.216 3.145 c
+42.451 2.917 42.568 2.631 42.568 2.278 c
+41.921 2.278 l
+41.921 2.454 41.863 2.605 41.745 2.734 c
+41.628 2.859 41.473 2.925 41.289 2.925 c
+41.091 2.925 40.94 2.869 40.834 2.763 c
+40.724 2.664 40.672 2.532 40.672 2.366 c
+40.672 2.238 40.709 2.131 40.79 2.043 c
+40.867 1.962 41.058 1.859 41.362 1.734 c
+41.84 1.547 42.171 1.359 42.347 1.176 c
+42.524 0.999 42.613 0.771 42.613 0.5 c
+42.613 0.147 42.488 -0.133 42.245 -0.339 c
+42.01 -0.544 41.694 -0.647 41.304 -0.647 c
+40.882 -0.647 40.543 -0.53 40.29 -0.294 c
+40.032 -0.052 39.908 0.253 39.908 0.617 c
+40.554 0.617 l
+40.562 0.389 40.631 0.213 40.76 0.087 c
+40.885 -0.03 41.069 -0.088 41.304 -0.088 c
+41.518 -0.088 41.679 -0.04 41.79 0.058 c
+41.907 0.154 41.965 0.282 41.965 0.44 c
+45.156 1.602 m
+45.156 2.238 45.243 2.84 45.42 3.41 c
+45.596 3.976 45.838 4.472 46.155 4.895 c
+46.349 5.159 46.536 5.35 46.713 5.468 c
+46.846 5.012 l
+46.552 4.737 46.309 4.314 46.125 3.748 c
+45.938 3.179 45.835 2.547 45.817 1.851 c
+45.817 1.558 l
+45.817 0.694 45.934 -0.071 46.17 -0.736 c
+46.353 -1.235 46.581 -1.617 46.846 -1.881 c
+46.713 -2.308 l
+46.486 -2.15 46.261 -1.9 46.037 -1.559 c
+45.449 -0.676 45.156 0.374 45.156 1.602 c
+48.242 -0.574 -0.647 5.644 re
+49.962 -0.574 -0.646 3.984 re
+50.006 4.453 m
+50.006 4.343 49.977 4.251 49.918 4.174 c
+49.859 4.104 49.763 4.072 49.638 4.072 c
+49.521 4.072 49.426 4.104 49.359 4.174 c
+49.3 4.251 49.271 4.343 49.271 4.453 c
+49.271 4.571 49.3 4.663 49.359 4.733 c
+49.426 4.81 49.521 4.85 49.638 4.85 c
+49.763 4.85 49.859 4.81 49.918 4.733 c
+49.977 4.652 50.006 4.56 50.006 4.453 c
+51.976 1.249 m
+51.637 0.852 l
+51.637 -0.574 l
+50.976 -0.574 l
+50.976 5.071 l
+51.637 5.071 l
+51.637 1.691 l
+52.872 3.41 l
+53.651 3.41 l
+52.387 1.749 l
+53.813 -0.574 l
+53.063 -0.574 l
+h
+55.724 -0.647 m
+55.224 -0.647 54.842 -0.5 54.577 -0.206 c
+54.313 0.087 54.18 0.521 54.18 1.103 c
+54.18 1.573 l
+54.18 2.167 54.305 2.634 54.563 2.969 c
+54.827 3.31 55.188 3.484 55.65 3.484 c
+56.109 3.484 56.451 3.329 56.68 3.027 c
+56.915 2.734 57.036 2.271 57.046 1.646 c
+57.046 1.22 l
+54.827 1.22 l
+54.827 1.132 l
+54.827 0.698 54.904 0.386 55.062 0.191 c
+55.228 0.004 55.459 -0.088 55.753 -0.088 c
+55.948 -0.088 56.121 -0.055 56.268 0.014 c
+56.414 0.091 56.551 0.209 56.68 0.367 c
+57.017 -0.044 l
+56.73 -0.449 56.3 -0.647 55.724 -0.647 c
+55.65 2.925 m
+55.375 2.925 55.172 2.829 55.047 2.645 c
+54.919 2.458 54.845 2.167 54.827 1.778 c
+56.4 1.778 l
+56.4 1.866 l
+56.378 2.248 56.312 2.516 56.194 2.674 c
+56.077 2.84 55.893 2.925 55.65 2.925 c
+60.927 -0.088 m
+61.141 -0.088 61.313 -0.026 61.442 0.103 c
+61.578 0.239 61.651 0.43 61.663 0.675 c
+62.28 0.675 l
+62.257 0.294 62.122 -0.026 61.868 -0.279 c
+61.611 -0.526 61.299 -0.647 60.927 -0.647 c
+60.435 -0.647 60.06 -0.497 59.795 -0.191 c
+59.538 0.121 59.413 0.588 59.413 1.205 c
+59.413 1.646 l
+59.413 2.241 59.538 2.697 59.795 3.013 c
+60.06 3.326 60.435 3.484 60.927 3.484 c
+61.328 3.484 61.648 3.351 61.883 3.087 c
+62.125 2.829 62.257 2.484 62.28 2.043 c
+61.663 2.043 l
+61.64 2.337 61.567 2.557 61.442 2.705 c
+61.324 2.851 61.152 2.925 60.927 2.925 c
+60.633 2.925 60.416 2.826 60.281 2.631 c
+60.141 2.443 60.067 2.135 60.06 1.705 c
+60.06 1.19 l
+60.06 0.72 60.126 0.386 60.266 0.191 c
+60.412 0.004 60.633 -0.088 60.927 -0.088 c
+63.676 2.998 m
+63.93 3.322 64.25 3.484 64.632 3.484 c
+65.337 3.484 65.694 3.013 65.704 2.072 c
+65.704 -0.574 l
+65.058 -0.574 l
+65.058 2.043 l
+65.058 2.356 65.002 2.576 64.896 2.705 c
+64.786 2.829 64.632 2.896 64.426 2.896 c
+64.268 2.896 64.121 2.84 63.984 2.734 c
+63.856 2.624 63.753 2.487 63.676 2.322 c
+63.676 -0.574 l
+63.03 -0.574 l
+63.03 5.071 l
+63.676 5.071 l
+h
+68.086 -0.647 m
+67.586 -0.647 67.204 -0.5 66.939 -0.206 c
+66.675 0.087 66.542 0.521 66.542 1.103 c
+66.542 1.573 l
+66.542 2.167 66.667 2.634 66.924 2.969 c
+67.189 3.31 67.549 3.484 68.013 3.484 c
+68.472 3.484 68.813 3.329 69.041 3.027 c
+69.276 2.734 69.397 2.271 69.409 1.646 c
+69.409 1.22 l
+67.189 1.22 l
+67.189 1.132 l
+67.189 0.698 67.267 0.386 67.425 0.191 c
+67.589 0.004 67.821 -0.088 68.115 -0.088 c
+68.31 -0.088 68.483 -0.055 68.63 0.014 c
+68.777 0.091 68.913 0.209 69.041 0.367 c
+69.38 -0.044 l
+69.093 -0.449 68.663 -0.647 68.086 -0.647 c
+68.013 2.925 m
+67.737 2.925 67.535 2.829 67.41 2.645 c
+67.281 2.458 67.207 2.167 67.189 1.778 c
+68.761 1.778 l
+68.761 1.866 l
+68.74 2.248 68.674 2.516 68.556 2.674 c
+68.439 2.84 68.254 2.925 68.013 2.925 c
+71.57 -0.088 m
+71.782 -0.088 71.955 -0.026 72.084 0.103 c
+72.22 0.239 72.293 0.43 72.304 0.675 c
+72.921 0.675 l
+72.9 0.294 72.763 -0.026 72.51 -0.279 c
+72.253 -0.526 71.94 -0.647 71.57 -0.647 c
+71.077 -0.647 70.702 -0.497 70.438 -0.191 c
+70.18 0.121 70.055 0.588 70.055 1.205 c
+70.055 1.646 l
+70.055 2.241 70.18 2.697 70.438 3.013 c
+70.702 3.326 71.077 3.484 71.57 3.484 c
+71.97 3.484 72.289 3.351 72.524 3.087 c
+72.767 2.829 72.9 2.484 72.921 2.043 c
+72.304 2.043 l
+72.283 2.337 72.208 2.557 72.084 2.705 c
+71.967 2.851 71.793 2.925 71.57 2.925 c
+71.275 2.925 71.059 2.826 70.922 2.631 c
+70.783 2.443 70.71 2.135 70.702 1.705 c
+70.702 1.19 l
+70.702 0.72 70.768 0.386 70.908 0.191 c
+71.055 0.004 71.275 -0.088 71.57 -0.088 c
+74.671 1.249 m
+74.333 0.852 l
+74.333 -0.574 l
+73.671 -0.574 l
+73.671 5.071 l
+74.333 5.071 l
+74.333 1.691 l
+75.568 3.41 l
+76.347 3.41 l
+75.082 1.749 l
+76.508 -0.574 l
+75.759 -0.574 l
+h
+76.935 1.602 m
+76.935 2.179 77.07 2.634 77.346 2.969 c
+77.629 3.31 78 3.484 78.463 3.484 c
+78.922 3.484 79.29 3.314 79.566 2.984 c
+79.849 2.66 79.996 2.212 80.007 1.646 c
+80.007 1.22 l
+80.007 0.65 79.863 0.195 79.58 -0.148 c
+79.304 -0.482 78.937 -0.647 78.478 -0.647 c
+78.015 -0.647 77.644 -0.485 77.361 -0.162 c
+77.085 0.168 76.942 0.61 76.935 1.161 c
+h
+77.581 1.22 m
+77.581 0.816 77.658 0.5 77.816 0.264 c
+77.982 0.029 78.203 -0.088 78.478 -0.088 c
+79.044 -0.088 79.338 0.323 79.36 1.146 c
+79.36 1.602 l
+79.36 2.003 79.275 2.322 79.11 2.557 c
+78.952 2.8 78.735 2.925 78.463 2.925 c
+78.199 2.925 77.982 2.8 77.816 2.557 c
+77.658 2.322 77.581 2.003 77.581 1.602 c
+h
+82.873 -0.221 m
+82.656 -0.507 82.344 -0.647 81.932 -0.647 c
+81.569 -0.647 81.293 -0.526 81.109 -0.279 c
+80.933 -0.026 80.837 0.338 80.83 0.808 c
+80.83 3.41 l
+81.477 3.41 l
+81.477 0.867 l
+81.477 0.239 81.66 -0.073 82.035 -0.073 c
+82.436 -0.073 82.712 0.103 82.858 0.455 c
+82.858 3.41 l
+83.505 3.41 l
+83.505 -0.574 l
+82.888 -0.574 l
+h
+85.342 4.365 m
+85.342 3.41 l
+85.945 3.41 l
+85.945 2.881 l
+85.342 2.881 l
+85.342 0.411 l
+85.342 0.253 85.365 0.135 85.416 0.058 c
+85.475 -0.023 85.563 -0.059 85.681 -0.059 c
+85.769 -0.059 85.857 -0.044 85.945 -0.015 c
+85.945 -0.574 l
+85.798 -0.621 85.644 -0.647 85.49 -0.647 c
+85.232 -0.647 85.037 -0.555 84.902 -0.368 c
+84.762 -0.184 84.696 0.077 84.696 0.411 c
+84.696 2.881 l
+84.093 2.881 l
+84.093 3.41 l
+84.696 3.41 l
+84.696 4.365 l
+h
+88.65 0.44 m
+88.65 0.588 88.594 0.709 88.488 0.808 c
+88.378 0.904 88.172 1.022 87.871 1.161 c
+87.525 1.308 87.283 1.429 87.136 1.529 c
+86.988 1.635 86.878 1.753 86.812 1.881 c
+86.743 2.006 86.71 2.164 86.71 2.352 c
+86.71 2.674 86.827 2.944 87.063 3.16 c
+87.298 3.374 87.599 3.484 87.973 3.484 c
+88.356 3.484 88.665 3.37 88.9 3.145 c
+89.135 2.917 89.253 2.631 89.253 2.278 c
+88.605 2.278 l
+88.605 2.454 88.547 2.605 88.429 2.734 c
+88.312 2.859 88.158 2.925 87.973 2.925 c
+87.775 2.925 87.624 2.869 87.518 2.763 c
+87.408 2.664 87.356 2.532 87.356 2.366 c
+87.356 2.238 87.393 2.131 87.474 2.043 c
+87.551 1.962 87.742 1.859 88.047 1.734 c
+88.525 1.547 88.856 1.359 89.032 1.176 c
+89.208 0.999 89.297 0.771 89.297 0.5 c
+89.297 0.147 89.172 -0.133 88.929 -0.339 c
+88.694 -0.544 88.378 -0.647 87.988 -0.647 c
+87.566 -0.647 87.227 -0.53 86.974 -0.294 c
+86.716 -0.052 86.592 0.253 86.592 0.617 c
+87.239 0.617 l
+87.246 0.389 87.316 0.213 87.445 0.087 c
+87.57 -0.03 87.753 -0.088 87.988 -0.088 c
+88.201 -0.088 88.363 -0.04 88.474 0.058 c
+88.591 0.154 88.65 0.282 88.65 0.44 c
+90.149 -1.646 m
+89.752 -1.382 l
+89.987 -1.058 90.109 -0.724 90.12 -0.383 c
+90.12 0.235 l
+90.781 0.235 l
+90.781 -0.294 l
+90.781 -0.551 90.715 -0.798 90.59 -1.044 c
+90.473 -1.287 90.325 -1.488 90.149 -1.646 c
+94.72 -0.088 m
+94.934 -0.088 95.106 -0.026 95.235 0.103 c
+95.371 0.239 95.445 0.43 95.455 0.675 c
+96.073 0.675 l
+96.05 0.294 95.915 -0.026 95.661 -0.279 c
+95.404 -0.526 95.092 -0.647 94.72 -0.647 c
+94.228 -0.647 93.853 -0.497 93.589 -0.191 c
+93.332 0.121 93.207 0.588 93.207 1.205 c
+93.207 1.646 l
+93.207 2.241 93.332 2.697 93.589 3.013 c
+93.853 3.326 94.228 3.484 94.72 3.484 c
+95.121 3.484 95.441 3.351 95.676 3.087 c
+95.919 2.829 96.05 2.484 96.073 2.043 c
+95.455 2.043 l
+95.433 2.337 95.36 2.557 95.235 2.705 c
+95.117 2.851 94.944 2.925 94.72 2.925 c
+94.427 2.925 94.209 2.826 94.074 2.631 c
+93.934 2.443 93.86 2.135 93.853 1.705 c
+93.853 1.19 l
+93.853 0.72 93.92 0.386 94.059 0.191 c
+94.206 0.004 94.427 -0.088 94.72 -0.088 c
+96.69 1.602 m
+96.69 2.179 96.826 2.634 97.101 2.969 c
+97.384 3.31 97.756 3.484 98.219 3.484 c
+98.678 3.484 99.046 3.314 99.321 2.984 c
+99.605 2.66 99.751 2.212 99.763 1.646 c
+99.763 1.22 l
+99.763 0.65 99.619 0.195 99.335 -0.148 c
+99.06 -0.482 98.693 -0.647 98.234 -0.647 c
+97.77 -0.647 97.399 -0.485 97.116 -0.162 c
+96.841 0.168 96.698 0.61 96.69 1.161 c
+h
+97.336 1.22 m
+97.336 0.816 97.414 0.5 97.572 0.264 c
+97.737 0.029 97.958 -0.088 98.234 -0.088 c
+98.799 -0.088 99.094 0.323 99.115 1.146 c
+99.115 1.602 l
+99.115 2.003 99.031 2.322 98.865 2.557 c
+98.707 2.8 98.491 2.925 98.219 2.925 c
+97.954 2.925 97.737 2.8 97.572 2.557 c
+97.414 2.322 97.336 2.003 97.336 1.602 c
+h
+101.217 3.41 m
+101.232 3.042 l
+101.475 3.337 101.795 3.484 102.188 3.484 c
+102.628 3.484 102.938 3.285 103.114 2.896 c
+103.368 3.285 103.717 3.484 104.157 3.484 c
+104.892 3.484 105.267 3.021 105.289 2.102 c
+105.289 -0.574 l
+104.642 -0.574 l
+104.642 2.043 l
+104.642 2.337 104.587 2.55 104.48 2.69 c
+104.382 2.826 104.209 2.896 103.966 2.896 c
+103.767 2.896 103.606 2.815 103.481 2.66 c
+103.364 2.514 103.293 2.322 103.275 2.087 c
+103.275 -0.574 l
+102.614 -0.574 l
+102.614 2.072 l
+102.614 2.62 102.393 2.896 101.953 2.896 c
+101.618 2.896 101.383 2.734 101.247 2.41 c
+101.247 -0.574 l
+100.6 -0.574 l
+100.6 3.41 l
+h
+106.876 3.41 m
+106.892 3.042 l
+107.134 3.337 107.453 3.484 107.846 3.484 c
+108.288 3.484 108.596 3.285 108.773 2.896 c
+109.026 3.285 109.375 3.484 109.816 3.484 c
+110.551 3.484 110.926 3.021 110.948 2.102 c
+110.948 -0.574 l
+110.302 -0.574 l
+110.302 2.043 l
+110.302 2.337 110.246 2.55 110.14 2.69 c
+110.04 2.826 109.868 2.896 109.625 2.896 c
+109.427 2.896 109.265 2.815 109.14 2.66 c
+109.022 2.514 108.953 2.322 108.935 2.087 c
+108.935 -0.574 l
+108.273 -0.574 l
+108.273 2.072 l
+108.273 2.62 108.052 2.896 107.611 2.896 c
+107.277 2.896 107.042 2.734 106.906 2.41 c
+106.906 -0.574 l
+106.259 -0.574 l
+106.259 3.41 l
+h
+112.623 -0.574 -0.646 3.984 re
+112.668 4.453 m
+112.668 4.343 112.638 4.251 112.58 4.174 c
+112.521 4.104 112.425 4.072 112.301 4.072 c
+112.183 4.072 112.087 4.104 112.021 4.174 c
+111.962 4.251 111.933 4.343 111.933 4.453 c
+111.933 4.571 111.962 4.663 112.021 4.733 c
+112.087 4.81 112.183 4.85 112.301 4.85 c
+112.425 4.85 112.521 4.81 112.58 4.733 c
+112.638 4.652 112.668 4.56 112.668 4.453 c
+114.491 4.365 m
+114.491 3.41 l
+115.093 3.41 l
+115.093 2.881 l
+114.491 2.881 l
+114.491 0.411 l
+114.491 0.253 114.512 0.135 114.564 0.058 c
+114.622 -0.023 114.711 -0.059 114.829 -0.059 c
+114.917 -0.059 115.005 -0.044 115.093 -0.015 c
+115.093 -0.574 l
+114.946 -0.621 114.792 -0.647 114.638 -0.647 c
+114.381 -0.647 114.186 -0.555 114.05 -0.368 c
+113.91 -0.184 113.844 0.077 113.844 0.411 c
+113.844 2.881 l
+113.242 2.881 l
+113.242 3.41 l
+113.844 3.41 l
+113.844 4.365 l
+h
+117.798 0.44 m
+117.798 0.588 117.743 0.709 117.637 0.808 c
+117.526 0.904 117.321 1.022 117.019 1.161 c
+116.673 1.308 116.431 1.429 116.284 1.529 c
+116.137 1.635 116.027 1.753 115.96 1.881 c
+115.891 2.006 115.858 2.164 115.858 2.352 c
+115.858 2.674 115.975 2.944 116.21 3.16 c
+116.446 3.374 116.747 3.484 117.122 3.484 c
+117.504 3.484 117.813 3.37 118.048 3.145 c
+118.283 2.917 118.401 2.631 118.401 2.278 c
+117.754 2.278 l
+117.754 2.454 117.695 2.605 117.577 2.734 c
+117.46 2.859 117.305 2.925 117.122 2.925 c
+116.924 2.925 116.773 2.869 116.666 2.763 c
+116.556 2.664 116.504 2.532 116.504 2.366 c
+116.504 2.238 116.542 2.131 116.622 2.043 c
+116.699 1.962 116.891 1.859 117.195 1.734 c
+117.673 1.547 118.004 1.359 118.18 1.176 c
+118.356 0.999 118.445 0.771 118.445 0.5 c
+118.445 0.147 118.32 -0.133 118.077 -0.339 c
+117.842 -0.544 117.526 -0.647 117.136 -0.647 c
+116.714 -0.647 116.376 -0.53 116.122 -0.294 c
+115.865 -0.052 115.74 0.253 115.74 0.617 c
+116.386 0.617 l
+116.394 0.389 116.464 0.213 116.592 0.087 c
+116.718 -0.03 116.901 -0.088 117.136 -0.088 c
+117.35 -0.088 117.512 -0.04 117.622 0.058 c
+117.739 0.154 117.798 0.282 117.798 0.44 c
+122.428 -0.647 m
+121.928 -0.647 121.546 -0.5 121.282 -0.206 c
+121.017 0.087 120.885 0.521 120.885 1.103 c
+120.885 1.573 l
+120.885 2.167 121.01 2.634 121.267 2.969 c
+121.531 3.31 121.892 3.484 122.354 3.484 c
+122.814 3.484 123.156 3.329 123.384 3.027 c
+123.619 2.734 123.74 2.271 123.751 1.646 c
+123.751 1.22 l
+121.531 1.22 l
+121.531 1.132 l
+121.531 0.698 121.608 0.386 121.766 0.191 c
+121.932 0.004 122.163 -0.088 122.458 -0.088 c
+122.653 -0.088 122.825 -0.055 122.972 0.014 c
+123.119 0.091 123.255 0.209 123.384 0.367 c
+123.721 -0.044 l
+123.435 -0.449 123.005 -0.647 122.428 -0.647 c
+122.354 2.925 m
+122.079 2.925 121.877 2.829 121.752 2.645 c
+121.623 2.458 121.55 2.167 121.531 1.778 c
+123.104 1.778 l
+123.104 1.866 l
+123.083 2.248 123.016 2.516 122.898 2.674 c
+122.781 2.84 122.597 2.925 122.354 2.925 c
+125.383 4.365 m
+125.383 3.41 l
+125.986 3.41 l
+125.986 2.881 l
+125.383 2.881 l
+125.383 0.411 l
+125.383 0.253 125.404 0.135 125.456 0.058 c
+125.515 -0.023 125.603 -0.059 125.72 -0.059 c
+125.809 -0.059 125.897 -0.044 125.986 -0.015 c
+125.986 -0.574 l
+125.838 -0.621 125.684 -0.647 125.529 -0.647 c
+125.273 -0.647 125.078 -0.555 124.941 -0.368 c
+124.802 -0.184 124.735 0.077 124.735 0.411 c
+124.735 2.881 l
+124.133 2.881 l
+124.133 3.41 l
+124.735 3.41 l
+124.735 4.365 l
+h
+128.132 -0.088 m
+128.344 -0.088 128.517 -0.026 128.646 0.103 c
+128.782 0.239 128.855 0.43 128.866 0.675 c
+129.483 0.675 l
+129.462 0.294 129.325 -0.026 129.072 -0.279 c
+128.814 -0.526 128.502 -0.647 128.132 -0.647 c
+127.639 -0.647 127.264 -0.497 127 -0.191 c
+126.742 0.121 126.617 0.588 126.617 1.205 c
+126.617 1.646 l
+126.617 2.241 126.742 2.697 127 3.013 c
+127.264 3.326 127.639 3.484 128.132 3.484 c
+128.532 3.484 128.851 3.351 129.086 3.087 c
+129.329 2.829 129.462 2.484 129.483 2.043 c
+128.866 2.043 l
+128.845 2.337 128.771 2.557 128.646 2.705 c
+128.529 2.851 128.355 2.925 128.132 2.925 c
+127.837 2.925 127.621 2.826 127.484 2.631 c
+127.345 2.443 127.272 2.135 127.264 1.705 c
+127.264 1.19 l
+127.264 0.72 127.33 0.386 127.47 0.191 c
+127.617 0.004 127.837 -0.088 128.132 -0.088 c
+130.277 -0.221 m
+130.277 -0.103 130.31 -0.008 130.38 0.073 c
+130.447 0.151 130.549 0.191 130.689 0.191 c
+130.836 0.191 130.942 0.151 131.012 0.073 c
+131.089 -0.008 131.13 -0.103 131.13 -0.221 c
+131.13 -0.331 131.089 -0.423 131.012 -0.5 c
+130.942 -0.578 130.836 -0.618 130.689 -0.618 c
+130.549 -0.618 130.447 -0.578 130.38 -0.5 c
+130.31 -0.423 130.277 -0.331 130.277 -0.221 c
+133.614 1.558 m
+133.614 0.47 133.368 -0.497 132.879 -1.338 c
+132.614 -1.786 132.339 -2.11 132.056 -2.308 c
+131.939 -1.881 l
+132.24 -1.588 132.486 -1.135 132.673 -0.53 c
+132.868 0.077 132.967 0.742 132.967 1.469 c
+132.967 1.602 l
+132.967 2.532 132.813 3.366 132.512 4.101 c
+132.342 4.501 132.151 4.821 131.939 5.056 c
+132.056 5.468 l
+132.328 5.28 132.593 4.983 132.849 4.571 c
+133.356 3.719 133.614 2.711 133.614 1.558 c
+136.951 3.41 m
+136.965 3.042 l
+137.208 3.337 137.528 3.484 137.921 3.484 c
+138.362 3.484 138.671 3.285 138.847 2.896 c
+139.101 3.285 139.45 3.484 139.891 3.484 c
+140.625 3.484 141.001 3.021 141.022 2.102 c
+141.022 -0.574 l
+140.375 -0.574 l
+140.375 2.043 l
+140.375 2.337 140.321 2.55 140.214 2.69 c
+140.115 2.826 139.942 2.896 139.7 2.896 c
+139.501 2.896 139.339 2.815 139.214 2.66 c
+139.097 2.514 139.027 2.322 139.008 2.087 c
+139.008 -0.574 l
+138.347 -0.574 l
+138.347 2.072 l
+138.347 2.62 138.127 2.896 137.686 2.896 c
+137.352 2.896 137.117 2.734 136.98 2.41 c
+136.98 -0.574 l
+136.334 -0.574 l
+136.334 3.41 l
+h
+144.036 -0.574 m
+143.995 -0.485 143.97 -0.339 143.962 -0.133 c
+143.727 -0.478 143.433 -0.647 143.08 -0.647 c
+142.717 -0.647 142.434 -0.551 142.228 -0.353 c
+142.029 -0.148 141.934 0.139 141.934 0.515 c
+141.934 0.914 142.07 1.234 142.345 1.469 c
+142.617 1.712 142.992 1.837 143.463 1.837 c
+143.947 1.837 l
+143.947 2.263 l
+143.947 2.499 143.893 2.664 143.785 2.763 c
+143.675 2.869 143.514 2.925 143.301 2.925 c
+143.102 2.925 142.941 2.866 142.816 2.749 c
+142.698 2.631 142.64 2.484 142.64 2.308 c
+141.992 2.308 l
+141.992 2.502 142.052 2.693 142.169 2.881 c
+142.293 3.064 142.455 3.212 142.654 3.322 c
+142.86 3.428 143.087 3.484 143.345 3.484 c
+143.745 3.484 144.051 3.38 144.256 3.175 c
+144.469 2.969 144.583 2.674 144.594 2.293 c
+144.594 0.279 l
+144.594 -0.026 144.631 -0.291 144.712 -0.515 c
+144.712 -0.574 l
+h
+143.168 -0.059 m
+143.334 -0.059 143.484 -0.015 143.625 0.073 c
+143.771 0.162 143.878 0.272 143.947 0.411 c
+143.947 1.352 l
+143.58 1.352 l
+143.264 1.352 143.022 1.282 142.845 1.146 c
+142.669 1.018 142.58 0.83 142.58 0.588 c
+142.58 0.359 142.625 0.195 142.713 0.087 c
+142.801 -0.011 142.952 -0.059 143.168 -0.059 c
+145.462 1.602 m
+145.462 2.208 145.572 2.674 145.8 2.998 c
+146.035 3.322 146.362 3.484 146.785 3.484 c
+147.166 3.484 147.465 3.326 147.681 3.013 c
+147.681 5.071 l
+148.328 5.071 l
+148.328 -0.574 l
+147.74 -0.574 l
+147.696 -0.148 l
+147.49 -0.482 147.185 -0.647 146.785 -0.647 c
+146.372 -0.647 146.05 -0.493 145.815 -0.177 c
+145.579 0.147 145.462 0.602 145.462 1.19 c
+h
+146.108 1.22 m
+146.108 0.779 146.171 0.448 146.299 0.235 c
+146.435 0.029 146.656 -0.073 146.96 -0.073 c
+147.284 -0.073 147.523 0.087 147.681 0.411 c
+147.681 2.425 l
+147.512 2.738 147.273 2.896 146.96 2.896 c
+146.656 2.896 146.435 2.792 146.299 2.587 c
+146.171 2.381 146.108 2.057 146.108 1.616 c
+h
+150.753 -0.647 m
+150.253 -0.647 149.871 -0.5 149.607 -0.206 c
+149.342 0.087 149.21 0.521 149.21 1.103 c
+149.21 1.573 l
+149.21 2.167 149.335 2.634 149.592 2.969 c
+149.857 3.31 150.216 3.484 150.68 3.484 c
+151.139 3.484 151.481 3.329 151.708 3.027 c
+151.944 2.734 152.065 2.271 152.076 1.646 c
+152.076 1.22 l
+149.857 1.22 l
+149.857 1.132 l
+149.857 0.698 149.934 0.386 150.092 0.191 c
+150.257 0.004 150.488 -0.088 150.783 -0.088 c
+150.977 -0.088 151.15 -0.055 151.297 0.014 c
+151.444 0.091 151.58 0.209 151.708 0.367 c
+152.047 -0.044 l
+151.76 -0.449 151.33 -0.647 150.753 -0.647 c
+150.68 2.925 m
+150.404 2.925 150.202 2.829 150.077 2.645 c
+149.948 2.458 149.875 2.167 149.857 1.778 c
+151.429 1.778 l
+151.429 1.866 l
+151.407 2.248 151.341 2.516 151.224 2.674 c
+151.106 2.84 150.922 2.925 150.68 2.925 c
+154.443 1.602 m
+154.443 2.179 154.579 2.634 154.854 2.969 c
+155.137 3.31 155.508 3.484 155.972 3.484 c
+156.431 3.484 156.798 3.314 157.073 2.984 c
+157.357 2.66 157.503 2.212 157.515 1.646 c
+157.515 1.22 l
+157.515 0.65 157.372 0.195 157.088 -0.148 c
+156.813 -0.482 156.445 -0.647 155.986 -0.647 c
+155.523 -0.647 155.151 -0.485 154.869 -0.162 c
+154.594 0.168 154.45 0.61 154.443 1.161 c
+h
+155.089 1.22 m
+155.089 0.816 155.166 0.5 155.325 0.264 c
+155.49 0.029 155.71 -0.088 155.986 -0.088 c
+156.552 -0.088 156.846 0.323 156.868 1.146 c
+156.868 1.602 l
+156.868 2.003 156.784 2.322 156.618 2.557 c
+156.46 2.8 156.244 2.925 155.972 2.925 c
+155.706 2.925 155.49 2.8 155.325 2.557 c
+155.166 2.322 155.089 2.003 155.089 1.602 c
+h
+158.97 3.41 m
+158.985 2.969 l
+159.238 3.31 159.562 3.484 159.955 3.484 c
+160.66 3.484 161.017 3.013 161.028 2.072 c
+161.028 -0.574 l
+160.381 -0.574 l
+160.381 2.043 l
+160.381 2.356 160.326 2.576 160.219 2.705 c
+160.109 2.829 159.955 2.896 159.749 2.896 c
+159.591 2.896 159.444 2.84 159.308 2.734 c
+159.18 2.624 159.076 2.487 158.999 2.322 c
+158.999 -0.574 l
+158.353 -0.574 l
+158.353 3.41 l
+h
+164.423 -0.574 -0.647 5.644 re
+165.305 1.602 m
+165.305 2.179 165.441 2.634 165.717 2.969 c
+166 3.31 166.371 3.484 166.834 3.484 c
+167.294 3.484 167.66 3.314 167.936 2.984 c
+168.219 2.66 168.366 2.212 168.377 1.646 c
+168.377 1.22 l
+168.377 0.65 168.234 0.195 167.951 -0.148 c
+167.676 -0.482 167.308 -0.647 166.849 -0.647 c
+166.386 -0.647 166.014 -0.485 165.732 -0.162 c
+165.456 0.168 165.312 0.61 165.305 1.161 c
+h
+165.952 1.22 m
+165.952 0.816 166.029 0.5 166.187 0.264 c
+166.353 0.029 166.573 -0.088 166.849 -0.088 c
+167.415 -0.088 167.708 0.323 167.731 1.146 c
+167.731 1.602 l
+167.731 2.003 167.646 2.322 167.481 2.557 c
+167.323 2.8 167.106 2.925 166.834 2.925 c
+166.569 2.925 166.353 2.8 166.187 2.557 c
+166.029 2.322 165.952 2.003 165.952 1.602 c
+h
+170.596 -0.088 m
+170.81 -0.088 170.983 -0.026 171.111 0.103 c
+171.247 0.239 171.321 0.43 171.332 0.675 c
+171.949 0.675 l
+171.927 0.294 171.791 -0.026 171.537 -0.279 c
+171.28 -0.526 170.968 -0.647 170.596 -0.647 c
+170.104 -0.647 169.73 -0.497 169.465 -0.191 c
+169.208 0.121 169.083 0.588 169.083 1.205 c
+169.083 1.646 l
+169.083 2.241 169.208 2.697 169.465 3.013 c
+169.73 3.326 170.104 3.484 170.596 3.484 c
+170.997 3.484 171.317 3.351 171.552 3.087 c
+171.795 2.829 171.927 2.484 171.949 2.043 c
+171.332 2.043 l
+171.31 2.337 171.236 2.557 171.111 2.705 c
+170.993 2.851 170.821 2.925 170.596 2.925 c
+170.303 2.925 170.086 2.826 169.95 2.631 c
+169.81 2.443 169.737 2.135 169.73 1.705 c
+169.73 1.19 l
+169.73 0.72 169.796 0.386 169.935 0.191 c
+170.083 0.004 170.303 -0.088 170.596 -0.088 c
+174.742 -0.574 m
+174.702 -0.485 174.676 -0.339 174.669 -0.133 c
+174.434 -0.478 174.139 -0.647 173.787 -0.647 c
+173.422 -0.647 173.14 -0.551 172.934 -0.353 c
+172.736 -0.148 172.64 0.139 172.64 0.515 c
+172.64 0.914 172.776 1.234 173.052 1.469 c
+173.324 1.712 173.698 1.837 174.169 1.837 c
+174.654 1.837 l
+174.654 2.263 l
+174.654 2.499 174.598 2.664 174.492 2.763 c
+174.382 2.869 174.22 2.925 174.007 2.925 c
+173.808 2.925 173.647 2.866 173.522 2.749 c
+173.405 2.631 173.345 2.484 173.345 2.308 c
+172.699 2.308 l
+172.699 2.502 172.757 2.693 172.875 2.881 c
+173 3.064 173.162 3.212 173.36 3.322 c
+173.566 3.428 173.794 3.484 174.051 3.484 c
+174.452 3.484 174.756 3.38 174.962 3.175 c
+175.176 2.969 175.29 2.674 175.3 2.293 c
+175.3 0.279 l
+175.3 -0.026 175.338 -0.291 175.418 -0.515 c
+175.418 -0.574 l
+h
+173.875 -0.059 m
+174.041 -0.059 174.191 -0.015 174.33 0.073 c
+174.477 0.162 174.584 0.272 174.654 0.411 c
+174.654 1.352 l
+174.286 1.352 l
+173.97 1.352 173.728 1.282 173.551 1.146 c
+173.375 1.018 173.287 0.83 173.287 0.588 c
+173.287 0.359 173.331 0.195 173.419 0.087 c
+173.507 -0.011 173.658 -0.059 173.875 -0.059 c
+177.006 -0.574 -0.647 5.644 re
+181.386 2.792 m
+181.297 2.811 181.199 2.822 181.092 2.822 c
+180.757 2.822 180.522 2.638 180.387 2.278 c
+180.387 -0.574 l
+179.74 -0.574 l
+179.74 3.41 l
+180.372 3.41 l
+180.387 2.998 l
+180.563 3.322 180.805 3.484 181.121 3.484 c
+181.228 3.484 181.316 3.461 181.386 3.424 c
+h
+183.385 -0.647 m
+182.885 -0.647 182.503 -0.5 182.238 -0.206 c
+181.974 0.087 181.842 0.521 181.842 1.103 c
+181.842 1.573 l
+181.842 2.167 181.966 2.634 182.224 2.969 c
+182.488 3.31 182.849 3.484 183.312 3.484 c
+183.771 3.484 184.113 3.329 184.341 3.027 c
+184.576 2.734 184.697 2.271 184.708 1.646 c
+184.708 1.22 l
+182.488 1.22 l
+182.488 1.132 l
+182.488 0.698 182.566 0.386 182.724 0.191 c
+182.889 0.004 183.121 -0.088 183.414 -0.088 c
+183.609 -0.088 183.782 -0.055 183.929 0.014 c
+184.076 0.091 184.212 0.209 184.341 0.367 c
+184.678 -0.044 l
+184.391 -0.449 183.962 -0.647 183.385 -0.647 c
+183.312 2.925 m
+183.036 2.925 182.834 2.829 182.709 2.645 c
+182.581 2.458 182.507 2.167 182.488 1.778 c
+184.061 1.778 l
+184.061 1.866 l
+184.04 2.248 183.973 2.516 183.855 2.674 c
+183.738 2.84 183.554 2.925 183.312 2.925 c
+188.368 1.22 m
+188.368 0.592 188.25 0.121 188.015 -0.191 c
+187.788 -0.497 187.471 -0.647 187.059 -0.647 c
+186.656 -0.647 186.347 -0.497 186.134 -0.191 c
+186.134 -2.103 l
+185.487 -2.103 l
+185.487 3.41 l
+186.075 3.41 l
+186.119 2.969 l
+186.332 3.31 186.641 3.484 187.045 3.484 c
+187.487 3.484 187.813 3.329 188.03 3.027 c
+188.243 2.722 188.357 2.267 188.368 1.66 c
+h
+187.722 1.602 m
+187.722 2.043 187.651 2.366 187.516 2.572 c
+187.376 2.786 187.155 2.896 186.854 2.896 c
+186.538 2.896 186.299 2.741 186.134 2.439 c
+186.134 0.367 l
+186.299 0.062 186.538 -0.088 186.854 -0.088 c
+187.148 -0.088 187.361 0.014 187.501 0.22 c
+187.637 0.434 187.71 0.764 187.722 1.205 c
+h
+189.074 1.602 m
+189.074 2.179 189.21 2.634 189.486 2.969 c
+189.768 3.31 190.139 3.484 190.602 3.484 c
+191.061 3.484 191.429 3.314 191.705 2.984 c
+191.988 2.66 192.135 2.212 192.146 1.646 c
+192.146 1.22 l
+192.146 0.65 192.002 0.195 191.72 -0.148 c
+191.444 -0.482 191.076 -0.647 190.617 -0.647 c
+190.154 -0.647 189.783 -0.485 189.5 -0.162 c
+189.224 0.168 189.081 0.61 189.074 1.161 c
+h
+189.721 1.22 m
+189.721 0.816 189.798 0.5 189.956 0.264 c
+190.121 0.029 190.342 -0.088 190.617 -0.088 c
+191.183 -0.088 191.477 0.323 191.499 1.146 c
+191.499 1.602 l
+191.499 2.003 191.414 2.322 191.249 2.557 c
+191.091 2.8 190.874 2.925 190.602 2.925 c
+190.338 2.925 190.121 2.8 189.956 2.557 c
+189.798 2.322 189.721 2.003 189.721 1.602 c
+h
+194.924 0.44 m
+194.924 0.588 194.869 0.709 194.762 0.808 c
+194.652 0.904 194.446 1.022 194.145 1.161 c
+193.799 1.308 193.557 1.429 193.409 1.529 c
+193.263 1.635 193.153 1.753 193.087 1.881 c
+193.016 2.006 192.983 2.164 192.983 2.352 c
+192.983 2.674 193.101 2.944 193.336 3.16 c
+193.571 3.374 193.873 3.484 194.248 3.484 c
+194.63 3.484 194.938 3.37 195.173 3.145 c
+195.409 2.917 195.526 2.631 195.526 2.278 c
+194.88 2.278 l
+194.88 2.454 194.821 2.605 194.703 2.734 c
+194.585 2.859 194.431 2.925 194.248 2.925 c
+194.049 2.925 193.899 2.869 193.792 2.763 c
+193.682 2.664 193.63 2.532 193.63 2.366 c
+193.63 2.238 193.667 2.131 193.748 2.043 c
+193.825 1.962 194.016 1.859 194.321 1.734 c
+194.799 1.547 195.13 1.359 195.306 1.176 c
+195.483 0.999 195.57 0.771 195.57 0.5 c
+195.57 0.147 195.445 -0.133 195.203 -0.339 c
+194.968 -0.544 194.652 -0.647 194.263 -0.647 c
+193.839 -0.647 193.502 -0.53 193.249 -0.294 c
+192.991 -0.052 192.866 0.253 192.866 0.617 c
+193.513 0.617 l
+193.52 0.389 193.59 0.213 193.719 0.087 c
+193.843 -0.03 194.027 -0.088 194.263 -0.088 c
+194.475 -0.088 194.637 -0.04 194.747 0.058 c
+194.865 0.154 194.924 0.282 194.924 0.44 c
+197.114 -0.574 -0.647 3.984 re
+197.158 4.453 m
+197.158 4.343 197.129 4.251 197.07 4.174 c
+197.012 4.104 196.916 4.072 196.79 4.072 c
+196.673 4.072 196.578 4.104 196.511 4.174 c
+196.453 4.251 196.424 4.343 196.424 4.453 c
+196.424 4.571 196.453 4.663 196.511 4.733 c
+196.578 4.81 196.673 4.85 196.79 4.85 c
+196.916 4.85 197.012 4.81 197.07 4.733 c
+197.129 4.652 197.158 4.56 197.158 4.453 c
+198.98 4.365 m
+198.98 3.41 l
+199.584 3.41 l
+199.584 2.881 l
+198.98 2.881 l
+198.98 0.411 l
+198.98 0.253 199.003 0.135 199.054 0.058 c
+199.113 -0.023 199.202 -0.059 199.319 -0.059 c
+199.407 -0.059 199.495 -0.044 199.584 -0.015 c
+199.584 -0.574 l
+199.437 -0.621 199.282 -0.647 199.128 -0.647 c
+198.87 -0.647 198.676 -0.555 198.54 -0.368 c
+198.4 -0.184 198.334 0.077 198.334 0.411 c
+198.334 2.881 l
+197.731 2.881 l
+197.731 3.41 l
+198.334 3.41 l
+198.334 4.365 l
+h
+200.142 1.602 m
+200.142 2.179 200.278 2.634 200.553 2.969 c
+200.837 3.31 201.208 3.484 201.671 3.484 c
+202.13 3.484 202.498 3.314 202.774 2.984 c
+203.056 2.66 203.203 2.212 203.214 1.646 c
+203.214 1.22 l
+203.214 0.65 203.071 0.195 202.788 -0.148 c
+202.512 -0.482 202.145 -0.647 201.685 -0.647 c
+201.222 -0.647 200.852 -0.485 200.568 -0.162 c
+200.293 0.168 200.149 0.61 200.142 1.161 c
+h
+200.789 1.22 m
+200.789 0.816 200.866 0.5 201.024 0.264 c
+201.189 0.029 201.41 -0.088 201.685 -0.088 c
+202.251 -0.088 202.545 0.323 202.568 1.146 c
+202.568 1.602 l
+202.568 2.003 202.483 2.322 202.317 2.557 c
+202.159 2.8 201.943 2.925 201.671 2.925 c
+201.406 2.925 201.189 2.8 201.024 2.557 c
+200.866 2.322 200.789 2.003 200.789 1.602 c
+h
+205.698 2.792 m
+205.61 2.811 205.511 2.822 205.404 2.822 c
+205.07 2.822 204.835 2.638 204.698 2.278 c
+204.698 -0.574 l
+204.052 -0.574 l
+204.052 3.41 l
+204.684 3.41 l
+204.698 2.998 l
+204.875 3.322 205.118 3.484 205.434 3.484 c
+205.54 3.484 205.629 3.461 205.698 3.424 c
+h
+207.506 0.515 m
+208.226 3.41 l
+208.918 3.41 l
+207.624 -1.132 l
+207.524 -1.474 207.381 -1.735 207.198 -1.912 c
+207.021 -2.087 206.819 -2.176 206.595 -2.176 c
+206.506 -2.176 206.393 -2.153 206.257 -2.117 c
+206.257 -1.573 l
+206.404 -1.588 l
+206.587 -1.588 206.734 -1.544 206.845 -1.455 c
+206.951 -1.367 207.04 -1.209 207.109 -0.985 c
+207.227 -0.544 l
+206.066 3.41 l
+206.772 3.41 l
+h
+209.197 -0.221 m
+209.197 -0.103 209.23 -0.008 209.299 0.073 c
+209.365 0.151 209.469 0.191 209.608 0.191 c
+209.755 0.191 209.862 0.151 209.932 0.073 c
+210.009 -0.008 210.049 -0.103 210.049 -0.221 c
+210.049 -0.331 210.009 -0.423 209.932 -0.5 c
+209.862 -0.578 209.755 -0.618 209.608 -0.618 c
+209.469 -0.618 209.365 -0.578 209.299 -0.5 c
+209.23 -0.423 209.197 -0.331 209.197 -0.221 c
+f
+Q
+0.793 0.801 0.129 0.016 k
+287.665 501.669 234.667 -21.46 re
+f
+0 0 0 0 k
+q 1 0 0 1 356.4047 495.6455 cm
+0 0 m
+0 -1.543 l
+-0.103 -1.543 l
+-0.79 -1.554 -1.334 -1.764 -1.735 -2.175 c
+-2.128 -2.579 -2.367 -3.142 -2.454 -3.865 c
+-2.065 -3.418 -1.573 -3.189 -0.985 -3.189 c
+-0.309 -3.189 0.228 -3.484 0.632 -4.072 c
+1.033 -4.652 1.235 -5.42 1.235 -6.379 c
+1.235 -6.996 1.118 -7.551 0.882 -8.04 c
+0.654 -8.533 0.331 -8.914 -0.088 -9.186 c
+-0.5 -9.462 -0.97 -9.598 -1.5 -9.598 c
+-2.352 -9.598 -3.036 -9.26 -3.543 -8.584 c
+-4.054 -7.9 -4.307 -6.978 -4.307 -5.82 c
+-4.307 -5.144 l
+-4.307 -4.116 -4.145 -3.215 -3.821 -2.439 c
+-3.499 -1.657 -3.036 -1.058 -2.425 -0.646 c
+-1.808 -0.228 -1.095 -0.01 -0.279 0 c
+h
+-1.558 -4.704 m
+-1.793 -4.704 -1.992 -4.777 -2.146 -4.924 c
+-2.304 -5.071 -2.421 -5.247 -2.499 -5.453 c
+-2.499 -6.115 l
+-2.499 -6.772 -2.41 -7.268 -2.234 -7.599 c
+-2.057 -7.923 -1.83 -8.084 -1.544 -8.084 c
+-1.249 -8.084 -1.014 -7.93 -0.838 -7.613 c
+-0.661 -7.301 -0.573 -6.894 -0.573 -6.394 c
+-0.573 -5.894 -0.669 -5.49 -0.852 -5.174 c
+-1.029 -4.862 -1.264 -4.704 -1.558 -4.704 c
+2.708 -8.54 m
+2.708 -8.246 2.804 -8.007 3.002 -7.819 c
+3.198 -7.636 3.451 -7.54 3.767 -7.54 c
+4.068 -7.54 4.318 -7.636 4.516 -7.819 c
+4.723 -8.007 4.825 -8.246 4.825 -8.54 c
+4.825 -8.845 4.723 -9.091 4.516 -9.275 c
+4.318 -9.452 4.068 -9.539 3.767 -9.539 c
+3.462 -9.539 3.208 -9.448 3.002 -9.26 c
+2.804 -9.076 2.708 -8.834 2.708 -8.54 c
+15.387 -1.675 m
+13.064 -1.675 l
+13.064 -9.466 l
+11.168 -9.466 l
+11.168 -1.675 l
+8.889 -1.675 l
+8.889 -0.103 l
+15.387 -0.103 l
+h
+20.347 -7.555 m
+17.775 -7.555 l
+17.275 -9.466 l
+15.276 -9.466 l
+18.201 -0.103 l
+19.921 -0.103 l
+22.875 -9.466 l
+20.847 -9.466 l
+h
+18.186 -5.967 m
+19.935 -5.967 l
+19.054 -2.631 l
+h
+30.206 -8.407 m
+29.843 -8.801 29.398 -9.099 28.869 -9.304 c
+28.34 -9.499 27.759 -9.598 27.135 -9.598 c
+26.054 -9.598 25.217 -9.267 24.621 -8.598 c
+24.022 -7.933 23.717 -6.963 23.709 -5.689 c
+23.709 -3.998 l
+23.709 -2.705 23.989 -1.712 24.548 -1.014 c
+25.113 -0.32 25.936 0.03 27.017 0.03 c
+28.035 0.03 28.799 -0.228 29.31 -0.735 c
+29.828 -1.234 30.125 -2.021 30.206 -3.087 c
+28.369 -3.087 l
+28.318 -2.491 28.197 -2.084 28.002 -1.866 c
+27.804 -1.654 27.495 -1.543 27.075 -1.543 c
+26.565 -1.543 26.194 -1.731 25.959 -2.102 c
+25.731 -2.477 25.613 -3.068 25.606 -3.881 c
+25.606 -5.585 l
+25.606 -6.437 25.731 -7.063 25.988 -7.453 c
+26.242 -7.834 26.657 -8.025 27.237 -8.025 c
+27.609 -8.025 27.914 -7.952 28.149 -7.805 c
+28.311 -7.688 l
+28.311 -5.967 l
+26.988 -5.967 l
+26.988 -4.542 l
+30.206 -4.542 l
+h
+38.144 -8.407 m
+37.78 -8.801 37.336 -9.099 36.806 -9.304 c
+36.278 -9.499 35.696 -9.598 35.072 -9.598 c
+33.992 -9.598 33.154 -9.267 32.558 -8.598 c
+31.96 -7.933 31.655 -6.963 31.647 -5.689 c
+31.647 -3.998 l
+31.647 -2.705 31.927 -1.712 32.485 -1.014 c
+33.051 -0.32 33.874 0.03 34.954 0.03 c
+35.972 0.03 36.737 -0.228 37.248 -0.735 c
+37.766 -1.234 38.063 -2.021 38.144 -3.087 c
+36.307 -3.087 l
+36.255 -2.491 36.134 -2.084 35.939 -1.866 c
+35.741 -1.654 35.432 -1.543 35.013 -1.543 c
+34.503 -1.543 34.131 -1.731 33.896 -2.102 c
+33.668 -2.477 33.551 -3.068 33.543 -3.881 c
+33.543 -5.585 l
+33.543 -6.437 33.668 -7.063 33.926 -7.453 c
+34.179 -7.834 34.594 -8.025 35.175 -8.025 c
+35.546 -8.025 35.851 -7.952 36.086 -7.805 c
+36.248 -7.688 l
+36.248 -5.967 l
+34.925 -5.967 l
+34.925 -4.542 l
+38.144 -4.542 l
+h
+41.701 -9.466 -1.896 9.363 re
+49.951 -9.466 m
+48.055 -9.466 l
+45.292 -3.322 l
+45.292 -9.466 l
+43.395 -9.466 l
+43.395 -0.103 l
+45.292 -0.103 l
+48.055 -6.247 l
+48.055 -0.103 l
+49.951 -0.103 l
+h
+58.069 -8.407 m
+57.705 -8.801 57.26 -9.099 56.731 -9.304 c
+56.202 -9.499 55.621 -9.598 54.997 -9.598 c
+53.917 -9.598 53.078 -9.267 52.483 -8.598 c
+51.884 -7.933 51.579 -6.963 51.571 -5.689 c
+51.571 -3.998 l
+51.571 -2.705 51.851 -1.712 52.41 -1.014 c
+52.976 -0.32 53.799 0.03 54.879 0.03 c
+55.897 0.03 56.662 -0.228 57.172 -0.735 c
+57.69 -1.234 57.988 -2.021 58.069 -3.087 c
+56.231 -3.087 l
+56.18 -2.491 56.059 -2.084 55.864 -1.866 c
+55.665 -1.654 55.357 -1.543 54.938 -1.543 c
+54.427 -1.543 54.056 -1.731 53.821 -2.102 c
+53.593 -2.477 53.475 -3.068 53.468 -3.881 c
+53.468 -5.585 l
+53.468 -6.437 53.593 -7.063 53.85 -7.453 c
+54.104 -7.834 54.519 -8.025 55.099 -8.025 c
+55.471 -8.025 55.776 -7.952 56.011 -7.805 c
+56.172 -7.688 l
+56.172 -5.967 l
+54.85 -5.967 l
+54.85 -4.542 l
+58.069 -4.542 l
+h
+65.407 -5.85 m
+64.658 -6.79 l
+64.658 -9.466 l
+62.761 -9.466 l
+62.761 -0.103 l
+64.658 -0.103 l
+64.658 -4.189 l
+65.26 -3.175 l
+66.995 -0.103 l
+69.317 -0.103 l
+66.627 -4.218 l
+69.362 -9.466 l
+67.112 -9.466 l
+h
+76.807 -9.466 m
+74.91 -9.466 l
+72.146 -3.322 l
+72.146 -9.466 l
+70.251 -9.466 l
+70.251 -0.103 l
+72.146 -0.103 l
+74.91 -6.247 l
+74.91 -0.103 l
+76.807 -0.103 l
+h
+85.159 -5.629 m
+85.159 -6.886 84.858 -7.86 84.262 -8.554 c
+83.664 -9.253 82.841 -9.598 81.793 -9.598 c
+80.742 -9.598 79.915 -9.257 79.309 -8.569 c
+78.71 -7.875 78.405 -6.908 78.397 -5.674 c
+78.397 -4.072 l
+78.397 -2.789 78.695 -1.786 79.294 -1.058 c
+79.889 -0.334 80.72 0.03 81.778 0.03 c
+82.814 0.03 83.634 -0.33 84.233 -1.043 c
+84.84 -1.749 85.148 -2.745 85.159 -4.027 c
+h
+83.263 -4.056 m
+83.263 -3.215 83.138 -2.587 82.895 -2.175 c
+82.66 -1.764 82.286 -1.558 81.778 -1.558 c
+81.279 -1.558 80.904 -1.76 80.661 -2.161 c
+80.426 -2.554 80.301 -3.152 80.294 -3.954 c
+80.294 -5.629 l
+80.294 -6.445 80.415 -7.048 80.661 -7.437 c
+80.904 -7.831 81.282 -8.025 81.793 -8.025 c
+82.282 -8.025 82.646 -7.834 82.881 -7.453 c
+83.123 -7.07 83.252 -6.482 83.263 -5.689 c
+h
+92.821 -5.982 m
+93.703 -0.103 l
+95.585 -0.103 l
+93.908 -9.466 l
+92.013 -9.466 l
+90.924 -3.954 l
+89.852 -9.466 l
+87.941 -9.466 l
+86.265 -0.103 l
+88.146 -0.103 l
+89.029 -5.982 l
+90.131 -0.103 l
+91.718 -0.103 l
+h
+103.448 -9.466 m
+101.552 -9.466 l
+98.789 -3.322 l
+98.789 -9.466 l
+96.892 -9.466 l
+96.892 -0.103 l
+98.789 -0.103 l
+101.552 -6.247 l
+101.552 -0.103 l
+103.448 -0.103 l
+h
+114.675 -6.35 m
+114.623 -7.419 114.322 -8.228 113.764 -8.775 c
+113.212 -9.327 112.44 -9.598 111.441 -9.598 c
+110.371 -9.598 109.552 -9.253 108.987 -8.554 c
+108.428 -7.86 108.148 -6.865 108.148 -5.571 c
+108.148 -3.998 l
+108.148 -2.705 108.435 -1.712 109.016 -1.014 c
+109.604 -0.32 110.416 0.03 111.456 0.03 c
+112.474 0.03 113.249 -0.261 113.778 -0.837 c
+114.307 -1.407 114.608 -2.227 114.689 -3.293 c
+112.794 -3.293 l
+112.771 -2.628 112.669 -2.171 112.484 -1.926 c
+112.297 -1.672 111.956 -1.543 111.456 -1.543 c
+110.956 -1.543 110.596 -1.72 110.383 -2.072 c
+110.177 -2.425 110.063 -3.009 110.045 -3.821 c
+110.045 -5.585 l
+110.045 -6.518 110.147 -7.158 110.353 -7.511 c
+110.566 -7.856 110.93 -8.025 111.441 -8.025 c
+111.93 -8.025 112.268 -7.908 112.455 -7.673 c
+112.65 -7.43 112.756 -6.989 112.779 -6.35 c
+h
+122.649 -5.629 m
+122.649 -6.886 122.348 -7.86 121.752 -8.554 c
+121.153 -9.253 120.33 -9.598 119.283 -9.598 c
+118.232 -9.598 117.405 -9.257 116.798 -8.569 c
+116.2 -7.875 115.894 -6.908 115.888 -5.674 c
+115.888 -4.072 l
+115.888 -2.789 116.185 -1.786 116.784 -1.058 c
+117.379 -0.334 118.21 0.03 119.268 0.03 c
+120.305 0.03 121.124 -0.33 121.723 -1.043 c
+122.329 -1.749 122.638 -2.745 122.649 -4.027 c
+h
+120.752 -4.056 m
+120.752 -3.215 120.628 -2.587 120.385 -2.175 c
+120.15 -1.764 119.775 -1.558 119.268 -1.558 c
+118.768 -1.558 118.394 -1.76 118.151 -2.161 c
+117.916 -2.554 117.791 -3.152 117.783 -3.954 c
+117.783 -5.629 l
+117.783 -6.445 117.905 -7.048 118.151 -7.437 c
+118.394 -7.831 118.772 -8.025 119.283 -8.025 c
+119.771 -8.025 120.135 -7.834 120.37 -7.453 c
+120.613 -7.07 120.742 -6.482 120.752 -5.689 c
+h
+126.695 -0.103 m
+128.473 -6.879 l
+130.223 -0.103 l
+132.692 -0.103 l
+132.692 -9.466 l
+130.796 -9.466 l
+130.796 -6.938 l
+130.973 -3.027 l
+129.105 -9.466 l
+127.812 -9.466 l
+125.945 -3.027 l
+126.121 -6.938 l
+126.121 -9.466 l
+124.226 -9.466 l
+124.226 -0.103 l
+h
+136.962 -0.103 m
+138.741 -6.879 l
+140.49 -0.103 l
+142.96 -0.103 l
+142.96 -9.466 l
+141.063 -9.466 l
+141.063 -6.938 l
+141.24 -3.027 l
+139.372 -9.466 l
+138.079 -9.466 l
+136.212 -3.027 l
+136.389 -6.938 l
+136.389 -9.466 l
+134.493 -9.466 l
+134.493 -0.103 l
+h
+146.74 -9.466 -1.896 9.363 re
+154.322 -1.675 m
+151.999 -1.675 l
+151.999 -9.466 l
+150.103 -9.466 l
+150.103 -1.675 l
+147.825 -1.675 l
+147.825 -0.103 l
+154.322 -0.103 l
+h
+159.452 -7.011 m
+159.452 -6.629 159.353 -6.342 159.158 -6.144 c
+158.96 -5.949 158.607 -5.747 158.1 -5.541 c
+157.159 -5.182 156.483 -4.762 156.071 -4.292 c
+155.659 -3.814 155.453 -3.245 155.453 -2.587 c
+155.453 -1.804 155.733 -1.172 156.292 -0.69 c
+156.85 -0.213 157.559 0.03 158.422 0.03 c
+159 0.03 159.515 -0.095 159.966 -0.338 c
+160.415 -0.584 160.76 -0.926 160.995 -1.367 c
+161.238 -1.808 161.362 -2.308 161.362 -2.866 c
+159.481 -2.866 l
+159.481 -2.425 159.386 -2.094 159.202 -1.866 c
+159.014 -1.643 158.746 -1.529 158.393 -1.529 c
+158.059 -1.529 157.798 -1.627 157.614 -1.822 c
+157.438 -2.009 157.35 -2.271 157.35 -2.601 c
+157.35 -2.859 157.452 -3.094 157.659 -3.307 c
+157.865 -3.513 158.224 -3.73 158.746 -3.954 c
+159.658 -4.278 160.319 -4.681 160.731 -5.159 c
+161.15 -5.641 161.362 -6.254 161.362 -6.996 c
+161.362 -7.812 161.102 -8.448 160.583 -8.907 c
+160.062 -9.371 159.357 -9.598 158.467 -9.598 c
+157.857 -9.598 157.306 -9.473 156.806 -9.231 c
+156.313 -8.977 155.928 -8.621 155.644 -8.158 c
+155.358 -7.688 155.218 -7.14 155.218 -6.512 c
+157.115 -6.512 l
+157.115 -7.052 157.217 -7.445 157.423 -7.688 c
+157.636 -7.933 157.986 -8.055 158.467 -8.055 c
+159.121 -8.055 159.452 -7.709 159.452 -7.011 c
+f
+Q
+0.113 0.082 0.09 0 k
+287.665 471.367 234.667 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 464.5277 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.771 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.279 -3.219 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.985 c
+-3.322 2.18 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.003 -2.469 3.043 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.182 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.455 c
+-2.26 2.425 -2.319 2.385 -2.366 2.338 c
+-2.406 2.297 -2.436 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.44 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.014 c
+6.402 -2.66 m
+6.184 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.147 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.596 4.935 -0.411 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.632 5.137 1.779 c
+5.244 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.151 2.22 c
+8.004 2.22 l
+7.993 2.139 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.871 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.279 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.279 5.835 1.162 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.597 1.602 m
+13.053 1.602 l
+13.053 2.22 l
+13.641 2.22 l
+13.92 3.117 l
+14.494 3.117 l
+14.494 2.22 l
+15.728 2.22 l
+15.728 1.602 l
+14.494 1.602 l
+14.494 -0.103 l
+14.494 -0.324 l
+14.501 -0.393 14.523 -0.455 14.552 -0.515 c
+14.589 -0.565 14.645 -0.61 14.714 -0.646 c
+14.791 -0.676 14.905 -0.691 15.052 -0.691 c
+15.188 -0.691 15.324 -0.687 15.464 -0.676 c
+15.599 -0.658 15.732 -0.632 15.861 -0.602 c
+15.861 -1.205 l
+15.78 -1.216 15.703 -1.23 15.626 -1.249 c
+15.545 -1.261 15.468 -1.267 15.391 -1.278 c
+15.31 -1.286 15.221 -1.294 15.125 -1.294 c
+15.038 -1.301 14.938 -1.308 14.832 -1.308 c
+14.645 -1.308 14.483 -1.294 14.346 -1.264 c
+14.218 -1.228 14.104 -1.183 14.009 -1.132 c
+13.92 -1.084 13.847 -1.025 13.788 -0.955 c
+13.729 -0.878 13.685 -0.801 13.656 -0.72 c
+13.627 -0.632 13.604 -0.544 13.597 -0.455 c
+13.586 -0.36 13.582 -0.264 13.582 -0.176 c
+h
+21.722 1.602 m
+21.178 1.602 l
+21.178 2.22 l
+21.766 2.22 l
+22.045 3.117 l
+22.618 3.117 l
+22.618 2.22 l
+23.853 2.22 l
+23.853 1.602 l
+22.618 1.602 l
+22.618 -0.103 l
+22.618 -0.324 l
+22.626 -0.393 22.647 -0.455 22.677 -0.515 c
+22.714 -0.565 22.769 -0.61 22.839 -0.646 c
+22.916 -0.676 23.03 -0.691 23.177 -0.691 c
+23.313 -0.691 23.449 -0.687 23.588 -0.676 c
+23.725 -0.658 23.857 -0.632 23.985 -0.602 c
+23.985 -1.205 l
+23.904 -1.216 23.827 -1.23 23.75 -1.249 c
+23.669 -1.261 23.592 -1.267 23.515 -1.278 c
+23.434 -1.286 23.346 -1.294 23.25 -1.294 c
+23.162 -1.301 23.063 -1.308 22.957 -1.308 c
+22.769 -1.308 22.608 -1.294 22.471 -1.264 c
+22.343 -1.228 22.229 -1.183 22.134 -1.132 c
+22.045 -1.084 21.972 -1.025 21.913 -0.955 c
+21.854 -0.878 21.81 -0.801 21.781 -0.72 c
+21.751 -0.632 21.729 -0.544 21.722 -0.455 c
+21.71 -0.36 21.707 -0.264 21.707 -0.176 c
+h
+26.136 -1.323 m
+25.966 -1.323 25.816 -1.301 25.679 -1.264 c
+25.551 -1.216 25.437 -1.147 25.342 -1.058 c
+25.253 -0.97 25.184 -0.864 25.136 -0.735 c
+25.084 -0.599 25.062 -0.448 25.062 -0.279 c
+25.062 -0.073 25.095 0.096 25.165 0.235 c
+25.232 0.382 25.327 0.493 25.444 0.574 c
+25.569 0.661 25.712 0.724 25.87 0.765 c
+26.036 0.802 26.213 0.827 26.4 0.838 c
+27.12 0.852 l
+27.12 1.029 l
+27.12 1.147 27.109 1.249 27.09 1.338 c
+27.069 1.426 27.036 1.492 26.988 1.544 c
+26.947 1.602 26.9 1.639 26.841 1.661 c
+26.782 1.679 26.716 1.691 26.649 1.691 c
+26.58 1.691 26.518 1.679 26.458 1.661 c
+26.408 1.65 26.36 1.625 26.312 1.588 c
+26.271 1.558 26.238 1.507 26.209 1.44 c
+26.186 1.382 26.172 1.301 26.165 1.205 c
+25.224 1.249 l
+25.253 1.397 25.297 1.532 25.356 1.661 c
+25.423 1.786 25.518 1.897 25.635 1.985 c
+25.753 2.08 25.893 2.153 26.061 2.205 c
+26.238 2.253 26.444 2.278 26.679 2.278 c
+27.12 2.278 27.451 2.168 27.678 1.955 c
+27.914 1.75 28.031 1.44 28.031 1.029 c
+28.031 -0.235 l
+28.031 -0.455 l
+28.039 -0.515 28.054 -0.569 28.075 -0.617 c
+28.094 -0.658 28.123 -0.691 28.164 -0.72 c
+28.201 -0.742 28.252 -0.75 28.311 -0.75 c
+28.376 -0.75 28.447 -0.746 28.517 -0.735 c
+28.517 -1.22 l
+28.457 -1.23 28.403 -1.242 28.355 -1.249 c
+28.314 -1.261 28.274 -1.267 28.237 -1.278 c
+28.197 -1.286 28.153 -1.294 28.105 -1.294 c
+28.054 -1.301 27.995 -1.308 27.929 -1.308 c
+27.701 -1.308 27.535 -1.257 27.429 -1.147 c
+27.318 -1.029 27.256 -0.864 27.237 -0.646 c
+27.223 -0.646 l
+27.154 -0.757 27.083 -0.852 27.017 -0.941 c
+26.947 -1.022 26.87 -1.087 26.782 -1.147 c
+26.693 -1.205 26.595 -1.249 26.488 -1.278 c
+26.389 -1.308 26.271 -1.323 26.136 -1.323 c
+27.12 0.353 m
+26.693 0.339 l
+26.595 0.339 26.503 0.331 26.414 0.324 c
+26.333 0.312 26.267 0.287 26.209 0.25 c
+26.15 0.21 26.098 0.15 26.061 0.073 c
+26.021 0.004 26.003 -0.088 26.003 -0.206 c
+26.003 -0.374 26.036 -0.496 26.106 -0.573 c
+26.172 -0.654 26.271 -0.691 26.4 -0.691 c
+26.506 -0.691 26.606 -0.669 26.693 -0.617 c
+26.789 -0.569 26.87 -0.507 26.929 -0.426 c
+26.995 -0.349 27.046 -0.261 27.076 -0.162 c
+27.106 -0.055 27.12 0.059 27.12 0.177 c
+h
+30.769 -2.66 m
+30.552 -2.66 30.361 -2.635 30.196 -2.587 c
+30.027 -2.547 29.887 -2.484 29.77 -2.396 c
+29.652 -2.315 29.552 -2.219 29.475 -2.102 c
+29.406 -1.984 29.358 -1.855 29.328 -1.72 c
+30.225 -1.617 l
+30.262 -1.753 30.331 -1.859 30.431 -1.94 c
+30.527 -2.028 30.651 -2.072 30.799 -2.072 c
+30.886 -2.072 30.967 -2.057 31.048 -2.028 c
+31.125 -1.999 31.195 -1.944 31.254 -1.866 c
+31.313 -1.797 31.357 -1.705 31.387 -1.587 c
+31.424 -1.469 31.445 -1.323 31.445 -1.147 c
+31.445 -0.955 l
+31.445 -0.889 31.449 -0.831 31.46 -0.779 c
+31.46 -0.588 l
+31.445 -0.588 l
+31.346 -0.816 31.202 -0.977 31.019 -1.072 c
+30.832 -1.172 30.626 -1.22 30.402 -1.22 c
+30.196 -1.22 30.012 -1.183 29.858 -1.103 c
+29.71 -1.014 29.582 -0.897 29.475 -0.75 c
+29.376 -0.596 29.303 -0.411 29.255 -0.206 c
+29.203 0.008 29.182 0.243 29.182 0.5 c
+29.182 0.771 29.203 1.018 29.255 1.235 c
+29.313 1.448 29.394 1.632 29.505 1.779 c
+29.612 1.933 29.743 2.051 29.901 2.132 c
+30.057 2.22 30.244 2.263 30.46 2.263 c
+30.556 2.263 30.655 2.253 30.755 2.234 c
+30.85 2.213 30.938 2.18 31.019 2.132 c
+31.107 2.08 31.185 2.018 31.254 1.941 c
+31.331 1.86 31.393 1.768 31.445 1.661 c
+31.46 1.661 l
+31.46 1.808 l
+31.468 1.867 31.474 1.918 31.474 1.97 c
+31.482 2.028 31.489 2.076 31.489 2.117 c
+31.497 2.165 31.507 2.198 31.519 2.22 c
+32.371 2.22 l
+32.361 2.139 32.349 2.028 32.342 1.881 c
+32.342 1.411 l
+32.342 -1.161 l
+32.342 -1.415 32.305 -1.635 32.239 -1.822 c
+32.17 -2.007 32.066 -2.161 31.931 -2.279 c
+31.79 -2.404 31.625 -2.499 31.43 -2.558 c
+31.233 -2.624 31.011 -2.66 30.769 -2.66 c
+31.46 0.53 m
+31.46 0.742 31.434 0.919 31.387 1.058 c
+31.346 1.205 31.291 1.323 31.225 1.411 c
+31.166 1.5 31.096 1.558 31.019 1.588 c
+30.938 1.625 30.861 1.646 30.784 1.646 c
+30.684 1.646 30.593 1.621 30.504 1.573 c
+30.424 1.532 30.358 1.463 30.298 1.367 c
+30.248 1.279 30.203 1.162 30.167 1.014 c
+30.137 0.875 30.122 0.706 30.122 0.5 c
+30.122 0.125 30.181 -0.154 30.298 -0.338 c
+30.416 -0.515 30.578 -0.602 30.784 -0.602 c
+30.85 -0.602 30.923 -0.588 31.004 -0.559 c
+31.092 -0.522 31.166 -0.463 31.225 -0.382 c
+31.291 -0.294 31.346 -0.176 31.387 -0.029 c
+31.434 0.118 31.46 0.301 31.46 0.53 c
+f
+Q
+q 1 0 0 1 482.8862 448.9472 cm
+0 0 m
+2.103 0 l
+2.103 -0.574 l
+-0.675 -0.574 l
+-0.675 4.777 l
+0 4.777 l
+h
+3.514 -0.574 -0.647 3.984 re
+3.558 4.453 m
+3.558 4.343 3.528 4.251 3.469 4.174 c
+3.41 4.104 3.315 4.072 3.19 4.072 c
+3.072 4.072 2.977 4.104 2.911 4.174 c
+2.852 4.251 2.822 4.343 2.822 4.453 c
+2.822 4.571 2.852 4.663 2.911 4.733 c
+2.977 4.81 3.072 4.85 3.19 4.85 c
+3.315 4.85 3.41 4.81 3.469 4.733 c
+3.528 4.652 3.558 4.56 3.558 4.453 c
+6.468 0.44 m
+6.468 0.588 6.413 0.709 6.306 0.808 c
+6.196 0.904 5.99 1.022 5.689 1.161 c
+5.343 1.308 5.101 1.429 4.954 1.529 c
+4.807 1.635 4.696 1.753 4.63 1.881 c
+4.561 2.006 4.528 2.164 4.528 2.352 c
+4.528 2.674 4.645 2.944 4.881 3.16 c
+5.116 3.374 5.417 3.484 5.792 3.484 c
+6.174 3.484 6.483 3.37 6.718 3.145 c
+6.953 2.917 7.071 2.631 7.071 2.278 c
+6.423 2.278 l
+6.423 2.454 6.365 2.605 6.247 2.734 c
+6.13 2.859 5.976 2.925 5.792 2.925 c
+5.594 2.925 5.442 2.869 5.336 2.763 c
+5.226 2.664 5.174 2.532 5.174 2.366 c
+5.174 2.238 5.211 2.131 5.292 2.043 c
+5.369 1.962 5.56 1.859 5.866 1.734 c
+6.342 1.547 6.674 1.359 6.85 1.176 c
+7.026 0.999 7.115 0.771 7.115 0.5 c
+7.115 0.147 6.99 -0.133 6.747 -0.339 c
+6.512 -0.544 6.196 -0.647 5.806 -0.647 c
+5.384 -0.647 5.046 -0.53 4.792 -0.294 c
+4.535 -0.052 4.41 0.253 4.41 0.617 c
+5.056 0.617 l
+5.064 0.389 5.134 0.213 5.262 0.087 c
+5.388 -0.03 5.571 -0.088 5.806 -0.088 c
+6.02 -0.088 6.182 -0.04 6.292 0.058 c
+6.409 0.154 6.468 0.282 6.468 0.44 c
+8.805 4.365 m
+8.805 3.41 l
+9.407 3.41 l
+9.407 2.881 l
+8.805 2.881 l
+8.805 0.411 l
+8.805 0.253 8.827 0.135 8.879 0.058 c
+8.937 -0.023 9.025 -0.059 9.143 -0.059 c
+9.232 -0.059 9.32 -0.044 9.407 -0.015 c
+9.407 -0.574 l
+9.261 -0.621 9.106 -0.647 8.952 -0.647 c
+8.694 -0.647 8.5 -0.555 8.364 -0.368 c
+8.224 -0.184 8.158 0.077 8.158 0.411 c
+8.158 2.881 l
+7.556 2.881 l
+7.556 3.41 l
+8.158 3.41 l
+8.158 4.365 l
+h
+13.935 -0.574 m
+13.895 -0.485 13.868 -0.339 13.862 -0.133 c
+13.627 -0.478 13.332 -0.647 12.979 -0.647 c
+12.615 -0.647 12.333 -0.551 12.127 -0.353 c
+11.929 -0.148 11.833 0.139 11.833 0.515 c
+11.833 0.914 11.969 1.234 12.245 1.469 c
+12.517 1.712 12.891 1.837 13.361 1.837 c
+13.847 1.837 l
+13.847 2.263 l
+13.847 2.499 13.791 2.664 13.685 2.763 c
+13.575 2.869 13.413 2.925 13.2 2.925 c
+13.002 2.925 12.84 2.866 12.715 2.749 c
+12.597 2.631 12.538 2.484 12.538 2.308 c
+11.892 2.308 l
+11.892 2.502 11.95 2.693 12.068 2.881 c
+12.193 3.064 12.355 3.212 12.553 3.322 c
+12.759 3.428 12.987 3.484 13.244 3.484 c
+13.645 3.484 13.949 3.38 14.155 3.175 c
+14.369 2.969 14.483 2.674 14.494 2.293 c
+14.494 0.279 l
+14.494 -0.026 14.531 -0.291 14.612 -0.515 c
+14.612 -0.574 l
+h
+13.068 -0.059 m
+13.233 -0.059 13.384 -0.015 13.523 0.073 c
+13.671 0.162 13.777 0.272 13.847 0.411 c
+13.847 1.352 l
+13.479 1.352 l
+13.163 1.352 12.921 1.282 12.744 1.146 c
+12.568 1.018 12.48 0.83 12.48 0.588 c
+12.48 0.359 12.524 0.195 12.613 0.087 c
+12.7 -0.011 12.85 -0.059 13.068 -0.059 c
+16.199 -0.574 -0.646 5.644 re
+17.918 -0.574 -0.646 5.644 re
+21.505 4.365 m
+21.505 3.41 l
+22.107 3.41 l
+22.107 2.881 l
+21.505 2.881 l
+21.505 0.411 l
+21.505 0.253 21.527 0.135 21.579 0.058 c
+21.637 -0.023 21.725 -0.059 21.843 -0.059 c
+21.931 -0.059 22.02 -0.044 22.107 -0.015 c
+22.107 -0.574 l
+21.961 -0.621 21.806 -0.647 21.652 -0.647 c
+21.394 -0.647 21.2 -0.555 21.064 -0.368 c
+20.924 -0.184 20.858 0.077 20.858 0.411 c
+20.858 2.881 l
+20.256 2.881 l
+20.256 3.41 l
+20.858 3.41 l
+20.858 4.365 l
+h
+24.915 -0.574 m
+24.875 -0.485 24.849 -0.339 24.842 -0.133 c
+24.607 -0.478 24.312 -0.647 23.96 -0.647 c
+23.596 -0.647 23.313 -0.551 23.107 -0.353 c
+22.909 -0.148 22.813 0.139 22.813 0.515 c
+22.813 0.914 22.949 1.234 23.225 1.469 c
+23.497 1.712 23.871 1.837 24.342 1.837 c
+24.827 1.837 l
+24.827 2.263 l
+24.827 2.499 24.772 2.664 24.665 2.763 c
+24.555 2.869 24.393 2.925 24.18 2.925 c
+23.981 2.925 23.82 2.866 23.695 2.749 c
+23.578 2.631 23.518 2.484 23.518 2.308 c
+22.872 2.308 l
+22.872 2.502 22.931 2.693 23.048 2.881 c
+23.173 3.064 23.335 3.212 23.534 3.322 c
+23.74 3.428 23.967 3.484 24.224 3.484 c
+24.625 3.484 24.93 3.38 25.136 3.175 c
+25.349 2.969 25.463 2.674 25.473 2.293 c
+25.473 0.279 l
+25.473 -0.026 25.51 -0.291 25.591 -0.515 c
+25.591 -0.574 l
+h
+24.048 -0.059 m
+24.214 -0.059 24.364 -0.015 24.503 0.073 c
+24.65 0.162 24.757 0.272 24.827 0.411 c
+24.827 1.352 l
+24.459 1.352 l
+24.143 1.352 23.901 1.282 23.724 1.146 c
+23.549 1.018 23.46 0.83 23.46 0.588 c
+23.46 0.359 23.504 0.195 23.592 0.087 c
+23.68 -0.011 23.831 -0.059 24.048 -0.059 c
+26.341 1.602 m
+26.341 2.219 26.451 2.682 26.679 2.998 c
+26.903 3.322 27.237 3.484 27.678 3.484 c
+28.079 3.484 28.384 3.307 28.59 2.954 c
+28.634 3.41 l
+29.222 3.41 l
+29.222 -0.618 l
+29.222 -1.106 29.093 -1.484 28.84 -1.75 c
+28.582 -2.014 28.23 -2.147 27.782 -2.147 c
+27.583 -2.147 27.362 -2.095 27.12 -1.999 c
+26.874 -1.9 26.693 -1.779 26.576 -1.632 c
+26.841 -1.191 l
+27.106 -1.455 27.403 -1.588 27.738 -1.588 c
+28.274 -1.588 28.55 -1.294 28.561 -0.706 c
+28.561 -0.177 l
+28.355 -0.493 28.054 -0.647 27.664 -0.647 c
+27.252 -0.647 26.929 -0.497 26.693 -0.191 c
+26.466 0.121 26.348 0.573 26.341 1.161 c
+h
+27.002 1.22 m
+27.002 0.779 27.065 0.448 27.194 0.235 c
+27.318 0.029 27.535 -0.073 27.84 -0.073 c
+28.164 -0.073 28.403 0.091 28.561 0.426 c
+28.561 2.41 l
+28.392 2.734 28.153 2.896 27.84 2.896 c
+27.547 2.896 27.329 2.792 27.194 2.587 c
+27.065 2.381 27.002 2.057 27.002 1.616 c
+h
+32.118 0.44 m
+32.118 0.588 32.062 0.709 31.956 0.808 c
+31.846 0.904 31.64 1.022 31.339 1.161 c
+30.994 1.308 30.751 1.429 30.604 1.529 c
+30.456 1.635 30.346 1.753 30.281 1.881 c
+30.211 2.006 30.177 2.164 30.177 2.352 c
+30.177 2.674 30.295 2.944 30.53 3.16 c
+30.765 3.374 31.067 3.484 31.441 3.484 c
+31.823 3.484 32.133 3.37 32.368 3.145 c
+32.603 2.917 32.721 2.631 32.721 2.278 c
+32.074 2.278 l
+32.074 2.454 32.015 2.605 31.898 2.734 c
+31.78 2.859 31.625 2.925 31.441 2.925 c
+31.243 2.925 31.092 2.869 30.986 2.763 c
+30.876 2.664 30.824 2.532 30.824 2.366 c
+30.824 2.238 30.861 2.131 30.942 2.043 c
+31.019 1.962 31.21 1.859 31.515 1.734 c
+31.993 1.547 32.324 1.359 32.5 1.176 c
+32.677 0.999 32.764 0.771 32.764 0.5 c
+32.764 0.147 32.64 -0.133 32.397 -0.339 c
+32.162 -0.544 31.846 -0.647 31.456 -0.647 c
+31.034 -0.647 30.695 -0.53 30.442 -0.294 c
+30.185 -0.052 30.059 0.253 30.059 0.617 c
+30.707 0.617 l
+30.714 0.389 30.784 0.213 30.913 0.087 c
+31.037 -0.03 31.221 -0.088 31.456 -0.088 c
+31.669 -0.088 31.831 -0.04 31.941 0.058 c
+32.058 0.154 32.118 0.282 32.118 0.44 c
+33.646 -0.221 m
+33.646 -0.103 33.679 -0.008 33.749 0.073 c
+33.816 0.151 33.918 0.191 34.058 0.191 c
+34.205 0.191 34.312 0.151 34.381 0.073 c
+34.458 -0.008 34.499 -0.103 34.499 -0.221 c
+34.499 -0.331 34.458 -0.423 34.381 -0.5 c
+34.312 -0.578 34.205 -0.618 34.058 -0.618 c
+33.918 -0.618 33.816 -0.578 33.749 -0.5 c
+33.679 -0.423 33.646 -0.331 33.646 -0.221 c
+f
+Q
+0.113 0.082 0.09 0 k
+287.665 441.263 234.667 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 434.424 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.69 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.771 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.279 -3.219 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.985 c
+-3.322 2.18 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.003 -2.469 3.043 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.182 -0.103 1.999 c
+-0.941 1.882 l
+-1.01 2.253 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.455 c
+-2.26 2.425 -2.319 2.385 -2.366 2.338 c
+-2.406 2.297 -2.436 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.44 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.014 c
+6.402 -2.66 m
+6.184 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.147 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.411 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.632 5.137 1.779 c
+5.244 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.151 2.22 c
+8.004 2.22 l
+7.993 2.139 7.982 2.028 7.975 1.882 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.871 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.279 5.835 1.162 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.597 1.602 m
+13.053 1.602 l
+13.053 2.22 l
+13.641 2.22 l
+13.92 3.117 l
+14.494 3.117 l
+14.494 2.22 l
+15.728 2.22 l
+15.728 1.602 l
+14.494 1.602 l
+14.494 -0.103 l
+14.494 -0.324 l
+14.501 -0.393 14.523 -0.455 14.552 -0.515 c
+14.589 -0.565 14.645 -0.61 14.714 -0.646 c
+14.791 -0.676 14.905 -0.69 15.052 -0.69 c
+15.188 -0.69 15.324 -0.687 15.464 -0.676 c
+15.599 -0.658 15.732 -0.632 15.861 -0.602 c
+15.861 -1.205 l
+15.78 -1.216 15.703 -1.23 15.626 -1.249 c
+15.545 -1.261 15.468 -1.267 15.391 -1.278 c
+15.31 -1.286 15.221 -1.294 15.125 -1.294 c
+15.038 -1.301 14.938 -1.308 14.832 -1.308 c
+14.645 -1.308 14.483 -1.294 14.346 -1.264 c
+14.218 -1.228 14.104 -1.183 14.009 -1.132 c
+13.92 -1.084 13.847 -1.025 13.788 -0.955 c
+13.729 -0.878 13.685 -0.801 13.656 -0.72 c
+13.627 -0.632 13.604 -0.544 13.597 -0.455 c
+13.586 -0.36 13.582 -0.264 13.582 -0.176 c
+h
+21.722 1.602 m
+21.178 1.602 l
+21.178 2.22 l
+21.766 2.22 l
+22.045 3.117 l
+22.618 3.117 l
+22.618 2.22 l
+23.853 2.22 l
+23.853 1.602 l
+22.618 1.602 l
+22.618 -0.103 l
+22.618 -0.324 l
+22.626 -0.393 22.647 -0.455 22.677 -0.515 c
+22.714 -0.565 22.769 -0.61 22.839 -0.646 c
+22.916 -0.676 23.03 -0.69 23.177 -0.69 c
+23.313 -0.69 23.449 -0.687 23.588 -0.676 c
+23.725 -0.658 23.857 -0.632 23.985 -0.602 c
+23.985 -1.205 l
+23.904 -1.216 23.827 -1.23 23.75 -1.249 c
+23.669 -1.261 23.592 -1.267 23.515 -1.278 c
+23.434 -1.286 23.346 -1.294 23.25 -1.294 c
+23.162 -1.301 23.063 -1.308 22.957 -1.308 c
+22.769 -1.308 22.608 -1.294 22.471 -1.264 c
+22.343 -1.228 22.229 -1.183 22.134 -1.132 c
+22.045 -1.084 21.972 -1.025 21.913 -0.955 c
+21.854 -0.878 21.81 -0.801 21.781 -0.72 c
+21.751 -0.632 21.729 -0.544 21.722 -0.455 c
+21.71 -0.36 21.707 -0.264 21.707 -0.176 c
+h
+26.136 -1.323 m
+25.966 -1.323 25.816 -1.301 25.679 -1.264 c
+25.551 -1.216 25.437 -1.147 25.342 -1.058 c
+25.253 -0.97 25.184 -0.864 25.136 -0.735 c
+25.084 -0.599 25.062 -0.448 25.062 -0.279 c
+25.062 -0.073 25.095 0.096 25.165 0.235 c
+25.232 0.382 25.327 0.493 25.444 0.574 c
+25.569 0.661 25.712 0.724 25.87 0.765 c
+26.036 0.802 26.213 0.827 26.4 0.838 c
+27.12 0.852 l
+27.12 1.029 l
+27.12 1.147 27.109 1.249 27.09 1.338 c
+27.069 1.426 27.036 1.492 26.988 1.544 c
+26.947 1.602 26.9 1.639 26.841 1.661 c
+26.782 1.679 26.716 1.691 26.649 1.691 c
+26.58 1.691 26.518 1.679 26.458 1.661 c
+26.408 1.65 26.36 1.625 26.312 1.588 c
+26.271 1.558 26.238 1.507 26.209 1.44 c
+26.186 1.382 26.172 1.301 26.165 1.205 c
+25.224 1.249 l
+25.253 1.397 25.297 1.532 25.356 1.661 c
+25.423 1.786 25.518 1.897 25.635 1.985 c
+25.753 2.08 25.893 2.153 26.061 2.205 c
+26.238 2.253 26.444 2.278 26.679 2.278 c
+27.12 2.278 27.451 2.168 27.678 1.955 c
+27.914 1.75 28.031 1.44 28.031 1.029 c
+28.031 -0.235 l
+28.031 -0.455 l
+28.039 -0.515 28.054 -0.569 28.075 -0.617 c
+28.094 -0.658 28.123 -0.69 28.164 -0.72 c
+28.201 -0.742 28.252 -0.75 28.311 -0.75 c
+28.376 -0.75 28.447 -0.746 28.517 -0.735 c
+28.517 -1.22 l
+28.457 -1.23 28.403 -1.242 28.355 -1.249 c
+28.314 -1.261 28.274 -1.267 28.237 -1.278 c
+28.197 -1.286 28.153 -1.294 28.105 -1.294 c
+28.054 -1.301 27.995 -1.308 27.929 -1.308 c
+27.701 -1.308 27.535 -1.257 27.429 -1.147 c
+27.318 -1.029 27.256 -0.864 27.237 -0.646 c
+27.223 -0.646 l
+27.154 -0.757 27.083 -0.852 27.017 -0.941 c
+26.947 -1.022 26.87 -1.087 26.782 -1.147 c
+26.693 -1.205 26.595 -1.249 26.488 -1.278 c
+26.389 -1.308 26.271 -1.323 26.136 -1.323 c
+27.12 0.353 m
+26.693 0.339 l
+26.595 0.339 26.503 0.331 26.414 0.324 c
+26.333 0.312 26.267 0.287 26.209 0.25 c
+26.15 0.21 26.098 0.151 26.061 0.073 c
+26.021 0.004 26.003 -0.088 26.003 -0.206 c
+26.003 -0.374 26.036 -0.496 26.106 -0.573 c
+26.172 -0.654 26.271 -0.69 26.4 -0.69 c
+26.506 -0.69 26.606 -0.669 26.693 -0.617 c
+26.789 -0.569 26.87 -0.507 26.929 -0.426 c
+26.995 -0.349 27.046 -0.261 27.076 -0.162 c
+27.106 -0.055 27.12 0.059 27.12 0.177 c
+h
+30.769 -2.66 m
+30.552 -2.66 30.361 -2.635 30.196 -2.587 c
+30.027 -2.547 29.887 -2.484 29.77 -2.396 c
+29.652 -2.315 29.552 -2.219 29.475 -2.102 c
+29.406 -1.984 29.358 -1.855 29.328 -1.72 c
+30.225 -1.617 l
+30.262 -1.753 30.331 -1.859 30.431 -1.94 c
+30.527 -2.028 30.651 -2.072 30.799 -2.072 c
+30.886 -2.072 30.967 -2.057 31.048 -2.028 c
+31.125 -1.999 31.195 -1.944 31.254 -1.866 c
+31.313 -1.797 31.357 -1.705 31.387 -1.587 c
+31.424 -1.469 31.445 -1.323 31.445 -1.147 c
+31.445 -0.955 l
+31.445 -0.889 31.449 -0.831 31.46 -0.779 c
+31.46 -0.588 l
+31.445 -0.588 l
+31.346 -0.816 31.202 -0.977 31.019 -1.072 c
+30.832 -1.172 30.626 -1.22 30.402 -1.22 c
+30.196 -1.22 30.012 -1.183 29.858 -1.103 c
+29.71 -1.014 29.582 -0.897 29.475 -0.75 c
+29.376 -0.595 29.303 -0.411 29.255 -0.206 c
+29.203 0.008 29.182 0.243 29.182 0.5 c
+29.182 0.771 29.203 1.018 29.255 1.235 c
+29.313 1.448 29.394 1.632 29.505 1.779 c
+29.612 1.933 29.743 2.051 29.901 2.132 c
+30.057 2.22 30.244 2.263 30.46 2.263 c
+30.556 2.263 30.655 2.253 30.755 2.234 c
+30.85 2.213 30.938 2.18 31.019 2.132 c
+31.107 2.08 31.185 2.018 31.254 1.941 c
+31.331 1.86 31.393 1.768 31.445 1.661 c
+31.46 1.661 l
+31.46 1.808 l
+31.468 1.867 31.474 1.918 31.474 1.97 c
+31.482 2.028 31.489 2.076 31.489 2.117 c
+31.497 2.165 31.507 2.198 31.519 2.22 c
+32.371 2.22 l
+32.361 2.139 32.349 2.028 32.342 1.882 c
+32.342 1.411 l
+32.342 -1.161 l
+32.342 -1.415 32.305 -1.635 32.239 -1.822 c
+32.17 -2.007 32.066 -2.161 31.931 -2.278 c
+31.79 -2.404 31.625 -2.499 31.43 -2.558 c
+31.233 -2.624 31.011 -2.66 30.769 -2.66 c
+31.46 0.53 m
+31.46 0.742 31.434 0.919 31.387 1.058 c
+31.346 1.205 31.291 1.323 31.225 1.411 c
+31.166 1.5 31.096 1.558 31.019 1.588 c
+30.938 1.625 30.861 1.646 30.784 1.646 c
+30.684 1.646 30.593 1.621 30.504 1.573 c
+30.424 1.532 30.358 1.463 30.298 1.367 c
+30.248 1.279 30.203 1.162 30.167 1.014 c
+30.137 0.875 30.122 0.706 30.122 0.5 c
+30.122 0.125 30.181 -0.154 30.298 -0.338 c
+30.416 -0.515 30.578 -0.602 30.784 -0.602 c
+30.85 -0.602 30.923 -0.588 31.004 -0.559 c
+31.092 -0.522 31.166 -0.463 31.225 -0.382 c
+31.291 -0.294 31.346 -0.176 31.387 -0.029 c
+31.434 0.118 31.46 0.301 31.46 0.53 c
+38.115 -2.631 m
+38.115 3.514 l
+40.041 3.514 l
+40.041 2.896 l
+38.967 2.896 l
+38.967 -2.013 l
+40.041 -2.013 l
+40.041 -2.631 l
+h
+43.616 -1.264 m
+43.616 0.721 l
+43.616 1.022 43.572 1.242 43.484 1.382 c
+43.403 1.529 43.267 1.602 43.072 1.602 c
+42.962 1.602 42.859 1.577 42.763 1.529 c
+42.676 1.477 42.595 1.411 42.528 1.323 c
+42.47 1.235 42.418 1.124 42.381 1 c
+42.352 0.882 42.337 0.75 42.337 0.603 c
+42.337 -1.264 l
+41.425 -1.264 l
+41.425 1.44 l
+41.425 1.661 l
+41.425 1.75 41.419 1.827 41.411 1.897 c
+41.411 2.087 l
+41.411 2.22 l
+42.264 2.22 l
+42.271 2.19 42.279 2.146 42.279 2.087 c
+42.279 1.897 l
+42.286 1.827 42.293 1.756 42.293 1.691 c
+42.3 1.621 42.308 1.565 42.308 1.529 c
+42.323 1.529 l
+42.441 1.793 42.591 1.985 42.778 2.103 c
+42.962 2.22 43.183 2.278 43.44 2.278 c
+43.623 2.278 43.785 2.249 43.925 2.19 c
+44.06 2.132 44.174 2.043 44.263 1.926 c
+44.351 1.808 44.413 1.665 44.454 1.5 c
+44.502 1.341 44.527 1.154 44.527 0.941 c
+44.527 -1.264 l
+h
+46.441 -1.323 m
+46.273 -1.323 46.123 -1.301 45.986 -1.264 c
+45.857 -1.216 45.743 -1.147 45.648 -1.058 c
+45.56 -0.97 45.49 -0.864 45.442 -0.735 c
+45.391 -0.599 45.369 -0.448 45.369 -0.279 c
+45.369 -0.073 45.402 0.096 45.472 0.235 c
+45.538 0.382 45.633 0.493 45.751 0.574 c
+45.876 0.661 46.019 0.724 46.177 0.765 c
+46.343 0.802 46.52 0.827 46.707 0.838 c
+47.426 0.852 l
+47.426 1.029 l
+47.426 1.147 47.416 1.249 47.397 1.338 c
+47.376 1.426 47.342 1.492 47.295 1.544 c
+47.254 1.602 47.206 1.639 47.147 1.661 c
+47.089 1.679 47.023 1.691 46.956 1.691 c
+46.886 1.691 46.824 1.679 46.765 1.661 c
+46.714 1.65 46.666 1.625 46.618 1.588 c
+46.578 1.558 46.545 1.507 46.516 1.44 c
+46.493 1.382 46.479 1.301 46.472 1.205 c
+45.531 1.249 l
+45.56 1.397 45.604 1.532 45.663 1.661 c
+45.729 1.786 45.824 1.897 45.942 1.985 c
+46.06 2.08 46.2 2.153 46.368 2.205 c
+46.545 2.253 46.751 2.278 46.986 2.278 c
+47.426 2.278 47.758 2.168 47.985 1.955 c
+48.22 1.75 48.338 1.44 48.338 1.029 c
+48.338 -0.235 l
+48.338 -0.455 l
+48.346 -0.515 48.361 -0.569 48.382 -0.617 c
+48.401 -0.658 48.43 -0.69 48.471 -0.72 c
+48.507 -0.742 48.558 -0.75 48.617 -0.75 c
+48.683 -0.75 48.753 -0.746 48.823 -0.735 c
+48.823 -1.22 l
+48.764 -1.23 48.71 -1.242 48.662 -1.249 c
+48.621 -1.261 48.581 -1.267 48.544 -1.278 c
+48.504 -1.286 48.459 -1.294 48.411 -1.294 c
+48.361 -1.301 48.301 -1.308 48.235 -1.308 c
+48.008 -1.308 47.842 -1.257 47.735 -1.147 c
+47.625 -1.029 47.563 -0.864 47.544 -0.646 c
+47.53 -0.646 l
+47.46 -0.757 47.39 -0.852 47.324 -0.941 c
+47.254 -1.022 47.177 -1.087 47.089 -1.147 c
+47 -1.205 46.901 -1.249 46.794 -1.278 c
+46.695 -1.308 46.578 -1.323 46.441 -1.323 c
+47.426 0.353 m
+47 0.339 l
+46.901 0.339 46.809 0.331 46.721 0.324 c
+46.64 0.312 46.574 0.287 46.516 0.25 c
+46.457 0.21 46.405 0.151 46.368 0.073 c
+46.328 0.004 46.31 -0.088 46.31 -0.206 c
+46.31 -0.374 46.343 -0.496 46.412 -0.573 c
+46.479 -0.654 46.578 -0.69 46.707 -0.69 c
+46.813 -0.69 46.912 -0.669 47 -0.617 c
+47.096 -0.569 47.177 -0.507 47.235 -0.426 c
+47.302 -0.349 47.353 -0.261 47.382 -0.162 c
+47.412 -0.055 47.426 0.059 47.426 0.177 c
+h
+50.709 -1.264 m
+50.709 0.852 l
+50.709 1.018 50.701 1.154 50.694 1.264 c
+50.682 1.371 50.664 1.455 50.634 1.515 c
+50.613 1.58 50.584 1.632 50.547 1.661 c
+50.518 1.691 50.477 1.706 50.429 1.706 c
+50.37 1.706 50.315 1.675 50.267 1.617 c
+50.227 1.565 50.194 1.492 50.164 1.397 c
+50.135 1.309 50.109 1.195 50.091 1.058 c
+50.08 0.919 50.077 0.769 50.077 0.603 c
+50.077 -1.264 l
+49.327 -1.264 l
+49.327 1.47 l
+49.327 1.706 l
+49.327 1.926 l
+49.327 2.003 49.319 2.065 49.312 2.117 c
+49.312 2.22 l
+49.988 2.22 l
+49.988 2.132 l
+49.988 1.985 l
+49.996 1.926 50.003 1.867 50.003 1.808 c
+50.003 1.646 l
+50.017 1.646 l
+50.036 1.735 50.065 1.812 50.106 1.882 c
+50.142 1.959 50.187 2.028 50.238 2.087 c
+50.297 2.146 50.362 2.19 50.443 2.22 c
+50.521 2.257 50.609 2.278 50.709 2.278 c
+50.892 2.278 51.031 2.223 51.12 2.117 c
+51.216 2.018 51.285 1.86 51.326 1.646 c
+51.34 1.646 l
+51.378 1.742 51.418 1.83 51.458 1.911 c
+51.505 1.988 51.561 2.051 51.619 2.103 c
+51.679 2.161 51.744 2.205 51.825 2.234 c
+51.902 2.263 51.991 2.278 52.09 2.278 c
+52.226 2.278 52.34 2.253 52.428 2.205 c
+52.516 2.153 52.583 2.08 52.634 1.985 c
+52.693 1.885 52.729 1.756 52.751 1.602 c
+52.781 1.455 52.795 1.272 52.795 1.058 c
+52.795 -1.264 l
+52.076 -1.264 l
+52.076 0.852 l
+52.076 1.018 52.068 1.154 52.061 1.264 c
+52.049 1.371 52.031 1.455 52.002 1.515 c
+51.98 1.58 51.95 1.632 51.914 1.661 c
+51.885 1.691 51.844 1.706 51.796 1.706 c
+51.679 1.706 51.583 1.617 51.517 1.44 c
+51.458 1.272 51.428 1.014 51.428 0.661 c
+51.428 -1.264 l
+h
+55.166 -1.323 m
+54.908 -1.323 54.68 -1.286 54.475 -1.22 c
+54.269 -1.143 54.093 -1.029 53.946 -0.881 c
+53.799 -0.727 53.681 -0.536 53.593 -0.309 c
+53.512 -0.085 53.475 0.181 53.475 0.485 c
+53.475 0.816 53.52 1.095 53.608 1.323 c
+53.703 1.558 53.832 1.742 53.99 1.882 c
+54.156 2.018 54.343 2.117 54.549 2.176 c
+54.754 2.242 54.964 2.278 55.181 2.278 c
+55.453 2.278 55.688 2.227 55.887 2.132 c
+56.092 2.043 56.257 1.911 56.386 1.735 c
+56.522 1.565 56.621 1.359 56.68 1.118 c
+56.746 0.882 56.783 0.617 56.783 0.324 c
+56.783 0.309 l
+54.416 0.309 l
+54.416 0.162 54.431 0.023 54.46 -0.103 c
+54.497 -0.231 54.553 -0.345 54.622 -0.441 c
+54.688 -0.529 54.773 -0.599 54.871 -0.646 c
+54.967 -0.698 55.081 -0.72 55.21 -0.72 c
+55.364 -0.72 55.504 -0.687 55.621 -0.617 c
+55.746 -0.551 55.835 -0.448 55.887 -0.309 c
+56.724 -0.382 l
+56.695 -0.482 56.639 -0.588 56.562 -0.706 c
+56.481 -0.816 56.379 -0.918 56.253 -1.014 c
+56.136 -1.103 55.982 -1.176 55.798 -1.234 c
+55.621 -1.294 55.409 -1.323 55.166 -1.323 c
+55.166 1.706 m
+55.077 1.706 54.989 1.691 54.902 1.661 c
+54.813 1.632 54.732 1.58 54.666 1.515 c
+54.596 1.444 54.537 1.357 54.49 1.249 c
+54.449 1.139 54.431 1.014 54.431 0.867 c
+55.901 0.867 l
+55.901 1.004 55.875 1.124 55.827 1.235 c
+55.787 1.341 55.731 1.43 55.665 1.5 c
+55.607 1.565 55.534 1.617 55.445 1.646 c
+55.357 1.683 55.261 1.706 55.166 1.706 c
+58.04 -2.631 m
+58.04 -2.013 l
+59.112 -2.013 l
+59.112 2.896 l
+58.04 2.896 l
+58.04 3.514 l
+59.965 3.514 l
+59.965 -2.631 l
+h
+66.543 -2.631 m
+66.543 3.514 l
+68.469 3.514 l
+68.469 2.896 l
+67.396 2.896 l
+67.396 -2.013 l
+68.469 -2.013 l
+68.469 -2.631 l
+h
+71.412 -1.323 m
+71.126 -1.323 70.883 -1.282 70.677 -1.205 c
+70.471 -1.117 70.299 -0.995 70.162 -0.837 c
+70.023 -0.683 69.92 -0.496 69.854 -0.279 c
+69.784 -0.055 69.751 0.191 69.751 0.456 c
+69.751 0.75 69.784 1.007 69.854 1.235 c
+69.931 1.459 70.038 1.646 70.177 1.793 c
+70.324 1.947 70.501 2.065 70.706 2.146 c
+70.912 2.234 71.147 2.278 71.412 2.278 c
+71.636 2.278 71.839 2.249 72.015 2.19 c
+72.191 2.132 72.342 2.047 72.47 1.941 c
+72.595 1.841 72.698 1.72 72.779 1.573 c
+72.857 1.434 72.911 1.282 72.94 1.118 c
+72.03 1.073 l
+72 1.249 71.93 1.389 71.824 1.5 c
+71.724 1.606 71.581 1.661 71.397 1.661 c
+71.151 1.661 70.975 1.558 70.868 1.353 c
+70.758 1.154 70.706 0.867 70.706 0.485 c
+70.706 -0.309 70.941 -0.706 71.412 -0.706 c
+71.577 -0.706 71.721 -0.654 71.839 -0.544 c
+71.956 -0.437 72.03 -0.276 72.059 -0.058 c
+72.97 -0.103 l
+72.94 -0.272 72.886 -0.426 72.809 -0.573 c
+72.739 -0.72 72.635 -0.852 72.5 -0.97 c
+72.371 -1.08 72.213 -1.168 72.03 -1.234 c
+71.853 -1.294 71.647 -1.323 71.412 -1.323 c
+77.119 0.485 m
+77.119 0.21 77.082 -0.04 77.016 -0.264 c
+76.946 -0.482 76.843 -0.669 76.707 -0.823 c
+76.568 -0.981 76.391 -1.103 76.178 -1.19 c
+75.961 -1.278 75.708 -1.323 75.413 -1.323 c
+75.138 -1.323 74.892 -1.278 74.679 -1.19 c
+74.473 -1.103 74.301 -0.981 74.164 -0.823 c
+74.025 -0.669 73.921 -0.482 73.856 -0.264 c
+73.786 -0.04 73.753 0.21 73.753 0.485 c
+73.753 0.738 73.782 0.974 73.841 1.191 c
+73.907 1.415 74.01 1.606 74.15 1.764 c
+74.285 1.929 74.462 2.058 74.679 2.146 c
+74.892 2.234 75.149 2.278 75.444 2.278 c
+75.756 2.278 76.016 2.234 76.222 2.146 c
+76.435 2.058 76.608 1.929 76.737 1.764 c
+76.873 1.606 76.972 1.415 77.031 1.191 c
+77.09 0.974 77.119 0.738 77.119 0.485 c
+76.163 0.485 m
+76.163 0.691 76.149 0.867 76.119 1.014 c
+76.097 1.162 76.061 1.282 76.001 1.382 c
+75.943 1.477 75.87 1.548 75.781 1.588 c
+75.693 1.635 75.583 1.661 75.458 1.661 c
+75.193 1.661 75.002 1.562 74.885 1.367 c
+74.767 1.18 74.708 0.886 74.708 0.485 c
+74.708 0.063 74.767 -0.243 74.885 -0.426 c
+75.002 -0.613 75.178 -0.706 75.413 -0.706 c
+75.539 -0.706 75.652 -0.687 75.752 -0.646 c
+75.847 -0.599 75.928 -0.525 75.987 -0.426 c
+76.053 -0.33 76.097 -0.206 76.119 -0.058 c
+76.149 0.088 76.163 0.268 76.163 0.485 c
+79.14 -1.264 m
+79.14 0.852 l
+79.14 1.018 79.132 1.154 79.126 1.264 c
+79.114 1.371 79.095 1.455 79.066 1.515 c
+79.045 1.58 79.015 1.632 78.978 1.661 c
+78.949 1.691 78.908 1.706 78.86 1.706 c
+78.802 1.706 78.746 1.675 78.699 1.617 c
+78.659 1.565 78.625 1.492 78.596 1.397 c
+78.567 1.309 78.541 1.195 78.523 1.058 c
+78.511 0.919 78.508 0.769 78.508 0.603 c
+78.508 -1.264 l
+77.759 -1.264 l
+77.759 1.47 l
+77.759 1.706 l
+77.759 1.926 l
+77.759 2.003 77.751 2.065 77.744 2.117 c
+77.744 2.22 l
+78.42 2.22 l
+78.42 2.132 l
+78.42 1.985 l
+78.427 1.926 78.434 1.867 78.434 1.808 c
+78.434 1.646 l
+78.449 1.646 l
+78.467 1.735 78.497 1.812 78.538 1.882 c
+78.574 1.959 78.619 2.028 78.669 2.087 c
+78.729 2.146 78.794 2.19 78.875 2.22 c
+78.952 2.257 79.041 2.278 79.14 2.278 c
+79.324 2.278 79.463 2.223 79.552 2.117 c
+79.647 2.018 79.717 1.86 79.758 1.646 c
+79.772 1.646 l
+79.809 1.742 79.849 1.83 79.889 1.911 c
+79.937 1.988 79.993 2.051 80.051 2.103 c
+80.111 2.161 80.176 2.205 80.257 2.234 c
+80.334 2.263 80.423 2.278 80.522 2.278 c
+80.658 2.278 80.772 2.253 80.859 2.205 c
+80.948 2.153 81.014 2.08 81.065 1.985 c
+81.125 1.885 81.161 1.756 81.183 1.602 c
+81.212 1.455 81.227 1.272 81.227 1.058 c
+81.227 -1.264 l
+80.507 -1.264 l
+80.507 0.852 l
+80.507 1.018 80.5 1.154 80.492 1.264 c
+80.481 1.371 80.463 1.455 80.433 1.515 c
+80.412 1.58 80.382 1.632 80.346 1.661 c
+80.316 1.691 80.275 1.706 80.228 1.706 c
+80.111 1.706 80.015 1.617 79.949 1.44 c
+79.889 1.272 79.86 1.014 79.86 0.661 c
+79.86 -1.264 l
+h
+83.201 -1.264 m
+83.201 0.852 l
+83.201 1.018 83.193 1.154 83.186 1.264 c
+83.175 1.371 83.157 1.455 83.128 1.515 c
+83.105 1.58 83.076 1.632 83.039 1.661 c
+83.01 1.691 82.969 1.706 82.921 1.706 c
+82.862 1.706 82.808 1.675 82.76 1.617 c
+82.719 1.565 82.686 1.492 82.657 1.397 c
+82.627 1.309 82.602 1.195 82.583 1.058 c
+82.572 0.919 82.569 0.769 82.569 0.603 c
+82.569 -1.264 l
+81.819 -1.264 l
+81.819 1.47 l
+81.819 1.706 l
+81.819 1.926 l
+81.819 2.003 81.811 2.065 81.804 2.117 c
+81.804 2.22 l
+82.48 2.22 l
+82.48 2.132 l
+82.48 1.985 l
+82.488 1.926 82.495 1.867 82.495 1.808 c
+82.495 1.646 l
+82.509 1.646 l
+82.528 1.735 82.557 1.812 82.598 1.882 c
+82.635 1.959 82.679 2.028 82.73 2.087 c
+82.789 2.146 82.855 2.19 82.936 2.22 c
+83.013 2.257 83.101 2.278 83.201 2.278 c
+83.384 2.278 83.524 2.223 83.612 2.117 c
+83.708 2.018 83.778 1.86 83.818 1.646 c
+83.833 1.646 l
+83.87 1.742 83.91 1.83 83.951 1.911 c
+83.998 1.988 84.053 2.051 84.112 2.103 c
+84.171 2.161 84.237 2.205 84.318 2.234 c
+84.395 2.263 84.483 2.278 84.582 2.278 c
+84.718 2.278 84.832 2.253 84.921 2.205 c
+85.009 2.153 85.075 2.08 85.127 1.985 c
+85.185 1.885 85.222 1.756 85.244 1.602 c
+85.273 1.455 85.287 1.272 85.287 1.058 c
+85.287 -1.264 l
+84.568 -1.264 l
+84.568 0.852 l
+84.568 1.018 84.56 1.154 84.553 1.264 c
+84.541 1.371 84.524 1.455 84.494 1.515 c
+84.472 1.58 84.443 1.632 84.406 1.661 c
+84.377 1.691 84.336 1.706 84.288 1.706 c
+84.171 1.706 84.075 1.617 84.009 1.44 c
+83.951 1.272 83.921 1.014 83.921 0.661 c
+83.921 -1.264 l
+h
+88.202 -0.646 m
+89.334 -0.646 l
+89.334 -1.264 l
+86.027 -1.264 l
+86.027 -0.646 l
+87.29 -0.646 l
+87.29 1.602 l
+86.365 1.602 l
+86.365 2.22 l
+88.202 2.22 l
+h
+87.29 3.514 0.912 -0.676 re
+87.29 2.837 m
+90.763 1.602 m
+90.22 1.602 l
+90.22 2.22 l
+90.808 2.22 l
+91.086 3.117 l
+91.66 3.117 l
+91.66 2.22 l
+92.894 2.22 l
+92.894 1.602 l
+91.66 1.602 l
+91.66 -0.103 l
+91.66 -0.324 l
+91.668 -0.393 91.689 -0.455 91.718 -0.515 c
+91.755 -0.565 91.811 -0.61 91.88 -0.646 c
+91.957 -0.676 92.071 -0.69 92.219 -0.69 c
+92.354 -0.69 92.491 -0.687 92.63 -0.676 c
+92.766 -0.658 92.898 -0.632 93.027 -0.602 c
+93.027 -1.205 l
+92.946 -1.216 92.869 -1.23 92.792 -1.249 c
+92.711 -1.261 92.634 -1.267 92.557 -1.278 c
+92.476 -1.286 92.387 -1.294 92.292 -1.294 c
+92.204 -1.301 92.105 -1.308 91.998 -1.308 c
+91.811 -1.308 91.649 -1.294 91.513 -1.264 c
+91.384 -1.228 91.271 -1.183 91.175 -1.132 c
+91.086 -1.084 91.013 -1.025 90.954 -0.955 c
+90.895 -0.878 90.851 -0.801 90.822 -0.72 c
+90.793 -0.632 90.771 -0.544 90.763 -0.455 c
+90.752 -0.36 90.748 -0.264 90.748 -0.176 c
+h
+101.387 -0.249 m
+101.387 -0.419 101.347 -0.569 101.27 -0.706 c
+101.199 -0.834 101.097 -0.948 100.961 -1.043 c
+100.832 -1.132 100.67 -1.201 100.476 -1.249 c
+100.288 -1.297 100.071 -1.323 99.828 -1.323 c
+99.601 -1.323 99.402 -1.308 99.226 -1.278 c
+99.05 -1.249 98.891 -1.201 98.756 -1.132 c
+98.616 -1.055 98.506 -0.955 98.417 -0.837 c
+98.33 -0.72 98.26 -0.573 98.212 -0.397 c
+99.02 -0.279 l
+99.039 -0.378 99.068 -0.455 99.109 -0.515 c
+99.157 -0.573 99.215 -0.617 99.285 -0.646 c
+99.351 -0.676 99.432 -0.702 99.52 -0.72 c
+99.608 -0.731 99.711 -0.735 99.828 -0.735 c
+99.924 -0.735 100.02 -0.731 100.108 -0.72 c
+100.196 -0.702 100.273 -0.676 100.343 -0.646 c
+100.41 -0.617 100.461 -0.58 100.491 -0.529 c
+100.527 -0.482 100.549 -0.419 100.549 -0.338 c
+100.549 -0.243 100.52 -0.169 100.461 -0.118 c
+100.41 -0.07 100.343 -0.029 100.256 0 c
+100.167 0.037 100.057 0.066 99.932 0.088 c
+99.814 0.118 99.682 0.147 99.535 0.177 c
+99.396 0.214 99.256 0.254 99.109 0.294 c
+98.969 0.341 98.844 0.405 98.727 0.485 c
+98.616 0.563 98.528 0.661 98.462 0.779 c
+98.392 0.897 98.359 1.047 98.359 1.235 c
+98.359 1.389 98.388 1.532 98.447 1.661 c
+98.513 1.797 98.609 1.911 98.727 1.999 c
+98.851 2.087 99.009 2.153 99.197 2.205 c
+99.381 2.253 99.593 2.278 99.828 2.278 c
+100.013 2.278 100.189 2.257 100.358 2.22 c
+100.524 2.19 100.67 2.135 100.799 2.058 c
+100.924 1.988 101.034 1.889 101.122 1.764 c
+101.21 1.646 101.27 1.503 101.299 1.338 c
+100.505 1.264 l
+100.483 1.341 100.454 1.404 100.416 1.455 c
+100.377 1.515 100.329 1.558 100.27 1.588 c
+100.219 1.625 100.156 1.65 100.079 1.661 c
+99.998 1.669 99.917 1.675 99.828 1.675 c
+99.612 1.675 99.45 1.646 99.344 1.588 c
+99.234 1.536 99.182 1.448 99.182 1.323 c
+99.182 1.242 99.201 1.18 99.24 1.132 c
+99.288 1.081 99.351 1.044 99.432 1.014 c
+99.52 0.985 99.616 0.956 99.726 0.927 c
+99.832 0.904 99.954 0.882 100.094 0.852 c
+100.248 0.823 100.406 0.783 100.564 0.735 c
+100.718 0.684 100.858 0.621 100.975 0.544 c
+101.093 0.463 101.189 0.36 101.27 0.235 c
+101.347 0.106 101.387 -0.055 101.387 -0.249 c
+103.242 1.515 m
+103.36 1.786 103.511 1.985 103.699 2.103 c
+103.882 2.22 104.102 2.278 104.36 2.278 c
+104.566 2.278 104.734 2.242 104.875 2.176 c
+105.021 2.105 105.131 2.014 105.212 1.897 c
+105.301 1.779 105.359 1.635 105.389 1.47 c
+105.426 1.301 105.447 1.124 105.447 0.941 c
+105.447 -1.264 l
+104.536 -1.264 l
+104.536 0.735 l
+104.536 0.871 104.526 0.992 104.507 1.103 c
+104.495 1.209 104.47 1.297 104.433 1.367 c
+104.393 1.444 104.335 1.503 104.257 1.544 c
+104.187 1.58 104.096 1.602 103.978 1.602 c
+103.867 1.602 103.772 1.577 103.684 1.529 c
+103.595 1.477 103.514 1.411 103.448 1.323 c
+103.39 1.235 103.338 1.124 103.302 1 c
+103.272 0.882 103.257 0.75 103.257 0.603 c
+103.257 -1.264 l
+102.346 -1.264 l
+102.346 3.514 l
+103.257 3.514 l
+103.257 2.205 l
+103.257 2.135 103.25 2.065 103.242 1.999 c
+103.242 1.793 l
+103.242 1.735 103.236 1.679 103.228 1.632 c
+103.228 1.515 l
+h
+107.362 -1.323 m
+107.193 -1.323 107.042 -1.301 106.907 -1.264 c
+106.778 -1.216 106.664 -1.147 106.569 -1.058 c
+106.48 -0.97 106.411 -0.864 106.363 -0.735 c
+106.311 -0.599 106.289 -0.448 106.289 -0.279 c
+106.289 -0.073 106.322 0.096 106.392 0.235 c
+106.458 0.382 106.554 0.493 106.671 0.574 c
+106.797 0.661 106.939 0.724 107.098 0.765 c
+107.263 0.802 107.439 0.827 107.627 0.838 c
+108.347 0.852 l
+108.347 1.029 l
+108.347 1.147 108.336 1.249 108.318 1.338 c
+108.295 1.426 108.262 1.492 108.215 1.544 c
+108.175 1.602 108.127 1.639 108.067 1.661 c
+108.009 1.679 107.942 1.691 107.876 1.691 c
+107.807 1.691 107.745 1.679 107.685 1.661 c
+107.634 1.65 107.587 1.625 107.539 1.588 c
+107.498 1.558 107.465 1.507 107.435 1.44 c
+107.414 1.382 107.399 1.301 107.392 1.205 c
+106.451 1.249 l
+106.48 1.397 106.525 1.532 106.583 1.661 c
+106.649 1.786 106.745 1.897 106.862 1.985 c
+106.98 2.08 107.119 2.153 107.289 2.205 c
+107.465 2.253 107.67 2.278 107.906 2.278 c
+108.347 2.278 108.678 2.168 108.906 1.955 c
+109.141 1.75 109.258 1.44 109.258 1.029 c
+109.258 -0.235 l
+109.258 -0.455 l
+109.266 -0.515 109.28 -0.569 109.303 -0.617 c
+109.321 -0.658 109.351 -0.69 109.391 -0.72 c
+109.428 -0.742 109.479 -0.75 109.538 -0.75 c
+109.604 -0.75 109.673 -0.746 109.744 -0.735 c
+109.744 -1.22 l
+109.685 -1.23 109.629 -1.242 109.582 -1.249 c
+109.542 -1.261 109.501 -1.267 109.464 -1.278 c
+109.424 -1.286 109.38 -1.294 109.332 -1.294 c
+109.28 -1.301 109.222 -1.308 109.156 -1.308 c
+108.927 -1.308 108.763 -1.257 108.655 -1.147 c
+108.545 -1.029 108.483 -0.864 108.464 -0.646 c
+108.45 -0.646 l
+108.38 -0.757 108.31 -0.852 108.244 -0.941 c
+108.175 -1.022 108.098 -1.087 108.009 -1.147 c
+107.921 -1.205 107.822 -1.249 107.715 -1.278 c
+107.616 -1.308 107.498 -1.323 107.362 -1.323 c
+108.347 0.353 m
+107.921 0.339 l
+107.822 0.339 107.73 0.331 107.641 0.324 c
+107.56 0.312 107.495 0.287 107.435 0.25 c
+107.377 0.21 107.325 0.151 107.289 0.073 c
+107.248 0.004 107.23 -0.088 107.23 -0.206 c
+107.23 -0.374 107.263 -0.496 107.333 -0.573 c
+107.399 -0.654 107.498 -0.69 107.627 -0.69 c
+107.733 -0.69 107.832 -0.669 107.921 -0.617 c
+108.017 -0.569 108.098 -0.507 108.156 -0.426 c
+108.222 -0.349 108.273 -0.261 108.303 -0.162 c
+108.333 -0.055 108.347 0.059 108.347 0.177 c
+h
+110.835 -2.631 m
+110.835 -2.013 l
+111.908 -2.013 l
+111.908 2.896 l
+110.835 2.896 l
+110.835 3.514 l
+112.761 3.514 l
+112.761 -2.631 l
+h
+f
+Q
+q 1 0 0 1 300.6696 419.9752 cm
+0 0 m
+-0.029 -0.58 -0.191 -1.022 -0.485 -1.323 c
+-0.779 -1.628 -1.198 -1.779 -1.735 -1.779 c
+-2.263 -1.779 -2.69 -1.58 -3.013 -1.176 c
+-3.329 -0.765 -3.484 -0.206 -3.484 0.5 c
+-3.484 1.469 l
+-3.484 2.165 -3.322 2.712 -2.999 3.116 c
+-2.675 3.517 -2.23 3.719 -1.661 3.719 c
+-1.154 3.719 -0.757 3.561 -0.47 3.248 c
+-0.187 2.944 -0.029 2.502 0 1.926 c
+-0.69 1.926 l
+-0.721 2.366 -0.816 2.678 -0.97 2.866 c
+-1.118 3.05 -1.349 3.146 -1.661 3.146 c
+-2.036 3.146 -2.319 2.998 -2.514 2.705 c
+-2.712 2.418 -2.807 2.003 -2.807 1.455 c
+-2.807 0.47 l
+-2.807 -0.07 -2.716 -0.485 -2.529 -0.779 c
+-2.344 -1.066 -2.08 -1.205 -1.735 -1.205 c
+-1.382 -1.205 -1.128 -1.118 -0.97 -0.941 c
+-0.816 -0.765 -0.721 -0.453 -0.69 0 c
+h
+2.454 1.66 m
+2.367 1.679 2.267 1.691 2.161 1.691 c
+1.826 1.691 1.591 1.506 1.455 1.147 c
+1.455 -1.706 l
+0.808 -1.706 l
+0.808 2.278 l
+1.44 2.278 l
+1.455 1.866 l
+1.631 2.19 1.874 2.352 2.19 2.352 c
+2.296 2.352 2.385 2.329 2.454 2.293 c
+h
+4.453 -1.779 m
+3.954 -1.779 3.572 -1.632 3.308 -1.338 c
+3.042 -1.044 2.911 -0.611 2.911 -0.029 c
+2.911 0.441 l
+2.911 1.036 3.036 1.502 3.293 1.837 c
+3.557 2.179 3.917 2.352 4.38 2.352 c
+4.84 2.352 5.182 2.198 5.409 1.896 c
+5.644 1.602 5.766 1.139 5.777 0.515 c
+5.777 0.088 l
+3.557 0.088 l
+3.557 0 l
+3.557 -0.434 3.634 -0.746 3.792 -0.941 c
+3.958 -1.128 4.189 -1.22 4.484 -1.22 c
+4.678 -1.22 4.85 -1.187 4.997 -1.118 c
+5.145 -1.04 5.28 -0.923 5.409 -0.765 c
+5.747 -1.176 l
+5.461 -1.58 5.031 -1.779 4.453 -1.779 c
+4.38 1.793 m
+4.104 1.793 3.902 1.697 3.778 1.514 c
+3.649 1.326 3.576 1.036 3.557 0.646 c
+5.13 0.646 l
+5.13 0.735 l
+5.108 1.117 5.041 1.385 4.924 1.543 c
+4.806 1.708 4.623 1.793 4.38 1.793 c
+8.599 -1.706 m
+8.559 -1.617 8.533 -1.47 8.525 -1.264 c
+8.29 -1.61 7.996 -1.779 7.644 -1.779 c
+7.279 -1.779 6.996 -1.683 6.791 -1.484 c
+6.593 -1.279 6.497 -0.992 6.497 -0.617 c
+6.497 -0.217 6.633 0.103 6.909 0.338 c
+7.181 0.58 7.555 0.706 8.025 0.706 c
+8.511 0.706 l
+8.511 1.132 l
+8.511 1.367 8.455 1.532 8.349 1.631 c
+8.239 1.738 8.077 1.793 7.864 1.793 c
+7.665 1.793 7.504 1.735 7.379 1.617 c
+7.262 1.5 7.202 1.352 7.202 1.176 c
+6.556 1.176 l
+6.556 1.371 6.614 1.562 6.732 1.749 c
+6.857 1.932 7.019 2.08 7.217 2.19 c
+7.423 2.296 7.651 2.352 7.908 2.352 c
+8.309 2.352 8.613 2.248 8.819 2.043 c
+9.033 1.837 9.147 1.543 9.157 1.161 c
+9.157 -0.852 l
+9.157 -1.158 9.194 -1.422 9.275 -1.646 c
+9.275 -1.706 l
+h
+7.732 -1.191 m
+7.897 -1.191 8.048 -1.147 8.187 -1.058 c
+8.334 -0.97 8.441 -0.86 8.511 -0.721 c
+8.511 0.22 l
+8.143 0.22 l
+7.827 0.22 7.584 0.151 7.408 0.014 c
+7.231 -0.114 7.144 -0.302 7.144 -0.544 c
+7.144 -0.772 7.188 -0.937 7.276 -1.044 c
+7.364 -1.143 7.515 -1.191 7.732 -1.191 c
+11.009 3.233 m
+11.009 2.278 l
+11.612 2.278 l
+11.612 1.749 l
+11.009 1.749 l
+11.009 -0.721 l
+11.009 -0.879 11.032 -0.996 11.083 -1.073 c
+11.142 -1.154 11.23 -1.191 11.347 -1.191 c
+11.436 -1.191 11.524 -1.176 11.612 -1.147 c
+11.612 -1.706 l
+11.465 -1.753 11.311 -1.779 11.156 -1.779 c
+10.899 -1.779 10.705 -1.687 10.568 -1.5 c
+10.429 -1.316 10.363 -1.055 10.363 -0.721 c
+10.363 1.749 l
+9.76 1.749 l
+9.76 2.278 l
+10.363 2.278 l
+10.363 3.233 l
+h
+13.803 -1.779 m
+13.303 -1.779 12.92 -1.632 12.656 -1.338 c
+12.391 -1.044 12.259 -0.611 12.259 -0.029 c
+12.259 0.441 l
+12.259 1.036 12.384 1.502 12.641 1.837 c
+12.906 2.179 13.266 2.352 13.729 2.352 c
+14.188 2.352 14.53 2.198 14.757 1.896 c
+14.993 1.602 15.114 1.139 15.125 0.515 c
+15.125 0.088 l
+12.906 0.088 l
+12.906 0 l
+12.906 -0.434 12.983 -0.746 13.141 -0.941 c
+13.307 -1.128 13.538 -1.22 13.832 -1.22 c
+14.026 -1.22 14.2 -1.187 14.346 -1.118 c
+14.493 -1.04 14.629 -0.923 14.757 -0.765 c
+15.096 -1.176 l
+14.809 -1.58 14.379 -1.779 13.803 -1.779 c
+13.729 1.793 m
+13.454 1.793 13.251 1.697 13.126 1.514 c
+12.997 1.326 12.924 1.036 12.906 0.646 c
+14.479 0.646 l
+14.479 0.735 l
+14.456 1.117 14.391 1.385 14.273 1.543 c
+14.155 1.708 13.972 1.793 13.729 1.793 c
+19.667 -1.706 m
+19.627 -1.617 19.601 -1.47 19.594 -1.264 c
+19.359 -1.61 19.065 -1.779 18.712 -1.779 c
+18.348 -1.779 18.065 -1.683 17.859 -1.484 c
+17.661 -1.279 17.565 -0.992 17.565 -0.617 c
+17.565 -0.217 17.701 0.103 17.977 0.338 c
+18.248 0.58 18.624 0.706 19.094 0.706 c
+19.579 0.706 l
+19.579 1.132 l
+19.579 1.367 19.524 1.532 19.418 1.631 c
+19.307 1.738 19.146 1.793 18.932 1.793 c
+18.734 1.793 18.572 1.735 18.447 1.617 c
+18.329 1.5 18.271 1.352 18.271 1.176 c
+17.624 1.176 l
+17.624 1.371 17.683 1.562 17.801 1.749 c
+17.926 1.932 18.088 2.08 18.285 2.19 c
+18.491 2.296 18.719 2.352 18.977 2.352 c
+19.377 2.352 19.682 2.248 19.888 2.043 c
+20.101 1.837 20.215 1.543 20.226 1.161 c
+20.226 -0.852 l
+20.226 -1.158 20.263 -1.422 20.344 -1.646 c
+20.344 -1.706 l
+h
+18.8 -1.191 m
+18.965 -1.191 19.116 -1.147 19.256 -1.058 c
+19.403 -0.97 19.509 -0.86 19.579 -0.721 c
+19.579 0.22 l
+19.212 0.22 l
+18.896 0.22 18.653 0.151 18.477 0.014 c
+18.3 -0.114 18.212 -0.302 18.212 -0.544 c
+18.212 -0.772 18.256 -0.937 18.344 -1.044 c
+18.433 -1.143 18.583 -1.191 18.8 -1.191 c
+23.798 3.233 m
+23.798 2.278 l
+24.4 2.278 l
+24.4 1.749 l
+23.798 1.749 l
+23.798 -0.721 l
+23.798 -0.879 23.82 -0.996 23.871 -1.073 c
+23.93 -1.154 24.018 -1.191 24.136 -1.191 c
+24.224 -1.191 24.312 -1.176 24.4 -1.147 c
+24.4 -1.706 l
+24.253 -1.753 24.099 -1.779 23.945 -1.779 c
+23.688 -1.779 23.493 -1.687 23.357 -1.5 c
+23.217 -1.316 23.151 -1.055 23.151 -0.721 c
+23.151 1.749 l
+22.549 1.749 l
+22.549 2.278 l
+23.151 2.278 l
+23.151 3.233 l
+h
+27.208 -1.706 m
+27.168 -1.617 27.142 -1.47 27.135 -1.264 c
+26.9 -1.61 26.605 -1.779 26.252 -1.779 c
+25.888 -1.779 25.606 -1.683 25.4 -1.484 c
+25.201 -1.279 25.106 -0.992 25.106 -0.617 c
+25.106 -0.217 25.242 0.103 25.518 0.338 c
+25.789 0.58 26.164 0.706 26.634 0.706 c
+27.12 0.706 l
+27.12 1.132 l
+27.12 1.367 27.064 1.532 26.958 1.631 c
+26.848 1.738 26.686 1.793 26.473 1.793 c
+26.275 1.793 26.113 1.735 25.988 1.617 c
+25.87 1.5 25.811 1.352 25.811 1.176 c
+25.165 1.176 l
+25.165 1.371 25.223 1.562 25.341 1.749 c
+25.466 1.932 25.628 2.08 25.826 2.19 c
+26.032 2.296 26.26 2.352 26.517 2.352 c
+26.917 2.352 27.222 2.248 27.428 2.043 c
+27.642 1.837 27.756 1.543 27.767 1.161 c
+27.767 -0.852 l
+27.767 -1.158 27.804 -1.422 27.884 -1.646 c
+27.884 -1.706 l
+h
+26.341 -1.191 m
+26.506 -1.191 26.657 -1.147 26.796 -1.058 c
+26.944 -0.97 27.05 -0.86 27.12 -0.721 c
+27.12 0.22 l
+26.752 0.22 l
+26.437 0.22 26.194 0.151 26.017 0.014 c
+25.841 -0.114 25.753 -0.302 25.753 -0.544 c
+25.753 -0.772 25.797 -0.937 25.885 -1.044 c
+25.973 -1.143 26.123 -1.191 26.341 -1.191 c
+28.633 0.47 m
+28.633 1.088 28.744 1.55 28.972 1.866 c
+29.196 2.19 29.531 2.352 29.971 2.352 c
+30.372 2.352 30.677 2.175 30.883 1.822 c
+30.927 2.278 l
+31.515 2.278 l
+31.515 -1.75 l
+31.515 -2.238 31.386 -2.616 31.133 -2.882 c
+30.875 -3.146 30.522 -3.278 30.074 -3.278 c
+29.876 -3.278 29.655 -3.227 29.413 -3.131 c
+29.167 -3.032 28.986 -2.911 28.868 -2.764 c
+29.134 -2.323 l
+29.398 -2.587 29.695 -2.72 30.03 -2.72 c
+30.567 -2.72 30.842 -2.425 30.853 -1.837 c
+30.853 -1.309 l
+30.647 -1.625 30.346 -1.779 29.957 -1.779 c
+29.545 -1.779 29.221 -1.628 28.986 -1.323 c
+28.758 -1.01 28.641 -0.559 28.633 0.029 c
+h
+29.296 0.088 m
+29.296 -0.353 29.358 -0.684 29.487 -0.897 c
+29.612 -1.103 29.828 -1.205 30.133 -1.205 c
+30.456 -1.205 30.695 -1.04 30.853 -0.706 c
+30.853 1.278 l
+30.684 1.602 30.445 1.764 30.133 1.764 c
+29.839 1.764 29.622 1.66 29.487 1.455 c
+29.358 1.249 29.296 0.926 29.296 0.484 c
+h
+35.837 1.66 m
+35.748 1.679 35.649 1.691 35.542 1.691 c
+35.208 1.691 34.973 1.506 34.837 1.147 c
+34.837 -1.706 l
+34.19 -1.706 l
+34.19 2.278 l
+34.822 2.278 l
+34.837 1.866 l
+35.013 2.19 35.256 2.352 35.571 2.352 c
+35.678 2.352 35.766 2.329 35.837 2.293 c
+h
+37.836 -1.779 m
+37.335 -1.779 36.953 -1.632 36.689 -1.338 c
+36.424 -1.044 36.292 -0.611 36.292 -0.029 c
+36.292 0.441 l
+36.292 1.036 36.417 1.502 36.674 1.837 c
+36.939 2.179 37.298 2.352 37.762 2.352 c
+38.221 2.352 38.563 2.198 38.79 1.896 c
+39.026 1.602 39.147 1.139 39.158 0.515 c
+39.158 0.088 l
+36.939 0.088 l
+36.939 0 l
+36.939 -0.434 37.016 -0.746 37.174 -0.941 c
+37.339 -1.128 37.57 -1.22 37.865 -1.22 c
+38.06 -1.22 38.233 -1.187 38.379 -1.118 c
+38.526 -1.04 38.663 -0.923 38.79 -0.765 c
+39.129 -1.176 l
+38.842 -1.58 38.412 -1.779 37.836 -1.779 c
+37.762 1.793 m
+37.487 1.793 37.284 1.697 37.159 1.514 c
+37.03 1.326 36.957 1.036 36.939 0.646 c
+38.511 0.646 l
+38.511 0.735 l
+38.489 1.117 38.424 1.385 38.306 1.543 c
+38.188 1.708 38.004 1.793 37.762 1.793 c
+40.232 -1.706 m
+40.232 1.749 l
+39.702 1.749 l
+39.702 2.278 l
+40.232 2.278 l
+40.232 2.734 l
+40.232 3.135 40.327 3.447 40.525 3.675 c
+40.731 3.898 41.011 4.012 41.363 4.012 c
+41.499 4.012 41.632 3.991 41.76 3.954 c
+41.73 3.41 l
+41.632 3.428 41.532 3.439 41.437 3.439 c
+41.061 3.439 40.878 3.175 40.878 2.645 c
+40.878 2.278 l
+41.554 2.278 l
+41.554 1.749 l
+40.878 1.749 l
+40.878 -1.706 l
+h
+43.656 -1.779 m
+43.156 -1.779 42.774 -1.632 42.509 -1.338 c
+42.245 -1.044 42.113 -0.611 42.113 -0.029 c
+42.113 0.441 l
+42.113 1.036 42.237 1.502 42.495 1.837 c
+42.759 2.179 43.12 2.352 43.583 2.352 c
+44.042 2.352 44.384 2.198 44.612 1.896 c
+44.847 1.602 44.968 1.139 44.979 0.515 c
+44.979 0.088 l
+42.759 0.088 l
+42.759 0 l
+42.759 -0.434 42.837 -0.746 42.995 -0.941 c
+43.16 -1.128 43.392 -1.22 43.685 -1.22 c
+43.881 -1.22 44.053 -1.187 44.2 -1.118 c
+44.347 -1.04 44.483 -0.923 44.612 -0.765 c
+44.949 -1.176 l
+44.663 -1.58 44.233 -1.779 43.656 -1.779 c
+43.583 1.793 m
+43.307 1.793 43.105 1.697 42.98 1.514 c
+42.852 1.326 42.778 1.036 42.759 0.646 c
+44.332 0.646 l
+44.332 0.735 l
+44.311 1.117 44.244 1.385 44.126 1.543 c
+44.009 1.708 43.825 1.793 43.583 1.793 c
+47.405 1.66 m
+47.316 1.679 47.217 1.691 47.11 1.691 c
+46.776 1.691 46.541 1.506 46.405 1.147 c
+46.405 -1.706 l
+45.759 -1.706 l
+45.759 2.278 l
+46.39 2.278 l
+46.405 1.866 l
+46.582 2.19 46.823 2.352 47.14 2.352 c
+47.247 2.352 47.334 2.329 47.405 2.293 c
+h
+49.404 -1.779 m
+48.903 -1.779 48.521 -1.632 48.257 -1.338 c
+47.993 -1.044 47.86 -0.611 47.86 -0.029 c
+47.86 0.441 l
+47.86 1.036 47.985 1.502 48.242 1.837 c
+48.506 2.179 48.867 2.352 49.33 2.352 c
+49.79 2.352 50.131 2.198 50.359 1.896 c
+50.594 1.602 50.715 1.139 50.727 0.515 c
+50.727 0.088 l
+48.506 0.088 l
+48.506 0 l
+48.506 -0.434 48.584 -0.746 48.742 -0.941 c
+48.907 -1.128 49.139 -1.22 49.433 -1.22 c
+49.628 -1.22 49.8 -1.187 49.948 -1.118 c
+50.094 -1.04 50.231 -0.923 50.359 -0.765 c
+50.697 -1.176 l
+50.41 -1.58 49.981 -1.779 49.404 -1.779 c
+49.33 1.793 m
+49.055 1.793 48.853 1.697 48.727 1.514 c
+48.599 1.326 48.525 1.036 48.506 0.646 c
+50.079 0.646 l
+50.079 0.735 l
+50.058 1.117 49.992 1.385 49.874 1.543 c
+49.757 1.708 49.572 1.793 49.33 1.793 c
+52.123 2.278 m
+52.138 1.837 l
+52.391 2.179 52.714 2.352 53.108 2.352 c
+53.813 2.352 54.17 1.882 54.181 0.941 c
+54.181 -1.706 l
+53.534 -1.706 l
+53.534 0.912 l
+53.534 1.224 53.479 1.444 53.372 1.573 c
+53.262 1.697 53.108 1.764 52.902 1.764 c
+52.743 1.764 52.597 1.708 52.461 1.602 c
+52.332 1.492 52.229 1.356 52.152 1.19 c
+52.152 -1.706 l
+51.505 -1.706 l
+51.505 2.278 l
+h
+56.533 -1.22 m
+56.745 -1.22 56.918 -1.158 57.047 -1.029 c
+57.183 -0.893 57.256 -0.702 57.268 -0.456 c
+57.885 -0.456 l
+57.863 -0.838 57.727 -1.158 57.474 -1.411 c
+57.216 -1.658 56.903 -1.779 56.533 -1.779 c
+56.04 -1.779 55.665 -1.628 55.401 -1.323 c
+55.143 -1.01 55.018 -0.544 55.018 0.073 c
+55.018 0.515 l
+55.018 1.109 55.143 1.565 55.401 1.882 c
+55.665 2.194 56.04 2.352 56.533 2.352 c
+56.933 2.352 57.252 2.219 57.488 1.955 c
+57.73 1.697 57.863 1.352 57.885 0.912 c
+57.268 0.912 l
+57.246 1.205 57.172 1.425 57.047 1.573 c
+56.93 1.72 56.757 1.793 56.533 1.793 c
+56.238 1.793 56.022 1.694 55.886 1.5 c
+55.746 1.311 55.673 1.003 55.665 0.573 c
+55.665 0.058 l
+55.665 -0.412 55.731 -0.746 55.871 -0.941 c
+56.018 -1.128 56.238 -1.22 56.533 -1.22 c
+60.061 -1.779 m
+59.56 -1.779 59.178 -1.632 58.914 -1.338 c
+58.649 -1.044 58.517 -0.611 58.517 -0.029 c
+58.517 0.441 l
+58.517 1.036 58.642 1.502 58.899 1.837 c
+59.164 2.179 59.523 2.352 59.987 2.352 c
+60.446 2.352 60.788 2.198 61.015 1.896 c
+61.251 1.602 61.372 1.139 61.383 0.515 c
+61.383 0.088 l
+59.164 0.088 l
+59.164 0 l
+59.164 -0.434 59.241 -0.746 59.399 -0.941 c
+59.564 -1.128 59.795 -1.22 60.09 -1.22 c
+60.284 -1.22 60.458 -1.187 60.604 -1.118 c
+60.751 -1.04 60.887 -0.923 61.015 -0.765 c
+61.354 -1.176 l
+61.067 -1.58 60.637 -1.779 60.061 -1.779 c
+59.987 1.793 m
+59.712 1.793 59.509 1.697 59.384 1.514 c
+59.255 1.326 59.182 1.036 59.164 0.646 c
+60.736 0.646 l
+60.736 0.735 l
+60.714 1.117 60.649 1.385 60.531 1.543 c
+60.413 1.708 60.229 1.793 59.987 1.793 c
+64.499 2.278 m
+64.514 1.837 l
+64.768 2.179 65.091 2.352 65.484 2.352 c
+66.189 2.352 66.546 1.882 66.557 0.941 c
+66.557 -1.706 l
+65.91 -1.706 l
+65.91 0.912 l
+65.91 1.224 65.856 1.444 65.749 1.573 c
+65.638 1.697 65.484 1.764 65.279 1.764 c
+65.121 1.764 64.973 1.708 64.838 1.602 c
+64.709 1.492 64.606 1.356 64.529 1.19 c
+64.529 -1.706 l
+63.882 -1.706 l
+63.882 2.278 l
+h
+69.57 -1.706 m
+69.53 -1.617 69.505 -1.47 69.497 -1.264 c
+69.262 -1.61 68.967 -1.779 68.615 -1.779 c
+68.252 -1.779 67.968 -1.683 67.762 -1.484 c
+67.564 -1.279 67.469 -0.992 67.469 -0.617 c
+67.469 -0.217 67.604 0.103 67.88 0.338 c
+68.152 0.58 68.527 0.706 68.998 0.706 c
+69.482 0.706 l
+69.482 1.132 l
+69.482 1.367 69.428 1.532 69.32 1.631 c
+69.21 1.738 69.048 1.793 68.836 1.793 c
+68.637 1.793 68.475 1.735 68.35 1.617 c
+68.233 1.5 68.174 1.352 68.174 1.176 c
+67.527 1.176 l
+67.527 1.371 67.586 1.562 67.704 1.749 c
+67.829 1.932 67.99 2.08 68.189 2.19 c
+68.395 2.296 68.622 2.352 68.88 2.352 c
+69.281 2.352 69.586 2.248 69.791 2.043 c
+70.004 1.837 70.118 1.543 70.129 1.161 c
+70.129 -0.852 l
+70.129 -1.158 70.166 -1.422 70.247 -1.646 c
+70.247 -1.706 l
+h
+68.703 -1.191 m
+68.869 -1.191 69.019 -1.147 69.159 -1.058 c
+69.306 -0.97 69.412 -0.86 69.482 -0.721 c
+69.482 0.22 l
+69.115 0.22 l
+68.799 0.22 68.556 0.151 68.38 0.014 c
+68.204 -0.114 68.115 -0.302 68.115 -0.544 c
+68.115 -0.772 68.159 -0.937 68.248 -1.044 c
+68.336 -1.143 68.487 -1.191 68.703 -1.191 c
+71.746 2.278 m
+71.761 1.911 l
+72.003 2.205 72.323 2.352 72.716 2.352 c
+73.158 2.352 73.466 2.153 73.642 1.764 c
+73.896 2.153 74.245 2.352 74.686 2.352 c
+75.421 2.352 75.795 1.889 75.818 0.97 c
+75.818 -1.706 l
+75.171 -1.706 l
+75.171 0.912 l
+75.171 1.205 75.116 1.419 75.009 1.558 c
+74.91 1.694 74.737 1.764 74.494 1.764 c
+74.297 1.764 74.135 1.683 74.01 1.529 c
+73.892 1.382 73.823 1.19 73.804 0.955 c
+73.804 -1.706 l
+73.142 -1.706 l
+73.142 0.941 l
+73.142 1.488 72.922 1.764 72.481 1.764 c
+72.146 1.764 71.911 1.602 71.776 1.278 c
+71.776 -1.706 l
+71.128 -1.706 l
+71.128 2.278 l
+h
+78.214 -1.779 m
+77.714 -1.779 77.332 -1.632 77.067 -1.338 c
+76.803 -1.044 76.67 -0.611 76.67 -0.029 c
+76.67 0.441 l
+76.67 1.036 76.795 1.502 77.052 1.837 c
+77.317 2.179 77.677 2.352 78.14 2.352 c
+78.6 2.352 78.941 2.198 79.169 1.896 c
+79.404 1.602 79.525 1.139 79.537 0.515 c
+79.537 0.088 l
+77.317 0.088 l
+77.317 0 l
+77.317 -0.434 77.394 -0.746 77.552 -0.941 c
+77.717 -1.128 77.949 -1.22 78.243 -1.22 c
+78.438 -1.22 78.61 -1.187 78.758 -1.118 c
+78.905 -1.04 79.04 -0.923 79.169 -0.765 c
+79.508 -1.176 l
+79.221 -1.58 78.791 -1.779 78.214 -1.779 c
+78.14 1.793 m
+77.864 1.793 77.663 1.697 77.538 1.514 c
+77.409 1.326 77.335 1.036 77.317 0.646 c
+78.889 0.646 l
+78.889 0.735 l
+78.868 1.117 78.802 1.385 78.684 1.543 c
+78.567 1.708 78.382 1.793 78.14 1.793 c
+80.183 0.47 m
+80.183 1.076 80.294 1.543 80.522 1.866 c
+80.757 2.19 81.083 2.352 81.507 2.352 c
+81.889 2.352 82.186 2.194 82.403 1.882 c
+82.403 3.939 l
+83.049 3.939 l
+83.049 -1.706 l
+82.461 -1.706 l
+82.417 -1.279 l
+82.212 -1.613 81.906 -1.779 81.507 -1.779 c
+81.095 -1.779 80.771 -1.625 80.536 -1.309 c
+80.301 -0.985 80.183 -0.53 80.183 0.058 c
+h
+80.83 0.088 m
+80.83 -0.353 80.892 -0.684 81.021 -0.897 c
+81.157 -1.103 81.378 -1.205 81.683 -1.205 c
+82.006 -1.205 82.245 -1.044 82.403 -0.721 c
+82.403 1.294 l
+82.234 1.606 81.995 1.764 81.683 1.764 c
+81.378 1.764 81.157 1.66 81.021 1.455 c
+80.892 1.249 80.83 0.926 80.83 0.484 c
+h
+f
+Q
+q 1 0 0 1 387.291 422.2537 cm
+0 0 m
+0.029 -0.397 l
+0.264 -0.085 0.566 0.073 0.941 0.073 c
+1.625 0.073 1.977 -0.408 1.999 -1.367 c
+1.999 -3.984 l
+0.956 -3.984 l
+0.956 -1.441 l
+0.956 -1.216 0.919 -1.055 0.852 -0.956 c
+0.783 -0.86 0.665 -0.809 0.5 -0.809 c
+0.312 -0.809 0.166 -0.904 0.059 -1.088 c
+0.059 -3.984 l
+-0.985 -3.984 l
+-0.985 0 l
+h
+4.63 -3.984 m
+4.601 -3.925 4.571 -3.822 4.542 -3.675 c
+4.355 -3.932 4.104 -4.057 3.792 -4.057 c
+3.458 -4.057 3.179 -3.951 2.955 -3.734 c
+2.738 -3.51 2.631 -3.219 2.631 -2.866 c
+2.631 -2.455 2.764 -2.139 3.028 -1.912 c
+3.293 -1.676 3.675 -1.559 4.175 -1.559 c
+4.498 -1.559 l
+4.498 -1.235 l
+4.498 -1.058 4.461 -0.937 4.395 -0.867 c
+4.336 -0.79 4.248 -0.75 4.131 -0.75 c
+3.873 -0.75 3.748 -0.904 3.748 -1.206 c
+2.705 -1.206 l
+2.705 -0.834 2.841 -0.53 3.117 -0.294 c
+3.389 -0.052 3.738 0.073 4.16 0.073 c
+4.601 0.073 4.939 -0.044 5.174 -0.279 c
+5.417 -0.507 5.542 -0.831 5.542 -1.249 c
+5.542 -3.117 l
+5.542 -3.462 5.589 -3.73 5.689 -3.925 c
+5.689 -3.984 l
+h
+4.027 -3.234 m
+4.135 -3.234 4.226 -3.215 4.307 -3.175 c
+4.395 -3.128 4.457 -3.069 4.498 -2.999 c
+4.498 -2.176 l
+4.248 -2.176 l
+4.072 -2.176 3.929 -2.234 3.822 -2.352 c
+3.723 -2.463 3.675 -2.61 3.675 -2.793 c
+3.675 -3.088 3.792 -3.234 4.027 -3.234 c
+7.262 0 m
+7.291 -0.368 l
+7.526 -0.073 7.835 0.073 8.216 0.073 c
+8.617 0.073 8.897 -0.111 9.055 -0.47 c
+9.29 -0.111 9.617 0.073 10.04 0.073 c
+10.734 0.073 11.087 -0.412 11.098 -1.382 c
+11.098 -3.984 l
+10.069 -3.984 l
+10.069 -1.441 l
+10.069 -1.216 10.032 -1.055 9.966 -0.956 c
+9.907 -0.86 9.797 -0.809 9.643 -0.809 c
+9.444 -0.809 9.305 -0.927 9.216 -1.162 c
+9.216 -3.984 l
+8.173 -3.984 l
+8.173 -1.455 l
+8.173 -1.22 8.143 -1.055 8.085 -0.956 c
+8.025 -0.86 7.915 -0.809 7.761 -0.809 c
+7.585 -0.809 7.441 -0.904 7.335 -1.088 c
+7.335 -3.984 l
+6.292 -3.984 l
+6.292 0 l
+h
+13.479 -4.057 m
+12.95 -4.057 12.531 -3.903 12.23 -3.587 c
+11.936 -3.263 11.788 -2.804 11.788 -2.205 c
+11.788 -1.897 l
+11.788 -1.272 11.925 -0.786 12.2 -0.441 c
+12.472 -0.1 12.866 0.073 13.376 0.073 c
+13.876 0.073 14.247 -0.088 14.493 -0.412 c
+14.747 -0.736 14.88 -1.213 14.89 -1.837 c
+14.89 -2.338 l
+12.818 -2.338 l
+12.836 -2.631 12.898 -2.849 13.009 -2.984 c
+13.126 -3.124 13.307 -3.19 13.552 -3.19 c
+13.895 -3.19 14.184 -3.072 14.42 -2.837 c
+14.832 -3.469 l
+14.703 -3.645 14.516 -3.789 14.273 -3.896 c
+14.026 -4.002 13.762 -4.057 13.479 -4.057 c
+12.833 -1.617 m
+13.861 -1.617 l
+13.861 -1.515 l
+13.861 -1.279 13.82 -1.103 13.743 -0.985 c
+13.674 -0.86 13.546 -0.794 13.361 -0.794 c
+13.185 -0.794 13.053 -0.864 12.964 -1 c
+12.883 -1.129 12.84 -1.334 12.833 -1.617 c
+f
+Q
+q 1 0 0 1 404.8857 418.2697 cm
+0 0 m
+0 3.454 l
+-0.529 3.454 l
+-0.529 3.984 l
+0 3.984 l
+0 4.439 l
+0 4.84 0.096 5.152 0.294 5.38 c
+0.5 5.604 0.779 5.718 1.132 5.718 c
+1.268 5.718 1.4 5.696 1.529 5.66 c
+1.5 5.116 l
+1.4 5.134 1.301 5.145 1.205 5.145 c
+0.831 5.145 0.647 4.881 0.647 4.351 c
+0.647 3.984 l
+1.323 3.984 l
+1.323 3.454 l
+0.647 3.454 l
+0.647 0 l
+h
+1.955 2.176 m
+1.955 2.753 2.091 3.208 2.367 3.543 c
+2.65 3.884 3.021 4.057 3.484 4.057 c
+3.944 4.057 4.31 3.888 4.586 3.558 c
+4.869 3.234 5.016 2.786 5.027 2.22 c
+5.027 1.794 l
+5.027 1.224 4.884 0.769 4.601 0.426 c
+4.326 0.092 3.958 -0.073 3.499 -0.073 c
+3.036 -0.073 2.664 0.088 2.381 0.412 c
+2.105 0.742 1.962 1.183 1.955 1.735 c
+h
+2.602 1.794 m
+2.602 1.389 2.679 1.073 2.837 0.838 c
+3.003 0.603 3.223 0.485 3.499 0.485 c
+4.065 0.485 4.358 0.897 4.38 1.72 c
+4.38 2.176 l
+4.38 2.577 4.296 2.896 4.131 3.131 c
+3.973 3.373 3.755 3.499 3.484 3.499 c
+3.219 3.499 3.003 3.373 2.837 3.131 c
+2.679 2.896 2.602 2.577 2.602 2.176 c
+h
+7.512 3.366 m
+7.423 3.385 7.324 3.396 7.217 3.396 c
+6.883 3.396 6.648 3.212 6.512 2.852 c
+6.512 0 l
+5.865 0 l
+5.865 3.984 l
+6.497 3.984 l
+6.512 3.572 l
+6.689 3.896 6.93 4.057 7.247 4.057 c
+7.354 4.057 7.441 4.035 7.512 3.998 c
+h
+11.26 0.485 m
+11.473 0.485 11.645 0.548 11.774 0.676 c
+11.91 0.813 11.983 1.004 11.994 1.249 c
+12.612 1.249 l
+12.59 0.867 12.454 0.548 12.2 0.294 c
+11.944 0.048 11.631 -0.073 11.26 -0.073 c
+10.768 -0.073 10.392 0.077 10.128 0.383 c
+9.87 0.695 9.746 1.162 9.746 1.779 c
+9.746 2.22 l
+9.746 2.815 9.87 3.271 10.128 3.587 c
+10.392 3.899 10.768 4.057 11.26 4.057 c
+11.66 4.057 11.98 3.925 12.215 3.66 c
+12.457 3.403 12.59 3.057 12.612 2.617 c
+11.994 2.617 l
+11.973 2.911 11.899 3.131 11.774 3.279 c
+11.657 3.425 11.484 3.499 11.26 3.499 c
+10.965 3.499 10.749 3.4 10.612 3.205 c
+10.473 3.017 10.4 2.708 10.392 2.279 c
+10.392 1.764 l
+10.392 1.294 10.458 0.96 10.598 0.765 c
+10.745 0.578 10.965 0.485 11.26 0.485 c
+15.39 0.353 m
+15.173 0.067 14.861 -0.073 14.45 -0.073 c
+14.086 -0.073 13.81 0.048 13.627 0.294 c
+13.45 0.548 13.355 0.912 13.347 1.382 c
+13.347 3.984 l
+13.993 3.984 l
+13.993 1.441 l
+13.993 0.813 14.178 0.5 14.552 0.5 c
+14.953 0.5 15.229 0.676 15.375 1.029 c
+15.375 3.984 l
+16.022 3.984 l
+16.022 0 l
+15.405 0 l
+h
+18.653 3.366 m
+18.565 3.385 18.466 3.396 18.359 3.396 c
+18.025 3.396 17.789 3.212 17.654 2.852 c
+17.654 0 l
+17.007 0 l
+17.007 3.984 l
+17.639 3.984 l
+17.654 3.572 l
+17.83 3.896 18.073 4.057 18.389 4.057 c
+18.495 4.057 18.583 4.035 18.653 3.998 c
+h
+20.947 3.366 m
+20.858 3.385 20.759 3.396 20.652 3.396 c
+20.318 3.396 20.083 3.212 19.947 2.852 c
+19.947 0 l
+19.3 0 l
+19.3 3.984 l
+19.932 3.984 l
+19.947 3.572 l
+20.123 3.896 20.366 4.057 20.682 4.057 c
+20.788 4.057 20.877 4.035 20.947 3.998 c
+h
+22.946 -0.073 m
+22.446 -0.073 22.063 0.073 21.799 0.368 c
+21.534 0.661 21.402 1.095 21.402 1.676 c
+21.402 2.147 l
+21.402 2.741 21.527 3.208 21.784 3.543 c
+22.049 3.884 22.409 4.057 22.872 4.057 c
+23.331 4.057 23.673 3.903 23.9 3.601 c
+24.136 3.308 24.257 2.845 24.268 2.22 c
+24.268 1.794 l
+22.049 1.794 l
+22.049 1.706 l
+22.049 1.272 22.126 0.96 22.284 0.765 c
+22.45 0.578 22.681 0.485 22.975 0.485 c
+23.169 0.485 23.343 0.518 23.489 0.588 c
+23.636 0.665 23.772 0.783 23.9 0.941 c
+24.239 0.53 l
+23.952 0.125 23.522 -0.073 22.946 -0.073 c
+22.872 3.499 m
+22.597 3.499 22.394 3.403 22.269 3.219 c
+22.14 3.032 22.067 2.741 22.049 2.352 c
+23.622 2.352 l
+23.622 2.44 l
+23.599 2.822 23.534 3.09 23.416 3.248 c
+23.298 3.414 23.115 3.499 22.872 3.499 c
+25.664 3.984 m
+25.679 3.543 l
+25.933 3.884 26.256 4.057 26.649 4.057 c
+27.355 4.057 27.711 3.587 27.723 2.646 c
+27.723 0 l
+27.075 0 l
+27.075 2.617 l
+27.075 2.929 27.021 3.15 26.915 3.279 c
+26.804 3.403 26.649 3.469 26.444 3.469 c
+26.286 3.469 26.138 3.414 26.003 3.308 c
+25.874 3.198 25.772 3.061 25.694 2.896 c
+25.694 0 l
+25.047 0 l
+25.047 3.984 l
+h
+29.545 4.939 m
+29.545 3.984 l
+30.148 3.984 l
+30.148 3.454 l
+29.545 3.454 l
+29.545 0.985 l
+29.545 0.827 29.567 0.709 29.619 0.632 c
+29.677 0.551 29.766 0.515 29.884 0.515 c
+29.972 0.515 30.059 0.53 30.148 0.559 c
+30.148 0 l
+30.001 -0.047 29.847 -0.073 29.693 -0.073 c
+29.435 -0.073 29.24 0.019 29.105 0.206 c
+28.964 0.389 28.899 0.651 28.899 0.985 c
+28.899 3.454 l
+28.296 3.454 l
+28.296 3.984 l
+28.899 3.984 l
+28.899 4.939 l
+h
+34.013 0.485 m
+34.227 0.485 34.4 0.548 34.528 0.676 c
+34.664 0.813 34.738 1.004 34.749 1.249 c
+35.366 1.249 l
+35.345 0.867 35.208 0.548 34.954 0.294 c
+34.697 0.048 34.385 -0.073 34.013 -0.073 c
+33.521 -0.073 33.147 0.077 32.882 0.383 c
+32.625 0.695 32.5 1.162 32.5 1.779 c
+32.5 2.22 l
+32.5 2.815 32.625 3.271 32.882 3.587 c
+33.147 3.899 33.521 4.057 34.013 4.057 c
+34.414 4.057 34.734 3.925 34.969 3.66 c
+35.212 3.403 35.345 3.057 35.366 2.617 c
+34.749 2.617 l
+34.726 2.911 34.653 3.131 34.528 3.279 c
+34.41 3.425 34.238 3.499 34.013 3.499 c
+33.72 3.499 33.503 3.4 33.367 3.205 c
+33.228 3.017 33.154 2.708 33.147 2.279 c
+33.147 1.764 l
+33.147 1.294 33.213 0.96 33.352 0.765 c
+33.5 0.578 33.72 0.485 34.013 0.485 c
+35.983 2.176 m
+35.983 2.753 36.12 3.208 36.395 3.543 c
+36.678 3.884 37.049 4.057 37.512 4.057 c
+37.972 4.057 38.339 3.888 38.615 3.558 c
+38.898 3.234 39.044 2.786 39.056 2.22 c
+39.056 1.794 l
+39.056 1.224 38.913 0.769 38.63 0.426 c
+38.354 0.092 37.986 -0.073 37.527 -0.073 c
+37.064 -0.073 36.693 0.088 36.409 0.412 c
+36.134 0.742 35.991 1.183 35.983 1.735 c
+h
+36.63 1.794 m
+36.63 1.389 36.708 1.073 36.866 0.838 c
+37.031 0.603 37.251 0.485 37.527 0.485 c
+38.092 0.485 38.387 0.897 38.409 1.72 c
+38.409 2.176 l
+38.409 2.577 38.324 2.896 38.159 3.131 c
+38.001 3.373 37.784 3.499 37.512 3.499 c
+37.248 3.499 37.031 3.373 36.866 3.131 c
+36.708 2.896 36.63 2.577 36.63 2.176 c
+h
+40.511 3.984 m
+40.525 3.616 l
+40.768 3.911 41.088 4.057 41.481 4.057 c
+41.922 4.057 42.231 3.859 42.407 3.469 c
+42.661 3.859 43.01 4.057 43.451 4.057 c
+44.186 4.057 44.56 3.595 44.583 2.675 c
+44.583 0 l
+43.935 0 l
+43.935 2.617 l
+43.935 2.911 43.881 3.124 43.774 3.263 c
+43.675 3.4 43.502 3.469 43.26 3.469 c
+43.061 3.469 42.9 3.389 42.774 3.234 c
+42.657 3.088 42.587 2.896 42.568 2.66 c
+42.568 0 l
+41.907 0 l
+41.907 2.646 l
+41.907 3.194 41.687 3.469 41.246 3.469 c
+40.911 3.469 40.676 3.308 40.54 2.984 c
+40.54 0 l
+39.893 0 l
+39.893 3.984 l
+h
+46.17 3.984 m
+46.185 3.616 l
+46.427 3.911 46.747 4.057 47.14 4.057 c
+47.581 4.057 47.889 3.859 48.066 3.469 c
+48.32 3.859 48.669 4.057 49.109 4.057 c
+49.845 4.057 50.219 3.595 50.241 2.675 c
+50.241 0 l
+49.595 0 l
+49.595 2.617 l
+49.595 2.911 49.539 3.124 49.433 3.263 c
+49.334 3.4 49.161 3.469 48.918 3.469 c
+48.72 3.469 48.558 3.389 48.434 3.234 c
+48.316 3.088 48.246 2.896 48.228 2.66 c
+48.228 0 l
+47.567 0 l
+47.567 2.646 l
+47.567 3.194 47.346 3.469 46.905 3.469 c
+46.57 3.469 46.335 3.308 46.2 2.984 c
+46.2 0 l
+45.552 0 l
+45.552 3.984 l
+h
+51.918 0 -0.647 3.984 re
+51.962 5.027 m
+51.962 4.917 51.932 4.825 51.873 4.748 c
+51.814 4.678 51.719 4.645 51.594 4.645 c
+51.476 4.645 51.38 4.678 51.315 4.748 c
+51.256 4.825 51.226 4.917 51.226 5.027 c
+51.226 5.145 51.256 5.237 51.315 5.307 c
+51.38 5.384 51.476 5.424 51.594 5.424 c
+51.719 5.424 51.814 5.384 51.873 5.307 c
+51.932 5.226 51.962 5.134 51.962 5.027 c
+53.784 4.939 m
+53.784 3.984 l
+54.387 3.984 l
+54.387 3.454 l
+53.784 3.454 l
+53.784 0.985 l
+53.784 0.827 53.807 0.709 53.857 0.632 c
+53.917 0.551 54.004 0.515 54.122 0.515 c
+54.21 0.515 54.299 0.53 54.387 0.559 c
+54.387 0 l
+54.239 -0.047 54.085 -0.073 53.931 -0.073 c
+53.674 -0.073 53.479 0.019 53.343 0.206 c
+53.203 0.389 53.138 0.651 53.138 0.985 c
+53.138 3.454 l
+52.535 3.454 l
+52.535 3.984 l
+53.138 3.984 l
+53.138 4.939 l
+h
+55.195 0.353 m
+55.195 0.47 55.228 0.566 55.298 0.647 c
+55.364 0.724 55.467 0.765 55.607 0.765 c
+55.754 0.765 55.86 0.724 55.93 0.647 c
+56.007 0.566 56.047 0.47 56.047 0.353 c
+56.047 0.243 56.007 0.151 55.93 0.073 c
+55.86 -0.004 55.754 -0.044 55.607 -0.044 c
+55.467 -0.044 55.364 -0.004 55.298 0.073 c
+55.228 0.151 55.195 0.243 55.195 0.353 c
+61.443 1.397 m
+59.634 1.397 l
+59.222 0 l
+58.532 0 l
+60.252 5.351 l
+60.824 5.351 l
+62.559 0 l
+61.869 0 l
+h
+59.81 1.985 m
+61.266 1.985 l
+60.546 4.41 l
+h
+63.059 2.176 m
+63.059 2.782 63.17 3.248 63.397 3.572 c
+63.633 3.896 63.959 4.057 64.382 4.057 c
+64.764 4.057 65.062 3.899 65.279 3.587 c
+65.279 5.644 l
+65.925 5.644 l
+65.925 0 l
+65.337 0 l
+65.293 0.426 l
+65.088 0.092 64.783 -0.073 64.382 -0.073 c
+63.97 -0.073 63.647 0.081 63.411 0.397 c
+63.176 0.721 63.059 1.176 63.059 1.764 c
+h
+63.706 1.794 m
+63.706 1.353 63.768 1.022 63.897 0.809 c
+64.033 0.603 64.253 0.5 64.558 0.5 c
+64.882 0.5 65.121 0.661 65.279 0.985 c
+65.279 2.999 l
+65.109 3.311 64.871 3.469 64.558 3.469 c
+64.253 3.469 64.033 3.366 63.897 3.161 c
+63.768 2.955 63.706 2.631 63.706 2.19 c
+h
+66.792 2.176 m
+66.792 2.782 66.903 3.248 67.131 3.572 c
+67.366 3.896 67.693 4.057 68.115 4.057 c
+68.498 4.057 68.795 3.899 69.013 3.587 c
+69.013 5.644 l
+69.659 5.644 l
+69.659 0 l
+69.071 0 l
+69.027 0.426 l
+68.821 0.092 68.516 -0.073 68.115 -0.073 c
+67.704 -0.073 67.38 0.081 67.145 0.397 c
+66.91 0.721 66.792 1.176 66.792 1.764 c
+h
+67.44 1.794 m
+67.44 1.353 67.502 1.022 67.631 0.809 c
+67.766 0.603 67.987 0.5 68.292 0.5 c
+68.616 0.5 68.855 0.661 69.013 0.985 c
+69.013 2.999 l
+68.843 3.311 68.604 3.469 68.292 3.469 c
+67.987 3.469 67.766 3.366 67.631 3.161 c
+67.502 2.955 67.44 2.631 67.44 2.19 c
+h
+f
+Q
+q 1 0 0 1 478.602 419.0637 cm
+0 0 m
+0.294 0 0.444 0.195 0.455 0.588 c
+1.425 0.588 l
+1.425 0.154 1.294 -0.198 1.028 -0.47 c
+0.764 -0.735 0.426 -0.867 0.014 -0.867 c
+-0.497 -0.867 -0.89 -0.713 -1.162 -0.397 c
+-1.426 -0.073 -1.565 0.397 -1.573 1.014 c
+-1.573 1.338 l
+-1.573 1.962 -1.441 2.44 -1.176 2.764 c
+-0.904 3.094 -0.507 3.263 0.014 3.263 c
+0.444 3.263 0.786 3.123 1.043 2.851 c
+1.296 2.576 1.425 2.194 1.425 1.706 c
+0.455 1.706 l
+0.455 1.918 0.415 2.087 0.338 2.205 c
+0.268 2.33 0.151 2.396 -0.015 2.396 c
+-0.192 2.396 -0.32 2.33 -0.397 2.205 c
+-0.478 2.076 -0.522 1.826 -0.53 1.455 c
+-0.53 1.043 l
+-0.53 0.721 -0.515 0.492 -0.485 0.368 c
+-0.449 0.239 -0.393 0.147 -0.324 0.088 c
+-0.246 0.029 -0.14 0 0 0 c
+1.911 1.323 m
+1.911 1.929 2.05 2.404 2.337 2.749 c
+2.62 3.09 3.013 3.263 3.513 3.263 c
+4.02 3.263 4.417 3.09 4.704 2.749 c
+4.986 2.404 5.13 1.929 5.13 1.323 c
+5.13 1.058 l
+5.13 0.459 4.986 -0.011 4.704 -0.353 c
+4.417 -0.698 4.02 -0.867 3.513 -0.867 c
+3.002 -0.867 2.605 -0.698 2.322 -0.353 c
+2.046 -0.011 1.911 0.463 1.911 1.073 c
+h
+2.954 1.058 m
+2.954 0.353 3.138 0 3.513 0 c
+3.866 0 4.056 0.294 4.086 0.882 c
+4.086 1.323 l
+4.086 1.683 4.035 1.955 3.939 2.132 c
+3.84 2.308 3.696 2.396 3.513 2.396 c
+3.336 2.396 3.197 2.308 3.101 2.132 c
+3.002 1.955 2.954 1.683 2.954 1.323 c
+h
+6.746 3.19 m
+6.776 2.822 l
+7.011 3.117 7.32 3.263 7.702 3.263 c
+8.103 3.263 8.382 3.079 8.54 2.72 c
+8.775 3.079 9.102 3.263 9.525 3.263 c
+10.219 3.263 10.572 2.778 10.583 1.808 c
+10.583 -0.794 l
+9.554 -0.794 l
+9.554 1.749 l
+9.554 1.974 9.517 2.135 9.451 2.234 c
+9.392 2.33 9.282 2.381 9.128 2.381 c
+8.93 2.381 8.789 2.263 8.702 2.028 c
+8.702 -0.794 l
+7.658 -0.794 l
+7.658 1.735 l
+7.658 1.97 7.628 2.135 7.569 2.234 c
+7.511 2.33 7.401 2.381 7.247 2.381 c
+7.07 2.381 6.927 2.286 6.82 2.102 c
+6.82 -0.794 l
+5.776 -0.794 l
+5.776 3.19 l
+h
+12.332 3.19 m
+12.361 2.822 l
+12.596 3.117 12.905 3.263 13.288 3.263 c
+13.688 3.263 13.967 3.079 14.125 2.72 c
+14.36 3.079 14.688 3.263 15.11 3.263 c
+15.804 3.263 16.157 2.778 16.168 1.808 c
+16.168 -0.794 l
+15.139 -0.794 l
+15.139 1.749 l
+15.139 1.974 15.103 2.135 15.037 2.234 c
+14.978 2.33 14.867 2.381 14.713 2.381 c
+14.515 2.381 14.375 2.263 14.287 2.028 c
+14.287 -0.794 l
+13.244 -0.794 l
+13.244 1.735 l
+13.244 1.97 13.214 2.135 13.155 2.234 c
+13.096 2.33 12.986 2.381 12.832 2.381 c
+12.656 2.381 12.512 2.286 12.406 2.102 c
+12.406 -0.794 l
+11.362 -0.794 l
+11.362 3.19 l
+h
+18.035 -0.794 -1.043 3.984 re
+16.947 4.218 m
+16.947 4.373 16.995 4.501 17.094 4.601 c
+17.201 4.707 17.337 4.763 17.506 4.763 c
+17.682 4.763 17.819 4.707 17.917 4.601 c
+18.025 4.501 18.079 4.373 18.079 4.218 c
+18.079 4.05 18.025 3.913 17.917 3.807 c
+17.819 3.707 17.682 3.66 17.506 3.66 c
+17.337 3.66 17.201 3.707 17.094 3.807 c
+16.995 3.913 16.947 4.05 16.947 4.218 c
+20.049 4.16 m
+20.049 3.19 l
+20.579 3.19 l
+20.579 2.396 l
+20.049 2.396 l
+20.049 0.426 l
+20.049 0.268 20.068 0.162 20.108 0.103 c
+20.155 0.044 20.24 0.015 20.358 0.015 c
+20.465 0.015 20.549 0.022 20.608 0.044 c
+20.608 -0.764 l
+20.431 -0.831 20.24 -0.867 20.034 -0.867 c
+19.359 -0.867 19.013 -0.482 19.006 0.294 c
+19.006 2.396 l
+18.549 2.396 l
+18.549 3.19 l
+19.006 3.19 l
+19.006 4.16 l
+h
+24.65 0.279 m
+24.65 0.368 24.606 0.445 24.518 0.515 c
+24.429 0.592 24.242 0.694 23.959 0.823 c
+23.525 1 23.228 1.18 23.062 1.367 c
+22.904 1.55 22.827 1.783 22.827 2.058 c
+22.827 2.4 22.948 2.683 23.195 2.911 c
+23.448 3.146 23.787 3.263 24.209 3.263 c
+24.639 3.263 24.988 3.15 25.252 2.925 c
+25.518 2.697 25.649 2.396 25.649 2.014 c
+24.606 2.014 l
+24.606 2.337 24.466 2.499 24.194 2.499 c
+24.084 2.499 23.995 2.462 23.93 2.396 c
+23.86 2.326 23.827 2.227 23.827 2.102 c
+23.827 2.014 23.864 1.933 23.945 1.866 c
+24.022 1.808 24.201 1.712 24.488 1.588 c
+24.918 1.43 25.216 1.253 25.385 1.058 c
+25.561 0.871 25.649 0.621 25.649 0.309 c
+25.649 -0.044 25.518 -0.331 25.252 -0.544 c
+24.988 -0.761 24.639 -0.867 24.209 -0.867 c
+23.915 -0.867 23.654 -0.812 23.43 -0.706 c
+23.202 -0.588 23.026 -0.426 22.9 -0.22 c
+22.783 -0.015 22.725 0.206 22.725 0.441 c
+23.71 0.441 l
+23.71 0.254 23.746 0.118 23.827 0.029 c
+23.915 -0.058 24.047 -0.103 24.224 -0.103 c
+24.506 -0.103 24.65 0.022 24.65 0.279 c
+27.325 2.837 m
+27.55 3.119 27.825 3.263 28.148 3.263 c
+28.508 3.263 28.784 3.135 28.971 2.881 c
+29.167 2.624 29.266 2.242 29.266 1.735 c
+29.266 -0.794 l
+28.222 -0.794 l
+28.222 1.72 l
+28.222 1.955 28.182 2.12 28.105 2.219 c
+28.034 2.326 27.92 2.381 27.766 2.381 c
+27.579 2.381 27.432 2.296 27.325 2.132 c
+27.325 -0.794 l
+26.281 -0.794 l
+26.281 4.85 l
+27.325 4.85 l
+h
+31.897 -0.794 m
+31.868 -0.735 31.837 -0.632 31.808 -0.485 c
+31.621 -0.742 31.371 -0.867 31.059 -0.867 c
+30.725 -0.867 30.445 -0.761 30.221 -0.544 c
+30.004 -0.32 29.898 -0.029 29.898 0.324 c
+29.898 0.735 30.029 1.051 30.295 1.278 c
+30.559 1.514 30.941 1.631 31.44 1.631 c
+31.764 1.631 l
+31.764 1.955 l
+31.764 2.132 31.727 2.253 31.662 2.323 c
+31.602 2.4 31.515 2.44 31.397 2.44 c
+31.139 2.44 31.014 2.286 31.014 1.984 c
+29.971 1.984 l
+29.971 2.356 30.107 2.66 30.382 2.896 c
+30.655 3.138 31.004 3.263 31.426 3.263 c
+31.868 3.263 32.205 3.146 32.44 2.911 c
+32.683 2.683 32.808 2.359 32.808 1.941 c
+32.808 0.073 l
+32.808 -0.272 32.855 -0.54 32.955 -0.735 c
+32.955 -0.794 l
+h
+31.294 -0.044 m
+31.4 -0.044 31.492 -0.025 31.573 0.015 c
+31.662 0.062 31.724 0.121 31.764 0.191 c
+31.764 1.014 l
+31.515 1.014 l
+31.338 1.014 31.195 0.956 31.088 0.838 c
+30.989 0.727 30.941 0.58 30.941 0.397 c
+30.941 0.103 31.059 -0.044 31.294 -0.044 c
+f
+Q
+q 1 0 0 1 514.8346 423.2085 cm
+0 0 m
+0 -0.955 l
+0.603 -0.955 l
+0.603 -1.484 l
+0 -1.484 l
+0 -3.954 l
+0 -4.112 0.023 -4.23 0.073 -4.307 c
+0.133 -4.388 0.221 -4.424 0.339 -4.424 c
+0.426 -4.424 0.515 -4.409 0.603 -4.38 c
+0.603 -4.939 l
+0.456 -4.986 0.302 -5.012 0.147 -5.012 c
+-0.11 -5.012 -0.305 -4.92 -0.441 -4.733 c
+-0.58 -4.549 -0.646 -4.288 -0.646 -3.954 c
+-0.646 -1.484 l
+-1.249 -1.484 l
+-1.249 -0.955 l
+-0.646 -0.955 l
+-0.646 0 l
+h
+1.162 -2.763 m
+1.162 -2.186 1.297 -1.731 1.573 -1.396 c
+1.856 -1.055 2.227 -0.881 2.691 -0.881 c
+3.15 -0.881 3.517 -1.051 3.792 -1.381 c
+4.075 -1.705 4.223 -2.153 4.233 -2.719 c
+4.233 -3.145 l
+4.233 -3.715 4.09 -4.17 3.807 -4.513 c
+3.532 -4.847 3.164 -5.012 2.705 -5.012 c
+2.242 -5.012 1.871 -4.85 1.588 -4.527 c
+1.312 -4.197 1.168 -3.755 1.162 -3.204 c
+h
+1.808 -3.145 m
+1.808 -3.549 1.885 -3.865 2.043 -4.101 c
+2.209 -4.336 2.429 -4.453 2.705 -4.453 c
+3.271 -4.453 3.564 -4.042 3.587 -3.219 c
+3.587 -2.763 l
+3.587 -2.362 3.502 -2.043 3.337 -1.808 c
+3.179 -1.565 2.962 -1.44 2.691 -1.44 c
+2.425 -1.44 2.209 -1.565 2.043 -1.808 c
+1.885 -2.043 1.808 -2.362 1.808 -2.763 c
+h
+f
+Q
+q 1 0 0 1 388.0258 413.8011 cm
+0 0 m
+0 -0.955 l
+0.603 -0.955 l
+0.603 -1.484 l
+0 -1.484 l
+0 -3.954 l
+0 -4.112 0.023 -4.23 0.073 -4.307 c
+0.133 -4.388 0.221 -4.424 0.339 -4.424 c
+0.426 -4.424 0.515 -4.409 0.603 -4.38 c
+0.603 -4.939 l
+0.456 -4.986 0.302 -5.012 0.148 -5.012 c
+-0.11 -5.012 -0.305 -4.92 -0.44 -4.733 c
+-0.58 -4.549 -0.646 -4.288 -0.646 -3.954 c
+-0.646 -1.484 l
+-1.249 -1.484 l
+-1.249 -0.955 l
+-0.646 -0.955 l
+-0.646 0 l
+h
+3.41 -4.939 m
+3.37 -4.85 3.344 -4.704 3.337 -4.498 c
+3.102 -4.843 2.808 -5.012 2.455 -5.012 c
+2.091 -5.012 1.808 -4.916 1.602 -4.718 c
+1.405 -4.513 1.309 -4.226 1.309 -3.85 c
+1.309 -3.451 1.445 -3.131 1.72 -2.896 c
+1.992 -2.653 2.367 -2.528 2.837 -2.528 c
+3.323 -2.528 l
+3.323 -2.102 l
+3.323 -1.866 3.267 -1.701 3.161 -1.602 c
+3.051 -1.496 2.889 -1.44 2.675 -1.44 c
+2.477 -1.44 2.315 -1.499 2.19 -1.616 c
+2.072 -1.734 2.014 -1.882 2.014 -2.057 c
+1.367 -2.057 l
+1.367 -1.863 1.426 -1.672 1.544 -1.484 c
+1.669 -1.301 1.831 -1.153 2.029 -1.043 c
+2.234 -0.937 2.463 -0.881 2.72 -0.881 c
+3.12 -0.881 3.425 -0.985 3.631 -1.19 c
+3.844 -1.396 3.958 -1.691 3.969 -2.072 c
+3.969 -4.086 l
+3.969 -4.391 4.006 -4.656 4.087 -4.88 c
+4.087 -4.939 l
+h
+2.543 -4.424 m
+2.708 -4.424 2.859 -4.38 2.999 -4.292 c
+3.146 -4.203 3.252 -4.093 3.323 -3.954 c
+3.323 -3.013 l
+2.955 -3.013 l
+2.639 -3.013 2.396 -3.083 2.22 -3.219 c
+2.043 -3.347 1.955 -3.535 1.955 -3.777 c
+1.955 -4.006 1.999 -4.17 2.087 -4.278 c
+2.176 -4.376 2.326 -4.424 2.543 -4.424 c
+4.836 -2.763 m
+4.836 -2.146 4.946 -1.683 5.174 -1.367 c
+5.399 -1.043 5.733 -0.881 6.174 -0.881 c
+6.575 -0.881 6.88 -1.058 7.086 -1.411 c
+7.129 -0.955 l
+7.717 -0.955 l
+7.717 -4.983 l
+7.717 -5.471 7.589 -5.85 7.335 -6.115 c
+7.078 -6.379 6.725 -6.512 6.277 -6.512 c
+6.078 -6.512 5.858 -6.46 5.615 -6.364 c
+5.369 -6.265 5.189 -6.144 5.072 -5.997 c
+5.336 -5.556 l
+5.6 -5.82 5.898 -5.953 6.232 -5.953 c
+6.77 -5.953 7.045 -5.659 7.056 -5.071 c
+7.056 -4.542 l
+6.85 -4.858 6.548 -5.012 6.159 -5.012 c
+5.748 -5.012 5.424 -4.862 5.189 -4.556 c
+4.961 -4.244 4.844 -3.792 4.836 -3.204 c
+h
+5.498 -3.145 m
+5.498 -3.586 5.56 -3.917 5.689 -4.13 c
+5.814 -4.336 6.03 -4.438 6.336 -4.438 c
+6.659 -4.438 6.897 -4.274 7.056 -3.939 c
+7.056 -1.955 l
+6.887 -1.631 6.648 -1.469 6.336 -1.469 c
+6.041 -1.469 5.825 -1.573 5.689 -1.778 c
+5.56 -1.984 5.498 -2.308 5.498 -2.749 c
+h
+12.436 -4.939 m
+12.395 -4.85 12.37 -4.704 12.362 -4.498 c
+12.127 -4.843 11.833 -5.012 11.48 -5.012 c
+11.117 -5.012 10.834 -4.916 10.628 -4.718 c
+10.429 -4.513 10.334 -4.226 10.334 -3.85 c
+10.334 -3.451 10.469 -3.131 10.745 -2.896 c
+11.017 -2.653 11.392 -2.528 11.863 -2.528 c
+12.347 -2.528 l
+12.347 -2.102 l
+12.347 -1.866 12.293 -1.701 12.185 -1.602 c
+12.075 -1.496 11.914 -1.44 11.701 -1.44 c
+11.502 -1.44 11.341 -1.499 11.215 -1.616 c
+11.098 -1.734 11.04 -1.882 11.04 -2.057 c
+10.392 -2.057 l
+10.392 -1.863 10.452 -1.672 10.569 -1.484 c
+10.694 -1.301 10.855 -1.153 11.054 -1.043 c
+11.26 -0.937 11.487 -0.881 11.745 -0.881 c
+12.145 -0.881 12.451 -0.985 12.656 -1.19 c
+12.869 -1.396 12.983 -1.691 12.994 -2.072 c
+12.994 -4.086 l
+12.994 -4.391 13.031 -4.656 13.112 -4.88 c
+13.112 -4.939 l
+h
+11.568 -4.424 m
+11.734 -4.424 11.884 -4.38 12.025 -4.292 c
+12.171 -4.203 12.278 -4.093 12.347 -3.954 c
+12.347 -3.013 l
+11.98 -3.013 l
+11.664 -3.013 11.422 -3.083 11.245 -3.219 c
+11.069 -3.347 10.98 -3.535 10.98 -3.777 c
+10.98 -4.006 11.025 -4.17 11.113 -4.278 c
+11.201 -4.376 11.352 -4.424 11.568 -4.424 c
+17.654 -3.925 m
+17.654 -3.777 17.598 -3.656 17.492 -3.557 c
+17.382 -3.461 17.176 -3.343 16.875 -3.204 c
+16.53 -3.057 16.287 -2.936 16.14 -2.836 c
+15.993 -2.73 15.883 -2.612 15.817 -2.484 c
+15.747 -2.359 15.713 -2.201 15.713 -2.013 c
+15.713 -1.691 15.831 -1.421 16.066 -1.205 c
+16.301 -0.992 16.603 -0.881 16.978 -0.881 c
+17.359 -0.881 17.669 -0.995 17.904 -1.22 c
+18.139 -1.448 18.257 -1.734 18.257 -2.087 c
+17.61 -2.087 l
+17.61 -1.911 17.551 -1.76 17.434 -1.631 c
+17.316 -1.506 17.162 -1.44 16.978 -1.44 c
+16.779 -1.44 16.629 -1.496 16.522 -1.602 c
+16.412 -1.701 16.36 -1.833 16.36 -1.999 c
+16.36 -2.127 16.397 -2.234 16.478 -2.322 c
+16.555 -2.403 16.746 -2.506 17.051 -2.631 c
+17.529 -2.818 17.86 -3.006 18.036 -3.189 c
+18.213 -3.366 18.3 -3.594 18.3 -3.865 c
+18.3 -4.218 18.176 -4.498 17.933 -4.704 c
+17.698 -4.909 17.382 -5.012 16.993 -5.012 c
+16.57 -5.012 16.232 -4.895 15.978 -4.659 c
+15.721 -4.417 15.596 -4.112 15.596 -3.748 c
+16.243 -3.748 l
+16.25 -3.976 16.32 -4.152 16.449 -4.278 c
+16.574 -4.395 16.757 -4.453 16.993 -4.453 c
+17.205 -4.453 17.367 -4.405 17.477 -4.307 c
+17.595 -4.211 17.654 -4.083 17.654 -3.925 c
+22.02 -3.145 m
+22.02 -3.773 21.902 -4.244 21.667 -4.556 c
+21.439 -4.862 21.122 -5.012 20.711 -5.012 c
+20.307 -5.012 19.998 -4.862 19.786 -4.556 c
+19.786 -6.468 l
+19.138 -6.468 l
+19.138 -0.955 l
+19.726 -0.955 l
+19.771 -1.396 l
+19.984 -1.055 20.293 -0.881 20.696 -0.881 c
+21.137 -0.881 21.465 -1.036 21.681 -1.338 c
+21.895 -1.643 22.009 -2.098 22.02 -2.705 c
+h
+21.373 -2.763 m
+21.373 -2.322 21.303 -1.999 21.167 -1.793 c
+21.027 -1.579 20.807 -1.469 20.505 -1.469 c
+20.189 -1.469 19.95 -1.624 19.786 -1.926 c
+19.786 -3.998 l
+19.95 -4.303 20.189 -4.453 20.505 -4.453 c
+20.8 -4.453 21.012 -4.351 21.152 -4.145 c
+21.288 -3.931 21.361 -3.601 21.373 -3.16 c
+h
+24.283 -5.012 m
+23.784 -5.012 23.401 -4.866 23.137 -4.571 c
+22.872 -4.278 22.74 -3.844 22.74 -3.262 c
+22.74 -2.792 l
+22.74 -2.198 22.865 -1.731 23.121 -1.396 c
+23.387 -1.055 23.747 -0.881 24.21 -0.881 c
+24.669 -0.881 25.01 -1.036 25.238 -1.338 c
+25.473 -1.631 25.595 -2.094 25.606 -2.719 c
+25.606 -3.145 l
+23.387 -3.145 l
+23.387 -3.233 l
+23.387 -3.667 23.464 -3.979 23.622 -4.174 c
+23.788 -4.361 24.019 -4.453 24.312 -4.453 c
+24.507 -4.453 24.68 -4.421 24.827 -4.351 c
+24.974 -4.274 25.11 -4.156 25.238 -3.998 c
+25.577 -4.409 l
+25.29 -4.814 24.86 -5.012 24.283 -5.012 c
+24.21 -1.44 m
+23.934 -1.44 23.732 -1.536 23.607 -1.72 c
+23.478 -1.907 23.405 -2.198 23.387 -2.587 c
+24.96 -2.587 l
+24.96 -2.499 l
+24.937 -2.117 24.871 -1.849 24.754 -1.691 c
+24.636 -1.525 24.453 -1.44 24.21 -1.44 c
+27.767 -4.453 m
+27.98 -4.453 28.153 -4.391 28.281 -4.262 c
+28.417 -4.126 28.491 -3.935 28.502 -3.69 c
+29.119 -3.69 l
+29.097 -4.072 28.962 -4.391 28.708 -4.644 c
+28.451 -4.891 28.138 -5.012 27.767 -5.012 c
+27.275 -5.012 26.899 -4.862 26.635 -4.556 c
+26.377 -4.244 26.253 -3.777 26.253 -3.16 c
+26.253 -2.719 l
+26.253 -2.124 26.377 -1.668 26.635 -1.352 c
+26.899 -1.04 27.275 -0.881 27.767 -0.881 c
+28.168 -0.881 28.487 -1.014 28.723 -1.278 c
+28.964 -1.536 29.097 -1.882 29.119 -2.322 c
+28.502 -2.322 l
+28.48 -2.028 28.407 -1.808 28.281 -1.66 c
+28.164 -1.514 27.991 -1.44 27.767 -1.44 c
+27.472 -1.44 27.256 -1.539 27.12 -1.734 c
+26.98 -1.922 26.907 -2.23 26.899 -2.66 c
+26.899 -3.175 l
+26.899 -3.645 26.965 -3.979 27.105 -4.174 c
+27.252 -4.361 27.472 -4.453 27.767 -4.453 c
+30.574 -4.939 -0.646 3.984 re
+30.618 0.088 m
+30.618 -0.022 30.589 -0.114 30.53 -0.191 c
+30.471 -0.261 30.376 -0.293 30.251 -0.293 c
+30.134 -0.293 30.038 -0.261 29.972 -0.191 c
+29.913 -0.114 29.884 -0.022 29.884 0.088 c
+29.884 0.206 29.913 0.298 29.972 0.368 c
+30.038 0.445 30.134 0.485 30.251 0.485 c
+30.376 0.485 30.471 0.445 30.53 0.368 c
+30.589 0.287 30.618 0.195 30.618 0.088 c
+31.765 -4.939 m
+31.765 -1.484 l
+31.25 -1.484 l
+31.25 -0.955 l
+31.765 -0.955 l
+31.765 -0.588 l
+31.773 -0.158 31.886 0.177 32.103 0.412 c
+32.328 0.655 32.64 0.779 33.043 0.779 c
+33.191 0.779 33.33 0.757 33.47 0.721 c
+33.617 0.68 33.768 0.625 33.926 0.559 c
+33.808 -0.014 l
+33.573 0.11 33.33 0.177 33.088 0.177 c
+32.841 0.177 32.669 0.107 32.573 -0.029 c
+32.474 -0.158 32.426 -0.353 32.426 -0.617 c
+32.426 -0.955 l
+33.074 -0.955 l
+33.074 -1.484 l
+32.426 -1.484 l
+32.426 -4.939 l
+h
+34.234 -4.939 -0.647 3.984 re
+36.66 -4.453 m
+36.873 -4.453 37.045 -4.391 37.174 -4.262 c
+37.31 -4.126 37.384 -3.935 37.394 -3.69 c
+38.012 -3.69 l
+37.99 -4.072 37.854 -4.391 37.6 -4.644 c
+37.344 -4.891 37.031 -5.012 36.66 -5.012 c
+36.168 -5.012 35.792 -4.862 35.528 -4.556 c
+35.271 -4.244 35.146 -3.777 35.146 -3.16 c
+35.146 -2.719 l
+35.146 -2.124 35.271 -1.668 35.528 -1.352 c
+35.792 -1.04 36.168 -0.881 36.66 -0.881 c
+37.06 -0.881 37.38 -1.014 37.615 -1.278 c
+37.858 -1.536 37.99 -1.882 38.012 -2.322 c
+37.394 -2.322 l
+37.373 -2.028 37.299 -1.808 37.174 -1.66 c
+37.057 -1.514 36.884 -1.44 36.66 -1.44 c
+36.366 -1.44 36.149 -1.539 36.013 -1.734 c
+35.873 -1.922 35.8 -2.23 35.792 -2.66 c
+35.792 -3.175 l
+35.792 -3.645 35.859 -3.979 35.998 -4.174 c
+36.145 -4.361 36.366 -4.453 36.66 -4.453 c
+41.863 -4.453 m
+42.076 -4.453 42.249 -4.391 42.377 -4.262 c
+42.514 -4.126 42.587 -3.935 42.599 -3.69 c
+43.216 -3.69 l
+43.193 -4.072 43.058 -4.391 42.804 -4.644 c
+42.547 -4.891 42.234 -5.012 41.863 -5.012 c
+41.371 -5.012 40.996 -4.862 40.731 -4.556 c
+40.474 -4.244 40.349 -3.777 40.349 -3.16 c
+40.349 -2.719 l
+40.349 -2.124 40.474 -1.668 40.731 -1.352 c
+40.996 -1.04 41.371 -0.881 41.863 -0.881 c
+42.264 -0.881 42.583 -1.014 42.819 -1.278 c
+43.061 -1.536 43.193 -1.882 43.216 -2.322 c
+42.599 -2.322 l
+42.576 -2.028 42.503 -1.808 42.377 -1.66 c
+42.26 -1.514 42.088 -1.44 41.863 -1.44 c
+41.569 -1.44 41.352 -1.539 41.217 -1.734 c
+41.076 -1.922 41.003 -2.23 40.996 -2.66 c
+40.996 -3.175 l
+40.996 -3.645 41.062 -3.979 41.202 -4.174 c
+41.348 -4.361 41.569 -4.453 41.863 -4.453 c
+43.833 -2.763 m
+43.833 -2.186 43.969 -1.731 44.245 -1.396 c
+44.527 -1.055 44.899 -0.881 45.362 -0.881 c
+45.821 -0.881 46.188 -1.051 46.464 -1.381 c
+46.747 -1.705 46.894 -2.153 46.905 -2.719 c
+46.905 -3.145 l
+46.905 -3.715 46.761 -4.17 46.479 -4.513 c
+46.203 -4.847 45.836 -5.012 45.377 -5.012 c
+44.914 -5.012 44.542 -4.85 44.259 -4.527 c
+43.983 -4.197 43.84 -3.755 43.833 -3.204 c
+h
+44.48 -3.145 m
+44.48 -3.549 44.557 -3.865 44.715 -4.101 c
+44.88 -4.336 45.101 -4.453 45.377 -4.453 c
+45.942 -4.453 46.236 -4.042 46.258 -3.219 c
+46.258 -2.763 l
+46.258 -2.362 46.173 -2.043 46.009 -1.808 c
+45.851 -1.565 45.633 -1.44 45.362 -1.44 c
+45.097 -1.44 44.88 -1.565 44.715 -1.808 c
+44.557 -2.043 44.48 -2.362 44.48 -2.763 c
+h
+48.361 -0.955 m
+48.375 -1.323 l
+48.617 -1.028 48.937 -0.881 49.33 -0.881 c
+49.772 -0.881 50.08 -1.08 50.256 -1.469 c
+50.51 -1.08 50.859 -0.881 51.3 -0.881 c
+52.035 -0.881 52.41 -1.344 52.432 -2.263 c
+52.432 -4.939 l
+51.785 -4.939 l
+51.785 -2.322 l
+51.785 -2.028 51.73 -1.815 51.623 -1.675 c
+51.524 -1.539 51.351 -1.469 51.108 -1.469 c
+50.911 -1.469 50.749 -1.55 50.624 -1.705 c
+50.506 -1.851 50.437 -2.043 50.418 -2.278 c
+50.418 -4.939 l
+49.757 -4.939 l
+49.757 -2.293 l
+49.757 -1.745 49.536 -1.469 49.095 -1.469 c
+48.76 -1.469 48.525 -1.631 48.39 -1.955 c
+48.39 -4.939 l
+47.743 -4.939 l
+47.743 -0.955 l
+h
+54.019 -0.955 m
+54.034 -1.323 l
+54.277 -1.028 54.597 -0.881 54.989 -0.881 c
+55.43 -0.881 55.739 -1.08 55.916 -1.469 c
+56.169 -1.08 56.518 -0.881 56.959 -0.881 c
+57.694 -0.881 58.069 -1.344 58.091 -2.263 c
+58.091 -4.939 l
+57.444 -4.939 l
+57.444 -2.322 l
+57.444 -2.028 57.389 -1.815 57.283 -1.675 c
+57.184 -1.539 57.011 -1.469 56.768 -1.469 c
+56.569 -1.469 56.408 -1.55 56.283 -1.705 c
+56.165 -1.851 56.095 -2.043 56.077 -2.278 c
+56.077 -4.939 l
+55.416 -4.939 l
+55.416 -2.293 l
+55.416 -1.745 55.195 -1.469 54.754 -1.469 c
+54.42 -1.469 54.185 -1.631 54.048 -1.955 c
+54.048 -4.939 l
+53.402 -4.939 l
+53.402 -0.955 l
+h
+59.767 -4.939 -0.647 3.984 re
+59.81 0.088 m
+59.81 -0.022 59.781 -0.114 59.723 -0.191 c
+59.664 -0.261 59.569 -0.293 59.443 -0.293 c
+59.326 -0.293 59.23 -0.261 59.164 -0.191 c
+59.105 -0.114 59.076 -0.022 59.076 0.088 c
+59.076 0.206 59.105 0.298 59.164 0.368 c
+59.23 0.445 59.326 0.485 59.443 0.485 c
+59.569 0.485 59.664 0.445 59.723 0.368 c
+59.781 0.287 59.81 0.195 59.81 0.088 c
+61.633 0 m
+61.633 -0.955 l
+62.236 -0.955 l
+62.236 -1.484 l
+61.633 -1.484 l
+61.633 -3.954 l
+61.633 -4.112 61.655 -4.23 61.707 -4.307 c
+61.766 -4.388 61.854 -4.424 61.971 -4.424 c
+62.06 -4.424 62.148 -4.409 62.236 -4.38 c
+62.236 -4.939 l
+62.089 -4.986 61.935 -5.012 61.78 -5.012 c
+61.523 -5.012 61.329 -4.92 61.192 -4.733 c
+61.053 -4.549 60.986 -4.288 60.986 -3.954 c
+60.986 -1.484 l
+60.384 -1.484 l
+60.384 -0.955 l
+60.986 -0.955 l
+60.986 0 l
+h
+65.426 -4.939 -0.646 3.984 re
+65.47 0.088 m
+65.47 -0.022 65.441 -0.114 65.381 -0.191 c
+65.323 -0.261 65.227 -0.293 65.102 -0.293 c
+64.984 -0.293 64.889 -0.261 64.824 -0.191 c
+64.764 -0.114 64.735 -0.022 64.735 0.088 c
+64.735 0.206 64.764 0.298 64.824 0.368 c
+64.889 0.445 64.984 0.485 65.102 0.485 c
+65.227 0.485 65.323 0.445 65.381 0.368 c
+65.441 0.287 65.47 0.195 65.47 0.088 c
+67.058 -0.955 m
+67.072 -1.396 l
+67.326 -1.055 67.649 -0.881 68.042 -0.881 c
+68.747 -0.881 69.104 -1.352 69.115 -2.293 c
+69.115 -4.939 l
+68.469 -4.939 l
+68.469 -2.322 l
+68.469 -2.009 68.413 -1.789 68.307 -1.66 c
+68.197 -1.536 68.042 -1.469 67.837 -1.469 c
+67.679 -1.469 67.532 -1.525 67.396 -1.631 c
+67.267 -1.741 67.164 -1.878 67.087 -2.043 c
+67.087 -4.939 l
+66.44 -4.939 l
+66.44 -0.955 l
+h
+72.026 -3.925 m
+72.026 -3.777 71.97 -3.656 71.864 -3.557 c
+71.754 -3.461 71.548 -3.343 71.247 -3.204 c
+70.902 -3.057 70.659 -2.936 70.511 -2.836 c
+70.364 -2.73 70.254 -2.612 70.189 -2.484 c
+70.119 -2.359 70.085 -2.201 70.085 -2.013 c
+70.085 -1.691 70.203 -1.421 70.438 -1.205 c
+70.673 -0.992 70.975 -0.881 71.349 -0.881 c
+71.731 -0.881 72.04 -0.995 72.275 -1.22 c
+72.51 -1.448 72.628 -1.734 72.628 -2.087 c
+71.982 -2.087 l
+71.982 -1.911 71.922 -1.76 71.805 -1.631 c
+71.687 -1.506 71.533 -1.44 71.349 -1.44 c
+71.151 -1.44 71 -1.496 70.894 -1.602 c
+70.784 -1.701 70.732 -1.833 70.732 -1.999 c
+70.732 -2.127 70.769 -2.234 70.85 -2.322 c
+70.927 -2.403 71.118 -2.506 71.423 -2.631 c
+71.901 -2.818 72.232 -3.006 72.408 -3.189 c
+72.585 -3.366 72.672 -3.594 72.672 -3.865 c
+72.672 -4.218 72.548 -4.498 72.305 -4.704 c
+72.07 -4.909 71.754 -5.012 71.364 -5.012 c
+70.941 -5.012 70.603 -4.895 70.35 -4.659 c
+70.093 -4.417 69.967 -4.112 69.967 -3.748 c
+70.615 -3.748 l
+70.622 -3.976 70.692 -4.152 70.821 -4.278 c
+70.945 -4.395 71.129 -4.453 71.364 -4.453 c
+71.577 -4.453 71.739 -4.405 71.849 -4.307 c
+71.967 -4.211 72.026 -4.083 72.026 -3.925 c
+74.363 0 m
+74.363 -0.955 l
+74.966 -0.955 l
+74.966 -1.484 l
+74.363 -1.484 l
+74.363 -3.954 l
+74.363 -4.112 74.385 -4.23 74.436 -4.307 c
+74.495 -4.388 74.584 -4.424 74.701 -4.424 c
+74.789 -4.424 74.877 -4.409 74.966 -4.38 c
+74.966 -4.939 l
+74.819 -4.986 74.665 -5.012 74.509 -5.012 c
+74.253 -5.012 74.058 -4.92 73.921 -4.733 c
+73.782 -4.549 73.716 -4.288 73.716 -3.954 c
+73.716 -1.484 l
+73.113 -1.484 l
+73.113 -0.955 l
+73.716 -0.955 l
+73.716 0 l
+h
+77.156 -5.012 m
+76.656 -5.012 76.273 -4.866 76.009 -4.571 c
+75.745 -4.278 75.612 -3.844 75.612 -3.262 c
+75.612 -2.792 l
+75.612 -2.198 75.737 -1.731 75.995 -1.396 c
+76.259 -1.055 76.619 -0.881 77.082 -0.881 c
+77.541 -0.881 77.883 -1.036 78.111 -1.338 c
+78.347 -1.631 78.467 -2.094 78.478 -2.719 c
+78.478 -3.145 l
+76.259 -3.145 l
+76.259 -3.233 l
+76.259 -3.667 76.336 -3.979 76.494 -4.174 c
+76.66 -4.361 76.891 -4.453 77.185 -4.453 c
+77.38 -4.453 77.553 -4.421 77.699 -4.351 c
+77.846 -4.274 77.983 -4.156 78.111 -3.998 c
+78.449 -4.409 l
+78.162 -4.814 77.732 -5.012 77.156 -5.012 c
+77.082 -1.44 m
+76.807 -1.44 76.604 -1.536 76.479 -1.72 c
+76.35 -1.907 76.277 -2.198 76.259 -2.587 c
+77.832 -2.587 l
+77.832 -2.499 l
+77.809 -2.117 77.744 -1.849 77.626 -1.691 c
+77.508 -1.525 77.325 -1.44 77.082 -1.44 c
+81.301 -4.939 m
+81.26 -4.85 81.235 -4.704 81.227 -4.498 c
+80.992 -4.843 80.698 -5.012 80.346 -5.012 c
+79.982 -5.012 79.698 -4.916 79.492 -4.718 c
+79.294 -4.513 79.199 -4.226 79.199 -3.85 c
+79.199 -3.451 79.334 -3.131 79.61 -2.896 c
+79.882 -2.653 80.257 -2.528 80.728 -2.528 c
+81.212 -2.528 l
+81.212 -2.102 l
+81.212 -1.866 81.158 -1.701 81.051 -1.602 c
+80.94 -1.496 80.779 -1.44 80.566 -1.44 c
+80.367 -1.44 80.206 -1.499 80.08 -1.616 c
+79.963 -1.734 79.905 -1.882 79.905 -2.057 c
+79.257 -2.057 l
+79.257 -1.863 79.317 -1.672 79.434 -1.484 c
+79.559 -1.301 79.721 -1.153 79.919 -1.043 c
+80.125 -0.937 80.352 -0.881 80.61 -0.881 c
+81.011 -0.881 81.316 -0.985 81.522 -1.19 c
+81.734 -1.396 81.848 -1.691 81.859 -2.072 c
+81.859 -4.086 l
+81.859 -4.391 81.896 -4.656 81.977 -4.88 c
+81.977 -4.939 l
+h
+80.433 -4.424 m
+80.599 -4.424 80.749 -4.38 80.889 -4.292 c
+81.036 -4.203 81.143 -4.093 81.212 -3.954 c
+81.212 -3.013 l
+80.845 -3.013 l
+80.529 -3.013 80.286 -3.083 80.111 -3.219 c
+79.934 -3.347 79.845 -3.535 79.845 -3.777 c
+79.845 -4.006 79.889 -4.17 79.978 -4.278 c
+80.066 -4.376 80.217 -4.424 80.433 -4.424 c
+82.727 -2.763 m
+82.727 -2.157 82.837 -1.691 83.064 -1.367 c
+83.3 -1.043 83.627 -0.881 84.049 -0.881 c
+84.431 -0.881 84.73 -1.04 84.946 -1.352 c
+84.946 0.706 l
+85.593 0.706 l
+85.593 -4.939 l
+85.005 -4.939 l
+84.961 -4.513 l
+84.755 -4.847 84.45 -5.012 84.049 -5.012 c
+83.638 -5.012 83.315 -4.858 83.079 -4.542 c
+82.844 -4.218 82.727 -3.763 82.727 -3.175 c
+h
+83.373 -3.145 m
+83.373 -3.586 83.436 -3.917 83.564 -4.13 c
+83.7 -4.336 83.921 -4.438 84.226 -4.438 c
+84.549 -4.438 84.788 -4.278 84.946 -3.954 c
+84.946 -1.94 l
+84.778 -1.627 84.539 -1.469 84.226 -1.469 c
+83.921 -1.469 83.7 -1.573 83.564 -1.778 c
+83.436 -1.984 83.373 -2.308 83.373 -2.749 c
+h
+88.18 -2.763 m
+88.18 -2.186 88.316 -1.731 88.591 -1.396 c
+88.874 -1.055 89.246 -0.881 89.709 -0.881 c
+90.168 -0.881 90.536 -1.051 90.811 -1.381 c
+91.094 -1.705 91.241 -2.153 91.252 -2.719 c
+91.252 -3.145 l
+91.252 -3.715 91.109 -4.17 90.826 -4.513 c
+90.55 -4.847 90.183 -5.012 89.723 -5.012 c
+89.26 -5.012 88.889 -4.85 88.606 -4.527 c
+88.331 -4.197 88.188 -3.755 88.18 -3.204 c
+h
+88.826 -3.145 m
+88.826 -3.549 88.904 -3.865 89.062 -4.101 c
+89.227 -4.336 89.447 -4.453 89.723 -4.453 c
+90.289 -4.453 90.583 -4.042 90.605 -3.219 c
+90.605 -2.763 l
+90.605 -2.362 90.521 -2.043 90.355 -1.808 c
+90.197 -1.565 89.981 -1.44 89.709 -1.44 c
+89.444 -1.44 89.227 -1.565 89.062 -1.808 c
+88.904 -2.043 88.826 -2.362 88.826 -2.763 c
+h
+92.383 -4.939 m
+92.383 -1.484 l
+91.855 -1.484 l
+91.855 -0.955 l
+92.383 -0.955 l
+92.383 -0.5 l
+92.383 -0.099 92.479 0.214 92.678 0.441 c
+92.884 0.665 93.163 0.779 93.516 0.779 c
+93.652 0.779 93.784 0.757 93.912 0.721 c
+93.883 0.177 l
+93.784 0.195 93.684 0.206 93.589 0.206 c
+93.214 0.206 93.031 -0.058 93.031 -0.588 c
+93.031 -0.955 l
+93.707 -0.955 l
+93.707 -1.484 l
+93.031 -1.484 l
+93.031 -4.939 l
+h
+97.573 -4.453 m
+97.786 -4.453 97.958 -4.391 98.087 -4.262 c
+98.223 -4.126 98.297 -3.935 98.307 -3.69 c
+98.925 -3.69 l
+98.903 -4.072 98.767 -4.391 98.513 -4.644 c
+98.256 -4.891 97.944 -5.012 97.573 -5.012 c
+97.081 -5.012 96.705 -4.862 96.441 -4.556 c
+96.184 -4.244 96.059 -3.777 96.059 -3.16 c
+96.059 -2.719 l
+96.059 -2.124 96.184 -1.668 96.441 -1.352 c
+96.705 -1.04 97.081 -0.881 97.573 -0.881 c
+97.973 -0.881 98.293 -1.014 98.528 -1.278 c
+98.771 -1.536 98.903 -1.882 98.925 -2.322 c
+98.307 -2.322 l
+98.286 -2.028 98.212 -1.808 98.087 -1.66 c
+97.97 -1.514 97.796 -1.44 97.573 -1.44 c
+97.279 -1.44 97.062 -1.539 96.926 -1.734 c
+96.786 -1.922 96.713 -2.23 96.705 -2.66 c
+96.705 -3.175 l
+96.705 -3.645 96.772 -3.979 96.911 -4.174 c
+97.058 -4.361 97.279 -4.453 97.573 -4.453 c
+101.703 -4.586 m
+101.486 -4.872 101.174 -5.012 100.763 -5.012 c
+100.398 -5.012 100.123 -4.891 99.939 -4.644 c
+99.763 -4.391 99.668 -4.027 99.66 -3.557 c
+99.66 -0.955 l
+100.306 -0.955 l
+100.306 -3.498 l
+100.306 -4.126 100.491 -4.438 100.865 -4.438 c
+101.266 -4.438 101.542 -4.262 101.688 -3.91 c
+101.688 -0.955 l
+102.335 -0.955 l
+102.335 -4.939 l
+101.717 -4.939 l
+h
+104.966 -1.573 m
+104.878 -1.554 104.779 -1.543 104.672 -1.543 c
+104.337 -1.543 104.102 -1.727 103.967 -2.087 c
+103.967 -4.939 l
+103.319 -4.939 l
+103.319 -0.955 l
+103.952 -0.955 l
+103.967 -1.367 l
+104.143 -1.043 104.385 -0.881 104.701 -0.881 c
+104.808 -0.881 104.896 -0.904 104.966 -0.941 c
+h
+107.259 -1.573 m
+107.171 -1.554 107.072 -1.543 106.965 -1.543 c
+106.631 -1.543 106.396 -1.727 106.259 -2.087 c
+106.259 -4.939 l
+105.613 -4.939 l
+105.613 -0.955 l
+106.245 -0.955 l
+106.259 -1.367 l
+106.436 -1.043 106.679 -0.881 106.995 -0.881 c
+107.101 -0.881 107.19 -0.904 107.259 -0.941 c
+h
+109.258 -5.012 m
+108.759 -5.012 108.376 -4.866 108.112 -4.571 c
+107.847 -4.278 107.715 -3.844 107.715 -3.262 c
+107.715 -2.792 l
+107.715 -2.198 107.84 -1.731 108.098 -1.396 c
+108.362 -1.055 108.722 -0.881 109.185 -0.881 c
+109.644 -0.881 109.986 -1.036 110.214 -1.338 c
+110.449 -1.631 110.571 -2.094 110.581 -2.719 c
+110.581 -3.145 l
+108.362 -3.145 l
+108.362 -3.233 l
+108.362 -3.667 108.439 -3.979 108.597 -4.174 c
+108.763 -4.361 108.994 -4.453 109.288 -4.453 c
+109.482 -4.453 109.655 -4.421 109.802 -4.351 c
+109.949 -4.274 110.085 -4.156 110.214 -3.998 c
+110.552 -4.409 l
+110.265 -4.814 109.835 -5.012 109.258 -5.012 c
+109.185 -1.44 m
+108.909 -1.44 108.707 -1.536 108.582 -1.72 c
+108.454 -1.907 108.38 -2.198 108.362 -2.587 c
+109.935 -2.587 l
+109.935 -2.499 l
+109.912 -2.117 109.846 -1.849 109.729 -1.691 c
+109.611 -1.525 109.428 -1.44 109.185 -1.44 c
+111.978 -0.955 m
+111.992 -1.396 l
+112.246 -1.055 112.569 -0.881 112.962 -0.881 c
+113.668 -0.881 114.024 -1.352 114.035 -2.293 c
+114.035 -4.939 l
+113.389 -4.939 l
+113.389 -2.322 l
+113.389 -2.009 113.334 -1.789 113.227 -1.66 c
+113.117 -1.536 112.962 -1.469 112.757 -1.469 c
+112.599 -1.469 112.452 -1.525 112.316 -1.631 c
+112.187 -1.741 112.084 -1.878 112.007 -2.043 c
+112.007 -4.939 l
+111.36 -4.939 l
+111.36 -0.955 l
+h
+115.859 0 m
+115.859 -0.955 l
+116.461 -0.955 l
+116.461 -1.484 l
+115.859 -1.484 l
+115.859 -3.954 l
+115.859 -4.112 115.88 -4.23 115.932 -4.307 c
+115.99 -4.388 116.079 -4.424 116.196 -4.424 c
+116.285 -4.424 116.372 -4.409 116.461 -4.38 c
+116.461 -4.939 l
+116.314 -4.986 116.16 -5.012 116.005 -5.012 c
+115.748 -5.012 115.553 -4.92 115.417 -4.733 c
+115.277 -4.549 115.211 -4.288 115.211 -3.954 c
+115.211 -1.484 l
+114.608 -1.484 l
+114.608 -0.955 l
+115.211 -0.955 l
+115.211 0 l
+h
+118.813 -2.763 m
+118.813 -2.186 118.949 -1.731 119.225 -1.396 c
+119.508 -1.055 119.878 -0.881 120.341 -0.881 c
+120.8 -0.881 121.168 -1.051 121.444 -1.381 c
+121.727 -1.705 121.874 -2.153 121.885 -2.719 c
+121.885 -3.145 l
+121.885 -3.715 121.741 -4.17 121.459 -4.513 c
+121.183 -4.847 120.815 -5.012 120.356 -5.012 c
+119.893 -5.012 119.522 -4.85 119.239 -4.527 c
+118.963 -4.197 118.82 -3.755 118.813 -3.204 c
+h
+119.46 -3.145 m
+119.46 -3.549 119.537 -3.865 119.695 -4.101 c
+119.86 -4.336 120.081 -4.453 120.356 -4.453 c
+120.922 -4.453 121.216 -4.042 121.238 -3.219 c
+121.238 -2.763 l
+121.238 -2.362 121.154 -2.043 120.988 -1.808 c
+120.83 -1.565 120.613 -1.44 120.341 -1.44 c
+120.077 -1.44 119.86 -1.565 119.695 -1.808 c
+119.537 -2.043 119.46 -2.362 119.46 -2.763 c
+h
+123.34 -0.955 m
+123.354 -1.396 l
+123.608 -1.055 123.932 -0.881 124.325 -0.881 c
+125.031 -0.881 125.387 -1.352 125.398 -2.293 c
+125.398 -4.939 l
+124.751 -4.939 l
+124.751 -2.322 l
+124.751 -2.009 124.696 -1.789 124.59 -1.66 c
+124.48 -1.536 124.325 -1.469 124.119 -1.469 c
+123.961 -1.469 123.814 -1.525 123.678 -1.631 c
+123.549 -1.741 123.447 -1.878 123.37 -2.043 c
+123.37 -4.939 l
+122.722 -4.939 l
+122.722 -0.955 l
+h
+127.794 -5.012 m
+127.294 -5.012 126.912 -4.866 126.647 -4.571 c
+126.383 -4.278 126.25 -3.844 126.25 -3.262 c
+126.25 -2.792 l
+126.25 -2.198 126.375 -1.731 126.633 -1.396 c
+126.897 -1.055 127.258 -0.881 127.72 -0.881 c
+128.179 -0.881 128.522 -1.036 128.75 -1.338 c
+128.985 -1.631 129.106 -2.094 129.116 -2.719 c
+129.116 -3.145 l
+126.897 -3.145 l
+126.897 -3.233 l
+126.897 -3.667 126.974 -3.979 127.132 -4.174 c
+127.298 -4.361 127.529 -4.453 127.823 -4.453 c
+128.018 -4.453 128.191 -4.421 128.337 -4.351 c
+128.484 -4.274 128.621 -4.156 128.75 -3.998 c
+129.087 -4.409 l
+128.8 -4.814 128.37 -5.012 127.794 -5.012 c
+127.72 -1.44 m
+127.445 -1.44 127.242 -1.536 127.117 -1.72 c
+126.989 -1.907 126.915 -2.198 126.897 -2.587 c
+128.47 -2.587 l
+128.47 -2.499 l
+128.448 -2.117 128.382 -1.849 128.264 -1.691 c
+128.147 -1.525 127.963 -1.44 127.72 -1.44 c
+129.94 -4.586 m
+129.94 -4.469 129.973 -4.373 130.043 -4.292 c
+130.109 -4.215 130.211 -4.174 130.352 -4.174 c
+130.498 -4.174 130.605 -4.215 130.675 -4.292 c
+130.752 -4.373 130.793 -4.469 130.793 -4.586 c
+130.793 -4.696 130.752 -4.788 130.675 -4.866 c
+130.605 -4.943 130.498 -4.983 130.352 -4.983 c
+130.211 -4.983 130.109 -4.943 130.043 -4.866 c
+129.973 -4.788 129.94 -4.696 129.94 -4.586 c
+f
+Q
+0.113 0.082 0.09 0 k
+287.665 402.127 234.667 -12.895 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 395.2921 cm
+0 0 m
+0 -0.188 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.647 -0.243 -0.776 -0.367 -0.882 c
+-0.496 -0.992 -0.658 -1.081 -0.852 -1.147 c
+-1.051 -1.206 -1.278 -1.243 -1.543 -1.25 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.162 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.927 c
+-3.127 -0.82 -3.23 -0.691 -3.307 -0.545 c
+-3.388 -0.39 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.132 l
+-2.642 0.033 -2.616 -0.059 -2.587 -0.148 c
+-2.55 -0.229 -2.506 -0.302 -2.454 -0.368 c
+-2.396 -0.427 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.581 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.675 c
+-1.977 0.683 -1.992 0.69 -1.999 0.69 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.881 -2.786 0.959 -2.91 1.058 c
+-3.039 1.153 -3.142 1.278 -3.219 1.425 c
+-3.289 1.572 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.219 2.484 c
+-3.152 2.63 -3.054 2.748 -2.925 2.836 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.119 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.119 -1.128 3.09 -0.97 3.042 c
+-0.804 2.991 -0.669 2.917 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.252 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.352 c
+-1.294 1.311 -1.117 1.263 -0.941 1.205 c
+-0.756 1.146 -0.595 1.065 -0.455 0.97 c
+-0.32 0.87 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.513 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.319 2.385 -2.366 2.337 c
+-2.406 2.296 -2.436 2.248 -2.454 2.19 c
+-2.477 2.131 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.778 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.201 1.558 -2.131 1.529 c
+-2.065 1.499 -1.984 1.469 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.091 -0.86 0.176 -0.897 0.235 c
+-0.926 0.301 -0.977 0.356 -1.043 0.396 c
+-1.103 0.433 -1.176 0.47 -1.263 0.5 c
+-1.352 0.529 -1.448 0.558 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.581 -1.146 -0.53 -1.028 -0.441 c
+-0.904 -0.346 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.661 m
+6.184 -2.661 5.993 -2.635 5.829 -2.587 c
+5.659 -2.548 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.22 5.108 -2.103 c
+5.039 -1.985 4.991 -1.856 4.961 -1.721 c
+5.858 -1.617 l
+5.895 -1.754 5.964 -1.86 6.064 -1.941 c
+6.159 -2.029 6.284 -2.073 6.431 -2.073 c
+6.519 -2.073 6.6 -2.058 6.681 -2.029 c
+6.758 -1.999 6.828 -1.945 6.887 -1.867 c
+6.945 -1.798 6.99 -1.706 7.019 -1.588 c
+7.056 -1.47 7.078 -1.324 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.89 7.082 -0.831 7.092 -0.78 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.817 6.835 -0.978 6.652 -1.073 c
+6.464 -1.173 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.015 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.412 4.888 -0.206 c
+4.836 0.007 4.814 0.242 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.234 c
+4.946 1.448 5.027 1.631 5.137 1.778 c
+5.244 1.932 5.376 2.05 5.534 2.131 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.252 6.387 2.234 c
+6.483 2.212 6.571 2.179 6.652 2.131 c
+6.739 2.079 6.817 2.017 6.887 1.94 c
+6.964 1.859 7.026 1.767 7.078 1.66 c
+7.092 1.66 l
+7.092 1.807 l
+7.1 1.866 7.107 1.918 7.107 1.969 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.164 7.14 2.197 7.151 2.219 c
+8.004 2.219 l
+7.993 2.138 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.162 l
+7.975 -1.415 7.938 -1.636 7.871 -1.823 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.5 7.063 -2.558 c
+6.865 -2.625 6.644 -2.661 6.402 -2.661 c
+7.092 0.529 m
+7.092 0.742 7.067 0.918 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.499 6.729 1.558 6.652 1.587 c
+6.571 1.624 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.62 6.137 1.572 c
+6.056 1.531 5.99 1.462 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.874 5.755 0.706 5.755 0.5 c
+5.755 0.124 5.814 -0.155 5.931 -0.339 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.464 6.857 -0.383 c
+6.924 -0.294 6.978 -0.177 7.019 -0.03 c
+7.067 0.118 7.092 0.301 7.092 0.529 c
+11.036 -0.647 m
+12.168 -0.647 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.647 l
+10.124 -0.647 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.676 re
+10.124 2.836 m
+13.597 1.602 m
+13.053 1.602 l
+13.053 2.219 l
+13.641 2.219 l
+13.92 3.116 l
+14.494 3.116 l
+14.494 2.219 l
+15.728 2.219 l
+15.728 1.602 l
+14.494 1.602 l
+14.494 -0.103 l
+14.494 -0.324 l
+14.501 -0.393 14.523 -0.456 14.552 -0.515 c
+14.589 -0.566 14.645 -0.611 14.714 -0.647 c
+14.791 -0.676 14.905 -0.691 15.052 -0.691 c
+15.188 -0.691 15.324 -0.688 15.464 -0.676 c
+15.599 -0.659 15.732 -0.632 15.861 -0.603 c
+15.861 -1.206 l
+15.78 -1.216 15.703 -1.231 15.626 -1.25 c
+15.545 -1.261 15.468 -1.268 15.391 -1.279 c
+15.31 -1.287 15.221 -1.294 15.125 -1.294 c
+15.038 -1.301 14.938 -1.309 14.832 -1.309 c
+14.645 -1.309 14.483 -1.294 14.346 -1.264 c
+14.218 -1.228 14.104 -1.183 14.009 -1.133 c
+13.92 -1.085 13.847 -1.025 13.788 -0.956 c
+13.729 -0.879 13.685 -0.802 13.656 -0.721 c
+13.627 -0.632 13.604 -0.545 13.597 -0.456 c
+13.586 -0.36 13.582 -0.265 13.582 -0.177 c
+h
+21.722 1.602 m
+21.178 1.602 l
+21.178 2.219 l
+21.766 2.219 l
+22.045 3.116 l
+22.618 3.116 l
+22.618 2.219 l
+23.853 2.219 l
+23.853 1.602 l
+22.618 1.602 l
+22.618 -0.103 l
+22.618 -0.324 l
+22.626 -0.393 22.647 -0.456 22.677 -0.515 c
+22.714 -0.566 22.769 -0.611 22.839 -0.647 c
+22.916 -0.676 23.03 -0.691 23.177 -0.691 c
+23.313 -0.691 23.449 -0.688 23.588 -0.676 c
+23.725 -0.659 23.857 -0.632 23.985 -0.603 c
+23.985 -1.206 l
+23.904 -1.216 23.827 -1.231 23.75 -1.25 c
+23.669 -1.261 23.592 -1.268 23.515 -1.279 c
+23.434 -1.287 23.346 -1.294 23.25 -1.294 c
+23.162 -1.301 23.063 -1.309 22.957 -1.309 c
+22.769 -1.309 22.608 -1.294 22.471 -1.264 c
+22.343 -1.228 22.229 -1.183 22.134 -1.133 c
+22.045 -1.085 21.972 -1.025 21.913 -0.956 c
+21.854 -0.879 21.81 -0.802 21.781 -0.721 c
+21.751 -0.632 21.729 -0.545 21.722 -0.456 c
+21.71 -0.36 21.707 -0.265 21.707 -0.177 c
+h
+26.136 -1.324 m
+25.966 -1.324 25.816 -1.301 25.679 -1.264 c
+25.551 -1.216 25.437 -1.147 25.342 -1.058 c
+25.253 -0.971 25.184 -0.864 25.136 -0.736 c
+25.084 -0.599 25.062 -0.449 25.062 -0.279 c
+25.062 -0.074 25.095 0.095 25.165 0.235 c
+25.232 0.382 25.327 0.492 25.444 0.573 c
+25.569 0.661 25.712 0.723 25.87 0.764 c
+26.036 0.801 26.213 0.826 26.4 0.837 c
+27.12 0.852 l
+27.12 1.028 l
+27.12 1.146 27.109 1.249 27.09 1.337 c
+27.069 1.425 27.036 1.491 26.988 1.543 c
+26.947 1.602 26.9 1.639 26.841 1.66 c
+26.782 1.679 26.716 1.69 26.649 1.69 c
+26.58 1.69 26.518 1.679 26.458 1.66 c
+26.408 1.649 26.36 1.624 26.312 1.587 c
+26.271 1.558 26.238 1.506 26.209 1.44 c
+26.186 1.381 26.172 1.3 26.165 1.205 c
+25.224 1.249 l
+25.253 1.396 25.297 1.531 25.356 1.66 c
+25.423 1.786 25.518 1.896 25.635 1.984 c
+25.753 2.079 25.893 2.153 26.061 2.204 c
+26.238 2.252 26.444 2.277 26.679 2.277 c
+27.12 2.277 27.451 2.167 27.678 1.955 c
+27.914 1.749 28.031 1.44 28.031 1.028 c
+28.031 -0.235 l
+28.031 -0.456 l
+28.039 -0.515 28.054 -0.57 28.075 -0.618 c
+28.094 -0.659 28.123 -0.691 28.164 -0.721 c
+28.201 -0.743 28.252 -0.75 28.311 -0.75 c
+28.376 -0.75 28.447 -0.746 28.517 -0.736 c
+28.517 -1.22 l
+28.457 -1.231 28.403 -1.243 28.355 -1.25 c
+28.314 -1.261 28.274 -1.268 28.237 -1.279 c
+28.197 -1.287 28.153 -1.294 28.105 -1.294 c
+28.054 -1.301 27.995 -1.309 27.929 -1.309 c
+27.701 -1.309 27.535 -1.257 27.429 -1.147 c
+27.318 -1.029 27.256 -0.864 27.237 -0.647 c
+27.223 -0.647 l
+27.154 -0.757 27.083 -0.853 27.017 -0.941 c
+26.947 -1.022 26.87 -1.088 26.782 -1.147 c
+26.693 -1.206 26.595 -1.25 26.488 -1.279 c
+26.389 -1.309 26.271 -1.324 26.136 -1.324 c
+27.12 0.353 m
+26.693 0.338 l
+26.595 0.338 26.503 0.33 26.414 0.323 c
+26.333 0.312 26.267 0.286 26.209 0.249 c
+26.15 0.209 26.098 0.151 26.061 0.073 c
+26.021 0.003 26.003 -0.088 26.003 -0.206 c
+26.003 -0.375 26.036 -0.497 26.106 -0.574 c
+26.172 -0.655 26.271 -0.691 26.4 -0.691 c
+26.506 -0.691 26.606 -0.669 26.693 -0.618 c
+26.789 -0.57 26.87 -0.508 26.929 -0.427 c
+26.995 -0.35 27.046 -0.262 27.076 -0.162 c
+27.106 -0.056 27.12 0.058 27.12 0.176 c
+h
+30.769 -2.661 m
+30.552 -2.661 30.361 -2.635 30.196 -2.587 c
+30.027 -2.548 29.887 -2.484 29.77 -2.396 c
+29.652 -2.315 29.552 -2.22 29.475 -2.103 c
+29.406 -1.985 29.358 -1.856 29.328 -1.721 c
+30.225 -1.617 l
+30.262 -1.754 30.331 -1.86 30.431 -1.941 c
+30.527 -2.029 30.651 -2.073 30.799 -2.073 c
+30.886 -2.073 30.967 -2.058 31.048 -2.029 c
+31.125 -1.999 31.195 -1.945 31.254 -1.867 c
+31.313 -1.798 31.357 -1.706 31.387 -1.588 c
+31.424 -1.47 31.445 -1.324 31.445 -1.147 c
+31.445 -0.956 l
+31.445 -0.89 31.449 -0.831 31.46 -0.78 c
+31.46 -0.588 l
+31.445 -0.588 l
+31.346 -0.817 31.202 -0.978 31.019 -1.073 c
+30.832 -1.173 30.626 -1.22 30.402 -1.22 c
+30.196 -1.22 30.012 -1.183 29.858 -1.103 c
+29.71 -1.015 29.582 -0.897 29.475 -0.75 c
+29.376 -0.595 29.303 -0.412 29.255 -0.206 c
+29.203 0.007 29.182 0.242 29.182 0.5 c
+29.182 0.771 29.203 1.018 29.255 1.234 c
+29.313 1.448 29.394 1.631 29.505 1.778 c
+29.612 1.932 29.743 2.05 29.901 2.131 c
+30.057 2.219 30.244 2.263 30.46 2.263 c
+30.556 2.263 30.655 2.252 30.755 2.234 c
+30.85 2.212 30.938 2.179 31.019 2.131 c
+31.107 2.079 31.185 2.017 31.254 1.94 c
+31.331 1.859 31.393 1.767 31.445 1.66 c
+31.46 1.66 l
+31.46 1.807 l
+31.468 1.866 31.474 1.918 31.474 1.969 c
+31.482 2.028 31.489 2.076 31.489 2.117 c
+31.497 2.164 31.507 2.197 31.519 2.219 c
+32.371 2.219 l
+32.361 2.138 32.349 2.028 32.342 1.881 c
+32.342 1.411 l
+32.342 -1.162 l
+32.342 -1.415 32.305 -1.636 32.239 -1.823 c
+32.17 -2.007 32.066 -2.161 31.931 -2.278 c
+31.79 -2.404 31.625 -2.5 31.43 -2.558 c
+31.233 -2.625 31.011 -2.661 30.769 -2.661 c
+31.46 0.529 m
+31.46 0.742 31.434 0.918 31.387 1.058 c
+31.346 1.205 31.291 1.323 31.225 1.411 c
+31.166 1.499 31.096 1.558 31.019 1.587 c
+30.938 1.624 30.861 1.646 30.784 1.646 c
+30.684 1.646 30.593 1.62 30.504 1.572 c
+30.424 1.531 30.358 1.462 30.298 1.367 c
+30.248 1.278 30.203 1.161 30.167 1.014 c
+30.137 0.874 30.122 0.706 30.122 0.5 c
+30.122 0.124 30.181 -0.155 30.298 -0.339 c
+30.416 -0.515 30.578 -0.603 30.784 -0.603 c
+30.85 -0.603 30.923 -0.588 31.004 -0.559 c
+31.092 -0.522 31.166 -0.464 31.225 -0.383 c
+31.291 -0.294 31.346 -0.177 31.387 -0.03 c
+31.434 0.118 31.46 0.301 31.46 0.529 c
+37.953 0.837 1.866 -0.794 re
+37.953 0.043 m
+42.381 -1.324 m
+42.212 -1.324 42.061 -1.301 41.926 -1.264 c
+41.797 -1.216 41.683 -1.147 41.587 -1.058 c
+41.5 -0.971 41.429 -0.864 41.382 -0.736 c
+41.33 -0.599 41.308 -0.449 41.308 -0.279 c
+41.308 -0.074 41.342 0.095 41.411 0.235 c
+41.477 0.382 41.573 0.492 41.691 0.573 c
+41.816 0.661 41.959 0.723 42.117 0.764 c
+42.282 0.801 42.458 0.826 42.646 0.837 c
+43.366 0.852 l
+43.366 1.028 l
+43.366 1.146 43.355 1.249 43.337 1.337 c
+43.314 1.425 43.282 1.491 43.234 1.543 c
+43.193 1.602 43.146 1.639 43.087 1.66 c
+43.028 1.679 42.962 1.69 42.896 1.69 c
+42.826 1.69 42.763 1.679 42.705 1.66 c
+42.653 1.649 42.605 1.624 42.558 1.587 c
+42.518 1.558 42.484 1.506 42.455 1.44 c
+42.433 1.381 42.418 1.3 42.41 1.205 c
+41.47 1.249 l
+41.5 1.396 41.543 1.531 41.602 1.66 c
+41.668 1.786 41.764 1.896 41.882 1.984 c
+41.999 2.079 42.139 2.153 42.308 2.204 c
+42.484 2.252 42.69 2.277 42.925 2.277 c
+43.366 2.277 43.697 2.167 43.925 1.955 c
+44.16 1.749 44.278 1.44 44.278 1.028 c
+44.278 -0.235 l
+44.278 -0.456 l
+44.284 -0.515 44.299 -0.57 44.322 -0.618 c
+44.34 -0.659 44.369 -0.691 44.409 -0.721 c
+44.446 -0.743 44.498 -0.75 44.557 -0.75 c
+44.623 -0.75 44.693 -0.746 44.762 -0.736 c
+44.762 -1.22 l
+44.704 -1.231 44.648 -1.243 44.6 -1.25 c
+44.56 -1.261 44.52 -1.268 44.483 -1.279 c
+44.442 -1.287 44.399 -1.294 44.351 -1.294 c
+44.299 -1.301 44.241 -1.309 44.174 -1.309 c
+43.947 -1.309 43.781 -1.257 43.675 -1.147 c
+43.565 -1.029 43.502 -0.864 43.484 -0.647 c
+43.469 -0.647 l
+43.399 -0.757 43.33 -0.853 43.264 -0.941 c
+43.193 -1.022 43.116 -1.088 43.028 -1.147 c
+42.94 -1.206 42.84 -1.25 42.734 -1.279 c
+42.635 -1.309 42.518 -1.324 42.381 -1.324 c
+43.366 0.353 m
+42.94 0.338 l
+42.84 0.338 42.749 0.33 42.661 0.323 c
+42.58 0.312 42.514 0.286 42.455 0.249 c
+42.396 0.209 42.345 0.151 42.308 0.073 c
+42.267 0.003 42.249 -0.088 42.249 -0.206 c
+42.249 -0.375 42.282 -0.497 42.352 -0.574 c
+42.418 -0.655 42.518 -0.691 42.646 -0.691 c
+42.753 -0.691 42.852 -0.669 42.94 -0.618 c
+43.035 -0.57 43.116 -0.508 43.175 -0.427 c
+43.241 -0.35 43.293 -0.262 43.322 -0.162 c
+43.351 -0.056 43.366 0.058 43.366 0.176 c
+h
+50.297 -2.631 m
+50.297 3.513 l
+52.222 3.513 l
+52.222 2.896 l
+51.149 2.896 l
+51.149 -2.014 l
+52.222 -2.014 l
+52.222 -2.631 l
+h
+55.798 -1.264 m
+55.798 0.72 l
+55.798 1.021 55.754 1.242 55.665 1.381 c
+55.585 1.529 55.449 1.602 55.254 1.602 c
+55.143 1.602 55.041 1.576 54.946 1.529 c
+54.857 1.477 54.776 1.411 54.711 1.323 c
+54.651 1.234 54.6 1.124 54.563 0.999 c
+54.534 0.881 54.519 0.749 54.519 0.602 c
+54.519 -1.264 l
+53.608 -1.264 l
+53.608 1.44 l
+53.608 1.66 l
+53.608 1.749 53.6 1.826 53.593 1.896 c
+53.593 2.087 l
+53.593 2.219 l
+54.445 2.219 l
+54.453 2.19 54.46 2.146 54.46 2.087 c
+54.46 1.896 l
+54.468 1.826 54.475 1.756 54.475 1.69 c
+54.482 1.62 54.49 1.565 54.49 1.529 c
+54.505 1.529 l
+54.622 1.793 54.773 1.984 54.96 2.102 c
+55.143 2.219 55.364 2.277 55.621 2.277 c
+55.806 2.277 55.966 2.248 56.107 2.19 c
+56.242 2.131 56.357 2.042 56.444 1.925 c
+56.533 1.807 56.595 1.664 56.635 1.499 c
+56.683 1.341 56.71 1.153 56.71 0.941 c
+56.71 -1.264 l
+h
+58.628 -1.324 m
+58.458 -1.324 58.308 -1.301 58.172 -1.264 c
+58.044 -1.216 57.929 -1.147 57.834 -1.058 c
+57.745 -0.971 57.676 -0.864 57.628 -0.736 c
+57.576 -0.599 57.554 -0.449 57.554 -0.279 c
+57.554 -0.074 57.587 0.095 57.657 0.235 c
+57.724 0.382 57.819 0.492 57.936 0.573 c
+58.061 0.661 58.204 0.723 58.363 0.764 c
+58.528 0.801 58.705 0.826 58.892 0.837 c
+59.612 0.852 l
+59.612 1.028 l
+59.612 1.146 59.601 1.249 59.583 1.337 c
+59.561 1.425 59.528 1.491 59.48 1.543 c
+59.44 1.602 59.392 1.639 59.333 1.66 c
+59.274 1.679 59.208 1.69 59.141 1.69 c
+59.072 1.69 59.01 1.679 58.951 1.66 c
+58.9 1.649 58.852 1.624 58.804 1.587 c
+58.763 1.558 58.73 1.506 58.701 1.44 c
+58.679 1.381 58.664 1.3 58.657 1.205 c
+57.716 1.249 l
+57.745 1.396 57.79 1.531 57.848 1.66 c
+57.915 1.786 58.01 1.896 58.127 1.984 c
+58.245 2.079 58.385 2.153 58.554 2.204 c
+58.73 2.252 58.936 2.277 59.172 2.277 c
+59.612 2.277 59.943 2.167 60.171 1.955 c
+60.406 1.749 60.523 1.44 60.523 1.028 c
+60.523 -0.235 l
+60.523 -0.456 l
+60.531 -0.515 60.546 -0.57 60.568 -0.618 c
+60.586 -0.659 60.616 -0.691 60.656 -0.721 c
+60.693 -0.743 60.744 -0.75 60.803 -0.75 c
+60.869 -0.75 60.939 -0.746 61.009 -0.736 c
+61.009 -1.22 l
+60.95 -1.231 60.895 -1.243 60.847 -1.25 c
+60.807 -1.261 60.766 -1.268 60.729 -1.279 c
+60.689 -1.287 60.645 -1.294 60.597 -1.294 c
+60.546 -1.301 60.487 -1.309 60.421 -1.309 c
+60.193 -1.309 60.028 -1.257 59.921 -1.147 c
+59.81 -1.029 59.748 -0.864 59.729 -0.647 c
+59.715 -0.647 l
+59.646 -0.757 59.575 -0.853 59.509 -0.941 c
+59.44 -1.022 59.363 -1.088 59.274 -1.147 c
+59.186 -1.206 59.087 -1.25 58.981 -1.279 c
+58.881 -1.309 58.763 -1.324 58.628 -1.324 c
+59.612 0.353 m
+59.186 0.338 l
+59.087 0.338 58.995 0.33 58.906 0.323 c
+58.826 0.312 58.76 0.286 58.701 0.249 c
+58.642 0.209 58.591 0.151 58.554 0.073 c
+58.514 0.003 58.495 -0.088 58.495 -0.206 c
+58.495 -0.375 58.528 -0.497 58.598 -0.574 c
+58.664 -0.655 58.763 -0.691 58.892 -0.691 c
+58.998 -0.691 59.098 -0.669 59.186 -0.618 c
+59.282 -0.57 59.363 -0.508 59.421 -0.427 c
+59.488 -0.35 59.538 -0.262 59.569 -0.162 c
+59.598 -0.056 59.612 0.058 59.612 0.176 c
+h
+62.894 -1.264 m
+62.894 0.852 l
+62.894 1.018 62.887 1.153 62.879 1.263 c
+62.868 1.371 62.85 1.454 62.821 1.514 c
+62.798 1.579 62.769 1.631 62.732 1.66 c
+62.703 1.69 62.663 1.705 62.615 1.705 c
+62.555 1.705 62.501 1.675 62.453 1.616 c
+62.412 1.565 62.379 1.491 62.35 1.396 c
+62.32 1.308 62.295 1.194 62.277 1.058 c
+62.266 0.918 62.262 0.768 62.262 0.602 c
+62.262 -1.264 l
+61.512 -1.264 l
+61.512 1.469 l
+61.512 1.705 l
+61.512 1.925 l
+61.512 2.002 61.505 2.065 61.497 2.117 c
+61.497 2.219 l
+62.173 2.219 l
+62.173 2.131 l
+62.173 1.984 l
+62.181 1.925 62.189 1.866 62.189 1.807 c
+62.189 1.646 l
+62.203 1.646 l
+62.221 1.734 62.251 1.811 62.291 1.881 c
+62.328 1.959 62.372 2.028 62.424 2.087 c
+62.482 2.146 62.549 2.19 62.629 2.219 c
+62.707 2.256 62.794 2.277 62.894 2.277 c
+63.078 2.277 63.218 2.223 63.305 2.117 c
+63.401 2.017 63.471 1.859 63.511 1.646 c
+63.526 1.646 l
+63.563 1.741 63.603 1.83 63.644 1.911 c
+63.691 1.988 63.746 2.05 63.805 2.102 c
+63.864 2.16 63.93 2.204 64.011 2.234 c
+64.088 2.263 64.176 2.277 64.275 2.277 c
+64.411 2.277 64.525 2.252 64.614 2.204 c
+64.702 2.153 64.768 2.079 64.82 1.984 c
+64.878 1.884 64.915 1.756 64.937 1.602 c
+64.967 1.454 64.981 1.271 64.981 1.058 c
+64.981 -1.264 l
+64.261 -1.264 l
+64.261 0.852 l
+64.261 1.018 64.253 1.153 64.246 1.263 c
+64.236 1.371 64.217 1.454 64.188 1.514 c
+64.165 1.579 64.136 1.631 64.099 1.66 c
+64.07 1.69 64.03 1.705 63.982 1.705 c
+63.864 1.705 63.768 1.616 63.702 1.44 c
+63.644 1.271 63.614 1.014 63.614 0.661 c
+63.614 -1.264 l
+h
+67.351 -1.324 m
+67.094 -1.324 66.866 -1.287 66.661 -1.22 c
+66.455 -1.143 66.278 -1.029 66.131 -0.882 c
+65.984 -0.728 65.867 -0.537 65.778 -0.31 c
+65.697 -0.085 65.661 0.18 65.661 0.484 c
+65.661 0.816 65.705 1.095 65.793 1.323 c
+65.888 1.558 66.017 1.741 66.175 1.881 c
+66.341 2.017 66.528 2.117 66.734 2.175 c
+66.94 2.241 67.149 2.277 67.366 2.277 c
+67.638 2.277 67.873 2.227 68.072 2.131 c
+68.277 2.042 68.443 1.911 68.571 1.734 c
+68.707 1.565 68.807 1.359 68.865 1.117 c
+68.932 0.881 68.968 0.617 68.968 0.323 c
+68.968 0.309 l
+66.602 0.309 l
+66.602 0.161 66.617 0.022 66.646 -0.103 c
+66.682 -0.232 66.738 -0.346 66.808 -0.441 c
+66.873 -0.53 66.958 -0.599 67.058 -0.647 c
+67.153 -0.699 67.267 -0.721 67.396 -0.721 c
+67.55 -0.721 67.689 -0.688 67.807 -0.618 c
+67.932 -0.551 68.02 -0.449 68.072 -0.31 c
+68.909 -0.383 l
+68.88 -0.482 68.824 -0.588 68.747 -0.706 c
+68.666 -0.817 68.564 -0.919 68.439 -1.015 c
+68.321 -1.103 68.167 -1.176 67.983 -1.235 c
+67.807 -1.294 67.594 -1.324 67.351 -1.324 c
+67.351 1.705 m
+67.263 1.705 67.175 1.69 67.087 1.66 c
+66.999 1.631 66.918 1.579 66.852 1.514 c
+66.782 1.444 66.723 1.356 66.675 1.249 c
+66.634 1.138 66.617 1.014 66.617 0.866 c
+68.086 0.866 l
+68.086 1.003 68.061 1.124 68.013 1.234 c
+67.972 1.341 67.918 1.429 67.851 1.499 c
+67.793 1.565 67.719 1.616 67.631 1.646 c
+67.542 1.683 67.447 1.705 67.351 1.705 c
+70.221 -2.631 m
+70.221 -2.014 l
+71.294 -2.014 l
+71.294 2.896 l
+70.221 2.896 l
+70.221 3.513 l
+72.147 3.513 l
+72.147 -2.631 l
+h
+78.729 -2.631 m
+78.729 3.513 l
+80.654 3.513 l
+80.654 2.896 l
+79.581 2.896 l
+79.581 -2.014 l
+80.654 -2.014 l
+80.654 -2.631 l
+h
+83.598 -1.324 m
+83.311 -1.324 83.068 -1.283 82.862 -1.206 c
+82.657 -1.118 82.484 -0.996 82.348 -0.838 c
+82.208 -0.684 82.106 -0.497 82.039 -0.279 c
+81.969 -0.056 81.937 0.191 81.937 0.455 c
+81.937 0.749 81.969 1.007 82.039 1.234 c
+82.116 1.458 82.223 1.646 82.363 1.793 c
+82.509 1.947 82.686 2.065 82.892 2.146 c
+83.097 2.234 83.333 2.277 83.598 2.277 c
+83.822 2.277 84.024 2.248 84.2 2.19 c
+84.377 2.131 84.527 2.046 84.656 1.94 c
+84.78 1.841 84.884 1.72 84.965 1.572 c
+85.042 1.433 85.096 1.282 85.127 1.117 c
+84.215 1.072 l
+84.186 1.249 84.115 1.389 84.009 1.499 c
+83.91 1.606 83.766 1.66 83.583 1.66 c
+83.336 1.66 83.16 1.558 83.053 1.352 c
+82.943 1.153 82.892 0.866 82.892 0.484 c
+82.892 -0.31 83.128 -0.706 83.598 -0.706 c
+83.763 -0.706 83.906 -0.655 84.024 -0.545 c
+84.142 -0.437 84.215 -0.276 84.244 -0.059 c
+85.156 -0.103 l
+85.127 -0.273 85.071 -0.427 84.994 -0.574 c
+84.924 -0.721 84.821 -0.853 84.685 -0.971 c
+84.556 -1.081 84.398 -1.169 84.215 -1.235 c
+84.038 -1.294 83.833 -1.324 83.598 -1.324 c
+89.304 0.484 m
+89.304 0.209 89.268 -0.04 89.202 -0.265 c
+89.131 -0.482 89.029 -0.669 88.892 -0.823 c
+88.753 -0.981 88.577 -1.103 88.364 -1.191 c
+88.147 -1.279 87.893 -1.324 87.599 -1.324 c
+87.323 -1.324 87.078 -1.279 86.864 -1.191 c
+86.658 -1.103 86.486 -0.981 86.35 -0.823 c
+86.21 -0.669 86.108 -0.482 86.041 -0.265 c
+85.971 -0.04 85.938 0.209 85.938 0.484 c
+85.938 0.738 85.968 0.974 86.027 1.19 c
+86.093 1.414 86.195 1.606 86.335 1.764 c
+86.471 1.928 86.648 2.057 86.864 2.146 c
+87.078 2.234 87.335 2.277 87.629 2.277 c
+87.941 2.277 88.202 2.234 88.408 2.146 c
+88.62 2.057 88.794 1.928 88.922 1.764 c
+89.058 1.606 89.158 1.414 89.216 1.19 c
+89.275 0.974 89.304 0.738 89.304 0.484 c
+88.349 0.484 m
+88.349 0.69 88.334 0.866 88.304 1.014 c
+88.283 1.161 88.246 1.282 88.187 1.381 c
+88.128 1.477 88.055 1.547 87.967 1.587 c
+87.878 1.635 87.768 1.66 87.643 1.66 c
+87.379 1.66 87.188 1.562 87.07 1.367 c
+86.953 1.179 86.893 0.885 86.893 0.484 c
+86.893 0.062 86.953 -0.243 87.07 -0.427 c
+87.188 -0.614 87.364 -0.706 87.599 -0.706 c
+87.724 -0.706 87.838 -0.688 87.938 -0.647 c
+88.033 -0.599 88.113 -0.526 88.173 -0.427 c
+88.239 -0.331 88.283 -0.206 88.304 -0.059 c
+88.334 0.087 88.349 0.268 88.349 0.484 c
+91.321 -1.264 m
+91.321 0.852 l
+91.321 1.018 91.315 1.153 91.307 1.263 c
+91.296 1.371 91.278 1.454 91.248 1.514 c
+91.226 1.579 91.197 1.631 91.16 1.66 c
+91.13 1.69 91.09 1.705 91.043 1.705 c
+90.984 1.705 90.929 1.675 90.881 1.616 c
+90.841 1.565 90.808 1.491 90.778 1.396 c
+90.748 1.308 90.723 1.194 90.704 1.058 c
+90.694 0.918 90.69 0.768 90.69 0.602 c
+90.69 -1.264 l
+89.94 -1.264 l
+89.94 1.469 l
+89.94 1.705 l
+89.94 1.925 l
+89.94 2.002 89.933 2.065 89.925 2.117 c
+89.925 2.219 l
+90.602 2.219 l
+90.602 2.131 l
+90.602 1.984 l
+90.609 1.925 90.616 1.866 90.616 1.807 c
+90.616 1.646 l
+90.631 1.646 l
+90.65 1.734 90.679 1.811 90.719 1.881 c
+90.756 1.959 90.8 2.028 90.851 2.087 c
+90.91 2.146 90.976 2.19 91.057 2.219 c
+91.134 2.256 91.223 2.277 91.321 2.277 c
+91.506 2.277 91.645 2.223 91.733 2.117 c
+91.829 2.017 91.899 1.859 91.939 1.646 c
+91.954 1.646 l
+91.99 1.741 92.031 1.83 92.071 1.911 c
+92.119 1.988 92.175 2.05 92.233 2.102 c
+92.292 2.16 92.358 2.204 92.439 2.234 c
+92.516 2.263 92.604 2.277 92.703 2.277 c
+92.84 2.277 92.954 2.252 93.042 2.204 c
+93.129 2.153 93.196 2.079 93.247 1.984 c
+93.306 1.884 93.343 1.756 93.365 1.602 c
+93.395 1.454 93.409 1.271 93.409 1.058 c
+93.409 -1.264 l
+92.689 -1.264 l
+92.689 0.852 l
+92.689 1.018 92.682 1.153 92.674 1.263 c
+92.663 1.371 92.645 1.454 92.616 1.514 c
+92.593 1.579 92.564 1.631 92.527 1.66 c
+92.497 1.69 92.458 1.705 92.41 1.705 c
+92.292 1.705 92.196 1.616 92.13 1.44 c
+92.071 1.271 92.042 1.014 92.042 0.661 c
+92.042 -1.264 l
+h
+95.383 -1.264 m
+95.383 0.852 l
+95.383 1.018 95.375 1.153 95.367 1.263 c
+95.357 1.371 95.338 1.454 95.309 1.514 c
+95.287 1.579 95.257 1.631 95.221 1.66 c
+95.192 1.69 95.151 1.705 95.103 1.705 c
+95.045 1.705 94.989 1.675 94.941 1.616 c
+94.901 1.565 94.868 1.491 94.839 1.396 c
+94.81 1.308 94.783 1.194 94.765 1.058 c
+94.754 0.918 94.75 0.768 94.75 0.602 c
+94.75 -1.264 l
+94.001 -1.264 l
+94.001 1.469 l
+94.001 1.705 l
+94.001 1.925 l
+94.001 2.002 93.993 2.065 93.986 2.117 c
+93.986 2.219 l
+94.662 2.219 l
+94.662 2.131 l
+94.662 1.984 l
+94.669 1.925 94.677 1.866 94.677 1.807 c
+94.677 1.646 l
+94.692 1.646 l
+94.71 1.734 94.739 1.811 94.78 1.881 c
+94.816 1.959 94.86 2.028 94.912 2.087 c
+94.97 2.146 95.037 2.19 95.118 2.219 c
+95.195 2.256 95.283 2.277 95.383 2.277 c
+95.566 2.277 95.706 2.223 95.794 2.117 c
+95.89 2.017 95.959 1.859 96 1.646 c
+96.015 1.646 l
+96.051 1.741 96.092 1.83 96.132 1.911 c
+96.18 1.988 96.235 2.05 96.294 2.102 c
+96.352 2.16 96.418 2.204 96.499 2.234 c
+96.576 2.263 96.665 2.277 96.764 2.277 c
+96.9 2.277 97.014 2.252 97.102 2.204 c
+97.191 2.153 97.256 2.079 97.308 1.984 c
+97.367 1.884 97.403 1.756 97.426 1.602 c
+97.455 1.454 97.47 1.271 97.47 1.058 c
+97.47 -1.264 l
+96.749 -1.264 l
+96.749 0.852 l
+96.749 1.018 96.742 1.153 96.734 1.263 c
+96.724 1.371 96.705 1.454 96.676 1.514 c
+96.653 1.579 96.624 1.631 96.588 1.66 c
+96.558 1.69 96.518 1.705 96.47 1.705 c
+96.352 1.705 96.257 1.616 96.191 1.44 c
+96.132 1.271 96.103 1.014 96.103 0.661 c
+96.103 -1.264 l
+h
+100.387 -0.647 m
+101.519 -0.647 l
+101.519 -1.264 l
+98.212 -1.264 l
+98.212 -0.647 l
+99.476 -0.647 l
+99.476 1.602 l
+98.55 1.602 l
+98.55 2.219 l
+100.387 2.219 l
+h
+99.476 3.513 0.912 -0.676 re
+99.476 2.836 m
+102.949 1.602 m
+102.405 1.602 l
+102.405 2.219 l
+102.993 2.219 l
+103.272 3.116 l
+103.845 3.116 l
+103.845 2.219 l
+105.081 2.219 l
+105.081 1.602 l
+103.845 1.602 l
+103.845 -0.103 l
+103.845 -0.324 l
+103.853 -0.393 103.875 -0.456 103.905 -0.515 c
+103.941 -0.566 103.996 -0.611 104.066 -0.647 c
+104.143 -0.676 104.257 -0.691 104.404 -0.691 c
+104.54 -0.691 104.676 -0.688 104.815 -0.676 c
+104.952 -0.659 105.083 -0.632 105.212 -0.603 c
+105.212 -1.206 l
+105.131 -1.216 105.054 -1.231 104.977 -1.25 c
+104.896 -1.261 104.819 -1.268 104.742 -1.279 c
+104.661 -1.287 104.573 -1.294 104.478 -1.294 c
+104.389 -1.301 104.29 -1.309 104.183 -1.309 c
+103.996 -1.309 103.834 -1.294 103.699 -1.264 c
+103.57 -1.228 103.456 -1.183 103.36 -1.133 c
+103.272 -1.085 103.199 -1.025 103.14 -0.956 c
+103.081 -0.879 103.037 -0.802 103.007 -0.721 c
+102.978 -0.632 102.956 -0.545 102.949 -0.456 c
+102.938 -0.36 102.934 -0.265 102.934 -0.177 c
+h
+113.569 -0.25 m
+113.569 -0.42 113.528 -0.57 113.451 -0.706 c
+113.382 -0.834 113.278 -0.948 113.143 -1.044 c
+113.014 -1.133 112.852 -1.202 112.657 -1.25 c
+112.47 -1.297 112.253 -1.324 112.011 -1.324 c
+111.782 -1.324 111.585 -1.309 111.408 -1.279 c
+111.232 -1.25 111.074 -1.202 110.938 -1.133 c
+110.798 -1.056 110.687 -0.956 110.6 -0.838 c
+110.511 -0.721 110.442 -0.574 110.394 -0.397 c
+111.202 -0.279 l
+111.221 -0.379 111.25 -0.456 111.29 -0.515 c
+111.338 -0.574 111.397 -0.618 111.467 -0.647 c
+111.533 -0.676 111.614 -0.703 111.702 -0.721 c
+111.79 -0.732 111.893 -0.736 112.011 -0.736 c
+112.106 -0.736 112.202 -0.732 112.29 -0.721 c
+112.378 -0.703 112.455 -0.676 112.526 -0.647 c
+112.591 -0.618 112.643 -0.581 112.672 -0.53 c
+112.709 -0.482 112.731 -0.42 112.731 -0.339 c
+112.731 -0.243 112.702 -0.169 112.643 -0.118 c
+112.591 -0.071 112.526 -0.03 112.437 0 c
+112.349 0.037 112.239 0.066 112.114 0.087 c
+111.996 0.118 111.863 0.147 111.717 0.176 c
+111.577 0.213 111.437 0.253 111.29 0.294 c
+111.151 0.341 111.026 0.404 110.908 0.484 c
+110.798 0.562 110.71 0.661 110.644 0.779 c
+110.574 0.897 110.541 1.047 110.541 1.234 c
+110.541 1.389 110.57 1.531 110.629 1.66 c
+110.695 1.797 110.791 1.911 110.908 1.999 c
+111.034 2.087 111.192 2.153 111.379 2.204 c
+111.562 2.252 111.776 2.277 112.011 2.277 c
+112.194 2.277 112.371 2.256 112.54 2.219 c
+112.705 2.19 112.852 2.135 112.981 2.057 c
+113.106 1.988 113.216 1.888 113.305 1.764 c
+113.392 1.646 113.451 1.502 113.48 1.337 c
+112.686 1.263 l
+112.665 1.341 112.636 1.404 112.599 1.454 c
+112.559 1.514 112.511 1.558 112.451 1.587 c
+112.4 1.624 112.337 1.649 112.26 1.66 c
+112.179 1.668 112.099 1.675 112.011 1.675 c
+111.794 1.675 111.632 1.646 111.526 1.587 c
+111.416 1.535 111.364 1.448 111.364 1.323 c
+111.364 1.242 111.383 1.179 111.423 1.132 c
+111.47 1.08 111.533 1.043 111.614 1.014 c
+111.702 0.984 111.797 0.955 111.908 0.926 c
+112.015 0.903 112.136 0.881 112.275 0.852 c
+112.43 0.823 112.588 0.783 112.746 0.735 c
+112.9 0.683 113.039 0.621 113.157 0.544 c
+113.274 0.463 113.37 0.359 113.451 0.235 c
+113.528 0.106 113.569 -0.056 113.569 -0.25 c
+115.425 1.514 m
+115.543 1.786 115.693 1.984 115.88 2.102 c
+116.064 2.219 116.285 2.277 116.542 2.277 c
+116.748 2.277 116.917 2.241 117.056 2.175 c
+117.203 2.105 117.313 2.013 117.394 1.896 c
+117.482 1.778 117.542 1.635 117.571 1.469 c
+117.607 1.3 117.629 1.124 117.629 0.941 c
+117.629 -1.264 l
+116.718 -1.264 l
+116.718 0.735 l
+116.718 0.87 116.707 0.992 116.688 1.102 c
+116.678 1.209 116.652 1.296 116.615 1.367 c
+116.575 1.444 116.516 1.502 116.439 1.543 c
+116.369 1.579 116.277 1.602 116.16 1.602 c
+116.05 1.602 115.954 1.576 115.865 1.529 c
+115.778 1.477 115.697 1.411 115.63 1.323 c
+115.572 1.234 115.52 1.124 115.483 0.999 c
+115.454 0.881 115.439 0.749 115.439 0.602 c
+115.439 -1.264 l
+114.527 -1.264 l
+114.527 3.513 l
+115.439 3.513 l
+115.439 2.204 l
+115.439 2.135 115.432 2.065 115.425 1.999 c
+115.425 1.793 l
+115.425 1.734 115.417 1.679 115.41 1.631 c
+115.41 1.514 l
+h
+119.547 -1.324 m
+119.379 -1.324 119.228 -1.301 119.092 -1.264 c
+118.963 -1.216 118.849 -1.147 118.754 -1.058 c
+118.666 -0.971 118.596 -0.864 118.548 -0.736 c
+118.496 -0.599 118.475 -0.449 118.475 -0.279 c
+118.475 -0.074 118.508 0.095 118.577 0.235 c
+118.643 0.382 118.739 0.492 118.857 0.573 c
+118.982 0.661 119.125 0.723 119.283 0.764 c
+119.449 0.801 119.624 0.826 119.813 0.837 c
+120.532 0.852 l
+120.532 1.028 l
+120.532 1.146 120.522 1.249 120.503 1.337 c
+120.481 1.425 120.448 1.491 120.401 1.543 c
+120.36 1.602 120.312 1.639 120.253 1.66 c
+120.195 1.679 120.129 1.69 120.062 1.69 c
+119.992 1.69 119.93 1.679 119.871 1.66 c
+119.819 1.649 119.772 1.624 119.724 1.587 c
+119.684 1.558 119.651 1.506 119.622 1.44 c
+119.599 1.381 119.584 1.3 119.577 1.205 c
+118.637 1.249 l
+118.666 1.396 118.71 1.531 118.768 1.66 c
+118.835 1.786 118.93 1.896 119.048 1.984 c
+119.165 2.079 119.306 2.153 119.474 2.204 c
+119.651 2.252 119.857 2.277 120.092 2.277 c
+120.532 2.277 120.863 2.167 121.091 1.955 c
+121.326 1.749 121.444 1.44 121.444 1.028 c
+121.444 -0.235 l
+121.444 -0.456 l
+121.451 -0.515 121.465 -0.57 121.488 -0.618 c
+121.506 -0.659 121.536 -0.691 121.576 -0.721 c
+121.613 -0.743 121.664 -0.75 121.723 -0.75 c
+121.789 -0.75 121.859 -0.746 121.929 -0.736 c
+121.929 -1.22 l
+121.87 -1.231 121.815 -1.243 121.767 -1.25 c
+121.727 -1.261 121.687 -1.268 121.65 -1.279 c
+121.609 -1.287 121.565 -1.294 121.517 -1.294 c
+121.465 -1.301 121.407 -1.309 121.341 -1.309 c
+121.113 -1.309 120.948 -1.257 120.841 -1.147 c
+120.731 -1.029 120.669 -0.864 120.65 -0.647 c
+120.636 -0.647 l
+120.565 -0.757 120.496 -0.853 120.43 -0.941 c
+120.36 -1.022 120.283 -1.088 120.195 -1.147 c
+120.106 -1.206 120.007 -1.25 119.9 -1.279 c
+119.801 -1.309 119.684 -1.324 119.547 -1.324 c
+120.532 0.353 m
+120.106 0.338 l
+120.007 0.338 119.915 0.33 119.827 0.323 c
+119.746 0.312 119.68 0.286 119.622 0.249 c
+119.562 0.209 119.511 0.151 119.474 0.073 c
+119.433 0.003 119.416 -0.088 119.416 -0.206 c
+119.416 -0.375 119.449 -0.497 119.518 -0.574 c
+119.584 -0.655 119.684 -0.691 119.813 -0.691 c
+119.919 -0.691 120.018 -0.669 120.106 -0.618 c
+120.202 -0.57 120.283 -0.508 120.341 -0.427 c
+120.407 -0.35 120.459 -0.262 120.488 -0.162 c
+120.518 -0.056 120.532 0.058 120.532 0.176 c
+h
+123.02 -2.631 m
+123.02 -2.014 l
+124.093 -2.014 l
+124.093 2.896 l
+123.02 2.896 l
+123.02 3.513 l
+124.946 3.513 l
+124.946 -2.631 l
+h
+f
+Q
+q 1 0 0 1 368.1085 380.8423 cm
+0 0 m
+-0.029 -0.58 -0.191 -1.022 -0.484 -1.323 c
+-0.779 -1.627 -1.198 -1.778 -1.734 -1.778 c
+-2.263 -1.778 -2.69 -1.58 -3.013 -1.176 c
+-3.329 -0.764 -3.484 -0.206 -3.484 0.5 c
+-3.484 1.47 l
+-3.484 2.165 -3.322 2.712 -2.998 3.117 c
+-2.675 3.516 -2.23 3.719 -1.66 3.719 c
+-1.153 3.719 -0.756 3.561 -0.47 3.248 c
+-0.187 2.944 -0.029 2.502 0 1.926 c
+-0.691 1.926 l
+-0.72 2.367 -0.816 2.679 -0.97 2.866 c
+-1.117 3.05 -1.348 3.146 -1.66 3.146 c
+-2.036 3.146 -2.318 2.999 -2.513 2.705 c
+-2.711 2.418 -2.807 2.003 -2.807 1.455 c
+-2.807 0.47 l
+-2.807 -0.07 -2.715 -0.484 -2.528 -0.779 c
+-2.344 -1.066 -2.079 -1.205 -1.734 -1.205 c
+-1.381 -1.205 -1.128 -1.117 -0.97 -0.941 c
+-0.816 -0.764 -0.72 -0.452 -0.691 0 c
+h
+2.455 1.661 m
+2.367 1.679 2.268 1.691 2.161 1.691 c
+1.827 1.691 1.592 1.507 1.455 1.147 c
+1.455 -1.705 l
+0.809 -1.705 l
+0.809 2.278 l
+1.441 2.278 l
+1.455 1.867 l
+1.632 2.19 1.875 2.352 2.191 2.352 c
+2.297 2.352 2.386 2.33 2.455 2.294 c
+h
+4.454 -1.778 m
+3.955 -1.778 3.572 -1.631 3.308 -1.338 c
+3.043 -1.043 2.911 -0.61 2.911 -0.029 c
+2.911 0.441 l
+2.911 1.037 3.036 1.503 3.293 1.837 c
+3.558 2.18 3.918 2.352 4.381 2.352 c
+4.84 2.352 5.182 2.198 5.409 1.897 c
+5.644 1.602 5.766 1.139 5.777 0.515 c
+5.777 0.088 l
+3.558 0.088 l
+3.558 0 l
+3.558 -0.434 3.635 -0.746 3.793 -0.941 c
+3.959 -1.128 4.19 -1.22 4.484 -1.22 c
+4.678 -1.22 4.851 -1.187 4.998 -1.117 c
+5.145 -1.04 5.281 -0.922 5.409 -0.764 c
+5.748 -1.176 l
+5.461 -1.58 5.031 -1.778 4.454 -1.778 c
+4.381 1.793 m
+4.105 1.793 3.903 1.698 3.778 1.515 c
+3.649 1.326 3.576 1.037 3.558 0.647 c
+5.131 0.647 l
+5.131 0.735 l
+5.108 1.118 5.042 1.386 4.925 1.544 c
+4.807 1.709 4.624 1.793 4.381 1.793 c
+8.599 -1.705 m
+8.559 -1.617 8.533 -1.469 8.526 -1.264 c
+8.291 -1.61 7.996 -1.778 7.643 -1.778 c
+7.28 -1.778 6.997 -1.683 6.791 -1.484 c
+6.593 -1.278 6.498 -0.992 6.498 -0.617 c
+6.498 -0.216 6.633 0.103 6.909 0.339 c
+7.181 0.58 7.556 0.706 8.026 0.706 c
+8.511 0.706 l
+8.511 1.132 l
+8.511 1.367 8.456 1.532 8.349 1.632 c
+8.239 1.738 8.077 1.793 7.865 1.793 c
+7.666 1.793 7.504 1.735 7.379 1.617 c
+7.262 1.5 7.203 1.353 7.203 1.176 c
+6.556 1.176 l
+6.556 1.371 6.615 1.562 6.733 1.75 c
+6.858 1.933 7.019 2.08 7.217 2.19 c
+7.423 2.297 7.651 2.352 7.909 2.352 c
+8.309 2.352 8.614 2.249 8.819 2.043 c
+9.033 1.837 9.147 1.544 9.158 1.162 c
+9.158 -0.852 l
+9.158 -1.157 9.195 -1.422 9.276 -1.646 c
+9.276 -1.705 l
+h
+7.732 -1.19 m
+7.897 -1.19 8.048 -1.147 8.188 -1.058 c
+8.335 -0.97 8.441 -0.86 8.511 -0.72 c
+8.511 0.221 l
+8.144 0.221 l
+7.828 0.221 7.585 0.151 7.408 0.015 c
+7.232 -0.114 7.144 -0.301 7.144 -0.544 c
+7.144 -0.771 7.188 -0.937 7.277 -1.043 c
+7.365 -1.143 7.516 -1.19 7.732 -1.19 c
+11.01 3.234 m
+11.01 2.278 l
+11.612 2.278 l
+11.612 1.75 l
+11.01 1.75 l
+11.01 -0.72 l
+11.01 -0.878 11.032 -0.995 11.084 -1.072 c
+11.142 -1.153 11.231 -1.19 11.348 -1.19 c
+11.437 -1.19 11.524 -1.176 11.612 -1.147 c
+11.612 -1.705 l
+11.466 -1.753 11.311 -1.778 11.157 -1.778 c
+10.899 -1.778 10.705 -1.687 10.569 -1.5 c
+10.429 -1.315 10.363 -1.055 10.363 -0.72 c
+10.363 1.75 l
+9.76 1.75 l
+9.76 2.278 l
+10.363 2.278 l
+10.363 3.234 l
+h
+13.803 -1.778 m
+13.303 -1.778 12.921 -1.631 12.657 -1.338 c
+12.391 -1.043 12.26 -0.61 12.26 -0.029 c
+12.26 0.441 l
+12.26 1.037 12.385 1.503 12.642 1.837 c
+12.906 2.18 13.266 2.352 13.729 2.352 c
+14.188 2.352 14.531 2.198 14.758 1.897 c
+14.993 1.602 15.115 1.139 15.126 0.515 c
+15.126 0.088 l
+12.906 0.088 l
+12.906 0 l
+12.906 -0.434 12.983 -0.746 13.141 -0.941 c
+13.307 -1.128 13.538 -1.22 13.833 -1.22 c
+14.027 -1.22 14.199 -1.187 14.346 -1.117 c
+14.494 -1.04 14.629 -0.922 14.758 -0.764 c
+15.096 -1.176 l
+14.81 -1.58 14.38 -1.778 13.803 -1.778 c
+13.729 1.793 m
+13.453 1.793 13.251 1.698 13.127 1.515 c
+12.998 1.326 12.925 1.037 12.906 0.647 c
+14.479 0.647 l
+14.479 0.735 l
+14.457 1.118 14.39 1.386 14.273 1.544 c
+14.155 1.709 13.972 1.793 13.729 1.793 c
+19.668 -1.705 m
+19.628 -1.617 19.601 -1.469 19.595 -1.264 c
+19.359 -1.61 19.065 -1.778 18.712 -1.778 c
+18.348 -1.778 18.066 -1.683 17.86 -1.484 c
+17.661 -1.278 17.565 -0.992 17.565 -0.617 c
+17.565 -0.216 17.702 0.103 17.978 0.339 c
+18.249 0.58 18.624 0.706 19.094 0.706 c
+19.58 0.706 l
+19.58 1.132 l
+19.58 1.367 19.524 1.532 19.418 1.632 c
+19.308 1.738 19.146 1.793 18.932 1.793 c
+18.735 1.793 18.573 1.735 18.448 1.617 c
+18.33 1.5 18.271 1.353 18.271 1.176 c
+17.625 1.176 l
+17.625 1.371 17.683 1.562 17.801 1.75 c
+17.926 1.933 18.088 2.08 18.286 2.19 c
+18.492 2.297 18.72 2.352 18.977 2.352 c
+19.377 2.352 19.682 2.249 19.888 2.043 c
+20.102 1.837 20.216 1.544 20.226 1.162 c
+20.226 -0.852 l
+20.226 -1.157 20.263 -1.422 20.343 -1.646 c
+20.343 -1.705 l
+h
+18.801 -1.19 m
+18.966 -1.19 19.117 -1.147 19.256 -1.058 c
+19.403 -0.97 19.51 -0.86 19.58 -0.72 c
+19.58 0.221 l
+19.212 0.221 l
+18.896 0.221 18.654 0.151 18.477 0.015 c
+18.301 -0.114 18.213 -0.301 18.213 -0.544 c
+18.213 -0.771 18.257 -0.937 18.344 -1.043 c
+18.433 -1.143 18.583 -1.19 18.801 -1.19 c
+23.798 3.234 m
+23.798 2.278 l
+24.401 2.278 l
+24.401 1.75 l
+23.798 1.75 l
+23.798 -0.72 l
+23.798 -0.878 23.82 -0.995 23.871 -1.072 c
+23.931 -1.153 24.019 -1.19 24.137 -1.19 c
+24.224 -1.19 24.312 -1.176 24.401 -1.147 c
+24.401 -1.705 l
+24.254 -1.753 24.1 -1.778 23.946 -1.778 c
+23.688 -1.778 23.493 -1.687 23.358 -1.5 c
+23.217 -1.315 23.152 -1.055 23.152 -0.72 c
+23.152 1.75 l
+22.549 1.75 l
+22.549 2.278 l
+23.152 2.278 l
+23.152 3.234 l
+h
+27.208 -1.705 m
+27.168 -1.617 27.142 -1.469 27.135 -1.264 c
+26.899 -1.61 26.606 -1.778 26.253 -1.778 c
+25.889 -1.778 25.606 -1.683 25.4 -1.484 c
+25.202 -1.278 25.106 -0.992 25.106 -0.617 c
+25.106 -0.216 25.242 0.103 25.518 0.339 c
+25.79 0.58 26.165 0.706 26.635 0.706 c
+27.121 0.706 l
+27.121 1.132 l
+27.121 1.367 27.065 1.532 26.959 1.632 c
+26.849 1.738 26.687 1.793 26.473 1.793 c
+26.275 1.793 26.113 1.735 25.988 1.617 c
+25.87 1.5 25.812 1.353 25.812 1.176 c
+25.165 1.176 l
+25.165 1.371 25.224 1.562 25.342 1.75 c
+25.467 1.933 25.629 2.08 25.827 2.19 c
+26.032 2.297 26.261 2.352 26.518 2.352 c
+26.918 2.352 27.223 2.249 27.429 2.043 c
+27.642 1.837 27.756 1.544 27.767 1.162 c
+27.767 -0.852 l
+27.767 -1.157 27.804 -1.422 27.884 -1.646 c
+27.884 -1.705 l
+h
+26.341 -1.19 m
+26.506 -1.19 26.657 -1.147 26.797 -1.058 c
+26.944 -0.97 27.05 -0.86 27.121 -0.72 c
+27.121 0.221 l
+26.753 0.221 l
+26.437 0.221 26.194 0.151 26.018 0.015 c
+25.841 -0.114 25.753 -0.301 25.753 -0.544 c
+25.753 -0.771 25.797 -0.937 25.885 -1.043 c
+25.974 -1.143 26.124 -1.19 26.341 -1.19 c
+28.634 0.47 m
+28.634 1.087 28.744 1.551 28.972 1.867 c
+29.197 2.19 29.531 2.352 29.972 2.352 c
+30.373 2.352 30.677 2.176 30.884 1.823 c
+30.927 2.278 l
+31.515 2.278 l
+31.515 -1.749 l
+31.515 -2.238 31.387 -2.616 31.133 -2.881 c
+30.876 -3.146 30.523 -3.278 30.074 -3.278 c
+29.876 -3.278 29.656 -3.227 29.413 -3.131 c
+29.167 -3.032 28.987 -2.911 28.869 -2.763 c
+29.134 -2.323 l
+29.398 -2.587 29.696 -2.719 30.03 -2.719 c
+30.567 -2.719 30.843 -2.425 30.853 -1.837 c
+30.853 -1.308 l
+30.648 -1.624 30.346 -1.778 29.957 -1.778 c
+29.546 -1.778 29.222 -1.627 28.987 -1.323 c
+28.759 -1.01 28.642 -0.559 28.634 0.029 c
+h
+29.296 0.088 m
+29.296 -0.353 29.359 -0.683 29.487 -0.897 c
+29.612 -1.103 29.829 -1.205 30.134 -1.205 c
+30.456 -1.205 30.695 -1.04 30.853 -0.706 c
+30.853 1.279 l
+30.685 1.602 30.446 1.764 30.134 1.764 c
+29.839 1.764 29.623 1.661 29.487 1.455 c
+29.359 1.249 29.296 0.927 29.296 0.485 c
+h
+34.059 0.47 m
+34.059 1.047 34.194 1.503 34.47 1.837 c
+34.753 2.18 35.123 2.352 35.587 2.352 c
+36.046 2.352 36.414 2.182 36.689 1.852 c
+36.972 1.529 37.12 1.081 37.13 0.515 c
+37.13 0.088 l
+37.13 -0.482 36.987 -0.937 36.704 -1.278 c
+36.428 -1.613 36.06 -1.778 35.601 -1.778 c
+35.138 -1.778 34.768 -1.617 34.485 -1.293 c
+34.209 -0.962 34.065 -0.522 34.059 0.029 c
+h
+34.705 0.088 m
+34.705 -0.316 34.782 -0.632 34.94 -0.867 c
+35.106 -1.103 35.326 -1.22 35.601 -1.22 c
+36.168 -1.22 36.461 -0.808 36.484 0.015 c
+36.484 0.47 l
+36.484 0.871 36.399 1.191 36.233 1.426 c
+36.075 1.669 35.859 1.793 35.587 1.793 c
+35.322 1.793 35.106 1.669 34.94 1.426 c
+34.782 1.191 34.705 0.871 34.705 0.47 c
+h
+40.849 0.088 m
+40.849 -0.529 40.735 -0.995 40.511 -1.308 c
+40.294 -1.624 39.971 -1.778 39.541 -1.778 c
+39.118 -1.778 38.805 -1.598 38.6 -1.234 c
+38.57 -1.705 l
+37.968 -1.705 l
+37.968 3.94 l
+38.615 3.94 l
+38.615 1.837 l
+38.828 2.18 39.137 2.352 39.541 2.352 c
+39.971 2.352 40.294 2.194 40.511 1.882 c
+40.735 1.577 40.849 1.11 40.849 0.485 c
+h
+40.202 0.47 m
+40.202 0.941 40.133 1.272 39.996 1.47 c
+39.868 1.665 39.659 1.764 39.364 1.764 c
+39.03 1.764 38.78 1.58 38.615 1.22 c
+38.615 -0.661 l
+38.78 -1.025 39.034 -1.205 39.379 -1.205 c
+39.673 -1.205 39.883 -1.103 40.012 -0.897 c
+40.137 -0.69 40.202 -0.374 40.202 0.059 c
+h
+42.348 2.278 m
+42.348 -2.205 l
+42.348 -2.94 42.059 -3.307 41.481 -3.307 c
+41.342 -3.307 41.22 -3.285 41.114 -3.248 c
+41.114 -2.705 l
+41.184 -2.723 41.268 -2.734 41.378 -2.734 c
+41.485 -2.734 41.562 -2.69 41.614 -2.601 c
+41.672 -2.521 41.702 -2.381 41.702 -2.175 c
+41.702 2.278 l
+h
+42.377 3.322 m
+42.377 3.212 42.348 3.12 42.29 3.043 c
+42.231 2.973 42.136 2.94 42.011 2.94 c
+41.893 2.94 41.797 2.973 41.731 3.043 c
+41.672 3.12 41.643 3.212 41.643 3.322 c
+41.643 3.439 41.672 3.532 41.731 3.601 c
+41.797 3.678 41.893 3.719 42.011 3.719 c
+42.136 3.719 42.231 3.678 42.29 3.601 c
+42.348 3.52 42.377 3.429 42.377 3.322 c
+44.803 -1.778 m
+44.303 -1.778 43.921 -1.631 43.657 -1.338 c
+43.392 -1.043 43.26 -0.61 43.26 -0.029 c
+43.26 0.441 l
+43.26 1.037 43.385 1.503 43.642 1.837 c
+43.906 2.18 44.266 2.352 44.729 2.352 c
+45.189 2.352 45.531 2.198 45.758 1.897 c
+45.994 1.602 46.115 1.139 46.126 0.515 c
+46.126 0.088 l
+43.906 0.088 l
+43.906 0 l
+43.906 -0.434 43.983 -0.746 44.141 -0.941 c
+44.307 -1.128 44.538 -1.22 44.833 -1.22 c
+45.028 -1.22 45.2 -1.187 45.347 -1.117 c
+45.494 -1.04 45.63 -0.922 45.758 -0.764 c
+46.096 -1.176 l
+45.81 -1.58 45.38 -1.778 44.803 -1.778 c
+44.729 1.793 m
+44.454 1.793 44.252 1.698 44.127 1.515 c
+43.998 1.326 43.925 1.037 43.906 0.647 c
+45.479 0.647 l
+45.479 0.735 l
+45.457 1.118 45.391 1.386 45.273 1.544 c
+45.155 1.709 44.972 1.793 44.729 1.793 c
+48.287 -1.22 m
+48.5 -1.22 48.673 -1.157 48.801 -1.029 c
+48.937 -0.893 49.011 -0.702 49.022 -0.455 c
+49.639 -0.455 l
+49.617 -0.837 49.481 -1.157 49.228 -1.411 c
+48.97 -1.658 48.658 -1.778 48.287 -1.778 c
+47.794 -1.778 47.42 -1.627 47.155 -1.323 c
+46.898 -1.01 46.773 -0.544 46.773 0.073 c
+46.773 0.515 l
+46.773 1.11 46.898 1.565 47.155 1.882 c
+47.42 2.194 47.794 2.352 48.287 2.352 c
+48.687 2.352 49.007 2.22 49.242 1.955 c
+49.485 1.698 49.617 1.353 49.639 0.912 c
+49.022 0.912 l
+48.999 1.205 48.926 1.426 48.801 1.573 c
+48.683 1.72 48.511 1.793 48.287 1.793 c
+47.993 1.793 47.776 1.694 47.64 1.5 c
+47.501 1.312 47.427 1.004 47.42 0.574 c
+47.42 0.059 l
+47.42 -0.411 47.486 -0.746 47.625 -0.941 c
+47.773 -1.128 47.993 -1.22 48.287 -1.22 c
+51.241 3.234 m
+51.241 2.278 l
+51.844 2.278 l
+51.844 1.75 l
+51.241 1.75 l
+51.241 -0.72 l
+51.241 -0.878 51.264 -0.995 51.314 -1.072 c
+51.374 -1.153 51.462 -1.19 51.58 -1.19 c
+51.667 -1.19 51.756 -1.176 51.844 -1.147 c
+51.844 -1.705 l
+51.697 -1.753 51.543 -1.778 51.388 -1.778 c
+51.131 -1.778 50.936 -1.687 50.8 -1.5 c
+50.661 -1.315 50.595 -1.055 50.595 -0.72 c
+50.595 1.75 l
+49.992 1.75 l
+49.992 2.278 l
+50.595 2.278 l
+50.595 3.234 l
+h
+54.946 2.278 m
+54.96 1.837 l
+55.214 2.18 55.537 2.352 55.931 2.352 c
+56.636 2.352 56.992 1.882 57.003 0.941 c
+57.003 -1.705 l
+56.357 -1.705 l
+56.357 0.912 l
+56.357 1.224 56.301 1.444 56.195 1.573 c
+56.085 1.698 55.931 1.764 55.725 1.764 c
+55.567 1.764 55.42 1.709 55.283 1.602 c
+55.155 1.492 55.052 1.357 54.975 1.191 c
+54.975 -1.705 l
+54.328 -1.705 l
+54.328 2.278 l
+h
+60.016 -1.705 m
+59.976 -1.617 59.95 -1.469 59.943 -1.264 c
+59.708 -1.61 59.414 -1.778 59.061 -1.778 c
+58.697 -1.778 58.414 -1.683 58.208 -1.484 c
+58.011 -1.278 57.915 -0.992 57.915 -0.617 c
+57.915 -0.216 58.051 0.103 58.326 0.339 c
+58.599 0.58 58.973 0.706 59.443 0.706 c
+59.929 0.706 l
+59.929 1.132 l
+59.929 1.367 59.873 1.532 59.767 1.632 c
+59.657 1.738 59.495 1.793 59.282 1.793 c
+59.083 1.793 58.921 1.735 58.796 1.617 c
+58.679 1.5 58.62 1.353 58.62 1.176 c
+57.973 1.176 l
+57.973 1.371 58.032 1.562 58.15 1.75 c
+58.275 1.933 58.437 2.08 58.635 2.19 c
+58.84 2.297 59.069 2.352 59.326 2.352 c
+59.727 2.352 60.031 2.249 60.237 2.043 c
+60.45 1.837 60.564 1.544 60.575 1.162 c
+60.575 -0.852 l
+60.575 -1.157 60.612 -1.422 60.693 -1.646 c
+60.693 -1.705 l
+h
+59.149 -1.19 m
+59.315 -1.19 59.465 -1.147 59.605 -1.058 c
+59.752 -0.97 59.858 -0.86 59.929 -0.72 c
+59.929 0.221 l
+59.561 0.221 l
+59.245 0.221 59.002 0.151 58.826 0.015 c
+58.649 -0.114 58.561 -0.301 58.561 -0.544 c
+58.561 -0.771 58.605 -0.937 58.694 -1.043 c
+58.782 -1.143 58.933 -1.19 59.149 -1.19 c
+62.192 2.278 m
+62.206 1.911 l
+62.449 2.205 62.769 2.352 63.162 2.352 c
+63.603 2.352 63.912 2.153 64.088 1.764 c
+64.342 2.153 64.691 2.352 65.132 2.352 c
+65.867 2.352 66.242 1.889 66.264 0.97 c
+66.264 -1.705 l
+65.617 -1.705 l
+65.617 0.912 l
+65.617 1.205 65.562 1.419 65.456 1.558 c
+65.356 1.694 65.184 1.764 64.941 1.764 c
+64.743 1.764 64.581 1.683 64.456 1.529 c
+64.338 1.382 64.268 1.191 64.25 0.956 c
+64.25 -1.705 l
+63.588 -1.705 l
+63.588 0.941 l
+63.588 1.488 63.368 1.764 62.927 1.764 c
+62.593 1.764 62.358 1.602 62.221 1.279 c
+62.221 -1.705 l
+61.575 -1.705 l
+61.575 2.278 l
+h
+68.66 -1.778 m
+68.16 -1.778 67.777 -1.631 67.513 -1.338 c
+67.249 -1.043 67.116 -0.61 67.116 -0.029 c
+67.116 0.441 l
+67.116 1.037 67.241 1.503 67.498 1.837 c
+67.763 2.18 68.124 2.352 68.586 2.352 c
+69.046 2.352 69.387 2.198 69.615 1.897 c
+69.85 1.602 69.971 1.139 69.983 0.515 c
+69.983 0.088 l
+67.763 0.088 l
+67.763 0 l
+67.763 -0.434 67.84 -0.746 67.999 -0.941 c
+68.164 -1.128 68.395 -1.22 68.689 -1.22 c
+68.884 -1.22 69.057 -1.187 69.204 -1.117 c
+69.35 -1.04 69.487 -0.922 69.615 -0.764 c
+69.953 -1.176 l
+69.666 -1.58 69.237 -1.778 68.66 -1.778 c
+68.586 1.793 m
+68.311 1.793 68.109 1.698 67.983 1.515 c
+67.855 1.326 67.781 1.037 67.763 0.647 c
+69.336 0.647 l
+69.336 0.735 l
+69.314 1.118 69.248 1.386 69.13 1.544 c
+69.013 1.709 68.829 1.793 68.586 1.793 c
+70.63 0.47 m
+70.63 1.077 70.74 1.544 70.967 1.867 c
+71.203 2.19 71.53 2.352 71.952 2.352 c
+72.334 2.352 72.633 2.194 72.849 1.882 c
+72.849 3.94 l
+73.495 3.94 l
+73.495 -1.705 l
+72.907 -1.705 l
+72.864 -1.278 l
+72.658 -1.613 72.353 -1.778 71.952 -1.778 c
+71.54 -1.778 71.218 -1.624 70.983 -1.308 c
+70.747 -0.985 70.63 -0.529 70.63 0.059 c
+h
+71.276 0.088 m
+71.276 -0.353 71.338 -0.683 71.467 -0.897 c
+71.603 -1.103 71.824 -1.205 72.128 -1.205 c
+72.452 -1.205 72.691 -1.043 72.849 -0.72 c
+72.849 1.294 l
+72.68 1.606 72.441 1.764 72.128 1.764 c
+71.824 1.764 71.603 1.661 71.467 1.455 c
+71.338 1.249 71.276 0.927 71.276 0.485 c
+h
+f
+Q
+q 1 0 0 1 445.1757 383.1208 cm
+0 0 m
+0.03 -0.397 l
+0.265 -0.085 0.566 0.073 0.941 0.073 c
+1.625 0.073 1.977 -0.408 1.999 -1.367 c
+1.999 -3.983 l
+0.956 -3.983 l
+0.956 -1.44 l
+0.956 -1.216 0.919 -1.055 0.853 -0.956 c
+0.783 -0.86 0.665 -0.808 0.5 -0.808 c
+0.312 -0.808 0.166 -0.904 0.059 -1.087 c
+0.059 -3.983 l
+-0.985 -3.983 l
+-0.985 0 l
+h
+4.63 -3.983 m
+4.601 -3.925 4.572 -3.821 4.542 -3.675 c
+4.355 -3.932 4.105 -4.056 3.793 -4.056 c
+3.458 -4.056 3.179 -3.95 2.955 -3.734 c
+2.738 -3.509 2.631 -3.219 2.631 -2.866 c
+2.631 -2.454 2.764 -2.138 3.028 -1.911 c
+3.293 -1.675 3.675 -1.558 4.175 -1.558 c
+4.499 -1.558 l
+4.499 -1.234 l
+4.499 -1.058 4.462 -0.937 4.395 -0.867 c
+4.337 -0.79 4.248 -0.75 4.131 -0.75 c
+3.874 -0.75 3.749 -0.904 3.749 -1.205 c
+2.705 -1.205 l
+2.705 -0.834 2.841 -0.529 3.117 -0.294 c
+3.389 -0.052 3.738 0.073 4.16 0.073 c
+4.601 0.073 4.939 -0.044 5.174 -0.279 c
+5.417 -0.507 5.542 -0.831 5.542 -1.249 c
+5.542 -3.116 l
+5.542 -3.462 5.59 -3.73 5.689 -3.925 c
+5.689 -3.983 l
+h
+4.028 -3.233 m
+4.135 -3.233 4.227 -3.215 4.307 -3.175 c
+4.395 -3.127 4.458 -3.069 4.499 -2.998 c
+4.499 -2.175 l
+4.248 -2.175 l
+4.072 -2.175 3.929 -2.234 3.822 -2.352 c
+3.723 -2.462 3.675 -2.609 3.675 -2.793 c
+3.675 -3.087 3.793 -3.233 4.028 -3.233 c
+7.262 0 m
+7.291 -0.368 l
+7.526 -0.073 7.835 0.073 8.217 0.073 c
+8.617 0.073 8.897 -0.11 9.055 -0.47 c
+9.29 -0.11 9.617 0.073 10.04 0.073 c
+10.734 0.073 11.088 -0.411 11.098 -1.382 c
+11.098 -3.983 l
+10.069 -3.983 l
+10.069 -1.44 l
+10.069 -1.216 10.032 -1.055 9.966 -0.956 c
+9.908 -0.86 9.797 -0.808 9.643 -0.808 c
+9.444 -0.808 9.305 -0.926 9.216 -1.161 c
+9.216 -3.983 l
+8.173 -3.983 l
+8.173 -1.455 l
+8.173 -1.22 8.144 -1.055 8.085 -0.956 c
+8.026 -0.86 7.915 -0.808 7.761 -0.808 c
+7.585 -0.808 7.441 -0.904 7.335 -1.087 c
+7.335 -3.983 l
+6.292 -3.983 l
+6.292 0 l
+h
+13.479 -4.056 m
+12.95 -4.056 12.532 -3.902 12.23 -3.586 c
+11.936 -3.263 11.789 -2.803 11.789 -2.205 c
+11.789 -1.897 l
+11.789 -1.272 11.925 -0.786 12.2 -0.441 c
+12.472 -0.099 12.866 0.073 13.376 0.073 c
+13.876 0.073 14.247 -0.088 14.494 -0.411 c
+14.747 -0.735 14.88 -1.213 14.89 -1.837 c
+14.89 -2.337 l
+12.818 -2.337 l
+12.836 -2.631 12.898 -2.848 13.009 -2.984 c
+13.126 -3.123 13.307 -3.19 13.553 -3.19 c
+13.895 -3.19 14.184 -3.072 14.42 -2.837 c
+14.832 -3.469 l
+14.703 -3.645 14.516 -3.788 14.273 -3.896 c
+14.026 -4.002 13.762 -4.056 13.479 -4.056 c
+12.833 -1.617 m
+13.862 -1.617 l
+13.862 -1.514 l
+13.862 -1.278 13.821 -1.103 13.744 -0.985 c
+13.675 -0.86 13.546 -0.794 13.361 -0.794 c
+13.185 -0.794 13.053 -0.864 12.965 -0.999 c
+12.884 -1.128 12.84 -1.334 12.833 -1.617 c
+f
+Q
+q 1 0 0 1 462.7704 379.1377 cm
+0 0 m
+0 3.454 l
+-0.529 3.454 l
+-0.529 3.983 l
+0 3.983 l
+0 4.438 l
+0 4.839 0.096 5.151 0.294 5.379 c
+0.5 5.604 0.78 5.718 1.133 5.718 c
+1.268 5.718 1.401 5.695 1.529 5.659 c
+1.5 5.115 l
+1.401 5.134 1.301 5.144 1.206 5.144 c
+0.831 5.144 0.647 4.88 0.647 4.351 c
+0.647 3.983 l
+1.324 3.983 l
+1.324 3.454 l
+0.647 3.454 l
+0.647 0 l
+h
+1.956 2.175 m
+1.956 2.752 2.091 3.208 2.367 3.542 c
+2.65 3.884 3.021 4.056 3.484 4.056 c
+3.944 4.056 4.311 3.887 4.586 3.557 c
+4.869 3.233 5.017 2.786 5.027 2.219 c
+5.027 1.793 l
+5.027 1.223 4.884 0.768 4.601 0.426 c
+4.326 0.091 3.958 -0.073 3.499 -0.073 c
+3.036 -0.073 2.665 0.087 2.382 0.411 c
+2.106 0.742 1.962 1.182 1.956 1.734 c
+h
+2.602 1.793 m
+2.602 1.389 2.679 1.072 2.837 0.837 c
+3.003 0.602 3.223 0.484 3.499 0.484 c
+4.065 0.484 4.358 0.897 4.381 1.72 c
+4.381 2.175 l
+4.381 2.576 4.296 2.896 4.131 3.131 c
+3.973 3.374 3.756 3.498 3.484 3.498 c
+3.219 3.498 3.003 3.374 2.837 3.131 c
+2.679 2.896 2.602 2.576 2.602 2.175 c
+h
+7.512 3.366 m
+7.423 3.384 7.325 3.395 7.217 3.395 c
+6.883 3.395 6.648 3.212 6.512 2.851 c
+6.512 0 l
+5.865 0 l
+5.865 3.983 l
+6.498 3.983 l
+6.512 3.572 l
+6.689 3.895 6.931 4.056 7.247 4.056 c
+7.354 4.056 7.442 4.035 7.512 3.998 c
+h
+11.26 0.484 m
+11.473 0.484 11.645 0.548 11.774 0.675 c
+11.911 0.812 11.984 1.003 11.994 1.249 c
+12.612 1.249 l
+12.59 0.867 12.454 0.548 12.2 0.294 c
+11.944 0.047 11.631 -0.073 11.26 -0.073 c
+10.768 -0.073 10.392 0.077 10.128 0.382 c
+9.871 0.694 9.746 1.161 9.746 1.778 c
+9.746 2.219 l
+9.746 2.815 9.871 3.27 10.128 3.586 c
+10.392 3.898 10.768 4.056 11.26 4.056 c
+11.66 4.056 11.98 3.925 12.215 3.659 c
+12.458 3.403 12.59 3.057 12.612 2.616 c
+11.994 2.616 l
+11.973 2.91 11.899 3.131 11.774 3.278 c
+11.657 3.424 11.484 3.498 11.26 3.498 c
+10.966 3.498 10.749 3.399 10.613 3.204 c
+10.473 3.017 10.4 2.708 10.392 2.278 c
+10.392 1.764 l
+10.392 1.294 10.459 0.959 10.598 0.764 c
+10.745 0.577 10.966 0.484 11.26 0.484 c
+15.39 0.353 m
+15.173 0.066 14.861 -0.073 14.45 -0.073 c
+14.086 -0.073 13.81 0.047 13.627 0.294 c
+13.45 0.548 13.355 0.911 13.347 1.381 c
+13.347 3.983 l
+13.993 3.983 l
+13.993 1.44 l
+13.993 0.812 14.178 0.5 14.552 0.5 c
+14.953 0.5 15.229 0.675 15.375 1.028 c
+15.375 3.983 l
+16.023 3.983 l
+16.023 0 l
+15.405 0 l
+h
+18.654 3.366 m
+18.565 3.384 18.466 3.395 18.359 3.395 c
+18.025 3.395 17.79 3.212 17.654 2.851 c
+17.654 0 l
+17.008 0 l
+17.008 3.983 l
+17.639 3.983 l
+17.654 3.572 l
+17.831 3.895 18.073 4.056 18.389 4.056 c
+18.496 4.056 18.583 4.035 18.654 3.998 c
+h
+20.947 3.366 m
+20.858 3.384 20.759 3.395 20.653 3.395 c
+20.318 3.395 20.083 3.212 19.947 2.851 c
+19.947 0 l
+19.3 0 l
+19.3 3.983 l
+19.932 3.983 l
+19.947 3.572 l
+20.123 3.895 20.366 4.056 20.682 4.056 c
+20.788 4.056 20.877 4.035 20.947 3.998 c
+h
+22.946 -0.073 m
+22.446 -0.073 22.064 0.073 21.799 0.367 c
+21.534 0.661 21.402 1.095 21.402 1.675 c
+21.402 2.146 l
+21.402 2.741 21.527 3.208 21.785 3.542 c
+22.049 3.884 22.409 4.056 22.872 4.056 c
+23.331 4.056 23.674 3.902 23.901 3.601 c
+24.137 3.307 24.258 2.844 24.268 2.219 c
+24.268 1.793 l
+22.049 1.793 l
+22.049 1.705 l
+22.049 1.271 22.126 0.959 22.284 0.764 c
+22.45 0.577 22.681 0.484 22.975 0.484 c
+23.169 0.484 23.343 0.517 23.489 0.588 c
+23.636 0.665 23.772 0.783 23.901 0.941 c
+24.239 0.529 l
+23.952 0.124 23.522 -0.073 22.946 -0.073 c
+22.872 3.498 m
+22.597 3.498 22.394 3.403 22.269 3.219 c
+22.141 3.031 22.067 2.741 22.049 2.352 c
+23.622 2.352 l
+23.622 2.439 l
+23.599 2.822 23.534 3.09 23.416 3.248 c
+23.298 3.414 23.115 3.498 22.872 3.498 c
+25.665 3.983 m
+25.679 3.542 l
+25.933 3.884 26.257 4.056 26.65 4.056 c
+27.356 4.056 27.711 3.586 27.723 2.645 c
+27.723 0 l
+27.076 0 l
+27.076 2.616 l
+27.076 2.929 27.021 3.149 26.915 3.278 c
+26.804 3.403 26.65 3.469 26.444 3.469 c
+26.286 3.469 26.139 3.414 26.003 3.307 c
+25.874 3.197 25.772 3.061 25.694 2.896 c
+25.694 0 l
+25.047 0 l
+25.047 3.983 l
+h
+29.546 4.939 m
+29.546 3.983 l
+30.148 3.983 l
+30.148 3.454 l
+29.546 3.454 l
+29.546 0.985 l
+29.546 0.827 29.567 0.709 29.619 0.632 c
+29.677 0.551 29.766 0.515 29.883 0.515 c
+29.972 0.515 30.06 0.529 30.148 0.558 c
+30.148 0 l
+30.001 -0.048 29.847 -0.073 29.693 -0.073 c
+29.436 -0.073 29.241 0.018 29.105 0.205 c
+28.965 0.389 28.899 0.65 28.899 0.985 c
+28.899 3.454 l
+28.297 3.454 l
+28.297 3.983 l
+28.899 3.983 l
+28.899 4.939 l
+h
+34.014 0.484 m
+34.227 0.484 34.4 0.548 34.529 0.675 c
+34.664 0.812 34.738 1.003 34.749 1.249 c
+35.366 1.249 l
+35.345 0.867 35.208 0.548 34.955 0.294 c
+34.697 0.047 34.385 -0.073 34.014 -0.073 c
+33.521 -0.073 33.147 0.077 32.883 0.382 c
+32.625 0.694 32.5 1.161 32.5 1.778 c
+32.5 2.219 l
+32.5 2.815 32.625 3.27 32.883 3.586 c
+33.147 3.898 33.521 4.056 34.014 4.056 c
+34.415 4.056 34.734 3.925 34.969 3.659 c
+35.212 3.403 35.345 3.057 35.366 2.616 c
+34.749 2.616 l
+34.727 2.91 34.653 3.131 34.529 3.278 c
+34.411 3.424 34.238 3.498 34.014 3.498 c
+33.72 3.498 33.503 3.399 33.367 3.204 c
+33.228 3.017 33.154 2.708 33.147 2.278 c
+33.147 1.764 l
+33.147 1.294 33.213 0.959 33.353 0.764 c
+33.5 0.577 33.72 0.484 34.014 0.484 c
+35.983 2.175 m
+35.983 2.752 36.12 3.208 36.395 3.542 c
+36.678 3.884 37.049 4.056 37.512 4.056 c
+37.972 4.056 38.339 3.887 38.615 3.557 c
+38.898 3.233 39.044 2.786 39.056 2.219 c
+39.056 1.793 l
+39.056 1.223 38.913 0.768 38.63 0.426 c
+38.354 0.091 37.986 -0.073 37.527 -0.073 c
+37.064 -0.073 36.693 0.087 36.41 0.411 c
+36.135 0.742 35.991 1.182 35.983 1.734 c
+h
+36.631 1.793 m
+36.631 1.389 36.708 1.072 36.866 0.837 c
+37.031 0.602 37.251 0.484 37.527 0.484 c
+38.093 0.484 38.387 0.897 38.409 1.72 c
+38.409 2.175 l
+38.409 2.576 38.325 2.896 38.159 3.131 c
+38.001 3.374 37.785 3.498 37.512 3.498 c
+37.248 3.498 37.031 3.374 36.866 3.131 c
+36.708 2.896 36.631 2.576 36.631 2.175 c
+h
+40.511 3.983 m
+40.526 3.615 l
+40.768 3.91 41.088 4.056 41.481 4.056 c
+41.922 4.056 42.231 3.858 42.408 3.469 c
+42.661 3.858 43.01 4.056 43.451 4.056 c
+44.186 4.056 44.561 3.594 44.583 2.674 c
+44.583 0 l
+43.936 0 l
+43.936 2.616 l
+43.936 2.91 43.881 3.123 43.774 3.262 c
+43.675 3.399 43.503 3.469 43.26 3.469 c
+43.061 3.469 42.9 3.388 42.774 3.233 c
+42.657 3.087 42.587 2.896 42.568 2.66 c
+42.568 0 l
+41.907 0 l
+41.907 2.645 l
+41.907 3.193 41.687 3.469 41.246 3.469 c
+40.912 3.469 40.677 3.307 40.54 2.984 c
+40.54 0 l
+39.894 0 l
+39.894 3.983 l
+h
+46.171 3.983 m
+46.185 3.615 l
+46.427 3.91 46.747 4.056 47.14 4.056 c
+47.582 4.056 47.89 3.858 48.066 3.469 c
+48.32 3.858 48.669 4.056 49.11 4.056 c
+49.845 4.056 50.219 3.594 50.242 2.674 c
+50.242 0 l
+49.595 0 l
+49.595 2.616 l
+49.595 2.91 49.54 3.123 49.433 3.262 c
+49.334 3.399 49.161 3.469 48.918 3.469 c
+48.721 3.469 48.559 3.388 48.434 3.233 c
+48.316 3.087 48.247 2.896 48.228 2.66 c
+48.228 0 l
+47.567 0 l
+47.567 2.645 l
+47.567 3.193 47.346 3.469 46.905 3.469 c
+46.57 3.469 46.335 3.307 46.2 2.984 c
+46.2 0 l
+45.552 0 l
+45.552 3.983 l
+h
+51.918 0 -0.647 3.983 re
+51.962 5.026 m
+51.962 4.916 51.933 4.825 51.873 4.748 c
+51.815 4.677 51.719 4.644 51.594 4.644 c
+51.476 4.644 51.381 4.677 51.314 4.748 c
+51.256 4.825 51.227 4.916 51.227 5.026 c
+51.227 5.144 51.256 5.236 51.314 5.306 c
+51.381 5.383 51.476 5.423 51.594 5.423 c
+51.719 5.423 51.815 5.383 51.873 5.306 c
+51.933 5.225 51.962 5.134 51.962 5.026 c
+53.784 4.939 m
+53.784 3.983 l
+54.387 3.983 l
+54.387 3.454 l
+53.784 3.454 l
+53.784 0.985 l
+53.784 0.827 53.807 0.709 53.857 0.632 c
+53.917 0.551 54.005 0.515 54.123 0.515 c
+54.21 0.515 54.298 0.529 54.387 0.558 c
+54.387 0 l
+54.24 -0.048 54.086 -0.073 53.932 -0.073 c
+53.674 -0.073 53.479 0.018 53.344 0.205 c
+53.203 0.389 53.138 0.65 53.138 0.985 c
+53.138 3.454 l
+52.535 3.454 l
+52.535 3.983 l
+53.138 3.983 l
+53.138 4.939 l
+h
+55.195 0.353 m
+55.195 0.47 55.228 0.565 55.299 0.646 c
+55.364 0.723 55.467 0.764 55.607 0.764 c
+55.754 0.764 55.86 0.723 55.931 0.646 c
+56.008 0.565 56.048 0.47 56.048 0.353 c
+56.048 0.242 56.008 0.151 55.931 0.073 c
+55.86 -0.004 55.754 -0.044 55.607 -0.044 c
+55.467 -0.044 55.364 -0.004 55.299 0.073 c
+55.228 0.151 55.195 0.242 55.195 0.353 c
+f
+Q
+0.113 0.082 0.09 0 k
+287.665 373.53 234.667 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 366.6908 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.882 c
+-0.496 -0.993 -0.658 -1.08 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.771 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.279 -3.219 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.985 c
+-3.322 2.18 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.003 -2.469 3.043 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.182 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.455 c
+-2.26 2.425 -2.319 2.385 -2.366 2.338 c
+-2.406 2.297 -2.436 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.44 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.014 c
+6.402 -2.66 m
+6.184 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.147 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.596 4.935 -0.411 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.632 5.137 1.779 c
+5.244 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.151 2.22 c
+8.004 2.22 l
+7.993 2.139 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.871 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.279 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.279 5.835 1.162 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.597 1.602 m
+13.053 1.602 l
+13.053 2.22 l
+13.641 2.22 l
+13.92 3.117 l
+14.494 3.117 l
+14.494 2.22 l
+15.728 2.22 l
+15.728 1.602 l
+14.494 1.602 l
+14.494 -0.103 l
+14.494 -0.324 l
+14.501 -0.393 14.523 -0.455 14.552 -0.515 c
+14.589 -0.565 14.645 -0.61 14.714 -0.646 c
+14.791 -0.676 14.905 -0.691 15.052 -0.691 c
+15.188 -0.691 15.324 -0.687 15.464 -0.676 c
+15.599 -0.658 15.732 -0.632 15.861 -0.602 c
+15.861 -1.205 l
+15.78 -1.216 15.703 -1.23 15.626 -1.249 c
+15.545 -1.261 15.468 -1.267 15.391 -1.278 c
+15.31 -1.286 15.221 -1.294 15.125 -1.294 c
+15.038 -1.301 14.938 -1.308 14.832 -1.308 c
+14.645 -1.308 14.483 -1.294 14.346 -1.264 c
+14.218 -1.228 14.104 -1.183 14.009 -1.132 c
+13.92 -1.084 13.847 -1.025 13.788 -0.955 c
+13.729 -0.878 13.685 -0.801 13.656 -0.72 c
+13.627 -0.632 13.604 -0.544 13.597 -0.455 c
+13.586 -0.36 13.582 -0.264 13.582 -0.176 c
+h
+21.722 1.602 m
+21.178 1.602 l
+21.178 2.22 l
+21.766 2.22 l
+22.045 3.117 l
+22.618 3.117 l
+22.618 2.22 l
+23.853 2.22 l
+23.853 1.602 l
+22.618 1.602 l
+22.618 -0.103 l
+22.618 -0.324 l
+22.626 -0.393 22.647 -0.455 22.677 -0.515 c
+22.714 -0.565 22.769 -0.61 22.839 -0.646 c
+22.916 -0.676 23.03 -0.691 23.177 -0.691 c
+23.313 -0.691 23.449 -0.687 23.588 -0.676 c
+23.725 -0.658 23.857 -0.632 23.985 -0.602 c
+23.985 -1.205 l
+23.904 -1.216 23.827 -1.23 23.75 -1.249 c
+23.669 -1.261 23.592 -1.267 23.515 -1.278 c
+23.434 -1.286 23.346 -1.294 23.25 -1.294 c
+23.162 -1.301 23.063 -1.308 22.957 -1.308 c
+22.769 -1.308 22.608 -1.294 22.471 -1.264 c
+22.343 -1.228 22.229 -1.183 22.134 -1.132 c
+22.045 -1.084 21.972 -1.025 21.913 -0.955 c
+21.854 -0.878 21.81 -0.801 21.781 -0.72 c
+21.751 -0.632 21.729 -0.544 21.722 -0.455 c
+21.71 -0.36 21.707 -0.264 21.707 -0.176 c
+h
+26.136 -1.323 m
+25.966 -1.323 25.816 -1.301 25.679 -1.264 c
+25.551 -1.216 25.437 -1.147 25.342 -1.058 c
+25.253 -0.97 25.184 -0.864 25.136 -0.735 c
+25.084 -0.599 25.062 -0.448 25.062 -0.279 c
+25.062 -0.073 25.095 0.096 25.165 0.235 c
+25.232 0.382 25.327 0.493 25.444 0.574 c
+25.569 0.661 25.712 0.724 25.87 0.765 c
+26.036 0.801 26.213 0.827 26.4 0.838 c
+27.12 0.852 l
+27.12 1.029 l
+27.12 1.147 27.109 1.249 27.09 1.338 c
+27.069 1.426 27.036 1.492 26.988 1.544 c
+26.947 1.602 26.9 1.639 26.841 1.661 c
+26.782 1.679 26.716 1.69 26.649 1.69 c
+26.58 1.69 26.518 1.679 26.458 1.661 c
+26.408 1.65 26.36 1.625 26.312 1.588 c
+26.271 1.558 26.238 1.507 26.209 1.44 c
+26.186 1.382 26.172 1.301 26.165 1.205 c
+25.224 1.249 l
+25.253 1.397 25.297 1.532 25.356 1.661 c
+25.423 1.786 25.518 1.897 25.635 1.985 c
+25.753 2.08 25.893 2.153 26.061 2.205 c
+26.238 2.253 26.444 2.278 26.679 2.278 c
+27.12 2.278 27.451 2.168 27.678 1.955 c
+27.914 1.75 28.031 1.44 28.031 1.029 c
+28.031 -0.235 l
+28.031 -0.455 l
+28.039 -0.515 28.054 -0.569 28.075 -0.617 c
+28.094 -0.658 28.123 -0.691 28.164 -0.72 c
+28.201 -0.742 28.252 -0.75 28.311 -0.75 c
+28.376 -0.75 28.447 -0.746 28.517 -0.735 c
+28.517 -1.22 l
+28.457 -1.23 28.403 -1.242 28.355 -1.249 c
+28.314 -1.261 28.274 -1.267 28.237 -1.278 c
+28.197 -1.286 28.153 -1.294 28.105 -1.294 c
+28.054 -1.301 27.995 -1.308 27.929 -1.308 c
+27.701 -1.308 27.535 -1.257 27.429 -1.147 c
+27.318 -1.029 27.256 -0.864 27.237 -0.646 c
+27.223 -0.646 l
+27.154 -0.757 27.083 -0.852 27.017 -0.941 c
+26.947 -1.022 26.87 -1.087 26.782 -1.147 c
+26.693 -1.205 26.595 -1.249 26.488 -1.278 c
+26.389 -1.308 26.271 -1.323 26.136 -1.323 c
+27.12 0.353 m
+26.693 0.339 l
+26.595 0.339 26.503 0.331 26.414 0.324 c
+26.333 0.312 26.267 0.287 26.209 0.25 c
+26.15 0.21 26.098 0.15 26.061 0.073 c
+26.021 0.004 26.003 -0.088 26.003 -0.206 c
+26.003 -0.374 26.036 -0.496 26.106 -0.573 c
+26.172 -0.654 26.271 -0.691 26.4 -0.691 c
+26.506 -0.691 26.606 -0.669 26.693 -0.617 c
+26.789 -0.569 26.87 -0.507 26.929 -0.426 c
+26.995 -0.349 27.046 -0.261 27.076 -0.162 c
+27.106 -0.055 27.12 0.059 27.12 0.177 c
+h
+30.769 -2.66 m
+30.552 -2.66 30.361 -2.635 30.196 -2.587 c
+30.027 -2.547 29.887 -2.484 29.77 -2.396 c
+29.652 -2.315 29.552 -2.219 29.475 -2.102 c
+29.406 -1.984 29.358 -1.855 29.328 -1.72 c
+30.225 -1.617 l
+30.262 -1.753 30.331 -1.859 30.431 -1.94 c
+30.527 -2.028 30.651 -2.072 30.799 -2.072 c
+30.886 -2.072 30.967 -2.057 31.048 -2.028 c
+31.125 -1.999 31.195 -1.944 31.254 -1.866 c
+31.313 -1.797 31.357 -1.705 31.387 -1.587 c
+31.424 -1.469 31.445 -1.323 31.445 -1.147 c
+31.445 -0.955 l
+31.445 -0.889 31.449 -0.831 31.46 -0.779 c
+31.46 -0.588 l
+31.445 -0.588 l
+31.346 -0.816 31.202 -0.977 31.019 -1.072 c
+30.832 -1.172 30.626 -1.22 30.402 -1.22 c
+30.196 -1.22 30.012 -1.183 29.858 -1.103 c
+29.71 -1.014 29.582 -0.897 29.475 -0.75 c
+29.376 -0.596 29.303 -0.411 29.255 -0.206 c
+29.203 0.008 29.182 0.243 29.182 0.5 c
+29.182 0.771 29.203 1.018 29.255 1.235 c
+29.313 1.448 29.394 1.632 29.505 1.779 c
+29.612 1.933 29.743 2.051 29.901 2.132 c
+30.057 2.22 30.244 2.263 30.46 2.263 c
+30.556 2.263 30.655 2.253 30.755 2.234 c
+30.85 2.213 30.938 2.18 31.019 2.132 c
+31.107 2.08 31.185 2.018 31.254 1.941 c
+31.331 1.86 31.393 1.768 31.445 1.661 c
+31.46 1.661 l
+31.46 1.808 l
+31.468 1.867 31.474 1.918 31.474 1.97 c
+31.482 2.028 31.489 2.076 31.489 2.117 c
+31.497 2.165 31.507 2.198 31.519 2.22 c
+32.371 2.22 l
+32.361 2.139 32.349 2.028 32.342 1.881 c
+32.342 1.411 l
+32.342 -1.161 l
+32.342 -1.415 32.305 -1.635 32.239 -1.822 c
+32.17 -2.007 32.066 -2.161 31.931 -2.279 c
+31.79 -2.404 31.625 -2.499 31.43 -2.558 c
+31.233 -2.624 31.011 -2.66 30.769 -2.66 c
+31.46 0.53 m
+31.46 0.742 31.434 0.919 31.387 1.058 c
+31.346 1.205 31.291 1.323 31.225 1.411 c
+31.166 1.5 31.096 1.558 31.019 1.588 c
+30.938 1.625 30.861 1.646 30.784 1.646 c
+30.684 1.646 30.593 1.621 30.504 1.573 c
+30.424 1.532 30.358 1.463 30.298 1.367 c
+30.248 1.279 30.203 1.162 30.167 1.014 c
+30.137 0.875 30.122 0.706 30.122 0.5 c
+30.122 0.125 30.181 -0.154 30.298 -0.338 c
+30.416 -0.515 30.578 -0.602 30.784 -0.602 c
+30.85 -0.602 30.923 -0.588 31.004 -0.559 c
+31.092 -0.522 31.166 -0.463 31.225 -0.382 c
+31.291 -0.294 31.346 -0.176 31.387 -0.029 c
+31.434 0.118 31.46 0.301 31.46 0.53 c
+37.953 0.838 1.866 -0.794 re
+37.953 0.044 m
+43.601 -1.264 m
+43.59 -1.246 43.579 -1.216 43.572 -1.176 c
+43.572 -1.128 43.565 -1.08 43.557 -1.029 c
+43.557 -0.97 43.55 -0.912 43.542 -0.852 c
+43.542 -0.691 l
+43.425 -0.926 43.282 -1.095 43.116 -1.19 c
+42.948 -1.278 42.749 -1.323 42.514 -1.323 c
+42.315 -1.323 42.139 -1.278 41.984 -1.19 c
+41.826 -1.103 41.695 -0.981 41.587 -0.823 c
+41.488 -0.658 41.411 -0.467 41.352 -0.249 c
+41.301 -0.037 41.279 0.206 41.279 0.47 c
+41.279 0.735 41.301 0.974 41.352 1.191 c
+41.411 1.415 41.488 1.606 41.587 1.764 c
+41.695 1.918 41.826 2.043 41.984 2.132 c
+42.15 2.227 42.341 2.278 42.558 2.278 c
+42.653 2.278 42.749 2.263 42.837 2.234 c
+42.933 2.213 43.028 2.18 43.116 2.132 c
+43.204 2.08 43.282 2.018 43.351 1.941 c
+43.428 1.86 43.491 1.768 43.542 1.661 c
+43.542 1.75 l
+43.542 1.897 l
+43.542 2.058 l
+43.542 2.234 l
+43.542 3.514 l
+44.44 3.514 l
+44.44 -0.5 l
+44.44 -0.676 44.442 -0.834 44.454 -0.97 c
+44.461 -1.099 44.469 -1.198 44.469 -1.264 c
+h
+43.557 0.485 m
+43.557 0.721 43.532 0.912 43.484 1.058 c
+43.443 1.213 43.388 1.338 43.322 1.426 c
+43.264 1.515 43.193 1.573 43.116 1.602 c
+43.035 1.639 42.958 1.661 42.881 1.661 c
+42.782 1.661 42.69 1.635 42.601 1.588 c
+42.521 1.547 42.455 1.477 42.396 1.382 c
+42.345 1.282 42.3 1.162 42.264 1.014 c
+42.234 0.867 42.219 0.684 42.219 0.47 c
+42.219 0.077 42.271 -0.216 42.381 -0.411 c
+42.499 -0.61 42.661 -0.706 42.867 -0.706 c
+42.944 -0.706 43.021 -0.687 43.102 -0.646 c
+43.179 -0.61 43.252 -0.544 43.322 -0.455 c
+43.388 -0.367 43.443 -0.246 43.484 -0.088 c
+43.532 0.066 43.557 0.258 43.557 0.485 c
+50.297 -2.631 m
+50.297 3.514 l
+52.222 3.514 l
+52.222 2.896 l
+51.149 2.896 l
+51.149 -2.013 l
+52.222 -2.013 l
+52.222 -2.631 l
+h
+55.798 -1.264 m
+55.798 0.721 l
+55.798 1.022 55.754 1.242 55.665 1.382 c
+55.585 1.529 55.449 1.602 55.254 1.602 c
+55.143 1.602 55.041 1.577 54.946 1.529 c
+54.857 1.477 54.776 1.411 54.711 1.323 c
+54.651 1.235 54.6 1.124 54.563 1 c
+54.534 0.882 54.519 0.75 54.519 0.603 c
+54.519 -1.264 l
+53.608 -1.264 l
+53.608 1.44 l
+53.608 1.661 l
+53.608 1.75 53.6 1.827 53.593 1.897 c
+53.593 2.087 l
+53.593 2.22 l
+54.445 2.22 l
+54.453 2.19 54.46 2.146 54.46 2.087 c
+54.46 1.897 l
+54.468 1.827 54.475 1.756 54.475 1.69 c
+54.482 1.621 54.49 1.565 54.49 1.529 c
+54.505 1.529 l
+54.622 1.793 54.773 1.985 54.96 2.103 c
+55.143 2.22 55.364 2.278 55.621 2.278 c
+55.806 2.278 55.966 2.249 56.107 2.19 c
+56.242 2.132 56.357 2.043 56.444 1.926 c
+56.533 1.808 56.595 1.665 56.635 1.5 c
+56.683 1.341 56.71 1.154 56.71 0.941 c
+56.71 -1.264 l
+h
+58.628 -1.323 m
+58.458 -1.323 58.308 -1.301 58.172 -1.264 c
+58.044 -1.216 57.929 -1.147 57.834 -1.058 c
+57.745 -0.97 57.676 -0.864 57.628 -0.735 c
+57.576 -0.599 57.554 -0.448 57.554 -0.279 c
+57.554 -0.073 57.587 0.096 57.657 0.235 c
+57.724 0.382 57.819 0.493 57.936 0.574 c
+58.061 0.661 58.204 0.724 58.363 0.765 c
+58.528 0.801 58.705 0.827 58.892 0.838 c
+59.612 0.852 l
+59.612 1.029 l
+59.612 1.147 59.601 1.249 59.583 1.338 c
+59.561 1.426 59.528 1.492 59.48 1.544 c
+59.44 1.602 59.392 1.639 59.333 1.661 c
+59.274 1.679 59.208 1.69 59.141 1.69 c
+59.072 1.69 59.01 1.679 58.951 1.661 c
+58.9 1.65 58.852 1.625 58.804 1.588 c
+58.763 1.558 58.73 1.507 58.701 1.44 c
+58.679 1.382 58.664 1.301 58.657 1.205 c
+57.716 1.249 l
+57.745 1.397 57.79 1.532 57.848 1.661 c
+57.915 1.786 58.01 1.897 58.127 1.985 c
+58.245 2.08 58.385 2.153 58.554 2.205 c
+58.73 2.253 58.936 2.278 59.172 2.278 c
+59.612 2.278 59.943 2.168 60.171 1.955 c
+60.406 1.75 60.523 1.44 60.523 1.029 c
+60.523 -0.235 l
+60.523 -0.455 l
+60.531 -0.515 60.546 -0.569 60.568 -0.617 c
+60.586 -0.658 60.616 -0.691 60.656 -0.72 c
+60.693 -0.742 60.744 -0.75 60.803 -0.75 c
+60.869 -0.75 60.939 -0.746 61.009 -0.735 c
+61.009 -1.22 l
+60.95 -1.23 60.895 -1.242 60.847 -1.249 c
+60.807 -1.261 60.766 -1.267 60.729 -1.278 c
+60.689 -1.286 60.645 -1.294 60.597 -1.294 c
+60.546 -1.301 60.487 -1.308 60.421 -1.308 c
+60.193 -1.308 60.028 -1.257 59.921 -1.147 c
+59.81 -1.029 59.748 -0.864 59.729 -0.646 c
+59.715 -0.646 l
+59.646 -0.757 59.575 -0.852 59.509 -0.941 c
+59.44 -1.022 59.363 -1.087 59.274 -1.147 c
+59.186 -1.205 59.087 -1.249 58.981 -1.278 c
+58.881 -1.308 58.763 -1.323 58.628 -1.323 c
+59.612 0.353 m
+59.186 0.339 l
+59.087 0.339 58.995 0.331 58.906 0.324 c
+58.826 0.312 58.76 0.287 58.701 0.25 c
+58.642 0.21 58.591 0.15 58.554 0.073 c
+58.514 0.004 58.495 -0.088 58.495 -0.206 c
+58.495 -0.374 58.528 -0.496 58.598 -0.573 c
+58.664 -0.654 58.763 -0.691 58.892 -0.691 c
+58.998 -0.691 59.098 -0.669 59.186 -0.617 c
+59.282 -0.569 59.363 -0.507 59.421 -0.426 c
+59.488 -0.349 59.538 -0.261 59.569 -0.162 c
+59.598 -0.055 59.612 0.059 59.612 0.177 c
+h
+62.894 -1.264 m
+62.894 0.852 l
+62.894 1.018 62.887 1.154 62.879 1.264 c
+62.868 1.371 62.85 1.455 62.821 1.515 c
+62.798 1.58 62.769 1.632 62.732 1.661 c
+62.703 1.69 62.663 1.706 62.615 1.706 c
+62.555 1.706 62.501 1.675 62.453 1.617 c
+62.412 1.565 62.379 1.492 62.35 1.397 c
+62.32 1.309 62.295 1.195 62.277 1.058 c
+62.266 0.919 62.262 0.769 62.262 0.603 c
+62.262 -1.264 l
+61.512 -1.264 l
+61.512 1.47 l
+61.512 1.706 l
+61.512 1.926 l
+61.512 2.003 61.505 2.065 61.497 2.117 c
+61.497 2.22 l
+62.173 2.22 l
+62.173 2.132 l
+62.173 1.985 l
+62.181 1.926 62.189 1.867 62.189 1.808 c
+62.189 1.646 l
+62.203 1.646 l
+62.221 1.735 62.251 1.812 62.291 1.881 c
+62.328 1.959 62.372 2.028 62.424 2.087 c
+62.482 2.146 62.549 2.19 62.629 2.22 c
+62.707 2.257 62.794 2.278 62.894 2.278 c
+63.078 2.278 63.218 2.223 63.305 2.117 c
+63.401 2.018 63.471 1.86 63.511 1.646 c
+63.526 1.646 l
+63.563 1.742 63.603 1.83 63.644 1.911 c
+63.691 1.988 63.746 2.051 63.805 2.103 c
+63.864 2.161 63.93 2.205 64.011 2.234 c
+64.088 2.263 64.176 2.278 64.275 2.278 c
+64.411 2.278 64.525 2.253 64.614 2.205 c
+64.702 2.153 64.768 2.08 64.82 1.985 c
+64.878 1.885 64.915 1.756 64.937 1.602 c
+64.967 1.455 64.981 1.272 64.981 1.058 c
+64.981 -1.264 l
+64.261 -1.264 l
+64.261 0.852 l
+64.261 1.018 64.253 1.154 64.246 1.264 c
+64.236 1.371 64.217 1.455 64.188 1.515 c
+64.165 1.58 64.136 1.632 64.099 1.661 c
+64.07 1.69 64.03 1.706 63.982 1.706 c
+63.864 1.706 63.768 1.617 63.702 1.44 c
+63.644 1.272 63.614 1.014 63.614 0.661 c
+63.614 -1.264 l
+h
+67.351 -1.323 m
+67.094 -1.323 66.866 -1.286 66.661 -1.22 c
+66.455 -1.143 66.278 -1.029 66.131 -0.882 c
+65.984 -0.727 65.867 -0.536 65.778 -0.309 c
+65.697 -0.085 65.661 0.181 65.661 0.485 c
+65.661 0.816 65.705 1.095 65.793 1.323 c
+65.888 1.558 66.017 1.742 66.175 1.881 c
+66.341 2.018 66.528 2.117 66.734 2.176 c
+66.94 2.242 67.149 2.278 67.366 2.278 c
+67.638 2.278 67.873 2.227 68.072 2.132 c
+68.277 2.043 68.443 1.911 68.571 1.735 c
+68.707 1.565 68.807 1.359 68.865 1.118 c
+68.932 0.882 68.968 0.617 68.968 0.324 c
+68.968 0.309 l
+66.602 0.309 l
+66.602 0.162 66.617 0.023 66.646 -0.103 c
+66.682 -0.231 66.738 -0.345 66.808 -0.441 c
+66.873 -0.529 66.958 -0.599 67.058 -0.646 c
+67.153 -0.698 67.267 -0.72 67.396 -0.72 c
+67.55 -0.72 67.689 -0.687 67.807 -0.617 c
+67.932 -0.551 68.02 -0.448 68.072 -0.309 c
+68.909 -0.382 l
+68.88 -0.482 68.824 -0.588 68.747 -0.706 c
+68.666 -0.816 68.564 -0.918 68.439 -1.014 c
+68.321 -1.103 68.167 -1.176 67.983 -1.234 c
+67.807 -1.294 67.594 -1.323 67.351 -1.323 c
+67.351 1.706 m
+67.263 1.706 67.175 1.69 67.087 1.661 c
+66.999 1.632 66.918 1.58 66.852 1.515 c
+66.782 1.444 66.723 1.357 66.675 1.249 c
+66.634 1.139 66.617 1.014 66.617 0.867 c
+68.086 0.867 l
+68.086 1.004 68.061 1.124 68.013 1.235 c
+67.972 1.341 67.918 1.43 67.851 1.5 c
+67.793 1.565 67.719 1.617 67.631 1.646 c
+67.542 1.683 67.447 1.706 67.351 1.706 c
+70.221 -2.631 m
+70.221 -2.013 l
+71.294 -2.013 l
+71.294 2.896 l
+70.221 2.896 l
+70.221 3.514 l
+72.147 3.514 l
+72.147 -2.631 l
+h
+f
+Q
+q 1 0 0 1 411.2216 352.6973 cm
+0 0 m
+-0.941 0 l
+-0.941 -2.161 l
+-1.617 -2.161 l
+-1.617 3.19 l
+-0.118 3.19 l
+0.411 3.19 0.808 3.05 1.072 2.778 c
+1.344 2.502 1.484 2.105 1.484 1.588 c
+1.484 1.253 1.411 0.963 1.263 0.721 c
+1.117 0.474 0.911 0.287 0.646 0.162 c
+1.675 -2.117 l
+1.675 -2.161 l
+0.955 -2.161 l
+h
+-0.941 0.588 m
+-0.118 0.588 l
+0.165 0.588 0.389 0.676 0.558 0.852 c
+0.723 1.037 0.808 1.282 0.808 1.588 c
+0.808 2.271 0.492 2.616 -0.133 2.616 c
+-0.941 2.616 l
+h
+3.719 -2.234 m
+3.218 -2.234 2.836 -2.088 2.572 -1.793 c
+2.308 -1.5 2.175 -1.066 2.175 -0.484 c
+2.175 -0.014 l
+2.175 0.58 2.3 1.047 2.557 1.382 c
+2.822 1.723 3.182 1.897 3.645 1.897 c
+4.104 1.897 4.446 1.742 4.674 1.44 c
+4.909 1.147 5.03 0.684 5.041 0.059 c
+5.041 -0.367 l
+2.822 -0.367 l
+2.822 -0.455 l
+2.822 -0.889 2.899 -1.201 3.057 -1.396 c
+3.222 -1.583 3.453 -1.675 3.748 -1.675 c
+3.943 -1.675 4.116 -1.643 4.262 -1.573 c
+4.409 -1.496 4.546 -1.378 4.674 -1.22 c
+5.012 -1.631 l
+4.725 -2.036 4.295 -2.234 3.719 -2.234 c
+3.645 1.338 m
+3.37 1.338 3.167 1.242 3.042 1.058 c
+2.913 0.871 2.84 0.58 2.822 0.191 c
+4.394 0.191 l
+4.394 0.279 l
+4.373 0.661 4.307 0.929 4.189 1.087 c
+4.072 1.253 3.887 1.338 3.645 1.338 c
+6.437 1.823 m
+6.453 1.455 l
+6.695 1.75 7.015 1.897 7.408 1.897 c
+7.849 1.897 8.157 1.698 8.334 1.309 c
+8.588 1.698 8.937 1.897 9.377 1.897 c
+10.113 1.897 10.487 1.434 10.509 0.515 c
+10.509 -2.161 l
+9.863 -2.161 l
+9.863 0.456 l
+9.863 0.75 9.807 0.963 9.701 1.103 c
+9.602 1.239 9.429 1.309 9.186 1.309 c
+8.988 1.309 8.826 1.228 8.702 1.073 c
+8.584 0.927 8.514 0.735 8.496 0.5 c
+8.496 -2.161 l
+7.834 -2.161 l
+7.834 0.485 l
+7.834 1.033 7.613 1.309 7.173 1.309 c
+6.838 1.309 6.603 1.147 6.468 0.823 c
+6.468 -2.161 l
+5.82 -2.161 l
+5.82 1.823 l
+h
+11.347 0.015 m
+11.347 0.592 11.484 1.047 11.759 1.382 c
+12.041 1.723 12.413 1.897 12.876 1.897 c
+13.335 1.897 13.703 1.727 13.978 1.397 c
+14.262 1.073 14.408 0.625 14.42 0.059 c
+14.42 -0.367 l
+14.42 -0.937 14.276 -1.392 13.993 -1.735 c
+13.718 -2.069 13.35 -2.234 12.891 -2.234 c
+12.428 -2.234 12.057 -2.072 11.773 -1.749 c
+11.498 -1.419 11.355 -0.977 11.347 -0.426 c
+h
+11.994 -0.367 m
+11.994 -0.771 12.072 -1.087 12.23 -1.323 c
+12.394 -1.558 12.615 -1.675 12.891 -1.675 c
+13.456 -1.675 13.751 -1.264 13.772 -0.441 c
+13.772 0.015 l
+13.772 0.416 13.688 0.735 13.523 0.97 c
+13.365 1.213 13.148 1.338 12.876 1.338 c
+12.612 1.338 12.394 1.213 12.23 0.97 c
+12.072 0.735 11.994 0.416 11.994 0.015 c
+h
+16.33 -1.176 m
+17.08 1.823 l
+17.741 1.823 l
+16.565 -2.161 l
+16.08 -2.161 l
+14.89 1.823 l
+15.551 1.823 l
+h
+19.799 -2.234 m
+19.299 -2.234 18.917 -2.088 18.653 -1.793 c
+18.388 -1.5 18.256 -1.066 18.256 -0.484 c
+18.256 -0.014 l
+18.256 0.58 18.381 1.047 18.638 1.382 c
+18.902 1.723 19.263 1.897 19.725 1.897 c
+20.185 1.897 20.527 1.742 20.755 1.44 c
+20.99 1.147 21.111 0.684 21.122 0.059 c
+21.122 -0.367 l
+18.902 -0.367 l
+18.902 -0.455 l
+18.902 -0.889 18.979 -1.201 19.137 -1.396 c
+19.303 -1.583 19.534 -1.675 19.829 -1.675 c
+20.024 -1.675 20.196 -1.643 20.343 -1.573 c
+20.49 -1.496 20.626 -1.378 20.755 -1.22 c
+21.092 -1.631 l
+20.806 -2.036 20.376 -2.234 19.799 -2.234 c
+19.725 1.338 m
+19.45 1.338 19.248 1.242 19.123 1.058 c
+18.994 0.871 18.921 0.58 18.902 0.191 c
+20.475 0.191 l
+20.475 0.279 l
+20.454 0.661 20.387 0.929 20.269 1.087 c
+20.152 1.253 19.968 1.338 19.725 1.338 c
+25.664 -2.161 m
+25.624 -2.072 25.598 -1.926 25.591 -1.72 c
+25.356 -2.065 25.061 -2.234 24.709 -2.234 c
+24.345 -2.234 24.062 -2.138 23.856 -1.94 c
+23.658 -1.735 23.562 -1.448 23.562 -1.072 c
+23.562 -0.673 23.698 -0.353 23.974 -0.118 c
+24.246 0.125 24.62 0.25 25.09 0.25 c
+25.576 0.25 l
+25.576 0.676 l
+25.576 0.912 25.521 1.077 25.414 1.176 c
+25.304 1.282 25.142 1.338 24.93 1.338 c
+24.731 1.338 24.569 1.279 24.444 1.162 c
+24.327 1.044 24.267 0.896 24.267 0.721 c
+23.621 0.721 l
+23.621 0.915 23.679 1.106 23.797 1.294 c
+23.922 1.477 24.084 1.625 24.282 1.735 c
+24.488 1.841 24.716 1.897 24.973 1.897 c
+25.374 1.897 25.678 1.793 25.884 1.588 c
+26.098 1.382 26.212 1.087 26.223 0.706 c
+26.223 -1.308 l
+26.223 -1.613 26.26 -1.878 26.341 -2.102 c
+26.341 -2.161 l
+h
+24.797 -1.646 m
+24.963 -1.646 25.113 -1.602 25.252 -1.514 c
+25.4 -1.425 25.506 -1.315 25.576 -1.176 c
+25.576 -0.235 l
+25.208 -0.235 l
+24.893 -0.235 24.65 -0.305 24.473 -0.441 c
+24.297 -0.569 24.209 -0.757 24.209 -0.999 c
+24.209 -1.228 24.253 -1.392 24.342 -1.5 c
+24.429 -1.598 24.581 -1.646 24.797 -1.646 c
+29.794 2.778 m
+29.794 1.823 l
+30.397 1.823 l
+30.397 1.294 l
+29.794 1.294 l
+29.794 -1.176 l
+29.794 -1.334 29.817 -1.452 29.868 -1.529 c
+29.927 -1.61 30.015 -1.646 30.133 -1.646 c
+30.221 -1.646 30.309 -1.631 30.397 -1.602 c
+30.397 -2.161 l
+30.25 -2.208 30.096 -2.234 29.942 -2.234 c
+29.684 -2.234 29.489 -2.142 29.354 -1.955 c
+29.214 -1.771 29.148 -1.51 29.148 -1.176 c
+29.148 1.294 l
+28.545 1.294 l
+28.545 1.823 l
+29.148 1.823 l
+29.148 2.778 l
+h
+33.204 -2.161 m
+33.164 -2.072 33.138 -1.926 33.131 -1.72 c
+32.896 -2.065 32.602 -2.234 32.249 -2.234 c
+31.885 -2.234 31.602 -2.138 31.397 -1.94 c
+31.199 -1.735 31.103 -1.448 31.103 -1.072 c
+31.103 -0.673 31.239 -0.353 31.515 -0.118 c
+31.787 0.125 32.161 0.25 32.631 0.25 c
+33.117 0.25 l
+33.117 0.676 l
+33.117 0.912 33.061 1.077 32.955 1.176 c
+32.845 1.282 32.683 1.338 32.47 1.338 c
+32.271 1.338 32.109 1.279 31.985 1.162 c
+31.868 1.044 31.808 0.896 31.808 0.721 c
+31.162 0.721 l
+31.162 0.915 31.22 1.106 31.338 1.294 c
+31.463 1.477 31.625 1.625 31.823 1.735 c
+32.028 1.841 32.257 1.897 32.514 1.897 c
+32.915 1.897 33.219 1.793 33.425 1.588 c
+33.638 1.382 33.753 1.087 33.763 0.706 c
+33.763 -1.308 l
+33.763 -1.613 33.8 -1.878 33.881 -2.102 c
+33.881 -2.161 l
+h
+32.338 -1.646 m
+32.503 -1.646 32.654 -1.602 32.793 -1.514 c
+32.94 -1.425 33.047 -1.315 33.117 -1.176 c
+33.117 -0.235 l
+32.749 -0.235 l
+32.433 -0.235 32.19 -0.305 32.014 -0.441 c
+31.837 -0.569 31.75 -0.757 31.75 -0.999 c
+31.75 -1.228 31.793 -1.392 31.882 -1.5 c
+31.97 -1.598 32.121 -1.646 32.338 -1.646 c
+34.63 0.015 m
+34.63 0.632 34.741 1.095 34.968 1.411 c
+35.193 1.735 35.527 1.897 35.968 1.897 c
+36.369 1.897 36.674 1.72 36.88 1.367 c
+36.924 1.823 l
+37.512 1.823 l
+37.512 -2.205 l
+37.512 -2.693 37.383 -3.072 37.129 -3.337 c
+36.872 -3.601 36.52 -3.734 36.071 -3.734 c
+35.872 -3.734 35.652 -3.682 35.409 -3.586 c
+35.164 -3.487 34.983 -3.366 34.866 -3.219 c
+35.13 -2.778 l
+35.395 -3.042 35.693 -3.175 36.027 -3.175 c
+36.564 -3.175 36.839 -2.881 36.85 -2.293 c
+36.85 -1.764 l
+36.645 -2.08 36.343 -2.234 35.953 -2.234 c
+35.542 -2.234 35.218 -2.084 34.983 -1.778 c
+34.756 -1.466 34.638 -1.014 34.63 -0.426 c
+h
+35.292 -0.367 m
+35.292 -0.808 35.355 -1.139 35.483 -1.352 c
+35.608 -1.558 35.825 -1.66 36.13 -1.66 c
+36.454 -1.66 36.692 -1.496 36.85 -1.161 c
+36.85 0.823 l
+36.681 1.147 36.442 1.309 36.13 1.309 c
+35.836 1.309 35.619 1.205 35.483 1 c
+35.355 0.794 35.292 0.47 35.292 0.029 c
+h
+40.481 -2.161 m
+40.481 1.294 l
+39.951 1.294 l
+39.951 1.823 l
+40.481 1.823 l
+40.481 2.278 l
+40.481 2.679 40.576 2.992 40.774 3.219 c
+40.98 3.443 41.26 3.557 41.613 3.557 c
+41.749 3.557 41.881 3.535 42.01 3.499 c
+41.98 2.955 l
+41.881 2.973 41.782 2.984 41.686 2.984 c
+41.312 2.984 41.127 2.72 41.127 2.19 c
+41.127 1.823 l
+41.804 1.823 l
+41.804 1.294 l
+41.127 1.294 l
+41.127 -2.161 l
+h
+44.215 1.205 m
+44.126 1.224 44.027 1.235 43.92 1.235 c
+43.586 1.235 43.351 1.051 43.215 0.691 c
+43.215 -2.161 l
+42.568 -2.161 l
+42.568 1.823 l
+43.2 1.823 l
+43.215 1.411 l
+43.392 1.735 43.633 1.897 43.949 1.897 c
+44.057 1.897 44.144 1.874 44.215 1.837 c
+h
+44.655 0.015 m
+44.655 0.592 44.791 1.047 45.067 1.382 c
+45.35 1.723 45.721 1.897 46.184 1.897 c
+46.644 1.897 47.011 1.727 47.286 1.397 c
+47.569 1.073 47.716 0.625 47.727 0.059 c
+47.727 -0.367 l
+47.727 -0.937 47.584 -1.392 47.301 -1.735 c
+47.026 -2.069 46.658 -2.234 46.199 -2.234 c
+45.736 -2.234 45.364 -2.072 45.081 -1.749 c
+44.806 -1.419 44.663 -0.977 44.655 -0.426 c
+h
+45.302 -0.367 m
+45.302 -0.771 45.379 -1.087 45.537 -1.323 c
+45.703 -1.558 45.923 -1.675 46.199 -1.675 c
+46.765 -1.675 47.059 -1.264 47.08 -0.441 c
+47.08 0.015 l
+47.08 0.416 46.996 0.735 46.831 0.97 c
+46.673 1.213 46.456 1.338 46.184 1.338 c
+45.919 1.338 45.703 1.213 45.537 0.97 c
+45.379 0.735 45.302 0.416 45.302 0.015 c
+h
+49.183 1.823 m
+49.197 1.455 l
+49.44 1.75 49.759 1.897 50.153 1.897 c
+50.594 1.897 50.902 1.698 51.078 1.309 c
+51.332 1.698 51.681 1.897 52.123 1.897 c
+52.857 1.897 53.233 1.434 53.254 0.515 c
+53.254 -2.161 l
+52.607 -2.161 l
+52.607 0.456 l
+52.607 0.75 52.553 0.963 52.446 1.103 c
+52.346 1.239 52.174 1.309 51.932 1.309 c
+51.733 1.309 51.571 1.228 51.446 1.073 c
+51.329 0.927 51.259 0.735 51.24 0.5 c
+51.24 -2.161 l
+50.579 -2.161 l
+50.579 0.485 l
+50.579 1.033 50.359 1.309 49.918 1.309 c
+49.584 1.309 49.348 1.147 49.212 0.823 c
+49.212 -2.161 l
+48.566 -2.161 l
+48.566 1.823 l
+h
+57.987 -2.161 m
+57.947 -2.072 57.921 -1.926 57.914 -1.72 c
+57.679 -2.065 57.385 -2.234 57.032 -2.234 c
+56.668 -2.234 56.385 -2.138 56.179 -1.94 c
+55.981 -1.735 55.886 -1.448 55.886 -1.072 c
+55.886 -0.673 56.021 -0.353 56.297 -0.118 c
+56.569 0.125 56.944 0.25 57.414 0.25 c
+57.899 0.25 l
+57.899 0.676 l
+57.899 0.912 57.844 1.077 57.738 1.176 c
+57.627 1.282 57.466 1.338 57.252 1.338 c
+57.054 1.338 56.892 1.279 56.767 1.162 c
+56.649 1.044 56.591 0.896 56.591 0.721 c
+55.944 0.721 l
+55.944 0.915 56.003 1.106 56.121 1.294 c
+56.246 1.477 56.408 1.625 56.605 1.735 c
+56.811 1.841 57.039 1.897 57.297 1.897 c
+57.697 1.897 58.002 1.793 58.208 1.588 c
+58.421 1.382 58.535 1.087 58.546 0.706 c
+58.546 -1.308 l
+58.546 -1.613 58.583 -1.878 58.664 -2.102 c
+58.664 -2.161 l
+h
+57.12 -1.646 m
+57.285 -1.646 57.436 -1.602 57.576 -1.514 c
+57.723 -1.425 57.829 -1.315 57.899 -1.176 c
+57.899 -0.235 l
+57.532 -0.235 l
+57.216 -0.235 56.973 -0.305 56.797 -0.441 c
+56.62 -0.569 56.532 -0.757 56.532 -0.999 c
+56.532 -1.228 56.576 -1.392 56.664 -1.5 c
+56.753 -1.598 56.903 -1.646 57.12 -1.646 c
+61.971 -2.161 -0.647 5.644 re
+62.853 0.015 m
+62.853 0.592 62.989 1.047 63.265 1.382 c
+63.547 1.723 63.919 1.897 64.381 1.897 c
+64.84 1.897 65.208 1.727 65.484 1.397 c
+65.767 1.073 65.914 0.625 65.925 0.059 c
+65.925 -0.367 l
+65.925 -0.937 65.781 -1.392 65.499 -1.735 c
+65.223 -2.069 64.855 -2.234 64.396 -2.234 c
+63.934 -2.234 63.562 -2.072 63.279 -1.749 c
+63.003 -1.419 62.86 -0.977 62.853 -0.426 c
+h
+63.5 -0.367 m
+63.5 -0.771 63.577 -1.087 63.735 -1.323 c
+63.9 -1.558 64.121 -1.675 64.396 -1.675 c
+64.962 -1.675 65.256 -1.264 65.278 -0.441 c
+65.278 0.015 l
+65.278 0.416 65.193 0.735 65.029 0.97 c
+64.871 1.213 64.653 1.338 64.381 1.338 c
+64.117 1.338 63.9 1.213 63.735 0.97 c
+63.577 0.735 63.5 0.416 63.5 0.015 c
+h
+68.144 -1.675 m
+68.358 -1.675 68.53 -1.613 68.659 -1.484 c
+68.795 -1.348 68.869 -1.157 68.879 -0.912 c
+69.497 -0.912 l
+69.475 -1.294 69.339 -1.613 69.085 -1.866 c
+68.828 -2.113 68.516 -2.234 68.144 -2.234 c
+67.652 -2.234 67.277 -2.084 67.013 -1.778 c
+66.756 -1.466 66.631 -0.999 66.631 -0.382 c
+66.631 0.059 l
+66.631 0.654 66.756 1.11 67.013 1.426 c
+67.277 1.738 67.652 1.897 68.144 1.897 c
+68.545 1.897 68.865 1.764 69.1 1.5 c
+69.343 1.242 69.475 0.896 69.497 0.456 c
+68.879 0.456 l
+68.857 0.75 68.784 0.97 68.659 1.118 c
+68.541 1.264 68.368 1.338 68.144 1.338 c
+67.851 1.338 67.634 1.239 67.498 1.044 c
+67.358 0.856 67.284 0.547 67.277 0.118 c
+67.277 -0.397 l
+67.277 -0.867 67.344 -1.201 67.483 -1.396 c
+67.63 -1.583 67.851 -1.675 68.144 -1.675 c
+72.289 -2.161 m
+72.249 -2.072 72.223 -1.926 72.216 -1.72 c
+71.981 -2.065 71.687 -2.234 71.334 -2.234 c
+70.97 -2.234 70.687 -2.138 70.481 -1.94 c
+70.284 -1.735 70.188 -1.448 70.188 -1.072 c
+70.188 -0.673 70.323 -0.353 70.599 -0.118 c
+70.872 0.125 71.246 0.25 71.716 0.25 c
+72.202 0.25 l
+72.202 0.676 l
+72.202 0.912 72.146 1.077 72.04 1.176 c
+71.93 1.282 71.768 1.338 71.555 1.338 c
+71.356 1.338 71.194 1.279 71.069 1.162 c
+70.952 1.044 70.893 0.896 70.893 0.721 c
+70.246 0.721 l
+70.246 0.915 70.305 1.106 70.423 1.294 c
+70.548 1.477 70.71 1.625 70.908 1.735 c
+71.113 1.841 71.342 1.897 71.599 1.897 c
+71.999 1.897 72.304 1.793 72.51 1.588 c
+72.723 1.382 72.837 1.087 72.848 0.706 c
+72.848 -1.308 l
+72.848 -1.613 72.885 -1.878 72.966 -2.102 c
+72.966 -2.161 l
+h
+71.422 -1.646 m
+71.587 -1.646 71.738 -1.602 71.878 -1.514 c
+72.025 -1.425 72.131 -1.315 72.202 -1.176 c
+72.202 -0.235 l
+71.834 -0.235 l
+71.518 -0.235 71.275 -0.305 71.099 -0.441 c
+70.922 -0.569 70.834 -0.757 70.834 -0.999 c
+70.834 -1.228 70.878 -1.392 70.967 -1.5 c
+71.055 -1.598 71.206 -1.646 71.422 -1.646 c
+74.554 -2.161 -0.647 5.644 re
+78.934 1.205 m
+78.845 1.224 78.746 1.235 78.639 1.235 c
+78.305 1.235 78.07 1.051 77.934 0.691 c
+77.934 -2.161 l
+77.287 -2.161 l
+77.287 1.823 l
+77.92 1.823 l
+77.934 1.411 l
+78.111 1.735 78.353 1.897 78.669 1.897 c
+78.776 1.897 78.864 1.874 78.934 1.837 c
+h
+80.933 -2.234 m
+80.433 -2.234 80.05 -2.088 79.786 -1.793 c
+79.522 -1.5 79.389 -1.066 79.389 -0.484 c
+79.389 -0.014 l
+79.389 0.58 79.514 1.047 79.771 1.382 c
+80.036 1.723 80.397 1.897 80.859 1.897 c
+81.318 1.897 81.66 1.742 81.888 1.44 c
+82.123 1.147 82.244 0.684 82.255 0.059 c
+82.255 -0.367 l
+80.036 -0.367 l
+80.036 -0.455 l
+80.036 -0.889 80.113 -1.201 80.271 -1.396 c
+80.436 -1.583 80.668 -1.675 80.962 -1.675 c
+81.157 -1.675 81.33 -1.643 81.477 -1.573 c
+81.623 -1.496 81.76 -1.378 81.888 -1.22 c
+82.226 -1.631 l
+81.939 -2.036 81.509 -2.234 80.933 -2.234 c
+80.859 1.338 m
+80.584 1.338 80.382 1.242 80.256 1.058 c
+80.127 0.871 80.054 0.58 80.036 0.191 c
+81.609 0.191 l
+81.609 0.279 l
+81.587 0.661 81.521 0.929 81.403 1.087 c
+81.286 1.253 81.102 1.338 80.859 1.338 c
+85.916 -0.367 m
+85.916 -0.995 85.798 -1.466 85.563 -1.778 c
+85.335 -2.084 85.019 -2.234 84.607 -2.234 c
+84.203 -2.234 83.894 -2.084 83.682 -1.778 c
+83.682 -3.69 l
+83.034 -3.69 l
+83.034 1.823 l
+83.622 1.823 l
+83.667 1.382 l
+83.88 1.723 84.189 1.897 84.592 1.897 c
+85.033 1.897 85.361 1.742 85.577 1.44 c
+85.791 1.135 85.905 0.68 85.916 0.073 c
+h
+85.269 0.015 m
+85.269 0.456 85.199 0.779 85.063 0.985 c
+84.923 1.198 84.703 1.309 84.401 1.309 c
+84.085 1.309 83.847 1.154 83.682 0.852 c
+83.682 -1.22 l
+83.847 -1.525 84.085 -1.675 84.401 -1.675 c
+84.696 -1.675 84.908 -1.573 85.048 -1.367 c
+85.184 -1.153 85.258 -0.823 85.269 -0.382 c
+h
+86.621 0.015 m
+86.621 0.592 86.757 1.047 87.032 1.382 c
+87.316 1.723 87.687 1.897 88.15 1.897 c
+88.609 1.897 88.977 1.727 89.253 1.397 c
+89.535 1.073 89.683 0.625 89.693 0.059 c
+89.693 -0.367 l
+89.693 -0.937 89.55 -1.392 89.267 -1.735 c
+88.991 -2.069 88.624 -2.234 88.164 -2.234 c
+87.701 -2.234 87.331 -2.072 87.048 -1.749 c
+86.772 -1.419 86.629 -0.977 86.621 -0.426 c
+h
+87.268 -0.367 m
+87.268 -0.771 87.345 -1.087 87.503 -1.323 c
+87.668 -1.558 87.889 -1.675 88.164 -1.675 c
+88.731 -1.675 89.024 -1.264 89.047 -0.441 c
+89.047 0.015 l
+89.047 0.416 88.962 0.735 88.796 0.97 c
+88.638 1.213 88.422 1.338 88.15 1.338 c
+87.885 1.338 87.668 1.213 87.503 0.97 c
+87.345 0.735 87.268 0.416 87.268 0.015 c
+h
+92.471 -1.147 m
+92.471 -0.999 92.416 -0.878 92.31 -0.779 c
+92.199 -0.683 91.994 -0.565 91.692 -0.426 c
+91.347 -0.279 91.104 -0.158 90.957 -0.058 c
+90.811 0.048 90.7 0.166 90.634 0.294 c
+90.564 0.419 90.531 0.577 90.531 0.765 c
+90.531 1.087 90.649 1.357 90.884 1.573 c
+91.119 1.786 91.42 1.897 91.795 1.897 c
+92.177 1.897 92.486 1.783 92.721 1.558 c
+92.956 1.33 93.074 1.044 93.074 0.691 c
+92.428 0.691 l
+92.428 0.867 92.368 1.018 92.251 1.147 c
+92.133 1.272 91.979 1.338 91.795 1.338 c
+91.597 1.338 91.446 1.282 91.339 1.176 c
+91.229 1.077 91.177 0.944 91.177 0.779 c
+91.177 0.651 91.215 0.544 91.295 0.456 c
+91.373 0.375 91.564 0.272 91.869 0.147 c
+92.347 -0.04 92.677 -0.228 92.854 -0.411 c
+93.03 -0.588 93.118 -0.816 93.118 -1.087 c
+93.118 -1.44 92.993 -1.72 92.75 -1.926 c
+92.515 -2.131 92.199 -2.234 91.81 -2.234 c
+91.387 -2.234 91.049 -2.117 90.795 -1.881 c
+90.539 -1.639 90.414 -1.334 90.414 -0.97 c
+91.06 -0.97 l
+91.067 -1.198 91.138 -1.374 91.266 -1.5 c
+91.391 -1.617 91.574 -1.675 91.81 -1.675 c
+92.023 -1.675 92.185 -1.628 92.295 -1.529 c
+92.413 -1.433 92.471 -1.305 92.471 -1.147 c
+94.662 -2.161 -0.647 3.984 re
+94.705 2.866 m
+94.705 2.756 94.676 2.664 94.618 2.587 c
+94.558 2.517 94.463 2.484 94.338 2.484 c
+94.221 2.484 94.125 2.517 94.059 2.587 c
+94 2.664 93.97 2.756 93.97 2.866 c
+93.97 2.984 94 3.076 94.059 3.146 c
+94.125 3.223 94.221 3.263 94.338 3.263 c
+94.463 3.263 94.558 3.223 94.618 3.146 c
+94.676 3.065 94.705 2.973 94.705 2.866 c
+96.528 2.778 m
+96.528 1.823 l
+97.131 1.823 l
+97.131 1.294 l
+96.528 1.294 l
+96.528 -1.176 l
+96.528 -1.334 96.55 -1.452 96.602 -1.529 c
+96.661 -1.61 96.748 -1.646 96.866 -1.646 c
+96.954 -1.646 97.043 -1.631 97.131 -1.602 c
+97.131 -2.161 l
+96.984 -2.208 96.829 -2.234 96.675 -2.234 c
+96.418 -2.234 96.224 -2.142 96.087 -1.955 c
+95.948 -1.771 95.881 -1.51 95.881 -1.176 c
+95.881 1.294 l
+95.279 1.294 l
+95.279 1.823 l
+95.881 1.823 l
+95.881 2.778 l
+h
+97.689 0.015 m
+97.689 0.592 97.826 1.047 98.101 1.382 c
+98.384 1.723 98.755 1.897 99.218 1.897 c
+99.678 1.897 100.045 1.727 100.32 1.397 c
+100.604 1.073 100.75 0.625 100.762 0.059 c
+100.762 -0.367 l
+100.762 -0.937 100.619 -1.392 100.336 -1.735 c
+100.06 -2.069 99.692 -2.234 99.233 -2.234 c
+98.77 -2.234 98.399 -2.072 98.115 -1.749 c
+97.84 -1.419 97.697 -0.977 97.689 -0.426 c
+h
+98.336 -0.367 m
+98.336 -0.771 98.414 -1.087 98.572 -1.323 c
+98.737 -1.558 98.957 -1.675 99.233 -1.675 c
+99.799 -1.675 100.093 -1.264 100.114 -0.441 c
+100.114 0.015 l
+100.114 0.416 100.031 0.735 99.865 0.97 c
+99.707 1.213 99.49 1.338 99.218 1.338 c
+98.954 1.338 98.737 1.213 98.572 0.97 c
+98.414 0.735 98.336 0.416 98.336 0.015 c
+h
+103.246 1.205 m
+103.158 1.224 103.058 1.235 102.952 1.235 c
+102.618 1.235 102.383 1.051 102.246 0.691 c
+102.246 -2.161 l
+101.6 -2.161 l
+101.6 1.823 l
+102.231 1.823 l
+102.246 1.411 l
+102.423 1.735 102.665 1.897 102.981 1.897 c
+103.088 1.897 103.176 1.874 103.246 1.837 c
+h
+105.053 -1.072 m
+105.774 1.823 l
+106.464 1.823 l
+105.171 -2.719 l
+105.072 -3.061 104.929 -3.322 104.745 -3.499 c
+104.569 -3.675 104.367 -3.763 104.143 -3.763 c
+104.054 -3.763 103.94 -3.74 103.804 -3.704 c
+103.804 -3.16 l
+103.952 -3.175 l
+104.135 -3.175 104.282 -3.131 104.392 -3.042 c
+104.499 -2.954 104.587 -2.796 104.657 -2.572 c
+104.775 -2.131 l
+103.613 1.823 l
+104.319 1.823 l
+h
+106.744 -1.808 m
+106.744 -1.691 106.777 -1.595 106.847 -1.514 c
+106.913 -1.437 107.016 -1.396 107.156 -1.396 c
+107.303 -1.396 107.409 -1.437 107.479 -1.514 c
+107.557 -1.595 107.597 -1.691 107.597 -1.808 c
+107.597 -1.918 107.557 -2.01 107.479 -2.088 c
+107.409 -2.165 107.303 -2.205 107.156 -2.205 c
+107.016 -2.205 106.913 -2.165 106.847 -2.088 c
+106.777 -2.01 106.744 -1.918 106.744 -1.808 c
+f
+Q
+0.793 0.801 0.129 0.016 k
+287.665 337.903 234.667 -21.457 re
+f
+0 0 0 0 k
+q 1 0 0 1 389.6758 330.7339 cm
+0 0 m
+-2.954 -8.32 l
+-4.88 -8.32 l
+-1.911 -0.47 l
+-5.659 -0.47 l
+-5.659 1.043 l
+0 1.043 l
+h
+1.562 -7.394 m
+1.562 -7.1 1.658 -6.861 1.856 -6.674 c
+2.051 -6.49 2.304 -6.394 2.62 -6.394 c
+2.922 -6.394 3.171 -6.49 3.37 -6.674 c
+3.576 -6.861 3.678 -7.1 3.678 -7.394 c
+3.678 -7.699 3.576 -7.945 3.37 -8.129 c
+3.171 -8.306 2.922 -8.393 2.62 -8.393 c
+2.315 -8.393 2.062 -8.302 1.856 -8.114 c
+1.658 -7.93 1.562 -7.688 1.562 -7.394 c
+11.403 -4.896 m
+10.462 -4.896 l
+10.462 -8.32 l
+8.58 -8.32 l
+8.58 1.043 l
+11.594 1.043 l
+12.542 1.043 13.274 0.797 13.785 0.309 c
+14.302 -0.184 14.564 -0.879 14.564 -1.779 c
+14.564 -3.024 14.111 -3.896 13.211 -4.395 c
+14.843 -8.231 l
+14.843 -8.32 l
+12.814 -8.32 l
+h
+10.462 -3.323 m
+11.535 -3.323 l
+11.917 -3.323 12.2 -3.201 12.388 -2.955 c
+12.572 -2.702 12.667 -2.363 12.667 -1.941 c
+12.667 -1 12.303 -0.53 11.58 -0.53 c
+10.462 -0.53 l
+h
+20.917 -4.263 m
+17.978 -4.263 l
+17.978 -6.747 l
+21.461 -6.747 l
+21.461 -8.32 l
+16.081 -8.32 l
+16.081 1.043 l
+21.446 1.043 l
+21.446 -0.53 l
+17.978 -0.53 l
+17.978 -2.749 l
+20.917 -2.749 l
+h
+25.779 -5.748 m
+27.351 1.043 l
+29.454 1.043 l
+26.763 -8.32 l
+24.794 -8.32 l
+22.104 1.043 l
+24.206 1.043 l
+h
+35.388 -4.263 m
+32.448 -4.263 l
+32.448 -6.747 l
+35.932 -6.747 l
+35.932 -8.32 l
+30.552 -8.32 l
+30.552 1.043 l
+35.917 1.043 l
+35.917 -0.53 l
+32.448 -0.53 l
+32.448 -2.749 l
+35.388 -2.749 l
+h
+40.033 -4.896 m
+39.092 -4.896 l
+39.092 -8.32 l
+37.211 -8.32 l
+37.211 1.043 l
+40.224 1.043 l
+41.172 1.043 41.903 0.797 42.414 0.309 c
+42.932 -0.184 43.193 -0.879 43.193 -1.779 c
+43.193 -3.024 42.742 -3.896 41.841 -4.395 c
+43.473 -8.231 l
+43.473 -8.32 l
+41.444 -8.32 l
+h
+39.092 -3.323 m
+40.166 -3.323 l
+40.548 -3.323 40.831 -3.201 41.018 -2.955 c
+41.202 -2.702 41.297 -2.363 41.297 -1.941 c
+41.297 -1 40.933 -0.53 40.209 -0.53 c
+39.092 -0.53 l
+h
+50.462 -0.53 m
+48.139 -0.53 l
+48.139 -8.32 l
+46.243 -8.32 l
+46.243 -0.53 l
+43.965 -0.53 l
+43.965 1.043 l
+50.462 1.043 l
+h
+53.732 -8.32 -1.896 9.363 re
+61.979 -8.32 m
+60.082 -8.32 l
+57.319 -2.176 l
+57.319 -8.32 l
+55.423 -8.32 l
+55.423 1.043 l
+57.319 1.043 l
+60.082 -5.101 l
+60.082 1.043 l
+61.979 1.043 l
+h
+70.096 -7.262 m
+69.732 -7.655 69.288 -7.953 68.759 -8.158 c
+68.23 -8.353 67.649 -8.453 67.024 -8.453 c
+65.944 -8.453 65.106 -8.121 64.51 -7.453 c
+63.912 -6.787 63.607 -5.818 63.6 -4.543 c
+63.6 -2.852 l
+63.6 -1.559 63.879 -0.566 64.437 0.132 c
+65.003 0.826 65.826 1.176 66.906 1.176 c
+67.924 1.176 68.689 0.918 69.2 0.411 c
+69.718 -0.088 70.015 -0.875 70.096 -1.941 c
+68.259 -1.941 l
+68.207 -1.345 68.086 -0.938 67.891 -0.721 c
+67.693 -0.508 67.384 -0.397 66.966 -0.397 c
+66.455 -0.397 66.083 -0.585 65.848 -0.956 c
+65.62 -1.331 65.503 -1.922 65.495 -2.735 c
+65.495 -4.439 l
+65.495 -5.292 65.62 -5.917 65.878 -6.307 c
+66.131 -6.689 66.547 -6.88 67.127 -6.88 c
+67.498 -6.88 67.803 -6.806 68.038 -6.659 c
+68.2 -6.542 l
+68.2 -4.821 l
+66.877 -4.821 l
+66.877 -3.396 l
+70.096 -3.396 l
+h
+81.143 -5.204 m
+81.091 -6.273 80.79 -7.082 80.231 -7.629 c
+79.68 -8.181 78.908 -8.453 77.909 -8.453 c
+76.84 -8.453 76.02 -8.107 75.454 -7.408 c
+74.896 -6.714 74.617 -5.719 74.617 -4.425 c
+74.617 -2.852 l
+74.617 -1.559 74.903 -0.566 75.484 0.132 c
+76.072 0.826 76.884 1.176 77.923 1.176 c
+78.941 1.176 79.717 0.885 80.246 0.309 c
+80.776 -0.262 81.077 -1.081 81.158 -2.147 c
+79.261 -2.147 l
+79.239 -1.482 79.136 -1.025 78.952 -0.78 c
+78.765 -0.526 78.424 -0.397 77.923 -0.397 c
+77.424 -0.397 77.063 -0.574 76.851 -0.927 c
+76.645 -1.279 76.531 -1.864 76.512 -2.675 c
+76.512 -4.439 l
+76.512 -5.373 76.616 -6.012 76.821 -6.365 c
+77.034 -6.71 77.398 -6.88 77.909 -6.88 c
+78.397 -6.88 78.736 -6.762 78.923 -6.527 c
+79.118 -6.284 79.224 -5.843 79.247 -5.204 c
+h
+89.087 -8.32 m
+87.206 -8.32 l
+87.206 -4.308 l
+84.413 -4.308 l
+84.413 -8.32 l
+82.517 -8.32 l
+82.517 1.043 l
+84.413 1.043 l
+84.413 -2.749 l
+87.206 -2.749 l
+87.206 1.043 l
+89.087 1.043 l
+h
+95.427 -6.409 m
+92.854 -6.409 l
+92.354 -8.32 l
+90.355 -8.32 l
+93.28 1.043 l
+95.001 1.043 l
+97.954 -8.32 l
+95.926 -8.32 l
+h
+93.266 -4.821 m
+95.015 -4.821 l
+94.133 -1.485 l
+h
+105.609 -8.32 m
+103.713 -8.32 l
+100.95 -2.176 l
+100.95 -8.32 l
+99.053 -8.32 l
+99.053 1.043 l
+100.95 1.043 l
+103.713 -5.101 l
+103.713 1.043 l
+105.609 1.043 l
+h
+113.727 -7.262 m
+113.363 -7.655 112.919 -7.953 112.389 -8.158 c
+111.86 -8.353 111.279 -8.453 110.654 -8.453 c
+109.574 -8.453 108.736 -8.121 108.141 -7.453 c
+107.543 -6.787 107.237 -5.818 107.23 -4.543 c
+107.23 -2.852 l
+107.23 -1.559 107.51 -0.566 108.067 0.132 c
+108.634 0.826 109.457 1.176 110.537 1.176 c
+111.555 1.176 112.32 0.918 112.83 0.411 c
+113.349 -0.088 113.646 -0.875 113.727 -1.941 c
+111.89 -1.941 l
+111.838 -1.345 111.717 -0.938 111.522 -0.721 c
+111.323 -0.508 111.015 -0.397 110.596 -0.397 c
+110.085 -0.397 109.714 -0.585 109.479 -0.956 c
+109.251 -1.331 109.133 -1.922 109.126 -2.735 c
+109.126 -4.439 l
+109.126 -5.292 109.251 -5.917 109.508 -6.307 c
+109.762 -6.689 110.177 -6.88 110.758 -6.88 c
+111.129 -6.88 111.433 -6.806 111.669 -6.659 c
+111.83 -6.542 l
+111.83 -4.821 l
+110.508 -4.821 l
+110.508 -3.396 l
+113.727 -3.396 l
+h
+120.135 -4.263 m
+117.195 -4.263 l
+117.195 -6.747 l
+120.68 -6.747 l
+120.68 -8.32 l
+115.3 -8.32 l
+115.3 1.043 l
+120.665 1.043 l
+120.665 -0.53 l
+117.195 -0.53 l
+117.195 -2.749 l
+120.135 -2.749 l
+h
+125.893 -5.865 m
+125.893 -5.484 125.795 -5.197 125.6 -4.998 c
+125.401 -4.803 125.049 -4.601 124.542 -4.395 c
+123.601 -4.036 122.924 -3.616 122.513 -3.146 c
+122.101 -2.668 121.895 -2.099 121.895 -1.441 c
+121.895 -0.659 122.175 -0.026 122.734 0.455 c
+123.292 0.933 124.002 1.176 124.865 1.176 c
+125.442 1.176 125.957 1.051 126.408 0.808 c
+126.857 0.562 127.202 0.22 127.437 -0.221 c
+127.68 -0.662 127.805 -1.162 127.805 -1.721 c
+125.924 -1.721 l
+125.924 -1.279 125.828 -0.948 125.644 -0.721 c
+125.457 -0.497 125.188 -0.383 124.835 -0.383 c
+124.501 -0.383 124.241 -0.482 124.056 -0.676 c
+123.88 -0.864 123.792 -1.125 123.792 -1.455 c
+123.792 -1.713 123.894 -1.948 124.1 -2.161 c
+124.307 -2.367 124.667 -2.584 125.188 -2.808 c
+126.099 -3.132 126.761 -3.535 127.173 -4.013 c
+127.591 -4.495 127.805 -5.108 127.805 -5.85 c
+127.805 -6.666 127.544 -7.302 127.026 -7.761 c
+126.504 -8.225 125.799 -8.453 124.909 -8.453 c
+124.299 -8.453 123.748 -8.327 123.248 -8.085 c
+122.756 -7.832 122.37 -7.475 122.087 -7.012 c
+121.8 -6.542 121.66 -5.994 121.66 -5.366 c
+123.557 -5.366 l
+123.557 -5.906 123.659 -6.299 123.865 -6.542 c
+124.079 -6.787 124.428 -6.909 124.909 -6.909 c
+125.563 -6.909 125.893 -6.564 125.893 -5.865 c
+f
+Q
+0.113 0.082 0.09 0 k
+287.665 307.601 234.667 -12.895 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 300.7657 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.882 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.69 -1.999 0.69 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.278 -3.219 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.119 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.119 -1.128 3.09 -0.97 3.042 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.182 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.319 2.385 -2.366 2.337 c
+-2.406 2.296 -2.436 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.66 m
+6.184 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.485 5.402 -2.396 c
+5.284 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.856 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.86 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.073 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.596 4.935 -0.411 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.631 5.137 1.779 c
+5.244 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.179 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.866 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.151 2.219 c
+8.004 2.219 l
+7.993 2.138 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.871 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.675 re
+10.124 2.837 m
+13.597 1.602 m
+13.053 1.602 l
+13.053 2.219 l
+13.641 2.219 l
+13.92 3.117 l
+14.494 3.117 l
+14.494 2.219 l
+15.728 2.219 l
+15.728 1.602 l
+14.494 1.602 l
+14.494 -0.103 l
+14.494 -0.324 l
+14.501 -0.393 14.523 -0.455 14.552 -0.515 c
+14.589 -0.566 14.645 -0.61 14.714 -0.646 c
+14.791 -0.676 14.905 -0.691 15.052 -0.691 c
+15.188 -0.691 15.324 -0.687 15.464 -0.676 c
+15.599 -0.658 15.732 -0.632 15.861 -0.603 c
+15.861 -1.205 l
+15.78 -1.216 15.703 -1.231 15.626 -1.249 c
+15.545 -1.261 15.468 -1.268 15.391 -1.278 c
+15.31 -1.286 15.221 -1.294 15.125 -1.294 c
+15.038 -1.301 14.938 -1.309 14.832 -1.309 c
+14.645 -1.309 14.483 -1.294 14.346 -1.264 c
+14.218 -1.228 14.104 -1.183 14.009 -1.132 c
+13.92 -1.084 13.847 -1.025 13.788 -0.956 c
+13.729 -0.879 13.685 -0.802 13.656 -0.721 c
+13.627 -0.632 13.604 -0.544 13.597 -0.455 c
+13.586 -0.36 13.582 -0.264 13.582 -0.176 c
+h
+24.133 1.47 m
+24.033 1.477 23.931 1.488 23.823 1.5 c
+23.713 1.517 23.592 1.529 23.456 1.529 c
+23.28 1.529 23.121 1.488 22.986 1.411 c
+22.846 1.341 22.728 1.242 22.633 1.118 c
+22.545 0.989 22.475 0.842 22.427 0.676 c
+22.387 0.507 22.369 0.331 22.369 0.147 c
+22.369 -1.264 l
+21.471 -1.264 l
+21.471 0.985 l
+21.471 1.11 21.461 1.235 21.442 1.353 c
+21.432 1.477 21.417 1.595 21.398 1.706 c
+21.388 1.823 21.373 1.918 21.355 1.999 c
+21.332 2.087 21.314 2.161 21.296 2.219 c
+22.177 2.219 l
+22.185 2.168 22.196 2.117 22.207 2.058 c
+22.225 1.999 22.24 1.933 22.251 1.866 c
+22.269 1.808 22.284 1.742 22.296 1.675 c
+22.302 1.606 22.313 1.544 22.325 1.484 c
+22.339 1.484 l
+22.375 1.602 22.427 1.708 22.486 1.808 c
+22.552 1.903 22.633 1.988 22.722 2.058 c
+22.809 2.124 22.913 2.179 23.03 2.219 c
+23.155 2.256 23.302 2.278 23.471 2.278 c
+23.596 2.278 23.713 2.271 23.823 2.263 c
+23.942 2.253 24.044 2.238 24.133 2.219 c
+h
+26.738 -1.323 m
+26.481 -1.323 26.253 -1.286 26.047 -1.22 c
+25.841 -1.143 25.665 -1.029 25.518 -0.882 c
+25.371 -0.727 25.253 -0.536 25.165 -0.309 c
+25.084 -0.085 25.047 0.18 25.047 0.485 c
+25.047 0.816 25.091 1.095 25.18 1.323 c
+25.275 1.558 25.404 1.742 25.562 1.881 c
+25.727 2.018 25.915 2.117 26.121 2.176 c
+26.327 2.242 26.535 2.278 26.753 2.278 c
+27.025 2.278 27.26 2.227 27.458 2.132 c
+27.664 2.043 27.829 1.911 27.958 1.735 c
+28.094 1.565 28.193 1.359 28.252 1.118 c
+28.318 0.882 28.355 0.617 28.355 0.324 c
+28.355 0.309 l
+25.988 0.309 l
+25.988 0.162 26.003 0.022 26.032 -0.103 c
+26.069 -0.231 26.124 -0.345 26.194 -0.441 c
+26.26 -0.529 26.344 -0.599 26.444 -0.646 c
+26.539 -0.698 26.653 -0.721 26.782 -0.721 c
+26.936 -0.721 27.076 -0.687 27.194 -0.617 c
+27.318 -0.551 27.407 -0.449 27.458 -0.309 c
+28.296 -0.382 l
+28.266 -0.482 28.212 -0.588 28.135 -0.706 c
+28.054 -0.816 27.95 -0.919 27.825 -1.014 c
+27.708 -1.103 27.553 -1.176 27.37 -1.234 c
+27.194 -1.294 26.98 -1.323 26.738 -1.323 c
+26.738 1.706 m
+26.649 1.706 26.562 1.69 26.473 1.661 c
+26.385 1.631 26.304 1.58 26.238 1.514 c
+26.169 1.444 26.109 1.356 26.061 1.249 c
+26.021 1.139 26.003 1.014 26.003 0.867 c
+27.472 0.867 l
+27.472 1.003 27.447 1.124 27.399 1.235 c
+27.359 1.341 27.304 1.43 27.237 1.5 c
+27.179 1.565 27.106 1.617 27.017 1.646 c
+26.929 1.683 26.834 1.706 26.738 1.706 c
+32.342 -0.25 m
+32.342 -0.419 32.301 -0.569 32.224 -0.706 c
+32.154 -0.834 32.052 -0.948 31.916 -1.043 c
+31.787 -1.132 31.625 -1.201 31.43 -1.249 c
+31.243 -1.297 31.027 -1.323 30.784 -1.323 c
+30.556 -1.323 30.358 -1.309 30.181 -1.278 c
+30.005 -1.249 29.847 -1.201 29.71 -1.132 c
+29.571 -1.055 29.461 -0.956 29.373 -0.838 c
+29.284 -0.721 29.215 -0.573 29.167 -0.397 c
+29.976 -0.279 l
+29.994 -0.378 30.023 -0.455 30.063 -0.515 c
+30.111 -0.573 30.17 -0.617 30.24 -0.646 c
+30.306 -0.676 30.387 -0.702 30.475 -0.721 c
+30.564 -0.731 30.666 -0.735 30.784 -0.735 c
+30.879 -0.735 30.975 -0.731 31.063 -0.721 c
+31.152 -0.702 31.229 -0.676 31.298 -0.646 c
+31.364 -0.617 31.416 -0.58 31.445 -0.529 c
+31.482 -0.482 31.504 -0.419 31.504 -0.338 c
+31.504 -0.243 31.474 -0.169 31.416 -0.118 c
+31.364 -0.07 31.298 -0.029 31.21 0 c
+31.122 0.037 31.011 0.066 30.886 0.088 c
+30.769 0.118 30.637 0.147 30.489 0.177 c
+30.35 0.214 30.211 0.254 30.063 0.294 c
+29.924 0.341 29.799 0.405 29.681 0.485 c
+29.571 0.563 29.483 0.661 29.417 0.779 c
+29.347 0.897 29.313 1.047 29.313 1.235 c
+29.313 1.389 29.344 1.532 29.402 1.661 c
+29.468 1.797 29.564 1.911 29.681 1.999 c
+29.806 2.087 29.964 2.153 30.152 2.205 c
+30.335 2.253 30.549 2.278 30.784 2.278 c
+30.967 2.278 31.144 2.256 31.313 2.219 c
+31.478 2.19 31.625 2.135 31.754 2.058 c
+31.879 1.988 31.989 1.889 32.077 1.764 c
+32.166 1.646 32.224 1.503 32.253 1.338 c
+31.46 1.264 l
+31.438 1.341 31.408 1.404 31.372 1.455 c
+31.331 1.514 31.283 1.558 31.225 1.588 c
+31.173 1.625 31.111 1.65 31.034 1.661 c
+30.953 1.668 30.872 1.675 30.784 1.675 c
+30.567 1.675 30.406 1.646 30.298 1.588 c
+30.188 1.536 30.137 1.448 30.137 1.323 c
+30.137 1.242 30.155 1.18 30.196 1.132 c
+30.244 1.08 30.306 1.043 30.387 1.014 c
+30.475 0.985 30.57 0.956 30.681 0.926 c
+30.788 0.904 30.909 0.882 31.048 0.852 c
+31.202 0.823 31.361 0.783 31.519 0.735 c
+31.673 0.684 31.813 0.621 31.931 0.544 c
+32.048 0.463 32.143 0.36 32.224 0.235 c
+32.301 0.106 32.342 -0.056 32.342 -0.25 c
+34.859 -1.323 m
+34.602 -1.323 34.374 -1.286 34.169 -1.22 c
+33.963 -1.143 33.786 -1.029 33.639 -0.882 c
+33.492 -0.727 33.375 -0.536 33.286 -0.309 c
+33.205 -0.085 33.169 0.18 33.169 0.485 c
+33.169 0.816 33.213 1.095 33.301 1.323 c
+33.396 1.558 33.525 1.742 33.683 1.881 c
+33.849 2.018 34.036 2.117 34.242 2.176 c
+34.447 2.242 34.657 2.278 34.874 2.278 c
+35.146 2.278 35.381 2.227 35.58 2.132 c
+35.785 2.043 35.95 1.911 36.079 1.735 c
+36.215 1.565 36.314 1.359 36.373 1.118 c
+36.44 0.882 36.476 0.617 36.476 0.324 c
+36.476 0.309 l
+34.109 0.309 l
+34.109 0.162 34.124 0.022 34.154 -0.103 c
+34.19 -0.231 34.246 -0.345 34.315 -0.441 c
+34.381 -0.529 34.466 -0.599 34.565 -0.646 c
+34.661 -0.698 34.774 -0.721 34.903 -0.721 c
+35.058 -0.721 35.197 -0.687 35.314 -0.617 c
+35.44 -0.551 35.528 -0.449 35.58 -0.309 c
+36.417 -0.382 l
+36.388 -0.482 36.332 -0.588 36.255 -0.706 c
+36.174 -0.816 36.072 -0.919 35.947 -1.014 c
+35.829 -1.103 35.675 -1.176 35.491 -1.234 c
+35.314 -1.294 35.102 -1.323 34.859 -1.323 c
+34.859 1.706 m
+34.771 1.706 34.682 1.69 34.595 1.661 c
+34.506 1.631 34.425 1.58 34.36 1.514 c
+34.29 1.444 34.231 1.356 34.183 1.249 c
+34.142 1.139 34.124 1.014 34.124 0.867 c
+35.594 0.867 l
+35.594 1.003 35.568 1.124 35.52 1.235 c
+35.48 1.341 35.425 1.43 35.359 1.5 c
+35.3 1.565 35.227 1.617 35.138 1.646 c
+35.05 1.683 34.955 1.706 34.859 1.706 c
+37.968 1.602 m
+37.424 1.602 l
+37.424 2.219 l
+38.012 2.219 l
+38.291 3.117 l
+38.865 3.117 l
+38.865 2.219 l
+40.099 2.219 l
+40.099 1.602 l
+38.865 1.602 l
+38.865 -0.103 l
+38.865 -0.324 l
+38.872 -0.393 38.894 -0.455 38.923 -0.515 c
+38.96 -0.566 39.015 -0.61 39.085 -0.646 c
+39.162 -0.676 39.276 -0.691 39.424 -0.691 c
+39.559 -0.691 39.695 -0.687 39.835 -0.676 c
+39.971 -0.658 40.103 -0.632 40.232 -0.603 c
+40.232 -1.205 l
+40.151 -1.216 40.074 -1.231 39.996 -1.249 c
+39.916 -1.261 39.838 -1.268 39.761 -1.278 c
+39.68 -1.286 39.592 -1.294 39.497 -1.294 c
+39.409 -1.301 39.309 -1.309 39.202 -1.309 c
+39.015 -1.309 38.853 -1.294 38.718 -1.264 c
+38.589 -1.228 38.475 -1.183 38.379 -1.132 c
+38.291 -1.084 38.218 -1.025 38.159 -0.956 c
+38.1 -0.879 38.056 -0.802 38.027 -0.721 c
+37.997 -0.632 37.975 -0.544 37.968 -0.455 c
+37.957 -0.36 37.953 -0.264 37.953 -0.176 c
+h
+46.236 -2.631 m
+46.236 3.513 l
+48.162 3.513 l
+48.162 2.896 l
+47.089 2.896 l
+47.089 -2.014 l
+48.162 -2.014 l
+48.162 -2.631 l
+h
+50.135 0.838 1.867 -0.794 re
+50.135 0.044 m
+54.196 0.838 1.866 -0.794 re
+54.196 0.044 m
+58.569 1.514 m
+58.686 1.785 58.837 1.984 59.024 2.102 c
+59.208 2.219 59.428 2.278 59.686 2.278 c
+59.891 2.278 60.061 2.242 60.2 2.176 c
+60.347 2.105 60.458 2.014 60.538 1.897 c
+60.627 1.779 60.685 1.635 60.714 1.47 c
+60.751 1.301 60.774 1.124 60.774 0.941 c
+60.774 -1.264 l
+59.862 -1.264 l
+59.862 0.735 l
+59.862 0.871 59.851 0.992 59.833 1.103 c
+59.822 1.209 59.796 1.297 59.76 1.367 c
+59.719 1.444 59.66 1.503 59.583 1.544 c
+59.513 1.58 59.421 1.602 59.303 1.602 c
+59.193 1.602 59.098 1.577 59.01 1.529 c
+58.921 1.477 58.84 1.411 58.775 1.323 c
+58.715 1.235 58.664 1.124 58.628 1 c
+58.598 0.882 58.584 0.75 58.584 0.603 c
+58.584 -1.264 l
+57.672 -1.264 l
+57.672 3.513 l
+58.584 3.513 l
+58.584 2.205 l
+58.584 2.135 58.576 2.065 58.569 1.999 c
+58.569 1.793 l
+58.569 1.735 58.561 1.679 58.554 1.631 c
+58.554 1.514 l
+h
+62.688 -1.323 m
+62.519 -1.323 62.368 -1.301 62.233 -1.264 c
+62.104 -1.216 61.99 -1.147 61.894 -1.058 c
+61.807 -0.97 61.736 -0.864 61.688 -0.735 c
+61.637 -0.599 61.615 -0.449 61.615 -0.279 c
+61.615 -0.073 61.649 0.096 61.718 0.235 c
+61.784 0.382 61.88 0.492 61.998 0.573 c
+62.122 0.661 62.266 0.724 62.424 0.765 c
+62.589 0.801 62.765 0.827 62.952 0.838 c
+63.673 0.852 l
+63.673 1.029 l
+63.673 1.147 63.662 1.249 63.644 1.338 c
+63.621 1.426 63.588 1.492 63.54 1.544 c
+63.5 1.602 63.453 1.639 63.394 1.661 c
+63.334 1.679 63.268 1.69 63.203 1.69 c
+63.133 1.69 63.07 1.679 63.012 1.661 c
+62.96 1.65 62.912 1.625 62.864 1.588 c
+62.824 1.558 62.791 1.507 62.761 1.44 c
+62.74 1.382 62.725 1.301 62.717 1.205 c
+61.776 1.249 l
+61.807 1.396 61.85 1.532 61.909 1.661 c
+61.975 1.785 62.071 1.897 62.189 1.984 c
+62.306 2.08 62.445 2.153 62.615 2.205 c
+62.791 2.253 62.997 2.278 63.232 2.278 c
+63.673 2.278 64.003 2.168 64.232 1.955 c
+64.467 1.749 64.585 1.44 64.585 1.029 c
+64.585 -0.235 l
+64.585 -0.455 l
+64.591 -0.515 64.606 -0.569 64.629 -0.617 c
+64.647 -0.658 64.676 -0.691 64.716 -0.721 c
+64.753 -0.742 64.805 -0.75 64.864 -0.75 c
+64.93 -0.75 64.999 -0.746 65.069 -0.735 c
+65.069 -1.22 l
+65.011 -1.231 64.955 -1.242 64.907 -1.249 c
+64.867 -1.261 64.826 -1.268 64.79 -1.278 c
+64.749 -1.286 64.706 -1.294 64.658 -1.294 c
+64.606 -1.301 64.548 -1.309 64.481 -1.309 c
+64.253 -1.309 64.088 -1.257 63.982 -1.147 c
+63.871 -1.029 63.808 -0.864 63.791 -0.646 c
+63.776 -0.646 l
+63.706 -0.757 63.636 -0.852 63.57 -0.941 c
+63.5 -1.022 63.423 -1.087 63.334 -1.147 c
+63.247 -1.205 63.147 -1.249 63.041 -1.278 c
+62.942 -1.309 62.824 -1.323 62.688 -1.323 c
+63.673 0.353 m
+63.247 0.338 l
+63.147 0.338 63.056 0.331 62.967 0.324 c
+62.887 0.312 62.821 0.287 62.761 0.25 c
+62.703 0.21 62.651 0.15 62.615 0.073 c
+62.574 0.004 62.555 -0.088 62.555 -0.206 c
+62.555 -0.374 62.589 -0.496 62.659 -0.573 c
+62.725 -0.654 62.824 -0.691 62.952 -0.691 c
+63.06 -0.691 63.158 -0.669 63.247 -0.617 c
+63.342 -0.569 63.423 -0.507 63.482 -0.426 c
+63.548 -0.349 63.6 -0.261 63.629 -0.162 c
+63.658 -0.056 63.673 0.059 63.673 0.177 c
+h
+68.807 1.47 m
+68.707 1.477 68.604 1.488 68.498 1.5 c
+68.388 1.517 68.267 1.529 68.13 1.529 c
+67.954 1.529 67.796 1.488 67.66 1.411 c
+67.521 1.341 67.403 1.242 67.307 1.118 c
+67.219 0.989 67.149 0.842 67.101 0.676 c
+67.061 0.507 67.043 0.331 67.043 0.147 c
+67.043 -1.264 l
+66.146 -1.264 l
+66.146 0.985 l
+66.146 1.11 66.135 1.235 66.117 1.353 c
+66.106 1.477 66.091 1.595 66.073 1.706 c
+66.062 1.823 66.047 1.918 66.029 1.999 c
+66.006 2.087 65.988 2.161 65.969 2.219 c
+66.852 2.219 l
+66.859 2.168 66.87 2.117 66.881 2.058 c
+66.9 1.999 66.914 1.933 66.925 1.866 c
+66.943 1.808 66.958 1.742 66.969 1.675 c
+66.977 1.606 66.987 1.544 66.999 1.484 c
+67.014 1.484 l
+67.05 1.602 67.101 1.708 67.16 1.808 c
+67.226 1.903 67.307 1.988 67.396 2.058 c
+67.484 2.124 67.586 2.179 67.704 2.219 c
+67.829 2.256 67.976 2.278 68.145 2.278 c
+68.27 2.278 68.388 2.271 68.498 2.263 c
+68.616 2.253 68.718 2.238 68.807 2.219 c
+h
+72.03 -1.264 m
+72.018 -1.246 72.007 -1.216 72 -1.176 c
+72 -1.128 71.993 -1.08 71.985 -1.029 c
+71.985 -0.97 71.978 -0.912 71.97 -0.852 c
+71.97 -0.691 l
+71.853 -0.926 71.71 -1.095 71.544 -1.191 c
+71.375 -1.278 71.176 -1.323 70.941 -1.323 c
+70.744 -1.323 70.567 -1.278 70.412 -1.191 c
+70.254 -1.103 70.122 -0.981 70.015 -0.823 c
+69.917 -0.658 69.84 -0.467 69.78 -0.25 c
+69.729 -0.037 69.707 0.206 69.707 0.47 c
+69.707 0.735 69.729 0.974 69.78 1.191 c
+69.84 1.415 69.917 1.606 70.015 1.764 c
+70.122 1.918 70.254 2.043 70.412 2.132 c
+70.578 2.227 70.769 2.278 70.985 2.278 c
+71.081 2.278 71.176 2.263 71.265 2.234 c
+71.361 2.213 71.456 2.179 71.544 2.132 c
+71.633 2.08 71.71 2.018 71.779 1.941 c
+71.857 1.86 71.92 1.768 71.97 1.661 c
+71.97 1.749 l
+71.97 1.897 l
+71.97 2.058 l
+71.97 2.234 l
+71.97 3.513 l
+72.867 3.513 l
+72.867 -0.5 l
+72.867 -0.676 72.871 -0.834 72.882 -0.97 c
+72.889 -1.099 72.897 -1.198 72.897 -1.264 c
+h
+71.985 0.485 m
+71.985 0.721 71.959 0.912 71.912 1.058 c
+71.872 1.213 71.816 1.338 71.75 1.426 c
+71.691 1.514 71.621 1.573 71.544 1.602 c
+71.463 1.639 71.386 1.661 71.309 1.661 c
+71.21 1.661 71.118 1.635 71.03 1.588 c
+70.949 1.548 70.883 1.477 70.824 1.382 c
+70.773 1.282 70.729 1.161 70.692 1.014 c
+70.663 0.867 70.648 0.684 70.648 0.47 c
+70.648 0.077 70.699 -0.216 70.809 -0.411 c
+70.927 -0.61 71.089 -0.706 71.294 -0.706 c
+71.371 -0.706 71.449 -0.687 71.529 -0.646 c
+71.606 -0.61 71.681 -0.544 71.75 -0.455 c
+71.816 -0.368 71.872 -0.246 71.912 -0.088 c
+71.959 0.066 71.985 0.257 71.985 0.485 c
+74.282 -2.631 m
+74.282 -2.014 l
+75.355 -2.014 l
+75.355 2.896 l
+74.282 2.896 l
+74.282 3.513 l
+76.207 3.513 l
+76.207 -2.631 l
+h
+82.789 -2.631 m
+82.789 3.513 l
+84.715 3.513 l
+84.715 2.896 l
+83.641 2.896 l
+83.641 -2.014 l
+84.715 -2.014 l
+84.715 -2.631 l
+h
+86.702 1.602 m
+86.159 1.602 l
+86.159 2.219 l
+86.747 2.219 l
+87.026 3.117 l
+87.599 3.117 l
+87.599 2.219 l
+88.834 2.219 l
+88.834 1.602 l
+87.599 1.602 l
+87.599 -0.103 l
+87.599 -0.324 l
+87.606 -0.393 87.629 -0.455 87.658 -0.515 c
+87.695 -0.566 87.75 -0.61 87.82 -0.646 c
+87.897 -0.676 88.011 -0.691 88.158 -0.691 c
+88.294 -0.691 88.43 -0.687 88.57 -0.676 c
+88.705 -0.658 88.838 -0.632 88.967 -0.603 c
+88.967 -1.205 l
+88.886 -1.216 88.809 -1.231 88.731 -1.249 c
+88.651 -1.261 88.573 -1.268 88.496 -1.278 c
+88.415 -1.286 88.327 -1.294 88.231 -1.294 c
+88.144 -1.301 88.044 -1.309 87.938 -1.309 c
+87.75 -1.309 87.588 -1.294 87.452 -1.264 c
+87.323 -1.228 87.209 -1.183 87.114 -1.132 c
+87.026 -1.084 86.953 -1.025 86.893 -0.956 c
+86.835 -0.879 86.791 -0.802 86.762 -0.721 c
+86.732 -0.632 86.71 -0.544 86.702 -0.455 c
+86.692 -0.36 86.688 -0.264 86.688 -0.176 c
+h
+91.116 -1.323 m
+90.947 -1.323 90.796 -1.301 90.66 -1.264 c
+90.532 -1.216 90.418 -1.147 90.322 -1.058 c
+90.234 -0.97 90.164 -0.864 90.116 -0.735 c
+90.065 -0.599 90.043 -0.449 90.043 -0.279 c
+90.043 -0.073 90.076 0.096 90.145 0.235 c
+90.212 0.382 90.307 0.492 90.425 0.573 c
+90.55 0.661 90.694 0.724 90.851 0.765 c
+91.017 0.801 91.193 0.827 91.381 0.838 c
+92.101 0.852 l
+92.101 1.029 l
+92.101 1.147 92.09 1.249 92.071 1.338 c
+92.049 1.426 92.017 1.492 91.969 1.544 c
+91.928 1.602 91.88 1.639 91.822 1.661 c
+91.763 1.679 91.697 1.69 91.631 1.69 c
+91.56 1.69 91.498 1.679 91.44 1.661 c
+91.388 1.65 91.34 1.625 91.292 1.588 c
+91.252 1.558 91.219 1.507 91.19 1.44 c
+91.167 1.382 91.153 1.301 91.145 1.205 c
+90.205 1.249 l
+90.234 1.396 90.278 1.532 90.337 1.661 c
+90.403 1.785 90.499 1.897 90.616 1.984 c
+90.734 2.08 90.874 2.153 91.043 2.205 c
+91.219 2.253 91.425 2.278 91.66 2.278 c
+92.101 2.278 92.431 2.168 92.659 1.955 c
+92.894 1.749 93.012 1.44 93.012 1.029 c
+93.012 -0.235 l
+93.012 -0.455 l
+93.019 -0.515 93.034 -0.569 93.056 -0.617 c
+93.075 -0.658 93.104 -0.691 93.145 -0.721 c
+93.181 -0.742 93.233 -0.75 93.291 -0.75 c
+93.358 -0.75 93.428 -0.746 93.497 -0.735 c
+93.497 -1.22 l
+93.438 -1.231 93.383 -1.242 93.335 -1.249 c
+93.295 -1.261 93.255 -1.268 93.218 -1.278 c
+93.177 -1.286 93.133 -1.294 93.086 -1.294 c
+93.034 -1.301 92.975 -1.309 92.909 -1.309 c
+92.682 -1.309 92.516 -1.257 92.41 -1.147 c
+92.3 -1.029 92.237 -0.864 92.219 -0.646 c
+92.204 -0.646 l
+92.134 -0.757 92.065 -0.852 91.998 -0.941 c
+91.928 -1.022 91.851 -1.087 91.763 -1.147 c
+91.675 -1.205 91.575 -1.249 91.469 -1.278 c
+91.369 -1.309 91.252 -1.323 91.116 -1.323 c
+92.101 0.353 m
+91.675 0.338 l
+91.575 0.338 91.483 0.331 91.396 0.324 c
+91.315 0.312 91.248 0.287 91.19 0.25 c
+91.13 0.21 91.08 0.15 91.043 0.073 c
+91.002 0.004 90.984 -0.088 90.984 -0.206 c
+90.984 -0.374 91.017 -0.496 91.086 -0.573 c
+91.153 -0.654 91.252 -0.691 91.381 -0.691 c
+91.487 -0.691 91.587 -0.669 91.675 -0.617 c
+91.77 -0.569 91.851 -0.507 91.91 -0.426 c
+91.976 -0.349 92.027 -0.261 92.057 -0.162 c
+92.086 -0.056 92.101 0.059 92.101 0.177 c
+h
+97.235 1.47 m
+97.135 1.477 97.033 1.488 96.926 1.5 c
+96.815 1.517 96.694 1.529 96.558 1.529 c
+96.382 1.529 96.224 1.488 96.088 1.411 c
+95.948 1.341 95.83 1.242 95.735 1.118 c
+95.647 0.989 95.577 0.842 95.529 0.676 c
+95.489 0.507 95.471 0.331 95.471 0.147 c
+95.471 -1.264 l
+94.574 -1.264 l
+94.574 0.985 l
+94.574 1.11 94.563 1.235 94.544 1.353 c
+94.534 1.477 94.519 1.595 94.5 1.706 c
+94.49 1.823 94.475 1.918 94.457 1.999 c
+94.434 2.087 94.416 2.161 94.398 2.219 c
+95.28 2.219 l
+95.287 2.168 95.298 2.117 95.309 2.058 c
+95.327 1.999 95.342 1.933 95.353 1.866 c
+95.371 1.808 95.386 1.742 95.398 1.675 c
+95.404 1.606 95.415 1.544 95.427 1.484 c
+95.441 1.484 l
+95.478 1.602 95.529 1.708 95.589 1.808 c
+95.654 1.903 95.735 1.988 95.824 2.058 c
+95.911 2.124 96.015 2.179 96.132 2.219 c
+96.257 2.256 96.404 2.278 96.573 2.278 c
+96.698 2.278 96.815 2.271 96.926 2.263 c
+97.044 2.253 97.146 2.238 97.235 2.219 c
+h
+99.814 -2.66 m
+99.597 -2.66 99.406 -2.635 99.24 -2.587 c
+99.072 -2.547 98.932 -2.485 98.814 -2.396 c
+98.697 -2.315 98.598 -2.219 98.521 -2.102 c
+98.451 -1.984 98.403 -1.856 98.374 -1.72 c
+99.271 -1.617 l
+99.307 -1.753 99.377 -1.86 99.476 -1.94 c
+99.572 -2.028 99.697 -2.072 99.844 -2.072 c
+99.932 -2.072 100.013 -2.057 100.094 -2.028 c
+100.171 -1.999 100.24 -1.944 100.299 -1.866 c
+100.358 -1.797 100.402 -1.705 100.431 -1.587 c
+100.468 -1.469 100.491 -1.323 100.491 -1.147 c
+100.491 -0.956 l
+100.491 -0.889 100.494 -0.831 100.505 -0.779 c
+100.505 -0.588 l
+100.491 -0.588 l
+100.391 -0.816 100.248 -0.977 100.064 -1.073 c
+99.876 -1.172 99.671 -1.22 99.447 -1.22 c
+99.24 -1.22 99.057 -1.183 98.903 -1.103 c
+98.756 -1.014 98.627 -0.897 98.521 -0.75 c
+98.421 -0.596 98.348 -0.411 98.3 -0.206 c
+98.249 0.008 98.226 0.243 98.226 0.5 c
+98.226 0.771 98.249 1.018 98.3 1.235 c
+98.359 1.448 98.44 1.631 98.55 1.779 c
+98.656 1.933 98.789 2.051 98.947 2.132 c
+99.101 2.219 99.288 2.263 99.506 2.263 c
+99.601 2.263 99.701 2.253 99.799 2.234 c
+99.895 2.213 99.984 2.179 100.064 2.132 c
+100.152 2.08 100.229 2.018 100.299 1.941 c
+100.377 1.86 100.439 1.768 100.491 1.661 c
+100.505 1.661 l
+100.505 1.808 l
+100.512 1.866 100.52 1.918 100.52 1.97 c
+100.527 2.028 100.534 2.076 100.534 2.117 c
+100.542 2.165 100.553 2.198 100.564 2.219 c
+101.416 2.219 l
+101.405 2.138 101.395 2.028 101.387 1.881 c
+101.387 1.411 l
+101.387 -1.161 l
+101.387 -1.415 101.351 -1.635 101.284 -1.822 c
+101.214 -2.007 101.112 -2.161 100.975 -2.278 c
+100.836 -2.404 100.67 -2.499 100.476 -2.558 c
+100.277 -2.624 100.057 -2.66 99.814 -2.66 c
+100.505 0.53 m
+100.505 0.742 100.479 0.919 100.431 1.058 c
+100.391 1.205 100.336 1.323 100.27 1.411 c
+100.211 1.5 100.142 1.558 100.064 1.588 c
+99.984 1.625 99.907 1.646 99.828 1.646 c
+99.73 1.646 99.637 1.621 99.55 1.573 c
+99.469 1.532 99.402 1.463 99.344 1.367 c
+99.292 1.278 99.248 1.161 99.211 1.014 c
+99.182 0.875 99.167 0.706 99.167 0.5 c
+99.167 0.125 99.226 -0.154 99.344 -0.338 c
+99.462 -0.515 99.623 -0.603 99.828 -0.603 c
+99.895 -0.603 99.969 -0.588 100.049 -0.559 c
+100.138 -0.522 100.211 -0.463 100.27 -0.382 c
+100.336 -0.294 100.391 -0.176 100.431 -0.029 c
+100.479 0.118 100.505 0.301 100.505 0.53 c
+103.905 -1.323 m
+103.647 -1.323 103.419 -1.286 103.213 -1.22 c
+103.007 -1.143 102.831 -1.029 102.685 -0.882 c
+102.537 -0.727 102.419 -0.536 102.332 -0.309 c
+102.251 -0.085 102.214 0.18 102.214 0.485 c
+102.214 0.816 102.258 1.095 102.346 1.323 c
+102.442 1.558 102.571 1.742 102.729 1.881 c
+102.893 2.018 103.081 2.117 103.287 2.176 c
+103.493 2.242 103.702 2.278 103.919 2.278 c
+104.191 2.278 104.426 2.227 104.624 2.132 c
+104.83 2.043 104.996 1.911 105.124 1.735 c
+105.26 1.565 105.359 1.359 105.418 1.118 c
+105.484 0.882 105.521 0.617 105.521 0.324 c
+105.521 0.309 l
+103.155 0.309 l
+103.155 0.162 103.169 0.022 103.199 -0.103 c
+103.236 -0.231 103.29 -0.345 103.36 -0.441 c
+103.427 -0.529 103.511 -0.599 103.61 -0.646 c
+103.706 -0.698 103.82 -0.721 103.948 -0.721 c
+104.102 -0.721 104.242 -0.687 104.36 -0.617 c
+104.485 -0.551 104.573 -0.449 104.624 -0.309 c
+105.463 -0.382 l
+105.432 -0.482 105.378 -0.588 105.301 -0.706 c
+105.22 -0.816 105.117 -0.919 104.992 -1.014 c
+104.875 -1.103 104.72 -1.176 104.536 -1.234 c
+104.36 -1.294 104.146 -1.323 103.905 -1.323 c
+103.905 1.706 m
+103.816 1.706 103.728 1.69 103.639 1.661 c
+103.551 1.631 103.471 1.58 103.404 1.514 c
+103.335 1.444 103.276 1.356 103.228 1.249 c
+103.188 1.139 103.169 1.014 103.169 0.867 c
+104.639 0.867 l
+104.639 1.003 104.613 1.124 104.566 1.235 c
+104.526 1.341 104.47 1.43 104.404 1.5 c
+104.345 1.565 104.272 1.617 104.183 1.646 c
+104.096 1.683 104 1.706 103.905 1.706 c
+107.009 1.602 m
+106.465 1.602 l
+106.465 2.219 l
+107.053 2.219 l
+107.333 3.117 l
+107.906 3.117 l
+107.906 2.219 l
+109.141 2.219 l
+109.141 1.602 l
+107.906 1.602 l
+107.906 -0.103 l
+107.906 -0.324 l
+107.913 -0.393 107.936 -0.455 107.965 -0.515 c
+108.002 -0.566 108.057 -0.61 108.127 -0.646 c
+108.204 -0.676 108.318 -0.691 108.464 -0.691 c
+108.601 -0.691 108.736 -0.687 108.876 -0.676 c
+109.012 -0.658 109.145 -0.632 109.273 -0.603 c
+109.273 -1.205 l
+109.193 -1.216 109.115 -1.231 109.038 -1.249 c
+108.957 -1.261 108.88 -1.268 108.803 -1.278 c
+108.722 -1.286 108.634 -1.294 108.538 -1.294 c
+108.45 -1.301 108.351 -1.309 108.244 -1.309 c
+108.057 -1.309 107.895 -1.294 107.759 -1.264 c
+107.63 -1.228 107.516 -1.183 107.421 -1.132 c
+107.333 -1.084 107.259 -1.025 107.2 -0.956 c
+107.142 -0.879 107.098 -0.802 107.068 -0.721 c
+107.039 -0.632 107.017 -0.544 107.009 -0.455 c
+106.999 -0.36 106.995 -0.264 106.995 -0.176 c
+h
+117.542 1.47 m
+117.442 1.477 117.339 1.488 117.232 1.5 c
+117.122 1.517 117.001 1.529 116.865 1.529 c
+116.688 1.529 116.53 1.488 116.395 1.411 c
+116.255 1.341 116.137 1.242 116.042 1.118 c
+115.954 0.989 115.884 0.842 115.836 0.676 c
+115.796 0.507 115.778 0.331 115.778 0.147 c
+115.778 -1.264 l
+114.88 -1.264 l
+114.88 0.985 l
+114.88 1.11 114.87 1.235 114.851 1.353 c
+114.84 1.477 114.826 1.595 114.807 1.706 c
+114.797 1.823 114.781 1.918 114.763 1.999 c
+114.741 2.087 114.723 2.161 114.704 2.219 c
+115.586 2.219 l
+115.593 2.168 115.605 2.117 115.616 2.058 c
+115.634 1.999 115.649 1.933 115.66 1.866 c
+115.678 1.808 115.693 1.742 115.703 1.675 c
+115.711 1.606 115.722 1.544 115.734 1.484 c
+115.748 1.484 l
+115.784 1.602 115.836 1.708 115.895 1.808 c
+115.961 1.903 116.042 1.988 116.13 2.058 c
+116.218 2.124 116.321 2.179 116.439 2.219 c
+116.564 2.256 116.711 2.278 116.879 2.278 c
+117.004 2.278 117.122 2.271 117.232 2.263 c
+117.35 2.253 117.453 2.238 117.542 2.219 c
+h
+120.15 -1.323 m
+119.893 -1.323 119.665 -1.286 119.46 -1.22 c
+119.254 -1.143 119.077 -1.029 118.93 -0.882 c
+118.783 -0.727 118.666 -0.536 118.577 -0.309 c
+118.496 -0.085 118.46 0.18 118.46 0.485 c
+118.46 0.816 118.504 1.095 118.592 1.323 c
+118.687 1.558 118.816 1.742 118.974 1.881 c
+119.14 2.018 119.327 2.117 119.533 2.176 c
+119.739 2.242 119.948 2.278 120.165 2.278 c
+120.437 2.278 120.672 2.227 120.871 2.132 c
+121.076 2.043 121.242 1.911 121.37 1.735 c
+121.506 1.565 121.606 1.359 121.664 1.118 c
+121.731 0.882 121.767 0.617 121.767 0.324 c
+121.767 0.309 l
+119.401 0.309 l
+119.401 0.162 119.416 0.022 119.445 -0.103 c
+119.481 -0.231 119.537 -0.345 119.607 -0.441 c
+119.672 -0.529 119.757 -0.599 119.857 -0.646 c
+119.952 -0.698 120.066 -0.721 120.195 -0.721 c
+120.349 -0.721 120.488 -0.687 120.606 -0.617 c
+120.731 -0.551 120.819 -0.449 120.871 -0.309 c
+121.708 -0.382 l
+121.679 -0.482 121.624 -0.588 121.546 -0.706 c
+121.465 -0.816 121.363 -0.919 121.238 -1.014 c
+121.12 -1.103 120.966 -1.176 120.782 -1.234 c
+120.606 -1.294 120.393 -1.323 120.15 -1.323 c
+120.15 1.706 m
+120.062 1.706 119.974 1.69 119.886 1.661 c
+119.798 1.631 119.717 1.58 119.651 1.514 c
+119.581 1.444 119.522 1.356 119.474 1.249 c
+119.433 1.139 119.416 1.014 119.416 0.867 c
+120.885 0.867 l
+120.885 1.003 120.86 1.124 120.812 1.235 c
+120.771 1.341 120.717 1.43 120.65 1.5 c
+120.591 1.565 120.518 1.617 120.43 1.646 c
+120.341 1.683 120.246 1.706 120.15 1.706 c
+124.299 1.602 m
+124.299 -1.264 l
+123.402 -1.264 l
+123.402 1.602 l
+122.579 1.602 l
+122.579 2.219 l
+123.402 2.219 l
+123.402 2.484 l
+123.402 2.609 123.417 2.741 123.447 2.881 c
+123.483 3.017 123.553 3.135 123.653 3.234 c
+123.759 3.341 123.902 3.429 124.079 3.499 c
+124.255 3.564 124.48 3.601 124.755 3.601 c
+124.968 3.601 125.166 3.59 125.343 3.572 c
+125.519 3.549 125.67 3.532 125.798 3.513 c
+125.798 2.925 l
+125.67 2.944 125.527 2.959 125.372 2.969 c
+125.214 2.977 125.064 2.984 124.916 2.984 c
+124.788 2.984 124.685 2.969 124.608 2.94 c
+124.527 2.911 124.465 2.87 124.417 2.822 c
+124.366 2.77 124.332 2.708 124.314 2.631 c
+124.303 2.562 124.299 2.484 124.299 2.396 c
+124.299 2.219 l
+125.725 2.219 l
+125.725 1.602 l
+h
+128.272 -1.323 m
+128.014 -1.323 127.786 -1.286 127.58 -1.22 c
+127.375 -1.143 127.198 -1.029 127.052 -0.882 c
+126.905 -0.727 126.787 -0.536 126.699 -0.309 c
+126.618 -0.085 126.581 0.18 126.581 0.485 c
+126.581 0.816 126.625 1.095 126.714 1.323 c
+126.809 1.558 126.938 1.742 127.096 1.881 c
+127.261 2.018 127.449 2.117 127.655 2.176 c
+127.86 2.242 128.069 2.278 128.286 2.278 c
+128.559 2.278 128.794 2.227 128.991 2.132 c
+129.197 2.043 129.363 1.911 129.492 1.735 c
+129.627 1.565 129.727 1.359 129.785 1.118 c
+129.852 0.882 129.889 0.617 129.889 0.324 c
+129.889 0.309 l
+127.522 0.309 l
+127.522 0.162 127.537 0.022 127.566 -0.103 c
+127.603 -0.231 127.658 -0.345 127.728 -0.441 c
+127.794 -0.529 127.878 -0.599 127.977 -0.646 c
+128.073 -0.698 128.187 -0.721 128.316 -0.721 c
+128.47 -0.721 128.609 -0.687 128.727 -0.617 c
+128.852 -0.551 128.941 -0.449 128.991 -0.309 c
+129.83 -0.382 l
+129.8 -0.482 129.745 -0.588 129.668 -0.706 c
+129.587 -0.816 129.484 -0.919 129.359 -1.014 c
+129.242 -1.103 129.087 -1.176 128.904 -1.234 c
+128.727 -1.294 128.514 -1.323 128.272 -1.323 c
+128.272 1.706 m
+128.183 1.706 128.095 1.69 128.007 1.661 c
+127.919 1.631 127.838 1.58 127.772 1.514 c
+127.702 1.444 127.643 1.356 127.595 1.249 c
+127.555 1.139 127.537 1.014 127.537 0.867 c
+129.006 0.867 l
+129.006 1.003 128.981 1.124 128.933 1.235 c
+128.893 1.341 128.837 1.43 128.771 1.5 c
+128.713 1.565 128.639 1.617 128.551 1.646 c
+128.463 1.683 128.367 1.706 128.272 1.706 c
+133.787 1.47 m
+133.688 1.477 133.585 1.488 133.479 1.5 c
+133.369 1.517 133.247 1.529 133.111 1.529 c
+132.935 1.529 132.777 1.488 132.641 1.411 c
+132.501 1.341 132.384 1.242 132.288 1.118 c
+132.2 0.989 132.13 0.842 132.083 0.676 c
+132.042 0.507 132.023 0.331 132.023 0.147 c
+132.023 -1.264 l
+131.127 -1.264 l
+131.127 0.985 l
+131.127 1.11 131.116 1.235 131.098 1.353 c
+131.086 1.477 131.071 1.595 131.053 1.706 c
+131.042 1.823 131.028 1.918 131.009 1.999 c
+130.988 2.087 130.969 2.161 130.951 2.219 c
+131.832 2.219 l
+131.84 2.168 131.851 2.117 131.862 2.058 c
+131.88 1.999 131.895 1.933 131.906 1.866 c
+131.925 1.808 131.939 1.742 131.95 1.675 c
+131.958 1.606 131.969 1.544 131.979 1.484 c
+131.994 1.484 l
+132.031 1.602 132.083 1.708 132.141 1.808 c
+132.207 1.903 132.288 1.988 132.376 2.058 c
+132.465 2.124 132.567 2.179 132.685 2.219 c
+132.81 2.256 132.957 2.278 133.126 2.278 c
+133.251 2.278 133.369 2.271 133.479 2.263 c
+133.596 2.253 133.699 2.238 133.787 2.219 c
+h
+136.393 -1.323 m
+136.135 -1.323 135.908 -1.286 135.702 -1.22 c
+135.497 -1.143 135.32 -1.029 135.173 -0.882 c
+135.026 -0.727 134.909 -0.536 134.82 -0.309 c
+134.739 -0.085 134.703 0.18 134.703 0.485 c
+134.703 0.816 134.747 1.095 134.834 1.323 c
+134.93 1.558 135.059 1.742 135.217 1.881 c
+135.382 2.018 135.57 2.117 135.775 2.176 c
+135.981 2.242 136.191 2.278 136.407 2.278 c
+136.679 2.278 136.914 2.227 137.113 2.132 c
+137.319 2.043 137.484 1.911 137.613 1.735 c
+137.749 1.565 137.848 1.359 137.907 1.118 c
+137.973 0.882 138.009 0.617 138.009 0.324 c
+138.009 0.309 l
+135.643 0.309 l
+135.643 0.162 135.657 0.022 135.688 -0.103 c
+135.724 -0.231 135.779 -0.345 135.849 -0.441 c
+135.915 -0.529 136 -0.599 136.099 -0.646 c
+136.195 -0.698 136.308 -0.721 136.437 -0.721 c
+136.592 -0.721 136.731 -0.687 136.848 -0.617 c
+136.974 -0.551 137.062 -0.449 137.113 -0.309 c
+137.951 -0.382 l
+137.922 -0.482 137.866 -0.588 137.789 -0.706 c
+137.708 -0.816 137.606 -0.919 137.481 -1.014 c
+137.363 -1.103 137.209 -1.176 137.025 -1.234 c
+136.848 -1.294 136.635 -1.323 136.393 -1.323 c
+136.393 1.706 m
+136.305 1.706 136.216 1.69 136.128 1.661 c
+136.04 1.631 135.959 1.58 135.893 1.514 c
+135.823 1.444 135.765 1.356 135.717 1.249 c
+135.676 1.139 135.657 1.014 135.657 0.867 c
+137.128 0.867 l
+137.128 1.003 137.102 1.124 137.054 1.235 c
+137.014 1.341 136.958 1.43 136.893 1.5 c
+136.833 1.565 136.76 1.617 136.672 1.646 c
+136.584 1.683 136.488 1.706 136.393 1.706 c
+141.089 -1.264 m
+141.089 0.721 l
+141.089 1.022 141.045 1.242 140.957 1.382 c
+140.876 1.529 140.74 1.602 140.546 1.602 c
+140.435 1.602 140.332 1.577 140.237 1.529 c
+140.149 1.477 140.068 1.411 140.002 1.323 c
+139.943 1.235 139.891 1.124 139.854 1 c
+139.825 0.882 139.81 0.75 139.81 0.603 c
+139.81 -1.264 l
+138.899 -1.264 l
+138.899 1.44 l
+138.899 1.661 l
+138.899 1.749 138.892 1.826 138.884 1.897 c
+138.884 2.087 l
+138.884 2.219 l
+139.737 2.219 l
+139.744 2.19 139.752 2.146 139.752 2.087 c
+139.752 1.897 l
+139.759 1.826 139.767 1.756 139.767 1.69 c
+139.773 1.621 139.781 1.565 139.781 1.529 c
+139.796 1.529 l
+139.913 1.793 140.064 1.984 140.251 2.102 c
+140.435 2.219 140.656 2.278 140.912 2.278 c
+141.097 2.278 141.259 2.249 141.398 2.19 c
+141.534 2.132 141.648 2.043 141.736 1.926 c
+141.824 1.808 141.886 1.665 141.927 1.5 c
+141.975 1.341 142.001 1.154 142.001 0.941 c
+142.001 -1.264 l
+h
+144.517 -1.323 m
+144.231 -1.323 143.989 -1.282 143.783 -1.205 c
+143.577 -1.117 143.404 -0.996 143.268 -0.838 c
+143.129 -0.684 143.025 -0.496 142.959 -0.279 c
+142.89 -0.056 142.857 0.191 142.857 0.455 c
+142.857 0.75 142.89 1.007 142.959 1.235 c
+143.037 1.459 143.143 1.646 143.283 1.793 c
+143.43 1.947 143.607 2.065 143.812 2.146 c
+144.018 2.234 144.253 2.278 144.517 2.278 c
+144.742 2.278 144.943 2.249 145.12 2.19 c
+145.297 2.132 145.448 2.047 145.576 1.941 c
+145.701 1.841 145.804 1.72 145.884 1.573 c
+145.962 1.433 146.017 1.282 146.046 1.118 c
+145.135 1.073 l
+145.105 1.249 145.036 1.389 144.929 1.5 c
+144.83 1.606 144.687 1.661 144.503 1.661 c
+144.257 1.661 144.081 1.558 143.974 1.353 c
+143.864 1.154 143.812 0.867 143.812 0.485 c
+143.812 -0.309 144.047 -0.706 144.517 -0.706 c
+144.683 -0.706 144.827 -0.654 144.943 -0.544 c
+145.062 -0.437 145.135 -0.276 145.165 -0.058 c
+146.076 -0.103 l
+146.046 -0.272 145.991 -0.426 145.914 -0.573 c
+145.845 -0.721 145.741 -0.852 145.606 -0.97 c
+145.477 -1.08 145.319 -1.168 145.135 -1.234 c
+144.959 -1.294 144.753 -1.323 144.517 -1.323 c
+148.578 -1.323 m
+148.321 -1.323 148.093 -1.286 147.887 -1.22 c
+147.682 -1.143 147.505 -1.029 147.358 -0.882 c
+147.212 -0.727 147.094 -0.536 147.006 -0.309 c
+146.925 -0.085 146.888 0.18 146.888 0.485 c
+146.888 0.816 146.932 1.095 147.021 1.323 c
+147.116 1.558 147.245 1.742 147.403 1.881 c
+147.568 2.018 147.755 2.117 147.961 2.176 c
+148.166 2.242 148.376 2.278 148.593 2.278 c
+148.865 2.278 149.1 2.227 149.298 2.132 c
+149.504 2.043 149.67 1.911 149.799 1.735 c
+149.934 1.565 150.034 1.359 150.092 1.118 c
+150.158 0.882 150.196 0.617 150.196 0.324 c
+150.196 0.309 l
+147.829 0.309 l
+147.829 0.162 147.844 0.022 147.873 -0.103 c
+147.91 -0.231 147.964 -0.345 148.035 -0.441 c
+148.101 -0.529 148.185 -0.599 148.284 -0.646 c
+148.38 -0.698 148.494 -0.721 148.623 -0.721 c
+148.777 -0.721 148.916 -0.687 149.034 -0.617 c
+149.159 -0.551 149.247 -0.449 149.298 -0.309 c
+150.136 -0.382 l
+150.107 -0.482 150.052 -0.588 149.975 -0.706 c
+149.894 -0.816 149.791 -0.919 149.666 -1.014 c
+149.548 -1.103 149.394 -1.176 149.211 -1.234 c
+149.034 -1.294 148.821 -1.323 148.578 -1.323 c
+148.578 1.706 m
+148.49 1.706 148.402 1.69 148.314 1.661 c
+148.226 1.631 148.145 1.58 148.079 1.514 c
+148.008 1.444 147.95 1.356 147.902 1.249 c
+147.862 1.139 147.844 1.014 147.844 0.867 c
+149.313 0.867 l
+149.313 1.003 149.288 1.124 149.24 1.235 c
+149.199 1.341 149.144 1.43 149.078 1.5 c
+149.02 1.565 148.945 1.617 148.858 1.646 c
+148.769 1.683 148.674 1.706 148.578 1.706 c
+151.449 -2.631 m
+151.449 -2.014 l
+152.521 -2.014 l
+152.521 2.896 l
+151.449 2.896 l
+151.449 3.513 l
+153.373 3.513 l
+153.373 -2.631 l
+h
+f
+Q
+q 1 0 0 1 296.7449 285.9641 cm
+0 0 m
+0 0.264 -0.073 0.463 -0.22 0.602 c
+-0.36 0.75 -0.617 0.889 -0.999 1.028 c
+-1.374 1.165 -1.661 1.308 -1.866 1.455 c
+-2.065 1.602 -2.212 1.768 -2.308 1.955 c
+-2.407 2.15 -2.454 2.37 -2.454 2.616 c
+-2.454 3.035 -2.315 3.384 -2.028 3.659 c
+-1.745 3.931 -1.378 4.072 -0.926 4.072 c
+-0.613 4.072 -0.334 3.998 -0.088 3.85 c
+0.154 3.711 0.341 3.516 0.47 3.262 c
+0.607 3.017 0.676 2.749 0.676 2.454 c
+0 2.454 l
+0 2.786 -0.081 3.042 -0.235 3.219 c
+-0.393 3.403 -0.625 3.498 -0.926 3.498 c
+-1.191 3.498 -1.404 3.417 -1.558 3.262 c
+-1.705 3.116 -1.779 2.903 -1.779 2.631 c
+-1.779 2.403 -1.702 2.212 -1.544 2.057 c
+-1.378 1.911 -1.124 1.77 -0.779 1.646 c
+-0.261 1.477 0.11 1.267 0.338 1.014 c
+0.573 0.756 0.69 0.426 0.69 0.014 c
+0.69 -0.426 0.548 -0.779 0.264 -1.044 c
+-0.022 -1.301 -0.405 -1.426 -0.882 -1.426 c
+-1.198 -1.426 -1.484 -1.357 -1.749 -1.22 c
+-2.014 -1.085 -2.227 -0.894 -2.381 -0.647 c
+-2.528 -0.405 -2.602 -0.118 -2.602 0.205 c
+-1.926 0.205 l
+-1.926 -0.129 -1.834 -0.389 -1.646 -0.574 c
+-1.463 -0.761 -1.205 -0.853 -0.882 -0.853 c
+-0.588 -0.853 -0.368 -0.779 -0.22 -0.632 c
+-0.073 -0.478 0 -0.265 0 0 c
+4.439 -0.206 m
+5.041 2.631 l
+5.689 2.631 l
+4.704 -1.353 l
+4.189 -1.353 l
+3.41 1.499 l
+2.66 -1.353 l
+2.132 -1.353 l
+1.176 2.631 l
+1.808 2.631 l
+2.425 -0.133 l
+3.16 2.631 l
+3.675 2.631 l
+h
+7.071 -1.353 -0.647 3.984 re
+7.115 3.675 m
+7.115 3.564 7.085 3.472 7.026 3.395 c
+6.967 3.326 6.872 3.293 6.747 3.293 c
+6.629 3.293 6.533 3.326 6.468 3.395 c
+6.409 3.472 6.379 3.564 6.379 3.675 c
+6.379 3.792 6.409 3.884 6.468 3.954 c
+6.533 4.031 6.629 4.072 6.747 4.072 c
+6.872 4.072 6.967 4.031 7.026 3.954 c
+7.085 3.873 7.115 3.781 7.115 3.675 c
+8.937 3.586 m
+8.937 2.631 l
+9.54 2.631 l
+9.54 2.102 l
+8.937 2.102 l
+8.937 -0.368 l
+8.937 -0.526 8.96 -0.643 9.01 -0.721 c
+9.07 -0.802 9.157 -0.838 9.275 -0.838 c
+9.363 -0.838 9.452 -0.823 9.54 -0.794 c
+9.54 -1.353 l
+9.392 -1.401 9.238 -1.426 9.084 -1.426 c
+8.827 -1.426 8.632 -1.334 8.496 -1.147 c
+8.357 -0.963 8.291 -0.702 8.291 -0.368 c
+8.291 2.102 l
+7.688 2.102 l
+7.688 2.631 l
+8.291 2.631 l
+8.291 3.586 l
+h
+11.686 -0.867 m
+11.899 -0.867 12.072 -0.805 12.2 -0.676 c
+12.336 -0.541 12.409 -0.349 12.421 -0.103 c
+13.038 -0.103 l
+13.016 -0.485 12.88 -0.805 12.627 -1.058 c
+12.37 -1.305 12.057 -1.426 11.686 -1.426 c
+11.194 -1.426 10.818 -1.276 10.554 -0.971 c
+10.296 -0.659 10.172 -0.191 10.172 0.426 c
+10.172 0.867 l
+10.172 1.462 10.296 1.918 10.554 2.234 c
+10.818 2.547 11.194 2.705 11.686 2.705 c
+12.087 2.705 12.406 2.572 12.642 2.308 c
+12.883 2.05 13.016 1.705 13.038 1.263 c
+12.421 1.263 l
+12.399 1.558 12.326 1.778 12.2 1.926 c
+12.083 2.072 11.91 2.146 11.686 2.146 c
+11.391 2.146 11.175 2.046 11.039 1.851 c
+10.899 1.664 10.826 1.356 10.818 0.926 c
+10.818 0.411 l
+10.818 -0.059 10.884 -0.393 11.025 -0.588 c
+11.171 -0.776 11.391 -0.867 11.686 -0.867 c
+14.435 2.219 m
+14.688 2.543 15.008 2.705 15.39 2.705 c
+16.095 2.705 16.452 2.234 16.463 1.294 c
+16.463 -1.353 l
+15.817 -1.353 l
+15.817 1.263 l
+15.817 1.576 15.761 1.797 15.655 1.926 c
+15.545 2.05 15.39 2.117 15.184 2.117 c
+15.026 2.117 14.88 2.061 14.743 1.955 c
+14.614 1.845 14.512 1.708 14.435 1.543 c
+14.435 -1.353 l
+13.787 -1.353 l
+13.787 4.292 l
+14.435 4.292 l
+h
+20.52 -0.867 m
+20.733 -0.867 20.906 -0.805 21.034 -0.676 c
+21.17 -0.541 21.244 -0.349 21.255 -0.103 c
+21.872 -0.103 l
+21.851 -0.485 21.714 -0.805 21.461 -1.058 c
+21.203 -1.305 20.891 -1.426 20.52 -1.426 c
+20.027 -1.426 19.653 -1.276 19.388 -0.971 c
+19.131 -0.659 19.006 -0.191 19.006 0.426 c
+19.006 0.867 l
+19.006 1.462 19.131 1.918 19.388 2.234 c
+19.653 2.547 20.027 2.705 20.52 2.705 c
+20.92 2.705 21.24 2.572 21.475 2.308 c
+21.718 2.05 21.851 1.705 21.872 1.263 c
+21.255 1.263 l
+21.232 1.558 21.159 1.778 21.034 1.926 c
+20.916 2.072 20.744 2.146 20.52 2.146 c
+20.226 2.146 20.009 2.046 19.873 1.851 c
+19.734 1.664 19.66 1.356 19.653 0.926 c
+19.653 0.411 l
+19.653 -0.059 19.719 -0.393 19.858 -0.588 c
+20.006 -0.776 20.226 -0.867 20.52 -0.867 c
+24.65 -1 m
+24.434 -1.287 24.121 -1.426 23.709 -1.426 c
+23.346 -1.426 23.071 -1.305 22.886 -1.058 c
+22.71 -0.805 22.614 -0.441 22.607 0.029 c
+22.607 2.631 l
+23.254 2.631 l
+23.254 0.087 l
+23.254 -0.541 23.438 -0.853 23.813 -0.853 c
+24.213 -0.853 24.488 -0.676 24.636 -0.324 c
+24.636 2.631 l
+25.282 2.631 l
+25.282 -1.353 l
+24.665 -1.353 l
+h
+27.914 2.013 m
+27.825 2.032 27.726 2.043 27.619 2.043 c
+27.285 2.043 27.05 1.859 26.914 1.499 c
+26.914 -1.353 l
+26.267 -1.353 l
+26.267 2.631 l
+26.899 2.631 l
+26.914 2.219 l
+27.09 2.543 27.333 2.705 27.649 2.705 c
+27.756 2.705 27.844 2.682 27.914 2.645 c
+h
+30.206 2.013 m
+30.119 2.032 30.019 2.043 29.913 2.043 c
+29.578 2.043 29.343 1.859 29.207 1.499 c
+29.207 -1.353 l
+28.56 -1.353 l
+28.56 2.631 l
+29.192 2.631 l
+29.207 2.219 l
+29.383 2.543 29.626 2.705 29.942 2.705 c
+30.048 2.705 30.137 2.682 30.206 2.645 c
+h
+32.205 -1.426 m
+31.706 -1.426 31.324 -1.279 31.059 -0.985 c
+30.794 -0.691 30.662 -0.258 30.662 0.323 c
+30.662 0.793 l
+30.662 1.389 30.788 1.855 31.044 2.19 c
+31.309 2.532 31.669 2.705 32.132 2.705 c
+32.592 2.705 32.933 2.55 33.161 2.248 c
+33.396 1.955 33.518 1.492 33.529 0.867 c
+33.529 0.44 l
+31.309 0.44 l
+31.309 0.353 l
+31.309 -0.081 31.386 -0.393 31.544 -0.588 c
+31.71 -0.776 31.941 -0.867 32.235 -0.867 c
+32.43 -0.867 32.602 -0.834 32.75 -0.765 c
+32.897 -0.688 33.032 -0.57 33.161 -0.412 c
+33.499 -0.823 l
+33.213 -1.228 32.783 -1.426 32.205 -1.426 c
+32.132 2.146 m
+31.856 2.146 31.655 2.05 31.53 1.866 c
+31.401 1.679 31.328 1.389 31.309 0.999 c
+32.882 0.999 l
+32.882 1.087 l
+32.86 1.469 32.793 1.738 32.676 1.896 c
+32.558 2.061 32.375 2.146 32.132 2.146 c
+34.925 2.631 m
+34.94 2.19 l
+35.193 2.532 35.517 2.705 35.91 2.705 c
+36.615 2.705 36.972 2.234 36.983 1.294 c
+36.983 -1.353 l
+36.336 -1.353 l
+36.336 1.263 l
+36.336 1.576 36.281 1.797 36.174 1.926 c
+36.064 2.05 35.91 2.117 35.704 2.117 c
+35.546 2.117 35.399 2.061 35.263 1.955 c
+35.135 1.845 35.031 1.708 34.954 1.543 c
+34.954 -1.353 l
+34.308 -1.353 l
+34.308 2.631 l
+h
+38.805 3.586 m
+38.805 2.631 l
+39.409 2.631 l
+39.409 2.102 l
+38.805 2.102 l
+38.805 -0.368 l
+38.805 -0.526 38.828 -0.643 38.879 -0.721 c
+38.938 -0.802 39.026 -0.838 39.143 -0.838 c
+39.232 -0.838 39.32 -0.823 39.409 -0.794 c
+39.409 -1.353 l
+39.261 -1.401 39.107 -1.426 38.952 -1.426 c
+38.695 -1.426 38.501 -1.334 38.364 -1.147 c
+38.225 -0.963 38.159 -0.702 38.159 -0.368 c
+38.159 2.102 l
+37.556 2.102 l
+37.556 2.631 l
+38.159 2.631 l
+38.159 3.586 l
+h
+44.774 0.44 m
+44.774 -0.177 44.66 -0.643 44.435 -0.956 c
+44.219 -1.272 43.895 -1.426 43.465 -1.426 c
+43.043 -1.426 42.73 -1.246 42.524 -0.882 c
+42.495 -1.353 l
+41.892 -1.353 l
+41.892 4.292 l
+42.539 4.292 l
+42.539 2.19 l
+42.752 2.532 43.061 2.705 43.465 2.705 c
+43.895 2.705 44.219 2.547 44.435 2.234 c
+44.66 1.928 44.774 1.462 44.774 0.837 c
+h
+44.126 0.823 m
+44.126 1.294 44.057 1.624 43.921 1.822 c
+43.792 2.017 43.583 2.117 43.289 2.117 c
+42.954 2.117 42.705 1.932 42.539 1.573 c
+42.539 -0.309 l
+42.705 -0.673 42.958 -0.853 43.303 -0.853 c
+43.598 -0.853 43.807 -0.75 43.935 -0.544 c
+44.06 -0.339 44.126 -0.023 44.126 0.411 c
+h
+47.257 2.013 m
+47.17 2.032 47.07 2.043 46.964 2.043 c
+46.63 2.043 46.394 1.859 46.258 1.499 c
+46.258 -1.353 l
+45.611 -1.353 l
+45.611 2.631 l
+46.243 2.631 l
+46.258 2.219 l
+46.434 2.543 46.677 2.705 46.993 2.705 c
+47.1 2.705 47.187 2.682 47.257 2.645 c
+h
+49.801 -1.353 m
+49.76 -1.264 49.734 -1.118 49.727 -0.912 c
+49.491 -1.257 49.198 -1.426 48.845 -1.426 c
+48.481 -1.426 48.198 -1.33 47.993 -1.132 c
+47.794 -0.927 47.698 -0.64 47.698 -0.265 c
+47.698 0.135 47.835 0.455 48.11 0.691 c
+48.382 0.933 48.757 1.058 49.227 1.058 c
+49.712 1.058 l
+49.712 1.484 l
+49.712 1.72 49.657 1.885 49.551 1.984 c
+49.441 2.09 49.279 2.146 49.065 2.146 c
+48.867 2.146 48.706 2.087 48.581 1.969 c
+48.463 1.851 48.404 1.705 48.404 1.529 c
+47.758 1.529 l
+47.758 1.723 47.816 1.914 47.933 2.102 c
+48.059 2.285 48.22 2.433 48.419 2.543 c
+48.625 2.649 48.853 2.705 49.109 2.705 c
+49.51 2.705 49.815 2.601 50.021 2.396 c
+50.235 2.19 50.348 1.896 50.359 1.514 c
+50.359 -0.5 l
+50.359 -0.805 50.395 -1.07 50.476 -1.294 c
+50.476 -1.353 l
+h
+48.933 -0.838 m
+49.098 -0.838 49.25 -0.794 49.389 -0.706 c
+49.536 -0.618 49.643 -0.507 49.712 -0.368 c
+49.712 0.573 l
+49.345 0.573 l
+49.029 0.573 48.786 0.503 48.61 0.367 c
+48.433 0.239 48.346 0.051 48.346 -0.191 c
+48.346 -0.42 48.39 -0.584 48.477 -0.691 c
+48.566 -0.79 48.716 -0.838 48.933 -0.838 c
+51.976 2.631 m
+51.991 2.19 l
+52.244 2.532 52.568 2.705 52.961 2.705 c
+53.666 2.705 54.023 2.234 54.034 1.294 c
+54.034 -1.353 l
+53.387 -1.353 l
+53.387 1.263 l
+53.387 1.576 53.331 1.797 53.225 1.926 c
+53.115 2.05 52.961 2.117 52.755 2.117 c
+52.597 2.117 52.45 2.061 52.314 1.955 c
+52.186 1.845 52.082 1.708 52.005 1.543 c
+52.005 -1.353 l
+51.359 -1.353 l
+51.359 2.631 l
+h
+56.386 -0.867 m
+56.599 -0.867 56.772 -0.805 56.9 -0.676 c
+57.036 -0.541 57.109 -0.349 57.121 -0.103 c
+57.738 -0.103 l
+57.716 -0.485 57.58 -0.805 57.327 -1.058 c
+57.069 -1.305 56.757 -1.426 56.386 -1.426 c
+55.893 -1.426 55.519 -1.276 55.253 -0.971 c
+54.997 -0.659 54.871 -0.191 54.871 0.426 c
+54.871 0.867 l
+54.871 1.462 54.997 1.918 55.253 2.234 c
+55.519 2.547 55.893 2.705 56.386 2.705 c
+56.786 2.705 57.106 2.572 57.341 2.308 c
+57.584 2.05 57.716 1.705 57.738 1.263 c
+57.121 1.263 l
+57.098 1.558 57.025 1.778 56.9 1.926 c
+56.782 2.072 56.61 2.146 56.386 2.146 c
+56.092 2.146 55.875 2.046 55.739 1.851 c
+55.6 1.664 55.526 1.356 55.519 0.926 c
+55.519 0.411 l
+55.519 -0.059 55.585 -0.393 55.724 -0.588 c
+55.871 -0.776 56.092 -0.867 56.386 -0.867 c
+59.134 2.219 m
+59.388 2.543 59.708 2.705 60.09 2.705 c
+60.795 2.705 61.152 2.234 61.163 1.294 c
+61.163 -1.353 l
+60.516 -1.353 l
+60.516 1.263 l
+60.516 1.576 60.461 1.797 60.354 1.926 c
+60.244 2.05 60.09 2.117 59.884 2.117 c
+59.726 2.117 59.579 2.061 59.443 1.955 c
+59.315 1.845 59.211 1.708 59.134 1.543 c
+59.134 -1.353 l
+58.488 -1.353 l
+58.488 4.292 l
+59.134 4.292 l
+h
+64.691 3.586 m
+64.691 2.631 l
+65.293 2.631 l
+65.293 2.102 l
+64.691 2.102 l
+64.691 -0.368 l
+64.691 -0.526 64.713 -0.643 64.764 -0.721 c
+64.823 -0.802 64.911 -0.838 65.029 -0.838 c
+65.117 -0.838 65.205 -0.823 65.293 -0.794 c
+65.293 -1.353 l
+65.146 -1.401 64.992 -1.426 64.838 -1.426 c
+64.581 -1.426 64.385 -1.334 64.25 -1.147 c
+64.11 -0.963 64.044 -0.702 64.044 -0.368 c
+64.044 2.102 l
+63.442 2.102 l
+63.442 2.631 l
+64.044 2.631 l
+64.044 3.586 l
+h
+65.852 0.823 m
+65.852 1.4 65.988 1.855 66.264 2.19 c
+66.546 2.532 66.918 2.705 67.38 2.705 c
+67.84 2.705 68.207 2.535 68.483 2.204 c
+68.766 1.881 68.913 1.433 68.924 0.867 c
+68.924 0.44 l
+68.924 -0.129 68.78 -0.584 68.498 -0.927 c
+68.222 -1.261 67.855 -1.426 67.395 -1.426 c
+66.933 -1.426 66.561 -1.264 66.278 -0.941 c
+66.002 -0.611 65.859 -0.169 65.852 0.382 c
+h
+66.499 0.44 m
+66.499 0.037 66.576 -0.279 66.734 -0.515 c
+66.899 -0.75 67.12 -0.867 67.395 -0.867 c
+67.961 -0.867 68.255 -0.456 68.277 0.367 c
+68.277 0.823 l
+68.277 1.223 68.192 1.543 68.028 1.778 c
+67.87 2.021 67.652 2.146 67.38 2.146 c
+67.116 2.146 66.899 2.021 66.734 1.778 c
+66.576 1.543 66.499 1.223 66.499 0.823 c
+h
+72.334 3.586 m
+72.334 2.631 l
+72.936 2.631 l
+72.936 2.102 l
+72.334 2.102 l
+72.334 -0.368 l
+72.334 -0.526 72.356 -0.643 72.408 -0.721 c
+72.466 -0.802 72.555 -0.838 72.672 -0.838 c
+72.761 -0.838 72.849 -0.823 72.936 -0.794 c
+72.936 -1.353 l
+72.79 -1.401 72.635 -1.426 72.481 -1.426 c
+72.224 -1.426 72.03 -1.334 71.893 -1.147 c
+71.754 -0.963 71.687 -0.702 71.687 -0.368 c
+71.687 2.102 l
+71.085 2.102 l
+71.085 2.631 l
+71.687 2.631 l
+71.687 3.586 l
+h
+74.348 2.219 m
+74.602 2.543 74.921 2.705 75.303 2.705 c
+76.009 2.705 76.365 2.234 76.377 1.294 c
+76.377 -1.353 l
+75.73 -1.353 l
+75.73 1.263 l
+75.73 1.576 75.674 1.797 75.568 1.926 c
+75.458 2.05 75.303 2.117 75.097 2.117 c
+74.939 2.117 74.793 2.061 74.656 1.955 c
+74.528 1.845 74.425 1.708 74.348 1.543 c
+74.348 -1.353 l
+73.701 -1.353 l
+73.701 4.292 l
+74.348 4.292 l
+h
+78.758 -1.426 m
+78.258 -1.426 77.875 -1.279 77.611 -0.985 c
+77.347 -0.691 77.214 -0.258 77.214 0.323 c
+77.214 0.793 l
+77.214 1.389 77.339 1.855 77.596 2.19 c
+77.861 2.532 78.222 2.705 78.684 2.705 c
+79.143 2.705 79.485 2.55 79.713 2.248 c
+79.948 1.955 80.069 1.492 80.08 0.867 c
+80.08 0.44 l
+77.861 0.44 l
+77.861 0.353 l
+77.861 -0.081 77.938 -0.393 78.096 -0.588 c
+78.261 -0.776 78.493 -0.867 78.787 -0.867 c
+78.982 -0.867 79.155 -0.834 79.301 -0.765 c
+79.448 -0.688 79.585 -0.57 79.713 -0.412 c
+80.051 -0.823 l
+79.764 -1.228 79.334 -1.426 78.758 -1.426 c
+78.684 2.146 m
+78.409 2.146 78.206 2.05 78.081 1.866 c
+77.952 1.679 77.879 1.389 77.861 0.999 c
+79.434 0.999 l
+79.434 1.087 l
+79.412 1.469 79.346 1.738 79.228 1.896 c
+79.111 2.061 78.927 2.146 78.684 2.146 c
+f
+Q
+q 1 0 0 1 380.4265 289.5652 cm
+0 0 m
+0 -0.97 l
+0.53 -0.97 l
+0.53 -1.764 l
+0 -1.764 l
+0 -3.734 l
+0 -3.892 0.019 -3.998 0.059 -4.057 c
+0.107 -4.116 0.191 -4.145 0.309 -4.145 c
+0.416 -4.145 0.5 -4.138 0.559 -4.116 c
+0.559 -4.925 l
+0.382 -4.991 0.191 -5.027 -0.014 -5.027 c
+-0.691 -5.027 -1.036 -4.642 -1.043 -3.866 c
+-1.043 -1.764 l
+-1.5 -1.764 l
+-1.5 -0.97 l
+-1.043 -0.97 l
+-1.043 0 l
+h
+2.984 -4.954 m
+2.955 -4.895 2.926 -4.792 2.896 -4.645 c
+2.708 -4.902 2.459 -5.027 2.146 -5.027 c
+1.812 -5.027 1.532 -4.921 1.309 -4.704 c
+1.091 -4.48 0.985 -4.189 0.985 -3.836 c
+0.985 -3.425 1.118 -3.109 1.382 -2.882 c
+1.646 -2.646 2.028 -2.529 2.529 -2.529 c
+2.851 -2.529 l
+2.851 -2.205 l
+2.851 -2.028 2.815 -1.908 2.749 -1.837 c
+2.69 -1.76 2.602 -1.72 2.484 -1.72 c
+2.227 -1.72 2.103 -1.874 2.103 -2.176 c
+1.058 -2.176 l
+1.058 -1.804 1.195 -1.5 1.47 -1.264 c
+1.742 -1.022 2.091 -0.897 2.514 -0.897 c
+2.955 -0.897 3.293 -1.014 3.528 -1.249 c
+3.77 -1.478 3.896 -1.801 3.896 -2.22 c
+3.896 -4.087 l
+3.896 -4.432 3.944 -4.7 4.042 -4.895 c
+4.042 -4.954 l
+h
+2.381 -4.204 m
+2.488 -4.204 2.58 -4.185 2.66 -4.145 c
+2.749 -4.098 2.811 -4.039 2.851 -3.969 c
+2.851 -3.146 l
+2.602 -3.146 l
+2.425 -3.146 2.282 -3.204 2.176 -3.322 c
+2.076 -3.433 2.028 -3.58 2.028 -3.763 c
+2.028 -4.057 2.146 -4.204 2.381 -4.204 c
+6.6 -1.985 m
+6.262 -1.955 l
+5.976 -1.955 5.785 -2.08 5.689 -2.323 c
+5.689 -4.954 l
+4.645 -4.954 l
+4.645 -0.97 l
+5.615 -0.97 l
+5.644 -1.411 l
+5.81 -1.07 6.041 -0.897 6.336 -0.897 c
+6.453 -0.897 6.545 -0.919 6.614 -0.956 c
+h
+6.938 -2.837 m
+6.938 -2.19 7.056 -1.706 7.291 -1.382 c
+7.526 -1.058 7.857 -0.897 8.291 -0.897 c
+8.643 -0.897 8.915 -1.04 9.114 -1.323 c
+9.158 -0.97 l
+10.099 -0.97 l
+10.099 -4.954 l
+10.099 -5.461 9.955 -5.85 9.672 -6.115 c
+9.386 -6.387 8.981 -6.527 8.453 -6.527 c
+8.224 -6.527 7.989 -6.483 7.747 -6.394 c
+7.512 -6.306 7.335 -6.192 7.217 -6.057 c
+7.57 -5.336 l
+7.666 -5.442 7.794 -5.527 7.952 -5.586 c
+8.106 -5.652 8.254 -5.689 8.393 -5.689 c
+8.628 -5.689 8.794 -5.63 8.893 -5.513 c
+9 -5.402 9.055 -5.226 9.055 -4.983 c
+9.055 -4.63 l
+8.856 -4.895 8.599 -5.027 8.276 -5.027 c
+7.853 -5.027 7.526 -4.866 7.291 -4.542 c
+7.063 -4.212 6.945 -3.741 6.938 -3.131 c
+h
+7.982 -3.102 m
+7.982 -3.477 8.029 -3.745 8.129 -3.91 c
+8.224 -4.079 8.378 -4.16 8.584 -4.16 c
+8.798 -4.16 8.956 -4.083 9.055 -3.925 c
+9.055 -2.028 l
+8.945 -1.864 8.79 -1.779 8.584 -1.779 c
+8.378 -1.779 8.224 -1.864 8.129 -2.028 c
+8.029 -2.198 7.982 -2.466 7.982 -2.837 c
+h
+12.465 -5.027 m
+11.936 -5.027 11.517 -4.873 11.215 -4.557 c
+10.922 -4.233 10.774 -3.774 10.774 -3.175 c
+10.774 -2.866 l
+10.774 -2.242 10.911 -1.756 11.186 -1.411 c
+11.458 -1.07 11.851 -0.897 12.362 -0.897 c
+12.862 -0.897 13.233 -1.058 13.479 -1.382 c
+13.733 -1.706 13.865 -2.183 13.876 -2.808 c
+13.876 -3.308 l
+11.803 -3.308 l
+11.822 -3.601 11.884 -3.818 11.994 -3.954 c
+12.112 -4.094 12.293 -4.16 12.538 -4.16 c
+12.881 -4.16 13.17 -4.042 13.406 -3.807 c
+13.818 -4.439 l
+13.689 -4.615 13.501 -4.759 13.259 -4.866 c
+13.012 -4.972 12.748 -5.027 12.465 -5.027 c
+11.819 -2.587 m
+12.847 -2.587 l
+12.847 -2.484 l
+12.847 -2.249 12.807 -2.072 12.729 -1.955 c
+12.66 -1.831 12.532 -1.764 12.347 -1.764 c
+12.171 -1.764 12.039 -1.834 11.95 -1.97 c
+11.869 -2.099 11.826 -2.304 11.819 -2.587 c
+15.669 0 m
+15.669 -0.97 l
+16.199 -0.97 l
+16.199 -1.764 l
+15.669 -1.764 l
+15.669 -3.734 l
+15.669 -3.892 15.688 -3.998 15.728 -4.057 c
+15.776 -4.116 15.861 -4.145 15.978 -4.145 c
+16.085 -4.145 16.169 -4.138 16.228 -4.116 c
+16.228 -4.925 l
+16.052 -4.991 15.861 -5.027 15.655 -5.027 c
+14.978 -5.027 14.633 -4.642 14.626 -3.866 c
+14.626 -1.764 l
+14.17 -1.764 l
+14.17 -0.97 l
+14.626 -0.97 l
+14.626 0 l
+h
+20.461 -1.985 m
+20.123 -1.955 l
+19.836 -1.955 19.645 -2.08 19.549 -2.323 c
+19.549 -4.954 l
+18.506 -4.954 l
+18.506 -0.97 l
+19.476 -0.97 l
+19.506 -1.411 l
+19.671 -1.07 19.902 -0.897 20.197 -0.897 c
+20.314 -0.897 20.406 -0.919 20.476 -0.956 c
+h
+22.534 -5.027 m
+22.005 -5.027 21.586 -4.873 21.284 -4.557 c
+20.991 -4.233 20.843 -3.774 20.843 -3.175 c
+20.843 -2.866 l
+20.843 -2.242 20.979 -1.756 21.255 -1.411 c
+21.527 -1.07 21.92 -0.897 22.431 -0.897 c
+22.931 -0.897 23.302 -1.058 23.548 -1.382 c
+23.802 -1.706 23.934 -2.183 23.945 -2.808 c
+23.945 -3.308 l
+21.872 -3.308 l
+21.891 -3.601 21.953 -3.818 22.063 -3.954 c
+22.181 -4.094 22.361 -4.16 22.607 -4.16 c
+22.949 -4.16 23.239 -4.042 23.474 -3.807 c
+23.886 -4.439 l
+23.757 -4.615 23.57 -4.759 23.328 -4.866 c
+23.081 -4.972 22.817 -5.027 22.534 -5.027 c
+21.887 -2.587 m
+22.916 -2.587 l
+22.916 -2.484 l
+22.916 -2.249 22.876 -2.072 22.799 -1.955 c
+22.728 -1.831 22.6 -1.764 22.416 -1.764 c
+22.24 -1.764 22.107 -1.834 22.019 -1.97 c
+21.939 -2.099 21.895 -2.304 21.887 -2.587 c
+24.768 -4.954 m
+24.768 -1.764 l
+24.283 -1.764 l
+24.283 -0.97 l
+24.768 -0.97 l
+24.768 -0.617 l
+24.768 -0.177 24.879 0.162 25.106 0.397 c
+25.342 0.639 25.658 0.764 26.061 0.764 c
+26.186 0.764 26.344 0.738 26.532 0.69 c
+26.532 -0.133 l
+26.462 -0.114 26.377 -0.104 26.282 -0.104 c
+25.966 -0.104 25.812 -0.287 25.812 -0.647 c
+25.812 -0.97 l
+26.429 -0.97 l
+26.429 -1.764 l
+25.812 -1.764 l
+25.812 -4.954 l
+h
+28.517 -5.027 m
+27.987 -5.027 27.568 -4.873 27.267 -4.557 c
+26.973 -4.233 26.826 -3.774 26.826 -3.175 c
+26.826 -2.866 l
+26.826 -2.242 26.962 -1.756 27.237 -1.411 c
+27.509 -1.07 27.902 -0.897 28.413 -0.897 c
+28.914 -0.897 29.284 -1.058 29.531 -1.382 c
+29.784 -1.706 29.916 -2.183 29.928 -2.808 c
+29.928 -3.308 l
+27.855 -3.308 l
+27.873 -3.601 27.936 -3.818 28.046 -3.954 c
+28.164 -4.094 28.344 -4.16 28.59 -4.16 c
+28.931 -4.16 29.222 -4.042 29.457 -3.807 c
+29.868 -4.439 l
+29.741 -4.615 29.552 -4.759 29.31 -4.866 c
+29.064 -4.972 28.8 -5.027 28.517 -5.027 c
+27.869 -2.587 m
+28.899 -2.587 l
+28.899 -2.484 l
+28.899 -2.249 28.858 -2.072 28.781 -1.955 c
+28.711 -1.831 28.582 -1.764 28.399 -1.764 c
+28.222 -1.764 28.09 -1.834 28.002 -1.97 c
+27.921 -2.099 27.877 -2.304 27.869 -2.587 c
+32.471 -1.985 m
+32.132 -1.955 l
+31.846 -1.955 31.655 -2.08 31.559 -2.323 c
+31.559 -4.954 l
+30.516 -4.954 l
+30.516 -0.97 l
+31.486 -0.97 l
+31.515 -1.411 l
+31.68 -1.07 31.912 -0.897 32.206 -0.897 c
+32.324 -0.897 32.415 -0.919 32.485 -0.956 c
+h
+34.543 -5.027 m
+34.013 -5.027 33.595 -4.873 33.294 -4.557 c
+32.999 -4.233 32.853 -3.774 32.853 -3.175 c
+32.853 -2.866 l
+32.853 -2.242 32.989 -1.756 33.265 -1.411 c
+33.536 -1.07 33.93 -0.897 34.44 -0.897 c
+34.94 -0.897 35.311 -1.058 35.557 -1.382 c
+35.811 -1.706 35.943 -2.183 35.954 -2.808 c
+35.954 -3.308 l
+33.882 -3.308 l
+33.9 -3.601 33.963 -3.818 34.073 -3.954 c
+34.19 -4.094 34.37 -4.16 34.616 -4.16 c
+34.958 -4.16 35.249 -4.042 35.484 -3.807 c
+35.895 -4.439 l
+35.767 -4.615 35.58 -4.759 35.337 -4.866 c
+35.091 -4.972 34.826 -5.027 34.543 -5.027 c
+33.896 -2.587 m
+34.925 -2.587 l
+34.925 -2.484 l
+34.925 -2.249 34.884 -2.072 34.807 -1.955 c
+34.738 -1.831 34.609 -1.764 34.425 -1.764 c
+34.249 -1.764 34.117 -1.834 34.028 -1.97 c
+33.948 -2.099 33.903 -2.304 33.896 -2.587 c
+37.498 -0.97 m
+37.527 -1.367 l
+37.762 -1.055 38.063 -0.897 38.439 -0.897 c
+39.122 -0.897 39.474 -1.378 39.497 -2.338 c
+39.497 -4.954 l
+38.453 -4.954 l
+38.453 -2.411 l
+38.453 -2.186 38.416 -2.025 38.35 -1.926 c
+38.281 -1.831 38.163 -1.779 37.997 -1.779 c
+37.81 -1.779 37.663 -1.874 37.556 -2.058 c
+37.556 -4.954 l
+36.513 -4.954 l
+36.513 -0.97 l
+h
+41.687 -4.16 m
+41.98 -4.16 42.131 -3.965 42.142 -3.572 c
+43.112 -3.572 l
+43.112 -4.006 42.98 -4.358 42.715 -4.63 c
+42.451 -4.895 42.113 -5.027 41.701 -5.027 c
+41.19 -5.027 40.797 -4.873 40.525 -4.557 c
+40.261 -4.233 40.122 -3.763 40.114 -3.146 c
+40.114 -2.822 l
+40.114 -2.198 40.246 -1.72 40.511 -1.397 c
+40.783 -1.066 41.18 -0.897 41.701 -0.897 c
+42.131 -0.897 42.473 -1.037 42.73 -1.309 c
+42.984 -1.584 43.112 -1.966 43.112 -2.455 c
+42.142 -2.455 l
+42.142 -2.242 42.102 -2.072 42.025 -1.955 c
+41.955 -1.831 41.837 -1.764 41.672 -1.764 c
+41.496 -1.764 41.367 -1.831 41.29 -1.955 c
+41.209 -2.084 41.165 -2.334 41.157 -2.705 c
+41.157 -3.117 l
+41.157 -3.439 41.172 -3.668 41.202 -3.792 c
+41.238 -3.921 41.294 -4.013 41.363 -4.072 c
+41.441 -4.131 41.547 -4.16 41.687 -4.16 c
+45.317 -5.027 m
+44.789 -5.027 44.369 -4.873 44.068 -4.557 c
+43.774 -4.233 43.627 -3.774 43.627 -3.175 c
+43.627 -2.866 l
+43.627 -2.242 43.763 -1.756 44.039 -1.411 c
+44.311 -1.07 44.704 -0.897 45.215 -0.897 c
+45.714 -0.897 46.085 -1.058 46.331 -1.382 c
+46.585 -1.706 46.717 -2.183 46.728 -2.808 c
+46.728 -3.308 l
+44.656 -3.308 l
+44.674 -3.601 44.737 -3.818 44.847 -3.954 c
+44.965 -4.094 45.144 -4.16 45.391 -4.16 c
+45.733 -4.16 46.023 -4.042 46.258 -3.807 c
+46.67 -4.439 l
+46.541 -4.615 46.354 -4.759 46.111 -4.866 c
+45.865 -4.972 45.6 -5.027 45.317 -5.027 c
+44.671 -2.587 m
+45.699 -2.587 l
+45.699 -2.484 l
+45.699 -2.249 45.659 -2.072 45.582 -1.955 c
+45.512 -1.831 45.383 -1.764 45.2 -1.764 c
+45.024 -1.764 44.891 -1.834 44.803 -1.97 c
+44.722 -2.099 44.678 -2.304 44.671 -2.587 c
+f
+Q
+q 1 0 0 1 427.8604 283.5388 cm
+0 0 m
+-0.397 0.264 l
+-0.162 0.588 -0.04 0.922 -0.029 1.263 c
+-0.029 1.881 l
+0.632 1.881 l
+0.632 1.352 l
+0.632 1.095 0.566 0.849 0.441 0.602 c
+0.324 0.359 0.177 0.158 0 0 c
+5.233 1.072 m
+5.193 1.161 5.167 1.308 5.159 1.514 c
+4.924 1.168 4.63 0.999 4.278 0.999 c
+3.913 0.999 3.63 1.095 3.425 1.294 c
+3.227 1.499 3.131 1.786 3.131 2.16 c
+3.131 2.561 3.267 2.881 3.543 3.116 c
+3.815 3.358 4.189 3.484 4.659 3.484 c
+5.145 3.484 l
+5.145 3.91 l
+5.145 4.145 5.089 4.31 4.983 4.409 c
+4.873 4.516 4.711 4.571 4.498 4.571 c
+4.299 4.571 4.138 4.512 4.013 4.394 c
+3.896 4.277 3.836 4.13 3.836 3.954 c
+3.19 3.954 l
+3.19 4.149 3.248 4.34 3.366 4.527 c
+3.491 4.71 3.653 4.858 3.851 4.968 c
+4.057 5.074 4.285 5.13 4.542 5.13 c
+4.943 5.13 5.247 5.026 5.453 4.821 c
+5.667 4.615 5.781 4.321 5.791 3.939 c
+5.791 1.925 l
+5.791 1.62 5.828 1.356 5.909 1.132 c
+5.909 1.072 l
+h
+4.366 1.587 m
+4.531 1.587 4.682 1.631 4.821 1.72 c
+4.968 1.807 5.075 1.918 5.145 2.057 c
+5.145 2.998 l
+4.777 2.998 l
+4.461 2.998 4.218 2.929 4.042 2.792 c
+3.866 2.664 3.778 2.476 3.778 2.234 c
+3.778 2.006 3.822 1.841 3.91 1.734 c
+3.998 1.635 4.149 1.587 4.366 1.587 c
+7.408 5.056 m
+7.423 4.615 l
+7.676 4.957 8 5.13 8.393 5.13 c
+9.099 5.13 9.455 4.659 9.467 3.719 c
+9.467 1.072 l
+8.819 1.072 l
+8.819 3.689 l
+8.819 4.001 8.764 4.222 8.658 4.351 c
+8.548 4.475 8.393 4.542 8.187 4.542 c
+8.029 4.542 7.882 4.486 7.746 4.38 c
+7.618 4.27 7.515 4.134 7.437 3.968 c
+7.437 1.072 l
+6.791 1.072 l
+6.791 5.056 l
+h
+10.304 3.248 m
+10.304 3.854 10.414 4.321 10.643 4.644 c
+10.878 4.968 11.204 5.13 11.627 5.13 c
+12.009 5.13 12.307 4.972 12.524 4.659 c
+12.524 6.717 l
+13.17 6.717 l
+13.17 1.072 l
+12.582 1.072 l
+12.538 1.499 l
+12.332 1.165 12.027 0.999 11.627 0.999 c
+11.215 0.999 10.892 1.153 10.657 1.469 c
+10.422 1.793 10.304 2.248 10.304 2.836 c
+h
+10.951 2.865 m
+10.951 2.425 11.013 2.094 11.142 1.881 c
+11.278 1.675 11.499 1.572 11.803 1.572 c
+12.127 1.572 12.366 1.734 12.524 2.057 c
+12.524 4.072 l
+12.355 4.384 12.116 4.542 11.803 4.542 c
+11.499 4.542 11.278 4.438 11.142 4.233 c
+11.013 4.027 10.951 3.704 10.951 3.262 c
+h
+16.596 1.072 -0.647 5.644 re
+19.035 0.999 m
+18.535 0.999 18.153 1.146 17.889 1.44 c
+17.624 1.734 17.492 2.167 17.492 2.748 c
+17.492 3.218 l
+17.492 3.814 17.617 4.28 17.874 4.615 c
+18.138 4.957 18.499 5.13 18.962 5.13 c
+19.422 5.13 19.763 4.976 19.991 4.674 c
+20.226 4.38 20.347 3.917 20.359 3.293 c
+20.359 2.865 l
+18.138 2.865 l
+18.138 2.778 l
+18.138 2.344 18.216 2.032 18.374 1.837 c
+18.539 1.649 18.771 1.558 19.065 1.558 c
+19.26 1.558 19.432 1.591 19.58 1.66 c
+19.726 1.738 19.862 1.855 19.991 2.013 c
+20.328 1.602 l
+20.042 1.198 19.613 0.999 19.035 0.999 c
+18.962 4.571 m
+18.686 4.571 18.485 4.475 18.359 4.292 c
+18.231 4.104 18.157 3.814 18.138 3.424 c
+19.711 3.424 l
+19.711 3.513 l
+19.69 3.895 19.623 4.163 19.505 4.321 c
+19.388 4.486 19.204 4.571 18.962 4.571 c
+23.181 1.072 m
+23.14 1.161 23.114 1.308 23.107 1.514 c
+22.872 1.168 22.578 0.999 22.225 0.999 c
+21.861 0.999 21.579 1.095 21.373 1.294 c
+21.174 1.499 21.078 1.786 21.078 2.16 c
+21.078 2.561 21.215 2.881 21.49 3.116 c
+21.762 3.358 22.137 3.484 22.607 3.484 c
+23.092 3.484 l
+23.092 3.91 l
+23.092 4.145 23.037 4.31 22.931 4.409 c
+22.82 4.516 22.659 4.571 22.445 4.571 c
+22.248 4.571 22.086 4.512 21.961 4.394 c
+21.843 4.277 21.784 4.13 21.784 3.954 c
+21.137 3.954 l
+21.137 4.149 21.196 4.34 21.313 4.527 c
+21.439 4.71 21.6 4.858 21.799 4.968 c
+22.005 5.074 22.232 5.13 22.489 5.13 c
+22.89 5.13 23.195 5.026 23.401 4.821 c
+23.614 4.615 23.728 4.321 23.739 3.939 c
+23.739 1.925 l
+23.739 1.62 23.776 1.356 23.856 1.132 c
+23.856 1.072 l
+h
+22.313 1.587 m
+22.479 1.587 22.629 1.631 22.769 1.72 c
+22.915 1.807 23.023 1.918 23.092 2.057 c
+23.092 2.998 l
+22.725 2.998 l
+22.408 2.998 22.167 2.929 21.99 2.792 c
+21.814 2.664 21.725 2.476 21.725 2.234 c
+21.725 2.006 21.77 1.841 21.857 1.734 c
+21.946 1.635 22.096 1.587 22.313 1.587 c
+25.812 2.057 m
+26.561 5.056 l
+27.223 5.056 l
+26.047 1.072 l
+25.562 1.072 l
+24.371 5.056 l
+25.032 5.056 l
+h
+29.281 0.999 m
+28.781 0.999 28.399 1.146 28.134 1.44 c
+27.869 1.734 27.737 2.167 27.737 2.748 c
+27.737 3.218 l
+27.737 3.814 27.862 4.28 28.12 4.615 c
+28.384 4.957 28.744 5.13 29.207 5.13 c
+29.666 5.13 30.009 4.976 30.236 4.674 c
+30.471 4.38 30.593 3.917 30.603 3.293 c
+30.603 2.865 l
+28.384 2.865 l
+28.384 2.778 l
+28.384 2.344 28.461 2.032 28.619 1.837 c
+28.785 1.649 29.016 1.558 29.31 1.558 c
+29.504 1.558 29.677 1.591 29.824 1.66 c
+29.971 1.738 30.107 1.855 30.236 2.013 c
+30.574 1.602 l
+30.287 1.198 29.857 0.999 29.281 0.999 c
+29.207 4.571 m
+28.931 4.571 28.729 4.475 28.604 4.292 c
+28.476 4.104 28.403 3.814 28.384 3.424 c
+29.957 3.424 l
+29.957 3.513 l
+29.934 3.895 29.868 4.163 29.751 4.321 c
+29.633 4.486 29.45 4.571 29.207 4.571 c
+33.323 2.087 m
+33.323 2.234 33.267 2.355 33.161 2.454 c
+33.051 2.549 32.845 2.667 32.544 2.807 c
+32.199 2.954 31.956 3.075 31.809 3.175 c
+31.662 3.281 31.551 3.399 31.486 3.528 c
+31.416 3.652 31.382 3.81 31.382 3.998 c
+31.382 4.321 31.5 4.589 31.735 4.806 c
+31.97 5.019 32.272 5.13 32.646 5.13 c
+33.028 5.13 33.338 5.016 33.573 4.791 c
+33.808 4.564 33.926 4.277 33.926 3.924 c
+33.279 3.924 l
+33.279 4.101 33.22 4.251 33.103 4.38 c
+32.985 4.505 32.831 4.571 32.646 4.571 c
+32.448 4.571 32.297 4.516 32.191 4.409 c
+32.081 4.31 32.029 4.178 32.029 4.012 c
+32.029 3.883 32.066 3.777 32.147 3.689 c
+32.224 3.608 32.415 3.505 32.72 3.38 c
+33.198 3.193 33.529 3.006 33.705 2.822 c
+33.882 2.645 33.969 2.418 33.969 2.146 c
+33.969 1.793 33.845 1.514 33.602 1.308 c
+33.367 1.102 33.051 0.999 32.662 0.999 c
+32.239 0.999 31.9 1.117 31.647 1.352 c
+31.39 1.595 31.265 1.899 31.265 2.263 c
+31.912 2.263 l
+31.919 2.036 31.989 1.859 32.118 1.734 c
+32.243 1.616 32.426 1.558 32.662 1.558 c
+32.874 1.558 33.036 1.606 33.146 1.705 c
+33.264 1.801 33.323 1.928 33.323 2.087 c
+38.57 1.072 m
+38.53 1.161 38.504 1.308 38.497 1.514 c
+38.262 1.168 37.967 0.999 37.615 0.999 c
+37.251 0.999 36.968 1.095 36.762 1.294 c
+36.564 1.499 36.469 1.786 36.469 2.16 c
+36.469 2.561 36.604 2.881 36.88 3.116 c
+37.152 3.358 37.527 3.484 37.997 3.484 c
+38.482 3.484 l
+38.482 3.91 l
+38.482 4.145 38.427 4.31 38.32 4.409 c
+38.21 4.516 38.048 4.571 37.836 4.571 c
+37.637 4.571 37.475 4.512 37.35 4.394 c
+37.233 4.277 37.174 4.13 37.174 3.954 c
+36.527 3.954 l
+36.527 4.149 36.586 4.34 36.704 4.527 c
+36.829 4.71 36.99 4.858 37.188 4.968 c
+37.394 5.074 37.622 5.13 37.88 5.13 c
+38.281 5.13 38.585 5.026 38.79 4.821 c
+39.004 4.615 39.118 4.321 39.129 3.939 c
+39.129 1.925 l
+39.129 1.62 39.166 1.356 39.247 1.132 c
+39.247 1.072 l
+h
+37.703 1.587 m
+37.869 1.587 38.019 1.631 38.159 1.72 c
+38.306 1.807 38.412 1.918 38.482 2.057 c
+38.482 2.998 l
+38.115 2.998 l
+37.799 2.998 37.556 2.929 37.379 2.792 c
+37.203 2.664 37.115 2.476 37.115 2.234 c
+37.115 2.006 37.159 1.841 37.248 1.734 c
+37.336 1.635 37.487 1.587 37.703 1.587 c
+41.716 3.248 m
+41.716 3.854 41.826 4.321 42.054 4.644 c
+42.289 4.968 42.616 5.13 43.039 5.13 c
+43.421 5.13 43.719 4.972 43.935 4.659 c
+43.935 6.717 l
+44.583 6.717 l
+44.583 1.072 l
+43.995 1.072 l
+43.95 1.499 l
+43.744 1.165 43.44 0.999 43.039 0.999 c
+42.628 0.999 42.304 1.153 42.069 1.469 c
+41.834 1.793 41.716 2.248 41.716 2.836 c
+h
+42.362 2.865 m
+42.362 2.425 42.425 2.094 42.553 1.881 c
+42.69 1.675 42.91 1.572 43.216 1.572 c
+43.538 1.572 43.777 1.734 43.935 2.057 c
+43.935 4.072 l
+43.767 4.384 43.528 4.542 43.216 4.542 c
+42.91 4.542 42.69 4.438 42.553 4.233 c
+42.425 4.027 42.362 3.704 42.362 3.262 c
+h
+46.287 1.072 -0.646 3.984 re
+46.331 6.1 m
+46.331 5.99 46.302 5.898 46.243 5.82 c
+46.185 5.751 46.089 5.718 45.964 5.718 c
+45.846 5.718 45.751 5.751 45.685 5.82 c
+45.626 5.898 45.597 5.99 45.597 6.1 c
+45.597 6.217 45.626 6.31 45.685 6.379 c
+45.751 6.456 45.846 6.497 45.964 6.497 c
+46.089 6.497 46.185 6.456 46.243 6.379 c
+46.302 6.298 46.331 6.206 46.331 6.1 c
+47.596 1.072 m
+47.596 4.527 l
+47.066 4.527 l
+47.066 5.056 l
+47.596 5.056 l
+47.596 5.512 l
+47.596 5.913 47.691 6.225 47.889 6.453 c
+48.095 6.676 48.375 6.79 48.727 6.79 c
+48.864 6.79 48.996 6.769 49.124 6.732 c
+49.095 6.188 l
+48.996 6.206 48.897 6.217 48.801 6.217 c
+48.426 6.217 48.242 5.953 48.242 5.423 c
+48.242 5.056 l
+48.918 5.056 l
+48.918 4.527 l
+48.242 4.527 l
+48.242 1.072 l
+h
+49.977 1.072 m
+49.977 4.527 l
+49.448 4.527 l
+49.448 5.056 l
+49.977 5.056 l
+49.977 5.512 l
+49.977 5.913 50.073 6.225 50.271 6.453 c
+50.476 6.676 50.756 6.79 51.108 6.79 c
+51.245 6.79 51.377 6.769 51.505 6.732 c
+51.476 6.188 l
+51.377 6.206 51.278 6.217 51.182 6.217 c
+50.807 6.217 50.624 5.953 50.624 5.423 c
+50.624 5.056 l
+51.299 5.056 l
+51.299 4.527 l
+50.624 4.527 l
+50.624 1.072 l
+h
+53.402 0.999 m
+52.902 0.999 52.52 1.146 52.255 1.44 c
+51.991 1.734 51.858 2.167 51.858 2.748 c
+51.858 3.218 l
+51.858 3.814 51.983 4.28 52.24 4.615 c
+52.505 4.957 52.865 5.13 53.329 5.13 c
+53.788 5.13 54.129 4.976 54.357 4.674 c
+54.592 4.38 54.713 3.917 54.725 3.293 c
+54.725 2.865 l
+52.505 2.865 l
+52.505 2.778 l
+52.505 2.344 52.583 2.032 52.741 1.837 c
+52.905 1.649 53.137 1.558 53.431 1.558 c
+53.626 1.558 53.799 1.591 53.946 1.66 c
+54.092 1.738 54.229 1.855 54.357 2.013 c
+54.696 1.602 l
+54.409 1.198 53.979 0.999 53.402 0.999 c
+53.329 4.571 m
+53.053 4.571 52.851 4.475 52.726 4.292 c
+52.597 4.104 52.523 3.814 52.505 3.424 c
+54.077 3.424 l
+54.077 3.513 l
+54.056 3.895 53.99 4.163 53.872 4.321 c
+53.755 4.486 53.57 4.571 53.329 4.571 c
+57.15 4.438 m
+57.061 4.457 56.963 4.469 56.856 4.469 c
+56.522 4.469 56.286 4.284 56.151 3.924 c
+56.151 1.072 l
+55.504 1.072 l
+55.504 5.056 l
+56.136 5.056 l
+56.151 4.644 l
+56.327 4.968 56.569 5.13 56.886 5.13 c
+56.992 5.13 57.08 5.107 57.15 5.071 c
+h
+59.149 0.999 m
+58.649 0.999 58.268 1.146 58.002 1.44 c
+57.738 1.734 57.605 2.167 57.605 2.748 c
+57.605 3.218 l
+57.605 3.814 57.73 4.28 57.988 4.615 c
+58.252 4.957 58.613 5.13 59.076 5.13 c
+59.535 5.13 59.877 4.976 60.105 4.674 c
+60.34 4.38 60.461 3.917 60.472 3.293 c
+60.472 2.865 l
+58.252 2.865 l
+58.252 2.778 l
+58.252 2.344 58.33 2.032 58.488 1.837 c
+58.653 1.649 58.885 1.558 59.178 1.558 c
+59.373 1.558 59.546 1.591 59.693 1.66 c
+59.84 1.738 59.976 1.855 60.105 2.013 c
+60.443 1.602 l
+60.156 1.198 59.726 0.999 59.149 0.999 c
+59.076 4.571 m
+58.8 4.571 58.598 4.475 58.473 4.292 c
+58.345 4.104 58.271 3.814 58.252 3.424 c
+59.825 3.424 l
+59.825 3.513 l
+59.803 3.895 59.737 4.163 59.619 4.321 c
+59.502 4.486 59.318 4.571 59.076 4.571 c
+61.869 5.056 m
+61.883 4.615 l
+62.137 4.957 62.46 5.13 62.854 5.13 c
+63.559 5.13 63.916 4.659 63.926 3.719 c
+63.926 1.072 l
+63.28 1.072 l
+63.28 3.689 l
+63.28 4.001 63.224 4.222 63.118 4.351 c
+63.008 4.475 62.854 4.542 62.648 4.542 c
+62.49 4.542 62.343 4.486 62.206 4.38 c
+62.078 4.27 61.975 4.134 61.898 3.968 c
+61.898 1.072 l
+61.251 1.072 l
+61.251 5.056 l
+h
+66.278 1.558 m
+66.491 1.558 66.664 1.62 66.792 1.749 c
+66.929 1.884 67.002 2.076 67.013 2.322 c
+67.631 2.322 l
+67.608 1.94 67.473 1.62 67.219 1.367 c
+66.962 1.12 66.65 0.999 66.278 0.999 c
+65.786 0.999 65.411 1.15 65.146 1.454 c
+64.889 1.767 64.764 2.234 64.764 2.851 c
+64.764 3.293 l
+64.764 3.887 64.889 4.343 65.146 4.659 c
+65.411 4.972 65.786 5.13 66.278 5.13 c
+66.679 5.13 66.999 4.997 67.234 4.733 c
+67.476 4.475 67.608 4.13 67.631 3.689 c
+67.013 3.689 l
+66.991 3.983 66.918 4.203 66.792 4.351 c
+66.675 4.498 66.503 4.571 66.278 4.571 c
+65.984 4.571 65.767 4.471 65.632 4.277 c
+65.491 4.089 65.418 3.781 65.411 3.351 c
+65.411 2.836 l
+65.411 2.366 65.477 2.032 65.617 1.837 c
+65.763 1.649 65.984 1.558 66.278 1.558 c
+69.806 0.999 m
+69.306 0.999 68.924 1.146 68.659 1.44 c
+68.395 1.734 68.263 2.167 68.263 2.748 c
+68.263 3.218 l
+68.263 3.814 68.387 4.28 68.645 4.615 c
+68.909 4.957 69.27 5.13 69.732 5.13 c
+70.191 5.13 70.534 4.976 70.762 4.674 c
+70.997 4.38 71.118 3.917 71.128 3.293 c
+71.128 2.865 l
+68.909 2.865 l
+68.909 2.778 l
+68.909 2.344 68.986 2.032 69.144 1.837 c
+69.31 1.649 69.541 1.558 69.835 1.558 c
+70.031 1.558 70.203 1.591 70.349 1.66 c
+70.497 1.738 70.633 1.855 70.762 2.013 c
+71.099 1.602 l
+70.813 1.198 70.382 0.999 69.806 0.999 c
+69.732 4.571 m
+69.457 4.571 69.254 4.475 69.129 4.292 c
+69.001 4.104 68.928 3.814 68.909 3.424 c
+70.482 3.424 l
+70.482 3.513 l
+70.46 3.895 70.394 4.163 70.276 4.321 c
+70.158 4.486 69.975 4.571 69.732 4.571 c
+75.671 1.072 m
+75.631 1.161 75.604 1.308 75.597 1.514 c
+75.362 1.168 75.068 0.999 74.715 0.999 c
+74.351 0.999 74.068 1.095 73.863 1.294 c
+73.665 1.499 73.569 1.786 73.569 2.16 c
+73.569 2.561 73.705 2.881 73.981 3.116 c
+74.253 3.358 74.627 3.484 75.097 3.484 c
+75.583 3.484 l
+75.583 3.91 l
+75.583 4.145 75.527 4.31 75.421 4.409 c
+75.311 4.516 75.149 4.571 74.936 4.571 c
+74.737 4.571 74.576 4.512 74.451 4.394 c
+74.333 4.277 74.274 4.13 74.274 3.954 c
+73.628 3.954 l
+73.628 4.149 73.686 4.34 73.804 4.527 c
+73.929 4.71 74.091 4.858 74.289 4.968 c
+74.495 5.074 74.723 5.13 74.98 5.13 c
+75.38 5.13 75.685 5.026 75.891 4.821 c
+76.105 4.615 76.219 4.321 76.229 3.939 c
+76.229 1.925 l
+76.229 1.62 76.266 1.356 76.347 1.132 c
+76.347 1.072 l
+h
+74.804 1.587 m
+74.969 1.587 75.12 1.631 75.259 1.72 c
+75.406 1.807 75.513 1.918 75.583 2.057 c
+75.583 2.998 l
+75.215 2.998 l
+74.899 2.998 74.656 2.929 74.48 2.792 c
+74.303 2.664 74.216 2.476 74.216 2.234 c
+74.216 2.006 74.26 1.841 74.348 1.734 c
+74.436 1.635 74.587 1.587 74.804 1.587 c
+79.169 2.087 m
+79.169 2.234 79.114 2.355 79.007 2.454 c
+78.897 2.549 78.692 2.667 78.39 2.807 c
+78.045 2.954 77.802 3.075 77.655 3.175 c
+77.508 3.281 77.398 3.399 77.332 3.528 c
+77.262 3.652 77.229 3.81 77.229 3.998 c
+77.229 4.321 77.347 4.589 77.582 4.806 c
+77.817 5.019 78.118 5.13 78.493 5.13 c
+78.875 5.13 79.184 5.016 79.419 4.791 c
+79.654 4.564 79.772 4.277 79.772 3.924 c
+79.125 3.924 l
+79.125 4.101 79.066 4.251 78.949 4.38 c
+78.831 4.505 78.677 4.571 78.493 4.571 c
+78.295 4.571 78.143 4.516 78.037 4.409 c
+77.927 4.31 77.875 4.178 77.875 4.012 c
+77.875 3.883 77.912 3.777 77.993 3.689 c
+78.07 3.608 78.262 3.505 78.567 3.38 c
+79.045 3.193 79.375 3.006 79.552 2.822 c
+79.728 2.645 79.816 2.418 79.816 2.146 c
+79.816 1.793 79.691 1.514 79.448 1.308 c
+79.213 1.102 78.897 0.999 78.508 0.999 c
+78.085 0.999 77.747 1.117 77.493 1.352 c
+77.237 1.595 77.111 1.899 77.111 2.263 c
+77.758 2.263 l
+77.765 2.036 77.835 1.859 77.964 1.734 c
+78.089 1.616 78.272 1.558 78.508 1.558 c
+78.721 1.558 78.883 1.606 78.993 1.705 c
+79.111 1.801 79.169 1.928 79.169 2.087 c
+84.416 1.072 m
+84.377 1.161 84.35 1.308 84.343 1.514 c
+84.108 1.168 83.814 0.999 83.461 0.999 c
+83.097 0.999 82.814 1.095 82.609 1.294 c
+82.411 1.499 82.315 1.786 82.315 2.16 c
+82.315 2.561 82.451 2.881 82.727 3.116 c
+82.999 3.358 83.373 3.484 83.843 3.484 c
+84.329 3.484 l
+84.329 3.91 l
+84.329 4.145 84.273 4.31 84.167 4.409 c
+84.057 4.516 83.895 4.571 83.682 4.571 c
+83.483 4.571 83.321 4.512 83.197 4.394 c
+83.08 4.277 83.02 4.13 83.02 3.954 c
+82.374 3.954 l
+82.374 4.149 82.432 4.34 82.55 4.527 c
+82.675 4.71 82.837 4.858 83.035 4.968 c
+83.24 5.074 83.469 5.13 83.726 5.13 c
+84.127 5.13 84.431 5.026 84.637 4.821 c
+84.85 4.615 84.964 4.321 84.975 3.939 c
+84.975 1.925 l
+84.975 1.62 85.012 1.356 85.093 1.132 c
+85.093 1.072 l
+h
+83.55 1.587 m
+83.715 1.587 83.866 1.631 84.005 1.72 c
+84.152 1.807 84.258 1.918 84.329 2.057 c
+84.329 2.998 l
+83.961 2.998 l
+83.645 2.998 83.402 2.929 83.226 2.792 c
+83.049 2.664 82.962 2.476 82.962 2.234 c
+82.962 2.006 83.005 1.841 83.094 1.734 c
+83.182 1.635 83.333 1.587 83.55 1.587 c
+86.592 5.056 m
+86.607 4.615 l
+86.86 4.957 87.184 5.13 87.577 5.13 c
+88.283 5.13 88.639 4.659 88.65 3.719 c
+88.65 1.072 l
+88.003 1.072 l
+88.003 3.689 l
+88.003 4.001 87.948 4.222 87.842 4.351 c
+87.731 4.475 87.577 4.542 87.371 4.542 c
+87.213 4.542 87.066 4.486 86.93 4.38 c
+86.802 4.27 86.699 4.134 86.621 3.968 c
+86.621 1.072 l
+85.975 1.072 l
+85.975 5.056 l
+h
+f
+Q
+q 1 0 0 1 311.0178 275.5567 cm
+0 0 m
+-0.217 -0.287 -0.53 -0.426 -0.941 -0.426 c
+-1.305 -0.426 -1.58 -0.305 -1.764 -0.058 c
+-1.941 0.195 -2.036 0.559 -2.043 1.029 c
+-2.043 3.631 l
+-1.396 3.631 l
+-1.396 1.087 l
+-1.396 0.459 -1.213 0.147 -0.838 0.147 c
+-0.437 0.147 -0.162 0.324 -0.015 0.676 c
+-0.015 3.631 l
+0.632 3.631 l
+0.632 -0.353 l
+0.015 -0.353 l
+h
+2.234 3.631 m
+2.249 3.19 l
+2.502 3.532 2.826 3.705 3.219 3.705 c
+3.925 3.705 4.281 3.234 4.292 2.294 c
+4.292 -0.353 l
+3.645 -0.353 l
+3.645 2.263 l
+3.645 2.576 3.59 2.797 3.484 2.926 c
+3.373 3.05 3.219 3.117 3.013 3.117 c
+2.855 3.117 2.708 3.061 2.572 2.955 c
+2.444 2.845 2.341 2.708 2.263 2.543 c
+2.263 -0.353 l
+1.617 -0.353 l
+1.617 3.631 l
+h
+6.644 0.133 m
+6.857 0.133 7.03 0.195 7.158 0.324 c
+7.294 0.459 7.368 0.651 7.379 0.897 c
+7.996 0.897 l
+7.975 0.515 7.838 0.195 7.584 -0.058 c
+7.327 -0.305 7.015 -0.426 6.644 -0.426 c
+6.151 -0.426 5.777 -0.276 5.512 0.029 c
+5.255 0.341 5.13 0.809 5.13 1.426 c
+5.13 1.867 l
+5.13 2.462 5.255 2.918 5.512 3.234 c
+5.777 3.547 6.151 3.705 6.644 3.705 c
+7.044 3.705 7.364 3.572 7.599 3.308 c
+7.842 3.05 7.975 2.705 7.996 2.263 c
+7.379 2.263 l
+7.357 2.558 7.283 2.778 7.158 2.926 c
+7.04 3.072 6.868 3.146 6.644 3.146 c
+6.35 3.146 6.133 3.046 5.997 2.851 c
+5.858 2.664 5.784 2.356 5.777 1.926 c
+5.777 1.411 l
+5.777 0.941 5.843 0.607 5.982 0.412 c
+6.13 0.224 6.35 0.133 6.644 0.133 c
+8.613 1.823 m
+8.613 2.4 8.75 2.855 9.025 3.19 c
+9.309 3.532 9.679 3.705 10.142 3.705 c
+10.601 3.705 10.969 3.535 11.245 3.204 c
+11.528 2.882 11.675 2.433 11.686 1.867 c
+11.686 1.44 l
+11.686 0.871 11.542 0.416 11.26 0.073 c
+10.984 -0.261 10.616 -0.426 10.157 -0.426 c
+9.694 -0.426 9.323 -0.264 9.04 0.059 c
+8.764 0.389 8.621 0.831 8.613 1.382 c
+h
+9.261 1.44 m
+9.261 1.037 9.338 0.721 9.496 0.485 c
+9.66 0.25 9.882 0.133 10.157 0.133 c
+10.723 0.133 11.017 0.544 11.039 1.367 c
+11.039 1.823 l
+11.039 2.223 10.955 2.543 10.789 2.778 c
+10.631 3.021 10.414 3.146 10.142 3.146 c
+9.878 3.146 9.66 3.021 9.496 2.778 c
+9.338 2.543 9.261 2.223 9.261 1.823 c
+h
+13.141 3.631 m
+13.155 3.263 l
+13.398 3.557 13.718 3.705 14.111 3.705 c
+14.552 3.705 14.861 3.506 15.037 3.117 c
+15.291 3.506 15.64 3.705 16.081 3.705 c
+16.816 3.705 17.19 3.241 17.213 2.323 c
+17.213 -0.353 l
+16.565 -0.353 l
+16.565 2.263 l
+16.565 2.558 16.511 2.77 16.404 2.911 c
+16.305 3.046 16.132 3.117 15.89 3.117 c
+15.692 3.117 15.53 3.036 15.405 2.882 c
+15.287 2.734 15.217 2.543 15.199 2.308 c
+15.199 -0.353 l
+14.537 -0.353 l
+14.537 2.294 l
+14.537 2.841 14.317 3.117 13.876 3.117 c
+13.542 3.117 13.307 2.955 13.17 2.631 c
+13.17 -0.353 l
+12.523 -0.353 l
+12.523 3.631 l
+h
+18.8 3.631 m
+18.815 3.263 l
+19.057 3.557 19.377 3.705 19.771 3.705 c
+20.211 3.705 20.519 3.506 20.696 3.117 c
+20.949 3.506 21.299 3.705 21.74 3.705 c
+22.475 3.705 22.85 3.241 22.871 2.323 c
+22.871 -0.353 l
+22.225 -0.353 l
+22.225 2.263 l
+22.225 2.558 22.169 2.77 22.063 2.911 c
+21.964 3.046 21.791 3.117 21.549 3.117 c
+21.35 3.117 21.188 3.036 21.064 2.882 c
+20.947 2.734 20.876 2.543 20.858 2.308 c
+20.858 -0.353 l
+20.197 -0.353 l
+20.197 2.294 l
+20.197 2.841 19.976 3.117 19.535 3.117 c
+19.201 3.117 18.965 2.955 18.83 2.631 c
+18.83 -0.353 l
+18.183 -0.353 l
+18.183 3.631 l
+h
+24.548 -0.353 -0.647 3.984 re
+24.592 4.675 m
+24.592 4.564 24.562 4.472 24.503 4.395 c
+24.444 4.326 24.349 4.293 24.224 4.293 c
+24.106 4.293 24.01 4.326 23.945 4.395 c
+23.886 4.472 23.856 4.564 23.856 4.675 c
+23.856 4.792 23.886 4.884 23.945 4.954 c
+24.01 5.031 24.106 5.072 24.224 5.072 c
+24.349 5.072 24.444 5.031 24.503 4.954 c
+24.562 4.873 24.592 4.781 24.592 4.675 c
+26.414 4.586 m
+26.414 3.631 l
+27.017 3.631 l
+27.017 3.102 l
+26.414 3.102 l
+26.414 0.632 l
+26.414 0.474 26.437 0.357 26.487 0.279 c
+26.547 0.199 26.634 0.162 26.752 0.162 c
+26.84 0.162 26.929 0.177 27.017 0.206 c
+27.017 -0.353 l
+26.869 -0.401 26.715 -0.426 26.561 -0.426 c
+26.304 -0.426 26.109 -0.334 25.973 -0.147 c
+25.834 0.037 25.768 0.298 25.768 0.632 c
+25.768 3.102 l
+25.165 3.102 l
+25.165 3.631 l
+25.768 3.631 l
+25.768 4.586 l
+h
+29.207 -0.426 m
+28.708 -0.426 28.325 -0.279 28.06 0.015 c
+27.796 0.309 27.663 0.742 27.663 1.323 c
+27.663 1.793 l
+27.663 2.389 27.789 2.855 28.045 3.19 c
+28.311 3.532 28.671 3.705 29.134 3.705 c
+29.593 3.705 29.934 3.55 30.162 3.248 c
+30.397 2.955 30.519 2.492 30.53 1.867 c
+30.53 1.44 l
+28.311 1.44 l
+28.311 1.353 l
+28.311 0.919 28.388 0.607 28.546 0.412 c
+28.71 0.224 28.943 0.133 29.236 0.133 c
+29.431 0.133 29.604 0.166 29.751 0.235 c
+29.898 0.312 30.034 0.43 30.162 0.588 c
+30.501 0.177 l
+30.214 -0.228 29.784 -0.426 29.207 -0.426 c
+29.134 3.146 m
+28.858 3.146 28.656 3.05 28.531 2.866 c
+28.402 2.679 28.328 2.389 28.311 1.999 c
+29.884 1.999 l
+29.884 2.088 l
+29.861 2.469 29.795 2.738 29.677 2.896 c
+29.56 3.061 29.376 3.146 29.134 3.146 c
+31.177 1.823 m
+31.177 2.429 31.287 2.896 31.515 3.219 c
+31.75 3.543 32.077 3.705 32.5 3.705 c
+32.882 3.705 33.179 3.547 33.396 3.234 c
+33.396 5.292 l
+34.043 5.292 l
+34.043 -0.353 l
+33.455 -0.353 l
+33.411 0.073 l
+33.205 -0.261 32.9 -0.426 32.5 -0.426 c
+32.088 -0.426 31.765 -0.272 31.53 0.044 c
+31.295 0.368 31.177 0.823 31.177 1.411 c
+h
+31.823 1.44 m
+31.823 1 31.886 0.669 32.014 0.456 c
+32.151 0.25 32.371 0.147 32.676 0.147 c
+32.999 0.147 33.238 0.309 33.396 0.632 c
+33.396 2.646 l
+33.227 2.959 32.988 3.117 32.676 3.117 c
+32.371 3.117 32.151 3.013 32.014 2.808 c
+31.886 2.602 31.823 2.279 31.823 1.837 c
+h
+38.144 0.133 m
+38.357 0.133 38.53 0.195 38.659 0.324 c
+38.794 0.459 38.868 0.651 38.879 0.897 c
+39.496 0.897 l
+39.474 0.515 39.338 0.195 39.085 -0.058 c
+38.827 -0.305 38.515 -0.426 38.144 -0.426 c
+37.651 -0.426 37.277 -0.276 37.012 0.029 c
+36.755 0.341 36.63 0.809 36.63 1.426 c
+36.63 1.867 l
+36.63 2.462 36.755 2.918 37.012 3.234 c
+37.277 3.547 37.651 3.705 38.144 3.705 c
+38.545 3.705 38.864 3.572 39.099 3.308 c
+39.342 3.05 39.474 2.705 39.496 2.263 c
+38.879 2.263 l
+38.857 2.558 38.784 2.778 38.659 2.926 c
+38.541 3.072 38.368 3.146 38.144 3.146 c
+37.85 3.146 37.633 3.046 37.497 2.851 c
+37.358 2.664 37.284 2.356 37.277 1.926 c
+37.277 1.411 l
+37.277 0.941 37.343 0.607 37.483 0.412 c
+37.63 0.224 37.85 0.133 38.144 0.133 c
+40.893 3.219 m
+41.146 3.543 41.466 3.705 41.848 3.705 c
+42.553 3.705 42.91 3.234 42.921 2.294 c
+42.921 -0.353 l
+42.274 -0.353 l
+42.274 2.263 l
+42.274 2.576 42.219 2.797 42.113 2.926 c
+42.002 3.05 41.848 3.117 41.643 3.117 c
+41.485 3.117 41.337 3.061 41.202 2.955 c
+41.073 2.845 40.97 2.708 40.893 2.543 c
+40.893 -0.353 l
+40.246 -0.353 l
+40.246 5.292 l
+40.893 5.292 l
+h
+45.919 -0.353 m
+45.879 -0.264 45.854 -0.118 45.846 0.088 c
+45.611 -0.257 45.317 -0.426 44.965 -0.426 c
+44.6 -0.426 44.317 -0.33 44.112 -0.132 c
+43.914 0.073 43.818 0.36 43.818 0.735 c
+43.818 1.135 43.954 1.455 44.23 1.691 c
+44.502 1.933 44.876 2.058 45.346 2.058 c
+45.832 2.058 l
+45.832 2.484 l
+45.832 2.72 45.776 2.885 45.67 2.984 c
+45.56 3.09 45.398 3.146 45.185 3.146 c
+44.986 3.146 44.824 3.087 44.7 2.969 c
+44.583 2.851 44.523 2.705 44.523 2.529 c
+43.877 2.529 l
+43.877 2.723 43.935 2.914 44.053 3.102 c
+44.178 3.285 44.34 3.433 44.538 3.543 c
+44.743 3.649 44.972 3.705 45.229 3.705 c
+45.63 3.705 45.934 3.601 46.14 3.396 c
+46.353 3.19 46.468 2.896 46.478 2.514 c
+46.478 0.5 l
+46.478 0.195 46.515 -0.07 46.596 -0.293 c
+46.596 -0.353 l
+h
+45.053 0.162 m
+45.218 0.162 45.369 0.206 45.508 0.294 c
+45.655 0.382 45.762 0.493 45.832 0.632 c
+45.832 1.573 l
+45.464 1.573 l
+45.148 1.573 44.905 1.503 44.729 1.367 c
+44.552 1.239 44.465 1.051 44.465 0.809 c
+44.465 0.58 44.508 0.416 44.597 0.309 c
+44.685 0.21 44.836 0.162 45.053 0.162 c
+48.095 3.631 m
+48.11 3.19 l
+48.363 3.532 48.687 3.705 49.08 3.705 c
+49.786 3.705 50.142 3.234 50.153 2.294 c
+50.153 -0.353 l
+49.506 -0.353 l
+49.506 2.263 l
+49.506 2.576 49.451 2.797 49.345 2.926 c
+49.235 3.05 49.08 3.117 48.874 3.117 c
+48.716 3.117 48.569 3.061 48.433 2.955 c
+48.305 2.845 48.202 2.708 48.124 2.543 c
+48.124 -0.353 l
+47.478 -0.353 l
+47.478 3.631 l
+h
+50.991 1.823 m
+50.991 2.44 51.101 2.903 51.329 3.219 c
+51.553 3.543 51.887 3.705 52.329 3.705 c
+52.729 3.705 53.034 3.528 53.24 3.175 c
+53.284 3.631 l
+53.872 3.631 l
+53.872 -0.397 l
+53.872 -0.885 53.743 -1.264 53.49 -1.529 c
+53.233 -1.793 52.88 -1.926 52.431 -1.926 c
+52.233 -1.926 52.013 -1.874 51.77 -1.778 c
+51.523 -1.679 51.344 -1.558 51.226 -1.411 c
+51.49 -0.97 l
+51.756 -1.234 52.053 -1.367 52.387 -1.367 c
+52.924 -1.367 53.2 -1.072 53.21 -0.484 c
+53.21 0.044 l
+53.005 -0.272 52.703 -0.426 52.314 -0.426 c
+51.902 -0.426 51.579 -0.276 51.344 0.029 c
+51.116 0.341 50.998 0.794 50.991 1.382 c
+h
+51.652 1.44 m
+51.652 1 51.715 0.669 51.843 0.456 c
+51.968 0.25 52.186 0.147 52.49 0.147 c
+52.814 0.147 53.053 0.312 53.21 0.647 c
+53.21 2.631 l
+53.042 2.955 52.803 3.117 52.49 3.117 c
+52.196 3.117 51.98 3.013 51.843 2.808 c
+51.715 2.602 51.652 2.279 51.652 1.837 c
+h
+56.253 -0.426 m
+55.754 -0.426 55.371 -0.279 55.107 0.015 c
+54.842 0.309 54.71 0.742 54.71 1.323 c
+54.71 1.793 l
+54.71 2.389 54.835 2.855 55.092 3.19 c
+55.357 3.532 55.717 3.705 56.18 3.705 c
+56.639 3.705 56.981 3.55 57.208 3.248 c
+57.443 2.955 57.565 2.492 57.576 1.867 c
+57.576 1.44 l
+55.357 1.44 l
+55.357 1.353 l
+55.357 0.919 55.434 0.607 55.592 0.412 c
+55.757 0.224 55.989 0.133 56.283 0.133 c
+56.477 0.133 56.65 0.166 56.797 0.235 c
+56.944 0.312 57.08 0.43 57.208 0.588 c
+57.547 0.177 l
+57.26 -0.228 56.83 -0.426 56.253 -0.426 c
+56.18 3.146 m
+55.904 3.146 55.702 3.05 55.577 2.866 c
+55.448 2.679 55.375 2.389 55.357 1.999 c
+56.93 1.999 l
+56.93 2.088 l
+56.907 2.469 56.841 2.738 56.724 2.896 c
+56.606 3.061 56.423 3.146 56.18 3.146 c
+60.296 0.661 m
+60.296 0.809 60.24 0.929 60.134 1.029 c
+60.024 1.124 59.818 1.242 59.517 1.382 c
+59.171 1.529 58.929 1.65 58.781 1.75 c
+58.634 1.856 58.524 1.974 58.458 2.103 c
+58.388 2.227 58.355 2.385 58.355 2.573 c
+58.355 2.896 58.473 3.164 58.708 3.381 c
+58.943 3.594 59.245 3.705 59.619 3.705 c
+60.001 3.705 60.31 3.591 60.545 3.366 c
+60.78 3.138 60.898 2.851 60.898 2.499 c
+60.252 2.499 l
+60.252 2.675 60.192 2.826 60.075 2.955 c
+59.957 3.08 59.803 3.146 59.619 3.146 c
+59.421 3.146 59.27 3.09 59.164 2.984 c
+59.053 2.885 59.002 2.753 59.002 2.587 c
+59.002 2.458 59.039 2.352 59.12 2.263 c
+59.197 2.183 59.388 2.08 59.693 1.955 c
+60.171 1.768 60.501 1.58 60.678 1.397 c
+60.854 1.22 60.942 0.992 60.942 0.721 c
+60.942 0.368 60.817 0.088 60.575 -0.118 c
+60.34 -0.324 60.024 -0.426 59.634 -0.426 c
+59.211 -0.426 58.873 -0.309 58.619 -0.073 c
+58.363 0.169 58.237 0.474 58.237 0.838 c
+58.885 0.838 l
+58.892 0.611 58.962 0.434 59.09 0.309 c
+59.215 0.191 59.399 0.133 59.634 0.133 c
+59.847 0.133 60.009 0.181 60.119 0.279 c
+60.236 0.375 60.296 0.503 60.296 0.661 c
+61.824 0 m
+61.824 0.118 61.857 0.214 61.927 0.294 c
+61.993 0.372 62.096 0.412 62.236 0.412 c
+62.382 0.412 62.49 0.372 62.559 0.294 c
+62.636 0.214 62.677 0.118 62.677 0 c
+62.677 -0.11 62.636 -0.202 62.559 -0.279 c
+62.49 -0.357 62.382 -0.397 62.236 -0.397 c
+62.096 -0.397 61.993 -0.357 61.927 -0.279 c
+61.857 -0.202 61.824 -0.11 61.824 0 c
+66.602 1.338 m
+66.675 0.735 l
+66.777 1.264 l
+67.631 4.998 l
+68.189 4.998 l
+69.027 1.264 l
+69.129 0.721 l
+69.203 1.338 l
+69.865 4.998 l
+70.54 4.998 l
+69.468 -0.353 l
+68.865 -0.353 l
+67.968 3.543 l
+67.909 3.866 l
+67.866 3.543 l
+66.939 -0.353 l
+66.322 -0.353 l
+65.264 4.998 l
+65.94 4.998 l
+h
+71.864 3.219 m
+72.117 3.543 72.437 3.705 72.819 3.705 c
+73.524 3.705 73.881 3.234 73.892 2.294 c
+73.892 -0.353 l
+73.245 -0.353 l
+73.245 2.263 l
+73.245 2.576 73.19 2.797 73.083 2.926 c
+72.973 3.05 72.819 3.117 72.613 3.117 c
+72.455 3.117 72.308 3.061 72.173 2.955 c
+72.044 2.845 71.941 2.708 71.864 2.543 c
+71.864 -0.353 l
+71.217 -0.353 l
+71.217 5.292 l
+71.864 5.292 l
+h
+76.273 -0.426 m
+75.774 -0.426 75.392 -0.279 75.126 0.015 c
+74.862 0.309 74.73 0.742 74.73 1.323 c
+74.73 1.793 l
+74.73 2.389 74.855 2.855 75.112 3.19 c
+75.377 3.532 75.737 3.705 76.2 3.705 c
+76.659 3.705 77.001 3.55 77.229 3.248 c
+77.464 2.955 77.586 2.492 77.596 1.867 c
+77.596 1.44 l
+75.377 1.44 l
+75.377 1.353 l
+75.377 0.919 75.454 0.607 75.612 0.412 c
+75.777 0.224 76.009 0.133 76.302 0.133 c
+76.497 0.133 76.67 0.166 76.817 0.235 c
+76.964 0.312 77.1 0.43 77.229 0.588 c
+77.567 0.177 l
+77.28 -0.228 76.85 -0.426 76.273 -0.426 c
+76.2 3.146 m
+75.924 3.146 75.722 3.05 75.597 2.866 c
+75.469 2.679 75.396 2.389 75.377 1.999 c
+76.95 1.999 l
+76.95 2.088 l
+76.927 2.469 76.861 2.738 76.744 2.896 c
+76.626 3.061 76.443 3.146 76.2 3.146 c
+78.993 3.631 m
+79.007 3.19 l
+79.261 3.532 79.585 3.705 79.978 3.705 c
+80.683 3.705 81.04 3.234 81.05 2.294 c
+81.05 -0.353 l
+80.404 -0.353 l
+80.404 2.263 l
+80.404 2.576 80.349 2.797 80.242 2.926 c
+80.132 3.05 79.978 3.117 79.772 3.117 c
+79.614 3.117 79.467 3.061 79.331 2.955 c
+79.202 2.845 79.099 2.708 79.022 2.543 c
+79.022 -0.353 l
+78.375 -0.353 l
+78.375 3.631 l
+h
+f
+Q
+396.523 277.071 -1.794 0.866 re
+399.256 277.071 -1.793 0.866 re
+401.138 278.835 m
+401.362 279.117 401.637 279.261 401.961 279.261 c
+402.321 279.261 402.597 279.132 402.784 278.878 c
+402.979 278.622 403.078 278.24 403.078 277.733 c
+403.078 275.204 l
+402.034 275.204 l
+402.034 277.718 l
+402.034 277.953 401.994 278.118 401.917 278.217 c
+401.847 278.324 401.733 278.379 401.579 278.379 c
+401.391 278.379 401.244 278.294 401.138 278.13 c
+401.138 275.204 l
+400.094 275.204 l
+400.094 280.848 l
+401.138 280.848 l
+h
+405.709 275.204 m
+405.68 275.263 405.651 275.366 405.62 275.512 c
+405.433 275.256 405.184 275.131 404.872 275.131 c
+404.537 275.131 404.257 275.237 404.033 275.454 c
+403.817 275.678 403.71 275.969 403.71 276.322 c
+403.71 276.733 403.842 277.049 404.107 277.276 c
+404.371 277.512 404.754 277.629 405.254 277.629 c
+405.577 277.629 l
+405.577 277.953 l
+405.577 278.13 405.54 278.25 405.474 278.321 c
+405.415 278.398 405.327 278.438 405.209 278.438 c
+404.952 278.438 404.827 278.284 404.827 277.982 c
+403.783 277.982 l
+403.783 278.354 403.92 278.658 404.195 278.893 c
+404.467 279.136 404.816 279.261 405.238 279.261 c
+405.68 279.261 406.017 279.144 406.253 278.909 c
+406.495 278.68 406.62 278.357 406.62 277.938 c
+406.62 276.071 l
+406.62 275.726 406.668 275.458 406.767 275.263 c
+406.767 275.204 l
+h
+405.107 275.954 m
+405.213 275.954 405.305 275.972 405.385 276.013 c
+405.474 276.06 405.537 276.119 405.577 276.189 c
+405.577 277.012 l
+405.327 277.012 l
+405.15 277.012 405.007 276.954 404.901 276.836 c
+404.801 276.725 404.754 276.578 404.754 276.395 c
+404.754 276.1 404.872 275.954 405.107 275.954 c
+409.325 278.173 m
+408.987 278.203 l
+408.7 278.203 408.509 278.078 408.413 277.835 c
+408.413 275.204 l
+407.37 275.204 l
+407.37 279.188 l
+408.34 279.188 l
+408.369 278.747 l
+408.535 279.088 408.766 279.261 409.061 279.261 c
+409.178 279.261 409.27 279.239 409.34 279.202 c
+h
+409.649 277.321 m
+409.649 277.968 409.755 278.452 409.971 278.776 c
+410.196 279.1 410.519 279.261 410.942 279.261 c
+411.255 279.261 411.508 279.129 411.706 278.864 c
+411.706 280.848 l
+412.764 280.848 l
+412.764 275.204 l
+411.81 275.204 l
+411.765 275.616 l
+411.548 275.292 411.272 275.131 410.942 275.131 c
+410.53 275.131 410.21 275.285 409.986 275.601 c
+409.77 275.924 409.656 276.395 409.649 277.012 c
+h
+410.692 277.056 m
+410.692 276.663 410.729 276.387 410.81 276.233 c
+410.898 276.075 411.045 275.998 411.251 275.998 c
+411.457 275.998 411.607 276.09 411.706 276.277 c
+411.706 278.085 l
+411.607 278.28 411.457 278.379 411.251 278.379 c
+411.052 278.379 410.912 278.298 410.825 278.144 c
+410.736 277.997 410.692 277.725 410.692 277.336 c
+h
+f
+416.057 275.204 -0.646 3.984 re
+416.101 280.231 m
+416.101 280.121 416.072 280.029 416.013 279.952 c
+415.954 279.882 415.858 279.849 415.733 279.849 c
+415.616 279.849 415.521 279.882 415.455 279.952 c
+415.396 280.029 415.366 280.121 415.366 280.231 c
+415.366 280.349 415.396 280.441 415.455 280.511 c
+415.521 280.588 415.616 280.628 415.733 280.628 c
+415.858 280.628 415.954 280.588 416.013 280.511 c
+416.072 280.43 416.101 280.337 416.101 280.231 c
+419.012 276.218 m
+419.012 276.366 418.956 276.486 418.85 276.586 c
+418.74 276.681 418.534 276.798 418.233 276.939 c
+417.888 277.085 417.645 277.207 417.497 277.306 c
+417.35 277.413 417.24 277.53 417.175 277.659 c
+417.104 277.783 417.071 277.941 417.071 278.13 c
+417.071 278.452 417.189 278.72 417.424 278.938 c
+417.659 279.15 417.961 279.261 418.335 279.261 c
+418.717 279.261 419.026 279.147 419.261 278.923 c
+419.496 278.695 419.614 278.408 419.614 278.055 c
+418.968 278.055 l
+418.968 278.232 418.908 278.383 418.791 278.512 c
+418.673 278.637 418.519 278.703 418.335 278.703 c
+418.137 278.703 417.986 278.647 417.88 278.541 c
+417.77 278.442 417.718 278.309 417.718 278.144 c
+417.718 278.015 417.755 277.909 417.836 277.82 c
+417.913 277.739 418.104 277.637 418.409 277.512 c
+418.887 277.324 419.218 277.137 419.394 276.954 c
+419.571 276.777 419.658 276.549 419.658 276.277 c
+419.658 275.924 419.534 275.645 419.291 275.439 c
+419.056 275.233 418.74 275.131 418.35 275.131 c
+417.928 275.131 417.589 275.248 417.336 275.483 c
+417.079 275.726 416.954 276.031 416.954 276.395 c
+417.601 276.395 l
+417.608 276.167 417.678 275.99 417.807 275.865 c
+417.931 275.748 418.115 275.689 418.35 275.689 c
+418.563 275.689 418.725 275.737 418.835 275.836 c
+418.953 275.932 419.012 276.06 419.012 276.218 c
+424.244 275.557 m
+424.028 275.27 423.716 275.131 423.303 275.131 c
+422.94 275.131 422.665 275.252 422.48 275.498 c
+422.304 275.751 422.208 276.115 422.201 276.586 c
+422.201 279.188 l
+422.848 279.188 l
+422.848 276.644 l
+422.848 276.016 423.032 275.703 423.407 275.703 c
+423.808 275.703 424.082 275.88 424.23 276.233 c
+424.23 279.188 l
+424.876 279.188 l
+424.876 275.204 l
+424.259 275.204 l
+h
+427.802 276.218 m
+427.802 276.366 427.747 276.486 427.64 276.586 c
+427.53 276.681 427.324 276.798 427.022 276.939 c
+426.677 277.085 426.434 277.207 426.288 277.306 c
+426.141 277.413 426.031 277.53 425.964 277.659 c
+425.894 277.783 425.861 277.941 425.861 278.13 c
+425.861 278.452 425.979 278.72 426.214 278.938 c
+426.449 279.15 426.75 279.261 427.126 279.261 c
+427.508 279.261 427.816 279.147 428.051 278.923 c
+428.287 278.695 428.404 278.408 428.404 278.055 c
+427.758 278.055 l
+427.758 278.232 427.699 278.383 427.581 278.512 c
+427.463 278.637 427.309 278.703 427.126 278.703 c
+426.927 278.703 426.777 278.647 426.669 278.541 c
+426.559 278.442 426.509 278.309 426.509 278.144 c
+426.509 278.015 426.545 277.909 426.626 277.82 c
+426.703 277.739 426.894 277.637 427.199 277.512 c
+427.677 277.324 428.007 277.137 428.184 276.954 c
+428.36 276.777 428.448 276.549 428.448 276.277 c
+428.448 275.924 428.323 275.645 428.081 275.439 c
+427.845 275.233 427.53 275.131 427.14 275.131 c
+426.717 275.131 426.38 275.248 426.126 275.483 c
+425.869 275.726 425.744 276.031 425.744 276.395 c
+426.391 276.395 l
+426.398 276.167 426.468 275.99 426.596 275.865 c
+426.721 275.748 426.905 275.689 427.14 275.689 c
+427.353 275.689 427.515 275.737 427.625 275.836 c
+427.743 275.932 427.802 276.06 427.802 276.218 c
+430.712 275.131 m
+430.212 275.131 429.83 275.277 429.566 275.572 c
+429.301 275.865 429.169 276.299 429.169 276.879 c
+429.169 277.35 l
+429.169 277.945 429.294 278.412 429.551 278.747 c
+429.815 279.088 430.176 279.261 430.638 279.261 c
+431.098 279.261 431.44 279.107 431.668 278.805 c
+431.903 278.512 432.024 278.049 432.035 277.424 c
+432.035 276.997 l
+429.815 276.997 l
+429.815 276.909 l
+429.815 276.476 429.892 276.163 430.05 275.969 c
+430.216 275.781 430.447 275.689 430.742 275.689 c
+430.937 275.689 431.109 275.722 431.256 275.792 c
+431.403 275.869 431.539 275.987 431.668 276.145 c
+432.005 275.734 l
+431.719 275.329 431.289 275.131 430.712 275.131 c
+430.638 278.703 m
+430.363 278.703 430.161 278.607 430.036 278.423 c
+429.908 278.236 429.834 277.945 429.815 277.556 c
+431.388 277.556 l
+431.388 277.644 l
+431.367 278.026 431.3 278.294 431.182 278.452 c
+431.065 278.618 430.881 278.703 430.638 278.703 c
+432.682 277.38 m
+432.682 277.986 432.792 278.452 433.019 278.776 c
+433.255 279.1 433.582 279.261 434.004 279.261 c
+434.387 279.261 434.685 279.103 434.901 278.791 c
+434.901 280.848 l
+435.548 280.848 l
+435.548 275.204 l
+434.96 275.204 l
+434.916 275.63 l
+434.71 275.296 434.405 275.131 434.004 275.131 c
+433.593 275.131 433.27 275.285 433.035 275.601 c
+432.799 275.924 432.682 276.38 432.682 276.968 c
+h
+433.329 276.997 m
+433.329 276.557 433.391 276.226 433.52 276.013 c
+433.655 275.807 433.876 275.703 434.181 275.703 c
+434.505 275.703 434.743 275.865 434.901 276.189 c
+434.901 278.203 l
+434.733 278.515 434.494 278.673 434.181 278.673 c
+433.876 278.673 433.655 278.57 433.52 278.365 c
+433.391 278.159 433.329 277.835 433.329 277.394 c
+h
+436.562 274.131 m
+436.165 274.396 l
+436.4 274.719 436.522 275.053 436.533 275.395 c
+436.533 276.013 l
+437.194 276.013 l
+437.194 275.483 l
+437.194 275.226 437.129 274.98 437.003 274.734 c
+436.886 274.491 436.739 274.289 436.562 274.131 c
+441.796 275.204 m
+441.755 275.292 441.729 275.439 441.721 275.645 c
+441.486 275.3 441.193 275.131 440.84 275.131 c
+440.476 275.131 440.193 275.226 439.988 275.425 c
+439.789 275.63 439.693 275.917 439.693 276.291 c
+439.693 276.692 439.829 277.012 440.105 277.247 c
+440.377 277.49 440.751 277.615 441.222 277.615 c
+441.707 277.615 l
+441.707 278.041 l
+441.707 278.276 441.652 278.442 441.545 278.541 c
+441.435 278.647 441.273 278.703 441.06 278.703 c
+440.861 278.703 440.701 278.643 440.575 278.526 c
+440.458 278.408 440.399 278.261 440.399 278.085 c
+439.752 278.085 l
+439.752 278.28 439.811 278.471 439.928 278.658 c
+440.053 278.842 440.215 278.989 440.414 279.1 c
+440.62 279.206 440.847 279.261 441.104 279.261 c
+441.505 279.261 441.81 279.158 442.016 278.953 c
+442.229 278.747 442.343 278.452 442.353 278.07 c
+442.353 276.056 l
+442.353 275.751 442.39 275.487 442.471 275.263 c
+442.471 275.204 l
+h
+440.928 275.718 m
+441.093 275.718 441.244 275.763 441.384 275.851 c
+441.53 275.939 441.638 276.05 441.707 276.189 c
+441.707 277.13 l
+441.339 277.13 l
+441.023 277.13 440.781 277.06 440.605 276.924 c
+440.428 276.796 440.34 276.607 440.34 276.366 c
+440.34 276.137 440.384 275.972 440.472 275.865 c
+440.56 275.766 440.711 275.718 440.928 275.718 c
+444.059 275.204 -0.647 5.644 re
+445.779 275.204 -0.647 5.644 re
+449.894 275.689 m
+450.108 275.689 450.28 275.751 450.409 275.88 c
+450.544 276.016 450.619 276.208 450.629 276.453 c
+451.246 276.453 l
+451.225 276.071 451.089 275.751 450.835 275.498 c
+450.578 275.252 450.265 275.131 449.894 275.131 c
+449.402 275.131 449.027 275.281 448.763 275.586 c
+448.505 275.898 448.381 276.366 448.381 276.983 c
+448.381 277.424 l
+448.381 278.019 448.505 278.475 448.763 278.791 c
+449.027 279.103 449.402 279.261 449.894 279.261 c
+450.295 279.261 450.615 279.129 450.85 278.864 c
+451.092 278.607 451.225 278.261 451.246 277.82 c
+450.629 277.82 l
+450.608 278.115 450.534 278.335 450.409 278.482 c
+450.291 278.629 450.118 278.703 449.894 278.703 c
+449.6 278.703 449.384 278.603 449.247 278.408 c
+449.108 278.221 449.035 277.912 449.027 277.482 c
+449.027 276.968 l
+449.027 276.497 449.093 276.163 449.233 275.969 c
+449.38 275.781 449.6 275.689 449.894 275.689 c
+452.643 278.776 m
+452.896 279.1 453.216 279.261 453.598 279.261 c
+454.304 279.261 454.66 278.791 454.672 277.85 c
+454.672 275.204 l
+454.025 275.204 l
+454.025 277.82 l
+454.025 278.132 453.97 278.354 453.863 278.482 c
+453.753 278.607 453.598 278.673 453.393 278.673 c
+453.235 278.673 453.087 278.618 452.952 278.512 c
+452.823 278.401 452.72 278.265 452.643 278.099 c
+452.643 275.204 l
+451.996 275.204 l
+451.996 280.848 l
+452.643 280.848 l
+h
+457.671 275.204 m
+457.63 275.292 457.604 275.439 457.596 275.645 c
+457.361 275.3 457.068 275.131 456.715 275.131 c
+456.351 275.131 456.068 275.226 455.862 275.425 c
+455.664 275.63 455.568 275.917 455.568 276.291 c
+455.568 276.692 455.704 277.012 455.98 277.247 c
+456.252 277.49 456.626 277.615 457.097 277.615 c
+457.582 277.615 l
+457.582 278.041 l
+457.582 278.276 457.527 278.442 457.42 278.541 c
+457.31 278.647 457.148 278.703 456.935 278.703 c
+456.736 278.703 456.576 278.643 456.45 278.526 c
+456.333 278.408 456.274 278.261 456.274 278.085 c
+455.627 278.085 l
+455.627 278.28 455.686 278.471 455.803 278.658 c
+455.928 278.842 456.09 278.989 456.289 279.1 c
+456.495 279.206 456.722 279.261 456.979 279.261 c
+457.38 279.261 457.685 279.158 457.891 278.953 c
+458.104 278.747 458.218 278.452 458.228 278.07 c
+458.228 276.056 l
+458.228 275.751 458.265 275.487 458.346 275.263 c
+458.346 275.204 l
+h
+456.803 275.718 m
+456.969 275.718 457.119 275.763 457.259 275.851 c
+457.405 275.939 457.513 276.05 457.582 276.189 c
+457.582 277.13 l
+457.214 277.13 l
+456.898 277.13 456.656 277.06 456.48 276.924 c
+456.303 276.796 456.215 276.607 456.215 276.366 c
+456.215 276.137 456.259 275.972 456.347 275.865 c
+456.435 275.766 456.586 275.718 456.803 275.718 c
+459.846 279.188 m
+459.861 278.747 l
+460.114 279.088 460.437 279.261 460.831 279.261 c
+461.536 279.261 461.893 278.791 461.904 277.85 c
+461.904 275.204 l
+461.257 275.204 l
+461.257 277.82 l
+461.257 278.132 461.202 278.354 461.095 278.482 c
+460.985 278.607 460.831 278.673 460.625 278.673 c
+460.466 278.673 460.32 278.618 460.183 278.512 c
+460.055 278.401 459.952 278.265 459.875 278.099 c
+459.875 275.204 l
+459.228 275.204 l
+459.228 279.188 l
+h
+462.741 277.38 m
+462.741 277.997 462.851 278.46 463.08 278.776 c
+463.304 279.1 463.638 279.261 464.079 279.261 c
+464.48 279.261 464.784 279.084 464.99 278.732 c
+465.035 279.188 l
+465.623 279.188 l
+465.623 275.16 l
+465.623 274.671 465.494 274.292 465.24 274.028 c
+464.983 273.764 464.63 273.631 464.181 273.631 c
+463.984 273.631 463.763 273.683 463.52 273.779 c
+463.275 273.877 463.094 273.999 462.976 274.146 c
+463.241 274.587 l
+463.506 274.322 463.803 274.19 464.138 274.19 c
+464.674 274.19 464.95 274.484 464.961 275.072 c
+464.961 275.601 l
+464.755 275.285 464.454 275.131 464.064 275.131 c
+463.653 275.131 463.329 275.281 463.094 275.586 c
+462.866 275.898 462.749 276.351 462.741 276.939 c
+h
+463.403 276.997 m
+463.403 276.557 463.466 276.226 463.594 276.013 c
+463.719 275.807 463.936 275.703 464.241 275.703 c
+464.564 275.703 464.803 275.869 464.961 276.204 c
+464.961 278.188 l
+464.792 278.512 464.553 278.673 464.241 278.673 c
+463.946 278.673 463.73 278.57 463.594 278.365 c
+463.466 278.159 463.403 277.835 463.403 277.394 c
+h
+468.004 275.131 m
+467.504 275.131 467.121 275.277 466.857 275.572 c
+466.593 275.865 466.46 276.299 466.46 276.879 c
+466.46 277.35 l
+466.46 277.945 466.585 278.412 466.843 278.747 c
+467.107 279.088 467.467 279.261 467.93 279.261 c
+468.389 279.261 468.731 279.107 468.959 278.805 c
+469.195 278.512 469.315 278.049 469.326 277.424 c
+469.326 276.997 l
+467.107 276.997 l
+467.107 276.909 l
+467.107 276.476 467.184 276.163 467.342 275.969 c
+467.508 275.781 467.739 275.689 468.033 275.689 c
+468.228 275.689 468.401 275.722 468.547 275.792 c
+468.694 275.869 468.831 275.987 468.959 276.145 c
+469.297 275.734 l
+469.01 275.329 468.58 275.131 468.004 275.131 c
+467.93 278.703 m
+467.655 278.703 467.452 278.607 467.327 278.423 c
+467.198 278.236 467.125 277.945 467.107 277.556 c
+468.68 277.556 l
+468.68 277.644 l
+468.658 278.026 468.592 278.294 468.474 278.452 c
+468.356 278.618 468.173 278.703 467.93 278.703 c
+472.046 276.218 m
+472.046 276.366 471.991 276.486 471.884 276.586 c
+471.774 276.681 471.568 276.798 471.267 276.939 c
+470.922 277.085 470.679 277.207 470.531 277.306 c
+470.385 277.413 470.275 277.53 470.209 277.659 c
+470.139 277.783 470.105 277.941 470.105 278.13 c
+470.105 278.452 470.223 278.72 470.458 278.938 c
+470.693 279.15 470.995 279.261 471.37 279.261 c
+471.752 279.261 472.06 279.147 472.295 278.923 c
+472.531 278.695 472.648 278.408 472.648 278.055 c
+472.002 278.055 l
+472.002 278.232 471.943 278.383 471.825 278.512 c
+471.707 278.637 471.553 278.703 471.37 278.703 c
+471.171 278.703 471.021 278.647 470.914 278.541 c
+470.804 278.442 470.753 278.309 470.753 278.144 c
+470.753 278.015 470.789 277.909 470.87 277.82 c
+470.947 277.739 471.138 277.637 471.443 277.512 c
+471.921 277.324 472.252 277.137 472.428 276.954 c
+472.605 276.777 472.692 276.549 472.692 276.277 c
+472.692 275.924 472.568 275.645 472.325 275.439 c
+472.09 275.233 471.774 275.131 471.385 275.131 c
+470.961 275.131 470.624 275.248 470.371 275.483 c
+470.113 275.726 469.988 276.031 469.988 276.395 c
+470.635 276.395 l
+470.642 276.167 470.712 275.99 470.841 275.865 c
+470.965 275.748 471.15 275.689 471.385 275.689 c
+471.597 275.689 471.759 275.737 471.869 275.836 c
+471.987 275.932 472.046 276.06 472.046 276.218 c
+477.293 275.204 m
+477.253 275.292 477.228 275.439 477.22 275.645 c
+476.985 275.3 476.69 275.131 476.338 275.131 c
+475.975 275.131 475.691 275.226 475.485 275.425 c
+475.287 275.63 475.192 275.917 475.192 276.291 c
+475.192 276.692 475.327 277.012 475.603 277.247 c
+475.875 277.49 476.25 277.615 476.721 277.615 c
+477.205 277.615 l
+477.205 278.041 l
+477.205 278.276 477.15 278.442 477.043 278.541 c
+476.933 278.647 476.771 278.703 476.559 278.703 c
+476.36 278.703 476.198 278.643 476.073 278.526 c
+475.956 278.408 475.897 278.261 475.897 278.085 c
+475.25 278.085 l
+475.25 278.28 475.309 278.471 475.427 278.658 c
+475.551 278.842 475.713 278.989 475.912 279.1 c
+476.118 279.206 476.345 279.261 476.603 279.261 c
+477.003 279.261 477.309 279.158 477.514 278.953 c
+477.727 278.747 477.841 278.452 477.852 278.07 c
+477.852 276.056 l
+477.852 275.751 477.889 275.487 477.97 275.263 c
+477.97 275.204 l
+h
+476.426 275.718 m
+476.592 275.718 476.742 275.763 476.881 275.851 c
+477.029 275.939 477.135 276.05 477.205 276.189 c
+477.205 277.13 l
+476.838 277.13 l
+476.522 277.13 476.279 277.06 476.103 276.924 c
+475.927 276.796 475.838 276.607 475.838 276.366 c
+475.838 276.137 475.882 275.972 475.971 275.865 c
+476.058 275.766 476.21 275.718 476.426 275.718 c
+480.498 278.57 m
+480.409 278.589 480.31 278.6 480.204 278.6 c
+479.869 278.6 479.634 278.416 479.499 278.055 c
+479.499 275.204 l
+478.851 275.204 l
+478.851 279.188 l
+479.484 279.188 l
+479.499 278.776 l
+479.674 279.1 479.917 279.261 480.233 279.261 c
+480.34 279.261 480.428 279.239 480.498 279.202 c
+h
+482.497 275.131 m
+481.997 275.131 481.615 275.277 481.35 275.572 c
+481.086 275.865 480.954 276.299 480.954 276.879 c
+480.954 277.35 l
+480.954 277.945 481.078 278.412 481.336 278.747 c
+481.6 279.088 481.96 279.261 482.423 279.261 c
+482.882 279.261 483.225 279.107 483.452 278.805 c
+483.688 278.512 483.809 278.049 483.819 277.424 c
+483.819 276.997 l
+481.6 276.997 l
+481.6 276.909 l
+481.6 276.476 481.677 276.163 481.835 275.969 c
+482.001 275.781 482.232 275.689 482.526 275.689 c
+482.721 275.689 482.894 275.722 483.04 275.792 c
+483.188 275.869 483.324 275.987 483.452 276.145 c
+483.79 275.734 l
+483.504 275.329 483.074 275.131 482.497 275.131 c
+482.423 278.703 m
+482.148 278.703 481.945 278.607 481.82 278.423 c
+481.692 278.236 481.619 277.945 481.6 277.556 c
+483.173 277.556 l
+483.173 277.644 l
+483.151 278.026 483.085 278.294 482.967 278.452 c
+482.849 278.618 482.666 278.703 482.423 278.703 c
+486.186 277.38 m
+486.186 277.986 486.296 278.452 486.524 278.776 c
+486.759 279.1 487.087 279.261 487.509 279.261 c
+487.892 279.261 488.189 279.103 488.405 278.791 c
+488.405 280.848 l
+489.053 280.848 l
+489.053 275.204 l
+488.465 275.204 l
+488.421 275.63 l
+488.215 275.296 487.91 275.131 487.509 275.131 c
+487.098 275.131 486.774 275.285 486.539 275.601 c
+486.304 275.924 486.186 276.38 486.186 276.968 c
+h
+486.833 276.997 m
+486.833 276.557 486.896 276.226 487.024 276.013 c
+487.16 275.807 487.381 275.703 487.686 275.703 c
+488.009 275.703 488.248 275.865 488.405 276.189 c
+488.405 278.203 l
+488.237 278.515 487.998 278.673 487.686 278.673 c
+487.381 278.673 487.16 278.57 487.024 278.365 c
+486.896 278.159 486.833 277.835 486.833 277.394 c
+h
+490.757 275.204 -0.646 3.984 re
+490.802 280.231 m
+490.802 280.121 490.772 280.029 490.714 279.952 c
+490.655 279.882 490.56 279.849 490.435 279.849 c
+490.317 279.849 490.221 279.882 490.155 279.952 c
+490.096 280.029 490.067 280.121 490.067 280.231 c
+490.067 280.349 490.096 280.441 490.155 280.511 c
+490.221 280.588 490.317 280.628 490.435 280.628 c
+490.56 280.628 490.655 280.588 490.714 280.511 c
+490.772 280.43 490.802 280.337 490.802 280.231 c
+493.712 276.218 m
+493.712 276.366 493.658 276.486 493.55 276.586 c
+493.44 276.681 493.234 276.798 492.933 276.939 c
+492.588 277.085 492.345 277.207 492.199 277.306 c
+492.051 277.413 491.941 277.53 491.875 277.659 c
+491.805 277.783 491.772 277.941 491.772 278.13 c
+491.772 278.452 491.89 278.72 492.125 278.938 c
+492.36 279.15 492.661 279.261 493.036 279.261 c
+493.419 279.261 493.727 279.147 493.962 278.923 c
+494.198 278.695 494.315 278.408 494.315 278.055 c
+493.668 278.055 l
+493.668 278.232 493.61 278.383 493.492 278.512 c
+493.374 278.637 493.22 278.703 493.036 278.703 c
+492.837 278.703 492.687 278.647 492.581 278.541 c
+492.47 278.442 492.419 278.309 492.419 278.144 c
+492.419 278.015 492.455 277.909 492.536 277.82 c
+492.613 277.739 492.804 277.637 493.109 277.512 c
+493.587 277.324 493.918 277.137 494.094 276.954 c
+494.271 276.777 494.359 276.549 494.359 276.277 c
+494.359 275.924 494.234 275.645 493.992 275.439 c
+493.756 275.233 493.44 275.131 493.051 275.131 c
+492.628 275.131 492.29 275.248 492.037 275.483 c
+491.779 275.726 491.655 276.031 491.655 276.395 c
+492.301 276.395 l
+492.309 276.167 492.378 275.99 492.507 275.865 c
+492.632 275.748 492.816 275.689 493.051 275.689 c
+493.264 275.689 493.425 275.737 493.536 275.836 c
+493.654 275.932 493.712 276.06 493.712 276.218 c
+496.579 275.689 m
+496.792 275.689 496.964 275.751 497.093 275.88 c
+497.229 276.016 497.302 276.208 497.313 276.453 c
+497.93 276.453 l
+497.909 276.071 497.772 275.751 497.519 275.498 c
+497.263 275.252 496.95 275.131 496.579 275.131 c
+496.087 275.131 495.711 275.281 495.447 275.586 c
+495.189 275.898 495.065 276.366 495.065 276.983 c
+495.065 277.424 l
+495.065 278.019 495.189 278.475 495.447 278.791 c
+495.711 279.103 496.087 279.261 496.579 279.261 c
+496.979 279.261 497.299 279.129 497.534 278.864 c
+497.776 278.607 497.909 278.261 497.93 277.82 c
+497.313 277.82 l
+497.292 278.115 497.218 278.335 497.093 278.482 c
+496.976 278.629 496.803 278.703 496.579 278.703 c
+496.284 278.703 496.068 278.603 495.931 278.408 c
+495.792 278.221 495.719 277.912 495.711 277.482 c
+495.711 276.968 l
+495.711 276.497 495.777 276.163 495.917 275.969 c
+496.064 275.781 496.284 275.689 496.579 275.689 c
+500.724 275.204 m
+500.683 275.292 500.658 275.439 500.65 275.645 c
+500.415 275.3 500.121 275.131 499.769 275.131 c
+499.405 275.131 499.121 275.226 498.915 275.425 c
+498.717 275.63 498.622 275.917 498.622 276.291 c
+498.622 276.692 498.757 277.012 499.033 277.247 c
+499.305 277.49 499.68 277.615 500.151 277.615 c
+500.635 277.615 l
+500.635 278.041 l
+500.635 278.276 500.581 278.442 500.474 278.541 c
+500.363 278.647 500.202 278.703 499.989 278.703 c
+499.79 278.703 499.628 278.643 499.503 278.526 c
+499.386 278.408 499.327 278.261 499.327 278.085 c
+498.68 278.085 l
+498.68 278.28 498.74 278.471 498.857 278.658 c
+498.982 278.842 499.144 278.989 499.342 279.1 c
+499.548 279.206 499.775 279.261 500.033 279.261 c
+500.434 279.261 500.739 279.158 500.945 278.953 c
+501.157 278.747 501.271 278.452 501.282 278.07 c
+501.282 276.056 l
+501.282 275.751 501.319 275.487 501.4 275.263 c
+501.4 275.204 l
+h
+499.856 275.718 m
+500.022 275.718 500.172 275.763 500.312 275.851 c
+500.459 275.939 500.565 276.05 500.635 276.189 c
+500.635 277.13 l
+500.268 277.13 l
+499.952 277.13 499.709 277.06 499.534 276.924 c
+499.357 276.796 499.268 276.607 499.268 276.366 c
+499.268 276.137 499.312 275.972 499.401 275.865 c
+499.489 275.766 499.64 275.718 499.856 275.718 c
+503.928 278.57 m
+503.84 278.589 503.74 278.6 503.634 278.6 c
+503.3 278.6 503.065 278.416 502.929 278.055 c
+502.929 275.204 l
+502.281 275.204 l
+502.281 279.188 l
+502.914 279.188 l
+502.929 278.776 l
+503.105 279.1 503.347 279.261 503.663 279.261 c
+503.771 279.261 503.858 279.239 503.928 279.202 c
+h
+504.369 277.38 m
+504.369 277.986 504.479 278.452 504.708 278.776 c
+504.943 279.1 505.269 279.261 505.692 279.261 c
+506.074 279.261 506.372 279.103 506.589 278.791 c
+506.589 280.848 l
+507.235 280.848 l
+507.235 275.204 l
+506.647 275.204 l
+506.603 275.63 l
+506.397 275.296 506.092 275.131 505.692 275.131 c
+505.28 275.131 504.957 275.285 504.722 275.601 c
+504.486 275.924 504.369 276.38 504.369 276.968 c
+h
+505.016 276.997 m
+505.016 276.557 505.078 276.226 505.207 276.013 c
+505.343 275.807 505.564 275.703 505.868 275.703 c
+506.192 275.703 506.431 275.865 506.589 276.189 c
+506.589 278.203 l
+506.42 278.515 506.181 278.673 505.868 278.673 c
+505.564 278.673 505.343 278.57 505.207 278.365 c
+505.078 278.159 505.016 277.835 505.016 277.394 c
+h
+509.661 275.131 m
+509.161 275.131 508.779 275.277 508.514 275.572 c
+508.249 275.865 508.118 276.299 508.118 276.879 c
+508.118 277.35 l
+508.118 277.945 508.242 278.412 508.5 278.747 c
+508.764 279.088 509.124 279.261 509.587 279.261 c
+510.046 279.261 510.389 279.107 510.616 278.805 c
+510.852 278.512 510.973 278.049 510.983 277.424 c
+510.983 276.997 l
+508.764 276.997 l
+508.764 276.909 l
+508.764 276.476 508.841 276.163 508.999 275.969 c
+509.165 275.781 509.396 275.689 509.69 275.689 c
+509.885 275.689 510.058 275.722 510.204 275.792 c
+510.352 275.869 510.487 275.987 510.616 276.145 c
+510.954 275.734 l
+510.668 275.329 510.237 275.131 509.661 275.131 c
+509.587 278.703 m
+509.312 278.703 509.109 278.607 508.984 278.423 c
+508.856 278.236 508.783 277.945 508.764 277.556 c
+510.337 277.556 l
+510.337 277.644 l
+510.315 278.026 510.249 278.294 510.131 278.452 c
+510.013 278.618 509.83 278.703 509.587 278.703 c
+511.63 277.38 m
+511.63 277.986 511.741 278.452 511.968 278.776 c
+512.203 279.1 512.531 279.261 512.953 279.261 c
+513.335 279.261 513.633 279.103 513.85 278.791 c
+513.85 280.848 l
+514.497 280.848 l
+514.497 275.204 l
+513.909 275.204 l
+513.865 275.63 l
+513.659 275.296 513.354 275.131 512.953 275.131 c
+512.542 275.131 512.218 275.285 511.983 275.601 c
+511.748 275.924 511.63 276.38 511.63 276.968 c
+h
+512.277 276.997 m
+512.277 276.557 512.34 276.226 512.469 276.013 c
+512.604 275.807 512.824 275.703 513.13 275.703 c
+513.453 275.703 513.692 275.865 513.85 276.189 c
+513.85 278.203 l
+513.681 278.515 513.442 278.673 513.13 278.673 c
+512.824 278.673 512.604 278.57 512.469 278.365 c
+512.34 278.159 512.277 277.835 512.277 277.394 c
+h
+515.54 275.557 m
+515.54 275.674 515.573 275.77 515.644 275.851 c
+515.71 275.928 515.812 275.969 515.952 275.969 c
+516.099 275.969 516.205 275.928 516.275 275.851 c
+516.352 275.77 516.392 275.674 516.392 275.557 c
+516.392 275.447 516.352 275.354 516.275 275.277 c
+516.205 275.2 516.099 275.16 515.952 275.16 c
+515.812 275.16 515.71 275.2 515.644 275.277 c
+515.573 275.354 515.54 275.447 515.54 275.557 c
+f
+0.113 0.082 0.09 0 k
+287.665 268.468 234.667 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 261.629 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.146 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.807 l
+-1.896 -1.807 l
+-1.896 -1.263 l
+-2.142 -1.256 -2.359 -1.219 -2.543 -1.161 c
+-2.719 -1.102 -2.873 -1.024 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.69 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.034 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.477 -2.234 -0.514 c
+-2.138 -0.554 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.662 l
+-1.907 0.662 -1.926 0.666 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.772 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.279 -3.219 1.426 c
+-3.289 1.573 -3.322 1.757 -3.322 1.985 c
+-3.322 2.18 -3.289 2.345 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.933 -2.645 3.003 -2.469 3.043 c
+-2.293 3.091 -2.102 3.12 -1.896 3.132 c
+-1.896 3.558 l
+-1.543 3.558 l
+-1.543 3.132 l
+-1.319 3.12 -1.128 3.091 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.735 -0.349 2.621 -0.279 2.484 c
+-0.202 2.345 -0.143 2.183 -0.103 1.999 c
+-0.941 1.882 l
+-1.01 2.253 -1.213 2.459 -1.543 2.5 c
+-1.543 1.368 l
+-1.514 1.368 l
+-1.506 1.368 -1.492 1.36 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.206 c
+-0.756 1.147 -0.595 1.066 -0.455 0.971 c
+-0.32 0.871 -0.213 0.743 -0.132 0.588 c
+-0.044 0.431 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.503 -2.113 2.484 -2.19 2.455 c
+-2.26 2.426 -2.319 2.386 -2.366 2.338 c
+-2.406 2.297 -2.436 2.249 -2.454 2.191 c
+-2.477 2.132 -2.484 2.066 -2.484 1.999 c
+-2.484 1.912 -2.469 1.838 -2.439 1.779 c
+-2.41 1.721 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.201 1.559 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.441 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.302 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.44 c
+-0.904 -0.345 -0.837 -0.201 -0.837 -0.014 c
+6.402 -2.66 m
+6.184 -2.66 5.993 -2.634 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.395 c
+5.284 -2.314 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.616 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.146 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.83 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.219 6.034 -1.219 c
+5.829 -1.219 5.644 -1.182 5.49 -1.102 c
+5.343 -1.014 5.215 -0.897 5.108 -0.749 c
+5.009 -0.595 4.935 -0.411 4.888 -0.205 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.772 4.836 1.019 4.888 1.235 c
+4.946 1.449 5.027 1.632 5.137 1.779 c
+5.244 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.264 6.093 2.264 c
+6.188 2.264 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.919 7.107 1.97 c
+7.115 2.029 7.122 2.077 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.151 2.22 c
+8.004 2.22 l
+7.993 2.139 7.982 2.029 7.975 1.882 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.414 7.938 -1.635 7.871 -1.822 c
+7.802 -2.006 7.699 -2.16 7.563 -2.278 c
+7.423 -2.403 7.258 -2.499 7.063 -2.557 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.743 7.067 0.919 7.019 1.058 c
+6.978 1.206 6.924 1.324 6.857 1.411 c
+6.799 1.5 6.729 1.559 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.368 c
+5.88 1.279 5.835 1.162 5.799 1.015 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.514 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.558 c
+6.725 -0.521 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.302 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.263 l
+8.86 -1.263 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.603 l
+9.199 1.603 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.597 1.603 m
+13.053 1.603 l
+13.053 2.22 l
+13.641 2.22 l
+13.92 3.117 l
+14.494 3.117 l
+14.494 2.22 l
+15.728 2.22 l
+15.728 1.603 l
+14.494 1.603 l
+14.494 -0.103 l
+14.494 -0.323 l
+14.501 -0.392 14.523 -0.455 14.552 -0.514 c
+14.589 -0.565 14.645 -0.61 14.714 -0.646 c
+14.791 -0.675 14.905 -0.69 15.052 -0.69 c
+15.188 -0.69 15.324 -0.687 15.464 -0.675 c
+15.599 -0.658 15.732 -0.631 15.861 -0.602 c
+15.861 -1.205 l
+15.78 -1.215 15.703 -1.23 15.626 -1.249 c
+15.545 -1.26 15.468 -1.267 15.391 -1.278 c
+15.31 -1.286 15.221 -1.294 15.125 -1.294 c
+15.038 -1.3 14.938 -1.308 14.832 -1.308 c
+14.645 -1.308 14.483 -1.294 14.346 -1.263 c
+14.218 -1.227 14.104 -1.182 14.009 -1.132 c
+13.92 -1.084 13.847 -1.024 13.788 -0.955 c
+13.729 -0.878 13.685 -0.801 13.656 -0.72 c
+13.627 -0.631 13.604 -0.544 13.597 -0.455 c
+13.586 -0.359 13.582 -0.264 13.582 -0.176 c
+h
+24.133 1.47 m
+24.033 1.478 23.931 1.489 23.823 1.5 c
+23.713 1.518 23.592 1.529 23.456 1.529 c
+23.28 1.529 23.121 1.489 22.986 1.411 c
+22.846 1.341 22.728 1.243 22.633 1.118 c
+22.545 0.989 22.475 0.842 22.427 0.676 c
+22.387 0.508 22.369 0.331 22.369 0.148 c
+22.369 -1.263 l
+21.471 -1.263 l
+21.471 0.985 l
+21.471 1.11 21.461 1.235 21.442 1.353 c
+21.432 1.478 21.417 1.595 21.398 1.706 c
+21.388 1.823 21.373 1.919 21.355 1.999 c
+21.332 2.087 21.314 2.161 21.296 2.22 c
+22.177 2.22 l
+22.185 2.168 22.196 2.117 22.207 2.058 c
+22.225 1.999 22.24 1.933 22.251 1.867 c
+22.269 1.808 22.284 1.742 22.296 1.676 c
+22.302 1.607 22.313 1.544 22.325 1.485 c
+22.339 1.485 l
+22.375 1.603 22.427 1.709 22.486 1.808 c
+22.552 1.904 22.633 1.989 22.722 2.058 c
+22.809 2.124 22.913 2.18 23.03 2.22 c
+23.155 2.257 23.302 2.278 23.471 2.278 c
+23.596 2.278 23.713 2.272 23.823 2.264 c
+23.942 2.253 24.044 2.238 24.133 2.22 c
+h
+26.738 -1.323 m
+26.481 -1.323 26.253 -1.286 26.047 -1.219 c
+25.841 -1.142 25.665 -1.028 25.518 -0.881 c
+25.371 -0.727 25.253 -0.536 25.165 -0.309 c
+25.084 -0.084 25.047 0.181 25.047 0.485 c
+25.047 0.817 25.091 1.096 25.18 1.324 c
+25.275 1.559 25.404 1.742 25.562 1.882 c
+25.727 2.018 25.915 2.117 26.121 2.176 c
+26.327 2.242 26.535 2.278 26.753 2.278 c
+27.025 2.278 27.26 2.228 27.458 2.132 c
+27.664 2.043 27.829 1.912 27.958 1.735 c
+28.094 1.566 28.193 1.36 28.252 1.118 c
+28.318 0.882 28.355 0.618 28.355 0.324 c
+28.355 0.31 l
+25.988 0.31 l
+25.988 0.162 26.003 0.023 26.032 -0.103 c
+26.069 -0.231 26.124 -0.345 26.194 -0.44 c
+26.26 -0.529 26.344 -0.598 26.444 -0.646 c
+26.539 -0.698 26.653 -0.72 26.782 -0.72 c
+26.936 -0.72 27.076 -0.687 27.194 -0.617 c
+27.318 -0.55 27.407 -0.448 27.458 -0.309 c
+28.296 -0.382 l
+28.266 -0.481 28.212 -0.588 28.135 -0.706 c
+28.054 -0.816 27.95 -0.918 27.825 -1.014 c
+27.708 -1.102 27.553 -1.176 27.37 -1.234 c
+27.194 -1.294 26.98 -1.323 26.738 -1.323 c
+26.738 1.706 m
+26.649 1.706 26.562 1.691 26.473 1.661 c
+26.385 1.632 26.304 1.58 26.238 1.515 c
+26.169 1.445 26.109 1.357 26.061 1.25 c
+26.021 1.139 26.003 1.015 26.003 0.867 c
+27.472 0.867 l
+27.472 1.004 27.447 1.125 27.399 1.235 c
+27.359 1.341 27.304 1.43 27.237 1.5 c
+27.179 1.566 27.106 1.617 27.017 1.646 c
+26.929 1.684 26.834 1.706 26.738 1.706 c
+31.269 -1.263 m
+30.196 -1.263 l
+28.887 2.22 l
+29.843 2.22 l
+30.504 0.221 l
+30.523 0.151 30.541 0.078 30.564 0 c
+30.593 -0.07 30.615 -0.139 30.637 -0.205 c
+30.655 -0.275 30.67 -0.345 30.681 -0.411 c
+30.699 -0.481 30.718 -0.54 30.74 -0.588 c
+30.747 -0.54 30.762 -0.481 30.784 -0.411 c
+30.802 -0.345 30.82 -0.275 30.842 -0.205 c
+30.861 -0.139 30.879 -0.07 30.901 0 c
+30.931 0.067 30.953 0.136 30.975 0.206 c
+31.68 2.22 l
+32.621 2.22 l
+h
+34.859 -1.323 m
+34.602 -1.323 34.374 -1.286 34.169 -1.219 c
+33.963 -1.142 33.786 -1.028 33.639 -0.881 c
+33.492 -0.727 33.375 -0.536 33.286 -0.309 c
+33.205 -0.084 33.169 0.181 33.169 0.485 c
+33.169 0.817 33.213 1.096 33.301 1.324 c
+33.396 1.559 33.525 1.742 33.683 1.882 c
+33.849 2.018 34.036 2.117 34.242 2.176 c
+34.447 2.242 34.657 2.278 34.874 2.278 c
+35.146 2.278 35.381 2.228 35.58 2.132 c
+35.785 2.043 35.95 1.912 36.079 1.735 c
+36.215 1.566 36.314 1.36 36.373 1.118 c
+36.44 0.882 36.476 0.618 36.476 0.324 c
+36.476 0.31 l
+34.109 0.31 l
+34.109 0.162 34.124 0.023 34.154 -0.103 c
+34.19 -0.231 34.246 -0.345 34.315 -0.44 c
+34.381 -0.529 34.466 -0.598 34.565 -0.646 c
+34.661 -0.698 34.774 -0.72 34.903 -0.72 c
+35.058 -0.72 35.197 -0.687 35.314 -0.617 c
+35.44 -0.55 35.528 -0.448 35.58 -0.309 c
+36.417 -0.382 l
+36.388 -0.481 36.332 -0.588 36.255 -0.706 c
+36.174 -0.816 36.072 -0.918 35.947 -1.014 c
+35.829 -1.102 35.675 -1.176 35.491 -1.234 c
+35.314 -1.294 35.102 -1.323 34.859 -1.323 c
+34.859 1.706 m
+34.771 1.706 34.682 1.691 34.595 1.661 c
+34.506 1.632 34.425 1.58 34.36 1.515 c
+34.29 1.445 34.231 1.357 34.183 1.25 c
+34.142 1.139 34.124 1.015 34.124 0.867 c
+35.594 0.867 l
+35.594 1.004 35.568 1.125 35.52 1.235 c
+35.48 1.341 35.425 1.43 35.359 1.5 c
+35.3 1.566 35.227 1.617 35.138 1.646 c
+35.05 1.684 34.955 1.706 34.859 1.706 c
+40.378 1.47 m
+40.28 1.478 40.176 1.489 40.07 1.5 c
+39.96 1.518 39.838 1.529 39.702 1.529 c
+39.526 1.529 39.368 1.489 39.232 1.411 c
+39.092 1.341 38.975 1.243 38.879 1.118 c
+38.791 0.989 38.721 0.842 38.674 0.676 c
+38.633 0.508 38.615 0.331 38.615 0.148 c
+38.615 -1.263 l
+37.718 -1.263 l
+37.718 0.985 l
+37.718 1.11 37.707 1.235 37.689 1.353 c
+37.678 1.478 37.663 1.595 37.645 1.706 c
+37.633 1.823 37.619 1.919 37.6 1.999 c
+37.579 2.087 37.56 2.161 37.542 2.22 c
+38.424 2.22 l
+38.431 2.168 38.442 2.117 38.453 2.058 c
+38.472 1.999 38.486 1.933 38.497 1.867 c
+38.516 1.808 38.53 1.742 38.541 1.676 c
+38.549 1.607 38.56 1.544 38.57 1.485 c
+38.585 1.485 l
+38.622 1.603 38.674 1.709 38.732 1.808 c
+38.798 1.904 38.879 1.989 38.967 2.058 c
+39.056 2.124 39.158 2.18 39.276 2.22 c
+39.401 2.257 39.548 2.278 39.717 2.278 c
+39.842 2.278 39.96 2.272 40.07 2.264 c
+40.187 2.253 40.29 2.238 40.378 2.22 c
+h
+42.028 1.603 m
+41.485 1.603 l
+41.485 2.22 l
+42.073 2.22 l
+42.352 3.117 l
+42.925 3.117 l
+42.925 2.22 l
+44.16 2.22 l
+44.16 1.603 l
+42.925 1.603 l
+42.925 -0.103 l
+42.925 -0.323 l
+42.933 -0.392 42.954 -0.455 42.984 -0.514 c
+43.021 -0.565 43.076 -0.61 43.146 -0.646 c
+43.223 -0.675 43.337 -0.69 43.484 -0.69 c
+43.619 -0.69 43.756 -0.687 43.895 -0.675 c
+44.031 -0.658 44.164 -0.631 44.292 -0.602 c
+44.292 -1.205 l
+44.211 -1.215 44.134 -1.23 44.057 -1.249 c
+43.976 -1.26 43.899 -1.267 43.822 -1.278 c
+43.741 -1.286 43.653 -1.294 43.557 -1.294 c
+43.469 -1.3 43.37 -1.308 43.264 -1.308 c
+43.076 -1.308 42.914 -1.294 42.778 -1.263 c
+42.649 -1.227 42.536 -1.182 42.441 -1.132 c
+42.352 -1.084 42.279 -1.024 42.219 -0.955 c
+42.161 -0.878 42.117 -0.801 42.088 -0.72 c
+42.058 -0.631 42.036 -0.544 42.028 -0.455 c
+42.017 -0.359 42.013 -0.264 42.013 -0.176 c
+h
+50.297 -2.63 m
+50.297 3.514 l
+52.222 3.514 l
+52.222 2.897 l
+51.149 2.897 l
+51.149 -2.013 l
+52.222 -2.013 l
+52.222 -2.63 l
+h
+55.166 -1.323 m
+54.879 -1.323 54.636 -1.282 54.431 -1.205 c
+54.225 -1.117 54.052 -0.995 53.917 -0.837 c
+53.776 -0.683 53.674 -0.496 53.608 -0.278 c
+53.538 -0.055 53.505 0.192 53.505 0.456 c
+53.505 0.75 53.538 1.008 53.608 1.235 c
+53.685 1.459 53.791 1.646 53.931 1.794 c
+54.078 1.948 54.254 2.066 54.46 2.147 c
+54.666 2.234 54.902 2.278 55.166 2.278 c
+55.39 2.278 55.592 2.249 55.769 2.191 c
+55.945 2.132 56.095 2.047 56.224 1.941 c
+56.349 1.842 56.452 1.721 56.533 1.573 c
+56.61 1.434 56.665 1.283 56.695 1.118 c
+55.783 1.073 l
+55.754 1.25 55.684 1.389 55.577 1.5 c
+55.478 1.607 55.335 1.661 55.151 1.661 c
+54.905 1.661 54.728 1.559 54.622 1.353 c
+54.512 1.154 54.46 0.867 54.46 0.485 c
+54.46 -0.309 54.696 -0.706 55.166 -0.706 c
+55.331 -0.706 55.474 -0.654 55.592 -0.544 c
+55.71 -0.436 55.783 -0.275 55.812 -0.058 c
+56.724 -0.103 l
+56.695 -0.272 56.639 -0.426 56.562 -0.573 c
+56.492 -0.72 56.39 -0.852 56.253 -0.97 c
+56.125 -1.08 55.966 -1.168 55.783 -1.234 c
+55.607 -1.294 55.401 -1.323 55.166 -1.323 c
+60.876 0.485 m
+60.876 0.21 60.84 -0.04 60.774 -0.264 c
+60.704 -0.481 60.601 -0.668 60.465 -0.823 c
+60.325 -0.98 60.149 -1.102 59.935 -1.19 c
+59.719 -1.278 59.465 -1.323 59.172 -1.323 c
+58.896 -1.323 58.649 -1.278 58.436 -1.19 c
+58.231 -1.102 58.058 -0.98 57.922 -0.823 c
+57.782 -0.668 57.68 -0.481 57.613 -0.264 c
+57.543 -0.04 57.51 0.21 57.51 0.485 c
+57.51 0.739 57.539 0.975 57.599 1.191 c
+57.665 1.415 57.768 1.607 57.907 1.764 c
+58.044 1.929 58.22 2.058 58.436 2.147 c
+58.649 2.234 58.906 2.278 59.201 2.278 c
+59.513 2.278 59.774 2.234 59.98 2.147 c
+60.193 2.058 60.365 1.929 60.494 1.764 c
+60.631 1.607 60.729 1.415 60.788 1.191 c
+60.847 0.975 60.876 0.739 60.876 0.485 c
+59.921 0.485 m
+59.921 0.691 59.906 0.867 59.877 1.015 c
+59.855 1.162 59.818 1.283 59.76 1.382 c
+59.7 1.478 59.627 1.548 59.538 1.588 c
+59.451 1.636 59.34 1.661 59.216 1.661 c
+58.951 1.661 58.76 1.563 58.642 1.368 c
+58.524 1.18 58.466 0.886 58.466 0.485 c
+58.466 0.063 58.524 -0.242 58.642 -0.426 c
+58.76 -0.613 58.936 -0.706 59.172 -0.706 c
+59.297 -0.706 59.411 -0.687 59.509 -0.646 c
+59.605 -0.598 59.686 -0.525 59.744 -0.426 c
+59.81 -0.33 59.855 -0.205 59.877 -0.058 c
+59.906 0.088 59.921 0.269 59.921 0.485 c
+62.894 -1.263 m
+62.894 0.853 l
+62.894 1.019 62.887 1.154 62.879 1.264 c
+62.868 1.372 62.85 1.455 62.821 1.515 c
+62.798 1.58 62.769 1.632 62.732 1.661 c
+62.703 1.691 62.663 1.706 62.615 1.706 c
+62.555 1.706 62.501 1.676 62.453 1.617 c
+62.412 1.566 62.379 1.492 62.35 1.397 c
+62.32 1.309 62.295 1.195 62.277 1.058 c
+62.266 0.919 62.262 0.769 62.262 0.603 c
+62.262 -1.263 l
+61.512 -1.263 l
+61.512 1.47 l
+61.512 1.706 l
+61.512 1.926 l
+61.512 2.003 61.505 2.066 61.497 2.117 c
+61.497 2.22 l
+62.173 2.22 l
+62.173 2.132 l
+62.173 1.985 l
+62.181 1.926 62.189 1.867 62.189 1.808 c
+62.189 1.646 l
+62.203 1.646 l
+62.221 1.735 62.251 1.812 62.291 1.882 c
+62.328 1.96 62.372 2.029 62.424 2.087 c
+62.482 2.147 62.549 2.191 62.629 2.22 c
+62.707 2.257 62.794 2.278 62.894 2.278 c
+63.078 2.278 63.218 2.224 63.305 2.117 c
+63.401 2.018 63.471 1.86 63.511 1.646 c
+63.526 1.646 l
+63.563 1.742 63.603 1.831 63.644 1.912 c
+63.691 1.989 63.746 2.051 63.805 2.103 c
+63.864 2.161 63.93 2.205 64.011 2.234 c
+64.088 2.264 64.176 2.278 64.275 2.278 c
+64.411 2.278 64.525 2.253 64.614 2.205 c
+64.702 2.154 64.768 2.08 64.82 1.985 c
+64.878 1.885 64.915 1.757 64.937 1.603 c
+64.967 1.455 64.981 1.272 64.981 1.058 c
+64.981 -1.263 l
+64.261 -1.263 l
+64.261 0.853 l
+64.261 1.019 64.253 1.154 64.246 1.264 c
+64.236 1.372 64.217 1.455 64.188 1.515 c
+64.165 1.58 64.136 1.632 64.099 1.661 c
+64.07 1.691 64.03 1.706 63.982 1.706 c
+63.864 1.706 63.768 1.617 63.702 1.441 c
+63.644 1.272 63.614 1.015 63.614 0.662 c
+63.614 -1.263 l
+h
+66.954 -1.263 m
+66.954 0.853 l
+66.954 1.019 66.947 1.154 66.94 1.264 c
+66.929 1.372 66.91 1.455 66.881 1.515 c
+66.859 1.58 66.829 1.632 66.793 1.661 c
+66.763 1.691 66.723 1.706 66.675 1.706 c
+66.617 1.706 66.561 1.676 66.513 1.617 c
+66.473 1.566 66.44 1.492 66.411 1.397 c
+66.381 1.309 66.355 1.195 66.337 1.058 c
+66.326 0.919 66.322 0.769 66.322 0.603 c
+66.322 -1.263 l
+65.572 -1.263 l
+65.572 1.47 l
+65.572 1.706 l
+65.572 1.926 l
+65.572 2.003 65.566 2.066 65.558 2.117 c
+65.558 2.22 l
+66.235 2.22 l
+66.235 2.132 l
+66.235 1.985 l
+66.241 1.926 66.249 1.867 66.249 1.808 c
+66.249 1.646 l
+66.264 1.646 l
+66.282 1.735 66.312 1.812 66.352 1.882 c
+66.389 1.96 66.432 2.029 66.484 2.087 c
+66.543 2.147 66.609 2.191 66.69 2.22 c
+66.767 2.257 66.856 2.278 66.954 2.278 c
+67.138 2.278 67.278 2.224 67.366 2.117 c
+67.461 2.018 67.531 1.86 67.571 1.646 c
+67.586 1.646 l
+67.623 1.742 67.664 1.831 67.704 1.912 c
+67.752 1.989 67.807 2.051 67.866 2.103 c
+67.924 2.161 67.991 2.205 68.072 2.234 c
+68.149 2.264 68.237 2.278 68.336 2.278 c
+68.472 2.278 68.586 2.253 68.674 2.205 c
+68.762 2.154 68.828 2.08 68.88 1.985 c
+68.939 1.885 68.976 1.757 68.998 1.603 c
+69.027 1.455 69.042 1.272 69.042 1.058 c
+69.042 -1.263 l
+68.321 -1.263 l
+68.321 0.853 l
+68.321 1.019 68.314 1.154 68.307 1.264 c
+68.296 1.372 68.277 1.455 68.248 1.515 c
+68.226 1.58 68.196 1.632 68.159 1.661 c
+68.13 1.691 68.09 1.706 68.042 1.706 c
+67.924 1.706 67.829 1.617 67.763 1.441 c
+67.704 1.272 67.675 1.015 67.675 0.662 c
+67.675 -1.263 l
+h
+71.956 -0.646 m
+73.088 -0.646 l
+73.088 -1.263 l
+69.78 -1.263 l
+69.78 -0.646 l
+71.045 -0.646 l
+71.045 1.603 l
+70.118 1.603 l
+70.118 2.22 l
+71.956 2.22 l
+h
+71.045 3.514 0.912 -0.676 re
+71.045 2.837 m
+74.517 1.603 m
+73.973 1.603 l
+73.973 2.22 l
+74.561 2.22 l
+74.841 3.117 l
+75.413 3.117 l
+75.413 2.22 l
+76.649 2.22 l
+76.649 1.603 l
+75.413 1.603 l
+75.413 -0.103 l
+75.413 -0.323 l
+75.421 -0.392 75.444 -0.455 75.473 -0.514 c
+75.509 -0.565 75.564 -0.61 75.634 -0.646 c
+75.712 -0.675 75.825 -0.69 75.972 -0.69 c
+76.109 -0.69 76.244 -0.687 76.384 -0.675 c
+76.52 -0.658 76.652 -0.631 76.78 -0.602 c
+76.78 -1.205 l
+76.7 -1.215 76.623 -1.23 76.545 -1.249 c
+76.465 -1.26 76.388 -1.267 76.31 -1.278 c
+76.23 -1.286 76.142 -1.294 76.046 -1.294 c
+75.957 -1.3 75.858 -1.308 75.752 -1.308 c
+75.564 -1.308 75.403 -1.294 75.267 -1.263 c
+75.138 -1.227 75.024 -1.182 74.929 -1.132 c
+74.841 -1.084 74.767 -1.024 74.708 -0.955 c
+74.65 -0.878 74.605 -0.801 74.576 -0.72 c
+74.546 -0.631 74.524 -0.544 74.517 -0.455 c
+74.507 -0.359 74.503 -0.264 74.503 -0.176 c
+h
+85.141 -0.249 m
+85.141 -0.419 85.1 -0.569 85.023 -0.706 c
+84.953 -0.833 84.851 -0.947 84.715 -1.043 c
+84.586 -1.132 84.424 -1.201 84.229 -1.249 c
+84.042 -1.296 83.826 -1.323 83.583 -1.323 c
+83.355 -1.323 83.157 -1.308 82.98 -1.278 c
+82.804 -1.249 82.646 -1.201 82.509 -1.132 c
+82.37 -1.055 82.26 -0.955 82.172 -0.837 c
+82.083 -0.72 82.014 -0.573 81.966 -0.396 c
+82.775 -0.278 l
+82.793 -0.378 82.822 -0.455 82.862 -0.514 c
+82.91 -0.573 82.969 -0.617 83.039 -0.646 c
+83.105 -0.675 83.186 -0.702 83.274 -0.72 c
+83.363 -0.731 83.465 -0.735 83.583 -0.735 c
+83.679 -0.735 83.774 -0.731 83.862 -0.72 c
+83.951 -0.702 84.028 -0.675 84.097 -0.646 c
+84.163 -0.617 84.215 -0.58 84.244 -0.529 c
+84.281 -0.481 84.303 -0.419 84.303 -0.338 c
+84.303 -0.242 84.273 -0.168 84.215 -0.118 c
+84.163 -0.07 84.097 -0.029 84.009 0 c
+83.921 0.038 83.81 0.067 83.685 0.088 c
+83.568 0.118 83.436 0.148 83.288 0.177 c
+83.149 0.214 83.01 0.254 82.862 0.294 c
+82.723 0.342 82.598 0.405 82.48 0.485 c
+82.37 0.563 82.282 0.662 82.216 0.78 c
+82.146 0.897 82.112 1.048 82.112 1.235 c
+82.112 1.389 82.143 1.532 82.201 1.661 c
+82.268 1.798 82.363 1.912 82.48 1.999 c
+82.605 2.087 82.763 2.154 82.951 2.205 c
+83.134 2.253 83.348 2.278 83.583 2.278 c
+83.766 2.278 83.943 2.257 84.112 2.22 c
+84.277 2.191 84.424 2.135 84.553 2.058 c
+84.678 1.989 84.788 1.889 84.876 1.764 c
+84.965 1.646 85.023 1.503 85.052 1.338 c
+84.259 1.264 l
+84.237 1.341 84.207 1.405 84.171 1.455 c
+84.13 1.515 84.082 1.559 84.024 1.588 c
+83.972 1.625 83.91 1.65 83.833 1.661 c
+83.752 1.669 83.671 1.676 83.583 1.676 c
+83.366 1.676 83.205 1.646 83.097 1.588 c
+82.987 1.536 82.936 1.449 82.936 1.324 c
+82.936 1.243 82.954 1.18 82.995 1.133 c
+83.043 1.081 83.105 1.044 83.186 1.015 c
+83.274 0.985 83.369 0.956 83.48 0.927 c
+83.587 0.904 83.708 0.882 83.847 0.853 c
+84.001 0.823 84.159 0.784 84.318 0.736 c
+84.472 0.684 84.612 0.622 84.73 0.545 c
+84.847 0.464 84.942 0.36 85.023 0.235 c
+85.1 0.107 85.141 -0.055 85.141 -0.249 c
+86.997 1.515 m
+87.114 1.786 87.265 1.985 87.452 2.103 c
+87.636 2.22 87.857 2.278 88.113 2.278 c
+88.319 2.278 88.489 2.242 88.628 2.176 c
+88.775 2.106 88.886 2.014 88.967 1.897 c
+89.054 1.779 89.113 1.636 89.143 1.47 c
+89.179 1.301 89.202 1.125 89.202 0.941 c
+89.202 -1.263 l
+88.29 -1.263 l
+88.29 0.736 l
+88.29 0.871 88.279 0.992 88.261 1.103 c
+88.25 1.21 88.224 1.297 88.187 1.368 c
+88.147 1.445 88.088 1.503 88.011 1.544 c
+87.941 1.58 87.849 1.603 87.731 1.603 c
+87.621 1.603 87.525 1.577 87.438 1.529 c
+87.35 1.478 87.269 1.411 87.203 1.324 c
+87.144 1.235 87.092 1.125 87.055 1 c
+87.026 0.882 87.011 0.75 87.011 0.603 c
+87.011 -1.263 l
+86.1 -1.263 l
+86.1 3.514 l
+87.011 3.514 l
+87.011 2.205 l
+87.011 2.135 87.004 2.066 86.997 1.999 c
+86.997 1.794 l
+86.997 1.735 86.989 1.68 86.982 1.632 c
+86.982 1.515 l
+h
+91.116 -1.323 m
+90.947 -1.323 90.796 -1.3 90.66 -1.263 c
+90.532 -1.215 90.418 -1.146 90.322 -1.058 c
+90.234 -0.97 90.164 -0.863 90.116 -0.735 c
+90.065 -0.598 90.043 -0.448 90.043 -0.278 c
+90.043 -0.073 90.076 0.096 90.145 0.235 c
+90.212 0.383 90.307 0.493 90.425 0.574 c
+90.55 0.662 90.694 0.724 90.851 0.765 c
+91.017 0.802 91.193 0.827 91.381 0.838 c
+92.101 0.853 l
+92.101 1.029 l
+92.101 1.147 92.09 1.25 92.071 1.338 c
+92.049 1.426 92.017 1.492 91.969 1.544 c
+91.928 1.603 91.88 1.64 91.822 1.661 c
+91.763 1.68 91.697 1.691 91.631 1.691 c
+91.56 1.691 91.498 1.68 91.44 1.661 c
+91.388 1.65 91.34 1.625 91.292 1.588 c
+91.252 1.559 91.219 1.507 91.19 1.441 c
+91.167 1.382 91.153 1.301 91.145 1.206 c
+90.205 1.25 l
+90.234 1.397 90.278 1.532 90.337 1.661 c
+90.403 1.786 90.499 1.897 90.616 1.985 c
+90.734 2.08 90.874 2.154 91.043 2.205 c
+91.219 2.253 91.425 2.278 91.66 2.278 c
+92.101 2.278 92.431 2.168 92.659 1.956 c
+92.894 1.75 93.012 1.441 93.012 1.029 c
+93.012 -0.235 l
+93.012 -0.455 l
+93.019 -0.514 93.034 -0.569 93.056 -0.617 c
+93.075 -0.658 93.104 -0.69 93.145 -0.72 c
+93.181 -0.742 93.233 -0.749 93.291 -0.749 c
+93.358 -0.749 93.428 -0.745 93.497 -0.735 c
+93.497 -1.219 l
+93.438 -1.23 93.383 -1.242 93.335 -1.249 c
+93.295 -1.26 93.255 -1.267 93.218 -1.278 c
+93.177 -1.286 93.133 -1.294 93.086 -1.294 c
+93.034 -1.3 92.975 -1.308 92.909 -1.308 c
+92.682 -1.308 92.516 -1.256 92.41 -1.146 c
+92.3 -1.028 92.237 -0.863 92.219 -0.646 c
+92.204 -0.646 l
+92.134 -0.756 92.065 -0.852 91.998 -0.941 c
+91.928 -1.021 91.851 -1.087 91.763 -1.146 c
+91.675 -1.205 91.575 -1.249 91.469 -1.278 c
+91.369 -1.308 91.252 -1.323 91.116 -1.323 c
+92.101 0.353 m
+91.675 0.339 l
+91.575 0.339 91.483 0.331 91.396 0.324 c
+91.315 0.313 91.248 0.287 91.19 0.25 c
+91.13 0.21 91.08 0.151 91.043 0.074 c
+91.002 0.004 90.984 -0.087 90.984 -0.205 c
+90.984 -0.374 91.017 -0.496 91.086 -0.573 c
+91.153 -0.654 91.252 -0.69 91.381 -0.69 c
+91.487 -0.69 91.587 -0.668 91.675 -0.617 c
+91.77 -0.569 91.851 -0.507 91.91 -0.426 c
+91.976 -0.349 92.027 -0.261 92.057 -0.161 c
+92.086 -0.055 92.101 0.059 92.101 0.177 c
+h
+94.589 -2.63 m
+94.589 -2.013 l
+95.662 -2.013 l
+95.662 2.897 l
+94.589 2.897 l
+94.589 3.514 l
+96.514 3.514 l
+96.514 -2.63 l
+h
+f
+Q
+q 1 0 0 1 314.6631 247.1802 cm
+0 0 m
+-0.029 -0.58 -0.191 -1.022 -0.485 -1.323 c
+-0.779 -1.627 -1.198 -1.779 -1.735 -1.779 c
+-2.263 -1.779 -2.69 -1.58 -3.013 -1.176 c
+-3.329 -0.764 -3.484 -0.206 -3.484 0.5 c
+-3.484 1.47 l
+-3.484 2.165 -3.322 2.712 -2.999 3.117 c
+-2.675 3.516 -2.23 3.719 -1.661 3.719 c
+-1.154 3.719 -0.757 3.561 -0.47 3.248 c
+-0.187 2.944 -0.029 2.502 0 1.926 c
+-0.69 1.926 l
+-0.721 2.367 -0.816 2.679 -0.97 2.866 c
+-1.118 3.05 -1.349 3.146 -1.661 3.146 c
+-2.036 3.146 -2.319 2.999 -2.514 2.705 c
+-2.712 2.418 -2.807 2.003 -2.807 1.455 c
+-2.807 0.47 l
+-2.807 -0.07 -2.716 -0.485 -2.529 -0.779 c
+-2.344 -1.066 -2.08 -1.205 -1.735 -1.205 c
+-1.382 -1.205 -1.128 -1.117 -0.97 -0.941 c
+-0.816 -0.764 -0.721 -0.452 -0.69 0 c
+h
+2.454 1.661 m
+2.367 1.679 2.267 1.691 2.161 1.691 c
+1.826 1.691 1.591 1.507 1.455 1.147 c
+1.455 -1.705 l
+0.808 -1.705 l
+0.808 2.278 l
+1.44 2.278 l
+1.455 1.866 l
+1.631 2.19 1.874 2.352 2.19 2.352 c
+2.296 2.352 2.385 2.33 2.454 2.294 c
+h
+4.453 -1.779 m
+3.954 -1.779 3.572 -1.631 3.308 -1.338 c
+3.042 -1.043 2.911 -0.61 2.911 -0.029 c
+2.911 0.441 l
+2.911 1.037 3.036 1.503 3.293 1.837 c
+3.557 2.18 3.917 2.352 4.38 2.352 c
+4.839 2.352 5.182 2.198 5.409 1.897 c
+5.644 1.602 5.766 1.139 5.777 0.515 c
+5.777 0.088 l
+3.557 0.088 l
+3.557 0 l
+3.557 -0.434 3.634 -0.746 3.792 -0.941 c
+3.958 -1.128 4.189 -1.22 4.484 -1.22 c
+4.678 -1.22 4.85 -1.187 4.997 -1.117 c
+5.145 -1.04 5.28 -0.922 5.409 -0.764 c
+5.747 -1.176 l
+5.461 -1.58 5.031 -1.779 4.453 -1.779 c
+4.38 1.793 m
+4.104 1.793 3.902 1.698 3.778 1.514 c
+3.649 1.326 3.576 1.037 3.557 0.647 c
+5.13 0.647 l
+5.13 0.735 l
+5.108 1.118 5.041 1.386 4.924 1.544 c
+4.806 1.709 4.623 1.793 4.38 1.793 c
+8.599 -1.705 m
+8.559 -1.617 8.533 -1.469 8.525 -1.264 c
+8.29 -1.61 7.996 -1.779 7.644 -1.779 c
+7.279 -1.779 6.996 -1.683 6.791 -1.484 c
+6.593 -1.278 6.497 -0.992 6.497 -0.617 c
+6.497 -0.216 6.633 0.103 6.909 0.338 c
+7.181 0.58 7.555 0.706 8.025 0.706 c
+8.511 0.706 l
+8.511 1.132 l
+8.511 1.367 8.455 1.532 8.349 1.631 c
+8.239 1.738 8.077 1.793 7.864 1.793 c
+7.665 1.793 7.504 1.735 7.379 1.617 c
+7.262 1.5 7.202 1.353 7.202 1.176 c
+6.556 1.176 l
+6.556 1.371 6.614 1.562 6.732 1.749 c
+6.857 1.933 7.019 2.08 7.217 2.19 c
+7.423 2.297 7.651 2.352 7.908 2.352 c
+8.309 2.352 8.613 2.249 8.819 2.043 c
+9.033 1.837 9.147 1.544 9.157 1.161 c
+9.157 -0.852 l
+9.157 -1.157 9.194 -1.422 9.275 -1.646 c
+9.275 -1.705 l
+h
+7.732 -1.191 m
+7.897 -1.191 8.048 -1.147 8.187 -1.058 c
+8.334 -0.97 8.441 -0.86 8.511 -0.721 c
+8.511 0.22 l
+8.143 0.22 l
+7.827 0.22 7.584 0.151 7.408 0.015 c
+7.231 -0.114 7.144 -0.301 7.144 -0.544 c
+7.144 -0.771 7.188 -0.937 7.276 -1.043 c
+7.364 -1.143 7.515 -1.191 7.732 -1.191 c
+11.009 3.234 m
+11.009 2.278 l
+11.612 2.278 l
+11.612 1.749 l
+11.009 1.749 l
+11.009 -0.721 l
+11.009 -0.878 11.032 -0.995 11.083 -1.073 c
+11.142 -1.153 11.23 -1.191 11.347 -1.191 c
+11.436 -1.191 11.524 -1.176 11.612 -1.147 c
+11.612 -1.705 l
+11.465 -1.753 11.311 -1.779 11.156 -1.779 c
+10.899 -1.779 10.705 -1.687 10.568 -1.5 c
+10.429 -1.315 10.363 -1.055 10.363 -0.721 c
+10.363 1.749 l
+9.76 1.749 l
+9.76 2.278 l
+10.363 2.278 l
+10.363 3.234 l
+h
+13.803 -1.779 m
+13.303 -1.779 12.92 -1.631 12.656 -1.338 c
+12.391 -1.043 12.259 -0.61 12.259 -0.029 c
+12.259 0.441 l
+12.259 1.037 12.384 1.503 12.641 1.837 c
+12.906 2.18 13.266 2.352 13.729 2.352 c
+14.188 2.352 14.53 2.198 14.757 1.897 c
+14.993 1.602 15.114 1.139 15.125 0.515 c
+15.125 0.088 l
+12.906 0.088 l
+12.906 0 l
+12.906 -0.434 12.983 -0.746 13.141 -0.941 c
+13.306 -1.128 13.538 -1.22 13.832 -1.22 c
+14.026 -1.22 14.2 -1.187 14.346 -1.117 c
+14.493 -1.04 14.629 -0.922 14.757 -0.764 c
+15.096 -1.176 l
+14.809 -1.58 14.379 -1.779 13.803 -1.779 c
+13.729 1.793 m
+13.454 1.793 13.251 1.698 13.126 1.514 c
+12.997 1.326 12.924 1.037 12.906 0.647 c
+14.479 0.647 l
+14.479 0.735 l
+14.456 1.118 14.391 1.386 14.273 1.544 c
+14.155 1.709 13.972 1.793 13.729 1.793 c
+19.667 -1.705 m
+19.627 -1.617 19.601 -1.469 19.594 -1.264 c
+19.359 -1.61 19.065 -1.779 18.712 -1.779 c
+18.348 -1.779 18.065 -1.683 17.859 -1.484 c
+17.661 -1.278 17.565 -0.992 17.565 -0.617 c
+17.565 -0.216 17.701 0.103 17.977 0.338 c
+18.248 0.58 18.624 0.706 19.094 0.706 c
+19.579 0.706 l
+19.579 1.132 l
+19.579 1.367 19.524 1.532 19.418 1.631 c
+19.307 1.738 19.146 1.793 18.932 1.793 c
+18.734 1.793 18.572 1.735 18.447 1.617 c
+18.329 1.5 18.271 1.353 18.271 1.176 c
+17.624 1.176 l
+17.624 1.371 17.683 1.562 17.801 1.749 c
+17.926 1.933 18.088 2.08 18.285 2.19 c
+18.491 2.297 18.719 2.352 18.977 2.352 c
+19.377 2.352 19.682 2.249 19.888 2.043 c
+20.101 1.837 20.215 1.544 20.226 1.161 c
+20.226 -0.852 l
+20.226 -1.157 20.263 -1.422 20.344 -1.646 c
+20.344 -1.705 l
+h
+18.8 -1.191 m
+18.965 -1.191 19.116 -1.147 19.256 -1.058 c
+19.403 -0.97 19.509 -0.86 19.579 -0.721 c
+19.579 0.22 l
+19.212 0.22 l
+18.896 0.22 18.653 0.151 18.477 0.015 c
+18.3 -0.114 18.212 -0.301 18.212 -0.544 c
+18.212 -0.771 18.256 -0.937 18.344 -1.043 c
+18.433 -1.143 18.583 -1.191 18.8 -1.191 c
+23.563 2.278 m
+23.577 1.837 l
+23.831 2.18 24.154 2.352 24.548 2.352 c
+25.253 2.352 25.61 1.881 25.62 0.941 c
+25.62 -1.705 l
+24.974 -1.705 l
+24.974 0.912 l
+24.974 1.224 24.918 1.444 24.812 1.573 c
+24.702 1.698 24.548 1.764 24.342 1.764 c
+24.184 1.764 24.037 1.709 23.9 1.602 c
+23.772 1.492 23.669 1.357 23.592 1.191 c
+23.592 -1.705 l
+22.946 -1.705 l
+22.946 2.278 l
+h
+28.016 -1.779 m
+27.517 -1.779 27.135 -1.631 26.869 -1.338 c
+26.605 -1.043 26.473 -0.61 26.473 -0.029 c
+26.473 0.441 l
+26.473 1.037 26.598 1.503 26.855 1.837 c
+27.12 2.18 27.48 2.352 27.943 2.352 c
+28.402 2.352 28.744 2.198 28.972 1.897 c
+29.207 1.602 29.328 1.139 29.339 0.515 c
+29.339 0.088 l
+27.12 0.088 l
+27.12 0 l
+27.12 -0.434 27.197 -0.746 27.355 -0.941 c
+27.52 -1.128 27.752 -1.22 28.045 -1.22 c
+28.241 -1.22 28.413 -1.187 28.56 -1.117 c
+28.708 -1.04 28.843 -0.922 28.972 -0.764 c
+29.31 -1.176 l
+29.024 -1.58 28.593 -1.779 28.016 -1.779 c
+27.943 1.793 m
+27.667 1.793 27.465 1.698 27.34 1.514 c
+27.212 1.326 27.138 1.037 27.12 0.647 c
+28.693 0.647 l
+28.693 0.735 l
+28.671 1.118 28.604 1.386 28.487 1.544 c
+28.369 1.709 28.185 1.793 27.943 1.793 c
+33.088 -0.559 m
+33.69 2.278 l
+34.337 2.278 l
+33.352 -1.705 l
+32.837 -1.705 l
+32.059 1.147 l
+31.309 -1.705 l
+30.78 -1.705 l
+29.824 2.278 l
+30.456 2.278 l
+31.074 -0.485 l
+31.808 2.278 l
+32.323 2.278 l
+h
+38.115 -1.22 m
+38.328 -1.22 38.501 -1.157 38.629 -1.029 c
+38.765 -0.893 38.838 -0.702 38.85 -0.455 c
+39.467 -0.455 l
+39.445 -0.838 39.309 -1.157 39.056 -1.411 c
+38.798 -1.658 38.486 -1.779 38.115 -1.779 c
+37.622 -1.779 37.248 -1.627 36.982 -1.323 c
+36.726 -1.01 36.6 -0.544 36.6 0.073 c
+36.6 0.515 l
+36.6 1.11 36.726 1.565 36.982 1.881 c
+37.248 2.194 37.622 2.352 38.115 2.352 c
+38.515 2.352 38.835 2.219 39.07 1.955 c
+39.313 1.698 39.445 1.353 39.467 0.912 c
+38.85 0.912 l
+38.827 1.205 38.754 1.426 38.629 1.573 c
+38.511 1.72 38.339 1.793 38.115 1.793 c
+37.821 1.793 37.604 1.694 37.468 1.5 c
+37.329 1.312 37.255 1.004 37.248 0.573 c
+37.248 0.059 l
+37.248 -0.411 37.314 -0.746 37.453 -0.941 c
+37.6 -1.128 37.821 -1.22 38.115 -1.22 c
+40.084 0.47 m
+40.084 1.047 40.22 1.503 40.496 1.837 c
+40.779 2.18 41.15 2.352 41.613 2.352 c
+42.073 2.352 42.44 2.183 42.715 1.852 c
+42.998 1.529 43.145 1.081 43.156 0.515 c
+43.156 0.088 l
+43.156 -0.482 43.013 -0.937 42.73 -1.278 c
+42.455 -1.613 42.087 -1.779 41.628 -1.779 c
+41.165 -1.779 40.793 -1.617 40.51 -1.294 c
+40.235 -0.962 40.091 -0.522 40.084 0.029 c
+h
+40.731 0.088 m
+40.731 -0.316 40.808 -0.632 40.966 -0.867 c
+41.132 -1.103 41.352 -1.22 41.628 -1.22 c
+42.194 -1.22 42.488 -0.808 42.509 0.015 c
+42.509 0.47 l
+42.509 0.871 42.425 1.191 42.26 1.426 c
+42.102 1.669 41.885 1.793 41.613 1.793 c
+41.348 1.793 41.132 1.669 40.966 1.426 c
+40.808 1.191 40.731 0.871 40.731 0.47 c
+h
+44.612 2.278 m
+44.626 1.911 l
+44.869 2.205 45.188 2.352 45.582 2.352 c
+46.023 2.352 46.331 2.153 46.507 1.764 c
+46.761 2.153 47.11 2.352 47.552 2.352 c
+48.286 2.352 48.662 1.889 48.683 0.97 c
+48.683 -1.705 l
+48.036 -1.705 l
+48.036 0.912 l
+48.036 1.205 47.981 1.419 47.875 1.558 c
+47.775 1.694 47.603 1.764 47.361 1.764 c
+47.162 1.764 47 1.683 46.875 1.529 c
+46.758 1.382 46.688 1.191 46.669 0.956 c
+46.669 -1.705 l
+46.008 -1.705 l
+46.008 0.941 l
+46.008 1.488 45.788 1.764 45.346 1.764 c
+45.012 1.764 44.777 1.602 44.641 1.278 c
+44.641 -1.705 l
+43.995 -1.705 l
+43.995 2.278 l
+h
+50.27 2.278 m
+50.285 1.911 l
+50.528 2.205 50.848 2.352 51.241 2.352 c
+51.681 2.352 51.991 2.153 52.167 1.764 c
+52.421 2.153 52.77 2.352 53.21 2.352 c
+53.946 2.352 54.32 1.889 54.343 0.97 c
+54.343 -1.705 l
+53.696 -1.705 l
+53.696 0.912 l
+53.696 1.205 53.641 1.419 53.534 1.558 c
+53.435 1.694 53.262 1.764 53.019 1.764 c
+52.821 1.764 52.66 1.683 52.535 1.529 c
+52.417 1.382 52.347 1.191 52.329 0.956 c
+52.329 -1.705 l
+51.667 -1.705 l
+51.667 0.941 l
+51.667 1.488 51.446 1.764 51.006 1.764 c
+50.671 1.764 50.436 1.602 50.3 1.278 c
+50.3 -1.705 l
+49.653 -1.705 l
+49.653 2.278 l
+h
+56.018 -1.705 -0.647 3.983 re
+56.062 3.322 m
+56.062 3.212 56.032 3.12 55.974 3.042 c
+55.915 2.973 55.82 2.94 55.695 2.94 c
+55.577 2.94 55.482 2.973 55.415 3.042 c
+55.357 3.12 55.327 3.212 55.327 3.322 c
+55.327 3.439 55.357 3.532 55.415 3.601 c
+55.482 3.678 55.577 3.719 55.695 3.719 c
+55.82 3.719 55.915 3.678 55.974 3.601 c
+56.032 3.52 56.062 3.429 56.062 3.322 c
+57.885 3.234 m
+57.885 2.278 l
+58.488 2.278 l
+58.488 1.749 l
+57.885 1.749 l
+57.885 -0.721 l
+57.885 -0.878 57.907 -0.995 57.958 -1.073 c
+58.017 -1.153 58.106 -1.191 58.223 -1.191 c
+58.311 -1.191 58.399 -1.176 58.488 -1.147 c
+58.488 -1.705 l
+58.341 -1.753 58.187 -1.779 58.031 -1.779 c
+57.775 -1.779 57.58 -1.687 57.443 -1.5 c
+57.304 -1.315 57.238 -1.055 57.238 -0.721 c
+57.238 1.749 l
+56.635 1.749 l
+56.635 2.278 l
+57.238 2.278 l
+57.238 3.234 l
+h
+59.267 -2.778 m
+58.87 -2.514 l
+59.105 -2.19 59.226 -1.856 59.237 -1.514 c
+59.237 -0.897 l
+59.899 -0.897 l
+59.899 -1.426 l
+59.899 -1.683 59.833 -1.929 59.708 -2.175 c
+59.59 -2.418 59.443 -2.62 59.267 -2.778 c
+64.103 1.661 m
+64.014 1.679 63.915 1.691 63.808 1.691 c
+63.475 1.691 63.239 1.507 63.103 1.147 c
+63.103 -1.705 l
+62.457 -1.705 l
+62.457 2.278 l
+63.088 2.278 l
+63.103 1.866 l
+63.28 2.19 63.522 2.352 63.838 2.352 c
+63.945 2.352 64.032 2.33 64.103 2.294 c
+h
+66.102 -1.779 m
+65.602 -1.779 65.22 -1.631 64.955 -1.338 c
+64.691 -1.043 64.558 -0.61 64.558 -0.029 c
+64.558 0.441 l
+64.558 1.037 64.683 1.503 64.94 1.837 c
+65.205 2.18 65.565 2.352 66.028 2.352 c
+66.488 2.352 66.829 2.198 67.057 1.897 c
+67.292 1.602 67.413 1.139 67.425 0.515 c
+67.425 0.088 l
+65.205 0.088 l
+65.205 0 l
+65.205 -0.434 65.282 -0.746 65.44 -0.941 c
+65.605 -1.128 65.837 -1.22 66.131 -1.22 c
+66.326 -1.22 66.498 -1.187 66.646 -1.117 c
+66.793 -1.04 66.928 -0.922 67.057 -0.764 c
+67.396 -1.176 l
+67.109 -1.58 66.679 -1.779 66.102 -1.779 c
+66.028 1.793 m
+65.752 1.793 65.551 1.698 65.426 1.514 c
+65.297 1.326 65.223 1.037 65.205 0.647 c
+66.777 0.647 l
+66.777 0.735 l
+66.756 1.118 66.69 1.386 66.572 1.544 c
+66.455 1.709 66.27 1.793 66.028 1.793 c
+69.291 -0.721 m
+70.041 2.278 l
+70.702 2.278 l
+69.526 -1.705 l
+69.042 -1.705 l
+67.851 2.278 l
+68.512 2.278 l
+h
+72.761 -1.779 m
+72.26 -1.779 71.878 -1.631 71.614 -1.338 c
+71.349 -1.043 71.217 -0.61 71.217 -0.029 c
+71.217 0.441 l
+71.217 1.037 71.342 1.503 71.599 1.837 c
+71.864 2.18 72.223 2.352 72.687 2.352 c
+73.146 2.352 73.488 2.198 73.715 1.897 c
+73.951 1.602 74.072 1.139 74.083 0.515 c
+74.083 0.088 l
+71.864 0.088 l
+71.864 0 l
+71.864 -0.434 71.941 -0.746 72.099 -0.941 c
+72.264 -1.128 72.495 -1.22 72.79 -1.22 c
+72.984 -1.22 73.158 -1.187 73.304 -1.117 c
+73.451 -1.04 73.587 -0.922 73.715 -0.764 c
+74.054 -1.176 l
+73.767 -1.58 73.337 -1.779 72.761 -1.779 c
+72.687 1.793 m
+72.412 1.793 72.209 1.698 72.084 1.514 c
+71.955 1.326 71.882 1.037 71.864 0.647 c
+73.436 0.647 l
+73.436 0.735 l
+73.414 1.118 73.349 1.386 73.231 1.544 c
+73.113 1.709 72.929 1.793 72.687 1.793 c
+76.508 1.661 m
+76.42 1.679 76.321 1.691 76.215 1.691 c
+75.88 1.691 75.645 1.507 75.509 1.147 c
+75.509 -1.705 l
+74.862 -1.705 l
+74.862 2.278 l
+75.494 2.278 l
+75.509 1.866 l
+75.685 2.19 75.928 2.352 76.244 2.352 c
+76.35 2.352 76.439 2.33 76.508 2.294 c
+h
+78.199 3.234 m
+78.199 2.278 l
+78.802 2.278 l
+78.802 1.749 l
+78.199 1.749 l
+78.199 -0.721 l
+78.199 -0.878 78.221 -0.995 78.272 -1.073 c
+78.332 -1.153 78.419 -1.191 78.537 -1.191 c
+78.625 -1.191 78.714 -1.176 78.802 -1.147 c
+78.802 -1.705 l
+78.654 -1.753 78.5 -1.779 78.346 -1.779 c
+78.089 -1.779 77.894 -1.687 77.758 -1.5 c
+77.619 -1.315 77.552 -1.055 77.552 -0.721 c
+77.552 1.749 l
+76.95 1.749 l
+76.95 2.278 l
+77.552 2.278 l
+77.552 3.234 l
+h
+80.271 -1.705 -0.646 3.983 re
+80.316 3.322 m
+80.316 3.212 80.286 3.12 80.227 3.042 c
+80.169 2.973 80.073 2.94 79.948 2.94 c
+79.83 2.94 79.735 2.973 79.668 3.042 c
+79.61 3.12 79.581 3.212 79.581 3.322 c
+79.581 3.439 79.61 3.532 79.668 3.601 c
+79.735 3.678 79.83 3.719 79.948 3.719 c
+80.073 3.719 80.169 3.678 80.227 3.601 c
+80.286 3.52 80.316 3.429 80.316 3.322 c
+81.903 2.278 m
+81.918 1.837 l
+82.172 2.18 82.494 2.352 82.888 2.352 c
+83.593 2.352 83.95 1.881 83.961 0.941 c
+83.961 -1.705 l
+83.314 -1.705 l
+83.314 0.912 l
+83.314 1.224 83.259 1.444 83.153 1.573 c
+83.042 1.698 82.888 1.764 82.683 1.764 c
+82.524 1.764 82.377 1.709 82.241 1.602 c
+82.112 1.492 82.01 1.357 81.933 1.191 c
+81.933 -1.705 l
+81.286 -1.705 l
+81.286 2.278 l
+h
+84.799 0.47 m
+84.799 1.087 84.909 1.551 85.137 1.866 c
+85.361 2.19 85.696 2.352 86.136 2.352 c
+86.537 2.352 86.842 2.176 87.048 1.823 c
+87.092 2.278 l
+87.68 2.278 l
+87.68 -1.749 l
+87.68 -2.238 87.551 -2.616 87.298 -2.881 c
+87.04 -3.146 86.687 -3.278 86.239 -3.278 c
+86.041 -3.278 85.821 -3.227 85.578 -3.131 c
+85.332 -3.032 85.152 -2.911 85.034 -2.763 c
+85.299 -2.323 l
+85.563 -2.587 85.861 -2.72 86.195 -2.72 c
+86.731 -2.72 87.007 -2.425 87.018 -1.837 c
+87.018 -1.309 l
+86.812 -1.624 86.511 -1.779 86.122 -1.779 c
+85.71 -1.779 85.387 -1.627 85.152 -1.323 c
+84.923 -1.01 84.806 -0.559 84.799 0.029 c
+h
+85.461 0.088 m
+85.461 -0.353 85.523 -0.683 85.651 -0.897 c
+85.777 -1.103 85.993 -1.205 86.298 -1.205 c
+86.621 -1.205 86.86 -1.04 87.018 -0.706 c
+87.018 1.278 l
+86.849 1.602 86.61 1.764 86.298 1.764 c
+86.004 1.764 85.787 1.661 85.651 1.455 c
+85.523 1.249 85.461 0.926 85.461 0.485 c
+h
+91.737 -1.22 m
+91.95 -1.22 92.123 -1.157 92.251 -1.029 c
+92.387 -0.893 92.461 -0.702 92.472 -0.455 c
+93.089 -0.455 l
+93.067 -0.838 92.931 -1.157 92.678 -1.411 c
+92.42 -1.658 92.108 -1.779 91.737 -1.779 c
+91.244 -1.779 90.87 -1.627 90.605 -1.323 c
+90.348 -1.01 90.223 -0.544 90.223 0.073 c
+90.223 0.515 l
+90.223 1.11 90.348 1.565 90.605 1.881 c
+90.87 2.194 91.244 2.352 91.737 2.352 c
+92.137 2.352 92.457 2.219 92.692 1.955 c
+92.935 1.698 93.067 1.353 93.089 0.912 c
+92.472 0.912 l
+92.449 1.205 92.376 1.426 92.251 1.573 c
+92.133 1.72 91.961 1.793 91.737 1.793 c
+91.443 1.793 91.226 1.694 91.09 1.5 c
+90.951 1.312 90.877 1.004 90.87 0.573 c
+90.87 0.059 l
+90.87 -0.411 90.936 -0.746 91.075 -0.941 c
+91.223 -1.128 91.443 -1.22 91.737 -1.22 c
+94.485 1.866 m
+94.739 2.19 95.059 2.352 95.441 2.352 c
+96.146 2.352 96.503 1.881 96.514 0.941 c
+96.514 -1.705 l
+95.867 -1.705 l
+95.867 0.912 l
+95.867 1.224 95.812 1.444 95.705 1.573 c
+95.595 1.698 95.441 1.764 95.235 1.764 c
+95.077 1.764 94.93 1.709 94.795 1.602 c
+94.666 1.492 94.563 1.357 94.485 1.191 c
+94.485 -1.705 l
+93.839 -1.705 l
+93.839 3.94 l
+94.485 3.94 l
+h
+99.512 -1.705 m
+99.472 -1.617 99.447 -1.469 99.439 -1.264 c
+99.204 -1.61 98.91 -1.779 98.557 -1.779 c
+98.193 -1.779 97.91 -1.683 97.704 -1.484 c
+97.506 -1.278 97.411 -0.992 97.411 -0.617 c
+97.411 -0.216 97.546 0.103 97.822 0.338 c
+98.094 0.58 98.469 0.706 98.939 0.706 c
+99.424 0.706 l
+99.424 1.132 l
+99.424 1.367 99.369 1.532 99.263 1.631 c
+99.152 1.738 98.991 1.793 98.778 1.793 c
+98.579 1.793 98.417 1.735 98.292 1.617 c
+98.175 1.5 98.116 1.353 98.116 1.176 c
+97.469 1.176 l
+97.469 1.371 97.528 1.562 97.646 1.749 c
+97.771 1.933 97.933 2.08 98.13 2.19 c
+98.336 2.297 98.564 2.352 98.822 2.352 c
+99.223 2.352 99.527 2.249 99.733 2.043 c
+99.946 1.837 100.06 1.544 100.071 1.161 c
+100.071 -0.852 l
+100.071 -1.157 100.108 -1.422 100.189 -1.646 c
+100.189 -1.705 l
+h
+98.645 -1.191 m
+98.811 -1.191 98.961 -1.147 99.101 -1.058 c
+99.248 -0.97 99.354 -0.86 99.424 -0.721 c
+99.424 0.22 l
+99.057 0.22 l
+98.741 0.22 98.498 0.151 98.322 0.015 c
+98.145 -0.114 98.057 -0.301 98.057 -0.544 c
+98.057 -0.771 98.101 -0.937 98.19 -1.043 c
+98.278 -1.143 98.429 -1.191 98.645 -1.191 c
+101.688 2.278 m
+101.702 1.837 l
+101.956 2.18 102.28 2.352 102.673 2.352 c
+103.379 2.352 103.735 1.881 103.746 0.941 c
+103.746 -1.705 l
+103.099 -1.705 l
+103.099 0.912 l
+103.099 1.224 103.044 1.444 102.938 1.573 c
+102.828 1.698 102.673 1.764 102.467 1.764 c
+102.309 1.764 102.162 1.709 102.026 1.602 c
+101.897 1.492 101.795 1.357 101.717 1.191 c
+101.717 -1.705 l
+101.07 -1.705 l
+101.07 2.278 l
+h
+104.584 0.47 m
+104.584 1.087 104.694 1.551 104.922 1.866 c
+105.146 2.19 105.48 2.352 105.922 2.352 c
+106.322 2.352 106.627 2.176 106.832 1.823 c
+106.876 2.278 l
+107.464 2.278 l
+107.464 -1.749 l
+107.464 -2.238 107.336 -2.616 107.082 -2.881 c
+106.826 -3.146 106.473 -3.278 106.024 -3.278 c
+105.826 -3.278 105.606 -3.227 105.363 -3.131 c
+105.116 -3.032 104.937 -2.911 104.819 -2.763 c
+105.083 -2.323 l
+105.348 -2.587 105.646 -2.72 105.98 -2.72 c
+106.517 -2.72 106.793 -2.425 106.803 -1.837 c
+106.803 -1.309 l
+106.597 -1.624 106.296 -1.779 105.907 -1.779 c
+105.495 -1.779 105.172 -1.627 104.937 -1.323 c
+104.709 -1.01 104.591 -0.559 104.584 0.029 c
+h
+105.245 0.088 m
+105.245 -0.353 105.307 -0.683 105.436 -0.897 c
+105.561 -1.103 105.778 -1.205 106.083 -1.205 c
+106.406 -1.205 106.645 -1.04 106.803 -0.706 c
+106.803 1.278 l
+106.635 1.602 106.396 1.764 106.083 1.764 c
+105.789 1.764 105.573 1.661 105.436 1.455 c
+105.307 1.249 105.245 0.926 105.245 0.485 c
+h
+109.846 -1.779 m
+109.346 -1.779 108.964 -1.631 108.7 -1.338 c
+108.435 -1.043 108.303 -0.61 108.303 -0.029 c
+108.303 0.441 l
+108.303 1.037 108.428 1.503 108.685 1.837 c
+108.949 2.18 109.309 2.352 109.772 2.352 c
+110.232 2.352 110.574 2.198 110.801 1.897 c
+111.036 1.602 111.158 1.139 111.169 0.515 c
+111.169 0.088 l
+108.949 0.088 l
+108.949 0 l
+108.949 -0.434 109.026 -0.746 109.184 -0.941 c
+109.35 -1.128 109.581 -1.22 109.876 -1.22 c
+110.07 -1.22 110.242 -1.187 110.39 -1.117 c
+110.537 -1.04 110.672 -0.922 110.801 -0.764 c
+111.14 -1.176 l
+110.853 -1.58 110.423 -1.779 109.846 -1.779 c
+109.772 1.793 m
+109.496 1.793 109.295 1.698 109.17 1.514 c
+109.041 1.326 108.968 1.037 108.949 0.647 c
+110.522 0.647 l
+110.522 0.735 l
+110.5 1.118 110.434 1.386 110.317 1.544 c
+110.199 1.709 110.015 1.793 109.772 1.793 c
+113.888 -0.691 m
+113.888 -0.544 113.833 -0.422 113.727 -0.324 c
+113.616 -0.228 113.411 -0.11 113.109 0.029 c
+112.764 0.177 112.521 0.298 112.374 0.397 c
+112.227 0.503 112.117 0.621 112.051 0.75 c
+111.981 0.875 111.948 1.033 111.948 1.22 c
+111.948 1.544 112.066 1.812 112.301 2.028 c
+112.536 2.242 112.837 2.352 113.212 2.352 c
+113.594 2.352 113.903 2.238 114.138 2.014 c
+114.373 1.786 114.491 1.5 114.491 1.147 c
+113.845 1.147 l
+113.845 1.323 113.785 1.474 113.668 1.602 c
+113.55 1.727 113.396 1.793 113.212 1.793 c
+113.014 1.793 112.863 1.738 112.756 1.631 c
+112.646 1.532 112.594 1.4 112.594 1.235 c
+112.594 1.106 112.632 1 112.712 0.912 c
+112.789 0.831 112.981 0.728 113.286 0.603 c
+113.764 0.416 114.094 0.228 114.271 0.044 c
+114.447 -0.133 114.535 -0.36 114.535 -0.632 c
+114.535 -0.985 114.41 -1.264 114.167 -1.469 c
+113.932 -1.675 113.616 -1.779 113.226 -1.779 c
+112.804 -1.779 112.466 -1.661 112.212 -1.426 c
+111.956 -1.183 111.83 -0.878 111.83 -0.515 c
+112.477 -0.515 l
+112.484 -0.742 112.554 -0.918 112.683 -1.043 c
+112.808 -1.161 112.991 -1.22 113.226 -1.22 c
+113.44 -1.22 113.602 -1.172 113.712 -1.073 c
+113.829 -0.977 113.888 -0.849 113.888 -0.691 c
+117.386 -1.705 m
+117.386 1.749 l
+116.858 1.749 l
+116.858 2.278 l
+117.386 2.278 l
+117.386 2.734 l
+117.386 3.135 117.482 3.447 117.681 3.675 c
+117.886 3.899 118.165 4.013 118.518 4.013 c
+118.655 4.013 118.787 3.991 118.915 3.954 c
+118.886 3.41 l
+118.787 3.429 118.687 3.439 118.591 3.439 c
+118.217 3.439 118.034 3.175 118.034 2.646 c
+118.034 2.278 l
+118.709 2.278 l
+118.709 1.749 l
+118.034 1.749 l
+118.034 -1.705 l
+h
+121.12 1.661 m
+121.032 1.679 120.933 1.691 120.826 1.691 c
+120.492 1.691 120.257 1.507 120.12 1.147 c
+120.12 -1.705 l
+119.474 -1.705 l
+119.474 2.278 l
+120.106 2.278 l
+120.12 1.866 l
+120.297 2.19 120.54 2.352 120.856 2.352 c
+120.962 2.352 121.051 2.33 121.12 2.294 c
+h
+121.561 0.47 m
+121.561 1.047 121.697 1.503 121.973 1.837 c
+122.256 2.18 122.627 2.352 123.09 2.352 c
+123.549 2.352 123.917 2.183 124.193 1.852 c
+124.475 1.529 124.623 1.081 124.633 0.515 c
+124.633 0.088 l
+124.633 -0.482 124.49 -0.937 124.207 -1.278 c
+123.931 -1.613 123.564 -1.779 123.104 -1.779 c
+122.641 -1.779 122.271 -1.617 121.988 -1.294 c
+121.712 -0.962 121.569 -0.522 121.561 0.029 c
+h
+122.208 0.088 m
+122.208 -0.316 122.285 -0.632 122.443 -0.867 c
+122.608 -1.103 122.829 -1.22 123.104 -1.22 c
+123.671 -1.22 123.964 -0.808 123.987 0.015 c
+123.987 0.47 l
+123.987 0.871 123.902 1.191 123.736 1.426 c
+123.578 1.669 123.362 1.793 123.09 1.793 c
+122.825 1.793 122.608 1.669 122.443 1.426 c
+122.285 1.191 122.208 0.871 122.208 0.47 c
+h
+126.088 2.278 m
+126.103 1.911 l
+126.346 2.205 126.665 2.352 127.058 2.352 c
+127.499 2.352 127.808 2.153 127.985 1.764 c
+128.238 2.153 128.587 2.352 129.028 2.352 c
+129.763 2.352 130.138 1.889 130.16 0.97 c
+130.16 -1.705 l
+129.513 -1.705 l
+129.513 0.912 l
+129.513 1.205 129.458 1.419 129.352 1.558 c
+129.252 1.694 129.08 1.764 128.837 1.764 c
+128.639 1.764 128.477 1.683 128.352 1.529 c
+128.234 1.382 128.164 1.191 128.147 0.956 c
+128.147 -1.705 l
+127.485 -1.705 l
+127.485 0.941 l
+127.485 1.488 127.264 1.764 126.823 1.764 c
+126.489 1.764 126.254 1.602 126.117 1.278 c
+126.117 -1.705 l
+125.471 -1.705 l
+125.471 2.278 l
+h
+133.703 3.234 m
+133.703 2.278 l
+134.306 2.278 l
+134.306 1.749 l
+133.703 1.749 l
+133.703 -0.721 l
+133.703 -0.878 133.724 -0.995 133.776 -1.073 c
+133.835 -1.153 133.923 -1.191 134.04 -1.191 c
+134.129 -1.191 134.217 -1.176 134.306 -1.147 c
+134.306 -1.705 l
+134.158 -1.753 134.004 -1.779 133.849 -1.779 c
+133.593 -1.779 133.398 -1.687 133.261 -1.5 c
+133.122 -1.315 133.055 -1.055 133.055 -0.721 c
+133.055 1.749 l
+132.453 1.749 l
+132.453 2.278 l
+133.055 2.278 l
+133.055 3.234 l
+h
+135.717 1.866 m
+135.97 2.19 136.29 2.352 136.672 2.352 c
+137.377 2.352 137.734 1.881 137.745 0.941 c
+137.745 -1.705 l
+137.098 -1.705 l
+137.098 0.912 l
+137.098 1.224 137.043 1.444 136.936 1.573 c
+136.826 1.698 136.672 1.764 136.466 1.764 c
+136.307 1.764 136.161 1.709 136.025 1.602 c
+135.896 1.492 135.794 1.357 135.717 1.191 c
+135.717 -1.705 l
+135.069 -1.705 l
+135.069 3.94 l
+135.717 3.94 l
+h
+140.126 -1.779 m
+139.626 -1.779 139.244 -1.631 138.979 -1.338 c
+138.715 -1.043 138.582 -0.61 138.582 -0.029 c
+138.582 0.441 l
+138.582 1.037 138.707 1.503 138.965 1.837 c
+139.229 2.18 139.59 2.352 140.053 2.352 c
+140.512 2.352 140.854 2.198 141.082 1.897 c
+141.317 1.602 141.438 1.139 141.449 0.515 c
+141.449 0.088 l
+139.229 0.088 l
+139.229 0 l
+139.229 -0.434 139.307 -0.746 139.465 -0.941 c
+139.63 -1.128 139.862 -1.22 140.155 -1.22 c
+140.35 -1.22 140.523 -1.187 140.67 -1.117 c
+140.816 -1.04 140.953 -0.922 141.082 -0.764 c
+141.419 -1.176 l
+141.133 -1.58 140.703 -1.779 140.126 -1.779 c
+140.053 1.793 m
+139.777 1.793 139.575 1.698 139.45 1.514 c
+139.322 1.326 139.248 1.037 139.229 0.647 c
+140.802 0.647 l
+140.802 0.735 l
+140.78 1.118 140.714 1.386 140.596 1.544 c
+140.479 1.709 140.295 1.793 140.053 1.793 c
+145.888 -0.691 m
+145.888 -0.544 145.833 -0.422 145.726 -0.324 c
+145.616 -0.228 145.41 -0.11 145.109 0.029 c
+144.764 0.177 144.521 0.298 144.374 0.397 c
+144.227 0.503 144.117 0.621 144.051 0.75 c
+143.981 0.875 143.948 1.033 143.948 1.22 c
+143.948 1.544 144.066 1.812 144.301 2.028 c
+144.536 2.242 144.837 2.352 145.212 2.352 c
+145.594 2.352 145.903 2.238 146.138 2.014 c
+146.373 1.786 146.491 1.5 146.491 1.147 c
+145.844 1.147 l
+145.844 1.323 145.785 1.474 145.668 1.602 c
+145.55 1.727 145.396 1.793 145.212 1.793 c
+145.013 1.793 144.863 1.738 144.756 1.631 c
+144.646 1.532 144.594 1.4 144.594 1.235 c
+144.594 1.106 144.631 1 144.712 0.912 c
+144.789 0.831 144.98 0.728 145.285 0.603 c
+145.763 0.416 146.094 0.228 146.27 0.044 c
+146.447 -0.133 146.535 -0.36 146.535 -0.632 c
+146.535 -0.985 146.41 -1.264 146.167 -1.469 c
+145.932 -1.675 145.616 -1.779 145.227 -1.779 c
+144.804 -1.779 144.466 -1.661 144.213 -1.426 c
+143.955 -1.183 143.831 -0.878 143.831 -0.515 c
+144.477 -0.515 l
+144.484 -0.742 144.554 -0.918 144.683 -1.043 c
+144.808 -1.161 144.991 -1.22 145.227 -1.22 c
+145.44 -1.22 145.601 -1.172 145.712 -1.073 c
+145.83 -0.977 145.888 -0.849 145.888 -0.691 c
+150.254 0.088 m
+150.254 -0.54 150.136 -1.01 149.901 -1.323 c
+149.674 -1.627 149.357 -1.779 148.945 -1.779 c
+148.541 -1.779 148.232 -1.627 148.02 -1.323 c
+148.02 -3.233 l
+147.372 -3.233 l
+147.372 2.278 l
+147.96 2.278 l
+148.005 1.837 l
+148.218 2.18 148.527 2.352 148.93 2.352 c
+149.372 2.352 149.699 2.198 149.915 1.897 c
+150.129 1.592 150.243 1.135 150.254 0.53 c
+h
+149.607 0.47 m
+149.607 0.912 149.537 1.235 149.401 1.44 c
+149.261 1.654 149.041 1.764 148.739 1.764 c
+148.423 1.764 148.185 1.61 148.02 1.309 c
+148.02 -0.764 l
+148.185 -1.07 148.423 -1.22 148.739 -1.22 c
+149.034 -1.22 149.246 -1.117 149.387 -0.912 c
+149.522 -0.698 149.596 -0.368 149.607 0.073 c
+h
+152.517 -1.779 m
+152.018 -1.779 151.635 -1.631 151.371 -1.338 c
+151.106 -1.043 150.974 -0.61 150.974 -0.029 c
+150.974 0.441 l
+150.974 1.037 151.099 1.503 151.357 1.837 c
+151.621 2.18 151.981 2.352 152.444 2.352 c
+152.903 2.352 153.245 2.198 153.473 1.897 c
+153.708 1.602 153.83 1.139 153.84 0.515 c
+153.84 0.088 l
+151.621 0.088 l
+151.621 0 l
+151.621 -0.434 151.698 -0.746 151.856 -0.941 c
+152.022 -1.128 152.253 -1.22 152.547 -1.22 c
+152.741 -1.22 152.914 -1.187 153.061 -1.117 c
+153.208 -1.04 153.344 -0.922 153.473 -0.764 c
+153.811 -1.176 l
+153.524 -1.58 153.094 -1.779 152.517 -1.779 c
+152.444 1.793 m
+152.168 1.793 151.966 1.698 151.841 1.514 c
+151.713 1.326 151.639 1.037 151.621 0.647 c
+153.194 0.647 l
+153.194 0.735 l
+153.171 1.118 153.105 1.386 152.988 1.544 c
+152.87 1.709 152.687 1.793 152.444 1.793 c
+156.001 -1.22 m
+156.214 -1.22 156.387 -1.157 156.516 -1.029 c
+156.652 -0.893 156.725 -0.702 156.736 -0.455 c
+157.354 -0.455 l
+157.331 -0.838 157.196 -1.157 156.942 -1.411 c
+156.685 -1.658 156.373 -1.779 156.001 -1.779 c
+155.509 -1.779 155.134 -1.627 154.869 -1.323 c
+154.612 -1.01 154.487 -0.544 154.487 0.073 c
+154.487 0.515 l
+154.487 1.11 154.612 1.565 154.869 1.881 c
+155.134 2.194 155.509 2.352 156.001 2.352 c
+156.402 2.352 156.722 2.219 156.957 1.955 c
+157.199 1.698 157.331 1.353 157.354 0.912 c
+156.736 0.912 l
+156.714 1.205 156.641 1.426 156.516 1.573 c
+156.398 1.72 156.225 1.793 156.001 1.793 c
+155.707 1.793 155.49 1.694 155.355 1.5 c
+155.214 1.312 155.141 1.004 155.134 0.573 c
+155.134 0.059 l
+155.134 -0.411 155.2 -0.746 155.34 -0.941 c
+155.486 -1.128 155.707 -1.22 156.001 -1.22 c
+158.808 -1.705 -0.646 3.983 re
+158.852 3.322 m
+158.852 3.212 158.823 3.12 158.765 3.042 c
+158.706 2.973 158.611 2.94 158.485 2.94 c
+158.368 2.94 158.272 2.973 158.206 3.042 c
+158.147 3.12 158.118 3.212 158.118 3.322 c
+158.118 3.439 158.147 3.532 158.206 3.601 c
+158.272 3.678 158.368 3.719 158.485 3.719 c
+158.611 3.719 158.706 3.678 158.765 3.601 c
+158.823 3.52 158.852 3.429 158.852 3.322 c
+159.999 -1.705 m
+159.999 1.749 l
+159.484 1.749 l
+159.484 2.278 l
+159.999 2.278 l
+159.999 2.646 l
+160.007 3.076 160.12 3.41 160.337 3.645 c
+160.562 3.888 160.874 4.013 161.278 4.013 c
+161.425 4.013 161.564 3.991 161.705 3.954 c
+161.851 3.913 162.002 3.859 162.16 3.792 c
+162.042 3.219 l
+161.807 3.344 161.564 3.41 161.322 3.41 c
+161.076 3.41 160.903 3.341 160.807 3.204 c
+160.708 3.076 160.66 2.881 160.66 2.616 c
+160.66 2.278 l
+161.308 2.278 l
+161.308 1.749 l
+160.66 1.749 l
+160.66 -1.705 l
+h
+162.469 -1.705 -0.646 3.983 re
+164.938 -1.779 m
+164.438 -1.779 164.056 -1.631 163.791 -1.338 c
+163.527 -1.043 163.394 -0.61 163.394 -0.029 c
+163.394 0.441 l
+163.394 1.037 163.519 1.503 163.777 1.837 c
+164.041 2.18 164.402 2.352 164.865 2.352 c
+165.324 2.352 165.666 2.198 165.894 1.897 c
+166.129 1.602 166.25 1.139 166.261 0.515 c
+166.261 0.088 l
+164.041 0.088 l
+164.041 0 l
+164.041 -0.434 164.119 -0.746 164.277 -0.941 c
+164.442 -1.128 164.674 -1.22 164.967 -1.22 c
+165.162 -1.22 165.335 -1.187 165.482 -1.117 c
+165.628 -1.04 165.765 -0.922 165.894 -0.764 c
+166.231 -1.176 l
+165.945 -1.58 165.515 -1.779 164.938 -1.779 c
+164.865 1.793 m
+164.589 1.793 164.387 1.698 164.262 1.514 c
+164.134 1.326 164.059 1.037 164.041 0.647 c
+165.614 0.647 l
+165.614 0.735 l
+165.592 1.118 165.526 1.386 165.408 1.544 c
+165.291 1.709 165.107 1.793 164.865 1.793 c
+166.908 0.47 m
+166.908 1.077 167.018 1.544 167.246 1.866 c
+167.481 2.19 167.808 2.352 168.231 2.352 c
+168.612 2.352 168.911 2.194 169.127 1.881 c
+169.127 3.94 l
+169.774 3.94 l
+169.774 -1.705 l
+169.186 -1.705 l
+169.142 -1.278 l
+168.936 -1.613 168.631 -1.779 168.231 -1.779 c
+167.819 -1.779 167.496 -1.624 167.261 -1.309 c
+167.025 -0.985 166.908 -0.529 166.908 0.059 c
+h
+167.554 0.088 m
+167.554 -0.353 167.617 -0.683 167.745 -0.897 c
+167.882 -1.103 168.102 -1.205 168.407 -1.205 c
+168.73 -1.205 168.969 -1.043 169.127 -0.721 c
+169.127 1.294 l
+168.959 1.606 168.72 1.764 168.407 1.764 c
+168.102 1.764 167.882 1.661 167.745 1.455 c
+167.617 1.249 167.554 0.926 167.554 0.485 c
+h
+173.875 -1.22 m
+174.089 -1.22 174.261 -1.157 174.39 -1.029 c
+174.526 -0.893 174.599 -0.702 174.61 -0.455 c
+175.228 -0.455 l
+175.205 -0.838 175.07 -1.157 174.816 -1.411 c
+174.559 -1.658 174.247 -1.779 173.875 -1.779 c
+173.383 -1.779 173.008 -1.627 172.743 -1.323 c
+172.486 -1.01 172.361 -0.544 172.361 0.073 c
+172.361 0.515 l
+172.361 1.11 172.486 1.565 172.743 1.881 c
+173.008 2.194 173.383 2.352 173.875 2.352 c
+174.276 2.352 174.596 2.219 174.831 1.955 c
+175.073 1.698 175.205 1.353 175.228 0.912 c
+174.61 0.912 l
+174.588 1.205 174.515 1.426 174.39 1.573 c
+174.272 1.72 174.099 1.793 173.875 1.793 c
+173.581 1.793 173.364 1.694 173.229 1.5 c
+173.089 1.312 173.015 1.004 173.008 0.573 c
+173.008 0.059 l
+173.008 -0.411 173.074 -0.746 173.214 -0.941 c
+173.36 -1.128 173.581 -1.22 173.875 -1.22 c
+175.845 0.47 m
+175.845 1.047 175.98 1.503 176.256 1.837 c
+176.539 2.18 176.911 2.352 177.374 2.352 c
+177.833 2.352 178.201 2.183 178.476 1.852 c
+178.759 1.529 178.906 1.081 178.916 0.515 c
+178.916 0.088 l
+178.916 -0.482 178.773 -0.937 178.49 -1.278 c
+178.215 -1.613 177.848 -1.779 177.388 -1.779 c
+176.925 -1.779 176.554 -1.617 176.271 -1.294 c
+175.995 -0.962 175.852 -0.522 175.845 0.029 c
+h
+176.491 0.088 m
+176.491 -0.316 176.568 -0.632 176.726 -0.867 c
+176.892 -1.103 177.113 -1.22 177.388 -1.22 c
+177.954 -1.22 178.249 -0.808 178.27 0.015 c
+178.27 0.47 l
+178.27 0.871 178.185 1.191 178.02 1.426 c
+177.862 1.669 177.646 1.793 177.374 1.793 c
+177.109 1.793 176.892 1.669 176.726 1.426 c
+176.568 1.191 176.491 0.871 176.491 0.47 c
+h
+180.372 2.278 m
+180.387 1.911 l
+180.63 2.205 180.949 2.352 181.343 2.352 c
+181.783 2.352 182.091 2.153 182.268 1.764 c
+182.522 2.153 182.871 2.352 183.312 2.352 c
+184.047 2.352 184.422 1.889 184.443 0.97 c
+184.443 -1.705 l
+183.797 -1.705 l
+183.797 0.912 l
+183.797 1.205 183.741 1.419 183.635 1.558 c
+183.536 1.694 183.363 1.764 183.121 1.764 c
+182.922 1.764 182.76 1.683 182.636 1.529 c
+182.519 1.382 182.448 1.191 182.43 0.956 c
+182.43 -1.705 l
+181.769 -1.705 l
+181.769 0.941 l
+181.769 1.488 181.548 1.764 181.107 1.764 c
+180.772 1.764 180.537 1.602 180.402 1.278 c
+180.402 -1.705 l
+179.755 -1.705 l
+179.755 2.278 l
+h
+186.031 2.278 m
+186.046 1.911 l
+186.288 2.205 186.608 2.352 187.001 2.352 c
+187.442 2.352 187.751 2.153 187.928 1.764 c
+188.181 2.153 188.53 2.352 188.971 2.352 c
+189.706 2.352 190.081 1.889 190.103 0.97 c
+190.103 -1.705 l
+189.456 -1.705 l
+189.456 0.912 l
+189.456 1.205 189.401 1.419 189.295 1.558 c
+189.195 1.694 189.023 1.764 188.78 1.764 c
+188.582 1.764 188.42 1.683 188.295 1.529 c
+188.177 1.382 188.107 1.191 188.089 0.956 c
+188.089 -1.705 l
+187.427 -1.705 l
+187.427 0.941 l
+187.427 1.488 187.207 1.764 186.766 1.764 c
+186.432 1.764 186.197 1.602 186.06 1.278 c
+186.06 -1.705 l
+185.414 -1.705 l
+185.414 2.278 l
+h
+191.778 -1.705 -0.646 3.983 re
+191.822 3.322 m
+191.822 3.212 191.793 3.12 191.734 3.042 c
+191.676 2.973 191.58 2.94 191.456 2.94 c
+191.338 2.94 191.242 2.973 191.176 3.042 c
+191.117 3.12 191.088 3.212 191.088 3.322 c
+191.088 3.439 191.117 3.532 191.176 3.601 c
+191.242 3.678 191.338 3.719 191.456 3.719 c
+191.58 3.719 191.676 3.678 191.734 3.601 c
+191.793 3.52 191.822 3.429 191.822 3.322 c
+193.646 3.234 m
+193.646 2.278 l
+194.248 2.278 l
+194.248 1.749 l
+193.646 1.749 l
+193.646 -0.721 l
+193.646 -0.878 193.667 -0.995 193.719 -1.073 c
+193.777 -1.153 193.866 -1.191 193.983 -1.191 c
+194.072 -1.191 194.16 -1.176 194.248 -1.147 c
+194.248 -1.705 l
+194.101 -1.753 193.947 -1.779 193.792 -1.779 c
+193.536 -1.779 193.341 -1.687 193.204 -1.5 c
+193.065 -1.315 192.998 -1.055 192.998 -0.721 c
+192.998 1.749 l
+192.396 1.749 l
+192.396 2.278 l
+192.998 2.278 l
+192.998 3.234 l
+h
+195.057 -1.352 m
+195.057 -1.234 195.09 -1.139 195.159 -1.058 c
+195.225 -0.981 195.329 -0.941 195.468 -0.941 c
+195.615 -0.941 195.722 -0.981 195.791 -1.058 c
+195.869 -1.139 195.909 -1.234 195.909 -1.352 c
+195.909 -1.463 195.869 -1.554 195.791 -1.631 c
+195.722 -1.708 195.615 -1.749 195.468 -1.749 c
+195.329 -1.749 195.225 -1.708 195.159 -1.631 c
+195.09 -1.554 195.057 -1.463 195.057 -1.352 c
+199.51 -1.705 -0.676 5.35 re
+201.451 3.234 m
+201.451 2.278 l
+202.053 2.278 l
+202.053 1.749 l
+201.451 1.749 l
+201.451 -0.721 l
+201.451 -0.878 201.472 -0.995 201.524 -1.073 c
+201.583 -1.153 201.671 -1.191 201.789 -1.191 c
+201.877 -1.191 201.964 -1.176 202.053 -1.147 c
+202.053 -1.705 l
+201.906 -1.753 201.752 -1.779 201.598 -1.779 c
+201.34 -1.779 201.145 -1.687 201.01 -1.5 c
+200.87 -1.315 200.804 -1.055 200.804 -0.721 c
+200.804 1.749 l
+200.201 1.749 l
+200.201 2.278 l
+200.804 2.278 l
+200.804 3.234 l
+h
+f
+Q
+q 1 0 0 1 412.9262 238.2432 cm
+0 0 m
+0 0.617 0.11 1.081 0.338 1.396 c
+0.563 1.72 0.897 1.881 1.338 1.881 c
+1.738 1.881 2.043 1.706 2.249 1.353 c
+2.294 1.808 l
+2.881 1.808 l
+2.881 -2.219 l
+2.881 -2.708 2.753 -3.087 2.499 -3.351 c
+2.242 -3.616 1.889 -3.748 1.44 -3.748 c
+1.242 -3.748 1.022 -3.697 0.779 -3.601 c
+0.533 -3.502 0.353 -3.381 0.235 -3.233 c
+0.5 -2.793 l
+0.765 -3.057 1.062 -3.19 1.396 -3.19 c
+1.933 -3.19 2.209 -2.896 2.219 -2.308 c
+2.219 -1.779 l
+2.014 -2.094 1.712 -2.249 1.323 -2.249 c
+0.912 -2.249 0.588 -2.098 0.353 -1.793 c
+0.125 -1.481 0.008 -1.029 0 -0.441 c
+h
+0.661 -0.382 m
+0.661 -0.823 0.724 -1.153 0.852 -1.367 c
+0.977 -1.573 1.195 -1.675 1.5 -1.675 c
+1.823 -1.675 2.061 -1.51 2.219 -1.176 c
+2.219 0.808 l
+2.051 1.132 1.812 1.294 1.5 1.294 c
+1.205 1.294 0.989 1.191 0.852 0.985 c
+0.724 0.779 0.661 0.455 0.661 0.015 c
+h
+5.262 -2.249 m
+4.763 -2.249 4.38 -2.102 4.116 -1.808 c
+3.851 -1.514 3.719 -1.08 3.719 -0.5 c
+3.719 -0.029 l
+3.719 0.566 3.844 1.033 4.101 1.367 c
+4.366 1.709 4.726 1.881 5.189 1.881 c
+5.648 1.881 5.99 1.727 6.217 1.426 c
+6.453 1.132 6.574 0.669 6.585 0.044 c
+6.585 -0.382 l
+4.366 -0.382 l
+4.366 -0.47 l
+4.366 -0.904 4.443 -1.216 4.601 -1.411 c
+4.767 -1.598 4.998 -1.691 5.292 -1.691 c
+5.486 -1.691 5.659 -1.658 5.806 -1.587 c
+5.953 -1.51 6.089 -1.392 6.217 -1.234 c
+6.556 -1.646 l
+6.269 -2.051 5.839 -2.249 5.262 -2.249 c
+5.189 1.323 m
+4.913 1.323 4.711 1.228 4.586 1.043 c
+4.457 0.856 4.384 0.566 4.366 0.177 c
+5.939 0.177 l
+5.939 0.264 l
+5.916 0.647 5.85 0.915 5.733 1.073 c
+5.615 1.239 5.432 1.323 5.189 1.323 c
+7.981 1.808 m
+7.996 1.367 l
+8.25 1.709 8.573 1.881 8.966 1.881 c
+9.672 1.881 10.028 1.411 10.04 0.47 c
+10.04 -2.175 l
+9.392 -2.175 l
+9.392 0.441 l
+9.392 0.754 9.338 0.974 9.231 1.103 c
+9.12 1.228 8.966 1.294 8.761 1.294 c
+8.603 1.294 8.455 1.239 8.32 1.132 c
+8.191 1.022 8.088 0.886 8.011 0.721 c
+8.011 -2.175 l
+7.364 -2.175 l
+7.364 1.808 l
+h
+12.436 -2.249 m
+11.936 -2.249 11.553 -2.102 11.289 -1.808 c
+11.025 -1.514 10.892 -1.08 10.892 -0.5 c
+10.892 -0.029 l
+10.892 0.566 11.017 1.033 11.274 1.367 c
+11.539 1.709 11.899 1.881 12.362 1.881 c
+12.821 1.881 13.163 1.727 13.391 1.426 c
+13.626 1.132 13.747 0.669 13.758 0.044 c
+13.758 -0.382 l
+11.539 -0.382 l
+11.539 -0.47 l
+11.539 -0.904 11.616 -1.216 11.774 -1.411 c
+11.939 -1.598 12.171 -1.691 12.465 -1.691 c
+12.66 -1.691 12.833 -1.658 12.979 -1.587 c
+13.126 -1.51 13.263 -1.392 13.391 -1.234 c
+13.729 -1.646 l
+13.442 -2.051 13.012 -2.249 12.436 -2.249 c
+12.362 1.323 m
+12.087 1.323 11.884 1.228 11.759 1.043 c
+11.63 0.856 11.557 0.566 11.539 0.177 c
+13.112 0.177 l
+13.112 0.264 l
+13.089 0.647 13.024 0.915 12.906 1.073 c
+12.788 1.239 12.605 1.323 12.362 1.323 c
+16.184 1.191 m
+16.095 1.209 15.996 1.22 15.89 1.22 c
+15.555 1.22 15.32 1.037 15.184 0.676 c
+15.184 -2.175 l
+14.537 -2.175 l
+14.537 1.808 l
+15.169 1.808 l
+15.184 1.396 l
+15.36 1.72 15.603 1.881 15.919 1.881 c
+16.025 1.881 16.114 1.86 16.184 1.823 c
+h
+18.726 -2.175 m
+18.686 -2.087 18.66 -1.94 18.653 -1.735 c
+18.418 -2.08 18.124 -2.249 17.771 -2.249 c
+17.407 -2.249 17.124 -2.153 16.918 -1.955 c
+16.721 -1.749 16.625 -1.463 16.625 -1.087 c
+16.625 -0.687 16.761 -0.368 17.036 -0.133 c
+17.309 0.11 17.683 0.235 18.153 0.235 c
+18.639 0.235 l
+18.639 0.661 l
+18.639 0.897 18.583 1.062 18.477 1.161 c
+18.367 1.268 18.205 1.323 17.992 1.323 c
+17.793 1.323 17.631 1.264 17.506 1.147 c
+17.389 1.029 17.33 0.882 17.33 0.706 c
+16.683 0.706 l
+16.683 0.9 16.742 1.091 16.86 1.278 c
+16.985 1.463 17.147 1.61 17.345 1.72 c
+17.55 1.827 17.779 1.881 18.036 1.881 c
+18.437 1.881 18.741 1.779 18.947 1.573 c
+19.16 1.367 19.274 1.073 19.285 0.691 c
+19.285 -1.323 l
+19.285 -1.627 19.322 -1.893 19.403 -2.117 c
+19.403 -2.175 l
+h
+17.859 -1.661 m
+18.025 -1.661 18.175 -1.617 18.315 -1.529 c
+18.462 -1.44 18.568 -1.33 18.639 -1.191 c
+18.639 -0.25 l
+18.271 -0.25 l
+17.955 -0.25 17.712 -0.32 17.536 -0.455 c
+17.359 -0.584 17.271 -0.771 17.271 -1.014 c
+17.271 -1.242 17.315 -1.407 17.404 -1.514 c
+17.492 -1.613 17.643 -1.661 17.859 -1.661 c
+21.137 2.764 m
+21.137 1.808 l
+21.74 1.808 l
+21.74 1.278 l
+21.137 1.278 l
+21.137 -1.191 l
+21.137 -1.348 21.159 -1.466 21.211 -1.544 c
+21.269 -1.624 21.358 -1.661 21.475 -1.661 c
+21.564 -1.661 21.652 -1.646 21.74 -1.617 c
+21.74 -2.175 l
+21.593 -2.223 21.439 -2.249 21.284 -2.249 c
+21.027 -2.249 20.833 -2.157 20.696 -1.97 c
+20.557 -1.786 20.49 -1.525 20.49 -1.191 c
+20.49 1.278 l
+19.888 1.278 l
+19.888 1.808 l
+20.49 1.808 l
+20.49 2.764 l
+h
+23.931 -2.249 m
+23.43 -2.249 23.048 -2.102 22.784 -1.808 c
+22.519 -1.514 22.387 -1.08 22.387 -0.5 c
+22.387 -0.029 l
+22.387 0.566 22.512 1.033 22.769 1.367 c
+23.033 1.709 23.393 1.881 23.856 1.881 c
+24.316 1.881 24.658 1.727 24.885 1.426 c
+25.121 1.132 25.242 0.669 25.253 0.044 c
+25.253 -0.382 l
+23.033 -0.382 l
+23.033 -0.47 l
+23.033 -0.904 23.111 -1.216 23.268 -1.411 c
+23.434 -1.598 23.665 -1.691 23.96 -1.691 c
+24.154 -1.691 24.327 -1.658 24.474 -1.587 c
+24.621 -1.51 24.757 -1.392 24.885 -1.234 c
+25.224 -1.646 l
+24.937 -2.051 24.507 -2.249 23.931 -2.249 c
+23.856 1.323 m
+23.582 1.323 23.379 1.228 23.254 1.043 c
+23.125 0.856 23.052 0.566 23.033 0.177 c
+24.606 0.177 l
+24.606 0.264 l
+24.584 0.647 24.518 0.915 24.401 1.073 c
+24.283 1.239 24.099 1.323 23.856 1.323 c
+27.972 -1.161 m
+27.972 -1.014 27.917 -0.893 27.811 -0.794 c
+27.7 -0.698 27.495 -0.58 27.193 -0.441 c
+26.848 -0.294 26.605 -0.172 26.458 -0.073 c
+26.312 0.033 26.201 0.151 26.135 0.279 c
+26.065 0.405 26.032 0.563 26.032 0.75 c
+26.032 1.073 26.15 1.341 26.385 1.558 c
+26.62 1.771 26.921 1.881 27.296 1.881 c
+27.678 1.881 27.987 1.768 28.222 1.544 c
+28.457 1.316 28.575 1.029 28.575 0.676 c
+27.929 0.676 l
+27.929 0.852 27.869 1.004 27.752 1.132 c
+27.634 1.257 27.48 1.323 27.296 1.323 c
+27.098 1.323 26.947 1.268 26.84 1.161 c
+26.73 1.062 26.678 0.929 26.678 0.765 c
+26.678 0.636 26.716 0.53 26.796 0.441 c
+26.874 0.36 27.065 0.258 27.37 0.133 c
+27.848 -0.055 28.178 -0.243 28.355 -0.426 c
+28.531 -0.603 28.619 -0.831 28.619 -1.103 c
+28.619 -1.455 28.494 -1.735 28.251 -1.94 c
+28.016 -2.146 27.7 -2.249 27.311 -2.249 c
+26.888 -2.249 26.55 -2.132 26.296 -1.897 c
+26.04 -1.654 25.915 -1.348 25.915 -0.985 c
+26.561 -0.985 l
+26.568 -1.213 26.639 -1.389 26.767 -1.514 c
+26.892 -1.631 27.075 -1.691 27.311 -1.691 c
+27.524 -1.691 27.686 -1.643 27.796 -1.544 c
+27.914 -1.448 27.972 -1.319 27.972 -1.161 c
+33.22 -2.175 m
+33.18 -2.087 33.154 -1.94 33.146 -1.735 c
+32.911 -2.08 32.617 -2.249 32.265 -2.249 c
+31.9 -2.249 31.617 -2.153 31.412 -1.955 c
+31.214 -1.749 31.118 -1.463 31.118 -1.087 c
+31.118 -0.687 31.254 -0.368 31.53 -0.133 c
+31.802 0.11 32.176 0.235 32.646 0.235 c
+33.132 0.235 l
+33.132 0.661 l
+33.132 0.897 33.076 1.062 32.97 1.161 c
+32.86 1.268 32.698 1.323 32.485 1.323 c
+32.286 1.323 32.125 1.264 32 1.147 c
+31.883 1.029 31.823 0.882 31.823 0.706 c
+31.177 0.706 l
+31.177 0.9 31.235 1.091 31.353 1.278 c
+31.478 1.463 31.64 1.61 31.838 1.72 c
+32.044 1.827 32.272 1.881 32.529 1.881 c
+32.93 1.881 33.234 1.779 33.44 1.573 c
+33.654 1.367 33.768 1.073 33.778 0.691 c
+33.778 -1.323 l
+33.778 -1.627 33.815 -1.893 33.896 -2.117 c
+33.896 -2.175 l
+h
+32.353 -1.661 m
+32.519 -1.661 32.669 -1.617 32.808 -1.529 c
+32.955 -1.44 33.062 -1.33 33.132 -1.191 c
+33.132 -0.25 l
+32.764 -0.25 l
+32.448 -0.25 32.205 -0.32 32.029 -0.455 c
+31.853 -0.584 31.765 -0.771 31.765 -1.014 c
+31.765 -1.242 31.809 -1.407 31.897 -1.514 c
+31.985 -1.613 32.136 -1.661 32.353 -1.661 c
+35.395 1.808 m
+35.41 1.367 l
+35.663 1.709 35.987 1.881 36.38 1.881 c
+37.086 1.881 37.442 1.411 37.454 0.47 c
+37.454 -2.175 l
+36.806 -2.175 l
+36.806 0.441 l
+36.806 0.754 36.752 0.974 36.645 1.103 c
+36.535 1.228 36.38 1.294 36.174 1.294 c
+36.016 1.294 35.869 1.239 35.733 1.132 c
+35.605 1.022 35.502 0.886 35.424 0.721 c
+35.424 -2.175 l
+34.778 -2.175 l
+34.778 1.808 l
+h
+f
+Q
+454.054 236.068 -1.044 3.983 re
+452.967 241.08 m
+452.967 241.235 453.014 241.364 453.114 241.462 c
+453.22 241.569 453.356 241.624 453.525 241.624 c
+453.702 241.624 453.837 241.569 453.937 241.462 c
+454.043 241.364 454.099 241.235 454.099 241.08 c
+454.099 240.911 454.043 240.776 453.937 240.668 c
+453.837 240.57 453.702 240.522 453.525 240.522 c
+453.356 240.522 453.22 240.57 453.114 240.668 c
+453.014 240.776 452.967 240.911 452.967 241.08 c
+455.818 240.051 m
+455.847 239.654 l
+456.083 239.967 456.384 240.125 456.759 240.125 c
+457.442 240.125 457.795 239.643 457.817 238.684 c
+457.817 236.068 l
+456.773 236.068 l
+456.773 238.611 l
+456.773 238.835 456.736 238.997 456.671 239.096 c
+456.601 239.191 456.483 239.243 456.318 239.243 c
+456.131 239.243 455.984 239.147 455.877 238.964 c
+455.877 236.068 l
+454.833 236.068 l
+454.833 240.051 l
+h
+459.875 237.538 m
+460.375 240.051 l
+461.463 240.051 l
+460.36 236.068 l
+459.375 236.068 l
+458.273 240.051 l
+459.36 240.051 l
+h
+463.506 235.994 m
+462.976 235.994 462.558 236.149 462.257 236.464 c
+461.962 236.788 461.815 237.248 461.815 237.846 c
+461.815 238.155 l
+461.815 238.779 461.951 239.265 462.227 239.61 c
+462.498 239.953 462.892 240.125 463.403 240.125 c
+463.903 240.125 464.274 239.963 464.52 239.639 c
+464.773 239.317 464.906 238.839 464.917 238.214 c
+464.917 237.714 l
+462.845 237.714 l
+462.863 237.42 462.926 237.204 463.036 237.067 c
+463.153 236.928 463.333 236.861 463.579 236.861 c
+463.921 236.861 464.212 236.979 464.447 237.214 c
+464.858 236.582 l
+464.73 236.406 464.542 236.263 464.299 236.156 c
+464.053 236.049 463.789 235.994 463.506 235.994 c
+462.859 238.434 m
+463.888 238.434 l
+463.888 238.538 l
+463.888 238.773 463.847 238.949 463.77 239.066 c
+463.701 239.191 463.572 239.257 463.388 239.257 c
+463.212 239.257 463.08 239.188 462.991 239.051 c
+462.91 238.923 462.866 238.717 462.859 238.434 c
+467.46 239.037 m
+467.121 239.066 l
+466.835 239.066 466.644 238.941 466.548 238.699 c
+466.548 236.068 l
+465.505 236.068 l
+465.505 240.051 l
+466.475 240.051 l
+466.504 239.61 l
+466.67 239.953 466.901 240.125 467.196 240.125 c
+467.313 240.125 467.404 240.103 467.474 240.066 c
+h
+469.768 237.141 m
+469.768 237.229 469.723 237.306 469.635 237.376 c
+469.547 237.453 469.359 237.556 469.077 237.684 c
+468.643 237.861 468.345 238.041 468.18 238.228 c
+468.022 238.413 467.944 238.644 467.944 238.92 c
+467.944 239.261 468.066 239.544 468.312 239.772 c
+468.566 240.007 468.904 240.125 469.326 240.125 c
+469.756 240.125 470.105 240.011 470.371 239.787 c
+470.635 239.559 470.767 239.257 470.767 238.875 c
+469.723 238.875 l
+469.723 239.199 469.584 239.361 469.312 239.361 c
+469.201 239.361 469.114 239.324 469.047 239.257 c
+468.977 239.188 468.944 239.089 468.944 238.964 c
+468.944 238.875 468.981 238.794 469.062 238.729 c
+469.139 238.669 469.319 238.574 469.606 238.449 c
+470.036 238.291 470.334 238.114 470.502 237.92 c
+470.679 237.732 470.767 237.483 470.767 237.17 c
+470.767 236.817 470.635 236.531 470.371 236.318 c
+470.105 236.101 469.756 235.994 469.326 235.994 c
+469.033 235.994 468.771 236.049 468.547 236.156 c
+468.32 236.273 468.143 236.435 468.019 236.641 c
+467.901 236.847 467.842 237.067 467.842 237.302 c
+468.827 237.302 l
+468.827 237.115 468.863 236.979 468.944 236.891 c
+469.033 236.803 469.165 236.759 469.341 236.759 c
+469.625 236.759 469.768 236.884 469.768 237.141 c
+472.516 236.068 -1.044 3.983 re
+471.429 241.08 m
+471.429 241.235 471.476 241.364 471.576 241.462 c
+471.682 241.569 471.818 241.624 471.987 241.624 c
+472.164 241.624 472.299 241.569 472.399 241.462 c
+472.505 241.364 472.561 241.235 472.561 241.08 c
+472.561 240.911 472.505 240.776 472.399 240.668 c
+472.299 240.57 472.164 240.522 471.987 240.522 c
+471.818 240.522 471.682 240.57 471.576 240.668 c
+471.476 240.776 471.429 240.911 471.429 241.08 c
+473.207 238.185 m
+473.207 238.791 473.347 239.265 473.633 239.61 c
+473.916 239.953 474.309 240.125 474.809 240.125 c
+475.316 240.125 475.713 239.953 476 239.61 c
+476.283 239.265 476.426 238.791 476.426 238.185 c
+476.426 237.92 l
+476.426 237.321 476.283 236.851 476 236.508 c
+475.713 236.163 475.316 235.994 474.809 235.994 c
+474.298 235.994 473.902 236.163 473.619 236.508 c
+473.343 236.851 473.207 237.325 473.207 237.935 c
+h
+474.251 237.92 m
+474.251 237.214 474.435 236.861 474.809 236.861 c
+475.162 236.861 475.353 237.156 475.383 237.744 c
+475.383 238.185 l
+475.383 238.544 475.331 238.816 475.235 238.993 c
+475.136 239.169 474.993 239.257 474.809 239.257 c
+474.633 239.257 474.493 239.169 474.398 238.993 c
+474.298 238.816 474.251 238.544 474.251 238.185 c
+h
+478.028 240.051 m
+478.057 239.654 l
+478.293 239.967 478.595 240.125 478.969 240.125 c
+479.653 240.125 480.006 239.643 480.027 238.684 c
+480.027 236.068 l
+478.984 236.068 l
+478.984 238.611 l
+478.984 238.835 478.947 238.997 478.881 239.096 c
+478.811 239.191 478.693 239.243 478.528 239.243 c
+478.341 239.243 478.194 239.147 478.087 238.964 c
+478.087 236.068 l
+477.043 236.068 l
+477.043 240.051 l
+h
+f
+q 1 0 0 1 482.4675 238.2432 cm
+0 0 m
+0 0.577 0.136 1.033 0.411 1.367 c
+0.694 1.709 1.066 1.881 1.529 1.881 c
+1.988 1.881 2.356 1.712 2.631 1.382 c
+2.914 1.058 3.061 0.611 3.072 0.044 c
+3.072 -0.382 l
+3.072 -0.952 2.929 -1.407 2.645 -1.749 c
+2.37 -2.084 2.003 -2.249 1.544 -2.249 c
+1.08 -2.249 0.709 -2.087 0.426 -1.764 c
+0.151 -1.433 0.008 -0.992 0 -0.441 c
+h
+0.646 -0.382 m
+0.646 -0.786 0.723 -1.103 0.882 -1.338 c
+1.047 -1.573 1.268 -1.691 1.544 -1.691 c
+2.109 -1.691 2.404 -1.278 2.425 -0.455 c
+2.425 0 l
+2.425 0.401 2.341 0.721 2.175 0.956 c
+2.018 1.199 1.801 1.323 1.529 1.323 c
+1.264 1.323 1.047 1.199 0.882 0.956 c
+0.723 0.721 0.646 0.401 0.646 0 c
+h
+4.204 -2.175 m
+4.204 1.278 l
+3.675 1.278 l
+3.675 1.808 l
+4.204 1.808 l
+4.204 2.263 l
+4.204 2.664 4.299 2.977 4.498 3.204 c
+4.704 3.429 4.983 3.543 5.336 3.543 c
+5.471 3.543 5.604 3.52 5.733 3.484 c
+5.703 2.94 l
+5.604 2.959 5.505 2.969 5.409 2.969 c
+5.035 2.969 4.85 2.705 4.85 2.176 c
+4.85 1.808 l
+5.527 1.808 l
+5.527 1.278 l
+4.85 1.278 l
+4.85 -2.175 l
+h
+9.392 -1.691 m
+9.606 -1.691 9.779 -1.627 9.907 -1.5 c
+10.043 -1.363 10.117 -1.172 10.128 -0.926 c
+10.745 -0.926 l
+10.723 -1.309 10.587 -1.627 10.333 -1.881 c
+10.076 -2.128 9.764 -2.249 9.392 -2.249 c
+8.9 -2.249 8.525 -2.098 8.261 -1.793 c
+8.004 -1.481 7.879 -1.014 7.879 -0.397 c
+7.879 0.044 l
+7.879 0.64 8.004 1.095 8.261 1.411 c
+8.525 1.723 8.9 1.881 9.392 1.881 c
+9.793 1.881 10.113 1.749 10.348 1.484 c
+10.591 1.228 10.723 0.882 10.745 0.441 c
+10.128 0.441 l
+10.105 0.735 10.032 0.956 9.907 1.103 c
+9.789 1.249 9.617 1.323 9.392 1.323 c
+9.099 1.323 8.882 1.224 8.746 1.029 c
+8.606 0.842 8.533 0.533 8.525 0.103 c
+8.525 -0.411 l
+8.525 -0.881 8.592 -1.216 8.731 -1.411 c
+8.878 -1.598 9.099 -1.691 9.392 -1.691 c
+12.141 1.396 m
+12.395 1.72 12.715 1.881 13.097 1.881 c
+13.803 1.881 14.159 1.411 14.169 0.47 c
+14.169 -2.175 l
+13.523 -2.175 l
+13.523 0.441 l
+13.523 0.754 13.468 0.974 13.361 1.103 c
+13.251 1.228 13.097 1.294 12.891 1.294 c
+12.733 1.294 12.586 1.239 12.45 1.132 c
+12.322 1.022 12.218 0.886 12.141 0.721 c
+12.141 -2.175 l
+11.495 -2.175 l
+11.495 3.469 l
+12.141 3.469 l
+h
+17.169 -2.175 m
+17.128 -2.087 17.103 -1.94 17.095 -1.735 c
+16.86 -2.08 16.565 -2.249 16.213 -2.249 c
+15.85 -2.249 15.566 -2.153 15.36 -1.955 c
+15.162 -1.749 15.067 -1.463 15.067 -1.087 c
+15.067 -0.687 15.202 -0.368 15.478 -0.133 c
+15.75 0.11 16.125 0.235 16.596 0.235 c
+17.08 0.235 l
+17.08 0.661 l
+17.08 0.897 17.026 1.062 16.918 1.161 c
+16.808 1.268 16.646 1.323 16.434 1.323 c
+16.235 1.323 16.074 1.264 15.948 1.147 c
+15.831 1.029 15.772 0.882 15.772 0.706 c
+15.125 0.706 l
+15.125 0.9 15.185 1.091 15.302 1.278 c
+15.426 1.463 15.588 1.61 15.787 1.72 c
+15.993 1.827 16.22 1.881 16.478 1.881 c
+16.878 1.881 17.184 1.779 17.389 1.573 c
+17.602 1.367 17.716 1.073 17.727 0.691 c
+17.727 -1.323 l
+17.727 -1.627 17.764 -1.893 17.845 -2.117 c
+17.845 -2.175 l
+h
+16.301 -1.661 m
+16.467 -1.661 16.617 -1.617 16.756 -1.529 c
+16.904 -1.44 17.01 -1.33 17.08 -1.191 c
+17.08 -0.25 l
+16.713 -0.25 l
+16.397 -0.25 16.154 -0.32 15.978 -0.455 c
+15.802 -0.584 15.713 -0.771 15.713 -1.014 c
+15.713 -1.242 15.757 -1.407 15.846 -1.514 c
+15.933 -1.613 16.085 -1.661 16.301 -1.661 c
+19.343 1.808 m
+19.359 1.367 l
+19.613 1.709 19.935 1.881 20.328 1.881 c
+21.034 1.881 21.391 1.411 21.402 0.47 c
+21.402 -2.175 l
+20.755 -2.175 l
+20.755 0.441 l
+20.755 0.754 20.7 0.974 20.594 1.103 c
+20.483 1.228 20.328 1.294 20.123 1.294 c
+19.965 1.294 19.818 1.239 19.682 1.132 c
+19.553 1.022 19.451 0.886 19.374 0.721 c
+19.374 -2.175 l
+18.726 -2.175 l
+18.726 1.808 l
+h
+22.24 0 m
+22.24 0.617 22.35 1.081 22.578 1.396 c
+22.802 1.72 23.137 1.881 23.577 1.881 c
+23.978 1.881 24.282 1.706 24.488 1.353 c
+24.533 1.808 l
+25.121 1.808 l
+25.121 -2.219 l
+25.121 -2.708 24.992 -3.087 24.739 -3.351 c
+24.481 -3.616 24.128 -3.748 23.68 -3.748 c
+23.482 -3.748 23.262 -3.697 23.019 -3.601 c
+22.772 -3.502 22.593 -3.381 22.475 -3.233 c
+22.74 -2.793 l
+23.004 -3.057 23.301 -3.19 23.636 -3.19 c
+24.172 -3.19 24.448 -2.896 24.459 -2.308 c
+24.459 -1.779 l
+24.253 -2.094 23.952 -2.249 23.563 -2.249 c
+23.151 -2.249 22.828 -2.098 22.593 -1.793 c
+22.364 -1.481 22.247 -1.029 22.24 -0.441 c
+h
+22.901 -0.382 m
+22.901 -0.823 22.963 -1.153 23.092 -1.367 c
+23.217 -1.573 23.434 -1.675 23.739 -1.675 c
+24.062 -1.675 24.301 -1.51 24.459 -1.176 c
+24.459 0.808 l
+24.29 1.132 24.051 1.294 23.739 1.294 c
+23.445 1.294 23.228 1.191 23.092 0.985 c
+22.963 0.779 22.901 0.455 22.901 0.015 c
+h
+27.502 -2.249 m
+27.002 -2.249 26.62 -2.102 26.356 -1.808 c
+26.09 -1.514 25.959 -1.08 25.959 -0.5 c
+25.959 -0.029 l
+25.959 0.566 26.084 1.033 26.341 1.367 c
+26.605 1.709 26.965 1.881 27.428 1.881 c
+27.888 1.881 28.23 1.727 28.457 1.426 c
+28.693 1.132 28.814 0.669 28.825 0.044 c
+28.825 -0.382 l
+26.605 -0.382 l
+26.605 -0.47 l
+26.605 -0.904 26.682 -1.216 26.84 -1.411 c
+27.006 -1.598 27.237 -1.691 27.532 -1.691 c
+27.726 -1.691 27.899 -1.658 28.045 -1.587 c
+28.193 -1.51 28.328 -1.392 28.457 -1.234 c
+28.795 -1.646 l
+28.509 -2.051 28.079 -2.249 27.502 -2.249 c
+27.428 1.323 m
+27.153 1.323 26.95 1.228 26.826 1.043 c
+26.697 0.856 26.624 0.566 26.605 0.177 c
+28.178 0.177 l
+28.178 0.264 l
+28.156 0.647 28.09 0.915 27.972 1.073 c
+27.854 1.239 27.671 1.323 27.428 1.323 c
+31.544 -1.161 m
+31.544 -1.014 31.489 -0.893 31.382 -0.794 c
+31.272 -0.698 31.066 -0.58 30.765 -0.441 c
+30.42 -0.294 30.177 -0.172 30.03 -0.073 c
+29.884 0.033 29.773 0.151 29.707 0.279 c
+29.637 0.405 29.604 0.563 29.604 0.75 c
+29.604 1.073 29.722 1.341 29.957 1.558 c
+30.192 1.771 30.493 1.881 30.868 1.881 c
+31.25 1.881 31.559 1.768 31.794 1.544 c
+32.029 1.316 32.147 1.029 32.147 0.676 c
+31.5 0.676 l
+31.5 0.852 31.441 1.004 31.324 1.132 c
+31.206 1.257 31.052 1.323 30.868 1.323 c
+30.67 1.323 30.519 1.268 30.412 1.161 c
+30.302 1.062 30.25 0.929 30.25 0.765 c
+30.25 0.636 30.287 0.53 30.368 0.441 c
+30.445 0.36 30.636 0.258 30.942 0.133 c
+31.419 -0.055 31.75 -0.243 31.926 -0.426 c
+32.103 -0.603 32.191 -0.831 32.191 -1.103 c
+32.191 -1.455 32.066 -1.735 31.823 -1.94 c
+31.588 -2.146 31.272 -2.249 30.883 -2.249 c
+30.46 -2.249 30.122 -2.132 29.869 -1.897 c
+29.612 -1.654 29.487 -1.348 29.487 -0.985 c
+30.133 -0.985 l
+30.14 -1.213 30.21 -1.389 30.339 -1.514 c
+30.464 -1.631 30.647 -1.691 30.883 -1.691 c
+31.096 -1.691 31.258 -1.643 31.368 -1.544 c
+31.486 -1.448 31.544 -1.319 31.544 -1.161 c
+33.073 -1.822 m
+33.073 -1.705 33.106 -1.61 33.176 -1.529 c
+33.242 -1.452 33.344 -1.411 33.485 -1.411 c
+33.631 -1.411 33.738 -1.452 33.807 -1.529 c
+33.885 -1.61 33.925 -1.705 33.925 -1.822 c
+33.925 -1.933 33.885 -2.024 33.807 -2.102 c
+33.738 -2.179 33.631 -2.219 33.485 -2.219 c
+33.344 -2.219 33.242 -2.179 33.176 -2.102 c
+33.106 -2.024 33.073 -1.933 33.073 -1.822 c
+f
+Q
+0.793 0.801 0.129 0.016 k
+35.668 310.736 238.665 -21.457 re
+f
+0 0 0 0 k
+q 1 0 0 1 84.2441 302.125 cm
+0 0 m
+0 -0.463 -0.099 -0.867 -0.294 -1.22 c
+-0.492 -1.565 -0.756 -1.845 -1.087 -2.057 c
+-0.706 -2.275 -0.404 -2.572 -0.176 -2.954 c
+0.048 -3.337 0.162 -3.788 0.162 -4.307 c
+0.162 -5.14 -0.081 -5.802 -0.558 -6.291 c
+-1.04 -6.772 -1.697 -7.011 -2.528 -7.011 c
+-3.351 -7.011 -4.008 -6.772 -4.498 -6.291 c
+-4.99 -5.802 -5.232 -5.14 -5.232 -4.307 c
+-5.232 -3.788 -5.126 -3.337 -4.909 -2.954 c
+-4.685 -2.572 -4.376 -2.275 -3.983 -2.057 c
+-4.328 -1.845 -4.596 -1.565 -4.791 -1.22 c
+-4.979 -0.867 -5.071 -0.463 -5.071 0 c
+-5.071 0.813 -4.847 1.448 -4.395 1.912 c
+-3.935 2.382 -3.318 2.617 -2.543 2.617 c
+-1.76 2.617 -1.142 2.382 -0.691 1.912 c
+-0.231 1.441 0 0.802 0 0 c
+-2.528 -5.497 m
+-2.256 -5.497 -2.043 -5.379 -1.896 -5.144 c
+-1.749 -4.909 -1.675 -4.586 -1.675 -4.174 c
+-1.675 -3.755 -1.756 -3.424 -1.911 -3.189 c
+-2.057 -2.954 -2.271 -2.836 -2.543 -2.836 c
+-2.807 -2.836 -3.021 -2.954 -3.175 -3.189 c
+-3.333 -3.424 -3.41 -3.755 -3.41 -4.174 c
+-3.41 -4.586 -3.333 -4.909 -3.175 -5.144 c
+-3.021 -5.379 -2.803 -5.497 -2.528 -5.497 c
+-1.822 -0.103 m
+-1.822 0.258 -1.881 0.548 -1.999 0.765 c
+-2.117 0.989 -2.3 1.103 -2.543 1.103 c
+-2.77 1.103 -2.946 0.992 -3.072 0.779 c
+-3.189 0.574 -3.248 0.279 -3.248 -0.103 c
+-3.248 -0.467 -3.189 -0.76 -3.072 -0.985 c
+-2.946 -1.213 -2.763 -1.323 -2.528 -1.323 c
+-2.285 -1.323 -2.109 -1.213 -1.999 -0.985 c
+-1.881 -0.76 -1.822 -0.467 -1.822 -0.103 c
+1.798 -5.953 m
+1.798 -5.659 1.893 -5.42 2.091 -5.232 c
+2.286 -5.049 2.54 -4.953 2.856 -4.953 c
+3.157 -4.953 3.406 -5.049 3.605 -5.232 c
+3.811 -5.42 3.914 -5.659 3.914 -5.953 c
+3.914 -6.258 3.811 -6.504 3.605 -6.688 c
+3.406 -6.865 3.157 -6.952 2.856 -6.952 c
+2.55 -6.952 2.297 -6.861 2.091 -6.673 c
+1.893 -6.489 1.798 -6.246 1.798 -5.953 c
+12.755 -4.424 m
+12.755 -4.042 12.657 -3.755 12.461 -3.557 c
+12.263 -3.362 11.911 -3.16 11.403 -2.954 c
+10.462 -2.594 9.786 -2.175 9.374 -1.705 c
+8.963 -1.227 8.757 -0.658 8.757 0 c
+8.757 0.783 9.037 1.415 9.596 1.897 c
+10.153 2.374 10.863 2.617 11.726 2.617 c
+12.303 2.617 12.818 2.492 13.27 2.249 c
+13.718 2.003 14.064 1.661 14.299 1.22 c
+14.541 0.779 14.666 0.279 14.666 -0.279 c
+12.785 -0.279 l
+12.785 0.162 12.69 0.493 12.505 0.721 c
+12.318 0.944 12.05 1.058 11.697 1.058 c
+11.362 1.058 11.102 0.96 10.918 0.765 c
+10.741 0.578 10.654 0.316 10.654 -0.014 c
+10.654 -0.272 10.756 -0.507 10.962 -0.72 c
+11.168 -0.926 11.528 -1.142 12.05 -1.367 c
+12.962 -1.691 13.623 -2.094 14.034 -2.572 c
+14.454 -3.054 14.666 -3.667 14.666 -4.409 c
+14.666 -5.225 14.406 -5.861 13.887 -6.32 c
+13.365 -6.784 12.66 -7.011 11.771 -7.011 c
+11.161 -7.011 10.61 -6.886 10.109 -6.643 c
+9.617 -6.39 9.231 -6.034 8.948 -5.571 c
+8.661 -5.101 8.522 -4.552 8.522 -3.925 c
+10.419 -3.925 l
+10.419 -4.465 10.521 -4.858 10.727 -5.101 c
+10.94 -5.346 11.289 -5.468 11.771 -5.468 c
+12.424 -5.468 12.755 -5.122 12.755 -4.424 c
+18.955 -1.72 m
+20.366 2.484 l
+22.423 2.484 l
+19.91 -3.484 l
+19.91 -6.879 l
+17.999 -6.879 l
+17.999 -3.484 l
+15.486 2.484 l
+17.544 2.484 l
+h
+30.042 -6.879 m
+28.145 -6.879 l
+25.382 -0.735 l
+25.382 -6.879 l
+23.486 -6.879 l
+23.486 2.484 l
+25.382 2.484 l
+28.145 -3.659 l
+28.145 2.484 l
+30.042 2.484 l
+h
+38.144 -3.763 m
+38.093 -4.832 37.791 -5.641 37.233 -6.188 c
+36.682 -6.739 35.91 -7.011 34.911 -7.011 c
+33.841 -7.011 33.022 -6.666 32.456 -5.967 c
+31.898 -5.273 31.618 -4.278 31.618 -2.984 c
+31.618 -1.411 l
+31.618 -0.118 31.904 0.875 32.486 1.573 c
+33.074 2.268 33.885 2.617 34.925 2.617 c
+35.943 2.617 36.719 2.326 37.248 1.75 c
+37.777 1.18 38.078 0.36 38.159 -0.706 c
+36.263 -0.706 l
+36.241 -0.04 36.138 0.416 35.954 0.661 c
+35.767 0.915 35.425 1.044 34.925 1.044 c
+34.425 1.044 34.065 0.867 33.852 0.515 c
+33.646 0.162 33.533 -0.422 33.514 -1.234 c
+33.514 -2.998 l
+33.514 -3.931 33.617 -4.571 33.823 -4.924 c
+34.036 -5.269 34.4 -5.438 34.911 -5.438 c
+35.399 -5.438 35.738 -5.321 35.925 -5.086 c
+36.12 -4.843 36.226 -4.402 36.249 -3.763 c
+h
+46.09 -6.879 m
+44.208 -6.879 l
+44.208 -2.866 l
+41.415 -2.866 l
+41.415 -6.879 l
+39.519 -6.879 l
+39.519 2.484 l
+41.415 2.484 l
+41.415 -1.308 l
+44.208 -1.308 l
+44.208 2.484 l
+46.09 2.484 l
+h
+50.664 -3.454 m
+49.724 -3.454 l
+49.724 -6.879 l
+47.842 -6.879 l
+47.842 2.484 l
+50.855 2.484 l
+51.804 2.484 52.535 2.238 53.045 1.75 c
+53.564 1.257 53.824 0.563 53.824 -0.338 c
+53.824 -1.583 53.373 -2.454 52.473 -2.954 c
+54.104 -6.79 l
+54.104 -6.879 l
+52.076 -6.879 l
+h
+49.724 -1.881 m
+50.796 -1.881 l
+51.179 -1.881 51.462 -1.76 51.649 -1.514 c
+51.833 -1.26 51.929 -0.922 51.929 -0.5 c
+51.929 0.441 51.565 0.912 50.84 0.912 c
+49.724 0.912 l
+h
+61.942 -3.042 m
+61.942 -4.299 61.641 -5.273 61.046 -5.967 c
+60.446 -6.666 59.623 -7.011 58.576 -7.011 c
+57.525 -7.011 56.698 -6.669 56.092 -5.982 c
+55.493 -5.288 55.188 -4.321 55.181 -3.087 c
+55.181 -1.484 l
+55.181 -0.201 55.478 0.802 56.077 1.529 c
+56.673 2.253 57.503 2.617 58.561 2.617 c
+59.598 2.617 60.417 2.257 61.016 1.544 c
+61.622 0.838 61.931 -0.158 61.942 -1.44 c
+h
+60.046 -1.469 m
+60.046 -0.628 59.921 0 59.679 0.412 c
+59.443 0.823 59.068 1.029 58.561 1.029 c
+58.061 1.029 57.687 0.827 57.444 0.426 c
+57.209 0.034 57.084 -0.565 57.077 -1.367 c
+57.077 -3.042 l
+57.077 -3.858 57.198 -4.461 57.444 -4.85 c
+57.687 -5.244 58.065 -5.438 58.576 -5.438 c
+59.065 -5.438 59.428 -5.247 59.664 -4.866 c
+59.906 -4.483 60.035 -3.895 60.046 -3.102 c
+h
+70.075 -6.879 m
+68.178 -6.879 l
+65.415 -0.735 l
+65.415 -6.879 l
+63.519 -6.879 l
+63.519 2.484 l
+65.415 2.484 l
+68.178 -3.659 l
+68.178 2.484 l
+70.075 2.484 l
+h
+73.811 -6.879 -1.896 9.363 re
+77.472 -5.306 m
+81.323 -5.306 l
+81.323 -6.879 l
+75.253 -6.879 l
+75.253 -5.747 l
+79.074 0.912 l
+75.222 0.912 l
+75.222 2.484 l
+81.25 2.484 l
+81.25 1.367 l
+h
+84.685 -6.879 -1.897 9.363 re
+92.935 -6.879 m
+91.039 -6.879 l
+88.275 -0.735 l
+88.275 -6.879 l
+86.38 -6.879 l
+86.38 2.484 l
+88.275 2.484 l
+91.039 -3.659 l
+91.039 2.484 l
+92.935 2.484 l
+h
+101.049 -5.82 m
+100.685 -6.214 100.24 -6.512 99.712 -6.717 c
+99.182 -6.912 98.602 -7.011 97.977 -7.011 c
+96.896 -7.011 96.059 -6.68 95.463 -6.011 c
+94.864 -5.346 94.559 -4.376 94.552 -3.102 c
+94.552 -1.411 l
+94.552 -0.118 94.831 0.875 95.39 1.573 c
+95.955 2.268 96.779 2.617 97.859 2.617 c
+98.877 2.617 99.641 2.359 100.152 1.852 c
+100.67 1.353 100.968 0.566 101.049 -0.5 c
+99.211 -0.5 l
+99.161 0.096 99.039 0.504 98.844 0.721 c
+98.646 0.934 98.337 1.044 97.918 1.044 c
+97.407 1.044 97.036 0.857 96.801 0.485 c
+96.573 0.111 96.456 -0.481 96.448 -1.294 c
+96.448 -2.998 l
+96.448 -3.85 96.573 -4.475 96.83 -4.866 c
+97.084 -5.247 97.499 -5.438 98.08 -5.438 c
+98.451 -5.438 98.756 -5.365 98.991 -5.218 c
+99.153 -5.101 l
+99.153 -3.38 l
+97.83 -3.38 l
+97.83 -1.955 l
+101.049 -1.955 l
+h
+108.582 -3.454 m
+107.641 -3.454 l
+107.641 -6.879 l
+105.76 -6.879 l
+105.76 2.484 l
+108.773 2.484 l
+109.721 2.484 110.453 2.238 110.964 1.75 c
+111.481 1.257 111.743 0.563 111.743 -0.338 c
+111.743 -1.583 111.29 -2.454 110.39 -2.954 c
+112.021 -6.79 l
+112.021 -6.879 l
+109.993 -6.879 l
+h
+107.641 -1.881 m
+108.715 -1.881 l
+109.097 -1.881 109.38 -1.76 109.567 -1.514 c
+109.75 -1.26 109.846 -0.922 109.846 -0.5 c
+109.846 0.441 109.482 0.912 108.759 0.912 c
+107.641 0.912 l
+h
+118.097 -2.822 m
+115.157 -2.822 l
+115.157 -5.306 l
+118.64 -5.306 l
+118.64 -6.879 l
+113.26 -6.879 l
+113.26 2.484 l
+118.625 2.484 l
+118.625 0.912 l
+115.157 0.912 l
+115.157 -1.308 l
+118.097 -1.308 l
+h
+121.797 -3.586 m
+121.797 -6.879 l
+119.901 -6.879 l
+119.901 2.484 l
+123.09 2.484 l
+124.02 2.484 124.759 2.194 125.31 1.617 c
+125.858 1.048 126.132 0.302 126.132 -0.617 c
+126.132 -1.529 125.858 -2.256 125.31 -2.792 c
+124.769 -3.322 124.02 -3.586 123.061 -3.586 c
+h
+121.797 -2.013 m
+123.09 -2.013 l
+123.45 -2.013 123.73 -1.896 123.928 -1.66 c
+124.123 -1.425 124.222 -1.084 124.222 -0.632 c
+124.222 -0.162 124.119 0.21 123.913 0.485 c
+123.715 0.757 123.45 0.9 123.119 0.912 c
+121.797 0.912 l
+h
+134.199 -3.042 m
+134.199 -4.299 133.897 -5.273 133.303 -5.967 c
+132.704 -6.666 131.88 -7.011 130.833 -7.011 c
+129.782 -7.011 128.955 -6.669 128.349 -5.982 c
+127.75 -5.288 127.445 -4.321 127.437 -3.087 c
+127.437 -1.484 l
+127.437 -0.201 127.735 0.802 128.334 1.529 c
+128.929 2.253 129.76 2.617 130.818 2.617 c
+131.855 2.617 132.674 2.257 133.273 1.544 c
+133.879 0.838 134.188 -0.158 134.199 -1.44 c
+h
+132.303 -1.469 m
+132.303 -0.628 132.178 0 131.935 0.412 c
+131.7 0.823 131.325 1.029 130.818 1.029 c
+130.319 1.029 129.943 0.827 129.701 0.426 c
+129.465 0.034 129.341 -0.565 129.334 -1.367 c
+129.334 -3.042 l
+129.334 -3.858 129.455 -4.461 129.701 -4.85 c
+129.943 -5.244 130.322 -5.438 130.833 -5.438 c
+131.322 -5.438 131.686 -5.247 131.921 -4.866 c
+132.164 -4.483 132.291 -3.895 132.303 -3.102 c
+h
+139.73 -4.424 m
+139.73 -4.042 139.63 -3.755 139.435 -3.557 c
+139.237 -3.362 138.884 -3.16 138.377 -2.954 c
+137.436 -2.594 136.76 -2.175 136.349 -1.705 c
+135.937 -1.227 135.732 -0.658 135.732 0 c
+135.732 0.783 136.01 1.415 136.569 1.897 c
+137.128 2.374 137.837 2.617 138.701 2.617 c
+139.277 2.617 139.792 2.492 140.244 2.249 c
+140.692 2.003 141.038 1.661 141.273 1.22 c
+141.515 0.779 141.641 0.279 141.641 -0.279 c
+139.759 -0.279 l
+139.759 0.162 139.663 0.493 139.48 0.721 c
+139.292 0.944 139.024 1.058 138.672 1.058 c
+138.337 1.058 138.076 0.96 137.892 0.765 c
+137.716 0.578 137.627 0.316 137.627 -0.014 c
+137.627 -0.272 137.731 -0.507 137.936 -0.72 c
+138.142 -0.926 138.502 -1.142 139.024 -1.367 c
+139.935 -1.691 140.597 -2.094 141.008 -2.572 c
+141.427 -3.054 141.641 -3.667 141.641 -4.409 c
+141.641 -5.225 141.38 -5.861 140.862 -6.32 c
+140.339 -6.784 139.634 -7.011 138.745 -7.011 c
+138.134 -7.011 137.583 -6.886 137.084 -6.643 c
+136.592 -6.39 136.206 -6.034 135.923 -5.571 c
+135.636 -5.101 135.497 -4.552 135.497 -3.925 c
+137.392 -3.925 l
+137.392 -4.465 137.496 -4.858 137.701 -5.101 c
+137.914 -5.346 138.263 -5.468 138.745 -5.468 c
+139.399 -5.468 139.73 -5.122 139.73 -4.424 c
+145.087 -6.879 -1.897 9.363 re
+152.669 0.912 m
+150.346 0.912 l
+150.346 -6.879 l
+148.45 -6.879 l
+148.45 0.912 l
+146.171 0.912 l
+146.171 2.484 l
+152.669 2.484 l
+h
+160.367 -3.042 m
+160.367 -4.299 160.066 -5.273 159.47 -5.967 c
+158.871 -6.666 158.048 -7.011 157.001 -7.011 c
+155.95 -7.011 155.123 -6.669 154.516 -5.982 c
+153.918 -5.288 153.612 -4.321 153.606 -3.087 c
+153.606 -1.484 l
+153.606 -0.201 153.903 0.802 154.502 1.529 c
+155.098 2.253 155.928 2.617 156.986 2.617 c
+158.023 2.617 158.842 2.257 159.441 1.544 c
+160.047 0.838 160.356 -0.158 160.367 -1.44 c
+h
+158.471 -1.469 m
+158.471 -0.628 158.346 0 158.103 0.412 c
+157.868 0.823 157.493 1.029 156.986 1.029 c
+156.486 1.029 156.112 0.827 155.869 0.426 c
+155.634 0.034 155.509 -0.565 155.501 -1.367 c
+155.501 -3.042 l
+155.501 -3.858 155.623 -4.461 155.869 -4.85 c
+156.112 -5.244 156.49 -5.438 157.001 -5.438 c
+157.49 -5.438 157.853 -5.247 158.088 -4.866 c
+158.331 -4.483 158.46 -3.895 158.471 -3.102 c
+h
+164.781 -3.454 m
+163.84 -3.454 l
+163.84 -6.879 l
+161.959 -6.879 l
+161.959 2.484 l
+164.972 2.484 l
+165.919 2.484 166.651 2.238 167.162 1.75 c
+167.68 1.257 167.941 0.563 167.941 -0.338 c
+167.941 -1.583 167.488 -2.454 166.588 -2.954 c
+168.22 -6.79 l
+168.22 -6.879 l
+166.192 -6.879 l
+h
+163.84 -1.881 m
+164.913 -1.881 l
+165.294 -1.881 165.578 -1.76 165.765 -1.514 c
+165.949 -1.26 166.044 -0.922 166.044 -0.5 c
+166.044 0.441 165.681 0.912 164.957 0.912 c
+163.84 0.912 l
+h
+171.443 -6.879 -1.897 9.363 re
+177.969 -2.822 m
+175.029 -2.822 l
+175.029 -5.306 l
+178.513 -5.306 l
+178.513 -6.879 l
+173.133 -6.879 l
+173.133 2.484 l
+178.499 2.484 l
+178.499 0.912 l
+175.029 0.912 l
+175.029 -1.308 l
+177.969 -1.308 l
+h
+183.731 -4.424 m
+183.731 -4.042 183.632 -3.755 183.438 -3.557 c
+183.239 -3.362 182.886 -3.16 182.379 -2.954 c
+181.439 -2.594 180.762 -2.175 180.35 -1.705 c
+179.939 -1.227 179.733 -0.658 179.733 0 c
+179.733 0.783 180.012 1.415 180.571 1.897 c
+181.129 2.374 181.838 2.617 182.702 2.617 c
+183.28 2.617 183.793 2.492 184.246 2.249 c
+184.693 2.003 185.04 1.661 185.275 1.22 c
+185.518 0.779 185.642 0.279 185.642 -0.279 c
+183.76 -0.279 l
+183.76 0.162 183.665 0.493 183.481 0.721 c
+183.294 0.944 183.026 1.058 182.673 1.058 c
+182.339 1.058 182.077 0.96 181.894 0.765 c
+181.717 0.578 181.629 0.316 181.629 -0.014 c
+181.629 -0.272 181.732 -0.507 181.938 -0.72 c
+182.144 -0.926 182.503 -1.142 183.026 -1.367 c
+183.937 -1.691 184.598 -2.094 185.01 -2.572 c
+185.429 -3.054 185.642 -3.667 185.642 -4.409 c
+185.642 -5.225 185.381 -5.861 184.863 -6.32 c
+184.342 -6.784 183.636 -7.011 182.746 -7.011 c
+182.137 -7.011 181.585 -6.886 181.086 -6.643 c
+180.593 -6.39 180.207 -6.034 179.924 -5.571 c
+179.638 -5.101 179.498 -4.552 179.498 -3.925 c
+181.394 -3.925 l
+181.394 -4.465 181.497 -4.858 181.703 -5.101 c
+181.915 -5.346 182.264 -5.468 182.746 -5.468 c
+183.401 -5.468 183.731 -5.122 183.731 -4.424 c
+f
+Q
+0.113 0.082 0.09 0 k
+35.668 280.433 238.665 -12.895 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 40.8563 273.5943 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.69 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.772 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.279 -3.219 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.985 c
+-3.322 2.18 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.003 -2.469 3.043 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.459 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.36 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.455 c
+-2.26 2.425 -2.319 2.385 -2.366 2.338 c
+-2.406 2.297 -2.437 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.066 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.44 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.302 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.014 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.147 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.411 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.772 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.632 5.137 1.779 c
+5.245 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.152 2.22 c
+8.004 2.22 l
+7.993 2.139 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.871 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.403 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.279 5.835 1.162 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.559 c
+6.725 -0.521 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.302 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.22 l
+13.644 2.22 l
+13.924 3.117 l
+14.497 3.117 l
+14.497 2.22 l
+15.732 2.22 l
+15.732 1.602 l
+14.497 1.602 l
+14.497 -0.103 l
+14.497 -0.324 l
+14.504 -0.393 14.527 -0.455 14.556 -0.515 c
+14.593 -0.565 14.648 -0.61 14.718 -0.646 c
+14.795 -0.676 14.909 -0.69 15.056 -0.69 c
+15.192 -0.69 15.327 -0.687 15.468 -0.676 c
+15.603 -0.658 15.736 -0.632 15.865 -0.602 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.23 15.629 -1.249 c
+15.549 -1.261 15.471 -1.267 15.394 -1.278 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.041 -1.301 14.942 -1.308 14.835 -1.308 c
+14.648 -1.308 14.486 -1.294 14.35 -1.264 c
+14.221 -1.227 14.107 -1.183 14.012 -1.132 c
+13.924 -1.084 13.85 -1.025 13.791 -0.955 c
+13.733 -0.878 13.689 -0.801 13.66 -0.72 c
+13.63 -0.632 13.608 -0.544 13.6 -0.455 c
+13.59 -0.36 13.586 -0.264 13.586 -0.176 c
+h
+22.765 1.602 m
+22.765 -1.264 l
+21.868 -1.264 l
+21.868 1.602 l
+21.045 1.602 l
+21.045 2.22 l
+21.868 2.22 l
+21.868 2.484 l
+21.868 2.61 21.883 2.741 21.913 2.882 c
+21.949 3.017 22.02 3.135 22.119 3.234 c
+22.225 3.341 22.369 3.429 22.545 3.499 c
+22.722 3.564 22.946 3.601 23.221 3.601 c
+23.434 3.601 23.632 3.591 23.809 3.572 c
+23.985 3.55 24.137 3.532 24.264 3.514 c
+24.264 2.926 l
+24.137 2.944 23.993 2.959 23.838 2.969 c
+23.68 2.976 23.53 2.984 23.383 2.984 c
+23.254 2.984 23.152 2.969 23.074 2.94 c
+22.994 2.911 22.931 2.87 22.883 2.822 c
+22.832 2.771 22.799 2.708 22.78 2.631 c
+22.769 2.562 22.765 2.484 22.765 2.396 c
+22.765 2.22 l
+24.191 2.22 l
+24.191 1.602 l
+h
+26.738 -1.323 m
+26.481 -1.323 26.253 -1.286 26.047 -1.22 c
+25.841 -1.143 25.665 -1.029 25.518 -0.881 c
+25.371 -0.727 25.253 -0.536 25.165 -0.309 c
+25.084 -0.085 25.047 0.181 25.047 0.485 c
+25.047 0.816 25.091 1.095 25.18 1.323 c
+25.275 1.558 25.404 1.742 25.562 1.881 c
+25.727 2.018 25.915 2.117 26.121 2.176 c
+26.327 2.242 26.535 2.278 26.753 2.278 c
+27.025 2.278 27.26 2.227 27.458 2.132 c
+27.664 2.043 27.829 1.911 27.958 1.735 c
+28.094 1.565 28.193 1.36 28.252 1.118 c
+28.318 0.882 28.355 0.617 28.355 0.324 c
+28.355 0.309 l
+25.988 0.309 l
+25.988 0.162 26.003 0.023 26.032 -0.103 c
+26.069 -0.231 26.124 -0.345 26.194 -0.441 c
+26.26 -0.529 26.344 -0.598 26.444 -0.646 c
+26.539 -0.698 26.653 -0.72 26.782 -0.72 c
+26.936 -0.72 27.076 -0.687 27.194 -0.617 c
+27.318 -0.551 27.407 -0.448 27.458 -0.309 c
+28.296 -0.382 l
+28.266 -0.481 28.212 -0.588 28.135 -0.706 c
+28.054 -0.816 27.95 -0.918 27.825 -1.014 c
+27.708 -1.103 27.553 -1.176 27.37 -1.234 c
+27.194 -1.294 26.98 -1.323 26.738 -1.323 c
+26.738 1.706 m
+26.649 1.706 26.562 1.69 26.473 1.661 c
+26.385 1.632 26.304 1.58 26.238 1.515 c
+26.169 1.444 26.109 1.357 26.061 1.249 c
+26.021 1.139 26.003 1.014 26.003 0.867 c
+27.472 0.867 l
+27.472 1.004 27.447 1.125 27.399 1.235 c
+27.359 1.341 27.304 1.43 27.237 1.5 c
+27.179 1.565 27.106 1.617 27.017 1.646 c
+26.929 1.683 26.834 1.706 26.738 1.706 c
+29.843 1.602 m
+29.299 1.602 l
+29.299 2.22 l
+29.887 2.22 l
+30.167 3.117 l
+30.74 3.117 l
+30.74 2.22 l
+31.975 2.22 l
+31.975 1.602 l
+30.74 1.602 l
+30.74 -0.103 l
+30.74 -0.324 l
+30.747 -0.393 30.769 -0.455 30.799 -0.515 c
+30.836 -0.565 30.89 -0.61 30.96 -0.646 c
+31.037 -0.676 31.152 -0.69 31.298 -0.69 c
+31.434 -0.69 31.57 -0.687 31.71 -0.676 c
+31.846 -0.658 31.978 -0.632 32.106 -0.602 c
+32.106 -1.205 l
+32.026 -1.216 31.948 -1.23 31.871 -1.249 c
+31.79 -1.261 31.713 -1.267 31.636 -1.278 c
+31.555 -1.286 31.467 -1.294 31.372 -1.294 c
+31.283 -1.301 31.185 -1.308 31.077 -1.308 c
+30.89 -1.308 30.728 -1.294 30.593 -1.264 c
+30.464 -1.227 30.35 -1.183 30.254 -1.132 c
+30.167 -1.084 30.093 -1.025 30.034 -0.955 c
+29.976 -0.878 29.932 -0.801 29.901 -0.72 c
+29.872 -0.632 29.851 -0.544 29.843 -0.455 c
+29.832 -0.36 29.828 -0.264 29.828 -0.176 c
+h
+34.863 -1.323 m
+34.576 -1.323 34.333 -1.282 34.128 -1.205 c
+33.922 -1.117 33.749 -0.995 33.614 -0.837 c
+33.473 -0.683 33.371 -0.496 33.305 -0.279 c
+33.234 -0.055 33.202 0.191 33.202 0.456 c
+33.202 0.75 33.234 1.008 33.305 1.235 c
+33.382 1.459 33.488 1.646 33.628 1.793 c
+33.775 1.948 33.951 2.066 34.157 2.146 c
+34.363 2.234 34.599 2.278 34.863 2.278 c
+35.087 2.278 35.289 2.249 35.465 2.19 c
+35.642 2.132 35.792 2.047 35.921 1.941 c
+36.046 1.841 36.149 1.72 36.23 1.573 c
+36.307 1.434 36.362 1.283 36.392 1.118 c
+35.48 1.073 l
+35.451 1.249 35.381 1.389 35.274 1.5 c
+35.175 1.606 35.032 1.661 34.848 1.661 c
+34.602 1.661 34.425 1.558 34.319 1.353 c
+34.209 1.154 34.157 0.867 34.157 0.485 c
+34.157 -0.309 34.392 -0.706 34.863 -0.706 c
+35.028 -0.706 35.171 -0.654 35.289 -0.544 c
+35.407 -0.437 35.48 -0.276 35.509 -0.058 c
+36.421 -0.103 l
+36.392 -0.272 36.336 -0.426 36.259 -0.573 c
+36.189 -0.72 36.087 -0.852 35.95 -0.97 c
+35.821 -1.08 35.663 -1.168 35.48 -1.234 c
+35.304 -1.294 35.098 -1.323 34.863 -1.323 c
+38.262 1.515 m
+38.379 1.786 38.53 1.985 38.718 2.103 c
+38.901 2.22 39.122 2.278 39.379 2.278 c
+39.584 2.278 39.754 2.242 39.894 2.176 c
+40.041 2.106 40.151 2.014 40.232 1.897 c
+40.32 1.779 40.378 1.636 40.408 1.47 c
+40.444 1.301 40.467 1.125 40.467 0.941 c
+40.467 -1.264 l
+39.555 -1.264 l
+39.555 0.735 l
+39.555 0.871 39.544 0.992 39.526 1.103 c
+39.515 1.209 39.489 1.297 39.453 1.367 c
+39.412 1.444 39.353 1.503 39.276 1.544 c
+39.206 1.58 39.114 1.602 38.996 1.602 c
+38.886 1.602 38.791 1.577 38.703 1.529 c
+38.615 1.478 38.534 1.411 38.468 1.323 c
+38.409 1.235 38.358 1.125 38.321 1 c
+38.291 0.882 38.277 0.75 38.277 0.603 c
+38.277 -1.264 l
+37.365 -1.264 l
+37.365 3.514 l
+38.277 3.514 l
+38.277 2.205 l
+38.277 2.135 38.269 2.066 38.262 1.999 c
+38.262 1.793 l
+38.262 1.735 38.254 1.679 38.248 1.632 c
+38.248 1.515 l
+h
+46.236 -2.631 m
+46.236 3.514 l
+48.162 3.514 l
+48.162 2.896 l
+47.089 2.896 l
+47.089 -2.013 l
+48.162 -2.013 l
+48.162 -2.631 l
+h
+52.56 1.47 m
+52.461 1.478 52.359 1.488 52.251 1.5 c
+52.141 1.518 52.02 1.529 51.885 1.529 c
+51.708 1.529 51.55 1.488 51.414 1.411 c
+51.274 1.341 51.156 1.243 51.061 1.118 c
+50.973 0.989 50.903 0.842 50.855 0.676 c
+50.815 0.507 50.796 0.331 50.796 0.147 c
+50.796 -1.264 l
+49.9 -1.264 l
+49.9 0.985 l
+49.9 1.11 49.889 1.235 49.87 1.353 c
+49.859 1.478 49.845 1.595 49.826 1.706 c
+49.815 1.823 49.801 1.918 49.782 1.999 c
+49.76 2.087 49.742 2.161 49.724 2.22 c
+50.605 2.22 l
+50.613 2.168 50.624 2.117 50.635 2.058 c
+50.653 1.999 50.668 1.933 50.679 1.867 c
+50.697 1.808 50.712 1.742 50.723 1.675 c
+50.73 1.606 50.742 1.544 50.752 1.484 c
+50.767 1.484 l
+50.804 1.602 50.855 1.709 50.914 1.808 c
+50.981 1.904 51.061 1.989 51.149 2.058 c
+51.237 2.124 51.341 2.18 51.458 2.22 c
+51.583 2.257 51.73 2.278 51.899 2.278 c
+52.024 2.278 52.141 2.271 52.251 2.263 c
+52.369 2.253 52.473 2.238 52.56 2.22 c
+h
+55.17 -1.323 m
+54.912 -1.323 54.684 -1.286 54.478 -1.22 c
+54.273 -1.143 54.096 -1.029 53.95 -0.881 c
+53.803 -0.727 53.685 -0.536 53.597 -0.309 c
+53.516 -0.085 53.479 0.181 53.479 0.485 c
+53.479 0.816 53.523 1.095 53.612 1.323 c
+53.707 1.558 53.836 1.742 53.994 1.881 c
+54.159 2.018 54.347 2.117 54.553 2.176 c
+54.758 2.242 54.967 2.278 55.184 2.278 c
+55.456 2.278 55.691 2.227 55.889 2.132 c
+56.095 2.043 56.261 1.911 56.39 1.735 c
+56.525 1.565 56.625 1.36 56.683 1.118 c
+56.75 0.882 56.787 0.617 56.787 0.324 c
+56.787 0.309 l
+54.42 0.309 l
+54.42 0.162 54.435 0.023 54.464 -0.103 c
+54.501 -0.231 54.555 -0.345 54.626 -0.441 c
+54.692 -0.529 54.776 -0.598 54.875 -0.646 c
+54.971 -0.698 55.085 -0.72 55.214 -0.72 c
+55.368 -0.72 55.507 -0.687 55.625 -0.617 c
+55.75 -0.551 55.839 -0.448 55.889 -0.309 c
+56.728 -0.382 l
+56.698 -0.481 56.643 -0.588 56.566 -0.706 c
+56.485 -0.816 56.382 -0.918 56.257 -1.014 c
+56.14 -1.103 55.985 -1.176 55.802 -1.234 c
+55.625 -1.294 55.412 -1.323 55.17 -1.323 c
+55.17 1.706 m
+55.081 1.706 54.993 1.69 54.905 1.661 c
+54.817 1.632 54.736 1.58 54.67 1.515 c
+54.6 1.444 54.541 1.357 54.493 1.249 c
+54.453 1.139 54.435 1.014 54.435 0.867 c
+55.904 0.867 l
+55.904 1.004 55.879 1.125 55.831 1.235 c
+55.791 1.341 55.735 1.43 55.669 1.5 c
+55.611 1.565 55.537 1.617 55.449 1.646 c
+55.361 1.683 55.265 1.706 55.17 1.706 c
+58.833 -1.264 m
+58.833 0.852 l
+58.833 1.018 58.826 1.154 58.819 1.264 c
+58.807 1.371 58.789 1.455 58.76 1.515 c
+58.738 1.58 58.709 1.632 58.671 1.661 c
+58.642 1.69 58.601 1.706 58.553 1.706 c
+58.495 1.706 58.44 1.675 58.393 1.617 c
+58.352 1.565 58.318 1.492 58.289 1.397 c
+58.26 1.309 58.235 1.195 58.216 1.058 c
+58.204 0.919 58.201 0.769 58.201 0.603 c
+58.201 -1.264 l
+57.452 -1.264 l
+57.452 1.47 l
+57.452 1.706 l
+57.452 1.926 l
+57.452 2.003 57.444 2.066 57.437 2.117 c
+57.437 2.22 l
+58.113 2.22 l
+58.113 2.132 l
+58.113 1.985 l
+58.121 1.926 58.127 1.867 58.127 1.808 c
+58.127 1.646 l
+58.142 1.646 l
+58.161 1.735 58.19 1.812 58.231 1.881 c
+58.268 1.959 58.312 2.028 58.363 2.087 c
+58.422 2.146 58.488 2.19 58.569 2.22 c
+58.646 2.257 58.734 2.278 58.833 2.278 c
+59.017 2.278 59.157 2.224 59.245 2.117 c
+59.34 2.018 59.411 1.86 59.451 1.646 c
+59.465 1.646 l
+59.502 1.742 59.542 1.831 59.583 1.911 c
+59.631 1.989 59.686 2.051 59.744 2.103 c
+59.804 2.161 59.87 2.205 59.951 2.234 c
+60.028 2.263 60.116 2.278 60.215 2.278 c
+60.351 2.278 60.465 2.253 60.553 2.205 c
+60.641 2.153 60.708 2.08 60.759 1.985 c
+60.818 1.885 60.855 1.756 60.876 1.602 c
+60.905 1.455 60.92 1.272 60.92 1.058 c
+60.92 -1.264 l
+60.2 -1.264 l
+60.2 0.852 l
+60.2 1.018 60.193 1.154 60.186 1.264 c
+60.174 1.371 60.157 1.455 60.126 1.515 c
+60.105 1.58 60.076 1.632 60.039 1.661 c
+60.009 1.69 59.968 1.706 59.921 1.706 c
+59.804 1.706 59.708 1.617 59.642 1.44 c
+59.583 1.272 59.553 1.014 59.553 0.661 c
+59.553 -1.264 l
+h
+64.937 0.485 m
+64.937 0.21 64.901 -0.04 64.834 -0.264 c
+64.764 -0.481 64.662 -0.669 64.525 -0.823 c
+64.386 -0.981 64.209 -1.103 63.997 -1.19 c
+63.779 -1.278 63.526 -1.323 63.232 -1.323 c
+62.956 -1.323 62.71 -1.278 62.497 -1.19 c
+62.291 -1.103 62.119 -0.981 61.982 -0.823 c
+61.843 -0.669 61.74 -0.481 61.674 -0.264 c
+61.604 -0.04 61.57 0.21 61.57 0.485 c
+61.57 0.738 61.601 0.974 61.659 1.191 c
+61.726 1.415 61.828 1.606 61.967 1.764 c
+62.104 1.929 62.28 2.058 62.497 2.146 c
+62.71 2.234 62.967 2.278 63.261 2.278 c
+63.573 2.278 63.835 2.234 64.041 2.146 c
+64.253 2.058 64.427 1.929 64.554 1.764 c
+64.691 1.606 64.79 1.415 64.849 1.191 c
+64.907 0.974 64.937 0.738 64.937 0.485 c
+63.982 0.485 m
+63.982 0.691 63.967 0.867 63.937 1.014 c
+63.916 1.162 63.879 1.283 63.82 1.382 c
+63.761 1.478 63.687 1.548 63.6 1.588 c
+63.511 1.636 63.401 1.661 63.276 1.661 c
+63.012 1.661 62.821 1.562 62.703 1.367 c
+62.586 1.18 62.526 0.886 62.526 0.485 c
+62.526 0.063 62.586 -0.243 62.703 -0.426 c
+62.821 -0.613 62.997 -0.706 63.232 -0.706 c
+63.357 -0.706 63.471 -0.687 63.57 -0.646 c
+63.665 -0.598 63.746 -0.525 63.806 -0.426 c
+63.872 -0.33 63.916 -0.206 63.937 -0.058 c
+63.967 0.088 63.982 0.268 63.982 0.485 c
+66.396 1.602 m
+65.852 1.602 l
+65.852 2.22 l
+66.44 2.22 l
+66.719 3.117 l
+67.293 3.117 l
+67.293 2.22 l
+68.527 2.22 l
+68.527 1.602 l
+67.293 1.602 l
+67.293 -0.103 l
+67.293 -0.324 l
+67.3 -0.393 67.322 -0.455 67.351 -0.515 c
+67.388 -0.565 67.443 -0.61 67.513 -0.646 c
+67.59 -0.676 67.704 -0.69 67.851 -0.69 c
+67.987 -0.69 68.123 -0.687 68.263 -0.676 c
+68.398 -0.658 68.531 -0.632 68.66 -0.602 c
+68.66 -1.205 l
+68.579 -1.216 68.502 -1.23 68.425 -1.249 c
+68.344 -1.261 68.267 -1.267 68.189 -1.278 c
+68.109 -1.286 68.02 -1.294 67.924 -1.294 c
+67.837 -1.301 67.737 -1.308 67.631 -1.308 c
+67.443 -1.308 67.282 -1.294 67.145 -1.264 c
+67.017 -1.227 66.903 -1.183 66.808 -1.132 c
+66.719 -1.084 66.646 -1.025 66.587 -0.955 c
+66.528 -0.878 66.484 -0.801 66.455 -0.72 c
+66.426 -0.632 66.403 -0.544 66.396 -0.455 c
+66.385 -0.36 66.381 -0.264 66.381 -0.176 c
+h
+71.412 -1.323 m
+71.155 -1.323 70.927 -1.286 70.721 -1.22 c
+70.515 -1.143 70.339 -1.029 70.192 -0.881 c
+70.045 -0.727 69.927 -0.536 69.84 -0.309 c
+69.759 -0.085 69.722 0.181 69.722 0.485 c
+69.722 0.816 69.765 1.095 69.854 1.323 c
+69.95 1.558 70.078 1.742 70.236 1.881 c
+70.401 2.018 70.588 2.117 70.794 2.176 c
+71 2.242 71.21 2.278 71.427 2.278 c
+71.698 2.278 71.934 2.227 72.132 2.132 c
+72.338 2.043 72.504 1.911 72.632 1.735 c
+72.768 1.565 72.867 1.36 72.926 1.118 c
+72.992 0.882 73.029 0.617 73.029 0.324 c
+73.029 0.309 l
+70.663 0.309 l
+70.663 0.162 70.677 0.023 70.706 -0.103 c
+70.743 -0.231 70.798 -0.345 70.868 -0.441 c
+70.935 -0.529 71.018 -0.598 71.118 -0.646 c
+71.213 -0.698 71.328 -0.72 71.456 -0.72 c
+71.61 -0.72 71.75 -0.687 71.868 -0.617 c
+71.993 -0.551 72.08 -0.448 72.132 -0.309 c
+72.97 -0.382 l
+72.94 -0.481 72.886 -0.588 72.809 -0.706 c
+72.728 -0.816 72.624 -0.918 72.5 -1.014 c
+72.382 -1.103 72.228 -1.176 72.044 -1.234 c
+71.868 -1.294 71.654 -1.323 71.412 -1.323 c
+71.412 1.706 m
+71.324 1.706 71.236 1.69 71.147 1.661 c
+71.059 1.632 70.978 1.58 70.912 1.515 c
+70.842 1.444 70.783 1.357 70.736 1.249 c
+70.696 1.139 70.677 1.014 70.677 0.867 c
+72.147 0.867 l
+72.147 1.004 72.121 1.125 72.074 1.235 c
+72.033 1.341 71.978 1.43 71.912 1.5 c
+71.853 1.565 71.779 1.617 71.691 1.646 c
+71.603 1.683 71.507 1.706 71.412 1.706 c
+74.285 -2.631 m
+74.285 -2.013 l
+75.359 -2.013 l
+75.359 2.896 l
+74.285 2.896 l
+74.285 3.514 l
+76.211 3.514 l
+76.211 -2.631 l
+h
+f
+Q
+q 1 0 0 1 76.2337 259.8106 cm
+0 0 m
+-1.808 0 l
+-1.808 -2.367 l
+-2.484 -2.367 l
+-2.484 2.984 l
+0.309 2.984 l
+0.309 2.41 l
+-1.808 2.41 l
+-1.808 0.573 l
+0 0.573 l
+h
+2.396 -2.44 m
+1.896 -2.44 1.514 -2.294 1.249 -1.999 c
+0.985 -1.706 0.852 -1.272 0.852 -0.69 c
+0.852 -0.22 l
+0.852 0.374 0.977 0.841 1.234 1.176 c
+1.499 1.517 1.859 1.691 2.323 1.691 c
+2.782 1.691 3.123 1.536 3.351 1.234 c
+3.586 0.941 3.707 0.478 3.719 -0.147 c
+3.719 -0.573 l
+1.499 -0.573 l
+1.499 -0.661 l
+1.499 -1.095 1.577 -1.407 1.734 -1.602 c
+1.899 -1.789 2.131 -1.881 2.425 -1.881 c
+2.62 -1.881 2.793 -1.849 2.94 -1.779 c
+3.087 -1.702 3.223 -1.584 3.351 -1.426 c
+3.69 -1.837 l
+3.403 -2.242 2.973 -2.44 2.396 -2.44 c
+2.323 1.132 m
+2.047 1.132 1.845 1.036 1.72 0.852 c
+1.591 0.665 1.517 0.374 1.499 -0.015 c
+3.072 -0.015 l
+3.072 0.073 l
+3.05 0.455 2.984 0.723 2.866 0.881 c
+2.749 1.047 2.564 1.132 2.323 1.132 c
+5.35 2.572 m
+5.35 1.617 l
+5.953 1.617 l
+5.953 1.087 l
+5.35 1.087 l
+5.35 -1.382 l
+5.35 -1.54 5.373 -1.658 5.423 -1.735 c
+5.483 -1.816 5.571 -1.852 5.689 -1.852 c
+5.776 -1.852 5.865 -1.837 5.953 -1.808 c
+5.953 -2.367 l
+5.806 -2.415 5.652 -2.44 5.497 -2.44 c
+5.24 -2.44 5.045 -2.348 4.91 -2.161 c
+4.77 -1.977 4.704 -1.716 4.704 -1.382 c
+4.704 1.087 l
+4.101 1.087 l
+4.101 1.617 l
+4.704 1.617 l
+4.704 2.572 l
+h
+8.099 -1.881 m
+8.312 -1.881 8.485 -1.819 8.613 -1.691 c
+8.75 -1.554 8.823 -1.363 8.834 -1.118 c
+9.452 -1.118 l
+9.429 -1.5 9.294 -1.819 9.04 -2.072 c
+8.783 -2.319 8.47 -2.44 8.099 -2.44 c
+7.607 -2.44 7.231 -2.29 6.967 -1.984 c
+6.71 -1.672 6.585 -1.205 6.585 -0.588 c
+6.585 -0.147 l
+6.585 0.448 6.71 0.904 6.967 1.22 c
+7.231 1.532 7.607 1.691 8.099 1.691 c
+8.5 1.691 8.819 1.558 9.055 1.294 c
+9.297 1.036 9.429 0.691 9.452 0.25 c
+8.834 0.25 l
+8.812 0.544 8.739 0.764 8.613 0.912 c
+8.496 1.058 8.323 1.132 8.099 1.132 c
+7.805 1.132 7.588 1.033 7.453 0.838 c
+7.312 0.65 7.239 0.341 7.231 -0.088 c
+7.231 -0.603 l
+7.231 -1.073 7.298 -1.407 7.437 -1.602 c
+7.584 -1.789 7.805 -1.881 8.099 -1.881 c
+10.848 1.205 m
+11.102 1.529 11.421 1.691 11.803 1.691 c
+12.509 1.691 12.866 1.22 12.876 0.279 c
+12.876 -2.367 l
+12.23 -2.367 l
+12.23 0.25 l
+12.23 0.563 12.174 0.783 12.068 0.912 c
+11.958 1.036 11.803 1.103 11.597 1.103 c
+11.439 1.103 11.293 1.047 11.156 0.941 c
+11.027 0.831 10.925 0.694 10.848 0.529 c
+10.848 -2.367 l
+10.2 -2.367 l
+10.2 3.278 l
+10.848 3.278 l
+h
+16.933 -1.881 m
+17.146 -1.881 17.319 -1.819 17.448 -1.691 c
+17.583 -1.554 17.657 -1.363 17.668 -1.118 c
+18.285 -1.118 l
+18.264 -1.5 18.127 -1.819 17.874 -2.072 c
+17.616 -2.319 17.304 -2.44 16.933 -2.44 c
+16.44 -2.44 16.066 -2.29 15.802 -1.984 c
+15.544 -1.672 15.419 -1.205 15.419 -0.588 c
+15.419 -0.147 l
+15.419 0.448 15.544 0.904 15.802 1.22 c
+16.066 1.532 16.44 1.691 16.933 1.691 c
+17.334 1.691 17.653 1.558 17.888 1.294 c
+18.131 1.036 18.264 0.691 18.285 0.25 c
+17.668 0.25 l
+17.646 0.544 17.572 0.764 17.448 0.912 c
+17.33 1.058 17.157 1.132 16.933 1.132 c
+16.639 1.132 16.422 1.033 16.286 0.838 c
+16.147 0.65 16.073 0.341 16.066 -0.088 c
+16.066 -0.603 l
+16.066 -1.073 16.132 -1.407 16.272 -1.602 c
+16.419 -1.789 16.639 -1.881 16.933 -1.881 c
+19.682 1.205 m
+19.935 1.529 20.255 1.691 20.637 1.691 c
+21.343 1.691 21.699 1.22 21.71 0.279 c
+21.71 -2.367 l
+21.063 -2.367 l
+21.063 0.25 l
+21.063 0.563 21.009 0.783 20.902 0.912 c
+20.791 1.036 20.637 1.103 20.432 1.103 c
+20.274 1.103 20.126 1.047 19.991 0.941 c
+19.862 0.831 19.759 0.694 19.682 0.529 c
+19.682 -2.367 l
+19.035 -2.367 l
+19.035 3.278 l
+19.682 3.278 l
+h
+24.709 -2.367 m
+24.668 -2.278 24.643 -2.132 24.635 -1.926 c
+24.4 -2.271 24.106 -2.44 23.754 -2.44 c
+23.39 -2.44 23.106 -2.344 22.9 -2.146 c
+22.703 -1.941 22.607 -1.654 22.607 -1.278 c
+22.607 -0.879 22.743 -0.559 23.019 -0.324 c
+23.291 -0.081 23.665 0.044 24.136 0.044 c
+24.621 0.044 l
+24.621 0.47 l
+24.621 0.706 24.566 0.871 24.459 0.97 c
+24.349 1.076 24.187 1.132 23.974 1.132 c
+23.775 1.132 23.613 1.073 23.489 0.956 c
+23.371 0.838 23.312 0.691 23.312 0.515 c
+22.665 0.515 l
+22.665 0.709 22.725 0.9 22.842 1.087 c
+22.967 1.271 23.129 1.419 23.328 1.529 c
+23.533 1.635 23.761 1.691 24.018 1.691 c
+24.419 1.691 24.724 1.587 24.93 1.382 c
+25.142 1.176 25.256 0.881 25.267 0.5 c
+25.267 -1.514 l
+25.267 -1.819 25.304 -2.084 25.385 -2.308 c
+25.385 -2.367 l
+h
+23.841 -1.852 m
+24.007 -1.852 24.157 -1.808 24.297 -1.72 c
+24.444 -1.631 24.55 -1.521 24.621 -1.382 c
+24.621 -0.441 l
+24.253 -0.441 l
+23.937 -0.441 23.694 -0.511 23.518 -0.647 c
+23.342 -0.775 23.254 -0.963 23.254 -1.205 c
+23.254 -1.434 23.297 -1.598 23.386 -1.706 c
+23.474 -1.804 23.625 -1.852 23.841 -1.852 c
+26.884 1.617 m
+26.899 1.176 l
+27.153 1.517 27.476 1.691 27.869 1.691 c
+28.575 1.691 28.932 1.22 28.942 0.279 c
+28.942 -2.367 l
+28.296 -2.367 l
+28.296 0.25 l
+28.296 0.563 28.24 0.783 28.134 0.912 c
+28.024 1.036 27.869 1.103 27.663 1.103 c
+27.505 1.103 27.359 1.047 27.222 0.941 c
+27.094 0.831 26.991 0.694 26.914 0.529 c
+26.914 -2.367 l
+26.267 -2.367 l
+26.267 1.617 l
+h
+29.78 -0.191 m
+29.78 0.426 29.89 0.889 30.118 1.205 c
+30.343 1.529 30.677 1.691 31.118 1.691 c
+31.519 1.691 31.823 1.514 32.029 1.161 c
+32.073 1.617 l
+32.662 1.617 l
+32.662 -2.411 l
+32.662 -2.899 32.533 -3.278 32.279 -3.543 c
+32.022 -3.807 31.669 -3.94 31.22 -3.94 c
+31.022 -3.94 30.802 -3.888 30.559 -3.792 c
+30.313 -3.693 30.133 -3.572 30.015 -3.425 c
+30.28 -2.984 l
+30.545 -3.248 30.842 -3.381 31.176 -3.381 c
+31.713 -3.381 31.989 -3.087 31.999 -2.499 c
+31.999 -1.97 l
+31.794 -2.286 31.492 -2.44 31.103 -2.44 c
+30.692 -2.44 30.368 -2.29 30.133 -1.984 c
+29.905 -1.672 29.788 -1.22 29.78 -0.632 c
+h
+30.441 -0.573 m
+30.441 -1.014 30.504 -1.345 30.632 -1.558 c
+30.757 -1.764 30.975 -1.866 31.28 -1.866 c
+31.602 -1.866 31.841 -1.702 31.999 -1.367 c
+31.999 0.617 l
+31.831 0.941 31.592 1.103 31.28 1.103 c
+30.985 1.103 30.769 0.999 30.632 0.794 c
+30.504 0.588 30.441 0.264 30.441 -0.177 c
+h
+35.043 -2.44 m
+34.543 -2.44 34.16 -2.294 33.896 -1.999 c
+33.631 -1.706 33.499 -1.272 33.499 -0.69 c
+33.499 -0.22 l
+33.499 0.374 33.624 0.841 33.881 1.176 c
+34.146 1.517 34.505 1.691 34.969 1.691 c
+35.428 1.691 35.77 1.536 35.997 1.234 c
+36.233 0.941 36.354 0.478 36.365 -0.147 c
+36.365 -0.573 l
+34.146 -0.573 l
+34.146 -0.661 l
+34.146 -1.095 34.223 -1.407 34.381 -1.602 c
+34.546 -1.789 34.778 -1.881 35.072 -1.881 c
+35.266 -1.881 35.44 -1.849 35.586 -1.779 c
+35.733 -1.702 35.869 -1.584 35.997 -1.426 c
+36.336 -1.837 l
+36.049 -2.242 35.619 -2.44 35.043 -2.44 c
+34.969 1.132 m
+34.694 1.132 34.491 1.036 34.366 0.852 c
+34.237 0.665 34.164 0.374 34.146 -0.015 c
+35.719 -0.015 l
+35.719 0.073 l
+35.696 0.455 35.631 0.723 35.513 0.881 c
+35.395 1.047 35.211 1.132 34.969 1.132 c
+39.085 -1.353 m
+39.085 -1.205 39.029 -1.084 38.923 -0.985 c
+38.813 -0.889 38.607 -0.771 38.306 -0.632 c
+37.96 -0.485 37.717 -0.364 37.57 -0.264 c
+37.424 -0.158 37.313 -0.04 37.247 0.088 c
+37.177 0.213 37.144 0.371 37.144 0.559 c
+37.144 0.881 37.262 1.151 37.497 1.367 c
+37.732 1.58 38.033 1.691 38.409 1.691 c
+38.79 1.691 39.099 1.577 39.334 1.352 c
+39.569 1.124 39.687 0.838 39.687 0.485 c
+39.041 0.485 l
+39.041 0.661 38.981 0.812 38.864 0.941 c
+38.746 1.066 38.592 1.132 38.409 1.132 c
+38.21 1.132 38.059 1.076 37.952 0.97 c
+37.842 0.871 37.791 0.738 37.791 0.573 c
+37.791 0.445 37.828 0.338 37.909 0.25 c
+37.986 0.169 38.177 0.066 38.482 -0.059 c
+38.96 -0.246 39.29 -0.434 39.467 -0.617 c
+39.643 -0.794 39.731 -1.022 39.731 -1.294 c
+39.731 -1.646 39.606 -1.926 39.363 -2.132 c
+39.128 -2.337 38.813 -2.44 38.423 -2.44 c
+38 -2.44 37.663 -2.323 37.409 -2.087 c
+37.152 -1.845 37.027 -1.54 37.027 -1.176 c
+37.674 -1.176 l
+37.68 -1.404 37.751 -1.58 37.879 -1.706 c
+38.004 -1.823 38.187 -1.881 38.423 -1.881 c
+38.636 -1.881 38.798 -1.833 38.908 -1.735 c
+39.026 -1.639 39.085 -1.511 39.085 -1.353 c
+42.583 -2.367 m
+42.583 1.087 l
+42.054 1.087 l
+42.054 1.617 l
+42.583 1.617 l
+42.583 2.072 l
+42.583 2.473 42.679 2.786 42.877 3.013 c
+43.083 3.237 43.361 3.351 43.715 3.351 c
+43.851 3.351 43.983 3.329 44.111 3.293 c
+44.082 2.749 l
+43.983 2.767 43.884 2.778 43.789 2.778 c
+43.413 2.778 43.23 2.514 43.23 1.984 c
+43.23 1.617 l
+43.906 1.617 l
+43.906 1.087 l
+43.23 1.087 l
+43.23 -2.367 l
+h
+46.316 0.999 m
+46.228 1.018 46.129 1.029 46.023 1.029 c
+45.688 1.029 45.453 0.845 45.317 0.485 c
+45.317 -2.367 l
+44.67 -2.367 l
+44.67 1.617 l
+45.302 1.617 l
+45.317 1.205 l
+45.493 1.529 45.736 1.691 46.052 1.691 c
+46.158 1.691 46.247 1.668 46.316 1.631 c
+h
+46.758 -0.191 m
+46.758 0.386 46.893 0.841 47.169 1.176 c
+47.452 1.517 47.823 1.691 48.286 1.691 c
+48.745 1.691 49.113 1.521 49.389 1.191 c
+49.672 0.867 49.819 0.419 49.83 -0.147 c
+49.83 -0.573 l
+49.83 -1.143 49.686 -1.598 49.403 -1.941 c
+49.127 -2.275 48.76 -2.44 48.3 -2.44 c
+47.838 -2.44 47.467 -2.278 47.184 -1.955 c
+46.908 -1.625 46.765 -1.183 46.758 -0.632 c
+h
+47.404 -0.573 m
+47.404 -0.977 47.481 -1.294 47.639 -1.529 c
+47.805 -1.764 48.026 -1.881 48.3 -1.881 c
+48.867 -1.881 49.161 -1.47 49.183 -0.647 c
+49.183 -0.191 l
+49.183 0.21 49.098 0.529 48.933 0.764 c
+48.775 1.007 48.558 1.132 48.286 1.132 c
+48.022 1.132 47.805 1.007 47.639 0.764 c
+47.481 0.529 47.404 0.21 47.404 -0.191 c
+h
+51.284 1.617 m
+51.299 1.249 l
+51.542 1.544 51.862 1.691 52.255 1.691 c
+52.696 1.691 53.004 1.492 53.181 1.103 c
+53.435 1.492 53.784 1.691 54.224 1.691 c
+54.96 1.691 55.334 1.228 55.356 0.309 c
+55.356 -2.367 l
+54.71 -2.367 l
+54.71 0.25 l
+54.71 0.544 54.654 0.757 54.548 0.897 c
+54.449 1.033 54.276 1.103 54.033 1.103 c
+53.835 1.103 53.673 1.022 53.549 0.867 c
+53.431 0.721 53.361 0.529 53.343 0.294 c
+53.343 -2.367 l
+52.681 -2.367 l
+52.681 0.279 l
+52.681 0.827 52.46 1.103 52.02 1.103 c
+51.685 1.103 51.45 0.941 51.315 0.617 c
+51.315 -2.367 l
+50.667 -2.367 l
+50.667 1.617 l
+h
+58.899 2.572 m
+58.899 1.617 l
+59.502 1.617 l
+59.502 1.087 l
+58.899 1.087 l
+58.899 -1.382 l
+58.899 -1.54 58.921 -1.658 58.972 -1.735 c
+59.031 -1.816 59.119 -1.852 59.237 -1.852 c
+59.325 -1.852 59.413 -1.837 59.502 -1.808 c
+59.502 -2.367 l
+59.354 -2.415 59.2 -2.44 59.046 -2.44 c
+58.789 -2.44 58.594 -2.348 58.458 -2.161 c
+58.318 -1.977 58.252 -1.716 58.252 -1.382 c
+58.252 1.087 l
+57.649 1.087 l
+57.649 1.617 l
+58.252 1.617 l
+58.252 2.572 l
+h
+60.913 1.205 m
+61.166 1.529 61.486 1.691 61.868 1.691 c
+62.573 1.691 62.93 1.22 62.941 0.279 c
+62.941 -2.367 l
+62.295 -2.367 l
+62.295 0.25 l
+62.295 0.563 62.239 0.783 62.133 0.912 c
+62.022 1.036 61.868 1.103 61.663 1.103 c
+61.505 1.103 61.357 1.047 61.221 0.941 c
+61.093 0.831 60.99 0.694 60.913 0.529 c
+60.913 -2.367 l
+60.266 -2.367 l
+60.266 3.278 l
+60.913 3.278 l
+h
+65.322 -2.44 m
+64.823 -2.44 64.441 -2.294 64.176 -1.999 c
+63.911 -1.706 63.779 -1.272 63.779 -0.69 c
+63.779 -0.22 l
+63.779 0.374 63.903 0.841 64.161 1.176 c
+64.426 1.517 64.786 1.691 65.249 1.691 c
+65.708 1.691 66.05 1.536 66.278 1.234 c
+66.513 0.941 66.634 0.478 66.645 -0.147 c
+66.645 -0.573 l
+64.426 -0.573 l
+64.426 -0.661 l
+64.426 -1.095 64.503 -1.407 64.661 -1.602 c
+64.826 -1.789 65.058 -1.881 65.352 -1.881 c
+65.547 -1.881 65.719 -1.849 65.866 -1.779 c
+66.014 -1.702 66.149 -1.584 66.278 -1.426 c
+66.616 -1.837 l
+66.33 -2.242 65.9 -2.44 65.322 -2.44 c
+65.249 1.132 m
+64.973 1.132 64.771 1.036 64.647 0.852 c
+64.518 0.665 64.444 0.374 64.426 -0.015 c
+65.999 -0.015 l
+65.999 0.073 l
+65.977 0.455 65.91 0.723 65.792 0.881 c
+65.675 1.047 65.491 1.132 65.249 1.132 c
+f
+Q
+q 1 0 0 1 147.2304 260.4136 cm
+0 0 m
+-0.339 0.029 l
+-0.626 0.029 -0.817 -0.096 -0.912 -0.339 c
+-0.912 -2.97 l
+-1.956 -2.97 l
+-1.956 1.014 l
+-0.985 1.014 l
+-0.956 0.573 l
+-0.79 0.914 -0.559 1.087 -0.265 1.087 c
+-0.148 1.087 -0.056 1.065 0.014 1.028 c
+h
+2.072 -3.043 m
+1.543 -3.043 1.124 -2.889 0.822 -2.573 c
+0.529 -2.249 0.382 -1.79 0.382 -1.191 c
+0.382 -0.882 l
+0.382 -0.258 0.517 0.228 0.793 0.573 c
+1.065 0.914 1.458 1.087 1.969 1.087 c
+2.468 1.087 2.84 0.926 3.087 0.602 c
+3.34 0.278 3.472 -0.199 3.484 -0.823 c
+3.484 -1.324 l
+1.411 -1.324 l
+1.429 -1.617 1.491 -1.834 1.602 -1.97 c
+1.72 -2.11 1.899 -2.176 2.146 -2.176 c
+2.487 -2.176 2.778 -2.058 3.013 -1.823 c
+3.424 -2.455 l
+3.295 -2.631 3.108 -2.775 2.865 -2.882 c
+2.62 -2.988 2.355 -3.043 2.072 -3.043 c
+1.425 -0.603 m
+2.454 -0.603 l
+2.454 -0.5 l
+2.454 -0.265 2.414 -0.088 2.337 0.029 c
+2.267 0.154 2.138 0.22 1.955 0.22 c
+1.778 0.22 1.646 0.151 1.558 0.014 c
+1.477 -0.115 1.433 -0.32 1.425 -0.603 c
+5.041 1.014 m
+5.071 0.646 l
+5.306 0.941 5.614 1.087 5.996 1.087 c
+6.397 1.087 6.676 0.903 6.834 0.544 c
+7.07 0.903 7.397 1.087 7.819 1.087 c
+8.514 1.087 8.866 0.602 8.878 -0.368 c
+8.878 -2.97 l
+7.849 -2.97 l
+7.849 -0.427 l
+7.849 -0.202 7.812 -0.04 7.746 0.058 c
+7.687 0.154 7.577 0.205 7.422 0.205 c
+7.224 0.205 7.085 0.087 6.996 -0.148 c
+6.996 -2.97 l
+5.953 -2.97 l
+5.953 -0.441 l
+5.953 -0.206 5.923 -0.04 5.865 0.058 c
+5.805 0.154 5.695 0.205 5.541 0.205 c
+5.365 0.205 5.221 0.11 5.115 -0.074 c
+5.115 -2.97 l
+4.072 -2.97 l
+4.072 1.014 l
+h
+9.539 -0.853 m
+9.539 -0.246 9.679 0.228 9.965 0.573 c
+10.248 0.914 10.642 1.087 11.141 1.087 c
+11.648 1.087 12.045 0.914 12.332 0.573 c
+12.615 0.228 12.758 -0.246 12.758 -0.853 c
+12.758 -1.118 l
+12.758 -1.717 12.615 -2.187 12.332 -2.529 c
+12.045 -2.874 11.648 -3.043 11.141 -3.043 c
+10.63 -3.043 10.233 -2.874 9.951 -2.529 c
+9.676 -2.187 9.539 -1.713 9.539 -1.103 c
+h
+10.583 -1.118 m
+10.583 -1.823 10.767 -2.176 11.141 -2.176 c
+11.494 -2.176 11.685 -1.882 11.715 -1.294 c
+11.715 -0.853 l
+11.715 -0.493 11.663 -0.221 11.567 -0.044 c
+11.469 0.132 11.326 0.22 11.141 0.22 c
+10.965 0.22 10.825 0.132 10.73 -0.044 c
+10.63 -0.221 10.583 -0.493 10.583 -0.853 c
+h
+14.611 1.984 m
+14.611 1.014 l
+15.139 1.014 l
+15.139 0.22 l
+14.611 0.22 l
+14.611 -1.75 l
+14.611 -1.908 14.629 -2.014 14.669 -2.073 c
+14.717 -2.132 14.802 -2.161 14.919 -2.161 c
+15.025 -2.161 15.11 -2.154 15.168 -2.132 c
+15.168 -2.94 l
+14.993 -3.007 14.802 -3.043 14.596 -3.043 c
+13.919 -3.043 13.574 -2.658 13.566 -1.882 c
+13.566 0.22 l
+13.111 0.22 l
+13.111 1.014 l
+13.566 1.014 l
+13.566 1.984 l
+h
+17.315 -3.043 m
+16.786 -3.043 16.367 -2.889 16.066 -2.573 c
+15.771 -2.249 15.625 -1.79 15.625 -1.191 c
+15.625 -0.882 l
+15.625 -0.258 15.76 0.228 16.036 0.573 c
+16.308 0.914 16.701 1.087 17.212 1.087 c
+17.712 1.087 18.083 0.926 18.329 0.602 c
+18.582 0.278 18.715 -0.199 18.726 -0.823 c
+18.726 -1.324 l
+16.654 -1.324 l
+16.672 -1.617 16.735 -1.834 16.845 -1.97 c
+16.962 -2.11 17.142 -2.176 17.389 -2.176 c
+17.73 -2.176 18.021 -2.058 18.256 -1.823 c
+18.667 -2.455 l
+18.539 -2.631 18.351 -2.775 18.109 -2.882 c
+17.863 -2.988 17.598 -3.043 17.315 -3.043 c
+16.668 -0.603 m
+17.697 -0.603 l
+17.697 -0.5 l
+17.697 -0.265 17.657 -0.088 17.58 0.029 c
+17.51 0.154 17.381 0.22 17.198 0.22 c
+17.021 0.22 16.889 0.151 16.801 0.014 c
+16.72 -0.115 16.676 -0.32 16.668 -0.603 c
+f
+Q
+q 1 0 0 1 166.6623 256.3712 cm
+0 0 m
+-0.397 0.264 l
+-0.162 0.588 -0.04 0.922 -0.03 1.263 c
+-0.03 1.881 l
+0.632 1.881 l
+0.632 1.352 l
+0.632 1.095 0.565 0.849 0.44 0.602 c
+0.324 0.359 0.176 0.158 0 0 c
+6.071 2.866 m
+6.071 2.248 5.957 1.782 5.733 1.469 c
+5.516 1.153 5.192 0.999 4.762 0.999 c
+4.34 0.999 4.027 1.18 3.821 1.543 c
+3.792 1.072 l
+3.189 1.072 l
+3.189 6.717 l
+3.836 6.717 l
+3.836 4.615 l
+4.049 4.957 4.358 5.13 4.762 5.13 c
+5.192 5.13 5.516 4.972 5.733 4.659 c
+5.957 4.355 6.071 3.887 6.071 3.262 c
+h
+5.423 3.248 m
+5.423 3.719 5.354 4.049 5.218 4.247 c
+5.089 4.442 4.88 4.542 4.586 4.542 c
+4.251 4.542 4.002 4.358 3.836 3.998 c
+3.836 2.117 l
+4.002 1.753 4.255 1.573 4.6 1.573 c
+4.895 1.573 5.104 1.675 5.232 1.881 c
+5.358 2.087 5.423 2.403 5.423 2.836 c
+h
+8.937 1.425 m
+8.72 1.139 8.407 0.999 7.996 0.999 c
+7.632 0.999 7.357 1.12 7.173 1.367 c
+6.996 1.62 6.901 1.984 6.894 2.454 c
+6.894 5.056 l
+7.54 5.056 l
+7.54 2.514 l
+7.54 1.885 7.724 1.573 8.099 1.573 c
+8.5 1.573 8.775 1.749 8.922 2.102 c
+8.922 5.056 l
+9.569 5.056 l
+9.569 1.072 l
+8.951 1.072 l
+h
+11.406 6.011 m
+11.406 5.056 l
+12.009 5.056 l
+12.009 4.527 l
+11.406 4.527 l
+11.406 2.057 l
+11.406 1.899 11.428 1.782 11.48 1.705 c
+11.538 1.624 11.627 1.587 11.744 1.587 c
+11.833 1.587 11.921 1.602 12.009 1.631 c
+12.009 1.072 l
+11.862 1.024 11.708 0.999 11.553 0.999 c
+11.296 0.999 11.102 1.091 10.965 1.278 c
+10.826 1.462 10.759 1.723 10.759 2.057 c
+10.759 4.527 l
+10.157 4.527 l
+10.157 5.056 l
+10.759 5.056 l
+10.759 6.011 l
+h
+15.11 5.056 m
+15.125 4.615 l
+15.378 4.957 15.702 5.13 16.095 5.13 c
+16.801 5.13 17.157 4.659 17.169 3.719 c
+17.169 1.072 l
+16.521 1.072 l
+16.521 3.69 l
+16.521 4.002 16.467 4.222 16.359 4.351 c
+16.249 4.475 16.095 4.542 15.889 4.542 c
+15.731 4.542 15.584 4.486 15.449 4.38 c
+15.32 4.27 15.217 4.134 15.14 3.968 c
+15.14 1.072 l
+14.493 1.072 l
+14.493 5.056 l
+h
+18.006 3.248 m
+18.006 3.825 18.142 4.28 18.418 4.615 c
+18.701 4.957 19.072 5.13 19.534 5.13 c
+19.994 5.13 20.361 4.961 20.637 4.63 c
+20.92 4.307 21.067 3.858 21.078 3.293 c
+21.078 2.866 l
+21.078 2.296 20.935 1.841 20.652 1.499 c
+20.376 1.165 20.009 0.999 19.55 0.999 c
+19.087 0.999 18.715 1.161 18.433 1.484 c
+18.157 1.815 18.013 2.256 18.006 2.807 c
+h
+18.653 2.866 m
+18.653 2.462 18.73 2.146 18.888 1.911 c
+19.054 1.675 19.274 1.558 19.55 1.558 c
+20.116 1.558 20.409 1.969 20.431 2.792 c
+20.431 3.248 l
+20.431 3.649 20.347 3.968 20.182 4.203 c
+20.024 4.446 19.806 4.571 19.534 4.571 c
+19.27 4.571 19.054 4.446 18.888 4.203 c
+18.73 3.968 18.653 3.649 18.653 3.248 c
+h
+22.769 6.011 m
+22.769 5.056 l
+23.372 5.056 l
+23.372 4.527 l
+22.769 4.527 l
+22.769 2.057 l
+22.769 1.899 22.79 1.782 22.842 1.705 c
+22.901 1.624 22.989 1.587 23.106 1.587 c
+23.195 1.587 23.283 1.602 23.372 1.631 c
+23.372 1.072 l
+23.224 1.024 23.07 0.999 22.915 0.999 c
+22.659 0.999 22.464 1.091 22.328 1.278 c
+22.188 1.462 22.121 1.723 22.121 2.057 c
+22.121 4.527 l
+21.519 4.527 l
+21.519 5.056 l
+22.121 5.056 l
+22.121 6.011 l
+h
+27.884 1.425 m
+27.667 1.139 27.355 0.999 26.943 0.999 c
+26.58 0.999 26.304 1.12 26.12 1.367 c
+25.944 1.62 25.848 1.984 25.84 2.454 c
+25.84 5.056 l
+26.487 5.056 l
+26.487 2.514 l
+26.487 1.885 26.671 1.573 27.046 1.573 c
+27.447 1.573 27.722 1.749 27.869 2.102 c
+27.869 5.056 l
+28.516 5.056 l
+28.516 1.072 l
+27.899 1.072 l
+h
+32.382 2.866 m
+32.382 2.238 32.265 1.768 32.029 1.455 c
+31.801 1.15 31.485 0.999 31.074 0.999 c
+30.669 0.999 30.361 1.15 30.148 1.455 c
+30.148 -0.456 l
+29.501 -0.456 l
+29.501 5.056 l
+30.089 5.056 l
+30.133 4.615 l
+30.346 4.957 30.655 5.13 31.059 5.13 c
+31.5 5.13 31.827 4.976 32.043 4.674 c
+32.257 4.369 32.371 3.913 32.382 3.307 c
+h
+31.735 3.248 m
+31.735 3.69 31.665 4.012 31.529 4.218 c
+31.39 4.432 31.17 4.542 30.868 4.542 c
+30.551 4.542 30.313 4.388 30.148 4.086 c
+30.148 2.013 l
+30.313 1.708 30.551 1.558 30.868 1.558 c
+31.162 1.558 31.375 1.66 31.515 1.866 c
+31.65 2.08 31.724 2.41 31.735 2.851 c
+h
+33.088 3.248 m
+33.088 3.854 33.198 4.321 33.425 4.644 c
+33.661 4.968 33.988 5.13 34.41 5.13 c
+34.792 5.13 35.091 4.972 35.307 4.659 c
+35.307 6.717 l
+35.953 6.717 l
+35.953 1.072 l
+35.366 1.072 l
+35.322 1.499 l
+35.116 1.165 34.811 0.999 34.41 0.999 c
+33.998 0.999 33.676 1.153 33.44 1.469 c
+33.205 1.793 33.088 2.248 33.088 2.836 c
+h
+33.734 2.866 m
+33.734 2.425 33.797 2.094 33.925 1.881 c
+34.061 1.675 34.281 1.573 34.586 1.573 c
+34.91 1.573 35.149 1.734 35.307 2.057 c
+35.307 4.072 l
+35.138 4.384 34.899 4.542 34.586 4.542 c
+34.281 4.542 34.061 4.438 33.925 4.233 c
+33.797 4.027 33.734 3.704 33.734 3.262 c
+h
+38.996 1.072 m
+38.956 1.161 38.931 1.308 38.923 1.514 c
+38.688 1.168 38.393 0.999 38.041 0.999 c
+37.678 0.999 37.394 1.095 37.188 1.294 c
+36.99 1.499 36.894 1.786 36.894 2.161 c
+36.894 2.561 37.03 2.881 37.306 3.116 c
+37.578 3.358 37.953 3.484 38.424 3.484 c
+38.908 3.484 l
+38.908 3.91 l
+38.908 4.145 38.853 4.31 38.746 4.409 c
+38.636 4.516 38.474 4.571 38.262 4.571 c
+38.063 4.571 37.901 4.513 37.776 4.395 c
+37.659 4.278 37.599 4.13 37.599 3.954 c
+36.953 3.954 l
+36.953 4.149 37.012 4.34 37.129 4.527 c
+37.254 4.71 37.416 4.858 37.615 4.968 c
+37.821 5.074 38.048 5.13 38.305 5.13 c
+38.706 5.13 39.011 5.026 39.217 4.821 c
+39.43 4.615 39.544 4.321 39.555 3.939 c
+39.555 1.926 l
+39.555 1.62 39.592 1.356 39.673 1.132 c
+39.673 1.072 l
+h
+38.129 1.587 m
+38.295 1.587 38.445 1.631 38.584 1.72 c
+38.732 1.808 38.838 1.918 38.908 2.057 c
+38.908 2.998 l
+38.54 2.998 l
+38.225 2.998 37.982 2.928 37.806 2.792 c
+37.63 2.664 37.541 2.476 37.541 2.234 c
+37.541 2.006 37.585 1.841 37.674 1.734 c
+37.761 1.635 37.913 1.587 38.129 1.587 c
+41.407 6.011 m
+41.407 5.056 l
+42.01 5.056 l
+42.01 4.527 l
+41.407 4.527 l
+41.407 2.057 l
+41.407 1.899 41.429 1.782 41.481 1.705 c
+41.539 1.624 41.628 1.587 41.745 1.587 c
+41.833 1.587 41.921 1.602 42.01 1.631 c
+42.01 1.072 l
+41.863 1.024 41.709 0.999 41.554 0.999 c
+41.297 0.999 41.102 1.091 40.966 1.278 c
+40.826 1.462 40.76 1.723 40.76 2.057 c
+40.76 4.527 l
+40.157 4.527 l
+40.157 5.056 l
+40.76 5.056 l
+40.76 6.011 l
+h
+44.2 0.999 m
+43.7 0.999 43.318 1.146 43.053 1.44 c
+42.789 1.734 42.657 2.167 42.657 2.749 c
+42.657 3.219 l
+42.657 3.814 42.781 4.28 43.039 4.615 c
+43.303 4.957 43.663 5.13 44.126 5.13 c
+44.585 5.13 44.928 4.976 45.156 4.674 c
+45.391 4.38 45.512 3.917 45.522 3.293 c
+45.522 2.866 l
+43.303 2.866 l
+43.303 2.778 l
+43.303 2.344 43.38 2.032 43.538 1.837 c
+43.704 1.65 43.935 1.558 44.229 1.558 c
+44.424 1.558 44.597 1.591 44.743 1.66 c
+44.89 1.738 45.027 1.855 45.156 2.013 c
+45.493 1.602 l
+45.206 1.198 44.776 0.999 44.2 0.999 c
+44.126 4.571 m
+43.851 4.571 43.648 4.475 43.523 4.292 c
+43.395 4.104 43.322 3.814 43.303 3.424 c
+44.876 3.424 l
+44.876 3.513 l
+44.854 3.895 44.788 4.163 44.67 4.321 c
+44.552 4.486 44.369 4.571 44.126 4.571 c
+48.874 6.011 m
+48.874 5.056 l
+49.477 5.056 l
+49.477 4.527 l
+48.874 4.527 l
+48.874 2.057 l
+48.874 1.899 48.896 1.782 48.948 1.705 c
+49.007 1.624 49.094 1.587 49.212 1.587 c
+49.3 1.587 49.389 1.602 49.477 1.631 c
+49.477 1.072 l
+49.33 1.024 49.175 0.999 49.021 0.999 c
+48.764 0.999 48.569 1.091 48.433 1.278 c
+48.294 1.462 48.227 1.723 48.227 2.057 c
+48.227 4.527 l
+47.625 4.527 l
+47.625 5.056 l
+48.227 5.056 l
+48.227 6.011 l
+h
+51.887 4.438 m
+51.799 4.457 51.7 4.469 51.594 4.469 c
+51.259 4.469 51.024 4.284 50.888 3.925 c
+50.888 1.072 l
+50.241 1.072 l
+50.241 5.056 l
+50.873 5.056 l
+50.888 4.644 l
+51.064 4.968 51.307 5.13 51.623 5.13 c
+51.729 5.13 51.818 5.107 51.887 5.071 c
+h
+54.43 1.072 m
+54.39 1.161 54.364 1.308 54.357 1.514 c
+54.122 1.168 53.827 0.999 53.475 0.999 c
+53.111 0.999 52.828 1.095 52.622 1.294 c
+52.424 1.499 52.329 1.786 52.329 2.161 c
+52.329 2.561 52.464 2.881 52.74 3.116 c
+53.012 3.358 53.387 3.484 53.857 3.484 c
+54.342 3.484 l
+54.342 3.91 l
+54.342 4.145 54.287 4.31 54.181 4.409 c
+54.07 4.516 53.908 4.571 53.696 4.571 c
+53.497 4.571 53.335 4.513 53.21 4.395 c
+53.093 4.278 53.034 4.13 53.034 3.954 c
+52.387 3.954 l
+52.387 4.149 52.446 4.34 52.564 4.527 c
+52.689 4.71 52.85 4.858 53.048 4.968 c
+53.254 5.074 53.482 5.13 53.74 5.13 c
+54.141 5.13 54.445 5.026 54.651 4.821 c
+54.864 4.615 54.978 4.321 54.989 3.939 c
+54.989 1.926 l
+54.989 1.62 55.026 1.356 55.107 1.132 c
+55.107 1.072 l
+h
+53.563 1.587 m
+53.728 1.587 53.879 1.631 54.019 1.72 c
+54.166 1.808 54.272 1.918 54.342 2.057 c
+54.342 2.998 l
+53.975 2.998 l
+53.659 2.998 53.416 2.928 53.24 2.792 c
+53.063 2.664 52.975 2.476 52.975 2.234 c
+52.975 2.006 53.019 1.841 53.108 1.734 c
+53.196 1.635 53.347 1.587 53.563 1.587 c
+57.37 1.558 m
+57.584 1.558 57.756 1.62 57.885 1.749 c
+58.021 1.885 58.094 2.076 58.105 2.322 c
+58.723 2.322 l
+58.7 1.94 58.565 1.62 58.311 1.367 c
+58.054 1.12 57.742 0.999 57.37 0.999 c
+56.878 0.999 56.503 1.15 56.238 1.455 c
+55.982 1.768 55.856 2.234 55.856 2.851 c
+55.856 3.293 l
+55.856 3.887 55.982 4.343 56.238 4.659 c
+56.503 4.972 56.878 5.13 57.37 5.13 c
+57.771 5.13 58.091 4.997 58.326 4.733 c
+58.569 4.475 58.7 4.13 58.723 3.69 c
+58.105 3.69 l
+58.083 3.983 58.01 4.203 57.885 4.351 c
+57.767 4.498 57.594 4.571 57.37 4.571 c
+57.077 4.571 56.859 4.472 56.724 4.278 c
+56.584 4.089 56.51 3.781 56.503 3.351 c
+56.503 2.836 l
+56.503 2.366 56.57 2.032 56.709 1.837 c
+56.855 1.65 57.077 1.558 57.37 1.558 c
+60.472 2.896 m
+60.134 2.499 l
+60.134 1.072 l
+59.472 1.072 l
+59.472 6.717 l
+60.134 6.717 l
+60.134 3.337 l
+61.368 5.056 l
+62.147 5.056 l
+60.883 3.395 l
+62.309 1.072 l
+61.559 1.072 l
+h
+63.573 1.072 -0.647 3.984 re
+63.618 6.1 m
+63.618 5.99 63.588 5.897 63.529 5.82 c
+63.47 5.751 63.375 5.718 63.25 5.718 c
+63.132 5.718 63.037 5.751 62.97 5.82 c
+62.912 5.897 62.883 5.99 62.883 6.1 c
+62.883 6.217 62.912 6.31 62.97 6.379 c
+63.037 6.456 63.132 6.497 63.25 6.497 c
+63.375 6.497 63.47 6.456 63.529 6.379 c
+63.588 6.298 63.618 6.206 63.618 6.1 c
+65.205 5.056 m
+65.22 4.615 l
+65.473 4.957 65.796 5.13 66.189 5.13 c
+66.895 5.13 67.252 4.659 67.263 3.719 c
+67.263 1.072 l
+66.616 1.072 l
+66.616 3.69 l
+66.616 4.002 66.561 4.222 66.454 4.351 c
+66.344 4.475 66.189 4.542 65.983 4.542 c
+65.825 4.542 65.679 4.486 65.543 4.38 c
+65.414 4.27 65.312 4.134 65.235 3.968 c
+65.235 1.072 l
+64.587 1.072 l
+64.587 5.056 l
+h
+68.1 3.248 m
+68.1 3.865 68.211 4.328 68.439 4.644 c
+68.663 4.968 68.998 5.13 69.438 5.13 c
+69.839 5.13 70.143 4.953 70.349 4.6 c
+70.394 5.056 l
+70.982 5.056 l
+70.982 1.028 l
+70.982 0.54 70.853 0.162 70.6 -0.103 c
+70.342 -0.368 69.989 -0.5 69.541 -0.5 c
+69.343 -0.5 69.122 -0.449 68.879 -0.353 c
+68.634 -0.254 68.453 -0.133 68.335 0.014 c
+68.601 0.455 l
+68.865 0.191 69.162 0.058 69.497 0.058 c
+70.033 0.058 70.309 0.353 70.32 0.941 c
+70.32 1.469 l
+70.114 1.153 69.813 0.999 69.424 0.999 c
+69.012 0.999 68.688 1.15 68.453 1.455 c
+68.225 1.768 68.108 2.219 68.1 2.807 c
+h
+68.762 2.866 m
+68.762 2.425 68.825 2.094 68.953 1.881 c
+69.078 1.675 69.295 1.573 69.6 1.573 c
+69.923 1.573 70.162 1.738 70.32 2.072 c
+70.32 4.056 l
+70.151 4.38 69.912 4.542 69.6 4.542 c
+69.306 4.542 69.089 4.438 68.953 4.233 c
+68.825 4.027 68.762 3.704 68.762 3.262 c
+h
+76.538 2.866 m
+76.538 2.248 76.424 1.782 76.2 1.469 c
+75.983 1.153 75.66 0.999 75.229 0.999 c
+74.807 0.999 74.494 1.18 74.288 1.543 c
+74.259 1.072 l
+73.657 1.072 l
+73.657 6.717 l
+74.303 6.717 l
+74.303 4.615 l
+74.517 4.957 74.825 5.13 75.229 5.13 c
+75.66 5.13 75.983 4.972 76.2 4.659 c
+76.424 4.355 76.538 3.887 76.538 3.262 c
+h
+75.891 3.248 m
+75.891 3.719 75.821 4.049 75.685 4.247 c
+75.556 4.442 75.348 4.542 75.053 4.542 c
+74.719 4.542 74.469 4.358 74.303 3.998 c
+74.303 2.117 l
+74.469 1.753 74.722 1.573 75.068 1.573 c
+75.362 1.573 75.571 1.675 75.699 1.881 c
+75.825 2.087 75.891 2.403 75.891 2.836 c
+h
+79.022 4.438 m
+78.934 4.457 78.835 4.469 78.728 4.469 c
+78.394 4.469 78.159 4.284 78.022 3.925 c
+78.022 1.072 l
+77.376 1.072 l
+77.376 5.056 l
+78.008 5.056 l
+78.022 4.644 l
+78.199 4.968 78.442 5.13 78.757 5.13 c
+78.864 5.13 78.953 5.107 79.022 5.071 c
+h
+81.565 1.072 m
+81.524 1.161 81.499 1.308 81.492 1.514 c
+81.256 1.168 80.962 0.999 80.609 0.999 c
+80.246 0.999 79.963 1.095 79.757 1.294 c
+79.558 1.499 79.462 1.786 79.462 2.161 c
+79.462 2.561 79.599 2.881 79.874 3.116 c
+80.146 3.358 80.522 3.484 80.992 3.484 c
+81.477 3.484 l
+81.477 3.91 l
+81.477 4.145 81.422 4.31 81.315 4.409 c
+81.205 4.516 81.043 4.571 80.83 4.571 c
+80.632 4.571 80.47 4.513 80.345 4.395 c
+80.227 4.278 80.168 4.13 80.168 3.954 c
+79.522 3.954 l
+79.522 4.149 79.581 4.34 79.698 4.527 c
+79.823 4.71 79.984 4.858 80.183 4.968 c
+80.389 5.074 80.617 5.13 80.873 5.13 c
+81.274 5.13 81.579 5.026 81.785 4.821 c
+81.999 4.615 82.112 4.321 82.124 3.939 c
+82.124 1.926 l
+82.124 1.62 82.16 1.356 82.241 1.132 c
+82.241 1.072 l
+h
+80.698 1.587 m
+80.863 1.587 81.014 1.631 81.153 1.72 c
+81.301 1.808 81.407 1.918 81.477 2.057 c
+81.477 2.998 l
+81.109 2.998 l
+80.794 2.998 80.551 2.928 80.374 2.792 c
+80.198 2.664 80.11 2.476 80.11 2.234 c
+80.11 2.006 80.154 1.841 80.242 1.734 c
+80.33 1.635 80.481 1.587 80.698 1.587 c
+83.74 5.056 m
+83.755 4.615 l
+84.009 4.957 84.332 5.13 84.725 5.13 c
+85.43 5.13 85.787 4.659 85.798 3.719 c
+85.798 1.072 l
+85.151 1.072 l
+85.151 3.69 l
+85.151 4.002 85.096 4.222 84.99 4.351 c
+84.879 4.475 84.725 4.542 84.52 4.542 c
+84.362 4.542 84.214 4.486 84.079 4.38 c
+83.95 4.27 83.847 4.134 83.77 3.968 c
+83.77 1.072 l
+83.123 1.072 l
+83.123 5.056 l
+h
+88.15 1.558 m
+88.363 1.558 88.536 1.62 88.665 1.749 c
+88.8 1.885 88.874 2.076 88.885 2.322 c
+89.502 2.322 l
+89.48 1.94 89.344 1.62 89.091 1.367 c
+88.833 1.12 88.521 0.999 88.15 0.999 c
+87.657 0.999 87.283 1.15 87.018 1.455 c
+86.761 1.768 86.636 2.234 86.636 2.851 c
+86.636 3.293 l
+86.636 3.887 86.761 4.343 87.018 4.659 c
+87.283 4.972 87.657 5.13 88.15 5.13 c
+88.551 5.13 88.87 4.997 89.105 4.733 c
+89.348 4.475 89.48 4.13 89.502 3.69 c
+88.885 3.69 l
+88.863 3.983 88.79 4.203 88.665 4.351 c
+88.547 4.498 88.374 4.571 88.15 4.571 c
+87.856 4.571 87.639 4.472 87.503 4.278 c
+87.364 4.089 87.29 3.781 87.283 3.351 c
+87.283 2.836 l
+87.283 2.366 87.349 2.032 87.489 1.837 c
+87.636 1.65 87.856 1.558 88.15 1.558 c
+90.899 4.644 m
+91.152 4.968 91.472 5.13 91.854 5.13 c
+92.559 5.13 92.916 4.659 92.927 3.719 c
+92.927 1.072 l
+92.281 1.072 l
+92.281 3.69 l
+92.281 4.002 92.225 4.222 92.119 4.351 c
+92.008 4.475 91.854 4.542 91.649 4.542 c
+91.491 4.542 91.343 4.486 91.208 4.38 c
+91.079 4.27 90.976 4.134 90.899 3.968 c
+90.899 1.072 l
+90.252 1.072 l
+90.252 6.717 l
+90.899 6.717 l
+h
+95.308 0.999 m
+94.809 0.999 94.427 1.146 94.162 1.44 c
+93.897 1.734 93.765 2.167 93.765 2.749 c
+93.765 3.219 l
+93.765 3.814 93.89 4.28 94.147 4.615 c
+94.412 4.957 94.772 5.13 95.235 5.13 c
+95.694 5.13 96.036 4.976 96.264 4.674 c
+96.499 4.38 96.621 3.917 96.631 3.293 c
+96.631 2.866 l
+94.412 2.866 l
+94.412 2.778 l
+94.412 2.344 94.489 2.032 94.647 1.837 c
+94.812 1.65 95.044 1.558 95.338 1.558 c
+95.533 1.558 95.705 1.591 95.852 1.66 c
+96 1.738 96.135 1.855 96.264 2.013 c
+96.602 1.602 l
+96.316 1.198 95.886 0.999 95.308 0.999 c
+95.235 4.571 m
+94.959 4.571 94.757 4.475 94.633 4.292 c
+94.504 4.104 94.43 3.814 94.412 3.424 c
+95.985 3.424 l
+95.985 3.513 l
+95.963 3.895 95.896 4.163 95.779 4.321 c
+95.661 4.486 95.478 4.571 95.235 4.571 c
+99.351 2.087 m
+99.351 2.234 99.296 2.356 99.189 2.454 c
+99.079 2.55 98.873 2.668 98.572 2.807 c
+98.226 2.954 97.984 3.075 97.837 3.175 c
+97.69 3.281 97.579 3.399 97.513 3.528 c
+97.444 3.652 97.411 3.81 97.411 3.998 c
+97.411 4.321 97.528 4.59 97.764 4.806 c
+97.999 5.02 98.3 5.13 98.674 5.13 c
+99.057 5.13 99.366 5.016 99.601 4.791 c
+99.836 4.564 99.954 4.278 99.954 3.925 c
+99.306 3.925 l
+99.306 4.101 99.248 4.251 99.13 4.38 c
+99.013 4.505 98.859 4.571 98.674 4.571 c
+98.476 4.571 98.325 4.516 98.219 4.409 c
+98.109 4.31 98.057 4.178 98.057 4.012 c
+98.057 3.884 98.094 3.777 98.175 3.69 c
+98.252 3.609 98.443 3.505 98.748 3.38 c
+99.225 3.193 99.557 3.006 99.733 2.822 c
+99.909 2.645 99.998 2.418 99.998 2.146 c
+99.998 1.793 99.873 1.514 99.63 1.308 c
+99.395 1.103 99.079 0.999 98.689 0.999 c
+98.267 0.999 97.928 1.117 97.675 1.352 c
+97.417 1.595 97.293 1.899 97.293 2.263 c
+97.939 2.263 l
+97.947 2.036 98.017 1.859 98.145 1.734 c
+98.271 1.616 98.454 1.558 98.689 1.558 c
+98.903 1.558 99.064 1.606 99.175 1.705 c
+99.292 1.801 99.351 1.929 99.351 2.087 c
+100.879 1.425 m
+100.879 1.543 100.912 1.639 100.983 1.72 c
+101.049 1.797 101.151 1.837 101.291 1.837 c
+101.438 1.837 101.544 1.797 101.614 1.72 c
+101.691 1.639 101.732 1.543 101.732 1.425 c
+101.732 1.315 101.691 1.223 101.614 1.146 c
+101.544 1.069 101.438 1.028 101.291 1.028 c
+101.151 1.028 101.049 1.069 100.983 1.146 c
+100.912 1.223 100.879 1.315 100.879 1.425 c
+f
+Q
+0.113 0.082 0.09 0 k
+35.668 250.33 238.665 -12.895 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 40.8563 243.4906 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.69 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.772 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.279 -3.219 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.985 c
+-3.322 2.18 -3.289 2.344 -3.219 2.485 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.003 -2.469 3.043 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.485 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.459 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.36 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.485 -2.19 2.455 c
+-2.26 2.425 -2.319 2.385 -2.366 2.338 c
+-2.406 2.297 -2.437 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.066 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.44 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.302 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.014 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.147 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.411 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.772 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.632 5.137 1.779 c
+5.245 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.152 2.22 c
+8.004 2.22 l
+7.993 2.139 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.871 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.403 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.279 5.835 1.162 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.559 c
+6.725 -0.521 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.302 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.22 l
+13.644 2.22 l
+13.924 3.117 l
+14.497 3.117 l
+14.497 2.22 l
+15.732 2.22 l
+15.732 1.602 l
+14.497 1.602 l
+14.497 -0.103 l
+14.497 -0.324 l
+14.504 -0.393 14.527 -0.455 14.556 -0.515 c
+14.593 -0.565 14.648 -0.61 14.718 -0.646 c
+14.795 -0.676 14.909 -0.69 15.056 -0.69 c
+15.192 -0.69 15.327 -0.687 15.468 -0.676 c
+15.603 -0.658 15.736 -0.632 15.865 -0.602 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.23 15.629 -1.249 c
+15.549 -1.261 15.471 -1.267 15.394 -1.278 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.041 -1.301 14.942 -1.308 14.835 -1.308 c
+14.648 -1.308 14.486 -1.294 14.35 -1.264 c
+14.221 -1.227 14.107 -1.183 14.012 -1.132 c
+13.924 -1.084 13.85 -1.025 13.791 -0.955 c
+13.733 -0.878 13.689 -0.801 13.66 -0.72 c
+13.63 -0.632 13.608 -0.544 13.6 -0.455 c
+13.59 -0.36 13.586 -0.264 13.586 -0.176 c
+h
+22.765 1.602 m
+22.765 -1.264 l
+21.868 -1.264 l
+21.868 1.602 l
+21.045 1.602 l
+21.045 2.22 l
+21.868 2.22 l
+21.868 2.485 l
+21.868 2.61 21.883 2.741 21.913 2.882 c
+21.949 3.017 22.02 3.135 22.119 3.234 c
+22.225 3.341 22.369 3.429 22.545 3.499 c
+22.722 3.564 22.946 3.601 23.221 3.601 c
+23.434 3.601 23.632 3.591 23.809 3.572 c
+23.985 3.55 24.137 3.532 24.264 3.514 c
+24.264 2.926 l
+24.137 2.944 23.993 2.959 23.838 2.969 c
+23.68 2.977 23.53 2.984 23.383 2.984 c
+23.254 2.984 23.152 2.969 23.074 2.94 c
+22.994 2.911 22.931 2.87 22.883 2.822 c
+22.832 2.771 22.799 2.708 22.78 2.631 c
+22.769 2.562 22.765 2.485 22.765 2.396 c
+22.765 2.22 l
+24.191 2.22 l
+24.191 1.602 l
+h
+26.738 -1.323 m
+26.481 -1.323 26.253 -1.286 26.047 -1.22 c
+25.841 -1.143 25.665 -1.029 25.518 -0.881 c
+25.371 -0.727 25.253 -0.536 25.165 -0.309 c
+25.084 -0.085 25.047 0.181 25.047 0.485 c
+25.047 0.816 25.091 1.095 25.18 1.323 c
+25.275 1.558 25.404 1.742 25.562 1.881 c
+25.727 2.018 25.915 2.117 26.121 2.176 c
+26.327 2.242 26.535 2.278 26.753 2.278 c
+27.025 2.278 27.26 2.227 27.458 2.132 c
+27.664 2.043 27.829 1.911 27.958 1.735 c
+28.094 1.565 28.193 1.36 28.252 1.118 c
+28.318 0.882 28.355 0.617 28.355 0.324 c
+28.355 0.309 l
+25.988 0.309 l
+25.988 0.162 26.003 0.023 26.032 -0.103 c
+26.069 -0.231 26.124 -0.345 26.194 -0.441 c
+26.26 -0.529 26.344 -0.598 26.444 -0.646 c
+26.539 -0.698 26.653 -0.72 26.782 -0.72 c
+26.936 -0.72 27.076 -0.687 27.194 -0.617 c
+27.318 -0.551 27.407 -0.448 27.458 -0.309 c
+28.296 -0.382 l
+28.266 -0.481 28.212 -0.588 28.135 -0.706 c
+28.054 -0.816 27.95 -0.918 27.825 -1.014 c
+27.708 -1.103 27.553 -1.176 27.37 -1.234 c
+27.194 -1.294 26.98 -1.323 26.738 -1.323 c
+26.738 1.706 m
+26.649 1.706 26.562 1.691 26.473 1.661 c
+26.385 1.632 26.304 1.58 26.238 1.515 c
+26.169 1.444 26.109 1.357 26.061 1.249 c
+26.021 1.139 26.003 1.014 26.003 0.867 c
+27.472 0.867 l
+27.472 1.004 27.447 1.125 27.399 1.235 c
+27.359 1.341 27.304 1.43 27.237 1.5 c
+27.179 1.565 27.106 1.617 27.017 1.646 c
+26.929 1.683 26.834 1.706 26.738 1.706 c
+29.843 1.602 m
+29.299 1.602 l
+29.299 2.22 l
+29.887 2.22 l
+30.167 3.117 l
+30.74 3.117 l
+30.74 2.22 l
+31.975 2.22 l
+31.975 1.602 l
+30.74 1.602 l
+30.74 -0.103 l
+30.74 -0.324 l
+30.747 -0.393 30.769 -0.455 30.799 -0.515 c
+30.836 -0.565 30.89 -0.61 30.96 -0.646 c
+31.037 -0.676 31.152 -0.69 31.298 -0.69 c
+31.434 -0.69 31.57 -0.687 31.71 -0.676 c
+31.846 -0.658 31.978 -0.632 32.106 -0.602 c
+32.106 -1.205 l
+32.026 -1.216 31.948 -1.23 31.871 -1.249 c
+31.79 -1.261 31.713 -1.267 31.636 -1.278 c
+31.555 -1.286 31.467 -1.294 31.372 -1.294 c
+31.283 -1.301 31.185 -1.308 31.077 -1.308 c
+30.89 -1.308 30.728 -1.294 30.593 -1.264 c
+30.464 -1.227 30.35 -1.183 30.254 -1.132 c
+30.167 -1.084 30.093 -1.025 30.034 -0.955 c
+29.976 -0.878 29.932 -0.801 29.901 -0.72 c
+29.872 -0.632 29.851 -0.544 29.843 -0.455 c
+29.832 -0.36 29.828 -0.264 29.828 -0.176 c
+h
+34.863 -1.323 m
+34.576 -1.323 34.333 -1.282 34.128 -1.205 c
+33.922 -1.117 33.749 -0.995 33.614 -0.837 c
+33.473 -0.683 33.371 -0.496 33.305 -0.279 c
+33.234 -0.055 33.202 0.191 33.202 0.456 c
+33.202 0.75 33.234 1.008 33.305 1.235 c
+33.382 1.459 33.488 1.646 33.628 1.793 c
+33.775 1.948 33.951 2.066 34.157 2.146 c
+34.363 2.234 34.599 2.278 34.863 2.278 c
+35.087 2.278 35.289 2.249 35.465 2.19 c
+35.642 2.132 35.792 2.047 35.921 1.941 c
+36.046 1.841 36.149 1.72 36.23 1.573 c
+36.307 1.434 36.362 1.283 36.392 1.118 c
+35.48 1.073 l
+35.451 1.249 35.381 1.389 35.274 1.5 c
+35.175 1.606 35.032 1.661 34.848 1.661 c
+34.602 1.661 34.425 1.558 34.319 1.353 c
+34.209 1.154 34.157 0.867 34.157 0.485 c
+34.157 -0.309 34.392 -0.706 34.863 -0.706 c
+35.028 -0.706 35.171 -0.654 35.289 -0.544 c
+35.407 -0.437 35.48 -0.276 35.509 -0.058 c
+36.421 -0.103 l
+36.392 -0.272 36.336 -0.426 36.259 -0.573 c
+36.189 -0.72 36.087 -0.852 35.95 -0.97 c
+35.821 -1.08 35.663 -1.168 35.48 -1.234 c
+35.304 -1.294 35.098 -1.323 34.863 -1.323 c
+38.262 1.515 m
+38.379 1.786 38.53 1.985 38.718 2.103 c
+38.901 2.22 39.122 2.278 39.379 2.278 c
+39.584 2.278 39.754 2.242 39.894 2.176 c
+40.041 2.106 40.151 2.014 40.232 1.897 c
+40.32 1.779 40.378 1.636 40.408 1.47 c
+40.444 1.301 40.467 1.125 40.467 0.941 c
+40.467 -1.264 l
+39.555 -1.264 l
+39.555 0.735 l
+39.555 0.871 39.544 0.992 39.526 1.103 c
+39.515 1.209 39.489 1.297 39.453 1.367 c
+39.412 1.444 39.353 1.503 39.276 1.544 c
+39.206 1.58 39.114 1.602 38.996 1.602 c
+38.886 1.602 38.791 1.577 38.703 1.529 c
+38.615 1.478 38.534 1.411 38.468 1.323 c
+38.409 1.235 38.358 1.125 38.321 1 c
+38.291 0.882 38.277 0.75 38.277 0.603 c
+38.277 -1.264 l
+37.365 -1.264 l
+37.365 3.514 l
+38.277 3.514 l
+38.277 2.205 l
+38.277 2.135 38.269 2.066 38.262 1.999 c
+38.262 1.793 l
+38.262 1.735 38.254 1.679 38.248 1.632 c
+38.248 1.515 l
+h
+46.075 0.838 1.866 -0.794 re
+46.075 0.044 m
+50.135 0.838 1.867 -0.794 re
+50.135 0.044 m
+54.478 2.22 m
+54.486 2.198 54.493 2.165 54.493 2.117 c
+54.501 2.076 54.508 2.028 54.508 1.97 c
+54.515 1.918 54.522 1.867 54.522 1.808 c
+54.522 1.646 l
+54.537 1.646 l
+54.596 1.764 54.663 1.86 54.743 1.941 c
+54.821 2.018 54.905 2.08 54.993 2.132 c
+55.081 2.19 55.17 2.227 55.258 2.249 c
+55.353 2.267 55.453 2.278 55.552 2.278 c
+55.758 2.278 55.937 2.234 56.095 2.146 c
+56.25 2.058 56.379 1.929 56.477 1.764 c
+56.585 1.606 56.662 1.415 56.712 1.191 c
+56.772 0.974 56.801 0.738 56.801 0.485 c
+56.801 0.221 56.772 -0.025 56.712 -0.249 c
+56.662 -0.467 56.585 -0.658 56.477 -0.823 c
+56.379 -0.981 56.246 -1.103 56.081 -1.19 c
+55.923 -1.278 55.735 -1.323 55.522 -1.323 c
+55.423 -1.323 55.324 -1.311 55.228 -1.294 c
+55.129 -1.271 55.037 -1.242 54.949 -1.19 c
+54.869 -1.143 54.791 -1.08 54.713 -0.999 c
+54.644 -0.922 54.585 -0.831 54.537 -0.72 c
+54.522 -0.72 l
+54.522 -0.808 l
+54.53 -0.849 54.537 -0.897 54.537 -0.955 c
+54.537 -1.117 l
+54.537 -1.294 l
+54.537 -2.631 l
+53.626 -2.631 l
+53.626 1.455 l
+53.626 1.621 53.618 1.768 53.612 1.897 c
+53.612 2.22 l
+h
+54.522 0.456 m
+54.522 0.228 54.541 0.037 54.582 -0.118 c
+54.63 -0.264 54.684 -0.382 54.743 -0.47 c
+54.809 -0.559 54.883 -0.625 54.964 -0.661 c
+55.041 -0.702 55.118 -0.72 55.199 -0.72 c
+55.295 -0.72 55.382 -0.698 55.463 -0.646 c
+55.552 -0.598 55.617 -0.529 55.669 -0.441 c
+55.728 -0.345 55.772 -0.22 55.802 -0.073 c
+55.839 0.081 55.86 0.268 55.86 0.485 c
+55.86 0.875 55.802 1.168 55.684 1.367 c
+55.574 1.562 55.419 1.661 55.214 1.661 c
+55.133 1.661 55.056 1.639 54.979 1.602 c
+54.898 1.562 54.824 1.5 54.758 1.411 c
+54.688 1.323 54.63 1.199 54.582 1.044 c
+54.541 0.886 54.522 0.691 54.522 0.456 c
+60.685 1.47 m
+60.586 1.478 60.483 1.488 60.377 1.5 c
+60.267 1.518 60.145 1.529 60.009 1.529 c
+59.833 1.529 59.675 1.488 59.538 1.411 c
+59.399 1.341 59.282 1.243 59.186 1.118 c
+59.098 0.989 59.028 0.842 58.981 0.676 c
+58.94 0.507 58.921 0.331 58.921 0.147 c
+58.921 -1.264 l
+58.025 -1.264 l
+58.025 0.985 l
+58.025 1.11 58.014 1.235 57.996 1.353 c
+57.984 1.478 57.969 1.596 57.951 1.706 c
+57.94 1.823 57.926 1.918 57.907 1.999 c
+57.886 2.088 57.867 2.161 57.848 2.22 c
+58.73 2.22 l
+58.738 2.168 58.748 2.117 58.76 2.058 c
+58.778 1.999 58.792 1.933 58.804 1.867 c
+58.823 1.808 58.837 1.742 58.848 1.675 c
+58.855 1.606 58.867 1.544 58.877 1.484 c
+58.892 1.484 l
+58.929 1.602 58.981 1.709 59.039 1.808 c
+59.105 1.904 59.186 1.989 59.274 2.058 c
+59.363 2.124 59.465 2.18 59.583 2.22 c
+59.708 2.257 59.855 2.278 60.024 2.278 c
+60.149 2.278 60.267 2.271 60.377 2.263 c
+60.494 2.253 60.597 2.238 60.685 2.22 c
+h
+62.615 2.22 m
+62.615 0.264 l
+62.615 0.125 62.622 0 62.644 -0.118 c
+62.663 -0.228 62.696 -0.32 62.746 -0.397 c
+62.794 -0.478 62.854 -0.54 62.923 -0.588 c
+62.989 -0.628 63.074 -0.646 63.173 -0.646 c
+63.261 -0.646 63.342 -0.628 63.423 -0.588 c
+63.511 -0.54 63.585 -0.47 63.644 -0.382 c
+63.702 -0.286 63.746 -0.176 63.776 -0.058 c
+63.812 0.067 63.835 0.206 63.835 0.353 c
+63.835 2.22 l
+64.731 2.22 l
+64.731 -0.484 l
+64.731 -0.72 l
+64.739 -0.801 64.746 -0.878 64.746 -0.955 c
+64.746 -1.147 l
+64.753 -1.198 64.76 -1.234 64.76 -1.264 c
+63.908 -1.264 l
+63.897 -1.234 63.886 -1.198 63.879 -1.147 c
+63.879 -0.955 l
+63.879 -0.889 63.872 -0.819 63.864 -0.75 c
+63.864 -0.573 l
+63.849 -0.573 l
+63.731 -0.837 63.577 -1.029 63.394 -1.147 c
+63.217 -1.264 63.015 -1.323 62.791 -1.323 c
+62.586 -1.323 62.412 -1.286 62.276 -1.22 c
+62.137 -1.153 62.027 -1.058 61.938 -0.941 c
+61.857 -0.823 61.799 -0.687 61.762 -0.529 c
+61.732 -0.363 61.718 -0.187 61.718 0 c
+61.718 2.22 l
+h
+67.983 -1.264 m
+67.983 0.721 l
+67.983 1.022 67.939 1.243 67.851 1.382 c
+67.77 1.529 67.634 1.602 67.44 1.602 c
+67.33 1.602 67.226 1.577 67.131 1.529 c
+67.043 1.478 66.962 1.411 66.896 1.323 c
+66.837 1.235 66.785 1.125 66.748 1 c
+66.719 0.882 66.705 0.75 66.705 0.603 c
+66.705 -1.264 l
+65.793 -1.264 l
+65.793 1.44 l
+65.793 1.661 l
+65.793 1.75 65.786 1.827 65.778 1.897 c
+65.778 2.088 l
+65.778 2.22 l
+66.631 2.22 l
+66.638 2.19 66.646 2.146 66.646 2.088 c
+66.646 1.897 l
+66.653 1.827 66.661 1.756 66.661 1.691 c
+66.667 1.621 66.675 1.565 66.675 1.529 c
+66.69 1.529 l
+66.808 1.793 66.958 1.985 67.145 2.103 c
+67.33 2.22 67.55 2.278 67.807 2.278 c
+67.991 2.278 68.153 2.249 68.292 2.19 c
+68.428 2.132 68.542 2.043 68.63 1.926 c
+68.718 1.808 68.781 1.665 68.822 1.5 c
+68.869 1.341 68.895 1.154 68.895 0.941 c
+68.895 -1.264 l
+h
+71.412 -1.323 m
+71.155 -1.323 70.927 -1.286 70.721 -1.22 c
+70.515 -1.143 70.339 -1.029 70.192 -0.881 c
+70.045 -0.727 69.927 -0.536 69.84 -0.309 c
+69.759 -0.085 69.722 0.181 69.722 0.485 c
+69.722 0.816 69.765 1.095 69.854 1.323 c
+69.95 1.558 70.078 1.742 70.236 1.881 c
+70.401 2.018 70.588 2.117 70.794 2.176 c
+71 2.242 71.21 2.278 71.427 2.278 c
+71.698 2.278 71.934 2.227 72.132 2.132 c
+72.338 2.043 72.504 1.911 72.632 1.735 c
+72.768 1.565 72.867 1.36 72.926 1.118 c
+72.992 0.882 73.029 0.617 73.029 0.324 c
+73.029 0.309 l
+70.663 0.309 l
+70.663 0.162 70.677 0.023 70.706 -0.103 c
+70.743 -0.231 70.798 -0.345 70.868 -0.441 c
+70.935 -0.529 71.018 -0.598 71.118 -0.646 c
+71.213 -0.698 71.328 -0.72 71.456 -0.72 c
+71.61 -0.72 71.75 -0.687 71.868 -0.617 c
+71.993 -0.551 72.08 -0.448 72.132 -0.309 c
+72.97 -0.382 l
+72.94 -0.481 72.886 -0.588 72.809 -0.706 c
+72.728 -0.816 72.624 -0.918 72.5 -1.014 c
+72.382 -1.103 72.228 -1.176 72.044 -1.234 c
+71.868 -1.294 71.654 -1.323 71.412 -1.323 c
+71.412 1.706 m
+71.324 1.706 71.236 1.691 71.147 1.661 c
+71.059 1.632 70.978 1.58 70.912 1.515 c
+70.842 1.444 70.783 1.357 70.736 1.249 c
+70.696 1.139 70.677 1.014 70.677 0.867 c
+72.147 0.867 l
+72.147 1.004 72.121 1.125 72.074 1.235 c
+72.033 1.341 71.978 1.43 71.912 1.5 c
+71.853 1.565 71.779 1.617 71.691 1.646 c
+71.603 1.683 71.507 1.706 71.412 1.706 c
+78.729 -2.631 m
+78.729 3.514 l
+80.654 3.514 l
+80.654 2.896 l
+79.581 2.896 l
+79.581 -2.013 l
+80.654 -2.013 l
+80.654 -2.631 l
+h
+85.052 1.47 m
+84.953 1.478 84.851 1.488 84.744 1.5 c
+84.634 1.518 84.512 1.529 84.377 1.529 c
+84.2 1.529 84.042 1.488 83.906 1.411 c
+83.766 1.341 83.649 1.243 83.554 1.118 c
+83.465 0.989 83.396 0.842 83.348 0.676 c
+83.307 0.507 83.288 0.331 83.288 0.147 c
+83.288 -1.264 l
+82.392 -1.264 l
+82.392 0.985 l
+82.392 1.11 82.381 1.235 82.363 1.353 c
+82.351 1.478 82.337 1.596 82.318 1.706 c
+82.307 1.823 82.293 1.918 82.274 1.999 c
+82.253 2.088 82.234 2.161 82.216 2.22 c
+83.097 2.22 l
+83.105 2.168 83.116 2.117 83.127 2.058 c
+83.145 1.999 83.16 1.933 83.171 1.867 c
+83.19 1.808 83.205 1.742 83.215 1.675 c
+83.223 1.606 83.234 1.544 83.245 1.484 c
+83.259 1.484 l
+83.296 1.602 83.348 1.709 83.406 1.808 c
+83.473 1.904 83.554 1.989 83.641 2.058 c
+83.73 2.124 83.833 2.18 83.951 2.22 c
+84.075 2.257 84.223 2.278 84.391 2.278 c
+84.516 2.278 84.634 2.271 84.744 2.263 c
+84.861 2.253 84.965 2.238 85.052 2.22 c
+h
+87.658 -1.323 m
+87.401 -1.323 87.173 -1.286 86.968 -1.22 c
+86.762 -1.143 86.585 -1.029 86.438 -0.881 c
+86.291 -0.727 86.174 -0.536 86.085 -0.309 c
+86.004 -0.085 85.968 0.181 85.968 0.485 c
+85.968 0.816 86.012 1.095 86.1 1.323 c
+86.195 1.558 86.324 1.742 86.482 1.881 c
+86.648 2.018 86.835 2.117 87.041 2.176 c
+87.246 2.242 87.456 2.278 87.673 2.278 c
+87.945 2.278 88.18 2.227 88.379 2.132 c
+88.584 2.043 88.749 1.911 88.878 1.735 c
+89.014 1.565 89.113 1.36 89.172 1.118 c
+89.239 0.882 89.275 0.617 89.275 0.324 c
+89.275 0.309 l
+86.908 0.309 l
+86.908 0.162 86.923 0.023 86.953 -0.103 c
+86.989 -0.231 87.045 -0.345 87.114 -0.441 c
+87.18 -0.529 87.265 -0.598 87.364 -0.646 c
+87.46 -0.698 87.573 -0.72 87.702 -0.72 c
+87.857 -0.72 87.996 -0.687 88.113 -0.617 c
+88.239 -0.551 88.327 -0.448 88.379 -0.309 c
+89.216 -0.382 l
+89.187 -0.481 89.131 -0.588 89.054 -0.706 c
+88.973 -0.816 88.871 -0.918 88.746 -1.014 c
+88.628 -1.103 88.474 -1.176 88.29 -1.234 c
+88.113 -1.294 87.901 -1.323 87.658 -1.323 c
+87.658 1.706 m
+87.57 1.706 87.481 1.691 87.394 1.661 c
+87.305 1.632 87.224 1.58 87.159 1.515 c
+87.089 1.444 87.03 1.357 86.982 1.249 c
+86.941 1.139 86.923 1.014 86.923 0.867 c
+88.393 0.867 l
+88.393 1.004 88.367 1.125 88.319 1.235 c
+88.279 1.341 88.224 1.43 88.158 1.5 c
+88.099 1.565 88.026 1.617 87.937 1.646 c
+87.849 1.683 87.754 1.706 87.658 1.706 c
+91.322 -1.264 m
+91.322 0.852 l
+91.322 1.018 91.315 1.154 91.307 1.264 c
+91.296 1.371 91.278 1.455 91.248 1.515 c
+91.226 1.58 91.197 1.632 91.16 1.661 c
+91.13 1.691 91.09 1.706 91.043 1.706 c
+90.984 1.706 90.929 1.675 90.881 1.617 c
+90.841 1.565 90.808 1.492 90.778 1.397 c
+90.748 1.309 90.723 1.195 90.704 1.058 c
+90.694 0.919 90.69 0.769 90.69 0.603 c
+90.69 -1.264 l
+89.94 -1.264 l
+89.94 1.47 l
+89.94 1.706 l
+89.94 1.926 l
+89.94 2.003 89.933 2.066 89.925 2.117 c
+89.925 2.22 l
+90.602 2.22 l
+90.602 2.132 l
+90.602 1.985 l
+90.609 1.926 90.617 1.867 90.617 1.808 c
+90.617 1.646 l
+90.631 1.646 l
+90.65 1.735 90.679 1.812 90.719 1.881 c
+90.756 1.959 90.8 2.028 90.852 2.088 c
+90.91 2.146 90.976 2.19 91.057 2.22 c
+91.134 2.257 91.223 2.278 91.322 2.278 c
+91.506 2.278 91.645 2.224 91.733 2.117 c
+91.829 2.018 91.899 1.86 91.939 1.646 c
+91.954 1.646 l
+91.99 1.742 92.031 1.831 92.071 1.911 c
+92.119 1.989 92.175 2.051 92.233 2.103 c
+92.292 2.161 92.358 2.205 92.439 2.234 c
+92.516 2.263 92.604 2.278 92.703 2.278 c
+92.84 2.278 92.954 2.253 93.042 2.205 c
+93.129 2.153 93.196 2.08 93.247 1.985 c
+93.306 1.885 93.343 1.756 93.365 1.602 c
+93.395 1.455 93.409 1.272 93.409 1.058 c
+93.409 -1.264 l
+92.689 -1.264 l
+92.689 0.852 l
+92.689 1.018 92.682 1.154 92.674 1.264 c
+92.663 1.371 92.645 1.455 92.615 1.515 c
+92.593 1.58 92.564 1.632 92.527 1.661 c
+92.498 1.691 92.458 1.706 92.41 1.706 c
+92.292 1.706 92.196 1.617 92.13 1.44 c
+92.071 1.272 92.042 1.014 92.042 0.661 c
+92.042 -1.264 l
+h
+97.43 0.485 m
+97.43 0.21 97.393 -0.04 97.326 -0.264 c
+97.256 -0.481 97.154 -0.669 97.018 -0.823 c
+96.878 -0.981 96.701 -1.103 96.489 -1.19 c
+96.271 -1.278 96.018 -1.323 95.724 -1.323 c
+95.448 -1.323 95.202 -1.278 94.989 -1.19 c
+94.783 -1.103 94.611 -0.981 94.475 -0.823 c
+94.335 -0.669 94.232 -0.481 94.166 -0.264 c
+94.096 -0.04 94.064 0.21 94.064 0.485 c
+94.064 0.738 94.093 0.974 94.151 1.191 c
+94.218 1.415 94.32 1.606 94.46 1.764 c
+94.596 1.929 94.772 2.058 94.989 2.146 c
+95.202 2.234 95.46 2.278 95.753 2.278 c
+96.065 2.278 96.327 2.234 96.533 2.146 c
+96.746 2.058 96.919 1.929 97.047 1.764 c
+97.183 1.606 97.282 1.415 97.341 1.191 c
+97.399 0.974 97.43 0.738 97.43 0.485 c
+96.474 0.485 m
+96.474 0.691 96.459 0.867 96.43 1.014 c
+96.408 1.162 96.371 1.283 96.312 1.382 c
+96.254 1.478 96.18 1.548 96.092 1.588 c
+96.003 1.636 95.893 1.661 95.768 1.661 c
+95.504 1.661 95.313 1.562 95.195 1.367 c
+95.078 1.18 95.018 0.886 95.018 0.485 c
+95.018 0.063 95.078 -0.243 95.195 -0.426 c
+95.313 -0.613 95.489 -0.706 95.724 -0.706 c
+95.849 -0.706 95.963 -0.687 96.063 -0.646 c
+96.158 -0.598 96.239 -0.525 96.298 -0.426 c
+96.364 -0.33 96.408 -0.206 96.43 -0.058 c
+96.459 0.088 96.474 0.268 96.474 0.485 c
+98.888 1.602 m
+98.344 1.602 l
+98.344 2.22 l
+98.932 2.22 l
+99.211 3.117 l
+99.785 3.117 l
+99.785 2.22 l
+101.019 2.22 l
+101.019 1.602 l
+99.785 1.602 l
+99.785 -0.103 l
+99.785 -0.324 l
+99.792 -0.393 99.814 -0.455 99.843 -0.515 c
+99.88 -0.565 99.936 -0.61 100.005 -0.646 c
+100.082 -0.676 100.196 -0.69 100.343 -0.69 c
+100.479 -0.69 100.615 -0.687 100.755 -0.676 c
+100.891 -0.658 101.023 -0.632 101.152 -0.602 c
+101.152 -1.205 l
+101.071 -1.216 100.994 -1.23 100.917 -1.249 c
+100.836 -1.261 100.759 -1.267 100.682 -1.278 c
+100.601 -1.286 100.512 -1.294 100.416 -1.294 c
+100.329 -1.301 100.229 -1.308 100.123 -1.308 c
+99.936 -1.308 99.774 -1.294 99.637 -1.264 c
+99.51 -1.227 99.396 -1.183 99.3 -1.132 c
+99.211 -1.084 99.138 -1.025 99.08 -0.955 c
+99.02 -0.878 98.976 -0.801 98.947 -0.72 c
+98.918 -0.632 98.895 -0.544 98.888 -0.455 c
+98.877 -0.36 98.874 -0.264 98.874 -0.176 c
+h
+103.904 -1.323 m
+103.647 -1.323 103.419 -1.286 103.213 -1.22 c
+103.007 -1.143 102.831 -1.029 102.685 -0.881 c
+102.537 -0.727 102.419 -0.536 102.332 -0.309 c
+102.251 -0.085 102.214 0.181 102.214 0.485 c
+102.214 0.816 102.257 1.095 102.346 1.323 c
+102.442 1.558 102.571 1.742 102.728 1.881 c
+102.893 2.018 103.082 2.117 103.287 2.176 c
+103.493 2.242 103.702 2.278 103.919 2.278 c
+104.191 2.278 104.426 2.227 104.624 2.132 c
+104.83 2.043 104.996 1.911 105.124 1.735 c
+105.26 1.565 105.359 1.36 105.418 1.118 c
+105.484 0.882 105.521 0.617 105.521 0.324 c
+105.521 0.309 l
+103.155 0.309 l
+103.155 0.162 103.169 0.023 103.198 -0.103 c
+103.236 -0.231 103.29 -0.345 103.36 -0.441 c
+103.427 -0.529 103.511 -0.598 103.61 -0.646 c
+103.706 -0.698 103.82 -0.72 103.948 -0.72 c
+104.102 -0.72 104.242 -0.687 104.36 -0.617 c
+104.485 -0.551 104.573 -0.448 104.624 -0.309 c
+105.463 -0.382 l
+105.433 -0.481 105.378 -0.588 105.301 -0.706 c
+105.22 -0.816 105.117 -0.918 104.992 -1.014 c
+104.875 -1.103 104.72 -1.176 104.536 -1.234 c
+104.36 -1.294 104.146 -1.323 103.904 -1.323 c
+103.904 1.706 m
+103.816 1.706 103.728 1.691 103.639 1.661 c
+103.552 1.632 103.471 1.58 103.404 1.515 c
+103.335 1.444 103.276 1.357 103.228 1.249 c
+103.188 1.139 103.169 1.014 103.169 0.867 c
+104.639 0.867 l
+104.639 1.004 104.613 1.125 104.566 1.235 c
+104.526 1.341 104.47 1.43 104.404 1.5 c
+104.345 1.565 104.272 1.617 104.183 1.646 c
+104.096 1.683 104 1.706 103.904 1.706 c
+106.774 -2.631 m
+106.774 -2.013 l
+107.847 -2.013 l
+107.847 2.896 l
+106.774 2.896 l
+106.774 3.514 l
+108.7 3.514 l
+108.7 -2.631 l
+h
+f
+Q
+q 1 0 0 1 70.6476 229.5009 cm
+0 0 m
+-0.941 0 l
+-0.941 -2.161 l
+-1.617 -2.161 l
+-1.617 3.19 l
+-0.118 3.19 l
+0.412 3.19 0.809 3.05 1.073 2.778 c
+1.345 2.502 1.484 2.105 1.484 1.588 c
+1.484 1.253 1.411 0.963 1.264 0.721 c
+1.118 0.474 0.912 0.287 0.647 0.162 c
+1.675 -2.117 l
+1.675 -2.161 l
+0.956 -2.161 l
+h
+-0.941 0.588 m
+-0.118 0.588 l
+0.166 0.588 0.389 0.676 0.559 0.852 c
+0.724 1.037 0.809 1.282 0.809 1.588 c
+0.809 2.271 0.493 2.616 -0.132 2.616 c
+-0.941 2.616 l
+h
+3.719 -2.234 m
+3.219 -2.234 2.837 -2.087 2.573 -1.793 c
+2.308 -1.5 2.176 -1.066 2.176 -0.484 c
+2.176 -0.014 l
+2.176 0.58 2.301 1.047 2.558 1.382 c
+2.822 1.723 3.183 1.897 3.645 1.897 c
+4.105 1.897 4.447 1.742 4.675 1.44 c
+4.91 1.147 5.031 0.684 5.042 0.059 c
+5.042 -0.367 l
+2.822 -0.367 l
+2.822 -0.455 l
+2.822 -0.889 2.899 -1.201 3.057 -1.396 c
+3.223 -1.583 3.454 -1.675 3.749 -1.675 c
+3.944 -1.675 4.116 -1.643 4.262 -1.573 c
+4.41 -1.496 4.546 -1.378 4.675 -1.22 c
+5.012 -1.631 l
+4.726 -2.036 4.296 -2.234 3.719 -2.234 c
+3.645 1.338 m
+3.37 1.338 3.167 1.242 3.043 1.058 c
+2.914 0.871 2.841 0.58 2.822 0.191 c
+4.395 0.191 l
+4.395 0.279 l
+4.373 0.661 4.307 0.929 4.189 1.087 c
+4.072 1.253 3.888 1.338 3.645 1.338 c
+6.438 1.823 m
+6.453 1.455 l
+6.695 1.75 7.015 1.897 7.408 1.897 c
+7.85 1.897 8.158 1.698 8.335 1.309 c
+8.588 1.698 8.937 1.897 9.378 1.897 c
+10.113 1.897 10.488 1.434 10.51 0.515 c
+10.51 -2.161 l
+9.864 -2.161 l
+9.864 0.456 l
+9.864 0.75 9.808 0.963 9.702 1.103 c
+9.602 1.239 9.43 1.309 9.187 1.309 c
+8.989 1.309 8.827 1.228 8.702 1.073 c
+8.584 0.927 8.515 0.735 8.496 0.5 c
+8.496 -2.161 l
+7.834 -2.161 l
+7.834 0.485 l
+7.834 1.033 7.614 1.309 7.173 1.309 c
+6.839 1.309 6.604 1.147 6.468 0.823 c
+6.468 -2.161 l
+5.821 -2.161 l
+5.821 1.823 l
+h
+11.348 0.015 m
+11.348 0.592 11.484 1.047 11.759 1.382 c
+12.042 1.723 12.414 1.897 12.877 1.897 c
+13.336 1.897 13.704 1.727 13.979 1.397 c
+14.262 1.073 14.409 0.625 14.42 0.059 c
+14.42 -0.367 l
+14.42 -0.937 14.277 -1.392 13.993 -1.735 c
+13.718 -2.069 13.351 -2.234 12.891 -2.234 c
+12.428 -2.234 12.057 -2.072 11.774 -1.749 c
+11.499 -1.419 11.356 -0.977 11.348 -0.426 c
+h
+11.994 -0.367 m
+11.994 -0.771 12.072 -1.087 12.23 -1.323 c
+12.395 -1.558 12.615 -1.675 12.891 -1.675 c
+13.457 -1.675 13.751 -1.264 13.773 -0.441 c
+13.773 0.015 l
+13.773 0.416 13.689 0.735 13.523 0.97 c
+13.365 1.213 13.149 1.338 12.877 1.338 c
+12.612 1.338 12.395 1.213 12.23 0.97 c
+12.072 0.735 11.994 0.416 11.994 0.015 c
+h
+16.331 -1.176 m
+17.081 1.823 l
+17.742 1.823 l
+16.566 -2.161 l
+16.081 -2.161 l
+14.89 1.823 l
+15.551 1.823 l
+h
+19.8 -2.234 m
+19.3 -2.234 18.918 -2.087 18.653 -1.793 c
+18.389 -1.5 18.257 -1.066 18.257 -0.484 c
+18.257 -0.014 l
+18.257 0.58 18.381 1.047 18.639 1.382 c
+18.903 1.723 19.264 1.897 19.726 1.897 c
+20.185 1.897 20.528 1.742 20.756 1.44 c
+20.991 1.147 21.112 0.684 21.122 0.059 c
+21.122 -0.367 l
+18.903 -0.367 l
+18.903 -0.455 l
+18.903 -0.889 18.98 -1.201 19.138 -1.396 c
+19.304 -1.583 19.535 -1.675 19.829 -1.675 c
+20.024 -1.675 20.197 -1.643 20.343 -1.573 c
+20.49 -1.496 20.627 -1.378 20.756 -1.22 c
+21.093 -1.631 l
+20.806 -2.036 20.376 -2.234 19.8 -2.234 c
+19.726 1.338 m
+19.451 1.338 19.248 1.242 19.123 1.058 c
+18.995 0.871 18.922 0.58 18.903 0.191 c
+20.476 0.191 l
+20.476 0.279 l
+20.454 0.661 20.388 0.929 20.27 1.087 c
+20.153 1.253 19.969 1.338 19.726 1.338 c
+25.268 1.205 m
+25.18 1.224 25.08 1.235 24.974 1.235 c
+24.64 1.235 24.405 1.051 24.268 0.691 c
+24.268 -2.161 l
+23.622 -2.161 l
+23.622 1.823 l
+24.253 1.823 l
+24.268 1.411 l
+24.445 1.735 24.687 1.897 25.003 1.897 c
+25.11 1.897 25.198 1.874 25.268 1.837 c
+h
+27.267 -2.234 m
+26.767 -2.234 26.385 -2.087 26.121 -1.793 c
+25.856 -1.5 25.724 -1.066 25.724 -0.484 c
+25.724 -0.014 l
+25.724 0.58 25.849 1.047 26.106 1.382 c
+26.37 1.723 26.73 1.897 27.194 1.897 c
+27.653 1.897 27.995 1.742 28.222 1.44 c
+28.457 1.147 28.579 0.684 28.59 0.059 c
+28.59 -0.367 l
+26.37 -0.367 l
+26.37 -0.455 l
+26.37 -0.889 26.448 -1.201 26.605 -1.396 c
+26.771 -1.583 27.002 -1.675 27.296 -1.675 c
+27.491 -1.675 27.664 -1.643 27.811 -1.573 c
+27.958 -1.496 28.094 -1.378 28.222 -1.22 c
+28.561 -1.631 l
+28.274 -2.036 27.844 -2.234 27.267 -2.234 c
+27.194 1.338 m
+26.918 1.338 26.716 1.242 26.591 1.058 c
+26.462 0.871 26.389 0.58 26.37 0.191 c
+27.943 0.191 l
+27.943 0.279 l
+27.921 0.661 27.855 0.929 27.738 1.087 c
+27.62 1.253 27.436 1.338 27.194 1.338 c
+29.986 1.823 m
+30.001 1.455 l
+30.244 1.75 30.564 1.897 30.957 1.897 c
+31.397 1.897 31.706 1.698 31.883 1.309 c
+32.136 1.698 32.485 1.897 32.926 1.897 c
+33.661 1.897 34.036 1.434 34.058 0.515 c
+34.058 -2.161 l
+33.411 -2.161 l
+33.411 0.456 l
+33.411 0.75 33.356 0.963 33.249 1.103 c
+33.151 1.239 32.978 1.309 32.735 1.309 c
+32.536 1.309 32.375 1.228 32.249 1.073 c
+32.133 0.927 32.062 0.735 32.044 0.5 c
+32.044 -2.161 l
+31.383 -2.161 l
+31.383 0.485 l
+31.383 1.033 31.162 1.309 30.722 1.309 c
+30.387 1.309 30.152 1.147 30.016 0.823 c
+30.016 -2.161 l
+29.369 -2.161 l
+29.369 1.823 l
+h
+34.896 0.015 m
+34.896 0.592 35.032 1.047 35.307 1.382 c
+35.59 1.723 35.962 1.897 36.424 1.897 c
+36.884 1.897 37.251 1.727 37.527 1.397 c
+37.81 1.073 37.957 0.625 37.968 0.059 c
+37.968 -0.367 l
+37.968 -0.937 37.824 -1.392 37.542 -1.735 c
+37.266 -2.069 36.899 -2.234 36.44 -2.234 c
+35.976 -2.234 35.605 -2.072 35.322 -1.749 c
+35.046 -1.419 34.903 -0.977 34.896 -0.426 c
+h
+35.542 -0.367 m
+35.542 -0.771 35.62 -1.087 35.777 -1.323 c
+35.943 -1.558 36.164 -1.675 36.44 -1.675 c
+37.005 -1.675 37.299 -1.264 37.321 -0.441 c
+37.321 0.015 l
+37.321 0.416 37.236 0.735 37.072 0.97 c
+36.914 1.213 36.696 1.338 36.424 1.338 c
+36.16 1.338 35.943 1.213 35.777 0.97 c
+35.62 0.735 35.542 0.416 35.542 0.015 c
+h
+39.659 2.778 m
+39.659 1.823 l
+40.261 1.823 l
+40.261 1.294 l
+39.659 1.294 l
+39.659 -1.176 l
+39.659 -1.334 39.68 -1.452 39.732 -1.529 c
+39.79 -1.61 39.879 -1.646 39.996 -1.646 c
+40.085 -1.646 40.172 -1.631 40.261 -1.602 c
+40.261 -2.161 l
+40.114 -2.209 39.96 -2.234 39.805 -2.234 c
+39.548 -2.234 39.353 -2.142 39.218 -1.955 c
+39.077 -1.771 39.012 -1.51 39.012 -1.176 c
+39.012 1.294 l
+38.409 1.294 l
+38.409 1.823 l
+39.012 1.823 l
+39.012 2.778 l
+h
+42.451 -2.234 m
+41.951 -2.234 41.569 -2.087 41.305 -1.793 c
+41.04 -1.5 40.908 -1.066 40.908 -0.484 c
+40.908 -0.014 l
+40.908 0.58 41.032 1.047 41.29 1.382 c
+41.554 1.723 41.915 1.897 42.377 1.897 c
+42.837 1.897 43.179 1.742 43.407 1.44 c
+43.642 1.147 43.763 0.684 43.774 0.059 c
+43.774 -0.367 l
+41.554 -0.367 l
+41.554 -0.455 l
+41.554 -0.889 41.631 -1.201 41.79 -1.396 c
+41.955 -1.583 42.187 -1.675 42.481 -1.675 c
+42.676 -1.675 42.848 -1.643 42.995 -1.573 c
+43.142 -1.496 43.278 -1.378 43.407 -1.22 c
+43.744 -1.631 l
+43.458 -2.036 43.028 -2.234 42.451 -2.234 c
+42.377 1.338 m
+42.102 1.338 41.9 1.242 41.775 1.058 c
+41.647 0.871 41.573 0.58 41.554 0.191 c
+43.127 0.191 l
+43.127 0.279 l
+43.106 0.661 43.039 0.929 42.921 1.087 c
+42.804 1.253 42.62 1.338 42.377 1.338 c
+47.919 1.205 m
+47.831 1.224 47.732 1.235 47.625 1.235 c
+47.291 1.235 47.056 1.051 46.919 0.691 c
+46.919 -2.161 l
+46.273 -2.161 l
+46.273 1.823 l
+46.905 1.823 l
+46.919 1.411 l
+47.096 1.735 47.339 1.897 47.655 1.897 c
+47.761 1.897 47.85 1.874 47.919 1.837 c
+h
+49.918 -2.234 m
+49.418 -2.234 49.036 -2.087 48.772 -1.793 c
+48.507 -1.5 48.375 -1.066 48.375 -0.484 c
+48.375 -0.014 l
+48.375 0.58 48.5 1.047 48.757 1.382 c
+49.022 1.723 49.381 1.897 49.845 1.897 c
+50.304 1.897 50.646 1.742 50.873 1.44 c
+51.108 1.147 51.23 0.684 51.241 0.059 c
+51.241 -0.367 l
+49.022 -0.367 l
+49.022 -0.455 l
+49.022 -0.889 49.099 -1.201 49.257 -1.396 c
+49.422 -1.583 49.653 -1.675 49.948 -1.675 c
+50.142 -1.675 50.315 -1.643 50.462 -1.573 c
+50.609 -1.496 50.745 -1.378 50.873 -1.22 c
+51.212 -1.631 l
+50.925 -2.036 50.495 -2.234 49.918 -2.234 c
+49.845 1.338 m
+49.569 1.338 49.367 1.242 49.242 1.058 c
+49.113 0.871 49.04 0.58 49.022 0.191 c
+50.594 0.191 l
+50.594 0.279 l
+50.572 0.661 50.506 0.929 50.389 1.087 c
+50.271 1.253 50.087 1.338 49.845 1.338 c
+52.315 -2.161 m
+52.315 1.294 l
+51.785 1.294 l
+51.785 1.823 l
+52.315 1.823 l
+52.315 2.278 l
+52.315 2.679 52.41 2.992 52.608 3.219 c
+52.814 3.443 53.093 3.557 53.446 3.557 c
+53.582 3.557 53.714 3.535 53.843 3.499 c
+53.813 2.955 l
+53.714 2.973 53.615 2.984 53.52 2.984 c
+53.144 2.984 52.961 2.72 52.961 2.19 c
+52.961 1.823 l
+53.637 1.823 l
+53.637 1.294 l
+52.961 1.294 l
+52.961 -2.161 l
+h
+56.342 -1.147 m
+56.342 -0.999 56.286 -0.878 56.18 -0.779 c
+56.07 -0.683 55.864 -0.565 55.563 -0.426 c
+55.218 -0.279 54.975 -0.158 54.827 -0.058 c
+54.68 0.048 54.57 0.166 54.505 0.294 c
+54.435 0.419 54.401 0.577 54.401 0.765 c
+54.401 1.087 54.519 1.357 54.754 1.573 c
+54.989 1.786 55.291 1.897 55.665 1.897 c
+56.047 1.897 56.357 1.783 56.592 1.558 c
+56.827 1.33 56.944 1.044 56.944 0.691 c
+56.298 0.691 l
+56.298 0.867 56.238 1.018 56.122 1.147 c
+56.003 1.272 55.849 1.338 55.665 1.338 c
+55.467 1.338 55.316 1.282 55.21 1.176 c
+55.1 1.077 55.048 0.945 55.048 0.779 c
+55.048 0.651 55.085 0.544 55.166 0.456 c
+55.243 0.375 55.434 0.272 55.739 0.147 c
+56.217 -0.04 56.548 -0.228 56.724 -0.411 c
+56.901 -0.588 56.988 -0.816 56.988 -1.087 c
+56.988 -1.44 56.864 -1.72 56.621 -1.926 c
+56.386 -2.131 56.07 -2.234 55.68 -2.234 c
+55.258 -2.234 54.919 -2.117 54.666 -1.881 c
+54.409 -1.639 54.283 -1.334 54.283 -0.97 c
+54.931 -0.97 l
+54.938 -1.198 55.008 -1.374 55.137 -1.5 c
+55.261 -1.617 55.445 -1.675 55.68 -1.675 c
+55.893 -1.675 56.055 -1.627 56.165 -1.529 c
+56.283 -1.433 56.342 -1.305 56.342 -1.147 c
+57.841 -3.233 m
+57.444 -2.969 l
+57.68 -2.645 57.801 -2.311 57.811 -1.97 c
+57.811 -1.352 l
+58.474 -1.352 l
+58.474 -1.881 l
+58.474 -2.138 58.407 -2.385 58.282 -2.631 c
+58.164 -2.874 58.017 -3.075 57.841 -3.233 c
+61.883 2.778 m
+61.883 1.823 l
+62.486 1.823 l
+62.486 1.294 l
+61.883 1.294 l
+61.883 -1.176 l
+61.883 -1.334 61.905 -1.452 61.957 -1.529 c
+62.015 -1.61 62.104 -1.646 62.221 -1.646 c
+62.31 -1.646 62.397 -1.631 62.486 -1.602 c
+62.486 -2.161 l
+62.339 -2.209 62.185 -2.234 62.03 -2.234 c
+61.773 -2.234 61.578 -2.142 61.443 -1.955 c
+61.302 -1.771 61.236 -1.51 61.236 -1.176 c
+61.236 1.294 l
+60.633 1.294 l
+60.633 1.823 l
+61.236 1.823 l
+61.236 2.778 l
+h
+63.897 1.411 m
+64.151 1.735 64.47 1.897 64.853 1.897 c
+65.558 1.897 65.915 1.426 65.925 0.485 c
+65.925 -2.161 l
+65.279 -2.161 l
+65.279 0.456 l
+65.279 0.769 65.223 0.989 65.117 1.118 c
+65.007 1.242 64.853 1.309 64.647 1.309 c
+64.489 1.309 64.342 1.253 64.205 1.147 c
+64.078 1.037 63.974 0.9 63.897 0.735 c
+63.897 -2.161 l
+63.251 -2.161 l
+63.251 3.484 l
+63.897 3.484 l
+h
+68.924 -2.161 m
+68.884 -2.072 68.858 -1.926 68.851 -1.72 c
+68.616 -2.065 68.321 -2.234 67.968 -2.234 c
+67.605 -2.234 67.322 -2.138 67.116 -1.94 c
+66.918 -1.735 66.822 -1.448 66.822 -1.072 c
+66.822 -0.673 66.958 -0.353 67.234 -0.118 c
+67.506 0.125 67.881 0.25 68.351 0.25 c
+68.836 0.25 l
+68.836 0.676 l
+68.836 0.912 68.781 1.077 68.674 1.176 c
+68.564 1.282 68.402 1.338 68.189 1.338 c
+67.991 1.338 67.829 1.279 67.704 1.162 c
+67.586 1.044 67.527 0.897 67.527 0.721 c
+66.881 0.721 l
+66.881 0.915 66.94 1.106 67.057 1.294 c
+67.182 1.477 67.344 1.625 67.542 1.735 c
+67.748 1.841 67.976 1.897 68.233 1.897 c
+68.634 1.897 68.938 1.793 69.144 1.588 c
+69.358 1.382 69.472 1.087 69.483 0.706 c
+69.483 -1.308 l
+69.483 -1.613 69.52 -1.878 69.601 -2.102 c
+69.601 -2.161 l
+h
+68.057 -1.646 m
+68.222 -1.646 68.373 -1.602 68.512 -1.514 c
+68.66 -1.425 68.766 -1.315 68.836 -1.176 c
+68.836 -0.235 l
+68.468 -0.235 l
+68.153 -0.235 67.91 -0.305 67.733 -0.441 c
+67.557 -0.569 67.469 -0.757 67.469 -0.999 c
+67.469 -1.228 67.513 -1.392 67.602 -1.5 c
+67.689 -1.598 67.84 -1.646 68.057 -1.646 c
+71.334 2.778 m
+71.334 1.823 l
+71.937 1.823 l
+71.937 1.294 l
+71.334 1.294 l
+71.334 -1.176 l
+71.334 -1.334 71.357 -1.452 71.409 -1.529 c
+71.467 -1.61 71.555 -1.646 71.673 -1.646 c
+71.761 -1.646 71.849 -1.631 71.937 -1.602 c
+71.937 -2.161 l
+71.791 -2.209 71.636 -2.234 71.482 -2.234 c
+71.224 -2.234 71.03 -2.142 70.894 -1.955 c
+70.754 -1.771 70.688 -1.51 70.688 -1.176 c
+70.688 1.294 l
+70.085 1.294 l
+70.085 1.823 l
+70.688 1.823 l
+70.688 2.778 l
+h
+77.391 -1.014 m
+77.994 1.823 l
+78.64 1.823 l
+77.655 -2.161 l
+77.141 -2.161 l
+76.362 0.691 l
+75.612 -2.161 l
+75.083 -2.161 l
+74.127 1.823 l
+74.76 1.823 l
+75.377 -0.941 l
+76.112 1.823 l
+76.626 1.823 l
+h
+80.742 -2.234 m
+80.242 -2.234 79.86 -2.087 79.596 -1.793 c
+79.331 -1.5 79.199 -1.066 79.199 -0.484 c
+79.199 -0.014 l
+79.199 0.58 79.324 1.047 79.581 1.382 c
+79.845 1.723 80.206 1.897 80.668 1.897 c
+81.128 1.897 81.47 1.742 81.698 1.44 c
+81.933 1.147 82.054 0.684 82.065 0.059 c
+82.065 -0.367 l
+79.845 -0.367 l
+79.845 -0.455 l
+79.845 -0.889 79.922 -1.201 80.08 -1.396 c
+80.246 -1.583 80.477 -1.675 80.772 -1.675 c
+80.967 -1.675 81.139 -1.643 81.286 -1.573 c
+81.433 -1.496 81.569 -1.378 81.698 -1.22 c
+82.035 -1.631 l
+81.749 -2.036 81.319 -2.234 80.742 -2.234 c
+80.668 1.338 m
+80.393 1.338 80.19 1.242 80.066 1.058 c
+79.937 0.871 79.864 0.58 79.845 0.191 c
+81.418 0.191 l
+81.418 0.279 l
+81.397 0.661 81.33 0.929 81.212 1.087 c
+81.095 1.253 80.911 1.338 80.668 1.338 c
+84.491 1.205 m
+84.402 1.224 84.303 1.235 84.196 1.235 c
+83.862 1.235 83.627 1.051 83.491 0.691 c
+83.491 -2.161 l
+82.844 -2.161 l
+82.844 1.823 l
+83.477 1.823 l
+83.491 1.411 l
+83.667 1.735 83.91 1.897 84.225 1.897 c
+84.333 1.897 84.421 1.874 84.491 1.837 c
+h
+86.49 -2.234 m
+85.99 -2.234 85.607 -2.087 85.343 -1.793 c
+85.079 -1.5 84.946 -1.066 84.946 -0.484 c
+84.946 -0.014 l
+84.946 0.58 85.071 1.047 85.328 1.382 c
+85.593 1.723 85.953 1.897 86.416 1.897 c
+86.875 1.897 87.217 1.742 87.445 1.44 c
+87.68 1.147 87.801 0.684 87.812 0.059 c
+87.812 -0.367 l
+85.593 -0.367 l
+85.593 -0.455 l
+85.593 -0.889 85.67 -1.201 85.828 -1.396 c
+85.993 -1.583 86.225 -1.675 86.519 -1.675 c
+86.714 -1.675 86.887 -1.643 87.033 -1.573 c
+87.18 -1.496 87.317 -1.378 87.445 -1.22 c
+87.783 -1.631 l
+87.496 -2.036 87.066 -2.234 86.49 -2.234 c
+86.416 1.338 m
+86.141 1.338 85.938 1.242 85.813 1.058 c
+85.684 0.871 85.611 0.58 85.593 0.191 c
+87.166 0.191 l
+87.166 0.279 l
+87.144 0.661 87.078 0.929 86.96 1.087 c
+86.842 1.253 86.658 1.338 86.416 1.338 c
+91.957 1.205 m
+91.87 1.224 91.77 1.235 91.664 1.235 c
+91.329 1.235 91.094 1.051 90.958 0.691 c
+90.958 -2.161 l
+90.311 -2.161 l
+90.311 1.823 l
+90.943 1.823 l
+90.958 1.411 l
+91.134 1.735 91.377 1.897 91.693 1.897 c
+91.799 1.897 91.888 1.874 91.957 1.837 c
+h
+93.956 -2.234 m
+93.457 -2.234 93.075 -2.087 92.811 -1.793 c
+92.545 -1.5 92.414 -1.066 92.414 -0.484 c
+92.414 -0.014 l
+92.414 0.58 92.538 1.047 92.795 1.382 c
+93.06 1.723 93.42 1.897 93.883 1.897 c
+94.342 1.897 94.684 1.742 94.912 1.44 c
+95.147 1.147 95.269 0.684 95.279 0.059 c
+95.279 -0.367 l
+93.06 -0.367 l
+93.06 -0.455 l
+93.06 -0.889 93.137 -1.201 93.295 -1.396 c
+93.461 -1.583 93.692 -1.675 93.986 -1.675 c
+94.181 -1.675 94.353 -1.643 94.5 -1.573 c
+94.648 -1.496 94.783 -1.378 94.912 -1.22 c
+95.25 -1.631 l
+94.964 -2.036 94.534 -2.234 93.956 -2.234 c
+93.883 1.338 m
+93.607 1.338 93.405 1.242 93.281 1.058 c
+93.152 0.871 93.079 0.58 93.06 0.191 c
+94.633 0.191 l
+94.633 0.279 l
+94.611 0.661 94.544 0.929 94.427 1.087 c
+94.309 1.253 94.126 1.338 93.883 1.338 c
+96.676 1.823 m
+96.69 1.455 l
+96.933 1.75 97.253 1.897 97.646 1.897 c
+98.087 1.897 98.396 1.698 98.572 1.309 c
+98.826 1.698 99.175 1.897 99.616 1.897 c
+100.351 1.897 100.726 1.434 100.748 0.515 c
+100.748 -2.161 l
+100.101 -2.161 l
+100.101 0.456 l
+100.101 0.75 100.046 0.963 99.939 1.103 c
+99.84 1.239 99.668 1.309 99.425 1.309 c
+99.226 1.309 99.065 1.228 98.939 1.073 c
+98.822 0.927 98.752 0.735 98.733 0.5 c
+98.733 -2.161 l
+98.072 -2.161 l
+98.072 0.485 l
+98.072 1.033 97.852 1.309 97.411 1.309 c
+97.077 1.309 96.842 1.147 96.705 0.823 c
+96.705 -2.161 l
+96.059 -2.161 l
+96.059 1.823 l
+h
+101.586 0.015 m
+101.586 0.592 101.721 1.047 101.997 1.382 c
+102.28 1.723 102.651 1.897 103.114 1.897 c
+103.574 1.897 103.941 1.727 104.216 1.397 c
+104.499 1.073 104.647 0.625 104.657 0.059 c
+104.657 -0.367 l
+104.657 -0.937 104.514 -1.392 104.231 -1.735 c
+103.955 -2.069 103.589 -2.234 103.129 -2.234 c
+102.666 -2.234 102.295 -2.072 102.012 -1.749 c
+101.736 -1.419 101.592 -0.977 101.586 -0.426 c
+h
+102.232 -0.367 m
+102.232 -0.771 102.309 -1.087 102.467 -1.323 c
+102.633 -1.558 102.853 -1.675 103.129 -1.675 c
+103.695 -1.675 103.988 -1.264 104.011 -0.441 c
+104.011 0.015 l
+104.011 0.416 103.926 0.735 103.761 0.97 c
+103.603 1.213 103.386 1.338 103.114 1.338 c
+102.849 1.338 102.633 1.213 102.467 0.97 c
+102.309 0.735 102.232 0.416 102.232 0.015 c
+h
+106.568 -1.176 m
+107.318 1.823 l
+107.979 1.823 l
+106.803 -2.161 l
+106.319 -2.161 l
+105.128 1.823 l
+105.789 1.823 l
+h
+110.037 -2.234 m
+109.538 -2.234 109.155 -2.087 108.891 -1.793 c
+108.626 -1.5 108.494 -1.066 108.494 -0.484 c
+108.494 -0.014 l
+108.494 0.58 108.619 1.047 108.876 1.382 c
+109.141 1.723 109.501 1.897 109.964 1.897 c
+110.423 1.897 110.765 1.742 110.993 1.44 c
+111.228 1.147 111.35 0.684 111.36 0.059 c
+111.36 -0.367 l
+109.141 -0.367 l
+109.141 -0.455 l
+109.141 -0.889 109.218 -1.201 109.376 -1.396 c
+109.542 -1.583 109.773 -1.675 110.066 -1.675 c
+110.261 -1.675 110.434 -1.643 110.581 -1.573 c
+110.728 -1.496 110.864 -1.378 110.993 -1.22 c
+111.331 -1.631 l
+111.044 -2.036 110.614 -2.234 110.037 -2.234 c
+109.964 1.338 m
+109.688 1.338 109.486 1.242 109.361 1.058 c
+109.233 0.871 109.159 0.58 109.141 0.191 c
+110.714 0.191 l
+110.714 0.279 l
+110.691 0.661 110.625 0.929 110.508 1.087 c
+110.39 1.253 110.207 1.338 109.964 1.338 c
+112.007 0.015 m
+112.007 0.621 112.117 1.087 112.345 1.411 c
+112.58 1.735 112.908 1.897 113.33 1.897 c
+113.712 1.897 114.01 1.738 114.226 1.426 c
+114.226 3.484 l
+114.874 3.484 l
+114.874 -2.161 l
+114.286 -2.161 l
+114.242 -1.735 l
+114.035 -2.069 113.731 -2.234 113.33 -2.234 c
+112.918 -2.234 112.595 -2.08 112.36 -1.764 c
+112.125 -1.44 112.007 -0.985 112.007 -0.397 c
+h
+112.654 -0.367 m
+112.654 -0.808 112.717 -1.139 112.844 -1.352 c
+112.981 -1.558 113.201 -1.66 113.507 -1.66 c
+113.829 -1.66 114.068 -1.5 114.226 -1.176 c
+114.226 0.838 l
+114.057 1.151 113.819 1.309 113.507 1.309 c
+113.201 1.309 112.981 1.205 112.844 1 c
+112.717 0.794 112.654 0.47 112.654 0.029 c
+h
+117.887 -2.161 m
+117.887 1.294 l
+117.357 1.294 l
+117.357 1.823 l
+117.887 1.823 l
+117.887 2.278 l
+117.887 2.679 117.982 2.992 118.18 3.219 c
+118.386 3.443 118.666 3.557 119.019 3.557 c
+119.154 3.557 119.287 3.535 119.416 3.499 c
+119.386 2.955 l
+119.287 2.973 119.188 2.984 119.092 2.984 c
+118.718 2.984 118.533 2.72 118.533 2.19 c
+118.533 1.823 l
+119.21 1.823 l
+119.21 1.294 l
+118.533 1.294 l
+118.533 -2.161 l
+h
+121.62 1.205 m
+121.532 1.224 121.433 1.235 121.326 1.235 c
+120.992 1.235 120.757 1.051 120.621 0.691 c
+120.621 -2.161 l
+119.973 -2.161 l
+119.973 1.823 l
+120.606 1.823 l
+120.621 1.411 l
+120.798 1.735 121.039 1.897 121.355 1.897 c
+121.463 1.897 121.55 1.874 121.62 1.837 c
+h
+122.061 0.015 m
+122.061 0.592 122.197 1.047 122.473 1.382 c
+122.756 1.723 123.127 1.897 123.59 1.897 c
+124.05 1.897 124.417 1.727 124.692 1.397 c
+124.975 1.073 125.122 0.625 125.133 0.059 c
+125.133 -0.367 l
+125.133 -0.937 124.99 -1.392 124.707 -1.735 c
+124.432 -2.069 124.064 -2.234 123.605 -2.234 c
+123.142 -2.234 122.77 -2.072 122.487 -1.749 c
+122.211 -1.419 122.068 -0.977 122.061 -0.426 c
+h
+122.708 -0.367 m
+122.708 -0.771 122.785 -1.087 122.943 -1.323 c
+123.109 -1.558 123.329 -1.675 123.605 -1.675 c
+124.17 -1.675 124.465 -1.264 124.486 -0.441 c
+124.486 0.015 l
+124.486 0.416 124.402 0.735 124.237 0.97 c
+124.079 1.213 123.862 1.338 123.59 1.338 c
+123.325 1.338 123.109 1.213 122.943 0.97 c
+122.785 0.735 122.708 0.416 122.708 0.015 c
+h
+126.589 1.823 m
+126.603 1.455 l
+126.846 1.75 127.165 1.897 127.559 1.897 c
+128 1.897 128.308 1.698 128.484 1.309 c
+128.738 1.698 129.087 1.897 129.529 1.897 c
+130.263 1.897 130.638 1.434 130.66 0.515 c
+130.66 -2.161 l
+130.013 -2.161 l
+130.013 0.456 l
+130.013 0.75 129.958 0.963 129.851 1.103 c
+129.752 1.239 129.579 1.309 129.338 1.309 c
+129.139 1.309 128.977 1.228 128.852 1.073 c
+128.735 0.927 128.665 0.735 128.646 0.5 c
+128.646 -2.161 l
+127.985 -2.161 l
+127.985 0.485 l
+127.985 1.033 127.765 1.309 127.323 1.309 c
+126.989 1.309 126.754 1.147 126.618 0.823 c
+126.618 -2.161 l
+125.972 -2.161 l
+125.972 1.823 l
+h
+134.203 2.778 m
+134.203 1.823 l
+134.805 1.823 l
+134.805 1.294 l
+134.203 1.294 l
+134.203 -1.176 l
+134.203 -1.334 134.225 -1.452 134.276 -1.529 c
+134.335 -1.61 134.423 -1.646 134.541 -1.646 c
+134.629 -1.646 134.717 -1.631 134.805 -1.602 c
+134.805 -2.161 l
+134.658 -2.209 134.504 -2.234 134.35 -2.234 c
+134.092 -2.234 133.897 -2.142 133.762 -1.955 c
+133.622 -1.771 133.556 -1.51 133.556 -1.176 c
+133.556 1.294 l
+132.953 1.294 l
+132.953 1.823 l
+133.556 1.823 l
+133.556 2.778 l
+h
+136.216 1.411 m
+136.47 1.735 136.79 1.897 137.172 1.897 c
+137.878 1.897 138.234 1.426 138.244 0.485 c
+138.244 -2.161 l
+137.598 -2.161 l
+137.598 0.456 l
+137.598 0.769 137.543 0.989 137.436 1.118 c
+137.326 1.242 137.172 1.309 136.966 1.309 c
+136.808 1.309 136.661 1.253 136.525 1.147 c
+136.397 1.037 136.293 0.9 136.216 0.735 c
+136.216 -2.161 l
+135.57 -2.161 l
+135.57 3.484 l
+136.216 3.484 l
+h
+140.626 -2.234 m
+140.126 -2.234 139.744 -2.087 139.48 -1.793 c
+139.215 -1.5 139.083 -1.066 139.083 -0.484 c
+139.083 -0.014 l
+139.083 0.58 139.208 1.047 139.465 1.382 c
+139.729 1.723 140.089 1.897 140.553 1.897 c
+141.012 1.897 141.354 1.742 141.581 1.44 c
+141.816 1.147 141.938 0.684 141.949 0.059 c
+141.949 -0.367 l
+139.729 -0.367 l
+139.729 -0.455 l
+139.729 -0.889 139.807 -1.201 139.964 -1.396 c
+140.13 -1.583 140.361 -1.675 140.656 -1.675 c
+140.85 -1.675 141.023 -1.643 141.17 -1.573 c
+141.317 -1.496 141.453 -1.378 141.581 -1.22 c
+141.92 -1.631 l
+141.633 -2.036 141.203 -2.234 140.626 -2.234 c
+140.553 1.338 m
+140.277 1.338 140.075 1.242 139.95 1.058 c
+139.821 0.871 139.748 0.58 139.729 0.191 c
+141.302 0.191 l
+141.302 0.279 l
+141.28 0.661 141.214 0.929 141.097 1.087 c
+140.979 1.253 140.795 1.338 140.553 1.338 c
+f
+Q
+q 1 0 0 1 216.9476 230.3099 cm
+0 0 m
+-0.338 0.029 l
+-0.625 0.029 -0.816 -0.096 -0.912 -0.339 c
+-0.912 -2.97 l
+-1.955 -2.97 l
+-1.955 1.014 l
+-0.985 1.014 l
+-0.956 0.573 l
+-0.79 0.914 -0.559 1.087 -0.264 1.087 c
+-0.147 1.087 -0.055 1.065 0.014 1.028 c
+h
+2.072 -3.043 m
+1.544 -3.043 1.124 -2.889 0.823 -2.573 c
+0.529 -2.249 0.382 -1.79 0.382 -1.191 c
+0.382 -0.882 l
+0.382 -0.258 0.518 0.228 0.794 0.573 c
+1.066 0.914 1.459 1.087 1.97 1.087 c
+2.469 1.087 2.84 0.926 3.087 0.602 c
+3.341 0.278 3.472 -0.199 3.484 -0.823 c
+3.484 -1.324 l
+1.411 -1.324 l
+1.429 -1.617 1.492 -1.834 1.602 -1.97 c
+1.72 -2.11 1.899 -2.176 2.146 -2.176 c
+2.487 -2.176 2.778 -2.058 3.013 -1.823 c
+3.425 -2.455 l
+3.296 -2.631 3.109 -2.775 2.866 -2.881 c
+2.62 -2.988 2.356 -3.043 2.072 -3.043 c
+1.425 -0.603 m
+2.454 -0.603 l
+2.454 -0.5 l
+2.454 -0.265 2.414 -0.088 2.337 0.029 c
+2.267 0.154 2.138 0.22 1.955 0.22 c
+1.779 0.22 1.646 0.151 1.558 0.014 c
+1.477 -0.115 1.433 -0.32 1.425 -0.603 c
+5.041 1.014 m
+5.072 0.646 l
+5.307 0.941 5.615 1.087 5.997 1.087 c
+6.398 1.087 6.677 0.903 6.834 0.544 c
+7.07 0.903 7.397 1.087 7.819 1.087 c
+8.515 1.087 8.867 0.602 8.878 -0.368 c
+8.878 -2.97 l
+7.85 -2.97 l
+7.85 -0.427 l
+7.85 -0.202 7.813 -0.04 7.746 0.058 c
+7.688 0.154 7.578 0.205 7.423 0.205 c
+7.225 0.205 7.085 0.087 6.996 -0.148 c
+6.996 -2.97 l
+5.953 -2.97 l
+5.953 -0.441 l
+5.953 -0.206 5.924 -0.04 5.865 0.058 c
+5.806 0.154 5.696 0.205 5.542 0.205 c
+5.365 0.205 5.222 0.11 5.115 -0.074 c
+5.115 -2.97 l
+4.072 -2.97 l
+4.072 1.014 l
+h
+9.54 -0.853 m
+9.54 -0.246 9.679 0.228 9.966 0.573 c
+10.248 0.914 10.642 1.087 11.142 1.087 c
+11.649 1.087 12.046 0.914 12.332 0.573 c
+12.615 0.228 12.758 -0.246 12.758 -0.853 c
+12.758 -1.118 l
+12.758 -1.717 12.615 -2.187 12.332 -2.529 c
+12.046 -2.874 11.649 -3.043 11.142 -3.043 c
+10.631 -3.043 10.234 -2.874 9.951 -2.529 c
+9.676 -2.187 9.54 -1.713 9.54 -1.103 c
+h
+10.583 -1.118 m
+10.583 -1.823 10.767 -2.176 11.142 -2.176 c
+11.495 -2.176 11.686 -1.881 11.715 -1.294 c
+11.715 -0.853 l
+11.715 -0.493 11.663 -0.221 11.568 -0.044 c
+11.469 0.132 11.326 0.22 11.142 0.22 c
+10.965 0.22 10.826 0.132 10.73 -0.044 c
+10.631 -0.221 10.583 -0.493 10.583 -0.853 c
+h
+14.611 1.984 m
+14.611 1.014 l
+15.14 1.014 l
+15.14 0.22 l
+14.611 0.22 l
+14.611 -1.75 l
+14.611 -1.908 14.629 -2.014 14.67 -2.073 c
+14.717 -2.132 14.802 -2.161 14.919 -2.161 c
+15.026 -2.161 15.11 -2.154 15.169 -2.132 c
+15.169 -2.94 l
+14.993 -3.007 14.802 -3.043 14.596 -3.043 c
+13.92 -3.043 13.575 -2.658 13.567 -1.881 c
+13.567 0.22 l
+13.111 0.22 l
+13.111 1.014 l
+13.567 1.014 l
+13.567 1.984 l
+h
+17.315 -3.043 m
+16.787 -3.043 16.367 -2.889 16.066 -2.573 c
+15.771 -2.249 15.625 -1.79 15.625 -1.191 c
+15.625 -0.882 l
+15.625 -0.258 15.761 0.228 16.037 0.573 c
+16.309 0.914 16.702 1.087 17.213 1.087 c
+17.712 1.087 18.084 0.926 18.329 0.602 c
+18.583 0.278 18.715 -0.199 18.726 -0.823 c
+18.726 -1.324 l
+16.654 -1.324 l
+16.673 -1.617 16.735 -1.834 16.845 -1.97 c
+16.962 -2.11 17.143 -2.176 17.389 -2.176 c
+17.731 -2.176 18.021 -2.058 18.256 -1.823 c
+18.668 -2.455 l
+18.539 -2.631 18.352 -2.775 18.109 -2.881 c
+17.863 -2.988 17.598 -3.043 17.315 -3.043 c
+16.669 -0.603 m
+17.697 -0.603 l
+17.697 -0.5 l
+17.697 -0.265 17.657 -0.088 17.58 0.029 c
+17.51 0.154 17.381 0.22 17.198 0.22 c
+17.022 0.22 16.889 0.151 16.801 0.014 c
+16.72 -0.115 16.676 -0.32 16.669 -0.603 c
+f
+Q
+q 1 0 0 1 239.7314 230.706 cm
+0 0 m
+-0.088 0.019 -0.188 0.03 -0.294 0.03 c
+-0.628 0.03 -0.864 -0.154 -1 -0.514 c
+-1 -3.366 l
+-1.646 -3.366 l
+-1.646 0.618 l
+-1.014 0.618 l
+-1 0.206 l
+-0.823 0.53 -0.581 0.691 -0.265 0.691 c
+-0.158 0.691 -0.071 0.669 0 0.632 c
+h
+1.999 -3.439 m
+1.499 -3.439 1.117 -3.293 0.852 -2.998 c
+0.588 -2.705 0.455 -2.271 0.455 -1.69 c
+0.455 -1.219 l
+0.455 -0.625 0.58 -0.158 0.837 0.177 c
+1.103 0.518 1.462 0.691 1.925 0.691 c
+2.385 0.691 2.726 0.537 2.954 0.235 c
+3.189 -0.058 3.31 -0.521 3.322 -1.146 c
+3.322 -1.572 l
+1.103 -1.572 l
+1.103 -1.66 l
+1.103 -2.094 1.18 -2.406 1.338 -2.601 c
+1.502 -2.788 1.734 -2.881 2.028 -2.881 c
+2.223 -2.881 2.395 -2.848 2.543 -2.778 c
+2.69 -2.701 2.826 -2.583 2.954 -2.425 c
+3.293 -2.836 l
+3.006 -3.241 2.576 -3.439 1.999 -3.439 c
+1.925 0.133 m
+1.65 0.133 1.448 0.037 1.323 -0.147 c
+1.194 -0.334 1.12 -0.625 1.103 -1.014 c
+2.675 -1.014 l
+2.675 -0.926 l
+2.653 -0.544 2.587 -0.276 2.469 -0.118 c
+2.352 0.048 2.167 0.133 1.925 0.133 c
+6.982 -1.572 m
+6.982 -2.2 6.864 -2.671 6.628 -2.983 c
+6.401 -3.289 6.085 -3.439 5.674 -3.439 c
+5.269 -3.439 4.961 -3.289 4.747 -2.983 c
+4.747 -4.895 l
+4.101 -4.895 l
+4.101 0.618 l
+4.689 0.618 l
+4.733 0.177 l
+4.945 0.518 5.255 0.691 5.659 0.691 c
+6.1 0.691 6.427 0.537 6.644 0.235 c
+6.857 -0.07 6.971 -0.525 6.982 -1.132 c
+h
+6.335 -1.19 m
+6.335 -0.749 6.265 -0.426 6.129 -0.22 c
+5.99 -0.007 5.769 0.103 5.468 0.103 c
+5.151 0.103 4.913 -0.051 4.747 -0.353 c
+4.747 -2.425 l
+4.913 -2.73 5.151 -2.881 5.468 -2.881 c
+5.762 -2.881 5.975 -2.778 6.115 -2.572 c
+6.25 -2.358 6.324 -2.028 6.335 -1.587 c
+h
+7.688 -1.19 m
+7.688 -0.613 7.823 -0.158 8.099 0.177 c
+8.382 0.518 8.753 0.691 9.215 0.691 c
+9.675 0.691 10.042 0.522 10.318 0.192 c
+10.601 -0.132 10.748 -0.58 10.759 -1.146 c
+10.759 -1.572 l
+10.759 -2.142 10.616 -2.597 10.333 -2.94 c
+10.057 -3.274 9.69 -3.439 9.231 -3.439 c
+8.768 -3.439 8.396 -3.278 8.114 -2.954 c
+7.838 -2.624 7.694 -2.183 7.688 -1.631 c
+h
+8.334 -1.572 m
+8.334 -1.976 8.411 -2.293 8.569 -2.528 c
+8.735 -2.763 8.955 -2.881 9.231 -2.881 c
+9.797 -2.881 10.09 -2.469 10.113 -1.646 c
+10.113 -1.19 l
+10.113 -0.789 10.028 -0.47 9.863 -0.235 c
+9.705 0.008 9.488 0.133 9.215 0.133 c
+8.951 0.133 8.735 0.008 8.569 -0.235 c
+8.411 -0.47 8.334 -0.789 8.334 -1.19 c
+h
+13.537 -2.352 m
+13.537 -2.204 13.483 -2.083 13.375 -1.984 c
+13.265 -1.888 13.059 -1.77 12.758 -1.631 c
+12.413 -1.484 12.17 -1.363 12.024 -1.263 c
+11.877 -1.157 11.766 -1.04 11.7 -0.911 c
+11.63 -0.786 11.597 -0.628 11.597 -0.44 c
+11.597 -0.118 11.715 0.151 11.95 0.368 c
+12.185 0.581 12.486 0.691 12.862 0.691 c
+13.244 0.691 13.552 0.578 13.787 0.353 c
+14.023 0.125 14.14 -0.161 14.14 -0.514 c
+13.493 -0.514 l
+13.493 -0.338 13.435 -0.187 13.317 -0.058 c
+13.2 0.067 13.045 0.133 12.862 0.133 c
+12.663 0.133 12.512 0.077 12.406 -0.029 c
+12.295 -0.128 12.244 -0.261 12.244 -0.426 c
+12.244 -0.554 12.28 -0.661 12.361 -0.749 c
+12.438 -0.83 12.629 -0.933 12.935 -1.058 c
+13.412 -1.246 13.743 -1.433 13.919 -1.616 c
+14.096 -1.793 14.184 -2.021 14.184 -2.293 c
+14.184 -2.645 14.059 -2.925 13.817 -3.131 c
+13.581 -3.336 13.265 -3.439 12.876 -3.439 c
+12.454 -3.439 12.116 -3.322 11.862 -3.087 c
+11.605 -2.844 11.48 -2.539 11.48 -2.175 c
+12.126 -2.175 l
+12.134 -2.403 12.203 -2.58 12.332 -2.705 c
+12.457 -2.822 12.641 -2.881 12.876 -2.881 c
+13.089 -2.881 13.251 -2.833 13.361 -2.734 c
+13.479 -2.638 13.537 -2.51 13.537 -2.352 c
+15.727 -3.366 -0.646 3.984 re
+15.771 1.661 m
+15.771 1.551 15.742 1.459 15.684 1.382 c
+15.625 1.312 15.529 1.279 15.405 1.279 c
+15.287 1.279 15.191 1.312 15.125 1.382 c
+15.066 1.459 15.037 1.551 15.037 1.661 c
+15.037 1.779 15.066 1.871 15.125 1.941 c
+15.191 2.018 15.287 2.058 15.405 2.058 c
+15.529 2.058 15.625 2.018 15.684 1.941 c
+15.742 1.86 15.771 1.768 15.771 1.661 c
+17.595 1.573 m
+17.595 0.618 l
+18.197 0.618 l
+18.197 0.088 l
+17.595 0.088 l
+17.595 -2.381 l
+17.595 -2.539 17.616 -2.657 17.668 -2.734 c
+17.726 -2.815 17.815 -2.851 17.932 -2.851 c
+18.021 -2.851 18.109 -2.836 18.197 -2.807 c
+18.197 -3.366 l
+18.05 -3.414 17.896 -3.439 17.741 -3.439 c
+17.485 -3.439 17.29 -3.347 17.153 -3.16 c
+17.014 -2.977 16.947 -2.715 16.947 -2.381 c
+16.947 0.088 l
+16.345 0.088 l
+16.345 0.618 l
+16.947 0.618 l
+16.947 1.573 l
+h
+18.756 -1.19 m
+18.756 -0.613 18.892 -0.158 19.168 0.177 c
+19.45 0.518 19.821 0.691 20.284 0.691 c
+20.743 0.691 21.111 0.522 21.387 0.192 c
+21.67 -0.132 21.817 -0.58 21.828 -1.146 c
+21.828 -1.572 l
+21.828 -2.142 21.684 -2.597 21.402 -2.94 c
+21.126 -3.274 20.758 -3.439 20.299 -3.439 c
+19.836 -3.439 19.465 -3.278 19.182 -2.954 c
+18.906 -2.624 18.763 -2.183 18.756 -1.631 c
+h
+19.403 -1.572 m
+19.403 -1.976 19.48 -2.293 19.638 -2.528 c
+19.803 -2.763 20.024 -2.881 20.299 -2.881 c
+20.865 -2.881 21.159 -2.469 21.181 -1.646 c
+21.181 -1.19 l
+21.181 -0.789 21.096 -0.47 20.931 -0.235 c
+20.773 0.008 20.556 0.133 20.284 0.133 c
+20.02 0.133 19.803 0.008 19.638 -0.235 c
+19.48 -0.47 19.403 -0.789 19.403 -1.19 c
+h
+24.312 0 m
+24.224 0.019 24.124 0.03 24.018 0.03 c
+23.683 0.03 23.448 -0.154 23.312 -0.514 c
+23.312 -3.366 l
+22.665 -3.366 l
+22.665 0.618 l
+23.297 0.618 l
+23.312 0.206 l
+23.488 0.53 23.731 0.691 24.047 0.691 c
+24.154 0.691 24.242 0.669 24.312 0.632 c
+h
+26.12 -2.278 m
+26.84 0.618 l
+27.531 0.618 l
+26.237 -3.924 l
+26.138 -4.266 25.995 -4.527 25.811 -4.704 c
+25.635 -4.88 25.433 -4.968 25.208 -4.968 c
+25.121 -4.968 25.007 -4.945 24.87 -4.909 c
+24.87 -4.365 l
+25.017 -4.38 l
+25.201 -4.38 25.348 -4.336 25.458 -4.247 c
+25.565 -4.159 25.653 -4.002 25.723 -3.777 c
+25.84 -3.336 l
+24.679 0.618 l
+25.385 0.618 l
+h
+27.81 -3.013 m
+27.81 -2.896 27.843 -2.8 27.914 -2.719 c
+27.979 -2.642 28.082 -2.601 28.222 -2.601 c
+28.369 -2.601 28.475 -2.642 28.545 -2.719 c
+28.622 -2.8 28.662 -2.896 28.662 -3.013 c
+28.662 -3.123 28.622 -3.215 28.545 -3.293 c
+28.475 -3.37 28.369 -3.41 28.222 -3.41 c
+28.082 -3.41 27.979 -3.37 27.914 -3.293 c
+27.843 -3.215 27.81 -3.123 27.81 -3.013 c
+f
+Q
+0.113 0.082 0.09 0 k
+35.668 221.732 238.665 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 40.8563 214.894 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.647 -0.243 -0.775 -0.367 -0.882 c
+-0.496 -0.992 -0.658 -1.081 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.243 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.162 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.927 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.132 l
+-2.642 0.033 -2.616 -0.059 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.302 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.683 -1.992 0.691 -1.999 0.691 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.881 -2.786 0.959 -2.91 1.058 c
+-3.039 1.153 -3.142 1.278 -3.219 1.425 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.836 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.119 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.119 -1.128 3.09 -0.97 3.042 c
+-0.804 2.991 -0.669 2.917 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.252 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.352 c
+-1.294 1.311 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.319 2.385 -2.366 2.337 c
+-2.406 2.296 -2.437 2.248 -2.454 2.19 c
+-2.477 2.131 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.778 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.469 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.091 -0.86 0.176 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.529 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.53 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.22 5.108 -2.103 c
+5.039 -1.985 4.991 -1.856 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.86 6.064 -1.941 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.058 6.681 -2.028 c
+6.758 -1.999 6.828 -1.945 6.887 -1.867 c
+6.945 -1.797 6.99 -1.706 7.019 -1.588 c
+7.056 -1.47 7.078 -1.323 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.89 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.073 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.412 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.234 c
+4.946 1.448 5.027 1.631 5.137 1.778 c
+5.245 1.932 5.376 2.05 5.534 2.131 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.252 6.387 2.234 c
+6.483 2.212 6.571 2.179 6.652 2.131 c
+6.739 2.08 6.817 2.017 6.887 1.94 c
+6.964 1.859 7.026 1.768 7.078 1.66 c
+7.092 1.66 l
+7.092 1.808 l
+7.1 1.866 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.152 2.219 c
+8.004 2.219 l
+7.993 2.138 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.162 l
+7.975 -1.415 7.938 -1.635 7.871 -1.823 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.529 m
+7.092 0.742 7.067 0.918 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.587 c
+6.571 1.624 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.62 6.137 1.573 c
+6.056 1.532 5.99 1.462 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.874 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.339 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.177 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.529 c
+11.036 -0.647 m
+12.168 -0.647 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.647 l
+10.124 -0.647 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.676 re
+10.124 2.836 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.219 l
+13.644 2.219 l
+13.924 3.116 l
+14.497 3.116 l
+14.497 2.219 l
+15.732 2.219 l
+15.732 1.602 l
+14.497 1.602 l
+14.497 -0.103 l
+14.497 -0.324 l
+14.504 -0.393 14.527 -0.456 14.556 -0.515 c
+14.593 -0.566 14.648 -0.611 14.718 -0.647 c
+14.795 -0.676 14.909 -0.691 15.056 -0.691 c
+15.192 -0.691 15.327 -0.688 15.468 -0.676 c
+15.603 -0.658 15.736 -0.632 15.865 -0.603 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.231 15.629 -1.249 c
+15.549 -1.261 15.471 -1.268 15.394 -1.279 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.041 -1.301 14.942 -1.309 14.835 -1.309 c
+14.648 -1.309 14.486 -1.294 14.35 -1.264 c
+14.221 -1.228 14.107 -1.183 14.012 -1.132 c
+13.924 -1.085 13.85 -1.025 13.791 -0.956 c
+13.733 -0.879 13.689 -0.802 13.66 -0.721 c
+13.63 -0.632 13.608 -0.544 13.6 -0.456 c
+13.59 -0.36 13.586 -0.264 13.586 -0.177 c
+h
+21.986 2.219 m
+21.994 2.198 22.001 2.165 22.001 2.117 c
+22.009 2.076 22.016 2.028 22.016 1.97 c
+22.023 1.918 22.03 1.866 22.03 1.808 c
+22.03 1.646 l
+22.045 1.646 l
+22.104 1.764 22.17 1.859 22.251 1.94 c
+22.328 2.017 22.413 2.08 22.501 2.131 c
+22.589 2.19 22.677 2.227 22.765 2.248 c
+22.861 2.267 22.961 2.278 23.059 2.278 c
+23.265 2.278 23.445 2.234 23.603 2.146 c
+23.757 2.057 23.886 1.929 23.985 1.764 c
+24.092 1.606 24.169 1.415 24.22 1.19 c
+24.28 0.974 24.309 0.738 24.309 0.484 c
+24.309 0.22 24.28 -0.026 24.22 -0.25 c
+24.169 -0.467 24.092 -0.658 23.985 -0.823 c
+23.886 -0.981 23.754 -1.103 23.589 -1.191 c
+23.431 -1.279 23.243 -1.323 23.03 -1.323 c
+22.931 -1.323 22.832 -1.312 22.736 -1.294 c
+22.637 -1.272 22.545 -1.243 22.456 -1.191 c
+22.375 -1.143 22.298 -1.081 22.221 -1 c
+22.152 -0.923 22.093 -0.831 22.045 -0.721 c
+22.03 -0.721 l
+22.03 -0.809 l
+22.038 -0.849 22.045 -0.897 22.045 -0.956 c
+22.045 -1.118 l
+22.045 -1.294 l
+22.045 -2.631 l
+21.134 -2.631 l
+21.134 1.455 l
+21.134 1.62 21.126 1.768 21.119 1.896 c
+21.119 2.219 l
+h
+22.03 0.455 m
+22.03 0.228 22.049 0.037 22.089 -0.118 c
+22.137 -0.264 22.192 -0.382 22.251 -0.47 c
+22.317 -0.559 22.391 -0.625 22.471 -0.661 c
+22.549 -0.702 22.626 -0.721 22.707 -0.721 c
+22.803 -0.721 22.89 -0.698 22.971 -0.647 c
+23.059 -0.599 23.125 -0.53 23.177 -0.441 c
+23.235 -0.345 23.28 -0.221 23.31 -0.073 c
+23.346 0.081 23.368 0.268 23.368 0.484 c
+23.368 0.874 23.31 1.168 23.192 1.367 c
+23.081 1.562 22.927 1.66 22.722 1.66 c
+22.641 1.66 22.564 1.639 22.486 1.602 c
+22.406 1.562 22.332 1.5 22.265 1.411 c
+22.196 1.323 22.137 1.198 22.089 1.043 c
+22.049 0.885 22.03 0.691 22.03 0.455 c
+26.061 2.219 m
+26.061 0.264 l
+26.061 0.125 26.069 0 26.091 -0.118 c
+26.109 -0.228 26.142 -0.32 26.194 -0.397 c
+26.242 -0.478 26.3 -0.54 26.371 -0.588 c
+26.437 -0.628 26.521 -0.647 26.62 -0.647 c
+26.709 -0.647 26.789 -0.628 26.87 -0.588 c
+26.959 -0.54 27.032 -0.47 27.09 -0.382 c
+27.15 -0.287 27.194 -0.177 27.223 -0.059 c
+27.26 0.066 27.281 0.206 27.281 0.353 c
+27.281 2.219 l
+28.178 2.219 l
+28.178 -0.485 l
+28.178 -0.721 l
+28.185 -0.802 28.193 -0.879 28.193 -0.956 c
+28.193 -1.147 l
+28.201 -1.199 28.208 -1.235 28.208 -1.264 c
+27.355 -1.264 l
+27.344 -1.235 27.333 -1.199 27.326 -1.147 c
+27.326 -0.956 l
+27.326 -0.89 27.318 -0.819 27.312 -0.75 c
+27.312 -0.574 l
+27.296 -0.574 l
+27.179 -0.838 27.025 -1.029 26.841 -1.147 c
+26.664 -1.264 26.462 -1.323 26.238 -1.323 c
+26.032 -1.323 25.86 -1.286 25.724 -1.22 c
+25.584 -1.154 25.473 -1.058 25.386 -0.941 c
+25.305 -0.823 25.246 -0.688 25.209 -0.53 c
+25.18 -0.364 25.165 -0.187 25.165 0 c
+25.165 2.219 l
+h
+31.343 -0.647 m
+32.474 -0.647 l
+32.474 -1.264 l
+29.167 -1.264 l
+29.167 -0.647 l
+30.431 -0.647 l
+30.431 2.896 l
+29.505 2.896 l
+29.505 3.513 l
+31.343 3.513 l
+h
+35.407 -0.647 m
+36.538 -0.647 l
+36.538 -1.264 l
+33.232 -1.264 l
+33.232 -0.647 l
+34.495 -0.647 l
+34.495 2.896 l
+33.569 2.896 l
+33.569 3.513 l
+35.407 3.513 l
+h
+42.175 -2.631 m
+42.175 3.513 l
+44.101 3.513 l
+44.101 2.896 l
+43.028 2.896 l
+43.028 -2.014 l
+44.101 -2.014 l
+44.101 -2.631 l
+h
+48.5 1.469 m
+48.4 1.477 48.298 1.488 48.191 1.5 c
+48.081 1.517 47.96 1.529 47.823 1.529 c
+47.648 1.529 47.489 1.488 47.353 1.411 c
+47.214 1.341 47.096 1.242 47 1.117 c
+46.912 0.989 46.842 0.841 46.794 0.676 c
+46.754 0.507 46.736 0.33 46.736 0.147 c
+46.736 -1.264 l
+45.839 -1.264 l
+45.839 0.985 l
+45.839 1.109 45.828 1.234 45.81 1.352 c
+45.799 1.477 45.784 1.595 45.766 1.705 c
+45.755 1.822 45.74 1.918 45.722 1.999 c
+45.699 2.087 45.681 2.161 45.663 2.219 c
+46.545 2.219 l
+46.552 2.167 46.563 2.117 46.574 2.057 c
+46.593 1.999 46.607 1.932 46.618 1.866 c
+46.637 1.808 46.651 1.741 46.663 1.675 c
+46.67 1.606 46.68 1.543 46.692 1.484 c
+46.707 1.484 l
+46.743 1.602 46.794 1.708 46.854 1.808 c
+46.919 1.903 47 1.988 47.089 2.057 c
+47.177 2.124 47.28 2.179 47.397 2.219 c
+47.522 2.256 47.669 2.278 47.838 2.278 c
+47.964 2.278 48.081 2.271 48.191 2.263 c
+48.309 2.252 48.411 2.238 48.5 2.219 c
+h
+51.106 -1.323 m
+50.848 -1.323 50.62 -1.286 50.414 -1.22 c
+50.208 -1.143 50.032 -1.029 49.886 -0.882 c
+49.738 -0.728 49.62 -0.537 49.533 -0.309 c
+49.452 -0.085 49.415 0.18 49.415 0.484 c
+49.415 0.816 49.459 1.095 49.547 1.323 c
+49.643 1.558 49.772 1.741 49.93 1.881 c
+50.094 2.017 50.282 2.117 50.488 2.175 c
+50.694 2.242 50.903 2.278 51.12 2.278 c
+51.392 2.278 51.627 2.227 51.825 2.131 c
+52.031 2.043 52.197 1.911 52.325 1.735 c
+52.461 1.565 52.56 1.359 52.619 1.117 c
+52.685 0.881 52.722 0.617 52.722 0.324 c
+52.722 0.309 l
+50.356 0.309 l
+50.356 0.162 50.37 0.022 50.4 -0.103 c
+50.437 -0.231 50.491 -0.345 50.561 -0.441 c
+50.628 -0.53 50.712 -0.599 50.811 -0.647 c
+50.907 -0.698 51.021 -0.721 51.149 -0.721 c
+51.303 -0.721 51.443 -0.688 51.561 -0.617 c
+51.686 -0.551 51.774 -0.449 51.825 -0.309 c
+52.664 -0.382 l
+52.633 -0.482 52.579 -0.588 52.502 -0.706 c
+52.421 -0.816 52.318 -0.919 52.193 -1.014 c
+52.076 -1.103 51.921 -1.176 51.737 -1.235 c
+51.561 -1.294 51.347 -1.323 51.106 -1.323 c
+51.106 1.705 m
+51.017 1.705 50.929 1.691 50.84 1.66 c
+50.752 1.631 50.672 1.58 50.605 1.514 c
+50.536 1.444 50.477 1.356 50.429 1.249 c
+50.389 1.139 50.37 1.014 50.37 0.867 c
+51.84 0.867 l
+51.84 1.003 51.814 1.124 51.767 1.234 c
+51.727 1.341 51.671 1.429 51.605 1.5 c
+51.546 1.565 51.473 1.617 51.384 1.646 c
+51.297 1.683 51.201 1.705 51.106 1.705 c
+54.773 -1.264 m
+54.773 0.852 l
+54.773 1.018 54.765 1.153 54.758 1.264 c
+54.747 1.371 54.728 1.455 54.699 1.514 c
+54.677 1.58 54.648 1.631 54.611 1.66 c
+54.582 1.691 54.541 1.705 54.493 1.705 c
+54.435 1.705 54.379 1.675 54.331 1.617 c
+54.291 1.565 54.258 1.492 54.229 1.396 c
+54.2 1.308 54.173 1.194 54.156 1.058 c
+54.144 0.918 54.14 0.768 54.14 0.602 c
+54.14 -1.264 l
+53.391 -1.264 l
+53.391 1.469 l
+53.391 1.705 l
+53.391 1.926 l
+53.391 2.003 53.383 2.065 53.377 2.117 c
+53.377 2.219 l
+54.052 2.219 l
+54.052 2.131 l
+54.052 1.984 l
+54.06 1.926 54.067 1.866 54.067 1.808 c
+54.067 1.646 l
+54.082 1.646 l
+54.1 1.735 54.129 1.812 54.17 1.881 c
+54.206 1.959 54.251 2.028 54.302 2.087 c
+54.361 2.146 54.427 2.19 54.508 2.219 c
+54.585 2.256 54.673 2.278 54.773 2.278 c
+54.956 2.278 55.096 2.223 55.184 2.117 c
+55.28 2.017 55.349 1.859 55.39 1.646 c
+55.405 1.646 l
+55.442 1.741 55.482 1.83 55.522 1.911 c
+55.57 1.988 55.625 2.05 55.684 2.102 c
+55.743 2.161 55.809 2.205 55.889 2.234 c
+55.966 2.263 56.055 2.278 56.155 2.278 c
+56.29 2.278 56.404 2.252 56.492 2.205 c
+56.581 2.153 56.647 2.08 56.698 1.984 c
+56.757 1.885 56.793 1.756 56.816 1.602 c
+56.845 1.455 56.86 1.271 56.86 1.058 c
+56.86 -1.264 l
+56.14 -1.264 l
+56.14 0.852 l
+56.14 1.018 56.132 1.153 56.125 1.264 c
+56.114 1.371 56.095 1.455 56.066 1.514 c
+56.045 1.58 56.014 1.631 55.978 1.66 c
+55.949 1.691 55.908 1.705 55.86 1.705 c
+55.743 1.705 55.648 1.617 55.581 1.44 c
+55.522 1.271 55.493 1.014 55.493 0.661 c
+55.493 -1.264 l
+h
+60.876 0.484 m
+60.876 0.209 60.839 -0.04 60.774 -0.264 c
+60.704 -0.482 60.601 -0.669 60.465 -0.823 c
+60.325 -0.981 60.149 -1.103 59.935 -1.191 c
+59.719 -1.279 59.465 -1.323 59.172 -1.323 c
+58.896 -1.323 58.649 -1.279 58.436 -1.191 c
+58.231 -1.103 58.058 -0.981 57.922 -0.823 c
+57.782 -0.669 57.68 -0.482 57.613 -0.264 c
+57.543 -0.04 57.51 0.209 57.51 0.484 c
+57.51 0.738 57.539 0.974 57.599 1.19 c
+57.665 1.415 57.768 1.606 57.907 1.764 c
+58.043 1.929 58.22 2.057 58.436 2.146 c
+58.649 2.234 58.906 2.278 59.201 2.278 c
+59.513 2.278 59.774 2.234 59.98 2.146 c
+60.193 2.057 60.365 1.929 60.494 1.764 c
+60.63 1.606 60.729 1.415 60.788 1.19 c
+60.847 0.974 60.876 0.738 60.876 0.484 c
+59.921 0.484 m
+59.921 0.691 59.906 0.867 59.877 1.014 c
+59.855 1.161 59.818 1.282 59.76 1.382 c
+59.7 1.477 59.627 1.547 59.538 1.587 c
+59.451 1.635 59.34 1.66 59.216 1.66 c
+58.95 1.66 58.76 1.562 58.642 1.367 c
+58.524 1.18 58.466 0.885 58.466 0.484 c
+58.466 0.062 58.524 -0.243 58.642 -0.426 c
+58.76 -0.614 58.936 -0.706 59.172 -0.706 c
+59.297 -0.706 59.411 -0.688 59.509 -0.647 c
+59.605 -0.599 59.686 -0.526 59.744 -0.426 c
+59.81 -0.331 59.855 -0.206 59.877 -0.059 c
+59.906 0.088 59.921 0.268 59.921 0.484 c
+62.335 1.602 m
+61.792 1.602 l
+61.792 2.219 l
+62.379 2.219 l
+62.659 3.116 l
+63.232 3.116 l
+63.232 2.219 l
+64.467 2.219 l
+64.467 1.602 l
+63.232 1.602 l
+63.232 -0.103 l
+63.232 -0.324 l
+63.239 -0.393 63.261 -0.456 63.291 -0.515 c
+63.328 -0.566 63.382 -0.611 63.452 -0.647 c
+63.53 -0.676 63.644 -0.691 63.791 -0.691 c
+63.926 -0.691 64.062 -0.688 64.202 -0.676 c
+64.338 -0.658 64.471 -0.632 64.599 -0.603 c
+64.599 -1.205 l
+64.518 -1.216 64.441 -1.231 64.364 -1.249 c
+64.283 -1.261 64.205 -1.268 64.128 -1.279 c
+64.047 -1.286 63.96 -1.294 63.864 -1.294 c
+63.776 -1.301 63.677 -1.309 63.57 -1.309 c
+63.382 -1.309 63.221 -1.294 63.085 -1.264 c
+62.956 -1.228 62.842 -1.183 62.746 -1.132 c
+62.659 -1.085 62.586 -1.025 62.526 -0.956 c
+62.468 -0.879 62.424 -0.802 62.395 -0.721 c
+62.364 -0.632 62.343 -0.544 62.335 -0.456 c
+62.324 -0.36 62.32 -0.264 62.32 -0.177 c
+h
+67.351 -1.323 m
+67.094 -1.323 66.866 -1.286 66.661 -1.22 c
+66.455 -1.143 66.278 -1.029 66.131 -0.882 c
+65.984 -0.728 65.867 -0.537 65.778 -0.309 c
+65.697 -0.085 65.661 0.18 65.661 0.484 c
+65.661 0.816 65.705 1.095 65.793 1.323 c
+65.888 1.558 66.017 1.741 66.175 1.881 c
+66.341 2.017 66.528 2.117 66.734 2.175 c
+66.94 2.242 67.149 2.278 67.366 2.278 c
+67.638 2.278 67.873 2.227 68.072 2.131 c
+68.277 2.043 68.443 1.911 68.571 1.735 c
+68.707 1.565 68.807 1.359 68.865 1.117 c
+68.932 0.881 68.968 0.617 68.968 0.324 c
+68.968 0.309 l
+66.602 0.309 l
+66.602 0.162 66.617 0.022 66.646 -0.103 c
+66.682 -0.231 66.738 -0.345 66.808 -0.441 c
+66.873 -0.53 66.958 -0.599 67.058 -0.647 c
+67.153 -0.698 67.267 -0.721 67.396 -0.721 c
+67.55 -0.721 67.689 -0.688 67.807 -0.617 c
+67.932 -0.551 68.02 -0.449 68.072 -0.309 c
+68.909 -0.382 l
+68.88 -0.482 68.824 -0.588 68.747 -0.706 c
+68.666 -0.816 68.564 -0.919 68.439 -1.014 c
+68.321 -1.103 68.167 -1.176 67.983 -1.235 c
+67.807 -1.294 67.594 -1.323 67.351 -1.323 c
+67.351 1.705 m
+67.263 1.705 67.175 1.691 67.087 1.66 c
+66.999 1.631 66.918 1.58 66.852 1.514 c
+66.782 1.444 66.723 1.356 66.675 1.249 c
+66.634 1.139 66.617 1.014 66.617 0.867 c
+68.086 0.867 l
+68.086 1.003 68.061 1.124 68.013 1.234 c
+67.972 1.341 67.918 1.429 67.851 1.5 c
+67.792 1.565 67.719 1.617 67.631 1.646 c
+67.542 1.683 67.447 1.705 67.351 1.705 c
+70.221 -2.631 m
+70.221 -2.014 l
+71.294 -2.014 l
+71.294 2.896 l
+70.221 2.896 l
+70.221 3.513 l
+72.147 3.513 l
+72.147 -2.631 l
+h
+f
+Q
+q 1 0 0 1 46.321 201.1066 cm
+0 0 m
+-1.808 0 l
+-1.808 -2.367 l
+-2.484 -2.367 l
+-2.484 2.983 l
+0.309 2.983 l
+0.309 2.41 l
+-1.808 2.41 l
+-1.808 0.573 l
+0 0.573 l
+h
+2.396 -2.44 m
+1.897 -2.44 1.514 -2.294 1.249 -1.999 c
+0.985 -1.706 0.852 -1.272 0.852 -0.691 c
+0.852 -0.221 l
+0.852 0.374 0.977 0.841 1.234 1.176 c
+1.5 1.517 1.859 1.69 2.323 1.69 c
+2.782 1.69 3.123 1.535 3.351 1.234 c
+3.586 0.941 3.707 0.477 3.719 -0.148 c
+3.719 -0.574 l
+1.5 -0.574 l
+1.5 -0.662 l
+1.5 -1.096 1.577 -1.408 1.735 -1.603 c
+1.899 -1.79 2.132 -1.881 2.425 -1.881 c
+2.62 -1.881 2.793 -1.849 2.94 -1.779 c
+3.087 -1.702 3.223 -1.584 3.351 -1.426 c
+3.69 -1.838 l
+3.403 -2.242 2.973 -2.44 2.396 -2.44 c
+2.323 1.132 m
+2.047 1.132 1.845 1.036 1.72 0.852 c
+1.591 0.665 1.517 0.374 1.5 -0.015 c
+3.072 -0.015 l
+3.072 0.073 l
+3.05 0.455 2.984 0.723 2.866 0.881 c
+2.749 1.047 2.564 1.132 2.323 1.132 c
+5.35 2.572 m
+5.35 1.616 l
+5.953 1.616 l
+5.953 1.087 l
+5.35 1.087 l
+5.35 -1.382 l
+5.35 -1.54 5.373 -1.658 5.424 -1.735 c
+5.483 -1.816 5.571 -1.852 5.689 -1.852 c
+5.776 -1.852 5.865 -1.838 5.953 -1.808 c
+5.953 -2.367 l
+5.806 -2.415 5.652 -2.44 5.498 -2.44 c
+5.24 -2.44 5.045 -2.349 4.91 -2.161 c
+4.77 -1.977 4.704 -1.717 4.704 -1.382 c
+4.704 1.087 l
+4.101 1.087 l
+4.101 1.616 l
+4.704 1.616 l
+4.704 2.572 l
+h
+8.099 -1.881 m
+8.312 -1.881 8.485 -1.819 8.613 -1.691 c
+8.75 -1.555 8.823 -1.364 8.834 -1.118 c
+9.452 -1.118 l
+9.429 -1.5 9.294 -1.819 9.04 -2.073 c
+8.783 -2.319 8.47 -2.44 8.099 -2.44 c
+7.607 -2.44 7.231 -2.29 6.967 -1.985 c
+6.71 -1.673 6.585 -1.206 6.585 -0.588 c
+6.585 -0.148 l
+6.585 0.448 6.71 0.903 6.967 1.219 c
+7.231 1.532 7.607 1.69 8.099 1.69 c
+8.5 1.69 8.819 1.558 9.055 1.294 c
+9.297 1.036 9.429 0.69 9.452 0.249 c
+8.834 0.249 l
+8.812 0.544 8.739 0.764 8.613 0.911 c
+8.496 1.058 8.324 1.132 8.099 1.132 c
+7.805 1.132 7.588 1.032 7.453 0.837 c
+7.312 0.65 7.239 0.341 7.231 -0.088 c
+7.231 -0.603 l
+7.231 -1.073 7.298 -1.408 7.437 -1.603 c
+7.584 -1.79 7.805 -1.881 8.099 -1.881 c
+10.848 1.205 m
+11.102 1.529 11.421 1.69 11.803 1.69 c
+12.509 1.69 12.866 1.219 12.876 0.278 c
+12.876 -2.367 l
+12.23 -2.367 l
+12.23 0.249 l
+12.23 0.562 12.174 0.783 12.068 0.911 c
+11.958 1.036 11.803 1.102 11.597 1.102 c
+11.439 1.102 11.293 1.047 11.156 0.941 c
+11.028 0.83 10.925 0.694 10.848 0.529 c
+10.848 -2.367 l
+10.201 -2.367 l
+10.201 3.278 l
+10.848 3.278 l
+h
+16.933 -1.881 m
+17.146 -1.881 17.319 -1.819 17.448 -1.691 c
+17.583 -1.555 17.657 -1.364 17.668 -1.118 c
+18.285 -1.118 l
+18.264 -1.5 18.127 -1.819 17.874 -2.073 c
+17.616 -2.319 17.304 -2.44 16.933 -2.44 c
+16.44 -2.44 16.066 -2.29 15.802 -1.985 c
+15.544 -1.673 15.419 -1.206 15.419 -0.588 c
+15.419 -0.148 l
+15.419 0.448 15.544 0.903 15.802 1.219 c
+16.066 1.532 16.44 1.69 16.933 1.69 c
+17.334 1.69 17.654 1.558 17.889 1.294 c
+18.131 1.036 18.264 0.69 18.285 0.249 c
+17.668 0.249 l
+17.646 0.544 17.573 0.764 17.448 0.911 c
+17.33 1.058 17.157 1.132 16.933 1.132 c
+16.639 1.132 16.422 1.032 16.286 0.837 c
+16.147 0.65 16.073 0.341 16.066 -0.088 c
+16.066 -0.603 l
+16.066 -1.073 16.132 -1.408 16.272 -1.603 c
+16.419 -1.79 16.639 -1.881 16.933 -1.881 c
+19.682 1.205 m
+19.935 1.529 20.255 1.69 20.637 1.69 c
+21.343 1.69 21.699 1.219 21.71 0.278 c
+21.71 -2.367 l
+21.063 -2.367 l
+21.063 0.249 l
+21.063 0.562 21.009 0.783 20.902 0.911 c
+20.791 1.036 20.637 1.102 20.432 1.102 c
+20.274 1.102 20.126 1.047 19.991 0.941 c
+19.862 0.83 19.759 0.694 19.682 0.529 c
+19.682 -2.367 l
+19.035 -2.367 l
+19.035 3.278 l
+19.682 3.278 l
+h
+24.709 -2.367 m
+24.669 -2.278 24.643 -2.132 24.635 -1.926 c
+24.4 -2.272 24.106 -2.44 23.754 -2.44 c
+23.39 -2.44 23.106 -2.345 22.901 -2.147 c
+22.703 -1.941 22.607 -1.654 22.607 -1.279 c
+22.607 -0.879 22.743 -0.559 23.019 -0.324 c
+23.291 -0.081 23.665 0.043 24.136 0.043 c
+24.621 0.043 l
+24.621 0.47 l
+24.621 0.706 24.566 0.87 24.459 0.97 c
+24.349 1.076 24.187 1.132 23.974 1.132 c
+23.775 1.132 23.614 1.072 23.489 0.955 c
+23.372 0.837 23.312 0.69 23.312 0.514 c
+22.666 0.514 l
+22.666 0.708 22.725 0.9 22.842 1.087 c
+22.967 1.271 23.129 1.418 23.328 1.529 c
+23.534 1.635 23.761 1.69 24.018 1.69 c
+24.419 1.69 24.724 1.587 24.93 1.381 c
+25.142 1.176 25.257 0.881 25.267 0.5 c
+25.267 -1.515 l
+25.267 -1.819 25.304 -2.084 25.385 -2.309 c
+25.385 -2.367 l
+h
+23.842 -1.852 m
+24.007 -1.852 24.158 -1.808 24.297 -1.721 c
+24.444 -1.632 24.551 -1.522 24.621 -1.382 c
+24.621 -0.441 l
+24.253 -0.441 l
+23.937 -0.441 23.694 -0.511 23.518 -0.647 c
+23.342 -0.776 23.254 -0.963 23.254 -1.206 c
+23.254 -1.434 23.298 -1.599 23.386 -1.706 c
+23.474 -1.804 23.625 -1.852 23.842 -1.852 c
+26.884 1.616 m
+26.9 1.176 l
+27.153 1.517 27.476 1.69 27.869 1.69 c
+28.575 1.69 28.932 1.219 28.943 0.278 c
+28.943 -2.367 l
+28.296 -2.367 l
+28.296 0.249 l
+28.296 0.562 28.24 0.783 28.134 0.911 c
+28.024 1.036 27.869 1.102 27.663 1.102 c
+27.505 1.102 27.359 1.047 27.222 0.941 c
+27.094 0.83 26.991 0.694 26.914 0.529 c
+26.914 -2.367 l
+26.267 -2.367 l
+26.267 1.616 l
+h
+29.78 -0.192 m
+29.78 0.426 29.89 0.889 30.119 1.205 c
+30.343 1.529 30.677 1.69 31.118 1.69 c
+31.519 1.69 31.823 1.514 32.029 1.161 c
+32.074 1.616 l
+32.662 1.616 l
+32.662 -2.411 l
+32.662 -2.899 32.533 -3.278 32.279 -3.543 c
+32.022 -3.807 31.669 -3.94 31.22 -3.94 c
+31.022 -3.94 30.802 -3.888 30.559 -3.793 c
+30.313 -3.693 30.133 -3.572 30.015 -3.425 c
+30.28 -2.984 l
+30.545 -3.249 30.842 -3.381 31.176 -3.381 c
+31.713 -3.381 31.989 -3.088 32 -2.5 c
+32 -1.97 l
+31.794 -2.286 31.492 -2.44 31.103 -2.44 c
+30.692 -2.44 30.368 -2.29 30.133 -1.985 c
+29.905 -1.673 29.788 -1.22 29.78 -0.632 c
+h
+30.441 -0.574 m
+30.441 -1.015 30.504 -1.345 30.632 -1.559 c
+30.757 -1.764 30.975 -1.867 31.28 -1.867 c
+31.603 -1.867 31.842 -1.702 32 -1.368 c
+32 0.617 l
+31.831 0.941 31.592 1.102 31.28 1.102 c
+30.985 1.102 30.769 0.999 30.632 0.793 c
+30.504 0.588 30.441 0.264 30.441 -0.177 c
+h
+35.043 -2.44 m
+34.543 -2.44 34.16 -2.294 33.896 -1.999 c
+33.631 -1.706 33.499 -1.272 33.499 -0.691 c
+33.499 -0.221 l
+33.499 0.374 33.624 0.841 33.882 1.176 c
+34.146 1.517 34.506 1.69 34.969 1.69 c
+35.428 1.69 35.77 1.535 35.998 1.234 c
+36.234 0.941 36.354 0.477 36.365 -0.148 c
+36.365 -0.574 l
+34.146 -0.574 l
+34.146 -0.662 l
+34.146 -1.096 34.223 -1.408 34.381 -1.603 c
+34.547 -1.79 34.778 -1.881 35.072 -1.881 c
+35.266 -1.881 35.44 -1.849 35.586 -1.779 c
+35.733 -1.702 35.869 -1.584 35.998 -1.426 c
+36.336 -1.838 l
+36.049 -2.242 35.619 -2.44 35.043 -2.44 c
+34.969 1.132 m
+34.694 1.132 34.491 1.036 34.366 0.852 c
+34.237 0.665 34.164 0.374 34.146 -0.015 c
+35.719 -0.015 l
+35.719 0.073 l
+35.696 0.455 35.631 0.723 35.513 0.881 c
+35.395 1.047 35.212 1.132 34.969 1.132 c
+39.085 -1.353 m
+39.085 -1.206 39.029 -1.085 38.923 -0.985 c
+38.813 -0.89 38.607 -0.772 38.306 -0.632 c
+37.96 -0.485 37.718 -0.364 37.57 -0.265 c
+37.424 -0.158 37.313 -0.04 37.248 0.087 c
+37.177 0.213 37.144 0.371 37.144 0.558 c
+37.144 0.881 37.262 1.15 37.497 1.367 c
+37.732 1.579 38.034 1.69 38.409 1.69 c
+38.79 1.69 39.099 1.576 39.334 1.352 c
+39.569 1.124 39.687 0.837 39.687 0.484 c
+39.041 0.484 l
+39.041 0.661 38.981 0.812 38.864 0.941 c
+38.746 1.065 38.592 1.132 38.409 1.132 c
+38.21 1.132 38.059 1.076 37.953 0.97 c
+37.842 0.87 37.791 0.738 37.791 0.573 c
+37.791 0.444 37.828 0.338 37.909 0.249 c
+37.986 0.168 38.177 0.066 38.482 -0.059 c
+38.96 -0.246 39.291 -0.434 39.467 -0.618 c
+39.643 -0.794 39.731 -1.022 39.731 -1.294 c
+39.731 -1.646 39.606 -1.926 39.364 -2.132 c
+39.129 -2.338 38.813 -2.44 38.424 -2.44 c
+38 -2.44 37.663 -2.323 37.409 -2.087 c
+37.152 -1.845 37.027 -1.54 37.027 -1.176 c
+37.674 -1.176 l
+37.681 -1.405 37.751 -1.58 37.88 -1.706 c
+38.004 -1.823 38.188 -1.881 38.424 -1.881 c
+38.636 -1.881 38.798 -1.834 38.908 -1.735 c
+39.026 -1.64 39.085 -1.511 39.085 -1.353 c
+42.584 -2.367 m
+42.584 1.087 l
+42.054 1.087 l
+42.054 1.616 l
+42.584 1.616 l
+42.584 2.072 l
+42.584 2.472 42.679 2.785 42.877 3.013 c
+43.083 3.237 43.362 3.351 43.715 3.351 c
+43.851 3.351 43.983 3.329 44.111 3.293 c
+44.082 2.748 l
+43.983 2.767 43.884 2.778 43.789 2.778 c
+43.413 2.778 43.23 2.513 43.23 1.984 c
+43.23 1.616 l
+43.906 1.616 l
+43.906 1.087 l
+43.23 1.087 l
+43.23 -2.367 l
+h
+46.316 0.999 m
+46.228 1.018 46.129 1.028 46.023 1.028 c
+45.688 1.028 45.453 0.845 45.317 0.484 c
+45.317 -2.367 l
+44.67 -2.367 l
+44.67 1.616 l
+45.302 1.616 l
+45.317 1.205 l
+45.493 1.529 45.736 1.69 46.052 1.69 c
+46.158 1.69 46.247 1.668 46.316 1.631 c
+h
+46.758 -0.192 m
+46.758 0.386 46.894 0.841 47.169 1.176 c
+47.452 1.517 47.823 1.69 48.286 1.69 c
+48.745 1.69 49.113 1.521 49.389 1.19 c
+49.672 0.866 49.819 0.419 49.83 -0.148 c
+49.83 -0.574 l
+49.83 -1.143 49.686 -1.599 49.404 -1.941 c
+49.128 -2.275 48.76 -2.44 48.301 -2.44 c
+47.838 -2.44 47.467 -2.278 47.184 -1.956 c
+46.908 -1.625 46.765 -1.183 46.758 -0.632 c
+h
+47.404 -0.574 m
+47.404 -0.978 47.482 -1.294 47.639 -1.529 c
+47.805 -1.764 48.026 -1.881 48.301 -1.881 c
+48.867 -1.881 49.161 -1.47 49.183 -0.647 c
+49.183 -0.192 l
+49.183 0.209 49.098 0.529 48.934 0.764 c
+48.775 1.007 48.558 1.132 48.286 1.132 c
+48.022 1.132 47.805 1.007 47.639 0.764 c
+47.482 0.529 47.404 0.209 47.404 -0.192 c
+h
+51.285 1.616 m
+51.299 1.249 l
+51.542 1.543 51.862 1.69 52.255 1.69 c
+52.696 1.69 53.005 1.491 53.181 1.102 c
+53.435 1.491 53.784 1.69 54.224 1.69 c
+54.96 1.69 55.334 1.227 55.357 0.309 c
+55.357 -2.367 l
+54.71 -2.367 l
+54.71 0.249 l
+54.71 0.544 54.655 0.756 54.548 0.897 c
+54.449 1.032 54.276 1.102 54.033 1.102 c
+53.835 1.102 53.674 1.021 53.549 0.866 c
+53.431 0.72 53.362 0.529 53.343 0.294 c
+53.343 -2.367 l
+52.681 -2.367 l
+52.681 0.278 l
+52.681 0.826 52.461 1.102 52.02 1.102 c
+51.685 1.102 51.45 0.941 51.315 0.617 c
+51.315 -2.367 l
+50.667 -2.367 l
+50.667 1.616 l
+h
+58.899 2.572 m
+58.899 1.616 l
+59.502 1.616 l
+59.502 1.087 l
+58.899 1.087 l
+58.899 -1.382 l
+58.899 -1.54 58.921 -1.658 58.972 -1.735 c
+59.031 -1.816 59.12 -1.852 59.237 -1.852 c
+59.325 -1.852 59.413 -1.838 59.502 -1.808 c
+59.502 -2.367 l
+59.355 -2.415 59.201 -2.44 59.046 -2.44 c
+58.789 -2.44 58.594 -2.349 58.458 -2.161 c
+58.318 -1.977 58.252 -1.717 58.252 -1.382 c
+58.252 1.087 l
+57.649 1.087 l
+57.649 1.616 l
+58.252 1.616 l
+58.252 2.572 l
+h
+60.913 1.205 m
+61.166 1.529 61.486 1.69 61.869 1.69 c
+62.574 1.69 62.93 1.219 62.941 0.278 c
+62.941 -2.367 l
+62.295 -2.367 l
+62.295 0.249 l
+62.295 0.562 62.239 0.783 62.133 0.911 c
+62.023 1.036 61.869 1.102 61.663 1.102 c
+61.505 1.102 61.358 1.047 61.221 0.941 c
+61.093 0.83 60.99 0.694 60.913 0.529 c
+60.913 -2.367 l
+60.266 -2.367 l
+60.266 3.278 l
+60.913 3.278 l
+h
+65.322 -2.44 m
+64.823 -2.44 64.441 -2.294 64.176 -1.999 c
+63.911 -1.706 63.779 -1.272 63.779 -0.691 c
+63.779 -0.221 l
+63.779 0.374 63.904 0.841 64.161 1.176 c
+64.426 1.517 64.786 1.69 65.249 1.69 c
+65.709 1.69 66.05 1.535 66.278 1.234 c
+66.513 0.941 66.634 0.477 66.646 -0.148 c
+66.646 -0.574 l
+64.426 -0.574 l
+64.426 -0.662 l
+64.426 -1.096 64.503 -1.408 64.661 -1.603 c
+64.826 -1.79 65.058 -1.881 65.352 -1.881 c
+65.547 -1.881 65.719 -1.849 65.867 -1.779 c
+66.014 -1.702 66.149 -1.584 66.278 -1.426 c
+66.616 -1.838 l
+66.33 -2.242 65.9 -2.44 65.322 -2.44 c
+65.249 1.132 m
+64.973 1.132 64.771 1.036 64.647 0.852 c
+64.518 0.665 64.444 0.374 64.426 -0.015 c
+65.999 -0.015 l
+65.999 0.073 l
+65.977 0.455 65.91 0.723 65.792 0.881 c
+65.675 1.047 65.491 1.132 65.249 1.132 c
+f
+Q
+q 1 0 0 1 117.3177 201.7086 cm
+0 0 m
+-0.339 0.029 l
+-0.625 0.029 -0.817 -0.095 -0.912 -0.338 c
+-0.912 -2.969 l
+-1.956 -2.969 l
+-1.956 1.014 l
+-0.985 1.014 l
+-0.956 0.574 l
+-0.79 0.915 -0.559 1.088 -0.265 1.088 c
+-0.148 1.088 -0.055 1.066 0.014 1.029 c
+h
+2.072 -3.042 m
+1.543 -3.042 1.124 -2.888 0.823 -2.572 c
+0.529 -2.248 0.382 -1.789 0.382 -1.19 c
+0.382 -0.881 l
+0.382 -0.257 0.517 0.228 0.793 0.574 c
+1.065 0.915 1.458 1.088 1.969 1.088 c
+2.469 1.088 2.84 0.927 3.087 0.603 c
+3.34 0.279 3.472 -0.198 3.484 -0.823 c
+3.484 -1.323 l
+1.411 -1.323 l
+1.429 -1.617 1.492 -1.833 1.602 -1.97 c
+1.72 -2.109 1.899 -2.175 2.146 -2.175 c
+2.487 -2.175 2.778 -2.057 3.013 -1.822 c
+3.424 -2.454 l
+3.296 -2.631 3.108 -2.774 2.866 -2.881 c
+2.62 -2.988 2.356 -3.042 2.072 -3.042 c
+1.425 -0.602 m
+2.454 -0.602 l
+2.454 -0.5 l
+2.454 -0.264 2.414 -0.088 2.337 0.029 c
+2.267 0.154 2.138 0.221 1.955 0.221 c
+1.778 0.221 1.646 0.151 1.558 0.015 c
+1.477 -0.114 1.433 -0.32 1.425 -0.602 c
+5.041 1.014 m
+5.071 0.647 l
+5.306 0.941 5.614 1.088 5.997 1.088 c
+6.397 1.088 6.676 0.904 6.834 0.544 c
+7.07 0.904 7.397 1.088 7.819 1.088 c
+8.514 1.088 8.866 0.603 8.878 -0.367 c
+8.878 -2.969 l
+7.849 -2.969 l
+7.849 -0.426 l
+7.849 -0.202 7.812 -0.04 7.746 0.059 c
+7.687 0.154 7.577 0.206 7.422 0.206 c
+7.224 0.206 7.085 0.088 6.996 -0.147 c
+6.996 -2.969 l
+5.953 -2.969 l
+5.953 -0.441 l
+5.953 -0.206 5.924 -0.04 5.865 0.059 c
+5.805 0.154 5.695 0.206 5.541 0.206 c
+5.365 0.206 5.221 0.11 5.115 -0.073 c
+5.115 -2.969 l
+4.072 -2.969 l
+4.072 1.014 l
+h
+9.539 -0.852 m
+9.539 -0.246 9.679 0.228 9.965 0.574 c
+10.248 0.915 10.642 1.088 11.141 1.088 c
+11.648 1.088 12.045 0.915 12.332 0.574 c
+12.615 0.228 12.758 -0.246 12.758 -0.852 c
+12.758 -1.117 l
+12.758 -1.716 12.615 -2.186 12.332 -2.528 c
+12.045 -2.874 11.648 -3.042 11.141 -3.042 c
+10.63 -3.042 10.234 -2.874 9.951 -2.528 c
+9.676 -2.186 9.539 -1.712 9.539 -1.103 c
+h
+10.583 -1.117 m
+10.583 -1.822 10.767 -2.175 11.141 -2.175 c
+11.494 -2.175 11.685 -1.881 11.715 -1.294 c
+11.715 -0.852 l
+11.715 -0.492 11.663 -0.22 11.568 -0.044 c
+11.469 0.133 11.326 0.221 11.141 0.221 c
+10.965 0.221 10.825 0.133 10.73 -0.044 c
+10.63 -0.22 10.583 -0.492 10.583 -0.852 c
+h
+14.611 1.985 m
+14.611 1.014 l
+15.139 1.014 l
+15.139 0.221 l
+14.611 0.221 l
+14.611 -1.749 l
+14.611 -1.907 14.628 -2.013 14.669 -2.072 c
+14.717 -2.131 14.802 -2.161 14.919 -2.161 c
+15.025 -2.161 15.11 -2.153 15.169 -2.131 c
+15.169 -2.94 l
+14.993 -3.006 14.802 -3.042 14.596 -3.042 c
+13.92 -3.042 13.574 -2.657 13.566 -1.881 c
+13.566 0.221 l
+13.111 0.221 l
+13.111 1.014 l
+13.566 1.014 l
+13.566 1.985 l
+h
+17.315 -3.042 m
+16.786 -3.042 16.367 -2.888 16.066 -2.572 c
+15.771 -2.248 15.625 -1.789 15.625 -1.19 c
+15.625 -0.881 l
+15.625 -0.257 15.761 0.228 16.037 0.574 c
+16.309 0.915 16.702 1.088 17.213 1.088 c
+17.712 1.088 18.083 0.927 18.329 0.603 c
+18.583 0.279 18.715 -0.198 18.726 -0.823 c
+18.726 -1.323 l
+16.654 -1.323 l
+16.672 -1.617 16.735 -1.833 16.845 -1.97 c
+16.962 -2.109 17.142 -2.175 17.389 -2.175 c
+17.73 -2.175 18.021 -2.057 18.256 -1.822 c
+18.667 -2.454 l
+18.539 -2.631 18.351 -2.774 18.109 -2.881 c
+17.863 -2.988 17.598 -3.042 17.315 -3.042 c
+16.668 -0.602 m
+17.697 -0.602 l
+17.697 -0.5 l
+17.697 -0.264 17.657 -0.088 17.58 0.029 c
+17.51 0.154 17.381 0.221 17.198 0.221 c
+17.021 0.221 16.889 0.151 16.801 0.015 c
+16.72 -0.114 16.676 -0.32 16.668 -0.602 c
+f
+Q
+q 1 0 0 1 140.4975 198.7397 cm
+0 0 m
+-0.04 0.088 -0.066 0.235 -0.073 0.441 c
+-0.309 0.095 -0.602 -0.073 -0.955 -0.073 c
+-1.319 -0.073 -1.602 0.022 -1.808 0.22 c
+-2.007 0.426 -2.102 0.713 -2.102 1.088 c
+-2.102 1.488 -1.966 1.808 -1.691 2.043 c
+-1.419 2.286 -1.043 2.41 -0.573 2.41 c
+-0.087 2.41 l
+-0.087 2.837 l
+-0.087 3.072 -0.143 3.237 -0.249 3.337 c
+-0.36 3.443 -0.521 3.499 -0.735 3.499 c
+-0.933 3.499 -1.095 3.439 -1.22 3.322 c
+-1.338 3.204 -1.396 3.057 -1.396 2.881 c
+-2.043 2.881 l
+-2.043 3.075 -1.984 3.267 -1.866 3.454 c
+-1.741 3.638 -1.579 3.785 -1.382 3.896 c
+-1.176 4.002 -0.948 4.056 -0.691 4.056 c
+-0.29 4.056 0.015 3.954 0.221 3.748 c
+0.434 3.543 0.548 3.248 0.559 2.866 c
+0.559 0.852 l
+0.559 0.548 0.595 0.283 0.676 0.058 c
+0.676 0 l
+h
+-0.867 0.515 m
+-0.702 0.515 -0.551 0.559 -0.411 0.646 c
+-0.264 0.735 -0.158 0.845 -0.087 0.985 c
+-0.087 1.926 l
+-0.455 1.926 l
+-0.771 1.926 -1.014 1.856 -1.19 1.72 c
+-1.367 1.591 -1.455 1.404 -1.455 1.161 c
+-1.455 0.933 -1.411 0.768 -1.323 0.661 c
+-1.234 0.563 -1.084 0.515 -0.867 0.515 c
+2.176 3.983 m
+2.19 3.543 l
+2.444 3.884 2.768 4.056 3.161 4.056 c
+3.866 4.056 4.223 3.586 4.233 2.645 c
+4.233 0 l
+3.587 0 l
+3.587 2.616 l
+3.587 2.929 3.532 3.15 3.425 3.278 c
+3.315 3.403 3.161 3.469 2.955 3.469 c
+2.797 3.469 2.65 3.414 2.514 3.308 c
+2.385 3.197 2.282 3.061 2.205 2.896 c
+2.205 0 l
+1.559 0 l
+1.559 3.983 l
+h
+5.072 2.175 m
+5.072 2.782 5.182 3.248 5.409 3.572 c
+5.644 3.896 5.972 4.056 6.394 4.056 c
+6.776 4.056 7.074 3.898 7.291 3.586 c
+7.291 5.644 l
+7.938 5.644 l
+7.938 0 l
+7.35 0 l
+7.306 0.426 l
+7.1 0.092 6.795 -0.073 6.394 -0.073 c
+5.983 -0.073 5.659 0.081 5.424 0.397 c
+5.189 0.721 5.072 1.176 5.072 1.764 c
+h
+5.718 1.793 m
+5.718 1.352 5.781 1.022 5.909 0.808 c
+6.045 0.603 6.265 0.5 6.571 0.5 c
+6.894 0.5 7.133 0.661 7.291 0.985 c
+7.291 2.998 l
+7.122 3.31 6.883 3.469 6.571 3.469 c
+6.265 3.469 6.045 3.366 5.909 3.16 c
+5.781 2.955 5.718 2.631 5.718 2.19 c
+h
+11.275 3.983 m
+11.289 3.616 l
+11.532 3.91 11.851 4.056 12.245 4.056 c
+12.686 4.056 12.994 3.858 13.17 3.469 c
+13.424 3.858 13.773 4.056 14.215 4.056 c
+14.949 4.056 15.324 3.594 15.346 2.675 c
+15.346 0 l
+14.699 0 l
+14.699 2.616 l
+14.699 2.911 14.644 3.123 14.537 3.263 c
+14.438 3.399 14.265 3.469 14.024 3.469 c
+13.825 3.469 13.663 3.388 13.538 3.233 c
+13.421 3.087 13.351 2.896 13.332 2.66 c
+13.332 0 l
+12.671 0 l
+12.671 2.645 l
+12.671 3.193 12.451 3.469 12.009 3.469 c
+11.675 3.469 11.439 3.308 11.304 2.984 c
+11.304 0 l
+10.657 0 l
+10.657 3.983 l
+h
+17.742 -0.073 m
+17.242 -0.073 16.86 0.073 16.596 0.368 c
+16.331 0.661 16.199 1.095 16.199 1.675 c
+16.199 2.146 l
+16.199 2.741 16.324 3.208 16.581 3.543 c
+16.846 3.884 17.205 4.056 17.668 4.056 c
+18.128 4.056 18.47 3.902 18.697 3.601 c
+18.932 3.308 19.054 2.844 19.065 2.219 c
+19.065 1.793 l
+16.846 1.793 l
+16.846 1.705 l
+16.846 1.271 16.923 0.959 17.081 0.764 c
+17.246 0.577 17.477 0.485 17.771 0.485 c
+17.966 0.485 18.138 0.518 18.286 0.588 c
+18.433 0.665 18.569 0.783 18.697 0.941 c
+19.036 0.529 l
+18.749 0.125 18.319 -0.073 17.742 -0.073 c
+17.668 3.499 m
+17.393 3.499 17.191 3.403 17.066 3.219 c
+16.937 3.032 16.864 2.741 16.846 2.352 c
+18.418 2.352 l
+18.418 2.44 l
+18.396 2.822 18.33 3.09 18.213 3.248 c
+18.095 3.414 17.911 3.499 17.668 3.499 c
+21.49 3.366 m
+21.402 3.385 21.303 3.395 21.196 3.395 c
+20.862 3.395 20.627 3.212 20.49 2.851 c
+20.49 0 l
+19.844 0 l
+19.844 3.983 l
+20.476 3.983 l
+20.49 3.572 l
+20.667 3.896 20.91 4.056 21.226 4.056 c
+21.332 4.056 21.421 4.035 21.49 3.998 c
+h
+21.931 2.175 m
+21.931 2.793 22.042 3.256 22.269 3.572 c
+22.493 3.896 22.828 4.056 23.269 4.056 c
+23.669 4.056 23.975 3.881 24.18 3.528 c
+24.224 3.983 l
+24.812 3.983 l
+24.812 -0.044 l
+24.812 -0.532 24.684 -0.912 24.43 -1.176 c
+24.173 -1.44 23.82 -1.573 23.372 -1.573 c
+23.173 -1.573 22.953 -1.521 22.71 -1.426 c
+22.464 -1.326 22.284 -1.205 22.167 -1.058 c
+22.431 -0.617 l
+22.695 -0.882 22.994 -1.014 23.328 -1.014 c
+23.864 -1.014 24.139 -0.721 24.151 -0.133 c
+24.151 0.397 l
+23.945 0.081 23.644 -0.073 23.254 -0.073 c
+22.842 -0.073 22.519 0.077 22.284 0.382 c
+22.057 0.694 21.939 1.147 21.931 1.735 c
+h
+22.593 1.793 m
+22.593 1.352 22.655 1.022 22.784 0.808 c
+22.909 0.603 23.125 0.5 23.431 0.5 c
+23.754 0.5 23.993 0.665 24.151 0.999 c
+24.151 2.984 l
+23.981 3.308 23.743 3.469 23.431 3.469 c
+23.137 3.469 22.92 3.366 22.784 3.16 c
+22.655 2.955 22.593 2.631 22.593 2.19 c
+h
+27.194 -0.073 m
+26.693 -0.073 26.312 0.073 26.047 0.368 c
+25.783 0.661 25.65 1.095 25.65 1.675 c
+25.65 2.146 l
+25.65 2.741 25.775 3.208 26.032 3.543 c
+26.296 3.884 26.657 4.056 27.12 4.056 c
+27.58 4.056 27.921 3.902 28.149 3.601 c
+28.384 3.308 28.505 2.844 28.517 2.219 c
+28.517 1.793 l
+26.296 1.793 l
+26.296 1.705 l
+26.296 1.271 26.374 0.959 26.532 0.764 c
+26.697 0.577 26.929 0.485 27.223 0.485 c
+27.418 0.485 27.59 0.518 27.738 0.588 c
+27.884 0.665 28.02 0.783 28.149 0.941 c
+28.487 0.529 l
+28.201 0.125 27.771 -0.073 27.194 -0.073 c
+27.12 3.499 m
+26.844 3.499 26.643 3.403 26.518 3.219 c
+26.389 3.032 26.315 2.741 26.296 2.352 c
+27.869 2.352 l
+27.869 2.44 l
+27.848 2.822 27.781 3.09 27.664 3.248 c
+27.546 3.414 27.362 3.499 27.12 3.499 c
+32.397 0.485 m
+32.61 0.485 32.783 0.548 32.912 0.676 c
+33.047 0.812 33.121 1.003 33.132 1.249 c
+33.749 1.249 l
+33.727 0.867 33.591 0.548 33.338 0.294 c
+33.08 0.048 32.768 -0.073 32.397 -0.073 c
+31.904 -0.073 31.53 0.077 31.265 0.382 c
+31.008 0.694 30.883 1.161 30.883 1.779 c
+30.883 2.219 l
+30.883 2.815 31.008 3.27 31.265 3.586 c
+31.53 3.898 31.904 4.056 32.397 4.056 c
+32.798 4.056 33.117 3.925 33.352 3.66 c
+33.595 3.403 33.727 3.057 33.749 2.616 c
+33.132 2.616 l
+33.11 2.911 33.036 3.131 32.912 3.278 c
+32.794 3.425 32.621 3.499 32.397 3.499 c
+32.103 3.499 31.886 3.399 31.75 3.204 c
+31.611 3.017 31.537 2.708 31.53 2.278 c
+31.53 1.764 l
+31.53 1.294 31.596 0.959 31.736 0.764 c
+31.883 0.577 32.103 0.485 32.397 0.485 c
+36.527 0.353 m
+36.311 0.066 35.998 -0.073 35.586 -0.073 c
+35.223 -0.073 34.948 0.048 34.763 0.294 c
+34.587 0.548 34.491 0.912 34.485 1.382 c
+34.485 3.983 l
+35.131 3.983 l
+35.131 1.44 l
+35.131 0.812 35.314 0.5 35.69 0.5 c
+36.091 0.5 36.366 0.676 36.513 1.029 c
+36.513 3.983 l
+37.159 3.983 l
+37.159 0 l
+36.542 0 l
+h
+39.79 3.366 m
+39.702 3.385 39.603 3.395 39.497 3.395 c
+39.162 3.395 38.927 3.212 38.791 2.851 c
+38.791 0 l
+38.144 0 l
+38.144 3.983 l
+38.776 3.983 l
+38.791 3.572 l
+38.967 3.896 39.21 4.056 39.526 4.056 c
+39.632 4.056 39.721 4.035 39.79 3.998 c
+h
+42.084 3.366 m
+41.996 3.385 41.896 3.395 41.79 3.395 c
+41.456 3.395 41.22 3.212 41.084 2.851 c
+41.084 0 l
+40.438 0 l
+40.438 3.983 l
+41.07 3.983 l
+41.084 3.572 l
+41.261 3.896 41.503 4.056 41.819 4.056 c
+41.926 4.056 42.013 4.035 42.084 3.998 c
+h
+44.083 -0.073 m
+43.583 -0.073 43.201 0.073 42.936 0.368 c
+42.672 0.661 42.539 1.095 42.539 1.675 c
+42.539 2.146 l
+42.539 2.741 42.664 3.208 42.921 3.543 c
+43.187 3.884 43.546 4.056 44.009 4.056 c
+44.469 4.056 44.81 3.902 45.038 3.601 c
+45.273 3.308 45.394 2.844 45.406 2.219 c
+45.406 1.793 l
+43.187 1.793 l
+43.187 1.705 l
+43.187 1.271 43.264 0.959 43.422 0.764 c
+43.586 0.577 43.818 0.485 44.112 0.485 c
+44.307 0.485 44.479 0.518 44.627 0.588 c
+44.774 0.665 44.91 0.783 45.038 0.941 c
+45.377 0.529 l
+45.09 0.125 44.66 -0.073 44.083 -0.073 c
+44.009 3.499 m
+43.734 3.499 43.532 3.403 43.407 3.219 c
+43.278 3.032 43.204 2.741 43.187 2.352 c
+44.758 2.352 l
+44.758 2.44 l
+44.737 2.822 44.671 3.09 44.553 3.248 c
+44.436 3.414 44.251 3.499 44.009 3.499 c
+46.802 3.983 m
+46.817 3.543 l
+47.07 3.884 47.394 4.056 47.787 4.056 c
+48.492 4.056 48.849 3.586 48.86 2.645 c
+48.86 0 l
+48.213 0 l
+48.213 2.616 l
+48.213 2.929 48.158 3.15 48.051 3.278 c
+47.941 3.403 47.787 3.469 47.581 3.469 c
+47.423 3.469 47.276 3.414 47.14 3.308 c
+47.012 3.197 46.909 3.061 46.831 2.896 c
+46.831 0 l
+46.185 0 l
+46.185 3.983 l
+h
+50.682 4.939 m
+50.682 3.983 l
+51.285 3.983 l
+51.285 3.454 l
+50.682 3.454 l
+50.682 0.985 l
+50.682 0.827 50.705 0.709 50.756 0.632 c
+50.815 0.551 50.903 0.515 51.021 0.515 c
+51.108 0.515 51.197 0.529 51.285 0.559 c
+51.285 0 l
+51.139 -0.048 50.984 -0.073 50.829 -0.073 c
+50.572 -0.073 50.378 0.018 50.242 0.206 c
+50.102 0.389 50.036 0.65 50.036 0.985 c
+50.036 3.454 l
+49.433 3.454 l
+49.433 3.983 l
+50.036 3.983 l
+50.036 4.939 l
+h
+56.65 1.793 m
+56.65 1.176 56.537 0.709 56.313 0.397 c
+56.095 0.081 55.772 -0.073 55.342 -0.073 c
+54.919 -0.073 54.607 0.106 54.401 0.47 c
+54.372 0 l
+53.77 0 l
+53.77 5.644 l
+54.416 5.644 l
+54.416 3.543 l
+54.63 3.884 54.938 4.056 55.342 4.056 c
+55.772 4.056 56.095 3.898 56.313 3.586 c
+56.537 3.281 56.65 2.815 56.65 2.19 c
+h
+56.003 2.175 m
+56.003 2.645 55.934 2.977 55.798 3.175 c
+55.669 3.37 55.459 3.469 55.166 3.469 c
+54.831 3.469 54.582 3.285 54.416 2.925 c
+54.416 1.043 l
+54.582 0.68 54.835 0.5 55.181 0.5 c
+55.474 0.5 55.684 0.603 55.812 0.808 c
+55.937 1.014 56.003 1.33 56.003 1.764 c
+h
+59.135 3.366 m
+59.046 3.385 58.947 3.395 58.84 3.395 c
+58.506 3.395 58.271 3.212 58.135 2.851 c
+58.135 0 l
+57.489 0 l
+57.489 3.983 l
+58.12 3.983 l
+58.135 3.572 l
+58.312 3.896 58.553 4.056 58.87 4.056 c
+58.977 4.056 59.064 4.035 59.135 3.998 c
+h
+61.678 0 m
+61.637 0.088 61.611 0.235 61.604 0.441 c
+61.369 0.095 61.075 -0.073 60.722 -0.073 c
+60.358 -0.073 60.076 0.022 59.87 0.22 c
+59.671 0.426 59.575 0.713 59.575 1.088 c
+59.575 1.488 59.712 1.808 59.987 2.043 c
+60.259 2.286 60.633 2.41 61.104 2.41 c
+61.589 2.41 l
+61.589 2.837 l
+61.589 3.072 61.534 3.237 61.427 3.337 c
+61.317 3.443 61.156 3.499 60.942 3.499 c
+60.744 3.499 60.583 3.439 60.458 3.322 c
+60.34 3.204 60.281 3.057 60.281 2.881 c
+59.634 2.881 l
+59.634 3.075 59.693 3.267 59.81 3.454 c
+59.935 3.638 60.097 3.785 60.296 3.896 c
+60.502 4.002 60.729 4.056 60.986 4.056 c
+61.387 4.056 61.692 3.954 61.898 3.748 c
+62.111 3.543 62.225 3.248 62.236 2.866 c
+62.236 0.852 l
+62.236 0.548 62.273 0.283 62.353 0.058 c
+62.353 0 l
+h
+60.81 0.515 m
+60.976 0.515 61.126 0.559 61.266 0.646 c
+61.412 0.735 61.52 0.845 61.589 0.985 c
+61.589 1.926 l
+61.221 1.926 l
+60.905 1.926 60.664 1.856 60.487 1.72 c
+60.311 1.591 60.222 1.404 60.222 1.161 c
+60.222 0.933 60.267 0.768 60.355 0.661 c
+60.443 0.563 60.593 0.515 60.81 0.515 c
+63.853 3.983 m
+63.868 3.543 l
+64.121 3.884 64.444 4.056 64.838 4.056 c
+65.543 4.056 65.9 3.586 65.911 2.645 c
+65.911 0 l
+65.264 0 l
+65.264 2.616 l
+65.264 2.929 65.209 3.15 65.102 3.278 c
+64.992 3.403 64.838 3.469 64.632 3.469 c
+64.474 3.469 64.327 3.414 64.191 3.308 c
+64.062 3.197 63.96 3.061 63.883 2.896 c
+63.883 0 l
+63.236 0 l
+63.236 3.983 l
+h
+68.263 0.485 m
+68.475 0.485 68.649 0.548 68.777 0.676 c
+68.913 0.812 68.986 1.003 68.998 1.249 c
+69.615 1.249 l
+69.593 0.867 69.457 0.548 69.204 0.294 c
+68.946 0.048 68.634 -0.073 68.263 -0.073 c
+67.77 -0.073 67.395 0.077 67.131 0.382 c
+66.873 0.694 66.748 1.161 66.748 1.779 c
+66.748 2.219 l
+66.748 2.815 66.873 3.27 67.131 3.586 c
+67.395 3.898 67.77 4.056 68.263 4.056 c
+68.664 4.056 68.983 3.925 69.218 3.66 c
+69.46 3.403 69.593 3.057 69.615 2.616 c
+68.998 2.616 l
+68.976 2.911 68.902 3.131 68.777 3.278 c
+68.66 3.425 68.487 3.499 68.263 3.499 c
+67.968 3.499 67.752 3.399 67.616 3.204 c
+67.476 3.017 67.403 2.708 67.395 2.278 c
+67.395 1.764 l
+67.395 1.294 67.461 0.959 67.602 0.764 c
+67.748 0.577 67.968 0.485 68.263 0.485 c
+71.012 3.572 m
+71.265 3.896 71.585 4.056 71.967 4.056 c
+72.672 4.056 73.029 3.586 73.04 2.645 c
+73.04 0 l
+72.393 0 l
+72.393 2.616 l
+72.393 2.929 72.338 3.15 72.231 3.278 c
+72.121 3.403 71.967 3.469 71.761 3.469 c
+71.603 3.469 71.456 3.414 71.32 3.308 c
+71.191 3.197 71.089 3.061 71.012 2.896 c
+71.012 0 l
+70.364 0 l
+70.364 5.644 l
+71.012 5.644 l
+h
+78.684 1.147 m
+79.286 3.983 l
+79.934 3.983 l
+78.949 0 l
+78.434 0 l
+77.655 2.851 l
+76.905 0 l
+76.377 0 l
+75.421 3.983 l
+76.053 3.983 l
+76.67 1.22 l
+77.405 3.983 l
+77.92 3.983 l
+h
+81.316 0 -0.647 3.983 re
+81.36 5.027 m
+81.36 4.916 81.33 4.825 81.271 4.748 c
+81.212 4.678 81.117 4.644 80.992 4.644 c
+80.874 4.644 80.778 4.678 80.713 4.748 c
+80.654 4.825 80.624 4.916 80.624 5.027 c
+80.624 5.145 80.654 5.236 80.713 5.307 c
+80.778 5.384 80.874 5.424 80.992 5.424 c
+81.117 5.424 81.212 5.384 81.271 5.307 c
+81.33 5.226 81.36 5.134 81.36 5.027 c
+83.182 4.939 m
+83.182 3.983 l
+83.785 3.983 l
+83.785 3.454 l
+83.182 3.454 l
+83.182 0.985 l
+83.182 0.827 83.205 0.709 83.255 0.632 c
+83.315 0.551 83.403 0.515 83.52 0.515 c
+83.608 0.515 83.697 0.529 83.785 0.559 c
+83.785 0 l
+83.638 -0.048 83.483 -0.073 83.329 -0.073 c
+83.072 -0.073 82.877 0.018 82.741 0.206 c
+82.602 0.389 82.536 0.65 82.536 0.985 c
+82.536 3.454 l
+81.933 3.454 l
+81.933 3.983 l
+82.536 3.983 l
+82.536 4.939 l
+h
+85.196 3.572 m
+85.449 3.896 85.769 4.056 86.151 4.056 c
+86.857 4.056 87.213 3.586 87.224 2.645 c
+87.224 0 l
+86.577 0 l
+86.577 2.616 l
+86.577 2.929 86.523 3.15 86.416 3.278 c
+86.305 3.403 86.151 3.469 85.946 3.469 c
+85.788 3.469 85.64 3.414 85.505 3.308 c
+85.376 3.197 85.273 3.061 85.196 2.896 c
+85.196 0 l
+84.549 0 l
+84.549 5.644 l
+85.196 5.644 l
+h
+90.605 0 -0.647 3.983 re
+90.65 5.027 m
+90.65 4.916 90.62 4.825 90.561 4.748 c
+90.502 4.678 90.407 4.644 90.282 4.644 c
+90.164 4.644 90.068 4.678 90.002 4.748 c
+89.944 4.825 89.914 4.916 89.914 5.027 c
+89.914 5.145 89.944 5.236 90.002 5.307 c
+90.068 5.384 90.164 5.424 90.282 5.424 c
+90.407 5.424 90.502 5.384 90.561 5.307 c
+90.62 5.226 90.65 5.134 90.65 5.027 c
+92.472 4.939 m
+92.472 3.983 l
+93.075 3.983 l
+93.075 3.454 l
+92.472 3.454 l
+92.472 0.985 l
+92.472 0.827 92.494 0.709 92.545 0.632 c
+92.604 0.551 92.692 0.515 92.811 0.515 c
+92.898 0.515 92.986 0.529 93.075 0.559 c
+93.075 0 l
+92.927 -0.048 92.773 -0.073 92.619 -0.073 c
+92.362 -0.073 92.167 0.018 92.031 0.206 c
+91.891 0.389 91.826 0.65 91.826 0.985 c
+91.826 3.454 l
+91.223 3.454 l
+91.223 3.983 l
+91.826 3.983 l
+91.826 4.939 l
+h
+95.779 1.014 m
+95.779 1.161 95.724 1.282 95.618 1.382 c
+95.508 1.477 95.302 1.595 95.001 1.735 c
+94.654 1.881 94.413 2.003 94.265 2.102 c
+94.118 2.209 94.008 2.326 93.942 2.454 c
+93.872 2.58 93.839 2.738 93.839 2.925 c
+93.839 3.248 93.956 3.516 94.192 3.734 c
+94.427 3.946 94.729 4.056 95.103 4.056 c
+95.485 4.056 95.794 3.943 96.029 3.719 c
+96.264 3.491 96.382 3.204 96.382 2.851 c
+95.735 2.851 l
+95.735 3.028 95.676 3.179 95.558 3.308 c
+95.441 3.432 95.287 3.499 95.103 3.499 c
+94.905 3.499 94.754 3.443 94.648 3.337 c
+94.537 3.237 94.486 3.105 94.486 2.94 c
+94.486 2.811 94.523 2.705 94.604 2.616 c
+94.681 2.535 94.872 2.433 95.176 2.308 c
+95.654 2.12 95.985 1.933 96.161 1.749 c
+96.338 1.573 96.426 1.345 96.426 1.073 c
+96.426 0.721 96.301 0.441 96.059 0.235 c
+95.824 0.029 95.508 -0.073 95.118 -0.073 c
+94.695 -0.073 94.357 0.044 94.103 0.279 c
+93.846 0.522 93.721 0.827 93.721 1.191 c
+94.368 1.191 l
+94.376 0.962 94.446 0.786 94.573 0.661 c
+94.699 0.544 94.883 0.485 95.118 0.485 c
+95.331 0.485 95.493 0.532 95.603 0.632 c
+95.72 0.727 95.779 0.856 95.779 1.014 c
+101.012 0.353 m
+100.796 0.066 100.483 -0.073 100.071 -0.073 c
+99.708 -0.073 99.432 0.048 99.248 0.294 c
+99.072 0.548 98.976 0.912 98.969 1.382 c
+98.969 3.983 l
+99.616 3.983 l
+99.616 1.44 l
+99.616 0.812 99.799 0.5 100.175 0.5 c
+100.574 0.5 100.85 0.676 100.998 1.029 c
+100.998 3.983 l
+101.644 3.983 l
+101.644 0 l
+101.027 0 l
+h
+105.51 1.793 m
+105.51 1.165 105.392 0.694 105.157 0.382 c
+104.929 0.077 104.613 -0.073 104.202 -0.073 c
+103.797 -0.073 103.489 0.077 103.275 0.382 c
+103.275 -1.529 l
+102.629 -1.529 l
+102.629 3.983 l
+103.217 3.983 l
+103.261 3.543 l
+103.474 3.884 103.783 4.056 104.187 4.056 c
+104.628 4.056 104.955 3.902 105.172 3.601 c
+105.385 3.296 105.499 2.84 105.51 2.234 c
+h
+104.863 2.175 m
+104.863 2.616 104.794 2.94 104.657 3.146 c
+104.518 3.358 104.297 3.469 103.996 3.469 c
+103.68 3.469 103.441 3.314 103.275 3.013 c
+103.275 0.941 l
+103.441 0.636 103.68 0.485 103.996 0.485 c
+104.29 0.485 104.503 0.588 104.643 0.794 c
+104.779 1.007 104.852 1.338 104.863 1.779 c
+h
+108.289 1.014 m
+108.289 1.161 108.233 1.282 108.127 1.382 c
+108.017 1.477 107.811 1.595 107.509 1.735 c
+107.163 1.881 106.922 2.003 106.774 2.102 c
+106.627 2.209 106.517 2.326 106.451 2.454 c
+106.381 2.58 106.348 2.738 106.348 2.925 c
+106.348 3.248 106.465 3.516 106.701 3.734 c
+106.936 3.946 107.237 4.056 107.612 4.056 c
+107.994 4.056 108.303 3.943 108.538 3.719 c
+108.773 3.491 108.891 3.204 108.891 2.851 c
+108.244 2.851 l
+108.244 3.028 108.185 3.179 108.067 3.308 c
+107.95 3.432 107.796 3.499 107.612 3.499 c
+107.414 3.499 107.263 3.443 107.157 3.337 c
+107.046 3.237 106.995 3.105 106.995 2.94 c
+106.995 2.811 107.032 2.705 107.113 2.616 c
+107.19 2.535 107.381 2.433 107.685 2.308 c
+108.163 2.12 108.494 1.933 108.67 1.749 c
+108.846 1.573 108.935 1.345 108.935 1.073 c
+108.935 0.721 108.81 0.441 108.568 0.235 c
+108.333 0.029 108.017 -0.073 107.627 -0.073 c
+107.204 -0.073 106.866 0.044 106.612 0.279 c
+106.355 0.522 106.23 0.827 106.23 1.191 c
+106.877 1.191 l
+106.884 0.962 106.955 0.786 107.082 0.661 c
+107.208 0.544 107.392 0.485 107.627 0.485 c
+107.84 0.485 108.002 0.532 108.112 0.632 c
+108.229 0.727 108.289 0.856 108.289 1.014 c
+110.625 4.939 m
+110.625 3.983 l
+111.228 3.983 l
+111.228 3.454 l
+110.625 3.454 l
+110.625 0.985 l
+110.625 0.827 110.647 0.709 110.699 0.632 c
+110.758 0.551 110.845 0.515 110.963 0.515 c
+111.051 0.515 111.14 0.529 111.228 0.559 c
+111.228 0 l
+111.081 -0.048 110.926 -0.073 110.772 -0.073 c
+110.515 -0.073 110.32 0.018 110.184 0.206 c
+110.045 0.389 109.979 0.65 109.979 0.985 c
+109.979 3.454 l
+109.376 3.454 l
+109.376 3.983 l
+109.979 3.983 l
+109.979 4.939 l
+h
+113.638 3.366 m
+113.55 3.385 113.451 3.395 113.345 3.395 c
+113.01 3.395 112.775 3.212 112.639 2.851 c
+112.639 0 l
+111.992 0 l
+111.992 3.983 l
+112.624 3.983 l
+112.639 3.572 l
+112.815 3.896 113.058 4.056 113.374 4.056 c
+113.48 4.056 113.569 4.035 113.638 3.998 c
+h
+115.638 -0.073 m
+115.138 -0.073 114.756 0.073 114.491 0.368 c
+114.226 0.661 114.094 1.095 114.094 1.675 c
+114.094 2.146 l
+114.094 2.741 114.219 3.208 114.477 3.543 c
+114.741 3.884 115.101 4.056 115.564 4.056 c
+116.023 4.056 116.366 3.902 116.593 3.601 c
+116.829 3.308 116.95 2.844 116.96 2.219 c
+116.96 1.793 l
+114.741 1.793 l
+114.741 1.705 l
+114.741 1.271 114.818 0.959 114.976 0.764 c
+115.142 0.577 115.373 0.485 115.667 0.485 c
+115.861 0.485 116.035 0.518 116.181 0.588 c
+116.329 0.665 116.464 0.783 116.593 0.941 c
+116.931 0.529 l
+116.644 0.125 116.214 -0.073 115.638 -0.073 c
+115.564 3.499 m
+115.289 3.499 115.086 3.403 114.961 3.219 c
+114.833 3.032 114.76 2.741 114.741 2.352 c
+116.314 2.352 l
+116.314 2.44 l
+116.291 2.822 116.226 3.09 116.108 3.248 c
+115.99 3.414 115.807 3.499 115.564 3.499 c
+119.782 0 m
+119.742 0.088 119.717 0.235 119.709 0.441 c
+119.474 0.095 119.18 -0.073 118.828 -0.073 c
+118.464 -0.073 118.18 0.022 117.975 0.22 c
+117.777 0.426 117.681 0.713 117.681 1.088 c
+117.681 1.488 117.817 1.808 118.092 2.043 c
+118.365 2.286 118.739 2.41 119.21 2.41 c
+119.695 2.41 l
+119.695 2.837 l
+119.695 3.072 119.639 3.237 119.533 3.337 c
+119.423 3.443 119.261 3.499 119.048 3.499 c
+118.849 3.499 118.687 3.439 118.562 3.322 c
+118.446 3.204 118.386 3.057 118.386 2.881 c
+117.74 2.881 l
+117.74 3.075 117.798 3.267 117.916 3.454 c
+118.041 3.638 118.203 3.785 118.401 3.896 c
+118.607 4.002 118.835 4.056 119.092 4.056 c
+119.493 4.056 119.798 3.954 120.004 3.748 c
+120.216 3.543 120.33 3.248 120.341 2.866 c
+120.341 0.852 l
+120.341 0.548 120.378 0.283 120.459 0.058 c
+120.459 0 l
+h
+118.916 0.515 m
+119.081 0.515 119.231 0.559 119.371 0.646 c
+119.518 0.735 119.624 0.845 119.695 0.985 c
+119.695 1.926 l
+119.327 1.926 l
+119.011 1.926 118.768 1.856 118.592 1.72 c
+118.416 1.591 118.327 1.404 118.327 1.161 c
+118.327 0.933 118.371 0.768 118.46 0.661 c
+118.548 0.563 118.699 0.515 118.916 0.515 c
+121.958 3.983 m
+121.973 3.616 l
+122.215 3.91 122.535 4.056 122.928 4.056 c
+123.369 4.056 123.678 3.858 123.855 3.469 c
+124.108 3.858 124.457 4.056 124.898 4.056 c
+125.633 4.056 126.008 3.594 126.03 2.675 c
+126.03 0 l
+125.383 0 l
+125.383 2.616 l
+125.383 2.911 125.328 3.123 125.222 3.263 c
+125.122 3.399 124.95 3.469 124.707 3.469 c
+124.509 3.469 124.347 3.388 124.222 3.233 c
+124.104 3.087 124.035 2.896 124.016 2.66 c
+124.016 0 l
+123.354 0 l
+123.354 2.645 l
+123.354 3.193 123.134 3.469 122.693 3.469 c
+122.359 3.469 122.124 3.308 121.988 2.984 c
+121.988 0 l
+121.341 0 l
+121.341 3.983 l
+h
+127.044 0.353 m
+127.044 0.47 127.077 0.565 127.147 0.646 c
+127.213 0.723 127.316 0.764 127.456 0.764 c
+127.603 0.764 127.709 0.723 127.779 0.646 c
+127.856 0.565 127.896 0.47 127.896 0.353 c
+127.896 0.243 127.856 0.151 127.779 0.073 c
+127.709 -0.004 127.603 -0.044 127.456 -0.044 c
+127.316 -0.044 127.213 -0.004 127.147 0.073 c
+127.077 0.151 127.044 0.243 127.044 0.353 c
+f
+Q
+0.113 0.082 0.09 0 k
+35.668 193.132 238.665 -12.895 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 40.8563 186.2965 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.146 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.263 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.024 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.034 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.477 -2.234 -0.515 c
+-2.138 -0.554 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.772 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.279 -3.219 1.426 c
+-3.289 1.573 -3.322 1.757 -3.322 1.985 c
+-3.322 2.18 -3.289 2.345 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.933 -2.645 3.003 -2.469 3.043 c
+-2.293 3.091 -2.102 3.12 -1.896 3.131 c
+-1.896 3.558 l
+-1.543 3.558 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.091 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.735 -0.349 2.621 -0.279 2.484 c
+-0.202 2.345 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.459 -1.543 2.5 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.36 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.206 c
+-0.756 1.147 -0.595 1.066 -0.455 0.971 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.503 -2.113 2.484 -2.19 2.455 c
+-2.26 2.425 -2.319 2.386 -2.366 2.338 c
+-2.406 2.297 -2.437 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.066 -2.484 1.999 c
+-2.484 1.912 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.201 1.559 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.441 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.302 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.44 c
+-0.904 -0.345 -0.837 -0.201 -0.837 -0.014 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.634 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.616 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.146 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.83 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.411 4.888 -0.205 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.772 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.632 5.137 1.779 c
+5.245 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.264 6.093 2.264 c
+6.188 2.264 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.918 7.107 1.97 c
+7.115 2.029 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.152 2.22 c
+8.004 2.22 l
+7.993 2.139 7.982 2.029 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.871 -1.822 c
+7.802 -2.006 7.699 -2.161 7.563 -2.278 c
+7.423 -2.403 7.258 -2.499 7.063 -2.557 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.206 6.924 1.324 6.857 1.411 c
+6.799 1.5 6.729 1.559 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.279 5.835 1.162 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.558 c
+6.725 -0.521 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.302 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.263 l
+8.86 -1.263 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.22 l
+13.644 2.22 l
+13.924 3.117 l
+14.497 3.117 l
+14.497 2.22 l
+15.732 2.22 l
+15.732 1.602 l
+14.497 1.602 l
+14.497 -0.103 l
+14.497 -0.323 l
+14.504 -0.393 14.527 -0.455 14.556 -0.515 c
+14.593 -0.565 14.648 -0.61 14.718 -0.646 c
+14.795 -0.675 14.909 -0.691 15.056 -0.691 c
+15.192 -0.691 15.327 -0.687 15.468 -0.675 c
+15.603 -0.658 15.736 -0.632 15.865 -0.602 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.23 15.629 -1.249 c
+15.549 -1.26 15.471 -1.267 15.394 -1.278 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.041 -1.3 14.942 -1.308 14.835 -1.308 c
+14.648 -1.308 14.486 -1.294 14.35 -1.263 c
+14.221 -1.227 14.107 -1.183 14.012 -1.132 c
+13.924 -1.084 13.85 -1.024 13.791 -0.955 c
+13.733 -0.878 13.689 -0.801 13.66 -0.72 c
+13.63 -0.632 13.608 -0.544 13.6 -0.455 c
+13.59 -0.359 13.586 -0.264 13.586 -0.176 c
+h
+21.986 2.22 m
+21.994 2.198 22.001 2.165 22.001 2.117 c
+22.009 2.076 22.016 2.029 22.016 1.97 c
+22.023 1.918 22.03 1.867 22.03 1.808 c
+22.03 1.646 l
+22.045 1.646 l
+22.104 1.764 22.17 1.86 22.251 1.941 c
+22.328 2.018 22.413 2.08 22.501 2.132 c
+22.589 2.19 22.677 2.228 22.765 2.249 c
+22.861 2.268 22.961 2.278 23.059 2.278 c
+23.265 2.278 23.445 2.234 23.603 2.147 c
+23.757 2.058 23.886 1.929 23.985 1.764 c
+24.092 1.606 24.169 1.415 24.22 1.191 c
+24.28 0.975 24.309 0.739 24.309 0.485 c
+24.309 0.221 24.28 -0.025 24.22 -0.249 c
+24.169 -0.467 24.092 -0.658 23.985 -0.823 c
+23.886 -0.981 23.754 -1.103 23.589 -1.19 c
+23.431 -1.278 23.243 -1.323 23.03 -1.323 c
+22.931 -1.323 22.832 -1.311 22.736 -1.294 c
+22.637 -1.271 22.545 -1.242 22.456 -1.19 c
+22.375 -1.142 22.298 -1.08 22.221 -0.999 c
+22.152 -0.922 22.093 -0.83 22.045 -0.72 c
+22.03 -0.72 l
+22.03 -0.808 l
+22.038 -0.849 22.045 -0.897 22.045 -0.955 c
+22.045 -1.117 l
+22.045 -1.294 l
+22.045 -2.631 l
+21.134 -2.631 l
+21.134 1.455 l
+21.134 1.621 21.126 1.768 21.119 1.897 c
+21.119 2.22 l
+h
+22.03 0.456 m
+22.03 0.229 22.049 0.037 22.089 -0.118 c
+22.137 -0.264 22.192 -0.382 22.251 -0.47 c
+22.317 -0.558 22.391 -0.625 22.471 -0.661 c
+22.549 -0.702 22.626 -0.72 22.707 -0.72 c
+22.803 -0.72 22.89 -0.698 22.971 -0.646 c
+23.059 -0.598 23.125 -0.529 23.177 -0.44 c
+23.235 -0.345 23.28 -0.22 23.31 -0.073 c
+23.346 0.081 23.368 0.269 23.368 0.485 c
+23.368 0.875 23.31 1.169 23.192 1.367 c
+23.081 1.563 22.927 1.661 22.722 1.661 c
+22.641 1.661 22.564 1.64 22.486 1.602 c
+22.406 1.563 22.332 1.5 22.265 1.411 c
+22.196 1.324 22.137 1.199 22.089 1.044 c
+22.049 0.886 22.03 0.691 22.03 0.456 c
+26.061 2.22 m
+26.061 0.265 l
+26.061 0.125 26.069 0 26.091 -0.118 c
+26.109 -0.228 26.142 -0.319 26.194 -0.397 c
+26.242 -0.477 26.3 -0.54 26.371 -0.588 c
+26.437 -0.628 26.521 -0.646 26.62 -0.646 c
+26.709 -0.646 26.789 -0.628 26.87 -0.588 c
+26.959 -0.54 27.032 -0.47 27.09 -0.382 c
+27.15 -0.286 27.194 -0.176 27.223 -0.058 c
+27.26 0.067 27.281 0.206 27.281 0.353 c
+27.281 2.22 l
+28.178 2.22 l
+28.178 -0.484 l
+28.178 -0.72 l
+28.185 -0.801 28.193 -0.878 28.193 -0.955 c
+28.193 -1.146 l
+28.201 -1.198 28.208 -1.234 28.208 -1.263 c
+27.355 -1.263 l
+27.344 -1.234 27.333 -1.198 27.326 -1.146 c
+27.326 -0.955 l
+27.326 -0.889 27.318 -0.819 27.312 -0.75 c
+27.312 -0.573 l
+27.296 -0.573 l
+27.179 -0.837 27.025 -1.028 26.841 -1.146 c
+26.664 -1.263 26.462 -1.323 26.238 -1.323 c
+26.032 -1.323 25.86 -1.286 25.724 -1.22 c
+25.584 -1.153 25.473 -1.058 25.386 -0.941 c
+25.305 -0.823 25.246 -0.687 25.209 -0.529 c
+25.18 -0.363 25.165 -0.187 25.165 0 c
+25.165 2.22 l
+h
+32.342 -0.249 m
+32.342 -0.419 32.301 -0.569 32.224 -0.706 c
+32.154 -0.833 32.052 -0.947 31.916 -1.043 c
+31.787 -1.132 31.625 -1.201 31.43 -1.249 c
+31.243 -1.297 31.027 -1.323 30.784 -1.323 c
+30.556 -1.323 30.358 -1.308 30.181 -1.278 c
+30.005 -1.249 29.847 -1.201 29.71 -1.132 c
+29.571 -1.055 29.461 -0.955 29.373 -0.837 c
+29.284 -0.72 29.215 -0.573 29.167 -0.397 c
+29.976 -0.279 l
+29.994 -0.378 30.023 -0.455 30.063 -0.515 c
+30.111 -0.573 30.17 -0.617 30.24 -0.646 c
+30.306 -0.675 30.387 -0.702 30.475 -0.72 c
+30.564 -0.731 30.666 -0.735 30.784 -0.735 c
+30.88 -0.735 30.975 -0.731 31.063 -0.72 c
+31.152 -0.702 31.229 -0.675 31.298 -0.646 c
+31.364 -0.617 31.416 -0.58 31.445 -0.529 c
+31.482 -0.481 31.504 -0.419 31.504 -0.338 c
+31.504 -0.242 31.474 -0.168 31.416 -0.118 c
+31.364 -0.07 31.298 -0.029 31.21 0 c
+31.122 0.037 31.011 0.067 30.886 0.088 c
+30.769 0.118 30.637 0.148 30.489 0.177 c
+30.35 0.214 30.211 0.254 30.063 0.294 c
+29.924 0.342 29.799 0.405 29.681 0.485 c
+29.571 0.563 29.483 0.661 29.417 0.779 c
+29.347 0.897 29.313 1.048 29.313 1.235 c
+29.313 1.389 29.344 1.532 29.402 1.661 c
+29.469 1.798 29.564 1.912 29.681 1.999 c
+29.806 2.087 29.964 2.153 30.152 2.205 c
+30.335 2.253 30.549 2.278 30.784 2.278 c
+30.967 2.278 31.144 2.257 31.313 2.22 c
+31.478 2.19 31.625 2.135 31.754 2.058 c
+31.879 1.989 31.989 1.889 32.077 1.764 c
+32.166 1.646 32.224 1.503 32.253 1.338 c
+31.46 1.264 l
+31.438 1.341 31.408 1.405 31.372 1.455 c
+31.331 1.515 31.283 1.559 31.225 1.588 c
+31.173 1.625 31.111 1.65 31.034 1.661 c
+30.953 1.669 30.872 1.676 30.784 1.676 c
+30.567 1.676 30.406 1.646 30.298 1.588 c
+30.188 1.536 30.137 1.448 30.137 1.324 c
+30.137 1.243 30.155 1.18 30.196 1.132 c
+30.244 1.081 30.306 1.044 30.387 1.014 c
+30.475 0.985 30.57 0.956 30.681 0.927 c
+30.788 0.904 30.909 0.882 31.048 0.853 c
+31.202 0.823 31.36 0.783 31.519 0.736 c
+31.673 0.684 31.813 0.622 31.931 0.544 c
+32.048 0.464 32.143 0.36 32.224 0.235 c
+32.301 0.107 32.342 -0.055 32.342 -0.249 c
+34.202 1.515 m
+34.319 1.786 34.47 1.985 34.657 2.103 c
+34.84 2.22 35.061 2.278 35.318 2.278 c
+35.524 2.278 35.694 2.242 35.833 2.176 c
+35.98 2.106 36.091 2.014 36.17 1.897 c
+36.259 1.779 36.318 1.636 36.347 1.47 c
+36.384 1.301 36.406 1.125 36.406 0.941 c
+36.406 -1.263 l
+35.495 -1.263 l
+35.495 0.736 l
+35.495 0.871 35.484 0.992 35.465 1.103 c
+35.455 1.21 35.428 1.297 35.392 1.367 c
+35.351 1.445 35.293 1.503 35.216 1.544 c
+35.146 1.58 35.054 1.602 34.936 1.602 c
+34.826 1.602 34.73 1.577 34.643 1.529 c
+34.554 1.478 34.473 1.411 34.408 1.324 c
+34.348 1.235 34.297 1.125 34.26 1 c
+34.231 0.882 34.216 0.75 34.216 0.603 c
+34.216 -1.263 l
+33.305 -1.263 l
+33.305 3.514 l
+34.216 3.514 l
+34.216 2.205 l
+34.216 2.135 34.209 2.066 34.202 1.999 c
+34.202 1.794 l
+34.202 1.735 34.194 1.68 34.186 1.632 c
+34.186 1.515 l
+h
+42.175 -2.631 m
+42.175 3.514 l
+44.101 3.514 l
+44.101 2.896 l
+43.028 2.896 l
+43.028 -2.013 l
+44.101 -2.013 l
+44.101 -2.631 l
+h
+46.075 0.838 1.866 -0.794 re
+46.075 0.044 m
+50.135 0.838 1.867 -0.794 re
+50.135 0.044 m
+54.214 1.602 m
+53.67 1.602 l
+53.67 2.22 l
+54.258 2.22 l
+54.537 3.117 l
+55.11 3.117 l
+55.11 2.22 l
+56.346 2.22 l
+56.346 1.602 l
+55.11 1.602 l
+55.11 -0.103 l
+55.11 -0.323 l
+55.118 -0.393 55.14 -0.455 55.17 -0.515 c
+55.206 -0.565 55.261 -0.61 55.331 -0.646 c
+55.409 -0.675 55.522 -0.691 55.669 -0.691 c
+55.806 -0.691 55.941 -0.687 56.081 -0.675 c
+56.217 -0.658 56.349 -0.632 56.477 -0.602 c
+56.477 -1.205 l
+56.396 -1.216 56.319 -1.23 56.242 -1.249 c
+56.161 -1.26 56.084 -1.267 56.007 -1.278 c
+55.926 -1.286 55.839 -1.294 55.743 -1.294 c
+55.654 -1.3 55.555 -1.308 55.449 -1.308 c
+55.261 -1.308 55.1 -1.294 54.964 -1.263 c
+54.835 -1.227 54.721 -1.183 54.626 -1.132 c
+54.537 -1.084 54.464 -1.024 54.405 -0.955 c
+54.347 -0.878 54.302 -0.801 54.273 -0.72 c
+54.243 -0.632 54.221 -0.544 54.214 -0.455 c
+54.203 -0.359 54.2 -0.264 54.2 -0.176 c
+h
+58.628 -1.323 m
+58.458 -1.323 58.308 -1.3 58.172 -1.263 c
+58.043 -1.216 57.929 -1.146 57.834 -1.058 c
+57.745 -0.97 57.676 -0.864 57.628 -0.735 c
+57.576 -0.598 57.554 -0.448 57.554 -0.279 c
+57.554 -0.073 57.587 0.096 57.657 0.235 c
+57.724 0.383 57.819 0.493 57.936 0.574 c
+58.061 0.661 58.204 0.724 58.363 0.765 c
+58.528 0.801 58.705 0.827 58.892 0.838 c
+59.612 0.853 l
+59.612 1.029 l
+59.612 1.147 59.601 1.249 59.583 1.338 c
+59.561 1.426 59.528 1.492 59.48 1.544 c
+59.44 1.602 59.392 1.64 59.333 1.661 c
+59.274 1.68 59.208 1.691 59.141 1.691 c
+59.072 1.691 59.01 1.68 58.95 1.661 c
+58.9 1.65 58.852 1.625 58.804 1.588 c
+58.763 1.559 58.73 1.507 58.701 1.441 c
+58.679 1.382 58.665 1.301 58.657 1.206 c
+57.716 1.249 l
+57.745 1.397 57.79 1.532 57.848 1.661 c
+57.915 1.786 58.01 1.897 58.127 1.985 c
+58.245 2.08 58.385 2.153 58.553 2.205 c
+58.73 2.253 58.936 2.278 59.172 2.278 c
+59.612 2.278 59.943 2.168 60.171 1.955 c
+60.406 1.75 60.523 1.441 60.523 1.029 c
+60.523 -0.235 l
+60.523 -0.455 l
+60.531 -0.515 60.546 -0.569 60.568 -0.617 c
+60.586 -0.658 60.616 -0.691 60.656 -0.72 c
+60.693 -0.742 60.744 -0.75 60.803 -0.75 c
+60.869 -0.75 60.939 -0.746 61.009 -0.735 c
+61.009 -1.22 l
+60.95 -1.23 60.895 -1.242 60.847 -1.249 c
+60.807 -1.26 60.766 -1.267 60.729 -1.278 c
+60.689 -1.286 60.645 -1.294 60.597 -1.294 c
+60.546 -1.3 60.487 -1.308 60.421 -1.308 c
+60.193 -1.308 60.028 -1.257 59.921 -1.146 c
+59.81 -1.028 59.748 -0.864 59.729 -0.646 c
+59.715 -0.646 l
+59.646 -0.756 59.575 -0.852 59.509 -0.941 c
+59.44 -1.022 59.363 -1.087 59.274 -1.146 c
+59.186 -1.205 59.087 -1.249 58.981 -1.278 c
+58.881 -1.308 58.763 -1.323 58.628 -1.323 c
+59.612 0.353 m
+59.186 0.339 l
+59.087 0.339 58.995 0.331 58.906 0.324 c
+58.826 0.312 58.76 0.287 58.701 0.25 c
+58.642 0.21 58.591 0.151 58.553 0.073 c
+58.513 0.004 58.495 -0.087 58.495 -0.205 c
+58.495 -0.374 58.528 -0.496 58.598 -0.573 c
+58.665 -0.654 58.763 -0.691 58.892 -0.691 c
+58.998 -0.691 59.098 -0.669 59.186 -0.617 c
+59.282 -0.569 59.363 -0.507 59.421 -0.426 c
+59.488 -0.349 59.538 -0.261 59.569 -0.162 c
+59.598 -0.055 59.612 0.059 59.612 0.177 c
+h
+63.261 -2.66 m
+63.045 -2.66 62.854 -2.634 62.688 -2.587 c
+62.519 -2.547 62.379 -2.484 62.262 -2.396 c
+62.144 -2.315 62.045 -2.219 61.967 -2.102 c
+61.898 -1.984 61.85 -1.855 61.821 -1.72 c
+62.717 -1.616 l
+62.754 -1.753 62.824 -1.859 62.923 -1.94 c
+63.019 -2.028 63.143 -2.072 63.291 -2.072 c
+63.379 -2.072 63.459 -2.057 63.54 -2.028 c
+63.617 -1.999 63.687 -1.944 63.746 -1.866 c
+63.806 -1.797 63.849 -1.705 63.879 -1.587 c
+63.916 -1.469 63.937 -1.323 63.937 -1.146 c
+63.937 -0.955 l
+63.937 -0.889 63.941 -0.83 63.952 -0.779 c
+63.952 -0.588 l
+63.937 -0.588 l
+63.839 -0.816 63.695 -0.977 63.511 -1.072 c
+63.324 -1.172 63.118 -1.22 62.894 -1.22 c
+62.688 -1.22 62.505 -1.183 62.35 -1.103 c
+62.203 -1.014 62.075 -0.897 61.967 -0.75 c
+61.869 -0.595 61.795 -0.411 61.747 -0.205 c
+61.696 0.008 61.674 0.243 61.674 0.5 c
+61.674 0.772 61.696 1.018 61.747 1.235 c
+61.806 1.448 61.887 1.632 61.998 1.779 c
+62.104 1.933 62.236 2.051 62.395 2.132 c
+62.549 2.22 62.736 2.264 62.952 2.264 c
+63.048 2.264 63.147 2.253 63.247 2.234 c
+63.342 2.213 63.43 2.18 63.511 2.132 c
+63.6 2.08 63.677 2.018 63.746 1.941 c
+63.824 1.86 63.886 1.768 63.937 1.661 c
+63.952 1.661 l
+63.952 1.808 l
+63.96 1.867 63.967 1.918 63.967 1.97 c
+63.974 2.029 63.982 2.076 63.982 2.117 c
+63.989 2.165 64 2.198 64.011 2.22 c
+64.863 2.22 l
+64.853 2.139 64.841 2.029 64.834 1.881 c
+64.834 1.411 l
+64.834 -1.161 l
+64.834 -1.415 64.797 -1.635 64.731 -1.822 c
+64.662 -2.006 64.558 -2.161 64.423 -2.278 c
+64.283 -2.403 64.118 -2.499 63.922 -2.557 c
+63.725 -2.624 63.504 -2.66 63.261 -2.66 c
+63.952 0.53 m
+63.952 0.742 63.926 0.919 63.879 1.058 c
+63.839 1.206 63.783 1.324 63.717 1.411 c
+63.658 1.5 63.588 1.559 63.511 1.588 c
+63.43 1.625 63.353 1.646 63.276 1.646 c
+63.177 1.646 63.085 1.621 62.997 1.573 c
+62.916 1.532 62.85 1.463 62.791 1.367 c
+62.74 1.279 62.696 1.162 62.659 1.014 c
+62.63 0.875 62.615 0.706 62.615 0.5 c
+62.615 0.125 62.673 -0.154 62.791 -0.338 c
+62.908 -0.515 63.07 -0.602 63.276 -0.602 c
+63.342 -0.602 63.415 -0.588 63.496 -0.558 c
+63.585 -0.521 63.658 -0.463 63.717 -0.382 c
+63.783 -0.294 63.839 -0.176 63.879 -0.029 c
+63.926 0.118 63.952 0.302 63.952 0.53 c
+68.895 -0.249 m
+68.895 -0.419 68.855 -0.569 68.777 -0.706 c
+68.707 -0.833 68.604 -0.947 68.469 -1.043 c
+68.34 -1.132 68.178 -1.201 67.983 -1.249 c
+67.796 -1.297 67.579 -1.323 67.336 -1.323 c
+67.109 -1.323 66.91 -1.308 66.734 -1.278 c
+66.557 -1.249 66.399 -1.201 66.264 -1.132 c
+66.124 -1.055 66.014 -0.955 65.925 -0.837 c
+65.838 -0.72 65.767 -0.573 65.72 -0.397 c
+66.528 -0.279 l
+66.547 -0.378 66.576 -0.455 66.617 -0.515 c
+66.665 -0.573 66.723 -0.617 66.792 -0.646 c
+66.859 -0.675 66.94 -0.702 67.028 -0.72 c
+67.116 -0.731 67.219 -0.735 67.336 -0.735 c
+67.432 -0.735 67.528 -0.731 67.616 -0.72 c
+67.704 -0.702 67.781 -0.675 67.851 -0.646 c
+67.918 -0.617 67.968 -0.58 67.999 -0.529 c
+68.035 -0.481 68.057 -0.419 68.057 -0.338 c
+68.057 -0.242 68.028 -0.168 67.968 -0.118 c
+67.918 -0.07 67.851 -0.029 67.763 0 c
+67.675 0.037 67.565 0.067 67.44 0.088 c
+67.322 0.118 67.189 0.148 67.043 0.177 c
+66.903 0.214 66.763 0.254 66.617 0.294 c
+66.476 0.342 66.352 0.405 66.235 0.485 c
+66.124 0.563 66.036 0.661 65.969 0.779 c
+65.9 0.897 65.867 1.048 65.867 1.235 c
+65.867 1.389 65.896 1.532 65.955 1.661 c
+66.021 1.798 66.117 1.912 66.235 1.999 c
+66.359 2.087 66.517 2.153 66.705 2.205 c
+66.888 2.253 67.101 2.278 67.336 2.278 c
+67.521 2.278 67.697 2.257 67.866 2.22 c
+68.031 2.19 68.178 2.135 68.307 2.058 c
+68.431 1.989 68.542 1.889 68.63 1.764 c
+68.718 1.646 68.777 1.503 68.807 1.338 c
+68.013 1.264 l
+67.991 1.341 67.961 1.405 67.924 1.455 c
+67.884 1.515 67.837 1.559 67.777 1.588 c
+67.726 1.625 67.664 1.65 67.586 1.661 c
+67.506 1.669 67.425 1.676 67.336 1.676 c
+67.12 1.676 66.958 1.646 66.852 1.588 c
+66.742 1.536 66.69 1.448 66.69 1.324 c
+66.69 1.243 66.708 1.18 66.748 1.132 c
+66.796 1.081 66.859 1.044 66.94 1.014 c
+67.028 0.985 67.124 0.956 67.234 0.927 c
+67.34 0.904 67.461 0.882 67.602 0.853 c
+67.756 0.823 67.914 0.783 68.072 0.736 c
+68.226 0.684 68.365 0.622 68.483 0.544 c
+68.601 0.464 68.697 0.36 68.777 0.235 c
+68.855 0.107 68.895 -0.055 68.895 -0.249 c
+70.221 -2.631 m
+70.221 -2.013 l
+71.294 -2.013 l
+71.294 2.896 l
+70.221 2.896 l
+70.221 3.514 l
+72.147 3.514 l
+72.147 -2.631 l
+h
+78.729 -2.631 m
+78.729 3.514 l
+80.654 3.514 l
+80.654 2.896 l
+79.581 2.896 l
+79.581 -2.013 l
+80.654 -2.013 l
+80.654 -2.631 l
+h
+85.052 1.47 m
+84.953 1.478 84.851 1.488 84.744 1.5 c
+84.634 1.518 84.512 1.529 84.377 1.529 c
+84.2 1.529 84.042 1.488 83.906 1.411 c
+83.766 1.341 83.649 1.243 83.554 1.118 c
+83.465 0.989 83.396 0.842 83.348 0.676 c
+83.307 0.507 83.288 0.331 83.288 0.148 c
+83.288 -1.263 l
+82.392 -1.263 l
+82.392 0.985 l
+82.392 1.11 82.381 1.235 82.363 1.353 c
+82.351 1.478 82.337 1.595 82.318 1.706 c
+82.307 1.823 82.293 1.918 82.274 1.999 c
+82.253 2.087 82.234 2.161 82.216 2.22 c
+83.097 2.22 l
+83.105 2.168 83.116 2.117 83.127 2.058 c
+83.145 1.999 83.16 1.933 83.171 1.867 c
+83.19 1.808 83.205 1.742 83.215 1.676 c
+83.223 1.606 83.234 1.544 83.245 1.484 c
+83.259 1.484 l
+83.296 1.602 83.348 1.709 83.406 1.808 c
+83.473 1.904 83.554 1.989 83.641 2.058 c
+83.73 2.124 83.833 2.18 83.951 2.22 c
+84.075 2.257 84.223 2.278 84.391 2.278 c
+84.516 2.278 84.634 2.271 84.744 2.264 c
+84.861 2.253 84.965 2.238 85.052 2.22 c
+h
+87.658 -1.323 m
+87.401 -1.323 87.173 -1.286 86.968 -1.22 c
+86.762 -1.142 86.585 -1.028 86.438 -0.881 c
+86.291 -0.727 86.174 -0.536 86.085 -0.309 c
+86.004 -0.084 85.968 0.181 85.968 0.485 c
+85.968 0.817 86.012 1.095 86.1 1.324 c
+86.195 1.559 86.324 1.742 86.482 1.881 c
+86.648 2.018 86.835 2.117 87.041 2.176 c
+87.246 2.242 87.456 2.278 87.673 2.278 c
+87.945 2.278 88.18 2.228 88.379 2.132 c
+88.584 2.043 88.749 1.912 88.878 1.735 c
+89.014 1.565 89.113 1.36 89.172 1.118 c
+89.239 0.882 89.275 0.618 89.275 0.324 c
+89.275 0.309 l
+86.908 0.309 l
+86.908 0.162 86.923 0.023 86.953 -0.103 c
+86.989 -0.231 87.045 -0.345 87.114 -0.44 c
+87.18 -0.529 87.265 -0.598 87.364 -0.646 c
+87.46 -0.698 87.573 -0.72 87.702 -0.72 c
+87.857 -0.72 87.996 -0.687 88.113 -0.617 c
+88.239 -0.551 88.327 -0.448 88.379 -0.309 c
+89.216 -0.382 l
+89.187 -0.481 89.131 -0.588 89.054 -0.706 c
+88.973 -0.816 88.871 -0.918 88.746 -1.014 c
+88.628 -1.103 88.474 -1.176 88.29 -1.234 c
+88.113 -1.294 87.901 -1.323 87.658 -1.323 c
+87.658 1.706 m
+87.57 1.706 87.481 1.691 87.394 1.661 c
+87.305 1.632 87.224 1.58 87.159 1.515 c
+87.089 1.445 87.03 1.357 86.982 1.249 c
+86.941 1.139 86.923 1.014 86.923 0.867 c
+88.393 0.867 l
+88.393 1.004 88.367 1.125 88.319 1.235 c
+88.279 1.341 88.224 1.43 88.158 1.5 c
+88.099 1.565 88.026 1.617 87.937 1.646 c
+87.849 1.683 87.754 1.706 87.658 1.706 c
+91.322 -1.263 m
+91.322 0.853 l
+91.322 1.018 91.315 1.154 91.307 1.264 c
+91.296 1.371 91.278 1.455 91.248 1.515 c
+91.226 1.58 91.197 1.632 91.16 1.661 c
+91.13 1.691 91.09 1.706 91.043 1.706 c
+90.984 1.706 90.929 1.676 90.881 1.617 c
+90.841 1.565 90.808 1.492 90.778 1.397 c
+90.748 1.309 90.723 1.195 90.704 1.058 c
+90.694 0.919 90.69 0.769 90.69 0.603 c
+90.69 -1.263 l
+89.94 -1.263 l
+89.94 1.47 l
+89.94 1.706 l
+89.94 1.926 l
+89.94 2.003 89.933 2.066 89.925 2.117 c
+89.925 2.22 l
+90.602 2.22 l
+90.602 2.132 l
+90.602 1.985 l
+90.609 1.926 90.617 1.867 90.617 1.808 c
+90.617 1.646 l
+90.631 1.646 l
+90.65 1.735 90.679 1.812 90.719 1.881 c
+90.756 1.959 90.8 2.029 90.852 2.087 c
+90.91 2.147 90.976 2.19 91.057 2.22 c
+91.134 2.257 91.223 2.278 91.322 2.278 c
+91.506 2.278 91.645 2.224 91.733 2.117 c
+91.829 2.018 91.899 1.86 91.939 1.646 c
+91.954 1.646 l
+91.99 1.742 92.031 1.831 92.071 1.912 c
+92.119 1.989 92.175 2.051 92.233 2.103 c
+92.292 2.161 92.358 2.205 92.439 2.234 c
+92.516 2.264 92.604 2.278 92.703 2.278 c
+92.84 2.278 92.954 2.253 93.042 2.205 c
+93.129 2.153 93.196 2.08 93.247 1.985 c
+93.306 1.885 93.343 1.757 93.365 1.602 c
+93.395 1.455 93.409 1.272 93.409 1.058 c
+93.409 -1.263 l
+92.689 -1.263 l
+92.689 0.853 l
+92.689 1.018 92.682 1.154 92.674 1.264 c
+92.663 1.371 92.645 1.455 92.615 1.515 c
+92.593 1.58 92.564 1.632 92.527 1.661 c
+92.498 1.691 92.458 1.706 92.41 1.706 c
+92.292 1.706 92.196 1.617 92.13 1.441 c
+92.071 1.272 92.042 1.014 92.042 0.661 c
+92.042 -1.263 l
+h
+97.43 0.485 m
+97.43 0.21 97.393 -0.04 97.326 -0.264 c
+97.256 -0.481 97.154 -0.669 97.018 -0.823 c
+96.878 -0.981 96.701 -1.103 96.489 -1.19 c
+96.271 -1.278 96.018 -1.323 95.724 -1.323 c
+95.448 -1.323 95.202 -1.278 94.989 -1.19 c
+94.783 -1.103 94.611 -0.981 94.475 -0.823 c
+94.335 -0.669 94.232 -0.481 94.166 -0.264 c
+94.096 -0.04 94.064 0.21 94.064 0.485 c
+94.064 0.739 94.093 0.975 94.151 1.191 c
+94.218 1.415 94.32 1.606 94.46 1.764 c
+94.596 1.929 94.772 2.058 94.989 2.147 c
+95.202 2.234 95.46 2.278 95.753 2.278 c
+96.065 2.278 96.327 2.234 96.533 2.147 c
+96.746 2.058 96.919 1.929 97.047 1.764 c
+97.183 1.606 97.282 1.415 97.341 1.191 c
+97.399 0.975 97.43 0.739 97.43 0.485 c
+96.474 0.485 m
+96.474 0.691 96.459 0.867 96.43 1.014 c
+96.408 1.162 96.371 1.283 96.312 1.382 c
+96.254 1.478 96.18 1.548 96.092 1.588 c
+96.003 1.636 95.893 1.661 95.768 1.661 c
+95.504 1.661 95.313 1.563 95.195 1.367 c
+95.078 1.18 95.018 0.886 95.018 0.485 c
+95.018 0.063 95.078 -0.242 95.195 -0.426 c
+95.313 -0.613 95.489 -0.706 95.724 -0.706 c
+95.849 -0.706 95.963 -0.687 96.063 -0.646 c
+96.158 -0.598 96.239 -0.525 96.298 -0.426 c
+96.364 -0.33 96.408 -0.205 96.43 -0.058 c
+96.459 0.088 96.474 0.269 96.474 0.485 c
+98.888 1.602 m
+98.344 1.602 l
+98.344 2.22 l
+98.932 2.22 l
+99.211 3.117 l
+99.785 3.117 l
+99.785 2.22 l
+101.019 2.22 l
+101.019 1.602 l
+99.785 1.602 l
+99.785 -0.103 l
+99.785 -0.323 l
+99.792 -0.393 99.814 -0.455 99.843 -0.515 c
+99.88 -0.565 99.936 -0.61 100.005 -0.646 c
+100.082 -0.675 100.196 -0.691 100.343 -0.691 c
+100.479 -0.691 100.615 -0.687 100.755 -0.675 c
+100.891 -0.658 101.023 -0.632 101.152 -0.602 c
+101.152 -1.205 l
+101.071 -1.216 100.994 -1.23 100.917 -1.249 c
+100.836 -1.26 100.759 -1.267 100.682 -1.278 c
+100.601 -1.286 100.512 -1.294 100.416 -1.294 c
+100.329 -1.3 100.229 -1.308 100.123 -1.308 c
+99.936 -1.308 99.774 -1.294 99.637 -1.263 c
+99.51 -1.227 99.396 -1.183 99.3 -1.132 c
+99.211 -1.084 99.138 -1.024 99.08 -0.955 c
+99.02 -0.878 98.976 -0.801 98.947 -0.72 c
+98.918 -0.632 98.895 -0.544 98.888 -0.455 c
+98.877 -0.359 98.874 -0.264 98.874 -0.176 c
+h
+103.904 -1.323 m
+103.647 -1.323 103.419 -1.286 103.213 -1.22 c
+103.007 -1.142 102.831 -1.028 102.685 -0.881 c
+102.537 -0.727 102.419 -0.536 102.332 -0.309 c
+102.251 -0.084 102.214 0.181 102.214 0.485 c
+102.214 0.817 102.257 1.095 102.346 1.324 c
+102.442 1.559 102.571 1.742 102.728 1.881 c
+102.893 2.018 103.082 2.117 103.287 2.176 c
+103.493 2.242 103.702 2.278 103.919 2.278 c
+104.191 2.278 104.426 2.228 104.624 2.132 c
+104.83 2.043 104.996 1.912 105.124 1.735 c
+105.26 1.565 105.359 1.36 105.418 1.118 c
+105.484 0.882 105.521 0.618 105.521 0.324 c
+105.521 0.309 l
+103.155 0.309 l
+103.155 0.162 103.169 0.023 103.198 -0.103 c
+103.236 -0.231 103.29 -0.345 103.36 -0.44 c
+103.427 -0.529 103.511 -0.598 103.61 -0.646 c
+103.706 -0.698 103.82 -0.72 103.948 -0.72 c
+104.102 -0.72 104.242 -0.687 104.36 -0.617 c
+104.485 -0.551 104.573 -0.448 104.624 -0.309 c
+105.463 -0.382 l
+105.433 -0.481 105.378 -0.588 105.301 -0.706 c
+105.22 -0.816 105.117 -0.918 104.992 -1.014 c
+104.875 -1.103 104.72 -1.176 104.536 -1.234 c
+104.36 -1.294 104.146 -1.323 103.904 -1.323 c
+103.904 1.706 m
+103.816 1.706 103.728 1.691 103.639 1.661 c
+103.552 1.632 103.471 1.58 103.404 1.515 c
+103.335 1.445 103.276 1.357 103.228 1.249 c
+103.188 1.139 103.169 1.014 103.169 0.867 c
+104.639 0.867 l
+104.639 1.004 104.613 1.125 104.566 1.235 c
+104.526 1.341 104.47 1.43 104.404 1.5 c
+104.345 1.565 104.272 1.617 104.183 1.646 c
+104.096 1.683 104 1.706 103.904 1.706 c
+106.774 -2.631 m
+106.774 -2.013 l
+107.847 -2.013 l
+107.847 2.896 l
+106.774 2.896 l
+106.774 3.514 l
+108.7 3.514 l
+108.7 -2.631 l
+h
+f
+Q
+q 1 0 0 1 95.2978 172.2447 cm
+0 0 m
+0 -2.103 l
+-0.675 -2.103 l
+-0.675 3.248 l
+1.029 3.248 l
+1.529 3.248 1.918 3.094 2.205 2.793 c
+2.488 2.499 2.631 2.105 2.631 1.617 c
+2.631 1.095 2.492 0.698 2.22 0.426 c
+1.955 0.151 1.577 0.008 1.088 0 c
+h
+0 0.573 m
+1.029 0.573 l
+1.33 0.573 1.563 0.661 1.72 0.837 c
+1.875 1.014 1.955 1.268 1.955 1.602 c
+1.955 1.926 1.871 2.183 1.706 2.381 c
+1.548 2.576 1.327 2.675 1.044 2.675 c
+0 2.675 l
+h
+5.439 -1.75 m
+5.222 -2.036 4.91 -2.176 4.499 -2.176 c
+4.135 -2.176 3.859 -2.055 3.675 -1.808 c
+3.499 -1.554 3.404 -1.191 3.396 -0.721 c
+3.396 1.881 l
+4.042 1.881 l
+4.042 -0.661 l
+4.042 -1.29 4.227 -1.602 4.601 -1.602 c
+5.002 -1.602 5.278 -1.426 5.424 -1.073 c
+5.424 1.881 l
+6.072 1.881 l
+6.072 -2.103 l
+5.453 -2.103 l
+h
+8.996 -1.088 m
+8.996 -0.941 8.941 -0.819 8.834 -0.721 c
+8.724 -0.625 8.518 -0.507 8.217 -0.368 c
+7.872 -0.221 7.629 -0.1 7.483 0 c
+7.335 0.106 7.225 0.224 7.159 0.353 c
+7.089 0.478 7.056 0.636 7.056 0.823 c
+7.056 1.147 7.173 1.415 7.408 1.631 c
+7.644 1.845 7.945 1.955 8.32 1.955 c
+8.702 1.955 9.01 1.841 9.246 1.617 c
+9.481 1.389 9.599 1.103 9.599 0.75 c
+8.952 0.75 l
+8.952 0.926 8.894 1.076 8.775 1.205 c
+8.659 1.33 8.503 1.396 8.32 1.396 c
+8.121 1.396 7.971 1.341 7.865 1.234 c
+7.755 1.135 7.703 1.003 7.703 0.837 c
+7.703 0.709 7.739 0.602 7.82 0.515 c
+7.898 0.434 8.088 0.33 8.393 0.206 c
+8.871 0.018 9.202 -0.169 9.378 -0.353 c
+9.555 -0.53 9.643 -0.757 9.643 -1.029 c
+9.643 -1.382 9.518 -1.661 9.276 -1.867 c
+9.041 -2.072 8.724 -2.176 8.335 -2.176 c
+7.913 -2.176 7.574 -2.058 7.321 -1.823 c
+7.063 -1.58 6.938 -1.276 6.938 -0.912 c
+7.585 -0.912 l
+7.593 -1.139 7.662 -1.316 7.791 -1.44 c
+7.915 -1.558 8.1 -1.617 8.335 -1.617 c
+8.548 -1.617 8.709 -1.569 8.819 -1.47 c
+8.937 -1.374 8.996 -1.246 8.996 -1.088 c
+11.127 1.469 m
+11.381 1.793 11.701 1.955 12.083 1.955 c
+12.788 1.955 13.145 1.484 13.156 0.544 c
+13.156 -2.103 l
+12.509 -2.103 l
+12.509 0.515 l
+12.509 0.827 12.454 1.047 12.347 1.176 c
+12.237 1.301 12.083 1.367 11.877 1.367 c
+11.719 1.367 11.572 1.311 11.437 1.205 c
+11.308 1.095 11.205 0.959 11.127 0.794 c
+11.127 -2.103 l
+10.481 -2.103 l
+10.481 3.542 l
+11.127 3.542 l
+h
+16.536 -2.103 -0.646 5.644 re
+17.419 0.073 m
+17.419 0.65 17.555 1.106 17.831 1.44 c
+18.113 1.782 18.485 1.955 18.947 1.955 c
+19.407 1.955 19.774 1.786 20.05 1.455 c
+20.333 1.132 20.48 0.683 20.491 0.118 c
+20.491 -0.309 l
+20.491 -0.879 20.347 -1.334 20.064 -1.675 c
+19.789 -2.01 19.422 -2.176 18.962 -2.176 c
+18.499 -2.176 18.128 -2.014 17.845 -1.691 c
+17.569 -1.359 17.426 -0.919 17.419 -0.368 c
+h
+18.066 -0.309 m
+18.066 -0.713 18.143 -1.029 18.301 -1.264 c
+18.466 -1.5 18.687 -1.617 18.962 -1.617 c
+19.528 -1.617 19.822 -1.205 19.844 -0.382 c
+19.844 0.073 l
+19.844 0.474 19.759 0.794 19.594 1.029 c
+19.437 1.271 19.219 1.396 18.947 1.396 c
+18.683 1.396 18.466 1.271 18.301 1.029 c
+18.143 0.794 18.066 0.474 18.066 0.073 c
+h
+22.71 -1.617 m
+22.924 -1.617 23.096 -1.554 23.225 -1.426 c
+23.36 -1.29 23.435 -1.099 23.445 -0.852 c
+24.062 -0.852 l
+24.041 -1.235 23.905 -1.554 23.651 -1.808 c
+23.394 -2.055 23.082 -2.176 22.71 -2.176 c
+22.218 -2.176 21.843 -2.024 21.579 -1.72 c
+21.321 -1.407 21.197 -0.941 21.197 -0.324 c
+21.197 0.118 l
+21.197 0.713 21.321 1.168 21.579 1.484 c
+21.843 1.797 22.218 1.955 22.71 1.955 c
+23.111 1.955 23.431 1.822 23.666 1.558 c
+23.908 1.301 24.041 0.955 24.062 0.515 c
+23.445 0.515 l
+23.423 0.808 23.35 1.029 23.225 1.176 c
+23.107 1.323 22.934 1.396 22.71 1.396 c
+22.416 1.396 22.2 1.297 22.064 1.103 c
+21.924 0.915 21.851 0.606 21.843 0.176 c
+21.843 -0.339 l
+21.843 -0.809 21.909 -1.143 22.049 -1.338 c
+22.196 -1.525 22.416 -1.617 22.71 -1.617 c
+26.855 -2.103 m
+26.815 -2.014 26.789 -1.867 26.782 -1.661 c
+26.547 -2.007 26.253 -2.176 25.9 -2.176 c
+25.536 -2.176 25.253 -2.08 25.047 -1.881 c
+24.849 -1.675 24.754 -1.389 24.754 -1.014 c
+24.754 -0.613 24.889 -0.294 25.165 -0.059 c
+25.437 0.183 25.812 0.309 26.282 0.309 c
+26.768 0.309 l
+26.768 0.735 l
+26.768 0.97 26.712 1.135 26.606 1.234 c
+26.495 1.341 26.334 1.396 26.121 1.396 c
+25.922 1.396 25.76 1.338 25.635 1.22 c
+25.518 1.103 25.459 0.955 25.459 0.779 c
+24.812 0.779 l
+24.812 0.974 24.871 1.165 24.989 1.352 c
+25.114 1.536 25.276 1.683 25.473 1.793 c
+25.679 1.899 25.907 1.955 26.165 1.955 c
+26.566 1.955 26.87 1.852 27.076 1.646 c
+27.289 1.44 27.403 1.147 27.414 0.764 c
+27.414 -1.249 l
+27.414 -1.554 27.451 -1.819 27.532 -2.043 c
+27.532 -2.103 l
+h
+25.988 -1.588 m
+26.154 -1.588 26.304 -1.544 26.444 -1.455 c
+26.591 -1.367 26.697 -1.257 26.768 -1.118 c
+26.768 -0.177 l
+26.4 -0.177 l
+26.084 -0.177 25.841 -0.246 25.665 -0.382 c
+25.488 -0.511 25.4 -0.698 25.4 -0.941 c
+25.4 -1.168 25.444 -1.334 25.533 -1.44 c
+25.621 -1.54 25.772 -1.588 25.988 -1.588 c
+29.12 -2.103 -0.647 5.644 re
+33.234 -1.617 m
+33.448 -1.617 33.621 -1.554 33.749 -1.426 c
+33.885 -1.29 33.959 -1.099 33.97 -0.852 c
+34.587 -0.852 l
+34.566 -1.235 34.429 -1.554 34.175 -1.808 c
+33.918 -2.055 33.606 -2.176 33.234 -2.176 c
+32.742 -2.176 32.368 -2.024 32.103 -1.72 c
+31.846 -1.407 31.721 -0.941 31.721 -0.324 c
+31.721 0.118 l
+31.721 0.713 31.846 1.168 32.103 1.484 c
+32.368 1.797 32.742 1.955 33.234 1.955 c
+33.635 1.955 33.955 1.822 34.19 1.558 c
+34.433 1.301 34.566 0.955 34.587 0.515 c
+33.97 0.515 l
+33.948 0.808 33.874 1.029 33.749 1.176 c
+33.631 1.323 33.459 1.396 33.234 1.396 c
+32.941 1.396 32.725 1.297 32.588 1.103 c
+32.449 0.915 32.375 0.606 32.368 0.176 c
+32.368 -0.339 l
+32.368 -0.809 32.434 -1.143 32.573 -1.338 c
+32.721 -1.525 32.941 -1.617 33.234 -1.617 c
+35.983 1.469 m
+36.237 1.793 36.557 1.955 36.939 1.955 c
+37.645 1.955 38.001 1.484 38.012 0.544 c
+38.012 -2.103 l
+37.365 -2.103 l
+37.365 0.515 l
+37.365 0.827 37.311 1.047 37.203 1.176 c
+37.093 1.301 36.939 1.367 36.733 1.367 c
+36.575 1.367 36.428 1.311 36.292 1.205 c
+36.164 1.095 36.06 0.959 35.983 0.794 c
+35.983 -2.103 l
+35.337 -2.103 l
+35.337 3.542 l
+35.983 3.542 l
+h
+41.011 -2.103 m
+40.97 -2.014 40.945 -1.867 40.937 -1.661 c
+40.702 -2.007 40.409 -2.176 40.055 -2.176 c
+39.692 -2.176 39.409 -2.08 39.202 -1.881 c
+39.004 -1.675 38.909 -1.389 38.909 -1.014 c
+38.909 -0.613 39.044 -0.294 39.32 -0.059 c
+39.592 0.183 39.967 0.309 40.438 0.309 c
+40.922 0.309 l
+40.922 0.735 l
+40.922 0.97 40.868 1.135 40.76 1.234 c
+40.65 1.341 40.488 1.396 40.276 1.396 c
+40.077 1.396 39.916 1.338 39.79 1.22 c
+39.673 1.103 39.615 0.955 39.615 0.779 c
+38.967 0.779 l
+38.967 0.974 39.027 1.165 39.144 1.352 c
+39.269 1.536 39.43 1.683 39.629 1.793 c
+39.835 1.899 40.062 1.955 40.32 1.955 c
+40.721 1.955 41.026 1.852 41.231 1.646 c
+41.444 1.44 41.558 1.147 41.569 0.764 c
+41.569 -1.249 l
+41.569 -1.554 41.606 -1.819 41.687 -2.043 c
+41.687 -2.103 l
+h
+40.143 -1.588 m
+40.309 -1.588 40.459 -1.544 40.599 -1.455 c
+40.746 -1.367 40.853 -1.257 40.922 -1.118 c
+40.922 -0.177 l
+40.555 -0.177 l
+40.239 -0.177 39.996 -0.246 39.82 -0.382 c
+39.644 -0.511 39.555 -0.698 39.555 -0.941 c
+39.555 -1.168 39.599 -1.334 39.688 -1.44 c
+39.776 -1.54 39.927 -1.588 40.143 -1.588 c
+43.187 1.881 m
+43.201 1.44 l
+43.455 1.782 43.778 1.955 44.171 1.955 c
+44.877 1.955 45.233 1.484 45.244 0.544 c
+45.244 -2.103 l
+44.598 -2.103 l
+44.598 0.515 l
+44.598 0.827 44.542 1.047 44.436 1.176 c
+44.326 1.301 44.171 1.367 43.965 1.367 c
+43.807 1.367 43.661 1.311 43.524 1.205 c
+43.395 1.095 43.293 0.959 43.216 0.794 c
+43.216 -2.103 l
+42.568 -2.103 l
+42.568 1.881 l
+h
+46.082 0.073 m
+46.082 0.69 46.192 1.153 46.42 1.469 c
+46.644 1.793 46.979 1.955 47.42 1.955 c
+47.82 1.955 48.125 1.778 48.33 1.425 c
+48.375 1.881 l
+48.963 1.881 l
+48.963 -2.146 l
+48.963 -2.635 48.835 -3.013 48.581 -3.278 c
+48.324 -3.543 47.971 -3.675 47.522 -3.675 c
+47.324 -3.675 47.104 -3.624 46.861 -3.528 c
+46.615 -3.429 46.435 -3.308 46.317 -3.161 c
+46.582 -2.72 l
+46.846 -2.984 47.144 -3.117 47.478 -3.117 c
+48.014 -3.117 48.29 -2.822 48.301 -2.234 c
+48.301 -1.706 l
+48.095 -2.022 47.794 -2.176 47.405 -2.176 c
+46.994 -2.176 46.67 -2.024 46.435 -1.72 c
+46.207 -1.407 46.09 -0.956 46.082 -0.368 c
+h
+46.743 -0.309 m
+46.743 -0.75 46.806 -1.081 46.934 -1.294 c
+47.06 -1.5 47.276 -1.602 47.581 -1.602 c
+47.904 -1.602 48.143 -1.437 48.301 -1.103 c
+48.301 0.881 l
+48.132 1.205 47.894 1.367 47.581 1.367 c
+47.287 1.367 47.071 1.264 46.934 1.058 c
+46.806 0.852 46.743 0.529 46.743 0.088 c
+h
+51.344 -2.176 m
+50.844 -2.176 50.462 -2.028 50.198 -1.735 c
+49.933 -1.44 49.801 -1.007 49.801 -0.426 c
+49.801 0.044 l
+49.801 0.64 49.926 1.106 50.183 1.44 c
+50.447 1.782 50.807 1.955 51.27 1.955 c
+51.73 1.955 52.072 1.801 52.299 1.5 c
+52.535 1.205 52.656 0.742 52.667 0.118 c
+52.667 -0.309 l
+50.447 -0.309 l
+50.447 -0.397 l
+50.447 -0.831 50.524 -1.143 50.682 -1.338 c
+50.848 -1.525 51.079 -1.617 51.374 -1.617 c
+51.568 -1.617 51.741 -1.584 51.888 -1.515 c
+52.035 -1.437 52.171 -1.319 52.299 -1.162 c
+52.638 -1.573 l
+52.351 -1.977 51.921 -2.176 51.344 -2.176 c
+51.27 1.396 m
+50.995 1.396 50.793 1.301 50.668 1.117 c
+50.539 0.929 50.466 0.64 50.447 0.249 c
+52.02 0.249 l
+52.02 0.338 l
+51.998 0.72 51.933 0.989 51.814 1.147 c
+51.697 1.311 51.513 1.396 51.27 1.396 c
+55.386 -1.088 m
+55.386 -0.941 55.331 -0.819 55.225 -0.721 c
+55.114 -0.625 54.909 -0.507 54.607 -0.368 c
+54.262 -0.221 54.019 -0.1 53.872 0 c
+53.726 0.106 53.616 0.224 53.549 0.353 c
+53.479 0.478 53.446 0.636 53.446 0.823 c
+53.446 1.147 53.564 1.415 53.799 1.631 c
+54.034 1.845 54.335 1.955 54.711 1.955 c
+55.093 1.955 55.401 1.841 55.636 1.617 c
+55.871 1.389 55.989 1.103 55.989 0.75 c
+55.342 0.75 l
+55.342 0.926 55.283 1.076 55.166 1.205 c
+55.048 1.33 54.894 1.396 54.711 1.396 c
+54.512 1.396 54.362 1.341 54.254 1.234 c
+54.144 1.135 54.092 1.003 54.092 0.837 c
+54.092 0.709 54.129 0.602 54.21 0.515 c
+54.287 0.434 54.479 0.33 54.784 0.206 c
+55.262 0.018 55.592 -0.169 55.769 -0.353 c
+55.945 -0.53 56.033 -0.757 56.033 -1.029 c
+56.033 -1.382 55.908 -1.661 55.665 -1.867 c
+55.43 -2.072 55.114 -2.176 54.725 -2.176 c
+54.302 -2.176 53.965 -2.058 53.711 -1.823 c
+53.454 -1.58 53.329 -1.276 53.329 -0.912 c
+53.975 -0.912 l
+53.982 -1.139 54.052 -1.316 54.181 -1.44 c
+54.306 -1.558 54.49 -1.617 54.725 -1.617 c
+54.938 -1.617 55.1 -1.569 55.21 -1.47 c
+55.328 -1.374 55.386 -1.246 55.386 -1.088 c
+59.443 2.836 m
+59.443 1.881 l
+60.046 1.881 l
+60.046 1.352 l
+59.443 1.352 l
+59.443 -1.118 l
+59.443 -1.276 59.465 -1.393 59.517 -1.47 c
+59.575 -1.551 59.664 -1.588 59.781 -1.588 c
+59.87 -1.588 59.958 -1.573 60.046 -1.544 c
+60.046 -2.103 l
+59.899 -2.15 59.744 -2.176 59.59 -2.176 c
+59.333 -2.176 59.139 -2.084 59.002 -1.897 c
+58.863 -1.712 58.796 -1.452 58.796 -1.118 c
+58.796 1.352 l
+58.194 1.352 l
+58.194 1.881 l
+58.796 1.881 l
+58.796 2.836 l
+h
+60.604 0.073 m
+60.604 0.65 60.741 1.106 61.016 1.44 c
+61.3 1.782 61.67 1.955 62.133 1.955 c
+62.593 1.955 62.96 1.786 63.236 1.455 c
+63.519 1.132 63.665 0.683 63.677 0.118 c
+63.677 -0.309 l
+63.677 -0.879 63.534 -1.334 63.251 -1.675 c
+62.975 -2.01 62.607 -2.176 62.148 -2.176 c
+61.685 -2.176 61.314 -2.014 61.03 -1.691 c
+60.755 -1.359 60.612 -0.919 60.604 -0.368 c
+h
+61.252 -0.309 m
+61.252 -0.713 61.329 -1.029 61.487 -1.264 c
+61.652 -1.5 61.872 -1.617 62.148 -1.617 c
+62.713 -1.617 63.008 -1.205 63.03 -0.382 c
+63.03 0.073 l
+63.03 0.474 62.946 0.794 62.78 1.029 c
+62.622 1.271 62.405 1.396 62.133 1.396 c
+61.869 1.396 61.652 1.271 61.487 1.029 c
+61.329 0.794 61.252 0.474 61.252 0.073 c
+h
+67.087 2.836 m
+67.087 1.881 l
+67.69 1.881 l
+67.69 1.352 l
+67.087 1.352 l
+67.087 -1.118 l
+67.087 -1.276 67.109 -1.393 67.16 -1.47 c
+67.22 -1.551 67.307 -1.588 67.425 -1.588 c
+67.513 -1.588 67.602 -1.573 67.69 -1.544 c
+67.69 -2.103 l
+67.542 -2.15 67.388 -2.176 67.234 -2.176 c
+66.977 -2.176 66.782 -2.084 66.646 -1.897 c
+66.507 -1.712 66.44 -1.452 66.44 -1.118 c
+66.44 1.352 l
+65.838 1.352 l
+65.838 1.881 l
+66.44 1.881 l
+66.44 2.836 l
+h
+69.101 1.469 m
+69.354 1.793 69.674 1.955 70.056 1.955 c
+70.761 1.955 71.118 1.484 71.129 0.544 c
+71.129 -2.103 l
+70.482 -2.103 l
+70.482 0.515 l
+70.482 0.827 70.428 1.047 70.32 1.176 c
+70.21 1.301 70.056 1.367 69.85 1.367 c
+69.692 1.367 69.545 1.311 69.41 1.205 c
+69.281 1.095 69.178 0.959 69.101 0.794 c
+69.101 -2.103 l
+68.454 -2.103 l
+68.454 3.542 l
+69.101 3.542 l
+h
+73.51 -2.176 m
+73.011 -2.176 72.629 -2.028 72.364 -1.735 c
+72.099 -1.44 71.967 -1.007 71.967 -0.426 c
+71.967 0.044 l
+71.967 0.64 72.092 1.106 72.349 1.44 c
+72.614 1.782 72.974 1.955 73.437 1.955 c
+73.896 1.955 74.238 1.801 74.466 1.5 c
+74.701 1.205 74.823 0.742 74.833 0.118 c
+74.833 -0.309 l
+72.614 -0.309 l
+72.614 -0.397 l
+72.614 -0.831 72.691 -1.143 72.849 -1.338 c
+73.015 -1.525 73.246 -1.617 73.539 -1.617 c
+73.734 -1.617 73.907 -1.584 74.054 -1.515 c
+74.201 -1.437 74.337 -1.319 74.466 -1.162 c
+74.804 -1.573 l
+74.517 -1.977 74.087 -2.176 73.51 -2.176 c
+73.437 1.396 m
+73.161 1.396 72.959 1.301 72.834 1.117 c
+72.706 0.929 72.632 0.64 72.614 0.249 c
+74.187 0.249 l
+74.187 0.338 l
+74.164 0.72 74.098 0.989 73.981 1.147 c
+73.863 1.311 73.68 1.396 73.437 1.396 c
+f
+Q
+q 1 0 0 1 174.4817 173.112 cm
+0 0 m
+-0.338 0.029 l
+-0.625 0.029 -0.816 -0.096 -0.911 -0.339 c
+-0.911 -2.97 l
+-1.955 -2.97 l
+-1.955 1.014 l
+-0.985 1.014 l
+-0.955 0.573 l
+-0.79 0.914 -0.559 1.087 -0.264 1.087 c
+-0.147 1.087 -0.055 1.066 0.015 1.028 c
+h
+2.072 -3.043 m
+1.544 -3.043 1.125 -2.889 0.823 -2.573 c
+0.53 -2.249 0.382 -1.79 0.382 -1.191 c
+0.382 -0.882 l
+0.382 -0.258 0.518 0.228 0.794 0.573 c
+1.066 0.914 1.459 1.087 1.97 1.087 c
+2.469 1.087 2.841 0.926 3.088 0.602 c
+3.341 0.279 3.473 -0.198 3.484 -0.823 c
+3.484 -1.324 l
+1.411 -1.324 l
+1.43 -1.617 1.492 -1.834 1.602 -1.97 c
+1.72 -2.109 1.9 -2.176 2.147 -2.176 c
+2.488 -2.176 2.778 -2.058 3.013 -1.823 c
+3.425 -2.455 l
+3.296 -2.631 3.109 -2.774 2.866 -2.881 c
+2.62 -2.988 2.356 -3.043 2.072 -3.043 c
+1.426 -0.603 m
+2.455 -0.603 l
+2.455 -0.5 l
+2.455 -0.265 2.415 -0.088 2.338 0.029 c
+2.267 0.154 2.139 0.22 1.955 0.22 c
+1.779 0.22 1.646 0.151 1.558 0.014 c
+1.478 -0.114 1.434 -0.32 1.426 -0.603 c
+5.042 1.014 m
+5.072 0.646 l
+5.307 0.941 5.615 1.087 5.997 1.087 c
+6.398 1.087 6.677 0.904 6.835 0.544 c
+7.071 0.904 7.398 1.087 7.82 1.087 c
+8.515 1.087 8.867 0.602 8.879 -0.368 c
+8.879 -2.97 l
+7.85 -2.97 l
+7.85 -0.426 l
+7.85 -0.202 7.813 -0.04 7.747 0.058 c
+7.688 0.154 7.578 0.205 7.423 0.205 c
+7.225 0.205 7.086 0.087 6.997 -0.148 c
+6.997 -2.97 l
+5.953 -2.97 l
+5.953 -0.441 l
+5.953 -0.206 5.924 -0.04 5.866 0.058 c
+5.806 0.154 5.696 0.205 5.542 0.205 c
+5.365 0.205 5.222 0.11 5.116 -0.073 c
+5.116 -2.97 l
+4.072 -2.97 l
+4.072 1.014 l
+h
+9.54 -0.853 m
+9.54 -0.246 9.679 0.228 9.966 0.573 c
+10.249 0.914 10.643 1.087 11.142 1.087 c
+11.649 1.087 12.046 0.914 12.333 0.573 c
+12.615 0.228 12.759 -0.246 12.759 -0.853 c
+12.759 -1.118 l
+12.759 -1.716 12.615 -2.186 12.333 -2.529 c
+12.046 -2.874 11.649 -3.043 11.142 -3.043 c
+10.631 -3.043 10.234 -2.874 9.951 -2.529 c
+9.675 -2.186 9.54 -1.713 9.54 -1.103 c
+h
+10.583 -1.118 m
+10.583 -1.823 10.768 -2.176 11.142 -2.176 c
+11.495 -2.176 11.686 -1.881 11.715 -1.294 c
+11.715 -0.853 l
+11.715 -0.493 11.664 -0.221 11.568 -0.044 c
+11.469 0.132 11.326 0.22 11.142 0.22 c
+10.965 0.22 10.826 0.132 10.73 -0.044 c
+10.631 -0.221 10.583 -0.493 10.583 -0.853 c
+h
+14.612 1.984 m
+14.612 1.014 l
+15.14 1.014 l
+15.14 0.22 l
+14.612 0.22 l
+14.612 -1.75 l
+14.612 -1.908 14.629 -2.014 14.67 -2.072 c
+14.718 -2.132 14.803 -2.161 14.92 -2.161 c
+15.026 -2.161 15.111 -2.153 15.169 -2.132 c
+15.169 -2.94 l
+14.993 -3.007 14.803 -3.043 14.596 -3.043 c
+13.92 -3.043 13.575 -2.657 13.567 -1.881 c
+13.567 0.22 l
+13.112 0.22 l
+13.112 1.014 l
+13.567 1.014 l
+13.567 1.984 l
+h
+17.315 -3.043 m
+16.787 -3.043 16.368 -2.889 16.066 -2.573 c
+15.772 -2.249 15.626 -1.79 15.626 -1.191 c
+15.626 -0.882 l
+15.626 -0.258 15.761 0.228 16.037 0.573 c
+16.309 0.914 16.702 1.087 17.213 1.087 c
+17.712 1.087 18.084 0.926 18.33 0.602 c
+18.583 0.279 18.716 -0.198 18.726 -0.823 c
+18.726 -1.324 l
+16.654 -1.324 l
+16.673 -1.617 16.735 -1.834 16.845 -1.97 c
+16.963 -2.109 17.143 -2.176 17.39 -2.176 c
+17.731 -2.176 18.021 -2.058 18.256 -1.823 c
+18.668 -2.455 l
+18.539 -2.631 18.352 -2.774 18.109 -2.881 c
+17.864 -2.988 17.598 -3.043 17.315 -3.043 c
+16.669 -0.603 m
+17.698 -0.603 l
+17.698 -0.5 l
+17.698 -0.265 17.658 -0.088 17.581 0.029 c
+17.511 0.154 17.382 0.22 17.199 0.22 c
+17.022 0.22 16.889 0.151 16.802 0.014 c
+16.721 -0.114 16.676 -0.32 16.669 -0.603 c
+f
+Q
+q 1 0 0 1 193.9437 170.4949 cm
+0 0 m
+0 0.118 0.033 0.214 0.103 0.294 c
+0.168 0.372 0.272 0.412 0.411 0.412 c
+0.559 0.412 0.665 0.372 0.735 0.294 c
+0.812 0.214 0.852 0.118 0.852 0 c
+0.852 -0.11 0.812 -0.201 0.735 -0.278 c
+0.665 -0.356 0.559 -0.396 0.411 -0.396 c
+0.272 -0.396 0.168 -0.356 0.103 -0.278 c
+0.033 -0.201 0 -0.11 0 0 c
+6.938 4.998 m
+6.938 1.191 l
+6.938 0.691 6.79 0.294 6.497 0 c
+6.21 -0.286 5.81 -0.426 5.292 -0.426 c
+4.762 -0.426 4.355 -0.29 4.072 -0.014 c
+3.796 0.269 3.659 0.669 3.659 1.191 c
+3.659 4.998 l
+4.322 4.998 l
+4.322 1.22 l
+4.322 0.857 4.395 0.588 4.542 0.412 c
+4.696 0.235 4.946 0.148 5.292 0.148 c
+5.633 0.148 5.88 0.235 6.026 0.412 c
+6.181 0.588 6.262 0.857 6.262 1.22 c
+6.262 4.998 l
+h
+9.834 0.662 m
+9.834 0.809 9.778 0.93 9.672 1.029 c
+9.562 1.125 9.356 1.243 9.055 1.382 c
+8.709 1.529 8.467 1.65 8.32 1.75 c
+8.172 1.856 8.062 1.974 7.996 2.103 c
+7.927 2.228 7.893 2.386 7.893 2.573 c
+7.893 2.897 8.01 3.165 8.246 3.381 c
+8.481 3.595 8.783 3.705 9.157 3.705 c
+9.539 3.705 9.848 3.591 10.083 3.367 c
+10.318 3.138 10.437 2.852 10.437 2.5 c
+9.789 2.5 l
+9.789 2.675 9.731 2.826 9.612 2.955 c
+9.496 3.08 9.341 3.146 9.157 3.146 c
+8.959 3.146 8.808 3.091 8.702 2.984 c
+8.592 2.885 8.54 2.753 8.54 2.587 c
+8.54 2.459 8.577 2.352 8.658 2.264 c
+8.735 2.183 8.926 2.08 9.231 1.956 c
+9.708 1.768 10.04 1.58 10.215 1.397 c
+10.392 1.22 10.48 0.992 10.48 0.721 c
+10.48 0.368 10.356 0.088 10.113 -0.118 c
+9.878 -0.323 9.562 -0.426 9.172 -0.426 c
+8.75 -0.426 8.411 -0.309 8.158 -0.073 c
+7.9 0.169 7.775 0.474 7.775 0.838 c
+8.422 0.838 l
+8.43 0.611 8.5 0.434 8.628 0.309 c
+8.753 0.192 8.937 0.133 9.172 0.133 c
+9.385 0.133 9.547 0.181 9.657 0.279 c
+9.774 0.375 9.834 0.504 9.834 0.662 c
+12.744 -0.426 m
+12.244 -0.426 11.862 -0.278 11.597 0.015 c
+11.333 0.309 11.2 0.743 11.2 1.324 c
+11.2 1.794 l
+11.2 2.389 11.326 2.856 11.582 3.19 c
+11.848 3.532 12.207 3.705 12.67 3.705 c
+13.13 3.705 13.471 3.55 13.699 3.249 c
+13.934 2.955 14.056 2.492 14.067 1.867 c
+14.067 1.441 l
+11.848 1.441 l
+11.848 1.353 l
+11.848 0.919 11.925 0.607 12.083 0.412 c
+12.247 0.225 12.479 0.133 12.773 0.133 c
+12.968 0.133 13.14 0.166 13.288 0.235 c
+13.435 0.313 13.571 0.431 13.699 0.588 c
+14.038 0.177 l
+13.751 -0.228 13.321 -0.426 12.744 -0.426 c
+12.67 3.146 m
+12.395 3.146 12.193 3.051 12.068 2.866 c
+11.939 2.679 11.866 2.389 11.848 1.999 c
+13.42 1.999 l
+13.42 2.087 l
+13.398 2.469 13.332 2.738 13.215 2.897 c
+13.097 3.061 12.913 3.146 12.67 3.146 c
+f
+Q
+212.273 172.01 -1.793 0.867 re
+215.007 172.01 -1.793 0.867 re
+217.08 175.096 m
+217.08 174.126 l
+217.609 174.126 l
+217.609 173.332 l
+217.08 173.332 l
+217.08 171.362 l
+217.08 171.204 217.098 171.098 217.139 171.04 c
+217.187 170.98 217.271 170.951 217.389 170.951 c
+217.495 170.951 217.58 170.959 217.638 170.98 c
+217.638 170.172 l
+217.462 170.105 217.271 170.069 217.065 170.069 c
+216.389 170.069 216.044 170.455 216.036 171.231 c
+216.036 173.332 l
+215.581 173.332 l
+215.581 174.126 l
+216.036 174.126 l
+216.036 175.096 l
+h
+220.063 170.142 m
+220.034 170.201 220.005 170.304 219.976 170.452 c
+219.788 170.194 219.538 170.069 219.226 170.069 c
+218.891 170.069 218.612 170.176 218.388 170.392 c
+218.172 170.616 218.064 170.907 218.064 171.26 c
+218.064 171.671 218.197 171.987 218.461 172.216 c
+218.727 172.451 219.108 172.568 219.608 172.568 c
+219.932 172.568 l
+219.932 172.891 l
+219.932 173.068 219.895 173.189 219.828 173.259 c
+219.77 173.336 219.681 173.376 219.564 173.376 c
+219.307 173.376 219.182 173.222 219.182 172.921 c
+218.138 172.921 l
+218.138 173.292 218.274 173.597 218.55 173.832 c
+218.822 174.074 219.171 174.2 219.593 174.2 c
+220.034 174.2 220.373 174.082 220.608 173.847 c
+220.85 173.619 220.975 173.295 220.975 172.877 c
+220.975 171.009 l
+220.975 170.664 221.023 170.396 221.122 170.201 c
+221.122 170.142 l
+h
+219.461 170.892 m
+219.568 170.892 219.66 170.911 219.741 170.951 c
+219.828 170.999 219.891 171.057 219.932 171.127 c
+219.932 171.95 l
+219.681 171.95 l
+219.505 171.95 219.362 171.892 219.255 171.774 c
+219.156 171.664 219.108 171.517 219.108 171.333 c
+219.108 171.04 219.226 170.892 219.461 170.892 c
+221.592 172.259 m
+221.592 172.906 221.71 173.391 221.945 173.714 c
+222.18 174.038 222.511 174.2 222.945 174.2 c
+223.298 174.2 223.569 174.057 223.768 173.773 c
+223.812 174.126 l
+224.753 174.126 l
+224.753 170.142 l
+224.753 169.635 224.609 169.246 224.327 168.981 c
+224.04 168.709 223.635 168.57 223.107 168.57 c
+222.879 168.57 222.644 168.613 222.401 168.702 c
+222.166 168.79 221.989 168.904 221.871 169.041 c
+222.224 169.76 l
+222.32 169.654 222.449 169.569 222.606 169.511 c
+222.761 169.444 222.908 169.407 223.047 169.407 c
+223.283 169.407 223.448 169.467 223.547 169.584 c
+223.654 169.694 223.709 169.87 223.709 170.113 c
+223.709 170.466 l
+223.51 170.201 223.253 170.069 222.93 170.069 c
+222.507 170.069 222.18 170.231 221.945 170.554 c
+221.717 170.885 221.6 171.356 221.592 171.965 c
+h
+222.636 171.994 m
+222.636 171.62 222.684 171.352 222.783 171.186 c
+222.879 171.017 223.033 170.936 223.238 170.936 c
+223.452 170.936 223.61 171.013 223.709 171.171 c
+223.709 173.068 l
+223.599 173.233 223.444 173.317 223.238 173.317 c
+223.033 173.317 222.879 173.233 222.783 173.068 c
+222.684 172.898 222.636 172.63 222.636 172.259 c
+h
+227.281 171.216 m
+227.281 171.304 227.236 171.381 227.149 171.451 c
+227.061 171.528 226.873 171.631 226.59 171.759 c
+226.157 171.936 225.859 172.116 225.694 172.303 c
+225.536 172.487 225.458 172.719 225.458 172.994 c
+225.458 173.336 225.58 173.619 225.825 173.847 c
+226.079 174.082 226.417 174.2 226.839 174.2 c
+227.27 174.2 227.619 174.086 227.884 173.862 c
+228.148 173.633 228.281 173.332 228.281 172.95 c
+227.236 172.95 l
+227.236 173.274 227.097 173.435 226.825 173.435 c
+226.715 173.435 226.627 173.398 226.561 173.332 c
+226.49 173.263 226.458 173.163 226.458 173.039 c
+226.458 172.95 226.494 172.869 226.575 172.803 c
+226.652 172.744 226.833 172.649 227.119 172.524 c
+227.549 172.366 227.847 172.189 228.015 171.994 c
+228.192 171.807 228.281 171.557 228.281 171.245 c
+228.281 170.892 228.148 170.606 227.884 170.392 c
+227.619 170.176 227.27 170.069 226.839 170.069 c
+226.546 170.069 226.285 170.124 226.061 170.231 c
+225.833 170.348 225.657 170.51 225.532 170.716 c
+225.414 170.922 225.355 171.142 225.355 171.377 c
+226.34 171.377 l
+226.34 171.19 226.377 171.054 226.458 170.965 c
+226.546 170.878 226.679 170.834 226.855 170.834 c
+227.138 170.834 227.281 170.959 227.281 171.216 c
+f
+q 1 0 0 1 231.6175 175.081 cm
+0 0 m
+0 -0.955 l
+0.602 -0.955 l
+0.602 -1.484 l
+0 -1.484 l
+0 -3.954 l
+0 -4.112 0.022 -4.23 0.073 -4.307 c
+0.132 -4.388 0.22 -4.424 0.338 -4.424 c
+0.426 -4.424 0.515 -4.409 0.602 -4.38 c
+0.602 -4.939 l
+0.455 -4.986 0.301 -5.012 0.147 -5.012 c
+-0.111 -5.012 -0.306 -4.92 -0.441 -4.733 c
+-0.581 -4.548 -0.647 -4.288 -0.647 -3.954 c
+-0.647 -1.484 l
+-1.25 -1.484 l
+-1.25 -0.955 l
+-0.647 -0.955 l
+-0.647 0 l
+h
+1.161 -2.763 m
+1.161 -2.186 1.297 -1.73 1.572 -1.396 c
+1.855 -1.055 2.227 -0.881 2.69 -0.881 c
+3.149 -0.881 3.516 -1.051 3.792 -1.381 c
+4.075 -1.705 4.222 -2.153 4.233 -2.719 c
+4.233 -3.145 l
+4.233 -3.715 4.089 -4.17 3.807 -4.512 c
+3.532 -4.847 3.164 -5.012 2.705 -5.012 c
+2.241 -5.012 1.87 -4.85 1.587 -4.527 c
+1.311 -4.196 1.168 -3.755 1.161 -3.204 c
+h
+1.807 -3.145 m
+1.807 -3.549 1.885 -3.866 2.042 -4.101 c
+2.208 -4.336 2.429 -4.453 2.705 -4.453 c
+3.27 -4.453 3.564 -4.041 3.586 -3.218 c
+3.586 -2.763 l
+3.586 -2.362 3.501 -2.042 3.337 -1.807 c
+3.179 -1.565 2.961 -1.44 2.69 -1.44 c
+2.425 -1.44 2.208 -1.565 2.042 -1.807 c
+1.885 -2.042 1.807 -2.362 1.807 -2.763 c
+h
+9.672 -3.145 m
+9.672 -3.773 9.554 -4.244 9.319 -4.556 c
+9.091 -4.861 8.775 -5.012 8.363 -5.012 c
+7.96 -5.012 7.65 -4.861 7.437 -4.556 c
+7.437 -6.468 l
+6.79 -6.468 l
+6.79 -0.955 l
+7.378 -0.955 l
+7.422 -1.396 l
+7.636 -1.055 7.945 -0.881 8.349 -0.881 c
+8.789 -0.881 9.117 -1.036 9.333 -1.337 c
+9.547 -1.643 9.66 -2.098 9.672 -2.705 c
+h
+9.025 -2.763 m
+9.025 -2.322 8.955 -1.999 8.819 -1.793 c
+8.679 -1.58 8.459 -1.469 8.157 -1.469 c
+7.842 -1.469 7.603 -1.624 7.437 -1.925 c
+7.437 -3.998 l
+7.603 -4.303 7.842 -4.453 8.157 -4.453 c
+8.452 -4.453 8.665 -4.351 8.804 -4.145 c
+8.941 -3.931 9.014 -3.601 9.025 -3.16 c
+h
+12.538 -4.586 m
+12.321 -4.872 12.009 -5.012 11.597 -5.012 c
+11.233 -5.012 10.958 -4.891 10.774 -4.644 c
+10.597 -4.39 10.502 -4.027 10.495 -3.557 c
+10.495 -0.955 l
+11.141 -0.955 l
+11.141 -3.498 l
+11.141 -4.126 11.326 -4.438 11.7 -4.438 c
+12.101 -4.438 12.376 -4.262 12.523 -3.91 c
+12.523 -0.955 l
+13.17 -0.955 l
+13.17 -4.939 l
+12.552 -4.939 l
+h
+16.095 -3.924 m
+16.095 -3.777 16.04 -3.656 15.933 -3.557 c
+15.823 -3.461 15.617 -3.343 15.316 -3.204 c
+14.971 -3.057 14.728 -2.936 14.581 -2.836 c
+14.434 -2.73 14.324 -2.612 14.258 -2.484 c
+14.188 -2.358 14.155 -2.2 14.155 -2.013 c
+14.155 -1.69 14.272 -1.421 14.507 -1.205 c
+14.742 -0.992 15.044 -0.881 15.419 -0.881 c
+15.802 -0.881 16.11 -0.995 16.345 -1.219 c
+16.581 -1.448 16.698 -1.734 16.698 -2.087 c
+16.051 -2.087 l
+16.051 -1.911 15.993 -1.76 15.875 -1.631 c
+15.757 -1.506 15.603 -1.44 15.419 -1.44 c
+15.22 -1.44 15.07 -1.495 14.963 -1.602 c
+14.853 -1.701 14.802 -1.834 14.802 -1.999 c
+14.802 -2.127 14.838 -2.234 14.919 -2.322 c
+14.996 -2.403 15.187 -2.506 15.492 -2.63 c
+15.97 -2.818 16.301 -3.006 16.477 -3.189 c
+16.654 -3.366 16.742 -3.594 16.742 -3.866 c
+16.742 -4.218 16.617 -4.498 16.374 -4.704 c
+16.139 -4.909 15.823 -5.012 15.434 -5.012 c
+15.011 -5.012 14.673 -4.895 14.42 -4.659 c
+14.162 -4.417 14.037 -4.112 14.037 -3.748 c
+14.684 -3.748 l
+14.692 -3.976 14.761 -4.152 14.89 -4.277 c
+15.015 -4.394 15.199 -4.453 15.434 -4.453 c
+15.646 -4.453 15.808 -4.406 15.918 -4.307 c
+16.037 -4.211 16.095 -4.082 16.095 -3.924 c
+18.227 -1.367 m
+18.48 -1.043 18.8 -0.881 19.182 -0.881 c
+19.887 -0.881 20.244 -1.352 20.255 -2.293 c
+20.255 -4.939 l
+19.608 -4.939 l
+19.608 -2.322 l
+19.608 -2.009 19.553 -1.789 19.446 -1.66 c
+19.336 -1.535 19.182 -1.469 18.976 -1.469 c
+18.819 -1.469 18.671 -1.525 18.535 -1.631 c
+18.407 -1.741 18.304 -1.878 18.227 -2.042 c
+18.227 -4.939 l
+17.58 -4.939 l
+17.58 0.706 l
+18.227 0.706 l
+h
+23.783 0 m
+23.783 -0.955 l
+24.385 -0.955 l
+24.385 -1.484 l
+23.783 -1.484 l
+23.783 -3.954 l
+23.783 -4.112 23.804 -4.23 23.856 -4.307 c
+23.915 -4.388 24.003 -4.424 24.121 -4.424 c
+24.209 -4.424 24.297 -4.409 24.385 -4.38 c
+24.385 -4.939 l
+24.238 -4.986 24.084 -5.012 23.93 -5.012 c
+23.673 -5.012 23.478 -4.92 23.342 -4.733 c
+23.202 -4.548 23.136 -4.288 23.136 -3.954 c
+23.136 -1.484 l
+22.534 -1.484 l
+22.534 -0.955 l
+23.136 -0.955 l
+23.136 0 l
+h
+27.193 -4.939 m
+27.153 -4.85 27.127 -4.704 27.12 -4.498 c
+26.884 -4.843 26.59 -5.012 26.237 -5.012 c
+25.874 -5.012 25.591 -4.916 25.385 -4.718 c
+25.186 -4.512 25.09 -4.226 25.09 -3.85 c
+25.09 -3.45 25.227 -3.131 25.502 -2.896 c
+25.774 -2.653 26.15 -2.528 26.62 -2.528 c
+27.105 -2.528 l
+27.105 -2.102 l
+27.105 -1.866 27.05 -1.701 26.943 -1.602 c
+26.833 -1.495 26.671 -1.44 26.458 -1.44 c
+26.26 -1.44 26.098 -1.499 25.973 -1.616 c
+25.855 -1.734 25.796 -1.881 25.796 -2.057 c
+25.15 -2.057 l
+25.15 -1.863 25.209 -1.672 25.326 -1.484 c
+25.451 -1.3 25.613 -1.153 25.811 -1.043 c
+26.017 -0.937 26.245 -0.881 26.502 -0.881 c
+26.902 -0.881 27.207 -0.984 27.413 -1.19 c
+27.627 -1.396 27.741 -1.69 27.752 -2.072 c
+27.752 -4.086 l
+27.752 -4.39 27.788 -4.656 27.869 -4.88 c
+27.869 -4.939 l
+h
+26.326 -4.424 m
+26.491 -4.424 26.642 -4.38 26.781 -4.292 c
+26.929 -4.203 27.035 -4.093 27.105 -3.954 c
+27.105 -3.013 l
+26.737 -3.013 l
+26.422 -3.013 26.179 -3.083 26.002 -3.218 c
+25.826 -3.347 25.738 -3.534 25.738 -3.777 c
+25.738 -4.005 25.782 -4.17 25.87 -4.277 c
+25.958 -4.376 26.109 -4.424 26.326 -4.424 c
+28.618 -2.763 m
+28.618 -2.146 28.729 -1.683 28.957 -1.367 c
+29.181 -1.043 29.516 -0.881 29.956 -0.881 c
+30.357 -0.881 30.662 -1.058 30.868 -1.411 c
+30.912 -0.955 l
+31.5 -0.955 l
+31.5 -4.982 l
+31.5 -5.471 31.371 -5.85 31.118 -6.115 c
+30.86 -6.379 30.507 -6.511 30.059 -6.511 c
+29.861 -6.511 29.64 -6.46 29.398 -6.364 c
+29.152 -6.265 28.972 -6.144 28.853 -5.997 c
+29.119 -5.556 l
+29.383 -5.82 29.68 -5.953 30.015 -5.953 c
+30.551 -5.953 30.827 -5.659 30.838 -5.071 c
+30.838 -4.542 l
+30.632 -4.858 30.331 -5.012 29.942 -5.012 c
+29.53 -5.012 29.207 -4.861 28.972 -4.556 c
+28.743 -4.244 28.626 -3.792 28.618 -3.204 c
+h
+29.281 -3.145 m
+29.281 -3.586 29.343 -3.917 29.471 -4.13 c
+29.597 -4.336 29.813 -4.438 30.118 -4.438 c
+30.441 -4.438 30.68 -4.273 30.838 -3.939 c
+30.838 -1.955 l
+30.669 -1.631 30.43 -1.469 30.118 -1.469 c
+29.824 -1.469 29.607 -1.572 29.471 -1.778 c
+29.343 -1.984 29.281 -2.308 29.281 -2.748 c
+h
+34.395 -3.924 m
+34.395 -3.777 34.341 -3.656 34.234 -3.557 c
+34.123 -3.461 33.917 -3.343 33.616 -3.204 c
+33.271 -3.057 33.028 -2.936 32.882 -2.836 c
+32.735 -2.73 32.624 -2.612 32.558 -2.484 c
+32.488 -2.358 32.455 -2.2 32.455 -2.013 c
+32.455 -1.69 32.573 -1.421 32.808 -1.205 c
+33.043 -0.992 33.344 -0.881 33.719 -0.881 c
+34.102 -0.881 34.41 -0.995 34.646 -1.219 c
+34.881 -1.448 34.998 -1.734 34.998 -2.087 c
+34.351 -2.087 l
+34.351 -1.911 34.293 -1.76 34.175 -1.631 c
+34.058 -1.506 33.903 -1.44 33.719 -1.44 c
+33.52 -1.44 33.37 -1.495 33.264 -1.602 c
+33.154 -1.701 33.102 -1.834 33.102 -1.999 c
+33.102 -2.127 33.138 -2.234 33.219 -2.322 c
+33.297 -2.403 33.488 -2.506 33.792 -2.63 c
+34.27 -2.818 34.601 -3.006 34.777 -3.189 c
+34.954 -3.366 35.043 -3.594 35.043 -3.866 c
+35.043 -4.218 34.917 -4.498 34.675 -4.704 c
+34.44 -4.909 34.123 -5.012 33.734 -5.012 c
+33.312 -5.012 32.973 -4.895 32.72 -4.659 c
+32.462 -4.417 32.338 -4.112 32.338 -3.748 c
+32.984 -3.748 l
+32.992 -3.976 33.061 -4.152 33.19 -4.277 c
+33.315 -4.394 33.499 -4.453 33.734 -4.453 c
+33.947 -4.453 34.108 -4.406 34.219 -4.307 c
+34.337 -4.211 34.395 -4.082 34.395 -3.924 c
+35.924 -4.586 m
+35.924 -4.469 35.957 -4.373 36.027 -4.292 c
+36.093 -4.215 36.196 -4.174 36.336 -4.174 c
+36.483 -4.174 36.589 -4.215 36.659 -4.292 c
+36.736 -4.373 36.776 -4.469 36.776 -4.586 c
+36.776 -4.696 36.736 -4.787 36.659 -4.865 c
+36.589 -4.942 36.483 -4.982 36.336 -4.982 c
+36.196 -4.982 36.093 -4.942 36.027 -4.865 c
+35.957 -4.787 35.924 -4.696 35.924 -4.586 c
+f
+Q
+0.113 0.082 0.09 0 k
+35.668 164.535 238.665 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 40.8563 157.6961 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.69 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.278 -3.219 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.219 2.485 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.042 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.485 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.485 -2.19 2.454 c
+-2.26 2.425 -2.319 2.385 -2.366 2.337 c
+-2.406 2.296 -2.437 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.856 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.86 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.073 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.411 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.631 5.137 1.779 c
+5.245 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.179 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.866 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.152 2.219 c
+8.004 2.219 l
+7.993 2.138 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.871 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.675 re
+10.124 2.837 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.219 l
+13.644 2.219 l
+13.924 3.117 l
+14.497 3.117 l
+14.497 2.219 l
+15.732 2.219 l
+15.732 1.602 l
+14.497 1.602 l
+14.497 -0.103 l
+14.497 -0.324 l
+14.504 -0.393 14.527 -0.455 14.556 -0.515 c
+14.593 -0.566 14.648 -0.61 14.718 -0.646 c
+14.795 -0.676 14.909 -0.69 15.056 -0.69 c
+15.192 -0.69 15.327 -0.687 15.468 -0.676 c
+15.603 -0.658 15.736 -0.632 15.865 -0.603 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.231 15.629 -1.249 c
+15.549 -1.261 15.471 -1.268 15.394 -1.278 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.041 -1.301 14.942 -1.309 14.835 -1.309 c
+14.648 -1.309 14.486 -1.294 14.35 -1.264 c
+14.221 -1.228 14.107 -1.183 14.012 -1.132 c
+13.924 -1.084 13.85 -1.025 13.791 -0.956 c
+13.733 -0.879 13.689 -0.801 13.66 -0.721 c
+13.63 -0.632 13.608 -0.544 13.6 -0.455 c
+13.59 -0.36 13.586 -0.264 13.586 -0.176 c
+h
+21.986 2.219 m
+21.994 2.198 22.001 2.165 22.001 2.117 c
+22.009 2.076 22.016 2.028 22.016 1.97 c
+22.023 1.918 22.03 1.866 22.03 1.808 c
+22.03 1.646 l
+22.045 1.646 l
+22.104 1.764 22.17 1.86 22.251 1.941 c
+22.328 2.018 22.413 2.08 22.501 2.132 c
+22.589 2.19 22.677 2.227 22.765 2.249 c
+22.861 2.267 22.961 2.278 23.059 2.278 c
+23.265 2.278 23.445 2.234 23.603 2.146 c
+23.757 2.058 23.886 1.929 23.985 1.764 c
+24.092 1.606 24.169 1.415 24.22 1.191 c
+24.28 0.974 24.309 0.738 24.309 0.485 c
+24.309 0.22 24.28 -0.025 24.22 -0.25 c
+24.169 -0.467 24.092 -0.658 23.985 -0.823 c
+23.886 -0.981 23.754 -1.103 23.589 -1.191 c
+23.431 -1.278 23.243 -1.323 23.03 -1.323 c
+22.931 -1.323 22.832 -1.312 22.736 -1.294 c
+22.637 -1.272 22.545 -1.242 22.456 -1.191 c
+22.375 -1.143 22.298 -1.08 22.221 -0.999 c
+22.152 -0.922 22.093 -0.831 22.045 -0.721 c
+22.03 -0.721 l
+22.03 -0.808 l
+22.038 -0.849 22.045 -0.897 22.045 -0.956 c
+22.045 -1.117 l
+22.045 -1.294 l
+22.045 -2.631 l
+21.134 -2.631 l
+21.134 1.455 l
+21.134 1.621 21.126 1.768 21.119 1.897 c
+21.119 2.219 l
+h
+22.03 0.455 m
+22.03 0.228 22.049 0.037 22.089 -0.118 c
+22.137 -0.264 22.192 -0.382 22.251 -0.47 c
+22.317 -0.559 22.391 -0.625 22.471 -0.661 c
+22.549 -0.702 22.626 -0.721 22.707 -0.721 c
+22.803 -0.721 22.89 -0.698 22.971 -0.646 c
+23.059 -0.599 23.125 -0.529 23.177 -0.441 c
+23.235 -0.345 23.28 -0.22 23.31 -0.073 c
+23.346 0.081 23.368 0.268 23.368 0.485 c
+23.368 0.875 23.31 1.168 23.192 1.367 c
+23.081 1.562 22.927 1.661 22.722 1.661 c
+22.641 1.661 22.564 1.639 22.486 1.602 c
+22.406 1.562 22.332 1.5 22.265 1.411 c
+22.196 1.323 22.137 1.198 22.089 1.043 c
+22.049 0.885 22.03 0.691 22.03 0.455 c
+26.061 2.219 m
+26.061 0.264 l
+26.061 0.125 26.069 0 26.091 -0.118 c
+26.109 -0.228 26.142 -0.32 26.194 -0.397 c
+26.242 -0.478 26.3 -0.54 26.371 -0.588 c
+26.437 -0.628 26.521 -0.646 26.62 -0.646 c
+26.709 -0.646 26.789 -0.628 26.87 -0.588 c
+26.959 -0.54 27.032 -0.47 27.09 -0.382 c
+27.15 -0.287 27.194 -0.176 27.223 -0.058 c
+27.26 0.066 27.281 0.206 27.281 0.353 c
+27.281 2.219 l
+28.178 2.219 l
+28.178 -0.485 l
+28.178 -0.721 l
+28.185 -0.801 28.193 -0.879 28.193 -0.956 c
+28.193 -1.147 l
+28.201 -1.198 28.208 -1.234 28.208 -1.264 c
+27.355 -1.264 l
+27.344 -1.234 27.333 -1.198 27.326 -1.147 c
+27.326 -0.956 l
+27.326 -0.889 27.318 -0.819 27.312 -0.75 c
+27.312 -0.573 l
+27.296 -0.573 l
+27.179 -0.838 27.025 -1.029 26.841 -1.147 c
+26.664 -1.264 26.462 -1.323 26.238 -1.323 c
+26.032 -1.323 25.86 -1.286 25.724 -1.22 c
+25.584 -1.154 25.473 -1.058 25.386 -0.941 c
+25.305 -0.823 25.246 -0.687 25.209 -0.529 c
+25.18 -0.364 25.165 -0.187 25.165 0 c
+25.165 2.219 l
+h
+32.342 -0.25 m
+32.342 -0.419 32.301 -0.569 32.224 -0.706 c
+32.154 -0.834 32.052 -0.948 31.916 -1.043 c
+31.787 -1.132 31.625 -1.201 31.43 -1.249 c
+31.243 -1.297 31.027 -1.323 30.784 -1.323 c
+30.556 -1.323 30.358 -1.309 30.181 -1.278 c
+30.005 -1.249 29.847 -1.201 29.71 -1.132 c
+29.571 -1.055 29.461 -0.956 29.373 -0.838 c
+29.284 -0.721 29.215 -0.573 29.167 -0.397 c
+29.976 -0.279 l
+29.994 -0.378 30.023 -0.455 30.063 -0.515 c
+30.111 -0.573 30.17 -0.617 30.24 -0.646 c
+30.306 -0.676 30.387 -0.702 30.475 -0.721 c
+30.564 -0.731 30.666 -0.735 30.784 -0.735 c
+30.88 -0.735 30.975 -0.731 31.063 -0.721 c
+31.152 -0.702 31.229 -0.676 31.298 -0.646 c
+31.364 -0.617 31.416 -0.58 31.445 -0.529 c
+31.482 -0.482 31.504 -0.419 31.504 -0.338 c
+31.504 -0.243 31.474 -0.169 31.416 -0.118 c
+31.364 -0.07 31.298 -0.029 31.21 0 c
+31.122 0.037 31.011 0.066 30.886 0.088 c
+30.769 0.118 30.637 0.147 30.489 0.177 c
+30.35 0.214 30.211 0.254 30.063 0.294 c
+29.924 0.342 29.799 0.405 29.681 0.485 c
+29.571 0.563 29.483 0.661 29.417 0.779 c
+29.347 0.897 29.313 1.047 29.313 1.235 c
+29.313 1.389 29.344 1.532 29.402 1.661 c
+29.469 1.797 29.564 1.911 29.681 1.999 c
+29.806 2.088 29.964 2.153 30.152 2.205 c
+30.335 2.253 30.549 2.278 30.784 2.278 c
+30.967 2.278 31.144 2.256 31.313 2.219 c
+31.478 2.19 31.625 2.135 31.754 2.058 c
+31.879 1.988 31.989 1.889 32.077 1.764 c
+32.166 1.646 32.224 1.503 32.253 1.338 c
+31.46 1.264 l
+31.438 1.342 31.408 1.404 31.372 1.455 c
+31.331 1.514 31.283 1.558 31.225 1.588 c
+31.173 1.625 31.111 1.65 31.034 1.661 c
+30.953 1.668 30.872 1.675 30.784 1.675 c
+30.567 1.675 30.406 1.646 30.298 1.588 c
+30.188 1.536 30.137 1.448 30.137 1.323 c
+30.137 1.242 30.155 1.18 30.196 1.132 c
+30.244 1.08 30.306 1.043 30.387 1.014 c
+30.475 0.985 30.57 0.956 30.681 0.926 c
+30.788 0.904 30.909 0.882 31.048 0.852 c
+31.202 0.823 31.36 0.783 31.519 0.735 c
+31.673 0.684 31.813 0.621 31.931 0.544 c
+32.048 0.463 32.143 0.36 32.224 0.235 c
+32.301 0.106 32.342 -0.055 32.342 -0.25 c
+34.202 1.514 m
+34.319 1.786 34.47 1.984 34.657 2.102 c
+34.84 2.219 35.061 2.278 35.318 2.278 c
+35.524 2.278 35.694 2.242 35.833 2.176 c
+35.98 2.105 36.091 2.014 36.17 1.897 c
+36.259 1.779 36.318 1.635 36.347 1.47 c
+36.384 1.301 36.406 1.124 36.406 0.941 c
+36.406 -1.264 l
+35.495 -1.264 l
+35.495 0.735 l
+35.495 0.871 35.484 0.992 35.465 1.103 c
+35.455 1.209 35.428 1.297 35.392 1.367 c
+35.351 1.444 35.293 1.503 35.216 1.544 c
+35.146 1.58 35.054 1.602 34.936 1.602 c
+34.826 1.602 34.73 1.577 34.643 1.529 c
+34.554 1.477 34.473 1.411 34.408 1.323 c
+34.348 1.235 34.297 1.124 34.26 1 c
+34.231 0.882 34.216 0.75 34.216 0.603 c
+34.216 -1.264 l
+33.305 -1.264 l
+33.305 3.513 l
+34.216 3.513 l
+34.216 2.205 l
+34.216 2.135 34.209 2.065 34.202 1.999 c
+34.202 1.793 l
+34.202 1.735 34.194 1.679 34.186 1.631 c
+34.186 1.514 l
+h
+42.013 0.838 1.867 -0.794 re
+42.013 0.044 m
+46.368 2.219 m
+46.368 0.264 l
+46.368 0.125 46.376 0 46.398 -0.118 c
+46.416 -0.228 46.449 -0.32 46.501 -0.397 c
+46.549 -0.478 46.607 -0.54 46.677 -0.588 c
+46.743 -0.628 46.828 -0.646 46.927 -0.646 c
+47.015 -0.646 47.096 -0.628 47.177 -0.588 c
+47.265 -0.54 47.339 -0.47 47.397 -0.382 c
+47.457 -0.287 47.5 -0.176 47.53 -0.058 c
+47.567 0.066 47.588 0.206 47.588 0.353 c
+47.588 2.219 l
+48.485 2.219 l
+48.485 -0.485 l
+48.485 -0.721 l
+48.492 -0.801 48.5 -0.879 48.5 -0.956 c
+48.5 -1.147 l
+48.507 -1.198 48.515 -1.234 48.515 -1.264 c
+47.662 -1.264 l
+47.651 -1.234 47.64 -1.198 47.632 -1.147 c
+47.632 -0.956 l
+47.632 -0.889 47.625 -0.819 47.617 -0.75 c
+47.617 -0.573 l
+47.603 -0.573 l
+47.486 -0.838 47.331 -1.029 47.147 -1.147 c
+46.971 -1.264 46.769 -1.323 46.545 -1.323 c
+46.339 -1.323 46.167 -1.286 46.03 -1.22 c
+45.891 -1.154 45.78 -1.058 45.693 -0.941 c
+45.612 -0.823 45.552 -0.687 45.516 -0.529 c
+45.487 -0.364 45.472 -0.187 45.472 0 c
+45.472 2.219 l
+h
+54.361 -2.631 m
+54.361 3.513 l
+56.286 3.513 l
+56.286 2.896 l
+55.214 2.896 l
+55.214 -2.014 l
+56.286 -2.014 l
+56.286 -2.631 l
+h
+60.685 1.47 m
+60.586 1.477 60.483 1.488 60.377 1.5 c
+60.267 1.517 60.145 1.529 60.009 1.529 c
+59.833 1.529 59.675 1.488 59.538 1.411 c
+59.399 1.342 59.282 1.242 59.186 1.118 c
+59.098 0.989 59.028 0.842 58.981 0.676 c
+58.94 0.507 58.921 0.331 58.921 0.147 c
+58.921 -1.264 l
+58.025 -1.264 l
+58.025 0.985 l
+58.025 1.11 58.014 1.235 57.996 1.353 c
+57.984 1.477 57.969 1.595 57.951 1.706 c
+57.94 1.823 57.926 1.918 57.907 1.999 c
+57.886 2.088 57.867 2.161 57.848 2.219 c
+58.73 2.219 l
+58.738 2.168 58.748 2.117 58.76 2.058 c
+58.778 1.999 58.792 1.933 58.804 1.866 c
+58.823 1.808 58.837 1.742 58.848 1.675 c
+58.855 1.606 58.867 1.544 58.877 1.484 c
+58.892 1.484 l
+58.929 1.602 58.981 1.708 59.039 1.808 c
+59.105 1.903 59.186 1.988 59.274 2.058 c
+59.363 2.124 59.465 2.179 59.583 2.219 c
+59.708 2.256 59.855 2.278 60.024 2.278 c
+60.149 2.278 60.267 2.271 60.377 2.263 c
+60.494 2.253 60.597 2.238 60.685 2.219 c
+h
+63.291 -1.323 m
+63.033 -1.323 62.806 -1.286 62.6 -1.22 c
+62.395 -1.143 62.218 -1.029 62.071 -0.881 c
+61.924 -0.727 61.806 -0.536 61.718 -0.309 c
+61.637 -0.085 61.601 0.18 61.601 0.485 c
+61.601 0.816 61.645 1.095 61.732 1.323 c
+61.828 1.558 61.957 1.742 62.115 1.881 c
+62.28 2.018 62.468 2.117 62.673 2.176 c
+62.879 2.242 63.089 2.278 63.305 2.278 c
+63.577 2.278 63.812 2.227 64.011 2.132 c
+64.217 2.043 64.382 1.911 64.511 1.735 c
+64.647 1.565 64.746 1.359 64.805 1.118 c
+64.871 0.882 64.907 0.617 64.907 0.324 c
+64.907 0.309 l
+62.541 0.309 l
+62.541 0.162 62.555 0.022 62.586 -0.103 c
+62.622 -0.231 62.677 -0.345 62.746 -0.441 c
+62.813 -0.529 62.898 -0.599 62.997 -0.646 c
+63.093 -0.698 63.206 -0.721 63.335 -0.721 c
+63.49 -0.721 63.629 -0.687 63.746 -0.617 c
+63.872 -0.551 63.96 -0.449 64.011 -0.309 c
+64.849 -0.382 l
+64.82 -0.482 64.764 -0.588 64.687 -0.706 c
+64.606 -0.816 64.504 -0.919 64.379 -1.014 c
+64.261 -1.103 64.107 -1.176 63.922 -1.234 c
+63.746 -1.294 63.533 -1.323 63.291 -1.323 c
+63.291 1.706 m
+63.203 1.706 63.114 1.691 63.026 1.661 c
+62.938 1.631 62.857 1.58 62.791 1.514 c
+62.721 1.444 62.663 1.356 62.615 1.249 c
+62.574 1.139 62.555 1.014 62.555 0.867 c
+64.026 0.867 l
+64.026 1.003 64 1.124 63.952 1.235 c
+63.912 1.342 63.856 1.43 63.791 1.5 c
+63.731 1.565 63.658 1.617 63.57 1.646 c
+63.482 1.683 63.386 1.706 63.291 1.706 c
+66.954 -1.264 m
+66.954 0.852 l
+66.954 1.018 66.947 1.154 66.94 1.264 c
+66.929 1.371 66.91 1.455 66.881 1.514 c
+66.859 1.58 66.829 1.631 66.792 1.661 c
+66.763 1.691 66.723 1.706 66.675 1.706 c
+66.617 1.706 66.561 1.675 66.513 1.617 c
+66.473 1.565 66.44 1.492 66.411 1.396 c
+66.381 1.309 66.355 1.195 66.337 1.058 c
+66.326 0.919 66.322 0.768 66.322 0.603 c
+66.322 -1.264 l
+65.572 -1.264 l
+65.572 1.47 l
+65.572 1.706 l
+65.572 1.926 l
+65.572 2.003 65.566 2.065 65.558 2.117 c
+65.558 2.219 l
+66.235 2.219 l
+66.235 2.132 l
+66.235 1.984 l
+66.241 1.926 66.249 1.866 66.249 1.808 c
+66.249 1.646 l
+66.264 1.646 l
+66.282 1.735 66.312 1.812 66.352 1.881 c
+66.389 1.959 66.432 2.028 66.484 2.088 c
+66.543 2.146 66.609 2.19 66.69 2.219 c
+66.767 2.256 66.856 2.278 66.954 2.278 c
+67.138 2.278 67.278 2.223 67.366 2.117 c
+67.461 2.018 67.531 1.86 67.571 1.646 c
+67.586 1.646 l
+67.623 1.742 67.664 1.83 67.704 1.911 c
+67.752 1.988 67.807 2.051 67.866 2.102 c
+67.924 2.161 67.991 2.205 68.072 2.234 c
+68.149 2.263 68.237 2.278 68.336 2.278 c
+68.472 2.278 68.586 2.253 68.674 2.205 c
+68.762 2.153 68.828 2.08 68.88 1.984 c
+68.939 1.885 68.976 1.756 68.998 1.602 c
+69.027 1.455 69.042 1.272 69.042 1.058 c
+69.042 -1.264 l
+68.321 -1.264 l
+68.321 0.852 l
+68.321 1.018 68.314 1.154 68.307 1.264 c
+68.296 1.371 68.277 1.455 68.248 1.514 c
+68.226 1.58 68.196 1.631 68.159 1.661 c
+68.13 1.691 68.09 1.706 68.042 1.706 c
+67.924 1.706 67.829 1.617 67.763 1.44 c
+67.704 1.272 67.675 1.014 67.675 0.661 c
+67.675 -1.264 l
+h
+73.058 0.485 m
+73.058 0.21 73.021 -0.04 72.955 -0.264 c
+72.886 -0.482 72.782 -0.669 72.647 -0.823 c
+72.507 -0.981 72.331 -1.103 72.117 -1.191 c
+71.901 -1.278 71.647 -1.323 71.353 -1.323 c
+71.078 -1.323 70.831 -1.278 70.618 -1.191 c
+70.412 -1.103 70.239 -0.981 70.104 -0.823 c
+69.964 -0.669 69.861 -0.482 69.795 -0.264 c
+69.725 -0.04 69.692 0.21 69.692 0.485 c
+69.692 0.738 69.722 0.974 69.78 1.191 c
+69.846 1.415 69.95 1.606 70.089 1.764 c
+70.225 1.929 70.401 2.058 70.618 2.146 c
+70.831 2.234 71.089 2.278 71.382 2.278 c
+71.695 2.278 71.956 2.234 72.161 2.146 c
+72.375 2.058 72.547 1.929 72.676 1.764 c
+72.812 1.606 72.911 1.415 72.97 1.191 c
+73.029 0.974 73.058 0.738 73.058 0.485 c
+72.103 0.485 m
+72.103 0.691 72.088 0.867 72.059 1.014 c
+72.037 1.161 71.999 1.282 71.941 1.382 c
+71.882 1.477 71.809 1.548 71.721 1.588 c
+71.633 1.635 71.523 1.661 71.397 1.661 c
+71.133 1.661 70.941 1.562 70.824 1.367 c
+70.706 1.18 70.648 0.885 70.648 0.485 c
+70.648 0.062 70.706 -0.243 70.824 -0.426 c
+70.941 -0.613 71.118 -0.706 71.353 -0.706 c
+71.478 -0.706 71.592 -0.687 71.691 -0.646 c
+71.787 -0.599 71.868 -0.526 71.926 -0.426 c
+71.993 -0.331 72.037 -0.206 72.059 -0.058 c
+72.088 0.088 72.103 0.268 72.103 0.485 c
+74.521 1.602 m
+73.977 1.602 l
+73.977 2.219 l
+74.565 2.219 l
+74.844 3.117 l
+75.417 3.117 l
+75.417 2.219 l
+76.652 2.219 l
+76.652 1.602 l
+75.417 1.602 l
+75.417 -0.103 l
+75.417 -0.324 l
+75.425 -0.393 75.446 -0.455 75.476 -0.515 c
+75.513 -0.566 75.568 -0.61 75.638 -0.646 c
+75.715 -0.676 75.829 -0.69 75.976 -0.69 c
+76.112 -0.69 76.248 -0.687 76.387 -0.676 c
+76.523 -0.658 76.656 -0.632 76.784 -0.603 c
+76.784 -1.205 l
+76.703 -1.216 76.626 -1.231 76.549 -1.249 c
+76.468 -1.261 76.391 -1.268 76.314 -1.278 c
+76.233 -1.286 76.145 -1.294 76.049 -1.294 c
+75.961 -1.301 75.862 -1.309 75.756 -1.309 c
+75.568 -1.309 75.407 -1.294 75.27 -1.264 c
+75.142 -1.228 75.028 -1.183 74.933 -1.132 c
+74.844 -1.084 74.771 -1.025 74.712 -0.956 c
+74.653 -0.879 74.609 -0.801 74.58 -0.721 c
+74.55 -0.632 74.528 -0.544 74.521 -0.455 c
+74.509 -0.36 74.506 -0.264 74.506 -0.176 c
+h
+79.537 -1.323 m
+79.28 -1.323 79.052 -1.286 78.846 -1.22 c
+78.64 -1.143 78.464 -1.029 78.317 -0.881 c
+78.17 -0.727 78.052 -0.536 77.964 -0.309 c
+77.883 -0.085 77.846 0.18 77.846 0.485 c
+77.846 0.816 77.89 1.095 77.979 1.323 c
+78.074 1.558 78.203 1.742 78.361 1.881 c
+78.526 2.018 78.714 2.117 78.92 2.176 c
+79.126 2.242 79.334 2.278 79.552 2.278 c
+79.824 2.278 80.059 2.227 80.257 2.132 c
+80.463 2.043 80.628 1.911 80.757 1.735 c
+80.893 1.565 80.992 1.359 81.051 1.118 c
+81.117 0.882 81.154 0.617 81.154 0.324 c
+81.154 0.309 l
+78.787 0.309 l
+78.787 0.162 78.802 0.022 78.831 -0.103 c
+78.868 -0.231 78.923 -0.345 78.993 -0.441 c
+79.059 -0.529 79.143 -0.599 79.243 -0.646 c
+79.338 -0.698 79.452 -0.721 79.581 -0.721 c
+79.735 -0.721 79.875 -0.687 79.993 -0.617 c
+80.117 -0.551 80.206 -0.449 80.257 -0.309 c
+81.095 -0.382 l
+81.065 -0.482 81.011 -0.588 80.934 -0.706 c
+80.853 -0.816 80.749 -0.919 80.624 -1.014 c
+80.507 -1.103 80.352 -1.176 80.169 -1.234 c
+79.993 -1.294 79.779 -1.323 79.537 -1.323 c
+79.537 1.706 m
+79.448 1.706 79.361 1.691 79.272 1.661 c
+79.184 1.631 79.103 1.58 79.037 1.514 c
+78.968 1.444 78.908 1.356 78.86 1.249 c
+78.82 1.139 78.802 1.014 78.802 0.867 c
+80.271 0.867 l
+80.271 1.003 80.246 1.124 80.198 1.235 c
+80.158 1.342 80.103 1.43 80.036 1.5 c
+79.978 1.565 79.905 1.617 79.816 1.646 c
+79.728 1.683 79.633 1.706 79.537 1.706 c
+82.407 -2.631 m
+82.407 -2.014 l
+83.48 -2.014 l
+83.48 2.896 l
+82.407 2.896 l
+82.407 3.513 l
+84.333 3.513 l
+84.333 -2.631 l
+h
+90.91 -2.631 m
+90.91 3.513 l
+92.836 3.513 l
+92.836 2.896 l
+91.763 2.896 l
+91.763 -2.014 l
+92.836 -2.014 l
+92.836 -2.631 l
+h
+94.224 -1.264 m
+94.224 -0.97 l
+94.232 -0.834 94.24 -0.676 94.24 -0.5 c
+94.24 3.513 l
+95.151 3.513 l
+95.151 2.234 l
+95.151 2.072 l
+95.151 1.897 l
+95.151 1.845 95.144 1.801 95.136 1.764 c
+95.136 1.675 l
+95.151 1.675 l
+95.199 1.783 95.261 1.874 95.342 1.955 c
+95.419 2.032 95.504 2.095 95.592 2.146 c
+95.68 2.194 95.772 2.227 95.871 2.249 c
+95.967 2.267 96.065 2.278 96.165 2.278 c
+96.378 2.278 96.566 2.234 96.724 2.146 c
+96.878 2.058 97.006 1.929 97.106 1.764 c
+97.212 1.606 97.289 1.415 97.341 1.191 c
+97.389 0.974 97.415 0.735 97.415 0.47 c
+97.415 0.214 97.385 -0.025 97.326 -0.25 c
+97.268 -0.467 97.183 -0.658 97.077 -0.823 c
+96.967 -0.981 96.834 -1.103 96.68 -1.191 c
+96.522 -1.278 96.341 -1.323 96.136 -1.323 c
+96.036 -1.323 95.938 -1.312 95.842 -1.294 c
+95.753 -1.272 95.666 -1.242 95.577 -1.191 c
+95.489 -1.132 95.408 -1.066 95.342 -0.985 c
+95.272 -0.908 95.209 -0.808 95.151 -0.69 c
+95.136 -0.69 l
+95.136 -0.852 l
+95.136 -0.912 95.128 -0.97 95.122 -1.029 c
+95.122 -1.08 95.114 -1.128 95.107 -1.176 c
+95.107 -1.216 95.099 -1.246 95.092 -1.264 c
+h
+95.136 0.5 m
+95.136 0.264 95.155 0.066 95.195 -0.088 c
+95.242 -0.246 95.302 -0.368 95.371 -0.455 c
+95.437 -0.544 95.511 -0.61 95.592 -0.646 c
+95.669 -0.687 95.747 -0.706 95.827 -0.706 c
+96.033 -0.706 96.187 -0.61 96.298 -0.411 c
+96.415 -0.216 96.474 0.077 96.474 0.47 c
+96.474 0.684 96.452 0.867 96.415 1.014 c
+96.385 1.168 96.341 1.294 96.283 1.382 c
+96.231 1.477 96.165 1.55 96.077 1.602 c
+95.996 1.65 95.907 1.675 95.812 1.675 c
+95.732 1.675 95.654 1.654 95.577 1.617 c
+95.496 1.577 95.423 1.514 95.357 1.426 c
+95.298 1.338 95.242 1.213 95.195 1.058 c
+95.155 0.912 95.136 0.724 95.136 0.5 c
+101.299 1.47 m
+101.2 1.477 101.097 1.488 100.99 1.5 c
+100.88 1.517 100.759 1.529 100.622 1.529 c
+100.446 1.529 100.288 1.488 100.152 1.411 c
+100.013 1.342 99.895 1.242 99.799 1.118 c
+99.711 0.989 99.641 0.842 99.593 0.676 c
+99.554 0.507 99.535 0.331 99.535 0.147 c
+99.535 -1.264 l
+98.638 -1.264 l
+98.638 0.985 l
+98.638 1.11 98.627 1.235 98.609 1.353 c
+98.598 1.477 98.583 1.595 98.565 1.706 c
+98.554 1.823 98.539 1.918 98.521 1.999 c
+98.498 2.088 98.48 2.161 98.462 2.219 c
+99.344 2.219 l
+99.351 2.168 99.362 2.117 99.373 2.058 c
+99.392 1.999 99.406 1.933 99.417 1.866 c
+99.435 1.808 99.45 1.742 99.462 1.675 c
+99.469 1.606 99.479 1.544 99.491 1.484 c
+99.506 1.484 l
+99.542 1.602 99.593 1.708 99.653 1.808 c
+99.718 1.903 99.799 1.988 99.888 2.058 c
+99.976 2.124 100.079 2.179 100.196 2.219 c
+100.321 2.256 100.468 2.278 100.637 2.278 c
+100.763 2.278 100.88 2.271 100.99 2.263 c
+101.108 2.253 101.21 2.238 101.299 2.219 c
+h
+103.302 -1.323 m
+103.132 -1.323 102.982 -1.301 102.846 -1.264 c
+102.717 -1.216 102.604 -1.147 102.508 -1.058 c
+102.419 -0.97 102.35 -0.864 102.302 -0.735 c
+102.251 -0.599 102.228 -0.449 102.228 -0.279 c
+102.228 -0.073 102.261 0.096 102.332 0.235 c
+102.398 0.382 102.493 0.492 102.611 0.573 c
+102.735 0.661 102.879 0.724 103.037 0.765 c
+103.202 0.802 103.379 0.827 103.566 0.838 c
+104.287 0.852 l
+104.287 1.029 l
+104.287 1.147 104.275 1.249 104.257 1.338 c
+104.235 1.426 104.202 1.492 104.154 1.544 c
+104.114 1.602 104.066 1.639 104.007 1.661 c
+103.948 1.679 103.882 1.691 103.816 1.691 c
+103.747 1.691 103.684 1.679 103.625 1.661 c
+103.574 1.65 103.526 1.625 103.478 1.588 c
+103.437 1.558 103.404 1.507 103.375 1.44 c
+103.353 1.382 103.338 1.301 103.331 1.205 c
+102.39 1.249 l
+102.419 1.396 102.463 1.532 102.523 1.661 c
+102.589 1.786 102.685 1.897 102.802 1.984 c
+102.92 2.08 103.059 2.153 103.228 2.205 c
+103.404 2.253 103.61 2.278 103.845 2.278 c
+104.287 2.278 104.617 2.168 104.844 1.955 c
+105.08 1.749 105.198 1.44 105.198 1.029 c
+105.198 -0.235 l
+105.198 -0.455 l
+105.205 -0.515 105.22 -0.569 105.241 -0.617 c
+105.26 -0.658 105.289 -0.69 105.33 -0.721 c
+105.367 -0.742 105.418 -0.75 105.477 -0.75 c
+105.543 -0.75 105.613 -0.746 105.683 -0.735 c
+105.683 -1.22 l
+105.624 -1.231 105.569 -1.242 105.521 -1.249 c
+105.48 -1.261 105.44 -1.268 105.403 -1.278 c
+105.363 -1.286 105.319 -1.294 105.272 -1.294 c
+105.22 -1.301 105.161 -1.309 105.095 -1.309 c
+104.867 -1.309 104.701 -1.257 104.595 -1.147 c
+104.485 -1.029 104.422 -0.864 104.404 -0.646 c
+104.389 -0.646 l
+104.32 -0.757 104.25 -0.852 104.183 -0.941 c
+104.114 -1.022 104.036 -1.087 103.948 -1.147 c
+103.86 -1.205 103.761 -1.249 103.654 -1.278 c
+103.555 -1.309 103.437 -1.323 103.302 -1.323 c
+104.287 0.353 m
+103.86 0.338 l
+103.761 0.338 103.669 0.331 103.581 0.324 c
+103.5 0.312 103.433 0.287 103.375 0.25 c
+103.317 0.21 103.265 0.151 103.228 0.073 c
+103.188 0.004 103.169 -0.088 103.169 -0.206 c
+103.169 -0.374 103.202 -0.496 103.272 -0.573 c
+103.338 -0.654 103.437 -0.69 103.566 -0.69 c
+103.672 -0.69 103.772 -0.669 103.86 -0.617 c
+103.955 -0.569 104.036 -0.507 104.096 -0.426 c
+104.161 -0.349 104.213 -0.261 104.242 -0.162 c
+104.272 -0.055 104.287 0.059 104.287 0.177 c
+h
+108.597 -1.264 m
+108.597 0.721 l
+108.597 1.022 108.553 1.242 108.464 1.382 c
+108.384 1.529 108.248 1.602 108.053 1.602 c
+107.942 1.602 107.84 1.577 107.745 1.529 c
+107.656 1.477 107.575 1.411 107.51 1.323 c
+107.45 1.235 107.399 1.124 107.362 1 c
+107.333 0.882 107.318 0.75 107.318 0.603 c
+107.318 -1.264 l
+106.407 -1.264 l
+106.407 1.44 l
+106.407 1.661 l
+106.407 1.749 106.399 1.826 106.392 1.897 c
+106.392 2.088 l
+106.392 2.219 l
+107.244 2.219 l
+107.252 2.19 107.259 2.146 107.259 2.088 c
+107.259 1.897 l
+107.267 1.826 107.274 1.756 107.274 1.691 c
+107.281 1.621 107.288 1.565 107.288 1.529 c
+107.304 1.529 l
+107.421 1.793 107.572 1.984 107.759 2.102 c
+107.942 2.219 108.163 2.278 108.42 2.278 c
+108.605 2.278 108.765 2.249 108.906 2.19 c
+109.041 2.132 109.156 2.043 109.243 1.926 c
+109.332 1.808 109.394 1.665 109.434 1.5 c
+109.482 1.342 109.509 1.154 109.509 0.941 c
+109.509 -1.264 l
+h
+112.025 -1.323 m
+111.739 -1.323 111.496 -1.282 111.29 -1.205 c
+111.084 -1.117 110.912 -0.996 110.776 -0.838 c
+110.637 -0.684 110.533 -0.496 110.467 -0.279 c
+110.398 -0.055 110.365 0.191 110.365 0.455 c
+110.365 0.75 110.398 1.007 110.467 1.235 c
+110.544 1.459 110.651 1.646 110.791 1.793 c
+110.938 1.947 111.114 2.065 111.32 2.146 c
+111.526 2.234 111.761 2.278 112.025 2.278 c
+112.25 2.278 112.451 2.249 112.628 2.19 c
+112.804 2.132 112.956 2.047 113.083 1.941 c
+113.209 1.841 113.311 1.72 113.392 1.573 c
+113.469 1.433 113.525 1.282 113.554 1.118 c
+112.643 1.073 l
+112.613 1.249 112.543 1.389 112.437 1.5 c
+112.337 1.606 112.194 1.661 112.011 1.661 c
+111.765 1.661 111.588 1.558 111.481 1.353 c
+111.371 1.154 111.32 0.867 111.32 0.485 c
+111.32 -0.309 111.555 -0.706 112.025 -0.706 c
+112.191 -0.706 112.334 -0.654 112.451 -0.544 c
+112.569 -0.437 112.643 -0.276 112.672 -0.058 c
+113.584 -0.103 l
+113.554 -0.272 113.499 -0.426 113.422 -0.573 c
+113.352 -0.721 113.249 -0.852 113.114 -0.97 c
+112.985 -1.08 112.827 -1.168 112.643 -1.234 c
+112.466 -1.294 112.26 -1.323 112.025 -1.323 c
+115.428 1.514 m
+115.546 1.786 115.697 1.984 115.884 2.102 c
+116.067 2.219 116.289 2.278 116.545 2.278 c
+116.751 2.278 116.92 2.242 117.06 2.176 c
+117.207 2.105 117.317 2.014 117.398 1.897 c
+117.486 1.779 117.544 1.635 117.575 1.47 c
+117.611 1.301 117.633 1.124 117.633 0.941 c
+117.633 -1.264 l
+116.722 -1.264 l
+116.722 0.735 l
+116.722 0.871 116.711 0.992 116.692 1.103 c
+116.682 1.209 116.655 1.297 116.619 1.367 c
+116.578 1.444 116.52 1.503 116.443 1.544 c
+116.372 1.58 116.281 1.602 116.163 1.602 c
+116.053 1.602 115.957 1.577 115.869 1.529 c
+115.781 1.477 115.701 1.411 115.634 1.323 c
+115.575 1.235 115.524 1.124 115.487 1 c
+115.458 0.882 115.443 0.75 115.443 0.603 c
+115.443 -1.264 l
+114.531 -1.264 l
+114.531 3.513 l
+115.443 3.513 l
+115.443 2.205 l
+115.443 2.135 115.435 2.065 115.428 1.999 c
+115.428 1.793 l
+115.428 1.735 115.421 1.679 115.414 1.631 c
+115.414 1.514 l
+h
+118.959 -2.631 m
+118.959 -2.014 l
+120.033 -2.014 l
+120.033 2.896 l
+118.959 2.896 l
+118.959 3.513 l
+120.885 3.513 l
+120.885 -2.631 l
+h
+f
+Q
+q 1 0 0 1 67.9872 143.6443 cm
+0 0 m
+0 -2.103 l
+-0.676 -2.103 l
+-0.676 3.248 l
+1.029 3.248 l
+1.529 3.248 1.918 3.094 2.205 2.792 c
+2.488 2.499 2.631 2.105 2.631 1.616 c
+2.631 1.095 2.492 0.698 2.219 0.426 c
+1.955 0.151 1.577 0.007 1.087 0 c
+h
+0 0.573 m
+1.029 0.573 l
+1.33 0.573 1.562 0.661 1.72 0.837 c
+1.874 1.014 1.955 1.267 1.955 1.602 c
+1.955 1.925 1.87 2.183 1.706 2.381 c
+1.548 2.576 1.326 2.675 1.043 2.675 c
+0 2.675 l
+h
+5.438 -1.75 m
+5.222 -2.037 4.91 -2.176 4.498 -2.176 c
+4.135 -2.176 3.859 -2.055 3.675 -1.808 c
+3.499 -1.555 3.403 -1.191 3.395 -0.721 c
+3.395 1.881 l
+4.042 1.881 l
+4.042 -0.662 l
+4.042 -1.291 4.226 -1.603 4.601 -1.603 c
+5.002 -1.603 5.277 -1.426 5.424 -1.073 c
+5.424 1.881 l
+6.071 1.881 l
+6.071 -2.103 l
+5.453 -2.103 l
+h
+8.996 -1.088 m
+8.996 -0.941 8.941 -0.82 8.834 -0.721 c
+8.724 -0.626 8.518 -0.508 8.217 -0.368 c
+7.871 -0.221 7.628 -0.1 7.482 0 c
+7.335 0.106 7.225 0.224 7.158 0.353 c
+7.088 0.477 7.056 0.635 7.056 0.823 c
+7.056 1.146 7.173 1.414 7.408 1.631 c
+7.644 1.844 7.945 1.955 8.32 1.955 c
+8.702 1.955 9.01 1.841 9.246 1.616 c
+9.481 1.389 9.598 1.102 9.598 0.749 c
+8.952 0.749 l
+8.952 0.926 8.893 1.076 8.775 1.205 c
+8.658 1.33 8.503 1.396 8.32 1.396 c
+8.121 1.396 7.971 1.341 7.864 1.234 c
+7.754 1.135 7.703 1.003 7.703 0.837 c
+7.703 0.708 7.739 0.602 7.82 0.514 c
+7.898 0.433 8.088 0.33 8.393 0.205 c
+8.871 0.018 9.201 -0.169 9.378 -0.353 c
+9.554 -0.53 9.643 -0.757 9.643 -1.029 c
+9.643 -1.382 9.517 -1.661 9.275 -1.867 c
+9.04 -2.073 8.724 -2.176 8.334 -2.176 c
+7.912 -2.176 7.574 -2.058 7.32 -1.823 c
+7.063 -1.58 6.938 -1.276 6.938 -0.912 c
+7.585 -0.912 l
+7.592 -1.139 7.662 -1.316 7.79 -1.441 c
+7.915 -1.559 8.099 -1.617 8.334 -1.617 c
+8.548 -1.617 8.709 -1.569 8.819 -1.47 c
+8.937 -1.374 8.996 -1.246 8.996 -1.088 c
+11.127 1.469 m
+11.381 1.793 11.701 1.955 12.083 1.955 c
+12.788 1.955 13.145 1.484 13.156 0.544 c
+13.156 -2.103 l
+12.509 -2.103 l
+12.509 0.514 l
+12.509 0.826 12.454 1.047 12.347 1.176 c
+12.237 1.3 12.083 1.367 11.877 1.367 c
+11.719 1.367 11.572 1.311 11.436 1.205 c
+11.308 1.095 11.204 0.959 11.127 0.793 c
+11.127 -2.103 l
+10.481 -2.103 l
+10.481 3.542 l
+11.127 3.542 l
+h
+16.536 -2.103 -0.646 5.644 re
+17.419 0.073 m
+17.419 0.65 17.554 1.105 17.83 1.44 c
+18.113 1.782 18.485 1.955 18.947 1.955 c
+19.407 1.955 19.774 1.786 20.05 1.454 c
+20.332 1.132 20.48 0.683 20.49 0.118 c
+20.49 -0.309 l
+20.49 -0.879 20.347 -1.334 20.064 -1.676 c
+19.788 -2.01 19.422 -2.176 18.962 -2.176 c
+18.499 -2.176 18.128 -2.014 17.845 -1.691 c
+17.569 -1.36 17.426 -0.919 17.419 -0.368 c
+h
+18.065 -0.309 m
+18.065 -0.713 18.142 -1.029 18.3 -1.264 c
+18.466 -1.5 18.686 -1.617 18.962 -1.617 c
+19.528 -1.617 19.821 -1.206 19.844 -0.383 c
+19.844 0.073 l
+19.844 0.473 19.759 0.793 19.594 1.028 c
+19.436 1.271 19.219 1.396 18.947 1.396 c
+18.682 1.396 18.466 1.271 18.3 1.028 c
+18.142 0.793 18.065 0.473 18.065 0.073 c
+h
+22.71 -1.617 m
+22.923 -1.617 23.096 -1.555 23.225 -1.426 c
+23.36 -1.291 23.434 -1.099 23.445 -0.853 c
+24.062 -0.853 l
+24.041 -1.235 23.904 -1.555 23.651 -1.808 c
+23.393 -2.055 23.081 -2.176 22.71 -2.176 c
+22.217 -2.176 21.843 -2.025 21.579 -1.721 c
+21.321 -1.408 21.196 -0.941 21.196 -0.324 c
+21.196 0.118 l
+21.196 0.712 21.321 1.168 21.579 1.484 c
+21.843 1.797 22.217 1.955 22.71 1.955 c
+23.111 1.955 23.43 1.822 23.665 1.558 c
+23.908 1.3 24.041 0.955 24.062 0.514 c
+23.445 0.514 l
+23.423 0.808 23.349 1.028 23.225 1.176 c
+23.107 1.323 22.934 1.396 22.71 1.396 c
+22.416 1.396 22.2 1.296 22.063 1.102 c
+21.924 0.914 21.851 0.606 21.843 0.176 c
+21.843 -0.339 l
+21.843 -0.809 21.909 -1.143 22.049 -1.338 c
+22.196 -1.526 22.416 -1.617 22.71 -1.617 c
+26.855 -2.103 m
+26.815 -2.014 26.789 -1.867 26.782 -1.661 c
+26.547 -2.007 26.252 -2.176 25.9 -2.176 c
+25.536 -2.176 25.253 -2.08 25.047 -1.881 c
+24.849 -1.676 24.754 -1.389 24.754 -1.015 c
+24.754 -0.614 24.889 -0.294 25.165 -0.059 c
+25.437 0.183 25.812 0.309 26.282 0.309 c
+26.767 0.309 l
+26.767 0.735 l
+26.767 0.97 26.712 1.135 26.605 1.234 c
+26.495 1.341 26.333 1.396 26.121 1.396 c
+25.922 1.396 25.76 1.337 25.635 1.219 c
+25.518 1.102 25.459 0.955 25.459 0.779 c
+24.812 0.779 l
+24.812 0.974 24.871 1.165 24.989 1.352 c
+25.113 1.535 25.275 1.683 25.473 1.793 c
+25.679 1.899 25.907 1.955 26.165 1.955 c
+26.565 1.955 26.87 1.851 27.075 1.646 c
+27.289 1.44 27.403 1.146 27.414 0.764 c
+27.414 -1.25 l
+27.414 -1.555 27.451 -1.819 27.532 -2.043 c
+27.532 -2.103 l
+h
+25.988 -1.588 m
+26.153 -1.588 26.304 -1.544 26.443 -1.455 c
+26.591 -1.368 26.697 -1.257 26.767 -1.118 c
+26.767 -0.177 l
+26.4 -0.177 l
+26.084 -0.177 25.841 -0.246 25.664 -0.383 c
+25.488 -0.511 25.4 -0.699 25.4 -0.941 c
+25.4 -1.169 25.444 -1.334 25.533 -1.441 c
+25.621 -1.54 25.772 -1.588 25.988 -1.588 c
+29.119 -2.103 -0.646 5.644 re
+34.734 -0.309 m
+34.734 -0.927 34.62 -1.393 34.396 -1.706 c
+34.179 -2.022 33.855 -2.176 33.425 -2.176 c
+33.003 -2.176 32.691 -1.996 32.485 -1.632 c
+32.456 -2.103 l
+31.852 -2.103 l
+31.852 3.542 l
+32.5 3.542 l
+32.5 1.44 l
+32.713 1.782 33.022 1.955 33.425 1.955 c
+33.855 1.955 34.179 1.797 34.396 1.484 c
+34.62 1.179 34.734 0.712 34.734 0.087 c
+h
+34.088 0.073 m
+34.088 0.544 34.017 0.874 33.882 1.072 c
+33.753 1.267 33.543 1.367 33.249 1.367 c
+32.915 1.367 32.665 1.183 32.5 0.823 c
+32.5 -1.058 l
+32.665 -1.422 32.918 -1.603 33.264 -1.603 c
+33.558 -1.603 33.768 -1.5 33.896 -1.294 c
+34.021 -1.088 34.088 -0.772 34.088 -0.339 c
+h
+37.218 1.263 m
+37.13 1.282 37.03 1.294 36.924 1.294 c
+36.59 1.294 36.355 1.109 36.218 0.749 c
+36.218 -2.103 l
+35.572 -2.103 l
+35.572 1.881 l
+36.204 1.881 l
+36.218 1.469 l
+36.395 1.793 36.637 1.955 36.953 1.955 c
+37.06 1.955 37.148 1.932 37.218 1.896 c
+h
+39.761 -2.103 m
+39.721 -2.014 39.695 -1.867 39.688 -1.661 c
+39.453 -2.007 39.158 -2.176 38.805 -2.176 c
+38.441 -2.176 38.159 -2.08 37.953 -1.881 c
+37.755 -1.676 37.659 -1.389 37.659 -1.015 c
+37.659 -0.614 37.795 -0.294 38.071 -0.059 c
+38.343 0.183 38.717 0.309 39.187 0.309 c
+39.673 0.309 l
+39.673 0.735 l
+39.673 0.97 39.617 1.135 39.511 1.234 c
+39.401 1.341 39.239 1.396 39.027 1.396 c
+38.828 1.396 38.666 1.337 38.541 1.219 c
+38.424 1.102 38.364 0.955 38.364 0.779 c
+37.718 0.779 l
+37.718 0.974 37.776 1.165 37.894 1.352 c
+38.019 1.535 38.181 1.683 38.379 1.793 c
+38.585 1.899 38.813 1.955 39.07 1.955 c
+39.471 1.955 39.775 1.851 39.981 1.646 c
+40.195 1.44 40.309 1.146 40.319 0.764 c
+40.319 -1.25 l
+40.319 -1.555 40.357 -1.819 40.438 -2.043 c
+40.438 -2.103 l
+h
+38.894 -1.588 m
+39.059 -1.588 39.21 -1.544 39.349 -1.455 c
+39.497 -1.368 39.603 -1.257 39.673 -1.118 c
+39.673 -0.177 l
+39.305 -0.177 l
+38.989 -0.177 38.747 -0.246 38.57 -0.383 c
+38.394 -0.511 38.306 -0.699 38.306 -0.941 c
+38.306 -1.169 38.35 -1.334 38.438 -1.441 c
+38.526 -1.54 38.677 -1.588 38.894 -1.588 c
+41.936 1.881 m
+41.951 1.44 l
+42.204 1.782 42.528 1.955 42.921 1.955 c
+43.627 1.955 43.983 1.484 43.995 0.544 c
+43.995 -2.103 l
+43.347 -2.103 l
+43.347 0.514 l
+43.347 0.826 43.293 1.047 43.186 1.176 c
+43.076 1.3 42.921 1.367 42.715 1.367 c
+42.557 1.367 42.41 1.311 42.275 1.205 c
+42.146 1.095 42.044 0.959 41.965 0.793 c
+41.965 -2.103 l
+41.319 -2.103 l
+41.319 1.881 l
+h
+46.346 -1.617 m
+46.559 -1.617 46.732 -1.555 46.861 -1.426 c
+46.997 -1.291 47.07 -1.099 47.081 -0.853 c
+47.698 -0.853 l
+47.677 -1.235 47.54 -1.555 47.287 -1.808 c
+47.029 -2.055 46.717 -2.176 46.346 -2.176 c
+45.854 -2.176 45.479 -2.025 45.215 -1.721 c
+44.957 -1.408 44.832 -0.941 44.832 -0.324 c
+44.832 0.118 l
+44.832 0.712 44.957 1.168 45.215 1.484 c
+45.479 1.797 45.854 1.955 46.346 1.955 c
+46.747 1.955 47.066 1.822 47.301 1.558 c
+47.544 1.3 47.677 0.955 47.698 0.514 c
+47.081 0.514 l
+47.06 0.808 46.985 1.028 46.861 1.176 c
+46.743 1.323 46.57 1.396 46.346 1.396 c
+46.052 1.396 45.836 1.296 45.699 1.102 c
+45.56 0.914 45.487 0.606 45.479 0.176 c
+45.479 -0.339 l
+45.479 -0.809 45.545 -1.143 45.685 -1.338 c
+45.832 -1.526 46.052 -1.617 46.346 -1.617 c
+49.095 1.469 m
+49.348 1.793 49.668 1.955 50.05 1.955 c
+50.756 1.955 51.112 1.484 51.124 0.544 c
+51.124 -2.103 l
+50.476 -2.103 l
+50.476 0.514 l
+50.476 0.826 50.422 1.047 50.315 1.176 c
+50.204 1.3 50.05 1.367 49.845 1.367 c
+49.687 1.367 49.539 1.311 49.404 1.205 c
+49.275 1.095 49.172 0.959 49.095 0.793 c
+49.095 -2.103 l
+48.448 -2.103 l
+48.448 3.542 l
+49.095 3.542 l
+h
+54.651 2.836 m
+54.651 1.881 l
+55.254 1.881 l
+55.254 1.352 l
+54.651 1.352 l
+54.651 -1.118 l
+54.651 -1.276 54.673 -1.393 54.725 -1.47 c
+54.784 -1.551 54.871 -1.588 54.989 -1.588 c
+55.077 -1.588 55.166 -1.573 55.254 -1.544 c
+55.254 -2.103 l
+55.107 -2.151 54.952 -2.176 54.798 -2.176 c
+54.541 -2.176 54.347 -2.084 54.21 -1.897 c
+54.071 -1.713 54.004 -1.452 54.004 -1.118 c
+54.004 1.352 l
+53.402 1.352 l
+53.402 1.881 l
+54.004 1.881 l
+54.004 2.836 l
+h
+55.812 0.073 m
+55.812 0.65 55.949 1.105 56.224 1.44 c
+56.507 1.782 56.878 1.955 57.341 1.955 c
+57.801 1.955 58.168 1.786 58.443 1.454 c
+58.727 1.132 58.873 0.683 58.885 0.118 c
+58.885 -0.309 l
+58.885 -0.879 58.742 -1.334 58.458 -1.676 c
+58.183 -2.01 57.815 -2.176 57.356 -2.176 c
+56.893 -2.176 56.522 -2.014 56.238 -1.691 c
+55.963 -1.36 55.82 -0.919 55.812 -0.368 c
+h
+56.459 -0.309 m
+56.459 -0.713 56.537 -1.029 56.695 -1.264 c
+56.86 -1.5 57.08 -1.617 57.356 -1.617 c
+57.921 -1.617 58.216 -1.206 58.237 -0.383 c
+58.237 0.073 l
+58.237 0.473 58.154 0.793 57.988 1.028 c
+57.83 1.271 57.613 1.396 57.341 1.396 c
+57.077 1.396 56.86 1.271 56.695 1.028 c
+56.537 0.793 56.459 0.473 56.459 0.073 c
+h
+f
+Q
+q 1 0 0 1 131.2811 144.5107 cm
+0 0 m
+-0.338 0.03 l
+-0.625 0.03 -0.816 -0.095 -0.911 -0.338 c
+-0.911 -2.969 l
+-1.955 -2.969 l
+-1.955 1.015 l
+-0.984 1.015 l
+-0.955 0.574 l
+-0.789 0.915 -0.558 1.088 -0.264 1.088 c
+-0.147 1.088 -0.055 1.066 0.015 1.029 c
+h
+2.073 -3.042 m
+1.544 -3.042 1.125 -2.888 0.823 -2.572 c
+0.53 -2.248 0.383 -1.789 0.383 -1.19 c
+0.383 -0.881 l
+0.383 -0.257 0.518 0.229 0.794 0.574 c
+1.066 0.915 1.459 1.088 1.97 1.088 c
+2.469 1.088 2.841 0.927 3.088 0.603 c
+3.341 0.279 3.473 -0.199 3.484 -0.823 c
+3.484 -1.323 l
+1.411 -1.323 l
+1.43 -1.616 1.492 -1.833 1.603 -1.969 c
+1.72 -2.109 1.9 -2.175 2.147 -2.175 c
+2.488 -2.175 2.779 -2.057 3.014 -1.822 c
+3.425 -2.454 l
+3.296 -2.63 3.109 -2.774 2.866 -2.881 c
+2.621 -2.987 2.356 -3.042 2.073 -3.042 c
+1.426 -0.602 m
+2.455 -0.602 l
+2.455 -0.5 l
+2.455 -0.264 2.415 -0.087 2.338 0.03 c
+2.268 0.154 2.139 0.221 1.955 0.221 c
+1.779 0.221 1.646 0.151 1.559 0.015 c
+1.478 -0.114 1.434 -0.319 1.426 -0.602 c
+5.042 1.015 m
+5.072 0.647 l
+5.307 0.941 5.615 1.088 5.997 1.088 c
+6.398 1.088 6.677 0.904 6.835 0.545 c
+7.071 0.904 7.398 1.088 7.82 1.088 c
+8.515 1.088 8.867 0.603 8.879 -0.367 c
+8.879 -2.969 l
+7.85 -2.969 l
+7.85 -0.426 l
+7.85 -0.201 7.813 -0.04 7.747 0.059 c
+7.688 0.154 7.578 0.206 7.423 0.206 c
+7.225 0.206 7.086 0.088 6.997 -0.147 c
+6.997 -2.969 l
+5.953 -2.969 l
+5.953 -0.44 l
+5.953 -0.205 5.924 -0.04 5.866 0.059 c
+5.806 0.154 5.696 0.206 5.542 0.206 c
+5.366 0.206 5.222 0.111 5.116 -0.073 c
+5.116 -2.969 l
+4.072 -2.969 l
+4.072 1.015 l
+h
+9.54 -0.852 m
+9.54 -0.246 9.679 0.229 9.966 0.574 c
+10.249 0.915 10.643 1.088 11.142 1.088 c
+11.649 1.088 12.046 0.915 12.333 0.574 c
+12.616 0.229 12.759 -0.246 12.759 -0.852 c
+12.759 -1.117 l
+12.759 -1.716 12.616 -2.186 12.333 -2.528 c
+12.046 -2.873 11.649 -3.042 11.142 -3.042 c
+10.631 -3.042 10.234 -2.873 9.951 -2.528 c
+9.676 -2.186 9.54 -1.712 9.54 -1.102 c
+h
+10.583 -1.117 m
+10.583 -1.822 10.768 -2.175 11.142 -2.175 c
+11.495 -2.175 11.686 -1.881 11.716 -1.294 c
+11.716 -0.852 l
+11.716 -0.492 11.664 -0.22 11.568 -0.043 c
+11.469 0.133 11.326 0.221 11.142 0.221 c
+10.966 0.221 10.826 0.133 10.731 -0.043 c
+10.631 -0.22 10.583 -0.492 10.583 -0.852 c
+h
+14.612 1.985 m
+14.612 1.015 l
+15.14 1.015 l
+15.14 0.221 l
+14.612 0.221 l
+14.612 -1.749 l
+14.612 -1.907 14.629 -2.013 14.67 -2.072 c
+14.718 -2.131 14.803 -2.16 14.92 -2.16 c
+15.026 -2.16 15.111 -2.153 15.169 -2.131 c
+15.169 -2.94 l
+14.993 -3.006 14.803 -3.042 14.597 -3.042 c
+13.92 -3.042 13.575 -2.657 13.567 -1.881 c
+13.567 0.221 l
+13.112 0.221 l
+13.112 1.015 l
+13.567 1.015 l
+13.567 1.985 l
+h
+17.316 -3.042 m
+16.787 -3.042 16.368 -2.888 16.066 -2.572 c
+15.772 -2.248 15.626 -1.789 15.626 -1.19 c
+15.626 -0.881 l
+15.626 -0.257 15.761 0.229 16.037 0.574 c
+16.309 0.915 16.702 1.088 17.213 1.088 c
+17.712 1.088 18.084 0.927 18.33 0.603 c
+18.583 0.279 18.716 -0.199 18.727 -0.823 c
+18.727 -1.323 l
+16.655 -1.323 l
+16.673 -1.616 16.735 -1.833 16.846 -1.969 c
+16.963 -2.109 17.143 -2.175 17.39 -2.175 c
+17.731 -2.175 18.022 -2.057 18.257 -1.822 c
+18.668 -2.454 l
+18.539 -2.63 18.352 -2.774 18.109 -2.881 c
+17.864 -2.987 17.598 -3.042 17.316 -3.042 c
+16.669 -0.602 m
+17.698 -0.602 l
+17.698 -0.5 l
+17.698 -0.264 17.658 -0.087 17.581 0.03 c
+17.511 0.154 17.382 0.221 17.199 0.221 c
+17.022 0.221 16.89 0.151 16.802 0.015 c
+16.721 -0.114 16.676 -0.319 16.669 -0.602 c
+f
+Q
+q 1 0 0 1 154.0648 144.9077 cm
+0 0 m
+-0.088 0.019 -0.187 0.03 -0.294 0.03 c
+-0.628 0.03 -0.864 -0.154 -0.999 -0.515 c
+-0.999 -3.366 l
+-1.646 -3.366 l
+-1.646 0.618 l
+-1.014 0.618 l
+-0.999 0.206 l
+-0.823 0.53 -0.58 0.691 -0.264 0.691 c
+-0.158 0.691 -0.07 0.669 0 0.632 c
+h
+1.999 -3.439 m
+1.5 -3.439 1.118 -3.293 0.852 -2.998 c
+0.588 -2.705 0.456 -2.271 0.456 -1.691 c
+0.456 -1.22 l
+0.456 -0.625 0.58 -0.158 0.838 0.177 c
+1.103 0.518 1.463 0.691 1.926 0.691 c
+2.385 0.691 2.727 0.537 2.955 0.235 c
+3.19 -0.058 3.311 -0.521 3.322 -1.146 c
+3.322 -1.573 l
+1.103 -1.573 l
+1.103 -1.66 l
+1.103 -2.094 1.18 -2.406 1.338 -2.601 c
+1.503 -2.789 1.735 -2.881 2.028 -2.881 c
+2.223 -2.881 2.396 -2.848 2.543 -2.778 c
+2.69 -2.701 2.826 -2.583 2.955 -2.425 c
+3.293 -2.836 l
+3.006 -3.241 2.576 -3.439 1.999 -3.439 c
+1.926 0.133 m
+1.65 0.133 1.448 0.037 1.323 -0.147 c
+1.195 -0.334 1.121 -0.625 1.103 -1.014 c
+2.675 -1.014 l
+2.675 -0.926 l
+2.653 -0.544 2.587 -0.276 2.469 -0.118 c
+2.352 0.048 2.168 0.133 1.926 0.133 c
+6.982 -1.573 m
+6.982 -2.201 6.865 -2.672 6.629 -2.984 c
+6.402 -3.289 6.086 -3.439 5.674 -3.439 c
+5.27 -3.439 4.961 -3.289 4.748 -2.984 c
+4.748 -4.895 l
+4.101 -4.895 l
+4.101 0.618 l
+4.69 0.618 l
+4.733 0.177 l
+4.946 0.518 5.255 0.691 5.659 0.691 c
+6.101 0.691 6.427 0.537 6.644 0.235 c
+6.857 -0.07 6.971 -0.525 6.982 -1.132 c
+h
+6.336 -1.19 m
+6.336 -0.75 6.265 -0.426 6.13 -0.22 c
+5.99 -0.008 5.77 0.103 5.469 0.103 c
+5.152 0.103 4.913 -0.051 4.748 -0.353 c
+4.748 -2.425 l
+4.913 -2.73 5.152 -2.881 5.469 -2.881 c
+5.762 -2.881 5.976 -2.778 6.115 -2.572 c
+6.251 -2.359 6.325 -2.028 6.336 -1.587 c
+h
+7.688 -1.19 m
+7.688 -0.613 7.824 -0.158 8.099 0.177 c
+8.382 0.518 8.754 0.691 9.216 0.691 c
+9.676 0.691 10.043 0.522 10.319 0.191 c
+10.602 -0.132 10.749 -0.58 10.76 -1.146 c
+10.76 -1.573 l
+10.76 -2.142 10.616 -2.597 10.334 -2.94 c
+10.058 -3.274 9.691 -3.439 9.231 -3.439 c
+8.768 -3.439 8.397 -3.278 8.114 -2.954 c
+7.838 -2.624 7.695 -2.183 7.688 -1.631 c
+h
+8.334 -1.573 m
+8.334 -1.976 8.412 -2.293 8.569 -2.528 c
+8.735 -2.763 8.956 -2.881 9.231 -2.881 c
+9.797 -2.881 10.091 -2.469 10.113 -1.646 c
+10.113 -1.19 l
+10.113 -0.79 10.028 -0.47 9.864 -0.235 c
+9.706 0.008 9.488 0.133 9.216 0.133 c
+8.952 0.133 8.735 0.008 8.569 -0.235 c
+8.412 -0.47 8.334 -0.79 8.334 -1.19 c
+h
+13.538 -2.352 m
+13.538 -2.204 13.483 -2.084 13.376 -1.984 c
+13.266 -1.889 13.06 -1.771 12.759 -1.631 c
+12.413 -1.484 12.171 -1.363 12.024 -1.263 c
+11.877 -1.157 11.767 -1.04 11.701 -0.911 c
+11.63 -0.786 11.597 -0.628 11.597 -0.44 c
+11.597 -0.118 11.715 0.151 11.95 0.368 c
+12.185 0.58 12.487 0.691 12.862 0.691 c
+13.244 0.691 13.552 0.578 13.787 0.353 c
+14.023 0.125 14.14 -0.162 14.14 -0.515 c
+13.494 -0.515 l
+13.494 -0.338 13.435 -0.187 13.317 -0.058 c
+13.2 0.067 13.045 0.133 12.862 0.133 c
+12.663 0.133 12.513 0.077 12.406 -0.029 c
+12.295 -0.128 12.245 -0.261 12.245 -0.426 c
+12.245 -0.555 12.281 -0.661 12.362 -0.75 c
+12.439 -0.831 12.63 -0.933 12.935 -1.058 c
+13.413 -1.246 13.743 -1.433 13.92 -1.616 c
+14.097 -1.793 14.184 -2.021 14.184 -2.293 c
+14.184 -2.645 14.059 -2.925 13.818 -3.131 c
+13.582 -3.337 13.266 -3.439 12.877 -3.439 c
+12.454 -3.439 12.116 -3.322 11.862 -3.087 c
+11.605 -2.844 11.48 -2.539 11.48 -2.175 c
+12.127 -2.175 l
+12.135 -2.403 12.204 -2.579 12.332 -2.705 c
+12.457 -2.822 12.642 -2.881 12.877 -2.881 c
+13.089 -2.881 13.251 -2.833 13.361 -2.734 c
+13.479 -2.638 13.538 -2.51 13.538 -2.352 c
+15.728 -3.366 -0.647 3.984 re
+15.772 1.661 m
+15.772 1.551 15.743 1.459 15.684 1.382 c
+15.625 1.312 15.53 1.279 15.405 1.279 c
+15.287 1.279 15.192 1.312 15.125 1.382 c
+15.067 1.459 15.038 1.551 15.038 1.661 c
+15.038 1.779 15.067 1.871 15.125 1.941 c
+15.192 2.018 15.287 2.058 15.405 2.058 c
+15.53 2.058 15.625 2.018 15.684 1.941 c
+15.743 1.86 15.772 1.768 15.772 1.661 c
+17.595 1.573 m
+17.595 0.618 l
+18.198 0.618 l
+18.198 0.088 l
+17.595 0.088 l
+17.595 -2.381 l
+17.595 -2.539 17.617 -2.657 17.668 -2.734 c
+17.727 -2.815 17.816 -2.851 17.933 -2.851 c
+18.021 -2.851 18.109 -2.836 18.198 -2.807 c
+18.198 -3.366 l
+18.051 -3.414 17.897 -3.439 17.741 -3.439 c
+17.485 -3.439 17.29 -3.347 17.154 -3.16 c
+17.014 -2.976 16.948 -2.715 16.948 -2.381 c
+16.948 0.088 l
+16.345 0.088 l
+16.345 0.618 l
+16.948 0.618 l
+16.948 1.573 l
+h
+18.756 -1.19 m
+18.756 -0.613 18.892 -0.158 19.168 0.177 c
+19.451 0.518 19.821 0.691 20.285 0.691 c
+20.744 0.691 21.112 0.522 21.388 0.191 c
+21.67 -0.132 21.818 -0.58 21.828 -1.146 c
+21.828 -1.573 l
+21.828 -2.142 21.685 -2.597 21.402 -2.94 c
+21.126 -3.274 20.759 -3.439 20.299 -3.439 c
+19.836 -3.439 19.466 -3.278 19.183 -2.954 c
+18.907 -2.624 18.763 -2.183 18.756 -1.631 c
+h
+19.403 -1.573 m
+19.403 -1.976 19.48 -2.293 19.638 -2.528 c
+19.803 -2.763 20.024 -2.881 20.299 -2.881 c
+20.866 -2.881 21.159 -2.469 21.182 -1.646 c
+21.182 -1.19 l
+21.182 -0.79 21.097 -0.47 20.931 -0.235 c
+20.773 0.008 20.557 0.133 20.285 0.133 c
+20.02 0.133 19.803 0.008 19.638 -0.235 c
+19.48 -0.47 19.403 -0.79 19.403 -1.19 c
+h
+24.312 0 m
+24.224 0.019 24.125 0.03 24.018 0.03 c
+23.684 0.03 23.449 -0.154 23.312 -0.515 c
+23.312 -3.366 l
+22.666 -3.366 l
+22.666 0.618 l
+23.298 0.618 l
+23.312 0.206 l
+23.489 0.53 23.732 0.691 24.048 0.691 c
+24.154 0.691 24.243 0.669 24.312 0.632 c
+h
+26.121 -2.278 m
+26.84 0.618 l
+27.532 0.618 l
+26.238 -3.925 l
+26.138 -4.266 25.995 -4.527 25.812 -4.704 c
+25.635 -4.88 25.433 -4.968 25.209 -4.968 c
+25.121 -4.968 25.007 -4.946 24.871 -4.909 c
+24.871 -4.365 l
+25.018 -4.38 l
+25.201 -4.38 25.348 -4.336 25.459 -4.247 c
+25.566 -4.16 25.654 -4.002 25.724 -3.777 c
+25.841 -3.337 l
+24.68 0.618 l
+25.386 0.618 l
+h
+27.811 -3.013 m
+27.811 -2.896 27.844 -2.8 27.914 -2.719 c
+27.979 -2.642 28.083 -2.601 28.222 -2.601 c
+28.369 -2.601 28.476 -2.642 28.546 -2.719 c
+28.623 -2.8 28.663 -2.896 28.663 -3.013 c
+28.663 -3.123 28.623 -3.215 28.546 -3.293 c
+28.476 -3.37 28.369 -3.41 28.222 -3.41 c
+28.083 -3.41 27.979 -3.37 27.914 -3.293 c
+27.844 -3.215 27.811 -3.123 27.811 -3.013 c
+33.896 -2.013 m
+33.896 -1.749 33.822 -1.55 33.676 -1.411 c
+33.536 -1.263 33.279 -1.124 32.897 -0.985 c
+32.521 -0.849 32.235 -0.706 32.029 -0.558 c
+31.831 -0.411 31.684 -0.246 31.588 -0.058 c
+31.489 0.136 31.441 0.357 31.441 0.603 c
+31.441 1.022 31.581 1.371 31.868 1.646 c
+32.151 1.918 32.519 2.058 32.97 2.058 c
+33.282 2.058 33.562 1.985 33.808 1.837 c
+34.05 1.698 34.238 1.503 34.366 1.249 c
+34.503 1.004 34.572 0.736 34.572 0.441 c
+33.896 0.441 l
+33.896 0.772 33.815 1.029 33.661 1.206 c
+33.503 1.389 33.271 1.484 32.97 1.484 c
+32.706 1.484 32.492 1.404 32.338 1.249 c
+32.191 1.103 32.118 0.89 32.118 0.618 c
+32.118 0.389 32.195 0.199 32.353 0.044 c
+32.519 -0.103 32.772 -0.243 33.117 -0.367 c
+33.635 -0.536 34.007 -0.746 34.234 -0.999 c
+34.47 -1.257 34.587 -1.587 34.587 -1.999 c
+34.587 -2.439 34.443 -2.792 34.161 -3.057 c
+33.874 -3.314 33.492 -3.439 33.014 -3.439 c
+32.698 -3.439 32.411 -3.37 32.147 -3.233 c
+31.883 -3.098 31.669 -2.907 31.515 -2.66 c
+31.368 -2.418 31.295 -2.131 31.295 -1.808 c
+31.971 -1.808 l
+31.971 -2.142 32.062 -2.403 32.249 -2.587 c
+32.434 -2.774 32.691 -2.866 33.014 -2.866 c
+33.308 -2.866 33.529 -2.792 33.676 -2.645 c
+33.822 -2.491 33.896 -2.278 33.896 -2.013 c
+36.791 -3.439 m
+36.292 -3.439 35.91 -3.293 35.646 -2.998 c
+35.38 -2.705 35.249 -2.271 35.249 -1.691 c
+35.249 -1.22 l
+35.249 -0.625 35.374 -0.158 35.631 0.177 c
+35.895 0.518 36.255 0.691 36.718 0.691 c
+37.178 0.691 37.52 0.537 37.747 0.235 c
+37.982 -0.058 38.104 -0.521 38.115 -1.146 c
+38.115 -1.573 l
+35.895 -1.573 l
+35.895 -1.66 l
+35.895 -2.094 35.972 -2.406 36.13 -2.601 c
+36.296 -2.789 36.527 -2.881 36.821 -2.881 c
+37.016 -2.881 37.188 -2.848 37.336 -2.778 c
+37.483 -2.701 37.618 -2.583 37.747 -2.425 c
+38.086 -2.836 l
+37.799 -3.241 37.369 -3.439 36.791 -3.439 c
+36.718 0.133 m
+36.442 0.133 36.241 0.037 36.116 -0.147 c
+35.987 -0.334 35.914 -0.625 35.895 -1.014 c
+37.468 -1.014 l
+37.468 -0.926 l
+37.446 -0.544 37.38 -0.276 37.262 -0.118 c
+37.145 0.048 36.961 0.133 36.718 0.133 c
+39.746 1.573 m
+39.746 0.618 l
+40.349 0.618 l
+40.349 0.088 l
+39.746 0.088 l
+39.746 -2.381 l
+39.746 -2.539 39.769 -2.657 39.82 -2.734 c
+39.879 -2.815 39.967 -2.851 40.084 -2.851 c
+40.172 -2.851 40.261 -2.836 40.349 -2.807 c
+40.349 -3.366 l
+40.202 -3.414 40.047 -3.439 39.893 -3.439 c
+39.636 -3.439 39.441 -3.347 39.305 -3.16 c
+39.166 -2.976 39.1 -2.715 39.1 -2.381 c
+39.1 0.088 l
+38.497 0.088 l
+38.497 0.618 l
+39.1 0.618 l
+39.1 1.573 l
+h
+43.538 -3.366 -0.646 3.984 re
+43.583 1.661 m
+43.583 1.551 43.553 1.459 43.495 1.382 c
+43.436 1.312 43.34 1.279 43.216 1.279 c
+43.098 1.279 43.002 1.312 42.936 1.382 c
+42.877 1.459 42.848 1.551 42.848 1.661 c
+42.848 1.779 42.877 1.871 42.936 1.941 c
+43.002 2.018 43.098 2.058 43.216 2.058 c
+43.34 2.058 43.436 2.018 43.495 1.941 c
+43.553 1.86 43.583 1.768 43.583 1.661 c
+45.406 1.573 m
+45.406 0.618 l
+46.008 0.618 l
+46.008 0.088 l
+45.406 0.088 l
+45.406 -2.381 l
+45.406 -2.539 45.427 -2.657 45.479 -2.734 c
+45.537 -2.815 45.626 -2.851 45.743 -2.851 c
+45.832 -2.851 45.92 -2.836 46.008 -2.807 c
+46.008 -3.366 l
+45.861 -3.414 45.707 -3.439 45.552 -3.439 c
+45.296 -3.439 45.101 -3.347 44.965 -3.16 c
+44.825 -2.976 44.758 -2.715 44.758 -2.381 c
+44.758 0.088 l
+44.156 0.088 l
+44.156 0.618 l
+44.758 0.618 l
+44.758 1.573 l
+h
+48.712 -2.352 m
+48.712 -2.204 48.658 -2.084 48.551 -1.984 c
+48.441 -1.889 48.235 -1.771 47.934 -1.631 c
+47.588 -1.484 47.346 -1.363 47.199 -1.263 c
+47.052 -1.157 46.942 -1.04 46.875 -0.911 c
+46.806 -0.786 46.773 -0.628 46.773 -0.44 c
+46.773 -0.118 46.89 0.151 47.125 0.368 c
+47.361 0.58 47.662 0.691 48.037 0.691 c
+48.419 0.691 48.727 0.578 48.963 0.353 c
+49.198 0.125 49.315 -0.162 49.315 -0.515 c
+48.669 -0.515 l
+48.669 -0.338 48.61 -0.187 48.492 -0.058 c
+48.375 0.067 48.22 0.133 48.037 0.133 c
+47.838 0.133 47.688 0.077 47.581 -0.029 c
+47.471 -0.128 47.419 -0.261 47.419 -0.426 c
+47.419 -0.555 47.456 -0.661 47.536 -0.75 c
+47.614 -0.831 47.806 -0.933 48.11 -1.058 c
+48.588 -1.246 48.918 -1.433 49.095 -1.616 c
+49.271 -1.793 49.36 -2.021 49.36 -2.293 c
+49.36 -2.645 49.235 -2.925 48.992 -3.131 c
+48.757 -3.337 48.441 -3.439 48.051 -3.439 c
+47.629 -3.439 47.291 -3.322 47.037 -3.087 c
+46.78 -2.844 46.655 -2.539 46.655 -2.175 c
+47.301 -2.175 l
+47.309 -2.403 47.378 -2.579 47.507 -2.705 c
+47.632 -2.822 47.816 -2.881 48.051 -2.881 c
+48.265 -2.881 48.426 -2.833 48.536 -2.734 c
+48.654 -2.638 48.712 -2.51 48.712 -2.352 c
+53.299 -2.881 m
+53.512 -2.881 53.685 -2.818 53.813 -2.69 c
+53.95 -2.554 54.023 -2.362 54.034 -2.117 c
+54.651 -2.117 l
+54.629 -2.499 54.493 -2.818 54.239 -3.072 c
+53.982 -3.318 53.67 -3.439 53.299 -3.439 c
+52.807 -3.439 52.432 -3.289 52.167 -2.984 c
+51.91 -2.672 51.785 -2.204 51.785 -1.587 c
+51.785 -1.146 l
+51.785 -0.551 51.91 -0.095 52.167 0.221 c
+52.432 0.533 52.807 0.691 53.299 0.691 c
+53.699 0.691 54.019 0.559 54.254 0.294 c
+54.497 0.037 54.629 -0.309 54.651 -0.75 c
+54.034 -0.75 l
+54.012 -0.455 53.938 -0.235 53.813 -0.087 c
+53.696 0.059 53.523 0.133 53.299 0.133 c
+53.005 0.133 52.788 0.033 52.652 -0.162 c
+52.512 -0.349 52.439 -0.658 52.432 -1.087 c
+52.432 -1.602 l
+52.432 -2.072 52.498 -2.406 52.637 -2.601 c
+52.784 -2.789 53.005 -2.881 53.299 -2.881 c
+55.268 -1.19 m
+55.268 -0.613 55.405 -0.158 55.68 0.177 c
+55.963 0.518 56.334 0.691 56.797 0.691 c
+57.256 0.691 57.624 0.522 57.9 0.191 c
+58.183 -0.132 58.33 -0.58 58.341 -1.146 c
+58.341 -1.573 l
+58.341 -2.142 58.197 -2.597 57.915 -2.94 c
+57.639 -3.274 57.271 -3.439 56.812 -3.439 c
+56.349 -3.439 55.978 -3.278 55.695 -2.954 c
+55.419 -2.624 55.276 -2.183 55.268 -1.631 c
+h
+55.916 -1.573 m
+55.916 -1.976 55.993 -2.293 56.151 -2.528 c
+56.315 -2.763 56.537 -2.881 56.812 -2.881 c
+57.378 -2.881 57.672 -2.469 57.694 -1.646 c
+57.694 -1.19 l
+57.694 -0.79 57.609 -0.47 57.444 -0.235 c
+57.286 0.008 57.069 0.133 56.797 0.133 c
+56.533 0.133 56.315 0.008 56.151 -0.235 c
+55.993 -0.47 55.916 -0.79 55.916 -1.19 c
+h
+62.06 -1.573 m
+62.06 -2.201 61.942 -2.672 61.707 -2.984 c
+61.479 -3.289 61.163 -3.439 60.751 -3.439 c
+60.347 -3.439 60.038 -3.289 59.825 -2.984 c
+59.825 -4.895 l
+59.178 -4.895 l
+59.178 0.618 l
+59.766 0.618 l
+59.81 0.177 l
+60.024 0.518 60.332 0.691 60.737 0.691 c
+61.177 0.691 61.505 0.537 61.721 0.235 c
+61.935 -0.07 62.048 -0.525 62.06 -1.132 c
+h
+61.412 -1.19 m
+61.412 -0.75 61.343 -0.426 61.207 -0.22 c
+61.067 -0.008 60.847 0.103 60.545 0.103 c
+60.23 0.103 59.991 -0.051 59.825 -0.353 c
+59.825 -2.425 l
+59.991 -2.73 60.23 -2.881 60.545 -2.881 c
+60.839 -2.881 61.053 -2.778 61.192 -2.572 c
+61.329 -2.359 61.402 -2.028 61.412 -1.587 c
+h
+63.941 -2.278 m
+64.662 0.618 l
+65.352 0.618 l
+64.059 -3.925 l
+63.959 -4.266 63.816 -4.527 63.633 -4.704 c
+63.456 -4.88 63.253 -4.968 63.03 -4.968 c
+62.941 -4.968 62.827 -4.946 62.692 -4.909 c
+62.692 -4.365 l
+62.839 -4.38 l
+63.022 -4.38 63.17 -4.336 63.28 -4.247 c
+63.386 -4.16 63.475 -4.002 63.544 -3.777 c
+63.662 -3.337 l
+62.501 0.618 l
+63.206 0.618 l
+h
+69.747 -3.366 m
+69.707 -3.278 69.681 -3.131 69.674 -2.925 c
+69.439 -3.27 69.144 -3.439 68.792 -3.439 c
+68.427 -3.439 68.145 -3.343 67.939 -3.145 c
+67.741 -2.94 67.645 -2.653 67.645 -2.278 c
+67.645 -1.878 67.781 -1.558 68.057 -1.323 c
+68.329 -1.08 68.703 -0.955 69.173 -0.955 c
+69.659 -0.955 l
+69.659 -0.529 l
+69.659 -0.294 69.603 -0.128 69.497 -0.029 c
+69.387 0.077 69.225 0.133 69.012 0.133 c
+68.814 0.133 68.652 0.073 68.527 -0.044 c
+68.41 -0.162 68.35 -0.309 68.35 -0.484 c
+67.704 -0.484 l
+67.704 -0.29 67.762 -0.099 67.88 0.088 c
+68.005 0.272 68.167 0.42 68.365 0.53 c
+68.571 0.636 68.799 0.691 69.056 0.691 c
+69.457 0.691 69.761 0.588 69.967 0.383 c
+70.181 0.177 70.295 -0.118 70.306 -0.5 c
+70.306 -2.514 l
+70.306 -2.818 70.343 -3.083 70.423 -3.307 c
+70.423 -3.366 l
+h
+68.88 -2.851 m
+69.046 -2.851 69.196 -2.807 69.335 -2.719 c
+69.482 -2.631 69.589 -2.52 69.659 -2.381 c
+69.659 -1.44 l
+69.291 -1.44 l
+68.975 -1.44 68.733 -1.51 68.556 -1.646 c
+68.38 -1.774 68.292 -1.962 68.292 -2.204 c
+68.292 -2.433 68.336 -2.597 68.425 -2.705 c
+68.512 -2.803 68.663 -2.851 68.88 -2.851 c
+73.245 -2.352 m
+73.245 -2.204 73.19 -2.084 73.084 -1.984 c
+72.973 -1.889 72.768 -1.771 72.466 -1.631 c
+72.121 -1.484 71.878 -1.363 71.731 -1.263 c
+71.585 -1.157 71.475 -1.04 71.408 -0.911 c
+71.338 -0.786 71.305 -0.628 71.305 -0.44 c
+71.305 -0.118 71.423 0.151 71.658 0.368 c
+71.893 0.58 72.194 0.691 72.57 0.691 c
+72.952 0.691 73.26 0.578 73.495 0.353 c
+73.73 0.125 73.848 -0.162 73.848 -0.515 c
+73.202 -0.515 l
+73.202 -0.338 73.142 -0.187 73.025 -0.058 c
+72.907 0.067 72.753 0.133 72.57 0.133 c
+72.371 0.133 72.221 0.077 72.113 -0.029 c
+72.003 -0.128 71.952 -0.261 71.952 -0.426 c
+71.952 -0.555 71.989 -0.661 72.069 -0.75 c
+72.147 -0.831 72.338 -0.933 72.643 -1.058 c
+73.121 -1.246 73.451 -1.433 73.628 -1.616 c
+73.804 -1.793 73.892 -2.021 73.892 -2.293 c
+73.892 -2.645 73.767 -2.925 73.524 -3.131 c
+73.289 -3.337 72.973 -3.439 72.584 -3.439 c
+72.161 -3.439 71.824 -3.322 71.57 -3.087 c
+71.313 -2.844 71.188 -2.539 71.188 -2.175 c
+71.834 -2.175 l
+71.841 -2.403 71.912 -2.579 72.04 -2.705 c
+72.165 -2.822 72.348 -2.881 72.584 -2.881 c
+72.797 -2.881 72.959 -2.833 73.069 -2.734 c
+73.187 -2.638 73.245 -2.51 73.245 -2.352 c
+78.493 -3.366 m
+78.453 -3.278 78.427 -3.131 78.419 -2.925 c
+78.184 -3.27 77.89 -3.439 77.538 -3.439 c
+77.174 -3.439 76.891 -3.343 76.685 -3.145 c
+76.487 -2.94 76.391 -2.653 76.391 -2.278 c
+76.391 -1.878 76.527 -1.558 76.803 -1.323 c
+77.075 -1.08 77.449 -0.955 77.92 -0.955 c
+78.405 -0.955 l
+78.405 -0.529 l
+78.405 -0.294 78.349 -0.128 78.243 -0.029 c
+78.133 0.077 77.971 0.133 77.758 0.133 c
+77.559 0.133 77.398 0.073 77.273 -0.044 c
+77.156 -0.162 77.096 -0.309 77.096 -0.484 c
+76.45 -0.484 l
+76.45 -0.29 76.508 -0.099 76.626 0.088 c
+76.751 0.272 76.913 0.42 77.111 0.53 c
+77.317 0.636 77.545 0.691 77.802 0.691 c
+78.203 0.691 78.508 0.588 78.714 0.383 c
+78.927 0.177 79.041 -0.118 79.051 -0.5 c
+79.051 -2.514 l
+79.051 -2.818 79.088 -3.083 79.169 -3.307 c
+79.169 -3.366 l
+h
+77.626 -2.851 m
+77.792 -2.851 77.942 -2.807 78.081 -2.719 c
+78.228 -2.631 78.335 -2.52 78.405 -2.381 c
+78.405 -1.44 l
+78.037 -1.44 l
+77.721 -1.44 77.478 -1.51 77.302 -1.646 c
+77.127 -1.774 77.038 -1.962 77.038 -2.204 c
+77.038 -2.433 77.082 -2.597 77.17 -2.705 c
+77.258 -2.803 77.409 -2.851 77.626 -2.851 c
+80.668 0.618 m
+80.683 0.177 l
+80.937 0.518 81.26 0.691 81.653 0.691 c
+82.359 0.691 82.715 0.221 82.727 -0.72 c
+82.727 -3.366 l
+82.08 -3.366 l
+82.08 -0.75 l
+82.08 -0.437 82.025 -0.216 81.918 -0.087 c
+81.808 0.037 81.653 0.103 81.447 0.103 c
+81.289 0.103 81.143 0.048 81.006 -0.058 c
+80.878 -0.168 80.775 -0.305 80.698 -0.47 c
+80.698 -3.366 l
+80.051 -3.366 l
+80.051 0.618 l
+h
+87.445 -3.013 m
+87.228 -3.3 86.916 -3.439 86.504 -3.439 c
+86.141 -3.439 85.865 -3.318 85.681 -3.072 c
+85.505 -2.818 85.409 -2.454 85.401 -1.984 c
+85.401 0.618 l
+86.048 0.618 l
+86.048 -1.926 l
+86.048 -2.554 86.232 -2.866 86.607 -2.866 c
+87.007 -2.866 87.283 -2.69 87.43 -2.337 c
+87.43 0.618 l
+88.077 0.618 l
+88.077 -3.366 l
+87.46 -3.366 l
+h
+91.943 -1.573 m
+91.943 -2.201 91.825 -2.672 91.589 -2.984 c
+91.362 -3.289 91.046 -3.439 90.635 -3.439 c
+90.23 -3.439 89.922 -3.289 89.708 -2.984 c
+89.708 -4.895 l
+89.062 -4.895 l
+89.062 0.618 l
+89.65 0.618 l
+89.694 0.177 l
+89.906 0.518 90.216 0.691 90.62 0.691 c
+91.061 0.691 91.388 0.537 91.604 0.235 c
+91.818 -0.07 91.932 -0.525 91.943 -1.132 c
+h
+91.296 -1.19 m
+91.296 -0.75 91.226 -0.426 91.09 -0.22 c
+90.951 -0.008 90.73 0.103 90.429 0.103 c
+90.112 0.103 89.874 -0.051 89.708 -0.353 c
+89.708 -2.425 l
+89.874 -2.73 90.112 -2.881 90.429 -2.881 c
+90.723 -2.881 90.936 -2.778 91.076 -2.572 c
+91.211 -2.359 91.285 -2.028 91.296 -1.587 c
+h
+94.721 -2.352 m
+94.721 -2.204 94.666 -2.084 94.559 -1.984 c
+94.449 -1.889 94.243 -1.771 93.941 -1.631 c
+93.596 -1.484 93.354 -1.363 93.207 -1.263 c
+93.06 -1.157 92.95 -1.04 92.884 -0.911 c
+92.813 -0.786 92.78 -0.628 92.78 -0.44 c
+92.78 -0.118 92.898 0.151 93.133 0.368 c
+93.368 0.58 93.669 0.691 94.045 0.691 c
+94.427 0.691 94.735 0.578 94.97 0.353 c
+95.206 0.125 95.323 -0.162 95.323 -0.515 c
+94.677 -0.515 l
+94.677 -0.338 94.618 -0.187 94.5 -0.058 c
+94.383 0.067 94.228 0.133 94.045 0.133 c
+93.846 0.133 93.696 0.077 93.589 -0.029 c
+93.478 -0.128 93.428 -0.261 93.428 -0.426 c
+93.428 -0.555 93.464 -0.661 93.545 -0.75 c
+93.622 -0.831 93.813 -0.933 94.118 -1.058 c
+94.596 -1.246 94.926 -1.433 95.103 -1.616 c
+95.279 -1.793 95.367 -2.021 95.367 -2.293 c
+95.367 -2.645 95.242 -2.925 95.001 -3.131 c
+94.765 -3.337 94.449 -3.439 94.06 -3.439 c
+93.637 -3.439 93.299 -3.322 93.045 -3.087 c
+92.788 -2.844 92.663 -2.539 92.663 -2.175 c
+93.31 -2.175 l
+93.317 -2.403 93.387 -2.579 93.515 -2.705 c
+93.64 -2.822 93.825 -2.881 94.06 -2.881 c
+94.272 -2.881 94.434 -2.833 94.544 -2.734 c
+94.662 -2.638 94.721 -2.51 94.721 -2.352 c
+97.058 1.573 m
+97.058 0.618 l
+97.661 0.618 l
+97.661 0.088 l
+97.058 0.088 l
+97.058 -2.381 l
+97.058 -2.539 97.08 -2.657 97.131 -2.734 c
+97.191 -2.815 97.278 -2.851 97.396 -2.851 c
+97.484 -2.851 97.573 -2.836 97.661 -2.807 c
+97.661 -3.366 l
+97.513 -3.414 97.359 -3.439 97.205 -3.439 c
+96.948 -3.439 96.753 -3.347 96.617 -3.16 c
+96.478 -2.976 96.412 -2.715 96.412 -2.381 c
+96.412 0.088 l
+95.809 0.088 l
+95.809 0.618 l
+96.412 0.618 l
+96.412 1.573 l
+h
+100.071 0 m
+99.983 0.019 99.884 0.03 99.778 0.03 c
+99.443 0.03 99.208 -0.154 99.072 -0.515 c
+99.072 -3.366 l
+98.425 -3.366 l
+98.425 0.618 l
+99.057 0.618 l
+99.072 0.206 l
+99.248 0.53 99.491 0.691 99.807 0.691 c
+99.913 0.691 100.002 0.669 100.071 0.632 c
+h
+102.07 -3.439 m
+101.571 -3.439 101.189 -3.293 100.923 -2.998 c
+100.659 -2.705 100.526 -2.271 100.526 -1.691 c
+100.526 -1.22 l
+100.526 -0.625 100.652 -0.158 100.909 0.177 c
+101.174 0.518 101.534 0.691 101.997 0.691 c
+102.456 0.691 102.798 0.537 103.026 0.235 c
+103.261 -0.058 103.383 -0.521 103.393 -1.146 c
+103.393 -1.573 l
+101.174 -1.573 l
+101.174 -1.66 l
+101.174 -2.094 101.251 -2.406 101.409 -2.601 c
+101.574 -2.789 101.806 -2.881 102.099 -2.881 c
+102.294 -2.881 102.467 -2.848 102.614 -2.778 c
+102.762 -2.701 102.897 -2.583 103.026 -2.425 c
+103.364 -2.836 l
+103.077 -3.241 102.647 -3.439 102.07 -3.439 c
+101.997 0.133 m
+101.721 0.133 101.519 0.037 101.394 -0.147 c
+101.266 -0.334 101.193 -0.625 101.174 -1.014 c
+102.747 -1.014 l
+102.747 -0.926 l
+102.724 -0.544 102.658 -0.276 102.541 -0.118 c
+102.423 0.048 102.24 0.133 101.997 0.133 c
+106.215 -3.366 m
+106.175 -3.278 106.149 -3.131 106.142 -2.925 c
+105.907 -3.27 105.613 -3.439 105.26 -3.439 c
+104.896 -3.439 104.613 -3.343 104.408 -3.145 c
+104.209 -2.94 104.114 -2.653 104.114 -2.278 c
+104.114 -1.878 104.25 -1.558 104.525 -1.323 c
+104.797 -1.08 105.172 -0.955 105.642 -0.955 c
+106.128 -0.955 l
+106.128 -0.529 l
+106.128 -0.294 106.072 -0.128 105.966 -0.029 c
+105.856 0.077 105.694 0.133 105.48 0.133 c
+105.282 0.133 105.12 0.073 104.995 -0.044 c
+104.878 -0.162 104.819 -0.309 104.819 -0.484 c
+104.173 -0.484 l
+104.173 -0.29 104.231 -0.099 104.349 0.088 c
+104.474 0.272 104.636 0.42 104.834 0.53 c
+105.039 0.636 105.268 0.691 105.525 0.691 c
+105.925 0.691 106.23 0.588 106.436 0.383 c
+106.649 0.177 106.763 -0.118 106.774 -0.5 c
+106.774 -2.514 l
+106.774 -2.818 106.811 -3.083 106.892 -3.307 c
+106.892 -3.366 l
+h
+105.349 -2.851 m
+105.513 -2.851 105.664 -2.807 105.804 -2.719 c
+105.951 -2.631 106.057 -2.52 106.128 -2.381 c
+106.128 -1.44 l
+105.76 -1.44 l
+105.444 -1.44 105.201 -1.51 105.025 -1.646 c
+104.848 -1.774 104.76 -1.962 104.76 -2.204 c
+104.76 -2.433 104.804 -2.597 104.892 -2.705 c
+104.981 -2.803 105.131 -2.851 105.349 -2.851 c
+108.391 0.618 m
+108.406 0.25 l
+108.648 0.544 108.968 0.691 109.361 0.691 c
+109.802 0.691 110.111 0.493 110.288 0.103 c
+110.541 0.493 110.89 0.691 111.331 0.691 c
+112.066 0.691 112.441 0.228 112.463 -0.69 c
+112.463 -3.366 l
+111.815 -3.366 l
+111.815 -0.75 l
+111.815 -0.455 111.761 -0.243 111.654 -0.103 c
+111.555 0.033 111.383 0.103 111.14 0.103 c
+110.941 0.103 110.78 0.023 110.654 -0.132 c
+110.537 -0.279 110.467 -0.47 110.448 -0.706 c
+110.448 -3.366 l
+109.787 -3.366 l
+109.787 -0.72 l
+109.787 -0.172 109.567 0.103 109.126 0.103 c
+108.792 0.103 108.557 -0.058 108.42 -0.382 c
+108.42 -3.366 l
+107.774 -3.366 l
+107.774 0.618 l
+h
+113.477 -3.013 m
+113.477 -2.896 113.51 -2.8 113.58 -2.719 c
+113.646 -2.642 113.749 -2.601 113.889 -2.601 c
+114.035 -2.601 114.142 -2.642 114.211 -2.719 c
+114.289 -2.8 114.329 -2.896 114.329 -3.013 c
+114.329 -3.123 114.289 -3.215 114.211 -3.293 c
+114.142 -3.37 114.035 -3.41 113.889 -3.41 c
+113.749 -3.41 113.646 -3.37 113.58 -3.293 c
+113.51 -3.215 113.477 -3.123 113.477 -3.013 c
+f
+Q
+0.793 0.801 0.129 0.016 k
+535.667 501.669 238.665 -21.46 re
+f
+0 0 0 0 k
+q 1 0 0 1 597.5209 489.2955 cm
+0 0 m
+-0.052 -1.069 -0.353 -1.878 -0.912 -2.425 c
+-1.463 -2.977 -2.234 -3.248 -3.234 -3.248 c
+-4.303 -3.248 -5.123 -2.903 -5.689 -2.204 c
+-6.247 -1.51 -6.527 -0.515 -6.527 0.779 c
+-6.527 2.352 l
+-6.527 3.645 -6.24 4.638 -5.659 5.336 c
+-5.071 6.03 -4.26 6.38 -3.219 6.38 c
+-2.201 6.38 -1.426 6.089 -0.896 5.513 c
+-0.368 4.943 -0.067 4.123 0.014 3.057 c
+-1.881 3.057 l
+-1.904 3.723 -2.007 4.179 -2.19 4.424 c
+-2.378 4.678 -2.72 4.807 -3.219 4.807 c
+-3.719 4.807 -4.079 4.63 -4.293 4.278 c
+-4.499 3.925 -4.612 3.341 -4.63 2.529 c
+-4.63 0.765 l
+-4.63 -0.168 -4.528 -0.808 -4.322 -1.161 c
+-4.108 -1.506 -3.745 -1.675 -3.234 -1.675 c
+-2.745 -1.675 -2.407 -1.558 -2.22 -1.323 c
+-2.025 -1.08 -1.918 -0.639 -1.896 0 c
+h
+1.433 -2.19 m
+1.433 -1.896 1.529 -1.657 1.727 -1.469 c
+1.922 -1.286 2.175 -1.19 2.491 -1.19 c
+2.792 -1.19 3.042 -1.286 3.241 -1.469 c
+3.447 -1.657 3.549 -1.896 3.549 -2.19 c
+3.549 -2.495 3.447 -2.741 3.241 -2.925 c
+3.042 -3.102 2.792 -3.189 2.491 -3.189 c
+2.186 -3.189 1.932 -3.098 1.727 -2.91 c
+1.529 -2.726 1.433 -2.484 1.433 -2.19 c
+14.115 4.675 m
+11.792 4.675 l
+11.792 -3.116 l
+9.896 -3.116 l
+9.896 4.675 l
+7.617 4.675 l
+7.617 6.247 l
+14.115 6.247 l
+h
+21.967 -3.116 m
+20.086 -3.116 l
+20.086 0.897 l
+17.294 0.897 l
+17.294 -3.116 l
+15.397 -3.116 l
+15.397 6.247 l
+17.294 6.247 l
+17.294 2.455 l
+20.086 2.455 l
+20.086 6.247 l
+21.967 6.247 l
+h
+28.542 0.941 m
+25.602 0.941 l
+25.602 -1.543 l
+29.086 -1.543 l
+29.086 -3.116 l
+23.706 -3.116 l
+23.706 6.247 l
+29.071 6.247 l
+29.071 4.675 l
+25.602 4.675 l
+25.602 2.455 l
+28.542 2.455 l
+h
+35.44 -1.543 m
+39.29 -1.543 l
+39.29 -3.116 l
+33.219 -3.116 l
+33.219 -1.984 l
+37.042 4.675 l
+33.19 4.675 l
+33.19 6.247 l
+39.217 6.247 l
+39.217 5.13 l
+h
+47.107 0.721 m
+47.107 -0.536 46.806 -1.51 46.21 -2.204 c
+45.611 -2.903 44.788 -3.248 43.741 -3.248 c
+42.69 -3.248 41.863 -2.907 41.256 -2.219 c
+40.657 -1.525 40.352 -0.558 40.345 0.676 c
+40.345 2.279 l
+40.345 3.561 40.643 4.564 41.242 5.292 c
+41.837 6.016 42.667 6.38 43.726 6.38 c
+44.762 6.38 45.582 6.02 46.181 5.307 c
+46.787 4.601 47.095 3.605 47.107 2.323 c
+h
+45.21 2.294 m
+45.21 3.135 45.086 3.763 44.843 4.175 c
+44.608 4.586 44.233 4.792 43.726 4.792 c
+43.226 4.792 42.852 4.59 42.609 4.189 c
+42.374 3.796 42.249 3.198 42.241 2.396 c
+42.241 0.721 l
+42.241 -0.095 42.362 -0.698 42.609 -1.087 c
+42.852 -1.481 43.23 -1.675 43.741 -1.675 c
+44.229 -1.675 44.593 -1.484 44.828 -1.103 c
+45.071 -0.72 45.2 -0.132 45.21 0.661 c
+h
+55.283 0.721 m
+55.283 -0.536 54.982 -1.51 54.386 -2.204 c
+53.788 -2.903 52.965 -3.248 51.917 -3.248 c
+50.866 -3.248 50.039 -2.907 49.433 -2.219 c
+48.834 -1.525 48.529 -0.558 48.521 0.676 c
+48.521 2.279 l
+48.521 3.561 48.819 4.564 49.418 5.292 c
+50.013 6.016 50.844 6.38 51.902 6.38 c
+52.938 6.38 53.758 6.02 54.357 5.307 c
+54.964 4.601 55.272 3.605 55.283 2.323 c
+h
+53.387 2.294 m
+53.387 3.135 53.262 3.763 53.019 4.175 c
+52.784 4.586 52.41 4.792 51.902 4.792 c
+51.402 4.792 51.028 4.59 50.785 4.189 c
+50.55 3.796 50.425 3.198 50.418 2.396 c
+50.418 0.721 l
+50.418 -0.095 50.538 -0.698 50.785 -1.087 c
+51.028 -1.481 51.406 -1.675 51.917 -1.675 c
+52.406 -1.675 52.77 -1.484 53.005 -1.103 c
+53.247 -0.72 53.376 -0.132 53.387 0.661 c
+h
+66.579 0.721 m
+66.579 -0.536 66.278 -1.51 65.682 -2.204 c
+65.083 -2.903 64.26 -3.248 63.213 -3.248 c
+62.162 -3.248 61.335 -2.907 60.729 -2.219 c
+60.13 -1.525 59.825 -0.558 59.818 0.676 c
+59.818 2.279 l
+59.818 3.561 60.115 4.564 60.714 5.292 c
+61.31 6.016 62.14 6.38 63.198 6.38 c
+64.235 6.38 65.054 6.02 65.653 5.307 c
+66.259 4.601 66.568 3.605 66.579 2.323 c
+h
+64.683 2.294 m
+64.683 3.135 64.558 3.763 64.316 4.175 c
+64.08 4.586 63.705 4.792 63.198 4.792 c
+62.698 4.792 62.324 4.59 62.081 4.189 c
+61.846 3.796 61.721 3.198 61.714 2.396 c
+61.714 0.721 l
+61.714 -0.095 61.835 -0.698 62.081 -1.087 c
+62.324 -1.481 62.702 -1.675 63.213 -1.675 c
+63.702 -1.675 64.065 -1.484 64.301 -1.103 c
+64.543 -0.72 64.672 -0.132 64.683 0.661 c
+h
+72.992 0.706 m
+70.052 0.706 l
+70.052 -3.116 l
+68.156 -3.116 l
+68.156 6.247 l
+73.345 6.247 l
+73.345 4.675 l
+70.052 4.675 l
+70.052 2.279 l
+72.992 2.279 l
+h
+83.817 0.368 m
+84.7 6.247 l
+86.581 6.247 l
+84.906 -3.116 l
+83.009 -3.116 l
+81.922 2.396 l
+80.848 -3.116 l
+78.938 -3.116 l
+77.262 6.247 l
+79.143 6.247 l
+80.025 0.368 l
+81.128 6.247 l
+82.716 6.247 l
+h
+94.493 0.721 m
+94.493 -0.536 94.192 -1.51 93.596 -2.204 c
+92.997 -2.903 92.174 -3.248 91.127 -3.248 c
+90.076 -3.248 89.249 -2.907 88.642 -2.219 c
+88.044 -1.525 87.738 -0.558 87.732 0.676 c
+87.732 2.279 l
+87.732 3.561 88.029 4.564 88.628 5.292 c
+89.224 6.016 90.053 6.38 91.112 6.38 c
+92.148 6.38 92.968 6.02 93.567 5.307 c
+94.173 4.601 94.481 3.605 94.493 2.323 c
+h
+92.596 2.294 m
+92.596 3.135 92.472 3.763 92.229 4.175 c
+91.994 4.586 91.619 4.792 91.112 4.792 c
+90.612 4.792 90.238 4.59 89.995 4.189 c
+89.76 3.796 89.635 3.198 89.627 2.396 c
+89.627 0.721 l
+89.627 -0.095 89.748 -0.698 89.995 -1.087 c
+90.238 -1.481 90.616 -1.675 91.127 -1.675 c
+91.615 -1.675 91.979 -1.484 92.214 -1.103 c
+92.457 -0.72 92.586 -0.132 92.596 0.661 c
+h
+98.906 0.309 m
+97.965 0.309 l
+97.965 -3.116 l
+96.083 -3.116 l
+96.083 6.247 l
+99.098 6.247 l
+100.045 6.247 100.777 6.001 101.288 5.513 c
+101.805 5.02 102.067 4.326 102.067 3.425 c
+102.067 2.18 101.614 1.309 100.714 0.809 c
+102.346 -3.027 l
+102.346 -3.116 l
+100.317 -3.116 l
+h
+97.965 1.881 m
+99.038 1.881 l
+99.42 1.881 99.703 2.003 99.891 2.249 c
+100.075 2.502 100.17 2.841 100.17 3.263 c
+100.17 4.204 99.807 4.675 99.083 4.675 c
+97.965 4.675 l
+h
+106.23 0.5 m
+105.48 -0.44 l
+105.48 -3.116 l
+103.584 -3.116 l
+103.584 6.247 l
+105.48 6.247 l
+105.48 2.161 l
+106.083 3.175 l
+107.817 6.247 l
+110.14 6.247 l
+107.449 2.132 l
+110.184 -3.116 l
+107.935 -3.116 l
+h
+113.054 -3.116 -1.896 9.363 re
+121.304 -3.116 m
+119.407 -3.116 l
+116.644 3.028 l
+116.644 -3.116 l
+114.748 -3.116 l
+114.748 6.247 l
+116.644 6.247 l
+119.407 0.103 l
+119.407 6.247 l
+121.304 6.247 l
+h
+129.421 -2.057 m
+129.057 -2.451 128.613 -2.749 128.084 -2.954 c
+127.555 -3.149 126.974 -3.248 126.349 -3.248 c
+125.269 -3.248 124.431 -2.917 123.835 -2.248 c
+123.237 -1.583 122.932 -0.613 122.925 0.661 c
+122.925 2.352 l
+122.925 3.645 123.204 4.638 123.762 5.336 c
+124.328 6.03 125.151 6.38 126.231 6.38 c
+127.249 6.38 128.014 6.122 128.525 5.615 c
+129.043 5.116 129.34 4.329 129.421 3.263 c
+127.584 3.263 l
+127.532 3.859 127.411 4.266 127.216 4.484 c
+127.018 4.696 126.709 4.807 126.291 4.807 c
+125.78 4.807 125.408 4.619 125.173 4.248 c
+124.945 3.873 124.828 3.282 124.82 2.469 c
+124.82 0.765 l
+124.82 -0.087 124.945 -0.713 125.203 -1.103 c
+125.456 -1.484 125.872 -1.675 126.452 -1.675 c
+126.823 -1.675 127.128 -1.602 127.363 -1.455 c
+127.525 -1.338 l
+127.525 0.383 l
+126.202 0.383 l
+126.202 1.808 l
+129.421 1.808 l
+h
+138.586 -1.205 m
+136.014 -1.205 l
+135.515 -3.116 l
+133.515 -3.116 l
+136.44 6.247 l
+138.16 6.247 l
+141.115 -3.116 l
+139.086 -3.116 l
+h
+136.425 0.383 m
+138.175 0.383 l
+137.292 3.719 l
+h
+145.05 0.309 m
+144.109 0.309 l
+144.109 -3.116 l
+142.228 -3.116 l
+142.228 6.247 l
+145.241 6.247 l
+146.189 6.247 146.921 6.001 147.431 5.513 c
+147.949 5.02 148.211 4.326 148.211 3.425 c
+148.211 2.18 147.758 1.309 146.858 0.809 c
+148.49 -3.027 l
+148.49 -3.116 l
+146.461 -3.116 l
+h
+144.109 1.881 m
+145.182 1.881 l
+145.564 1.881 145.848 2.003 146.035 2.249 c
+146.218 2.502 146.314 2.841 146.314 3.263 c
+146.314 4.204 145.95 4.675 145.227 4.675 c
+144.109 4.675 l
+h
+154.564 0.941 m
+151.625 0.941 l
+151.625 -1.543 l
+155.108 -1.543 l
+155.108 -3.116 l
+149.728 -3.116 l
+149.728 6.247 l
+155.093 6.247 l
+155.093 4.675 l
+151.625 4.675 l
+151.625 2.455 l
+154.564 2.455 l
+h
+160.836 -1.205 m
+158.264 -1.205 l
+157.765 -3.116 l
+155.766 -3.116 l
+158.691 6.247 l
+160.41 6.247 l
+163.365 -3.116 l
+161.337 -3.116 l
+h
+158.676 0.383 m
+160.425 0.383 l
+159.544 3.719 l
+h
+168.418 -0.661 m
+168.418 -0.279 168.319 0.008 168.124 0.206 c
+167.926 0.401 167.573 0.603 167.066 0.809 c
+166.125 1.168 165.449 1.588 165.037 2.058 c
+164.626 2.536 164.42 3.105 164.42 3.763 c
+164.42 4.546 164.699 5.178 165.258 5.66 c
+165.816 6.137 166.525 6.38 167.389 6.38 c
+167.966 6.38 168.481 6.255 168.932 6.012 c
+169.381 5.766 169.726 5.424 169.962 4.983 c
+170.204 4.542 170.328 4.042 170.328 3.484 c
+168.447 3.484 l
+168.447 3.925 168.352 4.256 168.168 4.484 c
+167.98 4.707 167.712 4.821 167.359 4.821 c
+167.025 4.821 166.764 4.723 166.581 4.528 c
+166.404 4.341 166.316 4.079 166.316 3.749 c
+166.316 3.491 166.419 3.256 166.625 3.043 c
+166.831 2.837 167.19 2.62 167.712 2.396 c
+168.624 2.072 169.285 1.669 169.696 1.191 c
+170.116 0.709 170.328 0.096 170.328 -0.646 c
+170.328 -1.462 170.068 -2.098 169.549 -2.557 c
+169.028 -3.021 168.323 -3.248 167.433 -3.248 c
+166.823 -3.248 166.272 -3.123 165.772 -2.881 c
+165.279 -2.627 164.894 -2.271 164.611 -1.808 c
+164.325 -1.338 164.184 -0.79 164.184 -0.162 c
+166.081 -0.162 l
+166.081 -0.702 166.183 -1.095 166.39 -1.338 c
+166.602 -1.583 166.951 -1.705 167.433 -1.705 c
+168.088 -1.705 168.418 -1.359 168.418 -0.661 c
+f
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+/GS2 gs
+0 TL/Fm1 Do
+Q
+q 1 0 0 1 597.8069 284.3244 cm
+0 0 m
+0 0.107 -0.055 0.206 -0.161 0.294 c
+-0.272 0.39 -0.507 0.518 -0.866 0.676 c
+-1.407 0.89 -1.774 1.118 -1.969 1.353 c
+-2.167 1.588 -2.263 1.875 -2.263 2.22 c
+-2.263 2.661 -2.109 3.018 -1.793 3.293 c
+-1.481 3.576 -1.069 3.72 -0.558 3.72 c
+-0.01 3.72 0.427 3.576 0.75 3.293 c
+1.081 3.018 1.25 2.639 1.25 2.161 c
+-0.058 2.161 l
+-0.058 2.573 -0.228 2.779 -0.558 2.779 c
+-0.698 2.779 -0.808 2.735 -0.896 2.646 c
+-0.984 2.558 -1.028 2.44 -1.028 2.294 c
+-1.028 2.176 -0.981 2.073 -0.881 1.985 c
+-0.786 1.904 -0.554 1.786 -0.191 1.632 c
+0.339 1.434 0.709 1.214 0.927 0.971 c
+1.151 0.736 1.264 0.427 1.264 0.044 c
+1.264 -0.396 1.095 -0.756 0.765 -1.028 c
+0.43 -1.294 -0.01 -1.425 -0.558 -1.425 c
+-0.922 -1.425 -1.246 -1.356 -1.529 -1.219 c
+-1.804 -1.072 -2.021 -0.874 -2.175 -0.617 c
+-2.333 -0.363 -2.41 -0.087 -2.41 0.206 c
+-1.176 0.206 l
+-1.168 -0.022 -1.113 -0.191 -1.014 -0.309 c
+-0.918 -0.426 -0.756 -0.484 -0.529 -0.484 c
+-0.176 -0.484 0 -0.323 0 0 c
+3.421 4.851 m
+3.421 3.631 l
+4.083 3.631 l
+4.083 2.661 l
+3.421 2.661 l
+3.421 0.192 l
+3.421 -0.007 3.444 -0.143 3.495 -0.22 c
+3.554 -0.29 3.66 -0.323 3.818 -0.323 c
+3.936 -0.323 4.039 -0.315 4.127 -0.293 c
+4.113 -1.308 l
+3.884 -1.385 3.645 -1.425 3.392 -1.425 c
+2.558 -1.425 2.135 -0.947 2.128 0.015 c
+2.128 2.661 l
+1.555 2.661 l
+1.555 3.631 l
+2.128 3.631 l
+2.128 4.851 l
+h
+7.041 -1.337 m
+7.001 -1.26 6.961 -1.132 6.924 -0.955 c
+6.696 -1.271 6.384 -1.425 5.983 -1.425 c
+5.561 -1.425 5.212 -1.29 4.939 -1.014 c
+4.675 -0.742 4.543 -0.382 4.543 0.059 c
+4.543 0.578 4.704 0.978 5.027 1.264 c
+5.358 1.548 5.839 1.694 6.468 1.706 c
+6.865 1.706 l
+6.865 2.103 l
+6.865 2.326 6.824 2.484 6.747 2.573 c
+6.666 2.661 6.556 2.705 6.409 2.705 c
+6.086 2.705 5.924 2.517 5.924 2.147 c
+4.63 2.147 l
+4.63 2.595 4.8 2.97 5.145 3.263 c
+5.486 3.565 5.924 3.72 6.453 3.72 c
+6.99 3.72 7.408 3.576 7.703 3.293 c
+8.004 3.018 8.158 2.617 8.158 2.087 c
+8.158 -0.249 l
+8.166 -0.683 8.232 -1.021 8.349 -1.263 c
+8.349 -1.337 l
+h
+6.277 -0.411 m
+6.413 -0.411 6.531 -0.382 6.629 -0.323 c
+6.737 -0.264 6.814 -0.198 6.865 -0.118 c
+6.865 0.912 l
+6.556 0.912 l
+6.328 0.912 6.152 0.842 6.027 0.706 c
+5.898 0.566 5.836 0.383 5.836 0.148 c
+5.836 -0.228 5.983 -0.411 6.277 -0.411 c
+11.131 0 m
+11.131 0.107 11.076 0.206 10.97 0.294 c
+10.859 0.39 10.624 0.518 10.264 0.676 c
+9.724 0.89 9.357 1.118 9.162 1.353 c
+8.963 1.588 8.867 1.875 8.867 2.22 c
+8.867 2.661 9.022 3.018 9.338 3.293 c
+9.65 3.576 10.062 3.72 10.573 3.72 c
+11.12 3.72 11.558 3.576 11.881 3.293 c
+12.212 3.018 12.381 2.639 12.381 2.161 c
+11.073 2.161 l
+11.073 2.573 10.903 2.779 10.573 2.779 c
+10.433 2.779 10.323 2.735 10.234 2.646 c
+10.147 2.558 10.103 2.44 10.103 2.294 c
+10.103 2.176 10.151 2.073 10.249 1.985 c
+10.345 1.904 10.577 1.786 10.94 1.632 c
+11.47 1.434 11.84 1.214 12.057 0.971 c
+12.281 0.736 12.395 0.427 12.395 0.044 c
+12.395 -0.396 12.227 -0.756 11.896 -1.028 c
+11.562 -1.294 11.12 -1.425 10.573 -1.425 c
+10.209 -1.425 9.885 -1.356 9.602 -1.219 c
+9.326 -1.072 9.11 -0.874 8.956 -0.617 c
+8.798 -0.363 8.721 -0.087 8.721 0.206 c
+9.955 0.206 l
+9.962 -0.022 10.018 -0.191 10.117 -0.309 c
+10.213 -0.426 10.375 -0.484 10.602 -0.484 c
+10.955 -0.484 11.131 -0.323 11.131 0 c
+14.299 3.19 m
+14.581 3.543 14.931 3.72 15.342 3.72 c
+15.791 3.72 16.137 3.558 16.372 3.234 c
+16.607 2.918 16.728 2.448 16.739 1.823 c
+16.739 -1.337 l
+15.431 -1.337 l
+15.431 1.808 l
+15.431 2.103 15.387 2.312 15.298 2.44 c
+15.21 2.565 15.063 2.631 14.857 2.631 c
+14.622 2.631 14.435 2.521 14.299 2.309 c
+14.299 -1.337 l
+13.006 -1.337 l
+13.006 5.719 l
+14.299 5.719 l
+h
+f
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 708.0578 323.0349 cm
+0 0 m
+47.933 0 l
+50.538 0 52.637 -2.099 52.637 -4.704 c
+52.637 -19.264 l
+52.637 -21.868 50.538 -23.963 47.933 -23.963 c
+0 -23.963 l
+-2.606 -23.963 -4.7 -21.868 -4.7 -19.264 c
+-4.7 -4.704 l
+-4.7 -2.099 -2.606 0 0 0 c
+f
+Q
+0 0 0 0 k
+723.657 314.105 -1.309 4.968 re
+722.29 320.367 m
+722.29 320.562 722.352 320.723 722.481 320.852 c
+722.606 320.988 722.779 321.057 722.996 321.057 c
+723.208 321.057 723.381 320.988 723.51 320.852 c
+723.635 320.723 723.701 320.562 723.701 320.367 c
+723.701 320.161 723.635 319.989 723.51 319.852 c
+723.393 319.723 723.22 319.661 722.996 319.661 c
+722.779 319.661 722.606 319.723 722.481 319.852 c
+722.352 319.989 722.29 320.161 722.29 320.367 c
+725.759 319.073 m
+725.803 318.588 l
+726.097 318.971 726.479 319.162 726.95 319.162 c
+727.802 319.162 728.243 318.563 728.272 317.368 c
+728.272 314.105 l
+726.964 314.105 l
+726.964 317.28 l
+726.964 317.552 726.921 317.754 726.832 317.882 c
+726.751 318.008 726.604 318.073 726.391 318.073 c
+726.156 318.073 725.972 317.956 725.847 317.721 c
+725.847 314.105 l
+724.539 314.105 l
+724.539 319.073 l
+h
+728.835 316.737 m
+728.835 317.56 728.97 318.166 729.246 318.559 c
+729.529 318.96 729.93 319.162 730.451 319.162 c
+730.834 319.162 731.15 319 731.407 318.676 c
+731.407 321.161 l
+732.716 321.161 l
+732.716 314.105 l
+731.54 314.105 l
+731.48 314.605 l
+731.216 314.212 730.871 314.017 730.451 314.017 c
+729.93 314.017 729.533 314.212 729.261 314.605 c
+728.985 315.006 728.842 315.594 728.835 316.369 c
+h
+730.143 316.413 m
+730.143 315.92 730.191 315.579 730.29 315.384 c
+730.397 315.197 730.576 315.104 730.834 315.104 c
+731.087 315.104 731.278 315.214 731.407 315.443 c
+731.407 317.707 l
+731.278 317.949 731.087 318.073 730.834 318.073 c
+730.599 318.073 730.422 317.975 730.304 317.78 c
+730.194 317.593 730.143 317.254 730.143 316.766 c
+h
+735.505 314.017 m
+734.836 314.017 734.314 314.212 733.932 314.605 c
+733.557 315.006 733.373 315.579 733.373 316.325 c
+733.373 316.722 l
+733.373 317.504 733.542 318.107 733.888 318.53 c
+734.229 318.948 734.725 319.162 735.372 319.162 c
+735.989 319.162 736.452 318.96 736.768 318.559 c
+737.092 318.166 737.254 317.578 737.254 316.795 c
+737.254 316.149 l
+734.682 316.149 l
+734.688 315.785 734.769 315.516 734.917 315.34 c
+735.064 315.171 735.284 315.09 735.578 315.09 c
+736.018 315.09 736.379 315.241 736.666 315.546 c
+737.18 314.752 l
+737.022 314.535 736.791 314.358 736.489 314.223 c
+736.184 314.087 735.858 314.017 735.505 314.017 c
+734.682 317.059 m
+735.989 317.059 l
+735.989 317.177 l
+735.978 317.479 735.923 317.707 735.827 317.853 c
+735.74 318.008 735.582 318.088 735.357 318.088 c
+735.129 318.088 734.964 318.004 734.858 317.838 c
+734.759 317.681 734.7 317.42 734.682 317.059 c
+739.473 317.603 m
+740.061 319.073 l
+741.428 319.073 l
+740.296 316.648 l
+741.472 314.105 l
+740.091 314.105 l
+739.488 315.663 l
+738.871 314.105 l
+737.489 314.105 l
+738.665 316.648 l
+737.533 319.073 l
+738.929 319.073 l
+h
+f
+q 1 0 0 1 706.8743 306.8918 cm
+0 0 m
+0 0.683 0.077 1.341 0.235 1.97 c
+0.389 2.605 0.632 3.167 0.956 3.659 c
+1.279 4.16 1.621 4.505 1.984 4.704 c
+2.219 3.983 l
+1.874 3.659 1.602 3.16 1.396 2.484 c
+1.198 1.815 1.095 1.043 1.088 0.162 c
+1.088 -0.118 l
+1.088 -1.04 1.183 -1.849 1.382 -2.543 c
+1.587 -3.238 1.866 -3.755 2.219 -4.102 c
+1.984 -4.807 l
+1.621 -4.619 1.279 -4.281 0.956 -3.792 c
+0.64 -3.3 0.401 -2.749 0.235 -2.132 c
+0.077 -1.515 0 -0.867 0 -0.191 c
+h
+5.045 -1.382 m
+5.045 -1.276 4.991 -1.176 4.883 -1.088 c
+4.773 -0.992 4.538 -0.864 4.178 -0.706 c
+3.638 -0.493 3.27 -0.264 3.075 -0.029 c
+2.878 0.206 2.782 0.492 2.782 0.837 c
+2.782 1.278 2.936 1.635 3.252 1.911 c
+3.564 2.194 3.976 2.337 4.486 2.337 c
+5.035 2.337 5.471 2.194 5.795 1.911 c
+6.126 1.635 6.294 1.257 6.294 0.779 c
+4.987 0.779 l
+4.987 1.19 4.818 1.396 4.486 1.396 c
+4.347 1.396 4.237 1.352 4.149 1.264 c
+4.06 1.176 4.016 1.058 4.016 0.912 c
+4.016 0.794 4.064 0.69 4.164 0.602 c
+4.259 0.521 4.49 0.404 4.854 0.249 c
+5.384 0.051 5.755 -0.169 5.972 -0.412 c
+6.196 -0.647 6.31 -0.956 6.31 -1.338 c
+6.31 -1.779 6.14 -2.139 5.81 -2.411 c
+5.475 -2.675 5.035 -2.808 4.486 -2.808 c
+4.123 -2.808 3.8 -2.738 3.516 -2.602 c
+3.241 -2.455 3.024 -2.257 2.87 -1.999 c
+2.712 -1.746 2.635 -1.47 2.635 -1.176 c
+3.869 -1.176 l
+3.877 -1.404 3.932 -1.573 4.031 -1.691 c
+4.127 -1.808 4.289 -1.867 4.517 -1.867 c
+4.869 -1.867 5.045 -1.706 5.045 -1.382 c
+8.463 3.468 m
+8.463 2.248 l
+9.124 2.248 l
+9.124 1.278 l
+8.463 1.278 l
+8.463 -1.191 l
+8.463 -1.389 8.484 -1.525 8.536 -1.602 c
+8.596 -1.673 8.702 -1.706 8.86 -1.706 c
+8.977 -1.706 9.08 -1.698 9.168 -1.675 c
+9.153 -2.691 l
+8.926 -2.768 8.687 -2.808 8.434 -2.808 c
+7.599 -2.808 7.177 -2.33 7.169 -1.367 c
+7.169 1.278 l
+6.596 1.278 l
+6.596 2.248 l
+7.169 2.248 l
+7.169 3.468 l
+h
+12.087 -2.72 m
+12.046 -2.643 12.006 -2.514 11.969 -2.338 c
+11.74 -2.654 11.428 -2.808 11.028 -2.808 c
+10.605 -2.808 10.256 -2.672 9.984 -2.396 c
+9.72 -2.124 9.587 -1.764 9.587 -1.323 c
+9.587 -0.805 9.749 -0.405 10.073 -0.118 c
+10.404 0.166 10.884 0.312 11.513 0.324 c
+11.91 0.324 l
+11.91 0.72 l
+11.91 0.944 11.869 1.103 11.792 1.19 c
+11.711 1.278 11.601 1.323 11.454 1.323 c
+11.131 1.323 10.969 1.135 10.969 0.764 c
+9.675 0.764 l
+9.675 1.213 9.845 1.587 10.19 1.881 c
+10.532 2.182 10.969 2.337 11.499 2.337 c
+12.035 2.337 12.453 2.194 12.748 1.911 c
+13.049 1.635 13.203 1.234 13.203 0.706 c
+13.203 -1.632 l
+13.211 -2.066 13.277 -2.404 13.394 -2.646 c
+13.394 -2.72 l
+h
+11.322 -1.793 m
+11.458 -1.793 11.576 -1.764 11.675 -1.706 c
+11.781 -1.646 11.858 -1.58 11.91 -1.5 c
+11.91 -0.47 l
+11.601 -0.47 l
+11.374 -0.47 11.197 -0.54 11.072 -0.676 c
+10.944 -0.816 10.881 -1 10.881 -1.235 c
+10.881 -1.61 11.028 -1.793 11.322 -1.793 c
+13.824 -0.088 m
+13.824 0.735 13.972 1.341 14.265 1.735 c
+14.559 2.135 14.971 2.337 15.5 2.337 c
+15.948 2.337 16.297 2.161 16.544 1.808 c
+16.588 2.248 l
+17.764 2.248 l
+17.764 -2.72 l
+17.764 -3.356 17.58 -3.84 17.22 -4.175 c
+16.867 -4.505 16.357 -4.675 15.692 -4.675 c
+15.426 -4.675 15.14 -4.619 14.838 -4.513 c
+14.533 -4.403 14.31 -4.266 14.163 -4.102 c
+14.603 -3.204 l
+14.728 -3.329 14.89 -3.433 15.089 -3.514 c
+15.283 -3.591 15.463 -3.631 15.632 -3.631 c
+15.927 -3.631 16.136 -3.561 16.264 -3.425 c
+16.39 -3.285 16.455 -3.061 16.455 -2.749 c
+16.455 -2.323 l
+16.209 -2.646 15.886 -2.808 15.486 -2.808 c
+14.956 -2.808 14.545 -2.602 14.25 -2.19 c
+13.964 -1.779 13.824 -1.202 13.824 -0.456 c
+h
+15.118 -0.412 m
+15.118 -0.875 15.177 -1.205 15.295 -1.411 c
+15.412 -1.617 15.603 -1.72 15.867 -1.72 c
+16.132 -1.72 16.327 -1.628 16.455 -1.44 c
+16.455 0.941 l
+16.327 1.147 16.136 1.249 15.883 1.249 c
+15.618 1.249 15.42 1.139 15.295 0.926 c
+15.177 0.72 15.118 0.382 15.118 -0.088 c
+h
+19.888 -2.72 -1.309 4.968 re
+18.52 3.542 m
+18.52 3.737 18.583 3.898 18.712 4.027 c
+18.836 4.164 19.01 4.233 19.226 4.233 c
+19.439 4.233 19.613 4.164 19.74 4.027 c
+19.866 3.898 19.931 3.737 19.931 3.542 c
+19.931 3.337 19.866 3.164 19.74 3.028 c
+19.623 2.899 19.451 2.836 19.226 2.836 c
+19.01 2.836 18.836 2.899 18.712 3.028 c
+18.583 3.164 18.52 3.337 18.52 3.542 c
+21.986 2.248 m
+22.03 1.764 l
+22.324 2.146 22.707 2.337 23.177 2.337 c
+24.029 2.337 24.471 1.738 24.5 0.544 c
+24.5 -2.72 l
+23.191 -2.72 l
+23.191 0.455 l
+23.191 0.727 23.147 0.929 23.059 1.058 c
+22.979 1.183 22.831 1.249 22.618 1.249 c
+22.383 1.249 22.2 1.132 22.074 0.897 c
+22.074 -2.72 l
+20.766 -2.72 l
+20.766 2.248 l
+h
+25.095 -0.088 m
+25.095 0.735 25.242 1.341 25.535 1.735 c
+25.83 2.135 26.241 2.337 26.771 2.337 c
+27.219 2.337 27.568 2.161 27.814 1.808 c
+27.858 2.248 l
+29.034 2.248 l
+29.034 -2.72 l
+29.034 -3.356 28.851 -3.84 28.49 -4.175 c
+28.138 -4.505 27.627 -4.675 26.962 -4.675 c
+26.697 -4.675 26.41 -4.619 26.109 -4.513 c
+25.805 -4.403 25.58 -4.266 25.433 -4.102 c
+25.874 -3.204 l
+25.999 -3.329 26.161 -3.433 26.359 -3.514 c
+26.553 -3.591 26.734 -3.631 26.903 -3.631 c
+27.197 -3.631 27.407 -3.561 27.534 -3.425 c
+27.66 -3.285 27.726 -3.061 27.726 -2.749 c
+27.726 -2.323 l
+27.48 -2.646 27.156 -2.808 26.756 -2.808 c
+26.227 -2.808 25.815 -2.602 25.521 -2.19 c
+25.234 -1.779 25.095 -1.202 25.095 -0.456 c
+h
+26.389 -0.412 m
+26.389 -0.875 26.447 -1.205 26.565 -1.411 c
+26.682 -1.617 26.873 -1.72 27.138 -1.72 c
+27.403 -1.72 27.598 -1.628 27.726 -1.44 c
+27.726 0.941 l
+27.598 1.147 27.407 1.249 27.153 1.249 c
+26.888 1.249 26.69 1.139 26.565 0.926 c
+26.447 0.72 26.389 0.382 26.389 -0.088 c
+h
+34.241 -2.72 m
+34.201 -2.643 34.16 -2.514 34.123 -2.338 c
+33.896 -2.654 33.583 -2.808 33.183 -2.808 c
+32.76 -2.808 32.411 -2.672 32.139 -2.396 c
+31.875 -2.124 31.742 -1.764 31.742 -1.323 c
+31.742 -0.805 31.904 -0.405 32.228 -0.118 c
+32.558 0.166 33.04 0.312 33.668 0.324 c
+34.065 0.324 l
+34.065 0.72 l
+34.065 0.944 34.025 1.103 33.948 1.19 c
+33.867 1.278 33.757 1.323 33.609 1.323 c
+33.286 1.323 33.124 1.135 33.124 0.764 c
+31.831 0.764 l
+31.831 1.213 32 1.587 32.345 1.881 c
+32.687 2.182 33.124 2.337 33.653 2.337 c
+34.19 2.337 34.609 2.194 34.903 1.911 c
+35.204 1.635 35.359 1.234 35.359 0.706 c
+35.359 -1.632 l
+35.366 -2.066 35.432 -2.404 35.55 -2.646 c
+35.55 -2.72 l
+h
+33.477 -1.793 m
+33.613 -1.793 33.73 -1.764 33.83 -1.706 c
+33.936 -1.646 34.013 -1.58 34.065 -1.5 c
+34.065 -0.47 l
+33.757 -0.47 l
+33.529 -0.47 33.352 -0.54 33.227 -0.676 c
+33.099 -0.816 33.036 -1 33.036 -1.235 c
+33.036 -1.61 33.183 -1.793 33.477 -1.793 c
+38.582 0.999 m
+38.155 1.029 l
+37.791 1.029 37.552 0.871 37.435 0.559 c
+37.435 -2.72 l
+36.126 -2.72 l
+36.126 2.248 l
+37.346 2.248 l
+37.391 1.72 l
+37.597 2.131 37.88 2.337 38.243 2.337 c
+38.391 2.337 38.508 2.315 38.596 2.278 c
+h
+41.051 -2.808 m
+40.382 -2.808 39.86 -2.613 39.478 -2.22 c
+39.103 -1.819 38.919 -1.246 38.919 -0.5 c
+38.919 -0.104 l
+38.919 0.679 39.089 1.282 39.434 1.705 c
+39.775 2.124 40.272 2.337 40.918 2.337 c
+41.536 2.337 41.998 2.135 42.314 1.735 c
+42.638 1.341 42.8 0.754 42.8 -0.029 c
+42.8 -0.676 l
+40.228 -0.676 l
+40.234 -1.04 40.315 -1.309 40.463 -1.484 c
+40.61 -1.654 40.83 -1.735 41.124 -1.735 c
+41.566 -1.735 41.925 -1.584 42.212 -1.279 c
+42.727 -2.072 l
+42.568 -2.29 42.337 -2.466 42.036 -2.602 c
+41.73 -2.738 41.404 -2.808 41.051 -2.808 c
+40.228 0.235 m
+41.536 0.235 l
+41.536 0.353 l
+41.525 0.654 41.47 0.881 41.374 1.029 c
+41.286 1.183 41.128 1.264 40.903 1.264 c
+40.676 1.264 40.51 1.18 40.404 1.014 c
+40.305 0.856 40.246 0.595 40.228 0.235 c
+45.725 -2.72 m
+45.684 -2.643 45.644 -2.514 45.607 -2.338 c
+45.379 -2.654 45.067 -2.808 44.666 -2.808 c
+44.244 -2.808 43.895 -2.672 43.623 -2.396 c
+43.359 -2.124 43.226 -1.764 43.226 -1.323 c
+43.226 -0.805 43.388 -0.405 43.711 -0.118 c
+44.042 0.166 44.523 0.312 45.152 0.324 c
+45.549 0.324 l
+45.549 0.72 l
+45.549 0.944 45.508 1.103 45.431 1.19 c
+45.35 1.278 45.24 1.323 45.093 1.323 c
+44.77 1.323 44.608 1.135 44.608 0.764 c
+43.315 0.764 l
+43.315 1.213 43.484 1.587 43.829 1.881 c
+44.171 2.182 44.608 2.337 45.137 2.337 c
+45.674 2.337 46.092 2.194 46.387 1.911 c
+46.688 1.635 46.842 1.234 46.842 0.706 c
+46.842 -1.632 l
+46.85 -2.066 46.916 -2.404 47.033 -2.646 c
+47.033 -2.72 l
+h
+44.961 -1.793 m
+45.096 -1.793 45.214 -1.764 45.314 -1.706 c
+45.42 -1.646 45.497 -1.58 45.549 -1.5 c
+45.549 -0.47 l
+45.24 -0.47 l
+45.013 -0.47 44.836 -0.54 44.711 -0.676 c
+44.583 -0.816 44.52 -1 44.52 -1.235 c
+44.52 -1.61 44.666 -1.793 44.961 -1.793 c
+49.694 -0.104 m
+49.694 -0.819 49.599 -1.496 49.414 -2.132 c
+49.238 -2.768 48.988 -3.326 48.664 -3.807 c
+48.342 -4.285 47.996 -4.619 47.636 -4.807 c
+47.401 -4.102 l
+47.743 -3.767 48.011 -3.256 48.209 -2.573 c
+48.415 -1.889 48.521 -1.11 48.533 -0.235 c
+48.533 0.014 l
+48.533 0.904 48.429 1.697 48.224 2.396 c
+48.026 3.102 47.754 3.634 47.401 3.998 c
+47.636 4.704 l
+47.871 4.586 48.11 4.384 48.356 4.101 c
+48.599 3.825 48.819 3.484 49.017 3.071 c
+49.223 2.66 49.385 2.194 49.503 1.675 c
+49.628 1.165 49.694 0.573 49.694 -0.104 c
+f
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 646.1816 351.8337 cm
+0 0 m
+38.148 0 l
+40.754 0 42.852 -2.098 42.852 -4.704 c
+42.852 -10.231 l
+42.852 -12.835 40.754 -14.934 38.148 -14.934 c
+0 -14.934 l
+-2.605 -14.934 -4.704 -12.835 -4.704 -10.231 c
+-4.704 -4.704 l
+-4.704 -2.098 -2.605 0 0 0 c
+f
+Q
+0 0 0 0 k
+q 1 0 0 1 649.541 345.8732 cm
+0 0 m
+-0.426 0.03 l
+-0.79 0.03 -1.029 -0.128 -1.147 -0.44 c
+-1.147 -3.719 l
+-2.455 -3.719 l
+-2.455 1.249 l
+-1.235 1.249 l
+-1.191 0.721 l
+-0.985 1.132 -0.702 1.338 -0.339 1.338 c
+-0.191 1.338 -0.074 1.316 0.014 1.279 c
+h
+2.469 -3.807 m
+1.801 -3.807 1.279 -3.612 0.897 -3.219 c
+0.521 -2.818 0.338 -2.245 0.338 -1.499 c
+0.338 -1.103 l
+0.338 -0.32 0.507 0.283 0.852 0.706 c
+1.194 1.125 1.69 1.338 2.337 1.338 c
+2.954 1.338 3.417 1.135 3.733 0.736 c
+4.056 0.342 4.218 -0.246 4.218 -1.028 c
+4.218 -1.675 l
+1.646 -1.675 l
+1.653 -2.04 1.734 -2.308 1.881 -2.484 c
+2.028 -2.653 2.248 -2.734 2.543 -2.734 c
+2.983 -2.734 3.343 -2.583 3.63 -2.278 c
+4.145 -3.072 l
+3.987 -3.289 3.755 -3.465 3.453 -3.601 c
+3.149 -3.737 2.822 -3.807 2.469 -3.807 c
+1.646 -0.764 m
+2.954 -0.764 l
+2.954 -0.646 l
+2.944 -0.345 2.888 -0.118 2.792 0.03 c
+2.705 0.184 2.547 0.265 2.322 0.265 c
+2.094 0.265 1.929 0.181 1.822 0.015 c
+1.723 -0.143 1.664 -0.404 1.646 -0.764 c
+8.658 -1.396 m
+8.658 -2.171 8.517 -2.77 8.246 -3.189 c
+7.981 -3.601 7.584 -3.807 7.056 -3.807 c
+6.651 -3.807 6.327 -3.645 6.085 -3.322 c
+6.085 -5.629 l
+4.777 -5.629 l
+4.777 1.249 l
+5.982 1.249 l
+6.026 0.794 l
+6.279 1.154 6.618 1.338 7.041 1.338 c
+7.57 1.338 7.966 1.147 8.232 0.765 c
+8.503 0.383 8.646 -0.213 8.658 -1.014 c
+h
+7.364 -1.058 m
+7.364 -0.58 7.309 -0.243 7.202 -0.044 c
+7.092 0.151 6.912 0.25 6.659 0.25 c
+6.394 0.25 6.202 0.14 6.085 -0.073 c
+6.085 -2.41 l
+6.202 -2.627 6.397 -2.734 6.673 -2.734 c
+6.927 -2.734 7.103 -2.627 7.202 -2.41 c
+7.309 -2.186 7.364 -1.849 7.364 -1.396 c
+h
+9.109 -1.072 m
+9.109 -0.32 9.286 0.268 9.639 0.691 c
+9.992 1.121 10.48 1.338 11.108 1.338 c
+11.744 1.338 12.24 1.121 12.593 0.691 c
+12.953 0.268 13.136 -0.323 13.136 -1.087 c
+13.136 -1.396 l
+13.136 -2.153 12.961 -2.745 12.608 -3.175 c
+12.255 -3.597 11.759 -3.807 11.123 -3.807 c
+10.484 -3.807 9.992 -3.597 9.639 -3.175 c
+9.286 -2.745 9.109 -2.153 9.109 -1.396 c
+h
+10.418 -1.396 m
+10.418 -2.289 10.653 -2.734 11.123 -2.734 c
+11.565 -2.734 11.8 -2.362 11.829 -1.616 c
+11.843 -1.072 l
+11.843 -0.625 11.777 -0.29 11.652 -0.073 c
+11.524 0.151 11.343 0.265 11.108 0.265 c
+10.892 0.265 10.719 0.151 10.594 -0.073 c
+10.476 -0.29 10.418 -0.625 10.418 -1.072 c
+h
+15.959 -2.381 m
+15.959 -2.275 15.904 -2.175 15.798 -2.087 c
+15.687 -1.992 15.452 -1.863 15.092 -1.705 c
+14.551 -1.492 14.184 -1.263 13.99 -1.028 c
+13.791 -0.793 13.695 -0.507 13.695 -0.162 c
+13.695 0.279 13.85 0.636 14.166 0.912 c
+14.478 1.195 14.89 1.338 15.401 1.338 c
+15.948 1.338 16.386 1.195 16.708 0.912 c
+17.04 0.636 17.209 0.258 17.209 -0.22 c
+15.9 -0.22 l
+15.9 0.191 15.731 0.397 15.401 0.397 c
+15.261 0.397 15.151 0.353 15.062 0.265 c
+14.975 0.177 14.931 0.059 14.931 -0.087 c
+14.931 -0.205 14.978 -0.309 15.077 -0.397 c
+15.173 -0.478 15.405 -0.595 15.768 -0.75 c
+16.297 -0.948 16.668 -1.168 16.885 -1.411 c
+17.109 -1.646 17.223 -1.955 17.223 -2.337 c
+17.223 -2.778 17.055 -3.138 16.724 -3.41 c
+16.389 -3.674 15.948 -3.807 15.401 -3.807 c
+15.037 -3.807 14.713 -3.737 14.43 -3.601 c
+14.155 -3.454 13.938 -3.256 13.784 -2.998 c
+13.626 -2.745 13.549 -2.469 13.549 -2.175 c
+14.783 -2.175 l
+14.79 -2.403 14.846 -2.572 14.945 -2.69 c
+15.041 -2.807 15.202 -2.866 15.43 -2.866 c
+15.783 -2.866 15.959 -2.705 15.959 -2.381 c
+19.23 -3.719 -1.309 4.968 re
+17.863 2.543 m
+17.863 2.738 17.925 2.899 18.054 3.028 c
+18.179 3.165 18.351 3.234 18.568 3.234 c
+18.781 3.234 18.954 3.165 19.083 3.028 c
+19.208 2.899 19.274 2.738 19.274 2.543 c
+19.274 2.338 19.208 2.165 19.083 2.029 c
+18.965 1.9 18.792 1.837 18.568 1.837 c
+18.351 1.837 18.179 1.9 18.054 2.029 c
+17.925 2.165 17.863 2.338 17.863 2.543 c
+21.655 2.469 m
+21.655 1.249 l
+22.316 1.249 l
+22.316 0.279 l
+21.655 0.279 l
+21.655 -2.19 l
+21.655 -2.389 21.677 -2.524 21.728 -2.601 c
+21.788 -2.672 21.894 -2.705 22.052 -2.705 c
+22.169 -2.705 22.272 -2.697 22.36 -2.674 c
+22.346 -3.69 l
+22.118 -3.767 21.879 -3.807 21.626 -3.807 c
+20.791 -3.807 20.369 -3.329 20.361 -2.366 c
+20.361 0.279 l
+19.789 0.279 l
+19.789 1.249 l
+20.361 1.249 l
+20.361 2.469 l
+h
+22.64 -1.072 m
+22.64 -0.32 22.817 0.268 23.169 0.691 c
+23.522 1.121 24.01 1.338 24.639 1.338 c
+25.275 1.338 25.771 1.121 26.123 0.691 c
+26.484 0.268 26.667 -0.323 26.667 -1.087 c
+26.667 -1.396 l
+26.667 -2.153 26.491 -2.745 26.138 -3.175 c
+25.786 -3.597 25.289 -3.807 24.654 -3.807 c
+24.014 -3.807 23.522 -3.597 23.169 -3.175 c
+22.817 -2.745 22.64 -2.153 22.64 -1.396 c
+h
+23.948 -1.396 m
+23.948 -2.289 24.184 -2.734 24.654 -2.734 c
+25.094 -2.734 25.329 -2.362 25.36 -1.616 c
+25.374 -1.072 l
+25.374 -0.625 25.308 -0.29 25.183 -0.073 c
+25.054 0.151 24.874 0.265 24.639 0.265 c
+24.423 0.265 24.25 0.151 24.124 -0.073 c
+24.007 -0.29 23.948 -0.625 23.948 -1.072 c
+h
+29.74 0 m
+29.313 0.03 l
+28.949 0.03 28.71 -0.128 28.593 -0.44 c
+28.593 -3.719 l
+27.285 -3.719 l
+27.285 1.249 l
+28.504 1.249 l
+28.549 0.721 l
+28.755 1.132 29.038 1.338 29.402 1.338 c
+29.549 1.338 29.666 1.316 29.755 1.279 c
+h
+31.974 -1.558 m
+32.635 1.249 l
+34.017 1.249 l
+32.385 -4.469 l
+32.139 -5.31 31.679 -5.732 31.004 -5.732 c
+30.846 -5.732 30.665 -5.703 30.46 -5.644 c
+30.46 -4.63 l
+30.621 -4.63 l
+30.816 -4.63 30.964 -4.59 31.062 -4.513 c
+31.169 -4.432 31.253 -4.295 31.313 -4.101 c
+31.415 -3.763 l
+29.975 1.249 l
+31.371 1.249 l
+h
+f
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 653.8919 273.5134 cm
+0 0 m
+32.606 0 l
+35.211 0 37.306 -2.098 37.306 -4.704 c
+37.306 -19.829 l
+37.306 -22.434 35.211 -24.529 32.606 -24.529 c
+0 -24.529 l
+-2.606 -24.529 -4.704 -22.434 -4.704 -19.829 c
+-4.704 -4.704 l
+-4.704 -2.098 -2.606 0 0 0 c
+f
+Q
+0 0 0 0 k
+q 1 0 0 1 659.4808 265.2527 cm
+0 0 m
+0.455 2.793 l
+1.691 2.793 l
+0.661 -2.175 l
+-0.411 -2.175 l
+-1.117 0.706 l
+-1.822 -2.175 l
+-2.896 -2.175 l
+-3.925 2.793 l
+-2.675 2.793 l
+-2.234 0 l
+-1.573 2.793 l
+-0.661 2.793 l
+h
+1.951 0.47 m
+1.951 1.224 2.128 1.812 2.481 2.234 c
+2.834 2.664 3.322 2.882 3.95 2.882 c
+4.586 2.882 5.082 2.664 5.435 2.234 c
+5.795 1.812 5.978 1.22 5.978 0.455 c
+5.978 0.147 l
+5.978 -0.61 5.803 -1.201 5.45 -1.631 c
+5.097 -2.055 4.601 -2.263 3.965 -2.263 c
+3.326 -2.263 2.834 -2.055 2.481 -1.631 c
+2.128 -1.201 1.951 -0.61 1.951 0.147 c
+h
+3.26 0.147 m
+3.26 -0.746 3.495 -1.191 3.965 -1.191 c
+4.406 -1.191 4.642 -0.819 4.671 -0.073 c
+4.686 0.47 l
+4.686 0.919 4.619 1.253 4.494 1.47 c
+4.366 1.694 4.185 1.808 3.95 1.808 c
+3.734 1.808 3.561 1.694 3.436 1.47 c
+3.318 1.253 3.26 0.919 3.26 0.47 c
+h
+9.051 1.544 m
+8.625 1.573 l
+8.261 1.573 8.022 1.415 7.904 1.103 c
+7.904 -2.175 l
+6.596 -2.175 l
+6.596 2.793 l
+7.817 2.793 l
+7.86 2.263 l
+8.066 2.675 8.349 2.882 8.713 2.882 c
+8.86 2.882 8.978 2.859 9.066 2.822 c
+h
+11.241 -0.264 m
+10.903 -0.646 l
+10.903 -2.175 l
+9.595 -2.175 l
+9.595 4.881 l
+10.903 4.881 l
+10.903 1.073 l
+11.065 1.309 l
+11.962 2.793 l
+13.504 2.793 l
+12.064 0.75 l
+13.652 -2.175 l
+12.153 -2.175 l
+h
+15.283 -2.175 -1.309 4.968 re
+13.916 4.087 m
+13.916 4.281 13.978 4.443 14.107 4.571 c
+14.232 4.707 14.406 4.777 14.622 4.777 c
+14.836 4.777 15.008 4.707 15.137 4.571 c
+15.262 4.443 15.328 4.281 15.328 4.087 c
+15.328 3.881 15.262 3.707 15.137 3.572 c
+15.019 3.443 14.846 3.381 14.622 3.381 c
+14.406 3.381 14.232 3.443 14.107 3.572 c
+13.978 3.707 13.916 3.881 13.916 4.087 c
+17.382 2.793 m
+17.425 2.308 l
+17.72 2.69 18.102 2.882 18.572 2.882 c
+19.424 2.882 19.866 2.282 19.895 1.088 c
+19.895 -2.175 l
+18.587 -2.175 l
+18.587 1 l
+18.587 1.272 18.543 1.473 18.455 1.602 c
+18.374 1.727 18.227 1.793 18.013 1.793 c
+17.778 1.793 17.595 1.675 17.47 1.44 c
+17.47 -2.175 l
+16.162 -2.175 l
+16.162 2.793 l
+h
+20.49 0.455 m
+20.49 1.278 20.638 1.885 20.931 2.278 c
+21.226 2.679 21.637 2.882 22.167 2.882 c
+22.614 2.882 22.964 2.705 23.21 2.352 c
+23.254 2.793 l
+24.43 2.793 l
+24.43 -2.175 l
+24.43 -2.811 24.246 -3.296 23.886 -3.63 c
+23.534 -3.961 23.023 -4.131 22.358 -4.131 c
+22.092 -4.131 21.806 -4.075 21.504 -3.969 c
+21.2 -3.859 20.976 -3.723 20.829 -3.557 c
+21.269 -2.66 l
+21.394 -2.786 21.556 -2.888 21.755 -2.969 c
+21.949 -3.046 22.129 -3.087 22.298 -3.087 c
+22.593 -3.087 22.802 -3.017 22.931 -2.881 c
+23.056 -2.741 23.122 -2.517 23.122 -2.205 c
+23.122 -1.779 l
+22.875 -2.102 22.552 -2.263 22.152 -2.263 c
+21.622 -2.263 21.211 -2.057 20.916 -1.646 c
+20.63 -1.234 20.49 -0.658 20.49 0.088 c
+h
+21.784 0.133 m
+21.784 -0.331 21.843 -0.661 21.961 -0.867 c
+22.078 -1.073 22.269 -1.176 22.534 -1.176 c
+22.798 -1.176 22.993 -1.084 23.122 -0.897 c
+23.122 1.484 l
+22.993 1.691 22.802 1.793 22.549 1.793 c
+22.284 1.793 22.086 1.683 21.961 1.47 c
+21.843 1.264 21.784 0.926 21.784 0.455 c
+h
+f
+Q
+q 1 0 0 1 653.8806 255.7758 cm
+0 0 m
+0 0.823 0.135 1.429 0.411 1.822 c
+0.694 2.223 1.095 2.425 1.617 2.425 c
+1.999 2.425 2.315 2.263 2.572 1.94 c
+2.572 4.424 l
+3.881 4.424 l
+3.881 -2.631 l
+2.705 -2.631 l
+2.645 -2.132 l
+2.381 -2.525 2.036 -2.72 1.617 -2.72 c
+1.095 -2.72 0.698 -2.525 0.426 -2.132 c
+0.151 -1.731 0.008 -1.143 0 -0.368 c
+h
+1.309 -0.324 m
+1.309 -0.816 1.356 -1.158 1.455 -1.353 c
+1.562 -1.54 1.741 -1.632 1.999 -1.632 c
+2.252 -1.632 2.444 -1.521 2.572 -1.294 c
+2.572 0.97 l
+2.444 1.213 2.252 1.338 1.999 1.338 c
+1.764 1.338 1.587 1.238 1.469 1.043 c
+1.359 0.856 1.309 0.518 1.309 0.029 c
+h
+6.023 -2.631 -1.308 4.968 re
+4.656 3.63 m
+4.656 3.825 4.719 3.987 4.847 4.116 c
+4.972 4.251 5.145 4.322 5.361 4.322 c
+5.575 4.322 5.747 4.251 5.876 4.116 c
+6.001 3.987 6.067 3.825 6.067 3.63 c
+6.067 3.424 6.001 3.252 5.876 3.116 c
+5.758 2.988 5.585 2.925 5.361 2.925 c
+5.145 2.925 4.972 2.988 4.847 3.116 c
+4.719 3.252 4.656 3.424 4.656 3.63 c
+9.385 1.087 m
+8.959 1.117 l
+8.596 1.117 8.357 0.959 8.239 0.646 c
+8.239 -2.631 l
+6.93 -2.631 l
+6.93 2.337 l
+8.151 2.337 l
+8.195 1.808 l
+8.401 2.219 8.683 2.425 9.047 2.425 c
+9.194 2.425 9.311 2.404 9.4 2.366 c
+h
+11.854 -2.72 m
+11.186 -2.72 10.664 -2.525 10.282 -2.132 c
+9.907 -1.731 9.724 -1.158 9.724 -0.412 c
+9.724 -0.015 l
+9.724 0.768 9.893 1.371 10.238 1.793 c
+10.58 2.212 11.075 2.425 11.723 2.425 c
+12.34 2.425 12.802 2.223 13.119 1.822 c
+13.442 1.429 13.604 0.841 13.604 0.058 c
+13.604 -0.588 l
+11.031 -0.588 l
+11.039 -0.952 11.12 -1.22 11.266 -1.397 c
+11.414 -1.565 11.634 -1.646 11.929 -1.646 c
+12.369 -1.646 12.729 -1.496 13.016 -1.191 c
+13.531 -1.985 l
+13.373 -2.201 13.141 -2.378 12.839 -2.514 c
+12.534 -2.65 12.207 -2.72 11.854 -2.72 c
+11.031 0.324 m
+12.34 0.324 l
+12.34 0.441 l
+12.328 0.742 12.274 0.97 12.178 1.117 c
+12.089 1.271 11.932 1.352 11.707 1.352 c
+11.48 1.352 11.314 1.267 11.208 1.103 c
+11.108 0.944 11.05 0.683 11.031 0.324 c
+15.956 -1.646 m
+16.338 -1.646 16.529 -1.404 16.529 -0.912 c
+17.764 -0.912 l
+17.753 -1.452 17.58 -1.889 17.249 -2.22 c
+16.926 -2.554 16.503 -2.72 15.985 -2.72 c
+15.345 -2.72 14.857 -2.525 14.516 -2.132 c
+14.181 -1.731 14.015 -1.143 14.015 -0.368 c
+14.015 0.029 l
+14.015 0.812 14.177 1.404 14.501 1.808 c
+14.832 2.219 15.327 2.425 15.985 2.425 c
+16.533 2.425 16.962 2.252 17.279 1.911 c
+17.591 1.577 17.753 1.103 17.764 0.484 c
+16.529 0.484 l
+16.529 0.757 16.485 0.97 16.397 1.117 c
+16.309 1.271 16.162 1.352 15.956 1.352 c
+15.728 1.352 15.566 1.267 15.47 1.103 c
+15.372 0.944 15.316 0.636 15.309 0.176 c
+15.309 -0.324 l
+15.309 -0.735 15.327 -1.022 15.368 -1.176 c
+15.405 -1.334 15.47 -1.452 15.559 -1.529 c
+15.655 -1.61 15.786 -1.646 15.956 -1.646 c
+19.84 3.557 m
+19.84 2.337 l
+20.502 2.337 l
+20.502 1.367 l
+19.84 1.367 l
+19.84 -1.103 l
+19.84 -1.301 19.862 -1.437 19.914 -1.515 c
+19.972 -1.584 20.079 -1.617 20.237 -1.617 c
+20.355 -1.617 20.457 -1.61 20.546 -1.588 c
+20.531 -2.602 l
+20.303 -2.679 20.064 -2.72 19.81 -2.72 c
+18.977 -2.72 18.554 -2.242 18.547 -1.279 c
+18.547 1.367 l
+17.973 1.367 l
+17.973 2.337 l
+18.547 2.337 l
+18.547 3.557 l
+h
+20.825 0.014 m
+20.825 0.768 21.001 1.356 21.354 1.778 c
+21.707 2.208 22.196 2.425 22.824 2.425 c
+23.459 2.425 23.956 2.208 24.309 1.778 c
+24.669 1.356 24.852 0.764 24.852 0 c
+24.852 -0.309 l
+24.852 -1.066 24.676 -1.658 24.323 -2.088 c
+23.97 -2.51 23.474 -2.72 22.838 -2.72 c
+22.2 -2.72 21.707 -2.51 21.354 -2.088 c
+21.001 -1.658 20.825 -1.066 20.825 -0.309 c
+h
+22.133 -0.309 m
+22.133 -1.202 22.368 -1.646 22.838 -1.646 c
+23.28 -1.646 23.515 -1.276 23.544 -0.53 c
+23.559 0.014 l
+23.559 0.463 23.493 0.797 23.368 1.014 c
+23.239 1.238 23.059 1.352 22.824 1.352 c
+22.607 1.352 22.435 1.238 22.31 1.014 c
+22.192 0.797 22.133 0.463 22.133 0.014 c
+h
+27.925 1.087 m
+27.498 1.117 l
+27.135 1.117 26.896 0.959 26.778 0.646 c
+26.778 -2.631 l
+25.47 -2.631 l
+25.47 2.337 l
+26.69 2.337 l
+26.734 1.808 l
+26.94 2.219 27.222 2.425 27.586 2.425 c
+27.733 2.425 27.851 2.404 27.939 2.366 c
+h
+30.158 -0.47 m
+30.82 2.337 l
+32.201 2.337 l
+30.57 -3.381 l
+30.324 -4.222 29.865 -4.645 29.188 -4.645 c
+29.03 -4.645 28.851 -4.615 28.645 -4.557 c
+28.645 -3.543 l
+28.806 -3.543 l
+29.001 -3.543 29.148 -3.502 29.248 -3.425 c
+29.354 -3.344 29.439 -3.208 29.497 -3.013 c
+29.6 -2.675 l
+28.16 2.337 l
+29.556 2.337 l
+h
+f
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+/GS3 gs
+0 TL/Fm2 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+/GS3 gs
+0 TL/Fm3 Do
+Q
+0.793 0.801 0.129 0.016 K
+0.567 w 4 M 1 j 1 J []0 d
+q 1 0 0 1 649.192 239.6172 cm
+0 0 m
+3.193 5.056 l
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 651.2461 242.8702 cm
+0 0 m
+0.33 -1.473 l
+1.421 2.253 l
+-1.474 -0.335 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 651.2462 242.8702 cm
+0 0 m
+0.33 -1.473 l
+1.421 2.253 l
+-1.474 -0.335 l
+0 0 l
+h
+S
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm4 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm5 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm6 Do
+Q
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 584.4681 270.0962 cm
+0 0 m
+5.453 5.056 l
+S
+Q
+q 1 0 0 1 588.3553 273.7013 cm
+0 0 m
+-0.058 -1.507 l
+1.955 1.815 l
+-1.507 0.059 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 588.3554 273.7014 cm
+0 0 m
+-0.059 -1.507 l
+1.955 1.815 l
+-1.507 0.059 l
+0 0 l
+h
+S
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 637.7262 286.0224 cm
+0 0 m
+0 0.459 0.081 0.809 0.25 1.044 c
+0.426 1.286 0.676 1.411 1 1.411 c
+1.301 1.411 1.532 1.279 1.691 1.014 c
+1.72 1.353 l
+2.161 1.353 l
+2.161 -1.66 l
+2.161 -2.032 2.061 -2.315 1.866 -2.514 c
+1.679 -2.708 1.419 -2.807 1.088 -2.807 c
+0.941 -2.807 0.771 -2.767 0.588 -2.69 c
+0.401 -2.62 0.264 -2.532 0.177 -2.425 c
+0.368 -2.088 l
+0.573 -2.293 0.798 -2.396 1.043 -2.396 c
+1.444 -2.396 1.65 -2.168 1.661 -1.72 c
+1.661 -1.338 l
+1.503 -1.573 1.282 -1.691 1 -1.691 c
+0.684 -1.691 0.441 -1.573 0.264 -1.338 c
+0.096 -1.103 0.008 -0.771 0 -0.338 c
+h
+0.485 -0.279 m
+0.485 -0.613 0.532 -0.86 0.632 -1.014 c
+0.727 -1.172 0.889 -1.249 1.118 -1.249 c
+1.359 -1.249 1.544 -1.128 1.661 -0.882 c
+1.661 0.603 l
+1.544 0.846 1.367 0.97 1.132 0.97 c
+0.904 0.97 0.742 0.889 0.647 0.735 c
+0.548 0.577 0.492 0.339 0.485 0.015 c
+h
+3.227 -1.631 -0.501 2.984 re
+3.256 2.146 m
+3.256 2.058 3.231 1.985 3.183 1.926 c
+3.142 1.874 3.073 1.852 2.977 1.852 c
+2.888 1.852 2.818 1.874 2.771 1.926 c
+2.73 1.985 2.712 2.051 2.712 2.132 c
+2.712 2.22 2.73 2.293 2.771 2.352 c
+2.818 2.411 2.888 2.44 2.977 2.44 c
+3.073 2.44 3.142 2.411 3.183 2.352 c
+3.231 2.293 3.256 2.223 3.256 2.146 c
+4.534 2.072 m
+4.534 1.353 l
+4.991 1.353 l
+4.991 0.956 l
+4.534 0.956 l
+4.534 -0.897 l
+4.534 -1.014 4.553 -1.103 4.594 -1.161 c
+4.63 -1.22 4.7 -1.249 4.8 -1.249 c
+4.858 -1.249 4.92 -1.242 4.991 -1.22 c
+4.991 -1.631 l
+4.873 -1.668 4.759 -1.691 4.652 -1.691 c
+4.453 -1.691 4.303 -1.624 4.197 -1.484 c
+4.098 -1.348 4.05 -1.153 4.05 -0.897 c
+4.05 0.956 l
+3.594 0.956 l
+3.594 1.353 l
+4.05 1.353 l
+4.05 2.072 l
+h
+8.099 -0.867 m
+8.099 -0.76 8.058 -0.673 7.981 -0.602 c
+7.9 -0.525 7.75 -0.437 7.526 -0.338 c
+7.262 -0.231 7.074 -0.139 6.967 -0.058 c
+6.857 0.019 6.78 0.106 6.732 0.206 c
+6.681 0.301 6.659 0.419 6.659 0.559 c
+6.659 0.801 6.747 1.004 6.923 1.162 c
+7.1 1.326 7.324 1.411 7.599 1.411 c
+7.894 1.411 8.129 1.323 8.305 1.147 c
+8.482 0.977 8.569 0.765 8.569 0.5 c
+8.085 0.5 l
+8.085 0.636 8.033 0.75 7.938 0.838 c
+7.85 0.933 7.736 0.985 7.599 0.985 c
+7.453 0.985 7.339 0.944 7.262 0.867 c
+7.181 0.798 7.144 0.698 7.144 0.574 c
+7.144 0.474 7.173 0.397 7.232 0.339 c
+7.291 0.279 7.43 0.198 7.659 0.103 c
+8.018 -0.044 8.264 -0.187 8.393 -0.324 c
+8.529 -0.452 8.599 -0.625 8.599 -0.837 c
+8.599 -1.095 8.503 -1.301 8.32 -1.455 c
+8.143 -1.613 7.908 -1.691 7.614 -1.691 c
+7.298 -1.691 7.044 -1.602 6.85 -1.425 c
+6.662 -1.242 6.57 -1.01 6.57 -0.735 c
+7.056 -0.735 l
+7.063 -0.904 7.115 -1.036 7.202 -1.132 c
+7.298 -1.22 7.437 -1.264 7.614 -1.264 c
+7.769 -1.264 7.886 -1.23 7.967 -1.161 c
+8.056 -1.095 8.099 -0.995 8.099 -0.867 c
+9.687 2.072 m
+9.687 1.353 l
+10.142 1.353 l
+10.142 0.956 l
+9.687 0.956 l
+9.687 -0.897 l
+9.687 -1.014 9.705 -1.103 9.745 -1.161 c
+9.782 -1.22 9.852 -1.249 9.951 -1.249 c
+10.01 -1.249 10.073 -1.242 10.142 -1.22 c
+10.142 -1.631 l
+10.025 -1.668 9.911 -1.691 9.804 -1.691 c
+9.606 -1.691 9.455 -1.624 9.349 -1.484 c
+9.249 -1.348 9.201 -1.153 9.201 -0.897 c
+9.201 0.956 l
+8.746 0.956 l
+8.746 1.353 l
+9.201 1.353 l
+9.201 2.072 l
+h
+12.137 -1.631 m
+12.108 -1.565 12.087 -1.455 12.079 -1.308 c
+11.902 -1.565 11.682 -1.691 11.418 -1.691 c
+11.142 -1.691 10.925 -1.617 10.771 -1.469 c
+10.624 -1.315 10.55 -1.099 10.55 -0.823 c
+10.55 -0.522 10.653 -0.279 10.859 -0.103 c
+11.065 0.081 11.348 0.177 11.711 0.177 c
+12.064 0.177 l
+12.064 0.5 l
+12.064 0.676 12.024 0.798 11.946 0.867 c
+11.866 0.944 11.748 0.985 11.594 0.985 c
+11.447 0.985 11.322 0.941 11.227 0.852 c
+11.138 0.765 11.094 0.654 11.094 0.53 c
+10.609 0.53 l
+10.609 0.676 10.653 0.816 10.741 0.956 c
+10.83 1.103 10.947 1.213 11.094 1.294 c
+11.248 1.371 11.422 1.411 11.609 1.411 c
+11.921 1.411 12.156 1.33 12.314 1.176 c
+12.469 1.029 12.549 0.809 12.549 0.515 c
+12.549 -0.985 l
+12.557 -1.22 12.594 -1.422 12.652 -1.587 c
+12.652 -1.631 l
+h
+11.491 -1.249 m
+11.609 -1.249 11.719 -1.216 11.829 -1.147 c
+11.936 -1.08 12.013 -0.995 12.064 -0.897 c
+12.064 -0.191 l
+11.8 -0.191 l
+11.565 -0.191 11.377 -0.243 11.241 -0.338 c
+11.113 -0.437 11.05 -0.58 11.05 -0.764 c
+11.05 -0.933 11.079 -1.055 11.138 -1.132 c
+11.204 -1.213 11.322 -1.249 11.491 -1.249 c
+14.57 -0.867 m
+14.57 -0.76 14.53 -0.673 14.453 -0.602 c
+14.372 -0.525 14.221 -0.437 13.997 -0.338 c
+13.733 -0.231 13.545 -0.139 13.438 -0.058 c
+13.328 0.019 13.251 0.106 13.203 0.206 c
+13.152 0.301 13.13 0.419 13.13 0.559 c
+13.13 0.801 13.218 1.004 13.394 1.162 c
+13.571 1.326 13.795 1.411 14.071 1.411 c
+14.365 1.411 14.6 1.323 14.776 1.147 c
+14.953 0.977 15.041 0.765 15.041 0.5 c
+14.556 0.5 l
+14.556 0.636 14.504 0.75 14.408 0.838 c
+14.321 0.933 14.207 0.985 14.071 0.985 c
+13.924 0.985 13.81 0.944 13.733 0.867 c
+13.652 0.798 13.615 0.698 13.615 0.574 c
+13.615 0.474 13.645 0.397 13.703 0.339 c
+13.762 0.279 13.901 0.198 14.13 0.103 c
+14.489 -0.044 14.736 -0.187 14.865 -0.324 c
+15 -0.452 15.071 -0.625 15.071 -0.837 c
+15.071 -1.095 14.975 -1.301 14.791 -1.455 c
+14.614 -1.613 14.379 -1.691 14.086 -1.691 c
+13.77 -1.691 13.516 -1.602 13.321 -1.425 c
+13.134 -1.242 13.042 -1.01 13.042 -0.735 c
+13.527 -0.735 l
+13.534 -0.904 13.585 -1.036 13.674 -1.132 c
+13.77 -1.22 13.909 -1.264 14.086 -1.264 c
+14.24 -1.264 14.358 -1.23 14.438 -1.161 c
+14.526 -1.095 14.57 -0.995 14.57 -0.867 c
+16.014 1.044 m
+16.199 1.286 16.434 1.411 16.72 1.411 c
+17.249 1.411 17.518 1.058 17.529 0.353 c
+17.529 -1.631 l
+17.043 -1.631 l
+17.043 0.324 l
+17.043 0.559 17.003 0.724 16.926 0.823 c
+16.845 0.919 16.727 0.97 16.573 0.97 c
+16.455 0.97 16.345 0.929 16.249 0.852 c
+16.151 0.771 16.074 0.665 16.014 0.53 c
+16.014 -1.631 l
+15.53 -1.631 l
+15.53 2.602 l
+16.014 2.602 l
+h
+f
+Q
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 653.715 276.3362 cm
+0 0 m
+-10.796 5.008 -20.332 5.81 -29.005 3.726 c
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 626.7867 280.5622 cm
+0 0 m
+0.787 1.286 l
+-2.594 -0.624 l
+1.286 -0.791 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 626.7867 280.5622 cm
+0 0 m
+0.787 1.286 l
+-2.594 -0.625 l
+1.286 -0.791 l
+0 0 l
+h
+S
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 606.5934 264.4701 cm
+0 0 m
+0 0.459 0.081 0.808 0.25 1.043 c
+0.426 1.286 0.676 1.411 1 1.411 c
+1.301 1.411 1.532 1.278 1.69 1.014 c
+1.72 1.353 l
+2.161 1.353 l
+2.161 -1.661 l
+2.161 -2.032 2.062 -2.315 1.867 -2.514 c
+1.679 -2.708 1.419 -2.807 1.088 -2.807 c
+0.941 -2.807 0.772 -2.767 0.588 -2.69 c
+0.401 -2.62 0.265 -2.532 0.177 -2.425 c
+0.368 -2.087 l
+0.574 -2.293 0.798 -2.396 1.044 -2.396 c
+1.444 -2.396 1.65 -2.168 1.661 -1.72 c
+1.661 -1.338 l
+1.503 -1.573 1.283 -1.691 1 -1.691 c
+0.684 -1.691 0.441 -1.573 0.265 -1.338 c
+0.096 -1.103 0.008 -0.771 0 -0.338 c
+h
+0.485 -0.279 m
+0.485 -0.613 0.533 -0.86 0.632 -1.014 c
+0.728 -1.172 0.89 -1.249 1.118 -1.249 c
+1.36 -1.249 1.544 -1.128 1.661 -0.881 c
+1.661 0.603 l
+1.544 0.845 1.367 0.97 1.132 0.97 c
+0.904 0.97 0.742 0.889 0.647 0.735 c
+0.548 0.577 0.493 0.338 0.485 0.015 c
+h
+3.223 -1.631 -0.5 2.984 re
+3.252 2.146 m
+3.252 2.058 3.227 1.984 3.179 1.926 c
+3.138 1.874 3.069 1.852 2.973 1.852 c
+2.885 1.852 2.815 1.874 2.768 1.926 c
+2.727 1.984 2.708 2.051 2.708 2.132 c
+2.708 2.219 2.727 2.294 2.768 2.352 c
+2.815 2.411 2.885 2.44 2.973 2.44 c
+3.069 2.44 3.138 2.411 3.179 2.352 c
+3.227 2.294 3.252 2.223 3.252 2.146 c
+4.532 2.072 m
+4.532 1.353 l
+4.987 1.353 l
+4.987 0.956 l
+4.532 0.956 l
+4.532 -0.897 l
+4.532 -1.014 4.549 -1.103 4.59 -1.161 c
+4.627 -1.22 4.696 -1.249 4.796 -1.249 c
+4.854 -1.249 4.917 -1.242 4.987 -1.22 c
+4.987 -1.631 l
+4.869 -1.668 4.755 -1.691 4.649 -1.691 c
+4.451 -1.691 4.3 -1.625 4.193 -1.484 c
+4.094 -1.349 4.046 -1.154 4.046 -0.897 c
+4.046 0.956 l
+3.591 0.956 l
+3.591 1.353 l
+4.046 1.353 l
+4.046 2.072 l
+h
+8.096 -0.867 m
+8.096 -0.761 8.056 -0.673 7.978 -0.603 c
+7.898 -0.526 7.747 -0.437 7.522 -0.338 c
+7.258 -0.231 7.071 -0.139 6.964 -0.058 c
+6.853 0.019 6.776 0.106 6.729 0.206 c
+6.677 0.301 6.655 0.419 6.655 0.559 c
+6.655 0.802 6.743 1.003 6.92 1.161 c
+7.096 1.326 7.321 1.411 7.596 1.411 c
+7.89 1.411 8.125 1.323 8.301 1.147 c
+8.478 0.977 8.566 0.765 8.566 0.5 c
+8.081 0.5 l
+8.081 0.636 8.029 0.75 7.934 0.838 c
+7.846 0.933 7.732 0.985 7.596 0.985 c
+7.449 0.985 7.335 0.944 7.258 0.867 c
+7.177 0.798 7.14 0.698 7.14 0.573 c
+7.14 0.474 7.169 0.397 7.229 0.338 c
+7.287 0.279 7.427 0.198 7.655 0.103 c
+8.015 -0.044 8.262 -0.187 8.39 -0.324 c
+8.526 -0.452 8.596 -0.625 8.596 -0.838 c
+8.596 -1.095 8.5 -1.301 8.316 -1.455 c
+8.14 -1.613 7.905 -1.691 7.611 -1.691 c
+7.294 -1.691 7.041 -1.602 6.847 -1.426 c
+6.659 -1.242 6.567 -1.01 6.567 -0.735 c
+7.052 -0.735 l
+7.059 -0.904 7.111 -1.037 7.199 -1.132 c
+7.294 -1.22 7.435 -1.264 7.611 -1.264 c
+7.765 -1.264 7.882 -1.231 7.963 -1.161 c
+8.052 -1.095 8.096 -0.996 8.096 -0.867 c
+9.687 2.072 m
+9.687 1.353 l
+10.143 1.353 l
+10.143 0.956 l
+9.687 0.956 l
+9.687 -0.897 l
+9.687 -1.014 9.706 -1.103 9.746 -1.161 c
+9.783 -1.22 9.852 -1.249 9.951 -1.249 c
+10.01 -1.249 10.073 -1.242 10.143 -1.22 c
+10.143 -1.631 l
+10.026 -1.668 9.911 -1.691 9.804 -1.691 c
+9.606 -1.691 9.455 -1.625 9.349 -1.484 c
+9.249 -1.349 9.202 -1.154 9.202 -0.897 c
+9.202 0.956 l
+8.746 0.956 l
+8.746 1.353 l
+9.202 1.353 l
+9.202 2.072 l
+h
+12.135 -1.631 m
+12.104 -1.565 12.083 -1.455 12.075 -1.309 c
+11.899 -1.565 11.678 -1.691 11.414 -1.691 c
+11.138 -1.691 10.922 -1.617 10.768 -1.469 c
+10.62 -1.315 10.547 -1.099 10.547 -0.823 c
+10.547 -0.522 10.65 -0.279 10.855 -0.103 c
+11.061 0.081 11.344 0.177 11.708 0.177 c
+12.061 0.177 l
+12.061 0.5 l
+12.061 0.676 12.021 0.798 11.944 0.867 c
+11.863 0.944 11.745 0.985 11.591 0.985 c
+11.443 0.985 11.319 0.941 11.223 0.852 c
+11.135 0.765 11.09 0.654 11.09 0.53 c
+10.606 0.53 l
+10.606 0.676 10.65 0.816 10.738 0.956 c
+10.826 1.103 10.944 1.213 11.09 1.294 c
+11.245 1.371 11.418 1.411 11.605 1.411 c
+11.917 1.411 12.152 1.33 12.31 1.176 c
+12.465 1.029 12.546 0.808 12.546 0.515 c
+12.546 -0.985 l
+12.553 -1.22 12.59 -1.422 12.649 -1.587 c
+12.649 -1.631 l
+h
+11.487 -1.249 m
+11.605 -1.249 11.715 -1.216 11.826 -1.147 c
+11.932 -1.08 12.01 -0.996 12.061 -0.897 c
+12.061 -0.191 l
+11.796 -0.191 l
+11.561 -0.191 11.374 -0.243 11.238 -0.338 c
+11.109 -0.437 11.046 -0.58 11.046 -0.764 c
+11.046 -0.933 11.076 -1.055 11.135 -1.132 c
+11.201 -1.213 11.319 -1.249 11.487 -1.249 c
+14.567 -0.867 m
+14.567 -0.761 14.527 -0.673 14.45 -0.603 c
+14.369 -0.526 14.218 -0.437 13.993 -0.338 c
+13.729 -0.231 13.542 -0.139 13.436 -0.058 c
+13.325 0.019 13.247 0.106 13.201 0.206 c
+13.149 0.301 13.126 0.419 13.126 0.559 c
+13.126 0.802 13.215 1.003 13.391 1.161 c
+13.567 1.326 13.791 1.411 14.067 1.411 c
+14.361 1.411 14.597 1.323 14.772 1.147 c
+14.949 0.977 15.038 0.765 15.038 0.5 c
+14.552 0.5 l
+14.552 0.636 14.501 0.75 14.406 0.838 c
+14.317 0.933 14.203 0.985 14.067 0.985 c
+13.92 0.985 13.806 0.944 13.729 0.867 c
+13.648 0.798 13.612 0.698 13.612 0.573 c
+13.612 0.474 13.641 0.397 13.7 0.338 c
+13.758 0.279 13.898 0.198 14.126 0.103 c
+14.486 -0.044 14.732 -0.187 14.861 -0.324 c
+14.997 -0.452 15.067 -0.625 15.067 -0.838 c
+15.067 -1.095 14.971 -1.301 14.787 -1.455 c
+14.612 -1.613 14.376 -1.691 14.082 -1.691 c
+13.766 -1.691 13.513 -1.602 13.318 -1.426 c
+13.13 -1.242 13.039 -1.01 13.039 -0.735 c
+13.523 -0.735 l
+13.531 -0.904 13.582 -1.037 13.671 -1.132 c
+13.766 -1.22 13.906 -1.264 14.082 -1.264 c
+14.236 -1.264 14.354 -1.231 14.435 -1.161 c
+14.523 -1.095 14.567 -0.996 14.567 -0.867 c
+16.011 1.043 m
+16.195 1.286 16.43 1.411 16.717 1.411 c
+17.246 1.411 17.514 1.058 17.525 0.353 c
+17.525 -1.631 l
+17.041 -1.631 l
+17.041 0.324 l
+17.041 0.559 17 0.724 16.923 0.823 c
+16.842 0.919 16.724 0.97 16.57 0.97 c
+16.453 0.97 16.342 0.929 16.247 0.852 c
+16.147 0.771 16.07 0.665 16.011 0.53 c
+16.011 -1.631 l
+15.526 -1.631 l
+15.526 2.602 l
+16.011 2.602 l
+h
+21.417 -0.279 m
+21.417 -0.75 21.332 -1.103 21.167 -1.338 c
+20.998 -1.573 20.759 -1.691 20.447 -1.691 c
+20.141 -1.691 19.91 -1.58 19.755 -1.352 c
+19.755 -2.778 l
+19.271 -2.778 l
+19.271 1.353 l
+19.711 1.353 l
+19.741 1.014 l
+19.896 1.278 20.127 1.411 20.432 1.411 c
+20.763 1.411 21.009 1.294 21.167 1.058 c
+21.332 0.831 21.417 0.492 21.417 0.044 c
+h
+20.931 0 m
+20.931 0.331 20.877 0.577 20.77 0.735 c
+20.671 0.889 20.509 0.97 20.285 0.97 c
+20.05 0.97 19.873 0.852 19.755 0.617 c
+19.755 -0.926 l
+19.873 -1.154 20.054 -1.264 20.299 -1.264 c
+20.513 -1.264 20.671 -1.187 20.77 -1.029 c
+20.877 -0.875 20.931 -0.632 20.931 -0.309 c
+h
+21.77 0 m
+21.77 0.43 21.872 0.771 22.078 1.029 c
+22.292 1.282 22.57 1.411 22.916 1.411 c
+23.258 1.411 23.534 1.282 23.74 1.029 c
+23.952 0.783 24.066 0.449 24.077 0.029 c
+24.077 -0.279 l
+24.077 -0.713 23.967 -1.055 23.754 -1.309 c
+23.549 -1.565 23.269 -1.691 22.916 -1.691 c
+22.57 -1.691 22.298 -1.569 22.093 -1.323 c
+21.887 -1.08 21.777 -0.746 21.77 -0.324 c
+h
+22.255 -0.279 m
+22.255 -0.595 22.313 -0.838 22.431 -1.014 c
+22.556 -1.183 22.718 -1.264 22.916 -1.264 c
+23.346 -1.264 23.57 -0.956 23.592 -0.338 c
+23.592 0 l
+23.592 0.301 23.526 0.544 23.401 0.721 c
+23.283 0.897 23.121 0.985 22.916 0.985 c
+22.718 0.985 22.556 0.897 22.431 0.721 c
+22.313 0.544 22.255 0.301 22.255 0 c
+h
+26.664 -0.279 m
+26.664 -0.75 26.58 -1.103 26.414 -1.338 c
+26.246 -1.573 26.007 -1.691 25.694 -1.691 c
+25.39 -1.691 25.157 -1.58 25.003 -1.352 c
+25.003 -2.778 l
+24.519 -2.778 l
+24.519 1.353 l
+24.96 1.353 l
+24.989 1.014 l
+25.143 1.278 25.375 1.411 25.679 1.411 c
+26.011 1.411 26.256 1.294 26.414 1.058 c
+26.58 0.831 26.664 0.492 26.664 0.044 c
+h
+26.179 0 m
+26.179 0.331 26.124 0.577 26.018 0.735 c
+25.918 0.889 25.757 0.97 25.533 0.97 c
+25.297 0.97 25.121 0.852 25.003 0.617 c
+25.003 -0.926 l
+25.121 -1.154 25.301 -1.264 25.548 -1.264 c
+25.76 -1.264 25.918 -1.187 26.018 -1.029 c
+26.124 -0.875 26.179 -0.632 26.179 -0.309 c
+h
+f
+Q
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 619.5765 272.9739 cm
+0 0 m
+6.644 -3.018 14.244 -5.796 25.808 -5.322 c
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 643.2534 267.5639 cm
+0 0 m
+-1.022 -1.11 l
+2.664 0.111 l
+-1.11 1.026 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 643.2535 267.5639 cm
+0 0 m
+-1.022 -1.11 l
+2.664 0.111 l
+-1.11 1.026 l
+0 0 l
+h
+S
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 664.6398 301.7215 cm
+0 0 m
+0 0.459 0.081 0.808 0.25 1.043 c
+0.427 1.286 0.676 1.411 1 1.411 c
+1.301 1.411 1.532 1.278 1.69 1.014 c
+1.721 1.352 l
+2.161 1.352 l
+2.161 -1.661 l
+2.161 -2.032 2.062 -2.315 1.867 -2.514 c
+1.68 -2.708 1.419 -2.808 1.088 -2.808 c
+0.941 -2.808 0.772 -2.768 0.588 -2.691 c
+0.401 -2.62 0.265 -2.533 0.177 -2.425 c
+0.368 -2.087 l
+0.574 -2.294 0.798 -2.396 1.044 -2.396 c
+1.445 -2.396 1.65 -2.168 1.661 -1.72 c
+1.661 -1.338 l
+1.503 -1.573 1.283 -1.691 1 -1.691 c
+0.684 -1.691 0.441 -1.573 0.265 -1.338 c
+0.096 -1.103 0.008 -0.772 0 -0.339 c
+h
+0.485 -0.279 m
+0.485 -0.614 0.533 -0.86 0.632 -1.014 c
+0.728 -1.172 0.89 -1.249 1.118 -1.249 c
+1.36 -1.249 1.544 -1.129 1.661 -0.882 c
+1.661 0.602 l
+1.544 0.845 1.368 0.97 1.133 0.97 c
+0.904 0.97 0.742 0.889 0.647 0.735 c
+0.548 0.577 0.493 0.338 0.485 0.014 c
+h
+3.227 -1.632 -0.499 2.984 re
+3.256 2.146 m
+3.256 2.057 3.231 1.984 3.182 1.926 c
+3.142 1.874 3.072 1.851 2.977 1.851 c
+2.889 1.851 2.819 1.874 2.771 1.926 c
+2.731 1.984 2.712 2.05 2.712 2.131 c
+2.712 2.219 2.731 2.293 2.771 2.352 c
+2.819 2.41 2.889 2.439 2.977 2.439 c
+3.072 2.439 3.142 2.41 3.182 2.352 c
+3.231 2.293 3.256 2.223 3.256 2.146 c
+4.532 2.072 m
+4.532 1.352 l
+4.987 1.352 l
+4.987 0.955 l
+4.532 0.955 l
+4.532 -0.897 l
+4.532 -1.014 4.549 -1.103 4.59 -1.162 c
+4.627 -1.22 4.697 -1.249 4.796 -1.249 c
+4.855 -1.249 4.917 -1.243 4.987 -1.22 c
+4.987 -1.632 l
+4.869 -1.669 4.755 -1.691 4.649 -1.691 c
+4.451 -1.691 4.3 -1.625 4.193 -1.484 c
+4.094 -1.349 4.046 -1.154 4.046 -0.897 c
+4.046 0.955 l
+3.591 0.955 l
+3.591 1.352 l
+4.046 1.352 l
+4.046 2.072 l
+h
+7.894 0.897 m
+7.824 0.904 7.751 0.911 7.674 0.911 c
+7.416 0.911 7.24 0.771 7.144 0.5 c
+7.144 -1.632 l
+6.66 -1.632 l
+6.66 1.352 l
+7.13 1.352 l
+7.144 1.043 l
+7.269 1.286 7.453 1.411 7.688 1.411 c
+7.765 1.411 7.828 1.396 7.879 1.367 c
+h
+9.272 -1.691 m
+8.897 -1.691 8.614 -1.584 8.42 -1.367 c
+8.221 -1.143 8.125 -0.817 8.125 -0.383 c
+8.125 -0.015 l
+8.125 0.426 8.217 0.771 8.405 1.028 c
+8.599 1.282 8.875 1.411 9.228 1.411 c
+9.569 1.411 9.823 1.297 9.992 1.072 c
+10.168 0.845 10.261 0.5 10.271 0.029 c
+10.271 -0.279 l
+8.611 -0.279 l
+8.611 -0.353 l
+8.611 -0.676 8.669 -0.912 8.786 -1.058 c
+8.904 -1.199 9.073 -1.264 9.301 -1.264 c
+9.448 -1.264 9.573 -1.243 9.683 -1.191 c
+9.79 -1.132 9.893 -1.044 9.992 -0.927 c
+10.242 -1.235 l
+10.036 -1.54 9.713 -1.691 9.272 -1.691 c
+9.228 0.985 m
+9.022 0.985 8.867 0.914 8.772 0.779 c
+8.673 0.639 8.618 0.426 8.611 0.132 c
+9.786 0.132 l
+9.786 0.205 l
+9.764 0.477 9.713 0.675 9.625 0.793 c
+9.536 0.918 9.405 0.985 9.228 0.985 c
+12.123 -0.867 m
+12.123 -0.761 12.083 -0.673 12.006 -0.603 c
+11.925 -0.526 11.774 -0.437 11.55 -0.339 c
+11.286 -0.231 11.098 -0.14 10.992 -0.059 c
+10.882 0.018 10.804 0.106 10.756 0.205 c
+10.705 0.301 10.683 0.419 10.683 0.558 c
+10.683 0.801 10.771 1.003 10.947 1.161 c
+11.124 1.326 11.348 1.411 11.624 1.411 c
+11.917 1.411 12.152 1.323 12.329 1.146 c
+12.505 0.977 12.594 0.764 12.594 0.5 c
+12.108 0.5 l
+12.108 0.635 12.057 0.75 11.961 0.837 c
+11.873 0.933 11.759 0.985 11.624 0.985 c
+11.477 0.985 11.363 0.944 11.286 0.867 c
+11.205 0.797 11.168 0.698 11.168 0.573 c
+11.168 0.474 11.198 0.397 11.256 0.338 c
+11.315 0.279 11.454 0.198 11.682 0.103 c
+12.042 -0.044 12.289 -0.188 12.418 -0.324 c
+12.553 -0.453 12.623 -0.625 12.623 -0.838 c
+12.623 -1.095 12.528 -1.301 12.343 -1.455 c
+12.168 -1.613 11.932 -1.691 11.638 -1.691 c
+11.323 -1.691 11.069 -1.602 10.874 -1.426 c
+10.687 -1.243 10.595 -1.011 10.595 -0.736 c
+11.08 -0.736 l
+11.088 -0.904 11.138 -1.037 11.227 -1.132 c
+11.323 -1.22 11.462 -1.264 11.638 -1.264 c
+11.793 -1.264 11.911 -1.231 11.992 -1.162 c
+12.079 -1.095 12.123 -0.996 12.123 -0.867 c
+14.137 -1.691 m
+13.762 -1.691 13.48 -1.584 13.284 -1.367 c
+13.087 -1.143 12.991 -0.817 12.991 -0.383 c
+12.991 -0.015 l
+12.991 0.426 13.083 0.771 13.27 1.028 c
+13.465 1.282 13.74 1.411 14.093 1.411 c
+14.435 1.411 14.689 1.297 14.857 1.072 c
+15.034 0.845 15.126 0.5 15.137 0.029 c
+15.137 -0.279 l
+13.476 -0.279 l
+13.476 -0.353 l
+13.476 -0.676 13.534 -0.912 13.652 -1.058 c
+13.77 -1.199 13.939 -1.264 14.167 -1.264 c
+14.313 -1.264 14.438 -1.243 14.549 -1.191 c
+14.656 -1.132 14.758 -1.044 14.857 -0.927 c
+15.107 -1.235 l
+14.901 -1.54 14.579 -1.691 14.137 -1.691 c
+14.093 0.985 m
+13.887 0.985 13.733 0.914 13.638 0.779 c
+13.538 0.639 13.483 0.426 13.476 0.132 c
+14.652 0.132 l
+14.652 0.205 l
+14.629 0.477 14.579 0.675 14.49 0.793 c
+14.402 0.918 14.269 0.985 14.093 0.985 c
+16.181 2.072 m
+16.181 1.352 l
+16.636 1.352 l
+16.636 0.955 l
+16.181 0.955 l
+16.181 -0.897 l
+16.181 -1.014 16.199 -1.103 16.239 -1.162 c
+16.276 -1.22 16.345 -1.249 16.445 -1.249 c
+16.503 -1.249 16.566 -1.243 16.636 -1.22 c
+16.636 -1.632 l
+16.518 -1.669 16.405 -1.691 16.298 -1.691 c
+16.1 -1.691 15.949 -1.625 15.842 -1.484 c
+15.743 -1.349 15.695 -1.154 15.695 -0.897 c
+15.695 0.955 l
+15.24 0.955 l
+15.24 1.352 l
+15.695 1.352 l
+15.695 2.072 l
+h
+20.995 -1.632 m
+20.495 -1.632 l
+20.495 0.22 l
+18.878 0.22 l
+18.878 -1.632 l
+18.363 -1.632 l
+18.363 2.381 l
+18.878 2.381 l
+18.878 0.661 l
+20.495 0.661 l
+20.495 2.381 l
+20.995 2.381 l
+h
+23.563 0.22 m
+22.152 0.22 l
+22.152 -1.206 l
+23.798 -1.206 l
+23.798 -1.632 l
+21.637 -1.632 l
+21.637 2.381 l
+23.769 2.381 l
+23.769 1.94 l
+22.152 1.94 l
+22.152 0.661 l
+23.563 0.661 l
+h
+26.132 -0.588 m
+24.779 -0.588 l
+24.456 -1.632 l
+23.942 -1.632 l
+25.235 2.381 l
+25.661 2.381 l
+26.969 -1.632 l
+26.44 -1.632 l
+h
+24.912 -0.148 m
+25.999 -0.148 l
+25.455 1.675 l
+h
+27.285 -1.632 m
+27.285 2.381 l
+28.256 2.381 l
+28.715 2.381 29.072 2.234 29.328 1.94 c
+29.593 1.646 29.725 1.234 29.725 0.706 c
+29.725 0.029 l
+29.725 -0.5 29.593 -0.912 29.328 -1.206 c
+29.072 -1.492 28.696 -1.632 28.197 -1.632 c
+h
+27.8 1.94 m
+27.8 -1.206 l
+28.197 -1.206 l
+28.557 -1.206 28.818 -1.103 28.976 -0.897 c
+29.141 -0.691 29.226 -0.389 29.226 0.014 c
+29.226 0.72 l
+29.226 1.139 29.141 1.448 28.976 1.646 c
+28.818 1.841 28.579 1.94 28.256 1.94 c
+h
+f
+Q
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 700.2778 300.817 cm
+0 0 m
+-10.796 -4.575 -16.874 -12.02 -16.76 -23.684 c
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 683.4952 279.2684 cm
+0 0 m
+-1.077 1.055 l
+0.026 -2.668 l
+1.059 1.077 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 683.4952 279.2684 cm
+0 0 m
+-1.077 1.055 l
+0.026 -2.668 l
+1.059 1.077 l
+0 0 l
+h
+S
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 702.545 271.8379 cm
+0 0 m
+0 0.459 0.081 0.808 0.25 1.043 c
+0.427 1.286 0.676 1.411 1 1.411 c
+1.301 1.411 1.532 1.278 1.69 1.014 c
+1.72 1.353 l
+2.161 1.353 l
+2.161 -1.661 l
+2.161 -2.032 2.062 -2.315 1.867 -2.514 c
+1.68 -2.708 1.419 -2.807 1.088 -2.807 c
+0.941 -2.807 0.772 -2.767 0.588 -2.69 c
+0.401 -2.62 0.265 -2.532 0.177 -2.425 c
+0.368 -2.087 l
+0.574 -2.293 0.798 -2.396 1.044 -2.396 c
+1.445 -2.396 1.65 -2.168 1.661 -1.72 c
+1.661 -1.338 l
+1.503 -1.573 1.283 -1.69 1 -1.69 c
+0.684 -1.69 0.441 -1.573 0.265 -1.338 c
+0.096 -1.103 0.008 -0.771 0 -0.338 c
+h
+0.485 -0.279 m
+0.485 -0.613 0.533 -0.86 0.632 -1.014 c
+0.728 -1.172 0.89 -1.249 1.118 -1.249 c
+1.36 -1.249 1.544 -1.128 1.661 -0.881 c
+1.661 0.603 l
+1.544 0.845 1.368 0.97 1.133 0.97 c
+0.904 0.97 0.742 0.889 0.647 0.735 c
+0.547 0.577 0.493 0.338 0.485 0.015 c
+h
+3.223 -1.631 -0.5 2.984 re
+3.252 2.146 m
+3.252 2.058 3.227 1.984 3.179 1.926 c
+3.138 1.874 3.069 1.852 2.974 1.852 c
+2.885 1.852 2.816 1.874 2.768 1.926 c
+2.727 1.984 2.708 2.051 2.708 2.132 c
+2.708 2.219 2.727 2.294 2.768 2.352 c
+2.816 2.411 2.885 2.44 2.974 2.44 c
+3.069 2.44 3.138 2.411 3.179 2.352 c
+3.227 2.294 3.252 2.223 3.252 2.146 c
+4.532 2.072 m
+4.532 1.353 l
+4.987 1.353 l
+4.987 0.956 l
+4.532 0.956 l
+4.532 -0.897 l
+4.532 -1.014 4.549 -1.103 4.59 -1.161 c
+4.627 -1.22 4.697 -1.249 4.796 -1.249 c
+4.855 -1.249 4.917 -1.242 4.987 -1.22 c
+4.987 -1.631 l
+4.869 -1.668 4.755 -1.69 4.649 -1.69 c
+4.451 -1.69 4.3 -1.625 4.193 -1.484 c
+4.094 -1.349 4.046 -1.154 4.046 -0.897 c
+4.046 0.956 l
+3.591 0.956 l
+3.591 1.353 l
+4.046 1.353 l
+4.046 2.072 l
+h
+8.184 -1.631 m
+8.154 -1.565 8.133 -1.455 8.125 -1.309 c
+7.949 -1.565 7.728 -1.69 7.464 -1.69 c
+7.188 -1.69 6.972 -1.617 6.817 -1.469 c
+6.67 -1.315 6.596 -1.099 6.596 -0.823 c
+6.596 -0.522 6.699 -0.279 6.905 -0.103 c
+7.111 0.081 7.394 0.177 7.757 0.177 c
+8.11 0.177 l
+8.11 0.5 l
+8.11 0.676 8.07 0.798 7.992 0.867 c
+7.913 0.945 7.795 0.985 7.64 0.985 c
+7.493 0.985 7.368 0.941 7.273 0.852 c
+7.184 0.765 7.14 0.654 7.14 0.53 c
+6.656 0.53 l
+6.656 0.676 6.699 0.816 6.787 0.956 c
+6.876 1.103 6.993 1.213 7.14 1.294 c
+7.294 1.371 7.468 1.411 7.655 1.411 c
+7.967 1.411 8.202 1.33 8.36 1.176 c
+8.515 1.029 8.596 0.808 8.596 0.515 c
+8.596 -0.985 l
+8.603 -1.22 8.64 -1.422 8.698 -1.587 c
+8.698 -1.631 l
+h
+7.537 -1.249 m
+7.655 -1.249 7.765 -1.216 7.875 -1.147 c
+7.982 -1.08 8.059 -0.996 8.11 -0.897 c
+8.11 -0.191 l
+7.846 -0.191 l
+7.611 -0.191 7.423 -0.243 7.287 -0.338 c
+7.159 -0.437 7.096 -0.58 7.096 -0.764 c
+7.096 -0.933 7.126 -1.055 7.184 -1.132 c
+7.25 -1.213 7.368 -1.249 7.537 -1.249 c
+9.073 0 m
+9.073 0.459 9.154 0.808 9.324 1.043 c
+9.5 1.286 9.75 1.411 10.073 1.411 c
+10.356 1.411 10.577 1.294 10.735 1.058 c
+10.735 2.602 l
+11.219 2.602 l
+11.219 -1.631 l
+10.778 -1.631 l
+10.749 -1.309 l
+10.591 -1.565 10.367 -1.69 10.073 -1.69 c
+9.756 -1.69 9.515 -1.573 9.338 -1.338 c
+9.162 -1.095 9.073 -0.75 9.073 -0.309 c
+h
+9.559 -0.279 m
+9.559 -0.613 9.606 -0.86 9.706 -1.014 c
+9.801 -1.172 9.962 -1.249 10.19 -1.249 c
+10.433 -1.249 10.617 -1.132 10.735 -0.897 c
+10.735 0.617 l
+10.606 0.852 10.425 0.97 10.19 0.97 c
+9.962 0.97 9.801 0.889 9.706 0.735 c
+9.606 0.577 9.559 0.338 9.559 0.015 c
+h
+11.69 0 m
+11.69 0.459 11.771 0.808 11.94 1.043 c
+12.116 1.286 12.366 1.411 12.69 1.411 c
+12.972 1.411 13.193 1.294 13.351 1.058 c
+13.351 2.602 l
+13.835 2.602 l
+13.835 -1.631 l
+13.395 -1.631 l
+13.365 -1.309 l
+13.207 -1.565 12.983 -1.69 12.69 -1.69 c
+12.374 -1.69 12.131 -1.573 11.954 -1.338 c
+11.778 -1.095 11.69 -0.75 11.69 -0.309 c
+h
+12.175 -0.279 m
+12.175 -0.613 12.223 -0.86 12.322 -1.014 c
+12.418 -1.172 12.579 -1.249 12.807 -1.249 c
+13.049 -1.249 13.233 -1.132 13.351 -0.897 c
+13.351 0.617 l
+13.222 0.852 13.042 0.97 12.807 0.97 c
+12.579 0.97 12.418 0.889 12.322 0.735 c
+12.223 0.577 12.175 0.338 12.175 0.015 c
+h
+f
+Q
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 693.4612 270.8827 cm
+0 0 m
+10.797 4.571 16.875 12.016 16.764 23.68 c
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 710.2439 292.4276 cm
+0 0 m
+1.077 -1.055 l
+-0.025 2.668 l
+-1.055 -1.077 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 710.244 292.4276 cm
+0 0 m
+1.077 -1.055 l
+-0.025 2.668 l
+-1.055 -1.077 l
+0 0 l
+h
+S
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm7 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm8 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm9 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm10 Do
+Q
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 745.1474 289.2892 cm
+0 0 m
+-3.205 6.184 l
+S
+Q
+q 1 0 0 1 742.9236 293.5782 cm
+0 0 m
+1.437 -0.456 l
+-1.228 2.37 l
+-0.456 -1.438 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 742.9237 293.5782 cm
+0 0 m
+1.437 -0.456 l
+-1.228 2.37 l
+-0.456 -1.438 l
+0 0 l
+h
+S
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 711.5555 341.2288 cm
+0 0 m
+0 0.459 0.081 0.808 0.25 1.043 c
+0.427 1.286 0.676 1.411 1 1.411 c
+1.301 1.411 1.532 1.278 1.69 1.014 c
+1.721 1.352 l
+2.161 1.352 l
+2.161 -1.661 l
+2.161 -2.032 2.062 -2.315 1.867 -2.514 c
+1.68 -2.708 1.419 -2.808 1.088 -2.808 c
+0.941 -2.808 0.772 -2.768 0.589 -2.691 c
+0.401 -2.62 0.265 -2.533 0.177 -2.425 c
+0.368 -2.087 l
+0.574 -2.294 0.798 -2.396 1.044 -2.396 c
+1.445 -2.396 1.65 -2.168 1.661 -1.72 c
+1.661 -1.338 l
+1.503 -1.573 1.283 -1.691 1 -1.691 c
+0.684 -1.691 0.441 -1.573 0.265 -1.338 c
+0.096 -1.103 0.008 -0.772 0 -0.339 c
+h
+0.485 -0.279 m
+0.485 -0.614 0.533 -0.86 0.632 -1.014 c
+0.728 -1.172 0.89 -1.249 1.118 -1.249 c
+1.36 -1.249 1.544 -1.128 1.661 -0.882 c
+1.661 0.602 l
+1.544 0.845 1.368 0.97 1.133 0.97 c
+0.904 0.97 0.743 0.889 0.647 0.735 c
+0.548 0.577 0.493 0.338 0.485 0.014 c
+h
+3.223 -1.632 -0.5 2.984 re
+3.253 2.146 m
+3.253 2.057 3.227 1.984 3.179 1.926 c
+3.138 1.874 3.069 1.852 2.974 1.852 c
+2.885 1.852 2.816 1.874 2.768 1.926 c
+2.727 1.984 2.708 2.05 2.708 2.131 c
+2.708 2.219 2.727 2.293 2.768 2.352 c
+2.816 2.41 2.885 2.44 2.974 2.44 c
+3.069 2.44 3.138 2.41 3.179 2.352 c
+3.227 2.293 3.253 2.223 3.253 2.146 c
+4.532 2.072 m
+4.532 1.352 l
+4.987 1.352 l
+4.987 0.955 l
+4.532 0.955 l
+4.532 -0.897 l
+4.532 -1.014 4.549 -1.103 4.59 -1.162 c
+4.627 -1.22 4.697 -1.249 4.796 -1.249 c
+4.855 -1.249 4.917 -1.243 4.987 -1.22 c
+4.987 -1.632 l
+4.869 -1.669 4.755 -1.691 4.649 -1.691 c
+4.451 -1.691 4.3 -1.625 4.194 -1.484 c
+4.094 -1.349 4.046 -1.154 4.046 -0.897 c
+4.046 0.955 l
+3.591 0.955 l
+3.591 1.352 l
+4.046 1.352 l
+4.046 2.072 l
+h
+7.684 -1.264 m
+7.849 -1.264 7.982 -1.216 8.081 -1.118 c
+8.177 -1.022 8.231 -0.879 8.243 -0.691 c
+8.699 -0.691 l
+8.688 -0.977 8.585 -1.216 8.389 -1.411 c
+8.202 -1.598 7.967 -1.691 7.684 -1.691 c
+7.321 -1.691 7.041 -1.573 6.847 -1.338 c
+6.648 -1.103 6.552 -0.757 6.552 -0.294 c
+6.552 0.029 l
+6.552 0.478 6.644 0.823 6.832 1.058 c
+7.026 1.294 7.31 1.411 7.684 1.411 c
+7.986 1.411 8.229 1.311 8.404 1.117 c
+8.588 0.918 8.688 0.654 8.699 0.324 c
+8.243 0.324 l
+8.221 0.548 8.162 0.713 8.067 0.823 c
+7.978 0.929 7.849 0.985 7.684 0.985 c
+7.468 0.985 7.306 0.912 7.199 0.764 c
+7.1 0.625 7.045 0.397 7.038 0.073 c
+7.038 -0.309 l
+7.038 -0.661 7.086 -0.912 7.184 -1.058 c
+7.291 -1.199 7.456 -1.264 7.684 -1.264 c
+8.992 0 m
+8.992 0.43 9.095 0.771 9.301 1.029 c
+9.515 1.282 9.794 1.411 10.139 1.411 c
+10.481 1.411 10.756 1.282 10.962 1.029 c
+11.175 0.783 11.289 0.448 11.3 0.029 c
+11.3 -0.279 l
+11.3 -0.713 11.19 -1.055 10.977 -1.309 c
+10.771 -1.565 10.492 -1.691 10.139 -1.691 c
+9.794 -1.691 9.522 -1.569 9.316 -1.323 c
+9.11 -1.081 9 -0.746 8.992 -0.324 c
+h
+9.478 -0.279 m
+9.478 -0.595 9.536 -0.838 9.654 -1.014 c
+9.779 -1.183 9.941 -1.264 10.139 -1.264 c
+10.569 -1.264 10.793 -0.956 10.816 -0.339 c
+10.816 0 l
+10.816 0.301 10.749 0.544 10.624 0.72 c
+10.506 0.897 10.345 0.985 10.139 0.985 c
+9.941 0.985 9.779 0.897 9.654 0.72 c
+9.536 0.544 9.478 0.301 9.478 0 c
+h
+12.197 1.352 m
+12.212 1.072 l
+12.388 1.297 12.627 1.411 12.932 1.411 c
+13.263 1.411 13.494 1.264 13.623 0.97 c
+13.806 1.264 14.068 1.411 14.402 1.411 c
+14.961 1.411 15.244 1.066 15.254 0.382 c
+15.254 -1.632 l
+14.77 -1.632 l
+14.77 0.338 l
+14.77 0.551 14.729 0.709 14.652 0.808 c
+14.571 0.914 14.438 0.97 14.255 0.97 c
+14.108 0.97 13.991 0.912 13.902 0.794 c
+13.814 0.683 13.759 0.544 13.74 0.367 c
+13.74 -1.632 l
+13.255 -1.632 l
+13.255 0.353 l
+13.245 0.764 13.072 0.97 12.74 0.97 c
+12.495 0.97 12.322 0.845 12.227 0.602 c
+12.227 -1.632 l
+11.741 -1.632 l
+11.741 1.352 l
+h
+16.158 1.352 m
+16.173 1.072 l
+16.349 1.297 16.588 1.411 16.894 1.411 c
+17.224 1.411 17.455 1.264 17.584 0.97 c
+17.768 1.264 18.029 1.411 18.363 1.411 c
+18.922 1.411 19.205 1.066 19.216 0.382 c
+19.216 -1.632 l
+18.731 -1.632 l
+18.731 0.338 l
+18.731 0.551 18.691 0.709 18.613 0.808 c
+18.533 0.914 18.4 0.97 18.216 0.97 c
+18.07 0.97 17.952 0.912 17.864 0.794 c
+17.775 0.683 17.72 0.544 17.702 0.367 c
+17.702 -1.632 l
+17.216 -1.632 l
+17.216 0.353 l
+17.206 0.764 17.033 0.97 16.702 0.97 c
+16.456 0.97 16.283 0.845 16.188 0.602 c
+16.188 -1.632 l
+15.703 -1.632 l
+15.703 1.352 l
+h
+20.193 -1.632 -0.5 2.984 re
+20.223 2.146 m
+20.223 2.057 20.197 1.984 20.149 1.926 c
+20.109 1.874 20.039 1.852 19.944 1.852 c
+19.855 1.852 19.786 1.874 19.738 1.926 c
+19.697 1.984 19.678 2.05 19.678 2.131 c
+19.678 2.219 19.697 2.293 19.738 2.352 c
+19.786 2.41 19.855 2.44 19.944 2.44 c
+20.039 2.44 20.109 2.41 20.149 2.352 c
+20.197 2.293 20.223 2.223 20.223 2.146 c
+21.498 2.072 m
+21.498 1.352 l
+21.953 1.352 l
+21.953 0.955 l
+21.498 0.955 l
+21.498 -0.897 l
+21.498 -1.014 21.517 -1.103 21.557 -1.162 c
+21.594 -1.22 21.663 -1.249 21.762 -1.249 c
+21.821 -1.249 21.883 -1.243 21.953 -1.22 c
+21.953 -1.632 l
+21.836 -1.669 21.722 -1.691 21.615 -1.691 c
+21.417 -1.691 21.266 -1.625 21.16 -1.484 c
+21.06 -1.349 21.012 -1.154 21.012 -0.897 c
+21.012 0.955 l
+20.557 0.955 l
+20.557 1.352 l
+21.012 1.352 l
+21.012 2.072 l
+h
+f
+Q
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 715.6204 326.614 cm
+0 0 m
+-4.572 10.797 -12.017 16.875 -23.68 16.764 c
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 694.071 343.3966 cm
+0 0 m
+1.059 1.077 l
+-2.664 -0.025 l
+1.077 -1.055 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 694.071 343.3966 cm
+0 0 m
+1.059 1.077 l
+-2.664 -0.025 l
+1.077 -1.055 l
+0 0 l
+h
+S
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm11 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm12 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm13 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm14 Do
+Q
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 634.5146 329.9282 cm
+0 0 m
+5.074 5.056 l
+S
+Q
+q 1 0 0 1 638.0789 333.4787 cm
+0 0 m
+-0.004 -1.507 l
+1.889 1.882 l
+-1.506 0.003 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 638.0789 333.4787 cm
+0 0 m
+-0.004 -1.507 l
+1.889 1.882 l
+-1.506 0.003 l
+0 0 l
+h
+S
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS4 gs
+0 TL/Fm15 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS5 gs
+0 TL/Fm16 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS5 gs
+0 TL/Fm17 Do
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 563.3862 425.8473 cm
+0 0 m
+54.018 0 l
+56.624 0 58.722 -2.098 58.722 -4.704 c
+58.722 -21.406 l
+58.722 -24.01 56.624 -26.109 54.018 -26.109 c
+0 -26.109 l
+-2.606 -26.109 -4.701 -24.01 -4.701 -21.406 c
+-4.701 -4.704 l
+-4.701 -2.098 -2.606 0 0 0 c
+f
+Q
+0 0 0 0 k
+q 1 0 0 1 570.5405 419.8831 cm
+0 0 m
+-0.426 0.029 l
+-0.79 0.029 -1.029 -0.129 -1.147 -0.441 c
+-1.147 -3.719 l
+-2.454 -3.719 l
+-2.454 1.249 l
+-1.234 1.249 l
+-1.191 0.721 l
+-0.985 1.132 -0.702 1.338 -0.338 1.338 c
+-0.191 1.338 -0.073 1.316 0.015 1.279 c
+h
+2.469 -3.807 m
+1.801 -3.807 1.278 -3.612 0.896 -3.219 c
+0.522 -2.818 0.338 -2.246 0.338 -1.5 c
+0.338 -1.103 l
+0.338 -0.32 0.507 0.283 0.852 0.706 c
+1.195 1.124 1.69 1.338 2.337 1.338 c
+2.955 1.338 3.418 1.135 3.734 0.735 c
+4.057 0.341 4.218 -0.247 4.218 -1.029 c
+4.218 -1.675 l
+1.646 -1.675 l
+1.654 -2.04 1.735 -2.308 1.881 -2.484 c
+2.028 -2.653 2.249 -2.734 2.543 -2.734 c
+2.984 -2.734 3.344 -2.583 3.63 -2.279 c
+4.145 -3.072 l
+3.987 -3.289 3.755 -3.465 3.454 -3.601 c
+3.15 -3.738 2.822 -3.807 2.469 -3.807 c
+1.646 -0.764 m
+2.955 -0.764 l
+2.955 -0.646 l
+2.944 -0.345 2.888 -0.118 2.793 0.029 c
+2.705 0.183 2.547 0.264 2.323 0.264 c
+2.095 0.264 1.929 0.181 1.823 0.015 c
+1.723 -0.143 1.665 -0.405 1.646 -0.764 c
+5.997 1.249 m
+6.041 0.794 l
+6.335 1.154 6.718 1.338 7.188 1.338 c
+7.688 1.338 8.04 1.118 8.246 0.676 c
+8.529 1.118 8.937 1.338 9.467 1.338 c
+10.326 1.338 10.774 0.738 10.803 -0.455 c
+10.803 -3.719 l
+9.496 -3.719 l
+9.496 -0.544 l
+9.496 -0.261 9.455 -0.058 9.378 0.059 c
+9.297 0.183 9.165 0.25 8.981 0.25 c
+8.735 0.25 8.555 0.103 8.437 -0.191 c
+8.437 -3.719 l
+7.144 -3.719 l
+7.144 -0.559 l
+7.144 -0.276 7.104 -0.07 7.026 0.059 c
+6.945 0.183 6.809 0.25 6.614 0.25 c
+6.387 0.25 6.211 0.133 6.086 -0.103 c
+6.086 -3.719 l
+4.792 -3.719 l
+4.792 1.249 l
+h
+11.333 -1.072 m
+11.333 -0.32 11.509 0.268 11.862 0.691 c
+12.215 1.121 12.704 1.338 13.332 1.338 c
+13.968 1.338 14.464 1.121 14.817 0.691 c
+15.177 0.268 15.36 -0.324 15.36 -1.088 c
+15.36 -1.396 l
+15.36 -2.153 15.184 -2.745 14.832 -3.175 c
+14.479 -3.597 13.982 -3.807 13.347 -3.807 c
+12.707 -3.807 12.215 -3.597 11.862 -3.175 c
+11.509 -2.745 11.333 -2.153 11.333 -1.396 c
+h
+12.642 -1.396 m
+12.642 -2.289 12.877 -2.734 13.347 -2.734 c
+13.787 -2.734 14.023 -2.363 14.053 -1.617 c
+14.067 -1.072 l
+14.067 -0.625 14.001 -0.29 13.876 -0.073 c
+13.747 0.15 13.567 0.264 13.332 0.264 c
+13.115 0.264 12.943 0.15 12.818 -0.073 c
+12.7 -0.29 12.642 -0.625 12.642 -1.072 c
+h
+17.492 2.469 m
+17.492 1.249 l
+18.153 1.249 l
+18.153 0.279 l
+17.492 0.279 l
+17.492 -2.19 l
+17.492 -2.389 17.514 -2.524 17.565 -2.601 c
+17.624 -2.672 17.731 -2.705 17.889 -2.705 c
+18.007 -2.705 18.109 -2.697 18.198 -2.676 c
+18.183 -3.69 l
+17.955 -3.767 17.716 -3.807 17.463 -3.807 c
+16.628 -3.807 16.206 -3.329 16.199 -2.366 c
+16.199 0.279 l
+15.625 0.279 l
+15.625 1.249 l
+16.199 1.249 l
+16.199 2.469 l
+h
+20.762 -3.807 m
+20.093 -3.807 19.572 -3.612 19.189 -3.219 c
+18.815 -2.818 18.631 -2.246 18.631 -1.5 c
+18.631 -1.103 l
+18.631 -0.32 18.8 0.283 19.146 0.706 c
+19.487 1.124 19.983 1.338 20.63 1.338 c
+21.247 1.338 21.71 1.135 22.026 0.735 c
+22.35 0.341 22.512 -0.247 22.512 -1.029 c
+22.512 -1.675 l
+19.939 -1.675 l
+19.946 -2.04 20.027 -2.308 20.174 -2.484 c
+20.322 -2.653 20.542 -2.734 20.835 -2.734 c
+21.277 -2.734 21.637 -2.583 21.924 -2.279 c
+22.438 -3.072 l
+22.28 -3.289 22.049 -3.465 21.747 -3.601 c
+21.442 -3.738 21.115 -3.807 20.762 -3.807 c
+19.939 -0.764 m
+21.247 -0.764 l
+21.247 -0.646 l
+21.236 -0.345 21.182 -0.118 21.086 0.029 c
+20.997 0.183 20.839 0.264 20.615 0.264 c
+20.388 0.264 20.222 0.181 20.116 0.015 c
+20.016 -0.143 19.958 -0.405 19.939 -0.764 c
+27.605 0 m
+27.179 0.029 l
+26.815 0.029 26.576 -0.129 26.458 -0.441 c
+26.458 -3.719 l
+25.15 -3.719 l
+25.15 1.249 l
+26.37 1.249 l
+26.414 0.721 l
+26.62 1.132 26.903 1.338 27.266 1.338 c
+27.414 1.338 27.532 1.316 27.619 1.279 c
+h
+30.074 -3.807 m
+29.406 -3.807 28.883 -3.612 28.502 -3.219 c
+28.126 -2.818 27.943 -2.246 27.943 -1.5 c
+27.943 -1.103 l
+27.943 -0.32 28.112 0.283 28.457 0.706 c
+28.799 1.124 29.296 1.338 29.942 1.338 c
+30.559 1.338 31.023 1.135 31.339 0.735 c
+31.661 0.341 31.823 -0.247 31.823 -1.029 c
+31.823 -1.675 l
+29.251 -1.675 l
+29.259 -2.04 29.34 -2.308 29.487 -2.484 c
+29.633 -2.653 29.853 -2.734 30.148 -2.734 c
+30.589 -2.734 30.948 -2.583 31.235 -2.279 c
+31.75 -3.072 l
+31.592 -3.289 31.36 -3.465 31.059 -3.601 c
+30.754 -3.738 30.427 -3.807 30.074 -3.807 c
+29.251 -0.764 m
+30.559 -0.764 l
+30.559 -0.646 l
+30.549 -0.345 30.493 -0.118 30.398 0.029 c
+30.31 0.183 30.152 0.264 29.928 0.264 c
+29.699 0.264 29.534 0.181 29.427 0.015 c
+29.328 -0.143 29.269 -0.405 29.251 -0.764 c
+36.263 -1.396 m
+36.263 -2.171 36.122 -2.771 35.851 -3.189 c
+35.586 -3.601 35.189 -3.807 34.661 -3.807 c
+34.256 -3.807 33.932 -3.645 33.691 -3.322 c
+33.691 -5.629 l
+32.382 -5.629 l
+32.382 1.249 l
+33.587 1.249 l
+33.631 0.794 l
+33.885 1.154 34.223 1.338 34.646 1.338 c
+35.175 1.338 35.572 1.147 35.836 0.765 c
+36.108 0.382 36.251 -0.213 36.263 -1.014 c
+h
+34.969 -1.058 m
+34.969 -0.58 34.914 -0.243 34.807 -0.044 c
+34.697 0.15 34.517 0.25 34.264 0.25 c
+33.999 0.25 33.808 0.14 33.691 -0.073 c
+33.691 -2.41 l
+33.808 -2.628 34.003 -2.734 34.279 -2.734 c
+34.532 -2.734 34.709 -2.628 34.807 -2.41 c
+34.914 -2.186 34.969 -1.849 34.969 -1.396 c
+h
+36.714 -1.072 m
+36.714 -0.32 36.891 0.268 37.244 0.691 c
+37.597 1.121 38.085 1.338 38.713 1.338 c
+39.349 1.338 39.846 1.121 40.199 0.691 c
+40.558 0.268 40.742 -0.324 40.742 -1.088 c
+40.742 -1.396 l
+40.742 -2.153 40.566 -2.745 40.213 -3.175 c
+39.86 -3.597 39.364 -3.807 38.728 -3.807 c
+38.089 -3.807 37.597 -3.597 37.244 -3.175 c
+36.891 -2.745 36.714 -2.153 36.714 -1.396 c
+h
+38.023 -1.396 m
+38.023 -2.289 38.258 -2.734 38.728 -2.734 c
+39.17 -2.734 39.405 -2.363 39.434 -1.617 c
+39.449 -1.072 l
+39.449 -0.625 39.382 -0.29 39.258 -0.073 c
+39.129 0.15 38.948 0.264 38.713 0.264 c
+38.497 0.264 38.324 0.15 38.2 -0.073 c
+38.082 -0.29 38.023 -0.625 38.023 -1.072 c
+h
+f
+Q
+q 1 0 0 1 564.4878 408.9507 cm
+0 0 m
+0 0.684 0.077 1.341 0.235 1.97 c
+0.39 2.606 0.632 3.167 0.956 3.66 c
+1.279 4.16 1.621 4.505 1.985 4.704 c
+2.22 3.983 l
+1.875 3.66 1.603 3.16 1.397 2.484 c
+1.199 1.816 1.096 1.043 1.088 0.162 c
+1.088 -0.118 l
+1.088 -1.04 1.183 -1.849 1.382 -2.543 c
+1.588 -3.237 1.867 -3.755 2.22 -4.101 c
+1.985 -4.806 l
+1.621 -4.619 1.279 -4.281 0.956 -3.792 c
+0.64 -3.3 0.401 -2.749 0.235 -2.132 c
+0.077 -1.514 0 -0.867 0 -0.191 c
+h
+4.032 2.249 m
+4.075 1.764 l
+4.37 2.146 4.752 2.337 5.222 2.337 c
+6.075 2.337 6.516 1.738 6.546 0.544 c
+6.546 -2.72 l
+5.237 -2.72 l
+5.237 0.455 l
+5.237 0.727 5.193 0.929 5.104 1.058 c
+5.024 1.183 4.877 1.249 4.664 1.249 c
+4.429 1.249 4.245 1.132 4.12 0.897 c
+4.12 -2.72 l
+2.812 -2.72 l
+2.812 2.249 l
+h
+9.65 -2.72 m
+9.61 -2.643 9.569 -2.514 9.532 -2.337 c
+9.305 -2.653 8.992 -2.807 8.592 -2.807 c
+8.169 -2.807 7.82 -2.672 7.549 -2.396 c
+7.284 -2.124 7.151 -1.764 7.151 -1.323 c
+7.151 -0.804 7.313 -0.405 7.637 -0.118 c
+7.967 0.166 8.449 0.312 9.077 0.324 c
+9.474 0.324 l
+9.474 0.721 l
+9.474 0.944 9.434 1.103 9.357 1.191 c
+9.276 1.278 9.166 1.323 9.018 1.323 c
+8.695 1.323 8.533 1.135 8.533 0.765 c
+7.24 0.765 l
+7.24 1.213 7.408 1.588 7.755 1.881 c
+8.096 2.182 8.533 2.337 9.062 2.337 c
+9.599 2.337 10.018 2.194 10.311 1.911 c
+10.613 1.635 10.768 1.235 10.768 0.706 c
+10.768 -1.631 l
+10.775 -2.065 10.841 -2.404 10.959 -2.645 c
+10.959 -2.72 l
+h
+8.886 -1.793 m
+9.022 -1.793 9.139 -1.764 9.239 -1.705 c
+9.345 -1.646 9.422 -1.58 9.474 -1.5 c
+9.474 -0.47 l
+9.166 -0.47 l
+8.937 -0.47 8.761 -0.54 8.636 -0.676 c
+8.507 -0.816 8.445 -0.999 8.445 -1.234 c
+8.445 -1.61 8.592 -1.793 8.886 -1.793 c
+12.755 2.249 m
+12.8 1.793 l
+13.093 2.153 13.476 2.337 13.946 2.337 c
+14.446 2.337 14.799 2.117 15.005 1.675 c
+15.287 2.117 15.695 2.337 16.225 2.337 c
+17.085 2.337 17.533 1.738 17.562 0.544 c
+17.562 -2.72 l
+16.254 -2.72 l
+16.254 0.455 l
+16.254 0.738 16.214 0.941 16.136 1.058 c
+16.056 1.183 15.923 1.249 15.74 1.249 c
+15.493 1.249 15.313 1.103 15.196 0.808 c
+15.196 -2.72 l
+13.902 -2.72 l
+13.902 0.441 l
+13.902 0.724 13.862 0.929 13.785 1.058 c
+13.704 1.183 13.567 1.249 13.373 1.249 c
+13.145 1.249 12.969 1.132 12.844 0.897 c
+12.844 -2.72 l
+11.55 -2.72 l
+11.55 2.249 l
+h
+20.252 -2.807 m
+19.583 -2.807 19.061 -2.612 18.679 -2.219 c
+18.305 -1.819 18.121 -1.246 18.121 -0.5 c
+18.121 -0.103 l
+18.121 0.68 18.29 1.282 18.635 1.706 c
+18.977 2.124 19.473 2.337 20.12 2.337 c
+20.737 2.337 21.201 2.135 21.517 1.735 c
+21.839 1.341 22.001 0.754 22.001 -0.029 c
+22.001 -0.676 l
+19.429 -0.676 l
+19.437 -1.04 19.518 -1.309 19.664 -1.484 c
+19.811 -1.654 20.031 -1.735 20.326 -1.735 c
+20.767 -1.735 21.127 -1.584 21.413 -1.278 c
+21.928 -2.072 l
+21.77 -2.29 21.538 -2.466 21.237 -2.602 c
+20.931 -2.738 20.605 -2.807 20.252 -2.807 c
+19.429 0.235 m
+20.737 0.235 l
+20.737 0.353 l
+20.726 0.654 20.671 0.882 20.576 1.029 c
+20.487 1.183 20.329 1.264 20.105 1.264 c
+19.877 1.264 19.712 1.18 19.605 1.014 c
+19.506 0.856 19.447 0.595 19.429 0.235 c
+22.662 -2.057 m
+22.662 -1.852 22.729 -1.683 22.868 -1.544 c
+23.015 -1.407 23.2 -1.338 23.427 -1.338 c
+23.64 -1.338 23.817 -1.407 23.956 -1.544 c
+24.104 -1.672 24.177 -1.845 24.177 -2.057 c
+24.177 -2.275 24.104 -2.448 23.956 -2.572 c
+23.817 -2.701 23.64 -2.763 23.427 -2.763 c
+23.2 -2.763 23.015 -2.701 22.868 -2.572 c
+22.729 -2.448 22.662 -2.275 22.662 -2.057 c
+22.662 1.706 m
+22.662 1.911 22.729 2.08 22.868 2.219 c
+23.015 2.356 23.2 2.425 23.427 2.425 c
+23.64 2.425 23.817 2.356 23.956 2.219 c
+24.104 2.091 24.177 1.918 24.177 1.706 c
+24.177 1.488 24.104 1.315 23.956 1.191 c
+23.817 1.062 23.64 1 23.427 1 c
+23.2 1 23.015 1.062 22.868 1.191 c
+22.729 1.315 22.662 1.488 22.662 1.706 c
+26.98 -0.073 m
+26.98 0.68 27.157 1.268 27.51 1.69 c
+27.863 2.12 28.351 2.337 28.979 2.337 c
+29.615 2.337 30.111 2.12 30.464 1.69 c
+30.824 1.268 31.008 0.676 31.008 -0.088 c
+31.008 -0.397 l
+31.008 -1.154 30.832 -1.745 30.479 -2.175 c
+30.126 -2.598 29.63 -2.807 28.995 -2.807 c
+28.355 -2.807 27.863 -2.598 27.51 -2.175 c
+27.157 -1.745 26.98 -1.154 26.98 -0.397 c
+h
+28.289 -0.397 m
+28.289 -1.29 28.524 -1.735 28.995 -1.735 c
+29.436 -1.735 29.671 -1.363 29.7 -0.617 c
+29.714 -0.073 l
+29.714 0.374 29.648 0.709 29.523 0.926 c
+29.395 1.151 29.215 1.264 28.979 1.264 c
+28.763 1.264 28.59 1.151 28.465 0.926 c
+28.347 0.709 28.289 0.374 28.289 -0.073 c
+h
+34.08 1 m
+33.654 1.029 l
+33.29 1.029 33.051 0.871 32.933 0.559 c
+32.933 -2.72 l
+31.626 -2.72 l
+31.626 2.249 l
+32.846 2.249 l
+32.889 1.72 l
+33.095 2.132 33.378 2.337 33.742 2.337 c
+33.889 2.337 34.007 2.315 34.095 2.278 c
+h
+35.991 -2.72 -1.308 4.969 re
+34.624 3.543 m
+34.624 3.738 34.687 3.899 34.815 4.027 c
+34.94 4.164 35.113 4.233 35.329 4.233 c
+35.543 4.233 35.715 4.164 35.844 4.027 c
+35.969 3.899 36.035 3.738 36.035 3.543 c
+36.035 3.337 35.969 3.164 35.844 3.028 c
+35.726 2.899 35.553 2.837 35.329 2.837 c
+35.113 2.837 34.94 2.899 34.815 3.028 c
+34.687 3.164 34.624 3.337 34.624 3.543 c
+36.752 -0.088 m
+36.752 0.735 36.899 1.341 37.193 1.735 c
+37.487 2.135 37.899 2.337 38.427 2.337 c
+38.876 2.337 39.225 2.161 39.471 1.808 c
+39.515 2.249 l
+40.691 2.249 l
+40.691 -2.72 l
+40.691 -3.355 40.507 -3.84 40.147 -4.174 c
+39.794 -4.505 39.283 -4.675 38.618 -4.675 c
+38.354 -4.675 38.067 -4.619 37.766 -4.513 c
+37.461 -4.403 37.236 -4.266 37.09 -4.101 c
+37.531 -3.204 l
+37.656 -3.329 37.818 -3.432 38.016 -3.513 c
+38.211 -3.59 38.391 -3.63 38.56 -3.63 c
+38.853 -3.63 39.063 -3.561 39.192 -3.425 c
+39.316 -3.285 39.383 -3.061 39.383 -2.749 c
+39.383 -2.323 l
+39.137 -2.645 38.813 -2.807 38.412 -2.807 c
+37.884 -2.807 37.472 -2.602 37.178 -2.19 c
+36.891 -1.779 36.752 -1.201 36.752 -0.455 c
+h
+38.045 -0.411 m
+38.045 -0.875 38.104 -1.205 38.221 -1.411 c
+38.339 -1.617 38.531 -1.72 38.795 -1.72 c
+39.06 -1.72 39.254 -1.628 39.383 -1.44 c
+39.383 0.941 l
+39.254 1.147 39.063 1.249 38.809 1.249 c
+38.545 1.249 38.346 1.139 38.221 0.926 c
+38.104 0.721 38.045 0.382 38.045 -0.088 c
+h
+42.819 -2.72 -1.309 4.969 re
+41.452 3.543 m
+41.452 3.738 41.514 3.899 41.643 4.027 c
+41.768 4.164 41.94 4.233 42.157 4.233 c
+42.371 4.233 42.543 4.164 42.672 4.027 c
+42.797 3.899 42.863 3.738 42.863 3.543 c
+42.863 3.337 42.797 3.164 42.672 3.028 c
+42.554 2.899 42.381 2.837 42.157 2.837 c
+41.94 2.837 41.768 2.899 41.643 3.028 c
+41.514 3.164 41.452 3.337 41.452 3.543 c
+44.917 2.249 m
+44.961 1.764 l
+45.255 2.146 45.637 2.337 46.107 2.337 c
+46.96 2.337 47.401 1.738 47.43 0.544 c
+47.43 -2.72 l
+46.123 -2.72 l
+46.123 0.455 l
+46.123 0.727 46.078 0.929 45.99 1.058 c
+45.909 1.183 45.762 1.249 45.549 1.249 c
+45.314 1.249 45.13 1.132 45.005 0.897 c
+45.005 -2.72 l
+43.697 -2.72 l
+43.697 2.249 l
+h
+50.26 -0.103 m
+50.26 -0.819 50.165 -1.496 49.981 -2.132 c
+49.805 -2.767 49.554 -3.326 49.231 -3.807 c
+48.908 -4.285 48.563 -4.619 48.203 -4.806 c
+47.967 -4.101 l
+48.309 -3.767 48.577 -3.256 48.775 -2.572 c
+48.981 -1.889 49.088 -1.11 49.099 -0.235 c
+49.099 0.015 l
+49.099 0.904 48.996 1.698 48.79 2.396 c
+48.592 3.102 48.32 3.634 47.967 3.998 c
+48.203 4.704 l
+48.438 4.586 48.677 4.384 48.922 4.101 c
+49.165 3.825 49.386 3.484 49.584 3.072 c
+49.79 2.66 49.951 2.194 50.069 1.675 c
+50.194 1.165 50.26 0.573 50.26 -0.103 c
+f
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 661.8731 424.5284 cm
+0 0 m
+54.019 0 l
+56.624 0 58.723 -2.099 58.723 -4.704 c
+58.723 -21.409 l
+58.723 -24.015 56.624 -26.109 54.019 -26.109 c
+0 -26.109 l
+-2.606 -26.109 -4.7 -24.015 -4.7 -21.409 c
+-4.7 -4.704 l
+-4.7 -2.099 -2.606 0 0 0 c
+f
+Q
+0 0 0 0 k
+q 1 0 0 1 669.0274 418.5641 cm
+0 0 m
+-0.426 0.029 l
+-0.789 0.029 -1.028 -0.129 -1.146 -0.441 c
+-1.146 -3.719 l
+-2.454 -3.719 l
+-2.454 1.249 l
+-1.234 1.249 l
+-1.19 0.72 l
+-0.984 1.132 -0.702 1.338 -0.338 1.338 c
+-0.191 1.338 -0.073 1.315 0.015 1.278 c
+h
+2.469 -3.807 m
+1.802 -3.807 1.279 -3.612 0.898 -3.219 c
+0.522 -2.818 0.339 -2.246 0.339 -1.5 c
+0.339 -1.103 l
+0.339 -0.32 0.508 0.283 0.853 0.706 c
+1.195 1.124 1.691 1.338 2.338 1.338 c
+2.955 1.338 3.418 1.135 3.734 0.735 c
+4.057 0.341 4.219 -0.246 4.219 -1.029 c
+4.219 -1.675 l
+1.646 -1.675 l
+1.654 -2.04 1.735 -2.308 1.882 -2.484 c
+2.029 -2.654 2.249 -2.734 2.544 -2.734 c
+2.984 -2.734 3.344 -2.583 3.631 -2.278 c
+4.146 -3.072 l
+3.988 -3.289 3.756 -3.466 3.454 -3.601 c
+3.15 -3.738 2.822 -3.807 2.469 -3.807 c
+1.646 -0.765 m
+2.955 -0.765 l
+2.955 -0.647 l
+2.944 -0.345 2.889 -0.118 2.793 0.029 c
+2.705 0.183 2.547 0.264 2.323 0.264 c
+2.095 0.264 1.93 0.18 1.823 0.014 c
+1.724 -0.144 1.665 -0.405 1.646 -0.765 c
+5.997 1.249 m
+6.041 0.794 l
+6.336 1.153 6.718 1.338 7.188 1.338 c
+7.688 1.338 8.041 1.117 8.247 0.676 c
+8.53 1.117 8.937 1.338 9.467 1.338 c
+10.327 1.338 10.775 0.738 10.804 -0.456 c
+10.804 -3.719 l
+9.496 -3.719 l
+9.496 -0.544 l
+9.496 -0.262 9.455 -0.059 9.378 0.058 c
+9.297 0.183 9.166 0.249 8.981 0.249 c
+8.736 0.249 8.555 0.103 8.438 -0.191 c
+8.438 -3.719 l
+7.144 -3.719 l
+7.144 -0.559 l
+7.144 -0.276 7.104 -0.07 7.026 0.058 c
+6.945 0.183 6.81 0.249 6.615 0.249 c
+6.388 0.249 6.211 0.132 6.086 -0.103 c
+6.086 -3.719 l
+4.792 -3.719 l
+4.792 1.249 l
+h
+11.333 -1.073 m
+11.333 -0.32 11.51 0.268 11.863 0.691 c
+12.216 1.12 12.704 1.338 13.332 1.338 c
+13.968 1.338 14.464 1.12 14.817 0.691 c
+15.177 0.268 15.361 -0.324 15.361 -1.087 c
+15.361 -1.397 l
+15.361 -2.153 15.185 -2.745 14.832 -3.175 c
+14.479 -3.597 13.983 -3.807 13.347 -3.807 c
+12.708 -3.807 12.216 -3.597 11.863 -3.175 c
+11.51 -2.745 11.333 -2.153 11.333 -1.397 c
+h
+12.642 -1.397 m
+12.642 -2.29 12.877 -2.734 13.347 -2.734 c
+13.788 -2.734 14.024 -2.363 14.053 -1.617 c
+14.068 -1.073 l
+14.068 -0.625 14.001 -0.291 13.876 -0.073 c
+13.748 0.151 13.567 0.264 13.332 0.264 c
+13.116 0.264 12.943 0.151 12.818 -0.073 c
+12.7 -0.291 12.642 -0.625 12.642 -1.073 c
+h
+17.492 2.469 m
+17.492 1.249 l
+18.153 1.249 l
+18.153 0.279 l
+17.492 0.279 l
+17.492 -2.19 l
+17.492 -2.389 17.515 -2.525 17.565 -2.602 c
+17.625 -2.672 17.731 -2.705 17.889 -2.705 c
+18.007 -2.705 18.109 -2.697 18.198 -2.675 c
+18.184 -3.69 l
+17.955 -3.767 17.717 -3.807 17.463 -3.807 c
+16.629 -3.807 16.206 -3.329 16.199 -2.367 c
+16.199 0.279 l
+15.626 0.279 l
+15.626 1.249 l
+16.199 1.249 l
+16.199 2.469 l
+h
+20.759 -3.807 m
+20.09 -3.807 19.568 -3.612 19.186 -3.219 c
+18.812 -2.818 18.628 -2.246 18.628 -1.5 c
+18.628 -1.103 l
+18.628 -0.32 18.797 0.283 19.142 0.706 c
+19.484 1.124 19.98 1.338 20.627 1.338 c
+21.245 1.338 21.708 1.135 22.024 0.735 c
+22.346 0.341 22.508 -0.246 22.508 -1.029 c
+22.508 -1.675 l
+19.936 -1.675 l
+19.944 -2.04 20.025 -2.308 20.171 -2.484 c
+20.318 -2.654 20.539 -2.734 20.833 -2.734 c
+21.274 -2.734 21.634 -2.583 21.92 -2.278 c
+22.435 -3.072 l
+22.277 -3.289 22.045 -3.466 21.744 -3.601 c
+21.44 -3.738 21.112 -3.807 20.759 -3.807 c
+19.936 -0.765 m
+21.245 -0.765 l
+21.245 -0.647 l
+21.234 -0.345 21.178 -0.118 21.083 0.029 c
+20.995 0.183 20.836 0.264 20.613 0.264 c
+20.384 0.264 20.219 0.18 20.112 0.014 c
+20.013 -0.144 19.954 -0.405 19.936 -0.765 c
+27.605 0 m
+27.179 0.029 l
+26.815 0.029 26.576 -0.129 26.458 -0.441 c
+26.458 -3.719 l
+25.151 -3.719 l
+25.151 1.249 l
+26.371 1.249 l
+26.415 0.72 l
+26.62 1.132 26.903 1.338 27.267 1.338 c
+27.414 1.338 27.532 1.315 27.62 1.278 c
+h
+30.075 -3.807 m
+29.406 -3.807 28.885 -3.612 28.502 -3.219 c
+28.127 -2.818 27.944 -2.246 27.944 -1.5 c
+27.944 -1.103 l
+27.944 -0.32 28.112 0.283 28.457 0.706 c
+28.8 1.124 29.296 1.338 29.943 1.338 c
+30.56 1.338 31.023 1.135 31.339 0.735 c
+31.663 0.341 31.824 -0.246 31.824 -1.029 c
+31.824 -1.675 l
+29.251 -1.675 l
+29.259 -2.04 29.34 -2.308 29.487 -2.484 c
+29.633 -2.654 29.854 -2.734 30.148 -2.734 c
+30.589 -2.734 30.949 -2.583 31.236 -2.278 c
+31.75 -3.072 l
+31.593 -3.289 31.361 -3.466 31.059 -3.601 c
+30.755 -3.738 30.427 -3.807 30.075 -3.807 c
+29.251 -0.765 m
+30.56 -0.765 l
+30.56 -0.647 l
+30.549 -0.345 30.494 -0.118 30.398 0.029 c
+30.31 0.183 30.152 0.264 29.928 0.264 c
+29.7 0.264 29.535 0.18 29.428 0.014 c
+29.329 -0.144 29.27 -0.405 29.251 -0.765 c
+36.263 -1.397 m
+36.263 -2.172 36.124 -2.771 35.852 -3.19 c
+35.587 -3.601 35.19 -3.807 34.661 -3.807 c
+34.257 -3.807 33.933 -3.645 33.691 -3.322 c
+33.691 -5.63 l
+32.382 -5.63 l
+32.382 1.249 l
+33.588 1.249 l
+33.631 0.794 l
+33.885 1.153 34.223 1.338 34.647 1.338 c
+35.175 1.338 35.572 1.147 35.837 0.764 c
+36.108 0.382 36.252 -0.214 36.263 -1.014 c
+h
+34.969 -1.058 m
+34.969 -0.58 34.915 -0.243 34.807 -0.044 c
+34.697 0.151 34.518 0.249 34.264 0.249 c
+33.999 0.249 33.808 0.139 33.691 -0.073 c
+33.691 -2.411 l
+33.808 -2.627 34.003 -2.734 34.279 -2.734 c
+34.532 -2.734 34.709 -2.627 34.807 -2.411 c
+34.915 -2.186 34.969 -1.849 34.969 -1.397 c
+h
+36.715 -1.073 m
+36.715 -0.32 36.891 0.268 37.244 0.691 c
+37.597 1.12 38.086 1.338 38.714 1.338 c
+39.35 1.338 39.846 1.12 40.199 0.691 c
+40.559 0.268 40.742 -0.324 40.742 -1.087 c
+40.742 -1.397 l
+40.742 -2.153 40.567 -2.745 40.214 -3.175 c
+39.861 -3.597 39.364 -3.807 38.728 -3.807 c
+38.09 -3.807 37.597 -3.597 37.244 -3.175 c
+36.891 -2.745 36.715 -2.153 36.715 -1.397 c
+h
+38.023 -1.397 m
+38.023 -2.29 38.258 -2.734 38.728 -2.734 c
+39.17 -2.734 39.405 -2.363 39.434 -1.617 c
+39.449 -1.073 l
+39.449 -0.625 39.383 -0.291 39.258 -0.073 c
+39.129 0.151 38.949 0.264 38.714 0.264 c
+38.497 0.264 38.325 0.151 38.2 -0.073 c
+38.082 -0.291 38.023 -0.625 38.023 -1.073 c
+h
+f
+Q
+q 1 0 0 1 662.4357 407.6318 cm
+0 0 m
+0 0.683 0.077 1.341 0.235 1.969 c
+0.389 2.605 0.632 3.167 0.955 3.659 c
+1.278 4.16 1.62 4.505 1.984 4.704 c
+2.219 3.983 l
+1.874 3.659 1.602 3.16 1.396 2.484 c
+1.198 1.815 1.095 1.043 1.087 0.162 c
+1.087 -0.118 l
+1.087 -1.04 1.182 -1.849 1.381 -2.543 c
+1.587 -3.238 1.866 -3.755 2.219 -4.102 c
+1.984 -4.807 l
+1.62 -4.619 1.278 -4.281 0.955 -3.793 c
+0.639 -3.3 0.4 -2.749 0.235 -2.132 c
+0.077 -1.515 0 -0.867 0 -0.191 c
+h
+4.031 2.248 m
+4.075 1.764 l
+4.369 2.146 4.751 2.337 5.221 2.337 c
+6.074 2.337 6.515 1.738 6.545 0.544 c
+6.545 -2.72 l
+5.236 -2.72 l
+5.236 0.455 l
+5.236 0.727 5.192 0.929 5.103 1.058 c
+5.023 1.183 4.876 1.249 4.663 1.249 c
+4.428 1.249 4.244 1.132 4.119 0.897 c
+4.119 -2.72 l
+2.811 -2.72 l
+2.811 2.248 l
+h
+9.653 -2.72 m
+9.612 -2.643 9.572 -2.514 9.535 -2.338 c
+9.308 -2.654 8.995 -2.808 8.595 -2.808 c
+8.172 -2.808 7.823 -2.672 7.551 -2.396 c
+7.287 -2.124 7.154 -1.764 7.154 -1.324 c
+7.154 -0.805 7.316 -0.405 7.64 -0.118 c
+7.97 0.165 8.452 0.312 9.08 0.323 c
+9.477 0.323 l
+9.477 0.72 l
+9.477 0.945 9.437 1.103 9.359 1.19 c
+9.278 1.278 9.168 1.323 9.022 1.323 c
+8.698 1.323 8.536 1.135 8.536 0.764 c
+7.243 0.764 l
+7.243 1.213 7.412 1.587 7.757 1.882 c
+8.099 2.183 8.536 2.337 9.065 2.337 c
+9.602 2.337 10.021 2.194 10.314 1.911 c
+10.616 1.635 10.77 1.234 10.77 0.706 c
+10.77 -1.632 l
+10.778 -2.066 10.844 -2.404 10.961 -2.646 c
+10.961 -2.72 l
+h
+8.889 -1.794 m
+9.024 -1.794 9.142 -1.764 9.242 -1.706 c
+9.348 -1.646 9.425 -1.58 9.477 -1.5 c
+9.477 -0.47 l
+9.168 -0.47 l
+8.941 -0.47 8.764 -0.541 8.639 -0.676 c
+8.511 -0.816 8.448 -1 8.448 -1.235 c
+8.448 -1.61 8.595 -1.794 8.889 -1.794 c
+12.755 2.248 m
+12.799 1.793 l
+13.093 2.153 13.475 2.337 13.945 2.337 c
+14.445 2.337 14.798 2.117 15.004 1.675 c
+15.287 2.117 15.694 2.337 16.224 2.337 c
+17.084 2.337 17.532 1.738 17.562 0.544 c
+17.562 -2.72 l
+16.253 -2.72 l
+16.253 0.455 l
+16.253 0.738 16.213 0.941 16.135 1.058 c
+16.055 1.183 15.922 1.249 15.739 1.249 c
+15.492 1.249 15.312 1.103 15.195 0.808 c
+15.195 -2.72 l
+13.901 -2.72 l
+13.901 0.44 l
+13.901 0.723 13.861 0.929 13.784 1.058 c
+13.703 1.183 13.567 1.249 13.372 1.249 c
+13.144 1.249 12.968 1.132 12.843 0.897 c
+12.843 -2.72 l
+11.549 -2.72 l
+11.549 2.248 l
+h
+20.251 -2.808 m
+19.582 -2.808 19.06 -2.613 18.678 -2.22 c
+18.304 -1.819 18.12 -1.246 18.12 -0.5 c
+18.12 -0.103 l
+18.12 0.679 18.289 1.282 18.634 1.705 c
+18.977 2.124 19.472 2.337 20.119 2.337 c
+20.737 2.337 21.2 2.135 21.516 1.734 c
+21.838 1.341 22 0.753 22 -0.03 c
+22 -0.676 l
+19.428 -0.676 l
+19.436 -1.04 19.517 -1.309 19.663 -1.484 c
+19.81 -1.654 20.031 -1.735 20.325 -1.735 c
+20.766 -1.735 21.126 -1.584 21.412 -1.279 c
+21.927 -2.072 l
+21.769 -2.29 21.537 -2.466 21.236 -2.602 c
+20.931 -2.738 20.604 -2.808 20.251 -2.808 c
+19.428 0.235 m
+20.737 0.235 l
+20.737 0.353 l
+20.725 0.654 20.67 0.881 20.575 1.028 c
+20.486 1.183 20.328 1.263 20.104 1.263 c
+19.877 1.263 19.711 1.18 19.605 1.014 c
+19.505 0.856 19.447 0.595 19.428 0.235 c
+22.662 -2.058 m
+22.662 -1.852 22.728 -1.683 22.867 -1.544 c
+23.014 -1.407 23.199 -1.338 23.426 -1.338 c
+23.64 -1.338 23.816 -1.407 23.955 -1.544 c
+24.103 -1.673 24.176 -1.845 24.176 -2.058 c
+24.176 -2.275 24.103 -2.448 23.955 -2.573 c
+23.816 -2.701 23.64 -2.764 23.426 -2.764 c
+23.199 -2.764 23.014 -2.701 22.867 -2.573 c
+22.728 -2.448 22.662 -2.275 22.662 -2.058 c
+22.662 1.705 m
+22.662 1.911 22.728 2.08 22.867 2.219 c
+23.014 2.356 23.199 2.425 23.426 2.425 c
+23.64 2.425 23.816 2.356 23.955 2.219 c
+24.103 2.09 24.176 1.918 24.176 1.705 c
+24.176 1.488 24.103 1.315 23.955 1.19 c
+23.816 1.062 23.64 0.999 23.426 0.999 c
+23.199 0.999 23.014 1.062 22.867 1.19 c
+22.728 1.315 22.662 1.488 22.662 1.705 c
+31.01 -0.397 m
+31.01 -1.172 30.871 -1.771 30.599 -2.19 c
+30.335 -2.602 29.938 -2.808 29.408 -2.808 c
+29.005 -2.808 28.681 -2.646 28.439 -2.323 c
+28.439 -4.63 l
+27.131 -4.63 l
+27.131 2.248 l
+28.336 2.248 l
+28.38 1.793 l
+28.633 2.153 28.972 2.337 29.394 2.337 c
+29.923 2.337 30.32 2.146 30.584 1.764 c
+30.856 1.381 31 0.786 31.01 -0.015 c
+h
+29.718 -0.059 m
+29.718 0.419 29.662 0.756 29.556 0.955 c
+29.445 1.15 29.265 1.249 29.012 1.249 c
+28.747 1.249 28.556 1.139 28.439 0.926 c
+28.439 -1.411 l
+28.556 -1.628 28.751 -1.735 29.026 -1.735 c
+29.281 -1.735 29.456 -1.628 29.556 -1.411 c
+29.662 -1.187 29.718 -0.849 29.718 -0.397 c
+h
+34.05 -2.264 m
+33.786 -2.627 33.425 -2.808 32.977 -2.808 c
+32.514 -2.808 32.169 -2.654 31.933 -2.338 c
+31.698 -2.025 31.581 -1.569 31.581 -0.971 c
+31.581 2.248 l
+32.874 2.248 l
+32.874 -1 l
+32.882 -1.482 33.043 -1.72 33.36 -1.72 c
+33.661 -1.72 33.877 -1.595 34.006 -1.338 c
+34.006 2.248 l
+35.314 2.248 l
+35.314 -2.72 l
+34.094 -2.72 l
+h
+39.933 -0.397 m
+39.933 -1.202 39.801 -1.804 39.536 -2.205 c
+39.28 -2.61 38.879 -2.808 38.331 -2.808 c
+37.898 -2.808 37.556 -2.617 37.302 -2.234 c
+37.258 -2.72 l
+36.053 -2.72 l
+36.053 4.336 l
+37.36 4.336 l
+37.36 1.851 l
+37.603 2.175 37.927 2.337 38.331 2.337 c
+38.879 2.337 39.28 2.135 39.536 1.734 c
+39.79 1.341 39.922 0.756 39.933 -0.015 c
+h
+38.64 -0.073 m
+38.64 0.455 38.584 0.808 38.478 0.985 c
+38.379 1.161 38.202 1.249 37.949 1.249 c
+37.674 1.249 37.479 1.124 37.36 0.881 c
+37.36 -1.382 l
+37.479 -1.617 37.677 -1.735 37.964 -1.735 c
+38.206 -1.735 38.379 -1.658 38.478 -1.5 c
+38.574 -1.334 38.629 -1.014 38.64 -0.544 c
+h
+41.903 -2.72 -1.309 7.056 re
+44.178 -2.72 -1.309 4.968 re
+42.81 3.542 m
+42.81 3.737 42.873 3.898 43.002 4.027 c
+43.126 4.163 43.299 4.233 43.516 4.233 c
+43.729 4.233 43.902 4.163 44.03 4.027 c
+44.155 3.898 44.221 3.737 44.221 3.542 c
+44.221 3.337 44.155 3.164 44.03 3.027 c
+43.913 2.899 43.741 2.836 43.516 2.836 c
+43.299 2.836 43.126 2.899 43.002 3.027 c
+42.873 3.164 42.81 3.337 42.81 3.542 c
+46.879 -1.735 m
+47.261 -1.735 47.452 -1.492 47.452 -1 c
+48.687 -1 l
+48.676 -1.54 48.503 -1.977 48.172 -2.308 c
+47.849 -2.643 47.426 -2.808 46.908 -2.808 c
+46.268 -2.808 45.78 -2.613 45.438 -2.22 c
+45.104 -1.819 44.938 -1.231 44.938 -0.456 c
+44.938 -0.059 l
+44.938 0.723 45.1 1.315 45.424 1.72 c
+45.754 2.131 46.25 2.337 46.908 2.337 c
+47.456 2.337 47.885 2.164 48.202 1.822 c
+48.514 1.488 48.676 1.014 48.687 0.397 c
+47.452 0.397 l
+47.452 0.669 47.408 0.881 47.319 1.028 c
+47.232 1.183 47.084 1.263 46.879 1.263 c
+46.651 1.263 46.489 1.18 46.393 1.014 c
+46.295 0.856 46.239 0.548 46.232 0.087 c
+46.232 -0.412 l
+46.232 -0.823 46.25 -1.11 46.291 -1.264 c
+46.328 -1.422 46.393 -1.54 46.482 -1.617 c
+46.577 -1.698 46.71 -1.735 46.879 -1.735 c
+51.336 -0.103 m
+51.336 -0.819 51.24 -1.496 51.057 -2.132 c
+50.881 -2.768 50.631 -3.326 50.307 -3.807 c
+49.983 -4.285 49.638 -4.619 49.278 -4.807 c
+49.043 -4.102 l
+49.385 -3.767 49.653 -3.256 49.852 -2.573 c
+50.058 -1.889 50.164 -1.11 50.175 -0.235 c
+50.175 0.014 l
+50.175 0.904 50.072 1.697 49.866 2.396 c
+49.668 3.102 49.395 3.634 49.043 3.998 c
+49.278 4.704 l
+49.513 4.586 49.752 4.384 49.998 4.101 c
+50.241 3.825 50.461 3.484 50.66 3.072 c
+50.866 2.66 51.028 2.194 51.145 1.675 c
+51.27 1.165 51.336 0.573 51.336 -0.103 c
+f
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm18 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm19 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm20 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm21 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm22 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm23 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm24 Do
+Q
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 585.9855 434.2035 cm
+0 0 m
+5.053 -5.074 l
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 589.5352 430.6393 cm
+0 0 m
+-1.51 0.003 l
+1.882 -1.889 l
+0 1.511 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 589.5352 430.6393 cm
+0 0 m
+-1.51 0.003 l
+1.882 -1.889 l
+0 1.511 l
+0 0 l
+h
+S
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm25 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm26 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm27 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm28 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm29 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm30 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm31 Do
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS3 gs
+0 TL/Fm32 Do
+Q
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 710.4792 434.3578 cm
+0 0 m
+-5.075 -5.056 l
+S
+Q
+q 1 0 0 1 706.9185 430.8089 cm
+0 0 m
+0 1.509 l
+-1.893 -1.882 l
+1.506 -0.005 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 706.9186 430.8089 cm
+0 0 m
+0 1.509 l
+-1.893 -1.882 l
+1.506 -0.005 l
+0 0 l
+h
+S
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 695.2289 383.6354 cm
+0 0 m
+0 0.459 0.081 0.808 0.25 1.043 c
+0.426 1.286 0.676 1.411 1 1.411 c
+1.301 1.411 1.532 1.278 1.691 1.014 c
+1.72 1.352 l
+2.161 1.352 l
+2.161 -1.661 l
+2.161 -2.032 2.061 -2.315 1.866 -2.514 c
+1.679 -2.708 1.419 -2.807 1.088 -2.807 c
+0.941 -2.807 0.771 -2.768 0.588 -2.69 c
+0.401 -2.62 0.264 -2.532 0.177 -2.425 c
+0.368 -2.087 l
+0.573 -2.294 0.798 -2.396 1.043 -2.396 c
+1.444 -2.396 1.65 -2.168 1.661 -1.72 c
+1.661 -1.338 l
+1.503 -1.573 1.282 -1.69 1 -1.69 c
+0.684 -1.69 0.441 -1.573 0.264 -1.338 c
+0.096 -1.103 0.008 -0.771 0 -0.338 c
+h
+0.485 -0.279 m
+0.485 -0.613 0.533 -0.86 0.632 -1.014 c
+0.727 -1.172 0.889 -1.249 1.118 -1.249 c
+1.359 -1.249 1.544 -1.128 1.661 -0.882 c
+1.661 0.603 l
+1.544 0.845 1.367 0.97 1.132 0.97 c
+0.904 0.97 0.742 0.889 0.647 0.735 c
+0.548 0.577 0.492 0.338 0.485 0.015 c
+h
+3.227 -1.631 -0.501 2.983 re
+3.256 2.146 m
+3.256 2.057 3.231 1.984 3.183 1.926 c
+3.142 1.874 3.073 1.852 2.977 1.852 c
+2.888 1.852 2.818 1.874 2.771 1.926 c
+2.73 1.984 2.712 2.051 2.712 2.132 c
+2.712 2.219 2.73 2.293 2.771 2.352 c
+2.818 2.41 2.888 2.44 2.977 2.44 c
+3.073 2.44 3.142 2.41 3.183 2.352 c
+3.231 2.293 3.256 2.223 3.256 2.146 c
+4.531 2.072 m
+4.531 1.352 l
+4.987 1.352 l
+4.987 0.956 l
+4.531 0.956 l
+4.531 -0.897 l
+4.531 -1.014 4.549 -1.103 4.59 -1.161 c
+4.627 -1.22 4.696 -1.249 4.796 -1.249 c
+4.854 -1.249 4.917 -1.242 4.987 -1.22 c
+4.987 -1.631 l
+4.869 -1.669 4.755 -1.69 4.648 -1.69 c
+4.451 -1.69 4.299 -1.625 4.193 -1.484 c
+4.094 -1.349 4.046 -1.154 4.046 -0.897 c
+4.046 0.956 l
+3.59 0.956 l
+3.59 1.352 l
+4.046 1.352 l
+4.046 2.072 l
+h
+8.804 -0.279 m
+8.804 -0.75 8.721 -1.103 8.555 -1.338 c
+8.386 -1.573 8.147 -1.69 7.834 -1.69 c
+7.53 -1.69 7.298 -1.58 7.144 -1.353 c
+7.144 -2.778 l
+6.659 -2.778 l
+6.659 1.352 l
+7.1 1.352 l
+7.129 1.014 l
+7.283 1.278 7.515 1.411 7.82 1.411 c
+8.151 1.411 8.397 1.294 8.555 1.058 c
+8.721 0.831 8.804 0.492 8.804 0.044 c
+h
+8.32 0 m
+8.32 0.33 8.264 0.577 8.158 0.735 c
+8.058 0.889 7.898 0.97 7.673 0.97 c
+7.437 0.97 7.262 0.852 7.144 0.617 c
+7.144 -0.926 l
+7.262 -1.154 7.441 -1.264 7.688 -1.264 c
+7.9 -1.264 8.058 -1.187 8.158 -1.029 c
+8.264 -0.875 8.32 -0.632 8.32 -0.309 c
+h
+10.774 -1.367 m
+10.616 -1.584 10.381 -1.69 10.069 -1.69 c
+9.804 -1.69 9.598 -1.598 9.452 -1.411 c
+9.311 -1.228 9.246 -0.952 9.246 -0.588 c
+9.246 1.352 l
+9.731 1.352 l
+9.731 -0.559 l
+9.731 -1.022 9.87 -1.249 10.157 -1.249 c
+10.451 -1.249 10.649 -1.118 10.76 -0.852 c
+10.76 1.352 l
+11.26 1.352 l
+11.26 -1.631 l
+10.789 -1.631 l
+h
+13.251 -0.867 m
+13.251 -0.761 13.211 -0.673 13.134 -0.603 c
+13.053 -0.526 12.902 -0.437 12.678 -0.338 c
+12.413 -0.231 12.226 -0.14 12.12 -0.059 c
+12.01 0.018 11.932 0.106 11.884 0.206 c
+11.833 0.301 11.811 0.419 11.811 0.559 c
+11.811 0.801 11.898 1.003 12.075 1.161 c
+12.251 1.326 12.476 1.411 12.752 1.411 c
+13.045 1.411 13.28 1.323 13.457 1.147 c
+13.633 0.977 13.722 0.764 13.722 0.5 c
+13.236 0.5 l
+13.236 0.636 13.185 0.75 13.089 0.838 c
+13.001 0.933 12.887 0.985 12.752 0.985 c
+12.604 0.985 12.49 0.945 12.413 0.867 c
+12.332 0.798 12.295 0.698 12.295 0.573 c
+12.295 0.474 12.326 0.397 12.384 0.338 c
+12.443 0.279 12.582 0.198 12.81 0.103 c
+13.17 -0.044 13.417 -0.187 13.545 -0.324 c
+13.681 -0.453 13.751 -0.625 13.751 -0.838 c
+13.751 -1.095 13.656 -1.301 13.471 -1.455 c
+13.296 -1.613 13.06 -1.69 12.766 -1.69 c
+12.45 -1.69 12.197 -1.602 12.002 -1.426 c
+11.815 -1.242 11.723 -1.01 11.723 -0.735 c
+12.208 -0.735 l
+12.215 -0.904 12.266 -1.037 12.355 -1.132 c
+12.45 -1.22 12.59 -1.264 12.766 -1.264 c
+12.92 -1.264 13.038 -1.231 13.119 -1.161 c
+13.207 -1.095 13.251 -0.996 13.251 -0.867 c
+14.695 1.043 m
+14.879 1.286 15.114 1.411 15.401 1.411 c
+15.93 1.411 16.199 1.058 16.21 0.353 c
+16.21 -1.631 l
+15.724 -1.631 l
+15.724 0.324 l
+15.724 0.559 15.684 0.723 15.607 0.823 c
+15.526 0.918 15.408 0.97 15.254 0.97 c
+15.137 0.97 15.026 0.929 14.931 0.852 c
+14.832 0.771 14.755 0.665 14.695 0.529 c
+14.695 -1.631 l
+14.21 -1.631 l
+14.21 2.602 l
+14.695 2.602 l
+h
+20.101 -0.279 m
+20.101 -0.75 20.016 -1.103 19.852 -1.338 c
+19.682 -1.573 19.443 -1.69 19.131 -1.69 c
+18.826 -1.69 18.595 -1.58 18.44 -1.353 c
+18.44 -2.778 l
+17.955 -2.778 l
+17.955 1.352 l
+18.396 1.352 l
+18.425 1.014 l
+18.58 1.278 18.811 1.411 19.116 1.411 c
+19.447 1.411 19.693 1.294 19.852 1.058 c
+20.016 0.831 20.101 0.492 20.101 0.044 c
+h
+19.616 0 m
+19.616 0.33 19.561 0.577 19.455 0.735 c
+19.355 0.889 19.193 0.97 18.969 0.97 c
+18.734 0.97 18.558 0.852 18.44 0.617 c
+18.44 -0.926 l
+18.558 -1.154 18.738 -1.264 18.984 -1.264 c
+19.197 -1.264 19.355 -1.187 19.455 -1.029 c
+19.561 -0.875 19.616 -0.632 19.616 -0.309 c
+h
+22.071 -1.367 m
+21.913 -1.584 21.677 -1.69 21.365 -1.69 c
+21.101 -1.69 20.895 -1.598 20.748 -1.411 c
+20.608 -1.228 20.542 -0.952 20.542 -0.588 c
+20.542 1.352 l
+21.027 1.352 l
+21.027 -0.559 l
+21.027 -1.022 21.167 -1.249 21.454 -1.249 c
+21.747 -1.249 21.946 -1.118 22.056 -0.852 c
+22.056 1.352 l
+22.556 1.352 l
+22.556 -1.631 l
+22.086 -1.631 l
+h
+25.271 -0.279 m
+25.271 -0.75 25.186 -1.103 25.022 -1.338 c
+24.852 -1.573 24.61 -1.69 24.286 -1.69 c
+23.971 -1.69 23.736 -1.554 23.581 -1.278 c
+23.551 -1.631 l
+23.11 -1.631 l
+23.11 2.602 l
+23.596 2.602 l
+23.596 1.029 l
+23.75 1.282 23.981 1.411 24.286 1.411 c
+24.61 1.411 24.852 1.294 25.022 1.058 c
+25.186 0.823 25.271 0.474 25.271 0.015 c
+h
+24.787 0 m
+24.787 0.353 24.735 0.603 24.639 0.75 c
+24.54 0.897 24.378 0.97 24.154 0.97 c
+23.908 0.97 23.721 0.831 23.596 0.559 c
+23.596 -0.852 l
+23.713 -1.118 23.904 -1.249 24.169 -1.249 c
+24.382 -1.249 24.54 -1.176 24.639 -1.029 c
+24.735 -0.875 24.787 -0.632 24.787 -0.309 c
+h
+26.242 -1.631 -0.5 4.233 re
+27.447 -1.631 -0.5 2.983 re
+27.476 2.146 m
+27.476 2.057 27.451 1.984 27.403 1.926 c
+27.362 1.874 27.293 1.852 27.197 1.852 c
+27.108 1.852 27.039 1.874 26.991 1.926 c
+26.95 1.984 26.932 2.051 26.932 2.132 c
+26.932 2.219 26.95 2.293 26.991 2.352 c
+27.039 2.41 27.108 2.44 27.197 2.44 c
+27.293 2.44 27.362 2.41 27.403 2.352 c
+27.451 2.293 27.476 2.223 27.476 2.146 c
+29.148 -1.264 m
+29.313 -1.264 29.446 -1.216 29.545 -1.118 c
+29.641 -1.022 29.695 -0.879 29.707 -0.691 c
+30.163 -0.691 l
+30.152 -0.977 30.048 -1.216 29.853 -1.411 c
+29.666 -1.598 29.431 -1.69 29.148 -1.69 c
+28.785 -1.69 28.505 -1.573 28.311 -1.338 c
+28.112 -1.103 28.016 -0.757 28.016 -0.294 c
+28.016 0.029 l
+28.016 0.478 28.108 0.823 28.296 1.058 c
+28.49 1.294 28.773 1.411 29.148 1.411 c
+29.45 1.411 29.693 1.311 29.868 1.117 c
+30.052 0.918 30.152 0.654 30.163 0.324 c
+29.707 0.324 l
+29.685 0.548 29.626 0.713 29.531 0.823 c
+29.442 0.929 29.313 0.985 29.148 0.985 c
+28.932 0.985 28.77 0.912 28.663 0.764 c
+28.564 0.625 28.509 0.397 28.502 0.073 c
+28.502 -0.309 l
+28.502 -0.661 28.55 -0.912 28.648 -1.058 c
+28.755 -1.199 28.92 -1.264 29.148 -1.264 c
+32.22 1.352 m
+32.235 1.073 l
+32.411 1.297 32.65 1.411 32.955 1.411 c
+33.286 1.411 33.518 1.264 33.647 0.97 c
+33.83 1.264 34.091 1.411 34.425 1.411 c
+34.984 1.411 35.266 1.066 35.278 0.382 c
+35.278 -1.631 l
+34.792 -1.631 l
+34.792 0.338 l
+34.792 0.551 34.752 0.709 34.675 0.808 c
+34.594 0.915 34.462 0.97 34.279 0.97 c
+34.131 0.97 34.013 0.912 33.926 0.794 c
+33.838 0.683 33.782 0.544 33.764 0.368 c
+33.764 -1.631 l
+33.279 -1.631 l
+33.279 0.353 l
+33.267 0.764 33.095 0.97 32.764 0.97 c
+32.518 0.97 32.346 0.845 32.25 0.603 c
+32.25 -1.631 l
+31.765 -1.631 l
+31.765 1.352 l
+h
+37.255 -1.631 m
+37.225 -1.565 37.203 -1.455 37.196 -1.309 c
+37.02 -1.565 36.799 -1.69 36.535 -1.69 c
+36.259 -1.69 36.043 -1.617 35.887 -1.47 c
+35.741 -1.316 35.667 -1.099 35.667 -0.823 c
+35.667 -0.522 35.77 -0.279 35.976 -0.103 c
+36.182 0.081 36.465 0.176 36.828 0.176 c
+37.181 0.176 l
+37.181 0.5 l
+37.181 0.676 37.141 0.798 37.063 0.867 c
+36.983 0.945 36.866 0.985 36.711 0.985 c
+36.564 0.985 36.439 0.941 36.344 0.852 c
+36.255 0.764 36.211 0.654 36.211 0.529 c
+35.727 0.529 l
+35.727 0.676 35.77 0.816 35.858 0.956 c
+35.947 1.103 36.064 1.213 36.211 1.294 c
+36.365 1.371 36.538 1.411 36.726 1.411 c
+37.038 1.411 37.273 1.33 37.431 1.176 c
+37.585 1.029 37.666 0.808 37.666 0.515 c
+37.666 -0.985 l
+37.674 -1.22 37.711 -1.422 37.769 -1.588 c
+37.769 -1.631 l
+h
+36.608 -1.249 m
+36.726 -1.249 36.836 -1.216 36.946 -1.147 c
+37.053 -1.081 37.13 -0.996 37.181 -0.897 c
+37.181 -0.191 l
+36.917 -0.191 l
+36.681 -0.191 36.494 -0.243 36.358 -0.338 c
+36.23 -0.437 36.167 -0.58 36.167 -0.765 c
+36.167 -0.933 36.197 -1.055 36.255 -1.132 c
+36.321 -1.213 36.439 -1.249 36.608 -1.249 c
+39.688 -0.867 m
+39.688 -0.761 39.647 -0.673 39.57 -0.603 c
+39.49 -0.526 39.338 -0.437 39.114 -0.338 c
+38.85 -0.231 38.663 -0.14 38.555 -0.059 c
+38.445 0.018 38.368 0.106 38.32 0.206 c
+38.269 0.301 38.247 0.419 38.247 0.559 c
+38.247 0.801 38.335 1.003 38.512 1.161 c
+38.688 1.326 38.912 1.411 39.187 1.411 c
+39.482 1.411 39.717 1.323 39.893 1.147 c
+40.07 0.977 40.158 0.764 40.158 0.5 c
+39.673 0.5 l
+39.673 0.636 39.621 0.75 39.526 0.838 c
+39.438 0.933 39.324 0.985 39.187 0.985 c
+39.041 0.985 38.927 0.945 38.85 0.867 c
+38.769 0.798 38.732 0.698 38.732 0.573 c
+38.732 0.474 38.761 0.397 38.821 0.338 c
+38.879 0.279 39.019 0.198 39.247 0.103 c
+39.607 -0.044 39.853 -0.187 39.981 -0.324 c
+40.118 -0.453 40.188 -0.625 40.188 -0.838 c
+40.188 -1.095 40.091 -1.301 39.908 -1.455 c
+39.731 -1.613 39.496 -1.69 39.203 -1.69 c
+38.886 -1.69 38.632 -1.602 38.438 -1.426 c
+38.25 -1.242 38.159 -1.01 38.159 -0.735 c
+38.644 -0.735 l
+38.651 -0.904 38.703 -1.037 38.79 -1.132 c
+38.886 -1.22 39.026 -1.264 39.203 -1.264 c
+39.357 -1.264 39.474 -1.231 39.555 -1.161 c
+39.644 -1.095 39.688 -0.996 39.688 -0.867 c
+41.275 2.072 m
+41.275 1.352 l
+41.73 1.352 l
+41.73 0.956 l
+41.275 0.956 l
+41.275 -0.897 l
+41.275 -1.014 41.294 -1.103 41.334 -1.161 c
+41.371 -1.22 41.441 -1.249 41.539 -1.249 c
+41.599 -1.249 41.661 -1.242 41.73 -1.22 c
+41.73 -1.631 l
+41.613 -1.669 41.499 -1.69 41.393 -1.69 c
+41.194 -1.69 41.044 -1.625 40.937 -1.484 c
+40.838 -1.349 40.79 -1.154 40.79 -0.897 c
+40.79 0.956 l
+40.334 0.956 l
+40.334 1.352 l
+40.79 1.352 l
+40.79 2.072 l
+h
+43.256 -1.69 m
+42.881 -1.69 42.598 -1.584 42.403 -1.367 c
+42.204 -1.143 42.109 -0.816 42.109 -0.382 c
+42.109 -0.015 l
+42.109 0.426 42.201 0.771 42.389 1.029 c
+42.584 1.282 42.859 1.411 43.212 1.411 c
+43.553 1.411 43.807 1.297 43.976 1.073 c
+44.153 0.845 44.244 0.5 44.255 0.029 c
+44.255 -0.279 l
+42.594 -0.279 l
+42.594 -0.353 l
+42.594 -0.676 42.653 -0.912 42.771 -1.058 c
+42.888 -1.199 43.058 -1.264 43.285 -1.264 c
+43.432 -1.264 43.557 -1.242 43.667 -1.191 c
+43.774 -1.132 43.877 -1.043 43.976 -0.926 c
+44.226 -1.235 l
+44.02 -1.54 43.696 -1.69 43.256 -1.69 c
+43.212 0.985 m
+43.006 0.985 42.852 0.915 42.756 0.779 c
+42.657 0.64 42.601 0.426 42.594 0.133 c
+43.77 0.133 l
+43.77 0.206 l
+43.748 0.478 43.696 0.676 43.608 0.794 c
+43.521 0.918 43.388 0.985 43.212 0.985 c
+45.902 0.897 m
+45.832 0.904 45.759 0.912 45.681 0.912 c
+45.424 0.912 45.248 0.771 45.152 0.5 c
+45.152 -1.631 l
+44.667 -1.631 l
+44.667 1.352 l
+45.138 1.352 l
+45.152 1.043 l
+45.277 1.286 45.46 1.411 45.695 1.411 c
+45.773 1.411 45.836 1.396 45.886 1.367 c
+h
+f
+Q
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 672.622 356.2839 cm
+0 0 m
+-0.114 20.002 26.63 15.225 20.909 37.795 c
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 694.0562 392.01 cm
+0 0 m
+1.298 -0.771 l
+-0.654 2.583 l
+-0.772 -1.297 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 694.0562 392.01 cm
+0 0 m
+1.298 -0.771 l
+-0.654 2.584 l
+-0.772 -1.297 l
+0 0 l
+h
+S
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 635.2201 383.5761 cm
+0 0 m
+0 0.46 0.081 0.809 0.25 1.044 c
+0.426 1.287 0.676 1.411 0.999 1.411 c
+1.301 1.411 1.532 1.279 1.691 1.015 c
+1.72 1.353 l
+2.161 1.353 l
+2.161 -1.66 l
+2.161 -2.032 2.061 -2.315 1.866 -2.513 c
+1.679 -2.708 1.419 -2.807 1.087 -2.807 c
+0.941 -2.807 0.771 -2.767 0.588 -2.69 c
+0.401 -2.62 0.264 -2.532 0.176 -2.425 c
+0.368 -2.087 l
+0.573 -2.293 0.798 -2.395 1.043 -2.395 c
+1.444 -2.395 1.65 -2.167 1.661 -1.72 c
+1.661 -1.337 l
+1.503 -1.572 1.282 -1.69 0.999 -1.69 c
+0.684 -1.69 0.441 -1.572 0.264 -1.337 c
+0.096 -1.102 0.008 -0.771 0 -0.338 c
+h
+0.485 -0.278 m
+0.485 -0.613 0.532 -0.86 0.632 -1.014 c
+0.727 -1.172 0.889 -1.249 1.117 -1.249 c
+1.359 -1.249 1.544 -1.128 1.661 -0.881 c
+1.661 0.603 l
+1.544 0.846 1.367 0.971 1.132 0.971 c
+0.904 0.971 0.742 0.89 0.646 0.736 c
+0.547 0.578 0.492 0.339 0.485 0.015 c
+h
+3.223 -1.631 -0.5 2.984 re
+3.252 2.147 m
+3.252 2.058 3.227 1.985 3.179 1.926 c
+3.138 1.875 3.069 1.852 2.973 1.852 c
+2.884 1.852 2.815 1.875 2.767 1.926 c
+2.726 1.985 2.708 2.051 2.708 2.132 c
+2.708 2.22 2.726 2.294 2.767 2.352 c
+2.815 2.411 2.884 2.44 2.973 2.44 c
+3.069 2.44 3.138 2.411 3.179 2.352 c
+3.227 2.294 3.252 2.224 3.252 2.147 c
+4.531 2.073 m
+4.531 1.353 l
+4.987 1.353 l
+4.987 0.956 l
+4.531 0.956 l
+4.531 -0.897 l
+4.531 -1.014 4.549 -1.102 4.59 -1.161 c
+4.627 -1.219 4.696 -1.249 4.796 -1.249 c
+4.854 -1.249 4.917 -1.242 4.987 -1.219 c
+4.987 -1.631 l
+4.869 -1.668 4.755 -1.69 4.648 -1.69 c
+4.45 -1.69 4.299 -1.624 4.193 -1.484 c
+4.094 -1.348 4.046 -1.153 4.046 -0.897 c
+4.046 0.956 l
+3.59 0.956 l
+3.59 1.353 l
+4.046 1.353 l
+4.046 2.073 l
+h
+8.801 -0.278 m
+8.801 -0.749 8.717 -1.102 8.551 -1.337 c
+8.382 -1.572 8.143 -1.69 7.831 -1.69 c
+7.526 -1.69 7.294 -1.579 7.14 -1.352 c
+7.14 -2.778 l
+6.655 -2.778 l
+6.655 1.353 l
+7.096 1.353 l
+7.125 1.015 l
+7.279 1.279 7.511 1.411 7.817 1.411 c
+8.147 1.411 8.393 1.293 8.551 1.058 c
+8.717 0.831 8.801 0.493 8.801 0.044 c
+h
+8.316 0 m
+8.316 0.331 8.261 0.578 8.154 0.736 c
+8.055 0.89 7.894 0.971 7.669 0.971 c
+7.434 0.971 7.258 0.853 7.14 0.618 c
+7.14 -0.926 l
+7.258 -1.153 7.437 -1.263 7.684 -1.263 c
+7.897 -1.263 8.055 -1.186 8.154 -1.028 c
+8.261 -0.874 8.316 -0.631 8.316 -0.309 c
+h
+10.774 -1.367 m
+10.616 -1.583 10.381 -1.69 10.069 -1.69 c
+9.804 -1.69 9.598 -1.598 9.452 -1.411 c
+9.311 -1.227 9.246 -0.951 9.246 -0.588 c
+9.246 1.353 l
+9.731 1.353 l
+9.731 -0.558 l
+9.731 -1.022 9.87 -1.249 10.157 -1.249 c
+10.451 -1.249 10.649 -1.117 10.759 -0.852 c
+10.759 1.353 l
+11.26 1.353 l
+11.26 -1.631 l
+10.789 -1.631 l
+h
+13.251 -0.866 m
+13.251 -0.76 13.211 -0.672 13.134 -0.602 c
+13.053 -0.525 12.902 -0.436 12.678 -0.338 c
+12.413 -0.231 12.226 -0.139 12.12 -0.058 c
+12.01 0.019 11.932 0.107 11.884 0.206 c
+11.833 0.302 11.811 0.42 11.811 0.559 c
+11.811 0.802 11.898 1.004 12.075 1.162 c
+12.251 1.327 12.476 1.411 12.752 1.411 c
+13.045 1.411 13.28 1.324 13.457 1.147 c
+13.633 0.977 13.722 0.765 13.722 0.5 c
+13.236 0.5 l
+13.236 0.636 13.185 0.75 13.089 0.838 c
+13.001 0.934 12.887 0.985 12.752 0.985 c
+12.604 0.985 12.49 0.944 12.413 0.867 c
+12.332 0.798 12.295 0.699 12.295 0.574 c
+12.295 0.474 12.326 0.397 12.384 0.339 c
+12.443 0.279 12.582 0.198 12.81 0.103 c
+13.17 -0.043 13.417 -0.187 13.545 -0.323 c
+13.681 -0.452 13.751 -0.625 13.751 -0.837 c
+13.751 -1.095 13.656 -1.3 13.471 -1.454 c
+13.295 -1.612 13.06 -1.69 12.766 -1.69 c
+12.45 -1.69 12.197 -1.602 12.002 -1.425 c
+11.815 -1.242 11.723 -1.01 11.723 -0.735 c
+12.208 -0.735 l
+12.215 -0.904 12.266 -1.036 12.355 -1.132 c
+12.45 -1.219 12.59 -1.263 12.766 -1.263 c
+12.92 -1.263 13.038 -1.23 13.119 -1.161 c
+13.207 -1.095 13.251 -0.995 13.251 -0.866 c
+14.692 1.044 m
+14.875 1.287 15.11 1.411 15.397 1.411 c
+15.927 1.411 16.195 1.058 16.206 0.353 c
+16.206 -1.631 l
+15.721 -1.631 l
+15.721 0.324 l
+15.721 0.559 15.68 0.724 15.603 0.823 c
+15.522 0.919 15.405 0.971 15.25 0.971 c
+15.133 0.971 15.023 0.93 14.927 0.853 c
+14.828 0.772 14.751 0.665 14.692 0.53 c
+14.692 -1.631 l
+14.207 -1.631 l
+14.207 2.602 l
+14.692 2.602 l
+h
+f
+Q
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 656.8204 356.6593 cm
+0 0 m
+-0.118 20.001 -28.66 16.157 -38.177 39.485 c
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 619.4479 394.1704 cm
+0 0 m
+1.393 -0.584 l
+-1.007 2.47 l
+-0.584 -1.393 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 619.4479 394.1704 cm
+0 0 m
+1.393 -0.584 l
+-1.007 2.47 l
+-0.584 -1.393 l
+0 0 l
+h
+S
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 588.0693 386.1895 cm
+0 0 m
+0 0.459 0.081 0.808 0.249 1.043 c
+0.426 1.286 0.676 1.411 0.999 1.411 c
+1.301 1.411 1.533 1.278 1.691 1.014 c
+1.72 1.352 l
+2.161 1.352 l
+2.161 -1.661 l
+2.161 -2.032 2.061 -2.315 1.866 -2.514 c
+1.679 -2.708 1.419 -2.808 1.088 -2.808 c
+0.941 -2.808 0.771 -2.768 0.588 -2.691 c
+0.401 -2.62 0.264 -2.532 0.176 -2.425 c
+0.368 -2.087 l
+0.573 -2.294 0.798 -2.396 1.043 -2.396 c
+1.444 -2.396 1.65 -2.168 1.66 -1.72 c
+1.66 -1.338 l
+1.503 -1.573 1.282 -1.69 0.999 -1.69 c
+0.683 -1.69 0.441 -1.573 0.264 -1.338 c
+0.095 -1.103 0.008 -0.772 0 -0.339 c
+h
+0.484 -0.279 m
+0.484 -0.614 0.532 -0.86 0.632 -1.014 c
+0.727 -1.172 0.889 -1.249 1.117 -1.249 c
+1.359 -1.249 1.544 -1.128 1.66 -0.882 c
+1.66 0.602 l
+1.544 0.845 1.367 0.97 1.132 0.97 c
+0.904 0.97 0.742 0.889 0.646 0.735 c
+0.548 0.577 0.492 0.338 0.484 0.014 c
+h
+3.227 -1.632 -0.5 2.984 re
+3.256 2.146 m
+3.256 2.057 3.23 1.984 3.183 1.926 c
+3.142 1.874 3.072 1.851 2.977 1.851 c
+2.888 1.851 2.818 1.874 2.771 1.926 c
+2.73 1.984 2.712 2.05 2.712 2.131 c
+2.712 2.219 2.73 2.293 2.771 2.352 c
+2.818 2.41 2.888 2.439 2.977 2.439 c
+3.072 2.439 3.142 2.41 3.183 2.352 c
+3.23 2.293 3.256 2.223 3.256 2.146 c
+4.534 2.072 m
+4.534 1.352 l
+4.991 1.352 l
+4.991 0.955 l
+4.534 0.955 l
+4.534 -0.897 l
+4.534 -1.014 4.553 -1.103 4.594 -1.162 c
+4.63 -1.22 4.7 -1.249 4.799 -1.249 c
+4.858 -1.249 4.92 -1.243 4.991 -1.22 c
+4.991 -1.632 l
+4.873 -1.669 4.758 -1.69 4.652 -1.69 c
+4.453 -1.69 4.303 -1.625 4.197 -1.484 c
+4.097 -1.349 4.05 -1.154 4.05 -0.897 c
+4.05 0.955 l
+3.594 0.955 l
+3.594 1.352 l
+4.05 1.352 l
+4.05 2.072 l
+h
+6.865 -1.632 m
+6.865 0.955 l
+6.483 0.955 l
+6.483 1.352 l
+6.865 1.352 l
+6.865 1.691 l
+6.872 1.992 6.953 2.227 7.1 2.396 c
+7.247 2.572 7.456 2.66 7.732 2.66 c
+7.827 2.66 7.927 2.645 8.025 2.616 c
+7.996 2.204 l
+7.927 2.212 7.853 2.219 7.775 2.219 c
+7.501 2.219 7.364 2.021 7.364 1.631 c
+7.364 1.352 l
+7.864 1.352 l
+7.864 0.955 l
+7.364 0.955 l
+7.364 -1.632 l
+h
+9.323 -1.69 m
+8.948 -1.69 8.665 -1.584 8.47 -1.367 c
+8.272 -1.143 8.176 -0.816 8.176 -0.383 c
+8.176 -0.015 l
+8.176 0.426 8.268 0.771 8.455 1.028 c
+8.65 1.282 8.926 1.411 9.279 1.411 c
+9.62 1.411 9.874 1.297 10.043 1.072 c
+10.219 0.845 10.311 0.5 10.323 0.029 c
+10.323 -0.279 l
+8.661 -0.279 l
+8.661 -0.353 l
+8.661 -0.676 8.72 -0.912 8.837 -1.058 c
+8.955 -1.199 9.124 -1.264 9.352 -1.264 c
+9.5 -1.264 9.624 -1.243 9.735 -1.191 c
+9.841 -1.132 9.944 -1.044 10.043 -0.927 c
+10.293 -1.235 l
+10.088 -1.54 9.764 -1.69 9.323 -1.69 c
+9.279 0.985 m
+9.073 0.985 8.918 0.914 8.823 0.779 c
+8.724 0.639 8.669 0.426 8.661 0.132 c
+9.837 0.132 l
+9.837 0.205 l
+9.815 0.478 9.764 0.675 9.675 0.793 c
+9.587 0.918 9.455 0.985 9.279 0.985 c
+11.366 2.072 m
+11.366 1.352 l
+11.821 1.352 l
+11.821 0.955 l
+11.366 0.955 l
+11.366 -0.897 l
+11.366 -1.014 11.384 -1.103 11.424 -1.162 c
+11.461 -1.22 11.532 -1.249 11.63 -1.249 c
+11.69 -1.249 11.752 -1.243 11.821 -1.22 c
+11.821 -1.632 l
+11.704 -1.669 11.59 -1.69 11.484 -1.69 c
+11.285 -1.69 11.135 -1.625 11.028 -1.484 c
+10.929 -1.349 10.881 -1.154 10.881 -0.897 c
+10.881 0.955 l
+10.425 0.955 l
+10.425 1.352 l
+10.881 1.352 l
+10.881 2.072 l
+h
+13.317 -1.264 m
+13.483 -1.264 13.615 -1.216 13.714 -1.118 c
+13.81 -1.022 13.865 -0.879 13.876 -0.691 c
+14.331 -0.691 l
+14.321 -0.977 14.217 -1.216 14.023 -1.411 c
+13.836 -1.598 13.6 -1.69 13.317 -1.69 c
+12.953 -1.69 12.675 -1.573 12.479 -1.338 c
+12.281 -1.103 12.185 -0.757 12.185 -0.294 c
+12.185 0.029 l
+12.185 0.478 12.278 0.823 12.465 1.058 c
+12.66 1.294 12.943 1.411 13.317 1.411 c
+13.618 1.411 13.861 1.311 14.038 1.117 c
+14.221 0.918 14.321 0.654 14.331 0.323 c
+13.876 0.323 l
+13.853 0.548 13.795 0.713 13.699 0.823 c
+13.612 0.929 13.483 0.985 13.317 0.985 c
+13.101 0.985 12.939 0.911 12.833 0.764 c
+12.733 0.625 12.677 0.397 12.671 0.073 c
+12.671 -0.309 l
+12.671 -0.661 12.718 -0.912 12.818 -1.058 c
+12.924 -1.199 13.089 -1.264 13.317 -1.264 c
+15.21 1.043 m
+15.393 1.286 15.628 1.411 15.915 1.411 c
+16.444 1.411 16.712 1.058 16.724 0.353 c
+16.724 -1.632 l
+16.239 -1.632 l
+16.239 0.323 l
+16.239 0.558 16.199 0.723 16.122 0.823 c
+16.041 0.918 15.923 0.97 15.769 0.97 c
+15.651 0.97 15.54 0.929 15.445 0.852 c
+15.345 0.771 15.268 0.665 15.21 0.529 c
+15.21 -1.632 l
+14.724 -1.632 l
+14.724 2.601 l
+15.21 2.601 l
+h
+f
+Q
+q 1 0 0 1 594.5256 379.6043 cm
+0 0 m
+0 0.43 0.104 0.771 0.309 1.028 c
+0.522 1.282 0.802 1.411 1.147 1.411 c
+1.488 1.411 1.764 1.282 1.97 1.028 c
+2.182 0.783 2.297 0.448 2.308 0.029 c
+2.308 -0.279 l
+2.308 -0.713 2.198 -1.055 1.985 -1.309 c
+1.779 -1.565 1.5 -1.691 1.147 -1.691 c
+0.802 -1.691 0.53 -1.569 0.324 -1.324 c
+0.118 -1.081 0.008 -0.746 0 -0.324 c
+h
+0.485 -0.279 m
+0.485 -0.595 0.544 -0.838 0.661 -1.014 c
+0.786 -1.183 0.948 -1.264 1.147 -1.264 c
+1.577 -1.264 1.801 -0.956 1.823 -0.339 c
+1.823 0 l
+1.823 0.301 1.756 0.544 1.632 0.72 c
+1.515 0.897 1.353 0.985 1.147 0.985 c
+0.948 0.985 0.786 0.897 0.661 0.72 c
+0.544 0.544 0.485 0.301 0.485 0 c
+h
+3.984 0.897 m
+3.914 0.904 3.84 0.911 3.763 0.911 c
+3.506 0.911 3.329 0.771 3.234 0.5 c
+3.234 -1.632 l
+2.749 -1.632 l
+2.749 1.352 l
+3.219 1.352 l
+3.234 1.043 l
+3.358 1.286 3.543 1.411 3.778 1.411 c
+3.855 1.411 3.917 1.396 3.969 1.367 c
+h
+f
+Q
+q 1 0 0 1 589.5942 373.0192 cm
+0 0 m
+0 0.459 0.081 0.808 0.25 1.043 c
+0.426 1.286 0.676 1.411 0.999 1.411 c
+1.301 1.411 1.532 1.278 1.691 1.014 c
+1.72 1.352 l
+2.161 1.352 l
+2.161 -1.661 l
+2.161 -2.032 2.061 -2.315 1.866 -2.514 c
+1.679 -2.708 1.419 -2.808 1.087 -2.808 c
+0.941 -2.808 0.771 -2.768 0.588 -2.691 c
+0.401 -2.62 0.264 -2.533 0.176 -2.425 c
+0.368 -2.087 l
+0.573 -2.294 0.798 -2.396 1.043 -2.396 c
+1.444 -2.396 1.65 -2.168 1.661 -1.72 c
+1.661 -1.338 l
+1.503 -1.573 1.282 -1.691 0.999 -1.691 c
+0.684 -1.691 0.441 -1.573 0.264 -1.338 c
+0.096 -1.103 0.008 -0.772 0 -0.339 c
+h
+0.485 -0.279 m
+0.485 -0.614 0.532 -0.86 0.632 -1.014 c
+0.727 -1.172 0.889 -1.249 1.117 -1.249 c
+1.359 -1.249 1.544 -1.128 1.661 -0.882 c
+1.661 0.602 l
+1.544 0.845 1.367 0.97 1.132 0.97 c
+0.904 0.97 0.742 0.889 0.646 0.735 c
+0.547 0.577 0.492 0.338 0.485 0.014 c
+h
+3.223 -1.632 -0.5 2.984 re
+3.252 2.146 m
+3.252 2.057 3.227 1.984 3.179 1.926 c
+3.138 1.874 3.069 1.851 2.973 1.851 c
+2.884 1.851 2.815 1.874 2.767 1.926 c
+2.726 1.984 2.708 2.05 2.708 2.131 c
+2.708 2.219 2.726 2.293 2.767 2.352 c
+2.815 2.41 2.884 2.439 2.973 2.439 c
+3.069 2.439 3.138 2.41 3.179 2.352 c
+3.227 2.293 3.252 2.223 3.252 2.146 c
+4.531 2.072 m
+4.531 1.352 l
+4.987 1.352 l
+4.987 0.955 l
+4.531 0.955 l
+4.531 -0.897 l
+4.531 -1.014 4.549 -1.103 4.59 -1.162 c
+4.627 -1.22 4.696 -1.249 4.796 -1.249 c
+4.854 -1.249 4.917 -1.243 4.987 -1.22 c
+4.987 -1.632 l
+4.869 -1.669 4.755 -1.691 4.648 -1.691 c
+4.45 -1.691 4.299 -1.625 4.193 -1.484 c
+4.094 -1.349 4.046 -1.154 4.046 -0.897 c
+4.046 0.955 l
+3.59 0.955 l
+3.59 1.352 l
+4.046 1.352 l
+4.046 2.072 l
+h
+8.801 -0.279 m
+8.801 -0.75 8.717 -1.103 8.551 -1.338 c
+8.382 -1.573 8.143 -1.691 7.831 -1.691 c
+7.526 -1.691 7.294 -1.58 7.14 -1.353 c
+7.14 -2.778 l
+6.655 -2.778 l
+6.655 1.352 l
+7.096 1.352 l
+7.125 1.014 l
+7.279 1.278 7.511 1.411 7.817 1.411 c
+8.147 1.411 8.393 1.294 8.551 1.058 c
+8.717 0.831 8.801 0.492 8.801 0.044 c
+h
+8.316 0 m
+8.316 0.33 8.261 0.577 8.154 0.735 c
+8.055 0.889 7.894 0.97 7.669 0.97 c
+7.434 0.97 7.258 0.852 7.14 0.617 c
+7.14 -0.927 l
+7.258 -1.154 7.437 -1.264 7.684 -1.264 c
+7.897 -1.264 8.055 -1.187 8.154 -1.029 c
+8.261 -0.875 8.316 -0.632 8.316 -0.309 c
+h
+10.774 -1.367 m
+10.616 -1.584 10.381 -1.691 10.069 -1.691 c
+9.804 -1.691 9.598 -1.598 9.452 -1.411 c
+9.311 -1.228 9.246 -0.952 9.246 -0.588 c
+9.246 1.352 l
+9.731 1.352 l
+9.731 -0.559 l
+9.731 -1.022 9.87 -1.249 10.157 -1.249 c
+10.451 -1.249 10.649 -1.118 10.759 -0.853 c
+10.759 1.352 l
+11.26 1.352 l
+11.26 -1.632 l
+10.789 -1.632 l
+h
+12.34 -1.632 -0.5 4.233 re
+13.545 -1.632 -0.5 4.233 re
+f
+Q
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 600.5115 395.7545 cm
+0 0 m
+19.682 -14.736 18.124 -46.64 36.296 -49.646 c
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 634.7023 346.454 cm
+0 0 m
+-1.228 -0.878 l
+2.631 -0.433 l
+-0.878 1.227 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 634.7023 346.4541 cm
+0 0 m
+-1.228 -0.878 l
+2.631 -0.433 l
+-0.878 1.227 l
+0 0 l
+h
+S
+Q
+0.793 0.801 0.129 0.016 k
+535.667 213.99 238.665 -21.457 re
+f
+0 0 0 0 k
+q 1 0 0 1 571.6026 198.5045 cm
+0 0 m
+0 9.363 l
+2.484 9.363 l
+3.572 9.363 4.439 9.014 5.086 8.32 c
+5.74 7.621 6.074 6.674 6.086 5.468 c
+6.086 3.954 l
+6.086 2.72 5.762 1.749 5.115 1.043 c
+4.469 0.345 3.572 0 2.425 0 c
+h
+1.897 7.79 m
+1.897 1.573 l
+2.454 1.573 l
+3.09 1.573 3.535 1.738 3.792 2.072 c
+4.046 2.404 4.178 2.977 4.189 3.792 c
+4.189 5.409 l
+4.189 6.291 4.064 6.901 3.821 7.247 c
+3.586 7.588 3.175 7.769 2.587 7.79 c
+h
+6.913 0.926 m
+6.913 1.22 7.008 1.459 7.206 1.646 c
+7.401 1.83 7.655 1.926 7.971 1.926 c
+8.272 1.926 8.522 1.83 8.72 1.646 c
+8.926 1.459 9.029 1.22 9.029 0.926 c
+9.029 0.621 8.926 0.374 8.72 0.191 c
+8.522 0.015 8.272 -0.073 7.971 -0.073 c
+7.665 -0.073 7.412 0.018 7.206 0.206 c
+7.008 0.389 6.913 0.632 6.913 0.926 c
+20.266 3.116 m
+20.215 2.047 19.914 1.238 19.355 0.691 c
+18.804 0.139 18.032 -0.133 17.032 -0.133 c
+15.963 -0.133 15.144 0.213 14.578 0.912 c
+14.019 1.606 13.74 2.602 13.74 3.896 c
+13.74 5.468 l
+13.74 6.761 14.026 7.754 14.607 8.452 c
+15.195 9.147 16.008 9.496 17.047 9.496 c
+18.065 9.496 18.84 9.205 19.37 8.628 c
+19.898 8.058 20.201 7.239 20.281 6.173 c
+18.385 6.173 l
+18.362 6.838 18.26 7.295 18.076 7.541 c
+17.889 7.794 17.547 7.923 17.047 7.923 c
+16.548 7.923 16.187 7.746 15.974 7.393 c
+15.769 7.041 15.655 6.456 15.636 5.644 c
+15.636 3.881 l
+15.636 2.947 15.739 2.308 15.945 1.955 c
+16.158 1.61 16.521 1.44 17.032 1.44 c
+17.521 1.44 17.859 1.558 18.047 1.793 c
+18.242 2.036 18.348 2.477 18.37 3.116 c
+h
+28.244 3.836 m
+28.244 2.58 27.943 1.606 27.347 0.912 c
+26.749 0.213 25.926 -0.133 24.878 -0.133 c
+23.827 -0.133 23 0.21 22.394 0.897 c
+21.795 1.591 21.49 2.558 21.483 3.792 c
+21.483 5.394 l
+21.483 6.677 21.78 7.68 22.379 8.407 c
+22.975 9.132 23.805 9.496 24.864 9.496 c
+25.899 9.496 26.719 9.136 27.318 8.422 c
+27.925 7.717 28.233 6.721 28.244 5.438 c
+h
+26.348 5.409 m
+26.348 6.25 26.223 6.879 25.98 7.291 c
+25.745 7.702 25.371 7.908 24.864 7.908 c
+24.363 7.908 23.989 7.706 23.746 7.306 c
+23.511 6.913 23.386 6.313 23.379 5.512 c
+23.379 3.836 l
+23.379 3.021 23.5 2.418 23.746 2.028 c
+23.989 1.635 24.367 1.44 24.878 1.44 c
+25.367 1.44 25.731 1.631 25.966 2.014 c
+26.208 2.396 26.337 2.984 26.348 3.778 c
+h
+32.286 9.363 m
+34.065 2.587 l
+35.814 9.363 l
+38.283 9.363 l
+38.283 0 l
+36.388 0 l
+36.388 2.528 l
+36.564 6.438 l
+34.697 0 l
+33.404 0 l
+31.536 6.438 l
+31.713 2.528 l
+31.713 0 l
+29.817 0 l
+29.817 9.363 l
+h
+42.553 9.363 m
+44.332 2.587 l
+46.081 9.363 l
+48.551 9.363 l
+48.551 0 l
+46.655 0 l
+46.655 2.528 l
+46.831 6.438 l
+44.965 0 l
+43.671 0 l
+41.804 6.438 l
+41.981 2.528 l
+41.981 0 l
+40.084 0 l
+40.084 9.363 l
+h
+52.336 0 -1.897 9.363 re
+59.913 7.79 m
+57.591 7.79 l
+57.591 0 l
+55.695 0 l
+55.695 7.79 l
+53.416 7.79 l
+53.416 9.363 l
+59.913 9.363 l
+h
+65.047 2.454 m
+65.047 2.837 64.948 3.123 64.753 3.322 c
+64.554 3.516 64.202 3.719 63.695 3.925 c
+62.754 4.285 62.078 4.704 61.666 5.174 c
+61.254 5.652 61.049 6.221 61.049 6.879 c
+61.049 7.661 61.328 8.294 61.887 8.775 c
+62.445 9.253 63.155 9.496 64.018 9.496 c
+64.595 9.496 65.11 9.371 65.561 9.128 c
+66.01 8.882 66.355 8.54 66.59 8.099 c
+66.833 7.659 66.958 7.158 66.958 6.6 c
+65.077 6.6 l
+65.077 7.041 64.981 7.372 64.797 7.599 c
+64.61 7.823 64.342 7.937 63.988 7.937 c
+63.654 7.937 63.394 7.838 63.209 7.644 c
+63.033 7.456 62.945 7.195 62.945 6.865 c
+62.945 6.607 63.047 6.372 63.253 6.159 c
+63.459 5.953 63.82 5.737 64.342 5.512 c
+65.253 5.189 65.914 4.785 66.326 4.307 c
+66.745 3.825 66.958 3.212 66.958 2.469 c
+66.958 1.654 66.697 1.018 66.179 0.559 c
+65.657 0.095 64.951 -0.133 64.062 -0.133 c
+63.452 -0.133 62.901 -0.008 62.401 0.235 c
+61.909 0.488 61.522 0.845 61.24 1.309 c
+60.953 1.779 60.814 2.326 60.814 2.955 c
+62.71 2.955 l
+62.71 2.414 62.812 2.021 63.018 1.779 c
+63.232 1.532 63.581 1.411 64.062 1.411 c
+64.716 1.411 65.047 1.756 65.047 2.454 c
+68.876 -2.367 m
+67.906 -1.852 l
+68.141 -1.396 l
+68.413 -0.885 68.556 -0.375 68.568 0.133 c
+68.568 1.587 l
+70.155 1.587 l
+70.141 0.294 l
+70.141 -0.166 70.026 -0.636 69.802 -1.118 c
+69.574 -1.606 69.266 -2.022 68.876 -2.367 c
+74.877 0 m
+74.877 9.363 l
+77.773 9.363 l
+78.75 9.363 79.496 9.143 80.007 8.702 c
+80.514 8.268 80.771 7.632 80.771 6.791 c
+80.771 6.321 80.661 5.913 80.448 5.571 c
+80.242 5.226 79.952 4.976 79.581 4.821 c
+80 4.692 80.323 4.446 80.551 4.087 c
+80.786 3.734 80.904 3.285 80.904 2.749 c
+80.904 1.845 80.653 1.161 80.154 0.691 c
+79.654 0.228 78.926 0 77.979 0 c
+h
+76.773 4.072 m
+76.773 1.573 l
+77.979 1.573 l
+78.32 1.573 78.581 1.675 78.758 1.881 c
+78.934 2.094 79.022 2.396 79.022 2.778 c
+79.022 3.62 78.714 4.05 78.096 4.072 c
+h
+76.773 5.453 m
+77.758 5.453 l
+78.492 5.453 78.86 5.835 78.86 6.6 c
+78.86 7.019 78.772 7.324 78.596 7.511 c
+78.427 7.695 78.155 7.79 77.773 7.79 c
+76.773 7.79 l
+h
+85.306 3.425 m
+84.366 3.425 l
+84.366 0 l
+82.484 0 l
+82.484 9.363 l
+85.497 9.363 l
+86.445 9.363 87.176 9.117 87.687 8.628 c
+88.206 8.136 88.466 7.441 88.466 6.541 c
+88.466 5.295 88.015 4.424 87.114 3.925 c
+88.746 0.088 l
+88.746 0 l
+86.717 0 l
+h
+84.366 4.997 m
+85.438 4.997 l
+85.821 4.997 86.103 5.119 86.291 5.365 c
+86.475 5.619 86.57 5.957 86.57 6.379 c
+86.57 7.32 86.207 7.79 85.482 7.79 c
+84.366 7.79 l
+h
+94.452 1.911 m
+91.88 1.911 l
+91.381 0 l
+89.382 0 l
+92.306 9.363 l
+94.026 9.363 l
+96.981 0 l
+94.953 0 l
+h
+92.291 3.499 m
+94.041 3.499 l
+93.159 6.835 l
+h
+104.636 0 m
+102.739 0 l
+99.975 6.144 l
+99.975 0 l
+98.08 0 l
+98.08 9.363 l
+99.975 9.363 l
+102.739 3.219 l
+102.739 9.363 l
+104.636 9.363 l
+h
+112.738 3.116 m
+112.686 2.047 112.385 1.238 111.827 0.691 c
+111.275 0.139 110.504 -0.133 109.504 -0.133 c
+108.435 -0.133 107.616 0.213 107.05 0.912 c
+106.491 1.606 106.211 2.602 106.211 3.896 c
+106.211 5.468 l
+106.211 6.761 106.498 7.754 107.079 8.452 c
+107.667 9.147 108.479 9.496 109.519 9.496 c
+110.537 9.496 111.312 9.205 111.842 8.628 c
+112.37 8.058 112.671 7.239 112.752 6.173 c
+110.857 6.173 l
+110.834 6.838 110.732 7.295 110.548 7.541 c
+110.36 7.794 110.019 7.923 109.519 7.923 c
+109.019 7.923 108.659 7.746 108.446 7.393 c
+108.241 7.041 108.126 6.456 108.108 5.644 c
+108.108 3.881 l
+108.108 2.947 108.21 2.308 108.416 1.955 c
+108.63 1.61 108.993 1.44 109.504 1.44 c
+109.993 1.44 110.331 1.558 110.518 1.793 c
+110.713 2.036 110.82 2.477 110.842 3.116 c
+h
+120.686 0 m
+118.805 0 l
+118.805 4.013 l
+116.012 4.013 l
+116.012 0 l
+114.116 0 l
+114.116 9.363 l
+116.012 9.363 l
+116.012 5.571 l
+118.805 5.571 l
+118.805 9.363 l
+120.686 9.363 l
+h
+127.257 4.056 m
+124.317 4.056 l
+124.317 1.573 l
+127.801 1.573 l
+127.801 0 l
+122.421 0 l
+122.421 9.363 l
+127.786 9.363 l
+127.786 7.79 l
+124.317 7.79 l
+124.317 5.571 l
+127.257 5.571 l
+h
+133.019 2.454 m
+133.019 2.837 132.92 3.123 132.725 3.322 c
+132.527 3.516 132.174 3.719 131.667 3.925 c
+130.726 4.285 130.05 4.704 129.639 5.174 c
+129.227 5.652 129.021 6.221 129.021 6.879 c
+129.021 7.661 129.3 8.294 129.859 8.775 c
+130.418 9.253 131.127 9.496 131.99 9.496 c
+132.567 9.496 133.082 9.371 133.533 9.128 c
+133.982 8.882 134.327 8.54 134.562 8.099 c
+134.805 7.659 134.93 7.158 134.93 6.6 c
+133.049 6.6 l
+133.049 7.041 132.953 7.372 132.769 7.599 c
+132.582 7.823 132.313 7.937 131.96 7.937 c
+131.626 7.937 131.366 7.838 131.181 7.644 c
+131.005 7.456 130.917 7.195 130.917 6.865 c
+130.917 6.607 131.02 6.372 131.226 6.159 c
+131.432 5.953 131.792 5.737 132.313 5.512 c
+133.225 5.189 133.886 4.785 134.298 4.307 c
+134.717 3.825 134.93 3.212 134.93 2.469 c
+134.93 1.654 134.669 1.018 134.151 0.559 c
+133.629 0.095 132.924 -0.133 132.035 -0.133 c
+131.424 -0.133 130.873 -0.008 130.373 0.235 c
+129.88 0.488 129.495 0.845 129.212 1.309 c
+128.926 1.779 128.785 2.326 128.785 2.955 c
+130.682 2.955 l
+130.682 2.414 130.784 2.021 130.99 1.779 c
+131.204 1.532 131.553 1.411 132.035 1.411 c
+132.688 1.411 133.019 1.756 133.019 2.454 c
+143.985 1.911 m
+141.412 1.911 l
+140.912 0 l
+138.913 0 l
+141.838 9.363 l
+143.559 9.363 l
+146.513 0 l
+144.484 0 l
+h
+141.824 3.499 m
+143.573 3.499 l
+142.691 6.835 l
+h
+154.167 0 m
+152.271 0 l
+149.508 6.144 l
+149.508 0 l
+147.611 0 l
+147.611 9.363 l
+149.508 9.363 l
+152.271 3.219 l
+152.271 9.363 l
+154.167 9.363 l
+h
+155.92 0 m
+155.92 9.363 l
+158.405 9.363 l
+159.492 9.363 160.359 9.014 161.006 8.32 c
+161.66 7.621 161.994 6.674 162.006 5.468 c
+162.006 3.954 l
+162.006 2.72 161.682 1.749 161.036 1.043 c
+160.388 0.345 159.492 0 158.345 0 c
+h
+157.817 7.79 m
+157.817 1.573 l
+158.375 1.573 l
+159.01 1.573 159.455 1.738 159.712 2.072 c
+159.966 2.404 160.099 2.977 160.109 3.792 c
+160.109 5.409 l
+160.109 6.291 159.984 6.901 159.742 7.247 c
+159.507 7.588 159.095 7.769 158.507 7.79 c
+h
+172.361 7.79 m
+170.039 7.79 l
+170.039 0 l
+168.142 0 l
+168.142 7.79 l
+165.864 7.79 l
+165.864 9.363 l
+172.361 9.363 l
+h
+177.322 1.911 m
+174.75 1.911 l
+174.25 0 l
+172.251 0 l
+175.176 9.363 l
+176.896 9.363 l
+179.851 0 l
+177.821 0 l
+h
+175.161 3.499 m
+176.911 3.499 l
+176.028 6.835 l
+h
+187.182 1.058 m
+186.818 0.665 186.373 0.368 185.844 0.162 c
+185.314 -0.033 184.734 -0.133 184.109 -0.133 c
+183.029 -0.133 182.191 0.199 181.596 0.867 c
+180.996 1.532 180.692 2.502 180.684 3.778 c
+180.684 5.468 l
+180.684 6.761 180.963 7.754 181.522 8.452 c
+182.089 9.147 182.912 9.496 183.992 9.496 c
+185.01 9.496 185.774 9.238 186.284 8.731 c
+186.803 8.231 187.101 7.445 187.182 6.379 c
+185.344 6.379 l
+185.293 6.975 185.171 7.383 184.977 7.599 c
+184.778 7.813 184.47 7.923 184.051 7.923 c
+183.54 7.923 183.169 7.736 182.933 7.364 c
+182.706 6.99 182.588 6.398 182.581 5.585 c
+182.581 3.881 l
+182.581 3.028 182.706 2.404 182.963 2.014 c
+183.217 1.631 183.631 1.44 184.212 1.44 c
+184.583 1.44 184.888 1.514 185.123 1.661 c
+185.285 1.779 l
+185.285 3.499 l
+183.963 3.499 l
+183.963 4.924 l
+187.182 4.924 l
+h
+192.709 2.454 m
+192.709 2.837 192.609 3.123 192.414 3.322 c
+192.216 3.516 191.863 3.719 191.356 3.925 c
+190.415 4.285 189.739 4.704 189.328 5.174 c
+188.916 5.652 188.71 6.221 188.71 6.879 c
+188.71 7.661 188.99 8.294 189.548 8.775 c
+190.107 9.253 190.816 9.496 191.679 9.496 c
+192.256 9.496 192.771 9.371 193.223 9.128 c
+193.671 8.882 194.016 8.54 194.251 8.099 c
+194.494 7.659 194.619 7.158 194.619 6.6 c
+192.738 6.6 l
+192.738 7.041 192.642 7.372 192.458 7.599 c
+192.271 7.823 192.003 7.937 191.65 7.937 c
+191.315 7.937 191.055 7.838 190.871 7.644 c
+190.694 7.456 190.606 7.195 190.606 6.865 c
+190.606 6.607 190.709 6.372 190.915 6.159 c
+191.121 5.953 191.481 5.737 192.003 5.512 c
+192.914 5.189 193.575 4.785 193.987 4.307 c
+194.406 3.825 194.619 3.212 194.619 2.469 c
+194.619 1.654 194.359 1.018 193.84 0.559 c
+193.318 0.095 192.613 -0.133 191.724 -0.133 c
+191.113 -0.133 190.562 -0.008 190.062 0.235 c
+189.57 0.488 189.185 0.845 188.901 1.309 c
+188.615 1.779 188.475 2.326 188.475 2.955 c
+190.371 2.955 l
+190.371 2.414 190.474 2.021 190.679 1.779 c
+190.893 1.532 191.242 1.411 191.724 1.411 c
+192.377 1.411 192.709 1.756 192.709 2.454 c
+f
+Q
+0.797 0.801 0.141 0.02 K
+0.709 w 1 j 1 J
+q 1 0 0 1 535.6673 213.6594 cm
+0 0 m
+-254.669 0 l
+-254.669 -82.694 l
+-499.999 -82.694 l
+S
+Q
+0.793 0.801 0.129 0.016 k
+288.19 207.39 37.732 -54.746 re
+f
+0 0 0 0 k
+q 1 0 0 1 297.4504 198.7321 cm
+0 0 m
+0.294 0 0.445 0.195 0.455 0.588 c
+1.426 0.588 l
+1.426 0.154 1.294 -0.198 1.029 -0.47 c
+0.765 -0.735 0.426 -0.867 0.015 -0.867 c
+-0.496 -0.867 -0.889 -0.713 -1.161 -0.397 c
+-1.426 -0.073 -1.565 0.397 -1.573 1.014 c
+-1.573 1.338 l
+-1.573 1.962 -1.44 2.44 -1.176 2.764 c
+-0.904 3.094 -0.507 3.263 0.015 3.263 c
+0.445 3.263 0.786 3.123 1.043 2.851 c
+1.297 2.576 1.426 2.194 1.426 1.706 c
+0.455 1.706 l
+0.455 1.918 0.415 2.088 0.338 2.205 c
+0.268 2.33 0.151 2.396 -0.015 2.396 c
+-0.191 2.396 -0.32 2.33 -0.397 2.205 c
+-0.478 2.076 -0.522 1.827 -0.529 1.455 c
+-0.529 1.043 l
+-0.529 0.721 -0.515 0.493 -0.485 0.368 c
+-0.448 0.239 -0.393 0.147 -0.324 0.088 c
+-0.246 0.029 -0.139 0 0 0 c
+1.911 1.323 m
+1.911 1.929 2.051 2.404 2.337 2.749 c
+2.62 3.09 3.013 3.263 3.513 3.263 c
+4.021 3.263 4.417 3.09 4.704 2.749 c
+4.987 2.404 5.13 1.929 5.13 1.323 c
+5.13 1.058 l
+5.13 0.459 4.987 -0.011 4.704 -0.353 c
+4.417 -0.698 4.021 -0.867 3.513 -0.867 c
+3.002 -0.867 2.606 -0.698 2.323 -0.353 c
+2.047 -0.011 1.911 0.463 1.911 1.073 c
+h
+2.955 1.058 m
+2.955 0.353 3.138 0 3.513 0 c
+3.866 0 4.057 0.294 4.087 0.882 c
+4.087 1.323 l
+4.087 1.683 4.035 1.955 3.94 2.132 c
+3.84 2.308 3.697 2.396 3.513 2.396 c
+3.337 2.396 3.198 2.308 3.102 2.132 c
+3.002 1.955 2.955 1.683 2.955 1.323 c
+h
+6.747 3.19 m
+6.776 2.822 l
+7.011 3.117 7.32 3.263 7.703 3.263 c
+8.103 3.263 8.382 3.08 8.54 2.72 c
+8.775 3.08 9.103 3.263 9.525 3.263 c
+10.219 3.263 10.572 2.778 10.583 1.808 c
+10.583 -0.794 l
+9.554 -0.794 l
+9.554 1.749 l
+9.554 1.974 9.517 2.135 9.452 2.234 c
+9.392 2.33 9.282 2.381 9.128 2.381 c
+8.93 2.381 8.79 2.263 8.702 2.028 c
+8.702 -0.794 l
+7.659 -0.794 l
+7.659 1.735 l
+7.659 1.97 7.628 2.135 7.57 2.234 c
+7.511 2.33 7.401 2.381 7.247 2.381 c
+7.071 2.381 6.927 2.286 6.82 2.102 c
+6.82 -0.794 l
+5.777 -0.794 l
+5.777 3.19 l
+h
+12.332 3.19 m
+12.362 2.822 l
+12.597 3.117 12.906 3.263 13.288 3.263 c
+13.689 3.263 13.968 3.08 14.126 2.72 c
+14.361 3.08 14.688 3.263 15.111 3.263 c
+15.805 3.263 16.158 2.778 16.169 1.808 c
+16.169 -0.794 l
+15.14 -0.794 l
+15.14 1.749 l
+15.14 1.974 15.104 2.135 15.037 2.234 c
+14.978 2.33 14.868 2.381 14.714 2.381 c
+14.516 2.381 14.375 2.263 14.288 2.028 c
+14.288 -0.794 l
+13.244 -0.794 l
+13.244 1.735 l
+13.244 1.97 13.215 2.135 13.155 2.234 c
+13.097 2.33 12.987 2.381 12.833 2.381 c
+12.656 2.381 12.513 2.286 12.406 2.102 c
+12.406 -0.794 l
+11.362 -0.794 l
+11.362 3.19 l
+h
+18.036 -0.794 -1.043 3.984 re
+16.948 4.218 m
+16.948 4.374 16.996 4.501 17.095 4.601 c
+17.201 4.707 17.338 4.763 17.506 4.763 c
+17.683 4.763 17.819 4.707 17.918 4.601 c
+18.025 4.501 18.08 4.374 18.08 4.218 c
+18.08 4.05 18.025 3.913 17.918 3.807 c
+17.819 3.708 17.683 3.66 17.506 3.66 c
+17.338 3.66 17.201 3.708 17.095 3.807 c
+16.996 3.913 16.948 4.05 16.948 4.218 c
+20.05 4.16 m
+20.05 3.19 l
+20.579 3.19 l
+20.579 2.396 l
+20.05 2.396 l
+20.05 0.426 l
+20.05 0.268 20.068 0.162 20.108 0.103 c
+20.156 0.044 20.241 0.015 20.359 0.015 c
+20.465 0.015 20.549 0.023 20.608 0.044 c
+20.608 -0.764 l
+20.432 -0.831 20.241 -0.867 20.035 -0.867 c
+19.359 -0.867 19.013 -0.482 19.006 0.294 c
+19.006 2.396 l
+18.55 2.396 l
+18.55 3.19 l
+19.006 3.19 l
+19.006 4.16 l
+h
+f
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 331.7103 197.9382 cm
+0 0 m
+-0.04 0.088 -0.066 0.235 -0.073 0.441 c
+-0.309 0.096 -0.603 -0.073 -0.956 -0.073 c
+-1.319 -0.073 -1.602 0.023 -1.808 0.221 c
+-2.007 0.426 -2.102 0.713 -2.102 1.088 c
+-2.102 1.488 -1.966 1.808 -1.691 2.043 c
+-1.419 2.286 -1.043 2.411 -0.573 2.411 c
+-0.088 2.411 l
+-0.088 2.837 l
+-0.088 3.072 -0.143 3.238 -0.25 3.337 c
+-0.36 3.444 -0.522 3.499 -0.735 3.499 c
+-0.933 3.499 -1.095 3.44 -1.22 3.323 c
+-1.338 3.205 -1.396 3.057 -1.396 2.881 c
+-2.043 2.881 l
+-2.043 3.076 -1.984 3.267 -1.866 3.454 c
+-1.741 3.639 -1.58 3.786 -1.382 3.896 c
+-1.176 4.002 -0.948 4.057 -0.691 4.057 c
+-0.291 4.057 0.015 3.954 0.22 3.749 c
+0.434 3.543 0.548 3.248 0.559 2.866 c
+0.559 0.853 l
+0.559 0.548 0.595 0.283 0.676 0.059 c
+0.676 0 l
+h
+-0.867 0.515 m
+-0.702 0.515 -0.551 0.559 -0.411 0.647 c
+-0.264 0.736 -0.158 0.846 -0.088 0.985 c
+-0.088 1.926 l
+-0.455 1.926 l
+-0.771 1.926 -1.014 1.856 -1.191 1.72 c
+-1.367 1.592 -1.455 1.405 -1.455 1.162 c
+-1.455 0.934 -1.411 0.769 -1.323 0.661 c
+-1.234 0.563 -1.084 0.515 -0.867 0.515 c
+2.176 3.984 m
+2.19 3.543 l
+2.444 3.884 2.767 4.057 3.16 4.057 c
+3.866 4.057 4.222 3.587 4.233 2.646 c
+4.233 0 l
+3.587 0 l
+3.587 2.617 l
+3.587 2.929 3.532 3.15 3.425 3.278 c
+3.314 3.404 3.16 3.469 2.955 3.469 c
+2.797 3.469 2.649 3.414 2.514 3.308 c
+2.385 3.198 2.282 3.061 2.205 2.896 c
+2.205 0 l
+1.558 0 l
+1.558 3.984 l
+h
+6.791 2.176 m
+6.791 2.753 6.927 3.209 7.202 3.543 c
+7.485 3.884 7.857 4.057 8.32 4.057 c
+8.779 4.057 9.147 3.888 9.422 3.558 c
+9.705 3.234 9.852 2.786 9.863 2.22 c
+9.863 1.794 l
+9.863 1.224 9.72 0.769 9.437 0.426 c
+9.161 0.092 8.794 -0.073 8.334 -0.073 c
+7.871 -0.073 7.501 0.088 7.217 0.412 c
+6.942 0.742 6.799 1.183 6.791 1.735 c
+h
+7.437 1.794 m
+7.437 1.389 7.515 1.073 7.673 0.838 c
+7.838 0.603 8.058 0.485 8.334 0.485 c
+8.9 0.485 9.194 0.897 9.216 1.72 c
+9.216 2.176 l
+9.216 2.577 9.132 2.896 8.966 3.131 c
+8.808 3.373 8.592 3.499 8.32 3.499 c
+8.056 3.499 7.838 3.373 7.673 3.131 c
+7.515 2.896 7.437 2.577 7.437 2.176 c
+h
+13.582 1.794 m
+13.582 1.176 13.468 0.709 13.244 0.397 c
+13.027 0.081 12.704 -0.073 12.274 -0.073 c
+11.851 -0.073 11.539 0.107 11.333 0.47 c
+11.304 0 l
+10.701 0 l
+10.701 5.644 l
+11.348 5.644 l
+11.348 3.543 l
+11.561 3.884 11.869 4.057 12.274 4.057 c
+12.704 4.057 13.027 3.899 13.244 3.587 c
+13.468 3.282 13.582 2.816 13.582 2.19 c
+h
+12.935 2.176 m
+12.935 2.646 12.866 2.977 12.729 3.175 c
+12.601 3.37 12.391 3.469 12.097 3.469 c
+11.763 3.469 11.513 3.286 11.348 2.926 c
+11.348 1.044 l
+11.513 0.68 11.767 0.5 12.112 0.5 c
+12.406 0.5 12.615 0.603 12.744 0.809 c
+12.869 1.014 12.935 1.33 12.935 1.764 c
+h
+15.081 3.984 m
+15.081 -0.5 l
+15.081 -1.234 14.791 -1.602 14.214 -1.602 c
+14.074 -1.602 13.953 -1.579 13.847 -1.543 c
+13.847 -0.999 l
+13.916 -1.018 14.001 -1.028 14.111 -1.028 c
+14.217 -1.028 14.295 -0.985 14.346 -0.897 c
+14.406 -0.816 14.435 -0.675 14.435 -0.47 c
+14.435 3.984 l
+h
+15.111 5.027 m
+15.111 4.917 15.081 4.825 15.023 4.748 c
+14.963 4.678 14.868 4.645 14.743 4.645 c
+14.626 4.645 14.53 4.678 14.464 4.748 c
+14.406 4.825 14.375 4.917 14.375 5.027 c
+14.375 5.145 14.406 5.237 14.464 5.307 c
+14.53 5.384 14.626 5.424 14.743 5.424 c
+14.868 5.424 14.963 5.384 15.023 5.307 c
+15.081 5.226 15.111 5.134 15.111 5.027 c
+17.536 -0.073 m
+17.036 -0.073 16.654 0.073 16.39 0.368 c
+16.125 0.661 15.993 1.095 15.993 1.676 c
+15.993 2.147 l
+15.993 2.741 16.118 3.209 16.375 3.543 c
+16.64 3.884 16.999 4.057 17.463 4.057 c
+17.922 4.057 18.264 3.903 18.491 3.601 c
+18.726 3.308 18.848 2.845 18.859 2.22 c
+18.859 1.794 l
+16.64 1.794 l
+16.64 1.706 l
+16.64 1.272 16.717 0.96 16.875 0.765 c
+17.04 0.578 17.271 0.485 17.565 0.485 c
+17.76 0.485 17.933 0.518 18.08 0.588 c
+18.227 0.665 18.363 0.783 18.491 0.941 c
+18.83 0.53 l
+18.543 0.125 18.113 -0.073 17.536 -0.073 c
+17.463 3.499 m
+17.187 3.499 16.985 3.404 16.86 3.219 c
+16.731 3.032 16.658 2.741 16.64 2.352 c
+18.212 2.352 l
+18.212 2.44 l
+18.19 2.822 18.124 3.091 18.007 3.248 c
+17.889 3.414 17.705 3.499 17.463 3.499 c
+21.02 0.485 m
+21.232 0.485 21.406 0.548 21.534 0.676 c
+21.67 0.813 21.743 1.004 21.755 1.249 c
+22.372 1.249 l
+22.35 0.867 22.214 0.548 21.961 0.294 c
+21.703 0.048 21.391 -0.073 21.02 -0.073 c
+20.527 -0.073 20.153 0.077 19.888 0.383 c
+19.63 0.695 19.505 1.162 19.505 1.779 c
+19.505 2.22 l
+19.505 2.816 19.63 3.271 19.888 3.587 c
+20.153 3.899 20.527 4.057 21.02 4.057 c
+21.421 4.057 21.74 3.925 21.975 3.66 c
+22.217 3.404 22.35 3.057 22.372 2.617 c
+21.755 2.617 l
+21.733 2.911 21.659 3.131 21.534 3.278 c
+21.417 3.425 21.244 3.499 21.02 3.499 c
+20.725 3.499 20.509 3.4 20.373 3.205 c
+20.233 3.017 20.16 2.708 20.153 2.278 c
+20.153 1.764 l
+20.153 1.294 20.218 0.96 20.359 0.765 c
+20.505 0.578 20.725 0.485 21.02 0.485 c
+23.974 4.939 m
+23.974 3.984 l
+24.577 3.984 l
+24.577 3.454 l
+23.974 3.454 l
+23.974 0.985 l
+23.974 0.827 23.996 0.709 24.048 0.632 c
+24.106 0.551 24.195 0.515 24.312 0.515 c
+24.401 0.515 24.488 0.53 24.577 0.559 c
+24.577 0 l
+24.43 -0.047 24.276 -0.073 24.121 -0.073 c
+23.864 -0.073 23.669 0.019 23.534 0.206 c
+23.393 0.389 23.328 0.651 23.328 0.985 c
+23.328 3.454 l
+22.725 3.454 l
+22.725 3.984 l
+23.328 3.984 l
+23.328 4.939 l
+h
+f
+Q
+0 0 0 0 k
+q 1 0 0 1 301.3602 186.6493 cm
+0 0 m
+0 -0.646 -0.103 -1.132 -0.309 -1.455 c
+-0.515 -1.778 -0.837 -1.94 -1.278 -1.94 c
+-1.624 -1.94 -1.903 -1.786 -2.117 -1.469 c
+-2.146 -1.866 l
+-3.102 -1.866 l
+-3.102 3.778 l
+-2.057 3.778 l
+-2.057 1.794 l
+-1.863 2.058 -1.61 2.19 -1.294 2.19 c
+-0.852 2.19 -0.529 2.029 -0.323 1.706 c
+-0.118 1.382 -0.01 0.912 0 0.294 c
+h
+-1.043 0.25 m
+-1.043 0.669 -1.084 0.948 -1.161 1.088 c
+-1.242 1.235 -1.381 1.309 -1.587 1.309 c
+-1.804 1.309 -1.962 1.21 -2.057 1.014 c
+-2.057 -0.793 l
+-1.969 -0.981 -1.808 -1.072 -1.573 -1.072 c
+-1.378 -1.072 -1.242 -1.01 -1.161 -0.881 c
+-1.084 -0.756 -1.043 -0.5 -1.043 -0.118 c
+h
+2.587 1.103 m
+2.249 1.132 l
+1.962 1.132 1.771 1.008 1.676 0.765 c
+1.676 -1.866 l
+0.632 -1.866 l
+0.632 2.117 l
+1.602 2.117 l
+1.632 1.676 l
+1.798 2.018 2.029 2.19 2.323 2.19 c
+2.44 2.19 2.532 2.168 2.602 2.132 c
+h
+4.91 -1.866 m
+4.881 -1.808 4.851 -1.705 4.821 -1.558 c
+4.634 -1.815 4.385 -1.94 4.072 -1.94 c
+3.738 -1.94 3.458 -1.834 3.234 -1.616 c
+3.017 -1.392 2.911 -1.103 2.911 -0.75 c
+2.911 -0.338 3.043 -0.022 3.308 0.206 c
+3.572 0.441 3.954 0.559 4.454 0.559 c
+4.777 0.559 l
+4.777 0.882 l
+4.777 1.058 4.74 1.18 4.675 1.249 c
+4.616 1.327 4.528 1.367 4.41 1.367 c
+4.152 1.367 4.028 1.213 4.028 0.912 c
+2.984 0.912 l
+2.984 1.283 3.12 1.588 3.396 1.823 c
+3.668 2.066 4.017 2.19 4.439 2.19 c
+4.881 2.19 5.218 2.072 5.453 1.837 c
+5.696 1.61 5.821 1.287 5.821 0.867 c
+5.821 -0.999 l
+5.821 -1.344 5.869 -1.612 5.968 -1.808 c
+5.968 -1.866 l
+h
+4.307 -1.117 m
+4.414 -1.117 4.505 -1.099 4.586 -1.058 c
+4.675 -1.01 4.737 -0.951 4.777 -0.881 c
+4.777 -0.058 l
+4.528 -0.058 l
+4.351 -0.058 4.208 -0.118 4.102 -0.235 c
+4.002 -0.345 3.954 -0.492 3.954 -0.675 c
+3.954 -0.97 4.072 -1.117 4.307 -1.117 c
+7.526 2.117 m
+7.556 1.72 l
+7.791 2.033 8.092 2.19 8.467 2.19 c
+9.151 2.19 9.503 1.709 9.525 0.75 c
+9.525 -1.866 l
+8.482 -1.866 l
+8.482 0.676 l
+8.482 0.9 8.445 1.062 8.379 1.162 c
+8.309 1.257 8.191 1.309 8.026 1.309 c
+7.838 1.309 7.691 1.213 7.585 1.029 c
+7.585 -1.866 l
+6.541 -1.866 l
+6.541 2.117 l
+h
+11.715 -1.072 m
+12.009 -1.072 12.16 -0.878 12.171 -0.484 c
+13.141 -0.484 l
+13.141 -0.918 13.009 -1.271 12.744 -1.543 c
+12.48 -1.808 12.142 -1.94 11.73 -1.94 c
+11.219 -1.94 10.826 -1.786 10.554 -1.469 c
+10.29 -1.146 10.15 -0.675 10.143 -0.058 c
+10.143 0.265 l
+10.143 0.89 10.275 1.367 10.539 1.691 c
+10.812 2.022 11.208 2.19 11.73 2.19 c
+12.16 2.19 12.501 2.051 12.759 1.779 c
+13.012 1.503 13.141 1.121 13.141 0.632 c
+12.171 0.632 l
+12.171 0.846 12.131 1.014 12.054 1.132 c
+11.984 1.257 11.866 1.324 11.701 1.324 c
+11.524 1.324 11.396 1.257 11.319 1.132 c
+11.238 1.004 11.194 0.754 11.186 0.383 c
+11.186 -0.029 l
+11.186 -0.353 11.201 -0.58 11.231 -0.706 c
+11.267 -0.833 11.322 -0.926 11.392 -0.985 c
+11.469 -1.043 11.576 -1.072 11.715 -1.072 c
+14.758 1.764 m
+14.982 2.047 15.258 2.19 15.581 2.19 c
+15.942 2.19 16.217 2.062 16.405 1.808 c
+16.599 1.551 16.698 1.169 16.698 0.661 c
+16.698 -1.866 l
+15.655 -1.866 l
+15.655 0.647 l
+15.655 0.882 15.614 1.048 15.537 1.147 c
+15.468 1.253 15.354 1.309 15.199 1.309 c
+15.011 1.309 14.865 1.224 14.758 1.058 c
+14.758 -1.866 l
+13.714 -1.866 l
+13.714 3.778 l
+14.758 3.778 l
+h
+f
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 331.7103 184.7829 cm
+0 0 m
+-0.04 0.088 -0.066 0.235 -0.073 0.441 c
+-0.309 0.096 -0.603 -0.073 -0.956 -0.073 c
+-1.319 -0.073 -1.602 0.022 -1.808 0.22 c
+-2.007 0.426 -2.102 0.713 -2.102 1.087 c
+-2.102 1.488 -1.966 1.808 -1.691 2.043 c
+-1.419 2.286 -1.043 2.41 -0.573 2.41 c
+-0.088 2.41 l
+-0.088 2.837 l
+-0.088 3.072 -0.143 3.237 -0.25 3.337 c
+-0.36 3.443 -0.522 3.499 -0.735 3.499 c
+-0.933 3.499 -1.095 3.439 -1.22 3.322 c
+-1.338 3.204 -1.396 3.057 -1.396 2.881 c
+-2.043 2.881 l
+-2.043 3.076 -1.984 3.267 -1.866 3.454 c
+-1.741 3.638 -1.58 3.785 -1.382 3.896 c
+-1.176 4.002 -0.948 4.056 -0.691 4.056 c
+-0.291 4.056 0.015 3.954 0.22 3.748 c
+0.434 3.543 0.548 3.248 0.559 2.866 c
+0.559 0.852 l
+0.559 0.548 0.595 0.283 0.676 0.058 c
+0.676 0 l
+h
+-0.867 0.515 m
+-0.702 0.515 -0.551 0.559 -0.411 0.646 c
+-0.264 0.735 -0.158 0.845 -0.088 0.985 c
+-0.088 1.926 l
+-0.455 1.926 l
+-0.771 1.926 -1.014 1.856 -1.191 1.72 c
+-1.367 1.591 -1.455 1.404 -1.455 1.161 c
+-1.455 0.933 -1.411 0.768 -1.323 0.661 c
+-1.234 0.563 -1.084 0.515 -0.867 0.515 c
+4.924 3.366 m
+4.836 3.385 4.737 3.395 4.63 3.395 c
+4.295 3.395 4.06 3.212 3.925 2.851 c
+3.925 0 l
+3.278 0 l
+3.278 3.983 l
+3.91 3.983 l
+3.925 3.572 l
+4.101 3.896 4.343 4.056 4.659 4.056 c
+4.766 4.056 4.854 4.035 4.924 3.998 c
+h
+6.923 -0.073 m
+6.423 -0.073 6.041 0.073 5.777 0.368 c
+5.512 0.661 5.38 1.095 5.38 1.675 c
+5.38 2.146 l
+5.38 2.741 5.505 3.208 5.762 3.543 c
+6.026 3.884 6.387 4.056 6.85 4.056 c
+7.31 4.056 7.651 3.902 7.879 3.601 c
+8.114 3.308 8.235 2.844 8.247 2.219 c
+8.247 1.793 l
+6.026 1.793 l
+6.026 1.705 l
+6.026 1.272 6.104 0.96 6.262 0.764 c
+6.427 0.577 6.659 0.485 6.953 0.485 c
+7.148 0.485 7.32 0.518 7.468 0.588 c
+7.614 0.665 7.75 0.783 7.879 0.941 c
+8.216 0.529 l
+7.93 0.125 7.501 -0.073 6.923 -0.073 c
+6.85 3.499 m
+6.574 3.499 6.372 3.403 6.247 3.219 c
+6.119 3.032 6.045 2.741 6.026 2.352 c
+7.599 2.352 l
+7.599 2.44 l
+7.578 2.822 7.511 3.09 7.393 3.248 c
+7.276 3.414 7.092 3.499 6.85 3.499 c
+9.319 0 m
+9.319 3.454 l
+8.79 3.454 l
+8.79 3.983 l
+9.319 3.983 l
+9.319 4.439 l
+9.319 4.84 9.415 5.152 9.613 5.38 c
+9.819 5.604 10.098 5.718 10.451 5.718 c
+10.587 5.718 10.72 5.696 10.848 5.66 c
+10.819 5.115 l
+10.72 5.134 10.62 5.145 10.525 5.145 c
+10.15 5.145 9.966 4.88 9.966 4.351 c
+9.966 3.983 l
+10.643 3.983 l
+10.643 3.454 l
+9.966 3.454 l
+9.966 0 l
+h
+12.744 -0.073 m
+12.245 -0.073 11.862 0.073 11.597 0.368 c
+11.333 0.661 11.2 1.095 11.2 1.675 c
+11.2 2.146 l
+11.2 2.741 11.326 3.208 11.583 3.543 c
+11.848 3.884 12.208 4.056 12.671 4.056 c
+13.13 4.056 13.471 3.902 13.7 3.601 c
+13.935 3.308 14.056 2.844 14.067 2.219 c
+14.067 1.793 l
+11.848 1.793 l
+11.848 1.705 l
+11.848 1.272 11.925 0.96 12.083 0.764 c
+12.248 0.577 12.48 0.485 12.773 0.485 c
+12.968 0.485 13.141 0.518 13.288 0.588 c
+13.435 0.665 13.571 0.783 13.7 0.941 c
+14.038 0.529 l
+13.751 0.125 13.321 -0.073 12.744 -0.073 c
+12.671 3.499 m
+12.395 3.499 12.193 3.403 12.068 3.219 c
+11.939 3.032 11.866 2.741 11.848 2.352 c
+13.421 2.352 l
+13.421 2.44 l
+13.398 2.822 13.332 3.09 13.215 3.248 c
+13.097 3.414 12.914 3.499 12.671 3.499 c
+16.492 3.366 m
+16.405 3.385 16.305 3.395 16.199 3.395 c
+15.864 3.395 15.629 3.212 15.493 2.851 c
+15.493 0 l
+14.846 0 l
+14.846 3.983 l
+15.478 3.983 l
+15.493 3.572 l
+15.669 3.896 15.912 4.056 16.228 4.056 c
+16.334 4.056 16.422 4.035 16.492 3.998 c
+h
+18.491 -0.073 m
+17.992 -0.073 17.61 0.073 17.345 0.368 c
+17.08 0.661 16.948 1.095 16.948 1.675 c
+16.948 2.146 l
+16.948 2.741 17.073 3.208 17.33 3.543 c
+17.595 3.884 17.955 4.056 18.418 4.056 c
+18.877 4.056 19.219 3.902 19.447 3.601 c
+19.682 3.308 19.803 2.844 19.815 2.219 c
+19.815 1.793 l
+17.595 1.793 l
+17.595 1.705 l
+17.595 1.272 17.672 0.96 17.83 0.764 c
+17.995 0.577 18.227 0.485 18.521 0.485 c
+18.716 0.485 18.888 0.518 19.035 0.588 c
+19.183 0.665 19.318 0.783 19.447 0.941 c
+19.785 0.529 l
+19.499 0.125 19.069 -0.073 18.491 -0.073 c
+18.418 3.499 m
+18.142 3.499 17.94 3.403 17.816 3.219 c
+17.687 3.032 17.613 2.741 17.595 2.352 c
+19.168 2.352 l
+19.168 2.44 l
+19.146 2.822 19.079 3.09 18.962 3.248 c
+18.844 3.414 18.66 3.499 18.418 3.499 c
+21.211 3.983 m
+21.226 3.543 l
+21.479 3.884 21.803 4.056 22.196 4.056 c
+22.901 4.056 23.258 3.586 23.268 2.645 c
+23.268 0 l
+22.622 0 l
+22.622 2.616 l
+22.622 2.929 22.566 3.15 22.46 3.278 c
+22.35 3.403 22.196 3.469 21.99 3.469 c
+21.832 3.469 21.685 3.414 21.549 3.308 c
+21.421 3.197 21.317 3.061 21.24 2.896 c
+21.24 0 l
+20.594 0 l
+20.594 3.983 l
+h
+25.62 0.485 m
+25.834 0.485 26.007 0.548 26.135 0.676 c
+26.271 0.812 26.344 1.003 26.356 1.249 c
+26.973 1.249 l
+26.951 0.867 26.815 0.548 26.561 0.294 c
+26.304 0.048 25.992 -0.073 25.62 -0.073 c
+25.128 -0.073 24.754 0.077 24.488 0.382 c
+24.232 0.694 24.106 1.161 24.106 1.779 c
+24.106 2.219 l
+24.106 2.815 24.232 3.271 24.488 3.586 c
+24.754 3.899 25.128 4.056 25.62 4.056 c
+26.021 4.056 26.341 3.925 26.576 3.66 c
+26.819 3.403 26.951 3.057 26.973 2.616 c
+26.356 2.616 l
+26.333 2.911 26.26 3.131 26.135 3.278 c
+26.017 3.425 25.845 3.499 25.62 3.499 c
+25.327 3.499 25.109 3.399 24.974 3.204 c
+24.835 3.017 24.76 2.708 24.754 2.278 c
+24.754 1.764 l
+24.754 1.294 24.82 0.96 24.959 0.764 c
+25.106 0.577 25.327 0.485 25.62 0.485 c
+29.148 -0.073 m
+28.648 -0.073 28.266 0.073 28.002 0.368 c
+27.737 0.661 27.605 1.095 27.605 1.675 c
+27.605 2.146 l
+27.605 2.741 27.73 3.208 27.987 3.543 c
+28.251 3.884 28.612 4.056 29.074 4.056 c
+29.534 4.056 29.876 3.902 30.104 3.601 c
+30.339 3.308 30.46 2.844 30.471 2.219 c
+30.471 1.793 l
+28.251 1.793 l
+28.251 1.705 l
+28.251 1.272 28.328 0.96 28.487 0.764 c
+28.652 0.577 28.884 0.485 29.178 0.485 c
+29.373 0.485 29.545 0.518 29.693 0.588 c
+29.839 0.665 29.975 0.783 30.104 0.941 c
+30.441 0.529 l
+30.155 0.125 29.725 -0.073 29.148 -0.073 c
+29.074 3.499 m
+28.799 3.499 28.598 3.403 28.472 3.219 c
+28.344 3.032 28.27 2.741 28.251 2.352 c
+29.824 2.352 l
+29.824 2.44 l
+29.803 2.822 29.736 3.09 29.618 3.248 c
+29.501 3.414 29.317 3.499 29.074 3.499 c
+33.822 4.939 m
+33.822 3.983 l
+34.425 3.983 l
+34.425 3.454 l
+33.822 3.454 l
+33.822 0.985 l
+33.822 0.827 33.845 0.709 33.896 0.632 c
+33.955 0.551 34.043 0.515 34.161 0.515 c
+34.249 0.515 34.337 0.529 34.425 0.559 c
+34.425 0 l
+34.279 -0.048 34.123 -0.073 33.969 -0.073 c
+33.712 -0.073 33.518 0.019 33.381 0.206 c
+33.242 0.389 33.176 0.65 33.176 0.985 c
+33.176 3.454 l
+32.573 3.454 l
+32.573 3.983 l
+33.176 3.983 l
+33.176 4.939 l
+h
+34.984 2.175 m
+34.984 2.753 35.12 3.208 35.395 3.543 c
+35.678 3.884 36.049 4.056 36.513 4.056 c
+36.972 4.056 37.339 3.888 37.615 3.557 c
+37.898 3.233 38.044 2.786 38.056 2.219 c
+38.056 1.793 l
+38.056 1.224 37.913 0.768 37.63 0.426 c
+37.354 0.092 36.986 -0.073 36.527 -0.073 c
+36.064 -0.073 35.693 0.088 35.41 0.411 c
+35.135 0.742 34.991 1.183 34.984 1.735 c
+h
+35.63 1.793 m
+35.63 1.389 35.708 1.073 35.866 0.838 c
+36.031 0.603 36.251 0.485 36.527 0.485 c
+37.093 0.485 37.387 0.897 37.409 1.72 c
+37.409 2.175 l
+37.409 2.576 37.325 2.896 37.159 3.131 c
+37.001 3.373 36.785 3.499 36.513 3.499 c
+36.248 3.499 36.031 3.373 35.866 3.131 c
+35.708 2.896 35.63 2.576 35.63 2.175 c
+h
+42.657 0 m
+42.616 0.088 42.59 0.235 42.583 0.441 c
+42.348 0.096 42.054 -0.073 41.701 -0.073 c
+41.337 -0.073 41.055 0.022 40.849 0.22 c
+40.65 0.426 40.554 0.713 40.554 1.087 c
+40.554 1.488 40.691 1.808 40.966 2.043 c
+41.238 2.286 41.613 2.41 42.083 2.41 c
+42.568 2.41 l
+42.568 2.837 l
+42.568 3.072 42.513 3.237 42.407 3.337 c
+42.297 3.443 42.135 3.499 41.922 3.499 c
+41.724 3.499 41.562 3.439 41.437 3.322 c
+41.319 3.204 41.26 3.057 41.26 2.881 c
+40.614 2.881 l
+40.614 3.076 40.672 3.267 40.79 3.454 c
+40.915 3.638 41.076 3.785 41.275 3.896 c
+41.481 4.002 41.709 4.056 41.965 4.056 c
+42.366 4.056 42.671 3.954 42.877 3.748 c
+43.091 3.543 43.204 3.248 43.216 2.866 c
+43.216 0.852 l
+43.216 0.548 43.252 0.283 43.333 0.058 c
+43.333 0 l
+h
+41.79 0.515 m
+41.955 0.515 42.106 0.559 42.245 0.646 c
+42.393 0.735 42.499 0.845 42.568 0.985 c
+42.568 1.926 l
+42.201 1.926 l
+41.885 1.926 41.643 1.856 41.466 1.72 c
+41.29 1.591 41.202 1.404 41.202 1.161 c
+41.202 0.933 41.246 0.768 41.334 0.661 c
+41.422 0.563 41.572 0.515 41.79 0.515 c
+47.316 0.485 m
+47.529 0.485 47.702 0.548 47.831 0.676 c
+47.966 0.812 48.04 1.003 48.051 1.249 c
+48.668 1.249 l
+48.647 0.867 48.51 0.548 48.257 0.294 c
+47.999 0.048 47.687 -0.073 47.316 -0.073 c
+46.823 -0.073 46.449 0.077 46.185 0.382 c
+45.927 0.694 45.803 1.161 45.803 1.779 c
+45.803 2.219 l
+45.803 2.815 45.927 3.271 46.185 3.586 c
+46.449 3.899 46.823 4.056 47.316 4.056 c
+47.717 4.056 48.037 3.925 48.272 3.66 c
+48.514 3.403 48.647 3.057 48.668 2.616 c
+48.051 2.616 l
+48.029 2.911 47.956 3.131 47.831 3.278 c
+47.713 3.425 47.54 3.499 47.316 3.499 c
+47.022 3.499 46.806 3.399 46.669 3.204 c
+46.53 3.017 46.457 2.708 46.449 2.278 c
+46.449 1.764 l
+46.449 1.294 46.515 0.96 46.655 0.764 c
+46.802 0.577 47.022 0.485 47.316 0.485 c
+49.286 2.175 m
+49.286 2.753 49.422 3.208 49.697 3.543 c
+49.981 3.884 50.351 4.056 50.815 4.056 c
+51.274 4.056 51.642 3.888 51.918 3.557 c
+52.2 3.233 52.347 2.786 52.358 2.219 c
+52.358 1.793 l
+52.358 1.224 52.215 0.768 51.932 0.426 c
+51.656 0.092 51.289 -0.073 50.829 -0.073 c
+50.366 -0.073 49.996 0.088 49.712 0.411 c
+49.437 0.742 49.294 1.183 49.286 1.735 c
+h
+49.933 1.793 m
+49.933 1.389 50.01 1.073 50.168 0.838 c
+50.333 0.603 50.553 0.485 50.829 0.485 c
+51.395 0.485 51.689 0.897 51.711 1.72 c
+51.711 2.175 l
+51.711 2.576 51.627 2.896 51.461 3.131 c
+51.303 3.373 51.087 3.499 50.815 3.499 c
+50.55 3.499 50.333 3.373 50.168 3.131 c
+50.01 2.896 49.933 2.576 49.933 2.175 c
+h
+53.813 3.983 m
+53.828 3.616 l
+54.071 3.91 54.39 4.056 54.783 4.056 c
+55.224 4.056 55.533 3.859 55.71 3.469 c
+55.963 3.859 56.312 4.056 56.753 4.056 c
+57.488 4.056 57.863 3.594 57.885 2.675 c
+57.885 0 l
+57.238 0 l
+57.238 2.616 l
+57.238 2.911 57.183 3.123 57.077 3.263 c
+56.977 3.399 56.805 3.469 56.562 3.469 c
+56.363 3.469 56.202 3.389 56.077 3.233 c
+55.959 3.087 55.889 2.896 55.871 2.66 c
+55.871 0 l
+55.21 0 l
+55.21 2.645 l
+55.21 3.194 54.989 3.469 54.548 3.469 c
+54.214 3.469 53.979 3.308 53.842 2.984 c
+53.842 0 l
+53.196 0 l
+53.196 3.983 l
+h
+59.473 3.983 m
+59.487 3.616 l
+59.729 3.91 60.049 4.056 60.443 4.056 c
+60.884 4.056 61.192 3.859 61.368 3.469 c
+61.622 3.859 61.971 4.056 62.412 4.056 c
+63.147 4.056 63.522 3.594 63.544 2.675 c
+63.544 0 l
+62.897 0 l
+62.897 2.616 l
+62.897 2.911 62.842 3.123 62.736 3.263 c
+62.636 3.399 62.464 3.469 62.221 3.469 c
+62.023 3.469 61.861 3.389 61.736 3.233 c
+61.618 3.087 61.549 2.896 61.53 2.66 c
+61.53 0 l
+60.869 0 l
+60.869 2.645 l
+60.869 3.194 60.649 3.469 60.207 3.469 c
+59.873 3.469 59.638 3.308 59.502 2.984 c
+59.502 0 l
+58.855 0 l
+58.855 3.983 l
+h
+65.22 0 -0.646 3.983 re
+65.264 5.027 m
+65.264 4.917 65.235 4.825 65.175 4.748 c
+65.117 4.678 65.021 4.644 64.896 4.644 c
+64.778 4.644 64.683 4.678 64.617 4.748 c
+64.558 4.825 64.529 4.917 64.529 5.027 c
+64.529 5.145 64.558 5.236 64.617 5.307 c
+64.683 5.384 64.778 5.424 64.896 5.424 c
+65.021 5.424 65.117 5.384 65.175 5.307 c
+65.235 5.226 65.264 5.134 65.264 5.027 c
+67.087 4.939 m
+67.087 3.983 l
+67.689 3.983 l
+67.689 3.454 l
+67.087 3.454 l
+67.087 0.985 l
+67.087 0.827 67.109 0.709 67.16 0.632 c
+67.219 0.551 67.307 0.515 67.425 0.515 c
+67.513 0.515 67.601 0.529 67.689 0.559 c
+67.689 0 l
+67.542 -0.048 67.388 -0.073 67.234 -0.073 c
+66.976 -0.073 66.781 0.019 66.646 0.206 c
+66.506 0.389 66.44 0.65 66.44 0.985 c
+66.44 3.454 l
+65.837 3.454 l
+65.837 3.983 l
+66.44 3.983 l
+66.44 4.939 l
+h
+68.498 3.175 m
+68.498 3.293 68.531 3.389 68.601 3.469 c
+68.666 3.547 68.77 3.586 68.909 3.586 c
+69.056 3.586 69.163 3.547 69.233 3.469 c
+69.31 3.389 69.35 3.293 69.35 3.175 c
+69.35 3.065 69.31 2.973 69.233 2.896 c
+69.163 2.815 69.056 2.778 68.909 2.778 c
+68.77 2.778 68.666 2.815 68.601 2.896 c
+68.531 2.973 68.498 3.065 68.498 3.175 c
+68.468 -1.073 m
+68.071 -0.808 l
+68.306 -0.485 68.427 -0.151 68.439 0.191 c
+68.439 0.808 l
+69.1 0.808 l
+69.1 0.279 l
+69.1 0.022 69.034 -0.224 68.909 -0.47 c
+68.792 -0.713 68.645 -0.915 68.468 -1.073 c
+73.084 0.485 m
+73.297 0.485 73.47 0.548 73.598 0.676 c
+73.734 0.812 73.808 1.003 73.819 1.249 c
+74.436 1.249 l
+74.414 0.867 74.278 0.548 74.025 0.294 c
+73.767 0.048 73.455 -0.073 73.084 -0.073 c
+72.591 -0.073 72.217 0.077 71.952 0.382 c
+71.695 0.694 71.57 1.161 71.57 1.779 c
+71.57 2.219 l
+71.57 2.815 71.695 3.271 71.952 3.586 c
+72.217 3.899 72.591 4.056 73.084 4.056 c
+73.484 4.056 73.804 3.925 74.039 3.66 c
+74.282 3.403 74.414 3.057 74.436 2.616 c
+73.819 2.616 l
+73.796 2.911 73.723 3.131 73.598 3.278 c
+73.48 3.425 73.308 3.499 73.084 3.499 c
+72.79 3.499 72.573 3.399 72.437 3.204 c
+72.298 3.017 72.223 2.708 72.217 2.278 c
+72.217 1.764 l
+72.217 1.294 72.283 0.96 72.422 0.764 c
+72.57 0.577 72.79 0.485 73.084 0.485 c
+77.229 0 m
+77.189 0.088 77.162 0.235 77.156 0.441 c
+76.92 0.096 76.626 -0.073 76.273 -0.073 c
+75.909 -0.073 75.627 0.022 75.421 0.22 c
+75.222 0.426 75.127 0.713 75.127 1.087 c
+75.127 1.488 75.263 1.808 75.539 2.043 c
+75.81 2.286 76.185 2.41 76.655 2.41 c
+77.141 2.41 l
+77.141 2.837 l
+77.141 3.072 77.085 3.237 76.979 3.337 c
+76.869 3.443 76.707 3.499 76.494 3.499 c
+76.296 3.499 76.134 3.439 76.009 3.322 c
+75.891 3.204 75.832 3.057 75.832 2.881 c
+75.186 2.881 l
+75.186 3.076 75.244 3.267 75.362 3.454 c
+75.487 3.638 75.649 3.785 75.847 3.896 c
+76.053 4.002 76.281 4.056 76.538 4.056 c
+76.938 4.056 77.243 3.954 77.449 3.748 c
+77.663 3.543 77.777 3.248 77.788 2.866 c
+77.788 0.852 l
+77.788 0.548 77.825 0.283 77.905 0.058 c
+77.905 0 l
+h
+76.362 0.515 m
+76.527 0.515 76.678 0.559 76.817 0.646 c
+76.965 0.735 77.071 0.845 77.141 0.985 c
+77.141 1.926 l
+76.773 1.926 l
+76.457 1.926 76.215 1.856 76.038 1.72 c
+75.862 1.591 75.774 1.404 75.774 1.161 c
+75.774 0.933 75.818 0.768 75.906 0.661 c
+75.994 0.563 76.144 0.515 76.362 0.515 c
+79.404 3.983 m
+79.419 3.543 l
+79.672 3.884 79.996 4.056 80.389 4.056 c
+81.095 4.056 81.451 3.586 81.462 2.645 c
+81.462 0 l
+80.815 0 l
+80.815 2.616 l
+80.815 2.929 80.761 3.15 80.653 3.278 c
+80.543 3.403 80.389 3.469 80.183 3.469 c
+80.025 3.469 79.878 3.414 79.743 3.308 c
+79.614 3.197 79.511 3.061 79.434 2.896 c
+79.434 0 l
+78.787 0 l
+78.787 3.983 l
+h
+84.799 3.572 m
+85.052 3.896 85.372 4.056 85.754 4.056 c
+86.46 4.056 86.816 3.586 86.827 2.645 c
+86.827 0 l
+86.18 0 l
+86.18 2.616 l
+86.18 2.929 86.126 3.15 86.019 3.278 c
+85.908 3.403 85.754 3.469 85.549 3.469 c
+85.391 3.469 85.243 3.414 85.108 3.308 c
+84.979 3.197 84.876 3.061 84.799 2.896 c
+84.799 0 l
+84.152 0 l
+84.152 5.644 l
+84.799 5.644 l
+h
+89.826 0 m
+89.785 0.088 89.76 0.235 89.752 0.441 c
+89.517 0.096 89.223 -0.073 88.871 -0.073 c
+88.507 -0.073 88.223 0.022 88.018 0.22 c
+87.82 0.426 87.724 0.713 87.724 1.087 c
+87.724 1.488 87.86 1.808 88.136 2.043 c
+88.408 2.286 88.782 2.41 89.253 2.41 c
+89.738 2.41 l
+89.738 2.837 l
+89.738 3.072 89.683 3.237 89.576 3.337 c
+89.466 3.443 89.304 3.499 89.091 3.499 c
+88.892 3.499 88.731 3.439 88.606 3.322 c
+88.489 3.204 88.43 3.057 88.43 2.881 c
+87.783 2.881 l
+87.783 3.076 87.842 3.267 87.959 3.454 c
+88.084 3.638 88.246 3.785 88.445 3.896 c
+88.65 4.002 88.878 4.056 89.135 4.056 c
+89.536 4.056 89.841 3.954 90.047 3.748 c
+90.259 3.543 90.373 3.248 90.384 2.866 c
+90.384 0.852 l
+90.384 0.548 90.421 0.283 90.502 0.058 c
+90.502 0 l
+h
+88.959 0.515 m
+89.124 0.515 89.275 0.559 89.414 0.646 c
+89.561 0.735 89.668 0.845 89.738 0.985 c
+89.738 1.926 l
+89.37 1.926 l
+89.054 1.926 88.811 1.856 88.636 1.72 c
+88.459 1.591 88.371 1.404 88.371 1.161 c
+88.371 0.933 88.414 0.768 88.503 0.661 c
+88.591 0.563 88.742 0.515 88.959 0.515 c
+92.457 0.985 m
+93.207 3.983 l
+93.868 3.983 l
+92.692 0 l
+92.207 0 l
+91.017 3.983 l
+91.678 3.983 l
+h
+95.926 -0.073 m
+95.427 -0.073 95.044 0.073 94.779 0.368 c
+94.515 0.661 94.383 1.095 94.383 1.675 c
+94.383 2.146 l
+94.383 2.741 94.508 3.208 94.764 3.543 c
+95.03 3.884 95.39 4.056 95.853 4.056 c
+96.312 4.056 96.653 3.902 96.881 3.601 c
+97.116 3.308 97.238 2.844 97.249 2.219 c
+97.249 1.793 l
+95.03 1.793 l
+95.03 1.705 l
+95.03 1.272 95.107 0.96 95.265 0.764 c
+95.43 0.577 95.662 0.485 95.955 0.485 c
+96.15 0.485 96.323 0.518 96.47 0.588 c
+96.617 0.665 96.753 0.783 96.881 0.941 c
+97.22 0.529 l
+96.933 0.125 96.503 -0.073 95.926 -0.073 c
+95.853 3.499 m
+95.577 3.499 95.375 3.403 95.25 3.219 c
+95.121 3.032 95.048 2.741 95.03 2.352 c
+96.603 2.352 l
+96.603 2.44 l
+96.58 2.822 96.514 3.09 96.397 3.248 c
+96.279 3.414 96.096 3.499 95.853 3.499 c
+101.791 0 m
+101.75 0.088 101.725 0.235 101.717 0.441 c
+101.482 0.096 101.189 -0.073 100.836 -0.073 c
+100.472 -0.073 100.189 0.022 99.983 0.22 c
+99.784 0.426 99.689 0.713 99.689 1.087 c
+99.689 1.488 99.825 1.808 100.1 2.043 c
+100.372 2.286 100.748 2.41 101.218 2.41 c
+101.702 2.41 l
+101.702 2.837 l
+101.702 3.072 101.648 3.237 101.542 3.337 c
+101.431 3.443 101.27 3.499 101.056 3.499 c
+100.858 3.499 100.696 3.439 100.571 3.322 c
+100.453 3.204 100.395 3.057 100.395 2.881 c
+99.748 2.881 l
+99.748 3.076 99.807 3.267 99.924 3.454 c
+100.049 3.638 100.21 3.785 100.409 3.896 c
+100.615 4.002 100.843 4.056 101.1 4.056 c
+101.501 4.056 101.806 3.954 102.012 3.748 c
+102.224 3.543 102.338 3.248 102.35 2.866 c
+102.35 0.852 l
+102.35 0.548 102.386 0.283 102.467 0.058 c
+102.467 0 l
+h
+100.923 0.515 m
+101.089 0.515 101.24 0.559 101.38 0.646 c
+101.526 0.735 101.633 0.845 101.702 0.985 c
+101.702 1.926 l
+101.336 1.926 l
+101.019 1.926 100.777 1.856 100.601 1.72 c
+100.424 1.591 100.336 1.404 100.336 1.161 c
+100.336 0.933 100.38 0.768 100.468 0.661 c
+100.557 0.563 100.707 0.515 100.923 0.515 c
+f
+Q
+q 1 0 0 1 437.8812 189.7368 cm
+0 0 m
+0 -0.971 l
+0.53 -0.971 l
+0.53 -1.764 l
+0 -1.764 l
+0 -3.734 l
+0 -3.892 0.019 -3.998 0.059 -4.057 c
+0.107 -4.116 0.192 -4.146 0.31 -4.146 c
+0.416 -4.146 0.5 -4.138 0.559 -4.116 c
+0.559 -4.925 l
+0.383 -4.991 0.192 -5.027 -0.014 -5.027 c
+-0.69 -5.027 -1.036 -4.642 -1.043 -3.866 c
+-1.043 -1.764 l
+-1.499 -1.764 l
+-1.499 -0.971 l
+-1.043 -0.971 l
+-1.043 0 l
+h
+3.057 -1.985 m
+2.72 -1.956 l
+2.433 -1.956 2.242 -2.08 2.147 -2.323 c
+2.147 -4.954 l
+1.103 -4.954 l
+1.103 -0.971 l
+2.073 -0.971 l
+2.103 -1.411 l
+2.268 -1.07 2.5 -0.897 2.793 -0.897 c
+2.911 -0.897 3.003 -0.919 3.072 -0.956 c
+h
+5.38 -4.954 m
+5.351 -4.896 5.322 -4.792 5.292 -4.645 c
+5.104 -4.902 4.855 -5.027 4.543 -5.027 c
+4.208 -5.027 3.929 -4.921 3.705 -4.704 c
+3.487 -4.48 3.381 -4.19 3.381 -3.837 c
+3.381 -3.425 3.514 -3.109 3.778 -2.881 c
+4.042 -2.646 4.425 -2.529 4.925 -2.529 c
+5.248 -2.529 l
+5.248 -2.205 l
+5.248 -2.029 5.212 -1.908 5.145 -1.838 c
+5.087 -1.76 4.998 -1.721 4.881 -1.721 c
+4.623 -1.721 4.499 -1.875 4.499 -2.176 c
+3.454 -2.176 l
+3.454 -1.804 3.591 -1.5 3.866 -1.264 c
+4.138 -1.022 4.487 -0.897 4.91 -0.897 c
+5.351 -0.897 5.689 -1.015 5.924 -1.25 c
+6.167 -1.478 6.292 -1.801 6.292 -2.22 c
+6.292 -4.087 l
+6.292 -4.432 6.34 -4.7 6.438 -4.896 c
+6.438 -4.954 l
+h
+4.778 -4.204 m
+4.884 -4.204 4.977 -4.186 5.056 -4.146 c
+5.145 -4.098 5.208 -4.039 5.248 -3.969 c
+5.248 -3.146 l
+4.998 -3.146 l
+4.821 -3.146 4.678 -3.205 4.572 -3.323 c
+4.472 -3.433 4.425 -3.58 4.425 -3.763 c
+4.425 -4.057 4.543 -4.204 4.778 -4.204 c
+8.482 -4.16 m
+8.776 -4.16 8.927 -3.965 8.937 -3.572 c
+9.908 -3.572 l
+9.908 -4.006 9.775 -4.358 9.511 -4.63 c
+9.247 -4.896 8.908 -5.027 8.497 -5.027 c
+7.986 -5.027 7.593 -4.873 7.321 -4.557 c
+7.056 -4.233 6.916 -3.763 6.909 -3.146 c
+6.909 -2.822 l
+6.909 -2.198 7.041 -1.721 7.306 -1.397 c
+7.578 -1.066 7.975 -0.897 8.497 -0.897 c
+8.927 -0.897 9.268 -1.037 9.525 -1.309 c
+9.779 -1.584 9.908 -1.966 9.908 -2.455 c
+8.937 -2.455 l
+8.937 -2.242 8.897 -2.073 8.819 -1.956 c
+8.75 -1.831 8.632 -1.764 8.467 -1.764 c
+8.291 -1.764 8.162 -1.831 8.085 -1.956 c
+8.004 -2.084 7.96 -2.334 7.953 -2.705 c
+7.953 -3.117 l
+7.953 -3.44 7.967 -3.668 7.996 -3.793 c
+8.034 -3.921 8.088 -4.013 8.158 -4.072 c
+8.235 -4.131 8.342 -4.16 8.482 -4.16 c
+11.834 -3.425 m
+11.554 -3.734 l
+11.554 -4.954 l
+10.51 -4.954 l
+10.51 0.691 l
+11.554 0.691 l
+11.554 -2.352 l
+11.672 -2.161 l
+12.391 -0.971 l
+13.641 -0.971 l
+12.48 -2.617 l
+13.744 -4.954 l
+12.553 -4.954 l
+h
+15.64 -5.027 m
+15.111 -5.027 14.692 -4.873 14.391 -4.557 c
+14.097 -4.233 13.95 -3.774 13.95 -3.175 c
+13.95 -2.866 l
+13.95 -2.242 14.086 -1.757 14.361 -1.411 c
+14.633 -1.07 15.026 -0.897 15.537 -0.897 c
+16.037 -0.897 16.408 -1.058 16.655 -1.382 c
+16.908 -1.706 17.041 -2.183 17.051 -2.808 c
+17.051 -3.308 l
+14.978 -3.308 l
+14.997 -3.602 15.059 -3.818 15.169 -3.955 c
+15.287 -4.094 15.468 -4.16 15.714 -4.16 c
+16.056 -4.16 16.345 -4.042 16.581 -3.807 c
+16.993 -4.439 l
+16.864 -4.616 16.676 -4.759 16.434 -4.865 c
+16.187 -4.973 15.923 -5.027 15.64 -5.027 c
+14.993 -2.587 m
+16.023 -2.587 l
+16.023 -2.484 l
+16.023 -2.249 15.982 -2.073 15.905 -1.956 c
+15.835 -1.831 15.707 -1.764 15.522 -1.764 c
+15.346 -1.764 15.214 -1.834 15.126 -1.97 c
+15.045 -2.099 15.001 -2.305 14.993 -2.587 c
+17.492 -2.837 m
+17.492 -2.191 17.598 -1.706 17.816 -1.382 c
+18.04 -1.058 18.363 -0.897 18.786 -0.897 c
+19.098 -0.897 19.352 -1.029 19.55 -1.294 c
+19.55 0.691 l
+20.609 0.691 l
+20.609 -4.954 l
+19.653 -4.954 l
+19.609 -4.543 l
+19.392 -4.865 19.117 -5.027 18.786 -5.027 c
+18.375 -5.027 18.055 -4.873 17.831 -4.557 c
+17.613 -4.233 17.5 -3.763 17.492 -3.146 c
+h
+18.536 -3.102 m
+18.536 -3.495 18.573 -3.77 18.654 -3.925 c
+18.741 -4.083 18.889 -4.16 19.094 -4.16 c
+19.3 -4.16 19.451 -4.069 19.55 -3.881 c
+19.55 -2.073 l
+19.451 -1.878 19.3 -1.779 19.094 -1.779 c
+18.896 -1.779 18.756 -1.86 18.668 -2.014 c
+18.58 -2.161 18.536 -2.433 18.536 -2.822 c
+h
+25.062 -4.586 m
+24.846 -4.881 24.555 -5.027 24.195 -5.027 c
+23.831 -5.027 23.552 -4.906 23.358 -4.66 c
+23.169 -4.406 23.078 -4.039 23.078 -3.558 c
+23.078 -0.971 l
+24.121 -0.971 l
+24.121 -3.572 l
+24.121 -3.965 24.247 -4.16 24.503 -4.16 c
+24.739 -4.16 24.908 -4.057 25.018 -3.851 c
+25.018 -0.971 l
+26.062 -0.971 l
+26.062 -4.954 l
+25.091 -4.954 l
+h
+29.913 -3.087 m
+29.913 -3.716 29.803 -4.197 29.59 -4.528 c
+29.373 -4.862 29.053 -5.027 28.634 -5.027 c
+28.311 -5.027 28.05 -4.896 27.855 -4.63 c
+27.855 -6.483 l
+26.811 -6.483 l
+26.811 -0.971 l
+27.767 -0.971 l
+27.811 -1.338 l
+28.006 -1.044 28.274 -0.897 28.619 -0.897 c
+29.039 -0.897 29.358 -1.055 29.575 -1.368 c
+29.788 -1.673 29.902 -2.143 29.913 -2.779 c
+h
+28.869 -2.822 m
+28.869 -2.44 28.825 -2.172 28.737 -2.014 c
+28.656 -1.86 28.517 -1.779 28.311 -1.779 c
+28.105 -1.779 27.95 -1.867 27.855 -2.043 c
+27.855 -3.911 l
+27.944 -4.079 28.098 -4.16 28.326 -4.16 c
+28.532 -4.16 28.671 -4.079 28.752 -3.911 c
+28.829 -3.734 28.869 -3.462 28.869 -3.087 c
+h
+32.309 -3.881 m
+32.309 -3.793 32.265 -3.716 32.177 -3.645 c
+32.089 -3.568 31.901 -3.466 31.618 -3.337 c
+31.185 -3.161 30.886 -2.98 30.722 -2.793 c
+30.564 -2.61 30.487 -2.378 30.487 -2.103 c
+30.487 -1.76 30.608 -1.478 30.853 -1.25 c
+31.107 -1.015 31.445 -0.897 31.868 -0.897 c
+32.297 -0.897 32.647 -1.011 32.912 -1.235 c
+33.176 -1.463 33.309 -1.764 33.309 -2.147 c
+32.265 -2.147 l
+32.265 -1.823 32.125 -1.661 31.853 -1.661 c
+31.743 -1.661 31.655 -1.698 31.589 -1.764 c
+31.519 -1.834 31.486 -1.933 31.486 -2.058 c
+31.486 -2.147 31.522 -2.228 31.603 -2.294 c
+31.68 -2.352 31.861 -2.448 32.147 -2.573 c
+32.577 -2.731 32.875 -2.907 33.043 -3.102 c
+33.22 -3.289 33.309 -3.539 33.309 -3.851 c
+33.309 -4.204 33.176 -4.491 32.912 -4.704 c
+32.647 -4.921 32.297 -5.027 31.868 -5.027 c
+31.574 -5.027 31.313 -4.973 31.089 -4.865 c
+30.861 -4.748 30.685 -4.586 30.56 -4.381 c
+30.442 -4.175 30.383 -3.955 30.383 -3.72 c
+31.368 -3.72 l
+31.368 -3.907 31.405 -4.042 31.486 -4.131 c
+31.574 -4.219 31.707 -4.263 31.883 -4.263 c
+32.166 -4.263 32.309 -4.138 32.309 -3.881 c
+35.175 0 m
+35.175 -0.971 l
+35.705 -0.971 l
+35.705 -1.764 l
+35.175 -1.764 l
+35.175 -3.734 l
+35.175 -3.892 35.194 -3.998 35.234 -4.057 c
+35.281 -4.116 35.366 -4.146 35.484 -4.146 c
+35.59 -4.146 35.675 -4.138 35.734 -4.116 c
+35.734 -4.925 l
+35.557 -4.991 35.366 -5.027 35.16 -5.027 c
+34.485 -5.027 34.139 -4.642 34.132 -3.866 c
+34.132 -1.764 l
+33.676 -1.764 l
+33.676 -0.971 l
+34.132 -0.971 l
+34.132 0 l
+h
+38.233 -1.985 m
+37.895 -1.956 l
+37.608 -1.956 37.417 -2.08 37.321 -2.323 c
+37.321 -4.954 l
+36.278 -4.954 l
+36.278 -0.971 l
+37.248 -0.971 l
+37.277 -1.411 l
+37.442 -1.07 37.674 -0.897 37.968 -0.897 c
+38.086 -0.897 38.177 -0.919 38.248 -0.956 c
+h
+40.305 -5.027 m
+39.776 -5.027 39.357 -4.873 39.056 -4.557 c
+38.762 -4.233 38.615 -3.774 38.615 -3.175 c
+38.615 -2.866 l
+38.615 -2.242 38.751 -1.757 39.027 -1.411 c
+39.298 -1.07 39.692 -0.897 40.202 -0.897 c
+40.702 -0.897 41.074 -1.058 41.319 -1.382 c
+41.573 -1.706 41.705 -2.183 41.716 -2.808 c
+41.716 -3.308 l
+39.644 -3.308 l
+39.663 -3.602 39.725 -3.818 39.835 -3.955 c
+39.952 -4.094 40.133 -4.16 40.378 -4.16 c
+40.721 -4.16 41.011 -4.042 41.246 -3.807 c
+41.658 -4.439 l
+41.529 -4.616 41.342 -4.759 41.099 -4.865 c
+40.853 -4.973 40.588 -5.027 40.305 -5.027 c
+39.659 -2.587 m
+40.687 -2.587 l
+40.687 -2.484 l
+40.687 -2.249 40.647 -2.073 40.569 -1.956 c
+40.5 -1.831 40.371 -1.764 40.187 -1.764 c
+40.012 -1.764 39.879 -1.834 39.79 -1.97 c
+39.71 -2.099 39.665 -2.305 39.659 -2.587 c
+44.186 -4.954 m
+44.156 -4.896 44.127 -4.792 44.097 -4.645 c
+43.91 -4.902 43.661 -5.027 43.348 -5.027 c
+43.013 -5.027 42.734 -4.921 42.51 -4.704 c
+42.293 -4.48 42.187 -4.19 42.187 -3.837 c
+42.187 -3.425 42.319 -3.109 42.584 -2.881 c
+42.848 -2.646 43.231 -2.529 43.73 -2.529 c
+44.054 -2.529 l
+44.054 -2.205 l
+44.054 -2.029 44.017 -1.908 43.95 -1.838 c
+43.892 -1.76 43.804 -1.721 43.686 -1.721 c
+43.428 -1.721 43.304 -1.875 43.304 -2.176 c
+42.26 -2.176 l
+42.26 -1.804 42.396 -1.5 42.672 -1.264 c
+42.944 -1.022 43.293 -0.897 43.715 -0.897 c
+44.156 -0.897 44.494 -1.015 44.729 -1.25 c
+44.972 -1.478 45.097 -1.801 45.097 -2.22 c
+45.097 -4.087 l
+45.097 -4.432 45.145 -4.7 45.244 -4.896 c
+45.244 -4.954 l
+h
+43.583 -4.204 m
+43.69 -4.204 43.782 -4.186 43.862 -4.146 c
+43.95 -4.098 44.013 -4.039 44.054 -3.969 c
+44.054 -3.146 l
+43.804 -3.146 l
+43.627 -3.146 43.484 -3.205 43.378 -3.323 c
+43.278 -3.433 43.231 -3.58 43.231 -3.763 c
+43.231 -4.057 43.348 -4.204 43.583 -4.204 c
+46.817 -0.971 m
+46.846 -1.338 l
+47.081 -1.044 47.39 -0.897 47.773 -0.897 c
+48.172 -0.897 48.452 -1.081 48.61 -1.441 c
+48.845 -1.081 49.172 -0.897 49.595 -0.897 c
+50.289 -0.897 50.642 -1.382 50.653 -2.352 c
+50.653 -4.954 l
+49.624 -4.954 l
+49.624 -2.411 l
+49.624 -2.187 49.587 -2.025 49.521 -1.926 c
+49.463 -1.831 49.352 -1.779 49.198 -1.779 c
+48.999 -1.779 48.86 -1.897 48.772 -2.132 c
+48.772 -4.954 l
+47.728 -4.954 l
+47.728 -2.426 l
+47.728 -2.191 47.699 -2.025 47.64 -1.926 c
+47.582 -1.831 47.471 -1.779 47.316 -1.779 c
+47.14 -1.779 46.997 -1.875 46.89 -2.058 c
+46.89 -4.954 l
+45.847 -4.954 l
+45.847 -0.971 l
+h
+f
+Q
+0 0 0 0 k
+q 1 0 0 1 310.3894 176.5843 cm
+0 0 m
+0 -0.97 l
+0.53 -0.97 l
+0.53 -1.764 l
+0 -1.764 l
+0 -3.734 l
+0 -3.892 0.019 -3.998 0.059 -4.056 c
+0.106 -4.116 0.191 -4.145 0.309 -4.145 c
+0.415 -4.145 0.5 -4.137 0.559 -4.116 c
+0.559 -4.924 l
+0.382 -4.991 0.191 -5.027 -0.015 -5.027 c
+-0.691 -5.027 -1.037 -4.641 -1.043 -3.865 c
+-1.043 -1.764 l
+-1.5 -1.764 l
+-1.5 -0.97 l
+-1.043 -0.97 l
+-1.043 0 l
+h
+2.984 -4.953 m
+2.955 -4.895 2.925 -4.792 2.896 -4.644 c
+2.708 -4.902 2.458 -5.027 2.146 -5.027 c
+1.812 -5.027 1.532 -4.92 1.309 -4.704 c
+1.091 -4.48 0.985 -4.189 0.985 -3.836 c
+0.985 -3.424 1.117 -3.109 1.382 -2.881 c
+1.646 -2.645 2.028 -2.528 2.528 -2.528 c
+2.851 -2.528 l
+2.851 -2.205 l
+2.851 -2.028 2.815 -1.907 2.749 -1.837 c
+2.69 -1.76 2.602 -1.72 2.484 -1.72 c
+2.227 -1.72 2.102 -1.874 2.102 -2.175 c
+1.058 -2.175 l
+1.058 -1.804 1.195 -1.5 1.47 -1.264 c
+1.742 -1.022 2.091 -0.897 2.514 -0.897 c
+2.955 -0.897 3.293 -1.014 3.528 -1.249 c
+3.77 -1.477 3.896 -1.801 3.896 -2.219 c
+3.896 -4.087 l
+3.896 -4.432 3.943 -4.7 4.042 -4.895 c
+4.042 -4.953 l
+h
+2.381 -4.204 m
+2.488 -4.204 2.579 -4.185 2.66 -4.145 c
+2.749 -4.097 2.811 -4.039 2.851 -3.969 c
+2.851 -3.146 l
+2.602 -3.146 l
+2.425 -3.146 2.282 -3.204 2.176 -3.322 c
+2.076 -3.432 2.028 -3.579 2.028 -3.763 c
+2.028 -4.056 2.146 -4.204 2.381 -4.204 c
+4.513 -2.836 m
+4.513 -2.19 4.63 -1.705 4.866 -1.382 c
+5.101 -1.058 5.431 -0.897 5.865 -0.897 c
+6.217 -0.897 6.489 -1.04 6.688 -1.323 c
+6.732 -0.97 l
+7.673 -0.97 l
+7.673 -4.953 l
+7.673 -5.461 7.53 -5.85 7.247 -6.115 c
+6.96 -6.387 6.556 -6.526 6.026 -6.526 c
+5.799 -6.526 5.564 -6.482 5.321 -6.394 c
+5.086 -6.306 4.91 -6.192 4.792 -6.056 c
+5.145 -5.336 l
+5.24 -5.442 5.369 -5.527 5.527 -5.585 c
+5.681 -5.652 5.828 -5.689 5.968 -5.689 c
+6.203 -5.689 6.369 -5.629 6.468 -5.512 c
+6.574 -5.402 6.629 -5.226 6.629 -4.983 c
+6.629 -4.63 l
+6.431 -4.895 6.174 -5.027 5.85 -5.027 c
+5.428 -5.027 5.101 -4.865 4.866 -4.542 c
+4.638 -4.211 4.52 -3.74 4.513 -3.131 c
+h
+5.556 -3.102 m
+5.556 -3.476 5.604 -3.744 5.704 -3.91 c
+5.799 -4.079 5.953 -4.16 6.159 -4.16 c
+6.372 -4.16 6.53 -4.083 6.629 -3.925 c
+6.629 -2.028 l
+6.519 -1.863 6.365 -1.778 6.159 -1.778 c
+5.953 -1.778 5.799 -1.863 5.704 -2.028 c
+5.604 -2.198 5.556 -2.466 5.556 -2.836 c
+h
+f
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 331.7103 171.6313 cm
+0 0 m
+-0.04 0.087 -0.066 0.235 -0.073 0.44 c
+-0.309 0.095 -0.603 -0.074 -0.956 -0.074 c
+-1.319 -0.074 -1.602 0.022 -1.808 0.22 c
+-2.007 0.426 -2.102 0.712 -2.102 1.088 c
+-2.102 1.488 -1.966 1.807 -1.691 2.042 c
+-1.419 2.285 -1.043 2.41 -0.573 2.41 c
+-0.088 2.41 l
+-0.088 2.836 l
+-0.088 3.072 -0.143 3.237 -0.25 3.336 c
+-0.36 3.443 -0.522 3.498 -0.735 3.498 c
+-0.933 3.498 -1.095 3.439 -1.22 3.322 c
+-1.338 3.204 -1.396 3.057 -1.396 2.881 c
+-2.043 2.881 l
+-2.043 3.075 -1.984 3.266 -1.866 3.453 c
+-1.741 3.638 -1.58 3.785 -1.382 3.895 c
+-1.176 4.001 -0.948 4.056 -0.691 4.056 c
+-0.291 4.056 0.015 3.954 0.22 3.748 c
+0.434 3.542 0.548 3.248 0.559 2.865 c
+0.559 0.852 l
+0.559 0.548 0.595 0.282 0.676 0.058 c
+0.676 0 l
+h
+-0.867 0.514 m
+-0.702 0.514 -0.551 0.558 -0.411 0.646 c
+-0.264 0.735 -0.158 0.845 -0.088 0.984 c
+-0.088 1.925 l
+-0.455 1.925 l
+-0.771 1.925 -1.014 1.855 -1.191 1.72 c
+-1.367 1.591 -1.455 1.404 -1.455 1.161 c
+-1.455 0.933 -1.411 0.768 -1.323 0.661 c
+-1.234 0.562 -1.084 0.514 -0.867 0.514 c
+4.924 3.366 m
+4.836 3.384 4.737 3.395 4.63 3.395 c
+4.295 3.395 4.06 3.212 3.925 2.851 c
+3.925 0 l
+3.278 0 l
+3.278 3.983 l
+3.91 3.983 l
+3.925 3.571 l
+4.101 3.895 4.343 4.056 4.659 4.056 c
+4.766 4.056 4.854 4.035 4.924 3.998 c
+h
+6.923 -0.074 m
+6.423 -0.074 6.041 0.073 5.777 0.367 c
+5.512 0.661 5.38 1.095 5.38 1.675 c
+5.38 2.146 l
+5.38 2.741 5.505 3.208 5.762 3.542 c
+6.026 3.883 6.387 4.056 6.85 4.056 c
+7.31 4.056 7.651 3.902 7.879 3.601 c
+8.114 3.307 8.235 2.844 8.247 2.219 c
+8.247 1.793 l
+6.026 1.793 l
+6.026 1.705 l
+6.026 1.271 6.104 0.959 6.262 0.764 c
+6.427 0.577 6.659 0.484 6.953 0.484 c
+7.148 0.484 7.32 0.517 7.468 0.588 c
+7.614 0.665 7.75 0.783 7.879 0.941 c
+8.216 0.529 l
+7.93 0.124 7.501 -0.074 6.923 -0.074 c
+6.85 3.498 m
+6.574 3.498 6.372 3.403 6.247 3.218 c
+6.119 3.031 6.045 2.741 6.026 2.352 c
+7.599 2.352 l
+7.599 2.439 l
+7.578 2.822 7.511 3.09 7.393 3.248 c
+7.276 3.413 7.092 3.498 6.85 3.498 c
+9.319 0 m
+9.319 3.453 l
+8.79 3.453 l
+8.79 3.983 l
+9.319 3.983 l
+9.319 4.438 l
+9.319 4.839 9.415 5.151 9.613 5.379 c
+9.819 5.604 10.098 5.718 10.451 5.718 c
+10.587 5.718 10.72 5.695 10.848 5.659 c
+10.819 5.115 l
+10.72 5.134 10.62 5.144 10.525 5.144 c
+10.15 5.144 9.966 4.88 9.966 4.351 c
+9.966 3.983 l
+10.643 3.983 l
+10.643 3.453 l
+9.966 3.453 l
+9.966 0 l
+h
+12.744 -0.074 m
+12.245 -0.074 11.862 0.073 11.597 0.367 c
+11.333 0.661 11.2 1.095 11.2 1.675 c
+11.2 2.146 l
+11.2 2.741 11.326 3.208 11.583 3.542 c
+11.848 3.883 12.208 4.056 12.671 4.056 c
+13.13 4.056 13.471 3.902 13.7 3.601 c
+13.935 3.307 14.056 2.844 14.067 2.219 c
+14.067 1.793 l
+11.848 1.793 l
+11.848 1.705 l
+11.848 1.271 11.925 0.959 12.083 0.764 c
+12.248 0.577 12.48 0.484 12.773 0.484 c
+12.968 0.484 13.141 0.517 13.288 0.588 c
+13.435 0.665 13.571 0.783 13.7 0.941 c
+14.038 0.529 l
+13.751 0.124 13.321 -0.074 12.744 -0.074 c
+12.671 3.498 m
+12.395 3.498 12.193 3.403 12.068 3.218 c
+11.939 3.031 11.866 2.741 11.848 2.352 c
+13.421 2.352 l
+13.421 2.439 l
+13.398 2.822 13.332 3.09 13.215 3.248 c
+13.097 3.413 12.914 3.498 12.671 3.498 c
+16.492 3.366 m
+16.405 3.384 16.305 3.395 16.199 3.395 c
+15.864 3.395 15.629 3.212 15.493 2.851 c
+15.493 0 l
+14.846 0 l
+14.846 3.983 l
+15.478 3.983 l
+15.493 3.571 l
+15.669 3.895 15.912 4.056 16.228 4.056 c
+16.334 4.056 16.422 4.035 16.492 3.998 c
+h
+18.491 -0.074 m
+17.992 -0.074 17.61 0.073 17.345 0.367 c
+17.08 0.661 16.948 1.095 16.948 1.675 c
+16.948 2.146 l
+16.948 2.741 17.073 3.208 17.33 3.542 c
+17.595 3.883 17.955 4.056 18.418 4.056 c
+18.877 4.056 19.219 3.902 19.447 3.601 c
+19.682 3.307 19.803 2.844 19.815 2.219 c
+19.815 1.793 l
+17.595 1.793 l
+17.595 1.705 l
+17.595 1.271 17.672 0.959 17.83 0.764 c
+17.995 0.577 18.227 0.484 18.521 0.484 c
+18.716 0.484 18.888 0.517 19.035 0.588 c
+19.183 0.665 19.318 0.783 19.447 0.941 c
+19.785 0.529 l
+19.499 0.124 19.069 -0.074 18.491 -0.074 c
+18.418 3.498 m
+18.142 3.498 17.94 3.403 17.816 3.218 c
+17.687 3.031 17.613 2.741 17.595 2.352 c
+19.168 2.352 l
+19.168 2.439 l
+19.146 2.822 19.079 3.09 18.962 3.248 c
+18.844 3.413 18.66 3.498 18.418 3.498 c
+21.211 3.983 m
+21.226 3.542 l
+21.479 3.883 21.803 4.056 22.196 4.056 c
+22.901 4.056 23.258 3.586 23.268 2.645 c
+23.268 0 l
+22.622 0 l
+22.622 2.616 l
+22.622 2.929 22.566 3.149 22.46 3.278 c
+22.35 3.403 22.196 3.469 21.99 3.469 c
+21.832 3.469 21.685 3.413 21.549 3.307 c
+21.421 3.197 21.317 3.06 21.24 2.896 c
+21.24 0 l
+20.594 0 l
+20.594 3.983 l
+h
+25.62 0.484 m
+25.834 0.484 26.007 0.548 26.135 0.675 c
+26.271 0.812 26.344 1.003 26.356 1.249 c
+26.973 1.249 l
+26.951 0.866 26.815 0.548 26.561 0.294 c
+26.304 0.047 25.992 -0.074 25.62 -0.074 c
+25.128 -0.074 24.754 0.077 24.488 0.382 c
+24.232 0.694 24.106 1.161 24.106 1.778 c
+24.106 2.219 l
+24.106 2.815 24.232 3.27 24.488 3.586 c
+24.754 3.898 25.128 4.056 25.62 4.056 c
+26.021 4.056 26.341 3.924 26.576 3.659 c
+26.819 3.403 26.951 3.057 26.973 2.616 c
+26.356 2.616 l
+26.333 2.91 26.26 3.131 26.135 3.278 c
+26.017 3.424 25.845 3.498 25.62 3.498 c
+25.327 3.498 25.109 3.399 24.974 3.204 c
+24.835 3.017 24.76 2.707 24.754 2.278 c
+24.754 1.764 l
+24.754 1.294 24.82 0.959 24.959 0.764 c
+25.106 0.577 25.327 0.484 25.62 0.484 c
+29.148 -0.074 m
+28.648 -0.074 28.266 0.073 28.002 0.367 c
+27.737 0.661 27.605 1.095 27.605 1.675 c
+27.605 2.146 l
+27.605 2.741 27.73 3.208 27.987 3.542 c
+28.251 3.883 28.612 4.056 29.074 4.056 c
+29.534 4.056 29.876 3.902 30.104 3.601 c
+30.339 3.307 30.46 2.844 30.471 2.219 c
+30.471 1.793 l
+28.251 1.793 l
+28.251 1.705 l
+28.251 1.271 28.328 0.959 28.487 0.764 c
+28.652 0.577 28.884 0.484 29.178 0.484 c
+29.373 0.484 29.545 0.517 29.693 0.588 c
+29.839 0.665 29.975 0.783 30.104 0.941 c
+30.441 0.529 l
+30.155 0.124 29.725 -0.074 29.148 -0.074 c
+29.074 3.498 m
+28.799 3.498 28.598 3.403 28.472 3.218 c
+28.344 3.031 28.27 2.741 28.251 2.352 c
+29.824 2.352 l
+29.824 2.439 l
+29.803 2.822 29.736 3.09 29.618 3.248 c
+29.501 3.413 29.317 3.498 29.074 3.498 c
+32.955 2.175 m
+32.955 2.811 33.043 3.413 33.22 3.983 c
+33.396 4.548 33.639 5.045 33.955 5.468 c
+34.15 5.732 34.337 5.923 34.514 6.04 c
+34.646 5.585 l
+34.352 5.31 34.109 4.887 33.926 4.321 c
+33.738 3.752 33.635 3.119 33.616 2.425 c
+33.616 2.131 l
+33.616 1.267 33.734 0.503 33.969 -0.162 c
+34.154 -0.662 34.381 -1.044 34.646 -1.309 c
+34.514 -1.735 l
+34.285 -1.577 34.061 -1.327 33.837 -0.985 c
+33.249 -0.103 32.955 0.947 32.955 2.175 c
+37.277 1.014 m
+37.277 1.161 37.221 1.282 37.115 1.381 c
+37.005 1.477 36.799 1.595 36.498 1.734 c
+36.153 1.881 35.91 2.002 35.763 2.102 c
+35.615 2.208 35.505 2.326 35.44 2.454 c
+35.37 2.58 35.337 2.738 35.337 2.925 c
+35.337 3.248 35.455 3.516 35.69 3.733 c
+35.925 3.946 36.226 4.056 36.6 4.056 c
+36.983 4.056 37.292 3.943 37.527 3.719 c
+37.762 3.49 37.88 3.204 37.88 2.851 c
+37.233 2.851 l
+37.233 3.027 37.174 3.178 37.057 3.307 c
+36.939 3.432 36.785 3.498 36.6 3.498 c
+36.402 3.498 36.251 3.443 36.145 3.336 c
+36.035 3.237 35.983 3.104 35.983 2.94 c
+35.983 2.811 36.02 2.705 36.101 2.616 c
+36.178 2.535 36.369 2.432 36.674 2.308 c
+37.152 2.119 37.483 1.932 37.659 1.749 c
+37.836 1.572 37.924 1.344 37.924 1.072 c
+37.924 0.72 37.799 0.44 37.556 0.235 c
+37.321 0.029 37.005 -0.074 36.615 -0.074 c
+36.193 -0.074 35.854 0.043 35.601 0.278 c
+35.344 0.521 35.219 0.826 35.219 1.19 c
+35.866 1.19 l
+35.873 0.962 35.943 0.786 36.072 0.661 c
+36.197 0.544 36.38 0.484 36.615 0.484 c
+36.829 0.484 36.99 0.532 37.101 0.631 c
+37.218 0.727 37.277 0.856 37.277 1.014 c
+39.614 4.939 m
+39.614 3.983 l
+40.217 3.983 l
+40.217 3.453 l
+39.614 3.453 l
+39.614 0.984 l
+39.614 0.826 39.636 0.708 39.688 0.631 c
+39.746 0.55 39.835 0.514 39.952 0.514 c
+40.041 0.514 40.128 0.529 40.217 0.558 c
+40.217 0 l
+40.07 -0.048 39.916 -0.074 39.761 -0.074 c
+39.504 -0.074 39.309 0.018 39.173 0.205 c
+39.033 0.389 38.967 0.65 38.967 0.984 c
+38.967 3.453 l
+38.364 3.453 l
+38.364 3.983 l
+38.967 3.983 l
+38.967 4.939 l
+h
+43.024 0 m
+42.983 0.087 42.958 0.235 42.95 0.44 c
+42.715 0.095 42.422 -0.074 42.069 -0.074 c
+41.705 -0.074 41.422 0.022 41.217 0.22 c
+41.018 0.426 40.922 0.712 40.922 1.088 c
+40.922 1.488 41.059 1.807 41.334 2.042 c
+41.606 2.285 41.98 2.41 42.451 2.41 c
+42.936 2.41 l
+42.936 2.836 l
+42.936 3.072 42.881 3.237 42.774 3.336 c
+42.664 3.443 42.503 3.498 42.289 3.498 c
+42.091 3.498 41.929 3.439 41.805 3.322 c
+41.687 3.204 41.628 3.057 41.628 2.881 c
+40.981 2.881 l
+40.981 3.075 41.04 3.266 41.157 3.453 c
+41.282 3.638 41.444 3.785 41.643 3.895 c
+41.848 4.001 42.076 4.056 42.333 4.056 c
+42.734 4.056 43.039 3.954 43.245 3.748 c
+43.457 3.542 43.571 3.248 43.583 2.865 c
+43.583 0.852 l
+43.583 0.548 43.619 0.282 43.7 0.058 c
+43.7 0 l
+h
+42.157 0.514 m
+42.322 0.514 42.473 0.558 42.613 0.646 c
+42.759 0.735 42.866 0.845 42.936 0.984 c
+42.936 1.925 l
+42.568 1.925 l
+42.252 1.925 42.01 1.855 41.834 1.72 c
+41.657 1.591 41.569 1.404 41.569 1.161 c
+41.569 0.933 41.613 0.768 41.701 0.661 c
+41.79 0.562 41.94 0.514 42.157 0.514 c
+45.2 3.983 m
+45.215 3.542 l
+45.468 3.883 45.791 4.056 46.185 4.056 c
+46.89 4.056 47.247 3.586 47.257 2.645 c
+47.257 0 l
+46.611 0 l
+46.611 2.616 l
+46.611 2.929 46.555 3.149 46.449 3.278 c
+46.339 3.403 46.185 3.469 45.979 3.469 c
+45.821 3.469 45.674 3.413 45.537 3.307 c
+45.409 3.197 45.306 3.06 45.229 2.896 c
+45.229 0 l
+44.583 0 l
+44.583 3.983 l
+h
+48.095 2.175 m
+48.095 2.782 48.205 3.248 48.433 3.571 c
+48.668 3.895 48.996 4.056 49.418 4.056 c
+49.801 4.056 50.098 3.898 50.315 3.586 c
+50.315 5.644 l
+50.962 5.644 l
+50.962 0 l
+50.374 0 l
+50.33 0.426 l
+50.124 0.091 49.819 -0.074 49.418 -0.074 c
+49.007 -0.074 48.683 0.08 48.448 0.396 c
+48.213 0.72 48.095 1.176 48.095 1.764 c
+h
+48.743 1.793 m
+48.743 1.352 48.805 1.021 48.934 0.808 c
+49.069 0.602 49.29 0.5 49.595 0.5 c
+49.918 0.5 50.156 0.661 50.315 0.984 c
+50.315 2.998 l
+50.146 3.31 49.907 3.469 49.595 3.469 c
+49.29 3.469 49.069 3.366 48.934 3.16 c
+48.805 2.954 48.743 2.63 48.743 2.19 c
+h
+54.004 0 m
+53.964 0.087 53.938 0.235 53.931 0.44 c
+53.696 0.095 53.402 -0.074 53.049 -0.074 c
+52.685 -0.074 52.402 0.022 52.196 0.22 c
+51.997 0.426 51.902 0.712 51.902 1.088 c
+51.902 1.488 52.038 1.807 52.314 2.042 c
+52.586 2.285 52.961 2.41 53.431 2.41 c
+53.917 2.41 l
+53.917 2.836 l
+53.917 3.072 53.861 3.237 53.755 3.336 c
+53.644 3.443 53.483 3.498 53.269 3.498 c
+53.071 3.498 52.909 3.439 52.784 3.322 c
+52.666 3.204 52.608 3.057 52.608 2.881 c
+51.961 2.881 l
+51.961 3.075 52.02 3.266 52.138 3.453 c
+52.263 3.638 52.425 3.785 52.623 3.895 c
+52.828 4.001 53.057 4.056 53.314 4.056 c
+53.714 4.056 54.019 3.954 54.225 3.748 c
+54.438 3.542 54.552 3.248 54.563 2.865 c
+54.563 0.852 l
+54.563 0.548 54.6 0.282 54.68 0.058 c
+54.68 0 l
+h
+53.137 0.514 m
+53.302 0.514 53.453 0.558 53.593 0.646 c
+53.74 0.735 53.846 0.845 53.917 0.984 c
+53.917 1.925 l
+53.549 1.925 l
+53.233 1.925 52.99 1.855 52.814 1.72 c
+52.637 1.591 52.549 1.404 52.549 1.161 c
+52.549 0.933 52.593 0.768 52.681 0.661 c
+52.77 0.562 52.92 0.514 53.137 0.514 c
+57.209 3.366 m
+57.121 3.384 57.021 3.395 56.915 3.395 c
+56.581 3.395 56.346 3.212 56.209 2.851 c
+56.209 0 l
+55.563 0 l
+55.563 3.983 l
+56.194 3.983 l
+56.209 3.571 l
+56.386 3.895 56.628 4.056 56.944 4.056 c
+57.051 4.056 57.139 4.035 57.209 3.998 c
+h
+57.649 2.175 m
+57.649 2.782 57.76 3.248 57.988 3.571 c
+58.223 3.895 58.55 4.056 58.973 4.056 c
+59.355 4.056 59.652 3.898 59.87 3.586 c
+59.87 5.644 l
+60.516 5.644 l
+60.516 0 l
+59.928 0 l
+59.884 0.426 l
+59.679 0.091 59.373 -0.074 58.973 -0.074 c
+58.561 -0.074 58.237 0.08 58.002 0.396 c
+57.767 0.72 57.649 1.176 57.649 1.764 c
+h
+58.297 1.793 m
+58.297 1.352 58.359 1.021 58.488 0.808 c
+58.623 0.602 58.844 0.5 59.149 0.5 c
+59.473 0.5 59.712 0.661 59.87 0.984 c
+59.87 2.998 l
+59.7 3.31 59.461 3.469 59.149 3.469 c
+58.844 3.469 58.623 3.366 58.488 3.16 c
+58.359 2.954 58.297 2.63 58.297 2.19 c
+h
+62.912 2.131 m
+62.912 1.043 62.665 0.077 62.177 -0.765 c
+61.913 -1.214 61.637 -1.536 61.354 -1.735 c
+61.236 -1.309 l
+61.538 -1.015 61.784 -0.563 61.971 0.043 c
+62.166 0.65 62.266 1.315 62.266 2.042 c
+62.266 2.175 l
+62.266 3.104 62.11 3.939 61.809 4.674 c
+61.64 5.074 61.449 5.394 61.236 5.629 c
+61.354 6.04 l
+61.626 5.853 61.89 5.556 62.148 5.144 c
+62.655 4.292 62.912 3.285 62.912 2.131 c
+65.499 2.175 m
+65.499 2.752 65.635 3.208 65.911 3.542 c
+66.193 3.883 66.565 4.056 67.028 4.056 c
+67.487 4.056 67.855 3.887 68.13 3.557 c
+68.413 3.233 68.56 2.785 68.571 2.219 c
+68.571 1.793 l
+68.571 1.223 68.427 0.768 68.145 0.426 c
+67.87 0.091 67.502 -0.074 67.043 -0.074 c
+66.579 -0.074 66.208 0.087 65.925 0.411 c
+65.65 0.742 65.507 1.183 65.499 1.734 c
+h
+66.146 1.793 m
+66.146 1.389 66.223 1.072 66.381 0.837 c
+66.546 0.602 66.767 0.484 67.043 0.484 c
+67.608 0.484 67.903 0.897 67.924 1.72 c
+67.924 2.175 l
+67.924 2.576 67.84 2.896 67.675 3.131 c
+67.517 3.373 67.3 3.498 67.028 3.498 c
+66.763 3.498 66.546 3.373 66.381 3.131 c
+66.223 2.896 66.146 2.576 66.146 2.175 c
+h
+71.055 3.366 m
+70.967 3.384 70.868 3.395 70.761 3.395 c
+70.427 3.395 70.191 3.212 70.056 2.851 c
+70.056 0 l
+69.409 0 l
+69.409 3.983 l
+70.041 3.983 l
+70.056 3.571 l
+70.232 3.895 70.475 4.056 70.791 4.056 c
+70.897 4.056 70.985 4.035 71.055 3.998 c
+h
+75.465 0 m
+75.425 0.087 75.399 0.235 75.392 0.44 c
+75.157 0.095 74.862 -0.074 74.509 -0.074 c
+74.145 -0.074 73.863 0.022 73.657 0.22 c
+73.459 0.426 73.363 0.712 73.363 1.088 c
+73.363 1.488 73.499 1.807 73.775 2.042 c
+74.047 2.285 74.421 2.41 74.891 2.41 c
+75.377 2.41 l
+75.377 2.836 l
+75.377 3.072 75.321 3.237 75.215 3.336 c
+75.105 3.443 74.943 3.498 74.73 3.498 c
+74.532 3.498 74.37 3.439 74.245 3.322 c
+74.127 3.204 74.068 3.057 74.068 2.881 c
+73.422 2.881 l
+73.422 3.075 73.48 3.266 73.598 3.453 c
+73.723 3.638 73.885 3.785 74.083 3.895 c
+74.289 4.001 74.517 4.056 74.774 4.056 c
+75.174 4.056 75.479 3.954 75.685 3.748 c
+75.899 3.542 76.013 3.248 76.024 2.865 c
+76.024 0.852 l
+76.024 0.548 76.061 0.282 76.142 0.058 c
+76.142 0 l
+h
+74.598 0.514 m
+74.763 0.514 74.914 0.558 75.053 0.646 c
+75.201 0.735 75.307 0.845 75.377 0.984 c
+75.377 1.925 l
+75.009 1.925 l
+74.694 1.925 74.451 1.855 74.274 1.72 c
+74.098 1.591 74.01 1.404 74.01 1.161 c
+74.01 0.933 74.054 0.768 74.142 0.661 c
+74.23 0.562 74.38 0.514 74.598 0.514 c
+77.64 3.983 m
+77.655 3.542 l
+77.908 3.883 78.232 4.056 78.625 4.056 c
+79.331 4.056 79.687 3.586 79.698 2.645 c
+79.698 0 l
+79.051 0 l
+79.051 2.616 l
+79.051 2.929 78.997 3.149 78.889 3.278 c
+78.779 3.403 78.625 3.469 78.419 3.469 c
+78.261 3.469 78.114 3.413 77.979 3.307 c
+77.85 3.197 77.747 3.06 77.67 2.896 c
+77.67 0 l
+77.023 0 l
+77.023 3.983 l
+h
+82.256 2.175 m
+82.256 2.752 82.392 3.208 82.667 3.542 c
+82.951 3.883 83.321 4.056 83.785 4.056 c
+84.244 4.056 84.611 3.887 84.887 3.557 c
+85.17 3.233 85.317 2.785 85.328 2.219 c
+85.328 1.793 l
+85.328 1.223 85.185 0.768 84.902 0.426 c
+84.626 0.091 84.258 -0.074 83.799 -0.074 c
+83.336 -0.074 82.965 0.087 82.683 0.411 c
+82.407 0.742 82.263 1.183 82.256 1.734 c
+h
+82.903 1.793 m
+82.903 1.389 82.98 1.072 83.138 0.837 c
+83.303 0.602 83.524 0.484 83.799 0.484 c
+84.366 0.484 84.659 0.897 84.682 1.72 c
+84.682 2.175 l
+84.682 2.576 84.597 2.896 84.431 3.131 c
+84.273 3.373 84.057 3.498 83.785 3.498 c
+83.52 3.498 83.303 3.373 83.138 3.131 c
+82.98 2.896 82.903 2.576 82.903 2.175 c
+h
+89.047 1.793 m
+89.047 1.176 88.933 0.708 88.709 0.396 c
+88.492 0.08 88.169 -0.074 87.739 -0.074 c
+87.316 -0.074 87.003 0.106 86.798 0.47 c
+86.768 0 l
+86.166 0 l
+86.166 5.644 l
+86.812 5.644 l
+86.812 3.542 l
+87.026 3.883 87.334 4.056 87.739 4.056 c
+88.169 4.056 88.492 3.898 88.709 3.586 c
+88.933 3.281 89.047 2.815 89.047 2.19 c
+h
+88.4 2.175 m
+88.4 2.645 88.331 2.977 88.194 3.175 c
+88.065 3.37 87.857 3.469 87.562 3.469 c
+87.228 3.469 86.978 3.285 86.812 2.925 c
+86.812 1.043 l
+86.978 0.679 87.232 0.5 87.577 0.5 c
+87.871 0.5 88.08 0.602 88.209 0.808 c
+88.334 1.014 88.4 1.33 88.4 1.764 c
+h
+90.546 3.983 m
+90.546 -0.5 l
+90.546 -1.235 90.255 -1.603 89.679 -1.603 c
+89.54 -1.603 89.418 -1.58 89.312 -1.544 c
+89.312 -1 l
+89.382 -1.019 89.466 -1.029 89.576 -1.029 c
+89.683 -1.029 89.76 -0.985 89.811 -0.897 c
+89.87 -0.817 89.9 -0.676 89.9 -0.47 c
+89.9 3.983 l
+h
+90.575 5.026 m
+90.575 4.916 90.546 4.824 90.488 4.747 c
+90.429 4.677 90.333 4.644 90.208 4.644 c
+90.091 4.644 89.995 4.677 89.929 4.747 c
+89.87 4.824 89.841 4.916 89.841 5.026 c
+89.841 5.144 89.87 5.236 89.929 5.306 c
+89.995 5.383 90.091 5.423 90.208 5.423 c
+90.333 5.423 90.429 5.383 90.488 5.306 c
+90.546 5.225 90.575 5.134 90.575 5.026 c
+93.001 -0.074 m
+92.501 -0.074 92.119 0.073 91.855 0.367 c
+91.589 0.661 91.458 1.095 91.458 1.675 c
+91.458 2.146 l
+91.458 2.741 91.583 3.208 91.84 3.542 c
+92.104 3.883 92.464 4.056 92.927 4.056 c
+93.387 4.056 93.729 3.902 93.956 3.601 c
+94.192 3.307 94.313 2.844 94.324 2.219 c
+94.324 1.793 l
+92.104 1.793 l
+92.104 1.705 l
+92.104 1.271 92.181 0.959 92.339 0.764 c
+92.505 0.577 92.736 0.484 93.031 0.484 c
+93.225 0.484 93.398 0.517 93.545 0.588 c
+93.692 0.665 93.827 0.783 93.956 0.941 c
+94.294 0.529 l
+94.008 0.124 93.578 -0.074 93.001 -0.074 c
+92.927 3.498 m
+92.652 3.498 92.449 3.403 92.325 3.218 c
+92.196 3.031 92.123 2.741 92.104 2.352 c
+93.677 2.352 l
+93.677 2.439 l
+93.655 2.822 93.589 3.09 93.471 3.248 c
+93.353 3.413 93.17 3.498 92.927 3.498 c
+96.485 0.484 m
+96.698 0.484 96.871 0.548 96.999 0.675 c
+97.135 0.812 97.208 1.003 97.22 1.249 c
+97.837 1.249 l
+97.815 0.866 97.679 0.548 97.426 0.294 c
+97.168 0.047 96.856 -0.074 96.485 -0.074 c
+95.992 -0.074 95.618 0.077 95.352 0.382 c
+95.096 0.694 94.97 1.161 94.97 1.778 c
+94.97 2.219 l
+94.97 2.815 95.096 3.27 95.352 3.586 c
+95.618 3.898 95.992 4.056 96.485 4.056 c
+96.885 4.056 97.205 3.924 97.44 3.659 c
+97.683 3.403 97.815 3.057 97.837 2.616 c
+97.22 2.616 l
+97.197 2.91 97.124 3.131 96.999 3.278 c
+96.881 3.424 96.709 3.498 96.485 3.498 c
+96.191 3.498 95.974 3.399 95.838 3.204 c
+95.699 3.017 95.625 2.707 95.618 2.278 c
+95.618 1.764 l
+95.618 1.294 95.684 0.959 95.823 0.764 c
+95.97 0.577 96.191 0.484 96.485 0.484 c
+99.439 4.939 m
+99.439 3.983 l
+100.042 3.983 l
+100.042 3.453 l
+99.439 3.453 l
+99.439 0.984 l
+99.439 0.826 99.462 0.708 99.512 0.631 c
+99.572 0.55 99.66 0.514 99.778 0.514 c
+99.865 0.514 99.954 0.529 100.042 0.558 c
+100.042 0 l
+99.895 -0.048 99.74 -0.074 99.586 -0.074 c
+99.329 -0.074 99.134 0.018 98.998 0.205 c
+98.859 0.389 98.793 0.65 98.793 0.984 c
+98.793 3.453 l
+98.19 3.453 l
+98.19 3.983 l
+98.793 3.983 l
+98.793 4.939 l
+h
+102.511 2.175 m
+102.511 2.811 102.6 3.413 102.776 3.983 c
+102.953 4.548 103.194 5.045 103.51 5.468 c
+103.705 5.732 103.893 5.923 104.069 6.04 c
+104.202 5.585 l
+103.907 5.31 103.665 4.887 103.481 4.321 c
+103.294 3.752 103.191 3.119 103.173 2.425 c
+103.173 2.131 l
+103.173 1.267 103.29 0.503 103.526 -0.162 c
+103.709 -0.662 103.937 -1.044 104.202 -1.309 c
+104.069 -1.735 l
+103.842 -1.577 103.618 -1.327 103.393 -0.985 c
+102.805 -0.103 102.511 0.947 102.511 2.175 c
+106.936 0 m
+106.895 0.087 106.87 0.235 106.862 0.44 c
+106.627 0.095 106.333 -0.074 105.98 -0.074 c
+105.617 -0.074 105.334 0.022 105.128 0.22 c
+104.929 0.426 104.834 0.712 104.834 1.088 c
+104.834 1.488 104.97 1.807 105.245 2.042 c
+105.517 2.285 105.892 2.41 106.363 2.41 c
+106.847 2.41 l
+106.847 2.836 l
+106.847 3.072 106.793 3.237 106.685 3.336 c
+106.575 3.443 106.414 3.498 106.201 3.498 c
+106.003 3.498 105.841 3.439 105.716 3.322 c
+105.598 3.204 105.54 3.057 105.54 2.881 c
+104.892 2.881 l
+104.892 3.075 104.952 3.266 105.069 3.453 c
+105.193 3.638 105.355 3.785 105.554 3.895 c
+105.76 4.001 105.987 4.056 106.245 4.056 c
+106.645 4.056 106.951 3.954 107.156 3.748 c
+107.369 3.542 107.483 3.248 107.495 2.865 c
+107.495 0.852 l
+107.495 0.548 107.531 0.282 107.612 0.058 c
+107.612 0 l
+h
+106.068 0.514 m
+106.234 0.514 106.384 0.558 106.524 0.646 c
+106.671 0.735 106.778 0.845 106.847 0.984 c
+106.847 1.925 l
+106.48 1.925 l
+106.164 1.925 105.922 1.855 105.745 1.72 c
+105.569 1.591 105.48 1.404 105.48 1.161 c
+105.48 0.933 105.525 0.768 105.613 0.661 c
+105.701 0.562 105.852 0.514 106.068 0.514 c
+109.111 3.983 m
+109.126 3.542 l
+109.38 3.883 109.702 4.056 110.096 4.056 c
+110.801 4.056 111.158 3.586 111.169 2.645 c
+111.169 0 l
+110.522 0 l
+110.522 2.616 l
+110.522 2.929 110.467 3.149 110.361 3.278 c
+110.25 3.403 110.096 3.469 109.891 3.469 c
+109.733 3.469 109.585 3.413 109.449 3.307 c
+109.32 3.197 109.218 3.06 109.141 2.896 c
+109.141 0 l
+108.494 0 l
+108.494 3.983 l
+h
+112.756 3.983 m
+112.771 3.542 l
+113.025 3.883 113.348 4.056 113.741 4.056 c
+114.447 4.056 114.803 3.586 114.814 2.645 c
+114.814 0 l
+114.167 0 l
+114.167 2.616 l
+114.167 2.929 114.113 3.149 114.006 3.278 c
+113.895 3.403 113.741 3.469 113.536 3.469 c
+113.378 3.469 113.23 3.413 113.095 3.307 c
+112.966 3.197 112.863 3.06 112.786 2.896 c
+112.786 0 l
+112.139 0 l
+112.139 3.983 l
+h
+115.653 2.175 m
+115.653 2.752 115.788 3.208 116.064 3.542 c
+116.347 3.883 116.718 4.056 117.181 4.056 c
+117.64 4.056 118.007 3.887 118.283 3.557 c
+118.566 3.233 118.713 2.785 118.724 2.219 c
+118.724 1.793 l
+118.724 1.223 118.581 0.768 118.298 0.426 c
+118.022 0.091 117.655 -0.074 117.195 -0.074 c
+116.733 -0.074 116.361 0.087 116.079 0.411 c
+115.803 0.742 115.659 1.183 115.653 1.734 c
+h
+116.299 1.793 m
+116.299 1.389 116.376 1.072 116.534 0.837 c
+116.7 0.602 116.92 0.484 117.195 0.484 c
+117.762 0.484 118.055 0.897 118.078 1.72 c
+118.078 2.175 l
+118.078 2.576 117.993 2.896 117.828 3.131 c
+117.67 3.373 117.453 3.498 117.181 3.498 c
+116.916 3.498 116.7 3.373 116.534 3.131 c
+116.376 2.896 116.299 2.576 116.299 2.175 c
+h
+120.415 4.939 m
+120.415 3.983 l
+121.018 3.983 l
+121.018 3.453 l
+120.415 3.453 l
+120.415 0.984 l
+120.415 0.826 120.436 0.708 120.488 0.631 c
+120.547 0.55 120.635 0.514 120.752 0.514 c
+120.841 0.514 120.929 0.529 121.018 0.558 c
+121.018 0 l
+120.87 -0.048 120.716 -0.074 120.561 -0.074 c
+120.305 -0.074 120.11 0.018 119.973 0.205 c
+119.834 0.389 119.768 0.65 119.768 0.984 c
+119.768 3.453 l
+119.165 3.453 l
+119.165 3.983 l
+119.768 3.983 l
+119.768 4.939 l
+h
+123.825 0 m
+123.784 0.087 123.759 0.235 123.751 0.44 c
+123.516 0.095 123.222 -0.074 122.869 -0.074 c
+122.506 -0.074 122.223 0.022 122.017 0.22 c
+121.818 0.426 121.723 0.712 121.723 1.088 c
+121.723 1.488 121.859 1.807 122.134 2.042 c
+122.406 2.285 122.782 2.41 123.252 2.41 c
+123.736 2.41 l
+123.736 2.836 l
+123.736 3.072 123.682 3.237 123.575 3.336 c
+123.465 3.443 123.303 3.498 123.09 3.498 c
+122.892 3.498 122.73 3.439 122.605 3.322 c
+122.487 3.204 122.429 3.057 122.429 2.881 c
+121.782 2.881 l
+121.782 3.075 121.841 3.266 121.958 3.453 c
+122.083 3.638 122.244 3.785 122.443 3.895 c
+122.649 4.001 122.877 4.056 123.134 4.056 c
+123.534 4.056 123.84 3.954 124.045 3.748 c
+124.258 3.542 124.372 3.248 124.384 2.865 c
+124.384 0.852 l
+124.384 0.548 124.42 0.282 124.501 0.058 c
+124.501 0 l
+h
+122.957 0.514 m
+123.123 0.514 123.274 0.558 123.414 0.646 c
+123.56 0.735 123.667 0.845 123.736 0.984 c
+123.736 1.925 l
+123.369 1.925 l
+123.053 1.925 122.811 1.855 122.634 1.72 c
+122.458 1.591 122.37 1.404 122.37 1.161 c
+122.37 0.933 122.414 0.768 122.502 0.661 c
+122.591 0.562 122.741 0.514 122.957 0.514 c
+126.236 4.939 m
+126.236 3.983 l
+126.838 3.983 l
+126.838 3.453 l
+126.236 3.453 l
+126.236 0.984 l
+126.236 0.826 126.258 0.708 126.309 0.631 c
+126.368 0.55 126.456 0.514 126.574 0.514 c
+126.662 0.514 126.75 0.529 126.838 0.558 c
+126.838 0 l
+126.691 -0.048 126.537 -0.074 126.383 -0.074 c
+126.125 -0.074 125.93 0.018 125.795 0.205 c
+125.655 0.389 125.589 0.65 125.589 0.984 c
+125.589 3.453 l
+124.986 3.453 l
+124.986 3.983 l
+125.589 3.983 l
+125.589 4.939 l
+h
+129.028 -0.074 m
+128.529 -0.074 128.147 0.073 127.882 0.367 c
+127.617 0.661 127.485 1.095 127.485 1.675 c
+127.485 2.146 l
+127.485 2.741 127.61 3.208 127.867 3.542 c
+128.132 3.883 128.492 4.056 128.955 4.056 c
+129.414 4.056 129.756 3.902 129.984 3.601 c
+130.219 3.307 130.34 2.844 130.352 2.219 c
+130.352 1.793 l
+128.132 1.793 l
+128.132 1.705 l
+128.132 1.271 128.209 0.959 128.367 0.764 c
+128.532 0.577 128.764 0.484 129.058 0.484 c
+129.253 0.484 129.425 0.517 129.572 0.588 c
+129.719 0.665 129.855 0.783 129.984 0.941 c
+130.322 0.529 l
+130.036 0.124 129.606 -0.074 129.028 -0.074 c
+128.955 3.498 m
+128.679 3.498 128.477 3.403 128.353 3.218 c
+128.224 3.031 128.15 2.741 128.132 2.352 c
+129.704 2.352 l
+129.704 2.439 l
+129.683 2.822 129.616 3.09 129.498 3.248 c
+129.381 3.413 129.197 3.498 128.955 3.498 c
+130.998 2.175 m
+130.998 2.782 131.108 3.248 131.336 3.571 c
+131.571 3.895 131.898 4.056 132.321 4.056 c
+132.703 4.056 133.001 3.898 133.217 3.586 c
+133.217 5.644 l
+133.864 5.644 l
+133.864 0 l
+133.276 0 l
+133.232 0.426 l
+133.026 0.091 132.721 -0.074 132.321 -0.074 c
+131.91 -0.074 131.586 0.08 131.351 0.396 c
+131.116 0.72 130.998 1.176 130.998 1.764 c
+h
+131.645 1.793 m
+131.645 1.352 131.707 1.021 131.836 0.808 c
+131.972 0.602 132.193 0.5 132.497 0.5 c
+132.821 0.5 133.059 0.661 133.217 0.984 c
+133.217 2.998 l
+133.049 3.31 132.81 3.469 132.497 3.469 c
+132.193 3.469 131.972 3.366 131.836 3.16 c
+131.707 2.954 131.645 2.63 131.645 2.19 c
+h
+136.26 2.131 m
+136.26 1.043 136.014 0.077 135.526 -0.765 c
+135.26 -1.214 134.985 -1.536 134.703 -1.735 c
+134.585 -1.309 l
+134.886 -1.015 135.133 -0.563 135.32 0.043 c
+135.514 0.65 135.613 1.315 135.613 2.042 c
+135.613 2.175 l
+135.613 3.104 135.459 3.939 135.158 4.674 c
+134.989 5.074 134.798 5.394 134.585 5.629 c
+134.703 6.04 l
+134.974 5.853 135.239 5.556 135.496 5.144 c
+136.003 4.292 136.26 3.285 136.26 2.131 c
+f
+Q
+0 0 0 0 k
+q 1 0 0 1 305.5389 158.4271 cm
+0 0 m
+-1.088 0 l
+-1.088 2.294 l
+-2.675 2.294 l
+-2.675 0 l
+-3.763 0 l
+-3.763 5.351 l
+-2.675 5.351 l
+-2.675 3.19 l
+-1.088 3.19 l
+-1.088 5.351 l
+0 5.351 l
+h
+3.615 2.323 m
+1.94 2.323 l
+1.94 0.897 l
+3.925 0.897 l
+3.925 0 l
+0.852 0 l
+0.852 5.351 l
+3.925 5.351 l
+3.925 4.454 l
+1.94 4.454 l
+1.94 3.19 l
+3.615 3.19 l
+h
+7.1 1.103 m
+5.629 1.103 l
+5.336 0 l
+4.204 0 l
+5.865 5.351 l
+6.865 5.351 l
+8.54 0 l
+7.393 0 l
+h
+5.865 1.999 m
+6.865 1.999 l
+6.364 3.911 l
+h
+9.04 0 m
+9.04 5.351 l
+10.466 5.351 l
+11.083 5.351 11.575 5.149 11.95 4.748 c
+12.321 4.355 12.513 3.815 12.523 3.131 c
+12.523 2.264 l
+12.523 1.559 12.336 1.004 11.965 0.603 c
+11.59 0.198 11.083 0 10.436 0 c
+h
+10.127 4.454 m
+10.127 0.897 l
+10.451 0.897 l
+10.811 0.897 11.068 0.989 11.215 1.176 c
+11.362 1.371 11.436 1.698 11.436 2.161 c
+11.436 3.102 l
+11.436 3.601 11.366 3.947 11.23 4.146 c
+11.09 4.341 10.855 4.443 10.524 4.454 c
+h
+f
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 331.7103 158.4271 cm
+0 0 m
+-0.04 0.088 -0.066 0.235 -0.073 0.441 c
+-0.309 0.096 -0.603 -0.073 -0.956 -0.073 c
+-1.319 -0.073 -1.602 0.023 -1.808 0.221 c
+-2.007 0.426 -2.102 0.713 -2.102 1.088 c
+-2.102 1.488 -1.966 1.808 -1.691 2.043 c
+-1.419 2.286 -1.043 2.411 -0.573 2.411 c
+-0.088 2.411 l
+-0.088 2.837 l
+-0.088 3.072 -0.143 3.238 -0.25 3.337 c
+-0.36 3.444 -0.522 3.499 -0.735 3.499 c
+-0.933 3.499 -1.095 3.44 -1.22 3.323 c
+-1.338 3.205 -1.396 3.057 -1.396 2.881 c
+-2.043 2.881 l
+-2.043 3.076 -1.984 3.267 -1.866 3.454 c
+-1.741 3.639 -1.58 3.786 -1.382 3.896 c
+-1.176 4.002 -0.948 4.057 -0.691 4.057 c
+-0.291 4.057 0.015 3.954 0.22 3.749 c
+0.434 3.543 0.548 3.248 0.559 2.866 c
+0.559 0.853 l
+0.559 0.548 0.595 0.283 0.676 0.059 c
+0.676 0 l
+h
+-0.867 0.515 m
+-0.702 0.515 -0.551 0.559 -0.411 0.647 c
+-0.264 0.736 -0.158 0.846 -0.088 0.985 c
+-0.088 1.926 l
+-0.455 1.926 l
+-0.771 1.926 -1.014 1.856 -1.191 1.72 c
+-1.367 1.592 -1.455 1.405 -1.455 1.162 c
+-1.455 0.934 -1.411 0.769 -1.323 0.661 c
+-1.234 0.563 -1.084 0.515 -0.867 0.515 c
+6.159 1.794 m
+6.159 1.166 6.041 0.695 5.806 0.383 c
+5.579 0.077 5.262 -0.073 4.85 -0.073 c
+4.447 -0.073 4.138 0.077 3.925 0.383 c
+3.925 -1.529 l
+3.278 -1.529 l
+3.278 3.984 l
+3.866 3.984 l
+3.91 3.543 l
+4.123 3.884 4.432 4.057 4.836 4.057 c
+5.277 4.057 5.604 3.903 5.821 3.601 c
+6.034 3.296 6.148 2.841 6.159 2.234 c
+h
+5.512 2.176 m
+5.512 2.617 5.442 2.94 5.307 3.146 c
+5.167 3.359 4.946 3.469 4.645 3.469 c
+4.329 3.469 4.09 3.315 3.925 3.013 c
+3.925 0.941 l
+4.09 0.636 4.329 0.485 4.645 0.485 c
+4.939 0.485 5.152 0.588 5.292 0.794 c
+5.428 1.008 5.501 1.338 5.512 1.779 c
+h
+7.703 0 -0.647 5.644 re
+10.76 0 m
+10.72 0.088 10.693 0.235 10.686 0.441 c
+10.451 0.096 10.157 -0.073 9.804 -0.073 c
+9.44 -0.073 9.157 0.023 8.952 0.221 c
+8.754 0.426 8.658 0.713 8.658 1.088 c
+8.658 1.488 8.794 1.808 9.07 2.043 c
+9.342 2.286 9.716 2.411 10.186 2.411 c
+10.672 2.411 l
+10.672 2.837 l
+10.672 3.072 10.616 3.238 10.51 3.337 c
+10.4 3.444 10.238 3.499 10.025 3.499 c
+9.826 3.499 9.664 3.44 9.54 3.323 c
+9.422 3.205 9.363 3.057 9.363 2.881 c
+8.717 2.881 l
+8.717 3.076 8.775 3.267 8.893 3.454 c
+9.018 3.639 9.18 3.786 9.378 3.896 c
+9.584 4.002 9.812 4.057 10.069 4.057 c
+10.469 4.057 10.774 3.954 10.98 3.749 c
+11.194 3.543 11.308 3.248 11.318 2.866 c
+11.318 0.853 l
+11.318 0.548 11.355 0.283 11.436 0.059 c
+11.436 0 l
+h
+9.893 0.515 m
+10.057 0.515 10.209 0.559 10.348 0.647 c
+10.495 0.736 10.602 0.846 10.672 0.985 c
+10.672 1.926 l
+10.304 1.926 l
+9.988 1.926 9.745 1.856 9.569 1.72 c
+9.392 1.592 9.305 1.405 9.305 1.162 c
+9.305 0.934 9.349 0.769 9.437 0.661 c
+9.525 0.563 9.676 0.515 9.893 0.515 c
+13.7 0.485 m
+13.913 0.485 14.086 0.548 14.214 0.676 c
+14.35 0.813 14.423 1.004 14.435 1.249 c
+15.052 1.249 l
+15.03 0.867 14.894 0.548 14.641 0.294 c
+14.383 0.048 14.071 -0.073 13.7 -0.073 c
+13.207 -0.073 12.833 0.077 12.567 0.383 c
+12.311 0.695 12.185 1.162 12.185 1.779 c
+12.185 2.22 l
+12.185 2.816 12.311 3.271 12.567 3.587 c
+12.833 3.899 13.207 4.057 13.7 4.057 c
+14.1 4.057 14.42 3.925 14.655 3.66 c
+14.898 3.404 15.03 3.057 15.052 2.617 c
+14.435 2.617 l
+14.412 2.911 14.339 3.131 14.214 3.278 c
+14.096 3.425 13.924 3.499 13.7 3.499 c
+13.406 3.499 13.189 3.4 13.053 3.205 c
+12.914 3.017 12.84 2.708 12.833 2.278 c
+12.833 1.764 l
+12.833 1.294 12.898 0.96 13.038 0.765 c
+13.185 0.578 13.406 0.485 13.7 0.485 c
+17.228 -0.073 m
+16.727 -0.073 16.345 0.073 16.081 0.368 c
+15.817 0.661 15.684 1.095 15.684 1.676 c
+15.684 2.147 l
+15.684 2.741 15.809 3.209 16.066 3.543 c
+16.33 3.884 16.691 4.057 17.153 4.057 c
+17.613 4.057 17.955 3.903 18.183 3.601 c
+18.418 3.308 18.539 2.845 18.55 2.22 c
+18.55 1.794 l
+16.33 1.794 l
+16.33 1.706 l
+16.33 1.272 16.407 0.96 16.565 0.765 c
+16.731 0.578 16.962 0.485 17.257 0.485 c
+17.452 0.485 17.624 0.518 17.771 0.588 c
+17.918 0.665 18.054 0.783 18.183 0.941 c
+18.521 0.53 l
+18.234 0.125 17.804 -0.073 17.228 -0.073 c
+17.153 3.499 m
+16.878 3.499 16.676 3.404 16.551 3.219 c
+16.422 3.032 16.349 2.741 16.33 2.352 c
+17.903 2.352 l
+17.903 2.44 l
+17.882 2.822 17.816 3.091 17.698 3.248 c
+17.581 3.414 17.396 3.499 17.153 3.499 c
+24.018 1.147 m
+24.621 3.984 l
+25.267 3.984 l
+24.283 0 l
+23.769 0 l
+22.99 2.852 l
+22.24 0 l
+21.71 0 l
+20.756 3.984 l
+21.387 3.984 l
+22.005 1.22 l
+22.74 3.984 l
+23.254 3.984 l
+h
+26.591 3.572 m
+26.844 3.896 27.164 4.057 27.546 4.057 c
+28.251 4.057 28.608 3.587 28.619 2.646 c
+28.619 0 l
+27.972 0 l
+27.972 2.617 l
+27.972 2.929 27.917 3.15 27.811 3.278 c
+27.7 3.404 27.546 3.469 27.341 3.469 c
+27.183 3.469 27.035 3.414 26.9 3.308 c
+26.771 3.198 26.668 3.061 26.591 2.896 c
+26.591 0 l
+25.944 0 l
+25.944 5.644 l
+26.591 5.644 l
+h
+31 -0.073 m
+30.501 -0.073 30.119 0.073 29.853 0.368 c
+29.589 0.661 29.457 1.095 29.457 1.676 c
+29.457 2.147 l
+29.457 2.741 29.582 3.209 29.839 3.543 c
+30.104 3.884 30.464 4.057 30.927 4.057 c
+31.386 4.057 31.728 3.903 31.956 3.601 c
+32.191 3.308 32.313 2.845 32.323 2.22 c
+32.323 1.794 l
+30.104 1.794 l
+30.104 1.706 l
+30.104 1.272 30.181 0.96 30.339 0.765 c
+30.504 0.578 30.736 0.485 31.029 0.485 c
+31.224 0.485 31.397 0.518 31.544 0.588 c
+31.692 0.665 31.827 0.783 31.956 0.941 c
+32.294 0.53 l
+32.007 0.125 31.577 -0.073 31 -0.073 c
+30.927 3.499 m
+30.651 3.499 30.449 3.404 30.324 3.219 c
+30.196 3.032 30.122 2.741 30.104 2.352 c
+31.677 2.352 l
+31.677 2.44 l
+31.655 2.822 31.588 3.091 31.471 3.248 c
+31.353 3.414 31.17 3.499 30.927 3.499 c
+34.749 3.366 m
+34.661 3.385 34.561 3.396 34.455 3.396 c
+34.121 3.396 33.885 3.212 33.749 2.852 c
+33.749 0 l
+33.103 0 l
+33.103 3.984 l
+33.734 3.984 l
+33.749 3.572 l
+33.926 3.896 34.168 4.057 34.484 4.057 c
+34.591 4.057 34.678 4.035 34.749 3.998 c
+h
+36.748 -0.073 m
+36.248 -0.073 35.866 0.073 35.601 0.368 c
+35.337 0.661 35.204 1.095 35.204 1.676 c
+35.204 2.147 l
+35.204 2.741 35.329 3.209 35.586 3.543 c
+35.851 3.884 36.211 4.057 36.674 4.057 c
+37.134 4.057 37.475 3.903 37.703 3.601 c
+37.938 3.308 38.059 2.845 38.071 2.22 c
+38.071 1.794 l
+35.851 1.794 l
+35.851 1.706 l
+35.851 1.272 35.928 0.96 36.086 0.765 c
+36.251 0.578 36.483 0.485 36.777 0.485 c
+36.972 0.485 37.144 0.518 37.292 0.588 c
+37.439 0.665 37.574 0.783 37.703 0.941 c
+38.042 0.53 l
+37.755 0.125 37.325 -0.073 36.748 -0.073 c
+36.674 3.499 m
+36.398 3.499 36.197 3.404 36.072 3.219 c
+35.943 3.032 35.869 2.741 35.851 2.352 c
+37.424 2.352 l
+37.424 2.44 l
+37.402 2.822 37.336 3.091 37.218 3.248 c
+37.101 3.414 36.917 3.499 36.674 3.499 c
+41.657 1.088 m
+42.377 3.984 l
+43.068 3.984 l
+41.774 -0.558 l
+41.676 -0.9 41.533 -1.161 41.348 -1.338 c
+41.172 -1.514 40.97 -1.602 40.746 -1.602 c
+40.658 -1.602 40.544 -1.579 40.408 -1.543 c
+40.408 -0.999 l
+40.554 -1.014 l
+40.739 -1.014 40.885 -0.97 40.996 -0.881 c
+41.102 -0.793 41.19 -0.635 41.26 -0.411 c
+41.377 0.03 l
+40.217 3.984 l
+40.922 3.984 l
+h
+43.509 2.176 m
+43.509 2.753 43.646 3.209 43.921 3.543 c
+44.203 3.884 44.575 4.057 45.038 4.057 c
+45.497 4.057 45.865 3.888 46.14 3.558 c
+46.424 3.234 46.57 2.786 46.582 2.22 c
+46.582 1.794 l
+46.582 1.224 46.438 0.769 46.155 0.426 c
+45.88 0.092 45.512 -0.073 45.053 -0.073 c
+44.59 -0.073 44.219 0.088 43.935 0.412 c
+43.66 0.742 43.517 1.183 43.509 1.735 c
+h
+44.156 1.794 m
+44.156 1.389 44.234 1.073 44.392 0.838 c
+44.556 0.603 44.777 0.485 45.053 0.485 c
+45.618 0.485 45.913 0.897 45.934 1.72 c
+45.934 2.176 l
+45.934 2.577 45.85 2.896 45.685 3.131 c
+45.527 3.373 45.31 3.499 45.038 3.499 c
+44.774 3.499 44.556 3.373 44.392 3.131 c
+44.234 2.896 44.156 2.577 44.156 2.176 c
+h
+49.448 0.353 m
+49.231 0.067 48.918 -0.073 48.507 -0.073 c
+48.143 -0.073 47.868 0.048 47.684 0.294 c
+47.507 0.548 47.412 0.912 47.405 1.382 c
+47.405 3.984 l
+48.051 3.984 l
+48.051 1.441 l
+48.051 0.813 48.235 0.5 48.61 0.5 c
+49.011 0.5 49.286 0.676 49.433 1.029 c
+49.433 3.984 l
+50.079 3.984 l
+50.079 0 l
+49.462 0 l
+h
+52.711 3.366 m
+52.623 3.385 52.523 3.396 52.417 3.396 c
+52.082 3.396 51.847 3.212 51.711 2.852 c
+51.711 0 l
+51.064 0 l
+51.064 3.984 l
+51.696 3.984 l
+51.711 3.572 l
+51.887 3.896 52.13 4.057 52.446 4.057 c
+52.553 4.057 52.641 4.035 52.711 3.998 c
+h
+f
+Q
+q 1 0 0 1 389.5808 160.1769 cm
+0 0 m
+0.353 2.234 l
+1.352 2.234 l
+0.529 -1.75 l
+-0.339 -1.75 l
+-0.897 0.558 l
+-1.455 -1.75 l
+-2.323 -1.75 l
+-3.146 2.234 l
+-2.147 2.234 l
+-1.794 0 l
+-1.264 2.234 l
+-0.53 2.234 l
+h
+1.749 0.367 m
+1.749 0.974 1.888 1.448 2.175 1.793 c
+2.458 2.135 2.851 2.308 3.351 2.308 c
+3.858 2.308 4.255 2.135 4.542 1.793 c
+4.825 1.448 4.968 0.974 4.968 0.367 c
+4.968 0.103 l
+4.968 -0.497 4.825 -0.967 4.542 -1.309 c
+4.255 -1.654 3.858 -1.823 3.351 -1.823 c
+2.84 -1.823 2.443 -1.654 2.161 -1.309 c
+1.885 -0.967 1.749 -0.493 1.749 0.118 c
+h
+2.792 0.103 m
+2.792 -0.603 2.977 -0.956 3.351 -0.956 c
+3.704 -0.956 3.895 -0.661 3.925 -0.073 c
+3.925 0.367 l
+3.925 0.727 3.873 0.999 3.777 1.176 c
+3.678 1.352 3.534 1.44 3.351 1.44 c
+3.175 1.44 3.035 1.352 2.94 1.176 c
+2.84 0.999 2.792 0.727 2.792 0.367 c
+h
+7.57 1.22 m
+7.231 1.249 l
+6.945 1.249 6.754 1.124 6.659 0.881 c
+6.659 -1.75 l
+5.614 -1.75 l
+5.614 2.234 l
+6.585 2.234 l
+6.614 1.793 l
+6.78 2.135 7.011 2.308 7.305 2.308 c
+7.422 2.308 7.515 2.285 7.584 2.248 c
+h
+9.437 -0.221 m
+9.157 -0.53 l
+9.157 -1.75 l
+8.114 -1.75 l
+8.114 3.895 l
+9.157 3.895 l
+9.157 0.852 l
+9.275 1.043 l
+9.995 2.234 l
+11.245 2.234 l
+10.083 0.588 l
+11.347 -1.75 l
+10.157 -1.75 l
+h
+12.803 -1.75 -1.043 3.984 re
+11.715 3.262 m
+11.715 3.418 11.763 3.546 11.862 3.645 c
+11.968 3.752 12.104 3.807 12.274 3.807 c
+12.45 3.807 12.586 3.752 12.685 3.645 c
+12.791 3.546 12.847 3.418 12.847 3.262 c
+12.847 3.094 12.791 2.958 12.685 2.851 c
+12.586 2.753 12.45 2.705 12.274 2.705 c
+12.104 2.705 11.968 2.753 11.862 2.851 c
+11.763 2.958 11.715 3.094 11.715 3.262 c
+14.566 2.234 m
+14.596 1.837 l
+14.831 2.15 15.133 2.308 15.507 2.308 c
+16.191 2.308 16.544 1.826 16.565 0.867 c
+16.565 -1.75 l
+15.522 -1.75 l
+15.522 0.793 l
+15.522 1.018 15.486 1.18 15.419 1.278 c
+15.349 1.374 15.232 1.425 15.066 1.425 c
+14.879 1.425 14.732 1.33 14.626 1.146 c
+14.626 -1.75 l
+13.581 -1.75 l
+13.581 2.234 l
+h
+17.183 0.367 m
+17.183 1.014 17.3 1.499 17.535 1.822 c
+17.771 2.146 18.102 2.308 18.535 2.308 c
+18.888 2.308 19.16 2.165 19.359 1.881 c
+19.403 2.234 l
+20.343 2.234 l
+20.343 -1.75 l
+20.343 -2.257 20.2 -2.646 19.917 -2.911 c
+19.63 -3.183 19.226 -3.323 18.697 -3.323 c
+18.47 -3.323 18.234 -3.278 17.992 -3.19 c
+17.756 -3.102 17.58 -2.988 17.462 -2.852 c
+17.815 -2.132 l
+17.911 -2.238 18.039 -2.323 18.197 -2.382 c
+18.351 -2.448 18.499 -2.484 18.638 -2.484 c
+18.873 -2.484 19.039 -2.425 19.137 -2.308 c
+19.245 -2.198 19.299 -2.022 19.299 -1.779 c
+19.299 -1.426 l
+19.101 -1.691 18.844 -1.823 18.52 -1.823 c
+18.098 -1.823 17.771 -1.661 17.535 -1.338 c
+17.308 -1.008 17.19 -0.537 17.183 0.073 c
+h
+18.227 0.103 m
+18.227 -0.272 18.274 -0.54 18.374 -0.706 c
+18.47 -0.875 18.624 -0.956 18.829 -0.956 c
+19.042 -0.956 19.201 -0.879 19.299 -0.721 c
+19.299 1.176 l
+19.189 1.341 19.035 1.425 18.829 1.425 c
+18.624 1.425 18.47 1.341 18.374 1.176 c
+18.274 1.007 18.227 0.738 18.227 0.367 c
+h
+22.695 0.367 m
+22.695 1.014 22.802 1.499 23.018 1.822 c
+23.243 2.146 23.566 2.308 23.989 2.308 c
+24.301 2.308 24.554 2.175 24.753 1.911 c
+24.753 3.895 l
+25.811 3.895 l
+25.811 -1.75 l
+24.856 -1.75 l
+24.812 -1.338 l
+24.595 -1.661 24.319 -1.823 23.989 -1.823 c
+23.577 -1.823 23.257 -1.669 23.033 -1.353 c
+22.817 -1.029 22.703 -0.559 22.695 0.058 c
+h
+23.739 0.103 m
+23.739 -0.291 23.775 -0.566 23.856 -0.721 c
+23.945 -0.879 24.091 -0.956 24.297 -0.956 c
+24.503 -0.956 24.654 -0.864 24.753 -0.676 c
+24.753 1.132 l
+24.654 1.326 24.503 1.425 24.297 1.425 c
+24.099 1.425 23.959 1.344 23.871 1.19 c
+23.783 1.043 23.739 0.771 23.739 0.382 c
+h
+27.663 -1.75 -1.043 3.984 re
+26.576 3.262 m
+26.576 3.418 26.623 3.546 26.723 3.645 c
+26.829 3.752 26.965 3.807 27.134 3.807 c
+27.311 3.807 27.446 3.752 27.546 3.645 c
+27.652 3.546 27.708 3.418 27.708 3.262 c
+27.708 3.094 27.652 2.958 27.546 2.851 c
+27.446 2.753 27.311 2.705 27.134 2.705 c
+26.965 2.705 26.829 2.753 26.723 2.851 c
+26.623 2.958 26.576 3.094 26.576 3.262 c
+30.426 1.22 m
+30.089 1.249 l
+29.802 1.249 29.611 1.124 29.516 0.881 c
+29.516 -1.75 l
+28.471 -1.75 l
+28.471 2.234 l
+29.442 2.234 l
+29.471 1.793 l
+29.637 2.135 29.868 2.308 30.162 2.308 c
+30.28 2.308 30.372 2.285 30.441 2.248 c
+h
+32.5 -1.823 m
+31.97 -1.823 31.551 -1.669 31.249 -1.353 c
+30.956 -1.029 30.809 -0.57 30.809 0.029 c
+30.809 0.338 l
+30.809 0.962 30.945 1.448 31.22 1.793 c
+31.492 2.135 31.885 2.308 32.396 2.308 c
+32.896 2.308 33.267 2.146 33.514 1.822 c
+33.767 1.499 33.9 1.022 33.911 0.397 c
+33.911 -0.103 l
+31.837 -0.103 l
+31.856 -0.397 31.918 -0.614 32.029 -0.75 c
+32.147 -0.89 32.327 -0.956 32.573 -0.956 c
+32.915 -0.956 33.205 -0.838 33.44 -0.603 c
+33.852 -1.235 l
+33.723 -1.411 33.535 -1.555 33.293 -1.661 c
+33.047 -1.768 32.782 -1.823 32.5 -1.823 c
+31.853 0.617 m
+32.882 0.617 l
+32.882 0.72 l
+32.882 0.955 32.841 1.132 32.764 1.249 c
+32.694 1.374 32.566 1.44 32.382 1.44 c
+32.205 1.44 32.073 1.371 31.985 1.234 c
+31.904 1.106 31.86 0.9 31.853 0.617 c
+35.939 -0.956 m
+36.233 -0.956 36.383 -0.761 36.394 -0.368 c
+37.364 -0.368 l
+37.364 -0.802 37.233 -1.154 36.968 -1.426 c
+36.703 -1.691 36.365 -1.823 35.953 -1.823 c
+35.442 -1.823 35.049 -1.669 34.777 -1.353 c
+34.513 -1.029 34.374 -0.559 34.366 0.058 c
+34.366 0.382 l
+34.366 1.007 34.499 1.484 34.763 1.808 c
+35.035 2.138 35.432 2.308 35.953 2.308 c
+36.383 2.308 36.726 2.167 36.982 1.896 c
+37.236 1.62 37.364 1.238 37.364 0.75 c
+36.394 0.75 l
+36.394 0.962 36.354 1.132 36.277 1.249 c
+36.207 1.374 36.09 1.44 35.924 1.44 c
+35.748 1.44 35.619 1.374 35.542 1.249 c
+35.461 1.12 35.417 0.871 35.409 0.5 c
+35.409 0.087 l
+35.409 -0.235 35.424 -0.463 35.454 -0.588 c
+35.49 -0.717 35.546 -0.809 35.615 -0.867 c
+35.693 -0.927 35.799 -0.956 35.939 -0.956 c
+39.172 3.204 m
+39.172 2.234 l
+39.702 2.234 l
+39.702 1.44 l
+39.172 1.44 l
+39.172 -0.53 l
+39.172 -0.688 39.191 -0.794 39.232 -0.853 c
+39.28 -0.912 39.363 -0.941 39.481 -0.941 c
+39.588 -0.941 39.673 -0.933 39.731 -0.912 c
+39.731 -1.72 l
+39.555 -1.786 39.363 -1.823 39.158 -1.823 c
+38.482 -1.823 38.137 -1.437 38.129 -0.661 c
+38.129 1.44 l
+37.674 1.44 l
+37.674 2.234 l
+38.129 2.234 l
+38.129 3.204 l
+h
+40.055 0.367 m
+40.055 0.974 40.194 1.448 40.481 1.793 c
+40.764 2.135 41.157 2.308 41.657 2.308 c
+42.164 2.308 42.561 2.135 42.848 1.793 c
+43.13 1.448 43.274 0.974 43.274 0.367 c
+43.274 0.103 l
+43.274 -0.497 43.13 -0.967 42.848 -1.309 c
+42.561 -1.654 42.164 -1.823 41.657 -1.823 c
+41.146 -1.823 40.749 -1.654 40.466 -1.309 c
+40.19 -0.967 40.055 -0.493 40.055 0.118 c
+h
+41.098 0.103 m
+41.098 -0.603 41.282 -0.956 41.657 -0.956 c
+42.01 -0.956 42.201 -0.661 42.23 -0.073 c
+42.23 0.367 l
+42.23 0.727 42.179 0.999 42.083 1.176 c
+41.984 1.352 41.84 1.44 41.657 1.44 c
+41.48 1.44 41.341 1.352 41.245 1.176 c
+41.146 0.999 41.098 0.727 41.098 0.367 c
+h
+45.875 1.22 m
+45.537 1.249 l
+45.251 1.249 45.06 1.124 44.965 0.881 c
+44.965 -1.75 l
+43.92 -1.75 l
+43.92 2.234 l
+44.89 2.234 l
+44.92 1.793 l
+45.085 2.135 45.317 2.308 45.611 2.308 c
+45.728 2.308 45.821 2.285 45.89 2.248 c
+h
+47.772 -0.015 m
+48.3 2.234 l
+49.403 2.234 l
+48.095 -2.352 l
+47.897 -3.017 47.529 -3.352 46.993 -3.352 c
+46.864 -3.352 46.721 -3.329 46.567 -3.293 c
+46.567 -2.469 l
+46.684 -2.484 l
+46.849 -2.484 46.97 -2.448 47.051 -2.382 c
+47.128 -2.323 47.191 -2.213 47.242 -2.058 c
+47.316 -1.794 l
+46.17 2.234 l
+47.286 2.234 l
+h
+f
+Q
+441.968 158.427 -0.646 3.984 re
+442.012 163.454 m
+442.012 163.344 441.983 163.252 441.924 163.175 c
+441.865 163.105 441.769 163.072 441.644 163.072 c
+441.527 163.072 441.432 163.105 441.366 163.175 c
+441.306 163.252 441.277 163.344 441.277 163.454 c
+441.277 163.572 441.306 163.664 441.366 163.734 c
+441.432 163.811 441.527 163.851 441.644 163.851 c
+441.769 163.851 441.865 163.811 441.924 163.734 c
+441.983 163.653 442.012 163.561 442.012 163.454 c
+444.923 159.441 m
+444.923 159.589 444.867 159.71 444.761 159.809 c
+444.651 159.905 444.445 160.023 444.144 160.162 c
+443.798 160.309 443.556 160.43 443.408 160.53 c
+443.261 160.636 443.151 160.754 443.085 160.882 c
+443.015 161.008 442.982 161.166 442.982 161.353 c
+442.982 161.675 443.099 161.945 443.335 162.161 c
+443.57 162.374 443.872 162.485 444.246 162.485 c
+444.628 162.485 444.937 162.371 445.172 162.146 c
+445.407 161.918 445.525 161.632 445.525 161.279 c
+444.878 161.279 l
+444.878 161.455 444.819 161.606 444.702 161.735 c
+444.584 161.86 444.43 161.926 444.246 161.926 c
+444.048 161.926 443.897 161.871 443.791 161.764 c
+443.68 161.665 443.629 161.532 443.629 161.367 c
+443.629 161.239 443.666 161.132 443.747 161.044 c
+443.824 160.963 444.015 160.86 444.32 160.735 c
+444.798 160.548 445.129 160.36 445.305 160.177 c
+445.481 160 445.569 159.772 445.569 159.5 c
+445.569 159.148 445.445 158.868 445.202 158.662 c
+444.967 158.457 444.651 158.354 444.261 158.354 c
+443.838 158.354 443.5 158.471 443.247 158.706 c
+442.989 158.949 442.864 159.254 442.864 159.618 c
+443.512 159.618 l
+443.519 159.39 443.589 159.214 443.718 159.088 c
+443.842 158.971 444.026 158.913 444.261 158.913 c
+444.474 158.913 444.636 158.961 444.746 159.059 c
+444.863 159.155 444.923 159.284 444.923 159.441 c
+448.744 162.411 m
+448.759 161.97 l
+449.012 162.311 449.336 162.485 449.729 162.485 c
+450.434 162.485 450.791 162.014 450.802 161.073 c
+450.802 158.427 l
+450.155 158.427 l
+450.155 161.044 l
+450.155 161.357 450.1 161.577 449.993 161.706 c
+449.883 161.831 449.729 161.897 449.523 161.897 c
+449.365 161.897 449.218 161.841 449.083 161.735 c
+448.954 161.625 448.851 161.488 448.774 161.323 c
+448.774 158.427 l
+448.127 158.427 l
+448.127 162.411 l
+h
+451.64 160.603 m
+451.64 161.18 451.776 161.636 452.052 161.97 c
+452.335 162.311 452.705 162.485 453.168 162.485 c
+453.628 162.485 453.995 162.315 454.271 161.985 c
+454.554 161.661 454.701 161.213 454.712 160.647 c
+454.712 160.221 l
+454.712 159.651 454.569 159.196 454.286 158.853 c
+454.01 158.519 453.642 158.354 453.183 158.354 c
+452.72 158.354 452.349 158.516 452.067 158.839 c
+451.791 159.169 451.647 159.611 451.64 160.162 c
+h
+452.287 160.221 m
+452.287 159.817 452.364 159.5 452.522 159.265 c
+452.687 159.03 452.908 158.913 453.183 158.913 c
+453.75 158.913 454.043 159.324 454.066 160.147 c
+454.066 160.603 l
+454.066 161.004 453.981 161.323 453.815 161.558 c
+453.657 161.801 453.441 161.926 453.168 161.926 c
+452.904 161.926 452.687 161.801 452.522 161.558 c
+452.364 161.323 452.287 161.004 452.287 160.603 c
+h
+458.519 159.574 m
+459.122 162.411 l
+459.768 162.411 l
+458.783 158.427 l
+458.269 158.427 l
+457.49 161.279 l
+456.74 158.427 l
+456.211 158.427 l
+455.256 162.411 l
+455.888 162.411 l
+456.505 159.647 l
+457.241 162.411 l
+457.754 162.411 l
+h
+f
+0.69 w
+288.095 207.441 207.848 -54.945 re
+S
+0.793 0.801 0.129 0.016 K
+0.799 w
+q 1 0 0 1 563.3749 119.0558 cm
+0 0 m
+26.08 -0.095 26.08 27.113 48.253 27.098 c
+133.768 27.098 l
+155.865 27.113 155.865 -0.095 181.335 0 c
+S
+Q
+q 1 0 0 1 312.2897 119.0558 cm
+0 0 m
+458.551 0 l
+S
+Q
+0 0 0 0 k
+q 1 0 0 1 541.4877 119.0558 cm
+0 0 m
+0 -2.076 -1.679 -3.755 -3.755 -3.755 c
+-5.828 -3.755 -7.511 -2.076 -7.511 0 c
+-7.511 2.076 -5.828 3.755 -3.755 3.755 c
+-1.679 3.755 0 2.076 0 0 c
+f
+Q
+0.797 0.801 0.129 0.016 K
+0.709 w
+q 1 0 0 1 541.4877 119.0558 cm
+0 0 m
+0 -2.076 -1.679 -3.755 -3.755 -3.755 c
+-5.828 -3.755 -7.511 -2.076 -7.511 0 c
+-7.511 2.076 -5.828 3.755 -3.755 3.755 c
+-1.679 3.755 0 2.076 0 0 c
+h
+S
+Q
+q 1 0 0 1 567.4135 119.0558 cm
+0 0 m
+0 -2.076 -1.683 -3.755 -3.755 -3.755 c
+-5.832 -3.755 -7.515 -2.076 -7.515 0 c
+-7.515 2.076 -5.832 3.755 -3.755 3.755 c
+-1.683 3.755 0 2.076 0 0 c
+f
+Q
+q 1 0 0 1 567.4135 119.0558 cm
+0 0 m
+0 -2.076 -1.683 -3.755 -3.755 -3.755 c
+-5.832 -3.755 -7.515 -2.076 -7.515 0 c
+-7.515 2.076 -5.832 3.755 -3.755 3.755 c
+-1.683 3.755 0 2.076 0 0 c
+h
+S
+Q
+q 1 0 0 1 593.3356 119.0558 cm
+0 0 m
+0 -2.076 -1.684 -3.755 -3.756 -3.755 c
+-5.833 -3.755 -7.512 -2.076 -7.512 0 c
+-7.512 2.076 -5.833 3.755 -3.756 3.755 c
+-1.684 3.755 0 2.076 0 0 c
+f
+Q
+q 1 0 0 1 593.3356 119.0558 cm
+0 0 m
+0 -2.076 -1.684 -3.755 -3.756 -3.755 c
+-5.833 -3.755 -7.512 -2.076 -7.512 0 c
+-7.512 2.076 -5.833 3.755 -3.756 3.755 c
+-1.684 3.755 0 2.076 0 0 c
+h
+S
+Q
+q 1 0 0 1 619.2567 119.0558 cm
+0 0 m
+0 -2.076 -1.679 -3.755 -3.755 -3.755 c
+-5.832 -3.755 -7.511 -2.076 -7.511 0 c
+-7.511 2.076 -5.832 3.755 -3.755 3.755 c
+-1.679 3.755 0 2.076 0 0 c
+f
+Q
+q 1 0 0 1 619.2567 119.0558 cm
+0 0 m
+0 -2.076 -1.679 -3.755 -3.755 -3.755 c
+-5.832 -3.755 -7.511 -2.076 -7.511 0 c
+-7.511 2.076 -5.832 3.755 -3.755 3.755 c
+-1.679 3.755 0 2.076 0 0 c
+h
+S
+Q
+q 1 0 0 1 645.1788 119.0558 cm
+0 0 m
+0 -2.076 -1.679 -3.755 -3.755 -3.755 c
+-5.828 -3.755 -7.511 -2.076 -7.511 0 c
+-7.511 2.076 -5.828 3.755 -3.755 3.755 c
+-1.679 3.755 0 2.076 0 0 c
+f
+Q
+q 1 0 0 1 645.1788 119.0558 cm
+0 0 m
+0 -2.076 -1.679 -3.755 -3.755 -3.755 c
+-5.828 -3.755 -7.511 -2.076 -7.511 0 c
+-7.511 2.076 -5.828 3.755 -3.755 3.755 c
+-1.679 3.755 0 2.076 0 0 c
+h
+S
+Q
+q 1 0 0 1 671.1036 119.0558 cm
+0 0 m
+0 -2.076 -1.683 -3.755 -3.759 -3.755 c
+-5.832 -3.755 -7.515 -2.076 -7.515 0 c
+-7.515 2.076 -5.832 3.755 -3.759 3.755 c
+-1.683 3.755 0 2.076 0 0 c
+f
+Q
+q 1 0 0 1 671.1036 119.0558 cm
+0 0 m
+0 -2.076 -1.683 -3.755 -3.759 -3.755 c
+-5.832 -3.755 -7.515 -2.076 -7.515 0 c
+-7.515 2.076 -5.832 3.755 -3.759 3.755 c
+-1.683 3.755 0 2.076 0 0 c
+h
+S
+Q
+q 1 0 0 1 697.0258 119.0558 cm
+0 0 m
+0 -2.076 -1.683 -3.755 -3.755 -3.755 c
+-5.832 -3.755 -7.515 -2.076 -7.515 0 c
+-7.515 2.076 -5.832 3.755 -3.755 3.755 c
+-1.683 3.755 0 2.076 0 0 c
+f
+Q
+q 1 0 0 1 697.0258 119.0558 cm
+0 0 m
+0 -2.076 -1.683 -3.755 -3.755 -3.755 c
+-5.832 -3.755 -7.515 -2.076 -7.515 0 c
+-7.515 2.076 -5.832 3.755 -3.755 3.755 c
+-1.683 3.755 0 2.076 0 0 c
+h
+S
+Q
+q 1 0 0 1 722.9478 119.0558 cm
+0 0 m
+0 -2.076 -1.683 -3.755 -3.755 -3.755 c
+-5.832 -3.755 -7.511 -2.076 -7.511 0 c
+-7.511 2.076 -5.832 3.755 -3.755 3.755 c
+-1.683 3.755 0 2.076 0 0 c
+f
+Q
+q 1 0 0 1 722.9478 119.0558 cm
+0 0 m
+0 -2.076 -1.683 -3.755 -3.755 -3.755 c
+-5.832 -3.755 -7.511 -2.076 -7.511 0 c
+-7.511 2.076 -5.832 3.755 -3.755 3.755 c
+-1.683 3.755 0 2.076 0 0 c
+h
+S
+Q
+q 1 0 0 1 774.7947 119.0558 cm
+0 0 m
+0 -2.076 -1.683 -3.755 -3.759 -3.755 c
+-5.832 -3.755 -7.515 -2.076 -7.515 0 c
+-7.515 2.076 -5.832 3.755 -3.759 3.755 c
+-1.683 3.755 0 2.076 0 0 c
+f
+Q
+q 1 0 0 1 774.7947 119.0558 cm
+0 0 m
+0 -2.076 -1.683 -3.755 -3.759 -3.755 c
+-5.832 -3.755 -7.515 -2.076 -7.515 0 c
+-7.515 2.076 -5.832 3.755 -3.759 3.755 c
+-1.683 3.755 0 2.076 0 0 c
+h
+S
+Q
+q 1 0 0 1 748.8699 119.0558 cm
+0 0 m
+0 -2.076 -1.68 -3.755 -3.756 -3.755 c
+-5.829 -3.755 -7.512 -2.076 -7.512 0 c
+-7.512 2.076 -5.829 3.755 -3.756 3.755 c
+-1.68 3.755 0 2.076 0 0 c
+f
+Q
+q 1 0 0 1 748.8699 119.0558 cm
+0 0 m
+0 -2.076 -1.68 -3.755 -3.756 -3.755 c
+-5.829 -3.755 -7.512 -2.076 -7.512 0 c
+-7.512 2.076 -5.829 3.755 -3.756 3.755 c
+-1.68 3.755 0 2.076 0 0 c
+h
+S
+Q
+q 1 0 0 1 619.2567 146.1501 cm
+0 0 m
+0 -2.076 -1.679 -3.755 -3.755 -3.755 c
+-5.832 -3.755 -7.511 -2.076 -7.511 0 c
+-7.511 2.072 -5.832 3.755 -3.755 3.755 c
+-1.679 3.755 0 2.072 0 0 c
+f
+Q
+q 1 0 0 1 619.2567 146.1501 cm
+0 0 m
+0 -2.076 -1.679 -3.755 -3.755 -3.755 c
+-5.832 -3.755 -7.511 -2.076 -7.511 0 c
+-7.511 2.072 -5.832 3.755 -3.755 3.755 c
+-1.679 3.755 0 2.072 0 0 c
+h
+S
+Q
+q 1 0 0 1 645.1788 146.1501 cm
+0 0 m
+0 -2.076 -1.679 -3.755 -3.755 -3.755 c
+-5.828 -3.755 -7.511 -2.076 -7.511 0 c
+-7.511 2.072 -5.828 3.755 -3.755 3.755 c
+-1.679 3.755 0 2.072 0 0 c
+f
+Q
+q 1 0 0 1 645.1788 146.1501 cm
+0 0 m
+0 -2.076 -1.679 -3.755 -3.755 -3.755 c
+-5.828 -3.755 -7.511 -2.076 -7.511 0 c
+-7.511 2.072 -5.828 3.755 -3.755 3.755 c
+-1.679 3.755 0 2.072 0 0 c
+h
+S
+Q
+q 1 0 0 1 671.1036 146.1501 cm
+0 0 m
+0 -2.076 -1.683 -3.755 -3.759 -3.755 c
+-5.832 -3.755 -7.515 -2.076 -7.515 0 c
+-7.515 2.072 -5.832 3.755 -3.759 3.755 c
+-1.683 3.755 0 2.072 0 0 c
+f
+Q
+q 1 0 0 1 671.1036 146.1501 cm
+0 0 m
+0 -2.076 -1.683 -3.755 -3.759 -3.755 c
+-5.832 -3.755 -7.515 -2.076 -7.515 0 c
+-7.515 2.072 -5.832 3.755 -3.759 3.755 c
+-1.683 3.755 0 2.072 0 0 c
+h
+S
+Q
+q 1 0 0 1 697.0258 146.1501 cm
+0 0 m
+0 -2.076 -1.683 -3.755 -3.755 -3.755 c
+-5.832 -3.755 -7.515 -2.076 -7.515 0 c
+-7.515 2.072 -5.832 3.755 -3.755 3.755 c
+-1.683 3.755 0 2.072 0 0 c
+f
+Q
+q 1 0 0 1 697.0258 146.1501 cm
+0 0 m
+0 -2.076 -1.683 -3.755 -3.755 -3.755 c
+-5.832 -3.755 -7.515 -2.076 -7.515 0 c
+-7.515 2.072 -5.832 3.755 -3.755 3.755 c
+-1.683 3.755 0 2.072 0 0 c
+h
+S
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 689.9702 155.2305 cm
+0 0 m
+-0.008 12.072 l
+6.46 12.072 l
+6.468 0 l
+3.227 -3.561 l
+h
+f
+Q
+0 0 0 0 k
+q 1 0 0 1 691.3192 165.4168 cm
+0 0 m
+2.396 0 l
+2.396 0.368 l
+2.984 0.368 l
+2.984 0 l
+3.116 0 l
+3.487 0 3.777 -0.096 3.983 -0.294 c
+4.189 -0.5 4.292 -0.794 4.292 -1.176 c
+4.292 -1.382 4.237 -1.639 4.13 -1.955 c
+3.468 -1.852 l
+3.546 -1.625 3.586 -1.415 3.586 -1.22 c
+3.586 -0.933 3.428 -0.786 3.116 -0.779 c
+2.984 -0.779 l
+2.984 -1.249 l
+2.396 -1.249 l
+2.396 -0.779 l
+0 -0.779 l
+h
+0 -1.529 2.984 -0.794 re
+0 -2.323 m
+2.102 -3.719 m
+2.984 -4.072 l
+2.984 -4.895 l
+1.529 -4.218 l
+0 -4.924 l
+0 -4.087 l
+0.941 -3.719 l
+0 -3.366 l
+0 -2.528 l
+1.529 -3.233 l
+2.984 -2.558 l
+2.984 -3.395 l
+h
+-0.339 -5.398 m
+-0.339 -4.825 l
+4.012 -6.03 l
+4.012 -6.603 l
+h
+0 -8.279 m
+0.048 -8.249 0.125 -8.224 0.235 -8.206 c
+0.037 -8.066 -0.059 -7.882 -0.059 -7.647 c
+-0.059 -7.39 0.022 -7.181 0.191 -7.015 c
+0.357 -6.857 0.573 -6.78 0.837 -6.78 c
+1.15 -6.78 1.388 -6.876 1.558 -7.073 c
+1.735 -7.269 1.822 -7.551 1.822 -7.927 c
+1.822 -8.176 l
+2.057 -8.176 l
+2.194 -8.176 2.285 -8.151 2.337 -8.103 c
+2.396 -8.052 2.425 -7.985 2.425 -7.897 c
+2.425 -7.699 2.311 -7.603 2.088 -7.603 c
+2.088 -6.824 l
+2.359 -6.824 2.587 -6.927 2.763 -7.133 c
+2.947 -7.339 3.042 -7.603 3.042 -7.927 c
+3.042 -8.249 2.954 -8.5 2.778 -8.676 c
+2.609 -8.86 2.37 -8.955 2.057 -8.955 c
+0.646 -8.955 l
+0.389 -8.955 0.191 -8.989 0.044 -9.058 c
+0 -9.058 l
+h
+0.559 -7.809 m
+0.559 -7.897 0.573 -7.971 0.602 -8.029 c
+0.639 -8.095 0.683 -8.147 0.735 -8.176 c
+1.352 -8.176 l
+1.352 -7.985 l
+1.352 -7.846 1.308 -7.739 1.22 -7.661 c
+1.139 -7.592 1.029 -7.559 0.881 -7.559 c
+0.665 -7.559 0.559 -7.64 0.559 -7.809 c
+f
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 612.076 155.9689 cm
+0 0 m
+-0.007 25.419 l
+6.465 25.419 l
+6.468 0 l
+3.227 -3.561 l
+h
+f
+Q
+0 0 0 0 k
+q 1 0 0 1 615.2952 179.954 cm
+0 0 m
+0.449 0 0.802 -0.106 1.058 -0.324 c
+1.324 -0.536 1.455 -0.831 1.455 -1.205 c
+1.455 -1.587 1.324 -1.881 1.058 -2.087 c
+0.802 -2.3 0.449 -2.41 0 -2.41 c
+-0.191 -2.41 l
+-0.654 -2.41 -1.01 -2.3 -1.263 -2.087 c
+-1.521 -1.881 -1.646 -1.587 -1.646 -1.205 c
+-1.646 -0.823 -1.521 -0.522 -1.263 -0.309 c
+-0.999 -0.103 -0.643 0 -0.191 0 c
+h
+-0.191 -0.779 m
+-0.731 -0.779 -0.999 -0.918 -0.999 -1.205 c
+-0.999 -1.469 -0.775 -1.61 -0.323 -1.631 c
+0 -1.646 l
+0.272 -1.646 0.474 -1.606 0.603 -1.529 c
+0.739 -1.448 0.809 -1.341 0.809 -1.205 c
+0.809 -1.076 0.739 -0.974 0.603 -0.897 c
+0.474 -0.816 0.272 -0.779 0 -0.779 c
+h
+0.647 -4.182 m
+0.661 -3.932 l
+0.661 -3.715 0.566 -3.568 0.383 -3.491 c
+-1.587 -3.491 l
+-1.587 -2.712 l
+1.397 -2.712 l
+1.397 -3.447 l
+1.073 -3.476 l
+1.326 -3.594 1.455 -3.759 1.455 -3.976 c
+1.455 -4.064 1.441 -4.137 1.411 -4.197 c
+h
+-1.587 -4.505 2.984 -0.779 re
+-1.587 -5.284 m
+2.161 -4.461 m
+2.286 -4.461 2.389 -4.498 2.469 -4.579 c
+2.547 -4.656 2.587 -4.758 2.587 -4.887 c
+2.587 -5.012 2.547 -5.115 2.469 -5.196 c
+2.389 -5.273 2.286 -5.313 2.161 -5.313 c
+2.043 -5.313 1.945 -5.273 1.867 -5.196 c
+1.786 -5.126 1.75 -5.024 1.75 -4.887 c
+1.75 -4.758 1.786 -4.656 1.867 -4.579 c
+1.945 -4.498 2.043 -4.461 2.161 -4.461 c
+0 -5.699 m
+0.489 -5.699 0.853 -5.787 1.088 -5.964 c
+1.33 -6.14 1.455 -6.383 1.455 -6.699 c
+1.455 -6.971 1.345 -7.184 1.132 -7.331 c
+1.397 -7.36 l
+1.397 -8.066 l
+-1.587 -8.066 l
+-1.969 -8.066 -2.256 -7.956 -2.454 -7.742 c
+-2.66 -7.526 -2.763 -7.221 -2.763 -6.832 c
+-2.763 -6.662 -2.726 -6.485 -2.66 -6.302 c
+-2.601 -6.126 -2.517 -5.993 -2.41 -5.905 c
+-1.881 -6.169 l
+-1.947 -6.247 -2.007 -6.346 -2.057 -6.464 c
+-2.105 -6.581 -2.131 -6.688 -2.131 -6.787 c
+-2.131 -6.963 -2.087 -7.088 -1.999 -7.169 c
+-1.918 -7.247 -1.785 -7.287 -1.602 -7.287 c
+-1.352 -7.287 l
+-1.55 -7.14 -1.646 -6.942 -1.646 -6.699 c
+-1.646 -6.383 -1.525 -6.14 -1.278 -5.964 c
+-1.025 -5.787 -0.673 -5.699 -0.22 -5.699 c
+h
+-0.205 -6.479 m
+-0.481 -6.479 -0.683 -6.512 -0.808 -6.581 c
+-0.926 -6.659 -0.985 -6.776 -0.985 -6.934 c
+-0.985 -7.088 -0.933 -7.206 -0.823 -7.287 c
+0.603 -7.287 l
+0.728 -7.206 0.794 -7.088 0.794 -6.934 c
+0.794 -6.776 0.728 -6.659 0.603 -6.581 c
+0.474 -6.512 0.272 -6.479 0 -6.479 c
+h
+-1.587 -8.488 2.984 -0.779 re
+-1.587 -9.267 m
+2.161 -8.444 m
+2.286 -8.444 2.389 -8.481 2.469 -8.562 c
+2.547 -8.639 2.587 -8.742 2.587 -8.871 c
+2.587 -8.995 2.547 -9.099 2.469 -9.18 c
+2.389 -9.257 2.286 -9.297 2.161 -9.297 c
+2.043 -9.297 1.945 -9.257 1.867 -9.18 c
+1.786 -9.109 1.75 -9.007 1.75 -8.871 c
+1.75 -8.742 1.786 -8.639 1.867 -8.562 c
+1.945 -8.481 2.043 -8.444 2.161 -8.444 c
+1.397 -10.491 m
+1.103 -10.506 l
+1.338 -10.682 1.455 -10.91 1.455 -11.197 c
+1.455 -11.715 1.091 -11.979 0.368 -11.991 c
+-1.587 -11.991 l
+-1.587 -11.212 l
+0.309 -11.212 l
+0.485 -11.212 0.607 -11.185 0.676 -11.138 c
+0.754 -11.087 0.794 -10.998 0.794 -10.873 c
+0.794 -10.726 0.721 -10.612 0.574 -10.535 c
+-1.587 -10.535 l
+-1.587 -9.756 l
+1.397 -9.756 l
+h
+-1.926 -12.66 m
+-1.926 -12.086 l
+2.425 -13.292 l
+2.425 -13.865 l
+h
+-1.587 -14.277 m
+0.809 -14.277 l
+0.809 -13.909 l
+1.397 -13.909 l
+1.397 -14.277 l
+1.529 -14.277 l
+1.9 -14.277 2.19 -14.372 2.396 -14.57 c
+2.602 -14.776 2.705 -15.07 2.705 -15.453 c
+2.705 -15.658 2.65 -15.915 2.543 -16.232 c
+1.881 -16.128 l
+1.959 -15.9 1.999 -15.692 1.999 -15.496 c
+1.999 -15.21 1.841 -15.063 1.529 -15.056 c
+1.397 -15.056 l
+1.397 -15.526 l
+0.809 -15.526 l
+0.809 -15.056 l
+-1.587 -15.056 l
+h
+-1.587 -15.805 2.984 -0.793 re
+-1.587 -16.598 m
+0.515 -17.995 m
+1.397 -18.348 l
+1.397 -19.171 l
+-0.058 -18.495 l
+-1.587 -19.201 l
+-1.587 -18.362 l
+-0.646 -17.995 l
+-1.587 -17.643 l
+-1.587 -16.804 l
+-0.058 -17.51 l
+1.397 -16.834 l
+1.397 -17.672 l
+h
+-1.926 -19.675 m
+-1.926 -19.102 l
+2.425 -20.307 l
+2.425 -20.88 l
+h
+-1.587 -22.555 m
+-1.539 -22.526 -1.462 -22.501 -1.352 -22.482 c
+-1.55 -22.343 -1.646 -22.159 -1.646 -21.924 c
+-1.646 -21.666 -1.565 -21.456 -1.396 -21.292 c
+-1.23 -21.134 -1.014 -21.057 -0.75 -21.057 c
+-0.437 -21.057 -0.198 -21.152 -0.029 -21.35 c
+0.148 -21.545 0.235 -21.828 0.235 -22.202 c
+0.235 -22.453 l
+0.47 -22.453 l
+0.607 -22.453 0.698 -22.427 0.75 -22.379 c
+0.809 -22.327 0.838 -22.262 0.838 -22.173 c
+0.838 -21.975 0.724 -21.88 0.5 -21.88 c
+0.5 -21.101 l
+0.772 -21.101 1 -21.203 1.176 -21.409 c
+1.36 -21.614 1.455 -21.88 1.455 -22.202 c
+1.455 -22.526 1.367 -22.776 1.191 -22.952 c
+1.022 -23.137 0.783 -23.232 0.47 -23.232 c
+-0.941 -23.232 l
+-1.198 -23.232 -1.396 -23.264 -1.543 -23.335 c
+-1.587 -23.335 l
+h
+-1.028 -22.085 m
+-1.028 -22.173 -1.014 -22.247 -0.985 -22.306 c
+-0.948 -22.372 -0.904 -22.423 -0.852 -22.453 c
+-0.235 -22.453 l
+-0.235 -22.262 l
+-0.235 -22.121 -0.279 -22.015 -0.367 -21.938 c
+-0.448 -21.868 -0.558 -21.835 -0.706 -21.835 c
+-0.922 -21.835 -1.028 -21.916 -1.028 -22.085 c
+f
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 548.514 156.6265 cm
+0 0 m
+-1.058 0 l
+-1.058 -3.572 l
+-1.558 -3.572 l
+-1.558 0 l
+-2.616 0 l
+-2.616 0.441 l
+0 0.441 l
+h
+0.823 -0.897 m
+1.007 -0.654 1.242 -0.529 1.529 -0.529 c
+2.058 -0.529 2.326 -0.881 2.337 -1.587 c
+2.337 -3.572 l
+1.852 -3.572 l
+1.852 -1.616 l
+1.852 -1.381 1.812 -1.216 1.735 -1.117 c
+1.654 -1.022 1.536 -0.97 1.382 -0.97 c
+1.264 -0.97 1.154 -1.01 1.058 -1.087 c
+0.96 -1.168 0.882 -1.275 0.823 -1.411 c
+0.823 -3.572 l
+0.338 -3.572 l
+0.338 0.661 l
+0.823 0.661 l
+h
+3.406 -3.572 -0.499 2.984 re
+3.436 0.206 m
+3.436 0.118 3.41 0.044 3.362 -0.014 c
+3.322 -0.066 3.252 -0.087 3.156 -0.087 c
+3.069 -0.087 2.999 -0.066 2.951 -0.014 c
+2.911 0.044 2.892 0.11 2.892 0.191 c
+2.892 0.279 2.911 0.353 2.951 0.412 c
+2.999 0.47 3.069 0.5 3.156 0.5 c
+3.252 0.5 3.322 0.47 3.362 0.412 c
+3.41 0.353 3.436 0.283 3.436 0.206 c
+5.523 -2.807 m
+5.523 -2.701 5.483 -2.612 5.405 -2.543 c
+5.325 -2.466 5.174 -2.377 4.95 -2.278 c
+4.685 -2.171 4.498 -2.08 4.391 -1.999 c
+4.281 -1.922 4.204 -1.833 4.156 -1.734 c
+4.104 -1.639 4.083 -1.521 4.083 -1.381 c
+4.083 -1.139 4.171 -0.937 4.347 -0.779 c
+4.524 -0.613 4.748 -0.529 5.024 -0.529 c
+5.317 -0.529 5.552 -0.617 5.729 -0.793 c
+5.905 -0.962 5.993 -1.176 5.993 -1.44 c
+5.508 -1.44 l
+5.508 -1.304 5.457 -1.19 5.361 -1.103 c
+5.273 -1.007 5.159 -0.955 5.024 -0.955 c
+4.877 -0.955 4.762 -0.995 4.685 -1.072 c
+4.605 -1.143 4.567 -1.242 4.567 -1.367 c
+4.567 -1.466 4.597 -1.543 4.656 -1.602 c
+4.715 -1.66 4.854 -1.741 5.082 -1.837 c
+5.442 -1.984 5.689 -2.127 5.818 -2.263 c
+5.953 -2.392 6.023 -2.564 6.023 -2.778 c
+6.023 -3.035 5.928 -3.241 5.743 -3.395 c
+5.567 -3.553 5.332 -3.63 5.038 -3.63 c
+4.723 -3.63 4.469 -3.542 4.274 -3.366 c
+4.087 -3.183 3.994 -2.95 3.994 -2.675 c
+4.48 -2.675 l
+4.487 -2.844 4.538 -2.977 4.627 -3.072 c
+4.723 -3.16 4.862 -3.204 5.038 -3.204 c
+5.193 -3.204 5.31 -3.171 5.39 -3.102 c
+5.479 -3.035 5.523 -2.936 5.523 -2.807 c
+8.213 -3.572 -0.5 2.984 re
+8.243 0.206 m
+8.243 0.118 8.216 0.044 8.169 -0.014 c
+8.129 -0.066 8.058 -0.087 7.963 -0.087 c
+7.875 -0.087 7.805 -0.066 7.757 -0.014 c
+7.717 0.044 7.699 0.11 7.699 0.191 c
+7.699 0.279 7.717 0.353 7.757 0.412 c
+7.805 0.47 7.875 0.5 7.963 0.5 c
+8.058 0.5 8.129 0.47 8.169 0.412 c
+8.216 0.353 8.243 0.283 8.243 0.206 c
+10.329 -2.807 m
+10.329 -2.701 10.29 -2.612 10.212 -2.543 c
+10.132 -2.466 9.98 -2.377 9.756 -2.278 c
+9.492 -2.171 9.305 -2.08 9.198 -1.999 c
+9.088 -1.922 9.01 -1.833 8.962 -1.734 c
+8.912 -1.639 8.889 -1.521 8.889 -1.381 c
+8.889 -1.139 8.977 -0.937 9.153 -0.779 c
+9.33 -0.613 9.554 -0.529 9.83 -0.529 c
+10.124 -0.529 10.359 -0.617 10.535 -0.793 c
+10.712 -0.962 10.8 -1.176 10.8 -1.44 c
+10.315 -1.44 l
+10.315 -1.304 10.263 -1.19 10.168 -1.103 c
+10.08 -1.007 9.966 -0.955 9.83 -0.955 c
+9.683 -0.955 9.569 -0.995 9.492 -1.072 c
+9.411 -1.143 9.375 -1.242 9.375 -1.367 c
+9.375 -1.466 9.404 -1.543 9.463 -1.602 c
+9.521 -1.66 9.661 -1.741 9.889 -1.837 c
+10.249 -1.984 10.495 -2.127 10.624 -2.263 c
+10.76 -2.392 10.83 -2.564 10.83 -2.778 c
+10.83 -3.035 10.734 -3.241 10.55 -3.395 c
+10.373 -3.553 10.138 -3.63 9.845 -3.63 c
+9.529 -3.63 9.275 -3.542 9.08 -3.366 c
+8.893 -3.183 8.801 -2.95 8.801 -2.675 c
+9.286 -2.675 l
+9.294 -2.844 9.345 -2.977 9.433 -3.072 c
+9.529 -3.16 9.668 -3.204 9.845 -3.204 c
+9.999 -3.204 10.117 -3.171 10.198 -3.102 c
+10.286 -3.035 10.329 -2.936 10.329 -2.807 c
+14.019 -3.572 m
+13.99 -3.505 13.968 -3.395 13.961 -3.248 c
+13.784 -3.505 13.564 -3.63 13.299 -3.63 c
+13.024 -3.63 12.806 -3.557 12.652 -3.41 c
+12.505 -3.256 12.432 -3.039 12.432 -2.763 c
+12.432 -2.462 12.534 -2.219 12.74 -2.043 c
+12.946 -1.859 13.229 -1.764 13.593 -1.764 c
+13.945 -1.764 l
+13.945 -1.44 l
+13.945 -1.263 13.905 -1.143 13.828 -1.072 c
+13.747 -0.995 13.629 -0.955 13.475 -0.955 c
+13.328 -0.955 13.203 -0.999 13.108 -1.087 c
+13.02 -1.176 12.976 -1.286 12.976 -1.411 c
+12.49 -1.411 l
+12.49 -1.263 12.534 -1.124 12.623 -0.985 c
+12.711 -0.837 12.829 -0.727 12.976 -0.646 c
+13.13 -0.569 13.303 -0.529 13.49 -0.529 c
+13.802 -0.529 14.038 -0.61 14.196 -0.764 c
+14.35 -0.911 14.431 -1.132 14.431 -1.425 c
+14.431 -2.925 l
+14.438 -3.16 14.475 -3.362 14.533 -3.528 c
+14.533 -3.572 l
+h
+13.373 -3.189 m
+13.49 -3.189 13.6 -3.156 13.71 -3.087 c
+13.818 -3.021 13.895 -2.936 13.945 -2.836 c
+13.945 -2.131 l
+13.681 -2.131 l
+13.446 -2.131 13.259 -2.183 13.122 -2.278 c
+12.993 -2.377 12.931 -2.52 12.931 -2.705 c
+12.931 -2.873 12.961 -2.994 13.02 -3.072 c
+13.086 -3.152 13.203 -3.189 13.373 -3.189 c
+15.467 -0.588 m
+15.482 -0.911 l
+15.665 -0.658 15.908 -0.529 16.202 -0.529 c
+16.731 -0.529 16.999 -0.881 17.01 -1.587 c
+17.01 -3.572 l
+16.525 -3.572 l
+16.525 -1.616 l
+16.525 -1.381 16.485 -1.216 16.407 -1.117 c
+16.326 -1.022 16.209 -0.97 16.055 -0.97 c
+15.937 -0.97 15.827 -1.01 15.732 -1.087 c
+15.632 -1.168 15.555 -1.275 15.497 -1.411 c
+15.497 -3.572 l
+15.011 -3.572 l
+15.011 -0.588 l
+h
+20.281 -3.307 m
+20.123 -3.524 19.888 -3.63 19.576 -3.63 c
+19.311 -3.63 19.105 -3.538 18.958 -3.351 c
+18.819 -3.167 18.753 -2.892 18.753 -2.528 c
+18.753 -0.588 l
+19.237 -0.588 l
+19.237 -2.499 l
+19.237 -2.961 19.377 -3.189 19.663 -3.189 c
+19.958 -3.189 20.156 -3.057 20.266 -2.792 c
+20.266 -0.588 l
+20.766 -0.588 l
+20.766 -3.572 l
+20.295 -3.572 l
+h
+23.463 -2.219 m
+23.463 -2.69 23.379 -3.042 23.214 -3.278 c
+23.044 -3.513 22.805 -3.63 22.493 -3.63 c
+22.188 -3.63 21.957 -3.52 21.803 -3.293 c
+21.803 -4.718 l
+21.317 -4.718 l
+21.317 -0.588 l
+21.758 -0.588 l
+21.787 -0.926 l
+21.942 -0.661 22.173 -0.529 22.479 -0.529 c
+22.809 -0.529 23.056 -0.646 23.214 -0.881 c
+23.379 -1.109 23.463 -1.448 23.463 -1.896 c
+h
+22.979 -1.94 m
+22.979 -1.61 22.923 -1.363 22.817 -1.205 c
+22.717 -1.051 22.556 -0.97 22.331 -0.97 c
+22.096 -0.97 21.92 -1.087 21.803 -1.323 c
+21.803 -2.866 l
+21.92 -3.094 22.1 -3.204 22.346 -3.204 c
+22.559 -3.204 22.717 -3.127 22.817 -2.969 c
+22.923 -2.815 22.979 -2.572 22.979 -2.248 c
+h
+25.359 -2.807 m
+25.359 -2.701 25.319 -2.612 25.242 -2.543 c
+25.161 -2.466 25.01 -2.377 24.787 -2.278 c
+24.521 -2.171 24.334 -2.08 24.228 -1.999 c
+24.118 -1.922 24.041 -1.833 23.993 -1.734 c
+23.941 -1.639 23.919 -1.521 23.919 -1.381 c
+23.919 -1.139 24.008 -0.937 24.184 -0.779 c
+24.36 -0.613 24.584 -0.529 24.86 -0.529 c
+25.153 -0.529 25.389 -0.617 25.566 -0.793 c
+25.741 -0.962 25.83 -1.176 25.83 -1.44 c
+25.344 -1.44 l
+25.344 -1.304 25.294 -1.19 25.198 -1.103 c
+25.109 -1.007 24.995 -0.955 24.86 -0.955 c
+24.713 -0.955 24.598 -0.995 24.521 -1.072 c
+24.44 -1.143 24.404 -1.242 24.404 -1.367 c
+24.404 -1.466 24.434 -1.543 24.492 -1.602 c
+24.551 -1.66 24.691 -1.741 24.918 -1.837 c
+25.279 -1.984 25.525 -2.127 25.654 -2.263 c
+25.789 -2.392 25.859 -2.564 25.859 -2.778 c
+25.859 -3.035 25.764 -3.241 25.58 -3.395 c
+25.404 -3.553 25.169 -3.63 24.874 -3.63 c
+24.558 -3.63 24.305 -3.542 24.11 -3.366 c
+23.923 -3.183 23.831 -2.95 23.831 -2.675 c
+24.316 -2.675 l
+24.323 -2.844 24.375 -2.977 24.463 -3.072 c
+24.558 -3.16 24.698 -3.204 24.874 -3.204 c
+25.028 -3.204 25.146 -3.171 25.227 -3.102 c
+25.315 -3.035 25.359 -2.936 25.359 -2.807 c
+26.95 0.133 m
+26.95 -0.588 l
+27.407 -0.588 l
+27.407 -0.985 l
+26.95 -0.985 l
+26.95 -2.836 l
+26.95 -2.954 26.969 -3.042 27.01 -3.102 c
+27.046 -3.16 27.116 -3.189 27.216 -3.189 c
+27.274 -3.189 27.337 -3.183 27.407 -3.16 c
+27.407 -3.572 l
+27.289 -3.609 27.175 -3.63 27.068 -3.63 c
+26.869 -3.63 26.719 -3.564 26.613 -3.424 c
+26.514 -3.289 26.466 -3.094 26.466 -2.836 c
+26.466 -0.985 l
+26.01 -0.985 l
+26.01 -0.588 l
+26.466 -0.588 l
+26.466 0.133 l
+h
+29.107 -1.043 m
+29.038 -1.036 28.964 -1.028 28.887 -1.028 c
+28.63 -1.028 28.454 -1.168 28.359 -1.44 c
+28.359 -3.572 l
+27.873 -3.572 l
+27.873 -0.588 l
+28.344 -0.588 l
+28.359 -0.897 l
+28.483 -0.654 28.667 -0.529 28.902 -0.529 c
+28.979 -0.529 29.042 -0.544 29.093 -0.573 c
+h
+30.482 -3.63 m
+30.107 -3.63 29.824 -3.524 29.63 -3.307 c
+29.431 -3.083 29.336 -2.755 29.336 -2.322 c
+29.336 -1.955 l
+29.336 -1.514 29.427 -1.168 29.614 -0.911 c
+29.81 -0.658 30.085 -0.529 30.438 -0.529 c
+30.78 -0.529 31.033 -0.643 31.202 -0.867 c
+31.378 -1.095 31.471 -1.44 31.482 -1.911 c
+31.482 -2.219 l
+29.82 -2.219 l
+29.82 -2.293 l
+29.82 -2.616 29.88 -2.851 29.997 -2.998 c
+30.115 -3.138 30.283 -3.204 30.512 -3.204 c
+30.659 -3.204 30.784 -3.183 30.894 -3.131 c
+31 -3.072 31.103 -2.984 31.202 -2.866 c
+31.453 -3.175 l
+31.247 -3.48 30.923 -3.63 30.482 -3.63 c
+30.438 -0.955 m
+30.233 -0.955 30.078 -1.025 29.982 -1.161 c
+29.883 -1.301 29.828 -1.514 29.82 -1.808 c
+30.996 -1.808 l
+30.996 -1.734 l
+30.975 -1.462 30.923 -1.263 30.835 -1.146 c
+30.747 -1.022 30.615 -0.955 30.438 -0.955 c
+33.422 -3.572 m
+33.392 -3.505 33.371 -3.395 33.363 -3.248 c
+33.186 -3.505 32.966 -3.63 32.702 -3.63 c
+32.426 -3.63 32.209 -3.557 32.055 -3.41 c
+31.908 -3.256 31.835 -3.039 31.835 -2.763 c
+31.835 -2.462 31.937 -2.219 32.143 -2.043 c
+32.349 -1.859 32.632 -1.764 32.995 -1.764 c
+33.348 -1.764 l
+33.348 -1.44 l
+33.348 -1.263 33.308 -1.143 33.231 -1.072 c
+33.15 -0.995 33.032 -0.955 32.878 -0.955 c
+32.731 -0.955 32.606 -0.999 32.511 -1.087 c
+32.423 -1.176 32.378 -1.286 32.378 -1.411 c
+31.893 -1.411 l
+31.893 -1.263 31.937 -1.124 32.026 -0.985 c
+32.114 -0.837 32.232 -0.727 32.378 -0.646 c
+32.533 -0.569 32.706 -0.529 32.893 -0.529 c
+33.205 -0.529 33.44 -0.61 33.599 -0.764 c
+33.753 -0.911 33.834 -1.132 33.834 -1.425 c
+33.834 -2.925 l
+33.841 -3.16 33.878 -3.362 33.936 -3.528 c
+33.936 -3.572 l
+h
+32.775 -3.189 m
+32.893 -3.189 33.003 -3.156 33.113 -3.087 c
+33.219 -3.021 33.297 -2.936 33.348 -2.836 c
+33.348 -2.131 l
+33.084 -2.131 l
+32.849 -2.131 32.661 -2.183 32.525 -2.278 c
+32.397 -2.377 32.334 -2.52 32.334 -2.705 c
+32.334 -2.873 32.363 -2.994 32.423 -3.072 c
+32.488 -3.152 32.606 -3.189 32.775 -3.189 c
+34.869 -0.588 m
+34.884 -0.867 l
+35.061 -0.643 35.299 -0.529 35.605 -0.529 c
+35.935 -0.529 36.167 -0.675 36.296 -0.97 c
+36.479 -0.675 36.741 -0.529 37.075 -0.529 c
+37.633 -0.529 37.917 -0.874 37.927 -1.558 c
+37.927 -3.572 l
+37.442 -3.572 l
+37.442 -1.602 l
+37.442 -1.389 37.402 -1.23 37.325 -1.132 c
+37.244 -1.025 37.111 -0.97 36.928 -0.97 c
+36.781 -0.97 36.663 -1.028 36.575 -1.146 c
+36.487 -1.257 36.432 -1.396 36.413 -1.573 c
+36.413 -3.572 l
+35.928 -3.572 l
+35.928 -1.587 l
+35.917 -1.176 35.744 -0.97 35.414 -0.97 c
+35.168 -0.97 34.995 -1.095 34.9 -1.338 c
+34.9 -3.572 l
+34.414 -3.572 l
+34.414 -0.588 l
+h
+41.742 -2.219 m
+41.742 -2.69 41.657 -3.042 41.491 -3.278 c
+41.323 -3.513 41.08 -3.63 40.757 -3.63 c
+40.44 -3.63 40.205 -3.495 40.051 -3.219 c
+40.022 -3.572 l
+39.581 -3.572 l
+39.581 0.661 l
+40.066 0.661 l
+40.066 -0.911 l
+40.22 -0.658 40.452 -0.529 40.757 -0.529 c
+41.08 -0.529 41.323 -0.646 41.491 -0.881 c
+41.657 -1.117 41.742 -1.466 41.742 -1.926 c
+h
+41.256 -1.94 m
+41.256 -1.587 41.205 -1.338 41.109 -1.19 c
+41.011 -1.043 40.849 -0.97 40.625 -0.97 c
+40.378 -0.97 40.191 -1.109 40.066 -1.381 c
+40.066 -2.792 l
+40.184 -3.057 40.375 -3.189 40.639 -3.189 c
+40.853 -3.189 41.011 -3.116 41.109 -2.969 c
+41.205 -2.815 41.256 -2.572 41.256 -2.248 c
+h
+43.417 -1.043 m
+43.347 -1.036 43.274 -1.028 43.197 -1.028 c
+42.94 -1.028 42.763 -1.168 42.667 -1.44 c
+42.667 -3.572 l
+42.183 -3.572 l
+42.183 -0.588 l
+42.653 -0.588 l
+42.667 -0.897 l
+42.792 -0.654 42.977 -0.529 43.212 -0.529 c
+43.289 -0.529 43.351 -0.544 43.403 -0.573 c
+h
+45.214 -3.572 m
+45.185 -3.505 45.163 -3.395 45.155 -3.248 c
+44.979 -3.505 44.758 -3.63 44.494 -3.63 c
+44.219 -3.63 44.001 -3.557 43.847 -3.41 c
+43.7 -3.256 43.627 -3.039 43.627 -2.763 c
+43.627 -2.462 43.729 -2.219 43.935 -2.043 c
+44.141 -1.859 44.425 -1.764 44.788 -1.764 c
+45.14 -1.764 l
+45.14 -1.44 l
+45.14 -1.263 45.1 -1.143 45.023 -1.072 c
+44.942 -0.995 44.824 -0.955 44.67 -0.955 c
+44.523 -0.955 44.398 -0.999 44.303 -1.087 c
+44.215 -1.176 44.171 -1.286 44.171 -1.411 c
+43.686 -1.411 l
+43.686 -1.263 43.729 -1.124 43.818 -0.985 c
+43.906 -0.837 44.024 -0.727 44.171 -0.646 c
+44.325 -0.569 44.498 -0.529 44.685 -0.529 c
+44.997 -0.529 45.233 -0.61 45.391 -0.764 c
+45.545 -0.911 45.626 -1.132 45.626 -1.425 c
+45.626 -2.925 l
+45.633 -3.16 45.67 -3.362 45.728 -3.528 c
+45.728 -3.572 l
+h
+44.568 -3.189 m
+44.685 -3.189 44.795 -3.156 44.905 -3.087 c
+45.013 -3.021 45.09 -2.936 45.14 -2.836 c
+45.14 -2.131 l
+44.876 -2.131 l
+44.641 -2.131 44.454 -2.183 44.317 -2.278 c
+44.189 -2.377 44.126 -2.52 44.126 -2.705 c
+44.126 -2.873 44.156 -2.994 44.215 -3.072 c
+44.281 -3.152 44.398 -3.189 44.568 -3.189 c
+46.663 -0.588 m
+46.677 -0.911 l
+46.86 -0.658 47.103 -0.529 47.397 -0.529 c
+47.926 -0.529 48.194 -0.881 48.205 -1.587 c
+48.205 -3.572 l
+47.721 -3.572 l
+47.721 -1.616 l
+47.721 -1.381 47.68 -1.216 47.603 -1.117 c
+47.522 -1.022 47.405 -0.97 47.25 -0.97 c
+47.133 -0.97 47.022 -1.01 46.927 -1.087 c
+46.827 -1.168 46.75 -1.275 46.692 -1.411 c
+46.692 -3.572 l
+46.206 -3.572 l
+46.206 -0.588 l
+h
+49.79 -3.204 m
+49.955 -3.204 50.087 -3.156 50.187 -3.057 c
+50.282 -2.961 50.337 -2.818 50.348 -2.631 c
+50.804 -2.631 l
+50.792 -2.917 50.69 -3.156 50.495 -3.351 c
+50.308 -3.538 50.073 -3.63 49.79 -3.63 c
+49.425 -3.63 49.146 -3.513 48.951 -3.278 c
+48.753 -3.042 48.658 -2.697 48.658 -2.234 c
+48.658 -1.911 l
+48.658 -1.462 48.749 -1.117 48.937 -0.881 c
+49.132 -0.646 49.414 -0.529 49.79 -0.529 c
+50.091 -0.529 50.333 -0.628 50.509 -0.823 c
+50.694 -1.022 50.792 -1.286 50.804 -1.616 c
+50.348 -1.616 l
+50.326 -1.392 50.267 -1.227 50.171 -1.117 c
+50.083 -1.01 49.955 -0.955 49.79 -0.955 c
+49.572 -0.955 49.41 -1.028 49.304 -1.176 c
+49.205 -1.315 49.15 -1.543 49.142 -1.866 c
+49.142 -2.248 l
+49.142 -2.601 49.19 -2.851 49.29 -2.998 c
+49.396 -3.138 49.562 -3.204 49.79 -3.204 c
+51.682 -0.897 m
+51.866 -0.654 52.101 -0.529 52.388 -0.529 c
+52.917 -0.529 53.185 -0.881 53.196 -1.587 c
+53.196 -3.572 l
+52.711 -3.572 l
+52.711 -1.616 l
+52.711 -1.381 52.67 -1.216 52.593 -1.117 c
+52.512 -1.022 52.394 -0.97 52.24 -0.97 c
+52.123 -0.97 52.013 -1.01 51.917 -1.087 c
+51.818 -1.168 51.741 -1.275 51.682 -1.411 c
+51.682 -3.572 l
+51.197 -3.572 l
+51.197 0.661 l
+51.682 0.661 l
+h
+f
+Q
+0.793 0.801 0.129 0.016 K
+0.567 w
+q 1 0 0 1 602.8229 154.5574 cm
+0 0 m
+5.862 3.679 l
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 606.8806 157.1041 cm
+0 0 m
+-0.338 -1.47 l
+2.257 1.419 l
+-1.474 0.335 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 606.8807 157.1041 cm
+0 0 m
+-0.338 -1.47 l
+2.257 1.419 l
+-1.474 0.335 l
+0 0 l
+h
+S
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 634.8231 174.5965 cm
+0 0 m
+-1.058 0 l
+-1.058 -3.572 l
+-1.558 -3.572 l
+-1.558 0 l
+-2.616 0 l
+-2.616 0.441 l
+0 0.441 l
+h
+0.823 -0.897 m
+1.007 -0.654 1.242 -0.53 1.529 -0.53 c
+2.058 -0.53 2.326 -0.882 2.337 -1.588 c
+2.337 -3.572 l
+1.852 -3.572 l
+1.852 -1.617 l
+1.852 -1.382 1.812 -1.216 1.735 -1.118 c
+1.654 -1.022 1.536 -0.97 1.382 -0.97 c
+1.264 -0.97 1.154 -1.01 1.058 -1.088 c
+0.96 -1.168 0.882 -1.276 0.823 -1.411 c
+0.823 -3.572 l
+0.338 -3.572 l
+0.338 0.661 l
+0.823 0.661 l
+h
+3.406 -3.572 -0.5 2.984 re
+3.436 0.206 m
+3.436 0.118 3.41 0.044 3.362 -0.015 c
+3.322 -0.066 3.252 -0.088 3.157 -0.088 c
+3.069 -0.088 2.999 -0.066 2.951 -0.015 c
+2.911 0.044 2.892 0.11 2.892 0.191 c
+2.892 0.279 2.911 0.353 2.951 0.411 c
+2.999 0.47 3.069 0.5 3.157 0.5 c
+3.252 0.5 3.322 0.47 3.362 0.411 c
+3.41 0.353 3.436 0.283 3.436 0.206 c
+5.523 -2.808 m
+5.523 -2.701 5.483 -2.612 5.406 -2.543 c
+5.325 -2.466 5.174 -2.377 4.95 -2.278 c
+4.686 -2.172 4.498 -2.08 4.391 -1.999 c
+4.281 -1.922 4.204 -1.834 4.156 -1.735 c
+4.104 -1.639 4.083 -1.521 4.083 -1.382 c
+4.083 -1.139 4.171 -0.937 4.347 -0.779 c
+4.524 -0.613 4.748 -0.53 5.024 -0.53 c
+5.317 -0.53 5.552 -0.617 5.729 -0.794 c
+5.905 -0.963 5.993 -1.176 5.993 -1.44 c
+5.509 -1.44 l
+5.509 -1.305 5.457 -1.191 5.361 -1.103 c
+5.274 -1.007 5.159 -0.956 5.024 -0.956 c
+4.877 -0.956 4.763 -0.996 4.686 -1.073 c
+4.605 -1.143 4.568 -1.242 4.568 -1.367 c
+4.568 -1.467 4.597 -1.544 4.656 -1.602 c
+4.715 -1.661 4.854 -1.742 5.082 -1.837 c
+5.442 -1.985 5.689 -2.128 5.818 -2.263 c
+5.953 -2.392 6.023 -2.565 6.023 -2.778 c
+6.023 -3.036 5.928 -3.241 5.744 -3.396 c
+5.567 -3.553 5.332 -3.631 5.039 -3.631 c
+4.723 -3.631 4.469 -3.543 4.274 -3.366 c
+4.087 -3.183 3.994 -2.951 3.994 -2.675 c
+4.48 -2.675 l
+4.487 -2.845 4.538 -2.977 4.627 -3.072 c
+4.723 -3.161 4.862 -3.204 5.039 -3.204 c
+5.193 -3.204 5.31 -3.171 5.391 -3.102 c
+5.479 -3.036 5.523 -2.936 5.523 -2.808 c
+8.214 -3.572 -0.5 2.984 re
+8.243 0.206 m
+8.243 0.118 8.216 0.044 8.169 -0.015 c
+8.129 -0.066 8.058 -0.088 7.963 -0.088 c
+7.875 -0.088 7.805 -0.066 7.757 -0.015 c
+7.717 0.044 7.699 0.11 7.699 0.191 c
+7.699 0.279 7.717 0.353 7.757 0.411 c
+7.805 0.47 7.875 0.5 7.963 0.5 c
+8.058 0.5 8.129 0.47 8.169 0.411 c
+8.216 0.353 8.243 0.283 8.243 0.206 c
+10.327 -2.808 m
+10.327 -2.701 10.286 -2.612 10.209 -2.543 c
+10.128 -2.466 9.978 -2.377 9.753 -2.278 c
+9.488 -2.172 9.301 -2.08 9.195 -1.999 c
+9.084 -1.922 9.007 -1.834 8.96 -1.735 c
+8.908 -1.639 8.885 -1.521 8.885 -1.382 c
+8.885 -1.139 8.974 -0.937 9.151 -0.779 c
+9.327 -0.613 9.55 -0.53 9.826 -0.53 c
+10.121 -0.53 10.356 -0.617 10.532 -0.794 c
+10.708 -0.963 10.797 -1.176 10.797 -1.44 c
+10.311 -1.44 l
+10.311 -1.305 10.26 -1.191 10.165 -1.103 c
+10.076 -1.007 9.962 -0.956 9.826 -0.956 c
+9.679 -0.956 9.565 -0.996 9.488 -1.073 c
+9.407 -1.143 9.371 -1.242 9.371 -1.367 c
+9.371 -1.467 9.4 -1.544 9.459 -1.602 c
+9.517 -1.661 9.658 -1.742 9.885 -1.837 c
+10.246 -1.985 10.491 -2.128 10.62 -2.263 c
+10.756 -2.392 10.826 -2.565 10.826 -2.778 c
+10.826 -3.036 10.73 -3.241 10.547 -3.396 c
+10.371 -3.553 10.136 -3.631 9.841 -3.631 c
+9.525 -3.631 9.272 -3.543 9.077 -3.366 c
+8.889 -3.183 8.798 -2.951 8.798 -2.675 c
+9.282 -2.675 l
+9.29 -2.845 9.342 -2.977 9.43 -3.072 c
+9.525 -3.161 9.665 -3.204 9.841 -3.204 c
+9.995 -3.204 10.113 -3.171 10.194 -3.102 c
+10.282 -3.036 10.327 -2.936 10.327 -2.808 c
+14.016 -3.572 m
+13.986 -3.506 13.964 -3.396 13.957 -3.248 c
+13.781 -3.506 13.56 -3.631 13.296 -3.631 c
+13.02 -3.631 12.803 -3.557 12.648 -3.41 c
+12.502 -3.256 12.428 -3.04 12.428 -2.764 c
+12.428 -2.462 12.531 -2.22 12.737 -2.043 c
+12.943 -1.86 13.226 -1.764 13.589 -1.764 c
+13.942 -1.764 l
+13.942 -1.44 l
+13.942 -1.264 13.901 -1.143 13.824 -1.073 c
+13.743 -0.996 13.626 -0.956 13.471 -0.956 c
+13.325 -0.956 13.2 -1 13.105 -1.088 c
+13.016 -1.176 12.972 -1.286 12.972 -1.411 c
+12.487 -1.411 l
+12.487 -1.264 12.531 -1.124 12.619 -0.985 c
+12.708 -0.838 12.825 -0.728 12.972 -0.647 c
+13.126 -0.57 13.299 -0.53 13.486 -0.53 c
+13.799 -0.53 14.034 -0.611 14.192 -0.765 c
+14.346 -0.912 14.427 -1.132 14.427 -1.426 c
+14.427 -2.926 l
+14.435 -3.161 14.471 -3.362 14.53 -3.528 c
+14.53 -3.572 l
+h
+13.369 -3.19 m
+13.486 -3.19 13.596 -3.157 13.707 -3.087 c
+13.814 -3.021 13.891 -2.936 13.942 -2.837 c
+13.942 -2.132 l
+13.677 -2.132 l
+13.442 -2.132 13.255 -2.183 13.119 -2.278 c
+12.991 -2.377 12.928 -2.521 12.928 -2.705 c
+12.928 -2.874 12.958 -2.995 13.016 -3.072 c
+13.082 -3.153 13.2 -3.19 13.369 -3.19 c
+16.742 -3.572 -0.5 4.233 re
+17.315 -1.941 m
+17.315 -1.511 17.419 -1.168 17.624 -0.912 c
+17.837 -0.658 18.117 -0.53 18.462 -0.53 c
+18.804 -0.53 19.079 -0.658 19.285 -0.912 c
+19.499 -1.158 19.613 -1.492 19.623 -1.911 c
+19.623 -2.22 l
+19.623 -2.653 19.513 -2.995 19.3 -3.248 c
+19.094 -3.506 18.815 -3.631 18.462 -3.631 c
+18.117 -3.631 17.845 -3.51 17.639 -3.263 c
+17.433 -3.021 17.323 -2.687 17.315 -2.263 c
+h
+17.801 -2.22 m
+17.801 -2.535 17.859 -2.778 17.977 -2.955 c
+18.102 -3.123 18.264 -3.204 18.462 -3.204 c
+18.892 -3.204 19.116 -2.896 19.138 -2.278 c
+19.138 -1.941 l
+19.138 -1.639 19.073 -1.397 18.948 -1.22 c
+18.83 -1.044 18.668 -0.956 18.462 -0.956 c
+18.264 -0.956 18.102 -1.044 17.977 -1.22 c
+17.859 -1.397 17.801 -1.639 17.801 -1.941 c
+h
+21.09 -3.204 m
+21.255 -3.204 21.387 -3.157 21.487 -3.057 c
+21.582 -2.962 21.637 -2.818 21.648 -2.631 c
+22.104 -2.631 l
+22.092 -2.918 21.99 -3.157 21.795 -3.352 c
+21.608 -3.539 21.373 -3.631 21.09 -3.631 c
+20.725 -3.631 20.446 -3.514 20.251 -3.278 c
+20.053 -3.043 19.958 -2.697 19.958 -2.234 c
+19.958 -1.911 l
+19.958 -1.463 20.05 -1.118 20.237 -0.882 c
+20.432 -0.647 20.715 -0.53 21.09 -0.53 c
+21.391 -0.53 21.633 -0.628 21.81 -0.823 c
+21.994 -1.022 22.092 -1.286 22.104 -1.617 c
+21.648 -1.617 l
+21.626 -1.393 21.567 -1.228 21.471 -1.118 c
+21.384 -1.01 21.255 -0.956 21.09 -0.956 c
+20.873 -0.956 20.711 -1.029 20.604 -1.176 c
+20.505 -1.316 20.45 -1.544 20.443 -1.867 c
+20.443 -2.249 l
+20.443 -2.602 20.49 -2.851 20.59 -2.999 c
+20.696 -3.138 20.862 -3.204 21.09 -3.204 c
+24.029 -3.572 m
+24 -3.506 23.978 -3.396 23.971 -3.248 c
+23.794 -3.506 23.574 -3.631 23.309 -3.631 c
+23.033 -3.631 22.817 -3.557 22.662 -3.41 c
+22.516 -3.256 22.442 -3.04 22.442 -2.764 c
+22.442 -2.462 22.545 -2.22 22.751 -2.043 c
+22.956 -1.86 23.239 -1.764 23.603 -1.764 c
+23.956 -1.764 l
+23.956 -1.44 l
+23.956 -1.264 23.916 -1.143 23.838 -1.073 c
+23.757 -0.996 23.64 -0.956 23.486 -0.956 c
+23.339 -0.956 23.214 -1 23.118 -1.088 c
+23.03 -1.176 22.986 -1.286 22.986 -1.411 c
+22.501 -1.411 l
+22.501 -1.264 22.545 -1.124 22.633 -0.985 c
+22.721 -0.838 22.838 -0.728 22.986 -0.647 c
+23.14 -0.57 23.312 -0.53 23.501 -0.53 c
+23.813 -0.53 24.048 -0.611 24.206 -0.765 c
+24.36 -0.912 24.441 -1.132 24.441 -1.426 c
+24.441 -2.926 l
+24.448 -3.161 24.485 -3.362 24.544 -3.528 c
+24.544 -3.572 l
+h
+23.383 -3.19 m
+23.501 -3.19 23.611 -3.157 23.721 -3.087 c
+23.827 -3.021 23.904 -2.936 23.956 -2.837 c
+23.956 -2.132 l
+23.692 -2.132 l
+23.456 -2.132 23.268 -2.183 23.133 -2.278 c
+23.004 -2.377 22.942 -2.521 22.942 -2.705 c
+22.942 -2.874 22.971 -2.995 23.03 -3.072 c
+23.096 -3.153 23.214 -3.19 23.383 -3.19 c
+25.551 -3.572 -0.5 4.233 re
+29.589 -2.22 m
+29.589 -2.691 29.504 -3.043 29.34 -3.278 c
+29.171 -3.514 28.928 -3.631 28.604 -3.631 c
+28.288 -3.631 28.053 -3.495 27.899 -3.219 c
+27.869 -3.572 l
+27.428 -3.572 l
+27.428 0.661 l
+27.914 0.661 l
+27.914 -0.912 l
+28.068 -0.658 28.299 -0.53 28.604 -0.53 c
+28.928 -0.53 29.171 -0.647 29.34 -0.882 c
+29.504 -1.118 29.589 -1.467 29.589 -1.926 c
+h
+29.105 -1.941 m
+29.105 -1.588 29.053 -1.338 28.957 -1.191 c
+28.858 -1.044 28.696 -0.97 28.472 -0.97 c
+28.226 -0.97 28.039 -1.11 27.914 -1.382 c
+27.914 -2.793 l
+28.031 -3.057 28.222 -3.19 28.487 -3.19 c
+28.7 -3.19 28.858 -3.117 28.957 -2.969 c
+29.053 -2.815 29.105 -2.573 29.105 -2.249 c
+h
+31.265 -1.044 m
+31.195 -1.037 31.122 -1.029 31.044 -1.029 c
+30.788 -1.029 30.611 -1.168 30.516 -1.44 c
+30.516 -3.572 l
+30.03 -3.572 l
+30.03 -0.588 l
+30.501 -0.588 l
+30.516 -0.897 l
+30.64 -0.654 30.824 -0.53 31.06 -0.53 c
+31.137 -0.53 31.199 -0.544 31.25 -0.574 c
+h
+33.062 -3.572 m
+33.032 -3.506 33.011 -3.396 33.003 -3.248 c
+32.827 -3.506 32.606 -3.631 32.342 -3.631 c
+32.066 -3.631 31.85 -3.557 31.695 -3.41 c
+31.548 -3.256 31.474 -3.04 31.474 -2.764 c
+31.474 -2.462 31.577 -2.22 31.783 -2.043 c
+31.989 -1.86 32.272 -1.764 32.636 -1.764 c
+32.988 -1.764 l
+32.988 -1.44 l
+32.988 -1.264 32.949 -1.143 32.871 -1.073 c
+32.79 -0.996 32.673 -0.956 32.518 -0.956 c
+32.371 -0.956 32.246 -1 32.151 -1.088 c
+32.062 -1.176 32.018 -1.286 32.018 -1.411 c
+31.534 -1.411 l
+31.534 -1.264 31.577 -1.124 31.665 -0.985 c
+31.754 -0.838 31.871 -0.728 32.018 -0.647 c
+32.172 -0.57 32.346 -0.53 32.533 -0.53 c
+32.845 -0.53 33.08 -0.611 33.238 -0.765 c
+33.393 -0.912 33.473 -1.132 33.473 -1.426 c
+33.473 -2.926 l
+33.481 -3.161 33.518 -3.362 33.577 -3.528 c
+33.577 -3.572 l
+h
+32.415 -3.19 m
+32.533 -3.19 32.643 -3.157 32.753 -3.087 c
+32.86 -3.021 32.937 -2.936 32.988 -2.837 c
+32.988 -2.132 l
+32.724 -2.132 l
+32.488 -2.132 32.301 -2.183 32.166 -2.278 c
+32.037 -2.377 31.974 -2.521 31.974 -2.705 c
+31.974 -2.874 32.004 -2.995 32.062 -3.072 c
+32.128 -3.153 32.246 -3.19 32.415 -3.19 c
+34.51 -0.588 m
+34.524 -0.912 l
+34.709 -0.658 34.95 -0.53 35.245 -0.53 c
+35.774 -0.53 36.043 -0.882 36.053 -1.588 c
+36.053 -3.572 l
+35.568 -3.572 l
+35.568 -1.617 l
+35.568 -1.382 35.528 -1.216 35.451 -1.118 c
+35.37 -1.022 35.252 -0.97 35.098 -0.97 c
+34.98 -0.97 34.87 -1.01 34.774 -1.088 c
+34.675 -1.168 34.598 -1.276 34.539 -1.411 c
+34.539 -3.572 l
+34.054 -3.572 l
+34.054 -0.588 l
+h
+37.637 -3.204 m
+37.803 -3.204 37.934 -3.157 38.034 -3.057 c
+38.129 -2.962 38.185 -2.818 38.196 -2.631 c
+38.651 -2.631 l
+38.64 -2.918 38.537 -3.157 38.343 -3.352 c
+38.155 -3.539 37.92 -3.631 37.637 -3.631 c
+37.273 -3.631 36.994 -3.514 36.799 -3.278 c
+36.6 -3.043 36.505 -2.697 36.505 -2.234 c
+36.505 -1.911 l
+36.505 -1.463 36.597 -1.118 36.785 -0.882 c
+36.98 -0.647 37.262 -0.53 37.637 -0.53 c
+37.938 -0.53 38.181 -0.628 38.358 -0.823 c
+38.541 -1.022 38.64 -1.286 38.651 -1.617 c
+38.196 -1.617 l
+38.173 -1.393 38.115 -1.228 38.019 -1.118 c
+37.931 -1.01 37.803 -0.956 37.637 -0.956 c
+37.42 -0.956 37.259 -1.029 37.152 -1.176 c
+37.053 -1.316 36.997 -1.544 36.99 -1.867 c
+36.99 -2.249 l
+36.99 -2.602 37.038 -2.851 37.138 -2.999 c
+37.244 -3.138 37.409 -3.204 37.637 -3.204 c
+39.53 -0.897 m
+39.713 -0.654 39.949 -0.53 40.235 -0.53 c
+40.764 -0.53 41.032 -0.882 41.044 -1.588 c
+41.044 -3.572 l
+40.558 -3.572 l
+40.558 -1.617 l
+40.558 -1.382 40.518 -1.216 40.441 -1.118 c
+40.36 -1.022 40.242 -0.97 40.088 -0.97 c
+39.97 -0.97 39.86 -1.01 39.765 -1.088 c
+39.665 -1.168 39.588 -1.276 39.53 -1.411 c
+39.53 -3.572 l
+39.044 -3.572 l
+39.044 0.661 l
+39.53 0.661 l
+h
+41.616 -3.308 m
+41.616 -3.219 41.639 -3.146 41.69 -3.087 c
+41.749 -3.028 41.826 -2.999 41.925 -2.999 c
+42.032 -2.999 42.109 -3.028 42.16 -3.087 c
+42.219 -3.146 42.249 -3.219 42.249 -3.308 c
+42.249 -3.389 42.219 -3.454 42.16 -3.514 c
+42.109 -3.572 42.032 -3.601 41.925 -3.601 c
+41.826 -3.601 41.749 -3.572 41.69 -3.514 c
+41.639 -3.454 41.616 -3.389 41.616 -3.308 c
+f
+Q
+633.001 164.439 -0.501 4.013 re
+634.36 168.143 m
+634.36 167.423 l
+634.816 167.423 l
+634.816 167.026 l
+634.36 167.026 l
+634.36 165.174 l
+634.36 165.056 634.378 164.968 634.419 164.91 c
+634.455 164.85 634.526 164.821 634.625 164.821 c
+634.684 164.821 634.746 164.829 634.816 164.85 c
+634.816 164.439 l
+634.698 164.403 634.584 164.38 634.478 164.38 c
+634.279 164.38 634.129 164.447 634.023 164.586 c
+633.923 164.723 633.875 164.917 633.875 165.174 c
+633.875 167.026 l
+633.42 167.026 l
+633.42 167.423 l
+633.875 167.423 l
+633.875 168.143 l
+h
+637.017 164.439 -0.5 2.984 re
+637.046 168.217 m
+637.046 168.129 637.021 168.056 636.973 167.996 c
+636.932 167.945 636.863 167.923 636.767 167.923 c
+636.679 167.923 636.61 167.945 636.562 167.996 c
+636.521 168.056 636.502 168.121 636.502 168.202 c
+636.502 168.291 636.521 168.364 636.562 168.422 c
+636.61 168.482 636.679 168.511 636.767 168.511 c
+636.863 168.511 636.932 168.482 636.973 168.422 c
+637.021 168.364 637.046 168.295 637.046 168.217 c
+639.13 165.203 m
+639.13 165.311 639.089 165.399 639.012 165.469 c
+638.931 165.546 638.781 165.634 638.557 165.733 c
+638.293 165.839 638.104 165.931 637.998 166.012 c
+637.888 166.089 637.811 166.178 637.763 166.277 c
+637.711 166.373 637.69 166.49 637.69 166.629 c
+637.69 166.872 637.778 167.074 637.954 167.232 c
+638.131 167.398 638.355 167.482 638.63 167.482 c
+638.924 167.482 639.159 167.394 639.336 167.217 c
+639.512 167.048 639.6 166.835 639.6 166.571 c
+639.116 166.571 l
+639.116 166.707 639.064 166.82 638.968 166.909 c
+638.881 167.005 638.767 167.056 638.63 167.056 c
+638.484 167.056 638.37 167.015 638.293 166.938 c
+638.212 166.868 638.175 166.77 638.175 166.644 c
+638.175 166.545 638.204 166.468 638.262 166.409 c
+638.322 166.35 638.461 166.269 638.689 166.174 c
+639.049 166.026 639.295 165.883 639.424 165.748 c
+639.56 165.619 639.629 165.446 639.629 165.233 c
+639.629 164.976 639.534 164.771 639.351 164.615 c
+639.174 164.458 638.939 164.38 638.645 164.38 c
+638.329 164.38 638.075 164.469 637.88 164.645 c
+637.693 164.829 637.601 165.06 637.601 165.336 c
+638.087 165.336 l
+638.094 165.167 638.145 165.035 638.233 164.939 c
+638.329 164.85 638.468 164.807 638.645 164.807 c
+638.8 164.807 638.917 164.84 638.998 164.91 c
+639.086 164.976 639.13 165.075 639.13 165.203 c
+641.864 166.689 m
+642.187 166.689 l
+642.382 166.689 642.532 166.751 642.643 166.88 c
+642.75 167.005 642.804 167.173 642.804 167.379 c
+642.804 167.85 642.621 168.085 642.261 168.085 c
+642.085 168.085 641.944 168.019 641.849 167.894 c
+641.75 167.765 641.703 167.599 641.703 167.394 c
+641.217 167.394 l
+641.217 167.717 641.313 167.982 641.511 168.187 c
+641.706 168.401 641.956 168.511 642.261 168.511 c
+642.573 168.511 642.823 168.408 643.01 168.202 c
+643.195 168.004 643.29 167.732 643.29 167.379 c
+643.29 167.192 643.238 167.015 643.143 166.85 c
+643.043 166.692 642.922 166.575 642.775 166.497 c
+643.147 166.358 643.334 166.045 643.334 165.556 c
+643.334 165.203 643.235 164.917 643.039 164.704 c
+642.842 164.487 642.584 164.38 642.261 164.38 c
+641.938 164.38 641.676 164.476 641.482 164.675 c
+641.283 164.881 641.188 165.152 641.188 165.498 c
+641.688 165.498 l
+641.688 165.281 641.736 165.108 641.834 164.983 c
+641.941 164.866 642.085 164.807 642.261 164.807 c
+642.437 164.807 642.577 164.866 642.687 164.983 c
+642.794 165.108 642.849 165.295 642.849 165.542 c
+642.849 166.03 642.617 166.277 642.158 166.277 c
+641.864 166.277 l
+h
+646.127 164.807 m
+646.293 164.807 646.424 164.854 646.524 164.954 c
+646.619 165.049 646.675 165.193 646.685 165.38 c
+647.141 165.38 l
+647.13 165.093 647.027 164.854 646.833 164.66 c
+646.644 164.472 646.409 164.38 646.127 164.38 c
+645.763 164.38 645.484 164.498 645.289 164.733 c
+645.09 164.968 644.995 165.314 644.995 165.777 c
+644.995 166.101 l
+644.995 166.549 645.087 166.894 645.274 167.129 c
+645.469 167.364 645.752 167.482 646.127 167.482 c
+646.428 167.482 646.671 167.383 646.847 167.188 c
+647.031 166.99 647.13 166.725 647.141 166.394 c
+646.685 166.394 l
+646.663 166.618 646.605 166.784 646.509 166.894 c
+646.421 167.001 646.293 167.056 646.127 167.056 c
+645.91 167.056 645.748 166.982 645.642 166.835 c
+645.543 166.695 645.487 166.468 645.48 166.144 c
+645.48 165.762 l
+645.48 165.409 645.528 165.16 645.627 165.012 c
+645.734 164.873 645.899 164.807 646.127 164.807 c
+647.435 166.071 m
+647.435 166.501 647.538 166.843 647.743 167.1 c
+647.957 167.354 648.236 167.482 648.581 167.482 c
+648.923 167.482 649.199 167.354 649.405 167.1 c
+649.618 166.853 649.732 166.519 649.742 166.101 c
+649.742 165.791 l
+649.742 165.358 649.632 165.016 649.42 164.763 c
+649.214 164.505 648.934 164.38 648.581 164.38 c
+648.236 164.38 647.964 164.501 647.758 164.748 c
+647.552 164.991 647.442 165.325 647.435 165.748 c
+h
+647.92 165.791 m
+647.92 165.476 647.978 165.233 648.096 165.056 c
+648.221 164.888 648.383 164.807 648.581 164.807 c
+649.011 164.807 649.235 165.116 649.258 165.733 c
+649.258 166.071 l
+649.258 166.373 649.192 166.614 649.067 166.791 c
+648.949 166.967 648.787 167.056 648.581 167.056 c
+648.383 167.056 648.221 166.967 648.096 166.791 c
+647.978 166.614 647.92 166.373 647.92 166.071 c
+h
+650.64 167.423 m
+650.654 167.144 l
+650.831 167.368 651.07 167.482 651.375 167.482 c
+651.705 167.482 651.937 167.335 652.065 167.041 c
+652.249 167.335 652.51 167.482 652.844 167.482 c
+653.403 167.482 653.686 167.136 653.697 166.453 c
+653.697 164.439 l
+653.212 164.439 l
+653.212 166.409 l
+653.212 166.622 653.171 166.78 653.094 166.88 c
+653.013 166.986 652.881 167.041 652.697 167.041 c
+652.55 167.041 652.433 166.982 652.344 166.865 c
+652.256 166.755 652.201 166.614 652.183 166.438 c
+652.183 164.439 l
+651.698 164.439 l
+651.698 166.423 l
+651.687 166.835 651.514 167.041 651.184 167.041 c
+650.937 167.041 650.764 166.916 650.669 166.674 c
+650.669 164.439 l
+650.183 164.439 l
+650.183 167.423 l
+h
+654.601 167.423 m
+654.615 167.144 l
+654.792 167.368 655.031 167.482 655.336 167.482 c
+655.666 167.482 655.898 167.335 656.026 167.041 c
+656.21 167.335 656.471 167.482 656.805 167.482 c
+657.364 167.482 657.647 167.136 657.659 166.453 c
+657.659 164.439 l
+657.173 164.439 l
+657.173 166.409 l
+657.173 166.622 657.133 166.78 657.056 166.88 c
+656.975 166.986 656.842 167.041 656.659 167.041 c
+656.512 167.041 656.394 166.982 656.306 166.865 c
+656.217 166.755 656.163 166.614 656.144 166.438 c
+656.144 164.439 l
+655.66 164.439 l
+655.66 166.423 l
+655.648 166.835 655.475 167.041 655.145 167.041 c
+654.898 167.041 654.725 166.916 654.63 166.674 c
+654.63 164.439 l
+654.145 164.439 l
+654.145 167.423 l
+h
+658.636 164.439 -0.5 2.984 re
+658.665 168.217 m
+658.665 168.129 658.639 168.056 658.592 167.996 c
+658.551 167.945 658.482 167.923 658.386 167.923 c
+658.297 167.923 658.228 167.945 658.18 167.996 c
+658.139 168.056 658.121 168.121 658.121 168.202 c
+658.121 168.291 658.139 168.364 658.18 168.422 c
+658.228 168.482 658.297 168.511 658.386 168.511 c
+658.482 168.511 658.551 168.482 658.592 168.422 c
+658.639 168.364 658.665 168.295 658.665 168.217 c
+659.94 168.143 m
+659.94 167.423 l
+660.396 167.423 l
+660.396 167.026 l
+659.94 167.026 l
+659.94 165.174 l
+659.94 165.056 659.959 164.968 659.999 164.91 c
+660.036 164.85 660.105 164.821 660.205 164.821 c
+660.263 164.821 660.326 164.829 660.396 164.85 c
+660.396 164.439 l
+660.279 164.403 660.165 164.38 660.057 164.38 c
+659.859 164.38 659.708 164.447 659.602 164.586 c
+659.502 164.723 659.455 164.917 659.455 165.174 c
+659.455 167.026 l
+658.999 167.026 l
+658.999 167.423 l
+659.455 167.423 l
+659.455 168.143 l
+h
+662.303 165.203 m
+662.303 165.311 662.263 165.399 662.185 165.469 c
+662.104 165.546 661.954 165.634 661.73 165.733 c
+661.465 165.839 661.278 165.931 661.171 166.012 c
+661.061 166.089 660.984 166.178 660.936 166.277 c
+660.884 166.373 660.863 166.49 660.863 166.629 c
+660.863 166.872 660.951 167.074 661.127 167.232 c
+661.304 167.398 661.528 167.482 661.804 167.482 c
+662.097 167.482 662.332 167.394 662.509 167.217 c
+662.685 167.048 662.773 166.835 662.773 166.571 c
+662.288 166.571 l
+662.288 166.707 662.237 166.82 662.141 166.909 c
+662.053 167.005 661.939 167.056 661.804 167.056 c
+661.657 167.056 661.542 167.015 661.465 166.938 c
+661.384 166.868 661.347 166.77 661.347 166.644 c
+661.347 166.545 661.377 166.468 661.436 166.409 c
+661.495 166.35 661.634 166.269 661.862 166.174 c
+662.222 166.026 662.469 165.883 662.598 165.748 c
+662.733 165.619 662.803 165.446 662.803 165.233 c
+662.803 164.976 662.708 164.771 662.523 164.615 c
+662.347 164.458 662.112 164.38 661.818 164.38 c
+661.502 164.38 661.248 164.469 661.054 164.645 c
+660.867 164.829 660.774 165.06 660.774 165.336 c
+661.26 165.336 l
+661.266 165.167 661.318 165.035 661.407 164.939 c
+661.502 164.85 661.642 164.807 661.818 164.807 c
+661.972 164.807 662.089 164.84 662.17 164.91 c
+662.259 164.976 662.303 165.075 662.303 165.203 c
+665.993 164.439 m
+665.964 164.505 665.941 164.615 665.933 164.763 c
+665.757 164.505 665.537 164.38 665.272 164.38 c
+664.996 164.38 664.78 164.454 664.626 164.601 c
+664.479 164.755 664.405 164.972 664.405 165.247 c
+664.405 165.549 664.508 165.791 664.714 165.968 c
+664.919 166.152 665.202 166.247 665.566 166.247 c
+665.919 166.247 l
+665.919 166.571 l
+665.919 166.747 665.879 166.868 665.802 166.938 c
+665.721 167.015 665.603 167.056 665.449 167.056 c
+665.302 167.056 665.177 167.011 665.081 166.924 c
+664.993 166.835 664.949 166.725 664.949 166.6 c
+664.464 166.6 l
+664.464 166.747 664.508 166.887 664.597 167.026 c
+664.684 167.173 664.802 167.283 664.949 167.364 c
+665.104 167.441 665.276 167.482 665.463 167.482 c
+665.775 167.482 666.01 167.401 666.169 167.247 c
+666.323 167.1 666.404 166.88 666.404 166.585 c
+666.404 165.086 l
+666.411 164.85 666.448 164.649 666.507 164.484 c
+666.507 164.439 l
+h
+665.345 164.821 m
+665.463 164.821 665.574 164.854 665.684 164.925 c
+665.79 164.991 665.867 165.075 665.919 165.174 c
+665.919 165.88 l
+665.655 165.88 l
+665.42 165.88 665.232 165.829 665.096 165.733 c
+664.967 165.634 664.905 165.49 664.905 165.307 c
+664.905 165.137 664.934 165.016 664.993 164.939 c
+665.059 164.858 665.177 164.821 665.345 164.821 c
+667.47 167.115 m
+667.654 167.358 667.889 167.482 668.175 167.482 c
+668.705 167.482 668.973 167.129 668.984 166.423 c
+668.984 164.439 l
+668.499 164.439 l
+668.499 166.394 l
+668.499 166.629 668.458 166.795 668.381 166.894 c
+668.3 166.99 668.183 167.041 668.028 167.041 c
+667.911 167.041 667.801 167.001 667.705 166.924 c
+667.606 166.843 667.529 166.736 667.47 166.6 c
+667.47 164.439 l
+666.985 164.439 l
+666.985 168.673 l
+667.47 168.673 l
+h
+670.586 164.38 m
+670.211 164.38 669.928 164.487 669.733 164.704 c
+669.535 164.929 669.44 165.255 669.44 165.689 c
+669.44 166.057 l
+669.44 166.497 669.532 166.843 669.719 167.1 c
+669.914 167.354 670.189 167.482 670.542 167.482 c
+670.884 167.482 671.138 167.368 671.306 167.144 c
+671.483 166.916 671.574 166.571 671.585 166.101 c
+671.585 165.791 l
+669.925 165.791 l
+669.925 165.718 l
+669.925 165.395 669.983 165.16 670.101 165.012 c
+670.218 164.873 670.388 164.807 670.615 164.807 c
+670.762 164.807 670.887 164.829 670.997 164.881 c
+671.104 164.939 671.207 165.027 671.306 165.145 c
+671.556 164.836 l
+671.35 164.532 671.026 164.38 670.586 164.38 c
+670.542 167.056 m
+670.336 167.056 670.182 166.986 670.086 166.85 c
+669.987 166.71 669.931 166.497 669.925 166.203 c
+671.101 166.203 l
+671.101 166.277 l
+671.078 166.549 671.026 166.747 670.939 166.865 c
+670.851 166.99 670.718 167.056 670.542 167.056 c
+673.526 164.439 m
+673.496 164.505 673.474 164.615 673.467 164.763 c
+673.291 164.505 673.07 164.38 672.805 164.38 c
+672.53 164.38 672.313 164.454 672.159 164.601 c
+672.011 164.755 671.938 164.972 671.938 165.247 c
+671.938 165.549 672.042 165.791 672.247 165.968 c
+672.453 166.152 672.736 166.247 673.1 166.247 c
+673.453 166.247 l
+673.453 166.571 l
+673.453 166.747 673.412 166.868 673.335 166.938 c
+673.254 167.015 673.137 167.056 672.982 167.056 c
+672.835 167.056 672.71 167.011 672.615 166.924 c
+672.526 166.835 672.482 166.725 672.482 166.6 c
+671.997 166.6 l
+671.997 166.747 672.042 166.887 672.129 167.026 c
+672.217 167.173 672.335 167.283 672.482 167.364 c
+672.636 167.441 672.809 167.482 672.996 167.482 c
+673.309 167.482 673.544 167.401 673.702 167.247 c
+673.856 167.1 673.937 166.88 673.937 166.585 c
+673.937 165.086 l
+673.945 164.85 673.981 164.649 674.041 164.484 c
+674.041 164.439 l
+h
+672.879 164.821 m
+672.996 164.821 673.106 164.854 673.218 164.925 c
+673.324 164.991 673.401 165.075 673.453 165.174 c
+673.453 165.88 l
+673.187 165.88 l
+672.952 165.88 672.765 165.829 672.63 165.733 c
+672.501 165.634 672.438 165.49 672.438 165.307 c
+672.438 165.137 672.468 165.016 672.526 164.939 c
+672.593 164.858 672.71 164.821 672.879 164.821 c
+674.415 166.071 m
+674.415 166.531 674.496 166.88 674.665 167.115 c
+674.841 167.358 675.091 167.482 675.415 167.482 c
+675.697 167.482 675.918 167.364 676.076 167.129 c
+676.076 168.673 l
+676.561 168.673 l
+676.561 164.439 l
+676.121 164.439 l
+676.091 164.763 l
+675.932 164.505 675.709 164.38 675.415 164.38 c
+675.099 164.38 674.856 164.498 674.679 164.733 c
+674.504 164.976 674.415 165.321 674.415 165.762 c
+h
+674.901 165.791 m
+674.901 165.457 674.948 165.211 675.047 165.056 c
+675.142 164.898 675.304 164.821 675.533 164.821 c
+675.774 164.821 675.959 164.939 676.076 165.174 c
+676.076 166.689 l
+675.948 166.924 675.768 167.041 675.533 167.041 c
+675.304 167.041 675.142 166.961 675.047 166.806 c
+674.948 166.648 674.901 166.409 674.901 166.086 c
+h
+677.131 163.645 m
+676.837 163.836 l
+677.013 164.083 677.105 164.333 677.116 164.586 c
+677.116 165.042 l
+677.615 165.042 l
+677.615 164.645 l
+677.615 164.458 677.565 164.274 677.469 164.087 c
+677.38 163.903 677.266 163.755 677.131 163.645 c
+f
+q 1 0 0 1 633.2211 158.6623 cm
+0 0 m
+0.544 2.176 l
+1.058 2.176 l
+0.088 -1.234 l
+0.018 -1.488 -0.085 -1.679 -0.22 -1.808 c
+-0.36 -1.944 -0.511 -2.013 -0.676 -2.013 c
+-0.746 -2.013 -0.831 -1.999 -0.926 -1.969 c
+-0.926 -1.558 l
+-0.823 -1.573 l
+-0.688 -1.573 -0.58 -1.535 -0.5 -1.469 c
+-0.412 -1.4 -0.345 -1.282 -0.294 -1.117 c
+-0.206 -0.779 l
+-1.073 2.176 l
+-0.544 2.176 l
+h
+1.238 0.823 m
+1.238 1.253 1.341 1.595 1.547 1.852 c
+1.76 2.106 2.039 2.234 2.385 2.234 c
+2.726 2.234 3.002 2.106 3.208 1.852 c
+3.421 1.606 3.535 1.272 3.546 0.853 c
+3.546 0.544 l
+3.546 0.111 3.436 -0.231 3.223 -0.484 c
+3.017 -0.742 2.737 -0.867 2.385 -0.867 c
+2.039 -0.867 1.768 -0.746 1.562 -0.5 c
+1.356 -0.257 1.245 0.077 1.238 0.5 c
+h
+1.723 0.544 m
+1.723 0.229 1.783 -0.014 1.899 -0.191 c
+2.024 -0.359 2.186 -0.44 2.385 -0.44 c
+2.815 -0.44 3.039 -0.132 3.061 0.485 c
+3.061 0.823 l
+3.061 1.125 2.995 1.367 2.87 1.544 c
+2.753 1.72 2.591 1.808 2.385 1.808 c
+2.186 1.808 2.024 1.72 1.899 1.544 c
+1.783 1.367 1.723 1.125 1.723 0.823 c
+h
+5.501 -0.544 m
+5.343 -0.76 5.108 -0.867 4.796 -0.867 c
+4.531 -0.867 4.325 -0.775 4.178 -0.588 c
+4.039 -0.404 3.973 -0.128 3.973 0.235 c
+3.973 2.176 l
+4.457 2.176 l
+4.457 0.265 l
+4.457 -0.199 4.597 -0.426 4.883 -0.426 c
+5.178 -0.426 5.376 -0.294 5.486 -0.029 c
+5.486 2.176 l
+5.986 2.176 l
+5.986 -0.808 l
+5.516 -0.808 l
+h
+9.183 -0.044 m
+9.183 0.063 9.143 0.151 9.066 0.221 c
+8.985 0.298 8.834 0.387 8.61 0.485 c
+8.345 0.592 8.158 0.684 8.052 0.765 c
+7.941 0.842 7.864 0.93 7.817 1.029 c
+7.765 1.125 7.742 1.243 7.742 1.382 c
+7.742 1.625 7.831 1.827 8.008 1.985 c
+8.183 2.151 8.407 2.234 8.683 2.234 c
+8.977 2.234 9.213 2.147 9.389 1.97 c
+9.565 1.801 9.654 1.588 9.654 1.324 c
+9.168 1.324 l
+9.168 1.459 9.117 1.573 9.022 1.661 c
+8.933 1.757 8.819 1.808 8.683 1.808 c
+8.536 1.808 8.422 1.768 8.345 1.691 c
+8.264 1.621 8.228 1.522 8.228 1.397 c
+8.228 1.297 8.257 1.22 8.316 1.162 c
+8.374 1.103 8.515 1.022 8.742 0.927 c
+9.103 0.779 9.348 0.636 9.477 0.5 c
+9.613 0.372 9.683 0.198 9.683 -0.014 c
+9.683 -0.272 9.587 -0.477 9.404 -0.632 c
+9.228 -0.789 8.992 -0.867 8.698 -0.867 c
+8.382 -0.867 8.129 -0.779 7.934 -0.602 c
+7.746 -0.419 7.655 -0.187 7.655 0.088 c
+8.139 0.088 l
+8.147 -0.081 8.198 -0.213 8.287 -0.309 c
+8.382 -0.397 8.522 -0.44 8.698 -0.44 c
+8.852 -0.44 8.97 -0.407 9.051 -0.338 c
+9.139 -0.272 9.183 -0.172 9.183 -0.044 c
+11.197 -0.867 m
+10.822 -0.867 10.539 -0.76 10.344 -0.544 c
+10.146 -0.319 10.051 0.008 10.051 0.441 c
+10.051 0.809 l
+10.051 1.249 10.142 1.595 10.329 1.852 c
+10.524 2.106 10.8 2.234 11.152 2.234 c
+11.495 2.234 11.748 2.12 11.917 1.897 c
+12.093 1.669 12.185 1.324 12.197 0.853 c
+12.197 0.544 l
+10.535 0.544 l
+10.535 0.47 l
+10.535 0.148 10.595 -0.087 10.712 -0.235 c
+10.83 -0.374 10.998 -0.44 11.227 -0.44 c
+11.373 -0.44 11.499 -0.419 11.609 -0.367 c
+11.715 -0.309 11.818 -0.22 11.917 -0.103 c
+12.167 -0.411 l
+11.961 -0.716 11.638 -0.867 11.197 -0.867 c
+11.152 1.808 m
+10.947 1.808 10.793 1.738 10.697 1.602 c
+10.598 1.463 10.543 1.249 10.535 0.956 c
+11.711 0.956 l
+11.711 1.029 l
+11.69 1.301 11.638 1.5 11.549 1.617 c
+11.462 1.742 11.329 1.808 11.152 1.808 c
+13.666 -0.867 m
+13.292 -0.867 13.008 -0.76 12.814 -0.544 c
+12.615 -0.319 12.52 0.008 12.52 0.441 c
+12.52 0.809 l
+12.52 1.249 12.612 1.595 12.799 1.852 c
+12.993 2.106 13.269 2.234 13.622 2.234 c
+13.964 2.234 14.217 2.12 14.387 1.897 c
+14.563 1.669 14.655 1.324 14.666 0.853 c
+14.666 0.544 l
+13.005 0.544 l
+13.005 0.47 l
+13.005 0.148 13.064 -0.087 13.182 -0.235 c
+13.299 -0.374 13.468 -0.44 13.696 -0.44 c
+13.843 -0.44 13.968 -0.419 14.078 -0.367 c
+14.184 -0.309 14.287 -0.22 14.387 -0.103 c
+14.637 -0.411 l
+14.431 -0.716 14.107 -0.867 13.666 -0.867 c
+13.622 1.808 m
+13.417 1.808 13.263 1.738 13.167 1.602 c
+13.068 1.463 13.012 1.249 13.005 0.956 c
+14.181 0.956 l
+14.181 1.029 l
+14.159 1.301 14.107 1.5 14.019 1.617 c
+13.931 1.742 13.799 1.808 13.622 1.808 c
+16.812 -0.808 -0.5 2.984 re
+16.841 2.97 m
+16.841 2.881 16.816 2.808 16.768 2.749 c
+16.727 2.698 16.658 2.675 16.562 2.675 c
+16.474 2.675 16.404 2.698 16.357 2.749 c
+16.316 2.808 16.297 2.874 16.297 2.955 c
+16.297 3.043 16.316 3.117 16.357 3.175 c
+16.404 3.234 16.474 3.263 16.562 3.263 c
+16.658 3.263 16.727 3.234 16.768 3.175 c
+16.816 3.117 16.841 3.047 16.841 2.97 c
+18.117 2.896 m
+18.117 2.176 l
+18.572 2.176 l
+18.572 1.779 l
+18.117 1.779 l
+18.117 -0.073 l
+18.117 -0.191 18.135 -0.279 18.175 -0.338 c
+18.212 -0.397 18.282 -0.426 18.381 -0.426 c
+18.44 -0.426 18.502 -0.419 18.572 -0.397 c
+18.572 -0.808 l
+18.454 -0.845 18.341 -0.867 18.234 -0.867 c
+18.036 -0.867 17.885 -0.801 17.778 -0.661 c
+17.679 -0.525 17.631 -0.33 17.631 -0.073 c
+17.631 1.779 l
+17.176 1.779 l
+17.176 2.176 l
+17.631 2.176 l
+17.631 2.896 l
+h
+19.039 -1.602 m
+18.745 -1.411 l
+18.921 -1.165 19.013 -0.914 19.025 -0.661 c
+19.025 -0.205 l
+19.524 -0.205 l
+19.524 -0.602 l
+19.524 -0.789 19.472 -0.974 19.377 -1.161 c
+19.289 -1.344 19.175 -1.492 19.039 -1.602 c
+22.518 1.72 m
+22.449 1.727 22.375 1.735 22.298 1.735 c
+22.042 1.735 21.865 1.595 21.77 1.324 c
+21.77 -0.808 l
+21.284 -0.808 l
+21.284 2.176 l
+21.755 2.176 l
+21.77 1.867 l
+21.894 2.11 22.078 2.234 22.313 2.234 c
+22.391 2.234 22.453 2.22 22.504 2.19 c
+h
+23.416 -0.808 -0.5 2.984 re
+23.445 2.97 m
+23.445 2.881 23.42 2.808 23.372 2.749 c
+23.331 2.698 23.262 2.675 23.166 2.675 c
+23.077 2.675 23.008 2.698 22.96 2.749 c
+22.919 2.808 22.901 2.874 22.901 2.955 c
+22.901 3.043 22.919 3.117 22.96 3.175 c
+23.008 3.234 23.077 3.263 23.166 3.263 c
+23.262 3.263 23.331 3.234 23.372 3.175 c
+23.42 3.117 23.445 3.047 23.445 2.97 c
+23.989 0.823 m
+23.989 1.283 24.07 1.632 24.239 1.867 c
+24.415 2.11 24.665 2.234 24.988 2.234 c
+25.29 2.234 25.521 2.103 25.679 1.837 c
+25.708 2.176 l
+26.15 2.176 l
+26.15 -0.837 l
+26.15 -1.209 26.05 -1.492 25.855 -1.691 c
+25.668 -1.885 25.407 -1.984 25.076 -1.984 c
+24.93 -1.984 24.76 -1.944 24.577 -1.866 c
+24.39 -1.797 24.253 -1.708 24.165 -1.602 c
+24.357 -1.263 l
+24.562 -1.469 24.787 -1.573 25.032 -1.573 c
+25.433 -1.573 25.639 -1.344 25.65 -0.897 c
+25.65 -0.515 l
+25.492 -0.75 25.271 -0.867 24.988 -0.867 c
+24.673 -0.867 24.43 -0.75 24.253 -0.515 c
+24.085 -0.279 23.996 0.052 23.989 0.485 c
+h
+24.474 0.544 m
+24.474 0.21 24.521 -0.037 24.621 -0.191 c
+24.716 -0.349 24.878 -0.426 25.105 -0.426 c
+25.348 -0.426 25.533 -0.305 25.65 -0.058 c
+25.65 1.426 l
+25.533 1.669 25.356 1.794 25.12 1.794 c
+24.893 1.794 24.731 1.713 24.635 1.559 c
+24.536 1.401 24.481 1.162 24.474 0.838 c
+h
+27.171 1.867 m
+27.355 2.11 27.59 2.234 27.877 2.234 c
+28.406 2.234 28.674 1.881 28.685 1.176 c
+28.685 -0.808 l
+28.201 -0.808 l
+28.201 1.147 l
+28.201 1.382 28.16 1.548 28.083 1.646 c
+28.002 1.742 27.884 1.794 27.73 1.794 c
+27.613 1.794 27.502 1.754 27.407 1.676 c
+27.307 1.595 27.23 1.488 27.171 1.353 c
+27.171 -0.808 l
+26.686 -0.808 l
+26.686 3.425 l
+27.171 3.425 l
+h
+29.857 2.896 m
+29.857 2.176 l
+30.313 2.176 l
+30.313 1.779 l
+29.857 1.779 l
+29.857 -0.073 l
+29.857 -0.191 29.876 -0.279 29.916 -0.338 c
+29.953 -0.397 30.023 -0.426 30.122 -0.426 c
+30.181 -0.426 30.243 -0.419 30.313 -0.397 c
+30.313 -0.808 l
+30.196 -0.845 30.082 -0.867 29.975 -0.867 c
+29.776 -0.867 29.626 -0.801 29.519 -0.661 c
+29.42 -0.525 29.373 -0.33 29.373 -0.073 c
+29.373 1.779 l
+28.916 1.779 l
+28.916 2.176 l
+29.373 2.176 l
+29.373 2.896 l
+h
+31.28 0.324 m
+31.28 0.537 31.297 0.713 31.338 0.853 c
+31.386 1 31.5 1.176 31.677 1.382 c
+31.883 1.632 l
+32.007 1.816 32.074 2.003 32.074 2.19 c
+32.074 2.386 32.029 2.536 31.941 2.646 c
+31.86 2.753 31.75 2.808 31.603 2.808 c
+31.463 2.808 31.345 2.756 31.25 2.66 c
+31.162 2.562 31.118 2.429 31.118 2.264 c
+30.632 2.264 l
+30.632 2.565 30.721 2.808 30.898 2.984 c
+31.081 3.168 31.316 3.263 31.603 3.263 c
+31.897 3.263 32.124 3.168 32.294 2.984 c
+32.471 2.797 32.558 2.543 32.558 2.22 c
+32.558 1.904 32.43 1.592 32.176 1.279 c
+31.926 0.971 l
+31.816 0.823 31.765 0.607 31.765 0.324 c
+h
+31.544 -0.264 m
+31.632 -0.264 31.698 -0.294 31.75 -0.353 c
+31.798 -0.404 31.823 -0.47 31.823 -0.558 c
+31.823 -0.639 31.798 -0.706 31.75 -0.764 c
+31.698 -0.812 31.632 -0.837 31.544 -0.837 c
+31.445 -0.837 31.372 -0.812 31.324 -0.764 c
+31.283 -0.706 31.264 -0.639 31.264 -0.558 c
+31.264 -0.47 31.283 -0.404 31.324 -0.353 c
+31.372 -0.294 31.445 -0.264 31.544 -0.264 c
+f
+Q
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 678.972 167.5189 cm
+0 0 m
+7.555 -2.874 l
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 684.5352 165.4025 cm
+0 0 m
+-1.377 -0.618 l
+2.492 -0.949 l
+-0.618 1.377 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 684.5352 165.4025 cm
+0 0 m
+-1.377 -0.618 l
+2.492 -0.949 l
+-0.618 1.377 l
+0 0 l
+h
+S
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 501.1054 110.5303 cm
+0 0 m
+-1.058 0 l
+-1.058 -3.572 l
+-1.558 -3.572 l
+-1.558 0 l
+-2.616 0 l
+-2.616 0.441 l
+0 0.441 l
+h
+0.823 -0.897 m
+1.008 -0.654 1.243 -0.529 1.529 -0.529 c
+2.058 -0.529 2.326 -0.881 2.338 -1.587 c
+2.338 -3.572 l
+1.852 -3.572 l
+1.852 -1.616 l
+1.852 -1.381 1.812 -1.216 1.735 -1.117 c
+1.654 -1.022 1.536 -0.97 1.382 -0.97 c
+1.264 -0.97 1.154 -1.01 1.058 -1.087 c
+0.96 -1.168 0.882 -1.275 0.823 -1.411 c
+0.823 -3.572 l
+0.339 -3.572 l
+0.339 0.661 l
+0.823 0.661 l
+h
+3.407 -3.572 -0.5 2.984 re
+3.437 0.206 m
+3.437 0.118 3.41 0.044 3.363 -0.014 c
+3.323 -0.066 3.252 -0.087 3.157 -0.087 c
+3.069 -0.087 2.999 -0.066 2.951 -0.014 c
+2.911 0.044 2.893 0.11 2.893 0.191 c
+2.893 0.279 2.911 0.353 2.951 0.412 c
+2.999 0.47 3.069 0.5 3.157 0.5 c
+3.252 0.5 3.323 0.47 3.363 0.412 c
+3.41 0.353 3.437 0.283 3.437 0.206 c
+5.524 -2.807 m
+5.524 -2.701 5.484 -2.612 5.406 -2.543 c
+5.326 -2.466 5.174 -2.377 4.95 -2.278 c
+4.686 -2.171 4.499 -2.08 4.391 -1.999 c
+4.281 -1.922 4.204 -1.834 4.156 -1.734 c
+4.105 -1.639 4.083 -1.521 4.083 -1.381 c
+4.083 -1.139 4.171 -0.937 4.348 -0.779 c
+4.524 -0.613 4.748 -0.529 5.024 -0.529 c
+5.318 -0.529 5.553 -0.617 5.729 -0.793 c
+5.906 -0.962 5.994 -1.176 5.994 -1.44 c
+5.509 -1.44 l
+5.509 -1.304 5.457 -1.19 5.362 -1.103 c
+5.274 -1.007 5.16 -0.955 5.024 -0.955 c
+4.877 -0.955 4.763 -0.995 4.686 -1.072 c
+4.605 -1.143 4.568 -1.242 4.568 -1.367 c
+4.568 -1.466 4.597 -1.543 4.657 -1.602 c
+4.715 -1.66 4.855 -1.741 5.083 -1.837 c
+5.443 -1.984 5.689 -2.127 5.818 -2.263 c
+5.954 -2.392 6.024 -2.564 6.024 -2.778 c
+6.024 -3.035 5.928 -3.241 5.744 -3.395 c
+5.567 -3.553 5.332 -3.63 5.039 -3.63 c
+4.723 -3.63 4.469 -3.542 4.274 -3.366 c
+4.087 -3.183 3.995 -2.95 3.995 -2.675 c
+4.48 -2.675 l
+4.487 -2.844 4.539 -2.977 4.627 -3.072 c
+4.723 -3.16 4.862 -3.204 5.039 -3.204 c
+5.193 -3.204 5.311 -3.171 5.391 -3.102 c
+5.48 -3.035 5.524 -2.936 5.524 -2.807 c
+8.214 -3.572 -0.5 2.984 re
+8.243 0.206 m
+8.243 0.118 8.217 0.044 8.169 -0.014 c
+8.129 -0.066 8.059 -0.087 7.963 -0.087 c
+7.876 -0.087 7.805 -0.066 7.758 -0.014 c
+7.718 0.044 7.699 0.11 7.699 0.191 c
+7.699 0.279 7.718 0.353 7.758 0.412 c
+7.805 0.47 7.876 0.5 7.963 0.5 c
+8.059 0.5 8.129 0.47 8.169 0.412 c
+8.217 0.353 8.243 0.283 8.243 0.206 c
+10.33 -2.807 m
+10.33 -2.701 10.29 -2.612 10.213 -2.543 c
+10.132 -2.466 9.981 -2.377 9.757 -2.278 c
+9.492 -2.171 9.305 -2.08 9.199 -1.999 c
+9.089 -1.922 9.011 -1.834 8.963 -1.734 c
+8.912 -1.639 8.89 -1.521 8.89 -1.381 c
+8.89 -1.139 8.978 -0.937 9.154 -0.779 c
+9.33 -0.613 9.555 -0.529 9.831 -0.529 c
+10.124 -0.529 10.359 -0.617 10.536 -0.793 c
+10.712 -0.962 10.801 -1.176 10.801 -1.44 c
+10.315 -1.44 l
+10.315 -1.304 10.264 -1.19 10.168 -1.103 c
+10.08 -1.007 9.966 -0.955 9.831 -0.955 c
+9.683 -0.955 9.569 -0.995 9.492 -1.072 c
+9.411 -1.143 9.375 -1.242 9.375 -1.367 c
+9.375 -1.466 9.405 -1.543 9.463 -1.602 c
+9.522 -1.66 9.661 -1.741 9.889 -1.837 c
+10.249 -1.984 10.496 -2.127 10.624 -2.263 c
+10.76 -2.392 10.83 -2.564 10.83 -2.778 c
+10.83 -3.035 10.735 -3.241 10.55 -3.395 c
+10.375 -3.553 10.139 -3.63 9.845 -3.63 c
+9.529 -3.63 9.276 -3.542 9.081 -3.366 c
+8.894 -3.183 8.802 -2.95 8.802 -2.675 c
+9.287 -2.675 l
+9.294 -2.844 9.345 -2.977 9.434 -3.072 c
+9.529 -3.16 9.669 -3.204 9.845 -3.204 c
+9.999 -3.204 10.117 -3.171 10.198 -3.102 c
+10.286 -3.035 10.33 -2.936 10.33 -2.807 c
+14.02 -3.572 m
+13.991 -3.505 13.968 -3.395 13.961 -3.248 c
+13.785 -3.505 13.564 -3.63 13.299 -3.63 c
+13.024 -3.63 12.807 -3.557 12.653 -3.41 c
+12.505 -3.256 12.432 -3.039 12.432 -2.763 c
+12.432 -2.462 12.535 -2.219 12.74 -2.043 c
+12.947 -1.859 13.23 -1.764 13.594 -1.764 c
+13.947 -1.764 l
+13.947 -1.44 l
+13.947 -1.263 13.906 -1.143 13.829 -1.072 c
+13.748 -0.995 13.63 -0.955 13.476 -0.955 c
+13.328 -0.955 13.204 -0.999 13.108 -1.087 c
+13.02 -1.176 12.976 -1.286 12.976 -1.411 c
+12.491 -1.411 l
+12.491 -1.263 12.535 -1.124 12.623 -0.985 c
+12.711 -0.837 12.829 -0.727 12.976 -0.646 c
+13.13 -0.569 13.303 -0.529 13.49 -0.529 c
+13.803 -0.529 14.038 -0.61 14.196 -0.764 c
+14.35 -0.911 14.431 -1.132 14.431 -1.425 c
+14.431 -2.925 l
+14.439 -3.16 14.475 -3.362 14.534 -3.528 c
+14.534 -3.572 l
+h
+13.373 -3.189 m
+13.49 -3.189 13.6 -3.156 13.711 -3.087 c
+13.818 -3.021 13.895 -2.936 13.947 -2.836 c
+13.947 -2.131 l
+13.681 -2.131 l
+13.446 -2.131 13.259 -2.183 13.123 -2.278 c
+12.994 -2.377 12.932 -2.52 12.932 -2.705 c
+12.932 -2.873 12.962 -2.994 13.02 -3.072 c
+13.087 -3.152 13.204 -3.189 13.373 -3.189 c
+16.669 -0.588 m
+16.684 -0.911 l
+16.867 -0.658 17.11 -0.529 17.404 -0.529 c
+17.933 -0.529 18.201 -0.881 18.213 -1.587 c
+18.213 -3.572 l
+17.727 -3.572 l
+17.727 -1.616 l
+17.727 -1.381 17.687 -1.216 17.61 -1.117 c
+17.529 -1.022 17.411 -0.97 17.257 -0.97 c
+17.139 -0.97 17.029 -1.01 16.933 -1.087 c
+16.835 -1.168 16.757 -1.275 16.698 -1.411 c
+16.698 -3.572 l
+16.214 -3.572 l
+16.214 -0.588 l
+h
+18.664 -1.94 m
+18.664 -1.51 18.768 -1.168 18.973 -0.911 c
+19.186 -0.658 19.466 -0.529 19.811 -0.529 c
+20.153 -0.529 20.428 -0.658 20.634 -0.911 c
+20.848 -1.157 20.962 -1.492 20.972 -1.911 c
+20.972 -2.219 l
+20.972 -2.653 20.862 -2.994 20.649 -3.248 c
+20.443 -3.505 20.164 -3.63 19.811 -3.63 c
+19.466 -3.63 19.194 -3.509 18.988 -3.262 c
+18.782 -3.021 18.672 -2.686 18.664 -2.263 c
+h
+19.15 -2.219 m
+19.15 -2.535 19.208 -2.778 19.326 -2.954 c
+19.451 -3.123 19.613 -3.204 19.811 -3.204 c
+20.241 -3.204 20.465 -2.896 20.487 -2.278 c
+20.487 -1.94 l
+20.487 -1.639 20.421 -1.396 20.296 -1.22 c
+20.179 -1.043 20.017 -0.955 19.811 -0.955 c
+19.613 -0.955 19.451 -1.043 19.326 -1.22 c
+19.208 -1.396 19.15 -1.639 19.15 -1.94 c
+h
+22.645 -1.043 m
+22.575 -1.036 22.501 -1.028 22.423 -1.028 c
+22.167 -1.028 21.99 -1.168 21.895 -1.44 c
+21.895 -3.572 l
+21.409 -3.572 l
+21.409 -0.588 l
+21.88 -0.588 l
+21.895 -0.897 l
+22.02 -0.654 22.203 -0.529 22.439 -0.529 c
+22.516 -0.529 22.578 -0.544 22.629 -0.573 c
+h
+23.471 -0.588 m
+23.486 -0.867 l
+23.662 -0.643 23.901 -0.529 24.206 -0.529 c
+24.537 -0.529 24.769 -0.675 24.897 -0.97 c
+25.081 -0.675 25.342 -0.529 25.676 -0.529 c
+26.234 -0.529 26.518 -0.874 26.529 -1.558 c
+26.529 -3.572 l
+26.043 -3.572 l
+26.043 -1.602 l
+26.043 -1.389 26.003 -1.23 25.926 -1.132 c
+25.845 -1.025 25.713 -0.97 25.529 -0.97 c
+25.382 -0.97 25.264 -1.028 25.176 -1.146 c
+25.088 -1.257 25.033 -1.396 25.014 -1.573 c
+25.014 -3.572 l
+24.53 -3.572 l
+24.53 -1.587 l
+24.519 -1.176 24.345 -0.97 24.015 -0.97 c
+23.769 -0.97 23.597 -1.095 23.501 -1.338 c
+23.501 -3.572 l
+23.015 -3.572 l
+23.015 -0.588 l
+h
+28.505 -3.572 m
+28.476 -3.505 28.455 -3.395 28.447 -3.248 c
+28.27 -3.505 28.05 -3.63 27.786 -3.63 c
+27.51 -3.63 27.293 -3.557 27.138 -3.41 c
+26.992 -3.256 26.918 -3.039 26.918 -2.763 c
+26.918 -2.462 27.021 -2.219 27.227 -2.043 c
+27.433 -1.859 27.715 -1.764 28.079 -1.764 c
+28.432 -1.764 l
+28.432 -1.44 l
+28.432 -1.263 28.392 -1.143 28.314 -1.072 c
+28.233 -0.995 28.116 -0.955 27.962 -0.955 c
+27.815 -0.955 27.69 -0.999 27.595 -1.087 c
+27.506 -1.176 27.462 -1.286 27.462 -1.411 c
+26.977 -1.411 l
+26.977 -1.263 27.021 -1.124 27.109 -0.985 c
+27.198 -0.837 27.315 -0.727 27.462 -0.646 c
+27.616 -0.569 27.789 -0.529 27.977 -0.529 c
+28.289 -0.529 28.524 -0.61 28.682 -0.764 c
+28.837 -0.911 28.917 -1.132 28.917 -1.425 c
+28.917 -2.925 l
+28.925 -3.16 28.962 -3.362 29.02 -3.528 c
+29.02 -3.572 l
+h
+27.859 -3.189 m
+27.977 -3.189 28.087 -3.156 28.197 -3.087 c
+28.303 -3.021 28.38 -2.936 28.432 -2.836 c
+28.432 -2.131 l
+28.168 -2.131 l
+27.932 -2.131 27.745 -2.183 27.609 -2.278 c
+27.48 -2.377 27.418 -2.52 27.418 -2.705 c
+27.418 -2.873 27.447 -2.994 27.506 -3.072 c
+27.572 -3.152 27.69 -3.189 27.859 -3.189 c
+30.027 -3.572 -0.5 4.233 re
+32.933 -3.204 m
+33.099 -3.204 33.232 -3.156 33.33 -3.057 c
+33.426 -2.961 33.481 -2.818 33.492 -2.631 c
+33.948 -2.631 l
+33.937 -2.917 33.834 -3.156 33.639 -3.351 c
+33.452 -3.538 33.217 -3.63 32.933 -3.63 c
+32.57 -3.63 32.291 -3.513 32.096 -3.278 c
+31.898 -3.042 31.802 -2.697 31.802 -2.234 c
+31.802 -1.911 l
+31.802 -1.462 31.894 -1.117 32.081 -0.881 c
+32.276 -0.646 32.559 -0.529 32.933 -0.529 c
+33.235 -0.529 33.477 -0.628 33.654 -0.823 c
+33.837 -1.022 33.937 -1.286 33.948 -1.616 c
+33.492 -1.616 l
+33.471 -1.392 33.411 -1.227 33.316 -1.117 c
+33.228 -1.01 33.099 -0.955 32.933 -0.955 c
+32.717 -0.955 32.555 -1.028 32.449 -1.176 c
+32.349 -1.315 32.295 -1.543 32.287 -1.866 c
+32.287 -2.248 l
+32.287 -2.601 32.335 -2.851 32.434 -2.998 c
+32.54 -3.138 32.706 -3.204 32.933 -3.204 c
+34.242 -1.94 m
+34.242 -1.51 34.345 -1.168 34.551 -0.911 c
+34.764 -0.658 35.043 -0.529 35.389 -0.529 c
+35.73 -0.529 36.006 -0.658 36.212 -0.911 c
+36.424 -1.157 36.538 -1.492 36.55 -1.911 c
+36.55 -2.219 l
+36.55 -2.653 36.44 -2.994 36.226 -3.248 c
+36.021 -3.505 35.742 -3.63 35.389 -3.63 c
+35.043 -3.63 34.771 -3.509 34.566 -3.262 c
+34.36 -3.021 34.25 -2.686 34.242 -2.263 c
+h
+34.727 -2.219 m
+34.727 -2.535 34.786 -2.778 34.903 -2.954 c
+35.028 -3.123 35.19 -3.204 35.389 -3.204 c
+35.819 -3.204 36.043 -2.896 36.064 -2.278 c
+36.064 -1.94 l
+36.064 -1.639 35.998 -1.396 35.873 -1.22 c
+35.756 -1.043 35.594 -0.955 35.389 -0.955 c
+35.19 -0.955 35.028 -1.043 34.903 -1.22 c
+34.786 -1.396 34.727 -1.639 34.727 -1.94 c
+h
+37.442 -0.588 m
+37.457 -0.867 l
+37.633 -0.643 37.872 -0.529 38.178 -0.529 c
+38.508 -0.529 38.74 -0.675 38.869 -0.97 c
+39.052 -0.675 39.314 -0.529 39.647 -0.529 c
+40.206 -0.529 40.489 -0.874 40.5 -1.558 c
+40.5 -3.572 l
+40.015 -3.572 l
+40.015 -1.602 l
+40.015 -1.389 39.975 -1.23 39.898 -1.132 c
+39.817 -1.025 39.684 -0.97 39.501 -0.97 c
+39.354 -0.97 39.235 -1.028 39.148 -1.146 c
+39.06 -1.257 39.004 -1.396 38.986 -1.573 c
+38.986 -3.572 l
+38.501 -3.572 l
+38.501 -1.587 l
+38.49 -1.176 38.317 -0.97 37.986 -0.97 c
+37.741 -0.97 37.568 -1.095 37.473 -1.338 c
+37.473 -3.572 l
+36.987 -3.572 l
+36.987 -0.588 l
+h
+41.404 -0.588 m
+41.419 -0.867 l
+41.595 -0.643 41.834 -0.529 42.139 -0.529 c
+42.47 -0.529 42.701 -0.675 42.83 -0.97 c
+43.013 -0.675 43.274 -0.529 43.609 -0.529 c
+44.168 -0.529 44.45 -0.874 44.461 -1.558 c
+44.461 -3.572 l
+43.977 -3.572 l
+43.977 -1.602 l
+43.977 -1.389 43.936 -1.23 43.859 -1.132 c
+43.778 -1.025 43.646 -0.97 43.462 -0.97 c
+43.314 -0.97 43.197 -1.028 43.109 -1.146 c
+43.021 -1.257 42.965 -1.396 42.948 -1.573 c
+42.948 -3.572 l
+42.462 -3.572 l
+42.462 -1.587 l
+42.451 -1.176 42.279 -0.97 41.948 -0.97 c
+41.702 -0.97 41.529 -1.095 41.433 -1.338 c
+41.433 -3.572 l
+40.949 -3.572 l
+40.949 -0.588 l
+h
+45.439 -3.572 -0.5 2.984 re
+45.469 0.206 m
+45.469 0.118 45.442 0.044 45.395 -0.014 c
+45.354 -0.066 45.284 -0.087 45.189 -0.087 c
+45.101 -0.087 45.031 -0.066 44.983 -0.014 c
+44.943 0.044 44.924 0.11 44.924 0.191 c
+44.924 0.279 44.943 0.353 44.983 0.412 c
+45.031 0.47 45.101 0.5 45.189 0.5 c
+45.284 0.5 45.354 0.47 45.395 0.412 c
+45.442 0.353 45.469 0.283 45.469 0.206 c
+46.747 0.133 m
+46.747 -0.588 l
+47.203 -0.588 l
+47.203 -0.985 l
+46.747 -0.985 l
+46.747 -2.836 l
+46.747 -2.954 46.765 -3.042 46.806 -3.102 c
+46.842 -3.16 46.913 -3.189 47.012 -3.189 c
+47.071 -3.189 47.133 -3.183 47.203 -3.16 c
+47.203 -3.572 l
+47.085 -3.609 46.971 -3.63 46.865 -3.63 c
+46.666 -3.63 46.516 -3.564 46.41 -3.424 c
+46.31 -3.289 46.262 -3.094 46.262 -2.836 c
+46.262 -0.985 l
+45.806 -0.985 l
+45.806 -0.588 l
+46.262 -0.588 l
+46.262 0.133 l
+h
+47.669 -4.365 m
+47.376 -4.174 l
+47.552 -3.928 47.644 -3.678 47.655 -3.424 c
+47.655 -2.969 l
+48.155 -2.969 l
+48.155 -3.366 l
+48.155 -3.553 48.103 -3.737 48.008 -3.925 c
+47.919 -4.108 47.806 -4.255 47.669 -4.365 c
+f
+Q
+515.596 100.373 -0.5 2.984 re
+515.625 104.151 m
+515.625 104.063 515.599 103.989 515.551 103.931 c
+515.511 103.879 515.441 103.858 515.345 103.858 c
+515.257 103.858 515.187 103.879 515.139 103.931 c
+515.099 103.989 515.081 104.055 515.081 104.136 c
+515.081 104.225 515.099 104.298 515.139 104.357 c
+515.187 104.415 515.257 104.446 515.345 104.446 c
+515.441 104.446 515.511 104.415 515.551 104.357 c
+515.599 104.298 515.625 104.228 515.625 104.151 c
+516.903 104.078 m
+516.903 103.357 l
+517.36 103.357 l
+517.36 102.96 l
+516.903 102.96 l
+516.903 101.109 l
+516.903 100.991 516.922 100.903 516.963 100.844 c
+516.999 100.785 517.069 100.756 517.169 100.756 c
+517.227 100.756 517.29 100.763 517.36 100.785 c
+517.36 100.373 l
+517.242 100.336 517.128 100.315 517.021 100.315 c
+516.822 100.315 516.672 100.381 516.566 100.521 c
+516.467 100.656 516.419 100.851 516.419 101.109 c
+516.419 102.96 l
+515.963 102.96 l
+515.963 103.357 l
+516.419 103.357 l
+516.419 104.078 l
+h
+519.513 103.049 m
+519.696 103.291 519.932 103.416 520.218 103.416 c
+520.747 103.416 521.016 103.064 521.027 102.358 c
+521.027 100.373 l
+520.542 100.373 l
+520.542 102.329 l
+520.542 102.564 520.502 102.729 520.424 102.828 c
+520.344 102.923 520.226 102.975 520.072 102.975 c
+519.954 102.975 519.843 102.935 519.748 102.858 c
+519.648 102.777 519.571 102.67 519.513 102.534 c
+519.513 100.373 l
+519.028 100.373 l
+519.028 104.606 l
+519.513 104.606 l
+h
+523.099 100.373 m
+523.07 100.44 523.048 100.55 523.041 100.697 c
+522.864 100.44 522.644 100.315 522.379 100.315 c
+522.104 100.315 521.886 100.388 521.732 100.535 c
+521.585 100.689 521.512 100.907 521.512 101.182 c
+521.512 101.483 521.615 101.726 521.821 101.902 c
+522.027 102.086 522.31 102.181 522.673 102.181 c
+523.026 102.181 l
+523.026 102.505 l
+523.026 102.682 522.985 102.802 522.908 102.873 c
+522.827 102.95 522.71 102.99 522.555 102.99 c
+522.409 102.99 522.283 102.946 522.188 102.858 c
+522.1 102.769 522.056 102.659 522.056 102.534 c
+521.57 102.534 l
+521.57 102.682 521.615 102.821 521.703 102.96 c
+521.791 103.108 521.909 103.218 522.056 103.299 c
+522.21 103.376 522.383 103.416 522.57 103.416 c
+522.883 103.416 523.118 103.336 523.276 103.181 c
+523.43 103.034 523.511 102.813 523.511 102.52 c
+523.511 101.02 l
+523.519 100.785 523.555 100.583 523.614 100.417 c
+523.614 100.373 l
+h
+522.453 100.756 m
+522.57 100.756 522.68 100.789 522.79 100.859 c
+522.898 100.924 522.975 101.009 523.026 101.109 c
+523.026 101.814 l
+522.761 101.814 l
+522.526 101.814 522.339 101.763 522.203 101.667 c
+522.075 101.568 522.012 101.425 522.012 101.241 c
+522.012 101.072 522.041 100.951 522.1 100.874 c
+522.166 100.793 522.283 100.756 522.453 100.756 c
+525.532 101.138 m
+525.532 101.244 525.491 101.333 525.414 101.402 c
+525.333 101.479 525.183 101.568 524.959 101.667 c
+524.695 101.774 524.506 101.865 524.4 101.946 c
+524.29 102.023 524.213 102.112 524.165 102.211 c
+524.113 102.306 524.091 102.424 524.091 102.564 c
+524.091 102.806 524.18 103.008 524.356 103.166 c
+524.533 103.332 524.757 103.416 525.032 103.416 c
+525.327 103.416 525.562 103.328 525.738 103.152 c
+525.915 102.983 526.002 102.769 526.002 102.505 c
+525.518 102.505 l
+525.518 102.641 525.466 102.755 525.37 102.843 c
+525.282 102.939 525.169 102.99 525.032 102.99 c
+524.885 102.99 524.772 102.95 524.695 102.873 c
+524.614 102.802 524.577 102.703 524.577 102.578 c
+524.577 102.479 524.606 102.402 524.664 102.343 c
+524.724 102.285 524.863 102.204 525.091 102.108 c
+525.451 101.961 525.697 101.818 525.826 101.682 c
+525.962 101.553 526.032 101.381 526.032 101.167 c
+526.032 100.91 525.936 100.704 525.753 100.55 c
+525.576 100.392 525.341 100.315 525.047 100.315 c
+524.731 100.315 524.477 100.403 524.282 100.579 c
+524.095 100.763 524.003 100.995 524.003 101.271 c
+524.488 101.271 l
+524.496 101.101 524.547 100.969 524.635 100.874 c
+524.731 100.785 524.87 100.741 525.047 100.741 c
+525.202 100.741 525.319 100.774 525.4 100.844 c
+525.488 100.91 525.532 101.009 525.532 101.138 c
+527.59 102.005 m
+527.59 102.435 527.693 102.777 527.899 103.034 c
+528.111 103.288 528.391 103.416 528.737 103.416 c
+529.078 103.416 529.354 103.288 529.56 103.034 c
+529.773 102.788 529.886 102.453 529.898 102.034 c
+529.898 101.726 l
+529.898 101.292 529.788 100.951 529.574 100.697 c
+529.368 100.44 529.09 100.315 528.737 100.315 c
+528.391 100.315 528.119 100.436 527.914 100.683 c
+527.708 100.924 527.598 101.259 527.59 101.682 c
+h
+528.075 101.726 m
+528.075 101.41 528.134 101.167 528.251 100.991 c
+528.377 100.822 528.538 100.741 528.737 100.741 c
+529.167 100.741 529.391 101.05 529.412 101.667 c
+529.412 102.005 l
+529.412 102.306 529.346 102.549 529.221 102.725 c
+529.104 102.902 528.942 102.99 528.737 102.99 c
+528.538 102.99 528.377 102.902 528.251 102.725 c
+528.134 102.549 528.075 102.306 528.075 102.005 c
+h
+530.79 103.357 m
+530.806 103.034 l
+530.989 103.288 531.232 103.416 531.525 103.416 c
+532.055 103.416 532.323 103.064 532.334 102.358 c
+532.334 100.373 l
+531.849 100.373 l
+531.849 102.329 l
+531.849 102.564 531.808 102.729 531.731 102.828 c
+531.65 102.923 531.533 102.975 531.378 102.975 c
+531.261 102.975 531.151 102.935 531.055 102.858 c
+530.956 102.777 530.879 102.67 530.82 102.534 c
+530.82 100.373 l
+530.335 100.373 l
+530.335 103.357 l
+h
+533.948 100.315 m
+533.572 100.315 533.289 100.421 533.094 100.638 c
+532.896 100.862 532.801 101.19 532.801 101.623 c
+532.801 101.99 l
+532.801 102.431 532.893 102.777 533.08 103.034 c
+533.275 103.288 533.551 103.416 533.903 103.416 c
+534.245 103.416 534.499 103.303 534.667 103.078 c
+534.844 102.85 534.935 102.505 534.947 102.034 c
+534.947 101.726 l
+533.285 101.726 l
+533.285 101.653 l
+533.285 101.329 533.345 101.094 533.462 100.947 c
+533.58 100.807 533.749 100.741 533.977 100.741 c
+534.124 100.741 534.249 100.763 534.359 100.814 c
+534.465 100.874 534.569 100.961 534.667 101.079 c
+534.918 100.77 l
+534.711 100.465 534.388 100.315 533.948 100.315 c
+533.903 102.99 m
+533.697 102.99 533.543 102.92 533.447 102.784 c
+533.348 102.644 533.293 102.431 533.285 102.137 c
+534.461 102.137 l
+534.461 102.211 l
+534.44 102.483 534.388 102.682 534.3 102.799 c
+534.212 102.923 534.079 102.99 533.903 102.99 c
+538.706 101.726 m
+538.706 101.256 538.621 100.903 538.457 100.668 c
+538.287 100.432 538.048 100.315 537.736 100.315 c
+537.431 100.315 537.2 100.425 537.045 100.653 c
+537.045 99.227 l
+536.56 99.227 l
+536.56 103.357 l
+537.001 103.357 l
+537.03 103.019 l
+537.185 103.284 537.416 103.416 537.721 103.416 c
+538.052 103.416 538.299 103.299 538.457 103.064 c
+538.621 102.836 538.706 102.497 538.706 102.05 c
+h
+538.221 102.005 m
+538.221 102.336 538.166 102.582 538.06 102.74 c
+537.96 102.894 537.798 102.975 537.574 102.975 c
+537.339 102.975 537.163 102.858 537.045 102.622 c
+537.045 101.079 l
+537.163 100.851 537.343 100.741 537.589 100.741 c
+537.802 100.741 537.96 100.818 538.06 100.976 c
+538.166 101.13 538.221 101.373 538.221 101.697 c
+h
+540.695 100.373 m
+540.664 100.44 540.643 100.55 540.635 100.697 c
+540.459 100.44 540.238 100.315 539.974 100.315 c
+539.698 100.315 539.481 100.388 539.327 100.535 c
+539.18 100.689 539.107 100.907 539.107 101.182 c
+539.107 101.483 539.209 101.726 539.415 101.902 c
+539.621 102.086 539.904 102.181 540.268 102.181 c
+540.62 102.181 l
+540.62 102.505 l
+540.62 102.682 540.58 102.802 540.503 102.873 c
+540.422 102.95 540.304 102.99 540.15 102.99 c
+540.003 102.99 539.878 102.946 539.783 102.858 c
+539.695 102.769 539.65 102.659 539.65 102.534 c
+539.165 102.534 l
+539.165 102.682 539.209 102.821 539.298 102.96 c
+539.386 103.108 539.504 103.218 539.65 103.299 c
+539.805 103.376 539.978 103.416 540.165 103.416 c
+540.477 103.416 540.712 103.336 540.871 103.181 c
+541.025 103.034 541.106 102.813 541.106 102.52 c
+541.106 101.02 l
+541.113 100.785 541.15 100.583 541.208 100.417 c
+541.208 100.373 l
+h
+540.047 100.756 m
+540.165 100.756 540.275 100.789 540.385 100.859 c
+540.492 100.924 540.569 101.009 540.62 101.109 c
+540.62 101.814 l
+540.356 101.814 l
+540.121 101.814 539.934 101.763 539.797 101.667 c
+539.669 101.568 539.606 101.425 539.606 101.241 c
+539.606 101.072 539.635 100.951 539.695 100.874 c
+539.76 100.793 539.878 100.756 540.047 100.756 c
+542.921 102.902 m
+542.851 102.909 542.777 102.917 542.7 102.917 c
+542.443 102.917 542.267 102.777 542.172 102.505 c
+542.172 100.373 l
+541.686 100.373 l
+541.686 103.357 l
+542.156 103.357 l
+542.172 103.049 l
+542.297 103.291 542.48 103.416 542.715 103.416 c
+542.792 103.416 542.855 103.401 542.906 103.372 c
+h
+544.296 100.315 m
+543.92 100.315 543.637 100.421 543.443 100.638 c
+543.244 100.862 543.149 101.19 543.149 101.623 c
+543.149 101.99 l
+543.149 102.431 543.241 102.777 543.428 103.034 c
+543.623 103.288 543.899 103.416 544.252 103.416 c
+544.593 103.416 544.847 103.303 545.015 103.078 c
+545.192 102.85 545.284 102.505 545.295 102.034 c
+545.295 101.726 l
+543.633 101.726 l
+543.633 101.653 l
+543.633 101.329 543.693 101.094 543.81 100.947 c
+543.928 100.807 544.097 100.741 544.325 100.741 c
+544.472 100.741 544.597 100.763 544.707 100.814 c
+544.813 100.874 544.917 100.961 545.015 101.079 c
+545.266 100.77 l
+545.06 100.465 544.736 100.315 544.296 100.315 c
+544.252 102.99 m
+544.046 102.99 543.891 102.92 543.795 102.784 c
+543.697 102.644 543.641 102.431 543.633 102.137 c
+544.809 102.137 l
+544.809 102.211 l
+544.788 102.483 544.736 102.682 544.648 102.799 c
+544.56 102.923 544.427 102.99 544.252 102.99 c
+546.162 103.357 m
+546.177 103.034 l
+546.361 103.288 546.603 103.416 546.897 103.416 c
+547.427 103.416 547.695 103.064 547.706 102.358 c
+547.706 100.373 l
+547.221 100.373 l
+547.221 102.329 l
+547.221 102.564 547.18 102.729 547.103 102.828 c
+547.022 102.923 546.904 102.975 546.75 102.975 c
+546.633 102.975 546.522 102.935 546.427 102.858 c
+546.328 102.777 546.251 102.67 546.191 102.534 c
+546.191 100.373 l
+545.707 100.373 l
+545.707 103.357 l
+h
+548.892 104.078 m
+548.892 103.357 l
+549.349 103.357 l
+549.349 102.96 l
+548.892 102.96 l
+548.892 101.109 l
+548.892 100.991 548.911 100.903 548.951 100.844 c
+548.988 100.785 549.058 100.756 549.158 100.756 c
+549.216 100.756 549.278 100.763 549.349 100.785 c
+549.349 100.373 l
+549.231 100.336 549.117 100.315 549.01 100.315 c
+548.811 100.315 548.661 100.381 548.555 100.521 c
+548.456 100.656 548.408 100.851 548.408 101.109 c
+548.408 102.96 l
+547.951 102.96 l
+547.951 103.357 l
+548.408 103.357 l
+548.408 104.078 l
+h
+f
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 550.895 108.4612 cm
+0 0 m
+5.56 4.844 l
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 554.8461 111.9046 cm
+0 0 m
+-0.104 -1.507 l
+2.009 1.75 l
+-1.504 0.103 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 554.8461 111.9047 cm
+0 0 m
+-0.104 -1.507 l
+2.009 1.75 l
+-1.504 0.103 l
+0 0 l
+h
+S
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 684.3624 112.9743 cm
+0 0 m
+-1.058 0 l
+-1.058 -3.572 l
+-1.558 -3.572 l
+-1.558 0 l
+-2.616 0 l
+-2.616 0.441 l
+0 0.441 l
+h
+0.823 -0.897 m
+1.008 -0.654 1.243 -0.53 1.529 -0.53 c
+2.058 -0.53 2.326 -0.882 2.338 -1.588 c
+2.338 -3.572 l
+1.852 -3.572 l
+1.852 -1.617 l
+1.852 -1.382 1.812 -1.216 1.735 -1.118 c
+1.654 -1.022 1.536 -0.97 1.382 -0.97 c
+1.264 -0.97 1.154 -1.01 1.058 -1.088 c
+0.96 -1.168 0.882 -1.276 0.823 -1.411 c
+0.823 -3.572 l
+0.339 -3.572 l
+0.339 0.661 l
+0.823 0.661 l
+h
+3.406 -3.572 -0.5 2.984 re
+3.437 0.206 m
+3.437 0.118 3.41 0.044 3.362 -0.015 c
+3.323 -0.066 3.252 -0.088 3.157 -0.088 c
+3.069 -0.088 2.999 -0.066 2.951 -0.015 c
+2.911 0.044 2.892 0.11 2.892 0.191 c
+2.892 0.279 2.911 0.353 2.951 0.411 c
+2.999 0.47 3.069 0.5 3.157 0.5 c
+3.252 0.5 3.323 0.47 3.362 0.411 c
+3.41 0.353 3.437 0.283 3.437 0.206 c
+5.523 -2.807 m
+5.523 -2.701 5.483 -2.612 5.405 -2.543 c
+5.325 -2.466 5.174 -2.377 4.95 -2.278 c
+4.686 -2.172 4.499 -2.08 4.391 -1.999 c
+4.281 -1.922 4.204 -1.834 4.156 -1.735 c
+4.105 -1.639 4.083 -1.521 4.083 -1.382 c
+4.083 -1.139 4.171 -0.937 4.347 -0.779 c
+4.524 -0.613 4.748 -0.53 5.024 -0.53 c
+5.318 -0.53 5.553 -0.617 5.729 -0.794 c
+5.906 -0.962 5.993 -1.176 5.993 -1.44 c
+5.509 -1.44 l
+5.509 -1.305 5.457 -1.191 5.361 -1.103 c
+5.274 -1.007 5.16 -0.956 5.024 -0.956 c
+4.877 -0.956 4.763 -0.996 4.686 -1.073 c
+4.605 -1.143 4.568 -1.242 4.568 -1.367 c
+4.568 -1.467 4.597 -1.544 4.656 -1.602 c
+4.715 -1.661 4.854 -1.742 5.083 -1.837 c
+5.442 -1.984 5.689 -2.128 5.818 -2.263 c
+5.953 -2.392 6.024 -2.565 6.024 -2.778 c
+6.024 -3.036 5.928 -3.241 5.744 -3.395 c
+5.567 -3.553 5.332 -3.63 5.039 -3.63 c
+4.723 -3.63 4.469 -3.543 4.274 -3.366 c
+4.087 -3.183 3.994 -2.951 3.994 -2.675 c
+4.48 -2.675 l
+4.487 -2.844 4.538 -2.977 4.627 -3.072 c
+4.723 -3.16 4.862 -3.204 5.039 -3.204 c
+5.193 -3.204 5.31 -3.171 5.391 -3.102 c
+5.479 -3.036 5.523 -2.936 5.523 -2.807 c
+8.214 -3.572 -0.5 2.984 re
+8.243 0.206 m
+8.243 0.118 8.217 0.044 8.169 -0.015 c
+8.129 -0.066 8.059 -0.088 7.963 -0.088 c
+7.875 -0.088 7.805 -0.066 7.757 -0.015 c
+7.717 0.044 7.699 0.11 7.699 0.191 c
+7.699 0.279 7.717 0.353 7.757 0.411 c
+7.805 0.47 7.875 0.5 7.963 0.5 c
+8.059 0.5 8.129 0.47 8.169 0.411 c
+8.217 0.353 8.243 0.283 8.243 0.206 c
+10.326 -2.807 m
+10.326 -2.701 10.286 -2.612 10.209 -2.543 c
+10.128 -2.466 9.978 -2.377 9.753 -2.278 c
+9.488 -2.172 9.301 -2.08 9.195 -1.999 c
+9.084 -1.922 9.007 -1.834 8.96 -1.735 c
+8.908 -1.639 8.886 -1.521 8.886 -1.382 c
+8.886 -1.139 8.974 -0.937 9.151 -0.779 c
+9.327 -0.613 9.551 -0.53 9.827 -0.53 c
+10.12 -0.53 10.356 -0.617 10.533 -0.794 c
+10.708 -0.962 10.797 -1.176 10.797 -1.44 c
+10.311 -1.44 l
+10.311 -1.305 10.26 -1.191 10.165 -1.103 c
+10.076 -1.007 9.962 -0.956 9.827 -0.956 c
+9.679 -0.956 9.565 -0.996 9.488 -1.073 c
+9.407 -1.143 9.371 -1.242 9.371 -1.367 c
+9.371 -1.467 9.4 -1.544 9.459 -1.602 c
+9.517 -1.661 9.658 -1.742 9.885 -1.837 c
+10.246 -1.984 10.492 -2.128 10.62 -2.263 c
+10.756 -2.392 10.826 -2.565 10.826 -2.778 c
+10.826 -3.036 10.73 -3.241 10.547 -3.395 c
+10.371 -3.553 10.136 -3.63 9.841 -3.63 c
+9.525 -3.63 9.272 -3.543 9.077 -3.366 c
+8.889 -3.183 8.798 -2.951 8.798 -2.675 c
+9.282 -2.675 l
+9.29 -2.844 9.342 -2.977 9.43 -3.072 c
+9.525 -3.16 9.665 -3.204 9.841 -3.204 c
+9.995 -3.204 10.113 -3.171 10.194 -3.102 c
+10.282 -3.036 10.326 -2.936 10.326 -2.807 c
+14.016 -3.572 m
+13.986 -3.506 13.964 -3.395 13.957 -3.248 c
+13.781 -3.506 13.56 -3.63 13.295 -3.63 c
+13.02 -3.63 12.803 -3.557 12.649 -3.41 c
+12.502 -3.256 12.428 -3.04 12.428 -2.764 c
+12.428 -2.462 12.532 -2.219 12.737 -2.043 c
+12.943 -1.86 13.226 -1.764 13.59 -1.764 c
+13.943 -1.764 l
+13.943 -1.44 l
+13.943 -1.264 13.902 -1.143 13.825 -1.073 c
+13.744 -0.996 13.627 -0.956 13.472 -0.956 c
+13.325 -0.956 13.2 -1 13.104 -1.088 c
+13.016 -1.176 12.972 -1.286 12.972 -1.411 c
+12.487 -1.411 l
+12.487 -1.264 12.532 -1.124 12.619 -0.985 c
+12.708 -0.838 12.825 -0.727 12.972 -0.647 c
+13.126 -0.57 13.299 -0.53 13.486 -0.53 c
+13.799 -0.53 14.034 -0.61 14.192 -0.765 c
+14.346 -0.912 14.427 -1.132 14.427 -1.426 c
+14.427 -2.925 l
+14.435 -3.16 14.471 -3.362 14.531 -3.528 c
+14.531 -3.572 l
+h
+13.369 -3.19 m
+13.486 -3.19 13.596 -3.157 13.708 -3.087 c
+13.814 -3.021 13.891 -2.936 13.943 -2.837 c
+13.943 -2.132 l
+13.677 -2.132 l
+13.442 -2.132 13.255 -2.183 13.12 -2.278 c
+12.991 -2.377 12.928 -2.521 12.928 -2.705 c
+12.928 -2.874 12.958 -2.995 13.016 -3.072 c
+13.082 -3.153 13.2 -3.19 13.369 -3.19 c
+16.669 -0.588 m
+16.684 -0.867 l
+16.86 -0.643 17.099 -0.53 17.404 -0.53 c
+17.735 -0.53 17.966 -0.676 18.095 -0.97 c
+18.279 -0.676 18.539 -0.53 18.874 -0.53 c
+19.432 -0.53 19.715 -0.875 19.726 -1.558 c
+19.726 -3.572 l
+19.241 -3.572 l
+19.241 -1.602 l
+19.241 -1.389 19.201 -1.231 19.123 -1.132 c
+19.042 -1.025 18.911 -0.97 18.726 -0.97 c
+18.58 -0.97 18.462 -1.029 18.375 -1.147 c
+18.286 -1.257 18.231 -1.396 18.213 -1.573 c
+18.213 -3.572 l
+17.727 -3.572 l
+17.727 -1.588 l
+17.716 -1.176 17.544 -0.97 17.213 -0.97 c
+16.966 -0.97 16.794 -1.095 16.698 -1.338 c
+16.698 -3.572 l
+16.214 -3.572 l
+16.214 -0.588 l
+h
+21.233 -3.63 m
+20.858 -3.63 20.575 -3.524 20.38 -3.308 c
+20.182 -3.083 20.087 -2.756 20.087 -2.323 c
+20.087 -1.955 l
+20.087 -1.514 20.178 -1.168 20.366 -0.912 c
+20.561 -0.658 20.836 -0.53 21.189 -0.53 c
+21.531 -0.53 21.784 -0.643 21.953 -0.867 c
+22.13 -1.095 22.221 -1.44 22.232 -1.911 c
+22.232 -2.219 l
+20.571 -2.219 l
+20.571 -2.294 l
+20.571 -2.616 20.63 -2.851 20.748 -2.999 c
+20.866 -3.138 21.035 -3.204 21.263 -3.204 c
+21.409 -3.204 21.534 -3.183 21.645 -3.131 c
+21.751 -3.072 21.854 -2.984 21.953 -2.866 c
+22.203 -3.175 l
+21.997 -3.48 21.674 -3.63 21.233 -3.63 c
+21.189 -0.956 m
+20.983 -0.956 20.829 -1.025 20.733 -1.161 c
+20.634 -1.301 20.579 -1.514 20.571 -1.808 c
+21.747 -1.808 l
+21.747 -1.735 l
+21.725 -1.463 21.674 -1.264 21.586 -1.147 c
+21.498 -1.022 21.365 -0.956 21.189 -0.956 c
+23.879 -1.043 m
+23.809 -1.037 23.736 -1.029 23.659 -1.029 c
+23.401 -1.029 23.225 -1.168 23.129 -1.44 c
+23.129 -3.572 l
+22.645 -3.572 l
+22.645 -0.588 l
+23.115 -0.588 l
+23.129 -0.897 l
+23.254 -0.654 23.438 -0.53 23.673 -0.53 c
+23.75 -0.53 23.813 -0.544 23.864 -0.573 c
+h
+24.096 -1.941 m
+24.096 -1.481 24.176 -1.132 24.345 -0.897 c
+24.522 -0.654 24.772 -0.53 25.095 -0.53 c
+25.396 -0.53 25.628 -0.661 25.786 -0.926 c
+25.816 -0.588 l
+26.256 -0.588 l
+26.256 -3.601 l
+26.256 -3.973 26.157 -4.255 25.963 -4.453 c
+25.775 -4.648 25.514 -4.748 25.184 -4.748 c
+25.037 -4.748 24.868 -4.707 24.684 -4.63 c
+24.496 -4.561 24.36 -4.472 24.272 -4.366 c
+24.463 -4.027 l
+24.669 -4.233 24.893 -4.336 25.139 -4.336 c
+25.54 -4.336 25.745 -4.108 25.756 -3.66 c
+25.756 -3.278 l
+25.598 -3.513 25.378 -3.63 25.095 -3.63 c
+24.779 -3.63 24.536 -3.513 24.36 -3.278 c
+24.191 -3.042 24.103 -2.712 24.096 -2.278 c
+h
+24.581 -2.219 m
+24.581 -2.554 24.629 -2.801 24.727 -2.955 c
+24.823 -3.113 24.985 -3.19 25.213 -3.19 c
+25.456 -3.19 25.639 -3.069 25.756 -2.822 c
+25.756 -1.338 l
+25.639 -1.095 25.463 -0.97 25.228 -0.97 c
+24.999 -0.97 24.838 -1.051 24.742 -1.205 c
+24.644 -1.363 24.588 -1.602 24.581 -1.926 c
+h
+27.848 -3.63 m
+27.472 -3.63 27.19 -3.524 26.995 -3.308 c
+26.797 -3.083 26.701 -2.756 26.701 -2.323 c
+26.701 -1.955 l
+26.701 -1.514 26.793 -1.168 26.98 -0.912 c
+27.175 -0.658 27.451 -0.53 27.804 -0.53 c
+28.145 -0.53 28.399 -0.643 28.567 -0.867 c
+28.744 -1.095 28.836 -1.44 28.847 -1.911 c
+28.847 -2.219 l
+27.186 -2.219 l
+27.186 -2.294 l
+27.186 -2.616 27.245 -2.851 27.362 -2.999 c
+27.48 -3.138 27.649 -3.204 27.877 -3.204 c
+28.024 -3.204 28.149 -3.183 28.259 -3.131 c
+28.366 -3.072 28.469 -2.984 28.567 -2.866 c
+28.818 -3.175 l
+28.612 -3.48 28.289 -3.63 27.848 -3.63 c
+27.804 -0.956 m
+27.598 -0.956 27.443 -1.025 27.348 -1.161 c
+27.248 -1.301 27.193 -1.514 27.186 -1.808 c
+28.362 -1.808 l
+28.362 -1.735 l
+28.34 -1.463 28.289 -1.264 28.201 -1.147 c
+28.112 -1.022 27.979 -0.956 27.804 -0.956 c
+31.493 -3.204 m
+31.659 -3.204 31.79 -3.157 31.89 -3.057 c
+31.985 -2.961 32.041 -2.818 32.052 -2.631 c
+32.507 -2.631 l
+32.496 -2.918 32.393 -3.157 32.199 -3.352 c
+32.012 -3.539 31.776 -3.63 31.493 -3.63 c
+31.129 -3.63 30.85 -3.513 30.655 -3.278 c
+30.456 -3.042 30.361 -2.697 30.361 -2.234 c
+30.361 -1.911 l
+30.361 -1.463 30.453 -1.118 30.641 -0.882 c
+30.836 -0.647 31.118 -0.53 31.493 -0.53 c
+31.794 -0.53 32.037 -0.628 32.213 -0.823 c
+32.397 -1.022 32.496 -1.286 32.507 -1.617 c
+32.052 -1.617 l
+32.029 -1.393 31.971 -1.228 31.875 -1.118 c
+31.787 -1.01 31.659 -0.956 31.493 -0.956 c
+31.276 -0.956 31.114 -1.029 31.008 -1.176 c
+30.909 -1.315 30.853 -1.544 30.846 -1.866 c
+30.846 -2.249 l
+30.846 -2.602 30.894 -2.851 30.994 -2.999 c
+31.1 -3.138 31.266 -3.204 31.493 -3.204 c
+32.801 -1.941 m
+32.801 -1.511 32.904 -1.168 33.11 -0.912 c
+33.323 -0.658 33.602 -0.53 33.948 -0.53 c
+34.289 -0.53 34.565 -0.658 34.771 -0.912 c
+34.984 -1.158 35.098 -1.492 35.109 -1.911 c
+35.109 -2.219 l
+35.109 -2.653 34.998 -2.995 34.786 -3.248 c
+34.58 -3.506 34.3 -3.63 33.948 -3.63 c
+33.602 -3.63 33.33 -3.51 33.124 -3.263 c
+32.918 -3.021 32.808 -2.687 32.801 -2.263 c
+h
+33.286 -2.219 m
+33.286 -2.535 33.345 -2.778 33.463 -2.955 c
+33.587 -3.123 33.749 -3.204 33.948 -3.204 c
+34.377 -3.204 34.602 -2.896 34.624 -2.278 c
+34.624 -1.941 l
+34.624 -1.639 34.558 -1.396 34.433 -1.22 c
+34.315 -1.043 34.154 -0.956 33.948 -0.956 c
+33.749 -0.956 33.587 -1.043 33.463 -1.22 c
+33.345 -1.396 33.286 -1.639 33.286 -1.941 c
+h
+36.002 -0.588 m
+36.016 -0.867 l
+36.193 -0.643 36.432 -0.53 36.737 -0.53 c
+37.068 -0.53 37.299 -0.676 37.427 -0.97 c
+37.612 -0.676 37.872 -0.53 38.207 -0.53 c
+38.765 -0.53 39.048 -0.875 39.06 -1.558 c
+39.06 -3.572 l
+38.574 -3.572 l
+38.574 -1.602 l
+38.574 -1.389 38.534 -1.231 38.456 -1.132 c
+38.376 -1.025 38.244 -0.97 38.06 -0.97 c
+37.913 -0.97 37.795 -1.029 37.707 -1.147 c
+37.619 -1.257 37.564 -1.396 37.545 -1.573 c
+37.545 -3.572 l
+37.06 -3.572 l
+37.06 -1.588 l
+37.049 -1.176 36.876 -0.97 36.546 -0.97 c
+36.299 -0.97 36.127 -1.095 36.031 -1.338 c
+36.031 -3.572 l
+35.546 -3.572 l
+35.546 -0.588 l
+h
+39.964 -0.588 m
+39.978 -0.867 l
+40.155 -0.643 40.393 -0.53 40.698 -0.53 c
+41.029 -0.53 41.261 -0.676 41.389 -0.97 c
+41.573 -0.676 41.834 -0.53 42.168 -0.53 c
+42.727 -0.53 43.01 -0.875 43.021 -1.558 c
+43.021 -3.572 l
+42.536 -3.572 l
+42.536 -1.602 l
+42.536 -1.389 42.495 -1.231 42.418 -1.132 c
+42.337 -1.025 42.205 -0.97 42.021 -0.97 c
+41.874 -0.97 41.757 -1.029 41.668 -1.147 c
+41.58 -1.257 41.525 -1.396 41.506 -1.573 c
+41.506 -3.572 l
+41.022 -3.572 l
+41.022 -1.588 l
+41.011 -1.176 40.837 -0.97 40.507 -0.97 c
+40.261 -0.97 40.089 -1.095 39.993 -1.338 c
+39.993 -3.572 l
+39.507 -3.572 l
+39.507 -0.588 l
+h
+43.998 -3.572 -0.5 2.984 re
+44.028 0.206 m
+44.028 0.118 44.002 0.044 43.954 -0.015 c
+43.914 -0.066 43.844 -0.088 43.748 -0.088 c
+43.66 -0.088 43.59 -0.066 43.542 -0.015 c
+43.502 0.044 43.484 0.11 43.484 0.191 c
+43.484 0.279 43.502 0.353 43.542 0.411 c
+43.59 0.47 43.66 0.5 43.748 0.5 c
+43.844 0.5 43.914 0.47 43.954 0.411 c
+44.002 0.353 44.028 0.283 44.028 0.206 c
+45.306 0.133 m
+45.306 -0.588 l
+45.762 -0.588 l
+45.762 -0.985 l
+45.306 -0.985 l
+45.306 -2.837 l
+45.306 -2.955 45.325 -3.042 45.365 -3.102 c
+45.402 -3.16 45.472 -3.19 45.571 -3.19 c
+45.63 -3.19 45.693 -3.183 45.762 -3.16 c
+45.762 -3.572 l
+45.645 -3.609 45.531 -3.63 45.424 -3.63 c
+45.225 -3.63 45.075 -3.564 44.968 -3.425 c
+44.87 -3.289 44.822 -3.094 44.822 -2.837 c
+44.822 -0.985 l
+44.365 -0.985 l
+44.365 -0.588 l
+44.822 -0.588 l
+44.822 0.133 l
+h
+46.229 -4.366 m
+45.934 -4.175 l
+46.111 -3.929 46.203 -3.678 46.214 -3.425 c
+46.214 -2.969 l
+46.713 -2.969 l
+46.713 -3.366 l
+46.713 -3.553 46.663 -3.738 46.567 -3.925 c
+46.478 -4.108 46.364 -4.255 46.229 -4.366 c
+f
+Q
+693.76 102.817 -0.501 2.984 re
+693.789 106.595 m
+693.789 106.507 693.762 106.433 693.715 106.374 c
+693.675 106.323 693.604 106.301 693.509 106.301 c
+693.421 106.301 693.351 106.323 693.303 106.374 c
+693.263 106.433 693.245 106.499 693.245 106.58 c
+693.245 106.669 693.263 106.742 693.303 106.8 c
+693.351 106.86 693.421 106.889 693.509 106.889 c
+693.604 106.889 693.675 106.86 693.715 106.8 c
+693.762 106.742 693.789 106.672 693.789 106.595 c
+695.063 106.522 m
+695.063 105.801 l
+695.52 105.801 l
+695.52 105.404 l
+695.063 105.404 l
+695.063 103.552 l
+695.063 103.434 695.082 103.347 695.123 103.288 c
+695.159 103.229 695.229 103.199 695.328 103.199 c
+695.387 103.199 695.449 103.207 695.52 103.229 c
+695.52 102.817 l
+695.402 102.78 695.288 102.759 695.181 102.759 c
+694.982 102.759 694.832 102.825 694.726 102.964 c
+694.626 103.1 694.579 103.295 694.579 103.552 c
+694.579 105.404 l
+694.123 105.404 l
+694.123 105.801 l
+694.579 105.801 l
+694.579 106.522 l
+h
+697.677 105.493 m
+697.86 105.735 698.095 105.86 698.382 105.86 c
+698.911 105.86 699.179 105.507 699.19 104.801 c
+699.19 102.817 l
+698.705 102.817 l
+698.705 104.772 l
+698.705 105.007 698.664 105.173 698.587 105.272 c
+698.506 105.368 698.389 105.419 698.235 105.419 c
+698.117 105.419 698.007 105.379 697.912 105.302 c
+697.812 105.221 697.735 105.114 697.677 104.978 c
+697.677 102.817 l
+697.191 102.817 l
+697.191 107.051 l
+697.677 107.051 l
+h
+701.259 102.817 m
+701.23 102.883 701.207 102.994 701.201 103.141 c
+701.024 102.883 700.804 102.759 700.539 102.759 c
+700.264 102.759 700.046 102.832 699.892 102.979 c
+699.745 103.133 699.672 103.35 699.672 103.625 c
+699.672 103.927 699.775 104.17 699.981 104.346 c
+700.187 104.529 700.469 104.625 700.833 104.625 c
+701.186 104.625 l
+701.186 104.949 l
+701.186 105.125 701.145 105.246 701.068 105.316 c
+700.987 105.393 700.87 105.433 700.715 105.433 c
+700.569 105.433 700.443 105.389 700.347 105.302 c
+700.26 105.213 700.216 105.103 700.216 104.978 c
+699.73 104.978 l
+699.73 105.125 699.775 105.265 699.863 105.404 c
+699.951 105.551 700.069 105.662 700.216 105.742 c
+700.37 105.819 700.542 105.86 700.73 105.86 c
+701.043 105.86 701.278 105.78 701.436 105.624 c
+701.59 105.478 701.671 105.257 701.671 104.963 c
+701.671 103.464 l
+701.678 103.229 701.715 103.027 701.774 102.861 c
+701.774 102.817 l
+h
+700.613 103.199 m
+700.73 103.199 700.84 103.232 700.951 103.303 c
+701.057 103.368 701.134 103.453 701.186 103.552 c
+701.186 104.257 l
+700.921 104.257 l
+700.686 104.257 700.499 104.207 700.363 104.111 c
+700.234 104.012 700.172 103.868 700.172 103.685 c
+700.172 103.515 700.201 103.394 700.26 103.317 c
+700.326 103.236 700.443 103.199 700.613 103.199 c
+703.692 103.582 m
+703.692 103.688 703.651 103.777 703.574 103.846 c
+703.493 103.923 703.343 104.012 703.119 104.111 c
+702.854 104.217 702.666 104.309 702.56 104.39 c
+702.45 104.467 702.373 104.556 702.325 104.654 c
+702.273 104.75 702.252 104.868 702.252 105.007 c
+702.252 105.25 702.34 105.452 702.516 105.61 c
+702.693 105.776 702.917 105.86 703.192 105.86 c
+703.486 105.86 703.721 105.772 703.898 105.595 c
+704.074 105.427 704.162 105.213 704.162 104.949 c
+703.678 104.949 l
+703.678 105.084 703.626 105.198 703.53 105.287 c
+703.443 105.383 703.328 105.433 703.192 105.433 c
+703.046 105.433 702.932 105.393 702.854 105.316 c
+702.774 105.246 702.737 105.147 702.737 105.022 c
+702.737 104.923 702.766 104.845 702.824 104.787 c
+702.884 104.728 703.023 104.647 703.251 104.552 c
+703.611 104.405 703.857 104.261 703.986 104.126 c
+704.122 103.997 704.191 103.824 704.191 103.611 c
+704.191 103.353 704.096 103.148 703.913 102.994 c
+703.736 102.836 703.501 102.759 703.207 102.759 c
+702.891 102.759 702.637 102.846 702.443 103.023 c
+702.255 103.207 702.163 103.438 702.163 103.714 c
+702.648 103.714 l
+702.656 103.545 702.707 103.413 702.795 103.317 c
+702.891 103.229 703.03 103.185 703.207 103.185 c
+703.362 103.185 703.479 103.218 703.559 103.288 c
+703.648 103.353 703.692 103.453 703.692 103.582 c
+706.485 106.522 m
+706.485 105.801 l
+706.94 105.801 l
+706.94 105.404 l
+706.485 105.404 l
+706.485 103.552 l
+706.485 103.434 706.503 103.347 706.543 103.288 c
+706.58 103.229 706.65 103.199 706.749 103.199 c
+706.808 103.199 706.871 103.207 706.94 103.229 c
+706.94 102.817 l
+706.823 102.78 706.709 102.759 706.602 102.759 c
+706.404 102.759 706.253 102.825 706.146 102.964 c
+706.047 103.1 705.999 103.295 705.999 103.552 c
+705.999 105.404 l
+705.544 105.404 l
+705.544 105.801 l
+705.999 105.801 l
+705.999 106.522 l
+h
+709.627 103.669 m
+710.082 105.801 l
+710.568 105.801 l
+709.832 102.817 l
+709.45 102.817 l
+708.862 104.949 l
+708.289 102.817 l
+707.907 102.817 l
+707.172 105.801 l
+707.657 105.801 l
+708.127 103.729 l
+708.671 105.801 l
+709.053 105.801 l
+h
+710.733 104.448 m
+710.733 104.878 710.836 105.221 711.042 105.478 c
+711.254 105.732 711.534 105.86 711.879 105.86 c
+712.221 105.86 712.496 105.732 712.702 105.478 c
+712.916 105.231 713.03 104.897 713.041 104.479 c
+713.041 104.17 l
+713.041 103.736 712.93 103.394 712.717 103.141 c
+712.511 102.883 712.232 102.759 711.879 102.759 c
+711.534 102.759 711.262 102.879 711.056 103.126 c
+710.85 103.368 710.74 103.702 710.733 104.126 c
+h
+711.218 104.17 m
+711.218 103.854 711.277 103.611 711.395 103.434 c
+711.519 103.266 711.681 103.185 711.879 103.185 c
+712.309 103.185 712.534 103.494 712.555 104.111 c
+712.555 104.448 l
+712.555 104.75 712.49 104.993 712.365 105.169 c
+712.247 105.346 712.085 105.433 711.879 105.433 c
+711.681 105.433 711.519 105.346 711.395 105.169 c
+711.277 104.993 711.218 104.75 711.218 104.448 c
+h
+716.829 104.17 m
+716.829 103.7 716.745 103.347 716.579 103.112 c
+716.411 102.876 716.172 102.759 715.859 102.759 c
+715.554 102.759 715.322 102.869 715.168 103.097 c
+715.168 101.67 l
+714.683 101.67 l
+714.683 105.801 l
+715.124 105.801 l
+715.154 105.463 l
+715.308 105.728 715.539 105.86 715.844 105.86 c
+716.175 105.86 716.421 105.742 716.579 105.507 c
+716.745 105.279 716.829 104.941 716.829 104.493 c
+h
+716.344 104.448 m
+716.344 104.78 716.289 105.026 716.182 105.184 c
+716.083 105.338 715.921 105.419 715.698 105.419 c
+715.462 105.419 715.285 105.302 715.168 105.066 c
+715.168 103.523 l
+715.285 103.295 715.466 103.185 715.712 103.185 c
+715.925 103.185 716.083 103.262 716.182 103.42 c
+716.289 103.574 716.344 103.817 716.344 104.14 c
+h
+718.813 102.817 m
+718.784 102.883 718.762 102.994 718.755 103.141 c
+718.578 102.883 718.358 102.759 718.094 102.759 c
+717.818 102.759 717.601 102.832 717.446 102.979 c
+717.3 103.133 717.226 103.35 717.226 103.625 c
+717.226 103.927 717.329 104.17 717.535 104.346 c
+717.741 104.529 718.024 104.625 718.387 104.625 c
+718.74 104.625 l
+718.74 104.949 l
+718.74 105.125 718.699 105.246 718.622 105.316 c
+718.541 105.393 718.424 105.433 718.269 105.433 c
+718.123 105.433 717.998 105.389 717.903 105.302 c
+717.814 105.213 717.77 105.103 717.77 104.978 c
+717.285 104.978 l
+717.285 105.125 717.329 105.265 717.417 105.404 c
+717.506 105.551 717.623 105.662 717.77 105.742 c
+717.924 105.819 718.097 105.86 718.285 105.86 c
+718.597 105.86 718.832 105.78 718.99 105.624 c
+719.144 105.478 719.225 105.257 719.225 104.963 c
+719.225 103.464 l
+719.233 103.229 719.27 103.027 719.328 102.861 c
+719.328 102.817 l
+h
+718.167 103.199 m
+718.285 103.199 718.395 103.232 718.505 103.303 c
+718.611 103.368 718.689 103.453 718.74 103.552 c
+718.74 104.257 l
+718.476 104.257 l
+718.24 104.257 718.053 104.207 717.917 104.111 c
+717.789 104.012 717.726 103.868 717.726 103.685 c
+717.726 103.515 717.755 103.394 717.814 103.317 c
+717.88 103.236 717.998 103.199 718.167 103.199 c
+721.041 105.346 m
+720.97 105.352 720.897 105.36 720.82 105.36 c
+720.563 105.36 720.386 105.221 720.291 104.949 c
+720.291 102.817 l
+719.806 102.817 l
+719.806 105.801 l
+720.276 105.801 l
+720.291 105.493 l
+720.415 105.735 720.6 105.86 720.835 105.86 c
+720.912 105.86 720.974 105.845 721.026 105.816 c
+h
+722.418 102.759 m
+722.044 102.759 721.761 102.865 721.566 103.082 c
+721.367 103.306 721.272 103.633 721.272 104.066 c
+721.272 104.434 l
+721.272 104.876 721.364 105.221 721.552 105.478 c
+721.747 105.732 722.022 105.86 722.374 105.86 c
+722.716 105.86 722.969 105.746 723.139 105.522 c
+723.315 105.294 723.407 104.949 723.418 104.479 c
+723.418 104.17 l
+721.757 104.17 l
+721.757 104.096 l
+721.757 103.773 721.816 103.538 721.934 103.39 c
+722.051 103.251 722.22 103.185 722.448 103.185 c
+722.595 103.185 722.72 103.207 722.83 103.258 c
+722.936 103.317 723.04 103.405 723.139 103.523 c
+723.389 103.214 l
+723.183 102.909 722.859 102.759 722.418 102.759 c
+722.374 105.433 m
+722.169 105.433 722.015 105.364 721.919 105.228 c
+721.82 105.088 721.764 104.876 721.757 104.581 c
+722.933 104.581 l
+722.933 104.654 l
+722.911 104.926 722.859 105.125 722.771 105.242 c
+722.683 105.368 722.551 105.433 722.374 105.433 c
+724.286 105.801 m
+724.3 105.478 l
+724.484 105.732 724.726 105.86 725.02 105.86 c
+725.55 105.86 725.818 105.507 725.828 104.801 c
+725.828 102.817 l
+725.344 102.817 l
+725.344 104.772 l
+725.344 105.007 725.303 105.173 725.226 105.272 c
+725.145 105.368 725.028 105.419 724.873 105.419 c
+724.756 105.419 724.646 105.379 724.55 105.302 c
+724.451 105.221 724.374 105.114 724.315 104.978 c
+724.315 102.817 l
+723.829 102.817 l
+723.829 105.801 l
+h
+727.012 106.522 m
+727.012 105.801 l
+727.468 105.801 l
+727.468 105.404 l
+727.012 105.404 l
+727.012 103.552 l
+727.012 103.434 727.031 103.347 727.071 103.288 c
+727.108 103.229 727.177 103.199 727.276 103.199 c
+727.335 103.199 727.397 103.207 727.468 103.229 c
+727.468 102.817 l
+727.35 102.78 727.236 102.759 727.129 102.759 c
+726.931 102.759 726.78 102.825 726.674 102.964 c
+726.574 103.1 726.527 103.295 726.527 103.552 c
+726.527 105.404 l
+726.071 105.404 l
+726.071 105.801 l
+726.527 105.801 l
+726.527 106.522 l
+h
+729.375 103.582 m
+729.375 103.688 729.334 103.777 729.257 103.846 c
+729.176 103.923 729.026 104.012 728.802 104.111 c
+728.537 104.217 728.35 104.309 728.243 104.39 c
+728.133 104.467 728.056 104.556 728.008 104.654 c
+727.956 104.75 727.935 104.868 727.935 105.007 c
+727.935 105.25 728.022 105.452 728.199 105.61 c
+728.375 105.776 728.6 105.86 728.875 105.86 c
+729.169 105.86 729.404 105.772 729.581 105.595 c
+729.757 105.427 729.845 105.213 729.845 104.949 c
+729.36 104.949 l
+729.36 105.084 729.309 105.198 729.213 105.287 c
+729.125 105.383 729.011 105.433 728.875 105.433 c
+728.728 105.433 728.614 105.393 728.537 105.316 c
+728.456 105.246 728.419 105.147 728.419 105.022 c
+728.419 104.923 728.449 104.845 728.508 104.787 c
+728.567 104.728 728.706 104.647 728.934 104.552 c
+729.294 104.405 729.541 104.261 729.668 104.126 c
+729.805 103.997 729.874 103.824 729.874 103.611 c
+729.874 103.353 729.779 103.148 729.595 102.994 c
+729.419 102.836 729.184 102.759 728.889 102.759 c
+728.573 102.759 728.32 102.846 728.126 103.023 c
+727.938 103.207 727.846 103.438 727.846 103.714 c
+728.332 103.714 l
+728.338 103.545 728.39 103.413 728.478 103.317 c
+728.573 103.229 728.714 103.185 728.889 103.185 c
+729.044 103.185 729.161 103.218 729.242 103.288 c
+729.331 103.353 729.375 103.453 729.375 103.582 c
+730.878 103.949 m
+730.437 103.949 l
+730.408 106.83 l
+730.922 106.83 l
+h
+730.672 103.361 m
+730.767 103.361 730.838 103.332 730.878 103.272 c
+730.925 103.222 730.952 103.155 730.952 103.067 c
+730.952 102.987 730.925 102.92 730.878 102.861 c
+730.838 102.813 730.767 102.788 730.672 102.788 c
+730.584 102.788 730.514 102.813 730.466 102.861 c
+730.414 102.92 730.393 102.987 730.393 103.067 c
+730.393 103.155 730.414 103.222 730.466 103.272 c
+730.514 103.332 730.584 103.361 730.672 103.361 c
+f
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 734.152 110.909 cm
+0 0 m
+5.56 4.843 l
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 738.1018 114.3481 cm
+0 0 m
+-0.103 -1.502 l
+2.01 1.753 l
+-1.507 0.107 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 738.1018 114.3482 cm
+0 0 m
+-0.103 -1.502 l
+2.01 1.753 l
+-1.506 0.107 l
+0 0 l
+h
+S
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 767.8644 128.2905 cm
+0 0 m
+-0.008 16.393 l
+6.46 16.393 l
+6.468 0 l
+3.227 -3.564 l
+h
+f
+Q
+0 0 0 0 k
+q 1 0 0 1 772.5238 142.4204 cm
+0 0 m
+-0.279 -0.03 l
+-0.055 -0.206 0.059 -0.434 0.059 -0.721 c
+0.059 -1.014 -0.081 -1.224 -0.353 -1.353 c
+-0.081 -1.518 0.059 -1.756 0.059 -2.072 c
+0.059 -2.602 -0.305 -2.87 -1.029 -2.881 c
+-2.984 -2.881 l
+-2.984 -2.103 l
+-1.073 -2.103 l
+-0.908 -2.103 -0.79 -2.076 -0.721 -2.029 c
+-0.643 -1.977 -0.603 -1.9 -0.603 -1.794 c
+-0.603 -1.646 -0.69 -1.532 -0.867 -1.455 c
+-0.956 -1.47 l
+-2.984 -1.47 l
+-2.984 -0.691 l
+-1.087 -0.691 l
+-0.912 -0.691 -0.79 -0.665 -0.721 -0.618 c
+-0.643 -0.566 -0.603 -0.485 -0.603 -0.368 c
+-0.603 -0.239 -0.676 -0.136 -0.823 -0.059 c
+-2.984 -0.059 l
+-2.984 0.72 l
+0 0.72 l
+h
+-2.984 -4.601 m
+-2.936 -4.572 -2.859 -4.546 -2.749 -4.528 c
+-2.947 -4.388 -3.042 -4.204 -3.042 -3.969 c
+-3.042 -3.712 -2.961 -3.502 -2.793 -3.337 c
+-2.627 -3.179 -2.41 -3.102 -2.146 -3.102 c
+-1.833 -3.102 -1.594 -3.198 -1.426 -3.396 c
+-1.249 -3.591 -1.161 -3.873 -1.161 -4.248 c
+-1.161 -4.499 l
+-0.926 -4.499 l
+-0.79 -4.499 -0.698 -4.472 -0.646 -4.424 c
+-0.588 -4.374 -0.559 -4.307 -0.559 -4.219 c
+-0.559 -4.021 -0.673 -3.925 -0.896 -3.925 c
+-0.896 -3.146 l
+-0.625 -3.146 -0.397 -3.248 -0.22 -3.454 c
+-0.037 -3.66 0.059 -3.925 0.059 -4.248 c
+0.059 -4.572 -0.029 -4.821 -0.206 -4.998 c
+-0.374 -5.182 -0.613 -5.278 -0.926 -5.278 c
+-2.337 -5.278 l
+-2.595 -5.278 -2.793 -5.31 -2.94 -5.38 c
+-2.984 -5.38 l
+h
+-2.425 -4.131 m
+-2.425 -4.219 -2.41 -4.293 -2.381 -4.351 c
+-2.344 -4.418 -2.3 -4.469 -2.249 -4.499 c
+-1.631 -4.499 l
+-1.631 -4.307 l
+-1.631 -4.167 -1.675 -4.061 -1.764 -3.984 c
+-1.845 -3.913 -1.955 -3.881 -2.102 -3.881 c
+-2.319 -3.881 -2.425 -3.961 -2.425 -4.131 c
+-2.19 -6.978 m
+-2.124 -6.978 -2.057 -6.942 -1.999 -6.876 c
+-1.94 -6.817 -1.866 -6.677 -1.779 -6.464 c
+-1.643 -6.141 -1.506 -5.92 -1.367 -5.802 c
+-1.231 -5.685 -1.058 -5.627 -0.852 -5.627 c
+-0.588 -5.627 -0.374 -5.718 -0.206 -5.906 c
+-0.029 -6.089 0.059 -6.34 0.059 -6.655 c
+0.059 -6.978 -0.029 -7.236 -0.206 -7.435 c
+-0.374 -7.629 -0.599 -7.728 -0.881 -7.728 c
+-0.881 -6.949 l
+-0.64 -6.949 -0.515 -6.847 -0.515 -6.641 c
+-0.515 -6.56 -0.544 -6.494 -0.603 -6.435 c
+-0.654 -6.383 -0.721 -6.361 -0.808 -6.361 c
+-0.878 -6.361 -0.937 -6.39 -0.985 -6.45 c
+-1.036 -6.508 -1.11 -6.644 -1.205 -6.861 c
+-1.323 -7.184 -1.455 -7.408 -1.602 -7.537 c
+-1.741 -7.674 -1.926 -7.743 -2.161 -7.743 c
+-2.425 -7.743 -2.643 -7.64 -2.807 -7.435 c
+-2.965 -7.236 -3.042 -6.978 -3.042 -6.655 c
+-3.042 -6.427 -2.998 -6.232 -2.911 -6.067 c
+-2.822 -5.898 -2.705 -5.766 -2.558 -5.671 c
+-2.404 -5.582 -2.234 -5.538 -2.057 -5.538 c
+-2.057 -6.273 l
+-2.198 -6.28 -2.3 -6.317 -2.367 -6.376 c
+-2.436 -6.435 -2.469 -6.531 -2.469 -6.67 c
+-2.469 -6.876 -2.377 -6.978 -2.19 -6.978 c
+0.735 -8.967 m
+0 -8.967 l
+0 -9.363 l
+-0.588 -9.363 l
+-0.588 -8.967 l
+-2.072 -8.967 l
+-2.19 -8.967 -2.275 -8.981 -2.323 -9.01 c
+-2.363 -9.047 -2.381 -9.114 -2.381 -9.202 c
+-2.381 -9.279 -2.373 -9.342 -2.352 -9.393 c
+-2.969 -9.378 l
+-3.017 -9.249 -3.042 -9.106 -3.042 -8.952 c
+-3.042 -8.453 -2.756 -8.195 -2.175 -8.187 c
+-0.588 -8.187 l
+-0.588 -7.85 l
+0 -7.85 l
+0 -8.187 l
+0.735 -8.187 l
+h
+-3.042 -10.874 m
+-3.042 -10.469 -2.925 -10.157 -2.69 -9.933 c
+-2.447 -9.716 -2.102 -9.61 -1.661 -9.61 c
+-1.411 -9.61 l
+-0.941 -9.61 -0.58 -9.712 -0.324 -9.918 c
+-0.07 -10.124 0.059 -10.418 0.059 -10.801 c
+0.059 -11.171 -0.066 -11.451 -0.309 -11.638 c
+-0.544 -11.833 -0.896 -11.932 -1.367 -11.932 c
+-1.749 -11.932 l
+-1.749 -10.389 l
+-1.976 -10.396 -2.142 -10.44 -2.249 -10.521 c
+-2.348 -10.61 -2.396 -10.745 -2.396 -10.932 c
+-2.396 -11.186 -2.304 -11.403 -2.117 -11.58 c
+-2.602 -11.888 l
+-2.73 -11.789 -2.837 -11.645 -2.925 -11.462 c
+-3.002 -11.285 -3.042 -11.087 -3.042 -10.874 c
+-1.205 -10.389 m
+-1.205 -11.168 l
+-1.132 -11.168 l
+-0.956 -11.168 -0.823 -11.138 -0.735 -11.08 c
+-0.64 -11.021 -0.588 -10.922 -0.588 -10.786 c
+-0.588 -10.657 -0.64 -10.558 -0.735 -10.492 c
+-0.834 -10.433 -0.992 -10.396 -1.205 -10.389 c
+-0.75 -13.66 m
+-0.735 -13.409 l
+-0.735 -13.193 -0.831 -13.045 -1.014 -12.968 c
+-2.984 -12.968 l
+-2.984 -12.189 l
+0 -12.189 l
+0 -12.925 l
+-0.324 -12.954 l
+-0.07 -13.072 0.059 -13.237 0.059 -13.454 c
+0.059 -13.542 0.044 -13.615 0.015 -13.674 c
+h
+f
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 774.5925 108.726 cm
+0 0 m
+0.008 -14.188 l
+-6.464 -14.188 l
+-6.471 0 l
+-3.23 3.564 l
+h
+f
+Q
+0 0 0 0 k
+q 1 0 0 1 769.4918 104.7137 cm
+0 0 m
+0 0.808 l
+1.721 0.808 l
+1.721 1.999 l
+0 1.999 l
+0 2.807 l
+4.013 2.807 l
+4.013 1.999 l
+2.396 1.999 l
+2.396 0.808 l
+4.013 0.808 l
+4.013 0 l
+h
+1.735 -2.496 m
+1.735 -1.231 l
+0.676 -1.231 l
+0.676 -2.731 l
+0 -2.731 l
+0 -0.423 l
+4.013 -0.423 l
+4.013 -2.716 l
+3.337 -2.716 l
+3.337 -1.231 l
+2.396 -1.231 l
+2.396 -2.496 l
+h
+0.823 -4.917 m
+0.823 -3.815 l
+0 -3.595 l
+0 -2.741 l
+4.013 -3.991 l
+4.013 -4.74 l
+0 -6.005 l
+0 -5.137 l
+h
+1.5 -3.991 m
+1.5 -4.74 l
+2.926 -4.373 l
+h
+0 -6.155 m
+4.013 -6.155 l
+4.013 -7.214 l
+4.013 -7.684 3.859 -8.056 3.558 -8.331 c
+3.263 -8.614 2.856 -8.757 2.338 -8.757 c
+1.69 -8.757 l
+1.162 -8.757 0.743 -8.617 0.441 -8.345 c
+0.148 -8.07 0 -7.688 0 -7.199 c
+h
+3.337 -6.964 m
+0.676 -6.964 l
+0.676 -7.214 l
+0.676 -7.479 0.743 -7.662 0.882 -7.772 c
+1.029 -7.89 1.272 -7.949 1.617 -7.949 c
+2.323 -7.949 l
+2.694 -7.949 2.955 -7.894 3.102 -7.787 c
+3.249 -7.688 3.326 -7.512 3.337 -7.258 c
+h
+f
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 733.9356 155.8438 cm
+0 0 m
+-1.058 0 l
+-1.058 -3.572 l
+-1.559 -3.572 l
+-1.559 0 l
+-2.617 0 l
+-2.617 0.441 l
+0 0.441 l
+h
+0.823 -0.897 m
+1.007 -0.654 1.242 -0.529 1.529 -0.529 c
+2.057 -0.529 2.326 -0.881 2.337 -1.587 c
+2.337 -3.572 l
+1.851 -3.572 l
+1.851 -1.616 l
+1.851 -1.381 1.811 -1.216 1.734 -1.117 c
+1.653 -1.022 1.535 -0.97 1.381 -0.97 c
+1.263 -0.97 1.153 -1.01 1.058 -1.087 c
+0.959 -1.168 0.882 -1.275 0.823 -1.411 c
+0.823 -3.572 l
+0.338 -3.572 l
+0.338 0.661 l
+0.823 0.661 l
+h
+3.41 -3.572 -0.5 2.984 re
+3.439 0.206 m
+3.439 0.118 3.413 0.044 3.366 -0.014 c
+3.326 -0.066 3.255 -0.087 3.16 -0.087 c
+3.072 -0.087 3.002 -0.066 2.954 -0.014 c
+2.913 0.044 2.896 0.11 2.896 0.191 c
+2.896 0.279 2.913 0.353 2.954 0.412 c
+3.002 0.47 3.072 0.5 3.16 0.5 c
+3.255 0.5 3.326 0.47 3.366 0.412 c
+3.413 0.353 3.439 0.283 3.439 0.206 c
+5.523 -2.807 m
+5.523 -2.701 5.483 -2.612 5.406 -2.543 c
+5.325 -2.466 5.174 -2.377 4.949 -2.278 c
+4.685 -2.171 4.498 -2.08 4.391 -1.999 c
+4.28 -1.922 4.203 -1.833 4.156 -1.734 c
+4.104 -1.639 4.082 -1.521 4.082 -1.381 c
+4.082 -1.139 4.17 -0.937 4.347 -0.779 c
+4.523 -0.613 4.747 -0.529 5.023 -0.529 c
+5.317 -0.529 5.552 -0.617 5.728 -0.793 c
+5.905 -0.962 5.994 -1.176 5.994 -1.44 c
+5.508 -1.44 l
+5.508 -1.304 5.456 -1.19 5.361 -1.103 c
+5.273 -1.007 5.159 -0.955 5.023 -0.955 c
+4.876 -0.955 4.762 -0.995 4.685 -1.072 c
+4.604 -1.143 4.567 -1.242 4.567 -1.367 c
+4.567 -1.466 4.596 -1.543 4.656 -1.602 c
+4.714 -1.66 4.854 -1.741 5.082 -1.837 c
+5.442 -1.984 5.688 -2.127 5.817 -2.263 c
+5.953 -2.392 6.023 -2.564 6.023 -2.778 c
+6.023 -3.035 5.927 -3.241 5.743 -3.395 c
+5.567 -3.553 5.332 -3.63 5.038 -3.63 c
+4.722 -3.63 4.469 -3.542 4.274 -3.366 c
+4.086 -3.183 3.994 -2.95 3.994 -2.675 c
+4.479 -2.675 l
+4.486 -2.844 4.538 -2.977 4.627 -3.072 c
+4.722 -3.16 4.862 -3.204 5.038 -3.204 c
+5.192 -3.204 5.31 -3.171 5.39 -3.102 c
+5.479 -3.035 5.523 -2.936 5.523 -2.807 c
+8.213 -3.572 -0.499 2.984 re
+8.242 0.206 m
+8.242 0.118 8.216 0.044 8.168 -0.014 c
+8.128 -0.066 8.058 -0.087 7.962 -0.087 c
+7.875 -0.087 7.804 -0.066 7.757 -0.014 c
+7.717 0.044 7.698 0.11 7.698 0.191 c
+7.698 0.279 7.717 0.353 7.757 0.412 c
+7.804 0.47 7.875 0.5 7.962 0.5 c
+8.058 0.5 8.128 0.47 8.168 0.412 c
+8.216 0.353 8.242 0.283 8.242 0.206 c
+10.329 -2.807 m
+10.329 -2.701 10.289 -2.612 10.212 -2.543 c
+10.131 -2.466 9.98 -2.377 9.756 -2.278 c
+9.491 -2.171 9.304 -2.08 9.198 -1.999 c
+9.088 -1.922 9.01 -1.833 8.962 -1.734 c
+8.911 -1.639 8.889 -1.521 8.889 -1.381 c
+8.889 -1.139 8.978 -0.937 9.153 -0.779 c
+9.33 -0.613 9.554 -0.529 9.83 -0.529 c
+10.123 -0.529 10.359 -0.617 10.535 -0.793 c
+10.711 -0.962 10.8 -1.176 10.8 -1.44 c
+10.314 -1.44 l
+10.314 -1.304 10.264 -1.19 10.168 -1.103 c
+10.079 -1.007 9.965 -0.955 9.83 -0.955 c
+9.683 -0.955 9.568 -0.995 9.491 -1.072 c
+9.41 -1.143 9.374 -1.242 9.374 -1.367 c
+9.374 -1.466 9.404 -1.543 9.462 -1.602 c
+9.521 -1.66 9.66 -1.741 9.888 -1.837 c
+10.248 -1.984 10.495 -2.127 10.624 -2.263 c
+10.759 -2.392 10.829 -2.564 10.829 -2.778 c
+10.829 -3.035 10.734 -3.241 10.549 -3.395 c
+10.374 -3.553 10.138 -3.63 9.844 -3.63 c
+9.528 -3.63 9.275 -3.542 9.08 -3.366 c
+8.893 -3.183 8.801 -2.95 8.801 -2.675 c
+9.286 -2.675 l
+9.293 -2.844 9.344 -2.977 9.433 -3.072 c
+9.528 -3.16 9.668 -3.204 9.844 -3.204 c
+9.998 -3.204 10.116 -3.171 10.197 -3.102 c
+10.285 -3.035 10.329 -2.936 10.329 -2.807 c
+14.019 -3.572 m
+13.99 -3.505 13.967 -3.395 13.96 -3.248 c
+13.784 -3.505 13.564 -3.63 13.298 -3.63 c
+13.023 -3.63 12.806 -3.557 12.652 -3.41 c
+12.505 -3.256 12.431 -3.039 12.431 -2.763 c
+12.431 -2.462 12.534 -2.219 12.74 -2.043 c
+12.945 -1.859 13.229 -1.764 13.593 -1.764 c
+13.946 -1.764 l
+13.946 -1.44 l
+13.946 -1.263 13.905 -1.143 13.828 -1.072 c
+13.747 -0.995 13.63 -0.955 13.475 -0.955 c
+13.328 -0.955 13.203 -0.999 13.107 -1.087 c
+13.019 -1.176 12.976 -1.286 12.976 -1.411 c
+12.49 -1.411 l
+12.49 -1.263 12.534 -1.124 12.623 -0.985 c
+12.71 -0.837 12.828 -0.727 12.976 -0.646 c
+13.13 -0.569 13.302 -0.529 13.489 -0.529 c
+13.802 -0.529 14.037 -0.61 14.195 -0.764 c
+14.349 -0.911 14.43 -1.132 14.43 -1.425 c
+14.43 -2.925 l
+14.438 -3.16 14.474 -3.362 14.534 -3.528 c
+14.534 -3.572 l
+h
+13.372 -3.189 m
+13.489 -3.189 13.6 -3.156 13.71 -3.087 c
+13.817 -3.021 13.894 -2.936 13.946 -2.836 c
+13.946 -2.131 l
+13.681 -2.131 l
+13.446 -2.131 13.258 -2.183 13.122 -2.278 c
+12.994 -2.377 12.931 -2.52 12.931 -2.705 c
+12.931 -2.873 12.961 -2.994 13.019 -3.072 c
+13.086 -3.152 13.203 -3.189 13.372 -3.189 c
+15.54 -3.572 -0.5 4.233 re
+17.653 -2.807 m
+17.653 -2.701 17.613 -2.612 17.535 -2.543 c
+17.455 -2.466 17.304 -2.377 17.08 -2.278 c
+16.816 -2.171 16.628 -2.08 16.521 -1.999 c
+16.411 -1.922 16.334 -1.833 16.286 -1.734 c
+16.234 -1.639 16.213 -1.521 16.213 -1.381 c
+16.213 -1.139 16.301 -0.937 16.477 -0.779 c
+16.654 -0.613 16.878 -0.529 17.153 -0.529 c
+17.447 -0.529 17.682 -0.617 17.859 -0.793 c
+18.035 -0.962 18.123 -1.176 18.123 -1.44 c
+17.639 -1.44 l
+17.639 -1.304 17.587 -1.19 17.491 -1.103 c
+17.404 -1.007 17.289 -0.955 17.153 -0.955 c
+17.007 -0.955 16.893 -0.995 16.816 -1.072 c
+16.735 -1.143 16.698 -1.242 16.698 -1.367 c
+16.698 -1.466 16.727 -1.543 16.786 -1.602 c
+16.845 -1.66 16.984 -1.741 17.212 -1.837 c
+17.572 -1.984 17.819 -2.127 17.947 -2.263 c
+18.083 -2.392 18.153 -2.564 18.153 -2.778 c
+18.153 -3.035 18.057 -3.241 17.874 -3.395 c
+17.697 -3.553 17.462 -3.63 17.169 -3.63 c
+16.852 -3.63 16.598 -3.542 16.404 -3.366 c
+16.216 -3.183 16.124 -2.95 16.124 -2.675 c
+16.61 -2.675 l
+16.617 -2.844 16.668 -2.977 16.756 -3.072 c
+16.852 -3.16 16.992 -3.204 17.169 -3.204 c
+17.323 -3.204 17.44 -3.171 17.521 -3.102 c
+17.609 -3.035 17.653 -2.936 17.653 -2.807 c
+18.509 -1.94 m
+18.509 -1.51 18.613 -1.168 18.818 -0.911 c
+19.031 -0.658 19.311 -0.529 19.656 -0.529 c
+19.997 -0.529 20.273 -0.658 20.479 -0.911 c
+20.693 -1.157 20.806 -1.492 20.817 -1.911 c
+20.817 -2.219 l
+20.817 -2.653 20.707 -2.994 20.494 -3.248 c
+20.288 -3.505 20.009 -3.63 19.656 -3.63 c
+19.311 -3.63 19.039 -3.509 18.833 -3.262 c
+18.627 -3.021 18.517 -2.686 18.509 -2.263 c
+h
+18.995 -2.219 m
+18.995 -2.535 19.053 -2.778 19.17 -2.954 c
+19.296 -3.123 19.457 -3.204 19.656 -3.204 c
+20.086 -3.204 20.31 -2.896 20.332 -2.278 c
+20.332 -1.94 l
+20.332 -1.639 20.266 -1.396 20.141 -1.22 c
+20.024 -1.043 19.862 -0.955 19.656 -0.955 c
+19.457 -0.955 19.296 -1.043 19.17 -1.22 c
+19.053 -1.396 18.995 -1.639 18.995 -1.94 c
+h
+f
+Q
+q 1 0 0 1 727.6223 145.6867 cm
+0 0 m
+-0.03 0.067 -0.052 0.177 -0.059 0.324 c
+-0.235 0.067 -0.456 -0.058 -0.721 -0.058 c
+-0.996 -0.058 -1.213 0.015 -1.367 0.162 c
+-1.515 0.316 -1.588 0.533 -1.588 0.809 c
+-1.588 1.11 -1.485 1.353 -1.279 1.529 c
+-1.073 1.713 -0.79 1.808 -0.426 1.808 c
+-0.074 1.808 l
+-0.074 2.132 l
+-0.074 2.309 -0.114 2.429 -0.191 2.5 c
+-0.272 2.577 -0.389 2.617 -0.545 2.617 c
+-0.691 2.617 -0.817 2.573 -0.912 2.484 c
+-1 2.396 -1.044 2.286 -1.044 2.161 c
+-1.529 2.161 l
+-1.529 2.309 -1.485 2.448 -1.397 2.587 c
+-1.309 2.735 -1.191 2.845 -1.044 2.926 c
+-0.89 3.003 -0.717 3.043 -0.53 3.043 c
+-0.217 3.043 0.018 2.962 0.176 2.808 c
+0.33 2.661 0.411 2.44 0.411 2.147 c
+0.411 0.647 l
+0.419 0.412 0.455 0.21 0.515 0.044 c
+0.515 0 l
+h
+-0.647 0.383 m
+-0.53 0.383 -0.42 0.416 -0.309 0.485 c
+-0.202 0.551 -0.125 0.636 -0.074 0.736 c
+-0.074 1.441 l
+-0.339 1.441 l
+-0.574 1.441 -0.761 1.389 -0.896 1.294 c
+-1.025 1.195 -1.088 1.052 -1.088 0.867 c
+-1.088 0.699 -1.058 0.578 -1 0.5 c
+-0.934 0.42 -0.817 0.383 -0.647 0.383 c
+2.726 0 -0.5 4.233 re
+3.296 1.632 m
+3.296 2.062 3.399 2.404 3.605 2.661 c
+3.818 2.914 4.097 3.043 4.442 3.043 c
+4.785 3.043 5.06 2.914 5.265 2.661 c
+5.479 2.415 5.593 2.08 5.604 1.661 c
+5.604 1.353 l
+5.604 0.919 5.493 0.578 5.28 0.324 c
+5.074 0.067 4.795 -0.058 4.442 -0.058 c
+4.097 -0.058 3.825 0.063 3.619 0.31 c
+3.414 0.551 3.303 0.886 3.296 1.309 c
+h
+3.781 1.353 m
+3.781 1.037 3.84 0.794 3.958 0.618 c
+4.082 0.449 4.244 0.368 4.442 0.368 c
+4.872 0.368 5.097 0.676 5.119 1.294 c
+5.119 1.632 l
+5.119 1.933 5.053 2.176 4.928 2.352 c
+4.81 2.529 4.648 2.617 4.442 2.617 c
+4.244 2.617 4.082 2.529 3.958 2.352 c
+3.84 2.176 3.781 1.933 3.781 1.632 c
+h
+7.073 0.368 m
+7.239 0.368 7.372 0.416 7.47 0.515 c
+7.566 0.611 7.621 0.754 7.632 0.941 c
+8.088 0.941 l
+8.077 0.655 7.974 0.416 7.779 0.221 c
+7.592 0.034 7.357 -0.058 7.073 -0.058 c
+6.709 -0.058 6.431 0.059 6.236 0.294 c
+6.038 0.53 5.942 0.875 5.942 1.338 c
+5.942 1.661 l
+5.942 2.11 6.034 2.455 6.221 2.691 c
+6.416 2.926 6.699 3.043 7.073 3.043 c
+7.374 3.043 7.617 2.944 7.794 2.749 c
+7.977 2.55 8.077 2.286 8.088 1.956 c
+7.632 1.956 l
+7.61 2.18 7.551 2.345 7.455 2.455 c
+7.368 2.562 7.239 2.617 7.073 2.617 c
+6.857 2.617 6.695 2.544 6.589 2.396 c
+6.489 2.257 6.434 2.029 6.427 1.706 c
+6.427 1.324 l
+6.427 0.971 6.474 0.721 6.574 0.574 c
+6.68 0.434 6.846 0.368 7.073 0.368 c
+10.01 0 m
+9.98 0.067 9.959 0.177 9.951 0.324 c
+9.774 0.067 9.554 -0.058 9.29 -0.058 c
+9.014 -0.058 8.797 0.015 8.643 0.162 c
+8.496 0.316 8.422 0.533 8.422 0.809 c
+8.422 1.11 8.525 1.353 8.731 1.529 c
+8.937 1.713 9.219 1.808 9.583 1.808 c
+9.936 1.808 l
+9.936 2.132 l
+9.936 2.309 9.896 2.429 9.819 2.5 c
+9.738 2.577 9.62 2.617 9.466 2.617 c
+9.319 2.617 9.194 2.573 9.098 2.484 c
+9.01 2.396 8.966 2.286 8.966 2.161 c
+8.481 2.161 l
+8.481 2.309 8.525 2.448 8.613 2.587 c
+8.702 2.735 8.819 2.845 8.966 2.926 c
+9.12 3.003 9.294 3.043 9.481 3.043 c
+9.793 3.043 10.028 2.962 10.186 2.808 c
+10.341 2.661 10.422 2.44 10.422 2.147 c
+10.422 0.647 l
+10.429 0.412 10.466 0.21 10.524 0.044 c
+10.524 0 l
+h
+9.363 0.383 m
+9.481 0.383 9.591 0.416 9.701 0.485 c
+9.807 0.551 9.884 0.636 9.936 0.736 c
+9.936 1.441 l
+9.672 1.441 l
+9.437 1.441 9.249 1.389 9.113 1.294 c
+8.984 1.195 8.922 1.052 8.922 0.867 c
+8.922 0.699 8.951 0.578 9.01 0.5 c
+9.076 0.42 9.194 0.383 9.363 0.383 c
+11.531 0 -0.5 4.233 re
+15.573 1.353 m
+15.573 0.882 15.488 0.53 15.324 0.294 c
+15.154 0.059 14.912 -0.058 14.588 -0.058 c
+14.272 -0.058 14.037 0.077 13.883 0.353 c
+13.853 0 l
+13.412 0 l
+13.412 4.233 l
+13.898 4.233 l
+13.898 2.661 l
+14.052 2.914 14.283 3.043 14.588 3.043 c
+14.912 3.043 15.154 2.926 15.324 2.691 c
+15.488 2.455 15.573 2.106 15.573 1.646 c
+h
+15.089 1.632 m
+15.089 1.985 15.037 2.234 14.941 2.382 c
+14.842 2.529 14.68 2.602 14.456 2.602 c
+14.21 2.602 14.023 2.463 13.898 2.191 c
+13.898 0.78 l
+14.015 0.515 14.206 0.383 14.47 0.383 c
+14.684 0.383 14.842 0.456 14.941 0.603 c
+15.037 0.757 15.089 1 15.089 1.324 c
+h
+17.249 2.529 m
+17.179 2.536 17.105 2.544 17.028 2.544 c
+16.772 2.544 16.595 2.404 16.5 2.132 c
+16.5 0 l
+16.014 0 l
+16.014 2.984 l
+16.485 2.984 l
+16.5 2.675 l
+16.624 2.918 16.808 3.043 17.043 3.043 c
+17.121 3.043 17.183 3.028 17.234 2.999 c
+h
+19.046 0 m
+19.016 0.067 18.994 0.177 18.987 0.324 c
+18.811 0.067 18.59 -0.058 18.326 -0.058 c
+18.05 -0.058 17.834 0.015 17.679 0.162 c
+17.532 0.316 17.458 0.533 17.458 0.809 c
+17.458 1.11 17.562 1.353 17.767 1.529 c
+17.973 1.713 18.256 1.808 18.62 1.808 c
+18.973 1.808 l
+18.973 2.132 l
+18.973 2.309 18.932 2.429 18.855 2.5 c
+18.774 2.577 18.657 2.617 18.503 2.617 c
+18.355 2.617 18.231 2.573 18.135 2.484 c
+18.046 2.396 18.002 2.286 18.002 2.161 c
+17.518 2.161 l
+17.518 2.309 17.562 2.448 17.649 2.587 c
+17.738 2.735 17.855 2.845 18.002 2.926 c
+18.156 3.003 18.329 3.043 18.517 3.043 c
+18.829 3.043 19.064 2.962 19.222 2.808 c
+19.376 2.661 19.457 2.44 19.457 2.147 c
+19.457 0.647 l
+19.465 0.412 19.502 0.21 19.561 0.044 c
+19.561 0 l
+h
+18.399 0.383 m
+18.517 0.383 18.627 0.416 18.738 0.485 c
+18.844 0.551 18.921 0.636 18.973 0.736 c
+18.973 1.441 l
+18.708 1.441 l
+18.472 1.441 18.285 1.389 18.15 1.294 c
+18.021 1.195 17.958 1.052 17.958 0.867 c
+17.958 0.699 17.988 0.578 18.046 0.5 c
+18.113 0.42 18.231 0.383 18.399 0.383 c
+20.494 2.984 m
+20.508 2.661 l
+20.693 2.914 20.935 3.043 21.229 3.043 c
+21.758 3.043 22.026 2.691 22.037 1.985 c
+22.037 0 l
+21.552 0 l
+21.552 1.956 l
+21.552 2.191 21.512 2.356 21.435 2.455 c
+21.354 2.55 21.236 2.602 21.082 2.602 c
+20.964 2.602 20.854 2.562 20.758 2.484 c
+20.66 2.404 20.582 2.297 20.523 2.161 c
+20.523 0 l
+20.038 0 l
+20.038 2.984 l
+h
+23.617 0.368 m
+23.783 0.368 23.915 0.416 24.014 0.515 c
+24.11 0.611 24.165 0.754 24.176 0.941 c
+24.631 0.941 l
+24.62 0.655 24.518 0.416 24.323 0.221 c
+24.136 0.034 23.9 -0.058 23.617 -0.058 c
+23.253 -0.058 22.974 0.059 22.779 0.294 c
+22.582 0.53 22.486 0.875 22.486 1.338 c
+22.486 1.661 l
+22.486 2.11 22.578 2.455 22.765 2.691 c
+22.96 2.926 23.243 3.043 23.617 3.043 c
+23.918 3.043 24.161 2.944 24.338 2.749 c
+24.521 2.55 24.62 2.286 24.631 1.956 c
+24.176 1.956 l
+24.154 2.18 24.095 2.345 23.999 2.455 c
+23.912 2.562 23.783 2.617 23.617 2.617 c
+23.401 2.617 23.239 2.544 23.132 2.396 c
+23.033 2.257 22.978 2.029 22.971 1.706 c
+22.971 1.324 l
+22.971 0.971 23.018 0.721 23.118 0.574 c
+23.224 0.434 23.39 0.368 23.617 0.368 c
+25.514 2.675 m
+25.697 2.918 25.932 3.043 26.219 3.043 c
+26.748 3.043 27.016 2.691 27.027 1.985 c
+27.027 0 l
+26.542 0 l
+26.542 1.956 l
+26.542 2.191 26.502 2.356 26.424 2.455 c
+26.344 2.55 26.227 2.602 26.072 2.602 c
+25.954 2.602 25.844 2.562 25.749 2.484 c
+25.649 2.404 25.572 2.297 25.514 2.161 c
+25.514 0 l
+25.028 0 l
+25.028 4.233 l
+25.514 4.233 l
+h
+f
+Q
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 757.5933 146.8594 cm
+0 0 m
+7.559 -2.874 l
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 763.1567 144.7467 cm
+0 0 m
+-1.378 -0.622 l
+2.492 -0.949 l
+-0.617 1.374 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 763.1568 144.7467 cm
+0 0 m
+-1.378 -0.622 l
+2.492 -0.949 l
+-0.617 1.374 l
+0 0 l
+h
+S
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 710.7031 92.4728 cm
+0 0 m
+0.809 2.014 l
+1.382 2.014 l
+0.25 -0.5 l
+0.25 -1.999 l
+-0.264 -1.999 l
+-0.264 -0.5 l
+-1.396 2.014 l
+-0.823 2.014 l
+h
+1.382 -0.368 m
+1.382 0.062 1.484 0.405 1.691 0.661 c
+1.904 0.915 2.183 1.043 2.529 1.043 c
+2.87 1.043 3.146 0.915 3.352 0.661 c
+3.564 0.415 3.678 0.081 3.69 -0.338 c
+3.69 -0.647 l
+3.69 -1.08 3.58 -1.422 3.366 -1.675 c
+3.161 -1.933 2.881 -2.058 2.529 -2.058 c
+2.183 -2.058 1.912 -1.937 1.706 -1.691 c
+1.5 -1.448 1.389 -1.114 1.382 -0.691 c
+h
+1.867 -0.647 m
+1.867 -0.962 1.926 -1.205 2.043 -1.382 c
+2.168 -1.55 2.33 -1.631 2.529 -1.631 c
+2.959 -1.631 3.183 -1.323 3.204 -0.706 c
+3.204 -0.368 l
+3.204 -0.066 3.138 0.176 3.013 0.353 c
+2.896 0.529 2.734 0.617 2.529 0.617 c
+2.33 0.617 2.168 0.529 2.043 0.353 c
+1.926 0.176 1.867 -0.066 1.867 -0.368 c
+h
+5.644 -1.735 m
+5.486 -1.951 5.251 -2.058 4.939 -2.058 c
+4.675 -2.058 4.469 -1.966 4.322 -1.779 c
+4.183 -1.595 4.116 -1.319 4.116 -0.956 c
+4.116 0.985 l
+4.601 0.985 l
+4.601 -0.926 l
+4.601 -1.389 4.74 -1.617 5.027 -1.617 c
+5.321 -1.617 5.519 -1.484 5.63 -1.22 c
+5.63 0.985 l
+6.13 0.985 l
+6.13 -1.999 l
+5.659 -1.999 l
+h
+7.915 0.529 m
+7.846 0.536 7.772 0.544 7.695 0.544 c
+7.437 0.544 7.262 0.405 7.166 0.133 c
+7.166 -1.999 l
+6.681 -1.999 l
+6.681 0.985 l
+7.151 0.985 l
+7.166 0.676 l
+7.291 0.919 7.475 1.043 7.71 1.043 c
+7.787 1.043 7.85 1.029 7.901 0.999 c
+h
+f
+Q
+q 1 0 0 1 722.2789 91.7823 cm
+0 0 m
+0.264 1.675 l
+1.014 1.675 l
+0.397 -1.309 l
+-0.25 -1.309 l
+-0.676 0.411 l
+-1.088 -1.309 l
+-1.749 -1.309 l
+-2.367 1.675 l
+-1.617 1.675 l
+-1.353 0 l
+-0.956 1.675 l
+-0.397 1.675 l
+h
+1.073 0.278 m
+1.073 0.727 1.18 1.08 1.396 1.337 c
+1.61 1.602 1.903 1.734 2.279 1.734 c
+2.66 1.734 2.955 1.602 3.16 1.337 c
+3.373 1.08 3.484 0.727 3.484 0.278 c
+3.484 0.087 l
+3.484 -0.375 3.373 -0.732 3.16 -0.985 c
+2.955 -1.243 2.66 -1.368 2.279 -1.368 c
+1.897 -1.368 1.595 -1.243 1.382 -0.985 c
+1.176 -0.721 1.073 -0.364 1.073 0.087 c
+h
+1.852 0.087 m
+1.852 -0.452 1.992 -0.721 2.279 -0.721 c
+2.543 -0.721 2.682 -0.497 2.705 -0.044 c
+2.72 0.278 l
+2.72 0.551 2.679 0.753 2.602 0.881 c
+2.521 1.018 2.414 1.087 2.279 1.087 c
+2.15 1.087 2.047 1.018 1.97 0.881 c
+1.889 0.753 1.852 0.551 1.852 0.278 c
+h
+5.255 0.926 m
+5.005 0.941 l
+4.788 0.941 4.642 0.845 4.564 0.661 c
+4.564 -1.309 l
+3.785 -1.309 l
+3.785 1.675 l
+4.52 1.675 l
+4.549 1.352 l
+4.667 1.606 4.833 1.734 5.049 1.734 c
+5.137 1.734 5.211 1.72 5.269 1.69 c
+h
+6.533 -0.162 m
+6.313 -0.397 l
+6.313 -1.309 l
+5.534 -1.309 l
+5.534 2.925 l
+6.313 2.925 l
+6.313 0.631 l
+6.416 0.779 l
+6.96 1.675 l
+7.886 1.675 l
+7.019 0.44 l
+7.975 -1.309 l
+7.077 -1.309 l
+h
+8.878 -1.309 -0.779 2.984 re
+8.055 2.439 m
+8.055 2.564 8.091 2.668 8.172 2.748 c
+8.249 2.826 8.353 2.865 8.482 2.865 c
+8.606 2.865 8.709 2.826 8.79 2.748 c
+8.867 2.668 8.908 2.564 8.908 2.439 c
+8.908 2.322 8.867 2.223 8.79 2.146 c
+8.72 2.065 8.617 2.028 8.482 2.028 c
+8.353 2.028 8.249 2.065 8.172 2.146 c
+8.091 2.223 8.055 2.322 8.055 2.439 c
+10.102 1.675 m
+10.117 1.381 l
+10.293 1.616 10.521 1.734 10.807 1.734 c
+11.326 1.734 11.59 1.371 11.601 0.646 c
+11.601 -1.309 l
+10.822 -1.309 l
+10.822 0.588 l
+10.822 0.764 10.797 0.885 10.749 0.955 c
+10.697 1.032 10.609 1.072 10.484 1.072 c
+10.337 1.072 10.223 0.999 10.146 0.852 c
+10.146 -1.309 l
+9.367 -1.309 l
+9.367 1.675 l
+h
+11.884 0.278 m
+11.884 0.768 11.973 1.132 12.149 1.367 c
+12.325 1.61 12.567 1.734 12.883 1.734 c
+13.155 1.734 13.369 1.624 13.516 1.411 c
+13.545 1.675 l
+14.25 1.675 l
+14.25 -1.309 l
+14.25 -1.691 14.14 -1.977 13.928 -2.176 c
+13.71 -2.382 13.406 -2.484 13.016 -2.484 c
+12.847 -2.484 12.671 -2.448 12.486 -2.382 c
+12.311 -2.323 12.178 -2.238 12.089 -2.132 c
+12.355 -1.603 l
+12.432 -1.669 12.531 -1.727 12.648 -1.779 c
+12.766 -1.827 12.873 -1.852 12.972 -1.852 c
+13.149 -1.852 13.273 -1.808 13.354 -1.721 c
+13.431 -1.64 13.471 -1.507 13.471 -1.324 c
+13.471 -1.073 l
+13.325 -1.272 13.126 -1.368 12.883 -1.368 c
+12.567 -1.368 12.325 -1.246 12.149 -1 c
+11.973 -0.746 11.884 -0.393 11.884 0.058 c
+h
+12.663 0.073 m
+12.663 -0.202 12.696 -0.405 12.766 -0.53 c
+12.843 -0.647 12.961 -0.706 13.119 -0.706 c
+13.273 -0.706 13.391 -0.655 13.471 -0.545 c
+13.471 0.881 l
+13.391 1.007 13.273 1.072 13.119 1.072 c
+12.961 1.072 12.843 1.007 12.766 0.881 c
+12.696 0.753 12.663 0.551 12.663 0.278 c
+h
+15.739 0.278 m
+15.739 0.768 15.819 1.132 15.989 1.367 c
+16.154 1.61 16.393 1.734 16.709 1.734 c
+16.945 1.734 17.136 1.631 17.282 1.425 c
+17.282 2.925 l
+18.076 2.925 l
+18.076 -1.309 l
+17.356 -1.309 l
+17.327 -1 l
+17.169 -1.246 16.962 -1.368 16.709 -1.368 c
+16.393 -1.368 16.154 -1.25 15.989 -1.015 c
+15.831 -0.772 15.746 -0.42 15.739 0.043 c
+h
+16.518 0.073 m
+16.518 -0.221 16.548 -0.427 16.606 -0.545 c
+16.673 -0.655 16.783 -0.706 16.93 -0.706 c
+17.084 -0.706 17.201 -0.64 17.282 -0.5 c
+17.282 0.852 l
+17.201 0.999 17.091 1.072 16.945 1.072 c
+16.797 1.072 16.687 1.014 16.621 0.897 c
+16.551 0.786 16.518 0.58 16.518 0.278 c
+h
+19.278 -1.309 -0.779 2.984 re
+18.454 2.439 m
+18.454 2.564 18.491 2.668 18.572 2.748 c
+18.649 2.826 18.753 2.865 18.881 2.865 c
+19.006 2.865 19.108 2.826 19.189 2.748 c
+19.266 2.668 19.307 2.564 19.307 2.439 c
+19.307 2.322 19.266 2.223 19.189 2.146 c
+19.12 2.065 19.017 2.028 18.881 2.028 c
+18.753 2.028 18.649 2.065 18.572 2.146 c
+18.491 2.223 18.454 2.322 18.454 2.439 c
+21.255 0.926 m
+21.005 0.941 l
+20.789 0.941 20.641 0.845 20.564 0.661 c
+20.564 -1.309 l
+19.785 -1.309 l
+19.785 1.675 l
+20.519 1.675 l
+20.549 1.352 l
+20.667 1.606 20.832 1.734 21.049 1.734 c
+21.137 1.734 21.211 1.72 21.269 1.69 c
+h
+22.688 -1.368 m
+22.283 -1.368 21.971 -1.25 21.747 -1.015 c
+21.531 -0.772 21.423 -0.427 21.423 0.014 c
+21.423 0.264 l
+21.423 0.735 21.527 1.095 21.732 1.352 c
+21.938 1.606 22.232 1.734 22.614 1.734 c
+22.986 1.734 23.264 1.61 23.453 1.367 c
+23.647 1.132 23.746 0.779 23.746 0.309 c
+23.746 -0.074 l
+22.202 -0.074 l
+22.21 -0.302 22.254 -0.467 22.335 -0.574 c
+22.423 -0.673 22.559 -0.721 22.747 -0.721 c
+23 -0.721 23.217 -0.628 23.393 -0.441 c
+23.702 -0.927 l
+23.603 -1.055 23.459 -1.162 23.276 -1.25 c
+23.1 -1.327 22.901 -1.368 22.688 -1.368 c
+22.202 0.47 m
+22.982 0.47 l
+22.982 0.544 l
+22.982 0.72 22.952 0.852 22.894 0.941 c
+22.835 1.036 22.736 1.087 22.599 1.087 c
+22.471 1.087 22.372 1.036 22.306 0.941 c
+22.247 0.841 22.21 0.683 22.202 0.47 c
+25.091 -0.721 m
+25.315 -0.721 25.429 -0.574 25.429 -0.279 c
+26.164 -0.279 l
+26.164 -0.603 26.061 -0.867 25.855 -1.073 c
+25.657 -1.272 25.407 -1.368 25.106 -1.368 c
+24.724 -1.368 24.43 -1.25 24.224 -1.015 c
+24.018 -0.772 23.915 -0.42 23.915 0.043 c
+23.915 0.294 l
+23.915 0.753 24.01 1.105 24.209 1.352 c
+24.415 1.606 24.709 1.734 25.091 1.734 c
+25.422 1.734 25.683 1.631 25.87 1.425 c
+26.065 1.219 26.164 0.929 26.164 0.558 c
+25.429 0.558 l
+25.429 0.723 25.4 0.852 25.341 0.941 c
+25.29 1.036 25.201 1.087 25.076 1.087 c
+24.947 1.087 24.856 1.036 24.797 0.941 c
+24.739 0.841 24.702 0.654 24.694 0.382 c
+24.694 0.073 l
+24.694 -0.173 24.702 -0.346 24.724 -0.441 c
+24.753 -0.53 24.789 -0.599 24.841 -0.647 c
+24.9 -0.699 24.981 -0.721 25.091 -0.721 c
+27.34 2.41 m
+27.34 1.675 l
+27.737 1.675 l
+27.737 1.087 l
+27.34 1.087 l
+27.34 -0.397 l
+27.34 -0.515 27.355 -0.599 27.384 -0.647 c
+27.421 -0.688 27.487 -0.706 27.575 -0.706 c
+27.652 -0.706 27.715 -0.699 27.767 -0.676 c
+27.752 -1.294 l
+27.623 -1.341 27.48 -1.368 27.326 -1.368 c
+26.826 -1.368 26.568 -1.081 26.561 -0.5 c
+26.561 1.087 l
+26.223 1.087 l
+26.223 1.675 l
+26.561 1.675 l
+26.561 2.41 l
+h
+27.884 0.278 m
+27.884 0.727 27.991 1.08 28.207 1.337 c
+28.421 1.602 28.714 1.734 29.09 1.734 c
+29.471 1.734 29.766 1.602 29.971 1.337 c
+30.185 1.08 30.295 0.727 30.295 0.278 c
+30.295 0.087 l
+30.295 -0.375 30.185 -0.732 29.971 -0.985 c
+29.766 -1.243 29.471 -1.368 29.09 -1.368 c
+28.708 -1.368 28.406 -1.243 28.193 -0.985 c
+27.987 -0.721 27.884 -0.364 27.884 0.087 c
+h
+28.663 0.087 m
+28.663 -0.452 28.803 -0.721 29.09 -0.721 c
+29.354 -0.721 29.493 -0.497 29.516 -0.044 c
+29.531 0.278 l
+29.531 0.551 29.49 0.753 29.413 0.881 c
+29.332 1.018 29.225 1.087 29.09 1.087 c
+28.961 1.087 28.858 1.018 28.781 0.881 c
+28.7 0.753 28.663 0.551 28.663 0.278 c
+h
+32.066 0.926 m
+31.816 0.941 l
+31.599 0.941 31.453 0.845 31.375 0.661 c
+31.375 -1.309 l
+30.596 -1.309 l
+30.596 1.675 l
+31.331 1.675 l
+31.36 1.352 l
+31.478 1.606 31.644 1.734 31.86 1.734 c
+31.948 1.734 32.022 1.72 32.08 1.69 c
+h
+33.352 -0.015 m
+33.749 1.675 l
+34.587 1.675 l
+33.602 -1.75 l
+33.455 -2.257 33.179 -2.514 32.779 -2.514 c
+32.679 -2.514 32.573 -2.492 32.456 -2.455 c
+32.456 -1.852 l
+32.544 -1.852 l
+32.669 -1.852 32.764 -1.827 32.823 -1.779 c
+32.882 -1.738 32.926 -1.661 32.955 -1.544 c
+33.028 -1.338 l
+32.161 1.675 l
+32.999 1.675 l
+h
+f
+Q
+743.813 83.889 -0.5 2.984 re
+743.843 87.667 m
+743.843 87.578 743.816 87.505 743.769 87.445 c
+743.729 87.395 743.659 87.372 743.563 87.372 c
+743.475 87.372 743.405 87.395 743.357 87.445 c
+743.317 87.505 743.299 87.571 743.299 87.652 c
+743.299 87.74 743.317 87.813 743.357 87.872 c
+743.405 87.931 743.475 87.96 743.563 87.96 c
+743.659 87.96 743.729 87.931 743.769 87.872 c
+743.816 87.813 743.843 87.744 743.843 87.667 c
+745.926 84.652 m
+745.926 84.76 745.886 84.848 745.809 84.918 c
+745.728 84.995 745.577 85.083 745.352 85.182 c
+745.088 85.288 744.901 85.381 744.795 85.461 c
+744.684 85.539 744.606 85.627 744.559 85.726 c
+744.508 85.822 744.485 85.939 744.485 86.079 c
+744.485 86.321 744.573 86.524 744.75 86.682 c
+744.926 86.847 745.15 86.931 745.426 86.931 c
+745.72 86.931 745.956 86.843 746.131 86.667 c
+746.308 86.497 746.397 86.285 746.397 86.02 c
+745.911 86.02 l
+745.911 86.156 745.859 86.27 745.765 86.358 c
+745.676 86.454 745.562 86.505 745.426 86.505 c
+745.279 86.505 745.165 86.464 745.088 86.387 c
+745.007 86.318 744.97 86.219 744.97 86.094 c
+744.97 85.994 745 85.917 745.059 85.858 c
+745.117 85.799 745.257 85.718 745.485 85.623 c
+745.845 85.476 746.091 85.333 746.22 85.197 c
+746.356 85.068 746.426 84.895 746.426 84.683 c
+746.426 84.425 746.33 84.22 746.146 84.064 c
+745.971 83.907 745.735 83.829 745.441 83.829 c
+745.125 83.829 744.872 83.918 744.677 84.095 c
+744.489 84.278 744.398 84.509 744.398 84.785 c
+744.882 84.785 l
+744.89 84.616 744.941 84.484 745.03 84.388 c
+745.125 84.3 745.265 84.256 745.441 84.256 c
+745.595 84.256 745.713 84.289 745.794 84.359 c
+745.882 84.425 745.926 84.525 745.926 84.652 c
+748.572 86.564 m
+748.755 86.807 748.99 86.931 749.277 86.931 c
+749.807 86.931 750.075 86.578 750.086 85.873 c
+750.086 83.889 l
+749.601 83.889 l
+749.601 85.843 l
+749.601 86.079 749.56 86.244 749.483 86.343 c
+749.402 86.439 749.285 86.491 749.13 86.491 c
+749.013 86.491 748.903 86.45 748.807 86.373 c
+748.708 86.292 748.631 86.185 748.572 86.049 c
+748.572 83.889 l
+748.087 83.889 l
+748.087 88.122 l
+748.572 88.122 l
+h
+751.688 83.829 m
+751.313 83.829 751.03 83.937 750.835 84.153 c
+750.637 84.378 750.542 84.704 750.542 85.138 c
+750.542 85.506 l
+750.542 85.946 750.634 86.292 750.821 86.549 c
+751.016 86.803 751.291 86.931 751.644 86.931 c
+751.986 86.931 752.24 86.817 752.408 86.593 c
+752.585 86.366 752.676 86.02 752.687 85.55 c
+752.687 85.24 l
+751.027 85.24 l
+751.027 85.167 l
+751.027 84.844 751.085 84.609 751.203 84.461 c
+751.32 84.322 751.49 84.256 751.718 84.256 c
+751.864 84.256 751.989 84.278 752.099 84.33 c
+752.206 84.388 752.309 84.477 752.408 84.594 c
+752.658 84.286 l
+752.452 83.981 752.129 83.829 751.688 83.829 c
+751.644 86.505 m
+751.438 86.505 751.284 86.435 751.188 86.299 c
+751.089 86.16 751.034 85.946 751.027 85.652 c
+752.203 85.652 l
+752.203 85.726 l
+752.18 85.998 752.129 86.196 752.041 86.314 c
+751.953 86.439 751.82 86.505 751.644 86.505 c
+754.334 86.416 m
+754.264 86.424 754.191 86.431 754.114 86.431 c
+753.856 86.431 753.68 86.292 753.584 86.02 c
+753.584 83.889 l
+753.099 83.889 l
+753.099 86.873 l
+753.57 86.873 l
+753.584 86.564 l
+753.709 86.807 753.892 86.931 754.128 86.931 c
+754.205 86.931 754.268 86.917 754.32 86.887 c
+h
+755.712 83.829 m
+755.337 83.829 755.054 83.937 754.86 84.153 c
+754.661 84.378 754.565 84.704 754.565 85.138 c
+754.565 85.506 l
+754.565 85.946 754.657 86.292 754.845 86.549 c
+755.039 86.803 755.315 86.931 755.668 86.931 c
+756.009 86.931 756.263 86.817 756.432 86.593 c
+756.608 86.366 756.701 86.02 756.711 85.55 c
+756.711 85.24 l
+755.051 85.24 l
+755.051 85.167 l
+755.051 84.844 755.109 84.609 755.226 84.461 c
+755.344 84.322 755.513 84.256 755.741 84.256 c
+755.889 84.256 756.013 84.278 756.124 84.33 c
+756.23 84.388 756.333 84.477 756.432 84.594 c
+756.682 84.286 l
+756.476 83.981 756.153 83.829 755.712 83.829 c
+755.668 86.505 m
+755.462 86.505 755.307 86.435 755.212 86.299 c
+755.113 86.16 755.058 85.946 755.051 85.652 c
+756.226 85.652 l
+756.226 85.726 l
+756.204 85.998 756.153 86.196 756.065 86.314 c
+755.976 86.439 755.844 86.505 755.668 86.505 c
+f
+0.793 0.801 0.129 0.016 K
+0.567 w 1 j 1 J
+q 1 0 0 1 757.869 91.9766 cm
+0 0 m
+6.53 2.899 l
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 762.4514 94.0083 cm
+0 0 m
+-0.543 -1.407 l
+2.436 1.081 l
+-1.408 0.544 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 762.4514 94.0083 cm
+0 0 m
+-0.543 -1.407 l
+2.436 1.081 l
+-1.408 0.544 l
+0 0 l
+h
+S
+Q
+0 0 0 0 k
+q 1 0 0 1 317.2173 119.0558 cm
+0 0 m
+0 -2.076 -1.683 -3.755 -3.755 -3.755 c
+-5.832 -3.755 -7.512 -2.076 -7.512 0 c
+-7.512 2.076 -5.832 3.755 -3.755 3.755 c
+-1.683 3.755 0 2.076 0 0 c
+f
+Q
+0.797 0.801 0.129 0.016 K
+0.709 w 1 j 1 J
+q 1 0 0 1 317.2173 119.0558 cm
+0 0 m
+0 -2.076 -1.683 -3.755 -3.755 -3.755 c
+-5.832 -3.755 -7.512 -2.076 -7.512 0 c
+-7.512 2.076 -5.832 3.755 -3.755 3.755 c
+-1.683 3.755 0 2.076 0 0 c
+h
+S
+Q
+q
+320.12 122.007 211.589 -5.589 re
+W n
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS6 gs
+0 TL/Fm33 Do
+Q
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 325.9445 111.6592 cm
+0 0 m
+-1.058 0 l
+-1.058 -3.572 l
+-1.558 -3.572 l
+-1.558 0 l
+-2.616 0 l
+-2.616 0.44 l
+0 0.44 l
+h
+0.819 -0.897 m
+1.004 -0.655 1.239 -0.53 1.525 -0.53 c
+2.055 -0.53 2.323 -0.882 2.334 -1.588 c
+2.334 -3.572 l
+1.849 -3.572 l
+1.849 -1.617 l
+1.849 -1.382 1.808 -1.216 1.731 -1.118 c
+1.65 -1.022 1.532 -0.971 1.378 -0.971 c
+1.261 -0.971 1.151 -1.011 1.055 -1.088 c
+0.956 -1.169 0.879 -1.276 0.819 -1.411 c
+0.819 -3.572 l
+0.335 -3.572 l
+0.335 0.661 l
+0.819 0.661 l
+h
+3.406 -3.572 -0.5 2.984 re
+3.436 0.205 m
+3.436 0.118 3.41 0.043 3.362 -0.015 c
+3.322 -0.067 3.252 -0.088 3.157 -0.088 c
+3.069 -0.088 2.999 -0.067 2.951 -0.015 c
+2.911 0.043 2.892 0.11 2.892 0.191 c
+2.892 0.278 2.911 0.353 2.951 0.411 c
+2.999 0.47 3.069 0.5 3.157 0.5 c
+3.252 0.5 3.322 0.47 3.362 0.411 c
+3.41 0.353 3.436 0.282 3.436 0.205 c
+5.523 -2.808 m
+5.523 -2.702 5.483 -2.613 5.405 -2.544 c
+5.325 -2.467 5.174 -2.378 4.95 -2.278 c
+4.686 -2.172 4.498 -2.08 4.391 -1.999 c
+4.281 -1.922 4.204 -1.834 4.156 -1.735 c
+4.104 -1.64 4.083 -1.522 4.083 -1.382 c
+4.083 -1.139 4.171 -0.938 4.347 -0.78 c
+4.524 -0.614 4.748 -0.53 5.024 -0.53 c
+5.317 -0.53 5.552 -0.618 5.729 -0.794 c
+5.906 -0.963 5.993 -1.176 5.993 -1.441 c
+5.509 -1.441 l
+5.509 -1.305 5.457 -1.191 5.361 -1.103 c
+5.274 -1.008 5.16 -0.956 5.024 -0.956 c
+4.877 -0.956 4.763 -0.996 4.686 -1.073 c
+4.605 -1.143 4.568 -1.243 4.568 -1.368 c
+4.568 -1.467 4.597 -1.544 4.656 -1.603 c
+4.715 -1.661 4.854 -1.742 5.082 -1.838 c
+5.442 -1.985 5.689 -2.128 5.818 -2.264 c
+5.953 -2.392 6.023 -2.565 6.023 -2.779 c
+6.023 -3.036 5.928 -3.242 5.744 -3.396 c
+5.567 -3.554 5.332 -3.631 5.039 -3.631 c
+4.722 -3.631 4.469 -3.543 4.274 -3.367 c
+4.087 -3.183 3.994 -2.951 3.994 -2.675 c
+4.48 -2.675 l
+4.487 -2.845 4.538 -2.977 4.627 -3.072 c
+4.722 -3.161 4.862 -3.205 5.039 -3.205 c
+5.193 -3.205 5.31 -3.172 5.391 -3.102 c
+5.479 -3.036 5.523 -2.937 5.523 -2.808 c
+8.214 -3.572 -0.5 2.984 re
+8.243 0.205 m
+8.243 0.118 8.217 0.043 8.169 -0.015 c
+8.129 -0.067 8.059 -0.088 7.963 -0.088 c
+7.875 -0.088 7.805 -0.067 7.757 -0.015 c
+7.717 0.043 7.699 0.11 7.699 0.191 c
+7.699 0.278 7.717 0.353 7.757 0.411 c
+7.805 0.47 7.875 0.5 7.963 0.5 c
+8.059 0.5 8.129 0.47 8.169 0.411 c
+8.217 0.353 8.243 0.282 8.243 0.205 c
+10.326 -2.808 m
+10.326 -2.702 10.286 -2.613 10.209 -2.544 c
+10.128 -2.467 9.977 -2.378 9.753 -2.278 c
+9.488 -2.172 9.301 -2.08 9.195 -1.999 c
+9.084 -1.922 9.007 -1.834 8.96 -1.735 c
+8.908 -1.64 8.885 -1.522 8.885 -1.382 c
+8.885 -1.139 8.974 -0.938 9.151 -0.78 c
+9.326 -0.614 9.55 -0.53 9.826 -0.53 c
+10.12 -0.53 10.356 -0.618 10.532 -0.794 c
+10.708 -0.963 10.797 -1.176 10.797 -1.441 c
+10.311 -1.441 l
+10.311 -1.305 10.26 -1.191 10.165 -1.103 c
+10.076 -1.008 9.962 -0.956 9.826 -0.956 c
+9.679 -0.956 9.565 -0.996 9.488 -1.073 c
+9.407 -1.143 9.371 -1.243 9.371 -1.368 c
+9.371 -1.467 9.4 -1.544 9.459 -1.603 c
+9.517 -1.661 9.658 -1.742 9.885 -1.838 c
+10.246 -1.985 10.491 -2.128 10.62 -2.264 c
+10.756 -2.392 10.826 -2.565 10.826 -2.779 c
+10.826 -3.036 10.73 -3.242 10.547 -3.396 c
+10.371 -3.554 10.135 -3.631 9.841 -3.631 c
+9.525 -3.631 9.272 -3.543 9.077 -3.367 c
+8.889 -3.183 8.798 -2.951 8.798 -2.675 c
+9.282 -2.675 l
+9.29 -2.845 9.342 -2.977 9.43 -3.072 c
+9.525 -3.161 9.665 -3.205 9.841 -3.205 c
+9.995 -3.205 10.113 -3.172 10.194 -3.102 c
+10.282 -3.036 10.326 -2.937 10.326 -2.808 c
+14.016 -3.572 m
+13.986 -3.506 13.964 -3.396 13.957 -3.249 c
+13.781 -3.506 13.56 -3.631 13.295 -3.631 c
+13.02 -3.631 12.803 -3.558 12.648 -3.41 c
+12.501 -3.256 12.428 -3.04 12.428 -2.764 c
+12.428 -2.463 12.531 -2.22 12.737 -2.043 c
+12.943 -1.86 13.226 -1.764 13.589 -1.764 c
+13.942 -1.764 l
+13.942 -1.441 l
+13.942 -1.264 13.902 -1.143 13.824 -1.073 c
+13.744 -0.996 13.627 -0.956 13.471 -0.956 c
+13.325 -0.956 13.199 -1 13.104 -1.088 c
+13.016 -1.176 12.972 -1.287 12.972 -1.411 c
+12.487 -1.411 l
+12.487 -1.264 12.531 -1.125 12.619 -0.985 c
+12.707 -0.838 12.825 -0.728 12.972 -0.647 c
+13.126 -0.57 13.299 -0.53 13.486 -0.53 c
+13.799 -0.53 14.034 -0.611 14.192 -0.765 c
+14.346 -0.912 14.427 -1.133 14.427 -1.426 c
+14.427 -2.926 l
+14.435 -3.161 14.471 -3.363 14.53 -3.528 c
+14.53 -3.572 l
+h
+13.369 -3.19 m
+13.486 -3.19 13.596 -3.157 13.707 -3.088 c
+13.814 -3.021 13.891 -2.937 13.942 -2.837 c
+13.942 -2.132 l
+13.677 -2.132 l
+13.442 -2.132 13.255 -2.183 13.119 -2.278 c
+12.991 -2.378 12.928 -2.521 12.928 -2.705 c
+12.928 -2.874 12.958 -2.995 13.016 -3.072 c
+13.082 -3.153 13.199 -3.19 13.369 -3.19 c
+15.464 -0.588 m
+15.478 -0.912 l
+15.662 -0.659 15.904 -0.53 16.199 -0.53 c
+16.727 -0.53 16.996 -0.882 17.007 -1.588 c
+17.007 -3.572 l
+16.522 -3.572 l
+16.522 -1.617 l
+16.522 -1.382 16.482 -1.216 16.405 -1.118 c
+16.324 -1.022 16.206 -0.971 16.052 -0.971 c
+15.934 -0.971 15.823 -1.011 15.728 -1.088 c
+15.629 -1.169 15.551 -1.276 15.493 -1.411 c
+15.493 -3.572 l
+15.008 -3.572 l
+15.008 -0.588 l
+h
+19.293 -3.572 -0.5 2.984 re
+19.322 0.205 m
+19.322 0.118 19.296 0.043 19.248 -0.015 c
+19.208 -0.067 19.138 -0.088 19.042 -0.088 c
+18.955 -0.088 18.884 -0.067 18.837 -0.015 c
+18.797 0.043 18.778 0.11 18.778 0.191 c
+18.778 0.278 18.797 0.353 18.837 0.411 c
+18.884 0.47 18.955 0.5 19.042 0.5 c
+19.138 0.5 19.208 0.47 19.248 0.411 c
+19.296 0.353 19.322 0.282 19.322 0.205 c
+20.424 -0.588 m
+20.439 -0.912 l
+20.623 -0.659 20.866 -0.53 21.159 -0.53 c
+21.689 -0.53 21.957 -0.882 21.968 -1.588 c
+21.968 -3.572 l
+21.483 -3.572 l
+21.483 -1.617 l
+21.483 -1.382 21.442 -1.216 21.365 -1.118 c
+21.284 -1.022 21.167 -0.971 21.012 -0.971 c
+20.895 -0.971 20.785 -1.011 20.689 -1.088 c
+20.59 -1.169 20.513 -1.276 20.454 -1.411 c
+20.454 -3.572 l
+19.969 -3.572 l
+19.969 -0.588 l
+h
+23.048 -3.572 -0.5 2.984 re
+23.077 0.205 m
+23.077 0.118 23.052 0.043 23.004 -0.015 c
+22.963 -0.067 22.894 -0.088 22.799 -0.088 c
+22.71 -0.088 22.641 -0.067 22.593 -0.015 c
+22.552 0.043 22.534 0.11 22.534 0.191 c
+22.534 0.278 22.552 0.353 22.593 0.411 c
+22.641 0.47 22.71 0.5 22.799 0.5 c
+22.894 0.5 22.963 0.47 23.004 0.411 c
+23.052 0.353 23.077 0.282 23.077 0.205 c
+24.357 0.132 m
+24.357 -0.588 l
+24.812 -0.588 l
+24.812 -0.985 l
+24.357 -0.985 l
+24.357 -2.837 l
+24.357 -2.955 24.375 -3.043 24.415 -3.102 c
+24.452 -3.161 24.522 -3.19 24.621 -3.19 c
+24.68 -3.19 24.742 -3.183 24.812 -3.161 c
+24.812 -3.572 l
+24.694 -3.609 24.581 -3.631 24.474 -3.631 c
+24.276 -3.631 24.125 -3.565 24.018 -3.425 c
+23.919 -3.29 23.871 -3.095 23.871 -2.837 c
+23.871 -0.985 l
+23.416 -0.985 l
+23.416 -0.588 l
+23.871 -0.588 l
+23.871 0.132 l
+h
+25.808 -3.572 -0.5 2.984 re
+25.837 0.205 m
+25.837 0.118 25.812 0.043 25.764 -0.015 c
+25.724 -0.067 25.654 -0.088 25.558 -0.088 c
+25.47 -0.088 25.4 -0.067 25.352 -0.015 c
+25.312 0.043 25.294 0.11 25.294 0.191 c
+25.294 0.278 25.312 0.353 25.352 0.411 c
+25.4 0.47 25.47 0.5 25.558 0.5 c
+25.654 0.5 25.724 0.47 25.764 0.411 c
+25.812 0.353 25.837 0.282 25.837 0.205 c
+28.01 -3.572 m
+27.979 -3.506 27.958 -3.396 27.95 -3.249 c
+27.774 -3.506 27.553 -3.631 27.289 -3.631 c
+27.013 -3.631 26.797 -3.558 26.642 -3.41 c
+26.495 -3.256 26.422 -3.04 26.422 -2.764 c
+26.422 -2.463 26.524 -2.22 26.73 -2.043 c
+26.936 -1.86 27.219 -1.764 27.582 -1.764 c
+27.935 -1.764 l
+27.935 -1.441 l
+27.935 -1.264 27.895 -1.143 27.818 -1.073 c
+27.738 -0.996 27.62 -0.956 27.465 -0.956 c
+27.318 -0.956 27.193 -1 27.098 -1.088 c
+27.01 -1.176 26.965 -1.287 26.965 -1.411 c
+26.481 -1.411 l
+26.481 -1.264 26.524 -1.125 26.613 -0.985 c
+26.701 -0.838 26.819 -0.728 26.965 -0.647 c
+27.12 -0.57 27.293 -0.53 27.48 -0.53 c
+27.792 -0.53 28.027 -0.611 28.185 -0.765 c
+28.34 -0.912 28.421 -1.133 28.421 -1.426 c
+28.421 -2.926 l
+28.428 -3.161 28.465 -3.363 28.523 -3.528 c
+28.523 -3.572 l
+h
+27.362 -3.19 m
+27.48 -3.19 27.59 -3.157 27.7 -3.088 c
+27.807 -3.021 27.884 -2.937 27.935 -2.837 c
+27.935 -2.132 l
+27.671 -2.132 l
+27.436 -2.132 27.249 -2.183 27.112 -2.278 c
+26.984 -2.378 26.921 -2.521 26.921 -2.705 c
+26.921 -2.874 26.951 -2.995 27.01 -3.072 c
+27.075 -3.153 27.193 -3.19 27.362 -3.19 c
+29.531 -3.572 -0.5 4.233 re
+32.438 -3.205 m
+32.602 -3.205 32.735 -3.157 32.834 -3.057 c
+32.93 -2.962 32.985 -2.819 32.995 -2.631 c
+33.452 -2.631 l
+33.44 -2.918 33.338 -3.157 33.143 -3.352 c
+32.955 -3.539 32.72 -3.631 32.438 -3.631 c
+32.074 -3.631 31.794 -3.514 31.599 -3.278 c
+31.401 -3.043 31.306 -2.698 31.306 -2.234 c
+31.306 -1.912 l
+31.306 -1.463 31.397 -1.118 31.584 -0.882 c
+31.779 -0.647 32.062 -0.53 32.438 -0.53 c
+32.739 -0.53 32.981 -0.628 33.157 -0.823 c
+33.342 -1.022 33.44 -1.287 33.452 -1.617 c
+32.995 -1.617 l
+32.974 -1.393 32.915 -1.228 32.82 -1.118 c
+32.731 -1.011 32.602 -0.956 32.438 -0.956 c
+32.22 -0.956 32.059 -1.029 31.952 -1.176 c
+31.853 -1.316 31.798 -1.544 31.79 -1.867 c
+31.79 -2.249 l
+31.79 -2.602 31.838 -2.852 31.937 -2.999 c
+32.044 -3.138 32.209 -3.205 32.438 -3.205 c
+33.745 -1.941 m
+33.745 -1.511 33.849 -1.169 34.054 -0.912 c
+34.267 -0.659 34.547 -0.53 34.892 -0.53 c
+35.233 -0.53 35.509 -0.659 35.715 -0.912 c
+35.929 -1.158 36.043 -1.492 36.053 -1.912 c
+36.053 -2.22 l
+36.053 -2.654 35.943 -2.995 35.73 -3.249 c
+35.524 -3.506 35.245 -3.631 34.892 -3.631 c
+34.547 -3.631 34.275 -3.51 34.069 -3.263 c
+33.863 -3.021 33.753 -2.687 33.745 -2.264 c
+h
+34.231 -2.22 m
+34.231 -2.536 34.289 -2.779 34.407 -2.955 c
+34.532 -3.124 34.694 -3.205 34.892 -3.205 c
+35.322 -3.205 35.546 -2.897 35.568 -2.278 c
+35.568 -1.941 l
+35.568 -1.64 35.502 -1.397 35.377 -1.22 c
+35.26 -1.044 35.098 -0.956 34.892 -0.956 c
+34.694 -0.956 34.532 -1.044 34.407 -1.22 c
+34.289 -1.397 34.231 -1.64 34.231 -1.941 c
+h
+36.95 -0.588 m
+36.964 -0.867 l
+37.141 -0.643 37.38 -0.53 37.685 -0.53 c
+38.015 -0.53 38.247 -0.676 38.376 -0.971 c
+38.559 -0.676 38.821 -0.53 39.155 -0.53 c
+39.713 -0.53 39.996 -0.875 40.008 -1.559 c
+40.008 -3.572 l
+39.522 -3.572 l
+39.522 -1.603 l
+39.522 -1.389 39.482 -1.231 39.405 -1.133 c
+39.324 -1.025 39.191 -0.971 39.008 -0.971 c
+38.861 -0.971 38.743 -1.029 38.655 -1.147 c
+38.567 -1.257 38.512 -1.397 38.493 -1.573 c
+38.493 -3.572 l
+38.008 -3.572 l
+38.008 -1.588 l
+37.997 -1.176 37.824 -0.971 37.494 -0.971 c
+37.248 -0.971 37.075 -1.096 36.979 -1.338 c
+36.979 -3.572 l
+36.494 -3.572 l
+36.494 -0.588 l
+h
+40.911 -0.588 m
+40.926 -0.867 l
+41.103 -0.643 41.341 -0.53 41.647 -0.53 c
+41.977 -0.53 42.208 -0.676 42.337 -0.971 c
+42.52 -0.676 42.782 -0.53 43.116 -0.53 c
+43.675 -0.53 43.958 -0.875 43.968 -1.559 c
+43.968 -3.572 l
+43.484 -3.572 l
+43.484 -1.603 l
+43.484 -1.389 43.443 -1.231 43.366 -1.133 c
+43.285 -1.025 43.153 -0.971 42.969 -0.971 c
+42.822 -0.971 42.705 -1.029 42.616 -1.147 c
+42.528 -1.257 42.473 -1.397 42.455 -1.573 c
+42.455 -3.572 l
+41.969 -3.572 l
+41.969 -1.588 l
+41.959 -1.176 41.786 -0.971 41.456 -0.971 c
+41.209 -0.971 41.036 -1.096 40.941 -1.338 c
+40.941 -3.572 l
+40.456 -3.572 l
+40.456 -0.588 l
+h
+44.947 -3.572 -0.5 2.984 re
+44.976 0.205 m
+44.976 0.118 44.949 0.043 44.902 -0.015 c
+44.862 -0.067 44.791 -0.088 44.696 -0.088 c
+44.608 -0.088 44.538 -0.067 44.49 -0.015 c
+44.45 0.043 44.432 0.11 44.432 0.191 c
+44.432 0.278 44.45 0.353 44.49 0.411 c
+44.538 0.47 44.608 0.5 44.696 0.5 c
+44.791 0.5 44.862 0.47 44.902 0.411 c
+44.949 0.353 44.976 0.282 44.976 0.205 c
+46.25 0.132 m
+46.25 -0.588 l
+46.707 -0.588 l
+46.707 -0.985 l
+46.25 -0.985 l
+46.25 -2.837 l
+46.25 -2.955 46.269 -3.043 46.31 -3.102 c
+46.346 -3.161 46.416 -3.19 46.515 -3.19 c
+46.574 -3.19 46.636 -3.183 46.707 -3.161 c
+46.707 -3.572 l
+46.589 -3.609 46.474 -3.631 46.368 -3.631 c
+46.17 -3.631 46.019 -3.565 45.913 -3.425 c
+45.813 -3.29 45.766 -3.095 45.766 -2.837 c
+45.766 -0.985 l
+45.31 -0.985 l
+45.31 -0.588 l
+45.766 -0.588 l
+45.766 0.132 l
+h
+47.173 -4.366 m
+46.879 -4.175 l
+47.056 -3.929 47.147 -3.679 47.158 -3.425 c
+47.158 -2.97 l
+47.658 -2.97 l
+47.658 -3.367 l
+47.658 -3.554 47.607 -3.738 47.511 -3.925 c
+47.423 -4.109 47.309 -4.256 47.173 -4.366 c
+f
+Q
+324.063 101.502 -0.5 2.984 re
+324.092 105.279 m
+324.092 105.192 324.067 105.117 324.019 105.059 c
+323.978 105.007 323.909 104.986 323.814 104.986 c
+323.725 104.986 323.656 105.007 323.608 105.059 c
+323.567 105.117 323.548 105.184 323.548 105.265 c
+323.548 105.352 323.567 105.427 323.608 105.485 c
+323.656 105.544 323.725 105.574 323.814 105.574 c
+323.909 105.574 323.978 105.544 324.019 105.485 c
+324.067 105.427 324.092 105.356 324.092 105.279 c
+325.368 105.206 m
+325.368 104.486 l
+325.823 104.486 l
+325.823 104.089 l
+325.368 104.089 l
+325.368 102.237 l
+325.368 102.119 325.386 102.031 325.426 101.972 c
+325.463 101.913 325.533 101.884 325.632 101.884 c
+325.691 101.884 325.754 101.891 325.823 101.913 c
+325.823 101.502 l
+325.706 101.465 325.592 101.443 325.485 101.443 c
+325.287 101.443 325.136 101.509 325.03 101.649 c
+324.93 101.784 324.882 101.979 324.882 102.237 c
+324.882 104.089 l
+324.427 104.089 l
+324.427 104.486 l
+324.882 104.486 l
+324.882 105.206 l
+h
+327.98 104.177 m
+328.165 104.419 328.4 104.544 328.686 104.544 c
+329.215 104.544 329.484 104.192 329.495 103.486 c
+329.495 101.502 l
+329.009 101.502 l
+329.009 103.457 l
+329.009 103.692 328.969 103.858 328.892 103.956 c
+328.811 104.052 328.693 104.103 328.539 104.103 c
+328.421 104.103 328.311 104.063 328.215 103.986 c
+328.117 103.905 328.04 103.798 327.98 103.663 c
+327.98 101.502 l
+327.496 101.502 l
+327.496 105.735 l
+327.98 105.735 l
+h
+331.564 101.502 m
+331.534 101.568 331.512 101.678 331.504 101.825 c
+331.328 101.568 331.107 101.443 330.843 101.443 c
+330.567 101.443 330.351 101.516 330.197 101.664 c
+330.049 101.818 329.976 102.034 329.976 102.31 c
+329.976 102.611 330.079 102.854 330.284 103.031 c
+330.49 103.214 330.773 103.31 331.137 103.31 c
+331.49 103.31 l
+331.49 103.633 l
+331.49 103.81 331.45 103.931 331.373 104.001 c
+331.292 104.078 331.174 104.118 331.02 104.118 c
+330.872 104.118 330.748 104.074 330.652 103.986 c
+330.564 103.898 330.519 103.787 330.519 103.663 c
+330.035 103.663 l
+330.035 103.81 330.079 103.949 330.167 104.089 c
+330.255 104.236 330.373 104.346 330.519 104.427 c
+330.675 104.504 330.847 104.544 331.034 104.544 c
+331.346 104.544 331.581 104.463 331.739 104.309 c
+331.894 104.162 331.975 103.941 331.975 103.648 c
+331.975 102.148 l
+331.982 101.913 332.019 101.711 332.078 101.546 c
+332.078 101.502 l
+h
+330.916 101.884 m
+331.034 101.884 331.145 101.917 331.255 101.987 c
+331.361 102.053 331.438 102.137 331.49 102.237 c
+331.49 102.942 l
+331.225 102.942 l
+330.99 102.942 330.802 102.891 330.667 102.796 c
+330.538 102.696 330.476 102.553 330.476 102.369 c
+330.476 102.2 330.505 102.079 330.564 102.002 c
+330.63 101.921 330.748 101.884 330.916 101.884 c
+333.996 102.266 m
+333.996 102.372 333.956 102.461 333.879 102.53 c
+333.798 102.607 333.647 102.696 333.422 102.796 c
+333.158 102.902 332.971 102.994 332.865 103.075 c
+332.754 103.152 332.676 103.24 332.629 103.339 c
+332.578 103.434 332.556 103.552 332.556 103.692 c
+332.556 103.935 332.644 104.136 332.82 104.294 c
+332.996 104.46 333.221 104.544 333.497 104.544 c
+333.79 104.544 334.025 104.456 334.202 104.28 c
+334.378 104.111 334.467 103.898 334.467 103.633 c
+333.981 103.633 l
+333.981 103.769 333.93 103.883 333.834 103.971 c
+333.746 104.066 333.632 104.118 333.497 104.118 c
+333.349 104.118 333.235 104.078 333.158 104.001 c
+333.077 103.931 333.04 103.831 333.04 103.706 c
+333.04 103.607 333.07 103.53 333.129 103.471 c
+333.187 103.413 333.327 103.332 333.555 103.236 c
+333.915 103.089 334.162 102.946 334.29 102.81 c
+334.426 102.682 334.496 102.509 334.496 102.295 c
+334.496 102.038 334.4 101.832 334.216 101.678 c
+334.04 101.52 333.805 101.443 333.511 101.443 c
+333.195 101.443 332.942 101.531 332.747 101.707 c
+332.559 101.891 332.468 102.123 332.468 102.399 c
+332.952 102.399 l
+332.96 102.229 333.011 102.097 333.1 102.002 c
+333.195 101.913 333.335 101.869 333.511 101.869 c
+333.665 101.869 333.783 101.902 333.864 101.972 c
+333.952 102.038 333.996 102.137 333.996 102.266 c
+336.612 104.486 m
+336.628 104.162 l
+336.811 104.415 337.054 104.544 337.347 104.544 c
+337.877 104.544 338.145 104.192 338.156 103.486 c
+338.156 101.502 l
+337.671 101.502 l
+337.671 103.457 l
+337.671 103.692 337.63 103.858 337.553 103.956 c
+337.472 104.052 337.355 104.103 337.2 104.103 c
+337.083 104.103 336.973 104.063 336.877 103.986 c
+336.778 103.905 336.701 103.798 336.642 103.663 c
+336.642 101.502 l
+336.157 101.502 l
+336.157 104.486 l
+h
+338.608 103.133 m
+338.608 103.563 338.71 103.905 338.916 104.162 c
+339.13 104.415 339.409 104.544 339.755 104.544 c
+340.096 104.544 340.372 104.415 340.578 104.162 c
+340.79 103.916 340.904 103.582 340.915 103.162 c
+340.915 102.854 l
+340.915 102.42 340.805 102.079 340.592 101.825 c
+340.387 101.568 340.107 101.443 339.755 101.443 c
+339.409 101.443 339.137 101.564 338.931 101.811 c
+338.725 102.053 338.615 102.387 338.608 102.81 c
+h
+339.093 102.854 m
+339.093 102.538 339.152 102.295 339.269 102.119 c
+339.394 101.95 339.556 101.869 339.755 101.869 c
+340.184 101.869 340.408 102.177 340.431 102.796 c
+340.431 103.133 l
+340.431 103.434 340.364 103.677 340.239 103.854 c
+340.121 104.03 339.961 104.118 339.755 104.118 c
+339.556 104.118 339.394 104.03 339.269 103.854 c
+339.152 103.677 339.093 103.434 339.093 103.133 c
+h
+344.705 102.854 m
+344.705 102.383 344.62 102.031 344.454 101.796 c
+344.285 101.56 344.046 101.443 343.734 101.443 c
+343.429 101.443 343.198 101.553 343.043 101.781 c
+343.043 100.355 l
+342.558 100.355 l
+342.558 104.486 l
+342.999 104.486 l
+343.028 104.147 l
+343.183 104.412 343.414 104.544 343.72 104.544 c
+344.05 104.544 344.296 104.427 344.454 104.192 c
+344.62 103.964 344.705 103.625 344.705 103.177 c
+h
+344.219 103.133 m
+344.219 103.464 344.164 103.71 344.057 103.868 c
+343.959 104.022 343.797 104.103 343.572 104.103 c
+343.337 104.103 343.161 103.986 343.043 103.75 c
+343.043 102.208 l
+343.161 101.979 343.341 101.869 343.587 101.869 c
+343.801 101.869 343.959 101.946 344.057 102.104 c
+344.164 102.258 344.219 102.501 344.219 102.825 c
+h
+346.689 101.502 m
+346.66 101.568 346.637 101.678 346.629 101.825 c
+346.454 101.568 346.233 101.443 345.968 101.443 c
+345.693 101.443 345.476 101.516 345.322 101.664 c
+345.175 101.818 345.101 102.034 345.101 102.31 c
+345.101 102.611 345.204 102.854 345.41 103.031 c
+345.615 103.214 345.899 103.31 346.263 103.31 c
+346.615 103.31 l
+346.615 103.633 l
+346.615 103.81 346.575 103.931 346.498 104.001 c
+346.417 104.078 346.299 104.118 346.145 104.118 c
+345.998 104.118 345.873 104.074 345.777 103.986 c
+345.689 103.898 345.645 103.787 345.645 103.663 c
+345.16 103.663 l
+345.16 103.81 345.204 103.949 345.293 104.089 c
+345.38 104.236 345.498 104.346 345.645 104.427 c
+345.8 104.504 345.972 104.544 346.159 104.544 c
+346.471 104.544 346.707 104.463 346.865 104.309 c
+347.019 104.162 347.1 103.941 347.1 103.648 c
+347.1 102.148 l
+347.107 101.913 347.144 101.711 347.203 101.546 c
+347.203 101.502 l
+h
+346.042 101.884 m
+346.159 101.884 346.27 101.917 346.38 101.987 c
+346.486 102.053 346.564 102.137 346.615 102.237 c
+346.615 102.942 l
+346.351 102.942 l
+346.116 102.942 345.928 102.891 345.792 102.796 c
+345.663 102.696 345.601 102.553 345.601 102.369 c
+345.601 102.2 345.63 102.079 345.689 102.002 c
+345.756 101.921 345.873 101.884 346.042 101.884 c
+348.915 104.03 m
+348.846 104.037 348.772 104.045 348.695 104.045 c
+348.438 104.045 348.262 103.905 348.166 103.633 c
+348.166 101.502 l
+347.681 101.502 l
+347.681 104.486 l
+348.152 104.486 l
+348.166 104.177 l
+348.291 104.419 348.474 104.544 348.709 104.544 c
+348.787 104.544 348.85 104.529 348.9 104.5 c
+h
+350.294 101.443 m
+349.919 101.443 349.636 101.549 349.441 101.766 c
+349.243 101.99 349.147 102.318 349.147 102.751 c
+349.147 103.118 l
+349.147 103.559 349.239 103.905 349.426 104.162 c
+349.621 104.415 349.897 104.544 350.249 104.544 c
+350.591 104.544 350.845 104.431 351.014 104.207 c
+351.19 103.978 351.282 103.633 351.293 103.162 c
+351.293 102.854 l
+349.632 102.854 l
+349.632 102.78 l
+349.632 102.457 349.691 102.222 349.808 102.075 c
+349.926 101.936 350.095 101.869 350.323 101.869 c
+350.47 101.869 350.595 101.891 350.705 101.942 c
+350.812 102.002 350.915 102.09 351.014 102.208 c
+351.264 101.899 l
+351.058 101.593 350.735 101.443 350.294 101.443 c
+350.249 104.118 m
+350.043 104.118 349.889 104.049 349.794 103.912 c
+349.694 103.773 349.64 103.559 349.632 103.266 c
+350.808 103.266 l
+350.808 103.339 l
+350.786 103.611 350.735 103.81 350.646 103.927 c
+350.558 104.052 350.426 104.118 350.249 104.118 c
+352.16 104.486 m
+352.175 104.162 l
+352.359 104.415 352.601 104.544 352.896 104.544 c
+353.424 104.544 353.693 104.192 353.704 103.486 c
+353.704 101.502 l
+353.218 101.502 l
+353.218 103.457 l
+353.218 103.692 353.178 103.858 353.101 103.956 c
+353.02 104.052 352.902 104.103 352.748 104.103 c
+352.63 104.103 352.52 104.063 352.425 103.986 c
+352.326 103.905 352.249 103.798 352.19 103.663 c
+352.19 101.502 l
+351.705 101.502 l
+351.705 104.486 l
+h
+354.891 105.206 m
+354.891 104.486 l
+355.346 104.486 l
+355.346 104.089 l
+354.891 104.089 l
+354.891 102.237 l
+354.891 102.119 354.909 102.031 354.949 101.972 c
+354.986 101.913 355.056 101.884 355.155 101.884 c
+355.214 101.884 355.277 101.891 355.346 101.913 c
+355.346 101.502 l
+355.229 101.465 355.115 101.443 355.009 101.443 c
+354.81 101.443 354.66 101.509 354.552 101.649 c
+354.454 101.784 354.406 101.979 354.406 102.237 c
+354.406 104.089 l
+353.95 104.089 l
+353.95 104.486 l
+354.406 104.486 l
+354.406 105.206 l
+h
+357.25 102.266 m
+357.25 102.372 357.21 102.461 357.132 102.53 c
+357.052 102.607 356.9 102.696 356.677 102.796 c
+356.412 102.902 356.225 102.994 356.118 103.075 c
+356.008 103.152 355.931 103.24 355.883 103.339 c
+355.832 103.434 355.809 103.552 355.809 103.692 c
+355.809 103.935 355.898 104.136 356.074 104.294 c
+356.25 104.46 356.474 104.544 356.75 104.544 c
+357.044 104.544 357.28 104.456 357.456 104.28 c
+357.632 104.111 357.721 103.898 357.721 103.633 c
+357.235 103.633 l
+357.235 103.769 357.184 103.883 357.089 103.971 c
+357 104.066 356.886 104.118 356.75 104.118 c
+356.603 104.118 356.489 104.078 356.412 104.001 c
+356.331 103.931 356.295 103.831 356.295 103.706 c
+356.295 103.607 356.324 103.53 356.383 103.471 c
+356.441 103.413 356.582 103.332 356.809 103.236 c
+357.17 103.089 357.415 102.946 357.544 102.81 c
+357.68 102.682 357.75 102.509 357.75 102.295 c
+357.75 102.038 357.654 101.832 357.471 101.678 c
+357.294 101.52 357.059 101.443 356.765 101.443 c
+356.449 101.443 356.195 101.531 356 101.707 c
+355.813 101.891 355.721 102.123 355.721 102.399 c
+356.206 102.399 l
+356.214 102.229 356.265 102.097 356.353 102.002 c
+356.449 101.913 356.588 101.869 356.765 101.869 c
+356.919 101.869 357.037 101.902 357.118 101.972 c
+357.206 102.038 357.25 102.137 357.25 102.266 c
+f
+0.793 0.801 0.129 0.016 K
+0.567 w
+q 1 0 0 1 321.7337 107.7302 cm
+0 0 m
+-4.686 4.844 l
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 318.5327 111.0419 cm
+0 0 m
+1.507 -0.026 l
+-1.856 1.914 l
+-0.026 -1.511 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 318.5327 111.042 cm
+0 0 m
+1.507 -0.026 l
+-1.856 1.914 l
+-0.026 -1.511 l
+0 0 l
+h
+S
+Q
+0.793 0.801 0.129 0.016 K
+0.8 w
+q 1 0 0 1 644.4808 108.7265 cm
+0 0 m
+0.008 -15.25 l
+-6.464 -15.25 l
+-6.468 0 l
+-3.227 3.564 l
+0 0 l
+h
+S
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 640.4863 106.5801 cm
+0 0 m
+1.881 -0.382 l
+1.881 -1.191 l
+-1.103 -0.368 l
+-1.103 0.368 l
+1.881 1.191 l
+1.881 0.382 l
+h
+-1.103 -3.087 m
+-1.103 -2.293 l
+1.969 -2.293 l
+1.66 -1.529 l
+2.322 -1.529 l
+2.91 -2.998 l
+2.91 -3.087 l
+h
+-0.706 -4.12 m
+-0.581 -4.12 -0.478 -4.156 -0.397 -4.237 c
+-0.32 -4.326 -0.279 -4.432 -0.279 -4.561 c
+-0.279 -4.696 -0.32 -4.802 -0.397 -4.883 c
+-0.478 -4.972 -0.581 -5.016 -0.706 -5.016 c
+-0.834 -5.016 -0.937 -4.972 -1.014 -4.883 c
+-1.095 -4.802 -1.133 -4.696 -1.133 -4.561 c
+-1.133 -4.432 -1.095 -4.326 -1.014 -4.237 c
+-0.937 -4.156 -0.834 -4.12 -0.706 -4.12 c
+0.558 -7.886 m
+0 -7.886 -0.427 -7.783 -0.721 -7.578 c
+-1.014 -7.379 -1.162 -7.096 -1.162 -6.724 c
+-1.162 -6.361 -1.022 -6.078 -0.736 -5.872 c
+-0.441 -5.674 -0.03 -5.571 0.5 -5.564 c
+1.263 -5.564 l
+1.811 -5.564 2.234 -5.659 2.528 -5.857 c
+2.822 -6.063 2.969 -6.35 2.969 -6.724 c
+2.969 -7.096 2.822 -7.379 2.528 -7.578 c
+2.241 -7.783 1.83 -7.886 1.294 -7.886 c
+h
+1.367 -7.107 m
+1.679 -7.107 1.914 -7.071 2.072 -7.004 c
+2.238 -6.945 2.322 -6.85 2.322 -6.724 c
+2.322 -6.479 2.032 -6.35 1.454 -6.342 c
+0.455 -6.342 l
+0.132 -6.342 -0.114 -6.372 -0.279 -6.431 c
+-0.437 -6.497 -0.515 -6.596 -0.515 -6.724 c
+-0.515 -6.85 -0.441 -6.945 -0.294 -7.004 c
+-0.14 -7.071 0.091 -7.107 0.397 -7.107 c
+h
+-0.706 -8.32 m
+-0.581 -8.32 -0.478 -8.357 -0.397 -8.437 c
+-0.32 -8.525 -0.279 -8.632 -0.279 -8.76 c
+-0.279 -8.897 -0.32 -9.003 -0.397 -9.084 c
+-0.478 -9.172 -0.581 -9.216 -0.706 -9.216 c
+-0.834 -9.216 -0.937 -9.172 -1.014 -9.084 c
+-1.095 -9.003 -1.133 -8.897 -1.133 -8.76 c
+-1.133 -8.632 -1.095 -8.525 -1.014 -8.437 c
+-0.937 -8.357 -0.834 -8.32 -0.706 -8.32 c
+-1.103 -11.484 m
+-1.103 -10.69 l
+1.969 -10.69 l
+1.66 -9.926 l
+2.322 -9.926 l
+2.91 -11.395 l
+2.91 -11.484 l
+h
+f
+Q
+q 1 0 0 1 573.4436 98.4888 cm
+0 0 m
+-1.058 0 l
+-1.058 -3.572 l
+-1.558 -3.572 l
+-1.558 0 l
+-2.616 0 l
+-2.616 0.44 l
+0 0.44 l
+h
+0.823 -0.897 m
+1.007 -0.655 1.242 -0.53 1.529 -0.53 c
+2.058 -0.53 2.326 -0.882 2.337 -1.588 c
+2.337 -3.572 l
+1.852 -3.572 l
+1.852 -1.617 l
+1.852 -1.382 1.812 -1.216 1.735 -1.118 c
+1.654 -1.022 1.536 -0.971 1.382 -0.971 c
+1.264 -0.971 1.154 -1.011 1.058 -1.088 c
+0.96 -1.169 0.882 -1.276 0.823 -1.411 c
+0.823 -3.572 l
+0.338 -3.572 l
+0.338 0.661 l
+0.823 0.661 l
+h
+3.406 -3.572 -0.5 2.984 re
+3.436 0.205 m
+3.436 0.118 3.41 0.043 3.362 -0.015 c
+3.322 -0.067 3.252 -0.088 3.156 -0.088 c
+3.069 -0.088 2.999 -0.067 2.951 -0.015 c
+2.911 0.043 2.892 0.11 2.892 0.191 c
+2.892 0.278 2.911 0.353 2.951 0.411 c
+2.999 0.47 3.069 0.5 3.156 0.5 c
+3.252 0.5 3.322 0.47 3.362 0.411 c
+3.41 0.353 3.436 0.282 3.436 0.205 c
+5.523 -2.808 m
+5.523 -2.702 5.483 -2.613 5.405 -2.544 c
+5.325 -2.467 5.174 -2.378 4.95 -2.278 c
+4.685 -2.172 4.498 -2.08 4.391 -1.999 c
+4.281 -1.922 4.204 -1.834 4.156 -1.735 c
+4.104 -1.64 4.083 -1.522 4.083 -1.382 c
+4.083 -1.139 4.171 -0.938 4.347 -0.78 c
+4.524 -0.614 4.748 -0.53 5.024 -0.53 c
+5.317 -0.53 5.552 -0.618 5.729 -0.794 c
+5.905 -0.963 5.993 -1.176 5.993 -1.441 c
+5.508 -1.441 l
+5.508 -1.305 5.457 -1.191 5.361 -1.103 c
+5.273 -1.008 5.159 -0.956 5.024 -0.956 c
+4.877 -0.956 4.762 -0.996 4.685 -1.073 c
+4.605 -1.143 4.567 -1.243 4.567 -1.368 c
+4.567 -1.467 4.597 -1.544 4.656 -1.603 c
+4.715 -1.661 4.854 -1.742 5.082 -1.838 c
+5.442 -1.985 5.689 -2.128 5.818 -2.264 c
+5.953 -2.392 6.023 -2.565 6.023 -2.779 c
+6.023 -3.036 5.928 -3.242 5.743 -3.396 c
+5.567 -3.554 5.332 -3.631 5.038 -3.631 c
+4.723 -3.631 4.469 -3.543 4.274 -3.367 c
+4.087 -3.183 3.994 -2.951 3.994 -2.675 c
+4.48 -2.675 l
+4.487 -2.845 4.538 -2.977 4.627 -3.072 c
+4.723 -3.161 4.862 -3.205 5.038 -3.205 c
+5.193 -3.205 5.31 -3.172 5.39 -3.102 c
+5.479 -3.036 5.523 -2.937 5.523 -2.808 c
+8.213 -3.572 -0.5 2.984 re
+8.243 0.205 m
+8.243 0.118 8.216 0.043 8.169 -0.015 c
+8.129 -0.067 8.058 -0.088 7.963 -0.088 c
+7.875 -0.088 7.805 -0.067 7.757 -0.015 c
+7.717 0.043 7.699 0.11 7.699 0.191 c
+7.699 0.278 7.717 0.353 7.757 0.411 c
+7.805 0.47 7.875 0.5 7.963 0.5 c
+8.058 0.5 8.129 0.47 8.169 0.411 c
+8.216 0.353 8.243 0.282 8.243 0.205 c
+10.326 -2.808 m
+10.326 -2.702 10.286 -2.613 10.209 -2.544 c
+10.128 -2.467 9.977 -2.378 9.753 -2.278 c
+9.488 -2.172 9.301 -2.08 9.194 -1.999 c
+9.084 -1.922 9.007 -1.834 8.959 -1.735 c
+8.908 -1.64 8.885 -1.522 8.885 -1.382 c
+8.885 -1.139 8.974 -0.938 9.151 -0.78 c
+9.327 -0.614 9.55 -0.53 9.826 -0.53 c
+10.12 -0.53 10.356 -0.618 10.532 -0.794 c
+10.708 -0.963 10.797 -1.176 10.797 -1.441 c
+10.311 -1.441 l
+10.311 -1.305 10.26 -1.191 10.165 -1.103 c
+10.076 -1.008 9.962 -0.956 9.826 -0.956 c
+9.679 -0.956 9.565 -0.996 9.488 -1.073 c
+9.407 -1.143 9.371 -1.243 9.371 -1.368 c
+9.371 -1.467 9.4 -1.544 9.459 -1.603 c
+9.517 -1.661 9.658 -1.742 9.885 -1.838 c
+10.246 -1.985 10.491 -2.128 10.62 -2.264 c
+10.756 -2.392 10.826 -2.565 10.826 -2.779 c
+10.826 -3.036 10.73 -3.242 10.547 -3.396 c
+10.37 -3.554 10.135 -3.631 9.841 -3.631 c
+9.525 -3.631 9.271 -3.543 9.076 -3.367 c
+8.889 -3.183 8.798 -2.951 8.798 -2.675 c
+9.282 -2.675 l
+9.29 -2.845 9.342 -2.977 9.429 -3.072 c
+9.525 -3.161 9.664 -3.205 9.841 -3.205 c
+9.995 -3.205 10.113 -3.172 10.194 -3.102 c
+10.282 -3.036 10.326 -2.937 10.326 -2.808 c
+14.015 -3.572 m
+13.986 -3.506 13.964 -3.396 13.957 -3.249 c
+13.78 -3.506 13.56 -3.631 13.295 -3.631 c
+13.02 -3.631 12.803 -3.558 12.648 -3.41 c
+12.502 -3.256 12.428 -3.04 12.428 -2.764 c
+12.428 -2.463 12.531 -2.22 12.737 -2.043 c
+12.943 -1.86 13.226 -1.764 13.589 -1.764 c
+13.942 -1.764 l
+13.942 -1.441 l
+13.942 -1.264 13.901 -1.143 13.824 -1.073 c
+13.743 -0.996 13.626 -0.956 13.471 -0.956 c
+13.325 -0.956 13.2 -1 13.104 -1.088 c
+13.016 -1.176 12.972 -1.287 12.972 -1.411 c
+12.486 -1.411 l
+12.486 -1.264 12.531 -1.125 12.619 -0.985 c
+12.708 -0.838 12.825 -0.728 12.972 -0.647 c
+13.126 -0.57 13.299 -0.53 13.486 -0.53 c
+13.799 -0.53 14.034 -0.611 14.192 -0.765 c
+14.346 -0.912 14.427 -1.133 14.427 -1.426 c
+14.427 -2.926 l
+14.435 -3.161 14.471 -3.363 14.53 -3.528 c
+14.53 -3.572 l
+h
+13.369 -3.19 m
+13.486 -3.19 13.596 -3.157 13.707 -3.087 c
+13.814 -3.021 13.891 -2.937 13.942 -2.837 c
+13.942 -2.132 l
+13.677 -2.132 l
+13.442 -2.132 13.255 -2.183 13.119 -2.278 c
+12.991 -2.378 12.928 -2.521 12.928 -2.705 c
+12.928 -2.874 12.957 -2.995 13.016 -3.072 c
+13.082 -3.153 13.2 -3.19 13.369 -3.19 c
+16.845 0.132 m
+16.845 -0.588 l
+17.301 -0.588 l
+17.301 -0.985 l
+16.845 -0.985 l
+16.845 -2.837 l
+16.845 -2.955 16.864 -3.043 16.904 -3.102 c
+16.941 -3.161 17.01 -3.19 17.11 -3.19 c
+17.169 -3.19 17.231 -3.183 17.301 -3.161 c
+17.301 -3.572 l
+17.184 -3.609 17.07 -3.631 16.963 -3.631 c
+16.764 -3.631 16.613 -3.565 16.507 -3.425 c
+16.407 -3.29 16.36 -3.095 16.36 -2.837 c
+16.36 -0.985 l
+15.904 -0.985 l
+15.904 -0.588 l
+16.36 -0.588 l
+16.36 0.132 l
+h
+19.297 -3.572 m
+19.266 -3.506 19.245 -3.396 19.237 -3.249 c
+19.061 -3.506 18.84 -3.631 18.576 -3.631 c
+18.3 -3.631 18.084 -3.558 17.93 -3.41 c
+17.782 -3.256 17.708 -3.04 17.708 -2.764 c
+17.708 -2.463 17.812 -2.22 18.017 -2.043 c
+18.223 -1.86 18.506 -1.764 18.87 -1.764 c
+19.223 -1.764 l
+19.223 -1.441 l
+19.223 -1.264 19.183 -1.143 19.106 -1.073 c
+19.025 -0.996 18.907 -0.956 18.753 -0.956 c
+18.605 -0.956 18.481 -1 18.385 -1.088 c
+18.296 -1.176 18.252 -1.287 18.252 -1.411 c
+17.768 -1.411 l
+17.768 -1.264 17.812 -1.125 17.899 -0.985 c
+17.988 -0.838 18.105 -0.728 18.252 -0.647 c
+18.406 -0.57 18.58 -0.53 18.767 -0.53 c
+19.079 -0.53 19.314 -0.611 19.472 -0.765 c
+19.627 -0.912 19.708 -1.133 19.708 -1.426 c
+19.708 -2.926 l
+19.715 -3.161 19.752 -3.363 19.811 -3.528 c
+19.811 -3.572 l
+h
+18.649 -3.19 m
+18.767 -3.19 18.877 -3.157 18.988 -3.087 c
+19.094 -3.021 19.171 -2.937 19.223 -2.837 c
+19.223 -2.132 l
+18.958 -2.132 l
+18.723 -2.132 18.535 -2.183 18.4 -2.278 c
+18.271 -2.378 18.208 -2.521 18.208 -2.705 c
+18.208 -2.874 18.238 -2.995 18.296 -3.072 c
+18.363 -3.153 18.481 -3.19 18.649 -3.19 c
+20.185 -1.941 m
+20.185 -1.482 20.266 -1.133 20.436 -0.897 c
+20.612 -0.655 20.862 -0.53 21.185 -0.53 c
+21.487 -0.53 21.718 -0.662 21.876 -0.927 c
+21.905 -0.588 l
+22.346 -0.588 l
+22.346 -3.602 l
+22.346 -3.973 22.247 -4.256 22.052 -4.454 c
+21.865 -4.649 21.604 -4.748 21.273 -4.748 c
+21.126 -4.748 20.957 -4.707 20.773 -4.63 c
+20.586 -4.561 20.45 -4.472 20.362 -4.366 c
+20.553 -4.028 l
+20.758 -4.233 20.983 -4.337 21.229 -4.337 c
+21.63 -4.337 21.836 -4.109 21.847 -3.66 c
+21.847 -3.278 l
+21.689 -3.514 21.468 -3.631 21.185 -3.631 c
+20.869 -3.631 20.627 -3.514 20.45 -3.278 c
+20.281 -3.043 20.193 -2.712 20.185 -2.278 c
+h
+20.671 -2.22 m
+20.671 -2.554 20.718 -2.801 20.818 -2.955 c
+20.913 -3.113 21.074 -3.19 21.303 -3.19 c
+21.545 -3.19 21.729 -3.069 21.847 -2.822 c
+21.847 -1.338 l
+21.729 -1.096 21.552 -0.971 21.317 -0.971 c
+21.09 -0.971 20.928 -1.052 20.833 -1.206 c
+20.733 -1.364 20.677 -1.603 20.671 -1.926 c
+h
+22.909 -3.308 m
+22.909 -3.219 22.931 -3.146 22.982 -3.087 c
+23.041 -3.028 23.118 -2.999 23.217 -2.999 c
+23.324 -2.999 23.401 -3.028 23.453 -3.087 c
+23.511 -3.146 23.54 -3.219 23.54 -3.308 c
+23.54 -3.389 23.511 -3.454 23.453 -3.514 c
+23.401 -3.572 23.324 -3.602 23.217 -3.602 c
+23.118 -3.602 23.041 -3.572 22.982 -3.514 c
+22.931 -3.454 22.909 -3.389 22.909 -3.308 c
+26.061 -3.572 -0.5 4.012 re
+27.421 0.132 m
+27.421 -0.588 l
+27.877 -0.588 l
+27.877 -0.985 l
+27.421 -0.985 l
+27.421 -2.837 l
+27.421 -2.955 27.44 -3.043 27.48 -3.102 c
+27.517 -3.161 27.586 -3.19 27.686 -3.19 c
+27.744 -3.19 27.807 -3.183 27.877 -3.161 c
+27.877 -3.572 l
+27.759 -3.609 27.646 -3.631 27.538 -3.631 c
+27.34 -3.631 27.189 -3.565 27.083 -3.425 c
+26.984 -3.29 26.936 -3.095 26.936 -2.837 c
+26.936 -0.985 l
+26.48 -0.985 l
+26.48 -0.588 l
+26.936 -0.588 l
+26.936 0.132 l
+h
+30.078 -3.572 -0.501 4.233 re
+30.647 -1.941 m
+30.647 -1.511 30.751 -1.169 30.956 -0.912 c
+31.17 -0.659 31.449 -0.53 31.794 -0.53 c
+32.136 -0.53 32.411 -0.659 32.617 -0.912 c
+32.83 -1.158 32.945 -1.492 32.955 -1.912 c
+32.955 -2.22 l
+32.955 -2.654 32.845 -2.995 32.632 -3.249 c
+32.426 -3.506 32.147 -3.631 31.794 -3.631 c
+31.449 -3.631 31.177 -3.51 30.971 -3.263 c
+30.765 -3.021 30.655 -2.687 30.647 -2.264 c
+h
+31.133 -2.22 m
+31.133 -2.536 31.191 -2.779 31.309 -2.955 c
+31.434 -3.124 31.596 -3.205 31.794 -3.205 c
+32.224 -3.205 32.448 -2.897 32.471 -2.278 c
+32.471 -1.941 l
+32.471 -1.64 32.404 -1.397 32.279 -1.22 c
+32.162 -1.044 32 -0.956 31.794 -0.956 c
+31.596 -0.956 31.434 -1.044 31.309 -1.22 c
+31.191 -1.397 31.133 -1.64 31.133 -1.941 c
+h
+33.294 -1.941 m
+33.294 -1.511 33.396 -1.169 33.602 -0.912 c
+33.815 -0.659 34.094 -0.53 34.44 -0.53 c
+34.782 -0.53 35.058 -0.659 35.263 -0.912 c
+35.476 -1.158 35.59 -1.492 35.601 -1.912 c
+35.601 -2.22 l
+35.601 -2.654 35.491 -2.995 35.278 -3.249 c
+35.072 -3.506 34.792 -3.631 34.44 -3.631 c
+34.094 -3.631 33.822 -3.51 33.616 -3.263 c
+33.411 -3.021 33.3 -2.687 33.294 -2.264 c
+h
+33.778 -2.22 m
+33.778 -2.536 33.837 -2.779 33.955 -2.955 c
+34.08 -3.124 34.241 -3.205 34.44 -3.205 c
+34.869 -3.205 35.094 -2.897 35.116 -2.278 c
+35.116 -1.941 l
+35.116 -1.64 35.05 -1.397 34.925 -1.22 c
+34.807 -1.044 34.646 -0.956 34.44 -0.956 c
+34.241 -0.956 34.08 -1.044 33.955 -1.22 c
+33.837 -1.397 33.778 -1.64 33.778 -1.941 c
+h
+36.791 -2.205 m
+36.527 -2.5 l
+36.527 -3.572 l
+36.042 -3.572 l
+36.042 0.661 l
+36.527 0.661 l
+36.527 -1.867 l
+37.453 -0.588 l
+38.042 -0.588 l
+37.101 -1.838 l
+38.173 -3.572 l
+37.6 -3.572 l
+h
+39.856 -2.808 m
+39.856 -2.702 39.816 -2.613 39.739 -2.544 c
+39.658 -2.467 39.507 -2.378 39.283 -2.278 c
+39.019 -2.172 38.831 -2.08 38.725 -1.999 c
+38.615 -1.922 38.537 -1.834 38.489 -1.735 c
+38.438 -1.64 38.416 -1.522 38.416 -1.382 c
+38.416 -1.139 38.504 -0.938 38.68 -0.78 c
+38.857 -0.614 39.081 -0.53 39.357 -0.53 c
+39.65 -0.53 39.885 -0.618 40.062 -0.794 c
+40.238 -0.963 40.327 -1.176 40.327 -1.441 c
+39.842 -1.441 l
+39.842 -1.305 39.79 -1.191 39.695 -1.103 c
+39.607 -1.008 39.492 -0.956 39.357 -0.956 c
+39.21 -0.956 39.096 -0.996 39.019 -1.073 c
+38.938 -1.143 38.901 -1.243 38.901 -1.368 c
+38.901 -1.467 38.931 -1.544 38.989 -1.603 c
+39.048 -1.661 39.187 -1.742 39.415 -1.838 c
+39.775 -1.985 40.022 -2.128 40.151 -2.264 c
+40.286 -2.392 40.356 -2.565 40.356 -2.779 c
+40.356 -3.036 40.261 -3.242 40.077 -3.396 c
+39.901 -3.554 39.665 -3.631 39.372 -3.631 c
+39.056 -3.631 38.802 -3.543 38.607 -3.367 c
+38.42 -3.183 38.328 -2.951 38.328 -2.675 c
+38.813 -2.675 l
+38.821 -2.845 38.871 -2.977 38.96 -3.072 c
+39.056 -3.161 39.195 -3.205 39.372 -3.205 c
+39.526 -3.205 39.644 -3.172 39.725 -3.102 c
+39.812 -3.036 39.856 -2.937 39.856 -2.808 c
+42.547 -3.572 -0.5 4.233 re
+43.752 -3.572 -0.5 2.984 re
+43.781 0.205 m
+43.781 0.118 43.756 0.043 43.708 -0.015 c
+43.667 -0.067 43.598 -0.088 43.502 -0.088 c
+43.413 -0.088 43.344 -0.067 43.296 -0.015 c
+43.255 0.043 43.237 0.11 43.237 0.191 c
+43.237 0.278 43.255 0.353 43.296 0.411 c
+43.344 0.47 43.413 0.5 43.502 0.5 c
+43.598 0.5 43.667 0.47 43.708 0.411 c
+43.756 0.353 43.781 0.282 43.781 0.205 c
+45.177 -2.205 m
+44.913 -2.5 l
+44.913 -3.572 l
+44.428 -3.572 l
+44.428 0.661 l
+44.913 0.661 l
+44.913 -1.867 l
+45.839 -0.588 l
+46.427 -0.588 l
+45.487 -1.838 l
+46.559 -3.572 l
+45.986 -3.572 l
+h
+47.808 -3.631 m
+47.434 -3.631 47.151 -3.525 46.956 -3.308 c
+46.758 -3.084 46.663 -2.756 46.663 -2.323 c
+46.663 -1.956 l
+46.663 -1.515 46.754 -1.169 46.941 -0.912 c
+47.136 -0.659 47.411 -0.53 47.764 -0.53 c
+48.107 -0.53 48.36 -0.643 48.529 -0.867 c
+48.705 -1.096 48.797 -1.441 48.808 -1.912 c
+48.808 -2.22 l
+47.147 -2.22 l
+47.147 -2.294 l
+47.147 -2.617 47.206 -2.852 47.324 -2.999 c
+47.441 -3.138 47.61 -3.205 47.839 -3.205 c
+47.985 -3.205 48.11 -3.183 48.22 -3.132 c
+48.327 -3.072 48.429 -2.984 48.529 -2.866 c
+48.779 -3.175 l
+48.573 -3.481 48.25 -3.631 47.808 -3.631 c
+47.764 -0.956 m
+47.559 -0.956 47.405 -1.025 47.309 -1.162 c
+47.21 -1.301 47.155 -1.515 47.147 -1.808 c
+48.323 -1.808 l
+48.323 -1.735 l
+48.301 -1.463 48.25 -1.264 48.161 -1.147 c
+48.074 -1.022 47.941 -0.956 47.764 -0.956 c
+51.954 -3.572 m
+51.924 -3.506 51.902 -3.396 51.895 -3.249 c
+51.719 -3.506 51.498 -3.631 51.234 -3.631 c
+50.958 -3.631 50.742 -3.558 50.586 -3.41 c
+50.44 -3.256 50.366 -3.04 50.366 -2.764 c
+50.366 -2.463 50.469 -2.22 50.675 -2.043 c
+50.881 -1.86 51.164 -1.764 51.527 -1.764 c
+51.88 -1.764 l
+51.88 -1.441 l
+51.88 -1.264 51.839 -1.143 51.762 -1.073 c
+51.682 -0.996 51.564 -0.956 51.41 -0.956 c
+51.263 -0.956 51.138 -1 51.043 -1.088 c
+50.954 -1.176 50.91 -1.287 50.91 -1.411 c
+50.426 -1.411 l
+50.426 -1.264 50.469 -1.125 50.557 -0.985 c
+50.646 -0.838 50.763 -0.728 50.91 -0.647 c
+51.064 -0.57 51.237 -0.53 51.425 -0.53 c
+51.737 -0.53 51.972 -0.611 52.13 -0.765 c
+52.284 -0.912 52.365 -1.133 52.365 -1.426 c
+52.365 -2.926 l
+52.373 -3.161 52.41 -3.363 52.468 -3.528 c
+52.468 -3.572 l
+h
+51.307 -3.19 m
+51.425 -3.19 51.535 -3.157 51.645 -3.087 c
+51.752 -3.021 51.829 -2.937 51.88 -2.837 c
+51.88 -2.132 l
+51.616 -2.132 l
+51.38 -2.132 51.193 -2.183 51.057 -2.278 c
+50.929 -2.378 50.866 -2.521 50.866 -2.705 c
+50.866 -2.874 50.896 -2.995 50.954 -3.072 c
+51.02 -3.153 51.138 -3.19 51.307 -3.19 c
+f
+Q
+q 1 0 0 1 559.3175 89.0664 cm
+0 0 m
+0.574 2.249 l
+1.073 2.249 l
+0.177 -0.735 l
+-0.176 -0.735 l
+-1.072 2.249 l
+-0.588 2.249 l
+h
+2.444 -0.794 m
+2.07 -0.794 1.786 -0.688 1.592 -0.47 c
+1.393 -0.246 1.297 0.081 1.297 0.515 c
+1.297 0.881 l
+1.297 1.323 1.389 1.668 1.577 1.926 c
+1.771 2.179 2.047 2.308 2.4 2.308 c
+2.741 2.308 2.995 2.194 3.165 1.97 c
+3.341 1.741 3.433 1.396 3.444 0.926 c
+3.444 0.617 l
+1.783 0.617 l
+1.783 0.544 l
+1.783 0.22 1.841 -0.015 1.959 -0.162 c
+2.076 -0.301 2.245 -0.368 2.473 -0.368 c
+2.621 -0.368 2.745 -0.345 2.856 -0.294 c
+2.962 -0.235 3.065 -0.147 3.165 -0.029 c
+3.414 -0.338 l
+3.209 -0.643 2.885 -0.794 2.444 -0.794 c
+2.4 1.881 m
+2.194 1.881 2.039 1.812 1.945 1.675 c
+1.845 1.536 1.79 1.323 1.783 1.029 c
+2.959 1.029 l
+2.959 1.103 l
+2.936 1.374 2.885 1.573 2.797 1.691 c
+2.708 1.816 2.577 1.881 2.4 1.881 c
+5.09 1.793 m
+5.02 1.801 4.946 1.808 4.869 1.808 c
+4.612 1.808 4.436 1.668 4.341 1.396 c
+4.341 -0.735 l
+3.855 -0.735 l
+3.855 2.249 l
+4.325 2.249 l
+4.341 1.94 l
+4.465 2.183 4.649 2.308 4.884 2.308 c
+4.961 2.308 5.023 2.293 5.075 2.263 c
+h
+6.901 0.029 m
+6.901 0.135 6.861 0.224 6.784 0.294 c
+6.703 0.371 6.552 0.459 6.328 0.559 c
+6.064 0.665 5.876 0.757 5.77 0.838 c
+5.659 0.915 5.582 1.003 5.534 1.103 c
+5.483 1.198 5.461 1.315 5.461 1.455 c
+5.461 1.698 5.549 1.899 5.725 2.057 c
+5.902 2.223 6.126 2.308 6.402 2.308 c
+6.696 2.308 6.931 2.219 7.107 2.043 c
+7.284 1.874 7.372 1.661 7.372 1.396 c
+6.887 1.396 l
+6.887 1.532 6.835 1.646 6.739 1.735 c
+6.652 1.83 6.538 1.881 6.402 1.881 c
+6.255 1.881 6.141 1.841 6.064 1.764 c
+5.983 1.694 5.946 1.595 5.946 1.469 c
+5.946 1.371 5.976 1.294 6.034 1.234 c
+6.093 1.176 6.232 1.095 6.461 0.999 c
+6.82 0.852 7.067 0.709 7.196 0.573 c
+7.331 0.445 7.402 0.272 7.402 0.058 c
+7.402 -0.199 7.306 -0.405 7.122 -0.559 c
+6.945 -0.717 6.71 -0.794 6.417 -0.794 c
+6.101 -0.794 5.847 -0.706 5.652 -0.53 c
+5.465 -0.345 5.373 -0.114 5.373 0.162 c
+5.858 0.162 l
+5.865 -0.008 5.916 -0.14 6.005 -0.235 c
+6.101 -0.324 6.24 -0.368 6.417 -0.368 c
+6.571 -0.368 6.689 -0.335 6.77 -0.264 c
+6.857 -0.199 6.901 -0.1 6.901 0.029 c
+8.386 -0.735 -0.5 2.984 re
+8.416 3.042 m
+8.416 2.955 8.389 2.881 8.342 2.822 c
+8.302 2.77 8.231 2.749 8.136 2.749 c
+8.048 2.749 7.978 2.77 7.93 2.822 c
+7.89 2.881 7.872 2.947 7.872 3.028 c
+7.872 3.116 7.89 3.19 7.93 3.248 c
+7.978 3.308 8.048 3.337 8.136 3.337 c
+8.231 3.337 8.302 3.308 8.342 3.248 c
+8.389 3.19 8.416 3.119 8.416 3.042 c
+8.96 0.897 m
+8.96 1.326 9.062 1.668 9.268 1.926 c
+9.481 2.179 9.76 2.308 10.106 2.308 c
+10.448 2.308 10.723 2.179 10.93 1.926 c
+11.142 1.679 11.256 1.345 11.267 0.926 c
+11.267 0.617 l
+11.267 0.183 11.157 -0.158 10.944 -0.412 c
+10.738 -0.669 10.459 -0.794 10.106 -0.794 c
+9.76 -0.794 9.488 -0.673 9.283 -0.426 c
+9.077 -0.183 8.967 0.151 8.96 0.573 c
+h
+9.444 0.617 m
+9.444 0.301 9.503 0.058 9.621 -0.118 c
+9.746 -0.287 9.908 -0.368 10.106 -0.368 c
+10.536 -0.368 10.76 -0.059 10.782 0.559 c
+10.782 0.897 l
+10.782 1.198 10.716 1.44 10.591 1.617 c
+10.473 1.793 10.311 1.881 10.106 1.881 c
+9.908 1.881 9.746 1.793 9.621 1.617 c
+9.503 1.44 9.444 1.198 9.444 0.897 c
+h
+12.16 2.249 m
+12.175 1.926 l
+12.358 2.179 12.601 2.308 12.895 2.308 c
+13.424 2.308 13.692 1.955 13.704 1.249 c
+13.704 -0.735 l
+13.218 -0.735 l
+13.218 1.22 l
+13.218 1.455 13.178 1.621 13.101 1.72 c
+13.02 1.816 12.902 1.866 12.748 1.866 c
+12.63 1.866 12.52 1.826 12.424 1.749 c
+12.326 1.668 12.248 1.562 12.189 1.426 c
+12.189 -0.735 l
+11.705 -0.735 l
+11.705 2.249 l
+h
+16.9 0.029 m
+16.9 0.135 16.86 0.224 16.783 0.294 c
+16.702 0.371 16.551 0.459 16.327 0.559 c
+16.063 0.665 15.875 0.757 15.769 0.838 c
+15.659 0.915 15.581 1.003 15.533 1.103 c
+15.482 1.198 15.46 1.315 15.46 1.455 c
+15.46 1.698 15.549 1.899 15.724 2.057 c
+15.901 2.223 16.125 2.308 16.401 2.308 c
+16.694 2.308 16.93 2.219 17.106 2.043 c
+17.282 1.874 17.371 1.661 17.371 1.396 c
+16.886 1.396 l
+16.886 1.532 16.835 1.646 16.739 1.735 c
+16.651 1.83 16.536 1.881 16.401 1.881 c
+16.254 1.881 16.14 1.841 16.063 1.764 c
+15.982 1.694 15.946 1.595 15.946 1.469 c
+15.946 1.371 15.975 1.294 16.033 1.234 c
+16.092 1.176 16.231 1.095 16.459 0.999 c
+16.819 0.852 17.066 0.709 17.195 0.573 c
+17.33 0.445 17.4 0.272 17.4 0.058 c
+17.4 -0.199 17.305 -0.405 17.121 -0.559 c
+16.945 -0.717 16.709 -0.794 16.416 -0.794 c
+16.1 -0.794 15.846 -0.706 15.651 -0.53 c
+15.464 -0.345 15.372 -0.114 15.372 0.162 c
+15.857 0.162 l
+15.865 -0.008 15.915 -0.14 16.004 -0.235 c
+16.1 -0.324 16.239 -0.368 16.416 -0.368 c
+16.57 -0.368 16.688 -0.335 16.769 -0.264 c
+16.856 -0.199 16.9 -0.1 16.9 0.029 c
+17.756 0.897 m
+17.756 1.326 17.86 1.668 18.066 1.926 c
+18.279 2.179 18.558 2.308 18.903 2.308 c
+19.245 2.308 19.52 2.179 19.726 1.926 c
+19.94 1.679 20.054 1.345 20.064 0.926 c
+20.064 0.617 l
+20.064 0.183 19.954 -0.158 19.741 -0.412 c
+19.535 -0.669 19.256 -0.794 18.903 -0.794 c
+18.558 -0.794 18.286 -0.673 18.08 -0.426 c
+17.874 -0.183 17.764 0.151 17.756 0.573 c
+h
+18.242 0.617 m
+18.242 0.301 18.301 0.058 18.418 -0.118 c
+18.543 -0.287 18.705 -0.368 18.903 -0.368 c
+19.333 -0.368 19.557 -0.059 19.58 0.559 c
+19.58 0.897 l
+19.58 1.198 19.514 1.44 19.389 1.617 c
+19.271 1.793 19.109 1.881 18.903 1.881 c
+18.705 1.881 18.543 1.793 18.418 1.617 c
+18.301 1.44 18.242 1.198 18.242 0.897 c
+h
+22.236 -0.735 -0.5 2.984 re
+22.265 3.042 m
+22.265 2.955 22.24 2.881 22.192 2.822 c
+22.152 2.77 22.082 2.749 21.986 2.749 c
+21.898 2.749 21.829 2.77 21.781 2.822 c
+21.74 2.881 21.722 2.947 21.722 3.028 c
+21.722 3.116 21.74 3.19 21.781 3.248 c
+21.829 3.308 21.898 3.337 21.986 3.337 c
+22.082 3.337 22.152 3.308 22.192 3.248 c
+22.24 3.19 22.265 3.119 22.265 3.042 c
+23.541 2.969 m
+23.541 2.249 l
+23.996 2.249 l
+23.996 1.852 l
+23.541 1.852 l
+23.541 0 l
+23.541 -0.118 23.559 -0.206 23.599 -0.264 c
+23.636 -0.324 23.707 -0.353 23.805 -0.353 c
+23.865 -0.353 23.927 -0.345 23.996 -0.324 c
+23.996 -0.735 l
+23.879 -0.771 23.765 -0.794 23.659 -0.794 c
+23.46 -0.794 23.31 -0.728 23.202 -0.588 c
+23.104 -0.452 23.056 -0.258 23.056 0 c
+23.056 1.852 l
+22.6 1.852 l
+22.6 2.249 l
+23.056 2.249 l
+23.056 2.969 l
+h
+24.787 3.19 m
+24.742 2.175 l
+24.375 2.175 l
+24.39 3.499 l
+24.787 3.499 l
+h
+26.613 0.029 m
+26.613 0.135 26.572 0.224 26.495 0.294 c
+26.414 0.371 26.263 0.459 26.04 0.559 c
+25.775 0.665 25.588 0.757 25.481 0.838 c
+25.371 0.915 25.294 1.003 25.246 1.103 c
+25.195 1.198 25.172 1.315 25.172 1.455 c
+25.172 1.698 25.261 1.899 25.437 2.057 c
+25.613 2.223 25.837 2.308 26.113 2.308 c
+26.407 2.308 26.643 2.219 26.819 2.043 c
+26.995 1.874 27.083 1.661 27.083 1.396 c
+26.598 1.396 l
+26.598 1.532 26.547 1.646 26.452 1.735 c
+26.363 1.83 26.249 1.881 26.113 1.881 c
+25.966 1.881 25.852 1.841 25.775 1.764 c
+25.694 1.694 25.658 1.595 25.658 1.469 c
+25.658 1.371 25.687 1.294 25.746 1.234 c
+25.804 1.176 25.944 1.095 26.172 0.999 c
+26.533 0.852 26.778 0.709 26.907 0.573 c
+27.042 0.445 27.113 0.272 27.113 0.058 c
+27.113 -0.199 27.017 -0.405 26.834 -0.559 c
+26.657 -0.717 26.422 -0.794 26.128 -0.794 c
+25.812 -0.794 25.558 -0.706 25.363 -0.53 c
+25.176 -0.345 25.084 -0.114 25.084 0.162 c
+25.569 0.162 l
+25.577 -0.008 25.629 -0.14 25.716 -0.235 c
+25.812 -0.324 25.951 -0.368 26.128 -0.368 c
+26.282 -0.368 26.4 -0.335 26.481 -0.264 c
+26.569 -0.199 26.613 -0.1 26.613 0.029 c
+30.92 0.617 m
+30.92 0.147 30.836 -0.206 30.67 -0.441 c
+30.501 -0.676 30.262 -0.794 29.949 -0.794 c
+29.645 -0.794 29.413 -0.684 29.259 -0.455 c
+29.259 -1.881 l
+28.773 -1.881 l
+28.773 2.249 l
+29.215 2.249 l
+29.244 1.911 l
+29.398 2.175 29.629 2.308 29.935 2.308 c
+30.265 2.308 30.512 2.19 30.67 1.955 c
+30.836 1.727 30.92 1.389 30.92 0.941 c
+h
+30.435 0.897 m
+30.435 1.228 30.379 1.473 30.273 1.631 c
+30.174 1.786 30.012 1.866 29.788 1.866 c
+29.552 1.866 29.376 1.749 29.259 1.514 c
+29.259 -0.029 l
+29.376 -0.258 29.556 -0.368 29.803 -0.368 c
+30.016 -0.368 30.174 -0.291 30.273 -0.133 c
+30.379 0.022 30.435 0.264 30.435 0.588 c
+h
+32.614 1.793 m
+32.544 1.801 32.471 1.808 32.393 1.808 c
+32.137 1.808 31.96 1.668 31.864 1.396 c
+31.864 -0.735 l
+31.379 -0.735 l
+31.379 2.249 l
+31.85 2.249 l
+31.864 1.94 l
+31.989 2.183 32.173 2.308 32.408 2.308 c
+32.486 2.308 32.548 2.293 32.599 2.263 c
+h
+32.831 0.897 m
+32.831 1.326 32.933 1.668 33.139 1.926 c
+33.353 2.179 33.631 2.308 33.978 2.308 c
+34.319 2.308 34.595 2.179 34.801 1.926 c
+35.013 1.679 35.127 1.345 35.138 0.926 c
+35.138 0.617 l
+35.138 0.183 35.028 -0.158 34.815 -0.412 c
+34.609 -0.669 34.33 -0.794 33.978 -0.794 c
+33.631 -0.794 33.36 -0.673 33.154 -0.426 c
+32.948 -0.183 32.838 0.151 32.831 0.573 c
+h
+33.315 0.617 m
+33.315 0.301 33.375 0.058 33.492 -0.118 c
+33.617 -0.287 33.779 -0.368 33.978 -0.368 c
+34.408 -0.368 34.631 -0.059 34.653 0.559 c
+34.653 0.897 l
+34.653 1.198 34.587 1.44 34.462 1.617 c
+34.344 1.793 34.183 1.881 33.978 1.881 c
+33.779 1.881 33.617 1.793 33.492 1.617 c
+33.375 1.44 33.315 1.198 33.315 0.897 c
+h
+37.737 0.617 m
+37.737 0.147 37.652 -0.206 37.487 -0.441 c
+37.317 -0.676 37.076 -0.794 36.752 -0.794 c
+36.436 -0.794 36.201 -0.658 36.046 -0.382 c
+36.017 -0.735 l
+35.576 -0.735 l
+35.576 3.499 l
+36.06 3.499 l
+36.06 1.926 l
+36.215 2.179 36.447 2.308 36.752 2.308 c
+37.076 2.308 37.317 2.19 37.487 1.955 c
+37.652 1.72 37.737 1.371 37.737 0.912 c
+h
+37.251 0.897 m
+37.251 1.249 37.2 1.5 37.105 1.646 c
+37.005 1.793 36.843 1.866 36.619 1.866 c
+36.373 1.866 36.185 1.727 36.06 1.455 c
+36.06 0.044 l
+36.178 -0.22 36.37 -0.353 36.634 -0.353 c
+36.847 -0.353 37.005 -0.279 37.105 -0.133 c
+37.2 0.022 37.251 0.264 37.251 0.588 c
+h
+39.71 -0.735 m
+39.68 -0.669 39.659 -0.559 39.651 -0.412 c
+39.474 -0.669 39.254 -0.794 38.99 -0.794 c
+38.714 -0.794 38.497 -0.721 38.343 -0.573 c
+38.196 -0.419 38.122 -0.202 38.122 0.073 c
+38.122 0.374 38.225 0.617 38.431 0.794 c
+38.637 0.977 38.919 1.073 39.283 1.073 c
+39.636 1.073 l
+39.636 1.396 l
+39.636 1.573 39.596 1.694 39.519 1.764 c
+39.438 1.841 39.32 1.881 39.166 1.881 c
+39.019 1.881 38.894 1.837 38.799 1.749 c
+38.71 1.661 38.666 1.55 38.666 1.426 c
+38.181 1.426 l
+38.181 1.573 38.225 1.712 38.313 1.852 c
+38.402 1.999 38.519 2.109 38.666 2.19 c
+38.82 2.267 38.994 2.308 39.181 2.308 c
+39.493 2.308 39.728 2.227 39.886 2.072 c
+40.041 1.926 40.122 1.705 40.122 1.411 c
+40.122 -0.088 l
+40.129 -0.324 40.166 -0.526 40.224 -0.691 c
+40.224 -0.735 l
+h
+39.063 -0.353 m
+39.181 -0.353 39.291 -0.32 39.401 -0.25 c
+39.507 -0.183 39.584 -0.1 39.636 0 c
+39.636 0.706 l
+39.372 0.706 l
+39.137 0.706 38.949 0.654 38.813 0.559 c
+38.684 0.459 38.622 0.316 38.622 0.133 c
+38.622 -0.037 38.651 -0.158 38.71 -0.235 c
+38.776 -0.316 38.894 -0.353 39.063 -0.353 c
+42.863 0.617 m
+42.863 0.147 42.778 -0.206 42.613 -0.441 c
+42.444 -0.676 42.202 -0.794 41.878 -0.794 c
+41.562 -0.794 41.327 -0.658 41.172 -0.382 c
+41.143 -0.735 l
+40.702 -0.735 l
+40.702 3.499 l
+41.187 3.499 l
+41.187 1.926 l
+41.342 2.179 41.573 2.308 41.878 2.308 c
+42.202 2.308 42.444 2.19 42.613 1.955 c
+42.778 1.72 42.863 1.371 42.863 0.912 c
+h
+42.377 0.897 m
+42.377 1.249 42.327 1.5 42.231 1.646 c
+42.132 1.793 41.97 1.866 41.745 1.866 c
+41.5 1.866 41.312 1.727 41.187 1.455 c
+41.187 0.044 l
+41.305 -0.22 41.496 -0.353 41.76 -0.353 c
+41.974 -0.353 42.132 -0.279 42.231 -0.133 c
+42.327 0.022 42.377 0.264 42.377 0.588 c
+h
+43.833 -0.735 -0.5 4.233 re
+45.317 0.073 m
+45.861 2.249 l
+46.376 2.249 l
+45.406 -1.161 l
+45.336 -1.415 45.233 -1.606 45.097 -1.735 c
+44.957 -1.87 44.806 -1.941 44.642 -1.941 c
+44.571 -1.941 44.487 -1.926 44.392 -1.897 c
+44.392 -1.484 l
+44.494 -1.5 l
+44.631 -1.5 44.737 -1.463 44.818 -1.396 c
+44.906 -1.326 44.972 -1.209 45.024 -1.043 c
+45.112 -0.706 l
+44.245 2.249 l
+44.773 2.249 l
+h
+49.433 -0.735 m
+49.404 -0.669 49.382 -0.559 49.375 -0.412 c
+49.198 -0.669 48.978 -0.794 48.713 -0.794 c
+48.438 -0.794 48.22 -0.721 48.066 -0.573 c
+47.919 -0.419 47.846 -0.202 47.846 0.073 c
+47.846 0.374 47.949 0.617 48.155 0.794 c
+48.361 0.977 48.643 1.073 49.007 1.073 c
+49.36 1.073 l
+49.36 1.396 l
+49.36 1.573 49.319 1.694 49.242 1.764 c
+49.161 1.841 49.044 1.881 48.889 1.881 c
+48.742 1.881 48.617 1.837 48.521 1.749 c
+48.434 1.661 48.39 1.55 48.39 1.426 c
+47.904 1.426 l
+47.904 1.573 47.949 1.712 48.037 1.852 c
+48.125 1.999 48.243 2.109 48.39 2.19 c
+48.544 2.267 48.717 2.308 48.904 2.308 c
+49.217 2.308 49.452 2.227 49.61 2.072 c
+49.764 1.926 49.845 1.705 49.845 1.411 c
+49.845 -0.088 l
+49.853 -0.324 49.889 -0.526 49.948 -0.691 c
+49.948 -0.735 l
+h
+48.787 -0.353 m
+48.904 -0.353 49.014 -0.32 49.124 -0.25 c
+49.231 -0.183 49.308 -0.1 49.36 0 c
+49.36 0.706 l
+49.095 0.706 l
+48.86 0.706 48.673 0.654 48.536 0.559 c
+48.408 0.459 48.346 0.316 48.346 0.133 c
+48.346 -0.037 48.375 -0.158 48.434 -0.235 c
+48.5 -0.316 48.617 -0.353 48.787 -0.353 c
+50.881 2.249 m
+50.896 1.926 l
+51.079 2.179 51.322 2.308 51.616 2.308 c
+52.145 2.308 52.413 1.955 52.425 1.249 c
+52.425 -0.735 l
+51.939 -0.735 l
+51.939 1.22 l
+51.939 1.455 51.899 1.621 51.822 1.72 c
+51.741 1.816 51.623 1.866 51.469 1.866 c
+51.351 1.866 51.241 1.826 51.146 1.749 c
+51.046 1.668 50.969 1.562 50.911 1.426 c
+50.911 -0.735 l
+50.425 -0.735 l
+50.425 2.249 l
+h
+54.078 0.897 m
+54.078 1.326 54.181 1.668 54.387 1.926 c
+54.6 2.179 54.879 2.308 55.225 2.308 c
+55.567 2.308 55.842 2.179 56.047 1.926 c
+56.261 1.679 56.375 1.345 56.386 0.926 c
+56.386 0.617 l
+56.386 0.183 56.276 -0.158 56.062 -0.412 c
+55.856 -0.669 55.577 -0.794 55.225 -0.794 c
+54.879 -0.794 54.607 -0.673 54.401 -0.426 c
+54.196 -0.183 54.086 0.151 54.078 0.573 c
+h
+54.563 0.617 m
+54.563 0.301 54.622 0.058 54.74 -0.118 c
+54.865 -0.287 55.027 -0.368 55.225 -0.368 c
+55.655 -0.368 55.879 -0.059 55.901 0.559 c
+55.901 0.897 l
+55.901 1.198 55.835 1.44 55.71 1.617 c
+55.592 1.793 55.43 1.881 55.225 1.881 c
+55.027 1.881 54.865 1.793 54.74 1.617 c
+54.622 1.44 54.563 1.198 54.563 0.897 c
+h
+58.984 0.617 m
+58.984 0.147 58.9 -0.206 58.734 -0.441 c
+58.565 -0.676 58.322 -0.794 57.999 -0.794 c
+57.683 -0.794 57.448 -0.658 57.294 -0.382 c
+57.264 -0.735 l
+56.823 -0.735 l
+56.823 3.499 l
+57.308 3.499 l
+57.308 1.926 l
+57.462 2.179 57.694 2.308 57.999 2.308 c
+58.322 2.308 58.565 2.19 58.734 1.955 c
+58.9 1.72 58.984 1.371 58.984 0.912 c
+h
+58.499 0.897 m
+58.499 1.249 58.447 1.5 58.352 1.646 c
+58.252 1.793 58.091 1.866 57.867 1.866 c
+57.62 1.866 57.433 1.727 57.308 1.455 c
+57.308 0.044 l
+57.425 -0.22 57.616 -0.353 57.882 -0.353 c
+58.094 -0.353 58.252 -0.279 58.352 -0.133 c
+58.447 0.022 58.499 0.264 58.499 0.588 c
+h
+59.929 2.249 m
+59.929 -1.118 l
+59.918 -1.665 59.696 -1.941 59.267 -1.941 c
+59.168 -1.941 59.079 -1.926 59.002 -1.897 c
+59.002 -1.484 l
+59.054 -1.492 59.112 -1.5 59.193 -1.5 c
+59.27 -1.5 59.33 -1.47 59.37 -1.411 c
+59.418 -1.353 59.443 -1.242 59.443 -1.087 c
+59.443 2.249 l
+h
+59.943 3.042 m
+59.943 2.955 59.918 2.881 59.87 2.822 c
+59.829 2.77 59.76 2.749 59.664 2.749 c
+59.575 2.749 59.505 2.77 59.458 2.822 c
+59.418 2.881 59.399 2.947 59.399 3.028 c
+59.399 3.116 59.418 3.19 59.458 3.248 c
+59.505 3.308 59.575 3.337 59.664 3.337 c
+59.76 3.337 59.829 3.308 59.87 3.248 c
+59.918 3.19 59.943 3.119 59.943 3.042 c
+61.67 -0.794 m
+61.296 -0.794 61.013 -0.688 60.818 -0.47 c
+60.619 -0.246 60.523 0.081 60.523 0.515 c
+60.523 0.881 l
+60.523 1.323 60.616 1.668 60.803 1.926 c
+60.997 2.179 61.273 2.308 61.626 2.308 c
+61.967 2.308 62.221 2.194 62.391 1.97 c
+62.567 1.741 62.659 1.396 62.67 0.926 c
+62.67 0.617 l
+61.009 0.617 l
+61.009 0.544 l
+61.009 0.22 61.067 -0.015 61.185 -0.162 c
+61.302 -0.301 61.472 -0.368 61.699 -0.368 c
+61.847 -0.368 61.971 -0.345 62.082 -0.294 c
+62.189 -0.235 62.291 -0.147 62.391 -0.029 c
+62.64 -0.338 l
+62.435 -0.643 62.111 -0.794 61.67 -0.794 c
+61.626 1.881 m
+61.42 1.881 61.266 1.812 61.171 1.675 c
+61.071 1.536 61.016 1.323 61.009 1.029 c
+62.185 1.029 l
+62.185 1.103 l
+62.162 1.374 62.111 1.573 62.023 1.691 c
+61.935 1.816 61.803 1.881 61.626 1.881 c
+64.11 -0.368 m
+64.276 -0.368 64.408 -0.32 64.507 -0.22 c
+64.602 -0.125 64.658 0.018 64.669 0.206 c
+65.125 0.206 l
+65.113 -0.081 65.011 -0.32 64.816 -0.515 c
+64.629 -0.702 64.394 -0.794 64.11 -0.794 c
+63.746 -0.794 63.467 -0.676 63.272 -0.441 c
+63.074 -0.206 62.979 0.139 62.979 0.603 c
+62.979 0.926 l
+62.979 1.374 63.07 1.72 63.258 1.955 c
+63.453 2.19 63.735 2.308 64.11 2.308 c
+64.411 2.308 64.654 2.209 64.83 2.014 c
+65.014 1.816 65.113 1.55 65.125 1.22 c
+64.669 1.22 l
+64.647 1.444 64.588 1.61 64.492 1.72 c
+64.404 1.826 64.276 1.881 64.11 1.881 c
+63.893 1.881 63.731 1.808 63.625 1.661 c
+63.526 1.521 63.471 1.294 63.463 0.97 c
+63.463 0.588 l
+63.463 0.235 63.511 -0.015 63.611 -0.162 c
+63.717 -0.301 63.883 -0.368 64.11 -0.368 c
+66.15 2.969 m
+66.15 2.249 l
+66.605 2.249 l
+66.605 1.852 l
+66.15 1.852 l
+66.15 0 l
+66.15 -0.118 66.168 -0.206 66.208 -0.264 c
+66.245 -0.324 66.315 -0.353 66.414 -0.353 c
+66.474 -0.353 66.536 -0.345 66.605 -0.324 c
+66.605 -0.735 l
+66.488 -0.771 66.374 -0.794 66.268 -0.794 c
+66.069 -0.794 65.919 -0.728 65.811 -0.588 c
+65.713 -0.452 65.664 -0.258 65.664 0 c
+65.664 1.852 l
+65.209 1.852 l
+65.209 2.249 l
+65.664 2.249 l
+65.664 2.969 l
+h
+f
+Q
+q 1 0 0 1 594.1917 83.3777 cm
+0 0 m
+0 0.478 0.062 0.929 0.191 1.353 c
+0.326 1.783 0.515 2.153 0.75 2.469 c
+0.896 2.664 1.036 2.807 1.176 2.896 c
+1.263 2.558 l
+1.047 2.352 0.867 2.032 0.72 1.602 c
+0.58 1.18 0.507 0.709 0.5 0.191 c
+0.484 -0.029 l
+0.484 -0.676 0.577 -1.249 0.764 -1.749 c
+0.9 -2.12 1.066 -2.41 1.263 -2.616 c
+1.176 -2.925 l
+0.999 -2.815 0.827 -2.631 0.661 -2.367 c
+0.22 -1.708 0 -0.922 0 0 c
+3.197 -1.631 m
+3.167 -1.565 3.145 -1.455 3.138 -1.309 c
+2.961 -1.565 2.741 -1.691 2.477 -1.691 c
+2.201 -1.691 1.984 -1.617 1.83 -1.469 c
+1.683 -1.315 1.61 -1.099 1.61 -0.823 c
+1.61 -0.522 1.712 -0.279 1.918 -0.103 c
+2.123 0.081 2.406 0.177 2.77 0.177 c
+3.123 0.177 l
+3.123 0.5 l
+3.123 0.676 3.083 0.798 3.006 0.867 c
+2.925 0.945 2.807 0.985 2.653 0.985 c
+2.506 0.985 2.381 0.941 2.285 0.852 c
+2.198 0.765 2.153 0.654 2.153 0.53 c
+1.668 0.53 l
+1.668 0.676 1.712 0.816 1.801 0.956 c
+1.888 1.103 2.007 1.213 2.153 1.294 c
+2.308 1.371 2.48 1.411 2.668 1.411 c
+2.98 1.411 3.215 1.33 3.373 1.176 c
+3.528 1.029 3.609 0.808 3.609 0.515 c
+3.609 -0.985 l
+3.615 -1.22 3.653 -1.422 3.711 -1.587 c
+3.711 -1.631 l
+h
+2.55 -1.249 m
+2.668 -1.249 2.778 -1.216 2.888 -1.147 c
+2.994 -1.08 3.071 -0.996 3.123 -0.897 c
+3.123 -0.191 l
+2.859 -0.191 l
+2.624 -0.191 2.437 -0.243 2.3 -0.338 c
+2.171 -0.437 2.109 -0.58 2.109 -0.764 c
+2.109 -0.933 2.138 -1.055 2.198 -1.132 c
+2.263 -1.213 2.381 -1.249 2.55 -1.249 c
+4.644 1.353 m
+4.659 1.029 l
+4.843 1.282 5.086 1.411 5.379 1.411 c
+5.909 1.411 6.177 1.058 6.188 0.353 c
+6.188 -1.631 l
+5.703 -1.631 l
+5.703 0.324 l
+5.703 0.559 5.662 0.724 5.585 0.823 c
+5.504 0.919 5.387 0.97 5.232 0.97 c
+5.115 0.97 5.005 0.929 4.909 0.852 c
+4.81 0.771 4.733 0.665 4.674 0.53 c
+4.674 -1.631 l
+4.189 -1.631 l
+4.189 1.353 l
+h
+7.198 1.353 m
+7.214 1.029 l
+7.397 1.282 7.64 1.411 7.933 1.411 c
+8.463 1.411 8.731 1.058 8.742 0.353 c
+8.742 -1.631 l
+8.257 -1.631 l
+8.257 0.324 l
+8.257 0.559 8.216 0.724 8.139 0.823 c
+8.058 0.919 7.941 0.97 7.786 0.97 c
+7.669 0.97 7.559 0.929 7.463 0.852 c
+7.364 0.771 7.287 0.665 7.228 0.53 c
+7.228 -1.631 l
+6.743 -1.631 l
+6.743 1.353 l
+h
+9.19 0 m
+9.19 0.43 9.294 0.771 9.499 1.029 c
+9.712 1.282 9.992 1.411 10.337 1.411 c
+10.678 1.411 10.954 1.282 11.16 1.029 c
+11.374 0.783 11.487 0.449 11.498 0.029 c
+11.498 -0.279 l
+11.498 -0.713 11.388 -1.055 11.175 -1.309 c
+10.969 -1.565 10.69 -1.691 10.337 -1.691 c
+9.992 -1.691 9.72 -1.569 9.514 -1.323 c
+9.308 -1.08 9.198 -0.746 9.19 -0.324 c
+h
+9.676 -0.279 m
+9.676 -0.595 9.734 -0.838 9.851 -1.014 c
+9.977 -1.183 10.138 -1.264 10.337 -1.264 c
+10.767 -1.264 10.991 -0.956 11.013 -0.338 c
+11.013 0 l
+11.013 0.301 10.946 0.544 10.822 0.721 c
+10.705 0.897 10.543 0.985 10.337 0.985 c
+10.138 0.985 9.977 0.897 9.851 0.721 c
+9.734 0.544 9.676 0.301 9.676 0 c
+h
+12.571 2.072 m
+12.571 1.353 l
+13.026 1.353 l
+13.026 0.956 l
+12.571 0.956 l
+12.571 -0.897 l
+12.571 -1.014 12.59 -1.103 12.629 -1.161 c
+12.667 -1.22 12.737 -1.249 12.835 -1.249 c
+12.895 -1.249 12.957 -1.242 13.026 -1.22 c
+13.026 -1.631 l
+12.909 -1.668 12.795 -1.691 12.689 -1.691 c
+12.49 -1.691 12.34 -1.625 12.233 -1.484 c
+12.134 -1.349 12.086 -1.154 12.086 -0.897 c
+12.086 0.956 l
+11.63 0.956 l
+11.63 1.353 l
+12.086 1.353 l
+12.086 2.072 l
+h
+15.022 -1.631 m
+14.993 -1.565 14.971 -1.455 14.963 -1.309 c
+14.786 -1.565 14.566 -1.691 14.302 -1.691 c
+14.026 -1.691 13.809 -1.617 13.655 -1.469 c
+13.508 -1.315 13.435 -1.099 13.435 -0.823 c
+13.435 -0.522 13.537 -0.279 13.743 -0.103 c
+13.949 0.081 14.232 0.177 14.596 0.177 c
+14.948 0.177 l
+14.948 0.5 l
+14.948 0.676 14.908 0.798 14.831 0.867 c
+14.75 0.945 14.632 0.985 14.478 0.985 c
+14.331 0.985 14.206 0.941 14.111 0.852 c
+14.023 0.765 13.978 0.654 13.978 0.53 c
+13.493 0.53 l
+13.493 0.676 13.537 0.816 13.626 0.956 c
+13.714 1.103 13.832 1.213 13.978 1.294 c
+14.133 1.371 14.306 1.411 14.493 1.411 c
+14.805 1.411 15.041 1.33 15.199 1.176 c
+15.353 1.029 15.434 0.808 15.434 0.515 c
+15.434 -0.985 l
+15.441 -1.22 15.478 -1.422 15.536 -1.587 c
+15.536 -1.631 l
+h
+14.375 -1.249 m
+14.493 -1.249 14.603 -1.216 14.713 -1.147 c
+14.82 -1.08 14.898 -0.996 14.948 -0.897 c
+14.948 -0.191 l
+14.684 -0.191 l
+14.449 -0.191 14.262 -0.243 14.125 -0.338 c
+13.997 -0.437 13.934 -0.58 13.934 -0.764 c
+13.934 -0.933 13.963 -1.055 14.023 -1.132 c
+14.089 -1.213 14.206 -1.249 14.375 -1.249 c
+16.646 2.072 m
+16.646 1.353 l
+17.102 1.353 l
+17.102 0.956 l
+16.646 0.956 l
+16.646 -0.897 l
+16.646 -1.014 16.665 -1.103 16.705 -1.161 c
+16.742 -1.22 16.812 -1.249 16.911 -1.249 c
+16.97 -1.249 17.032 -1.242 17.102 -1.22 c
+17.102 -1.631 l
+16.984 -1.668 16.87 -1.691 16.764 -1.691 c
+16.565 -1.691 16.415 -1.625 16.309 -1.484 c
+16.209 -1.349 16.161 -1.154 16.161 -0.897 c
+16.161 0.956 l
+15.706 0.956 l
+15.706 1.353 l
+16.161 1.353 l
+16.161 2.072 l
+h
+18.624 -1.691 m
+18.248 -1.691 17.965 -1.584 17.771 -1.367 c
+17.572 -1.143 17.477 -0.816 17.477 -0.382 c
+17.477 -0.015 l
+17.477 0.426 17.568 0.771 17.756 1.029 c
+17.951 1.282 18.227 1.411 18.58 1.411 c
+18.921 1.411 19.175 1.297 19.343 1.073 c
+19.52 0.845 19.612 0.5 19.623 0.029 c
+19.623 -0.279 l
+17.962 -0.279 l
+17.962 -0.353 l
+17.962 -0.676 18.021 -0.912 18.138 -1.058 c
+18.256 -1.198 18.425 -1.264 18.653 -1.264 c
+18.8 -1.264 18.925 -1.242 19.035 -1.191 c
+19.141 -1.132 19.245 -1.043 19.343 -0.926 c
+19.594 -1.234 l
+19.388 -1.54 19.064 -1.691 18.624 -1.691 c
+18.58 0.985 m
+18.374 0.985 18.219 0.915 18.123 0.779 c
+18.025 0.64 17.969 0.426 17.962 0.133 c
+19.137 0.133 l
+19.137 0.206 l
+19.116 0.478 19.064 0.676 18.977 0.794 c
+18.888 0.919 18.755 0.985 18.58 0.985 c
+19.931 0 m
+19.931 0.459 20.012 0.808 20.182 1.043 c
+20.358 1.286 20.608 1.411 20.931 1.411 c
+21.214 1.411 21.435 1.294 21.593 1.058 c
+21.593 2.602 l
+22.077 2.602 l
+22.077 -1.631 l
+21.637 -1.631 l
+21.607 -1.309 l
+21.449 -1.565 21.225 -1.691 20.931 -1.691 c
+20.615 -1.691 20.373 -1.573 20.196 -1.338 c
+20.02 -1.095 19.931 -0.75 19.931 -0.309 c
+h
+20.417 -0.279 m
+20.417 -0.613 20.465 -0.86 20.564 -1.014 c
+20.66 -1.172 20.821 -1.249 21.049 -1.249 c
+21.292 -1.249 21.475 -1.132 21.593 -0.897 c
+21.593 0.617 l
+21.464 0.852 21.284 0.97 21.049 0.97 c
+20.821 0.97 20.66 0.889 20.564 0.735 c
+20.465 0.577 20.417 0.338 20.417 0.015 c
+h
+24.485 2.072 m
+24.485 1.353 l
+24.94 1.353 l
+24.94 0.956 l
+24.485 0.956 l
+24.485 -0.897 l
+24.485 -1.014 24.503 -1.103 24.544 -1.161 c
+24.581 -1.22 24.65 -1.249 24.749 -1.249 c
+24.808 -1.249 24.87 -1.242 24.94 -1.22 c
+24.94 -1.631 l
+24.822 -1.668 24.708 -1.691 24.602 -1.691 c
+24.404 -1.691 24.253 -1.625 24.147 -1.484 c
+24.047 -1.349 23.999 -1.154 23.999 -0.897 c
+23.999 0.956 l
+23.544 0.956 l
+23.544 1.353 l
+23.999 1.353 l
+23.999 2.072 l
+h
+26.936 -1.631 m
+26.906 -1.565 26.884 -1.455 26.877 -1.309 c
+26.701 -1.565 26.48 -1.691 26.216 -1.691 c
+25.94 -1.691 25.723 -1.617 25.568 -1.469 c
+25.422 -1.315 25.348 -1.099 25.348 -0.823 c
+25.348 -0.522 25.451 -0.279 25.657 -0.103 c
+25.863 0.081 26.146 0.177 26.509 0.177 c
+26.862 0.177 l
+26.862 0.5 l
+26.862 0.676 26.821 0.798 26.744 0.867 c
+26.663 0.945 26.546 0.985 26.391 0.985 c
+26.245 0.985 26.12 0.941 26.025 0.852 c
+25.936 0.765 25.892 0.654 25.892 0.53 c
+25.407 0.53 l
+25.407 0.676 25.451 0.816 25.539 0.956 c
+25.628 1.103 25.745 1.213 25.892 1.294 c
+26.046 1.371 26.219 1.411 26.407 1.411 c
+26.719 1.411 26.954 1.33 27.112 1.176 c
+27.266 1.029 27.347 0.808 27.347 0.515 c
+27.347 -0.985 l
+27.355 -1.22 27.391 -1.422 27.45 -1.587 c
+27.45 -1.631 l
+h
+26.289 -1.249 m
+26.407 -1.249 26.517 -1.216 26.627 -1.147 c
+26.734 -1.08 26.811 -0.996 26.862 -0.897 c
+26.862 -0.191 l
+26.598 -0.191 l
+26.362 -0.191 26.175 -0.243 26.039 -0.338 c
+25.911 -0.437 25.848 -0.58 25.848 -0.764 c
+25.848 -0.933 25.877 -1.055 25.936 -1.132 c
+26.002 -1.213 26.12 -1.249 26.289 -1.249 c
+27.825 0 m
+27.825 0.459 27.906 0.808 28.074 1.043 c
+28.251 1.286 28.502 1.411 28.824 1.411 c
+29.126 1.411 29.358 1.278 29.516 1.014 c
+29.545 1.353 l
+29.986 1.353 l
+29.986 -1.661 l
+29.986 -2.032 29.886 -2.315 29.692 -2.514 c
+29.504 -2.708 29.244 -2.807 28.913 -2.807 c
+28.766 -2.807 28.597 -2.767 28.413 -2.69 c
+28.226 -2.62 28.09 -2.532 28.001 -2.425 c
+28.192 -2.088 l
+28.398 -2.293 28.622 -2.396 28.868 -2.396 c
+29.269 -2.396 29.475 -2.168 29.486 -1.72 c
+29.486 -1.338 l
+29.328 -1.573 29.107 -1.691 28.824 -1.691 c
+28.508 -1.691 28.266 -1.573 28.09 -1.338 c
+27.92 -1.103 27.833 -0.771 27.825 -0.338 c
+h
+28.31 -0.279 m
+28.31 -0.613 28.358 -0.86 28.457 -1.014 c
+28.552 -1.172 28.714 -1.249 28.942 -1.249 c
+29.185 -1.249 29.368 -1.128 29.486 -0.881 c
+29.486 0.603 l
+29.368 0.845 29.192 0.97 28.957 0.97 c
+28.729 0.97 28.567 0.889 28.471 0.735 c
+28.373 0.577 28.317 0.338 28.31 0.015 c
+h
+31.566 -0.029 m
+31.566 -0.852 31.382 -1.58 31.022 -2.205 c
+30.816 -2.547 30.611 -2.786 30.405 -2.925 c
+30.302 -2.616 l
+30.537 -2.389 30.721 -2.051 30.86 -1.602 c
+31.008 -1.143 31.081 -0.643 31.081 -0.103 c
+31.081 0 l
+31.081 0.694 30.967 1.323 30.742 1.881 c
+30.615 2.176 30.467 2.411 30.302 2.587 c
+30.405 2.896 l
+30.599 2.756 30.794 2.535 30.993 2.234 c
+31.375 1.588 31.566 0.831 31.566 -0.029 c
+f
+Q
+0.567 w 1 j 1 J
+q 1 0 0 1 627.4703 96.4198 cm
+0 0 m
+5.747 3.34 l
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 631.3726 98.6865 cm
+0 0 m
+-0.386 -1.458 l
+2.308 1.341 l
+-1.455 0.387 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 631.3727 98.6865 cm
+0 0 m
+-0.386 -1.458 l
+2.308 1.341 l
+-1.455 0.387 l
+0 0 l
+h
+S
+Q
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+0 G
+/GS2 gs
+0 TL/Fm34 Do
+Q
+0 0 0 0 k
+q 1 0 0 1 121.1352 111.1992 cm
+0 0 m
+-1.323 0 l
+-1.808 -1.043 l
+-2.323 -1.043 l
+-0.382 2.969 l
+0.044 2.969 l
+0.603 -1.043 l
+0.118 -1.043 l
+h
+-1.117 0.441 m
+-0.058 0.441 l
+-0.264 2.263 l
+h
+2.903 1.941 m
+2.845 1.617 l
+3.057 1.871 3.304 1.999 3.58 1.999 c
+3.763 1.989 3.91 1.918 4.021 1.793 c
+4.138 1.675 4.2 1.503 4.212 1.279 c
+4.219 1.151 4.219 1.029 4.212 0.912 c
+3.888 -1.043 l
+3.403 -1.043 l
+3.741 0.927 l
+3.755 1.132 l
+3.755 1.415 3.638 1.562 3.403 1.573 c
+3.215 1.573 3.04 1.463 2.874 1.249 c
+2.786 1.132 l
+2.419 -1.043 l
+1.933 -1.043 l
+2.462 1.941 l
+h
+6.81 1.985 m
+7.082 1.985 7.287 1.871 7.427 1.646 c
+7.721 3.19 l
+8.191 3.19 l
+7.456 -1.043 l
+7.03 -1.043 l
+7.074 -0.72 l
+6.876 -0.985 6.641 -1.109 6.369 -1.103 c
+6.122 -1.091 5.931 -0.995 5.795 -0.808 c
+5.656 -0.625 5.59 -0.353 5.59 0 c
+5.59 0.166 5.608 0.382 5.648 0.647 c
+5.696 0.919 5.766 1.151 5.854 1.338 c
+6.06 1.786 6.376 2.003 6.81 1.985 c
+6.06 -0.118 m
+6.067 -0.481 6.221 -0.669 6.516 -0.676 c
+6.622 -0.676 6.725 -0.654 6.824 -0.602 c
+6.92 -0.544 7.015 -0.448 7.104 -0.309 c
+7.368 1.205 l
+7.28 1.43 7.125 1.548 6.913 1.558 c
+6.471 1.588 6.207 1.268 6.119 0.603 c
+6.078 0.279 6.06 0.037 6.06 -0.118 c
+12.48 2.66 m
+12.347 1.941 l
+12.788 1.941 l
+12.715 1.544 l
+12.274 1.544 l
+11.965 -0.309 l
+11.965 -0.426 l
+11.954 -0.584 12.009 -0.661 12.127 -0.661 c
+12.175 -0.661 12.245 -0.654 12.333 -0.632 c
+12.289 -1.043 l
+12.179 -1.08 12.075 -1.095 11.98 -1.087 c
+11.811 -1.087 11.686 -1.022 11.597 -0.881 c
+11.51 -0.746 11.48 -0.555 11.51 -0.309 c
+11.803 1.544 l
+11.362 1.544 l
+11.436 1.941 l
+11.877 1.941 l
+11.994 2.66 l
+h
+14.637 1.632 m
+14.85 1.874 15.092 1.992 15.357 1.985 c
+15.551 1.985 15.703 1.918 15.813 1.793 c
+15.919 1.675 15.978 1.503 15.989 1.279 c
+15.996 1.151 15.996 1.029 15.989 0.912 c
+15.666 -1.043 l
+15.181 -1.043 l
+15.518 0.927 l
+15.533 1.132 l
+15.533 1.415 15.416 1.562 15.181 1.573 c
+14.993 1.573 14.817 1.463 14.651 1.249 c
+14.564 1.132 l
+14.196 -1.043 l
+13.71 -1.043 l
+14.446 3.19 l
+14.93 3.19 l
+h
+17.742 -1.043 m
+17.272 -1.043 l
+17.786 1.941 l
+18.271 1.941 l
+h
+17.903 2.734 m
+17.903 2.812 17.926 2.881 17.978 2.94 c
+18.025 2.999 18.088 3.028 18.168 3.028 c
+18.246 3.028 18.308 2.999 18.359 2.94 c
+18.418 2.889 18.44 2.822 18.433 2.734 c
+18.433 2.654 18.407 2.587 18.359 2.529 c
+18.308 2.469 18.246 2.44 18.168 2.44 c
+18.08 2.429 18.01 2.455 17.962 2.514 c
+17.911 2.573 17.893 2.646 17.903 2.734 c
+20.939 -0.264 m
+20.968 -0.088 20.869 0.059 20.645 0.177 c
+20.278 0.368 l
+20.09 0.474 19.958 0.588 19.881 0.706 c
+19.8 0.823 19.767 0.963 19.778 1.132 c
+19.785 1.374 19.884 1.58 20.072 1.75 c
+20.266 1.914 20.505 1.999 20.792 1.999 c
+21.057 1.989 21.263 1.9 21.409 1.735 c
+21.564 1.565 21.633 1.353 21.615 1.087 c
+21.145 1.087 l
+21.153 1.235 21.119 1.353 21.042 1.44 c
+20.972 1.529 20.881 1.573 20.763 1.573 c
+20.615 1.573 20.498 1.532 20.41 1.455 c
+20.322 1.374 20.266 1.272 20.248 1.147 c
+20.218 1 20.285 0.875 20.454 0.779 c
+20.924 0.544 l
+21.266 0.345 21.428 0.092 21.409 -0.22 c
+21.388 -0.496 21.28 -0.716 21.086 -0.881 c
+20.887 -1.04 20.648 -1.109 20.366 -1.103 c
+20.09 -1.091 19.866 -1.007 19.69 -0.837 c
+19.52 -0.661 19.443 -0.434 19.454 -0.147 c
+19.94 -0.147 l
+19.929 -0.324 19.962 -0.455 20.042 -0.544 c
+20.131 -0.632 20.241 -0.676 20.38 -0.676 c
+20.534 -0.676 20.663 -0.639 20.763 -0.559 c
+20.858 -0.481 20.917 -0.382 20.939 -0.264 c
+25.423 -1.043 m
+24.952 -1.043 l
+25.467 1.941 l
+25.951 1.941 l
+h
+25.584 2.734 m
+25.584 2.812 25.606 2.881 25.658 2.94 c
+25.705 2.999 25.768 3.028 25.849 3.028 c
+25.926 3.028 25.988 2.999 26.04 2.94 c
+26.098 2.889 26.121 2.822 26.113 2.734 c
+26.113 2.654 26.088 2.587 26.04 2.529 c
+25.988 2.469 25.926 2.44 25.849 2.44 c
+25.76 2.429 25.691 2.455 25.643 2.514 c
+25.591 2.573 25.573 2.646 25.584 2.734 c
+28.619 -0.264 m
+28.648 -0.088 28.55 0.059 28.326 0.177 c
+27.958 0.368 l
+27.771 0.474 27.638 0.588 27.561 0.706 c
+27.48 0.823 27.447 0.963 27.458 1.132 c
+27.466 1.374 27.565 1.58 27.752 1.75 c
+27.947 1.914 28.186 1.999 28.472 1.999 c
+28.737 1.989 28.943 1.9 29.09 1.735 c
+29.244 1.565 29.313 1.353 29.296 1.087 c
+28.825 1.087 l
+28.833 1.235 28.799 1.353 28.722 1.44 c
+28.652 1.529 28.561 1.573 28.443 1.573 c
+28.296 1.573 28.178 1.532 28.09 1.455 c
+28.002 1.374 27.947 1.272 27.929 1.147 c
+27.899 1 27.965 0.875 28.134 0.779 c
+28.604 0.544 l
+28.947 0.345 29.108 0.092 29.09 -0.22 c
+29.068 -0.496 28.961 -0.716 28.766 -0.881 c
+28.567 -1.04 28.328 -1.109 28.046 -1.103 c
+27.771 -1.091 27.546 -1.007 27.37 -0.837 c
+27.201 -0.661 27.123 -0.434 27.135 -0.147 c
+27.62 -0.147 l
+27.609 -0.324 27.642 -0.455 27.723 -0.544 c
+27.811 -0.632 27.921 -0.676 28.06 -0.676 c
+28.215 -0.676 28.344 -0.639 28.443 -0.559 c
+28.538 -0.481 28.598 -0.382 28.619 -0.264 c
+33.87 2.66 m
+33.738 1.941 l
+34.179 1.941 l
+34.106 1.544 l
+33.664 1.544 l
+33.356 -0.309 l
+33.356 -0.426 l
+33.345 -0.584 33.4 -0.661 33.518 -0.661 c
+33.566 -0.661 33.635 -0.654 33.724 -0.632 c
+33.679 -1.043 l
+33.569 -1.08 33.466 -1.095 33.371 -1.087 c
+33.202 -1.087 33.076 -1.022 32.989 -0.881 c
+32.9 -0.746 32.871 -0.555 32.9 -0.309 c
+33.194 1.544 l
+32.754 1.544 l
+32.827 1.941 l
+33.267 1.941 l
+33.386 2.66 l
+h
+36.027 1.632 m
+36.241 1.874 36.483 1.992 36.748 1.985 c
+36.943 1.985 37.093 1.918 37.203 1.793 c
+37.31 1.675 37.369 1.503 37.38 1.279 c
+37.387 1.151 37.387 1.029 37.38 0.912 c
+37.057 -1.043 l
+36.571 -1.043 l
+36.91 0.927 l
+36.924 1.132 l
+36.924 1.415 36.806 1.562 36.571 1.573 c
+36.384 1.573 36.208 1.463 36.043 1.249 c
+35.954 1.132 l
+35.586 -1.043 l
+35.102 -1.043 l
+35.837 3.19 l
+36.322 3.19 l
+h
+39.732 -1.103 m
+39.397 -1.091 39.147 -0.97 38.982 -0.735 c
+38.813 -0.5 38.755 -0.176 38.805 0.235 c
+38.835 0.53 l
+38.894 0.989 39.033 1.353 39.262 1.617 c
+39.486 1.881 39.769 2.007 40.114 1.999 c
+40.397 1.989 40.606 1.889 40.746 1.706 c
+40.893 1.518 40.966 1.253 40.966 0.912 c
+40.937 0.588 l
+40.893 0.309 l
+39.291 0.309 l
+39.268 0.14 39.262 0.008 39.262 -0.088 c
+39.262 -0.276 39.305 -0.422 39.393 -0.529 c
+39.482 -0.628 39.607 -0.676 39.775 -0.676 c
+39.893 -0.687 40.011 -0.669 40.128 -0.617 c
+40.246 -0.559 40.363 -0.47 40.481 -0.353 c
+40.716 -0.661 l
+40.599 -0.808 40.452 -0.922 40.276 -0.999 c
+40.099 -1.066 39.916 -1.103 39.732 -1.103 c
+40.085 1.573 m
+39.761 1.592 39.534 1.397 39.409 0.985 c
+39.335 0.721 l
+40.481 0.721 l
+40.481 0.794 l
+40.5 0.871 40.511 0.96 40.511 1.058 c
+40.5 1.389 40.357 1.562 40.085 1.573 c
+45.398 -1.103 m
+45.111 -1.091 44.899 -0.977 44.752 -0.75 c
+44.487 -2.19 l
+44.016 -2.19 l
+44.737 1.941 l
+45.163 1.941 l
+45.105 1.602 l
+45.31 1.867 45.549 1.999 45.824 1.999 c
+46.089 1.989 46.283 1.885 46.412 1.691 c
+46.549 1.503 46.611 1.239 46.603 0.897 c
+46.593 0.738 46.567 0.53 46.53 0.264 c
+46.501 0.008 46.449 -0.206 46.383 -0.382 c
+46.177 -0.874 45.847 -1.109 45.398 -1.103 c
+46.133 1.014 m
+46.104 1.374 45.946 1.558 45.663 1.558 c
+45.446 1.565 45.251 1.455 45.075 1.22 c
+44.81 -0.338 l
+44.899 -0.555 45.049 -0.673 45.266 -0.691 c
+45.479 -0.702 45.655 -0.628 45.795 -0.47 c
+45.931 -0.305 46.019 -0.051 46.06 0.294 c
+46.108 0.636 46.133 0.875 46.133 1.014 c
+49.315 -1.043 m
+49.304 -0.985 49.3 -0.933 49.3 -0.881 c
+49.315 -0.72 l
+49.109 -0.977 48.882 -1.103 48.639 -1.103 c
+48.394 -1.103 48.203 -1.025 48.066 -0.867 c
+47.937 -0.713 47.883 -0.507 47.904 -0.249 c
+47.923 0.052 48.051 0.298 48.286 0.485 c
+48.521 0.669 48.823 0.765 49.198 0.765 c
+49.536 0.765 l
+49.58 1.087 l
+49.61 1.411 49.485 1.573 49.213 1.573 c
+49.065 1.573 48.941 1.529 48.845 1.44 c
+48.746 1.36 48.687 1.253 48.669 1.118 c
+48.199 1.118 l
+48.217 1.36 48.33 1.565 48.536 1.735 c
+48.743 1.911 48.981 1.999 49.257 1.999 c
+49.521 1.989 49.727 1.904 49.874 1.75 c
+50.021 1.592 50.08 1.367 50.05 1.073 c
+49.815 -0.397 l
+49.793 -0.496 49.786 -0.595 49.786 -0.691 c
+49.801 -0.999 l
+49.801 -1.043 l
+h
+48.727 -0.661 m
+48.97 -0.661 49.176 -0.544 49.345 -0.309 c
+49.477 0.397 l
+49.257 0.412 l
+49.069 0.412 48.904 0.375 48.757 0.309 c
+48.61 0.239 48.507 0.14 48.448 0.015 c
+48.39 -0.103 48.367 -0.235 48.39 -0.382 c
+48.408 -0.569 48.521 -0.661 48.727 -0.661 c
+52.847 -0.264 m
+52.876 -0.088 52.777 0.059 52.553 0.177 c
+52.186 0.368 l
+51.998 0.474 51.866 0.588 51.789 0.706 c
+51.708 0.823 51.675 0.963 51.686 1.132 c
+51.693 1.374 51.792 1.58 51.98 1.75 c
+52.174 1.914 52.413 1.999 52.7 1.999 c
+52.965 1.989 53.171 1.9 53.317 1.735 c
+53.472 1.565 53.541 1.353 53.523 1.087 c
+53.053 1.087 l
+53.061 1.235 53.027 1.353 52.95 1.44 c
+52.88 1.529 52.788 1.573 52.671 1.573 c
+52.523 1.573 52.406 1.532 52.317 1.455 c
+52.23 1.374 52.174 1.272 52.156 1.147 c
+52.126 1 52.193 0.875 52.362 0.779 c
+52.832 0.544 l
+53.174 0.345 53.336 0.092 53.317 -0.22 c
+53.296 -0.496 53.188 -0.716 52.994 -0.881 c
+52.795 -1.04 52.556 -1.109 52.274 -1.103 c
+51.998 -1.091 51.774 -1.007 51.598 -0.837 c
+51.428 -0.661 51.351 -0.434 51.362 -0.147 c
+51.847 -0.147 l
+51.837 -0.324 51.87 -0.455 51.95 -0.544 c
+52.039 -0.632 52.149 -0.676 52.288 -0.676 c
+52.442 -0.676 52.571 -0.639 52.671 -0.559 c
+52.766 -0.481 52.825 -0.382 52.847 -0.264 c
+55.941 2.66 m
+55.808 1.941 l
+56.25 1.941 l
+56.176 1.544 l
+55.735 1.544 l
+55.426 -0.309 l
+55.426 -0.426 l
+55.415 -0.584 55.471 -0.661 55.588 -0.661 c
+55.636 -0.661 55.706 -0.654 55.794 -0.632 c
+55.75 -1.043 l
+55.64 -1.08 55.537 -1.095 55.442 -1.087 c
+55.272 -1.087 55.147 -1.022 55.06 -0.881 c
+54.971 -0.746 54.942 -0.555 54.971 -0.309 c
+55.265 1.544 l
+54.824 1.544 l
+54.898 1.941 l
+55.338 1.941 l
+55.456 2.66 l
+h
+57.569 -0.47 m
+57.657 -0.463 57.73 -0.484 57.79 -0.544 c
+57.848 -0.602 57.878 -0.676 57.878 -0.764 c
+57.878 -0.852 57.848 -0.926 57.79 -0.985 c
+57.73 -1.043 57.657 -1.072 57.569 -1.072 c
+57.481 -1.08 57.408 -1.062 57.348 -1.014 c
+57.29 -0.955 57.26 -0.881 57.26 -0.794 c
+57.26 -0.698 57.29 -0.617 57.348 -0.559 c
+57.408 -0.5 57.481 -0.47 57.569 -0.47 c
+64.283 -1.043 m
+63.798 -1.043 l
+64.121 0.809 l
+62.563 0.809 l
+62.239 -1.043 l
+61.74 -1.043 l
+62.43 2.969 l
+62.931 2.969 l
+62.622 1.249 l
+64.195 1.249 l
+64.489 2.969 l
+64.988 2.969 l
+h
+67.043 -1.103 m
+66.708 -1.091 66.459 -0.97 66.293 -0.735 c
+66.124 -0.5 66.065 -0.176 66.116 0.235 c
+66.146 0.53 l
+66.205 0.989 66.345 1.353 66.572 1.617 c
+66.796 1.881 67.079 2.007 67.425 1.999 c
+67.708 1.989 67.918 1.889 68.057 1.706 c
+68.204 1.518 68.277 1.253 68.277 0.912 c
+68.248 0.588 l
+68.204 0.309 l
+66.602 0.309 l
+66.58 0.14 66.572 0.008 66.572 -0.088 c
+66.572 -0.276 66.617 -0.422 66.704 -0.529 c
+66.792 -0.628 66.918 -0.676 67.087 -0.676 c
+67.205 -0.687 67.322 -0.669 67.44 -0.617 c
+67.557 -0.559 67.675 -0.47 67.792 -0.353 c
+68.028 -0.661 l
+67.91 -0.808 67.762 -0.922 67.586 -0.999 c
+67.41 -1.066 67.226 -1.103 67.043 -1.103 c
+67.396 1.573 m
+67.072 1.592 66.844 1.397 66.719 0.985 c
+66.646 0.721 l
+67.792 0.721 l
+67.792 0.794 l
+67.81 0.871 67.822 0.96 67.822 1.058 c
+67.81 1.389 67.667 1.562 67.396 1.573 c
+71.022 1.484 m
+70.941 1.503 70.868 1.515 70.802 1.515 c
+70.567 1.515 70.368 1.371 70.214 1.087 c
+69.846 -1.043 l
+69.362 -1.043 l
+69.89 1.941 l
+70.347 1.941 l
+70.272 1.632 l
+70.449 1.885 70.648 2.007 70.875 1.999 c
+70.912 1.999 70.978 1.985 71.066 1.955 c
+h
+72.988 -1.103 m
+72.654 -1.091 72.404 -0.97 72.238 -0.735 c
+72.07 -0.5 72.011 -0.176 72.063 0.235 c
+72.092 0.53 l
+72.151 0.989 72.29 1.353 72.518 1.617 c
+72.742 1.881 73.025 2.007 73.37 1.999 c
+73.653 1.989 73.863 1.889 74.002 1.706 c
+74.15 1.518 74.223 1.253 74.223 0.912 c
+74.193 0.588 l
+74.15 0.309 l
+72.547 0.309 l
+72.525 0.14 72.518 0.008 72.518 -0.088 c
+72.518 -0.276 72.562 -0.422 72.65 -0.529 c
+72.739 -0.628 72.863 -0.676 73.032 -0.676 c
+73.15 -0.687 73.268 -0.669 73.385 -0.617 c
+73.503 -0.559 73.62 -0.47 73.738 -0.353 c
+73.973 -0.661 l
+73.856 -0.808 73.709 -0.922 73.532 -0.999 c
+73.356 -1.066 73.172 -1.103 72.988 -1.103 c
+73.341 1.573 m
+73.017 1.592 72.79 1.397 72.665 0.985 c
+72.591 0.721 l
+73.738 0.721 l
+73.738 0.794 l
+73.757 0.871 73.767 0.96 73.767 1.058 c
+73.757 1.389 73.613 1.562 73.341 1.573 c
+79.772 -0.176 m
+80.58 1.941 l
+81.065 1.941 l
+79.831 -1.043 l
+79.463 -1.043 l
+79.272 1.087 l
+78.346 -1.043 l
+77.964 -1.043 l
+77.773 1.941 l
+78.228 1.941 l
+78.317 -0.118 l
+79.213 1.941 l
+79.596 1.941 l
+h
+83.402 -1.043 m
+83.392 -0.985 83.388 -0.933 83.388 -0.881 c
+83.402 -0.72 l
+83.197 -0.977 82.969 -1.103 82.727 -1.103 c
+82.48 -1.103 82.289 -1.025 82.153 -0.867 c
+82.025 -0.713 81.969 -0.507 81.991 -0.249 c
+82.01 0.052 82.139 0.298 82.374 0.485 c
+82.609 0.669 82.91 0.765 83.285 0.765 c
+83.623 0.765 l
+83.667 1.087 l
+83.697 1.411 83.572 1.573 83.3 1.573 c
+83.153 1.573 83.028 1.529 82.932 1.44 c
+82.833 1.36 82.775 1.253 82.756 1.118 c
+82.286 1.118 l
+82.304 1.36 82.418 1.565 82.623 1.735 c
+82.829 1.911 83.068 1.999 83.344 1.999 c
+83.608 1.989 83.814 1.904 83.961 1.75 c
+84.108 1.592 84.167 1.367 84.138 1.073 c
+83.903 -0.397 l
+83.88 -0.496 83.873 -0.595 83.873 -0.691 c
+83.888 -0.999 l
+83.888 -1.043 l
+h
+82.814 -0.661 m
+83.057 -0.661 83.263 -0.544 83.432 -0.309 c
+83.564 0.397 l
+83.344 0.412 l
+83.157 0.412 82.991 0.375 82.844 0.309 c
+82.697 0.239 82.594 0.14 82.536 0.015 c
+82.477 -0.103 82.455 -0.235 82.477 -0.382 c
+82.495 -0.569 82.609 -0.661 82.814 -0.661 c
+86.938 -0.264 m
+86.968 -0.088 86.868 0.059 86.644 0.177 c
+86.276 0.368 l
+86.089 0.474 85.956 0.588 85.879 0.706 c
+85.798 0.823 85.765 0.963 85.777 1.132 c
+85.784 1.374 85.883 1.58 86.07 1.75 c
+86.265 1.914 86.504 1.999 86.791 1.999 c
+87.055 1.989 87.261 1.9 87.408 1.735 c
+87.562 1.565 87.633 1.353 87.614 1.087 c
+87.144 1.087 l
+87.151 1.235 87.118 1.353 87.041 1.44 c
+86.97 1.529 86.879 1.573 86.762 1.573 c
+86.615 1.573 86.497 1.532 86.409 1.455 c
+86.32 1.374 86.265 1.272 86.247 1.147 c
+86.218 1 86.284 0.875 86.453 0.779 c
+86.923 0.544 l
+87.265 0.345 87.427 0.092 87.408 -0.22 c
+87.386 -0.496 87.28 -0.716 87.085 -0.881 c
+86.887 -1.04 86.648 -1.109 86.365 -1.103 c
+86.089 -1.091 85.865 -1.007 85.688 -0.837 c
+85.519 -0.661 85.442 -0.434 85.453 -0.147 c
+85.938 -0.147 l
+85.927 -0.324 85.96 -0.455 86.041 -0.544 c
+86.129 -0.632 86.239 -0.676 86.38 -0.676 c
+86.534 -0.676 86.662 -0.639 86.762 -0.559 c
+86.857 -0.481 86.916 -0.382 86.938 -0.264 c
+91.994 -0.691 m
+92.148 -0.691 92.277 -0.643 92.377 -0.544 c
+92.483 -0.437 92.56 -0.29 92.612 -0.103 c
+93.052 -0.103 l
+93.012 -0.397 92.89 -0.643 92.685 -0.837 c
+92.479 -1.025 92.237 -1.109 91.965 -1.103 c
+91.7 -1.091 91.487 -1.014 91.333 -0.867 c
+91.175 -0.713 91.083 -0.496 91.053 -0.22 c
+91.032 -0.055 91.032 0.11 91.053 0.279 c
+91.097 0.574 l
+91.157 1.044 91.292 1.401 91.509 1.646 c
+91.733 1.889 92.027 2.007 92.391 1.999 c
+92.663 1.989 92.876 1.885 93.023 1.691 c
+93.177 1.492 93.251 1.235 93.243 0.912 c
+92.788 0.912 l
+92.795 1.341 92.655 1.562 92.362 1.573 c
+91.928 1.592 91.671 1.286 91.583 0.661 c
+91.524 0.268 91.498 0 91.509 -0.147 c
+91.527 -0.5 91.689 -0.683 91.994 -0.691 c
+95.24 1.632 m
+95.452 1.874 95.695 1.992 95.959 1.985 c
+96.154 1.985 96.304 1.918 96.415 1.793 c
+96.522 1.675 96.58 1.503 96.591 1.279 c
+96.599 1.151 96.599 1.029 96.591 0.912 c
+96.268 -1.043 l
+95.783 -1.043 l
+96.121 0.927 l
+96.136 1.132 l
+96.136 1.415 96.018 1.562 95.783 1.573 c
+95.595 1.573 95.419 1.463 95.254 1.249 c
+95.165 1.132 l
+94.798 -1.043 l
+94.313 -1.043 l
+95.048 3.19 l
+95.533 3.19 l
+h
+99.354 -1.043 m
+99.344 -0.985 99.34 -0.933 99.34 -0.881 c
+99.354 -0.72 l
+99.149 -0.977 98.922 -1.103 98.679 -1.103 c
+98.432 -1.103 98.241 -1.025 98.105 -0.867 c
+97.977 -0.713 97.922 -0.507 97.943 -0.249 c
+97.962 0.052 98.091 0.298 98.326 0.485 c
+98.561 0.669 98.862 0.765 99.238 0.765 c
+99.575 0.765 l
+99.62 1.087 l
+99.649 1.411 99.524 1.573 99.252 1.573 c
+99.105 1.573 98.98 1.529 98.884 1.44 c
+98.785 1.36 98.727 1.253 98.708 1.118 c
+98.238 1.118 l
+98.256 1.36 98.37 1.565 98.575 1.735 c
+98.781 1.911 99.02 1.999 99.296 1.999 c
+99.56 1.989 99.766 1.904 99.913 1.75 c
+100.06 1.592 100.119 1.367 100.09 1.073 c
+99.855 -0.397 l
+99.832 -0.496 99.825 -0.595 99.825 -0.691 c
+99.84 -0.999 l
+99.84 -1.043 l
+h
+98.767 -0.661 m
+99.009 -0.661 99.215 -0.544 99.384 -0.309 c
+99.516 0.397 l
+99.296 0.412 l
+99.109 0.412 98.943 0.375 98.796 0.309 c
+98.649 0.239 98.546 0.14 98.488 0.015 c
+98.429 -0.103 98.407 -0.235 98.429 -0.382 c
+98.447 -0.569 98.561 -0.661 98.767 -0.661 c
+101.534 0.574 m
+101.592 1.004 101.732 1.353 101.96 1.617 c
+102.195 1.881 102.49 2.007 102.843 1.999 c
+103.066 1.989 103.254 1.918 103.4 1.793 c
+103.548 1.675 103.651 1.507 103.709 1.294 c
+103.776 1.077 103.797 0.842 103.768 0.588 c
+103.739 0.309 l
+103.669 -0.125 103.518 -0.47 103.283 -0.735 c
+103.055 -0.992 102.768 -1.109 102.415 -1.103 c
+102.188 -1.091 102.004 -1.029 101.858 -0.912 c
+101.71 -0.786 101.6 -0.617 101.534 -0.411 c
+101.475 -0.199 101.461 0.044 101.49 0.309 c
+h
+101.96 0.103 m
+101.949 -0.143 101.982 -0.334 102.063 -0.47 c
+102.151 -0.61 102.276 -0.683 102.446 -0.691 c
+102.651 -0.702 102.82 -0.628 102.96 -0.47 c
+103.107 -0.305 103.202 -0.058 103.254 0.264 c
+103.298 0.588 l
+103.313 0.794 l
+103.313 1.037 103.269 1.228 103.18 1.367 c
+103.099 1.503 102.978 1.573 102.812 1.573 c
+102.596 1.58 102.415 1.492 102.269 1.309 c
+102.129 1.121 102.041 0.86 102.004 0.53 c
+101.96 0.25 l
+h
+106.51 -0.264 m
+106.539 -0.088 106.44 0.059 106.215 0.177 c
+105.848 0.368 l
+105.661 0.474 105.528 0.588 105.451 0.706 c
+105.37 0.823 105.337 0.963 105.349 1.132 c
+105.355 1.374 105.455 1.58 105.642 1.75 c
+105.837 1.914 106.076 1.999 106.363 1.999 c
+106.627 1.989 106.833 1.9 106.98 1.735 c
+107.134 1.565 107.204 1.353 107.186 1.087 c
+106.716 1.087 l
+106.723 1.235 106.689 1.353 106.612 1.44 c
+106.542 1.529 106.45 1.573 106.333 1.573 c
+106.186 1.573 106.068 1.532 105.98 1.455 c
+105.892 1.374 105.837 1.272 105.819 1.147 c
+105.789 1 105.856 0.875 106.024 0.779 c
+106.495 0.544 l
+106.837 0.345 106.999 0.092 106.98 -0.22 c
+106.958 -0.496 106.851 -0.716 106.656 -0.881 c
+106.458 -1.04 106.219 -1.109 105.937 -1.103 c
+105.661 -1.091 105.436 -1.007 105.26 -0.837 c
+105.091 -0.661 105.014 -0.434 105.025 -0.147 c
+105.51 -0.147 l
+105.499 -0.324 105.532 -0.455 105.613 -0.544 c
+105.701 -0.632 105.812 -0.676 105.951 -0.676 c
+106.105 -0.676 106.234 -0.639 106.333 -0.559 c
+106.429 -0.481 106.488 -0.382 106.51 -0.264 c
+108.237 -1.852 m
+107.957 -1.646 l
+108.175 -1.382 108.303 -1.117 108.354 -0.852 c
+108.428 -0.441 l
+108.913 -0.441 l
+108.854 -0.808 l
+108.784 -1.227 108.578 -1.577 108.237 -1.852 c
+f
+Q
+q 1 0 0 1 170.9031 102.5161 cm
+0 0 m
+0.808 2.117 l
+1.294 2.117 l
+0.058 -0.867 l
+-0.31 -0.867 l
+-0.5 1.264 l
+-1.426 -0.867 l
+-1.808 -0.867 l
+-1.999 2.117 l
+-1.544 2.117 l
+-1.455 0.058 l
+-0.559 2.117 l
+-0.177 2.117 l
+h
+3.027 1.808 m
+3.241 2.05 3.484 2.167 3.748 2.161 c
+3.943 2.161 4.093 2.094 4.203 1.97 c
+4.31 1.852 4.369 1.679 4.38 1.455 c
+4.388 1.326 4.388 1.205 4.38 1.087 c
+4.056 -0.867 l
+3.571 -0.867 l
+3.91 1.103 l
+3.924 1.308 l
+3.924 1.591 3.806 1.738 3.571 1.749 c
+3.384 1.749 3.208 1.639 3.042 1.425 c
+2.954 1.308 l
+2.587 -0.867 l
+2.102 -0.867 l
+2.836 3.366 l
+3.322 3.366 l
+h
+6.732 -0.927 m
+6.397 -0.915 6.148 -0.794 5.982 -0.559 c
+5.813 -0.324 5.754 0 5.805 0.411 c
+5.835 0.706 l
+5.894 1.165 6.034 1.529 6.262 1.793 c
+6.485 2.057 6.769 2.183 7.114 2.175 c
+7.397 2.165 7.607 2.065 7.746 1.881 c
+7.893 1.694 7.966 1.429 7.966 1.087 c
+7.937 0.764 l
+7.893 0.484 l
+6.291 0.484 l
+6.269 0.316 6.262 0.183 6.262 0.088 c
+6.262 -0.1 6.306 -0.246 6.393 -0.353 c
+6.482 -0.452 6.607 -0.5 6.776 -0.5 c
+6.894 -0.511 7.011 -0.493 7.129 -0.441 c
+7.247 -0.382 7.364 -0.294 7.482 -0.177 c
+7.717 -0.485 l
+7.599 -0.632 7.452 -0.746 7.276 -0.823 c
+7.099 -0.89 6.915 -0.927 6.732 -0.927 c
+7.085 1.749 m
+6.761 1.768 6.533 1.573 6.408 1.161 c
+6.335 0.897 l
+7.482 0.897 l
+7.482 0.97 l
+7.5 1.047 7.511 1.135 7.511 1.234 c
+7.5 1.565 7.357 1.738 7.085 1.749 c
+10.715 1.66 m
+10.634 1.679 10.561 1.691 10.495 1.691 c
+10.26 1.691 10.061 1.547 9.907 1.264 c
+9.539 -0.867 l
+9.055 -0.867 l
+9.583 2.117 l
+10.039 2.117 l
+9.965 1.808 l
+10.142 2.061 10.341 2.183 10.568 2.175 c
+10.605 2.175 10.671 2.161 10.759 2.131 c
+h
+12.681 -0.927 m
+12.347 -0.915 12.097 -0.794 11.931 -0.559 c
+11.762 -0.324 11.704 0 11.755 0.411 c
+11.785 0.706 l
+11.843 1.165 11.983 1.529 12.211 1.793 c
+12.435 2.057 12.718 2.183 13.063 2.175 c
+13.346 2.165 13.556 2.065 13.695 1.881 c
+13.842 1.694 13.916 1.429 13.916 1.087 c
+13.886 0.764 l
+13.842 0.484 l
+12.24 0.484 l
+12.218 0.316 12.211 0.183 12.211 0.088 c
+12.211 -0.1 12.255 -0.246 12.343 -0.353 c
+12.431 -0.452 12.556 -0.5 12.725 -0.5 c
+12.843 -0.511 12.961 -0.493 13.078 -0.441 c
+13.196 -0.382 13.313 -0.294 13.431 -0.177 c
+13.666 -0.485 l
+13.549 -0.632 13.402 -0.746 13.225 -0.823 c
+13.049 -0.89 12.865 -0.927 12.681 -0.927 c
+13.034 1.749 m
+12.71 1.768 12.483 1.573 12.358 1.161 c
+12.284 0.897 l
+13.431 0.897 l
+13.431 0.97 l
+13.449 1.047 13.46 1.135 13.46 1.234 c
+13.449 1.565 13.306 1.738 13.034 1.749 c
+18.127 2.117 m
+18.069 1.793 l
+18.281 2.047 18.528 2.175 18.803 2.175 c
+18.987 2.165 19.134 2.094 19.245 1.97 c
+19.362 1.852 19.424 1.679 19.436 1.455 c
+19.443 1.326 19.443 1.205 19.436 1.087 c
+19.112 -0.867 l
+18.627 -0.867 l
+18.965 1.103 l
+18.979 1.308 l
+18.979 1.591 18.862 1.738 18.627 1.749 c
+18.439 1.749 18.264 1.639 18.098 1.425 c
+18.01 1.308 l
+17.642 -0.867 l
+17.157 -0.867 l
+17.686 2.117 l
+h
+20.887 0.75 m
+20.946 1.18 21.086 1.529 21.313 1.793 c
+21.549 2.057 21.842 2.183 22.195 2.175 c
+22.42 2.165 22.607 2.094 22.754 1.97 c
+22.9 1.852 23.004 1.683 23.062 1.469 c
+23.129 1.253 23.151 1.018 23.121 0.764 c
+23.091 0.484 l
+23.022 0.051 22.871 -0.294 22.636 -0.559 c
+22.408 -0.816 22.121 -0.933 21.769 -0.927 c
+21.541 -0.915 21.358 -0.852 21.21 -0.735 c
+21.063 -0.611 20.953 -0.441 20.887 -0.235 c
+20.828 -0.023 20.814 0.22 20.843 0.484 c
+h
+21.313 0.279 m
+21.302 0.033 21.335 -0.158 21.416 -0.294 c
+21.504 -0.434 21.629 -0.507 21.798 -0.515 c
+22.004 -0.526 22.173 -0.452 22.312 -0.294 c
+22.46 -0.129 22.555 0.118 22.607 0.441 c
+22.651 0.764 l
+22.665 0.97 l
+22.665 1.213 22.621 1.404 22.534 1.543 c
+22.453 1.679 22.331 1.749 22.166 1.749 c
+21.949 1.756 21.769 1.668 21.622 1.484 c
+21.483 1.297 21.394 1.036 21.358 0.706 c
+21.313 0.426 l
+h
+f
+Q
+q 1 0 0 1 198.4339 102.7654 cm
+0 0 m
+0.661 1.867 l
+1.47 1.867 l
+0.206 -1.117 l
+-0.515 -1.117 l
+-0.852 1.867 l
+-0.073 1.867 l
+h
+3.396 -1.176 m
+3.15 -1.176 2.944 -1.117 2.778 -0.999 c
+2.61 -0.881 2.488 -0.72 2.411 -0.514 c
+2.341 -0.301 2.323 -0.058 2.352 0.206 c
+2.367 0.412 l
+2.433 0.9 2.587 1.279 2.822 1.544 c
+3.057 1.808 3.359 1.933 3.734 1.926 c
+4.006 1.915 4.222 1.827 4.38 1.661 c
+4.535 1.503 4.623 1.279 4.645 0.985 c
+4.663 0.809 4.663 0.636 4.645 0.47 c
+4.586 0.118 l
+3.102 0.118 l
+3.09 0.037 3.087 -0.04 3.087 -0.118 c
+3.105 -0.382 3.238 -0.514 3.484 -0.514 c
+3.708 -0.525 3.929 -0.44 4.145 -0.264 c
+4.41 -0.735 l
+4.3 -0.874 4.152 -0.981 3.969 -1.058 c
+3.792 -1.135 3.601 -1.176 3.396 -1.176 c
+3.66 1.279 m
+3.443 1.287 3.293 1.147 3.204 0.853 c
+3.146 0.662 l
+3.91 0.662 l
+3.929 0.757 3.94 0.842 3.94 0.912 c
+3.946 1.147 3.855 1.268 3.66 1.279 c
+7.493 1.118 m
+7.258 1.147 l
+7.052 1.147 6.883 1.048 6.758 0.853 c
+6.42 -1.117 l
+5.656 -1.117 l
+6.17 1.867 l
+6.89 1.867 l
+6.832 1.544 l
+6.92 1.68 7.001 1.779 7.082 1.838 c
+7.169 1.897 7.265 1.926 7.375 1.926 c
+7.435 1.926 7.508 1.912 7.596 1.881 c
+h
+9.801 -0.294 m
+9.819 -0.168 9.716 -0.055 9.492 0.044 c
+9.276 0.14 9.114 0.235 9.007 0.324 c
+8.897 0.42 8.816 0.522 8.757 0.632 c
+8.706 0.739 8.688 0.86 8.698 1 c
+8.706 1.264 8.816 1.485 9.022 1.661 c
+9.235 1.838 9.496 1.926 9.801 1.926 c
+10.095 1.915 10.323 1.823 10.492 1.646 c
+10.668 1.478 10.756 1.257 10.756 0.985 c
+9.992 0.985 l
+9.992 1.11 9.97 1.199 9.933 1.25 c
+9.893 1.309 9.834 1.338 9.756 1.338 c
+9.669 1.338 9.588 1.309 9.521 1.25 c
+9.463 1.191 9.426 1.118 9.419 1.029 c
+9.39 0.912 9.477 0.802 9.683 0.706 c
+9.897 0.618 10.051 0.545 10.139 0.485 c
+10.411 0.298 10.539 0.048 10.521 -0.264 c
+10.51 -0.452 10.452 -0.613 10.344 -0.749 c
+10.246 -0.889 10.109 -0.995 9.933 -1.072 c
+9.764 -1.139 9.58 -1.176 9.374 -1.176 c
+9.081 -1.165 8.838 -1.072 8.654 -0.897 c
+8.478 -0.712 8.39 -0.477 8.39 -0.191 c
+9.124 -0.191 l
+9.114 -0.338 9.132 -0.448 9.183 -0.514 c
+9.242 -0.573 9.323 -0.602 9.434 -0.602 c
+9.521 -0.602 9.598 -0.58 9.669 -0.529 c
+9.735 -0.47 9.779 -0.393 9.801 -0.294 c
+12.517 -1.117 m
+11.767 -1.117 l
+12.281 1.867 l
+13.045 1.867 l
+h
+12.384 2.617 m
+12.384 2.741 12.421 2.845 12.501 2.926 c
+12.579 3.014 12.678 3.057 12.796 3.057 c
+12.902 3.057 12.994 3.017 13.075 2.94 c
+13.163 2.859 13.207 2.764 13.207 2.646 c
+13.207 2.517 13.163 2.415 13.075 2.338 c
+12.994 2.257 12.898 2.22 12.781 2.22 c
+12.663 2.22 12.565 2.253 12.487 2.323 c
+12.417 2.4 12.384 2.5 12.384 2.617 c
+15.578 1.926 m
+15.879 1.915 16.114 1.812 16.283 1.617 c
+16.449 1.419 16.54 1.154 16.563 0.823 c
+16.563 0.632 l
+16.533 0.052 16.39 -0.396 16.137 -0.72 c
+15.89 -1.036 15.563 -1.183 15.152 -1.176 c
+14.916 -1.165 14.718 -1.102 14.564 -0.984 c
+14.416 -0.86 14.306 -0.687 14.24 -0.47 c
+14.17 -0.257 14.152 -0.007 14.181 0.279 c
+14.196 0.427 l
+14.255 0.897 14.406 1.264 14.651 1.529 c
+14.894 1.801 15.202 1.933 15.578 1.926 c
+14.93 -0.029 m
+14.93 -0.353 15.026 -0.521 15.225 -0.529 c
+15.489 -0.551 15.659 -0.349 15.74 0.074 c
+15.769 0.279 l
+15.798 0.545 15.813 0.709 15.813 0.78 c
+15.813 1.103 15.709 1.268 15.504 1.279 c
+15.357 1.287 15.232 1.22 15.136 1.073 c
+15.048 0.934 14.99 0.728 14.961 0.456 c
+14.938 0.192 14.93 0.03 14.93 -0.029 c
+18.811 1.867 m
+18.767 1.573 l
+18.973 1.816 19.2 1.933 19.458 1.926 c
+19.664 1.915 19.819 1.831 19.929 1.676 c
+20.046 1.529 20.105 1.312 20.105 1.029 c
+20.075 0.78 l
+19.767 -1.117 l
+19.002 -1.117 l
+19.311 0.78 l
+19.326 0.941 l
+19.333 1.154 19.256 1.264 19.09 1.264 c
+19.01 1.264 18.944 1.243 18.884 1.206 c
+18.826 1.166 18.774 1.118 18.738 1.058 c
+18.356 -1.117 l
+17.591 -1.117 l
+18.105 1.867 l
+h
+24.515 -0.529 m
+24.721 -0.54 24.845 -0.393 24.897 -0.087 c
+25.617 -0.087 l
+25.577 -0.411 25.448 -0.675 25.234 -0.881 c
+25.029 -1.087 24.772 -1.183 24.471 -1.176 c
+24.184 -1.165 23.96 -1.084 23.794 -0.926 c
+23.636 -0.771 23.545 -0.551 23.515 -0.264 c
+23.486 -0.029 23.493 0.25 23.545 0.574 c
+23.603 0.904 23.706 1.18 23.853 1.397 c
+24.089 1.757 24.43 1.933 24.882 1.926 c
+25.176 1.915 25.4 1.801 25.558 1.588 c
+25.724 1.382 25.797 1.103 25.779 0.75 c
+25.058 0.75 l
+25.058 0.927 l
+25.058 1.151 24.97 1.268 24.794 1.279 c
+24.529 1.287 24.368 1.077 24.309 0.647 c
+24.264 0.148 l
+24.235 0 24.224 -0.124 24.235 -0.22 c
+24.253 -0.419 24.345 -0.521 24.515 -0.529 c
+28.307 1.926 m
+28.608 1.915 28.843 1.812 29.012 1.617 c
+29.178 1.419 29.269 1.154 29.292 0.823 c
+29.292 0.632 l
+29.263 0.052 29.119 -0.396 28.866 -0.72 c
+28.619 -1.036 28.292 -1.183 27.881 -1.176 c
+27.646 -1.165 27.447 -1.102 27.293 -0.984 c
+27.146 -0.86 27.035 -0.687 26.969 -0.47 c
+26.899 -0.257 26.881 -0.007 26.911 0.279 c
+26.925 0.427 l
+26.984 0.897 27.135 1.264 27.381 1.529 c
+27.623 1.801 27.932 1.933 28.307 1.926 c
+27.661 -0.029 m
+27.661 -0.353 27.756 -0.521 27.954 -0.529 c
+28.218 -0.551 28.388 -0.349 28.469 0.074 c
+28.498 0.279 l
+28.527 0.545 28.542 0.709 28.542 0.78 c
+28.542 1.103 28.439 1.268 28.233 1.279 c
+28.087 1.287 27.962 1.22 27.866 1.073 c
+27.778 0.934 27.719 0.728 27.69 0.456 c
+27.667 0.192 27.661 0.03 27.661 -0.029 c
+31.541 1.867 m
+31.497 1.573 l
+31.702 1.816 31.931 1.933 32.187 1.926 c
+32.393 1.915 32.548 1.831 32.658 1.676 c
+32.775 1.529 32.835 1.312 32.835 1.029 c
+32.805 0.78 l
+32.496 -1.117 l
+31.732 -1.117 l
+32.041 0.78 l
+32.055 0.941 l
+32.062 1.154 31.985 1.264 31.82 1.264 c
+31.739 1.264 31.673 1.243 31.614 1.206 c
+31.555 1.166 31.503 1.118 31.467 1.058 c
+31.085 -1.117 l
+30.321 -1.117 l
+30.836 1.867 l
+h
+35.432 2.602 m
+35.314 1.867 l
+35.696 1.867 l
+35.594 1.279 l
+35.212 1.279 l
+34.948 -0.22 l
+34.948 -0.309 l
+34.936 -0.437 34.984 -0.5 35.094 -0.5 c
+35.123 -0.5 35.186 -0.496 35.285 -0.484 c
+35.212 -1.102 l
+35.102 -1.15 34.969 -1.176 34.815 -1.176 c
+34.599 -1.165 34.433 -1.084 34.315 -0.926 c
+34.205 -0.771 34.161 -0.558 34.183 -0.294 c
+34.447 1.279 l
+34.109 1.279 l
+34.212 1.867 l
+34.551 1.867 l
+34.668 2.602 l
+h
+38.317 1.118 m
+38.082 1.147 l
+37.876 1.147 37.707 1.048 37.582 0.853 c
+37.244 -1.117 l
+36.48 -1.117 l
+36.994 1.867 l
+37.714 1.867 l
+37.656 1.544 l
+37.743 1.68 37.824 1.779 37.905 1.838 c
+37.994 1.897 38.089 1.926 38.2 1.926 c
+38.258 1.926 38.331 1.912 38.42 1.881 c
+h
+40.658 1.926 m
+40.959 1.915 41.194 1.812 41.363 1.617 c
+41.529 1.419 41.62 1.154 41.643 0.823 c
+41.643 0.632 l
+41.614 0.052 41.47 -0.396 41.217 -0.72 c
+40.97 -1.036 40.643 -1.183 40.232 -1.176 c
+39.996 -1.165 39.798 -1.102 39.644 -0.984 c
+39.497 -0.86 39.386 -0.687 39.32 -0.47 c
+39.25 -0.257 39.232 -0.007 39.262 0.279 c
+39.276 0.427 l
+39.335 0.897 39.486 1.264 39.732 1.529 c
+39.974 1.801 40.283 1.933 40.658 1.926 c
+40.011 -0.029 m
+40.011 -0.353 40.107 -0.521 40.305 -0.529 c
+40.569 -0.551 40.739 -0.349 40.82 0.074 c
+40.849 0.279 l
+40.878 0.545 40.893 0.709 40.893 0.78 c
+40.893 1.103 40.79 1.268 40.584 1.279 c
+40.438 1.287 40.313 1.22 40.217 1.073 c
+40.128 0.934 40.07 0.728 40.041 0.456 c
+40.018 0.192 40.011 0.03 40.011 -0.029 c
+43.48 -1.117 m
+42.73 -1.117 l
+43.451 3.117 l
+44.23 3.117 l
+h
+f
+Q
+q 1 0 0 1 247.9403 102.5161 cm
+0 0 m
+0.809 2.117 l
+1.294 2.117 l
+0.059 -0.867 l
+-0.309 -0.867 l
+-0.5 1.264 l
+-1.425 -0.867 l
+-1.808 -0.867 l
+-1.999 2.117 l
+-1.543 2.117 l
+-1.455 0.058 l
+-0.559 2.117 l
+-0.176 2.117 l
+h
+3.631 -0.867 m
+3.62 -0.809 3.616 -0.757 3.616 -0.706 c
+3.631 -0.544 l
+3.425 -0.802 3.198 -0.927 2.955 -0.927 c
+2.708 -0.927 2.517 -0.849 2.381 -0.691 c
+2.253 -0.537 2.198 -0.331 2.22 -0.073 c
+2.238 0.228 2.367 0.474 2.602 0.661 c
+2.837 0.845 3.138 0.941 3.514 0.941 c
+3.851 0.941 l
+3.896 1.264 l
+3.925 1.587 3.8 1.749 3.528 1.749 c
+3.381 1.749 3.256 1.705 3.161 1.617 c
+3.061 1.536 3.003 1.429 2.984 1.294 c
+2.514 1.294 l
+2.532 1.536 2.646 1.741 2.851 1.911 c
+3.057 2.087 3.296 2.175 3.572 2.175 c
+3.836 2.165 4.042 2.08 4.189 1.926 c
+4.337 1.768 4.395 1.543 4.366 1.249 c
+4.131 -0.221 l
+4.108 -0.32 4.102 -0.42 4.102 -0.515 c
+4.116 -0.823 l
+4.116 -0.867 l
+h
+3.043 -0.485 m
+3.285 -0.485 3.491 -0.368 3.66 -0.133 c
+3.792 0.573 l
+3.572 0.588 l
+3.385 0.588 3.219 0.551 3.072 0.484 c
+2.926 0.415 2.822 0.316 2.764 0.191 c
+2.705 0.073 2.683 -0.059 2.705 -0.206 c
+2.723 -0.393 2.837 -0.485 3.043 -0.485 c
+7.162 -0.088 m
+7.192 0.088 7.092 0.235 6.868 0.353 c
+6.501 0.544 l
+6.313 0.65 6.181 0.764 6.104 0.881 c
+6.024 0.999 5.99 1.139 6.001 1.308 c
+6.008 1.55 6.107 1.756 6.295 1.926 c
+6.49 2.09 6.729 2.175 7.015 2.175 c
+7.279 2.165 7.485 2.076 7.632 1.911 c
+7.787 1.741 7.857 1.529 7.838 1.264 c
+7.368 1.264 l
+7.375 1.411 7.342 1.529 7.265 1.617 c
+7.196 1.705 7.104 1.749 6.986 1.749 c
+6.839 1.749 6.722 1.708 6.633 1.631 c
+6.545 1.55 6.49 1.448 6.471 1.323 c
+6.442 1.176 6.508 1.051 6.677 0.955 c
+7.148 0.72 l
+7.489 0.521 7.651 0.268 7.632 -0.044 c
+7.611 -0.32 7.504 -0.54 7.31 -0.706 c
+7.111 -0.864 6.872 -0.933 6.589 -0.927 c
+6.313 -0.915 6.089 -0.831 5.913 -0.661 c
+5.744 -0.485 5.667 -0.258 5.677 0.029 c
+6.163 0.029 l
+6.152 -0.147 6.184 -0.279 6.265 -0.368 c
+6.354 -0.456 6.464 -0.5 6.604 -0.5 c
+6.758 -0.5 6.886 -0.463 6.986 -0.382 c
+7.082 -0.305 7.14 -0.206 7.162 -0.088 c
+12.689 -0.603 m
+12.491 -0.831 12.252 -0.933 11.969 -0.927 c
+11.752 -0.927 11.587 -0.852 11.469 -0.706 c
+11.358 -0.551 11.308 -0.335 11.308 -0.059 c
+11.322 0.191 l
+11.645 2.117 l
+12.116 2.117 l
+11.807 0.176 l
+11.792 -0.015 l
+11.782 -0.154 11.8 -0.264 11.851 -0.353 c
+11.899 -0.441 11.977 -0.485 12.087 -0.485 c
+12.351 -0.507 12.565 -0.375 12.733 -0.088 c
+13.116 2.117 l
+13.6 2.117 l
+13.086 -0.867 l
+12.63 -0.867 l
+h
+16.214 -0.088 m
+16.243 0.088 16.143 0.235 15.919 0.353 c
+15.551 0.544 l
+15.364 0.65 15.232 0.764 15.155 0.881 c
+15.074 0.999 15.041 1.139 15.052 1.308 c
+15.059 1.55 15.158 1.756 15.346 1.926 c
+15.541 2.09 15.78 2.175 16.066 2.175 c
+16.331 2.165 16.536 2.076 16.684 1.911 c
+16.838 1.741 16.908 1.529 16.889 1.264 c
+16.419 1.264 l
+16.426 1.411 16.393 1.529 16.316 1.617 c
+16.247 1.705 16.154 1.749 16.037 1.749 c
+15.89 1.749 15.772 1.708 15.684 1.631 c
+15.596 1.55 15.541 1.448 15.522 1.323 c
+15.493 1.176 15.559 1.051 15.728 0.955 c
+16.199 0.72 l
+16.54 0.521 16.702 0.268 16.684 -0.044 c
+16.661 -0.32 16.555 -0.54 16.36 -0.706 c
+16.162 -0.864 15.923 -0.933 15.64 -0.927 c
+15.364 -0.915 15.14 -0.831 14.963 -0.661 c
+14.795 -0.485 14.718 -0.258 14.728 0.029 c
+15.214 0.029 l
+15.202 -0.147 15.236 -0.279 15.316 -0.368 c
+15.405 -0.456 15.515 -0.5 15.655 -0.5 c
+15.809 -0.5 15.938 -0.463 16.037 -0.382 c
+16.133 -0.305 16.191 -0.206 16.214 -0.088 c
+19.146 -0.927 m
+18.811 -0.915 18.562 -0.794 18.396 -0.559 c
+18.227 -0.324 18.168 0 18.219 0.411 c
+18.249 0.706 l
+18.308 1.165 18.448 1.529 18.676 1.793 c
+18.899 2.057 19.183 2.183 19.528 2.175 c
+19.811 2.165 20.02 2.065 20.16 1.881 c
+20.307 1.694 20.38 1.429 20.38 1.087 c
+20.351 0.764 l
+20.307 0.484 l
+18.705 0.484 l
+18.683 0.316 18.676 0.183 18.676 0.088 c
+18.676 -0.1 18.72 -0.246 18.807 -0.353 c
+18.896 -0.452 19.021 -0.5 19.19 -0.5 c
+19.308 -0.511 19.425 -0.493 19.543 -0.441 c
+19.66 -0.382 19.778 -0.294 19.896 -0.177 c
+20.131 -0.485 l
+20.013 -0.632 19.866 -0.746 19.69 -0.823 c
+19.513 -0.89 19.329 -0.927 19.146 -0.927 c
+19.499 1.749 m
+19.175 1.768 18.947 1.573 18.822 1.161 c
+18.749 0.897 l
+19.896 0.897 l
+19.896 0.97 l
+19.914 1.047 19.925 1.135 19.925 1.234 c
+19.914 1.565 19.771 1.738 19.499 1.749 c
+22.82 2.161 m
+23.092 2.161 23.298 2.047 23.438 1.822 c
+23.732 3.366 l
+24.202 3.366 l
+23.468 -0.867 l
+23.041 -0.867 l
+23.085 -0.544 l
+22.886 -0.809 22.651 -0.933 22.379 -0.927 c
+22.134 -0.915 21.942 -0.819 21.806 -0.632 c
+21.666 -0.449 21.6 -0.177 21.6 0.176 c
+21.6 0.341 21.619 0.559 21.66 0.823 c
+21.707 1.095 21.777 1.326 21.865 1.514 c
+22.071 1.962 22.387 2.179 22.82 2.161 c
+22.071 0.058 m
+22.078 -0.305 22.232 -0.493 22.527 -0.5 c
+22.633 -0.5 22.736 -0.478 22.836 -0.426 c
+22.931 -0.368 23.026 -0.272 23.114 -0.133 c
+23.379 1.382 l
+23.291 1.606 23.137 1.723 22.923 1.735 c
+22.483 1.764 22.217 1.444 22.13 0.779 c
+22.089 0.455 22.071 0.213 22.071 0.058 c
+25.455 -0.294 m
+25.544 -0.287 25.617 -0.309 25.676 -0.368 c
+25.735 -0.426 25.764 -0.5 25.764 -0.588 c
+25.764 -0.676 25.735 -0.75 25.676 -0.809 c
+25.617 -0.867 25.544 -0.897 25.455 -0.897 c
+25.367 -0.904 25.294 -0.886 25.234 -0.838 c
+25.176 -0.779 25.147 -0.706 25.147 -0.617 c
+25.147 -0.522 25.176 -0.441 25.234 -0.382 c
+25.294 -0.324 25.367 -0.294 25.455 -0.294 c
+f
+Q
+q 1 0 0 1 138.5097 93.1379 cm
+0 0 m
+0.691 4.013 l
+1.587 4.013 l
+2.017 4.002 2.337 3.844 2.543 3.543 c
+2.749 3.237 2.822 2.837 2.763 2.337 c
+2.675 1.706 l
+2.587 1.147 2.389 0.721 2.087 0.426 c
+1.782 0.139 1.396 0 0.926 0 c
+h
+1.117 3.572 m
+0.573 0.426 l
+0.926 0.426 l
+1.268 0.426 1.547 0.53 1.764 0.735 c
+1.977 0.941 2.117 1.253 2.175 1.675 c
+2.278 2.352 l
+2.296 2.499 2.308 2.646 2.308 2.793 c
+2.296 3.036 2.227 3.223 2.102 3.352 c
+1.984 3.487 1.808 3.561 1.573 3.572 c
+h
+4.119 1.617 m
+4.178 2.047 4.318 2.396 4.546 2.66 c
+4.781 2.925 5.074 3.05 5.428 3.042 c
+5.652 3.032 5.839 2.961 5.986 2.837 c
+6.134 2.72 6.236 2.55 6.294 2.337 c
+6.361 2.12 6.383 1.885 6.354 1.631 c
+6.325 1.353 l
+6.254 0.919 6.104 0.573 5.868 0.309 c
+5.641 0.052 5.354 -0.066 5.001 -0.058 c
+4.773 -0.048 4.59 0.015 4.443 0.133 c
+4.295 0.257 4.185 0.426 4.119 0.632 c
+4.06 0.845 4.046 1.087 4.075 1.353 c
+h
+4.546 1.147 m
+4.534 0.9 4.567 0.709 4.648 0.573 c
+4.737 0.434 4.862 0.36 5.031 0.353 c
+5.236 0.341 5.405 0.415 5.545 0.573 c
+5.692 0.738 5.787 0.985 5.839 1.309 c
+5.883 1.631 l
+5.898 1.837 l
+5.898 2.08 5.854 2.271 5.766 2.411 c
+5.685 2.547 5.564 2.616 5.398 2.616 c
+5.182 2.624 5.001 2.535 4.854 2.352 c
+4.715 2.165 4.627 1.903 4.59 1.573 c
+4.546 1.294 l
+h
+8.507 2.984 m
+8.448 2.66 l
+8.661 2.914 8.908 3.042 9.183 3.042 c
+9.367 3.032 9.514 2.961 9.624 2.837 c
+9.741 2.72 9.804 2.547 9.816 2.323 c
+9.822 2.194 9.822 2.072 9.816 1.955 c
+9.492 0 l
+9.007 0 l
+9.345 1.97 l
+9.359 2.176 l
+9.359 2.458 9.242 2.606 9.007 2.616 c
+8.819 2.616 8.643 2.506 8.478 2.294 c
+8.39 2.176 l
+8.022 0 l
+7.537 0 l
+8.066 2.984 l
+h
+11.752 3.91 m
+11.546 2.911 l
+11.193 2.911 l
+11.399 4.233 l
+11.811 4.233 l
+h
+13.924 3.705 m
+13.791 2.984 l
+14.232 2.984 l
+14.159 2.587 l
+13.718 2.587 l
+13.409 0.735 l
+13.409 0.617 l
+13.398 0.459 13.454 0.382 13.571 0.382 c
+13.619 0.382 13.689 0.389 13.776 0.412 c
+13.733 0 l
+13.622 -0.037 13.519 -0.052 13.424 -0.044 c
+13.255 -0.044 13.13 0.022 13.041 0.162 c
+12.954 0.297 12.924 0.489 12.954 0.735 c
+13.247 2.587 l
+12.806 2.587 l
+12.88 2.984 l
+13.321 2.984 l
+13.438 3.705 l
+h
+17.822 0 m
+17.352 0 l
+18.088 4.233 l
+18.558 4.233 l
+h
+19.976 0 m
+19.505 0 l
+20.02 2.984 l
+20.505 2.984 l
+h
+20.137 3.778 m
+20.137 3.855 20.16 3.925 20.211 3.983 c
+20.259 4.042 20.322 4.072 20.402 4.072 c
+20.48 4.072 20.542 4.042 20.594 3.983 c
+20.652 3.932 20.675 3.865 20.667 3.778 c
+20.667 3.697 20.641 3.63 20.594 3.572 c
+20.542 3.513 20.48 3.484 20.402 3.484 c
+20.314 3.472 20.245 3.499 20.197 3.557 c
+20.145 3.616 20.126 3.69 20.137 3.778 c
+22.585 0.75 m
+23.482 2.984 l
+23.981 2.984 l
+22.659 0 l
+22.291 0 l
+21.894 2.984 l
+22.364 2.984 l
+h
+25.926 -0.058 m
+25.591 -0.048 25.341 0.073 25.176 0.309 c
+25.007 0.544 24.948 0.867 24.999 1.278 c
+25.028 1.573 l
+25.088 2.032 25.227 2.396 25.455 2.66 c
+25.679 2.925 25.963 3.05 26.308 3.042 c
+26.591 3.032 26.8 2.932 26.94 2.749 c
+27.087 2.562 27.16 2.296 27.16 1.955 c
+27.131 1.631 l
+27.087 1.353 l
+25.485 1.353 l
+25.462 1.183 25.455 1.051 25.455 0.956 c
+25.455 0.768 25.499 0.621 25.587 0.515 c
+25.676 0.415 25.801 0.368 25.969 0.368 c
+26.087 0.357 26.204 0.374 26.322 0.426 c
+26.439 0.485 26.557 0.573 26.675 0.691 c
+26.91 0.382 l
+26.792 0.235 26.646 0.121 26.47 0.044 c
+26.293 -0.022 26.109 -0.058 25.926 -0.058 c
+26.279 2.616 m
+25.955 2.635 25.727 2.44 25.602 2.028 c
+25.529 1.764 l
+26.675 1.764 l
+26.675 1.837 l
+26.693 1.914 26.705 2.003 26.705 2.102 c
+26.693 2.433 26.55 2.606 26.279 2.616 c
+30.916 0 m
+30.445 0 l
+30.96 2.984 l
+31.445 2.984 l
+h
+31.077 3.778 m
+31.077 3.855 31.1 3.925 31.151 3.983 c
+31.199 4.042 31.261 4.072 31.342 4.072 c
+31.419 4.072 31.482 4.042 31.534 3.983 c
+31.592 3.932 31.614 3.865 31.607 3.778 c
+31.607 3.697 31.581 3.63 31.534 3.572 c
+31.482 3.513 31.419 3.484 31.342 3.484 c
+31.254 3.472 31.184 3.499 31.137 3.557 c
+31.085 3.616 31.066 3.69 31.077 3.778 c
+33.525 2.984 m
+33.466 2.66 l
+33.679 2.914 33.925 3.042 34.201 3.042 c
+34.385 3.032 34.532 2.961 34.642 2.837 c
+34.759 2.72 34.822 2.547 34.833 2.323 c
+34.84 2.194 34.84 2.072 34.833 1.955 c
+34.51 0 l
+34.025 0 l
+34.362 1.97 l
+34.377 2.176 l
+34.377 2.458 34.26 2.606 34.025 2.616 c
+33.837 2.616 33.661 2.506 33.495 2.294 c
+33.408 2.176 l
+33.04 0 l
+32.554 0 l
+33.084 2.984 l
+h
+39.32 0.353 m
+39.474 0.353 39.603 0.401 39.702 0.5 c
+39.808 0.607 39.885 0.754 39.937 0.941 c
+40.378 0.941 l
+40.338 0.647 40.217 0.401 40.011 0.206 c
+39.805 0.019 39.563 -0.066 39.291 -0.058 c
+39.026 -0.048 38.813 0.029 38.659 0.177 c
+38.501 0.331 38.409 0.548 38.379 0.823 c
+38.357 0.989 38.357 1.154 38.379 1.323 c
+38.424 1.617 l
+38.482 2.087 38.618 2.444 38.835 2.69 c
+39.06 2.932 39.353 3.05 39.717 3.042 c
+39.989 3.032 40.202 2.929 40.349 2.734 c
+40.504 2.535 40.577 2.278 40.569 1.955 c
+40.114 1.955 l
+40.121 2.385 39.981 2.606 39.687 2.616 c
+39.254 2.635 38.996 2.33 38.908 1.706 c
+38.85 1.312 38.824 1.043 38.835 0.897 c
+38.853 0.544 39.015 0.36 39.32 0.353 c
+42.565 2.675 m
+42.778 2.918 43.02 3.036 43.285 3.028 c
+43.48 3.028 43.631 2.961 43.741 2.837 c
+43.847 2.72 43.906 2.547 43.917 2.323 c
+43.924 2.194 43.924 2.072 43.917 1.955 c
+43.594 0 l
+43.108 0 l
+43.447 1.97 l
+43.461 2.176 l
+43.461 2.458 43.344 2.606 43.108 2.616 c
+42.921 2.616 42.744 2.506 42.58 2.294 c
+42.491 2.176 l
+42.123 0 l
+41.639 0 l
+42.374 4.233 l
+42.859 4.233 l
+h
+46.68 0 m
+46.669 0.059 46.665 0.11 46.665 0.162 c
+46.68 0.324 l
+46.474 0.066 46.247 -0.058 46.004 -0.058 c
+45.759 -0.058 45.567 0.019 45.431 0.177 c
+45.302 0.331 45.248 0.536 45.269 0.794 c
+45.288 1.095 45.416 1.341 45.651 1.529 c
+45.886 1.712 46.188 1.808 46.563 1.808 c
+46.901 1.808 l
+46.945 2.132 l
+46.975 2.454 46.85 2.616 46.578 2.616 c
+46.43 2.616 46.306 2.572 46.21 2.484 c
+46.111 2.404 46.052 2.296 46.034 2.161 c
+45.564 2.161 l
+45.582 2.404 45.695 2.609 45.902 2.778 c
+46.108 2.955 46.346 3.042 46.622 3.042 c
+46.886 3.032 47.092 2.947 47.239 2.793 c
+47.386 2.635 47.445 2.411 47.415 2.117 c
+47.18 0.647 l
+47.158 0.548 47.151 0.449 47.151 0.353 c
+47.166 0.044 l
+47.166 0 l
+h
+46.092 0.382 m
+46.335 0.382 46.541 0.5 46.71 0.735 c
+46.842 1.44 l
+46.622 1.455 l
+46.434 1.455 46.269 1.419 46.122 1.353 c
+45.975 1.282 45.872 1.183 45.813 1.058 c
+45.755 0.941 45.732 0.808 45.755 0.661 c
+45.773 0.474 45.886 0.382 46.092 0.382 c
+48.863 1.617 m
+48.922 2.047 49.061 2.396 49.289 2.66 c
+49.524 2.925 49.819 3.05 50.172 3.042 c
+50.395 3.032 50.584 2.961 50.73 2.837 c
+50.877 2.72 50.98 2.55 51.039 2.337 c
+51.105 2.12 51.127 1.885 51.097 1.631 c
+51.068 1.353 l
+50.998 0.919 50.848 0.573 50.613 0.309 c
+50.385 0.052 50.098 -0.066 49.745 -0.058 c
+49.518 -0.048 49.333 0.015 49.187 0.133 c
+49.04 0.257 48.93 0.426 48.863 0.632 c
+48.805 0.845 48.79 1.087 48.819 1.353 c
+h
+49.289 1.147 m
+49.279 0.9 49.312 0.709 49.393 0.573 c
+49.481 0.434 49.605 0.36 49.775 0.353 c
+49.981 0.341 50.15 0.415 50.289 0.573 c
+50.436 0.738 50.532 0.985 50.584 1.309 c
+50.627 1.631 l
+50.642 1.837 l
+50.642 2.08 50.598 2.271 50.509 2.411 c
+50.428 2.547 50.308 2.616 50.142 2.616 c
+49.925 2.624 49.745 2.535 49.599 2.352 c
+49.458 2.165 49.37 1.903 49.333 1.573 c
+49.289 1.294 l
+h
+53.836 0.779 m
+53.865 0.956 53.765 1.103 53.541 1.22 c
+53.173 1.411 l
+52.986 1.517 52.855 1.631 52.777 1.749 c
+52.696 1.866 52.663 2.007 52.674 2.176 c
+52.681 2.418 52.78 2.624 52.968 2.793 c
+53.163 2.959 53.402 3.042 53.688 3.042 c
+53.953 3.032 54.158 2.944 54.306 2.778 c
+54.46 2.609 54.53 2.396 54.511 2.132 c
+54.041 2.132 l
+54.048 2.278 54.015 2.396 53.938 2.484 c
+53.869 2.572 53.776 2.616 53.659 2.616 c
+53.512 2.616 53.394 2.576 53.306 2.499 c
+53.218 2.418 53.163 2.315 53.144 2.19 c
+53.115 2.043 53.181 1.918 53.35 1.823 c
+53.821 1.588 l
+54.162 1.389 54.324 1.135 54.306 0.823 c
+54.283 0.548 54.177 0.327 53.982 0.162 c
+53.784 0.004 53.545 -0.066 53.262 -0.058 c
+52.986 -0.048 52.762 0.037 52.585 0.206 c
+52.417 0.382 52.34 0.61 52.35 0.897 c
+52.836 0.897 l
+52.824 0.721 52.857 0.588 52.938 0.5 c
+53.027 0.412 53.137 0.368 53.277 0.368 c
+53.431 0.368 53.56 0.405 53.659 0.485 c
+53.755 0.563 53.813 0.661 53.836 0.779 c
+56.4 1.132 m
+55.974 1.132 l
+56.429 4.013 l
+56.93 4.013 l
+h
+55.768 0.25 m
+55.768 0.327 55.791 0.397 55.841 0.455 c
+55.889 0.515 55.959 0.548 56.047 0.559 c
+56.125 0.559 56.188 0.53 56.238 0.47 c
+56.286 0.412 56.312 0.341 56.312 0.264 c
+56.312 0.183 56.286 0.118 56.238 0.059 c
+56.188 0 56.121 -0.029 56.032 -0.029 c
+55.952 -0.037 55.889 -0.019 55.841 0.029 c
+55.791 0.088 55.768 0.162 55.768 0.25 c
+f
+Q
+q 1 0 0 1 206.7387 88.644 cm
+0 0 m
+-0.47 -2.749 l
+-0.529 -3.171 -0.687 -3.499 -0.941 -3.734 c
+-1.186 -3.969 -1.514 -4.079 -1.926 -4.072 c
+-2.319 -4.061 -2.612 -3.94 -2.807 -3.705 c
+-3.006 -3.469 -3.083 -3.153 -3.042 -2.749 c
+-2.572 0 l
+-1.778 0 l
+-2.234 -2.764 l
+-2.248 -2.999 l
+-2.248 -3.256 -2.123 -3.389 -1.866 -3.396 c
+-1.691 -3.406 -1.554 -3.363 -1.455 -3.263 c
+-1.359 -3.157 -1.29 -2.992 -1.249 -2.764 c
+-0.793 0 l
+h
+2.124 -3.19 m
+2.143 -3.065 2.04 -2.951 1.816 -2.852 c
+1.599 -2.756 1.437 -2.66 1.33 -2.573 c
+1.22 -2.477 1.139 -2.374 1.081 -2.264 c
+1.029 -2.157 1.011 -2.036 1.022 -1.897 c
+1.029 -1.632 1.139 -1.411 1.345 -1.235 c
+1.559 -1.058 1.819 -0.971 2.124 -0.971 c
+2.419 -0.981 2.646 -1.073 2.816 -1.249 c
+2.992 -1.419 3.08 -1.64 3.08 -1.912 c
+2.315 -1.912 l
+2.315 -1.786 2.294 -1.698 2.257 -1.646 c
+2.216 -1.588 2.157 -1.559 2.08 -1.559 c
+1.992 -1.559 1.912 -1.588 1.845 -1.646 c
+1.786 -1.706 1.75 -1.779 1.742 -1.867 c
+1.713 -1.985 1.801 -2.095 2.007 -2.19 c
+2.22 -2.278 2.374 -2.352 2.462 -2.411 c
+2.735 -2.598 2.863 -2.849 2.845 -3.161 c
+2.833 -3.348 2.775 -3.51 2.668 -3.645 c
+2.569 -3.786 2.433 -3.892 2.257 -3.969 c
+2.087 -4.035 1.904 -4.072 1.698 -4.072 c
+1.405 -4.061 1.162 -3.969 0.977 -3.793 c
+0.801 -3.609 0.713 -3.373 0.713 -3.088 c
+1.448 -3.088 l
+1.437 -3.234 1.455 -3.344 1.507 -3.41 c
+1.565 -3.469 1.646 -3.499 1.756 -3.499 c
+1.845 -3.499 1.922 -3.477 1.992 -3.425 c
+2.058 -3.366 2.103 -3.289 2.124 -3.19 c
+5.281 -4.072 m
+5.035 -4.072 4.829 -4.013 4.663 -3.896 c
+4.495 -3.778 4.373 -3.616 4.296 -3.41 c
+4.227 -3.198 4.208 -2.955 4.237 -2.691 c
+4.252 -2.484 l
+4.318 -1.995 4.472 -1.617 4.707 -1.353 c
+4.943 -1.088 5.245 -0.963 5.619 -0.971 c
+5.891 -0.981 6.108 -1.07 6.265 -1.235 c
+6.421 -1.393 6.508 -1.617 6.531 -1.912 c
+6.548 -2.087 6.548 -2.261 6.531 -2.425 c
+6.471 -2.778 l
+4.987 -2.778 l
+4.976 -2.859 4.972 -2.936 4.972 -3.013 c
+4.991 -3.278 5.123 -3.41 5.369 -3.41 c
+5.594 -3.421 5.814 -3.337 6.03 -3.161 c
+6.295 -3.631 l
+6.185 -3.77 6.038 -3.877 5.854 -3.954 c
+5.677 -4.031 5.486 -4.072 5.281 -4.072 c
+5.546 -1.617 m
+5.328 -1.61 5.178 -1.75 5.089 -2.043 c
+5.031 -2.234 l
+5.795 -2.234 l
+5.814 -2.139 5.825 -2.055 5.825 -1.985 c
+5.833 -1.75 5.74 -1.628 5.546 -1.617 c
+12.495 -3.558 m
+12.347 -3.726 12.149 -3.851 11.907 -3.94 c
+11.672 -4.028 11.422 -4.072 11.157 -4.072 c
+10.911 -4.072 10.701 -4.017 10.525 -3.911 c
+10.348 -3.803 10.209 -3.653 10.113 -3.454 c
+10.014 -3.26 9.966 -3.036 9.966 -2.778 c
+9.955 -2.643 9.959 -2.5 9.981 -2.352 c
+10.084 -1.691 l
+10.161 -1.132 10.338 -0.702 10.613 -0.397 c
+10.896 -0.085 11.263 0.066 11.715 0.058 c
+12.098 0.047 12.384 -0.071 12.582 -0.294 c
+12.777 -0.522 12.877 -0.849 12.877 -1.279 c
+12.112 -1.279 l
+12.098 -1.058 l
+12.075 -0.776 11.936 -0.628 11.672 -0.618 c
+11.296 -0.599 11.047 -0.849 10.922 -1.367 c
+10.892 -1.573 l
+10.774 -2.352 l
+10.753 -2.529 10.745 -2.675 10.745 -2.793 c
+10.753 -2.999 10.797 -3.153 10.878 -3.248 c
+10.966 -3.337 11.087 -3.389 11.245 -3.396 c
+11.381 -3.396 11.539 -3.348 11.715 -3.248 c
+11.863 -2.514 l
+11.304 -2.514 l
+11.422 -1.897 l
+12.759 -1.897 l
+h
+14.56 -4.013 m
+13.81 -4.013 l
+14.325 -1.029 l
+15.089 -1.029 l
+h
+14.427 -0.279 m
+14.427 -0.154 14.464 -0.052 14.545 0.029 c
+14.622 0.118 14.722 0.162 14.839 0.162 c
+14.946 0.162 15.038 0.121 15.119 0.044 c
+15.206 -0.037 15.25 -0.133 15.25 -0.25 c
+15.25 -0.379 15.206 -0.482 15.119 -0.559 c
+15.038 -0.64 14.942 -0.676 14.824 -0.676 c
+14.707 -0.676 14.608 -0.643 14.531 -0.574 c
+14.46 -0.497 14.427 -0.397 14.427 -0.279 c
+17.581 -0.294 m
+17.463 -1.029 l
+17.845 -1.029 l
+17.742 -1.617 l
+17.359 -1.617 l
+17.095 -3.117 l
+17.095 -3.205 l
+17.084 -3.333 17.132 -3.396 17.242 -3.396 c
+17.272 -3.396 17.334 -3.392 17.434 -3.381 c
+17.359 -3.998 l
+17.249 -4.046 17.118 -4.072 16.963 -4.072 c
+16.746 -4.061 16.581 -3.98 16.463 -3.822 c
+16.353 -3.668 16.309 -3.454 16.331 -3.19 c
+16.596 -1.617 l
+16.258 -1.617 l
+16.36 -1.029 l
+16.698 -1.029 l
+16.816 -0.294 l
+h
+19.624 -2.778 m
+18.992 -2.778 l
+19.374 0 l
+20.182 0 l
+h
+18.741 -3.645 m
+18.741 -3.521 18.778 -3.418 18.859 -3.337 c
+18.936 -3.248 19.036 -3.205 19.153 -3.205 c
+19.271 -3.205 19.366 -3.246 19.447 -3.323 c
+19.524 -3.404 19.565 -3.499 19.565 -3.616 c
+19.565 -3.745 19.524 -3.851 19.447 -3.94 c
+19.366 -4.017 19.271 -4.057 19.153 -4.057 c
+19.025 -4.057 18.922 -4.017 18.845 -3.94 c
+18.774 -3.863 18.741 -3.763 18.741 -3.645 c
+f
+Q
+0.793 0.801 0.129 0.016 K
+0.8 w
+q 1 0 0 1 534.418 129.4519 cm
+0 0 m
+-0.008 35.572 l
+6.464 35.572 l
+6.471 0 l
+3.23 -3.564 l
+0 0 l
+h
+S
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 537.5488 161.6247 cm
+0 0 m
+1.675 -0.264 l
+1.675 -1.014 l
+-1.309 -0.397 l
+-1.309 0.249 l
+0.411 0.676 l
+-1.309 1.087 l
+-1.309 1.749 l
+1.675 2.366 l
+1.675 1.617 l
+0 1.352 l
+1.675 0.955 l
+1.675 0.397 l
+h
+0.279 -1.07 m
+0.727 -1.07 1.08 -1.176 1.338 -1.393 c
+1.602 -1.606 1.735 -1.9 1.735 -2.275 c
+1.735 -2.657 1.602 -2.951 1.338 -3.157 c
+1.08 -3.37 0.727 -3.48 0.279 -3.48 c
+0.088 -3.48 l
+-0.375 -3.48 -0.732 -3.37 -0.985 -3.157 c
+-1.243 -2.951 -1.367 -2.657 -1.367 -2.275 c
+-1.367 -1.893 -1.243 -1.592 -0.985 -1.378 c
+-0.721 -1.172 -0.364 -1.07 0.088 -1.07 c
+h
+0.088 -1.849 m
+-0.453 -1.849 -0.721 -1.988 -0.721 -2.275 c
+-0.721 -2.539 -0.497 -2.679 -0.044 -2.701 c
+0.279 -2.716 l
+0.551 -2.716 0.754 -2.675 0.881 -2.598 c
+1.018 -2.517 1.088 -2.411 1.088 -2.275 c
+1.088 -2.146 1.018 -2.043 0.881 -1.966 c
+0.754 -1.885 0.551 -1.849 0.279 -1.849 c
+h
+0.926 -5.251 m
+0.941 -5.002 l
+0.941 -4.785 0.845 -4.638 0.661 -4.561 c
+-1.309 -4.561 l
+-1.309 -3.782 l
+1.675 -3.782 l
+1.675 -4.516 l
+1.352 -4.546 l
+1.606 -4.663 1.735 -4.829 1.735 -5.045 c
+1.735 -5.134 1.72 -5.207 1.69 -5.266 c
+h
+-0.162 -6.531 m
+-0.397 -6.31 l
+-1.309 -6.31 l
+-1.309 -5.531 l
+2.925 -5.531 l
+2.925 -6.31 l
+0.632 -6.31 l
+0.779 -6.413 l
+1.675 -6.957 l
+1.675 -7.882 l
+0.44 -7.015 l
+-1.309 -7.971 l
+-1.309 -7.074 l
+h
+-1.309 -8.096 2.984 -0.779 re
+-1.309 -8.875 m
+2.44 -8.052 m
+2.564 -8.052 2.668 -8.088 2.749 -8.169 c
+2.826 -8.247 2.866 -8.349 2.866 -8.478 c
+2.866 -8.603 2.826 -8.706 2.749 -8.787 c
+2.668 -8.864 2.564 -8.904 2.44 -8.904 c
+2.322 -8.904 2.223 -8.864 2.146 -8.787 c
+2.065 -8.717 2.028 -8.613 2.028 -8.478 c
+2.028 -8.349 2.065 -8.247 2.146 -8.169 c
+2.223 -8.088 2.322 -8.052 2.44 -8.052 c
+1.675 -10.099 m
+1.381 -10.113 l
+1.616 -10.29 1.735 -10.517 1.735 -10.804 c
+1.735 -11.322 1.371 -11.587 0.646 -11.597 c
+-1.309 -11.597 l
+-1.309 -10.819 l
+0.588 -10.819 l
+0.764 -10.819 0.885 -10.793 0.955 -10.745 c
+1.032 -10.693 1.072 -10.606 1.072 -10.481 c
+1.072 -10.334 0.999 -10.219 0.852 -10.142 c
+-1.309 -10.142 l
+-1.309 -9.363 l
+1.675 -9.363 l
+h
+0.279 -11.884 m
+0.768 -11.884 1.132 -11.973 1.367 -12.149 c
+1.61 -12.326 1.735 -12.568 1.735 -12.884 c
+1.735 -13.156 1.624 -13.369 1.411 -13.516 c
+1.675 -13.546 l
+1.675 -14.251 l
+-1.309 -14.251 l
+-1.69 -14.251 -1.977 -14.14 -2.176 -13.928 c
+-2.382 -13.71 -2.484 -13.406 -2.484 -13.016 c
+-2.484 -12.847 -2.448 -12.671 -2.382 -12.487 c
+-2.323 -12.311 -2.238 -12.179 -2.132 -12.09 c
+-1.602 -12.355 l
+-1.669 -12.432 -1.727 -12.532 -1.779 -12.649 c
+-1.827 -12.767 -1.852 -12.873 -1.852 -12.972 c
+-1.852 -13.149 -1.808 -13.274 -1.72 -13.355 c
+-1.639 -13.432 -1.507 -13.472 -1.323 -13.472 c
+-1.073 -13.472 l
+-1.272 -13.325 -1.367 -13.126 -1.367 -12.884 c
+-1.367 -12.568 -1.246 -12.326 -1 -12.149 c
+-0.746 -11.973 -0.393 -11.884 0.058 -11.884 c
+h
+0.073 -12.663 m
+-0.202 -12.663 -0.405 -12.696 -0.53 -12.767 c
+-0.647 -12.844 -0.706 -12.962 -0.706 -13.12 c
+-0.706 -13.274 -0.655 -13.391 -0.544 -13.472 c
+0.881 -13.472 l
+1.007 -13.391 1.072 -13.274 1.072 -13.12 c
+1.072 -12.962 1.007 -12.844 0.881 -12.767 c
+0.754 -12.696 0.551 -12.663 0.279 -12.663 c
+h
+0.088 -14.685 0.646 -1.352 re
+0.088 -16.037 m
+-0.206 -17.525 m
+1.675 -17.907 l
+1.675 -18.716 l
+-1.309 -17.893 l
+-1.309 -17.157 l
+1.675 -16.334 l
+1.675 -17.143 l
+h
+-1.367 -20.083 m
+-1.367 -19.678 -1.249 -19.366 -1.014 -19.142 c
+-0.772 -18.925 -0.426 -18.819 0.014 -18.819 c
+0.264 -18.819 l
+0.735 -18.819 1.095 -18.921 1.352 -19.127 c
+1.606 -19.333 1.735 -19.627 1.735 -20.01 c
+1.735 -20.38 1.61 -20.66 1.367 -20.847 c
+1.132 -21.042 0.779 -21.141 0.309 -21.141 c
+-0.073 -21.141 l
+-0.073 -19.597 l
+-0.302 -19.605 -0.467 -19.649 -0.574 -19.73 c
+-0.673 -19.819 -0.721 -19.954 -0.721 -20.141 c
+-0.721 -20.395 -0.628 -20.612 -0.441 -20.788 c
+-0.927 -21.097 l
+-1.055 -20.998 -1.162 -20.854 -1.249 -20.671 c
+-1.326 -20.494 -1.367 -20.296 -1.367 -20.083 c
+0.47 -19.597 m
+0.47 -20.376 l
+0.544 -20.376 l
+0.72 -20.376 0.852 -20.347 0.941 -20.289 c
+1.036 -20.23 1.088 -20.131 1.088 -19.994 c
+1.088 -19.866 1.036 -19.767 0.941 -19.701 c
+0.841 -19.642 0.683 -19.605 0.47 -19.597 c
+0.926 -22.868 m
+0.941 -22.618 l
+0.941 -22.402 0.845 -22.254 0.661 -22.177 c
+-1.309 -22.177 l
+-1.309 -21.398 l
+1.675 -21.398 l
+1.675 -22.134 l
+1.352 -22.163 l
+1.606 -22.28 1.735 -22.446 1.735 -22.662 c
+1.735 -22.751 1.72 -22.824 1.69 -22.883 c
+h
+-0.515 -24.471 m
+-0.449 -24.471 -0.382 -24.434 -0.324 -24.368 c
+-0.265 -24.309 -0.191 -24.169 -0.103 -23.956 c
+0.033 -23.632 0.168 -23.412 0.309 -23.295 c
+0.444 -23.177 0.617 -23.118 0.823 -23.118 c
+1.088 -23.118 1.301 -23.21 1.469 -23.397 c
+1.646 -23.582 1.735 -23.831 1.735 -24.147 c
+1.735 -24.471 1.646 -24.727 1.469 -24.926 c
+1.301 -25.121 1.076 -25.22 0.794 -25.22 c
+0.794 -24.441 l
+1.036 -24.441 1.161 -24.338 1.161 -24.133 c
+1.161 -24.052 1.132 -23.985 1.072 -23.927 c
+1.022 -23.875 0.955 -23.853 0.867 -23.853 c
+0.797 -23.853 0.739 -23.883 0.69 -23.941 c
+0.639 -24 0.565 -24.136 0.47 -24.353 c
+0.353 -24.677 0.22 -24.9 0.073 -25.029 c
+-0.067 -25.165 -0.25 -25.234 -0.485 -25.234 c
+-0.75 -25.234 -0.967 -25.132 -1.132 -24.926 c
+-1.29 -24.727 -1.367 -24.471 -1.367 -24.147 c
+-1.367 -23.919 -1.323 -23.725 -1.235 -23.559 c
+-1.147 -23.39 -1.029 -23.258 -0.882 -23.162 c
+-0.728 -23.074 -0.559 -23.03 -0.382 -23.03 c
+-0.382 -23.765 l
+-0.522 -23.772 -0.625 -23.809 -0.691 -23.868 c
+-0.761 -23.927 -0.794 -24.022 -0.794 -24.162 c
+-0.794 -24.368 -0.702 -24.471 -0.515 -24.471 c
+-1.309 -25.587 2.984 -0.78 re
+-1.309 -26.367 m
+2.44 -25.544 m
+2.564 -25.544 2.668 -25.581 2.749 -25.661 c
+2.826 -25.739 2.866 -25.841 2.866 -25.97 c
+2.866 -26.094 2.826 -26.198 2.749 -26.279 c
+2.668 -26.356 2.564 -26.396 2.44 -26.396 c
+2.322 -26.396 2.223 -26.356 2.146 -26.279 c
+2.065 -26.209 2.028 -26.106 2.028 -25.97 c
+2.028 -25.841 2.065 -25.739 2.146 -25.661 c
+2.223 -25.581 2.322 -25.544 2.44 -25.544 c
+0.279 -26.782 m
+0.727 -26.782 1.08 -26.888 1.338 -27.106 c
+1.602 -27.318 1.735 -27.613 1.735 -27.987 c
+1.735 -28.369 1.602 -28.663 1.338 -28.869 c
+1.08 -29.082 0.727 -29.192 0.279 -29.192 c
+0.088 -29.192 l
+-0.375 -29.192 -0.732 -29.082 -0.985 -28.869 c
+-1.243 -28.663 -1.367 -28.369 -1.367 -27.987 c
+-1.367 -27.605 -1.243 -27.304 -0.985 -27.09 c
+-0.721 -26.884 -0.364 -26.782 0.088 -26.782 c
+h
+0.088 -27.561 m
+-0.453 -27.561 -0.721 -27.701 -0.721 -27.987 c
+-0.721 -28.251 -0.497 -28.392 -0.044 -28.413 c
+0.279 -28.428 l
+0.551 -28.428 0.754 -28.388 0.881 -28.311 c
+1.018 -28.23 1.088 -28.123 1.088 -27.987 c
+1.088 -27.858 1.018 -27.756 0.881 -27.678 c
+0.754 -27.598 0.551 -27.561 0.279 -27.561 c
+h
+1.675 -30.214 m
+1.381 -30.229 l
+1.616 -30.406 1.735 -30.633 1.735 -30.919 c
+1.735 -31.438 1.371 -31.702 0.646 -31.713 c
+-1.309 -31.713 l
+-1.309 -30.934 l
+0.588 -30.934 l
+0.764 -30.934 0.885 -30.909 0.955 -30.861 c
+1.032 -30.809 1.072 -30.721 1.072 -30.597 c
+1.072 -30.449 0.999 -30.335 0.852 -30.258 c
+-1.309 -30.258 l
+-1.309 -29.479 l
+1.675 -29.479 l
+h
+f
+Q
+q 1 0 0 1 442.9198 145.1834 cm
+0 0 m
+-1.058 0 l
+-1.058 -3.572 l
+-1.558 -3.572 l
+-1.558 0 l
+-2.616 0 l
+-2.616 0.441 l
+0 0.441 l
+h
+0.819 -0.897 m
+1.003 -0.654 1.238 -0.529 1.525 -0.529 c
+2.055 -0.529 2.323 -0.881 2.333 -1.587 c
+2.333 -3.572 l
+1.849 -3.572 l
+1.849 -1.617 l
+1.849 -1.382 1.808 -1.216 1.731 -1.117 c
+1.65 -1.022 1.532 -0.97 1.378 -0.97 c
+1.261 -0.97 1.151 -1.01 1.055 -1.087 c
+0.956 -1.168 0.879 -1.275 0.819 -1.411 c
+0.819 -3.572 l
+0.334 -3.572 l
+0.334 0.661 l
+0.819 0.661 l
+h
+3.406 -3.572 -0.5 2.984 re
+3.436 0.206 m
+3.436 0.118 3.41 0.044 3.362 -0.014 c
+3.322 -0.066 3.252 -0.088 3.156 -0.088 c
+3.069 -0.088 2.998 -0.066 2.951 -0.014 c
+2.911 0.044 2.892 0.11 2.892 0.191 c
+2.892 0.279 2.911 0.353 2.951 0.412 c
+2.998 0.47 3.069 0.5 3.156 0.5 c
+3.252 0.5 3.322 0.47 3.362 0.412 c
+3.41 0.353 3.436 0.283 3.436 0.206 c
+5.523 -2.807 m
+5.523 -2.701 5.483 -2.612 5.405 -2.543 c
+5.325 -2.466 5.174 -2.377 4.95 -2.278 c
+4.685 -2.171 4.498 -2.08 4.391 -1.999 c
+4.281 -1.922 4.204 -1.834 4.156 -1.735 c
+4.104 -1.639 4.083 -1.521 4.083 -1.382 c
+4.083 -1.139 4.171 -0.937 4.347 -0.779 c
+4.523 -0.613 4.748 -0.529 5.024 -0.529 c
+5.317 -0.529 5.552 -0.617 5.729 -0.794 c
+5.905 -0.962 5.993 -1.176 5.993 -1.44 c
+5.508 -1.44 l
+5.508 -1.304 5.457 -1.19 5.361 -1.103 c
+5.273 -1.007 5.159 -0.955 5.024 -0.955 c
+4.877 -0.955 4.762 -0.995 4.685 -1.072 c
+4.604 -1.143 4.567 -1.242 4.567 -1.367 c
+4.567 -1.466 4.597 -1.543 4.656 -1.602 c
+4.715 -1.66 4.854 -1.741 5.082 -1.837 c
+5.442 -1.984 5.689 -2.127 5.818 -2.263 c
+5.953 -2.392 6.023 -2.564 6.023 -2.778 c
+6.023 -3.035 5.928 -3.241 5.743 -3.395 c
+5.567 -3.553 5.332 -3.63 5.038 -3.63 c
+4.722 -3.63 4.469 -3.542 4.274 -3.366 c
+4.087 -3.183 3.994 -2.95 3.994 -2.675 c
+4.48 -2.675 l
+4.486 -2.844 4.538 -2.977 4.627 -3.072 c
+4.722 -3.16 4.862 -3.204 5.038 -3.204 c
+5.192 -3.204 5.31 -3.171 5.39 -3.102 c
+5.479 -3.035 5.523 -2.936 5.523 -2.807 c
+8.213 -3.572 -0.5 2.984 re
+8.243 0.206 m
+8.243 0.118 8.216 0.044 8.169 -0.014 c
+8.129 -0.066 8.058 -0.088 7.963 -0.088 c
+7.875 -0.088 7.805 -0.066 7.757 -0.014 c
+7.717 0.044 7.699 0.11 7.699 0.191 c
+7.699 0.279 7.717 0.353 7.757 0.412 c
+7.805 0.47 7.875 0.5 7.963 0.5 c
+8.058 0.5 8.129 0.47 8.169 0.412 c
+8.216 0.353 8.243 0.283 8.243 0.206 c
+10.326 -2.807 m
+10.326 -2.701 10.286 -2.612 10.208 -2.543 c
+10.128 -2.466 9.977 -2.377 9.753 -2.278 c
+9.488 -2.171 9.301 -2.08 9.194 -1.999 c
+9.084 -1.922 9.007 -1.834 8.959 -1.735 c
+8.908 -1.639 8.885 -1.521 8.885 -1.382 c
+8.885 -1.139 8.974 -0.937 9.15 -0.779 c
+9.326 -0.613 9.55 -0.529 9.826 -0.529 c
+10.12 -0.529 10.356 -0.617 10.532 -0.794 c
+10.708 -0.962 10.796 -1.176 10.796 -1.44 c
+10.311 -1.44 l
+10.311 -1.304 10.26 -1.19 10.165 -1.103 c
+10.076 -1.007 9.962 -0.955 9.826 -0.955 c
+9.679 -0.955 9.565 -0.995 9.488 -1.072 c
+9.407 -1.143 9.371 -1.242 9.371 -1.367 c
+9.371 -1.466 9.4 -1.543 9.459 -1.602 c
+9.517 -1.66 9.658 -1.741 9.885 -1.837 c
+10.246 -1.984 10.491 -2.127 10.62 -2.263 c
+10.756 -2.392 10.826 -2.564 10.826 -2.778 c
+10.826 -3.035 10.73 -3.241 10.547 -3.395 c
+10.37 -3.553 10.135 -3.63 9.841 -3.63 c
+9.525 -3.63 9.271 -3.542 9.076 -3.366 c
+8.889 -3.183 8.797 -2.95 8.797 -2.675 c
+9.282 -2.675 l
+9.29 -2.844 9.342 -2.977 9.429 -3.072 c
+9.525 -3.16 9.664 -3.204 9.841 -3.204 c
+9.995 -3.204 10.113 -3.171 10.194 -3.102 c
+10.282 -3.035 10.326 -2.936 10.326 -2.807 c
+14.015 -3.572 m
+13.986 -3.505 13.964 -3.395 13.957 -3.248 c
+13.78 -3.505 13.56 -3.63 13.295 -3.63 c
+13.02 -3.63 12.803 -3.557 12.648 -3.41 c
+12.501 -3.256 12.428 -3.039 12.428 -2.763 c
+12.428 -2.462 12.531 -2.219 12.737 -2.043 c
+12.943 -1.859 13.225 -1.764 13.589 -1.764 c
+13.942 -1.764 l
+13.942 -1.44 l
+13.942 -1.264 13.901 -1.143 13.824 -1.072 c
+13.743 -0.995 13.626 -0.955 13.471 -0.955 c
+13.325 -0.955 13.2 -0.999 13.104 -1.087 c
+13.016 -1.176 12.972 -1.286 12.972 -1.411 c
+12.486 -1.411 l
+12.486 -1.264 12.531 -1.124 12.619 -0.985 c
+12.707 -0.837 12.825 -0.727 12.972 -0.646 c
+13.126 -0.569 13.299 -0.529 13.486 -0.529 c
+13.799 -0.529 14.034 -0.61 14.192 -0.764 c
+14.346 -0.912 14.427 -1.132 14.427 -1.425 c
+14.427 -2.925 l
+14.435 -3.16 14.471 -3.362 14.53 -3.528 c
+14.53 -3.572 l
+h
+13.369 -3.189 m
+13.486 -3.189 13.596 -3.156 13.707 -3.087 c
+13.814 -3.021 13.891 -2.936 13.942 -2.836 c
+13.942 -2.131 l
+13.677 -2.131 l
+13.442 -2.131 13.255 -2.183 13.119 -2.278 c
+12.99 -2.377 12.928 -2.52 12.928 -2.705 c
+12.928 -2.873 12.957 -2.994 13.016 -3.072 c
+13.082 -3.152 13.2 -3.189 13.369 -3.189 c
+16.845 0.133 m
+16.845 -0.588 l
+17.301 -0.588 l
+17.301 -0.985 l
+16.845 -0.985 l
+16.845 -2.836 l
+16.845 -2.954 16.864 -3.042 16.904 -3.102 c
+16.941 -3.16 17.01 -3.189 17.109 -3.189 c
+17.168 -3.189 17.231 -3.183 17.301 -3.16 c
+17.301 -3.572 l
+17.184 -3.609 17.069 -3.63 16.962 -3.63 c
+16.764 -3.63 16.613 -3.564 16.507 -3.424 c
+16.407 -3.289 16.36 -3.094 16.36 -2.836 c
+16.36 -0.985 l
+15.904 -0.985 l
+15.904 -0.588 l
+16.36 -0.588 l
+16.36 0.133 l
+h
+19.296 -3.572 m
+19.266 -3.505 19.245 -3.395 19.237 -3.248 c
+19.061 -3.505 18.84 -3.63 18.576 -3.63 c
+18.3 -3.63 18.084 -3.557 17.929 -3.41 c
+17.782 -3.256 17.708 -3.039 17.708 -2.763 c
+17.708 -2.462 17.812 -2.219 18.017 -2.043 c
+18.223 -1.859 18.506 -1.764 18.869 -1.764 c
+19.223 -1.764 l
+19.223 -1.44 l
+19.223 -1.264 19.183 -1.143 19.105 -1.072 c
+19.025 -0.995 18.907 -0.955 18.753 -0.955 c
+18.605 -0.955 18.48 -0.999 18.385 -1.087 c
+18.296 -1.176 18.252 -1.286 18.252 -1.411 c
+17.768 -1.411 l
+17.768 -1.264 17.812 -1.124 17.899 -0.985 c
+17.988 -0.837 18.105 -0.727 18.252 -0.646 c
+18.407 -0.569 18.58 -0.529 18.767 -0.529 c
+19.079 -0.529 19.314 -0.61 19.472 -0.764 c
+19.627 -0.912 19.708 -1.132 19.708 -1.425 c
+19.708 -2.925 l
+19.715 -3.16 19.752 -3.362 19.81 -3.528 c
+19.81 -3.572 l
+h
+18.649 -3.189 m
+18.767 -3.189 18.877 -3.156 18.988 -3.087 c
+19.094 -3.021 19.171 -2.936 19.223 -2.836 c
+19.223 -2.131 l
+18.958 -2.131 l
+18.723 -2.131 18.535 -2.183 18.399 -2.278 c
+18.271 -2.377 18.208 -2.52 18.208 -2.705 c
+18.208 -2.873 18.238 -2.994 18.296 -3.072 c
+18.362 -3.152 18.48 -3.189 18.649 -3.189 c
+20.185 -1.94 m
+20.185 -1.481 20.266 -1.132 20.436 -0.897 c
+20.612 -0.654 20.862 -0.529 21.185 -0.529 c
+21.486 -0.529 21.718 -0.661 21.876 -0.926 c
+21.905 -0.588 l
+22.346 -0.588 l
+22.346 -3.601 l
+22.346 -3.972 22.247 -4.255 22.052 -4.453 c
+21.865 -4.648 21.604 -4.748 21.273 -4.748 c
+21.126 -4.748 20.957 -4.707 20.773 -4.63 c
+20.586 -4.56 20.45 -4.472 20.361 -4.365 c
+20.553 -4.027 l
+20.758 -4.233 20.983 -4.336 21.229 -4.336 c
+21.629 -4.336 21.836 -4.108 21.847 -3.659 c
+21.847 -3.278 l
+21.689 -3.513 21.468 -3.63 21.185 -3.63 c
+20.869 -3.63 20.627 -3.513 20.45 -3.278 c
+20.28 -3.042 20.193 -2.712 20.185 -2.278 c
+h
+20.671 -2.219 m
+20.671 -2.554 20.718 -2.8 20.818 -2.954 c
+20.913 -3.112 21.074 -3.189 21.302 -3.189 c
+21.545 -3.189 21.729 -3.068 21.847 -2.822 c
+21.847 -1.338 l
+21.729 -1.095 21.552 -0.97 21.317 -0.97 c
+21.089 -0.97 20.928 -1.051 20.832 -1.205 c
+20.733 -1.363 20.677 -1.602 20.671 -1.926 c
+h
+22.908 -3.307 m
+22.908 -3.219 22.931 -3.146 22.982 -3.087 c
+23.041 -3.028 23.118 -2.998 23.217 -2.998 c
+23.324 -2.998 23.401 -3.028 23.453 -3.087 c
+23.511 -3.146 23.54 -3.219 23.54 -3.307 c
+23.54 -3.388 23.511 -3.454 23.453 -3.513 c
+23.401 -3.572 23.324 -3.601 23.217 -3.601 c
+23.118 -3.601 23.041 -3.572 22.982 -3.513 c
+22.931 -3.454 22.908 -3.388 22.908 -3.307 c
+26.061 -3.572 -0.5 4.013 re
+27.421 0.133 m
+27.421 -0.588 l
+27.877 -0.588 l
+27.877 -0.985 l
+27.421 -0.985 l
+27.421 -2.836 l
+27.421 -2.954 27.439 -3.042 27.48 -3.102 c
+27.517 -3.16 27.586 -3.189 27.686 -3.189 c
+27.744 -3.189 27.806 -3.183 27.877 -3.16 c
+27.877 -3.572 l
+27.759 -3.609 27.646 -3.63 27.538 -3.63 c
+27.34 -3.63 27.189 -3.564 27.083 -3.424 c
+26.984 -3.289 26.936 -3.094 26.936 -2.836 c
+26.936 -0.985 l
+26.48 -0.985 l
+26.48 -0.588 l
+26.936 -0.588 l
+26.936 0.133 l
+h
+30.078 -3.572 -0.5 4.233 re
+30.647 -1.94 m
+30.647 -1.51 30.75 -1.168 30.956 -0.912 c
+31.169 -0.658 31.449 -0.529 31.794 -0.529 c
+32.136 -0.529 32.411 -0.658 32.617 -0.912 c
+32.83 -1.157 32.944 -1.492 32.955 -1.911 c
+32.955 -2.219 l
+32.955 -2.653 32.845 -2.994 32.631 -3.248 c
+32.426 -3.505 32.147 -3.63 31.794 -3.63 c
+31.449 -3.63 31.177 -3.509 30.971 -3.263 c
+30.765 -3.021 30.655 -2.686 30.647 -2.263 c
+h
+31.133 -2.219 m
+31.133 -2.535 31.191 -2.778 31.309 -2.954 c
+31.434 -3.123 31.596 -3.204 31.794 -3.204 c
+32.224 -3.204 32.448 -2.896 32.471 -2.278 c
+32.471 -1.94 l
+32.471 -1.639 32.404 -1.396 32.279 -1.22 c
+32.161 -1.043 32 -0.955 31.794 -0.955 c
+31.596 -0.955 31.434 -1.043 31.309 -1.22 c
+31.191 -1.396 31.133 -1.639 31.133 -1.94 c
+h
+33.294 -1.94 m
+33.294 -1.51 33.396 -1.168 33.602 -0.912 c
+33.815 -0.658 34.094 -0.529 34.44 -0.529 c
+34.782 -0.529 35.058 -0.658 35.263 -0.912 c
+35.476 -1.157 35.59 -1.492 35.601 -1.911 c
+35.601 -2.219 l
+35.601 -2.653 35.49 -2.994 35.278 -3.248 c
+35.072 -3.505 34.792 -3.63 34.44 -3.63 c
+34.094 -3.63 33.822 -3.509 33.616 -3.263 c
+33.411 -3.021 33.3 -2.686 33.294 -2.263 c
+h
+33.778 -2.219 m
+33.778 -2.535 33.837 -2.778 33.955 -2.954 c
+34.079 -3.123 34.241 -3.204 34.44 -3.204 c
+34.869 -3.204 35.094 -2.896 35.116 -2.278 c
+35.116 -1.94 l
+35.116 -1.639 35.05 -1.396 34.925 -1.22 c
+34.807 -1.043 34.646 -0.955 34.44 -0.955 c
+34.241 -0.955 34.079 -1.043 33.955 -1.22 c
+33.837 -1.396 33.778 -1.639 33.778 -1.94 c
+h
+36.788 -2.205 m
+36.523 -2.499 l
+36.523 -3.572 l
+36.038 -3.572 l
+36.038 0.661 l
+36.523 0.661 l
+36.523 -1.866 l
+37.449 -0.588 l
+38.038 -0.588 l
+37.097 -1.837 l
+38.17 -3.572 l
+37.597 -3.572 l
+h
+39.856 -2.807 m
+39.856 -2.701 39.816 -2.612 39.739 -2.543 c
+39.658 -2.466 39.507 -2.377 39.283 -2.278 c
+39.018 -2.171 38.831 -2.08 38.725 -1.999 c
+38.615 -1.922 38.537 -1.834 38.489 -1.735 c
+38.438 -1.639 38.416 -1.521 38.416 -1.382 c
+38.416 -1.139 38.504 -0.937 38.68 -0.779 c
+38.857 -0.613 39.081 -0.529 39.357 -0.529 c
+39.65 -0.529 39.885 -0.617 40.062 -0.794 c
+40.238 -0.962 40.327 -1.176 40.327 -1.44 c
+39.841 -1.44 l
+39.841 -1.304 39.79 -1.19 39.694 -1.103 c
+39.606 -1.007 39.492 -0.955 39.357 -0.955 c
+39.21 -0.955 39.095 -0.995 39.018 -1.072 c
+38.938 -1.143 38.901 -1.242 38.901 -1.367 c
+38.901 -1.466 38.931 -1.543 38.989 -1.602 c
+39.048 -1.66 39.187 -1.741 39.415 -1.837 c
+39.775 -1.984 40.022 -2.127 40.151 -2.263 c
+40.286 -2.392 40.356 -2.564 40.356 -2.778 c
+40.356 -3.035 40.261 -3.241 40.076 -3.395 c
+39.901 -3.553 39.665 -3.63 39.371 -3.63 c
+39.056 -3.63 38.802 -3.542 38.607 -3.366 c
+38.42 -3.183 38.328 -2.95 38.328 -2.675 c
+38.813 -2.675 l
+38.821 -2.844 38.871 -2.977 38.96 -3.072 c
+39.056 -3.16 39.195 -3.204 39.371 -3.204 c
+39.526 -3.204 39.644 -3.171 39.724 -3.102 c
+39.812 -3.035 39.856 -2.936 39.856 -2.807 c
+42.546 -3.572 -0.5 4.233 re
+43.752 -3.572 -0.5 2.984 re
+43.781 0.206 m
+43.781 0.118 43.756 0.044 43.708 -0.014 c
+43.667 -0.066 43.598 -0.088 43.502 -0.088 c
+43.413 -0.088 43.344 -0.066 43.296 -0.014 c
+43.255 0.044 43.237 0.11 43.237 0.191 c
+43.237 0.279 43.255 0.353 43.296 0.412 c
+43.344 0.47 43.413 0.5 43.502 0.5 c
+43.598 0.5 43.667 0.47 43.708 0.412 c
+43.756 0.353 43.781 0.283 43.781 0.206 c
+45.173 -2.205 m
+44.909 -2.499 l
+44.909 -3.572 l
+44.425 -3.572 l
+44.425 0.661 l
+44.909 0.661 l
+44.909 -1.866 l
+45.836 -0.588 l
+46.424 -0.588 l
+45.483 -1.837 l
+46.555 -3.572 l
+45.982 -3.572 l
+h
+47.808 -3.63 m
+47.434 -3.63 47.151 -3.524 46.956 -3.307 c
+46.758 -3.083 46.662 -2.755 46.662 -2.323 c
+46.662 -1.955 l
+46.662 -1.514 46.754 -1.168 46.941 -0.912 c
+47.136 -0.658 47.411 -0.529 47.764 -0.529 c
+48.107 -0.529 48.36 -0.643 48.529 -0.867 c
+48.705 -1.095 48.797 -1.44 48.808 -1.911 c
+48.808 -2.219 l
+47.147 -2.219 l
+47.147 -2.293 l
+47.147 -2.616 47.206 -2.851 47.324 -2.998 c
+47.441 -3.138 47.61 -3.204 47.838 -3.204 c
+47.985 -3.204 48.11 -3.183 48.22 -3.131 c
+48.327 -3.072 48.429 -2.984 48.529 -2.866 c
+48.778 -3.175 l
+48.573 -3.48 48.25 -3.63 47.808 -3.63 c
+47.764 -0.955 m
+47.559 -0.955 47.405 -1.025 47.309 -1.161 c
+47.21 -1.301 47.155 -1.514 47.147 -1.808 c
+48.323 -1.808 l
+48.323 -1.735 l
+48.301 -1.462 48.25 -1.264 48.161 -1.147 c
+48.073 -1.022 47.941 -0.955 47.764 -0.955 c
+51.953 -3.572 m
+51.924 -3.505 51.902 -3.395 51.895 -3.248 c
+51.718 -3.505 51.498 -3.63 51.234 -3.63 c
+50.958 -3.63 50.741 -3.557 50.586 -3.41 c
+50.44 -3.256 50.366 -3.039 50.366 -2.763 c
+50.366 -2.462 50.469 -2.219 50.675 -2.043 c
+50.881 -1.859 51.164 -1.764 51.527 -1.764 c
+51.88 -1.764 l
+51.88 -1.44 l
+51.88 -1.264 51.839 -1.143 51.762 -1.072 c
+51.681 -0.995 51.564 -0.955 51.41 -0.955 c
+51.263 -0.955 51.138 -0.999 51.043 -1.087 c
+50.954 -1.176 50.91 -1.286 50.91 -1.411 c
+50.425 -1.411 l
+50.425 -1.264 50.469 -1.124 50.557 -0.985 c
+50.646 -0.837 50.763 -0.727 50.91 -0.646 c
+51.064 -0.569 51.237 -0.529 51.425 -0.529 c
+51.737 -0.529 51.972 -0.61 52.13 -0.764 c
+52.284 -0.912 52.365 -1.132 52.365 -1.425 c
+52.365 -2.925 l
+52.373 -3.16 52.41 -3.362 52.468 -3.528 c
+52.468 -3.572 l
+h
+51.307 -3.189 m
+51.425 -3.189 51.535 -3.156 51.645 -3.087 c
+51.752 -3.021 51.829 -2.936 51.88 -2.836 c
+51.88 -2.131 l
+51.616 -2.131 l
+51.38 -2.131 51.193 -2.183 51.057 -2.278 c
+50.929 -2.377 50.866 -2.52 50.866 -2.705 c
+50.866 -2.873 50.895 -2.994 50.954 -3.072 c
+51.02 -3.152 51.138 -3.189 51.307 -3.189 c
+54.045 -1.94 m
+54.045 -1.481 54.125 -1.132 54.295 -0.897 c
+54.471 -0.654 54.721 -0.529 55.045 -0.529 c
+55.327 -0.529 55.548 -0.646 55.706 -0.881 c
+55.706 0.661 l
+56.19 0.661 l
+56.19 -3.572 l
+55.75 -3.572 l
+55.72 -3.248 l
+55.562 -3.505 55.338 -3.63 55.045 -3.63 c
+54.728 -3.63 54.486 -3.513 54.309 -3.278 c
+54.133 -3.035 54.045 -2.69 54.045 -2.248 c
+h
+54.53 -2.219 m
+54.53 -2.554 54.578 -2.8 54.677 -2.954 c
+54.773 -3.112 54.934 -3.189 55.162 -3.189 c
+55.404 -3.189 55.588 -3.072 55.706 -2.836 c
+55.706 -1.323 l
+55.577 -1.087 55.397 -0.97 55.162 -0.97 c
+54.934 -0.97 54.773 -1.051 54.677 -1.205 c
+54.578 -1.363 54.53 -1.602 54.53 -1.926 c
+h
+57.823 -3.63 m
+57.447 -3.63 57.165 -3.524 56.969 -3.307 c
+56.772 -3.083 56.676 -2.755 56.676 -2.323 c
+56.676 -1.955 l
+56.676 -1.514 56.768 -1.168 56.955 -0.912 c
+57.15 -0.658 57.426 -0.529 57.778 -0.529 c
+58.12 -0.529 58.374 -0.643 58.542 -0.867 c
+58.719 -1.095 58.811 -1.44 58.822 -1.911 c
+58.822 -2.219 l
+57.161 -2.219 l
+57.161 -2.293 l
+57.161 -2.616 57.22 -2.851 57.337 -2.998 c
+57.455 -3.138 57.624 -3.204 57.852 -3.204 c
+57.998 -3.204 58.124 -3.183 58.234 -3.131 c
+58.341 -3.072 58.443 -2.984 58.542 -2.866 c
+58.792 -3.175 l
+58.586 -3.48 58.264 -3.63 57.823 -3.63 c
+57.778 -0.955 m
+57.572 -0.955 57.418 -1.025 57.323 -1.161 c
+57.223 -1.301 57.168 -1.514 57.161 -1.808 c
+58.337 -1.808 l
+58.337 -1.735 l
+58.315 -1.462 58.264 -1.264 58.175 -1.147 c
+58.087 -1.022 57.954 -0.955 57.778 -0.955 c
+60.038 -2.836 m
+60.612 -0.588 l
+61.111 -0.588 l
+60.215 -3.572 l
+59.862 -3.572 l
+58.966 -0.588 l
+59.45 -0.588 l
+h
+62.482 -3.63 m
+62.107 -3.63 61.824 -3.524 61.63 -3.307 c
+61.431 -3.083 61.335 -2.755 61.335 -2.323 c
+61.335 -1.955 l
+61.335 -1.514 61.427 -1.168 61.615 -0.912 c
+61.809 -0.658 62.085 -0.529 62.438 -0.529 c
+62.779 -0.529 63.033 -0.643 63.203 -0.867 c
+63.379 -1.095 63.471 -1.44 63.481 -1.911 c
+63.481 -2.219 l
+61.821 -2.219 l
+61.821 -2.293 l
+61.821 -2.616 61.879 -2.851 61.997 -2.998 c
+62.114 -3.138 62.284 -3.204 62.511 -3.204 c
+62.658 -3.204 62.783 -3.183 62.893 -3.131 c
+63 -3.072 63.103 -2.984 63.203 -2.866 c
+63.452 -3.175 l
+63.246 -3.48 62.923 -3.63 62.482 -3.63 c
+62.438 -0.955 m
+62.232 -0.955 62.078 -1.025 61.982 -1.161 c
+61.883 -1.301 61.828 -1.514 61.821 -1.808 c
+62.997 -1.808 l
+62.997 -1.735 l
+62.974 -1.462 62.923 -1.264 62.835 -1.147 c
+62.746 -1.022 62.614 -0.955 62.438 -0.955 c
+64.422 -3.572 -0.5 4.233 re
+64.996 -1.94 m
+64.996 -1.51 65.098 -1.168 65.304 -0.912 c
+65.517 -0.658 65.796 -0.529 66.142 -0.529 c
+66.484 -0.529 66.76 -0.658 66.966 -0.912 c
+67.178 -1.157 67.292 -1.492 67.303 -1.911 c
+67.303 -2.219 l
+67.303 -2.653 67.193 -2.994 66.98 -3.248 c
+66.774 -3.505 66.495 -3.63 66.142 -3.63 c
+65.796 -3.63 65.524 -3.509 65.319 -3.263 c
+65.113 -3.021 65.003 -2.686 64.996 -2.263 c
+h
+65.48 -2.219 m
+65.48 -2.535 65.539 -2.778 65.657 -2.954 c
+65.782 -3.123 65.944 -3.204 66.142 -3.204 c
+66.572 -3.204 66.796 -2.896 66.818 -2.278 c
+66.818 -1.94 l
+66.818 -1.639 66.752 -1.396 66.627 -1.22 c
+66.509 -1.043 66.348 -0.955 66.142 -0.955 c
+65.944 -0.955 65.782 -1.043 65.657 -1.22 c
+65.539 -1.396 65.48 -1.639 65.48 -1.94 c
+h
+69.887 -2.219 m
+69.887 -2.69 69.802 -3.042 69.636 -3.278 c
+69.468 -3.513 69.229 -3.63 68.917 -3.63 c
+68.612 -3.63 68.379 -3.52 68.225 -3.293 c
+68.225 -4.718 l
+67.741 -4.718 l
+67.741 -0.588 l
+68.181 -0.588 l
+68.211 -0.926 l
+68.365 -0.661 68.597 -0.529 68.902 -0.529 c
+69.233 -0.529 69.478 -0.646 69.636 -0.881 c
+69.802 -1.109 69.887 -1.448 69.887 -1.896 c
+h
+69.401 -1.94 m
+69.401 -1.61 69.347 -1.363 69.239 -1.205 c
+69.141 -1.051 68.979 -0.97 68.755 -0.97 c
+68.52 -0.97 68.343 -1.087 68.225 -1.323 c
+68.225 -2.866 l
+68.343 -3.094 68.523 -3.204 68.769 -3.204 c
+68.983 -3.204 69.141 -3.127 69.239 -2.969 c
+69.347 -2.815 69.401 -2.572 69.401 -2.248 c
+h
+71.404 -3.63 m
+71.03 -3.63 70.746 -3.524 70.552 -3.307 c
+70.353 -3.083 70.258 -2.755 70.258 -2.323 c
+70.258 -1.955 l
+70.258 -1.514 70.349 -1.168 70.537 -0.912 c
+70.731 -0.658 71.007 -0.529 71.36 -0.529 c
+71.702 -0.529 71.955 -0.643 72.125 -0.867 c
+72.301 -1.095 72.393 -1.44 72.404 -1.911 c
+72.404 -2.219 l
+70.743 -2.219 l
+70.743 -2.293 l
+70.743 -2.616 70.802 -2.851 70.919 -2.998 c
+71.037 -3.138 71.206 -3.204 71.434 -3.204 c
+71.581 -3.204 71.706 -3.183 71.816 -3.131 c
+71.922 -3.072 72.025 -2.984 72.125 -2.866 c
+72.375 -3.175 l
+72.169 -3.48 71.845 -3.63 71.404 -3.63 c
+71.36 -0.955 m
+71.155 -0.955 71 -1.025 70.904 -1.161 c
+70.806 -1.301 70.75 -1.514 70.743 -1.808 c
+71.919 -1.808 l
+71.919 -1.735 l
+71.897 -1.462 71.845 -1.264 71.757 -1.147 c
+71.669 -1.022 71.537 -0.955 71.36 -0.955 c
+74.05 -1.043 m
+73.981 -1.036 73.906 -1.029 73.829 -1.029 c
+73.572 -1.029 73.396 -1.168 73.301 -1.44 c
+73.301 -3.572 l
+72.815 -3.572 l
+72.815 -0.588 l
+73.285 -0.588 l
+73.301 -0.897 l
+73.426 -0.654 73.609 -0.529 73.844 -0.529 c
+73.921 -0.529 73.984 -0.544 74.035 -0.573 c
+h
+74.785 0.353 m
+74.741 -0.661 l
+74.373 -0.661 l
+74.388 0.661 l
+74.785 0.661 l
+h
+76.611 -2.807 m
+76.611 -2.701 76.571 -2.612 76.493 -2.543 c
+76.412 -2.466 76.262 -2.377 76.038 -2.278 c
+75.774 -2.171 75.586 -2.08 75.479 -1.999 c
+75.369 -1.922 75.292 -1.834 75.244 -1.735 c
+75.193 -1.639 75.171 -1.521 75.171 -1.382 c
+75.171 -1.139 75.259 -0.937 75.435 -0.779 c
+75.612 -0.613 75.836 -0.529 76.111 -0.529 c
+76.406 -0.529 76.641 -0.617 76.817 -0.794 c
+76.994 -0.962 77.081 -1.176 77.081 -1.44 c
+76.597 -1.44 l
+76.597 -1.304 76.545 -1.19 76.45 -1.103 c
+76.362 -1.007 76.248 -0.955 76.111 -0.955 c
+75.965 -0.955 75.851 -0.995 75.774 -1.072 c
+75.693 -1.143 75.656 -1.242 75.656 -1.367 c
+75.656 -1.466 75.685 -1.543 75.745 -1.602 c
+75.803 -1.66 75.942 -1.741 76.171 -1.837 c
+76.53 -1.984 76.777 -2.127 76.905 -2.263 c
+77.041 -2.392 77.112 -2.564 77.112 -2.778 c
+77.112 -3.035 77.016 -3.241 76.832 -3.395 c
+76.655 -3.553 76.42 -3.63 76.127 -3.63 c
+75.81 -3.63 75.556 -3.542 75.362 -3.366 c
+75.174 -3.183 75.082 -2.95 75.082 -2.675 c
+75.568 -2.675 l
+75.575 -2.844 75.627 -2.977 75.714 -3.072 c
+75.81 -3.16 75.95 -3.204 76.127 -3.204 c
+76.281 -3.204 76.398 -3.171 76.479 -3.102 c
+76.568 -3.035 76.611 -2.936 76.611 -2.807 c
+f
+Q
+q 1 0 0 1 453.7345 138.0102 cm
+0 0 m
+0.015 -0.324 l
+0.199 -0.07 0.441 0.059 0.735 0.059 c
+1.264 0.059 1.532 -0.294 1.544 -0.999 c
+1.544 -2.984 l
+1.058 -2.984 l
+1.058 -1.029 l
+1.058 -0.794 1.018 -0.628 0.941 -0.529 c
+0.86 -0.434 0.742 -0.382 0.588 -0.382 c
+0.47 -0.382 0.36 -0.422 0.264 -0.5 c
+0.166 -0.58 0.088 -0.687 0.029 -0.823 c
+0.029 -2.984 l
+-0.455 -2.984 l
+-0.455 0 l
+h
+1.992 -1.352 m
+1.992 -0.922 2.095 -0.58 2.3 -0.324 c
+2.514 -0.07 2.793 0.059 3.138 0.059 c
+3.48 0.059 3.755 -0.07 3.961 -0.324 c
+4.175 -0.569 4.289 -0.904 4.299 -1.323 c
+4.299 -1.631 l
+4.299 -2.065 4.189 -2.406 3.977 -2.66 c
+3.77 -2.917 3.491 -3.042 3.138 -3.042 c
+2.793 -3.042 2.521 -2.921 2.315 -2.675 c
+2.109 -2.433 1.999 -2.098 1.992 -1.675 c
+h
+2.477 -1.631 m
+2.477 -1.947 2.535 -2.19 2.653 -2.366 c
+2.778 -2.535 2.94 -2.616 3.138 -2.616 c
+3.568 -2.616 3.792 -2.308 3.815 -1.691 c
+3.815 -1.352 l
+3.815 -1.051 3.748 -0.808 3.624 -0.632 c
+3.506 -0.455 3.344 -0.367 3.138 -0.367 c
+2.94 -0.367 2.778 -0.455 2.653 -0.632 c
+2.535 -0.808 2.477 -1.051 2.477 -1.352 c
+h
+5.373 0.721 m
+5.373 0 l
+5.828 0 l
+5.828 -0.397 l
+5.373 -0.397 l
+5.373 -2.248 l
+5.373 -2.366 5.39 -2.454 5.431 -2.514 c
+5.468 -2.572 5.538 -2.601 5.637 -2.601 c
+5.696 -2.601 5.758 -2.595 5.828 -2.572 c
+5.828 -2.984 l
+5.71 -3.021 5.596 -3.042 5.49 -3.042 c
+5.292 -3.042 5.141 -2.977 5.035 -2.836 c
+4.935 -2.701 4.887 -2.506 4.887 -2.248 c
+4.887 -0.397 l
+4.432 -0.397 l
+4.432 0 l
+4.887 0 l
+4.887 0.721 l
+h
+7.349 -3.042 m
+6.975 -3.042 6.691 -2.936 6.497 -2.719 c
+6.298 -2.495 6.203 -2.167 6.203 -1.735 c
+6.203 -1.367 l
+6.203 -0.926 6.294 -0.58 6.483 -0.324 c
+6.677 -0.07 6.953 0.059 7.306 0.059 c
+7.647 0.059 7.9 -0.055 8.07 -0.279 c
+8.247 -0.507 8.338 -0.852 8.349 -1.323 c
+8.349 -1.631 l
+6.688 -1.631 l
+6.688 -1.705 l
+6.688 -2.028 6.747 -2.263 6.865 -2.41 c
+6.982 -2.55 7.151 -2.616 7.379 -2.616 c
+7.526 -2.616 7.651 -2.595 7.761 -2.543 c
+7.867 -2.484 7.971 -2.396 8.07 -2.278 c
+8.32 -2.587 l
+8.114 -2.892 7.79 -3.042 7.349 -3.042 c
+7.306 -0.367 m
+7.1 -0.367 6.945 -0.437 6.85 -0.573 c
+6.751 -0.713 6.695 -0.926 6.688 -1.22 c
+7.864 -1.22 l
+7.864 -1.147 l
+7.842 -0.874 7.79 -0.676 7.703 -0.559 c
+7.614 -0.434 7.482 -0.367 7.306 -0.367 c
+11.406 -2.219 m
+11.406 -2.113 11.366 -2.024 11.289 -1.955 c
+11.208 -1.878 11.057 -1.789 10.834 -1.691 c
+10.568 -1.583 10.381 -1.492 10.275 -1.411 c
+10.165 -1.334 10.088 -1.246 10.04 -1.147 c
+9.988 -1.051 9.966 -0.933 9.966 -0.794 c
+9.966 -0.551 10.055 -0.349 10.231 -0.191 c
+10.406 -0.025 10.631 0.059 10.907 0.059 c
+11.2 0.059 11.436 -0.029 11.612 -0.206 c
+11.788 -0.374 11.877 -0.588 11.877 -0.852 c
+11.391 -0.852 l
+11.391 -0.716 11.341 -0.602 11.245 -0.515 c
+11.156 -0.419 11.042 -0.367 10.907 -0.367 c
+10.76 -0.367 10.645 -0.407 10.568 -0.484 c
+10.487 -0.555 10.451 -0.654 10.451 -0.779 c
+10.451 -0.878 10.481 -0.955 10.539 -1.014 c
+10.598 -1.072 10.738 -1.153 10.965 -1.249 c
+11.326 -1.396 11.572 -1.539 11.701 -1.675 c
+11.836 -1.804 11.906 -1.977 11.906 -2.19 c
+11.906 -2.447 11.811 -2.653 11.627 -2.807 c
+11.451 -2.965 11.216 -3.042 10.921 -3.042 c
+10.605 -3.042 10.352 -2.954 10.157 -2.778 c
+9.97 -2.595 9.878 -2.362 9.878 -2.088 c
+10.363 -2.088 l
+10.37 -2.256 10.422 -2.389 10.51 -2.484 c
+10.605 -2.572 10.745 -2.616 10.921 -2.616 c
+11.075 -2.616 11.193 -2.583 11.274 -2.514 c
+11.362 -2.447 11.406 -2.348 11.406 -2.219 c
+12.259 -1.352 m
+12.259 -0.922 12.362 -0.58 12.567 -0.324 c
+12.781 -0.07 13.06 0.059 13.406 0.059 c
+13.747 0.059 14.023 -0.07 14.229 -0.324 c
+14.442 -0.569 14.556 -0.904 14.566 -1.323 c
+14.566 -1.631 l
+14.566 -2.065 14.456 -2.406 14.244 -2.66 c
+14.038 -2.917 13.758 -3.042 13.406 -3.042 c
+13.06 -3.042 12.788 -2.921 12.582 -2.675 c
+12.376 -2.433 12.266 -2.098 12.259 -1.675 c
+h
+12.744 -1.631 m
+12.744 -1.947 12.803 -2.19 12.92 -2.366 c
+13.045 -2.535 13.207 -2.616 13.406 -2.616 c
+13.835 -2.616 14.059 -2.308 14.082 -1.691 c
+14.082 -1.352 l
+14.082 -1.051 14.015 -0.808 13.891 -0.632 c
+13.773 -0.455 13.612 -0.367 13.406 -0.367 c
+13.207 -0.367 13.045 -0.455 12.92 -0.632 c
+12.803 -0.808 12.744 -1.051 12.744 -1.352 c
+h
+16.742 -2.984 -0.5 2.984 re
+16.772 0.794 m
+16.772 0.706 16.746 0.632 16.698 0.574 c
+16.658 0.522 16.588 0.5 16.492 0.5 c
+16.405 0.5 16.334 0.522 16.286 0.574 c
+16.247 0.632 16.228 0.698 16.228 0.779 c
+16.228 0.867 16.247 0.941 16.286 1 c
+16.334 1.058 16.405 1.087 16.492 1.087 c
+16.588 1.087 16.658 1.058 16.698 1 c
+16.746 0.941 16.772 0.871 16.772 0.794 c
+18.047 0.721 m
+18.047 0 l
+18.502 0 l
+18.502 -0.397 l
+18.047 -0.397 l
+18.047 -2.248 l
+18.047 -2.366 18.065 -2.454 18.105 -2.514 c
+18.142 -2.572 18.212 -2.601 18.311 -2.601 c
+18.37 -2.601 18.433 -2.595 18.502 -2.572 c
+18.502 -2.984 l
+18.385 -3.021 18.271 -3.042 18.165 -3.042 c
+17.966 -3.042 17.816 -2.977 17.708 -2.836 c
+17.61 -2.701 17.562 -2.506 17.562 -2.248 c
+17.562 -0.397 l
+17.106 -0.397 l
+17.106 0 l
+17.562 0 l
+17.562 0.721 l
+h
+19.293 0.941 m
+19.248 -0.073 l
+18.881 -0.073 l
+18.896 1.249 l
+19.293 1.249 l
+h
+21.119 -2.219 m
+21.119 -2.113 21.078 -2.024 21.001 -1.955 c
+20.92 -1.878 20.77 -1.789 20.546 -1.691 c
+20.281 -1.583 20.093 -1.492 19.987 -1.411 c
+19.877 -1.334 19.8 -1.246 19.752 -1.147 c
+19.7 -1.051 19.678 -0.933 19.678 -0.794 c
+19.678 -0.551 19.767 -0.349 19.943 -0.191 c
+20.12 -0.025 20.344 0.059 20.619 0.059 c
+20.913 0.059 21.148 -0.029 21.325 -0.206 c
+21.501 -0.374 21.589 -0.588 21.589 -0.852 c
+21.105 -0.852 l
+21.105 -0.716 21.053 -0.602 20.957 -0.515 c
+20.869 -0.419 20.755 -0.367 20.619 -0.367 c
+20.472 -0.367 20.359 -0.407 20.281 -0.484 c
+20.201 -0.555 20.164 -0.654 20.164 -0.779 c
+20.164 -0.878 20.193 -0.955 20.251 -1.014 c
+20.311 -1.072 20.45 -1.153 20.677 -1.249 c
+21.038 -1.396 21.284 -1.539 21.413 -1.675 c
+21.549 -1.804 21.618 -1.977 21.618 -2.19 c
+21.618 -2.447 21.523 -2.653 21.34 -2.807 c
+21.163 -2.965 20.928 -3.042 20.634 -3.042 c
+20.318 -3.042 20.064 -2.954 19.869 -2.778 c
+19.682 -2.595 19.59 -2.362 19.59 -2.088 c
+20.075 -2.088 l
+20.083 -2.256 20.134 -2.389 20.222 -2.484 c
+20.318 -2.572 20.457 -2.616 20.634 -2.616 c
+20.788 -2.616 20.906 -2.583 20.987 -2.514 c
+21.074 -2.447 21.119 -2.348 21.119 -2.219 c
+25.425 -1.631 m
+25.425 -2.102 25.342 -2.454 25.176 -2.69 c
+25.007 -2.925 24.768 -3.042 24.455 -3.042 c
+24.151 -3.042 23.919 -2.932 23.765 -2.705 c
+23.765 -4.13 l
+23.28 -4.13 l
+23.28 0 l
+23.721 0 l
+23.75 -0.338 l
+23.904 -0.073 24.136 0.059 24.44 0.059 c
+24.772 0.059 25.018 -0.058 25.176 -0.294 c
+25.342 -0.521 25.425 -0.86 25.425 -1.308 c
+h
+24.941 -1.352 m
+24.941 -1.022 24.885 -0.775 24.779 -0.617 c
+24.679 -0.463 24.518 -0.382 24.294 -0.382 c
+24.058 -0.382 23.883 -0.5 23.765 -0.735 c
+23.765 -2.278 l
+23.883 -2.506 24.062 -2.616 24.309 -2.616 c
+24.521 -2.616 24.679 -2.539 24.779 -2.381 c
+24.885 -2.227 24.941 -1.984 24.941 -1.66 c
+h
+27.12 -0.455 m
+27.05 -0.448 26.977 -0.441 26.9 -0.441 c
+26.642 -0.441 26.466 -0.58 26.37 -0.852 c
+26.37 -2.984 l
+25.885 -2.984 l
+25.885 0 l
+26.356 0 l
+26.37 -0.309 l
+26.495 -0.066 26.678 0.059 26.914 0.059 c
+26.991 0.059 27.054 0.044 27.105 0.015 c
+h
+27.333 -1.352 m
+27.333 -0.922 27.436 -0.58 27.642 -0.324 c
+27.854 -0.07 28.134 0.059 28.479 0.059 c
+28.821 0.059 29.097 -0.07 29.302 -0.324 c
+29.516 -0.569 29.63 -0.904 29.641 -1.323 c
+29.641 -1.631 l
+29.641 -2.065 29.531 -2.406 29.317 -2.66 c
+29.111 -2.917 28.832 -3.042 28.479 -3.042 c
+28.134 -3.042 27.862 -2.921 27.656 -2.675 c
+27.451 -2.433 27.34 -2.098 27.333 -1.675 c
+h
+27.818 -1.631 m
+27.818 -1.947 27.877 -2.19 27.995 -2.366 c
+28.12 -2.535 28.281 -2.616 28.479 -2.616 c
+28.909 -2.616 29.134 -2.308 29.155 -1.691 c
+29.155 -1.352 l
+29.155 -1.051 29.09 -0.808 28.964 -0.632 c
+28.847 -0.455 28.685 -0.367 28.479 -0.367 c
+28.281 -0.367 28.12 -0.455 27.995 -0.632 c
+27.877 -0.808 27.818 -1.051 27.818 -1.352 c
+h
+32.242 -1.631 m
+32.242 -2.102 32.158 -2.454 31.993 -2.69 c
+31.823 -2.925 31.581 -3.042 31.258 -3.042 c
+30.942 -3.042 30.707 -2.907 30.552 -2.631 c
+30.522 -2.984 l
+30.082 -2.984 l
+30.082 1.249 l
+30.567 1.249 l
+30.567 -0.324 l
+30.721 -0.07 30.952 0.059 31.258 0.059 c
+31.581 0.059 31.823 -0.058 31.993 -0.294 c
+32.158 -0.529 32.242 -0.878 32.242 -1.338 c
+h
+31.757 -1.352 m
+31.757 -0.999 31.706 -0.75 31.611 -0.602 c
+31.511 -0.455 31.349 -0.382 31.125 -0.382 c
+30.879 -0.382 30.692 -0.521 30.567 -0.794 c
+30.567 -2.205 l
+30.684 -2.469 30.875 -2.601 31.14 -2.601 c
+31.353 -2.601 31.511 -2.528 31.611 -2.381 c
+31.706 -2.227 31.757 -1.984 31.757 -1.66 c
+h
+34.212 -2.984 m
+34.183 -2.917 34.16 -2.807 34.154 -2.66 c
+33.977 -2.917 33.757 -3.042 33.492 -3.042 c
+33.217 -3.042 32.999 -2.969 32.845 -2.822 c
+32.698 -2.668 32.625 -2.451 32.625 -2.175 c
+32.625 -1.874 32.727 -1.631 32.933 -1.455 c
+33.139 -1.271 33.422 -1.176 33.786 -1.176 c
+34.138 -1.176 l
+34.138 -0.852 l
+34.138 -0.676 34.098 -0.555 34.021 -0.484 c
+33.94 -0.407 33.822 -0.367 33.668 -0.367 c
+33.521 -0.367 33.396 -0.411 33.3 -0.5 c
+33.213 -0.588 33.169 -0.698 33.169 -0.823 c
+32.683 -0.823 l
+32.683 -0.676 32.727 -0.536 32.816 -0.397 c
+32.904 -0.249 33.022 -0.139 33.169 -0.058 c
+33.323 0.019 33.495 0.059 33.683 0.059 c
+33.996 0.059 34.231 -0.022 34.389 -0.176 c
+34.543 -0.324 34.624 -0.544 34.624 -0.837 c
+34.624 -2.337 l
+34.631 -2.572 34.668 -2.774 34.726 -2.94 c
+34.726 -2.984 l
+h
+33.566 -2.601 m
+33.683 -2.601 33.793 -2.568 33.903 -2.499 c
+34.01 -2.433 34.087 -2.348 34.138 -2.248 c
+34.138 -1.543 l
+33.874 -1.543 l
+33.639 -1.543 33.452 -1.595 33.315 -1.691 c
+33.186 -1.789 33.124 -1.932 33.124 -2.117 c
+33.124 -2.285 33.154 -2.406 33.213 -2.484 c
+33.279 -2.564 33.396 -2.601 33.566 -2.601 c
+37.365 -1.631 m
+37.365 -2.102 37.281 -2.454 37.115 -2.69 c
+36.946 -2.925 36.704 -3.042 36.38 -3.042 c
+36.064 -3.042 35.829 -2.907 35.675 -2.631 c
+35.646 -2.984 l
+35.204 -2.984 l
+35.204 1.249 l
+35.69 1.249 l
+35.69 -0.324 l
+35.844 -0.07 36.075 0.059 36.38 0.059 c
+36.704 0.059 36.946 -0.058 37.115 -0.294 c
+37.281 -0.529 37.365 -0.878 37.365 -1.338 c
+h
+36.88 -1.352 m
+36.88 -0.999 36.828 -0.75 36.733 -0.602 c
+36.633 -0.455 36.472 -0.382 36.248 -0.382 c
+36.002 -0.382 35.814 -0.521 35.69 -0.794 c
+35.69 -2.205 l
+35.806 -2.469 35.998 -2.601 36.263 -2.601 c
+36.475 -2.601 36.633 -2.528 36.733 -2.381 c
+36.828 -2.227 36.88 -1.984 36.88 -1.66 c
+h
+38.339 -2.984 -0.5 4.233 re
+39.82 -2.175 m
+40.363 0 l
+40.878 0 l
+39.908 -3.41 l
+39.838 -3.663 39.735 -3.854 39.599 -3.983 c
+39.459 -4.119 39.309 -4.189 39.143 -4.189 c
+39.074 -4.189 38.989 -4.174 38.894 -4.145 c
+38.894 -3.734 l
+38.996 -3.748 l
+39.133 -3.748 39.239 -3.711 39.32 -3.645 c
+39.409 -3.576 39.474 -3.458 39.526 -3.293 c
+39.614 -2.954 l
+38.747 0 l
+39.276 0 l
+h
+43.935 -2.984 m
+43.906 -2.917 43.884 -2.807 43.877 -2.66 c
+43.7 -2.917 43.48 -3.042 43.216 -3.042 c
+42.94 -3.042 42.723 -2.969 42.568 -2.822 c
+42.422 -2.668 42.348 -2.451 42.348 -2.175 c
+42.348 -1.874 42.451 -1.631 42.657 -1.455 c
+42.862 -1.271 43.145 -1.176 43.509 -1.176 c
+43.862 -1.176 l
+43.862 -0.852 l
+43.862 -0.676 43.822 -0.555 43.744 -0.484 c
+43.663 -0.407 43.546 -0.367 43.392 -0.367 c
+43.245 -0.367 43.12 -0.411 43.024 -0.5 c
+42.936 -0.588 42.892 -0.698 42.892 -0.823 c
+42.407 -0.823 l
+42.407 -0.676 42.451 -0.536 42.539 -0.397 c
+42.627 -0.249 42.745 -0.139 42.892 -0.058 c
+43.046 0.019 43.219 0.059 43.407 0.059 c
+43.719 0.059 43.954 -0.022 44.112 -0.176 c
+44.266 -0.324 44.347 -0.544 44.347 -0.837 c
+44.347 -2.337 l
+44.354 -2.572 44.392 -2.774 44.45 -2.94 c
+44.45 -2.984 l
+h
+43.289 -2.601 m
+43.407 -2.601 43.517 -2.568 43.627 -2.499 c
+43.733 -2.433 43.81 -2.348 43.862 -2.248 c
+43.862 -1.543 l
+43.598 -1.543 l
+43.362 -1.543 43.175 -1.595 43.039 -1.691 c
+42.91 -1.789 42.848 -1.932 42.848 -2.117 c
+42.848 -2.285 42.877 -2.406 42.936 -2.484 c
+43.002 -2.564 43.12 -2.601 43.289 -2.601 c
+47.368 -0.455 m
+47.298 -0.448 47.224 -0.441 47.147 -0.441 c
+46.89 -0.441 46.713 -0.58 46.618 -0.852 c
+46.618 -2.984 l
+46.133 -2.984 l
+46.133 0 l
+46.603 0 l
+46.618 -0.309 l
+46.743 -0.066 46.927 0.059 47.162 0.059 c
+47.239 0.059 47.301 0.044 47.353 0.015 c
+h
+48.745 -3.042 m
+48.371 -3.042 48.088 -2.936 47.893 -2.719 c
+47.695 -2.495 47.6 -2.167 47.6 -1.735 c
+47.6 -1.367 l
+47.6 -0.926 47.691 -0.58 47.879 -0.324 c
+48.074 -0.07 48.349 0.059 48.702 0.059 c
+49.044 0.059 49.297 -0.055 49.466 -0.279 c
+49.643 -0.507 49.734 -0.852 49.745 -1.323 c
+49.745 -1.631 l
+48.084 -1.631 l
+48.084 -1.705 l
+48.084 -2.028 48.143 -2.263 48.261 -2.41 c
+48.379 -2.55 48.547 -2.616 48.775 -2.616 c
+48.922 -2.616 49.047 -2.595 49.157 -2.543 c
+49.264 -2.484 49.367 -2.396 49.466 -2.278 c
+49.716 -2.587 l
+49.51 -2.892 49.187 -3.042 48.745 -3.042 c
+48.702 -0.367 m
+48.496 -0.367 48.342 -0.437 48.246 -0.573 c
+48.147 -0.713 48.092 -0.926 48.084 -1.22 c
+49.26 -1.22 l
+49.26 -1.147 l
+49.238 -0.874 49.187 -0.676 49.098 -0.559 c
+49.011 -0.434 48.878 -0.367 48.702 -0.367 c
+50.362 -2.984 m
+50.362 -0.397 l
+49.981 -0.397 l
+49.981 0 l
+50.362 0 l
+50.362 0.339 l
+50.37 0.64 50.451 0.875 50.598 1.044 c
+50.744 1.22 50.954 1.309 51.23 1.309 c
+51.326 1.309 51.425 1.294 51.524 1.264 c
+51.494 0.852 l
+51.425 0.86 51.351 0.867 51.274 0.867 c
+50.998 0.867 50.862 0.669 50.862 0.279 c
+50.862 0 l
+51.363 0 l
+51.363 -0.397 l
+50.862 -0.397 l
+50.862 -2.984 l
+h
+52.821 -3.042 m
+52.446 -3.042 52.163 -2.936 51.968 -2.719 c
+51.77 -2.495 51.675 -2.167 51.675 -1.735 c
+51.675 -1.367 l
+51.675 -0.926 51.766 -0.58 51.954 -0.324 c
+52.149 -0.07 52.425 0.059 52.777 0.059 c
+53.119 0.059 53.372 -0.055 53.541 -0.279 c
+53.718 -0.507 53.809 -0.852 53.821 -1.323 c
+53.821 -1.631 l
+52.159 -1.631 l
+52.159 -1.705 l
+52.159 -2.028 52.219 -2.263 52.336 -2.41 c
+52.454 -2.55 52.623 -2.616 52.851 -2.616 c
+52.997 -2.616 53.123 -2.595 53.233 -2.543 c
+53.339 -2.484 53.443 -2.396 53.541 -2.278 c
+53.791 -2.587 l
+53.585 -2.892 53.262 -3.042 52.821 -3.042 c
+52.777 -0.367 m
+52.571 -0.367 52.417 -0.437 52.321 -0.573 c
+52.222 -0.713 52.167 -0.926 52.159 -1.22 c
+53.335 -1.22 l
+53.335 -1.147 l
+53.314 -0.874 53.262 -0.676 53.173 -0.559 c
+53.086 -0.434 52.953 -0.367 52.777 -0.367 c
+55.467 -0.455 m
+55.397 -0.448 55.324 -0.441 55.247 -0.441 c
+54.989 -0.441 54.813 -0.58 54.717 -0.852 c
+54.717 -2.984 l
+54.232 -2.984 l
+54.232 0 l
+54.702 0 l
+54.717 -0.309 l
+54.842 -0.066 55.026 0.059 55.261 0.059 c
+55.338 0.059 55.401 0.044 55.452 0.015 c
+h
+56.841 -3.042 m
+56.466 -3.042 56.184 -2.936 55.989 -2.719 c
+55.791 -2.495 55.695 -2.167 55.695 -1.735 c
+55.695 -1.367 l
+55.695 -0.926 55.787 -0.58 55.974 -0.324 c
+56.169 -0.07 56.444 0.059 56.797 0.059 c
+57.139 0.059 57.393 -0.055 57.562 -0.279 c
+57.738 -0.507 57.83 -0.852 57.84 -1.323 c
+57.84 -1.631 l
+56.18 -1.631 l
+56.18 -1.705 l
+56.18 -2.028 56.238 -2.263 56.356 -2.41 c
+56.474 -2.55 56.643 -2.616 56.871 -2.616 c
+57.017 -2.616 57.142 -2.595 57.252 -2.543 c
+57.36 -2.484 57.462 -2.396 57.562 -2.278 c
+57.811 -2.587 l
+57.605 -2.892 57.283 -3.042 56.841 -3.042 c
+56.797 -0.367 m
+56.591 -0.367 56.437 -0.437 56.342 -0.573 c
+56.242 -0.713 56.188 -0.926 56.18 -1.22 c
+57.356 -1.22 l
+57.356 -1.147 l
+57.333 -0.874 57.283 -0.676 57.194 -0.559 c
+57.106 -0.434 56.973 -0.367 56.797 -0.367 c
+58.708 0 m
+58.723 -0.324 l
+58.906 -0.07 59.149 0.059 59.443 0.059 c
+59.972 0.059 60.24 -0.294 60.252 -0.999 c
+60.252 -2.984 l
+59.766 -2.984 l
+59.766 -1.029 l
+59.766 -0.794 59.726 -0.628 59.649 -0.529 c
+59.568 -0.434 59.45 -0.382 59.296 -0.382 c
+59.178 -0.382 59.068 -0.422 58.973 -0.5 c
+58.873 -0.58 58.796 -0.687 58.738 -0.823 c
+58.738 -2.984 l
+58.252 -2.984 l
+58.252 0 l
+h
+61.835 -2.616 m
+62 -2.616 62.133 -2.568 62.232 -2.469 c
+62.328 -2.373 62.382 -2.23 62.394 -2.043 c
+62.85 -2.043 l
+62.839 -2.329 62.736 -2.568 62.54 -2.763 c
+62.353 -2.95 62.118 -3.042 61.835 -3.042 c
+61.472 -3.042 61.192 -2.925 60.998 -2.69 c
+60.799 -2.454 60.703 -2.109 60.703 -1.646 c
+60.703 -1.323 l
+60.703 -0.874 60.795 -0.529 60.982 -0.294 c
+61.177 -0.058 61.46 0.059 61.835 0.059 c
+62.137 0.059 62.379 -0.04 62.555 -0.235 c
+62.739 -0.434 62.839 -0.698 62.85 -1.029 c
+62.394 -1.029 l
+62.372 -0.804 62.313 -0.639 62.218 -0.529 c
+62.129 -0.422 62 -0.367 61.835 -0.367 c
+61.618 -0.367 61.457 -0.441 61.35 -0.588 c
+61.251 -0.727 61.196 -0.955 61.189 -1.278 c
+61.189 -1.66 l
+61.189 -2.013 61.236 -2.263 61.335 -2.41 c
+61.442 -2.55 61.607 -2.616 61.835 -2.616 c
+64.301 -3.042 m
+63.926 -3.042 63.643 -2.936 63.448 -2.719 c
+63.25 -2.495 63.155 -2.167 63.155 -1.735 c
+63.155 -1.367 l
+63.155 -0.926 63.246 -0.58 63.434 -0.324 c
+63.629 -0.07 63.904 0.059 64.257 0.059 c
+64.599 0.059 64.853 -0.055 65.021 -0.279 c
+65.198 -0.507 65.289 -0.852 65.301 -1.323 c
+65.301 -1.631 l
+63.639 -1.631 l
+63.639 -1.705 l
+63.639 -2.028 63.698 -2.263 63.816 -2.41 c
+63.934 -2.55 64.103 -2.616 64.331 -2.616 c
+64.477 -2.616 64.602 -2.595 64.713 -2.543 c
+64.819 -2.484 64.922 -2.396 65.021 -2.278 c
+65.271 -2.587 l
+65.065 -2.892 64.742 -3.042 64.301 -3.042 c
+64.257 -0.367 m
+64.051 -0.367 63.897 -0.437 63.801 -0.573 c
+63.702 -0.713 63.647 -0.926 63.639 -1.22 c
+64.815 -1.22 l
+64.815 -1.147 l
+64.793 -0.874 64.742 -0.676 64.654 -0.559 c
+64.566 -0.434 64.433 -0.367 64.257 -0.367 c
+65.713 -3.777 m
+65.418 -3.586 l
+65.595 -3.341 65.686 -3.09 65.697 -2.836 c
+65.697 -2.381 l
+66.197 -2.381 l
+66.197 -2.778 l
+66.197 -2.965 66.145 -3.149 66.05 -3.337 c
+65.962 -3.52 65.848 -3.667 65.713 -3.777 c
+f
+Q
+q 1 0 0 1 492.43 131.4251 cm
+0 0 m
+0.014 -0.324 l
+0.198 -0.07 0.441 0.059 0.735 0.059 c
+1.264 0.059 1.533 -0.294 1.543 -0.999 c
+1.543 -2.984 l
+1.058 -2.984 l
+1.058 -1.029 l
+1.058 -0.794 1.018 -0.628 0.941 -0.529 c
+0.86 -0.434 0.742 -0.382 0.588 -0.382 c
+0.47 -0.382 0.36 -0.422 0.264 -0.5 c
+0.166 -0.58 0.088 -0.687 0.029 -0.823 c
+0.029 -2.984 l
+-0.456 -2.984 l
+-0.456 0 l
+h
+1.995 -1.352 m
+1.995 -0.922 2.098 -0.58 2.304 -0.324 c
+2.517 -0.07 2.796 0.059 3.142 0.059 c
+3.484 0.059 3.759 -0.07 3.965 -0.324 c
+4.178 -0.569 4.292 -0.904 4.303 -1.323 c
+4.303 -1.631 l
+4.303 -2.065 4.193 -2.406 3.979 -2.66 c
+3.774 -2.917 3.495 -3.042 3.142 -3.042 c
+2.796 -3.042 2.524 -2.921 2.319 -2.675 c
+2.113 -2.433 2.003 -2.098 1.995 -1.675 c
+h
+2.481 -1.631 m
+2.481 -1.947 2.539 -2.19 2.657 -2.366 c
+2.782 -2.535 2.944 -2.616 3.142 -2.616 c
+3.572 -2.616 3.796 -2.308 3.818 -1.691 c
+3.818 -1.352 l
+3.818 -1.051 3.752 -0.808 3.627 -0.632 c
+3.509 -0.455 3.347 -0.367 3.142 -0.367 c
+2.944 -0.367 2.782 -0.455 2.657 -0.632 c
+2.539 -0.808 2.481 -1.051 2.481 -1.352 c
+h
+5.373 0.721 m
+5.373 0 l
+5.828 0 l
+5.828 -0.397 l
+5.373 -0.397 l
+5.373 -2.248 l
+5.373 -2.366 5.39 -2.454 5.431 -2.514 c
+5.468 -2.572 5.538 -2.601 5.637 -2.601 c
+5.696 -2.601 5.758 -2.595 5.828 -2.572 c
+5.828 -2.984 l
+5.71 -3.021 5.596 -3.042 5.49 -3.042 c
+5.292 -3.042 5.141 -2.977 5.034 -2.836 c
+4.935 -2.701 4.887 -2.506 4.887 -2.248 c
+4.887 -0.397 l
+4.432 -0.397 l
+4.432 0 l
+4.887 0 l
+4.887 0.721 l
+h
+9.028 -2.984 m
+8.999 -2.917 8.978 -2.807 8.97 -2.66 c
+8.793 -2.917 8.573 -3.042 8.309 -3.042 c
+8.033 -3.042 7.816 -2.969 7.661 -2.822 c
+7.515 -2.668 7.441 -2.451 7.441 -2.175 c
+7.441 -1.874 7.544 -1.631 7.75 -1.455 c
+7.956 -1.271 8.239 -1.176 8.602 -1.176 c
+8.955 -1.176 l
+8.955 -0.852 l
+8.955 -0.676 8.914 -0.555 8.837 -0.484 c
+8.756 -0.407 8.639 -0.367 8.485 -0.367 c
+8.338 -0.367 8.213 -0.411 8.118 -0.5 c
+8.029 -0.588 7.985 -0.698 7.985 -0.823 c
+7.5 -0.823 l
+7.5 -0.676 7.544 -0.536 7.632 -0.397 c
+7.721 -0.249 7.838 -0.139 7.985 -0.058 c
+8.139 0.019 8.312 0.059 8.5 0.059 c
+8.812 0.059 9.047 -0.022 9.205 -0.176 c
+9.359 -0.324 9.44 -0.544 9.44 -0.837 c
+9.44 -2.337 l
+9.448 -2.572 9.485 -2.774 9.543 -2.94 c
+9.543 -2.984 l
+h
+8.382 -2.601 m
+8.5 -2.601 8.61 -2.568 8.72 -2.499 c
+8.827 -2.433 8.904 -2.348 8.955 -2.248 c
+8.955 -1.543 l
+8.691 -1.543 l
+8.455 -1.543 8.268 -1.595 8.132 -1.691 c
+8.004 -1.789 7.941 -1.932 7.941 -2.117 c
+7.941 -2.285 7.97 -2.406 8.029 -2.484 c
+8.095 -2.564 8.213 -2.601 8.382 -2.601 c
+10.477 0 m
+10.491 -0.324 l
+10.675 -0.07 10.917 0.059 11.212 0.059 c
+11.74 0.059 12.009 -0.294 12.02 -0.999 c
+12.02 -2.984 l
+11.535 -2.984 l
+11.535 -1.029 l
+11.535 -0.794 11.495 -0.628 11.418 -0.529 c
+11.337 -0.434 11.219 -0.382 11.065 -0.382 c
+10.947 -0.382 10.836 -0.422 10.741 -0.5 c
+10.642 -0.58 10.564 -0.687 10.506 -0.823 c
+10.506 -2.984 l
+10.021 -2.984 l
+10.021 0 l
+h
+13.674 -1.352 m
+13.674 -0.922 13.776 -0.58 13.982 -0.324 c
+14.196 -0.07 14.475 0.059 14.82 0.059 c
+15.162 0.059 15.438 -0.07 15.644 -0.324 c
+15.856 -0.569 15.97 -0.904 15.981 -1.323 c
+15.981 -1.631 l
+15.981 -2.065 15.871 -2.406 15.658 -2.66 c
+15.453 -2.917 15.173 -3.042 14.82 -3.042 c
+14.475 -3.042 14.202 -2.921 13.997 -2.675 c
+13.791 -2.433 13.681 -2.098 13.674 -1.675 c
+h
+14.159 -1.631 m
+14.159 -1.947 14.217 -2.19 14.335 -2.366 c
+14.46 -2.535 14.622 -2.616 14.82 -2.616 c
+15.25 -2.616 15.474 -2.308 15.496 -1.691 c
+15.496 -1.352 l
+15.496 -1.051 15.43 -0.808 15.305 -0.632 c
+15.187 -0.455 15.025 -0.367 14.82 -0.367 c
+14.622 -0.367 14.46 -0.455 14.335 -0.632 c
+14.217 -0.808 14.159 -1.051 14.159 -1.352 c
+h
+18.58 -1.631 m
+18.58 -2.102 18.495 -2.454 18.329 -2.69 c
+18.161 -2.925 17.918 -3.042 17.595 -3.042 c
+17.279 -3.042 17.043 -2.907 16.889 -2.631 c
+16.86 -2.984 l
+16.419 -2.984 l
+16.419 1.249 l
+16.904 1.249 l
+16.904 -0.324 l
+17.058 -0.07 17.29 0.059 17.595 0.059 c
+17.918 0.059 18.161 -0.058 18.329 -0.294 c
+18.495 -0.529 18.58 -0.878 18.58 -1.338 c
+h
+18.094 -1.352 m
+18.094 -0.999 18.042 -0.75 17.947 -0.602 c
+17.848 -0.455 17.687 -0.382 17.462 -0.382 c
+17.216 -0.382 17.028 -0.521 16.904 -0.794 c
+16.904 -2.205 l
+17.022 -2.469 17.213 -2.601 17.477 -2.601 c
+17.691 -2.601 17.848 -2.528 17.947 -2.381 c
+18.042 -2.227 18.094 -1.984 18.094 -1.66 c
+h
+19.524 0 m
+19.524 -3.366 l
+19.513 -3.913 19.293 -4.189 18.863 -4.189 c
+18.763 -4.189 18.675 -4.174 18.597 -4.145 c
+18.597 -3.734 l
+18.649 -3.74 18.708 -3.748 18.788 -3.748 c
+18.867 -3.748 18.925 -3.719 18.965 -3.659 c
+19.013 -3.601 19.039 -3.491 19.039 -3.337 c
+19.039 0 l
+h
+19.538 0.794 m
+19.538 0.706 19.513 0.632 19.465 0.574 c
+19.424 0.522 19.355 0.5 19.259 0.5 c
+19.171 0.5 19.102 0.522 19.054 0.574 c
+19.013 0.632 18.994 0.698 18.994 0.779 c
+18.994 0.867 19.013 0.941 19.054 1 c
+19.102 1.058 19.171 1.087 19.259 1.087 c
+19.355 1.087 19.424 1.058 19.465 1 c
+19.513 0.941 19.538 0.871 19.538 0.794 c
+21.265 -3.042 m
+20.891 -3.042 20.608 -2.936 20.413 -2.719 c
+20.215 -2.495 20.12 -2.167 20.12 -1.735 c
+20.12 -1.367 l
+20.12 -0.926 20.211 -0.58 20.398 -0.324 c
+20.593 -0.07 20.868 0.059 21.221 0.059 c
+21.564 0.059 21.817 -0.055 21.986 -0.279 c
+22.162 -0.507 22.254 -0.852 22.265 -1.323 c
+22.265 -1.631 l
+20.604 -1.631 l
+20.604 -1.705 l
+20.604 -2.028 20.663 -2.263 20.781 -2.41 c
+20.899 -2.55 21.067 -2.616 21.296 -2.616 c
+21.442 -2.616 21.567 -2.595 21.677 -2.543 c
+21.784 -2.484 21.886 -2.396 21.986 -2.278 c
+22.236 -2.587 l
+22.03 -2.892 21.707 -3.042 21.265 -3.042 c
+21.221 -0.367 m
+21.016 -0.367 20.862 -0.437 20.766 -0.573 c
+20.667 -0.713 20.612 -0.926 20.604 -1.22 c
+21.78 -1.22 l
+21.78 -1.147 l
+21.758 -0.874 21.707 -0.676 21.618 -0.559 c
+21.531 -0.434 21.398 -0.367 21.221 -0.367 c
+23.706 -2.616 m
+23.871 -2.616 24.003 -2.568 24.103 -2.469 c
+24.198 -2.373 24.253 -2.23 24.264 -2.043 c
+24.72 -2.043 l
+24.709 -2.329 24.606 -2.568 24.411 -2.763 c
+24.224 -2.95 23.989 -3.042 23.706 -3.042 c
+23.342 -3.042 23.062 -2.925 22.867 -2.69 c
+22.669 -2.454 22.574 -2.109 22.574 -1.646 c
+22.574 -1.323 l
+22.574 -0.874 22.666 -0.529 22.853 -0.294 c
+23.048 -0.058 23.331 0.059 23.706 0.059 c
+24.007 0.059 24.249 -0.04 24.426 -0.235 c
+24.61 -0.434 24.709 -0.698 24.72 -1.029 c
+24.264 -1.029 l
+24.242 -0.804 24.184 -0.639 24.088 -0.529 c
+24 -0.422 23.871 -0.367 23.706 -0.367 c
+23.489 -0.367 23.327 -0.441 23.22 -0.588 c
+23.121 -0.727 23.066 -0.955 23.059 -1.278 c
+23.059 -1.66 l
+23.059 -2.013 23.106 -2.263 23.206 -2.41 c
+23.312 -2.55 23.478 -2.616 23.706 -2.616 c
+25.745 0.721 m
+25.745 0 l
+26.201 0 l
+26.201 -0.397 l
+25.745 -0.397 l
+25.745 -2.248 l
+25.745 -2.366 25.764 -2.454 25.804 -2.514 c
+25.841 -2.572 25.911 -2.601 26.01 -2.601 c
+26.069 -2.601 26.131 -2.595 26.201 -2.572 c
+26.201 -2.984 l
+26.083 -3.021 25.969 -3.042 25.863 -3.042 c
+25.664 -3.042 25.514 -2.977 25.408 -2.836 c
+25.308 -2.701 25.26 -2.506 25.26 -2.248 c
+25.26 -0.397 l
+24.804 -0.397 l
+24.804 0 l
+25.26 0 l
+25.26 0.721 l
+h
+26.697 -2.719 m
+26.697 -2.631 26.719 -2.558 26.771 -2.499 c
+26.829 -2.44 26.906 -2.41 27.006 -2.41 c
+27.112 -2.41 27.189 -2.44 27.241 -2.499 c
+27.299 -2.558 27.329 -2.631 27.329 -2.719 c
+27.329 -2.8 27.299 -2.866 27.241 -2.925 c
+27.189 -2.984 27.112 -3.013 27.006 -3.013 c
+26.906 -3.013 26.829 -2.984 26.771 -2.925 c
+26.719 -2.866 26.697 -2.8 26.697 -2.719 c
+f
+Q
+0.567 w 1 j 1 J
+q 1 0 0 1 522.4669 140.1895 cm
+0 0 m
+6.928 0.754 l
+S
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 527.2745 140.7116 cm
+0 0 m
+-0.949 -1.176 l
+2.649 0.291 l
+-1.177 0.948 l
+h
+f*
+Q
+0.906 0.785 0.617 0.969 K
+0.283 w 0 j 0 J
+q 1 0 0 1 527.2745 140.7116 cm
+0 0 m
+-0.949 -1.176 l
+2.649 0.291 l
+-1.177 0.948 l
+0 0 l
+h
+S
+Q
+ endstream endobj 21 0 obj <</I true/K false/S/Transparency/Type/Group>> endobj 28 0 obj <</BBox[198.027 568.502 444.988 526.485]/Group 63 0 R/Length 127/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>/Shading<</Sh0 64 0 R>>>>/Subtype/Form>>stream
+q
+198.027 568.502 246.962 -42.017 re
+W n
+q
+0 g
+/GS0 gs
+246.9619598 0 0 246.9619598 198.026535 547.4932861 cm
+BX /Sh0 sh EX Q
+Q
+ endstream endobj 29 0 obj <</BBox[589.44 293.423 621.568 278.07]/Group 65 0 R/Length 293/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 592.6808 293.4232 cm
+0 0 m
+25.646 0 l
+27.443 0 28.887 -1.448 28.887 -3.241 c
+28.887 -12.112 l
+28.887 -13.909 27.443 -15.353 25.646 -15.353 c
+0 -15.353 l
+-1.793 -15.353 -3.241 -13.909 -3.241 -12.112 c
+-3.241 -3.241 l
+-3.241 -1.448 -1.793 0 0 0 c
+f
+Q
+ endstream endobj 30 0 obj <</BBox[738.029 266.921 763.227 262.629]/Group 66 0 R/Length 5754/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 740.4832 263.5406 cm
+0 0 m
+0.456 2.131 l
+0.941 2.131 l
+0.206 -0.853 l
+-0.176 -0.853 l
+-0.764 1.278 l
+-1.337 -0.853 l
+-1.72 -0.853 l
+-2.454 2.131 l
+-1.969 2.131 l
+-1.499 0.058 l
+-0.955 2.131 l
+-0.573 2.131 l
+h
+1.69 1.822 m
+1.875 2.065 2.11 2.19 2.396 2.19 c
+2.926 2.19 3.194 1.837 3.205 1.132 c
+3.205 -0.853 l
+2.72 -0.853 l
+2.72 1.103 l
+2.72 1.338 2.679 1.502 2.602 1.602 c
+2.521 1.697 2.404 1.749 2.249 1.749 c
+2.132 1.749 2.022 1.708 1.926 1.631 c
+1.827 1.55 1.75 1.444 1.69 1.308 c
+1.69 -0.853 l
+1.206 -0.853 l
+1.206 3.38 l
+1.69 3.38 l
+h
+5.278 -0.853 m
+5.248 -0.786 5.226 -0.676 5.218 -0.53 c
+5.042 -0.786 4.822 -0.912 4.557 -0.912 c
+4.281 -0.912 4.065 -0.838 3.911 -0.691 c
+3.763 -0.537 3.69 -0.32 3.69 -0.044 c
+3.69 0.257 3.793 0.5 3.998 0.675 c
+4.204 0.86 4.487 0.955 4.851 0.955 c
+5.204 0.955 l
+5.204 1.278 l
+5.204 1.455 5.164 1.577 5.087 1.646 c
+5.006 1.723 4.888 1.764 4.734 1.764 c
+4.587 1.764 4.462 1.72 4.366 1.631 c
+4.278 1.543 4.233 1.433 4.233 1.308 c
+3.749 1.308 l
+3.749 1.455 3.793 1.595 3.881 1.734 c
+3.969 1.881 4.087 1.992 4.233 2.072 c
+4.388 2.15 4.561 2.19 4.748 2.19 c
+5.06 2.19 5.295 2.109 5.453 1.955 c
+5.608 1.808 5.689 1.587 5.689 1.294 c
+5.689 -0.206 l
+5.696 -0.441 5.733 -0.643 5.792 -0.809 c
+5.792 -0.853 l
+h
+4.63 -0.47 m
+4.748 -0.47 4.859 -0.437 4.969 -0.368 c
+5.075 -0.302 5.152 -0.217 5.204 -0.118 c
+5.204 0.588 l
+4.939 0.588 l
+4.704 0.588 4.516 0.536 4.381 0.44 c
+4.252 0.341 4.19 0.198 4.19 0.014 c
+4.19 -0.154 4.219 -0.276 4.278 -0.353 c
+4.344 -0.434 4.462 -0.47 4.63 -0.47 c
+6.901 2.851 m
+6.901 2.131 l
+7.357 2.131 l
+7.357 1.734 l
+6.901 1.734 l
+6.901 -0.118 l
+6.901 -0.235 6.92 -0.324 6.961 -0.383 c
+6.997 -0.441 7.067 -0.47 7.167 -0.47 c
+7.225 -0.47 7.288 -0.463 7.357 -0.441 c
+7.357 -0.853 l
+7.24 -0.89 7.126 -0.912 7.019 -0.912 c
+6.82 -0.912 6.67 -0.846 6.564 -0.706 c
+6.465 -0.57 6.417 -0.375 6.417 -0.118 c
+6.417 1.734 l
+5.961 1.734 l
+5.961 2.131 l
+6.417 2.131 l
+6.417 2.851 l
+h
+9.658 2.851 m
+9.658 2.131 l
+10.113 2.131 l
+10.113 1.734 l
+9.658 1.734 l
+9.658 -0.118 l
+9.658 -0.235 9.676 -0.324 9.717 -0.383 c
+9.754 -0.441 9.823 -0.47 9.922 -0.47 c
+9.981 -0.47 10.043 -0.463 10.113 -0.441 c
+10.113 -0.853 l
+9.996 -0.89 9.881 -0.912 9.775 -0.912 c
+9.577 -0.912 9.426 -0.846 9.32 -0.706 c
+9.22 -0.57 9.172 -0.375 9.172 -0.118 c
+9.172 1.734 l
+8.717 1.734 l
+8.717 2.131 l
+9.172 2.131 l
+9.172 2.851 l
+h
+10.426 0.779 m
+10.426 1.209 10.529 1.55 10.735 1.808 c
+10.947 2.061 11.227 2.19 11.572 2.19 c
+11.914 2.19 12.19 2.061 12.395 1.808 c
+12.609 1.562 12.723 1.227 12.734 0.808 c
+12.734 0.5 l
+12.734 0.066 12.623 -0.276 12.41 -0.53 c
+12.204 -0.786 11.925 -0.912 11.572 -0.912 c
+11.227 -0.912 10.955 -0.79 10.749 -0.544 c
+10.544 -0.302 10.433 0.033 10.426 0.455 c
+h
+10.911 0.5 m
+10.911 0.183 10.97 -0.059 11.088 -0.235 c
+11.212 -0.405 11.373 -0.485 11.572 -0.485 c
+12.002 -0.485 12.227 -0.177 12.248 0.44 c
+12.248 0.779 l
+12.248 1.08 12.183 1.323 12.057 1.499 c
+11.94 1.675 11.778 1.764 11.572 1.764 c
+11.373 1.764 11.212 1.675 11.088 1.499 c
+10.97 1.323 10.911 1.08 10.911 0.779 c
+h
+15.905 -0.853 m
+15.876 -0.786 15.853 -0.676 15.846 -0.53 c
+15.67 -0.786 15.449 -0.912 15.184 -0.912 c
+14.909 -0.912 14.692 -0.838 14.538 -0.691 c
+14.39 -0.537 14.317 -0.32 14.317 -0.044 c
+14.317 0.257 14.421 0.5 14.626 0.675 c
+14.832 0.86 15.115 0.955 15.479 0.955 c
+15.832 0.955 l
+15.832 1.278 l
+15.832 1.455 15.791 1.577 15.714 1.646 c
+15.633 1.723 15.516 1.764 15.361 1.764 c
+15.214 1.764 15.089 1.72 14.993 1.631 c
+14.905 1.543 14.861 1.433 14.861 1.308 c
+14.376 1.308 l
+14.376 1.455 14.421 1.595 14.508 1.734 c
+14.596 1.881 14.714 1.992 14.861 2.072 c
+15.015 2.15 15.188 2.19 15.375 2.19 c
+15.688 2.19 15.923 2.109 16.081 1.955 c
+16.235 1.808 16.316 1.587 16.316 1.294 c
+16.316 -0.206 l
+16.324 -0.441 16.36 -0.643 16.42 -0.809 c
+16.42 -0.853 l
+h
+15.258 -0.47 m
+15.375 -0.47 15.485 -0.437 15.596 -0.368 c
+15.703 -0.302 15.78 -0.217 15.832 -0.118 c
+15.832 0.588 l
+15.566 0.588 l
+15.331 0.588 15.144 0.536 15.009 0.44 c
+14.88 0.341 14.817 0.198 14.817 0.014 c
+14.817 -0.154 14.847 -0.276 14.905 -0.353 c
+14.972 -0.434 15.089 -0.47 15.258 -0.47 c
+16.794 0.779 m
+16.794 1.238 16.875 1.587 17.044 1.822 c
+17.22 2.065 17.47 2.19 17.794 2.19 c
+18.076 2.19 18.297 2.072 18.455 1.837 c
+18.455 3.38 l
+18.94 3.38 l
+18.94 -0.853 l
+18.5 -0.853 l
+18.47 -0.53 l
+18.311 -0.786 18.088 -0.912 17.794 -0.912 c
+17.478 -0.912 17.235 -0.794 17.058 -0.559 c
+16.882 -0.316 16.794 0.029 16.794 0.47 c
+h
+17.279 0.5 m
+17.279 0.166 17.326 -0.081 17.426 -0.235 c
+17.522 -0.393 17.683 -0.47 17.912 -0.47 c
+18.153 -0.47 18.338 -0.353 18.455 -0.118 c
+18.455 1.396 l
+18.327 1.631 18.147 1.749 17.912 1.749 c
+17.683 1.749 17.522 1.668 17.426 1.514 c
+17.326 1.356 17.279 1.117 17.279 0.793 c
+h
+19.41 0.779 m
+19.41 1.238 19.491 1.587 19.66 1.822 c
+19.836 2.065 20.087 2.19 20.41 2.19 c
+20.693 2.19 20.914 2.072 21.072 1.837 c
+21.072 3.38 l
+21.557 3.38 l
+21.557 -0.853 l
+21.116 -0.853 l
+21.087 -0.53 l
+20.929 -0.786 20.704 -0.912 20.41 -0.912 c
+20.094 -0.912 19.851 -0.794 19.676 -0.559 c
+19.499 -0.316 19.41 0.029 19.41 0.47 c
+h
+19.896 0.5 m
+19.896 0.166 19.944 -0.081 20.042 -0.235 c
+20.138 -0.393 20.3 -0.47 20.528 -0.47 c
+20.771 -0.47 20.954 -0.353 21.072 -0.118 c
+21.072 1.396 l
+20.943 1.631 20.763 1.749 20.528 1.749 c
+20.3 1.749 20.138 1.668 20.042 1.514 c
+19.944 1.356 19.896 1.117 19.896 0.793 c
+h
+22.67 0.279 m
+22.229 0.279 l
+22.2 3.16 l
+22.714 3.16 l
+h
+22.464 -0.309 m
+22.56 -0.309 22.629 -0.339 22.67 -0.397 c
+22.718 -0.449 22.743 -0.515 22.743 -0.603 c
+22.743 -0.684 22.718 -0.75 22.67 -0.809 c
+22.629 -0.856 22.56 -0.882 22.464 -0.882 c
+22.376 -0.882 22.306 -0.856 22.259 -0.809 c
+22.207 -0.75 22.185 -0.684 22.185 -0.603 c
+22.185 -0.515 22.207 -0.449 22.259 -0.397 c
+22.306 -0.339 22.376 -0.309 22.464 -0.309 c
+f
+Q
+ endstream endobj 31 0 obj <</BBox[580.256 333.713 630.219 328.304]/Group 67 0 R/Length 12062/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 582.8727 330.7593 cm
+0 0 m
+-0.029 -0.434 -0.154 -0.765 -0.367 -1 c
+-0.584 -1.228 -0.893 -1.338 -1.294 -1.338 c
+-1.697 -1.338 -2.021 -1.187 -2.263 -0.882 c
+-2.499 -0.57 -2.616 -0.154 -2.616 0.367 c
+-2.616 1.103 l
+-2.616 1.621 -2.495 2.032 -2.248 2.337 c
+-2.006 2.639 -1.672 2.793 -1.249 2.793 c
+-0.866 2.793 -0.569 2.675 -0.353 2.44 c
+-0.139 2.205 -0.022 1.87 0 1.44 c
+-0.514 1.44 l
+-0.536 1.771 -0.602 2.007 -0.72 2.146 c
+-0.837 2.282 -1.014 2.352 -1.249 2.352 c
+-1.525 2.352 -1.734 2.242 -1.881 2.028 c
+-2.028 1.812 -2.102 1.5 -2.102 1.087 c
+-2.102 0.353 l
+-2.102 -0.052 -2.036 -0.36 -1.896 -0.574 c
+-1.76 -0.79 -1.558 -0.897 -1.294 -0.897 c
+-1.028 -0.897 -0.845 -0.834 -0.735 -0.706 c
+-0.617 -0.58 -0.544 -0.345 -0.514 0 c
+h
+0.882 1.396 m
+1.066 1.639 1.301 1.764 1.588 1.764 c
+2.117 1.764 2.386 1.411 2.396 0.706 c
+2.396 -1.279 l
+1.912 -1.279 l
+1.912 0.676 l
+1.912 0.912 1.871 1.076 1.794 1.176 c
+1.713 1.271 1.595 1.323 1.441 1.323 c
+1.324 1.323 1.213 1.282 1.118 1.205 c
+1.018 1.124 0.941 1.018 0.882 0.881 c
+0.882 -1.279 l
+0.397 -1.279 l
+0.397 2.954 l
+0.882 2.954 l
+h
+4.466 -1.279 m
+4.436 -1.213 4.414 -1.103 4.406 -0.956 c
+4.23 -1.213 4.009 -1.338 3.745 -1.338 c
+3.469 -1.338 3.252 -1.264 3.098 -1.118 c
+2.951 -0.963 2.878 -0.746 2.878 -0.47 c
+2.878 -0.169 2.98 0.073 3.186 0.249 c
+3.392 0.434 3.675 0.529 4.039 0.529 c
+4.391 0.529 l
+4.391 0.852 l
+4.391 1.029 4.351 1.151 4.274 1.22 c
+4.193 1.297 4.075 1.338 3.921 1.338 c
+3.774 1.338 3.649 1.294 3.554 1.205 c
+3.466 1.117 3.421 1.007 3.421 0.881 c
+2.937 0.881 l
+2.937 1.029 2.98 1.168 3.069 1.308 c
+3.157 1.455 3.275 1.565 3.421 1.646 c
+3.576 1.723 3.749 1.764 3.936 1.764 c
+4.248 1.764 4.484 1.683 4.642 1.529 c
+4.796 1.382 4.877 1.161 4.877 0.867 c
+4.877 -0.632 l
+4.884 -0.867 4.921 -1.07 4.979 -1.235 c
+4.979 -1.279 l
+h
+3.818 -0.897 m
+3.936 -0.897 4.046 -0.864 4.156 -0.794 c
+4.263 -0.728 4.341 -0.643 4.391 -0.544 c
+4.391 0.162 l
+4.127 0.162 l
+3.892 0.162 3.705 0.11 3.568 0.014 c
+3.44 -0.085 3.377 -0.228 3.377 -0.412 c
+3.377 -0.58 3.407 -0.702 3.466 -0.779 c
+3.531 -0.86 3.649 -0.897 3.818 -0.897 c
+5.913 1.705 m
+5.928 1.382 l
+6.112 1.635 6.354 1.764 6.648 1.764 c
+7.177 1.764 7.446 1.411 7.456 0.706 c
+7.456 -1.279 l
+6.972 -1.279 l
+6.972 0.676 l
+6.972 0.912 6.931 1.076 6.854 1.176 c
+6.773 1.271 6.656 1.323 6.501 1.323 c
+6.384 1.323 6.273 1.282 6.178 1.205 c
+6.078 1.124 6.001 1.018 5.943 0.881 c
+5.943 -1.279 l
+5.457 -1.279 l
+5.457 1.705 l
+h
+7.909 0.353 m
+7.909 0.812 7.99 1.161 8.158 1.396 c
+8.335 1.639 8.584 1.764 8.908 1.764 c
+9.209 1.764 9.441 1.631 9.599 1.367 c
+9.628 1.705 l
+10.07 1.705 l
+10.07 -1.309 l
+10.07 -1.679 9.97 -1.962 9.775 -2.161 c
+9.588 -2.356 9.327 -2.455 8.996 -2.455 c
+8.849 -2.455 8.68 -2.415 8.497 -2.338 c
+8.309 -2.267 8.173 -2.18 8.085 -2.072 c
+8.276 -1.735 l
+8.482 -1.941 8.706 -2.043 8.952 -2.043 c
+9.353 -2.043 9.559 -1.816 9.569 -1.367 c
+9.569 -0.985 l
+9.411 -1.22 9.191 -1.338 8.908 -1.338 c
+8.592 -1.338 8.349 -1.22 8.173 -0.985 c
+8.004 -0.75 7.916 -0.419 7.909 0.014 c
+h
+8.393 0.073 m
+8.393 -0.261 8.441 -0.507 8.541 -0.661 c
+8.636 -0.819 8.798 -0.897 9.025 -0.897 c
+9.268 -0.897 9.452 -0.775 9.569 -0.53 c
+9.569 0.955 l
+9.452 1.198 9.276 1.323 9.04 1.323 c
+8.813 1.323 8.651 1.242 8.555 1.087 c
+8.456 0.929 8.401 0.69 8.393 0.367 c
+h
+11.66 -1.338 m
+11.286 -1.338 11.003 -1.231 10.808 -1.014 c
+10.61 -0.79 10.514 -0.463 10.514 -0.029 c
+10.514 0.338 l
+10.514 0.779 10.606 1.124 10.793 1.382 c
+10.988 1.635 11.263 1.764 11.616 1.764 c
+11.958 1.764 12.212 1.65 12.381 1.425 c
+12.557 1.198 12.649 0.852 12.659 0.382 c
+12.659 0.073 l
+10.999 0.073 l
+10.999 0 l
+10.999 -0.324 11.057 -0.559 11.175 -0.706 c
+11.293 -0.846 11.462 -0.912 11.69 -0.912 c
+11.836 -0.912 11.961 -0.889 12.072 -0.838 c
+12.179 -0.779 12.281 -0.691 12.381 -0.574 c
+12.63 -0.882 l
+12.424 -1.187 12.102 -1.338 11.66 -1.338 c
+11.616 1.338 m
+11.41 1.338 11.256 1.268 11.161 1.132 c
+11.061 0.992 11.007 0.779 10.999 0.484 c
+12.175 0.484 l
+12.175 0.559 l
+12.152 0.831 12.102 1.029 12.013 1.147 c
+11.925 1.271 11.793 1.338 11.616 1.338 c
+14.512 -0.515 m
+14.512 -0.408 14.471 -0.32 14.394 -0.25 c
+14.313 -0.173 14.163 -0.085 13.939 0.014 c
+13.675 0.121 13.486 0.213 13.38 0.293 c
+13.27 0.371 13.193 0.459 13.145 0.559 c
+13.093 0.654 13.072 0.771 13.072 0.912 c
+13.072 1.153 13.16 1.356 13.336 1.514 c
+13.513 1.679 13.737 1.764 14.012 1.764 c
+14.306 1.764 14.541 1.675 14.718 1.5 c
+14.894 1.33 14.982 1.117 14.982 0.852 c
+14.498 0.852 l
+14.498 0.989 14.446 1.103 14.35 1.19 c
+14.263 1.286 14.148 1.338 14.012 1.338 c
+13.866 1.338 13.752 1.297 13.675 1.22 c
+13.594 1.151 13.557 1.051 13.557 0.926 c
+13.557 0.827 13.586 0.75 13.644 0.69 c
+13.704 0.632 13.843 0.551 14.071 0.455 c
+14.431 0.309 14.677 0.166 14.806 0.029 c
+14.942 -0.1 15.011 -0.272 15.011 -0.485 c
+15.011 -0.742 14.916 -0.948 14.733 -1.103 c
+14.556 -1.261 14.321 -1.338 14.027 -1.338 c
+13.711 -1.338 13.457 -1.249 13.263 -1.073 c
+13.075 -0.889 12.983 -0.658 12.983 -0.382 c
+13.469 -0.382 l
+13.476 -0.551 13.527 -0.684 13.615 -0.779 c
+13.711 -0.867 13.85 -0.912 14.027 -0.912 c
+14.182 -0.912 14.299 -0.879 14.38 -0.809 c
+14.468 -0.742 14.512 -0.643 14.512 -0.515 c
+17.702 -0.912 m
+17.867 -0.912 17.999 -0.864 18.099 -0.765 c
+18.194 -0.669 18.249 -0.526 18.261 -0.339 c
+18.716 -0.339 l
+18.705 -0.625 18.602 -0.864 18.407 -1.058 c
+18.22 -1.246 17.985 -1.338 17.702 -1.338 c
+17.338 -1.338 17.058 -1.22 16.864 -0.985 c
+16.665 -0.75 16.57 -0.405 16.57 0.058 c
+16.57 0.382 l
+16.57 0.831 16.661 1.176 16.85 1.411 c
+17.044 1.646 17.326 1.764 17.702 1.764 c
+18.003 1.764 18.246 1.664 18.422 1.469 c
+18.606 1.271 18.705 1.007 18.716 0.676 c
+18.261 0.676 l
+18.238 0.9 18.18 1.066 18.084 1.176 c
+17.995 1.282 17.867 1.338 17.702 1.338 c
+17.485 1.338 17.324 1.264 17.216 1.117 c
+17.118 0.977 17.062 0.75 17.055 0.426 c
+17.055 0.044 l
+17.055 -0.309 17.103 -0.559 17.202 -0.706 c
+17.309 -0.846 17.474 -0.912 17.702 -0.912 c
+19.009 0.353 m
+19.009 0.783 19.113 1.124 19.319 1.382 c
+19.532 1.635 19.811 1.764 20.156 1.764 c
+20.498 1.764 20.773 1.635 20.979 1.382 c
+21.193 1.135 21.307 0.801 21.318 0.382 c
+21.318 0.073 l
+21.318 -0.36 21.207 -0.702 20.995 -0.956 c
+20.788 -1.213 20.509 -1.338 20.156 -1.338 c
+19.811 -1.338 19.539 -1.216 19.333 -0.97 c
+19.127 -0.728 19.017 -0.393 19.009 0.029 c
+h
+19.495 0.073 m
+19.495 -0.243 19.554 -0.485 19.672 -0.661 c
+19.796 -0.831 19.958 -0.912 20.156 -0.912 c
+20.586 -0.912 20.811 -0.603 20.833 0.014 c
+20.833 0.353 l
+20.833 0.654 20.767 0.897 20.642 1.072 c
+20.524 1.249 20.362 1.338 20.156 1.338 c
+19.958 1.338 19.796 1.249 19.672 1.072 c
+19.554 0.897 19.495 0.654 19.495 0.353 c
+h
+22.215 1.705 m
+22.229 1.425 l
+22.406 1.65 22.645 1.764 22.949 1.764 c
+23.28 1.764 23.512 1.617 23.64 1.323 c
+23.824 1.617 24.085 1.764 24.419 1.764 c
+24.978 1.764 25.261 1.419 25.272 0.735 c
+25.272 -1.279 l
+24.787 -1.279 l
+24.787 0.69 l
+24.787 0.904 24.746 1.062 24.669 1.161 c
+24.588 1.268 24.456 1.323 24.272 1.323 c
+24.125 1.323 24.008 1.264 23.919 1.147 c
+23.831 1.036 23.776 0.897 23.757 0.72 c
+23.757 -1.279 l
+23.273 -1.279 l
+23.273 0.706 l
+23.262 1.117 23.089 1.323 22.758 1.323 c
+22.512 1.323 22.34 1.198 22.244 0.955 c
+22.244 -1.279 l
+21.758 -1.279 l
+21.758 1.705 l
+h
+26.176 1.705 m
+26.19 1.425 l
+26.367 1.65 26.606 1.764 26.911 1.764 c
+27.241 1.764 27.473 1.617 27.601 1.323 c
+27.786 1.617 28.046 1.764 28.38 1.764 c
+28.939 1.764 29.222 1.419 29.233 0.735 c
+29.233 -1.279 l
+28.748 -1.279 l
+28.748 0.69 l
+28.748 0.904 28.708 1.062 28.63 1.161 c
+28.549 1.268 28.417 1.323 28.233 1.323 c
+28.087 1.323 27.969 1.264 27.881 1.147 c
+27.792 1.036 27.738 0.897 27.719 0.72 c
+27.719 -1.279 l
+27.234 -1.279 l
+27.234 0.706 l
+27.223 1.117 27.05 1.323 26.72 1.323 c
+26.473 1.323 26.3 1.198 26.205 0.955 c
+26.205 -1.279 l
+25.72 -1.279 l
+25.72 1.705 l
+h
+30.211 -1.279 -0.5 2.984 re
+30.24 2.499 m
+30.24 2.41 30.215 2.337 30.167 2.278 c
+30.126 2.227 30.057 2.205 29.961 2.205 c
+29.872 2.205 29.803 2.227 29.755 2.278 c
+29.714 2.337 29.696 2.404 29.696 2.484 c
+29.696 2.572 29.714 2.645 29.755 2.705 c
+29.803 2.763 29.872 2.793 29.961 2.793 c
+30.057 2.793 30.126 2.763 30.167 2.705 c
+30.215 2.645 30.24 2.576 30.24 2.499 c
+31.515 2.425 m
+31.515 1.705 l
+31.971 1.705 l
+31.971 1.308 l
+31.515 1.308 l
+31.515 -0.544 l
+31.515 -0.661 31.534 -0.75 31.574 -0.809 c
+31.611 -0.867 31.68 -0.897 31.78 -0.897 c
+31.838 -0.897 31.901 -0.889 31.971 -0.867 c
+31.971 -1.279 l
+31.853 -1.316 31.74 -1.338 31.632 -1.338 c
+31.435 -1.338 31.283 -1.272 31.177 -1.132 c
+31.078 -0.996 31.03 -0.802 31.03 -0.544 c
+31.03 1.308 l
+30.574 1.308 l
+30.574 1.705 l
+31.03 1.705 l
+31.03 2.425 l
+h
+33.496 -1.338 m
+33.121 -1.338 32.838 -1.231 32.644 -1.014 c
+32.445 -0.79 32.349 -0.463 32.349 -0.029 c
+32.349 0.338 l
+32.349 0.779 32.441 1.124 32.629 1.382 c
+32.823 1.635 33.099 1.764 33.452 1.764 c
+33.793 1.764 34.047 1.65 34.217 1.425 c
+34.392 1.198 34.485 0.852 34.495 0.382 c
+34.495 0.073 l
+32.835 0.073 l
+32.835 0 l
+32.835 -0.324 32.893 -0.559 33.01 -0.706 c
+33.128 -0.846 33.297 -0.912 33.525 -0.912 c
+33.672 -0.912 33.797 -0.889 33.907 -0.838 c
+34.014 -0.779 34.117 -0.691 34.217 -0.574 c
+34.466 -0.882 l
+34.26 -1.187 33.937 -1.338 33.496 -1.338 c
+33.452 1.338 m
+33.246 1.338 33.091 1.268 32.996 1.132 c
+32.897 0.992 32.842 0.779 32.835 0.484 c
+34.011 0.484 l
+34.011 0.559 l
+33.988 0.831 33.937 1.029 33.849 1.147 c
+33.76 1.271 33.629 1.338 33.452 1.338 c
+34.805 0.353 m
+34.805 0.812 34.884 1.161 35.054 1.396 c
+35.231 1.639 35.48 1.764 35.804 1.764 c
+36.087 1.764 36.307 1.646 36.465 1.411 c
+36.465 2.954 l
+36.95 2.954 l
+36.95 -1.279 l
+36.509 -1.279 l
+36.48 -0.956 l
+36.322 -1.213 36.098 -1.338 35.804 -1.338 c
+35.487 -1.338 35.245 -1.22 35.069 -0.985 c
+34.892 -0.742 34.805 -0.397 34.805 0.044 c
+h
+35.289 0.073 m
+35.289 -0.261 35.337 -0.507 35.436 -0.661 c
+35.532 -0.819 35.694 -0.897 35.921 -0.897 c
+36.164 -0.897 36.347 -0.779 36.465 -0.544 c
+36.465 0.97 l
+36.336 1.205 36.156 1.323 35.921 1.323 c
+35.694 1.323 35.532 1.242 35.436 1.087 c
+35.337 0.929 35.289 0.69 35.289 0.367 c
+h
+39.21 1.396 m
+39.393 1.639 39.629 1.764 39.916 1.764 c
+40.445 1.764 40.713 1.411 40.724 0.706 c
+40.724 -1.279 l
+40.239 -1.279 l
+40.239 0.676 l
+40.239 0.912 40.199 1.076 40.122 1.176 c
+40.041 1.271 39.923 1.323 39.769 1.323 c
+39.651 1.323 39.541 1.282 39.445 1.205 c
+39.346 1.124 39.269 1.018 39.21 0.881 c
+39.21 -1.279 l
+38.726 -1.279 l
+38.726 2.954 l
+39.21 2.954 l
+h
+42.323 -1.338 m
+41.948 -1.338 41.664 -1.231 41.47 -1.014 c
+41.272 -0.79 41.176 -0.463 41.176 -0.029 c
+41.176 0.338 l
+41.176 0.779 41.268 1.124 41.456 1.382 c
+41.65 1.635 41.926 1.764 42.279 1.764 c
+42.62 1.764 42.874 1.65 43.043 1.425 c
+43.219 1.198 43.311 0.852 43.322 0.382 c
+43.322 0.073 l
+41.662 0.073 l
+41.662 0 l
+41.662 -0.324 41.72 -0.559 41.837 -0.706 c
+41.955 -0.846 42.124 -0.912 42.352 -0.912 c
+42.499 -0.912 42.624 -0.889 42.734 -0.838 c
+42.84 -0.779 42.944 -0.691 43.043 -0.574 c
+43.293 -0.882 l
+43.087 -1.187 42.763 -1.338 42.323 -1.338 c
+42.279 1.338 m
+42.073 1.338 41.918 1.268 41.822 1.132 c
+41.724 0.992 41.668 0.779 41.662 0.484 c
+42.838 0.484 l
+42.838 0.559 l
+42.815 0.831 42.763 1.029 42.676 1.147 c
+42.587 1.271 42.455 1.338 42.279 1.338 c
+44.968 1.249 m
+44.899 1.257 44.825 1.264 44.748 1.264 c
+44.49 1.264 44.314 1.124 44.218 0.852 c
+44.218 -1.279 l
+43.734 -1.279 l
+43.734 1.705 l
+44.204 1.705 l
+44.218 1.396 l
+44.344 1.639 44.527 1.764 44.762 1.764 c
+44.84 1.764 44.902 1.749 44.954 1.72 c
+h
+46.346 -1.338 m
+45.972 -1.338 45.689 -1.231 45.494 -1.014 c
+45.296 -0.79 45.2 -0.463 45.2 -0.029 c
+45.2 0.338 l
+45.2 0.779 45.292 1.124 45.479 1.382 c
+45.674 1.635 45.949 1.764 46.302 1.764 c
+46.644 1.764 46.898 1.65 47.067 1.425 c
+47.243 1.198 47.335 0.852 47.346 0.382 c
+47.346 0.073 l
+45.685 0.073 l
+45.685 0 l
+45.685 -0.324 45.743 -0.559 45.861 -0.706 c
+45.979 -0.846 46.148 -0.912 46.376 -0.912 c
+46.523 -0.912 46.647 -0.889 46.758 -0.838 c
+46.865 -0.779 46.967 -0.691 47.067 -0.574 c
+47.316 -0.882 l
+47.111 -1.187 46.788 -1.338 46.346 -1.338 c
+46.302 1.338 m
+46.096 1.338 45.942 1.268 45.847 1.132 c
+45.747 0.992 45.693 0.779 45.685 0.484 c
+46.861 0.484 l
+46.861 0.559 l
+46.838 0.831 46.788 1.029 46.699 1.147 c
+46.611 1.271 46.479 1.338 46.302 1.338 c
+f
+Q
+ endstream endobj 32 0 obj <</BBox[592.773 327.187 617.18 322.836]/Group 68 0 R/Length 5562/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 595.2274 323.7479 cm
+0 0 m
+0.456 2.131 l
+0.941 2.131 l
+0.206 -0.853 l
+-0.176 -0.853 l
+-0.764 1.278 l
+-1.338 -0.853 l
+-1.72 -0.853 l
+-2.454 2.131 l
+-1.97 2.131 l
+-1.5 0.058 l
+-0.955 2.131 l
+-0.573 2.131 l
+h
+1.735 -0.853 -0.5 2.984 re
+1.764 2.925 m
+1.764 2.836 1.738 2.763 1.69 2.705 c
+1.65 2.653 1.58 2.631 1.484 2.631 c
+1.397 2.631 1.326 2.653 1.279 2.705 c
+1.239 2.763 1.22 2.83 1.22 2.91 c
+1.22 2.998 1.239 3.072 1.279 3.131 c
+1.326 3.189 1.397 3.219 1.484 3.219 c
+1.58 3.219 1.65 3.189 1.69 3.131 c
+1.738 3.072 1.764 3.002 1.764 2.925 c
+2.94 -0.853 -0.5 4.233 re
+4.145 -0.853 -0.5 4.233 re
+8.183 0.5 m
+8.183 0.029 8.1 -0.324 7.934 -0.559 c
+7.765 -0.794 7.522 -0.912 7.199 -0.912 c
+6.883 -0.912 6.648 -0.775 6.494 -0.5 c
+6.464 -0.853 l
+6.024 -0.853 l
+6.024 3.38 l
+6.508 3.38 l
+6.508 1.808 l
+6.662 2.061 6.894 2.19 7.199 2.19 c
+7.522 2.19 7.765 2.072 7.934 1.837 c
+8.1 1.602 8.183 1.253 8.183 0.793 c
+h
+7.699 0.779 m
+7.699 1.132 7.647 1.381 7.552 1.529 c
+7.453 1.675 7.291 1.749 7.067 1.749 c
+6.82 1.749 6.633 1.61 6.508 1.338 c
+6.508 -0.073 l
+6.626 -0.339 6.817 -0.47 7.082 -0.47 c
+7.294 -0.47 7.453 -0.397 7.552 -0.25 c
+7.647 -0.096 7.699 0.147 7.699 0.47 c
+h
+9.683 -0.912 m
+9.309 -0.912 9.025 -0.805 8.831 -0.588 c
+8.632 -0.364 8.536 -0.037 8.536 0.397 c
+8.536 0.764 l
+8.536 1.205 8.628 1.55 8.816 1.808 c
+9.01 2.061 9.286 2.19 9.639 2.19 c
+9.981 2.19 10.234 2.076 10.404 1.851 c
+10.58 1.624 10.672 1.278 10.683 0.808 c
+10.683 0.5 l
+9.022 0.5 l
+9.022 0.426 l
+9.022 0.103 9.081 -0.133 9.199 -0.279 c
+9.316 -0.42 9.484 -0.485 9.712 -0.485 c
+9.86 -0.485 9.985 -0.463 10.095 -0.412 c
+10.201 -0.353 10.304 -0.265 10.404 -0.148 c
+10.653 -0.456 l
+10.448 -0.761 10.124 -0.912 9.683 -0.912 c
+9.639 1.764 m
+9.434 1.764 9.279 1.694 9.183 1.558 c
+9.084 1.419 9.029 1.205 9.022 0.911 c
+10.198 0.911 l
+10.198 0.985 l
+10.176 1.257 10.124 1.455 10.036 1.573 c
+9.947 1.697 9.816 1.764 9.639 1.764 c
+13.74 -0.088 m
+13.74 0.018 13.7 0.106 13.623 0.176 c
+13.542 0.253 13.391 0.342 13.167 0.44 c
+12.902 0.548 12.715 0.639 12.609 0.72 c
+12.498 0.797 12.421 0.885 12.374 0.985 c
+12.322 1.08 12.299 1.198 12.299 1.338 c
+12.299 1.579 12.388 1.782 12.565 1.94 c
+12.74 2.105 12.965 2.19 13.24 2.19 c
+13.534 2.19 13.77 2.102 13.945 1.926 c
+14.122 1.756 14.211 1.543 14.211 1.278 c
+13.725 1.278 l
+13.725 1.415 13.674 1.529 13.579 1.616 c
+13.49 1.712 13.376 1.764 13.24 1.764 c
+13.093 1.764 12.979 1.723 12.902 1.646 c
+12.821 1.577 12.785 1.477 12.785 1.352 c
+12.785 1.253 12.814 1.176 12.873 1.117 c
+12.931 1.058 13.072 0.977 13.299 0.881 c
+13.66 0.735 13.906 0.592 14.034 0.455 c
+14.17 0.326 14.24 0.154 14.24 -0.059 c
+14.24 -0.316 14.144 -0.522 13.961 -0.676 c
+13.785 -0.834 13.549 -0.912 13.255 -0.912 c
+12.939 -0.912 12.686 -0.823 12.491 -0.647 c
+12.303 -0.463 12.212 -0.231 12.212 0.044 c
+12.696 0.044 l
+12.704 -0.125 12.755 -0.258 12.844 -0.353 c
+12.939 -0.441 13.079 -0.485 13.255 -0.485 c
+13.409 -0.485 13.527 -0.452 13.608 -0.383 c
+13.696 -0.316 13.74 -0.217 13.74 -0.088 c
+16.224 -0.853 m
+16.195 -0.786 16.173 -0.676 16.166 -0.53 c
+15.989 -0.786 15.769 -0.912 15.504 -0.912 c
+15.229 -0.912 15.011 -0.838 14.857 -0.691 c
+14.71 -0.537 14.637 -0.32 14.637 -0.044 c
+14.637 0.257 14.739 0.5 14.945 0.675 c
+15.152 0.86 15.434 0.955 15.798 0.955 c
+16.151 0.955 l
+16.151 1.278 l
+16.151 1.455 16.11 1.577 16.033 1.646 c
+15.952 1.723 15.834 1.764 15.68 1.764 c
+15.534 1.764 15.408 1.72 15.313 1.631 c
+15.225 1.543 15.181 1.433 15.181 1.308 c
+14.695 1.308 l
+14.695 1.455 14.739 1.595 14.828 1.734 c
+14.916 1.882 15.034 1.992 15.181 2.072 c
+15.335 2.15 15.508 2.19 15.695 2.19 c
+16.008 2.19 16.243 2.109 16.401 1.955 c
+16.555 1.808 16.636 1.587 16.636 1.294 c
+16.636 -0.206 l
+16.644 -0.441 16.68 -0.643 16.739 -0.809 c
+16.739 -0.853 l
+h
+15.578 -0.47 m
+15.695 -0.47 15.805 -0.437 15.915 -0.368 c
+16.023 -0.302 16.1 -0.217 16.151 -0.118 c
+16.151 0.588 l
+15.886 0.588 l
+15.651 0.588 15.464 0.536 15.327 0.44 c
+15.199 0.342 15.136 0.199 15.136 0.014 c
+15.136 -0.154 15.166 -0.276 15.225 -0.353 c
+15.291 -0.434 15.408 -0.47 15.578 -0.47 c
+17.422 -0.853 m
+17.422 1.734 l
+17.041 1.734 l
+17.041 2.131 l
+17.422 2.131 l
+17.422 2.469 l
+17.43 2.771 17.511 3.006 17.658 3.175 c
+17.804 3.351 18.014 3.439 18.29 3.439 c
+18.385 3.439 18.485 3.424 18.583 3.395 c
+18.554 2.984 l
+18.485 2.991 18.411 2.998 18.334 2.998 c
+18.058 2.998 17.922 2.8 17.922 2.41 c
+17.922 2.131 l
+18.422 2.131 l
+18.422 1.734 l
+17.922 1.734 l
+17.922 -0.853 l
+h
+19.881 -0.912 m
+19.506 -0.912 19.223 -0.805 19.028 -0.588 c
+18.83 -0.364 18.734 -0.037 18.734 0.397 c
+18.734 0.764 l
+18.734 1.205 18.826 1.55 19.013 1.808 c
+19.208 2.061 19.484 2.19 19.836 2.19 c
+20.178 2.19 20.432 2.076 20.601 1.851 c
+20.777 1.624 20.869 1.278 20.881 0.808 c
+20.881 0.5 l
+19.219 0.5 l
+19.219 0.426 l
+19.219 0.103 19.278 -0.133 19.395 -0.279 c
+19.513 -0.42 19.682 -0.485 19.91 -0.485 c
+20.057 -0.485 20.182 -0.463 20.293 -0.412 c
+20.399 -0.353 20.501 -0.265 20.601 -0.148 c
+20.851 -0.456 l
+20.645 -0.761 20.322 -0.912 19.881 -0.912 c
+19.836 1.764 m
+19.63 1.764 19.476 1.694 19.381 1.558 c
+19.281 1.419 19.227 1.205 19.219 0.911 c
+20.395 0.911 l
+20.395 0.985 l
+20.373 1.257 20.322 1.455 20.233 1.573 c
+20.145 1.697 20.013 1.764 19.836 1.764 c
+21.321 -0.588 m
+21.321 -0.5 21.343 -0.426 21.394 -0.368 c
+21.454 -0.309 21.531 -0.279 21.629 -0.279 c
+21.737 -0.279 21.814 -0.309 21.865 -0.368 c
+21.924 -0.426 21.953 -0.5 21.953 -0.588 c
+21.953 -0.669 21.924 -0.736 21.865 -0.794 c
+21.814 -0.853 21.737 -0.882 21.629 -0.882 c
+21.531 -0.882 21.454 -0.853 21.394 -0.794 c
+21.343 -0.736 21.321 -0.669 21.321 -0.588 c
+f
+Q
+ endstream endobj 33 0 obj <</BBox[579.503 320.602 630.821 315.104]/Group 69 0 R/Length 14034/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+580.003 316.31 -0.5 4.013 re
+580.94 316.31 m
+580.94 318.897 l
+580.557 318.897 l
+580.557 319.294 l
+580.94 319.294 l
+580.94 319.632 l
+580.948 319.933 581.028 320.168 581.176 320.338 c
+581.322 320.514 581.532 320.602 581.808 320.602 c
+581.903 320.602 582.003 320.587 582.101 320.558 c
+582.072 320.147 l
+582.003 320.153 581.929 320.161 581.852 320.161 c
+581.576 320.161 581.44 319.962 581.44 319.573 c
+581.44 319.294 l
+581.939 319.294 l
+581.939 318.897 l
+581.44 318.897 l
+581.44 316.31 l
+h
+584.413 317.119 m
+584.956 319.294 l
+585.471 319.294 l
+584.501 315.883 l
+584.431 315.63 584.328 315.439 584.193 315.31 c
+584.052 315.174 583.902 315.104 583.736 315.104 c
+583.667 315.104 583.582 315.119 583.487 315.149 c
+583.487 315.561 l
+583.589 315.546 l
+583.726 315.546 583.832 315.582 583.913 315.648 c
+584.002 315.719 584.067 315.836 584.119 316.001 c
+584.207 316.34 l
+583.34 319.294 l
+583.869 319.294 l
+h
+585.652 317.942 m
+585.652 318.372 585.754 318.713 585.96 318.971 c
+586.173 319.224 586.452 319.353 586.797 319.353 c
+587.14 319.353 587.415 319.224 587.621 318.971 c
+587.834 318.724 587.948 318.389 587.959 317.971 c
+587.959 317.662 l
+587.959 317.229 587.848 316.887 587.636 316.633 c
+587.43 316.376 587.15 316.251 586.797 316.251 c
+586.452 316.251 586.18 316.373 585.974 316.619 c
+585.769 316.861 585.658 317.196 585.652 317.618 c
+h
+586.136 317.662 m
+586.136 317.346 586.195 317.103 586.313 316.928 c
+586.437 316.758 586.599 316.677 586.797 316.677 c
+587.227 316.677 587.452 316.986 587.474 317.603 c
+587.474 317.942 l
+587.474 318.243 587.408 318.485 587.283 318.661 c
+587.165 318.838 587.003 318.927 586.797 318.927 c
+586.599 318.927 586.437 318.838 586.313 318.661 c
+586.195 318.485 586.136 318.243 586.136 317.942 c
+h
+589.914 316.575 m
+589.756 316.357 589.521 316.251 589.209 316.251 c
+588.944 316.251 588.738 316.343 588.591 316.531 c
+588.451 316.714 588.385 316.99 588.385 317.354 c
+588.385 319.294 l
+588.87 319.294 l
+588.87 317.383 l
+588.87 316.92 589.01 316.692 589.297 316.692 c
+589.59 316.692 589.789 316.824 589.899 317.089 c
+589.899 319.294 l
+590.399 319.294 l
+590.399 316.31 l
+589.928 316.31 l
+h
+593.685 316.31 m
+593.654 316.376 593.633 316.486 593.625 316.633 c
+593.449 316.376 593.228 316.251 592.964 316.251 c
+592.688 316.251 592.472 316.325 592.317 316.471 c
+592.17 316.626 592.097 316.843 592.097 317.119 c
+592.097 317.42 592.2 317.662 592.405 317.838 c
+592.611 318.023 592.894 318.118 593.258 318.118 c
+593.611 318.118 l
+593.611 318.441 l
+593.611 318.618 593.571 318.739 593.493 318.809 c
+593.413 318.886 593.295 318.927 593.141 318.927 c
+592.993 318.927 592.868 318.882 592.773 318.794 c
+592.685 318.706 592.64 318.596 592.64 318.47 c
+592.156 318.47 l
+592.156 318.618 592.2 318.757 592.288 318.897 c
+592.376 319.044 592.494 319.154 592.64 319.235 c
+592.795 319.312 592.968 319.353 593.155 319.353 c
+593.467 319.353 593.702 319.272 593.86 319.118 c
+594.015 318.971 594.096 318.75 594.096 318.456 c
+594.096 316.957 l
+594.103 316.722 594.14 316.519 594.198 316.354 c
+594.198 316.31 l
+h
+593.037 316.692 m
+593.155 316.692 593.265 316.725 593.376 316.795 c
+593.482 316.861 593.559 316.945 593.611 317.045 c
+593.611 317.751 l
+593.346 317.751 l
+593.111 317.751 592.923 317.699 592.787 317.603 c
+592.659 317.504 592.596 317.361 592.596 317.177 c
+592.596 317.008 592.626 316.887 592.685 316.81 c
+592.75 316.729 592.868 316.692 593.037 316.692 c
+595.911 318.838 m
+595.842 318.846 595.767 318.853 595.69 318.853 c
+595.433 318.853 595.257 318.713 595.161 318.441 c
+595.161 316.31 l
+594.676 316.31 l
+594.676 319.294 l
+595.146 319.294 l
+595.161 318.985 l
+595.287 319.228 595.47 319.353 595.705 319.353 c
+595.782 319.353 595.845 319.338 595.896 319.309 c
+h
+597.286 316.251 m
+596.91 316.251 596.628 316.357 596.433 316.575 c
+596.235 316.799 596.139 317.126 596.139 317.56 c
+596.139 317.927 l
+596.139 318.368 596.231 318.713 596.418 318.971 c
+596.613 319.224 596.889 319.353 597.242 319.353 c
+597.583 319.353 597.837 319.239 598.005 319.014 c
+598.182 318.786 598.274 318.441 598.285 317.971 c
+598.285 317.662 l
+596.624 317.662 l
+596.624 317.589 l
+596.624 317.265 596.683 317.03 596.8 316.883 c
+596.918 316.743 597.087 316.677 597.315 316.677 c
+597.462 316.677 597.587 316.7 597.697 316.751 c
+597.804 316.81 597.907 316.897 598.005 317.015 c
+598.256 316.706 l
+598.05 316.402 597.726 316.251 597.286 316.251 c
+597.242 318.927 m
+597.035 318.927 596.881 318.857 596.785 318.721 c
+596.686 318.581 596.631 318.368 596.624 318.073 c
+597.8 318.073 l
+597.8 318.148 l
+597.778 318.42 597.726 318.618 597.638 318.736 c
+597.55 318.86 597.417 318.927 597.242 318.927 c
+599.799 317.942 m
+599.799 318.401 599.88 318.75 600.049 318.985 c
+600.226 319.228 600.475 319.353 600.798 319.353 c
+601.082 319.353 601.302 319.235 601.46 319 c
+601.46 320.543 l
+601.945 320.543 l
+601.945 316.31 l
+601.504 316.31 l
+601.475 316.633 l
+601.317 316.376 601.093 316.251 600.798 316.251 c
+600.482 316.251 600.24 316.369 600.064 316.604 c
+599.887 316.847 599.799 317.192 599.799 317.633 c
+h
+600.284 317.662 m
+600.284 317.328 600.332 317.082 600.432 316.928 c
+600.527 316.77 600.688 316.692 600.916 316.692 c
+601.159 316.692 601.342 316.81 601.46 317.045 c
+601.46 318.559 l
+601.332 318.794 601.151 318.912 600.916 318.912 c
+600.688 318.912 600.527 318.831 600.432 318.676 c
+600.332 318.518 600.284 318.279 600.284 317.956 c
+h
+602.412 317.942 m
+602.412 318.372 602.514 318.713 602.72 318.971 c
+602.934 319.224 603.213 319.353 603.559 319.353 c
+603.9 319.353 604.176 319.224 604.382 318.971 c
+604.594 318.724 604.708 318.389 604.719 317.971 c
+604.719 317.662 l
+604.719 317.229 604.609 316.887 604.396 316.633 c
+604.191 316.376 603.911 316.251 603.559 316.251 c
+603.213 316.251 602.94 316.373 602.735 316.619 c
+602.529 316.861 602.419 317.196 602.412 317.618 c
+h
+602.897 317.662 m
+602.897 317.346 602.956 317.103 603.073 316.928 c
+603.198 316.758 603.36 316.677 603.559 316.677 c
+603.988 316.677 604.212 316.986 604.234 317.603 c
+604.234 317.942 l
+604.234 318.243 604.168 318.485 604.043 318.661 c
+603.925 318.838 603.764 318.927 603.559 318.927 c
+603.36 318.927 603.198 318.838 603.073 318.661 c
+602.956 318.485 602.897 318.243 602.897 317.942 c
+h
+605.689 316.31 -0.5 2.984 re
+605.719 320.088 m
+605.719 319.999 605.693 319.926 605.645 319.867 c
+605.606 319.816 605.535 319.794 605.44 319.794 c
+605.352 319.794 605.282 319.816 605.234 319.867 c
+605.194 319.926 605.175 319.992 605.175 320.072 c
+605.175 320.161 605.194 320.234 605.234 320.294 c
+605.282 320.352 605.352 320.382 605.44 320.382 c
+605.535 320.382 605.606 320.352 605.645 320.294 c
+605.693 320.234 605.719 320.165 605.719 320.088 c
+606.818 319.294 m
+606.832 318.971 l
+607.017 319.224 607.258 319.353 607.553 319.353 c
+608.082 319.353 608.35 319 608.361 318.294 c
+608.361 316.31 l
+607.877 316.31 l
+607.877 318.265 l
+607.877 318.5 607.836 318.665 607.759 318.765 c
+607.678 318.86 607.56 318.912 607.406 318.912 c
+607.289 318.912 607.178 318.871 607.083 318.794 c
+606.983 318.713 606.906 318.607 606.847 318.47 c
+606.847 316.31 l
+606.362 316.31 l
+606.362 319.294 l
+h
+608.814 317.942 m
+608.814 318.401 608.894 318.75 609.063 318.985 c
+609.24 319.228 609.489 319.353 609.813 319.353 c
+610.114 319.353 610.346 319.22 610.504 318.956 c
+610.533 319.294 l
+610.974 319.294 l
+610.974 316.28 l
+610.974 315.91 610.875 315.627 610.68 315.428 c
+610.493 315.233 610.231 315.134 609.901 315.134 c
+609.754 315.134 609.585 315.174 609.402 315.251 c
+609.213 315.322 609.078 315.409 608.989 315.516 c
+609.18 315.854 l
+609.386 315.648 609.61 315.546 609.857 315.546 c
+610.258 315.546 610.464 315.773 610.474 316.222 c
+610.474 316.604 l
+610.316 316.369 610.096 316.251 609.813 316.251 c
+609.497 316.251 609.254 316.369 609.078 316.604 c
+608.909 316.839 608.82 317.17 608.814 317.603 c
+h
+609.298 317.662 m
+609.298 317.328 609.346 317.082 609.446 316.928 c
+609.541 316.77 609.703 316.692 609.93 316.692 c
+610.173 316.692 610.356 316.814 610.474 317.059 c
+610.474 318.544 l
+610.356 318.786 610.18 318.912 609.945 318.912 c
+609.718 318.912 609.556 318.831 609.46 318.676 c
+609.361 318.518 609.306 318.279 609.298 317.956 c
+h
+614.873 317.662 m
+614.873 317.192 614.788 316.839 614.623 316.604 c
+614.454 316.369 614.211 316.251 613.888 316.251 c
+613.572 316.251 613.337 316.388 613.182 316.662 c
+613.153 316.31 l
+612.712 316.31 l
+612.712 320.543 l
+613.197 320.543 l
+613.197 318.971 l
+613.352 319.224 613.583 319.353 613.888 319.353 c
+614.211 319.353 614.454 319.235 614.623 319 c
+614.788 318.765 614.873 318.416 614.873 317.956 c
+h
+614.387 317.942 m
+614.387 318.294 614.337 318.544 614.241 318.691 c
+614.142 318.838 613.98 318.912 613.756 318.912 c
+613.51 318.912 613.323 318.772 613.197 318.5 c
+613.197 317.089 l
+613.315 316.824 613.506 316.692 613.77 316.692 c
+613.984 316.692 614.142 316.766 614.241 316.913 c
+614.337 317.067 614.387 317.31 614.387 317.633 c
+h
+616.843 316.31 m
+616.814 316.376 616.791 316.486 616.784 316.633 c
+616.608 316.376 616.386 316.251 616.122 316.251 c
+615.846 316.251 615.63 316.325 615.476 316.471 c
+615.328 316.626 615.255 316.843 615.255 317.119 c
+615.255 317.42 615.358 317.662 615.563 317.838 c
+615.769 318.023 616.053 318.118 616.417 318.118 c
+616.769 318.118 l
+616.769 318.441 l
+616.769 318.618 616.729 318.739 616.652 318.809 c
+616.571 318.886 616.453 318.927 616.299 318.927 c
+616.151 318.927 616.027 318.882 615.931 318.794 c
+615.843 318.706 615.799 318.596 615.799 318.47 c
+615.314 318.47 l
+615.314 318.618 615.358 318.757 615.446 318.897 c
+615.534 319.044 615.652 319.154 615.799 319.235 c
+615.954 319.312 616.126 319.353 616.313 319.353 c
+616.625 319.353 616.861 319.272 617.019 319.118 c
+617.173 318.971 617.254 318.75 617.254 318.456 c
+617.254 316.957 l
+617.261 316.722 617.298 316.519 617.357 316.354 c
+617.357 316.31 l
+h
+616.196 316.692 m
+616.313 316.692 616.424 316.725 616.534 316.795 c
+616.641 316.861 616.718 316.945 616.769 317.045 c
+616.769 317.751 l
+616.504 317.751 l
+616.269 317.751 616.082 317.699 615.946 317.603 c
+615.817 317.504 615.755 317.361 615.755 317.177 c
+615.755 317.008 615.784 316.887 615.843 316.81 c
+615.91 316.729 616.027 316.692 616.196 316.692 c
+618.863 316.677 m
+619.029 316.677 619.162 316.725 619.26 316.824 c
+619.356 316.92 619.411 317.063 619.422 317.25 c
+619.878 317.25 l
+619.867 316.964 619.764 316.725 619.569 316.531 c
+619.382 316.343 619.147 316.251 618.863 316.251 c
+618.5 316.251 618.221 316.369 618.026 316.604 c
+617.828 316.839 617.732 317.184 617.732 317.647 c
+617.732 317.971 l
+617.732 318.42 617.824 318.765 618.011 319 c
+618.206 319.235 618.489 319.353 618.863 319.353 c
+619.165 319.353 619.407 319.253 619.584 319.058 c
+619.768 318.86 619.867 318.596 619.878 318.265 c
+619.422 318.265 l
+619.401 318.489 619.341 318.655 619.246 318.765 c
+619.158 318.871 619.029 318.927 618.863 318.927 c
+618.647 318.927 618.485 318.853 618.379 318.706 c
+618.279 318.566 618.225 318.339 618.217 318.015 c
+618.217 317.633 l
+618.217 317.28 618.265 317.03 618.364 316.883 c
+618.47 316.743 618.636 316.677 618.863 316.677 c
+621.024 317.677 m
+620.76 317.383 l
+620.76 316.31 l
+620.275 316.31 l
+620.275 320.543 l
+620.76 320.543 l
+620.76 318.015 l
+621.686 319.294 l
+622.274 319.294 l
+621.333 318.044 l
+622.406 316.31 l
+621.833 316.31 l
+h
+624.166 316.575 m
+624.008 316.357 623.773 316.251 623.461 316.251 c
+623.197 316.251 622.991 316.343 622.844 316.531 c
+622.704 316.714 622.638 316.99 622.638 317.354 c
+622.638 319.294 l
+623.123 319.294 l
+623.123 317.383 l
+623.123 316.92 623.262 316.692 623.549 316.692 c
+623.843 316.692 624.041 316.824 624.151 317.089 c
+624.151 319.294 l
+624.652 319.294 l
+624.652 316.31 l
+624.181 316.31 l
+h
+627.349 317.662 m
+627.349 317.192 627.264 316.839 627.099 316.604 c
+626.929 316.369 626.691 316.251 626.379 316.251 c
+626.073 316.251 625.842 316.361 625.688 316.589 c
+625.688 315.164 l
+625.203 315.164 l
+625.203 319.294 l
+625.643 319.294 l
+625.673 318.956 l
+625.828 319.22 626.059 319.353 626.364 319.353 c
+626.694 319.353 626.941 319.235 627.099 319 c
+627.264 318.772 627.349 318.434 627.349 317.986 c
+h
+626.863 317.942 m
+626.863 318.272 626.809 318.518 626.702 318.676 c
+626.603 318.831 626.441 318.912 626.217 318.912 c
+625.982 318.912 625.805 318.794 625.688 318.559 c
+625.688 317.015 l
+625.805 316.787 625.986 316.677 626.231 316.677 c
+626.445 316.677 626.603 316.754 626.702 316.913 c
+626.809 317.067 626.863 317.31 626.863 317.633 c
+h
+629.248 317.074 m
+629.248 317.181 629.208 317.269 629.131 317.339 c
+629.05 317.416 628.899 317.504 628.675 317.603 c
+628.411 317.71 628.223 317.802 628.117 317.882 c
+628.007 317.96 627.929 318.048 627.881 318.148 c
+627.83 318.243 627.808 318.36 627.808 318.5 c
+627.808 318.742 627.896 318.945 628.072 319.103 c
+628.249 319.268 628.473 319.353 628.749 319.353 c
+629.043 319.353 629.278 319.264 629.454 319.088 c
+629.631 318.919 629.719 318.706 629.719 318.441 c
+629.234 318.441 l
+629.234 318.578 629.182 318.691 629.086 318.779 c
+628.999 318.875 628.885 318.927 628.749 318.927 c
+628.602 318.927 628.488 318.886 628.411 318.809 c
+628.33 318.739 628.293 318.64 628.293 318.515 c
+628.293 318.416 628.323 318.339 628.381 318.279 c
+628.44 318.221 628.579 318.14 628.808 318.044 c
+629.167 317.897 629.414 317.754 629.543 317.618 c
+629.678 317.489 629.749 317.317 629.749 317.103 c
+629.749 316.847 629.653 316.641 629.469 316.486 c
+629.292 316.328 629.057 316.251 628.764 316.251 c
+628.448 316.251 628.194 316.34 627.999 316.516 c
+627.812 316.7 627.72 316.931 627.72 317.207 c
+628.205 317.207 l
+628.213 317.038 628.263 316.905 628.352 316.81 c
+628.448 316.722 628.587 316.677 628.764 316.677 c
+628.918 316.677 629.036 316.71 629.117 316.78 c
+629.204 316.847 629.248 316.945 629.248 317.074 c
+630.748 317.442 m
+630.307 317.442 l
+630.277 320.323 l
+630.792 320.323 l
+h
+630.542 316.854 m
+630.638 316.854 630.707 316.824 630.748 316.766 c
+630.796 316.714 630.821 316.648 630.821 316.56 c
+630.821 316.479 630.796 316.413 630.748 316.354 c
+630.707 316.307 630.638 316.28 630.542 316.28 c
+630.454 316.28 630.384 316.307 630.337 316.354 c
+630.285 316.413 630.262 316.479 630.262 316.56 c
+630.262 316.648 630.285 316.714 630.337 316.766 c
+630.384 316.824 630.454 316.854 630.542 316.854 c
+f
+ endstream endobj 34 0 obj <</BBox[581.388 313.958 628.804 308.548]/Group 70 0 R/Length 10862/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 582.7852 311.7234 cm
+0 0 m
+0.808 2.014 l
+1.381 2.014 l
+0.249 -0.5 l
+0.249 -1.999 l
+-0.265 -1.999 l
+-0.265 -0.5 l
+-1.397 2.014 l
+-0.823 2.014 l
+h
+1.385 -0.367 m
+1.385 0.063 1.488 0.405 1.693 0.662 c
+1.907 0.915 2.186 1.044 2.531 1.044 c
+2.873 1.044 3.149 0.915 3.355 0.662 c
+3.568 0.416 3.682 0.081 3.692 -0.338 c
+3.692 -0.646 l
+3.692 -1.08 3.582 -1.421 3.37 -1.675 c
+3.164 -1.932 2.884 -2.057 2.531 -2.057 c
+2.186 -2.057 1.914 -1.936 1.708 -1.69 c
+1.502 -1.448 1.392 -1.113 1.385 -0.69 c
+h
+1.87 -0.646 m
+1.87 -0.962 1.929 -1.205 2.046 -1.381 c
+2.171 -1.55 2.333 -1.631 2.531 -1.631 c
+2.961 -1.631 3.185 -1.323 3.208 -0.706 c
+3.208 -0.367 l
+3.208 -0.066 3.142 0.177 3.017 0.353 c
+2.899 0.53 2.738 0.618 2.531 0.618 c
+2.333 0.618 2.171 0.53 2.046 0.353 c
+1.929 0.177 1.87 -0.066 1.87 -0.367 c
+h
+5.644 -1.734 m
+5.486 -1.951 5.251 -2.057 4.939 -2.057 c
+4.674 -2.057 4.469 -1.965 4.321 -1.778 c
+4.182 -1.595 4.116 -1.319 4.116 -0.955 c
+4.116 0.985 l
+4.6 0.985 l
+4.6 -0.926 l
+4.6 -1.389 4.74 -1.616 5.026 -1.616 c
+5.321 -1.616 5.519 -1.484 5.629 -1.219 c
+5.629 0.985 l
+6.129 0.985 l
+6.129 -1.999 l
+5.659 -1.999 l
+h
+9.415 -1.999 m
+9.385 -1.932 9.363 -1.822 9.356 -1.675 c
+9.18 -1.932 8.959 -2.057 8.694 -2.057 c
+8.419 -2.057 8.201 -1.984 8.047 -1.837 c
+7.9 -1.683 7.827 -1.466 7.827 -1.19 c
+7.827 -0.889 7.93 -0.646 8.135 -0.47 c
+8.342 -0.286 8.625 -0.191 8.988 -0.191 c
+9.341 -0.191 l
+9.341 0.133 l
+9.341 0.31 9.3 0.431 9.223 0.5 c
+9.142 0.578 9.025 0.618 8.87 0.618 c
+8.724 0.618 8.598 0.574 8.503 0.485 c
+8.415 0.397 8.371 0.287 8.371 0.162 c
+7.885 0.162 l
+7.885 0.31 7.93 0.449 8.018 0.588 c
+8.106 0.736 8.224 0.846 8.371 0.927 c
+8.525 1.004 8.698 1.044 8.885 1.044 c
+9.198 1.044 9.433 0.963 9.591 0.809 c
+9.745 0.662 9.826 0.441 9.826 0.148 c
+9.826 -1.352 l
+9.834 -1.587 9.87 -1.789 9.929 -1.955 c
+9.929 -1.999 l
+h
+8.768 -1.616 m
+8.885 -1.616 8.995 -1.583 9.105 -1.514 c
+9.213 -1.448 9.29 -1.363 9.341 -1.263 c
+9.341 -0.558 l
+9.076 -0.558 l
+8.841 -0.558 8.654 -0.61 8.517 -0.706 c
+8.39 -0.804 8.326 -0.947 8.326 -1.132 c
+8.326 -1.3 8.356 -1.421 8.415 -1.499 c
+8.481 -1.579 8.598 -1.616 8.768 -1.616 c
+11.642 0.53 m
+11.571 0.537 11.498 0.545 11.421 0.545 c
+11.164 0.545 10.987 0.405 10.892 0.133 c
+10.892 -1.999 l
+10.406 -1.999 l
+10.406 0.985 l
+10.877 0.985 l
+10.892 0.676 l
+11.017 0.919 11.2 1.044 11.436 1.044 c
+11.513 1.044 11.575 1.029 11.627 1 c
+h
+13.02 -2.057 m
+12.644 -2.057 12.361 -1.951 12.167 -1.734 c
+11.968 -1.51 11.873 -1.182 11.873 -0.749 c
+11.873 -0.382 l
+11.873 0.059 11.964 0.405 12.153 0.662 c
+12.347 0.915 12.623 1.044 12.976 1.044 c
+13.317 1.044 13.57 0.93 13.74 0.706 c
+13.916 0.478 14.008 0.133 14.019 -0.338 c
+14.019 -0.646 l
+12.358 -0.646 l
+12.358 -0.72 l
+12.358 -1.043 12.417 -1.278 12.534 -1.425 c
+12.652 -1.565 12.821 -1.631 13.049 -1.631 c
+13.196 -1.631 13.321 -1.609 13.431 -1.558 c
+13.537 -1.499 13.641 -1.411 13.74 -1.294 c
+13.99 -1.602 l
+13.784 -1.907 13.46 -2.057 13.02 -2.057 c
+12.976 0.618 m
+12.77 0.618 12.615 0.548 12.519 0.412 c
+12.421 0.273 12.365 0.059 12.358 -0.235 c
+13.533 -0.235 l
+13.533 -0.161 l
+13.512 0.111 13.46 0.31 13.373 0.427 c
+13.284 0.551 13.151 0.618 12.976 0.618 c
+15.533 -0.367 m
+15.533 0.092 15.613 0.441 15.783 0.676 c
+15.96 0.919 16.209 1.044 16.533 1.044 c
+16.816 1.044 17.036 0.927 17.194 0.691 c
+17.194 2.234 l
+17.679 2.234 l
+17.679 -1.999 l
+17.238 -1.999 l
+17.209 -1.675 l
+17.051 -1.932 16.826 -2.057 16.533 -2.057 c
+16.216 -2.057 15.974 -1.94 15.798 -1.705 c
+15.621 -1.462 15.533 -1.117 15.533 -0.675 c
+h
+16.018 -0.646 m
+16.018 -0.98 16.066 -1.227 16.165 -1.381 c
+16.261 -1.539 16.423 -1.616 16.65 -1.616 c
+16.893 -1.616 17.076 -1.499 17.194 -1.263 c
+17.194 0.25 l
+17.065 0.485 16.885 0.603 16.65 0.603 c
+16.423 0.603 16.261 0.522 16.165 0.368 c
+16.066 0.21 16.018 -0.029 16.018 -0.353 c
+h
+18.146 -0.367 m
+18.146 0.063 18.248 0.405 18.454 0.662 c
+18.667 0.915 18.947 1.044 19.293 1.044 c
+19.634 1.044 19.91 0.915 20.115 0.662 c
+20.328 0.416 20.442 0.081 20.454 -0.338 c
+20.454 -0.646 l
+20.454 -1.08 20.344 -1.421 20.13 -1.675 c
+19.924 -1.932 19.645 -2.057 19.293 -2.057 c
+18.947 -2.057 18.675 -1.936 18.469 -1.69 c
+18.263 -1.448 18.153 -1.113 18.146 -0.69 c
+h
+18.63 -0.646 m
+18.63 -0.962 18.69 -1.205 18.807 -1.381 c
+18.932 -1.55 19.094 -1.631 19.293 -1.631 c
+19.723 -1.631 19.946 -1.323 19.968 -0.706 c
+19.968 -0.367 l
+19.968 -0.066 19.902 0.177 19.777 0.353 c
+19.66 0.53 19.498 0.618 19.293 0.618 c
+19.094 0.618 18.932 0.53 18.807 0.353 c
+18.69 0.177 18.63 -0.066 18.63 -0.367 c
+h
+21.423 -1.999 -0.5 2.984 re
+21.453 1.779 m
+21.453 1.691 21.427 1.617 21.379 1.559 c
+21.339 1.507 21.269 1.485 21.174 1.485 c
+21.086 1.485 21.016 1.507 20.968 1.559 c
+20.928 1.617 20.909 1.684 20.909 1.764 c
+20.909 1.852 20.928 1.926 20.968 1.985 c
+21.016 2.043 21.086 2.073 21.174 2.073 c
+21.269 2.073 21.339 2.043 21.379 1.985 c
+21.427 1.926 21.453 1.856 21.453 1.779 c
+22.551 0.985 m
+22.566 0.662 l
+22.75 0.915 22.993 1.044 23.287 1.044 c
+23.816 1.044 24.084 0.691 24.095 -0.014 c
+24.095 -1.999 l
+23.61 -1.999 l
+23.61 -0.043 l
+23.61 0.192 23.569 0.357 23.492 0.456 c
+23.411 0.551 23.294 0.603 23.139 0.603 c
+23.022 0.603 22.912 0.563 22.817 0.485 c
+22.717 0.405 22.64 0.298 22.582 0.162 c
+22.582 -1.999 l
+22.096 -1.999 l
+22.096 0.985 l
+h
+24.547 -0.367 m
+24.547 0.092 24.628 0.441 24.797 0.676 c
+24.974 0.919 25.223 1.044 25.547 1.044 c
+25.848 1.044 26.079 0.912 26.237 0.647 c
+26.267 0.985 l
+26.708 0.985 l
+26.708 -2.028 l
+26.708 -2.399 26.609 -2.682 26.414 -2.881 c
+26.227 -3.075 25.965 -3.175 25.635 -3.175 c
+25.487 -3.175 25.319 -3.135 25.135 -3.057 c
+24.947 -2.987 24.812 -2.899 24.724 -2.792 c
+24.915 -2.454 l
+25.121 -2.66 25.344 -2.763 25.591 -2.763 c
+25.992 -2.763 26.197 -2.535 26.208 -2.087 c
+26.208 -1.705 l
+26.05 -1.94 25.83 -2.057 25.547 -2.057 c
+25.231 -2.057 24.988 -1.94 24.812 -1.705 c
+24.643 -1.469 24.554 -1.138 24.547 -0.706 c
+h
+25.032 -0.646 m
+25.032 -0.98 25.08 -1.227 25.179 -1.381 c
+25.275 -1.539 25.437 -1.616 25.664 -1.616 c
+25.907 -1.616 26.09 -1.495 26.208 -1.249 c
+26.208 0.235 l
+26.09 0.478 25.915 0.603 25.679 0.603 c
+25.451 0.603 25.289 0.522 25.194 0.368 c
+25.094 0.21 25.04 -0.029 25.032 -0.353 c
+h
+28.975 -1.999 -0.5 2.984 re
+29.005 1.779 m
+29.005 1.691 28.979 1.617 28.932 1.559 c
+28.891 1.507 28.82 1.485 28.726 1.485 c
+28.637 1.485 28.567 1.507 28.519 1.559 c
+28.479 1.617 28.461 1.684 28.461 1.764 c
+28.461 1.852 28.479 1.926 28.519 1.985 c
+28.567 2.043 28.637 2.073 28.726 2.073 c
+28.82 2.073 28.891 2.043 28.932 1.985 c
+28.979 1.926 29.005 1.856 29.005 1.779 c
+30.28 1.706 m
+30.28 0.985 l
+30.736 0.985 l
+30.736 0.588 l
+30.28 0.588 l
+30.28 -1.263 l
+30.28 -1.381 30.298 -1.469 30.339 -1.529 c
+30.376 -1.587 30.445 -1.616 30.544 -1.616 c
+30.603 -1.616 30.665 -1.609 30.736 -1.587 c
+30.736 -1.999 l
+30.618 -2.036 30.503 -2.057 30.397 -2.057 c
+30.199 -2.057 30.048 -1.992 29.942 -1.851 c
+29.842 -1.716 29.795 -1.521 29.795 -1.263 c
+29.795 0.588 l
+29.339 0.588 l
+29.339 0.985 l
+29.795 0.985 l
+29.795 1.706 l
+h
+31.202 -2.792 m
+30.908 -2.601 l
+31.085 -2.355 31.176 -2.105 31.187 -1.851 c
+31.187 -1.396 l
+31.687 -1.396 l
+31.687 -1.793 l
+31.687 -1.98 31.636 -2.164 31.54 -2.352 c
+31.452 -2.535 31.338 -2.682 31.202 -2.792 c
+34.682 0.53 m
+34.613 0.537 34.539 0.545 34.461 0.545 c
+34.204 0.545 34.028 0.405 33.932 0.133 c
+33.932 -1.999 l
+33.447 -1.999 l
+33.447 0.985 l
+33.917 0.985 l
+33.932 0.676 l
+34.058 0.919 34.241 1.044 34.476 1.044 c
+34.553 1.044 34.616 1.029 34.667 1 c
+h
+35.579 -1.999 -0.5 2.984 re
+35.608 1.779 m
+35.608 1.691 35.583 1.617 35.535 1.559 c
+35.494 1.507 35.424 1.485 35.329 1.485 c
+35.241 1.485 35.17 1.507 35.123 1.559 c
+35.083 1.617 35.064 1.684 35.064 1.764 c
+35.064 1.852 35.083 1.926 35.123 1.985 c
+35.17 2.043 35.241 2.073 35.329 2.073 c
+35.424 2.073 35.494 2.043 35.535 1.985 c
+35.583 1.926 35.608 1.856 35.608 1.779 c
+36.152 -0.367 m
+36.152 0.092 36.233 0.441 36.402 0.676 c
+36.578 0.919 36.828 1.044 37.152 1.044 c
+37.453 1.044 37.684 0.912 37.842 0.647 c
+37.872 0.985 l
+38.313 0.985 l
+38.313 -2.028 l
+38.313 -2.399 38.214 -2.682 38.019 -2.881 c
+37.832 -3.075 37.57 -3.175 37.24 -3.175 c
+37.092 -3.175 36.924 -3.135 36.74 -3.057 c
+36.552 -2.987 36.417 -2.899 36.329 -2.792 c
+36.52 -2.454 l
+36.726 -2.66 36.949 -2.763 37.196 -2.763 c
+37.597 -2.763 37.802 -2.535 37.813 -2.087 c
+37.813 -1.705 l
+37.655 -1.94 37.435 -2.057 37.152 -2.057 c
+36.836 -2.057 36.593 -1.94 36.417 -1.705 c
+36.248 -1.469 36.159 -1.138 36.152 -0.706 c
+h
+36.637 -0.646 m
+36.637 -0.98 36.685 -1.227 36.784 -1.381 c
+36.88 -1.539 37.042 -1.616 37.269 -1.616 c
+37.512 -1.616 37.695 -1.495 37.813 -1.249 c
+37.813 0.235 l
+37.695 0.478 37.519 0.603 37.283 0.603 c
+37.056 0.603 36.894 0.522 36.799 0.368 c
+36.699 0.21 36.645 -0.029 36.637 -0.353 c
+h
+39.334 0.676 m
+39.519 0.919 39.754 1.044 40.04 1.044 c
+40.569 1.044 40.838 0.691 40.849 -0.014 c
+40.849 -1.999 l
+40.363 -1.999 l
+40.363 -0.043 l
+40.363 0.192 40.323 0.357 40.246 0.456 c
+40.165 0.551 40.047 0.603 39.893 0.603 c
+39.775 0.603 39.665 0.563 39.569 0.485 c
+39.471 0.405 39.393 0.298 39.334 0.162 c
+39.334 -1.999 l
+38.85 -1.999 l
+38.85 2.234 l
+39.334 2.234 l
+h
+42.021 1.706 m
+42.021 0.985 l
+42.476 0.985 l
+42.476 0.588 l
+42.021 0.588 l
+42.021 -1.263 l
+42.021 -1.381 42.039 -1.469 42.079 -1.529 c
+42.116 -1.587 42.186 -1.616 42.285 -1.616 c
+42.344 -1.616 42.407 -1.609 42.476 -1.587 c
+42.476 -1.999 l
+42.359 -2.036 42.245 -2.057 42.139 -2.057 c
+41.94 -2.057 41.79 -1.992 41.682 -1.851 c
+41.583 -1.716 41.536 -1.521 41.536 -1.263 c
+41.536 0.588 l
+41.08 0.588 l
+41.08 0.985 l
+41.536 0.985 l
+41.536 1.706 l
+h
+43.487 -0.866 m
+43.046 -0.866 l
+43.016 2.014 l
+43.531 2.014 l
+h
+43.282 -1.454 m
+43.377 -1.454 43.446 -1.484 43.487 -1.543 c
+43.535 -1.595 43.56 -1.66 43.56 -1.749 c
+43.56 -1.83 43.535 -1.896 43.487 -1.955 c
+43.446 -2.002 43.377 -2.028 43.282 -2.028 c
+43.193 -2.028 43.124 -2.002 43.076 -1.955 c
+43.024 -1.896 43.002 -1.83 43.002 -1.749 c
+43.002 -1.66 43.024 -1.595 43.076 -1.543 c
+43.124 -1.484 43.193 -1.454 43.282 -1.454 c
+44.74 -0.866 m
+44.74 -0.654 44.758 -0.477 44.799 -0.338 c
+44.847 -0.191 44.961 -0.014 45.137 0.192 c
+45.343 0.441 l
+45.468 0.626 45.534 0.813 45.534 1 c
+45.534 1.195 45.489 1.345 45.401 1.455 c
+45.32 1.563 45.21 1.617 45.063 1.617 c
+44.924 1.617 44.807 1.566 44.711 1.47 c
+44.622 1.372 44.578 1.239 44.578 1.073 c
+44.093 1.073 l
+44.093 1.374 44.182 1.617 44.358 1.794 c
+44.541 1.977 44.776 2.073 45.063 2.073 c
+45.358 2.073 45.585 1.977 45.754 1.794 c
+45.931 1.607 46.019 1.353 46.019 1.029 c
+46.019 0.713 45.89 0.401 45.636 0.088 c
+45.387 -0.22 l
+45.277 -0.367 45.225 -0.584 45.225 -0.866 c
+h
+45.005 -1.454 m
+45.092 -1.454 45.159 -1.484 45.21 -1.543 c
+45.258 -1.595 45.283 -1.66 45.283 -1.749 c
+45.283 -1.83 45.258 -1.896 45.21 -1.955 c
+45.159 -2.002 45.092 -2.028 45.005 -2.028 c
+44.905 -2.028 44.832 -2.002 44.784 -1.955 c
+44.743 -1.896 44.726 -1.83 44.726 -1.749 c
+44.726 -1.66 44.743 -1.595 44.784 -1.543 c
+44.832 -1.484 44.905 -1.454 45.005 -1.454 c
+f
+Q
+ endstream endobj 35 0 obj <</BBox[535.367 366.838 774.632 366.237]/Group 71 0 R/Length 124/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 K
+0.601 w 4 M 1 j 1 J [4.808 4.808]0 d
+/GS0 gs
+q 1 0 0 1 535.6673 366.537 cm
+0 0 m
+238.665 0 l
+S
+Q
+ endstream endobj 36 0 obj <</BBox[741.792 364.828 774.49 359.389]/Group 72 0 R/Length 8999/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+742.571 360.595 -0.779 4.233 re
+742.99 362.182 m
+742.99 362.631 743.097 362.983 743.313 363.24 c
+743.526 363.505 743.82 363.637 744.195 363.637 c
+744.577 363.637 744.872 363.505 745.077 363.24 c
+745.29 362.983 745.4 362.631 745.4 362.182 c
+745.4 361.991 l
+745.4 361.528 745.29 361.172 745.077 360.917 c
+744.872 360.661 744.577 360.536 744.195 360.536 c
+743.813 360.536 743.511 360.661 743.299 360.917 c
+743.093 361.183 742.99 361.539 742.99 361.991 c
+h
+743.769 361.991 m
+743.769 361.451 743.908 361.183 744.195 361.183 c
+744.46 361.183 744.6 361.407 744.622 361.858 c
+744.637 362.182 l
+744.637 362.454 744.596 362.656 744.519 362.785 c
+744.438 362.92 744.331 362.991 744.195 362.991 c
+744.066 362.991 743.964 362.92 743.887 362.785 c
+743.806 362.656 743.769 362.454 743.769 362.182 c
+h
+746.79 361.183 m
+747.014 361.183 747.128 361.33 747.128 361.623 c
+747.862 361.623 l
+747.862 361.3 747.76 361.035 747.554 360.83 c
+747.355 360.632 747.106 360.536 746.804 360.536 c
+746.422 360.536 746.128 360.653 745.923 360.888 c
+745.716 361.131 745.614 361.484 745.614 361.947 c
+745.614 362.197 l
+745.614 362.656 745.709 363.009 745.907 363.255 c
+746.114 363.508 746.407 363.637 746.79 363.637 c
+747.12 363.637 747.382 363.535 747.569 363.329 c
+747.764 363.123 747.862 362.833 747.862 362.461 c
+747.128 362.461 l
+747.128 362.627 747.098 362.756 747.039 362.843 c
+746.988 362.939 746.9 362.991 746.775 362.991 c
+746.646 362.991 746.555 362.939 746.495 362.843 c
+746.437 362.744 746.4 362.557 746.393 362.285 c
+746.393 361.976 l
+746.393 361.73 746.4 361.557 746.422 361.462 c
+746.451 361.374 746.488 361.304 746.54 361.256 c
+746.598 361.204 746.679 361.183 746.79 361.183 c
+749.553 360.595 m
+749.524 360.642 749.498 360.72 749.479 360.83 c
+749.34 360.632 749.156 360.536 748.921 360.536 c
+748.664 360.536 748.454 360.616 748.289 360.786 c
+748.13 360.951 748.053 361.168 748.053 361.432 c
+748.053 361.744 748.149 361.983 748.348 362.153 c
+748.543 362.329 748.826 362.417 749.2 362.417 c
+749.45 362.417 l
+749.45 362.652 l
+749.45 362.789 749.424 362.88 749.377 362.932 c
+749.325 362.991 749.259 363.02 749.171 363.02 c
+748.972 363.02 748.876 362.906 748.876 362.681 c
+748.098 362.681 l
+748.098 362.954 748.201 363.182 748.406 363.358 c
+748.612 363.542 748.876 363.637 749.2 363.637 c
+749.524 363.637 749.774 363.549 749.95 363.373 c
+750.133 363.203 750.229 362.965 750.229 362.652 c
+750.229 361.241 l
+750.229 360.984 750.262 360.786 750.332 360.639 c
+750.332 360.595 l
+h
+749.082 361.153 m
+749.171 361.153 749.244 361.168 749.304 361.197 c
+749.369 361.234 749.42 361.278 749.45 361.33 c
+749.45 361.947 l
+749.259 361.947 l
+749.119 361.947 749.013 361.902 748.936 361.815 c
+748.866 361.734 748.833 361.623 748.833 361.476 c
+748.833 361.26 748.913 361.153 749.082 361.153 c
+751.431 360.595 -0.779 4.233 re
+754.621 362.829 m
+754.37 362.843 l
+754.154 362.843 754.007 362.748 753.929 362.564 c
+753.929 360.595 l
+753.15 360.595 l
+753.15 363.579 l
+753.886 363.579 l
+753.915 363.255 l
+754.033 363.508 754.198 363.637 754.415 363.637 c
+754.503 363.637 754.576 363.622 754.635 363.593 c
+h
+756.053 360.536 m
+755.65 360.536 755.337 360.653 755.113 360.888 c
+754.896 361.131 754.79 361.476 754.79 361.918 c
+754.79 362.168 l
+754.79 362.638 754.893 362.997 755.099 363.255 c
+755.304 363.508 755.598 363.637 755.98 363.637 c
+756.352 363.637 756.631 363.512 756.818 363.269 c
+757.013 363.034 757.112 362.681 757.112 362.211 c
+757.112 361.829 l
+755.569 361.829 l
+755.575 361.601 755.62 361.436 755.701 361.33 c
+755.789 361.23 755.925 361.183 756.113 361.183 c
+756.366 361.183 756.583 361.274 756.759 361.462 c
+757.067 360.977 l
+756.969 360.848 756.826 360.742 756.641 360.653 c
+756.465 360.576 756.267 360.536 756.053 360.536 c
+755.569 362.373 m
+756.348 362.373 l
+756.348 362.446 l
+756.348 362.623 756.319 362.756 756.259 362.843 c
+756.201 362.939 756.101 362.991 755.966 362.991 c
+755.837 362.991 755.737 362.939 755.671 362.843 c
+755.613 362.744 755.575 362.586 755.569 362.373 c
+759.691 361.991 m
+759.691 361.521 759.611 361.156 759.456 360.903 c
+759.298 360.657 759.06 360.536 758.736 360.536 c
+758.49 360.536 758.295 360.632 758.148 360.83 c
+758.148 359.448 l
+757.37 359.448 l
+757.37 363.579 l
+758.089 363.579 l
+758.119 363.299 l
+758.273 363.523 758.479 363.637 758.736 363.637 c
+759.049 363.637 759.284 363.52 759.442 363.284 c
+759.607 363.049 759.691 362.696 759.691 362.226 c
+h
+758.927 362.182 m
+758.927 362.476 758.891 362.681 758.825 362.799 c
+758.766 362.917 758.655 362.976 758.501 362.976 c
+758.343 362.976 758.226 362.91 758.148 362.785 c
+758.148 361.374 l
+758.226 361.245 758.347 361.183 758.515 361.183 c
+758.663 361.183 758.766 361.245 758.825 361.374 c
+758.891 361.509 758.927 361.715 758.927 361.991 c
+h
+759.893 362.182 m
+759.893 362.631 760.001 362.983 760.217 363.24 c
+760.431 363.505 760.724 363.637 761.099 363.637 c
+761.481 363.637 761.775 363.505 761.981 363.24 c
+762.195 362.983 762.305 362.631 762.305 362.182 c
+762.305 361.991 l
+762.305 361.528 762.195 361.172 761.981 360.917 c
+761.775 360.661 761.481 360.536 761.099 360.536 c
+760.717 360.536 760.416 360.661 760.202 360.917 c
+759.997 361.183 759.893 361.539 759.893 361.991 c
+h
+760.672 361.991 m
+760.672 361.451 760.813 361.183 761.099 361.183 c
+761.364 361.183 761.503 361.407 761.526 361.858 c
+761.54 362.182 l
+761.54 362.454 761.499 362.656 761.422 362.785 c
+761.341 362.92 761.235 362.991 761.099 362.991 c
+760.971 362.991 760.867 362.92 760.79 362.785 c
+760.709 362.656 760.672 362.454 760.672 362.182 c
+h
+763.928 361.388 m
+763.928 361.455 763.892 361.521 763.826 361.58 c
+763.766 361.638 763.627 361.711 763.415 361.8 c
+763.091 361.935 762.87 362.072 762.752 362.211 c
+762.635 362.347 762.576 362.521 762.576 362.726 c
+762.576 362.991 762.669 363.203 762.856 363.373 c
+763.039 363.549 763.29 363.637 763.606 363.637 c
+763.928 363.637 764.186 363.549 764.385 363.373 c
+764.579 363.203 764.678 362.98 764.678 362.696 c
+763.899 362.696 l
+763.899 362.939 763.797 363.064 763.591 363.064 c
+763.51 363.064 763.444 363.034 763.385 362.976 c
+763.334 362.924 763.311 362.858 763.311 362.77 c
+763.311 362.7 763.34 362.641 763.4 362.594 c
+763.458 362.542 763.594 362.469 763.811 362.373 c
+764.134 362.255 764.358 362.124 764.487 361.976 c
+764.624 361.837 764.693 361.653 764.693 361.418 c
+764.693 361.153 764.591 360.936 764.385 360.771 c
+764.186 360.613 763.928 360.536 763.606 360.536 c
+763.377 360.536 763.182 360.58 763.018 360.668 c
+762.848 360.757 762.716 360.874 762.621 361.021 c
+762.532 361.175 762.488 361.345 762.488 361.521 c
+763.223 361.521 l
+763.23 361.381 763.267 361.278 763.326 361.212 c
+763.385 361.142 763.48 361.109 763.62 361.109 c
+763.826 361.109 763.928 361.201 763.928 361.388 c
+765.825 360.595 -0.779 2.984 re
+765.002 364.343 m
+765.002 364.468 765.038 364.57 765.119 364.651 c
+765.196 364.728 765.299 364.769 765.428 364.769 c
+765.553 364.769 765.656 364.728 765.736 364.651 c
+765.814 364.57 765.854 364.468 765.854 364.343 c
+765.854 364.225 765.814 364.126 765.736 364.049 c
+765.667 363.968 765.564 363.932 765.428 363.932 c
+765.299 363.932 765.196 363.968 765.119 364.049 c
+765.038 364.126 765.002 364.225 765.002 364.343 c
+767.243 364.314 m
+767.243 363.579 l
+767.64 363.579 l
+767.64 362.991 l
+767.243 362.991 l
+767.243 361.505 l
+767.243 361.388 767.258 361.304 767.288 361.256 c
+767.324 361.216 767.39 361.197 767.479 361.197 c
+767.556 361.197 767.618 361.204 767.67 361.227 c
+767.655 360.609 l
+767.527 360.562 767.383 360.536 767.228 360.536 c
+766.729 360.536 766.472 360.822 766.465 361.403 c
+766.465 362.991 l
+766.126 362.991 l
+766.126 363.579 l
+766.465 363.579 l
+766.465 364.314 l
+h
+767.787 362.182 m
+767.787 362.631 767.893 362.983 768.111 363.24 c
+768.323 363.505 768.618 363.637 768.992 363.637 c
+769.374 363.637 769.669 363.505 769.875 363.24 c
+770.087 362.983 770.197 362.631 770.197 362.182 c
+770.197 361.991 l
+770.197 361.528 770.087 361.172 769.875 360.917 c
+769.669 360.661 769.374 360.536 768.992 360.536 c
+768.61 360.536 768.309 360.661 768.096 360.917 c
+767.89 361.183 767.787 361.539 767.787 361.991 c
+h
+768.566 361.991 m
+768.566 361.451 768.705 361.183 768.992 361.183 c
+769.257 361.183 769.397 361.407 769.418 361.858 c
+769.433 362.182 l
+769.433 362.454 769.393 362.656 769.316 362.785 c
+769.235 362.92 769.129 362.991 768.992 362.991 c
+768.863 362.991 768.761 362.92 768.684 362.785 c
+768.603 362.656 768.566 362.454 768.566 362.182 c
+h
+771.969 362.829 m
+771.719 362.843 l
+771.502 362.843 771.355 362.748 771.278 362.564 c
+771.278 360.595 l
+770.499 360.595 l
+770.499 363.579 l
+771.234 363.579 l
+771.263 363.255 l
+771.381 363.508 771.546 363.637 771.763 363.637 c
+771.851 363.637 771.925 363.622 771.984 363.593 c
+h
+773.255 361.888 m
+773.652 363.579 l
+774.49 363.579 l
+773.505 360.154 l
+773.358 359.647 773.083 359.389 772.682 359.389 c
+772.583 359.389 772.476 359.411 772.358 359.448 c
+772.358 360.051 l
+772.447 360.051 l
+772.572 360.051 772.667 360.076 772.726 360.124 c
+772.784 360.165 772.829 360.242 772.859 360.36 c
+772.932 360.565 l
+772.065 363.579 l
+772.902 363.579 l
+h
+f
+ endstream endobj 37 0 obj <</BBox[733.362 374.614 774.497 369.293]/Group 73 0 R/Length 10421/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 734.8322 372.6739 cm
+0 0 m
+-0.25 0.014 l
+-0.467 0.014 -0.614 -0.081 -0.691 -0.265 c
+-0.691 -2.234 l
+-1.47 -2.234 l
+-1.47 0.749 l
+-0.736 0.749 l
+-0.706 0.426 l
+-0.588 0.679 -0.423 0.808 -0.206 0.808 c
+-0.118 0.808 -0.044 0.793 0.014 0.764 c
+h
+1.433 -2.294 m
+1.028 -2.294 0.716 -2.176 0.492 -1.941 c
+0.276 -1.698 0.168 -1.353 0.168 -0.912 c
+0.168 -0.662 l
+0.168 -0.192 0.272 0.168 0.477 0.426 c
+0.683 0.679 0.977 0.808 1.359 0.808 c
+1.731 0.808 2.009 0.683 2.198 0.44 c
+2.392 0.205 2.491 -0.148 2.491 -0.618 c
+2.491 -1 l
+0.947 -1 l
+0.955 -1.228 0.999 -1.393 1.08 -1.5 c
+1.168 -1.599 1.304 -1.646 1.492 -1.646 c
+1.745 -1.646 1.962 -1.555 2.138 -1.368 c
+2.447 -1.852 l
+2.348 -1.981 2.204 -2.087 2.021 -2.176 c
+1.845 -2.253 1.646 -2.294 1.433 -2.294 c
+0.947 -0.456 m
+1.727 -0.456 l
+1.727 -0.383 l
+1.727 -0.206 1.697 -0.074 1.639 0.014 c
+1.58 0.11 1.481 0.161 1.344 0.161 c
+1.216 0.161 1.117 0.11 1.051 0.014 c
+0.992 -0.085 0.955 -0.243 0.947 -0.456 c
+3.484 0.749 m
+3.513 0.47 l
+3.69 0.694 3.917 0.808 4.203 0.808 c
+4.498 0.808 4.708 0.668 4.835 0.396 c
+5.001 0.668 5.24 0.808 5.556 0.808 c
+6.085 0.808 6.354 0.444 6.364 -0.279 c
+6.364 -2.234 l
+5.585 -2.234 l
+5.585 -0.324 l
+5.585 -0.158 5.56 -0.04 5.512 0.029 c
+5.46 0.106 5.383 0.147 5.277 0.147 c
+5.13 0.147 5.016 0.058 4.939 -0.118 c
+4.953 -0.206 l
+4.953 -2.234 l
+4.174 -2.234 l
+4.174 -0.339 l
+4.174 -0.162 4.149 -0.04 4.101 0.029 c
+4.049 0.106 3.968 0.147 3.85 0.147 c
+3.723 0.147 3.619 0.073 3.542 -0.074 c
+3.542 -2.234 l
+2.763 -2.234 l
+2.763 0.749 l
+h
+6.57 -0.647 m
+6.57 -0.199 6.676 0.154 6.894 0.411 c
+7.106 0.675 7.401 0.808 7.775 0.808 c
+8.158 0.808 8.452 0.675 8.658 0.411 c
+8.87 0.154 8.981 -0.199 8.981 -0.647 c
+8.981 -0.838 l
+8.981 -1.301 8.87 -1.658 8.658 -1.912 c
+8.452 -2.168 8.158 -2.294 7.775 -2.294 c
+7.393 -2.294 7.092 -2.168 6.879 -1.912 c
+6.673 -1.646 6.57 -1.291 6.57 -0.838 c
+h
+7.349 -0.838 m
+7.349 -1.378 7.489 -1.646 7.775 -1.646 c
+8.041 -1.646 8.18 -1.422 8.201 -0.971 c
+8.216 -0.647 l
+8.216 -0.375 8.176 -0.173 8.099 -0.044 c
+8.018 0.091 7.912 0.161 7.775 0.161 c
+7.647 0.161 7.544 0.091 7.467 -0.044 c
+7.386 -0.173 7.349 -0.375 7.349 -0.647 c
+h
+10.194 1.484 m
+10.194 0.749 l
+10.59 0.749 l
+10.59 0.161 l
+10.194 0.161 l
+10.194 -1.324 l
+10.194 -1.441 10.208 -1.526 10.238 -1.573 c
+10.275 -1.613 10.341 -1.632 10.429 -1.632 c
+10.506 -1.632 10.568 -1.625 10.62 -1.603 c
+10.605 -2.22 l
+10.476 -2.268 10.333 -2.294 10.179 -2.294 c
+9.679 -2.294 9.422 -2.007 9.414 -1.426 c
+9.414 0.161 l
+9.076 0.161 l
+9.076 0.749 l
+9.414 0.749 l
+9.414 1.484 l
+h
+12.104 -2.294 m
+11.7 -2.294 11.388 -2.176 11.164 -1.941 c
+10.946 -1.698 10.84 -1.353 10.84 -0.912 c
+10.84 -0.662 l
+10.84 -0.192 10.944 0.168 11.149 0.426 c
+11.355 0.679 11.649 0.808 12.031 0.808 c
+12.402 0.808 12.681 0.683 12.868 0.44 c
+13.063 0.205 13.163 -0.148 13.163 -0.618 c
+13.163 -1 l
+11.619 -1 l
+11.627 -1.228 11.671 -1.393 11.752 -1.5 c
+11.84 -1.599 11.976 -1.646 12.163 -1.646 c
+12.417 -1.646 12.633 -1.555 12.81 -1.368 c
+13.119 -1.852 l
+13.02 -1.981 12.876 -2.087 12.692 -2.176 c
+12.516 -2.253 12.317 -2.294 12.104 -2.294 c
+11.619 -0.456 m
+12.398 -0.456 l
+12.398 -0.383 l
+12.398 -0.206 12.369 -0.074 12.311 0.014 c
+12.251 0.11 12.153 0.161 12.016 0.161 c
+11.887 0.161 11.788 0.11 11.723 0.014 c
+11.663 -0.085 11.627 -0.243 11.619 -0.456 c
+16.103 0 m
+15.852 0.014 l
+15.636 0.014 15.489 -0.081 15.412 -0.265 c
+15.412 -2.234 l
+14.632 -2.234 l
+14.632 0.749 l
+15.368 0.749 l
+15.397 0.426 l
+15.515 0.679 15.68 0.808 15.897 0.808 c
+15.985 0.808 16.058 0.793 16.118 0.764 c
+h
+17.535 -2.294 m
+17.132 -2.294 16.82 -2.176 16.595 -1.941 c
+16.378 -1.698 16.272 -1.353 16.272 -0.912 c
+16.272 -0.662 l
+16.272 -0.192 16.375 0.168 16.581 0.426 c
+16.786 0.679 17.08 0.808 17.462 0.808 c
+17.834 0.808 18.113 0.683 18.3 0.44 c
+18.495 0.205 18.594 -0.148 18.594 -0.618 c
+18.594 -1 l
+17.051 -1 l
+17.058 -1.228 17.102 -1.393 17.183 -1.5 c
+17.271 -1.599 17.407 -1.646 17.595 -1.646 c
+17.848 -1.646 18.065 -1.555 18.241 -1.368 c
+18.549 -1.852 l
+18.451 -1.981 18.308 -2.087 18.123 -2.176 c
+17.947 -2.253 17.749 -2.294 17.535 -2.294 c
+17.051 -0.456 m
+17.83 -0.456 l
+17.83 -0.383 l
+17.83 -0.206 17.801 -0.074 17.741 0.014 c
+17.683 0.11 17.583 0.161 17.448 0.161 c
+17.319 0.161 17.219 0.11 17.153 0.014 c
+17.095 -0.085 17.058 -0.243 17.051 -0.456 c
+21.173 -0.838 m
+21.173 -1.309 21.093 -1.673 20.938 -1.926 c
+20.781 -2.172 20.542 -2.294 20.218 -2.294 c
+19.972 -2.294 19.777 -2.198 19.63 -1.999 c
+19.63 -3.381 l
+18.852 -3.381 l
+18.852 0.749 l
+19.571 0.749 l
+19.601 0.47 l
+19.756 0.694 19.961 0.808 20.218 0.808 c
+20.531 0.808 20.766 0.69 20.924 0.455 c
+21.09 0.22 21.173 -0.133 21.173 -0.603 c
+h
+20.409 -0.647 m
+20.409 -0.353 20.373 -0.148 20.307 -0.03 c
+20.248 0.087 20.137 0.147 19.983 0.147 c
+19.825 0.147 19.708 0.08 19.63 -0.044 c
+19.63 -1.455 l
+19.708 -1.584 19.829 -1.646 19.997 -1.646 c
+20.145 -1.646 20.248 -1.584 20.307 -1.455 c
+20.373 -1.32 20.409 -1.114 20.409 -0.838 c
+h
+21.375 -0.647 m
+21.375 -0.199 21.483 0.154 21.699 0.411 c
+21.913 0.675 22.206 0.808 22.582 0.808 c
+22.964 0.808 23.257 0.675 23.463 0.411 c
+23.677 0.154 23.787 -0.199 23.787 -0.647 c
+23.787 -0.838 l
+23.787 -1.301 23.677 -1.658 23.463 -1.912 c
+23.257 -2.168 22.964 -2.294 22.582 -2.294 c
+22.199 -2.294 21.898 -2.168 21.684 -1.912 c
+21.479 -1.646 21.375 -1.291 21.375 -0.838 c
+h
+22.154 -0.838 m
+22.154 -1.378 22.295 -1.646 22.582 -1.646 c
+22.846 -1.646 22.985 -1.422 23.008 -0.971 c
+23.022 -0.647 l
+23.022 -0.375 22.981 -0.173 22.904 -0.044 c
+22.823 0.091 22.717 0.161 22.582 0.161 c
+22.453 0.161 22.349 0.091 22.272 -0.044 c
+22.192 -0.173 22.154 -0.375 22.154 -0.647 c
+h
+25.41 -1.441 m
+25.41 -1.374 25.374 -1.309 25.308 -1.25 c
+25.249 -1.191 25.109 -1.118 24.897 -1.029 c
+24.573 -0.894 24.352 -0.757 24.234 -0.618 c
+24.117 -0.482 24.059 -0.31 24.059 -0.103 c
+24.059 0.161 24.151 0.374 24.338 0.544 c
+24.521 0.72 24.772 0.808 25.088 0.808 c
+25.41 0.808 25.668 0.72 25.867 0.544 c
+26.061 0.374 26.16 0.151 26.16 -0.133 c
+25.381 -0.133 l
+25.381 0.11 25.279 0.235 25.073 0.235 c
+24.992 0.235 24.926 0.205 24.867 0.147 c
+24.816 0.095 24.793 0.029 24.793 -0.059 c
+24.793 -0.129 24.822 -0.188 24.882 -0.235 c
+24.94 -0.287 25.076 -0.36 25.293 -0.456 c
+25.616 -0.574 25.84 -0.706 25.969 -0.853 c
+26.106 -0.992 26.175 -1.176 26.175 -1.411 c
+26.175 -1.676 26.073 -1.893 25.867 -2.058 c
+25.668 -2.216 25.41 -2.294 25.088 -2.294 c
+24.859 -2.294 24.664 -2.249 24.5 -2.161 c
+24.33 -2.073 24.198 -1.956 24.103 -1.808 c
+24.014 -1.654 23.97 -1.485 23.97 -1.309 c
+24.705 -1.309 l
+24.712 -1.449 24.749 -1.551 24.808 -1.617 c
+24.867 -1.687 24.963 -1.721 25.102 -1.721 c
+25.308 -1.721 25.41 -1.628 25.41 -1.441 c
+27.311 -2.234 -0.779 2.983 re
+26.487 1.514 m
+26.487 1.639 26.524 1.741 26.605 1.822 c
+26.682 1.899 26.785 1.94 26.914 1.94 c
+27.039 1.94 27.141 1.899 27.222 1.822 c
+27.299 1.741 27.34 1.639 27.34 1.514 c
+27.34 1.396 27.299 1.296 27.222 1.219 c
+27.153 1.138 27.05 1.102 26.914 1.102 c
+26.785 1.102 26.682 1.138 26.605 1.219 c
+26.524 1.296 26.487 1.396 26.487 1.514 c
+28.726 1.484 m
+28.726 0.749 l
+29.122 0.749 l
+29.122 0.161 l
+28.726 0.161 l
+28.726 -1.324 l
+28.726 -1.441 28.74 -1.526 28.77 -1.573 c
+28.806 -1.613 28.872 -1.632 28.961 -1.632 c
+29.038 -1.632 29.1 -1.625 29.152 -1.603 c
+29.137 -2.22 l
+29.009 -2.268 28.865 -2.294 28.71 -2.294 c
+28.211 -2.294 27.954 -2.007 27.947 -1.426 c
+27.947 0.161 l
+27.608 0.161 l
+27.608 0.749 l
+27.947 0.749 l
+27.947 1.484 l
+h
+29.269 -0.647 m
+29.269 -0.199 29.376 0.154 29.593 0.411 c
+29.805 0.675 30.1 0.808 30.474 0.808 c
+30.856 0.808 31.151 0.675 31.357 0.411 c
+31.569 0.154 31.679 -0.199 31.679 -0.647 c
+31.679 -0.838 l
+31.679 -1.301 31.569 -1.658 31.357 -1.912 c
+31.151 -2.168 30.856 -2.294 30.474 -2.294 c
+30.092 -2.294 29.791 -2.168 29.578 -1.912 c
+29.372 -1.646 29.269 -1.291 29.269 -0.838 c
+h
+30.048 -0.838 m
+30.048 -1.378 30.188 -1.646 30.474 -1.646 c
+30.739 -1.646 30.879 -1.422 30.9 -0.971 c
+30.916 -0.647 l
+30.916 -0.375 30.875 -0.173 30.798 -0.044 c
+30.717 0.091 30.611 0.161 30.474 0.161 c
+30.345 0.161 30.243 0.091 30.166 -0.044 c
+30.085 -0.173 30.048 -0.375 30.048 -0.647 c
+h
+33.451 0 m
+33.202 0.014 l
+32.984 0.014 32.837 -0.081 32.76 -0.265 c
+32.76 -2.234 l
+31.981 -2.234 l
+31.981 0.749 l
+32.716 0.749 l
+32.745 0.426 l
+32.863 0.679 33.028 0.808 33.246 0.808 c
+33.333 0.808 33.407 0.793 33.466 0.764 c
+h
+34.553 -2.234 -0.779 2.983 re
+33.73 1.514 m
+33.73 1.639 33.767 1.741 33.848 1.822 c
+33.925 1.899 34.028 1.94 34.156 1.94 c
+34.281 1.94 34.384 1.899 34.465 1.822 c
+34.542 1.741 34.583 1.639 34.583 1.514 c
+34.583 1.396 34.542 1.296 34.465 1.219 c
+34.395 1.138 34.293 1.102 34.156 1.102 c
+34.028 1.102 33.925 1.138 33.848 1.219 c
+33.767 1.296 33.73 1.396 33.73 1.514 c
+36.263 -2.294 m
+35.858 -2.294 35.546 -2.176 35.322 -1.941 c
+35.105 -1.698 34.998 -1.353 34.998 -0.912 c
+34.998 -0.662 l
+34.998 -0.192 35.101 0.168 35.307 0.426 c
+35.513 0.679 35.806 0.808 36.188 0.808 c
+36.56 0.808 36.839 0.683 37.027 0.44 c
+37.221 0.205 37.321 -0.148 37.321 -0.618 c
+37.321 -1 l
+35.777 -1 l
+35.785 -1.228 35.829 -1.393 35.91 -1.5 c
+35.997 -1.599 36.134 -1.646 36.321 -1.646 c
+36.575 -1.646 36.791 -1.555 36.968 -1.368 c
+37.277 -1.852 l
+37.177 -1.981 37.034 -2.087 36.851 -2.176 c
+36.674 -2.253 36.475 -2.294 36.263 -2.294 c
+35.777 -0.456 m
+36.556 -0.456 l
+36.556 -0.383 l
+36.556 -0.206 36.527 -0.074 36.468 0.014 c
+36.409 0.11 36.31 0.161 36.174 0.161 c
+36.045 0.161 35.947 0.11 35.88 0.014 c
+35.821 -0.085 35.785 -0.243 35.777 -0.456 c
+38.901 -1.441 m
+38.901 -1.374 38.864 -1.309 38.798 -1.25 c
+38.739 -1.191 38.599 -1.118 38.386 -1.029 c
+38.063 -0.894 37.842 -0.757 37.725 -0.618 c
+37.607 -0.482 37.549 -0.31 37.549 -0.103 c
+37.549 0.161 37.64 0.374 37.828 0.544 c
+38.012 0.72 38.262 0.808 38.577 0.808 c
+38.901 0.808 39.158 0.72 39.357 0.544 c
+39.552 0.374 39.65 0.151 39.65 -0.133 c
+38.871 -0.133 l
+38.871 0.11 38.769 0.235 38.563 0.235 c
+38.482 0.235 38.416 0.205 38.357 0.147 c
+38.305 0.095 38.283 0.029 38.283 -0.059 c
+38.283 -0.129 38.313 -0.188 38.372 -0.235 c
+38.43 -0.287 38.567 -0.36 38.783 -0.456 c
+39.107 -0.574 39.33 -0.706 39.459 -0.853 c
+39.596 -0.992 39.665 -1.176 39.665 -1.411 c
+39.665 -1.676 39.562 -1.893 39.357 -2.058 c
+39.158 -2.216 38.901 -2.294 38.577 -2.294 c
+38.349 -2.294 38.154 -2.249 37.99 -2.161 c
+37.821 -2.073 37.688 -1.956 37.593 -1.808 c
+37.504 -1.654 37.46 -1.485 37.46 -1.309 c
+38.195 -1.309 l
+38.203 -1.449 38.239 -1.551 38.298 -1.617 c
+38.357 -1.687 38.453 -1.721 38.592 -1.721 c
+38.798 -1.721 38.901 -1.628 38.901 -1.441 c
+f
+Q
+ endstream endobj 38 0 obj <</BBox[543.633 459.986 581.22 454.709]/Group 74 0 R/Length 9136/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 544.8536 457.5314 cm
+0 0 m
+-0.706 0 l
+-0.706 -1.617 l
+-1.22 -1.617 l
+-1.22 2.396 l
+-0.088 2.396 l
+0.302 2.396 0.595 2.293 0.794 2.087 c
+1 1.881 1.103 1.579 1.103 1.19 c
+1.103 0.944 1.048 0.727 0.941 0.544 c
+0.831 0.357 0.68 0.213 0.485 0.118 c
+1.25 -1.588 l
+1.25 -1.617 l
+0.721 -1.617 l
+h
+-0.706 0.44 m
+-0.088 0.44 l
+0.118 0.44 0.283 0.507 0.412 0.646 c
+0.537 0.783 0.603 0.962 0.603 1.19 c
+0.603 1.697 0.368 1.955 -0.103 1.955 c
+-0.706 1.955 l
+h
+2.58 -1.676 m
+2.205 -1.676 1.922 -1.569 1.727 -1.353 c
+1.529 -1.129 1.434 -0.802 1.434 -0.368 c
+1.434 0 l
+1.434 0.44 1.525 0.786 1.713 1.043 c
+1.908 1.297 2.183 1.425 2.536 1.425 c
+2.878 1.425 3.132 1.311 3.3 1.087 c
+3.477 0.86 3.568 0.515 3.579 0.044 c
+3.579 -0.265 l
+1.918 -0.265 l
+1.918 -0.339 l
+1.918 -0.661 1.977 -0.897 2.095 -1.044 c
+2.213 -1.183 2.382 -1.249 2.61 -1.249 c
+2.756 -1.249 2.881 -1.228 2.992 -1.176 c
+3.098 -1.118 3.201 -1.029 3.3 -0.912 c
+3.55 -1.22 l
+3.344 -1.525 3.021 -1.676 2.58 -1.676 c
+2.536 0.999 m
+2.33 0.999 2.176 0.929 2.08 0.793 c
+1.981 0.654 1.926 0.44 1.918 0.147 c
+3.094 0.147 l
+3.094 0.22 l
+3.072 0.492 3.021 0.69 2.933 0.808 c
+2.845 0.933 2.712 0.999 2.536 0.999 c
+4.447 1.367 m
+4.462 1.087 l
+4.638 1.311 4.877 1.425 5.182 1.425 c
+5.513 1.425 5.744 1.278 5.873 0.985 c
+6.056 1.278 6.317 1.425 6.652 1.425 c
+7.21 1.425 7.493 1.08 7.504 0.397 c
+7.504 -1.617 l
+7.019 -1.617 l
+7.019 0.353 l
+7.019 0.565 6.978 0.723 6.901 0.823 c
+6.82 0.929 6.689 0.985 6.504 0.985 c
+6.357 0.985 6.24 0.926 6.151 0.808 c
+6.064 0.698 6.008 0.558 5.991 0.382 c
+5.991 -1.617 l
+5.505 -1.617 l
+5.505 0.367 l
+5.494 0.779 5.322 0.985 4.991 0.985 c
+4.744 0.985 4.572 0.86 4.476 0.617 c
+4.476 -1.617 l
+3.992 -1.617 l
+3.992 1.367 l
+h
+7.849 0.014 m
+7.849 0.444 7.952 0.786 8.158 1.043 c
+8.372 1.297 8.651 1.425 8.996 1.425 c
+9.338 1.425 9.613 1.297 9.819 1.043 c
+10.032 0.797 10.147 0.463 10.157 0.044 c
+10.157 -0.265 l
+10.157 -0.699 10.047 -1.04 9.834 -1.294 c
+9.628 -1.551 9.349 -1.676 8.996 -1.676 c
+8.651 -1.676 8.379 -1.555 8.173 -1.309 c
+7.967 -1.066 7.857 -0.732 7.849 -0.309 c
+h
+8.335 -0.265 m
+8.335 -0.581 8.393 -0.823 8.511 -1 c
+8.636 -1.169 8.798 -1.249 8.996 -1.249 c
+9.426 -1.249 9.65 -0.941 9.673 -0.324 c
+9.673 0.014 l
+9.673 0.316 9.606 0.558 9.482 0.735 c
+9.363 0.911 9.202 0.999 8.996 0.999 c
+8.798 0.999 8.636 0.911 8.511 0.735 c
+8.393 0.558 8.335 0.316 8.335 0.014 c
+h
+11.231 2.087 m
+11.231 1.367 l
+11.686 1.367 l
+11.686 0.97 l
+11.231 0.97 l
+11.231 -0.882 l
+11.231 -1 11.248 -1.088 11.289 -1.147 c
+11.326 -1.206 11.396 -1.235 11.495 -1.235 c
+11.554 -1.235 11.616 -1.228 11.686 -1.206 c
+11.686 -1.617 l
+11.568 -1.654 11.454 -1.676 11.348 -1.676 c
+11.15 -1.676 10.999 -1.61 10.893 -1.47 c
+10.793 -1.334 10.745 -1.139 10.745 -0.882 c
+10.745 0.97 l
+10.29 0.97 l
+10.29 1.367 l
+10.745 1.367 l
+10.745 2.087 l
+h
+13.207 -1.676 m
+12.833 -1.676 12.549 -1.569 12.355 -1.353 c
+12.156 -1.129 12.061 -0.802 12.061 -0.368 c
+12.061 0 l
+12.061 0.44 12.152 0.786 12.341 1.043 c
+12.535 1.297 12.811 1.425 13.164 1.425 c
+13.505 1.425 13.758 1.311 13.928 1.087 c
+14.104 0.86 14.196 0.515 14.207 0.044 c
+14.207 -0.265 l
+12.546 -0.265 l
+12.546 -0.339 l
+12.546 -0.661 12.605 -0.897 12.723 -1.044 c
+12.84 -1.183 13.009 -1.249 13.237 -1.249 c
+13.384 -1.249 13.509 -1.228 13.619 -1.176 c
+13.725 -1.118 13.829 -1.029 13.928 -0.912 c
+14.178 -1.22 l
+13.972 -1.525 13.648 -1.676 13.207 -1.676 c
+13.164 0.999 m
+12.958 0.999 12.803 0.929 12.707 0.793 c
+12.609 0.654 12.553 0.44 12.546 0.147 c
+13.722 0.147 l
+13.722 0.22 l
+13.7 0.492 13.648 0.69 13.56 0.808 c
+13.472 0.933 13.34 0.999 13.164 0.999 c
+17.058 0.911 m
+16.989 0.918 16.915 0.926 16.838 0.926 c
+16.581 0.926 16.405 0.786 16.309 0.515 c
+16.309 -1.617 l
+15.824 -1.617 l
+15.824 1.367 l
+16.294 1.367 l
+16.309 1.058 l
+16.434 1.3 16.617 1.425 16.852 1.425 c
+16.93 1.425 16.993 1.411 17.044 1.381 c
+h
+18.437 -1.676 m
+18.062 -1.676 17.779 -1.569 17.584 -1.353 c
+17.386 -1.129 17.29 -0.802 17.29 -0.368 c
+17.29 0 l
+17.29 0.44 17.382 0.786 17.569 1.043 c
+17.764 1.297 18.04 1.425 18.392 1.425 c
+18.734 1.425 18.988 1.311 19.157 1.087 c
+19.333 0.86 19.425 0.515 19.437 0.044 c
+19.437 -0.265 l
+17.775 -0.265 l
+17.775 -0.339 l
+17.775 -0.661 17.834 -0.897 17.951 -1.044 c
+18.069 -1.183 18.238 -1.249 18.466 -1.249 c
+18.613 -1.249 18.738 -1.228 18.849 -1.176 c
+18.955 -1.118 19.057 -1.029 19.157 -0.912 c
+19.406 -1.22 l
+19.201 -1.525 18.878 -1.676 18.437 -1.676 c
+18.392 0.999 m
+18.186 0.999 18.032 0.929 17.937 0.793 c
+17.837 0.654 17.783 0.44 17.775 0.147 c
+18.951 0.147 l
+18.951 0.22 l
+18.929 0.492 18.878 0.69 18.789 0.808 c
+18.701 0.933 18.569 0.999 18.392 0.999 c
+21.993 -0.265 m
+21.993 -0.736 21.909 -1.088 21.744 -1.324 c
+21.575 -1.559 21.336 -1.676 21.024 -1.676 c
+20.719 -1.676 20.487 -1.565 20.333 -1.338 c
+20.333 -2.764 l
+19.848 -2.764 l
+19.848 1.367 l
+20.289 1.367 l
+20.318 1.028 l
+20.472 1.294 20.704 1.425 21.009 1.425 c
+21.34 1.425 21.586 1.308 21.744 1.072 c
+21.909 0.845 21.993 0.507 21.993 0.058 c
+h
+21.509 0.014 m
+21.509 0.345 21.454 0.592 21.347 0.75 c
+21.247 0.904 21.086 0.985 20.862 0.985 c
+20.627 0.985 20.451 0.867 20.333 0.632 c
+20.333 -0.912 l
+20.451 -1.139 20.63 -1.249 20.877 -1.249 c
+21.089 -1.249 21.247 -1.172 21.347 -1.014 c
+21.454 -0.86 21.509 -0.618 21.509 -0.294 c
+h
+22.346 0.014 m
+22.346 0.444 22.45 0.786 22.655 1.043 c
+22.868 1.297 23.148 1.425 23.493 1.425 c
+23.835 1.425 24.11 1.297 24.316 1.043 c
+24.53 0.797 24.644 0.463 24.654 0.044 c
+24.654 -0.265 l
+24.654 -0.699 24.544 -1.04 24.331 -1.294 c
+24.125 -1.551 23.846 -1.676 23.493 -1.676 c
+23.148 -1.676 22.876 -1.555 22.67 -1.309 c
+22.464 -1.066 22.354 -0.732 22.346 -0.309 c
+h
+22.832 -0.265 m
+22.832 -0.581 22.89 -0.823 23.008 -1 c
+23.133 -1.169 23.295 -1.249 23.493 -1.249 c
+23.923 -1.249 24.147 -0.941 24.169 -0.324 c
+24.169 0.014 l
+24.169 0.316 24.103 0.558 23.979 0.735 c
+23.861 0.911 23.699 0.999 23.493 0.999 c
+23.295 0.999 23.133 0.911 23.008 0.735 c
+22.89 0.558 22.832 0.316 22.832 0.014 c
+h
+26.535 -0.853 m
+26.535 -0.746 26.495 -0.659 26.418 -0.588 c
+26.337 -0.511 26.186 -0.423 25.962 -0.324 c
+25.698 -0.217 25.511 -0.125 25.404 -0.044 c
+25.294 0.033 25.216 0.121 25.169 0.22 c
+25.118 0.316 25.095 0.434 25.095 0.573 c
+25.095 0.816 25.184 1.018 25.359 1.176 c
+25.536 1.341 25.76 1.425 26.036 1.425 c
+26.33 1.425 26.566 1.338 26.741 1.161 c
+26.918 0.992 27.006 0.779 27.006 0.515 c
+26.521 0.515 l
+26.521 0.65 26.47 0.764 26.375 0.852 c
+26.286 0.947 26.172 0.999 26.036 0.999 c
+25.889 0.999 25.775 0.959 25.698 0.881 c
+25.617 0.812 25.581 0.712 25.581 0.588 c
+25.581 0.488 25.61 0.411 25.669 0.353 c
+25.727 0.294 25.867 0.213 26.095 0.118 c
+26.454 -0.03 26.701 -0.173 26.83 -0.309 c
+26.965 -0.437 27.036 -0.611 27.036 -0.823 c
+27.036 -1.081 26.94 -1.287 26.757 -1.441 c
+26.58 -1.599 26.344 -1.676 26.051 -1.676 c
+25.735 -1.676 25.481 -1.588 25.286 -1.411 c
+25.099 -1.228 25.007 -0.996 25.007 -0.721 c
+25.492 -0.721 l
+25.5 -0.89 25.551 -1.022 25.639 -1.118 c
+25.735 -1.206 25.874 -1.249 26.051 -1.249 c
+26.205 -1.249 26.323 -1.216 26.404 -1.147 c
+26.492 -1.081 26.535 -0.981 26.535 -0.853 c
+28.021 -1.617 -0.501 2.984 re
+28.05 2.161 m
+28.05 2.072 28.024 1.999 27.977 1.94 c
+27.936 1.888 27.866 1.866 27.771 1.866 c
+27.682 1.866 27.613 1.888 27.565 1.94 c
+27.524 1.999 27.506 2.065 27.506 2.146 c
+27.506 2.234 27.524 2.308 27.565 2.366 c
+27.613 2.425 27.682 2.454 27.771 2.454 c
+27.866 2.454 27.936 2.425 27.977 2.366 c
+28.024 2.308 28.05 2.238 28.05 2.161 c
+29.328 2.087 m
+29.328 1.367 l
+29.785 1.367 l
+29.785 0.97 l
+29.328 0.97 l
+29.328 -0.882 l
+29.328 -1 29.347 -1.088 29.388 -1.147 c
+29.424 -1.206 29.494 -1.235 29.593 -1.235 c
+29.652 -1.235 29.714 -1.228 29.785 -1.206 c
+29.785 -1.617 l
+29.667 -1.654 29.552 -1.676 29.446 -1.676 c
+29.248 -1.676 29.097 -1.61 28.991 -1.47 c
+28.891 -1.334 28.844 -1.139 28.844 -0.882 c
+28.844 0.97 l
+28.388 0.97 l
+28.388 1.367 l
+28.844 1.367 l
+28.844 2.087 l
+h
+30.097 0.014 m
+30.097 0.444 30.2 0.786 30.406 1.043 c
+30.618 1.297 30.898 1.425 31.243 1.425 c
+31.585 1.425 31.861 1.297 32.066 1.043 c
+32.28 0.797 32.393 0.463 32.405 0.044 c
+32.405 -0.265 l
+32.405 -0.699 32.295 -1.04 32.081 -1.294 c
+31.875 -1.551 31.596 -1.676 31.243 -1.676 c
+30.898 -1.676 30.626 -1.555 30.42 -1.309 c
+30.215 -1.066 30.104 -0.732 30.097 -0.309 c
+h
+30.582 -0.265 m
+30.582 -0.581 30.641 -0.823 30.758 -1 c
+30.883 -1.169 31.044 -1.249 31.243 -1.249 c
+31.673 -1.249 31.898 -0.941 31.919 -0.324 c
+31.919 0.014 l
+31.919 0.316 31.853 0.558 31.728 0.735 c
+31.611 0.911 31.449 0.999 31.243 0.999 c
+31.044 0.999 30.883 0.911 30.758 0.735 c
+30.641 0.558 30.582 0.316 30.582 0.014 c
+h
+34.076 0.911 m
+34.007 0.918 33.933 0.926 33.856 0.926 c
+33.598 0.926 33.423 0.786 33.327 0.515 c
+33.327 -1.617 l
+32.842 -1.617 l
+32.842 1.367 l
+33.313 1.367 l
+33.327 1.058 l
+33.452 1.3 33.635 1.425 33.87 1.425 c
+33.948 1.425 34.011 1.411 34.061 1.381 c
+h
+35.308 -0.809 m
+35.852 1.367 l
+36.366 1.367 l
+35.395 -2.043 l
+35.326 -2.297 35.223 -2.488 35.087 -2.617 c
+34.948 -2.753 34.797 -2.822 34.631 -2.822 c
+34.562 -2.822 34.477 -2.808 34.381 -2.778 c
+34.381 -2.367 l
+34.485 -2.382 l
+34.62 -2.382 34.726 -2.345 34.807 -2.278 c
+34.896 -2.209 34.962 -2.091 35.013 -1.926 c
+35.102 -1.588 l
+34.234 1.367 l
+34.763 1.367 l
+h
+f
+Q
+ endstream endobj 39 0 obj <</BBox[547.65 453.562 561.199 449.27]/Group 75 0 R/Length 3370/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 548.1057 452.3131 cm
+0 0 m
+0.015 -0.324 l
+0.198 -0.07 0.441 0.058 0.736 0.058 c
+1.264 0.058 1.533 -0.294 1.544 -1 c
+1.544 -2.984 l
+1.058 -2.984 l
+1.058 -1.029 l
+1.058 -0.794 1.018 -0.628 0.941 -0.53 c
+0.86 -0.434 0.742 -0.382 0.588 -0.382 c
+0.47 -0.382 0.36 -0.422 0.265 -0.5 c
+0.166 -0.58 0.088 -0.688 0.03 -0.823 c
+0.03 -2.984 l
+-0.455 -2.984 l
+-0.455 0 l
+h
+3.628 -2.984 m
+3.598 -2.918 3.576 -2.808 3.568 -2.66 c
+3.392 -2.918 3.172 -3.043 2.907 -3.043 c
+2.631 -3.043 2.415 -2.969 2.261 -2.822 c
+2.113 -2.668 2.04 -2.452 2.04 -2.176 c
+2.04 -1.874 2.143 -1.632 2.348 -1.455 c
+2.554 -1.272 2.837 -1.176 3.201 -1.176 c
+3.554 -1.176 l
+3.554 -0.852 l
+3.554 -0.676 3.514 -0.555 3.437 -0.485 c
+3.356 -0.408 3.238 -0.368 3.084 -0.368 c
+2.937 -0.368 2.812 -0.412 2.716 -0.5 c
+2.628 -0.588 2.583 -0.698 2.583 -0.823 c
+2.099 -0.823 l
+2.099 -0.676 2.143 -0.537 2.231 -0.397 c
+2.319 -0.25 2.437 -0.14 2.583 -0.059 c
+2.739 0.018 2.911 0.058 3.098 0.058 c
+3.41 0.058 3.645 -0.023 3.803 -0.177 c
+3.958 -0.324 4.039 -0.544 4.039 -0.838 c
+4.039 -2.338 l
+4.046 -2.573 4.083 -2.774 4.142 -2.94 c
+4.142 -2.984 l
+h
+2.98 -2.602 m
+3.098 -2.602 3.209 -2.569 3.319 -2.499 c
+3.425 -2.433 3.502 -2.348 3.554 -2.249 c
+3.554 -1.544 l
+3.289 -1.544 l
+3.054 -1.544 2.866 -1.595 2.731 -1.69 c
+2.602 -1.79 2.54 -1.933 2.54 -2.117 c
+2.54 -2.286 2.569 -2.407 2.628 -2.484 c
+2.694 -2.565 2.812 -2.602 2.98 -2.602 c
+5.075 0 m
+5.09 -0.279 l
+5.266 -0.056 5.505 0.058 5.81 0.058 c
+6.141 0.058 6.373 -0.088 6.501 -0.382 c
+6.685 -0.088 6.945 0.058 7.28 0.058 c
+7.838 0.058 8.121 -0.287 8.133 -0.97 c
+8.133 -2.984 l
+7.647 -2.984 l
+7.647 -1.014 l
+7.647 -0.802 7.607 -0.643 7.53 -0.544 c
+7.449 -0.437 7.317 -0.382 7.133 -0.382 c
+6.986 -0.382 6.868 -0.441 6.78 -0.559 c
+6.692 -0.669 6.637 -0.809 6.619 -0.985 c
+6.619 -2.984 l
+6.134 -2.984 l
+6.134 -1 l
+6.122 -0.588 5.95 -0.382 5.619 -0.382 c
+5.373 -0.382 5.2 -0.507 5.104 -0.75 c
+5.104 -2.984 l
+4.62 -2.984 l
+4.62 0 l
+h
+9.639 -3.043 m
+9.264 -3.043 8.981 -2.936 8.787 -2.72 c
+8.588 -2.496 8.493 -2.168 8.493 -1.735 c
+8.493 -1.367 l
+8.493 -0.927 8.584 -0.58 8.772 -0.324 c
+8.967 -0.07 9.243 0.058 9.596 0.058 c
+9.937 0.058 10.19 -0.056 10.359 -0.279 c
+10.536 -0.507 10.628 -0.852 10.639 -1.323 c
+10.639 -1.632 l
+8.978 -1.632 l
+8.978 -1.706 l
+8.978 -2.028 9.037 -2.263 9.154 -2.411 c
+9.272 -2.55 9.441 -2.616 9.669 -2.616 c
+9.816 -2.616 9.941 -2.595 10.051 -2.543 c
+10.157 -2.484 10.261 -2.396 10.359 -2.278 c
+10.61 -2.587 l
+10.404 -2.892 10.08 -3.043 9.639 -3.043 c
+9.596 -0.368 m
+9.39 -0.368 9.235 -0.437 9.139 -0.574 c
+9.041 -0.713 8.985 -0.927 8.978 -1.22 c
+10.153 -1.22 l
+10.153 -1.147 l
+10.132 -0.875 10.08 -0.676 9.993 -0.559 c
+9.904 -0.434 9.771 -0.368 9.596 -0.368 c
+10.947 -1.353 m
+10.947 -0.893 11.028 -0.544 11.198 -0.309 c
+11.374 -0.067 11.624 0.058 11.947 0.058 c
+12.23 0.058 12.451 -0.059 12.609 -0.294 c
+12.609 1.249 l
+13.093 1.249 l
+13.093 -2.984 l
+12.653 -2.984 l
+12.623 -2.66 l
+12.465 -2.918 12.241 -3.043 11.947 -3.043 c
+11.631 -3.043 11.389 -2.926 11.212 -2.691 c
+11.036 -2.448 10.947 -2.103 10.947 -1.661 c
+h
+11.433 -1.632 m
+11.433 -1.966 11.481 -2.213 11.58 -2.367 c
+11.676 -2.525 11.836 -2.602 12.065 -2.602 c
+12.307 -2.602 12.491 -2.484 12.609 -2.249 c
+12.609 -0.735 l
+12.48 -0.5 12.3 -0.382 12.065 -0.382 c
+11.836 -0.382 11.676 -0.463 11.58 -0.617 c
+11.481 -0.775 11.433 -1.014 11.433 -1.338 c
+h
+f
+Q
+ endstream endobj 40 0 obj <</BBox[628.727 237.005 656.757 232.713]/Group 76 0 R/Length 5146/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 630.1232 234.7709 cm
+0 0 m
+0.808 2.013 l
+1.382 2.013 l
+0.25 -0.5 l
+0.25 -1.999 l
+-0.264 -1.999 l
+-0.264 -0.5 l
+-1.396 2.013 l
+-0.823 2.013 l
+h
+1.386 -0.368 m
+1.386 0.062 1.488 0.404 1.694 0.661 c
+1.907 0.914 2.186 1.043 2.531 1.043 c
+2.874 1.043 3.15 0.914 3.355 0.661 c
+3.568 0.415 3.682 0.081 3.693 -0.339 c
+3.693 -0.647 l
+3.693 -1.081 3.583 -1.422 3.37 -1.676 c
+3.164 -1.933 2.884 -2.058 2.531 -2.058 c
+2.186 -2.058 1.914 -1.937 1.708 -1.691 c
+1.503 -1.448 1.392 -1.114 1.386 -0.691 c
+h
+1.87 -0.647 m
+1.87 -0.963 1.93 -1.206 2.047 -1.382 c
+2.172 -1.551 2.333 -1.632 2.531 -1.632 c
+2.961 -1.632 3.186 -1.324 3.208 -0.706 c
+3.208 -0.368 l
+3.208 -0.067 3.142 0.176 3.017 0.353 c
+2.899 0.529 2.738 0.617 2.531 0.617 c
+2.333 0.617 2.172 0.529 2.047 0.353 c
+1.93 0.176 1.87 -0.067 1.87 -0.368 c
+h
+5.644 -1.735 m
+5.486 -1.952 5.251 -2.058 4.939 -2.058 c
+4.674 -2.058 4.469 -1.966 4.322 -1.779 c
+4.182 -1.595 4.116 -1.32 4.116 -0.956 c
+4.116 0.985 l
+4.601 0.985 l
+4.601 -0.927 l
+4.601 -1.389 4.74 -1.617 5.027 -1.617 c
+5.321 -1.617 5.519 -1.484 5.629 -1.22 c
+5.629 0.985 l
+6.13 0.985 l
+6.13 -1.999 l
+5.659 -1.999 l
+h
+7.783 -0.368 m
+7.783 0.091 7.864 0.44 8.033 0.675 c
+8.21 0.918 8.459 1.043 8.783 1.043 c
+9.066 1.043 9.286 0.926 9.444 0.691 c
+9.444 2.234 l
+9.93 2.234 l
+9.93 -1.999 l
+9.488 -1.999 l
+9.459 -1.676 l
+9.301 -1.933 9.076 -2.058 8.783 -2.058 c
+8.467 -2.058 8.224 -1.941 8.048 -1.706 c
+7.871 -1.463 7.783 -1.118 7.783 -0.676 c
+h
+8.268 -0.647 m
+8.268 -0.981 8.316 -1.228 8.415 -1.382 c
+8.511 -1.54 8.673 -1.617 8.9 -1.617 c
+9.143 -1.617 9.326 -1.5 9.444 -1.264 c
+9.444 0.249 l
+9.315 0.484 9.135 0.602 8.9 0.602 c
+8.673 0.602 8.511 0.521 8.415 0.367 c
+8.316 0.209 8.268 -0.03 8.268 -0.353 c
+h
+10.396 -0.368 m
+10.396 0.062 10.499 0.404 10.705 0.661 c
+10.917 0.914 11.197 1.043 11.543 1.043 c
+11.884 1.043 12.16 0.914 12.366 0.661 c
+12.579 0.415 12.692 0.081 12.704 -0.339 c
+12.704 -0.647 l
+12.704 -1.081 12.594 -1.422 12.38 -1.676 c
+12.174 -1.933 11.896 -2.058 11.543 -2.058 c
+11.197 -2.058 10.925 -1.937 10.72 -1.691 c
+10.514 -1.448 10.404 -1.114 10.396 -0.691 c
+h
+10.881 -0.647 m
+10.881 -0.963 10.94 -1.206 11.057 -1.382 c
+11.183 -1.551 11.344 -1.632 11.543 -1.632 c
+11.973 -1.632 12.197 -1.324 12.218 -0.706 c
+12.218 -0.368 l
+12.218 -0.067 12.153 0.176 12.027 0.353 c
+11.91 0.529 11.748 0.617 11.543 0.617 c
+11.344 0.617 11.183 0.529 11.057 0.353 c
+10.94 0.176 10.881 -0.067 10.881 -0.368 c
+h
+15.879 -1.999 m
+15.85 -1.933 15.827 -1.823 15.819 -1.676 c
+15.644 -1.933 15.423 -2.058 15.158 -2.058 c
+14.883 -2.058 14.666 -1.985 14.512 -1.837 c
+14.365 -1.683 14.291 -1.467 14.291 -1.191 c
+14.291 -0.89 14.394 -0.647 14.6 -0.47 c
+14.805 -0.287 15.089 -0.191 15.453 -0.191 c
+15.805 -0.191 l
+15.805 0.132 l
+15.805 0.309 15.765 0.43 15.688 0.5 c
+15.607 0.577 15.489 0.617 15.335 0.617 c
+15.188 0.617 15.063 0.573 14.967 0.484 c
+14.879 0.397 14.835 0.286 14.835 0.162 c
+14.35 0.162 l
+14.35 0.309 14.394 0.448 14.483 0.588 c
+14.57 0.735 14.688 0.845 14.835 0.926 c
+14.99 1.003 15.162 1.043 15.349 1.043 c
+15.661 1.043 15.897 0.962 16.055 0.808 c
+16.209 0.661 16.29 0.44 16.29 0.147 c
+16.29 -1.353 l
+16.297 -1.588 16.334 -1.79 16.393 -1.955 c
+16.393 -1.999 l
+h
+15.232 -1.617 m
+15.349 -1.617 15.46 -1.584 15.57 -1.515 c
+15.676 -1.448 15.754 -1.364 15.805 -1.264 c
+15.805 -0.559 l
+15.541 -0.559 l
+15.306 -0.559 15.118 -0.611 14.982 -0.706 c
+14.853 -0.805 14.791 -0.948 14.791 -1.132 c
+14.791 -1.301 14.82 -1.422 14.879 -1.5 c
+14.946 -1.58 15.063 -1.617 15.232 -1.617 c
+17.4 -1.999 -0.5 4.233 re
+18.601 -1.999 -0.5 4.233 re
+21.111 1.705 m
+21.111 0.985 l
+21.567 0.985 l
+21.567 0.588 l
+21.111 0.588 l
+21.111 -1.264 l
+21.111 -1.382 21.13 -1.47 21.17 -1.529 c
+21.207 -1.588 21.277 -1.617 21.376 -1.617 c
+21.435 -1.617 21.498 -1.61 21.567 -1.588 c
+21.567 -1.999 l
+21.45 -2.036 21.336 -2.058 21.229 -2.058 c
+21.03 -2.058 20.88 -1.992 20.773 -1.852 c
+20.675 -1.717 20.627 -1.521 20.627 -1.264 c
+20.627 0.588 l
+20.17 0.588 l
+20.17 0.985 l
+20.627 0.985 l
+20.627 1.705 l
+h
+22.519 0.675 m
+22.703 0.918 22.938 1.043 23.225 1.043 c
+23.754 1.043 24.022 0.691 24.033 -0.015 c
+24.033 -1.999 l
+23.548 -1.999 l
+23.548 -0.044 l
+23.548 0.191 23.507 0.357 23.43 0.455 c
+23.349 0.551 23.232 0.602 23.077 0.602 c
+22.96 0.602 22.85 0.562 22.755 0.484 c
+22.655 0.404 22.578 0.297 22.519 0.162 c
+22.519 -1.999 l
+22.034 -1.999 l
+22.034 2.234 l
+22.519 2.234 l
+h
+25.635 -2.058 m
+25.261 -2.058 24.978 -1.952 24.783 -1.735 c
+24.584 -1.511 24.488 -1.183 24.488 -0.75 c
+24.488 -0.383 l
+24.488 0.058 24.581 0.404 24.768 0.661 c
+24.962 0.914 25.238 1.043 25.591 1.043 c
+25.932 1.043 26.186 0.929 26.356 0.706 c
+26.532 0.478 26.624 0.132 26.634 -0.339 c
+26.634 -0.647 l
+24.974 -0.647 l
+24.974 -0.721 l
+24.974 -1.044 25.032 -1.279 25.15 -1.426 c
+25.267 -1.565 25.437 -1.632 25.664 -1.632 c
+25.812 -1.632 25.936 -1.61 26.047 -1.559 c
+26.154 -1.5 26.256 -1.411 26.356 -1.294 c
+26.605 -1.602 l
+26.399 -1.908 26.076 -2.058 25.635 -2.058 c
+25.591 0.617 m
+25.385 0.617 25.231 0.548 25.136 0.411 c
+25.036 0.272 24.981 0.058 24.974 -0.235 c
+26.15 -0.235 l
+26.15 -0.162 l
+26.127 0.11 26.076 0.309 25.988 0.426 c
+25.899 0.551 25.768 0.617 25.591 0.617 c
+f
+Q
+ endstream endobj 41 0 obj <</BBox[562.794 453.503 574.785 448.153]/Group 77 0 R/Length 2760/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 562.7944 450.9161 cm
+0 0 m
+0 0.449 0.106 0.802 0.323 1.058 c
+0.536 1.324 0.83 1.455 1.205 1.455 c
+1.587 1.455 1.881 1.324 2.087 1.058 c
+2.3 0.802 2.41 0.449 2.41 0 c
+2.41 -0.191 l
+2.41 -0.654 2.3 -1.01 2.087 -1.263 c
+1.881 -1.521 1.587 -1.646 1.205 -1.646 c
+0.823 -1.646 0.521 -1.521 0.309 -1.263 c
+0.103 -0.999 0 -0.643 0 -0.191 c
+h
+0.779 -0.191 m
+0.779 -0.731 0.918 -0.999 1.205 -0.999 c
+1.469 -0.999 1.61 -0.775 1.631 -0.323 c
+1.646 0 l
+1.646 0.272 1.606 0.474 1.529 0.603 c
+1.448 0.739 1.341 0.809 1.205 0.809 c
+1.076 0.809 0.974 0.739 0.897 0.603 c
+0.816 0.474 0.779 0.272 0.779 0 c
+h
+4.182 0.647 m
+3.931 0.662 l
+3.715 0.662 3.568 0.566 3.491 0.383 c
+3.491 -1.587 l
+2.711 -1.587 l
+2.711 1.397 l
+3.447 1.397 l
+3.476 1.073 l
+3.594 1.327 3.759 1.455 3.976 1.455 c
+4.064 1.455 4.137 1.441 4.197 1.411 c
+h
+5.284 -1.587 -0.779 2.984 re
+4.461 2.161 m
+4.461 2.286 4.498 2.389 4.579 2.469 c
+4.656 2.547 4.758 2.587 4.887 2.587 c
+5.012 2.587 5.115 2.547 5.196 2.469 c
+5.273 2.389 5.313 2.286 5.313 2.161 c
+5.313 2.043 5.273 1.945 5.196 1.867 c
+5.126 1.786 5.024 1.75 4.887 1.75 c
+4.758 1.75 4.656 1.786 4.579 1.867 c
+4.498 1.945 4.461 2.043 4.461 2.161 c
+5.703 0 m
+5.703 0.489 5.791 0.853 5.967 1.088 c
+6.144 1.33 6.387 1.455 6.703 1.455 c
+6.975 1.455 7.187 1.345 7.335 1.133 c
+7.364 1.397 l
+8.07 1.397 l
+8.07 -1.587 l
+8.07 -1.969 7.96 -2.256 7.746 -2.454 c
+7.53 -2.66 7.224 -2.763 6.834 -2.763 c
+6.666 -2.763 6.489 -2.726 6.306 -2.66 c
+6.129 -2.601 5.997 -2.516 5.909 -2.41 c
+6.173 -1.881 l
+6.25 -1.947 6.35 -2.006 6.468 -2.057 c
+6.585 -2.105 6.692 -2.131 6.79 -2.131 c
+6.967 -2.131 7.092 -2.087 7.173 -1.999 c
+7.25 -1.918 7.291 -1.786 7.291 -1.602 c
+7.291 -1.352 l
+7.143 -1.55 6.945 -1.646 6.703 -1.646 c
+6.387 -1.646 6.144 -1.525 5.967 -1.278 c
+5.791 -1.024 5.703 -0.672 5.703 -0.22 c
+h
+6.482 -0.205 m
+6.482 -0.481 6.515 -0.683 6.585 -0.808 c
+6.662 -0.926 6.78 -0.984 6.938 -0.984 c
+7.092 -0.984 7.21 -0.933 7.291 -0.823 c
+7.291 0.603 l
+7.21 0.728 7.092 0.794 6.938 0.794 c
+6.78 0.794 6.662 0.728 6.585 0.603 c
+6.515 0.474 6.482 0.272 6.482 0 c
+h
+9.267 -1.587 -0.779 2.984 re
+8.444 2.161 m
+8.444 2.286 8.481 2.389 8.562 2.469 c
+8.639 2.547 8.742 2.587 8.87 2.587 c
+8.995 2.587 9.099 2.547 9.18 2.469 c
+9.257 2.389 9.296 2.286 9.296 2.161 c
+9.296 2.043 9.257 1.945 9.18 1.867 c
+9.109 1.786 9.007 1.75 8.87 1.75 c
+8.742 1.75 8.639 1.786 8.562 1.867 c
+8.481 1.945 8.444 2.043 8.444 2.161 c
+10.491 1.397 m
+10.506 1.103 l
+10.682 1.338 10.91 1.455 11.197 1.455 c
+11.715 1.455 11.979 1.092 11.991 0.368 c
+11.991 -1.587 l
+11.212 -1.587 l
+11.212 0.31 l
+11.212 0.485 11.185 0.607 11.138 0.676 c
+11.087 0.754 10.998 0.794 10.873 0.794 c
+10.726 0.794 10.612 0.721 10.535 0.574 c
+10.535 -1.587 l
+9.756 -1.587 l
+9.756 1.397 l
+h
+f
+Q
+ endstream endobj 42 0 obj <</BBox[575.101 453.401 577.027 449.3]/Group 78 0 R/Length 944/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 575.7475 450.4608 cm
+0 0 m
+0 0.214 0.019 0.389 0.059 0.53 c
+0.106 0.676 0.221 0.852 0.397 1.058 c
+0.603 1.309 l
+0.728 1.492 0.794 1.679 0.794 1.866 c
+0.794 2.061 0.75 2.213 0.661 2.323 c
+0.58 2.429 0.47 2.484 0.324 2.484 c
+0.184 2.484 0.067 2.433 -0.029 2.337 c
+-0.118 2.238 -0.162 2.105 -0.162 1.941 c
+-0.646 1.941 l
+-0.646 2.242 -0.559 2.484 -0.382 2.66 c
+-0.199 2.844 0.037 2.94 0.324 2.94 c
+0.617 2.94 0.846 2.844 1.014 2.66 c
+1.191 2.473 1.279 2.219 1.279 1.897 c
+1.279 1.58 1.151 1.268 0.896 0.956 c
+0.647 0.647 l
+0.537 0.5 0.485 0.283 0.485 0 c
+h
+0.264 -0.588 m
+0.353 -0.588 0.42 -0.617 0.47 -0.676 c
+0.518 -0.727 0.544 -0.794 0.544 -0.882 c
+0.544 -0.962 0.518 -1.029 0.47 -1.088 c
+0.42 -1.135 0.353 -1.161 0.264 -1.161 c
+0.166 -1.161 0.092 -1.135 0.044 -1.088 c
+0.004 -1.029 -0.014 -0.962 -0.014 -0.882 c
+-0.014 -0.794 0.004 -0.727 0.044 -0.676 c
+0.092 -0.617 0.166 -0.588 0.264 -0.588 c
+f
+Q
+ endstream endobj 43 0 obj <</BBox[539.629 446.977 584.802 441.539]/Group 79 0 R/Length 9416/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 541.0248 444.743 cm
+0 0 m
+0.808 2.014 l
+1.382 2.014 l
+0.25 -0.5 l
+0.25 -1.999 l
+-0.264 -1.999 l
+-0.264 -0.5 l
+-1.396 2.014 l
+-0.823 2.014 l
+h
+1.386 -0.368 m
+1.386 0.062 1.488 0.405 1.694 0.661 c
+1.907 0.915 2.186 1.043 2.532 1.043 c
+2.874 1.043 3.15 0.915 3.355 0.661 c
+3.568 0.415 3.682 0.081 3.693 -0.338 c
+3.693 -0.647 l
+3.693 -1.081 3.583 -1.422 3.37 -1.675 c
+3.164 -1.933 2.884 -2.058 2.532 -2.058 c
+2.186 -2.058 1.914 -1.937 1.708 -1.69 c
+1.503 -1.448 1.393 -1.114 1.386 -0.69 c
+h
+1.87 -0.647 m
+1.87 -0.963 1.93 -1.205 2.047 -1.382 c
+2.172 -1.551 2.334 -1.631 2.532 -1.631 c
+2.962 -1.631 3.186 -1.323 3.208 -0.706 c
+3.208 -0.368 l
+3.208 -0.066 3.142 0.176 3.017 0.353 c
+2.899 0.529 2.738 0.617 2.532 0.617 c
+2.334 0.617 2.172 0.529 2.047 0.353 c
+1.93 0.176 1.87 -0.066 1.87 -0.368 c
+h
+5.644 -1.735 m
+5.486 -1.951 5.251 -2.058 4.939 -2.058 c
+4.675 -2.058 4.469 -1.966 4.322 -1.779 c
+4.182 -1.595 4.116 -1.319 4.116 -0.956 c
+4.116 0.985 l
+4.601 0.985 l
+4.601 -0.926 l
+4.601 -1.389 4.74 -1.617 5.027 -1.617 c
+5.321 -1.617 5.519 -1.484 5.629 -1.22 c
+5.629 0.985 l
+6.13 0.985 l
+6.13 -1.999 l
+5.659 -1.999 l
+h
+7.008 1.926 m
+6.963 0.912 l
+6.596 0.912 l
+6.611 2.234 l
+7.008 2.234 l
+h
+8.438 -1.264 m
+9.01 0.985 l
+9.51 0.985 l
+8.613 -1.999 l
+8.261 -1.999 l
+7.364 0.985 l
+7.85 0.985 l
+h
+10.881 -2.058 m
+10.506 -2.058 10.223 -1.951 10.028 -1.735 c
+9.83 -1.511 9.735 -1.183 9.735 -0.75 c
+9.735 -0.382 l
+9.735 0.058 9.826 0.405 10.014 0.661 c
+10.209 0.915 10.485 1.043 10.837 1.043 c
+11.179 1.043 11.432 0.929 11.601 0.706 c
+11.778 0.478 11.869 0.133 11.881 -0.338 c
+11.881 -0.647 l
+10.219 -0.647 l
+10.219 -0.721 l
+10.219 -1.043 10.279 -1.278 10.396 -1.426 c
+10.514 -1.565 10.683 -1.631 10.911 -1.631 c
+11.057 -1.631 11.183 -1.61 11.293 -1.558 c
+11.399 -1.5 11.502 -1.411 11.601 -1.294 c
+11.852 -1.602 l
+11.645 -1.907 11.322 -2.058 10.881 -2.058 c
+10.837 0.617 m
+10.631 0.617 10.477 0.548 10.381 0.411 c
+10.282 0.272 10.227 0.058 10.219 -0.235 c
+11.395 -0.235 l
+11.395 -0.162 l
+11.374 0.11 11.322 0.309 11.233 0.426 c
+11.146 0.551 11.013 0.617 10.837 0.617 c
+15.64 -0.647 m
+15.64 -1.118 15.555 -1.47 15.39 -1.706 c
+15.221 -1.941 14.982 -2.058 14.67 -2.058 c
+14.365 -2.058 14.133 -1.947 13.978 -1.72 c
+13.978 -3.146 l
+13.494 -3.146 l
+13.494 0.985 l
+13.935 0.985 l
+13.964 0.646 l
+14.119 0.912 14.35 1.043 14.655 1.043 c
+14.986 1.043 15.232 0.926 15.39 0.69 c
+15.555 0.463 15.64 0.125 15.64 -0.324 c
+h
+15.154 -0.368 m
+15.154 -0.037 15.1 0.21 14.994 0.368 c
+14.894 0.522 14.732 0.603 14.508 0.603 c
+14.273 0.603 14.096 0.485 13.978 0.25 c
+13.978 -1.294 l
+14.096 -1.521 14.277 -1.631 14.523 -1.631 c
+14.736 -1.631 14.894 -1.554 14.994 -1.396 c
+15.1 -1.242 15.154 -1 15.154 -0.676 c
+h
+17.334 0.529 m
+17.264 0.536 17.19 0.544 17.113 0.544 c
+16.856 0.544 16.68 0.405 16.584 0.133 c
+16.584 -1.999 l
+16.099 -1.999 l
+16.099 0.985 l
+16.569 0.985 l
+16.584 0.676 l
+16.709 0.918 16.893 1.043 17.128 1.043 c
+17.205 1.043 17.268 1.029 17.319 0.999 c
+h
+17.547 -0.368 m
+17.547 0.062 17.65 0.405 17.856 0.661 c
+18.069 0.915 18.348 1.043 18.693 1.043 c
+19.035 1.043 19.311 0.915 19.517 0.661 c
+19.73 0.415 19.844 0.081 19.855 -0.338 c
+19.855 -0.647 l
+19.855 -1.081 19.744 -1.422 19.532 -1.675 c
+19.326 -1.933 19.046 -2.058 18.693 -2.058 c
+18.348 -2.058 18.076 -1.937 17.87 -1.69 c
+17.664 -1.448 17.554 -1.114 17.547 -0.69 c
+h
+18.032 -0.647 m
+18.032 -0.963 18.091 -1.205 18.209 -1.382 c
+18.333 -1.551 18.495 -1.631 18.693 -1.631 c
+19.123 -1.631 19.347 -1.323 19.37 -0.706 c
+19.37 -0.368 l
+19.37 -0.066 19.304 0.176 19.179 0.353 c
+19.061 0.529 18.899 0.617 18.693 0.617 c
+18.495 0.617 18.333 0.529 18.209 0.353 c
+18.091 0.176 18.032 -0.066 18.032 -0.368 c
+h
+22.456 -0.647 m
+22.456 -1.118 22.372 -1.47 22.207 -1.706 c
+22.038 -1.941 21.795 -2.058 21.471 -2.058 c
+21.155 -2.058 20.92 -1.922 20.766 -1.646 c
+20.737 -1.999 l
+20.296 -1.999 l
+20.296 2.234 l
+20.781 2.234 l
+20.781 0.661 l
+20.935 0.915 21.167 1.043 21.471 1.043 c
+21.795 1.043 22.038 0.926 22.207 0.69 c
+22.372 0.455 22.456 0.106 22.456 -0.353 c
+h
+21.972 -0.368 m
+21.972 -0.015 21.92 0.235 21.824 0.382 c
+21.725 0.529 21.564 0.603 21.34 0.603 c
+21.093 0.603 20.906 0.463 20.781 0.191 c
+20.781 -1.22 l
+20.899 -1.484 21.089 -1.617 21.354 -1.617 c
+21.567 -1.617 21.725 -1.544 21.824 -1.396 c
+21.92 -1.242 21.972 -1 21.972 -0.676 c
+h
+24.426 -1.999 m
+24.397 -1.933 24.375 -1.823 24.367 -1.675 c
+24.191 -1.933 23.971 -2.058 23.706 -2.058 c
+23.43 -2.058 23.214 -1.984 23.059 -1.837 c
+22.913 -1.683 22.838 -1.467 22.838 -1.191 c
+22.838 -0.889 22.942 -0.647 23.148 -0.47 c
+23.353 -0.287 23.636 -0.191 24 -0.191 c
+24.353 -0.191 l
+24.353 0.133 l
+24.353 0.309 24.312 0.43 24.235 0.5 c
+24.154 0.577 24.037 0.617 23.883 0.617 c
+23.736 0.617 23.611 0.573 23.515 0.485 c
+23.426 0.397 23.383 0.287 23.383 0.162 c
+22.898 0.162 l
+22.898 0.309 22.942 0.448 23.03 0.588 c
+23.118 0.735 23.235 0.845 23.383 0.926 c
+23.537 1.003 23.709 1.043 23.897 1.043 c
+24.209 1.043 24.444 0.962 24.602 0.808 c
+24.757 0.661 24.837 0.441 24.837 0.147 c
+24.837 -1.353 l
+24.845 -1.588 24.882 -1.789 24.941 -1.955 c
+24.941 -1.999 l
+h
+23.779 -1.617 m
+23.897 -1.617 24.008 -1.584 24.118 -1.514 c
+24.224 -1.448 24.301 -1.363 24.353 -1.264 c
+24.353 -0.559 l
+24.089 -0.559 l
+23.853 -0.559 23.665 -0.611 23.53 -0.706 c
+23.401 -0.805 23.339 -0.948 23.339 -1.132 c
+23.339 -1.301 23.368 -1.422 23.426 -1.5 c
+23.493 -1.58 23.611 -1.617 23.779 -1.617 c
+27.579 -0.647 m
+27.579 -1.118 27.495 -1.47 27.329 -1.706 c
+27.16 -1.941 26.917 -2.058 26.595 -2.058 c
+26.279 -2.058 26.043 -1.922 25.889 -1.646 c
+25.859 -1.999 l
+25.419 -1.999 l
+25.419 2.234 l
+25.903 2.234 l
+25.903 0.661 l
+26.058 0.915 26.289 1.043 26.595 1.043 c
+26.917 1.043 27.16 0.926 27.329 0.69 c
+27.495 0.455 27.579 0.106 27.579 -0.353 c
+h
+27.094 -0.368 m
+27.094 -0.015 27.042 0.235 26.948 0.382 c
+26.848 0.529 26.686 0.603 26.462 0.603 c
+26.216 0.603 26.028 0.463 25.903 0.191 c
+25.903 -1.22 l
+26.021 -1.484 26.212 -1.617 26.477 -1.617 c
+26.69 -1.617 26.848 -1.544 26.948 -1.396 c
+27.042 -1.242 27.094 -1 27.094 -0.676 c
+h
+28.553 -1.999 -0.5 4.233 re
+30.034 -1.191 m
+30.578 0.985 l
+31.092 0.985 l
+30.122 -2.425 l
+30.052 -2.679 29.949 -2.87 29.813 -2.999 c
+29.674 -3.135 29.523 -3.204 29.358 -3.204 c
+29.288 -3.204 29.203 -3.19 29.107 -3.16 c
+29.107 -2.749 l
+29.211 -2.764 l
+29.346 -2.764 29.454 -2.727 29.535 -2.66 c
+29.622 -2.591 29.689 -2.473 29.74 -2.308 c
+29.828 -1.97 l
+28.961 0.985 l
+29.49 0.985 l
+h
+33.076 0.985 m
+33.091 0.706 l
+33.267 0.929 33.506 1.043 33.811 1.043 c
+34.142 1.043 34.374 0.897 34.503 0.603 c
+34.686 0.897 34.948 1.043 35.282 1.043 c
+35.84 1.043 36.123 0.698 36.134 0.015 c
+36.134 -1.999 l
+35.649 -1.999 l
+35.649 -0.029 l
+35.649 0.183 35.609 0.341 35.532 0.441 c
+35.451 0.548 35.318 0.603 35.135 0.603 c
+34.987 0.603 34.869 0.544 34.782 0.426 c
+34.694 0.316 34.638 0.176 34.62 0 c
+34.62 -1.999 l
+34.135 -1.999 l
+34.135 -0.015 l
+34.123 0.397 33.951 0.603 33.62 0.603 c
+33.375 0.603 33.202 0.478 33.106 0.235 c
+33.106 -1.999 l
+32.621 -1.999 l
+32.621 0.985 l
+h
+38.111 -1.999 m
+38.082 -1.933 38.06 -1.823 38.052 -1.675 c
+37.876 -1.933 37.655 -2.058 37.391 -2.058 c
+37.115 -2.058 36.899 -1.984 36.744 -1.837 c
+36.597 -1.683 36.523 -1.467 36.523 -1.191 c
+36.523 -0.889 36.627 -0.647 36.832 -0.47 c
+37.038 -0.287 37.321 -0.191 37.685 -0.191 c
+38.038 -0.191 l
+38.038 0.133 l
+38.038 0.309 37.997 0.43 37.92 0.5 c
+37.839 0.577 37.722 0.617 37.568 0.617 c
+37.42 0.617 37.296 0.573 37.2 0.485 c
+37.111 0.397 37.067 0.287 37.067 0.162 c
+36.583 0.162 l
+36.583 0.309 36.627 0.448 36.714 0.588 c
+36.803 0.735 36.92 0.845 37.067 0.926 c
+37.221 1.003 37.394 1.043 37.582 1.043 c
+37.894 1.043 38.129 0.962 38.287 0.808 c
+38.441 0.661 38.522 0.441 38.522 0.147 c
+38.522 -1.353 l
+38.53 -1.588 38.567 -1.789 38.626 -1.955 c
+38.626 -1.999 l
+h
+37.464 -1.617 m
+37.582 -1.617 37.692 -1.584 37.803 -1.514 c
+37.909 -1.448 37.986 -1.363 38.038 -1.264 c
+38.038 -0.559 l
+37.773 -0.559 l
+37.537 -0.559 37.35 -0.611 37.215 -0.706 c
+37.086 -0.805 37.024 -0.948 37.024 -1.132 c
+37.024 -1.301 37.053 -1.422 37.111 -1.5 c
+37.178 -1.58 37.296 -1.617 37.464 -1.617 c
+39 -0.368 m
+39 0.092 39.081 0.441 39.25 0.676 c
+39.426 0.918 39.677 1.043 40 1.043 c
+40.282 1.043 40.504 0.926 40.662 0.69 c
+40.662 2.234 l
+41.146 2.234 l
+41.146 -1.999 l
+40.706 -1.999 l
+40.676 -1.675 l
+40.518 -1.933 40.294 -2.058 40 -2.058 c
+39.684 -2.058 39.441 -1.941 39.265 -1.706 c
+39.089 -1.463 39 -1.118 39 -0.676 c
+h
+39.486 -0.647 m
+39.486 -0.981 39.533 -1.228 39.632 -1.382 c
+39.728 -1.54 39.889 -1.617 40.118 -1.617 c
+40.36 -1.617 40.544 -1.5 40.662 -1.264 c
+40.662 0.25 l
+40.533 0.485 40.353 0.603 40.118 0.603 c
+39.889 0.603 39.728 0.522 39.632 0.368 c
+39.533 0.21 39.486 -0.029 39.486 -0.353 c
+h
+42.778 -2.058 m
+42.403 -2.058 42.12 -1.951 41.925 -1.735 c
+41.727 -1.511 41.632 -1.183 41.632 -0.75 c
+41.632 -0.382 l
+41.632 0.058 41.724 0.405 41.911 0.661 c
+42.106 0.915 42.381 1.043 42.734 1.043 c
+43.076 1.043 43.33 0.929 43.498 0.706 c
+43.675 0.478 43.766 0.133 43.777 -0.338 c
+43.777 -0.647 l
+42.117 -0.647 l
+42.117 -0.721 l
+42.117 -1.043 42.175 -1.278 42.293 -1.426 c
+42.41 -1.565 42.58 -1.631 42.807 -1.631 c
+42.954 -1.631 43.079 -1.61 43.189 -1.558 c
+43.296 -1.5 43.399 -1.411 43.498 -1.294 c
+43.748 -1.602 l
+43.542 -1.907 43.219 -2.058 42.778 -2.058 c
+42.734 0.617 m
+42.528 0.617 42.374 0.548 42.278 0.411 c
+42.179 0.272 42.123 0.058 42.117 -0.235 c
+43.293 -0.235 l
+43.293 -0.162 l
+43.27 0.11 43.219 0.309 43.131 0.426 c
+43.043 0.551 42.91 0.617 42.734 0.617 c
+f
+Q
+ endstream endobj 44 0 obj <</BBox[541.904 440.392 560.038 434.983]/Group 80 0 R/Length 4112/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 541.9035 437.7458 cm
+0 0 m
+0 0.489 0.087 0.853 0.264 1.088 c
+0.44 1.33 0.683 1.455 0.999 1.455 c
+1.271 1.455 1.484 1.345 1.631 1.133 c
+1.66 1.397 l
+2.366 1.397 l
+2.366 -1.587 l
+2.366 -1.969 2.256 -2.256 2.043 -2.454 c
+1.826 -2.66 1.521 -2.763 1.132 -2.763 c
+0.962 -2.763 0.786 -2.726 0.602 -2.66 c
+0.426 -2.601 0.293 -2.516 0.205 -2.41 c
+0.47 -1.882 l
+0.547 -1.947 0.646 -2.006 0.764 -2.057 c
+0.881 -2.105 0.988 -2.131 1.087 -2.131 c
+1.263 -2.131 1.388 -2.087 1.469 -1.999 c
+1.547 -1.918 1.587 -1.786 1.587 -1.602 c
+1.587 -1.352 l
+1.44 -1.55 1.242 -1.646 0.999 -1.646 c
+0.683 -1.646 0.44 -1.525 0.264 -1.278 c
+0.087 -1.024 0 -0.672 0 -0.22 c
+h
+0.779 -0.205 m
+0.779 -0.481 0.812 -0.683 0.881 -0.808 c
+0.959 -0.926 1.076 -0.984 1.234 -0.984 c
+1.388 -0.984 1.506 -0.933 1.587 -0.823 c
+1.587 0.603 l
+1.506 0.728 1.388 0.794 1.234 0.794 c
+1.076 0.794 0.959 0.728 0.881 0.603 c
+0.812 0.474 0.779 0.272 0.779 0 c
+h
+3.564 -1.587 -0.779 2.984 re
+2.741 2.161 m
+2.741 2.286 2.778 2.389 2.859 2.469 c
+2.936 2.547 3.039 2.587 3.167 2.587 c
+3.293 2.587 3.395 2.547 3.476 2.469 c
+3.553 2.389 3.594 2.286 3.594 2.161 c
+3.594 2.043 3.553 1.945 3.476 1.867 c
+3.406 1.786 3.303 1.75 3.167 1.75 c
+3.039 1.75 2.936 1.786 2.859 1.867 c
+2.778 1.945 2.741 2.043 2.741 2.161 c
+4.983 2.132 m
+4.983 1.397 l
+5.379 1.397 l
+5.379 0.809 l
+4.983 0.809 l
+4.983 -0.675 l
+4.983 -0.793 4.997 -0.878 5.026 -0.926 c
+5.063 -0.966 5.13 -0.984 5.218 -0.984 c
+5.295 -0.984 5.357 -0.977 5.409 -0.955 c
+5.394 -1.572 l
+5.265 -1.62 5.122 -1.646 4.968 -1.646 c
+4.469 -1.646 4.211 -1.359 4.203 -0.779 c
+4.203 0.809 l
+3.865 0.809 l
+3.865 1.397 l
+4.203 1.397 l
+4.203 2.132 l
+h
+7.989 -0.999 m
+8.213 -0.999 8.326 -0.852 8.326 -0.558 c
+9.061 -0.558 l
+9.061 -0.881 8.959 -1.146 8.753 -1.352 c
+8.554 -1.55 8.305 -1.646 8.003 -1.646 c
+7.621 -1.646 7.327 -1.529 7.121 -1.294 c
+6.915 -1.051 6.813 -0.698 6.813 -0.235 c
+6.813 0.015 l
+6.813 0.474 6.908 0.827 7.106 1.073 c
+7.312 1.327 7.607 1.455 7.989 1.455 c
+8.319 1.455 8.58 1.353 8.768 1.147 c
+8.962 0.941 9.061 0.651 9.061 0.279 c
+8.326 0.279 l
+8.326 0.445 8.297 0.574 8.238 0.662 c
+8.187 0.757 8.099 0.809 7.974 0.809 c
+7.845 0.809 7.754 0.757 7.694 0.662 c
+7.636 0.563 7.599 0.375 7.592 0.103 c
+7.592 -0.205 l
+7.592 -0.452 7.599 -0.625 7.621 -0.72 c
+7.65 -0.808 7.688 -0.878 7.738 -0.926 c
+7.798 -0.977 7.879 -0.999 7.989 -0.999 c
+10.15 -1.587 -0.779 4.233 re
+10.568 0 m
+10.568 0.449 10.674 0.802 10.892 1.058 c
+11.104 1.324 11.399 1.455 11.773 1.455 c
+12.156 1.455 12.45 1.324 12.656 1.058 c
+12.868 0.802 12.979 0.449 12.979 0 c
+12.979 -0.191 l
+12.979 -0.654 12.868 -1.01 12.656 -1.263 c
+12.45 -1.521 12.156 -1.646 11.773 -1.646 c
+11.391 -1.646 11.09 -1.521 10.877 -1.263 c
+10.671 -0.999 10.568 -0.643 10.568 -0.191 c
+h
+11.347 -0.191 m
+11.347 -0.731 11.487 -0.999 11.773 -0.999 c
+12.039 -0.999 12.178 -0.775 12.199 -0.323 c
+12.214 0 l
+12.214 0.272 12.174 0.474 12.097 0.603 c
+12.016 0.739 11.91 0.809 11.773 0.809 c
+11.645 0.809 11.542 0.739 11.465 0.603 c
+11.384 0.474 11.347 0.272 11.347 0 c
+h
+14 1.397 m
+14.015 1.103 l
+14.192 1.338 14.42 1.455 14.706 1.455 c
+15.224 1.455 15.489 1.092 15.5 0.368 c
+15.5 -1.587 l
+14.721 -1.587 l
+14.721 0.31 l
+14.721 0.485 14.695 0.607 14.647 0.676 c
+14.596 0.754 14.508 0.794 14.383 0.794 c
+14.235 0.794 14.121 0.721 14.044 0.574 c
+14.044 -1.587 l
+13.265 -1.587 l
+13.265 1.397 l
+h
+17.076 -1.646 m
+16.672 -1.646 16.359 -1.529 16.135 -1.294 c
+15.919 -1.051 15.812 -0.706 15.812 -0.264 c
+15.812 -0.014 l
+15.812 0.456 15.915 0.817 16.12 1.073 c
+16.326 1.327 16.621 1.455 17.003 1.455 c
+17.373 1.455 17.653 1.33 17.841 1.088 c
+18.036 0.853 18.135 0.5 18.135 0.03 c
+18.135 -0.353 l
+16.591 -0.353 l
+16.598 -0.58 16.643 -0.746 16.723 -0.852 c
+16.812 -0.951 16.947 -0.999 17.135 -0.999 c
+17.389 -0.999 17.606 -0.907 17.782 -0.72 c
+18.09 -1.205 l
+17.992 -1.334 17.848 -1.44 17.664 -1.529 c
+17.487 -1.606 17.29 -1.646 17.076 -1.646 c
+16.591 0.192 m
+17.371 0.192 l
+17.371 0.265 l
+17.371 0.441 17.341 0.574 17.282 0.662 c
+17.223 0.757 17.124 0.809 16.988 0.809 c
+16.86 0.809 16.76 0.757 16.694 0.662 c
+16.635 0.563 16.598 0.405 16.591 0.192 c
+f
+Q
+ endstream endobj 45 0 obj <</BBox[561.412 440.45 582.315 436.099]/Group 81 0 R/Length 4153/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 561.7944 436.1588 cm
+0 0 m
+0 2.587 l
+-0.382 2.587 l
+-0.382 2.984 l
+0 2.984 l
+0 3.322 l
+0.008 3.623 0.088 3.858 0.235 4.027 c
+0.382 4.204 0.592 4.292 0.867 4.292 c
+0.963 4.292 1.062 4.278 1.162 4.248 c
+1.132 3.836 l
+1.062 3.844 0.989 3.851 0.912 3.851 c
+0.636 3.851 0.5 3.653 0.5 3.263 c
+0.5 2.984 l
+1 2.984 l
+1 2.587 l
+0.5 2.587 l
+0.5 0 l
+h
+2.693 2.528 m
+2.624 2.535 2.55 2.543 2.473 2.543 c
+2.216 2.543 2.039 2.404 1.945 2.132 c
+1.945 0 l
+1.459 0 l
+1.459 2.984 l
+1.93 2.984 l
+1.945 2.675 l
+2.069 2.917 2.253 3.042 2.488 3.042 c
+2.565 3.042 2.628 3.028 2.679 2.998 c
+h
+2.911 1.631 m
+2.911 2.061 3.013 2.404 3.219 2.66 c
+3.433 2.914 3.711 3.042 4.057 3.042 c
+4.399 3.042 4.675 2.914 4.881 2.66 c
+5.093 2.414 5.207 2.08 5.218 1.661 c
+5.218 1.352 l
+5.218 0.918 5.108 0.577 4.895 0.324 c
+4.69 0.066 4.41 -0.059 4.057 -0.059 c
+3.711 -0.059 3.439 0.062 3.234 0.309 c
+3.028 0.551 2.918 0.885 2.911 1.309 c
+h
+3.396 1.352 m
+3.396 1.036 3.454 0.794 3.572 0.617 c
+3.697 0.448 3.859 0.368 4.057 0.368 c
+4.487 0.368 4.711 0.676 4.733 1.294 c
+4.733 1.631 l
+4.733 1.933 4.667 2.175 4.542 2.352 c
+4.424 2.528 4.263 2.616 4.057 2.616 c
+3.859 2.616 3.697 2.528 3.572 2.352 c
+3.454 2.175 3.396 1.933 3.396 1.631 c
+h
+6.115 2.984 m
+6.13 2.705 l
+6.306 2.928 6.545 3.042 6.85 3.042 c
+7.181 3.042 7.412 2.896 7.541 2.602 c
+7.724 2.896 7.985 3.042 8.32 3.042 c
+8.879 3.042 9.161 2.697 9.172 2.014 c
+9.172 0 l
+8.688 0 l
+8.688 1.97 l
+8.688 2.182 8.647 2.341 8.57 2.44 c
+8.489 2.547 8.357 2.602 8.173 2.602 c
+8.025 2.602 7.908 2.543 7.82 2.425 c
+7.732 2.315 7.676 2.175 7.659 1.999 c
+7.659 0 l
+7.173 0 l
+7.173 1.984 l
+7.162 2.396 6.99 2.602 6.659 2.602 c
+6.413 2.602 6.24 2.477 6.144 2.234 c
+6.144 0 l
+5.659 0 l
+5.659 2.984 l
+h
+11.308 2.675 m
+11.491 2.917 11.726 3.042 12.013 3.042 c
+12.542 3.042 12.81 2.69 12.821 1.984 c
+12.821 0 l
+12.336 0 l
+12.336 1.955 l
+12.336 2.19 12.296 2.356 12.218 2.454 c
+12.138 2.55 12.021 2.602 11.866 2.602 c
+11.748 2.602 11.638 2.562 11.543 2.484 c
+11.443 2.404 11.366 2.296 11.308 2.161 c
+11.308 0 l
+10.822 0 l
+10.822 4.233 l
+11.308 4.233 l
+h
+14.423 -0.059 m
+14.049 -0.059 13.766 0.048 13.571 0.264 c
+13.373 0.488 13.277 0.816 13.277 1.249 c
+13.277 1.617 l
+13.277 2.057 13.369 2.404 13.556 2.66 c
+13.751 2.914 14.026 3.042 14.379 3.042 c
+14.722 3.042 14.975 2.928 15.144 2.705 c
+15.32 2.477 15.412 2.132 15.423 1.661 c
+15.423 1.352 l
+13.762 1.352 l
+13.762 1.278 l
+13.762 0.956 13.821 0.721 13.939 0.573 c
+14.057 0.434 14.225 0.368 14.453 0.368 c
+14.6 0.368 14.725 0.389 14.836 0.441 c
+14.942 0.5 15.044 0.588 15.144 0.706 c
+15.393 0.397 l
+15.188 0.092 14.865 -0.059 14.423 -0.059 c
+14.379 2.616 m
+14.174 2.616 14.02 2.547 13.924 2.41 c
+13.824 2.271 13.77 2.057 13.762 1.764 c
+14.938 1.764 l
+14.938 1.837 l
+14.916 2.109 14.865 2.308 14.776 2.425 c
+14.688 2.55 14.556 2.616 14.379 2.616 c
+17.07 2.528 m
+17 2.535 16.926 2.543 16.849 2.543 c
+16.592 2.543 16.415 2.404 16.32 2.132 c
+16.32 0 l
+15.835 0 l
+15.835 2.984 l
+16.305 2.984 l
+16.32 2.675 l
+16.445 2.917 16.629 3.042 16.864 3.042 c
+16.941 3.042 17.003 3.028 17.055 2.998 c
+h
+18.448 -0.059 m
+18.073 -0.059 17.789 0.048 17.595 0.264 c
+17.396 0.488 17.301 0.816 17.301 1.249 c
+17.301 1.617 l
+17.301 2.057 17.392 2.404 17.581 2.66 c
+17.775 2.914 18.051 3.042 18.404 3.042 c
+18.745 3.042 18.998 2.928 19.168 2.705 c
+19.344 2.477 19.436 2.132 19.447 1.661 c
+19.447 1.352 l
+17.786 1.352 l
+17.786 1.278 l
+17.786 0.956 17.845 0.721 17.962 0.573 c
+18.08 0.434 18.249 0.368 18.477 0.368 c
+18.624 0.368 18.749 0.389 18.859 0.441 c
+18.965 0.5 19.069 0.588 19.168 0.706 c
+19.418 0.397 l
+19.212 0.092 18.888 -0.059 18.448 -0.059 c
+18.404 2.616 m
+18.198 2.616 18.043 2.547 17.947 2.41 c
+17.849 2.271 17.793 2.057 17.786 1.764 c
+18.962 1.764 l
+18.962 1.837 l
+18.94 2.109 18.888 2.308 18.801 2.425 c
+18.712 2.55 18.58 2.616 18.404 2.616 c
+19.888 0.264 m
+19.888 0.353 19.91 0.426 19.962 0.485 c
+20.02 0.544 20.097 0.573 20.197 0.573 c
+20.303 0.573 20.38 0.544 20.432 0.485 c
+20.49 0.426 20.52 0.353 20.52 0.264 c
+20.52 0.183 20.49 0.118 20.432 0.058 c
+20.38 0 20.303 -0.029 20.197 -0.029 c
+20.097 -0.029 20.02 0 19.962 0.058 c
+19.91 0.118 19.888 0.183 19.888 0.264 c
+f
+Q
+ endstream endobj 46 0 obj <</BBox[705.559 469.842 760.518 464.403]/Group 82 0 R/Length 12288/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 707.7492 466.6519 cm
+0 0 m
+-1.353 0 l
+-1.676 -1.043 l
+-2.19 -1.043 l
+-0.897 2.969 l
+-0.47 2.969 l
+0.837 -1.043 l
+0.309 -1.043 l
+h
+-1.22 0.441 m
+-0.133 0.441 l
+-0.676 2.263 l
+h
+1.55 1.94 m
+1.565 1.617 l
+1.749 1.87 1.992 1.999 2.285 1.999 c
+2.815 1.999 3.083 1.646 3.094 0.941 c
+3.094 -1.043 l
+2.609 -1.043 l
+2.609 0.912 l
+2.609 1.147 2.568 1.312 2.491 1.411 c
+2.41 1.507 2.293 1.558 2.138 1.558 c
+2.021 1.558 1.911 1.517 1.815 1.44 c
+1.716 1.359 1.639 1.253 1.58 1.117 c
+1.58 -1.043 l
+1.095 -1.043 l
+1.095 1.94 l
+h
+3.542 0.588 m
+3.542 1.018 3.645 1.359 3.85 1.617 c
+4.064 1.87 4.343 1.999 4.689 1.999 c
+5.03 1.999 5.306 1.87 5.512 1.617 c
+5.725 1.371 5.839 1.037 5.85 0.617 c
+5.85 0.309 l
+5.85 -0.125 5.739 -0.467 5.527 -0.721 c
+5.321 -0.977 5.041 -1.103 4.689 -1.103 c
+4.343 -1.103 4.072 -0.981 3.866 -0.735 c
+3.659 -0.492 3.549 -0.158 3.542 0.264 c
+h
+4.027 0.309 m
+4.027 -0.008 4.086 -0.25 4.203 -0.426 c
+4.328 -0.595 4.49 -0.676 4.689 -0.676 c
+5.119 -0.676 5.342 -0.368 5.365 0.25 c
+5.365 0.588 l
+5.365 0.889 5.298 1.132 5.174 1.309 c
+5.056 1.484 4.895 1.573 4.689 1.573 c
+4.49 1.573 4.328 1.484 4.203 1.309 c
+4.086 1.132 4.027 0.889 4.027 0.588 c
+h
+6.923 2.66 m
+6.923 1.94 l
+7.378 1.94 l
+7.378 1.544 l
+6.923 1.544 l
+6.923 -0.309 l
+6.923 -0.426 6.942 -0.515 6.982 -0.573 c
+7.019 -0.632 7.089 -0.661 7.187 -0.661 c
+7.247 -0.661 7.309 -0.654 7.378 -0.632 c
+7.378 -1.043 l
+7.261 -1.08 7.147 -1.103 7.041 -1.103 c
+6.842 -1.103 6.692 -1.037 6.585 -0.897 c
+6.485 -0.761 6.437 -0.566 6.437 -0.309 c
+6.437 1.544 l
+5.982 1.544 l
+5.982 1.94 l
+6.437 1.94 l
+6.437 2.66 l
+h
+8.326 1.631 m
+8.51 1.874 8.745 1.999 9.032 1.999 c
+9.562 1.999 9.83 1.646 9.841 0.941 c
+9.841 -1.043 l
+9.356 -1.043 l
+9.356 0.912 l
+9.356 1.147 9.315 1.312 9.238 1.411 c
+9.157 1.507 9.04 1.558 8.885 1.558 c
+8.768 1.558 8.658 1.517 8.562 1.44 c
+8.463 1.359 8.386 1.253 8.326 1.117 c
+8.326 -1.043 l
+7.842 -1.043 l
+7.842 3.19 l
+8.326 3.19 l
+h
+11.443 -1.103 m
+11.068 -1.103 10.785 -0.996 10.59 -0.779 c
+10.391 -0.555 10.296 -0.228 10.296 0.206 c
+10.296 0.573 l
+10.296 1.014 10.389 1.359 10.576 1.617 c
+10.771 1.87 11.046 1.999 11.399 1.999 c
+11.74 1.999 11.994 1.885 12.163 1.661 c
+12.34 1.433 12.431 1.087 12.442 0.617 c
+12.442 0.309 l
+10.782 0.309 l
+10.782 0.235 l
+10.782 -0.088 10.84 -0.324 10.958 -0.47 c
+11.075 -0.61 11.245 -0.676 11.472 -0.676 c
+11.619 -0.676 11.744 -0.654 11.854 -0.603 c
+11.961 -0.544 12.064 -0.455 12.163 -0.338 c
+12.413 -0.647 l
+12.207 -0.952 11.883 -1.103 11.443 -1.103 c
+11.399 1.573 m
+11.193 1.573 11.039 1.503 10.943 1.367 c
+10.844 1.228 10.788 1.014 10.782 0.721 c
+11.958 0.721 l
+11.958 0.794 l
+11.935 1.066 11.883 1.264 11.796 1.382 c
+11.708 1.507 11.575 1.573 11.399 1.573 c
+14.089 1.484 m
+14.019 1.492 13.946 1.5 13.868 1.5 c
+13.611 1.5 13.435 1.359 13.339 1.087 c
+13.339 -1.043 l
+12.854 -1.043 l
+12.854 1.94 l
+13.325 1.94 l
+13.339 1.631 l
+13.464 1.874 13.647 1.999 13.883 1.999 c
+13.96 1.999 14.023 1.984 14.074 1.955 c
+h
+16.897 1.484 m
+16.826 1.492 16.753 1.5 16.676 1.5 c
+16.419 1.5 16.242 1.359 16.147 1.087 c
+16.147 -1.043 l
+15.661 -1.043 l
+15.661 1.94 l
+16.132 1.94 l
+16.147 1.631 l
+16.271 1.874 16.455 1.999 16.691 1.999 c
+16.768 1.999 16.83 1.984 16.882 1.955 c
+h
+18.274 -1.103 m
+17.899 -1.103 17.616 -0.996 17.422 -0.779 c
+17.223 -0.555 17.128 -0.228 17.128 0.206 c
+17.128 0.573 l
+17.128 1.014 17.219 1.359 17.407 1.617 c
+17.602 1.87 17.878 1.999 18.231 1.999 c
+18.572 1.999 18.825 1.885 18.994 1.661 c
+19.171 1.433 19.263 1.087 19.274 0.617 c
+19.274 0.309 l
+17.612 0.309 l
+17.612 0.235 l
+17.612 -0.088 17.672 -0.324 17.789 -0.47 c
+17.907 -0.61 18.075 -0.676 18.304 -0.676 c
+18.451 -0.676 18.576 -0.654 18.686 -0.603 c
+18.792 -0.544 18.896 -0.455 18.994 -0.338 c
+19.245 -0.647 l
+19.039 -0.952 18.715 -1.103 18.274 -1.103 c
+18.231 1.573 m
+18.025 1.573 17.87 1.503 17.774 1.367 c
+17.676 1.228 17.62 1.014 17.612 0.721 c
+18.788 0.721 l
+18.788 0.794 l
+18.767 1.066 18.715 1.264 18.627 1.382 c
+18.539 1.507 18.406 1.573 18.231 1.573 c
+20.141 1.94 m
+20.155 1.661 l
+20.332 1.885 20.571 1.999 20.876 1.999 c
+21.207 1.999 21.439 1.852 21.566 1.558 c
+21.751 1.852 22.011 1.999 22.346 1.999 c
+22.904 1.999 23.187 1.654 23.199 0.97 c
+23.199 -1.043 l
+22.713 -1.043 l
+22.713 0.926 l
+22.713 1.139 22.673 1.297 22.596 1.396 c
+22.515 1.503 22.383 1.558 22.199 1.558 c
+22.052 1.558 21.934 1.5 21.846 1.382 c
+21.758 1.272 21.703 1.132 21.684 0.956 c
+21.684 -1.043 l
+21.2 -1.043 l
+21.2 0.941 l
+21.188 1.352 21.015 1.558 20.685 1.558 c
+20.439 1.558 20.266 1.433 20.17 1.191 c
+20.17 -1.043 l
+19.685 -1.043 l
+19.685 1.94 l
+h
+23.544 0.588 m
+23.544 1.018 23.646 1.359 23.852 1.617 c
+24.066 1.87 24.345 1.999 24.691 1.999 c
+25.032 1.999 25.308 1.87 25.514 1.617 c
+25.726 1.371 25.84 1.037 25.852 0.617 c
+25.852 0.309 l
+25.852 -0.125 25.742 -0.467 25.528 -0.721 c
+25.323 -0.977 25.043 -1.103 24.691 -1.103 c
+24.345 -1.103 24.073 -0.981 23.868 -0.735 c
+23.661 -0.492 23.551 -0.158 23.544 0.264 c
+h
+24.029 0.309 m
+24.029 -0.008 24.088 -0.25 24.205 -0.426 c
+24.33 -0.595 24.492 -0.676 24.691 -0.676 c
+25.121 -0.676 25.344 -0.368 25.366 0.25 c
+25.366 0.588 l
+25.366 0.889 25.3 1.132 25.175 1.309 c
+25.057 1.484 24.896 1.573 24.691 1.573 c
+24.492 1.573 24.33 1.484 24.205 1.309 c
+24.088 1.132 24.029 0.889 24.029 0.588 c
+h
+26.925 2.66 m
+26.925 1.94 l
+27.38 1.94 l
+27.38 1.544 l
+26.925 1.544 l
+26.925 -0.309 l
+26.925 -0.426 26.943 -0.515 26.983 -0.573 c
+27.02 -0.632 27.09 -0.661 27.189 -0.661 c
+27.248 -0.661 27.311 -0.654 27.38 -0.632 c
+27.38 -1.043 l
+27.263 -1.08 27.149 -1.103 27.043 -1.103 c
+26.844 -1.103 26.693 -1.037 26.586 -0.897 c
+26.487 -0.761 26.439 -0.566 26.439 -0.309 c
+26.439 1.544 l
+25.984 1.544 l
+25.984 1.94 l
+26.439 1.94 l
+26.439 2.66 l
+h
+28.905 -1.103 m
+28.531 -1.103 28.248 -0.996 28.053 -0.779 c
+27.854 -0.555 27.758 -0.228 27.758 0.206 c
+27.758 0.573 l
+27.758 1.014 27.851 1.359 28.038 1.617 c
+28.233 1.87 28.508 1.999 28.861 1.999 c
+29.203 1.999 29.456 1.885 29.626 1.661 c
+29.802 1.433 29.894 1.087 29.905 0.617 c
+29.905 0.309 l
+28.244 0.309 l
+28.244 0.235 l
+28.244 -0.088 28.303 -0.324 28.421 -0.47 c
+28.538 -0.61 28.707 -0.676 28.934 -0.676 c
+29.082 -0.676 29.206 -0.654 29.317 -0.603 c
+29.424 -0.544 29.526 -0.455 29.626 -0.338 c
+29.875 -0.647 l
+29.67 -0.952 29.346 -1.103 28.905 -1.103 c
+28.861 1.573 m
+28.656 1.573 28.501 1.503 28.406 1.367 c
+28.306 1.228 28.251 1.014 28.244 0.721 c
+29.42 0.721 l
+29.42 0.794 l
+29.398 1.066 29.346 1.264 29.258 1.382 c
+29.17 1.507 29.038 1.573 28.861 1.573 c
+32.753 1.484 m
+32.683 1.492 32.61 1.5 32.533 1.5 c
+32.275 1.5 32.099 1.359 32.003 1.087 c
+32.003 -1.043 l
+31.519 -1.043 l
+31.519 1.94 l
+31.989 1.94 l
+32.003 1.631 l
+32.128 1.874 32.312 1.999 32.547 1.999 c
+32.624 1.999 32.687 1.984 32.738 1.955 c
+h
+34.131 -1.103 m
+33.756 -1.103 33.473 -0.996 33.279 -0.779 c
+33.08 -0.555 32.984 -0.228 32.984 0.206 c
+32.984 0.573 l
+32.984 1.014 33.076 1.359 33.264 1.617 c
+33.458 1.87 33.734 1.999 34.087 1.999 c
+34.428 1.999 34.682 1.885 34.851 1.661 c
+35.028 1.433 35.12 1.087 35.13 0.617 c
+35.13 0.309 l
+33.47 0.309 l
+33.47 0.235 l
+33.47 -0.088 33.528 -0.324 33.646 -0.47 c
+33.763 -0.61 33.932 -0.676 34.16 -0.676 c
+34.307 -0.676 34.432 -0.654 34.542 -0.603 c
+34.649 -0.544 34.752 -0.455 34.851 -0.338 c
+35.101 -0.647 l
+34.895 -0.952 34.572 -1.103 34.131 -1.103 c
+34.087 1.573 m
+33.881 1.573 33.726 1.503 33.631 1.367 c
+33.532 1.228 33.477 1.014 33.47 0.721 c
+34.646 0.721 l
+34.646 0.794 l
+34.623 1.066 34.572 1.264 34.484 1.382 c
+34.395 1.507 34.264 1.573 34.087 1.573 c
+37.688 0.309 m
+37.688 -0.162 37.603 -0.515 37.438 -0.75 c
+37.269 -0.985 37.03 -1.103 36.718 -1.103 c
+36.413 -1.103 36.182 -0.992 36.027 -0.765 c
+36.027 -2.19 l
+35.542 -2.19 l
+35.542 1.94 l
+35.983 1.94 l
+36.012 1.602 l
+36.167 1.866 36.398 1.999 36.703 1.999 c
+37.034 1.999 37.281 1.882 37.438 1.646 c
+37.603 1.419 37.688 1.08 37.688 0.632 c
+h
+37.203 0.588 m
+37.203 0.919 37.148 1.165 37.042 1.323 c
+36.942 1.477 36.78 1.558 36.556 1.558 c
+36.321 1.558 36.145 1.44 36.027 1.205 c
+36.027 -0.338 l
+36.145 -0.566 36.325 -0.676 36.571 -0.676 c
+36.784 -0.676 36.942 -0.599 37.042 -0.441 c
+37.148 -0.287 37.203 -0.044 37.203 0.279 c
+h
+38.041 0.588 m
+38.041 1.018 38.143 1.359 38.349 1.617 c
+38.563 1.87 38.842 1.999 39.187 1.999 c
+39.529 1.999 39.805 1.87 40.011 1.617 c
+40.223 1.371 40.338 1.037 40.348 0.617 c
+40.348 0.309 l
+40.348 -0.125 40.238 -0.467 40.025 -0.721 c
+39.82 -0.977 39.54 -1.103 39.187 -1.103 c
+38.842 -1.103 38.57 -0.981 38.364 -0.735 c
+38.158 -0.492 38.048 -0.158 38.041 0.264 c
+h
+38.526 0.309 m
+38.526 -0.008 38.584 -0.25 38.702 -0.426 c
+38.827 -0.595 38.989 -0.676 39.187 -0.676 c
+39.617 -0.676 39.841 -0.368 39.864 0.25 c
+39.864 0.588 l
+39.864 0.889 39.797 1.132 39.673 1.309 c
+39.554 1.484 39.393 1.573 39.187 1.573 c
+38.989 1.573 38.827 1.484 38.702 1.309 c
+38.584 1.132 38.526 0.889 38.526 0.588 c
+h
+42.23 -0.279 m
+42.23 -0.173 42.189 -0.085 42.112 -0.015 c
+42.031 0.062 41.881 0.151 41.657 0.25 c
+41.393 0.357 41.204 0.449 41.098 0.529 c
+40.988 0.607 40.911 0.694 40.863 0.794 c
+40.811 0.889 40.79 1.007 40.79 1.147 c
+40.79 1.389 40.878 1.591 41.054 1.749 c
+41.231 1.914 41.455 1.999 41.73 1.999 c
+42.025 1.999 42.26 1.911 42.436 1.735 c
+42.612 1.565 42.7 1.352 42.7 1.087 c
+42.216 1.087 l
+42.216 1.224 42.164 1.338 42.068 1.426 c
+41.98 1.521 41.867 1.573 41.73 1.573 c
+41.583 1.573 41.47 1.532 41.393 1.455 c
+41.312 1.386 41.275 1.286 41.275 1.161 c
+41.275 1.062 41.304 0.985 41.362 0.926 c
+41.422 0.867 41.561 0.786 41.79 0.69 c
+42.149 0.544 42.395 0.401 42.524 0.264 c
+42.66 0.136 42.73 -0.037 42.73 -0.25 c
+42.73 -0.507 42.634 -0.713 42.451 -0.867 c
+42.274 -1.025 42.039 -1.103 41.745 -1.103 c
+41.429 -1.103 41.175 -1.014 40.981 -0.838 c
+40.793 -0.654 40.701 -0.422 40.701 -0.147 c
+41.187 -0.147 l
+41.194 -0.316 41.245 -0.449 41.333 -0.544 c
+41.429 -0.632 41.568 -0.676 41.745 -0.676 c
+41.9 -0.676 42.017 -0.643 42.098 -0.573 c
+42.186 -0.507 42.23 -0.408 42.23 -0.279 c
+43.714 -1.043 -0.5 2.983 re
+43.744 2.734 m
+43.744 2.645 43.718 2.572 43.671 2.514 c
+43.631 2.462 43.56 2.44 43.465 2.44 c
+43.377 2.44 43.307 2.462 43.259 2.514 c
+43.219 2.572 43.201 2.639 43.201 2.72 c
+43.201 2.807 43.219 2.881 43.259 2.94 c
+43.307 2.998 43.377 3.028 43.465 3.028 c
+43.56 3.028 43.631 2.998 43.671 2.94 c
+43.718 2.881 43.744 2.811 43.744 2.734 c
+45.023 2.66 m
+45.023 1.94 l
+45.478 1.94 l
+45.478 1.544 l
+45.023 1.544 l
+45.023 -0.309 l
+45.023 -0.426 45.042 -0.515 45.082 -0.573 c
+45.119 -0.632 45.188 -0.661 45.287 -0.661 c
+45.346 -0.661 45.409 -0.654 45.478 -0.632 c
+45.478 -1.043 l
+45.361 -1.08 45.247 -1.103 45.14 -1.103 c
+44.942 -1.103 44.791 -1.037 44.685 -0.897 c
+44.585 -0.761 44.537 -0.566 44.537 -0.309 c
+44.537 1.544 l
+44.082 1.544 l
+44.082 1.94 l
+44.537 1.94 l
+44.537 2.66 l
+h
+45.79 0.588 m
+45.79 1.018 45.894 1.359 46.1 1.617 c
+46.313 1.87 46.592 1.999 46.937 1.999 c
+47.279 1.999 47.554 1.87 47.76 1.617 c
+47.974 1.371 48.088 1.037 48.099 0.617 c
+48.099 0.309 l
+48.099 -0.125 47.988 -0.467 47.776 -0.721 c
+47.569 -0.977 47.29 -1.103 46.937 -1.103 c
+46.592 -1.103 46.32 -0.981 46.114 -0.735 c
+45.908 -0.492 45.798 -0.158 45.79 0.264 c
+h
+46.276 0.309 m
+46.276 -0.008 46.335 -0.25 46.453 -0.426 c
+46.577 -0.595 46.739 -0.676 46.937 -0.676 c
+47.367 -0.676 47.591 -0.368 47.614 0.25 c
+47.614 0.588 l
+47.614 0.889 47.548 1.132 47.423 1.309 c
+47.305 1.484 47.143 1.573 46.937 1.573 c
+46.739 1.573 46.577 1.484 46.453 1.309 c
+46.335 1.132 46.276 0.889 46.276 0.588 c
+h
+49.771 1.484 m
+49.701 1.492 49.628 1.5 49.551 1.5 c
+49.293 1.5 49.117 1.359 49.021 1.087 c
+49.021 -1.043 l
+48.536 -1.043 l
+48.536 1.94 l
+49.006 1.94 l
+49.021 1.631 l
+49.146 1.874 49.33 1.999 49.565 1.999 c
+49.642 1.999 49.705 1.984 49.756 1.955 c
+h
+51.001 -0.235 m
+51.546 1.94 l
+52.06 1.94 l
+51.09 -1.47 l
+51.02 -1.723 50.918 -1.914 50.781 -2.043 c
+50.642 -2.179 50.491 -2.249 50.326 -2.249 c
+50.256 -2.249 50.172 -2.234 50.076 -2.205 c
+50.076 -1.793 l
+50.178 -1.808 l
+50.315 -1.808 50.421 -1.771 50.502 -1.706 c
+50.59 -1.635 50.656 -1.517 50.708 -1.353 c
+50.796 -1.014 l
+49.929 1.94 l
+50.457 1.94 l
+h
+52.138 -0.779 m
+52.138 -0.69 52.159 -0.617 52.211 -0.559 c
+52.269 -0.5 52.346 -0.47 52.446 -0.47 c
+52.553 -0.47 52.63 -0.5 52.681 -0.559 c
+52.74 -0.617 52.769 -0.69 52.769 -0.779 c
+52.769 -0.86 52.74 -0.926 52.681 -0.985 c
+52.63 -1.043 52.553 -1.073 52.446 -1.073 c
+52.346 -1.073 52.269 -1.043 52.211 -0.985 c
+52.159 -0.926 52.138 -0.86 52.138 -0.779 c
+f
+Q
+ endstream endobj 47 0 obj <</BBox[698.93 463.095 712.887 458.964]/Group 83 0 R/Length 3851/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 701.5309 459.523 cm
+0 0 m
+-0.088 -0.118 l
+-0.345 -0.412 -0.713 -0.559 -1.19 -0.559 c
+-1.631 -0.559 -1.977 -0.419 -2.219 -0.133 c
+-2.466 0.162 -2.595 0.573 -2.601 1.103 c
+-2.601 1.881 l
+-2.601 2.447 -2.491 2.87 -2.263 3.146 c
+-2.04 3.428 -1.701 3.572 -1.249 3.572 c
+-0.867 3.572 -0.569 3.462 -0.353 3.248 c
+-0.139 3.032 -0.022 2.726 0 2.337 c
+-0.5 2.337 l
+-0.521 2.579 -0.588 2.77 -0.706 2.911 c
+-0.823 3.057 -1.007 3.131 -1.249 3.131 c
+-1.536 3.131 -1.745 3.035 -1.881 2.851 c
+-2.021 2.664 -2.087 2.366 -2.087 1.955 c
+-2.087 1.132 l
+-2.087 0.727 -2.013 0.419 -1.866 0.206 c
+-1.712 -0.011 -1.484 -0.118 -1.19 -0.118 c
+-0.926 -0.118 -0.72 -0.056 -0.573 0.073 c
+-0.5 0.147 l
+-0.5 1.072 l
+-1.234 1.072 l
+-1.234 1.5 l
+0 1.5 l
+h
+1.077 -0.5 -0.5 2.983 re
+1.106 3.277 m
+1.106 3.189 1.081 3.116 1.033 3.057 c
+0.992 3.006 0.923 2.984 0.827 2.984 c
+0.738 2.984 0.669 3.006 0.621 3.057 c
+0.58 3.116 0.563 3.183 0.563 3.263 c
+0.563 3.351 0.58 3.424 0.621 3.484 c
+0.669 3.542 0.738 3.572 0.827 3.572 c
+0.923 3.572 0.992 3.542 1.033 3.484 c
+1.081 3.424 1.106 3.355 1.106 3.277 c
+2.382 3.204 m
+2.382 2.484 l
+2.837 2.484 l
+2.837 2.087 l
+2.382 2.087 l
+2.382 0.235 l
+2.382 0.118 2.4 0.029 2.44 -0.029 c
+2.477 -0.088 2.547 -0.118 2.646 -0.118 c
+2.705 -0.118 2.768 -0.11 2.837 -0.088 c
+2.837 -0.5 l
+2.72 -0.536 2.606 -0.559 2.499 -0.559 c
+2.301 -0.559 2.15 -0.493 2.043 -0.353 c
+1.945 -0.217 1.896 -0.023 1.896 0.235 c
+1.896 2.087 l
+1.441 2.087 l
+1.441 2.484 l
+1.896 2.484 l
+1.896 3.204 l
+h
+5.039 -0.5 -0.501 2.983 re
+5.068 3.277 m
+5.068 3.189 5.042 3.116 4.994 3.057 c
+4.954 3.006 4.884 2.984 4.788 2.984 c
+4.7 2.984 4.63 3.006 4.582 3.057 c
+4.542 3.116 4.524 3.183 4.524 3.263 c
+4.524 3.351 4.542 3.424 4.582 3.484 c
+4.63 3.542 4.7 3.572 4.788 3.572 c
+4.884 3.572 4.954 3.542 4.994 3.484 c
+5.042 3.424 5.068 3.355 5.068 3.277 c
+7.151 0.264 m
+7.151 0.371 7.111 0.459 7.034 0.529 c
+6.953 0.606 6.802 0.694 6.578 0.794 c
+6.313 0.9 6.126 0.992 6.02 1.072 c
+5.91 1.151 5.832 1.238 5.785 1.338 c
+5.733 1.433 5.711 1.55 5.711 1.69 c
+5.711 1.933 5.799 2.135 5.976 2.293 c
+6.151 2.458 6.376 2.543 6.652 2.543 c
+6.945 2.543 7.181 2.454 7.357 2.278 c
+7.533 2.109 7.622 1.896 7.622 1.631 c
+7.136 1.631 l
+7.136 1.768 7.086 1.881 6.99 1.97 c
+6.901 2.065 6.787 2.117 6.652 2.117 c
+6.504 2.117 6.39 2.076 6.313 1.999 c
+6.232 1.929 6.196 1.83 6.196 1.705 c
+6.196 1.606 6.225 1.529 6.284 1.469 c
+6.342 1.411 6.483 1.33 6.71 1.234 c
+7.071 1.087 7.317 0.944 7.445 0.808 c
+7.581 0.68 7.651 0.507 7.651 0.293 c
+7.651 0.037 7.556 -0.169 7.372 -0.324 c
+7.196 -0.482 6.961 -0.559 6.666 -0.559 c
+6.35 -0.559 6.097 -0.47 5.902 -0.294 c
+5.714 -0.11 5.623 0.121 5.623 0.397 c
+6.107 0.397 l
+6.115 0.228 6.167 0.095 6.255 0 c
+6.35 -0.088 6.49 -0.133 6.666 -0.133 c
+6.82 -0.133 6.938 -0.1 7.019 -0.029 c
+7.107 0.037 7.151 0.135 7.151 0.264 c
+10.841 -0.5 m
+10.811 -0.434 10.789 -0.324 10.782 -0.177 c
+10.606 -0.434 10.385 -0.559 10.12 -0.559 c
+9.845 -0.559 9.628 -0.485 9.474 -0.339 c
+9.326 -0.183 9.253 0.033 9.253 0.309 c
+9.253 0.61 9.357 0.852 9.562 1.029 c
+9.768 1.213 10.051 1.308 10.415 1.308 c
+10.768 1.308 l
+10.768 1.631 l
+10.768 1.808 10.727 1.929 10.65 1.999 c
+10.569 2.076 10.452 2.117 10.297 2.117 c
+10.15 2.117 10.025 2.072 9.93 1.984 c
+9.841 1.896 9.797 1.785 9.797 1.66 c
+9.312 1.66 l
+9.312 1.808 9.357 1.947 9.444 2.087 c
+9.532 2.234 9.65 2.344 9.797 2.425 c
+9.951 2.502 10.124 2.543 10.311 2.543 c
+10.624 2.543 10.859 2.462 11.017 2.308 c
+11.171 2.161 11.252 1.94 11.252 1.646 c
+11.252 0.147 l
+11.26 -0.088 11.296 -0.291 11.356 -0.456 c
+11.356 -0.5 l
+h
+10.194 -0.118 m
+10.311 -0.118 10.422 -0.085 10.532 -0.015 c
+10.639 0.052 10.716 0.135 10.768 0.235 c
+10.768 0.941 l
+10.502 0.941 l
+10.267 0.941 10.08 0.889 9.945 0.794 c
+9.816 0.694 9.753 0.551 9.753 0.367 c
+9.753 0.198 9.783 0.077 9.841 0 c
+9.908 -0.081 10.025 -0.118 10.194 -0.118 c
+f
+Q
+ endstream endobj 48 0 obj <</BBox[714.378 463.257 737.088 458.964]/Group 84 0 R/Length 5616/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 714.3777 460.6105 cm
+0 0 m
+0 0.489 0.081 0.852 0.25 1.087 c
+0.416 1.33 0.655 1.455 0.971 1.455 c
+1.206 1.455 1.397 1.353 1.544 1.147 c
+1.544 2.646 l
+2.338 2.646 l
+2.338 -1.587 l
+1.617 -1.587 l
+1.588 -1.278 l
+1.43 -1.525 1.224 -1.646 0.971 -1.646 c
+0.655 -1.646 0.416 -1.529 0.25 -1.294 c
+0.092 -1.051 0.008 -0.698 0 -0.235 c
+h
+0.78 -0.206 m
+0.78 -0.5 0.809 -0.706 0.867 -0.823 c
+0.934 -0.933 1.044 -0.985 1.191 -0.985 c
+1.345 -0.985 1.463 -0.918 1.544 -0.779 c
+1.544 0.573 l
+1.463 0.721 1.353 0.794 1.206 0.794 c
+1.059 0.794 0.948 0.735 0.882 0.617 c
+0.813 0.507 0.78 0.301 0.78 0 c
+h
+3.539 -1.587 -0.779 2.983 re
+2.716 2.161 m
+2.716 2.286 2.753 2.389 2.833 2.469 c
+2.911 2.547 3.014 2.587 3.142 2.587 c
+3.267 2.587 3.371 2.547 3.451 2.469 c
+3.528 2.389 3.568 2.286 3.568 2.161 c
+3.568 2.043 3.528 1.944 3.451 1.866 c
+3.381 1.786 3.278 1.749 3.142 1.749 c
+3.014 1.749 2.911 1.786 2.833 1.866 c
+2.753 1.944 2.716 2.043 2.716 2.161 c
+5.366 -0.794 m
+5.366 -0.727 5.329 -0.661 5.263 -0.603 c
+5.204 -0.544 5.064 -0.47 4.851 -0.382 c
+4.528 -0.246 4.308 -0.11 4.19 0.029 c
+4.072 0.166 4.013 0.338 4.013 0.544 c
+4.013 0.808 4.105 1.022 4.293 1.191 c
+4.476 1.367 4.726 1.455 5.042 1.455 c
+5.366 1.455 5.623 1.367 5.821 1.191 c
+6.016 1.022 6.115 0.798 6.115 0.515 c
+5.336 0.515 l
+5.336 0.757 5.233 0.882 5.027 0.882 c
+4.946 0.882 4.881 0.852 4.822 0.794 c
+4.77 0.742 4.748 0.676 4.748 0.588 c
+4.748 0.518 4.778 0.459 4.836 0.412 c
+4.896 0.36 5.031 0.287 5.248 0.191 c
+5.571 0.073 5.796 -0.058 5.924 -0.206 c
+6.06 -0.345 6.13 -0.529 6.13 -0.764 c
+6.13 -1.029 6.027 -1.246 5.821 -1.411 c
+5.623 -1.569 5.366 -1.646 5.042 -1.646 c
+4.815 -1.646 4.62 -1.602 4.454 -1.514 c
+4.285 -1.426 4.153 -1.309 4.057 -1.161 c
+3.969 -1.007 3.925 -0.838 3.925 -0.661 c
+4.66 -0.661 l
+4.667 -0.801 4.704 -0.904 4.763 -0.97 c
+4.822 -1.04 4.917 -1.073 5.057 -1.073 c
+5.263 -1.073 5.366 -0.981 5.366 -0.794 c
+7.354 2.132 m
+7.354 1.396 l
+7.751 1.396 l
+7.751 0.808 l
+7.354 0.808 l
+7.354 -0.676 l
+7.354 -0.794 7.369 -0.878 7.398 -0.926 c
+7.435 -0.966 7.5 -0.985 7.589 -0.985 c
+7.666 -0.985 7.728 -0.977 7.78 -0.956 c
+7.765 -1.573 l
+7.637 -1.621 7.493 -1.646 7.339 -1.646 c
+6.839 -1.646 6.582 -1.359 6.575 -0.779 c
+6.575 0.808 l
+6.236 0.808 l
+6.236 1.396 l
+6.575 1.396 l
+6.575 2.132 l
+h
+9.526 0.647 m
+9.276 0.661 l
+9.058 0.661 8.912 0.566 8.834 0.382 c
+8.834 -1.587 l
+8.056 -1.587 l
+8.056 1.396 l
+8.79 1.396 l
+8.82 1.073 l
+8.937 1.326 9.103 1.455 9.32 1.455 c
+9.407 1.455 9.482 1.44 9.54 1.411 c
+h
+10.628 -1.587 -0.779 2.983 re
+9.804 2.161 m
+9.804 2.286 9.841 2.389 9.922 2.469 c
+9.999 2.547 10.103 2.587 10.231 2.587 c
+10.356 2.587 10.459 2.547 10.54 2.469 c
+10.617 2.389 10.658 2.286 10.658 2.161 c
+10.658 2.043 10.617 1.944 10.54 1.866 c
+10.469 1.786 10.367 1.749 10.231 1.749 c
+10.103 1.749 9.999 1.786 9.922 1.866 c
+9.841 1.944 9.804 2.043 9.804 2.161 c
+13.469 -0.191 m
+13.469 -0.673 13.388 -1.036 13.233 -1.278 c
+13.075 -1.525 12.829 -1.646 12.499 -1.646 c
+12.241 -1.646 12.035 -1.529 11.881 -1.294 c
+11.851 -1.587 l
+11.132 -1.587 l
+11.132 2.646 l
+11.911 2.646 l
+11.911 1.147 l
+12.057 1.353 12.252 1.455 12.499 1.455 c
+12.829 1.455 13.072 1.33 13.218 1.087 c
+13.373 0.852 13.457 0.5 13.469 0.029 c
+h
+12.69 0 m
+12.69 0.312 12.653 0.522 12.586 0.632 c
+12.528 0.738 12.425 0.794 12.278 0.794 c
+12.109 0.794 11.988 0.721 11.911 0.573 c
+11.911 -0.779 l
+11.988 -0.926 12.109 -0.999 12.278 -0.999 c
+12.425 -0.999 12.528 -0.952 12.586 -0.852 c
+12.645 -0.757 12.678 -0.565 12.69 -0.279 c
+h
+15.217 -1.309 m
+15.059 -1.536 14.843 -1.646 14.571 -1.646 c
+14.295 -1.646 14.086 -1.554 13.939 -1.367 c
+13.799 -1.172 13.733 -0.897 13.733 -0.544 c
+13.733 1.396 l
+14.512 1.396 l
+14.512 -0.559 l
+14.512 -0.845 14.608 -0.985 14.806 -0.985 c
+14.982 -0.985 15.107 -0.912 15.188 -0.764 c
+15.188 1.396 l
+15.967 1.396 l
+15.967 -1.587 l
+15.247 -1.587 l
+h
+17.249 2.132 m
+17.249 1.396 l
+17.646 1.396 l
+17.646 0.808 l
+17.249 0.808 l
+17.249 -0.676 l
+17.249 -0.794 17.264 -0.878 17.294 -0.926 c
+17.33 -0.966 17.397 -0.985 17.485 -0.985 c
+17.562 -0.985 17.625 -0.977 17.676 -0.956 c
+17.661 -1.573 l
+17.533 -1.621 17.39 -1.646 17.235 -1.646 c
+16.736 -1.646 16.478 -1.359 16.47 -0.779 c
+16.47 0.808 l
+16.133 0.808 l
+16.133 1.396 l
+16.47 1.396 l
+16.47 2.132 l
+h
+19.161 -1.646 m
+18.756 -1.646 18.444 -1.529 18.22 -1.294 c
+18.003 -1.051 17.897 -0.706 17.897 -0.264 c
+17.897 -0.015 l
+17.897 0.455 17.999 0.816 18.205 1.073 c
+18.411 1.326 18.705 1.455 19.088 1.455 c
+19.458 1.455 19.738 1.33 19.925 1.087 c
+20.12 0.852 20.219 0.5 20.219 0.029 c
+20.219 -0.353 l
+18.676 -0.353 l
+18.683 -0.58 18.727 -0.746 18.808 -0.852 c
+18.896 -0.952 19.032 -0.999 19.219 -0.999 c
+19.473 -0.999 19.69 -0.908 19.867 -0.721 c
+20.175 -1.205 l
+20.075 -1.334 19.932 -1.44 19.749 -1.529 c
+19.572 -1.606 19.374 -1.646 19.161 -1.646 c
+18.676 0.191 m
+19.454 0.191 l
+19.454 0.264 l
+19.454 0.441 19.425 0.573 19.366 0.661 c
+19.308 0.757 19.208 0.808 19.073 0.808 c
+18.944 0.808 18.845 0.757 18.778 0.661 c
+18.72 0.563 18.683 0.405 18.676 0.191 c
+20.374 0 m
+20.374 0.489 20.454 0.852 20.623 1.087 c
+20.788 1.33 21.027 1.455 21.344 1.455 c
+21.579 1.455 21.77 1.353 21.916 1.147 c
+21.916 2.646 l
+22.71 2.646 l
+22.71 -1.587 l
+21.991 -1.587 l
+21.961 -1.278 l
+21.803 -1.525 21.597 -1.646 21.344 -1.646 c
+21.027 -1.646 20.788 -1.529 20.623 -1.294 c
+20.465 -1.051 20.381 -0.698 20.374 -0.235 c
+h
+21.153 -0.206 m
+21.153 -0.5 21.182 -0.706 21.241 -0.823 c
+21.307 -0.933 21.417 -0.985 21.564 -0.985 c
+21.718 -0.985 21.836 -0.918 21.916 -0.779 c
+21.916 0.573 l
+21.836 0.721 21.725 0.794 21.579 0.794 c
+21.432 0.794 21.322 0.735 21.255 0.617 c
+21.185 0.507 21.153 0.301 21.153 0 c
+h
+f
+Q
+ endstream endobj 49 0 obj <</BBox[738.525 463.257 767.419 458.964]/Group 85 0 R/Length 6236/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 739.5979 459.7581 cm
+0 0 m
+0.573 2.248 l
+1.073 2.248 l
+0.177 -0.735 l
+-0.176 -0.735 l
+-1.073 2.248 l
+-0.588 2.248 l
+h
+2.44 -0.794 m
+2.065 -0.794 1.783 -0.688 1.588 -0.47 c
+1.39 -0.246 1.294 0.081 1.294 0.515 c
+1.294 0.881 l
+1.294 1.323 1.386 1.668 1.573 1.926 c
+1.768 2.179 2.043 2.308 2.396 2.308 c
+2.738 2.308 2.992 2.194 3.16 1.97 c
+3.337 1.741 3.429 1.396 3.439 0.926 c
+3.439 0.617 l
+1.779 0.617 l
+1.779 0.544 l
+1.779 0.22 1.837 -0.015 1.955 -0.162 c
+2.072 -0.301 2.242 -0.368 2.469 -0.368 c
+2.616 -0.368 2.741 -0.345 2.851 -0.294 c
+2.959 -0.235 3.061 -0.147 3.16 -0.029 c
+3.41 -0.339 l
+3.204 -0.643 2.882 -0.794 2.44 -0.794 c
+2.396 1.882 m
+2.19 1.882 2.036 1.812 1.941 1.675 c
+1.841 1.536 1.787 1.323 1.779 1.029 c
+2.955 1.029 l
+2.955 1.103 l
+2.932 1.374 2.882 1.573 2.793 1.691 c
+2.705 1.816 2.572 1.882 2.396 1.882 c
+5.086 1.793 m
+5.016 1.801 4.943 1.808 4.866 1.808 c
+4.609 1.808 4.432 1.668 4.336 1.396 c
+4.336 -0.735 l
+3.851 -0.735 l
+3.851 2.248 l
+4.322 2.248 l
+4.336 1.94 l
+4.461 2.183 4.645 2.308 4.881 2.308 c
+4.958 2.308 5.02 2.293 5.072 2.263 c
+h
+6.898 0.029 m
+6.898 0.135 6.857 0.224 6.78 0.294 c
+6.699 0.371 6.549 0.459 6.325 0.559 c
+6.059 0.665 5.872 0.757 5.766 0.837 c
+5.656 0.915 5.579 1.003 5.531 1.103 c
+5.479 1.198 5.457 1.315 5.457 1.455 c
+5.457 1.698 5.546 1.899 5.722 2.057 c
+5.898 2.223 6.122 2.308 6.398 2.308 c
+6.692 2.308 6.927 2.219 7.104 2.043 c
+7.279 1.874 7.368 1.66 7.368 1.396 c
+6.883 1.396 l
+6.883 1.532 6.832 1.646 6.736 1.735 c
+6.648 1.83 6.533 1.882 6.398 1.882 c
+6.251 1.882 6.137 1.841 6.059 1.764 c
+5.979 1.694 5.943 1.595 5.943 1.469 c
+5.943 1.371 5.972 1.294 6.03 1.234 c
+6.089 1.176 6.229 1.095 6.456 0.999 c
+6.817 0.852 7.063 0.709 7.192 0.573 c
+7.327 0.445 7.397 0.272 7.397 0.058 c
+7.397 -0.198 7.302 -0.405 7.119 -0.559 c
+6.942 -0.717 6.707 -0.794 6.413 -0.794 c
+6.097 -0.794 5.843 -0.706 5.648 -0.53 c
+5.461 -0.345 5.369 -0.114 5.369 0.162 c
+5.854 0.162 l
+5.862 -0.008 5.913 -0.14 6.001 -0.235 c
+6.097 -0.324 6.236 -0.368 6.413 -0.368 c
+6.567 -0.368 6.685 -0.335 6.765 -0.264 c
+6.853 -0.198 6.898 -0.1 6.898 0.029 c
+8.386 -0.735 -0.5 2.983 re
+8.415 3.042 m
+8.415 2.954 8.39 2.881 8.342 2.822 c
+8.301 2.771 8.232 2.749 8.137 2.749 c
+8.048 2.749 7.978 2.771 7.93 2.822 c
+7.89 2.881 7.871 2.947 7.871 3.028 c
+7.871 3.116 7.89 3.189 7.93 3.248 c
+7.978 3.307 8.048 3.337 8.137 3.337 c
+8.232 3.337 8.301 3.307 8.342 3.248 c
+8.39 3.189 8.415 3.119 8.415 3.042 c
+8.956 0.897 m
+8.956 1.326 9.058 1.668 9.264 1.926 c
+9.477 2.179 9.756 2.308 10.102 2.308 c
+10.444 2.308 10.72 2.179 10.925 1.926 c
+11.138 1.679 11.252 1.345 11.263 0.926 c
+11.263 0.617 l
+11.263 0.183 11.153 -0.158 10.94 -0.412 c
+10.734 -0.669 10.454 -0.794 10.102 -0.794 c
+9.756 -0.794 9.485 -0.673 9.279 -0.426 c
+9.073 -0.183 8.962 0.151 8.956 0.573 c
+h
+9.44 0.617 m
+9.44 0.301 9.5 0.058 9.617 -0.118 c
+9.742 -0.287 9.903 -0.368 10.102 -0.368 c
+10.532 -0.368 10.756 -0.059 10.778 0.559 c
+10.778 0.897 l
+10.778 1.198 10.712 1.44 10.587 1.617 c
+10.47 1.793 10.308 1.882 10.102 1.882 c
+9.903 1.882 9.742 1.793 9.617 1.617 c
+9.5 1.44 9.44 1.198 9.44 0.897 c
+h
+12.16 2.248 m
+12.174 1.926 l
+12.359 2.179 12.601 2.308 12.895 2.308 c
+13.424 2.308 13.693 1.955 13.704 1.249 c
+13.704 -0.735 l
+13.218 -0.735 l
+13.218 1.22 l
+13.218 1.455 13.178 1.621 13.101 1.72 c
+13.02 1.816 12.902 1.866 12.748 1.866 c
+12.63 1.866 12.52 1.826 12.424 1.749 c
+12.326 1.668 12.248 1.562 12.189 1.425 c
+12.189 -0.735 l
+11.704 -0.735 l
+11.704 2.248 l
+h
+16.488 -0.368 m
+16.654 -0.368 16.787 -0.32 16.885 -0.221 c
+16.981 -0.125 17.036 0.018 17.047 0.206 c
+17.503 0.206 l
+17.492 -0.081 17.389 -0.32 17.194 -0.515 c
+17.007 -0.702 16.772 -0.794 16.488 -0.794 c
+16.125 -0.794 15.846 -0.676 15.651 -0.441 c
+15.453 -0.206 15.357 0.139 15.357 0.602 c
+15.357 0.926 l
+15.357 1.374 15.449 1.72 15.636 1.955 c
+15.831 2.19 16.114 2.308 16.488 2.308 c
+16.79 2.308 17.033 2.209 17.209 2.013 c
+17.392 1.816 17.492 1.55 17.503 1.22 c
+17.047 1.22 l
+17.026 1.444 16.966 1.61 16.871 1.72 c
+16.783 1.826 16.654 1.882 16.488 1.882 c
+16.272 1.882 16.11 1.808 16.004 1.66 c
+15.904 1.521 15.85 1.294 15.842 0.97 c
+15.842 0.588 l
+15.842 0.235 15.89 -0.015 15.989 -0.162 c
+16.095 -0.301 16.261 -0.368 16.488 -0.368 c
+17.793 0.897 m
+17.793 1.326 17.897 1.668 18.102 1.926 c
+18.315 2.179 18.595 2.308 18.94 2.308 c
+19.281 2.308 19.557 2.179 19.763 1.926 c
+19.976 1.679 20.09 1.345 20.101 0.926 c
+20.101 0.617 l
+20.101 0.183 19.991 -0.158 19.778 -0.412 c
+19.572 -0.669 19.293 -0.794 18.94 -0.794 c
+18.595 -0.794 18.323 -0.673 18.117 -0.426 c
+17.911 -0.183 17.801 0.151 17.793 0.573 c
+h
+18.279 0.617 m
+18.279 0.301 18.337 0.058 18.455 -0.118 c
+18.58 -0.287 18.742 -0.368 18.94 -0.368 c
+19.37 -0.368 19.594 -0.059 19.616 0.559 c
+19.616 0.897 l
+19.616 1.198 19.55 1.44 19.425 1.617 c
+19.308 1.793 19.146 1.882 18.94 1.882 c
+18.742 1.882 18.58 1.793 18.455 1.617 c
+18.337 1.44 18.279 1.198 18.279 0.897 c
+h
+20.997 2.248 m
+21.012 1.926 l
+21.196 2.179 21.439 2.308 21.733 2.308 c
+22.262 2.308 22.53 1.955 22.541 1.249 c
+22.541 -0.735 l
+22.056 -0.735 l
+22.056 1.22 l
+22.056 1.455 22.015 1.621 21.938 1.72 c
+21.857 1.816 21.74 1.866 21.585 1.866 c
+21.468 1.866 21.358 1.826 21.263 1.749 c
+21.163 1.668 21.086 1.562 21.027 1.425 c
+21.027 -0.735 l
+20.542 -0.735 l
+20.542 2.248 l
+h
+24.327 1.793 m
+24.257 1.801 24.184 1.808 24.106 1.808 c
+23.85 1.808 23.673 1.668 23.578 1.396 c
+23.578 -0.735 l
+23.092 -0.735 l
+23.092 2.248 l
+23.563 2.248 l
+23.578 1.94 l
+23.702 2.183 23.886 2.308 24.122 2.308 c
+24.199 2.308 24.261 2.293 24.313 2.263 c
+h
+24.544 0.897 m
+24.544 1.326 24.646 1.668 24.852 1.926 c
+25.066 2.179 25.345 2.308 25.691 2.308 c
+26.032 2.308 26.308 2.179 26.514 1.926 c
+26.726 1.679 26.84 1.345 26.852 0.926 c
+26.852 0.617 l
+26.852 0.183 26.742 -0.158 26.528 -0.412 c
+26.323 -0.669 26.043 -0.794 25.691 -0.794 c
+25.345 -0.794 25.073 -0.673 24.868 -0.426 c
+24.662 -0.183 24.551 0.151 24.544 0.573 c
+h
+25.029 0.617 m
+25.029 0.301 25.088 0.058 25.205 -0.118 c
+25.33 -0.287 25.492 -0.368 25.691 -0.368 c
+26.121 -0.368 26.345 -0.059 26.366 0.559 c
+26.366 0.897 l
+26.366 1.198 26.3 1.44 26.175 1.617 c
+26.058 1.793 25.896 1.882 25.691 1.882 c
+25.492 1.882 25.33 1.793 25.205 1.617 c
+25.088 1.44 25.029 1.198 25.029 0.897 c
+h
+27.821 -0.735 -0.5 4.233 re
+f
+Q
+ endstream endobj 50 0 obj <</BBox[701.664 456.672 764.976 451.232]/Group 86 0 R/Length 14524/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 703.1923 453.2021 cm
+0 0 m
+0 0.106 -0.04 0.195 -0.118 0.264 c
+-0.198 0.341 -0.349 0.43 -0.574 0.53 c
+-0.838 0.636 -1.025 0.728 -1.132 0.808 c
+-1.242 0.886 -1.319 0.974 -1.367 1.073 c
+-1.419 1.168 -1.44 1.286 -1.44 1.426 c
+-1.44 1.669 -1.353 1.87 -1.176 2.028 c
+-1 2.194 -0.775 2.278 -0.5 2.278 c
+-0.206 2.278 0.029 2.19 0.206 2.014 c
+0.382 1.845 0.47 1.631 0.47 1.367 c
+-0.015 1.367 l
+-0.015 1.503 -0.066 1.617 -0.162 1.706 c
+-0.25 1.801 -0.364 1.852 -0.5 1.852 c
+-0.647 1.852 -0.761 1.812 -0.838 1.735 c
+-0.919 1.665 -0.956 1.565 -0.956 1.44 c
+-0.956 1.341 -0.926 1.264 -0.867 1.205 c
+-0.809 1.147 -0.669 1.066 -0.441 0.97 c
+-0.081 0.823 0.166 0.68 0.294 0.544 c
+0.43 0.416 0.5 0.243 0.5 0.029 c
+0.5 -0.228 0.405 -0.434 0.22 -0.588 c
+0.044 -0.746 -0.191 -0.823 -0.485 -0.823 c
+-0.802 -0.823 -1.055 -0.735 -1.249 -0.559 c
+-1.436 -0.374 -1.529 -0.143 -1.529 0.133 c
+-1.044 0.133 l
+-1.037 -0.037 -0.985 -0.169 -0.896 -0.264 c
+-0.802 -0.353 -0.661 -0.397 -0.485 -0.397 c
+-0.331 -0.397 -0.214 -0.364 -0.133 -0.294 c
+-0.044 -0.228 0 -0.129 0 0 c
+1.768 0.044 m
+2.311 2.219 l
+2.826 2.219 l
+1.856 -1.191 l
+1.786 -1.444 1.683 -1.635 1.547 -1.764 c
+1.407 -1.899 1.257 -1.97 1.091 -1.97 c
+1.022 -1.97 0.937 -1.955 0.841 -1.926 c
+0.841 -1.514 l
+0.945 -1.529 l
+1.08 -1.529 1.187 -1.492 1.268 -1.426 c
+1.356 -1.356 1.422 -1.238 1.473 -1.073 c
+1.562 -0.735 l
+0.694 2.219 l
+1.224 2.219 l
+h
+4.59 0 m
+4.59 0.106 4.549 0.195 4.472 0.264 c
+4.391 0.341 4.241 0.43 4.016 0.53 c
+3.752 0.636 3.564 0.728 3.458 0.808 c
+3.347 0.886 3.27 0.974 3.223 1.073 c
+3.171 1.168 3.15 1.286 3.15 1.426 c
+3.15 1.669 3.237 1.87 3.414 2.028 c
+3.59 2.194 3.815 2.278 4.09 2.278 c
+4.384 2.278 4.619 2.19 4.796 2.014 c
+4.972 1.845 5.06 1.631 5.06 1.367 c
+4.575 1.367 l
+4.575 1.503 4.523 1.617 4.428 1.706 c
+4.34 1.801 4.226 1.852 4.09 1.852 c
+3.943 1.852 3.829 1.812 3.752 1.735 c
+3.671 1.665 3.634 1.565 3.634 1.44 c
+3.634 1.341 3.663 1.264 3.723 1.205 c
+3.781 1.147 3.921 1.066 4.149 0.97 c
+4.509 0.823 4.755 0.68 4.883 0.544 c
+5.02 0.416 5.089 0.243 5.089 0.029 c
+5.089 -0.228 4.993 -0.434 4.81 -0.588 c
+4.634 -0.746 4.399 -0.823 4.104 -0.823 c
+3.788 -0.823 3.535 -0.735 3.341 -0.559 c
+3.152 -0.374 3.061 -0.143 3.061 0.133 c
+3.546 0.133 l
+3.553 -0.037 3.605 -0.169 3.693 -0.264 c
+3.788 -0.353 3.929 -0.397 4.104 -0.397 c
+4.259 -0.397 4.376 -0.364 4.457 -0.294 c
+4.546 -0.228 4.59 -0.129 4.59 0 c
+6.181 2.94 m
+6.181 2.219 l
+6.637 2.219 l
+6.637 1.823 l
+6.181 1.823 l
+6.181 -0.029 l
+6.181 -0.147 6.2 -0.235 6.24 -0.294 c
+6.277 -0.353 6.346 -0.382 6.445 -0.382 c
+6.504 -0.382 6.566 -0.374 6.637 -0.353 c
+6.637 -0.764 l
+6.519 -0.801 6.405 -0.823 6.298 -0.823 c
+6.1 -0.823 5.949 -0.757 5.843 -0.617 c
+5.743 -0.482 5.696 -0.287 5.696 -0.029 c
+5.696 1.823 l
+5.24 1.823 l
+5.24 2.219 l
+5.696 2.219 l
+5.696 2.94 l
+h
+8.158 -0.823 m
+7.783 -0.823 7.501 -0.717 7.306 -0.5 c
+7.107 -0.276 7.011 0.052 7.011 0.485 c
+7.011 0.852 l
+7.011 1.294 7.104 1.639 7.291 1.897 c
+7.486 2.15 7.761 2.278 8.114 2.278 c
+8.455 2.278 8.709 2.165 8.878 1.941 c
+9.055 1.712 9.147 1.367 9.157 0.897 c
+9.157 0.588 l
+7.497 0.588 l
+7.497 0.515 l
+7.497 0.191 7.555 -0.044 7.673 -0.191 c
+7.79 -0.33 7.96 -0.397 8.187 -0.397 c
+8.334 -0.397 8.459 -0.374 8.569 -0.324 c
+8.676 -0.264 8.779 -0.176 8.878 -0.058 c
+9.128 -0.368 l
+8.922 -0.673 8.598 -0.823 8.158 -0.823 c
+8.114 1.852 m
+7.908 1.852 7.754 1.783 7.658 1.646 c
+7.559 1.507 7.503 1.294 7.497 1 c
+8.673 1 l
+8.673 1.073 l
+8.65 1.345 8.598 1.544 8.511 1.661 c
+8.422 1.786 8.29 1.852 8.114 1.852 c
+10.025 2.219 m
+10.04 1.941 l
+10.216 2.165 10.454 2.278 10.759 2.278 c
+11.09 2.278 11.322 2.132 11.451 1.837 c
+11.634 2.132 11.895 2.278 12.23 2.278 c
+12.788 2.278 13.071 1.933 13.082 1.249 c
+13.082 -0.764 l
+12.597 -0.764 l
+12.597 1.205 l
+12.597 1.419 12.557 1.577 12.48 1.675 c
+12.399 1.783 12.266 1.837 12.083 1.837 c
+11.935 1.837 11.818 1.779 11.73 1.661 c
+11.642 1.551 11.586 1.411 11.568 1.235 c
+11.568 -0.764 l
+11.083 -0.764 l
+11.083 1.22 l
+11.072 1.631 10.899 1.837 10.568 1.837 c
+10.323 1.837 10.15 1.712 10.054 1.47 c
+10.054 -0.764 l
+9.569 -0.764 l
+9.569 2.219 l
+h
+13.56 -0.5 m
+13.56 -0.411 13.581 -0.338 13.633 -0.279 c
+13.692 -0.22 13.77 -0.191 13.868 -0.191 c
+13.975 -0.191 14.052 -0.22 14.104 -0.279 c
+14.163 -0.338 14.192 -0.411 14.192 -0.5 c
+14.192 -0.58 14.163 -0.646 14.104 -0.706 c
+14.052 -0.764 13.975 -0.794 13.868 -0.794 c
+13.77 -0.794 13.692 -0.764 13.633 -0.706 c
+13.581 -0.646 13.56 -0.58 13.56 -0.5 c
+17.242 1.235 m
+18.05 3.248 l
+18.624 3.248 l
+17.492 0.735 l
+17.492 -0.764 l
+16.978 -0.764 l
+16.978 0.735 l
+15.846 3.248 l
+16.419 3.248 l
+h
+18.624 0.867 m
+18.624 1.297 18.726 1.639 18.932 1.897 c
+19.145 2.15 19.424 2.278 19.771 2.278 c
+20.112 2.278 20.388 2.15 20.593 1.897 c
+20.806 1.65 20.92 1.316 20.931 0.897 c
+20.931 0.588 l
+20.931 0.154 20.821 -0.187 20.608 -0.441 c
+20.402 -0.698 20.122 -0.823 19.771 -0.823 c
+19.424 -0.823 19.153 -0.702 18.947 -0.455 c
+18.741 -0.213 18.631 0.121 18.624 0.544 c
+h
+19.108 0.588 m
+19.108 0.272 19.168 0.029 19.285 -0.147 c
+19.41 -0.316 19.572 -0.397 19.771 -0.397 c
+20.201 -0.397 20.424 -0.088 20.446 0.53 c
+20.446 0.867 l
+20.446 1.168 20.38 1.411 20.255 1.588 c
+20.138 1.764 19.976 1.852 19.771 1.852 c
+19.572 1.852 19.41 1.764 19.285 1.588 c
+19.168 1.411 19.108 1.168 19.108 0.867 c
+h
+22.886 -0.5 m
+22.728 -0.717 22.493 -0.823 22.181 -0.823 c
+21.916 -0.823 21.71 -0.731 21.564 -0.544 c
+21.423 -0.36 21.358 -0.085 21.358 0.279 c
+21.358 2.219 l
+21.843 2.219 l
+21.843 0.309 l
+21.843 -0.154 21.982 -0.382 22.269 -0.382 c
+22.563 -0.382 22.761 -0.25 22.871 0.015 c
+22.871 2.219 l
+23.372 2.219 l
+23.372 -0.764 l
+22.901 -0.764 l
+h
+26.157 -0.397 m
+26.322 -0.397 26.455 -0.349 26.553 -0.25 c
+26.649 -0.154 26.705 -0.011 26.715 0.177 c
+27.171 0.177 l
+27.16 -0.11 27.058 -0.349 26.863 -0.544 c
+26.675 -0.731 26.439 -0.823 26.157 -0.823 c
+25.793 -0.823 25.514 -0.706 25.319 -0.47 c
+25.121 -0.235 25.025 0.11 25.025 0.573 c
+25.025 0.897 l
+25.025 1.345 25.117 1.691 25.304 1.926 c
+25.499 2.161 25.782 2.278 26.157 2.278 c
+26.458 2.278 26.701 2.18 26.877 1.984 c
+27.061 1.786 27.16 1.521 27.171 1.191 c
+26.715 1.191 l
+26.693 1.415 26.634 1.58 26.539 1.691 c
+26.451 1.797 26.322 1.852 26.157 1.852 c
+25.94 1.852 25.778 1.779 25.672 1.631 c
+25.572 1.492 25.518 1.264 25.51 0.941 c
+25.51 0.559 l
+25.51 0.206 25.558 -0.044 25.657 -0.191 c
+25.764 -0.33 25.929 -0.397 26.157 -0.397 c
+29.097 -0.764 m
+29.067 -0.698 29.045 -0.588 29.038 -0.441 c
+28.862 -0.698 28.641 -0.823 28.376 -0.823 c
+28.101 -0.823 27.884 -0.75 27.729 -0.603 c
+27.583 -0.448 27.509 -0.231 27.509 0.044 c
+27.509 0.345 27.612 0.588 27.818 0.765 c
+28.024 0.948 28.307 1.043 28.67 1.043 c
+29.023 1.043 l
+29.023 1.367 l
+29.023 1.544 28.982 1.665 28.905 1.735 c
+28.824 1.812 28.708 1.852 28.552 1.852 c
+28.406 1.852 28.281 1.808 28.185 1.72 c
+28.097 1.631 28.053 1.521 28.053 1.396 c
+27.568 1.396 l
+27.568 1.544 27.612 1.683 27.7 1.823 c
+27.789 1.97 27.906 2.08 28.053 2.161 c
+28.207 2.238 28.38 2.278 28.567 2.278 c
+28.88 2.278 29.115 2.198 29.273 2.043 c
+29.427 1.897 29.508 1.675 29.508 1.382 c
+29.508 -0.118 l
+29.516 -0.353 29.552 -0.555 29.611 -0.721 c
+29.611 -0.764 l
+h
+28.45 -0.382 m
+28.567 -0.382 28.677 -0.349 28.788 -0.279 c
+28.895 -0.213 28.972 -0.129 29.023 -0.029 c
+29.023 0.676 l
+28.758 0.676 l
+28.523 0.676 28.336 0.625 28.2 0.53 c
+28.072 0.43 28.009 0.287 28.009 0.103 c
+28.009 -0.066 28.039 -0.187 28.097 -0.264 c
+28.163 -0.345 28.281 -0.382 28.45 -0.382 c
+30.545 2.219 m
+30.559 1.897 l
+30.743 2.15 30.985 2.278 31.28 2.278 c
+31.808 2.278 32.077 1.926 32.088 1.22 c
+32.088 -0.764 l
+31.603 -0.764 l
+31.603 1.191 l
+31.603 1.426 31.563 1.592 31.486 1.691 c
+31.405 1.786 31.287 1.837 31.133 1.837 c
+31.015 1.837 30.904 1.797 30.809 1.72 c
+30.709 1.639 30.632 1.532 30.574 1.396 c
+30.574 -0.764 l
+30.089 -0.764 l
+30.089 2.219 l
+h
+34.329 1.911 m
+34.513 2.153 34.748 2.278 35.035 2.278 c
+35.565 2.278 35.833 1.926 35.843 1.22 c
+35.843 -0.764 l
+35.359 -0.764 l
+35.359 1.191 l
+35.359 1.426 35.318 1.592 35.241 1.691 c
+35.16 1.786 35.043 1.837 34.888 1.837 c
+34.771 1.837 34.661 1.797 34.565 1.72 c
+34.466 1.639 34.389 1.532 34.329 1.396 c
+34.329 -0.764 l
+33.844 -0.764 l
+33.844 3.469 l
+34.329 3.469 l
+h
+37.913 -0.764 m
+37.883 -0.698 37.861 -0.588 37.853 -0.441 c
+37.678 -0.698 37.456 -0.823 37.192 -0.823 c
+36.917 -0.823 36.7 -0.75 36.546 -0.603 c
+36.398 -0.448 36.325 -0.231 36.325 0.044 c
+36.325 0.345 36.428 0.588 36.633 0.765 c
+36.839 0.948 37.123 1.043 37.487 1.043 c
+37.839 1.043 l
+37.839 1.367 l
+37.839 1.544 37.799 1.665 37.722 1.735 c
+37.641 1.812 37.523 1.852 37.369 1.852 c
+37.221 1.852 37.096 1.808 37.001 1.72 c
+36.913 1.631 36.869 1.521 36.869 1.396 c
+36.384 1.396 l
+36.384 1.544 36.428 1.683 36.516 1.823 c
+36.604 1.97 36.722 2.08 36.869 2.161 c
+37.023 2.238 37.196 2.278 37.383 2.278 c
+37.695 2.278 37.931 2.198 38.089 2.043 c
+38.243 1.897 38.324 1.675 38.324 1.382 c
+38.324 -0.118 l
+38.331 -0.353 38.368 -0.555 38.427 -0.721 c
+38.427 -0.764 l
+h
+37.266 -0.382 m
+37.383 -0.382 37.493 -0.349 37.604 -0.279 c
+37.711 -0.213 37.788 -0.129 37.839 -0.029 c
+37.839 0.676 l
+37.574 0.676 l
+37.339 0.676 37.152 0.625 37.016 0.53 c
+36.887 0.43 36.824 0.287 36.824 0.103 c
+36.824 -0.066 36.854 -0.187 36.913 -0.264 c
+36.979 -0.345 37.096 -0.382 37.266 -0.382 c
+39.702 -0.029 m
+40.275 2.219 l
+40.775 2.219 l
+39.878 -0.764 l
+39.526 -0.764 l
+38.629 2.219 l
+39.114 2.219 l
+h
+42.146 -0.823 m
+41.771 -0.823 41.488 -0.717 41.293 -0.5 c
+41.094 -0.276 40.999 0.052 40.999 0.485 c
+40.999 0.852 l
+40.999 1.294 41.091 1.639 41.279 1.897 c
+41.473 2.15 41.749 2.278 42.102 2.278 c
+42.443 2.278 42.697 2.165 42.866 1.941 c
+43.043 1.712 43.134 1.367 43.145 0.897 c
+43.145 0.588 l
+41.485 0.588 l
+41.485 0.515 l
+41.485 0.191 41.543 -0.044 41.661 -0.191 c
+41.778 -0.33 41.948 -0.397 42.175 -0.397 c
+42.322 -0.397 42.447 -0.374 42.557 -0.324 c
+42.664 -0.264 42.767 -0.176 42.866 -0.058 c
+43.116 -0.368 l
+42.91 -0.673 42.586 -0.823 42.146 -0.823 c
+42.102 1.852 m
+41.896 1.852 41.742 1.783 41.646 1.646 c
+41.547 1.507 41.491 1.294 41.485 1 c
+42.661 1 l
+42.661 1.073 l
+42.638 1.345 42.586 1.544 42.499 1.661 c
+42.41 1.786 42.278 1.852 42.102 1.852 c
+46.287 -0.764 m
+46.258 -0.698 46.235 -0.588 46.228 -0.441 c
+46.052 -0.698 45.832 -0.823 45.567 -0.823 c
+45.291 -0.823 45.075 -0.75 44.92 -0.603 c
+44.774 -0.448 44.7 -0.231 44.7 0.044 c
+44.7 0.345 44.803 0.588 45.009 0.765 c
+45.214 0.948 45.497 1.043 45.861 1.043 c
+46.214 1.043 l
+46.214 1.367 l
+46.214 1.544 46.173 1.665 46.096 1.735 c
+46.015 1.812 45.898 1.852 45.743 1.852 c
+45.597 1.852 45.472 1.808 45.376 1.72 c
+45.287 1.631 45.244 1.521 45.244 1.396 c
+44.758 1.396 l
+44.758 1.544 44.803 1.683 44.891 1.823 c
+44.979 1.97 45.096 2.08 45.244 2.161 c
+45.398 2.238 45.57 2.278 45.758 2.278 c
+46.071 2.278 46.306 2.198 46.463 2.043 c
+46.618 1.897 46.698 1.675 46.698 1.382 c
+46.698 -0.118 l
+46.706 -0.353 46.743 -0.555 46.802 -0.721 c
+46.802 -0.764 l
+h
+45.641 -0.382 m
+45.758 -0.382 45.869 -0.349 45.979 -0.279 c
+46.085 -0.213 46.162 -0.129 46.214 -0.029 c
+46.214 0.676 l
+45.949 0.676 l
+45.714 0.676 45.526 0.625 45.391 0.53 c
+45.262 0.43 45.2 0.287 45.2 0.103 c
+45.2 -0.066 45.229 -0.187 45.287 -0.264 c
+45.354 -0.345 45.472 -0.382 45.641 -0.382 c
+48.72 0 m
+48.72 0.106 48.68 0.195 48.602 0.264 c
+48.521 0.341 48.371 0.43 48.147 0.53 c
+47.882 0.636 47.695 0.728 47.588 0.808 c
+47.478 0.886 47.401 0.974 47.353 1.073 c
+47.301 1.168 47.28 1.286 47.28 1.426 c
+47.28 1.669 47.367 1.87 47.544 2.028 c
+47.72 2.194 47.945 2.278 48.22 2.278 c
+48.514 2.278 48.749 2.19 48.926 2.014 c
+49.102 1.845 49.19 1.631 49.19 1.367 c
+48.705 1.367 l
+48.705 1.503 48.654 1.617 48.558 1.706 c
+48.47 1.801 48.356 1.852 48.22 1.852 c
+48.073 1.852 47.959 1.812 47.882 1.735 c
+47.801 1.665 47.764 1.565 47.764 1.44 c
+47.764 1.341 47.794 1.264 47.853 1.205 c
+47.912 1.147 48.051 1.066 48.279 0.97 c
+48.639 0.823 48.886 0.68 49.013 0.544 c
+49.15 0.416 49.219 0.243 49.219 0.029 c
+49.219 -0.228 49.124 -0.434 48.94 -0.588 c
+48.764 -0.746 48.529 -0.823 48.235 -0.823 c
+47.918 -0.823 47.665 -0.735 47.471 -0.559 c
+47.284 -0.374 47.191 -0.143 47.191 0.133 c
+47.677 0.133 l
+47.683 -0.037 47.735 -0.169 47.823 -0.264 c
+47.918 -0.353 48.059 -0.397 48.235 -0.397 c
+48.389 -0.397 48.506 -0.364 48.587 -0.294 c
+48.676 -0.228 48.72 -0.129 48.72 0 c
+51.336 2.219 m
+51.351 1.941 l
+51.527 2.165 51.766 2.278 52.071 2.278 c
+52.402 2.278 52.633 2.132 52.762 1.837 c
+52.946 2.132 53.206 2.278 53.541 2.278 c
+54.1 2.278 54.382 1.933 54.394 1.249 c
+54.394 -0.764 l
+53.909 -0.764 l
+53.909 1.205 l
+53.909 1.419 53.869 1.577 53.792 1.675 c
+53.711 1.783 53.578 1.837 53.394 1.837 c
+53.247 1.837 53.129 1.779 53.042 1.661 c
+52.953 1.551 52.898 1.411 52.88 1.235 c
+52.88 -0.764 l
+52.394 -0.764 l
+52.394 1.22 l
+52.383 1.631 52.211 1.837 51.88 1.837 c
+51.634 1.837 51.461 1.712 51.365 1.47 c
+51.365 -0.764 l
+50.881 -0.764 l
+50.881 2.219 l
+h
+56.371 -0.764 m
+56.341 -0.698 56.319 -0.588 56.312 -0.441 c
+56.136 -0.698 55.915 -0.823 55.65 -0.823 c
+55.375 -0.823 55.158 -0.75 55.004 -0.603 c
+54.856 -0.448 54.783 -0.231 54.783 0.044 c
+54.783 0.345 54.887 0.588 55.092 0.765 c
+55.298 0.948 55.581 1.043 55.945 1.043 c
+56.298 1.043 l
+56.298 1.367 l
+56.298 1.544 56.257 1.665 56.18 1.735 c
+56.099 1.812 55.982 1.852 55.827 1.852 c
+55.68 1.852 55.555 1.808 55.459 1.72 c
+55.371 1.631 55.327 1.521 55.327 1.396 c
+54.842 1.396 l
+54.842 1.544 54.887 1.683 54.974 1.823 c
+55.062 1.97 55.18 2.08 55.327 2.161 c
+55.481 2.238 55.654 2.278 55.841 2.278 c
+56.154 2.278 56.389 2.198 56.547 2.043 c
+56.701 1.897 56.782 1.675 56.782 1.382 c
+56.782 -0.118 l
+56.79 -0.353 56.826 -0.555 56.886 -0.721 c
+56.886 -0.764 l
+h
+55.724 -0.382 m
+55.841 -0.382 55.951 -0.349 56.062 -0.279 c
+56.169 -0.213 56.246 -0.129 56.298 -0.029 c
+56.298 0.676 l
+56.032 0.676 l
+55.797 0.676 55.61 0.625 55.474 0.53 c
+55.346 0.43 55.284 0.287 55.284 0.103 c
+55.284 -0.066 55.313 -0.187 55.371 -0.264 c
+55.438 -0.345 55.555 -0.382 55.724 -0.382 c
+57.819 2.219 m
+57.833 1.897 l
+58.017 2.15 58.26 2.278 58.554 2.278 c
+59.083 2.278 59.351 1.926 59.362 1.22 c
+59.362 -0.764 l
+58.877 -0.764 l
+58.877 1.191 l
+58.877 1.426 58.837 1.592 58.76 1.691 c
+58.679 1.786 58.561 1.837 58.407 1.837 c
+58.289 1.837 58.179 1.797 58.083 1.72 c
+57.984 1.639 57.907 1.532 57.848 1.396 c
+57.848 -0.764 l
+57.363 -0.764 l
+57.363 2.219 l
+h
+60.726 0.044 m
+61.269 2.219 l
+61.784 2.219 l
+60.813 -1.191 l
+60.744 -1.444 60.641 -1.635 60.505 -1.764 c
+60.365 -1.899 60.215 -1.97 60.049 -1.97 c
+59.98 -1.97 59.895 -1.955 59.799 -1.926 c
+59.799 -1.514 l
+59.903 -1.529 l
+60.038 -1.529 60.144 -1.492 60.225 -1.426 c
+60.314 -1.356 60.379 -1.238 60.431 -1.073 c
+60.52 -0.735 l
+59.652 2.219 l
+60.182 2.219 l
+h
+f
+Q
+ endstream endobj 51 0 obj <</BBox[623.858 230.42 661.638 225.011]/Group 87 0 R/Length 8912/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 624.3423 228.8612 cm
+0 0 m
+0.184 0.243 0.42 0.368 0.706 0.368 c
+1.235 0.368 1.503 0.015 1.515 -0.691 c
+1.515 -2.675 l
+1.029 -2.675 l
+1.029 -0.72 l
+1.029 -0.484 0.989 -0.319 0.912 -0.22 c
+0.831 -0.124 0.713 -0.073 0.559 -0.073 c
+0.441 -0.073 0.331 -0.114 0.235 -0.191 c
+0.136 -0.272 0.059 -0.378 0 -0.514 c
+0 -2.675 l
+-0.484 -2.675 l
+-0.484 1.559 l
+0 1.559 l
+h
+3.583 -2.675 m
+3.554 -2.609 3.532 -2.499 3.525 -2.352 c
+3.348 -2.609 3.128 -2.734 2.863 -2.734 c
+2.587 -2.734 2.371 -2.66 2.216 -2.513 c
+2.07 -2.358 1.996 -2.142 1.996 -1.866 c
+1.996 -1.565 2.099 -1.323 2.305 -1.146 c
+2.51 -0.962 2.793 -0.866 3.157 -0.866 c
+3.51 -0.866 l
+3.51 -0.544 l
+3.51 -0.367 3.47 -0.246 3.392 -0.176 c
+3.311 -0.099 3.194 -0.058 3.04 -0.058 c
+2.893 -0.058 2.768 -0.103 2.672 -0.191 c
+2.584 -0.278 2.54 -0.389 2.54 -0.514 c
+2.055 -0.514 l
+2.055 -0.367 2.099 -0.228 2.187 -0.087 c
+2.275 0.059 2.392 0.169 2.54 0.25 c
+2.694 0.327 2.866 0.368 3.055 0.368 c
+3.367 0.368 3.602 0.287 3.76 0.133 c
+3.914 -0.014 3.995 -0.235 3.995 -0.529 c
+3.995 -2.028 l
+4.002 -2.263 4.039 -2.466 4.098 -2.63 c
+4.098 -2.675 l
+h
+2.937 -2.293 m
+3.055 -2.293 3.165 -2.26 3.275 -2.19 c
+3.381 -2.123 3.458 -2.04 3.51 -1.94 c
+3.51 -1.234 l
+3.246 -1.234 l
+3.01 -1.234 2.822 -1.286 2.687 -1.381 c
+2.558 -1.481 2.496 -1.624 2.496 -1.807 c
+2.496 -1.977 2.525 -2.098 2.584 -2.175 c
+2.65 -2.256 2.768 -2.293 2.937 -2.293 c
+5.604 -2.308 m
+5.77 -2.308 5.902 -2.26 6.001 -2.16 c
+6.097 -2.065 6.152 -1.922 6.163 -1.734 c
+6.619 -1.734 l
+6.608 -2.021 6.505 -2.26 6.31 -2.454 c
+6.122 -2.642 5.887 -2.734 5.604 -2.734 c
+5.241 -2.734 4.962 -2.616 4.767 -2.381 c
+4.568 -2.146 4.472 -1.801 4.472 -1.337 c
+4.472 -1.014 l
+4.472 -0.565 4.564 -0.22 4.752 0.015 c
+4.946 0.25 5.23 0.368 5.604 0.368 c
+5.906 0.368 6.149 0.269 6.325 0.074 c
+6.508 -0.124 6.608 -0.389 6.619 -0.72 c
+6.163 -0.72 l
+6.141 -0.496 6.082 -0.33 5.987 -0.22 c
+5.898 -0.114 5.77 -0.058 5.604 -0.058 c
+5.388 -0.058 5.226 -0.132 5.12 -0.278 c
+5.02 -0.419 4.965 -0.646 4.958 -0.97 c
+4.958 -1.352 l
+4.958 -1.705 5.006 -1.955 5.104 -2.102 c
+5.212 -2.241 5.376 -2.308 5.604 -2.308 c
+7.765 -1.308 m
+7.501 -1.602 l
+7.501 -2.675 l
+7.015 -2.675 l
+7.015 1.559 l
+7.501 1.559 l
+7.501 -0.97 l
+8.426 0.309 l
+9.015 0.309 l
+8.074 -0.941 l
+9.147 -2.675 l
+8.574 -2.675 l
+h
+9.922 -2.675 -0.5 2.984 re
+9.952 1.103 m
+9.952 1.015 9.926 0.941 9.878 0.882 c
+9.837 0.831 9.768 0.809 9.673 0.809 c
+9.584 0.809 9.515 0.831 9.467 0.882 c
+9.426 0.941 9.407 1.008 9.407 1.088 c
+9.407 1.176 9.426 1.25 9.467 1.309 c
+9.515 1.368 9.584 1.397 9.673 1.397 c
+9.768 1.397 9.837 1.368 9.878 1.309 c
+9.926 1.25 9.952 1.18 9.952 1.103 c
+11.051 0.309 m
+11.065 -0.014 l
+11.248 0.239 11.491 0.368 11.786 0.368 c
+12.314 0.368 12.582 0.015 12.594 -0.691 c
+12.594 -2.675 l
+12.109 -2.675 l
+12.109 -0.72 l
+12.109 -0.484 12.069 -0.319 11.992 -0.22 c
+11.911 -0.124 11.793 -0.073 11.639 -0.073 c
+11.521 -0.073 11.41 -0.114 11.315 -0.191 c
+11.216 -0.272 11.138 -0.378 11.08 -0.514 c
+11.08 -2.675 l
+10.595 -2.675 l
+10.595 0.309 l
+h
+13.046 -1.043 m
+13.046 -0.584 13.127 -0.235 13.295 0 c
+13.472 0.243 13.722 0.368 14.045 0.368 c
+14.346 0.368 14.579 0.235 14.737 -0.029 c
+14.766 0.309 l
+15.207 0.309 l
+15.207 -2.705 l
+15.207 -3.075 15.107 -3.358 14.913 -3.557 c
+14.725 -3.752 14.464 -3.85 14.134 -3.85 c
+13.987 -3.85 13.818 -3.81 13.634 -3.733 c
+13.446 -3.663 13.311 -3.575 13.222 -3.469 c
+13.413 -3.131 l
+13.619 -3.336 13.843 -3.439 14.089 -3.439 c
+14.49 -3.439 14.696 -3.212 14.707 -2.763 c
+14.707 -2.381 l
+14.549 -2.616 14.328 -2.734 14.045 -2.734 c
+13.729 -2.734 13.486 -2.616 13.311 -2.381 c
+13.141 -2.146 13.053 -1.815 13.046 -1.381 c
+h
+13.531 -1.323 m
+13.531 -1.657 13.579 -1.903 13.678 -2.057 c
+13.773 -2.215 13.935 -2.293 14.163 -2.293 c
+14.406 -2.293 14.589 -2.171 14.707 -1.925 c
+14.707 -0.44 l
+14.589 -0.198 14.413 -0.073 14.178 -0.073 c
+13.95 -0.073 13.788 -0.154 13.693 -0.309 c
+13.594 -0.467 13.538 -0.706 13.531 -1.028 c
+h
+18.18 -0.147 m
+18.109 -0.139 18.036 -0.132 17.959 -0.132 c
+17.702 -0.132 17.525 -0.272 17.43 -0.544 c
+17.43 -2.675 l
+16.945 -2.675 l
+16.945 0.309 l
+17.415 0.309 l
+17.43 0 l
+17.555 0.243 17.739 0.368 17.974 0.368 c
+18.051 0.368 18.113 0.353 18.165 0.324 c
+h
+19.08 -2.675 -0.5 2.984 re
+19.109 1.103 m
+19.109 1.015 19.084 0.941 19.036 0.882 c
+18.995 0.831 18.926 0.809 18.83 0.809 c
+18.741 0.809 18.672 0.831 18.624 0.882 c
+18.583 0.941 18.566 1.008 18.566 1.088 c
+18.566 1.176 18.583 1.25 18.624 1.309 c
+18.672 1.368 18.741 1.397 18.83 1.397 c
+18.926 1.397 18.995 1.368 19.036 1.309 c
+19.084 1.25 19.109 1.18 19.109 1.103 c
+19.649 -1.043 m
+19.649 -0.584 19.73 -0.235 19.899 0 c
+20.075 0.243 20.326 0.368 20.649 0.368 c
+20.95 0.368 21.182 0.235 21.34 -0.029 c
+21.369 0.309 l
+21.81 0.309 l
+21.81 -2.705 l
+21.81 -3.075 21.711 -3.358 21.517 -3.557 c
+21.328 -3.752 21.068 -3.85 20.737 -3.85 c
+20.59 -3.85 20.421 -3.81 20.237 -3.733 c
+20.05 -3.663 19.914 -3.575 19.826 -3.469 c
+20.017 -3.131 l
+20.223 -3.336 20.447 -3.439 20.693 -3.439 c
+21.093 -3.439 21.299 -3.212 21.311 -2.763 c
+21.311 -2.381 l
+21.153 -2.616 20.931 -2.734 20.649 -2.734 c
+20.333 -2.734 20.09 -2.616 19.914 -2.381 c
+19.745 -2.146 19.657 -1.815 19.649 -1.381 c
+h
+20.135 -1.323 m
+20.135 -1.657 20.183 -1.903 20.281 -2.057 c
+20.377 -2.215 20.539 -2.293 20.767 -2.293 c
+21.01 -2.293 21.193 -2.171 21.311 -1.925 c
+21.311 -0.44 l
+21.193 -0.198 21.016 -0.073 20.781 -0.073 c
+20.553 -0.073 20.392 -0.154 20.297 -0.309 c
+20.197 -0.467 20.142 -0.706 20.135 -1.028 c
+h
+22.832 0 m
+23.015 0.243 23.25 0.368 23.537 0.368 c
+24.067 0.368 24.335 0.015 24.345 -0.691 c
+24.345 -2.675 l
+23.861 -2.675 l
+23.861 -0.72 l
+23.861 -0.484 23.82 -0.319 23.743 -0.22 c
+23.662 -0.124 23.545 -0.073 23.391 -0.073 c
+23.273 -0.073 23.163 -0.114 23.067 -0.191 c
+22.968 -0.272 22.891 -0.378 22.832 -0.514 c
+22.832 -2.675 l
+22.346 -2.675 l
+22.346 1.559 l
+22.832 1.559 l
+h
+25.521 1.029 m
+25.521 0.309 l
+25.978 0.309 l
+25.978 -0.087 l
+25.521 -0.087 l
+25.521 -1.94 l
+25.521 -2.057 25.54 -2.146 25.581 -2.204 c
+25.617 -2.263 25.687 -2.293 25.787 -2.293 c
+25.845 -2.293 25.908 -2.285 25.978 -2.263 c
+25.978 -2.675 l
+25.86 -2.711 25.746 -2.734 25.639 -2.734 c
+25.44 -2.734 25.29 -2.667 25.184 -2.528 c
+25.085 -2.392 25.037 -2.197 25.037 -1.94 c
+25.037 -0.087 l
+24.581 -0.087 l
+24.581 0.309 l
+25.037 0.309 l
+25.037 1.029 l
+h
+28.131 0 m
+28.314 0.243 28.55 0.368 28.837 0.368 c
+29.365 0.368 29.633 0.015 29.645 -0.691 c
+29.645 -2.675 l
+29.16 -2.675 l
+29.16 -0.72 l
+29.16 -0.484 29.12 -0.319 29.043 -0.22 c
+28.962 -0.124 28.844 -0.073 28.69 -0.073 c
+28.572 -0.073 28.461 -0.114 28.366 -0.191 c
+28.266 -0.272 28.189 -0.378 28.131 -0.514 c
+28.131 -2.675 l
+27.646 -2.675 l
+27.646 1.559 l
+28.131 1.559 l
+h
+31.247 -2.734 m
+30.872 -2.734 30.589 -2.627 30.394 -2.41 c
+30.196 -2.186 30.101 -1.859 30.101 -1.425 c
+30.101 -1.058 l
+30.101 -0.617 30.192 -0.272 30.379 -0.014 c
+30.574 0.239 30.85 0.368 31.203 0.368 c
+31.545 0.368 31.798 0.254 31.967 0.03 c
+32.143 -0.198 32.235 -0.544 32.247 -1.014 c
+32.247 -1.323 l
+30.585 -1.323 l
+30.585 -1.396 l
+30.585 -1.72 30.645 -1.955 30.762 -2.102 c
+30.88 -2.241 31.048 -2.308 31.277 -2.308 c
+31.424 -2.308 31.549 -2.285 31.659 -2.234 c
+31.765 -2.175 31.868 -2.087 31.967 -1.969 c
+32.218 -2.278 l
+32.012 -2.583 31.688 -2.734 31.247 -2.734 c
+31.203 -0.058 m
+30.997 -0.058 30.843 -0.128 30.747 -0.264 c
+30.648 -0.404 30.593 -0.617 30.585 -0.911 c
+31.761 -0.911 l
+31.761 -0.837 l
+31.74 -0.565 31.688 -0.367 31.599 -0.249 c
+31.512 -0.124 31.379 -0.058 31.203 -0.058 c
+33.893 -0.147 m
+33.823 -0.139 33.749 -0.132 33.672 -0.132 c
+33.415 -0.132 33.239 -0.272 33.143 -0.544 c
+33.143 -2.675 l
+32.658 -2.675 l
+32.658 0.309 l
+33.128 0.309 l
+33.143 0 l
+33.268 0.243 33.452 0.368 33.687 0.368 c
+33.764 0.368 33.826 0.353 33.878 0.324 c
+h
+35.267 -2.734 m
+34.892 -2.734 34.61 -2.627 34.415 -2.41 c
+34.217 -2.186 34.121 -1.859 34.121 -1.425 c
+34.121 -1.058 l
+34.121 -0.617 34.213 -0.272 34.4 -0.014 c
+34.595 0.239 34.87 0.368 35.223 0.368 c
+35.565 0.368 35.819 0.254 35.987 0.03 c
+36.164 -0.198 36.256 -0.544 36.266 -1.014 c
+36.266 -1.323 l
+34.606 -1.323 l
+34.606 -1.396 l
+34.606 -1.72 34.664 -1.955 34.782 -2.102 c
+34.9 -2.241 35.069 -2.308 35.297 -2.308 c
+35.443 -2.308 35.568 -2.285 35.679 -2.234 c
+35.786 -2.175 35.888 -2.087 35.987 -1.969 c
+36.237 -2.278 l
+36.031 -2.583 35.708 -2.734 35.267 -2.734 c
+35.223 -0.058 m
+35.017 -0.058 34.863 -0.128 34.767 -0.264 c
+34.668 -0.404 34.613 -0.617 34.606 -0.911 c
+35.782 -0.911 l
+35.782 -0.837 l
+35.759 -0.565 35.708 -0.367 35.62 -0.249 c
+35.532 -0.124 35.399 -0.058 35.223 -0.058 c
+37.222 -1.543 m
+36.781 -1.543 l
+36.752 1.338 l
+37.266 1.338 l
+h
+37.016 -2.131 m
+37.112 -2.131 37.182 -2.16 37.222 -2.219 c
+37.27 -2.271 37.296 -2.337 37.296 -2.425 c
+37.296 -2.506 37.27 -2.572 37.222 -2.63 c
+37.182 -2.678 37.112 -2.705 37.016 -2.705 c
+36.928 -2.705 36.858 -2.678 36.81 -2.63 c
+36.759 -2.572 36.737 -2.506 36.737 -2.425 c
+36.737 -2.337 36.759 -2.271 36.81 -2.219 c
+36.858 -2.16 36.928 -2.131 37.016 -2.131 c
+f
+Q
+ endstream endobj 52 0 obj <</BBox[699.591 449.925 766.733 444.647]/Group 88 0 R/Length 17061/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 700.8254 448.3809 cm
+0 0 m
+-0.07 0.008 -0.143 0.015 -0.22 0.015 c
+-0.478 0.015 -0.654 -0.125 -0.75 -0.397 c
+-0.75 -2.528 l
+-1.234 -2.528 l
+-1.234 0.455 l
+-0.764 0.455 l
+-0.75 0.147 l
+-0.625 0.389 -0.44 0.515 -0.205 0.515 c
+-0.128 0.515 -0.066 0.5 -0.014 0.47 c
+h
+1.378 -2.587 m
+1.004 -2.587 0.721 -2.481 0.526 -2.263 c
+0.327 -2.04 0.231 -1.712 0.231 -1.278 c
+0.231 -0.912 l
+0.231 -0.47 0.324 -0.125 0.511 0.133 c
+0.706 0.386 0.981 0.515 1.334 0.515 c
+1.676 0.515 1.929 0.401 2.099 0.177 c
+2.275 -0.052 2.367 -0.397 2.378 -0.867 c
+2.378 -1.176 l
+0.717 -1.176 l
+0.717 -1.249 l
+0.717 -1.573 0.775 -1.808 0.893 -1.955 c
+1.01 -2.094 1.18 -2.161 1.407 -2.161 c
+1.555 -2.161 1.679 -2.138 1.79 -2.088 c
+1.897 -2.028 1.999 -1.94 2.099 -1.822 c
+2.348 -2.132 l
+2.143 -2.437 1.819 -2.587 1.378 -2.587 c
+1.334 0.088 m
+1.128 0.088 0.974 0.019 0.879 -0.118 c
+0.779 -0.257 0.724 -0.47 0.717 -0.764 c
+1.893 -0.764 l
+1.893 -0.691 l
+1.871 -0.419 1.819 -0.22 1.731 -0.103 c
+1.643 0.023 1.511 0.088 1.334 0.088 c
+3.245 0.455 m
+3.26 0.177 l
+3.437 0.401 3.675 0.515 3.98 0.515 c
+4.31 0.515 4.542 0.368 4.671 0.073 c
+4.854 0.368 5.116 0.515 5.45 0.515 c
+6.009 0.515 6.292 0.169 6.302 -0.515 c
+6.302 -2.528 l
+5.818 -2.528 l
+5.818 -0.559 l
+5.818 -0.345 5.777 -0.187 5.7 -0.088 c
+5.619 0.019 5.486 0.073 5.303 0.073 c
+5.156 0.073 5.039 0.015 4.95 -0.103 c
+4.862 -0.213 4.807 -0.353 4.788 -0.529 c
+4.788 -2.528 l
+4.303 -2.528 l
+4.303 -0.544 l
+4.293 -0.133 4.119 0.073 3.789 0.073 c
+3.543 0.073 3.37 -0.052 3.275 -0.294 c
+3.275 -2.528 l
+2.789 -2.528 l
+2.789 0.455 l
+h
+6.648 -0.897 m
+6.648 -0.467 6.751 -0.125 6.957 0.133 c
+7.169 0.386 7.449 0.515 7.794 0.515 c
+8.136 0.515 8.412 0.386 8.617 0.133 c
+8.831 -0.114 8.945 -0.448 8.956 -0.867 c
+8.956 -1.176 l
+8.956 -1.61 8.846 -1.951 8.632 -2.205 c
+8.426 -2.462 8.147 -2.587 7.794 -2.587 c
+7.449 -2.587 7.177 -2.466 6.971 -2.219 c
+6.766 -1.977 6.655 -1.643 6.648 -1.22 c
+h
+7.133 -1.176 m
+7.133 -1.492 7.192 -1.735 7.31 -1.911 c
+7.435 -2.08 7.596 -2.161 7.794 -2.161 c
+8.224 -2.161 8.449 -1.852 8.47 -1.234 c
+8.47 -0.897 l
+8.47 -0.596 8.405 -0.353 8.279 -0.176 c
+8.162 0 8 0.088 7.794 0.088 c
+7.596 0.088 7.435 0 7.31 -0.176 c
+7.192 -0.353 7.133 -0.596 7.133 -0.897 c
+h
+10.028 1.176 m
+10.028 0.455 l
+10.485 0.455 l
+10.485 0.059 l
+10.028 0.059 l
+10.028 -1.793 l
+10.028 -1.911 10.047 -1.999 10.088 -2.057 c
+10.124 -2.117 10.194 -2.146 10.294 -2.146 c
+10.352 -2.146 10.415 -2.138 10.485 -2.117 c
+10.485 -2.528 l
+10.367 -2.564 10.253 -2.587 10.146 -2.587 c
+9.947 -2.587 9.797 -2.521 9.691 -2.381 c
+9.592 -2.246 9.544 -2.051 9.544 -1.793 c
+9.544 0.059 l
+9.088 0.059 l
+9.088 0.455 l
+9.544 0.455 l
+9.544 1.176 l
+h
+12.009 -2.587 m
+11.634 -2.587 11.352 -2.481 11.157 -2.263 c
+10.959 -2.04 10.863 -1.712 10.863 -1.278 c
+10.863 -0.912 l
+10.863 -0.47 10.955 -0.125 11.142 0.133 c
+11.337 0.386 11.612 0.515 11.965 0.515 c
+12.307 0.515 12.561 0.401 12.73 0.177 c
+12.906 -0.052 12.998 -0.397 13.009 -0.867 c
+13.009 -1.176 l
+11.348 -1.176 l
+11.348 -1.249 l
+11.348 -1.573 11.406 -1.808 11.524 -1.955 c
+11.642 -2.094 11.811 -2.161 12.039 -2.161 c
+12.185 -2.161 12.311 -2.138 12.421 -2.088 c
+12.528 -2.028 12.63 -1.94 12.73 -1.822 c
+12.979 -2.132 l
+12.773 -2.437 12.451 -2.587 12.009 -2.587 c
+11.965 0.088 m
+11.759 0.088 11.605 0.019 11.51 -0.118 c
+11.41 -0.257 11.356 -0.47 11.348 -0.764 c
+12.524 -0.764 l
+12.524 -0.691 l
+12.501 -0.419 12.451 -0.22 12.362 -0.103 c
+12.274 0.023 12.141 0.088 11.965 0.088 c
+15.857 0 m
+15.787 0.008 15.713 0.015 15.636 0.015 c
+15.379 0.015 15.202 -0.125 15.107 -0.397 c
+15.107 -2.528 l
+14.622 -2.528 l
+14.622 0.455 l
+15.092 0.455 l
+15.107 0.147 l
+15.232 0.389 15.416 0.515 15.651 0.515 c
+15.728 0.515 15.79 0.5 15.842 0.47 c
+h
+17.235 -2.587 m
+16.86 -2.587 16.577 -2.481 16.382 -2.263 c
+16.184 -2.04 16.089 -1.712 16.089 -1.278 c
+16.089 -0.912 l
+16.089 -0.47 16.18 -0.125 16.368 0.133 c
+16.563 0.386 16.838 0.515 17.191 0.515 c
+17.533 0.515 17.786 0.401 17.955 0.177 c
+18.132 -0.052 18.223 -0.397 18.234 -0.867 c
+18.234 -1.176 l
+16.573 -1.176 l
+16.573 -1.249 l
+16.573 -1.573 16.632 -1.808 16.75 -1.955 c
+16.867 -2.094 17.037 -2.161 17.264 -2.161 c
+17.411 -2.161 17.536 -2.138 17.646 -2.088 c
+17.753 -2.028 17.856 -1.94 17.955 -1.822 c
+18.205 -2.132 l
+17.999 -2.437 17.676 -2.587 17.235 -2.587 c
+17.191 0.088 m
+16.985 0.088 16.831 0.019 16.735 -0.118 c
+16.636 -0.257 16.581 -0.47 16.573 -0.764 c
+17.749 -0.764 l
+17.749 -0.691 l
+17.727 -0.419 17.676 -0.22 17.588 -0.103 c
+17.5 0.023 17.367 0.088 17.191 0.088 c
+20.792 -1.176 m
+20.792 -1.646 20.708 -1.999 20.542 -2.234 c
+20.373 -2.469 20.135 -2.587 19.822 -2.587 c
+19.517 -2.587 19.285 -2.477 19.131 -2.249 c
+19.131 -3.675 l
+18.646 -3.675 l
+18.646 0.455 l
+19.087 0.455 l
+19.117 0.118 l
+19.271 0.382 19.503 0.515 19.807 0.515 c
+20.137 0.515 20.384 0.397 20.542 0.162 c
+20.708 -0.066 20.792 -0.405 20.792 -0.852 c
+h
+20.307 -0.897 m
+20.307 -0.565 20.252 -0.32 20.145 -0.162 c
+20.046 -0.008 19.884 0.073 19.661 0.073 c
+19.425 0.073 19.248 -0.044 19.131 -0.279 c
+19.131 -1.822 l
+19.248 -2.051 19.429 -2.161 19.675 -2.161 c
+19.888 -2.161 20.046 -2.084 20.145 -1.926 c
+20.252 -1.771 20.307 -1.529 20.307 -1.205 c
+h
+21.145 -0.897 m
+21.145 -0.467 21.248 -0.125 21.454 0.133 c
+21.667 0.386 21.946 0.515 22.292 0.515 c
+22.633 0.515 22.909 0.386 23.115 0.133 c
+23.328 -0.114 23.441 -0.448 23.453 -0.867 c
+23.453 -1.176 l
+23.453 -1.61 23.343 -1.951 23.129 -2.205 c
+22.923 -2.462 22.645 -2.587 22.292 -2.587 c
+21.946 -2.587 21.674 -2.466 21.469 -2.219 c
+21.263 -1.977 21.153 -1.643 21.145 -1.22 c
+h
+21.63 -1.176 m
+21.63 -1.492 21.689 -1.735 21.806 -1.911 c
+21.931 -2.08 22.093 -2.161 22.292 -2.161 c
+22.722 -2.161 22.946 -1.852 22.967 -1.234 c
+22.967 -0.897 l
+22.967 -0.596 22.901 -0.353 22.776 -0.176 c
+22.659 0 22.497 0.088 22.292 0.088 c
+22.093 0.088 21.931 0 21.806 -0.176 c
+21.689 -0.353 21.63 -0.596 21.63 -0.897 c
+h
+25.334 -1.764 m
+25.334 -1.658 25.294 -1.569 25.216 -1.5 c
+25.136 -1.422 24.985 -1.334 24.761 -1.234 c
+24.496 -1.128 24.309 -1.036 24.202 -0.956 c
+24.092 -0.878 24.015 -0.79 23.967 -0.691 c
+23.915 -0.596 23.894 -0.478 23.894 -0.338 c
+23.894 -0.095 23.981 0.106 24.158 0.264 c
+24.334 0.43 24.559 0.515 24.835 0.515 c
+25.128 0.515 25.363 0.426 25.54 0.25 c
+25.716 0.081 25.805 -0.133 25.805 -0.397 c
+25.319 -0.397 l
+25.319 -0.261 25.268 -0.147 25.172 -0.058 c
+25.084 0.037 24.97 0.088 24.835 0.088 c
+24.687 0.088 24.573 0.048 24.496 -0.029 c
+24.415 -0.099 24.378 -0.198 24.378 -0.324 c
+24.378 -0.422 24.408 -0.5 24.467 -0.559 c
+24.526 -0.617 24.665 -0.698 24.893 -0.794 c
+25.253 -0.941 25.5 -1.084 25.628 -1.22 c
+25.764 -1.348 25.834 -1.521 25.834 -1.735 c
+25.834 -1.992 25.739 -2.198 25.554 -2.352 c
+25.378 -2.51 25.143 -2.587 24.849 -2.587 c
+24.533 -2.587 24.28 -2.499 24.085 -2.323 c
+23.898 -2.138 23.805 -1.907 23.805 -1.631 c
+24.291 -1.631 l
+24.297 -1.801 24.349 -1.933 24.438 -2.028 c
+24.533 -2.117 24.673 -2.161 24.849 -2.161 c
+25.003 -2.161 25.121 -2.128 25.201 -2.057 c
+25.29 -1.992 25.334 -1.893 25.334 -1.764 c
+26.819 -2.528 -0.5 2.983 re
+26.848 1.249 m
+26.848 1.161 26.822 1.087 26.774 1.029 c
+26.734 0.977 26.664 0.956 26.568 0.956 c
+26.481 0.956 26.41 0.977 26.363 1.029 c
+26.323 1.087 26.304 1.154 26.304 1.235 c
+26.304 1.323 26.323 1.396 26.363 1.455 c
+26.41 1.514 26.481 1.544 26.568 1.544 c
+26.664 1.544 26.734 1.514 26.774 1.455 c
+26.822 1.396 26.848 1.326 26.848 1.249 c
+28.127 1.176 m
+28.127 0.455 l
+28.582 0.455 l
+28.582 0.059 l
+28.127 0.059 l
+28.127 -1.793 l
+28.127 -1.911 28.145 -1.999 28.185 -2.057 c
+28.222 -2.117 28.292 -2.146 28.392 -2.146 c
+28.45 -2.146 28.513 -2.138 28.582 -2.117 c
+28.582 -2.528 l
+28.465 -2.564 28.351 -2.587 28.245 -2.587 c
+28.046 -2.587 27.896 -2.521 27.789 -2.381 c
+27.69 -2.246 27.642 -2.051 27.642 -1.793 c
+27.642 0.059 l
+27.186 0.059 l
+27.186 0.455 l
+27.642 0.455 l
+27.642 1.176 l
+h
+28.895 -0.897 m
+28.895 -0.467 28.997 -0.125 29.203 0.133 c
+29.417 0.386 29.696 0.515 30.042 0.515 c
+30.383 0.515 30.659 0.386 30.865 0.133 c
+31.077 -0.114 31.191 -0.448 31.202 -0.867 c
+31.202 -1.176 l
+31.202 -1.61 31.092 -1.951 30.879 -2.205 c
+30.674 -2.462 30.394 -2.587 30.042 -2.587 c
+29.696 -2.587 29.424 -2.466 29.218 -2.219 c
+29.012 -1.977 28.902 -1.643 28.895 -1.22 c
+h
+29.38 -1.176 m
+29.38 -1.492 29.439 -1.735 29.556 -1.911 c
+29.681 -2.08 29.843 -2.161 30.042 -2.161 c
+30.471 -2.161 30.695 -1.852 30.718 -1.234 c
+30.718 -0.897 l
+30.718 -0.596 30.651 -0.353 30.526 -0.176 c
+30.408 0 30.248 0.088 30.042 0.088 c
+29.843 0.088 29.681 0 29.556 -0.176 c
+29.439 -0.353 29.38 -0.596 29.38 -0.897 c
+h
+32.875 0 m
+32.805 0.008 32.731 0.015 32.654 0.015 c
+32.397 0.015 32.22 -0.125 32.125 -0.397 c
+32.125 -2.528 l
+31.64 -2.528 l
+31.64 0.455 l
+32.11 0.455 l
+32.125 0.147 l
+32.25 0.389 32.434 0.515 32.669 0.515 c
+32.746 0.515 32.808 0.5 32.86 0.47 c
+h
+33.775 -2.528 -0.501 2.983 re
+33.805 1.249 m
+33.805 1.161 33.778 1.087 33.731 1.029 c
+33.691 0.977 33.621 0.956 33.525 0.956 c
+33.437 0.956 33.367 0.977 33.319 1.029 c
+33.279 1.087 33.261 1.154 33.261 1.235 c
+33.261 1.323 33.279 1.396 33.319 1.455 c
+33.367 1.514 33.437 1.544 33.525 1.544 c
+33.621 1.544 33.691 1.514 33.731 1.455 c
+33.778 1.396 33.805 1.326 33.805 1.249 c
+35.509 -2.587 m
+35.135 -2.587 34.852 -2.481 34.657 -2.263 c
+34.458 -2.04 34.363 -1.712 34.363 -1.278 c
+34.363 -0.912 l
+34.363 -0.47 34.455 -0.125 34.642 0.133 c
+34.837 0.386 35.112 0.515 35.465 0.515 c
+35.807 0.515 36.06 0.401 36.23 0.177 c
+36.406 -0.052 36.498 -0.397 36.509 -0.867 c
+36.509 -1.176 l
+34.848 -1.176 l
+34.848 -1.249 l
+34.848 -1.573 34.907 -1.808 35.025 -1.955 c
+35.142 -2.094 35.311 -2.161 35.539 -2.161 c
+35.686 -2.161 35.811 -2.138 35.921 -2.088 c
+36.028 -2.028 36.13 -1.94 36.23 -1.822 c
+36.48 -2.132 l
+36.274 -2.437 35.95 -2.587 35.509 -2.587 c
+35.465 0.088 m
+35.26 0.088 35.106 0.019 35.01 -0.118 c
+34.911 -0.257 34.855 -0.47 34.848 -0.764 c
+36.024 -0.764 l
+36.024 -0.691 l
+36.002 -0.419 35.95 -0.22 35.862 -0.103 c
+35.774 0.023 35.642 0.088 35.465 0.088 c
+38.362 -1.764 m
+38.362 -1.658 38.321 -1.569 38.244 -1.5 c
+38.163 -1.422 38.012 -1.334 37.788 -1.234 c
+37.523 -1.128 37.336 -1.036 37.229 -0.956 c
+37.119 -0.878 37.042 -0.79 36.994 -0.691 c
+36.943 -0.596 36.92 -0.478 36.92 -0.338 c
+36.92 -0.095 37.009 0.106 37.186 0.264 c
+37.361 0.43 37.585 0.515 37.861 0.515 c
+38.155 0.515 38.391 0.426 38.567 0.25 c
+38.743 0.081 38.832 -0.133 38.832 -0.397 c
+38.346 -0.397 l
+38.346 -0.261 38.295 -0.147 38.2 -0.058 c
+38.111 0.037 37.997 0.088 37.861 0.088 c
+37.714 0.088 37.6 0.048 37.523 -0.029 c
+37.442 -0.099 37.406 -0.198 37.406 -0.324 c
+37.406 -0.422 37.435 -0.5 37.494 -0.559 c
+37.552 -0.617 37.693 -0.698 37.92 -0.794 c
+38.281 -0.941 38.526 -1.084 38.655 -1.22 c
+38.791 -1.348 38.861 -1.521 38.861 -1.735 c
+38.861 -1.992 38.765 -2.198 38.582 -2.352 c
+38.405 -2.51 38.17 -2.587 37.876 -2.587 c
+37.56 -2.587 37.306 -2.499 37.111 -2.323 c
+36.924 -2.138 36.833 -1.907 36.833 -1.631 c
+37.317 -1.631 l
+37.325 -1.801 37.377 -1.933 37.464 -2.028 c
+37.56 -2.117 37.699 -2.161 37.876 -2.161 c
+38.03 -2.161 38.148 -2.128 38.229 -2.057 c
+38.317 -1.992 38.362 -1.893 38.362 -1.764 c
+42.05 -2.528 m
+42.021 -2.462 41.999 -2.352 41.992 -2.205 c
+41.815 -2.462 41.595 -2.587 41.33 -2.587 c
+41.055 -2.587 40.837 -2.514 40.683 -2.367 c
+40.536 -2.212 40.463 -1.995 40.463 -1.72 c
+40.463 -1.419 40.566 -1.176 40.772 -0.999 c
+40.978 -0.816 41.261 -0.721 41.624 -0.721 c
+41.977 -0.721 l
+41.977 -0.397 l
+41.977 -0.22 41.936 -0.099 41.859 -0.029 c
+41.778 0.048 41.661 0.088 41.506 0.088 c
+41.36 0.088 41.234 0.044 41.139 -0.044 c
+41.051 -0.133 41.007 -0.243 41.007 -0.368 c
+40.521 -0.368 l
+40.521 -0.22 40.566 -0.081 40.654 0.059 c
+40.742 0.206 40.86 0.316 41.007 0.397 c
+41.161 0.474 41.334 0.515 41.521 0.515 c
+41.834 0.515 42.069 0.434 42.227 0.279 c
+42.381 0.133 42.462 -0.088 42.462 -0.382 c
+42.462 -1.881 l
+42.47 -2.117 42.506 -2.319 42.565 -2.484 c
+42.565 -2.528 l
+h
+41.404 -2.146 m
+41.521 -2.146 41.631 -2.113 41.742 -2.043 c
+41.849 -1.977 41.926 -1.893 41.977 -1.793 c
+41.977 -1.087 l
+41.712 -1.087 l
+41.477 -1.087 41.29 -1.139 41.154 -1.234 c
+41.026 -1.334 40.963 -1.477 40.963 -1.661 c
+40.963 -1.83 40.992 -1.951 41.051 -2.028 c
+41.117 -2.109 41.234 -2.146 41.404 -2.146 c
+44.483 -1.764 m
+44.483 -1.658 44.442 -1.569 44.365 -1.5 c
+44.284 -1.422 44.134 -1.334 43.91 -1.234 c
+43.646 -1.128 43.458 -1.036 43.351 -0.956 c
+43.241 -0.878 43.164 -0.79 43.116 -0.691 c
+43.065 -0.596 43.043 -0.478 43.043 -0.338 c
+43.043 -0.095 43.131 0.106 43.307 0.264 c
+43.484 0.43 43.708 0.515 43.983 0.515 c
+44.278 0.515 44.513 0.426 44.689 0.25 c
+44.866 0.081 44.953 -0.133 44.953 -0.397 c
+44.469 -0.397 l
+44.469 -0.261 44.417 -0.147 44.322 -0.058 c
+44.234 0.037 44.12 0.088 43.983 0.088 c
+43.837 0.088 43.723 0.048 43.646 -0.029 c
+43.565 -0.099 43.528 -0.198 43.528 -0.324 c
+43.528 -0.422 43.557 -0.5 43.616 -0.559 c
+43.675 -0.617 43.814 -0.698 44.043 -0.794 c
+44.402 -0.941 44.648 -1.084 44.777 -1.22 c
+44.913 -1.348 44.983 -1.521 44.983 -1.735 c
+44.983 -1.992 44.887 -2.198 44.704 -2.352 c
+44.527 -2.51 44.292 -2.587 43.998 -2.587 c
+43.682 -2.587 43.428 -2.499 43.234 -2.323 c
+43.046 -2.138 42.954 -1.907 42.954 -1.631 c
+43.44 -1.631 l
+43.447 -1.801 43.499 -1.933 43.586 -2.028 c
+43.682 -2.117 43.821 -2.161 43.998 -2.161 c
+44.153 -2.161 44.27 -2.128 44.351 -2.057 c
+44.44 -1.992 44.483 -1.893 44.483 -1.764 c
+47.453 -1.72 m
+47.997 0.455 l
+48.511 0.455 l
+47.54 -2.955 l
+47.471 -3.208 47.368 -3.399 47.232 -3.528 c
+47.092 -3.663 46.942 -3.734 46.776 -3.734 c
+46.707 -3.734 46.622 -3.719 46.526 -3.69 c
+46.526 -3.278 l
+46.63 -3.293 l
+46.765 -3.293 46.871 -3.256 46.952 -3.19 c
+47.041 -3.12 47.107 -3.002 47.158 -2.837 c
+47.247 -2.499 l
+46.379 0.455 l
+46.909 0.455 l
+h
+48.691 -0.897 m
+48.691 -0.467 48.793 -0.125 48.999 0.133 c
+49.213 0.386 49.492 0.515 49.838 0.515 c
+50.179 0.515 50.455 0.386 50.661 0.133 c
+50.873 -0.114 50.987 -0.448 50.998 -0.867 c
+50.998 -1.176 l
+50.998 -1.61 50.888 -1.951 50.675 -2.205 c
+50.47 -2.462 50.19 -2.587 49.838 -2.587 c
+49.492 -2.587 49.22 -2.466 49.014 -2.219 c
+48.808 -1.977 48.698 -1.643 48.691 -1.22 c
+h
+49.176 -1.176 m
+49.176 -1.492 49.235 -1.735 49.352 -1.911 c
+49.477 -2.08 49.639 -2.161 49.838 -2.161 c
+50.268 -2.161 50.491 -1.852 50.514 -1.234 c
+50.514 -0.897 l
+50.514 -0.596 50.447 -0.353 50.322 -0.176 c
+50.204 0 50.044 0.088 49.838 0.088 c
+49.639 0.088 49.477 0 49.352 -0.176 c
+49.235 -0.353 49.176 -0.596 49.176 -0.897 c
+h
+52.953 -2.263 m
+52.795 -2.481 52.56 -2.587 52.248 -2.587 c
+51.983 -2.587 51.777 -2.495 51.631 -2.308 c
+51.491 -2.124 51.425 -1.849 51.425 -1.484 c
+51.425 0.455 l
+51.91 0.455 l
+51.91 -1.455 l
+51.91 -1.918 52.049 -2.146 52.336 -2.146 c
+52.631 -2.146 52.828 -2.014 52.939 -1.749 c
+52.939 0.455 l
+53.439 0.455 l
+53.439 -2.528 l
+52.968 -2.528 l
+h
+57.415 -1.675 m
+57.871 0.455 l
+58.356 0.455 l
+57.62 -2.528 l
+57.238 -2.528 l
+56.65 -0.397 l
+56.077 -2.528 l
+55.695 -2.528 l
+54.96 0.455 l
+55.445 0.455 l
+55.916 -1.617 l
+56.459 0.455 l
+56.841 0.455 l
+h
+60.149 -2.528 m
+60.119 -2.462 60.097 -2.352 60.09 -2.205 c
+59.914 -2.462 59.693 -2.587 59.428 -2.587 c
+59.153 -2.587 58.936 -2.514 58.782 -2.367 c
+58.634 -2.212 58.561 -1.995 58.561 -1.72 c
+58.561 -1.419 58.664 -1.176 58.87 -0.999 c
+59.076 -0.816 59.359 -0.721 59.723 -0.721 c
+60.076 -0.721 l
+60.076 -0.397 l
+60.076 -0.22 60.035 -0.099 59.958 -0.029 c
+59.877 0.048 59.76 0.088 59.605 0.088 c
+59.458 0.088 59.333 0.044 59.237 -0.044 c
+59.149 -0.133 59.105 -0.243 59.105 -0.368 c
+58.62 -0.368 l
+58.62 -0.22 58.664 -0.081 58.752 0.059 c
+58.84 0.206 58.958 0.316 59.105 0.397 c
+59.259 0.474 59.432 0.515 59.619 0.515 c
+59.932 0.515 60.167 0.434 60.325 0.279 c
+60.479 0.133 60.56 -0.088 60.56 -0.382 c
+60.56 -1.881 l
+60.568 -2.117 60.604 -2.319 60.664 -2.484 c
+60.664 -2.528 l
+h
+59.502 -2.146 m
+59.619 -2.146 59.729 -2.113 59.84 -2.043 c
+59.947 -1.977 60.024 -1.893 60.076 -1.793 c
+60.076 -1.087 l
+59.81 -1.087 l
+59.575 -1.087 59.388 -1.139 59.252 -1.234 c
+59.124 -1.334 59.061 -1.477 59.061 -1.661 c
+59.061 -1.83 59.091 -1.951 59.149 -2.028 c
+59.216 -2.109 59.333 -2.146 59.502 -2.146 c
+61.597 0.455 m
+61.611 0.133 l
+61.795 0.386 62.038 0.515 62.331 0.515 c
+62.861 0.515 63.129 0.162 63.14 -0.544 c
+63.14 -2.528 l
+62.655 -2.528 l
+62.655 -0.573 l
+62.655 -0.338 62.615 -0.172 62.538 -0.073 c
+62.457 0.023 62.339 0.073 62.185 0.073 c
+62.067 0.073 61.957 0.033 61.861 -0.044 c
+61.762 -0.125 61.685 -0.231 61.626 -0.368 c
+61.626 -2.528 l
+61.141 -2.528 l
+61.141 0.455 l
+h
+64.323 1.176 m
+64.323 0.455 l
+64.779 0.455 l
+64.779 0.059 l
+64.323 0.059 l
+64.323 -1.793 l
+64.323 -1.911 64.342 -1.999 64.382 -2.057 c
+64.419 -2.117 64.489 -2.146 64.587 -2.146 c
+64.647 -2.146 64.709 -2.138 64.779 -2.117 c
+64.779 -2.528 l
+64.662 -2.564 64.548 -2.587 64.441 -2.587 c
+64.242 -2.587 64.092 -2.521 63.985 -2.381 c
+63.886 -2.246 63.839 -2.051 63.839 -1.793 c
+63.839 0.059 l
+63.382 0.059 l
+63.382 0.455 l
+63.839 0.455 l
+63.839 1.176 l
+h
+65.275 -2.263 m
+65.275 -2.175 65.297 -2.102 65.348 -2.043 c
+65.408 -1.984 65.485 -1.955 65.584 -1.955 c
+65.69 -1.955 65.767 -1.984 65.819 -2.043 c
+65.878 -2.102 65.907 -2.175 65.907 -2.263 c
+65.907 -2.344 65.878 -2.41 65.819 -2.469 c
+65.767 -2.528 65.69 -2.558 65.584 -2.558 c
+65.485 -2.558 65.408 -2.528 65.348 -2.469 c
+65.297 -2.41 65.275 -2.344 65.275 -2.263 c
+f
+Q
+ endstream endobj 53 0 obj <</BBox[703.328 443.501 763.072 438.121]/Group 89 0 R/Length 13734/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 704.9891 443.2802 cm
+0 0 m
+0.5 0 l
+0.5 -2.836 l
+0.5 -3.219 0.401 -3.524 0.206 -3.748 c
+0.008 -3.965 -0.257 -4.072 -0.588 -4.072 c
+-0.922 -4.072 -1.187 -3.969 -1.382 -3.763 c
+-1.569 -3.557 -1.661 -3.274 -1.661 -2.911 c
+-1.161 -2.911 l
+-1.161 -3.138 -1.114 -3.314 -1.014 -3.439 c
+-0.908 -3.568 -0.764 -3.63 -0.588 -3.63 c
+-0.411 -3.63 -0.272 -3.564 -0.162 -3.424 c
+-0.055 -3.289 0 -3.094 0 -2.836 c
+h
+2.609 -3.748 m
+2.452 -3.965 2.216 -4.072 1.903 -4.072 c
+1.639 -4.072 1.433 -3.979 1.286 -3.792 c
+1.147 -3.609 1.08 -3.333 1.08 -2.969 c
+1.08 -1.029 l
+1.565 -1.029 l
+1.565 -2.94 l
+1.565 -3.403 1.706 -3.63 1.992 -3.63 c
+2.286 -3.63 2.485 -3.499 2.595 -3.233 c
+2.595 -1.029 l
+3.094 -1.029 l
+3.094 -4.012 l
+2.624 -4.012 l
+h
+5.089 -3.248 m
+5.089 -3.142 5.049 -3.054 4.972 -2.984 c
+4.891 -2.907 4.74 -2.818 4.516 -2.719 c
+4.252 -2.612 4.064 -2.52 3.958 -2.44 c
+3.848 -2.362 3.771 -2.275 3.723 -2.175 c
+3.671 -2.08 3.649 -1.962 3.649 -1.822 c
+3.649 -1.579 3.738 -1.378 3.914 -1.22 c
+4.09 -1.055 4.314 -0.97 4.59 -0.97 c
+4.883 -0.97 5.119 -1.058 5.295 -1.234 c
+5.471 -1.404 5.56 -1.617 5.56 -1.881 c
+5.075 -1.881 l
+5.075 -1.745 5.024 -1.631 4.928 -1.543 c
+4.84 -1.448 4.725 -1.396 4.59 -1.396 c
+4.443 -1.396 4.329 -1.436 4.252 -1.514 c
+4.171 -1.583 4.135 -1.683 4.135 -1.808 c
+4.135 -1.907 4.164 -1.984 4.222 -2.043 c
+4.281 -2.102 4.421 -2.182 4.648 -2.278 c
+5.009 -2.425 5.255 -2.568 5.384 -2.705 c
+5.519 -2.833 5.589 -3.006 5.589 -3.219 c
+5.589 -3.476 5.494 -3.682 5.31 -3.836 c
+5.134 -3.994 4.898 -4.072 4.605 -4.072 c
+4.289 -4.072 4.035 -3.983 3.84 -3.807 c
+3.653 -3.623 3.561 -3.391 3.561 -3.116 c
+4.046 -3.116 l
+4.054 -3.285 4.104 -3.418 4.193 -3.513 c
+4.289 -3.601 4.428 -3.645 4.605 -3.645 c
+4.759 -3.645 4.877 -3.612 4.958 -3.542 c
+5.045 -3.476 5.089 -3.377 5.089 -3.248 c
+6.677 -0.309 m
+6.677 -1.029 l
+7.133 -1.029 l
+7.133 -1.425 l
+6.677 -1.425 l
+6.677 -3.278 l
+6.677 -3.395 6.695 -3.484 6.736 -3.542 c
+6.772 -3.601 6.842 -3.63 6.942 -3.63 c
+7 -3.63 7.063 -3.623 7.133 -3.601 c
+7.133 -4.012 l
+7.015 -4.049 6.901 -4.072 6.795 -4.072 c
+6.596 -4.072 6.446 -4.006 6.339 -3.865 c
+6.24 -3.73 6.192 -3.535 6.192 -3.278 c
+6.192 -1.425 l
+5.737 -1.425 l
+5.737 -1.029 l
+6.192 -1.029 l
+6.192 -0.309 l
+h
+10.036 -1.484 m
+9.966 -1.477 9.893 -1.469 9.816 -1.469 c
+9.558 -1.469 9.382 -1.61 9.286 -1.881 c
+9.286 -4.012 l
+8.802 -4.012 l
+8.802 -1.029 l
+9.272 -1.029 l
+9.286 -1.338 l
+9.411 -1.095 9.595 -0.97 9.83 -0.97 c
+9.907 -0.97 9.97 -0.985 10.021 -1.014 c
+h
+11.414 -4.072 m
+11.039 -4.072 10.756 -3.965 10.562 -3.748 c
+10.363 -3.524 10.267 -3.197 10.267 -2.763 c
+10.267 -2.396 l
+10.267 -1.955 10.359 -1.61 10.547 -1.352 c
+10.741 -1.099 11.017 -0.97 11.37 -0.97 c
+11.711 -0.97 11.965 -1.084 12.134 -1.308 c
+12.311 -1.536 12.403 -1.881 12.413 -2.352 c
+12.413 -2.66 l
+10.753 -2.66 l
+10.753 -2.734 l
+10.753 -3.057 10.811 -3.293 10.929 -3.439 c
+11.046 -3.579 11.216 -3.645 11.443 -3.645 c
+11.59 -3.645 11.715 -3.623 11.825 -3.572 c
+11.932 -3.513 12.035 -3.424 12.134 -3.307 c
+12.384 -3.616 l
+12.178 -3.921 11.855 -4.072 11.414 -4.072 c
+11.37 -1.396 m
+11.164 -1.396 11.009 -1.466 10.914 -1.602 c
+10.815 -1.741 10.76 -1.955 10.753 -2.248 c
+11.929 -2.248 l
+11.929 -2.175 l
+11.906 -1.903 11.855 -1.705 11.767 -1.587 c
+11.678 -1.462 11.546 -1.396 11.37 -1.396 c
+13.28 -1.029 m
+13.296 -1.308 l
+13.471 -1.084 13.71 -0.97 14.015 -0.97 c
+14.346 -0.97 14.578 -1.117 14.707 -1.411 c
+14.89 -1.117 15.152 -0.97 15.486 -0.97 c
+16.044 -0.97 16.327 -1.315 16.338 -1.999 c
+16.338 -4.012 l
+15.853 -4.012 l
+15.853 -2.043 l
+15.853 -1.83 15.813 -1.672 15.736 -1.573 c
+15.655 -1.466 15.522 -1.411 15.339 -1.411 c
+15.191 -1.411 15.073 -1.469 14.986 -1.587 c
+14.898 -1.697 14.842 -1.837 14.824 -2.013 c
+14.824 -4.012 l
+14.339 -4.012 l
+14.339 -2.028 l
+14.328 -1.617 14.155 -1.411 13.824 -1.411 c
+13.579 -1.411 13.406 -1.536 13.31 -1.778 c
+13.31 -4.012 l
+12.825 -4.012 l
+12.825 -1.029 l
+h
+17.845 -4.072 m
+17.47 -4.072 17.187 -3.965 16.993 -3.748 c
+16.794 -3.524 16.698 -3.197 16.698 -2.763 c
+16.698 -2.396 l
+16.698 -1.955 16.79 -1.61 16.978 -1.352 c
+17.172 -1.099 17.448 -0.97 17.801 -0.97 c
+18.142 -0.97 18.396 -1.084 18.565 -1.308 c
+18.741 -1.536 18.834 -1.881 18.844 -2.352 c
+18.844 -2.66 l
+17.184 -2.66 l
+17.184 -2.734 l
+17.184 -3.057 17.242 -3.293 17.359 -3.439 c
+17.477 -3.579 17.646 -3.645 17.874 -3.645 c
+18.021 -3.645 18.146 -3.623 18.256 -3.572 c
+18.363 -3.513 18.466 -3.424 18.565 -3.307 c
+18.815 -3.616 l
+18.609 -3.921 18.286 -4.072 17.845 -4.072 c
+17.801 -1.396 m
+17.595 -1.396 17.44 -1.466 17.345 -1.602 c
+17.246 -1.741 17.19 -1.955 17.184 -2.248 c
+18.359 -2.248 l
+18.359 -2.175 l
+18.337 -1.903 18.286 -1.705 18.198 -1.587 c
+18.109 -1.462 17.977 -1.396 17.801 -1.396 c
+21.417 -2.66 m
+21.417 -3.131 21.332 -3.484 21.167 -3.719 c
+20.997 -3.954 20.756 -4.072 20.432 -4.072 c
+20.116 -4.072 19.881 -3.935 19.726 -3.659 c
+19.697 -4.012 l
+19.256 -4.012 l
+19.256 0.221 l
+19.74 0.221 l
+19.74 -1.352 l
+19.895 -1.099 20.127 -0.97 20.432 -0.97 c
+20.756 -0.97 20.997 -1.087 21.167 -1.323 c
+21.332 -1.558 21.417 -1.907 21.417 -2.366 c
+h
+20.931 -2.381 m
+20.931 -2.028 20.88 -1.778 20.785 -1.631 c
+20.685 -1.484 20.523 -1.411 20.299 -1.411 c
+20.053 -1.411 19.866 -1.55 19.74 -1.822 c
+19.74 -3.233 l
+19.858 -3.499 20.05 -3.63 20.314 -3.63 c
+20.527 -3.63 20.685 -3.557 20.785 -3.41 c
+20.88 -3.256 20.931 -3.013 20.931 -2.69 c
+h
+22.919 -4.072 m
+22.545 -4.072 22.262 -3.965 22.067 -3.748 c
+21.868 -3.524 21.773 -3.197 21.773 -2.763 c
+21.773 -2.396 l
+21.773 -1.955 21.865 -1.61 22.052 -1.352 c
+22.247 -1.099 22.522 -0.97 22.875 -0.97 c
+23.217 -0.97 23.471 -1.084 23.64 -1.308 c
+23.816 -1.536 23.908 -1.881 23.919 -2.352 c
+23.919 -2.66 l
+22.258 -2.66 l
+22.258 -2.734 l
+22.258 -3.057 22.317 -3.293 22.435 -3.439 c
+22.552 -3.579 22.721 -3.645 22.949 -3.645 c
+23.096 -3.645 23.221 -3.623 23.331 -3.572 c
+23.438 -3.513 23.54 -3.424 23.64 -3.307 c
+23.89 -3.616 l
+23.684 -3.921 23.36 -4.072 22.919 -4.072 c
+22.875 -1.396 m
+22.67 -1.396 22.516 -1.466 22.42 -1.602 c
+22.321 -1.741 22.265 -1.955 22.258 -2.248 c
+23.434 -2.248 l
+23.434 -2.175 l
+23.412 -1.903 23.36 -1.705 23.272 -1.587 c
+23.185 -1.462 23.052 -1.396 22.875 -1.396 c
+25.566 -1.484 m
+25.496 -1.477 25.422 -1.469 25.344 -1.469 c
+25.088 -1.469 24.911 -1.61 24.816 -1.881 c
+24.816 -4.012 l
+24.33 -4.012 l
+24.33 -1.029 l
+24.801 -1.029 l
+24.816 -1.338 l
+24.941 -1.095 25.124 -0.97 25.359 -0.97 c
+25.437 -0.97 25.5 -0.985 25.55 -1.014 c
+h
+27.771 -0.309 m
+27.771 -1.029 l
+28.226 -1.029 l
+28.226 -1.425 l
+27.771 -1.425 l
+27.771 -3.278 l
+27.771 -3.395 27.789 -3.484 27.829 -3.542 c
+27.866 -3.601 27.935 -3.63 28.035 -3.63 c
+28.093 -3.63 28.156 -3.623 28.226 -3.601 c
+28.226 -4.012 l
+28.108 -4.049 27.995 -4.072 27.888 -4.072 c
+27.69 -4.072 27.538 -4.006 27.432 -3.865 c
+27.333 -3.73 27.285 -3.535 27.285 -3.278 c
+27.285 -1.425 l
+26.83 -1.425 l
+26.83 -1.029 l
+27.285 -1.029 l
+27.285 -0.309 l
+h
+28.538 -2.381 m
+28.538 -1.951 28.641 -1.61 28.847 -1.352 c
+29.06 -1.099 29.34 -0.97 29.685 -0.97 c
+30.027 -0.97 30.302 -1.099 30.508 -1.352 c
+30.721 -1.598 30.835 -1.932 30.846 -2.352 c
+30.846 -2.66 l
+30.846 -3.094 30.736 -3.436 30.522 -3.69 c
+30.317 -3.946 30.038 -4.072 29.685 -4.072 c
+29.34 -4.072 29.067 -3.95 28.862 -3.704 c
+28.656 -3.461 28.546 -3.127 28.538 -2.705 c
+h
+29.024 -2.66 m
+29.024 -2.976 29.082 -3.219 29.2 -3.395 c
+29.325 -3.564 29.487 -3.645 29.685 -3.645 c
+30.115 -3.645 30.339 -3.337 30.36 -2.719 c
+30.36 -2.381 l
+30.36 -2.08 30.295 -1.837 30.169 -1.66 c
+30.052 -1.484 29.89 -1.396 29.685 -1.396 c
+29.487 -1.396 29.325 -1.484 29.2 -1.66 c
+29.082 -1.837 29.024 -2.08 29.024 -2.381 c
+h
+34.003 -3.748 m
+33.845 -3.965 33.61 -4.072 33.297 -4.072 c
+33.032 -4.072 32.827 -3.979 32.679 -3.792 c
+32.54 -3.609 32.474 -3.333 32.474 -2.969 c
+32.474 -1.029 l
+32.959 -1.029 l
+32.959 -2.94 l
+32.959 -3.403 33.099 -3.63 33.385 -3.63 c
+33.679 -3.63 33.878 -3.499 33.988 -3.233 c
+33.988 -1.029 l
+34.488 -1.029 l
+34.488 -4.012 l
+34.017 -4.012 l
+h
+37.185 -2.66 m
+37.185 -3.131 37.101 -3.484 36.935 -3.719 c
+36.766 -3.954 36.527 -4.072 36.215 -4.072 c
+35.91 -4.072 35.678 -3.961 35.524 -3.734 c
+35.524 -5.159 l
+35.039 -5.159 l
+35.039 -1.029 l
+35.48 -1.029 l
+35.509 -1.367 l
+35.663 -1.103 35.895 -0.97 36.2 -0.97 c
+36.531 -0.97 36.777 -1.087 36.935 -1.323 c
+37.101 -1.55 37.185 -1.889 37.185 -2.337 c
+h
+36.7 -2.381 m
+36.7 -2.05 36.645 -1.804 36.538 -1.646 c
+36.439 -1.492 36.278 -1.411 36.053 -1.411 c
+35.818 -1.411 35.642 -1.529 35.524 -1.764 c
+35.524 -3.307 l
+35.642 -3.535 35.821 -3.645 36.068 -3.645 c
+36.281 -3.645 36.439 -3.568 36.538 -3.41 c
+36.645 -3.256 36.7 -3.013 36.7 -2.69 c
+h
+37.541 -2.381 m
+37.541 -1.922 37.622 -1.573 37.791 -1.338 c
+37.967 -1.095 38.218 -0.97 38.541 -0.97 c
+38.824 -0.97 39.044 -1.087 39.203 -1.323 c
+39.203 0.221 l
+39.688 0.221 l
+39.688 -4.012 l
+39.247 -4.012 l
+39.218 -3.69 l
+39.06 -3.946 38.835 -4.072 38.541 -4.072 c
+38.225 -4.072 37.982 -3.954 37.806 -3.719 c
+37.63 -3.476 37.541 -3.131 37.541 -2.69 c
+h
+38.027 -2.66 m
+38.027 -2.994 38.075 -3.241 38.173 -3.395 c
+38.269 -3.553 38.431 -3.63 38.659 -3.63 c
+38.901 -3.63 39.085 -3.513 39.203 -3.278 c
+39.203 -1.764 l
+39.074 -1.529 38.894 -1.411 38.659 -1.411 c
+38.431 -1.411 38.269 -1.492 38.173 -1.646 c
+38.075 -1.804 38.027 -2.043 38.027 -2.366 c
+h
+41.786 -4.012 m
+41.757 -3.946 41.734 -3.836 41.727 -3.69 c
+41.551 -3.946 41.33 -4.072 41.065 -4.072 c
+40.789 -4.072 40.573 -3.998 40.419 -3.851 c
+40.272 -3.696 40.198 -3.48 40.198 -3.204 c
+40.198 -2.903 40.301 -2.66 40.507 -2.484 c
+40.712 -2.3 40.996 -2.205 41.36 -2.205 c
+41.712 -2.205 l
+41.712 -1.881 l
+41.712 -1.705 41.672 -1.583 41.595 -1.514 c
+41.514 -1.436 41.396 -1.396 41.242 -1.396 c
+41.095 -1.396 40.97 -1.44 40.874 -1.529 c
+40.787 -1.617 40.742 -1.727 40.742 -1.852 c
+40.257 -1.852 l
+40.257 -1.705 40.301 -1.565 40.39 -1.425 c
+40.477 -1.278 40.595 -1.168 40.742 -1.087 c
+40.897 -1.01 41.069 -0.97 41.257 -0.97 c
+41.569 -0.97 41.805 -1.051 41.963 -1.205 c
+42.117 -1.352 42.198 -1.573 42.198 -1.866 c
+42.198 -3.366 l
+42.204 -3.601 42.241 -3.803 42.3 -3.969 c
+42.3 -4.012 l
+h
+41.139 -3.63 m
+41.257 -3.63 41.367 -3.597 41.477 -3.528 c
+41.583 -3.461 41.661 -3.377 41.712 -3.278 c
+41.712 -2.572 l
+41.448 -2.572 l
+41.213 -2.572 41.025 -2.624 40.889 -2.719 c
+40.76 -2.818 40.698 -2.961 40.698 -3.146 c
+40.698 -3.314 40.727 -3.436 40.787 -3.513 c
+40.853 -3.594 40.97 -3.63 41.139 -3.63 c
+43.41 -0.309 m
+43.41 -1.029 l
+43.866 -1.029 l
+43.866 -1.425 l
+43.41 -1.425 l
+43.41 -3.278 l
+43.41 -3.395 43.428 -3.484 43.469 -3.542 c
+43.505 -3.601 43.575 -3.63 43.675 -3.63 c
+43.733 -3.63 43.796 -3.623 43.866 -3.601 c
+43.866 -4.012 l
+43.748 -4.049 43.634 -4.072 43.528 -4.072 c
+43.33 -4.072 43.178 -4.006 43.072 -3.865 c
+42.973 -3.73 42.925 -3.535 42.925 -3.278 c
+42.925 -1.425 l
+42.47 -1.425 l
+42.47 -1.029 l
+42.925 -1.029 l
+42.925 -0.309 l
+h
+45.391 -4.072 m
+45.016 -4.072 44.733 -3.965 44.538 -3.748 c
+44.34 -3.524 44.244 -3.197 44.244 -2.763 c
+44.244 -2.396 l
+44.244 -1.955 44.336 -1.61 44.523 -1.352 c
+44.718 -1.099 44.994 -0.97 45.346 -0.97 c
+45.688 -0.97 45.942 -1.084 46.111 -1.308 c
+46.287 -1.536 46.379 -1.881 46.391 -2.352 c
+46.391 -2.66 l
+44.729 -2.66 l
+44.729 -2.734 l
+44.729 -3.057 44.788 -3.293 44.905 -3.439 c
+45.023 -3.579 45.192 -3.645 45.42 -3.645 c
+45.568 -3.645 45.692 -3.623 45.803 -3.572 c
+45.909 -3.513 46.012 -3.424 46.111 -3.307 c
+46.361 -3.616 l
+46.156 -3.921 45.832 -4.072 45.391 -4.072 c
+45.346 -1.396 m
+45.14 -1.396 44.986 -1.466 44.891 -1.602 c
+44.791 -1.741 44.737 -1.955 44.729 -2.248 c
+45.905 -2.248 l
+45.905 -2.175 l
+45.883 -1.903 45.832 -1.705 45.743 -1.587 c
+45.655 -1.462 45.523 -1.396 45.346 -1.396 c
+48.635 -0.309 m
+48.635 -1.029 l
+49.092 -1.029 l
+49.092 -1.425 l
+48.635 -1.425 l
+48.635 -3.278 l
+48.635 -3.395 48.654 -3.484 48.695 -3.542 c
+48.731 -3.601 48.801 -3.63 48.9 -3.63 c
+48.959 -3.63 49.021 -3.623 49.092 -3.601 c
+49.092 -4.012 l
+48.974 -4.049 48.86 -4.072 48.753 -4.072 c
+48.554 -4.072 48.404 -4.006 48.298 -3.865 c
+48.198 -3.73 48.151 -3.535 48.151 -3.278 c
+48.151 -1.425 l
+47.695 -1.425 l
+47.695 -1.029 l
+48.151 -1.029 l
+48.151 -0.309 l
+h
+50.043 -1.338 m
+50.227 -1.095 50.462 -0.97 50.748 -0.97 c
+51.278 -0.97 51.546 -1.323 51.557 -2.028 c
+51.557 -4.012 l
+51.072 -4.012 l
+51.072 -2.057 l
+51.072 -1.822 51.031 -1.657 50.954 -1.558 c
+50.873 -1.462 50.756 -1.411 50.601 -1.411 c
+50.484 -1.411 50.374 -1.452 50.278 -1.529 c
+50.179 -1.61 50.102 -1.716 50.043 -1.852 c
+50.043 -4.012 l
+49.558 -4.012 l
+49.558 0.221 l
+50.043 0.221 l
+h
+53.159 -4.072 m
+52.784 -4.072 52.502 -3.965 52.307 -3.748 c
+52.109 -3.524 52.013 -3.197 52.013 -2.763 c
+52.013 -2.396 l
+52.013 -1.955 52.105 -1.61 52.292 -1.352 c
+52.487 -1.099 52.762 -0.97 53.115 -0.97 c
+53.457 -0.97 53.711 -1.084 53.879 -1.308 c
+54.056 -1.536 54.148 -1.881 54.158 -2.352 c
+54.158 -2.66 l
+52.498 -2.66 l
+52.498 -2.734 l
+52.498 -3.057 52.556 -3.293 52.674 -3.439 c
+52.791 -3.579 52.961 -3.645 53.188 -3.645 c
+53.335 -3.645 53.46 -3.623 53.57 -3.572 c
+53.678 -3.513 53.78 -3.424 53.879 -3.307 c
+54.129 -3.616 l
+53.923 -3.921 53.601 -4.072 53.159 -4.072 c
+53.115 -1.396 m
+52.909 -1.396 52.755 -1.466 52.66 -1.602 c
+52.56 -1.741 52.505 -1.955 52.498 -2.248 c
+53.674 -2.248 l
+53.674 -2.175 l
+53.651 -1.903 53.601 -1.705 53.512 -1.587 c
+53.424 -1.462 53.291 -1.396 53.115 -1.396 c
+55.026 -1.029 m
+55.041 -1.308 l
+55.217 -1.084 55.456 -0.97 55.76 -0.97 c
+56.092 -0.97 56.323 -1.117 56.452 -1.411 c
+56.635 -1.117 56.896 -0.97 57.231 -0.97 c
+57.79 -0.97 58.072 -1.315 58.083 -1.999 c
+58.083 -4.012 l
+57.599 -4.012 l
+57.599 -2.043 l
+57.599 -1.83 57.558 -1.672 57.481 -1.573 c
+57.4 -1.466 57.268 -1.411 57.084 -1.411 c
+56.936 -1.411 56.819 -1.469 56.731 -1.587 c
+56.643 -1.697 56.587 -1.837 56.57 -2.013 c
+56.57 -4.012 l
+56.084 -4.012 l
+56.084 -2.028 l
+56.074 -1.617 55.901 -1.411 55.569 -1.411 c
+55.324 -1.411 55.151 -1.536 55.055 -1.778 c
+55.055 -4.012 l
+54.57 -4.012 l
+54.57 -1.029 l
+h
+f
+Q
+ endstream endobj 54 0 obj <</BBox[720.868 437.21 745.375 431.389]/Group 90 0 R/Length 5115/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 721.2498 432.6827 cm
+0 0 m
+0 2.587 l
+-0.382 2.587 l
+-0.382 2.983 l
+0 2.983 l
+0 3.322 l
+0.008 3.623 0.088 3.858 0.235 4.027 c
+0.382 4.203 0.592 4.292 0.867 4.292 c
+0.963 4.292 1.062 4.277 1.162 4.247 c
+1.132 3.836 l
+1.062 3.844 0.989 3.85 0.912 3.85 c
+0.636 3.85 0.5 3.652 0.5 3.262 c
+0.5 2.983 l
+1 2.983 l
+1 2.587 l
+0.5 2.587 l
+0.5 0 l
+h
+2.697 2.528 m
+2.628 2.535 2.554 2.543 2.477 2.543 c
+2.22 2.543 2.043 2.403 1.948 2.131 c
+1.948 0 l
+1.463 0 l
+1.463 2.983 l
+1.933 2.983 l
+1.948 2.674 l
+2.072 2.917 2.257 3.042 2.492 3.042 c
+2.569 3.042 2.631 3.027 2.683 2.998 c
+h
+4.075 -0.059 m
+3.701 -0.059 3.418 0.047 3.223 0.264 c
+3.024 0.488 2.929 0.816 2.929 1.249 c
+2.929 1.616 l
+2.929 2.057 3.021 2.403 3.208 2.66 c
+3.403 2.913 3.678 3.042 4.031 3.042 c
+4.373 3.042 4.627 2.929 4.796 2.705 c
+4.972 2.476 5.064 2.131 5.075 1.66 c
+5.075 1.352 l
+3.414 1.352 l
+3.414 1.278 l
+3.414 0.955 3.473 0.72 3.591 0.573 c
+3.708 0.434 3.877 0.367 4.104 0.367 c
+4.252 0.367 4.377 0.389 4.487 0.44 c
+4.594 0.5 4.696 0.588 4.796 0.706 c
+5.045 0.396 l
+4.84 0.091 4.517 -0.059 4.075 -0.059 c
+4.031 2.616 m
+3.826 2.616 3.672 2.547 3.576 2.41 c
+3.476 2.271 3.422 2.057 3.414 1.764 c
+4.59 1.764 l
+4.59 1.837 l
+4.568 2.109 4.517 2.308 4.428 2.425 c
+4.34 2.55 4.208 2.616 4.031 2.616 c
+5.384 1.631 m
+5.384 2.09 5.465 2.439 5.633 2.674 c
+5.799 2.917 6.049 3.042 6.383 3.042 c
+6.677 3.042 6.901 2.925 7.059 2.69 c
+7.088 2.983 l
+7.53 2.983 l
+7.53 -1.147 l
+7.044 -1.147 l
+7.044 0.264 l
+6.887 0.047 6.666 -0.059 6.383 -0.059 c
+6.06 -0.059 5.81 0.058 5.633 0.294 c
+5.465 0.529 5.384 0.87 5.384 1.323 c
+h
+5.868 1.352 m
+5.868 1.018 5.916 0.768 6.016 0.602 c
+6.122 0.444 6.288 0.367 6.516 0.367 c
+6.74 0.367 6.916 0.474 7.044 0.69 c
+7.044 2.293 l
+6.905 2.506 6.729 2.616 6.516 2.616 c
+6.288 2.616 6.122 2.532 6.016 2.366 c
+5.916 2.208 5.868 1.969 5.868 1.646 c
+h
+9.635 0.264 m
+9.477 0.047 9.242 -0.059 8.93 -0.059 c
+8.665 -0.059 8.459 0.033 8.312 0.22 c
+8.173 0.404 8.106 0.679 8.106 1.043 c
+8.106 2.983 l
+8.592 2.983 l
+8.592 1.072 l
+8.592 0.61 8.731 0.382 9.018 0.382 c
+9.312 0.382 9.511 0.514 9.621 0.779 c
+9.621 2.983 l
+10.12 2.983 l
+10.12 0 l
+9.65 0 l
+h
+11.73 -0.059 m
+11.356 -0.059 11.073 0.047 10.878 0.264 c
+10.679 0.488 10.583 0.816 10.583 1.249 c
+10.583 1.616 l
+10.583 2.057 10.676 2.403 10.863 2.66 c
+11.057 2.913 11.333 3.042 11.686 3.042 c
+12.027 3.042 12.281 2.929 12.451 2.705 c
+12.627 2.476 12.719 2.131 12.729 1.66 c
+12.729 1.352 l
+11.069 1.352 l
+11.069 1.278 l
+11.069 0.955 11.127 0.72 11.245 0.573 c
+11.362 0.434 11.532 0.367 11.759 0.367 c
+11.906 0.367 12.031 0.389 12.141 0.44 c
+12.248 0.5 12.351 0.588 12.451 0.706 c
+12.7 0.396 l
+12.494 0.091 12.171 -0.059 11.73 -0.059 c
+11.686 2.616 m
+11.48 2.616 11.326 2.547 11.231 2.41 c
+11.131 2.271 11.076 2.057 11.069 1.764 c
+12.245 1.764 l
+12.245 1.837 l
+12.222 2.109 12.171 2.308 12.083 2.425 c
+11.994 2.55 11.863 2.616 11.686 2.616 c
+13.596 2.983 m
+13.612 2.66 l
+13.795 2.913 14.038 3.042 14.332 3.042 c
+14.861 3.042 15.129 2.69 15.14 1.984 c
+15.14 0 l
+14.655 0 l
+14.655 1.955 l
+14.655 2.19 14.614 2.356 14.537 2.454 c
+14.456 2.55 14.339 2.601 14.185 2.601 c
+14.067 2.601 13.957 2.561 13.862 2.484 c
+13.762 2.403 13.685 2.296 13.627 2.16 c
+13.627 0 l
+13.141 0 l
+13.141 2.983 l
+h
+16.324 3.704 m
+16.324 2.983 l
+16.779 2.983 l
+16.779 2.587 l
+16.324 2.587 l
+16.324 0.735 l
+16.324 0.617 16.342 0.529 16.382 0.47 c
+16.419 0.411 16.489 0.382 16.588 0.382 c
+16.646 0.382 16.709 0.389 16.779 0.411 c
+16.779 0 l
+16.661 -0.037 16.548 -0.059 16.441 -0.059 c
+16.243 -0.059 16.092 0.007 15.985 0.147 c
+15.886 0.282 15.838 0.477 15.838 0.735 c
+15.838 2.587 l
+15.383 2.587 l
+15.383 2.983 l
+15.838 2.983 l
+15.838 3.704 l
+h
+17.775 0 -0.501 4.233 re
+19.26 0.808 m
+19.804 2.983 l
+20.318 2.983 l
+19.348 -0.427 l
+19.278 -0.68 19.175 -0.871 19.039 -1 c
+18.899 -1.135 18.749 -1.206 18.583 -1.206 c
+18.514 -1.206 18.429 -1.191 18.333 -1.162 c
+18.333 -0.75 l
+18.437 -0.765 l
+18.572 -0.765 18.679 -0.728 18.76 -0.662 c
+18.848 -0.592 18.915 -0.474 18.965 -0.31 c
+19.054 0.029 l
+18.186 2.983 l
+18.716 2.983 l
+h
+21.876 0.264 m
+21.876 0.353 21.899 0.426 21.949 0.484 c
+22.009 0.544 22.086 0.573 22.185 0.573 c
+22.291 0.573 22.369 0.544 22.42 0.484 c
+22.479 0.426 22.508 0.353 22.508 0.264 c
+22.508 0.183 22.479 0.118 22.42 0.058 c
+22.369 0 22.291 -0.03 22.185 -0.03 c
+22.086 -0.03 22.009 0 21.949 0.058 c
+21.899 0.118 21.876 0.183 21.876 0.264 c
+21.876 3.087 m
+21.876 3.175 21.899 3.248 21.949 3.307 c
+22.009 3.366 22.086 3.395 22.185 3.395 c
+22.291 3.395 22.369 3.366 22.42 3.307 c
+22.479 3.248 22.508 3.175 22.508 3.087 c
+22.508 3.006 22.479 2.94 22.42 2.881 c
+22.369 2.822 22.291 2.792 22.185 2.792 c
+22.086 2.792 22.009 2.822 21.949 2.881 c
+21.899 2.94 21.876 3.006 21.876 3.087 c
+24.125 1.602 m
+24.125 0.779 23.941 0.051 23.582 -0.574 c
+23.376 -0.915 23.169 -1.154 22.963 -1.294 c
+22.861 -0.985 l
+23.096 -0.757 23.28 -0.42 23.42 0.029 c
+23.567 0.488 23.64 0.988 23.64 1.529 c
+23.64 1.631 l
+23.64 2.326 23.526 2.954 23.302 3.513 c
+23.173 3.806 23.026 4.041 22.861 4.218 c
+22.963 4.527 l
+23.158 4.388 23.353 4.167 23.551 3.866 c
+23.934 3.218 24.125 2.462 24.125 1.602 c
+f
+Q
+ endstream endobj 55 0 obj <</BBox[320.12 122.007 531.709 116.418]/Group 91 0 R/Length 125/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 92 0 R>>/ExtGState<</GS0 12 0 R>>/Shading<</Sh0 93 0 R>>>>/Subtype/Form>>stream
+q
+320.12 122.007 211.589 -5.589 re
+W n
+q
+0 g
+/GS0 gs
+212.3990173 0 0 139.9599457 319.716156 119.2128296 cm
+BX /Sh0 sh EX Q
+Q
+ endstream endobj 56 0 obj <</BBox[80.2243 128.522 302.099 76.7775]/Group 94 0 R/Length 1745/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 217.0464 128.5219 cm
+0 0 m
+-12.446 0 -23.272 -2.697 -28.986 -6.673 c
+-31.187 -6.214 -33.551 -5.953 -35.983 -5.953 c
+-41.337 -5.953 -46.243 -7.162 -50.141 -9.161 c
+-52.585 -7.919 -55.856 -7.136 -59.461 -7.136 c
+-64.727 -7.136 -69.287 -8.764 -71.573 -11.135 c
+-74.947 -10.329 -79.352 -9.834 -84.196 -9.834 c
+-91.013 -9.834 -96.981 -10.815 -100.372 -12.274 c
+-103.823 -11.439 -107.74 -10.95 -111.904 -10.95 c
+-125.666 -10.95 -136.822 -16.11 -136.822 -22.478 c
+-136.822 -27.097 -130.935 -31.077 -122.458 -32.915 c
+-124.924 -33.932 -126.408 -35.215 -126.408 -36.612 c
+-126.408 -39.901 -118.25 -42.565 -108.185 -42.565 c
+-103.875 -42.565 -99.913 -42.079 -96.793 -41.26 c
+-95.863 -41.863 -94.805 -42.189 -93.681 -42.189 c
+-92.133 -42.189 -90.722 -41.547 -89.587 -40.47 c
+-86.603 -41.984 -82.384 -42.935 -77.688 -42.935 c
+-74.98 -42.935 -72.426 -42.605 -70.176 -42.05 c
+-69.544 -44.417 -63.745 -46.283 -56.672 -46.283 c
+-50.112 -46.283 -44.641 -44.681 -43.377 -42.565 c
+-40.415 -43.832 -36.454 -44.608 -32.103 -44.608 c
+-31.268 -44.608 -30.463 -44.571 -29.662 -44.516 c
+-24.992 -48.768 -14.14 -51.744 -1.488 -51.744 c
+11.198 -51.744 22.082 -48.76 26.73 -44.494 c
+27.987 -44.575 29.307 -44.608 30.637 -44.608 c
+41.639 -44.608 50.558 -41.69 50.558 -38.077 c
+50.558 -37.512 50.315 -36.971 49.907 -36.45 c
+53.178 -36.138 55.463 -35.413 55.463 -34.568 c
+55.463 -34.322 55.258 -34.087 54.905 -33.87 c
+55.633 -33.892 56.349 -33.914 57.092 -33.914 c
+72.525 -33.914 85.052 -28.696 85.052 -22.295 c
+85.052 -15.889 72.525 -10.715 57.092 -10.715 c
+53.362 -10.715 49.812 -11.027 46.56 -11.575 c
+43.962 -10.697 39.783 -10.113 35.076 -10.113 c
+34.183 -10.113 33.323 -10.142 32.474 -10.183 c
+29.101 -4.358 15.842 0 0 0 c
+f
+Q
+ endstream endobj 57 0 obj <</BBox[549.22 269.428 582.876 265.077]/Group 95 0 R/Length 6396/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 551.4096 266.1785 cm
+0 0 m
+-1.352 0 l
+-1.675 -1.043 l
+-2.19 -1.043 l
+-0.896 2.97 l
+-0.47 2.97 l
+0.838 -1.043 l
+0.309 -1.043 l
+h
+-1.22 0.441 m
+-0.132 0.441 l
+-0.676 2.264 l
+h
+3.05 0.324 m
+2.786 0.03 l
+2.786 -1.043 l
+2.3 -1.043 l
+2.3 3.19 l
+2.786 3.19 l
+2.786 0.662 l
+3.711 1.941 l
+4.299 1.941 l
+3.358 0.691 l
+4.432 -1.043 l
+3.859 -1.043 l
+h
+5.203 -1.043 -0.5 2.984 re
+5.233 2.735 m
+5.233 2.646 5.207 2.573 5.159 2.514 c
+5.12 2.463 5.049 2.44 4.954 2.44 c
+4.866 2.44 4.796 2.463 4.748 2.514 c
+4.707 2.573 4.689 2.639 4.689 2.72 c
+4.689 2.808 4.707 2.881 4.748 2.94 c
+4.796 2.999 4.866 3.028 4.954 3.028 c
+5.049 3.028 5.12 2.999 5.159 2.94 c
+5.207 2.881 5.233 2.812 5.233 2.735 c
+6.335 1.941 m
+6.35 1.617 l
+6.533 1.871 6.776 1.999 7.071 1.999 c
+7.599 1.999 7.867 1.646 7.879 0.941 c
+7.879 -1.043 l
+7.394 -1.043 l
+7.394 0.912 l
+7.394 1.147 7.354 1.312 7.276 1.411 c
+7.196 1.507 7.078 1.559 6.924 1.559 c
+6.805 1.559 6.695 1.518 6.6 1.441 c
+6.5 1.36 6.423 1.253 6.365 1.118 c
+6.365 -1.043 l
+5.88 -1.043 l
+5.88 1.941 l
+h
+8.327 0.588 m
+8.327 1.048 8.408 1.397 8.577 1.632 c
+8.754 1.875 9.003 1.999 9.327 1.999 c
+9.61 1.999 9.83 1.881 9.988 1.646 c
+9.988 3.19 l
+10.473 3.19 l
+10.473 -1.043 l
+10.032 -1.043 l
+10.003 -0.72 l
+9.845 -0.977 9.621 -1.102 9.327 -1.102 c
+9.01 -1.102 8.768 -0.984 8.592 -0.749 c
+8.415 -0.507 8.327 -0.161 8.327 0.279 c
+h
+8.812 0.309 m
+8.812 -0.025 8.86 -0.272 8.96 -0.426 c
+9.055 -0.584 9.216 -0.661 9.444 -0.661 c
+9.687 -0.661 9.87 -0.544 9.988 -0.309 c
+9.988 1.206 l
+9.86 1.441 9.679 1.559 9.444 1.559 c
+9.216 1.559 9.055 1.478 8.96 1.324 c
+8.86 1.166 8.812 0.927 8.812 0.603 c
+h
+12.145 0.588 m
+12.145 1.018 12.248 1.36 12.453 1.617 c
+12.667 1.871 12.946 1.999 13.292 1.999 c
+13.633 1.999 13.909 1.871 14.115 1.617 c
+14.328 1.371 14.442 1.037 14.453 0.618 c
+14.453 0.309 l
+14.453 -0.124 14.343 -0.467 14.13 -0.72 c
+13.924 -0.977 13.644 -1.102 13.292 -1.102 c
+12.946 -1.102 12.675 -0.981 12.469 -0.735 c
+12.263 -0.492 12.152 -0.158 12.145 0.265 c
+h
+12.63 0.309 m
+12.63 -0.007 12.689 -0.249 12.806 -0.426 c
+12.931 -0.595 13.093 -0.675 13.292 -0.675 c
+13.722 -0.675 13.945 -0.367 13.968 0.25 c
+13.968 0.588 l
+13.968 0.89 13.901 1.133 13.777 1.309 c
+13.66 1.485 13.498 1.573 13.292 1.573 c
+13.093 1.573 12.931 1.485 12.806 1.309 c
+12.689 1.133 12.63 0.89 12.63 0.588 c
+h
+15.1 -1.043 m
+15.1 1.544 l
+14.718 1.544 l
+14.718 1.941 l
+15.1 1.941 l
+15.1 2.278 l
+15.107 2.58 15.188 2.816 15.335 2.984 c
+15.482 3.161 15.692 3.249 15.967 3.249 c
+16.062 3.249 16.162 3.234 16.261 3.205 c
+16.232 2.793 l
+16.162 2.801 16.089 2.808 16.011 2.808 c
+15.736 2.808 15.599 2.61 15.599 2.22 c
+15.599 1.941 l
+16.099 1.941 l
+16.099 1.544 l
+15.599 1.544 l
+15.599 -1.043 l
+h
+19.293 -1.043 m
+19.264 -0.977 19.241 -0.866 19.233 -0.72 c
+19.057 -0.977 18.837 -1.102 18.572 -1.102 c
+18.296 -1.102 18.08 -1.028 17.926 -0.882 c
+17.779 -0.727 17.705 -0.511 17.705 -0.235 c
+17.705 0.067 17.808 0.309 18.014 0.485 c
+18.219 0.669 18.502 0.765 18.867 0.765 c
+19.219 0.765 l
+19.219 1.088 l
+19.219 1.264 19.179 1.386 19.102 1.455 c
+19.021 1.532 18.903 1.573 18.749 1.573 c
+18.602 1.573 18.477 1.529 18.381 1.441 c
+18.293 1.353 18.249 1.243 18.249 1.118 c
+17.764 1.118 l
+17.764 1.264 17.808 1.405 17.897 1.544 c
+17.984 1.69 18.102 1.801 18.249 1.881 c
+18.404 1.959 18.576 1.999 18.763 1.999 c
+19.075 1.999 19.311 1.918 19.469 1.764 c
+19.624 1.617 19.704 1.397 19.704 1.103 c
+19.704 -0.396 l
+19.711 -0.631 19.748 -0.833 19.807 -0.999 c
+19.807 -1.043 l
+h
+18.646 -0.661 m
+18.763 -0.661 18.874 -0.628 18.984 -0.558 c
+19.09 -0.492 19.168 -0.407 19.219 -0.309 c
+19.219 0.397 l
+18.955 0.397 l
+18.72 0.397 18.532 0.346 18.396 0.25 c
+18.267 0.151 18.205 0.008 18.205 -0.176 c
+18.205 -0.345 18.234 -0.467 18.293 -0.544 c
+18.359 -0.625 18.477 -0.661 18.646 -0.661 c
+22.931 -0.278 m
+22.931 -0.172 22.89 -0.084 22.813 -0.014 c
+22.732 0.063 22.581 0.151 22.358 0.25 c
+22.092 0.357 21.905 0.449 21.799 0.53 c
+21.689 0.607 21.612 0.695 21.564 0.794 c
+21.512 0.89 21.49 1.008 21.49 1.147 c
+21.49 1.389 21.579 1.592 21.755 1.75 c
+21.931 1.915 22.155 1.999 22.431 1.999 c
+22.725 1.999 22.96 1.912 23.137 1.735 c
+23.312 1.565 23.401 1.353 23.401 1.088 c
+22.916 1.088 l
+22.916 1.224 22.865 1.338 22.769 1.426 c
+22.681 1.522 22.566 1.573 22.431 1.573 c
+22.284 1.573 22.17 1.532 22.092 1.455 c
+22.012 1.386 21.976 1.287 21.976 1.162 c
+21.976 1.062 22.005 0.985 22.063 0.927 c
+22.122 0.867 22.262 0.786 22.489 0.691 c
+22.85 0.545 23.096 0.401 23.225 0.265 c
+23.36 0.136 23.43 -0.037 23.43 -0.249 c
+23.43 -0.507 23.335 -0.712 23.152 -0.866 c
+22.975 -1.024 22.74 -1.102 22.446 -1.102 c
+22.13 -1.102 21.876 -1.014 21.681 -0.837 c
+21.494 -0.654 21.402 -0.422 21.402 -0.147 c
+21.887 -0.147 l
+21.895 -0.316 21.946 -0.448 22.034 -0.544 c
+22.13 -0.631 22.269 -0.675 22.446 -0.675 c
+22.6 -0.675 22.718 -0.643 22.798 -0.573 c
+22.886 -0.507 22.931 -0.407 22.931 -0.278 c
+24.371 1.632 m
+24.555 1.875 24.79 1.999 25.076 1.999 c
+25.606 1.999 25.874 1.646 25.885 0.941 c
+25.885 -1.043 l
+25.4 -1.043 l
+25.4 0.912 l
+25.4 1.147 25.359 1.312 25.282 1.411 c
+25.201 1.507 25.084 1.559 24.93 1.559 c
+24.812 1.559 24.702 1.518 24.606 1.441 c
+24.507 1.36 24.43 1.253 24.371 1.118 c
+24.371 -1.043 l
+23.886 -1.043 l
+23.886 3.19 l
+24.371 3.19 l
+h
+27.487 -1.102 m
+27.112 -1.102 26.83 -0.995 26.635 -0.779 c
+26.437 -0.554 26.341 -0.228 26.341 0.206 c
+26.341 0.574 l
+26.341 1.015 26.433 1.36 26.62 1.617 c
+26.815 1.871 27.091 1.999 27.443 1.999 c
+27.785 1.999 28.039 1.885 28.207 1.661 c
+28.384 1.434 28.476 1.088 28.487 0.618 c
+28.487 0.309 l
+26.826 0.309 l
+26.826 0.235 l
+26.826 -0.087 26.884 -0.323 27.002 -0.47 c
+27.12 -0.61 27.289 -0.675 27.517 -0.675 c
+27.663 -0.675 27.789 -0.654 27.899 -0.602 c
+28.006 -0.544 28.108 -0.455 28.207 -0.338 c
+28.457 -0.646 l
+28.251 -0.951 27.929 -1.102 27.487 -1.102 c
+27.443 1.573 m
+27.237 1.573 27.083 1.503 26.988 1.368 c
+26.888 1.228 26.834 1.015 26.826 0.721 c
+28.002 0.721 l
+28.002 0.794 l
+27.979 1.066 27.929 1.264 27.84 1.382 c
+27.752 1.507 27.62 1.573 27.443 1.573 c
+29.427 -1.043 -0.5 4.233 re
+30.306 -1.043 m
+30.306 1.544 l
+29.924 1.544 l
+29.924 1.941 l
+30.306 1.941 l
+30.306 2.278 l
+30.313 2.58 30.394 2.816 30.541 2.984 c
+30.688 3.161 30.898 3.249 31.173 3.249 c
+31.268 3.249 31.368 3.234 31.467 3.205 c
+31.438 2.793 l
+31.368 2.801 31.295 2.808 31.218 2.808 c
+30.942 2.808 30.805 2.61 30.805 2.22 c
+30.805 1.941 l
+31.305 1.941 l
+31.305 1.544 l
+30.805 1.544 l
+30.805 -1.043 l
+h
+f
+Q
+ endstream endobj 58 0 obj <</BBox[553.089 262.843 578.922 258.492]/Group 96 0 R/Length 6110/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 553.4717 258.55 cm
+0 0 m
+0 2.587 l
+-0.383 2.587 l
+-0.383 2.984 l
+0 2.984 l
+0 3.322 l
+0.007 3.624 0.087 3.859 0.235 4.027 c
+0.382 4.204 0.591 4.293 0.866 4.293 c
+0.962 4.293 1.061 4.278 1.161 4.248 c
+1.132 3.836 l
+1.061 3.844 0.988 3.851 0.911 3.851 c
+0.635 3.851 0.5 3.653 0.5 3.263 c
+0.5 2.984 l
+0.999 2.984 l
+0.999 2.587 l
+0.5 2.587 l
+0.5 0 l
+h
+1.359 1.631 m
+1.359 2.061 1.462 2.404 1.668 2.66 c
+1.881 2.914 2.16 3.042 2.506 3.042 c
+2.848 3.042 3.123 2.914 3.329 2.66 c
+3.542 2.414 3.656 2.08 3.667 1.661 c
+3.667 1.353 l
+3.667 0.919 3.557 0.577 3.343 0.324 c
+3.137 0.066 2.859 -0.058 2.506 -0.058 c
+2.16 -0.058 1.888 0.062 1.683 0.309 c
+1.477 0.551 1.367 0.885 1.359 1.309 c
+h
+1.844 1.353 m
+1.844 1.037 1.903 0.794 2.021 0.617 c
+2.146 0.449 2.308 0.368 2.506 0.368 c
+2.936 0.368 3.16 0.676 3.182 1.294 c
+3.182 1.631 l
+3.182 1.933 3.116 2.176 2.991 2.352 c
+2.873 2.529 2.711 2.616 2.506 2.616 c
+2.308 2.616 2.146 2.529 2.021 2.352 c
+1.903 2.176 1.844 1.933 1.844 1.631 c
+h
+5.339 2.529 m
+5.269 2.535 5.196 2.543 5.119 2.543 c
+4.862 2.543 4.685 2.404 4.589 2.132 c
+4.589 0 l
+4.104 0 l
+4.104 2.984 l
+4.575 2.984 l
+4.589 2.675 l
+4.714 2.918 4.898 3.042 5.134 3.042 c
+5.211 3.042 5.273 3.028 5.325 2.999 c
+h
+7.548 3.705 m
+7.548 2.984 l
+8.003 2.984 l
+8.003 2.587 l
+7.548 2.587 l
+7.548 0.735 l
+7.548 0.617 7.565 0.53 7.606 0.47 c
+7.643 0.412 7.713 0.382 7.812 0.382 c
+7.871 0.382 7.933 0.389 8.003 0.412 c
+8.003 0 l
+7.885 -0.037 7.771 -0.058 7.665 -0.058 c
+7.467 -0.058 7.316 0.008 7.21 0.147 c
+7.11 0.283 7.062 0.478 7.062 0.735 c
+7.062 2.587 l
+6.607 2.587 l
+6.607 2.984 l
+7.062 2.984 l
+7.062 3.705 l
+h
+8.955 2.675 m
+9.138 2.918 9.374 3.042 9.66 3.042 c
+10.19 3.042 10.458 2.69 10.469 1.984 c
+10.469 0 l
+9.984 0 l
+9.984 1.955 l
+9.984 2.19 9.944 2.356 9.866 2.454 c
+9.786 2.55 9.668 2.602 9.514 2.602 c
+9.396 2.602 9.286 2.562 9.19 2.484 c
+9.091 2.404 9.014 2.296 8.955 2.161 c
+8.955 0 l
+8.469 0 l
+8.469 4.233 l
+8.955 4.233 l
+h
+12.068 -0.058 m
+11.692 -0.058 11.409 0.048 11.215 0.264 c
+11.016 0.489 10.921 0.816 10.921 1.249 c
+10.921 1.617 l
+10.921 2.058 11.013 2.404 11.2 2.66 c
+11.395 2.914 11.671 3.042 12.024 3.042 c
+12.365 3.042 12.619 2.929 12.787 2.705 c
+12.964 2.477 13.056 2.132 13.067 1.661 c
+13.067 1.353 l
+11.406 1.353 l
+11.406 1.278 l
+11.406 0.956 11.465 0.721 11.582 0.573 c
+11.7 0.434 11.869 0.368 12.097 0.368 c
+12.244 0.368 12.369 0.389 12.479 0.441 c
+12.585 0.5 12.689 0.588 12.787 0.706 c
+13.038 0.397 l
+12.832 0.092 12.508 -0.058 12.068 -0.058 c
+12.024 2.616 m
+11.818 2.616 11.663 2.547 11.567 2.411 c
+11.469 2.271 11.413 2.058 11.406 1.764 c
+12.582 1.764 l
+12.582 1.837 l
+12.56 2.109 12.508 2.308 12.421 2.425 c
+12.332 2.55 12.199 2.616 12.024 2.616 c
+15.139 2.984 m
+15.154 2.705 l
+15.33 2.929 15.569 3.042 15.875 3.042 c
+16.205 3.042 16.437 2.896 16.565 2.602 c
+16.749 2.896 17.01 3.042 17.344 3.042 c
+17.903 3.042 18.186 2.697 18.197 2.014 c
+18.197 0 l
+17.712 0 l
+17.712 1.97 l
+17.712 2.183 17.672 2.341 17.595 2.44 c
+17.514 2.547 17.381 2.602 17.198 2.602 c
+17.051 2.602 16.933 2.543 16.845 2.425 c
+16.756 2.315 16.701 2.176 16.683 1.999 c
+16.683 0 l
+16.198 0 l
+16.198 1.984 l
+16.187 2.396 16.014 2.602 15.683 2.602 c
+15.438 2.602 15.264 2.477 15.169 2.234 c
+15.169 0 l
+14.684 0 l
+14.684 2.984 l
+h
+19.704 -0.058 m
+19.328 -0.058 19.046 0.048 18.852 0.264 c
+18.653 0.489 18.557 0.816 18.557 1.249 c
+18.557 1.617 l
+18.557 2.058 18.649 2.404 18.836 2.66 c
+19.031 2.914 19.307 3.042 19.66 3.042 c
+20.001 3.042 20.255 2.929 20.423 2.705 c
+20.6 2.477 20.693 2.132 20.703 1.661 c
+20.703 1.353 l
+19.042 1.353 l
+19.042 1.278 l
+19.042 0.956 19.101 0.721 19.218 0.573 c
+19.336 0.434 19.505 0.368 19.733 0.368 c
+19.88 0.368 20.005 0.389 20.115 0.441 c
+20.222 0.5 20.325 0.588 20.423 0.706 c
+20.674 0.397 l
+20.468 0.092 20.145 -0.058 19.704 -0.058 c
+19.66 2.616 m
+19.453 2.616 19.299 2.547 19.204 2.411 c
+19.104 2.271 19.05 2.058 19.042 1.764 c
+20.218 1.764 l
+20.218 1.837 l
+20.196 2.109 20.145 2.308 20.057 2.425 c
+19.968 2.55 19.835 2.616 19.66 2.616 c
+22.555 0.765 m
+22.555 0.871 22.515 0.96 22.438 1.029 c
+22.357 1.106 22.206 1.195 21.982 1.294 c
+21.717 1.4 21.53 1.492 21.423 1.573 c
+21.313 1.65 21.236 1.738 21.188 1.837 c
+21.136 1.933 21.115 2.051 21.115 2.19 c
+21.115 2.433 21.203 2.635 21.379 2.793 c
+21.556 2.959 21.78 3.042 22.056 3.042 c
+22.349 3.042 22.584 2.955 22.761 2.778 c
+22.937 2.609 23.026 2.396 23.026 2.132 c
+22.54 2.132 l
+22.54 2.267 22.489 2.381 22.393 2.469 c
+22.305 2.565 22.191 2.616 22.056 2.616 c
+21.909 2.616 21.795 2.576 21.717 2.499 c
+21.637 2.429 21.599 2.33 21.599 2.205 c
+21.599 2.105 21.629 2.028 21.688 1.97 c
+21.747 1.911 21.886 1.83 22.114 1.735 c
+22.474 1.588 22.721 1.444 22.85 1.309 c
+22.985 1.18 23.055 1.007 23.055 0.794 c
+23.055 0.536 22.96 0.331 22.775 0.177 c
+22.599 0.019 22.364 -0.058 22.07 -0.058 c
+21.755 -0.058 21.501 0.029 21.306 0.206 c
+21.119 0.389 21.026 0.621 21.026 0.897 c
+21.512 0.897 l
+21.519 0.727 21.57 0.595 21.659 0.5 c
+21.755 0.412 21.894 0.368 22.07 0.368 c
+22.225 0.368 22.343 0.401 22.422 0.47 c
+22.511 0.536 22.555 0.636 22.555 0.765 c
+24.951 0.765 m
+24.951 0.871 24.911 0.96 24.834 1.029 c
+24.753 1.106 24.602 1.195 24.378 1.294 c
+24.113 1.4 23.926 1.492 23.82 1.573 c
+23.709 1.65 23.632 1.738 23.584 1.837 c
+23.533 1.933 23.511 2.051 23.511 2.19 c
+23.511 2.433 23.598 2.635 23.775 2.793 c
+23.951 2.959 24.176 3.042 24.452 3.042 c
+24.745 3.042 24.98 2.955 25.157 2.778 c
+25.333 2.609 25.422 2.396 25.422 2.132 c
+24.936 2.132 l
+24.936 2.267 24.885 2.381 24.789 2.469 c
+24.701 2.565 24.587 2.616 24.452 2.616 c
+24.304 2.616 24.19 2.576 24.113 2.499 c
+24.032 2.429 23.995 2.33 23.995 2.205 c
+23.995 2.105 24.026 2.028 24.084 1.97 c
+24.143 1.911 24.282 1.83 24.51 1.735 c
+24.87 1.588 25.117 1.444 25.245 1.309 c
+25.381 1.18 25.451 1.007 25.451 0.794 c
+25.451 0.536 25.356 0.331 25.171 0.177 c
+24.995 0.019 24.76 -0.058 24.466 -0.058 c
+24.15 -0.058 23.897 0.029 23.702 0.206 c
+23.515 0.389 23.423 0.621 23.423 0.897 c
+23.908 0.897 l
+23.914 0.727 23.966 0.595 24.055 0.5 c
+24.15 0.412 24.29 0.368 24.466 0.368 c
+24.62 0.368 24.738 0.401 24.819 0.47 c
+24.907 0.536 24.951 0.636 24.951 0.765 c
+f
+Q
+ endstream endobj 59 0 obj <</BBox[539.662 256.198 591.994 250.76]/Group 97 0 R/Length 10262/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 540.7341 252.7729 cm
+0 0 m
+0.545 2.176 l
+1.058 2.176 l
+0.088 -1.234 l
+0.019 -1.488 -0.084 -1.679 -0.22 -1.807 c
+-0.359 -1.944 -0.51 -2.013 -0.675 -2.013 c
+-0.745 -2.013 -0.83 -1.999 -0.926 -1.969 c
+-0.926 -1.558 l
+-0.823 -1.572 l
+-0.687 -1.572 -0.58 -1.535 -0.5 -1.469 c
+-0.411 -1.4 -0.345 -1.282 -0.293 -1.117 c
+-0.205 -0.779 l
+-1.072 2.176 l
+-0.544 2.176 l
+h
+1.239 0.823 m
+1.239 1.253 1.342 1.595 1.548 1.852 c
+1.761 2.106 2.04 2.234 2.386 2.234 c
+2.727 2.234 3.003 2.106 3.209 1.852 c
+3.422 1.606 3.535 1.272 3.547 0.853 c
+3.547 0.545 l
+3.547 0.111 3.437 -0.231 3.223 -0.484 c
+3.018 -0.742 2.739 -0.866 2.386 -0.866 c
+2.04 -0.866 1.768 -0.746 1.563 -0.5 c
+1.357 -0.257 1.247 0.077 1.239 0.5 c
+h
+1.724 0.545 m
+1.724 0.229 1.783 -0.014 1.9 -0.191 c
+2.025 -0.359 2.187 -0.44 2.386 -0.44 c
+2.816 -0.44 3.04 -0.132 3.061 0.485 c
+3.061 0.823 l
+3.061 1.125 2.995 1.368 2.87 1.544 c
+2.753 1.721 2.591 1.808 2.386 1.808 c
+2.187 1.808 2.025 1.721 1.9 1.544 c
+1.783 1.368 1.724 1.125 1.724 0.823 c
+h
+5.501 -0.544 m
+5.343 -0.76 5.108 -0.866 4.796 -0.866 c
+4.532 -0.866 4.326 -0.775 4.179 -0.588 c
+4.039 -0.404 3.973 -0.128 3.973 0.235 c
+3.973 2.176 l
+4.458 2.176 l
+4.458 0.265 l
+4.458 -0.199 4.597 -0.426 4.884 -0.426 c
+5.178 -0.426 5.376 -0.294 5.486 -0.029 c
+5.486 2.176 l
+5.987 2.176 l
+5.987 -0.808 l
+5.517 -0.808 l
+h
+7.641 0.823 m
+7.641 1.283 7.722 1.632 7.89 1.867 c
+8.067 2.11 8.316 2.234 8.64 2.234 c
+8.923 2.234 9.143 2.117 9.301 1.881 c
+9.301 3.425 l
+9.787 3.425 l
+9.787 -0.808 l
+9.345 -0.808 l
+9.316 -0.484 l
+9.158 -0.742 8.934 -0.866 8.64 -0.866 c
+8.324 -0.866 8.081 -0.749 7.905 -0.514 c
+7.728 -0.272 7.641 0.074 7.641 0.515 c
+h
+8.125 0.545 m
+8.125 0.21 8.173 -0.037 8.272 -0.191 c
+8.368 -0.349 8.53 -0.426 8.757 -0.426 c
+9 -0.426 9.184 -0.309 9.301 -0.073 c
+9.301 1.441 l
+9.172 1.676 8.993 1.794 8.757 1.794 c
+8.53 1.794 8.368 1.713 8.272 1.559 c
+8.173 1.401 8.125 1.162 8.125 0.838 c
+h
+10.253 0.823 m
+10.253 1.253 10.356 1.595 10.562 1.852 c
+10.775 2.106 11.054 2.234 11.4 2.234 c
+11.741 2.234 12.017 2.106 12.223 1.852 c
+12.436 1.606 12.549 1.272 12.561 0.853 c
+12.561 0.545 l
+12.561 0.111 12.451 -0.231 12.237 -0.484 c
+12.032 -0.742 11.753 -0.866 11.4 -0.866 c
+11.054 -0.866 10.782 -0.746 10.577 -0.5 c
+10.371 -0.257 10.261 0.077 10.253 0.5 c
+h
+10.739 0.545 m
+10.739 0.229 10.797 -0.014 10.914 -0.191 c
+11.04 -0.359 11.201 -0.44 11.4 -0.44 c
+11.83 -0.44 12.054 -0.132 12.075 0.485 c
+12.075 0.823 l
+12.075 1.125 12.01 1.368 11.884 1.544 c
+11.767 1.721 11.605 1.808 11.4 1.808 c
+11.201 1.808 11.04 1.721 10.914 1.544 c
+10.797 1.368 10.739 1.125 10.739 0.823 c
+h
+13.457 2.176 m
+13.472 1.852 l
+13.656 2.106 13.899 2.234 14.192 2.234 c
+14.722 2.234 14.99 1.881 15.001 1.176 c
+15.001 -0.808 l
+14.516 -0.808 l
+14.516 1.147 l
+14.516 1.382 14.475 1.548 14.398 1.646 c
+14.317 1.742 14.2 1.794 14.045 1.794 c
+13.928 1.794 13.818 1.754 13.722 1.676 c
+13.623 1.595 13.546 1.488 13.486 1.353 c
+13.486 -0.808 l
+13.002 -0.808 l
+13.002 2.176 l
+h
+15.607 3.117 m
+15.563 2.103 l
+15.196 2.103 l
+15.21 3.425 l
+15.607 3.425 l
+h
+16.831 2.897 m
+16.831 2.176 l
+17.286 2.176 l
+17.286 1.779 l
+16.831 1.779 l
+16.831 -0.073 l
+16.831 -0.191 16.85 -0.278 16.89 -0.338 c
+16.927 -0.396 16.996 -0.426 17.095 -0.426 c
+17.154 -0.426 17.216 -0.419 17.286 -0.396 c
+17.286 -0.808 l
+17.169 -0.845 17.055 -0.866 16.948 -0.866 c
+16.75 -0.866 16.599 -0.801 16.493 -0.661 c
+16.393 -0.525 16.345 -0.33 16.345 -0.073 c
+16.345 1.779 l
+15.89 1.779 l
+15.89 2.176 l
+16.345 2.176 l
+16.345 2.897 l
+h
+21.178 0.044 m
+21.634 2.176 l
+22.119 2.176 l
+21.384 -0.808 l
+21.002 -0.808 l
+20.414 1.324 l
+19.84 -0.808 l
+19.458 -0.808 l
+18.724 2.176 l
+19.208 2.176 l
+19.678 0.103 l
+20.223 2.176 l
+20.605 2.176 l
+h
+23.912 -0.808 m
+23.883 -0.742 23.861 -0.631 23.853 -0.484 c
+23.677 -0.742 23.456 -0.866 23.192 -0.866 c
+22.917 -0.866 22.699 -0.793 22.545 -0.646 c
+22.398 -0.492 22.325 -0.276 22.325 0 c
+22.325 0.302 22.427 0.545 22.633 0.721 c
+22.839 0.904 23.122 1 23.486 1 c
+23.838 1 l
+23.838 1.324 l
+23.838 1.5 23.798 1.621 23.721 1.691 c
+23.64 1.768 23.522 1.808 23.368 1.808 c
+23.221 1.808 23.096 1.764 23.001 1.676 c
+22.913 1.588 22.868 1.478 22.868 1.353 c
+22.383 1.353 l
+22.383 1.5 22.427 1.64 22.516 1.779 c
+22.604 1.926 22.722 2.036 22.868 2.117 c
+23.023 2.194 23.196 2.234 23.383 2.234 c
+23.695 2.234 23.931 2.153 24.089 1.999 c
+24.243 1.852 24.324 1.632 24.324 1.338 c
+24.324 -0.161 l
+24.331 -0.396 24.368 -0.598 24.426 -0.764 c
+24.426 -0.808 l
+h
+23.265 -0.426 m
+23.383 -0.426 23.493 -0.393 23.603 -0.323 c
+23.71 -0.257 23.788 -0.172 23.838 -0.073 c
+23.838 0.632 l
+23.574 0.632 l
+23.339 0.632 23.152 0.581 23.015 0.485 c
+22.887 0.387 22.824 0.243 22.824 0.059 c
+22.824 -0.11 22.853 -0.231 22.913 -0.309 c
+22.979 -0.389 23.096 -0.426 23.265 -0.426 c
+25.36 2.176 m
+25.375 1.852 l
+25.558 2.106 25.801 2.234 26.095 2.234 c
+26.624 2.234 26.892 1.881 26.903 1.176 c
+26.903 -0.808 l
+26.418 -0.808 l
+26.418 1.147 l
+26.418 1.382 26.378 1.548 26.301 1.646 c
+26.22 1.742 26.103 1.794 25.948 1.794 c
+25.831 1.794 25.72 1.754 25.625 1.676 c
+25.525 1.595 25.448 1.488 25.39 1.353 c
+25.39 -0.808 l
+24.904 -0.808 l
+24.904 2.176 l
+h
+28.091 2.897 m
+28.091 2.176 l
+28.546 2.176 l
+28.546 1.779 l
+28.091 1.779 l
+28.091 -0.073 l
+28.091 -0.191 28.108 -0.278 28.149 -0.338 c
+28.185 -0.396 28.256 -0.426 28.355 -0.426 c
+28.414 -0.426 28.476 -0.419 28.546 -0.396 c
+28.546 -0.808 l
+28.428 -0.845 28.314 -0.866 28.208 -0.866 c
+28.01 -0.866 27.859 -0.801 27.752 -0.661 c
+27.653 -0.525 27.605 -0.33 27.605 -0.073 c
+27.605 1.779 l
+27.15 1.779 l
+27.15 2.176 l
+27.605 2.176 l
+27.605 2.897 l
+h
+30.847 2.897 m
+30.847 2.176 l
+31.302 2.176 l
+31.302 1.779 l
+30.847 1.779 l
+30.847 -0.073 l
+30.847 -0.191 30.865 -0.278 30.905 -0.338 c
+30.942 -0.396 31.012 -0.426 31.111 -0.426 c
+31.17 -0.426 31.233 -0.419 31.302 -0.396 c
+31.302 -0.808 l
+31.185 -0.845 31.071 -0.866 30.964 -0.866 c
+30.766 -0.866 30.615 -0.801 30.508 -0.661 c
+30.409 -0.525 30.362 -0.33 30.362 -0.073 c
+30.362 1.779 l
+29.906 1.779 l
+29.906 2.176 l
+30.362 2.176 l
+30.362 2.897 l
+h
+31.615 0.823 m
+31.615 1.253 31.717 1.595 31.923 1.852 c
+32.137 2.106 32.416 2.234 32.761 2.234 c
+33.103 2.234 33.378 2.106 33.584 1.852 c
+33.797 1.606 33.911 1.272 33.922 0.853 c
+33.922 0.545 l
+33.922 0.111 33.812 -0.231 33.599 -0.484 c
+33.393 -0.742 33.114 -0.866 32.761 -0.866 c
+32.416 -0.866 32.143 -0.746 31.938 -0.5 c
+31.732 -0.257 31.622 0.077 31.615 0.5 c
+h
+32.1 0.545 m
+32.1 0.229 32.158 -0.014 32.276 -0.191 c
+32.401 -0.359 32.563 -0.44 32.761 -0.44 c
+33.191 -0.44 33.415 -0.132 33.437 0.485 c
+33.437 0.823 l
+33.437 1.125 33.371 1.368 33.246 1.544 c
+33.128 1.721 32.966 1.808 32.761 1.808 c
+32.563 1.808 32.401 1.721 32.276 1.544 c
+32.158 1.368 32.1 1.125 32.1 0.823 c
+h
+36.094 -0.808 -0.501 2.984 re
+36.124 2.97 m
+36.124 2.881 36.098 2.808 36.05 2.749 c
+36.01 2.698 35.94 2.675 35.844 2.675 c
+35.756 2.675 35.686 2.698 35.638 2.749 c
+35.598 2.808 35.58 2.874 35.58 2.955 c
+35.58 3.043 35.598 3.117 35.638 3.175 c
+35.686 3.234 35.756 3.263 35.844 3.263 c
+35.94 3.263 36.01 3.234 36.05 3.175 c
+36.098 3.117 36.124 3.047 36.124 2.97 c
+37.226 2.176 m
+37.24 1.852 l
+37.425 2.106 37.667 2.234 37.961 2.234 c
+38.49 2.234 38.758 1.881 38.769 1.176 c
+38.769 -0.808 l
+38.284 -0.808 l
+38.284 1.147 l
+38.284 1.382 38.244 1.548 38.167 1.646 c
+38.086 1.742 37.968 1.794 37.814 1.794 c
+37.696 1.794 37.586 1.754 37.49 1.676 c
+37.392 1.595 37.315 1.488 37.255 1.353 c
+37.255 -0.808 l
+36.77 -0.808 l
+36.77 2.176 l
+h
+40.349 -0.44 m
+40.515 -0.44 40.648 -0.393 40.746 -0.294 c
+40.842 -0.199 40.897 -0.055 40.908 0.133 c
+41.363 0.133 l
+41.353 -0.154 41.25 -0.393 41.055 -0.588 c
+40.868 -0.775 40.632 -0.866 40.349 -0.866 c
+39.985 -0.866 39.707 -0.749 39.511 -0.514 c
+39.314 -0.278 39.218 0.067 39.218 0.53 c
+39.218 0.853 l
+39.218 1.301 39.31 1.646 39.497 1.881 c
+39.692 2.117 39.975 2.234 40.349 2.234 c
+40.65 2.234 40.893 2.135 41.07 1.941 c
+41.253 1.742 41.353 1.478 41.363 1.147 c
+40.908 1.147 l
+40.885 1.371 40.827 1.536 40.731 1.646 c
+40.644 1.754 40.515 1.808 40.349 1.808 c
+40.133 1.808 39.971 1.735 39.864 1.588 c
+39.765 1.448 39.71 1.22 39.703 0.897 c
+39.703 0.515 l
+39.703 0.162 39.75 -0.087 39.85 -0.235 c
+39.956 -0.374 40.122 -0.44 40.349 -0.44 c
+42.29 -0.808 -0.5 4.233 re
+44.476 -0.544 m
+44.318 -0.76 44.083 -0.866 43.771 -0.866 c
+43.506 -0.866 43.3 -0.775 43.154 -0.588 c
+43.013 -0.404 42.948 -0.128 42.948 0.235 c
+42.948 2.176 l
+43.432 2.176 l
+43.432 0.265 l
+43.432 -0.199 43.572 -0.426 43.859 -0.426 c
+44.153 -0.426 44.351 -0.294 44.461 -0.029 c
+44.461 2.176 l
+44.961 2.176 l
+44.961 -0.808 l
+44.49 -0.808 l
+h
+45.413 0.823 m
+45.413 1.283 45.494 1.632 45.664 1.867 c
+45.839 2.11 46.09 2.234 46.412 2.234 c
+46.696 2.234 46.917 2.117 47.075 1.881 c
+47.075 3.425 l
+47.559 3.425 l
+47.559 -0.808 l
+47.118 -0.808 l
+47.089 -0.484 l
+46.931 -0.742 46.707 -0.866 46.412 -0.866 c
+46.096 -0.866 45.855 -0.749 45.678 -0.514 c
+45.502 -0.272 45.413 0.074 45.413 0.515 c
+h
+45.899 0.545 m
+45.899 0.21 45.946 -0.037 46.045 -0.191 c
+46.14 -0.349 46.302 -0.426 46.53 -0.426 c
+46.773 -0.426 46.957 -0.309 47.075 -0.073 c
+47.075 1.441 l
+46.946 1.676 46.765 1.794 46.53 1.794 c
+46.302 1.794 46.14 1.713 46.045 1.559 c
+45.946 1.401 45.899 1.162 45.899 0.838 c
+h
+49.188 -0.866 m
+48.812 -0.866 48.529 -0.76 48.334 -0.544 c
+48.136 -0.319 48.041 0.008 48.041 0.441 c
+48.041 0.809 l
+48.041 1.25 48.133 1.595 48.32 1.852 c
+48.515 2.106 48.791 2.234 49.143 2.234 c
+49.485 2.234 49.739 2.12 49.907 1.897 c
+50.084 1.669 50.175 1.324 50.187 0.853 c
+50.187 0.545 l
+48.525 0.545 l
+48.525 0.47 l
+48.525 0.148 48.585 -0.087 48.702 -0.235 c
+48.82 -0.374 48.989 -0.44 49.217 -0.44 c
+49.363 -0.44 49.489 -0.419 49.599 -0.367 c
+49.705 -0.309 49.808 -0.22 49.907 -0.103 c
+50.157 -0.411 l
+49.951 -0.716 49.628 -0.866 49.188 -0.866 c
+49.143 1.808 m
+48.937 1.808 48.783 1.738 48.687 1.603 c
+48.588 1.463 48.533 1.25 48.525 0.956 c
+49.701 0.956 l
+49.701 1.029 l
+49.68 1.301 49.628 1.5 49.54 1.617 c
+49.452 1.742 49.319 1.808 49.143 1.808 c
+50.628 -0.544 m
+50.628 -0.455 50.649 -0.382 50.701 -0.323 c
+50.76 -0.264 50.838 -0.235 50.936 -0.235 c
+51.043 -0.235 51.12 -0.264 51.172 -0.323 c
+51.231 -0.382 51.26 -0.455 51.26 -0.544 c
+51.26 -0.625 51.231 -0.691 51.172 -0.749 c
+51.12 -0.808 51.043 -0.837 50.936 -0.837 c
+50.838 -0.837 50.76 -0.808 50.701 -0.749 c
+50.649 -0.691 50.628 -0.625 50.628 -0.544 c
+f
+Q
+ endstream endobj 60 0 obj <</BBox[733.061 286.676 768.669 281.238]/Group 98 0 R/Length 5722/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 735.7654 284.1042 cm
+0 0 m
+0 -0.551 -0.118 -0.977 -0.353 -1.278 c
+-0.588 -1.573 -0.919 -1.72 -1.338 -1.72 c
+-1.76 -1.72 -2.095 -1.58 -2.338 -1.294 c
+-2.573 -0.999 -2.697 -0.588 -2.705 -0.058 c
+-2.705 0.69 l
+-2.705 1.228 -2.587 1.65 -2.352 1.955 c
+-2.109 2.257 -1.775 2.411 -1.353 2.411 c
+-0.933 2.411 -0.603 2.263 -0.368 1.97 c
+-0.133 1.675 -0.011 1.257 0 0.721 c
+h
+-0.5 0.69 m
+-0.5 1.121 -0.573 1.44 -0.721 1.646 c
+-0.86 1.852 -1.07 1.955 -1.353 1.955 c
+-1.628 1.955 -1.837 1.845 -1.984 1.631 c
+-2.124 1.426 -2.19 1.118 -2.19 0.706 c
+-2.19 0 l
+-2.19 -0.411 -2.124 -0.727 -1.984 -0.941 c
+-1.837 -1.157 -1.628 -1.264 -1.353 -1.264 c
+-1.07 -1.264 -0.86 -1.168 -0.721 -0.97 c
+-0.584 -0.775 -0.511 -0.47 -0.5 -0.058 c
+h
+0.948 1.323 m
+0.962 1 l
+1.147 1.253 1.389 1.382 1.683 1.382 c
+2.212 1.382 2.481 1.029 2.491 0.324 c
+2.491 -1.661 l
+2.007 -1.661 l
+2.007 0.294 l
+2.007 0.53 1.966 0.694 1.889 0.794 c
+1.808 0.889 1.69 0.941 1.536 0.941 c
+1.419 0.941 1.309 0.9 1.213 0.823 c
+1.113 0.742 1.036 0.636 0.977 0.5 c
+0.977 -1.661 l
+0.492 -1.661 l
+0.492 1.323 l
+h
+3.572 -1.661 -0.5 4.233 re
+5.056 -0.852 m
+5.6 1.323 l
+6.115 1.323 l
+5.145 -2.088 l
+5.074 -2.341 4.972 -2.532 4.836 -2.66 c
+4.696 -2.797 4.546 -2.866 4.38 -2.866 c
+4.31 -2.866 4.226 -2.851 4.131 -2.822 c
+4.131 -2.41 l
+4.233 -2.425 l
+4.369 -2.425 4.476 -2.389 4.557 -2.323 c
+4.644 -2.252 4.711 -2.135 4.762 -1.97 c
+4.85 -1.631 l
+3.983 1.323 l
+4.513 1.323 l
+h
+8.172 -1.661 -0.5 2.984 re
+8.202 2.117 m
+8.202 2.028 8.176 1.955 8.129 1.897 c
+8.089 1.845 8.018 1.823 7.923 1.823 c
+7.834 1.823 7.765 1.845 7.717 1.897 c
+7.676 1.955 7.659 2.022 7.659 2.102 c
+7.659 2.19 7.676 2.263 7.717 2.323 c
+7.765 2.381 7.834 2.411 7.923 2.411 c
+8.018 2.411 8.089 2.381 8.129 2.323 c
+8.176 2.263 8.202 2.194 8.202 2.117 c
+9.305 1.323 m
+9.319 1 l
+9.502 1.253 9.745 1.382 10.04 1.382 c
+10.568 1.382 10.836 1.029 10.848 0.324 c
+10.848 -1.661 l
+10.362 -1.661 l
+10.362 0.294 l
+10.362 0.53 10.323 0.694 10.246 0.794 c
+10.165 0.889 10.047 0.941 9.892 0.941 c
+9.775 0.941 9.664 0.9 9.569 0.823 c
+9.469 0.742 9.392 0.636 9.334 0.5 c
+9.334 -1.661 l
+8.849 -1.661 l
+8.849 1.323 l
+h
+11.296 -0.029 m
+11.296 0.43 11.377 0.779 11.546 1.014 c
+11.723 1.257 11.972 1.382 12.295 1.382 c
+12.579 1.382 12.799 1.264 12.957 1.029 c
+12.957 2.572 l
+13.442 2.572 l
+13.442 -1.661 l
+13.001 -1.661 l
+12.972 -1.338 l
+12.814 -1.595 12.59 -1.72 12.295 -1.72 c
+11.979 -1.72 11.737 -1.602 11.561 -1.367 c
+11.384 -1.124 11.296 -0.779 11.296 -0.338 c
+h
+11.781 -0.309 m
+11.781 -0.643 11.829 -0.889 11.929 -1.043 c
+12.024 -1.201 12.185 -1.278 12.413 -1.278 c
+12.656 -1.278 12.839 -1.161 12.957 -0.926 c
+12.957 0.588 l
+12.829 0.823 12.648 0.941 12.413 0.941 c
+12.185 0.941 12.024 0.86 11.929 0.706 c
+11.829 0.548 11.781 0.309 11.781 -0.015 c
+h
+15.07 -1.72 m
+14.695 -1.72 14.412 -1.613 14.217 -1.396 c
+14.019 -1.172 13.924 -0.845 13.924 -0.411 c
+13.924 -0.044 l
+13.924 0.397 14.015 0.742 14.203 1 c
+14.398 1.253 14.674 1.382 15.026 1.382 c
+15.368 1.382 15.621 1.268 15.79 1.043 c
+15.967 0.816 16.058 0.47 16.07 0 c
+16.07 -0.309 l
+14.408 -0.309 l
+14.408 -0.382 l
+14.408 -0.706 14.468 -0.941 14.585 -1.087 c
+14.703 -1.228 14.871 -1.294 15.1 -1.294 c
+15.247 -1.294 15.372 -1.271 15.482 -1.22 c
+15.588 -1.161 15.692 -1.073 15.79 -0.956 c
+16.041 -1.264 l
+15.835 -1.569 15.511 -1.72 15.07 -1.72 c
+15.026 0.956 m
+14.82 0.956 14.666 0.886 14.57 0.75 c
+14.471 0.611 14.416 0.397 14.408 0.103 c
+15.584 0.103 l
+15.584 0.177 l
+15.563 0.449 15.511 0.647 15.422 0.765 c
+15.335 0.889 15.202 0.956 15.026 0.956 c
+17.334 0.235 m
+17.849 1.323 l
+18.422 1.323 l
+17.598 -0.147 l
+18.437 -1.661 l
+17.878 -1.661 l
+17.348 -0.544 l
+16.82 -1.661 l
+16.261 -1.661 l
+17.084 -0.147 l
+16.276 1.323 l
+16.834 1.323 l
+h
+22.221 -0.808 m
+22.677 1.323 l
+23.162 1.323 l
+22.427 -1.661 l
+22.044 -1.661 l
+21.456 0.47 l
+20.883 -1.661 l
+20.502 -1.661 l
+19.767 1.323 l
+20.251 1.323 l
+20.722 -0.75 l
+21.265 1.323 l
+21.648 1.323 l
+h
+23.956 -1.661 -0.5 2.984 re
+23.985 2.117 m
+23.985 2.028 23.96 1.955 23.912 1.897 c
+23.871 1.845 23.802 1.823 23.706 1.823 c
+23.617 1.823 23.548 1.845 23.5 1.897 c
+23.459 1.955 23.441 2.022 23.441 2.102 c
+23.441 2.19 23.459 2.263 23.5 2.323 c
+23.548 2.381 23.617 2.411 23.706 2.411 c
+23.802 2.411 23.871 2.381 23.912 2.323 c
+23.96 2.263 23.985 2.194 23.985 2.117 c
+25.161 -1.661 -0.5 4.233 re
+26.362 -1.661 -0.5 4.233 re
+30.405 -0.309 m
+30.405 -0.779 30.32 -1.132 30.155 -1.367 c
+29.986 -1.602 29.743 -1.72 29.42 -1.72 c
+29.104 -1.72 28.868 -1.583 28.714 -1.309 c
+28.685 -1.661 l
+28.244 -1.661 l
+28.244 2.572 l
+28.729 2.572 l
+28.729 1 l
+28.884 1.253 29.115 1.382 29.42 1.382 c
+29.743 1.382 29.986 1.264 30.155 1.029 c
+30.32 0.794 30.405 0.445 30.405 -0.015 c
+h
+29.92 -0.029 m
+29.92 0.324 29.868 0.573 29.773 0.721 c
+29.674 0.867 29.512 0.941 29.288 0.941 c
+29.042 0.941 28.854 0.802 28.729 0.53 c
+28.729 -0.881 l
+28.847 -1.147 29.038 -1.278 29.302 -1.278 c
+29.516 -1.278 29.674 -1.205 29.773 -1.058 c
+29.868 -0.904 29.92 -0.661 29.92 -0.338 c
+h
+31.904 -1.72 m
+31.529 -1.72 31.247 -1.613 31.052 -1.396 c
+30.853 -1.172 30.757 -0.845 30.757 -0.411 c
+30.757 -0.044 l
+30.757 0.397 30.85 0.742 31.037 1 c
+31.232 1.253 31.507 1.382 31.86 1.382 c
+32.201 1.382 32.456 1.268 32.625 1.043 c
+32.801 0.816 32.893 0.47 32.903 0 c
+32.903 -0.309 l
+31.243 -0.309 l
+31.243 -0.382 l
+31.243 -0.706 31.301 -0.941 31.419 -1.087 c
+31.536 -1.228 31.706 -1.294 31.933 -1.294 c
+32.08 -1.294 32.205 -1.271 32.315 -1.22 c
+32.423 -1.161 32.525 -1.073 32.625 -0.956 c
+32.874 -1.264 l
+32.668 -1.569 32.345 -1.72 31.904 -1.72 c
+31.86 0.956 m
+31.654 0.956 31.5 0.886 31.405 0.75 c
+31.305 0.611 31.25 0.397 31.243 0.103 c
+32.419 0.103 l
+32.419 0.177 l
+32.396 0.449 32.345 0.647 32.257 0.765 c
+32.169 0.889 32.037 0.956 31.86 0.956 c
+f
+Q
+ endstream endobj 61 0 obj <</BBox[739.087 280.091 762.253 275.799]/Group 99 0 R/Length 5385/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 740.2189 276.2256 cm
+0 0 m
+0.166 0 0.298 0.048 0.397 0.147 c
+0.493 0.243 0.547 0.386 0.559 0.573 c
+1.014 0.573 l
+1.004 0.287 0.9 0.048 0.706 -0.147 c
+0.518 -0.334 0.283 -0.426 0 -0.426 c
+-0.363 -0.426 -0.643 -0.309 -0.837 -0.073 c
+-1.036 0.162 -1.132 0.507 -1.132 0.97 c
+-1.132 1.294 l
+-1.132 1.742 -1.04 2.087 -0.852 2.323 c
+-0.658 2.558 -0.374 2.675 0 2.675 c
+0.302 2.675 0.544 2.576 0.721 2.381 c
+0.904 2.182 1.004 1.918 1.014 1.588 c
+0.559 1.588 l
+0.537 1.812 0.478 1.977 0.383 2.087 c
+0.294 2.194 0.166 2.249 0 2.249 c
+-0.216 2.249 -0.378 2.176 -0.484 2.028 c
+-0.584 1.889 -0.639 1.661 -0.646 1.338 c
+-0.646 0.956 l
+-0.646 0.603 -0.598 0.353 -0.5 0.206 c
+-0.393 0.066 -0.228 0 0 0 c
+1.309 1.264 m
+1.309 1.694 1.411 2.036 1.617 2.294 c
+1.831 2.547 2.109 2.675 2.455 2.675 c
+2.797 2.675 3.072 2.547 3.278 2.294 c
+3.491 2.047 3.605 1.712 3.616 1.294 c
+3.616 0.985 l
+3.616 0.551 3.506 0.21 3.293 -0.044 c
+3.087 -0.301 2.808 -0.426 2.455 -0.426 c
+2.109 -0.426 1.837 -0.305 1.632 -0.058 c
+1.426 0.183 1.316 0.518 1.309 0.941 c
+h
+1.794 0.985 m
+1.794 0.669 1.852 0.426 1.97 0.25 c
+2.095 0.081 2.257 0 2.455 0 c
+2.885 0 3.109 0.309 3.131 0.926 c
+3.131 1.264 l
+3.131 1.565 3.065 1.808 2.94 1.984 c
+2.822 2.161 2.66 2.249 2.455 2.249 c
+2.257 2.249 2.095 2.161 1.97 1.984 c
+1.852 1.808 1.794 1.565 1.794 1.264 c
+h
+4.509 2.616 m
+4.524 2.337 l
+4.7 2.562 4.939 2.675 5.244 2.675 c
+5.575 2.675 5.806 2.529 5.935 2.234 c
+6.119 2.529 6.379 2.675 6.714 2.675 c
+7.273 2.675 7.555 2.33 7.566 1.646 c
+7.566 -0.368 l
+7.082 -0.368 l
+7.082 1.602 l
+7.082 1.816 7.041 1.974 6.964 2.072 c
+6.883 2.18 6.751 2.234 6.567 2.234 c
+6.42 2.234 6.302 2.176 6.215 2.058 c
+6.126 1.947 6.071 1.808 6.053 1.631 c
+6.053 -0.368 l
+5.567 -0.368 l
+5.567 1.617 l
+5.557 2.028 5.384 2.234 5.053 2.234 c
+4.807 2.234 4.634 2.109 4.538 1.866 c
+4.538 -0.368 l
+4.054 -0.368 l
+4.054 2.616 l
+h
+8.47 2.616 m
+8.485 2.337 l
+8.661 2.562 8.9 2.675 9.205 2.675 c
+9.536 2.675 9.768 2.529 9.897 2.234 c
+10.08 2.529 10.341 2.675 10.675 2.675 c
+11.234 2.675 11.516 2.33 11.528 1.646 c
+11.528 -0.368 l
+11.043 -0.368 l
+11.043 1.602 l
+11.043 1.816 11.003 1.974 10.926 2.072 c
+10.845 2.18 10.712 2.234 10.529 2.234 c
+10.381 2.234 10.263 2.176 10.176 2.058 c
+10.088 1.947 10.032 1.808 10.014 1.631 c
+10.014 -0.368 l
+9.529 -0.368 l
+9.529 1.617 l
+9.517 2.028 9.345 2.234 9.014 2.234 c
+8.769 2.234 8.596 2.109 8.5 1.866 c
+8.5 -0.368 l
+8.015 -0.368 l
+8.015 2.616 l
+h
+12.505 -0.368 -0.499 2.984 re
+12.534 3.41 m
+12.534 3.322 12.509 3.248 12.461 3.19 c
+12.421 3.138 12.351 3.117 12.256 3.117 c
+12.168 3.117 12.098 3.138 12.05 3.19 c
+12.009 3.248 11.991 3.315 11.991 3.395 c
+11.991 3.484 12.009 3.557 12.05 3.616 c
+12.098 3.674 12.168 3.705 12.256 3.705 c
+12.351 3.705 12.421 3.674 12.461 3.616 c
+12.509 3.557 12.534 3.487 12.534 3.41 c
+13.814 3.337 m
+13.814 2.616 l
+14.269 2.616 l
+14.269 2.219 l
+13.814 2.219 l
+13.814 0.368 l
+13.814 0.25 13.832 0.162 13.872 0.103 c
+13.909 0.044 13.979 0.015 14.078 0.015 c
+14.137 0.015 14.199 0.023 14.269 0.044 c
+14.269 -0.368 l
+14.151 -0.405 14.038 -0.426 13.931 -0.426 c
+13.733 -0.426 13.582 -0.36 13.475 -0.22 c
+13.376 -0.085 13.328 0.11 13.328 0.368 c
+13.328 2.219 l
+12.873 2.219 l
+12.873 2.616 l
+13.328 2.616 l
+13.328 3.337 l
+h
+15.368 3.337 m
+15.368 2.616 l
+15.824 2.616 l
+15.824 2.219 l
+15.368 2.219 l
+15.368 0.368 l
+15.368 0.25 15.387 0.162 15.427 0.103 c
+15.464 0.044 15.534 0.015 15.632 0.015 c
+15.691 0.015 15.754 0.023 15.824 0.044 c
+15.824 -0.368 l
+15.707 -0.405 15.592 -0.426 15.485 -0.426 c
+15.287 -0.426 15.136 -0.36 15.03 -0.22 c
+14.93 -0.085 14.883 0.11 14.883 0.368 c
+14.883 2.219 l
+14.427 2.219 l
+14.427 2.616 l
+14.883 2.616 l
+14.883 3.337 l
+h
+17.345 -0.426 m
+16.97 -0.426 16.688 -0.32 16.492 -0.103 c
+16.294 0.121 16.199 0.449 16.199 0.882 c
+16.199 1.249 l
+16.199 1.691 16.291 2.036 16.478 2.294 c
+16.673 2.547 16.948 2.675 17.301 2.675 c
+17.643 2.675 17.897 2.562 18.065 2.337 c
+18.242 2.109 18.334 1.764 18.344 1.294 c
+18.344 0.985 l
+16.684 0.985 l
+16.684 0.912 l
+16.684 0.588 16.742 0.353 16.86 0.206 c
+16.977 0.066 17.147 0 17.374 0 c
+17.521 0 17.646 0.023 17.756 0.073 c
+17.864 0.133 17.966 0.22 18.065 0.338 c
+18.315 0.029 l
+18.109 -0.276 17.786 -0.426 17.345 -0.426 c
+17.301 2.249 m
+17.095 2.249 16.941 2.18 16.846 2.043 c
+16.746 1.904 16.691 1.691 16.684 1.396 c
+17.86 1.396 l
+17.86 1.47 l
+17.837 1.742 17.786 1.941 17.698 2.058 c
+17.61 2.182 17.477 2.249 17.301 2.249 c
+18.653 1.264 m
+18.653 1.723 18.734 2.072 18.903 2.308 c
+19.079 2.55 19.329 2.675 19.653 2.675 c
+19.936 2.675 20.156 2.558 20.314 2.323 c
+20.314 3.865 l
+20.8 3.865 l
+20.8 -0.368 l
+20.359 -0.368 l
+20.329 -0.044 l
+20.171 -0.301 19.946 -0.426 19.653 -0.426 c
+19.337 -0.426 19.094 -0.309 18.918 -0.073 c
+18.741 0.169 18.653 0.515 18.653 0.956 c
+h
+19.138 0.985 m
+19.138 0.651 19.186 0.405 19.285 0.25 c
+19.381 0.092 19.543 0.015 19.771 0.015 c
+20.013 0.015 20.197 0.133 20.314 0.368 c
+20.314 1.881 l
+20.185 2.117 20.006 2.234 19.771 2.234 c
+19.543 2.234 19.381 2.153 19.285 1.999 c
+19.186 1.841 19.138 1.602 19.138 1.278 c
+h
+21.402 -0.103 m
+21.402 -0.015 21.424 0.059 21.475 0.118 c
+21.534 0.177 21.612 0.206 21.71 0.206 c
+21.818 0.206 21.895 0.177 21.946 0.118 c
+22.005 0.059 22.034 -0.015 22.034 -0.103 c
+22.034 -0.183 22.005 -0.25 21.946 -0.309 c
+21.895 -0.368 21.818 -0.397 21.71 -0.397 c
+21.612 -0.397 21.534 -0.368 21.475 -0.309 c
+21.424 -0.25 21.402 -0.183 21.402 -0.103 c
+f
+Q
+ endstream endobj 62 0 obj <</BBox[736.166 273.506 765.648 268.067]/Group 100 0 R/Length 6993/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+q 1 0 0 1 738.7823 270.5519 cm
+0 0 m
+-0.029 -0.434 -0.154 -0.765 -0.368 -1 c
+-0.584 -1.228 -0.893 -1.338 -1.294 -1.338 c
+-1.698 -1.338 -2.022 -1.187 -2.263 -0.882 c
+-2.499 -0.57 -2.616 -0.154 -2.616 0.367 c
+-2.616 1.103 l
+-2.616 1.621 -2.495 2.032 -2.249 2.337 c
+-2.007 2.639 -1.672 2.793 -1.249 2.793 c
+-0.867 2.793 -0.57 2.675 -0.353 2.44 c
+-0.14 2.205 -0.023 1.87 0 1.44 c
+-0.515 1.44 l
+-0.536 1.771 -0.603 2.007 -0.721 2.146 c
+-0.838 2.282 -1.014 2.352 -1.249 2.352 c
+-1.525 2.352 -1.735 2.242 -1.881 2.028 c
+-2.028 1.812 -2.102 1.5 -2.102 1.087 c
+-2.102 0.353 l
+-2.102 -0.052 -2.036 -0.36 -1.897 -0.574 c
+-1.76 -0.79 -1.558 -0.897 -1.294 -0.897 c
+-1.029 -0.897 -0.846 -0.834 -0.735 -0.706 c
+-0.617 -0.58 -0.544 -0.345 -0.515 0 c
+h
+0.881 1.396 m
+1.066 1.639 1.301 1.764 1.587 1.764 c
+2.117 1.764 2.385 1.411 2.396 0.706 c
+2.396 -1.279 l
+1.911 -1.279 l
+1.911 0.676 l
+1.911 0.912 1.87 1.076 1.793 1.176 c
+1.712 1.271 1.594 1.323 1.44 1.323 c
+1.323 1.323 1.213 1.282 1.117 1.205 c
+1.018 1.124 0.941 1.018 0.881 0.881 c
+0.881 -1.279 l
+0.397 -1.279 l
+0.397 2.954 l
+0.881 2.954 l
+h
+2.837 0.353 m
+2.837 0.783 2.94 1.124 3.146 1.382 c
+3.358 1.635 3.638 1.764 3.983 1.764 c
+4.326 1.764 4.601 1.635 4.806 1.382 c
+5.02 1.135 5.134 0.801 5.145 0.382 c
+5.145 0.073 l
+5.145 -0.36 5.034 -0.702 4.821 -0.956 c
+4.615 -1.213 4.336 -1.338 3.983 -1.338 c
+3.638 -1.338 3.366 -1.216 3.16 -0.97 c
+2.955 -0.728 2.844 -0.393 2.837 0.029 c
+h
+3.322 0.073 m
+3.322 -0.243 3.381 -0.485 3.499 -0.661 c
+3.623 -0.831 3.785 -0.912 3.983 -0.912 c
+4.413 -0.912 4.638 -0.603 4.659 0.014 c
+4.659 0.353 l
+4.659 0.654 4.594 0.897 4.469 1.072 c
+4.351 1.249 4.189 1.338 3.983 1.338 c
+3.785 1.338 3.623 1.249 3.499 1.072 c
+3.381 0.897 3.322 0.654 3.322 0.353 c
+h
+5.479 0.353 m
+5.479 0.783 5.582 1.124 5.787 1.382 c
+6.001 1.635 6.28 1.764 6.626 1.764 c
+6.967 1.764 7.243 1.635 7.449 1.382 c
+7.661 1.135 7.776 0.801 7.786 0.382 c
+7.786 0.073 l
+7.786 -0.36 7.676 -0.702 7.464 -0.956 c
+7.258 -1.213 6.978 -1.338 6.626 -1.338 c
+6.28 -1.338 6.008 -1.216 5.802 -0.97 c
+5.596 -0.728 5.486 -0.393 5.479 0.029 c
+h
+5.964 0.073 m
+5.964 -0.243 6.023 -0.485 6.14 -0.661 c
+6.265 -0.831 6.427 -0.912 6.626 -0.912 c
+7.056 -0.912 7.279 -0.603 7.302 0.014 c
+7.302 0.353 l
+7.302 0.654 7.235 0.897 7.11 1.072 c
+6.993 1.249 6.832 1.338 6.626 1.338 c
+6.427 1.338 6.265 1.249 6.14 1.072 c
+6.023 0.897 5.964 0.654 5.964 0.353 c
+h
+9.668 -0.515 m
+9.668 -0.408 9.628 -0.32 9.55 -0.25 c
+9.469 -0.173 9.319 -0.085 9.095 0.014 c
+8.831 0.121 8.643 0.213 8.536 0.294 c
+8.426 0.371 8.349 0.459 8.301 0.559 c
+8.249 0.654 8.228 0.771 8.228 0.912 c
+8.228 1.153 8.316 1.356 8.492 1.514 c
+8.669 1.679 8.893 1.764 9.168 1.764 c
+9.462 1.764 9.697 1.675 9.874 1.5 c
+10.051 1.33 10.138 1.117 10.138 0.852 c
+9.654 0.852 l
+9.654 0.989 9.602 1.103 9.506 1.19 c
+9.419 1.286 9.305 1.338 9.168 1.338 c
+9.022 1.338 8.908 1.297 8.831 1.22 c
+8.75 1.151 8.713 1.051 8.713 0.926 c
+8.713 0.827 8.742 0.75 8.801 0.691 c
+8.86 0.632 8.999 0.551 9.227 0.455 c
+9.587 0.309 9.833 0.166 9.962 0.029 c
+10.098 -0.1 10.167 -0.272 10.167 -0.485 c
+10.167 -0.742 10.072 -0.948 9.889 -1.103 c
+9.712 -1.261 9.477 -1.338 9.183 -1.338 c
+8.867 -1.338 8.613 -1.249 8.419 -1.073 c
+8.232 -0.889 8.139 -0.658 8.139 -0.382 c
+8.625 -0.382 l
+8.632 -0.551 8.683 -0.684 8.771 -0.779 c
+8.867 -0.867 9.007 -0.912 9.183 -0.912 c
+9.338 -0.912 9.455 -0.879 9.536 -0.809 c
+9.624 -0.742 9.668 -0.643 9.668 -0.515 c
+11.682 -1.338 m
+11.307 -1.338 11.025 -1.231 10.83 -1.014 c
+10.631 -0.79 10.535 -0.463 10.535 -0.029 c
+10.535 0.338 l
+10.535 0.779 10.628 1.124 10.815 1.382 c
+11.009 1.635 11.285 1.764 11.638 1.764 c
+11.979 1.764 12.233 1.65 12.403 1.425 c
+12.579 1.198 12.671 0.852 12.681 0.382 c
+12.681 0.073 l
+11.021 0.073 l
+11.021 0 l
+11.021 -0.324 11.079 -0.559 11.197 -0.706 c
+11.314 -0.846 11.484 -0.912 11.711 -0.912 c
+11.858 -0.912 11.983 -0.889 12.093 -0.838 c
+12.2 -0.779 12.303 -0.691 12.403 -0.574 c
+12.652 -0.882 l
+12.446 -1.187 12.123 -1.338 11.682 -1.338 c
+11.638 1.338 m
+11.432 1.338 11.278 1.268 11.183 1.132 c
+11.083 0.992 11.028 0.779 11.021 0.484 c
+12.197 0.484 l
+12.197 0.559 l
+12.174 0.831 12.123 1.029 12.035 1.147 c
+11.946 1.271 11.814 1.338 11.638 1.338 c
+16.518 -0.426 m
+16.974 1.705 l
+17.458 1.705 l
+16.724 -1.279 l
+16.342 -1.279 l
+15.754 0.852 l
+15.181 -1.279 l
+14.798 -1.279 l
+14.063 1.705 l
+14.549 1.705 l
+15.019 -0.368 l
+15.563 1.705 l
+15.945 1.705 l
+h
+18.252 -1.279 -0.5 2.984 re
+18.282 2.499 m
+18.282 2.41 18.256 2.337 18.208 2.278 c
+18.168 2.227 18.098 2.205 18.003 2.205 c
+17.914 2.205 17.845 2.227 17.797 2.278 c
+17.756 2.337 17.738 2.404 17.738 2.484 c
+17.738 2.572 17.756 2.645 17.797 2.705 c
+17.845 2.763 17.914 2.793 18.003 2.793 c
+18.098 2.793 18.168 2.763 18.208 2.705 c
+18.256 2.645 18.282 2.576 18.282 2.499 c
+20.369 -0.515 m
+20.369 -0.408 20.328 -0.32 20.251 -0.25 c
+20.17 -0.173 20.02 -0.085 19.796 0.014 c
+19.532 0.121 19.343 0.213 19.237 0.294 c
+19.127 0.371 19.05 0.459 19.002 0.559 c
+18.95 0.654 18.929 0.771 18.929 0.912 c
+18.929 1.153 19.017 1.356 19.193 1.514 c
+19.37 1.679 19.594 1.764 19.869 1.764 c
+20.164 1.764 20.399 1.675 20.575 1.5 c
+20.751 1.33 20.839 1.117 20.839 0.852 c
+20.355 0.852 l
+20.355 0.989 20.303 1.103 20.207 1.19 c
+20.12 1.286 20.006 1.338 19.869 1.338 c
+19.723 1.338 19.609 1.297 19.532 1.22 c
+19.451 1.151 19.414 1.051 19.414 0.926 c
+19.414 0.827 19.443 0.75 19.502 0.691 c
+19.561 0.632 19.7 0.551 19.929 0.455 c
+20.288 0.309 20.534 0.166 20.663 0.029 c
+20.799 -0.1 20.869 -0.272 20.869 -0.485 c
+20.869 -0.742 20.773 -0.948 20.59 -1.103 c
+20.413 -1.261 20.178 -1.338 19.884 -1.338 c
+19.568 -1.338 19.314 -1.249 19.12 -1.073 c
+18.932 -0.889 18.84 -0.658 18.84 -0.382 c
+19.326 -0.382 l
+19.333 -0.551 19.384 -0.684 19.472 -0.779 c
+19.568 -0.867 19.708 -0.912 19.884 -0.912 c
+20.039 -0.912 20.156 -0.879 20.237 -0.809 c
+20.325 -0.742 20.369 -0.643 20.369 -0.515 c
+22.383 -1.338 m
+22.008 -1.338 21.725 -1.231 21.531 -1.014 c
+21.332 -0.79 21.236 -0.463 21.236 -0.029 c
+21.236 0.338 l
+21.236 0.779 21.328 1.124 21.516 1.382 c
+21.71 1.635 21.986 1.764 22.339 1.764 c
+22.68 1.764 22.934 1.65 23.103 1.425 c
+23.28 1.198 23.372 0.852 23.382 0.382 c
+23.382 0.073 l
+21.722 0.073 l
+21.722 0 l
+21.722 -0.324 21.78 -0.559 21.898 -0.706 c
+22.015 -0.846 22.185 -0.912 22.412 -0.912 c
+22.559 -0.912 22.684 -0.889 22.794 -0.838 c
+22.901 -0.779 23.004 -0.691 23.103 -0.574 c
+23.353 -0.882 l
+23.147 -1.187 22.824 -1.338 22.383 -1.338 c
+22.339 1.338 m
+22.133 1.338 21.978 1.268 21.883 1.132 c
+21.784 0.992 21.729 0.779 21.722 0.484 c
+22.898 0.484 l
+22.898 0.559 l
+22.875 0.831 22.824 1.029 22.736 1.147 c
+22.647 1.271 22.516 1.338 22.339 1.338 c
+24.323 -1.279 -0.5 4.233 re
+25.808 -0.47 m
+26.352 1.705 l
+26.866 1.705 l
+25.896 -1.706 l
+25.826 -1.959 25.724 -2.15 25.587 -2.278 c
+25.448 -2.415 25.297 -2.484 25.132 -2.484 c
+25.062 -2.484 24.978 -2.469 24.882 -2.44 c
+24.882 -2.028 l
+24.984 -2.043 l
+25.121 -2.043 25.227 -2.007 25.308 -1.941 c
+25.396 -1.87 25.462 -1.753 25.514 -1.588 c
+25.602 -1.249 l
+24.735 1.705 l
+25.264 1.705 l
+h
+f
+Q
+ endstream endobj 100 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 12 0 obj <</AIS false/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask/None/Type/ExtGState/ca 1.0/op false>> endobj 99 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 98 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 97 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 96 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 95 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 94 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 91 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 93 0 obj <</AntiAlias false/ColorSpace 92 0 R/Coords[0.0 0.0 1.0 0.0]/Domain[0.0 1.0]/Extend[true true]/Function 101 0 R/ShadingType 2>> endobj 92 0 obj [/Separation/Black/DeviceCMYK<</C0[0.0 0.0 0.0 0.0]/C1[0.0 0.0 0.0 1.0]/Domain[0 1]/FunctionType 2/N 1.0/Range[0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0]>>] endobj 101 0 obj <</Bounds[0.25 0.75]/Domain[0.0 1.0]/Encode[0.0 1.0 0.0 1.0 0.0 1.0]/FunctionType 3/Functions[102 0 R 102 0 R 102 0 R]>> endobj 102 0 obj <</C0[0.0]/C1[0.0]/Domain[0.0 1.0]/FunctionType 2/N 1.0>> endobj 90 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 89 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 88 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 87 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 86 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 85 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 84 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 83 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 82 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 81 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 80 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 79 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 78 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 77 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 76 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 75 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 74 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 73 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 72 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 71 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 70 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 69 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 68 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 67 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 66 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 65 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 63 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 64 0 obj <</AntiAlias false/ColorSpace/DeviceCMYK/Coords[0.0 0.0 1.0 0.0]/Domain[0.0 1.0]/Extend[true true]/Function 103 0 R/ShadingType 2>> endobj 103 0 obj <</Bounds[0.5]/Domain[0.0 1.0]/Encode[0.0 1.0 0.0 1.0]/FunctionType 3/Functions[104 0 R 105 0 R]>> endobj 104 0 obj <</C0[0.792969 0.800781 0.128906 0.015625]/C1[0.652344 0.660156 0.0 0.0]/Domain[0.0 1.0]/FunctionType 2/N 1.0>> endobj 105 0 obj <</C0[0.652344 0.660156 0.0 0.0]/C1[0.0 0.0 0.0 0.0]/Domain[0.0 1.0]/FunctionType 2/N 1.0>> endobj 22 0 obj <</AIS false/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask 106 0 R/Type/ExtGState/ca 1.0/op false>> endobj 23 0 obj <</AIS false/BM/Normal/CA 0.75/OP false/OPM 1/SA true/SMask/None/Type/ExtGState/ca 0.75/op false>> endobj 24 0 obj <</AIS false/BM/Normal/CA 0.899994/OP false/OPM 1/SA true/SMask/None/Type/ExtGState/ca 0.899994/op false>> endobj 25 0 obj <</AIS false/BM/Normal/CA 0.666672/OP false/OPM 1/SA true/SMask/None/Type/ExtGState/ca 0.666672/op false>> endobj 26 0 obj <</AIS false/BM/Normal/CA 0.669998/OP false/OPM 1/SA true/SMask/None/Type/ExtGState/ca 0.669998/op false>> endobj 27 0 obj <</AIS false/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask 107 0 R/Type/ExtGState/ca 1.0/op false>> endobj 107 0 obj <</BC 108 0 R/G 109 0 R/S/Luminosity/Type/Mask>> endobj 108 0 obj [0.0] endobj 109 0 obj <</BBox[320.12 122.007 531.709 116.418]/Group 110 0 R/Length 117/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>/XObject<</Fm0 111 0 R>>>>/Subtype/Form>>stream
+0 g
+/GS0 gs
+320.12 122.007 211.589 -5.589 re
+f
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0.709 w 4 M 1 j 1 J []0 d
+0 TL/Fm0 Do
+Q
+ endstream endobj 110 0 obj <</CS/DeviceGray/I false/K false/S/Transparency/Type/Group>> endobj 111 0 obj <</BBox[320.12 122.007 531.709 116.418]/Group 112 0 R/Length 126/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 113 0 R>>/ExtGState<</GS0 12 0 R>>/Shading<</Sh0 114 0 R>>>>/Subtype/Form>>stream
+q
+320.12 122.007 211.589 -5.589 re
+W n
+q
+0 g
+/GS0 gs
+212.3990173 0 0 139.9599457 319.7158203 119.2128906 cm
+BX /Sh0 sh EX Q
+Q
+ endstream endobj 112 0 obj <</CS/DeviceCMYK/I true/K false/S/Transparency/Type/Group>> endobj 114 0 obj <</AntiAlias false/ColorSpace 113 0 R/Coords[0.0 0.0 1.0 0.0]/Domain[0.0 1.0]/Extend[true true]/Function 115 0 R/ShadingType 2>> endobj 113 0 obj [/DeviceN[/Black]/DeviceCMYK 116 0 R 117 0 R] endobj 115 0 obj <</Bounds[0.25 0.75]/Domain[0.0 1.0]/Encode[0.0 1.0 0.0 1.0 0.0 1.0]/FunctionType 3/Functions[118 0 R 119 0 R 120 0 R]>> endobj 118 0 obj <</C0[1.0]/C1[0.05]/Domain[0.0 1.0]/FunctionType 2/N 1.0>> endobj 119 0 obj <</C0[0.05]/C1[0.05]/Domain[0.0 1.0]/FunctionType 2/N 1.0>> endobj 120 0 obj <</C0[0.05]/C1[1.0]/Domain[0.0 1.0]/FunctionType 2/N 1.0>> endobj 116 0 obj <</Domain[0.0 1.0]/FunctionType 4/Length 267/Range[0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0]>>stream
+{1.000000 2 1 roll 1.000000 2 1 roll 1.000000 2 1 roll 0 index 1.000000
+cvr exch sub 2 1 roll 5 -1 roll 1.000000 cvr exch sub 5 1
+roll 4 -1 roll 1.000000 cvr exch sub 4 1 roll 3 -1 roll 1.000000
+cvr exch sub 3 1 roll 2 -1 roll 1.000000 cvr exch sub 2 1
+roll pop } endstream endobj 117 0 obj <</Process 121 0 R/Subtype/NChannel>> endobj 121 0 obj <</ColorSpace/DeviceCMYK/Components[/Cyan/Magenta/Yellow/Black]>> endobj 106 0 obj <</BC 122 0 R/G 123 0 R/S/Luminosity/Type/Mask>> endobj 122 0 obj [0.0] endobj 123 0 obj <</BBox[198.027 568.502 444.988 526.485]/Group 124 0 R/Length 92/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>/XObject<</Fm0 125 0 R>>>>/Subtype/Form>>stream
+0 g
+/GS0 gs
+198.026 568.502 246.962 -42.017 re
+f
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 TL/Fm0 Do
+Q
+ endstream endobj 124 0 obj <</CS/DeviceGray/I false/K false/S/Transparency/Type/Group>> endobj 125 0 obj <</BBox[198.026 568.502 444.988 526.485]/Group 126 0 R/Length 128/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 113 0 R>>/ExtGState<</GS0 12 0 R>>/Shading<</Sh0 127 0 R>>>>/Subtype/Form>>stream
+q
+198.026 568.502 246.962 -42.017 re
+W n
+q
+0 g
+/GS0 gs
+246.9619904 0 0 246.9619904 198.0263672 547.4936523 cm
+BX /Sh0 sh EX Q
+Q
+ endstream endobj 126 0 obj <</CS/DeviceCMYK/I true/K false/S/Transparency/Type/Group>> endobj 127 0 obj <</AntiAlias false/ColorSpace 113 0 R/Coords[0.0 0.0 1.0 0.0]/Domain[0.0 1.0]/Extend[true true]/Function 128 0 R/ShadingType 2>> endobj 128 0 obj <</Bounds[0.5]/Domain[0.0 1.0]/Encode[0.0 1.0 0.0 1.0]/FunctionType 3/Functions[129 0 R 130 0 R]>> endobj 129 0 obj <</C0[0.0]/C1[0.643137]/Domain[0.0 1.0]/FunctionType 2/N 1.0>> endobj 130 0 obj <</C0[0.643137]/C1[0.682759]/Domain[0.0 1.0]/FunctionType 2/N 1.0>> endobj 5 0 obj <</Intent 131 0 R/Name(Layer 1)/Type/OCG/Usage 132 0 R>> endobj 131 0 obj [/View/Design] endobj 132 0 obj <</CreatorInfo<</Creator(Adobe Illustrator 20.1)/Subtype/Artwork>>>> endobj 11 0 obj <</LastModified(D:20161031172420Z)/Private 133 0 R>> endobj 133 0 obj <</AIMetaData 134 0 R/AIPDFPrivateData1 135 0 R/AIPDFPrivateData10 136 0 R/AIPDFPrivateData100 137 0 R/AIPDFPrivateData101 138 0 R/AIPDFPrivateData102 139 0 R/AIPDFPrivateData103 140 0 R/AIPDFPrivateData104 141 0 R/AIPDFPrivateData105 142 0 R/AIPDFPrivateData106 143 0 R/AIPDFPrivateData107 144 0 R/AIPDFPrivateData108 145 0 R/AIPDFPrivateData109 146 0 R/AIPDFPrivateData11 147 0 R/AIPDFPrivateData110 148 0 R/AIPDFPrivateData111 149 0 R/AIPDFPrivateData112 150 0 R/AIPDFPrivateData113 151 0 R/AIPDFPrivateData114 152 0 R/AIPDFPrivateData115 153 0 R/AIPDFPrivateData116 154 0 R/AIPDFPrivateData117 155 0 R/AIPDFPrivateData118 156 0 R/AIPDFPrivateData119 157 0 R/AIPDFPrivateData12 158 0 R/AIPDFPrivateData120 159 0 R/AIPDFPrivateData121 160 0 R/AIPDFPrivateData122 161 0 R/AIPDFPrivateData123 162 0 R/AIPDFPrivateData124 163 0 R/AIPDFPrivateData125 164 0 R/AIPDFPrivateData126 165 0 R/AIPDFPrivateData127 166 0 R/AIPDFPrivateData128 167 0 R/AIPDFPrivateData129 168 0 R/AIPDFPrivateData13 169 0 R/AIPDFPrivateData130 170 0 R/AIPDFPrivateData131 171 0 R/AIPDFPrivateData132 172 0 R/AIPDFPrivateData133 173 0 R/AIPDFPrivateData134 174 0 R/AIPDFPrivateData135 175 0 R/AIPDFPrivateData136 176 0 R/AIPDFPrivateData137 177 0 R/AIPDFPrivateData138 178 0 R/AIPDFPrivateData139 179 0 R/AIPDFPrivateData14 180 0 R/AIPDFPrivateData140 181 0 R/AIPDFPrivateData141 182 0 R/AIPDFPrivateData142 183 0 R/AIPDFPrivateData143 184 0 R/AIPDFPrivateData144 185 0 R/AIPDFPrivateData145 186 0 R/AIPDFPrivateData146 187 0 R/AIPDFPrivateData147 188 0 R/AIPDFPrivateData148 189 0 R/AIPDFPrivateData149 190 0 R/AIPDFPrivateData15 191 0 R/AIPDFPrivateData150 192 0 R/AIPDFPrivateData151 193 0 R/AIPDFPrivateData152 194 0 R/AIPDFPrivateData153 195 0 R/AIPDFPrivateData154 196 0 R/AIPDFPrivateData155 197 0 R/AIPDFPrivateData156 198 0 R/AIPDFPrivateData157 199 0 R/AIPDFPrivateData158 200 0 R/AIPDFPrivateData159 201 0 R/AIPDFPrivateData16 202 0 R/AIPDFPrivateData160 203 0 R/AIPDFPrivateData17 204 0 R/AIPDFPrivateData18 205 0 R/AIPDFPrivateData19 206 0 R/AIPDFPrivateData2 207 0 R/AIPDFPrivateData20 208 0 R/AIPDFPrivateData21 209 0 R/AIPDFPrivateData22 210 0 R/AIPDFPrivateData23 211 0 R/AIPDFPrivateData24 212 0 R/AIPDFPrivateData25 213 0 R/AIPDFPrivateData26 214 0 R/AIPDFPrivateData27 215 0 R/AIPDFPrivateData28 216 0 R/AIPDFPrivateData29 217 0 R/AIPDFPrivateData3 218 0 R/AIPDFPrivateData30 219 0 R/AIPDFPrivateData31 220 0 R/AIPDFPrivateData32 221 0 R/AIPDFPrivateData33 222 0 R/AIPDFPrivateData34 223 0 R/AIPDFPrivateData35 224 0 R/AIPDFPrivateData36 225 0 R/AIPDFPrivateData37 226 0 R/AIPDFPrivateData38 227 0 R/AIPDFPrivateData39 228 0 R/AIPDFPrivateData4 229 0 R/AIPDFPrivateData40 230 0 R/AIPDFPrivateData41 231 0 R/AIPDFPrivateData42 232 0 R/AIPDFPrivateData43 233 0 R/AIPDFPrivateData44 234 0 R/AIPDFPrivateData45 235 0 R/AIPDFPrivateData46 236 0 R/AIPDFPrivateData47 237 0 R/AIPDFPrivateData48 238 0 R/AIPDFPrivateData49 239 0 R/AIPDFPrivateData5 240 0 R/AIPDFPrivateData50 241 0 R/AIPDFPrivateData51 242 0 R/AIPDFPrivateData52 243 0 R/AIPDFPrivateData53 244 0 R/AIPDFPrivateData54 245 0 R/AIPDFPrivateData55 246 0 R/AIPDFPrivateData56 247 0 R/AIPDFPrivateData57 248 0 R/AIPDFPrivateData58 249 0 R/AIPDFPrivateData59 250 0 R/AIPDFPrivateData6 251 0 R/AIPDFPrivateData60 252 0 R/AIPDFPrivateData61 253 0 R/AIPDFPrivateData62 254 0 R/AIPDFPrivateData63 255 0 R/AIPDFPrivateData64 256 0 R/AIPDFPrivateData65 257 0 R/AIPDFPrivateData66 258 0 R/AIPDFPrivateData67 259 0 R/AIPDFPrivateData68 260 0 R/AIPDFPrivateData69 261 0 R/AIPDFPrivateData7 262 0 R/AIPDFPrivateData70 263 0 R/AIPDFPrivateData71 264 0 R/AIPDFPrivateData72 265 0 R/AIPDFPrivateData73 266 0 R/AIPDFPrivateData74 267 0 R/AIPDFPrivateData75 268 0 R/AIPDFPrivateData76 269 0 R/AIPDFPrivateData77 270 0 R/AIPDFPrivateData78 271 0 R/AIPDFPrivateData79 272 0 R/AIPDFPrivateData8 273 0 R/AIPDFPrivateData80 274 0 R/AIPDFPrivateData81 275 0 R/AIPDFPrivateData82 276 0 R/AIPDFPrivateData83 277 0 R/AIPDFPrivateData84 278 0 R/AIPDFPrivateData85 279 0 R/AIPDFPrivateData86 280 0 R/AIPDFPrivateData87 281 0 R/AIPDFPrivateData88 282 0 R/AIPDFPrivateData89 283 0 R/AIPDFPrivateData9 284 0 R/AIPDFPrivateData90 285 0 R/AIPDFPrivateData91 286 0 R/AIPDFPrivateData92 287 0 R/AIPDFPrivateData93 288 0 R/AIPDFPrivateData94 289 0 R/AIPDFPrivateData95 290 0 R/AIPDFPrivateData96 291 0 R/AIPDFPrivateData97 292 0 R/AIPDFPrivateData98 293 0 R/AIPDFPrivateData99 294 0 R/ContainerVersion 11/CreatorVersion 20/NumBlock 160/RoundtripVersion 20>> endobj 134 0 obj <</Length 1246>>stream
+%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 17.0 %%AI8_CreatorVersion: 20.1.0 %%For: (David Fran\615a) () %%Title: (Untitled-2) %%CreationDate: 31/10/2016 17:24 %%Canvassize: 16383 %%BoundingBox: -9 -621 1763 9 %%HiResBoundingBox: -9 -621 1762.47226464325 9 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 13.0 %AI12_BuildNumber: 174 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%CMYKProcessColor: 1 1 1 1 ([Registration]) %AI3_Cropmarks: 0 -612 792 0 %AI3_TemplateBox: 396.5 -306.5 396.5 -306.5 %AI3_TileBox: 0 -612 792 0 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 0 %AI9_ColorModel: 2 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI17_Begin_Content_if_version_gt:17 1 %AI9_OpenToView: -280.375731213439 535.367481625915 0.6667 2125 1336 18 0 0 93 55 0 0 0 1 1 0 1 1 0 0 %AI17_Alternate_Content %AI9_OpenToView: -280.375731213439 535.367481625915 0.6667 2125 1336 18 0 0 93 55 0 0 0 1 1 0 1 1 0 0 %AI17_End_Versioned_Content %AI5_OpenViewLayers: 7 %%PageOrigin:0 0 %AI7_GridSettings: 72 8 72 8 1 0 0.800000011920929 0.800000011920929 0.800000011920929 0.899999976158142 0.899999976158142 0.899999976158142 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 135 0 obj <</Length 12281>>stream
+%%BoundingBox: -9 -621 1763 9 %%HiResBoundingBox: -9 -621 1762.47226464325 9 %AI7_Thumbnail: 128 48 8 %%BeginData: 12140 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45534D534D534D534D534D534D534D534D534D534D534D534D534D53 %4D534D534D534D534D534D534D534D534D534D534D534D534D534D534D53 %287EFD0AFF7D4D4D534D534D534D534D534D534D534D534D534D534D534D %534D534D534D534D534D534D534D534D534D534D534D534D534D534D534D %534D534D2853284D2853284D2853284D2853284D2853284D2853284D2853 %284D2853284D2853284D2853284D2853284D2853284D2853284D2853284D %284D77FD0AFF7E284D2853284D2853284D2853284D2853284D2853284D28 %53284D2853284D2853284D2853284D2853284D2853284D2853284D285328 %4D2853284D5328534D5328534D5328534D5328534D5328534D5328534D53 %28534D5328534D5328534D5328534D5328534D5328534D5328534D532853 %4D53287EFD0AFF77534D5328534D5328534D5328534D5328534D5328534D %5328534D5328534D5328534D5328534D5328534D5328534D5328534D5328 %534D5328534D284D284D284D2853284D2853284D2853284D2853284D2853 %284D2853284D2853284D2853284D2853284D2853284D2853284D2853284D %2853282953FD0AFF7E2853284D2853284D2853284D2853284D2853284D28 %53284D2853284D2853284D2853284D284D284D2853284D284D284D284D28 %4D284D284D2853534D534C5329774C534D534D534D534D534D534D534D53 %4D534D534D534D534D534C534D534D534D534D534D534D534D534D534D53 %4D534D53287EFD0AFF77534D5329534C5328534D534D534D534D534D534D %534D534D534D534D534D534D534D534D534D534D534D5328534D534D534D %534D5353534D534D284D28994C296F9A284D2853284D284D284D2853284D %2853284D2853284D2853284D2853284D2853284D2853284D2853284D2853 %284D2853284D77FD0AFF7E285393766F9A29534D534D4D2853284D285328 %53285328532853284D2853284D2853284D287E7D7E537E7D7E7D7E7D7D53 %A253A277A27E532853532977939A709A93537E7E777E537E53534D532853 %4D5328534D5328534D5328534D5328534D534C534D534D534D5328534D53 %28534D532853287EFD0AFF7D4D4CC299BB997EA87E7EA84D5328534D5328 %534D534D534D5328534D534D534D5328534D537EA87D5377A27EA27EA853 %53A27EA87E7E7E535328282976C193B599C14CA97E7E7D7EA8A84C4D284D %2853284D2853284D2853284D2853284D2853284D2853284D2853284D2853 %284D2853284D284D77FD0AFF7E28294CBB995228534C53284D284D284D28 %4D284D284D284D284D2853284D2853284D284D285328532853284D4D5328 %53285328534D53284D284D534D539AC1BBC1765353774D7E537753534D53 %28534D5328534D5328534D534C534D534D534D534D534D534C534D532853 %4D534D534D534D53287EFD0AFF7E77537E7D7E537E777E537E777E777E77 %7E777E777E777E777E777E777E777E777E777E777E537E777E777E777E53 %7E777E537E777E537E777E532853284D76C25229285328532853284D2853 %28532853284D28534D532853284D285328532853284D28534C5328534D53 %4C534D534C534D4D284D77FD0DFF7EA87EA87EA87EA87EA9A8A8A8A9A8A9 %A2FFA8A87EA87EA8A8A9A8A8A8A9A8A8A8A9A8FFA8A87EA8A2A9A8A8A2A9 %A8A9A8A9A8A8A2FFFFFF53285329534C534D537D7E7E77537E7E7E777E77 %777E7E7D7E777E535328534D5328534D5328534D534C534D534C534D5328 %534D534D534D53287EFD0DFF532853284D284D537E7EA97EA27EA2A87E7E %7E284D285377A8A2A97EA8A2A87EA97EA2A853284D297E7DA27E7E7DA2A8 %A97EA2A87E7EFFFF284D284D284D284D28A27D7E4D7D77A87E7E7D7753A8 %7D7E7D7E5353284D284D284D284D284D284D284D284D284D284D284D284D %284D284D282953FD0DFF7D7E7DA27D7E7EA8A2A87EA87EA87EA87ECB7E7E %7DA27EA87EA87EA87EA87EA8A2A87EFFA8A87EA87EA87EA8A2A87EA8A2A8 %7EA87EA9FFFF534D534D534D534D5353775353537753775377FD0753774D %534D534D534D534D534D534D534D534D534D534D534D534D534D534D5328 %7EFD0DFFFD057D52FFCFFFA8FFA8FFA8FFA8FFFFA87D7DCFFD0BFFA8FFFF %FFA9FD0AFFA87DA87EA9FFFFFFA8A9A8A9A8A9A8A9A8A8A2A9A8A87EA8A2 %A87EA9A8A8A8A9A8A8A8A9A8A8A2A9A8A8A2A9A2A8A8A9A8A9A8A9A8A9A8 %A9A8A8A2A9A8A8A2A9A8A9A8FD0DFFA852527D527D537D7D7D527D52527D %7D7DFD0FFF7D5253FFA87753A8FD08FF5377537777FD05FFA84C5353534D %5353777DA27EA87EA87EA27EA953534D5353534D777DA27EA27E7E7EA8A2 %A94D5353534D53537777A27EA87E7E7EA27DFD10FFA27DA27D7D7DA853A8 %7D7DA8FFFFFFCFFFFFA87DA8FD057DA8FD09FFCB7EA27EFD08FFA87D7E7D %CBFD05FF7E534D5353534D5353A27DA87EA27E7E7EA2A25353534D534D53 %537E7E7E7DA27D7E7EA87E534D5353534D53537E7DA27EA27DA27E7EA8FD %0FFFA87D527D527DFD05527D777D537D7DFFA852527D527D527D527D527D %5253527752FFFFCB7EA87DA8A2FFA87E7EA877A8A8FD07FFA87DA87DA87D %A8A2A87EA87D7EA8FFCBFFA9FF7DA87DFD07FFA9FFCBFFA8FFFFA8527D52 %7D5253537D525253524C7D537752FD10FFA8537D7DFD04A8CBA8A8A2A8A8 %A8A2CBFFFFFD06A852522752275252522752FFFFA87E7EA97EA2FFFF77A8 %7EA87EFD08FFFD04A87D52527D5252527D52FD047DA8FFA8525277A8FD06 %7D52FD047DFF7DFD042752275227522728272727522752A8FD0FFF7D7D52 %5353A87DA87DA87DA87DA87DA87DFF7D7D7DA8FD067DAEFFFFFFAEFD05FF %7EA27E7E7EFFA8A9A87E7EA9FD09FFFD04A8527D537D527D527D52527DA8 %A8FFA87D525252A87DA87DA87D7D7DA87DA8A8A8525252FD07FFA9FD18FF %A8A8A87DA852522752272827522752A8FFA8FFA8FFA852527D527D527D53 %7D527DFD05FFA8A8FFA2A9FFFFA2A27EA9FD07FFA8A853527753527D527D %FD05527D7DFFA8A27DA87D527DA87DA87DA87DA87DA87DA8A8FD087DFFFF %FFA8FFFFFFA8FD11FF7D7D7DA8A8FFCFFD0AA8FF7D7D7DA87D7D7DA87DA8 %7DA87DA87DA87DFFFFFFA8FF7EA9A8FFA8FFA8FFA9FFA8A27EA9FD06FF7D %527D5277527D52777DA87DA87D7DA8FFA8FFA8A8527D527D7DA87D7D7DA8 %7D7DA8A87D7D7DA87D7D527D7D7E7DA2FD047DA8FD11FFA8FD047DA87DA8 %7DA87DA87DA87DA8FFFFA8FFA8FFA8FFFFFF7DA87DA87DA87DA8FD09FFA9 %A8A9FD04FFA8A9A9FD04FFA8FD067DA87D7D7DFD06A8FFA8FD07527DA87D %A8A2A87DA87DFF7D27274C2752272727FD087DFD11FFA8A8527DA8A87DA8 %7DA87DA87DA87DA87DFFA8FFA9FFA8FFA8CBA87D7D7D777D7D7D77FD07FF %A87D7D7E77A2A8A8A8FD10FF7DA87D7D527D7D7DA8FF527D527D7D7D52A2 %FD087DA8FF7DFD07A8FD19FFA87D5352FD08A8CFFD04A8FF772853284D28 %53537E7EA27E7E7EA27E7EA8FFFFFFA8A87EA97EFFA9FFA9FFA8FFCBFD06 %FFA87E777E7D7E777E7EA87EA97EA87EA8A2A8A8A87D5252A85253FD09A8 %FF7D5227FD04527752522752275227522752A8FD11FF777D527D5253527D %527D527D525352FF7E77537E5377537E7EA87EA87EA27EA87EA9FFFFFFA8 %53777DFD05FF777EA2537EFD05FFA228534D532853537E7EA27E7E77A27E %7E53FFFFA8527D527D527D527D777D777D5253A8A8275252532752287D52 %7D5252527D525252FD10FF534D5377A27EA27EA27EA27EA87EA27EA2A8A8 %7DA87DA87DA87DA87D7D7DFD09FFA9CBA8CBFFFFA8A9A8A87EA877A9FD05 %FFA87E7DA87DA87EFD04A8A9A8A8A8A9A8A9A87D527D52A2AEFFA8FFA8FF %A8FFA8FFA8FFA87E7DA27EA27DA2A8FFA8FFCBFFA8FFA9FD11FF537E77A2 %7EA9A2A87EA9A2A87EA87EA87ECB7DFD0B527D7D527D7DFD05FFA2A9A8CB %A8FFA8CBA8FFA87DA8FD05FFCBFD047D777D52FFFFFFA8FFA8FFA8FD04FF %A87D7752525277527DFD06527DA94D534DFD04537E7E7E7D7E7E7E7DA277 %FD10FFA87D7DA2A87DFD0DFF7D5227FD055227524C5252522752FD04FFA8 %7EA8A2FD05A8A9FFFF7DA2FD05FFA87E2752274C2752FD052728272727A8 %FFA8A8A85227FD075277525252A8A87753775377537E7EA87EA87EA97EA8 %7E7EA8FD0FFFA8A87D5252527DA27D7D777D527D527D7DFFFD047D777D52 %7DA8FFA8FFA8FFA8FFA8FFFF7E53A8A8A97EA87DA27D7EA8FFA87E7EFD05 %FFA827522752525227525252275228522752A8FF7D7D7DA87DFFA8FD0BFF %A8A87DA8A8FD1CFFA8A8A8FD047D537D7DA8A8A87DA87EA8FFFFA852527D %5253527D527D7D7D527D77A8FFFF7EA2A2FD04FFA87EA8A8FD0AFFFD05A8 %A9A8A8A8FFA8A8A8A9A85227A8FD04FFA8FF7D52527D5252527D527D527D %A877525352FD077D77FD047DA8FD10FF7DA8527D7D7D52527DA87DA8A8A8 %A2A8A8FFFFFF7DA87DA87DA87D5227522752522752FD07FFA8A97DFD0DFF %A8FD047D527D7DFD05FFCFFD05FF7D7D52A8FFFFA8FFA8FFA8FFFFFFA8FF %FFFF527D5277527D7DA27DA87DA87DA87DA8A8FD11FFA87D537D7DA87DA8 %7D7D7DA87DA87DA8FD1AFF7EA8FD0DFFA8FF7D525277525352525253527D %525352FFFF7D4CFD09524C52272827A2A8A87DA87D7DFD04A87DA87DA87D %A87DA8FD10FF777D527D527DFD0BA8FFA8A8A2A9A8A9A8CBA8A9A8CBA8A9 %A8FFA8FF5377537E7DA27E7E7D7E7D7E7D7E7D7E77A8FD04FFA853785377 %53775353537E7EA27EA27D7E7EFF7DA87D7DA8FD07FFA8A87DA8A8FFA8FF %A8FFFFFF52FD067DA87D7DA2FD10FFA8527D527D5252527D527D527D527D %527DA97853787EA2A8FFCBFFA9FFA9FFA8FFA9FFFF7729777DA8A8A87DA8 %A8A8A2A87E7E7EA27EFD04FF7E4D28534D532853285353A27EA2FD047EA8 %A87D5227FD097D7E7D7DA8A87D5252527D527D7DA8A8FFA8A8A8FFA8FD11 %FF7D7D527DFD04527DFFA8A8A8FFA8A8A8FF537D53A27EA27EA87EA87EA8 %7EA2A2FFFFFFA8FFA9FFA8CBA8FFA8FFA9FFA8FFA8FFA8FD05FFA87DA852 %7DA8FFA8FFA8CBA8CBA8A9A8CBA8FFA8A8527D527D527D527D7D7D527D52 %537DFFFD057DA27D7D525228524C5252527DFD11FFA8FFFF7D527D52FD04 %7DA8537D777DA953537E7EA87EA27EA87E7E7EA2A8FFA9FD07FFA8FF7E7E %7DA8FD0BFF7D28527D52A8A8FFA8FFA8FFA8FFA8FFA8FFA87D7DA8FD06FF %A8A9FD05A8CBA8A8A2A87DA87DA8FFFF7D7D7DA87D7D7DA8FD10FF7D7D52 %A87D7D527D52A8A8FFA8FFA8FFA8A94D7E537E7EA87EA87DA87EA8A8FD05 %FF7DA87EA87E7EA8A8777E7D7EFFFF7EA2FD06FFA8277D7DA8FFFFA8FFCA %FFA8FFCAFFA8FFFFFFA8FFA8FFCBFFFFFFA8FD077DA8FF775328FD0452A8 %7DA87DA87DFD04A8FD11FFA87D537D527D7D7D52FD047DA87DA8A9FFA9FF %A9FFFFFFCBFFFFFFFD057EA87E7EFD04FFA8FFA9FFA8FFA8FFFFA9A2A8A8 %FD04FFA87DA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA87D7D7D527DFD0CA8 %FFA87D7D537D7D7D527D527D527D2827007DFD10FFA9FFFD06A8A2A87DA8 %7D7D7DA8A8FD0DFF7E7E7D7753A87EFFFFFFA9FD0BFFA8A8FD05FF527D7D %7D777D777D7DA87D7D52FD047DFFFFFF52525253FD07527D52537DFF7DA8 %7DCBA8A8FD08FFA8A8A8FD13FFA8A9A8A9A8A9A8A27D7E77787EA9A8CBA8 %A8A8CBA8FFFFFFA9FD05FFA8CBA8CBA2A9A8FFA9FFA8FFA8A97EA9A8A2A8 %FFA8FD04FF7DFD10277DA87D527D53A8A8FFA8FFA8FFA8FFA8FFA8FFA852 %275252522777527D527D777D7DA27DA8FD13FF7E4C53537D537E7EA27DA2 %7D7E535353A8A27E77A2A8FD09FF7D7753A8A8FFA8FFA87EA8FFCBA87D7E %7EFFA8A9FD04FFA827527DA87DA87DA87DA8A8A87DA87D7DA8FD06FFFD05 %7D527D7D7D527DA8FFFD08A8A1A8A8A8FD0452A8FD14FFA2777E7EA87EA8 %7EA27E7E77A8A8FD11FFA9FFFFA97EA27DA2A8FD05FFA8CB7EA8FFFFFFA2 %A9A8A87DCBA8CBA8FFA9FFA8FFA8FFA8FFA8A9A2A9A8A8A2A9A8A9A8A9A2 %A8A2A9A8A8A8A9A8A9A8A9A8A9A8A9A8A9A8A9A8A87DA27DA8A8A9A8FD0B %FFA2A8A8CBA8A97EA8A2A87EA27E7E537E77A27ECBA8A8A8A9A8A8A2A9A8 %A8A2A9A8A8A2A9A8A9A8A97EA87D7E7DA9A8A9A8A8A8A9A87E7EA9A8A84D %287EA87E7EA27D7E7DA877777EA27EA27EA2774D2853284D2853284D2853 %284D2853284D2853284D2853284D2853284D2853295328537753287EFD0A %FF774D28A2777E7E7E777E7EA853A27EA27DA87E7E4D4D284D2853284D28 %53284D2853284D2853284D28534D532853284D2853284D28534D4D285328 %284D2853284D2853284D285328532853284D2853284D2853284D2853284D %2853284D2853284D2853284D2853284D2853284D2853284D2853282953FD %0AFF7E2853284D2853284D2853284D285328532853284D2853284D285328 %4D2853284D2853284D2853284D2853284D2853284D2853284D2853284D28 %53534D534D534D534D534D534D5328534D534D534D534D534D534D534D53 %4D534D534D534D534D534D534D534D534D534D534D534D534D534D53287E %FD0AFF77534D534D534D534D534D534D534D5328534D534D534D534D534D %534D534D534D534D534D534D534D534D534D534D534D534D534D534D534D %534D284D2853284D2853284D2853284D2853284D2853284D2853284D2853 %284D2853284D2853284D2853284D2853284D2853284D2853284D2853284D %77FD0AFF7E2853284D2853284D2853284D2853284D2853284D2853284D28 %53284D2853284D2853284D2853284D2853284D2853284D2853284D285328 %4D285353284D2853284D2853284D2853284D2853284D2853284D2853284D %2853284D2853284D2853284D2853284D2853284D2853284D2853284D2853 %287EFD0AFF7729284D284D284D284D284D284D284D284D284D284D284D28 %4D284D284D284D284D284D284D284D284D284D284D284D284D284D284D28 %4D284D28537E777E537E777E537E777E537E777E537E777E537E777E537E %777E537E777E537E777E537E777E537E777E537E777E537E777E537E777E %537E7EFD0AFFA87D7E7DA27E7E7DA27E7E7DA27E7E7DA27E7E7DA27E7E7D %A27E7E7DA27E7E7DA27E7E7DA27E7E7DA27E7E7DA27E7E7DA27E7E7DA27E %7E7DA27E7E %%EndData endstream endobj 136 0 obj <</Filter[/FlateDecode]/Length 29427>>stream
+H‰¬—KfÅ …W=ÜI$’¢ì²ë‘Œx¬ Y@„Z
+b
+5…ÂÓ]¨èÇ„Z}.ìxã„ŠoÚ$ã"†ªå1# °»¹
+@›ô ç¨Ñz1U°ïtµr:öÇÄÄ¢ø¡ì'™g„ð™šuí©D½|œcTvÐ߸ÄßM·ÒŸ‹áJ§Ú›†ïp ••^^o¦8äY‡LPÔa’1xôyh«‰7õ5Ã+@̾.€ž€”Ž°HC™ÿ'¾úú×ßýøáã¿üüý¯ÿyþÂO_ü™)ËÝ¿|¾úûÇ_üù‡ç‹o¾ùúÇýô·_>~/ì—ÏŸ@þ•?ügÏwr–¦MòyÌçáƾhjúô0ÇžŸ*aÖé9†kQó9«ÑI/±© càÞ  ijŠŽEõÞ
+Õú0¶4qØŸo¡9„yê¨Ï=Ü$쥿¾ÆÔV
+Hɺ
+ôô¶móz«"Ë[ŠcÕ«³¾/Š-T.«Ù8Ö3õuÅ+š—ñÎEÐÀB0x×—€£…€Žß=Š¤…P죥e9¼Ï,+”¿ÇízÂnQvÙ%y¯¡åH{ ñ,Hô[ú°/ã t½Çm!25”à ¢GÉ…”\ K€µ™6Û¯sóÿ‘oÇ™ôÁ2>d%Lö‡b6îí"Ô“¾j …"±ÊE°…ÚË„šP£?B@®C(+®§Õd‡l
+@Þ–
+1 ) Kë"Ä—µ›ã-»‰µ{BCkQ¬
+2%wÊÆ”1Š{/’Ô”(ÿ<d‹’ ´iä"CAOL1¢g}* †‘BG»ùªCŠÃÔÑÌì|¸ÊBdæýÐd‰öS©ùHÀ‚(?î‚_Nsú¡2†œeïâ'ëKëT&ÚâAÂ=”d`LÍ ;ÜÓA%"Ö-3JP2ÔW6²¸^šavût‰Eh€b=mjßQ â"iKËW6v¾tLfÒ^ˆÎ¿ÊÙb¶t¼ÕpK>{ÑšHn}Ò0D SC UA. Bd TjL†Ô°_DP !è?Š)„1dÝ4w!BêÞŠ ](Ü/Š…-‘í²cÛ©Ž'U¸ˆÕ•=©Î
+‡úQT¨‰q´ßì1²çÚJˆ‰ö\sÝž¥Žê$¢‰iƒ&Õ»¥Ø¥Ç!³V!h-cB¼[@ÜŒ·eÑÔ°
+ÓDÖÒs½G˜ ‚!ÅÉ.¤hIÂñƒÂT¾1MdúÑ2¡f’ ) ïlŠJ§TLzX†¤³wØLO¡¤žjèeºœeÈSC±B”7?…ŽŠ¢§OrûýX£Êïø¨ƒ(ºœ.›…ÀÑBC]ˆ±Æg³·eT ¿v¥1oð|QtåWt•ìjSž#àκvS¹Å<ó2ù|‘U0â†ÏÒª'©¸‡Öª§(ûsG`&ýFöuÏïùò!WW “!i¼z8Ò%z8ÒTùª,øÇÐñ<Í‚Wržb‡„›S’ÔYTõ€€³õeþ» 6·>%[b2 ™ì¸ÅÝ¿Þt rcIB!y](6–—­(! A^HKbB/
+F’/ A+Jç ú)#ôù&† P¡=T¨òß•’ÛŠlée"_¸C¾ø=×3¦Î%k*"ԉΓ&yï?B7ê_PȮԉýªV…GR)+‰‡s—ö«ÈøðtÂØô
+CÊ3õ«wÄk^DrT0=5´ÿ+Xx[ï w&%'±d—]O9ÌšÒLƒÑM¡›)&CÿÇHà+zx-ÔíSœ§àõTõ9ƒ-Ë/çEH`²*¡àÁ>Ba\Äœ«èªÏˆÄ…
+{¡R¤¤WïɲƒäíB «ÎuôTÉõˆY±#ˆ>¯/lyµæó½î“r¤ ô4bñ}ÈQÀ¡‘Fq›Bâ1Éb£û& DêZ?¦¦•áì]F•8=;§I’vú³_±Ãú˜¨†! Š¹%z|p¬•²§Çy)’ØDB
+"DÒÏÿKw™åXrÃ@ð*}‚v©.æó;"UÕ ûk0]|ÚHfÅÕæŒyn}2àÜ ˜Øâ-ó,#…QZÁ2Ý@åµ(Å!Ïìx(&Äb#iŽ( âÎTÎ(RòòNµöÕu¬‰gÜÂ(÷ë+Wâ.Í–R»hÍ|B~§ßwÁ³ãî5†…!`ÔîHK¿­{ÝÜò„)©Îzu‚c1²‚¼¢Dâ‡ÛVyKi‚Õ,c•¥q¾ÒSÙ¨ Gp\ÛßuÔS¢@ü¹ X5\ÐíL²Ùx%ZÈ«ÙtÎAýè:‰VrÌEö–c.Çy-„!€66*çöm”ò:Ö&© RË``—ðoú‘),ÀÖš”ÃfF0 ¼(QãºÞF䶭ÑS¤Ö²QR=·ÎÄp*\ŒcZÆuÒcð°8Á¤·C4<ìÒ„8®©–ÆÖï×b’âC=N¶Ã.¬+!(°~¨~æ2seÒuD@¤,L‚À
+vj8F8õ‘Ïs>Ãœ+pMT—m% …Y.wâ5óáPµ;ÿ_3\…ða8ƒmO‹ïZ(7)vÊ}õ}'˜8ÝÂ}©W®–ðDL²è ÷LuKSý>ÔãÈßÎÉÏ-¶ïô`PÉÜÊðÁx`Г"¦@3·ŽB‘™ç½q²†ì2ÔÂÕNG´…¾y¦ôO};Ô˜gÊ7"´¹ÑÀ/[›á
+ZÇ\·ÊMÀÚgÙßp€;_5 aÚ«j½.²†p˜ìDvjŠØvg
+ÀV?•J<z7•Ñí¤5£4"ɪÔR\Ýë*ÐçíßuiÙ±Cadx>ñ8®”ûNZ«LF¢†fLBÁ´m”9$ê‘äY‰ˆ®}CYZ@¡Å´:òoŸq‹íN—JzU³òȨ&ªƒ²øË–¢•NgD“L÷ÐÎü*f8K|Œ?cBÁCù¸ÜÑâBTkW4E9à%3ÓqÒÌI ñW{¹8$„óQ?y ýùvÙ¶Óɪ ‚ZˆÝ8«C~Åú!+zµ@ѱïú¬±N.2”`îNR¹ÑKÕã2‡Ý\‡‹PÇ>7!t£E:°(Îí ¨±cû=‰¶sŠóŒüƒ¾`Xv7„—eÎËFKcŸ‚rˆ¸¡ºXcÉ‘«Ä’µqÊ¥]!*4 ¦Êû¸Òžë篬£»ëÆÀ¬|A—$›
+ÐÃ
+¿Â™šÄLñ<ƒ÷K4^6b™ PŒD‘¸Èöl:É©3PÒÃø¢oØ]aX×ÎzÃ44œ¢Ã©(¸Ìò؇ù¡º¿Àvl“äq3Ù³Òê)ã>ƒ®<‚qj" ‹“`pÁ:Æ•#¬‹Üà¦ÕÙÇ|®A(ÀS¿óʵGx×X™ëŒG.gLz¢¢¡^.?¹4,Â3ÌçRGE‘úb¸QGç1±:žÄˈí“qz‚}ÎîÄ ”øˆ™a …×ßîNÌØ(Q Ü^7ŠšLÚ†”AD¦Y"€•z#ògLÉ#RG¤6^#ØßÄÔQ[ôAãXŸ(˜ÿñ ('oYpÌé£R%–Òû8ª £ö 5ôïC°ð"Üî#N£:/a£ÖH”àKÔd^hY'(Ç5xº™ñ׈±Rþáý0Í$üoƒÒîî(uÍG*ó˜âAïÎS‡ÑÆ €o0ßõûþ–ux<Õ¦¸-™õG¾†ÿ «[`(eãÅR“|FqºsÀæ9?Ťž+A=8Éž­iÏ<Çè£Ì´_zÕPìÖ?âhû°˜zcÈÚ'R8gê}Qt”ûÒ+vNšM±ÛCÇ¡2tk®O/ì»Óœ»¨
+*7éâWayÈX܈ª¿´yxc ÷}¹‚a48œX«º=xˆ¹iö ¬täD¨ ¹ “²‘ôxKvª¶l‘S[lHXÛdÇ—WRx«TN n“îUº’ÂF™ùMU .6KŸJrejDjÐqFŠãëNXÎ&¢Úno–À¥q¿n÷qLû|ŒEB?/òž$Š‹×Ù¤iúvÈ)Òç:1õ×1üˆefƒ­ÔŽúæ˜áoÚ~ ¸Vªú ˜ì–E|)î2Æïú×X2®Da)35Òy:#¦UØ~J¿ÀˆZ"°b¯ˆÊ¼;ñ‡–5*u}w̦­K!-HZÇ¢¿ÃVäÄQmëŽÆšB Za)VD æž…á¼bW·Íí5Þ#„ÁÖ5ñ™²›2ç’÷iè} HÙwå]†b–ìL4ˆ+íÀΡ0kü¤Qeï•èðâ¨Rñ`.qTnÔZP;RLWîJ®Õ2ÒnÚ…ÃftŒÃ]ýÃè¿Žý8I8!‘\ÌŒÁ!ËŒ89JÈ9c¸™×-jw0Ë¡‚zÑ—ÿ¨øG'{xQï©Û UuBU>âP¨3bw5ddÀrº-ëExd­÷äÄi”9Œò—ô!Àü·;¯‰&*>‡¥ùuýbªN6t#ºŠ›êzÕTt-³O3`Z×›úL @)A>¸Q7ÃGŸY¦QåD½ÁÛYmkµu7ê1NÄYí5 ¢Ö7 ƒ…ºw—8 ’ÒÕ ÖÍ* !ÂÁ²ßˆ°äšˆ{Ö¥c&âBguV»;˜¢6ZÒC0ÏPîÂÐòI„óÛ¶b€Ý®ÄRðþôÕnÿ
+ÇA¡æ-0òÁÍR‰~=ÒØø]Ût9ÙMeEÆÑ~´Û”ã(tùá„Œ¹
+ «…
+:v“êžNj_’†,·ÒsM½ûDH§Í‡Ò¨ áÁöå‘mûÈIðU¾#l¡ø;ïÆ),²òuþ’]à^îè„@ÑâÜÅié¾|…¢CL“äf‡BWŽ¶…qê|WúœxÏB@û‘4ç#~Ê3Ñå%3@÷ X›vgÞ®[¯½ ©#SGPÜTC Sb"“„t f_Ó(aÙ´i¥… pC‚hÓI¯%vŽmÓ@ -uí`œàÊPÃ=b„‰ñ¦÷ ßýì˜ “WÓ¤bòb®^gK1Ørãø±‡¯…ð
+uç’ÓæLšq·MÈbçb•6Yf¨”Z#tâ Ï &=X†!Úá|Pm]?”î.êLÓtéwä; ¬,o¥•åÃóæ2T9ù>%qê9O«M{­ê;b|ícúNNDŽ“»NÖƒ‚x€}§Ù‹î âeÝJâ²¼Ë\ÜÅÝ£s|¤§(㈉9Æ šN#võp-¤§ç¿göbUX§’AG|ÍçÉhNSC… q/xìøší>T{>[A´M¬Aùõ8îT´|³§5¢Â%¦¾aÌ‚˜Kô…;À
+îø.ú3÷¼ýƒŸ/ß¼ÿðÍ»·Þýø÷ï~ü>û=M ݵöùãË¿|xÿî‡>>ûê«7oßþôýŸüð­ØÏ¿ùG~øÿ‹¿þF •Ç›ïøë§ÿþó‹ýïoòçþï_ùw½ûÛÏaG‚ŸÓÉ) =ôn´džÍCßߘ͠§zô”…¡)y.€Sûêƒ#«wy0vX"|®gØÓ,ÙòP“?<(6™Hä Ñ0ô‰·ßŽ¦VѪqN_£m[ª•Èic¬'|Ì‚Õ¼™@q«ME«™qPíÒ Lw"F ¢NUÓ~ièð½ÆQ÷-€¢ð]rH»>n„a-‚ð+¤Ù¤««g1_X+˺t¹ö‘V-z€"o„ž]Dy
+ôàý:-»ÍL¤1 ò⇖›\}3Ò=¶©&[aúŒf™4ͳ°Î¶wו¨ä¥Ò²8/ëq·×1"[=¶‰×S, m;u2ÀpW¸ŒÙî8lÇHøƒ¯ø€Ês{'½BírâiœPíÖ¹ÕNmb™z÷g­ÛmÌ´†~:)ÊŒò‘©®8ØÙ² ¨ÿ([FKÇg}£îšÂ™©:avg2.D³² !U¯iR¬¯‚£lúqƒSònι7Ø'™Pñ¸ï·+8‡Y7éÏ
+S=ì»lm¥ÑÖºó¡ÔÃ2 ÷N2ÃÐkÅ ·¡m‰uÖ-KÈ@§¡æµúô–âû+Q·s‡/´»bÆ“Ö gðVÅxrJ"I©ô–¦þâH5› »wzš‘øË AèN$˜Þ?íçhNÌ
+/‰ÔTÓ«Áóãƒ}„BÑêÔpÁó[œ¿77\g|ßñbhÕq´DËúÅî[%ÌÖ{ÐòcîÃ9kÍCÀœ‰yÑ81u:|=û‚`J4w´¼® „9NýÞ‚ ,dñ$Q4·Vmèýƒš®(
+¬§"4Á>"lõh5ëÔk® Îû£ëÕöv‹"mº’AŠr¾Àæ³3”´Ž]¢Sgýú®d¤á{Ý_¢–3˜ÁhÕC†÷[5ªíUmÆÎÚA×K‚·Îó‰è7â¸7@×Õ¤é5J1tj&§o®¹§Š¾Âh秞ª3_¡ðnšCh¨c¹¦ÅÂg˜AWˆjiŒÓ™GÚ„<¦oŤäÁ×wÇ.Y‡¡jÞ¬²
+rÅ}—çäø°Ö|†ëõøVàÊ·ê9²áå€ ¸òVTÀå˜& ØýFt×a‡wgS‹Ùä¤Ç«°Ü1ÂÂXÌ=CjŽ³kÛ:~9¥ÜÇû 3ÓA ,à/aI(‰à@ ŸZ'¹°;TÊc¥½¹ëÜ7W<-SÉÁJ©{apâ^Æu °(Ô¡7Ñüœ5îk¼-ª§l{„"gLënö_sa¿j9ù*¯~ý¿N±Æ6H]ÿ¢öK*ª ÂòDÓ¾6?ü‹ßGlÍ Çº
+1”º’èh2²ÚdØqâBìøI¼n#CÑ/Í;zÔ²¨ê.¢¨9ð2ͯé†@`†(&¡f©“¬ âÜAÀ¹ÇÞ yAµ÷Nd…&¡íw¢‡‹¨ãPDÁÍ> º)IÝó™Ë¯£1=(¡‹è½ÝØVŒ·¹ƒf‚£¬,ÝvÌíÊð\î5›%Cåâ'ÔŽ*G/s¥äÍ àAànq̺a\ïÇ(
+ Õ2Ÿݹ寰îõ9žNƇįZ&?í4È=±m y, ÁpŠ ËÚ½TÜõ0Nmz{BWšõ(8XGZyâBé&{žQ«þ×T|ýN"žî%É“õáÀõ *¼ôX3®‚Oö ",­!
+K<‚²(¨’vqŒÄ‰«n" D-%;áu6
+jã4Å2”ai_{¬¼
+¾áŒÓ°%ÂiH+ab¤Fcs/ê ' O¬êù»‰2P4} š!­ç:3^µ˜š
+P]–6Äl’wþ=Vt]ÿH=ó÷K{ÕG¦¶ö‡¾þ³PЃ­ðjhÖx˜·ô‰F5]ññ,ŒˆtÏÿ1ê­8:Õï¼â
+ŠÂ³pc‚éAëјž¶ø±Ñ ´ãÁU1’‰ËÀB[z|k~"Ÿ:]ô7âΕgЕ¯öúþi£-ËR5^¬~YoÕеèC1‚<®"8H.p ~mï4ýTÁéÀCO—ò‘Éæ×K¥ ¥+˜PõÌŸ;­ $¹°Ÿè¼?²Kqô¶~8r7rðÜlëñŠ9°/åq
+Y¢h¿À5óô'µÄRF ²eýÁÊ5ÒEq´ïw§ûŠwYO¦œf…3Ú„†Zjb4Ý=¦V7ðéæÕY߈Ü
+¦ú6µqeƒìø
+ëˤGÅéö<
+%n"L÷q,†C IJã ä~®2ZÇ b$óm0Ô^NÏ<q`þpÂØqÓ—F‘¢£A©üä Þ­,9óóI:om{B‹ÀžF“y×Bb$f½÷œ@(Â×áNƒ‰yh8ŒÉƒ¢¼¿­G´µùóg!Pæ€AR0K¨s»×8qYÇv¿ë ;œnæJs'Ÿ/À¿¶ÒAÂÑ­0DV/îd9¹”m‰o¡º½ÔÐe\¯À`; k˜Ù8­†ðAÝ^ˆ¸“c=:ûq?_Ö‘'œ(Zé;gy ã,#7¾ ¾Êæ …
+ŠêE€SEp¨S{âÑX‡Þ¡“Ù‰È
+?×ïNH._2¦w9Y¸G¯‡š)#ú0äº-±TZ §l9ž¬»7ÿ_Ö˥Ǯ«ˆÂåí®Ï~ï#›  JaF–e;È‚¸-Óøßó}µÏm'}/3’Øé>UûUµVA:ÑžêÚ“¶ê±ÁÀL¤ ÛÖ~&èJ~ðb«·<i±âf ™ôæ8©ïãðrÜ„»
+reÊBiX@AˆPÞ-Èl6;ìÚ(;fŸ%kó‰šg‚Èÿ¼ÑÍc=©4e6ƺîÉ
+iØmÀsœÝ€cá¾¢ª%ªVÕãP¼$rß
+ϏR
+‚=Ó1\ïö[Ô:¨q$8ÆPš›–+içÝ›ñeòñúë{l–Â=§Î0¸?¬`\*ÁÊ´_LtmŒíÖ½’0îÕ¸{ä×Ò „a æ.L`Hp„‘fÆ ²Ñtpq:ÀC-šd<ö–Õ—G_µ\ÞÐW}À ¤¤ÞØÇÌ &EÞ%-i„¦û-ôµÀ‹ ‚7¾ЯœŠ´†zÚ<©ƒ"*©O…eCþÃ>èAMgˆ·5I¼iîŠÈ D_“!(b´ÇÃs ¥c„„×ô
+¹ZÔà Êu¶eP󾤞ê/âÑ@éÒ +êÌ^F>NB
+Ä&–1`ò³ÁœŒ,|T@èøªTœÈD‹âJó;PÝB+4 ™æY猥‘pÝƨÖ!«©‘êjzQ¬„[å|3wÚhr^Ë|eO„ÇXd~EŠSc
+X© R×û9J‚÷çÉ®1²^¾ó%0€]&š‹‚„÷Á¤• ç1€¦¦åƒ2ԚϘÔ:¨x3{Ax†£¬<å÷<]Í“Y ÙËÌr¢X·´—Ǿ<ºi{Ì¡Km>ö“Z(åJY¥ŽFKç-¹çÅ+ý˜,X&Cæ<ú¡ØÕB}1Lfõ·¡–ììggZdgâ늣7ïc3´Èrf=‡#«¦°Ë¾Hõ# 8Ä–
+I®CbÀhDx†mx
+QË@ˆFe´ƒˆ¢ÃÛ‚MjŒŠe¬¢X
+®ó(Aáêpm·ÓºH8ŒüàØ‹±KÚø5 jv \­…f Ã1¶zœå—ŠTÁ•Á OfÞ\®5Ú!g3 8¬Ík­±¢ÓN±J©ÌCàЙUY(í'ÙY8­Ýp@æNâÃ<ÞM:ÇWÙxìÂGÀ +u!Ûäå<!Q7Å6[°ŠmÁ<å.­ œ5º‹Ó¶CBVg^{ÆEÁœÃH±m;RN×"…ÑžX ´p¦©q@=ïFDf¸Hy¯,£ÃHû»ÎˆÏ Ÿ±y/»\E @,™H¹Åe3emÆüæªÔÅ@†VrÒ€rSjZW;X­Æ|ÁÈÒ”<™ è`.e•ÈÆ&eQˆAèøuèQ¥ëh´ÕÀ7$R]û…ÉÆ—@ΛÔÉ4 ö•Â˜ ߈’UAݹ)tiNgºäú{Ü@¶®ÖOµx$=ƒ¡ç.8¬ø&4N2´T>j[[²{¦?lEãnä5@xÚj+òW6OQ)å± ÌŒ¡mí²°… ­¸iC°Hå*˜Ã
+Ö?åÚÄ
+ÚUä$ÖxfÑ ûD¡ØF‘°ÚœÁH D‡?˜GÑý äÆý}f¡ pÀü‚Çg`Ì
+ °
+¹Ø;Èœov.nN‹! Ö¤)¹îüÐ#Èn¤ì¢üúù{”u Êì1ª
+uµ{ÝfEÃ/ø´hSÈÂæDø¹bUàu2@÷ž1öEÒ‰„¶'Æ|ù;â¼×‡?]ž©yP*qö‰¯Y,öòEŽxÖÍxdy
+taù<ô|¼gžM†Ô¸!+U•ÆŒ‡™ ƒò™È ™° Ciø¹Î£º“ÞiøõÛ1ÞÝÞd˜Ôújƒæ:üàigÌĹœ¼„mÖaÜ8†MÈ€Ò¶‘OUßaTxÁ4*” ‘¡H›Î m"… w‚ãg õ™5šËDû`ËêüÌòuK¾?¦•>‡\E Âm¶/<φ¼¹(ðÝ\ÿÈÁ»¡w%ÐhФ úï*»ÏÒ ¦'~Û'>a[©à7Ft~fDE€qk„C´¾¬Ã—€mIw«ašú·
+hÖÐ=Üæä-
+ÄKè¨J"ÄéΉ£{`.­Ã :)"`vï˜S-œ}ddW¡Äwûòù£Ó\MÔjM©<:(‚Tü¾%À*Ž:}¾k}­ÿ‘”̆‰Ã¡^ž+ &ãüxNžª¦Þ
+,je’Ì_óÙí3#ïl§ÁÊzù’ÅTCCP
+²ílÛ€  B‡û™qÐHÅ×)¤½^çg–¸@ÁÐ2¦
+«'¦bûvÊ'¿è!úVì¦;=ª¦@úÀk$k\Ɇ1[ûòù„°íãx„ùùsø›vì®P°¹üG°¼cè[TK
+T椢òj¡eCeÍ«²Žœ;5€>Š¶ )èF.ÿ‚-c¬å|¶ UVÀ矣M»cï>Md s"ƒ¿ö [ïôžöÏ{'4¹Ô
+lhoÛ„uGïü­"2ƒ8‘±ETwY##~p ®"2žù*¥R'j|Ð1zLo¾AeÄ>§‡ë±±CƒÏÇõ
+]€Aéx`€€ZŸ©#F\à—Ïg 6±6Jꃒdçª)šõ[ÆN¥@—ÏyÅgÖDH¡TŽ`ÀCÙ2®1Â'òÜ3*x1V°¢F2–ä^qý%ÞË•a¢r“Ž§À_1b±ÌÔ~
+iJ–5E_‹Ï8öyyÌ*„¿ßD¼%»ïQÍF1z_à"çÊh8T·éN@¸ìÀ)&'“ƒ£
+ï€5ÁÕµ{§BÉx¸¡‘èG),M F¡ñ9Liû5ð?gaM©'ùk,ÇdÃ5Â:B°š)Çž×ÿËVϸ+Îßæç7U
+¹£hN°Öqt>㨟ԜÔá½Z]ËÕ”îôÏæ„Äu
+‡@T‰¬ì%„]g,Âò." ÕAãGDÊg.™Œà~ùlïí×6½›ãRAç09¦“œÍrzsW –:NòûJø8u Áîe+•»==¬iCŒù ä’€-‘•!vL üÁ ÀQqå÷
+äÞXd`ãü²QF©ˆZ3µˆ:år”ÖÎN®áNµžˆF•ÄÙúŒ#T¹>rŽ©ˆ¥úÊ{(¥IÑè:4!¨ÐOí³µ„Aeú &jqQôwJ§Dü^h–­TBµi]rÈXn̺¼¾½†XApªV gŽ7ã}¿C±Zñ9f r+GÛiyì¯ïp“êF
+ì<äy¶†HäL¸Zd˜«!+¥n
+¼/uÃìRòf¼À`(«¶gÄy"sÁÂÆ¡oÖñQoñLY¤B×h8
+fÑ6ed6O…#½‰P"¸iŠ=¸¯ô=Š2A ‚ÒBÔÀZÙ«SÃ{uµD¶¸ (­„¥!óñã–CT@ ýå<£ð„£8;Gê Ó9Š¤vOªÈCgç B›’]:ïE$E.±6TÈ‚e‰Èà]ª"c‡ýñBŠ6D
+ž,}®¾7µRîïçPê\Hh†Íóô]L¦'jëä±<‚§÷N>Œb«Qnî ÔÆDDïžeQè3"ÐÑO1³SÈÖ ì#‚RIFðò_;ÏCDÁ}]˜ó}b˜Î³ ¿jå-à°4LÄñY§PÏÓË:Þöâ¾³×”ê
+‘¢4(îŒ6î<KJæ·Xûa­ž¼¨`o¯óŒZ€æòÄdœ½xï­vçzÔ:ƒ¾i´qh^´†o|(¨ߣº(ç”Ëclñ+°Îw&cŽ-öpän²ã°†·7\ö„0+a]8PÂÞáXeQÃYØ;ìÔ5‘½ÐWÎ!g]…àFn Ñ°ˆ(o(ûŽ~ô„utžnHÉÔØc L]Jês°£ Å@Û E.¥äüÓ
+”ZŠ ~xF<X%vzDqt˜Ì‡ëÑ.-$
+fP Ea~tMÆ\¹D¼oA “ïµHÿZ.¢Pu$¼ªHÈŠä#<Î;kxQùH…z„ÂœôÏTÆ:üÛ•0ó1Š¼È3ŠM@´P7!y¤A„$éjRb^lF$­DZUËÅ=‡»44ìõG¬³>]¬Ãi@"ÖÁîÑ,*£_œý9Y¦`r …º•—«òòë*”‰ŠòûwsúáæœÖ$]õ9™g·6°ÉýjˆÌéEÉEW×=#0¨·¢5éíÄg”¼Âdm¨7ìm[ã‚ähæ~y2µ'+@\¾èš€~p%8N–!x=Ù°eä‡($ÙÒMÀÛäŸu 'mkÓ˜ …Xœ|íÄa´|œ A¹Js2ÑW›š-·uú7ÿñ;ÿ¤ë—ùóãç_}¡ rºRüùçŸwëC)àÞ³‚mI»@/Û¨ÿ¹£xäa}:"j.û¼KÔ=ÚãYb9"†6ƒˆªM5â´@é…Ö8¦ˆ»[oŠª‰8fîÅÊŽ†b{šùFŸ Â$ihSiž¦í± I;9fë¼O¡¸%Çhšœw­&=ÌȱèFÉÇïø¨b [iÇDñPégù2gDŒj/„ÍâQÃfý´>*¤ÅóÞQ"ŒQ!œ‰ ö«s’¸ ÁFöÔK‰T›Tr/ õz”f.ÅÓ&¨,›|È G–¸¨.!H¤q@9ÎtóU P‡6Çé~èéÄ9”#ùèPUO@ýŒþ¥š»šLÓ²Q6zdsB/Ò¶´ÑÞ
+ÞØßG¬OI=ˆ„< h—²ÒÅÂ4ÞÇqÑ3”
+9F££çz|—‹Ñ
+)nWõµ™ñO4‘O²;eCFåÝPðÌ7ÇòJÊCËÚ¾Ô<]5è‘Ïi'6ª™
+²4‹òe³b„îd3(Vº‹Œêóa¦èa€”i®oœâ¢,A³Ö!+dY¸¹{Y‹ÓðÜÏŒsë "Ú’ì“"ÔŒq–OÛ‹f]RÓ5(b ½ËSŽyçF¥5N9vT¥•½×7¯}ÎjY'°²üÿ:r¶>ÃÍxI¢;Æ`ÃX^°ºÂ[pœ:JË
+6 ¥Tï:bš 6dð¿Ôd/•÷ÍwŸ¿üøñן~ûùóŸoùé«2WU ùúùæ§/Ÿ?þöËóÕ÷ß÷áÃï¿þûÓ—ŸÍýúù™ÿâ¿„?^¹Tæ«pi4/of3™ûˆR˜Ó2V@¨"tuJP^ôyö2æ¹³-‚Û4"@/
+Oua– Ö
+KѺ7¸8ÊFò•_³p‡>@–„,ì²859Õi"I:32
+oˆwEG?9#?üc9”ÀZXô]†TE¼Ny=±ˆ RÄà˜ Õ>_Á/ñPÅïÍâB5€ãŒÕèêYÃIÌV„`µ"F¬†çP5Hèë؆D "Qà6ÊQËe¾™TbàåòKÀúÑ¡‚[©ÖÊtÔÚèÕ h³ßQÂõ9Øa5â«É ç„xÆ*È'…
+ãÙÍŠ!dd:2&½fLgÅPŸ ÍnÒó#`vÅuìà[6
+e!ÅÚR¨&kì64¢‘tÚ~p ²}ŸjwŒôò¢@ÇŒÔt~fíg£´Ñ½øV…éOÕ@X†ÕÐû\$ÛyÕñl•ªô›N=,H•2ÀÞ¼Û¼š}ißéOã8C–ÚYq
+ò ÂÂDXƒaÝûx9q@«5ß•
+÷u”c¤Äl²8AÝQš¬˜t§ÏhÅÈ
+ê#Ò*‚¹'ÉŽ^cäu¤@2±˜orÒkÝ`À³ º É7ûä]¬ôT´ªïg«2àj†ÇBw!sU±@ ð -n´ X Ó¡Ð}©‚×rŸeL”ë#Çsr˜z&¶Ý+ôc ÍD¤9lJ´•|dµ|¨Ë*6Yúl­ðqk°ûÙAJ9+•{X>Zg9
+\=0äæåAPTAö¡¢PØ€õ‹x_ø0³8TòîuÁmĪíêrªdÑm¹K‚; 5íx+:þs8º[" €´835﯒u@+‚}•HÖëø·â…d|õÝþ}~¯×ño•ã7EO”Õó÷Øø6*©Mjè²ø¸[
+ñêW4~;e à ͞
+~1\L@M
+€Ÿ§ ®¯HT:ÜŒP¬
+BO3Ü@îÒžñê
+ß`bc‡eÂfí.¬Ëasô5*‡yHÝqšX˜zpo„$(íÆhvKü¸:ˆßýÑ‹×Ŭí»ØdMÄã‚OÜü•ÇéoN[”å®æ{P®"©#]h¡¬¿R1µg©¶d7:¥É{IÈãµJàxÝú=²H-¾T1ˆg¯ >˱£ϽwK²ÀË)Kìùÿ r•­xåæàî!rF,wy™
+ žÖÀ“ð;‚ª‚ø¨}”ãå·–kú7fÈŠ©´‡Ôg«Ø×)§„b99ZÚLk©ƒò°Ó𬴓€Žd,uùL¡Aô5¶£%xw
+lÑÐ-zÅ8€Ð]Y²Ý8ÜJ® ½÷žzý0Sõ@:¿’x40×læš^…sZLÒaJ˜/Þ‹6"K´Æ ô­êØÇÎnÜx(½V‡ ñ{›js«91iâäU»ŠÏT”‰˜¤—ë4'©YîüóŽÌÆà‹ykHõ±/ÚN¥Ì 0r4iª+î&jêŠ+òàËzSµÃ¦‘­,Vì‹®«k"ù}Г´²|)9!ëU§©=¡ ‚¸vŠ Ç
+ï">ÊHFɯÀ¼âB-ù`O.DZ€äýn7Ä×X$˱]þÀ‘çp/^ÎüΙ€äѵ»µ“
+‰[-’]Úañ"§¡yà&jì ×ú4é|· ±Ñ«b'ò­ wu…¬*0mUøÏÈ—6ƒ|Ñ­¤ÿ´à˜¤î4C >#7©æ°|0„‚é©Þ—;ñž°8¸.Gß /;Ò.P²Dñº ö®NX3Às;™€ó¡Ê¡‘ÿð3@ù Ñ ‘9ŽÜƒ¦ïN= ðĮĿéz*Îp3àâ=8d½ò¨“=[XÁ§Ïµ\ÙþaÐŒÞhÂÔŠr@w‘^•äz(‘‹ºÐSáKÙOÑ­* 'ÀH͈sß34¼Ó¥HøÙ}¸/=qœ RYkUµPÏ{Ë JѤ¡Lh`P°…¦¹`‚î
+Y*iÞö2Òëô’^gÈ\U†ïÀNp…WãüpŠJÓ¯ÏãÙ²Æ R@ÒÇ]Q„¶DpÆ´±Oaª®“™@w˜=«Öö^ˆ<@µ¡à™hþeA.Æôåáߢe£**/# œˆ€k3bÔŒøD£q
+M›»DóÏIv
+Dº„ÃÃ1ŸhçÍ„ @B‘·E3`þôd4 ½êƒšHõxØ(æÍÅ-µï»ÆçVßÏÁ¨*J(Pþýô°¿MmDz(5·»ªË'¹¾Fl†Ö¡áãc­ ëSåb)ÛFÐh;#Š-×
+Ç›¨¢fR± «ïÆ,RÅ\â"4u|…÷°ë ÁȈøyÁ`þÌÌ¿y½ÎP „‘1Õx4Ä·©iþ3'\Œé‹ T=£‡“@ILäŒ-Æ …z€_ePwšYT²±ÈÌ9.,pÎôëÛJÊÖ+*|Rȱ9Ðù"¦•!BÅó= €1F±–AØœê"e4
+ʌ
+DóÄ÷ê}Qºj¥Õ<R¦|jÚÚáÆü[P "Ý%2éú&yr½Ë¼ŒüÏÍ—J«5O²W9–ÚÖ‘aU-ÖQ›?Ô@ÑÛx¢¶‰Eöä<î…¬>qêƒ
+c_é~èÈœ¤‰Ö»bCûzEÔ\»ý™ÞªeÈÎ[G¹B£¹ûCïÿ Ô—æc=›Bai-ÛÔR€Éôõ¥QèåèºA'K#âóFj¸¦†¥ÈDaÕz20Ä!òŠ¯ÁA¦¹
+³«À ùƒšQe3Œ#²¨½Â÷Ä’©ÕÁs4×6óœ„Nú€R˜Al#¶¦·•Û¤m$ƒ ÷Áé4¹âSª4û{ÁùÍ ¾qiÁpŸ–TûIêÇœ’ÒmûD(HJ„úŒñż䴅®zE=c’ê˨-}:®ˆb8¥ÜYÔˆF=™‘¯b›+œ ŸŠÔñšHÝ“øV#ŒïA9eFáhwDµ.v3wàû'"äv"Ô­A1c›7Oº-ö@JgDáµZ…‚öy'A#ìÈ“¦;EcS º ”àoˆ:Am€EE!Òž¿ðý1ÿ˘—*÷£Bñ2v4Ü®g¥Z¦wÈ~xåøn b:wÊlU4b˜“¬)6ħEÄè_1æ&C`"H‡l¿8íI¾È“‚‚Á}‘`M¨9÷o‡„Å Ev7GK™w<[£¤m
+s{Ð ¦Iƒ5ÈžËOéÚc‘)“b"âöBVçõ†•‰Q1æ!Ùñ4°†Îôã²@ôàV­€~ùñ÷;äÊM̃ßjî‡÷}l7 6Ôá£o(Ú»ãkÊÁ™Ï§èˆå¬H˜PDîÀF‡„g‡vð&n¸Ehi3Xaa¥ëÎómì Žêñ'ßCñÕøùF
+5Àažp?ñTëSŒP4uøÓ$BÏB5FÒ
+Qõ‡ÙՠÓjX*êÌ)b%òÔÁ[°Ù*#õ›]OßF–'ÕçÞ÷Œ*9\þeöQY¤En9d‡TªöÙI§ûr!ÂðøûÖÿóûT‡b€üÉ×Ùý"0CD×&ˆ˜Æ]ä»ú2?ó·5”û§fñ 9M×42)úŽõäVFî if¶CÜ‘u#"SVto\4:–ô…4ùÄ(Uª
+ísð:Áó=ô¢¡qúÊQS ¸{èñzˆ• šŒÍGdzcëƒóÕÞŽcÖ÷U×K$ b­î•^£fhõÑó_Z«‰ä!()u<¼´Rå&¹f°ÅTøË@ž
+ƒk‰RÔÛ>âA$øïîÒ§ž™—gàJR I¹4„ŸËðÆI¼S7mê„7u¦Tõzü'æ…ýU®‘(Liµ•§@,‹vÚ¡5LLV ÏŒðÓå¹…¬5~C‡ôØüM²u
+ æj_UÈæöyÕÅåSZhQ‹lÑù4⪞42(¥li¶«á³-÷…ëçmtýÕ˜KA¤°UÒ
+¼“·W¥àƒ4ýp×®ñ9VcÇç³$"|9’ÓÎXM„F €&ií/ PˆSÔ
+ÎÅ‘ ëÅ线®Õ8Š+cKŠå€Ñ#žÖDÀ²"ö¸õ²’uÎE¬žóc­dRaó¦Êýÿ¼<\Ë].™AÒ¦ÒñÑ,T¨³ÆNš9%i½h ÒE»g Äôrlî“KNÑCF% ÑÀ¬3ñ®n×nÔ+#êè¦ë£or
+T)9O¦)žd[(Îc
+±çµ1)ôá‡=WZ6ÎD›ß" s/ ©Y,¸§²-‚1Kñ$»  ±ŸGGǹ½²çðö^ü‘îNµ”¸_™—®$®_4tnüüÔzâ=àç¡2(¤’ºÚÒnÄ †cHùÓÆ
+ë‡Þ@°[úéÚJÖ8÷JŸ¢°¾a<Lµ…#¦2XÒæR%Tzj¾¨WKÙ^×ë\ _•Ssp÷+”%Wußúà5ÜBXÆè90t$[!°²·2_¬Ók4€"rÎeF;Ÿ69wUˆXiÒ(9=¼"G…[46×Nc³W´ù½^w)Ê\ãI”!WÔTêa¡ ˆ¢D4˜:q™ã¸A×SQV@P9ûe%h6PL=Eó‰ZW»W:Ƙ鈕õRÉ
+H‰Œ—A’\7DO ;ô¦ƒ \ËKÝb"¼jÝë—$~M¨ê—§¥°$We“H$Ê1fÿ©Ý>ÇŒ°ˆµº×«V>=ÂËl¥6;YÇ\6£›ûDés¬ê7ˆŸ?þþQ>þúRÇ×ÚÇh=ª õx/Õ&_ÆÇï5›Ë½•5ȼ®¾úì}îG)£Å\ܺ¤”Á)­®°u ηcÔÂQçUQ
+÷ðUáÿ=WµÑFX><¯êÞ+¡´Qç9§Wç)³Å4ëÓ›rt¢Ÿ6úh³´Õ_
+dþ Ji:ºKæõZ‹Emeg°Åç*ÝéTî‰Íh _ÅC¾9x4Ÿáçób–rKÄ&xfW‹ót¯œë­Ý@²³­Ry4}wŽÏÝÞ²t0ªÂsš²ÂGƒ<c²+œæŽG·´.&•™/4㢃¿Î)\laÆj¦7ÚZ«ò«ûHCÖš([Œ]põ Ä‘Ùn»gÐ× ·16»ýyDÀXÞ¹"£šÝ œ‰?Ù¾Åõþ¸r¬¸­º÷ÿuÕj![ÈO‚FiŽ
+ÑÙd÷o$rƒoÎá…}*ÙT#{g@&‰0ÎìÓ'(lEKNé}y DOvæÈÆ3è5„ô1Jêî·@MbCÂÚ¹Ÿ$Þ€$út‚7í -%³À€MÍ”ÿr*m3“ˆHhÂ`.BNé”Ø9œÒx}ÊJ ÷ê)m¡/oj1ùW“cBò¤‘ßAÐ47¼
+#ƃÅwç… ýzB¾¦ÎNsسƒ&ýdp³¦´ œ4²)üs$H™•Wn:?Sçv”ç˜)—ˆém]ó„ ¦Sü@cX=¯ å>/™íðâ s[qG15cTäõ]Ðs~}§Kw3oÛ]p?Œµ¥È þ„Î@@ lœ†¾º(Qý$AV‚!ÈT«=åLb:P[Mõ©´[AVOóر¬NÇ3Ʋ$|FEÀã9eQŽnÊõŸ^å®Á¶¢”yFZ‡;”= ‰ò±n û*¥WžR·ûs꧖w“x§%ž4¬[%êàä0V¼r¥±æ¿Fƒ5MñSþgÙ)‹L×t\6‘%îjÝ_{^Ì v)W}ÓÏ‘ßv˜rZµÍõoÏ¡úˆsÀ£”gÁœ[R yWOuN#(K×UòB‘CA]V™}a—”N?H
+Â>b·¨}J‰L+æwA’Eæ Ÿhûrbš³›a.jÝKg“pË5–Ašv×Â…Ep"“AdUËp“BI¸’¨êj;J×p¨ä•^¦›ãœÓø p‘±½ КåXšûÔ‹¯Ñƒnórõ©®ÂPÈw¿9§ãu+ÞÅóôÉaÖ÷Rf‚4;6ò½ü*¤ÎŃ„Œ WXBWÛ# ؃Ê{¤±µVÏÔà|:¼Žå¦÷
+3+I\B˜8\Ìh~ !SLÌ£¢TUF—CŽvÒ3é=bD½Zäs0*=²¬a$ˆ^lè‚bM›Ì#T¶S‰Û–Úõc‰nAš(“gµ<GÓ„pùå_1Ù…-eÍžQ!JÚLþ«è¨‹‹N~ºB ”„P7‹“<H™©û8<Èãã¿ÄOÿ/‘^^óñ‰¸B!iw+irý_GƒõÙñÄ¹× ‚L–!„_´í
+›“Æ#“p%‚tøžO—&p÷d3æìEù
+ÓÄ´ÎImôH•÷Ô¦¶!4­õUŸ(ùÊddîÝiÜ® )~£“è愼V2J@¾aöJâ`SI öðzS49Êž¹$Š8éK×É\Ç,jOüخ܋h¨ îoɪÔõ¢ôKÁV³ë¢' ¬\ËÕDn?¸èµ³á²ïÀ¢$¦ßÙšuBÙæø1-AHÐba{4íŒKE°r]AHd‚zWS-ŒÍIÛ¤¯g\T8‹é
+K‘dj›ž3n ·²ô úõÔe3ð—rà—,½€(.W/7”<µÔ¥¦#¿Ça·±WKâM×j‰.œ 8“8‘5èöà/7W9É~íN4÷`Ïãš”ËÆõ—AÞÇ\šg3!…x¥Á—ý’WHŒõ çý9”¡è=ŒÏs ç2ÿ[KÙBa2v™ì…­cW¡·ÿ¡¼<Žì8‚ j| ­ÅWxëÂÿ+_vWâÏÔ
+.˜VÄél±˜U–Än£ãÜ¢àcãˤNpÄåìùtï(‹—_¼­á±¦Úe!ªÐDÏg+LÚTN'}•*¯Ã ö×ë ô]ÓQ‡“ál+ J"à ;7+\¾ ,Flé¤"^@[ä¨\Äz ÈôáÃpã’´ÉÉØiØ´+!Az»„ÞV´2Ø
+¢¼Ô ^1>u„ï0‘O$
+ºøY¹y¶ý «À; @غüÉ!ç=6ùÞÛ[‘t9t¨
+‰@m>]ÒæÀ^Å ~ÒÅ`ÃP%HNÎ:—¤>Î*É©ôø”tÃïW䈱õ“nPÞ
+|Ô“Ÿto%^ÒuŠ®I—’Deñ“.±ê‰ÁI‡èîI—«Œè_TwIº¼WoŒÿVx¿€åß².çlQ¹ççÑæ/+0P~øYWÐ+J@«ûaWÞƒ±áútú)ì*Æ >ÄÁ<ý°”I R t˜ñ]ƒ&¥©YÃçgZ¡wbzŸÇ\[èác?üüu)i¨¯Úó¹ð5êRT¤ÍË‹ ß³î›¸?Ö=cþuŠkÒ½•Ü‚®N‚&0º)íãÞ‚.%bµcã:Ÿ‚.@W38ZYÊå]VŽ˜â†}.ź´p`­›¢§WâÒ’t¢{ÐuŠ®A—‰çÀ ?ëB¬K×ë"./êÒ)xQF˜~ÔE2ÎIdqâÓ5¢Ò=Ê Ò¨‡¨+N„æ3Ú–¼¢Í°£†nöáGÝ i×fÀ%=D]`€™ Mf™ŸuAvFìÐü¤{+¸å\!m“U¬¡?ä\¯è’sUÒÙ‹f†Ð[Îsó#‹GϦØHuú‰¸Ìœ§sÅŒ‡rí8ñôsƒä-†úÛ|Š¹4÷æÅBœÇ]b.Ýæùs"´êÇSPC<k.ó)æPÌKd늿Ž”«B´ö æsei"s°|äSÌ…êÐ5Æ|¼fás¥ô€¤YóAß%æRÂ>(ñðÍ=æ^‹Ü˜ë]b.H*öDÔ¹¨‘˜8ùážrï5÷ ò7ÙÝ!wtN„¤pšM0iDâ˜z_ê<Ú8e@å`càÈc…Åþ탸·–ÆYG¨”žqÐ]‚«$yáJwJ~î­èËX¬ãÊïË°'ÇÅôY»‚Ä †ìl¾+ŒUÙ†Üg•iÎ`½Ý߇ŸUT‰ÓW‹¼$¡í2,9H…ù)“Ü … †¿ Ù› Ú‡ˆ w°ûÀïGT€@ª?Êêò‰Ò@'éa”ÕSô¿WÈŸdƒ1U8ÊÓÎBŸH™8ζR¦0½“¬w&hîþ†ÂÿRÔHËYñeƒ€Ífð+™^ZÓ6`"ÅÖEëôàŸU¢ýȹÉRÄ…å>fI&¸¡¢Ìùd=êMe8÷¹ÓÆNçðÃir*¸pæ¼íu
+‹}̽N Œ7ñi&{ÚÚgRnhSÎÀáíôÒ¹b;;ýq*ÿÓÆÞ?zNj †Ó#¹_»ˆ¼I@›=»%Xmš$(9&äшºä]E·™ÙlñØ°¤˜@·ªS#OÂÓã·Íª%Â$€",§Ò1Ì®khV­òF
+’Ðù.I ¶(m˜^SÇϽUðy±~|Ü
+ÚÚG%^
+‹$1aÞ6á° S` Cê_-RÞ£²få‚ÔçCÑF”_?/DDB¤­ãäOuŒåíaʇ ©‡ö< Šq8|A0€¯Qr
+„Ç- h|@³§½÷"wæÀO
+N#}·H×!F£Hj†-†SÄà`7E±ýy¦ô0¯ô sñózÂÓ¼àXaG{8ºŽ¢O–#P]G
+«g
+^”½Õ?}—È| $Ø
+Ü@N‰]•Ò˜2ÌõèÚû9A–ÚÆö˜Á‚pS¼'oMRn©×HXÄà€íqÁ¿Bp®æŒ :œèdâÉ
+o¾Ì0kSÔí $<àÿ,u}x
+¬«ÆêUë…,“3YÌâ•=e~¤^z‘’ TJdXªš—£ Ô÷mw€úV䜢˜rⱯoåÆBUfôúÓEà­èõ˜š@òÁst3 lÁlü)u‹3E<ª üó¨Ù)Z%%t®Ç;®n¿Y*j&Ž°‰\hQ‘u8Þ±}7¡²Øš=E¼–_*qkû®dy’ìî.jDÚZšn%bú*ëSwÄ˃r@¹kh†
+Š]ëpŠ^VTÅÁƒÏ/fËÈ6QÊHÚúX%Ø«ÖWæ_.Ì­ÏcÊ
+5x´ÒÍkê͘ðJor´%`a‘Ù¹ÏÉ’7´ %ÄÞ‹Ÿ·‚Û0¿¬kPrWês¹\çŒ
+é”Jzc8v =âR2ÕX†¶¢È3(³€äý9C‘a.­/û|XNz= iûÀ
+ÞJ {x²ä:
+t°éÉ”””Ù´=Æ{ (æ“zྼ8^™ ÂHY\œï¾«ˆõ÷kû–ðá¢X|CúpFàß}žð rà¿öâ¹çÐÍJ'Øñ“ÝÔ¶ófÀŸÀX ôëÓ¥Œþ²W`áI¾:Üq²˜ÁÊ ³~8x»KÞ¿äzº¨"L1ãd
+²ê8ÞÈl©Bv6o"l“ÿ©&!w:òd‘“i›vÄjD©WÈDÜÇðyx‹¸ÉHr†—mr‘x©‡Y~)±µa
+Œ,  [Ã+(‰áˆëÒ2£÷
+Wqßk:EVâ½üçÜ$öPóJ4ÿ*¸¡Üu4
+ÈZÚaÝãL¶Œ±`><– DÝ "i ðÂÀÛ{eYa~=ÑAòVí®”ôÐiéFøCL"k–Η·€ó ²YÄŠ®gÐÑúÅ|â
+v¤”+`Ý}t\О‡ï>š Ä‹áB‰¾‘ü’ï£YöÂðÀ‘ó“¾¹—M+ Þžõ»E^àý_”.‹üñ7¥Q¤¯‰¸Ìò€Ò®/<Sƒ,‘7bNÕ©Y›~€Åí–®
+à‹O(¡¹‰faÆJH9ü
+L†t¯‘P }ÿ,Ç[aé5C©}“ø¬"WwJ2é@‚‰^å]"¾d½QI£2­\;g5“ü^@NåÑny„Ïš#yÄp Ø—¢×.j¼§
+@á?ÖT»ð”ÚÿÔ'BË·/šÒsè…)@UV~Dë;‰}ɲCp˜9“?•¨ýвpAôVÐ(V/*9¤¾>îñåRcŒãU㟶*$ó†Á÷…ÐÌ$µ»š‡ÅȉÐ\úa¸ûÖRuEX¦
+ª×L‰k%3©æö! F–)5:ßâ
+•&°èÛà‘̦UtÓ€„;®Çˆ&Ÿ®8ºîÛ‰#:˜`;Æ
+¥Ï‚äç¾g%<4îðÀ1Nñ3´ ‘ôýߣÂ
+4Át¹Îc„GNóm É.´D¢–¨<±¼ÒSƒ£X¸rÔCQ’ê'¸‡ÿo«èmÿªèfoövö& ,.ðï@<›¿^ÜÍÊ–ò™Àïc8
+Á}˜Çï¼BbÊ’ÖÞž¡¥7éwèjàáãÑÉ`Äúƒz¶Ð̬b@äú±D«Åï—>CWÛG}¿U¿5'‘ à´ y0÷nLÿ>c)s)âíL
+öÌ(6µ…\š P5Gö#¡WëA1„0z%ßÐ>ÑÁ_áÖä‰NßÀ;ç.Ó'÷ìmaJµ´Õ¡“1‹ÔÕKdüQ'ôB)ÔÜ`läÈŸLçrÎŒtƒ<6½&—½çXœX¡ÅO%j¿lÏØÝjÂ'ω%ÊȦ¾>c(-«¯ é\˜’ɲðO[%Ež½ÉçørÆÑu{˜&^Í뉹°>ÜU³2bÖ&8S‚Á+æ`¿ ia[{ô)6fÌ;8ìPrd¦{Ñχ"Ø·ÖdLËb¦CQ¬¸q˜MëŽOBWUDÙ™’¼•¦µ­q3.ˆµ:PwåÂò[Ô7‚ ¢ˆŽa.à™QVé¼ï§Ü&éÖÆ„…J&Äñ¾qo9CA!zÏñPá'1no %=}±q°Ó6
+A«$‰µ;oê{Rz8ž Ïr-™’,H:(>òøW˜ò£*’K(ü*É ƒìþÕÊò±U–.ë€êâ¾ÀFÀJ0Šß‡—eOÎÜÃâòQpÝææÒ„í°ÁléÉí‰fnÝ 5çïp8Ö‘ÝòÍÜày–ßÝEnR™&kë—
+²íjúŲÂ4l>ØÜY"wÚ`4?j M »næ·†"ññÈ‹†
+1­aõ:H7ùÑâ’À{Éì5/í3®B‰ß‘£ °xÈ~åÒp̘VÚ*Qg ¾±d< Æ’¤º‹2ïEмA»% :m®þ19lÝp÷4’”‚Ÿ—Mã´Jg]rØQ¹Aþäxzø½Ä{Œ@±:ÞŽßѸ©<uòÏ@¨¦6´vš¦¼ÐÅûÉ@õ}Ò+*ôî^õ‹Èdôï¼b‹ÌNTÛŠ|*~`;)±Øp¾òÏ+JMÕ¤±vžïUÅŽ„4¯løV#÷;pmZFQ¯©k ?Xê¶bòá4÷­B—n¹­O•*wâ"/Ü77šÒjÏv0Q«ÙØÔŠ¹í}M«gQr®>ïþ((BTXŸ°Ÿ¾ÃU™ÚÐuü6Z71±‡<F\RÜ×´(ß äk¾ /+€µâî³yX¿[VƉ"*‚Á]ÖðEwöýz(Âè “Š¨6Yº‰P=¿Ã*IÊ›4´)ŽØ*™ëÃé6ƒ%™gÚ¤ µ^@—„ìWQŠÚ&Ö¹¯•RˆS Ñü¨Ž"*ú°w›¢X®¨Ôðãe’œG®áô|çaí­ná­|ÿmI‚¿ì*”¬Žýl5T$D[.% ‘’Žê~G›:@#kÓ¾Ó(êñpsÑ’²/§µ Óf~1¾65’X¹1˜·ZÉ¡éf–AŽ@>y7§´ÒX×¾^±‘m#&¦hI$œ,Ñã : †Å:ŽTM”‡R¿ˆv®Õ•30L §Ø£zГg¬°¸Ê +,é0¿T§tï#(¡–ì”Ø8ÑmšÙXìúô¾ ê÷•ÙtZB´}ØMFž'v L¸* Y& -‡rT@¦ Cßµ÷cH#¬gay÷Y¹O8T)¦ÚY¤
+¯Ì¹[C¸êÜŸ“ú­ÀæÍç¡¢(ó¿AäxÒË;A·IT€04qORÉ)ƒ°B£cÏÌäbÈÈ’ÙX6h`>ÈZ&Ãlê@¾ŠÙpu#lR(2WÛ9èKVß#5]Ùå#=¯èb†U‚cd}¸¦o©)$eÂS(Óƒ5Oý-$±¹ŸF>èG˜µ¹AŒ02$…¨ƒ¢"à çÄVž¾ƒ•€ñªÇÛ
+Œ Kæ] ‰,Ñ’ÙJˆblp•ëýy 9LÏͳ¹SDçÅ[6ÚÑ[Õ”fÛ%èÍJghS³ô¸Él; å Hqo‹^}ãá0î„ÛSôþT"f·[P¢+’…„}SNfLÑuö³‰ë~ì’°’&ûf߉¸‘†(¬_Z%p0Ž)öy\"ˆ¡QàH¶Æ-S¾Š‰[›q(ãïm·™yÖ8ä*óÓ°¾úÏOc^Øf JOjJ7Q2t$ We+i³‰-<^¢8È_%Ì+ó®†k3Äb:«^’8rÐCK‰å&O‹O*û;䵬´˜§!?–¶ØTþÞ-A¹è阸ܶÁáIqÜ,òÃ+r‘˜€¿`sú ¤G¶§Ãrh¾ü„…â62§_M€k
+'Ü;P
+æäå¾ð®Sv? ûNÍü™wæf·)uÅHzzŽú”d“ Xî… ”«Äóí(H«€q9±§ò3rƳ=æ?"`âJ.jï¢}OË~M¢Ÿjoò>¨1Eü™ Å¢çè|d‘"+3¤?¾S“T
+¸øjåß I¿äŠ1j<®
+\Éâ@dcÈZ¼ÕbJ° M `ú:|¯¸)ì­¿ß-ºÉ°Wt‘añ[Ñ/Çž\¦Û*
+äééA‡×ÒÆ®þuW‰£¨›HHꥺ
+ªíže°!jsJ œÄ¢Á(¾  6’K”ÎúBÌhð’Æ™…lÕuÛ2òqÛ!¸[pNð :|…Ÿ«Ãà‚áµ(þ9ºé0_êZz$tyWG‡yp«=÷äsß×üù‡7<9H©ƒ.f3«Š~Àc3íµF¤3åÙž±†ÞÞ˜§¢*-0ûšèyÀ€´·Ìß±zA7ZBÜAÙˆ ½¥¤=›c»8éLgÞ9´Ôª}‡z0™IH'Ñá[²ä«íg”‘x%ï©9%ë(å](Ë “?}'Ò…4᜗k×>ÜДŤØÅ JÁrÛ«ðù(Î!…¾yýZ$y˜\‘>³l{‡¯g ƒ-"Àrµ[dtc>Ý–0ðhK»ª•àmÿ#¦SbM [Ù@Ü —×ï0LJX>ý+-Gk§vÐæÙFü5ß fø-.9F?G•YiC£½d'v¤+¢üð8`|Ž¬>””¥ú¨ ŒvŽúÈïŸÞ¢CP4›÷éïo·(®Ïрǖt˜‰ o¢5›K£Åk…´o>dø ˜1âQ…¦j7o¨üèTí&ɧÌä\‚ÍRQÐ’ûöö½®˜U©îûn€Ç03h·Mÿt4ÀŠ¡¼üäZ*}N7’5Èsn—ÑH¬« ÿ{Â
+/’,Kæ¿]”2ʆf¤wo»¾Wtq<gQŠØ‘ú8|ÇC›‚£¬ãÁñ\Gá:žë@ï\a¡Û€Ì_”¯ðà¥Wxìm—\죮0],6‰]Ýîà
+v%‰D¿X&àá–h½ø}º€±8îà_›¥%„¼…:=š Kh£‰e ‚¿­h0¢¨5O£ˆ´£Ìñ-þÄwn8óuûÆSk
+˜‹¢®®¢&A¨ZÖ¥-¡î+ÃBÁ¨œ¥ ž§îI\+pHØC–+Éñíƒî5t+2dñs´¯hžüˆËœØ©Ð$i,ö$è*Ñ™’Ãñƃ(1Y¨j.Š"2ÒâÞã´ZÅ}!`kAR@@{Âß×0þùr‘šû—@Þ?—5ûmE
+E´S˜7ÇLƒ ù
+Œfá3ÜdX`s– |ƒ
+Mq¾–i› ÅC#ŠUdºCnì>›˜ 7Ó’!+@O =4Šäëò‘Sâ’Òµèý¡¨Èúó4Ç4À)ŠíÆË9# ¢'àÆ–èÿÇTP¦Ü=ÁÆZͽ¿^vUAA4H`˜Ó¿ÊÊÌZ
+(ùX®¤ÌtBk;µ'f[X•:ÝI¶R"²6úú`p¤|§…óo=—Žô»S'ˆ³y‡Ž´5šœ5Š¸O,»@œÆ A¤8¸ë«uª¢6#eëž ’>ÎJ^tPÍŠ#vVbÅWÛúhr wº¿Œ‚MÚ”¼xÓ‘ŽÉ³ ꬈„UF(d´¿€0Ž)nl5´U¼æ6©Â¸€Þ_€T×A·æd›Áõ¬’{š? 2Lp*ºh4pM …¼Chu¢:îÕþi+Ü„«»GNˆB1kl…sÜ­{Á€®Fš¯eH
+´P.U{ÊÆ]->ƒäÒ¢,á(´B¾€ð–Å4:5{b£æ¹ÂÄÆÙ³Ú<Yþrò{9Ô‘M@q¯ïâu}rÖ÷ïدšmÂ\”©šG8ŠµY:¥‹_ju1Ú¥>. áQ™d%æ÷Û×·9HÊÆ5B
+J¾4P3+jEö
+)‰d¡³‘°ÑBLi [:).iüòЉS¬“²!FAƒ"/Ÿø©8riS¿±;#Ülл([PÔî›A®À£7ÒHk…Ä[g»Þ¼aueÎ:“®`uo`ª2@Й3£Gä*éW~×FŠ›ðío ka=UØ·pñ¥˜_J¡
+4y‘Î]
+¿¯ÆãAîìq+«í齶¬gø„]”®Vñû,ÉEA<nò™Ò:U@á¼ÜŒŽ<ršÏÔ‹0w¾Å
+"MÏ*¶²t=“Yâ8ty†AQ¾ zÚî€x2vS÷¨¾¢†zê¬!îåvß
+ )¢AˆÓøvhäD—CøÏdp0”•x\æi+0Ì“…wTb¶Ìj Ù¦$̓ªŒ‡Ëix„ L S±< ‚Vï¢8E³ØV„V¦]Æ ðœøPÓQL*åq íæV<I5"KÓc)t©A¸a¯ç)Å!È52NSç[u¼ß#—ùVJ†HŒ²ð²uøŠ®*ûrHRº%úsANN*ƒ\ g+„³“ øýZ§ .×yÔMcÖ j5gá9±ž§šj±ëÒ£Š„qîG<¦„Û–Ùš~ø¢>0„TmY”Ëx(‰ÒµIÌV* e‡åä© HãoÞ)OqŽ~Ù+«2"Iaóã0"ÕÚ45‡ âCýM\ò‹#Ú¨FLjaD©ÜiÅÅ;4J²Û#ìÕ"W×8ãÈʸÜMù)r™Êsílô3#õ Âw‚·”»kíû2
+…(Ì1‡r9ñ,ž
+HDüx&1äñ¢ÁQN_ŽqØŠéÉåkÃ)Ú©vî) oqšÈ:s°8)Z’aª/Â!  ÷Ä,c'z•y‰ 5Ñ6èõ­Þxt¢Qpänª–éD·áõó{“)Yˆš|ó£ñÖF6EäI6ê܃˵ÇMÞŸðÙÜÓ$Õ8zó’/j+"+ªSÌT¿ù¤ÿïß1.Ùa~ü!(AÆ#OÃeN¬ò®T„üeˆJø*{ž„û„94˜©ø‹#2©˜„\ƒ`Í‹¤c!4‘I–’êm#º­^‰¿ƒàë¾ôí¶ezÂs¯~–‰¢4â „=‡Ñd
+o«Šè;A b&*-):[‘¶‰bP„¹ÁO¼HèGÀŠ­ƒ€ÉYÈ´nÊ’äA8ºAH^sc|å¤×^ßØA%ËšÄVJ¥M`G®<ÅæD¤˜Ô²­3h“BYùƒm(>¯žË+<ÉŠ±¬ë‘™i‚}½¿
+E¶%i1]Z,oª5%¡z¾ÌP!®}ùaPLØG(á„.¶˜\ÁõËòE8mÑ\&n}ø:Ûˆ;D;a2©&ìØ[°Cžâ¨#ª¬õB>½÷Ú"Æl8Ú.ßi*§ð{øë2*|oÓ󤼚¹“hJ’q…Ì'£ €aÕ¢IÝ
+s 9ú^jŽ1ãñP]„W´ÙImˆºtÜ,£èE?©× ƒ¥€#ºë—B¶jѺýM´BJ¶Tó*‘VŸrúiÇdiŠ®€v å%¾¢Ça Œ3ç„5>hëˆ#ð™•Hî§R@0êÄÎs©ñÔ¶Ú|áÞýT†Ë›å}„ >0gdcY›é†×ç™Úôþ”U­Œ1¯& ßPÂL )¸Šò‘4&k:ŠO2Cÿ'° “ã¤M Ô5µ6²m !i¦ÛºŸ9B<°Î±ý4ˆ®œ‹¾s ¤qR š׊­È`Ø! ùû Ƭ‹¬é‘ªÉË7c€$£À‘î‰nešØ!ÜEÁGón´ ý΂ãö#J†ß57·=MeY5$]þJhonB¼–ä¹J;Æ\5°h’l¯ÖÁ6O‘ýe»‰QR¿õy<6*¡è¤Žš3]EpÿÈ/8o‘]4_‡]šD‚QD%äpÞEK>³ í!x2!n[a¯o)êMÜ2"B{tû›ñ2I’äÖèUúeœÀa--u‹¿-ÝûŸ(e&úۤM*HÐÕdYfÆ°º<XÚ\KIÂMÕ…þûa‚O²²†%¯tª`-ktO@7ÅÍy¿|(Ÿ&„pçFQPlþˆO9/!Ø`
+{¨AáNÉ©F®,(ªj‡P¹KX…®¼QL¡¬:7*T´“̲ŸÝ{Y+•@hòP}ÖY鶀&s—ˆqðÕhìgHóƒØÌ¢©nQˆ
+åò|¥OiUáÞÔxt¤öæn¨ùmkæÍhî{Ÿ„ ë kF8-âV53¥øxºûM9]€UòÅnu"2ô™Á}„k] Gˆùî|f^
+Âd/ù°AŸíûWúç²Tçªm µ!!ú÷XD¶R6àR€w‹Uÿ=ËX÷?-y;êûOîãצK†»E·z{¼öGÑáNÉàzøxí÷’ÓµwŸëÚ¿þ¦´/ˆŠè3–ÞÈ`Xà…[ÿ÷¡HœAbö.¦> a£‚^R‘-F\Tç%Ĥ+ý-wFZé¶
+(Áó,1¯õP L^güÞÞGÕ d¨ÜéÔ€}°pÒ÷wº²O“Sò£&¡Š#V³z ].c(çF‹£Ð›œ‘Ø9©H¤„j~†g%zÜÌ3€"/
+„A-½_eúw b©LŸîreá_´úŠ §A ÿYå,î£^‹„l#ØgXþ*ðµÉ†¹Ã§úxyl ëÑôzZ¹g>±©k#½AǬ2oB@ý3‹'g©ë~wû¸3r¶#þ^+~y0Yd%­ñð"ä!åç0
+Ep`>’Ÿž)7M(ì.ýŸ$Ú®”:QZ[qå7*n2‘Ø
+¬Ó<W¼1ú_
+ògL´=/W«;þxq”fÛº%2
+ˆba@{ã©ÂyÆØó.¹¼:Y·Ùã$ŽÍF.ÊÍû‘ç&Æõ“Ä“¬xZ;»tŒ¢`‰¯·Ë¤ª„nvS´ºJ®ÀÄgY”|%5<WÙí}eƒëá[Lú]|{‘V¸òâíáöcê6tÄçiK´&C÷¡ˆ!:á¼Mþºf3‡_¹°2ýò¥1Ï©9N¿´rèd—å3ä¡ï ”Ó ç¶x™2CI(lnÜÄfôøó3PÌ%_%û³e}'»’qÎ<d”)NÞÜôvÝ`Ãl#QãþŽq¥õïÀ¡
+Ÿ ÃoÌï‡ É}…´€0ÌæÏfüì
+ ?®'³s {DQ2µxêKN<p|Ch½ÏŒ`—Ò¬ýÈ;¶÷.Ÿr󎤜A ç»ˆNIðÅ+Φch;ÃÝ#<Àô&)í¡¤™"Š
+jAƒ§Tz:¸H˜ƒÜ‘'"Ácˆ#[õnÁAÉò£èAŒrÇŠãKrtpI)àd€ƒÝ?%"ØPÓ¢„U
+å Ї€#Œà‰jó¡$³„y€7Ùé8 ÆË\hÇ9†ÝSbí}G‡C$úehpϱs#/!›àJ9ìî5M¼Ó
+d©Š¾½ˆŸ)¬÷áÏ
+°6ƒ]¡Ó‡BôhkßV «Ž¼F3?M{‰ {ôÓ !„+ö;ùnÁMÀ[Õ·Ó¡(c±¬²
+Ò@&ÀÌ%Õ¬ñ-lÝ’~™¨@¦½8ø²8Ñ·M=æÅÀsq¢œ'æÓÒ}Ù ¢‰‚žãa/%›*a{šÕ’ûñ;â ä
+aøåxJЕÄ%™îáV±èR°ÊÞ†û§¢ÂÃzõãˆ)7„QCOEªƒð³_6ŽON ×!ü2Â8”…Ø‘ Ãü
+­Ï=ÁÔ¶“£ þàþ¼I€÷UtpÅg *ž¦J¸!·A¥#í›0L¸œîÈGü)hdPd+/9þn8&²ÈÔ.%vyœtŠï yGæSÇow‰AŸ*eJ|1íß6)ïß™ì–pVõ|Jð0
+´Õ§[ÁJJòüm¿Ôm:”FÉ&)¾J®#ÿeF‡çBsÎ%ÒY­¶º½·È¸bí¸Ò(ùˆ‘:MAVZÛr
+H‰”—Kr$6DOà;Ô¦‚à$×í¥oѳ’ï¿—$¨±ª¨ Ýa««R $‰Ç¿rKÏ>[+%Ò²?þúÃ’ù³ÕÙK)¹Œñx}\Aõ ¦ö9l$›œôo`ÉŸ3>“÷Ö„ÊÏžºåî­–ÞoL-ÕjÞ/ ¿¾¥1w07¯Ä•ø_n£Úw þäóšÜGñ"=mòQ.Õr+4øÙjuëãÇ [¸ùLž¸ùœÍêÿzOÁ%Ü@õYÍzž=9õYÅ»‚föbÓjöñ¸Cš{2%ÀJÿâ%Sÿ2z*óñ;BñY™£ÔY ž2÷œ4<Îáf6¸¯-ù<aFm#uêÕö×#óû\¥¥6N˜™ÉDš¼s¨×Ö»[*©ísf÷Þu™iÁX}LO¿ 㙪Ãç>À]H½B§"—dìœÃfs
+¸_4ž\°pçÚbN'šå<çF(j¤/ç "µœ œ(ý»c(ê<k–ƒh³$’Á6¢O·6Æì­\n‘f1êÉÞtïžë }דÄP¸1k¯çÂÕŠJâ9õ0NiÖkç£è]Õª_Ü0í ás/hv⵫Õ
+ürÙÉZk*º…˜”ʃÉiÄ)•h¯Ò‰ß× Ñž…ÒædJñ*~æ¹Ñ&)aN<Ý, Ц͉ÎÅóW´&ÁãÓy¶²Zh¤æñt¾›©tx1C·ˆ›ihú-nciª9…û6̽1T"£ŠêòLÎGH$ É
+ªQïʳ‹è—·C¨ ÷4½Fq[mДF×'4+ e"»(®p©§ÓÐê¼!ÐnÔI«÷3Ã
+ŒÝñ0PjÎøa°•Ä¥bl«EwÓÖI˽ÎA$F¬Pc»Ÿ‚ Pz
+}‡ˆ\Ýd×x¹*¼Õ¤¦†çà'©¶òÓÓ?ý_}\Ȫô ÌÌ»S+ªgnËÚ±h¡÷ÁI6¢öîxoüŠª‹
+%¦žJ•Ï•_Ô¸>Zc%ÉwÄ‹¨ÿBÿú¿Jª¥ç—d)âCŠYEv¿Íæï½â³è…ÛaÂRÅv µbìµx0™TኚvÉ aYÍt5웦c9?“[ÙÔ´¡ðB¬òCB#_Ðv»:ǹdÈÂh×ú)ˆE HÒ„hJÜ\„òUe˜ ísx^ÑÔzîë½9VnlCš–ƒƒè›ÑoУˆ„[„ªƒr,W, ÞQ¹ÅÁc­Jqw¤B•)9ŠW6Â4À‹Ú$ÛB øÉBr, 2Å4Û¬üµ
+…ÛFëä§ÏBÊÆÀ)L}©ÅÇÖRN™c%>NrëC—ÑxZ”€ûÃÔ“cú9¡ËtiݲMíåصBÄ)°ŠÈ?·3!èxØKäXs)Ãn´jO•ùÅ;ù@æB)h aí¨F…k=eø ÝÄFxÜ¿9gîÎ×ô ®wzKÌ^^„È­¾~¿ðQRC e,jï9Î1µŸ³é"Ë!ªR8 šƒb³›¤¸‹Ñ±,+4ò DÞ¦˜qZÆ`½Ü‡N
+QaÂ2háx6’ƒC¿âWÙi»ïØldT>eg c†afÐkàKVBL¨¸\ú†À!ø¦’ë7̈òYÔf'Ô?寊öoÎy]G/÷uô2y`ˆD‚B”µÝI9)P@Šº9ãmúULÙF±µh²4és½ƒ(=ßË”Ø7²ýÅ”ß!ÿœŒ¿®oúŠù¸šhÅßáâݲKÎH% ÌQ'تlWgÛvG­*-ÚíÅ‘ÖQcÙHe©hˆIƒh($öË· ÃD·H/Šmãs]û'bGzoÇ0=:i Ìs™)wÚ4‹·Ðªü8|e+FãA/T»œÉÀ›åÍPÅxxfoHH²-³ÉdÀb™ÓGh™ ’gT ß&ŒhËi2PÚçdPc‚Àš%s‹LeUnɾ³Ê™l«…iƒ™HS* šýÚe[ ɨÌY7æ™v¦•…55Aí0É–É÷¼'™œ&EDÒ± ñ#vä÷r1µ7%ÃâàuhÑÇí2òáVÖ–âs\…áïžtÒI_îË=2>×<§úŒÓ÷•±Q°•Š3vÞ±ˆæ\ëÐØ»åf!‰u¨Éñ²¡¹¿CA>ž‰¼§»
+{ûf-
+ãE "X‚ó_@ wÔ
+“N (…£“,«X$<þQ_œÂNYuËÆ!&˜@ˆ½™Q˜sSæ!L#ò ÁxqôJ‘‚0IÈß´ã³ÁÃlγSúG¢Pð½@¾¿ýý–ßÿ„×)ÔmÈœŸÔæ^©«÷»¿ÿ~*6ÏRج8Y´]گί‡C²*Z®9‚ÍdMêŽ3’ÂÑHIÔn*é¯b¼¶j€Ò’“àb?„
+Ñs²z_›ƒ,vsGÝ ªä€/n{$ =—¸÷9åÙPe6x>DG€ L-_…~d-“qØtç€tü)M@j K`OyZÐEµ%&¶LIhé ôœ-ìÉ<U¤H-Œä²< Qªáöá ›„wfIf@à1º«ô.$Í9F–Q W “ALtk=šYH  %;hˆ’Y¦ÑÏù<XäCtc ^@> ¨fYŸÎ†àh(}uÞ¡Ô¸(äéÑ¿ T¥Þ¨‡ÜŽƒU ^ƒ«³œeåé½û´9!_ƒäŠI¼1ûŽé?Lˆ`ÑtÎå؇á2¡Wqjb.½¥Ö h‘)a;Yœ!Ó
+$±¶,/álÌv šGÅ$tÖ®»QzT}…EÆï¤ë–¥‘œb ñp´r\ ÿšµm³9D“T†’ÇC7 ƒì5jŽ« Ne^ ñ8ºö¿Î ¸(ȆQ‡È;øÂñ‚fùõ)Ú‹«>ƒ6 :íÅŒ¿^³5oXÝóžÆXÊ…ÌåèG“Óz‘ ( ÉÔ»WnQ@¨Ó$þ*Ó7ÐJÙŽ|<œæz$Ë~ÞNdƒ-¾$•3Ѩ2sŒ“e(a ¯¢øŠ÷ÞÇZ¡>Œ­2WÔE$ ²D£Nè+®bkè1"ãUŒ›š!Û²sª]; ,ü¸1Ež¸Ó÷Û^)¢É·â]ظêÿ,ßv4™ÞT–×ú‡â>Ö9Q•^·=½˜q¦ß6CS´+í¡;6¡Û*Hw,Ì:4&çÛ) ý´›X6Ô^–!Gm 8£@âÜv ~4]nWx¬‚A–6Žâ×l5Ä…wt-Çä \lwÐ!ŠÍ0­Ýɹóå8c¨69ª?SÔ
+È’g(šâìtÈ´3!Ìe>&Œ ðg—#nSÒ†µeôÄ
+ð6Þœ§‹ü%ç‹™<>­k+´É#í«äóuý×Û ÉÁ©!ZômL‘üë|| Äuø‰®•*Ð/奴Åô¯Ç—©Èh9«Êˆ42N…X¥
+ij>œVíÑ“0s¿8YgÊ@J›
+$aSqÕ²“ä«TíJ/™^xÞh—„
+YD’ý&”
+Q`”±:)1QÂ
+—SOsŒ €p°©¹Û9i/m
+¾a( !f¦ÚPT»*²UOÖ‰¤Ù±Ÿ,òÏmü•uî%ošÄð•Œ7¾jm¬Søgì;} aÐ!ãMµ\pЭF×ø¤|È‚hYN¿žfâÝùo~ØS”™5F@z © !xf­£6r$Âö¯yÖH (¦å¨ ƒÅˆæL¦Ѫü6_…p°ˆy‚Ša‘®qŒœŒªÊ«Áºp ÊÏñ¹¢¸|¡‘†¼j‹ŽÃãjö>¯ÝGÏøýºšõ›t¶â=´×W³ñü¦¥Ã _@ÁÞS^ª´ç@Ò#‹<ãÅuì0dxs#²
+\ñåH3ÉŽ‰ÐeÂIþ]"Y|7€Ú„P-Kïƒ?CG¾@¢È ¬—àÌæ ©¸ûÝΰ‰8
+ ±÷HEtYîÕñÔo,BR£6$}çi
+†ÀñÏ¥}©Ý¿[ɇIBçŽáÒaF%¯¸‰¨¡Fd<Ø8ÌgUmc—ö¿„'’w@¾°9»¾€T z“ S¿Ï ,ŸLíH+^œç×à§a?8·4ðüUOÀ¯ÊòÒҔ峞åõ0$ì}¯~ôÄÁ¼°Œ°îL­„ah»·
+í¢èQã5ò¯ü¡6eÇU”ÂÒa~œÃ°óxŠýîƒSå?TŒx²Ž” ª‚W«,{È_±DRcNÑÑÆ6âMã=P?b+FÜž}–wi¯ã*!†ÌƪW>ŒJ—v{Å'ð3”
+/Q\øggñ%ÐÇÛî‰÷ùÍø%¼6:5~úpæMf)áØúË2·XN^Çu½E#˜”Šî1®n‡ÌVµ„;‚‘ÌLeo
+BjÐŒÈgç ˜AÞÿ²›d¸KŒA Pg½Ùb<ÍWŠ §é “T±C³Ì»EÆy’å( ËöbØ¡&…æOï×¥‘ÖÊòÿ©Ö³z8€)ŠÃÝxQ¡ ýd¡ï»}#;uÍXÞNü.ï`{eÜKô³ò¬Ï– 8aV® {„2Û§c ©*ß5Wt‹ˆBÉDº«»"^O›Ñ_¸[Š
+ídå…1[ùŠÏ¤Òãdà A0ŒÝc|ö~QL1V¬ëñ 5BÝWûÛ9ŒU}µÙhH‘´¹±72ÀXóœsUÇc/—¢’/&˜È9×s½Â´âQšg|Äb«‚NhDk&zJï·†2* ¬Ú§äqÖvÓRìzÔ#„MLìÖö«¦ŒtÕÆö£j3$öíÁHÖ¸ˆO e´z³-ÄœçñºEf?¶./åf²W}p u…¾Ðò¡}à ‡Pè…šñ‘s6oØÏMèWÕàè Ô®È÷ð?çsÈMl8Ü‘”?_@ªü;r® ÈŒþýöÇ¿ßÒû¿þzûãŸ7\KÕRÉn5Å1P”I[´þþ;0œ”›5ÒAÈ SÇŒ`£ja( 3zeVA½e7ñÇþOÅD̸Œ[¨×0Ó
+zÞÁ__ØÓ,v~ÿó yÜ(à†£6´ZLÌV!t22¿¯  —YJ®t)¿¤Û¿S@3ô@ꆡrAuª>Læ1N`wœ2f3¶³O3OqÎ’ÝÁ.QNk-6»géÞ¨8ƇæqDÜ­-{] Ö~\+Ô§ÎrÚýY9ò¦v£ ‡ü‡ñ2É’äÆè t‡<A<ÎÃ:{©[Ô6uÿm#@¯Êpº”=¼nE¡H:`°ÙùpÀ>­¯¬T'}¶v$-È
+±C6þCQˆÙòíÖ×±ˆ6šœü=²Sòæ5°¶¾Šé)‘I·}ã•p§>$õëÓ‘d‡!ïšøX!mŽjç¬XÊ RqNd 0rJ¾¡x—ñ¦IwmêŸ%~Uz!¤¸bçíœÃÌß_sÀÎý«|ïÎÉï=>nÄ·YýúÉÚhÂmxдR–¯<œ÷ϱ¨¿:?CYM©ác•°Ks ,Nž°~„a“ÄÄözÄÔÖÇ"ê»ôî§÷¾Äœž¤w ¤ÌÜ•?æ<Kæaöwé%RÑzÌ5èAÂA4z  ¬)î×0¾4䕳•,7!'–7‚pä8ÿFf„t)b1½ì¾Ìc4ÉÎÑÓÀž¼‚ Â.“d»_D/ñ²Jµ{Rh"6}`ß|•oEß&ÿu,š/d³P°û5Ä‹€š‹„œ —“f¤û”ïqt_V=ô©Ó¢z}8
+Œ›•åèVDDc·P²’ͪá-CˆÍJ ]Z§¨Xó‰0ßK67ËÁ˜3×Ó9 \“Ö»‚ß~ ¹ˆ6‡”|¿’RÓM»>gúc›¯2`—`Jeg·î0µœa6Бlè-%ì«ÞãAâÃG“/çÇyõøH -vûªßÏ%–¬âK˜DqÖߤ¬âðɲ-f[ã[ÑMx•HI±uiÄÈ?.‚åÉôL<ŒÝ®ûQ‘€íÊ2®+ôž‹m¢×°(¸*ãrò
+š>FÁiºÅJdÙIt1wWfv
+AUh?âž
+£ 2ù¨äH‘ßO¿ñŸeÄôÏaό֢rXò«€SÏ+*”fß/Êe7eG²G’!×:­ª ô~àz­îð²~‰`-o%2ØBaÅßGóK§"45²fJïE7(êÅ"¡©
+Y—ê%¨L m_5Å&R®Z
+PdV}â<`FqX}P¤ŠS"–ñµŸÄfãðÖåiÒƒ"± 8À\zÍœC«Pzµ’¥Xì,Úë_Åÿ§alÞ(û*Ç
+PÆŽ0,™†Ú8ÝÎa_X—~u¸Ò¹°²# HÐ#-¶f.ØL
+¢lA/‡¢¯‡¢’yûý‹Xndpíô20«HD+ÉߊrUx´åYR3€1ÂïíÆTf ìgQÛÍÏ K9R:›Êà ¿•øMjXlíêîí2k)ÓÎ[øDöÅ«Ù1ñAÃ4}øw#൓NÝZPz[:ÕöÓ/`”ÔQ;'ó vñ€›r´Í …ŸJ¸£CjQÀ¿®z/Âú÷ %4R ®eâ×Â~2ôÊó𥨹ý‘¬W=øŒB0zÞW‘!')qpq&ÝËØ
+?¦(
+Ê )iç8¦ûKX§Hç°\ÓJ0r;kwÝ„ÆÁV’ @Yb>’zð
+ÕŠž÷r¨Øxà±D&rÓÉO˜ÎÆZhÑš?†^ÄN9ÒJ@ Vyg¿
+~àÞäe.i7i8t·±C6ð«S~g• YÀNšîhòÎf¢Þ¡>”°‘8 ND>]ZX^| ]̇¢//Šòò…M»ìs åýu[˜±®yGAÆWð÷Ró&Kϳ”n–C ¼º,›+é_tLƒ¯ÎG¿ñ¤Ýœ7cü6Σ¿†g›D+˯ž8wà›S½ÌjP² %M—þþ2Ë;ðV„ Û»ÚÁÙ>½¦g¿àsõcnS>‹¥×±=”üéS—›ýøŸ®K/š7'8˜ã@üËÑÆÅe•)â°Îê_cÅj®M\2‡Ù¬¤’ªèZ¸DÑ)_¦Ê>>¾$ؘÙù­¬â@ñ‰íy„@ày…¢‹±¥I:%D¯P")8ÊÞœF㺅çL‹|÷„ 9îeŠþ~(
+(à-ÇOÞÓš3,Ô³ë¢^SêK6÷zà™u¶‹C&Ò¯N׋•ôEC¨Ñÿ/—ä:rˆ®À{è(þ9öT»ðÔÞÿ´O’`ٺŒäxáx-C,Häg™¿øk} ò‚øeWýœ
+SÑæA {f¬Ù"_t‰wF?›VÙ‰.ÐFØ]¤÷%Ì’&A%nÄæÜ£ÄISÂá­åë¡„ÎÜŠ« AÊÜÄ5ø[Ñ ‰Ü˜=fò5ï
+¬Yµà˜’Ãû”¿²í1v}(Ê1ûZ¼ ±#ƒPhôEª˜,ý}ðwGÄja!ùé|L"I!P¾Ëµü;ãÇ’ö´.“àeà›VüQ½Fþö+Û&â!½УŸ,ð,!üü ‘ѶÇ“ðOhÎ.áIx´ÓÃ"¤¨èÅwý^™Â,5C]«~ oáƒ2-×ñtp+ é
+θ2àèXrì C>,-Þ!ôÐæUö)¨Ë`zX7•4^
+A”%E•Q±4ññ°†5¨9oŠ#QñLR^%±uÖÚ`Œ¼·FF6ùùbÜ[‘Üp•Q"É@Ïsÿ;‰
+AA2?œŠ^¨ì÷ÓÇ Všž Í9úû•o~úA
+ÔÂ&‹žùûœ©(áj G‹`¢_åEÜ‘Û‡à2OŒóèƘf#Äy  ³ñ­9t:þ•ì[mÉR*~Pÿ;b”ÿ‹©¬¤§®¯pü~™b*Ѻ½-zy1
+ŽEP ’#ì˺Um¨#=‰Y\Huà€ª?M&"™7HžXkËcªmß›ßGópvFL}4}: -Ũ‘Í¢%ù(N” ÐxþÞ¼ú¡ÄÇ®ÏW]<‹œ@H|;üy¸Í+˜__uD|#A-xOvÎo¶ 3$Löw‹Ž<_¦·açÈ£öIæ øZé{áÿ5ê{ K Ü ^²òbÔÕFú ¨x´ák KˆsRíYÂA»ó1`ŠÀà§ÊѨ bÅ0LãƒQRq gz%\Ãî&V±Ä½…%oÄtìdZc”¿%Ø ßÂÛÞÐñ¤Þp©ý¥Ïwëá1“·’"m+݇;ׄ–-ÄLè*éP4Kp¾4‰¯ì‚£†ÈÈiÝ“a¹À_`ÂßOœ$š’žK’ Âk^–°êX´°zæªr0ËšNq‘
+SGãª?ßl~„ß+Ìðp¬Êë¡èý¡ZÅÇÚÄâ«"#8ӠƇ†™ƒa½!M —Ýàx¿2&8ԢϫB˜2Ñ”yÿ°Ý,FÆ&6gWò6„
+m°LpCìëø äÊtœ'õÕÄþåh›þ—}`&õ@UðŠ£)¬ÑÉ‘¯‘N'o_ŸP#Ü٠9¼ƒ§å9xñ<–dõk^~JÒF Ò¹B8Y¶,–¶Î)“¸ØÞ-uŠ2Ÿœ×ÝKHŸ] ,
+eËGŸŠl=ˆ§øùœü½èŠóÆlxìiì
+–¨Š•9Éo ‘@&E>¢¯Å ¤ï„HÛ9K&9<3ÙaôwBd€ž¾ròt!‰+Kyë™#È$Pð^öĈ„98‰õ†ÝÏÚu¢BÏHÐ:‡%b‚Œõz:ÚÓZ/ѶsÇ"MZ¡í¸Ãâë~(z¡Ä3q|«¨á…Y]h…Ý{vjÈñÖ>î–CR2l7²ÛQvMíÞ^r*>
+aÐíÑKɤÜN¬cEì霨ô š¥Íq„EX„pšW ¾Zoio1”ŒŸÅð8å¾ þD2J?Ïí“ÈL\óù»E'#ªÏ‘è=Eõ“¢W
+€ y¿°d€€|š<û¦CE¶@œ¦…’b§*¡NGR¥¤ócãÓÙò¡ÄÇÕF'K» AÖbBɱQÅ"­H$·â¼
+ˆ}`áÒÚOQø×BÖ‚ª õ;bÚöÊ3~P>DIV”ºúíP4K{ˆâ·´+ˆ
+’Á®–ÞU AƳeæ3Í ä"Aò9³ˆé ؉Ö9º0¤*?´^˜ÄÒ¯)Ju¶Í†ìÇþÔ­OŸDt£Ääç@û<Û˜áV7d„¼V–šèÂÈᨵ¼¥â_ÃçŸ"?tGf56pˆøf6Ò»ƒs rxÁúú>Gñ_[L)êÖ/Ù䀗x!ïÚN— Ø8‚"/XŸoƒ3è—D9ÅNjÃúz »ÌÁV&GËG-„i·ø¢ØÈàSñ"d‰Åi`f: J=Ü4&-ÙQèîwðaP}° ÖŠçëï§sæ§05a—ˆZº,®©•æ‘Üë“-3>çÜ—ã­‰&‡™³pEþr(N¨Íþ¥7 `ПᶚcH„ÿ¡dNA‚¶ÆÝŠ`Yö<‰%0Ùë1+åÞÖ é‹m½Iïs\Á7=“pD4¦Ùµ•ü–åI|0±öè½ÁŸ@2M‘×#gÏ€„VÉÒXmcâãPñDNŠÞEÈ2™cÈt²Í›žnEx2l›]X*¶i}d
+ùø^˜ }´ `»7b=x–Zæ4HXŠm÷W’N{GN%Ðèjßò±Z€Cã¡ÓCÍïs VɘÚb\€Î\÷ äôX<œuÛÛyäžv¦eqŒW'#¸íw›¬%ݼ""„ô5D þ*Ѐ‡ŒXE w>öý§[1œ•j¦A¾—ÆöDø("ƾ_ÜÖq8eâèh›Ê|'žG˜|²_ TB,¥93qQ«~LÁFaýЕ™Jø‰‰þÐ'KÞÌ3»"kgNõ-~É8U ="ùp×:ô&ããmÛnAŸxH“‡W@Q\
+õp„r|wçÑqs+’
+ú:çV[À91q‚‘œÖê1%xài§£ó> NÂÃ]yÉÿŒ—Ir[IDO ;𴜇5·¼…¶Ðý·ý<3’%àÇoAe’ GNáCmh̘loÄ#hµ¨ß9Ïô·º>Þ‘àï¥Â§†"`ÛVOSzˆ°`‹–¥. /ÄOcŠˆŒ›Þ½LÆ·»Ý[ ú¸1ObU‰ïê hG *¥IdQ\‘)Âÿ³7!/d¨ë°
+Có{o…îñ9tYŒUš%å{{™)û‰7›½ú+’ Ð?©Ÿç°~ï'Ä®qžÇñ]—I}fDû¬“}þ)Ž¯/YâË«–ÛhlÑø®pWÍðè¶Ð&«6»VešeuKó=¤bêsÏ6Ù7^Ï!G|·tª»'œÉñVðUrdqC(%^¶^ISæ
+Ç$}–†œ­bg–á|.o檓q«J8æ^'jA¥~¬wÔJ“­J¿\SÒä´{%DóŽPßy#xÙî-Ð -øÓõZ³AíÚ£Ð(5'§gÿlLÃc;bîhA8i Ç®]ú¡¢ÊùT¥a[(wh{X+Vo¬ÐIlæ‘tüÙU= Òg¢Šp¦™æh,¾ˆ>E69¨ËýÚ^AÏÉõ{ß{ ©)Ê-Ž+æ±1t,ÉIýŠY: T««å¿ƒ|4rˆl•ÛäÚ"ØRœD+í§AEûÀè©ì4Œúà)ÞŇ@p|¨’|ˆÞ›å,sWÁäÀÃà™Å[g« ¨RYÍ2Î3ïu&¯/v·:Ì"Ž¬M+8¶“A¤ˆ3†Ê
+d÷V\ÙÅ>póÈ\‘?x¿`¯ƒmï`ðÇ]ûýß.þ¢ßÃî÷ñ™‹¬šâ¢Çœ „½ƒtx|㪽Ð]Àš â¤+C‰Æœ c?ƒ‚W<„êt¨À¶âÛ$2J7¨†g¨MM›ÙVMsÓ¡Ïe…4[%Cš™ùJ.¹ªÇ8,Çhô’^õÀ;%DÉWU×V4â8&ZU@,sCøvÓK0þÅq¢'õ4PæS}eÒdÄQÜ^O¯&9c˜þÈZ@ hŒ·XE`f ZùlôŒŸºÂ^;íU4Š˜Ï8`¤y]Ÿ‹¡¸v¨Ñˆ à‘Y‘¶¥!Îì¥ÅKÆ–ÁÓæ:i'Y•rà~Œl¬ÅI­»ËabF<Aîˆé ôí‚ h†DkO&yS“Êõâ³d‘×?ºùpîPø?7D àJ2HLòiŠfù§³PÖ2dGR>‰“bÊ7¨×6—j˜º±™ý’[%3pA*‘‘Ķ*Q7­-n7ï­Cƒ@³A`ç4j .†Í ‹4(’°§‰…á¡ËÉtég^”©ÈH£™ÛåAI;D:<‰± M¢¼4¶/ì+UñÂĘÙo OáöËæ%0‡2éÑ=n@è$šJ­ú4vÇ+ÅmÙ̈¢!“‡hv›_Q%~®gÏ®X»7fòÖ'2`l|kÇÿÚµ0{9w(9Zž­¢t¨È°É£2P"™-wÀ˜>öÿø¿.«ˆÓú‚^Ã&FvüêOuQ7ºªu*çUOLr¨–œ€lA0Ñ_âׄÓq™]YýÏdeN¹!|Ʊ{›ŽN¦ˆ†ÍXÏV¼í>h1Mâ-"À$[g XS…8Y
+\“ÒÙˆ¡å=q=çù¨ç$ǤšRÛËè­”‡àì#;üpíòÜî}u²Z¼±ãäÖ<AÆÌ6:È€¿ j…>”çç²Ý"ÐåHϘÇ;SjÑ/z
+/‘fqBé´äŠTêAh¾7ˆhD¡‹gzô"tßîvo^òäãÔ”R+Qv.BfH4c?–—ºÂ®ÁL1.׌Ñ"C†– ôØß{+<:¡Nr{Ò¾+bkm{‡ÖBœÇMbŠL3Ù
+[w_ ¶SÏêjt!µ»uè2Dâ'¿å  )Ž¯Šx¥¯Y`´v[¿‚\Ùà<x”Œ©> †©TêImÚ՛ܾJ3§rx¿JžÄD¶æå »:Ú„ªÉÇÅ»uB€ˆðµÌà KøbR…_þ0|â‹E%<N¶°T¿"á²›YŸð%ÄÔfÛ
+€ÂÀÿhë^6ÑE™+K°,J¹<ué×/äõ{X>‰‰"ä½òfð²Ý[ ^ðÇë´9¦ˆvéDRIJ]=ªh©TÚ~¡ÀNð°Òi\¡Q_&òûØ E¾6(#Z¾kBç# LsZîL{–4ËÜ !$aC‰p)½  À2 yVþ.!¡7ƒ¾~9 1 •Æ§×Ëæj@ƒ`‡àbé]вpeõQ"ž›]@}FP  ÷±9C¯µË“K•ÒËç-ˆbÈTœv3=FYGj«±‹B Ozõ%y¼t$5Ô)ž
+¶•B•m1YÅ
+Y¤Ê²Œ÷AÎŒ\·{ 䨋zQ CL¡ý¢«.‚°@ãÁÃ!‘Wqáb!€µ ¤Ÿ¤ð·¸€ˆ!‘ ˜˜Ð]Q
+wêG.âB!Dípg¾¶€Àj¸iúcàžµˆ6!Ñ1'wÚ(º¶ËÕ•‰¤)EĪ+-ä"-W×ìd¾T@…pç·® o
+UwZ6mˆâ˜ØÚ5èxNGË·ìVs®Yk³LkWÞ,v” Xhwë`QÀã–—ÓŒ;jÆóѳíæV€pì‘gǬô)%KŽ´²6Ñ oµÏ3"…ˆ³q@ƒœ
+ê[þ^0nF ò„VJÌ^ÆuAì6J+üˆ!Æ=n@«+h8jîÇá~»–Ç¡rB®œ˜çmgä¤q8H¶
+¦§ÉB!÷£·2{³—‚V–­œÅÊP³Ûf^Å$0˜Á™r½o
+†þ¢0åfeEfL–Óa0E\¨÷´EØ—‚ÍÇæ9å´I«1‰\ë¿þ#sL,U3¢´£y­Û€…ÏÌÃåŽhËГýãå’\É­Ñô´‚üÆí¡wá©´ÿ©O’àu¨
+ÕÖ{“ŽëY™ þ05ƒ$l$Ù¡uŠLÔ´Þôµ™8 ¯çš<Lf²GÎuÙ@ºŽ!"†+†ííÎ×ýå¶sÏ0j¬“cvË „ÕŠ% ¾Œ§v!;­ÉÚHŠ}úç ¸“é rUìk”ª¸˜Ê¦´!ØÉZ·‰ö­“‰üÕw|¿aÜòt¨$ýÑ®OßÿW¸Mß‚5É2BjìË@‰—P¥Væ“Â'Ô¦NM÷lÙWøÌÞÁôPÇÒ”Y)B%bû ž ¬–É»
+Ð ´ „M3]e³™.aô'v¶ÏNŒ@'fõÏ!]„&ö»ÿ5ŠwNò™žx¯«Ø6 5*2BéŸÃå„Ur 5MŽÄ ÐW¬IíÌÍMão —c,€(‚ ¡êq௠Oä=ÐE䩇ÎÕ1{rE·jß#®Ä‘ÏZHQLæ’ÿ䉼:AG£kë ‚¬LÈ…ÚyÂb7Å:H²ÌIöȳ¨CXlåeÕuEÈz"D~Q0O¸,£ôD”!w¢—a¸"/H£ØÈÖñþ›Æ_1nÇ=)Ϥ í‘;W+ñè*ñò"râ™@\Y®àþdU0¿4xAÂÒšž`Nî¿å<|‰O+‰Dš¶›8Ÿå!ʱ±çÅ?ØääŠüÿ©÷ù¿€¦ñê ÖHZó*”|‹šJªòå‚pÐ^Èœ1·^´—¡ðï1Mæç+«‡“¹ë‹Ž@fC|Ù¥J³S›W+¬\´|õ$Í%’…„ÞÛ¡§X‚ü± üƒê‡¸'žÔÞG,’Þ2 A´Fh ~ªduŸ$?QHmj5¹ç
+åÞ*F­ ¼âØvû䤷<] ÷Ó1Úyª¶ÓQì{ŸRªùÛ}žaµeÄ„—£˜‚Ü¥¼öršK¨…£é(n1×Ö;ê®à Ñé í¸¶L ~…bEƸ˜ÀÂcˆµ3BY©RhýéœKÇï_scŽóª;oÕ¹óøVbo¾µêŸŸ æ+œùbs¬°hÀËy_.{æ,„†¬VíÓSl½“Eó8²X+¶Ö¬fAŠ"ß'þ0$r9žÏœO'š ÙÄÙ)}Bì•›’5„šuVSœØ ^ïïÁšÑã©RŒt .àæ<«¯aØ3ODßÖ7¶"öÛj_ƒZ ÐÈöÌå\5õC…CÑ3Ì%œ±,F…–L¦›”¿âž=¢µf!Nk™…cÜýû—úÖúO4_I:B½ˆ§ö9P|°À’Äb: pÔo¤ âtß~Vö©J×ï——ªÜ±´nƒ2„o¢ê¿Ï £D¼
+|ØÌtraMÅÔ;ñ€H@íùᢨš×ó<7ýy>÷>”Ú ³½ð·Ç,¾6Í‚  †Z2¥Y Ž"¶@À`üFÞø ›É6ø#÷çDþ×í«Û«C›*+8ç°úu…ƈCìs˜{ÜKËÎ)ZeÕ¿d
+t¨WKqåûÜ%ºó8-aŠ–Õ­Ëñ5´!Ò¸x4QŒ™ñ}CVLÖ~S»ùg×Põ«´õv.Ǥ—–‘eÖÉ|mbtžõs§”[#€@î¦ÉP>üíuK®OBÚ¨]ã´–Z¢&Ù̘`ÌAŒ›örùÚ
+f̾¥S>¤áÆ¡ƒp|)ƒHFjxˆ•c?i{1ßW|cæ†TaC°D#iÚªá,[¨çª ‡v¡ØU¤çH]»F\çh÷á–JS‹1‡#8irUéo$]U¾<º“pf®Ô0Œüs7‚·ë~ºÈ‚?]ÐŽðQ‰‰B"¨É8Íž
+Kç"‘ƒ˜-e»‰ É‡Œž
+zY{SjOçhZ&ƒù_2§¼]ÃW³ñ†ÁUgSz'ü¤Â/9çsUÐ
+Ø«Ø=pgb°ê`Ö¬ =°Ù=A¸££l‘°ÐÞW]A­j8ð?ŒÕΡà„äJ=É›M§SrüÖ^µD\KJtV$»Šy&KAõa ~2u™”ч³‡•ÌÖŸ±ºI¶ˆ éë'v«= c±¹ãQ=ža£¿ÛÔÁBF™ÞŒ]o„žLP1Áβ —ºAÐ(6+Ì¢Ø)…èS«Þ¹ŠÏ¥ÈóùdVÒ;<¨­ÛTiÃÄžz?ËD$Ùàëñuq@|nº:Ȧ@çÜç ù³3z'Ȥ¤ÁãœnÃpR+u興Y]¯µ¿¯"fAÚ¾d~«Œ¥ŠHÓùÃñÖ{<ÓTIXÔƒ2bžH‘H®}­7þ9r‹rf¶«JFóô²!k€c›Å@P‰àRúOø³Œ;ˆÿïLþ/ãeŽÙ‘Ñà)Àr_ı¦uN
+:Ýôv}Û"bµ#ÃIü<2È°ñþz4#¯‰èÇ#PH£²åšeYQC^ Ü1,­5]e,~²\EÈ°Ì8†e2õÐ iŸS‚&=|üìÅfÞ
+z…ØUƒ>B3žµµÈ°&ÄcY$Óy4êÔôð° òþ‰ Óaî³Bf}:‚F¥ªs›’\êY£ùˆ¿+Ö_[Ö6æ±Òl8‰¼ÅoÉjˆfŒ~û˜Ê1(Tª±ÌˆèW:fº¡¸ ÞÉ0‚RÊIn­0ŽœµÈÑ;êFÔ£©ÛÓ°‹ú@¢B´\ÚÇPû^ØÔ{C†¬*ƒ?Ânã3tm2„Øt ëªJ—`õØÔuï³û9úÿHž„'¯á ›?ôD©`gc%Z*njø@é8” ?¿ä¡Lç¢+EÁX–²¡ûÞ^ôfh»? ‰%n¶Ç±Nf šuo؃àä7ä™pT,ñò¤LGXCܪ};åÖ2קÜ;ïÓ¾’Èx$œþ½Ì@Æb°»6ûˆ‡ý5o( þƒ—ÏB& °aÝŒ$E@±­»ÞЧ’‡cØ'p>åþô®»‚¾_yÓç~z‚¨†¢£—ŒÜƘڥ…T®§6P¨?Õé€>=_ú Kõ¬ÔWB_©ºL^¨÷æòîGÌ÷+±)üû-¼ÿë?oü÷ß•‰0L
+¢sNS,‰»@h6Ùª[Îò“"G÷P± ¡uYĨÒZȺI´‹ÇbV¦ ZâE–$­ƒào
+‹—™6ÈH\ÚÎ,ÏtGI"9®&K=BGÚ|(jUÀ½–¼Æ^i"êÚò¾J¦‘éÄ}4ƒ@aR8Àj†áù£29 ¹ˆÁ³–ñìè¾¢áb²¯ÜàíJ÷m‘(£¼p†Å}ÅÜ› :Z æ%¶—AÞ@\o{sQ·Ó]ò{ÿSÐø"“3rÌ¡…IÉÀrÐùÄ.)˜¯¤îr@Ÿ.9,ÅŽ¸Í\°_æ€Ý邤Rñ=lçÔ1AD(M‚¶„@—HŽ=bø0yx¥¢´|í«`^“´Þ xFOaOÂ7 øÑ`c—ê±ÔÊÆÄÎì@¾vYÚ¾‰0žƒã ÷dËä*ÒúRd Øá%Ù)«’|Ç87IQ³„1uc˜¯Bm)øÈûfÇK5ÛMƒ{ˆ4iðß_(ºöz8ýñrp9x¶ð÷‰OhnyÏ
+‚2dúJæu3T0P"D·ŠüÜ1}³¬ºAð{VDØÖH „¼Cc¦8¤O1sŸƒázäT7ãHfˆÞ¬>¯Dæñ'l ¿Þ|P–ýƒóp$ÖÏ7ú9Âô2t1íˈy¢¬bÝBŒæàžIütù =µõÈ›A˜o:<—DQNè´”ÌÖ}ƒp¢\«°²5Yo=äoü"ùmXÒbM6°e8\_r 6: —6Ú„»ýs’âÄ„!xÎÆeÒPá,9ænC&j£‰‰öÎh¬<|Ä’Ñe_•?hR…˜­ÖЉyųbHúªVV«0ê:ܦ”üóþ2*¡#*ê¸ #¨,¿ª ’Ž]P´¦÷IJÛf1RÈLÐ_… TSË3£µõA'0fl6fŒ›Ž Ž ‘Ö‘P$T+E•H|F±^K³}"µù‹Zä8J£°eƒšø”sáXI‘
+¬—OÃfÕqQÎÆsUë±°Yãqj>á§IÖK{r
+*éÃ)Re º?á3­ä˜ èF.Ï¢–
+ÒuʨT\LK)¸ ÚDœa1« è¨?£™Ì{Å,ÖÂÞ–4©aOmçrÒù*ÿµoªº[B 7ÑoQêôI)äU"‰d9” ‰ƒˆiA@:»
+½°Î\Ðê$bƒz–7žç£]bÒQ$Qzvœ¨Ä}9¢’¶Â\=È d´M/ž=‚™)ðoD,'ãsˆï^·÷ÕÈ NÔJ^qy5ã™Íû{³¼
+j…&Àe0HòaŸî
+–âϱgY?ÅZQŸP 
+„¥1ò‘òôW€;òFÐ\”Á8ËqHÞ²´Hþ.Ý+º$œm{M„™BR³ÏAŽÖe\ì1E
+‚©€Ë‘šÝö[¢!¥1M¬îuSý€xn.ÝJIKgœ k}C‘ ¢ñ£…²<¦ŒWÜDpE …Ø9˜X„]Ê;&Ae ÛGµJ^1C1Z)®Õw{­Ú5Á8GdŒôu‡XÐÉ[[¯$Ö4.¶Ö÷{îËê>“ÎÒS?^šLO¼Û¨@oÚŒ‡±kVÃÒ½utëNøŽžòM;¨c‘Š,ý§;Ù Ý »ºËá>*}½ÇhÎþîÜeãýzó†×Y‹š–Ù+å„¡ýÃäÆ„HAMì¸ Õ¤zâKl/R7–E:Ç#$g/®,¯rRO뜀ËüoîÝÆNRû’LhóW 7¬Pžôb“‰ªã}<¨<='v©s*Qæ)D–7D¢‚çé!}ž:Ð#¥“Š’GüiR"ª‰qÍgéá¹(;mº›SFA‘T÷L„3y<Áà)ÊžÏpÞ@l Æ߬—Ÿé¼€¦Æ5ÐɨŸ|.ƒµ-ŒŠÏ•u-›”ÆBÉ‘ç‰ýq’å Æ9&‘
+žxj† û9t“]`7ã–§2Ý¥-YÑ…ßж81‘ì:è¶PW$â/}ìÙ
+Ð. E¯^@mïô)ãnü~c)X˜¯Æ³ãiµzزoÇà˜'± gè[bz€ ¤ð$„¾ )¡3jËIIªâ÷Œ\SÞk{à±6˜1 ´SCÓŠðòt@ 7¦Œ²Æv 9@àL]Ž+¥›¬¤~z*ë|LçKðsDûÁ°‹¥4(ShŒ çÉŽ‘…™!=ŒðþâЊØ'í‡#¶É¨Œ­ImÐ:&VëÞsPëô1LÑ=AfL©²ú›. V‰™¥ÄÔt¤uev´
+1ßP”ž ' Góg3~úb¸5î,KÐâs'0tT8»/æ܆}äbOÞ(eÚ‚²ê $¯L„ÃyOÏmñ€'È7½€þAdkÎÇ·@½#ÝòZg'Ü"ëÀ{ÓVAUø?‹2D±y¬;Yð‡¨¨F~Î1„…á×\r.½e
+)ÍßÞøêhZ®c"›b
+±ä“<ÏÉBÃN³©§ÙÝ9H†›ª»>ÝFCÁ3• ñˆ·)Ö؃ÂÀœž+ãÈÜw4{É "ËǸá¸Qñ1È…Œª
+ŽÙt- Ãc!@ºã
+#³ëÔÎãï;ö!0ÝEÖæàH 0G(DOäÅ}Ÿ+è…}| ÂÓ¡ŠÝé·1“£øó=˜å¼¼)ÛVµ#8Û`ŽáˆN:PpœˆY,>×v*¹–?oMÁ–HgË2§Gì¨aív>…ñrȘѶ¹‚«ã Å²ó=Ö)›³#íøy*¸ˆàtÊÁh_HÀè–>]sÀú\_ØŽ¾·øz½8lÀ¬WžÏš–ENì…‰KÝ[ú²í«†x›¦ßlç=¦hƒ5è|º¥»E–Šñ¾¤Ïßÿ
+H‰Œ—Mr\7 „O ;Ì2E
+½ýøøçCn'ÐøºGí.Ñ/d¿sZS·REëí×÷.Q›‡„k»]õ&¥.V'Äz”^½€ªReðß Ä'„ÛxÎë<þkUFéE<lß\»›h·rUHï½ó!þ·Ù|ÿÆS£ 6|ÕµNÒä:IïÕ5‹4Zõ™RTµ••y
+@ªfÁRïÜ5BèÙXo¢K4V ·ÏhÜM† áŸõöóãtظGW+á´Âã¶nZ[éQë„Œ¦46´ô]›V*Ìñ6ú ²^Þ½ÒÊOÏŸ±»ç a Ò[që=DmA*/€eœdBQ\«5i&»›êƒWókd·©¹ðʵÆ](C4+#Ž~oc4þÒÂØì“þŸÇIù2)ï÷4%ò5c}Æt).ü:‚Æõ=E›®äïÐdÏ©› sƒ] =› ¿BDÉ2F¹—Öà-Ξ®›»ð‹B…'H;—’B | — ÓbüæÂØÁ‘ÓÙxJÆœŒîÕÕx5)Qh·WßA"ÂLùa_·ñ–¤£8sŽ¡3`>T9qá›ó1ÔQªm}‡¶{‡TCèÇ’!•ìúüÔ ñÉŸ$ëÆ<LØ;¡T†¬6j¶§Ð…Yh.äLdT£ÏZg…’Ó‘4ÞÂñ¨áÍx„¬¾oêá;ÔÈÛ4«¥¬t?Q HÒ´2b<Ì÷QTEÈPF…âQÆíD÷¸7þ›RU“#„ uÕ¨ò<èO£u fJê‰\Uö»Órèî“æ@Ô'h7¦L#›š j3Á˜¿ ÂSÊVU%uéÇñ¸·@èzS4}P.%?‚š¶†8””ß&„G[à&*'í¸ Ñk*y±%]1Á±gùšG1‰ëUo[î¥raF/¥#Š[5ºØÂúH¥£Ä„˜M¾¸ê²Nâ¦é UûËïp7rFìw…üÕ+‡Ÿ:¤àƒ¥#@µ§t<ƒUa™ÂT“XúâRÒѪ±žNµ‡Yãð£j^õcÂ
+¿&gÕäÏRÞxªÁ,=§£vp%igë(î/Â\3Ì=[:!!E*õó}”üð妺 #%ø04æwÌÉKx/Å^¼ü>Û,^@¾±ôóã:ñœçÈœbÚ=Þfð鸷@ºp¯ÐÒ¿×jä4»Îûµ0¤JbXw¶„áa™°yy;YBBhªdxlv”r2æ½kÑB®p‚\íçx¹ô™>ZKR@iÂ×¾ò7½ŸÒ¹c¼d•CZÿü8€Ö›÷É
+iË°ÐtïP„èL¥:o£H)4¯¸¾74‰5«e$þš“Cåú¬ÎÞ¡þ«Ò„%§DaÞÇrüƒ•³°Hņ0{X!¯­%
+YÁÍ »Àïq=lQgáx ì€ÅK^¨Ob<HXX*ÖæÑgèÂíX +V<! [Aå$(ÜRLJ‡±,!I°¬’ì~‘ˆ`I"Ì™`ð!ôdöýÚ'á83¸V„è„+öhBèJÏ­¦ˆ ë¨ÜMº¥Þūˆ1m«¥¹ÓxM÷g·Ùjh¼ ãëºYÃZTµmbàa| 3‰µ¨]Ž:RœÕæWÈËxIßǤJgˆÉi?2ú2a©S4jlZðMä Ù‘ý¢ÿîWKà™ßJ‹Ñø%pÔ
+9A0c6“7utŠ7ÔrZzÞÐÒÏ™±ùiA­JßNI0}He_zK*Èñƒ;þ _XTcÇ™Ç
+Qä~xŒ„.è†PñBÞ8@² =[’çw;~DKÆäv%[Þøiäê"6ùž’»ÅvGŠI0ãÎk;}ÄœrOïxêLÁäš…·@§ˆÓXuø›Ýmˆ3èûµ‘¯‘ͯøsb2Í55~o10«e—+«
+Ù܆ùÍæ„ý£µZ¢î,A)ãéáÅ‘½jÿÞW᱈CCéHü¨Ä R[Îg7¸H9’j“`DÛŒmaI¤1¹Ç„¡:ƒ”ÖЧ
+9·GºkŸ\aÞIw”i¿]ù”ØßÖüöî^×o´ÑŸöOæš’ɧˆ ÀÍÈâläsí¥KbÐ#]bÍÐÿœÎ*”wõÃP.‚Ds¨k-º¬“2gbÊŸÑ"Z覮Má[Â,é´ÏÛH¥ Íߧp`l‰ÓO
+ `öEcòv„H7
+I´QÞºS€ú– ?]ª‰‡m*»Ä—óÅqØ*‹AjsÞ-Á¦ï +B¬©çÝßË·—ho{9Mp”ö¶˜žb³uªwy7ÿ&+‹á0aÚ×Èñ&¸ŽnÚÉZYFÄ ¿[”Q±­û* :JË;DžfÕõ2Pþi»pÙ–¾¾fðT³¿¼­ët“^!ý¤½š·ý½€> DHb©ØµºAH vkeîw‚nÔdûžœŸB uŽÇI]ê,]a aw•!$vClOÏöÁ £&ûœ
+t1/Öè•Ë% åkn€P-xM
+ɬ«ªÔ°aêNÿœÆvÁ¨YYѺÚäsü‹!X[VÖîòu¾< ·u0Ħ›‡Çl
+pÅ@+C†…aŠöM±`‘Tž”µØ
+“Ú~öä1$_Q„C*öì!âû|”CC¶ö9M’™±ÇS_6]¦Iƒ˜>0Æêì^1>ñÜÛ}ÿ˜ÛØxºß½8·!¾—ØY†oúý“‘y {¹2Z…Ôõ€Uç¼/•Å°LÙêô‚L5Œ„ˆ<¤‰#‚ ¡Ö¾?JpâÍÓÔ¦ æåù©¾«$ ƒ±ÅÏ”ºü`]D¦†t©·‡âª¶×ú›ú"?$q2TåŸÃ@+óàOÇVI} ›žXøò†
+(»ÜýÑ%Hv’%˜›²öÑ“ügÆvYS‚¿ùHø'ísèt[ä Ò8BRž»Ý„ïй8,ϦÙ"ß@ßZÿé‚0 }>‡IözÞA‚D$#WßÌCbÁ‰Œ€’›‹Í2á}­ï—ãÑP
+vèøîÌÀ#_Ðv³”)Šî:ê+WzÎ\c3!ëÌüôÏQ¦mÜÊ3c?Cû©2Šlû• !VÜ Šà™l•³¤=öý0oζd´›éH{0v@è ) u‚§)CYöÊÛ<""ŸÇ<ÏM^ÏC{‹£as>°Š—NžPÞÊ{‹o ÈäÊ8k]ÈMTMRþs”(ÓGéö²A·ë~"C(Câìe ö¸: rš¾C¯ i¬(ñ£°´<”\]-AQcºðVíåÍ´¾ÕÊ ˆ_I:ü˜¦)FÉLÛ§ ~F\àïGØ˘4ãú†@Õì$K1¢±¾òšŽ¯`2»NþдW Ñy5Ÿ(?
+ÇËëh³‰Dp ›® &º0@Cú…>ísuáŸàKÛå (b¶6íé0Ú8`ÃîïåãžÖ!Ãî­ ÕXÞZš%>Cýhz2í*<hW)Vg$a¹XMRWÙíàÏqjº
+BÉ6Ôm·€èaâ‚lŽ ¾Sü ÙÚ,ëI±ÊŸSÞœÍZEÜœB¼ÀÞ3´`U¸¼¨Ákö‚‘îò eC*º71Ña:»‰T Éð„áqO,>Žâ˜qˆ=Ç}%› ÜDW°ã<Jñ5³a3Ù£9Šô#»UŽ]Å‘Lù¼´Ì8"Jh“]…è–ˆäôÚ ¢CšÐ”géýÏyM¤äÄòÿøSÐu?²¨¶ÏEu–ÒvD¨øØÆÉ>çëĸaÕd— ‚neÔ×´! çNÖ|#ˆškŠÖ7sŦ´©`µû(/5-‡ÂÓŠ½™šE
+ Vx&ö,Œ pÍdÅ)JÝœdbðPÕ¬«F–N1 µ<S'€ôóIOõžžæ¨ORå“ÆeÍnm@Ô”„ü;o:7]A|zZÐÑ8_þÇ0èò¹¥ÅÞ£ø)/ÊŸç¦[m Ò V.p
+´³Jk©<´éß»çÖíË)ÎÈ\¿Ä½ÛƒœN¹Ë="ÊÁnº­AN“ƒñaqe³ÿ\§_ï­ËyÇ”é©Ä—5GJxU•ž¸à
+ò Àí:—0þë›a¼þ4r)‹‚çÚÔrÉ–_:¦%´õêk½âGÅaŒK÷l~J´*±Ân>>‡±›?]ä“Z$îÎÅÝš‚²˜]…+«eží0€Šš)IXÌ 7Ö‹ƒ~iAäFDúixu•âec}اs$“ å0Û?*†ŸÓÏt°sèg|0’w²ÃmÓ¼{F ™YbD%Ä!ö)M‰ìþ
+FÝ Ÿ0|-½½ÜÓä[ïçÜúÀÚÁˆ«â¬ÛN¬ˆ@ œÚÞí¼ŒbJþÀ»ãÄÚ|9³…3"¬áEð[´ïšúâ®Jçž?±Æ=ìqÇÓ•U :ºÆ»3……ýÒž÷¨óX†€å§=K,‡Œ-ÍaéŽÙàG&šÕíe‘âÁeó͆bOŽ)H+ΗǶémHv£Éöa÷9§H.bžŽE¸8çD®d»»2ǃqSKïƒ&õXžŽa"'–°‡ÜÏÇ”ð¿Suçýâ­ýy/Œ>‘cÉ›ÇòÌ ÚPÄþCŒËšyyâ,©ùzgVé“Ä Kª•Tˆ¢„d&nǽA™`SŽ!íQ.fÆMÕ͹×V\ÖtÈAv¶îV8Ç0€µîiÃ×3Ò…_³½€ÜqýUaÈÕt@UÍE0§MCÙ†9^|=®¿®T³iå6ís­DÅÐ`m\û…Vò_ ϹéÏ›õÍ©²ÏLÙŒ1…fÔ
+)Sôùkƒ  ¶œ‰ZÈÂ^i×1@ÐêÁxPc –8ã‘:»i
+P`çzfs›í»žÂ½Ø…µ„µ‹"+þ¥>ÔP6¢º-Û…ææ¸.ás悪ĄÈÔ–™Nô÷(¤Œk")&VìÓ@4œžÎpª0«5rûÔ¦‚`%Ю¦æA÷œˆ‚¤¤Q6$ãh"D›ë)οIì÷¾‰wŠÙùˆ#ß㔀yAËz}jÕŸ[þëMÑU!—ïcfg;l:xLgARìþ&®–™ôåÙ–>Ï€O¤’á4­C<— #Û
+ÍÊîjïKÛXóØPFÝÄys@05°SÉÜB„ gÔžÃ+‚z Í  ¾§ãŽQÞCOWBqæS&uœ‹µ´R‘Qÿa¼L’ã8b(zß'`ä<¬é¥ná­tÿ­ßÏD¶­*”ØŒ¨h¡³²€?ÐÎl—í¥ø1Ÿ49™¹ƒm¨ç¥/pF
+ =PÂgÛ‡ëÌœžFsÅ›úM˜°:¦º%UÄ3@G´—Jòì7ò¾ Ca€º^Ë„ ½ÎA™)çÃQàÒU~ê1Yp(#(lÁæ:þ̓+Ri%ê&ßßO Ä‹â´Û˜J!IeÊ­NÑÅ“ø¤ñVQ_¹6èBãàâR„GŸQP¸1æBT8 µ]R¥&àX‚¶K %@ëÇ£Oä®uéÅ–¸9R)?ý¸b\NÕh¬Ûh“ÛØÊÌN
+IÁΠ1ev•îjrJ Aÿ±³ù瀞.fÂ3µSRª^3;Fô
+f8—ÁÍ°Ò"ÔΓà[h€’³ä–äO’±ÙÇÐ:­··ÞÈßa+´ì.ÅÒ YD:|€Aã°È¼˜ÉíÌB2XNqzëñ˜“hôF ƒM Ë¾Ç©„5'6ŸÝ÷œÆLúõŸ$Ú-*|”üïE· HIQkRÞ%RÂ~-´ »)ªËM’‚CÝ HÉн‰¸Ü
+d |Ó“Ý‚’+¦š‡"‚±`JÉ€N‡ìþ |Í•ñ
+Ö‚*?À·¼°ÌŽ@jòÖÖ"G !s—¨•èžTv— É
+#¾(w4irbypGPx·Äå[ä]ˆ2mÕГ“À²ï¾(r%1ôàå¤#¶Ú™)—žŽÿ Ö¨4q.Ó$휻Íã aÍæ$äðRÿl:úp%X 8ÛµþaŒ ’øn8ŽÇײIc”Sraî.=¢‡˜Ðyõgz—¬2Ì!“ç‹©ßÎD ŒÄ¬ŠËjÈoœÜêObÝ
+€[³¿9`„k˜k0‰¿Ò•Q+ž. ÉëMóÆsi0j8 {ñ ¦¡)¢ŒP¨Èg+8à{²ÊöIwzñ&£)!‘§J2:áÓTÀØA$ˆIÇÎ7}½Ìë6”xŽÚ…1pE}
+,
+2lrL¶‚ŠhBT4Ù(ÌhöW/}l ôÀ
+`®XàURñqÀñtŸ5ðâ‰a±’1?™›B¶jš…NöÏQ¶Êb–˜Ì³Ñu¾D«¡]A`«ƒÎcÀŒ
+'vèvsG«R?#&QÒéìŸS3Ÿ£ÇíÁiQ¤ }Fì–¬Gq2ûÀ zÙÌË9]ü>…‚ÜÏPQâXëÕ
+`|0KV0/ Ñ
+“ÎBéVñ¸9Ö•vÖ½èTººˆò¤*…
+4JÔ­„vã‰`jë0ÞB¶…HeÃâZäNœÍc´ÚsâÝ"=.bê«QãçCtˆ¹…! å“5ãE0—!ûmÎððåR”žÆ•y¦?0Ôö0vB ¢¡Õ<]s ä5ÜÍ,¦D.‘ÙÝÃkÛR ˆ˜¯Aï]yùç;ä½²WÌX3@KëåÀ/Ï
+z÷±¾9)—"äC@¸Êð#IBM
+{n…Ãp‡ötLo%Ùðuç.ÿ·Þ ( …ëãŠÑšÙ[ÑÖc.‹(ãhÛI]‘. ‚e›öæu…PÔ=ø–Dí›}íYZÉôZb¯ÎúɶÆ蟃 …þØ0þnvåç^¬õ¸Kh±ÌIl½ì.F ‚Qàáý(n¨ž÷†„-Bé| </£¥ÐÆg¡o
+’åÔI“G•þPòH¿þòŠ<¸+¾ÁÁU õí"oo{«èB þv]ŠÅ|ü­R¼R:C‚Û@óË-šê9ë±5eÍNºˆÏŽÙ1ðg$
+U(ª „÷c‹Í®AŒ}öµÆZ”XÜŒ‘ò
+$€6‡=dŠè†4³ægJƤCâvòAc«êàÑuîØ„ÝK:ÆÂ9›Ï!„«¯¿ü¢„¡p!É2ÿt‹PàR’{±û$ Ñùê®m K‘µ#ï‘ù©0ÊÞWعfNÈbH§Øc®`D÷cXÐW9f‰TÅèÈz0˜ßê”Ø8•$KÛüsn¿ßæ†ïn¼÷æ†ã{‡}ø—ñrG®#G¢è
+¸Ù1 ñ7'äÊ(ÆjÒœýϹ@âI¬‡R?K”˜Bù¹÷ä—Jý|eh4_aÍW~ÏZ8en /ç}ƒØ
+Aø¼N²>E§ÏÝ‹nœšÖ)þ[ç°(.r³1Ôwe_kÈiî
+1¢:%òWÑ„‹Ó;ãìrY§Ü[±å“ô2‚F&:Ž»B˜ˆYÍïõc>fîppÛïo‡ cÕÔ•Q'ãôÛþ¹]Gðã•9ý…½&Ñcô
+hÙNJþy bÍ‘ïY¢›&D!0#;µõ¬<EõZõ²Ê¼ãÌ1í™þÍ‹z‰IìWðÆëH½„’ÔÒÕe~ãë ±Òû”Í®ƒŸCæ§ÚÄ$¼‡/ÝœCµK¨(îé·‘„cžR[!Ú#qGõÛÍþôÄÁès'>žEÓÇ’z»l¶{Æ‘ò±>f l1×ãh<?ü0bÏ <s)ƒP´UIÖq*&Êh¼±yóÒŒyà kßN…ÒÑ´h v0gðÔ¡†Õ'ä'8‡þcÿâP¡Ñzð8c7úD»xÑhê""@Á"(Oßʯ8ŠÕÆ
+i²´\GŒÛXÎ3Fͽ…®35FJÙ!Rú!®P¼çš²VIÈÙÁˆÿc¸%ß’¨©†$¢Y£Ï¡ŠþôCØ$Š°°²ƒ[dž¿¸å¹áAòÈÉŠ5›Jf]ܵ\ÖJùBÌIõ±* ãαý!ˆnfÌ¥Gî¤[˜]*iq<>Eaì‘ÿžŠqâHMYEz¨gUgØ̸Œ eºM§_qb- Þa\QÛa®9€Áev‡!b‘´òÏ®†M…•CÞ©—~s(Êà?¥~Œ`ÂÆ 3ìZI~¾2[ #ÍcFh´ºñŠ‘¡ˆí 
+JXL‚¹¥z@E”•¢•3bÒ?ÏKæ_¢W•ÙÜ-”‚
+¡/Wñ»‹Å%H<´‡ È5n%x
+¢äÜP+Ww¿‚²xh`Æmú¼ï‘ÔïìÍö†ØI;]ÒcÞ÷yúÝb?^°aê_ÿy Z8™„qÝå?b´4ß·ðíï7ÜH³›IÚªN¿!O¼î:P®п‹â9~¡ü5æÇ!fp-
+‹{ ÷.1¯ÜçÇä‘ÿ÷í¯ÿM‚©ù²ä–õ#XÇÖ£Ÿ(þýFUi£Æ’ÓÔ ÿBß;9Ã
+~£Ö&?žÉ)Ú$
+[-çŸJcŽ ‰üÌ9©ïR!M¸†@ìOq_ZÉÓ› ¢RtH×–Ö9¹Qrìļm
+ÄÇœÁ~›ªå ¨ÉÛ¶c$‹²ïO)QY,Öü>ì]ˆíÐæ•ýª; Ä™ÎB58Y\zQoIfH±=>õ5(¿ÃM›®Ðüœ!`mZm‘åt$L9Žå˜À,‹àI ;’ñ¨cJÙ?‡jf%Hhå5*šçüš€í¡áa4æ±/!ÞIŠ‹ÊÐbwç Zó°ïý©0é±âÇR0A<½ú…ÿOy™$GrÃPô¾CŸ@ÁyXËË>‡Wòý·~ŸªTYÌh9¢Ã¶Ô0™>þÐI]+ý¹ÁAÖT„ï¯ÊÚÇsª¸,y‘`q.þzŽtâ
+ú'SÅ#ÅxÒ+ãPDT€ P§œ o1ª¡¸Åaµ鯂—3€­ô ¿W§Ð!ûÞ.rDà>™íPpáòGf]ó<QR¼_…c£U0AgËÛÂmg „¬z(²5ד¢l%Ò[JG¬„6 Ûa+×à#‰r‚ p”²ß…_!ÍÙŠ )~d|Õv˜)ÃÃÄ]2,FmWðäâXôf¨K’ú¢“~X
+˜”’j²íL~Ÿ£wCýllÚ% .᧰ì"%À Ù]r»DÜ(9*å}E"×.ÚËÕpŸ~•}΢I>¹xs’Bzw+)@ „0wIT
+åníPâöïU<Nç°#Dº®·¯¡¿±¢Ñ­¡CÛA»Ò£u™L„Aän±«’
+0ð%)L}î^&„?ì=uá°Ë:¸Ìáò —=!Í|ÊïJ&\ÃÏ«¦¨îÙ²T ã¬ï%`Ð\=2æ%̇`§
+x
+)ˆ¼íìç¾GSšPß·úË*pÓDÁÖ}ñåý ~è7Ú=|CDEø¶»®×SF®Y‰˜ê• þæ·"Ý ËÐÇ›sPpR$¨Éé|U¦Ý|l”E?W‰Þa­~`o¾nŠX‚a†MÓ°Ë"ZÙ‘ædIBùr­>‹»Kˆž2µ‹ *€$K–=µ§£1d–å¼Ü»Ozˆ’7o!r1W|¬éødˆñù1E<‰y¼lRA†Õ@°_„ŸDÇYlQL»Ãâ6lXÚÇ,o”5{F‰ƒµ Å·RÖ”¦˜¹Ÿ.±$Tó ½Î_³—$´uŽàØ72þÔh—ŽÇÃsîtD V®ÊèfÏ ™æL·¾”|þõÏ_ñ×ߺ™%,Br›îØþHAÚ¯oŠ;ª„iKyušY
+‚£ñÐûùœ¸z£D—v/)-0˹K´ª >© k¡Í‚_ý*L"bÁ¼Ç’ùªõÏÑÎX‰•HÁpP¤ÖäýÑ™~Sò‚?»êRTH+S1ÉËvÕåkp®r• „Ž¯Âsæ1'ÄOú_ué–2aD‹ô¸ÊRLY%‹Q„À
+,{‘Ñ,Ùé@ó1Ïâ)q.—åÙðÇTðÀ…Èwˆ£vUSìaEa7+Š¸<šLª‰¶2¸ä¾ºžwwdÏ©ê¶[”4\°`Íw Ôvòà“±,»¨‹<¶¡¶O¾ìø%䜸‚ˆ£0Ø«&ã7](T¤‚+Ç"òç׉¸ˆA¥@­|¡òÊP\6Wf>ª£é åêw\ùVT>Dð:?®FSÐè½$:øÓ ”$‹ëï’.C†4¬AŠ¹¨(‡X¶ƒ®!l»®*ïÎë›k|F—óÚ
+ÉØad>e0Ú¾K 8RTY‹´JÀ´Ü‚ÞæW±C ,ç-Ûâ³rœ›C¾ì‘ë¢L˜À àÙMèÂucýÍà ÇWhéAÉxÐG6³ä˜4˜MD–Gå áþb
+ª»Qfùpì#º¶6¡¸ô(u7¢ð1B&ö.[pu`à ¼¡ÍqLøŒÆ©¬“î€P< u+7
+ç]ÈÐVwå<\7;aa±Ù‘å6y¡rûƒÜý&À$U97#À ÏÝ"½c²D?L¡•ðY•8kÚ”’âJ‘Gõ€8p{¬ §9 ‚ì&qLÏKƒŸ§fWêDâyMðÀÊH*„N>Mó=¬žl’`ŸBvA0{!ÇÁW4!Ó'7'/ák¥Î·©‚x Öcè‡ÛÚŠ#BÕñí9‹Ñ¿õ¸yýš9ØHdlä»W1> Â2Îvîd5H…j¼7ðÚã¬5œ ›ÓãݬÀn 0óry–·">ÊyÜಗy%bÎuNø“"(/òE±žq|žë6üI–釡DuH3C/Nßý‚D,M¾ˆìÀÛ{뇢ß7E²vú9ˆºVQ[ö˜ÆiÊÿ(z¿ŽØ('quü¸_¿‡\i±_G§ØxlC®?.‚açŒÚ¹ ]ôÖÌKÑ×O:þ{¦Úì*Káp‹rd¥Éžï¹\kNÍ̲•ØãÌ ÿ¨èrÛ*bq&øJÈÃñ“îŠx¬;1åî²?–,nÊ\•^îFŠ=Ì:ÚYVâP éLF:Ø%Z*ñ ¦[ §"‹ÚL›>„Bîbfc/¿Š&;`§½L‘_04ün1íshÃX¯h†¢Ôñ¾UÌZó.áþ¯ÙŒËãf=%‡Tü&Y:\ÂöÝr˜¶)PÇ>%窬شQ†çf÷‰ÔírË^x”‘UJòdÚmG@¼Ôô+|€¡•`$A‹g(á™…»QÕa%¨ñ"ˆ]v‰„%×eÅ%vÕÀw”°vè|Ž ÊÊ6ˬïDff¨}W$>uªcÙ?†#á
+†>ìQ®¬ò5<ÊšÃÖ’ò &Ú¸Ïa@ ÊÁZ‰¬VKbCò!:Œ`¢ñãer%×­Q ä-àAbÆZ)SZþoÿ ó‰¬BöF"»ƒÀC1¼,òßÝ@;—2])iæξ]HæciNg;—ÕŠh}Ï>Ç´?k(BæOŸ¤¬E¡}üd, IN1^Î`Æh8†÷ÈÊ`}½U[Žø“ׄsùK™^E¸, în³^ ÞM¶'¡{Ëq;‡@CŸ˜°Óð—/Þô”ú
+>£t
+–wëÕ¿©¦îÎ7oÏÎB¨åÎ\²FX™yÒµ¿àU tÌ‚Y>¢ï˜W¦E * ÅǸÙøä7Þÿú†\mQûñ?!¦·x-­ðÎX¤¼ '…me³Å¨HŽÔo  aœòðgq(‹¬'3„»ÂH22Pà 6ÔûhÈžN¬¸‡¤Š]äÔSõsÐfF…DУ T¢°ØA`ÀõTdÃk2„l‰­U¶Í‡Ö„Ì’œ¼S¤ E-dR³Ó–$É#s>€rÎ}º«ã; `ƒpÔV\„*ʪêYî2á ËS¼‚*ATyx"R¤ÑhóŽÀX£'Ã(û<㥔™øø:Ýé¿€¾>€D’}÷ ƒU”{ŽËà†yÁÇG;°˜pk+cùÃ\Œ~0—åì•’ÉÒ¤¤^>šË¹â;稕ìu^Ãã
+ŠC —Ñ”ÿb °g4¡6½ÅU-I`[YÑÌÉ:óI“”:Ï9Ê0œÑq,
+l͘íÒDsh„Àá„7 X$«=®Â½ˆ&É­Ï /¾„X3žsŒ•"aÕfùº.\;åôaC›,k“‡êõYPRšgŽwÌY ¡@–sºÏí|µì8:U}Æ [£TÖ!–4vÆ4³Tl ŒÚÊ1³kPqã:gbw4è¥ù#©Ý,ÛÖ›2Òî”Q9V˜–ÑÂsÑäûVÁ¹2+²šÈSS»qNÙOb7ÇBUÂ#oÀ`\V?Ì6<°àÓµâ&B†®<Y²Šš4Š¥h畆>àì@¨@fspE¼<¿é Ôü]£4ûc–H o‘ ð—0Š&±ø»†
+«×<‘²Á†è%Tø©¡³÷­¾²Ž|ŠÒî9YĪ•¡MÛηÁâÿ˜Mê&kჼÝ8šD ž‰H
+L:T¿‰3y‚¼Ü°1D)JY§€Ê°eÈ“{ÃëÑ¡mÆ$Ü#„×XÔÆ ‹fS0Öc _;β¨¾„;w»E´²§zݬӟ ˜¬šîü©U&dѬ°²ø ¬š
+iÈnÜ “·ËYÞ!òAƒ5·PW
+„Å ’µ<êðTˆš1Ûä.H#'ð³ÔH^r§C†s8ʆbi—&
+cP1[5®BXUVèa9hhœ«´ÍÎ9d'D…Za‘ß.„ü4YÀNw)k$Wl0Ô´Ó„¿jþ´,ö4ñ˜ƒpJ<ƒôp^5¡""ît8Â,…Õ€­ÚA(ã–óáÑ6”œ±ˆÄô~ œ¸B´Ð?eÉÑ‹dþ)4|ÈV?Yòׯõ›Dxd&­g&i^&<
+øÇT¹O¢à@%6)!Úlòó‘6“ì7º³µéï¿î &h™äéŒ( ÊR ȵƒ0NU£[úçM
+õ}‚6! S×B)Vß9ä;˜ËfŸß9‘üºÔE‹Ö¹WkRG‰Í8€þ¹½ ØaK†šgOSxzßîízßì ùžÒþ9}sµW×w|A|~ã¥W=>~ ˆ3”άžË˜¡4U»™ M²ʳº;<”´à<Ëe…YŒ?£ä’Q'ƒ(&‰Ño§*@øºTаî vîp2Ü”}+˜@C‹Eƒ(h78Bñ§sÓý0Ît¼ÓÞ w…$hÑí'/„õÇQm¨·É­À^.H›‰m©2øD…:È#ögXåô"ZèNc-Mó»Ð¼¤ˆF£À!s-3äÛJ“öxI™ÀªpÐmA0ˆYf ¾˜ˆíD.ÔN”¾´›uPä,¥’ê:„)­<_W椈#›ŒZØ­Œ®dùV
+.°9JT·Çbó^¸ÏµN&]P|ÍÌ;Lñ9²M´‹'Ì?áZi›Ôù>Œ}+$[±QI^O*…úò®tÙZGÚN3bK÷¾‘›B6äò B½3V½Žè[azY
+R‡o((Ÿqr³XùQÕ³L5F¿¬uÐ[ìÍ¢Éb®Jn”ðÝ@Ô[Xc AN{« ¨<’\:%œ˜m;rQ =mÐŒÖ1ëzc
+qz@´IŽ¡àøb׊jã–½cµï7²ä*׃×=uàâ½ CÝúÍ:J?*%ûoç= `eƒ`OŠz8-–³£ÊyÉûs‚qب5 gŒÊeʼAÇ› ^‡y‡Ç˜ï†#HG²à¹àXŽ®½Õ…sÊò|PR}“Î…¹^õýD€åQàU„æJ_øJ¤tYZBØ'¾°qÁ™1iUœ2ÛraõŸ@@
+wÂŒ ¨u¨8Î*
+—C„Ö‡È%ZíQ‰¬«MI|{§w„M“H6âÍ:×8z€¼ÇÑHV‘Uu¶AA*Å4úã$ñÚ8žpfSâèÄðq±3O5z1ß…eûÍ:/¶üò·6þ¼¹Õ èó褹RA9ùÚêØÄ£pUvHž¬ÂH`îúÑßV›*ØŸ¹ÚN††ÅûÀ£x«2‡Ø«´¹_ž–ĵõâa ³PÞFÝPX;Žg\ûa;]%äm¤#˜´äº~‘]eùVÖ4IUÐÕ@#ŒßÜê°Ü.V"v•Ô,u¦iÔ/ÏÌCñÙx6,6'K9©=Á)H­S±ÕA£ Ÿ°‹‰Ó…ÛÛ NýX È÷Ý8 Xö>¦Õ H‰ÊY7“–c¸fð2Ø®#¦9·‘˜ ÷aÊ)Ú Šа½EK
+SÅgÚ³ƒ¨:•¥Ò¤1W^8%ˆVAgDRŠ²X9ÊÍ AÈ(bý"üWU¸€>ï@±Œˆÿã¡ãQ]8Vúx“€`äKR²úKÁùbP„¾û#]dŠm[ëè! %¿þ‚$¡€?27” 6Ì%¯­ð>2ºîh“|
+Ù¶wÒÎ>rÕ£Ó»äX†p(–Hšó£šõéµ v¬{èøNŠ]˜®x^ŠòÓN\}CèýŽÈ&‘–AĸØ6·Å/³»ªÕ‘YRáŽ÷òéºÃôÜ}êX±aìä]×F@èGÌ*PÏ$0?“á}6(/n¶k@pBã¢%Þ¬C%PÒ;9·Ê¨§ezyÓò¼ø+¨ŠR™+8€/žW¿‚0~¸`¸Wz½ $…Œ¦òZÊÑ+ˆDÍ ‚gmò>´˜gc㉲¼ª_=2®t5vçȪi½¬ßKñÀïxôБaÈ}˜
+Ôê ²œ^îI‰VÛM$u¶ù+La°±‰Þo½Õ"úAÉ®ß@^zTí¬Ë—Œü€Ñø
+eIâP“òT«•E»ÌÀ¤]¢•ò@Õ
+‹9®é‰Ë< "½V‡¨-•:Ëêe1 è¹hc
+¤vê׆äÃëøK•LŽ4c·J_ˬJí<Ý2Õ”Á] Øá$Û8— Œp˜Àªí(©08+FÇ%Inn$1ä\ëÈ¡ÐJPã^‡£sŸ )ˆA0–ÝÆ*éå½zë¾sÄ3ô¨»¾[¸…€õP6ʳÝ툅‚ÅúšÐ„»äé˜{§7P¥Ù¸é”³u°ýËîÃP…Fbâ¿X ¿kö±-ã&ð~¼Ö±øûÁÀq©3zcu¨¶†éàÜž•¬$}`ÅlVUcöCNÙ=aȆÎýÆ)Êp°I²ÞJÊ®ÔܾŠÁ‚`P¶>BÑxÿôãåŽ[ç Dáh®]$‡Ï2P«Ö+0’*)³ÿ|‡3¼€tyb{ô“œ9sxÓS2%™t²Z¥¤º¦Å—¸IP²Üß1 ®¦,üøf¸ŽnÔwž—ªHP1(L÷ûýÍû`AÓÖb¢Ø9! é±Ë™Ÿ0a†7ö’ÞŠ´&(Çî½0  hWù§E jÒµHJ;^º¦lô!1ÎØ
+šå£'“b‰@-ç`L^g«‹¡ûþÖ“´ÆgŠKWã—ðq°!Úá’Ão«¬™—0=ùÑá£nþ
+Q³ '¥^y·á"J­Š¶!}ŠËö8)š]k^Åp–ƒS’˜7ù³†ˆA²ù0… OTï ºU'–]Œ“´ô”8¯\Ũè1¨ú$Ø/ò¨.8´w{ë ºB¿+äoW‰¤d,¾9–ÌðQ€D³Û|l°!Bꪔ0%À Yµå%q×ü™`Ì’ ÚdU0’A»xÕ¢}äð3ð>ø;,Nj.J¦ÖbjéG¿z½ÛÚ}òŒï×Ý4E"&
+¬>JðûYBbÙJqd‰|)‰.cš
+iV/êb…D\˜Éa:ã(b%
+ø¶Q¯†Çˆ‹JyôS>ô÷u(b|ì%*“opìK/"%Fû ¸:†±òAWäh6Ù™béCmô
+5
+MÆÌÙWÜ
+¬TÇF¬
+M‡â'‘¢æ ´[Ä')cÉ{£®^ñ0?¾£è1´jÈó—ÿhÀ4®ŒõIÙ@TÎw« øHÆAÏãN±TX1F³â>ÈP3E^ÀÃD{°g#Ž*ì….WW„Ùg7HŸ1Qrl/ E7lj4²Ì}\½Å·Š¾wϼO×+l=VP6²\O‘aJn_6‘‚ïœ ŠÃ(oXŒé™¾ãP…؎çÜà.1ÉŽd*-­Cciä(¿z%
+·œaíoß"à]잶žâüP /´ÉÊç(^½… ðâÆ1öT<ãÀŽ`&p·Þb²ë²³!Y\¬*ƒñä¯Ó8Re.Zgg 7mIJ£¸Ÿ4E f±rÒ&%kG×j‡ˆÒ⎞žè[ÁæCPñ¦Êå»–•5ƒ‡}Ìàµ!²„AøBØò¼·q +÷…š³Œ¼ íõa¹q“‹¸ D/Ýacf“ø  8*ô" Ò•T< >ÇÜ,ú!mòkö¢¤f~&‘¤ôþö÷ÛÏ_oéÇŸ½ýüï-þ ÷¨†J­$÷0¤Zqš ÿñï‹à¢<B®C^"k„ÇJ«E‰V ù·yIÃåHÎƆÇ"\€mp$ua©k˜h]/‚ãh.oA
+»dh®ÀO)ÏK|·€¶î%S†Þ‰ûžKöQÌ6+,c—Ïlã6þ`
+H‰Œ—Anœ¹„O;ô¦!R")­3ËÜ"À[Å÷ßÎGI¿1î_ýÆ@
+µ¼Ê ^šj´«VÕ)dãphÅ©òf£l„z»¸©-¾ƒˆ!‚;µÅwjµÎu|&'I1h¥ÎÿÆî¿yc*å¯ÜÔZbГހ³…V>þ|§¹~Í”þ„#è
+/³s‚ÇÉLqcö 2m¦D²…¡ÝºÐ%&SA­ð–„ßa„'Ø(ñǂ̲“Èq€ü^'M¡«àš½‹CújPÇ&R-[‘¸<DÌ7ÑÁZú>)™dö¶¨úšÕ@çeÕRb•ƒÐp¥SÇñ)ñÿ:Ö,k~€Þö~q‡äÌ©Á‘¤aµFJ¥3R
+Í'ÈQB6grf±k¦PE.9,I{R„îj ¤ŸbˆÄ²«ÑÉz­4U±wq¦~dô}K)©Kœ(sPr¶ŽÝ†ÿÉÃI×Çß mÏÂðh”:³”äã̬oåžGЀHDòV1¯ÞH$úÕ˜‡)z³C†>Ö¤QÝ:)ðÑ*Z™ú²§3 fÈÌî´ñr@¤¾tèÞú>Š‡¡tžl}È SPP÷ZjÄ௬ó${š8¤è£#‘½(B³îâQB 'Å4ÞJÔê£ÊJ_‡‚iµÐi]Ýq
+mñü•áä×Q·ìð} ¤Nµî£n)¦¬ˆbyQâV©/͉[Áïqn´y¹Í}·GH\sÝ&ò8·‰Ây8|‡øR©ŸWãUü ÂUTúA»?6w*>1Ý\‹è×tÖŒ—ãn ?ß¹ÓÒŒÒIng~`Á½nÙäñʈ³ô2o@Þ:w
+îΙ “
+â)­GÛ©ô+lÅq¹áíŒ
+¡nˆÑ,ÒÔ=R>ãÍÁzA€`7íÑ9eò äHåÆžK=Å¥bÆ Ï¾Œ‡@L"E'Ît!Þ\™vˆðcæËí”uá%¤µÿttT1¢Em®ÚzÀ…}L0‚À¡”#ã†ÁâiŒó Z¨Tt¡lº9å¥Þק\úæôI—þ»¦æÒÅצá©P¿~22ÚƒO—D
+ü.;‚ÿObÍh[Q"šMRãuÂni7’ÁÇ5^×»DQ<›^*RÂ˃OÆþòág@ ¡D[à«»sx`ÐÞÑ×Ø.Øö&žãï­
+ÅÃf¥ØYFÒåT?Ðß=èÀ†ö1/ÍBm4Œš_·Ø(kç!¾›±Mjô¯>®ú¶“ÿp¯È>%qdž— À/D Ú–ÜÅw*ú–b÷‘æ;
+t)Úk/aQBÉá»/×]‚>ò¦/ü43¢±¤ÌVºµ›AÏíæß!£æ ø̧ Rèwƒr¸Œ2äóÍBÙÄУ›¦a
+ºü*
+Á@În´Ùçà)Ð9¡;¯ÄTK nóOÌj7i¥‘q呼yH¨\Á*ÚÔæY†˜~iÁï[ù ìÇàü.÷ª1Í»¡{‘5~µ³û$LüSʲ#ÈúSç´vQ¡6~¸èL!•%gG±@±
+ 63foz–@*µæ7i³ ØU%€Ñu¢ó–ArŪ(ćïhËñf[!„t‘wJÜa¤¦2<]¾B„–ôÅÿŒ—Ir·EWà=h ôÍX¨]xJíúÏ-$žø
+Yv„E'Q@6÷žÌW7_/P[Ép.iŸ
+:B›Õ´ûDdxÔŒ7¬V…ðH/c\¢õˆÆF¤m`<D\5àKÒŽõ¡3F{%\‚¿&›>]D‹lyMÓ¸¾­¸<¥Û`1À¬*£ö×HP€x@³µ’È+ÇíÑšèÉd<ã°FDÌŒqVˬéßâ„<©Ó[Ð/7Hëü™¡ko^P¡Þ
+„ª •p^Á.¿kÇ©·˜´ÚBÈwi‘Èþgc 3äµ´ÒÏûj2pþØýC¨‚
+‡p¦½š2O¼:h7µ6ÚØXô©½}•R"2¼_¤ÍŽ"üÔê-k½ÕÂú#;‰Dš¸ìGȪé;Ô­/ W7æ‚í£ïW¿}>aKlæÖ[hUK¥Hß.ÌÚ6a~餖˜a©‰ w¤–ùå22Û¦É(kJ®QˆžöwhjÏ·\lKŒÜÅaÏV'p³°v×Ú—°÷@_å¹yŽ’ðZ&¾dmHÁùÒÆÔwäŸ å$†ÎŸä¨Æ“öM²÷s°…D.ðõȺ15úØ[¯ŠöÊX·Â
+ˆìQ–­õ©Áv¤¢äþšö"%³·/Ñߨ5Ìw_ñS<pˆÕBZAÌÙÌ¢ñ§¦¢É›µÍ„S]Øh°^žÜ‚.cÄ p*Œh%`á†S‹h1ÍGN†"_!lXLe
+\9Ðwy™´ö
+¼’ÆÉ ºBX` Óÿù¬½Òïøo54ÅÞSQ¹C]Ue±`¤1wòkP y¡â˜"¿ÎA*kLkvL…ƒª,´Xʀ߮:`fÊš¥w&L,°·ìĘDø¡«¨/:›ŒMÕ¦3ÇòN„€gä?y>Nª´ïÍõª;¬ÅPÃÍœÜ82±÷ÒH£Ä¢—tËqf÷ÃLszÀ
+§œ'ždä™"YX“N‚¤Ábò =.2a
+òû2Ž%ØÈ —Ùyú¥ÜT˜Ì·TFÜOÿšÁKå€FÕ˜éÇYO+oåô5—¶ht
+óRǃæjdx4l›Ó†ƒ„$4M°&ÅY04aŒ=*h1!5-¦ ´‰ÌšõÑìœÏðY–>Dö‡72§Uß'vª¸×Ú+Ò*ç1· O ê(5‹A-vvÉ+z½<hªØð6
+±WŽ}W—¨øàWâÅŽã•dR' »ûåø!?TØÆ<\õeQ¬Ñ¦£œueÉ4‘½<’™¸l>‰ô/—®÷gŒ!‚îPÙ‡$êvˆÔ
+UÅ/Èï\›!,Q¸œZ!œ0dt• S(« PqOæ=dš¾IKÀÜO/f~\8@­gnö&•»bq˜øˆm™y¦õ˜‚Žç !‰@MÂk{‰Ÿ>/YAȃFi­6˜o%ðìîo¶ùSîúã|°óÕg¬-î/Ĥ€Õ°}½ öˆ™šVô_Ž >VÞÔµ\-ÚA&§~†—fRäœm¾™¦”–.«äD4œÊ-íí¤˜¶åGþC™æAî›ÿv„ž¦ ?]ƒx†\iÆRÀ–Yšøx6)bÎ%Ø“š¶>:§ËAVË"waCܽCõàáդ boEÈ);Új°#=á,—>]6´ÎÐ(pN1 J3hI®¼B:cǬ©55±§WÝ&yé[Ôz!òÇ_!tiÈáZ|Ý!']Ô
+Ô—þp·Ÿ£T3CÒ¡k™%¤ëªÕûñïjŠÛ4´Œnña QŽ¬¬»0í¯µ×¨µî)
+Üæpó¿§Ìùõ©RÊuŸúgU ×rCèZ^ç
+~^åhïIGž©9ÚøH°7ªÿufþ°z CW' UO¬~¬NC’Ð2¼y+Õ;«s+°k¨Ykq w' ‘DáJZ1‡áªÚ︠my‡Yž…w,— (ˆ.ÄSÃéÒ͸+žvM¶Çê„@™"’wéV'H­ Dm.«‚)r¼¼7—Õ‚ªWqBÝ[ÚÕ½ ƒÕÏ ƒÕueÌL4ZRuY]Og¦n¬—Õ•ÂÞqá!/òP]£f£`$6ºŒí©åÁêê @-dö¼1üsè.*tMòðX]=J=kÕ뾫«×ñi€×W—Õ51‚
+œrtYÝ›¼ƒÕÿ:ž_Œ„,¼†a*µŸJö{Å4¥¹¶8^#ø®v VÃ*^}Š"$ Ð4Å;$—BÓM‚„Z‚_ Ñ´ãHqLMn^çĬ=¡Ê&ˆCó@÷$ÔÅBxhFj`žõ|öÃ< ühTµ|+ 2iå!&з _Aè®É?yù›b:> ‰j–AZbþËz;!táïi[`é¤4ÐafXÅüºXvz¢Nä7pš•ž¬‚æ¬Da+ê  î‘qt”‡ZýgÅþQù֢ؽ]h|Œ†õ—FˆKǼýùQÅè Y÷11˜k\Ó wÊYÙ¦}
+=gÖq¹>l€YdRÌ›ZļQè:‡{àa”,™Dx9EÆ'­Z! ÐDõ§Ô²šÃ Öh¦*Yá ³Áõ9ãRÚ~ó7íôê°o ¹ûÛÑЧ¿iÙÁ‡Úµ3ùþvÞó7úP)–eßß¡˜Ü˜“^·¡æsƈ¼ÍÂë NF{­^ì›A:@¨ {ýÀܘ¦gƒÖÛ.s…¤Æö·¤ÍAûOØ!EnÖÒñào^Ð m|ÙøV³Ãûyƒ·:ãŠÐAä
+ k'Æä\ Ñj²ÏôŠÁ²¨óÇ\Á¢£¬Øf¨m>åŠòJÚ9H‰ç\!ð@"Ìؽ¤HÄ»2®óœd„à[†á‹ ã*&n¶¥}TW3$ÿ^tèŸ á/í+Cöv
++n3øU礤¿$y®pß°ˆš”ÎæÛ}ñèCHΞ:)¢é žv¾ÍHQàK¸Ø7ÂC~±n¹ŸIð7\úùVäŠæ㦸7zŠ®÷"‹î…¿ˆê4%%WIJ÷øËbAgB´¨§ã-0
+ÅûÈŸLÀC°èZå´xkÇÜ”cr¥‚Ã=™˜7±5>€üA8z|x%¬ô1RŠ‡’5ôÀõä÷мv*Z%ëÉÜ8ä|V€
+´mB¤>·ÖíÐQžŽˆçU°²T)‘²?&X·aÑ1]¦mÓiqÅÔ?+Òš*þ¡Éô(¼‹ïïD¯:êSwBòxü@–Ipo¡xríù!
+ŠçdªS—<²ïeÇ(¨±rr¿h‡ïÖ°lE—ËZ· ð8¦é´Ë¿ò¡y yV,€œ¦¥Â*ÎqH:³“*=ÖÄ ïÅ-wÄO­… êb?–ðYˆ‘Nãóúû¨ÿ_¯ï,Xxdè½u®¸tÀŽë°0HQz-÷LåP´J:vˆµƒ®6“¸*Èô6/ÀWüo9“C!SA“:»:D÷0zzéEXÿÚeãØ‘UËÚT^ìV
+u(êi»È>Jφcêôau$ ˜ô)Û…aMÌ8™ùþÇú‡ê‹lyï!É«j}¢4k |hL|‚àÿCù;å2ú,;!óÛã«þu|€ÄAsëh›†4€ï¶}¥"kíJz;<6Dòg_QE%ršä¯´Yº ,5 Šï÷¤:þ—¶Ô}e²$I{W•]/Ëœˆªxi£Ë"<óÀôà¸pýñüú’ɬînŽäJ Ã[XIaîX€:œZ|*ÖØÇ}îr¦3—Õ¯¢( ÓwÚáÜ<B©8燒5Îyì£nEÇ@ÉpvêööÙ%ânJk’ Ì“ù Þ È:¾£ìðD®™Nèï­p;ÿ€>[Ù‚|Šg›çXzæ„C ÍJøÞ'± nÆ–X¹HH«íTòÄO?Šþ>u¹˜¾-gdüt(Â^“<¹"Òᤊ×Ì-Š"ÌI%9ÔJ&
+Õ*‚ˆ0˾¸gÅÖÑ=ž
+Õdš¢¤— ÔÕ†ë†Å»ÜžEŠ*AMG}ͧ
+ÆpÌY‘éc•àáa×úñF+55x‚X\IðÈ<}…IËønŒ!þ"VìrY½Nl$ìÁåÒ܈·é²m[´¡·5±êãé;›ðH·_÷Ëä—@še^çãÞdÀ!0ÚÊù3åE
+&€…¿Š0’ôj7ˆgãÊŒ¬s.'±ÝìFNVRð…›rÜœ ‡QsÎc÷_PBE¢-H
+íBõÊRV‚‚2®!yp "¦Œ*ŠÞÃKѱ?e¾=`k•Ÿ:}-ºóן°·‘|A<áöMúi6·Èt’óȤc‘ü½hÊ›sŒ OúX%D=ý!ǹĭÈ”¾|%±ȆK¥•³¢\&&K›ºRê:
+ɧáÙŠÈF2b£>VI á´± [3èÖôãV‚¶Ê†£¸ÑJ².“Œܧ•–
+â²C³£ÇÍ2ê/+ª¤WØDÁÈŠª®Çô³:a„ÀXËôgÁÃÌ'É+zÉ$UœTäSUÿhþÍNwò¢o¨}ZŽ*„—l „ߪ˜N“Y%XþŒ(ØK;–\RÔç_ç¢,{‚˜A}þð[ÜÒ䳪è¤Øag†´ð»±F°b“ØŒ\½9XnEÆn¢Ã| †Ø!li{æ²"y¤Ò²ÕÈifv›üà#/Ü…Ô4ü3±ccÙS eû¸O3ÍòƒAZa õ{ä?p¡"L. t¹ä÷ÈaØ$cJQdé0ñ#wäÊ‘qˆ¿‡_x%(óp´ã‘Ôj¿*É
+,œ¼‡Þ´gƒt’›u6E`Ø?N»ýà:^W»v,¹ìð§­:JŠ$%´¡n'r,ñ¶é‡<0j ,®Ó(ÁÝ€•8Ü©ª5$ù½iÒm°|#$C–2\¬½<ÓS´¤ÀRV„±–¿C“c¶Ï°hCŒ÷wPò’°´Z v`µT%ë¨=¹¥6Ê©h•Iȧ‰7¥óm(AGJí'òôªBPÊ$´Ž¯JçæPBÀU\©3;|(ùuPû¤kMÆb¡¶/;sº žPÀ“£´Ã£ŒµeÓÁ_tçtmÎb¯NKÙ`œ†?êG‹UÒ´&•þ&ÃñeT·GÅ‘Ÿ¿ó8§ÛüÄßùQw_{sX…k‡³Q¾wò*-NX<[ôjå„7ükEØW¾3SOùP´J:¿¶hò9ER"–Ç/4gä©ä0 „†T»žž^øÊ{€_=æ_2½Áh/fWþáÎ8ÅÚü;äÒ"'P«—`Û£„±Z­£Íb²âBƒ.p›ì¨Ñä¥èË‹˜ ±5àgv¯À^&± Íå'2íÛZ^_ŽÀÃöˆ/!È›L'‘§)—˜Þ/GSHßS¯8B¡¢TorkƒÝªé ÓÂ=Ø`ùãe’$×­CÑh¹ûf,kšJûŸú\L)óñÉùýa•P|$€Ûy“/ó|)YŸÂ}†¬“ÙÌ›sd–Œ¯µy¶L<‚Uî2$þny¾"Ö ³ì/2 ÚÓçtbôx‹ø!úKUé`B ¬„»0¸‰PóX2þ‘¦
+·’·bá6ù-{‡­A_ø‚ŸzWl¸AËG9WgÑir«7¶€"TRÒ=9‡U b9Áú…A[€ÃÝJx#T5$•æK14“¯K?÷wÂ
+&Nø—ˆŒ%fIRµc7LF ušFwYƒ>òMÉËŠ~ÿv*:ì:äˆ|Ó°OkNà»|죢7B8#ë­èKäòøW¥üMdñàå²¹þO½øe5 Rl¹~Ò*`4ÄD–·W]§J Rΰ%*¨8©i`L&s[1X ñœ®MØv™<ëʪ*‰ìbûô¸(ùÆ•n(QØàYÛD%Â!¨Ê Éü{nlã5j¾Î5DE€Àÿ³“X“Kׄá~…|¬ÐñXü€kš·¦ô&Ë
+¦Á³w4øtêv?BÇ)‚ï¼Ú¼LI]¯)»ëŠ8Š˜Ì Z Åh\77 ¤éª$ÐÕ¨-¤iΨЃ2SŽ,„Í‚<DïEZ±ú†‰ìSŸŒ1ú9Ø.p]sp“üí+r×V÷H =3À†?φMÝä-ɶ÷9áÊZ¼ŠŸÈZ‰%d4$e«`rEê’ÂÚv*ð“"ê£nêæ+]–Øø—
+N„ˤ2\Õñ…Yö7§Úírl§Sx?ìAZ±°KxB„O»?› ªðÄ}‰×Àê²;CÌý­˜Õ^í 7eëÈÄtð¢ÚÆM ¶€FÐ0Ÿí»½X»qF>ŠébSp¥•_V‚ÑdÍSÕèu¾æ0zIûS=BþSÇxÚ" ³%Ã'D¼É„÷(${n'§?žqô"H¬d"«WòIµlÓ»ø‹ý,û6IR-JŽÉJ@PAañûUXñÉ Ø'ûRdsº(?]%
+¼§­MîÛ²‘ѯÂàr6^f& QW¶©BŸ
+×D'{C± ,'xÝ·a_¥¾yåW[b¾Íšcì¼5EFŒIâKÊMÉ2ßœ’Óø †÷"¢b›´üÑÎð5‹}ú»e£¢XuØ±Ì v7C@[øbüíù% {°æysª4‘ûŽ·îÖ?ø&«Áaz‰FÉ.Â~Ñ7¢´å¨húf6¶h‰x†Ù|R8tYŒÎÅZƒC¶MGæqé’Áèt BºË†]!
+a
+ûhÎ×#26˜®­w-0úQö•'ëxaRÛŠˆ
+Yž“ÅÞŸº‘Oå–P‡ìçÀç
+ªSãJ&jˆk‚¯@4ç¡ä‡5ZBë°u²çsVÊ­ñ®cX%A~„ên†NEpC’ÆÝn=æc¸î)Zn^P Ïôý] µÃ¶·3vÅH˜Oøêw|*o ªå»æ©h• k¼•ÛÔ Ð°‰Ç°p ó­û5‚®—°íÒ–bÚŸ‚aCÉËtºØ°(2UyÁJf’ëaƒ¹éÍÈ7%/KúýÛ©è°í²Öˆ¡ä9OkNð»|죢7J8cë­èË襂(‡$S«—ÜfPûå,Ýa9˜n³„eÃ( d3¢mšÅJ=È /ËaQ2Ä][­$Ëå‡l°ü!UŠ-oP„ I ïç `iþ)ü!û ‘ÆbìsQ V]+üCÜ‹€†Ä…|sJ–''s†–ï®"ÃÃ1Cy’&Õ³RçmkØo „Ó»_J^基`ËÚ×bæétÔN—×óÍ«’øCþô?ÆË%½’[‡Á+è=xçÓû1v†ÙE¦öþ§ù!Q•ö½™t7ŽJ"A
+Z_#'-FJƒ 8‰FS7
+¹ç8#a¸0=Ì~™ÙôˆÜè2—žÚ¥tŠÉ!u¥?´ «[3fÐb$e'ûn—áÏ\7Ùm–ZF¢ñrëɧ° #óåùò…þO
+¾…>–WY"1$ÐB/‹âÄ]Gè1Q… AÁ³+ô±²‡¨ŠJ ¾Ð¡Ëü‘R=j" R¾3ñÃâŸÓ^‰}†þw$ÖUh ¹ã©Y?íÄfÇCcÃWz |šTê«—Û0™dÎÒ3Qd<½ŠÅ²vL.ãÐþ1ƒÁˆŒ.
+7O¾ ½ 0/1< ýä³lë
+£‰T_èˆÆ,¾°0>½8˜“ůFs…H…隬†+ô‚ÀrVªÙ×ù Äï8³ÇHÂ3=zÁäʼºÈ<hBÆ„ý¡WU‡6+%<NqÁº“´©öùpNy‰z$ÒVueË„fX9âAæ¯ ¿>„ºÆ3•ÁåË?¹2ÿGý^2ÿö— áÕ‚ÒÔ¬–_Æ Å¢,,»J"Ÿ.hÂÙÞ1ÚF_³
+¤Xo¡ŸØƒ” Kbd6Du%Õ“—ìz„¤BUöÖã ýaìK³íq¾¤||°Q¬OEvYz µY]wˆ#H}ÉÕ‚®h A¦³YŸ"Ô“Æ‹Ö¼á“ØvÇÚTòŽš“W2Ùá"£dpSü7l,œ]
+B¬±j'K‘rñ÷ªev×x P¸Lw€}'15ÈWâÃ!—vßor£÷¢ý‘ø^_g¾õ韟LŒ†+¬á
+pÒÂðb›åå¼O„íQl(?ì{‘i°ôØ4J[ëdhrCòó†È(CBûÂÙCŽ©=±·¯›«ådÍV-L,­O„eøÝ´¥VnBÔµï^j`òªÀé)ûÇ@w8€½Tºi—á¹.Xîg š¤ý&R-CwðW›bZÍx‰»-Í„p˜bÄð ¢ÚBB%fDhÂ(û6 :U”éGSó÷_>è[ç?\Ðä$d¿+פ¾ß5äx÷(É„»Õuï áÑÄKê3LãHîahb—<Oçã•ò¥´AHëYFqh7¢vÎDŒ¦åµVp.ú€JÌ­ü9²L=• váoíÄFç2£ÏÀ¬f³njÐc:o"pÁ#t8CUM« &=' [ú’Fñ¯@ÑaªŒÑôÆ4„:Ê›?xÀ¾R  ¡áŸŸLç^†2ADE|ð‰äøÄbb:(ô2”ê{LN%@ßãIDEˆ‚ž,ýÂK±n%—i× va_{°|TVB€ñ«Wb11°2û˜®X…=æ`5¬p@{/{W5#ÃÑqì·SCÔ+Nô«/¾S ‰ŒR£–Ї¤æM
+nwn´kíuŽÝ ~¥
+=à2\ùñØ^‹’˜]qÅÚðUfT¢~U²aï9ËÝÏô¸5Ňõ%”‘¡g³­¶(Ò󞔊Ðá÷9œÈ3ûÚVv¶’§²0Ó…Ð`ÒíÐz9I·ï¿|Ð7‘ûpAˆeMt¡g¼´¿yW&Ó_ 3–§¯¥”i€Å-iß³"ÿ·‚Ë$È$FèŸÞîmp|äÚN×D $®Løw>u=GCSAð¬cGEê
+¯ÉàÆÑ¢åˆi3ãÓ®(Ꙏ¦`Ê%PªTÇY5™<öO’[|󦯻°ˆ h[*nƒÇ#«¬OQ¸íPyá èÃF†m´ã„±¨±Êô$7:§%8jAy¦“¯<]¢á$Cb›[¿kÇPbì–@°,E,f&Ø”ä1…"·tâཙ÷P Ì:“èðpJé%ˆÿµ¶Ó„®,”©$g1 o:M dF(‹JÆþÅO®ƒåõYŒçUöJŸê\ÉLD€QÎe8A\ã˜ê脆Nµ#¦VÆ»7¸U@¨›¤„x÷áa&™ …
+_­†¬›²3¶¾õù
+®¹Žd!Œ|`—Qm`´þ@KU2Ù‡Ñ^Žõ «¯àõv§f»é»)*0 ¬ZÒö2M
+ß%ÛMTÄM‚šçK— ÌQ
+eÕò?̹Š¶šj zÙØ®ØÑŽÊ1~ˆ@²Ð‹ø×ÖG®'ºÂ`Joט/‹á.âzjz˜žrO¹Ý4¨Úø™t°¿îß°¸<-3T gfŠ-’EäK™ùo† æÔ‡hO2œ)pŒ6vÔºc•tÏýN1ŸB¬mx$“™™ªvwN[ûM®XðNÑ9Ø­Öïì8çU4 gWا`GÌ„¦g”¿R†¤õÃÇÌ.xnZ[ë]È®.ª ’ÀZ‰<¬°Ê+
+£t9Û»ì¸RŽö.€©Èyx:¸ò§EŠšÉ“\K2k ‚»îÏa{¾çßQ4rK^§Ý@!ŒIž±Ã)&¨t»fÒÄt>è%<“æ³GIEÄ•Ìê0@wáÎù1ÊÂMjp?ä©IW’/AN·ƒHµk¥’š7c¼ñ»|ì­ Iðgë%è÷–—ähi‚–K/¿Àm¶ºTÖD*Ëz¬"
+mú„Ù¡%Ú‡éRåMÇå0ËÏX\vÿA[ôa0K†ód2Y{àn KWÓ‚ò!Fø\õvÐ܈%Úè¼ëë&ˆÙÄRÂZöµÉÌÃ-R‡5UÅÍ-QõS{€§™qBþìÆ`Ïb¯‰Œf¼;¹Òª‡öÙˆÁûò\
+—»šbóXx
+!-`;!¥HåÔÑwá ª‚#Þ,HÛéÅFÛç”&ÖcO9äûÌS
+a¡Ãä6yX!~jae]½wÿ˜„v€Ìj‘jCÔ¸Y f±¤'¡9}Ø6DE àéÕæÌ ÂF¸}ÒšbÈq BL9‚¿bEÛsÏ®“'wδšáMCo
+ËŸL;$w,4bÆÉB´ü° JËyº>Ìp‚2ÅLaJ¶é¡˜ÒÎ CÆ°ÚêÊ5hÌ¡KqBùØlÓè×+fÑ„å>è»›S^ÊíÝä¥m¼]Úïš™K_óë ÃSþ¼31®p†‹*ÉúAç¼o7¨#V­j3î{eˆ#Ïë©F®@#¦I ò!­J*`t–;Ô¡=n–^Ê‚;‰ÆÄ~¡½£ÙŒÂøÜ}8ŽM&iÊ3~/… ±c¢YÀ³›cèez”â#üÃ$ªµ»üÙçÊÓÞô‚Šîô¸¿”áØG,7Y;YIu¦å…™GQ¬YÐv Qni†å7 éHm…X¥hJv6Tt˜Ò;AO•ÿrƒØsK–éJ¦ûþXL,­™î̶0Ø7k-÷¶§#×8cÃ"Kêˆ/âI2:ƒ!bÍüé<Õ+yìsh‡H²Å¥–«V^ᇶèk×Á?»L©Ó5ŠÕsZ:ŠlѨžyû‰ˆµJ…àªN®›
+¥,S[}Ió
+zÑ4‚X—Ò ´›s2ì‰È°Gô`M&¿
+‘.B‡wH©"3Å#jð,ŠÅ†;7Dúx)““U½'‘oh5ä}ŽF\©áˆ—Á Þ’¦B7ÓF…h¸î‚:AOFöåaˆüAX /õïʵ«
+``ï<]?µÛŸ©Œxžþ”Âeór]Ö‚4fú¸…ׂºÌ¡ÆÀGþ˜BõÏÑØÀå‘koLä6 pÕΉ*X›j"U¼i!É •Ü´hmJ»ÓëšÏTLø æÓ°?¼¡éë6…qHqëÅeøЫ*ÂÑÆÓöîpã— / ¢ 0-1¯áoeÛK‚Žóô¶ñ–ÃROíi%ƒ-åieüM2Þ ^ çå%
+¤›`ƒŽ £UôN>ØöDý×r^wb¨””1¸;S*ÚaÂ<»ƒÃå
+‹&/BøX Ä¿I8sAûC棻CpS@Ÿv
+31šº, a1`-RË8všAu|¼Ù’åΡW4,·V?T\½No Þ2ò º'?þÞ%<–+Ž<“oÚÔƒSãùXyŠ’špqì$À ¯•ûmÚE]î7¶Æwf²wí–Í&•›Úoú±B0ð‰ÄgÑLÍUj‘Ð膌|YÿÐ7«;¼ DÞ@_ЙUùkÐ¥וù9¬ œD‚Êæµ/í§Sç““ kšG¢‰
+µ3/K*äÖ,É(¼†ºñìKå=ϦǴâ2 µeÿ:žÿW7÷q<›š£ÌȾMú”Íò^Ã…_´.dÓž>׬Ú<Õì­ª•eŠÕΩùãu„…râáSt{B
+j‘BRá¬lz0Zo^TÄ<gIÚ7.O˜\ÌŽÀræÎqä«¢(æ<{ ¼
+Tó×!\’óoÒ
+åբĆq¤•´D¶`<ÓXç©XÌÜ–_k2‘¤· !³ú(ä3¦Â‰buÑ[-+bj"
+¶Â-ämŒŽ0˜Cш²ó`§-"côtû‘X<GU0_ˆìŠ:$p™ày9DU‰LIbòå¯IÙ4ù.2)ž;··ÝT<êçd~ªè è7nßœSPŸ*ÿ/×ÛSÆE×Þ™Ú‚ð“Q)¹mKA‡K3GÕõ¥¬m•$§]ᮄQà*F÷š
+ðŸ¯~˜É®ïGñVþô®½Îæ׳‘mÝZÛ”G8¶§8 ÏyɹQ‹~R56ƒ€±¨!›Ÿ´ªÔÓE"'l¬—ëSðÀ’Îçb—xL‹ÏÛTæ€xT^ÑÔݼïÏ?¢ù Ð%
+pK?ÒŒ‰¿MÅ^OïESI#úö€J½ #·m%UŠ ’*SLÂJ¹ê&ã>æ§Çµ¯&¥l—¦E{í³ŸŸˆÍ5²2ðÃãS M‚ÛÒÉÓ×6&ñ±Š*²–rœú'LÖP’ý%æŒÑ€ÇúìÊ0…2Œ´%€Ÿ0ÓÊš{{¤ FUf­"¢÷Y<ÖP¨”V/ #@JB¶ú
+Al$NSh7f½_…Æ^]1Î-ÜHôp~ŸhÒ•¾YHT?Çî ꥟€ÿ¹Ü›ÛÝÛæ ˯¿ø`#6¢f•ºú³¥¿¡Î¨A¨1UÛÉ¿ž‰¸ „ë“f”ŠÜµÑ½¥Åd@4”d‹©¤3¡EC˹y&sAÉ0W î
+H‰Œ—Mr\9„Oà;Ô¦‚ €µ{©[tĬäûoç Ê¡z¯&Ôîp¸¤,’
+¶]Œ ÄžæÅzü7dlvÜ€F+pƒ'šdå/ +yòŒ4¨ŽMEÊ*N }’ž|²5΀*Á–]6º[•©sG~aô|N#èÖ´Ï™IÒZ™“(|C¤pȤðè¶ò/Ã1…dZÝŸãOåmDXË×k¨¹{­mì×P™1Z%òáùŸ³Bቶ®Rj¬>h¶®‡Î¤B¹G] Tfq÷n.š­sR³r µRß©Ãv¥úPêIÑi¸UÎ Dj<¹¶ ÒÇmŽ¢uˆžŸÙ”Í‹ ÈŸÍ¥£ÚJ“l‰é
+U@ße`ÒŠ0)y»‚>Rº]áþ¤™ÏŒy[Z½cÔϘ¿Þ€Gš51 ~ «v–„ÛP¼F¢k¢Ò êÁ/ßØŽ” Æêî5@®UªÔóœç9îå9H4ÇÛ´ ñ¶ÊH¿-KÑ¢?iò:Ú¶Ißë¢F‹
+ªÈOÚ|s
+Õ«®~ÿ ­ãÂú»Zt#
+I?x»O N› D˜õ>¿7ou:W½‚kA´±ûׄcë\ÒÜDÕftœÑmž«.Ùá÷t
+S¿õ¼ê’b*âaV­ŸÀ/•úIN\
+þzÎ m^_sC¿kTWãpùCÇï[atò¡–þñ­R¿¿Ãéaä®ÓÿdAiôÂ0v×é7 {ñy¹îúüÉ›R3*,~FÑÞ=½<MbØùrJ÷/ÿŽ¹é—Ë. ÏŸ¼h?\–kfaúwOÁ§—=˜Eî‡_Ax<¡¥Jc[ZÓˆàŽ×ÉÈ¿]|€ðÀõ(&óM¾ÿÝWV²³¤.aðô#Š0K Í)á¦Oß7LNôµ{B0 ðœ-¬%ápȘšnq›[@ìƒájóc§Ñ˜<ø#[ÝÇ„{B¶ÜZ"&Ô¶J\õÜD÷Ć‘ ÁâÃÍ|}ï*Øè˜Q¤‡¦È‚Ym‹-‘]às?Çb+ÁVéys£bXÄu-†[j‡ˆl²Ùõì(Å4°mDÇÖÎíòWö®‹ÄqÑ߸ùd2² 2V¦0Ø÷)¬
+8 IÜÅŒ5Š‡€|
+Þ³VEv1-ˆ Œ²UŽýýëD~eyKvâ~…'bŠȨX51 ‚\ÛJS2»NîYñm0ìplC4ÆITîü[q]=°4‘*ÒÝ&ˆõŒ‹ïwÊÎT‚DÁ#ᑺÔ쥚1* 9ýú7^`¢0Rµm'/:¡køÝÐè¡2Îö€,Ï :áÈ›××]ÎBYA4+Nk¯Õ¢!`Ã[KØáì*…3±ÐÊq‘,¥t, ê»dÅà ²X¿…¼hÅ–q·ÑƒüŒ,(Äf2‘¶¹%åÕ„\/b`‘åtÉ5a¢cá´ AôH“Oó K¬«½F­ài64ºÈÜmŒsV7g¨×uΠ-xKRv`œG«ñ ¶Àa°á í>G¨X=.
+…=7EA•,'ßCÑŒÆ<\üêè[ìWˆW¦Òp a—µ ‚P,ÎdŒó½l>+8T/ Úùša÷±Å}f)SšÀ61:/&§Àeo•î±„•„tv-:„$ž&fú;U®ç*^ϲ…pÖ¾Å`]K;¨ù‚Ðj zMñG¿é*B’ÍãȤÚ¢pr®º€(. ‚ZfT»b!"º!˜O."IJ!suxG®r„ÄŠRèÓv®2¦JH{݃vBw†®µ,9õàWÎ+†Åa±¹!0;Ì–´ß@ÿ(LŒô­ë×cb1a"YxÎ| ŒŒ•‰áÚ_8ëÅFCÃÉŒ ]CǼ‹ŸÜ„b²Ö×<†T [-«™a†YF½ª¾(‘ê£*sly 3¹l5ÏÐçÒŠ‡G}gÏȹI´EŸŠMB—=Œèq¦Ê^Ò(s1:šŒÒm'ÇT¿G§‡Ç~tfa¿d3¹©<Í92;“ô–*9^/ÕüŽÈ‹P,!nö+ǯ§4ÆN!µÌ_h\L‚çGévDð¬†@ñäCP؈װP‹ÌLsÄXb‚f/,bi™ôÒpýü5ÆÆ=" ;zázµw@”/ô;  B+’
+êÝ[N|±60È¿ô cùŠ½cë _pç êkm‰übÙ`+ûFªVÒ[ˆ_íB$œy–b  ùìøM=­@5ð0qÛH%µðŽ–äÕè@ «“R<aj‰ígœ¦›!ËsRó*ÛÒ §L¾ºŽ·ÖØ0-õÚ}Ä@FF7%h)³Ó—õÌÖ}3 ÇüB[¸9òsÕ„åŸ1}cãÚçÄ$CH†çºÂ
+ÊRVàº@>m"€€¦°Uõõ;¤Xþ•8XPu¿ _$žò+#?j:§Æš—×;Þ¹0"ņ¶¼}ßlˆ<a>  tlH,î`ÿ€ŸÂ€Ähœp’qÀº{VØyâI²¹x›^`;D½Däÿ‡˜Ëâ}ýd;?´Äoÿ×çÎ2*ªvw(ã1MŠ5I'|AJ:ÂVWƒ¶ˆx®Å0ËA©¤é ™Nþ•IcPEfQ
+­†?;„b—‚ÀùþLdNƒ“‡€2pQã÷ª>9z™u„1ÓlçX@3‰(ŽSœãø‘K»¯7¹ŒÍéE—ñ»Væ2Ä×ú–á©OŸ?Ù-W°åÂv2aø|X;|ïûb0ñ7±Êª-Ý.r¸¡Q—ðRÂ,KCê%ØÕåáª4¶ü©µ»Hiµ֖ŽZ „ˆå,Ðü£N^ú~P[ ز¸štÙ,©¿µá1qƒl«;¬Ê¼”Ýy) -ƒwX€O[4ª1gq”]"¡. 1ì;{®•=ªª-CˆR6¿ ·ÀÛçbþŠ£‘R& öò-~Å<õýë„Áãò¬šˆ¼ÛI°KÇeÖ¾mZ×’d,—öwÑÛÈ¡¸ ?A.(¶ùx·Ä
+^®0…s¨Ñh±”AmÙ^¸sò2”¸p9Ô˱Bwn®m'1èøWÜÈdpÜÃ&+ WÓvù²eÜÜKŒ@#Ò?ÊÛyíø
+«@X1œ%ÃR Ò ?PJ¡Žá³ú¦–幫ÃÛNž@WI3¨dÊ0ÄäßáM"¶«d&x¼äŽc2Q(©íý„ðƒˆ\-â[¿ùH†[Ø!´ÝÝ„ª‹Pz¹Od½ñ¬W¿« ÷ÈJµ”»ê^ O]ÚG½‚Š”²¥Zà‡·ómd+³2 íåM‰¹ƒè2“ÓöA—Êðçbï”Röƒ^«ËrM’ÀýêKž ~Ò¥Õ×ï\æz™Ëàuà¼\1$¢¨x^h­Q„láŸÛôë±täÚ$?¿¹âÉûÒ%FiH$û]Œzœðõ¸£§þçœ/ÒéQÎiÖŠa…È5xÌP´«_@§[ex†DMèÏAø§È5ÙÑJzú8žöÌä0¥JÔ¯w¨PÇ(d& Q^&+1J”ƒy*ÁÕmTÂRÇŠ™Ã
+È;X‰ä¡ZÞL°´ÙŸ ëJš½ÊŒò¥ïòX7†Æ¸vlŠ>,a°N l*7°I²}>H¼§(ßí£èh3äcøÐ} ONÑtaß±#¼a?*ÂÙå¹™U?mXC¤±ü=+_ï&ðï“,7ÖбŠ¬%B²áê
+\nHZý¨Ü9“vê‰ÉWS×Q(FüÍÒ…ëýa5H…•+ÔTª—:
+1ŠvqÏã¯qGâ!w.Í‘–£Äeë{‰äÕ¢^ß@V8K䱺€ ù9Ô9Wx
+“ 8'†þØŠ–˜ŸyÐKLe¢unžË©ŠôB48Ȧ\ •—
+hbrøJ"ûa%Ëo£Ê@àqÑW&òú¯á/*œŒÛ€ãÆce²¦ºéá^>Àûä7|¸ˆsšFÇ+SÃÄÙ S¼ýÂ~ÃL(*š¼:®•aršY­èëÄÍ™ÙùSRÖ«º—˜õ $¬@póa—ʼnêµW×â³NÚ¢ÌÑÌfH¦h¦èiŸÄžÁ©Œæ>´Þ•¨ÆØË‘°0É–c„ËË»M9™‡ÈÐ@ƒ¶UX¨Žö27»W˜ ä[ôYÂÓ–ÞÇp’ÔWÔ©–|€ì…=¸“?Žß¯Ã¸â™¶kr] ÷D ‚ˆåħàG .ˆùª^G9§¤¦T¯€Èp»à'ÑÂjýz£"·èÈë–·Òœ¶?Òeb …!jlªxA0¬Ç#ϳoxY b*ñM ªËÖµ¯,ºA’²Wƒ¦A"Š^Q@l@s±®ª(œÌrM»Ï tÉ&ÿRáåR!»w˜«hš0>¾¤ø”Nr ì&Ö€:ª¶Å¶×+®tÔhI[ÓÁ.agRáïx°*]+s¤Šôøÿ ŸvTTaùC.~þ{"¿Íˆ…âXV”R 1˜&-1Lí]¥Sx‚$U5:x
+´@d%"Ù,bà tŒ:n…ÉüXå#æùÞ<±Q1°ì?¨\“ÛSûóçÆ/;Á/Åní¼Í4ƒŸ(rüÍ6«©Ý\>ãö;2Ñ’A6›eAko§ýˆSYÒ>êïsøG¨* ªÌÞAâÖÄfé4‰ ô¸'öEÀ2ö£#É°kÚÍ#F!Æ' ‚!' âQ§kA.CZ0ºè÷ÓN¢eè¸Ëoƒ¨ã6!ÿdíÈÌ´|,˳/<Øø¤®Éçd0PÅlO+ˆ‡tõËýNoæmYž@7 %̘*ÔÑFLÖø@PÆöt±@h9m½½Ðzi2öd{š®¦uiD2’ƒ Œˆ^=°ë§Ä÷X–¶I@w8¶ªÛöh⨳ÖcŸþÑíß¹CH|7#…Éh÷íƒARSˆ Ü'ïí¦:ü+rJ˜mÒB^Þ±­ðÏÿñ2IŽ#‡¡è t@ÁœÖÚö-¼•ï¿í÷I°ÔUÉTËŽèA†I&ðñ‡ì¤À€ñ² ªut¢
+š¼
+@Ý;“‡`È¢ñèúñ1¯h¾|Ó ò0'ÛÅE&m6.u.tG„)ý²è˜¼tV—×èÂEÐ
+\nµîÿùÙ[Ýààßt6?Z–†ØuG¦×¢¦EëGQÚûa¨5ÄZè|È`ä)·?z5?Q¾ž†™…Ý«û¨]N§³åÛþà[Û¯T±Îé!ý¸„þ°?Ub?$ïÇ¥Û‰R>nuÿq±¾S`*¤^‚D«üq»ÙÁkÑøàªV¢²i›h,Ð&f‹m›pü~Vú‚t‘€óqF¥—µ§8WžTMÀG„Ò",ÂCÞpZVžWU¬U¤m€³+¡¤êØò»I¤(¶‹·dÙ¸ã9ÒÆ
+ÓÆÚ7ýÒ Œ{¥ßüD “TŠ¬SÀ·cÇ>ßÎEOœøu,BßeyX%éùºŒ0”yôÒwè
+6Ö1¶ +m&ÛÙÝ®ÕÈ5¨ ç­ë
+•8]!i_õójN…$ÒBXÏZ.„åO² õ[ üZs²< lXL[]FRs²kž/ûE vKaŽOdï]j®5 ã’µŽ`÷}Uà­r”§Ù³ÀJ&¹œÅ L&›óÙ1© +$³îQ€’DXž²ƒ»ÝÄ ü^§PNízŒ—À/Y¸ f«ÄÈ6á¥íºŸJü*DO=©éîEJ
+ŒrÞ¸`¥H£´¦ç›’'„~¾ŠH(å@øùòp· —šÓæ].ûUÑ ë¥fÑJdÝ Ë¬íÑ’A¡"¡ÕÉ+§"Æj³ûÜû,Aܹ
+˜gC(_ ®
+&XwŒSSÐ%Ð̹RDâjYEø
+®#(],Âd{cÚf•ð“"¨åº!^Š*ÒZvÑì,b'€'ñ†t¹ÎɵˆÏ!¿
+ýç>\¶w–¤Ø0éD?Īœ*ÇÄÜ÷Mò–¸tz³=· èËŠ@âªõΘ"÷r¨9šn-Åà%2•CCü11FÖMZíR¬"Ü2+w7Ëä1\XVÖ1x›¢<hÑÝ2"Wµüø‚~SR™vêdÓàŒz*b@ú¡6úU¼–ãÒ¶‚6¸¨²_ÓÑH’ƒ!ÇÒÞ»xßÝ›¥Ý?ÅR-Îè^T-ø )É'^9— ‘Â8yÁ‰›
+l×q^S¨`¡I؇aÇSðÍüdÎÎÅ1Y”)u-ŒxBé ÎÙi¬0{Ÿì›Q3@‰Åo‚ q^
+~ì ÛA ÍKWEåf7%h!ó›õÇ6\ŠPX
+Šî)ú9 ¥VvŠ;ɱbQÔ_|ïJW÷’vÜe·‰4àý{0$èbˈ™NnxÞ18%këñ ¾F©ÇI‰Iô¸Yz*¬ù)@œsx†Ú“Œ«ä 8Ò\.Âós¯P<¢gr¾Îxþ0‘t2’$ÓO!]Ya!ÛòX<´ƒ_!ï'¬…ü.È|«öHâ¦TáK "Ös…‘t2´Á1c_ôZÓMXLÊW~
+“Å)¡¸©Š©:Ç(f÷R˜ùµàFp©Ë å$Íbá±O¨^’r/¤x†·d(¾+Oªz0fZ'Îc/Ò1Ÿm<€+0Î)ç'ª†.ÉSPoa[‚lWuŒko©› ©0&þNÞŒ/qaìpqöS­²qŒ¥-'~NÔ²“ësp8•Ï’UX¸95òÞfp2aQÚsÍ×®A×àÆÜþÐMp)¡îòèIî§u?ióyxg ëËÝ!‰¡\žiw¸DÉ_«{Ü´Žub9±7¾qà6nzö”Ì:Ïò©Â1ƒTL©¥¦»cLî{„¿Ø)%÷ik1.N÷Pć*Õ›ì5½a’ Ợ/‚Ú¦ù´ø~v˜ÐN¬„ Ç]É“Sý\†¥EW1ËüE÷Æ<Ï„?çÿ½)ªX«º
+å¤àïZW ïgÜq[ÜG !EzÈž¯>†’ÆC]ëã1Øb‰¢­§†H4 ùý—ñrIÎä¸ð æ³Ö‚QïÇÒ1Zrë8¼2½ôýý%€fˆWk
+‡)*ÙU$™ñŽ·@[¦[—þ¶ Âù‰ 2†k¹b}EÄ9hJ&6Ùž¾‚£ÜRŸþtfþ+›öçѼV±R=T†zómæeŽ§úÞ _úGÝ@È)!m‡Û°U´{fÇ…<¼
+‘¥%°™¼ŽºU‡ÿÎB@P˜ÀŸçcmwfû°9æC§¾@â¨×~ß?s#Íý27òu#qŸdöõ,.'‡QÐv²xYŸ_:õ9x“ ±•Ôb•a °‰MÀ–¹£1üMG•×ô~
+uÐHƒÐ,ü¡Hªg¬ÒV6åÛ˜ã#„¸ÒhÒZ•Ú×Q7PfŽð°½Æwx Ñh—!óÉV“+’³ýÝò· ΀8$ÉâçÈvq+ÏŒÝàšjgéšb°’IV²£»tBå©h1¶«;£›Å†Ùnë
+é$ ƒ£”˜‹Ÿ„%¤K yUö0ÐVÒDçÕßÕ¤ƒæT/Ná_´}Qé*Ž=ÅÈÈ0§6Ì}¶).)n6ê>£Uä¢*þuûÂ=š ‘#× ­)Fï'„Æ¡gòÂðÿŠé¥ ð„åz}AÄì?K“-—®ç~°r庂}•ñ@8ÞG\Û–‘Æ 9DGµw˜´Ïn‚‡nÐ%ªƒ/Jƒ@Ô᳂˜€;`Ô€L 4) Ä™I4Í
+›wHÌø®
+äªÑÎß1Ÿ1±±\—ÁïmæY‘#X,Š³Øºs‚FAjKtèïuRÍ’)Ñs^‹ÝK¥öïʇUI9Ú‰‰#öÁ­4 JS:¶U-×Q/ Ãl & ®úw>V°^éuŠŒ™åì ÀÊAŒÓ„:Žh³bÁå:AïY -ÛAÈْ٘.&”cŠBq¥ìÒÆ¿v&ÑÞóØKfˆ€ÙBö‘»Êð´¢Ñ
+­%¡û …‹¹ãv«“­c”QÐÓ½—
+¥¨*0f"$=“ðÔƒ9'Ùpà²+ÚØE9ͺ߆J«,ANñžupB°45CA°´ëœ¯˜ú&"…Õýº{JÑ0l&k@ÀV©hÍ"„Fƒ×ìE!Ìz0S¶çU¼Í7V/LÔrÐ$|ò;–>Øg—ÎÓnz¹›¶
+‹bžð¡ŸãŽ¸ ÂÅôy›—¯`\Yl¥/vu„LŒ‘ݾ\6Õ}w‡Ð l½Æ¿·k¹d6grã¤
+ð°Ô«'ëÄ`OyÍéÕÓZãð„l‡ÐW¹ ºòrˆRÆI¦+_+“’³Z—JйËQ¤+3mTÚ\ÓûÝ´öé/­šGHfVó4±˜¹»³Lø øÈ+òôqqXlxŒUï±W¥©­±h›#&n »Ã”‡
+ªiÖ™­êç°0·¯5rD”&-3FÞ2(ÅŠç´a©'òÑrcN.ˆ#úgñ5Âüúq
+÷ÇåáytÒÙÛçŽgS•… Wßþr1dz¶Tקl9.10ǦAÍV†!ö
+# -&­Q€ðɱ0ûçü~UâH=kMt-†Èy­Xë©ë2mÂÖ¡ÍäL?âÓéªj´„t$_/"yÂRÈå@4¢vhR´}Øc¿ËÓÚÉ(õRqÊøy&i±‹áFÞ®“þ~*ÝÒ•úÖ{QP¦KŒI±hŠëûN6aˆÀrÏêçÚ±,ÕÔQv¾“”©Ué½ëNA%“Œ»»ø<psÅ-kE‘…f‚Ù­‘d£ÐqÒI3¶ç·ª|ÆòOû8w ÀäÕ{Àÿóôf‰í’MíºËׯäùE=R=êHžo,Qª Ò>˘šy•ö5»_E-k“±Úø¡Õk|e/&ê£z‚ÐK†édZøʯHAñCÚüÓæ÷‚\|GìrE~e«Öé Š&ÅV]8žëåÛò‰bcP« _ñV_V*àB Öbjmb‡VP2J"Ò¨ ²ªPr—óøÒKv>“‰”ž Æѵ©ì<¦À4¶1<ú
+6(cUJw{95ýÐ
+çáO¢ *ž6ASK²2Ÿ¶NóÏæ„)æ
+}F$ÀÅ^Of=2ëÜ>H§Üs¢šŸ‘ô ž…/—ǧKò3M=SµFye‹^W“Jíèw´ÖºãH]Ä*0Ú“3k(?˜¡™yîÈQtîF7i‰¸Hé›þùÄ4··FNGl$ÂLF+kîb!~QÞÃò™‚^œ ÿ~ ¦ŠÎ•hØÕHFC1Ôæ¹'U‹¦Ü”åÓ ä"!qð0†þp''è|ùU}àÁÔkôƒÜ“îɼ½?Éø.Là,ŠòÎmֲ䄎Dðó*L`¸B¸‘…çéV¡¼0û…4y ¤FdhG-å9çLŠ”®Lq¾S3NÜ––Ž»0x|À’èd=î ñꤓƹü$„®2?Q‰Í’g}I˜dóó‚çûëHf‘©Â]ñ´ç )ôÃ7TÜ3n¯ Ê6NÙfºÉ /´õG&úàǯ>Ðö
+­¾ô夌…ê,ºÝ ‹OÙm‚QL…€õÀc%™ã߬,l¬¢„ ÂI\–ü,;f? \@îÒñ2\›c² êH2À$lR¬C£dÙÁ6É ðº‚U¬Ûɘ–²Pv*o!ëS5·ŽÅ½)ºçŒIëJ0¹ßÒïuAðì~Þ!ò—´ ƒõ*|„å™ k™S—ÕÒÙl,;ä
+fß9)ܪ‚å¼CÈq Á¯B% “qÉâ´ÿï_NÐ}ñy»AÔ[bÅhÀ°½ 5×~Âd›Y”ÏPÌÚhΧËr0Ä©œÍ/ÿžÁ,ˆŠ‘ ,±|YX=ºvÂâ™äª'
+H#*­  Œ@ŽÜˆ­Xx›¢ø®YÉù%®3˜ò¶ø¤’“%”’ù˜{~žÀn)¢Uö·0°Œ…©š Ë>äos®ÁÓ»¥”rTÛçŠÚ–˜Ç~7ù£°Ym½DÔ!ÖÆ0í£ì Aʱ›ô¾:‚|.²êˆ¦žšÒÿ?mXg˜¡L«VÖ­9µ±£bEûQY•–˜¶`.C“£™ˆ[aéµäЩ¹he5…&…ƒ¸y ¥˜Ä!áJNj_Î0IÁ
+n;Ñ·ý¥Ÿ¦rY1lÄ;ÀÄÕböY™Š ¥êÊ0óV Z†Z*‹kxpóYù òNê˜D"¯¸‚ÉÜ'Aþœwò‚Ž×¬|¹'Ý“é0ÒÏß…é…©F°p kß*ºÚ«ðÇ*Lg!¢wH5æ]÷èk©ã5¤ugêòÒ©md­½1=æüä%áøÜgAŒrQV Q$`ä¾Éñ–^n2A`^a¸T_Ô…¿­ö°.à„/ ¤¬3‡‡uA'U>=›ŒÐ®ùÁøIš×A‰© kßp⥩2i—§l¢º½?©ïnƒ² õ–/Ÿ¡õ€e
+×òV
+jDY*Ï9_=[LfeoÛ ÏÖDPQhÈ\´žý ºØ±´‡""Ÿ2©ï‚nžý<ïÏþ£oÏ~û'Ð-É4™}§zNz¸™|–Ò3Å~1åÅõ9INH€ÆGB?RxWwöÍþø9Ý,ùÍà½U“e¯UœxK'IM¿J‚J5úÙQ¿€~9(·<†¬s¸8mZ§
+ÂÕâúŠ"&G&ë+20 }ÚÝb*¼ùp®_þ«ç Í"›âÊh½üÜ"/13 þÈv}|§NÐxŸ1‹¤â0½…qÅÑ;üñjfvÄ,%®á¢_1¿n˜ëŃR+t©®sß]¾–ÉzË/1ÖßÅÜšòôüÐÇ7jä•ÌŸn…ÿ$÷¢å±6mœ·+yÃtEM‡Hß‚©¢ÑØ¢Vëæ2 êb™t*E +ÇJ&· fƒ“µ)çV‹Ô‹±¯Jê\ûSä@yä´*Ës ×ÆÊN©@P]ìÌÖ8,ú‰O-\HÁ´[»ŸÃ ɱÒÃdõ~ÞI nZ©ò«G•÷m¬\å^4-)U0¯6î%¾@~ïT|éƒ,ÝoIˆÛÛí28keå0 ê^Þ¤Œ¿¬“ŸØwÊùÒCi
+l·*1“cÞnB%Ä%Ì×F=@¢QäKlžûåùêÏ„Ù¦·1¶ž1s¿ÒWåª8LjTß´žiLqð~`mo·Y¨
+ø€ò°Ý!_õóÓ¯ ˜ú)7"Ež|dõ…ªû{ú’yËJëâ/ˆD*<²™Ûvzß ÖTÆfÁÍÐ9–µáÂ(_]!|?_!‡Öî jÄ)­ÖýX@
+DÃK\µZÔ‚-‡è›ä‘VSÄ92ŒOkiüùãÊïìYx)bãÛ
+ö ²w¥TùŒÍÏb^-æžÓ!¹§åY ÿrä´øÐ îK³Ìrië¼²7lŽü!ÃkVÌ¿ÝŸ¢°™1a]‹¬¦‹ð#ù³U‡ÅpÅœ/¿½ŸzqËA_ÃÈßèWQçÇÄtAXq,±Ÿ–É/T;OÂ1±HÔ¢ùJª3¸TŽêõFhb+b#~JI,@ÊB=ªgUÂÚ™Ü^¯¼¾Î¡à.ý|ê ¤s¤ãĨ8ÇÒÌÉŒf°‚oЊŸV¼IË º˜‚Zʹ䑹Ú§x”…±fwñ…ÆL=ƒføøðâi—!ÇrðºÏËŸæîçgpãRl±(¹â`u«-èviÃêQãô°—ýr„ªL1ñg^@b¿•ƒV±Ìõ¬ý€*øåÞ¸¤Ö¹†}"ð‹pÖ!"ÊÞÎR¤W$=¢ž’à<ß¡ºŒÏ8W Ã,Æx ¦ªiz:ÞR<iž||
+¦Ðú”åÔ1ÿ+*Œl#PL`0
+diHµÙ®Æ‹à·kÜNRyáˆ4kRj¿1¦Ž2C€ÔNn†ÒK‡¹’¿¶¹”]b,p‚ `â[>¯j¼6O ž‰ÀOMK£\ôÎj¿4™»@Ùj>ÈC~dK¤t
+N[Ž;ê§fP …f),G쩹Ó;XÃûæ
+ÈB({X tÈŽe=#Ž©Á»<9wôë)ìªt%ËÄû <¿Gƒ Ñ¢Ç
+^˜Å¢Þ⤽
+={iT`¯V›ˆU¼:íqkóS"À¢É4r¤hdÛ.͈Ñ˳Õä¬VHò¼Uãgô
+½)'ŸÀÁ¡–¨)’’”Ÿ¡ÔÇCý MGñ9cE-ºÁœ¤Ü‹¼ºb*h“æ?×ôÄN´*áÒò»¤ÿýÝ×úô׿~h4‹!oíù§våü‘†PÚ·ôöŸ™ËÈdçÈýÖõºÞ;ÊCÓYœ a2J…â’wzýºº1²²ÂCñmôùs ïÜé×vÁüûÇ_ÿÝ51Ž}¿n̦h¡?Bú£?Aqþ_¯X Z=íß#׫
+e:¡+®Ë¾ƒÍ‘aØù^¹Ó:[¢@h ¦Œ¯%- ~‰ÎS ¶ÃÒK\bz7¤Tb¤b[©LØ$=UB:ŸRÌ0asˆFC`FΕI9¬@C«A@„e"1ÁÒ!RW‰K½AâS2ô¹_^îçÐ`ÞÄöæ@Z®Œð’t9d¢¡²9ÂnJ›j©
+P%ü´gSÕ!Àjº‘©8§K9ØTˆÃÑú"—7;C3>œGt3±M…™’Ï—¸+ÞHžAŠ¬A™´z€¬Ï[Û¢€`ƈIæ¸n©‹s$}[òÅ¿¦UJd%„áFܘQÄ¡Æš-ÎÙÁ—,1Âí¸,þ®D‡ˆ[>+j«ŸŸú
+— ‰Ò`>ç4ÛšCºq¿¥—~- \JJ_¶>ë7ª%<Ø› ˜¥tÔEÿB0ø‹‹óýÆ­i×^óÊ¿Hð‹À iÃ|uŽ†Šn1Œç[ø);¦ªMC‚´)t/(Æç
+n"ÊÙã¤d‚ÄÁ¯ÃïÄ£ˆ`vê—sâ##Í@za4 ú?Š#`Ò3cùeZCüÅ@1L!2ámK0?JŠÀB¹ÍÁ3@/(Ãq ¡HPÅ°‰«Äèù-y—CÆ%VsRÑ
+H_í(dUùmÉŠˆoΆ·¢ï‡"}ºMñI-G©×¹"cyˆ¼
+"n[’ù;43!¥+j’¦M×zè3 9xØî%ðrÂêÆð©$©ä8Hï„GÌi‘±‚D³Š‹Kéhy`bÁ¦8V£=•ðÌ"Ã?' ‘Kåë +²¶k" ñ&…†c›|TÐ{Ð/_â%UÒÂ+bà/«{MSºÅàÀzmãPôíE²ÿ7˜â>ŲDrÿw »€ïË%xâ½;*áü˼|ïX/vH¡±;Eð8ÐP/ß™SùÂ0K`C„—$FO‘Ä?Ç£øfñÑXþû¡h¢Ù<”ek~–‰Œe Ü=‚
+ª>°’y—ÐÈW±Õã›ìwÄ{—cKc}/Ÿ¼<踻wPV %
+¬iß¼BùžkÏK“=‚yˆ{»Gùëº
+˜"&y’Æä™»F#Mxøžâ ýE¶jlcF :7dW·T¸«H¥×8 @áùr®›$sEÝir$û;$—4 ¶búeà –¼â¬wvÈ€KÊeû<%ÜÖ°\'NBRÈlj´…¿CÝ4Xõ¯À0MfÓϹ~(‰ó\ñé#?kÈ«ì/Ìo5Îapóv¬R‹nr¶¹û›­¢Yä龌ˆ,™„8©aqv2螘d”‡&½ÚL nž 2]ƒÞYó£.§„$Ï:/%~Ô”ùã3 ëé;ˈ—¨QÀK€Þ ¶`G/D| œW‘+¸ÿá¢\±Y-Ž¢U¨´ý¬InGê h0[e»„-`¨O_ð®Hcgœ$‹Ô´¼ˆø’P‹šwâ¤d4Ɔ“˜îø@Ìípd¿1öe@“Gó~ŽâM±¥†ì!“¼9<A ‚¿¦¼†=”?0„N¸õ>êÿòÍßPSÚÔ”•pú”Õä#c\D“BofÊ:BŽ‘ô9>k®
+¦ƒØÉ&ûÀ5Áš*Žø„­á0j<T
+ö ›ì‹'Ÿ¦Ai#€Ú:=C±7Á§¯Aæ`µÓðÜÙ¥4iñZ[»BÚ¨6@Þ_5´F(JØWÜͤkÉOÂ¥¢?H!ܹ¿ƒ¨õ.Íj`1¡Ì8#š»âj&xN¯}O¢V9Nb…„VmÄÓ:`—î^%º¼™ärƒ¹( Ò…’í¡híNfÄQE­‚@`:“r
+‡ó²Z8D6æ.˜UÅûÓŒD‚½h-CˆqÃå:(]øv’úO~ªôÎ?#èB9žbÑaÑ0
+±á$ÀéEÔxÉ„·Ø`ýH ÜÛ­ý¢ÃpŽÄ›“Wù¼3*ëhå>|è˜A©ãµ°Ÿ%Ž/š7)RË|úV¡k ËómÀ!l2ªüôª,v•Î
+Q^„õÂöÁXÕ¡ ·6y¨–¢D y(y Ì€•´£ä¿™&œâ«Á` k|¿tò¬}N‘.ƒ.ƒèG£²°PP/%_…Ùá0k™ñ Αžâb=_ý0F
+êÔ§ºk•è ëÊéE«Rš"ÁÞNØ­±g(ï¨õ°0ßG á:0Ü¥l¬Cü)á Y[¸,¬\3ê%³Šß §õ4Í$²ïR¯îàêÊZpu²n E¾0ÐáÀda€†ë"v]®‘äêW™o¿)dÇõ¹_ñÃ…"`„’ãJò ›–;£æ9´þÍ‹Wµ˜CïÈŠi¾a‚¯2
+z‡ü$íà|êµ™ÆQ’\Ôuú£ø[m×à¹ÚWQR)ìHŽõ ƒÊû;r< ±*¨ŸK^xÿϯSQߊ†Ù`%6DO5,0%µóY8`lmc|,M}(AG6K–ÚŠ—+ùe%œì®®€ pCúôï µ=!4óN4¯¶ÞpÒ•=¥j‚œEm%2΢;VýÆL’í
+Xkëw ,ÛÑκj²nÜoy *3d¼?CD÷Ù鸌.€„6ùò¿dƒXéC…„/2˜öô™1.†Ýq”˜íN[î h#ч.üÅŽ:l>Š°¸’·¯À †FWD*@Ä'ÓÅzûaƒµG¤ûí}GF,ÔÒÞ}c4|L!B%øΕ¯<“ãå]¹]OV"àŸf߉a6è,ò‡‘)!)ÆçGë„ |£÷o jm5 þ3Ë&ôq¸ >•öV LÐñë?Ÿï›Ê_ä7î«Ãn”CElÂ;ÌßÃ%…"­ì(Y,2Öã$¥WF›ãPâG©1È)6Ÿ¿S¾4É<$Dq›|³¨º“R#ä@zŸ‡Lå$Úå¦Å‘wªÒH&ß^qTãoúÐ
+¤¿¦²ÇDèñ¨Ì'ù(`GìÜcû´aä†SQ¸ÞIƒàq49猹‚ogXZxÕÀŠë€ªÄÒà¹ü>ÔCv µóæTáAí•œ½èƒÀÂ1NOe§ %Ÿæð£KÚrz“ßlæ¹ÉP³\[é1Ïv´áØ¥âF“46ôx‡¥ÚaÒvŒÇoË€´fè$‹gû8¶Ž”Žèš¥êÛIuU—ú/ãe’d¹ Ñø*¤8¯½­[8«îûoýR"äÚWCÈ|È!¿þñ7[U,\›kâŒá?Qþ·D ªr*X%ÙPð}oD‡–-˜ nö=·ã U ‘½(5Y( íȤÊååí¦À`¾2SgùTãm5¾À)Š’î7BùHô¾¾³Ý">(LY’ñ8›ÇQàÔSQ ¨¢=‰l#êþÛN gQŒã"W‰ÇéÂatÁ”™ Êé>R49”¸9;t¤ƒ^µëk0
+¨Ô»ªˆ¡ÕË ë¼µ­ÖehòÄPÑ(Þ‰OIÇGŽØ˜qm˜V ¶@Ìi'Ì‘U“n¯ŒTï¯ep²NÖÄ“åmŸ£\¬–9ˆˆ·×¨
+!§S†V))—B$Á¥ñî~\ãì‹B$Á§™¸tÛP"\.TR²CŒ'…HÒˆnò%ß ²PHË€„=ÝIü‚ð¥é‡a^5Ñ!Õ§©$àáÃCøRb©ÉÞ¾ò(x}‰í:àN^z7g^!$ð2Üy$]t!ÏÞqÉò¯7¯BVê(éL¶ÕbdS#)nÌÇ^ òÖ¼MÐ%ˆc{ˆA8À ¸#t! æB\ßH ‹R/QS£l €èó~üiÇ(è
+*R½íóÏÄKãÑðÉ<vÑ&DŒ1ÞÕá‹££h´âIæVø9¿U’ãF‡'PŸµ.â½ÕTy.q¥P‰5ÝÚQË:j^|ƒêäý[!áèQ(¤£¬
+H‰”—Krd·DW =Ô\ ’ãöлp„GêýOßÁ%X¶¤[ƒçp·­RA‰D¢»ëèÚc<þÐÞžsˆ¹[ŸÍýñׇŸua:dêÿ²nÚ»›˜éÅÓ£Í9[7»}Þ‚ÆSuöÙ›™ŒÁIÿ|èãÏ„Ú³™:ß”±"¡ý¹šE(Ÿôßo@ÃE†4]KõqA|õ¥­GŸÁ•tùpÒ ÑÆjSemHS¾Ô"x°>þÞ‘\F[ÒÇ°¶AÃ̺†Æ>†?
+±V‘´­à:«Ë¹‹ÎPU’þ”PÃ× 1'’Ú˜"×Nä6º7™S*)Ð)3š´‚hkd•B©'DŸ‹ç\¯½
+KEr¿Ø¡
+oŠóTSzS’*ÃõD2¡]FL—:F—ÍÕ‚?§­­sŽb¨«´9”ãÈĆdÁI ½Rü#êêPBÇ<¡dÍ€²Í†×hðÑÆš}Ÿ#ÓûòÆ{5C—]Öhç7äÖàXç¯P_A‘ ¢½-=çh³I;p!ÛHR¯L±Çm㙹3Ñì’W¥x¸û‹”^9ù¤{ëQpbú„¸›ãIBYòÀÃoù÷ R¡ 4½á]ÚxwÎœ] ýxB]Í •æ*Š®€´ŒKÄ©äœNõÓÀ¤2ˆLTrÜÊÖ§‘w-»zóž9½•
+Ò‡Jº)¥X'Ð7Å
+Þ‘ªuÊ7Õ¢Nm¢ÊÃG›·âOÔªuTˆ¿ÄBte5Aܤ=î„8žd1
+n«óòMСý²µ_SÅ©$ÛM³ž|s U©`kk?ÌP’†Te“üm~!Ðȉ<çнü¨èÙa2r‚ -ZrCîëâêçù+'rÒȳF'DåîdòqAf›LÀ勃ó¹:¤4åS7äzTÎÑØNðÑ©M;,•gdŠœ µ:¡kt¬1Û>M„(ÓFÓ Jà —ڪ˴”ÄÖUÔ6„k. Z„ïžP# KÇQ_Go’Ú÷9™Zv&ý/ n>‘3”tC vq=¾:7„z3.x©¦¨;Ǩd0Ž¸á Ù$x©÷m Ð ~¢ž­m›|ÀURýU«œ<ÅP£‚aph*†e¯Š/Ïà'7-ée)®ÚÀm$¸sÍ“‘žj•¯Û§d¸4å«sz^ ­¢^ÁXÑî7#:É
+'9ëí9‹Geƒêë6¶è-¦ÁŒò'’ODÛºôíÂGt&²Åa•>žì}ö˜Õ£´%ÚŠVÉ<Ù!ÈůåŤK?¾Ò€^×
+¸ï‰ôÔ™¯“ùIWû›sˆÃ\$7 ˆw4Y±’×oC9ÉÄs¥+®cH
+s“<¯BˆåÌ·b:˜ÊÏ´ïÒW¡~€0Ûž2Ý‹ò7C~ù2½yÔÐç­‡æÒŒ~¥É0EÑtKh¢] Ìb&aŒuklÇÕS !°üR5Þ R·¦Ÿšã³^feºúLQØRw |€m”3=è æq–øR‘¾ÍŸç0>P9Ã/ɱ0ѳ1qB}”¨Ïti’ÃìÐÝS%g¼fÃÈöà¨vr“ @ð¡i ÇÂb_¼BéðNôß
+@gvaúÕ3P'’ÓÅÖ)%É_‚­µ£úÁ1èÿVUÁÍ0Æk0`
+µ®Ž¢_ßHÒMþ˜Ïý°$º0Ô_xÎÚ-~ŒULååw¥r‘HD—q;Ÿ³ÞBöׂ•Ž %ö*'yJVGêRM_ü¿f„nIFB÷ÕogYËým¥9L-~Éþ×Ùð ôù4’è3E¥ÙíŒB5¡&nôÍúÀ«3À­œô¯‰7'éáŸÓ4’õîôçkF{¤_Å
+ÒõtšÌ¶‰|ȃv&âDÊ0¡SÆ‹ŒwªgnâÔå*òé*+¸oÚßA8QA5Æ¿‘ØéôZý
+#47®zŸ'!
+šŽ\ÆìÍ9YþM”5n!¨1ÿ–åæÓ^/ÿ
+bD3«X^Qqúõó 0N4¶cYN.Æ­^¾ÕZ)C¸˜‚ˆXö¦¾Ö&ŽÀa´=ÎËÑ…`èþãÔ1 jÉïís„È}ÖÞ7Níï&Ecìbºn†Cmœ™9ƒ½rE¢ÓÏÈ;Ó°ÀÒZØ’é8‰ZbX
+ÙÑèYL§ÔLE^¹—Àõ”œt BÂIáGO±G' • L-:z%J{8,Ò`¹ÙeE¨#˜Ìp†bÜ@~}üó¡??ÒmãÎÑQhQÆ!í’¦†°<=~¿1#wå9éçk|µüBÏ^Âbà^¦“e$¾ i
+p­ÿ{=?A’#5“²:šdOŽ­KáZ6¿¦l7Ûü¢iùÑf…ÂÃà}<7Ä ¡¯ø=¹M×W¡Ì02é7Ï9Ⓣµ²"ºÏ¡\Lt¯E
+! ú€3݉ô˜óÝç7¦ªù3 5´Ë_ˆk0mT Íã‚ Ä6/>ˆæž:Rýdž°g1QQÖìjbFQ—«C‚nŒ¼t¦BCóÁmšr„ôÊ »õìNb ’$ôüÛN„Y l`á;;\9í’¦wyÕ“zsHP²À:Ò>¦{n{r±Mfë4¥¿|!éÅç||ó´^¼Í¯z‘ø¼\îƒ.ý½AžS:Ö4
+”^»åã®öb׮ű‹
+‡"¹zú&sJÏÊ žÖ¸‘´ZÌ#tÄOÝ!æ6Çïñ˜ž6H÷9W)RÂŽÄ eÖéÝvåÙ¸“‚Àz.Ì
+Êìž«H]P©³6UÚÅ•†,e6ƒ.4ëƒp)RÁ¼îûR‚ÐÁ8ÑÒÓ«ÿÚ¼_Yа §~ª²¸À»L+†Dw<„sÙ•I=Gßk¥Lãt®ˆX ”Rç û!âÛÔ>!C’ÌC¶&ˆohXïö»ýSÎ]²ô¾ÏÑÆæ]¨¶B¬RFy¤O³©f T*;è€h
+@mq²®1Û,öÝAls5l„ç$HwH¥ä2ë¼DBÈK\ÑüS´Ì\ÀÒZ•­Ò´ð ?ã©qG…‘¬ÁÀ'2½‡)àÃ*¡ )<Mz9Oöý– ©{7`Ì‹ IšÍO°Ç&€«HD–=oL4Õ°Œh½"¦–L»K#ªžM÷ÅzPW«ßåU£G”½`«¦¤q2ÀSò M2æ½Ô»Y¼/’ñ—ÛíD|Ft3i2îõl'¨)²SÊMБ¾g‹Ò´^ÆÎ&¸–¿È„šyvö)Áɱ¼§Œ“:þ­âìÂØ+LHŠø!¯ëœ,%…½"ˆ–ªNt²å7!§ÈÂÑŽ «Væ0Z”¡Œ=È™“¡N¢Y¯…ž@5"jnOýlEˆ8¦Dä|݇Š§[0÷‚©ª•scñUUK‰™1‡H]7mcrÈ"se‰'¼0GŠÏчû‘²Ð4ô}Ž°–ÍBŒ‚2
+b<¦Öv…‘‡Ú
+!ß e­ê KßÆ>/iš9„¥»áìÇÎò¥ÅÎH‹©}ñ1>p««ß+Á =ã]Ð4h".ÓWÒ‡#^¤Åÿ
+z¹îÞï¾?›IA©g‰ð‡Ô±9h@†É‰O%Ä¢HÒšy
+„ie=£èÈZ‘ê“9¦Ó-DXD@æÝ!Rx‘Ž²Äž‹ŠÝ"%¬_r’L³$¦ç+Ëšæ'ƒJhCAuÎ÷j_§P^îçiÖÙû$ÖŽÁÝzßÉè&åØÄÛvŽñÝÂ9.ÉÕ%KÏÿ`ù~Ù9eÐ;P›—ܧ~T£ân&ÝÇÆÂ<&\“ sç­ÚuQQ³
+ÒˆMx¼qàfnp‰ ÷#¹Ä-i22Êœ‰‡ôHsYK³— "µ Ÿã1„g¦A¦‡ô¾„xA—B¡e€Æã9día^OÃ(ϱÛó-,`.èÖ :Ä!
+BEu9„9Á&å\Ä<¦ ytŠ¯Jp¥kEJ’üEXŸófpQzB)(¸Ö‡Í4R›ú.ýÇ·Ÿ~û>~þýÛO}c¾&)¸bHº·‹ƒ–^ä#}üùÄÑ Žc)ê‚’‚º`ñ¼C‚ÄÌÏAq‡Ä 9Ñz\ÇYÈ‚!™·Q+裵 ÉpPHYU—BØç°Ù°¾iùBp$´Ó>‚Ú
+¬2`ÑnB|O•¶Ÿ2gç
+t Êܺ4/Nú‰ø¯ÈéÜ6ê%Ä7½4ü±¹yÌËôÝçô6ÅïµyÛ…÷ÿûNi ë:Åô¾'§#m"Ú{õn‚J+"Î LüØ!€¨l]ŠÞ‘>ÙNqî´>…ÅèIŠa'ßÁb
+š•ù=™SÜ¢4Ш”‘ºP¨D?ÄAtÑqLÆCHCû±X)§ðÏ>¼ aàs†£ä}à!^K½º~˜ 9!F.8o S"g5ŒcÐæå‚I
+³Ž/uÍFY6‘á>Ddå6׸D3ÑÓ¤–”†‚¶ ¤
+’¤Ò5ÐWD6ÇÔ€‹e ùBE´! ‹Ì0‘“„íTìO¥ÿ¼M«P±gɇLBÐcæÌfïdº÷UãSftáMµ¢J” ©õ‡`Žfv¡Ò¹é->$-¦‘Dö‹¡3H†ï‹5úMÀÚZÞ'Usþåjº§Ö¡Ð®v'T†–§3Á1UÂDB}ÜQk¨sÔ ¢š"ÞÊXµ÷ˆ3À j§PLúb:ú¥ÒÀ¢³ƒ>öãÈ,^T Ͻ°Ö 9‰žº :ŽIû±hv+ÔVx€©„ÛC œ3ªÀÓÆFžÛ*ìGZGì úî ÞWkìyxb 'œ& òzqZˆÑ΂¥`¾‘ƒÙû†aŒeÛ= ü(»Ôü³oŒ
+û>‘ЖéR;`eÐHï}üR–¤¥a\=8®Ö‡N~ ñÈ
+E|*ú'lqÊQER†÷•_<G¼è5r3L‡xµ/úVÔ?–§°§¥†‰Í‹Ìßa³E9Øög؈Œ0>¹Ø4!ìLuF‰Í½J½BÌ»C:é¯Û««œVÒ<´i=\aˆä…dÛòáÍ5vŒÈÛ„D–5¬t7Ì8ã;fÝ $T$}ì?w!zì û»-ò½`‚Z>¸–»¨ÃÇúêiÉ´›ö}}ziCÕð­)@‚¬APä%ìËxœ –;yid×±ËrÉ ÂÁþ†ð8kSúü‰£Zñoˆ*§ÈȼMK†!g~ƒ»|/lJ³7´žš#îÉMÑ „€ZS8ƒf~NM…ؼ¬L7«o¬ £wH±»ä¢/Ï]dÍÝêæÒ(ie5ˆâó6âVŠWö}Ïâ÷/¿äÖ5ÈÉvB”Ií’²Æ2<€ØW…ˆ×|àQÅ,ýä£Í8_•EîwÄ+S÷óFð…nûëL=—ýýª !(;÷f–ý´)-E6Qa]¶qÒ§"wÌs°³ÊÍfP$CÅì¨r dGYɵŸÊðÿ±7!äàäÁÕvRŠÖ‚è
+AæÅÙMÓ„?`²¬èctr.1ÜAÔ›$í›^0â?ÑÆ:†j6qËDí‚嘓[Fc©ù‚ð ÖÁÐʉ@*è’¦v²<¶…†zŸæ›™£/ƒY¸‹\7]ƒTR5gÇÐ;qz}œ@øNF—`Ä–m R´;AŒŠ«eJÖàÑFÐ0ÛÅ3IX¡“
+ÓŽDcÀ÷eÄÑ«ãrœú,ê"³†ØÌ!© ºf^-nE[fk:ר`
+´+‰ÀNžl t­à/,¶àâfN!-ûäÉ—`€ÂzÌ%ÈmõÄzKÎMZæòCÞª¬Å?ÃÊ9¤‰7è‚iEŒ|öÄPîMÇ›°T>¤Žw{8BŒ+5†M br&ø‘Zög£,€Ͷ‡Á+²)0Óæ)vÉ’öý^Ä*ÓŠ­»QM‚„¾p¿#'Æþà„²Ž[›Ü•â$7„ò¦ªû ˆ ÛX¥T™Ãü®
+¦cqÁFY݆Ѳ¸ ƒýÄ6eì5Ui m®d²ýœÐÓjýüÉþÞ”ÕË›2Þ™€ºæ¼‘žèÝËteùÒãëù¡Ôˆà´qM;K”¢ÝöcÐe.>Ž×ýt±ŸŸ7L~ƒœl³%b@:^‰ËÛ-µ´W„‘]ìCÝK?2ãQ¢ó{?b@­–Ý}~1CGœ2Ö&=3ÈéÆ_56¸
+çz€ü^5d/ÈÈ! ãîñœ ëãñšÑäb•Òò܉kx?µëÄ4]9—xÁtä;`PÉë²(‘¥ã쉨 ÖŒjá¹/qC!Â;<RQj„…{ÓF0¡ˆvÅЧ±
+p¸‹Ò·µ´+³|ʾïÉúƒµû¹Z—ìsù¾ºÎI|DÊ8ñ²J¥Êv¹æ£Ì‘éå딲°Ü,ýtš¾—ë~º(Âq²® W—ŒUÌëM(ü.k”Æ—c¾(ÕT¸N+“îÛIòzÝôù“7ùÓ±Áð†ÙÅœ^5ŸŽG9ÿÇÎg@ǧ_¯;>ýoošOŸñË0 ,]<Ø}‰? DÖc+“æN˜‰Àâ09é!$ÿW‰ éÐ^Ž¹LÇ9G}” à~çH«9 íx6¿ƒp-ìwì îmBH&e»î5äRÒJ¨@ð{Pâ­¤÷:R¯Ù,ë˜kwU[o–…Â[¹„^@Ÿ^„§Ç’ÅР Á‰IRÝÇ@¬®ìR“W‡œ…‡G¢¦ó"…£É«+ÉYû5å3g¾„¤Õ
+ˆ±Ì%D»#PRÛj’¯Çþ($Ü@¬jMuXPâ¾êD¬a É…ûªñ´]âîºJ¿XfÓëÁ±á,ZóF@Y²K\þŒO§o
+&oîP;ìíð†R?Î…*8²~ÇÀï‰üçÃâ<­W–àróç‘×mrÕÁMØŒC,ä%9ͤ®|^¾$ø ¤_ÝßDLÚx-×Ç
+îÅÔyv|ÙßOÒ Ê’¹}“ãtu}«‰í(Ñq§˜kæqÞ‹³h±†kÏË!ˆ3ïg5 ×»0ò·&œ<ìDžG©Ì_¢Èn<Ø<M™O»])ñ8•Ó:'2×™öpSð
+ÊæàPõ-&Ú–ö-D”©ï<µXGdÒŽ8zÕ0Ö”›¥îŸÃÌ1¼ä̺E~¨Ñ‚'Oñ¼eˆ++Ê„} ¥ôþv2Cgü&&‘Šjkr…„áÌmÀ w¢ôú8EàŽ’Ïl+žž@ج £—Zw!µ!MÇi6O=|ñ¡ ë‚È%é'¸ÁNR*ÎP=Ø›ù'DÒ“ŸB}ÝÌÇW‡œjD-h¾!©3ßd·Q½:X²jBÏúâW1F¤ÚÒl¥ÓÓ9Qïkø«¸„]ð= èc^ÚFÀ ¡åѾ:Ž€ 1–û†Ò‚¨‰a.~¨J—µñSæF⯨{9#à"ÁßJvÞ}P
+_ÌøŒéD¯ ÏPAdð¸teßÅD²I0\’©JƒÆv.ú[_J|5‡þÝ8s\1z–—íc©uL#ý+¶N!á@"–Ns‰4jIæ’}êsάó7TXv+㌗9’%·EWÐ{(›F¦‡ÁTf¹\C–ªMí_ç_ªL$õIF°«ãxÃÆP†fÔf’„c2‹÷Ii«^0 ¡
+W}s›ñførŒÀ8@¶£¥€ÄÛó9š
+¾SöÉÂV Q-‚ä<‰©ÀñðÁL®WF_Ï"rË:¦ðBL:µ³á>@XyÆÿÒ·-b5Åê4"nnúúz
+‘á!Œ¬?J<Œ–àœÄyÙ¡^^ɘcÕ›Twhv‰2KÃWœiõè¡—º™{šû¸Zu#„¤;'i*dÃsJ¯©ðÐ5›_Å ¡|¹Sžâ{¥*tíºråÒ²Á¾3
+>ð„éîÅü­ªY˜®½å¬Þ#Ò?)Ü“ÕÀÕ}ƒžA=ßµŠ"CÒ´ö
+—Õw›C
+ÿ2IÞÒmÂ
+rœÙ¹•ß>1ˆuŠ]SSŸŽ1./gw@ɉO‰JcNøb‘Œ¼Åñºh &ƒOÏýål$g'ò[t6¿9ÌÖ‚œ(Ûßòä›Sý}ÚŒÖFšÀ+ ^ø^#†ޔ߶ihO ð‡†²çå¶út7<4o ±+€"£;B1ŸÅYágÃ
+_ßå]1P |ÁëçOáù¸$¤®òð$v #Àmû¦[iÒœa‡Þ}œ %3I;Úõ âWÝ~?ç66÷¯¹ßéU×)f£;"‘çoW¡hŸ3½Jùñ­Q¯ÅëHh,=cSÄÚ{›
+#R—O¨f‚–¶)­NÍ ²e_…{Oô¥É™LˆšT¸øÓÉp,8$Ÿ÷EM.@WÓµ ‚~Œ`·N©â†;ÑO¥ „8GsHlòC”// h\¾@ÒGz§0å &±+õêo2ŠNq-HÕ˜u}]¶K70Ó8ß•  aŒ,¥û1¼ÒÄ×Í·ŸÂ`Ke¨£?ªŠ ‰83w
+ƒNS:ïÛ Æ)“ºüQüÌGß:|?WbÅ9ê{i±qË IÄ1qö¾i¶“W¶=Æ5£JÈ>aÒ‹s£
+4 ¦ÀD¾uƒÀ‚aôÄj¶×MË8KþXãÃߎ*!ñBóÅ<†Xj÷ˇ91ÆZ˜  A„b²nû’ dcA«WHª|ˆCJ`‡EÉö4ÃŒ3í9l8Fv¹Ã{³ŠZì¢Ò™yWá]¬r“¤ÖMÑdŸË‚@cØF2“Xf^((U³_§(Ÿ‰EÖ1-ëŒØðÕ‚
+äÊS}ÝT5’Ê&‡d^
+Úâ…
+ó†+z²æ=·zÄŒ~Îúg&ª
+Ÿ¬¼™èã@&>m0íÓ¼Æ;ÄònXüñ£˜Y~9qfãé;\†fçÅwð÷\‡¢9‘.J‡Ýë#.ó¬œHá˜!CœÞO _Ù*hîÌ&ô˜•MÊCl*»UÌ1ÏKcüWÓ˜†E &z1Ë äîw7‹¡À”û¼s•®—妊ÿÇ(1LÝß·@ÉLò2·¤
+L8@êQ׈þ
+òàHÁ ›J
+Ù¦›_EŒDwáq¯¾Ð±–݉¸Í{Y¹Á‡ÏXOU‘•î5ÎM.#Lð¶VÇ(VœÒËø<¬ú
+á` d
+îƒóeð€0øì{”Ý(v®ÖÇVíoÄïÿþ1¦Ê¸;.^Vx!eï¢ýüï‘´’†¹¸ °Bãq¸rq1@Ö¯„ËÎ’e(Ã*¥Sf@ÒîŽi’¼ûÑÄgüÛY â5¬WÛ
+üÈVSmïhâ ÷‰AŸ+žž è$¢´ó*†(Ù!(™b>º÷qù/iå‹™ô£:¯XšíêOò=Z#îy¾ÓŠÖ¶û•¹ Ã?$jã@FžZlæ=\}Rè%KGáÄä±Ìç·¯B현QQ6"ÅE,a¹ü
+ DCšüoñ±Á>4ô‰šŽq¾Ã?ÓÌÔ[÷ùñA(hVn$PÞˆ ·ã¾A·ÕD˜a>Œìý=EÅ’.˜#µè븿ÁíØ~¹Dć
+. èXQ°Q
+È›ÈAËÉ7r=Úñê¸D–Eß¾ý‘=Ï Ãìí ÁØ *ð qêé$‘ |‹²„§‹;Лè˜ ³&v4­B%Ÿ$ʈ[•{õú ‚/È¥<@þߤÜ_õúçžþk[:6OJèǤi\yñ1<ÐZµ!ªøi1ª1»lPw‹KHÃ.þÊò4Hþ£xVÓ6X€Yø¥ì]Ê>ô•áa| æéGU )@÷ïîðÛ(/m;YÅ.æëN~2lî"I¬8
+5µÜüÆbiò2¨>ÓDŽLñ„ÜB?´Â;ÛLÆ_†¿xˆŽ€àâ()Bvš4#r¾£ÉÂ!.w $K’€v죘'ö¿ˆç÷ï°ü(6\ëꦫÊ^(j{
+©Uô@BlŠýòò anåˆðv¯‰E2uëÂ>ªì
+€„o ÐuŽ˜à·—.£ ˜àá{×G¹ôj'8
+Ô·˜ãJ¦IßÎi¨Ì§€g1YMoxÂv \ÀÌ;[©jUfnâéüuãQMF&ÚYázý éþ.Æ‚!èŠÅMg–·è“Ž›CX:úk|&
+hâZUƒïúQü F]ãÊ&@Æãöé#JœàÍ8-Ÿ
+XÏD°|D™uZ´K§bö`eÙ¢‚0WⳄ§³S0 Bò«ðÁÞwÆ=>¬ÝÄ7ëæ®øòðÝp*¶Ry¸ qq©uA¡ßO¸p’†¯O|T²¡ÏDÓjá->ª B6ŒÕYù©Gx|F-eëzÝz±óMså¦XE,Áqü,ŸŽ¡J óæý^ã¨)qÅ•ŒäOJ8 6\þ1³ÅŒ5x—Ÿ @®r¡Ñœ÷:çÙ}nZÉqŒ†*á…O«Ñ=89L¯îÛ$òjV¥Ì‡âÂnÀ-4)zýÞ0‹Žì¯$Ø’
+wˆ<+1Kõ[qRe´§ …|&eIïs7ñD¨œž‚Ý@Ï18ÍÄ€Ó¨&£·!ør ‰að_AÃÅ6ÃÚ9†ŒÇË«L‘/ÄÔa(Úé÷óÌ^\(SJScîåÓè®iJb±µX&>ƒ¢ÎæF.ÍD·KµÉx„Õ!lV£zÉË÷Ezý¸ ™”ôâ[Uϸ<#Îh-?‰Ž!Ó
+DAwXX#$…žRø”m>¾¦ozezIU©Ü% m] ŸË.aCÂû`ŠLÍè®=ЦO Èc×Ð0òFüÇKÃ,©JB]<Æ gväÏwzt¥3Ï()S–eç o¹+äò”¥ \Ñ°ÛÌ.T#NA”;—C|>ÓW=<ñióU?É4%Ǭy´Cõ¤9¾³ÊDúælæ­pÈW·k«nÁƒ–³§ )žÍAPf6+,yËñWy;$wñdÈ“?|9(~þåe’$ÉCÑèu‚6ÎÃZÛº…Ìz•uÿm¿O®
+wz+¥M)#~p
+þ"¿W.¡ ©!\Ë— Ò fÇf‚Xm䆇CÐç„ŒŸ³ØÀÍg‰Š·PI9­±L³Í¤ÄsOѬ=F úNo…£éÛú](Å€L2oVƒm{)G ÞþТ7¢V¬åŒ`´Ðø‹pmtÈ|øÈHE[…]³†°˜@e q“ÛÈÝ‚Ch‹h¬ua‘eUž»§£|4„ƒdNP‘„Ûøq
+ôOfÌUÑQÎ)f©Šçr¼¶º 5+óYdb]à—v#êa;(:>…¸„¸ë¨ùªÒHƒ´‰Ñn«ËB14Pê ­¸2GìäJ|îÄ äBÇZº¬Ë^beøe÷!@$pÆ­Ú@öõÿPl/W‡ÃBÈMàÄvsìv˜ÑÙ6üŠp5w/XRâp¹á…*üFŒ¢¡‡@è@'F¨až‚í4Ô½ƒ”‹1ù ™÷u–™0·ÒkI3¯ô»›·„‰$ƒÆŽÑwb¤G¨(™çC&©
+³Û’‰Æ’0¥¨f˜¢1;IööÈÒmûšª¹¶j]>ßÜÈŠñ ¯réÝšy<<ªç€d™¡„òAÿhWŒ›Áöÿe³,·¨7`÷}/ÚM¡•°•èì_ˆ™û5ûñ‰ùù‚ùçŸ{3Å¢å¬k}…<$Ÿ
+”‘HBEWü`  Áµ¹µ=¢ß¶ÄOF ŽKãõLУ‡Ýþ£·FTú¸/y=¸œšek5¨'È`zº®ŸóbN"´…ÏY&Ü3%aÁrÁ\ì±6ÍFîRSfV
+»–áu=R>â,áìt0ïÕ ‚É­ËýÖÝÓ1½H„Ñn'Ï©À°8m'rœÎapƒ¨M*\Ô»Aäe°Ú6\| –—f%“Wðÿ,„Mt
+Q6 kôi`ÐÊ«h"ESËüùÇ„³N‘$w·'[uníû´­H\ôº/§„[Ës‡àëà™K¼nÍÍ )ÈÊnDôÄor³ˆ¢‹ç‰ ‚½›m5›†ÉúXý”t”b®u
+Ø”—Ò#`·V“Ú3ÁˆëÖ-åîo9dÂq9ûNðTQêB,ö2*†—ßn§)­k6„>¤çÉ) ¶•¬ gVî4l1³¸ÌÕÑ©æë XÀH¼+â‘‹dXè›r€ØV™º¯ÃÄÃœËñr+˜CÃÝDR¾
+§ã£Õ)N%]^!û“~°†Ê  ¡¡ ¼ç4€¸:)˜õh
+¬UÞð>¼
+°=EV ÁqPúì©Œ€Àu¡dƒh†£ßÒTŽ‘
+gÇ%7†Ð¤7 òÎÓÖ¡XÐ9B=’AP&¥Ž:Z> „ ,'’gêôn—¢®˜$;2›Óüè^±[éÝ:ïN³·0¿›œÂv"Ö‘!q=ïË ä-—‰ÿè~b¼
+;³½féådÃüÆ:“ÀÒ—ª¥íÊ2]ªO³Ö™°=#àÃœK©.…­¢ 4ü‚2¾õ( L#­ÏÅó["ªòN<˜;‹œuš)Ü›1ˆI¡ 6{†^`î®Î0±òÄ؉a
+ÓÖ‘ß&À®»ßJŒîdØ·zÑqþƒû‘Õº”0V¾À—ÄKÉ;9RD¨
+¤FyÒkD|CÃÒ¼‹2lœÝå( 4üœƒŸ§äÀ|ʈÓóˆZeÕ¹ÏË´3+¾d%¨H!h¢í0.²ü¦G¢Ÿ‡žD¼ô•LùxpN§Tx2:‡à˜JZ.Š½¯Ó…H^Ä›©;ù¸rW Ÿ`mè³ë(wU•N 3¯ò]4¼¥µDŽƒT\)žÕºB+Žr´j¿^ñj~˜7F%<9ægŒSÑo+ʽ)
+/gÈ·ÒXõÈÌI²#×À
+; „õsš• áԎý×NíK™‘„p$# §Ïå÷*¸ã®Éoe0Z c‰VQÁ¸Òx“‡ÆˆðÄó2œÞÔ¨Æ4Œ´×)È1$E ´f"óhŽlè°ÓT%†™°¼vÞ‰„rzªŸ;O±äxâTÏ)ƒ”v¬¥Ê9J¾™Î_?NE'“GË112ŽýÆÿ©èåEÏ(GIBA˜ÎWÞYN"@Ĩ´K–£†$=oÑmû#ËÕÅ’bã2.YŽ±‡@[æ-ËQD¤åx
+±ä3xl—¤ˆhIg{qöA+ÐÄð­¸÷‚Ǫ­³RD§r·[‘ Í&ƒ=™·!täcɾճ|²€³ý<¦}Éðàj•‡æñVý‹¥}4¡¹¿½N_#Ç2ú˸שÂ1ŸåíËûrÏ@˜l!¥WLÃÒ§ÛŠ~‚‰©ÞÖ½KGG²#ã x
+œR耰¡‡¦m)éŠhWrT€Réî…[Ù¥H5Qç1ö:)ŽFÄâ÷xý¨ÉÛ.ƒ±¢µŠà2ú~?'êSt3ëÃDsªš‘~žF¼ëî¡5¼Ô‘*ÚFO™ðâð{Qæep)$‹)ùy&7MÃ
+èPêíÖ Å@ž-9%ºœˆ~+468_žr+¹îññUÈÛ%˜é0yš,ëkOÍù; ÌÖxh+¶*+–¬eäT\‹TtUPøÞ%›¤Ì– „]Ù§f9×OW1O\µOQù,=hÎx¸€q„ôm<‘…{×Ø/Ó÷­Ä¦GíG™SøZ'éxúVÇù4ÐŽh±½âåRq~ÉQt\bËéø8”4„RZ¼U'¦¤¨-¤«Û¥UeÒPW*ñV=ZNI"2!\,C Âÿr9
+ ÎÞ£Y«Fe°â4#î’È Š]è¨ES¥„ù ÝN“†2
+ò°ÞŠñµ]Ÿ­¹a%Ô:c+†G^XÖ!Ö"Y*Ž\œ”ñÔóÜòí7àÎ0ÿ
+¦À¤ë㧊*&JK y}³¨ó•èI–>ÜE}âþÉ°ÖÛ·‹æI7>
+o*ÒSöÍÁKp9ôØ”R»!Fxrq^_2E»±¼ñgNƒÙŒ@À_£•oÕÉ×½Ù©ZIþivÖq0]nlô§‘ùýèÉCÒÔ~±ŸÒÂÁ‹j¾Ú–f'ÉÀ…D=ÌOá‰Y½¡ir%ìÙÜgÕÝô7ÌfÑЦ…g /BeÔR½7´06äŽÜDAÞÊ1¦ôòJ¨r²jÆíCqàSŽ­x+~A:ë¾'¼A`cZi„W[qE Ü”L^±H|xÆšî­& •uæ²Ë€_=už~à#N‰ngM±SÂùku Ú½ä+*_ŠLÃÍŒ°×©ç4D.!Š Î(B¿ì_U=>tï>]F¿+o*¯ø2KtÔDD¯9bß1°Š8¡Ñ‰|š³-/Ay?ú°{?CM L†FÓ«-X ìdA!¤¤…joÞ^h 6{…8`ä&MNª·}£dO’‚m1ðçз›
+届Ø3ì†þ `q‰~b®N¤¬$9}Hù켊(ûRâ[qŽ‰ •jã¾ÆüŒ•;B맑ëák®Ë)°Ë®çmXáË#´²Ñ£;7Æ3˜Ì>¢ßÇY1¥‰'@ë¯ÀÝ¢2ôαÇüC cøãFW—"ÞíöáE(>kݵ2# ÜN†÷©!رj*¨ O‚ê®Xf¬)ÁôÙŠ"–È[v|FPîÜ… g+®Bû¹‡J–¹ <´•k AM.˜_ÔîÏ?Šºt O+iÔvѦŸ¸˜5.EŸE-ë?~¦™nfÜiõÊ##pÐ6dr…]ÒœŒ6g´¬/&eâÚ Cù@W˜y›Å?‹Kc« }8µ(Ê¿%=¢¢#èêU^##‘ojK·TgCƒR÷‘É{U¾cºÖB|€ølúȆ»ø9}+LC¡)Ë¿GãÃ’ERÈÅÛðfn~äQ@PÞ{–šNæ1 #ë¥$¬˜ô'ܲçuèë‘.W”tn»32ÉC¯Óò
+ªn¯´4ˆÁXa–13»‘Qéü**Â0ªOŸÎÌ}7IJ÷@nBTW½ Á#òF¦ù­˜ÕÛ¡c¬X¶ÒKŸ^Ä!-w×à àœ¦„ê&&æ©ø‘{SäBP‚E ³øWí†à®JŽK¦ˆÆ¨òó—àeD±Å§#€(
+葆{9\AäàÔÍB»è|äžœI,6W{I ƒ†¤±|§._àEg¶@¥@Úì¡‚hÐc^&ËL{öÃðE€n¾týíÑ'–ÀШÅû‚‡êP'N²žˆê÷d&ˆSZÁ„ü‹vð2²Q©ŒùR
+Šò ŒÐiºÉcå…ê/IšINí’+£I}P½J<u ¸ÀeL7f§áw ¾ƒÎ´äˆRx~4¤ Ì;‘ ÓHymu³üAwQ’ˆf/aÎ
+~ ,¾‘Y—¼eÙÁÅÌw ­BóNþPˆ
+DhFkð¾Y§¶|+ú|*êÌL.ùx(a´:$?æ
+H‰Œ—A’d9
+DOPwÈ Lš„€u÷²oÑf³Ê¾ÿv_(l*âÿ±ÉE•e¤‡Àqœ/é¡ßCL¦wW±¯‰Ïï9g!½ŸüýëäsEë}™Í¯{ˆŽ¾Ö‘iö‰üØZª¯P}.km­Ö7hiëªyZ×:gt þ´|mˆ5×àÒæí²Ì§…Ž¼ð õò¾øÏÅÁ=œã.Ë‚çk“HôXÚÇŠÞÆ×j’Šebvú)ÐRé"+¼òã“2øð¶æÉrÌîAnæë]³¹µ5†Ö}æ˜6[~t“”j§`¯,O*1ZHœû,±¡“wØy—Š® &ÜÕ¢C‡÷~²£ËÅóuhAb(¹qð EÙL†*÷*ÐhÂÁKäTk…¨õÞÚ¨sõäz}jnÖyom^U•1‡ú å“S9‰*ˆÊôIŽaÇ>'È&D‘õª6ÂÃvOÈúnÉ‘5xšÞ@®Pë»S¨È =Ÿ3V›YR2v®<Z“5‡ËØIÂVƒà£^5á1‡À¦f'”‚j«Cž¨B¨g}upÔ>g M˧Þë6&¤wr•¥…ÐéÆåHÅKA‘Æ—zÜ~6ˆÈKÚrëR,#oCóµ ™|Àu¥UÈgÏ·'5
+âÙ=æÉ0: <&_/÷1¡XsXU/§ý|Mçq²ÏqnL(Øu’Ó•‡ÿ B·Žà+¡G¼Œ †¦h[;”}·f¤ˆƒô°T4“[}mìçʾ¨z¦îø¢gA„Zñ½ýpJêäâ!~Bõ!ª|²ôÅR®éˆàä oƒTï]Æý¨§6Oï}²Ô`Š
+ „ÏýéœlßÈ$K±} 9<Kh­º)ß'è×ÍÃ+”Oú @ÖJ Ó&q^¿ ŠÏ›xm•j††Áç!-Ã`×¹ïç„ðïÖyPöð‘®ÈB-ºFÛ¥HérAèFƒqØØ|0Šê6ÍA<ì@óÊI¿éÔŒðtÿ>uÉ| ®¼!&u‡óB=²_mBÌÝy L'Äc`f_ýµS<¯"AŒÂÿ„rÒ¿J¦‡ÍêáPJJŽCË‹‚$¸Cž¾KÁÈà7º¾¥’„9 OM6‘sÀ‹RÍüÒ¡Å0e)íÒá94è¸ ­SR&™Fðà>Ë@àÌB?Önrý¦å%tÜ+Rƒ‘e¼æpÀ~J¨ýtpÇ
+Š± iMEÀËéaŠfN¨¾ó-ˆ]Ð*ÎÁZ KÃüU
+n&|tBy^m%Â6ÝMJHºã 2Òoñ÷CW¡°”iRýî¡s}&ƒÖ)6¬yBŠ'y ¶º!ðEPZÎî’¾<&®ð5F¥%„ÑæUÜ$àé¾êM4(äÓ« )
+nCšõbxwüß|…zr{ešx“y@Vã°¬ååGúÁm–y÷Äß’ÐTI?†Û
+
+uâàª8pÙ d› »ÚÉ^äpô,Tb󙼜Ú# µg°Ù äïM>l1jEÃÈã9hUúÍ 2ÓÞ¤rïì}ðœWå\K:®£Ë=ë›ÃfÊ %w”…ݧÏ)kG2%•>O v ‰‚p=t…V¨_8svN¡+’Õ'IªMý†Ô«ðùùvú%6„Á̦±8[熆„……³Hl)Ý1.ûpBQNæîF*Sa imVv>¤‡t9ˆx½ê‚3£7°Eb¯HÿSqRœÚ'8–Da[`§)Ã…Œ´¨)ÿ›IíÏ%ätA(õb¦D%Û9¥×ØT¸³™š.¿‘Ì"4·%Pø8T4F"Í옱±ÏID·á¥+³Ø QZô«~‰i!hàžÉ1Ó¿Szüݪ1ƒítx-dR‘2ª¬Ù>†Æf9…dÑ7-PBáO$$«´NA’¸¬$,„&'RnœlÄ«$32À9µÝ÷9+0µˆ6¾ÈŠ„Cr|ýŒ[<T~A[è8¡>@Ð#ÅD+”t›¬v£Ø¦ð3s2ÏzxKÏzò"Y[º€åëõ*T_8¯Ò\²umì\ue:)(½— f—Š°QÖm$½.¯d
+‘<݆!ËЧÕ^ï¾y-že¡îuNteÂœÑå Ð ìÆj'T`±™&½%6„MP‚èv ¸rä;zyÅßåLQ¢Û–ÏÓ4Æ+ù'¦–$ÏÛLb­[¯x·
+)qdeƒ,·!pªRYNî0¿ÓâಘgÚÌ auà ¤¨Qf?˜L}i C‰"¤ƒ.~1¿—™©$ëåéHÈY2 ˆ+)îÇIÿîÈç•cE¡›½Êù;-
+œ‡ujÙ·Ыìûoõ>iæ©p§¥¬®2ê£Ù`Àê¤Í©Es
+Ù~<A|n~DYùO hÔk§¿Ó¯hQÛ•a//uCØFÜ!¬x²ú¶LìQ´Õ£‡<vå0Ø2§¾V‚=úQ>2•Qè$E±ºŸF‡=¤ “Y24?2ê/‰)­w¢©%¿6tüæx'ÄÎÌ1ÀS*)œ@î{±ƒŠ¯¨Šõ:Gi:qžæ¦ð$lÄX5?OSՙ̋Ö$;a’IÄqŽJ^,ãʼn‚QœC0å=ÍŠ*ZЯÃÒ´Bã÷Í‚ºÌs…™æb šméÃ,ÊÍ* }ÕÞ0iε-$\X ÊÛ$ «”³-&<öÌÃÕ™
+>˜‡ÍvU?BAu _ÿú›­Æ€ü(U 5ò5¼´}V¢ÃëýsÕ•n•éв^üªµ0DœZvtC ‰ i¹A”ÛFZbcÒ7B‘A–ª<äöN4)Ò@BÙ][Ç !0pø^‡¬¦ÞK˜ãS@QdIÒ:ïa¥e’Š:åeZ˜æg ²Ù9Gamu#Hšq˜ípXÛ(I
+^!•x¢.”vZgÈh"ìA-÷}[ûàe \¬M:o&AB9ÎG>AW?€î%<@nïpB<žfÃÜÆs[t%$(ŽÕ¾db# X¢½A¤Xø1ÓÏVL$LôÛVô::I >è¹á$¤ ˜Ê&«CéËä™Ò½Â¤Œëèå
+›°çìâJ?§|•ˆöÚZ„Q‡·µÿ1ÝJÑP@j¨ ¶6z’AJ9¯3ëßÙ o`ëdå*TZR½!©Šï#ö°Z}m5ùlJ½iq;r)j/bÀŒ¶NE
+Ze¡ÔÅ@d$
+ c¯ƒÉ„2«A /
+ÉãçhÆÖ ¦=Ï-¥<dA+p˜3%eƒ†(0Ë3îY/ëâ Ó†¨ªU&¨lŽíÑ ¼!¥yøN0 ©AêòOñ ù"ÛITY€ Rr\· oTƒT˜ Áœ~):¥Aäè#Åú2ªT?OšÏNÃØÅ £ª†¥™&©ßŠ U§eêË…¯ã¼q#áeƒ h‘æ&"¹]‰'ÝF(ºD÷˜²—X΄ KtæÁõò+CéÍlLÎ4æÔŽ.å
+"q½®4Yæ¶k¤
+NœîJW•I£ƒ'¤ÁìÐe¾˜¦–ÈÌéÎ'ùaŒŠAh¦‹6÷Ÿ
+rZG^S„«ÝŠ©+xJî`|£o“¡`¿”8­æ|ÝwÂÑñ™¤ÁŽgÒpY66†-•l{0Ÿƒ:§òuËE°^
+„Žàb:Ý,ÉÒ äø[#}t[D³™?A}ÇËÓu'ÃVNVv—8ð+Ó°–¶Õ2ȘĒÍ|Ïdåp%Û:‘ ¢'xÝ YçG&’U÷
+úYî c¿KžÛU¿Éî¼%#67ˆ­»æEÖÛL«Ò4»¥<8•A¶lÚ¡@ÅøQƒñ>5 . „hNQÃHĈ¢c¥Ìáð[Úo•‘nqžÌå.ªk„«3JÑö¨ø\ òÒ\³â‡$'cP1O’y¾Ñ²×Ч^ûœ
+
+ÞÒÃô7ÿ^vr¹Ì‚”„3v¬x„uìÀ^JWcö¦€Æ›âe­ñ Âi¹ºLÐÕ7#ao1å2!D““Ž0`î9ÆêÚiUkÑ>2mE2~š"eá
+þâ³»žÁaM¢J+µ@ßâMˆ  Ÿ'kB‚ÿR^&ÉrA=î ´å<¬ÅR·ÀL+éþ[žgFTW6™aˆOüÊ)Âý9:óu—0 X—(ã|;*A4Ùtœ6xÄ8’+ž3þEL¼æaêô¾ƒ aèבŽ%ˆ±|«36ðñuô{öŒ{$ í|ý½ˆ'Âv”§ÙbrƒŒóWãgÅMüu"Ñ}—`p—B«!m&ðéøÂc?:T€ ’{ü@uú 17¥o9Áq„54Á2  z†l)µNAÕs¶Ý§†)½k¾T”™A`³uϤ°
+7÷N17ˆ‘÷ƒ’l Ÿüá̓kÅ5aî*Q5'“€]ó)0‰j¯l5L*½]ˆ%Ñ¥ôhŠtq—€¡È®Ð£½/hki+Á[É·/?¾Ä¯h½„.!nÝ$¥,Ê_í"Í>zžÚö,ŠhŽ™ùM°h?}|q4zRÊýP´Jܪ«N2¢X ÿÞh!P-´ì'£ŸËüÖ1L‰¯µ—iß´ü~ÁÄî²øÒ³"mt‡/Õsª°¥xhƒŽv*až,
+ÍÓ·Ï à±åZíÈ< M7<5!ï,…%Øå5úŒ¹7-@üÂb­l !\*¸šg[‰-5„€|†×úôî“Â<Z±zg[÷í=ÚœSÍŒœáv˜Ò^*½$\è!É‹ØïËSÜ߉zÉÍ¥v#£˜ º¸Kè4
+.µ¹¶§—@ÔcÙKaM]”wꤤWd¼0-õøm-ÔÞÈ€#wYá'Y_uAôš°pŠoT™eõ&&VeÜŠ]ÎC(jD˜‚°Êõ(GsÁ«ôk¥Õ›ïHSØÒD“µ‚»ðLÁ^Œ-_@9ä¾¥)¾r
+5â ýP´J¢¢R,Û‹AWAÚKxœ»$Ȥ˜¦-Xrí\)‡iÞ[üÊïuïÄŽä1ÊF]ï .äOŠn“E=x$)ñªAê"´ôŽ°`à«6ÏFANÆ¥unßVBQð¥ _ÞŸÁ׸}µ˜gXš‡¥R»VZ×ÇUŒa%@q[é¤÷è+1ôÒ} `¢c‡ÇB¶éî`×vÍ@3%´! >Ëس/õ(¢Kó:E¬¶©V=Q¸–ŽÀbÀÅJ¦Ú›ýs™•-™6ö:SDÆK’‰?þt<”÷;pátÿì
+(8†`ùfà1D’•ƒÍÖšQ¤9º%Ÿ"µÒ¿e““ðžÁ%J´d½EŽ¤¤æçˆn˜C€=Ó¦%k{^!Xø>]í÷åªü0ÂóÓº¸FZP…ø£‹©Õ´.5
+ÇÞÇGz—$TX³{3!¢Ù¶À…)c Áo0jMó(êü-jvy ošþU«ç8»£¿¹Ù~¸ ,º]äKþ
+ÞZJWäCÂAHöd˜ÝõV<~ ¦¹ñ Ü«=¯%7óòUZ‡®Éýï·¬ê>øÀ÷Óh_ÎÎ…xOÐÁëŸéh¬ÂÇôK&äàÇ2*|ÞÛü= Qí(3µð2î3Ù +¾*1fϯ·[JWƒ.@ÃñüôÒ[Š”¹V¿a¶Ee®}ø‰ ŒC¤2 åöÑ4$ò
+UAI°LŒÍȇ¦wú{`Jû¡Z^0¸‡Ž?4
+ŒÊ;Ž)wQ‹
+ i®t-u7
+z³–Ü7ð ‚Õ£Uœöß™vÐdãràq·†z¢Ižzí[ôP·‡=yÔ1ío€Î–<¹êÐòQ·è!»ãúlnÊÍz()"/A/¸O®ræÆ䯔-zÜM|ƒ
+‚u¹,UŠ[ô˜!±A{Ã2wôØ…ÜÐãÿ ÂÑ£*§43Þóp‚š~Ã[Œ=6A  ˆv6³ÕÆX*Ž¤¿ z;îóOîäW¿}ëâDóêô ím³„ð-蟇 ·›Aaâ­ñù£ ûq·÷ýQІdÊ‹Vç'HUü‹˜;îÝRy úü“|ϲ|üPhz±gå”âœÂÙ ì)9É&dP¿¶AsÉ"<Œ¹ÌFO¬uDIÓ‘ŠÔ 4©Ã‹=¢°iBJѬ°
+Zde,*æO;‰Œ0ÌÈg*”ÉâÂa&IŽÏIj0?*X1Rº…ðT °ŠT, tþ"2ÏqÅȳ&bÅ½ˆöt ëZÞ<$NéCÊÔµˆhaú ¯›3…Å °Pê±D‹  Ue; k#€a¹1’nù‹x:Á£hRáÁª˜ÓBŽRñct¹ÔMˆÅFKˆ±¶Þ}gZ$k[Gá×u UÙ/S&™u˜ÏóBf‚(? »NÊ“7ÇèMÕe*Á‘öÈeô²ç#HWÉ’c AÊ1^ý(r‚]«–Nt
+
+ò‰&¿ó Þ„«âÕ>C‹Ø¥~¾I“ v€á—™õž$•¼ÿš²“'ùIÀw ÀK¶ x#è¬S´ï@9ì EàÃpР$ÔZ·!m¶Vf Ð×xu â=ä*L
+ñ+àBÉ݃9`·`Ã8Ò6Ø^sÐJ<¢¥šôJcæ¸Ù9¬)ò vœ|,Ûüxwýw ñ£IZ k½¹Ø€‘Y¿QÄÆd0Ÿ´†‡P^|T–ä(€¾Qÿ¦ê&œ"¤KÁ)^@oP%+ÄmÆåô}ªÐ0º¹Iù£ñÈ€ÔuÒErš‘‚b»*]„ëbô;d› 5ªI³/|ÓQ5m’;/Íãc¯ØP …e^HÈCÈ›¨GÿƒéTGQ2Íhd8•|X®šþÓ‘]‰Î¤–› k±„ Î=¿Ã3ùr*_3ªÌ‚ýˆ[‚áIžkïgס;š&CI‚ø°:qþÇ  ¢L%«… ^$’âgKu°WÉLçe ¬õã~tÚy’*ÌZ3šµsu) ’¥gØg*ö„­’àh!Ü–õôZ^,¤Ð<ƒe-Äd!]£5ݸ¯“HÐXzX ¸'ÿG„³Ÿ”ã`ȱºá!`;ùcÝ9bµD{e-u¹[ÈÄc,
+æ/s'UŽ»hS<;,ˆ±‹´?
+@Ö?]Ny6õÄz³៵È
+‹A¾àëcÔ#ü%qkfŸimx˜½¸ ¹5—).XÕºð[ÈÏu<+ÉšâÓw˜’¡)KkoÍÚ>¸÷ñC¶O+£[2é:é±ýa) HÖ‹1×s)¥”¨|FÌÖQ@ÅNÛVv Ä éÈÙÚÕ³ÃÔ!˜(nîÚGKBý´¥?\ÈdUJž·MÅQƒ(Fùk+Â1~˜½ ‚OS´åÏ,Žü+¦í=t))Ëqkeô¨Î…(ú©úïÖp ú|‚ †üŽ#úÖbIdÅî£î]ˆG¡E”Ž^gÍêüYS8'‰·ÂJ «6©™eùF½ ùz<…ðïEÛN._À s ¡UÐC!Z7ü3 Zàð¸Ê
+†IàÐð‹1út=Ý“4ì„h/‘ç“WG-Hº‡`M rœÏæ—X±Õ2‡ô´Ù1tiè–gUy‹UQ•WÍíå…CÆQVˆZJ«êU«C`²ã\,DWF¼Á‡~&™-E 9ºç‡% ùØ÷Ö)"°ÌA‹!o=:ÛYo/Yô%tg \f ºmu²t·
+  S—ïph`ÓB¤ÝôbìêäØÓŒ‹`óÒA“ºÝð$&õ*´UsZÀ¡-Æ‘9ò§Øgf$` iñD˜fŽÓkð€íÊŸ$¦J(Qf3²£RÛêo»û,ÿÕ„]iö-_ð¶Õ
+žÁeÁC¸ÎVȇðâ¬ý Y]GuH
+GÒ¡ýŽq‚ìq9FÅ3\ÿc¼\rë*‚0¼ïÁãHDý~ ‘zÊ
+"%CöÏ÷wUŸäúöISîÓ]Uÿ+ò]úÍŠÏ»TX×ãŽíúÔÇ"¦ŸyÚ±Àº )kÂxÜÊdR–¶'­Ì¨’[sq•7A „"q°ì©O|€ÞˆóH~ŽâJ‡Ôm…µùmlÓÇÉ*!:`v˵˜¦¤A_b\4pô°ú9â Î`:.Æ ’.0ËQv ÄŠ"vŽöÅX´(`u÷§ˆ àz ?Ù‹ &D|P´s²¼†¿oJÁ¡´<6§×¨(!™!GpÏûS?EÞ;ø &7¤Af K ʼ•'n™ÒC‘,wÕâFÅ¿O‘¼XeÀ¢Ðæ<~D-LrvÂÈøBº>xÞ®
+_¨%´kçpl"~¤x ò£L•D{‹È:qYœT¬¢HfÙ†AåæAlXB쇓%“Œ‘Ëo)Á"² J?¦I-Kg«º3.f•»ò_æïq`€>ó°,¡ß²Æ‹1±±™‚R¤èÅ‚C¨®ÄZ¦¸òŠU"M‚âÎbC 椬Á‚g±Á¦¡¦€
+ò⇒Ýc1(‚'ñ",+ÖvZŽÕÀÀ *‰.žC;ll3ŽF§*H¢›YÁñZœh¨Ÿ”V”¯Ø~;‡?¢Ë=ÇâŸâr¸ ¢ÍqÀGˆ#$/!"®;6êâ!’F>à`;+VœLD³àŠeV’`
+ÉKCcPðñ{‡c™#][ïà$®Wñ²yø0Ù8] íîÞ„Ö”±]´…UÌp]»)aiûDßêÕ¿§"Q!î©ûœÇÛÈFÓ@ŠÚÇã«]¿)ê»`ÈÌ8¹ŽöbîèVöS[Ø:o%h1‹^Y„áÏ.¼‡ÖaãÎ2­x¬,Ý_ªlbÎ
+½ÕŠV¨T¶*[‚šÊA•è‘1gL‰lÿ€ÁÄdÛ‘jr`fØÀ*7+0iÜns¡RhñSXꊳkðl>R ?
+‘éQÿã2‘üÅ*SÕ}»À¯¸Gãç@Iy5/Yš´JÃ1Æ5ëŠ<7›¤iÛ.Cÿ0òÎ:RÁsGJzäZ"‚:䵺Ìè†ï9ïÍ¥.^jsh6P…qÁ”…ºg™a%È0";¾bð÷1—fWóºd¨y°"a‘d`cñóimx8´Û”f@ã§åAjK‹@é<ˆ‚ÈÍMÙ‡¢U è*ÿã¶"±0r(qx.w"¯çí9¹+ »„‡7™øèbƒqyɲ×$Âý%ºÃ7È5ÍýòFÂøâR<8$Ù@ZÃŽY ;‚$Ô&_õÇiRЃðƒ5šWBÁ½âDAYn[…f”25¹ƒƒ|Ùfn- ˆ3›ƒC1ì°#ŽËK 'FõÕY÷ë—D®5nùå#I «Ås¤Ö†_ÃT¸"²ãD*FJ÷’É–àîrÝî¡ÄË©SüSòƒ°$Õͨ†_åÑZösžRmVÿ#¦‡({SPfQdItæíåß—O¿„×?ÿyùôßK|ýë÷Ä;s‘Ñ€!ÿ
+peJ´
+ž]
+.KY¬Hü— -µÝÁ‹Q1v™tÑ”­îe\(d·dÀcîVÄo`ó$š³Y\r`ðÙJrˆ9rØf|ÇSÉf:0%ò«›Æ>žÃRÇ$ÂWúeŠü q Û4X0‘pÅþí7é/¦5SÝ VJªA¦Ä?ƒ°¶4OßÒ€ˆ  ýìåX¼Úìý¡ŸãJtÕ‰(žì5Šº¤^„£À¯Â8D”oVD6Â]3×2E”% Žë˜^Â/.hZI£ÃÈUòme.¢`ºwH÷”·ªÕ‹ðf<¦ø7Ú)E'+Ý¡Ìn+’ò{!{ íð[ó×gZAßY•Q ôg¨Iî¹èý¦aÇP0¾z=(šOpf´1ùðëåÈ+” ¢ÌŸÅ4¢l6ÌJ04iIÕ<0ØÃråÐîÇÈÍã™~Jv Ž‰<n&õ«‰¿}çgÌHÅz!\|³‘[°^²7 ÔȈgXª±ñ.·Þð“øÅj%Øa¹ü"½ÐÃñSüÖó“xŸ¦”…²“ b
+à8_dHcjóPâ[QÉ\FáéîÐ3År39€S„¿x"«¿ùÄÒà\ŠÉ˜€ª‰Ï½ZÏ,1þŽq(M¬†nÚÈ#ËÈB¡¬nô'œ@²âé}puxà[@"¶:][! Ò–}å sÅ"ÉMîðPUO{ÝÂp¶e™Ã5ÙQpÏðÆ™
+®%‘õ;µbˆh`â/ï„v²‰±ú¡ç Ò´}xnfþ~, ÞÈÌzwNÒ²ýµú9¹ ÜØ/"F2C‰h¼4e*j‘Phé×ò÷ðq€­bmy˜M2·e9†¹K ›Õ@/ |‡¨ºó6•
+ Y1“ìfƒqzÎî¡,´G¡ãÇ >7Š4–yÍ6o˜åSPYx3ç±·˜üg;W™è—ˆ;¹¡7·K\ùÒ3Á±7]¯š”.±€ýh D‚‘š7¢LSsM­‚¯˜sm~ŒõD†\J~
+Ë~9Û"3G¶Kñ+³^ o¹7ã
+ùÉšMTSòÄ÷ÌYÏã÷ÝÅHzŠ;(ü)íi‡5ó‰GÉ'é$ÇàÂòØD>bx)3Ñ ô_%Lĥ挖Խ6cJíqèý9ï/Î!î4JË»(HŒh«E¸‰•°ÒÑÒ%^†ŸùŽõäúöø¯ËŸÞc ìDÆ Q¨¥Å‚!„$JN`Ã6ª²ìU¤®OþnMŽ-ø}ˆq„ Ö ±sš¬ê‹S¢ö£0-ò¦GHT&{Qäo÷§. ºK8Ix¯QírŸÚ_?v3äpÛÍ4$l|m  €
+ƺ€9Hd”Y|yˆ»Ç”só؈Kr‚ ÝÀµ¥›¨žC_‹g¼;'.sAÞÌ®%²¶Ú«®ŽB46yŸò?mup1iÇÚŻ쿃7ÒrHݜݡ{d
+ ‘Öaòyö¡{Ä;B¨¸éÖw]ÿ
+g@Dñ"²r
+2> Ì+ÿžã1Ǭ¦¹9ñ½ >— É‚Îje–¯Þ…ÆE±òÙrLTêe¨ù±ïtöo€]ˆV¡?™Q2~Èì5[D{æ D.*c×;Slãq¸ψåBªuþ tšEn¬*0XÙíXQZÍùžÖPB# áÌæA.÷bü;Ò'¹¤¤ˆõ+³õ³Ì]’Kf šWé7¦ ÈL4/@œÝíßÀtÙ% åã$£ÌŠ;#Ȧ"`A~Ó>UXwê‰öäd^xzA`±¡òœ`¹›þ·)K$UmAöù£U‘ 8„C_>~A¸hù·­û8~
+âL““WÒd6íèÀË?÷ö"ù^®.Ø8Xth§í&[ì¼\¶
+1£C ˜“!ù5{‚i{a±DCópØo¿ÖJÂ]„éHDÁœŠîmÆF´^E®3°gؗér'&ÓzŒzFž“.ÛÇ9šŽÉé§|&R€ºkÀÄgFVÑ0Ûâ"²+žcs
+!Û»±$²¦K7:è’ O‹ZWÍ6áCîžžõÀùÀ~/‘[/Ž¡f2,LóÜ"ámë¶Ág§·aàqIÈFQN^‹Ÿdç´ò´IÈŽ‚  ¨„l0Dß7"Ö-Gmù ,á÷ñ XoìÉ W¡
+ì0óèH"Er ´æ±(!i×¹Æ%áGC…¼Ò‘¢ôào¿ö±,x‚µ¸nºžŽaShZ!B·+õSÅåñn7­b)sÍZ½!rg팡E›¸U2ÎÏhs]Ä]”ȱûž§$vJJ«û¥`_M}ðÖ&OÏ-&jÏbáÂ^e)9I­çS¨¦¥m­Í ,QCk„Ý…‡d,jpݲˆûAÜ8 ˜Éƒ¹>]Ev#zºsáëÆå …Ý
+®ISʳ¬\ÿ·Ÿ­Œä&ÀRÛ3av¼e·R2<hÈ4X8XQ:g‚ß4â3±ù CÁ1&>˜#èø\=ÈbB¡¹)=öלšŠ1°¯ð9Ý°ç!!‚(?X×í cÉ8:ž>%¥ y §h¬FkÔQo-¶dô÷yÇŸiÄû|„Š;ùÝWMÂèdt•œK¶è»{X%íÆûzË{š;|†2ƒ÷`7v!ú‚O‰6ï1à€4¿«1vC²ÞTÇ°6OìÝ=‡o…Žƒ{Âg }ˆg"ûip­gÒ ¨ë{™„¦ÅQ±ºö¢Wˆ;ç÷ˆCdZ[1üùÖú$Õ>ŸÃ太͇£×vö߸à†Ck碵ŸMaÓ~u€çøb§ –6N;Gy–‹ñËqŠËU’<jk€(¦Qç²<òg]LMçbnâ V·ƒc"~€<¤i¶ÚB(ÄJÃ)JìKä¿9–™›&?î{‰"¹Sñ(ë”àcl±jÈS@!‚¼ŒE—•ˆë¨ÖS$C pöš¸Í̓*Ä'õ[IQüú\Jä¼l€K•8Dõà7å®'RóˆEöÌך\4öÞˆ®NìDeI#IÔ1{ZM"ñ·œ0êh©×¨A×Èî€?0¾ÍöSŠAZ+|r¶¬û׬{ÄA>^WïžÃ0ùðƒÛ{+W:æ’¿¬ãèpƒ“ÏõÞ÷«Þ÷á“é.
+†è„ÇCd7"¬h¡H<Žs•2„]÷+;í|Âã( ¨Š¦jš”Q÷Ó¤F‹qN,°ös*GÈ|qåAÛ2_àQ’*Ä3‡z”¨Ãx)é«›E
+ öªÕ¬Xô8$d9Ìœ°@›MÑ• MÓø@tò£)zÈ!©Mìçkm@»ä X!;g· R"RäK2R
+² or°ÈO
+¨ p³Í•U,'Ú¨
+E“CGëte9ÃøDÕ~.˜]K±ùq¸i“UñÉÂG)°®¯b„&>hñ£ÚÂá/ä#m~Ô“Úð‡LÂ{‹DZª0ƒäk&?þì¤ 0žY˜j÷Û(_é!^3ñȱ™Ñ¨<Ÿ|³¸>Yu¼îC9I¿{tɼÊCÄÝvõ|N†} I*ü&З"׊ŠJŠ"´a¼¸”)‰â’ŠEг‡Ø j$K„ÇuŠ|Ћ³Çc’æ„cãb=O…E"WžÀ¤)‘·7bº%C1^”ã•XãMõî1U›™b|+˜Ì@çS¡[¨Š)–¤òRl ©³YG¢½a÷P×çˆãùK­ZËyÎweŒZl‹•­sós!ÃKBðdå×ç°zr"ÊÎOÉ:8ƒŒpû¼»Õq=~•¬Ö&KÚvSÒ˜l#ÔµmŸü ȹÑLó”ô¹ÈŠãuˆŽAµúÝXxžNÖ°õ`
+êyµ$î6…û[Tª,xL…MáD5ÑÒ¼£›ÃˆûG¤³8~\sv‚¸h8áÚÙßë}Íÿq¤šÌ€/½qm€HÊÚ1íRÕÀ#®ï0{ñb±=dÙìâ ‰#Ê]E°>Cú_G‘"[øW4AÜP~h ¿hŒFÔ×f€Pß8úJá:4×îei»›O ¿ô³…á” ¹XäœÙÛø|TÝÂp¬ÐÉßxƒó
+Æœˆi¡aÏ*<QÀV·ÏéŽÅEè·Í÷œUd¬%Y=Æ»¡'³ã#÷«Þ7â_†l ¬I±—b4œó)’[TmE´áðrIzÏ]ïKÂ6Rµ’àÛK"MÌgˆyÍ= Dc§)"ª™³²x¤¸¦Ñ³å`4­³)ÌçtŽÊñJÊ«ÙB`±C¤É’$b ©ÒÙtI5$ãU‘=0¨HýísXéQl¥eÓÍpnÝ[ÖÁù Z‘_ø ¬W‘
+BÃrtî“F›½ÈË4Ràäa†ª>Yw
+@„ýþD1ƒK·jý¬[Æ:x6›F³C
+1uµ¶¥ª °)²›Ö2íYl½m}-¿É‘ûeŸ è°?õ0E–e'ôºÄÕȦ S\÷Û9-ÿß±÷. ÿɸ0€!LIe@šÖ„ä–ŠÚ„Ét\ŸZ= Áyù„6}³ÃǺDÅ{!W%×±†3  Ë’pÿÄññ?ãå’gáä9AŠ·Ð:Ûžÿ6_ƒ˜”mþ”g55–A«Š?{ 0Ó°&-_JâŽQ¨Fg™¿<­ƒ…D`¹ [)¸Ú7ËWàx
+’†­¢«¨¨êÃãM
+èŒÍ¤F­†dšm¥a`“™³ŸwÒv¥RŽCÚ(g§ÿ3û?çcp5z‹ G‚OrbëG ÿï»h´©T ìR´JÄI0;á€øÖYš{,e— Þ””æé{KLrê‚U”<;ÿDï/{ä –5“<=k)î.L¢Q—*ì¹H°ó°1ÃŽ`“ àš‚š¿%E²!h5ן$ZeiñRô¶‹ 0ºbVj¹­XqìqÊg3t]{sð¸B¨’¶i3…‡‚I–Äù¬ë1<-»ÀÊyXô.a•_&êÝ­È„WÌ"Þœ=x˜\òC‰Ì
+þ“îèVd.‡Aè^‡D‰ºaÐÚy¬‘¹P9<šBUÀ<$ŸòñŽÌÌ|Û¼«ÆÉ_°|RðÝØÁ+0dÀzP“5cæøÆå ÿGòïÎ'1Šø¤Ò.ì=Š€s}ÕyH(ã¿Ñš¶ú‚øŠ©Ê€«×–
+£„oR?Ì€‡‡Æ_ì…ù–yQf8‚©²qTÑ@Œ—Œ`‡éç•¥0ˆÃ"œ?°^V0Ym^בõ€}åVÛ ±i™U´aQJP¼ÉèŽfqÓ=AÞ.»d~àC  £ öA‰´é8 Ü^§È(ê‚Z”
+÷b[9  ‹EË‘à2ªz;Lð©¡…*¤UXÌÐ+#¢!åøjm*ÂnXЄ]ãiü‘a'!`¿Ü‹>HìÛwtxùT
+é:„QÆ2ÎÜÎ/%•±¾_‹$daîH&T¸ÜœmåBž¡µo}Œ?×í¾Qôņ¾=9wÀ´hÁå~†l•fJM‡P–,³ ܶ–E¢Â_ºÅÓ&Ý,ÓÀtnà«‚ÌS<aǤ;|gŒao{Æ¡¾VOúl´ŒN‚†©óR[A@¤ö.†Í~´*‘ÎçȨÜpÁ)ûùW€
+H‰Œ—AŽ\9DOà;Ô&!R)­=KߢY¹ï¿Ç/þêq}åØ §³¢D‰ ƒ¢¯a2çÔ¾†üK›¾$d¨ëìSõãû79‚¢·nÓÝ›ÛÇÏ â§üÛ瘽@=LF›s}\µ6ÍœmÈl=Zë3ß6}¸ŠpöòW†ò×ÔÅ \Õå|Ž¿¼ÛZ>'7¯Ûˆ £qí±!¶¦·Ö¤­:e¨ñ®a¡¾îP}¬îmõÙtƒ:o˜"sÉÔ}Ž.åÍÞD뜫›¡ìˆWØè>9z4ßIþ’µ^c‘[=âãG‚ÆËW³å®–•øCÐ$œ÷¦YÑ z„û#P¼b‰¹¯ˆÙbÞ_«¯ Â@?¾ýç›|ü;¡òZFa­É$ÁWªT”јÒäãïÁÀª«s};€.ˆŽ€EÍgH{!úŠÅS:¤­¢Ì.sÁõ]\
+nyOŸ.}×e-ó˜P+Zßçøhœd™ƒ RÞzöµ6$´5W¨ù»ê>@ ÊZf ÊüÇu~ëtøu
+¡^Hý»!”ƒáÆ]+—°¹ çªP´vï1׈»æt‘z·qGa\"öQÔñܸêIl0 6 9óïw<þåÛ¦|JÓJÚ¹Üò‹v僜ðRþ–ê9ºµ\°ý~ –킬mÕÍ*tð‚det =õ6E¥djŸ”oÍF²Y„2Uz¨æ"mÈ)Š³ºÒL„1áôÒw*M9HþJŠé•–+” qC‚’s1È·!(ô¢iŠËù
+K©Í&ÎÕÂ\tL9@n±…{¨ŸõåïÎ!Í}(aë6‘Ú4®yÔøW¥!*Èšù;ñkV÷T¡HT™;)è—S˜{€tf,cŽ›h5ƒq žîS¶ðƒÀû0׈]Ťxw¤Vºß¿=A—!¢r˜~P£vˆt¡9¨øÂw0ì1åœLãgPG¿…a#˜2 Ï1zI¶&Å`@ÃWÖu çjò»üCuV‹Œ1rH4ãï k N)OªqAÒQ¢¸Í¥aXenÑû¸¶! Šàc£Ý,h:.IBÿµCÑLÂ@‰9JXÇ“Öx%c.÷er@Ç[žà–áPŸ^:E2 ÝJà9°]S“©•©ôxÇ##¾Ã o@)t¬t܈ŒýÜ F
+€,Nœç5VŸ|ýkBì¡ ßÖËs~rªk¿F$A –ŸþJþ™Šä¤TxΡ§¥)v
+˜»
+¬Y-147 "F'‚ÿ_LSwõËÝ V¾ÊóÒ…€à/#öï#•¥È®nªÚ‹ûaðÊŸ^ë÷ /võÇ1Ü€®t­JïvÚu§ò
+‡fJaðK…ûØ4„é2xhµÆÕê}ä´(Qèdç˜ýsëX·d²P¡©û$µÑݲze¹ÅJM"”_HúýÛt¦»B\T#_²Þ6ÎtjÁG¸?}‘…Sw=@ÿcüÙd#-4Æ6Nœ½d†ÙÖ—!û¨³‰-¸T–™}+þ/¤½ÑO»N½=Û5ÖXxÖ®-ó‘Üq¼]y²µðCÛÛ'I0¹ž²û™E,=^ ½6i .Ë`x[܈L0eÒáX—šò’âÁ°ÅŒ˜@?w
+)³†Ñ˜ }k$%ù™uK!Ë{ˆÐ¹ÌâNo7Ê< ¦M¯m×s1a‘%E2ëé’G’¨ËÚÇh®¤i¦Z=×n‚ Cå „÷1Æ{Ã>Q¡ |9:‚5 ™ûœ4ˆHÍ~O^‰NÎŽºmH®½ù
+hñô鉒´ž{ƒW¯²Ï1Á¹qÕ³å–0P‚˜SÎôûÿg™I2
+ºHå$Åx´+©ÈBW·BŸç”Úöû!P˜u¸xËV%Sˆ‘p/<e€aùn±G£ð%xÄød<³ ûo*%yxžÔhÌã9[éòyÖV69!×J=ÙŽÊ41º§qÿe¼Ì‘ä°‘(z‚¾CÛ2Ø4'4&Ý9C^ÓÔýç}d¢%V¡H2B U1 [þüKyµÎÞÊ ‚™Q¸–67q'Ûpç,y('…fãǧS45êf&æã‚ppüÂ8áÖnJx),ã´R£$ñÁç›{IV,É‚•>ÎVOEL$$­^Ý×áÊ `ÈÂÏþ ¸\,8ÐÜÆ 2À&(ç0Úçø•Âǘ'<4€‘’s?3=hG¿¦—`fA"†:•€ ðfŽ)(·’WäôCÑ×KÑEø\ö& Ïz)¸Xå@óaTR(Ú‰o SÈyHȈ ¾ ¢]ÂxÂS}rT³¤qx’Eœ„ˆ‹oÂ|ù:r#zéâ‘‘å4(š^’RáBríR­@Æê㶭 ð6ttÖz$Iˆb0f]«Ø8%;†aHÈ"ŸüÔDÇGî¥3ãP<`&lJ¬jQ\œæ˜º|˜ð©„ç^’ ¦ÝM° {zC˜x®ù¸×@Œ#~ÈöV‚{x
+‚', D0î`¯ @é‚?ðãÜwçÔO\ µóÑKÙŒ%²Óÿùö\´ѤoèwÎOE¢TI£}3.M7°Ʀ\¢!Ãmy .u¶$bpµÂ²ïh€^žó<=g“_©ð?µO\Ž~öï^TÀò,RÒ;³P’£"7R‚çè ~åè;õñÅøºð´±‘Ú©YÈ‚ó‹!+-¥€!b#ÐM*eß2³¯‚¡6Ú=&‡IJÚl”íb)ÑH ú‘ƒà‘pt„¸ƒlm>XL%†¹ U.E__‰ç0‰œ’ýˆ¢žra6r
+™ø¦…böÕxà Ã&ºïÕRÂÐàg”$.…ý.²¤Ï€ýæ0¾$èäö’Ð$Rª[%)aœf–¡™/{õóžÿãçTjFÍÅÕÖ<p4<„_o)ºV ›UŽŸÃub÷$`Ö½¢añ<±fë(âÝÊÛÙÁºMð°ÇûüÛóî
+ŽÁkÀ:#æuÀ6ä—rpøT"Þ­è;2rñT”83tl¹{çŠîXT*£%ÖN /…žŸÄ ab« •ÅÅ€ôfz|?ˆ%2”¨Q’Û·+÷>÷ýÂá‚V„f‡;‡U@ÚvŠuDÕI|&òKh¥ 5,ØW²†ãI’'ß æW„+
+ð0 ·ÄæXÅP@ Y>Y^´‹Å–ã\QBrÀQ)MEŸÈ$ka!’3ëOEV¥ÏŠÃãè5~£ì0jÈ#Ä÷ñ¢¨X°¬–FÓA\Ó—g7[Y@º7ÜFÀ–µ‰
+S·
+Ò‰<3% Cˆþ@ÈgŠòHX ’^¢×4f<÷|)Ù½h`§Á×°ã}öE,Ëð¥ãà3>C ûê%Š@¼hkÇëÒ¥”ÅoÆCÑŲPT¿E Ð~¯fûK¼ “¶ÍkØ ¨0Ô”Ÿ=;w©¸¼
+¨:³¨¨cL<æ
+VT¨ÏJбãÿc-ÞfJ”ààyPæX&^€Õ‹}óødF¯AiX:5Ç¡™U +í,6Ãá¨Êʼ[‘»Q úƒf@Ms\J¾ù~ sÙ¦ë:È9æua›F·sÈ3§™‹—ìÃÊ[¤XeêÒ’Ãú­8ÌìBCýt¾}ð †^‚ƒÌßX5žxáÌ9 ž2J~Þt…‡äø¨Ä2× 3»ù›ï~ª©R¡íî^TBû 6TqÍp/Ðo+bßíÈÊ{ê14c)Wãó}<5^Ï +CžK±LJ¦|Êeá„]Âó€è©Ç°t‘dÝȲ×d¿g‘)¢ï0w-BÐÉC A³>^IˆY˜iøfÐHF`†ÈE< „zµ8Ž°?ä,@Fêìr72¬§óeß
+8\¢ò<”&ohÜ¢ ›º˜·%]ô€ó]A_Œ ž+ (Q¢Ô‰bó'©`[ã© ’9e¡sŸ·g°ÍA¬bšb 0oAp¹K0{õüòPrúÍÅAd…X^­#“2×XXNÄ£0»7£c“çÒkÕ‚–¢ ø<m ÙÍðæ ,eá&Î4årâT¥Ûœl´ƒ=Ê™ŒÊE?nسx’Û2})u®Áh3] ik³ COG´Ã<*Mé"!Dé]£Ý¯ÙQDŠdO)1†ùóà±DíUy
+SØÖ1ù§š,Y5l\‹ë¯òàw¡¨Ê·Ætœ~SÚ.`“Q4ÔŽÿ`Á‰ ÒŒtz%û¤_õsÌÅUeEåþ[?– â ‚œ~zÅ Q´ã@ö§9L—`Oç¦1‹V¶:¨¡™%†õlMàœu9Ç£­C>,ˆŽûL¶7߉&ZÌP·oƒ0Áéf?Û׿V»*¾§Ô¾·˜äC»¬‘Üv5¹bCZžÚÕ 9üém´î·«Q2 ¹!{½X”³xnVì¡]íE)XQ\Nyh;ì…vµ¬ŸcÉѼ#0÷mø{ŒDU÷»ù-·Kjéj×äw¢ŠN oYAá› 1~‡½¬VšÊˆŠú†Õíh2Ž²ð/hl^DŸ^ü€ê9}MÄjøñŠÛ9ÙÒ l²®ÁÎSüI@¸¿±!ѤÁ˜´´럋IJ—c"ðùq2ÜXçÀH)œ1ÕË ‚¸!Õô-äðø•,2)0r¨«)7ž:Šé-ÕZõ–qœÞ±õ@Ÿ»>%¶“NÞ@BaÑû†¨„C)g6!üŸœ$¼ë#Á%~a«>„Ä^pºwlc~ƒÙhûSó¤˜Ö↰Ì•Nn5{€`°pbÁÑ¿>u¡+]-³KtåR²¶ˆa{ŒßدäF­“|¡Fžò¾
+/¥ð§©˜*f‘ÏY~€àp@,Í:_º¤,™AEGÛ:_õȽÊØv
+÷Â+Ò1
+ƒAÍT:Œ=]</!Û²Ýrf±’&Щý¨òŽ" Þ=g\y>W|6!" ŒíòÊÏöíâ9
+r‘˜o¼”ô·<¶ô
+r£ÌWGö×qÿþß¿þú{¥š!?2_Ë_¾B{
+‘˜ÔI 瀘x|Qnü’¨ðcBºr(]maCðg8gE$•0FÒÉÍO5Ò˘§ÄæÚ™^Ù%þ¥"$M©9¥ ‰¸¶
+z±¡c9‹sZný)b
+zê°¼§7[—´š4n½ŠõÃÓ`]Ï1,é•ÕÅ;¿AöÃß
+èŸóÖAÐQQ%$ÆvÝÛ97 fÍr²¬÷úÔe,æË
+
+U×ôß@d ¶”iˆ’ÑfS,/ý~?Nzã‘•^øÂ>Üqa°c=3ÿšä§@ `œêºeCp*'œ–Aù "\ìÇQ|b¢Ñã?:ß@ýëêQD®)ýHUnQZÍ®~ŒbÇ<$3T†xÝz{1­µáŸS¹!&
+Åè‹.ØÙn¨¬øšqy¸¯=—úç¼µÁÓžK;}í¹Œ…§=Î^´ÇAܵçOƒüÚƒEA ’TÖŒyÚsyÚßoêˆð[õµûŽ³MÓ1Ø“öpSe]Ò%tæký0Ü; ’1ã ÃTçº=H–‰ŸÁàÕèŸÃ’´Œ*%úÚãŒó]{n OVÒ‹ƒpsü&È—>Ç­sC jû ˆs«‰t<i¯‹róµ‡2f d,Uò5ãÒ_{è*c@6@êÓ9øšÊŒàÍ×fŒÎ •L‘=h£šPñ˜
+nÒמÛVܵÇYœ›öüi¹~iµžB Ç]Pq'€_C¯ÚCcBcª±@DGËÞ@뤄sM¤$¯¡M< ³Ž=2ûÇÏýb>Ú);ì§0»O?¥ÑUˆlÞ¬²¶‘™eô±@…–R|ÁÓð^¦#Ú•öj¯FÁëvx`íJâµâŽv!úËzdeFJšL“A6€1{úš
+Ýå’¹Õ’Ï6è`Éf³uuHJÚï‚áŽÞ2Ò¹
+ „¥fD˜‘ì7êÙñÖnï”ÛÈ\ïâŒÞýMÎ_kã,µÂZ¨ÿ¬½3éÔâ×¼)[H똭öÞÝ@Zdñ¥Khõ±@ ‰ÌJñÛ 8?†ƒ…|°Øî羺¹êÏÐP»PœólÚŠGÂ&ܑ֥_æ¾ Ñ¨eŤ³\ZÚ„£Øˈï$l¤}Ž5<jm´’×9¨„MøÚ..>¢u›iþ„ˆ~v ûSØçÐdÍûÓ1ŒqÏx¦-Ã4kñǽë¾YD›8šº3<×Á&dyôµ=<Ñ¢ó»È¸ÞÕ¾2ÒÅĨ|]F#ôm\3((m`—ª=œ°¢Í¬aÌÚYB3þ„´ÛkYþ¢Ñ'Þvö+fžUd¨Çú–¤š¬zø2gIz• Ød§à<b)'‡Ò6>ó©ì"œäwýÃx¹$Yrë0t½‡ZÁ ý?ãzCUûŸ¾‰j»2™öµáð5Z)‘ ¸lóEÌclë¥wAÞÞ>÷è¢
+ÞpÝ@{³s+| >“ÈF2âƒ;IyT=`Ì’"ÜÇ‚$\ ¡ƒ ²°
+k™X“‡_â;⟲ï\!ˆ F‡¥+ÞM (þ|âs|x[â–’«…„{e°©D*‡DMûÔ¥¾@Øš091ÏÕíÓb”¸ôû~Î5÷Û8컿Êa1ÂT!x°p…DÑÛäŸú<ƒÇmXb¡Ì>ñþ6â$Y‹<4²¾Ñ¿‚\͸~îúzçN¦EFÆð?%{g}¨Pý†ò³ QÆG&ˆFíæWg
+ÚÅ°OTÍ›ŒnYc“«Æ‹g‹á¹ðKfqð”ö8À™O Éë¡çæ0zÿ¡EÁjá’uë¶!•#¦tÞÈåÙ#´Góó×ä—'Á ö†ßÞù
+ÿ_Ò½>Ë}ˆUpQyÕUø” CŒS‚«ÂÇÆKy‡§ð‚àG:«‘[%OÄÁfÌø+zßú”¶·(œjŠÙ?ÊÐ!æ4±Ï=e„YnÜבž=#)§Æ€þú
+ˆ“½©>5<ì-ÒçÔÚǽE~á`ôÉGÕ?'Òy\R{ñ%óJZ$éõ‰¿a<–‘gÖ•GªT¼‘¿`<•’G¯øà>|‘'ääXS>?‰¼riê\;}‘§¸¸Ò ó0ÎlÐ9:Îý™D.iRú ?á…Á¨ü(ÁõUžb儽`ú£Ì‹e™{$Û“y1y"è%lžÌ/ˆ$“žõ*Oæнåkøâ
+VÇÓ9˜*Œüx» Ÿ8+íTã(ÒHDH3ا2Šë3¦(žé*SœÉúVö²‡uÊíÃÆrüÜÚ-—ÌΖœ·½&œÁe1ìÌmNçSÿ>‡ØwÜ°FTÿ„´«â{ƒ˜Õ1Qžçï“ȈbÔ;E9Òë³”?ö¶!è?Ƙ\ÙÌG…ÊE3^½u-~C¡CSˆK;
+6‚)Sñ¦yû’ì}lI$:‡Ý^ø•mm ‚Ô¨*‡´}Ü;±ï Íšc²­å€z¦€Jˆ*×—ÝuR*‹ö­®7—¨ÆO{V(¶Ì‚»ÑU>>ÅBàOV˜F ”è9~Ìw ê+h‘ì2’FŒK× ‘ÊP/l«ÍNM%¯î%Û$€Ð_xSðx܃xŒÄ>ísJ]4ËçÝ…IÿøTqŠ~þºƒ|²WÙþæ~½¾ òðö¹·@QðfëÚ~d9fBî<NçƒßʘFVŽÈ< ŒQi®ðµA˜˜¬0×Ò<™µÁò±O>„Í¢Æ'7×k ²RX›ˆ@ãAVû ¬ILéT¤òÏ©òH µ$ÇfmÈOärí¬§QBÆ)@¿Ýþæ2aíëŠC¥±uãmÐÝ’\1Ë“¹º¸Ý­<ò’âbφu¦ Ñ­´!ì" ®Lé“%„Ÿb®èŠkÅî€Ô´[‰•í×w?Q Ê
+{q ¿7/Z‘Yö» )äS,(¾úx”0tüÛ6Z@r óÿŒ—Ir%·EWà=hì›±<ô.<}µÿ©Ï%A…_&²¤øáoW "“ÀÅmJR¾:¯J nX;WQŽ„fât'¯M,˜€} ŸA7
+ð¶G±üyH<æ. ò:23Õ|æ ´3-<èÆÅ¥È99 ά¢õQXt[À×O¶t-óÇß*U¾ AI §ç
+h2p'†ˆGñÉÈí^\ ‘N#â†Yˆ“NZ B‹ßˆrΆYªC‘#vã²€,4…ôçìã‰õ;µapýi};uÙÉp
+ `_ì{Ù1CŸçª9‹å>mÍiÓ2÷©ï©Ã°…£à‡l½)¢ÁÓûp0¸:<&Î A<=`°Á8C8ÿ¼üÿéêµk0 ‹˜Ça„ ‚Ìa›5do
+à`ŠvÖX ¬
+Œ¾§èõ“åÙ;ÖØ`•7ª³ø{aRy„uõe›¿X¶€ñ&²”@.p=KÔ½nkjñßP‡ &E"=Áœùk$€{ §™­ Xº¢h´lýˆÐ ÂÖÔ(±C0E«NÑËŠ
+vM
+3Úž5|)È"nÔ}Ù``c}u}zz¤;Æ#déõÍ u`Å“u0º ”.ÿxã¼ñE@µ¡²i”韃 "ز¦ ÌfÕ¦€iæ¡i—”Qs°8É
+™ëkÞƒ~o
+Ç}”€{ÌmÏW=1W0Qô¹"ìR¤³ž·"úÆÇ@(˜©—[!g;¬\°ïb ñE¤ZŒû!ÈŽÅ—/1_àH“q¿–5LÜ<ýEAë´ÉÆÙ5a¹†Zýqƒ§yßiçç–Ø‚b¬IáÙ›ãvï"öÖvÆu‰]TlyÊg÷Þã%€$ïü6bEIeóÃÉ÷s‚è0³Jnìjy?
+”§Ôu©q½ 5)­h
+zAË‘oàKÃ@ JJ¶g1õ,᜽}ŽüpáGiT[ Uô‹0Ò< ».‚o’„¡¤ìŸÛ(—`>˜½}®”•&œš
+1
+gÿ
+éKð¡¾i-Ì„äŒx™ýüw#Ë{ŠÄ¢ŒSÀX>G©ä×9°'¤ÃäßÒ<&$›Ò)Á¦íµÅ³^EŽ®´ÞŽë›hzÈSî¾ísd1
+¸«öô˜Öß™:ä”gµC‡9"¦{9ãyBQRL-|kR`&ÇDô»m…I¡‘Æ_:L{OŒZã†Ë•K0ãµÕô=*¬#g?a‹º×=?h°c,埠B_’á¥ÑfG‘oX>BÝ{Ë©LŠù«ÕÜÜw„qoÖCX ^Ÿd2m¢Šª“QÛ±þjXÔ[Ï[糕\<îT{ëRjT߇âZçîV¤(*ñÎO¨vסD˜Ì*£uŽÜfÇ<ñ’a—ƒ^˜u‰X´;ÁΓ{Sûy6BÞ ©ÃY%Õ&~žQW
+´©Q‰fwr@üIPžÔ÷±@ȳc›¦b0ü<;ź!Œí¬(<±!Ø:j°v-Ÿ[ᮧX¡n£,+É]sëu3îR…ºc[Æ|ÍzCÍÙ‡ƒx"o ßh9s(ŠfëSÒ¸˜|7,ö/$¹A¬ün!
+§"D à ³ÅQÌ΂GdÓY7„3´]7›/Z'ÖÊ6èñ&tK"›™Ñç0Z•Úµ½NfV’âÂÉ\©ɲåH€‰EЭÂèC¨†toU8ù€™#¿Y|ÉTšeXWƒ”wu !‹¼!Êe˜ñÔ»[ V˜ÁAi_aj½_!UðŽ Þ™ý4JïǨ f‰& ÕÞ6ç’àJ9œ… i"S\šs…¬VìC±‰NñµÓt±EU:Yi§~
+¬1–Lör ÙE¶¶@p¼¬^Û¾úävaÁ»  tû9Æ›‹Ûf?}U¯ã¯˜úÊÀÐGú”¿ K¢ºAÿúëDðá¹'ùh‰» ´ Y«öm°:õQÎÊ5cC"B…kÓ:\zË^i[B@òFümG1h_$¢+Rä½N‰2#tY·Ë+²X-¬"ÞÄó/9Û
+ëT’f!§uäþdjOO§A:ÅPjºCÓ†©%û¯3•òϹܧ÷ÄwÄ·JÙFW Û’Ý0ÄœêÍ;ŠŠË<9êá_‰ÊApª
+òÙÏë]žf¼¯eØgrè7ïWqÉ+Cv·¹…º@l«KÁ½u.mãæÒ~þ­.mì½Îm®oüOCµWÅb]‚€Z-ñGeŦV^³×ð»ˆÙˆÝýv@.i\·»>r&£ü^ø úM¥y~(#°ªA°ÐqˆtŸ”¹7Ìï0¾ GxšÑcs¥˜±*'?Ê<ɱîD:øN"¿{
+‹Ll’pW²Š‹ElInHþ:„·‚ìŒQŽ½ÁåbïÑOto#¸YŒÙÈi_Šd|°1¬oü…ÌDzZG‡iMAgø‡i¸ nO&œÇGÝ/Õ”×:ïŒã÷—³ˆbdÐÒgµ2T©¶( ƒ`e90¾ÉɬRÁ;ÆkDgÌO1ãÇ v½¢øen»/. z2¼V)ßÞ§7ºÀ4w(UìªC?/¨ú™®ÞÜÂY}óõ‚9¶†l{Þ‡³Â¡4&ÅÙÅš…”ª¨Ø BŸé§2™Õ“(Qꪪ±¾¨C™%æÓ;÷e˜AnUð,vmÕ“u1:›È*½Nu³Ûa˜/*¥ø?ãe’œGnDáè\÷‚yX:襶>Â;jéûû{@‚UV‹
+·Õ-=¢€ÞÀ}?~ÜA~#Øš¨|'¦Gn¹Â;õÄÈàà°u»[ÐîV#­vœÈÞb’)pþšiNn·Ê2Δ¦zêV¡édÈ@x:FëÚ-nÃváÁ1ë~™¡”P×ä6žº•U d0òWíÊ4´a§û„Õì6h"Þ¿"Ö†°wÞç—ÝkÞÙjyWk×äwû
+íÀ)ñy·^1>Çÿ‰¼7Çgt-ñjX[|àx¨)‰¹žŸ‘§Qõ“Åu9ðH*áÇ€à_9›Ÿ,Ot˜§8a@
+ìuñϙﴆÕ@q’OÎ@ø湇–žHüN§ù±ú@ò[טÕ>CôÙ9¼×‰ä°œÏñ$J*EWSÍ¥ܢÕ!2öî“<ªŽ†
+ù‰6ˆ‹ÜŽìƒ¯i>m„w¦‘×39õäE}Ü4ã®g¢ ÂA =rŒî9¢-Nƒö%—åhÚEâ±=±üävB{“#þUWß9,9,/HÀ%$¬¹,¢ÉÓTÉ{}hWV.`µ J\‹Û. "ÑÙiiôz±IE+R‰õ‰å©œ ­<žÐ"”pÂ+Ë‹'sÓóÈG
+fžæÕ/ú½Ÿ“º2+ ¤<]&ö‚Þ¥0ðdŒiwö‹ãŒàµÄä¥U¿¾3Êšú°§>q‰BW1¥^çû˜ȇÜ~@ ºUFF 'ówåT‘ý®i…Ý×B¥!ªi}—¢ z2;‘ßqý©ÎJ
+_GóùüÒN_.ûàŸC4䈦–Ùeð4¬g-¤
+„7ð“Ü2Ú‡0!ž&ÈóPÕn2DêeØŠ¦òïfjßaÎ|Þ4Cç·1#vu¢w”b–'Åûgáü@_ÿúþø_ÿýñ×ÿ,6X ×TÙoXÝhS?…»jü¾äöҤà f€…ß6„.á÷{8éh*1€6—\
+±Ú­ ÀO5rÌ>'Qµ'vS8 "kEÏç݇9QHH'ë@¬Ÿô4:ÂûÓ9/-wns÷U×tªãMû¥Æä¥W¿¾³5Ñ6Þù‡÷V‚ÃtÎû퀶å`±!u,'„MŠº*ëb%@KRÆ)-:A|ä‡rˆõ8ŽkhÓÍ‘5Ö‡?ÍnøS?`Sˆ—ß¼œéµÞ±š2† CA?|Ë¡Nâ,ÌÁq¯ö§³MˆœYâÑ曤Ä*Ko\;Ö— k lÙ
+\ø
+ÅÐdCࢠntò4*ò-•o{“ÐKã?]<yãaRÄsõÉË@.²fØ‹<£DtA˜14¶Ý¬3
+!†„Må Ñ sÍR8û‚ELCnW€pÎAƒÚÉüÄé_%`É~ñáM$F&<ˆ÷O~i€°Ö)çÆ×;—FO]A|!c˜ÞüÛpפ0šGrßÄÉä3ÃQäe_ºÔ²½ˆ£iÞ›Wa CÎ+‹&“Û© Ä:õÚpï˜ËÔx—¹ Ÿ÷(gˆ/µq6áZà?mÔ‡TþxõGѤôÅÁx‘,o€ãÆS¡ŸdÑ”*Ö¥9 M÷zùX:°!$Vy„,î1鼋T37dŠI¥-Õª}¥gAc ‹}Á­Ekš@ºÁJb†ç†ÈÑš
+S™Ð!º3ê¼eƒH%A€Ü =ÿØ/§]IV}¤î€~>€ ²ÂdfÞg~¶?S<ÝiÁæ3æ¡9Aåÿ„—ÑŽB! DÿhÓ[ŠÀóþÿ?í[Œ^IöѤ"v†öŒJL€x!J•À
+H‰”—Mrd7„O ;èó‚Xk–¾EGÌJ}ÿí| ù­*–-û§-—²H$­Hqñ÷¿ÞjëãÒ0mE4JÿÔr5•Ú[îíýóÆ»yÓÞ½”ú>!mH3qþ3!õªÃk—a±!]‹‰¯j ¢C¢¨õ^´¾ÿZ¡FôÒkç˲@ÖK­f¢]FžãWáÌÚ”Ûø‚t~[
+ì%D¥Äð.®'È å—U­–yÁçtw·î£Ž¨¡ƒ¯„E_Wã†Z¾ÞmÈEL„Ø;i ©µï8™$õÐÍò”¸jõÁëyÔ³ÒºU+P\ÒF·b­ù†Ô¥H¸xÿx›sSé·é¾oñâÞŠ«Ä*&E~Ào˼Ž\¥ŠE4~·ŠÉ£º[u2¬}ATÞD¢:'„ýòñö¿ ¦¤Ç5¢Ž,fñ«šöèRHW¼ÿÞ“Ö{ç}º@ÍcÀ¦AøyévÕÒ›7
+*û$‘ZÓxë„4jGNmÑo1†z_ª ¤P­gÄ,•]p8Š•.óéϧØ#ZmVFµ}_à|FGØ !-Ð`ðiBâjQ›4š¡úãí
+Á¼å["Ð檑:ëAtˆÑÑÙ-ˆ(Â@šß®c¸Ë¨5l; <ƒÌxCG["^
+ô©­)‘EÏçÔkÐß5û¢íI!0·¶€Hc#ÔP’ÒZi{ÎVG7˜³
+ÿ‚dj0%ªHÛÓø
+¼f2ÅÀG€HgÛC <ãsÉÔÃĽ“D$Æ)E9\ž’éÏ@z¸‡Â? ÜlmPÙÙfÇS 3æ€,T¤}_…òeO–ªº $ÄÉŠ­NÏA%îƒÚŽ„CasÈpg"à*¥òÃû„`îÈ>ÌvMWI©z«’-=餻NuXj#§­>~=”ýó&R@hJ÷u$3Sr8µm {‰œ·ð‘‚€öí—Q<œèÝî÷ã¤ÔuÏ
+& FgÀlöêôʱ*ílùž´òr«2…äd¸ôò\#æ‹Þï˦+·
+ûÝZÜ:çJíNN¤÷¦k`äûn”ÁbØ­¹ È^·nýýÐP©Ê%gÍ–;Ðßwæ‘8¿+™H¦Îb•¹³Ìôàö«Ÿ@Oãv‚,¾2ä_€:†=¹Z±-7è)Ü?ƒr³°´sâé&[O ²â 6€:s dx~‡f¹÷¦‡tŠß—8õéѧÝ«вnl1+Ý`œŠÅ¥ßŒ6|ÁÈm·ºŽ¡>P¹Å׺ÔÓÌ…¨Æ‚¶QI~> v¤y_ÖH-ýÕ1N/VYé÷9nT‡Bä}ºƒÛе™=ƒÜÚÎ1]šÃ×Û1};D|ºˆ|V
+c*_ÇöÊ䔜û%õE›þ`ýìzM[9liÁ÷mðÙ…—q£ 3‹ŽCŒ¿ô)´&Ý-ð€Æ€N¹çø6si ù×k]§ âð9^c—+‘l¼€|£èÇÛt$»ÍE’[3å_€žðî Q8öÖ#h Œ\p! {m®‡€¿7?·HÝ= ÿœíŸ „dÂtØx/hÃÝôÊè FÌœÆ2¤6ó}1ÜŪÏ=&r9<ÒXUQQRõö"†+fCüoˆ¦_‹|ÖÒß–C0I”›ëÇÛtZ‡¸²g’4ïòSPZ?)Š×Îþ|ÊÑŽ>a7—ËʽŠ6·Ø¶…¢2†zͽg4xnz?ÞYgÓLLدªSæÌšø>'{#UÚ÷¥À*áÌKRlAMxRÈURúÒÙùAÇ
+™g¬ŽMzšÝ ž} âØGAû ŸSÒk§0­HB×å¨æÎåNNÃæKàÀ—dbðV»SLLËeñß·azЃ¿ï*üiä?Þ cÑ+‰'ÅxaúSÐc~þ¤Kg3OËß"¥‡Ö`Þ†ôÛÊó{ÐdZÈy½jI=4Tö«É„¶Ã]ÙTË•îêô™0iÙì²&Ï Ä°EÂW6Ó÷TªÂÿ>!
+þ¸•m~I#žnÍÁ¶ 9°TÌé®T¶Rc²RõÞ=¿þzBS¦•çm%Äo[i|­î ±GÀ_™ò‘Ö›!†I—•A’hT·µ5a"¿Ãªn/Å’ ˜–N7,ƲYŠÏ†ØGæ“e
+Ÿ•qåM7`O K°š{3o5žç¡(ê¿Ô¹ŸyQHÇ-Aÿ&
+·èë½a/<]ããe‹>E ¥Uf°"Ù>*$Yc·ðÌÆ~]BfàveHÏ'd”fÔ-?Ð:¸À'<“M?‚VA‚ä“7_ÈÆ"€¯ØÏIᎀ¥‚ Œ Ý)>aµBYÚ\La‹>Vë;£IÍS{
+Ë2˜© ?|¦üLgc7?q¸(¿$B*‘ybE¡ñ”íQ<
+<N%-.õ¨û—’uTy€~Èäôôx…s0SÍ^Åȃ,æ©ààjÚAŠ
+5
+0]œ}·/pw(¥Àž~þãEQ`ä+8íra
+í9ï|uá…“WÙƒø³öƒ‰ÙIŠ°`H„N[´E8³Èöwº\}È„«Ó\„JmÜ ZIÁ €‚‹“Èl‰¿]fþùP3#ºÙäôÏuˆ§*³Ù¾FˆL˜ëhƒƒìÚ)é€PǶz^NR [Ò| ÇÈK#{Td-¥=˜w ߢ©Až¥¸<y)9ŒL/Dz"`ï;QN©F”º Š<åe³í0cc°W3ò‹%×죀¹2/¿±²ÖYÕS^óÞ^DINa_™K øw~½9ë$NšE+ç ¿ïåú˜ßᬋIb{ÐG§¦õ‰bÇZÏL²!\jÕT+"zX†´ hÂúà>3Æ $õ,p4}ÄAMˆ2¢©ú(?Ç1ƒôÒǼzÍjǹK0£rOÔ §dT™!`j¹"Kþw*Žš¡}·:¢0£
+—«zeoLmGŪÈÊOÒ•µ\·"E<¨¢°|<®íÒa}%º ½–}y÷Œq2Œ˜O<J‚€ÐO2§÷ôk‰5ùk Ýï|ƒd‹1q0 U’7O±úFð·}[ø.ôô¡®V6~¼9à’ja­à-öS K%þ¨¡X˜üȨV†
+d µ¦âlÇ,™FYǼ¯•sὨtµ î ‰jç® Hñð3m¦¬1®™KEcyŠ`:Ö
+<6àš1»¢ Ö»¼ÜÄŸ ïcªh¢§’ì:ì»,’ÕÚþκñÄ~7Ë ˆñõ°§à”0¢)ŸFÞ¬ç¨KMf“詶ï0Må‡4»ë1ua¾ Sc.ÎÀÿn;
+ùÍŠ!Ìœa løž'@̆°›ª¿ï`üë_ÝaòÂÙÊqxÊû‹IÓ·š²ü€*º=b«ëî°ƒ•0!
+ˆû¬ ˆSšlc¼Ï„ÅnõuFT. ØÞ§YI5>p]x¥†æ¶G®Ó8¦æ7â¬OßYGýŸòrIŽëV‚è
+´¯€Q…?ÆšjšÒûŸ¾“@¡ev£m>;!ÑE
+ÓØKœ˜ŠÇLtZ—áKK¾ÕQ5¨×ŒÛÃ2`Èxû®è‰Ž¡k&2™jw¤~©¸IÓsͯ{M6”vŸÂ—Ï{5)ÝžóÑR¦€Q€:!Ø èqWÐ ™Û‘µEs*nNš´Ó¨_¢QÒ¡&B&еÓÃØ'kð
++nªsÔ-³]\ =6¤E¨ÿ¥$A½‰ä0b~_‡W@5áF÷¬3{á<žÅAČՄŒ—Ì9—?ã‚(ÓH,—33ÌI{BÛ9N#¿@9ˆX,G
+´_¼ê=‹AW^ö5½ÆÆ^/D}¸Bñg‚"wrw.Ì€øŒ‹0CÔ‹‰¬„™? Ôox|QFÆÙ¥Hagh*€ ¥~AÞÆ=ñ…9ÖÉDI6¯£Õk`¡¢’ñøÃœ1º©;<ÑÊÆþ¸ɣɊ
+%ŽîQȹn „^æäÕÞ@ FßeðQ2™†kÅ®í4íC’AÜ@ŸBÿAñ¡Ì3æ^‡ 7å•BÞ±zˆ«B|¢„ßÁñ ô u ,qËÛpê4ùÇ2¦•Ú¥è×›¢¥sàE—XF硹ßc4ž@ŠÀ°]sé ªš4„ u2Ψ@Ø -!`^ö÷Þˆ§Çx¿—Œ3bsBî¹ß(¦ˆ4,½}ªò?G)ÌÑ]Ø=Ûf¢;ÐjröÙoXOær;”* )v:®ç+kRB'À Íênlš¸M©7]Çéî¿Ð›žù'뮶Vó
+1 2ôh‹¢é5o±âÂAØ<â¾.¼¢2ò&ÁEÈÄ„âžMq¬Éwü/%•èRVh“ŽZø/Ìyõ3d&ìø¥ˆ[eºÐ&x“c¯N­hš$%kõo×|áÔ_o6ûï"Ý5Úv9Ó¾ÈK‘2OV ª¾ÞŒ.uGüäÕž
+Lw¤-Àu±"¯=ÏZLCñ®»¨™,Âçúˆe @Üþ ™ýµ>šíqlˆÐÓ ØV‹øÜ%Î2IØSÓ¥ä÷¾Â4šÜ‡iïÖÁÀòbÕK—½>„ÎÛŠÈi=Hô¥æ~Ú
+qÍE‹^¥%{C*ÓØÆW5Hmãޫܱ°ô½û¥$îõÁ•öÆõËG}cF–Rœ†Ã:&'J»å$³¹Øþò©O`(y»v¶âð +äÆâ­ÐÅÄÃ}¯B;æF°$7DÛp*ÏÆiÞ”|éП?.E×^ψ!&Kéüÿ(z¿Ëvß(zR„ëh=ýÚê’>Pl‚Z"ÚeI¼¶¸¼ÔÖ‰'‘¾0ç5‚d¾Xj—<øIY¹êÏ]’•?Cß%½Š Hlzéß{+<ï4Dµ* L¸÷L{,`G  ¼”çB±bº©GÍ
+KF䧺½×N(Φ ‘£†oÆRdhsìeI1wc˼1_ñݶ­’$Šq7¼G;¹Ø™…÷V2{æ40à­øì“W·ê*I‰ß‹DA§­E{*¸~fù¡cˆÈèæÖÚÙ¨iP–¢{2m­‚§îuêPÞª'WcNX±oïRÂœòÁ¸u?[=}&û›Ô³¦h4b(@nƒ
+̲KÈU°)”Ñ£¤`š©4’óPÞE*|½kã÷o!QÙ¯
+­_ÎýN¡! Çùòµ„wâ n(7 —¹„}5—×’Ï{‰$›Dt·–RÁÃÍšxÊs¸-™"˜n“"äs\¸=.˜{cDJ­ëà¿\Aï%f;›¡8jûU//ù¥$z¦zÐ"†Êß­ÃÍÑhhh>[a;™pIWÍ¿B"’“=9]t´ÎÅhÞK9[ñÐ,IÐO&ÍH‰2÷2BÁÒ´TÜ°‰h {²Ú|S-`{½ú„—¢Ìÿ¬< ¯r„É9"¤P e
+P¶
+6!ì-ðÙJM‘ir} ¦TĤ`=Ä´âb­ÚC7òÄ׎ãt â×Å1Q<\ƒDzhi˜Ô(/—ðk @zÅŒèãB—"NL±!Ö‘‹5áÀÉWŠµI‘aÄgÓ™ xìñ5µÂ
+–q}ü™%†Òfð”1ƒ|%CÖüd©¯TæÛ ¤uv·ÓŒ˜Ü¼¡D¤š.áCaÍ=Œ6/Eˆlû4x!‡5h>ÐxÈG
+j›¯—sc‰‚ùE
+zƒ¬Õú›§hðsï¸D[†Ÿ 8" |©ˆò°Â Öùn% ¹
+® ¹â’I¡r}Í…*¹ôYå–(âéÄñHX<;RK@åWó‚.J0€:p¦¸b´Ÿ¸Â„Ò»„&aÊ?¯P”io¡ÛÏ—¢ë£·l#ÿô=Çß)zÀÏïLéN¦V?dËX¦Ä",ì•tñÖæK-^:¾Ë¥+9©$‹%°¤ ¸%N´&Û•Å2”ð~ w·ž{” çx
+ü ¢$»ÃŽw+ö¢ +r•g(üÿÇx™$É•Aô¼C ó°.-u‹Þ’÷ßê9†”%~ Y’ÉZLzã1ø€MÒtnHW¡?ôùˆ&C™&d}J*›”DJºƒÁa‘ o·Aú(MîË~S`‹pR¥ïSžµA V0¥[…NíO}‚˜l 6Éõußã2 œÌ7[0SÑù¤ÂÞ` d1û;GaÊ«Ê&2ßÐJÿ²Ê Äc6ºs0Ût@Ö§Žv[çCcÝæ>ûUÇq'QM
+{"«@ÕMZÚÒòѨï÷æ¡­Xi7cÕ×æA{‘<…ƒ½’Æ z®ºñ9“4þv§EúÕCØö°Ö ïKRE‹44Lu+R«ø_¯6KÙ 8Ž$
+ÛþïåsÉàdiÁ#g Ða{Éøiâirˬ* 2°sÉ"OјŸ‹k¦Œ%’K\â ÒwT?Áâ–ÜG5¦=ÄÃh+‘ªOD‚J´!ôÏ€¬/a¬KåÛag¥ç9rˆ*Na;ZÜP#G´ä³ºo%.ô^Gjü¶ºuÎЪ1mDŸ÷XËtVjئ—àYQ¾“?o!•¯b šî/
+Ó T:Ú»}^^Ž N‰oÏFÒp<Œ… ]*a¹Ý^Óζˤ¨O-*Æ
+â£ËË_§Vä¢øP®ÈÇ„~ÿ2@欓ñ:åد[c€žûg|î ƒÌÕ:A‹_Ü+2sdOn¦Ä
+/ÕeœJŠ»xò¹_ñ~A°G\§—a‰\ÇÞŒ
+ÓTÌú b˜4q\™”0ǹ¼ µq²v¿®© BŽ¦¬<ãŸù)xžÞð¹I>í%&êd-êç9ì¾Ãçé÷ΦH(E>º~ zŽç€p]pÉ>F4œ˜§¬†²¾9¾}Ÿ…û‚fÊš &šÿ_urüÿ’8Ùˆ87†â0±jDÆÿÎs¨9VŠä:7˜æ2Cë‚Ô, ]ò:„-äÃâáXæ`³ålž§šÑÅYô5~ ²sô9—¥åÒXËÉâ`‡’áí"Þ  GU{i·f%¾„´Þ[¼ô<½ôÞ.—= ;†»cqbšœÔˆ§®G šô쳂'ƬN”>ã&¢—÷ý!È ÷¿÷¤÷ÆS hl£ÒÒ…ßBþÉ`Pw¾ð{ãÅì Ÿ›ßdøÉï@¤àëÑŠI†M&¢å )Û¦ùA†Ò-´•m®=™dè”B—ð6-; C’;'PÅÛhø—šì±#ûòk®z&IÎV,‚JWôâ:b|ˆÈeÞ!ÁXÌS'ÆWkÞ8èL
+b@˜OªFÏØ’&D‹ív\~BBï𚦹Ì4 ˆ£¸1̨(#Œx¼æS™Ç`çp|,y_b.=‘Wy$9šÔ‘ Èø6ž€¸4ÔÝ8Ÿ1ÍÓ…®“ð| þå'O@¹eV†8êJS” s  BQÀÒl™Ê=áO¬oš+]¨%Ï6<÷É—”yù6}®tæ˜ß/‡ªÄƒ´(¨$)L–šçøÈ^–óVlÈÓs‘¤°ŠÌM$;<Ä€¬v‚Ç’K›Êžç|vܸÍ99æ«Î 4ªsαQcòÑ«~°3Ú.·· Ý‘ÍâýÁ8îÏÄs”/!÷’çµRÁWTý²ü* €ÍÁã÷´S4Ñ}Üþ(÷$™£p±¼‹¤µ ¤¿} û…Ÿ€°;³”£)Ù´-VãOÛ¢ÃòÏö}SfxAÓQw¶ ‰;@êˆ|œVG àñõ"x ÃÊ4m}‰ÔÅ3Òé%–‚µI©-Áˆ0‚6¤H"Nñn„n9$¼Ç!iîñ :Úþû‚‘r‘
+5¾ë:mÒ
+ÄÇth dÄû.'ÝG‚Q}XÂn[k‚Âðª±*ÈßðöÆ0Œ@ Hç/™’Úò¬ÞŽY¦¨¢´ïù¥:QJñÍ
+%¶ý.¤
+­ÒsþÝ Á%">4+®W‘”4 µ²^ÅìBì
+ ¹óí SÌœ¾-•8ñKïkF‘<*¡GNˆ¢¡‹ƒÚ{F3¢Ù€·³Â6ô‡ç×/caäe¸ *Î ÜúÒçâɦ‡fhë)çÚÎÏ>Ak;ä ±Éq{"Ö“üÉåõ1ç†SW2¼•ÁKê7MâA¤¶ß5Fœ£ãjT%p
+%n‹Þ2y–`Ç[m+hôòi)µg8zç¼} C“±dpu¡Š*åW¤§Ø
+p¥ìŒIå¢:ÃPîù«wJú2Ó> ‹ïùäK0Côe9 °1õâ¶xˆŠ'rû¶6AëKÝàG'­f Z4Ó²pë:,cQƒ[Œã¹J!=Š0&„yæ\êÕ—µˆDB([Bíßü‡7*r[ëÎõšš(:~vÁ¼Îµ¾´†P vÌ’Î?q•{7ós@Ø©$ˆ(˜*Õ@¢¿è+ &“ÍÎäºýLJ¾
+Ñ(/)0¦dê« ´X*Èh^ôµB‰ˆl‹…K}DT“ž1¹¦¼‚`’üY» Ž–=é`ç؇¼êÎìGp¸ëiòªÃê™ëݶÏvòZñþECW¾œS^c&#ôÛÜ~Ê+5ßÉ…p‘ך¡þþ?ÆË%¹’[¢+x{Ð
+nðÿû {žJûŸú$ ¶}«Pj…ÖREHd&ˆ’ûáÚ+VJ`Ëñ䜋½z›½Þ@ž½z ‹½Þ®|·×ÛÓ={½•ðn¯·FÜŒñÖOÇ^E ­&nªî²'nQ¬HÿXO]{…£(f!Ç—šãƒ½.®Ó\Ú;Ž]üõ:0w{½Íg¯· öìu=‹u9H±»ö
+¤k†¸aÍ®»ÞTÉs×Ubù,ø,ÞíU‰Òãj° ¹Æè5óæ¯pbhà©÷ô¿mŠÌJÎá,ªÐFs hÉ:w \ƒ]$îÄ4nV×aï<wö®'ŽÃz ‹ÃêÊ•t¨ÏL®ÃÁY3´q¤‡]%D¢!™ÓµØ[#\ÓûÞ<Íc‹Ö¢‚ø“ßLÚõÇ…€¾*ÿµA¬Ì0ª2ºúåhk¬¼•¡„¯ó€Þ»‚>r§_ûê8CcLŽ[êÓÕ¯ Q3NTE*³o…;0ôM¬<·úèþ>縀Pvô“2¾%™9¡šÆç #3Ðtdgq‰…SO¥”-œå98qnÝè¾£B‚4ÔçÔΔŒnDxælÂø²B æ0 3‘¸³<%«°ÚÙÊ @¸䌧mH¥.Q[Gqë$ö~=5÷3?}f$^Uîq E+Áõ fëZ%Fìç.}¤œl«¥ˆ‚c0«øfÛÉZšC‰ËrïU¾B0¢îhêäÁ—f”@H+”ôwÕÊ‹üGZBáRÛmXþ¸Â8ŒFù)zÌq¯ ôjàE²é’¢ûò{;óÚ’.´i8+2ŽÆ„ÓØø@ ÚÙz ˜H4©"è÷l–².¬´4 ’Ò Vd¤:Ã2Àôz"©¬R{I©56Ø„£íê@Æâyžïï*ß@Þ\QŸ®g„Xúã„: û¬;ÇýtÕŸÏŸˆ”iVAÀ^\¬& Qy–„ ×ÛZ怟e¤ c3Â+7dlÔLpœ …¸¶9 BX ö¢Ÿå6r.Î’Z$œ‹ØƒJAYi?dh
+¹Ì(F‘"@¶ñߺ!Cgê(¿±£°~Ô¥péöôŠŒöÒ¸VŸnSd«(ÓøüªƒV˜ýP ¨„îíq~È[¯ì¨ ¨½P:~DçÆï—A
+¹ˆõ¡o#Îìbd'ýïtš\ˆ.–Óˆ.¹ š® ¤E*“hN³†ªxH$ÛÙÌç( ;¢ÁÇ®N”±ñ TÐŽ*\·!®¬}R“àb¸É * “@¨Í_Þ8h†)"ÉClkõ@\/a‰©BM»OËlQ!˜ÞF®B@PËÏÓƒ.8ÛX{…<_ägMsþ[Åm†0ݦ梎¼çÃi„k{ßÛç
+ÿ×å3'¾ÅC²ÓÖ¯ b
+
+ŸªÈûШï.n„ßÜP¼™ÚC6jÿ¹U ÑwmºA6RÅ1ǵKn‘DcÚ¦—b¯ÈfÚMyŠ╇QHÆÞPl4`
+®oÂ2T*·óô Ÿp)«'f›?v=„"‡C ‹Ý:¿™6k¸Ðšû•úb¨ÑÂ
+×ö¢„
+“µ³BM/d^ä"Í-ù6ûßaÞß lL+•“”-ÙxƆ&"Ǹ× S!Ñnýt¡Ççÿœ³DV\®¯i.vÖû©¸¾Ü®ˆ¬uÂ~B-¦”×âbe';¾Îî'ë|æz6]R0¢IF â9Š ¯D„3¥qåj1†}Í!ëæb XGŠ˜ÈDڇÿëÞû÷O˜üëߘ‘^Rk€´ãþE{¿0ÈnW±0± PÔ­6{Ì¥íïcC¢T±ÍùäŒJÁpì·Ÿ›“»THÍè‰+Ay›47¬RJØbx˜yš´›Ku ÆùÔ/„r<|’;X¢´áú·qèüö*Ÿó ä%ÚÛá*ñµ¢¤-oÿ ˆ)¤‘ØMçöJŽ£ËÐ@öûÔÐD¹ÓYqß²ÏÄA£IHôÍÏ>¢h [âNÓÏ>pþDá¦;¹ÆúÞè†Á¬ö‡¯pÿ!gâ6~öa rËÌØ)Î=û$‚bRn§§'û65RlÍتŸIµÆ“}Zø6Ó^§®#¡ ãXŠY©i:G};[šBZªæI$ó¿#‰BÚŠ±­ ¼c4ä•B"ÏKŸ‘ ÃÌy° ETDŸåÔY­ª]A:-x±š¼TU8$ÔcwÐ ,!«©mkFi«â'Óžý6DÆ€,í(Þ¨ •ÈQì(ÔÉ&D-â(®!ñS“•ê9‰s¹ïÀñ “V¤RB›êDmZ V>la` £ÚDVÌB@a7Ð’g—!ª±ýÃxyÉ•Ä@Ô‚õL”g^iÊøÞ— Éî®æ.ƒƒ_
+‰„Éœ­éµÅW\ˆnq0舆ÖlËà Q[NãÒµˆGˆ Öq¯Èh6Š½šG$²ÂËg8b#ð gÉ=qçÝ8.bж­C‹ À0Y‰dŽ”Ý^ïR÷paLBr’/zN­vb=?d…‹rUçX©a¡@«•t¥8ŒF^qÀwh/V0vÒÆ ‚'õ¢¼E/ é?LI/‘Ï èú•¨h€mÐn°tga¯O‚>°æë*ìÌ nÙ€ò8
+Ç`[’Ÿ—€4N »ELÁ‚˜·c—
+ËÖ5‡NGk£c’Õê,ѪÄOœÛ‡•À4›×9ç5B9vÚ/oR²ð€­ à–íqxÍ\~õrgH«!£+“"IÙK–ÒBGyåœ.›0i¡-"nY;FÆGµ@É@ž·35óÆÄ×þÌŽÕæÅP'󊟇¹±É#vR"E³Ð ,3ˆeñØ >+zÀ
+%2ÂDZW¾UàòÑvI
+ÈMÖ4›¾¯Oóã¡kuϺ²Ą́±Ó „3½n»ˆg‹«çù[XP#@º“ç¾Æmâèª-Ã;âéܳàôɦr)y\K°,`–æ¼ÙÉ‘‹
+ñŽkîKÑwÉ>3ø‘-8ß¡jœÜ§NBظçã<tsa'C?ò–z³Ä
+LLI8©ã÷ÐádÑšÆ yÒCó@}~-†®wùxÚ<®yñ½—ÜI6ib¥ùUÈáÒUŠD•eK¹kòÓ`x<`äNÙ¥
+M¬5ó)fÀÊžp1Ü‹Ô 5ü¸[ÐBNÃÆhä燒?]êOyÙ“(»2ÒóÊøú±<;¥Mfh/Ô*žË¼†ºº!Wdw#Še¨úð„ ’oÅÓ7¹Ç‡y)¤(¨•¨WÖˆëõù,¶ÊÄÁa‚yÚæ·Çç'ÝZCqJÀ–Z5”ÄìöÄ$®–à ?ÿ¹%smŽ» pØ1'@¯…½~*ú¶"þ ›#Ó¯E”ÀF´ƒN€•,1Gp.%‰BLI©÷àÇá™=Š4e¡…—ï2êE¶ÖÖÑ‘¹.óç[áUaÓ„7·F\Jžò‰oõR”ŠÃ@gí¶Ž:°5F?– ºO…È(áyf/ŸYtŽï€rsPØ!îÍ‘½¥0óYñ‘½´Oü;’ú '}³€æt–Ï Øè’¢
+7‚†w¶ÃÐl0Û9]ôi…L@Á’ƽñÿRÖ<E00°H6¿¯§upWËJø ‹‚äXüÞ´
+’OS)bè¼Ä`…MÁŠ¨ØÍ–éغµ”â|'Ô¬È À•ÛJ˜4bjNûRrvš` ®G÷ü°Îü"6
+ZCÍt†§LB6˜—&-1ÿéÙ[0ß܉_¦ Ú •ãÜÙ J 
+·µÙNYV@¯Wœð*eÊ¿à‹o÷~-ñ†¬‘•OëÀ8t[4îsÕÀRÄ`ßš)Ɔ š´l2¾Õ3(to@×ËÆÿ¸ ‹
+x–Tª7®ŸJ¶ü±
+«¿õ¦§„ãÊ›!ugŽ+—‹0|P‹_ÅÝk¢ iX‰ôTR¡a‰7„¿³ Q:ÆŠ"žo3qÒðb딂=Cfhµ•0jàŸ ÃrY·˜$ýèæRSÊVƒùk«ZGê’|³¸†4té[E{TsÒ:ï¯ÇB²ÐÌ?* û2me!ƒÖ@F°;)(ûã´²0DÓlVÂCul(Ôã«ð·eðÐÅy°?)7XPÅwzÒD—n¥E2¥§]~h.‰y„ýrv±!؉Â8´ïu¨SóØýâGÕ@6nõRâíÄ ‹–ùÝïëÐñ†Á€¦— Â&¸Àtïÿ±HìY•ö´õ•ÿÓxJ¼ÐÁÕ…
++yÅböc·¬‚7@?]šÞVÌß@—„y{/¾›‰ŸviÇ7¹Ÿ8[‡5yU’æôk É\'ëÃ¥„&~€w kôVÄ3C‚EvcÔî먟( &ÕM,F®‰IFò­úê’‘=F@~%Ls!‘‰ L_$L°H¢{Gy?p»”¦jÿÀ¿ùçoßS¿‹TeK$pÌ/Ô]ê´Rö©gxÁÁ œ Çß Þ
+üU]áë DEbB°X-@ö®­Šô !×w´†#\DrK‡ì§ùø©nAJ䃥••¤N Å5XOf¹ŒKUa,v_^<(ª €Â…… #1 ÄI´’àŠð„ÖO£6=ƒ>n@¼‰„—í  œɶ VÙi¨_¶{GµÑX˜…=Äé1nu;BV¦2_$Φ3„iûáA;cr9þvˆÇEh¡g)´@üÃz/Oh<*œúâ@¯L"•xþ@(Vôí©±QäbÜÕ,&ÃS¦X­Wá/¸b’í¹&†#sJ¹ží±†bŒ’k߬6}š—ÕN
+á’ÁgHÄ}J1C«çarñä—Ë+æóð’™ÏbPP3´]ÌkCÍ!d¬§°n#yÊb¯×¦‹±˜Ï8®3ÓÒÈííDÁ íûUs±|cñÒ me§ïÚ¨)TÚ9ꟑÎjØbÓŽJ~Ÿ¹ÌY%8(o'ºsISÖ9%¶´8Ãýz—ûà1©TÌýœûØ ll…ÐTv^ë‰ÝN?ñð‚äwŠ¤ôHÅü „’Ójä"úJËËÇáíÒîÖ¯Ã@ê‘ü;™Mh¢x~”‹R–­ú‚PzCºÊÖOì©@ó4mžAÚÓ¤ˆ†'h¹¹C9€Ø®ÚŽâ~Y‡©ú(Œ¶Õ‚ ¥”éÕ†P½ðäa辶´pµû>/ ‡Ýúù•<ý)ŽÊu aYÊÔRÍ3þ<‚h» 4„o,­Ä
+^ÂäöãÍ·í†é®R•ùë@òFðÖkH,D¶7âFÃý3!iJPl‚õvçìqrO‚°SxÙSð£¦õÞîüù;ìðÀ“ri¸CCv‡¤Å!x?Ní:2ûPña‰Ú{¼Cä­(¤5—ñWÃC×›$)GÇ.†yº5W¦íÆ„‹Ú7IÒà/ÙÏ|ݘáR†åBq!02eh ¹¹JAtG]Çi{ˆº`>½Y-wʉ
+©›iº«O9op³L?•vyÉH/ Ù‘Ö[vÜÍ ô2€§ã¾
+5 ,v~îÝ™lê,®d}'À}e«´'‹_qÉ…Œézaʉ ©
+>¨ mÀš *“J?
+Ö
+šLQQ,Qo!/ˆœ6…`Ö×Q‰âK ÉÉÐÉ#±Ž±ê‘E•éˆ3žÛIóÂÌUBçá‘TéTå#Af³#vNfLæ+÷AÏ L%E†Ýµï“X^È)j»IF ¬2 øR¶av‘¾æŠŒ3†<¼›©ÞåÆƘ« ¦XÚˆxÇI* Ã!Œ(³4X7Ãe›”Ø‹¦¿†ÁÏ°Ø[" \
+—di`VõÏ(µ A˜ÔèªÍ*9šF{ÎÚµmúI/øCÍkuÉâoï¼¾\ªý¨É€˜ó™|-´¤•ÂBà¸G*TU;J©†Ì$ˆEfaÚê×EÈ@dnŽ Ê6¢+æí ^@¸;뼂W 6††ðKk nɨma‘]º©_O µ$ƒãò]k`_Þ‚q¥Á¤»bq?¾ÍÅÍ4† zJ<‰::$Š~¨Ñ I@˜xŽQÑ`Uå
+†Êï¯âèiÇ^5Óâ>Â7‹ºè…:Òœ¨þ58ïa% Úµð>lJM„3­a‰Y¹ö'ѯ‰ÝÅßD‚Ás7qÌŸ=•œNô]¾ˆD刷°g?üõ;œõÂZóÍ]”
+„A$ò7fðºþJæ¥QøÊ°_Ýá-ïdî·¿+“(¶C!”]ïñzÔ“·
+Üî;ÑDŠ¢šíÊx¡|rÊÇEXÞå®™e°`‚@ZK‘ðÒ±lA^´©™’ö™ •Zü6¬K®÷V¿c˜ðötÜÆUbJËšŽŒ™§ò+¸(k×Q,U£•-ûm
++G|vßRûäÅàç±ü&—puó‘‰"—Ƨ˜éî²5—’ÈBpHšbO›Cd*ð|è9û¡×ï°nñyIŽ__–E ÁâÀú£ZÑWXMZ­ó$,ÒÇC\Ñ!øÉž÷€Á vº5úxeúñ ú?ÞN ì
+ÑBʽà9SÞ/gÌc£Éí87Ǽ1Þ¿ïQÚáŠóâéë²Ñ(î’ *;þ*h%BBuÌ/ ÷ 'ãØob
+¶.bîpªîÈ2cK Ùâ1î£Þ5°7kp§ ;y5&,ß D¦±}†ƒHè¡ 8á¢ÉµVs=@æQíËòMâÛïÀE
+¸&¦‡bŒf_þg²¨=ÔfôÇÛ4¤àf}1§iËà²xœ—Gü•Ñd
+¥a3Ž»ï0eazß°{YE4– ØÕO2)v•C¤ò£X7l&è
+U ùTlPï¦ÐJ©á ªœóR™
+¦€çÍœÙv±«Ò6Ǻ¡´?•|
+ëÎç¤Ú4”Å–raö’öÊ”>$S]mú"*X†‡—ðt¿‰ß‚ÊܛÛÖ2édMvþIϬ¯Ü!\gñd¨¨´Bˆz'I» Î
++aïù ÷¨$V5šŸo÷Ù höÕß¿ìK_Þ‘âïƒD¹Œ%©ò«QÙ!ˆŒÕÇ‚Xû&F]Ã:§Õ†ÑÐgå @Ý!´TÕÆi‡´ÕÏCDðz§  XϪ'[g|ðëa4Ž´‰í$GDÅ÷æ@HQÑ㌾bK,¡B£4}¢¦R [ÇZ=Ú‹‚Ù¸à˜ N¾b0ð5µ™#¤LNM&4[\…tD¿ ¯âœŒp4ßJÉÈ <cjÁjÁnáf²†Z•L;„隷ÈCˆËDÊ=;m¹©££Ud¹C0ȶ`i3C”ÖAÔŒt÷„;µ„·ø÷º*fGÊ>½:Ðj¢‚¬QÍŃ)”$y‰§TIŒë1ƒ¶ ¢µÚMÒ ™ÿ¤öMÑÌ^Ë~LéÂ^¶PÆuŸ
+ë Æð_‡*HMàÜK£·Çé$§d[ðÖéë%èÛ>GOÇŽPÌ´1‰"p—x ©ë‚$G æçÛ)è0žub¹Mð‹1ÿ>(ñ~˜rO†Ÿ{Ðo×ý*Õ^ÊOúbпOAè…Л/^
+£?ê-§Ê£Ï0" -Dº«<^D›ÄT9%vO¸hG£Mu+RÇéA$ ȶ*tÿà“ñð@;½.º]¥àòSRB~ÂÉù›.A_ têÀÔXyï¼·.g¡á™8Æøû#ÉüDâCc¡_Š fY!P<ÍÊÒ-¢‹çj™/?‚X±Ïæ嵂@mŠVk·›(^^+$ûÞ>‡Í4u@±spú(w*sñ$!¥GÄŠ‡ü'À
+H‰Œ—KÒ7 „Oà;øQ‘x‘\{ë[¸*«äþÛ|‚ãD¥ügãH-Ä£»Ùú×?Dâ5\zÓ¾Lç×_ºú|©ÉïÚbC¦5wŸKšø× ÑgïÒF÷>6dõÖ-F_:/Èx­:cZŸÝ¦víÃv¤ñkõá­¯~Æ«5ŽÔ±øbísøÕÎ¹Ý ¢ÝekÍlC”ÏÉOç¢"õÞ½…¸z<“wÐ¥ù±­‚ô0‹%16„ÔÚÕ©çÞs¡5bŒ*^ÄÒæÒìáæÄÓ–Ëhú\¿x Gv ×1ºP¡º 4„ëW7C­›ç§ºÏÉKL[£ ƒS|J"üµdò%Ù´ ·h3Æ$¡Èwp[œ^3a2™ u©cÆhKݸS#“Vª7ׂˆ,z`¢éÍætW.k_¿Uù(M8IÅʯ/Í2Èø´él§:$ÌÈŒÑÞ}q À쪕2…èÖ)·Ø`ìgŽ wØ)‹ØË™6=5¦2Ry¾U‚­lØF¨ø&4¼š9¨œRcÓ ªÑsÜ‚Ÿ@3¤¯pf£VúÆ´1çNи¸ÑðjµÒAqå½ ×\Ëàd}èÔ½ «q%µJÇ”ÒQO#Ç}LVb1n^#…ÖÓÚ½!*åâM3ùtÌÕï6©¹|JæêSN±ÎÏw `‹Z÷Oµa¤éI®‡=Wx¼&Ã+¸÷üÔ)¸í‘©ÚÆc¿0Qt“Òè™ZsB{Qh#UH"3(ˆ&3ãÞô01œ<ë}Ö:{j pcëOŽý94%À8\,žžrM¿ýÃÎA–LÈbÐN’]Eßë %Œq­K—.·®³n+’Ÿk—´A­UèRèc €°çDiäWõ5¯èRÆ°W_zG‚’§t¾ñºT*׊žÞ³Æ“!bÒt°î©H{‚Äb†ßx=e[9·B1
+ÏÄŽßõkŒƒa»ŽQì:×R­W)Œ¿ ®Y< õ[á­B?$ùÛZœP´6’\ô€Xx…H°HR-ÇHà˜°Á90ç)ZRÙ°”鶚aëXLÆ1‡è!À·Èò 2¾å(ÚyL&þE딾z3ðþ$RoˆÚ^u’!ÐøtÌ nù­­“ Õ¼üM[1mKV6wb¡ãù“ÐÑ?¬1ûVÏË@›tx<zk ¸ ©˜ Ûæƒnb~N¨ð4R¬+ÊB]ÒK¿× ¼Ì¯ûœ,&c‚—*Èd‚ ã• ¾…ùe(·d2ZFE‰ÁØ 5˜™¶ËQCù€ü ª}ÎH“Œk“=öB®—‡d~d’*ë’¬öe\®=}ÀÜîfr äÚ<Àæñ‡&²¸Õ¿JcíäÕÀuWvëé‹ëÍ°àZ䎨|’º4@[£ 8$Þ&¤à•²§ß`PÎ3;3'ülD‘ƒMQ
+°z +&ð~:ž ñ$r²ÃýY¦+F«[1OÉfI¿ ¥òäò¨”a¥õ3ƒs–QJ—ÂFÜÈÜÓþRoë=µÒ_õõ‰N€pðJÛsŸ‚sa÷ ÍV,E
+gCK©^åY"?‹óßGEŠY¾îZ>iÆã£ÈâÑÉ~0Û·Ãy{VÓ¨4NóbµRùZeÀÕ¾àdè'•@=ëUÁï)z®pA„Ö²úÓLl3ÓÎUuÈ6™•Vù?4®k£2f'Ø%ÌKuŠMH?†óog/g’ZË'X»#ÁŸ\ƒÒKÕo’)’ [ÇÉÓ(²ÃŠÌc*<3fŸ\ÊS:蔎ïÀˆÀÙè¦ß›í§OPÅ,û‡f#9-5p«£š::ʸAaDJÏxL8BKülxùÌëMËF 2÷£#n–©s°Ê“lzž¼”ÒtCê•MJ8‚Ç{$l<bî?º•¥>¡Y¢@Ü眀ŸÓ+{óž ˆR~<"GÓ¦‘R|€¤ç¡›ð>žìÛ—?¿¤ÅxÉ`
+€¢WµÂ-½Q>ñƒ¿DKÙ3|úͤÿ}½Iõ÷NqB MŸAy_.Ìb\ô$<kG¹@ ª¡ÎƒÙümÌC0o/Ë!c9ùê·AOxö;ßFYÓÎ-´O˜Åœ³B؈êD&gyw>|BÄÅ4G±·'1Ž„
+Ä+4'·j²g86Rª
+’«`á­­ Ê …1Ö±!×û•0i¹O(Á×ä%6‚µqœ<%tîcÒ4 Á £ù0 ¯Í‚¬\Zƒ)zARN‡„>ŸH<)-Œƒ†S& ¹î;! ÎZÓgƒ*èe.<CÆ,òfÔ7HEJk
+ÛHÙ‹_ÎalÐén©7²„ûÁm¿Ào²äåä¶ùï=}îÀ÷Ó™jÔõ<ä%›2ºÏI¢F·ò¬‚`ÐK2ŒJ«v½ìÚ:åƒ_Û嬠¹o_žAë*0éAòÛ  À÷¢S,“Å[SŒý†h\Þ!?NÁ|#7ã ðóÚ¨)·e²,ý¼V¸9º0GO‰)P bÐC駂ü ¶ÐšzOÙ“eÛª.à°GˆøDB f21>ït»Ù¹‘Îs O­ô!¸Œ=|wrÞ~x"ÞM@€ðÃ5 èbx§&
+ÄmøJòyz@”Á•”¿ )Y/ÝHÏ-ÌwgT(Âàó'sã
+õ¶SOç rãR]?ÝŠ  qW˜ ·ÔôY¡RmÈ¿g»ì4<m5Ý/E·Ô¾|èÑj_ò)jrisAp-x¬°ÖaS‚Å°ù õ¦iØ$C-Öfìs [:ŠÚª\ètcü;6„‚C«lTmxäÓ8>åJÒçñpyâ “"œy¦µÙrÆÏ >nV¹\6"|tV¸ ¼xb'ŠÙo£¿‘ÏžŠUé9ëäÛú¦Pã%ر1´²¡Ö /O¹ŒÌ¯ZþÆÖŠ
+p+l°T°¶ÆÄkÃC§…¨•GIvʾaÇ? .‡géá<î8ÿk,¾oÿ±m(Á5¶!ëîN·SÝþãDÂÔ“©€t¶´bRù‡ò2É­#W¢è
+´¯@`ߌõ‡µ‹j$ïZç&#žÿË$•Wc_‘ÉhnSõÿôvÝ÷O¾É>ýqÖM®O×+9¾˜ð ô×ô¶b(_ÔÌT‘ã
+Ž^Êüª1¼d@ê’ Dx{ðGyÀ³™9Z…/+¡5mÞoèÀ¿‰Kd'¦i ƒÃ©U®Þ‰ò+„׳ z/Ù§™G„°[n1
+ˆ8jïJûsLE÷ã
+,·V¯-wLz™l\pq0)›TÊ0u½‘¹^DÿÀÏŒ¨(¶;Eü\jdzÛý€@JHIýòľÓT
+7EžÖ¬|Š$½jX»BVPäÉà z`…ŸÛmÂKI‹„kDûôÒG5wècÖÿx¬ŒVŠ)2ظ™Â.¢I‡âíÇD:Éå<‰×ûSaæ—O4ãÒu1éf
+´ƒ«p^´”™ÁHVûâW¬¥u¯MSÓŸ?K÷›Ø(.WE}D™ª†*ÃAVcl_,‡eˆ«ßhw톚à$£äƒÓsEd;»IÔÂ>ñÅ’bGœ%R°Î™R!f4”Ãl%ìJÖ¨‹sN3šäÀ.#”z;Ãoˆœà{Wx˵~ §ªAw­|{¸]UµÜ ‚?]ö§LPHi©Q_h«y§˜Z|dà°± Ì8rO5üƒ² ¾ Ÿ™Yç6êP`†°†=}¡²òGpÞÂ>T­ÍtHÅ ÀàÉ#Ë[³«0à,q¶I (ÛÁn¥}þ«à¡7gùõ±í"+Mç{ õ9ÚO1»´öÄÜÓšA"ȶ}ZÒÄ”~Ó hfðÜCZÂ?Ú€Sò!­a5Yb?¦5–fè¥Áû°¢24­2€‡´DŠ£0+§´ÆšõcŸÖ€6¬Òü‹ï)+^‡iY«dOK»s®ZÈf©=£ØBh7;K\|Œy#"©¿4æFÇÏ9Ž+^rpoÃdžG·Â9½m!•ò5%Iº•^"sÝÆØ\л?Fý9Ä×<ŲØï-h³;Ðm')DÞ8¨ÇØî„ ¨4?FËa'bø£lméÛç–ÑÊ÷ÄoŽ KÖúa'¢øØ Fu¿‚p*–¤É0ï–V‚c’gÞÇJÂ`XYô´] Aâ¼JRn£ „ çK˜ŒQO¬/9*VrúËÆd´Rº¼œ­  /ïZÒskì&*ÉMYVÚª‡+ ……ïcti‹SeŠXRÎÍ9ZchêÔÛÍŠU£øMAõTõÑ*—n¿ìÜ¡†EóÏ­xîÁ°Qsû”óe-kÞ¨ŒßC«±ÐHŸ˜ 6™NÃÚð%íúÉ…PÄ)yÒ~‡wD½„3 £ƒëWj½c6J•ë§\.ê_D ?QàÌ‹e^×òn@6 ¸ìæÂDÙî˜Ç8AÓ÷
+‹ ¼Ld‰pÄáWq5)Ÿæ‘x9t|²sô·ŒjT!¶/¦Y{–áÍ׆áÇ“u£_EÈÁƒ_é‹}W&j%µÌÌ!hˆfßl €¤öquæw‹•Hn_Y\x:û&OÕ}Ø öÎÁý,‚ÆÒðmÓˆ‰i˜ú3–|úMò°„Ñ伤\„ŠAC+¬€`ŒPoÆÄ©”)¤1ÈÏšˆä6y~Óã ¨
+ÿR^&×rÝ:À9(-6
+‚2Fþb¬÷Ò ™K‘›ÈZ¡Ðø$õ0!èeÔ:'øŠDD
+AÝacEÿ#ŸT(OÒËFPä‚zr‹}×q2%Li·#:8£ü”šu(²™f'ëÄ ü‚ý ,AÌØ;2€ŽXª³Ná}
+À÷¦E.…|×µ{ ‰ýF¹ Ø»=É·s,! PFyܯRNô‘“‹==)ë3DæßK“ù…ÅBûiÔ{3ƒ:
+êbéKZ}P2Яàö¹RŒ,ó;c¦©Ûýœ SIþqŸW*”k¶íÛL¬„®Ãf¨ O
+¯žù<‡gbSÈ·‘säM}÷\Ü@‡‘Ù}žSäÖ éÌŸLXŠÎÚé\Éh¡ŽG½®°}ÛÀžgÞC.:ò3_šÉÃ3ê+•¡ƒšL¢ðC0P7`'ºmù[H´ŠýE01]Ç›½Ÿ£n:ªp ^埸m“
+»á@[ÀOÉñ·ã•ÉzjÔcžÀ°bPªìÍ·Û‹©8ßÀÖÖ¡–¬¨rÄ<ûíÜ5k´3Ãð>·çàq@_DLÿóÛb)Òh |ѸBÐ*{¶c@*“ÃQžk€·›ÒaT-^>`˜¤z
+Z#µæ„ÿ?‚˜;;·ÒÿØéPG()ñ®9¨S}T3?BÒÙ¾óV€Ÿ_©ÒUÌŒnsH‚px(ægÐç¥2ðBVͶ†ýJÌ¥JŸÉ¾ôѹŒäCucþêv[_‰¹”ò?k´Jùí/…âI‡d‘ b‚p8ˆ\þÆ¿ý½ƒ Ú¹LܸÄìž“?ŠP­b.Q±y‡˜Ä)|Ñ}"AèQ©XŸ‡X;[Ššf¿Ë>‡mo<2-ø8JÃøÆmG`3ÖP]ŽLÐSAóÐØ™O&D‘˜ëý0Öû˜ØŸ¹ÏÁÃNM@*ñ*%ÀN5ÁîYHM¢Ô.²d¥Ê˜Gˆ
+ƒ+˜;þµ‡ßØYÜ‘Q°ˆƒÉiÜ(üçCÀ¯y!­Åò—q¬…SP´ª*T#„GËÏÕ#í><Œ‚°>M’1ÇÓ51Îè|¤Zí¤~°Ðn¢1è;DR™Y+ÃýAµ)ˆ%QEk=MGŽ"šFÛj”¤ Šâ±~F n>¤›˜9É
+dCóýd¢gl
+O–ŠaO[“VM:gPÞü[¡uúÄÏj®)FúЗ(žÞ0·q´Ð„ÌÀÙ‰p¨MV¦÷y7:C\Õÿc¼L²äÈq zÝA'Ðã<¬³–uŽ^©î¿­o$à©p§×k­‘@ÀhØ[j*d?~hMbÒJD­t}#D›Íš¡Ìœ$]ûÀ Š¼o‘6„
+‹ÐØx”sȵG¿ø¤Zô<ïeg®sXíÍBºby³ ¡H“ãSŽaœÔE— tIv)T
+¥´,å÷¾åAA0°!sï¦ýž+Â÷œ3{óiè´;u០ÔÉ´ R¨'7§ŸµU§/©)‘¡¹ê=×Áа™œ‚›|O&°RÁ´!ü׈Óq™þ3¬ØNˆ
+  `®/Ïùõã:y¼)·J–±ÿ7è”ä {’£¤¥uùœä€ôe8ºÆú%ÉÂfå*jIr@H «Ò9È@*è:ã5É1Z0‚ÉUÜÝÞ’jŸ°Íï}Or@hw¬nÊÁCÚ#É1ê4½K¿{0º%9 $ ff\éêÀ@DT°)¯¼Ùè3–Yƒµ2™GÏ?BÚF¨¸ôônæÍâ¯_scäG# ¢Ò0õüØ›Fs³ŽÞŽJñ8,]ƒ¦]:sÝÚØtæ¦Á^ÿßøó/AWöBU)ÈžJé!0<Á4þügƒÈ‚•-§,co~X>âΨÇâ©Ó´ Ü£Oª{źEEEj¼C¦’V‹V0— +ƒ+’í0 7)ËЖj È†Ý ªÝôJ^£É ·f[¹3Ô¡›;‚3àGÌ©ÝŠI¢ï gãæ åY[ݲT• p¹ó¹vR6“ÖÍ׆p”,·”©„‰7¦~yCp.°*íÁ}+.$m2m „ÐК]W϶NÂÙäŽÀؽZ¹–›íBb‘ö†¥][}‚ÕŸ D;Ù2•)à?¥[¥À¤«„j »7"ÏóR@ƒ T"WFjä«~X- VÀYl$Í“àÛêö_š8µ&6XGó;÷ Ò‰$tNçîˆ5rT«w~]C®/èÁiÍUyZßÜZ¿XÖ9Vß ý¦-
+Ôl|<ÖÖÖA¤¡èôµ—áÀ_4ŠADÿEV:Ù"‘Ò…%ñßw¢X¦ñuh"úVõê!ðµ@èÁÚ\E
+=ËrX›C Ú&ØD6»R"LÞ|#NÁŠg:‹¬‡fÝa~0…¤¸.Ù¨ó‚qÀ…NÍ⼶úOÆ9…MN²m(¢•mð»È¸&YTª¿ÉI Ä
+hÂT¹iÚ{
+k€6üðF`p´ÊñMpY¼ŽK
+uD{·¤Ègù¯)§ƒ~0v˜Åv˜f2pz_¤Ò#݃“1èˆ×z^S4t“zÆáöuðLøCLd<R)x7­óðÜ_ǽÙà¿_@mÅ>¢“ä¦àª-ÌÓ¬3V# d#’UÌ;¡Â”"ìN+ª¼Ö\pWg‰çå xYhs4̓ñ_ &L~w–å¦æÊGc‘à¢Ó)ÇEv;Úlp«P%¾—²úVx§G6ùgCHZDLì‡AX„ÂÃmwåRÙáŸXÜÂ>¼2 ê {ÒRv¨óªŠÙ‰éµœŽy-ssÓT'Q¡…äõû€ØNôÛT(ÙÛ:YóÄѧšÇagï0q¹ŒûáNŒo Ù—©²ÓüƒQö:ÏŽQÄ‹ùµÜÍ€DŽ`ŒßàýƒL¤±Ä¾÷î[ݼ…œc]"E{)—ÄK>óÈ‚ÃÄåŽFñ-Ø„«ï-ø……ƒ@þ<y!•¼˜ª©ÿ 2äFˆÑ^ŠîÞ øåËÈ oÉîZë01¿Ây¢ÈÊ&Š|¦±ã(Ãkƒæer«A¸SæD!”·ç„%‹~¥ù]”1¤èô$Œ;÷:jœ"b,}C¸bÂr4ë ÁcCájõ´!ʹöêa^¾eš·±^ b-üÅÝ^GÒ5–‚ÙixYâ)N{8ÙÞܸ´?³
+ -œ gCô\m‚Ojšè8rYþS¶i#p“çk» Å*‘ê Û ÁEÀ°>„
+Mm˜10‡‡Ïãe—?{ýŒøàý¯'†€K Ùy÷è„»M+ÃȳÆãf@
+JqX„’gº âgH§A`è Ãàv^þxˆÙ!¸«ž¨^URºÎƒIƒƒàI›þB~l±îZ)ÇÐé„;ÄÀ›+!¦Xøÿ
+ŽnJŠ²ìúIˆmE¿¢ÓD¢ÙžÖá…E]SçO̘"ŸŒ±&aöäú{ʇXe[ÅÌHZ»‚±¯*:‚ö:lgÊ­—sfª«TÊ£X5W<¥½P«ìôÆ«äxöz¹÷•VBK ¥µ;449ss©¼rBä~Jœ\‰žæH¹"S,;iIÁæÉŠrßÙró³!TlgÎl% )Vp£K0Øv˜›×<=2Š¦
+µéã¹®­/§m%—ÛaÊ>Óa®¶“D–È-´Xyš1j ÛÏ­óâï€ÀГ‹)þQÞÙíù|û­Íâ‡<W‘RÇîCœäÏiòÑßÿ:‚”ä†2D_vãëÄßW'¼¶Ú0âfÓ¤<80wp 5D•$ šýª±Éùä'× ½=ßÁn“#®Òü¤½ŽsVrŽõœUÂá â…z<@l+&M¥ÐíZÜ°¯Še×V´v[¼¼Ù)ÀÛô|Qk9ض—²UÑrfAh—„·GÛ^G^M†nz¬„^hÂÔN•*Ã"4Êaï‘ƨ2PvBr(0,å•N‘‚&;DT¢T ‚Ó„|k—bIXE¼ M/Èà
+¨{þ~]‹öBúºo5°ªô/]a¥b x¹Ð%݆ÈZ3¥XÉåÎh-JOŸ uUÇ™+ö~¾@·VþS `â •ÕZú1è»üzÂ|ËOGHÄÍàÅp`²ÿGÈ=i@wûº kÓpÃ’‰°Î‡è„€7Üþ #¾ÕK ÄûÃ:òÁØlЮè "»!Egš·bšqÒÏÖž¶ªJ!T ?ð)P¹´£ð^Þp}îTpq
+…TE¨ZvÁY‘vfH J/v
+àRmq†¿Ö ‚×Ð4¯BÜ‚€ݦoUeR¡Öœ60¶¶ëæv`è†u¨£WA¹NeµÙ ŠdPÄR^;}5t)ÃóCîÑÌ»h©ìPÒ`8S/¨¦Ø´­©/²9Ktº‹Î'ïz=Ö“ ,!f>+5.ï…jª7ÕCþ€c'>?Ûi¦*À3 ½ß ¿v÷…%â.{X‡o>ÂðPK!±§uðÕx?5:–€±¢2“í$ ^ágèÍnÞù
+@PÖÍša1ÿ TV¬S‹O4H’ƒ„0†½°j‰#
+úµV”ló ÚsñïF'åº W ÞRŒ¡Zk±.T‚Yó©„€z@{Ö}ü*8Ì RÔ¾hjä[Ý(s óU.=ëòÝ%&³{Ê5™F¡ãâ‘Itk‡zGöÖd£°MÈ ¤¸Fù" w/ eÃÑ b5Ò€{ç$âE»»DXCÒjw^¡ßp<u;µ«µÄ‚s\´"A ¤ªfuB“ ÂTÍ{4Ì
+I2€˜—šO³z]g2gHûLߊuKiYži#´=‰ ´KõªUH’ÖµÓü(â=¬’¼Ê.Æ¥" ÓâÅüh<ÃW^ýô÷o„ÿùö
+ÁpbB¤ ;šÞ!XZì/ IÕxØ
+Üšï‡w¥ F{*~#‚ uO-‚Š©ŽõÖRjãG–Hn%Þ¡¯}þž~掙™G¯þ.“»jH†-…N²Ð1Jl©Ä"d üÓw"¦˜"ůf¥o™aÛ ·2ä4­¶Cˆ2áä°xŒ-Y;Ãuša£,©hÓÃØ="­ô`7+Øl*ŒÒ^ØSv¦?Õ'¥z(2ÒÕká²ñÄchpæVO¤^FÍ¥d—Š*¢gd*1Óð“›³FÍÂPÑÔ´tÜ™>97­ÌÄjÆa0[÷äbýÇä@CRl/7°<_qZÐÊéƒ Î\‡Î²>[*êÝPT(à0UÛ)ù{Qç<MCW@ EÐynœ7š£ Ð딌#p<`
+ËéPòóÇo-–• 0–D;f6Ù)Ä~|‹nAie a‘Móùcš:Ý–ûú›=ýÒÖ?þ¡´óš9FMëX
+ 2»„në‚üæ#ؤùØÅPWÛRÈOÙµ-AR¨Zöªø6èc£Rz‚#êK9N%4¶SuªCQ%r°%ýv*`uðFy— ß‘ä*æ8^ ÀyzÔ`]o…„3Ѐb<⫺& ÅÒÝ•à}Œ{î缕X²:Þr¬|ÿŽ¦J€Þy¸^tƒVjÃÇ
+FcBuœaÂ0bF–£_L謃WlÉOEëðYnÀ„à6äÚÃ;`Uí¨
+L4­þ7V7ÍiëÍe94¡}ç¦\¼ÔQ$!¡¶£VzˆŠ«%\ºô*¤ô
+ !•0ß&:_´€öh
+}«$qˆF¸™ÕJ´Õ=PiÛ% Ng{xá´Ä‚7—ø™Ù`bCšG³&ûŠµâHtÍÇ*ÑÁ™þ1P¢Hz¯±]‚’PhW~ 6Dm(ÏŸ|%z²Ç¬V5Ú`#ð²°¿Çý‰%”… X ÿ×âwh¡•TqFg‡Éu5
+b@×…—ºdõ3IÆw“Ð"ÆžôÕStˆPÙŠ°qš—fîÃ…™û Äž¯í`X¼BÜqAªÒø¿´n‡^ÒíSQÅž“AÂpbEë4sÖ“%M`‰^£•qÝÅ°w‹åPâ6ËE‘A4ðOßIB×BG6;¸’¨däåá”…Í!t‡ýºòý†œïúLhz«¼Ñ[ª’„ÔKò¯pdêD[©ê«K-UY*
+ÌÌ\è@8¬Ò4äÓŠ¸ßª¼
+šð DDþcdžî‘èžtˆ£ðô­¸hlå»ð°:º!Z«GM@Æöí£â£Á3ä+4¿—¢À©è)Ž%ÌCÍ·§’&4ÛŒô¸R]rGfÃ/#äöqó¶Ê+6¦³œÒ
+Ö‚8þ"kM—iNBPÃH$Á`Ap·†9NH ÉۦϱaZ[lcK-PKvagè#Di;®‘hÉ©Uà ¸öõJÞùö­ˆËÊ:@$GÄùqÚŒ<@ítMy8ì­ç'=9}©&ÌZVm9ƒ˜A ØbÛŸÁ6‹–NÛ†=¼jŒ‘;wËhäš·Žf:‹áÐáŠr!C ´)0±wœE|Z6˜½ýÔ0l’†/»„$…– ’¨° vÈÓ¥à%\\Ô˜exà¡!'Õ¥]TÈ.ÌxÖPP‘‚6]lËxÀ@`­Î\Ò®ÜîÑÐ#·ÍìôX&D’P
+¶ßR1+ aÖ^ÊÄb|!Þ °ëÜúx‘­04†¨x8h É úRÓ‹ù¶ZŽ’tº=Æ,#á´fÍv5Š~”æ½ @$–•QZÅT®bœH¨G‹æµéD–ë—o.R¢uZ¶ÃáŠ|Î4=-´±uV‘a:¬#ÞþÄè­ÐÕø?s+úz*Ò2™[=z ûáºÕ÷:þS ÓT*=B÷_Ž‡m’_pO?8)ÛÉi€Æçn0öf%]!‡adæS V$£W®ü…<ãÙ±û;`ó šç–=ñ ¶hÇÙKrdZº¿<”TÔ‘žñk¥T16vmÀÅ”Œ´„6Úwt È<­j%‘¿ïL§›&0+0ªþà/£»^S
+®“¿Öp_‚ É€ìîëXŽò/œ7(¾,5&¡T#h1$œ1åÒ»„aOŠ6©Ô¢ˆ1Ÿ€³ýäp N€D:ÖÂè|…<‘ý…ô­ ËB^âFš]¢Æ,±Û qIâáKEYY,Jv–KiOžSñæ™5«×€´K’&Âc;>t.‘—Êa%¼@Á¥«“&QÝ•w ò]¥8Ù˜BB
+wàÉu&J0êÉ:Íz=,\¶CÉÏ¿Ä´^Â6xf€C”° `Áí$#râï]$IVäjÛ±(‚?š¾ˆ<î§/)lè/û¡h•ÀxZ&®N/A›ÅBaC{ü„*¢BÛÜO¶ 
+ h:ãÅϵÞ1Eß4Èj\Óî²ø©g¥Ëé[Šxƶ³Õ2*1„. œvª"g£ÛDÄ”¦Ë(VC"Ëtt­ÓV¢W‚\lÛLÕ º€Lß%™ßИ˜ÍØ%t:åÇ!ŠøtìÔìŒƤ®£ÛŽååUÄi+)€¥ ›í\ñ“÷šh‰c&û}Œ‹Z!ˆ:uê‰}è\3„¤yà™!u^ö…*ÊÄ’KL12Þdºu{5/ 9JÊ[µ`‘Wf’P‘m7‹–¸®áqç¥Ä–"À¢€øø!Ð Á·’ÞÄ,„ý”o}N ŸÀãI.&¸éSÂ%Š¯¾;¶(XÛzÇ ¥VA×! Ï°K’˜;’û, bn\ÂýHéS”ÄsÕ߉ØÊ}IxöW2:ÏC0+ôè±´•{ßÃxCÊ9 KÉš
+Ñî
+y€Eó•øF¥­Yé+$\! ´ ¿É-RâU{(A‡1#h\3øïßÈÍ/”)le¢ÅhYz—€W¶2å^¹
+Ì,«Í¡«P®ûò²IÒã6‚è tŸ`ÿ?kzÉ[8Â+êþ[½ªšê¯ÑÖX”©q€ª2_Ñþ~{…û¤ä#Ôm5Q2¹bMeÝ…Ù1\JíäÕ²~}-àaŒä)CËùOeÏ@‚²2¶‚My^¿.¸“  ®h½¥q†*c`tƒ£$H©I…`éxïš5$³lLR ÀÀg-
+:Àªoùà>.IQùr~Âè2í»'#D¾ xœ†=ü‹Ý
+¼Ï÷Öx´R$=´´Î3ó-ŠÜd€š2Zô,jk¬€Œ¹ûMQen<èRÍ4h 6'ê–(ƒù šº»¯PŠ>ä"·ˆ§´äƒs\f9y…¡ ›°5ÎBÚŸÖ Ò‚3®F JZuCòFn¤Ù<ñˆŸaÖç'¼»‹¿iëa_E·r™çØQƒ„þf'Ú4·œ,®!ÅB¢Š½å0^YðePxú|IIP‚µz`Úê+_†"‡é™-÷(¬ªŠôû»I¬¼¸¼Ž'‚óãm‹/ÂòÃ8†òbAä—ë³ß„(kÌÁ‚º­7ô–bP0¨Ìu—°$ó_0 º€»&c Ù_êï3câ.‘²z–ŽíYÓP›%D3~j"0ÛÒ›.>R"¨!êÈõ"*|Ž:Éixii> \ à<zg!
+=t¼e ÎTËX½ÙCQ¼´TÃrH‹fn¤*¶ÏpQ óë œjáwp3R@Œ»àɳ_ ™ÏÛQŽÕh”»aNóí5±É
+kË6}ò/à!`¸–*Ü‘ ºƒ‘Q‰*¨vPÄ/>Ée|
+›§¸¸ôëŽÃ€÷É
+ª`‹š>Q7¡šÝ0
+†ÃMÄûPžÄ¼  i2V2< ý¬¸™þ?N"h€86_Zw>D°-×€á0`ÔxÜLCíØLazD(
+16Æ:GÞç2»T…d¿^_J“âjÛ«ix~+0]Î jeóMyŸš—{Ù0ÿp‡Ðªpª^Qfd ±ó
+xý™>ÀDq;}ß½²ÀËŽIlrþPx#Ü«ü9!Á¼AXZÑwbÓª9/ØM®šóè‰m¥›¾WçuÒ—^’Ìáeš_0ÅJlÒÁFQxZ"³¨¸q§ÌBõ[Qy T™ªÕÈ@iïuȨ…¦—ú笔öC‘[}Ø[®±”â"¦²ƒ1ÌçBî“È™wpCªw9¡â[9Ðàœ2'?í$;®Lœ¢¥aéŒ,Én‡÷Çš"å…C›èjÚÎèpMES¢ÕKäØ«Øa>ó|Éלڊ7çúlÍ–ÓØo&Ñ"ßžû¡«6@ò7" t™oÝ@´Æ®Ô¡­Ú¹tX‡H wŠmUô wكهäÇÿe³ÆO9Œ^ã< üŸñ:8PÀaó5ü]ôó(RÏ•WÆðDZ(EÔó?é]Äôˆ½Ñ…’Ptà
+ŸÏÀH˜›dRó\5cgý¶è´Ùü©Š¦¤~QÊ?‹NðØî[¢JIDʈaÚ«ƒŽ" ’2®Ž>IfS‰p½Ç£¤­
+Ð É;³%"#g VLy ±–IÑåSA¥@ $mb‰ÒB:
+F7ûªñ¥@Š)®ABjÙsN'V±­¸©¢nïëtÝ&`ª$• %,ÐC1#~ –3¡ÎûŸ]ƒbUÜ‚_œGºZeŠCe–¯C·ã²ØMK[’y:,°LŒû‰ºæmó'ÑÍì~m4$bÇÃID„-OkHÐyx'8Žç¨GXÑW)”„8nóÑýL°ˆK×:w‘O!ãs\rG$Ì‹®.h|˜¯«‰€†kŠèÅ™„˜#¨ãqdUN§È ÉúAb;•‰W2’ÄzË FT¤´=(<&J}PkeŽtÊ
+ï¼{[=—¡É©5ª‡;<xI×Iª ü†u:\‰{t;i¥©Ëìù¦ñœŠdÌ^†IrDµ¬Óò ¸øbR¡›«íz—«lF…c‚!]Æu ÅzÒF\D¶ó`SSË;Xo[œQAàcŒÑH/¶»|z’Ƥ`§!ð(Æ g’íDsDý–ç>Êd¥l!RVšÎ3²±O#é/Ý«´0}à‡IU^ÃPFtÉ-СDYáÀá°ÇdçÈlÂ.F¾´x¾àrŒK@Rx“P¹øA:µk§ÿÉ?†Tµ/ôŠi—Í° ADš X?{ اèçÚ®á(½ðŠo¬R18&QÚ†”xc DÔ[`ì¬a“ì·D'ƈÜTÏ!‘7Ûž¾%:]Ác»o‰ rÝAä$ù
+‚äïð‰!Qå6f £ø2DÁ|P'Úß $|ðT$ÁBt}älðÆ (pÙÆSWgÊ'ƒðN|3ÿO‰wᱫvY{ŽëðU”†¤¨'‰í¤m)­»ãÃPŸ­&VžÆ×ù€ª¼‰˜–ï¿@ȳ£ë¨yéAª³ó Ç¯B 喸ÔÞ_ II7<ÇÉôN!H˜EZÅ°Ò#… ÉÔƒÚ»„øB!ÏŒxp}SÊâ…qäIxêÑVpÆ:Wòƒå ê9bˆ$±¨°zäå‹ïêv^8D"L‹Gú±y%ÉY~Ia—#‡<ýÀ!¿Ê‚â\t祈¥/w9Iò€aR龬Óæ­ï8X ÎK6µ¼9ä âÈ‘Ê $ÿÜù*S$¿ÙŽ:þ?D·í~}çLvôÇZ´ŽZφ%1š¸ÞD?_D·&["înòQï o‰žÛ=¾ï[¢Ó”/Z¡‘ÏaÄï‹Nì÷¸ÌѯïÜøz˜ý[ÒDŸq‚Ä°¹­â
+PWFMØã<De¡ŸŒ!¯¦J
+ì•7c º–à/ÃÚ,‘.
+V猻¸ì*|3HD°ï”‡&ƒrâD”qú¹×á;µ`£gùRþ
+iÁKgKòEàÓpKc¯3€×É7)Õ·¤‘]I6Zó–ôRù,¦>$¶ Ùe}Z‡š+¹{? ŽÎÅýR‘)—üÃ1ûðbÍ¢5L«Îé;qëüC;FçýÞ„²aò»{à¦÷‘SζWÈq<Øa0ó‚ùÖ«/pô95¨T¾WÚCoJ¼-âÿƒÆ Xcý( W5ÑvÝ”š»Rõ&у/š²«¡ý{okÔj¾@×2wœº=ÕàÙZ’A{ª0t€s°á2(•“|Ê‹$é'#R׿Ÿê!ªƒš%%“Jgy… ù’åG*=ÇñÉ©¿è.—$9nˆ^E'˜ ~×smG÷ßêe(©»Ø‡C¶Ñ$ H䧢}¸4ÞÓîYñåfŒÙ"VüŸ=6*8Ó¡up½'
+<z1…J°ŠZÐm—È” =Øñ¾K®¯’˜úc.–æµ%‡ÖfÔ#£EÕa¦ÂÔäoÛÇ´\+‹[ üíû!ÊT4®¹E‚4s--Ö5—]Âx«a5Xä¸ Å`…Ô±kú•TIXà} Ö‘-ǃ./á"Zu Yu—ÐN¬@µ¹K`‚,ˆœò½'å*âBk?¥6yÔ¶ŸÍ<±Dg¤U`3ˆ# éïÚL!{âaâhÂ
+ÂÇÌÅFð‡QFqù@.Ð9c/£@q[­Í[è4@Ûü=¤ᔋö@‡j˜¯ø僃Í8*˜h"†K/ni€‰éí
+iÀ×àkåS·ÞóÑ §ÈúÖWaùñK•g‡ýH÷b&ýÅò›ÔÀùnIIzÂ5Dó%Okû(".*šÈ5¯_§ÇÈ“’
+
+;6¥:ÜùkWpyÁÍrnIRP3TgùÞA 5Ã×½5Ï]‡"ü­,·’î<žS¿`Lfy–ü¡ÑdŽ@‰„÷}¼ ý• Hò~ŽERþzfl´?MOÇŦ{Ô$å“N{ ¯×jæ: >²ÉHT|9ôÝM[Ǥs
+™Ô¢ƒ ŸÁtz›ò:6
+8ñ¤ÄÕÀŽ’%H϶—j~Iû›DÏî|r½ þÛA’þW€
+H‰l—QŽd· EW=ÔO
+lNvŒˆÇƒÁ‘Õý«N®y˜—Æ7dæN\¬î;'ö6„ Æ-ä@öÍj„Ñu»‘àyÅ÷ +¡V´Ý(c/[î´2; îw"J00›¿ “K2(ê–Cn
+f¨jG°TÙ€B>¢3Ä»EµEg
+Å$Áᕤ“òê€ùù.žªï
+µŒ_ìR“;m ¤°!’ªOmeóC^’aäÚ;ë€îìðóÜaÌáù.d_Ïb֙ð]8÷Öóà%è‹âÒï J»×ØKÈ2Â%r¥ÑEHµÛd~"&Ô¶“·TºiE#«¦Qɘ¢’E‡¤ð][«CûO]‚mYÖ æ­ëimQøÂØÈ1 vù1×oäÞ$Iq+au )¤4ØÔº™[×Ãèä?4Ù™±æVQ-¾ÃÏ4þ´Ùºj{7ƼÞ¹Ô]ÇØKFù—RÉcÀ½¨c˜‹¹HÒó©•:æU«îMðD†úôÉO A6K¢5!†z9Ðœ]lš­¢4é.뤆ÿHä÷g¼˜p 2œÊ ñ1 qÑ7ŒÁÕ¡ $£h†˜Çqÿ{ÁézÚQ+‚´t]ÿM‹6…´B¯() ‡…“B±ðê†wFö»Ý ÍGö%¯!ÒÝôœá®¤„P?R‰°Î‹ƒ•GA÷Ì"*¼d5è4 X>ƒm½Z&°À
+,8d…â"Âd ¨­çšÉ
+Uc[³¼!Xl\4Îû þ©õNéZ†Bä15žK¨“­±8X;m¨Û™òt:ïS½1HÏfðγwÿÊŽÆ´fØÛqF"“ÓfmZ¿É'ìÉ ä4“˜| ¸(Wj€ ZŠXa–’ÝJöTÒëSJ…£A±¤ñR˜GaÄÓOÞ
+\=4t²3?˯›Š¢¥—”âa¼di1$š´è¹]vx÷剘;¬[ÙáùZ ŒßØåÆ®S0V/!ð•wtë5¼H° ÝçÚpØdä!˜v0êST_/<æ¨z‹]­†¦Ñ±:`åÊ‹F¥‰C9È,æG‘»ûTœ­àíZ«Õ¨ÐM²P@UŒlðPŒT»óf´¢”Œ‹iIö >Üò„]ZóÖÃ7îa@Ÿy8´‚… – A€ü±Z¦†ÏAž{ŽÃ¾H6w@£é5ƒŸÍà… +[A“ŽØzê´8c
+Óêi2vÐHÍø‡‹sho¶4§Ð-4TÃ.Z¨#bó6ïR E[Ni™¶{i1¶ò\M‹†–tˆ€ÖUª
+’xÌÕÉ =P ®ã¶±ò¸3’äœ6ªÓð%"5³K#€¤4@ú,¸=†ú †ÛÓNmFZ°§„Ò}ê°Õ,ØÌçMѦ‰/“LQ0’9™íhŒbuÌé®F/ºN
+ì’}W%À:PbtÎ[i”’– b®m³‰Nɪ½‘CcWiè#¡üWцâ˜z»<Ý@ꣴ6O@iQc¡ãÿ¬—mT¹…Áü‡û%DaðËõõuò‰·$$³D-Qµ&L0Ýhh‚ø÷yNÙîº{–|ˆv‡»n¹\®:u!“g;I“ IÖ†¯îaÞâ£2mßÔ+ûn¢¨û{L¡Ðf'hÓô"-”®)µ%XAé
+}ÈuŸ–²ýIÈt-v*Ä7}ì…ᦖB#¸úªê¹RI"aŽ …n% V”^øXØ­›×É2)õÊŸZ¼}[IŠZÒCֶƯi[èF8ak0ÚÆÕ¼Þ‘,™ ;‘ÞðGˆl2Fƒž¡"x
+ñÖâ@+LùÔçzvÕÔÄÈP ½ e·‘˜YXÃ1·jE{\ŠÂ…¡B. f:·q¤ÏÂ!¨¢I¸BoÑ ”)£I
+£„–¦<̃Õ:°œÔö
+C/§ 3òž¼3Å r`‘„#èWÅÀeOX!B– ˜›h¬V1T«,÷²*@$ìž©œm 2œy}ºŒ ¦Ù£b}C0‘â¡BQ³GDO'irÇV·X%5•hÄÍÎgF
+}ŽÔðõä©a}‰@´YÐæƒ7Þ÷ñd†T ÁF¹Š¦ÎڌۢyU~ØæcƒŒpìŒáp/ÍõÃkÚÔTÌ -Eý3Ç(Â:¾ðâñ…΀YÔ^
+í$)(Y!p¨'l“¦N€©ŒŒ4Æpbƒ2­)€…>æJƒÍ`S±{½š‘/ÊbÆô áM *µ‰X<“1çj%L… †Š8¶¨5­4t(y<ᇣíàij,‚8/âHïÌš‘½ìÑ­D r°G´ÌS&MU<zj>t`’Ä3·qî X“ 4Hp”de´ªSpbï G€‹pÎ{J‚òÔ·¦! îÄov~ŒI±0?8‰;©$ù\c‚{ÐFIª€Œì n/. à"=c³ÈÕ
+n¹
+®Uò¨æöñ„ Ö)D½“8¥Ä‘>Ο2`‚A~Ȩ½É‘Q¦i;Ò0)Ñ‚¬£$^ž¸o†‚›„:.‘¦›Ý‡qgÅfy¢›x3AqÎí>Äš1’¨Ïj¥¹ŒSÐÜ09Ì€Ñ ¢¨ éž“f!Ñ+ "6 ND°Á‰Y©@˜¿.äzPJ*²D4cõ#é*?³é>,¦ImŸ¼SÛ•(Y€£Õµ%H¢ Æ~RÓc#è3‚œKu‘:P¿¨DcY8Z7[r‹Õ;°F+²€TL`X¨±th¥3«;ÍòÃÓVÀ1æXßš\z½5´Z±øf!q˜æc ëÐ2W(/â—GV`ÏyQ·MtÅì謢Î’¢,Dý¤J3U¥¼Ô—%ŒæÖ7¹£¬Š† ¬Âܬàï-q,±Z„,-YJ­R©¤ÉFQ„Q³i4Ázd0w¨e.ÖeÍ‘`BVzQW@`öU’&(hQbE[]° ~ ù@¯ß§v*
+nc_À¸ä†[‰$›4ž¬r€Ô¤ò¯sµI;š¶æüÈ
+Ô²¹j% 9дÆÜ`ŽN”k†E#¤ÀG¨†¼µRý\ÉÆøÄ’EŸ]-Lnp5Ó€³˜ˆ
+B'›Ž) <bIð6™
+mÌb÷LDU=Hë%Ñ…af#û很Óúµ6—8ŽwžGVŸ“3‰*úX-µw#Õ—IÝŒ³&u›wÖk¢f+'áνAœU™¡
+·k"¾gð×ÔrxZ¨ÔÙ5Öoй6ÆŠnÊYW+­Î¿Œe¸§µišõÔúïWÃõó sŽ¨1–‹J5“Z][ã
+ÓÕŽ
+™Ê Ä÷D™Še×[²Ï}ØrÑ[v­°\W€ï$ï— ÇÒË•Ö÷K<‚âfUŠ{ÅÁnðüt C*ý‚«†’ó.i—æïmQ[ípÀ²§{+Òü9ÄÒ˜%.’C5ØåJ’%œÄ,w+ëÊ`MU"™Š¦ÒYd*ê½@iC’<Ö8‚ZðEϲ=?±|$›–.+»é˜éÃâ Þ<~?,ÂÚœ|Êg8ãO„«òØúw” ÂH N)d~²x¯úÄæ Öm&Yø·žm‰.«?ÕEQC
+Õ§)¾ÃÞ›3_…”ÒË´•KÓ­ü%bm^é« óÕX?Õï:›JŽ³½Þ¼ÊÍÃþH%nPMœ¦èd÷öíÌ^.QW,ˆ›~Ù
+opôà†ÃTŒ£bv€Vgn={“Án<ƒÙ‹2ý"
+ÕNn^˜Á%2,Üýøó6¤–+ø+Ë𢵺֊„Å¢qZ5é V§@®mWU~ 0Ô2ÏÖÓ¼uó&ãp.½Í€Uhp•cšw}¿{ß_°@iÕhÊ*à§Ô°,Îò1NÌ[Ÿñ@—Ïîwã…Âz23`%õå3o®ãFñ«·x¤â²ŒgGsس+æË篼r:UGÜd%òJ|MÀ%:È¡`» ‰n‰×„G"¼P³8+]°Ü¸Üfp¥¦Eéº,µH­]tT«ÊSgÓÙÞòï5ƒdï:ªµëÂ5ßcÆÑR¶eÀ¯>noÀF5dfGÝâ¿cç nÇú8˜²¸¯ƒe Ìt#@› J¿íÄ–J©¨Ëßôƒù9§$¥ŸÃ© >æàivÛñ¼vS€Ú¥ýüìÌ‚S˜ƒÊd”.lÕÀR¾~ÿ=/ÒÑ
+#5 R¶â$ßûý[â7c‹d¬ã(rÓÔöo1@ö·`VʼníAx&mÀ2OË8X
+ÏÖàJ‰¢¶²"nñ÷<7°#¼z1)N•X§¦tho¤í…úÐs/i¬bj˜þ“k¢tŠ®+Í0GWËâÃTY+m=çOÚJH/hM‚}wLôxÈ =Y®œX*+z¾ï6±XT!Bpï± ^w€}(-/˜ÿôC0§¬ß/lÞ•
+ ×çrD†0Üži ÍìéuöVÖÇ:ãN«W\|¹²k›)@í“kìÚ Ùß[¹¸
+­ ÎýÍ.”ñßÚ?g¨»\’&lí÷½˜A\ê|/X:_=ÿ
+ãH^—šë—vÆX=„1~žik×;N4€15- F‚¡é•õm‹”Ó˜ÝdZ9º^<8$4I“Koû n$¦ú~;.2XÅ;
+rÖ^‡î±tXˆEæð åŠÚÅô'MŸN‹;RŒ^Ǩô°Ðªd9€£äY‚Y
+€`„?íðYÿ’ïÈAÏ]pt…Y°l2n{e;Ò™›u>D[­}¹¾5†Ia=kihEëia
+óõ
+0Áö^ɸÚ?¦ªùñYGµO©äUàÜÛþS^¦†þCr`µZ×õ2€
+K¼Q¢µ“ì½ÔË€dÝŸuÞ~èAÖý•X
+&x›Œ[:õD=n‚ßÄ^ë ÐMâ³ k—t“³h=gúnÌARLØ‚JùêàûÙš@VTë—Èx¬µ%û p'Áö4µ!x΋OŸ¬xZIå¤ûX\aô:ãl'Hgw•ë
+0"*
+hs{ήºÇÚÞT·*€ìKûgþ®º‚ßÒKX{¥\V%ÁçXïÚݵ¶ÄѯR8jX'î·}8«
+”¨IN5õÃÈ©Há54LÑBJ$VðQúù‡ðd=¡'aC(銠À«
+t/A—Tut0ÐÊ9÷¼b݃R¹É¨st p*¥Œê¯r
+„×K¤é’ Ùec’שּׂç¯8Ÿð”2mÊ¢æÖ]Hš»¯Ø”i£G½ßªzN‡øÞqX—›Mõìy~¹ÙÎÉ¿}+†-XŸÅÁ‘bW³ñÀÝ6v ˈ—ïœ<tõNžåU
+Óð@\ä\~jr<¯$Ê dÓž°þòðriº¶z.Pfù4ÙG€»É ÍÞ…YùÌp„ÿð{éOtúÐa—è¾uÄÌ‰à„­ŸCrŸ}
+†’ Oa»¨š¹Ë‘g1_ø û[dpÍ*¶{­­IEípÎõ«Ì/€?º–6œ—bÕ8zºtAªŽ®B
+0D_Ã{}/7³á¶º•›Øv…5ùËÕPÖ­EÕ>ˆãR0軀6ÕÍ üÆÍz‰ù‘êÆZÔø’y}TùV'íIi!¬cÙk¼®1Jì_ÔÞ¾
+ìIð\1^cñûè;‰SLÀqFTÐE‚ëˆöªÜÐjm6ïÖZo¥Ú{´[•™C±ïÕ ú¸Û;Jóv{¿u<_IÃüpó€9Ú†~<: ÐÊé68;°EFUòÔiš•8jÕž/Wˬ¯Þ^Rúüo7õ¬¹_†ܽtÕ.×~ƒE·æ
+pÅNÓ
+:“w8»-¸sèÅÂ[*À
+§‘ÇÜ SßɲÅZvFãB?w~Mê:lå¶fɸVw5éì&pœ/ÀhzHCó23èsߌ;W»E* µÁ hi-äÅzŠ¸Êfg
+)<ê¶/I~–³>ÞðšàEí3Äi’FÇØÅ
+t¥LÈ âqÄ 9g\°0,y–Ë/ð ó—{µ3Lõ]ÐÁXGMv%«·)¦Â«à>¾¤ßA´¼Ëöx¾%ÜIYR¼Ö&ØvcÞ¯?ü¾ou”õ–Oü-GŠî½÷•ëzî7tI@dR¤†ÂbOgçàÔ_7-ŸõùpE½›ÕŒ—Î,¾Ž&t®,ÊóÔçŸÑÆ8×Êâª÷êN—Þ¹'Í(
+PiÍ ¸“»1‚í¹IQÑÁ—³Äߦ¾x¡©Ð_¨‰ †À*è*3  ©QåÕ±€ÚJ+"ïb
+hƒ4“Ygoá
+”§ðQÒ›¼ç.¥£eÝ!˜V.6ê«Øç·w€=³YKå/<¸•Þ¯pÙÄ
+VÕFžûf+³tå÷HFQH««ù¹ ¶Bâš–A“—™·¾ :YÅÚA%Ò" JÌ5ÊBõUÃp%¹Ú¶ÊUn‘ŒÊ4Gõ(!gÖ-jÿ­Œ]µžUQÛÏd%OÁ$R1øŽ!¯¦¸oh7•ÁCÁqmÒàyÍ•(‰Ê¨åš¨\4¾•Ê¤Žù–…4 }«Ø …%Æïç4Rýy}l‰ÿQŸáÄmšµ6ëPÀ!æ7&˜õ-:°‰Ä„GvM)A€XŠÇáM0~Å@áQ€¡LÄq¿ÄaL”ÇTËžÓX•û
+= ’²Lû%Ù3,gâ-°xqËG£Pþ}Vâ˜N†Ï‚U<ŸµV:V lYåDå9Ç™ïä‚ñBØk*[­„yl´õ¡FŒÈ(0/“¬_ =ú óÎH/¢Ä ÁÑs:l*›Àà=¿žKN@ßj~é¬î&亲Cd rÖÃg-ì3>-‹\–ˆ^„•ÆªXyZl: ƒÉ1hLÀ
+“‹d£X5F Œx0QÇ{J†;@ï1Ê›ÆTßp
+̆1ÈV6n„wŽvR^¢°˜qÅ
+‰©ÊvP;‘5­âÊ
+ 7^ Ø:jERxíª¨E›!N¹+%Å|ÐâÕH5´Ëše%éh(3TÕ!$žgÐT͉âÕ1Qam™, ‚Äêóâ"·’FBƒe‡¬(³àT¶Ù,jŠØˆùèy®€’*<bbŠmë²Í”ÑKr²/0O"OŸÄº~™m€tŬ–
+òšòžÏz€F¾2Í–wqÞ-_mn4¬Aâú·yºàMÔ)g8ªò ÁËÎEtIGƒa¡:~—vDáÐö•Ïûº³ÜJ½xïŠ@Áu,®[R¶S[Ûã¤Óߊ°BìœX—Ý/’T,Í@aƒZ•ZÖÄÉ‘Eþs ›œ¸Ì«Ã˜”ÿ½Ô¼ðbsð'CŸ¶íØì\ž{íô™•£oά®ÎŸ^.àkóï/.Á/X^žéÏÏ5m
+!ÁS×€…ÁMZeþ
+Ö`ëØ…§†a\Ñ2Õ5±%80°Œ;÷÷@À-JCsPU-‘“oö`éÝ G
+iÌ"å3n+öT×½TÒ©¦S7¾£q…Ïz\õ ˆÆ-2V]£PU_ R¶—×UÍùeUWøNÏYüžür9:é§a³¸¸&o~õXÞx° k¡ÐËŒßG¥­ã4ªï#¢Ê6:®8J­2nK)jìÝYP4î,©/WQ‡|k^q®´bî¡c€Èg&!›´²®l.‡— »hsÎÖI¡
+…Š࿕ѳµˆä&!o¦ãã—‰¸¾»1ô–¢61ÝÕ¨SšªlÜz ú{þ‰äLyEÚ@‡u\Ô9V‹[®Ï.½ƒý : ¼(#“Ž±âêhÃöãÖ÷óó=ŸP U+ Û$ äÑPˆGGÁ^ îÄÀ^# »ÕdÂ<LÆ4mj±¨EÌã^Çá†×O£>`ÈT‰Z…¥Uk?°R€¿ÂÒxãÖLϱԿº?Z t¿W˜õjˆpÐXXÔ\Ú›|q¿ëýW¿ž ÖM人µÕu.Ülz76Õö7jÕ&åP¯¥°,ùzã—+ÞzØõ!U4ÑQåed ƒzMâT°]FA^#‡ÜG¹à-wêIÄ¥,ùlhšÏoÐðsÜ4P ›zÉ5SY„bæ1ã0úˆ°u˜MzÍtRÛKFT­<
+X€r.åÒ±¨[Ïb>;‹‡¦HØk.E’j̧¡`¿Éx]tÖi$S.= 8ë7‰³s×?Û|">Íç‚ß³›ß³9ŸŸßÞ®?Ÿ¼Ç¥½.±ˆYX×M&åM<®èà3ª¾
+,>WŒK.ðB*dN-aè§1]/ŸÖöó¸~°W¶ä—$_1»¼ŽNÿr˜ž~H§ìÊR\Ó±¿.?•_$“NÅÑÆäOÀ»n6k×Ôs“?²éé
+¿y¯Œ:55XÓUMj:*°UÂçBwÙ´]z¨àð`ˆÁ‚>ó˜êËø›?ì>cÓ0˜SÃBÆa*,¿@ÆíÒ ˆÇÂÞrÁ[$f–î- ?Û]:±·,8UŽ©[³3‚†©ñ“ï<µ];Æ¥~\?X’_ÌýÜý×÷…Ç*ËÚVw›¹œÇA§¬c æPí\‡¸ÏUO»M j“íÍk/î-ê[Jqûèdº¾4ÕöÞÎcM —ô[±P¨Û³}ï><^ŽØD U4 T §jwQz
+x‡
+Ï¥M¤îà’² ¬¾FÁfQÌ7À’ì0¦}ž£œÛI#†Aø†Á½ö÷¬dý¶ŽÐIÛè!â1ÿui_§týGiE;Ë®‡>'–Íš •"ªöÒŠ¤¡Ž; ¯s^Ï›—þ)>í2‘°CAÂ>+þ ìR‘WG‚•Nƒìßð…¸ç[ÜF`’ËxltÆ¡{µ¦ºr
+ðÈ4¿¸ êæáˉ»õÍà>3ùðž‘ ý•ˆ¤‚$$½Pˆ
+N¢âÀ¥ª4 Q‡’‚-b.m¸Î`Ê6SŒýçÎÓÁãÕ°QXÇnÿ›Ã'§kC^Ž™…Õ¸aˆDÌ£dÒ.å³>?“qhˇ›S¿ñ¹[ÉÔD¨Š:µtJÝÅ¥4=õ¬YÆfÌJU´íGÕmëÈ«U©ÐÔÿ6Ý®7X´$b"’6q3Ž0E+ ò³œpŽ]”\fê…û<`æ–bê.Ö DÛ_Nj;w—Fð{]oÿªlæñ»«û󦎭ٙ¢ò˜<¬ëç1“ˆÍBó9Yl"H#~+ ytµ¨U@ÿŸã2}jã¾ÃøËN§Ó™N_¶q2M&uÇIÓÒØñ0›Ó˜p #s :V÷¹BB|àØqÛL\ã Ì)$ÐJZ skuì¡]IéÒ/}±o¤™ßî|Ï÷y>×$Èý_úÞ]·¼nùaë…ãYŸÆ€³Vô=„i"Ü¢*Ƨ¼[Àí.l5¦ýºî}à˜Ó²
+ts2§mʺum¤GÙHûT홤™
+è…TØfÜz%)<íütwJv}k¹¾?…ÜH/ª›Oæd•GÓÒò“YyUÆ£n%1ÍÝØ” dï%ûérAŽÑaM7á]§Š&¨º~ÝÍ…Á3‚CJtAacvý4®îËúÅÕ„§¿4½"­ÊúF¼=½ªå'ÝþѼ¦ùxV {©¸u<+,;xÕõåñ›o(·®ýÃë¾’Ý—’«'ïTµ^++‰7ú†íÉö‹«oüný_e—µ|³êXÜfÜ]DêR³°¸æ|˜‡û8Z꿶=ÕøñîÛ;…åÇnäVڧ퀜eWõ>¤gÃ6K!2< ™m`ÂÚ~&d“~m0
+óAT–‡Yp¤)×Ñxoùñ|ã§õ hmgFðurNX^¾8Û°ZÏ@+YÐrƧë&‰Y)ÈЬ_Å£€w˜(ªå¶˜¸ÅȬ™™u»öâ6ˆ2ÐB Õ7­Žâ¦ÅÂÅQCö§¸1öŒ‹Ú9Ü(Nyäõ…IYŒ™´…˜QSˆUlDÛGx‘
+˜*íSßûØ
+î¸Â^>¦•$1%okzðÚöŒ¢Š‹Œ~·Z‹q³Ž‹X‡Xð\i¡|Wögºþ¾ÿNRÁ†MH!î|ÂDGÆsQçC:rÿg66úOf™ê¹t²(¹ÎbŠÖšEÇm:&Næ +ÀÜ+ÊÆ”w°ŠXê+eýŠÈr>å×v¹eÕû zþ‰gÌž\µ"¤WÓ–õˆo/.ïN‹Kt­)*Ù™¬ŽþØüGr˜€&fijYÃK¯@¬Ö¦W´_uçpAT‘x.,ɺMý§a§34Ó>yCÒ;XC¬(nïÏÈ*fä7b¯û.›ú.ýúµªöÙY›ˆt[%™e}jQT±þ¾ýªó/“Ÿ'çUMàkÞË3çÀcH_oYÊÍÿ*½ÜñUjYðMjiàZÖ¯ì-k;÷g$7N#‹QîíîÉ’¨œX(˸ÅÛoÿxçªù}àqû¹U».³ªæ¼”$&Ûþ”xÖz!ñ7’òÄ´¨tDVò›ÍGòê¢ßaÉgp¸¼ :AkÒ#­9\–Vžx•ày&Yáœ?€=R^mû¹·¢zqÞÍÅôƒ¹5½˜Æ!SaÖ9ÿ£ŸiÜé‚ÙI˜ ¾Ÿ^S´mšõ…¸v€[Wv¸Å7Þ©Ï"®‰³-tèlSÑIa]— wWIr vER™ÃÕü\È â"-±Q!×=zmì vÝg€ 2 Ó”_ÑDø•-äš®Ÿ™”ì:ª=ç*âpÑa‹šØÐâ†Í~¶es7PCa5q1ØÙ5èE e6ägÃãOØõ‰™|ld¢°9dá6Lf
+û×ÆàºÞnVÐA³¬ÈÃ@f}jøRô™[d@ÉKze5TÈfJùô½I¯¢!·†ª¸õѧù¸óqaËæ*&¬#܆¡bÊvËd`6Ps6 (2ö”‹>xq¶íxLfLaçœ=,6ò¨£@Ôù·®[Pètíà•]4¦á§=’›„g°:ƒÉ¿ËâªN¼€‰Œÿ;·~*ƒÛLÉUð±sô—ˆcô¿VG
+“·„þÓ|ÄÆž÷Uƒ|„<g0}‹+x)OOÙΛÖ?ïL·}¾ Þý~ÞÖš”^ÛzÞ9íV5Al#½†.bÑÔ|TÙýåÖ$ÿ³|Ä„ìÍkš¡£09?—ĤuYŸ¨*åí¾²ý¢åã÷/zÿ–Y6öQ!T½÷Vz-íQßIyÁs`¾³ýWÏ >¹óÉ#é•_-YZ/f,}É9åmbV\NÌ ”§e5Ä¢¬úxvà[Ò+kHyÄ5™U¤96#„©?œ–/ôÂ]ˆk’ˢ볂’£Ea©ç‡ú°uÎ"ÚbT+¤0èBËòÚ£ÅÁJbIVM,Jo¼Ÿîý:ôŒéô´†žK{`ϽÊbIZµ÷¶ó‹Ä$ï³ãIÅÎ+á•Ç²«¿~ß]z, ^)#Áˆ)œ¥l¥ú~ðìžs_e¡ËBÎ 9ȇ ŽÊ’Ëòú”{°Š¯N{2ÀìtPþ»6dæ&rŽ1a×xôɬé„d@v›
+hø0
+ Ý wœ…¹SÀ”YLÅ£q~Óv¤0e EõlÌjec6·iµÀ`Gä#(·9ØÍ!øÏ>ÌFÇŸ1‘xŸý^>><ž‡ìƒgœ…~•¶ÌâêÎLX¸épa œò›D¹UKúÕí¤OÚ>ÏVý
+ìü#}·?hôËj´»ß÷ý|žGÛš]€ûòQ&<<^è$ œ§ØmÈ]ÿÜxyó£ÌO5îÎw_È®è[ß.™Z½S’¿“’ÅcG΋ÖSKêºÝYõwëÓÊóÉË?Ûé¿|”´˜·=ȵ]º|i`ÃÝqzÏ#9™]lùŒòJ«öç¤UE¯8Ct8+þ£ü –p¸¿biZ{ÖøQìQÃÈñ†B#MÌþ¢ÞAÃê?Þz&;sDê»ø€®†ûÜq˾Ü|ÑüÉÛç·ÿ
+=P->CÖƒ\¥ýÆžrÔx—ºóÐÛ¯:OoÎHND×þéíZμO ­<øã×Iòí”O]G-#5{s}²ÅÅ’mâH]{1
+ìs¸„Ô¼ƒR6dêç!û* £Š¡­ÞöªœWßY
+Ú-Ùy´úóVޫ뤽ºvEÓÈB&W‘¦Oç…õ鶓,!lÀª¥ ³’ñ›ûh˜)bêÿ-cµ½K[€1u–¨[¥8_ôãŸý‘&‡Kb¯¨›KA“Šm6³i« fs€KZq&1YmÅépCh;]ÈÏHeM)†4 ¹• ðEzè¡ÏØ“Jbü—JzÖúoUR:àõm8Cu9ábHÛ xŽ¾’ó¤ ?ö½èM&Œ¶C^ IJ“ºŽœ_U›g9™z·W¡GƒÀWñ¦ùÄÈd9iP²q­ŒOj;9ñ;nè£ã†;»à Ò†³ñ‰yœ€K8œÀ H‰ÔµüêÆbÀ gI‡9ëë­Þ÷ö\CùÈèƒÿûnĤÞlç!×بy œš€g¶ä g¸¸Ø ÷ž”Sc?WÀ…Ž€ÿÊi]/'öäšÕ.v\‰ÄUH£¥ÃÂ\“Á±rÒbbÂu‰ÄTá_eçfÆ®}P‰ O¥ï»ùÔðd!¦éØ™W]Þ˜15e]&.>1WÎbÂVC18ñŒ
+<%©È÷¿Æ:‚£lÂnç’W‘°Ü¥ƒN3v2!;ôì¸OyegYY½;\efÅÐ}òrÁch¥WïR‹Îì".ßöö`–6_Ȫöfûª¹€Uìq‰# k#v3 ¹ACÿmÍvœz;-?³¿€ÔòA;ƇGŠà¶E/ÖÉ®ÚPÚg’3«i~©÷âƳº?ï¹¥'©ye5íú7gºÏm½ý šU¥€YQð)¿Ýžnøøõ“Ú)w×9zYw›áª]³l’óàùå;)OˉÂBó§…%ézUô-“¢ n¸á–ÞšîþºLÚÌBÔ9$ÄlT°Q­¬è×J„8¼“®3 G¯`}\ddâp©ÿúösé§û¯äg‹ËH½ªi¦ ]»
+3í
+ðÒqÆyŸ‹¹Fi‘{€«™ ÝÀ’˜ι-Ï<hgcv+ÿÃÂuùUS 9Ì¥èèÔÛL¶5¯¾N“†ž£4n:†9|¿n-§Mšb8$â°Ã—)`ìC`26†ë„$¦=Y-á°3Q»™
+(ëödÿà‚¸¡ÊGœNjU×’[Ö+EŒŠÊÚУ
+ô£´`LðÑ"úág6êr11›)ÌJÙð™áÇÇo\SBÆbÍÃ{:\”Aæ^¢ƒ‰
+vöë5ðÒ‚¸ª3ŒÖ²8Ò eÈØ£¸~¼Vð³Þ¾‹5¶eŒrj4¡Cj³U]7Co-ôo3i²ºÔý¹ Ží9UÜÈkÑùœÓ (…1y)¦äÓ~YgÊ-l)ļR\!`ÂZ ²>Nò®´_-…ÜÕç#àJµî )úIŸ’ l)+†^žÐJ“Kª^ƯÇ
+!£• L•¨ÎT]GU•¸ÖÄ„•Ò'‚³X&HïðHÖ‹K aÃpiÍôK)n}]
+\BÁ¥‚¢öBÄ`Ù]Æx‰Yå-Ø+¸ÉÃbÌ0Rˆ,å8n„ÑVb,¹Ìk}§®?I-‡³+–G¡O© y¬3?.F­“5~;Z—ò
+AIçÚKÖ™ø«¦´ljÛiF6ƒ(é1hË«ÃOÊ1L›vJ:÷/ç}â;™eÁUÊ/é,÷µJpç ôzΫ<t*;÷—¤×¡ÃïU×qSi‘ÂY9)Æ! Ÿ>Ëød]›s=uÁ‡íÇ“óâŽÊªa,Ch‡2.ù-ï¼à=¤‡&P.<³+³ª†Ï‡=t"ìƒeQcÆ-mg¹›uÉÛsn„ubÞg½u¯D~ŸxÑs¥Á””¿æK¢[]Ü‹{s½?ÆŸÝ9•ž\+ùÕbʇòÓïd×*.“6¹(ïŠOõ~G;Á­Üòn†vfmÂFçƒÛÿÀÛOýÎfhùw%ª¿—òŠÛHŸŒUðkä•Ž ±/¤líߤ–Ùgö¦Û¾¬ƒMÅUqï«¿ž"4Š"ì3íQõC'ôüjQ’à7mÏp~¢ì¸º™ùÑο³Ø–sé¤C/Í, Ý䢒•µ«ØÎ]ßIo|õYjN‹2¡ñé¤S#ŠO žMÃWpàÜZb( ;–x3tžt¨é ͸5ÂŒ—“”[,†ß2ÀÕñÙÞKzNA-¡ÂjÄ4Aùý…„O}tPÖSŠ âbS¬½æÖ¿BêÿDŒµž¬ÄFßP¡{3YÿÈ£´—ËYª«ºá*ðã—ue’ʥ꥽j~!,î*GTÒ"8sÆD,O(øþ}ïâÖ<ï\rAÙV Œ”OÜΕƒÕ¨ùÅž‡ÛsKoï»%m;¶¡Æͼú”é_}7x>çÕ©˜¨åEau²]o$C¨(ë—³í¢ëñ)NÝÁœª£–™LÄ8’ ˜G™¨FÇDõÃ…ˆV[Ž¢2È ÁÆ,rsóƒìúÿ9.óç&Î;ŒÿéLgÚi:“ i!ÓN(!!c,߇°­û–VZiu[¶b0‡“š†k
+¨0°pB}•Ù‘žmʾƒáÏ¡3ýCÀç–¸¸ÏÉÄ0-
+Ïœ¥vßÒQÍe‘°)iÜ8ZßnKæé¦æâN}yÓÔ_?{»6üyáÞõO;†6KŽw¬SLê抸ùíòü‰&<ž£ CÏþªòkðÀ‘@5õ¸ÇZKÍ/ÒÄÂ]Ðë/4t 6ÈXÜ8ÖjåLÓ,.»T]ÿ˜‹é‡ÿ"Ó=›ÄBOw{M×. ªVÎ<ËÆf¿Û[•üåxS}f£gq›œ…ï
+ó÷9`µcèsLÖ娦¬²âKù—à˶<ÏvM5î4ò9hÕa‚Ž¤k¥­JúÚÑ6øLQÐäíW|É»DeP-M8-<î‡Ìš»Íg»Ü <³eRN3K,,—çÞ¶¡¯U˜»Û쮢ÿvŸÆ,tR3À§ôìüJ9îF#^”%n=òswÀïƒ<j2¨‘!E%&¿$d¡äôíÅU?´J•öÛ7Ä’ÿ.Ÿqt¹Pß$}ÈØŸ›yï\#ç]h<ÝTÈg)\Ù\¢ó6½XÄ\BÑ âè,›t!tÒe½éÛ»‰M™¦ö7eçËa]/wk1‡jÝÔ[ ¡à× IÈ›vZ7Ô ={kWOì>ºòûw‡?fºÜ5Q]‹»Mݞ¤P…HZ•íŒIÖ MÒ6p$èÁ_=í‡ôW¹˜Çr° lú«aå…w«C'ö_Œ~Á„ã¬ÇÇDt}LTw•Š
+&ŽLQý5>éÐtYŒ‡,apu ùÆZ 뇡G…Ìâ“j*°PO—ëÉ{<ü:•º…[ebÊ4IE ƒ<è&}>¸#BÖó¹ÿëé^»èt·³¹Hh8\ñC;¯ïäôã.ï=Ž){ê1§U̸ÁKm*‘pá¾ø¤aœë$aU@_: KÏ2i§›ÉÍÝ­‘vm…tZ)ȶà°S¤ü²@Æù´å†¿On‹y÷ƒ[¤lÊ8Æã: µ£îÝßœþç^Hy‘Íy‚\Ñfâá7Bné5›ù) œøØ*(ü·›……GMÐj«è[ò.›µÌ¶K.œƒf0×y
+I>9
+Ÿ†óï/G•½ÕˆM!¤Wš™à¿„ÛY‹"ãÇQtæ0d:ܺñ …»GIí
+ÝÏsë`ÍxfÉzNX?®­¼õebäxÑu¥ù£íŠ˜Mì½2~R=qºÍZº !ELk %gB³J>U¡¯É9ÏX vCY3o—l7ÿyö·/ˆ¿ÿ^Møp÷‘r5µrÞ‰}ðµÆªk@ÎÀl8æâ÷ñÏ 'tð“Ÿ«^—Ê/ÖÖŒ2®1k½,fÌŸ«9ÄPOÛ†¾!Nýê[ä“„UÜÝÝôEßmúçÞÃ6q˜v——&N&1sm­!ÃJ*ÖRñ§z><ÓHXûö–Æ>Ú]úðèõØ_¤åÜ{Ý8x…ö«Ð1ºåÐ\§„L*,ø0‹ŒJyϨ
+>lä0ëÑšk°Øæü¤Úë–z˜²^¬eMdÐLg±´«¤¯ Zò‘»íè¼¾IRͬc@d=bµ·‹ˆó—*ŠB§¯,¸µˆÃÜ×ý#¡P#™®'î~ÝL߇œ‰g)Çö:v{û'÷%™Ÿ}.@7jý´ÈûÂ-6—¸ÐŒRœîù\ál×֦εr8¢oFžˆeµÁ[®6ò–¾zÚ|¡Ušº,IR+ßYÒ·§çÛ•à6足™×¶HFƒ³ šiäŸ÷¥pˆ±™ÿLe°'¸K+¸ :Úßm`è/U‚ê– ¼§ÙFÊÖ÷æ'ÃÇR¹­—˜0ð*s>\äÂÔJä‰Z‰~Û€sK<áXÜ"i´L4¡Êi†j÷Þ¾”Æõ nÿ!»)"°P 8L/§u>ÓKt°["qG§$ø_<^ÊÎ<Ô*áGíM?ä#…‹ð rÈ¡—^abB‡ÿÀÍz1<×.Æž¶ ¡=šV²~LÖÓž)ëÓöæšå‚’
+2BúÎWÇë RK1Þ£r¢•ÂÍm˜¹Â£ŽZÆ=Q}Ù³àèïæbÔf9|m9w°l»,ݳö<Q/{Íd1äûýýƒî­PãJžÆu`­`j®O|vøzütåéåþóäæGzša4ŽD`7äMµùé/uðD>Ró~¬çl¦ýÀ#N™u@.¸Gá·6³ñgZÉïW
+Øô£Û;ßLÎ^ýu&>ø;9K -¶çߨIÈù¼GIÂÔÌa¦ƒ”kð ëÝËznî.;/u`¶àQ5–pëeÜÕÓÿÞ+Û¹Ý×ö
+ ìì¼Èß_iqáY±è÷‰%Ò[+¸GW¡çÐ)¥ yºîú÷+o#›“¹ø …=Õ·b úfhN¯*E¯åí3«@7
+¡Ù:;—6f>to7AN¤ £ÂyÆ;EûïÛ_6Ÿé½‡½zWÂÝ:‡Œ ç@ |çÍ“Ÿühü«VpèE…û2+À+"÷0)òXƒ¥<MÈ}#WËþ
+~Kn¯d<·Ä¤µ¯•˜º,¦ [¯9®Ië®zt›'1 ‡UΗ¤ìZ>2«"ÚÅÀL§Œ!õ”é|=a> ½g²§/!€Œ!ÝB3 t¬¹â¼ºûýä©7/ŸÊìÔU!m<Û映ÆÝy.åc_6sÄÔQÒÕ/BÇoÃœ$ßÆìpÇ#ÿcØl8"qÈ8d¶iÙy­gSX{3c>_ÏÙ¯ÉyÊ¥äh¼]ÏB¯É<áQËÌ´÷Ù©ð·Õžaö©áãT|ð7?{ªe ¸Åu[áÁ;@sÝ*E¿ßÁ°w[¨G+xL‡9;›L\Ûbîê[ûÚFàh$Ô©t·sÚ&ňEÂ}°êèƒ<ŽÈ\ä~ƒõ!õ\(¬”bóà3½Ô†N.æiLå! ¸«õ_ŽËô»iôŒâÿG9ý6SÚsÚ9´eé
+¼<ãÖt•Ãcx94>Zë%ÞùÆs˪nÒ7¦Ëz,òrxbüKrâÑYÒ ZÑ Ó~µ
+Œ LX7PáÝ<1n…® ™¬’¡[ÇÉMžÐñYaB kD a†ù°â»åÜRÙg2ç`½}¼¬¼õëöøCtÄ„F±BlöG.9ñ˜Kèäå-Uß,>ŒÜå7Õ%ðìBÒ„n[&ÊÛÓ/€ƒ^ÂzQOç“Ðk’#æB ñЗ²ÐÕ ÚO|ÓÓÌû)ÈxÍRÚÖŽZL\ “0aL”ñé…Ù(d-ñŒ £ó.6>ó=¿³Qƒ”‰j„¹Mis.h1Q¡ÿ¬“ÄÜ›Cà´Å'g^r¬ÓTëg¢f”€WEfŸåƒã¥ÄôS>6ý”öãLĬ{I
+›†L-½Ç¤å˜Y|ô¯òö#{qov©ôqò¿ån‚c¢ü¦¦›©;XBÓ“ßT÷€gu{p%CLÏÁS€áp6Þ3*ù¨¦7e“Uí¾_8x7üíÞ/ʪŸ¤W²MKÖÔ“p,µ.¯Ú+þÛÞkáŸvº¾âÊV.¨íaüzaúåA›iº•ñcÝ\Ð Ê:ô¤kTJÆtLÈj Ý¦ì&8YWÖP0çY§º%ãPÖ¦lŠ›Çë²ïŽíúö½eUÝÁ²ô*å–×’nE]æ:ëUµÙä·‚?´ž‹¾ìüêpþïµ(iŸiº­2ïÕõné­”cð*D;Ò.uÛÉš¶©è·¨Î ‹ÁŸô ?v?cSÞN¯Jÿ™±Io°uÇiÜýÔl,ÅGŒ9ŸQ”¶«›rmGؾÐv­ô_üøªç<µŽµ|cø6ÎGF˧Ïq‹5ïU H»ø*íê»x–0ªÊñ©'\ô·ÜA`.«–ä ðŽ‚/[zm)®“šû´GÙ˜²)k ÄNùÍ2º LË€3„IÆ„U)·è:åAš ~]oE;™ÐzhÃÚ²>¤™ +¡ó m§Q£ŒéûÙ
+z «ïçà^`‚",¦|ìÁ3È’Ç|¨,& Èç-³ `=i`éOncÿΪº<xHoNÎ9°ÎÝ_†/¢&„~®ô.Ò…´C'e6q„t›÷VômEàÄp 2gìÊÚ¼_ÞÀú‘VÞ¯2^ÓŸ˜zÊ&¦ž°ïg_”>Ì,aÏ !\‘à2Ò£¾{¸<xqçñÅo‡.¥lÒj6bÓ„E_ˆá§óå¨^ÂU‚¬C^ZSTEçEçw_Ê.¥Öк½7×2kò[›^pðNQµýSßß?üno¡ç|Ʀ¨¦€ÃR^ ºõJr…´)뿦“‚¹Î:uGËHõár3µ‚5íÿ¬¼–ÙÐu.#5; ÃM­¢59ª5 ó¿ÿ³øBâ¹ðë?Šÿ|ðfø2½ÜÉû‘–ýñ•ÝwâK'z'ëQ4Ð^´åd ­=\Tߎ>þádYÕPðš/ÚšsJndí—Ó«ƒ³ë’ë¬iλ5‚£Ueõö‚äå0
+÷ßÿ²ÿºëkÊ.«a½Ú.jC^C»õÔÚ|´„ÜÊmà9'>ÀzqIÖnêÉ:LÂOK*¸ŸôÛý·ýß.ü=ã”V“>E#@Û˜€¶ü\R©L@}¯Ññ›]Þ7"£=º¾bØ¢gFq1¢—Tòº’Q´ m¢œªfx§¦,<C>`–Ð+Fû'Ì':í3Šó>C?éPÖؤߑn´i÷äÊþ¢üú ôÒ¥iËØÕ¾ç3a”žÂb ×|Zºt´(»F;±îRÌ:Y‚É…ÌíÒõÒª–ÜzçxI~ýà-xŸMݘuhï’6³0½Ž÷ç½f1í6ö­ ÕŸ–¤×²NE1 Ó.­ ï3pÀŸy˜§1‚ýŸãò|J3Ûãø«»sg_ìì&îÞd“hŒ)š¨1±ÄÞMì]¤Jñ‘"
+&¹1UM EA±EEņÒ{ˆ%eî½û‡Üã¾zfž9Ï<gÎù–ÏϘÀ·Â%…Öxíž%èzj…OM.w^÷ÒÐêŽÖðÿì°ˆß78$°ö†ù¢e4y—È¥æBÖ¡†Iüïþ“þÛœö£uüt‡ mwàWé .p6¦É¶,½
+‰IöIJ‰GÙšT³‘ û|sÌ ý·Œ”æ”’Ìc-ñ[ÍQk/àQ¦ÑŽBãç‘þ#%É €’ŒŸ ¤ý„x‹ˆš©ÿHˆ·‹É.i{¡ ÌÐ/ÊŽj—œYæ¶å˜Æpww„°ª§Å¿©x•¿m}@Ç™Çðé^àIÐMbJ†iœœªÀ¯YEµW·þË<†ÊðÌv·X¦:ë»[<s¬Fó%ûŒ -"TÜ¡‚˜P’òôCuæ bšYB-pNÑJ=Šöb›ë’bî{¦±É%þÁöH˽ÙÇ¿ZD¸Œk<Ú™– cðhË2Î5MÈt)ˆnàk’Vì¡–Ú&ñóüÖÀâó.§ªg£çïÓ²ö>’în # Bì·ŒRx8˨µK¡¬c úòw‡RÿfH©Õ§`NZÃy®ädÝÐ0à~5˜Û–º¡X¿?ŠˆÙ„Eì¼k¾±û}s÷æ¦QHJt‚3sMQ‹sµ^9£Ô>¥Ú'Hv†š®‚¾½©{ƒˆ°Š)ÙÇk=LŸš‹u€~.óÍ·æYe˜„ƒ\âž
+œiF
+™hF
+ŸuO½”j;Äœl@¹Œ]#ЧmHÎ¥jBÒ§jCÊb1¬}D°N·ˆW¦yFШpSÕ¯yiË pJΤpKĘa-·ŠV¬{O­zQ¯V’cB¦vR!—g>ѧvXË£nI—_*‘[#µ€R»ŠU¾”[)°€NÓ¤s\È¥s¹”k<Æ¡qNÓ°ƒƒÈ¡rQµ‡V ¥nC¢mF a=k>
+¤sM ­|T¤oD žg= ¥~JfA¯|P.Í£tQº‘i2µ‡S²‚O¯€O©wK¥oE«|T–mL“^?ÇžqH¦yX mH
+¹†QÈ–^,¬yI i8·€E¾“j?³‚i;Â’qFЧx[Ì¡g9ǘ_+ÁŽZ!À]%µƒU³€S¾Žh6¨v_#¹ƒ`#Å™h7×f2ÌžqIÁ•h3¾‘c1¾“_3¨{<¹ŒP ÌŸyXÇ™rI¼e,ÈqEÈŸl?Èžf6Å›a.Ä™^+¾‘U#²…J±‚N¼p:»‘m8Å›l=Á”c.ºŠ\!»\$³†Xª~W’fDœoGÅ›gAÇŸnD¸ˆZ®€S¦wM­€O´†Pº‹PÉ¡a6¡~FžqBШycÉ tQ¸Š\!³„P¶ˆU»‹Y¥vDs>{S/¦yK!׫qUƘ^.Ä–Y(Çš].¿’W)È™R(ŘF±‚>Å¢dEÏ°q\ΨnLË£qK¸Œc(Óg2»‹`'À’c2»Ža.°„TÇže8ÈŸd:Á•]1ÆœmB¹Žb*²„Z¸Œ^%À™lBɤtRÁ–e2®€K
+H‰Œ—M’d· „OÐw¨µ"\A–ŠÑR[ŸÀa­FKßß_>‚ew÷+[­ M«”E@"‘ˆÑk-£[üã£Zس.ï±JëQ3›Ow‹>jxØ|
+¾¹·éÄæW¹œfŠ
+™¼·’\v˜s•àÿô 2Q§Ó…0fgÚj'þå±kÊ|*†ñð¨p´ñ¥YZ"ÂÛš vŸšÒ`êÃݦ@¦uú…„̵O¹ê@¢ۆ¸]<¥›Èö\ÄRîŒ ÉG- >ÓÚW"±ÝŒ&‰ ¢ a69¤×ö9Sýµ´]O Ê
+îj"Uê¢Ø⎣¤ØØE„Ã2p¨ÎKÈÌ°¼L-Â`.«ä¨!ÝTRyú3W`¿ÄFD×q¿Ç7ÉaK/`Â}„¾3Ž 9DH·ÓÈÀö!þ¨~¼æ5·.©9–ÈofuT·Û!«ŠXà{DZKÝЩiÒÑN²k(Ú]–€Ö®ÄàC8CYJyg‹((žÏuoón:ï“]üqÛžˆ"”5419ÛâkÔ0>Ú hCdí1_¶ü@ 5µ"–ód5™.~N¡0.³ Ì'tì>ðÏ™¨3Ù(
+>SÈ(çn&ÝATq æ oAa@Úür’,š>9‹‰A-iµµRsŸIOjÎPØ%¥¤±ëºu;Lƒ)icíyMˆo HœàX6DÀâ`G¨-¯ê¨Ö¶QF–´>:•°„à£cúл—‡»ÜëƘé hU
+};nGbKka æ†`áTILĮ̈°¡ (M€t;—¿5‘;W &7ËW¤Sq)—]^:Å‹†€©,Ç{…¶.¥¢½ƒè@© 5ÙÅo 0FŸ|EÌΗ×@‚îþ»ÆÄmTŸ­ÞT™¯,}ëXò"ÃÆ*$ZîSX$)
+F¯^i24¸dL­ %Ù¹ë-a1C0ʯñ@Ü>å~6ˆ› $Ó€ÃÉ×Ì#iž•q¬ÅŒ?nû³K–BsSŸ$0^T/Z(èš¹+®!È]¤S
+›k‘:S “ÇnÙdŸ%ö‹Rص ãÌ.˜~/'&ƒ»Ô!8žã¾x‹¿†ùtÙýªûýÑòÅx¾ÐVp8›.Ο‹Íg}—@šntì:éa: .Žö´x<ÂT{ÕŠ*a 5›ê´4S¯ROz8iA(Ý5®^n’¸ j$½Ø ŠÁ6Á4¥˜VZJŽ$©Ü$of#™im¸,GÚ|ÞP‡ŒFáÊËÚí™è.·Îþ9Oß]bÒd®ÓŒËr ¹ÒÓ¿ÿ½îýØA9…ÁÐEÏÞ¼ô'Õ¯jâbY¸FÅ-–á€öjSÝ+yC£¨gà̹uÊ9Æ­»umF†Ä¡ØsËÕ #†!b•[gæixu’šÖì è‚P'ÚŽ•ù¢ßé~óvÉö¼
+C3ÞžÕ”¯V^©¹£õª'DJ
+5 Dî“b ¾ Ï‘¸¤ðÌ!æo"`Q§ƒüXß
+ ½ážµ…æM6›|¢ö¤ "µdíZôÖã~¹mãšá.º¿Pש*ª ô_þþQ¿þóã—}ÔÇoìXstBOÆ*ñ­Vž8裟ž¡>M±S^dAŦØ5:{BXxÙ#0‘øpm*‡Œ
+v•Ÿ­ g0ÊT)¥B Ê@„€ R;‘f ¦µÏi¢^¿öÁ Aâ(ž¿)‚ÈÔM-¸×šõr]¥Ñ%'EuâÍ9t¸¼<±ÚµÑé5"kA+Õ6juuý¸V1Å=tˆv‹¸f×wOÖG$ßÄd´ãç)ó¤a%×EÐ-Zó*ÉØOf³¢ Qœ<Ç5{ÙwdËîBÿ
+É,Náí9Ÿ ÙgúÒ«1û]A09½Ö6¨ßyˆçÉkÒs=nØåëiòÁ ú–ñÁ¦HúèøÜ¢þ?“‡ÿåÞ /cõô<èl†îŸo@Ê+¯«Ïö»\Þ•FìàU“®å8 ‰†¯X½Y¾Íî¦QÎÓ±Ô~©O½@xb8?W²ži*wAú†L­-t8gfƒq(‹.ÃÛï Yú%KÔµ*®ûs "['c.¼^ãȲã”ç¼c½¢ÚyÈ׿/“ä¸n ˆž€wà ˜‡5·º·­ûoýUh‘Ýøf;,G˜J5ä0ÉRç©'%F=´×ÈÉŽå‰n`‚—^
+õˆ=äTú5庸2B×fZ9ç
+T$óÌäôFEp|>Ü»1cp…3ùAèœå`E¼Ôl‚‚ÛsÄD+)‡àÐNÍx„l¶ƒÚX4Ê]Îçp7ˆ„epÖÄÕ妄ÅNùˆ±NPRµ¸©75v™ís˜ŒW•ãJNˆ±¤§t&½¦íÁóqf‡„r¿€z ÉüLû¦ÿ_-m¡IϘ¸Óˆ£G£³ŠÛñ_‚©¶pÀ” ,T0úRáGЂ°$Œü®#©•¦¢ÂtÀ U¦%®{ 1ÁAVQ_V\ ’+ (~–Y™vNVÑèX[Ëë"NIvTÔãR0›ú¹´R†‹ïk5xúDÑ°>,ô<€þ\€
+nn9&Eƒ› YlEs–ÒTFüR°Çop|³³”¬0ˆ?Å! 8#YŽ]ŸïDöeWñû¨mI€E’èëdç`"µZ”û¢[¿uýóNÓ@™1f¼×þÇzø€¬ C¯óqƒÔJ¢K´½Aü3kƤwƒðxö¥¡~¾EÝð'¬š=¢¤øô"´rô H8ƒáH|‚-¾C1†õâ
+m|S¶Ps=Ž¢¾˜>'9B×^^ÄNCÈu­½^ÎÒ° ¹›$á¯îÅxiÞXá6 _ŒðݬgyznüAž
+rLñÁæÜŽ ±&ƒJ£8mÚgcN‰±RZoW§1ÄFò`rà<e4îä=I
+£ôÈjXròHÖýT#kWðµÅ{ÑV¤âôrhû‚ÀÀl’w9ÕÌú—’¯Ža‡±e²PþîÒKÃ?†sD7ãÀ9]Íi÷Œ:ŠJm»¹Ú&à k›åQæòöÙ’Ó¦Éqo„„˜%líV‰¢é%”iƒñˆ9öœíCU)ç˜á*š=t[T²•Ü4Œ'¯Ç¡RÁ¬üc|@l†fs™ó4À$¡kGÈ—±Sd=)* zÑu%<d¿6è»Ý˜2"0x¿j°žtŸ²ñt¬9£ vtlÿôHηWü_üêhašð6#¶ø,0–ŽZ\ß•.02T&ïôùÃ…Háj+¶¾SW"‚}Da‰È÷9B ¹2æ~kI@ùØyœy-.©tBÁ/0·ÉÎ)°@Äí`ƒ]u#2Œ¤°F~UÅ«MæéP]>kѸüùv
+)@7/æ Úé%@ Rˆeû€õ"²H0ïÜš:cä©ÝÓá=0ÒÌQ7S(åÀ~GÑ ÊÓåóü}²¼{Ú¶¯ðHØ—Zùìáfünb8Ãœ@¦1B·üZ
+/†V·šz÷ä "gÕ•»âîú÷¼äW±)p6oj{¾`pý 1j^À˜oõ‘O#øÛ  ”òÁÏOÌå°gT[£ÎÎ 2\òG'ÿù˜eùÎ*F5ˆB /ñƒáv€`ÇøË
+n ˆ¥Ì±‡ž i$|GSc÷í°ÇÍÉ΂S?z»®ÀFçø dO !2±møã9Ãn‚&Æ6šø*Y{èkñ/öSaÖeNïæî$ËÜ©÷±ÂÆh8¿îßSVªHlj´cx3>™1Ë{×kàÿB]Ÿ!a5¡É<·Y÷MO ¬¹%™V˜ÃÎáNi¬6Î× &û_-èèÝšâª1¶Ä™æM< yØ;ÑU©`¹L…h!(ø±x£¨¬È7Ç懱@¨°Éüq®ä­(yli WìôôçÄø€Îÿ˜<hß”8Òß¹RŠ(µ-ó–·ã¨kYÊl'ŠÝZ© m qñ}YõA”i[-Kœ¬Ù
+öóÇwµ»ºÍ œˆS…ÔZrvZIrÀ£ Þ‰†Ç-Šps^S‰#\ôϲ{Ä/Œ;7ß;“æçîIHü ›Öþ-Me퉖nUJô¢p±sH ª†>ýáø¹Ñ(OS^;CHFsâ0
+p@r¨Þà{/r zÎüW9è>¯Ž Ú”¾†M—ìˆ&ïö¾†‹…„yø}ʨøåÈE”¯=vº…¥™Kræ´sYƒ.ÓÖ’(¹I-½WŒø¬yhd—Å!Û`<‚Ž=/"¶ií{tŠœ¿n©/3ç'q(Ó±^f 4KË×›õ~Æ<(!EC“©øË •ûs¼îÐc¤¼A
+Á 5™V<Aæóóí
+„é`xq€ÑÇo‚GAÀÿc¼L’ä¸a(zÝ¡OPÁyX·—º…¶Òý·~Ÿ«£²RËv„[‚’$€?m`¨dÆŒAªÛ%hfuÊ–b3sÞ%,*Ú d ®Ülbü“dy•ØEr«BJ+NÑï]‰¤‚¸½_ÀE–ÛV¢b OÝr÷nÁ¯?ØO³‡˜ƒ2_4׫gÕ
+±*º4™i'ôßN*0ü€›´7u0)tcZú¡m®§ŽÆý ^ ‘“ºµ—œ‚‘úÌà¦UMêfhÓà[QVêÁÁèväÉ5J¯HæóÕO;ìõ¾+& &m
+!PÁï;E?oŠØÈÉñö͸›"
+Pu³0qhpëíõ¡´:¯í¤A˜‘ÿŠ•
+3Â_%{xJ•þÛÆÁŒCT)õ
+FÈ6[ƒ®Šn˜eûŒä6FoÕaf©_œ½à %æI†à»i••éŒáó "ï’ 2H·ž ß”»°Ò1úø/.ýÜ‘7a•µ`—Èæp™É36ᾕ`*&àLsnJ¡ Í@š¨çÆ'†ŒÑ÷°o“£k·Ác2BÁï¯Õkùà“"ý&ÚŽ­h¯¥í(±"¬‚…/»$-N¢­Ðé.á\;‰ã¥ÄŽ"¼œ¼šUÁ²!ü|xéý2tÔ¨³ß?*‰²Xç®7)±5,Á¸éð[ÉËœÎI×¢ñ3t^Ìç2¬#4‰µEÝ}œÉÒª6Íιt¦ÑLœfR{òá´—
+ÌPá6-¹Sº”ØI—i{ß¹ìŒw™Ëî¹oº¬0‘Wâ/ÂAõÃAg]*9 ·àeD_x»b«»tœÙ<÷RTh9[ÇO°õ°Ô÷V”¡kbìDð͒Nˆ¸Ê.A!^Ä‚Ñì9wžITNÉêÔ±zŽÑˆÓÿNDµ£4›¦$+)äOiYÛŽ!¢­°9¶alËE íE÷CVùüá1½–¤¬òc?>äx fX‘~mMt_§ÈǘWBP5+î°½»D~Ø/}/±½>kô¿“±¤Ê2¤pî¢ðÆÁA¶gWÈŒ¶:åÁVIWÀ!Dº<AMã½|™@ Œ„ ©£;‰¿Ýj£‰¨¾_ÁE›\-:e¾]7Ð]®kÑϯP‡áÉt‚f´øÃÆ6y¦f¦Ý)’É™Sö£-˜R‚'@Ï¡#KëÑ´zèî.!ˆF
+¬j²'éAÔ¯mùüáa-,ÍGÉ}‡ƒ·£dbèCWZÄ6}Ø…‹2G”UÛî^ɶíbôn¬5Yw–à•X‹YKV>ƒ¹î~GShYF%1ÛÕpmÌz†3oÞÇlÁ{4X6LµçsRç‘ʲ ^^pä‘u[ÿëjÉû’hpF8äšoJälÙ=ßLÏ£þºÇ?¿r*Y1Í"Tåà¹û?7Em`ô
+ü–QÌÒ¸ZoŽ›oç*÷2  Ž(£”Æ~1Õ1ϵ!Jz ¢ó3ë*Â*ÝF{>'v$D7ß-*RÄÇCY59%gߧœ¤{lòå;ZBèîc¶VÂs§F߀©müPžÃŸGçI`bÐü\ø—¡ý»f©
+ü¢ÈEðá¬:ÐÁOÖž‘ž±Ì)i¨d’&šüë;¸úRZWì„yÁBº W$_
+º¾mñ]sády^0‚é0kI!"y—ˆø¾;D•`h\5(Ûó p'úÁœ}£„ÿ+Ì|f¿×<[Ø`«$»-;%ë(œ§| öÃ-’ŠÒ@ÚصC›tµã&¤áÅJh/u—ÈÇ ¤$˜7¯EWNü}S$gÑ1ÂEßïbúbñjš,”r•ÌpÒ.œøxzÛ%JáCŒc”ótìÓÔ~TÓvúÝ…ù¾LÃpŠ4¨ag’DKźÜ:ü$—™¨UÉz34ÿ;×™;·¹îŽûªë:ݹn²Óc§äeV¿¾›/‘«e…‡TÞØ:§CÄ€à¼Ü— ”Gï>T™õH†šué©N{~¶EæKr¨õôHvB¿2»Pk}t¶^Ü´SÊ;%¾OÞ¡V-ÁEÈÁ§Ví3&µ¤'³J,*ÂTnx©U„±KØ£BÕ¦àëÚöü1 ¶£*àZsÒ`¦P¶âì*éÄ#Ep7jílCHeœü'zÉÝ&UôÿÊ”’_‹®ƒÿ}SÄ|—ÄNíÃDz”ÀÞæ% 3V–ÆåYôt¤a2®§Ý€RÐM´%Çóò€ƒA!æήØŽÆknm-†+!Kš5}Óâ±å»ia+â„Í›\‹ÿv« E)À~,KË Ø°mZªr`Öj…SR°µËoZôép›|î #X’4ÇÆB+uèGl”µZ$öÀ[#.€)ÓL-Ž`ž“þ
+Ì/‘, ]ìÃúŸ›"Æ[Dsc]œÙd©%µã«šyòš–>ÌBŠ½Ç¼1ó1 E<þ¾F"ШƒÒü„¢HPw¯bÄé¹G!²7? PÂ:†)zÏvcÌ¿n\0U»žŠ%ð¡bfAgÆ¶Ô «K2+,A²¤x£ß»ݘ×4zgcë д*´¿° óÆË$9’\¢'è;Ô Ê8kmu‹ÞJ÷ßösL)3-™ýúÖ’AApøpN’/Ï>Rº'ÈáéÀöÝg0ÙXobFÜ
+ŠÀ°bØŒO^g)ÍB¿píø½i||„4+àJ²º:柰¤YW_¤‡ý¦âb
+ñ—dQš¶äž|²+Ÿ7EÜ]ht$úÍa"–”_<x™@‰Ò3]¯€¹[1}Kvš
+,p°oÞá‘¡5ypÞ’A;2`½&
+•*>Šý¬5aÅJ°)ãN³ðw¾•LäSf0B>œÆEý¨9b0ôÈW¢€ÇDôÑ >Fv™ýF|e4ë;i߸ËU;ÈÎÒRBª²¸£ùM‘˜'9"qQWü8% &ðc•vmºJ‹YgX 
+A±Ù) +d±$d¦¹0”!*¸èg“ÞCSß²‘œ Œ¡ò!R‚=,2¬¶ˆÊTu˜ðÃéU^X9*Jö¢r£g]úÝwä…ñ ¹ßf¬ÜØd´–áIVNг.Ê\4çP Äë µ0Tµ¢ˆ¢6fÊP«ƒMǃ䱛Ó›b@߬¢
+unØ :I %q*ÅŠ˜RFHœkžº3äåWšÔ°ø£.Và/ýåܤÔfÏJb
+ëàOg“XLœ½(é_;©²¸4˜jÛ ÊÉ}JÐ]Ì„þÓZ2Ürk#ûQÈ‹ÌwKÁÛÈE‘â†wr)ÊÒf^ +šÙêÒ‹Ëkn[jŸŠ>¼= ¯)X,ì¼­.#ir’CWc½ˆ,‡QR§fT¹éôÁi:©„éX›GNä!!¹ªã¾e 2þÁ¿£+W>pX ö¹a ¹Ô(7%ÊšD¨¨º}Ô¥h²d7ıOÿŽFÚD­Û¾>§]¸I—Øüº§N$Kä½¢LàGUXA‡>7¾ÐWœrHs:5P"-£”ú‚?
+´‹Íêúçl £ã- %wüôTô~SÄø l÷ÜüôRD2Á)
+©e®X'R%ô-[R¶uOu-r![ @†ÃôoxKbæˆÅìíåD©Y1×sRœíʬrñÇã;I=üÏ£Tn+¡ñÿÉKLÓuôµÂ'1V‹žŠVÉ‚±ü _…uE7ÐÀèPÇcŸ˜×nŒÎe‹và±2[HûÒØ­©Då?§Ì¸PòW¼F[ù¨–›ÅT/
+Þ|e¸
+Vºì‡¢›¢.uŽ °ïÅâø.¯§Z¼/êŒi/F(¬0*+G”Ô’b×hRßO×g€QwQ’<Cx ¶•M&¶·z ƒ4*qw‡/3†2v‚úžçü¨ÆšALPÊôèÃñ»¬‰wQ)øoNÊǬ&Üh…¡8À|“ùÑ9ƒ0õsæ+úrV¿ì±k¶0<“³ N¶Ü[õò3m¬£†¹9
+Šˆ0Žƒ…ZØ+Ò è ‡$àçˆ}°ù
+j7_‘Õ»©îërovI¨¯éÏa
+¯âí4ª#È8 8–(ÜÉ.RlÃØa+ºÂIµÞ¸"Z“ø¤¨cÞº«‚´qÿE¼õî;Xu0'û·»*Ú9XÍö+óG8'bŸrw…OÐ8‰ŠÞ䌄@qþªÒå—ÉMݨ…’Œà±ÚµnPà¾ØRIë<–œ‚ÒkÑ뙜¦x0ˆ¿­9mßå°_=Âq¯^jµ¬8€e‚ëI®`2¤+^?­¦JURœc1M…L©ÌDù
+iûN'@eH¤¶t ®jéŠ QçJü(1y©œJŒ0]Q^¢z ›7Óâ¢è÷Êó±6Þ•Ã;g·¯‰Ä»®Þ»þïp0±IÊœi~Çâ½ÁÄŽu­å¦ä)Û¾ùÆ
+;c C*GG*Ÿ1Œ«j_Ô
+"Ó|¹eÞÛ±d¨Ü¯ýf„§©qñ~åzJQùÃèÙ…¾.ܺÌ@Ôô`’
+he8Cu%xź³þd˜D/Õr¼_ÁÉ„ñ(VŽ×a-çîU‚p ®¤ÓßLö¤¦Zášî‰¶¯Z/M_Ä\Ù¨výŒëI( Î~mûŽv(ÝÆí/êä9j…¸4eöÄøÞÏK±¨Ã-Ð$Ëq7ä¦æ Â1t¨*£ôsÆ®¸8»…ÁÑKûDjßuà!$B)TÜyÔ h5¤À7Híʧw¦¥oâ9y«³^؆J éõLý÷pZ›€|Â:üJ¤e­4¹À/0qF'ÕÜÞPðDþ¯¿0ù<SB«]”óW€*!“žOØJ,?_[c¨ RiÊ®Ue@&ÈûDßÁç8†L†¹eúâ<¤ŸÌ°ªÕµó(ÚɈíð#MRR„ëWqR”÷T'Çx#ÒGG”Ö¦ÝÏ<
+êJ(æñò \Îз8¤RTSWM ÉÓîJéë<*+û³šn|úN±…U n¤ý®Ž·'í>·µÃ+$í)teµvp©5â ° ?‡†È'
+Vcÿèraó` ÷`&¸L = 3-¾Ii¤=–¢çªÀž·ˆâ¶ø$ŠšS5UàûÓ”ˆðÿÐÊKXàÜ/ˆwâôôñ”$Æ_𧒆¿Š¦míH,HE`±ÐR#òõb{‹Y“Ð/v â‰"¨j‰çþà1y<)‘Ô óB§ òeµøvµFH`^6ÙZ*+4³&i|êTŠÊã‰GmYæ“—wçp] 9cŠQ6Y¢N¥%æ :aÀ¬õ-2‹×8çceš8+RÆ+#åj;½¦,…‹µ¢rI]Egß@ߨ°S)+>õ±©£6’g»€~¾)›ÁRÈ~KÜ׌njÛ1ªHUil+¤»fŸ 6×-Âǧ“3°€ATŽ—V"Þ’¬†Zàß@bô‚\„l2?n‡œÝÑv‚Ï¢^ÁÐÔçZg a¢»åS`xãÎýñý¡o$užÃkç@$‘ ;ª®KÓW¸’ëwÈa)F'~Ç弞³t #®Q”EN5;a7rãZ{‰ûCÒy5è#!øô݃‘òBëgeÂõëñ„ÞQœ]rb•Q„鯉S¸rØ4»zÄŒ¯ ¶3²zÉ„Ýûù„¨K»8éD'€Î“¹O«@<ßYu%Á7«4d­í)ÿ —`j{=·“¿ño1µÁ$A¶µæeá9H¤jÃÞßU¡A¦¬<rî[C„ªx•e‡p?˜/³~ŒcÎI?õÑ66a¡•
+U˜UƒÉpÃ~cåp8^BèãQXíö+ò•LvBÊf¹±·s•öƒ½m8"²eÐÇÔŽ‘²ŸR\+Ü0׆©u,½<·bÔóì3c¥H£ĸ;‡ ß(ûé‚iúßèq=‹'êb!B ˆ– R$ÞwÃúóÐËt†‡q+Êà×`ü@< %T>ã9ýhh"`Jó¤Ÿ1§Bn]H‘ ™¬ïÐ9lôãnò½Îª{dðÌ?õKîÝ…(‚–È6;fÄù4.Œi’ÿ!ŒÅê?ƒ˜ªâ‡Ufóó 虌¼2¿6RW×;FÇëßpëxe&Œ™3”£z_-Vã‰Ô¨'2@Aâà«3O52"Ç]ƒ_fÓrƒä˜ÆDéê-g1Ähfšw¸ÞîC÷bÝûò75/þ{XYAh¶¯TÛ™Ò; N£„Vdü£ÀË:íGu
+Ç&S
+¹g½ð áq©„¼8yoíi‹Ý >ÐgÂj'¸XaÈ·[þ.(S$êBýj@q1+ºÛC9WŠhV"=«©j£{¤gDs¨(âô¥ž*HrÐÁ´¨Ã Ö„©t,Å4iO-ÙÓsCnÒÀzy™Ø
+¹
+#Ê zHÛo±©a˜Ú`èÅ0ãxûÑé|z€4’“Y‹'!{l?
+uŽI,W®8•oÔ+ãÁ7Iƃ\]¦Ø)Št]MÒk1ÎŽ¦C]h:ò0Éœ$šgaYFü¦LþMN¥¼[¸áTÁÖÎO‰ÅC©"T·üàA]žÂ¿D‹iôYý
+›û$Ó;B‡ªêœËߨüàºàõ&Ùòé"Äv%f2ë»sPÏK¶rTŽlOÒEÖ±?Ê é±Ò„ !ùòÍÝgÐktÄx&EUð,ÅßAÒ°VJž‹Å"ó8X›“²?€¾¾8:F˜'©W±Ó£°ËEƒ,K÷[4m%¿ÚÞ¨jQ*èZU.î:3Ut¿*ó:ÃN¨NSÙ! Ú0q>—°Û'Ž©è‡ÐIúôù"~8_“¬ØAì\=ü exƒµ¶ ^nŠ‹ì·N{dÐQU26~¬ÊBÉcÍ! ÏäÐf±ª”Œö¡6®Q™ŒÌ "º¥Ÿ=D/™%­V% •»CG´à×UÍO6‰M…ZõÙ§¡ý”föq?‡k]Y#A®í¦ øe !Z7ùÙO//L@AK/B¶! }4 cÅ€S“¸¼#Ö3B.iÜ%e&Oþó¿ †=žt)®›æ…ç×ý–?ùÿx] sÒ¤®Y3_ñÕ}ïKÊë-Zv“UÑÎi§ƒŽ¯g ×d >§jZâBG™‡¤q¬em^ˆ…÷w›xFi $3J½¯øUŒ´ßBÅÁ\8™]wzf&»%ØSQçVaR¹£1¾Tÿ2^æÈuÝZçÀX
+}ºäP©GàRF…š¿×h½{Ï+½à—?©Í à4»¡/Sw&Hë„Lã‘?Zú~ßü9}bírïÎʉ”¸b¥‹w/¹1DÅ…ˆ0Ã}¨éÒìT²ëˆK€$9Ÿýr¼l ,‘A$5¸H/„Ð<„Ýú¦X”/×Ð>kÜJ!—j¬ƒ^Ítñ±ý™„Ô¢º MED™awî2½n^¶—U™ì1=û ç aSAÉ.S±U¤M¼ûØš²œ—fm?›oÂEqLKdÚïFEYL›•5ÀÈÈGÕ=êÑÊSR·»@oÕ½ªœà#:§rajE²Å|Ä̵˜LdiIôŠ’Ræ+Ž`‹)Ì{ô¾ Áõ!åX‰Qm£Ð°™ 0(ŠQMn²Uø×TO…n²hW2 —2.Y¥Èu§Æžçf Š(”¹í™G²›H=§Ø± ÿ;L²‹0m¶¹úÉû|z>ú6æÇ^—EåcÁCA[Çîöué®bøï+Š)aýòÏ[xÿëÇÛ—_oñýï·ˆžKìPú6ó–õ¹ä8Õ,“W¥³°#e×}ƒüµúþÄÙC; )-Oã‚tÉ‚â”U¢…‚Sú1¡sÈ(N]1mHV1ªaoÑØF#1†pŒê±@ü"G´>œ À:ZºV¨1$dÆf&´1rJÌ E5Ñyhºòï.âXòŠ'>žæú¬ Ì‘ôøb¼Ù‘^
+ßUƒ4™L”»K<ð_…¿Èše;
++“É|ËnË+Fâ¥ÐÅ|·–â"Ø-ܲ$G,E—Âý¹ë
+ a5B{LÜtüÈO»•z„&ÕàæA¢Œé
+E<*f$
+UG‘«)Ê1oÅ6ª4…£Î­çÁÿÃ%lê „ƒ†V÷]hì 㣿4ÂÂÖòWLCôµ&(mpüº;ˆér)%H"®ç‚`4Žæ@ñû0 %jŽÈ÷ÃÈ%Ìd
+ëÝE¯ªtÃfŒu.È <Wêi<*¢ ˆ™¹™2-ø\ûØ%&µ²_Lóž‹_ã¬H…}š¨kXKÊèTR`yò¬˜Ø3KœlB‰èLTðaÕ‹“qÖQ‰M†ù¨¬eœ¡%`R•2Äù‚ˆ‡9Ù´×›—™íͬ‰c—†Vq¦d$Ëä{s@2ÔÂæCùß qEyí¡ú8”Y”ʘ#ZzÎÙÉ%‰«øºit•}ãlœ½m{]Ò0‚Íàh0=Ï”¯?=Çži“1Å$fõvÀ‡û3ô¡ã˜8ÛÖS+âI¨F¨I£ÔÅ%Õœž³GäÚ^Ž²Þ¿3p-™KÆv´L½Eìç iw{ƒùù30¨ Ôeõ­0‰ž^Ï£ò2ÀIc°KœäÀµn(¡ésåò°GcÏx5%šuÖ†`/IpXÛFûcî“å@€$6E¹zŽWdâZkÇ
+ˆ=!ÝÈšLPg9æΣÀXR„J‹¼{Õ–Ôj^ttí ]ûi ¶Ú‹Œmq
+æ-È1X…BýªÜ£iÇHòa,>ù,Êø
+RèøŠ€{ok ë–YYÄ­?¡ƒÐ°µ Jž‡Ç "cŠ‰ÍÁNbî)vªÖ¶¼
+ƒY"½~Nbþ±,Ø…ýïô}íç Š×Ët¹Xõ8\\Gq<Õ‚Y‹þwäÈ\¢×™.¶!¥*mÒ>ãé9…ÍÒº­$W&Œ)%-1r°ž˜‡K³(è·Yx $‹…OÒJ (cO†bæª$Šô7O…Nˆ'£f-…ÒÃh¦šªO¹²íE–E¥f°À ä ˜mÏÅÍ`)ÜŽIÆ÷„‡£\8k(ÛÀ©[s vÔrÄâå4ýï4Í¿¬ ×.(LG {5ÄXœ,;Q¬0%@nÈ°(îÛ›rûÀÚ¨TEyu¾
+R³rQù”çYã(àsƒ’Q°… p‰Ø„æ¶
+
+rÛ©×lQkù‡—@W^þx…¼°vª
+•&Ä`Û€Dr.n®Txró¼ 0¿“KJÝ-üÔ¸/=Ò=Yä²`é7Õ¾ã³ì+²*xLT¯ïÔÐe2×”Xö£î¡)üÀ +SÁ·FŒ7ʦî¥#ÿP™4mC–_™;‚±â$h>Ëé>pâÓ®·ì#Ó–ð~Ç'<€>¬>Q›1{Z!å
+Z…Ç¡©©Í2/V))‰„a´3v´q¶cé…Qq‡ÿ³ëƒéÐ D0GÝ Ü%ÃΗ겡‚0­±#˜"ˆ å&Muö!8ª$å­õó¨+3ÄBËÉï|•e8ˆ-=xÓó€ýàhHbÎPÞB›œøi 2Õ}ªwhOÞE•*+3
+ñ®Xï0Ž›
+A~™Lƒ ÊCRÓˆ1>ªìÔþ΢ž.0ŽáB2‰ÄÀ=h|‘ULùôdÃåÕèbµ^3]ᇓ¯ßa„!O ÆùÜ£ƒŒTÙ†êc¬¢Évš‘»1©Fk+êD t;ßÁ;G¢I+
+(Œ† ó_}D
+í&kzЄ’²&)Ü^ÎAS™Å`l\‡Ñ¥Ô½RÔn®Ûz7È@²Ù>v-9—3® ïO@Úu¶˜µM;›ÝA’ËŽ”Â3 Ñ‘—K3-¤¹x¥·íœ¯t)*2Êpl=œÊ,a\+Uç;ÚF<'t¸ç‘æICŸœlŽÉe«¤1ª±£*»å2ž}ý"Ô £#ú’zƒ`5°Œ«vÍìÓD¯$k˜ ôá‚8,¼°¼°ñBöƒú°ÁVA\jÑ«HuC
+t¾“¾âãY­?/£”–)sÍ69Œ{P`8‘!ÖÁvÀySþ
+¹@%ŒW3ûCÞc?H68y)Î
+„ÍÕ]–¬!Øèæ!¤Èªò­NW÷gø ù±V†k¶@(Z` á‚æ@ì Š[2«M­üïÈdB E¤9Ý»ð V·DP5>{¿£lþP sK£ßlíçÆ—ú:ˆß»tºbPáŠø~i¾Ý…mÃC&i@}ò&4ÍÇx!~ç¨[i83dîn¾ûFwp«¬ž¦ÈoÔÄuí÷ý3·™¹_æ6{÷G93|-Ž³×ÿaŸ”ßp²h‚{r¬uëEÛŽCú˜wt»cn»¼@²gl|Á½ º˜¶ïîq¯€0 xõæwKèï ™½ŠŒJ[ª’ Ø•J2¬óìV厄ܙo VÊÖO‚›aXl·
+üÛ¶!,D,·,ÂÃÐdH{}”ë##%J c¸[Ö]kЭŠŒ3ÞzSžXŒ#“
+¥%íˆÈ`¨e¯'¤ÐlüË1V÷t˜ùwd"³YÍM¯êi*ê|8'cÙ ™¥•j-ÐɈ½eø 2õؤM³N¤üÜn;˜I¸©g±R{ç09c»ÿ1åE¢¤,£²®ª/~I#F$júçT¢ãp{>}h(ìàÿb>mä
+rëC¶5@Œý;›üäÒüßø{Ó|­¯N›Aâh^ ö–èžH¾¶ž»(Ä8\’’qòd>V鬦•9û6ÏW:¬Ò/„ZÑ?¦3®\EF P¸Ü „È¢ôɳÇÃp
+g¿)ÜAv°¼œ÷çå6TzV*·¿ 6I$Ç2Ç1¿$JÓ™6{]ËüAÅ!œé@^Ù=*{Š”¨eÁ?£†¹ÂhC ë‡Æ{ÆlÖÿn:n­÷Ì S&W*>j&ˆ±â_y¾¦Š›éÉ2j§#íu׫Mü‰ø]E+ÃÎêá}“ÌQdä:)ή1 è"öÄ >`ýõÖ«’¥Ä=_?е÷_ üݽ‰i_†d"·›ïÇê0…mÈ¡ÛÓ‰¸g.0ƒTpmiQ–¹BI¿—‚éX¢Ì©|¶™Œ¢Ò¤VSqž]¾ Ì7ˆ­r–‹cžÆÓ9ë'ˆ ß;ãù\9v«ããlJk¢Û™Õ4à‡ržyœUßàe~j•¡’r_ :ûØ-+{ òVßÎÃ3%n™¸î”ˆ_i|ÿ<Wý÷vî4T ‰*2 ûèHÅŸ *ü†>ǘ\=)š'ˆFVØžžåb µE$ Á#¸œé=OÇÉ32Ýì, açžxêǾ—À.À i2• P’Ѭ:¼d²FÎÁê6éH°êǘ$@(òu~¨1¤
+8 ¯ "3È·Í#ü”ž
+HLXüŽY¨,™T U÷Ù@âdy(ÕßQ
+à÷0TV4èÙúDë¹9¯)z€ÀïIÕ£sµòºRÛ×(•“ZŒi—½ïJ\â#å¢>¼g+‘v†>||Ÿ§ÀoÕï“Y3Ÿ„°cÞ[pW[+=ÒHTV9plõÕLƒ%‡‡7žÑ„J9 Œ ¿ç&#²œÇê0σí`Ô§I«æ¼(GÂt¦¿ü| ÍCÏ?ïË¢¬@tEGizµeyß9YDTͦÖÍëö^A_êÈ‘jO–]¦þQ¥AÍ؆&à¡:Bí™Å;!©ß£`9
+Äýßç™äÓ1p86FËk|Ã蓪ˆ[åd­wxï¦c'‹<]RhË9 ÿÞ@-8_wÚÐ öŽÂ„f·&ÓÊ1SCŽ«áŠê¹ªàoÌBX³”§xÀh0»ˆx0RæÛ*ƒ†4!Fá º
+3פœFqhHd
+Ñø]àªÛDaÁê;å;W¬Æ´W3‚‘­náÁý$î¼ùäÊKæ„W„-ÝcäE™x–Ô
+<PúÏâ,#„b¥½v
+Ú”ÔL4¿ž«”h®l´¹†ŽÔ`èémÝçDvonuZ)b]ÄòõéB.óùë‡r'€—OÌœYä@ÞöÝ®ûôNî^]0fÚE «_x´ñÇ@°V%`LOnµ¹Ø³“<¶%fqk²R* ã0‘/M"Ž’? _ÏŠ,ÈÀXMˆŸo}r+ †fŒ°<¼È?'ýŸñ29r#¢¨òa,èÀ–XÎ=ÇöBWÉÿë¼_ PÃ" ¦"¤ˆ³P
+ "FœÙ¦¯“ƒ
+'uJnÎg÷/ 2 ‘eÈcÇÔW‰1LXúfsCì\8¦LÍ
+\8ŒLÕ¼DÔ°F÷HøR¤Lˆœ¡} Xp¯ôrÇï!¢:@Pq`lŠènq©“3“=0÷9æmºg"øСõ˜éRM¼u…Ë»>§K5Gc•Glº¥K5'Ò=®,?"ÄÿK&.ôØ•jÚ>¥^þÁ¸¬\°+ÏÀj`_^'æˆðNš Bó º*Jק:σÎÛ˜l€èǪѹÔùÂÑQ­4—Áæs3èEqN½CÐÍ)á(M`²#/ÊðnòÕ//ŠÅiäÅ;t’l#<(°qx$6íIð;2ý¼l6„­‹œå[ù`”"—¨þýžE?˜Gy˜¿‚è—ÂIòb9††•³]¶­ÊPg`á;2l›¦œ±ÎSÉÕ
+û°*›Ô¸ÅxZ''3°©M/Ž 8IPwYQ*"ÍÌb‡^ÖÓîÌþ‘oŽhçrAS%pÌünÑ.és­ ZB‘ý¥èyãL
+1­#ÊlÎg©Î?tˆƒÍ#($ø€n‰B¨yº©è¤ÅzÌ3êjÆ‚YÛÃ:`´v£ÍÝtM˜0ï&úcMN‡±>⧟ï
+H‰Œ—AŽ£¹ …OPwðz€¢HŠÒ2è,g›42›T/sÿ|”ô¦lyÆ@£»Êý,Qäãã£Þûh.^šÕÛ?ªÆ½7“Í›Ü~~ˆ©>`úÝFÓ"¦·Ûï$ªÜ›jÅZÂLî^†E¥ß~-Œ‰Çh­jó…á7ÑZZ©· ‘¢–‡Xi 2Ô›ʵ@긷QùLÕM Ö^9¼”¨¯Î)^[+ææûª.^ͬKŸÑÔN:F-C{èØj=¬Wbc]Õg<MLJRÉÜp{~mB|„*¹”õðr.GÖ1®«øB—ê^º,qP‰0WRñãã
+˜zø0úÒ¤«nˆòêB­7¢QâæÙ»­/Γû¤;W‰êô¹AJe úÆØ F…–œŒš62Ã¥5­¯Þm ½EÈW홋Êeä5βAŠCÉŸH¯ý,>‡j>‹X£¥Í_œãpdžwÞµû&ºÓ#Íz³¤¸Ñ¤q?ŠWrÅ÷›üŽGhã™ûMÒb 52{Øî£÷æÙÁëÿË=ŠðDôŒ"¼€”Žb‘½@óW-AŠ–gƃFJ}¾
+lE,a\‰~z6þ_HSƒ_ïþ–=úœÉÖS„¨_¿JR@¼ƒ[8²žJùÙ¥Ó"©çs²_Ð7‡¶[™†ð°rÓÓ»”¢ªm¿¨ÔÎy|cøÅÎ@îJCMÃö´öˆ#­âr;ô
+¢7*J|»W¾÷%¨Ù9ÙpáãjÌoÍûˆÙ}Y¹™wy_w ¯Yo´­í¦ã/ÈT»úÝ'žuÝNz”åîèjrBì«Y@â9Ñ÷Ëëì]]•ŠÚA¾¢ aÑÅÕŽÅ|€ì«*Y'żÅÎç8úõ­eø;T>2íÒ½&×íWµ¬/$…p~14=E‹^ÜÅ l °5¶eE3R›;ÛG\Íðçƒüi/‚ bCV9•„þ€4•dÔUÎgLê£CHZsßBavÔmc ~CÓIÔýn+#u¡l=Ê‹-œcz?{ôÈcxðÖµ
+%±ZS‰E8Žº¿™?Öd­wh‰¨]=óg‡ûkš”VnPtTŸûu5V%99ðkå:‡H!/áªÙy6ÒÈÏu/}a†z>‡™Cxõ«Í -‘Xˆù((7¶ŠJ¤ª®š?‚Nß“’bௌÎèh:¹ŽRô”mïú82G.:,cà.ËTs’$LÀh—p£þ:JêÄÊ44$ÓBˆv\Š1
+®¥âkü
+$øM"§È8@æUlv%%‡á~MºJsžµmj4JÚ¸Ûvž g"U51¥Õfw<bÒ¬tzS¢-³rÀà½ØuPú6bœæ>«½G CHÙ$P>‰íØH•Fà~wŽÒ4™²§…uú!»0æ†DúF¤È–:Í®•a&/µNF¿o³RDV"÷Wç|¯÷1šï¼9>ꑇä<²øâä[¥~¾Ó2Ù]åê.a"±j6Xt8ï× äðΙ¤ÑV\hvol°êõRiD÷×öë¢Y’"m«VL•@€_¡V)¥ÚÖM&{j-"4çn{A,&vÒ²SírËØnð#xÊUûçs ´[A8ñ¥~Eã\KŽb:U ÄÝèstwÄØ’;ZŽ GÌ'WvjÎÅ`c[KE¹gObàñ‡;Ç
+/–f¿#c¢{ÃÎÓE^EšØ Å/zÌ À(@‚uă^í Y1y7sRÖˆxl©TåÚó;”dïªÛœsJ²ë P@Ôðrp-¿N ”±’.ƒ¦lk#†ŸÆ½êÛ ƒµy¾îMq'ƒ{ ºÆ΄°ÁÅ¡=åmBÐO0›¶)17’´ (UjÔ‹Á§s*g_Ã
+™D]oˆ<.F¯G
+3?Þþû!SZžP`þÉãh³(Epû™Ð©a ?mtˆ¯yý~µ‚]‚¬§ôŒ'èùºGÐç;1-‹òÏÿ|üö?Þ‰ÚÌ—³È×L¢œ¨·ô»ù//Õìr FKÍŸk…C+)ç’Ë㯭”=GºCõßÔÒë¦b°ö·AŒ
+Ɉ‚„nÐÓuoxêHÑ);Õ(3ÄÛƒvÐw1ßßÿùFŽ¾6/ÈÄ´AN<;+ÅÎù€/!lظÍÜ…YÉðëÏ((ôõÙ:‰ÀwE
+h¤H†®´Å† D–¡Ó¬%Æ9*À´–a’ãNX„ØG&íl£a)ëB a§#رH'[ȳuCð4¨`Ú¨qÝ„W£6Ý#vÀéÁ›:¦-LHÁ”gñ%vbFz°€¥ù†à;z^T&Dù ¢M#kë* J£•rÕ…É%Ò²YŠÍÔ€Àlz¥‹bz§…hp¬A¾€0gZ,—ÖyŸ‰d!J·èóˆ´Xƒ7_Î'ŒÎpØ—aWJÚÄÑsC™ËÞ,¦sùÈ—&:rÓ¶^ž'ckÎk©Ê 6f5‰À`Û:g–³°Î^ìC˜+¤Aá‡/5á;xi÷ wx•õë*åXi–†«èLÊ€ YçØOtÌ·Í-Ôʳ2m“äÿŒ—I’¹DOÀ;Ô h˜‡5u–^Q÷ßê9‘ìÊÐ$©M좀<|àš2ä+`Oê.Þ ÃM ”D{Èz¯Ch{iB/ÓòבûåÅ퀬Dx‹qL„ŸNò”Ê+R“ Mw¢”ÜZm=$öÚðp®Å0¥!-ÚV5‘©¹T¾s™è@Tâ4«*¢ü%Í>ß¿—!Ù„¥ñ9oNµåõ“a‰¹Ð®Î ¡­±쾓rú
+?¡xòj¾SàZPbbÞ Î¦NŠën¾.0¬¦ „ç­d*q>B2•1‹! gÏDÀ%eå…²ŒŒá¡ ±µÁJª=p
+Lhù¥`é&ø‰‰ßßœ¨„û3°ç1’ò HTÌžp>ÃÔßC™òö7¸ >ˆ‡ÓöâP¯.áŽ+»}‚øÒÚV£¨¤ÝߌüuESˆðµ!\'‡‰ô’Á]@lié± 5Y¦ÇWGV¡ e¿ ò1YuÉúIˆÅ¡°ë½ŽŽA:¥MKãЄäŒj¦nl¼U8/ýK˜„ŒÓâfu+úÞ〠¡B¡çèïePÂ
+Ù,þÙê bòÕ(%—eè…i-»H~BÚ²C}Ç|ž3KójJóòç„&D*h9­iCøD´‚óD%5A‰ýÐDH ¨vêK<vЕ>bŠ±óÿ©øy²(*fü.Œ_ÕØ{òrXÚi¤—8#;2'Aëqß©¡$8c—|¦+ÖºA‚!7&ãëPE¢ú ÁÒM±Ý
+A(ÍÃ8<æZ加l®S#]ÙÂ
+*×ujÁQTGö#Æ-¥Ú¢%¿¦ß¬ó¦9ãgÏ“ ®mJ[볊íCÖZ“xé³0¥~„œøиðÈN𸠶N;ã³ç C[¤`îm¥ÚC»iÁŽÃ´s+uZ ç8
+\*|DYƒÐ?I\!øå‘eeCäߟ=i0mQ½ºTö#Ðòµ!Hm×ÃI¢i“ø¸ðŽ^HØë.IA™~àV¾S$VP[Gðð‰¢\±úbÙë°2Ëâþ
+Qa1ÃþQ ’wùEnßž[¶J1Ã÷ªoU{8rôóðF,AØé-íuCœ/Ìš¸-ë¨P>ÖðÁÐI Sk…íºg'tU.©ù¸ Ÿ!Oêf–„S nœß>|Õ˜ÀÊ\9ßM5PU¶ë
+g«ÝaRevs¥€Jj:c¥ \±Mh.ûoo
+eHº~)p@
+C+ú¤sA?AL”¢nŽÁB'f§º¿ ¦!ñÍYú.p@ ;¡9eלÇœs4úÌcBÖc`ÆÓ«¾7/
+ó/tŒT7Dê_”£“­Â”j•ÌcFߊ_#Ëí|2ÊéB4¹ ú–1¯èÔòG3
+ö\~[ó)¶èôÏÅJgda¢ä®éƒ’5²xxì
+šÛ]ÓX¤(GæÖu$Êð"ùH¥ :½d<œóv‡ ýÛÿó€aøÕÄ•â¦à¤ãÞ‰Óè_Õ§æ*Ï)äÓ‘!"P•f¦æ"Š-i,’ 2æhš“£õAV”šýPýzŸœoáhÄ®,‰ÃðÇ°ýJjÓÍ+Ï08Õ‹ý)ºÞÓ£‡š·ä³!d¬±`wŸÌê±ÓgÑ”÷h‡gÝŸ\äW餶Ážu0ÿ4‹5½¢qRÔys³Ò¢{* q%¯ßÄ®*H*Û˜òÓ9Yëć—Ÿ¯¥ ÀA«ÚãGá1˜ë^™9ȪYj¸ÎÊá±)oþÝ0RÆ¢$¾ AUà5ÌÃ
+{™‡Ú}uêf-
+ S´m`ðð•Ô'òG_FnÔ"2‚œuX™ï£€ˆY i¨Ddï%Ðåyuðïú1öl¢È¾™ØˆPúÉÞS?ªJQ¬‚,97‘jrð'lˆ­C‘5ÂRõË"Ã08z »õí–Á‡+Ûu4ŠáÌ”ÚÎÁÚñ9bþbd 5ˆ$ÅBXP„ Šµ~tãIEføÍ«åêç}.‚”
+ÇWyViÊ6rLV¿ {6m´í ’@ô6œ g?ôyŽÔZJÓOÆJ²f4uKFcÊÐñ%ž*‹¹x0‡ÛBT¬L¦n  Ö+>SÞ%ÙÇàö
+D€èðŸ 7æÿúu•¥hM2¢¬÷ý
+ 0t‡q3z£*ˆ ’[O w¿Tý”´G~!ñ:°®æmƒ>ñqø{xül(¨ñL¤PVØÕKXéÑ<©>=ð1¯ÁÝfRCšB³y[ Èï“ß<U"§8Lòé
+íHX°éfÎJ¤y°eŸé°YÛLæ;”§@aƒ’”›âyv>,,ã(vß,ˆ©Bu†OÈׯuY|Éuiuì¾Æ°gg ¿ÿAÊrjg×Ì=@i5G&r«u|QÏ™é¨~±=f;5‰ÛŽY(U{“óÉQ®
+Š2‚Û¦Ný:G3Sv¶†1À´ÅzŽ+À«B›¼o»
+õ,aã§s²ÞҖ몬°‡tÀà’lõ-‡ÛU´‡«ŠŽ3’áó8*—Ï}NTîò戔Èw2vUÓgÂÔå]@ºŽ†âˆ6¿£·üU½*¼% ¶bAb¦Prf¦|HXbdÝû†Œ‰DV}0k¼AM,÷fÂba‘5Æ"m ïrqyqÏ‚@Z‰R,",†1ÖQ®9C(Ø'±Óså/jNᬖ~ ºÙÁï'Ð[†:B Ý.vËä–5Ž˜7ÿº‰Žìh·Ñ) 3¦L:Âûe¸Ýÿ¿¥¿éâï \¸ç9ûÃ9´wJ~Pª'¬Íë˜òxS„Üh®2Ƈs˜½K“Üò$ eBt5¶âs‹ãdK;€¾ „ˆU‰Tñ|™ ³$è¯q~òòùé'Ð{ˆ{Ïv»aAB<O;ú0qd±â£•FÑ¢Ã)Qa‚°/ùº N‡ËG¶‹ž„I"6vç
+ˆ9‚ú±G+9x‚üM’¾ä.æØ\ódÍÄA",I³u¨‹‚6eׇ¨ìÖÙ3¿ ¾LXnÖ¨%#mô¢/Ir2Xg¾;?êÃÛp-ÃIWd'rKº‘™L3Ôä¿&°š¾Ò÷ç9ñ @fä³æ£^ñÑ`rÝ.%¾
+ÿ‰X!Íå0èv8<Us_€ºªEŽèÉÎa¬gÉ*½oy[ñˆ?yCpd·Þ]_±tÈPŒtò›PÎÑ¥§þbª„0THyÄ}ÌTê%ƒ2àN‘^C–`Cø•¬aѹxŠHyo1}¥XÜÕ²úMÙ¹˜–{}”*ÊcÐBŒ¨‰^åÅ|óö€ÈmĪàÊöÉ ›ÈœýÒ‡ý«YƶÑ~cõ«½¦Rk!¨ÐÑ?G î‡9 Εš-Qël¶ò®ÜóÏ ŒÊ²Yð ùkCÚKEMˆ#þcùŽ–Y'8Œãe?‚üýåß?¨Îªáïÿ€ã…ÃOúâZ̬ ÝG
+Š´@oFwCHMê¶ù+€¡‡—qn‹1‰’ùI1õü cšDÔp˜ÐÍQX02Ä•c’k\bÝÊqÑ­£d6­iUQFDëƒ?@> þ~$ÓµÔ]%;ÌH]±`„ƒ A¨ð‡!t·° ›†ºnˆÂæ
+B•Ì”ó^&€‚ôdç[ <šœþáœÒš7_¼ˆ·2ÒLèVVÛL@Úö¶0Œ•B±žiXùPX&ú6§§§tuŠùNlnÝ3QH‰—ÄÉUò¸:N@µ­²•!)2ÛgSÎ0­y™¨OˆMe€àªÇcÐzUWÎÄÞ‚“`O²Í-ú‘_À¡Åðø‘´tÝD炤o'ÂÏO1¢$ ù´¯¦Úº @;RÅküE›×ÒÞh¦¼ÄŠxNö¥½‘-¢C½ë”2Ž¤W/ŠI‘àèWÝÈ“a(òE̼ÜÛ‰‚ †(ˆóJ©¥#äFå_°~pÖ׎³WˆÒ<ˆ¬±>1ω})ž «ˆ¡Ê•ëO–›¾t›A’(ŒŸkv„ fƒÃØCs>lwÄ@y)çpéÀÉâ—X!»J‹¬4ÿ;âñëà«új`ÎW¡ï Æ>ðK¸ÌIBøÔjþ]‘c‚?FqHTÆ@¬0Pc™t‚y¸ÆçDÕsK<j稧* é|•6†žñÑ)Ík0­ _ZÓõäL T§ "9Ș^@ˆ “<|ñÞ… ÄœºBù§¶ÆD0ª>ÜSY¥!SÌq… g°›ðÏ ‡¦’)ÌPøêJF'ˆÓ~)š¶ÿ1^&¹•Ü@=ï œ‡µ¼ì[ðJ}ÿ­_™%ÿú, á6ЖS$+32†ÞçÓ1 J…Rú8?¦"k|Ïh-=}SÇËŠH(‹v££™^„¼ è
+è¶\œÀÇu³4r
+¾AKƒœËSÈ€¡šŽ+40/,Ž#—ü{ tŪd9Ňc*¸!=ö§Ü2ƒ…*ÛãMUFR ‡’<SZÁk®<K%Q›€Q)>^Eï±7yÊê=œC\ƒ¯@bü(ÅGºœõâÇ«"se¿­øÔ?öÄÂ¥<•¼ üëxU >ÊZ€Xª>~©hb*!C’Ð,^„YE•£H§ÿýPÃÖâÄšrØš%¸.D)_Ê‹Ap"·Ò
+Íd7’UÁ)M9Ó¼ƹ׸òÈSÅÿ æ?âBaX)#©Á\À‰ìhŸžn ÒOÐÕ6«oED·&‚œÁ]«Ñjˆ…5ñ‹n×}ÿÉ›ÖÓ—×îèÔ"0¶ÛÉŸ2äÂ)èÿýPDraþ¦à°K ‚Š¼T˦̙ÑAœmQ*¨æs0@<µ!Ë
+†}¿f?vÆÅŒÄSîŠ+
+»‹Ð¸)жjฅÂràk…áw€‹€§h§˜Õö”IcEV‘YSv!Ô-T`‚„¥•µ›|#ÀÎÍe K‹wBoCú8m¸ÒŠReï´#Sмõ^@4%xgŠ‚è•ßÚ'ÞbN8S¦È¥|ä?2h."Öf>øFAŽgHY4{ñ‹Ë§¤ Á×}œ+n”þûgÿÀø3íRLAÞ
+G|+¹ìÔ= ÉÞuÙÒƒ»“Ú‰3˜éà#'°-! æ-êÀ×ç0@Öbœ%É” ÿrœ={IvSÄDÈè$c¸"Fqˆ}7Päà/·#ñÔ½yü§¬ÊE< rÕ½7R/ɳv=W߃9ï&«Q¥"©<”b@«‚àø¹ê^´¢iD3Bjç0ET›æÀª%x\ïÊ&íñªÈÚ(ä)–aGºÇ’[wb†>옸ñ)ü1ÐS±Ò%GïE)‰Æ›óÀÜ°²4ôÅùPòmü:~ÓkÍ÷ÑFóQlg`c©³ï®$S *„fýƒ´pÛ+ðÍÛÖ½R’Oz ¾˜ŠžÑ>o"že¢Î&PµTfÎbçèb´f¨¦
+»7J:”¸ |•Ó9rš"”Xí«؆øIŽpôëx>B…½0t *úÍ~9µŠ’¿ŽG† å¸ ç26Zؾ7œþa©Ay‚úQ8µ.·‰8Õqò‰Ö›-@J‘
+¸ŒvógD+½™a&´†X …ægÕJè@JÚ=ì¥_µ,26±dw pj
+Á4Ùƒ…=<bfê̬‘\&*^.![. à´l–‡B›ùqu!ã¼~€bŠži7>j… xÜá
+ÎO´)lm¢ÅS{—M”ç€Q…ã$fkS„ýª€‘í³‚Vb/Ú“mñd[K0…oÖðØ|H¢²ï¸ÔCBv,K:ƒyH|ŸÙX¸Š÷yVD‡‰³¬ÓÖÎR5zL(±#$ùÊòm›)0,a@øšDØ€´-ÙA¸MÐÌðþ¿£ßiò­j> qn ã:j¥OÙ‚ C#pÉáG1Á“ý‘ý¦ùþ*É^^÷w(–œ•Ã¬ßÉ
+ýÆ<Z“B€ÖšðzÔ#«Ô.B¶p™TÔñP™÷˜:¨â¤mZÖ
+BÇͦHM"ìýRʹ&„n1àæ¿h¹&•$P :³3.Ë\4´EYHÑrIߘgöLÖ&É¢¥¹OMÁÁ}O´"»É?ÓË·,…Ý»+.Î:PLN9‰†ƒç}×øûJxŠO_-ñ2jIo »1’­©Zn[#ýW´}d#\NÎÈn”!Ö]$¯cèSmûòQ/Ò¶9η¡½ø¸;Êõîû£ˆA­›~µû£¤ÕL,ôe}Œ‰ÃqðŸù ⶶ$ ½öJý}§qLüd ‚H–Ôf؆ÀÈ4í'1ørÉþ Ë$ å‘ izN@Ã_ ™Ã†ÕyoIqŠhb\ÃùÉBY–"-Ã7ü¢“g›Ä#ʹàžNÄ­f ‹µ¬”ÃÄü:÷ár;dÑ ¤‘ˆIóät!ua*²©:i—¼¡Nó¥œA)Õ
+˜›Ä`"2‘FH&¤êŽ%ÈæËcjé†Ç,¤?ѼæǺù̵]Cº˜©Á2`Ö†F~ß/Ô¯»/UÑöÀZ?‚xRŠQ–<.tUóÖA6¥ý5VßRô<Ú*û]TÈÔØžLE"ê)ä C§ï°Er5a e8‘ƒ]°åê$ªÐiµaÊR-. ìÚ0 ÐZSh7¬Ç*Uå:´Hoû3°É^ ²:ýr“ý?ÿ8•egM¥-ï×KPK6tÀ¼á2…@Òø-´‡<“AœÝ_ ]¡ 11^ÀºØ°†½ÈdaˆÈ
+ˆ,¢ÑA?_‚ØïÐhØ‘¹ÝAKaökx bS@áC…h=$Š®‡LšžT³xÖo›_@Ä”ÙPão=p8îA…Y`gÇ êÆ×cÐr\F
+A"Ë%9`dc¢ÆuXcÀ£þ•ù±£Ø*‹ÞÈ ¤X ö¢ñ%?U˨ËØ'‡Âƒ´9§ªØQP{Áos{ÿN_µ¡Ú~ª‡Kyœ%Í%ŠÊ©ÌáÂÿÞ Èª‡The™GºZ=Š<eù™üϽó’#Ȳ1«ƒœÌ¹«b›^Ÿ17¡ûµƒ`=´¾"i‰]5Ûm(G5êUô&ÝwIüƒC”à›Ñ&mþOQr‚¿!‘òÉ!„°<,¶ºñ¡»ªUK´Ãrü;Ÿ¢ŠwÚ†7Í2Ž ¢Îé49B?„ØQdóë!ºGÞHDM:â ,_G}º€Z}ÐKeŽtò Ÿ¼Ï±z~†ÏjZð°žn¼BØrðˆÎ–ëî3Àô?1)ih¦vÝìÞc*a‰wíÏð+#ÊŸ–¥k8%&ZÈlPçÕ7‹SೡúI!KOô€º6Ø“ ¯©%r0(ÚaywŒ;2‰z 0ÚZsèa»ÎLeš$ÒqVq}Èž˜uÌâd
+²‡Z¡õ»‡ÙE=rö?íïHäo×½º*A\¡Iäáy(9rzm{
+Üb¸.ÄxžŠJ²ÄðÈ4M¯à-KÝÖ))ҽŶW2áz—´´S”µƒxN¯ç;üÃIâ…y:°Ð9Hb±á~è«ÄL¦ì4ÄÌGEÿÉ‹_<´’`3µâ~ex–M1žÍX^=©*ÉÎÅ8Øõ™’‚«Áäw„ýE…ã¯.åGW¨¼aœ+g¼ Vˆ_È=œ’.öC]Ó–pJ†ü„â*õRâGm±tÔ`ß¾c2äIëqÔœÒ>Öa[--r‡ºùc l}
+÷2h/ÑÄ·*Ž@‘:2DÈq†g”dæNQ«ˆªò|GT¹°ýùxŠŠP{*º™ò‡kdí
+•y++5ØÖçø¦R;Â…œ§èŸ~Àט×6A@«XyfÅËi<±âÏìq`Q‘ Œönzo
+›á‚÷À¹n5çm:A²jÑvc­í¢íù6÷îðѦHR\h4.]“SÂä*£`3¼d@
+ SÉbjz¹pÏZ[ôÉÛÚ”/aîâßÁ ²ÔS¦Ú»ƒ·ƒ+„71Ü¢H ’?
+ É®³FØŠ Ü.kXü$„BMÖ²“Š–wNÿ ŒÃÐ@_íWÖ±³vk÷¼<¬#YƯ°Ó§Ñ–Þ‹VœKþiü‘<œé/0kÖ·´%dÓMø›ÏQoExÝ—þá;¯¡ôRòžJ/EY›@ƒœ“±hÞŒ"VHϸ’)¡PÃÉ¢¤G‹Þ‹Já°Ô*ùm³ä÷’?…ñçõMßk~]=4 “C¿{›%%Óå©@Yì*®ªä«±µ³QÒNk÷.±–àvF>³X¶‹ÝVLÑÞ»ùm¡ŠpöŒ'u*éx_Hk<‰íÏ?êE?Þ¿ƒzôè;=ò£XÓŽòI‹hgF´’Ä,.ÌÕ€(’‚7m sp
+ƒ)JÈh²¬ö[h'ݱTÜä¥H'³sÖïðT›»9˜§!SQ‚á2™#sk‡T"ÇlÞ\ÜáöqK˜Âæ׎S‚³\Êä4©ñÝÜñÿ°‚ˆÅÓß—’›©½^¼A
+èíëvùp¯”Ò×¼>
+Ã?ðq{7êÓ?¥'¢Ö(Ù'KW÷+oI(5•£Sd1wƒOJ;ë
+vð=A8Ì·ŽZWœ”ÏX+”áÎI·þñaìtãtŽ÷9”¥‚l›«¯ö”5þn“XqôW}fÞ/B&HÅ£erI]&7Ò­<ê 3XÈ/ì£ÄÜ\-ËÆU|Ô¼jm¸1Â.ñ¡ýïÒð½æק–Ð`Uˆ«Âp|<Wƒ¶îÙ
+–{Ã;fþ-w|±b¢}0þ,ŽÿOÄ«²ÑÑ¿…¼ Büö©„ME+
+®>GélPŒ¡ˆräR\—žØð3ÀÀFIü=?” B>{ŸÔ°+I^&G øÑá 6œí‡yY:o íí™›Á[¡àS²‹1\õ²º{–•gÆX¿ýò"9â¤uð³8#]ˆ=û,*HNMä6˵5Tð÷)ÉyùÊIWØ%¹$Çð¥H¾ðd¾#ëXd°ŒJ°Àš!`Fž‡/B{1}06<º~?üµˆ?1Lˆ ó‚Zô‘*ÚÁš{ÈZqlm”À;}FÄÉ ü|hÅÓYy®ë.½Ê×îcÞA¤w£˜ñnì(J틇ó° ç¢1¬àâØh(…y"Årò·pöÓq ŠtÙ÷SBÿÆ$gvÓ&3i„H‹ˆØÀkug˜8*¯*]‡ªü;0¬ˆQŠ „(d%Ýå}™¬ÿ*Íyv\@7xé—’Ÿýç¯üõ¯¿!±X@Eö²»mØ^É4ûe_ÿ|(*Ï’Øý8•°]5 wJ²>T´[››TÂ#ŒFCðîPFï¨)Ծ߯¢$‘­v£ÃÀ²r̘þ/Ò–×=ÖýÃea¼ÊöB”à`ø$Éä°6%Y™ C… ÄIukr›ñÉÔ%a¦ø¸KD¿–571³*<èW›1šL–IqÖõƒ¥jœŽõ¨È ? d`kyøk—ðÝ"±Çqx‰%¸ü¯v*v¢KÀn¸/Óç 9Ë{Eß‹Þã…®Œ©å$$ÃÜ‘¢ÔÄÏ»1{maüZ”k¹>ÆÂÒ*"¹¯ÅÀLšÜïY2k¾)ô¢.Jî
+—š‡¿Jó4y>TöEPÆî ¾®²8dvˆãæÎ!M4ŸgÚ™¨làÚ˜«6š—0)D!)ônTúRKý¨i ¿‘¹~sp§¤Ñ÷„]},
+D ’¿Ó?”Tž,Ç>°ûÏQoE(F‡Oõ[ÿ$Ç d\!1;ÓK؀͠3 Ük:PB6¬º\ƒ,“¬  ƒâ.IäYƒa>NøŒÅ$b¬KVy`@‹ŒrˆqŠ/Œ§w‡@ã¸ä(A±Ø=aQ²fÁL“©ÜÁ)Ezx+’wå¿ýU⦶+·‘Ö>È™­¤½D G“1.^ò²W
+ir­À³Gýïåû›MGp쇆1[íI²´_m$ž=½!ê²Jèâ٠ü/Ã
+jéb£ ZÎ"SÀëÑ^¶¢8‰É8Áu
+[úg %Ø·©œs¸PÞDÿuì=ŒuS.›å6^ ˜Àæ:E&'P›0ç–XƼ³eZ ­qOëª7*!™~¬}Ð|ŠÅîõ!†ÿû
+Žÿ«ˆãPC&£ÏGº€ýd¡¸*!΋Ôc[²T±§]Nœ4Ü"± |ΩûÒ¦¬¸.>Ö)Aî½¢Ðä"/âÖ4º¡qõ|‡
+ÀªÄ ¢¼xŽEÎïZè®Ø9Ï^ï¶x¯–ñ븜ùS2Bxá{˜}_΂ѤÔP ƒÈÜ£­iæ Á4ÂD¤»ýÅ4”æÒÏ}
+ >ÑX®ýr¤™8ÄÛ`@L=ó&õw…DÌëJ¢ÁØT9*½2K·d×X4Ú )Õ}9’àH
+ßÜÌ°Š ݘs/¿‘Ù«v¶Dbð@e„PŸ“sY²gŠ³¸}A*CL>]ÕZ\k#aÛ0Hl ?3f‡âfÖþÉ8òCGÞê0±3J vŒ˜–Å¢ Ãê-L®þn Û`´ ·;([HCdǾ)>d¶ýêòe™ùM\¬sª…uó¥ÑÃßN ÍHÖœ)R{ÖïŠrÉAþ'yq._!Blp,aóÀåUûïWEQxã$w;ôi®ÎÔìÇ$ª]dÅ UMišVÑ:…ˆˆ÷¨žEd^ùCiÒÜ7Áá,ÓR«`„™4úÔúás“¥x„ˆ#KUÀ£OŽXÃåúšäéL3‡°5ÃZˆ(ó2ÇÓƒÏÚL-Œ#
+sGk Dœ®”VßX[x¾¨u­õ²5¦ äæ¾ìZ:ÅÚñWo!ô.陹 ¾žË Ð38ãí9HD2}B&”úÅLírõ¦}òöϨ‚šÕ†¬¥]eÌ&¿ˆ;“Ÿ³¥‘¤6L™ëC)Kð!‡~¢1Ô€ag¾±X{iè&^-*Jˆ]eÝÙ¬é7u™;-€ËôÔ÷:=1iØ02ÁVz,ì"þÝ2άy ·¶’épx\\}Šò¾Â%QœY'CÖâ‰xáïrõuªÀ@bÝëó¦¤BÖe[%©ÉÄ0Hçp‹pQa‚ þþ #”wŠHÿýñÇ¿>Âã}üñŸ<}àA÷‡ÉX á,íØt¼iyü:Ú¤±2ªòXÔaAúZ¥ƒ éåÔÕ"LAªúHÛz™‰ÚH3´ÅQ! MQ@2oŒrØX§açðÌ<33 Áu‰&‘7ãiÎâ7Q:º¨à’ÎçÀù €ïžç‘t Kq­Ê»GEy©‚²ŽÚÓ¹8QÖj.BØŸ|-ñrmÕ¾ê
+¢m\ƒ³'*>_„¡c¨k@NÙ’G‹!Ä}Ókq4ø3T ÙôC‰5$BI±ž:uAx£^ú}:äufŽ_ò:{Ç]gø^˜Ã¶\«û»…Ò
+BëƒüÙ#†°vc ÔmqX^kÇÏx†ÞúRÈÖøÀ‰rt£æ?ì£!6_‘e¾qÛ¶Áxsˆ™i¹²ZŒe±õI¸“†ø®x †ÏC\ø¬DÒY´šÐ’àænX—c|êšc d%•b+³AF€ÒÄv8†Uh@]t":d öIÊ@Øñc‚”O‡,“ÑlŒ3
+E“§ÑÂ#‰+†]ëžN‘½¬–iN‡4TŽ5h&Bšº¼¼Œó‚0 8™6,X
+B‡ Ô!¾>NÜ'r‰ Îÿa œ4–…ÞR,Wk¶s½ŠýE/Ø­t
+º:Z¯që
+IÎv‡x0Ýꯂ5Tä¼^T«Â¤Ž²X÷¸¦3ËìF,HëÇsªŠÎÛ'ó}ÝáF,fPºŠ½ªuAØ”sÄ®«
+q•Æ²¿¬¾dÏ~Cy‚~Ÿ‚Ž@q½îôù799P´wh&I
+v´, yÆ Ïüƒ×C3Æ©åz³ÌßœªÖ´8$±©TKÑB($b Uê•ù²àŽ:šõŒ}&
+,1`:›OVà*ð
+55+0à=¼9úR$R B³Wi€´yq5•Áó<F#ûnwuvRÎ=4­À˜(7Ð>tòGˆ_Ģđ“µ=ñda–x6Ô¶kñjö¡!>ä*ÚoJ²1Ôœ™Ýó)°n'›<(“%Éb6_ÍU¦„9z£Àa¼žžBªè
+<£äÝëðlçtO†–QÎn« rMÌÕ_WafÇö^9—†oâ©ùí@ªG«((ãÏhÕ'¨¡1ІüÊçz¤ÉíìUu‹Ž¸ø±ðtŸ¿¢tdt‚Ë 0by<2|:˜&n­1%+à¤|ø6¿Š_²°zîHWƒK¨!¬%b(« !I™WÀ@t¦‚>=ج }~õ’u½
+z3¿³)¾{mO/¤J,¥R:5ôâWuÁ(G:±…Cý¹h£µdOÎ(NG~ð„Jä"×!ÑÓ·`€aX4”u[AvV‘9e~ªsÌMdJn±›#¶‡?µêãoÿè¾
+Á3B+>~ƒ
+H‰Œ—M’d9
+„OPwÈ L˜’€u÷²n1f³Ê¾ÿv>žPVwÄ‹ìªÿÊô8ŽóhSf“Ðeÿý!c¶ÇXÓ–šÿé+ÖEÕg³9úÇÑÞ-úìÍdCº7i>Ç#
+ÂÁÖLÃ-!Î)îºÖ¢q®zuçê97öŸ?þ÷C>þ:ü«!Òüú×-ÈND:d6éöqA<:OÑ6­oÈì¼µ“kCl®Ñ‡u½!*‰X­é”+t@‹¬ù\³Iâ1ZXø>G䉹·™õˆ 8ÂŽLíi1›w‰fër]e3˜2(Àý9<‚{cy³Šføh|„ù†(å[dKdlÐè_fü¸Ùé>ÔÍ—ÅÇç»Ëâá$GbWµ»ãæ2„ËÆÉÎÓÓŸ •eõ˜ÞZÛź;&£½¹ß†òñ€Ñ¥ŸzŽ®”ÛÚª`Ö
+(Þ(°ž‹œˆÛ²1šn̘«©¹’œbNÐ)mú’U7IŸÞgPŠU7½tAÀNC…Ï8W}Ïä$}Û¤'PØ$¼¦GõGFîÒÂeù&ý ˆf„‚1´¹|\|[©—WmÑ‹ѳï/HŸ+Èöˆ™ °öhä#šL
+»¥P#ó6FÛ©Óñ¨í•lQ |zC¦rðˆE¯hõEËÐNÃn Ezç¿YJ‰ûc !aôä¯é}0Ït~~Ô-çMh¯$½ñÏü™ •êE»ó¶>D£#Ö¢å3~Öu²$Åž@½Im¤{5<J«®£/N>]ˆlÎìò&Ä«»õ19¯ï继F“l9—qË\ uÕ>:L„€¿céèÑiÕ¸?fÃɳDêé´Ï@^MèÅ0Ô°-h~²ã4\p*ª‡a<ˆZ\)![äŠfœÝŠ©4ºFg®Rðʼn*¾Åú¸ïh¢™‚:7}ß[›=ã1É(zBQ*±è“¦P’óþÚ â› Í ìtAPCm©‹îÈAôá2uG®ˆ #ò÷Ú´B‡‰)°º¢·¨G_:V3¤‘JÛIR4^uhcuLå/NiRmH0Ÿ›}¿ŸÈïOôÝ“V•u²qúù„²vb¼Ø¸é:Ó!à!èÐV1/ŒÀÊÑc~lž€òë’3wMû¤LˆýØ*œÇ@¯Sø'¤ž”§g0$BóÿêuNC7¨âÐ}W‚äÄpã›ò®Xßý_2= àº8ØƸ«âéhNºäUѲhF.ÆbA4è…Le;U£¬Þ‚Á¥%¯ÔлäûRü )¨Ð°u^
+%³˜\Íâw8 HÛ]¸míPñ ‚ xòíDá7An@È[VZSwí_@7d¤†ä‚:Œî“´85p­ˆqr†3¥gO=þ.Šõò'R¿Š"MØÆDx¿³›Ò¿Š"Td¢¶Ë_Éý94ʾR7ã^'3 £Š}«‰ó 12$Æ.'š8¯éàŒõ:'îø
+„¤ü=Dª°EÈgA@§¸ÐM¥‰ ÒÊæW¿¿€žDñ^9~ diä°|ä‡O ,UpĘÓ»ìŒ×KÅÔʘá¸0qXA"‡CÐñÇÝ,ö ê˜Y’#
+è¼çˆØžž–À‘ÍÔ )kW]éáÅóùqo6iô™Í6ù;HÝÄzP¤·òûsf
+ä’Ü äxß¹Ä-O¾ bØÏN€w¶¶ˆÁ^‚{&;£œâ:k æȉ#i@Ë«ÓxeTx›ž8øäù1˜ÉJq´ÕUhL&©]ühüRº×b×N”ú¥žŽ“¹Ë‰Æ7æ08]ïUðßÔ4…XfJgx‰
+ƒ‚l¹fnÍí|2ÒiraMAÈN1øʺ.ë 6µÑÏ),”BDÓ©s“Îy¹J‘v0h
+£Û®²s t0s.{¾‚)•[­Tª‰8ý
+ãëòY™ì
+bL*^1 0«‹T ûÕ¨‹Ðsä›Ñ ]7k„>áäŒRþÝ<ç‰lZ¬•ÁZ
+ét#SrŽ}JF‹ÎáºêÙò0§©]‚NÄ°’èDŒsÑ ¥ÖÔfö ­s(eÉìk 3úÌž€.Vˆeð*ÿ«E­«H„ç`)<¬A=ôxþÊGN.tôñ¾'ð/”²Õ宋êÝdû[Ç¢V»Í™áïQ³Ülž)ˆÆjî¬i
+’»g΋U#ŽOcQYr{¸Î
+rîÆSç¸c%Ø!cŒ &†3ŽÛ%
+Ž!_¶è[Gª;ûŒ˜|uY¢GƒÆÙÌm…™PÉa!e+â´­ÜNó±”Àˆl‹RH¡Ùz&èòN–þúy ²tTy5.‰ýù„¼°/ðºk§HÄhÙØÃ(¿B¡ØÑ:cµø—›'vªùY;0§ðžþÔZ_’ÇÜ!’«Áž=Ń¯°ÛÕË¡véêü½Ù- tÚF¦Ä†¤£Í•ìß@ê"l7Ó!Ò„ÞŸƒ\äè& fz¢IJp,o(µ%W,€ÈF%FMÑ•Ÿ_ ƒ¯Fº ÷ÉÍÌí­¢QJÝZ_­Ç¨Ü¤!¿,!ao “)E63ÛygË$u<{?n@Ÿo@Øw…þ|e+®¦Cmé@õxËô¦4Û€fÑ„ìÈIÅ“àáÐß¿ô¿ÓÀÖæø²VL\²ìrç]xj²É® aæ€eŠxµ¯ÎBÀ¹+X7±ú¥*!<_þ á(]ý¨ÛuQËÍíÖç%u²…éõÎ.&E#M>Sm÷ÞÝ1Ád•bTÀ-×NÒÙ®=J«Í)LÓØCº ‰4Ѿˆsyå°ÕYnyÍH¡ßÇ0NINvС# O€Hí:’†‡ñQ¥dŠ³'Œ´ÍÅ›P:!¨¡ñìž›77 êÝP€‘‚R—™£Îô@Í8¬hf®¯…`ôKÓ{ HC,
+W¥Í°¤µ€Öäx)r&àzY<_ºw§Jµìþ"éPì!¦üôìÞ1—ܵ—rt„ë†2WNh½Vü3¯L­h‚Š¿Šµ¯•ô`O^fyu'ñ _Â0uá‡cH²ŠÆÖf÷\äC"'ƹ®¥ oÄIrfCÝzH
++kÛqÊÖЧ¢µ÷øÐi'¬)ÚìëàÈŠ‚ÖÒ.&ùV‚¯sÒ£)üúq/Âá¼^`ß|šGRŽ%FÈ“Æñóveñzâ™yîÛÓEÙØ×ÑÓøºŸþµ…“’1;é𺟗A\hòu7ol ,Ø;9¨6Øp!L0÷M¦˜læ¤h+Ö­ú}%1€˜¥èŸ~“dá¼õžmÁL`>Ì×áeaN>¯c¸x§}ÍóXá—¢w/bSõˆVÜ\T4DÔÍßÚz÷J¬Vý>˜V®ñÄÔ¯´ÄÈG•RƒÃ˜þtY6§1úýtt‘£ËÝ÷Ý ÆN[ÏwÃtÎóô]A>!ÒÍœ-ä0
+p Fs艟VæVX@¦=_Ÿdp²|ˆ”Ê_Ï>B…8ÜI”ðÆÀËÊím”–D
+ë~)™Ÿš°Dŧs
+&
+ò¢¦I)€”ÀrêÒ,ÁS`3`ïí¼Q;FÀw©%s°I%^íO½ÉcjÅÒK×)éáÑPðÅÐÙ ˆeUðOp
+'ù‚Ò‹„JŽ‚ÙþÜ úb=ƒÎñ«Ì)Oæ‹NZ͆º®Ž-¨xÕb8IYjqsÁ—’'fúRôϵHêË#AÎß9]Š²E®ÀëRrª„©ØþlÛÑž$9mŽ?y´8ÖýpäµÈàåü‰cœ$ Íâv¹óÄ@ñ‘/øÛ¹¿Dkãîñ!S¶Ѧ©Y°BGéÛ5žçTD ÷m
+;å² [Râ¯H¤cÓçÊàS PTlwûÂ1à{D'Â1É_€_%ò°ô>·þPB~cC´9t- àA`ÝR¿Ô¼ßk0Æ
+`YfAY¾( #b˜õ*“™†?{ß±ò$SÔÅ{ÃÔ´ô‘!ï½’ã©qÍžð˜Â6 °_EÈÂ^Uü[sùeAVtåÓÒñ¬¥Ÿ¢°…p#èýS
+ý<TÔ‡¼iü›‡ú‘w  ²Œ¯° D
+u«Ç”$# ’\A¨ÎJx˜+¯ÈýÆÌKJ … NRû:gÑ¿õõý;"¼luLh ²"¿v†ìdÐNiP܇™d–K/bA¹³@mÖâä7²Ašˆ•™¢îx§17'¿tÉ*РÏ é
+]¦­XºŸS˜bÃʃó ­ÞÃÕÓ2RÒ5›,¢ñO™€\Aq—É
+’$ì[é~N•d"ÏÐĨ÷ÛTyð"EµkÉü”Ú2vjïúë98ßnIÖç
+aÝ –VI³¸¥—°Ed°…X*‚‹ìÓ¢•£è:rvG*Aoûοés˜ŸV»Âa[¸¸ÑRY0¿pQäÉø­¥{—3LŒ4+
+] ©*¡=œÍ?@dÜ#ŠXlÚ8XõƒÝ«8Ã]ˆ¨’äZûX=|­¹¶ ãaPy¿}·è•˜ß¿ÃÞ“äg( ˜vD—à=Ú"öUF2“èÏ"Âm'ȧ¢8t!èo†s¹]ƒnY8(¯
+þ9uYéꇰQ™k&Ù‡9’ k9 ž›W”¡jÇ:§i0g´-¨xÒ"î-æ%C<Ü+V!]Jæôé.6 GoE³DôŠùeØ î¯VÍ+h
+œ¬´FHXö âÆí
+»"STNÔ{¡ãZMR /¤J4,o+p &³¦ü-v€£²V䳶oú+¨å3r­"U‹‡^ü>`tûBAÓ[¬Ì8gBâê+ŸütjØõ¶÷0Ô<!©­£eÖÓ+FI,£iù3ÒE¨ˆ ’e}©%"[ RÚP`@õ‡AÛ‘NL)ü/»ˆa"a"Þi1£|ŠpÈ{FÁ»£/ÈêÆèF &uÔ儹[%FQ±d]EPDR×Z²çœÎak´„«–r€4V:~1œéøA«Xñu‰–˜IúaW­¯Âã ST'Rýf{ë~ „ÏÇÍv‰uduÚܨȃ
+ü@Îøqâ–¶žÖ+ -)y9ŠÒº—%»é_<~¥*A³Ü9·DÛñ÷Xu
+°«ÎÇs2oú{e½†(yŠÑ>¦ÌÈPÄ]¹
+<Š_”FÔÓHÏ¿\64(ª`ôGó¡ªsM!ìOç"jHû»JïË©”Q\ÚbjÇâ Mt¼-/WO笞óQò2,cƒDIVfÛº«¾‹¤0”â°JòÃP~ÅmÈÿG„öµ²zC
+ýœœ‰íݾp6~—OÊÌBÈ—ÄrØÖg2úpŠ:¦a­A†”RùMCþ¾Žõ—7ä†Þóú°ýQg F>qYz!:Œç îg.™UVeÇTƒH‰¹?ø<­­ÏÌ{/Æ6ƒ!i"lÒÜõ\‚¦ÖgÚËôOÌ—×%ÉÞcXÌ…}Ç€¨ŸÒ@Ú'ßí+1LVBÚ ¢ª”&‹ëaòØâ¬vŒ¯ÕóÎÛçdúk†& uDš‹ƒNõ¹fÖÉèAƒg-8@ä4qwˆçvFPÍš¶¦qÎ~ŽZ çøEï® i‚…Ó¯ª:7@›º»èQ mi±
+ú1Ó•EÙú‰½ ^JSˆ¨¤ªöD½¿3øÇÿ®GÞC‰Óû!8ÙµJ!§L2¥ {Õ8Á¤}Cm ’Ø/ì@=;Bò­l_WöŠˆ‚TôMö:ä¶ mô‹šF†%MXÚg’ ¥³<U¾‘ƒ@µ'™S70“8ë0ä²®«Ølu‡È³ƒfƒˆAüCä…Œ¹65Ÿô§“ì*²jš"?Œþž —Q«±ÊWجMGµð!çDe)d¶>@VLYÞW]@H53¾ö>ŸkçÌœà+'¸6Q…T‚®øwÃd}’ìÖB`‰¨24·9á±½\MΟ‹Q8v¿gÀ}f[›À Va„ÃE’Êðç m<@ÎÊô òó
+Nk7ã‚m@Û)}9€¾@yty×Ü<ˆAôX¢<R_¦\ß5iØœ½ïñ¥8äÙ$Y´ê0ÐÚ;äÞW•qX3ŠÝóýǤ`÷waR¸W’cÙBŽf… ßz•ÿ£LãNPæ9¿ .2gèÇnz!Û »›E{I³‰›Ò9ô5Ë›¥#½¡oQ9 ¢1ú1ô B^¥àT¥ì'£•Ô*aEÖøRQÅ*¯ç¥áõ Œ$&ºüu³p|¿{%æ…|þ1ù9EÛ¾j_lv±(ò¥µ
+Iw°Æî&«†þ³*frêÜ@rBPcrØ׈–J¯Ô”ý²)UùPS츶€FmCP
+ò-Í {qâôº0îe¿çús»~½³‚—5Å ¸ûŒs1}‚R øI…FÙ6õ D[ù Æ.1ÿi³£¥•£9ÆÛ Ëhü<^÷èâ>¿@ €¶†YÌÃfF(Ô¡L¶-,·)#RÂÝL!;ÙíÁG£pœÆÇÌrø4©öÜýç·X¥µ6;F¥àð–Ƕî‹•Ñ
+F¸bM;eé$²vårH7Љìé3A5|…ˆû6è4€·ëÞ]Dá<[ИNO.€VÍœým º˜ñ‹4øœ@€÷†üÿ éÀÚ™Ìiç«-D]Vmǧ­öÛd|amÛ²€'b\eÃÄ)0ì ~wK~…×aªC»:"÷Û9ߺ{}®?íçCÓ[¹c¾ Sq¸Ök¼c"ÿÇx¹$ÇqAôºƒNÀ@á5·¼…¶œûoý(ŒÌi´Èp8lK@£*+?Ĉ$ƒý&Ô+¢¿«<.2`$WIËŒ„Ë€iõ¦½ Qº˜Â8 ê°&vpò¡J)LgG9m …´±Æp(IÁ¦F”òóª×"rSÒ2<™Ÿ¤rí±ít[G–C¯%ŸxHxeÞT79+>ÈF~úÏjŸEüâŒ]m'ðÉÄX{ƒåÃØPîà÷o¿ƒø°Ïsh¼d·”Ôùð"LšèHÞhåRe/tG/p }¹­9[E-
+ŠBæ‰>¨$qî°l‡èºf‰ '<d®;”ÜqÓ—¢cÀ_³æ¨µ­Øt*J"4ÿë µ"ePps+NG!4…¶±Jf¤jRgw}eÕ”ÏÒ]¬l'8!XyOæ™✜ +=$:!\⫤&¦Œ€ãʡįàR—mwçÄÊ,Z[™H_#L0ÕÐ}gd6ˆôÖ
+:= b%³I÷ÕƒÛåUj0?ž 
+9ì0 @ªÌ‡’M¶huã—”Çùq DŽÉŒÑ¯ÂÔc¸ N|•h
+^¨ÌYÒHÑÀµ²¯â…,k*q_ A‘¨>üµÎAW#kqƒ‹Vá `¢æ«ÇU2»½T|À‰õ86]¼É0
+ëãâ– %T²;½`,ÂÍ°¾úÿ,¥”ÑNøáQkhCÁRAñœtçÌh®Y¼,#t2ì¡%9^Å“ê7A´-%ño®rñ8”|r½ØÛ4Êøÿ>¶¯©H§Ö:,^JäB”5_è8%Ѧ8Fêþy,: ‘ùÑ:>yä­q4¥t;9œ“ 1}ÏãDfþîDÃœ² "<¯o ”Ô,kgþ=ÌýÊã@Œÿ+oÃdl ˨û¢må „ª¨nÄU‚!ÌóÕ¿¦cs‰C¤Öík2Ëž*æG²åzʪóJ®~Nà}Þ¶wË[lF— ¥Z }MŠ{ #`A*ÜËþZSµC†ð1ÕµëÖøQ¨f«ƒ>§/\\Špy« ‘ôá Áþ#!À»z
+ 9ÀqÎæ%¡¨°®ô2S`‡²zôäˆ@YÕ-&+A0+" buM]áI+3¶85ôÄP]“é Af
+Ýúþ˜/%Ž }ZÇ'×9¯çðºªeˆåK4}ôM„">Á+x´ÅƒñBJ±n\
+$»7`!PINv’ÏÊ•-(펅UC:5‰Úøî»""f‘fg8©½wŒyÝÑÙOPÓ±Ô‰åÃnnã  î¨ %Š>Ò¿ö¥ÙNñ«/;û8 ±2æDÆ>‹§)iµdçؼ„öšl¦0¶J ¦Œ¦§¶Kxl‹f‡²Ö±Uô©s7I¬ïu$–e€ii’'%x|Œ?oŒñ¸G”( ÜbHýf›¸’ˆ…R¤rÞkJ ,Ò}IX6˜”C†ñfAÔ€ˆÎàqv3à‚÷_ÇÂóçåܜ٥¦Atø¥åošÒ®–ñ)´Wºò³^%¤Wè,<c.ÛMУy²ŒþìPôu%s²; AÄÇ\|Ú×3Ðá–¤W,4ŒÛë)æú0nHÖNǼŒûú1Øœußµ7_;|X†/ƒúó“ùxz?JC¶
+@Æ0Ìc¾Šd‚Í°Ö6AMJL;Zò
+ÂHi£Ý˜ SÑ—Ñ‹ lZ B׳а¢$kѶ1‘f¦Oæ©]Ö† WÌ n¯Ý/Ï<GÈy–fŸÛ†ÜÌšz­Kí¨ª®|-ñMæKGV´¨é|àb³1ÐÅBÛS (ŠRæÉJþ¨BòPZEI6H±z¥âéðæ´(ÁË”ûÊtJšåÍÜ‘¼úd¬ñû¼zM€p»±¯ú÷~NDZßàDBéÍ}xJÞhäöë„ZöË4±… ZÒц‚“ß_
+ÿJŸXŠ9xŒ‰Œ"ÎçÅ1¡yšÚPO%ómöF³P¯†tÓ %YùÛw2 ÖavšøÁ“0ºM¬#G
+°ÃH×ð› ")íîœ
+;UàQʉ3(Ix
+LlýÄó* 2Àèú¤ç(^Α÷¬0&–|'4%Ë쮂7zPèšÓ´!M¦:·µê¯EGdžíýeˆzÇO‹¤;À4e¹¾ðó¦h#Ê~/DSÂœªN.Oq“bu•$À¾±°.q¸iåpân¡¬ .¦ö¹Ê’\š‡Rî_Ç6_
+ËZ†>çIÇLΩ·q &©iahãÝ9E/'6Ù¿á=L/ŒU‘S¸.Åq`÷@íf%ÎÙîMƒ¬0oe±¢nð© B8 œ¦‘× P˜Î…ÀÞŠŽ#g÷Œ<¬òŸé:kä›&¯ ‡¢(ñ•d:. “Åâ ’ãÞ¾×.6€?¥Ø¸9å:-1z7án¦NÔZ%Äd8t ÐF(†dW‰,jo—5¹@¶[=|­9µGN›ä>-?-:¥¡oéûoZ+á.üÑÉÕ>VûRçLG¶vRŽ.åO\3Á(ü¥¹«”4 <°Zu—°ì‰Á6rÎJC“H™Ý~úV…–sxhmSøfTöt„@|üƒS‚y…¡šj^*g6oá{Ʋ6ü&#Ž&TµCÑÇMF çnÓCÎvë·J¦SD*’Šä"
+zb`•2ßYËÞÖ„å-/'>½9Å<¡¤ÝSîEÞG[ò­—â=@kÏ;;àG2@†ëë<3äSù+ŸGõÝÈߟv^Í·ˆé6¾£LÐcL¦NK %Ò¦ m¬mÛ6pÔÈ°gåŒùcÖý*" !ÿ“¥qtPÅsu‘À°¢¼­*åM'‡@ K«„ö—*aY¢q-Á)u¡ff±<E0#ôøãeŽ$Y±DÑôJF(‹Ù#D¬¿Xê_‰Èþ97Ü_a/ÒHè6ŠÊ›1¹ûÈ”Ñ+ÝZ‘,‡ÑĘLù‚SÑÍ»,·I_^™{Kß‚ŒFš¬*ÿ u*ýÍqèkÊ¢%Ýó¸£ÿÈÓq¹8 ˆµ!J? Ï5Ô»uÀ°—)!`Ð4…›l¥ Ø€{¢:ýH¯ÛÅ’Vñ‹<{  M`$ËÚ©½(ôNIæz
+±gâx d ]êIòLt-™ü9Rç¹b(h7øpÔEÌ,Zƒ®ƒ2™=üÎœdÈ<4™ÊòM™nÖäKÌwì¢ ÎàeÏrÅâQ׃õ){ÛdW=}iÒ›T˜¶¬í
+y›™¢«ZlG4†‚ÆH•ª®˜U”/W%¨R‡…µÐª—¿óP *– ŠC5;âÂV_¯@·ÞáDhB§ÖS¸y¼Óôšßþÿ#Áò”ž7ùH*(êRô#ïŒNî¹­~øó¨ £8[eYuVLã@Pú@£Ô¬)ÔÙ꺷~}@5Ѩÿ@ë‹C Ûv7Ðã39üþÇßþæ¿þ/—i*dCÈ‘Ö<õÅ5ã0¸ŠÂRAý“!bžœœùi"ìfïÝIaÖï*Œa§§ÒÁb&QvU½(Lg’GGК9(!G&#™/Cg`g2m¯a^¼¢,ÐvȲoMyn.™["ÂpÈ€r‡©š>amì;àJé¾­®€Ôt¹“’|… ¸QÌâäÑÕÓ«*/á5³Hˆ½poâóA4Ùì/;!cÌiç!ÊΠ«|*iž…Vm¾¤Ž•å;«
+½B¼ÖWÌ8AŠY҈ƭØ
+ã;OvÕs¨«'c•C‘°¹Ûâ#%cîL–. üÄ BB¤o.R6Q ;@öNC¿c„ R^­SåÞaŽ:£ž²#èŠ(/ ˜ErLr›¢;Ic³òW±k'Vm lõîoCËèâUèlBn¥“ ²*©‹Ÿ ì/ ø‚&Ÿ^åøcòn ¥Wï4‡e?pâ€Ó\¶øÀ&ò ð¥I4âN$#þ_즠ʗz]ŠÁI=:cúƒU˜!fÄ×!Šñ¼X §Ú‚óO2H8†ÞŽÅD›ôàD:<Èô­ÈUx¥-ªPøP$€¡}€™–oVBf°1ҧˆ¯Õb8ËŽpjeçt LQ`mö=äFϦõ_‚“kqžóàaIL¼Z íªGd—ÇÖ:Ú­\;Ý@†ÓP(èØ×Áu\7ô¢bç­…ôÒ˜WŠIå1‰²…é×ó±ëp‚2Äc'µ~'A^
+-DÞ«9DŒ¯1<Z°±LÝfõ€¸z‚ê³—yº=,ƒ+ÆvBýHpsH_´•ë:ñ†P%Æ¥8Ze€ uþ^b¶ÔÇ´¦"nNO$^ù\.UDÚÆxµîïgm›þ„ÜñTŒ¸T¾8¢h¶‘j—ª¼Íä©1~Õë„EFPhIÈíc#ø äLÏ´(eÙÎM)ÒÚBd£õ`–AÄ©ÎÅ]‚b&ƒë=Ž šKdMÛŒmþ÷óœ"^Þãs³Äb¨{^Áh+‰²˜‡[E9Ù™ÒñÉÖÖ¥¨]DÉ|‘»””‡t ‰ÉG“W)§¾yBéòHãâ©í¼ÌÁ‹Jh-$±¾BüâVbsAwS77z.&¼óÒ”]ì\·©ípE“ñæþÛ2<ƒ¾Ž mX2–Ö^b;I9¿DímC1å-±8AßÎ4\Ø
+Qà¥òhÄG/q‡h® ­
+º*vÅPFáF¦jYÛÝÝ«¶°=–+‰³S8‰È†Ñ~EÀ]– `ˆóbÎëbqžûvmUy.JãµájÇ= B ZÔ*ø(púVM┸Îa¬9€À5±ùÄ2‘-È5¢ä“aåE½§•z ªAvV¼c*j*B†þmôÝwPf¤H‹Rxl”ï5À‰æìÑ«0·Å1A_qqª+[F%’«&o òýÆ´øÌø˜½~dôÄdóö”ƒ³Ð8;GŠÉóØ.Íц¦@K!Âl;vkAžcñšµ_A‹Yš:(×!T‘ˆ!G«LOÆv§å^˜NÇ”ó,Ä”6¶ÊᙚŒä†Ø’c²R|l]" âÖ×ÇiìWüâ,'¼ûÏiâÄÏèá7'$ üì‘7FÎuªµÚöÝ@æ@MÑY[QpŒ8 Y}Æ7„é]VãJQÏyC“gä”J.Ã%0Ž´j;—ä‹c†â”±šl_[^OÃBcð ‡w€ì­¸)ä…·ÁÔ­ó:t-#Å£0l8ðhPs¾„P½U${Mß‹‹‹•d[hî‹{ WpÊ%°-É«}“_ãsJ׊gÕò™ç”N33#¶"€pñ¬„œLñ " õ /è „cN(½„x¸i¹ƒ`ßN—Šh°þq:2ò Ù‹ÈF›qäñ"†¯ûfÓѯ«/Œ 9 Áíá«»BJŒôj1÷ƒZ¡vA]’Î.ÁJa~hQhoÏÞ3$zU¡Rš¦q^§¢ÑY™G1(X²¡Mš\at2•)—ëâ¨ÐPipûÅ_¹î)^i+¿öu!`Š¯`ÐMÇ”ý†‰÷€¾ÞÅh’è±$2jºMûèñŽ»`7ô…™Lð]fþk#Án¬5Xœ’À/üO«;xy™ÑùÁx“ߘ—3è´’ø„0¤V¯í]ÐÉIݶ;‚n·#Ñ„bí<ƒŽ+=?æ3èñ΋ïÂ|ühEr]Uãëç׎Qmª‰" X“ö¢óêáÙ"÷nx•ŽÇ(\““ícý×^:UòSÑH¨H‚AôÁˆmÀþO‚Æðcñm¬PbØþa¼LŽs· sP,ìËY>¾,|ýó?ûkh—ˆa‰®ò&õ#€Yz‘³ÙAç½ðpK$3
+~£s/‰àûÓ4èöx<ü †ª?´G¥B”LÓ©&nñ
+ =ÖEÎÞq)¬¢7ÐçMl3ƒŒƒ`´†_•3a.dàd³Þ­võí9(”×r‚HÕ{Lp›¯AÞqÖ©00¶²yEpA^Í·ã^¼,³—à È–{[¼]þµwÖâ„Z¡i3 Ôv‹_ãYä‹-²@”%ÛàñàÌÿ—Éu uBñÚr‡åJ˜²@
+¥aõª’²„Ë0ó(<]8Õ3É¡#1|\yÁ²ÂeCg4ÁD\†äÂ3)
+ŒA4&Á
+§dêæz:‚ðÖF^¬MýH™Œ©íª2ÄvÔ1®œÁ §zÖpU¹*Q ®×¢hv¾u‚‘ƒ¢V|³üô›(s¾TÅ¢†b‹q±×¥x|\WóôG
+¯¸¨ 5Y¯­ËâéÜ&Ñ
+XÁ]c°!…ˆÁôDWé& ( =y>hls'ÄŠÝýNÔ#NoÁë— #|¼°Æ­Úë'Y·‰ë¨¡ýŒP}˜‹™¤ÕMák­êdÈ„“Ùɯs©b£¿HxÎËÇ蘪 6sÖŽÿmˆC`¾íMÔ ƒÈgí ƶq‘h 4Ä¡Á¢¨ölzD"—Y«]ŽÙÜj—E[jßê%íÒ·BI­—T¢ÈI.%G^{eè‰w'è¦âB³+‹ÚKŽeØ 'ye/ØzÚýïÀ-ü
+lr˜»Cl!V+ Ê*†c™ƒb”õ
+evËÅ ÌfÒÖ‘†ª[e!ø2–_>ѲìdÚØ,ìŽuÂÁìôÇNbaŸä€>o†Ñè½£¸¹Ê¼¦`¾ŽUÞ™µæsf;?Ããîg¼RäЄ)‹9²¨¸û¹@CÕÞ2no1ÞX§CVyà|™É· oöuƒ—˜´ÐžuyZ²à2‹å ­¤uñ­)7ÐçMç¬ÁL“p‡M,¼L.ß‚LòÝÙàÆžÎÉxð§Ã“ vRbˆTwYB 66‡øÉOó“ƒi˜ñB°"ô-÷@åà†?ÏB<˜3}‰% –dôÁó‚Ÿ7%X•ÊjrITx\{¾­B#W0r‘s–‡UØAΘsœX¦s$¿{ r*UÉf ü3§Iæ1Ka0QäòØâ;È›ó½¯@Î2ìmq–á×Þýï¾êiÔB+x“1ÜW¥î#æ)=¸¯Zt(œ={™Õµ_@²Ú™ñZäæ¿€°Çí¨ÜôÁ€ê)P¬ƒG×€ÁÅš•Í€yÍ€í Í€)ÿ­ÞÏvr)”Ù].üv;áø¯_Ûõ¿ÿâL\ã€Ä°þkÿžã¿v·QÜ6 ~Çx²_wŒ·O*míP›èÖ¨µª®ÍsÍW­GIŸ‡OšÃ5_@p_—t­÷f¾j“×Âv2p×æÞÌâ'cÜgK®÷ÚŽõÚ0›ó‘ª^4:¿uO’†ÄÐÔùà¼øêF™¯¾óò0{; [G3iÈeÚÏ›14¹)´]±“ü¹Ø¿µ€ŽÑ¯lVwH&Рe…¨ç
+â?äðÜ^Ý k,
+Û Û-ï;‰à4º~z-’Ä…8»wyr#1«üËŽºò`"›ä¥Sñåí”ôJ\Û¨.àG›¾méHET&Õ¨¹â¦uú¢µË“ÃKü—ñ2GŽë‚è pÚ2½/¦®\@!K ©ûë寪‘0¿‡ œ^ª³2³PeËRP'_D[!#¼Ê°Õy_n>Z
+‡ƒ`‰wNŒ%¶‚Ë—H£m rr‘ÛÍN6ò¿×—4ýòû¹Œ|§ññ[b+Ä?bú[úö×[.\Oc¥§퇰 }̬ܗªI…xZ¢!§êýo ßN ‚ô益GÄ×è¾Ý3èã+g²¼ðëŸo¿üÍ=·l‚›ÍÅö©†Ðú´‡~rÓ* ⸔´uù¾°L´ÎÒd?^€J[k‘Ó¶E x¹:~;g“P}”Ñ¥º8W—<=o÷5¿Àíñ]¼x›÷A]"
+Ðj:É;.\hÉl š„ŸÝ 
+bp?EiÓŒ­hoÒ0 v‚qL¹‚ÛRˆ¸ÈŽè‘IÐ[}d·&AÐA ØÓû˜=Å;lñq%ê׸yñÜÆó2(Å?/I ˜ãíIÆ`D»ÎB±lþ*ÄŠn ˆÜ»,°\™ìv˜kŒ³±Mˆ{ºÔinRmÈ«ÌIÔ+&ØÙÉhÈ"1ËÖÁøê|T.„^ &sˆ ‡4Xrl4»œy‹9…0“®œ–†o¤„`Èžo›Ð}æ±Ükiq`†EO&˜o…p1_ØVp˜nÔ@›" JéJep¿ä° ¦¶Î-mÝ:ê˜ÚdÙ™Rð¶Õ=µÁ@"óìY]ÿc´?nº'’7¼~ ¦¼I¦cêc+ ´€៲݅@ŠÕ ¨t¤Þ¥ìJ %ç„ÐKH& wLŒŸZ éÐv¢ÉŠ:U"è ªt@Ž/æЈ/j}1bùKáf̲ÀZ =—tÇéÇ«#˜%v‚$È/òë`€0
+²]]«›QÕM¯Ø ;äíºF+qRŸÒÊ,ÇöeÝA˜VðDå_@nsí ôrìÄSf)GøƒÇÉ3OÙD,ç”_ü1‘6&„ùHA§Ò‰;÷yÒ
+"âB=LÜÓUpqt
+íJ¦2ŒÅ±ß½§õÎð×n‘¦$â‹
+ŽQl%Tžž( ù¶u¤ì½gÕÓË G›|Ž¤É Õaõ|wá¨]º‡åÑ„ÄtÈwâ©•îIPÝßó#Øm d±Þ¦k3…f£ø[—}˜
+eˆn/òê2˜y4΋Á½¿@Ï,þM FХ͙ézLÿÒC€ i0l¸#ˆ6¥ öu³)EÝI5xõ ÈÝ… )Š¦&‰eÍ->ùƒbquàU*ct
+tHð?Ï0»ÈTÙÿ4·H uó9#Ù2Lð…úÜJ~NáRñ9LMýäó딬ÍLøÉÈ^ã,è®=”`m(¸Æšóç®;DøbÁ+
+øìÿT\Q|£„”@ÌA0Ÿ½%^‘ ‡’!uÃÃÎ#“?úš—¢ï‡"Ç…ty¼4%Eadls}3iöU&† ”ëŸNï¯ÓIT­õy\ Si]7#¦¿&Ô„ D‰ ÊÎÕpžŸ;h_ô€/ɉqλ
++·yÐ÷Ëps5¶ ü,ó¾žÁð…É|ʘ'ß 2IÌ[µMÌ) çÂü5u2¹±Çë|®Ìo7O *]wô=kùŽŠ™+Þ/Eg+JšÑ«É/ „b»ìpÖ`úsdÌV«îÃ/Üx“UM’ˆ8ìP¢¬:˜ãƒÔÍ)`zJ«‘yáîD›j;cRÒͱ øŠS’Qg\0xI+ZñÂ$²v+v€á“¶¡žsߦLËž)%,éÚæ‹ÃŸ2 ±™’&á5ˆ²AêÞJJѪòV?E€é]¦DqÎá±:dMè(§„FAz‡xÞKXÈV“¬Ï«Õ{t-‚jËÕ–’!½-ä™X?¹Š–syÝFü N^õ)Žñ:='ŠzÖñÈÍh’·:Ï9p§¡µåÍ´ü*¼€” 1FU&»Á¥mFÖKIýúã‰+œ‚`ûuç‚Y’Uî9 ŽcÉw&oh¢Î/ËÍQlQy±6“¥FÌÜ}ÃE2`„ì &òpCùîfبÒõœíÁ͉
+¦¶Ž”û1S-ER~n¬÷Ï=Éme¶
+f0ŒûíŽwb$“Ñ­x™7»c°I!oë|†À.¯ƒß]€ádqª†c\—Ñð¶
+ "ÏTq@ÐßC–¯Ìèa7>ª‡ân>gÌóº……“‹6¾´†2t 93ZIIW³á2ÄP²V©m¥D l»«\Œ3™Ù|¯¼½%ƒGï.5¸F°‹‘gøt²ž
+ÌZnEß·"-7KͤQá~Ó_*
+)<B[ ±þë ÓÄïjr¾‚BFÅ6³?{0¦,ßÎz #ÃmØé‹-¶§•SSeHüGœG´2Ùo¶Û¶—5vD MBýÆ#‰{‘×8%ä]œ,Ǻø"6ï)Þjî„HD;¢UÛÚBé^‹L§²ç/7‘Cñðב«ƒa‰XJ_1)oмU„ô“àœ¸ŸÂÚòNk!Û+à>™}ž’òΣûH†¾@1íe'x)Ä@dêo7Ù~8µôFEkª|¶¼
+‚ŠLQn»mÿ»ò8„ ¥ª  %ǯ ´ó4ÿö"ù3æmÕ˜@²œèòÝ]M«@»˜¥I9åÊå DõDŠÕBOy¨!®¦Ý‹&0q €QÍ£Ì 2A¸g]ºÙþK6É\¼ƒžx~Å’CY\âà]ß¼ iñU!OŸÄfJ;¼ÕÞ˜„R¸xÛ—¾iIл» ÆF¦¸sx ºÍ¡ˆlóÛ ¸r6(µW«Ÿ3bÇá‘~.NÙòš7›õÿFL– iÚ„ˆeúG€
+H‰Œ—Mr\9„O ;è]A‚ ¬=˾EGÌJ}ÿí|x«Û¥Wr„-»œÅ ‘™œ«õþùÇèþX6bÊlüüüû£Ö×TµÖÛ*Ì\cy3“O þˆ®m­6›KAÀ›ñçàKÄØ­…dèr¾6›öÏ¿>.Ų`ÙÆîÔ-d5o¶×™œLÇÐàƒ iÓú4}CtD¨éš~ƒ¨Ä”{u]ï–émÆfú„¼\j=‚ó¬èRåsÒ8ë \{«õðÑ?»
+qYÖZSÛë¬.K§×Ý™&aÖ7Ä:ûЪ˜xt>à‹¶øÙŠ%$T$"6ˆÛXS§d!{¾ø¬Éš2B†ÍÕ—ŒÚJ{‡ÞÜuCæ\1z“‘ý­­g†&MÃ7hÉ’¹¤Ç î2ÞÈ_»Ù¤ÒnwiÆé\ƒÅ†}þú¸õ{Zh›2>ÿLq¯Ý}­°Ÿ‚®úD^~Ž ò_o@]TfŸ³‡\Ây† lˆÓ¯à?¨2õ/ˆXR[ç(ö¸wƈ֟vá[ki¿,p„Ý9AAÏå²Î>6d¸Ìá°¶ÕY²N¶Ìærvºº5¹ÒPzÌXS×N“7Œ vnÈèÖÕ»ñ½B Ì Ý«ÃHvf2>í¹SgDÂÑ‚¢rWsXÁ‡íu`-]æ»17¤Q¹¬EÖ¹ p݃>!h s
+Be(޶ΜwÔ†J¥%^Ô.¢!!ÎÞ5‚´ASŽ=oʳ!’Uî–ƒ¿kŒðò6|EAסÐÌcAR_Ø>þsnßU7Å„£4f{Ô2ðŠE¦®:1ÌC¡‰G'5n¹LeNw‡Á$ž1­©Ù©0×cÅ‘ãpVÉfR@?bÑDpéJÙ´Ög!@n6ž3Žprbiâß1_GEL1•3 YPa4ýV¹r¨¿ö…ÕT+u5ªŠ7¹©ÝÑQ4 í—ÖêÞct‘¦!]·zL·5'öI¯{3¥y>8,ïYƒ²¦UAb?ìkîs§S¿4 :êVL?"‰öØVÕòO„ejÜLBY^M—^;á^ø¯&Ñj§†”pÕä6in4¢¬•‚®½Ñ ¤6šNVPq º3útRÚŠúHn~ò¸ Æ®Ú|Þ ›„‹Þœ­OnAŸô’âKòÜ'ê; Â^øa"ÑÊùO
+ú^¾п£ÒŸÿýèŸÿIäxà®Ø2±áHÿoŠü÷ÍÎL0~Äô7ÐÉ&¨I±pê`Ìä
+D2Fê-ÔbÏÌLhœõÿ3ajÊ×Qvô¦1©±×Ìí’Åd8'cNÆ–d ó+I·ïÿ![!´³ ‰ˆ
+GÚ©=i ®â†¹ŽÐFfAÀ÷Ê™ÍѹËDøW*ðIœá“ݹFÊõ•à§#P}däÏÑ ;È
+´p†˜Ì0ËÞúƒ‡XdðlWrí[fLµ`ô éY×^o€™Vš‰gkÏ+$Š—q çV¯ $/5jFÙ.°°Ö.g
+‰Áa¡ÓzRðÿFªõûe'ap‰8ë<kZö€èœg«) ¥¢'·Óÿ€u=6y°Àᩧ H ’R¿½/“†ËÑ㓸eXl_
+Ï}æƒ\$Ç!,øˆŒ“OÏ$À¶#ž¦=jl“CC€Š}‘¢LNf>»ö7þºHê\“ýõñD‚Âêˆ7©g{(†ß ÷9óo˜¯LÎ8=¡ÙرÝ1ˆTÝHOXEsVpŸf]¤I)x)éÏøÚ—H}á!;¢Ä)YÊûéÚºfðß3ÝZøJš
+OÎÍa† ÇÑÏ*¤ÚDÈ ÏqI†òGI$¹êØÊWëN^¸)riæñ\)eÃLrM.€üµÖˆwó„ÁCÎV<V òØ,PÀQHÄÜQ.Ä3ƒ.ñ¡Ôi2à)e £Ô`"
+‚Ì…&û+r¨áú^Û|îôÒñŒ@ËSˆJÅŽ‡Î¡0›ÂwAêÿ²Ìnø4R†ûä”5-I7’$ÖI’ö+¶}Ãä©ŽL@qé–eà…ÖéÿÓ~
+zÙíÂà^0Ôò¥6åç˜ßÞ˜ï6ûh†˜kØYòë †
+ǯϞ's¨$a›XÏ™ê%³í«ˆ |­¸[yŠØû”X 빞svwHžlì)á"Ž
+a//IcQzÂãùëBtpî#`Ø ‡ ÀÁ.hm¹þCyx2Ò†÷\t9ɹìRâWHŒz‘3¿Ÿ‡±ÃTê®!äÎv,gKØq$Q±ó
+êÓIP ¶3¼Ë8Ëç
+9üu)Ê›óHQΉӆÖÒg¾¤ËS2Ñcl³ù¶ãÚæ˜%Œ7AÊõŸpE‰,‘oš—
+µÛ¥{A¤è!^— Ǥ˜Y‚\kãJÈÌÛ(û»5ýɯô^öyÀkΉæÿÌœÄT*%NçQ&Ê4±õ‘9òŒ@´\ˆ`"ƒMZtï ü&.)XHœP 0‡²Ê6y.×[ÞÜ%Œ•ß@®f¹”¸²ro3™ªÃŽ·sžtžåF¹)Ú|õ úÜ´±QÈyq•è 1ôøž)ªëŒÉÚ9gà-ñwdÇ8‡»x(+\½äŽvïFécÛ©¦·OAL»ñº¢²S-˵²‚¬B_¯5oj¾|Ò‡_6‹v©7»}·A~C¸$ŸÆæ7v+ë×vQ…«LÀ<xþVÑí:û[Ö•Iéþ è¥—Û~Yóc?ßA !aìZ‚§3=ß68n%2Exy!þȬŠÈ• Áz>*Ęrûª~8,³ˆbHeÄ/!êG˜˜G1h\;µ”µâªŠÃíŠY7ñ‰‹vΡç¹é¥©x‰B4g'Pb¼b`ÚÆf•à´r‡àô¸ªa¹ó$6ˆbpÆHŠ2Ï9PƒF²‰3²,‘€—¶'%H_ËXùRâWá§ê¯î瘜ø¶‡øš‚>J;ðS§†`mï·Ëÿ8;X•Îô[ÙgEŒT—¥Ø뜃Ga¾È_\5 ¬â±aÙ¿¦£´J‰r/tÄó–¶×t¡bLåA Ò³¥†Peå
+Ü•Ç5<|#¯~¹Žg çðuPâÂ|J¤–&§™¢ý)MØ_ŽÕ¥£qÁ«=GÿYü§4rlãålí8%¤Z¾WÂïA¶AîKÂùÇEXÂ&'=‚, @f0OGž\ÓVR‹ û5ëRBÓMy·_9«©¨³“Šøé4иZì(
+€Ðb3gJÉ¿.Ô[»¹ÀûòÂüÓ¼š­Z?Ôä¸
+ýlzÑÏ8 €€üöp &–zÀ4æç
+Xþ„lÍä^$Ãí¦QodldVžOnZôèÐ4iµDMyŸñãæ: Ìö®Å:··G(§äúFeÉ *Wü$gŠ`ìÇ 8zi8ª=ÈY 2B™héÆÂjMÁö¶¥{Ž(ôÃö¼ŒKˆ¹mýí{œ®§ ñ.¥è±Æª4¾@õˆ(ݯXöàÕ47“š²sAú•á€¢Õ)Š€$¥Z9•ì}íú{APL˜Ë(ãØ×éÞ
+iâ–©?i ã»ù 1Ïú Esà
+O–F4w!’™5Huø“§>i‰d|ã²<·ü!DîòáÌÆïÿ|*T™ˆ6°sºFêpqÏëôç¤ùf®©6>ÜoLµíR6
+V;ðXN‘Ji»@ûÆŽ ÁÉuùZ©% Žc—ë%f— t×Ô ^¢¦k:u¡$Ò`±œ‚-Š*
+8@µâùåÙ­¡H$ùù$uâ¨ÉJ!x¤lùUÖ6“:ùã_‚‡ÑŸ"ðÓ|¼‹aSMtâE~iæØØ ª y:›#Å ?ýE£Ë§“3 ¨jmì$­øŒ‹º‘ÑÕÂR«V›ë­hxGö†ùrŘaÝpãtQj­KNÈN¬h|(û¥(9t+«k,ùþZÚ¤ÑÀÄæ6E ‚˜h)ô›öÄ$ðùØ7!Üb[±œî‡šs8oMlLÚÕ%h‹f­–‚ZÞj.ú¡t”äåÄm»ñÚ Cý?ûý½\™‰²Òœ{s@½ø/b@†þù´=¸TQÌžtB0`@„ùꮦÊ:y¦$ù„ ­*= ]•ån&nnN8¦-iÇX,ØNñNµÏigÃL7‘¨v‹±Ð1
+\Üõø¹¼–m* ‡ žþb£¸û‘RiHèÄ~ÑGj/€Ö]¯7]Âì·ùÜ&ñ”ñÁ~†Þ˜âŘ"zÖX¸.H¿#²Xžíª¨ßD#˜i/ßÏiÀ©„Šó·°4sÒ׉` •ž ]±ßö¬m‡/~SC
+æÅ2‚ÐÇš´øÇ…¬÷HC g±@öÌ Xeƒ©ùºŒ¶œjq&¢Ê‚2oñÓÌüªW©Q†¥Æ#ÔѾÞõJ˜$ÙÇ,ø»Éž€LJyµØÄM¯ò©Ž±6‘H¼øM„Y(ÄI•A¬B^Ä\ºŸB÷É ¾ƒ¥í™)…= @D#…G÷é üŒ:íäCÎN%Å«ÕC0w5io­ÜKS§‡Yf¥+»=#‘´• zs ­tlüMòáÓcÀ.Ù‡dènËÛòVÖWñb¼ŸH—âµèr\Å ðHæ§~ŽØLâÑ×iÄʇÝDïÂÇh}aÊ<!Sf.
+¡
+TÂבڎnßµ¤†“?à”õ@ }˜‘ ¤p¤€¥…M™±•aË©n–Òú:²„èÚ©R"“Ôå˜/|m¢x°=_ê8´óâÙi%Ä\ÿúPÝk3Z¤µÿ´ßgéò]²¹ ìÊò,ø!ˆC/„
+Â{cæèž{{ 83†ô’¢?]cz¹„¡“à=âu²i“ŽiÙ!Ì'ìD·öô)ŠI¥ö°Lˆ”<†òÕ³â'w†p•Àâ Òò•‚¤ŠÅcàV¾©>6f¸h…˜,6¥Ãð˜1v‚9¸vŸ+&47’“…‡¯£ÄG3›\ÓC;„7€Ý)ø$Å„©´k…š´ èÛAL5dQßR=¬†ÏÄ 0`)ÜËÅ8Æ<ULn¸'Øw³ÇL(÷6„þò>b ªÀ÷{2 oÁETù{æ™’
+ßlÖ‹Ï;–hÊnüa Ò~cæ,‰@NãPÞ)Ù³µž­¨&®y¥ޡГ(oÏ1çøæ®Ì[²7ÎP"ÚpJ1QÍ]Ãìà±ÅÜ­F5¡IU9¶wÌwPÁ€éd‹­è5“éœWòÒ4P€&Ê›^Ë•E¾´öüd’Á°
+GÒ}™]ûDÛJ1nŒLµ›F…+ê!œ×±B<Ì{Ód™–²Ráå#VfdŸÁý;
+ì,Ãÿ*ܵa±†r©»E¿"Ÿ/Yì~s~œèëìÏ„É$œªHÅ‚di“Ÿ—_°õ>+<‡ã+Å7ªÈ¡T^=ŒÔ!ÞÉϘØÆJ]¾<Ö•X‘‚îë µ4&¯9„þ—[Ë®ÿ
+9#“OÔ釛Æ×Î&9lýÚ¬%0‚­L‡à–fÓ¬m!®ÙÇ3È_¦r1äûèýkYÌÏ
+ÓÎÐfœ±–³ ]P  8Á¤N ä <ÖdÀÖ¸@¤Á!ˆÂh¢D)›ï¤8Â×ÙA ìÆù¯³Y€öP‹I4RÀ‰¦_Jï‡ÂU oø!=éYìÄe:tÖzñ¢Å:nXVuœe4›Ä ÞÂË:&þ SÀ õ. ‘.Š:ƳÕOÉt[s6åÄÄ?‰D÷¡ ¯j+)Ô JŽ˜¦0òèóy>¦Øf¢¨Ã{Ld[a‰üm0jš.$;aÓKÉ¥2¥˜4‰2ê<¢¾¾Dnô£ïS)\ž˜qPWÎÅÁNÊIš—£'¡&5žîæt»é£:ÁÔP{j ç´ýÂÉí F ±ñN¦ôȘr³Ù!ÉÚ¦³UêLl6€|DrÛÜÞftç *SsâéÄá²úËâñôBj  ìJ;‡õLž…\î©u’kÏtµƒF¸º[S
+‹ûŽù%úŠáaGw•?ìÙõ«Î„¼ Þ»¤ÔóKe§’DwZ&j5%žÚ/éÀw¢=Yë˜[/€ÌŸü«¹ýÂÔãµISøLWõk6NèWÚ}õTŽ?Jõ#ß="#Nšé X¨‰+‡øÎÑ-…sgntOÊ8¡‹qA„|òsÜPWÐÐúœQò~šk° n¢÷ùéR€ ü69ÒŸOM…<Õ4}°FŒ ¬`ñÀ4-FÒ|§±]s¥ä±ÙâUøN¯ÞB ŠKÒpÍ·ê
+Zкtù´wÚ®ºúD èHS®Ç¾µ%n &Äy`œÊn|öÙ|õBjs¸™Í•VÝ(Âmx@ȹúl’µ”pð’Ùoç6ªŽ½g¢nãò}Ó§Ê Ue3§Zê– «ì×’gàw(ŽKŒ¢ ÄÁ=ǧrÂ’JaIãuS8,ÄåÏ:lMê±ÌjOMa5sQçZâÕ”cQrÖÔÅ‹bM<2ÝIS*júVø©6õ;OÈá!Iž':P\ƒÛ-ßì¸ Eí=çfOë¼öÅ[VSK
+e>|ü–5y[Ö±úù.ï†è}c®°bxˆåÕL” ÃTÜÒÝÙÚ.j(:úûñÀ°¬q†oE9¹›7&^Gv( jQ5D—Nü üß½AdH%e ÓRÄû¾B8Ÿ‡)üÜ
+¼‡\À¾»†Þ…ùïZç’rJ¯¾`Ùè&›`Äm(B‘1/þEß' ¾Ae1ä­Ÿ/–:@›vˆ—át05B4Ê:žCúý“ošAÈmiBN­ > ¯m~Í?@ÈÌ: з¢SÕfðgÙ$¿Šw*ÏU¾Cl+’X—¼æ0ÏëôS)ªÊôŽWžåDÍ&¾Ë˜;þ÷Ü1Êx³¥·¢rÁ@²m8&.–Œ7q4)æºÝd¤¾‰^ƒ›©3x ÷ÃÄPô^hõ
+ǧïh——*$.þr<×yó ¼·èkp‡x2 B*ÁÜÕĶ‚“Õ×ÁüïՃТU½äçVo"@£7*Š©Ëi >x¯Su]‡ùUŹ:u<ß*=ú_çU¦ÛÒ)‘ås"Ÿ³ ßã ðUn›´¦Ø…lb¬¤[òüK$ܦúrWƒR,ìR´ðVãÆiyq"O÷­^EB dýæXÎJ Èã=KÌHÂ$,dþÕJpËŽ¿ %ðQUÑÃwŠ Q™ŤyÅ·7£H± Γi°­¨6 *öè ”¼4ªØÝú¿§0Lu—A:Ž¯´š©Ï"ÎfLÛá¿NÕG-ù.çÇ0
+JJ+n󓊆(bb§½?œÙ\ªÞAX•uHI±>·úöâ×2!iH½a±Æ*Oâîµ*çÒcu¹ (b¦ ÐØ:£=ëVØð%Ó-„Z?á43¦X+Íøµ·›=,ú¯5}
+âàIÚ «qò~ÞîSÐK þ|R§]Î8-2ÜpÃÈ7Õ<`.gZ½SÍ™Ãî“O@§:½ïöæðr‹'™‰.ÑퟂN¥ü·­J~ýGHαÒ2¥=§ü „Ê$IÿÜ€0‘ˆ|‰k4ðm„1FiCØF…¸úha„:*P6
+EÌ¡º+~ ê
+ˆ7‘•ªŸ†sA
+|jµ”ña{ÞÔÍ2,^ëÌCˆMT«eéWº[çuxÁ5"£3…j†ªâ9HJÙôó"‚³ªÒØV¨)õäšÍArórŽ9¸PÏÈød¿wÕq0qÞ˜ìkù°+&±u±×ŒÜ€ó Oä$ɘ Áë6…žºna/=ò¶Ì
+Ýý—gÙ¦w¹3뉎åAÉ)Øtµ§k-¾Xoᘃ Üv¢ô£¡?*¯Æí1ÒGi„ï«ö& Ü@8Ö:.Í»“jÇ#1hgÒ½i44[R áœS ²½Ý
+‘ÑÅÖçr³‡]î=Ü•Oaë×Û"N¢b[w' 4ïÀ¨å£Ì¿wúÏãVô5Ý¥–Ì$ˆ¯_‰˜,ÈOAbþ̤aɨQúús‚t¨1óÙ7i 2•`BÓzåÛ^AÔ ÁysѸDçjƒ~ÿ0½íj-»*â‹`I˜Ôס#ÉmÌ‘™ì(ÓÊÚpðä»Ùüý‰#ý…yVH=µI·§Ïºäˆ¶‡0Í·–­Fü›íœ=óC±wQa,ÁX*0ÊámÄÄWl}òU°Ã£ ÷¡XÉt'ð‡åïVOÖÖö:’u‰.e€Á#eò8qCðAyñLˆm…0#D±q·LÄÖdõxŸçK¥ÇÄ r…±ã Ô3e‰iÃÆÛN‰0㋪›ƒ&,Ø1”œq¯+Ó>è{±Ó 󵥩7„%ÑñÊ:c‹9¼*–CéèRÛ
+éyI2SPj eÐÜÛ7$”™[Ï©îÞ„—@åS¶­+Œ…†À ̦*šät|+‹ÆÁÑ»ÿè ËŠå÷:™¼¥lÂï,b!L¤*=Ú "ÄqSÁ’(ãçèÒÊ€”¥B59 Å´ê#‹i0¥› ¬D³B «B@ð LíÔ+Û{͈ÀÓ¸i¤@kÝt¹F0! ÙŸK£]³Êë¤ód)ÜMZ4Ñ?Ö<Œ'œC·Ö˜ ÂA¨NÑ™j \¦„0ë[å ÍN%B›P ³­æö:0ŠŒÊëZüêÏ@ð9ºÀÍì0)‹çÿ/“$9wŸ@wÐ Ài-/}¯Ú÷ßúKø­êbÅ“­ˆ.¡8€‰Ä‚ýÙ DЮTàYW¢`ŽW÷e„5lh)!CôÑL}>%E>ÙÂ<`$3d ’Ñ5ÇE&´Ñt™ƒKÑWMè‹«&ï1áa©P®qGàG‚îÊVDîX/Œi¸äw…¤¨LÁ”皗 Êà;4ꇰS'«PB`%vô‡âRß߉³$3UýâV‡ áï|™94àÂOl[Ï 7˜ÜKè1?ø醈£ƒalÆzÆ<q,#5îæ¿&jÞx\;v¦pF!Ü !Ä™•ƒJ—(»Õgʹ`LõÿQòD€ÐñÅ05™Ý畺Þ%s³ÂÆÈ{ó‚H1  S7Â|áÉ4Ìê¸2ÏmšàW²_›Å¢â;û ›™[Á
+Í `ë,¢ÕË$¸âå¬@þŒÂšE_„§z«bÉ5Ë ¬¼|S÷æÇL$…^yMçu¾é<% M¤)åê¾Å&ßJQ•!ÈÙb+ȳu™9ÛL‚y±#Lé$JØ+á(h—¼y ÷îýƒQÚvêç¿~1XZ°Ÿ3˜¯G?ÄüuMåÖµ=URBÁësÊb®ÔÈiW‹@ïÜx§È cT~‚áKÑ.©t€qª»Æ&å.$°wðm^Â|$)B±¯§"¼ÙCýó"8›ŒE:[ã¬#Ú’VüEb…B¾n§‚„øáúì7ç¿æ5{U‚43#ô©¹à3#Ú–7ÚçÕ2gK/á ˜)‚£ÍKHI&©n2!–ñÐþ~¥¡N@oÃ_O¼Á ážiÈYgjŠPÜn¾|‚Äñ^LÔ‡(µ²ÓïfèVÔ†šÜB§ÉP+ôò"Š¤Ä=$|qï¡Îqq* PØgLŸþ5\ëâZÝoegí IÄ;¡]¼7Zê;*yí$‡ÄDØaQËíRâ[U½u6?®cÜ’içLÝK„¾ Osô½]Fÿ
+rÖ(@Û-JÚn9Óç ¬Kƒ‰”â—b+4)¦)
+5={ÙÀá^zGlp‡’è<rÌQºBƒK(“+¾[ñ³™(‡pææ¼$êˆã®—ßÊ:#A«r_ŸÖ©zªFt¨ŸSËC•Ï—¢{)!϶b§©\ƒÑšÞ¾"?’žñ
+IBHèIÎa)î)]D ÔÍÆøšù<Ô«½PS@ –æ[eQÉ$)/‘Ç3ÑÏÕ®V‘NÂ(ëAŸí0ÌAº¡™î9†óÅ çÄ!ÝÆ^Â#P ñöiAx=œ!éã·sÛŽTSìt™—¯›|è8U~óP‡{× +Q(Ški_ÚSRq…):1ýl!
+K­2¾Ñcp†3Ÿ(ÿòÀ µU"¡bÕYwŒœ#73Z›<Ä’Vtï¢`[)ÂN!¬Dþ£•¤Pu˜t &xïž#]ΤÀ·|3ä*¡Ée5ÎcãAÎ+,ÞÒš°ÎïâœyRÖ[vÔàÉ[¯)sü!ƒ¾Säû:Ð/7Þñ'~dÞ
+ÿØ‚¸
+nƒØ÷$4náC–&ÄAjpÄŽ¥­g¤T€VÝ°~+ùÆû® ¯Eò¥ê#µ”õ¾>qh• bn›É{0U8Y„®,AÐF±ÇssùXت­Haôjîðû:pŸHNïÆ~+M?jÏŸECнE@ß {|[GÎØbŒ5àV@½Æ•T¸œã§  ƒ—rTUhÕÿ§Ž‚eiœyœePÚ±–ûús+ÆGÄyJ@–Üg[ùRâ[•&JãRïëàF°1pøsbˆ|Hv¢„)²Þ¹l¬ò‡!ýýãV#ÍÈi‚•¿¼ˆª$×Úí÷&j'ìd¤O¹2é¢Wà,a¡!‡çUêŠê…™ç>Rf‰{ƒXžO”EXÄ
+mu_n4n€ÃwÞð¯<2jñYÑsL^×K˜lN1eµŸ·Xщ#¨‘bp\b!€â[q¹$I+GÉ` è'ë
+r~qb¬=oÏK´†@Â}ê‘©KZZ‡ó+én(Bt!P9±å­Ñ¨Y^—¢p½lN¡ä8˜w0¹ÜK\tù<qœ‰¶ðr3y”¡üxg@fBÔ1÷ónDum®ØäaËr¿?̦Ð2ÀüHxMòúób2¯–ôó ˆ_1ï@%Z ÙvW;&¬ÀÝ"±Ë@Íì²i‹ñ}äþ0«
+>
+ì1¶3#q´*<ö'JŒ©BÚc#`ohrz¢+àÁG?%ò[R[^Ň—§W_m¶T’•DÈzÆ%çÞÕ¹© ž5©Š¢bD[„BÔGû*ŸÐDd¦z)*Zç)Á~ pòÐ!È*¾EübÀa;9ï¡Ø(·äëpCF1Á’>,ž¦üTNj½”0)Ø
+´‡ZÆ`·ÌÚE»Ôþ]Ý@&¾šŸx*¶Ã>ÅàC , öyǯ(€¢Ÿ¢h‹ÙíÍ’êµÈM`5¥M±ev;íøR$±xR~øNeçN¯m=@–ke†ÌúãIê•&Ž RÎg¨³ð¬V'÷ ÿ(Ú8’Éaùíh,)¡±$ëuÔ7ÐÜ ÿ¤”;ä‹AyzÕÐo™Lë‡$Ìà¾V‡ûRlÙ†Çæ´dv¾ƒ´hpÙ»Úc€°ˆ
+¢Ø,æñ§ ÷ã>r§¸z'àm»Œ#ÉOW]n…îCzüîÉêú)èzõ?Ý)®Žñdá°±ÜÏ–Y+uˆ£üêï ËÚâ v8‚œ9 þ¤·ÌA _2áTÈ]L·”ó§®MÁ%qM[ã~ØOA_
+ðù“*y1gÅ ÉíÁó"ªå,T•3¸¸ï˜ß˜/>û·ÆJ1žc¦t3ã2Üž#?¼–Ø2šá¢Zuò·0 T!òcÐí8†®°O<gÔÇ;]@ß*p9í&¼nÛLbéçHƒc]ë"±;„‘hz~“°_!Ø|Ó‚iÏ TR&R"1=ÈÂð3$fNwC
+k ¥×KiŠµ ¥R­ á‘Cò»Ýž ¶´bÿ;I“Y>³éƒ! "¨ ‚ ·ÂePªæcЦtB(YNç+˜"ÞˆíÊù¥ZЪîä H’µ£™hC,a‰Zk,AØ3î"m(Â’½:·ù‰£xT5ÛÓwðʈ³„R<™®“m:„?甫_îû·O âi#
+"\ñò•Ud ÿòÏ4†ÃDhŠ“È!;dÛ!]¢;OýéžÉµPî_ÿºa°NxÈĈbçÌg”³H,2£ü
+)+,•×Q¬v’deÒ+{ËÖ3sHõ¶U·ïdƵC@†‡W±¥Šôx^üôßÎÜÔ©$¸ 9›¨ãpylÈÜ3Š±’/¡<6 p›êË"„ƒHU„‡½ªx z[1¹ãõU$Ê“¬ER˜ÎJ•w’§uRÌ ;IµøTåjBæƒèg%ÃQ¦Y·s”Ê…a£° ‹×šÜŒ‡×Lþ”íŒê0ã»weŒA|Y5Hrm7.G÷:©ã~%{m¾ï/Þ mˆÛ‚já]$×ÙãÙ_ý¯ã¤"’Q‹G‘@(ÞòöñnÂ΃ÓVÍ‹ö ‚HòD ê¯£þŸÁØ6ä׿…ÄíA¦Ä#Ø<ô0… )ÖDý°ˆÚ&ËwC ä¢nXˆ5–
+ƒ` åmÄ óAÍí ‹V¡(“•à¬3ÅÔB±‘?
+6QRã³:+g 1ùÐp¯„N,-]3¬+ÖøÐàðÄ8Rê8Ök_4¢H_¯#î`v !‹3Z0‚­ÚOŠ%¢)°T—`³¥ »?îa4æ\<•ÏQ\̦º°âQp††É`ײ§(Jy‹ïžÜ7“¿5†'×NEç¾>Ç=}¥S(&…û1’¿á‡Íp\
+ýƒÉ¢O½Öà$ªüò{Š±PSTZr=,ߊ£øF¤²eã¸DL>à é7x× ˜âÑ ö£‚¯nfÊÄo ðæÖ ¢È„6ÇÑ»ÌDÀ½8Ò ìB†Údz
+6Ë'vp,Vù!?}"]‰±ùí‹* |R2Ÿ ô{6þüPN›P€“夣h
+£ŸmA På 'Ð&R‹Sl¡S¢?ô›Ý YÇQhc°ŽÅEˆ2-Q‚bc¢ÜË&•>Í–fòä\,
+¤…Çïò½éò@ØF ¯ýlUSM|Š¿9©?:2™7É܇”¤Ë>„«àílu©ôÙÓÕ ³-ñ·ß<¶Øg=þ„¾I_à­vvÖKÁÈÏúÐR@xÕ5©5l™R‘ü7eêþ$†‡ìQ–ò&X‰µÈÅ!¥1¨øüF´I†3ù×:ÎQ¸¹Q¥‚%Šy7)ˆPß1v–1‘Ìh­±F?1Í!2+(ȸ0/°B˜¡ŠaL®‡€°³I)újÖä°6‚WïÄ1ìnë–©$ÓÚ­çû åuZW­Þ¿ÒY|B(ïn9&p +ïNÜÏ!°š&¶Çvs&ù½ú:ˆi ³Aä¶.ÏÞ¬ÒÀyÝæ½xý#ñ‘Œ‚”V.-ØG5˜‰P0Ñ”¯b¡øóN÷~mˆ¢,c…¥:#Á} +<´[@À³Ö\8‡d“Bqëô:J­fDðô‡u¾6¹l ²3ç£pˆ _uûL
+ãá+,$f  ÅžëUÌûDð/²Y­Ì]V_÷˜öí§s'#¾—×>LŽ®Ëº×§6bQ¶ßÛ ï5®F…[‹£0Ä k“üþ—ñrÉ®$·è
+zµ‚>$ø9¶‡^‡GåýO}ƒ²-)ßqºK‚˜ü
+1—Äzy‡U \3”ÐñÍ}^JØ'O²DóýùÒ÷"Ü©è
+óS¢gæ×ÅÉÑ£rˆ†1yËw`kÜ*è>ǯvhÝOZÂ4` 4 ”Ë0‰`€³ŸtC¶Q½ó¾5Jx)z
+¥GNXOɨSÆpBåUu ­Á†ñ)N‡ö,}ÝR$Ï·ÜÝ‚\Ú¥X°¡c¥ ù¡þ0ëÜÃPýVƒŠÇƒÄqn(–¿@ ±ÏüÒ99{Ì»áÏ(
+ÜB;ÿ‡LÄ €ÍeE¨á¯‚½/߰Ƙė+,ÁIÏ:â]qŠÆýÜuDL8 +D@š¹>”0C>ŠZÂÿï?ê¯êƒög¡Eu?¨pˆ‰WšýúŠªœH1uïKÑ)YòSÉS 1àšá'Ž»¢¤˜’$íòI)+sCŠ-êG“k:œï» ÃÀÉ9#lD ÂgÔlÜ’¡Œ Á/_êŠ,穳z†Eá5e8ãX
+Í€«UQHìÆä—|§Áä­ÒáŒõ-©u`?»)ñÞO„LǸhÕ+b蘊é—ë²åžJJ[Ú-!¼ m[^vKº€¸‰‘<ó{SZ|ªWV¥aÚa`Šèz`G餶»ŽnÇ~-„Yx1d»~Uç{‰lA, Ú`~òS?Š0sÉòîq;Ü zM”›1~( ·[Û³^`K@ZMfÿÁLEÊ ;€¾Þ1™ë~èc5³ˆtÖñc,%žŠÓeÇÜ`²ˆ¾•žMŠ²‚T$¤”ôØ»þI¸Íeý€2=š‹0¡h «
+µEy±}Þ&V)ÿ'Oa¢jëʧL¾d>eÐ9'ªP£ÅÔ²Úß“'C…[×bWàÞ,rÀÞàK™Ø§uDÖ Õ,=˜]UE¿}‡Pâ81û ½8ÄI¦Ú^|  â…ýÜù-øcã§ÑÛŸsÊ×ÇTBÛ§‡Oh­‘M2ð ÅòåÉfÆÂohuZö]'²`lO(3ÒòèpäëÞ/%«®[ÚÔ“{-IѼàè&9Ã?à$%Kæ9i¾•pÆßÐ^‹¤ù¡„‹!ºpXÊ®é½!ÒtpWèúõ¯°`1(*•úYôû­H3Îlk
+ÐÉzáüxŸwOàWz$”„1Üôuÿ‹¶Xd³zÈJBôCãÉ–1 P>ƒçæ!~ÃE<é^ÁA¤‚¢ñÝ›[†nxÞù©Ó¢ú…PHº‘ Nòg¤œç[Z‹O-Xx£Ä-\*ZáHu”¬¢”·1ù©Å肉èKìgÓ¤,<aÂp¡ÍØ¡á€PìFdŽ×H3&ÔÀ:Mxý³"=˜×‡@pœO«t/a¿qÁ ZáÈüg®˜]Ý*ÜŸScÈÖiXœ.Fþ0³¸½…ÈÚçŽOqyX™2Yl†vÖØA£ßEà»e#÷ªZyÅÜ/ÝÀ¬ÁÌ·A=N
+1ï1ãŠ3·ÔLñ– Ž¥á(+>Fƒ›¢
+na·¤O™ 5ÒX<-Éæs9ÀMS¦»æµè"ˆÅn•öBsœ?T`œ5\|è:•¯¬¦nu:¸#þaô&gCªƒžŸbx™ð¸'Shf8†…‹Ã¬KûÅJW² BÚ9î%È!‰€ãxì¦OægÕM3øCŠ__]CD´A’À¥xPÞ‰=.±ÿ;Lý?(;ñ
+Y`ôÎÖÂ]i¶8”ͺMº${KèôA³Ðs) D µˆ’ÃÀem€W<·C+p†-ãÙH¦¨œøG[®,BéN:[gl&öµ e$ÂÙ«ú»¸£„èÊ´;¡âKÉù”2ÛšNñi¬*]œï§ÂâPŠ¢¹J8Yz]6Ûfy>…ô(‘¦´«¯!cŠ"ѦGVÐ2xoÁ“*ÁÙ'+ .½p4Šb 6Ãa&센¡î˜à#ç1HÇ×Z|ʇ„
+0éÒÖÈž’‰…¸RÃ
+eè+‚ÂEÑþQ"7ÃÔ—xU<õ?ÞŠ˜›Ž•Æ¶cžsr®‚ç
+H‰”—Mrd7„OÐwЬ ’
+5G›CDln(GϘæsÕ9+Z˜ùuem½·Á Ý¢ ÞòEsZ!–Eok„ù#P¸¬%ÝšnÌþroÓM÷)‹D\‘¬.<BšÙ˜Ýà ’w“1‚.Ȝˆj‘ºÈ‡/ñaCe’¿:gÈ0—Þë2<qš4oä¸SR¹œ7Ùà¶xšžb®eY„©ãSµ4ÒBÞ׊^¡T2Ç}ž»Ø\ùì!'3SÈÿèÆ «”zM9þ”ºz´;uÖ㜢ÚEÚЕ·» ±D…âäªõX”Œæ# ¡Ñf³Ùúã×–á3ðd—‚Ûi½ÖäôUÇ·®ëZ•l“o)[ë±:C;%Š“ºOsP‘?‘X½«ÉyAv!ÿ:åª4­8¥¾Ï(Ñ¥S„ðÖf_‹!°HÅ¡£ŒOŒߟïäRÉPׂpQkÑÀȆô)jü?úð½t¥‰g=)ÞÅè)J²Ú¹w™\Pǘû54);ç«5¡}µ µ'#¿¯²w¢1ƒÞ¢Çõí×ÿšùö™Ýæ¼íµ?ÿÜõÎ÷Üë1.¿a~}ùt¥Å
+º†¾ö»ª_ R”c?²;æ~ÿEmôŸèy–ƒøMâÛ ›p«Óš¦Z±þè%7Ñþ#)]¹Díeܘ&
+rì¨Ûø`z`¹ávqX{ÏÆà*ÚêQ° *ÇLÁ»ñÛ{‡Ia á½@h}y‰‰ïcrJ¡Tó‚ §\f Ùø-:*€jÝ@*\JÃ#¡_Ÿ9!†È”žÛÒh\uÞ Þ9ó~sá
+ˆ˜¤ÖÌ“œH]´Ôê‹éÒÅÉšw:ÙYë¢1]6„ŸÀa«EEr&vv‚S•Ÿ?n ý@!ã …ù”¶‘]@Þ®bZ‘00³e_o·ò?·Øð"ú%Uö²‰pMƒ@ŸŽu^Â9²Í„œ@™)r¾úɹl2¤¡ßé_*£Z†TOzV˜Ä‚@ë‘’¦:OœÅ‹‘s2Uq(FŠ ²í)G‰
+ÐÀz Æè%Ì°!Df ‚’ÜA*”®tG´¾­aÛ<Å;æiO\œó£þŹ8Çt(cChzCmR'n gæ>ÔË99»'ÍIBî_„Q„ÔìÔÀI/ߣv'µd ”3N½ù ª Í‹‘èüîaIAàµÌ/C\¯œndž,x&¦N¨Ï‘ ¨eÂcᇑòM¢XÃYÝLJ°'y“‚ô¤•lF2²™);‘ZžBßc Ôq5†ÉbÎö1i–ÐXƵ.Cƒ§éÆQ_¾6U˜8fîXãMƒ2U™Ù‘<Ç"1ÍÂnG7!´}z”yùðdYƒüðY¼r¼Ýˆù3WŸPiTˆ=zñ  sakÕ9èˆÁ&ºòâ´$d,›«ï 9…©$Öç#Ôÿ3eA&S£i;|¼µ\qN8Loõç-h½üÙ¯ÖŒ¹åuÑ-Ѹæ·AOá>¾s§ºúóYÏzt]ÝHMŒÖÅðЯ[ÐÓ] ñžáJãü˜ Ý…{~ß·@wŽf$]\[÷yµ}/ey}|'ßWYÞþ“PaIêÜ!Ý–-rK6ÇII•æt­œøxŠ}Q’PxL4Îëb$Vºˆ½Ãø7mí‹}Âq¹ûíQ
+¡qFl=Œj·}åÎ …¦ÉcëDm`]²®›Š;vqBadkÌH…"<–Ì’¯ÎA\X•0më¼
+o¦¹ïPù ÁÃŒiÙÙ@r5L+Co>Ba9øÔ÷rû†[H³"Mê>…~UT+”|8àâr³HbˆÎG×u\2ŠÚžP/y7%¯jÎÜ,;Ñö}NOeCܪGñ†˜)ìç$+~¹)Ù,{Gü³»í„ÂÐ-VV,ŒV'CüÊNÈÔ«šó™’‹ËT
+”> :šíì8/§ð€0‡é‰#Ð’‰[­««^$7´ryo
+À€œìålòlR¡‡¿íò6ÂèÇ¡Ož:FÛ3d]ýŽ)Ò3%ø±!ã„úÌ8™â4îü½ÆÛ o=ëü ÿIÚWŠXòˆõà¿ßi4[Yæ~nüÂÅF›êÒ7_@>qúOè¿mú§¦øÎŽG‘í²…uiäg o>6ýç&@ 1¿íXš]Mç ­Ù¥ðÈéå™{$eµ^à³¥Ñ]Åÿx>ÚcåÆ´­¤¼SA-ò]æ7·]Hšõ½Éåâ¸k™r½*µ´.³”:äR¸ješYèT`R4ê˜t›I \¼Ž¡o6U0—Â[h6/~CÍÛÚeC4gš€Câ„Rdƒö Umƒ¤»Ža)‘õ(ªd¹ox„Íßß„ëô a%ÁhЩZÖ‡ìGyÓ±·ÒL²§Ûd'“ZаÔb£õ·=€2x7åå×ÓI
+€ÎÃÊtŒKoø¹Ï^C0§äAÓcò+7iÁ¡QVÝù`HCO¬Ê£…bÀ‚³—f¸tÐJ f}ñ
+(« –Œ$]ç äOvE®qñå9P¯æˆöÇm5#?räž™ÍÕ"65=]÷ðª Í ßÕ¡’î‹&Y»ûÈÄd^iIšð¤†;èêéÊÃpZÜ£Õ“zÃwÐ töƒuàÛ•ÆP*UÍ Oêt(%啽Åk©bo£‡á>TðD:}+!.G¤Ã&¦éifõCf-g†@ÅoØ¢”zbmCÐ R†÷ðÛ Fb.]k÷
+âŒNFyœqÎóRzyÝJï@T
+©¡ç¹2iA8Éte§¡ù5›Ð-—&„¿q8ó÷£>c`±ô8’Òïyrä_@~ÆŸ·z}Ü™è¼3Åؼêy¹¥ÜK£V$4Ñ0±-ê³ÍR1î »t¹ÆŽÐ‘¬åZém¥ý¤¥fñF-%†>¬ÛðM®L\y–ùE×_Ë ¤B=éÇë9äúç3›PgaâÿV‚¼dòëUº;ÎGÍÚ@æ`)ãdvQ˜8Y»´¿1‰§µ˜õ‘îCâ^þb¼Ü‘¤Jb(º‚ÞCÙctäÿcN€‰;+  ÌÙÿœ›)½¦ªóE@@ªüIº÷HÎFoSV8þ‡1ÐCgsòû, À0Õ”‹­ƒ_ä‰rU¹_5¸“% /(ÎH¾Ü.é»N©!ª2”b#Øä$ߘwÁK°Ev» ù„µ‡F,IBK‡ÃÄ©G¦‹4!.%âç4YÒûÛVˆ!UŒ55ᆈŸe3VYBJôÑ‹]ê`­$4ìpDÈB
+ê>ö褠 û‚ñ2 Ð`q5!Ü^Â]Ò®ÖùÎ$¥1­éYvÓÛÙ¶rB3*¯Ì~Ñ·£˜Ð¸ÂµNPE‰(’ÝŠ=ñ’7ÀLJ(>#nߤÃD2˜ÏXU2 Ã!
+: :³f;j7ôaA±0€Íö€ðédü+¢¡,¥Ù›§ )ülxË‘ ¢<
+=I
+7øØê5ˆy‘BBª­B;Kcñ
+±uøa‡ |J¤1\‡llB=[£Ü—£`»é ÒJfè5[%c²«ìJ7¯)°V׿Ý+—çÙ‚R/WãÆ0PlË@ µdq
+BÛt]<àðÞ!­Ü;¥Ü1taöÚ
+pd: »§3n DüXØ“Ü*-ÖyHš;¯n!RåêôþÉ‹÷óñXŒ¸$Õ‚T¥CLît„ßô®¦l¶Ù14S]ŠÝy™n·RWšÇlR˜”«loCO€_”ALW:y ´½öìTTtGnE7N3Š´š óuIQaÑÁæ<ù£Þ/ðX@ /öá%¢Õ––í  Æ…„ådÊUTöÒÄÜK¦ÚAù±·é*™ÑI°Û–\€E5­Fât]eJE™Àš v7Ϥ÷©õ^ˆñËQá'}—:”AïO•Ùà)å´CD÷
+“FÄD[h&±u²8‹YÔ#°.AªºÐŒh IþáO,åÕ©‹ =t³ ‰vÂ5”JN¢a9`Á<+‰©íH;„0œ¡e̽¥\’óÔñ"ŒOM\b¼Ã+N‡1ØVi}%q>ÇÅ¢ù• ÉBhwz åÂÅÅCCs®e— äàv\”ÖÒX€Áؾ?µ3£ššßB‚
+R`¼C:Ð
+8S( °8i?3rG5>òŒS]¨¨Œ œÇ†j<ˆr6©%Õ*¾
+ó%Ÿ„ GR$$h‚‚QEÈgi@¢[ÀaàeÐý£ —펃îáØE¦ÃE¡éóÍs!o|‚ª‰wXÈ_(ZžÓ@kv¼ã´Õä¹âf‘Æäf)Ê»à.’Oú×*gT¨ó’ü
+ºeî;N¨9éÅŒ Ú—NµJiÓœŸM¼¬/;W:t ¡ÂÁáÊèK¿ˆŸ›@ÑsxÏ ©1¶Þ†q¸”° H½wŸô¾ì;AÌ&˜º©!ƒwö+žK>Gz„…|€Â€††Ö}o½]—5»7ûò- ÝÏeÓ… ,éõ†k¥lM˜Aó¡îvè„ä§m({ Z!䉶ã0nC “÷\!Öž‹MÈšq»̈ß1“z ES0ªhƺ”€º ]¢Í¡«Ñ‡WiÑiÚÍq牽àgÙ9‰yðá Ôœ—ús:±°­J°Ô«cH¦<Yt"˜Ý(ÖéºÕš“µbØ)ä€2¸0¸Ç3òj”ég¯bº‡Âo£F÷Uê`±’¬Œ©ð¤0?äQï(Û°[ŠI•Àv¹ÚšÎ‚×iÚð­XSŒ8%Q
+ô
+9éLà S¢?Þþúç-<þþ÷í¯ÿÞâã뛦Üw¹JQŠ²’ÓêUVÁšxó_;†5ǤeÆr”× R’j(ò
+~ýtA™UhN‚áäÅ/ÁŽÕÚ²A\Y¯¤²ûFƒŸ€Ñ•Ó†ðUºBÛ¦ A’ÒM‹§<¼ŠÚÉzÚåAàR×*¡Ùµ2“äaùËþFÄ#Ö†öÔ¬¿ö\ƒ^ÓÁÇñ’—#䦤:ô±žñ(
+Ìì¡e1î
+²¦½&°\€° A{²-aE†X!+ZSšEjHÅ.ûù2Š¥d­å˹~Re¨Ì`i?\F>6D¦Ì²!„êF»ädÃ… ü¸’Ŧ$äÇ>gH x¦Ýùè>‹\Y­§„í@"+!†ÉîÃ|±tvÙµõƒÝ= 6qb\fš˜$Y©fÉÁ.L£i&5he"*D¿óßgÆD\œlo´ÎgÆ'!!Ƶ-Ä ®•Œßd€Â/à¢<ýÜ·K§ÉX„Ù¶’4'x»ô}‡M hjªÒ΂È,i%+#cÆ›Q¤Ö B{‰Õ¡‘£„j6eײÛyÇÔ¹HJ½Ê溣ï`”t
+ú@El*n åƒa¦#ï>ĵi¶ë†”¤M“ÝÓ†àX*Z8í+ Z3;0$¾ä›N´“0˜6H£¶v™6Œz<Z+—1ÎL\™ý ÖN˜MŽÑÍØX^)(.îaöà Q™ÙîÒ0™·èºe0Ê Á`äTàLÂ1cç Ö$LaìEr…*£Å¦•#Ä¡û„óF6€B…ÎQ—ù£ÂìRR~­¾¦BŠ¿BQ´ûÔšæµ:òŽþ×HhjÝäM™¦K.Ã0Í%G“ö‹BÅ“þ]I%ºÀdEÝpšH`࣪½WáoÈ'vÌûpr*´ê2{%cÙgñ)¬ÍƒÌÍ
+OBdѫs#ZbOQTs
+l¤ªŽ3T‹ºQÎÊÚABèG›3’1[ßÆ!·Œ•÷ORƦ2ŒpH2HkÌ+­ŒÄŽ’S![Ú¼'}††Ê%=þ˜ÛŸNáô&r ð6ÑWÈeV¿6ãÃ$©Í‰Êèo›røѪ=Šì0$Ë;0Þí†êMEPºT„=»h!Á6ùéÓg’¦F÷ìÆ|e'™´²!èâÅo6û
+‰îeb@³ô¨p”…
+m顪²Ã´=y–»Pw›rmWÍÞð
+„1X~ätþu$ ކݥ°V颸 àÁëæ{· Ö.LELØzÕÜ­ôŠ4mM¼Et¯ñ·¨¯c¿ I/ñWMs*•ÑhDãsL_6ÉU7¤†a¢3ùlü”¡¬1Z*¤´1Æ’O~¬eíe¨Ýj+Ë&q²wmx§Äœ?Gf¤„ý†0M<+»UQ1›z²¥–Mdôgç¿\LýTæ ²Ð©a<†ädA ,™·cwQ©½ö•ãõr‘€éœ!™:5¬ /Ô¢p^Î+W™Yym•œ M
+Ïy¢iˆ$Ù5å›X:Þ®±À?"/x¹òõ3Ì–:÷©¯xÍ`Áj-$ÝftV~i0ræ
+Í¥©»ö`Éï-Çuò9gÉ@W7<Pa4¢hh»BŠ»hê'e%DŽopÑ´U\âzéŽü;–Ì,
+ë%ðƒ£¦˜ÏQU+ÊdOÊBa4@íÏè.ÄIŽ¶
+ÕùðFý{DÿáÒÁë¸r!qWŒ<:÷(|*t±‘BˆõÓ=îúz‡¢ÆäºB%9’øçFù{ƒ¤w7]ô˜5‰ÆGƒŒ"ÑÀQ)¨ Zš³J\ìGZL|HYf“Pª™†²ƒye•Ý‘”"åÚßÑÞµ&z˜SæAOÊÔŸdö9#,·<›µ©d-ì` hjè:WÌ—aè8ÏέHã¥}„”}ÃÊѵå2Ÿ^^ñ!åÌy2/kOb_a¼^>H1ªj8&W„Qɼ¿£èÉS ø‰öÞOÇri2
+ÔÎõá;é©0£•±UƒÛ°óJžÂX«)á
+>kG±
+ÙIÔÑöΠt
+OkÚY0J–6ƒ¥¼@è
+âR^›oƒ<Æp@WSMQ¦·˜ß¹™júÇøËò¾ìç0T0ò‘æS¥Ó‰«Žˆ~dÔ1ºÓóËÿì¹Èmy:Ë‚Ã ©§SñËþÀ¨óÑT3‚ÇÕ”}SÍ$㇢Š|S €¯cRO®¦ú†ñ:Pov„MË£½ ú¾}__Ðe–?þ÷ƒñŸÈ,6€ÿƒq;AÑMÄí÷¡Jؽ†~u´ ø¸ŽÅrŒ. A‰p‰!H8“=ç=Éü2Š¥Õæï} DaùgX´™ŽîÁú„#[t— U:–¤…ÐîœÂZWÆi<”Š:c‡ ²PÕTä ÿAÍ1©ÖU¸©‰2 ûúÚ v…A~·h_@ ´²Pÿ,v¹ !~Q6Y¾ÄVÞ-Ç£'t¾ð'°hßõ锃åNpX°ï‘]Ç×0¡«±v¼m‹êAm´ºqq¨vÓ $­ÕåZï}ÛHó}µY
+2Ì8iŠòi:ýÅ~ádË<Wõ±Œ³~¤‹Ú0ÌØçȃÑ^Ì\yšÀ?O²¤+ì¡ŸŸØÈR ³f6ôÙ«ü4•³°4לlsVùèSM׈‰Ù…~F±,_ÈùGPa)jVaçùšz84iE³]…0õ"ºƒäl¿xž†c«é5⬃ã)4n¶ùQi÷ƒ„BŒþ9}ßDéòd"N±5ED!`¶˜»2γÌí¯¦2 :©Ïóp2R
+Û–ÕT\3É6ÐzÛü`4ps˜†Ü [ÒÂ×F7¨%M]퓃ˆ§EžŸlÿp'¡©7D¬J°Ô†dæV2*¯­@ :Ž2™ì!2ÝÑvK™–0N[ 4Eô^ŸmüE^ŒL‹ñÉéúõ
+c›™¤ŒþØDЃÀ†Hð\4Js@&vQ–Ôw­Žq˜w+ÓeϹ/ƒ’”váÞ\ü°†éÁÏQ¦ÂÀ"ƒÁgÛU8U67•·ý˜xçÁæ"ÛÓ®j¬*ÉŸ#¿‰V’éèU¯NöYˆ
+¯DMm:s…G¡¤IŽÖ l¼\Ô°N² I®žŽ{h®¼Pnz ­ÉFw ñ”’ó…4oß$~§6°ŸQ¾†9âU½„2!-xÚjª ÄÊ æˆ;±¯¹ƒþ««_ïˆï2§ufBd9‘D¤êãÖè¶f…g”vØ- ™kØgÊ[Aèf€LdelÚ1sYÄÈlÄ´8t²ZªªÁzp/þ9Èâ!¡Ï'g±„¬£†'Ô ¡<QH¬©SJ »N#ÿèž(½ì┃å!*8 kØ·iñ4rÖÂÃ|ÿ"šM‡fSßwceÕ#dƒ1¨÷eß%œP`GWÛ²Ð<Üž™—ŠÙÔ¡­7À(>CÔU8¤•o¾€ÌPU„€Äž›þ<„ÿ R01T1”‚ö•åKÀ[|Úž×(“ð}Xf,ð¢Õ ñ2Ôv °eI®ŠPbV6êÎâŸ1ÌA@ZŒwÁyÔ¼?]›€;<¸uC±_X\§@èSÍÁâ΄æpò,PmC
+^_;Iód]”ò(ÖdfΉcì VÏb„Üd•Ù•±!èHaS?Æie¨Šv%Kl7 f/Å xŠõõû«.sMi’Jÿa_\Å»¹G³¦œÀpJÖ­8d®,£7»±—óolUÔøçh^ä
+?µs°Mz[IÖM8…3¸Ê^UqZ¨G–êœn2Jä1ú$ZÜ9))ñÛ­ŠGã¢Ä
+49®
+“c6¤Ñòcn"Æb¼ÑÐ|r$#ƒkÔ´>Ob£?26¹b#}²‰uf?ÿ çd a¼§•>ß_ÈúpL\9/ê=Z¦cŒ¦¨k33Þ„O&àÎÇkâÙ}úAiãÉG–‰™«¤oƒ—Bu jÐeÁÞ]ÌÍÙB> áŠz1v­Aô¨R¶#Ö" ^G_XüÖ
+O n-½Ÿs ¤ )Â))Œ wÀxUPüAâÄ-vÕePÅcê!L—l”/ÓŽ¾®« *»2$Þ»3Éèi:7ýq³¶GCj„ùHßUÂH¶œ´]öŽŠývAw}ÓˆIËÂ1Iï`¾Å†_—½Â^\Ð,Š‹Û&z JªA%e;>6¢,GœôGmBf‡l´ÉðVY´~×,BÉ“B§Ñ8äªxÛ´š õu™´Ø ¨M;â¡V8@©;»ŠÕVz@âóÓ9B"Æl)’#Y%©F°W]:$)u±'3-æ¸c+®ÏÁv*ãµn¡±Ìž@S0Eµg!“Ãg:Õ+²<wª„9:ä–àû&ÛæŸÓ!;!±’ýð†õ«¸Á²!•êUåL»)ôýcoǹ ÊJ|·Å#ø¶;nâ’;§h¢Z»†$Q²¹üˆù6£?x oÚÛ'©Ø
+Ô‚ÿkÖÜÌæ•xåx?R×·Iâ׃©ã“ø¼Õ‘„o,ØNNÐ/„ÿÒ4 žP³Ñ ê×i.‹oÞNŽ,)†ì/ÂÔÃk¨œÙ?± 5é¬DH‘ÇäÓÙnêhåáUÔ†½ìæðØŒ^¬
+’Ùûˆ!T§8 ?4ëoMÿùJr@ÑL(™â—áÈóïÝ4ȪxÉȺF[y~yv䓧Äe– QàQðjÂŒ?…šåŒ¬Š÷ Ðè„T`*‘cúdg‹±ÃÅrå2ï0;ÛäB NE°ÝÝ<îøv‰¢S«õw7ŒL¼-'b&¼sQ’ï°—7Æ
+÷=Ò±´§_†ú.–,áh¢ÐƃÈ9­¿‹%£á4Ⱦt?91ÐŒvÕÄ·#Ý…t¹Ñ¶"¬aæ¢q¨žH§Í
+Æ«Ð`¼!Ù+,óØ‘]êÁÒ!tfH1t°ÆK°.6¦j °Û&—ØÄ8Rz1HÒ×¥º&ºø? qä’¤˜¯<3ªüˆW¢¸º=o˜rE/ÆNY¬­qÞ@õYÆú%Uu¬ú°7²ä‰LdObe¨+zÑPX!Ÿ¤“è@þ]ƒ!  ¡ÎA®í©·CR3WÕ=.È€ÁQÝJ]À(p©J «„È)Oaoù=ŒLÌ'FØ0ýð1ù3šŸCq@ß¿YµambÕ £X¬Šch218]
+]ÙÆ$³^ݸ~ŸV"S…:°º#{¥¾ZxIWCXÔéOG`剀dWl€ò³œú7¤c#)Çìö©H …‰±î¡ÜSXlYs@ßj2š8þlfS!'ãQš–åúØT#x›YïéÄ™
+Âv›ƒÒò„©Ð0H›j=ˆlºO¼ã•émÞ_bçùIéÐŒKÜEùÇüð–%_·Aiàú>¼¥ƒ€ ¨Qƒ•f[›¹­ïôm  óº¹@¥óÄÁÏûéYÆ [îû¤JBm‘-OÑ%%µ\Nd öß"ãu+ñ$ÞOÇ`Ô¨rk«Y³Án&óº»3”7ãl‡~¾Al5KFd1æñ¤)ÞÄ>ïFL5«c€lt虂ÔûU„ÆJ©øßtO)w PgÀÓX·d³ù#_{³@çݯ`Ý"¾æp.Q”UÀDIÙ›{;7PKlä^ñ^Ï«Â ©DÇôõ1fpÊSäib…ÂC8ž¾X‰§÷JÇ5Ýi„˜&ˆûE€bZÈöeÃبþx‘>±IÞ_¥ók)¬ì© >j¦còf`)1á=z&¿îŒNòšè3†ˆQÍãe÷œnŒÑPK 6%åµÝ?‡’‰`«<=’[!ÅÿKÑV´`"å=qe«íÈ13€ —¥M'dzƒFð@8ª¡å mUˆQ† ˆRÝbFŠyEñSZ'Á3V´s«e2Xµº\èõbò+²š³» õb"÷mÄ>…üWÈŠ®§sÂlä ¬AµÙ! 1™X[þò±Æ ÝJªL²Wá$‚Ô¾¾¶"_qÎ(sXq¸>®†5¬v º0aæÜ*ÌWV¡Qoسæ˜Ý­² _îBxç‚aùM[Ñ_Sˆ¯º&—Õúã~îúþÍ’š[ÚpFjÒüqrË‘‰iMQ<ñ©#‡ö‚±*®g"âc@z¼sÒf—Õš3_ómtv{ˤ—Ë}¸e!2Z‘`²áá«iÄÚÊøfY
+Mó…êše šURåöS-×2¼’éÚfYgØJή[V»öÕžžöÚé¹eŒ
+
+ŒˆR²¹;wú³>†K%/°tÙS8±LÈ¿v¦œ@éSµ¡73«¶GŠ$Þ{ˆ1]’:g«§ƒhgᇬ.6÷’Å™pñQoc5Ö8VFùˆixeÉ«ÖW.eÅU÷ˤlQ»ØNuTˆ ËÄ&93òý›Æ®þ—ù™¢"K{›_|7>µ/8©T{9R%¿ "ÔÔ»Fn,ª:Ž !·^²N0í⪲ p4ªš™ö_Á(;âˆÚ+àj"c÷ÆË7²c‰¢+àhË rŒÌ4…–Ù®V Èc›Ú¿Î}Yÿ³*D4œ¢rŠ¸Ž`5_†¿%|5¨D€äÆ
+™Õ‹ZiQ‘.S%Ÿ!†"&v²™úIq^iîÊ?¾Î
+ø:p(%kÕ¼dæ6±Ðt¯ÆVPuÏâ­¾ Uá®ë±f˜"˜É¶ƒcú§îª™‘bÝGÏë4¹T)–—p
+ßÁiß k­+ðCe’²OsÖcÂœ8ÌCIàÆ8žø±ô»e0p.‡t‚Åöñv2Ò«]g‰x-]zdHŒ56Ü–áÉ'4 ½wŸÀÓÙ Â’d¯ô‰Á„md±ƒE¦G 0 æö>xÇ ’¬•wóP$‚†`¸îg!ó UeÏ×¢Ï(…#±Öfê/ëàñÄOø¼Á®XÆs8õ&ùá39î`;¹öÜv˧Éï&ÙÞÐî¥Û›:ìì„âs ž5vrŒÍ•lŠ#ír³µCÉn9i”i‚€òÝ:(Û¶†8PxÎÍ;‘¹“!ǽ›fO”Gß`<™Éf\Q‡ž˜9ÚîÌdÔµÚ%´²§$ ™¿ †±/@¢nÇÆNä¯1 á˜ÄøaÀY¶lÒIryEf߶ì`8™ÅNÒ"@Œ]3ÄÆáp5Ið<)J¥¬‘c»"AÆ=žù—MùfiΣíO½u‡¯¤{y.Èr–(áQ
+gQœ‹Uz¢m ƒ¯G&˜dÐYv²…肳ØJCƒ
+Ð/ÑK–’’"ÓgÆÉüfHøõÉJ_Tœü™²qôäW ËȹëÐÛM£ŒØAx§G‰eÊ^ï܇OÍCîg¥¼™ÛÎ4EOÝ]0‡¦ÉC‰×ãá·Šê•YòJYŸ7EÌ ÏEa¡ã…¨¸¢A €qIB]Læ%E>wØ6ßÒM†Í
+ ÊŒðRD1PH‡¢ŸÇ¢ú±.ÖYăæëT“%©•w–
+Xœ!‘ •“©‚æ#óhJ½‘Sl³¦ É93D ÓÛŒëÙÆè«8QÂQ²Ör’¯Ø)+aèíÝ2r‘Bcª÷a&¶]Féj’;¢ml›Ñ”np¨#v2` ³-Í]h;Á&e™s_‡©Hü0Â9Á³"â4Þ¿Ñq±oòáp9YOÂ[Oîû—Ÿ
+yä üNOî›ÚÝhº|ñÑ}›]
+Õ$m[~^Ü·aÖÖLi½QŽî›’Á,5™Ç
+ñL#]\v*iRjþ“l»»ïSÅöKJ¦sâkÑ‹aÓ‘™p/7µ§ƒyÂCj¾ýæXvÊg C,òÉD°vçî¬d+oÞ[E³G¶2+Œ?ÒêQy4ͨ7cöÖ‚ ¡•Ý™K¥´ã:SO*«ÃÅ‘y}žFµáÿ2^&ÉqÝ@=îàt`ÖÞêÞJ÷ßú%RýQ¹q„èj| †¬— «?ø½ãŠÆVÛªÎ/5æ˜A ˆÔÒ!HVÍsZòÌ,ÌÖÖXpå¿.ƒ©Ó)ÔwÛ$nÏDˆ¤§úZAUn¯ÐºéŸK
+©‚˜œœA¿¶^ßE«x¹D|ÈB‰Ý3X$£¥‚çë˜Â©`Œ ÷ ÏÂÏElÒyV ¬™v!\Ã/aÁ‚$ž¥ÇÓóeÖA ŒÙD-i-MÙ‘o„ì’sf“Y86ò'c qÌæÇJàfÚ?ͪȌ£¯1‘N
+¿¢!»,vÁ
+³™W¢Œ1°&ÚV$¨|»îwSVÚ¹š‹„1c1ÁDok×Èà o.f[ܾÉI³{T Þà%ÊÀ2,?µTÍ4ÞÍ06ÛHº’^b«Öj9¼ÂeP"gI±[Ôkc­3„]ÈÚr⬵(ôU`[Ðf¹Ž ‹GôŒEw_¡åzÉø%¦_
+«×˜ä™þîøÛ†ç?ÕreÉÀZ ÂÝÛj‰c“«%…£Ðm‡o‘ÌrSKù1úÝ‹lÞWá™u>ìü˘G‚4tkGP·Ä,ÇÚ¶³Œc_ncéïýóÓ9ùZŸ5ô³,¦óŒ"¥%»S|-¤{ÆXDwÆ<€Ž€,™
+({2γ5û˜³êò èòNÚ\±yÎã꼬EkþbØ^«~ÃY7 Ã~°ß¨bZkò<Ç åðQ£²ÍÅ;Ðá\EºµÛo@‡GáäV+
+Tm £–¤OÿòVðt_•û #E
+„ÂÔ_ è¸JŠÄ@CÝÖ<ÜL‘ûBï}°Î½dûØù.¶ ÏåŽú{¶rqê‹çÉ¢ÈyqüÁsgˆÁsVÐÁsgÐÁsº²ô)v ¬És<œ0¥ß¥p:Hw µÔ$ÛEè÷¥½–þŒrFžàòØ-õYí¬©(øÎ>WáyNxùÆÜ
+ûxƒìé´©
+«9‰d¤ /™ÍÀT÷m¸N¤£3h.h9Ï&ÒÑ`0! É´‘.0ù,u?TôÆtþÅâhjŽä6°=˜ŽM¹ÊD7Eð:9™.×—È;ŠF‚…>¿Í Ç:ù9ƒ˜ä›–¶V—sâÑù­ïÅ>ö­6JYJxiý*! Ì!lRÐœ
+OóVœ‘G$Ðy…´B­á¢"i†8ø“7ÁBnŽA‘ÀçÐ|#ˆ‰ä2슊٭ó '®ê§Z:t™ÒÃá3„߈…JëÑYûƵLÃ3ë=ØçtnÃgpLùãu”×OÂZI)"íÌ+p†ù«kï›G±ÆµR™ Òö¾‘.»¬ÓW
+¡>–SÐr^÷w«Th¥bla
+;Cø‰aaÇh„¬,ÓN<4SÒ`Ÿƒ9ó®ò
+`d¦AsžéÉÞ ¡wèIT#tr>Ý:š—dPé.¬ÆXCq|ì[A9µ[þð1°3{„D
+sc¾vÎcÕ!¥a‘›AØgØVÐ;cQ™]XÓ×-Æ&¢ta¦sˆŒ­ Àè–Z÷wŒMW“CC
+mÆÎò;Ü4 ƒ.ŒMZOcÇPúõÇLPJ>[ŒM JîKlîÆ&[U}mPs1[åÔRË-¥ØLÆþ²âŸŒ­Ev¸°-Ý[W‡2èí¶8èØA„È
+Dc36ÏeÆI™¶ûaösö3æäk®‹ìK(k4ùZ– ”³ÊþÂ×J$Ú2Hl¾Vc ©4)m—M.V+A°`ǦkÍfP.ùïö)…t²w~pŸóN×D$Ù-5M¾Ñ5AòR2\©o¥{§kBd˜¾TMºVéît 7º¶‚ºÖH°éOÇéºsÃ¥Ž°“®Uîdž£Â&]kXŠW¥R߈~еä¢v†˜ær6]˜Ä)¶lÓ5!Q
+ŽËÇ]«æ0Ø›’3¹ ;às´ášX©•Ø§ÜàZ5§‡iü]½À5A%«Sø[1áZý抮դ¡€XÒþ¡6¸æáøÚÚuåhõ6g š@‹ ×_
+ä‚kŠË.‘Í[êî%È@ùŸ:‘aÄJÛ/[mä‡ÂTÚ’v0‚FwÆRÐz/ .a¡°=f¡²_CË2€Sëôï¬×t0A^[JyoÚcß 2
+ëÅÀ% —“ë¦K²QÑñ¿ý'B¿;¸3Ä°pVÐááΠÃÄéÊR[è’Ec™8^ŽŠŠ-hv1qÁ¥E/º6±DuÅ0õE8láDÔß»ÌAºa‰jCpxJ±ÏÓÏ·Z {Á¿Ù¸$¤çç$+÷~±q•ˆ>gʳðÝÅÁ E­³Ùz¸8…*¦: g.N Ac¿j´‚~­ àÑžúv<§˜Â±œ²‹–‹ÓÈô¨Rñ÷xqqÒÌ+ä‡{»¿»8Bä+î&¹½Ýßí×P¹¢‰¥»âUÅÍ0aµ)Z^¸IF·Óũ䆽¸¸8ÂSôÖ‘§tqq©ýúTæIO—d¶\Ђo9˜.N=
+Œ(ñy‘áâx9³ˆ64ï[0]œÖ Â%&ÂÔÀoÈä¿ŸëÖ½š¬ q9®MÊÁÌ1YÒ*ø} âš•¦÷ðÞx{QS«ærÕU.e*ªGÖ+7¯Ú;«É€Në,¦™
+-e¿ŠÀ
+4iuÙÄ6-Tºgäf“ñ-á=¿-qïd’§~æ´:¿UZWϳ•iàØÊ
+H‰Œ—Ïn¤¹ ÄŸ`ÞÁç¶!R¤DƒÉq®y‚Aròóþùñ?#v«³ »]­?dU±dÖe˜†½ýÙûxØÐ6E»/ó·ß?¤[{L×Ö-L—@ÄÔÆpQsCzk:Fhs™"±,šÎÕ/ˆ?Öä+sž®­úz¬!!Se.Ý aæÍ9£çV@ÂLÕæ³Ö‘9¤y[]{¤Ùz_=!öðán±ºÇÔ{«'NåxªÑùä×m˜åW“k»þ0YÓšû‹·¿6HF£Š‹ë÷ ê|‰Cªõèoï ŠGÌ,õZ¶ÖtAFp«6s± LGŸsC¸B_Á¯^~0ãzË%Þ~þ8hGÄX-ÚjÓ¹ ùpv’&ÔE¿ Ò‡5t[²1‘‡ltÌÛ| áê1¸§® ãŒ6D§®ÍÓeÄÛ o”"µÙëö+wòaÒê8½³„.f²›¯eéÇÒ8@ªùÝU[Ø`ƒWë˜u˜7,ƽ•_
+Ã6Ä¥·e7ï«Á3[­ÉÏþ7.ž½ý=¡ÑÄlÚ§û³÷ˆs®Ö7ל.Á!ç`=  b3”¸zI½Š@Ÿ±6Ä}AÖm7„PÔ€6²zßGOñMºÄ1·;
+ú_Ne¸—¡ÞaüƒbLGtjíâ*N4#Ü7GF:…zMí/ Pƒ?¶¬àüØé+È0þѯ;eùC±N;çÜú ÛMÃåc‰ØÁŠ†áÜÔÃk( mCVÞe
+»_!©ô 1UÛ˜§­¾BÙd-‚ “¯Uj>€Èh¾"]N.&&cf~çÍÒ¨6^>Q¥„ Ôœ·ˆÈ!dÔ$±&ª„yÅg¨¡dh_)9‡ó1kÆ!W^k>2`f—¤¶"/I÷‰WëdØ¢ù(JoHÆñŽËî€N' « èu8pyØPNt¼¹Å`·Ûîñç1*ŧvyàbê»ÊOWÎô*ƒ€+8{•A”úI³Ö ”‚DršÏ;¦L¯Ø43V¶¨AA²ãk݃“eG—+õº®þ:±P¨3<`Ÿßtñ´Ûw0ŸezfügL
+þfÿöÏüûGZÎãz
+©s)ÃýŽ/Ô„,ÁX÷ø ;B†ÝGA ’J%¿þ˜$kÆ Â‡ë?<CžÜó‚d¥r…ú·Al6Ñ;Aä± x
+òÊŠ½˜ôÅ7UÎ üLþ éÛ&=EãÈ@\™jžuV¤Ÿ$Ÿ…Kú¨ðAO•À¤<fgñŒ@È»ÀûmõÂ/8 ”™7§sbàœûTËrw‚éçƒõÈSIbèl¯ÃXš–v7¦”¾ ÇavÉGZúa.Žîc¦ë9
+] Io#àõu]Ü*íkÆíBHEÑ
+œDè£6Âb*ßɘÙgú3ëRJ‘é×$ShétÔ˜¤Œ‹½Î@ûè’ X¿ªÅÅó™÷ò)tÕV_@PQ|‡µ¨#s™¹è%AµÈP¼lÒoæh`ÄqÂZ¥CÀ–1ˆ1ò!@:NíØmnƒ’‡XcàßR'ôóÚT¸»ìªpð²0™LgOAÅrö§/ _/@ÄlìP(F ƒ†—¤Zš¦Ky3s<ç=÷­„ Þ°½•9¢ ˜+zšÔµ È 2F0eí&rd,mè•ŸVZîâ0(e¯“±âÊsQ/hVd\Á7„Ô¨¬‚ÉùRÀ…fl½1ž×é×ìà·|dܧañˆdŽõ2ÝLý™o®s+\wô+ê‡f÷ Õ.F ½›ªé…x7eW«Æ$
+C²-Ò;/ùÐnñ0dE}‡7}«JpEt‰?»k`ÎرsU
+µa^‚ÛÛöÃ^ˆ0&Ž^âì°ya‰J×}¸E ¸‘¨ óŒ›!0M²Bð:˜);ѽ¤2:Ä3ÅÉz ´Ù—çyý¬¯_¿#ÂÛ¤Ò,&@± }<Ê_ )¸ˆß“GÍ[Ñ/Žf—`…Ù Êh!$¢)lH­ÙK@5Ð0ÂA$H¥™ãáX¥ˆ‰éJ‰|9´I†
+a¸M”$±Eõ˜4Â+w¥±Š6±A&FÆ>µ0{â*€¨aó­ˆvÌî#…¿ªÎ¦`·M5%¤fã=rh–fQ£“·Ûkd²ÉöÜzä8,'ž’¤¶|Ò) ™Ñb BÕájÒ\|œzFZ‰R‡YcJwŒcõ™Í Íâ]0õg#iìdôÓˆ¼E¿y‡De‰3y`P©Ò¼¤7l]õXûP²7) ŸòÚé½æm¸tbÉÌX³d iÀZà;·)Ðëñ¯ì_ŠIçC¸ˆöãM£QY6"ÉßDêÊ<MV½Q? »ò%Ûõb–øKðKJЕïë0 YòŠ0â!÷ 
+àpQÉÍy…o™Œiª›Û3ŸáGÆëß”ñRÒè4¤Á£/÷:N
+ªlæ)‰ûÎ>ïEø4,?Ï,íödÆ ’‚)àéÄ”sÞØ©ŒíÓÔjˆ]‘ýx:,Ú¥±
+±¦âr÷Sî‚M6µ¬¶#©€Ÿ¡Ãcd‘ÔájÁa*³‚’ˆ¸ê/n§PH¥w8km—£‰-¤eÏU2 nŠLúðÈžãðþÚe A÷8®«&99rdÄ‹msÁýÚ:¦yªrmù¥tÌ¢â#‘)Û½¢°òH*91ðYƒ¥„‡i
+îÌWIV:tŸ²Ò[põ;óZ¤Ž'6æ³a=GÄ@±ã;1$QDÒ$¤`<$7I}dRµ‰^s|8öC´ÔW!üç¹ ÐT^ÃJžh+ÇÃC*!-4–Ð8riõx 5 qf~hË‚ß»ònx©ÞQ]ô²8Æ£Qà*F O&=‚ÒÒ‘–GE†ï˜ ôr¹•Ò‰ FŒQãKÑ×)âøL÷²Xi°.›Çîv]¾†³QÜЄȘIŽÒªrcô£Èý°µÞë‰ ·HF˜åXH”’‰’|ø2}CÔHò —õÞÊ·Š
+¥ÀŒå’ÿñ"ýÂ+¦ ¥·¢]‚¡è¨Ë:~Þ»
+hoBñ§q(Ö¨ø8~zÜŸ¿É1.¦ÆNr¢ä’¦æë(¸ð°ùõD¨H¶EK¼íô‡ëèV¬¢…ý—P5Çò£¨ºk#d2´†ã÷CKíØlxŠ{+úò"Ü”Õ|)¢[Ž2™Â«“ªi 3Ëþz ê ùãårp60N¢pÜqŒºHZ0ªì˜y:g“HP‡¯ÓÈL &'ŽÌÐÙµâ-ŸÄN"Y)†IŽºÅ:È]ZbáVcJ~¸¼"7IÆ©xŽ±îì“{—Þtp*xjf<ûÊìô•?ðß,Ì'Ç|Ç,°¸ê:´ûsÔ È/䓪ÒK‹"¤]2ÌÌ”á¦H*«zy/¡¥\D¹è"[y( Ioš _ͼrH€Ó•tÌâ¼)Î.I®:5ßD©ngü Lð}ª­ÄÕÌáyŽV»¢ê®
+oÛÃÍø”P
+å‘`¾vS)I‚åÄèžY‡ù„?—ñ¡fÂ`¯­~-- æÏj9É3qwŒiŒß¤QÒÐvƯðuÀûÄØȨ3ÂMÄöŠÙ˜µÌ¨ôH¦è7"^ì5èôŸÇ""†¡G !¯©ƒUA Îêv+¹³Ó[Ñ÷EL" géæ!§GMA4«(³å)mÈmö|÷â’*^.ažJþdéi_-PÚ’äÞƒWçÿœ‡ ˜÷xѶ™…C`¸[’‰­4åF
+ÂÒ§’F–È{‘â-§ÃA«¹7ýµæëC ;
+h³˜Ë+è| ˆ|IXK¤tjŠ´¤DÜFlAEبG ×^»O5¥w(˜í–Ë¥ä¸ ˆ"'ˆ©Œû:hC²þ[4üÄKŽþÀIÓKÒ$Çz°×71bÁ$ùNð*FpAũƉåZD»¦Ô¶K4« sµ3uÐ_cãaQG§SÓ„1p´ZFÎQó(’ìº(A—"t˘0:<Zl¦ãöa}ÙIàZG º—ÐZ:Ékõ#Œ
+ÃÃ<ñ¨ç<Ï¢ŸÕõë7øûªŠ êŽqtiuUòc²qéÀù (áñÑ4Y è‡ÐÞ•ûú¶*”ÐüŽµä†ÀŒ–Ĺì¾RçC}Œÿ8£ÞàŒ¦À;|„l£$.ÕZž,êŽRa‘q;*ÂÇ<þÎHÝß1a+8q
+íRôýZ? r,¹CW_^DCè3Æå7G®CºÕö‰TbÐÞöæ%°A*y°1¼„ÀF~Kàw\ðú?ߊF!@Êv‡t±¥¨,{óuJÛ­SòNÝÿÑóŸœ\‚ÈàŸFÚ¸ø™€G]$ànžÔrK_¦/Wœ
+ÂU2ÿ’&%“[A€–wZN™Ôð¨¬d x]ìî.!Úáê' ûtiq-›íž%uÓ‚ÃùÀê·?îE ) a—“gÑ‹9‹Ž2]¼qztªº_ÑÍq°”âÉ…Ëb0Þ0mˆ7Âè@·1p&f™¤z¥èkçŸ$ž A|=…)Û§e¦Ìª ÃfeÚ ÿ³ÛÆXþ+-ÈY]©Ç\Pca3²ø àê×1VÜž"_‡í°Nà°žá"6pg|d­x)<Q%)…gìSmAï¹ßþ¸ÖÐ9 )~¯îY¿±ÆïÔðaF  T<ŠˆNY¹f*^oUÁò
+Q˜à4k¢6 TÛ‰ÁBH|ii‘FnÀ¬¸öz¸Hˆ¢ÀK°8ëd<Wš¯T[³-{Ïn>ÿÌnz®Ïöá€íÙItNR´GK=}&Y9¥­ ÁCC”|–OxäŠ~Ñ- Ü­‡Ø=û¶Ö¹€à
+³Ìïà}Hš ÁÐ5QSK͆({õÊo62O×lÞHùÓÁí3Ày1~XWF>Ñ®³’!ºùtäÓyžTT××Ó%”b‘8£Ž X8tïè§!ŸLŽÃ›ÂpÑå3uü ÄHI––'"×ç/Ú‚Hy¹û&ùEi°;û(ü<[RVæ==÷±0qð
+·¶ó±xñ'l30]a™ås… µT¯-«Cg¨n•Ç[ÏbÏ.Ž{/?ï‚¢‘PÅ4‹—Ôqtëc¯"“c nÆi?Wé®@,‰% ènÖ3´œí|C¬õŒžû+h¶ÛW°vEÁw§Ý†®NÕ⽟#ŠGŒY;Ë6Ð –SNg¨h¥ÇF­VÁ7…_Èn[<€ÊðclâZ"”"[ÒLªH³zT!Èü2— fnÁËe}š m«ÃÒ4œr¼­ÓNž.†—'%¾±³7£
+¶.}9‡‡y¶Á’¼ÿTÎ¥¯ág HÂÕ/«ÍR²©úZò
+D—vØýÓN ÄNð©æm7”
+¡ç®Ú< )(Š‰¡½ñIdà0:ƒ¹ÓÁó;Š& gë4_NˆÞ@‚©~Nå}ÎÓ*ìÖœ‹DÕ YÄpçi™9”HŠ0¶oƒ,¾0@07œU™‚¹:…d+¥à&h.„‰ ~  ç]D‰7s
+œ ¿MP„Š›‚))•`†¹EÞz<o¨pɸÖ«ÈlöÍl_Äw¦,ÚEî9šd5vy’ŒseÛë”7@*WågËK²ß§HÉL4C,©2›õUÓEóî5.eÂãžÈ7cý{6MJM¦Ló=šÆ¸”óe›onÌzÊÖLˆ"PìòÒÛ|£SX[ŠötÀi™{RÌjQ
+˜ C†Ã{Bflý‚Àñ°Ÿ2ëÈZ'$‘Ù"
+òC±ÆtX 
+s¿ÝÑŸZ¹^þéC+Õ…”µäÈ·%„vã­ÔŒ•  ¯‹÷v?Åmž$¶r'Z€«¢¡LõÁ¹2Ða]¸RöÌÎRŽmÅà>CÅbh´…‹Ÿ3wÅêeÕF)P«â˜´Öý
+ý«…õ,ž$¨òäÀ¯¨tškH…r‘$r‰m1†œïîpe˜ŒKJì¸xÇÊ…¥KUD§ ¤'ÍTÓ‘òöP]×NE37!PZÑt–m'R?ÿÍöw”:Nlö²Uýì$—'$)I¶Û/uË”“?Ö
+ÃOÒ=@†ýQb‰p*F¡~ô4@ó4µ8)›õ;æýFp³/øjHœÑŸÛÎói`%¨æâ†:;Ç_Ï×S?¼Å%~¨]¾¥³Öo1Fmg0`ÈØÚõ;IæU‰ ­Ë@!*P“}X¤;^™0>ì£þ{ ÿð¨^ñ;ÈtÜ<$>Ž 0´5×lÛI£R „’.2Ž5ãVPH½yH~ŒvQ{¶ËöœÍº331ûf 7(®{ç ÉßÈc.‡pó'Èð€ÔRt„Öm™{÷‚\8LS¼O‰I¡óMLwyÉ1­ªvrÒ ]ô° ;ñ_5ýIl©z¹ ½±§‡T&…`bKÎ"ÇÕ4S’^/SÄ»˜d¦½]<$ÃŽHPÕžúK[ÞMd :Y|¶Mä±L¤:Mä²f1"}ÄlÆΨÉËIÊ­Í÷›‰<fú4‘|™g–XT›aŒÎŸL…Ä â‘žÙßa/ /ÖK¶‰Þ
+Á”{n7 ¨¢të}5M$ýƒØUèÇ6‘‚dœ L yBshÆw0§<@§dk™~vŸfÛ@R©f¬ør3Z¼æ|¢|áb #ểîi?V¨ˆ°åf a²ë{»|‡²3ê½Ë€™þQ+T[b°kéâ5Z¶åÙ8=Ó?ª3üMšþñœ>Ã?j(BCƒ–óâEReÈ1önH±;*Ófø.)g 5”&R3 ÒoÄ8Á¿Ò[FaŽjÀñ+0Ñ£uío‚eœö5Æ#“W5ž.ÍB ØžÝwMôý1 ¡¤8éÀ3à ˜Ã’!ŸBpèô YŒ"årÊ.mï…#® ‘pÓ³‘Hs8 ? àÇb/ËqBð†üPà ¦0!)áŠù†›ÉêGñ– Ã6i΢õ=@
+S¦‰
+’ŸŒ¡XµÎA°íôa³êÇ“¸ ƒïWi@ñRóùÃ: P&&'rIó,<Yætv'/HRð¨^¹o¾È§¬]©Í@¬WãMHœEÉÁüŠƒ0(Dʲà«ÛÒÿ¬ÈÛ› 80ø.CR×» Ð1~¼)uÁ¢ßÆØÀû`ö ÐcGía?’Žö=TôÁĺ·pY÷c-²2%ãLËÿèY&ã°/!Æ®˜Çª‡÷FùÖ^š7WˆlJLjPï˪â·“vÉ[«¤:L‡ùÏŽ…Ñî
+O%0V?ÏbiŠÅQ¸@²f¬:
+·Ní£ž ÇV—¡”¢/„(ôË£”›GbØõ;ŠÏâ£ipÖû,1…‡ê
+‘LŠÙªdõÖpë+ÇÐœw9†ÏzÓ1ľ„Ö]& ì™8VáÉo_­Ô¯×æ Giõ¦²t‹‡Aí9ôdn±2Èç8íóù ÊøøKЀ€àÇ*z1Eç=–þ61b³@,£šožnâöWÈ‹21=0ŒS&É­Jx®Ö^ú„ vE×´&„XJi}-T`¥<\"q‰±)S ¥¼0·.eY©
+úd€™¾Z';[@ã¼X'58 y·ËgHœÞiƒxÛ+*ÊpÉd¤>!¡ðbýP[JOì)a^g<A‘vôþe¼\’äºq(ºïA+Pð ’cõлð´zÿÓ>—
+ÅG÷XÙ*òóåEpÇË=™N |ÉÔxÕÜ;!H¶“3ƒÝþ¨ˆ‡?úw;æ1…ýƒÑ‘Ħ\§É±R’*xAÐð õ;ÊŒÚHG,»a‹MOljpÏóZÂ\°Ñ!¶r…ó©ßâXˆOñ(Êl @TØ•è%Q)¥1ò¢Ê^ÈèJãr~­Lñ‡ÄÂã%L¸òØ’ˆS^R'VüéÞiº1¸ô$Ž×ÅÙxMzíH(:ÐV~ù7sj±(Q‘=@üìóª#wþUº•ÄÜÙDi¥|? â 3ó¢#-‚‰‘´t»”yRʼ7á„ðNm¨ÇT Ìu¬º^ÆJüíŸÖÜ4³‘SQ“úÿ¦›GÛ!]&ë_¹4˜åe‡zÁírTO#",ùZPNb§y4×8"HÌDo³x”ÄÐMÅ̹ßÏre nmÅ»¸ßT~d‘ñ" ­)…£âU¬3Ī­ó)ƃ›ÖyjÜD‹ÑnÔÖû&„ UŸv-i ¶ÍÔ@æ<
+ÌŠkƒª#e)áØ*0˜!/~¬„* 6Ò(3¬8Jè)› oÃI %;v@ß72±„ÜÖr8!
+}Äp¡ò
+ÞTð‡± VÊɒ”3x‘~ÈX´Ö¼@*JÍõù`¤,,â5uñ0 –¿h$´[É]E(Âmèz®âÉׇĪ4IfÏAØ'>ô¹'Äû2‹“ó#=³Öˆ ¨íâíZ{¡¸adRâT"ÊJnWÁïãåS„êVú ,Œ
+Á{”–°¥”1ë¥$Æ€èÉðØÇýæ
+£Ø݈å&†´B›.%]ÛÎ>¤úÀ̓Íþ^òu/á;¬€TÛ¦ã<˪p‘¶Í;¡qÎS5áˆÙœ1UÀ (ƒ2WCÁó‹xŠ±ú¢–‡JÐG<Yíô
+KŠûòüýí…€š9—÷4¤GƸ«Œ~ôµ´çù°;×؃»Gn…q—gŽ|KÓ'Zdy.0/öéÚ—”52M$ÅäàξˢUŠŸø»x5TëZµJ
+é[œËb‘yìÙ"h6fÄ·WŽs¹®cZ¹n+ª€m¹›xP|`Ôô!;fÞŠºò^Så%ŽšK)±$B±FÆÇxôgEÉd¸æ%(gcš[ÜÊj•%¬jA‰û¼ýÛX¿þÄ}w2åh4ƒ8m†ŸW,qieb'r“¾ýe¼@þãð’¬rþ°f/‘2àÇàÒ¼$%-È<¹Ê§
+Ùð7)
+².“‰»YêæJÀ‡6\.ÙúIgò~T
+€¨(åňì1¹í|;€jH-L‘cŽ`Õ\ ˜2Rü” ž$PF¤dÞEœ\¢DA@˜sJeMÂäóAô̒š4$œ(3æGô"ï+g²+Ê‚0ÚÉœI[ÎÚ¬E M€ÁÜ0,Ê0.z¡ôŸâ¿1a쿆”jõIÛ™jñs;ò ³8jkК•WìïJvØî<³ô×—ž5Ozqã*-£Avœ`+ˆœØ H5Y×[Q‚O¬”‡À6Ϩ€2~'i ®#¾0B¹¹4?Ç$£]„ZwÝA‚"¾IÜ R˜á~žC»@H&¸Z݆¾´fÜ è°’29™QÂh¹­ÒóˆQ5õkM\›¤süU QSÛ¨
+ˈÀŸ$€‡Ï¢> ¥Óľ8gMI ±@¬q]tËâK­Î÷#¤ v.̨ülÞÖoR:§¨œ%€ëDc¬mÐìIÒOp“$ p ¸…¦§DðATå `5ÀK°&7šÖ¾åA‡O£«Z7Î) Jé~éŽN…„#ËKÓ:²_§¨‹·CºÂâf“ ¥p\›æ¡?neMËÏÜTu%Ƨ@ìgaÊåC ;%ÿkì›g ¼¡íh1úˆú9²2"li–/{«+ &R•#4ôªa¤Âuš'q™Ð
+ÐW¾óQ¸)‰-gÇêv?G0­ó{åÚ¾©Š¬ÎŠöŠ–¾%@båHG²à7;­ƒôå°M¦.k'C>c&·7D® ü¡ä—¸úC©öÛþ’±òÇD,žÓìfÿõ"ÎçíU¼š% i!Áì™gÅeè&nÑ•µifßG9Iˆqñ.pÑ/bp¶³ÀvÓº€¬ ? þIÎ U'PðSìËQ¢Œˆ(¢Œ!¥|º•Cs4',eqC­CýRô÷µ¡!Íñ%L°F" ˆ!’­Igqg®Ü4k~¶ñA ¬áʼ=‚-·‚Ì| /IJëtÙò-(þã“À‹–T¡ˆ]Œ&o¯;·R¢î5:ËÿÖï‡.|¤ƒ-ª(™¶_„,ð¡D„qÛ»jî©etl¡¯gC¡ëBhµ
+jÆ›;aâ6Ù †ºÏ©U»Æ‚ôXæ
+& QÖ ¤.ãésk7¿”k˜›ã‘7FG»StW»(“¡ú»Ør¾ýHgüŽM—0³T0¡|UØ&JݘEyËI·ÁÙ$?©Î^¯"¿Á¡pªaµL
+-²ç¶ ¨z$²W˜oÑì:Ú‚dŸÌV˶oì=ΊÕ[¾•îaª%•‹>¿ÿ×?§"‚ ÅŸÞÐë¶2eOzÃìóPôníá!Í•©:­> 5 4”Í‹xN¼û·D­çS°œ!G§EðQHÊšÖŸÄdqÉ|Pž~UDzwɪŒó*EóZ¾Çem×Ö ‘éXÀƒoQç(£í›nE(
+n #ÉÚ90Õ
+I³orŤMÅ6s¬I=ªëvõ·BQ‚¡ûó†Ol|p™ÃÛÇ á!âé|àÿù“%CÿPÞ:¤¿ó°‹¶‘ÄÊîtÉÒ5iPÝa†áBl!1ϨP@ ÊTä·]Â!ðCkÞE¾ûƒÒc|.Ð˱e[;‚¼Á{[wpÌätyãƒAÄÍÀ¦½5ïP²ñƒ•ƒ;Kó|Nä*æN°ŠûU¹S¦¬Bf¹ÉmÙày7¤žÑK>À1WJtZpßdèjÔeØ9k>(¢è
+ùNü*€q£SPñkÓv ;[Â<èûh²³ÉѬ0
+Q
+ó‡’3=½ý~(BÐä‚ ƒC HEœY£S3ö¾*‘a¨Üa3½¾<wóÔ:‰Ô¦¿Š-€20lœµq ücUVðÜ4Å·S²Ÿ7Œù4¶ºXÏÑ
+2Åæ,<¥Súò10½„¿S£ŸÎÁð’¦ð =@tÌW¶ü8·€ÿîÙ#@¹\,›ž®éʜ̪ö>Ä„$€á,ZhOó!l'ø
+¨|ŠëˆlóÄ]é%Áã^óþPÃEŒ‡šŽâŠ¡cCR~?TŽ¬{ L)6Kvg2hÀu±0eïT‡°kÅ© ï† ÌÓY"C¬ é2O°7c“æwoo òc¯Ü©Lè´ÃºåÒ3Û”‚Ï:KæÁár@6i˜H‰–e<'²¤ÅÅ1¦SŦ؄Í$w>†~³×#ã«òþÜ,šŒJ!n=°Y|‰Õ×سŠ"dRܾIÄ?¥¢è²y¸ìuH½Ö­È„vžaÁ…á}ð}C¼“¼2ð™[NH€G×詯ÿ¡á#GUH W»,ÜéÚî­cà…ùò²Þ¼dhqNøìˆ×`Mük^K>kêûO„÷ò¥8>v³H.øª|Øð+RVÀs.tÂt°®¸#ˆzdG²€þédZ |¥íÃa«˜H_!QEU¼
+4e»jºt+ÂA„ »Á*d›—¡yÍÈ톂W1‰™í²‚‘#Âõ;B"•üª
+î:ƒ5-ÂÜ‹h¦(ÊjC±=9‰{×ñÔ(†ÖÖÁCQ_3.—äŸÍr!£ætˆ1”8Œ°„€N<efQšë
+{z÷ÞŽ 5ËZ è]B®O
+̱©™¹V¥ŠŒþØMümŠ‚æE´{ሮËj¨$*M­·•L]*JéXN$¶7–†ˆ¶ë¦×"v† ]â\ýìÇm»õ†6Yµó EšÁ¢î@ñÅzûUø–!«;¹Ò AÈœÃÎAg¡‹)a?ãï;ÿºü#CEö©Šs<ä<Á6êÓn¸¯A¼Ð¯Ã î©Ê£ÿ1^îHrÜ@=ï°¶Œ ü?¦‚.]€!oeêþz‰*Lh§ÑäC†vsÑ@UVfÖ^<a¸’FC(6±r=¯dÛTÞFYæ¹9Ï@T)¶Gp%–Ô‹´ŽÙë&ŒbÏ Få˜4T
+úÄ\q#ï…åËÚÍ” ©cS‹Œ‚bšž‚ùm»»™ )ÒCãhĹ€xCnzi"»@l{ WB zõI(ª"®Ë¾X#gÆšAq ÷j½ÂO%2Yaßç
+ú¿·~¾cÀ¾a†µõAÜsÝŽØG±ÔlE>Ýçc-Zƒ‡X6'ãš³›h£}0<"í ¼=l‡äΡRU›‹ ÏÅ¡Ø[ª_œà‰²SÒ¶A'~HLÛø ;ƈ •E‡š¾‹L¼nX°$ˆSÆÛ µDt%ïQáý² èÅ®ê8C‚>³øJ¡ß+Ç1yÍ ŒìTTêÛÑ‘¯ ™Ìì Fê@ošpvÌè…¬LPl²sªv&œ*ÕnŠAòå½Ì¿î©bÚ‘ÔþüûÛÿòÝ ²H06X¦-ñA"â°Y…ò™¸œ9™Š€zK W­ŠDŒT‹P¤U+NbÏëòâdÅ*¸
+Y;ãØHm±¦"Ù@a>·èÇ (#«²ì©ðÓAʇ‰Ï9 ‘i*A\ƒÚBÁ>d‚dzÈZ¸,-šÕ8Išdª‡@áj†}Æå±úx¢~– ' :pÛ«_÷\Ê6=X'³&'.=¤Ø𨄶é‘`ú(ÌÖÚ\^AÞ3è8´<ç6/Êw˜­AZÄ×Õ!ú§ø%'/Mk›(Ò%óOQ•ÎtÊý¼ªöµF®”‡Vé`!¼è·äj X|¸‚ÁÒˆ„ú¶:]¹Èù( ö³5XN3ùØEüé!LÑRvðLú §/ž©F$…]ÚUÎ^wíýÉ3ƒÌ 6D½ëì™P~FD˜.~Î ÈÀ_ÂkIÚrÐ8·Ü³7Lm7lÜŸR8$b0å ÔKòH¢­(ÿ ç<é8kY¡aÅ!ØéXgY*‹ @ÌlÉæý*\?ð
+¢}”ÝA«£Ë¿ŸVúj¢ËB_%+ÓÜ¡þñWc)O}ðÝqxú»Ê;JPÂa²Ö¾q’F¶0ç¸Û)g/2¤V('#´ @íØä]„¾‚ˆK÷¬Ñçý›ao€ú
+ºDhíh$-ìpŽÐÚOÉКܖ·s¿Fh@¥å$ÙR:¤K3.Ñw-žè2nû)eÿ4jLÚÕl é£¥{\è˜#àñJzê]„$‰U—£c„RÐ+v9vÑs„>ñý¡¯ SÓeõm@U~u¡¯  /&2d>èò¹Ðç;ƒúÃæ9àp¡j6Ü 4=‘y6Ï’ÍÂ0h„ÓŽ- ‡ñe»UXB4‰uøI¥Ã?%Š
+3 èvï‚Ø!^åÙ€¦oç‰÷Œ( ñÉt)Þ}ˆI ²À€kó+¯
+ÕÈ-@n„Ç¢ô\YÓy{k¶¨ÓÙ ã]ÿ“<J:µ[&Ň’M'ƒÅÞòê Œ)D¹_w ÖF3’|7Ç'ˆm…k'3çÓA<%1‰$÷î8º@²¿½wŽk’7 ?å\%b™cÙ@lÚóùgÚIöRgq.ˆÒDŽϸ¨}ñî|©°úaÒ±VDuÇœÄNÒfÐS²A0ö@KÐkW}x¦íëî–„bó%®A'/¤´=‘cIQÍÎA‰2„´C¢Zþ‚Ñ+,hõ&tbÊ9‡÷ywÎT‡é©´ómÚ.h£¡ñîU¨¾ö ¤çâ€ÐæÄuÂN¯%>@¾´jé·”2Ù­|/CXbŠ‘?»{Ó—eÏËw©M×^K¨³Ås…G¡ÆaH(úM§¾@üS—Ž_Ϲðæz› ÿN¯ºðøµ:‡ix-ñï¦Êrbʤ@›‚2 ëï ç¢1ÈÈ´á;€FeÛçÊ‚:Bâe;#‡Öa¡ˆ²;?¨ž\ ÕàŸPnÏú3ôïÊ„oÞOhiÃÎ!ùSç¢ph"ïU’!`*3åa¾[áU —UºZÂS£s¶lÇgX< ]-®n‘Vâ`Ó%JMyeã2+¶¡{<Ç*Õ ,H¬Q«Ä¸?¹xu‰,9¾YŠ•MòýSA…à:­8„¹ÔÂÊÓÆ‚ ùÛb9Ñ·6b•Õ¨Y˜Ä$T<6ú}XÅ4"P¼ ;‡†þbr±Dœ­ƒ•R?Aˆ´„>\‚ÖŸ_zÅ(‡bí<|íº1µ”O’@<Út¦•žÛ»#»'—\=<+þO*ˆ„<[qƒþ¨ÚÔèÛDéÒVl²sµO<7™—õRUI¢Ly7k
+ f7S*Xp^wÄô¹›럢•.‘L3  $믢4 êÐÀ>k»r8®=ýé,-Zþ8¿;‡Ùƒ´Âäïhüãe’Ç Ñø:æa-/y nÉûoý™(‰](‰~–M5³1$"cˆX #Æö¡dÊpÑ`P—ïÕ‘KÄŠRR<}<AA4ù5Á$«$‹‘üÍ[Tla®kñáTó2º‚y°üê2+Œ8wŽ!Ôb7‹¦ßÖI$Ú3²˜c"ålÊ_åø /%Ž\ÒŒ û›ÓyÝp†)îÈÄœÞ 4û˜7èK„úVÌsºE-yoÅÄ!ÄkŸ‡©
+òÓãŒG³9Äâ©ŠNÉ£­âS ^ ÷«Øæ5¯E :¨ìÙÖ©ihH0
+ÓÇ\<:`³Úö­‚bFkùn7K2ù¼‰æ|Ò‚ÄH¾Š(‡!½:u­ÇÌÃr¢Þi$ñ!uN$."mH,:N=ßHÉ­1s8"攸Ti“U \$A–Fµa€a‘ÎÚ=o2ˆ¥ñUÄ‚aÜsÇW!bº:¶|$h JWm’I†¡O.pR*w*¾Äßé¥HÖ9á©“ÑgQ€%µåËÕR0Èš½!"¡þÁ;oJùånÞ
+é™Û
+F›¨•^sùUWñ/m_^ØÄßI2ÅQ¨9”8 €ƒB|3Ïë¬a–O‚§²Ÿz‹*ä8íkt%;aûž.Hìæ~(ãU”A(uËÊ ¥žd ‡1Ëœ¨ŽéÆd6üj_§þP‚ÈGvKŸ$GîÒ$4°j>¼†øä7«;œ‘‘^ôk¢r>»\NÏ}n;ϤÏ-/©únenë±{=¸­ÿj2(€§ .¿yM¹ÈoàЮHÁ¬Þ¼hSŠ,YßžóK‰#'CîH;•§uVµ†©òuäÛ—*; ³ªÉäHÐ_ªeÅS®ß÷N s<¿8û`qN¥mùj3Q:xxæ‰ù{(ùbW—«ýñÆ àhˆ%äáÓŠDü"lòÖQ(‰Rû€¸WØÌ~2;Œ©—p•À-¨Ù^¨ke%¦ÉCÿÎÌôRÒÖWDeŠT†úH Ü0èYéµnkÆluÞ$-yP ÆŽ†ûœµÑQyɾŒØ‚sÀ¸Nøïµ]é—¢·‡¢Œ^ÅåàAø‡Iw sÜv2DM-ˆ ” îËŒ W|zÁFâ¬Y­„W`eŒs?yÅwÛJ£¢#AñÞçe Z›õ•UëÏ.|„ÎlE¿XLæøHðÑ=æõHwëÑÒk›î~Ït«„
+G–…ã­Àt£ iT R\Åd`_ýê¡ * ñ°]د&¡,†-µ£‚iÒA(s#å%¹à÷É%ôó$—†x.ËCmEEÚq©Ú;{Ér¤²±—rË.s‰ ildˆÔè*ïU÷¤GI%–¹d[µ¥í™ÜÖ\¶ð±›T_@H±JPLçâ©È˜ûvPô²
+Ê{äßI¼Vo›w˜£©°“ë>  jÌÆ6-¯,ø76ýM˜¹íò¥°x«$~>ÁÁ
+zÜ€«y·E¨¶Í»XçŽÚ£‡Ó–QÊ/Í!`Ãá|•‘ˆ!„Ä<%k«†ÝW†`xÒÃ:m…HĆֱA ³­”áHåÞS fàÌFñ·"£„ N…5Ÿd6#ó`Q”ŽE í„â%ƒ¾N†2`ùî~õ—ï2$‹Ž*ħu >J ÖåVDèQNòøœÄSúÆT~zÜ;½À‚›ã3è<”1~œ°…Uæ$Ä#\d®%ÄS²Z¢ùÚéÏ@~ûe6@/Â
+A–ܶ5FŠ³è÷ùP¤õðýÌkXG‡ji×X…í¤M,Y¶¢~"Ú2Ý×ù.¶˜*²¢£+.$ F+Üy³§Û2ÇgÅ­¶•¬±õ ¸B|aÁÏË´¥™”[GÙò/*kܾwÇ|¦§ØŠzÙ<DdûFH¼0Ïüƒîê6baž±……†I\'²ôZkÿv7-È'qÞ‹oĬJ "ny•$‘cÇ鬄Å°Á‹ôÙnÆ_ª
+ðµV‚ß à•#¥¶{(K™ä­‰Z±o2áæ|Ù¼ÁÏ"`ÓAoÂÚX´^}|ØÀrÑ%Ž m•?-æžÖÁ,Ö™IMs—àIfx e~?†dä¼IW”@Œ ‚R4bc22ìX3ÄV†2Ž eŒN‚±IV©éÆ’Åf%=Ò<²Y±h¨ Jƒ«0FY Å% –hEÀœNb {NÎÌ$c±´ÓŠšÄ”á6œDÎx:ä%c™aìo®8ì U®–%þœ ”–­Ç÷uØ|phœ`l¾¿ãÁù´qÔ½¯^§aåIkñ)£×/«Ïy¦È€å“‹NÇ߉Œ‰,®ˆ"ìÀ„õÝ®ʈQ?e%uh¶Òú>¶”Þ×ÁÔðƈPïû4KÝȃ¥QWGaf8%8=£lf´w-ªä]
+ß €}EU<q÷7‡ðqµØÔ’›­CHlb=ñ*AV0PM>jx‰R#À\Z .¤Æ"»·¢Ó›ÒCŒ›žƒý½èeþ>¾3¤oW 9Hs©½S"N™÷ØÓO+Ñ– dÙî5«‚éÂÉeíÄHL &^ÆJdhð˜$/‰< ®+‹ð׋„ÉgXp˜ä‰¨L”šW»)yù´d†.Š’œòR8JH3Í Àx¨DŽ ^ЀþùÏ©(#zp~„cÎÕlºâ¸aì±9ñKч!h_DêÒ¡h•ä)ì¢á›¬ãÒ—9¤„ã瘎êAPMÇÇ2OÉ8š"Ø(ðÂÅ/_ÃãŒ*ÿÑ:#Ó˜;ï´¸Ä
+öùó¡„IÃõáLK0 u*-A#C_±J%zRů¸_ ¢e´´=ìVF*Ò¸¾_„0àr[ß·Âj°()$õ™ÙŸ”Ârzh,Òÿ„ãŸWŠáá!D-w‰ã}Ê>².ÊiaÏ+ÏÁó-ßë(#}ô
+/N¿Zer®¬xEÇy¢ÝÛ¶ õÕwþä‰E° –g«!¶«ÃÑ34{…L)ovƒ¨úÕ'g³Ñƒ¢±¾ól[xRmE’á@»9]¡†³”<)!bq‘‚´ï­Ÿ¡7´´nô4¸gLNôu9{^§iW†¢êõ`{Àðc]j=–à“iU$BÈÙínEú
+Q¿€]Ù@ÆçceÁqu§ʱ†¥«Î°ëbi[,œ¤)_SW+Öøï Äa\åNð4×·èȶ÷¬åmði„«Œx•dd%[?¼¤rqHå¼¾¦ÉHÑž·A
+‡;e7€ ¾0mî«Â¢¿åõó;¼²f‚ÊÕ°&îÛ]„kqÐ0`ù½ŠÔ@¿l– m¹(kD!‘ô‰ž¯+
+ˆs¤Æ˜ J„;'<ÅxªìŽ…)R%j).¢¥W1ò,
+’
+=üéEA8/1;¶læ–þEð
+ûæ=q*Þ„ó]òúó׬ºþ‡‘i¿š‹ZJœŒ¨r…& ‹ˆ·Ü];
+0Kdtaa)/cg}o«„ÆÃUHcÛŠ…¹Á+ÎC>Ö—8¤!sp¬¿ \§6YPÏW èî`®ò¬ xâYR%öƱMMª”ÌOa—Yd}È®—ç00ºÀÛlj"/
+¬³¤w’W†+€væ
+ endstream endobj 154 0 obj <</Filter[/FlateDecode]/Length 22162>>stream
+H‰Œ—Ar¹DO ;ô¦ƒ\k–¾ÅDü•}ÿí(²äQkÜ!GXng$H$ú³y‰¡møã/mòTé½…kõ¢*£?k7/ânÈ?€ì½ÄüÏþ{öVܼÖΤi©­QK›+M{‘F°‰èjR[)%¼ž‘Ô9H£Õº"ñ«hiµXÌc´ªy4·D(/h\MZmj7^øRÄôw¤ï ö,E Ò¸¢ùãÇÇÿ>Êãgï^"šhÈ:O
+yÓÞ¸áã× ˆçkÙµË〸{µQz«+GÖÜÕya1¯^J ‘*f«"­ŒÎßv^]2i}tTŸƒ¯e¢«ÆÊ’uî=Fíâ=z¶BDo1Šm G¨N=ª×QÃÊØŸÓy8᫇Œ nFñùJïÑ•2w´^UˆÚ•ªZ{|~ì@åY-K+AQ„‚
+Nåš’d&®xê{¡kaèòÓs‡£¨šEæÒËPó
+Ÿ0oÔì(+ ’§¨n›KfŠ6™#ï>ÏádDèï•ÆJHÎP©+MA\ŲBëÝÀ»¨Üc¥¤÷¦ñÆÝeò}|‰ýþQê QJ/6î’Ãox_ºÔ}†7o•:C½‚ßϺ”’ôØßƲ¿jŽÍæÛW¡W(L¤Uê_Ùûž›”4É.g$–xlŒ!:ŒàTºm™¾#Vœ—joNy¡Ìî&/Ô»¾çÊ_cú~ Û©}0¡ð&t¢–óÍôùÕsšÒ¥•hÿZ…iô+^l@?¶ X¼F{Áü|ãFK+°”øÉ[žËØËI¿&&÷’ßj[® w7ÈLã01NÆ?Ò“þó$6’湩<^ñ^hœo×À[uˆ¡¨šî G]Ó¢áÃ;ªncNºy†T_RÎîHû
+½'„bQÕ|ÊÒ÷ØÁNËf¨F×@ª1–ÝqU,ýÇnÑ”gcba½Ñ»G‰nbûc:dô¼Žs{,‚’°å—&„¬Ð¾Íý(«)H Wä1ý.  ù éÄ[JÕ» Mb°­Zº¤6‰qA~o©Lq&¨óHé©p}B:þë‡
+ÂJZ Ê1!–å2LÄ3‡-6”Y.JŠ¬Wt%Êaã°mdWcy½—ªBæÓ« ÷Ä ! WMÛ³?§ñd$åg:0v³ ì1¹7Mˆ±‡AR:b…2²_ÂãÊoâ2R“be‡„ïÜ>ÏQ†òÒåíQrÓÓÚòŸÊ>9H©§•ÌxÅìjΞEƒêxì·ADËÏØ&½M{Qu¼*«OíS X»¨Ÿ ¿cŸd–Pz‘RK¹íâ\ÇJj“ø¸):µáú(KÛ‚0\ƒ‚ÎÑɦ‰&%7ÊIäì.œƒ§«ýüØvé©IoÖ†¬½¿ Ú‰üä{Š¼÷'B‡¨21ÝnT>A<BÀíFå1qùbË·*ïŽ*ù¨FÊNíH/ƒÀwnÑ™_X€–ÂzZë×s‚-¨°Òƒ^·ò ]avw|îOW(v‘ •­íÏéÈQê¥ígZ½<ŒÊNÂ*buŠ±¥l÷½ÎãA¢Ô\2¼Ú^çñ 6ãã«¿.:íX–;`j;븥â´Óù èªó@)4»¨Ô­Î“D¦©£fä£Ýè¼;))ìC¿ú»ÎÁ^F¯¸‰Ø‰øQVTbQô~G êÎâëX2³½))­k©¾Õy¸þ¡ã„\t>Yˆ_ëy§"[OHá¶9à,¶:¤Ó‘ÉóU¡¿‚6UÏd«dÈ……½ Ú(ýôªô(BædBÙS š.-A·#‡ÎìF“O7ÕêùúëÿŒ—9r$GEO€;@¦
+&Ð*¬Œ»6©Kptï#—Õ† J9ÐN ~R<‰[r½AP“qÿ1ð] ûÃÄpÐçÛ®èDp·m‘Ô—[·Ã„Å÷Ý•µÖ´=gPÛÚöéÊ¥“›EºeuùÔBŒêl2ÿä¡uÎiW¹ t'F
+öfð2Ë©Ð!iþ ­Çc„šCè'’›× 8ÀIÙ°‚q¯cÿÖ‹fœHv`6}})ë\ü6ÐöAõ%#*sÀ<±‹˜i·øó)ò‹N(ÏGïP&@_>·«Àþb±Ø¼Aˆ›¶š›"Öü\ýcYƒƒ7csašp~S’þò.{—VO>Xµ+B¦ãN€bˆ\9eÓþI,°Ÿó8†Þý¬›Ÿ‡¼6ˆ3LÿÜäÕo/bôñŽŒÿºÛ›MúŽsD^¶æ¶5nÐèlú—rN<@ wcéÐ|fn[“³°lÕxrN+°’ >6h%HR:–'•Ÿ™L@wCƹ†FL’K|ØÂ_V#µ
+Ì&؆jŠ›kÑ®?åbÄGÐ6^.ÚmXV,ák#"a›¢Û+«£ ûíÏ·ðþû_o¿ýýßÿxÇ@â¸;ÞFì4RWÎê(µ²¦öíZÃœåøq©ŠýT;ÎPZ”ƒ²„¡+*2›^‚BpÝôõ˾ÄÁ)‡Aœ‹+ Ê2þ×Î!¶ ;­Ý)‰«ÈTÈ›{  :„¯oJüS3aP
+­öý9EJuD Ò=±êºrC[ Ä—-dìðF àÔ]þù¶+‚ ã?àš‚Ü| ^Z¾‚¿ëteÖ‚’
+…`P
+êcÙsÎ4CõÀ2çý|Ù§8
+Cëâ|½
+‹ò#ø~}©aà ÝòÄ\ÒA0íø‡Å ëÍãÊÈà¥/säºr$Š®@{ ]†ó`v¨Mº½E{t{ÿ}îCâ“ÿ#ŸÄ¨ŠÄK< ‡;Èy¨SoZWðiûSH
+÷b”j_çd,¾¢e¶µ©økX½…’íU 6"ç¶ ]DŒzA4s
+BAŽÂ`,HD…)á×FrgþJQ"¢F–ÊF`ÄB±Ù–Èg<Þo@3ÄSqNcù¨E÷çEŽÝÆ4Š´“R­i·†:MÊÖë›Ç–iÙ ¸ Æò˜äÁt+!õ¶£ Ë2”R†Mé ÉáÓá.¢Ã½V@™@ê«Íu ö%F Ï;ÊÝ9Iç¥Ú‰©x8¸¥ºÊÇìI¥éèòšäZYëùhùæÃÃðn
+æ°cpl’!Xb3¸:zŠ¢Æùr?@À9±ªÓú¤h:é¹'y‚æз-ÛPÉ`­1•u?÷Ïurh~°PxÇfË®Ž‰8)ð<g0þŠSka·QêœL჻¬
+´¹Å=qüjB…O;}pc±h¤ð†Ð¾)ušàí¤®”R-(Øn»"ÛŠn›ãqs–öu“U‹lV3Rm‰ºOÄU^žPÇ/í!|‚ü¶!ÄŽ¨a÷ÏÉ¢k¸¹A‡Öv2W+BKoþ¼U¶_îNxzPp¸8Ý·ô
+yû·>ˆÀ`âx±ée™µ ÏJ¢ ÀZ@¤ó$†)Ëè ÂÐ" DfÇNî}A°£ ÓDð’ùBĤ¥rr½_ÞxK±¸Š0…>”:dfôó4¯ÅûnÑ´ 4ZÓ‚\‰¨r㔈}‡o(.¨®þ9„^¸“*=²Û@–\˜‡µ¾ Ôtb¢ÛXÓ®*p º‹Æ_öÓ¡²³“p'H±˜óúXå|=VS}ÔJá¥Ê2¯ÇBh£ =o;fÕØÑì¾üb/© wÎ×&p“°9¤ÊPÜ>â,¨féFÇ<`pöø‘Èp½yC•/‰Öw#©äÒ1Å©æÇ—þ<Á°‡=†Dg
+½˜v^
+d7ÜÃ~€x~&6ÂY-­{%ˆšqB­•ÉÀ?c›Ç\RB¹Ä¯˜ýJlœÀÒ—º¯~qVêgE…&Ôë¡”ð)Tƒ˜0µþnPh0ÛÔƒR¹AášAx’!½7
+„F¾^ÃlÍx^È0µLëÍÀŸ.N È’ýcX{ù6è4×çµÊæ ’;ÉïÛ@ȤDZŸÒc3T›Ç>(°ÿä8FÄV똌´)^§ô©HšÛ‹È&9*e¨¦Lÿ&ƒ
+²ð²”vêCðW)Û„ñDt<†l¬U¬ÄÂï ãö¬A9[‘@¼yã^ÖN|fÝ @‚Z< ëãKÞ­÷OÍI䟦N"trØ0Ʋ¶ñ$[bP”1ÐÁ%ãïEF¦2 Ô&’: Rj£¤IÓh‹ÚóÍÎÁÖÍ#ó:(+Yn¦Z-¬-?èë<CÆÛ¸ó˜˜GÇaØ¡qKµ ’¿Œ¤ Ú½V p3÷fLÐû iŽÉëÖ¸*]vF ±EœÚç¦
+ÄkA$õºðHŸÒ Ziò’;Ž>ñØïõ¥Â.5ؾ&+OF7Ñÿ‰]ÇdªÀ$p™ä÷ê/-ÿõÉÑ5ï±wg9l:H9jJU¤–a!ëD¯“c·€üл¶Ïä‡ÊpT¶Ú²~-b§§ß„Ÿ|%°ÏÔm{ŸÀ"F)F¨7ýL—üúáX¡ÊFö^ýqzE®1üÿ¶¶ò(‘‚»¼1Å1aCà-F¹‚•öb¼Œ4ò£æW]÷ÂI µšË¯ž²òÚzO¸`úà·ÇÐ+nÌÌç¾Õ +Ãåxÿ%ËT‚èÃ+(«Íaœ5ˆÒ³ ,v3rÌëvZÓ9ò:‡ÈÀòA¥Û"Aù dP¿ŠAêµ*Ëígh…‹^*ÓÌ÷½@Wâø» $7CΔ¦ÂAÅl)üˆéX­ÂA@Å\3™OÌ>ë‚`ƒPœÑ0z‘ô÷Þ½
+¼ ñšu¦Ìü(Cï(¼’—­'ÓÉ4¢ääÉÕNñŽüvÉÄÆk„T¡ÚmÜ# DêŽfX)LKN2’êå¡Gj` Œý%ˆÚ‘ž•½å‘ÒÁ²¼u#eU œ;š
+i°,;€”Â0‘dSÁÀäüpD½jŒ¹Àê&N˜|ɧǫïe,hû¾ P1‹LnöðoLú™k¿v
+C@ø¥ÉÐSûÔ,Ó˜²¸œþ òí¤`d­gÿ6ˆMU² ê1Ac˜†¡
+ÉX#÷¦Õ9òöžÒîBÇþBîQWGŒLó%eae-mõ–ò¡¾9„ >Ñx<b¨~â(vùºÐŸrdF aÅ}{ÓåXX@«Öc¬ 0½éì¾é$KŨJÙø¼'™Æ[âÛghWÔ”²÷¼¡ Ü `+¤0i®íÚ4#Iü˜aíHÈ{ÏÙ4Bì‚‚¬¥çlöÔ'µ…?‰ ö=„¼aÓ ßÇ $%d‰ÌÙÐM‡TËd?ì+ŽMÒÙÉ¿
+ô‚ÎÖ›{+õ,B’ÀªÎ× ÓmœK Ñ ‡)‡3šlƒŸÃÁ\ݶeübA^V"7
+Fr,‡¿ŠVá¾X½øv á.*Ýú~LO™¸'¨#ådžTÇ–µ¯¤kc(E[{uíT‡„@™ºËAph£iÌ™Œ|
+mæ!°”Êr? Aãø4 þé¬ü-£â-;¬¦:4œ
+„)‰ê†70†qƒgϲ)iƒ¥ø•ÞäE €/‹ŸÏÉA’h?–¬”²‚wp+„rñcƒo¼6AÀ œÔ˜lå ¤{«×2W,–(;?pÅ„ø÷ZU¾ Ò“·ôv
+H´ºÛ9„e²±@ÑF‹[Š…GÒ l#Á-~d”L*ªyZ} 4¤"ƒc?鳑ٵ—t3.%´ýº`À˜•oaõ ú~ýú7$¼¼TÁÕ2·IÒÊ’óžGŠ¨0õ“« ‚¬°.¨ÍÜA3D*‰ÑcùÇ){"*Ô궕
+f”Á„ß}T ‚›_)ìJ3pz–”[çtu•ªÙ3ÖHhð¾ìÇp-H ×E§,ZñâE —õбҞ1_+&Ó*BL% Ô2V$Ç\À@šÔ bµ¼äÍ$5® c‘#]ÀÙ3î÷aÖ‹sÑäÆry¶Â‚âc
+÷–Ó¾<¨ú±uÀT—¨
+A/ãÑ㤪ü*:èb=l­C–-òMÂP Y¡ÎF02²g‰e/G¨È³€¸Ú@m>ëÀ
+ç„&ác¶t5ôå1…&ì—¥‚ )FúPÊÑ(ýäsBp%HJ*äÈr¤7SîØ…€Yö…aé¶<¦ð›½®~Ì­'Æû{æü\ÛH {
+u—ø§ñ<DÈn¤¦£)ߧ/.„Æøчxúz °QfÈã{uÖíj8ˆ¦M™vùRj^áÑÚ³3
+Í^žhèÔÍSvu|zæõÄ ÀÀÂ_¼ ˆ@MeÏ*°_|‰Îx¤¥A‘ʵu 3…Ö‹±P
+Ýš#A†çd’ÃEvo‰“¼º¹{5ŠKˆ˜²#¨fBÃ5¤½ pZfaÈÂOaDäÕà¾Ì®„õÍað#aþ­®¾É¡*æŽ
+ˆÈÌ4:¼Ú¾ c†‹1nŠbêA\(˜®sl~Xp÷wˆBjxb~‰ ?]%FB_9Ý‚¨&Ähô:-Ðj“ÙÑw¼¡Ÿ0jÙCÈÀ˜r¤³¦{âøDhH^Échɘâk\‹ù“PŸ~ªŠ¡pvTyõéäËdŽ˜i”|Ëý|¥€°
+
+%Ü}ç O^‚Žªgáwèæ¿ ÆX1ÛË1L£¬[H»ß m49!ßáÎ’°ì9azÈìûžÐ…¯U%õÒH}­méxW—Ð0L½E/!?Tª‹Ù¬9a"iÃâçÀD¢I\ÿç%Ȉ€ZñKlå©oøC.m… ÁDѯõh0ÓÐÀ´Ý×*‚8Œ —lØ_ë* tWQ WI"…´NÁh„¬’æRµe•€ÅR <öPÔoÇyŒm ⥧òvõÌLu€Úϯ!‘Û`JÓ[N›
+Q^B~´è{ç’¤'Xoº†«À;­£MœËk örú} B]ǤÔ+c+èqÝ-èë߼鷞þñ_Bóò¦ =q
+ 7LfPœõç%ˆKrLú=ñ]!ÈNðù0Ôݳ¾BÊ`”!LVÓqò¦ìó¿ÖM¨\ d²ƒwK*S§ !Īø§H6;0ÃŒLFoÎEl?Ò _ÒÛ8„Ì)ÑÜDT(Æp_õ<hhˆ:Jܤ5C äzŠµ¸2ôÅÉZºÅ² ¶ §¦#òÇXMã2Tí‰Û>¬
+,¾MO‘ !Ã8u;!ˆN©Ã¾[*$ÃU"˜ÿÇx™$Ç™ë@øï}çaÝ[ßÂ[ùþÛ÷%”­*–[‹îYÉHäÐx—W¡•yûÊCÞâ-\Ûò¦d: »e%
+îJ³wUL%œÖ¢Ÿ¹Á
+‡ZÇ=‡ _¯€ÐÁ¤q5¯ØpÛ˜ØÇiCèPa?Éf˜ë{-zq%··ÙåGEÆ¥HÜ TJÂuØ(rÛ‚6.nV 7ŠWZ:+ÁmC†˜¶U]1pùXyleYŒv‹z¸Ü:Ë
+m®K1u ‰“ Ö}mm@`M^wƒ~™Öz)q`è%€›÷s¤æýˆ~ yÇßl½Ô C¾õ@÷³—°{ñV\5X™å`žÌ] =å[ª3éÿA´~õÈ/XAªO ¤ÇÈXAy=€1$&UnÝ_ƒ²wA¹4œà7*ÞêÃÙò6¸`îñšsÍ– ÏïXðïlj!¶‚p„41ª¾#~üáøY¸jŽD*Àä ÷/k3}®-×Ø-ht³Zɘ£b´@x»”ü´«¤JL]Âýîœ,r-]
+ŽCJÁ.ƒ?“€­&ú  Úý* ;i5ßšs_Š.’¢*ÖÆR|£‚Ç£º4{EÑ–œ°bLí/EÏÿ’>­GÊ Ø«<ƒŸ£ƒ”z‹Gø|gÕc
+Ø$Z›ê;r.Š´4žåØoÏáòC˜Ûì3%D€%•ÄºüsÃ%,”Ñõ?¿Äß.²,èÿ)—´c‰¬3‚Ù‚GfQi(°¾Öœ
+²±gÜê[ÿ‚jL•Tfœ8§,¿lÊCS§1"E]ÄQMhŒS€BˆËÎ; ¡ÛF 8l~(Y÷– ¦’sîÀâÉßN%•ÿw+BËõ¼Š±­œüʪNÕç×})ú´‚xÔU×¥è”LLC$â—mV‘'8e%}B Lwq‚¹ÀàK[Ö‡b–1•é_àÔ›pt·sΓ;I®8qÒàÄðu¿)@Ä|Mj«ž‹ÐØyàOÀ«椃iõ˜VáC ú7+AILǼØ>¿ªSÓ•%W ôpþbúHÉEBèl2ÈWþ[c†*öE´F¹±Cª§##øU9v¢s
+”³î~?gÉæñ<EЯaå[-3;ãòSótÏ9 'XËce@<n¯Ñœ­4ľXl,àu8zFÌ9ªNÃr.÷6cdÚI0/+ˆÊ“`|–íÝSÑç›"àº`Si}@}eå»ÑÌ@ð^H?Üa8/a/ªâB1§A—²•?ã»S©MI‘/ñ Ø1¥ü%3ujÇÌèœ\ŠCKÙ•[YñÀ¾œ÷ï‘YЋ·
+òwøzø™“’àœääÏ71I6¿„+újœI;28oÖ*
+Oõãáû»cd*ÉQží¾RÎ
+Ë"v³àíÓÒ°Vh8hDs1¦­‰%ç#˜c(`Š"jV”’*˜@2û01Z•Ì…ÛK4n¾Ç)»lØ™ÇaeÌy¿á‡ØBÒÒ‘óZ„8¶ó½Û 
+µ7)+«3‡
+Öe%j|]ê 5%pWu«ùS[?¿¡¿Çœ¶Ò>d[NþÒvEšDÇ~½)úâdN‰,
+³Á¹éRWâ%.m[ K/ÒÖ§X —H½ä¬]<qZ\üº©¬0Pc̓µs’„`iZ¸3x€…ÙF¨
+Ï@^á+ù[
+²ëÒ Õo¥zk®ª*
+äå
+2t3¾\;I$°º×¦ß$”¾šÌò?§›¶D)cºn,Η-/
+,5áËý1µá•–\à¨qO§9<Ñ"m%1Œ‘2›3LÀ?!§«ŸÝKë$P™¯%ÅœöZhÙŒ›^jžöJ(Í&äl's.ìÈXÓK ÈZ¥›ÛK2¹¥P{L
+7ƒÃ²gÁpfÓ<›O
+•h‚‘ëÇ+ç`
+·ôeȦaˆè€ƒ}Òêѧ%M³Š1ì÷`Œfe9,§60q Kn LÀ×ëõ{Ø ˆ‹I-‡öò+ú
+«Pø8Æ ž·lA%ÚÁúô
+¥^)þ™?zÌ—®÷ï–k
+­†¸³‘û¥—- Àmvå§+b§R™Šœ;Æ~¥']pà²>?' CCasŹëÓ_J¼Ë¬te³b»=ã«<jÞ\ ®Í\]¦™Þ0cpîÃ`º BñÌð öë­¬`63è‘ç’øg¦eù÷—¾ÇñûÓcD1¿‡
+F¡[™Ûù°Ð-u_Æš8Õì*9C(jsÌcX«ñò°¥ÿ\4’’J*êrÆԃÖRÄfÂ6a¾Îç
+?ÉGè_ª‰‡fÀà3¯s
+Ä…´zƒúçcÅŽ"< /ä|WÃŒLÉbE>0»d'lT.OS¬Ç,JƒàÊ¡Ä?E˜èa®0twNXžŸ¥ÎÛˆ`qSœp‰ œÂļXS…þçôÜ ,Žc¶=ˆR$—5çíÎb€¥ÀqÛ`,A[Œé¦– Ê Cg~;Ž§¸ØæCÍǹ¦GÌ@Ô†:3›ù)Þ`Œ¥E=çðñ$Ô™lkEž™JiðÝ~7ê·Étù•!€Ä
+k¦NÜ„1ÏàÐb}°I<½Mï0L‡Fgt{àgé4ºö$MN’ó)ySø ¾3´þA‚C?zwáFŒ{m1J6ÕÖe#K:Ÿ#Ú
+dóˆ †‰4ÉEsÜ®òR„Z–o¤¹s-B˨¸ ¢?j}:Jb]yŒ[`! åP ©Í›½ 3Ì&ü5U×¢ÏÚúñ¶œ°
+,Ü«ƒ w‰ÕƒVÃX“IÏÒb«¤Éõs8à=£§¡är>úü¼CO“÷âOA{>§¿Iú§(6Öc‚T ã!Äiqnäµè¸OY¤7I­óÇE‡y-º$H•¸¦‰0ë1CR’Ųb¡ÝdHŠRÂ%1°ÃêK†¼ã’ý‚| <Ä6µÒo2døŸñ2I®cÇ¡èV¼‚ì›±k¨]ÔTµÿiK€i+“OV„ㇿ 1Iàâ6Ë°%IhïÎÁT(Ú\ø%CR¡ðÇðFÙ‡<2$EPÎJ¡°C¤°Œ„ÂŒ˜›y ‘¸?2ä£æ4òò*Êx¼\Ç‹D|‘æ°îJ:§¯Ýj>°¤¾Êô¤é¸c••h
+6DÙ.Ó5¥:ö‹WŠV‰"‰t4†¾2)s“Ë™q6Ùg‚¦kNFª@*«Z|‹"%'!ÙPH $‚šadÝ{Δӡ·»°IAÅT©¼äõèD£Cj°Q„â³æÓj÷ÃG"€þ)¼øtͬ
+N³JÙ8ÏÎr½8=üV÷¡WÞÈÒ’È\”ô¦Ê“øëîÈ(t«Jð²·àÌY¶sD8Ìò5MòÝPîøt?'Â:¬~–õðIuihGoR)V‚)‡±lÙ_Uжµ ž
+á;qÓþHÀ·AœTï{õü-‘~/¥¼&¤æ“ðÿOEýÕˆ*êiíìEOwpøÜÓüûNvõöªR·L—Ž†w] AÅ#òuŽ §¢ÓÕŸ;]ý_wZWÿõ•æW‘U P­.B?p–Ín/VƒXK|ÿ®Y4³JXÍ­òˆ1­D+ RbßHˆ Ÿ…ÌjèòóAšE¾ŽL–mòC07~­"‚ÐðFŽo5wù*ôÕK: UÂúú
+±Ó ÃâÞ¡ˆ â­'Žw9­ÛY¿ˆÙÊΟ·šOïàTW¡ý4E«$Õ4pý(µh&D96”ÁJH“µlÊQô7†–ÅÚ³|5«‹^øö§
+ÄÇÇñD´t¾)ùâ(üK"„‹íwza%ÊLÿ•Ó¶Š(¦ó[ –Q9.iH‡
+¤¬¥¾ßt?&Ù—äÊ樎ë›\´X\ÃûÙâZÌFêiâȘܪÐ&ÊC¤dÇðWa?É>rØŽ@BX®òTBˆá‰Š8Û¸¿ô("J§Y‚mçà(µš©õÍ“£k•Ò½¤òN¬ð~+%FRã¸ÖÄ›¹dÊ—‚Lœ¬pÞ;Ž"†ð[³’Ì/avpáÅaLËQZè,žJÞñÒ—¢cQ’Fâ嬧ñÒ¡¦K©y=Š¤ Ý¡5ÉݦËLtg[Ú‡×açC´ €Fµä ÆÈȅȽŒ“çðól D©pFxØ™à‹g[*ƒÃNZ³žÏÞoaÄB˜å~íÝ9 \Ì9m'*¢*XóØ£“-,9³8þ©Ò Uøàœ®…áÉE¬ÆÁ*
+ÀåLbWÛ¦£ò >Û­R8ˆjd0’E1È«OJ€Duø _’•#‡}˜3M||žK»œ+nEx¡Â‚>ç…œGÚHú¬7ÖÇažÉœ׈°™^vàܼbDÝÚ@ê]ú¿Õ³èoqýü·þš§KPª³v{-a’K´P2=¶¥Nа^­yòI–ý´¢ûãA²ð´Š vü`-«Ó”hæ` \zµþŠáœZsÝÏÅ¥c®z-hÞ
+Š‡J
+ÁM²±oJ˜F 1Œ-ÿùÒ·þ¸²¥¨
+v9În>3‰ ànÿÌ?b][—ÖÚó£Ú¨˜Ê¯æ³ ˆ/íû¬ àîë7£c¥ªS‰þtE^ƒÇ£Hór‰¦•þ|StÇ"Wlƈ}çR¾%²×¥úÓ;œ;/Ýòôwfò͸ayŠQøàuï Œ„ªÌz•ÇàOâ¤@I¾H ÷æÚ ê†¡nqÒÆ’
+H•ÐÒÌW°æÍ!&/;boŠ›…²Wõr%ÌŠ”.ǽ*ø‚áÊ5"‚AÃ*VBCšøɲTˆê³m˜¢‡-9uø§Eˆn–½ŸÙaq(ªXëX*9dN_†FnŽÀ±¢cC/‡ †JXÓ0pRÈglH4h'võoÛfºÌŸDƒü”É$‹ÒR÷s€&>6)“ø0¹§Ö2 Q0jÂìÊ»S`Åõœœ½$ýŸð2IŽ#†à—¸ƒø“þvV…f8aŸ,Ô$±T%~TÉï©Í Y¦·„©#£U.ïhEE榨8'¼’5c?Ñ @ÁEd ‘T
+´EÔT?Šê4?—áQÐ;h †¼kßÿ4ôYû.$l0ÍpV.0¶±^ÆRêGj/A« I%&Çf A]LÛÉ)9Í'¤åw ÀÓ2 þÜ1‚‹EžJº¿ &~Éèž N:††±=šm.¼ã!à掣À 2­ni'bà“”Æ¦µ—EÉI뼉©ƒ´«Ókx,Ç $¶ø­ÀÈ6(¥M
+yåÉÏ‚¾…ÄQ`ÇàQ¬%õÛw(ü9÷€X^êæPúÌÐCÚ9_EÛoÞ4¤ÈqTQƒ"±5ïÃTQÁÜ!(l|SŠ·âUË ¾D%Fý‡6i£C¯‰xOÁ2  õse†^dµXŒ¹dT°9SGe*CKhbd5¥e>˜õ’Iœ‘¿Â¡â;üÿ4í&ñGt0Kü&”Iåì€iw¹WÛ!’j
+µ—`!çAz¬±ß-É×$e”jGû!ú’Žî)’´ÐˆP§yB¸U`UéÉIƒ‘ÉÂ=wž´{CƒørbYkêGÏw4g:¼† œ½Eþû=@›…2L+½^ô7` "Ò»ö¨–$
+LãÓþ 0
+H‰Œ—Án¤¹ „Ÿ`Þ¡Ï ¤!‰EƒÝã\ó‹äÏ1ïŸ/Üþ³‹·«%‘,‹¿‰Î§ôf«©«Å£ËŠgøÒ9´ Ÿ 6,\Vkmñöl±æ¦Òí@ºIô¦_<þü±1£ÏÞ§ ƒáž05éÓô3–Êêm´±¢Ïà±hþ€,ï¢][Çï?þÅeËž«·ñPç2U^£Eü: ÙZ—æk = %-ãl1ûxlH÷åMɇUìn¡+†ƒË-¾´æZÝC†Ü@2x@Ê ÒLã
+þó9@ù¬‘z:uˆÕ\fBHÇ̈B'¡nÈlÝTIÇu Yf1mºW-†ú$Œ)Vǘ·¥áj'‡î)”A¢KÆðÞÜúAß®â+(Y¾õ'Ï¥¦m•?~žÀe4UÔD¾ Ò§ÌIÐkÀ1y¼}
+WB ˆwR8›x̼ˆ6­-á¬qD0$ ƒú äÏ˱"<f@âûs Nö‡¹®¢{:‚Ršû¬6ij æ(žR•ÑIbRò÷w »ä¬'Oµ,ÞÐùmä k”xÎ)뀸jM…r½ß€Þ¾Ó9?Oƒõ§:´[nDuÓ‡¿¾
+4ØKJY-Ýä(‹‚‰ÎTåJ‚)‰šDaÒ£p9JúÞ–ÇêgßÚö”²‰Ž4ÿÊÿÒ+ÙPBûhC˜µx”Ù.7Ž:¦ˆ2¯W©>”G
+Í?ûÑ@ˆªå©eßݵæ±/ ›ZÙb²-VSDµs
+«Ö çD,È$Q
+áF¯‹à/cD^Î䤮jž,)“÷ç,+‘Àxäýk€00qA&_Eµh|L.R&f÷¹ `/@ü×}†o *u]õ
+ÊÍÆÓ‰0÷¯™3Zv ʺŠ6cçô v]ô’ Ȧæ’ƨ|Üe˜¹zÚ×¼-ÔGDÕé¥Þ7§¼æî)¨÷9œúND–Ê•E÷M€v2íב„o4Ó_=7b°~âüf)ýU•ô4÷Þj=¹Yo?ƒ˜ë}dàŒ9Îþy{Ý èí;oúÉÓûÇÜór4²M¦Êœ@ý3°Õ¨}{üûÔÊ=‹Óæ/Ž›<L ŒC²ž!ROf›lrö+èçÈ&æ»á×F¤#OÐçë^AoßyS†ØÿçßþCœÝÈÈØ“PÝýϜ՞1æ:ÂßD*ÂZË%•,©9,JNÝ\c»íb~åz€½1]§T… ám¢ë» iOr¤i^¥ºAŸ®û†Š…TVºs[nìŠìsÌžob^ðö,eîûã„®S:,ok0ã‰×Á{¯^•ÐÅ×iröš«@’Ž™Vz_jQ3æÛú¿‚6.óûÔÖË a`7¶+¬ã0ø¥º$#é!G¤À˜bϱn8ó¥
+t²å뜒?£–X—뢤Ýࣤã@¯†bôY!)Â{¹J@lSÌ(ÚÎF¬gvp6Î9ØÃsèñh@Ø'fK«u;\J(!é«ÌÐ)¬sïJ×UÂ*ŠOa«sPœAÝø¤‚¢ýq‘ ‹«
+lM9A›µ½£ÝAXH„æ„Yï7½‚–¦ÙB\c»Á„0iÒS"Ý‚³¡3“`ZŽgXG°õ@(µ§Œ¾í=¨VÇA’å$"ÚEyáWîz•?ì"ŒÑÌQA°è9ò¡`ŽåKV‘µ~©«²‘é—çâiÛdDð†ƒ™'7LG”ù-¹P‘w+t~ÏÎgPìœÓùõLoS¼Á`°Fß›
+-‡·EQ†a‚L– ‚CÙXê˜Ünqäÿz02¸$n«†IãÊDèó‚°€åêõ-R°¹°¥1[|]7e9Yè¦EYOè•&i¬î…Bðg]ÈÞCúöŒ°æȧ¾_ô?çÌ…?Š=šs(=Õ‹ÚáÌ©Dãh“±¸]Ò²n@²×† ¿ö´MŽ¤îºŸ>)sP2Ý®«˜]´9î²UŽr¥„†féÁÌmõ„<î…Äâ©(’°
+Bßep&v8Äܘäl- ˜üñ¹©.¢9Xlòê"|.Kæ¹›®:GÚÎ$˜4F•ÑÏ(铑㢠d‰æ$- ‚ë*‚™};ñâ BÎi#=J9·|aÃÙuþËx™$‡q+AôºƒN 
+óZ[Ã+ùþÛÿ¨j‰$:¾ÃÞˆLr2`L{ƒPg«/Vc+êóçªÏ ˆI i†~•Î”H4ß £ &oÓùŽÎø æÒä£ OÚžú±Ä,MÕËÛÜ[̘ª\Þp¢åãhÈ<Js›3;Í„,=÷øц22ØÎô´
+ÊÓî§ô€Ô)\"ÿÕ3~Iš‡Èa„ñì°szµé‡ˆ†:öj¤ÔÅp<¼ý‘”q‘Y¡*¶“)V¼Ë5¤ìZaÓ²_ÉTí ØvD ×|[R@TŠÙ/R±ci. šI‰8Kï÷ ˆo1™ajkNy.,MeðDJlJé((VÎ]Šg’öd‹G{È}%ÀqãžRÿBøiXvS ¡G4³]G0fÊæ7‘K`ñ^ŽÇ‚m€ÿ­“Ñâ&æ“Ïi%;fޠ䥻£!J‚üÂ!2ï(¾a\"  Òȩ̈cwÆd¿%çÔÀýLw;¶qÀnÈ%l6K÷ò ¹¿Á1æ
+¶ÜÕ‘œ}a1œ1h…]ý­¡0% [±Á^B©1ÿN,¿ó-Þ1/t—ÓDÅ0Òu¿IÛ*×Þ£åò-òcÔõé'ãI˜®î7™ÚèøÒêƔт&eƒÂæŽJ†(Õ®†œ]ÄöCëºÕgt>Ï~gÉlÏÒ-´LKÏ2[ÓoÒ ŒQ¸yÜ-Ñ×sÄ0è·¼—<²)vPñ~HŒDÅš7Š¹Ëx$!ŒÈ»#Z<œ%"7An°ë÷ Aܸzß|˜ô¯€O¤ÿóÛWÈÚbV•v”ò~ß!òVxI¨Ë5k@.iÉJÞ
+Foi^Úc>zy ³É:¶i¯™`¢PEÎ §ñƒ¿€9iÛôs*/7&qÍ{B2ä?øÈésóbÇ­&œª_Õ²(Ÿ…Åc#©æóÚ!r"üÒj
+y<ö xñ–ýÔæâÁB+îõXHÞ‘hø@°Pøïiù h a$óÉëbB}^¾€5
+«Zíé¤"$춞¯ib2v±MÿàŠøOV¬5Ï ¼ ^-^bE7[kÊ |…Ä*|˜óK†U
+~œt2»O…?
+
+{ªNù âW‘ÆØÃ¥£ïç 3„Ž¦Zœc2͵Hnœñ°ü´Ü¿F)'Nm<ÚSYÏIkÁdˆ£=E‰h.o¿ä¤qˆ^‹[béð')¿Ë#1ýG/TÖv…Ùí,"+’}B¿‚â!6ÃYšK(ùaÄç0ã8NFü6…R°
+²”þ(
+GÉ9f¶«Ý§û2ÑìžÛKEŠ¤Äã9Mf¼Â½å½ÂÒ_yÙ1'𚨧1.q²8Xæ™Úe¥ŽP2œÌ 7Þ–?‡\š”r›­‹›³¹_Ÿ¸ªÚTkuØòóÛ?ºÌ(2÷ä½èî|¶œò•šœhw…^¡ðw[c´ßak>˜– ÁáÃú¸¾0Y&þƒóEóçñöcuR B«{Ìé
+s2³/ˆ„›m7vÛߥ^ð¹'F}™ 턽#ã°ä¸4õÚÏi| ;”‘U~£z ð÷Syµ„–S2É\D·õ&ÈŽ¼W©ÁA@­K*]k„¿AZà tì_ùA¢[2€¸ ‡0yØF½÷¸ sP<ËðñÂíB1
+·G1‡/ÃÃËõöC“…YJ؆¥ $˜‚=ƒ(qAý~ŽýPƒ0$(h@kˆ}B.ª“’þEý{Šä‡Û"§Š_z\+íLrŽƒÄœ2Ttç?L$£å^a
+Ìž%%%‡P—:%”±2¸\Lp“ôÅUT¥)­Ž‰–Ã(ß"êú'Óô`@o÷µ‚Ô5ÆLÖc>1û?ÐÃjP¤RR÷sªˆNÿéǨáR¨“fçI°<‡Û B=`dùZ(óç· èºš™G­m»Ö£ŒÿÔÚ‰8s\% ¿n·ý'̧ØûûdÄîÇa®Ï'>¿ø±“¶¢”z¥¨Ðg}E³YúÅеõ´â3#!}eËcx¾@ZVê‚·Ç7Ö—µëã‰2LoXª½”~zÁ+X,ßó¾$TŒvyúA:ÝBíY±%äûŸ«¾€>qÁòR^ ”·W}
+Ù¥wööª…¡„)rÁuÌ{uÖŽJÍz×Ý×/V§f™?Êo­Ä÷AÄÜzo9 X±Ì•Ý/18t/eÅ°eaŸ9:ñ}@í¡@X©yÌÄDŠlÉY1Èbv>û9}™ò»:_uè
+I½*ž¯ë¹ê3¨K€«¼r>F?xÛØüá88ÌŽaK}yøv‹å8ð×òGm5•·F’˜}4£î½*·W)›lÈv¯ü“Q¨ÏXTøöcdÅ ¶Ñü‹s‘…ƒ+°ŽJ–Ò¯_’Dò“ãðÖÖc.ƒöÝ0±l¦ òvš¤m2`TÙ·
+e7zß+?OtÂd'¥Îf6ÞiÉ=6š¡ÆÇ÷ñÜ #K˜É쟃ðB(ÈJ0NQ^ÄŸ˜¿)ó"&˜-›öÂ2F-éÊÃÚožȦã¬Îv­²ÈRM—NP4súåe’\Ç Ñè:ó°öVçðŠºÿÖ/ª–ø?à "ì°L%F 9°ŒûÛ-ªh"xf:Œ³˜ Ä|0I€ºÏ‘»©j÷°´¢)2F£³Â/pYyCêDí0›^Ä ÓѳÞnùŠxÅãÉ겶iûê¤ß­–W–ßÁ>P¿r|
+`~ÕgåB æh-t—úÂ
+ÈÊCxÈ´Ÿ#~A¶;[dçˆø+/Ëx(>Ô™UçVF?öêCÔó\$•-ñ`'Z•w ¦Ua¦ŠGeí$»iJ5<&œ"lŠÎчpå³Nå÷F/æêáêI¯ÐR[ª&Áz°ÒÁÕŠ_lÙ8zÄWˆK£[C9ž#‰Á)ëµìƒÇàØKS3a cãbÆ1E½cÌ~“:±…΀4îi‡ëÃ8™ì÷P™äW¢¢VJ~UÆd )16yr Tì9<û€=˜ò°ÓBŠ¨A¡¨ƒ”‡Äˆ —mCä!Cg”=â2¿°\…ÓB
+³”U‘êSšp•]}ýv4ëtHáÉCƒÿ4±mÜk%Gƒ2euf»DDcÎ/âZ«ímB{7DæÃ@¸n¹§è'É*R”j
+Rsƒo†êaë yñRÂU´FÀ'ò x
+bB“…ÍqG â50ra[áñ›)¹ºI”)¦yIK†W¢¿óyR/s4íž$†ä× /ÍŸábÉ/AƒïOáBZa#Ø%ÏñôéS¼¿¨Ì4ùL£c¸¤R„Ù]\ɱèbÖË6di ÃN)¸+xŒU¨ÏUZ3¾‰ÊØÃé6³4éS6®å´W®ÇŠ·¬¦þ鶼xF¼Ó·¬—XJÜüòàMyÇxbyí«iôö°<«aÅ‘P¡®(¬o½FÆ Œl¦u&î¢rÏòÒ6l"'»
+ׄ¿Š¤‚b$€ßã'¼ Xý”m¡)V!Eb&ä°qFön…ÛŽ,VM€±±žÎ1ìCå⠡䇓J!. æƒh4±áLú‘°ç29œœpŸÕ¯¢tWV40_+GËGõÚí*Œ1æ•ækñZrÐla½ ø‚Z0eÿ|û÷›Fè,'”žox}*Ê°äï¿6•„¢Ä¥å
+ýNwi,oÔ÷Á£Ý_À¢âÓƒ¸Y Ä/Zˆ?d[*A¡,Ž¤É„$+°!rQÄS vlØýÞÏ!7Ð,c1ÃÅüÅF`Ø2nclŽzý^»‰Æ ˜YÞÜ@H!û slM+ áœjö›ØI,FÄï/}Løº)O^EH»Â]QIS1Í ¾‚8‡ùbØÕÜ`Zæ‘ÊÃJ,å$¤&Ø»%Þ$µÒ0y¸JtѾ—’ÐjÚŠ'Ž‚AaÕú¼›%J8㹟0Dþš‡ïG©|¢E«_$ÓËÏú܉/ò.ŠßTø|ø*ó ~“½®Ë.
+#6‘âmûªÏÙM¿lì­ÈA)ЦÿˆÁ˜µž v“œuƒ ÛôGéh•÷¥8öþ\Åû˜
+%e†(å8üc"4Y•låX{‰$ý&$ƒU1ܪŠž >¾/ísТ\ÝÜó~ÐmCAP±u~ˆ—bWߦBúÓ Dø‘ñê0|ßÇp‡~FÚ‹T"Ö,p¥A ö!ñ 'Ⱥ
+»·äxÞq>'*~DÜ#â“ ²~ ÕêËB Bˆka¯^Ex„J°èfúâc buŠG16ÄÍ°¤•ÒK{yúÐy~o$9cJk¦~’ªf-úMØ‚Òä0—ûap Ž
+$×›`-F‹ñšìc˜7¦’m!°^Ð0<0ƒ=ŠÁÇKtü´m¹à·(ùUï  {1w%^ŽÑz`ÿ!·Ùn?ÙÝcQUÃXèãjúÚhØ÷ O‚¯ãq^ 2‹7“xÒWâASCq×íLû
+ÅnYâ@blØE¿Šö†9·W}é¸:† šïv
+ò‚ÿXëVo¶†m¿ïyÁ¨vhj£Dår RO¦‘Ø­ &iDþe7½™|]W¨}vêO5SëÿP)”ÈH3¤‚R锉Š¾0HÓÈNL}øLw—O³ Âfó7•v‰9Фˆí¥zsG'mJEo‘Yk•–(?鉂að™€"›Bb·t"POkL(¡’Ú­¦;g*¢üFȾ2s!fÇT=ER°õ° À6Y÷YG òÄî?+›Êe¦DÒdB!¢0Lì_LÎ ÄnRºËZâoç4-Z0JqŸGU” Hö1
+•¼ ¥©7ÆI²#Xöˆù°OVlE‚+÷9Ú¡¥Ü1:r
+Un—–$i3F¬›”¾.w„˜o¿¬“Úl‡¶±­tl…qvSÅ¥  -†ÝªËu—ÊŒ²#³fc<çF4ùç¦×µ·ìü˜ª¸}£¦‘Ì÷ŠS+À´ æ)ÍLÉ•q1ÁͨÏ‘gn:“AÒE”v5¶U°L 7É>ÒÍ5ƒÒNÇ4eoA›sÀú¢ñY Œë³:ýtX¡}1#N-|©ˆxÙIÝñKu·ð44 ªìaYE<@:ï‰C:C>9x
+’³’=l !ó3 ˜šA“ˆ´Ðp\RÆ‘ ¸xYF=GÜf»AþÒœýN/Ÿ@ÿ½šN‹MŽù나2ýP¢Çy@d:o& å«%>@}ʲK»nëdìQGOyÑxƒ<­«@D
+Ü-ã'>¹!zøkúÆxÃ}fR\iõikÄàGÆÏFŒŠ7*¯ƒM¿,Óº,q ÛN‘Q »0é˜+ý5ñx{šÚªƒŽ2L¥ÒÅ5¥3eÉÝÉ Æ‘Ó$±.‚’@¢­›¼ÂhóT˜r/1­_ÂÏCû*ìiºWWmMJX’L”5á,PÃgH—B—Kö¬‚F€8nȯY$3™yŸê™'é½õêÃgQGÿxóæëÄ;ƒì•= ‘åC;¼&lÕdåëÄ‚óêHמ°š÷Hç¬ë…OYïÓæ"# MÏ#Þ×!¯®¸„GO•…™$ÓNƒŽ«YC÷Ðø©9Œ’€‹‚Ž_äËØ«¨Xøz,HqåëlBø¨B1ÕŒÑî'GÁ0›°1磀xÁe³÷Ìè²·œÒœÙÌ* £'9G‹¢Wç«é êrkF?nMòaÎb~Iäb»#-)eš¯kéU[U7(œŸá.ˆ€y*¥â¾>5É„èÕ†ïy8o÷ ’'ïc›ÀÉÃŒ)§ÐüèæÑ3ONîØ,Û[è€âÍMÙä}«Bºâ„ˆ†ë1”·ÔgϪù­Ô1ÔÃùB­‰Ù`T|ºŽ~Rt2·Fj´ë:Ü‘©ÄøÏͽæÄcXý¶Öac}p¾Ý{å¢@ßEÔ¥ÌP¼È" ˜á÷׆ЅšJlfŒÏ`³LÛÍþ¬ìÙòe8
+>I!)õS<
+‘@6Û|ÍàGŠB+À¹Üœ£ÏªgLjvÁùLqt9OÌtƒëž›)HXjáˆGøAµ8]uóÏQú\f5•f…+Å[@ÛUwŠ×^á$ƒ ?Ãì!Ç  Ò0lyoç 4š´s\ ]Ñ åoñóz²ØFÌûüý¤úß¿â×­¨rP’£ŸŒ¨èVEê)ŒÃŸ H1,¢Ì)íñ„¡
+s›4m7D ‰XQz4HàM‘dáP‚¿öVcðB˨Ø9õ÷­s¯ÃÕ¦˜‡ÃµZóƒfœDwCøB*BhL˜#NR˜©ÕwZ9Šæªn.†”×Æ­§/ßÒ¯&[ìÓñ™õÊ÷ Ñל?tÅÊ83³ã…ÏÅ@0]–;B©!s%íe°Ä*£ŸåÐ8 R BµÔ b[%0¸òí¶ÎªMSD´up ˜„%ˆë¥ò·šñ¢[Lš‚OÐÒV¾Œˆ,ŸXJ¶W,Â…ù#d
+áo±ö‰<Ko7öÙN½û(ð[íÿu: ã]º%}há|'†;ŸÄÑÕÇÓË÷¨ Ã{@X&‚Õvù+°
+j ¨Ä„‚#Ã_
+}–ì°Ôb[µTa&iIåqŽU“¥Ý&VÀ¬+
+ôڳѵ›úæ‚ £Ì|<[ì¾<Çâ4R²[5 PÑ{Ó§ú \ɆŒIo¶®›Aúêˆo¤7ó”?›fê§2'‚‘=˜R<:\ƒ3V”Z?*…æŠD—Cc’}«‡â`0F¶Á5åòuÒ-&‚D!C¦Xˆ£”a+eãPp‘é9Ý”òÄŽx¢!íe-¶³üjFÄÂ$†ÜÈ`l!C Ö¼ª1™ÊrhÝwc,Qw@Ñˈ80HaCNi_Žš!üÈ~´1˜Í3ɧDJ8 ¿
+wv:¾S&yðÐD–âïô|c/±èà™4 ƒùÐË…{雼ŠÃ Øæ3ƒAd†)}8v‚ýìƒÈIû Œ0Çgo @ˆ£j•0<!Àú:3¼Úi–ö5"ÚðYÕå£5×cñ­ø …½áiE¯IMiW{oÜ¢L1—<õ¨Zp‰rØC¡I ª5w¶ç ’¤Žm¨/JdN34 “m%g`×´1k
+XÙÉæ¸b2wæ‘|ʃIAOqo¼vz'±Â'N
+Z5ÙhÒÑ>ð,ãré(<ÈÙ·z€XG â'¤€å¼NݺÆ^~íça*£}ô5¬J¼]ªrœDœÉ#ÍKqÐ,f[!{Žq©p•—Ë© Òݼ½ZåŒp{µž_!fF+FÈÔyƒžÓd¥ñPîì?ù¨7 :·ÈgFгþß”Ò@÷1Ô"ÖƒþýÙ $sB¡ÝO"™¦œDE·¸[5ägŒdàÕ” aºs¢e39Ö¼× F×0ˆ3Ò9tè4C#!“Y£ZL‚%€²¶A°ÔŒÆw‡, ’Ð5¼*iªž”íäa”oƒ<Œu•d¼éÀ=Ö¼— DƒJ3û$1ò\U/A3`©ØGN»ÙôÕp€M8º-Èñ5΃Öçá6¦êâø·º—ܘ…‹T|Ë$³ƒã‰¾ñakâf~BÉüÚé ÒÐÁ+¤¯ÓY`—:&pÕTÊñN°6~…à¯Z¥"HYƒ*dIûYÌœáAЊnÕ»£Ù»=mEk!(X;´¡ýlUÔè`N¦¶Xü¦ÑJcÚƒãG™w|×Û3kd]>C;•’‚9gEY4žµð*ãôžÊ•è.¾*©9ËÛ³©Ž2¾¡4q•ñ"·q…ÇÏ´ñÓ$ŠùåÚ‰šD²Rý%:R4ûáÃ3ó¤ð.¦™*ðÖ;îuxÌ‚
+âL'3˜(~a[6š‘€H<ÅÞŠ—Nz©QÊÿ/“,Ënˆ®@{ÈÔaߌåaíBÓ¬ýO}ƒ
+ƒrܯ[QÇ7wl6›¤­þ©ؾÃÈ̓ӟ+Ði@ i‡Ê­Dãu‹†íoŒ+lÀ
+ 9ø[ aBÊ€s­oK´Óâ šÍä«h°ZÉRΑ 7Ž-m~ÿÄÇ8¯2œ8äTREõÀ®^B`DsaéÚã*¾3î@š¿GÏÁ¢¹Y;P#_2×ÁœD8|Y¡óÅKpô‚”ä! Dé<Ë¿_Õ¡&ØgìÚ0Mò3ªÈDD^œLîÁ_L«X#p^½]Jü&-x¯ ÆÏ÷sÈôó+)‰È6¥„8öY­f‡qÒù„¯ïýÇ@ÈßëêÒ–¢ËÓè(n¬Ù9râ$FRœc&™¹ÉS2
+º½DL1¹X°9ÿu)z ½ŸV¼piÍ°ŽîpT…§ýÓ‘Èþsd‘ÓU1_4)éÅ…‡› 1åÜÿýp”J­­ž*mà#S|Uý'`ô¸¨*_àué…•då!<zòî)òÖpq$qS"Æ%>¢ô¸I|BÏßf¨
+½+Â쑾‡Ñ5ÿp”´ÉÚ¤æWÕrR
+)žh{<îL ¡`jTÇ|¿:뛪¿Pv\ÅvʺâÔú!‚"Û5ã&NÌ gcÃ×5 ’X£{EÐô ±¯å¹èÿz ·"¦eÛËvJÚdžˆÈ/+:|£õ;€WnS«Š6Úi,¿œO¤¿EÀ
+‘mÅ­´(x‰«ªòkT–j€I¢U•f§äòÁ@yžÒqËv +á]Y†mq)975NîÑæEoÎi0/D¤×Sòû'µ¬·ŠñKѼ®§±U)=78pýríÓ-/œòOµsèõ‰¡Z -¸³wëVR’¾‡O^Rຠَ¶r\¥tË“è²'ÚÊ"Bài-3 “í•-üAfäL;_%ÇÅGçâï<±²›*¬4,
+4=¾Ó+fbÛ`¯§„=gØ€”§Ä=S€ƒúçB58¤T_b “š‚Ø 7ñ 4ÝûKŽm-¯/iS¸†ØsÍ€¾`Á/E>ÌݱððæŒæü¦júÒ:diwwzSJ._ëk÷* Ð'ÄìƒC ÌS}¡äyسSvÞÁÚd1èïºÞÁö‡Xš¤ƒ }lø”‡ í6£êËobs †‰ÍÎëC Xûeü&†ŸDJ´Ð‹ˆ;`"#~~Óš2O´8ù‹‘_’›…Á®˜¤vóË~)q%ljy‹z-ºŠ}Ò&³e%ïz· òê"_ée\Ô™.>KÚß4%¿HS·SF†’ºø%XÐ7ä‹úq7A_›÷'§t ÕÇTŠ =NAoÈJþeE|îä·Ïo[IÖS“|Š—Ð ŒË,6¯‰ -)¦e;4&‚V ².Ìéé-$·±ü¾êÜ 'C#G³sØr$ÒþšØåʉ:ÅJ†Æµ$Ç%Ü™h[MÆUj6& Í@üf2’«tÈ€Š®tÂ^ç’CÛ BÒk/93d¹z?DŸð;üqÇMx¨
+@0.®Â0ÒÔÖ6ëŸJ9ô4YZ‘àsybKý»Øî’“šNM‰oIb˾}¾)‚‹\±l’Ís¡)[´ý2q‰Ë°DÝKXcè#4äÅ[ücW-…Ù±þÆR&›'1¡É@¼¶ÃïÛKȀ魧›=Å¥A<àoÔq@9í”NK  ëÙ?@½ÔgŒ‚—@g™
+þ[A0ÌèțƴW!ba¹/Ž˜qýª-chÏ]ÑN·¤ñ(ÚWc
+TlÀnœ©—¢ìšsIàŲøÊ®r¹¤/|6àÅmlÅy1^¼Ë*£³Uf^¹c½L*i‹h2·yÍ`
+Dâýƒ
+¾*‘#y§ïô0Þ“‰àZ((=. ŒPcz9xTä”ç©[ë5ÃGÎ|?0†™™A´Gx+M!Ð{Ãq¡p=à|Ø‚×5…¬ì‘'춹|ÖI"”©Ž!Ÿ(=Š·¬uÁ¢Ð[¡Dp§f6‘K‡«@ýh·lž“H“—Ó»ï0N
+/Y >žEØâñ¦ïDº(ÛD3èUüòâ*bˆ•ÕŽ«õW¹»®±¾š©ßš2ù7æ¡ãŸ]dãDX
+uü9úý8+1‘ƒSú{ÑäMIO@È¡
+$IL 7Ý<DHQ+È5ñu9Xeu˜/BÖÚìD‰T
+£;ßO#ÂSš³p¸·[aõñ%™iŸoÝMdEÀ:׽ǔ |çã³··ê2ØêŽå`¹_ß¼#ÎCÈ‘¾#‡’*žá €Ô4ÆÍgöóÌ<“3£<&(¥ÍŠR
+̤dÂè<^W0¤·|ó”T‚žô¾W/É<`Áõ ÿ+v‚QžP¦Ï 1¾» ötO¬#bΞê*Ž,Í­N/
+´¥;­Óm¥pζøNƒèK¶<%ëÒÏuâ~¸†FØCýˆ(³Ê÷ç",EáèÙw¢ 0G}'ÍN)d§y)ñAç;jÀ·uÈ(
+)[ ÕK$…GÉ„ðy;b®„[„*mæØŠ&
+MrÊ¡å3+Yß–’Á€õÅ'w‘§¯”#Š
+»×˜Acš—êqP! ,ñ…u0ÚY˜
+yWíEѺZZEK×+Æ£ j°ÛZg䔵å£=i~‰¹½ø¥<D 6y dݸú5WlŘ¾[ÑM*2H*¾UGA @“SaêyaÏüR"¨DÃÅÖæœoEBr•.ÊBc«gïÜ‹IÒþù‹vº.ÀÀŸ/E ©…ëqqï’¡ÜŽ@|—xyJŸJ&7)´JQ€y;M¤¨+Ñ•4ïsE Ó
+ó|Jä6åœÓðÃðL‚Y¡­Ø©‹cãdA£¬+ÈíÙUBØ…´¡4ó’“ü8³W‹—€ÿ_ØtˆygÑÇú?2ÍÂé!ßv)úô"r -ÕA}3œ
+–
+ÅÀ\S,w`üMÙzKµÚåªéh*‰>ÒØ=Ó›9], Å% ð“ƒ=s½4õ Â:=hÄs“ d„§k†Ô,ªÚ¼~1vÑ/¿Ö} <Yðd¸"?;Y¨iXÒ÷¤‚Þ«÷RéçRTUO¯À£Ôy˜Ð¿wx“9>‚~>½ÜÊ‚`/&‡ý§Æ¯ j¼à:$:ÔpˆL–`Vj"O¾sHÖâR3Ac¶ßz/À!Ý‚nnöó!ˆ+q¹¤…Q§¡«™°Þcš:Ke³˜+ˆ™À%™˜Ã"5Søä´s€Onˆw1S'E†F,,¦_†4/ÉŠ$˜¹IªàǪ§‚¿ñ¯M†Æ\×A‰ÈöZª)ã·Æ½º dà^D|ƒ1¤fÌ(­mÀÉt{”là
+¡5=ˆìZËû­)ÅBš˜‹
+‚òt„øÉ˺¢t[;„X*ð”‡HŸÏúD€Žì·a¸¸ `Ñí6tn85…q¸°¥«&N5ÑHQäÚj!CTò@M¹“§Â>QQ¤½CQSBrZ3î©`q¾{Ñ#¡Ã* ‚dßÔF ®‹†#²TèkJdgèv›,ÅFqg· ·Ê\íÖ‹˜qmwÌ]›¸$ÖëÕ¤x ä•;Cp™V¯"<¤’.1­qDPÎlCñ°¬Gr'‹ÉPgˆ×3ñ€ße€,H`")X·ôâUi÷Óì«Ùå—"1ƳžB,U&³Õh¯u‘Ƶl@›B¼R¡Î‡t "i‡ Z Þ$®8„øÖ½¬Ôû9ZVþÎOðÐùU‚úDw4¹Ãb©è&‹Ð
+~t]
+¹õ¤"Zþ[RÇ
+ÁMøÝB,Uc¨ÊÐÒÓ9Ð šÕÖ<ŠßÀ^õ¶Cø¤ :[w Ò™èZѯThþ°Ñÿ@ÏÑ&4`¯¢
+kNr.n° RÈÎÙL%²—홧›”Š¯}VO„âãòb
+
+4'jŸý©qŸÂ”©—Ñm>Q\
+ñ)ðÃx×£«H$™ÀÉ1äèßÁþ°±?JÐÐ2mKì$7‚ÚïÚ­¸±Ÿáˆ˜¥$Õ3A{Ä7Uý¯sBåõQ‚Ч¹ÊFÒÕ¾+]fÃòË ­çcuŽ&»´e$1ð*!؉¸ÊˆÓA%1ãŒsÝ! %·+I\´C֣ģmGtŠ‘§ñÊÔT¢L…ŠÃø1 Ð¥ôó
+©±U­»0hgDhϽ6èifg’žFîL­ØuÕS ƒ˜aÑÊnh˜Ð¶Ï¸&.9-$±ØSõlÝBKÍ.eìicxåVƲ¤ªñÔ¤=ÉÌ™ª à´ni ³sWÅJ·"Ç„rú;øó@@§ ¨ý:Täð®†OFžŸ¬4™i£ÌÇZ¾ÆÙ¬8™A¿¼>–}ŠºÀYm;§Èo&Ÿ¯ v€˜
+â©A5uW»D!”Îþy*æ•èn¶T™{Ð|ʱG=,µI˜oúŽµ{ˆj~›[ÈIØ‚h™IÑl}œn#%ž$ÖQýݽ¾
+ˆy`WQK¿
+˜$Aènifàæ’8 zº˜U¤2Š"šA9ôe%šõRV‡TÁvHõ3÷§YÓSPìSÓ
+†Có¥L$XvHN!
+ÀGt½ î3¡(RsC
+w®Zep’­wcÀfJ1]jAþÉb¤c GñB~K—+åTô#NëÊ4U;®ÓϘt¬_’ fl5oV
+ÔhH Ò þ V†²ÅaïFH…%$c92ôj8T‡ãà‹ §Xìæ–ï¹2CL»Œ•4ÃqÓB(/êy°èùHgQШ!Ž ø_Ùáôù’qETÅ>² !I›šZ4Qv©-ÁÒŒãå ï|ghÓ\ÐÛܨ
+5­ý§'â]´á̇Ý]½Ìà>3‚¤aAŸ$Q´>éd£3è·57Dp÷"té\B8€‘•7xc¡û݇ ÚÝ• •ÎAØb $>æ!'Ë\΀Åõò— 4'¡@¥`ŸAy¿0¨ÙË“40EoÝh“¿m›˜%å’63^&g*ýLn73@E‹{¥q.Ôi]BJ·îs
+W^­³
+¸Æ
+ˆùBC©R¯À°3…Þ¿OÍÔ<QïÝkЀ ‹jÎÜéOÕéhpp=Æan-É”ùþó&ˆçä±ëq
+aºäj ƒùƒ«¢dºrHMæ±–á¬iK²Ã-
+RÊøúŒ:DOÞϳƂ^/Ù–8$ÂK"Y>a‡h%jgÛº=”³)Näòv®ÂÐDoŸCË$ÓÙ¯¢^I‰Å3Õª¤r¨»W„‡ãWò T•Ìíd º8¨ÈMÇâ÷‚'Ù½Zw‡D$Üa›;¤#ãcg7šA““}F¹èkF_ƒ.V }4d˳(ô8A(, ÆfÏË2®¡²;dhÿÒ„â½®C¼ƒó[v’–ÐWµÁ£žÔ›CXG×&dݪ{Õ]Ub5*¥Þ„üÖ¥«¡õø’E^¼-¯zµÚ€\$Ðv3Kx«°€'7ñ¬*Gbv¦%ÞtŸ2ZéÚ>•Ö‚Àjƒ ¥ÊÁ¥«›¸/º³ÿr‡é ÂjBYé¢RHÄ6 ‚ìrFeç9±Wàp@<„ˈ°7 N·*†ff’˜K-_‚ Aî4ç>Fë€q ûÏ$
+oc ¬Ç"i0m`Óû•‚ }–0|á
+ )Alñœƒýsd¦5wRQ¥üÝ!R1úB>êÎÜ: ¤«µ’¶s (mÂÒy |t-xZ_•g”¥(_GN1r÷úÓXiQcÚÈl«þö~0¢a{NýP10e¹§Y8Ìò‚l•=¦A•÷s"¥K+¤8¥ ó( ž‘­¶]€¿/Êý°k.mžr{xdwEè
+ 
+ÊŒõØ÷9|]‡¢‡P(¼+2þ»…Mð 2•ÊÁË “Ö!‰‡á€Æàà³´ ¬óGlz·Ð5DoÙÇP~>-…lk]ÿ·ø^†~àS¸|œ#W±-U ßQµ¢`1ö-œ0®õÆ7ifŠ¦˜V½ò…¤ä¼[¼ö‘³˜š™¡øqÕ_ â:„<ˆ´ZßÎE×SB ßz¾i틹µEbK.qú†õC© 6¦ÌiîõÑ5cB'?ŸAÖŠ ~çï˜'ºtú$jx,Ìl
+Ôr
+H‰Œ—MŽ9„Oà;ÔæA”H‰\»—¾…YUÝ;SÊjW¦r\hh§ãIü CuÔ®!oÿiC^¦Òd´Ò›ØÛ¯¢}¼¢Ei5ZmömPy™›ÕRjñ¨oï r¾õV¼H­ºýúñß„õWW3é5bQÙ˪j‘QBÔß>d¯è!_Ìôk */ªµT‚)c‚n×]@ï߉i…^_UŠÕa±`2ø•ªÚ˜o DGé¸ÞH­VŠ¹‡uÒWX‰VŠú µèCF.M}¼ýž7µ^8³õVOP)1l Ó¡óí-¼´&Ý&dtb£¡ÒÅ'¤þU‚Öõ d]54¢V§"OǸl9õ§`¢v¯ƒô)§ö*¥…×3˜ke@hv¯[ŸÇÜë»üÑ¥óž+„ÀzuˆßZ¼mB±WÍÉarÛ%d/5)UøRGœ•»Ô%‰åc³©-€î]àiÓºoѲ.º´zwÎ…0›X¾ÒnŸÑ…½»ÂÜfàZÝÿ?I?縕×ð¹µViAùØ‚vú%¯æ脵ø6¨¾
+ìÔj(ìûµ½î[ }%Gä….¿?`z@JYº··â„ãFÏz¬‘+ŽLÉ'´ÞÕãD €Øÿ’½¼B*L/qÎÔhRƒÎ{;Ú.P]Ðm¸n‹`ü}Xãs>!"Þ·S ¿@~ÏÖ2ÄH’>>SÃ…8…$©W„õ·]€t²!>i5©±]äú}EÓz®>†ô›Q9Ш±ÆJÜ«Z™¿± ᤠ\fuVyBÆHáó”?!«Â=eÌÌÅëÓ9:º@6¦ñ ™.µB­Ç„Àƒ º& é£Õª„p^ý›‚\Öà4X£•¡î6ÏaÊFѵ‡SiµYG#›>Aþ$èÏ;̆é/ƒn!•ú·A»é»]÷-зüM6æ27g·@ÄIÏ CÀJ2¨~¨ËÔKžž¢~´-!Õ»£c½­ëzD3IC! âœ0×*1!c Š[«¶£³ )t’ið r¶B”u ”*ø°2Ë
+ÈW|Zý\‘7}¿ƒvåÁÊ9¢¦½?ÖðÚ(ü_¥ûPø·Ú^GLLÇ8J‰ÛÎ:÷ )u‰ü“v;ܯáW…ï%—©ObÂ|B[„£Nðˆ7 6ßIpœâ­¯RyÆÐm ”‘¹ðQf땾:ÝÀ‹6k”¡¦êÊ¡@¬"_—Pd9®âm—Ñ· Âsê¼:¥…‘ª|Œðd± QÃÈû|™$q’¹F­¿cÈPŨë~öëŠA-=¢Çˆ¾¬`jÁ_õÑÃ÷Ãl˜Tƒ«¼—n4–„ ¨l?Kb Ã’ƒ^ɱÚÛ¬bÅx3”SéòyI„Xÿá7…âñ£Ø@ÖU5ušQU}:æÒï{0WÚìrº‘ï^›+ƒï¾ÏÁ—6ýþƬäT•9UœÕA3ªMq9îc ª?9Ò³7Ûn Ac, çe‰_‡ÿlÒ iÇ#²©žÌkn7Ô¿Êgàƒ÷[nA?½
+†SƒTÅW/ Ö‰þìœÈ®ë;ÁØfγ"SØž—›åÝŒÉéÀR1,ìÖE÷ž‰7’[Y‘BÇ©ÔLaÍ0#<¨ Èi ¾,ÊC-Ù%,d¶¶%fÉó¢ÍĶ)ÒñÙjUaû¶Î³^~þ؃¾´þ} âRØò\NÏW^háA‚é"¶œiV7`iJg>5ï§ÂÑÑÜ/ÎÔñófŦ­}‚,Iú9³Ù«Àù¥÷߯]Â?Âœ¹Õü9%¹#á‘)ôý9Ëqžv<¹ÎX0ò…¼‘ï Ñ| ôTÒ®H£8A˜²ERä‹Û{Lg”B„ çˆúqLL~ø嵈(Az¶Ž›oûÁÃan‚‚,ÁøÛt®¼ z LÒfG|LŠ4>­ã}‘Ú9é°ãk­!‹x4o1!¬ÒqÒÂÕ‰bû¯ÉÊ÷ÏðŸûhFÇ2æ1ÈéÈ4F[%ÄäbéyŸzœ6sÍý¹b©#ƒñåVlïnÐûÑÔ¢)Þ±Ö£ñ¤2®ŒÙ Ô„ç6|H<²–‹Í !%©7h)ö™9
+žf™9ö?ÆË$9Žd¢'è;Ô h1knu m©ûoÿóEf"õ)µÌšETLpøÐO¶É(ÙóÜî¿;NvÞñÞø1C`ùaðÆLûRµÀÁHÑžUOœ±ø´Dá*F»SÄçTz™õ‰6¢ˆû‰µ‡…CZ.¶¿÷:Ì]—˯§„¾Ô,+7ŸÜK€{Ú‹x€Ó¼ÿç}c¸·¦TÇvbÆ^Þ‘éo-K±/ͽºr(÷¢¿*Ÿ7þö€Q„Ç@
+I[õnM¸kÈ­™žñÇ( ¦•þ´ŽdΚ4Cvš@ˆãçÄ?ƒ(ƒG$JÓv­àO˜E ÆaÚ6³*gh“ßæÔ¯úòæ…ÄÕ‰±'Óõòæ.I.°ñ¤CÂÌÎë
+]6»ÈPPM{²íÁsg†èf(JÔ˜wux"¯× ´
+–h§¥iä_Ò•èˆIßÑŽoóM%ÿd¬~ý•@£?Œ 6Ú±vQOþ`½îz,w”¢\áhÓµ|y?—!´E
+ƒ,ûÓ‚ÒŠªÀ‰‹¹_Èí±¨ VßGs¾Øャ‡s
+{$xt½9cU9jø`ÁÆÝ6Z¼«4l@ADÂEòæÕ<ŸSt±#>eü¨22v5.nEdð©¶#Â}·‚O4%9çãT¿gJ
+ç(Ÿ÷ä|nEõܶóœÏÿ;“F†WZ†X Éá8ã?»(‹®¥’|ûLI]¦R’wÌ(A‚‡Wuî|&r7¤f ¯äªÆ©v( ¨³OZiÃü3ÚÇlÑ—û^‡œØÙ¹¥vÌ1GéA0µ ¤G6V„0‹û¢j<·”7vÇaËŒL§èÊ7¬}±C+ëо¹ïUÞÈ=
+€‡:„Ösõ›ª
+Ã^yÅ!°öÊØy}s¦ƒ¡ïVÝkè·’µ–õÂÌ¢¿‘‰;Lì]<ªT¸ ì4‰¨ï¬SÃí´VìVº+£1sdâ;Ö„ï–ˆ 59G­áDwlœw W¨Y ¦Cn 8!”h§ÑwC":)ÕáÌânè­ˆÀ¦žWÜD‰ãå™·¨Ä<ZQBmîգ숯•Ï+_žP{óÎøÍR¶=º5"‚7:LZ™0•ÛÐK‰a§BNèPŽ;Þ:ð!Ô›€û9Ü%Á4ñÏ`ÊPg\_9Ä¢Lš3‚Ùß[ îed±ù&»†Lµž_ÞÌ$}€%%Î1a/oö¤üCˆ1aŒÞÿó¦øRôaEe*‰ô.¢MXÉ&OÕöÍaë ™/Õγš‰T¥šËMôN‘qÕ„ù÷‘ùCLŠ–ÿ¢ŽzxÖ¸—Ál¢¾@·Gó{‰W59n;/%†œÃÄéõ–üe’ ›äYS:m
+wN—+òz=ð@ÀÄ»; ´…0ñK7·¢²ˆ’T×Õ ½£³t±ý‹’ƒÀß­%Jpê`«h+ÎÔñhã“Á-ë„rX{ÑmûãåŽÇÑxZÁþ Æ~¡wáTÚún‘àØšf[Ê, j’@¡>ؤXÞS8©Þ¿Õsúƒ·ÿ8.Žw,üwlÇ™~¬¢X+î»OITïõ¶hÇý‹&ý)A3¾\0(›®×G_€ÌZôê'!3{A“z[ŸÁüÎUþ•ÃYÅÉ.¾PúÕd «­‘F$¯Âg`´æŽ«Â„ÁÖ<lŠ~ÝqR€¸KÅW=èÓÁ|ÛÔÔ{:Ò§jáò0²Úô‘œÝ É
+ÞCš—Ä„K2H/xi]Ëgƒ|-üƒU…Rÿ‹N»€°Á'`Êžéöݬþ=sÁ#lx´š:@çºã È¶%U9ß|Tí9³M*]…%€¸ì\JhO\pâ®Úµ³Íô{¼áÁ" E†j‰vãÚŒ¨­XAćÔñ1ócT‹¤´§cIž†Œ!½LxœŠr—RhðÞsò×¢ÁJ¬Ófy ªQäGÙ¿BÞávÑVV–¢·_þ‚id²„ 
+¥ÃŽù(¤ð²½Cl9føqÅ ÚÞý ä¸s\O{åÛ~)ê ,RÐÛ~âoÁ©@#Ãlé Œ—"ô€j¦Ž†‹ ­ÚY/D˜(ÛM~ì7z1—0am[OGÁ}›)u9J/‚¡5矠›ïŸÃO2¸ bÃn„èB.ò÷¨Š«r€‹ç)\€5òä´°±McOå
+‹ìÿ4lµùQ”b•H‘¼³ºeùÊ¿þ˜Îëô‰j?ðïDZˆàW;œ¤Ê·Y’È…p$‚å¯C•aRIeë«}€*X†m¢ÿPOˆ4Æ}u”Ñê@z¯=AU.>ë«tÌí¼öí!ÖßÈ\\Kõ­‹°ép¼¡€ˆ–'¼¹ËÎ/o:cžNÔmô¥qEa‹u/ :}»(>*Kñ‘º«%Æ/UEÀÔï‹¢¿T¾ThïaUŠEÙâÙÿÐC¢ö
+',âº
+/°^hðuP|˜ˆà˜ssI RÅYµ†»Óñ<Pafp‚š®A
+öÁFðD©<`,×wÀþP€hÏd:¤9&W7VI¤}„к߆ï!@ £¹R€z÷ôH~\ß †!`çÊ9eLs}(¨ƒ¹Ë ´ÍðךOÁu½ˆîËBG®énnÑ4Qa¨xæä#2¦Èl;´Ã®úI8_l<ë¸×·²ˆ:Â_ý„•¿! ŽæxC=í÷†0⎵çqþNž9 úcYý;Õ0A¨Eˆ {¬"3Kú3ó ³Þ”§ÔZsH€$Â!T @ww2äje}‡Î”ÐZNÞbL ÂõÌcš¤Œ‰m3÷;ÌŸž‚$¹äCÑûM–žAq]öí†t«ö¥8°22+×îõðŠÜ`j×dç-&q84úg`s¬hç1¾Ý°€d/·cLº3’‹§ùRâGQ@&L.ä×Ï€›¡H[”½„]‚:ô×Þœ$蔌\ó“豎WŠô¢2ÎQúºM9¢ž¡’ÜÝ{Ä -–’ÿõGÆ|8½)ùäÛ÷Q¯ENÀâ
+IåÎ)«Ê·
+¶dÅx˜—#\DÀ«¤@ÔYÛ,Ûñ¤=gIiîIGÑ’à|ÍÝXCÀ–ÚÞ*^Çú4Á!ÐsÈ Ž›’¡?Adç']jx‹Ø¼)Ù¬ÏL+2l91$R”•iP
+ìÏ€ðbq—°§R2iŸÄ€°èœ½¦ð( B›«o^­fš"â@V½³¬`‚ÜÂ87Ö¾0¾gXôÛ@iiêCð’,#cpôw«P[„ÝÊSa0@½Æ}y5aƒpA+‹„‡”é/!zìi`A¢ÚZ†C H’Ê…CranÇF,ò¥ä}—è§FÕŽN4+£d£íl̵´Üw“lp!߶.’I°·¡ïTÙà#^ÝÀí³ÃEO ë~›Áv3=§9ûÅ„$!¿È93†yžð —gœÜùî3àµίoÃ6hœ‹òœ“¾¨„•¶ê%¸|4.¯Ôç~3Ì~ÀGøËÁ4 *eeß΄#'…M]ó+£úS~v¦ÊЕ[uÕpä~YÚÐ#¦Lj}²ÿg ”_‘IqöGŠ6«u/¡Ëc6d—s¢ØVœÏ§FÆÞ&:”-¯¨ý£Ì=§öÆcÁ`½oWÆ«*‡½„‡(L—Vt
+/Àï#mý¹Îu®”žLú©è×M'…ù8vb^E¬õÈŠ±[ivž<k×þQbzG°ÛlòOrÔì——( ä¿í þ6Š¿×QMÙþ¢ÎÛCC˜)Ž”à±ÙH¸Ún†õÅÌ…Ž°Ñ ¥€¦,-ya1‡œJâáe;R&Òcc9ó&^!1QX%¸9:Oäi~݃Ҡ$·Þ_tG”X$;Ã,Á½£ñâ)_³"{!Ç–×4.%™ñ°‹CŠBþüq."d*ÒàE@Þû±è
+F® õih|ßaO¤ÁíÑ èÝÑæ 1CwWŽÈÓ¾ZY„¸WãÔð¨V<Èmó%ä¯J–W«GW~ýÁÜ dxÆÎV’èî>ƒÁ)0à0¿
+öYçWY L†Ç|‹_’|Úm5„¶@y`›Á¿\ð¬À”4ƯØë–œ„
+:ÅhÊú `Œ›Ëœ¥K;>Ä,ql‡Ç„Ú†.Ý}·†M©<k[4xˆ¶Þœw¢0àì÷¥Wø$Í<í“x{1¯¯8t7]¯ï‹AÂüX˜ýL‰ ]hùˆ?:lj Z2j{â¢"¬6P¡¸E»j&°½x_Epã*s÷rý”Ä–ü±¿+ëe]Tt&À¯ˆt*2=x(8ÒC6Ú7 ár%Ùù¡â0È6(3ÈîYŸ€¿Oì®ìò¸Ù`+•àÄ‚;&mpìZ;G<B×4ºÅ–¡@$^–ÔKPFZÝÿLÞ•µÂ£:Ù¾”Є‘âÓmí[Är0¯o½Äµ÷›"v$ »_9Šëÿg¼l²ëÊq¼‚ìÁ+ÈÑ/%ÓÃÚE¦Îþ§ýA¢|â'ݪwº¾’H
+…áoˆ­c n™¢o­÷Xt47®Ú{°pBÅ‚˜²µ;9}ƒøQ´[±€ù«OßI\g¾>¤¸Å?©LÅ‘NMö“ù®?‚ð^œÔZ£&Zf>&™X(«]ÀU´ A#…€ÕÑö$PžÖÆq‚nMçŠûÖ¶ºì¿A6Dá¸"|¾÷
+ú|gFÿY£¦(À;ö†Ù€¡hG`/]£|€"‹.0f9ºëD¹åﲋ·A´Ÿÿ‡@J˜ÿÏõ¸·@¨
+Œ2Œšö!ø"O–”¹D7m¶=šÖÇùr„_¿§5Û›bhxr«¶XgzCú =_ ¿WÙ9ÔV<®=}­®XOîuØ߆qëãE£dJ­Ð c?ý>šT¤ÍqÒ¤œÜÑß•‘RéóxHÞµÓ´Väqx•)óB( ö"šDó¹c.ÊèÃœ,Nθ`æ_á/²VRIÝG1%Ô“6‘²ˆxXc²º¾C^!FÂϦ’‰ðj«}‚üÍÑ_?n˜“ì 5C‰ÁÀ˜Ææº àqÜ[ Q¸× h
+ YögJJ4èsµË¤™¬­´s8 dìr,µè@
+”ý}
+ó%½.´_nD§¡Ü’@x&ìi\|ää÷ 2ßbÂ;¯+Š £`«&KŠ~#%J=rŒ‚À]™‘ënˆ‘ÏK
+²BD* 7ißÇ +îèò‚ Ö¤NíµÃÅÑ’ÃÈûè¨,¡CŒýô ³Mæõ.ò†©xWëê^NÊÃ×íºÊ]óu•›´h´/âØ=^¿£ä5©7³Pö]à‘Ö6dÜIš4ÉAë¥oi_Ñ^[ß:
+²—ó!eßµé(³¦¤§5ØÖ¦uc
+\¨
+G“áÚÇ}ò¸ºEcá‚’û¤ϵƒî¼,@½!k—ŒÀëöãÊÜ!*:ˆMƒ8#êëN™ Ó·´³(#;&„h°éƒ8}ÇŸ¿óÒM6¤HFõãÃWH
+.0gq«E’~"³c!æ‹ÿ«~Žd™nªŸ'×OÐ%‘t‚| ›)ßÛSl9Aç;+—L¬þ èûЃ*®êÙÊæü*8ƒI¡Ì×&ƒuÔ½ouÀZÕgä—WuR/hS…r±ç•SKƒ‹ÁÅöðˆ±ö¬p/qÞ2K¬ããF0žžÜ7(áÿ~‡…NÖŸRiIW-—†ü¹‚0f~_ø3W­IÑ4-’ZS³·A·®ǽ
+*\”®µñÄÈex‚¢‚}LôhR
+O á'7×Ó%° Ñ#— Yob©rÊ(½]ÅFk«™$|*ƒe0MÞ9Z¯Ê‡@`j«Ý9 ¢CÜŽŽµ˜l!ÈêU7ƒ#ˆŸÔ:%D·˜¿§ï ŸLlÜßáEø¿\pòÙ°R™iU
+«BqˆÌÈA¦p`CqÜ'#I'` —Ôžd¯/“昨½iµÉÐãaÓô=)uŽŸ1Iû$XF $` ÷zu+ ÎÕ§÷ÅY‰p?*½RTŸ*Ô¸‘X¸æ²IAÚÐëõ;Rl´° ‹ÐËoÓÅF108d0$`îýQ0_à·¾MfH‚VT/–“µµ™Ù['upÔ…¥«Äèw‘s[Óp0ÊòU.<RŽ8+
+H‘Èç† e9²[ô˜d µc2¡˜?›¾Tæ®DIÿg¼ÜÑäºu ¼‚»­@à+Ö gNGûOý¶­iYч$P¨ÇP»áQóuÑÚÑ&([>=Ñ!$%:(åÕa¥PüáЋ–Œ}&Aø›´vh 6ª!°-€BörÙÃ0)‰µã÷x iÑÓgx\¤—±d_ªq‰‚)ö%v®Œß}-8i["ÿh¢
+à)[èæ›Éá¸ãçn2ÿˬþ§ýöu±Ch°
+E+9¢¬°l ¹(¡²¢&tÛŸEÇ+R!%špQ<5€¶£ì=W ztG>ÎŒW‘1Q"B»ó:6—©°‰ËÛÊ•;<?})úx(Jê)3e·²Cž"E>¶fhº“±±x‡±×o°ݼ<ÄŽLXš*câ%&ÛLê,ãbÿò“$®¸f”öh,cAøB×ÆñPfFÊ'õû‰ éLØ*._8,°.j)×;Ñ1&™ÏCtÂ#R¢ BŸ¸œsX—ÞAÄ„<¢?ŸË%˜P•/¬°K´U@?ëc28¬`¹–Tö’EÔ‰PŽŽK ©Pƒ!•~^‹Þ‘È•E†E
+t‚Á /Œ:ºŽFš‰ëe_¨’vòìd!mî [ÕÿáJâAÂ>“
+C°—Né]ÆÜü3C&SJjå*\L*¡èdXd=èE…dÆ;Ñ´úôþ£ÇóÒQ¾H Æ,(‚¿»"†«kæåÕG¹ª±äøWV^ÎA•P‰,/ª~4RH tá=®ø£ÅSáløÀKRؽž†͆b–xkì¾&Ë™ 3‚O&["Êñ.òDÞK›O ø["ý—C˜þæè ÞjlK§ã–\jÑ
+ yÆaõÃpÃÐÛP"w‰aj>±Ê2ÉÕVüÚ
+À6¼.9n,!Ö‹¸¼x¼ÒâŸÑÑa¶%2W†N‘‡ÚK²‡|8jBxé9ê­k,_Qœš›TXäU @4Ðíð©`»$&F¤^D3ñ™²Û9‡SI[K6ðÀ†ÄÞ“øŽ(¸ÊÔyßøÇ+¿0ÒŽÏ uÌuY²ŸQ„”Š?L¡ÍôðpóUJ`Œáæ.A#Ác‘¦c¢zÄDKâR4Kæê/¸C.Ê­óeð¿Sd—ÆŒÍÂÀ(´¨]í†ð…ts½5æƒkÙ〳d\ÒݵP¢“ɯ¿J« ‘ö£ä?v‚)ý c[YÛ˜úQl$¿˜zV;/Fêòœ[”º6’T†7;KŒö”†Ûéc{ÇK…F
+Þ¨KƲ§¬
+Æÿ Í}z q¢0]0^bܽ§ÔÃæ î4X¾«ºüÕï†YlüŇàŠ>¡3ó’ ]‚AŒX î"æ!lpμ•<1Ó/E×"Tˆ é¼ÚóùP„ù•9àñÎL”$åîÕB H䱸‚´ ÈŒƒÚÐZp„7ì¹c~Eÿž*$[^‚›`º%–õ‡Ï£¤`vÙbo ö^Χ|)‰A IÌ óÍž¾#Qgù«åãC$~¥{Y,7%%)ÎÚ´:ÇkcrÂU akˆIÙÓaÑÄíÕ=2¬41Ú½¢›8]*È7~ľ€ˆdZº}>éŸ(üµz€ÆarZ¼
+–âh~9ìÊ~ ´¿ZÃ匨|òÙ*­WXî&ùå¬VÏ«È”ZWŒP¸¥Yh¸}è˜}ƒ•G˜{<!ÏòCþxÌ–¶ºKAÆòyVŠü†,áúÝÿ7ß^KZáÿ/·)ï‚xÙý;P>¶Ûp`ø‡û±©H§—ÈõAß,x5dž­Ï!hCÈ7µ|¥v‰>»…Ä b+!Œ©H`ˇ”%è9ŸIÒMìMåÐÍÿÝŠä„Š¾àMÃ
+^Š$6‹±ËmÄaØx>/«RfÛ-Ãë3®Ìöc¨±rAèà¹Éòäå\çkÍ/Âúù'ê!S`á­ (§Æš„Sý©ÅETåië1J ªeÊp‹}¼Ï¼4zib÷uƒØ*d4€¼˜ïþŒ+zPF¹æG•˜Ì »½þf¼L’ìÈq zÝ០ó°ÎZêÚJ÷ßÖsL“"Ò¯.Y›²$pø0òã½È ù#à!D“R»ÈÉ^Ñ%?Ò¡)u‡SLÍoù‘H £U—÷yéC,n@ ÅO·aÜ£Ÿ.‡ƒybJõ)A*ì% ,¦Ñ-Z%Œ¦`›q–ÑL0Má.Åð”!¡œ&1"¼gH`ɵ*£ùò†w/CÞŠ¼¡‡m
+1ª€ö´H½’Fsu¹ËYÀì̹Šrr
+Ž>ÆmY(*Ê\7£ƒ¿/¿>¶¥$«¥™ì½Øë•Šè9Q°üüæ-Ó
+¥d´z/‚ü4s,9^Þ“eÖ.£€šûéM±._Z¨¤Ïê˜_Þ nòu¨#ƒøDñ¾œ®µIð· iJIŒÙ,% ¦øŠHp³< ‡6© ¾Û¼äK?ºø ·¹{ïÛî]ðó›·ÅŽLê³ðºL²©cjs{\û¬*ëÓ+ÎÚÎYÔ"Ž.792©&7ª0þãè’žzḠZRœnºÓ‰RAgŒeçð=áR?¯O*d¶lÈAˆy¿bDuRÒ)~—v`Ø­H‘¯´³]ż±Û|y³a(ùÉ9]¶È« ‚)ô-“^æ? ¥ðÓ=Ï[QYTI‘¡?—u,3®§ìì
+dÙJpô. V¢«xSÇ/ä·x%{1¸ãbVI/owåû—‚~Jh_ÿéÂåà¦"`Ý’ÐdÐ
+³q¿Ü¢òÁœÑ ¾q¬«+rȨGIÐn@PPÑ@JÚ%K0&ö¨(óC¬“}>Ûµ¨1X‡hCæ†Â•ÎÈ
+÷Øq½Ñl Ž\T™À´KŠLXÄïAú£d]ÄWs´A»ŸÎ™rXëqdŸ¼—ð¾Cd¤Ú
+2Ôb|)Öðõµt§ÄºŒà"¨âLýzNÑ +› 'ÚkȤ0v. _Èdóù²ü UJËÐv0õ¥L
+ìÔ<N¾Qÿt]6Šo è´Z†Ÿ’à9èTÇx [PJÑ°íñá˜¤Ô Ÿ²ÛñD¿Kغ¡Â [’&K·†¶àøŽobh‘ V˜ý
+ÂõéãÄ”Ð@Ö:S„Ü$™¯‰Oä>i…ùpþ1Ó\Q xqü%þí¢€¢R>á…ß´ êËeõV4”‹"–=rÕ÷ýÜxb¹™Þ.ò²’S„†Adq7ˆ•\45æ®@ÿõ]‚5§‰M{ú”•”
+ƒ–$…scâ}7sÄ@†½.©M§äÇF7´Oç0-Á©Ûk"„È°ã.‘Ìܾ<Æo¦Ðn‚ÜÙ®K§9JW@¡ÝKͺhœX×ÚÊÚn´ËÊt2â1—ŽÒ ¶;l
+»9C/ãƒÅÆ$éAïÖ\öïç;Kj»Ü?J¥kÈ„õ&ð4õ[ÕÚÞe§¨q1xÂ
+¿vIÂ7CWuï)%S $¾
+-«xµõ¥íõ‡ Ò³ÁS„,Mrkr€iq½(J87Á ¸@„qœŠÎS”òXº]BØ :mí¿”¬›¶õ€€#3òÏAÇÑuœ¾L¨û*hsÒJäøôMMÉÃR õ‡Þ´åÆßÅï°SòǤÎU×"PPrãS¹ì忤ÂÌ<¼æòðU ·)ˆF¹)»êÖ4½ˆ»3o~ù-Æ!€#âi&õ{…Aâ6ðÛ)7Ð\Ÿâ€ïþIˆæ!ËÒ‘—¿
+¸t˜
+@G†Ad´Š‰,Êv’˜6ÜêÊ 8S¶ÈŽQBcsQßçTÈ&²F}ÓúôÙSþ´-ruÅRì‰Ä©°›B¸>Cd˜-+R²ÇLLø¬‘æ´—7J -ûÛ·ÈÝŠ.²Ë›B¤ æଳ«rRcoŸ…é׎ÖæÙðÝ?v>³ä1x&Ü>ç;EêùéY‰bæ´…ÁÌlòÝãÃ?%hh—d|Óæ3»u¹|ÐQ> èƒÍÎ#Ä2”Dںϑ©j˜^Úl¸€‰ù W•§’ß1úùÍ«ñÀ^dhC×4æãÚÜŠ¼¼]÷VÑ…üåºÁ(¥±o©(˜·«ƒ§ƒÛM0™Ý`›ÀË(Ö„X_©EZá!CÅP.™ùœCí+.µ]iåßnûõgÁ}O ŸT~ÚswIÀ9¤NÖä ó1Ñ âÄÆv kjfi lCñh õZãQ=™ׇ_aÌ·‹¼qÉ *éágüKÑOâdð_k€­Þ#%Á=$]d M'Óœ‰Ë¨»ÉœILˆÌ¦»éKs`D˜¨¸á‡8“ ‡SÀ5=žSe¿ØgøÎJƬm$Úf–¸øòÄ'N„蜫þŽÀÔ×”fM¢Ø캆=K/¸nüä×.bëؽ8ÇèNÑ*a‰Ú JÍêÇ+J8
+ÍõxVöw2xäYÙ«ÞøDW¥ÖÐr­Òð³úò™, /és Ÿ‚’ôiEï$ß°_ÙfšÊÔÁǘ4^­ýØîŸnLÜÅÿõ]¤XÏÎJ­YÜKòrKü
+Îñó›_ó³ŠÂ]ïkð÷"ŠŠd‹}y‚]~&þŒöä$V9ld6iâE<Ÿ~4DUBPJ j [A<[$˜…â±7x¨©"ÖÊÈÍ'*¯ÕV„Zm&­7"ö?ãerW’Ä` ÆY /÷å¬9Žs¥ü¿ö\ªY/#¥ê¾"^n
+ʹó³#L¾!•Ð ¢$Œ-Ë_ŠIôCBxÃø»¶)øXði®C“H›ÝJÇdF}¤Ôïû‚tNªs)u²ˆÁ…(XUG™ëˆ;4,½ì­P90ô¸¤0Ò)aÒ‹GJC|çaoE½õð*òlt„¶@›ý’Ë
+¹°Eïö2Ø6]ÎwL€&y⦇Ᾰêf†o¤¼ßïûè°¾#ÄÔU[s
+ A‚™Új‰D‡#!¤…zÁ?jé¯cA°
+²B(+þŒÐCq+VUˆ8ÎuòDRåWTë6²Y)<¦”ö
+SûDŒ)¶ôµì†‹—Ö[œu8@F@
+£µ52¹ú1ÈJQl‡A)Ÿ®Ië8– `NŽ Y¾&(©‚I©Ío-ì*LO­æyÿ‚qTCÆlE¥2`êàÝ”Y£¥ªèØdƹ¼ &u]¤o…'09$}ñÃâWÆؑȸ·ú3 G€Œ˜é <i<Ì&,¼=û£Zú§ÁU@4^Åj%NØGÃÄX-Åw¥/Ÿ0Ñœ}ä> ‘{ãÐ¥åYûB–ÊÒò~!J˜Ev\ôÐN¡I5&ÏN º!WD ñ¢PEÙ’<[Eû”¹CVÖ@À]š÷2@te%/1P¥<OMªÖS3ú,é hó ôSb„·×C‡´!]2Ï%8ÛÔg@UÚ‚Ä(6Œ'”àÔFänÃu€dª°«6%¨ŒA Zâ×+ÿ¹¤S¥Â¤‡ÈÝÔ;M›È!Zˆ3“á 2º ‚ÌïXZ˜
+öˆYÐ,³hq˜!¼ymGýb&ÉN6„'¡É6!•O4&$´vÖ5*IñQ áû j©º”Ó˜CA±%Õ8Z^aÉÒUÞÄù‰Àsd:¸7 c#¼×ÚéºN‘·'F¸–.gÉüè„êâíJŒ(
+ošüìŠói€ pœpSí6 o…Ú[=A‘†%‡3ðL]1Nƒg‡Ì07ÓåV …?H}úÞêxl‹È‚›ræöÓUÌ1ŠîéR©ïˆµÑ³ÞE Ê<ObP1Aá€*£:Ì.þ°$Wq"ÒBêÈ[~½úŽ]˜G‰{†ù®Ü¿çÕ©£cXÍè&È’Œc»èë“3MÉð•Ô’«'Ávg­õ{‚C³$oåyV!ˆ’¾ò l€JÁ5®4RÈ­¨//šd º¢1á‹<lÆpßPC|Êú’.qlÚS);Îûΰ¥ØɬÙöpAŽJ7—‚2bÓ’ù,&Âq‡¹#Q®ìbηuºËšØ8x5O W
+Ð<x¹UÐB^ñre{ØÂ2 ¨î:DÓë‚T^Ç))­¼G,hȃXyºà²¨èÔθËßGÆDƒ»†/1þèå¿. Q£cíôV™/DC¡lÈd 2&(¸Ë“¥ !DÀ9¤¬z–÷´šWDä2zÒ§1|ih90„ìR0Pùv÷FÕÄ‹f :61! ̸¬D~͵hõŽçð\«5Û€”J]‚׬µîDXi±R³ÿ—ƒƒ_ü¼2 •'eæ(-ÍuR“S Ûª:½Îy$ЭÓ$„%)ªåu4³7 9½÷AŒdÔ\íG°dmZý&d'(È‘b*Ú´$Ã
+Éfõâé§Z‚?ã.ÞŬÛJ§#iú«w1¿¡EÔ} ö:ݬó5˜"‚Ù %‘DíæzŠü ²(Æ U)¹­†+!òè!ò‚àÛ»­¢"„8˜k…„ÅÔx^Y umLR#ˆÀìØŠÝëLœ=wIx¬áF jÞõ¤Ì÷u<3h/¸rŠ¶Æ§q¥Ô ñ¦ñb``aˆ°à©ñ@=&skÉÖx (,:ÈÜn€¬’ÓzÒܘ<Qôc¥ñè©ñÐ UjrÁ‹Äù×Ðls«/3h¡.Õ¢“ÈÕã´]ЇÂû‘CÈ9—›À?1ÖÓxhàð6Æ©©],}ÿ›p}ÿñ_ C¶x@!#}àÉ)H˜`oÂñ¢ª*ÃL"É òô
+_3³MCje꜄ÞO\°.ƒ–²2çœ%£oyEš‚Îe’˜ª˜ûrlë!Eî ÕõC€ðÒ0Ik ÈØŠ XÄ5`h@ r_F’ÖÈdìu˼ èmë—QŒ>©ªŽþu”ÞAd¨]|m¡Š ø€0ÖÈüÜ åaûænyM·b^pýqk•ˆ:x|6$”e]=ðz™Úò“a˜hAç:Ï’ V[¨4ôF(s+^™“t–n;|¿AVA“½e†¼x[çQóó4OêX—:x>ΓÅç Ÿ½ðV¨ÿÐ/ê,·;+h¬u‘0ßå~› 2Žø3®—×¹ªvã°ëþ¤[$Hê&ÆssßÂÒ„ŽèaoØhð¯"Q2׆Ԯߗù‡î2Hbaà ú—ÄìœûþÿÜ•™8™é%U0É=[Ñ5ÑâË¥ôÙõ]Á ½,Íì3\Öc b]nC¤$Íᵤ;ÛÊ5„¸aÙð)ì\»7¤C+a£“R˜ráŒS%adçÏFႨ¤ÐfñìÔáú€9§ÍßÏtëüo 2"¡e CSV>ìr P<ê„4çPîS7šYzðŠHi°hÚ¾¬ë”ÿn2Í–jÁf:eé<£”ñ°øëºSð'¤Áš{yY•7H±GE‰}¸
+H‰Œ—A’[7 DOà;èQI
+æu™l¹3’6oe¬ L„¸œI|O³m·Wò€½•;҈Ƞa— ÔÖðØB¥=1tI¨n5+ð PFz?6“ˆ4ŸA ¶äéü²ÐâÝIvÜ÷C.ê;Рà1pVF]ÏË“zš¯+þ¦LùM8
+ä‘ËU ?¡2¸Ó¡ó½˜wRÜ[:FêbïÐçŸôwf­Ûßy!~‘¥x~?L÷Ïa“ ¹6ž$ !(8N[ÜŠœ¤8!ÍxóÈù¹$
+
+Šî
+R;êNT«ÝV} )–ÎO[µK÷…|Š
+j}Ë)æí®•èö¸‚X1ÏZS&A^¥Ú˜êJ©ºÎÐhkëýµR#µI—¡ÈÚn2 !lUm;±Ó+Œ&sÕêÆ Dgò‡eä!k‹P™«£øŸGÐ+3äQGD¼Ý¼ÛR·dOd<¯·Ü_¦U«\£ñDjBS+ÙéL¯¾‡P2ªb"vJ^‡Î¿&¸I2¾Ò#ÌßãYÐêz¯8Y“¿ÄR’ÍTOÉ©¡5WÆ#žV8ÒÌ÷“Óž²^7 ‘ + FY31f HGkeÓ}85H7TÛ×бÊO‰±ý´?¾Aä/4׺¥õ ÂYá…Ι\¬xå4[š¼­V‘æC¼ÙN±aÊe””BjN kð ZÏöSj˜Ú¶J³Z;E‚5ãN¤‰\ëÕÈ&…f.%
+±9¾;;CðHu+IAâÀ}+ÕDÏ¡­íá„Wì3#»^¯«œà*5÷®]¾ižÊ,[,©9õq±ëKÓï¹$ =ñ/cX3Ù^ ÉWêŠNHÙ‘±ºÉA=D“w!h­©–Í÷80/èx.‰gýûŽÎd†¯S§À  žìýç™Pähl ý Ÿ #·)†tŒ³\Ƚfl2žuÉÎóœóKs“ Öµdö A#²`
+
+”ÎÙþôºÑAõwpI¤õÙe©e}Ø-Z®}|¤­"2”MÒ‘írö§.A¹œ0?è÷9?½ô"¯ît0WÓØô•Æ
+%"ȾI…3ˆ¶ã„™É$žö¤oR†0ýõ‡†×Mÿ×Ly®»v™#ϱtpª:obÉ@—PNl (>·zÆDY«9]heìÊ Ö \ƚͰrZ^ÈnÂn+ z Ø¿Óÿ¶£TÊ~B0êW¬)~Al(k¢=µªðì¢Ú4!Lxm¹k´|h ·¢:y„fÌP²%ÏñÚ|,Z PW—a$zß’Gø»!œS9 V(cÒHÚ Â8ÜÍÒŒ„íª`*3º/uMs@\¥,Ó}Å(ÃÙXVÀÎon†Ž½@Ÿ 4W‹T¯Ð,³¹ÓJFwìË#ˆ… º£-ËF^†íqon‹³€š2·œäuúÃBÀÓdJ9ÜQ
+ضß.h*ùNSß@4Ý,IB5®«^@©3lúœ
+(ûÔˆcQéªgþŽÈÿ- ô+÷ÅÊ¿2ì‡AÛœ·ñê¿M“B¾ÍÝ,ñ铵¯L¡¥3Þˆ:9O
+¹‡bhD'öÅMyvÈÈ äýº‰Ðí©xCÖt±v(Ó$—2|5pÏP—Áþ<@.ö8fÁ¾X2ôrμ)Íà)ŒgdújóQBÅTþ«šæÚæj±¯‚ äRèE·"[³ÊîÓš’†/¤"Ûüq‚²=·ú’M(2w9{\õ "^ó(e_±Î„ìX$ º'ÔèÑ®Mvχc'¹ó¸éžP¦¹@)cÄc&œ )Ùò¯!?ë_ GulªöÜ$2þÅ‚ Ä"XºŒÀ;  “{‚¼“§/ ïGP. „å\ñ²>Ÿo@ŒQ¦¿ä Ií¹ŠìŽ]R‡š‹i[½¹5{$
+Ë!ï›.i@8¦Ul_ ¶|§sPœ?v¶Á¶vÄQª’Ú0˜¸Îýªñ"ø0Staë‚)óƒVJ@SW*´AéÛ$´©v/iX·ÒkðQ6Ü0nœ'ˉ—"D˜cRÍjfoÄŽpß4£Ä¹ì CÈ5Ãíÿøð7¬sp•ç|}”;Oûk.Eßäõó ~²¨˜pGƵÆtXõ?VDî<{ž8c•°I­#ÏøÉc†¡$!Ä£ÑÛŽZžwþ¶›0´MÉ¢nvbÓ²d
+ÝÃhÌ$°ÞO_8²$v§œgË»* m Í3Ž ×"Nk×Â
+þCR[ç¶Ì2a`)"šé%ú
+›Ü7 l[J¡mû¡¨³l…iÎŒ*~{üf»42Î5¹¸LB–Õ£Û(¢&Œµ-¨ˆx—!òLgLØ3H³ŸBÃùíe–¢lK]ƒØc ‹ÃrC?Y.ÄóB¦íÓEð°8n)|©ýPâÀеðÖx>ìàZáPlá.QЃtv¢Ã®§é>vÙ%bQÓÜÓ¾ŠaArgà’ŠŸJìì0á\NÅís0>¬9C–âŸ0H‡:ƒ¢ÌÚÐ@º›ìEsRá—tJ܃¯vŽú@ô4
+D9Æ,ÃW¢ê
+—ó‡v Q†.+smX
+6ÊÖe|8¦ä(“–]NÀ‰Ù0 fTwE(0{ qþQ40çäÎOUè­cì›H'«ŠMñí‚àpGá•Zé={’&çÉiìNó¾&¯–nÏY7 ²ß£$°žDÜÜzƒã£œcögc¼fsü*\2ö'‚‡±OÀ¨©Ë¬Ú9$ƒdÊm‹{J•€è§› !è„‚}Õ¥ áQX‚`ªÂ×0¦%}rÑAv4ÍæhüÀS¡§ÔŒµG?%h{ýø¹Óê²CÊJ¢Sþ¢9TmÐ÷ø‚FÜ(½‚²óW”…
+F¯F=”lª•*#cñî”^ÄOx§¾mZG…µ¬È§•L!d²0Å/êhÂÚ]ÓÚ/I2Û8­ê£!¼¦úwýÑHX‚;‡»NRXDÇKàs’iˆ{Œ(}kÉrêµH^}äÈi5ÌŠ˜G¡ìÜh—ej°ÄU§}"v4‡†ø'cæ¢>2e7ïÀ<tƒ«ÒþžKÑ5“ü¤¿Oö”öÇZµ³#æÿ±"H˜Ð˜ié «D$`'Ù˜ÞozÑ…Ta•„_“±»GYh°DŽŸ
+F†ìÌò¬\Â2â©y æ {Qèt9
+‡ïÀ)"EÝoA› ^^vŸ]ÀŸÒ¬÷ª_Šz†‹˜$4SmÕ¤ñVÑÐÚc{ ó(^ŠHz€SCÏ@Ç÷sy¤|„g?bƒ|õ}¹
+Sj~
+|PÕðØâcTüþ¥nSòèƒ-,6r¥7ä2ÆßƧ{ Nx%~ÛÌ7ßïÎa˜£Kç.á‰Ô `#;fÞ#ãØ·Tf‘^ÓÐÓ†E’ëmD"ËHl9äÈR€¥è¸(°ÃL÷9xVxÍ–
+Ô³OÍ*ÈfPã
++×
+¢_Uç.uþxÊ ˆ*+V¬tÜ—„Q :­Bùve{QŽG–È®EÏBQÝ´JÙoõ"OÁtÀ{ÑY×u¸ÍVÿRôý›
+Ÿ øjtPÀÀH„q&TJ²²ÉoˆY#å ±Ÿlàí9ßÿŒ—=rž9„Oà;8žÀÅ_ ·fB§{‚©Íäpï¿O <Ò˯Vr2#·I¾@£»AìU˜ˆ×àl|)Éd|¿LË€)q­¤Ëÿþ
+ :YãLÝ&BYæE5'ÐV8²Æº)+£güô½câk˜¾¬n?ÂÀRªÕuE>Àé:jSµnìg³‰PÌ
+4-¾ˆá!òKÎ= ENÒÉá˜ôˆêy~ÎKVÚÂïÄ«Ù¿ßæw^
+¡]‰"$•]‘·!`Xÿ¸€Þ”õ ²ÕÚƒ[ÆD<yU|:3MÎ êÆe2›.“†ƒÉ¢€V[þU[)£¤(>:’Ž—L9:Î,ÓlmxÓ[E¡ ˜CŠs`½O)Šülæ?ÑÌ$Ug»R½Âì’.LêAL©ªv˜¼!O³Îe3j—i
+‰¤%'²1›OQVÜ<!)ýÀIy—œ3¤•w*Úò¿oHe¸° ËÛµ¦ŠafQìæ1`5tïû ù[WÑYEa\ïãÅ9¤ï¶+šãÉ ÷ƒoš´€åÈú8A´ìþÆq+Ý$°Gužš¸ê§ƒðBèm_)ÍvmhÉŠ"^@ WšyG¦x6
+V1·¶}‹Cùø½)(wG°Ä¦½$Žêäγd§Š
+MüQÒ·ÚÔ Ó©­†€ví…B! ÏöT Â6µr{"â"¸mS>›ë‹SøoÆŽ«¶Âè)Ofs”â ‚nàèì8纔q¦ô:ÏMÔªF­Çs ?ˆ ‡L…™ št÷0dŽË ±2 Ô‘=`µë1²ÅYñ
+¬ÓökŒ|@'RKanH²ÑÎÑýH‹Ò¡Ï1À¸®iÚåGtM•tu„a]‹‡ÙQU~‘I{› Z„£¥W›ŸÃ©¨;TZË!ìt”Š5”R9d•¹ÿÐWo…Uè‰OÌߥK^™vŒŸS‡ž»š‹$E“°]Þ3±:k§ä1í¦üꉸ‹ÒGÌÏþƒØ)ò×êšô
+æÒ²¿¬S&8ï"2ŸdÆœ±ÄÌ"{÷ž’ÖD*‹ Žpš®…Rë¤W×@Ye=f˜ˆeGsÛCÊÙy0WÖ®xp^SéÍöoöU¬sÍ•
+ Qg2íž=ͼeæc•¨WyuR²?³sÕ§D…NP[Â;„[¯’3$M´ù¼çsÂ+N-k;z{²£¢¾[] P†„=‘‹ö> 1º:)á!~Hf“dÌ`E8Z¡¹¶X0­†>2ñ„Ù×a„rçBå9e½ëã(ÒÚrC§;,Gâ{HñV›L\q½„8ØÄ!Ã|Òj‚DÆF-ñäjýpBR¬ìq´é®Ûbà–S«Ó.G´¤á+i#È™m%4ŸMƒPÃÏïñæHRþ ÌïP ù#»æcíøƒÈÐç°)NS{™kõB%) ­ýªH«—T ¸òð'ÃKúOS¹¬­®$ô‰ž`”* ßÃÉxÔY7ñHµ¶'YE8=]b³ômñæ«Ï”N¥…00©6_m¶ÚÍ*¹Y÷sà,+
+áAlŠÓ²iærˆ¾¦WÞQ,>œ"`nÐdžéÕ°ÒJœbž¯j—¢`k#ΩÑ[Ë!äô)Ó<Fö
+üß@úû[ØF4¥|¹ÅØé3å£%>›OY(¸äüTøŒ—Kr7 „O;ø.¾kg©[d+Ý›¯ ð—5ñWR¶Ò’@£Ñ­ *Š
+~›²CVÙyyp[#Ö‰: ϸTt!z¦v
+ ’,÷ÝŠ¨­l¨®¹¼¨vè’—Ï"Ú†
+õv<ì[ ª]d ØŒ\ß&ãº8Qj¯òRu7>q9nœ—C€ù¥®å%Pëš5–Î˼EE>ªGì4­ä¶©JÂirJ¶KTeuDjSãâG!E¬û¢õwþNG0±“ µ¯ü…b‡.p_¶x¦~ŠítÅP– Ž\ÁÍë«ÕÑàZkþ*ÌÑ2ÉA¾ŒÄÀµOùÅÊ7HERøúpÀÐ"2/‚QN I’v4¿îh7e§qÆ…û„,H‘ñÝûâu­O»UÊ9MÍÍðGÉݤŽC1,3Þ“thGÖ
+ ™+; ~þúç:1½®pÇÅË~s½Ûaß]Õà8VWÐÛ§å—Ùéò8—yàë‡ Öâç‘Ô»Œ±aƒ§z`ìBt]@LŒc÷„I
+$ ìšõwÖ
+í59µ|€øQú¢³¥=}‡ö#–d¢°¿3Wý¨~õ–ÓìÆà":^8H]j¼xܵu•‡W}bH‘Ò-ƒ4 ʃ(5îŒu*U3p„$ BbDe¾¼éiQ_ZN÷„ƒªæEœ~—H—˜f û›ðºèÛlyúèRýŒCCÒÁ¢ø³)!Ç™ ¥É’¬áô£ÔíØq#Ûêà†±­8Ã0÷^@:c„Ž€Ì‡³ºöI0HÚª˜çF‡ÎͤYYMíîhFTÎò<3=âcÍÇn/÷ÆÐ d ,&Ÿ Ä„ÔówX ”¦Ë½804gTW´\‰Â`¥ZòÂ0<dÍQÕBë„5­» @0ßÌ<×¾Ó¨\!½´Ý'ì]Âüw¿
+?ikíN׉À¡„H¾}ÿ ÄÀk…€#üˆ<•µÃè'·×âeL«ÔŽ®;b¤o¢ŠÑ—%û‚†kz>}Ô tÏ![»ouѱ/±´Ç"›ÌA’¯ü0P™1ÁâšÕDMɉ,û²ÆœÚ¯‚ ÈÉù^ ]ÛlÁ ÷Ú ì¸|€¬¦Bi®Zvç¯ß lÁQ"]ÕÜ»Xð(„ˆu`^€kKÚ-ÞÔ™F(ƒ×ð¹•'.Ÿa­RXOß2ÇIÚª¶‡âúz'ŠÚÂnDßÚÊãibƒ/í‡i_uĆ.‚ÌÓ”Z·ôIÄsÌô4ÈQd6FÊÖÈé3ˆW–ÈuIl²›µ9/.üâá¨`ÍÆgŸôg~†§ÞÙAΕ_ý°”> „1値Æ7$·KÊheóUqÛ³K§A¨"FOYœ¯¼\‹`ˆlëê€Øó#÷’x€&Y„2áW¦ªÔÛOÙÄ*w«±‘̦ùáÉ!;$ÓPŠ™Í]!ûl í͆m®>¨6A­t^våwÐÛH¹¢x…e´HH&Ñia_ˆÕ
+]Š[M SÓ"wÞDØ=Í_´õ?;ˆ¹€5’èß‘«¬H~)Ûw04«{õ瞆  Üæ4j>¸n§GΪˆÂA=ZóÕ3>?,{ò¡%ÀðDƒ4I³–áp©r]ì0Ö·y(@’9„
+2GpéÛúŽOF½†š"Á,Ág¢D
+ƒ+Êæ³îø7-ýµd'KRß9܆_¬Í‡ƒH»pI–þ ïjüE–-égÕéèŠhêsŸvúC/)#'žòÇjOAz"¶¥å‡ïT¤[9¶l'ÊÖèLöÿŒ—K’7EW =hìAÿŸaGM=õ
+=“†½ÿ>—_èe"år‡ÑU(& \\Ô:g*„¿ä73î1ÉÖÇFË 5ïŠÝ‚<ˆd3˜""¤·/±?2Áh]0-‰N–±=àãw†x·fg5˜ÇhXh[ì`Ê`‚d«fß™ð.
+ñc¨r&KÝ|pþBP·R0¸i[fÝeW‰uVù{Ý=Â>$žM
+¬É=…‰Yµksú˜‘µ4àC"Óó¤ß½ûÇ §ûzogøe0€YLS¦} 5µÑµf/b†ÁEËõ¦…pìZbŒ®Bn@£Ýèó›äÕ›ÁÀG ÀíqG¹]ÚïçWzô7ÀÖ° Žúxì€ð"SMX› Âé,8}.®<›Dƒ§rBn€MШbg|{f° 鼂_SÿæbBšŒ¥–¼½ÌlÍ|ˆ®óW³>¶tlíW°Ñ€J.aǵ{eˆ"OŸ°#Ó<ŠBhßòDØX¤ê;´)=Hkã3CåŸé©X.úo„D\±Þ<x6}DM›4`†æNU„k.¦>â¾6!¬^4u„Áêa”
+}ÄmH¿KØ„DÀ$Ö1l„_ Û‹¸ö=Æ!l/è.Å$¬ í"6EÃö9‚7,íÝE߇%UHðî0¶C߇ܭðÞ°ÔÉxW¯”âÕuC䎕Q±Q/yÑ`dÆ?!6]Àþ
+'ñïÑü±éòEÚ—\Ä&„—ÊÇxBì[CÏ÷,1è†Ø^бeu,_]6
+%ÐGl/ ”£xº„õ´Ò
+în@Ð
+Ã3~ºAIW¾>0À¹J1X
+Yp(OhFƒÉÙ˜ù\¼ï—é·*Óx
+A¿zSŸ¤µÖrˆ÷‚Ù´BŠ;ˆÙPmß«µ)Êë²ß=±,F‘ì×8}*uöìE'ä4*ŸbXÕêÓ9°ldmìRód×)Â/³ft¨é®÷¥KæÄ@è/ Òpô8%M;²A&|?˜Ø»t@ªÒ–Ú?‰öB.áØ`šö$Û˜0ê6(€¬õ´ƒªP{¨Ûl
+êÊ
+Qš(¸È}]DÃœ"+‰Ö *2  › ‰Ë×¥¡À)¤Ö¾”´ØQúGÞIt‚X8k@ÌÈ£Ól² ‰4ÕÒ w)ÍA3G
+Ùð#º¹Ü“sSÖ=ÃNÈ[¥~|EƯ ƒCY 'úãU·ó~=%V½9ÈÛX"ö@•Üsd+YÏ'ÆôÚt©•jÍì­B¥ !Úͱۂ õx‚`¶ÂTÆœ’Õi³Ùð7Ù+÷Ê;ãIBÔ‘¯—ýsàðAÙIGJÅ¿Ì`‚%”J£·öô¨“˜DkÉbM…ðl?ÃNÄ[¡>¿yA—Âÿ|Ò²ÈÇxÊÈß½ã<…aÏL£+†ûò–§ÇÉÔ+çå— ÂfÀá
+LXz2‚ªnÔç;-jN &Põ×CÖ‚P±7ÿû""ËjX¶JHË€!ÝO…õÀTÝÃÂmB¸4 ÀN[Šƒ„TQl±í JÖ…¤ö9‰)IêK^üCHqf­r=ï¦và×e¬ÍóbŸjL¬7µUw÷œ®žlõé2âÖÛ9=?jÊRL~nÇ›h¯êgØ y«”Uý=oBÇYr­vã·ËA‡áù­i-ôÞD;dB!„pÞô–bॠcQ–iÉ{ϯBÈ.@ÌßI¼×éb_z¯·{λjÜÛ¼«Ï}ÔUÅNr®½àdøßzês·…<çí.œzZ¡Ö±ü³· §zŸsˆ÷_ïd®ÁŒaÕ6;z7xäiUt™ÛÜWw‚0Z-)´¯º2³¶0×h7³cAÚís:³
+‘ÑÌAƒŠZ·Lp5 8ÎoÙžþ‰ù^(U˜AnÂÆâkÉ“(\ÇôÒªWFƒYz-2¬CøùŽ«‘ø2žZ·*â ¹dô=R±Î¶äâa[€g2ñÉò˜ûœ7 
+Ã9yØÅ~Ž£&*h0qº}ƒlóC·‹ GÐɉqÆ!©5ãystîYóRoØ~l˽æq
+Âj}úÎ$¡
+d¿@…¥Šäæ1S¦˜­J¶™Æ÷cfñÕ„
+Ù£>ÑNÊ[yZTƒFÜ#¦•õñsÇ¥BisC6’Éàö§]ùÛA .2Ã^èÛB¢¸*Ï-± gOJXôíj©–#ÃèàRbr;¦0‚ÕX‹Úp¸Û*œ•@bûü;Èìéþú‰>bR9_{ø ÉبŀaQºËÙ $ÓiïDSÍPÁ}L­±ìµæʸð¢â×µsVL
+7¯, Äätøríí Sñtm6îÊIã,S´•B‡Ðó“9y"ÿšBìN2Å
+–fS“e½ê
+rRh°GɾyÖJ9ر-+R=¾J$ ›4È,8~‹£0ÇIN4Ì7F.Y
+ ³ðý
+•N‰ýFkp[Ù!T‡éÅL­ö&‰V«,(ºkÈJ‘°Sµ£c£[ ;‰+H,ËX§ð$q\J­:„L¦U™Žˆ/ç.tšâÜ&Ïý3­3Äp®l9{A„²j—©k@¸½JPÆÄ!E7Ì© ˆ"Ôšì†òÜÏè0`?NN Žâ[púÖy¡?-ë²ê¿@,n<‰±Ñ»Ø*Æ67O@°°¸.º.7Ž.ÎçË!l=ªÈšÐ–øò£0}årý#¾ƒû`,@yê2Õ0yüÔÂ9D.ùÜQ²„‚ÌÌ+;½C®£”
+Øl
+jöð–¡ØAÏómì³ÉºtÕ§W±]à
+\8WÈ`â˹ÆÈK¯öQ/ úÎú™ò‹h{\ùõ6@Š[ñ%9½
+H•ËJL »fõZ@M¼É;¬(àkòuU\§^½C‚¯=?~ç•9‡Û¼3ðøªw&ªó>‡ÿ4WîÔ
+,Úg+¶î¿Y.+µ¬=‰Â tXÍ÷ãNÊñÓ¤ü‡\øÏÿþãÿñ6ñ`4ÏJ¦¡¼Ø9ª–]DN &ÅR¤°j¡ ¬–äÊ5 —(Êk:£I±È»2æ}uçËâhœèÕÂ̱•xîÒ©
+/ô•µÎ8]äÔ©Huëøý;7ÞÜosãßéU7ß‹s›†{‰ÿzª\B ©žœ•§^2ËÇ“ep0>|ÐÀ¥ñ®„ü]Ì
+\1›Þ) ­èj¬cj2•
+èøZó!}A.(JEûjGS'S`äóû6ª]N%­ìQ1÷ óW’P[H;4ÞG¡L,ô»:Ø EâÃõ3@â öÚ5HGUŽi½!ôŠ:á(Äê?c|©ç:ýÿ¯ûÿ¿å)\žËÀµº#N[ê"¤8 `HË”
+H[yi|‡^ÂÏžˆFM¤Sëh†,¥"°ð$ë›U–Å*%¾C¨×j[N-ãG¦–x¶Pൺ¶(v1.4ÿÏx™dוã@t+^ûf\5ô.j*ïZ7@NÿÇïÔÉAÚ2ôHhR ®_`ˆá§kÍ–`dPbøÔå ò_Þ™—/Ê(1ÀönäIlÂg×0Ž¾”ȳ »ÁƒqÔKv,kûÉaøßYL›\²Û,LgZ[›è š3_f<BáÙ dPó‹þñ;[B²ºA^8N
+ûqÓÓÎÙ|Fy£ Ÿ&íçúÀÝ|ËK‰£¢©ŸÚ»Ïí;ü ž5ªî£ˆ5‚kלíñ®IiúÃäŠæÒ±X_„Ãס÷n’ÑG©§§‰q0E3Jrâd¦
+öR€caH*×-F‹ÜwòÄb~Ö|zÍ’bW«¢ÅÑL¼Æ ÑßN5ãß
+¨^Üáÿl ¤QFmÕ¿Ó3\F”`«}’á7¥Yo<Á¿M\àHŽÆyJ%Éäú…Å~ÙиԂŠ ao(“{²’•öµ/9î””MdQäòôž%1>ÂèH¯ EÎÜ/´ ¿ô!¥²B¡8¼Vî’q¼©@èàTÈ­º|ÔÐx„‹ªÅ›ýRôb‚ù`Ln7ÃŽò¤ÿ¼ØgÝÕÇE0ڸǞt÷ žùn›„<ñuñã
+qŠ%ùnÃc¿Ùy ʘœYnE¶ƒÃ
+áŸ_ƒJ Ð’uJÓ#-.u1Ýf ýQÄq4Vj–»ÝªH7¬ÎqÈlLÙ{CÆ”YÂF/¦èê|þÁ÷¸8!/`À›†tåsWïô”K…„ï
+Ia¢o™a S¥t2©ÓDëïß
+‚‘?åÞÅ.NFý<þpÅm)P ߇Ùé!j­g…ÁvÃkµ^¿gÓ<T†>ø9Jeiêd[Í­#²Àƒg€T˜óÎýD ÆP±V
+lëd7m™eNÆ1/¼áRtJ`æÍžÌ]"oÀ͵©›­YÉfÒΨÀ|kÐK‚a#ÉòŠ)>X¢ 3›|œí+[ ÄwϪHpÊ)Œõ©`
+ÓàWFÓqò!ö»ï¢$ˆ”|¡·ƒv¬jšËo±€?} ˆaäìBÝä°D ½x…XRŒžJ¾”øIX•,/™k{÷þMþ ß—Ù§}hL÷‰ãÁ&˜nO˜¯Ìs(.Äž€¬ªé†)(SŠ¿eœ×NŽbsûSÀNÃR9[b|”0œ€]Ò<yRÈ‘ÙÏs^j>o5š‹¶.âùŽô"ßCª Ï…²@p¬Uݾµ>Üè·’#ЬB.Û_„ÆPš¼¨l~ìƒÓC9~
+möÎä6¥j°úvM` j¡Q8P÷óUt/eÖ8jã”jù;¢‡k€çr>#ä±/áž^=ky—àÞÚ~çùiÖÿ/—$9R ˆž`îÐ'h# a­¹ÉlK÷ßê9D–LI¤¦L¦…ZÞ ÄÇ?t–!Wãï YòMåßN •c¡a†¾rƒd q”?»e*?Ä…¬“XVô=•ÑÞÆ÷´3!t¥“>z.×Ò!õt‰¾œ~ùLêÀÑÎH‰”#ÀÓ•‹(n ÐÉJbÈ£oØ@ü•ss’&¢l7º$¬ ò…sÜ;v's´‚Ž3Iå·ºAþPÓ×'’»Re9ñqIþp\V`­Ô•)˜F‰…íÑtM¹ŸBŠ<sØñÒeÏ;”EhŠ†BýD¼0üf?Š”@Ü ÙQæwºÅE 8î,:nëÂA\ÜAëç>…9h4¸¤§¸¸ƒ‚¸nqQ„ü%åý¬éc`Ä
+¬ki—RÝ£†‹¥†(š]m‰*?i]zEF J*œI÷02n£$Æ 5¼Iaà‹ÔOAç`¹´ä‚¢.Ðí´;æõÿ ê[ Ïš%À4îzå*ìx X?ˆ1âJ–ó™Є3àJöÉ,$°"SÞTY\Ée%ñšÚÛŒ-Z £"Œ.ãOð£ EŒØmÎ2FIåΨ‡<¾8¤dä¦â™rw{8k¢q‰k²:VùZ,ÙÐËATpõÈ0 +Q±÷Sý€`÷»BÖ:~z%H‰IàÕ+ð0µ¹÷T4zëé\éiþô.«^+†l4¯2 jÒ¾eL·P°74ÈEÃ*£×£
+ˆ=Š¿£µÁÂ)º^fšIÓ{²Ú>¦8L¼Ôt×ËT’¤:¾=®)Åø#¢ß1b‘ØvfóÛûîݤÏô¶Å‘>²ÀŸù8ÍÉ9kluUV²ŸÈc¿¿p䔋‹ÉÆM‘>Rd^JÎã¼D‰Z&~“…ìë;l+ÁƒíaìÙÛÄ'@I‰ÛVÚÃw˜ü-ÛjH§_†ÀÁV«¯°Zå4~3ˆF>¤p;®hàÈü¨‹/|„— §ò"óD1.[”±#p¢³E^õ£70A_ýÜ@,1Cyøs(ïõ
+Šf¢–È v§Éüâ¦]&;IE>ü§ˆÏ$¬ŒŽQÀä܈߇В ËXH/«4-9ññŸ²JÖdOÿ[G)¼2ÙÈñeÖ V¸{\Ùt Ö08ð%U1‹-?–µò7Ó‹
+s9ÒJƒ"]Yê¤ìfÁ•@³R€ùnÉ(ž9ÿñO
+H‰ ”‹;ŠÀïv昱±3¦yÌû™1ï7c’¤))*•¨ôð(äQ“:È[ŠÂ’’¤yÌ#D¢´÷l;çÞ{¾ï~ßýGîþ„ßïû~?«œœ|0JŒ<®
+º\¤ç†±À&À<^õÇ
+5çLLJ\ãU„l ÑV9«xO€2O3S÷DTàåiÀOPãÖ{1ÁlÐiom[`ä«Û ^ÊÆ|—õÎbƒíg¯Š¼Rפ}Û¢Ã?ÂBÅôT§í!|´]Éo:–°
+ÖÞcB¡/ëK<uœ"eCæc«ŸaýP t,Õ~lóryViy¨®=ë‘ž—÷Ä4÷1‰€ãQl I\«`bµ=UÑ·ºnæÍÊŽº”“lb¬ER}4YeŸ«É5Jêšd¤aû}«u1;›@ù[Řpƒ
+дä¸_«À·«\Šc¹ óUÇ£8V{–z†YZ ü$Dù|ä=Ù@žžN!¯×JÕ|è‹ýQfñå‡á¶³Y.|¼ÞôÓðÐÚnbÐë]¨y’Žú®ðNfØ mÜgGT8Eú›F áVI}Úº°*D@Èt™"æ>¿Öp°ÛBÌ˽~”ßÑ06d£ òø@€ô±ˆ @‹œ’ô¾&Û•S’øx€ý{·§Ý¾HJ2OWGŸMS"RÔZg©×®°*HÆ? ÜS°‹ÂOäL°Œ v#$þ¢bæ:/0óŽW§:/5¥¹}^$¥vV§?ë@¿r½R3Ë,rrÂáÊww¨`®x¹Õ_î¿Úùm[âs>CÍê'½q¥„],°ßí`ƒwûQ
+Ÿê:ÒÝ–›“ÜÏeØäk-³h¾ä½ÉGEýk—Ûð×n;ýj‰ Ú"
+Ü6E|
+ôîçž„LÇtë}Àó Ÿç°Ù¶9BÖ»ÎÒkK]ЛîE>Ü«ä!¶§ÚSÖú_ǪúÊ®ÛÆk’¿Ì"3O–ð/ÂZV½CF+Þ£îEô<œWI†ìL½þMÁÈ»ºÆ};OÉýå%ï²cžY»6NÉ|‹/¹dD‚Î lâùmƒhȯ> îKjþøÿ¬?ì=XïZWU@Ó ™‡¹.»Æ:Ô˜°Ê,¾¬î­H\ë+›#~RöÞ°Í`Óg%±jnùm÷"¹Ü·L ì}aââ#zvÛ±ªäÕ^…7„¬°AÄv¯ô6J¨¥ŽY\Îñ,2õ›ŽRVSËœ øL·´ã¥GÑYXã¢OW™•ãUñÛSØt’YéQÒË".jöù }Xç*¹8°56Üœ’õ}8×ö©ýmc¢e´>aGŒJ h»€œl6ŽÔ$jù7‚Z&Ú·Ênt}Äe}š„ý¾'†?p*èeÇË= þ5Q×é2»aOŒ}æ–Rª
+uMRÉÁ¾©“Xè40ëöÕÍ);Š¦$ß2ÀŠ™ÇÝ›&–fÄþ
+£rÞúWÄ}Nkm|¹3\} ,Ú’=Üè-Šù¾Å]lòÅ y¸’‹u‘$°, ø¸¿–wOR?:”älë!}
+^Õn?.i÷öh”í™$ù \ĉ‰Ýj:/à§IŸµ¬ÆÓÔ;Ϩ 9ͧzzõ©ŽPìœÄ¦»TÄì#5«l 5ïú²þø`—|¬ 埪è•n5§Ö&£ä®uÔEïàr\óBŒuœ”·$®4ˆ`Ïw¤°w†…þf0OfZ²í²šxë $Ò: î×ñ[Šæ”Í®Òð)r^˜†^aäA_m÷¢ÎÔU³»a97¶{qUÿ3‹ºÎôÈŒ“)x¼cþâ@…Ì:žÃY¡5œñ¥æ¾Ò¨ƒúG·¶‡»#g-ó«Ã¿£Àfßš¡äÝÑ0K[úš2×°©ÜÚ¬[’šô›ßW…l¿ dy}Škº.qW{îÔ r½Ë¤w™Ý|¬eÁ<ólè9è9M€ 'zÕð¤ãIXÂvoÁoëà0ß,®ìÜØÁ´ŽÒr
+bU4%¸æÈÀ?‹¹'ºv¢}š_oSÒ?ìŒR¬ý¤¤})#ËÖÏÌ\^òÿ~wI.ÿe•Oˆs¶A\£¬›Ýä=õh‡‹óOK‡ÓüCOsÂæ
+´t)Ï-]c>¼ÖWóÜ<Pô…BŸÓ´ÕŒÛtŒÖÅy”ˆ4¯ Ì1 Çã|膄‘¼×/(öOöü“­N£Ð$¬ |°8hær–NùÑŸ¸¯eTÙµ4ˆgÝp¶Ô†¿Xâü:v£}“~(mxæŸ!ä]8(÷,·¾Q|M†* 5‹HYçêÁ®s€h—7¾¶ Ã^yfZ¡›ipSÒ¾Þ.8Õ3êOô”ªóU>ÿÌÄÂ_¬³°žù†tûDíë4vO^÷â@‰ÍëªËýu°©ô¾‰‡{æ”3kϵ‚Sµ°y¿Ÿæ%çœM‹±{#¬úQm¬k›ë™Âæúh°À£þl‘¿ |6ËJ¿i“!ß;Û0â
+ÒÖ
+óî@IÈ°I‰ï9ð˜Eüñf7>c£·%Þ<
+þ]ëý¶òIöu­³ïd¾1Ç<µ-+ýÃclÉ Z˜ø=&}gŒ]¤“_ËÈ ·±Õ×Õ…ÿÁä¤]nHyRú<” Š¸}tãêÐýë?^‡ß
+!|xõ³–]}ß¡Ä€ÿÝâпY9t—‘R¹8ŒIÐö_j$˜˜y*BÅÄ„K1 ¿ak-ÀäÜw!œ|pˆRò§|•’û×eBÉ_—³À±¿_êm*Ѓ* [ ãôB÷,³Î6JȲàSíãœ2ó·@+$ÅÉHèÈA â¶ÿ™ñ±èJsfÆ¥ÚÄW!lpæ^qÆUBNÒ•ò„—!™DƒR"¥GßA“Ÿ„H‘Û»Rf¡{Z€<ÖŠ‡ó|Ô†Œ˜º
+°lW,‰ÛÒÕôÖ‡²VX¨ÓpGMÄ>Q¶"Ê›kï~‚CnÂ3/=¹wz”ñûÃKô¢Ìÿªh5‘ËÝèT`oÖ¿AE»(°u)"~ARcŸ&×L"Þ®ŠQ6Ën Ó²K|ôSÿÿ—ù;ZÇßHB²‰„ DVû.A,E-‰]…È"©-Bh„Vo/ZzÑ^[[UE[t¡Õ}y\:îôÞç™™gæ‡ùOæÌýáüzÞ÷|¾ï÷{ÎÑÇ?ÐIº¤òµ•dà 9)ø\!ßMŸ™èÙ‘›D°(Ü_NòÏ·¬¦³›ñûÞÛ‡ÕÇ{ÅÇU]z7eY·×=¿Ñ•òÄÕÿ`¨'f­¿E0o.ç k²hòh|CF²[" |:ÒCÝz
+2è³íE¡«ƒU)Ƿ۪η{µßwŒ¿#?^µ–}ZíP}߶~ì vœnwW½¼Ù$~<TølÜótÔœàÔkâ£1Iñ˜ŽÜ¼>+o)Hóì.Ê" ¾qr S%"èóä¾ãê|ÂÇÅγmGÇéΈõãê@õÛ}ÚË›5ñï–uÙ{ÓmQ¯nweî͘âŒ4ó~ÖUgÍíB4+ä!u1¡§$Ï+GÌÇ2½=À-:‘
+pÈ$÷c@°¼îèërÔ)Q˜ÚRòîH%ç']Õg{Öƃ»¦”ý;ý…›ÓŽì»ÎNá5£šèh(#تJp9阌È`4«(G‚:>R¸  û‚R1á@$àAŽf993Vã½]/Û½ÚvßÞ°ã4„¿šéÏÙœ´'Ívurúj½tÅ0•iiP‰<“} Öß2‚9ͦ•èX
+WÆ,‘× M¾e¸Öì4L«< Ú2“!KÀ ‹"¦P^@öÀAè<ò6~R« ?»^ñå¾>óíJSÌ—õöœ×³­²Ã›í k#ºÐ¹®fšK[C4¨òq—2S¡2^y">ˆ™4àS)  Q „Bª—7pn圄¸Ë°†«ì:l>qþí©£óÇž£ý?ZN6:Kß,Z¯™e×õu ƒ2ËÝ”¥t+Š1ƒ4*¤p¹  CÜ)À%‘AàçtooÀ¹a!Õ+–‰¡·<‡º;iŽ{ww¸îóúôØéc×ÈÉæñ튭ôѵÖðE{#{´µŒl)Q &rLv¤
+¤%Íw¡$šrœ¹8ÃçÅ-mÆ·æ¬Ãûí¢Óz£§™æh«õꮮÛÊ4¸ºÜ"l’P‚ñ#Q€†ØÑÀgq![”€3—T¯é[ƒ7G.§ζŞm÷ÔœîŽ×®4¾XmÚš›¨º;q%iÝ–ò|·¶%¦%O‰)KM —2´2"# .,éæ˜0 W&Âd‹ØŽ¢tê¬ñ{Í^q´Ø¥Ú»eIÞr™%ÛÖ¸í©þ”[}ZΔ¥ÍÜda4ÏT©RBˆåC0ttNÊÌ?:°©Tðq÷6‘ ÉA|hÉ(ð¾®U‡ïMåÇ¿ôä/ôü2¬^·ÆÏõ¶±Í•ž£Úz⨾ŧ½ü"^!•@(3
+ âP¾Žæù´¥qßÀh;2‚¢#ËèÜž”nY¸]Û6!-dÖÇèˆàïlqŽ)šÜšIŽm|œ¨ˆ9˜3B¡¤ˆ[‘ÉÌ_P¹¡‘mrQÌ&cv1çÄtŸ.ø³E.=æâ3jjÅêpoÁ††ùa['@ùÕ‚ö!q…mDñÞ:Ø_£ŠÌR)ÜÈ2Ôäî{Ž~iµA¾gO'„‚צ)Yë†UDŽØØ؈•Ñ¼£§TFPÏ"ZBÕ¿ý öt ®Ïâò<­aVLÉ™¿`F©¬ÓªêÀÞÎ[ƒ 0sR0T4Êàüâ çø§¤-A §aß‚¯ˆº)ŸŽ=|Áá’D]” ,*&NW$CÐx¶Ø×6˃z<Ü2Ðþ7Ë 9O-§áj+ÿHokû~T(/U²Yj1ïïJë‘œ%L5ö3^­k¸׸ýÔ NÄ<Bé©_®=[“NÇ<ðÄæGè¨;¥am–X<íŸe€U`W
+wuQ”U+¹.æb`N=Bñ¾ƒÙ~ì€r·¨2Ä—•úóep(îJÂN&v×Jª h0/·´]…úîZˆš.–ùÜ—ˆ³Ë ïқ㠽 g‹¤–]+þí¾ÖsÉúŒαÛ¶³q[&6.lÑ]zTO¬ŠL÷…& ù)RѶ¾Ÿ‚.8'Âlë$Ý[³Üæɾ²¨Ý~æäÑÌøú¬ð¥ËJóù’lüØIÇ»i­VrÏ
+s-¬Å>>_ë­Î7ÿÝ3ÑrÇ$ªºZèzšwi|›®~ó"bæÑ Ÿg,°gL™uòÈ!í`åŽôÝŸMŠšo’FBÇÅñØRj|qwº¯2fdà ª–Š~™òH
+cöѾˆ‘^ÑÓÞ%L¬.ËLçÝ]iÍý‹€jòN­d¬J^RϨj1c:Ü“Ø6­6eZzSÜó0ü‰Ò^ðhæsŽé…Œmj6e‘ç;þyº„ºÞ > ÕäZ‡†Ò‘ÜS
+qÞ¡Ö@6/kábÏ6‡ß†õøW°_&˻Ƥד0
+“FÎ
+¤ÆPÚ¦”•föàÏ“;qïø|Ê31Ÿtª53ð>nbµ§¬‚¡œ[Ì€÷ù”¯çcKWA™
+rsI/ uq@é…½Ìþ”™Þ˜w°Qp@Ì-\\ÎÊÁ~=–M~ Š%_ù¬¬•Õ\$üä›Æ?HèùxÈ£ú˜ÝWý¶ý™C™
+i¶/CÊÅÿ‹•‡BIÎËÆézîå|ttÁ§œ‚ýÊIȧP–‚êU["™gÉÅ#d,̶³O}÷ÎÖº¿ƒ\≖
+.’^$·™­‡GÉÅbøD¹T ŽÍÄ
+4Sr.æ93Nöp» vK¤ÅÅäeP$*úè}ec äe†–°÷ÓF>ù"0±ž² )aƒ :•²¤M)Ž[„#>'Ë~ ÿÚG“摺r@"‚ÜJÊÂhÉ:é'[öªg‹.¤o¥ñtýÈ;=p7¶E«-y´Ë}¡èaõÃn6&¹Ëê‰é™mE¿¸:”Ê£{ø713¥MY‘<µ—¶³‡ÂÛ}?Æv±¿@>&ºx8Ê(‰äQ#uº=Úï+¦A§€ŒÜ…ÛÅÔ¢K2
+!˜wPš .JkÞÅèÞà4ÜÐ º+@ÿ}\OoŽ‰uq+µ5a¥6¥ìÔú‚—…Š)w+1«”uJ9e¿(ûÙƒEµýh¡åöóþŸlò×ß]졬]Â<ßdÖƒ&êê üä–èþçÐñy`eäåéöð«óBUÂÄì)ø…Œœst çQ¨³Þi]á³j±p$Ÿ*‘5 "zpmäeÆ:Ú[òñH‘mú[Ø%ä2~Þ#dücó!õöå‰t"ë0€?x3þÉÕ°YDH˜þ/!ûkˆÍøârþ8–Íþq,™ˆ™x„qJÕebõí+›\}‰äçœ÷<¹ÑóÝÉlÛ­MÇ7§¿¢+¢[#¯×åw¤ÿ’Õ=%‹‚}éÓË.¢§ÃM)#úiLÛvçw­·i'‡tu$Vå}bÜHmˆiõi­ rÐ;sfjWx“òßȦ ^áu[£õ9=»%¥¥VGV©/Àd¯£ÖD×Þß?^èøGL‡®Ó5Fwf‡‡‰ì°ZŽµ”êã5zur[ÔŸÝb³6>)nº¯¹WòN¯_ ¹öˆ‘¿"«5j`4œíŒTÇvËcJÈ+"™ƒ:”c[¥.»ØïËNJ=dÅV&ôøçaéç°–X™0qP¾yê‹”YÎɻ՚œ“OÈ z±ÐûRÖÈ•šáª›¡Ur_ɯžƒ|ª‰Œ‹Õ ZIuˆÿÿŸâ2}JóÜÃðÌùr>tši“é’Óv¦=i›£mS£©ZÍ‚Æ ÷ˆŠ²ï›@PhÒ¨QãÀ”\pCÙ^VA›“äü)çÉð¼óÞ¿ë¾îa¡Ýÿi_3€ÂÀ®åÝi÷ elKñ<Ü)bá£Ú~X`P Ù…`çq^5¹ìLÃíÈl¾Î‚­—²Ë¥q³˜ÕÓ^%îhßXaÖ¨5ŸM÷U¼ßYxç“/O£D‹ƒ®k>Pá‹·_£ò’.5¶'?Ùbü+,Äû}ùÔ»ùÔ‡£¡‰÷ÇÒ‰ä&¥ýh ›¿3ß—ç[fÀO–©°¤ED¼Ø’+R–A~Ò*&C&ðÿ´„rÇ(âú2£òs¯ŠÙXCY•´Ü0ÉënDͬދ±èíþSYvW"ŠÚDä
+jUQ ¯%m’ÏT”û‘%fCZ/è>žìÉõÏ÷äy¦¹Cðk&éÃO]ŠÖ[Þe&Â1½ã™Àå®pºüÚLpMŒO{{ëŸjé­zEÃOGsýõYЇQÕÐÆG.
+³®x¦ÑÏ÷§P‰.)â噆EãDQò£.Î )§kÁ¾‘\«Lõ¯U¥­ÌÔ÷¦Ý4AîºäT°uŠœgö¿"`{W[{ýÀYm UFOÕg^l­ŒÿY-ο}  Ã>à2ÂÈiŽVøÍ;HÛ ¿£‚ÿÔ
+ ®È™ÉŒ‘¢ÏiÛRnÿ1nOÖP¾û‰’隤—(Ù$‚ZèS⳾蘘àZѯ6ׄ¼ÏëÀý»ÂBŸhéU-é_¢ýÀœåžD=³t…ì €ÃNˆ¹n9m!¥Ø&‰iîYr¶s¦6wo‚œ¾;‚KÔ´”F˜ûQÉÎy6æÇ}îYåQzAñšƒ jDìƒ%.îp¹¾&¨·ø4ÍMÖ9AõþJG§{©‘½¯¨‡x稠­aøãÍH´GŽM9œÃ§Ú&+âWš3®zòÃÎ ,ÊgSsÿ‘šTâž«yëUóì38àI-õs£[‰ÉÚ•àÞ½Uè˜û1O ùG6ñDÃÆNB{HyN.ks p¬áq}ßzsû±±±ëx£±Ï§ºTÛ@t̲
+—ýÌØ2AK:o¬Ž3 þýD׎¸¿/áTøU>¸gÙðÍìS ô;ôô'1øé99=÷º}”š©ì®MíÂf^ÜìE§~[rå´b}{Å#mkécç$ì•¡»,\RW¶ÞG,h™5ëÝù×·FÀ= ˜w{2äK»õÆ¿Ø€=^æתڠs‚¢{þU¾à‹¹õS`SkÇ'íŽâ’ìÄÌ35›ì[hÀOÕn©xe ž)É؇KT0ßÿ)«]V²Ên¨…àPc'ä‘u—¿3Å,+N¼õ3=?áÆÞ(“t¢mjÙ-‰Ð5e^6´äþÛ>;[ç04|Þ§ðIöÅ_ÿÛúµ4”K‚ˆ7µ][®Ëúc±.í÷í.ðÓ:D?€É.{ö‹¸êå}À+Bßj=fûcU̪8û_=Ș JÞëë~ “àÓuILV™MN]ojû¼&ä~Õ3ÿ>˜E'ïO#žÙ¤•q€'€Œ4²m
+N…SÎ,:R5 ·‘ñZ1èÆ2'û²”øqì“_ )×m2TÁ÷=a¯„›uß8KêÙÔS קz¾ ¨Þ3[ýv‘—ri£u¬­Ç®òÈÎùzøî -׳ÌÆøµ\ú©Žúf VKœ,ß{ç %ž:hi?2
+;\+Œ
+«ÚøÚ1G*8\%CƒÚÁ
+ë\¨‡®45nK8ø€V,s™_Åù§ÙP‡”úÎ<€ˆR‹aw\R&Ü>IÌÐ4‚nZA¡–þÒ»JAfˆ0ÆÁ 65°&àٔܚ­ Æ;Ï<¯Æ¯æNõLÌ“øÅÌb×I0ëTU¬}Š˜q¤æ6e¸÷ºl†kZH8‹H~• ö@Nβp[Áʺ¨ eýf¡Jy໋²”]¹/¥f›º+#·ªbÜ2ÌM{q˜J”÷—¹¦mlqÌàÓ ½ÐãPeÜFUÜf2aðÖÉ2¥Ô6CɱI˜Å_ ­ߌͽ>u=ÊÐ_~×Ô_fîß¼åžeïI¨9ÚVD¸u˜œê›g£lüëíìóyü?ˆ´ Â²Ä #øwWc TH+Œ?¿Ô {\f!u…7»Ð±¿Ôeßþi†Á9
+y왡–3]‰/ÔtEµ<Ö™QÜâUFW×UVÙx’Z²;†xìW³‰_MMÝq¨¦C|Ë<ʱŠ;TÔY?¢_ZÊéÛ`w,ƒø—ÒX¬¸üÕ Ë0&Ù9Å‚:§Dxï45Ç+%åZ‡ ùKÐèΪÄ.Š ÉGJ¡àPÉB,‹2®¬µG^~6ÔZý@Å®Yì®x!åæDü0—GE‡íˈ™ŽqBà« ûà˜aä#]Seô4=ïôø×ÉÚ´Èï&N£o‘V²û©ê¡mñÌ=C,8Vã ¿[Ù\¿0”±9N(ú¯éÃt`…MwL@cwF@¡öÉò˜½ÉŠØ ŽËöª…LÇ ì]àa<ÿ§¸ÌŸÒ¼Ö8>¹™{o’iL·˜¶6iÍbkbRc¢Æ˜ª1"Ȧ‚ìȾ(.Õh\£u‹
+P@6AÜÙQTb§÷ÎýGîéï¼3gæóÎ9Ïóù~9«öæÍåÖâø £èÔKs´´k›ƒGA úÙÒÒ~jápX%wþ¡æ$œ™™Ÿ†P±5 ;ÔJÝóõ™†^ð[*â3ð'—²…¦îEÇlÌRò¼¦^I`½_÷y'ðÉPI;CEƒE–¢H¯Sè×Q`Û"d‚GG†6ºfζçÛü¶ó ~Ë‘‘…óhèµÀ«Ã%^Ĭˆ šZAŸÔ
+(ÞyÜ)ƧîŽUG9ÇOŽY(Ç !Õ6ŠKôHHyrBpŠ'ûbxÜž8ì­rKÆ€Ød¬ª ¿¯&—ùôØ<¯‘ò÷sdÀd4 'Ë,"ðÅæùžÒ‡ šäcíÀL¸ipÖ)®OÖu¯âå~«m…FéÇÈ™lè³+°o"$|¬é}MôGâË+bjÒUmGöu);ýªŒžf­K:3¶
+·¦0ñ6!Ï¥à4ìÉ~%µÌ¯D§:$ÕÏ =7w§šÒB¦Î¾Óe¡pO\lóÂ%Æçy¥¤¢})ðT9!×>}µ5Œ~ìž!g:EÄ·ë bwÅ”‚iz¡¢¥&BÁ.þFÉ*W ªŽ3¯Ï6çÜØä¬~@½P ‹nÌs #g)ù÷7ßC_œéÙ¸#‡`š@<×ô=
+­ZCk-¿;WlSÐǶixœ}x¸ ™tfáóýz6Þ%§”¨È QØé–aSׇk¢ìÌ/´í9_›ûk¬MÞt¢r¾G¾zð¯µT¨uÊž¢¹Ö!‚=Õtäþøþk˜ èá?Œ,à”rŸR@3¼C%nÁãü‹LTPÏ%þµ.h™¸Í>5µÂ³@Ìõ«iUŸjá³½rFÝ ˜%ƒ::bOŠŒ_í¯º=P÷Û%ò›»„QÍù¿œ™x‡ÿÖ§¤”Ô XPË'ù4¤RÏRCÁ®8×'TRÐÈã„VºF}‹ ôöäᾕÔ3q`/(ø½ÿ‰Vµ=^Ÿ¸'£W®¢g¥
+@¾“Š×Ç0σ 7€e‡*~Óñ±Ø)†ÇZ§à1{’ÆWv)]&¨Šø$¬ˆÜ‘0ë¬ò–Æ¥ÄýI|Ú•¾Ú„‹=µÉ™y.,ðsnÙ
+J±G‚JZ(ŒúÄ{ýà #9Ì¿„ÉÿÏVÛàŸ«Â.ÿ¾`g þØ:‰xz¨&•ŸZ¸ìãU7hf“÷”„à,õþ%6ð-̳íqtÜÖxýk·ŒX´¯ ”ìˆIo—ºaQsø¬kîÙúì#C3Zó>ÿ'UwúW†²¨qrúÍ1\ê 2ÁŒI6Œ6æbS\Ù®Iøk‹+86 .)"Ù.©ŠõÈèõ'&a›S΂&<q˨‡!Ë.Á¥­@ï­ô×Ü–±ŠÂÛ _ ¡“¿sL"3Ö& œê„ðÝ92ìPÃlØš¨{¾2 ½gªüÙ2Rvs_™üC½o“2ËT,̉YØ}¾.|Ð6#–{ wÔ¼’psoÕm×1Û-çÖ±q>U Ü ss¸êa4æò(ò×KóÔ”k¸Ù_z$ Yÿµ
+úí‹ ˆöšGWí“ÄÒÐr×Ph™K?3*O EvQùÓåþ¬Ó@Vxhµíý©OâZl:¤ôŠSSÇЉžÛ|fäÔt˜OŽN·N”Ƹ$µ/?¯·öîi;ºóü¦Àr[ç±…K÷«(åÞy\†c“4Ñ”Þ^üè²{©•µ3GÍ÷¨éužEÒú±)yÔ’m¬.Ö:R~Û:Té‘à
+\
+J¥¦¯öîÎ4â–ó°6 !sWBxkãRìÒÆ”=>çÀÀÆúõ=£cß\`¹gòdåÝäéJk[ÈÒÒ
+Þ­‡à?fà’jJ©s‘ Û×´q­"ÂßóIâÊ{d´¥·îžVXüÝú`M¼}¦1kek ¾´Nv ¶ÇÛ;Ó<èö,5Û
+|ps
+“¸6UÐÓ Û2f•[ΆùÛ¹·aWFÊÙ_ÀgÔûõÔj‡—iŸ#Ííï–ø$¯Š‡ói@/qp¡UýÄÔŒqHÓLCµw7ÆqIöOôŽŒ42Ò,½œ7¦6ü#%½òÆ-ÿëÅÈ}Uoeôrf˜œ}æÑ!–ầƮÂ[Î)xÂê`y´©§à'ûGHtЄ-8Ô“Ê·gp¿YŤ¬cC+çÈÀ%˜yÌc‡æÓÓêœ ÿ§¸:¿š¾úxO{ÎÓ>=O«­×#Ö:¨ÕJÅÅ-K[62²HÈ™¿ ‚¦¢ŒH˜I$@È"ƒ$È d/°zêŸòü|q_Ü÷ÜÏ=÷ûY˜RÓDà ß
+¼à@Eiò-²`QÕ˜4®“ƒoé²K:Òlâº+º!ÈY"ýgÇ"Û"éÎÓ•{ÒöºõN| G6
+<´È€zÞã
+>优Tx>°Ê궋»Ë”üÊs9¶ÔCLÌĦ'­lfÔ¿°¶—³»@mð«yl¯ŒÙÝ ¶ú”èbûTkÚž‘åuÞ=˜C?qMÃó¥Wv$èrû{|ã<³:UɪNq‰y9¦8¾Jk /Ó‘që3˻ʻֱŠK Óq9;bh¦cºöêŽäùõ­‘ç×ö¥m™­8ȧáˆÅÕwLj7,³ cï«Ø:½Ó#Ef˜jRÖyÏ.8ÅMŸìÜaãâ©B
+'vá⡲§É.Be€=õ®]Œ-
+¯ÓP¡-€ÑS:¢ZjÇþ|wKŠËw/+¶Ç;ª/XF*/­OÞªLÙ™@üXâ¡LÈ|¥ ìÜŽ‘\%6‰G&4f¦ã#›<NTÇÄ ½}q}ŸðØ<8÷Á,>6qy1#­ëPƒ) èõ ©N3y2I*?ï•Rëö%äR%­êÌPSÚ×u·¿Q’sÚoùݳ@.×M“!£äê_&)ygwfP9Á>¬æÃbCL‡oô®‚½`“½/g!=Ê~ÞÖ4¥Ø:C,vɉ5A5È ºôo úÑÌá& ‚>cOdSÀ„ãqC_TÏ"Ô¸j¬-Ó-kê[¢Ôù
+hº7„5 Ö¬=²7ƒÉµ‹ -†±®Ÿ€ùd_ðt—d¸R·½=Ù•©4^åµ<:á¡ó3øëDgšg±»È!F?5M4Þr̶>ô*0E ‰›oáO” © çs?Ø^Š’ 7£R‹kžé^D庑Ï<Jr“i
+“ÎéÕ°
+ùìx›„ù´Ë8²¾œŒ™û^ûµ4xXÏ¢$-,Þ‘U07 %cß`Ô¯šòüß @ùÿ¦ðEgâj#ª¦Ã"*RMDIkÚŸÆdoÖ_2ŽT_´‹`Yn­uŽSwyåeCjP fÝ €t¸J¬ñ¯jükÄï*ñ¹jš®xÕ’6ñ'cVþ€OM®u+ˆ«TxÒÂæ€þŽ÷©˜û2B‰e‘Üd‚Ý’ÚêUâ*l"$Ä0ôâ¾m–ãœé,u/tæî.áJg9µ¿N÷”\K€~èUQ›öe”ZÏJOK@ <*6jONkòªXíkdÖ¶üýÀ”Üû”= ®Yl®sþÐ>½g— ‹öålØR?:R—yn{²åѼí±q¬ð¿º‘ –é–ŒµáúÌÍá†'‡rtÙG;л½€…¬Ž´Ýò(è¤I(Jš¨¸¸^éSÖü!¥ÿñ­”˜þ½SÒòôƒ•Óëâ!Æ)|¾WÍ¡›Fÿ˜úÇ?Ûh¤¿­ø–à:ªÐ2ÞvÇ·ÐSç_Úƒ«<BÂ28Ÿ´Ì% ¡gWlj¹×sÀ‚È°ŽÖ\¶¿«¿z°„É7Œ¶§ZF°÷’>¤ã56cƒS}^Î,:ûqïGn]ê¿Yϯ3
+Kÿnï=®božTâSàËBrS`ÒžÐóqSÿTd«o4´ÉÆ%
+ t0z|8Ý‘9…suƒ]~3 ¤6ù”½„ývù¥*E-†åøU|Z@×…J˜¨°¸™Ô1â]+ú.dÀÀÁƬ¢‘Ä>_”x9iZ‹Y$c1‹hèøÿöYD†eúÀ<ÖöÈ1G cs¯)º+ïäœFÏ>ÇÐW–¢á^²ÖÞsÎ!³ç©¥)›|ÐÃ8Ðù¼Jâ;Ûômúàxÿ*¼Ë„=ƒ3‰&Ϥª°•Çðj¸h߶´7²7¡8?èéYHஈpߤ©›3s\£ÔÄ€}B?0Ò°à¾-Rùûed¶~°1í`›ëÝf´&m=â l[Ä•†Œ|AÜ!œxÄ ‘Gòj˜P/0; «` dû÷ÄÂU$¤ö&ŒÂss¿8¨åv8å̪¯Þ¹ÜUy²N­¶LÀcÔ<ü·ž•ÖRqÁBõ©¢ý¥söÌ2ZŸ~ª$׸|¼CÆnø’þ»µ_äW“kýj|¥[…,:Þ„¿u,€Ÿž© ¨¥¿×¾È­3Í’ ü»½ÝnÅv™3"ff“¶¾˜©_š4ö÷ÆtÝ„ˆ¶‡4¢ŠBZΧáàüÛtð.þuò›Ð½: ¤ÕúÖp¯ÍÃÕ·â†4û½hQòõ"©ô’FX÷ý»êÖ¡4eƒöö²mrϽF.ÛB=´OKCº>†GÅ™ ›t!dJ<ZfË àñÎÅŽÜã5b©ZôîvHIEM’QÿNo§WA©0K¡ßO þ)mzöů6•Ñù/ZùÏ_Zšsƒ[ïÛ„²À6±Â-GæL2ö„yWTÌG!Grj•ZTsà ¬KsN"^
+›VUúPGÞõs§d9nVÆ-Ÿi:k]³-Ü«èÜ€š\°~Kɘ$¥ÌÀs¶iõYãSPAn`y´l¸}ž˜,£4F
+V³k•Þ·j"Ö }Ì>¦XG ‹PÖs:@_|¯dC”"Ø}ý(p¶Ž/1Î`Ãj.Ö+'»1™®™ÖûÎѦÛÚžâKj~íÍ©nè¼û—ÿ!€äÜðÈ %G˘Ë ì®c¢íþ‡9è/'ËàŸëä2 àëÈõåµà6ÔË=ÚÉef@Ö÷u´
+$13Ÿg_$¾v.Ò€ü&ÖœmSÁžu|Ñá8úé§éÇ5è6ðV÷H5ù_ÑÊûÚ$†—øå„ÒƒIÐ-Çl}šN\š:ra…’“*£ÞtN·fgO%¨×—ìClP@&¥FÔ4pB­ ë:JŽe­O<ëÐ̘ŽÿhäRÎT”º„Žý¯•‰û ¬ÿ9z…Ÿ,üž¤ž‰vÌÔÝ?Ûø‹KN,  ®®°@?ºf(…ÎqÔcË
+Ò[Ÿ’ ñ*ðUÞ-tùÑ:ì9Ðoñ‘8¬é"DtT艢!Ë%«Í<Ý€ç…ö
+NÙ-‡ó]Õ¶|VÜ 0¹…†KšÉˆ6.œíÖu6($u?/sËœ;Es^u/Ý£ìÁÕ=¬À&â—¡ =‹È·g›„z·æö4¥ô§Ã¥ŽZ×jgµ}º3×1‹Ïs­ŠOôš÷sø\ß±Ò£¢4nJÛ~•÷6<?ÛIB¡$hðÉfŸ– óµóA£@`˜&éFqY>]·s½ ¼Æ‚Ü€~3 Íúχ)ð!%ª8ºóŠËü›ítã÷ÜÛ¹Óé™étÚNÛÑeæhËæ–ÑÕ¢Z¤´ö5"‰¬²¯ßDV j_J‰"¤‰l$d³A6!—.çôœ¹Èýúíy~û<Ïy¿_Ÿ÷›\ÙÏxq=3îÆ¿T­ÙG¶^xI*tÏЊ·AÎí¨kí¨™F9l‘6ÚÄüiAáÕå7ÄTŸI.9佇+-þ³œd
+ï4»ÒÒ…þ}KA+˜ÛÞ€^j<^¬ÇçªÍ1êSq«oÙ™³mÔä.rÕªúÚ;µ¸ÎÜ
+ýeœž~¾ÿð\?1í› vÑU°
+ݲu ûñi•ýrŽö4ú|XCó
+³Z//¼>
+<º`îɺfé}qu]O>œÔ…[Û ]ÄŒõQÚ«SP/ÿs ¥»…ÿg¸<ü’Þ×8~nÝ[v´S™Õµ²Sž45GCS{ÏPT\ÈdËDPÀm™š3DEÙK®PPA%ÎÓ¯ûŸÜßðÏóù¼ß‚ÿZéø«eRé‘Ÿ±Ø[ÊÇþVŸÿÞÃ6ÉÀ^ÌñêÏ4Ô‘œZlA§Êy…Áª–LÀÁ2¼e¸‡œ _h«t~#fºf˜Å
+ržKE¹TŒÚC ¡æg{o!’/LüÀ%à.%>w_O)þad¢þ²ˆ¿¹8·™ÇØšj@jňèC«Ú=Ï®³á“L"è3µ ÷þl’Ï0)íéæ(:p-0¹8î^Ê+ߣôâ¨+`.÷ÔØd§
+›ìP õTàm°€;·däì]%³äÔÔ*>Òñh¶ñÚôC-­Ü9‰K4 óŸ c£nÛaÁíÄ|ÿ‚è—·ú y¾ßÙžÃÈøèéž:væoc¸Ø_?¡}:j|µ‚¢ EKYDbÀý_Éž¶:n}‚¼5…üóhžŽ¶«Èà•oèkS˜„#`oÿ·ÝÔiýV—~ j¤œ-·ºW:$›ª«­–ËU&éȨñš»gì‚oŒÔ¥:&HéöadÌöHM¢m¨"ÖÚ_úîXßDÜ¡YX>Íù[¿’€ó—=W2òîŒ×¥yJë’nÍP’~]~ôµ!«Â[ÐÑ=˜¯] )Ç)«Mú›Û
+ÒÂP—~º@‚/óù+âÏnscýÙ¼€{¾ »Mͬ=~¨`íO³¡ ˆ …VL¨‚û‚J÷ú\“rGXç9ŒÏº7Û\ô|o¼6Þ¥ Bí¸|Û>{OÃEº Bö‰‰wÌ ´Âü‡r^ƽå^X€s‚˜ybäÑö>9ÐqÑ'Faãñ,Ÿæ’³öåð(»`éxd —xijªwùŒ³ôØÀgDÜíIV¡u3×Y¦U™»ÁC„˜­ n™A\ùBÉ?™n
+wfâàÜsbᶎ‡kÅdz*Eeï/–8ä«U6é|‰9_Äåž™ñy
+\í*}¦ädÝm„¼ö dü~MBˆòü¡ÂçIZ`oa W{*Våü'È 7æž´>ÜÛÔû`ýkeä¾’UçÐrpô²Hß馬wÿÙˆ¯,M—óMìc=²+EÇ/v…è›2ý\Z
+dŒ y7H-viX8§‚qHñÉöQTª®µø­”–ñPß\ðϹ‡¬Áâ-_y
+|È"ä;
+k£Øp}®¥—ž»;Þ\³3FLÙ—R
+Z‘ ˜‰m5ª\Æ܇MpPÇæ¼{‘‰;ºß=G+?™«¯\ê« ×µVlŽ“À—⧊ݫ·RÖIéAù«ÑºLŸy4è@É€µQ žÖ¤…yiÛ±E;rL#ÌôVòýÔ-i+ý£OgyÔÓ9‘pGËBQJÞ?cçDþ\ã7»çþÔrí’š7–ÏÐgzA–^óbkš^L
+>¼¼É¯N952¨ÿú.è8_dàìã°!ÈïûjLÊ¥EØéÔpˆ“ —!øåå_pdb£~è°)9g[‚OZ¨|µ1Xj•ÒsàhOBöë›sŸ+’\@žnJPi–/eQÆvhÀ@]æmøÍu;õ‘C†HÛS²í2Dô‘¡ð­Ž¡‹Õ ðf£gnГ
+ e¨þ­Œ]±1\—±«¡{”¤,§’\àP±áÞ9>ùÈ,øt- vUÀ=åÔ"¿AÔº·(âz•Ì²uImü$%ózôYÐ î}°ŠQ2È@ÝNˆ »PŸõ2ÔÖS²õ"Ÿ- òîX:‹¢—Ú
+ïŽï@b¯ŒÖ§…hxл@ÖÓ+ö>DÒ™ŽŠÜøþÄÐ’nà§ÝT=ù¥õò’‚”qUÉ/Ž?¹
+<ŠÚw_Gp Û
+à£o*ÀaË
+wI±ÉŽQ4È)¯KÞ›o,ñÏs kC@®”Vð_Û é½¾£!yŠƒ~µ$FÄ؇¡±¾iD€Gªs¶µ@¾OÇ©ù±Æo?6rírfñî<»vWK*;61s¯íÄ¡ûæÉ…{b7ðÖ¥¤B]
+*Ä=M+¶‘Sí¸„-sº(îk[(%§Ò%ïflM´×m 1ÁÖ~Âk9£ |œœyË6LHöÈ9åû6z7°“{i©M´£g5mÏ5¢Ý* àëpuüžŽVé_â’¿웉N8¶4SM|öŽžG:Ò2±ºVHÔ)÷†¦¹äö†¤òѾÈ?1r›V¥ÄLóPMÂÎ æT³öôä"ŸŸm“Ö¾u«)E‡ <‚OM-;³´
+N¬<ξ‰Žûéä÷ýpŠÆ¾nÇÉ*‡çš¥×:g9U[rz¡GE‡|wtLïy¬# Ÿ¾&–¯¶9·´rNÍ<ºß$àÚeŒ|·‚È v…µ§2zµµ2Ö‚0tâžè…è¨Y.4t¹­ôŽm°êùædc¦y˜°ÜQ½Ñ/„¬KºQëýÌtÇxcÆJOy¤Y\æ¬{}làÔû ´J»—¼)%džY…ßV„ƒeAóþ"—¸=×Tê_æQ"Á¡IÜï_°½3¬r¯’Un!gZ»+ŸêDp)íÓm ¹â»ìc°„ð)RÝ\Ñ‹M
+k
+Ðï/ç%Þ¿ˆK{rq­+ÐÇnDŒcñÈÔYxWÖ”|­ þ0h´þů>ymú×) _Jˉ4‰Ëhø#=“èSÐË4EΡòGjVòMk<Ö«`À†)иµÑÚ¢atŠµ³2Á!!$ùElcS5-9aÝè×—ìÃ̼¥.r¾±»ú£w—2ÃÉ W1@7¿DŸ,×€ýZØ&) 0(2Ù¯o!›$”Òí2"À@5'–Fô+f¦¢Ï­šGÙ`˜{)!ç`Ž…óM5äȨ)·ÔôÜ(»¤&Á5†KØ¡dxåíDçx Ü+ç×zUíM)e§:¥äŒ€ËþŸâ:ñf{Mã
+8È1‚N`äF ÓîN±³BfY…/]øôc-¥dGE
+úG[>Ñ ªüçf&Ö5DÍtöc Ò‚À-»tOÓ.|Vz0ƒI¶Ê m]…Á[òšèC£|ž‡\Ä&ìh¾2‰ù€ã+wÔÔÎ!|¢M†ŠÚR’@޹ƲƒzºÒÜäšf•íiÅŒ#½”»§æÀ]j~í’R Õö³@ºNbœCÎ)ZbçN7aŸÑÑ!t|¤^ŠM°w‘ÁŽvÒS *LËG?U‘*î¥Õ!rVé#~~üM>ëÎÿç¶:BNßœb—¹g$¸õ™v–¶—’ÒýpGË/>32jªÚë0ì™c¤.Ê¥B¾õÎ6VmLÊú¾ÏµÍÈ’À]5µÚ;[—¼1TöÄØZpo›âßSº© dܶuÁ£-Jv1:?ùvlð?}†¥Œã2,­!&qÆ}51æ&òį™ Ö….wóÒái1? Jãžúæè?Öx<·¼"Âö¹àÁœ ó—Öª°Ÿ -¥Ñ =ÈTND
+ÃnÎ÷³·—DŒ ŠcIü'Yy 'F.öH#ÂocÓôMû‘oopóÃüÆé)÷œ1ÐÈßfEù‰?Ö¤½ß×¥²K;§ñØ@€z4¸ì¥®ÊÐQú‡
+ôl‘ùa¢UíÎ’sö´´{†·ÐR÷5bŒW tÄiFÁæ 2ÆÒ^òXÍ- ÆgÝrtÖÆì¨y¨ÅŽšöxô™Ž ?7²Q&ñÒÊcy”iN©MÅ„li¤l—®³Í6Ö‚tÏu6ûšùG3ô"Ÿº!ï«^u¨#äú´ä|ŸNBv
+å®onü§Ä†S°ÍM¥:½ 4G˜Múr~¸þÓ5jãŽÅÑûȼŸ‘\»…ü7tìѲŸ%,œîŒK@ŒšE¸„8ñ‹9ïveªª åœÔ&¤gÎØDCE78T @Ô¨‘Õrhãõ¥í|t5
+À§·ÈòfzSÊÈîJÙ•@Î==•õÌ-XçeÞµ9RxsC3.H’N‡_Ö°ûCvw£hß ¬ðÑßNÖ}š&ÞL¬P~;x‰ÿ>ºØ}µºMj®xô¸Eˆßßäv<R°äOÜ
+ôœx…´cXHɘ9yŸPòÈ…Q£„²ˆˆi«`(a±9HªîðFÎ÷Ģ〔Ÿ°JˆE¿zº‰°à•q;o kc¶e·ÆŸTœôŽ
+,¼S¤ýÊ‘Ú‚MFK™ tl•]—ÔsÚ"›¬gþUÎï{:>*ïQ
+ôÜ.x†z;ašæ%ÌsÂŒEŒ¸ˆ‰n0ž˜ïä4 欂éK½Àpq›ƒ/º
+Æq©É"’ù2¸ø:æšCØô¹þø/zÝ…
+RO$;‰I+ô<i–Ñ-
+JaIÎ&Im 0‡: 1¼@»^œ¸›Üât‡6 vÿ2Ø3@Ä#?²ÖÉêNXíy 4ˆ0f¨ìS)Éø¡S ì[f¹žµ„€n•ÔÎâÉ``jüazÑ\¶qpE§`Ô¿ÁkÕ0z.JpõŸ_²Ú3F #¼ˆ½º­ªû2²Ü}%oç “+íž|JiÞ+¤dbn[D͹Eã;ˆ)8è-Y#ñAÆ>јÛ‡}›¬fÁxã%FsíŸÊfÁPÅ!£l‚¡²ÍÃ\bÒ %ì"bVÈB
+U9(d"láUvøãÇ0PõòÇN}BÆ‘G0–²°Z÷–(w’›&i’<jâw^¶f÷æ:âÚ×cZ\mÆ4ÖP‚yøÀòè“ÀéßU?Ä(:lxiðÆîbó?Ïü˜{ov‡êO‚
+VxÉ#Úý$ª }ž;¥Õ1îV “A-ß±²ã3{±‰v€¹x‰Á„€ró3{ëCE{Q™¶QaÕYÆ)?HXÅ„¸–;‘7#ËQ0^Ôpfûä `cÏÚ„Ûw|Š½/³FÖ|C)ÑcÊýôÉþXÑŒßçpõ§4éFy‡íL-Øö'óêwu¼Õ‰ˆ­°j…ìV"õB
+pF éñ ÎgñxÎgW]ÐJÞ(|“<½3Ç#²•O*NÒD ;\¨¹ÀÕ¦_p3"ËYû13i•íd¬¬ç5LD+º”pÉ'ƒŠnÞV\CúöÂÄY+9”ü´Ãvê×é)!™èÙ¥IAë:•`îE+˜,ØßM^bK_½OÑ7®bÀ»k<ßûIu°ânW,‡SU+{®䬢ÌÕ~˜±R÷ kªä†6k ;wÊx’”,ßêyØ«í DîD`Z' îÔýÀzΘLánÞ …×I¹á: sI©ÜÕ ƒ{°D\qŠè>9<îRIžÅÌ2BÕ$m‡¤Ò¦ÞÉhˆ"¢¥;MŒ6×BŒŠþÚ'x{+­ÞºwiYÑq7Ác5‚|rÝ ®Ö=ô™²sw¬…³5J"¢ šø_I|P¼sÓ 'eCVŠ¿Ì:¾wÎîÝ*´ìÖ©<bè{îâÜïs6ä ›“»xæŠ2lT›:I˜ƒÏì\Þ,vÏÎUŽI¤÷ß”R8ëÑU‚:k3¢¶ç]Ú#·Fµt&V=>C•cAµbÑË?økV ¾ê„•'ƒ¤Â4LKtâ¨Ç8Än¤ rRó0¯ŒŒ*Šp?°+îݧeyºƒY Z ë8ã!-k,cÜÒÁnÄ òeˆKÌ;ä~J¨¼*ùûy™«™èë1)b/«p¯‘©ú8×ýÿ»ÄhEöúqòËQšMe¥æ^F‰åmÏË.æú -32¨b˜†ØŒý&e¡—B‡«ƒ›qSåÊ[ €ÞŽ#а ÒR¨x˜¥o2Z3"—&ÎÔ¤°ÎJó¨Ü{g"ýS#“ÿ·´RG,õœ¸†7á±ïFÈÉr­`²£f‹Ð¯Í8ê—!twü&%·ÓR}3*8LX9/Þsÿ™žìP› zTùíÑ.õ–dýа)DðTÜ‹À¤²K°’9•/y¥ÚI‡@ýÄ*Ð>R€©¯f~eb­ßë…TúnHml…´ö”UJ èuD—J·è?Ѭ'mF‘Cy²fk¦|j9n›£&ω[ãáøÖE=dxJ_gÜfÌ“î(€{fªî‘[h^
++ŽßTÌéC†þ[à ?äøè #ÑGOeK~ùéBPaXŽ¨Ä/JnðuÁNyt‰1^wÂÜĹNZ¥»˜øéIª7Jx˜?co–"J PêAzŸ‘þ]”¹qÆÞuƒ{³7y¾â—7ªEäâøøÊ!¤|ª§ÓþÒ­\xP'*‘5|ÜÍ„˜Š*éKgœWuÜu}Bâ§i c"££LMôÙ^…ëA„^öð »d7n.ܥˀ`ïÒÇY­¹ÉÏŠN`.j–­» fŠQ¢Ÿö+æÂúãMZ½âÑ[ALíà:ÿÇp}ö5u(
+ÒN {b|Xc>œ¾Äq”=q9µZ$¯:]ú -
+3ËQ³¥”)%jG»IïäCsæzˆ©FûåRôªľuIï×ô‘ý°Þ²Љ=í¨qÃHœ¯„6F„ ë#˜a/÷‰}ý©µ?$S½
+kmcv‰»CÏ^¬áQýOqXÒµ®ÚÉô1œàÊD7ÅÈX¨zÖY>¯* o|RFá5/š!›Æ5kCD½&JsÝUª=žµT‰ãÃbîb=mÆò¨;—ŠÇÎ]}Y9u.û6!/£2±¡ '…1¨+2óCÝAÈ4v죴|]%´}^#wÅ<l¼mA‡Ö°eÝR¤âè‹íZ{¯]¡BGhìQnx¬W¯0òž"³Ò\ñ(áסÊÉFÂxù.lá”’«
+äßÛÒÓÇ`Ðì}ÅïýMnHà7ÇVÐbã:”Ö$½0 Ô £O¶áFDÛ>xͬè7æŸ3úú.Á³Ôü°ÂÈÇh×]qîUÅ<ò@œm#ûÖÆhÝÐŽ?ß1 ‡ÂV´i§‚VÝ”K#©s*ø%n­®Å p·AÐz?‹„dÏ ²ï©Ê*™È…™‹»±”[غ©[µ•£?¶6Òz0#Ù""XìV¨ÑQ"Ü^Rߺí0DíÙuëcnñxØÓ]Yp†£dØš@š·„<³œ=8á¸ÖÑ%ý®©}ÝÄ<{;óuëYRvæ}”•©f¥‹4÷)™{KRæIPÀzë¡tîøQ/"r8\LÎÜ®\07(ÞN1ÏQÆ¡ÀO¹3òßfFèÏz±£wGÛi9付ڑkèö´™¡îë§È$”àlR5l³¨ÞÇ óï§.ùÎÿ½/2|Ûá ¾ìBÞO[ªÀɚʴÄkË&Èa´i×ðäÏljS¿Í`'Áb¨Ê,––û óõ>=»6î§ý±©\ü—!a‰hÑéR ¦WïsAÙž8}40lL›AÒÇ4?`jIç*JG’›êùßaÚ‘ w
+ÇŸiL,,ÀŸo­'\äMóo;ä õ1;DÜòA÷¢Ól{­”Á¯'Y²·Í ñ7ìÿc²vwzÔyƒ2æDÍN¸n‡ iý½Úmò«¸VÍ%L«ò|V¸õK#PQN;;2È€¤ý1 > CÊ-8¼á˜8¡É²Õ»]î^Ñ$m÷~Ϩ? Ý"IniÓ|ßÑiNinÑ$åŽ'\G5yOˆ žRŒl<ü].Pð¸ÿ|{«ðòˆî¦cAY½»’öÊß8CäÖ69jâ²—JfiÁû,ð]=‹{P%ãÝõ”M±>á̹Ç‘Œ ó*£(ñÁ ¶¨#¥­žˆ¢ôÑó¼rÏô¶Ëk9\^
+õÎ2âÔ
+,æ¨D®Û£0D»uƒ„Å›ÏËçÎåÞïI*+%^xÕa¼XÛ¬=ûä%=!ó^Pðœ’PTÉMHÏìPyd çOö\cÌsŒ2ä•C.­Y5±Ðk&ZͲI;¥T¯x {ís¢Xù(9€j锦vÙÒû†|?•—QÎÜË~•–ZÜÉD—3Ú€¤$€BU'àÌi/«Ù3³»Sjjg®Ã úî£U™üÛÖ¼îÃ
+ŸwŠþv¸T^Ç¢Öf}­ÖÁ›\~/`‚ÛuS3žL´-‹2~8E^ÎÁãU?—v_¬«›ý¾ª²ÿJ]…Ìs;bò~ˆ3é¶#T¹Î×Ã’í4‘{Ϩ±,t¯1¥¬~.±¢Žv¦ t¸qÿpáJ>p' —Ѭü …ª›JbÍsr.bQ ‡ôtÀl¢ ÆÅYPµÖE×N° ÓbY]SáŸ*›%g
+ž¥•ÔÄšðÌ“
+:p#¯¸|ÚJ½ÝääOw“îüŸ¡òúJ3A ø jªǸ‰%±·ØQL,£Ø
+*Ø°!¢€€ô¢"í£÷."ˆhÔhŒÉX’˜™³ÉìžÙ}سçì?³¾Þ‡ûô»¿;sdL–lP¢6+ù<¤•\„Ú£^ºáTá VË [{Ô‰[ü˜†!î'öMGî!ûAXqHzŠ²
+&€ºfäÙó% ½xÈ*§
+ñÚQGù¥‡$¸*{=â¼ÿ²Mw½9hR©@0Ü¢i »pâÚut ¼UdÂД<ÂÜ*:´¹Ï~«sj/3eËeö¾‹è2ÿËæBÛe‹Ùµ«&ô2G»bý»¬ü„¡òËgh§YãóÒ† ÛÚzÔ7
+*È@ ‚­¨_‚<Hiî'ÕC]+ñõÍÔ»Ø>Zæ;¿~‘3=VÞhÝ «,æ—5§Ãlù9Š"8.%{5÷®Ü®k[Šƒ·0n&罆$$V
+É4Wžd{ÚŠ–ܯo¡?ìì—> žIÞŽ¸Í9òm_cFóÏ= õÐ4WYÇf¿·ÎÂü+£¯jÍÝ\¦0‹AþM,?íÃÙ…cgÀ'í3w)$Åã†#‹4oBcxë¤Ë®>›ÖYô¸Ë0÷×>kò_‹#?¶©½_ü‹í_ŒÎ=#¶®b~—ÀíqÎ[Œ6ŒQçÒjBƒ’e‚Î6’©ÊÜyš¾€Î4V¯Ê@¤RÖ«õæ虈Ù}¬ËMçç®|éßG‚Åï;ó}ça>éCØ¤Û zÍ[A·Ìã³P4E£D¤+¡²CÅ“ÔH
+£I®G‰`¨ÅíjäB¢•vÙ/…6aÖâ›±ŠÄž{¹[®×-N)áçtµMÇ^E˜ã‰9wT,‡IÖ®ÕjÛö‹Bí%–.z‡ ðb%³¬ham—ðAJf7$-«¨ª£@^´.ÜÁà¤éd’5o…ã{¾šq§.vשXsZ¾ô ƾDäÔ÷þÕQÈ«6[|“ZCt\n¡µ–^iôâÖ”¶f™ÖÓÎSïu˜Žš²4›Ê1–ŠÁ0Nïp¡ÝnÓH$` ž„Õ´¿>ˆÿ½àóÿ÷M¼þŸs‰ìØÇí‹øÍÜ@зºy‹~ЩմÛt*”É ï0ZF»Ÿ`°xÆA0€Ñ;b,ÓFˆíöƽꅪO>æâÿ •×W‡ŸöqϼìÙ=ÉæL2“²³3“lb2›˜ª&Ç.VTTDQ¤Jo‚" UAzï]@Š  ‚k²gf˲¼ßsîýý¾Ï¹„Ⱥ–Ðyç¬O«ÉÛIcÅMí Äf&=<ªÏ¸<¡_#Ö¯-ŒÝYa£ eš.ʲ©~§x0AµuõÏ
+ ¸µw8®£ǵ½Ÿ™>,Šµï„
+ý€Ýë²f¶V%GAÒÔ úéЇ™(ǹÊrRì͇VµÛ†H£“#e
+H 1tód[P† ÐFàø?B«\íâß®ï¦>l-<…‘Y¯E)ÊmãÂê¹ÏQAÏs©ö»¼ÛVá{bzÖLÄ$DuÜQ¯R8äÓˆ'ÜJÑ°z™óJÁS´Èù¦Þ5ž ¨^5NZ%Z°}m0¡Oîëx3§þR%ÌåŸø¨“)5®5«! —}LƱŸO˜©}~õb¯ULi4 u£‘§Ti'×W$Í!»Á©b÷zõ¢Ÿn–t¬³òþeÒž—ƒ/ú—å-ó2¶¸pæCölKûÄă÷÷͸¶¤ß´cd‚bÖeÔ¦–Ú•pp°q»€0,hùSß+ÙSßêøðGv9·Ó¥“L…Œ´®-¶a×*`{6ìe?‹z@v•\¯÷ÌÓov ³ïSVÚX.°nÉúÖ q ÔͼjZ§cƒÛ§^]H¹ª&μæ«|H¢Úžc ªpÞwTÆÊ›Åeu _´þI.]i‹Û”ËÇ…½èf3ófð2È]¾‰
+´7ÑyƱ Ú–üÝ-ÞwJfŸ;”r”RêD«Yå­û¦–eA‘¹þ<†úflú Eú–Ãe=SÉ6FJ !jX'gõ´ž’7TòàG®‚tdZªõ,|ü«Ÿßô—€ôSØÄæáAOˆ Æ?…Ítb6"”Äí‹Ÿ–Ül•âß™Äø—ö Zæ…=¾[¢bdèÙÎ"ÿjwIz“¦Ó.·Ð×±9ðe 7]
+ÌSFlG2 RvÒ)bœF8¼ãÍeNÑÏ&˜Èb€ιýY'±/åàÀw<RiÊÇ¥ \ÁO#d¬DÀ‡Úw¡
+jW¤êÃuæ2
+¡&µhDo2,Èu6ªJiÆ4J¸ÃÀØ´ã[
+Û,N9ÊdíjÆ^†9­·Ââ¾÷iÍèS p'¼ŒjÈéب=#˜VÁjC‚ÞáGyÃ<p×ÌUÔ>òøĶ¿ ä7[4ü¡ ü:§ù1§y\°ÀêŽì˜–´Õª#vÞOIÀÍ¿… Ðs/¬ùÔ…n/¹ÐçA<¤è'€2NúØŸÇ=ÛéË1:®ÚýÞ}Ûôû#¼©¼‰–ý„áJÞ5ϵœôÉ› ý5J†ßD(³Ç.LïŽ
+þn[™Pcê‚kÈW)1bÚ3ÔÇc7~èÄ5(˜arúéºLõö)ÅtÍÎüURCîL«ŸËnàÜO?óG/‚8PÉ®æn®¿²IE\´‰œ6˜PÎýº­Àô¦µˆºˆtâYD
+{Sbëã<¬L… I©µèZÛØwò9‡<$g®ÍÊÛ¿?µÍvžo.R¯ãܵ/1žâ:LEVüÐ_sÚÑW§n:ª\dVÂŒ…¢ 9’ubû“N>!æX¡ûtK#âEÆ4?~hgLmØ‘¼mºãÔ‹,û1?ZÝ·q[¨v<šÕ#êBÂÎGÆñ¦›(j¸$ÃŽ]¤ÉmÙø³¨d¸æb›²PŽRû–ªo´ˆ¦Œò®ìE ^GðÊ&t`‡¾Ù·Â>\Fɨ¯)2éÄm
+
+ÚïeT#5y=¸öÌèþ}‡ˆ>MPñq ±;ª!wߤ—äEËLCZ2üÃ6oð¾o¡û^Jú©ìDw_©³9 nÄÁÜÉg
+Ï3v­Äþ‚—<UÙæi+)¡«²Ã–D´7a4a@ÔÇ 8ÀAH Ï„ÂŒ‡ ˹æ'÷ì´ñJŒ¼Ž1WAüì…5pÄ
+ÝUϾM* /l”ŽÛe VrÐLëŽxêå©Õ~éE÷^øZÐ/vó-ðÉ<Ô®§ÿŽ0è_袮ço9yë­##ðç’c¶ñÌKWüLlÁJ
+P³ÊO6z_Yz^Ú¦HY»Óô VÔú–æ“Óa€œ ä§;ã„´]âãÖ‹ü†Ð"£äu>ñx™ß] ûTqË1V—bý\sk{¬&þ?;]ÏÍíí.%­Ð6A) iÛ¡%ZÍ¡‰?0’‘©Â¯eVEVy˜c³¨Û7Ç,3 ²L_j! w¸ÞÝ}dä´ìÍbó¼³è4³„œëÖv3öÍýØ^I¢–çýþuQ§¹«ж"ö×x„€ž‡tí4—šÌ}/ƒ–»ªöFëxsÊŽäÇÜwKš’jJÁwG÷Kÿ >Ó+§@Ö‡šï½">ŒQ¶ÃÝX`–_œçÕl ­#˜Û;ãØ» 9}w’[l ÜÛüDJ )z¨'º^Î1˜Å¾ùæ쥰 Ë=Ð3ÆeW¼“ôR@ÕEtÏ;&wãˆ;¡y"$ºH/Þ•às¶Fš27‡P Nøä¨^€‹Ú‰Ž)lšm¤ä’]\uÃ;ƒÉ
+ñÉh¹ëýe¿)9˜Izö/räÌZÅC_I¬u
+Ñ|Dga#ªN, h«ñÈH]1ü®émQœ¾'ÿâJáùwu×ý
+^]J)ßwö̶@€yzKBH÷LSÒ–™°äò93Æ6Ú\tºÚß å¡-ƒ5 «¯Ÿ\2æ\
+-¢Ó Œ²¨–…ªXp·’UæÓˆè{*ãtµ‹}b‚Ë|œOíó/0 £†V¸UŒIú:„IpIÛ1€BÐ]¤ûg1iÎñ¦dÓûªk¶á¦DÐ/µ¡Uq¶§úò–Ÿ±¿,À¯ŠøÁùÖR`®%P¢s\Òºtœ–·· $xõ"¦EBƒlKZÒ³hÐ À´”]‚ÊÚ®3®ÿçæPãMÃ1ƒ{è”#¸g›²¢zü@ÇFœ®r±?¾¶·E äÖ("Þ£$—­÷öª6„wššçšÀ¥zdèä½™–œƒ¥bDÛ†ÙïhèÅ fU»ļàµÈ:T›ìžl‚ØG’}S˜Ì=µ+AeZ†7÷—º;†rd™^Рn:Ó&F?ð«éÅáev]ÈÀiØ‘`S6Xx{¼󳮀^@²Oo~ª÷)q9Áeá³ý ‘ðØ, ®±0‡–¾·¡Íªã¯ïfþgëî;^¡Ö8¦ÑÛ÷=
+2ä?lìdÛgÀÌPPŸ†4¬¦ˆ†ƒ k9ua0“l$dOM]ýPuiåâªu´%uoZPíšdä[‡ðI€¼î”± n¨«›èœ$gm ât} ¿[‡©Yû‹ÝT‡˜ü8¨b–„4­•ÞiZ鉖Zy¢ÇfèH0û4-çë0.ñ@+ÀF8p§ôé*ÞЛ;ÉLùËbWnLTÍ®ô¼í(6MÌ/ÿu_ÍEž®²NÖ˜µa1Ï)k¸k~Wþ›ùUåßìcÔ‡›£ÜüøÛ^)#×.&=Þ•¡N)Û)iI³|DÞØhLöHÛJ,ŸHéŸq~ãa1šÎê¿›ÞTßpŒ5Ü ÌS Ýs4¨²¿öæ(5?öÐð\°+¥=Y{SùûÚëüs:aþ¹•ž²ËÎ1tÊþ­Àöˆi.ôçåWUq‡Æ6üæ—† +ÿ… øìBwÑÙQrÖÏ;è{À³Ò 2Õ9IÉuHé9—äS0ª¦ù™ggø÷c—z2Îo},»Ô1J|*^ýÖF©ý úcSÈ?4µÓüÚ¨säíxE¢u¸öÚÆ@ÃU÷ô3¢m”ödk~Í>¿îž@%,=/<§äAbÁ®|Ç6ŠH1¼,ùÕ>NÈ -P;ã ¤øÔí1l’mqÛ#­¿²ÂÿDmf1.}ª£ô¼KÁ®Š®tº¶Û8îÁú›Â«n)2É7Ù˜R²Ö¹8ÝÛò[kƒõÙ§ëô}½¼5xXG)²WÝ´}.ý‡GV—t¸B­5 3z3®†µ,üŸ_…Â?Íí­9J¾{dà›Ò8 )é'·‚˜-De\(K¾ôWu_uêKçßk\Œ[ŠI×ó¡ôÌ3ú.è™ía$8“×¼öoAfœlò˜ß­ÂÞ ªµr_ÛZíYj|_tÙ:Vý¯C ›XáRíSt˜±›Ô÷½=XŠþkéàž®p))2{w´"Þôºàâí¾áðZß'¯šß]â6홨 
+éè5'&Öÿ).ó¶¤×5
+_gŸ†í6ˤÔÊ KMsÂÄT4DDp”sNƒœ EDÀYÁÉŇÔlï}ÎÕuö'9¿>Àûþñ<ëYë^Äk=»-Î
+\ëÍ|v¹PËúah`_ê1 s6ÅB™„ðÙ,+Ý>ÍN?Ö2‘6%ì`˜¨ïLi8ˆ?,vÚ×~Fˆ¡‹ÑwžÌµÜÝ>fq9tG‚í1áºfìƒ aÿÁHiŒMYcÊö6ð“\–;“]¶%DßSmiü™FÆ©š—¹-.
+:VqRŽÕeqGJJ°M™óòLK†ïJ‰SM¨û“ ™Oì<¢i  h{ˆl‘QCÕEQû_ÈÛÂüæ¡2¸´ýPĈsÜÒ v5gSU¢ÌZè\S:H[sÜåz®}. ‘¼Ëò %úýK[ãs5^C°«¨‘+üÔ‡³Íˆ{ã5q÷tmÙÏÆj ?[jmc•©ÇjvêéXÑ>ÌM¾žàeÊŠ"ÇëN#œˆ[ ío{°(é°ùvÔý##ðëÔCyž¿¾%Ém£7#`_žfåx®öä†^Ï º­JA³_±ÐN‡®÷Q¢®gËÞ^LÑ1ÈØ›í#*sî£Çºüg¥¹ñûR=Ë:No wf:ï &»Ÿj¨QV7ÃûÆd:øj±ŠlUÓa
+n‚;ÉÇ¡és[΀ÿn“LacM_(0rØaUHŽù °û•®$}_Žó[ëNt›nˆv’0ƒ×w$¹¨*ߪê3Íwæ^Ï·Õ_ÍT“NTä³0ÉMÁ v˜¨OvV×%ƒvåTøÉDIÊbÆëJÏÉ»Zøo˜¾øÿ¡œiWç"–(w%/Ñí|®"sKž½Ú“þä@ž¼/¥GXdEГ)FÒÞX1òsY²s3.ìpËiö‰¼i0Ë×4@ôÝö|¬*„ÙÇ‹
+ÏA¦>²×ÊGü3]kºÇ¯ï˜W@žéú¡šºÔûß—ëªÿ»ÑÐb×’c÷ehÈÁ—Üð= 1ìTSðm¦0þ[5Üénbb 1ì®a–ü÷ö§¹+ck—}¢»#ÅAfbïv罸3Û†ò»Z©.m$Þ1ôc®æk(ßçy¤s ùõ·96ÈwìÙTr{ Ö€9
+龿‰awÖ¥%;ÍI]KðÚ•U&nIË ëŸ)þ3­xÈtÆm¦ãòµ“ô|o„?Û™ë«kÍp·kY©ûRVÜ´,ú|œ hj¡„¹ûÂÐ…s;R=GÃI;TAW{“A‹m1Žsµ šÞ‚€7ÃPaÄ`y¬ÃRGA Y‚y``Ÿsã:òûˆ¯njkP÷W?Sƒ”ï±u=¼%¡C ‚Ï醔Fú©îÎc˜‹¼ÓOÝÒ·‡Œ6â|‡ß!@æRÈ‘’<V”'ÛǪ°‡ÊR”MM†ïH²½
+bÑÞ\LVå˜Å¤WÛÙ/e¤@›<?h¦yOÁ„Þùuo[ÄW¦<XZç:D ¿ghAºžª(пtœìËÙj’ésqôB ñéÉŸgê-G+‹âl£y¡+ü ˆ‘õÞS€ç¦ÿµÒÒd¯@ïÊ‹#vÄìx«„q¢Èö± ezoŠðž_{þVfÕ4éùž¦_œÉÁ¬vÏ×bœW>äz.ueù-}ÄB™¾ÇZnž]SÙ½7úsü7ûó¡¦^Ò‹ŒÇëiÌ ]êÌxl’C.f˜3­Yàɺ”€¿n<Ô"cÄìJŠ"m@·0Šˆþ½ ¸‹e¤ eU³Ód¨ûê7Q~ä-ue‚“ð‡59rg”ƒí #Ükp>ÿ¾^¨"ŸNVfûsCÆkM×'¹ÌÖ§ƒæêS@ßfÊpµ„PgaE¢ßÑté`¬
+=×öPÅÿì®®-Áiºê`UæÄþÜä•[µåÈóY^¾IH
+0õâ¶zs‚-ƒ$$àù‘+3¼ÖûÓÝÿÙ{W}®cV…9ž6 -þz¹“½ÔÑþÓÔøþr±4è
+ããHcýcVò_}uošt"¯Ã
+hüŒð;WUco´ML§´ldµI˜SEêRÝL»X®+ز?M
+H‰«}9æRŒ‰GˆßåâM¦§ˆ[`ølðý­D SFÉ83 «ßõB¤MLƒYy…Û}PÏÍnøÃPÁ3ëáÕ¹à}U~c¨ÄÿDÆȾ^oiºXmb‹))¶™üàíOo}·ûßù;ii)+Oþýl–öÞmKÎø±ÞôáZÃ!;„$°¶ ì¿Ú›ûzc ¢Ÿ!$Ÿi`›ùHëÃØç
+þÝPGÿeæp~™Øµßw*I.%¾Á…>ý2òÀ"À'Ê:rcÔý9¡N ³ôì ‹y¥¥~n×0¿n01‡| &Þg*ô`º,Æ2C‹w,Ve]¨98»¨2Ý%efÙ@ÇÍâ".d´Œ+«À!f#öf«’/ÍdË#uóS‰·~ígš,ö×t§º¯¶¦xO‘/ä¤íl°yq­h ¸¤tˆ}oãS“´½¹>{sØ#¯8Àʯ
+‚t}ùÞ§²ÊÜiõ{Ë%n¾<^;„ Uõ _î "oTÍ”}A]ÞÖt8Û†3Î5ÂÍÓ´Xó$.b­'÷‰y¼$ØìÓñ"#íR][r8}u8CL<•¶UëG«s¶úðþ+-¹ž‚šÄû²úÔ{—Ë­t‡¢­rk²*]Ú”ï~¼P™y pé…ººÀ¾T– lË÷’7!Ÿ*Z
+¼,"zæ‘Œ–nY Û\Ut»ÖÞúUÕP¾1„ Ÿ 'ÞÕC< ˜P§¼¦øVÛÞz«ýØdš"DX,Ä…²³Å%kÂëGÉ1+=„pI'6`„ž}GÑX¸
+i™/
+Ü›¿0OFïµN–†ŸŠË’w&P aC¶Ç$ð?®-½R2à»\˜ÏÚÇXOý'Èsó8*jw¼8Ì).»”Õ<VÚ=IKþëó6þZÍÌwI)à/}°§3Ìèÿˆ8'ŠŽ<_U7&\ÚD¥<¿;ÇÜ(Éï ƒpßÍ®ÿgÛKÛžóx{¤èÅÉ23²)×/;ÌýlhÈÇ" w¡f“¬s(a æ»Þ uß(ò6òˆ‘†ÙŠ¸F²{/ô—CHM?“Ôæ],QÓìl¢‰Weã—Äœ+Ê’ÎÕ4Øê0.8¡§CÈȺR–C.¤œÛ5&îv³®ÜÂgd¨:Q|Vö=ûbM願 ÙT$è'Ðaó5ÉϦXàçvI9ôf½šy£«kÕÏRg8àG–E"ü×ASÛO3§Úºˆ}«h{¬õ¿ 8 â.WÉY<l ügCqô‹oÆv.à4]ßµ$ø¹Ÿ´ÍCø­Î 2Ì)®ÉrnãWgºäläÉ
+cž¢D;ÄÔtÇ6úRJNq‰ [#0oýç\?ý(Êß%¯-´Šª`†1b˜eª"È௠ȹŒžy tÍÆ`A€¤|×8Œ‰¿]mo>–ÒÒl q>¬ë)² P§¼ºàDZ‹8° ºOȧ3ôt§„Sddžîôúh;2Êë“îrË¢ÿP4AŸ8ŬüƒÙªLý()ôz­‘~¦©A¹Lø±„”z¾LÎÜ2Õ¶ð?ŠËó+í4 ßwÎÙÍ$›ÉlœtÍšhìQ™$j4ØÐh`A¤‘ŽÄ¨5ŘXbED¥J¯Š¢AAE¤X2“Ùý°ÿÇþò¼ç9ïs?÷uQ‹‹bÔÊ(ó‘g†Vvbà¢:zí¹½ubæ¶î˽ӈÔý9tF`‘
+Þ“uBF©•·&i¥þ%VµoŸç›A¥ÅõÜÀÞÖðd)½ô‡c~ bÖyö•”òÍ ìcÇ[LæúLNXÇAµ<¤€» š‹ŠZĬ½y&Ø6Œ-‘ð_<´a*þt ÿÙðN­,RHE®sO·fí*x—„Or}¦–Yú1÷eœç?Ë9ËŽTZX'Â÷¼#ÅæÄ-JÂÑ#
+ª;ê7Æ÷”"ðE)3ïoû3Ðô¯«TØ·/<¦s— ôzFT#h;³½9_
+Ï,TX+õÎ4Ü÷ŒÁï&LBj`™Ó.ÕÜô/Ð*˘€†Ù1°¿$=3¾dh_—¤¬ W\OX)Mq3¶ñ v×3)¸äˆŽ é­GVÙ0†ÎüH,ú»RXc_ÎoÜž!ä[¡7—»«¯¹>6¥< =6p~½ZÙWwC;Í iùhÏ4ù‘çssŠu öú"ûÉ绚;gVZÓé:á˜h-’‹ 7LX@Kï΢Š<¿
+Ð¥ð­ilÑÆå‰é©pGÉ@ž¹ø,ïlsáÆäjÔÚ ¯tuE]¯úm|š[ɃßÝ¥½$ª%W½WíÁ?ðH°ê’¤˜ÏLk¶©|qåmÕOÞ)tVÌ$$„ÌB‚OÁª:Òð›·§ðYþy|ÁÞ2Ã:¾¤ë.ÿ‡N\ð¶ôÔÞ#Þ—ÓJCêκˆ’]ïŸ"†;êc^«_N¯p~D¥:Þ4\Û—uÔº§©`Ókè•Íá–4 _ÙïÑyŽßÑ™Þ1\^XÙ Û“‹=Ÿ[Óv>á@Exr¸Ô–ë“b²ƒ
+aùðÛu×'4(fx%<P ‰ACGÃéZ'6 Å?Ûkʉ¨pS»æ]¢¿¡”ýP³šÿp÷ Åì|rÔÐÙ°-i+\ýú/¹ða’oúàÿë*—T‹Oì"G‰Û…” ž ßU1+·Ú ]ãˆ{g± íùŽ
+û0!Ó+4í/uáÃË|tDK­Þ•â
+6>£ï»“3±[Žt¢vË{LºímãÈ2¥ð´ü ¬ ôm…Õ6“|J,hW†Ë ÙH-Ý+ØUãËÚ¤ˆ–ø
+¸ËcÛ@í?M½U—<3ˆ¾E\¾{›¸Î3¯¤³Z?ˆ¸cèƒ^ )…Ma¥°9,"|ÓÔâÑvÐ…DÆû饽 Ôý¨QˆwaÒ6†à×£ßßYåSOmthTGªpO£ÒÇÛ¿(€ÞÞ%ä¨Du—ƒjJeÂÂk‹y-q}ôp©ý‰w¶%mu¨î²©ûéGj p“`ºAlêÚt¨bBÂZFmÜÈm9”K¼óˆ\`rý
+FýùZoo@°ãáÑž„ï›mÏMhÙ §F15¤å",È[›³„ÇQëÐtÄ2<·ô ÎÖ€.0ÓžÇ4”ʘ†=ºaw™ƒ²Mâ@3äÊS[7Ï/kË÷IšÓw§“¿ŒÂïF´
+i1›˜©Ĥ˜ßàAU/àbÜ™…‡Žˆî)XÊŽ¤)-¬!AÎmÎ)ÀôëSÄB¿Šù¶)®pq#±òPŽ,t|¬N6½«LZùØxëÛqŸ_Ë@jûáÉ®q(nsÍ\fÌÌ&†T$°OŠÌ +ÚKBJZyÈÒ#\è©¿­~ Íëø¸¨I€;6v688¤3§³'§×'q9Qk齃c`( æ
+¿¼È%<mwRî× ±AC/{[Æk˜6ýl¢l-t£væØà€‡Š¶b×üO+©µ‰ÿs\æ_I¯yÿiî=gfÎíÞì–MMÝiê–šu­”n¹f*.˜;‚‚€²);Ê"*h¡×%ËÔÂQÙ Á‘}_ É–{ÎœùCæÛüü}~ø>Ÿó|Þï×k¿äØÜÛ§ ÏR5_æÚw¼ÝÝ}ºÏæ,6ÑwÖ[ÞÁÓ­ó­éa=6ô±$Ä|Ï* ÐÓà‰]Ó!¡<±Í‘ò½Ë”R`ç¡
+jSµEg"è-—}ß<½בêOŒ=]uw[TÝÛ~làßÁ2ôƒå)z~õyÝ@IÊþ8øJb þ í#î¾!€ÔCÏR€ÿ»]ï*÷‰QÙ&×%iýÍ%ÆÜ ¬’ËükœÍöáºà¯©â °?Ñu\ p‡¢€_uø¶þ†õmÕeÏ2"ûÓ.øÂ!Edù¨ï
+ªÐ¶Ð˜P´?=5ry_m¼q¯ŠøL÷ôª[B®Šhm€¯"›Ô&§ W\í‚$4´–Óm6Ý·Æ¢,öÔ_Ùà7çÇT¢m¾dš¨½t0Ó|Ë%m½V£ó>ï±i@/½NšB»Œ\–ÜwËéPó«Ö4 |NXå»eòã3–iDvbwp¦êgm¼€_ÝÆ€bZÀ‘ ,J\Ï¢Äô,RLÇêð
+FOm½<à$QŸÙ진4Œ&ùÀ¾Øp#¤@ƒ:zcÂÐð¯
+ÂJrå1ð=´ŠÏõÊÐ9»ojn™Æ+n8f0÷
+r½c¹»zssÝ'g<‹ëzÐ~®Ð+Çäl W¤š†Ë.{àÙ eY`Vè„M–7˜Òš^¼g•¥á•[¦åý}“_zV7þ‡{™PT±ëcˆLõ ,+i`¢ƒ«Hqœ:O-üq²='EF/LÙ›„Ý é¸ØíY£9fùO›£ðŒ¨šKJlqÉI#‡U“ê­ my.À-Ý4ø?ŠËü-É5ã?7sÍœ9g:ÓLÓ±šl3³c‹Y–[¹a– Ê""û¾#Š€¦m¦é)QLQP@ÙE\@EPáeQ05kÎ9óÌ{~z~y¯ë¹Þû¹ïïýùX_v;†ð³•ç@Ï* ëðUÉE.ìCLP‹.[*}JDVd†˜‹5÷>»lé©úi{ }ׯDç3¤gû "Ö¾³²Äü
+v.¬ãÀý“$È›'çã·b`vÆ ¼Æ]«
+L“ ¶wðó«Šæ{q;pr‰Ñ9z]ÂÁÀ
+,¹"êøìn—&<jÌÂDz”ØÜø<u<Ï!üwíÅ`r±«+bîä4Ìò€
+“½üKmšœvó„œréĬèΟ<ðÌÔ|#¤a?ÙTÒ
+¶TÔâæ60Ê
+ŽÃ®¯¾/þ—µçþ_S BrP/¡º†¹ÅkÃô÷`cfB¼÷û"ö«›KqO¡nzŸžw 4Þë$Äm•òkù¶{K/+ýÁÙ÷<#ª{!Œêú^§Ú›|£¸{ÞQbNHǃGLbò¦Š]fé†ýÇÒ^y2¨ÀÞŒké{V6<j¤@v¦ wtíÍKÃŒ|÷!ÛóžîŸÀÜŠ›¸ ‰¨»6)7 cVmM ®zbi|®•¸££CÖåÏ.®•]káÙ¡Ö³˜õå›ä|ßxDßFjZ¤Ôš¥•{Æ[îo©©%.9×5JÍÛ™áBc60E}´kÂjiH…Égï²ýUÑÅv=n¤U욥|ÀÜ-å?úÎÜ]—åUPk¢ô`Žò<e¥ÕÞT¾4€¸ä›dÕGfÙÐÅ>ðeÕ?ÎHà醮ºL¸‹S*aa5¸Çð9sï‘×\
+Øo‰ùVÒ¾S@Ù#UìLË–…¼¯=G+²•Qb¡¡–1)ã6> ÆçkÅNÏHò¿ L¡ï®ŠÀº0 ræãïUm s£¢ ëFô¸ÂuECÖº‘éÇÞJXYˆ”³C¼6BÈuö¡3£Z6úÛ²¤ó
+óþ"']ýsp¢¥4e—Š
+št=¨« ý¸ûI“
+hH… + ˜8Șž
+ùl£BÄ- ¾4HyœUùyµ³oSK©ZnÈtÔ^t€g%æðˆMDÚ6¶ãÝüªeEk­O#c¬OП{¡9 ýÈlç{è倪éᮑPù«§­3æ³O/Æmë…I‡¬+få!3ý™OÍñN4ÝŒÍ1ž¹ÛÄß|¼ÓÌjK/æŠoJ€:rI_üæ¿9^b6Ǧîx‹~´IKÏ®7?
+ZeëGr¡¡ zá‹«]ú¿€L~슿:™ä]ª"<Y}cSY{)îp÷]=Ã.%±J-+?õÅ+íÿæíV~qó%1¶ts™³ò11sksxVˆé85ž1j[Á,\SðÊÖGÛkšŽæ¨¹ƒ6 Pî1ìÏ+¿ /n~¢äµü:Ï'jÁÊ
+W3 Pkòæë~5¹
+÷^Á&&m*yÁùôÅÆ»6² é:ëÒä2ÔY¢ßL=ì ×lN>ºpàD%Çí‹¢•$L‚»À‹øÌŠ·¿À¸‘ÔSoµ[&Ú/­ÿ«÷Ò.àö˜YF]Œ×ó` ¿„q@äy§„ûñ=ùVlX9ø¸J@ó}Î;¦)zTò’猡ißíéz«Nƒ·è†3)5a–¶tâ®´sb<aÕ«’ž±Hzc‹Ì¦¸ÙXpKûAIsaoÒ0x«`G
+ï|J¨àƒ˜•
+V)1gæ·eV8-ÑbíæToUv…×zº6:v°¦ÆìC¸Ä² g{–Òž"]9^“ ‚°$b<p¿¡}³¥—ÑS&ëA0à‘œWê±JH9œð 2ÿÔnÿ‘S­Ÿ Öf\Ú'¥u6ïg,¢žÈ\_ýÁª”{üqx¤|¶˜´ CoI¶¦éÿ(yš°
+{²aWÖ!èLZ†:óÀ'›ÚÉRè©.b‚i §©ì“Òƒ° „ØyÀ[ù5¥$ë…Yড½rÆixX½gìp>'~™2ÊÉ9§:ÙBFÙ¼›KHY@/û=ŸÂj}I¾ uV}áxÕs÷ó®ú‡ÿ% 8kê
+ò"f0%a•Š~TZô‹yß?Š›Ä]¬cszèvD'¸»o”v…¦xu¡w¤ªè¥³ÉiÊÍØÔÔ
+ÒŸ¶¨Û(ø^ ´*ëÉ» à‚éq“œ°=Ǻ|M:ï{N<¿ö’r1:Ë?ã-<à¨î‚*ùQ(ïUòR6ÁýœcðNÚ4
+“’F).ë@XI ÃÍéοDçq/S®Æ ”«I«±èT
+*ÚWIÂ/
+[Š>„]"×Fõ=³VЫ!2 òGG¸Töˆû¶õPWhnàÈqBÑ)ÀaFJý‘o =o¸½=Û÷÷0Ð#æCÛ+JÆüñ\lAØ–wˆ˜‰Z—7QëÁY¿õ~ðÛ¨NØ’1£ƒeߘvwwksšZ•µH(i³”
+Í$™%Ž±ck\ˆ²/‚ˆ ®Ⱦ .±Só‡Ì—¾x/Ï÷ÕùÞ÷}žç·8‚¹œr°i¿îJ„9;ñVÖÆ@¸%ÄÊŠ´ÿÀ%ê>»÷«O«=ökµåUµpÏ£Éþ+{óÜI‹‚”µ‹sŽÑÁ´st0bP“?eŸÐ›öÏv§1ç3V&"iå"ÓVaÛ¡W)ü|òò$¨}R^…r1Ì@GÖ6,ˆ‡ÙI«º?m‘âÒ&NSÆ"øè92® +Nëدo©†R.ˆ´r3ö1U¬$ï¨}#«qóêÕˆŽY—²ÛÀw?lM’jÂïú®§-ÜæœêŠÌs¶§n†Þ¿Êy¨ªO«ÉºÅQ#¿%²Ày˜²Ã¤´ ä°gÛ:>Òÿ¶ïZhš~päzŧ·JXEè¬&¦¬6n â^sÒ*hݘaÜŒ›…­åU%¯ºÑBãÏFf±_ÆÉ7¶g(ײvNKðÔ–j÷N°¾){³Vq{ŠðUx_“1ñ[²6¦ì’1—Çž——a˜÷fà­˜‚gP’]’SN‚BÒI@@(­:OB0ï8¨É/k µ×¬Û ½syq¸ ’ÆÞÑùÎ/bïñ5;Ó]×’&jsxMÞ¥’æ]"ÊÁŠ’²RÆ6p?a¤ÖíLj=ÏQ ½Á×&ôÜÇi»’åyËAiH7þ0!h®ÍXĽE»5gdÔçç@¶Ý›gÜßœ¢Ü.x¤ÌˆQF Œ|{PÁÕõ!uiEÎ;ö úËN:"¾Ðùuø]ûÅàæéŽß©ÑöyÜ.ä}€Ž¼2æé:Ä<ñ È[˜ ¶‘æ?o½£#ó¾çÓ10o©e¸h¢ôÀ§‚Ë~ <Eõ¿°BSõ21Ñyüׇ go«‡‹k"bzIÐù©q›´;j‘+>˜]\â2ƒo0wý?uü£TÂA÷S|¼®¨‘ò]ÔÂlÉû$tÀ$U¯ÏqšÒ)ýtglª’É
+nQOÔÀjØÕqê÷Í|TqMLÿ“kNw%’¸¹UrA€É¨uÅ%zÃoæüÈ-¥UW•‚§Y±°[¢:fC~I„MÚh‘÷ø«…%vkqEJIYåÄ„Aü8²H­ó·ŸÝ™î¾tàá ü\ÜI€C8XebO7`þ¡fƤål2bÚ"@Çôœ¦¤îNš!,¸ŸXuËi¿ñ‰ ÂmŒw×ƨ E·˜PX•Róî'Ú„åßÿŒ‡ÌgQRbsbäî$ãÖÊ¿ÐB㸠³¸äàufÏw®¼¢]q½ÀŸg}Q´ò§Í|쮎õ(òMܪá
+Qò°Zã&Ê÷a=_ò?ùä®ÑÒº”~//Ë™)=£9ôº£fs]3ŽúÇg„³¿÷ýÔ|åctðEÁ/çƒâm©Çª¹øhC­©dpÂBÇx_a¾ôþ{n_ÏF…”°i u~g¾÷áOD9 À¼~a_ÑÂî ¼Æ#'E÷.J[Ïþ®ìRÐËnAWeUÐUp2…çp“fê½Â2È«0­èÈàÿqÅeqwÒF­ˆßø„½U¯¨dTè?ðl[l‘Ý’2òZ?¬CE×@cÊÒ]›0®ž
+%-if7ÅôÔ;;„›€è9Í¥%i/ÐÕ¾´YŒ^E¨Ý× <(­ð±‡ë"rÞ QAÎ#í[ä”s· 2bój÷-«Î6Œøkd[“53‘ñ2a“õìZT” ª'¬“ò6ˆ_dÜŒ÷\Úœ"_gõe–UÜ=“ eÏu$­OAßßÌ'íφsËCÂèBÝêÚÏ& ¼Ç%·Š[ ¨äQ›·c’t¦ÜeÎ3$K9 îè{Ú÷ÛoqgÔäl0Ì”ŒÓ‹Ûrv5'©µíÂŽŒ™‰Ø›¢ÔíNQ¯‡gè·sV˜PZR³csœÆÐkü¥íI•¼ÑTpг6jSÜH¬.²SKòœ{d(ª§?M´ý=mä ÓFqGBǬÿèƒy§[£?g<
+ÁžAÐ’óhUYÏسœwìEnuH3²š¼/Ñ—ØûE§Œ[T÷{dÔ†g%“&õ@ÒÄ@–\ttÊDk ¼"œ7È›ÿ4Ë¿{Æÿkï=¿É<Övä`DÞ)"Gf(ui‘s²Ú2.:é¶g—†¤¯VÑóQ‘ÖƒjP=TYÿ?ÅeþÔD–Àñ_­šÚ¶Ö-]«]Ygªt=ÆY¹d$\Ár;é„„KtvVQ0IÈ:$ä@’N:ݹ¸f¶öÿØÇïï‡î÷¾×GÛ…/ÂbÌ)êLÙùuI›¨–ð(™ÙÐÓÉ\ wh? Ø_îRïùÕÒ”MÅ \0; Þ5aeW~O½wˆ(™eX²1K½‘´3$œbæQñpD§Á¼Ï§‰å§¿a>…(‰ðëòˆþ„Y\i8?+¿}ÌÕSþWgÅá·¤{{!ô߈áß(Ȭ¸SAßûÒó
+óªx›³‚ª/cm?yGjÏ}žh)A¸$°C3ˆœnÔWœ
+} ÞÝ *ùEo¸dוŸ¢^?¦©»þ§'ô›gAVp0å¨"aN!Ø.œÂ)k%<òöµiÖÍVQÔÈ¿‡ÎKjò>Xø{H eÌ ""£áCÔ$«Í¸”ôœ»‹‹YdäŒKNKÙ$ —´=»¨`%íRrÊ%£ÆDàäõ¸CÍL‚ ·)©áIÖ-׋¦sñyaUQ²b “3ÎniÆ£ìÉ”r3î%Œâ#&
+ÖÆ:®¬‹ïG>*ɉ9y fQ¶¯MAåËÿ鼊ٻd@ìõ ÚÕÈGNQÜ*ª#–¤íù°Î,õ?Ç<zõØ“€»¤ÙÕÁɤKÍÌðË¢vEÞ Ñƒ°rø&ç7ô¦Ý:É~ ïŸ¿”SÉ
+ˆ@<tlÂÃy°ej½–:ÙžæG&™··ŒÂ&Ü¡þÔ=ùßW™"ƒt>ŠÕ¡÷‚¢à¨ðnÒýäõŽKѶÙCÔ*iÝ]VþXU “¤a{ZPe®Mµ_Åœâæ£ý˜´ólLR.}k»g×­šd Ñéó@ë)·2éàÝßØ÷éT~­*ç…¹3œ’Ïš VGÉç¢c­×ÓVfÕþ²‚}ÒªÂÚ®¬_ÁL€­‹ÎÒ®&æ:o&-¬"Â.®Ëºô4Ð3á’7§çä}j(ïë‚·”’°±ÊP»¬)nÕ2öÅŽ©W„ÙÔi7ÌBAf£ Òú”CÚ”v+Ú³H— üŽŒT1*®CzÊþ‚» ã¥4Ì®dÅ­ò–è¼¼!ú ¦lM
+ÊÃÕßn€oÝ™dÝN™$$pjnQ eý]R§dƒ|jJÚÅ 8©Ž[É×㦺‹‘ɦ‹8`,¢×f<OG¢¨Þÿ¦ö|øéûè ­0‡@Í€'A·–Æ™××gÄ$Àj= «²ué5åÁ×Îe¼G»ˆ¼·C-Ó¡wàÎ&xw£½]€[7¦9¥¦ÞÊŸÔ¥ßD§„¥À„ôÖ$`œYVq9i·’Ž.Ikc¤¾¾¯ùng†v-³(ïÌxGpO¯!aWÑS Ëâæ£ó@WnA3:G-I-0+Ij¿ÎŠ«q¯¾;<~Ϲm64 ?>OXé·r^~ý^@­H:»¸[s’jÔªãÆ,}²¸­W¾>;ë®9…üRsª9 ¼LÎûô½é%"Ô¨²¾þ! Ûg{_`Y.$¡G¦„e¨UÝI möHÏm?j“QQ›²-Ý ëúÂJéæ,ý¾o¸± çT,2 fí î†Eq«ÂÝ5áéÖí5º?ÖºŸ0 K“vYóÁŠFCøäì„ j[µ*± ¬ÍûeA¹`×µâ^í×±–ÌâÃÝ`Â5†?4]X%¬O´
+þÙà ó)ϤäÔ  ®
+:N>pêQ­
+]§4†Íìö°{¿¸CÅGßg¼*IÚ‘³>•8iW2¢&Ùô :NsÔÊjÏùäüÒÞüOùÀ?µ'&qÔ*êÇ)3‹Hi¨šÙì}ûαÔ}#¨a?ˆY‡Mó°÷»mç¹öâha9á„ÙI›ŒXB€— ô^Àv8Ì­Ëúžü+ï›{·òºÐ JMh\‰nÐ6ZCq{l¸¼qÏ-”šÓuJ`y¨Xx™l•w  n~Ü2ÖSÚXå}ÕDñàÑ‹ˆæõŠ!À3C˜E‚‹¯‘ë=‹-_¦ÿ°û¦ÿꙑ 8W6rô‘ßîXÄý)ð†T®ÓzÊÞI¨àáã&À ZÊíŒCF, Sâ‚gn*æ€F¶V˜•îŸi·¼/‡®~6üº/å—w¤ÌÒ¶œ‹9¥Ä’çñÓœ}z<cïEÕ„ëû¯ðWNWh• =¿ ³rZKn ±àSp³.#çQŽå
+}”ö;ž’/‡×YÍÀë8ň]Ú‚x +£=jâõ`ˆ„”t)Ù)÷â‹sã´À¿Ì®=xO« ©‰UÂÇübfa[ÌK»ÆÉApSµ´ºŒoB±K‰A ½
+]cÔ%üîœOHúõH_ì«fcN©èÄ*èN¹Uã`çÁÞ’÷ß’nyžãnVi+à&û¤òà«y9|u_Íê(þ`J:&%GïYw–ñ×"køëÀ™:³^ÿÓá£9ŸR~¤&W„68 ‡\”õJYa#¥.l¦ÜIþ
+™(Ugzzciwr¸Ñd‘‘1—”SÚUN¶ä‚¬Û—vp{.)#ìV0#N˜1‹ûϵìºýWƒW¼?<ø›yä>jdÄ6Ç¢V˜²½Ì¹cY$^Ž9•’R`f!¨¸9‡d8eൕ\ý¯‚Š.9-ï–QÃVawÄ2Å9×ÏrAž‚¹¢ÝÉúÈ …m^oy[L-úà±’{~!e’ ¦ÌÂnÌ,ΚTôäÆ؃ƒ×ÿº9WñûÀß$-ü®¼æ—ü³sYDF9Ö+ü¯ïÕ ÝÈnrÛKnˆTô*¹I»|4fVÑÃ`Oâ ž¸ž^‹jÁLêxMa½°#f…†²îiiÞ3%Í"0#nõÞPnDôüöœ æä\äákçæõÃ×pol ¼:Ö{ò±ïª%Ô„ôÐ<ŒmÎÁ˜c~êX õ
+ö( g×…çÙõ‘=šáb³p£ÿ#½tux¢¥xÇ"DC:Ö}ÜÄ¥n™9_ÕVíSrïGu|J`šZ´ü¶ê;l¦¹tÛˆ
+#ªÖÊpcškôþ9ûÛº ŽaZÆò\äžD©¶1ø¶E
+¥mÈé…ëcÔü¤‘KûËŠð&Ó òÄýY˜s¢‰À6HMSŠkŽÈ¸%KþÕvòp#*ÂæúŠÊ^è«K ª9õàz+²‡©öáÚóéƒ ®w éQ½¸3þ>šrÝ“Œâ½‰ª8ßDíeçЭ#æ—¹Ýt+™e!v¥ëE@+lÛ˜¤{¦e˜aÆ­hwÜ*~Žé¹4°›7Öä´ÜF@ éxdSý… ž}v%;ä%³îo‹@0³©{Þé'¦-Q³ÿl
+s:e”›ž)æ †Ó
+H‰Œ—Áne¹ D¿Àÿàõ
+9£#¼oýè¦óÕ|_ÞLò“) /è°ßxšß!óo¨T“ßG}•4ƒêÌJ‹‡¬ Cbxˆ ¼2hf¯‡F^‚Å|± ‰!!šèà>
+…küNÑIÔ™,6iY+ëU“AÏÉ M)±!ðƒYß@ÂÓU)TÌ‹¡–ù¹I‘=Ñwrïq”w•œf·%¦@höD&%?‘ Ø6`[Ï ¡ƒ$0„˦Ÿ8€tuÄýä¥ÛP(ÐWœ*€Ìá5?•-^¡û¸ÁFh,3ƒ!¶!ñEŽ¸€í“Äk×ôdÏ»RäŸË1—×›ä^DÏÒé‘ØÞ!)R;½2¹ÏÔL[í;ðN Þå¿^1O˜Élt™È´¨®Ÿ}î9ß2¬ü£é§Ã“£2tÞ†è$¦X/µmÞ˜¤´ëb’ïì ÆЄEÀ7)˜mÌ™ ‡E9:7ægä†@=ú‡w,x…ÞPk¼u¾Kõ‡w"Ì]øÜF2Å [næÅ ¬PoZÔó(>
+•jÍéùëU€k¥êK!%8IPˆE]æ}Ô„×&ŽÆÆ0É7‚nv„Ö4t™Ë¥ne#os‹£Iµ‚ÓcThÔ×¼9$ ækDãr7ʘÛMå˜Z£œL† I~Ä$ò‚qÙuùX×U3Se¹;4áWÛUi.ä{xЬˆ<ª&ÊSOñA_Ú‡KÄ =B˜šÒG† ïŽû¨P£Ã¥OÈf,M×äJÔGtZZ „A‹1PʾMÕ@A&`ú¾p§É0ôZù™0L  2!7(º þwü9ÅiË$‚ ªLè)­;JLŸðÏÚ²>#nBtÆ5A¹äcØÉzs#¸º<÷p™˜dYDù©…€p¼‡þÇÞÝÃFç"5õ¼ZCv¦ÜÀžc©T6ÑfìÜ¥¼*Åf78R€¯£S7#šQ¤Ëï÷Ȥ°2vˆå ;-H¡¥vì8Œ®Ï°¸_t…Ê Àí‚ÑLý#…Ôóã8^„¦ò{
+zÊÔ§ã^Aß¹Óºúû‚2Ý0ž ;ú¥­IDw®ëór¶ÏÊ6!Uü Z‡šÌ„ÀéæhA G‰bŒmM4l]fÛæÂPÀŽò_9[ Ɔ%€\- ñÀc ËåÞbð‹Uy`×Úq˜ê¡K’5üVõ8®Ñ¿€8›2ˆñ­÷I/˜å®[¶¡æƒ$¢~ÉÐh¹ó‡Á ¶¿ ?ž*ñ
+úøN¹TÙ²+‹åTËîæP„Õ‹ 0½ve?Å{ý|}f/èZ4– þè‘âd û=ZŸO Ã6˜ƒÉ¥,ñ°"Ý
+ækË ?ï^ ÉñmfÁçF8üÍ6Š¦:ëNø1aôt©òŽG‘@ŸeËäuhÅ¡o>€>¾CÆ_Š„¹E‹Õ¦®á
+ 1—&a¦„YhÉšÓìt.&r`”'iqA°Ex$Ö× óÈ:
+Qðrm°¾Íç8¦RrEúÃÏr}Š^º˜&HŸhœÖ„ej÷
+†¨Nr“±ÒB
+ÎÃZ^꽕î¿õû¨e²¬ÚtØ”$ü)
+ÿ ×pP+û¤ÿ…ç·
+†kÓ*ø? ·-ð^K|qB…„;ÚŸ|ùÇ1²êÉôË`oæü.YEc˜ô¦×ýM 7˪±&›K`Þ˜!”áÀôpA¼ÛwÖÿ3Á«³Ž!>ÂìÎ'%ƒUÂ^±©ì£.EŒÞ*UÛSŠ}§&0Ƀ&E“E[ûU? Xn°{I›ŠöIXHžÁŽæjEƒqgy÷”œh±e•™c‹1 $ØxÙûë,¯ ÒWBD“e[[v•š`ñ¿5T‘¬¸nÖ%­d²ú`Ø™ØïÔUætγ¼gŽß°#e heÛfGͶ"º-0…¼ÔÅ|–GdJ3—6ò)Þ>êRT@8%ì±Úw˜+ Ee«èÊtÀ«»LGM” ´;Ž N ›¥Ê[^ð_ZEjÒ²Ô‘é ±Þ$3Ž]²c`šuÔSdƒõ }èã|ÖB
+îÉ+HÝ4eaק$Óoʶñš$ç\·®€ØõÔÛŠr𠘄¡i¢€\­s0.jHÍ(^‚Ó |{ï>Û
+¾1‘?G¶•ü”ŽoòA2¶¶¾½ÂÝQ¤ B¿sÈdñX:è Dª¸Sé&…·•¹”8´Q‡¸¶¾Öówî”ΰʌðž+~xÔw9Ù·9®‘˜ˆü
+âV N†ñÙÿëT#ò#g,YX Ö ^t8’HGo¯µJèˆï<Ç'^†4ŒB)‚ø=rµH2/—Bldé†}§Ð&_Ñí[Û‘a E—¬6X
+É äù½¤X)¬1BUvsàUVó7Ä;‚ Ÿ•»ænq›\†ëYÿnÀcR°Éàð„æ]~C§iX8îA6¬v*¬ºþëX”3D,ƒÍ}„µ,k7J¥GE’*¼›
+‡u)L&¾Y —­Z }sqFÒ ³Ê€8tlヸ!ùg´“:Þç~—X­!¼‹ë ´÷øĽG´\tø}€o·B)]Ç¡N4ø¢ìª£×IèËLYÓŸñ ˆBbk¦úI¤]ðNòÅÀuÙ4âÐðì ÒG³¶¡R,zâ ä^ÄØe7¥Zò៧"(ƒ%E¨¼‘
+7–:EIÓ[ÁþW8 ——ŸË A‚YÕX‰$"_§¸¿¬%}'Á8 $#:tš^EçàzãäCpÕJtÙZ¨ÑØôþœ¹.Ç*ÚÖè2à• 81ÝÓJ”'˜VL°Ge¸® ~¸=(ZIJӛÃÞk0Z¶=Ç.ç&ªËŒÌŸ¨9q¼
+ŒúÇie¯E¾²¤9Qi­Š(!¢r0'-Q¼F^‘0½*gUk¦8„='‡%'"ªt[w|$yJv¬$IÉXFNaÌ—˲<>»s.Aôf; Gsõ³ˆ¹íl
+JŸóíp‚+ÕâçñU”ˆ˜º2ìt³Es3ˆf‡Òk“Öç2ÚÛ¡Å×ÍX£ê¨6"=¥4÷’?¯lØ¢4tæ1”w€,ð[O¼Ôh46[Ĉ›â7šq‡¢cê‡'R¤c[QE%!ȈŒõrÑa§Ë”´3ùåÕ¢ãæs“ÎC7åå¢ [ðRÛFzªØ.<yËVtË¥èó•ÙýU­Rd¡é‰öCñüÚ^\Ö4Õ*U|Ê÷2ÿEŸVR°|DÄZE”^„?œcß%MA®ŠzS¶’Ä[¸$nm ÒJro¶Â†‡d‘v§²–˜ÙÔí;P7€©ôÚñÍñEœ<B~R’{¡¸Ö÷I—rs+Ø%qÚg0Ëf?wbý1[ë†ú`Âæ%¹Mâ¤$¿Žë¯’ph¯v¦ÖºáœÕÂurUIû×ñ{—¢cÑ QI6—<W½Ps“z5ð•¥^ p’-
+þeÇ(¤‘:ŠÔâÁr“*v= ©0Ú^]‘+]OƒA9™¯¢J¥Da3
+°U/3O¾^îˆó™ÊD1v ÔÎá!Yïæ.— 1ÁŒ ·'ÃÀXϱ尳UN^ˆŒ´8ÅX³æÌÇ9ʹ†Qn* Ióë (<î†ØVÏ‹+þ‹9]ôWêf¾¹‘¨Ü]Zøp§ûÃÒÎxÝAé¡m@øNóX›½Ñ{4„ïeûꬬGüº‚¿¸?­ë^Æ] €ú¹e¬ÊLªaÑd=ák>çÄÃîâvx§œÝi~hK"çîa|¥—¨Ë¢1¨Á >3}×™‘¢|eÜ×s†è´/æfWwÝ s8êñ”
+8m¾>%$ó賈Äú.®/ ç'
+lB]öƒ‡$Ì@ô%Ôejáy7=-²œ#Ã…ã1d™ÍUàüžTÊ‹}Aå?Eô~§t{]yôÚð\úVbPxÒk1#ÃûcŽ1Yæˆ CCË»ÆPb–+STv¿©Ô ^ýõsáÕº“]=³øK²“3‹3‰!é,»:ì
+)bë¤|èŸ½Û‚Í ÐB
+ï¦óbäǨZÄ_TBCÆZ®An»N"Æ´(Û…˜ âçï ¬RËÇ ¬
+É/Ù—Ó–ëímI¸
+B€,vŠrÚ’j*+)÷ø®˜7Pxõ×ÏEõãìê‰h²ù_ŧÌhÎÕ1Ê»!£¸üöê˜Ln‚}lèü–ºÂ“0Âè$F^_ýUê~§t{]ÀR7PxÒk1£ÆüXñÓ˜¯ÿýÒn¢4g‚¿/¦Fº1µcÔšäPR%ÄÁ4~ĨÀv©»í\X-¸½M¡©øúU%cn;ƒÅËÛ#k >‡^Êẉ#Ñy—¥cý>Ÿt’ž¬ 燸Æù@¤¿J4Í.ó9_©ð“ÎÙƪ÷cÚC–àœë2ü)Ü™ä ’ñÉxò]Í—ò¦¦e^TÆ2X\;âÃÏp^›¦Ÿ3WÊ9Ì$¿øX3L”x¨8Õ s«¿
+$n-Š’ÍäzÂ÷¯“e<ÌFsŽ§ @xJŦƒkMûÓ\øørGIøâ_ ž-CYº†<c!÷^>Ñ÷-p4–ÍËÇphsÊoæûÛž^Êœãp
+±¡´™Èxf³Fá9 A©÷²•_{{”$…DÖ*—|æ¼È]â!O0:n›5`9 ênÇL|mÉxòÓn•—,È=dW¿‚£I°
+·›¯ý÷bþ‘à5Äö bJ¹{Û!˜v¢eæâÚá…uÌ… •6†/ §°šœEUÆ@@«Ï`pPvfa]Æ&ý¯†¨C4ÃȨaI0c0Þu©n6_z”iO–é#Û9£uÑ'ÚટÐa¶k¥úR'D”±®/½`Y(š¹Eýò¶ch ®gÀù%põV>9+:YLª_ ßQ#^AÏOºõ‡œùh]L
+>7‘ J«Žþnôo höoŸû$ò[¥cršFùM >…ûøÚ–p!êµxâp™Šˆ5ò´I º1áIóc~Q ³3.È#ÀL£ïžd±´@z’ÁÁO÷ÜØ^˜šò›; ¸<,6ƒo÷Ám
+OY4îûWW3öJ˜]¼ Ç”bÇÚG¨uå’¤ï«-—'â—¢LíÕ‰d;{.Ÿ()IŽeèžtUB]±“ãszÅÈ15’aúÀÝ7,ÛΡÑS;›Ì ú²æè©À (”NSŽû9øÿÚkJüYòÕêmñÇ8s–ÂG”ÙTb™©¼ëƒg –¼Ïìú³;a¯µî›@„€í™tóÀH#ªÓHº”³ M­‡WSfQ-Ÿmâ¿¿íI}'ŒhZÐÓA¬=¬clï¦l}ýˆÄð²'~{:„›b­LiµUoj²^À!øÁ!¡•Å»J ?•õÚ`ÙUf{Ú!hÕ\
+›Í3ÌGÑæpBÙT^ñû`Y;ñª°åR¬ùÓ+ÌñNÖ »¬[q­âÕ²-ËJ–*(fgë– (ɲU»¤¹zÆÛÒ£i_J7ÐÈgš\Áw€–¸£C8òÛ,E’[ºèÚÐQ&©çQ°
+£áùI O8f2Σ?¼"\?ü3ËŠòMµêÍ)Ò–Îþ`r½¿Q%N'ɼ(âïß‘Í£®½Óæ+)¦FÞHêÚõ-$lø7f¥—OµÇD£ v@ *—Ð…_J›ºñ~pRþnQäCžwŠŠ¯+à8dz^¬ÄEá—^›Ùž¿ìøLÃW°êr è¡­ÁÚfpx؃is_¸)éÓÆ›[5L
+j[‹(!’[ó
+äÛ“s‰æD‹ÅZ÷Mx0‘qÝæNtƒ<(²ßóÄå hnY7tK£³"gÃHKSéÎlô-©¡x”²È¾ç Yôb]Ht0G²Ó(;ÃIlÙð½Ó“•fç^pJVG÷2æðÍl ²t©£3:C®Ê^üøî‚Î:ùÁ‹pˆ¿Âeö-•ÜÑæ¾OÎp5¥›âGd†w÷{ÔK‘±â”
+CQ"|‰cú5™pšJs%š¯T­˜›‰HOp=|£”Äž/À|éGÓ¯
+O¿d’lÍ¡bL÷5Y†ƒó—¢ŸaQô‘!È8µÓc¹{”µ›ß†O,î_h‡/8vûÎ:õ¼É‡)3
+šV÷þÁÞ¬ÛØ„ŸÚ×r#b€•£ÇÖÃ'j^J|¿Ilî)Åß ¬(Á¹@Llð›’/nõ×mj+¼ŠÖ°Xø§|áñ­Ä¶×íi£üP‚UÇÐi”³ð ¸kÞžeç¨Ô¼³ƒ­¢Àü+äPö»Èé.WäŽýg‰Ù· ¨È™ã /JpXÌÕ}˜nÌ>c;æ©ÀS2R´©µg…4‡übáBÑG Û‰Ù™rl[ Ÿ7¡„u-kü"ŠPwfÇwë;C ¤À°™Í\a£’ÿ“ŸôRùU¹Y4aÿˆ.£uæé£Ây<
+ÂÑÔ:±ŽDvzi¼UuYÈKÍAƒ›.Œ3ååx‘pL/%>§"Eï¤テÁè´K\v/#Ç‹©Û[?±Ç£L^œÎzöî‰ašƒ@Ìõ­/ÏMhÒ$ãp¼ä°äë¤öÚ}ü]çñ ÐDö ?†•‡ÊÐÜ<OžŒŠ:WZºÔ\ûR”Ðè‰'Ì××M¨s=%#ù
+<ÉzcË(°Â]³‘ÿ›Ê+(ì¬ç3 9Ú^âTÈÇ)’àNò)!혴נdŸÄ*á®øö</ø,ÍUÔþV¯cE@øê‚þç)éôÄ$ u©Àñ¤‡ÖÊŸÍIYšÉ¨Æ:ß%×:,ŽQÉ—QùQ/E¸ØxÆ¿öÝ/Ç¢ŽIu[·ç«X$æ‚òp›ÿõµ;²’SNH"Pý;˜0:•Èt^’•@›zg5ùvA⨰šQ+éÝWä8Ôùæ.øEozÀøÙ›Ç2<;üWKå²÷x:;dvNLúîÍT‚¢óxøt(5÷¤ŠIò¾Ø¿LY±E~žŸÇcßæZ÷ñ m‡R‰.Y¢hø‡pöš·OxW>‡=pA2<ÎPŸÙÒ7%²F¤*‚‡Ç‡gQ‘nàê€ þï\y1žEšª{”È;`s*˜Ä‹-tË¿¢Ú‹gý¾
+cM£$Ï“t,»^•äœR0³ ê§DkG¯øYD(_ .@ܬþÈ7¦|ý;µðs˜ªúîU±¥b²û1üÑs°–$pßÚã®P‘zžüª×¸µ¯Ñ„ž5¯ƒ~½É-¯ï‰@÷h˼´6#
+je=%¦Ô„—g% #šNç¶þ)Ø)K¥ã´häÇ *²ØÛ®Rwœh•¸ÞÚy÷“OI˜äY—e1#:òˆvJp¦oå0&[¶ÐqÈþ\¹òKxÄú!õ¬üµ*†¾ð›SBt
+Ï;
+¤`´N š¢ñ—“^iëQòB~Ô£"@N@9ƒ€GÝ™æxc£Y#‹Ç¦7P)N~¹mfËýS.†æ0â^n9–Ç# ¶N‘-ÒagÀl ÍBYšÂŸ§(Zep
+|BÇÿRrý )’sLJH†kßøÚß-PÅêìÀz÷*þ ïY—LF5–S͈u¯ò +íMÉ—YIÕ~ùÇì0‰Q]üí%äÝ.ØŠóÓÇ?Ö$n;Sâ M|ÎÒ'÷i…%D£ª”µgÁ8Bçô æ· ¦mo@cñŽŒ€šà°×¢Ÿß¹Ño[¶ÿöÏ¿ü›WâŸ÷» úÜÎ?C§^È ôß?~hiø1ËïRVT"Ûrá¶þQd‹\É‚r7ƒZõP0ñÉWÿCy™äÆ‘ÄPô*>cØ÷Ò·è­|ÿm¿d¤­ªLC-À€¥úƒüC]p‰ïƒÈ°x@¼î`½m÷-P%Hœr+‰1sÐú n)xQ4û.赟ߩ“ªŸ·iê„'Ñ%OÖ7÷4C€`.ž5í¿ÄÓ¿"‘ë´!F`,ƒŸÖ‚˜¬.UªC($“Ô‘‰Öv3(gÏ V-²¢Ÿ
+­•îÒ’¡0hCl…7⇇ÄÈŸ­2±sè’×[n,sàLLš±UÖa;ö`û‹Öe¨tdŒ;„†x¬9„&­²ò,×Vh3l„îlj„:‹?›Üy¬“¬ì>RàªKï¡:·zƒ˜Ä±¢c<¬ÈTå!¦Îõôù
+H]Œ#ýt‚"öðNêvæI¡‘mÆiˆý±&«ÀüÝÁs3UH5RvvÒÄãdån‚#>õk%Lv¤äלhQõH_óœ¥í>‚1ë
+–j£èe‘´`?1½år1t¾ÌNQäµu–HÙÖ冰SM}/5!ë…3Åiõ[x‘¡èã‚ÎS.xà€ÐðFó@¹aðea Ì­ÚyômQ&¹4ϘOÃEaÆ#‹¨&¦“w¯5¦\ ©‡Yquìî>.Íz‘…a‡7K‡ÖìF?‰bƒtpß 6c8DÞ·ÿHB˜“¬tf€çG@ª!*<  ¥v‰ž{`,QBÅQ2$%Q ÈÌHºÒê³ÌºjÙ€p}l"£æßNñõÅÑ–BÄ ”è?yw£ Ä•'/õwO&û–“-þŠM–YÁýLF/;Á`¹~9(3ÐC)Ãn0?ï1'ó¬3˜a²Ë@Ÿ@,Øè'™¨U*ŒxãŒS&\ædà'œ¾ºÛ.3&!†Òþè­wÛ}ôB¼ŸO fî ©ÝÝ@:V!«
+D:@x<o?WR &Z õC&n
+ãm‚/á8d,"SÉàÒ²½ž :Ì(ØᨱE]93N<ø8ét5&5AFØ6„ËchúP|ã^`¾‘|ÂÈÑè8!å<!ÈŒB-míúe°œ6ýæí#ƒ ‚{嘫Dª{üëm »ÖžÖA˜zlθ¶úJòƒ ‰™|ðº9pl… õèq"³P\‰úÖ²hSÖ#_'®bgúRtŒ ËFø9‹àìáê΃Mçø/>8¤ˆëø ¹T’\OCóÇÜ
+§©p †ËŽŽ2 hfU£‡`ˆ(–)›Ä0H%zkœ{Óš˜læãZ‡^Ÿªç<·âÞYq¤¶í8 BéÙuÂaŒžÏVj%ô¤Ù*g+„‰iúè>€òàäDö¥O
+­FKˆa•q„QANº*†;Š—…¤±­ù:˜o.žÚyJ8_¹Lœ]¡P‹CÁNÝYÊØiàMÕ6\ëvz‘K™1:>þ4Yr¬ï;A¡ë³U¦/x¨HlC01,ÍŒeð14†ìè‹ÞÛÔù£?@äwòÀÞ¯Q®þê/~ʆüøGPRŠâ7SÓ·ŠàžöküzÀÈ¢ÒtXÓØ
+‚tò
+ugN8[º;Ã<úÉ•«h­“ál~¨¤eOÛÓàça?8­íÉ¢ÿ±;ÍZ#¨Ò\|e«åÙ g©<;zÀKtƒ¬˜7l¯ÃÛÄáœà6Ñ1&píçPµè&<tòö’ýBŽ˜P@øvÆ>¯˜P|-ÊÕ»žÅ×Á%ˆ}kñÞ
+«ÐcóògûÅN/úQ)ÃÅÛïí0 I&¦Ô|{'F´æÙ•ë,µS¾—ÚÈ ¡¸Xš«``˜b"ŸxùG:ÚÃ×A&'r›Ÿô”\‰–åEŸVhÿŽn¾¸5½<§n Ϋ'S{. z²ú1J‰¡|ëK ^+í‚;»ÁZØΆ0͘'¥¸²x¸ñT:ÍeJLoÆ&»1ýЛLãøq3Ü<RÎÌ…ÖõqzãˆñÁ#úÔ Å»vúÊ5â§Áì´=÷…°t­Z·?¹…|m<µä 9ýLxíáôÃo6”IÀl05ûò@Š ²tï\ C& 9„­ *ÁçÜÐÿ¿¾UOq“ê¤ÄcLÖÀÌÉZøÝ©LËæ£æ¼1‚ŠKè-žBÆ[¬|ŒÇT,˜ýw)1®
+ì»—äÕóæ-Rº’į£ØJl˜µ‘EWðþFã¯[‘Ù ÌÅù-¦Ž<`_?UDQÐfË·’’èPòÑ{«RøõœÏ¥ž GÂØý‹ùÿ¤ôqyí`)=À¶ñR2±yà}3ƒy*z æŸ*J\<̘̈&ÿ¡ˆkF-¥0ä7ŸßCÑ3ÖJОm+{ÈO%Mx(Bgén~†<¼¬sq¼"‡Æú\R'{á;­Y{ÝŠFVÿ(9_‡™^º )òÑ>5¶^rÙÞzÑ$1D£¥~oõQ$uCQ@»ú¶NâÃ:Š<–½” ¡( r#µòÖ P `nÜ8ð¥è×[ÑãBGè÷s‰Y§»ìò­dp=Yú9îQÿ(*X9^Šøò²NéÜÏÂÑH /%Âà*­’rß[)é
+5¥‚W¹ç—
+<
+ýÇ:Ó:¯Â”£íÈRM/ûŒ@\î1¯CäÌÒ©Šâ-粑Ûð4n  WZõ FÔ)Z²¶8”.·pÏ-ŽUº_}`¦¼ÇíÝú†jž[‰áIR§ªg“³ùSâ9 ˜ra¨ö’A.jôæDã$47vbvh,­×Ým·âÅ.Äî1/jMRj"\zÉR¿ð´7Žþsnƒå6±¦ëdÙ-ñG½ä^®ïH˸3±>缆c4î:no‹T¼ƒû²ÛÈF¸C¨¹ò.OpnÄc¾©{˜’ògòïp‘F…¹~$Ýw¹f,Úœ¯koLÉ 8äƒPݸ˜Ï¥»PjåÙß:Ô~(JÎ.ºŒ¤Ó PCWææGçqŸŒŠÇ÷p ò¥2‡—ˆÃ$Í-Ô¯2üЦÈö¾dÊ3n¹î—¨¼-’”„Z§@ê• Á:— s25ä_ö’!¤š4€oUÔŽ ˟ݧ@›ˆÈg…¦+û`Ef¾UVºãjÖì¡é‰FAkˆ]bŠ0pîhÑ£ÿŒ:¾Uauwš M x¯S/Ð…nǹ»ÊѲøÎê©Äwêc TûK£=xÇ‹¼ò5š–α]')›Ní”ÄWÓ¸½f0
+œ®¯4¦ÎmôûL>LhX›Ê(A=9„áíÃ*wÕE<tÿiK’¤t5ÿ.¡CÁî‘Bµ°'¢æ1öÀTÎP…}ÄÀL¾ÏК®U|+SôFÀûš.( Ó„½ž6‰1J0‚óÑ^*¾€æÏo§¢ÙñÞFwÌ+vüç¢S|;=œJchÃ88
+hÙ”“Lè-ÀQĨä)ýxIpek$£Y[?Þ1à ®NS¼&8Š
+qSó’û9ÁQÇ1='8æ&¨C1&Lü#ÁQĨTø ÕÈL‡\³Á•öï¢+
+Ç^Ïh}tñ¿±€ñüÑö“xñ=µ¿'‹Â1
+IÄ€m _[UP—­G†øš°Ô6Ê°|d Pù’ÔvûMѺJ`J[‹ó®UbúC è@˜¸Ñ[}&åFC›ñ6­¥SúÜóÉ °3tß_Ø_#$-+tNµó:h½VÑž–QþŽÍ eÍ­¤üHWgÐ?Y“ƒò”£„LV|¹wqFÜ_·+Ö2\&™Æ̓B¾Ä½«‡k£™ü5ÕT
+O€el5¯ Á¶ Á‡L.[&¬½U[!c@¨ëbÊĹA=W wP¦œôyñ<H͘!æly†muçÅ—Á’Ù{HMw¤ÈYY³Õc ]>/%€B:ýùí¥ˆÀ[”ÄdþéÌ;QGaÿ¬ùõRc•¥‘QÎu4aæƒ×FŽø)J–fl ®7¸"“jÑ}ùÄLC9Àé´ÓóQPor®ÛbŠ@n®[œ¯M¼søN« ¡²0bWðØK¡ƒ¾¼‘z9¦æ—CËòœÜߥª¼z…rGróHw4rÍîC;ãœ4Ép%FM—r{ÛZØ@pÜa²þ½¦öv×Ëú^¦:‡¢›ZXx]||akdØ”r%áÁ°¥0mx[‡kC:šXÒ?yé9q4àݹåÜr/‘±ðv½á£>0êcÉõ2¿äÕdwU×(¤ÑåÇ-yßL-Œí´qÕWx˜÷1xųÊî}Ù,9ˆ—²ºÑž"ÃÛ˜zBˆovñ *Äüû«³ñÄ^}3ôSÄÉ»—%ÔÞ+B¿Àœ¯Ï¥Yo© ÃÀÜ©Çå³.L9BrhF²‡Ý%EJf2•-&žfæWŒˆÚÔ|íV?Ìm6᱿”¦¢æ¾p@4¿ ‰Í‰‚—îÜ_E¤¼$Ë[íÕ½‹ñÚÚú|A‰ÏÇZ °I¸¾eà“ÎÖQßPê_‰LìFÊ*1ã ÜS+† 4‚\4Áï]„<’ø¦áRdD¦ ½®+DÅçPÚÍÍ–—`ôÍhº¼¯O&h|Ñà@Æ/8*jÁ»áZz¶íe8 3c1À” a)„ÎYw 
+p]C[b¢¼”
+.ÙÙ¡ª¨Ë¹s½kò}X«27B,–†šì¶]"@œe ®ƒ 0ñ#”nš8fUNò«}')<rç`C„¡¯RNÓ ’äb£v Ú÷hÈ/E¤!¾^º™Ùy&O¨1Gñ1ÊŽFËœw þ sÅá ÷Ï€"Y½ÎrAàzEçú°~³Q%L£@c…:m9¯&rx»/[ñö£XÑx÷÷g>ó“Ô«Ê|¹$<VˆKÕö™$åy,-²¹=Þ Ð:Ž‹aG ºÌê{=Jòåªý>Fð ³îï@
+ã†b¸Zô݃M¦Þ|rª6ñÅlûN¡ÞuÊ S‘3¢£h¡.âK~ÓuÔÈÿ…œì:ÊSœ¦e+¬v&Ù;Q<÷-ü³¿Iöí4¤Ab?
+lÞX ®++ÚÚ<€~0"D*Å;L_ÓŸx$¯* †ÉñmÍJAwÓìó[ù."¼Œµ®VAq3ë‚ ¤v$äºÈV”¼<áfuX¿ILýé÷Á)°HâtáÅ{óS<8êºÉ]¹[ä—ÝÞÍ”…e{r=lƒ4qO¨séQ‘LHk²¨g çê86¼zÞÓ¤׫;dŸR)%FÁ­ð×ÓgnB)wSÉúƒ_àöÔ›ú¢î~ü³Òo„D‡h)(l‹ƒ¨ãK þî†
+…÷äÜC÷ˆÊb*¥ÙüœžÙ¢k¯ñ˜|€4‚?ðÊé¼U@¸DF›K²(2¼g‹—©s¼»e,¸Öm]1Á¾¨g„ƒÝ›­ÍàR±<@°Ì†Ç¦<ðýã:ífø’ãÞÌeþtÐëûqà䀢B>Ŷ©àÂð j‰ÕgÛ'kÎsg¶ƒÏÐÖá7½Åº#¨ÃP<>"=|‡hAÃ`°°bÔ ‚I`šºçóQbÁ4c¢m˜ÅweÈ/»Jè3øy–ɽźDËJÓ‘@$›«ã:éôN'Èkº9Bþ4(Ozm³“KÝgÁ„Ì=e\Ò†íÙ±evR‡ø
+šNžËÌB´¦Å :À†uH3à¬jˆͳZm×£Pš¨Û—Dƒ^¢NÃTh¨*, ìû3Êb…GÔaw!Ä x!6Q7%ˆÜk/Â2ðf"o›W’¶Rï
+¤:¦ÌhŸ‘aAhë;ªMÀÌ°oÉ ˆ•âãèeCP©0µ’ݦ P…åš²àl¤LÀ?0!îï 3Ô’‚MûÌ)äÄ6½’
+sT B¡¸ açêÂÒÔ’ð£uÔübîGVe­UÛNÑ3“±?Cs!ÐÝê‡xsIî²Aª¨éî>Z‚ õìÑ’ã’y¾NYÐÎ`ìÏ°;ÿ·!ÆTæJ2)ÃNâ7x@®·9]ƺPŠ®YûÞåc°´ÒäJeœ?A3Ë).YT#Ô‰(ŸçC¯&מcyRAP¥Ä°Õj{Çêp£>ÖíŽc/5éÁ£“"-á®+ÞM¹lŠ²’mg ¹E`†}DZb;ª/<oýM›Q–=ñ·àËû±uÀÊiŽSçÏt6šÒqÉÿtã˜1PÈy4]€ %ŠX9$UùÚpÆ|mq»Ž[*ЋÖù°¼¢9‚b®SSzF(ˆ1yt²ù)¯.¡f•6é
+]â™&¨‚çÂ8îö+Â:Äç¦t_vïüDê†_c3íá)òš.–·åï‹íq
+èUÍ~’üN#gÂ2dô™nC÷6¼Ò§ˆá†är±¡cÚã‚W're%Åb3÷°)p+Õ„•Óñ–Ä r^°%¸­‡!Õ]²<máÈW2æ-F{[¤ýÇe‡bÛèdŒ |eÇ2a²2Ãן „oâûΔ˜¿µ^<×hD°Ü0«qª+žDV|¥¡3˜!Å Ñòž<g»ŽŠj–,wr»1äcp¢ló® ÑCLÈ?}‚^ùÏ;öþfÉvj¢fo§òÕèšÒn ƒÔÃE"L,œšè×ɬ}àç¾·íË’6†®æìô’—í#ÝR¢*>¿Òퟠ_ H’¬ÒÖAþÚÇAðC–þ?ƒä«ðÅ<dYWªÆ–¦ *_Ó:¡¦ü1èt"G«±€lUû { Ç}
+óbè˜Ú–ý¨¥t|s6ë²o8ÆQíʨL“m.Ö‘L)̇s1ŒT1|?0>˜8¦ºhįÊû¥Q[G’µÏrzû;Šq˜`XÓB:Yb¯Œ i²BЮè
+íhœzØû²€ø«lÏ_SCص9㑨'C–6$.w4± ~T­\ oRK¿^ÁC¨áÊ•Œ;eåWþ® +H}Òð£˜Zñ(Nͦ Ø´gµúQ+Í઻Wš…^P$8ο¸/Æ›{ÚèP 6“œÇß(–ËMÑÚbG¡€Ë`«7›¤e¢uF‹÷wjä$dûd”;)ÓÄaëY‚<:Y¨¤ÄŽº-Öý;¡6j$ÔçWe¶Zìñ-^@žˆd¼<idª#ÿÊôá=çjœý/ãe’ç áø>çaí,}åþÛ|E
+<¬D~q±ÙÛoü‡&§ÅMm ¹EøðèGòâ(î·cÀ JAd‹ŒƒÅÌ`ËÍJ ªÊ0F}Š¡~UU,ÊS/ó´ÅE| [ãzI4„{<òêÉ,ry¼é¹âK"ûmÓ\„)”b¥q+úxSÄgìZPÌt@–è9àéj˜Wm•"0gÞ*AшÂ$Ô…»Rû–ÛëôKŒG6ÁÏWïßÿòbbçh˜,{zm
+
+0 k5[·?;à] Ål
+zÜŒÒXw s5|¾ ÏÊ~ù+ÁWÊ]Ž, =gÒîT+ᯜÌÓcoHRÈ“>:å¸
+iĵBÍ£<-4ÊMl:f T¯ûò×½SfHoVô)^øŠ’«"jv)Z
+Zät®b+ŒÑüÌ4° á2ºŽiœ½ÍùØŒ*åj! ¢ÿ,ÝA³ò—Us!hRß}ï”°âÏmAñlHV¦ùˆbÅñ…:±`P ÞgU;æ<Šýœ†C‘3`ff‹
+~Ǹ-ãÇëϯ?+0ÒZÕ÷M|'ð®ü¼”É¢bh«”ØP¶$Éx?°‹3@WÕ€îîÈI&œ¢ï@/R =­:!Âv9³²CŠ¾ÝG2c6Ir·¸é ó¤¯ê¼ˆ øѧâ6
+‘{=_K(ó\Ÿ0Ì¢à;Kûf/sEJR9lå¡p.Ân9åíë’8( 3ã›MX
+*ÅK[Sà½_—ÿIy»‹¥®˜7ªMrdNtýÃj°!àGLÇÍ:¦Dü•—¯${Ìöc:bàè$Ï`êµZ ¦šAÑÃ'žø|-‰¥UºÄ!ðo d¨`“ðÎEiIb4]ÿ«Âu©W Õt+ÄРU#ðkФ G–²Ý‹h[ô}Åd[6u&':þ¥˜‘í¦ƒn%¨`ËMš]©›N‘ !î‡5|ž7bBÁ¯Ê¡ÑóÚ¢æô}5O5aòk ªdÍfC;ƒÉ¿$¯¯EËbžp­9t…”`²:ÿx×ñí¢— §Šá“ñ¾§Á{òH4.×·×}£¨á4jEÈbäV¤hv¼À:h¥Dÿ*A î;Ö¤Iäw9@Tô;È-ÕúØŽ3ɨªŒž¤·si'·‘îXu<ÅÌ~ÝeÑ׶­„çÈ¿&´¬¤5™~>yøÇàUáœÂf÷W!ÇT®Z›Åð¦ßtl2ëáþº’v+’
+´`cÈظ3ɉkÇÄ‘òöˆoÁ¸Š­ÚŠ‹PÔ %àÛ’iEý1¯e;G’¦<DŽÖñW92+!_$‚‰«pà4HLcÜ×¢ö ñJI̽Èt?n—Q®
+ŒAFh—f VxìÜž’¹aØ!žÄÒÿ¼ÑúñÝå¦0©kuƒç¥è•eÁ0 ZÙAwàß,úÂüß‘¬?GÙ’’,„CÏz#lÔð!´—1ß(Í­èåËu#¢½Ì5¿+¦34èay¾m'QÂ24Üm?Eôð6bçúvÑí:2.³–ýëùÝ\nE¯-¸\÷¢§@ññ®hmôE¨Z´[ ´'`€º5Þ” *ÜF¬h&:*‚ Ñ!rÏ
+H‰Œ—AŽ[9 DO;ôÆ(R”Ö™en`V=÷ßΣD9Óßß@ØeQ"‹Åbÿø«©?|ŽÙÊ,¦S>j)þfZ§Éhº!£×Rµ•&!Cm­Û†L)2Tª—Þ>~ÿX )U¼ÌÉßy-C§öa}Ÿ3½»hÎñ(Õdö©µŸhocø
+E‹Þ¬y̪8÷mÅûßv´#ž)ÏH_nc«ó>žASýúñO ]#ä"J±2¨ Bv‹ìÌoAí”-¤+®ô+@J ©£Å¿¹ûüÎòâ×£.óhÝÛÔ¦hpþÐì è×З[ y  JþÈò]¾½†{yÞ·@/Å[áÀçó&ßÇT\…9=Ýå‚ùüF¶WM>þdyPp·Ž”èâ]gôÒ}Ç.Ì ˆV£Nç.Š—G›L4
+Ó,¨¿MÓÎœ?uÁM·Sèûƒ‚ì= t‰Öòô-…(½0 i¹ÏAÒ"AŒ–º!È Â¢.'Rd„Ç;{iÒú¡^èPÆÁc1™¹Þfä [€²è>ñíaYfñ¬ePrCŽQŠTQˆ½•ÿD<)Åû
+”œ ”ž5eTÑh³áuƒe@!{ÌŸ,)bK²1*Ò‚¸¢ü­…•˜7ª«E(
+¯ýÍ9Ìâ’Þ°­y 1Š– ¢Ô Ä®•Cæ†)à3¬WËPá„PÐæÛÙ
+Ò·B×f7†÷ŽHRaoáññoΉ (*‰çÍW!š½+rowW1~ƒÁ2δ¤Øˆ¾Är#§‹58èÏ*…S£_Ñ…làK‹Ç|GprÞ
+ Dý”AòŸRqÑ_®/$‰¢×;Õº ø;õ ‡Ç
+퀌>Õï«Š-H*ìb&ä•/RŒ7Ãû`™‰­ÞB.’þõ/¨ÿ*k¬´S §÷W3òJ.Ø ¢Ø õ_ô¨-hFô³8F/2¡¬ˆ2ÆÈ7iØ…¯Ll +ç›cÔˆÕ’ îËûÕðJCz‚СiÄå~d‰0”gE‚äØËc[x?á½z èRh¹éÚ—ÄNϬÄÃ6ÈQšÓÈÛ>'ÞÍ"7uCÈÀdáz‡-ˆâLi
+–¨Œ#ÖRÆÄy
+pw%_Îe!ÝÚXú:¦±CPóÞ·þÓÙ<WCp™=X­„É‚sÞˆ•J€„’®Ó 1+ù8Ÿ×Pc
+G†3XšÁ)g wÏIì%
+j@*`êI1®¹c_YOf|m
+Uiy
+únË„‡%ßr
+¦ƒOTKÞ¥¢-ÒùÔºƒ‹ÇJ•´UÆ,â©í8*F,‚Îg£|ñg·²3VÛA}8ÜŸª\cðXILªÐZ$:œñ–
+øFRu~s„õÉ1…±@¯¦a“QÄ[ȵ½ul‚1r`ê~Õõ6˜q²€o¥Á‹Þ¾
+×Ïy%Ì% ˜¡$¶‡Zã¹ç1£`4¶ªïs0R8[*NÌÜw¨„÷×dÍÚw(w-W"äÔc(2rf†"O(qçdÍý Ù 3
+~ŸP´ ™@JÍßl€f˜QjÃV³7¸†j°¯ö,ƒ„«åÜn¹ï\é%{B3 ¶ÏÜ„q— {˜ä)}jÈ †d)ƒ}( Õžãv@Sí®Xó°šó¹‚„O
+RÔ– ´<DÔ”3  Ž0âf":þ~ Gív’AOÅFUcáçíx¹€>ߘaN£aMî ×!ùpI-ï  †xSý3îp•ÁoÈL‹1
+ý¢&â@x ®­)Ž\«C86üR¤r¦Ð)ª|,,¹M·Jˆ
+¹,<_D#'˃ü¥…yç÷7 ì&g#¾JŒAدÎr ‡à$ˆ&ü=/qˆ\Þq†ªÌ[>ϤHâÃH}Ìo ¹TRÒ\‡ ¬ŒzZðXqÒ‘ƒj1DY¬ ¯­µÆ!(÷Š
+F\DŒ Ÿ¸Mˆ#ÜÐ$ÊདF.ÛÑäl)Ô!|§t¬a5ß&)Gøö9åÙSe†~WÞh€½´èÑOAÖ2)oJ&‘Ý„óz²–æ/†š9a!ƒ.†í0ùµmß·è%`Ø£™¯T‘¿ÞÂNâ30̯²ž}úÂ+eíI›A!0¥rÑÞ…ds [î肽jJ|éé&OÃML]v”M»Š¹?ïƒe ÏúòÀj–õéÔOE»ªOû’.Ó0¬*ùÝ@5Ó@²,ƒx2gS|32Ù¼"ÂÃ{„bÔ¬ i̤ñ@¨ÇVT®!ãçMOð"<Œr•há Lc}`L²äÇ(—ºà6r“Zïà‡ÒËŸ{D;«HÄnÄÅ™ÆiÛBä´ñ¼ô·Ø9ª~½9çð{ü\;!¯e0óÇW©]é d\…¦ƒf6Ûüjá ÒìÕåMŽ‘QÅæ¢Ó;D>
+BQôìçªWUÆ}Ñ+‹¸z ’Ù¥r^ƒ™ ÁfáшaZoÒ$;´¥™jQ@¨ âžR½€»Óa&
+»3ë âHd*§›ƒéH_Ÿ—¬r¦¾à 9Ñ#ÄUffÎç«(À2´û8+&dÏrò
+}¯Ca84&Š¼Vá9ôGQqt·Â—m´fÛÎa”pŽ).[‹I¯Qdzd ůÑÖVK`ÂÓ<Ì8‚C !?~ØšI·(Ê^µs†bÛ­´åwð… 'C¦ Á åãÁºG¾)îm›R6šTòv««BkL¿ WÇj±ÿR×€ >lûî _µd)pÈpñ ¨Â]p0jÐ#r‹©¦ó·ñø ÈR)Ä°׸L¶˜ú¥¬Åä¯ÇWQ˜¢
+ä{Òš@øÔTE'qN8n
+z¥‘Ì\×[4‚¥‚·&›áÇ ˆ§‘KX kò;¹úÑ ‚‡–Ê8*ÆåUÕÅUÇF.Õ¡JI4”$3ûUÚFšÞòX=U­ÎUŒjvSÛ FVkôfØ«->€{¿.ü3sÎUX=«³“à&÷ÏØ€-æǪKÚûf_E¥¦®kÅU”QF\DïýDMÉ/
+?ù‘by"B¼Ý³–/ÔdgVûÍBMðÓ"ä}·µ@𴸜Œ£oolíø’×£»<úøQrUQÒÌãˆÈß1B Kt=Ï{¿A(T™“º^¾žfNäöÂÍ_NÁÌ0ëb® õ‡ÃñÌ@|µñ@gHR>‘^´,Øϳť™±sç&VJ©dQ _ŒÓ‡C¡TÜQ™­ª ûyëåЖ ¹X¶fŸØ´»YD~éÕ$ê-ßÍ)M—Ef¡g•­\Š}ÑnÊV°pS|T#ðmxŸ8bŠ™»†måÐU&lž&mjàtE½ñ!’g{×pIN¢D ã-²”-Ah'50é‹£P¦^ÚS‰•€Òb^£-¶ËCX;¿` ˜oh g>ÿüøå÷ôù¯?>~ùïGþüõCÊõµ™‡œÙ3+ú@òxfòyBýüî üDšòŒ!È—KŽÞ³èp¨ÀÈçv –Já<ÅKd¹K’ ¤ÝmpJ›ÛA¢:¹¢Œñs,øÈLµx ËÀ–*ª1´1–l‘½‚Âè&¦pŠ:
+_ýE.vµT™‹O‡ð3ubœG7ˆ}‰Ä%i’–¡[–P}(¤<fà „ËÏS³8‡:T%”® hlKÃÞõêÿ·\ƒ’|:q‘ Ô&{“PäJq; 𙘼cãv5{yC(,åÙÞzÆe‰-аÒ'¼ÂG‡0´Ê¢¨ažþõEUD4Wv¿"¯NÞˆ òcš¼øFÙZuD“y3sí­xÀqŠbd:öºùp\@4”s¯ò¾¿€^'‘SEZ]\
+ÕTB)[AìÍ;¾wBî}O™Ò@ܘž~öâlj„-ÀR0_Á-Še@Á<)gÊ~[ãŸ!1aM
++í~Këû¸)Î!~¡èr´#†Ù^“D˜G¼†êåÝXz¯]…æ °«Æ®—ÆlÃÕ=Êשv…÷³6S¹*‚v@Ø;Œ•4Ë;…òhL²¹½"VtYðØõ kü‹>ñY¢ß „PÅ3Ç4,náµapÎØ<Ö[Ξ_ŽfUÌ!PNÃM'xjž¹àÞ*gONqÒé#Û£ÅîÍQq (ÜŠõLÓ‘£ê!?’Ù¸Ñ/ Œêó¥ýŃ0ØÆsN쌗Ir$7EO ;ð4Ìúz©[pKÞÛïÃÙÆDuš©$UæO ÷?tœVPÿ/wDClÛŠó争óµ#¡¬ ³ç<Òq¢æè=ˆ9gÔø×27ªêÍ$NTfžz°‰>*~V¦¯åWgà'H­<–ó_ê%x/
+øm ŽzÿØ¿2®WŒYü8MZ[ÔÏøÿ¸T´qrŒ%•Kq49¼]^V#òc ÑµÕXÀ&°)òÁdÃda˜š“ì¹sŒ¶R22B1ûräT¿šÕœkëÄÏ&÷ÄîyøVSmÂÑÎèÒp”ÝæMé÷æ¤{ÑÝ(£QÖ ²RËæ¼b» ;B6 ?d¯z
+WkÁr±YÊë¬[S@ØoFŸðYàfyZ¡-ŠÑô¹©ÛÝ]C2À¦K9 [ƒ
+Ñ„{ð».²A¸qû?GÐTÌI¢E î£§@bm²øå]ž–‰DHŸtÝî=¢WTKC #Y ®hÛ‰ƒÄ‡AáQS6œ¨q¹0÷L‰Fv$6ehB*(u’ ±DÜ……‰/¢CDÒ§dë º´H[†Ó4ŒLl"g?ÍTâÄ1Žy@|Y i¬3Ð)æó2ƒ0sH)…6ªqz .Eé ¼í›/¹ƒ.=ûíçi!HæCôk)È/+øµ8ZI×y”Õ±kÒ¨å¯/2Ž»1œÈõ ´ œ†¸ƒŸ¦*±add… —<ÍÔt„¿&"Muªo°c#Pé[Q^oÀÐ]îo4<£lËÇx #aŒûÊ2'ȯ.]U¾NýÞ8£’ÊVê» ã ^·{tá…ãx]AÆ1æá@´•9jqLи`Ïx¹²9fZÃS%oµEóLå„Û’ûŠRyû‰˜ÅõþèTƒ÷Q®´÷î€ð{äVOõþ
+Th>}^ÿ-ÇLèÔ’§ÅÍòƒ …KFÏ’8ò†êa`F/çuå¦lNŠýìr€0ñ|Û{>ù©µã‚Ö©„ù©8Ø@’’!Ùf)ÊPж©;DÚ¢1‹ÎσØYõ¨5õ t’;|*uÐþ(œ7ÐÁ,@êŒ+däcAøϵ4×›Lƒ) ’äHqÔÓ!Q YÊ“v 1éxxtl«ÔDëu‘­½i%i
+k?Z ]oÉâ0ås_T¤Jzk{Z'÷!£=bõþŠØ¸&¯”s1#ÌnÌáΨPÒ$±ˆóÕ‚™Rw¼ŒPcQ\hä3['ðµÒRºÛ ûžþ¥> –#T9ò$»ïŠèôàñS}PC‘Oúº8öïMÌå±zµ ¼ÑX<Ÿ‹,wÜÐÜBd8½Ã—Q= ÓãáÑÕ)ýâ½v_ür­Æ‚ J¥l¦AD•ô e¬n7o C} ]ìtdÇß]™ùûú^,ÿñAÛ§ˆÿ¬bB‘Ð'y„_Ocú;(-eÍÊ(£‰a6EUÆóMü—˜zÆÎ6ǤfýÔ­*”„óQ£4âÀ1Thî ZqÚ2È#rE×Ý)H)ðäs5~Ç •°qÂ~€¬­ºj¢rÈ`?­Ãí"‹nü4 fÁ·ó´%:dÀÃ*í^¿¡nŽš"õÏ?gœ•uÍqÛ£Ý@ŒÑŸÌH˜¾T?ׯæi¤A´¬‰oê@¡kŽ/7Ù7/¬Ã{Ò!;;òIF€´u’î0 }uÃÚ‰rNíþœ2ܹ$½×âïIL¢¥‘ž–¹¼øý0·Æ9]êÖ€·Úܺø^àÃ4üz¨¯wFFÓlº*œœec±ÿã°ÞÏ 3½¨×M¢< ¼¨¸ƒ/7+âtfX}8  ÉV¡Œ›c¦¨Dj½vÞ¾Žæ¼ ¹â︿Øü94µ˜(þýÆíáO¾E=V£´:r€ó:t³¾Tj«û4œ¾(áe!¨ÐÇ£J!ÝÙÐýĸÔ!@ÛiÀˆ%¢_z<¨å‚ðV]ŒÈ Ò;ÓÿtQqË“/È&û¥ø©YFðÏ?gЯ—ÿ>‚P|<MÔÍ'Û +AÃäÍ„£+Óò
+Éo®œÆŒ<ñDÌ".¯L†g™ß3ìæN<%pe¹|+2fš>¤·øu"Ë[ŒS[-t®™<®Coõ„,f™—}¬Näw¼÷(A`"Ë„ ¿•ÃŒ·JL´­*‰¤,Ëà1wðAÇ<Θš­ÃSÓ
+"Ò1“@¶„éQYª<›A}ÛRñt¢‰X¯Û«h×Úý:<zÇju¬@t-WÐ)Àj;T‚ €þã_@¿Î$J õJÃi‘f#Hè•!i;桉h
+¸[ š3j¼ÏüÄcÈ<DaÆÏñ¦ÔuI!ç|¦Î¨èT„£VrнA•$Á
+¢ËÉ°ÿA¬…¿Jtod†­Öô.<ÃRô» ã«]·{D3Ì¥ƒhú÷40‘-ñ¸ÍÝ‚f˜ 7Tj8¢Ãæ0~Ò‡(8ê:›Aââq€ëYµ¡vž¥•–€u=#–äì+_Is•á <?‡†ë "®£p¸å
+o¬®É’`ùL]ˆ*iš¸bv+ÒhE•÷æi›Œ6‚)-sî¨ÒdMj É×ÑOË4“ç¦u;ÈÙ \ÀC†Q_[]Aˆ)ƒ`A—ù‘ñß±†ºuŠ çr[*Æ››%ajxŪ5Q¾¾‹Çä7Û$ÊC¼+ûïêu˜4Eù×zS:zÀËCàùA“ÁÍScb2 RmÔD™~È-cŸñå«Àd‚áæ5guÈÈ"”ÁŸæ—t ›ÐÑqGSê…”È~$[†á£…»ÁëKG)ïRÏù
+ǬläfoàPtŽœü4%6gó& 13ÿ"Gô•Eù_g$<eùÌêâÙTe®MH<eÓüfntvOh®#ÔÊvX‰¼;b±0s6v–"1© êiËЮS·®Æ4ð4rqaÿËx¹dÇyë@xÙƒVàÃ7ȱïP»ðTÞÿô~E€­XÍv4‰s$ˆü êцo‚2$D >[ð=ûTå®»=væÆ P_ƒÿdU§ ÌA˜.ä¾WW&ÿG·0”ùEI—غÔsÓSoÁ"mÜÄðà2o#m&ãµ$Ò7aó£­î%(­R"Ö¶?(‹'dúe¥G‘è3* ëXÝ/‚Z%Ã$ÒÇT™ä¾gŒKI ¶TB|ŽóçsÆ:&cÊZùøÑrÕC-J´» ¢Ùý}èÓƒˆ¥-†³ÝX^D¯¶!ÿ¡-øUA:íÌG‡Ù’¬¤‰ë^QADƒ‰‘ëæäÈs"Úh×¥è#Šp™Lt–ð5ÐÙZ[ôg<ŠÆ±bu„ÝàkÄ÷XíFšŒ½œMîœçÇ)²B--ûìð’Ê3ˆCÒòtÌD<Š[¸2ˆ¡ÖSÂñHAt¾æ%õ³’iÙ«s¸dÕ)åŸQ‚ÐÈN U
+€Ší’þ+Ø
+ùBù̬;·f­[–¬T±ÏÏîE •˜Æõêòû­Ëß-bELo(ókP™„H¹Ev”
+õËÌ„¢ÀXà póºaPÃ7i\À
+ßdKE™-> E˜ACì…wü/2ýf–…TWy9ð þ¾‰Ž*yÔðWI[H‰<%ËÃG€Øúaþ’]‚·Á<—òN!“ß{¢
+Ü(Ò]òõé_J¢Ë¸$—mëå9L—ˆÏªñÉô *Œ¤›ë@é(.¢Ê`ó•çª/ÀH’_)%ìÃú‚®_Ásˆ¯øøZñ* à–õQ禿Cùýá6:ag—5ûñµÎTqÀ˜…nŽú§"¦Èú࣠»±¿kŠHadožÇKÑðŒL/™|ÏÎ~GÁÖÄ'YÒ4ΧÓ3´}Ê†Ì ÙX6l¶h(Df0Žé¦¨»DW5Ý|- Ô—Òøq‚s^ˆ·¼0ŠÑU7Ž€;èã–Ot•냕€Î[±ÄiízCøìçõ"àa-DN“TBäúR¿[$BKlîŒÞu>5@Í“fƒ/]æ°Þš„±S½{‰Œ¸nWßO„W}y ™µèÒjêÌ@îEòtì3&³Æªâqa,aì«:5š¸º]H6‹A¬ºT0tÑD1s]/NaUðDRŒSX|¤I‚´s®V,g0Ï_;™¤ä’z@ôÓ(ʼhÎbr´<²”+ä³tîiÂ&eZÕK”½š*EÛ%T(‘@\ËqA‘(
+ ÿA^á/—_–5B¤¯y5zº8}Ñ÷|©ˆ¡ã[»lUO÷@%\p§Ñ!Î:³ÈO©yò.êžgUðd„~Õ˜˜*)ÕOè3)'ðÕt?ZÇhí$´:bÚÛÛ¸'šÅ÷Vñ×wØ]B@Y‡¼%eȵ]ˆç·× ùK0^ÓI°ÿŽL^4‰–ì)f"_#SDÌÂßpLnwö2™xtd¹ÝJöÓ s½¡}Ð÷ýû1dÙ
+n Á Ìþ±‡Q"gÝ0Ø9Ø;@ÇäÜGléSQÝÆÞ@„˜Æ»ñgX„¡¡}»ˆëêB¤O$Í›x)Ân+³ñIŽ³ñõ«˜ÅÖ¦%:m"(7
+(.ô/Ã1/ñ'ãçe5ð1 )س€Õ
+kÃÐÉ™i(Æ]†q1H¹Á&’¾^­ûÉUšáâvž¤`FW<<7é8TL|Û
+é (©3¡²¦HG¯~ÌÆ{Œn¥)Ìeá¹[”Ð:Ú7W9S•‘¸€íŸÿÜjn3Gbh/®™å}‰ž¯E_Wðãkúþ™eÊvë4.?¡/VøZ¾Ñ„ŽLjãe£æKÑ.™°ŸÚc²dh’í`ïÖ.áÐ׉õÍ'î ¦]ÕÝÝ'"ngÝ395ŸdYè½Ä‘õs
+O‡°Œq•‰Á&rS]å*yoà.¸Ù…g2Ò±™{ŸÉSQþ¡ RØ—!þ÷§#÷Œ)öþRôáEežØs.¹í ¨îã‚Km< îRÜþ¹Ì^„­8eŠZr"ð X¿ü*úËp3–ɼÁÃ@1š¾Ñ’2/Š6Ãá1z~Q!€é>&¶ðRD0`·aYÿ
+ßÍØBÁÍÃàÛªD¤%‰šå„Á¶ö×ÌvžD†úÕy S•LîÆ‘ùÇMN4ý
+½¤uTuJÔ.|Çqè+èæ%@áy¸¸à{Ýóï««"¼~Z-tá
+Ù…Þ„¡ ¨e·‡ß2/šà!Ð÷sò¾Š¯ÂGXtG‰ƒaÍKĸ/²Uôã\„T `9
+¿avŒw’já·PÖ
+ÚÍðÛÌ·—Ô,)ì¯ʈ[ˆÕšQÄB`•‘Ø\âíp¹uÖPKöÓäs­[¬Éš6÷RH&Çð¬!·óꨠáÎEЄ54wÿ=ß•ÝO¿&X u}=6ç'×Ù×ñ¼Ž¼õ(Ò, tú‹ÐÃDs=Øé©dp+²Ô}âYÀQä;×¥èãE.^ ‹F FᶔrÞõ ®ØY8Ê ‹Åî*Ï1õÞÔÁÔ<0˜%LñŽ»,„\QåÓ
+©{‰¼=
+ñ,^®
+Ñdz $+ sÀm0àÿ/w;’#ˆ~ÿalƒz?L2éê y”©ÿ׉®¬ NW6æ.v±Ëٜ̈ì½T4¯4éP<öÃUóE®>¥Æ›&œà9ÝòKNÉ|_ì†X 4˜pŠUÒW¨üèÖ›HÈ à•ö«O
+=¢ßÌW1ÝrŠ¾¸ëŸw,xÅÍ2¡ð{iñ5 X †ŽÔÿw¡Î‘û¤!Å™°«„6ö¼? O™85NXäQ’ Tx™AYÃå+L»ˆx†%)!4¬‡zŠ’G‘øèÎ-'uÑò[EN”ôŠnQR%šÌdm™û%‹e$4/Q²¨gýBåXü(y\Æ)AèÇBR¯ä÷ 8.–|ˆ’”@Ò|H/?ºEI "ăؗö%)Â:±-æ¬7KR"3Ò¯¼¬ä–%w²äYã]zoØBl4íÈö}Qí ¢ÖFþ¬èØÁ[ÑŸwÕö¹"›ìöê†ôŽ\$d‰3®}®Ÿ¬ØExuD§ˆ’ö ÁÒk³åã&g”pÖQG ³l¶d.å‘jùº´&cD‹›„ݤ“Íe7HÅžÃOÙÂþZ `^O§"Ø*é€0,¿pî¯æòvj¸cñG¼œ¢?VD†e^¡q+ÒfUne[Ö»†ºš¤.íéäÐaëÜÍAChÍ@—öÉ3tP#«Qö|°…î/“5CHl|Ø÷pË
+Þ}™ƒ"ºK«øä¤îÏ)`hÉ{vþa¼´;’ÄUP‡&ÑÈv&ݪ1Qt;Sù‚sô%\8ãÈÏ3¬V×S˜YD ù Ñ ¾^ ©€H‹Ò¿4×e:Ep1D}Q÷Yš#é˜GÄ ìØ_>X˜VYQ°Æâûn&vì¿›'÷CJ™gÌäç÷»_¤ç~ˆÐ3îÁý4VU(
+)ŽÖ>H™ûM­JXÓ|Øq®ŽND­’=9¹ÏÝD9ô$ÂEÿ9„P]”Ÿ”U2p®"“Œ¤|y¨£­®òž]äiSt'e&—ÿßIuqDŸ”1ƒ—²$qæ'-ü¦•‘ÙhzÁû]8€«DÉ!5‡{?OPôb=ÚQ·èrjÃ+Å.(k¾(fk˜Å}¨;(SÄwÐxÖ ”³L#Пa(óî€òYãÜy&"Ö°µÆ³ß-ò@ù\A”¿ÝÓÊÿCG¦ £4gë¯uîŸ!âG`^N¾zPo”YÎZ\\¤Ê’Óo”)*µÊ߀Šî‚2%H†¼¶ñ#”U’¹GúÙ[ ezÍc?BÞò@Ê*Â:˜üþ¢ò)ó²9g¥ñ¬i~:z/Ud«¤¬£T{6Î?\RV—É"ülŽäa°¡)S”aCIIËÏ©¨geÔÍÿ7V¦0 ,2ª>°2E°(DÆÜ•áÒ2%Ü'¦>„Y.-Ÿ%-{E-ŸE-ŸŸ|ðòqt—žÄ|\Äé^Ç…z.È`¤PyJgçýÇhkhÔØzÀ¬)ÕD*´ø
+Zæ Ô7Z>¥Âáe¯èNÌgÍÁÌúâ
+9“Í+Eƒ âêú+£0ÍE"Æ¥¯ç0{!ñzœÓJ
+¶3Ÿ"{ÁÀ•5õ·{y (D´ùôœ
+3£ Â~UjÆ¢/úð®‚SÑ;´a¸æ[GÑ ­Ëlo
+C\j/klþC—j³sñel +Ÿ}W§;à/ÿ¦«õ‰2+_ǯè*!bDQW{E!VvÉJ³«¤ñ] ‚m§ÊÈ‘¦FÕ^…bnæØÑ+·ëœ«&bSrÜ‹JÓ95oZRxV|ÒŸ?œoÚÊ@‰9Ïw‹Ü ¼½í­š›&¸«u/º þã_*—õÀ
+¹³®ZTsøHÎ)ÉÔQü+å½¼é~[ß\ºì'ìñˆ¸R’Ãg¥m<XfÒ°È}ï¹° XN1ÚÞ#“ÀtmP’ aâ!¦´d*„hKkQè¸ì—"jò¨2šíìÐœc·í"ì¤ü:¸.Þì
+öÓö0)úåÝÐЊ èÒ[W y·”H¼†Küµ¤0Dd¥Á¼×¾["3˜APûðáo¡ %W}!VÑÑÌ[ÑŸw:.PúÇ¿1ÃþçÇ?þ·˜ ûÌR“ÈcÖÚ÷cg¶&é“Ùéÿ'·ˆÿŒßdš>Ò)b§QÓ!j†Ê?VIBWi³lIøD[W ’Ã_â æ*à`Í‚òÃïõªô…cîˆ1ì*¿»žF–á"+ƒdù`à•ñãêžÙ›&|:%¿WõrÖ˜¸öøœ:i2‡Åï¯!aD¥ ÉÛU†ÁË°!3ò€XÔ׫`³Œ>“Äl^¤Ø:<6Zû°+…òйŸƒM£ejaIoÜú‹š®Ev ý›®¯"…>)D›TBã¸L,5åÁŽ¢‚E'EPQ1)¬wF
+751 ôŒÓ$»Õʯ•Fó»ÉU¸Ø3Õ×c0:~Éf6YŸØ^€ýÿŒ—9rd7EWÀ=´-#ó`vÐ-·WPÑËìý÷¹ÀC–òÿ—%J¡Py‰¼á.dYcªJ”«i)­ *d9Èr2‡qÏó Ä<Sq(ƒ÷Çpk|G¶@ã;V‰„Ví>|¼P)–åsZTdÂ…qÏ9­6à
+`bŸçxÖ8s&_GU=ˆmN‰x§Ì›BôÏéƤ¦(—f¶¨!ö¼¹ÏQV’I@cùšy4~Ãå“‚} nÅs@ÐZ'',H‰]“$?h?
+¤)ñ¶iõøa)5;÷óÃ1h°EQ”œ›ÂX‹Ú4XGw@_‡1iq’D›-OA6SlÙK^²Ë/¦9÷”ªð7éðƒ<Qðí V`
+Y²'ÑîƒGG\¡Ã]…Õd! ¬”=ž#Êy¦f´ƒgâÏVz³sh,—,¢cŸÞþ‰&—-Š±< <Ø‹T›Óö bBcÆÄ|o6½æ™K.er[è<FZÂü.è*L?¼Ï}”V8­5$uwÍz%ÔŒÅ\SƒžfAºÏ… ‹àþhNñ¼ÓFš´Óµ^Šš»iå¡w‘j±‘,˜r<C·ïÀ+ð$•í;öÑü@€íÒà+
+ßsÄ>„ôHµ ïÎáË,%›}VÊMæ!¥Z Ñ¡2þ£Ü¯ûùáaÃÄqž¸Øx
+LM¤Ô!<½ð„§k]1×}ø}V qÃÂ>'þ²®ŸÑ^~œûIg';ßaë [4_”´¡))ÔF`ùº\Žqó ä :OHÁÀ»žÇrAîR\?÷=ÐeQÝy¿‚d¹Íg)Ý,ˆê.ŽÊ8>^±×þ
+¹çBÚ1
+`dŸ¥å? 34´²z‹ÛÃpc¼Qä៸t¹Íx¶ð¥q "eæ~2~ûM,)xÎFvo#"ë‰â_o@ë8¤R†]‡ßÓêc¶—GÉš¬”]‡ŽM¹Ü`VBrÊîèõùp®¯¿jÇ‹Á Ä]‡i7Ÿfág
+|ÈF¯Æ^&àórìÁx °÷‰àÛkxs™YÔòÐÊ»7q0&ò€R»_šûð]Ê{¼4éç?Oðgbsi·¢WNÞi¿\·Vø òÁK€dHUi1–êç0W‘•áÈoŒ3 ¦Bê]C=^õbœ9¹@†òH£øŽ÷Út×93¦;Úâs›N”~ uþmΙþ‘Y|Ð_hؘݯNÔʆ™3”\ýß!—^}~ø ¿·þËÅp?Ò¬l'oߺÜÖ!;a£Yü6Ý—iĬhdE~­àruè!qÓoE~íƒ#^·%öDð¶[·s4]ôPâQ²{ iÍŠ/Pçxó( {—v+Br‹s_‚Çœe È*DVjé•Ôϧþ¼ŸKµXÊ\4–¼×ÓÒ_ê2,¹´ÇœÈ/ÅV(f#Ô‚È`ðÃa ¬$0µ¸ªX™ e›Xöóï‹„ýDW1MÕƒ¬·5ÂO™šB?ºå·‰¹²7v›µøÔ<Ò†T¹f±™”`©hbÂŽ¿ƒéª†ÜXxsLß—)dÈÜýË>R
+”žg{õ)ÂPdÜ”MÇôÏ„EU e6CÛ™~îá@9´/„f¬B1¹k•kÕï ¼b)ŠƒòžòFº4“äGû6(nCÿF©Û@ÝAáóLÚ¦QôÏ “ŒÄZ"q¼I[I2É0›&¸áÀ¿ô«[»ˆp²ÍÚ°a=…Lc¨³/%Ø
+.i)ÖO$דr'È臭6!Ë¥Tôe è‹Rð´ffœû#é˜Ú`ë'x†·óë%q—$O‡‚ÌyÆÆ YË¢©óÉ,üIP68¹IV™¸ÐûìÝ:ÊHv™ãi·ÁpÛ‘ÈiOžc,»X 9ÓôA¤€{¹•NZ<GÀ‰=ØjÁ]0<Ã<ö(óGPšÊ1³AV+˜olAy¶BòÉŒCŠ{Ó±D‰2È™T@•zà ÍŽb6û S9ógŒAÇ*|x´ApûÌ2Jñ;0j.g9OÇÞ׉ ¤Ã_>ãÒ‹*`’ÏÅVþ3SŠSÙŸ _£øÑ|Hž9"a aô_“–“<.éïúöµA¬:Ù §Ò=Ô®>ÐÖ ÆJ&MÎ_%*Ù΀CYtÄô Ad?YBVLýr@wg‚9Åtp:.ƒº}tw&ûs4º ²üTºÈ›Çº½pæ×ñr® 'öîq¦ÊÈ°’h„…(PBÑ”ÕáS¦@L÷d5Øéüîÿ‘eJíY Š‡%©uCðˆ€vÃXµ2Îñ’‚œOýq‚dîþúòýïÿ~üõ¿E,U»Ü+ÿØ&‰oA7²žfΡt®I³ašaw$1ˆøÞmž8GŻ͸QJL­V¥S
+ím[˜‘™$d~¤£àó >äfA “Ö¢×Îa
+û‹ûœ(G§£cܶ 
+MP-O A/áwB…[Xqc¬RÍðþPRhLL„_F
+ߦž¬Ö\±ÊxÖ)âʳ=Â7áQ‡Ò›³n el¦ÖÞ/ŒEKH’Åoc‚'¿öâ´}/¹JdŠpôõý( 0¿àÿ®|¿(fÌã ¡œÚºŒ
+8#ÑK.þ·t$-B'©ÄœÖ ¥›Ð÷—­:`Q&©ù—
+>ÿÂì¸rpSâKcA꡹<t_KŽ%‹ÁvmS>+E…¡¾Í$l Nš¯ÃÐ[9fúã¡}-ýçÙø«í’˜øÀ`£-Ó& SÇø:åý©ˆÇti?ÅñõEfŒß„m"Šµ‰e?Š4ÉÙX†èîFq"ø¢7gÉ Ql[ 4Ò8Û—÷"ª×h8;EŠ9
+1ÆääN/ûë}°ÐA&0ÔÊô¿†‡öé)Ó $Ó¾uJÎ
+jîÙ2=îô¿Ð·$fÑ>3V×;–$ÓNÃän©¨ C3^TH`l±A¥ômÈ°—ÞQ§Ý¤4¹w¼SsÞXض®a®ð49­o?€~?€tÂÑ`Äb]_©— …]Ú¦šdXø>皈N#.3¥Uàþ]#T¾´Õ. âŸÕŠN‘þäZ„ÖüŠ-ã:‡EH6õ¡[iºÆ#ìñ«`piÝŽzÿf±ïÕ´¡‘÷dmŽT§¦ÅDWër®× 7!üÆØ1
+ëlÝãjäô¾ç§[SªbwZ
+-ú](^TÐ3]÷ÏZ t“Ûr~Xà á¡&ý×¾K÷»dg±úÆVæL94JO²¨Ç—ýŠAňgô[þ}ªðOAÔðJØ“:¼Ž \‘aúƒv¯8#HYL*Ùú\Ûœè(•¸´ä§°ú…lú{!pt2h’BW•.fWÊê9Y׸ÍIãÖšwÍ`Ð
+bÌâסY•Iµœ9ðo\:Uû÷%HC¯Í7ǘ¤•¡-ÊeQŒÆ.N‡¯dj’Ÿ-™$” ùÐy‹É1fÂÕä=±ÙN
+»µÏIÈI!’e‹Šg%^I&íÑ! W^äú<B‰“¦½½÷á{,þˆšþ^·‘3bÿñ®öcÐ%°½@˜qc׳\ܯ QÒÒ®‘Ù\´ƒš‡é¬+©â°9Šœ5oël›Í²]B4ZÿTÏæèÚ
+I
+îÀ?e
+F|‘Åx‹ûÒ„y¼
+ÑJì_G É„&i®›Lò‚XŽL=ìÇd¢—C¢„\ úS2™ A™ïKîM8©ÞÿWÏ嘃„N¹“ÏͲW••R¨h(ôY@ll&•ðž20"à–#…iµŸÄr²Ø<#ÎÜD‹`Ñ? „W–(ëm'È,OùÒ7¨ëýᢶ-(‰´³¯„½##b²öž_õt²FE$\;Þ²ÄG“uã
+4§<1FQÑUˆ¹œõ­wG „a×K ­pÖêû¤3‹ãš„œôò£³"ÓLæÀ—íW]5 `ü–c\Κi†Ux%i)´£³„¹E ¹A?;ë;æÔt(RäÖlΣ³¾‚®;øúÉ¢NÓüëŸÿDjüE؉x5BÊf¨Kz¤qß „6!·ìã¾ÙˆOªð/Œ›¶áå7U¾K樶Ð
+ã„'&#Žñu˜aö„úŠÜtÝÍ/­ƒ@Ö9´Ïw&v{kÆÙ° béÁ›…ÜSÓ”/n¥§r»ØŸ´šrE„¦Å‹5hvÕ[s“©(3˜Æôòú$Ó?ʦ@"gý+jâ¢A6(E´˜mA]É•Åìºb"—(9LõˆrÁh,¸9„ÚI~ì]õcæ©\™Ì¸ÞŽÉëº`«ññaTýC7P™(ÓjÿWqQaùaˆ+¼(¶ Ä…ŽNË&{;‡R·±²¿T¢MDm>:ü oÆ6v¯ÛÆ_úƒÛ
+ä•CðÄn¾³ì¡%ІƒäP™¶?råÕàçµ¹R0NIG arCÆ©Õsbšý0y%Üÿ2^.¹qÄ0=Aîà ôµÎÖGqî¿Í+‰šd¦Õ‰Z-‘ÅúœbÕ,aȹcXw‡˜Ýd/Jì¡>´éL¼$S.¤jyק°Æl”Ë®ú}h cÌ1û9èO'µø"›¶Aâ,«w¬Ð`xÞÆþÐ{ Ø
+}Ãf®SÀSd}ùpÿð#¿—/h  ì®\7ËKó£çN(‚«1¶;¤ð$-èj…%±´ng#¼XñëAÒ)at»=7ø¥äŽ›^Š>Ed@š ’êÎ×M¾“¹
+%çÛ~‰G=²—0YñhÚÃl6Ìè×ýùãT‚Ü@cæ
+8œ2°KY\Øœ~°Tp*î
+TcµÌµòRD¼ã£à©˜ÊÂâåc¸KÈ R f sW§e·?âÓ±
+| 8´ßöÕ#
+8W®|éw‰r8p·A(ØéQÚ9œ¾
+/k+ºžòT~ |¬!÷.7¹L?1B¿ Þ_ AÚ˜‡mÉuìäÔ!qÐl´Ú1ê4Þm±Ý±=€ÁG9ç[Ex«©ðh=³†ò_Ÿ§ýúVÑ»ÃÙK¨° ~[q¯$Àã*f½­×c¦ÈhF;óøû$Žzð>ÑÃ9︨3­QÞÐË|ý`
+H‰Œ—Arœ·„Oà;Ì2E
+éÎÅëXãç JÓÃ% C é•'öëêðAŒî Ô‰Ðø `_É®œA³ÁÕGIO‘Zbx_H•}QÕˆ]ùp~>`Y×sxè°Œ2Ǿ -ÐIc5›ôÐ…ã¾›>ÉÝæ…`zqž£iþÒ “œ§k¥»f9h#H…¼‘µ?ѧ½kä•Äëìž;Ha'/™ÔâëÖ<±u*<|!´g4ŠÑd!²y`8r# BeÉ©YAÉ/ÙP‡HWi¶@ÍÀ²û´6PZéc&Èø x× Ív9É)߶-Ký$ÈQZùÏF ¥VȃÚnRÚsvàØ—”‘æ£/_=JžRú§™1šÓ£ÈL±Mãá*Í¢ëŽÃÏ5[”ZÉ‚0؆–êùÁ„€è©Á\¬à(*¤eX© ÃôS%¸;üÚ’¡ttÒ](áÇ|4ê¥ï©Ët7ò¸!šÐbVw7™÷øÜ]ËÚ9—ö„ÿç8”;¿È`ÛG!)‘rßå8 (Eª™Ã@õÎ3@žÕ=áoã5tðR´'’"_Uø㲇©Á62¼!\ Š8íäPJfs¦KM.jƒá«~ˆƒ ¶Ö+eþºMð}i­v9ÒBf=!" /a†€>$§–ï)Úk­ä™9¿é…ø1U5ûuAx"cÙl¶osÓìÁ¸bÈfZã:ê¿…}¾yŠ`:ýdö ;¿6ˆÔSväòš¤Ð/¸¥ä<ùZ TzO½xi%ò¡°§.þÐpèKŽÑ³àÚ3]aC§zÿ¤Û…%{“›ç(—’U«¼?îtAø!¥`Ô_“¶æÕd¨-žÞ@2 ©†«NIæÊN¸Ë_ýˆã¿€3ÂÊJàÄhb˜@¢¾H†›…ü‹êíqoyXŠÓ2xë1$õèå­“r…—É&‡Aß!ÅÈQÝ®‡ 3σ³=¥8ø"4¸:pkbŸü•¦é hÃŒ:&-Cvhýº!U›8_1¤{€(Üè`÷QÐv3eÛ¾²dO–tG&+~¢s¡ë6´YH.›/‰ã.ÀÊŽ’¤æX@¨þ8aN5—'®%(O½ôà·˜÷æûú“ÝÌal"äPÊôh_‹ßÛñëN4*]Ì|?‚cZéo_l^Ýå !/ ²¹ H¯ ‹¹¾ý»Žêt¨°$Èäa‚rw¶%®´âà%¨b?öQ4!úÆQê‚ Œ¹e Ÿcà²j4»^Ç€~ŠS)aIMíýÓmaÈùü¨’cœ‘Òkû”œ’[¬¦ÍŸR|ƒ|+ÕuÔ;(%Ö¡Ÿc<ηa À*ç¾Ðõü(– Ѓ—÷Wún¹ÉS¼ZI×ø8g8[–Á‹Í­íC¥¾AöQ·ŠßãÜxs¿Í§WÝx,Sñ0„îö8wƒ2æ±\EýùVªŸ¯æËe$ë¡ÙwóFøH«ûYÞA§5àvÜQ7~w§¥ΘÆù”ʵ•²+²KZ0µ½,
+zZ{
+Ž/ÆUæJêDYzlä˜%Žk±kßaƒ¥éXUâbhê:¼ ûÆ´
+Ö cë
+|tg ¼Ž ãJ"ÝÍ8Ž_qÛa/"h„¦¥:»[zDêᙶӡ c0bQNË@µÒ••F]üP4¸jýœÒš^íþVŸBüì`ÓÓù´Ž—¡@mI€Þ‹—ƒöL}s÷¢CàM}_D¹‹„fÂí}ÑäûPe0§'¢ÂÐk¡x¦Œ1%~6UÈ<k×ÙI“Ä黑X\*… ·(/´²Oå6n~A ašvf¥íÇð¼RßBÀ:IudYøcwL’|c S­â~Î ô±V_?Ù½ßò¤"WÀð!¡o’Ò*²+CPZ+Z‰ wR#úåªÄoVI "²'¬°Ç¯ñAû¾µh•i¥"M8ܽ#~ÛE¦ÒQ¶ûÓ)„/Dš€;!uÁ<TúÞ Á³Ë(úEt‹
+¯ä®WϬm"F}ìV]Kæ«,Kêém¬fqÔ8®?¼ 03Ýd·%÷Šjø 2#ƒŒ¨TY$ÌÉ!dJ9åfÎ#®!ƒI0_Ü
+æ)(3Hð ïì>3i£¹gj8e|ԓ龬g&¯C‚Ñ—P!w Š>î°L“«ªÍ!:ƒy-æ¯Þí·]…üåKœ”¹àÜŠ¼XŒvf”
+ÍêcoÖßšþ ~„Í@¨)¦­ŸÆßù!7(­9¿ºÆð¡è9¸~"ìjaTu Bµxò—‹';½ g¨t4WOù×dáúÜ;a*¸°Çº(~јÂU²‘† 3Ü„¥kÖŒ„TÒa†Š„PŒ-­¨Î¼Ê:ݹȋe)аߎ) ðÐX íì
+LÕMµÝa­¯CÐÕ-?üq«dwˆ3Cf–r öùé"ïe–m”±]×G–Òu˜
+™rÚ§iͱaz›¡Î¯Ó¯¸'%ÏÑYÈxÅ‚±ûÖ{ãblz›'ª¢¼‚mL}Z~Sƒ×¡±Ûƒ'{Iç« 6Â}Ý„•hfñÙ‚^3”QTŠ£
+þMM™ñgé‘x%Å)=ÿèdXW„#eÁòSÌÑÀ\/ûèdü «ñBÛ+Ï™ùìûÃê"kŽ»ÞÍ÷ê™ð
+ŽrñëákM¨ß|?¹«ÔZ†ð|‘¯jÅvT¨œ}ÿµ'ßÅœ|Ðï)ˆ 5{_|?_y±t­î4s¥*Õü#%Þëøîûƒf
+±åßm\¨K'/)ZvCdy: dKt®I4Í•JøMQÜFÿÞîÊðL˜³Ÿƒ-%ÑuvåØ»YPºè±=@Ôh€ïs_uÁ-Þ7{íœ(¿Ë§¦0|ø ldÔØå>5¥„•mFòù¬¼˜ŽÂ¨òž ÙxFOBb DŽMð'iBªkð #oÃb¢Í•@Æ9„ÞüyÒ¦Ð÷¤<¤5×ð×Ãré DæÄü$>»ž²oqÓøp^l.(›¶¬A@ô._ÜÜô%$†VÆ=o&cì{#Éžo™‡„4ÓÒdÇ9É9•9oe…䜫­e´tªSqf“ƒ Äo¢hMŠ!@Öˆ,­ïl˼Ã\!tÞõ6
+AºÜRG[.‘_}·|bš(é/ËãÀSÕ0]8ä¾ùtRá©€’¥O&*õ°“­çmQ'I…-v]@¯P‘WBüÙÐ>ÂQyõÆ?ë-\>ÒJŽÄŽƒañ§G
+‚Ìû—•îûªÉAžô}Ž1ÍBb`h^íYÊ“"åp1õ
+
+|4³Â±¡/1B{Ï
+lŒHmo·FV‚2l‘k“i›po×¾”X‡/íóÖ¹<üŞϗÝÇd²˜*Ì™b¢=æ  —†Ä3Æï²ÂÇL>6†5º[?®ÔÅ›ó(ã¿`üßow
+võÞÛ¼«õÐÏ÷ÒíAü¥ågÞPº\ŠV ±* uá¼ë•[@C(D(Ñ( F#´sô>%PNKƒï÷H‰WGGKñI• ^H7yÉ–KΙæ\éïdg€Hÿ¥ÆPœ‚˜!»‘ÌëRm&Å$3º˜—Šº/D¶»ªKiQñV—i|©èNek7bŸT
+Ú˜âÎãõ/ëPÂ,öËíèßq3¬_w n£D¹ÃãŠÌŽÒÇžÃ{Q¢;´¡â+dU¾Þ¼Íàmô׈û»wdøŸtÊY`ø6Ü«_J¬Ë€ƒFëOËàú#Yãtƒï«WNh%Œ,£;òÜO•ÙçÆU9ÃÙ©K‰–ÆCÂÌ22APd²1WÅl þ|4®Ys}÷QÚIŸØñ†›g«¿CùñQèm ÉÌ-!ºÙ­[Ã8eúzÍ&Šì0q¨` g¢‰> Z~¦î’ØTNˆÛ"3’ ÒIXÍçèsù8a«†p
+C›u‰¨˜ ³KòyŠW…n‚òE.|Wdá™&…™sžË:âßRñææŽçË¥|ÐKDH¤*LZrPpì†>èÕ"§ŽèÇ&ûýŸm—”eøïD·3ÜlcuÂÊÄ$F4¤šøâè$ÒPl»ÀIj½‡œ&₨Ø/ž´w·¼j.‰LË´>ä4°“&Ñë,Ç
+(Àvls‹†1„ƒh›à¬-1d:ðç›aem•W5¢JU¹c©ìuȹY¿ ÅÜb¢a­)ÙN·ÁÁ}¡Y #Ÿþ>]K~ QZ#í{¢Ðdf{CJ×–\BÛ¯0x1"z£ÅÀM_iIóÝà·¾laON Tn \kž-<¬S?ŠHj¬ù$:Ú^`RAÚ%-œ=bxÌBjqÀS·’ÏV¡3|DÝ ZʇäÞñ0-ЛÙ+!¹5e‘d±‡)Í|ƒk±!k
+¯EîXTn
+k
+gõqÀ®EÚ.®®ÓÜb"æño oAÔÝ!ŒWÁ œ»Ï{<õ ûûwË¡­•Ð>­ƒÏ„Ç°§‡øÚ™0•“¿o⯸åÀp˜>‰Îãĸc²k‘ÛžÎXÌM׌½ZäYdmG¨BØ`[ÏG½2=6dñ2Q”€Ö©àR¢E'Dz[‘wt€F!…ôj‘ìÖ9É*ãàvÑu»×Šd±a”<ñ,X‰¯‡"̦š¦ qšJüÐéè` ´É(-+éË*ãßã1^ VusÜŒî*Bª{gdñ·Yi«¬yd°?3Š?ìqh¤× zŸ»o¤ð‰+q*l§¬;€µpHæ¾ F–ÝžÇ&Q.üÀÞ½—àR´L5Xmn`ߊ<¤qÜ7á'¤i×"…1T‰&Õf×â þ ‹ø`*è¢À…À<Q°² дuÏÁ¬ž¿¨Ã̺ÊÃÎ"0Ë•Q×âeÁJ2S `j[!\¸% ÇÉ¡­É«Â\+bR’jcÊØû@g¢\›­z~(ù†Òo^‘‡÷ UŸÊ·±½\äÎàu»×Š.¼àŽ×µèwŽÌC„âc`íG}/J«çH*bÙôv”Œ&ÂDƒ-î`‡JRÏó
+Ä`ç’êúŽÔDðÉó˺ØÓ¼0eäâÜË0cPE^îÇ A”
+ ½f'"&AœAš†‘hv
+}F™ÙM6·—÷’@–]ìXì^цóDšaÜXÍ™°0,Í»aw `a‘Šf.FÁ+
+„¨ÏÍ®øÒ”5šõo…› Ù]Í¡ú@]H¢ÅÀÚ#¸©
+b„ Œàk¼Ç—7.hßnœÈ_t!èÈ(Uùœ†.Dd|L+© æ¹ÛiÈ:‰¤Ø*ÊPšfÅ °î zÖÉ«“W~·™xbšl=îˆ vïþìÁUVBôlõ÷Ýv<üŸÜ'"Ú¼4öÓŠ´:re)ó2_»H?' ¨‹$¤€p¬ø£CZ¥÷ü‚óJÖÝêÇÌ•9h¹„‡uÚê4ÙM³)åISç„òÇ»ìàR hµéšœ*å t[ánEN>â<2­zi/±]֜Թ¢é×CQC´”#µ¼;„MJÜ¡£¦à‰I%¡-¿II‘A a5ë†úbkB“<M$§N̯¬¼ÉÏ‹2i‚§÷z÷Ñ^ÐåìÒ#æiÓ)ùÜÐàƒ ;Á+Z%X¦A¯q€Çmb¯d±=+©C™£À¬Ö,J‘Õ™ÎV4‹ÀÐ9j˜LpÍ{™\#V¼Ê&Xÿ–þϵï7貦ꮸ?Þ¼ïÍÅ$Ž‚Õ\^-ºŽà×+sjã0v°’Fw òO·Èñã9Š]a&†y¾\äe„Ûv¯]rË×CQW2í("óÿ¾KÎÃü˜³êÛœ<T»¤EC*–é°âˆÒË£$›Ž ò’3k![:„’ƒÂ,³÷:82Dd+§D³$•¯ÝN3 Þ;•–ÛŠ+4‰ïó׉0N.i¿,}j §Yt¢wï)¸½ƒÌ¿Ù*/ºàѺ<ñŽjFív/47áeéRmv¯B eÁíHïŠIÿýJˆj->)/“GbѬXgÑKïs´sbXV›l¶ƒL¦ìníaX ²œ
+ 0Gp7ä&ëdËFñCHbG£—2’ÍI‰
+ÁGJ·ö[c8ñpÕY}2âK®Ân¤×*¦…Ùc2©Ûè<¯ƒ|3=åà'.
+CI“7äA ²A¬ðU@:욘¨ä¯pmƒ÷Ìe¼)bMF¢îÍš
+mÇ8„o|Ý£æë|½U¤y‡µaP>ëc‘lX’éÆÓB|@¶¢\=""1 Š¹tƒ’‚$U’z;5ãZâmÿÒÓÃ2W`è0 R¡Ym>¬ÊƒÎÄN…Ûé ¨¢1>Ôdw;ÁàÁ¦‰e±r,‰"
+MZ€w‚Í–ŠÚàDLhò"Q.i•±.¶£†I¼«¾}sedÁK`Où€}+lëà’ |{+$ƒc~ÖÈu0§ë•|cË´À§ð–a—DÌ8|&\F+Dû¼ùâJð)$LíÕ;U<?šÍ‘–IP)ÓÖaæØ½Ê X Y%)Ó5õE ̘1úD«
+\[ï~(º¿(ÂlÖ Îå2­S£Üt/![`oñ-y αJy“µI ™uL%“US¥-ÐAÉþ‚
+;\ÝζŒpÔ¹¿ó> Ã¹è•‡W¨›Âiö³ ð#Mº7ͨ¨ÁêôB:ï-/ô’Ȉ¸­Cg¥bΞ~klãXÈ@Ä«¼K”LˆòØ[!sÈ<k{d
+V³Í(ã…î£R˜°S‘pnaâ
+‹• û¿¤‘ëŽgê FrÆì%iÒ+hO°ñœùÄü+"
+g´9 X ô JÇmž—U•ß¬‚C1ÜBÐ8Vð²!Ç+ûí®5Ì'œ„]ƒÌ’·*tAÊá^ðTS°á—Æ¿òžÄ¶á%xµÖ™+ ÒÞ©÷€Í̺§O„‚.týÀC¹ ê"4Y ž *Ëàmz#ÅëÄŸ2²Uà^‡l S7Èn˜wš¯"ˆ@ ª¼Ùꡆ&6_õ"Su‘Ó›lþ±7/Ȉ‰ÿóй'Rbí~!YÕl®p¹DNȤB¬WÈ Æ7zIâdwÙB>”ø„×Æ”&÷iž×‘Ë®°h »„®J™ñöÓ94UbAš®e`¢1#P¸?.©ŠS¡Šý0$0Nâ¶J²Ze4+©<Å^ÕKJ•Çe6ª¦÷‚ï/ðáØ;i#ræMmW‚dŒÑ5„—ôé:^¤ÏðXVºü€È.‰YÓˆtÒñ½vµé…‹:¦l
+Л¯2øBé}ø,&Öæ<V`Ah;dÅ̲ȷsRוX3&RviAaáNyÔCÍý\£¡!È6€¿Š/"@:¢ã˜…â%UIç4þEn¢¦‚cÃ'Ð
+íLÅg½6M›9º'ÃÙŠ3c–d&wRH#FfÉ~o cŠ]Éa‘AÖ²e\ñ"OŸéf¾Ìàµ[ˆ3Y/#Mã@Gæ^‹÷í™6C„ð*O'GÒ 5)
+<Þ‡&•nUWut‘ΰ«$„á—B›PÀ)þðÚsŽ!rƒÙ¼WE¡— ÅÍÏêÿœ˜L› 1Ê:#Ê9×?úɘÆa†-"âð
+¢y ”
+†˜Q½S|x'CYÉ‚¯‰iï‚oë°þÃaƒvð.?mdÑkXåx"ÂàÆc 9=æÏäžåÜ&﹞Ҋx×2`Á¶—AÅiëpθ,JÄV‚­¼Ë>í—ß
+ŽF5å—ë(ò|UAëHîåeG=e{ûáÀ? |ÝPÉJeï„!çµ!Øl™\#-©Õ-#|››œ–¹ð‚xœz^ùô)Î+ÆìO%=®lE¿ÁÏÝç`ÊۙǸÐ2 ‡û• ÌÆ|zº¦yÄ!kf%¸,Ù‹~é.Ѧd0ïK㵋¬E~,C”×¢¹½'!z´¶+:
+$[á3°ÎûÚ%C‘à¬âÊ2Oå¥^[\õ! È´U,Ä
+fSƒqU—ÇDFÌ3,‹e(ð´}Lg•h4íÞGn໸ºúcø©6Ùý%øBC á¹7U0†pè»Hì™YBžäçÆî¤îö…­JŠ ´¯ïŠ$öçÕš%×M—Ë€¬•ó9×n788ø9Ö€ŠÞøa—€~¶7R¼5YI´¡WñÕ%”œA«ºÈ{Ÿ£¸7”.÷²
+d]ŸYaŸcÉþüª[‘¢•ž •¬ï§×°:]Û‡p´+ÑÜ¿Š-­) ¾Ž›>š£ÀePijÆ>ìó|<#¡þŒö¨ˆØ¥déTâ ÈH&Ð!>žƒ¢Ñö®Ðp41‚–eé È
+ƒòiÍÒÅ‚ˆõsX3(dBÅÀ¢9Ô1^J3ò°–Š°wuÖ6’
+”‡þi72ý3 × Ý\1¬~?-8ƒ‚paÁ"•#QL=N2ƒÂw{Å;áLm¢á@dèü›nÜF"+rC3姒7ø)¦¥‹)-]¯âó?<0婨˜uò$ê{5@%"_¼‹Ø<Å '/
+M™q¬vPÿì‹:ò(úhÕ/ÂÁ!­X×ÕÛ>§­B!5s€ÁÖE–­Ï’+1ü—Ë_e?h#Ì=F\ÅaÀ*ˆrUo&²°šÓ¿)ùÃ*’s‘ñÍC¨9}im°ç„Å]“ã5Sø/U¾ ;xÆwacËá%â ÒëÃò½•øž³{ ²/ßôyŽ¼ þµÏ¡[ì°É¨ôþôQ—ÛŸð‰öæÜ-’i¹dÕ¦Þg±H“¢hp†%™—rœøÒ*g€ÈìõˆJ€3Îʈ•ù*âv¬ûèiœ`L).+Ëac«p*¹“ÿ­hð~ÍAl³ù‹yÝ${¸Î" œ1Òe›TÁœPiZ\\¬²¬sAÖⶎÿ çAˆiVdX³w+k´omá«HFO“yçÂwÁÏ­¹õÂFã@©K7qhŸ•"ú>¡HXÝøü,lS“¿jÉý
+SÓ$‰’¦îíCúp.‚É oÐ…àU¢¤»«W;/ƒ h Wab™Ù6°…•Hc]ã*Ö›ž#S¯8©ŒgõŠ®^Âk±š
+±ì&?T`“Ñ1%ÐøÜÏJ
+ÎEÉ·` ír.çŠÎŠ@IÚñuä ÔúaÊ»¤éÚpc Všœ‹\l<”üpIâüºéVÓ¡9¬JnÛŸJðxÌ«_Ñõ©d@( £q¼¦Èˆ%/ã¥ÅÅŒ Ÿ²ü˧|mkƒÈâ4¢Õ\u† E”1ã<‰Íö
+dmÊO?óN3A¼Å()bC0&Ø¿Ø”¹¡¢™ÓpY9'HºaCÜ3K£V¼„lC®“ÀxIÀ&iJ)įâó¦RI úæê¶Da.
+–r*Šì’‘uq|Sã‹°’@Í,.b’Ûˬ‘,ùÄ
+ØÐyKvl1xï1À{@ª3 úgÂñ«¤L ' †¶3T!ùEøÌííÐ’”Ó7ˆÇùQL››€M_çhÞU±§¿F6§cз?Ç2a´é0qøl¿
+è! ¦Fû”‘˜çÏ} ½ È‘·à F‚0¤íÅ(™Ð#O²€è]"L&K¸7„‘RÁCúUÀ‘ €ál#8½˜ˆUì%° 8ÃÌHv;GöWô«8³t!;lßg¦ \‘YEnB«z“èýš%oóç·SÑÉÑ]FÆýë¢Sr;}$7Uð |hZýœÜ(* ¡p߷ܦ€E“»X½s[ß$‰ž°°ç_‚˜1‹÷æ”ÛÓ²VUtÎmW^!¸±¾óÛø €eåqàQrËmü&¥á ?ˆô=·7Pè^hÃgÞ¢¤.Ô@ɤJžHé~εU|F ®x e›C»~êïð jAn|öëª6¾ã¸_D€ÆP¹3Ü^¢QJ®þa@_HÌG͈};Ið éÿý–¿ÿ¥ÒôÃ0
+‘Œ1E¿Šàí¬’íúô ÃÃöL'O/©äZg¦Q¢¤¡Z°žÐþtXÑÄšº²QCÐ…÷–óåpöÏVÝÇ\ó„ú ™À|ƒGº¼v…<ãÿ·×¤’!sUj8â&Z‰Ó榰×â§ATì~ý&¦ø°í™I &%„<¾98¿Šž@
+íËØóúªÛ%ûè ³HwÂØß7æŸ7ï'Kš–taŸ‰2ioó%…áñArøv(Ú«“2.9…JÒš®´‘ÿÇx™$GvëPtµ‡Z‚=‰qyè]ÔTÿSŸKÏQ)¦¿ì°CJ!Ù€¸]öC‘_0½`çxˆõ±uCÄžìçd˜.hÝ…”j­ƒIçihi~ú)éäBæ#~õS‚Ád€èYœ—<ƒW eò&ÚŠ¢!îÃÀ‚†SÄ{uFc*®žuð*ÄR¤bRHàÍ8¸ï„¢‘™SîóN¸iÂø8VŠðß7LT9EN*¼|[Î:j4‡
+úƒáæCr`ì$Âò¤¡È¦ƒ` 鼟˜®ð0¬…Ûû3ŽP²0á…ÛðŒsápá¸öô(‚Ÿì³دÒ<Ï-®:…´å$ÜzI%).É5Æià•@ÜôKá(º Š%s©!+ãÜ#?½Zw
+˺Âa[¼qf"ðqr¥0ÜzŽ [­­ip6Í„–)Ð"Ì9d+ò%ñí “¶dý-•ka9œ¼
+“U8ü+îôÊ“…ؘQXÔc´šI§¡í²NIǽR‘WÆ*L¢ 9L5(ƒ˜Á’×0 ’d†}ø2Êk‚¹MÞŒ¬+™]+æ‡Ø
+'iÄV°BF]d&œ­üØQkÞÇU/IpÕOÃÙSQ•ôÿ@‰=ö¼”„Œ¬õ~Z LfÄú‘ rZ ±K•Ï¤ãðS("JÒä'\‹­4Ç܈&ywà8˜ 5¬X–ãž–ãè%
+HF­Wx!d”Í æã·¤.¸
+ØÖÝ=Eh]†£­Æ£K¡³Q‚ᾶÌý?Рºè˜§BŽkëEò÷Üçà5•®PÐ…X›/Ã&ëË :Ud381ÑW_lãˆinuoa/:³_½Ç|ÓzÜ›u1¬]ÂRàTÀôÀ{¼0ÚÛa †¡T†ºU,¹?Æ%Ã'E8’'h§yrÖÕ·€ýð§b”ªr#1â“úoG&ó„hÓ6…éJö
+ÌŠy6—Ô“ gó ¾
+X]Ð ‰A¶adlæ›Ð…+’x¿~ÜŠ€Œœ(|‡s,[:e#JÂß3ß½o©;M¢Ì»ôÃ]·"„[9å
+ž
+%UÞ†ûš*w^‚¨ªÏ@ÄPôßg£CKDF»ƒŠ¾E„aýHŒ™ö;±^ÀSP±u‰h±“ 'Œµvw¼øÆÐ Ÿ—_Î]OÜ×
+ë–ÅBgê^‚x±]ŽºŽ¸©ˆPRb'ÅIÜSç¦Kxˆ§Do”Så‘1÷šmÉŸð`£y ó†ÀëÖöŸŠ&s—e´ÛךO¯Á™7˜
+FǶàëzSŸpùÐEû·/E`T©Éï¹ø‘Ÿp ”8è 
+pÌ€øÅ…VäèÀ!àò9Rr/«îLø*É*‡§ÓIŠ\¹ù‘¥ ,Eˆ-W7«·¹Ë$EÉ`]f’kO™”ÊAËÎË4WÞÅ«~+\”q¨$ÜØŸa@”«]éØ
+T±UE²™ë#EFßðÊ_8š@Šq5Ú:²}uH•Ü˜È¬½sZ⎇lÁ-ù¾ŽöÆÉ$!àñ†|´h¿%ô×Új\{N™ÙÞ£{J¢CÔÈ°¸§kÑ
+ ÅYF
+E(9O;‰LYt¹À@“s­:Î)‘]VH.°›’u%³kv}uývYä×{‘œ/—ZÊNÛ7iøŒWdÓ˜—¢Ï7EÂîÎËúU†qþ‹—+¼piQ"ýâ<¸ðS"ã%âö˜‚ ë.º>* ù)½A°s€‡Ì÷å§ýC_¢¯îª°W
+.†ÇãσÂé]!óm'2+ž™œUêÛqÛ­Ÿ Gñç < ·‡ä7r)a|ëƒáÏkGWɪÁ‡Vß ê’«Êö÷N&¿ŽõÖ"> ±f1¼I£*  úeéo_é1æ;³2—ý‚ùÓy 1•)Â`Q*Ü,(”Éa’xð®Ø’§<¨RƒP¡T²‡ú#ëEœn¯Âðksmš …áˆí–áŽÚÑÀñÚbnŸ1OŠ‡AÌgy‰‹Y$û$nÌ™äž(«ëê(}»ê­Ï}§©š0‹«=£àFÀÿŠ}Ê÷ ˜™:”Ɣǖƒg g†çÉ‚*ðaq oâ™älµõÞ¨0Þ8BL>œÌH?î—õÒi ½u½”ÞÉ戲±Ärr)r¨ [Rb&‰{—T“Cjï óI 9¢ztš£-ÍÇiÐèK[î.é!@²e}Ïîr1{ýÙ]]1DF\‰¼¤<åá· H:.שԂp[ʤ”x ÒñÁeà®æH2íØŒtB;éÜv¨ +2F<|ö\ÉÍR¡uø¼É‹*„W莮÷üP¸Vâ?ó¨&Ù Ù}„çÖúNÿ ˆ§ºL!È«¶áë`úÑ?Mähg,_gMQhÜ0ët9x?ܾíÊ%…øV(:ÞùÎmž³Dõu`ŠBùª[®¯ì¹!´*å3õÄ·êL5ëë2,Àûq³0õÏÃ@Iòz”´¾_Š7!@^~¼GÁÎÄ“%žZˆ‘°âš‚ÃâCnapï4qeètf˜Òò¦€õeðq{©GÉoåý§Ø$ÇJ¯¬a2M‘£öØGè£ ?±„‚€p¥#åó§<‘„ãÛ}Qy%.qi` 0lÐdž/Œâ¬N_ÃçÇY<@¿çv‘”´CŠHKZõßb(²i>Ih Äáˆ/
+*áà~Ü!¡¯c+¾½@ ¯T& ñ꧄Z™©Â-óè)2-hBå𾯕 S­S¥ ¨£ZûŽ@"áŽ!ýìô RWŒ¦‘îùe…(ÒF¥·È`hìÊvý³Š²ÎîŸêH,@N[>7‚R p07 *&uƒ}CüJÛÞŒ¥ èÓ^@ _š|Ö}/<ϦTw?0u:C?#ë<ï}}×ïùz… äùšP5©¾5LÞgˆŸ¡ÃïMKAõk~H y‡©‚ÝJçu™;‰õgÊ¿A|Q)3¤Xíeʉ `9P½YÆ@¬VíŸ)GIñGJ_¿çž«müÑ+–?Ù—êD)ë…ý©+G•ùI§5ÒÉ°v¡¦~±üö è­EîmúêÙ_G­`ž¯õî± l4¡ë~ ±Ã$¼Hh9d
+·Ò
+õ¾–§SJËgOÌÞ•yòáRRGâÄ°rñœÅxJ‰©}lC
+7W…Ž_
+fý¬ƒÆHð ¹^?ØßZnzŒƒàÓ’CîË!è
+7ú”ãµ—lÁ8’`¢¤D¹•|Æyû)Ï¡ÍØh?-ÊHŽ
+!V>[e ìY|ò° kHJ”e-x î—"A1îDšzb졧;ßüÎ\Þ4(Š’­7C‡2˜Ë¬ÆVÄȃ™Y§Ó„§†6ûa¨A°œz>‡°OÓ[e_¥éæ|Qäù|²Ä‹9«Qãߪs %‰e³‡S s¨Ó¡Úìã+^ý\#^Š‘Gô,û° <4éTΑ3åÂE¹ªxÖý´P¼&—$VÑÖÅ¢Ó
+‡ÝÙ­¡hdHº±Ÿ$„:œÿ›BÆ–H)ÒÓ ô2ie°PÐE#݃š ª}–ÿ C®Nok5«+¶b[Ñ"7‹àÈt‚hg&… K
+ã.zÅ»† ·4ŽôŸ#àDF²çá ÚV·Ë˜´Ø ³Ëÿºªì]ü?ÆË%¹n¢[É
+RüÆžf™:ûŸæ4È÷JTâzU©g!)è>FäñÇ´uˆL'yÆJÄÁER–2íJ°*
+Žl©H!t>J’A*=]_xD§´Yž*^áÕ?Ÿ×A–ÛÙˆ€°¹°U2ä…%‚ÉV0hF  ÷%5K†H„Ù˜IE$ܤáw›½dˆû%^øv_r¥³mðÆ‹¢’} 6$Ø‘1y*áAøN|—ùðæÑ’75Ÿf¯‰+UJó˜Ö¥ÆMÆž’¬ƒé±SíþÝàî'–½»r{m,âRÏñäÝè£Ñ‡Ï0?ÓY•6ž É@JsôÂÿÄ C)Ñ” Å•¸ykÍ*³†žšCV©ú§=Ö¢¡¹+Þ;âxvy‚¼
+A;ä¹DÇI#þ‡¬4#eM>¢âKÞ]säRu.©t…ظ®’Ôð¯ÌLU/Á^àáÊ_棤è²ehÕ¶‚©• OõôVL“—âwžôÞ¸•hrd(úk§Ih‚™²•àêC‚<š¾¶•í$H«ŠdÃã×{BSÉDÏ‘Å]KÑ›0ä úÃOfkÊ„Ò˜.´X<ÊZ,s†$ñ1%´2Éó.€TpÀ'JŒ
+žCJŽ‹s[²±ð]Q"Ö±[¾Õûa A÷Ö‡m? v‘> Œ´õ8/ïífij·Âpß\®—„ J ƶ}%¦+'æv|§ËkkvX7É»5VEb
+†Ñ(o=™þÄK n¿’%|ƒäÝø†EA¶–ìŽå¦Â hÁíjP—lò±õËKÑçS=Îãñ!Õ÷º•óhdÞù©9eXàÓèÙCElØõpÃ2¶"Ü‚‰uëiß׊&ÝH
+ _ìs©‘ç"  kÛ/¢É€Gð§öpÆ»¢5矶óÒËø°ÿƒ3†þÅ+—‚·1رÈ@KàÐ ÂÃ/•4˜™¼‹Ô…o×È0z1˜~{tíðaÔÐGµã:2%t.:‹[÷'´G ÖŽ9P ÝJ+PeÜ£Wò<3ï¦H‘™SÕxX.ÒÒZ-?”¼B÷ïo€ù/žªL# øq°¼Ú$…ä¦@^ø³-"T .h8NUì¦9%™+Ò,‚¼ï]¶ûüΙŽ£g91‚çÜ­ôgS²;QƒáQË?Ž}+Úû?ç±CÇŸÊ©LÞl´4:Q¾ÜýØQJCo¢ÃPâñ¸dYºL ªúN–s‚NtCDÁPT•$t-㟥àpŒ{Éœ‡P„8"4£žÑìµKVE©š¾-JR¢óvqMËHJÑv*j?÷«d˜5 
+ßéRú˜Í*ÆI=¡– ô€ºñP[J ˆ„ N£Yç¦zí¶Jéw,Ó˜@¹ÛË< q”€”
+¨³{¼2E­°3 ‡ÒÎNqH}j;Ö¡z¹+G6aé™’0þ
+0
+H‰Œ—An¬7„Oðîà ¤AI$%®ß,}‹ÌÊsÿm>þ¢:±ý÷À8ÝÕ¢D²ŠÅÞfk2ÆcoÒ–LÑ·¿Æô‡ŒkŒµ¤÷·?¿6hö]ºèÚ .kô FÔ9aÃÕTzAÆÒÎ÷S¼Û ˆùòÞ‰ÖFûýë´ˆ=f³>¸ò{‚úƒ°3†ËðŸƒ:wŽ¾´½}¼
+55/Çi~Šê–õâ»ýÁýlHÈl½ â\Zy¸iADéËvHˆ=ÂÍ¥‡·fÏP6tÒCö•urC&úóÊJ>ÙQ-„̾DM¬­]ƒqG»T¤|rï­õ¸]Ö"$»r­‚Œîkr6ÿÞM3áCÎ)‹«Ë¢ƒ€\¡Ú#”¯i_=IÎ_ys²µ»¢=èܦº(V+H¬ÎbÑ¿2Ã{À$™U𶜎èp"ü„¢q…äé<çô©ô÷}³I_Þ3 × º¢½îkdòÎî-N$þ¤žY–j.ï0-ø{Õ9 &Å“ºÌ´àÚì"Ä×áº:7‡¿îè)'.צ›ÆAãC„Êt>y¿ ÷#Á>%Õs Y}«Á(»"‚ü®J€Åœ±¨ÖŠ Q…±aÒ ÷HŸS o°!èÍÑSï â4*}Ä‹s²ÌÍ8 ο€Ìæ”–r§—¡RUÕŸu·E*–@­b:Yi#Ú@­ª™Ñ$B“­ÔÀ”+ÇÐg¤¯ ¯bpù·¨¼€Ã}FJÈ«G}½ÿú/°¾GÌP®»Ë˜[¢œŒŽ·ÿ%hÒê°vè¸Á\wäkJKìf ®è .®°!jîP‹¬ž™„>À.šGÆuk@LþW,
+¥9âL¾÷12§)½`«.c¢œ;¸Íu§Ì„>ëEƒï[¬æ¨ðŽãj‰¢Ng@Ò|z-ûæ^þJë®Å—„–K+¼âv´û•ãÉð¡ó£1ý¸n…2Dε5ß cÈæ¬A ë”(åÑ[猶r²0_Ä_@`bÖy1Éüê3è«<}¿L
+!¡èkÔÓnõYp+]åFñ%î&9jÚXC÷1+cˆ­åÕ â1?¹ÁXU(£.Ñý9©7ä ÎE=~$Á}·²±p—0ÜIN6ß­Pâè–§ü¤ñDr
+Çe¨] G.ï”!êHÇm} ¨#SƒGí #ÔÈŸÍ:m†qA„_¡èDqÔ•aö’—]ŠÓ“bC­Ó”R‘F‚)€f-+CÑÌX›vÓ# s*é ð¸Ìºº V-Á!­Ø2ÇM:Ç?k°˜8Í;w¤à`E`nÓš)ˆnïc4'¿YÙC=}tl"ÄÃRh]×:Þ½àÿèP‰‡‚Àõ%6÷˜øH,jCö1Ù!œãÇ3äœÇ‰Ñ;kCfÇÿaïFT£ætžcb÷˜&w$
+-MÞa e²Kh]«NÂ"Ų8GQy!ÄœûÝ›–Ï&—aÇlâ–ÿÓO)Ód3þùé1oÀy£šf¤#ÁÝérjaÕè´ÓŸÓG_dHÆ ¤¨@äìáÞÖý1(å¦ þÏ ²´ŸLMÈX3Agê}œ¨™“8’ÎpÑâ|ÊzpŒä0ËU+SáwÔEŸwrFÂgÒ˜›WF­É{ƒÉM‚VKÏ\§ÌΑÁp¥÷×wéŽ{›·Üþ©2AbrÐ¥½:q
+ìEΤš>žŒcTKô[ú¯Kï› Ç 5©?n_™€ûU¡Nñ³ùd½ÝõpŽ(¢Ó[K/§ž²J×À=
+ãC?rtl.À—,.üg“Ú üH²×fªîǯ;RÍkײõ¤f²‡¾i­
+GÄðš›.h
+àmh~©Pßxõý±ôèbq,Ï×W 6ž6’i‹+ÇØò KŠäƒì¤} ”h’»d†ùîsœä²sd)jD¢m’Ë
+Oßœ{郙þa OM;5ô„ú2$˜Æ8$h½rùØçÜÜx[î&‚dh9é7dxϧgòkð3TQMþüçUS2xÖ8µ‚ôxÓ`媧×g6Dí+ P5f¾ CQÎ'ֻĸ1* ÿ“; }¨÷Îq£Ä%ó¬?x7Ñ¿v…béYvÕþ¬›ç¶â{ó—OO¯R®ò*9º…Cî/ Dè󚲞¡þ¯ÃxO#òöŸ„
+3 'î,y«¶ ì?{„aÐÂ4#-Xe')B0ýtAV$Ó EAÚÊ…fx!¤QEÉeöÅúýÄ\Žšû‹…Ž<#v¡ûœ‹ÃYÙü¬ªéf¢‹:@ÌÓK@ºŠ„z]{!¤Ô O¶ËYfQ0†hN?ÛÇ@hɾv ôµ¹R0‚Ú† (‹#ÅÍ›%´BÑJ”qæËjÕb¤â-íd3š±[!=µïB6í Û~éé âÓ2ö{s±Fqê¿}¼
+h€mw #Žö‚i#UZ·l2%›œ£„Š¸Çë2ŒÁ±š@I‰s/³.Å|ön:
+ÉU™n;1|(Ì71ù
+|Á£²”oW3±c¹²UÝ`t`Ìmh(ÑãQa÷¡ÿDjP<ƒÐq.‘+G+[ßêVÄòZY ŠÉŒM§1ûT™F€øÅy.žV›-|œt
+SMã&&ݸ=çÌ`±H̾fFy„Hk˜H,RL†)Æ^R3¼‚dž˜ãhôÅãcP Þ%6ê<0v€ÔRß–©¼Ûç<ÉÂ×ǘó4ž`‘FV²À[ÏLÙÛQC³A!¦{»¦§ŒSÐ2åá´c²K*Qs^×JðâYØ/É;ɹh5ÁÈ+bÐdn1ƒyœy2þÄä!É|µºèÑ“ª‘wˆ ûˆÃÆ÷gÍ$ú)«j;¡üØKäa»¦¶òBMÖqv (S˜ŠÓJ#ëJ; >*ú
+j£Ë"þq.’§ãRÐ ô—I0+íðû¯çï5°µã Ç¬'ííÄY„ŒœUSñ
+®šmË¢0!ŒÀ¼|
+·µ×A¹h<2ïžÿ›ß’I Ì~z3ëHo+pÂâ"÷\GÏ1ž&>'ÁýÖKÃz¾Že‡ ‚" ~çå\„Þ´4ÊÞþÂD`$»Â& å”Ô½ dbð‰QÇÙ¿)ÃWÂ)÷à —¢°0›¶e‹#
+x(J½îöI À4¡g†ègQö³#úñcUxQpY‘´+Àf ‚ä/+Á¹bÍá¾²KdLè?—È–()"ºÊ{Bø»HˆWdžƒm6™A¶Ì]‡HÃè»Ç„öpäf§òL*Ž|+p
+¢\/Ðí^Ð'ÎqVkUå+™µa°dW×dÈhNƒ¨xÃ2ù­ß*—e¬óªa×&ª‰ÍÞxÈYèi6¡R’ª”&‘mâ.é‘evûµÊK¬›U®;7R}[%'Ò±-}ßO¼+ˆüºB¡þ2(pD8¸‚ï¯K©k 6à2¬hDm‚þ†¨Ìj”íù–íܳY‰H ur M&jÒ˜Õá[Ÿ•
+œfznáeªp™Ö¥ù
+Fw0ÀݳÄ#¶¹þ\¥°ñ¸ø
+%`l"ºGòAŸÜ(Pโ”u+ÊAbÝḇ(Ñô>(KÜ%‘»k˜ +ÁT`‹vœ³KøVx,¤ó°qDQXPÆËÖ›\Ë nåqµœ/­ ¦ÐU€ĶɳʼåÉIxlÝJE
+ZO˜ÊËØVËs4rl¯Õ~69L%äÝ×:¨.‘–UÇö? eéSeüO}c«`·¯;=k²œÅÀå¼AÁKоbÓ€n4õA/úñù(%ç27ÔWèu—C îâÿ“9$x»‘a˜ëÁðžÐw+1 ó™â*lÔ_ÖQüQ™}s-­üº¶ïzŠð
+^åÀFo ß°ò)ÄÙ´©¸~ J-Ã|’/%A:`‚~Á:c|XGÖšÇRs•¨w@¯HO¸ó(gy9ð!Z³yöêäEC+fˆ$†/kò°À%*š¤L"³†¡`Á¿qà
+yL׊=7iæ­‡þ:SUŽ4[4­ú½ ±&Ž? ݨ½muaG… ™“&rcrÐÙ€*N•?öÝ?kÂKÑ÷§"b\ÅFsž»üt«Ž_ԉ’d4Ãoò¡[Ü]9°x7ËTZáÂÑ@Ú²%¬xöO%dQŒ
+è´ôûCÑ–´pLy÷ͤ&×v‹€JY´Ew€ãñbáš+Ö>ÇÈ×suð
+þ8ç<a€áí²éó´0AeˆûGîБü”ýÍQé¬TO®Ct± x…VÛA„ˆàÌ5Rxt”œeÒ™æ k„Z„ÞeÒVz°É»H_¢Bñ‚ â¼ÀýXR¦®z
+E™÷½âëÇäŸÿÖ‹˜s‚iŽÔi.‰æ€g†øïEbÁ9 %ÐéO+Q=¯Ål /ÑÔsŸ=F þ’~ÔkÈ L M*î¤(áG^|5<Za7– «ëoÑMk¡^¸¼+>ÃJxYl;ù ÖX…Iì4c+ÂÌÞÐ’.Ú\¢<µ­# ©XqdÜ"à(¼€•¤¡ã`÷>«¼x©Ìsñ±íŒÙBÝôî˜2ó‡ù×Z¦â0éÎQ²†Yù±­š˜¸Žzøbhˆaãb¦øëÇ­æ-UØ‘AW‚ñVoød¥¢K•î_  ŒæâˆUgÐûðgHÂ9L%ÁpG«W VëyMvLp{ÙkØs°.Þ¹ø2ïÈbÆUÂÜäü¡ä ¡³îÞà*ˆ|9ï´_¸‘ID
+yIf (Ö«j«ôKb:€ö˜í”ˆQãî@¦jƒï…Ü°ÇÄ
+°Œqé—Äp.ÎY¾KÆoöT0‹µà¼–Ša•ægh«N9ªöǼYEkPWÇc±7"eÁâ^Ây‹¢6ÄNïEÈ=¾kað¼3M âÑ9 \Ês´ÄõV³sæ½®©€öé’L'F0ÚG²àí8“E@*z‡y%ý9æM.vŠÊw¼$Ó} qóQ"º(#tzŒM’0Å(GVQhå_ûX*ðË°ˆ¶÷òX‹þKTN ÃÍ­ÑÊ5c«"¼R3YÃiIʲ|¼l×ôòë%¶AW÷Ó¼Ž”²Mg¸ÔÙê_æî7ã™Lk*¦bNŒ~zL2Ü9àJüA³½YW›ŽžÕíŠmã*ùô(!”±ð¥ë^Òh5†‚Ç? –Ûš,׶£WhŽþÓ¶¨ÆŠ”€(AÉÒ°u$¼Y·¸jX‘™Š]î
+
+L!£êÂw¥®ž¥ãÑa¾¡ï«ÞåF%²„Øê½Á¥å)úUîï÷ ÿWÛá H@cS. ¿´€ÿzÜŒ±\5,@𥒠«ŒÓ!”š(Ò]+±Cƒ7–ï묀œK‘ÒÍœŠdßqÞ¤‰nëÀõðÂ’SŒç¢CgcέßF$ËuÇyILè#Ú͉p‘ZFo d¸bïÍOÌ«l2Š éÁ)c :°–+J$YðÓäïtSó³]jáY“òf…‡ø¯ï”à~†4
+Q3LZÚUŽ­}ʬ"â>bB«R wÅòûsRD2cÌ› ®’þUèš],øD€¼?ØÇb ²z)ÁÁ­-á͇/˜ >K’Ñh2Æ¡îta‘=¦ÅÅ¢–ùêhN¶³5Tó.’”0òîšÊ£'U® [TÁ0ÄÃ5®RAÅB%ªxJè–íÇÆq¶Æôæ¬ Q¹¦´sÞ[D›È…9Áëô€¦WŸw›º'¿øuÍñKîG‚‰™Él%³=ðü½×XΞÖÒ¡ýX¥•.-:~à‰82D°`ˆO±ÕaN÷F*HtÐP„5jxÅ–à¿Q}'fŸ¶Ü)Á`Iåe+½„©ÆË š#_J¢Åø¥ncè@0Ûð?Å×Ïó $þ
+Ã`ҵ[®vgöxLK¶y™ŠŠx†˜ÚmÌúÖò>¯À_
+ȼy?|ºyx x'`çŸ"dh‘„à&N´‚qR”µå]Ë€‰™¹ùÂû@½«\J ŽZ²øûS·"FÌ
+M<B°îÜoÓY„çñQço_Š²Ñ ‹+6³;C9‰Û
+‘X¹0~ƒ½WL¡¸!Å2¨[qóUq™è:ëÐÊÑ'—Ï‚[DÇAKhÛšòHxï9ý>†‘55 ÂQHt¨“DüKHŸVùŠg6¡DZ‹ æ~éM27Ar}m»«¯x«èò¹sؽ]¿„btX³Ýæ×·“uå•ø%ÖÇ&¡2!±òQ@&q(fuû¶™
+¯\B:£ÃBJR
+¨TQȆ)O¿#ÕÄc™9 òÊæ1Ï3ÊêóýY¤d jOggK ÂC”•³³mŸD€ÂjM½ÖUë#$4ºmy)R ¤ZQ=°3çS‰2J–;ÉãPb ºÜ‰ÏMýéœÌlæb¯²K&` ê½eÇÅ×ÙŸB™º¼1ÒíøâƲ+¼=ïOA£¬”3³•µ 6o®WÐÞNÎȱ~h“áºÊ½÷Î@nÚ°éâHd³jϼÎVB&¾åÞ[Ôd¢éfC;KESWÆ,íDÖ´ô†d ±>ÓQ
+WX´
+‚hu‡² (ò¹˜CSâ{fgPf5dxR÷ËÌ$ìkÿD>ÌBŽêÌß-"É
+)¾÷ˆ‹d`ÿØ‹°&u*a¶4ÿƒ?¤ÿþøãŸáÛ?þõñÇ>â·??p^Y*BH¡=C\±@hSÕxY MHS`zp©Yô$Чa£“¢18›±ƒµUûASE¦ßJd‘(Ü4Ô Š ¡Oh‹ß††šˆ:y• '
+dU\©ox jÁ ÝP‰Œ-n€¸)nPSä?û"Řï5?jÒÂ5™
+¥™q7™oàquhùj2ûÞÆBn}˜Ôÿ·@62:¦—)îVeÖbq!VŸmtd(¸h‹Ç
+—{2v»tþ¬šéOà°ZÑ9+¢p¥
+Ë;Á”÷Ë_Ñ<¦Ä»);U®`C¥ 1q*FÆJZÎCˆ9§¹_KaGNªaÃÒùàÑ¢=uQ•._MœgYE×c.bòE'£ F\îÜ_‚™²0Ÿ«U4åá8¬’aè¡ð¤%ÝZ¬(ä2dô­¤©WMÆF…
+2v—"éb–%rÀO9c R˜V‚ༀ!sw¶TðåçœüÞI]ʾÚ>=Œ&6ßP”RrÈ|†SøÄ@NßOð¨pG&ÎË](†us¯‡ÿWág’Öò‡sÀNà£L€—ð$,ÜÀD'9^­Tš—UøpÀ2-7€åÖYJÆÕ÷¢ãv"ªÕ1(mB¤€ÞœŽ@a™°VgÒbˆƒUgá¾pVp.¢ýpùA¹Œ¸Ù'C_¸ðå´D_௉.Y6gw,›/:sào˜Tœ+²‡á8·cÝ·Ê‚Ÿ”@ áR„cV¬{ó5ØY—Çh”º *úy‰Ž•CHIµ=‘ŒÆe2é’ÇsÐL|ÓèøÙáüÅ@'¤Œ
+,Ï·ø›Ó­~yQR¼ÂùU§z ¨*J×,¸RÄ,貂¨;‰‚tg Øò©•¦ ˜ !)m?îÕP‚Wã. c>ÅŠI5ɯ‚ìùŒ{’uÅí¤d±A¯²_ÕJ:N
+þ®k [?ûšÝ@.…F—'\0tz üž ºoŒ È¿¤!=ö 0üQÁFMi€ûìñª‹;þ`1OAt¦kY{ÒÓím -…ÖNÎÇJ$—³²}õœ“¸…Ï/÷¢ÓÀY=–7iN©¾]ôâÑKdúšðùDg‹Á¬Gk„‘ *C,lÛã¬ø-(BÈqžÏº†&ž¢"áÁ§Âd,(Ôä%âÉŠ HÓjá½èЊ[e¸üÔç[Ñ•–¾ÃÝ‹â¿ý©Òú9Ìh’‰*Àâ«DüFvš¿%‰*ö"‹ ~¡„ÖqQÜÆV̪ƒ¾Ðäê:×XöµB~ÊHPQ®ô¡P”’¢M¸8WüØkdç0}–#|-èLc¬Ö.SÀ& 8s™ª{Éú–êKÐj|>Û7¤fðhó7Á¦…êÄ°\_pMÝ<Çÿ+ˆaU³-Щ¨,*lË[ÙÌE"îË#é> éÎ4gÃe¡)ÁÖÂ'§ûÎW΀ÙzÃ?^pE‰ö; ”HóãWk!)&sP‰›ÈF†â")õ˜»**bï>K6‚"„q<œr™öé&Ôœ^tCß½3 _û{(y™Ó_ï,Œv+ìÝŠCvzòþt8ï×±
+PîàZÑî•é×”;Þ™ªT¤
+Y7ÉEóÜI5R¿;§Q[öºå¥
+ ¶lB{Y
+$fßË·b„zÃVí…NëQT+P +N) kÆô]ãË]` ¢Ÿ¸3ï»rÀ®AUy )&úHuCà¨ÁŠ•™¢±Ó$nãoëÍ9‘áE Râ6ƒ n¬¾‚`›.d>± 2,{·—; ë ò.-òÛ o-^o{ ó²§îÀ_ÉõD¸\)Låı¦Ú‹pWÐj%rÚPœ¬Ý•œÚQ7„IêñÑ#mÈA ðeìK…àñZ8·íscÕJ1ît#®™Ð"űì%öLJи `³H‚W„ÝÃŒe„#ÁçCd lHf´0¿X¨ÆåËiÉ8<ÎèBãá‹.G3Ö]AŽCž‰blåÑeH/\ÏxÄ Ê™6jÅ£¤ý(*E ñM'wEÉ÷M%:ïÝ/{øsõ¼c^Zð,^'!t8÷(>Ü–ì:Ä*æñ¢»€Îð"NA?ó ¤ ‹YÖ’n«¾⿱
+h¤©,u7±ê
+’缕èÃçíï¢Í±§!a%€xÅÇŒëÜBÊ"³RÏq>ÂEá±Åõô†—U“Áu½RH1+vöÆs
+—5Dï`<—¨ˆ%áÈq2†Êjcº°ÉN*:kÈÔÑME*b ¨cúšh.½pR‘Zš;¦àæ$§=hš¶,—|bÑT¥‹²¨Íþ£óžxXršƒ7×Ѿ¶0‘/˜a4’õ&^»êeÚÓZ ¨?¢ aÁÈ…CÑ%×v®ú~µþQH}Pü¹ØßX¨‰üxL7ÑAX8F¯˜®˜…h¡’aèrìh•¹@Pà‡ ):%ãšÏÒM…ÜÇØŽšUh‡³6£è•.;µuŸC<­Ë“5#èÅ1‰YHà MªKBÜ•–a˜ERhÛшw#‰X4¤l³ï3æ÷ }ìšÁŽ`
+v”mHÀ½`_Øw»&Œ4™qªfG0ë¼wB«¾ À‘1_bйv¹ÉAK,bu!ñW±ÏpK5Êt0> ȲӻíÐu ùâ,çÀŸh“Ad›áÇZís&9€Ð‚ý9>.ˆ7ºäÒ–âyœ%Ì
+Œ¤N'Û?U!ÒÖx#L¯}w…‰Þ”4Y€Ðo¬8u/åëcxcQÇy– …7 ]PyüQ`{±9$´j*²U t¹ˆÕ‡a‘e«_‘¿` ·`;A£ Æ=lÄËíÜm­*(Fš,~q÷Ó½xŸ3ÞMò—î`I㞌 Rcѧ(”Ïßíʹ‹ Qf³«xè™1¤ïF—SÔÇG;…¡P¸b[G9“¡Õˌ¨É,úH¹‰ÅºQ!6p”–ôzs×Qc :£æ–ôH©sv 6Y4ÇRÿ»s°È8u½OÂÙc±¦qO_KÄ“ 2ƒ†öâ(2†lMÖ+–³çMàžZm¡;FC—,q+:AlD-ݤÂC\»Í‹]MÞ}²I›»ÍÝLÎiŒdÇ¿L3L$öJ½˜F¹0îŠNÉ¥ÀˆT”«¯}àÑ:Qˆˆ ³ø
+ɲSpM7 V Œ|Xè7nc‰øÓŠ‹UĪÃÀ!Tï@ê”ݹ¿n<¦þ§Àò±8 w*ð׶¤
+[¬YC­½uýtAÒ"ieFÄƒÖ ˆøŽ¡ÛÄ¥NsÈ Áæ1¦UÞÚ¦-EÍ+ű,¨ãGX:ý±É–ÆËÁÇÅõ@ 6d†æåé®PjåH‚I/7«ˆ:®e˜.î`›¹
+Íïù<< ¨Èü³‰*9p*Xew«zàÓHMÅÕT*ÿERÖ0ÈaôéžÂö‘ â "Tó,(u­*ƒmó™õùˆi°OÑh¬TÚìAŒ9ü˧ËTxùTºM>É{:##u3—@u»h
+^I»ÙÎÒ‘&DmÌó¦Ÿ6si$3öPžé•M žÞ~n¶Tk•B¶< ŠÆL¶o“Ì;ªÙ$‰¶4’hD™–Bä¡ $‹êdž$VÃ{ed½->÷(Kô“-^ÏQÓMäÉ97¥fB1_<wCpô«×/ffͨ#,Û^Kíj†mòÏÁ,0 xÑú ¡ «Y/0Ûd]•i4]SéÇ?G–—‚S?‰©a¦q´"Sϻ˜'oòKøù±¼÷üòüó›h~n¢¨·AhNIkÐ4+.&¬ÉP»èjAX¤&ñϦU<TþŠßYˆPåÛ“² åÀÙXÑŽ &’¬S©0§Ýn"c¡ÍH@Ú–‡VÀŒ°Q';]_²Zg›éi½ ¢i F€$¼éYN€7"Õ°sRg;;Q¶;Hzùƒ(Í¡ö¯Œš˜£UG²³,Ã,{–õ £k÷šï€À¥Êe%Ù)Ü QôbYç
+òzyi¤êĦXÞ1Œ
+E¤~¹¦»nég¸€Bëþ9œ>£JIÎ`p >@ק±!èÌ7skYÊßAW}•ð
+rªˆ…äWs
+·éò²Ðþ7 Eäû” Vž~5«‹êåœ{D¨y~@…5(KËÍƈ)ÌX3íxÙ
+-ᆤí¼£Üœ:öªÒ=cžm7µ¥•P™tŸiëÄó»6±Q~$aÿg¼L’¬Ê x‚¾'(Ó<¬Ùr ¶pÿm{høðŸRT™uƒY%=åé93‚„éʹÍOBðÚ1Øg`W?REàüRÔ†xj~\4JhЇsÂI„ç(¸UiéF»&™Ì·!¡Ê|iÄf²¶;‘áà–„y’•"·ëT"
+ð†fÕÏy¿Âþ™}ëPpÔV:úI Z#sóø,Ýß_/eÅ ³¹µ
+ƒÁ#V„\ ŽZé8›ÐF$%‹©6¤`[Šmâ†> =§ÈÄÈsû@T`*ZŽ‹‘`\)ðÓ2Ïî˜PRY’\
+z‡ë8‹>&‹Â"ÄhUiupòGÒ—Sú$d÷ñ{Ob8Ö&Øa—…ZŒtj˜]ïÅ"«Ë 1¤øÝ9„<¯­q¹å±°·!YeÇæ©.î·sfOY3Ë÷9<‰ÒnI)žè; C!µåN«'Ô¶Öy)û*nKy—Ý唣kîªÀ>Öºqn§2Dx§UDØËĹ'½ª‚xü—Ík}/4|+íÊ1yÔKÛº¨¾"§Ì}¹mɬ§*”MûûÄD¿Ï}+£-1¸²W© €-ŒT¬bXmª˜,­q£n`<9Ù P IÓžåÆ/ÐåÏ<H·LIÕ"ßm·Þ›ä缊Íwnì×sða¼Î‰}Osæ8èØéˆ)qbu ¯ÁH0xz¡#Ö>Dò°1›Àæ®ìôÐœÀ3/£Úù-4ÿ=?[-.d[CŸçg }úòA™%¤óãõü„é0è€ûn»)ùò¡R?L»›)“v9A}4ûªGk
+ K¦"ht 6à”Mr7hD$'¤“ñÇdB#AšRH>Ìy-Éð€¦)tF>°‰]°ÌpaÆSr"ãh'¶àÀGµ‰Tª’ŽßË݃)K>Ô—ŒÃîÐ<‰Ñi} Ð kUÛíþNŒN8Q•f×T~žì?ÄèTšÌÄÒrÛ$÷$F4üN#¬†!ÎD°°nA€ÙDF$IöD Ý‘†!ÄUMdDâ
+÷ª«Œ§äDFKs ã)²Jp´:ý·äŒzyÒ¸Öp½!ãQÊ'2ª÷À‹–5<LW9Òn¹“ê‹E—±(ó·Ý ¶£ÔSsce1€Q¥Í
+
+
+âr.æðnŸï"~Ì&!™aU#8ΫN€L*ÖÃ#3­©¸×EÏS@.FŠ a1_Îɸr‰í3–t×z‘b—ùWŽ‹ðM¼Î©Õýº(°ik(
+‹ÜÃV&ö¹œÊ«Ž)ÃÜÒ«äc&þ0@]¢Q–Ô+[Î:g¥àñÎd4õÅ*…q6ƒ$W˜ÕVØBÅÐ ·È#á’Z“U†”û•q\…=†AñògòM‘†ªâZ7OÝëÂõêÞd~ô0ÎÖ3žÁÔf¶( zWA`_ ‰¼¦x˜ÃÖ®ÚS)Áéó|MÆTK,«ó2I`fWó”°pɱ!ºÕœ€9°IMB¯¯ÖÃ’"/àè)Rpø˜ZÊv8ç0g-µM ¶Ä—‰]{_™$0T[X üÜœéMôÃÑG<’¡BÙÎtˆð3x‰Â’V‚J0:‹¦ŸX>#ìB‡xZ«`Ÿ:.î뻌)tøžzÏK0»×R«H3'ð œL'VmMuÝ$O§b]¤úLr¡lh¦]°$¼ý$Ý«ùâ®õi@Ä–8.ÿ_-ƒõÒœ¼h}/W6í»LƒU:”=ÂÓ"afT´@”‹„¢ÒêÊCñ–ï«g( Ó«†è×E”‰yÖÄpe=ݱä1 ÿg¼L’#¹• z‚¾OP†yXSKÞ¢·ìûoõ(‰™(벯oR³ Ú¬nFÖ3©Üæ÷)õ×ðíÁ¼û˱è
+Ž%{3að˜£d$ºˆ°Î¸îÁÿÝ­ pØäÏâ`+)ùŒÛõÀ0­˜ã)is¦hÊù¹ë_Vâ<W|ž<D‡hªC(rƒÊ4Ú>8UªY¾d3-µbt(Ћï@ûu1•~æW¦¢¥@®#Tƒ$mÏÒ¿0c†–Úâf EVh)a)ÓIÑ«}§ÎÈPDŒ¹w³,j ãÍØ"é~ -awSÙͨÃfŸ¿N T˜ …VCyÉá „<B
+MìÙƒ?½‰ëÉ$s§‰¬ì…#†èiM>+½ <ØÄÌ\îëÜA·Pò7 ¶Ü;:Ë¡A>†ƒ êDè{)5 ¬)/ešC:LÙ‚ðQf¯ãØx ²%f­Æ‹ÂG·µ~:<? P ·c_ö•;9+5v2 ‡ôòÌÛS2ûPé›Ï_'È­>ë6¼¯©=µ·A&k´\Ö;†1ËŒXIâaµ^+?as§>@Ck—úI©™Ù©cŽGêZ…]Á˜dXqvÕA°%rÀh²§NhuÔqù!ì§Aºìva™R9@~Û\Po¼+÷NùÕwŠÔ‰w²5 vÀ®RüâÌj§)߯â¿Äs\sì£è&îð+à <’™DHí;AÁgŠ¼Æ»áT<´?ü6ídžªøÓm2n SÓ›KZãF³×ë
+¿òP,ÍÑÙ†ÀC–|F6æŽMo5·)O.ge' EU2Uß.®¬8eæ9о0ñ£òönF']·åÖ:.‹TŠœ1»/dBÙ(†Y°“:IŽÂ+š 0Ä•Ôä¬S³Ï0ÞúAÃ?#¾Ì%ñ†ÞBŒ!¦Þ + ©µöIUѦhmÛTQ®L`¬þ‰(§‚Îc.$óéë/]7aþ"lû<é
+ºÄ.Ý8£5õ™„pŽxáJz"yùQXß..‹½yD†º:ÅÞ(9^¦˜2;ˆkœ­‹>¢œžRì}óåÏD¤KøøNm¯¢­¦ ­Ñ)ç`¢9g¿ÙBìdß—!ñ1›˜Àn±šŒö(™ªÜ$›09û$Šé9bµ‹Ã¢LF–5Û`V¥ë8í%¦ý|Ãv§!´¬ÞŒ‹(uem½¸³µèû¨AT<ë‡ö.V.BºLï¶çŠÑ­_ñ5¢1å1^Ø|"G á!ÿ%UÑÎéÍB¨^w2ûtìR<µó‚ðÁ©.fcŸ èú‘"ïÈ%³!Ü„.´ª8SJèõì-N¢*U1ßç§ %øŒ£ñªHÚ‡2û1|4V ¹[d^¥UA‚öü^4YcåÇf‘;F14%ÞâtÅðÃ&ãå« ‘Ø K# 2 vŠ?63þ?ÇnblI=“††Aj,¦æ×*KzavCîÎ3ja*û¹9xPýzâ‹k¤¼Êr> ø¿ª|Ù§ßFW?ôp›(Ø&ojf»`éÄOR+!ƒ(4I#ˆ‚Îö8dQQbãLSÙŠƒ‡Ò•]5¤EÔT²iˤ5ý N—0#V Ký„GÒÊ¡<7öQ7DŸ;§Q0Õ’0 pße4[-{Ñ¿´à
+W™úOÿ©e•WGoâN›ƒXS·“ ^½¸:%y"•ƒåß#Ñ
+ôÒzñæÛ’Wwí&(PeÓŒìeV´+ÏøñÃf=ue,»ˆ­ÛH;L¡(–}§p]©Mý˜Oe IŽLºÑ"7¦xj^‹õŽùÞ8þ@ÿÜÑY,ì´—‰æ·bÞv„¿CÇ‹êîÈ„6U^êöij¢ñå·ø,1]Ò‡æîwŒ¬¦+Åä5–Õ„^붗4\5ù¥Pέüð™¡ØSŽ“tþÌÔOðFëê”
+}@1¶ßKcy.ÖÕ!AnÓš¥ ~T ”Ùú^„(³„FŸÎ›³T¤Ô˾€üp¨nd ·Ò¶ÖíÏé-®àp#{ÝZ/‚6±š—xsÊg·ÃÞA™Z
+§á DŸ)=·Oc& ÔR‡öš=œEU­‰MÍ ˜É1ZЭ ’ø}Ü_dm½eõ¡”–Œ;ˆÇOö’™«õí¡_Àssàz¼L0jOÖ¾„€žál;êYGµkÏ)Ëm¿ø I‰¹\9Â!Mœ²2S™’»4Ùe¿.W]b€mÓÁ â*_ªþ¦Z
+SÉ3Ìï_§£†Â,´2C¶£°Áx- ƆDÙ7y&ãöÄ
+ ”(£´(ÑÈw¯âA±¹O°ÍÑϨMrVðiw³²œ^‘û4å1WØ ð¡›8¹æ²r‹«mÔ
+Û<lî©wyað¾O˜ûäqÛ85E¥='ÃÝ—ÌÛ£;·Ãaæ¸s+õ—»éÄ·½?Fé2¤Øt E²úÖÀfóR®N:›D‹Ìà¡ãWˆÏVÑŸ¸p/óüzÛ*WfOŸ·Áyu›wDi¬Q¬¼#)Ó3’ƶ£
+ÊŒH`XÝ0^Â킶˜{Z»I‚BWœ«C8‡àJ¸óèTäÄ0|ÖÍH’±ªòשÊï‚0³ìhÆìN·¹7dÇŠO8E×·fP˜Ôµ ƒtf[Þ;w†$©‰dë†0R6u”=•_ÂeÜ6Ò–&êêN~T+@Í„ø`OùºÝðÜNÖ#)|6è.œ¼°ÍN®ÃÌ…¶¡ær9Q¿4£ÓÛ`òdœÜ•sÅùB;1`0"ñŠnå½ãJä Z}i lWÛ);ÆxÏ/—ܺa ž wð rø_û(ÞÆ÷ߦZ¤l<qäà¡MŠÃaw¼ÕëA*¯ƒòw[ÀÏF•ÃÈçp¦oáCó2ó{È™9’­ìt.Ú¯Ê(á‡åë2+7ö÷»‡.äŽÇÌ—4еå¤, 2x%e:-C@ãÒX–b">ÆD£ïßI×â›ÓR /P†Ûªsò ï„eë1¢êH>çVPU7ÞѸ_GÅd ´3ĉïAXñ"¦ä8TP£¬­H·ÊÑI¹±Òwm€©±'êÁæ{x"rá‹íp!ÚŽ*Ýbœóá”/*Ô:¯Ì§$j1ár[žŠ§Î;æW`þþ9jä8*×ÑdhŒ{Ñ3ïu|i’xÙõnÌ’ 䧓<9hæåÆ0VȾö˜$¸I:œ˜ÑçóA#þàb…,É®ÌhYüš"~!úkñPEˆ#“8TۧŚe}?ÖøÝgXDÓªú37êáÂ"ŽÀµ£9#çÙ’4>•É¯µêÃbeâ`ˆýÔÑ}^ô42JdLlL‡V¢ËŒH€¡Åè3#’¼F
+Ìm‚@½õî#ªÆ ¨¼»¥ß®ú‡òý ©ž}^ÔSȧ•3^ S×Е±¬ñ`ãE$ ÊdÂœû<^D¤ñ€¬qfÛÆ‹Hd–”‘kˆ.0î’=͆Œ»ÈkÀˆ}óð¸ß³×_¡Q'‡f²^v¿ƒÆ­‘whÔ5$²­‘³Á‡Æë­{Τö¢`¬IHúΤF§³¹¥æ2#’bÿÅÊ3"jUÞZøŸ‘ð)þ5¥€›¥t‡Œžh£AÏ,‰6dÜE2Êßh¨Äu”pÍ+2"d
+H‰Œ—A²9„OÀÞæË’lyM/¹ÅDÌ
+î¿Oeš¿\𺃎~¸l)3•j2j/µýøŽúâ¡£—¢R<^ÝJ)á­Æ‚x4#Š¸Ç„Äè"Âo׉*=¬™†÷ÿ~4^¥Õ¦ê ÒWñ6Ú°hôqAøDçônuLˆtó&£t-6!îC‡µZÌüT+/©Ö;¯"Çs€ïV.)ûὩåßâó± V¢Kõf‰×°¢TB ȯ_Ž +&­U.ùñýŒánæbÕÚü’RÝR(é¸Þ]¸ŒioÜX¬OÿëÔfônâœ1¤wjûÝEÕ«ËpþÖªÑ,\\{Y%iUbh¯uB¤ :\º¬
+MÒ±qG¬^Ö>W þpÊ[·ïW¹±æð¤;ûn¥’?ü‹Ã·Ÿ ¿õi}êJžGWçòñíËÿ¾”&î7N/ÍýpÞ#¨¼’½yp-™÷‡Èͼ—˜ã7n÷U%«© X·JM!‚÷¼Õ®Ì)b# ãÕ»7
+Em½®†„xQ¤V¤(Y”zêü;ds¬¨UíÒÝŽç$“íÜr ß·A{j6LD³AÛ(*UŠPB}i 6îß‹îâät„eq†+0ÓV‰£*®>l#U5˜©cuJGÔÑZˆ´©âè·Î?‚*'µÒ£xÇ-糆Á-é`ˇðþàÞKéÉ1Ã7«Út¦ª¸SÓÚu?\ƒCªÑäe_Þz¥+Ë›ŠåÄÔ– vEúœ[&ã>ùoÄvä)jëü:ž¯ªA4n;uÎMàžS¹¤Òâ§ÁMÌ«mÞ‹ŒFM7=†4ƒ]f]RåX±hmkÊ”tc.b­¯ê¢TÜ ÒRÂMt£&=ð™±ßô7e¦ˆ1x…kÚ¶:œáõtY¦€Õ2zM2/—+XOW&W½hH›6è"u,ÑtŠ@øǯé«a‚ ~Õ³ô,‰ÜžÂ‚¢(z²àéxæƒßj×}0£¡§{~ÕÐQ/¼súµ„7RcŒÊ¾'µ¿8LТ§c´âÃô°/Ó¨ÂÈ“UŸÞÔ^ÈÇ,j˜ûùœþÊ”Á¹ònBs“•9¡ Ò/ÕçÜ[FËÌvF”ë¥ñ;ˆ®xþ9 AŒë>®‚%ëŸá V/’œáûS.V(Ä!ˆØ,aÑ.™'ÖÃøHÚ‰Tõ1!Ú†æÐ,{ž+½uï$‘»†Œ¬ôÙ£¸¶"é ©ýÕŠÑ­+îzhúÕÐàñDæÃxæE£5(¿ºùÓ9†6Ü2Óã¼Mg wô`3øõ(γÛÁÖR° Ñß!èÜzÁÙyü<G™©*tN@°¬£^ŸBaXã*LbÜ@§ž#>Éý„V|1.wÍ 4yqƒðø´Fä™U/H ¼½ m?Y_•f”Ú¶tïF]Zlj=׫5#™²iAxdþíz áþd^ÂW¬Ë¤Mz–Ë¡Û×/'Щ6Ø9ó~ÄtóO‚Þ]ùûg¬ûrøÓxӗêì„ùï˜úcbH#GS’5Ü9r¾¿3Ti½^mBºjm½¯®Zz¬mêG†[&S¬Ö·kJb>Ïá Ž<²‹¯9UgG€X¦fƒªLŽ7„ˆHd6D®ì1îš&oogH4G Ü\“-mT‰¹®ê±AÂA¹Nñ²ƒÖIr›Š¹Òá†A]ÈÉc¸­ò‘ñh=9ƒy7ÙŠtu2Y®.éø)WÑ©eNNã :ßÏ+Ç_ºýõW|Ï€E q.¿Ÿ³]AŠ“ \*§ptu‹}ÀωâÙ,ÒgrcB˜cV´moAýâ¦9ñæÞaA[²EzY©‘@l™>®O±*e0¿J¶¶UBAý’êÒÄ…^}x\Ä8aœ†Wã²Pðût'!7&o;­í–þ¾µäÃ/xaÄíyò¾µÜ¸|ßZ² ž‰…èýÞÛ~ Œ»3s˜"§Õæ¢;jÖ¬RX·ñ–Á«>!ð³(S»íŒJŸxîÚŨ)GÔdn‹³­Ê«QîÈ‘·-….f"¦ º>•‘d‰Í>í-'ÐÛÆzvŒO 5BUC¤Óyï ŠŽxæ’×_šÈM´š^2}SV¿Ì£d^Óe/I~­Ì<ÛÔˆ¸ Xô¥PtÃÄz̶Kã¿-}â­92”.ëÉeŒÐP›ø²˜Á
+Z°«f>žÎé Ül³o»<™lg,(˵к$Ã:…¨Âôç±w“ÜVYWÑHÌä“B‡×Ô“²HXÓežŽº–LR8c‚Ó­œIH‰åbvìH¿Ò¡¶ÚÚɸÉ4/Ûs”svÞð¯¾w;ø—û-ö¼<ON¢Ö(Ÿü»“~½¶-ü"'M¦.©Ë j&Ø ·øʼn!ª?-SêNŽ¸Je;€ùÓv„qÄ|á[?£.ÿõ+ë.£Ìâ5ö$ßáò7ÈE®Ž°vZ¶9½ŸÓ_¹p°åbç{ 3ÊÉŽ$›ˆëM5CÇúR’ˆ—Sû1'ñtH=Æ”ì‚ÿ^ŸòÓ tO=ósI%ˆÌ{þ
+‘óy”.ø'¹QY8œéP°ó±EžK}aæ^v‹ß²ƒÁ-ÛáàzÐ YðHRm >Ç AƆ+ô‡ (?çÜ¢ö§´¦ÄP³ÀYj}ü\ð{’–N™N‘îûgJð+³¨ç[Í«½þ8‚PUÏQÉñ¥¤Î‚ÙÜð³=2®i¬lópi“mU’°dDŸiëÿŒ—;R¬7…WÀnì`JïGè"%õ
+\Î ôþý©wæï1TAD£_ê>}i9Yt
+RxK«û.»Èioýe‡r»ų1c:Ið²‹1WËèž2zhø<ÊÉ¥DCh»¶xA%SNŽ „#ƒ(†õÉ{A¼"L³x
+½'*¼?)â^2½à¯ò@6‘Ë_ã·Õû¾KðBÌ…ׂñgY2ÎÃù<Ìœ¢Ä. ¡±¯µ§$µ!3Fpˆžûa
+,F,QÞWØ0{†*H·ã«Ë)ã¾^åïIø][ã ý±ÁNÉÝ þþÉƼ}ú¾\àé®ð)rÎûp‹0@@TH†m«Kå&o*Γa%ı ‰Ôšž8 ]ëÒ䆻ï€4</'CׇïËeòžÆS:Ä\=›´áŒÆÊó–¥ë6¬_.½ŒE*ý&õlÅÁ jä÷ˆû;
+¦d3qp3ˆä"Ewkú ÝC›ÿéò 8‚r*2‡}ë c¼¢»¹¿»EX ÞØ-/™ÓQÙ„Ø ¢‹¤îÝvNˆµÁÆdÓJ’Þ€žØž` V6"ÖhZXÉSªã¦Ò±18‰x\½žz4ù{Å!äÒ§¬„å©Ë) 
+/uÅnž¥EÄ[dð˜ä:XŠ‚™š+Ž6{ ‡ýØ­aqJjßÅÅd†–÷1E~VfÓ­»ì‰¦ÓÙƒËÊ‘$è,|6Ï›¾ÛË¥¸ÎDg¹Ñ ¿Kí‡ÕÐ\‹ún&Þé£â²ÚεɱÒA|K7¤³Ê+öee3ØÍÌÚýuíü\ñÙÚÁm²¿øƒäÑn26š¸K`VeÎïu—¹,8FIì%]ä)ý(5™ \ó5º8ýs’´{Ð ¸©ø·a‚X&Š {|³>%ü§´1°OÎÁPñ"œ$ÜvæÐjÞ¼v£‡®¡
+ö)庌ßJÎØW ‘,*ÌŸ!C± ·FÊaÕüsd“š–"•içàŒ1µìDÙÖ êUÀK¦¬:Ìþ Bú C”cw:Ì‚…Öã÷1²lƒ¸Usò%ò
+J&¯sN¬ ò[,å\‹¼™åX’Ù
+»>íz{oþ‚…ŒºƒEœ
+ÅêËœS÷Ô/EA –wyüCnÑËy7Ó„sNŒ|Ì-`¾Æ ! c®Nxá2uÏi
+&"Ài»ˆ¨Û“œ°!­ V…´„‚ž>7ŵú¤äŠ´Ç"Çe1•´”²èÆRJ iMpšÍÂèŠÍØþΧÒJx\`s+aˆL(—ÛJ:”¾´”sûaYPºÐZà׌‡Ò+TÇœ,š‚ƒºÀŠº3&ëP=‰®CKuŠšÞž]ÀÃ…üB€}8Eï?À¼¶ã¿X?ÿyùãßMÌ .²¢½b¤ˆÁµ)qt9¤ |ÅóÚ»¢·'EŠuÈ2Ñ–qwŠ”;©¡¥EØTÂÆ3ˆFÈÎ×¥I „š‚Úœ›âIéQ¢©9¯¢„Y¥·cd/*Aw ñŸTÊBà]‚½JàL;{œû]‰}ªH”JB¤Û³s”5ºœÉÉjœŠ (°ò·J$à}Â7N¢µOE¸¶ô†Æ™ˆ„Bæì ÏûÔ’«°ÆóàÄÈUò¹Ìÿý3¨?†"­òtóȺx€ÝÙûzâÆ$ÇQo}¹–3›ø³¢ATÂËê.!YVîk BðŒ|×ëëcô_knEßR½ßçàf*7Â>'q0Æï[Ÿn ÎsD"aG îõÅ/ª=qÔ2‘cÃùRœ1W‰ñ°å} 
+©ƒò4=¹^O‡`±A€ú¤Ã‡D²ZˆÅX]'ÜE’… :ƒIL© /K,8Ë!&ö#ÉZR¬Ð…"“¶1@óÀe¤¸ÊÀRl‰ŽÊÜÑÌ „*·+ö)2IÈœªõ=›ƒÜ²;µ²A¿VI?°²#Û’ÞZ±îà«[Éê)¿q8éñõÅ+J7yž¨LT6‰±}…:0å½[ÑL-ÈÛƒXV&…F±n£¨ìWLå3qðlèkQ+IÚcþí¸jQ:0IÔ³írðøÁж %1VTbÑغk0ôˆÛeÆ:¨1<Í „\1¯9%gèò§léÝ?ëMûäÆ{:1ŠQ²ÕŒ}C¹‹²Xt:¯Z“`GiÇ„pÀV@èŸÉ2äÃx=B1ë$54-Æ.â8Š”ißê4=J‡§Q~…éÜf5”Ji´j'#U¾@+ ‹³X)h‡ÔÖS:Ú*ÁÁô`ìá!ÊÒg¿§É•9p_øŠP!ó‘§Ù;˜+H¥3Û³ÙôR4— NƒµMl1C-е‹ŽŸ=ÊÒ›÷¹ŸAªìy‹íâ™STeà“ìyZm¢¤@ð|À,
+
+E„E Ù»LÉœqpÅÔeùX÷ÑŽàb_ \ÔçÁ<ÌÇÌ  jǤ¹\Ç*ŸÐ*|į¼K2¯íÐMŽÙ)±/Aðü}–±•Ë;ÂÕZ´ˆ©"3Y‰ÐƒÕé19~}ñŠ
+A`F–Š?ÔvM ¨”ßd ÆY=Y@pL}Ե뚊Êd6w¯„"T"to«ÖËêûàyµRé8ýcÜ:;Fó^«7HV Ic.7„çäÂQëmÞò\Q¹h}©½³_5à%=B.™ëÊ!ùw!väåörÍýéM¤ \*ÓBo<ÐjhB­&ëP² âÕd=XÏAyÇxya¢½iíø”W¥GÜ:ù±ï“xh”Ù<ê  ¸Ù ”èòž‹už,´ŸöÄ*”h—¬êQ?ö‘¤ú4Anf|L>É :´“×O¬†‘©™MYÄÜ#—Å
+¦‘E³W‘Õ ‘a8åpXš&â{,¹wÆ÷†ú·Äñ½úƒe¹aWU+»6ˆœ4ó Y5bŸŠä„R¤ìÔabøWLXús›‰w(!a›ÞV+O|,®
+!ž> Ñ¿4­X¨Š.ÌEÜg†ƒ“#ìIu¢q§0üpH9cQÙé4ôCƒ6Zˆ”Ëf”%dˆùÓ稒˜ÆpÖJ‘#<_†Ñ•Ü´ÊD6«“Æ×’²Kn Èï+SÁ8 …ºt–œAÄú ìã"R0A¤´HŽ°-ÎÄ:6†ÑšG>„­RБ䘆v?V£@`è;M#VŽà˜€~ÿæ`?ÒºªÊÃ=9›èîGÖ×È]8+:ÿÔÈ’…‹†äP¥ˆ+s :xRÓ…*hY‡zä&ÊÕ f…ЀÕö@•€X<m0áÉÏ®@¤çr”9Ÿs’|qƒ fÜ^©Ù€ ¤EâÙÈÒ¤ó©ßÎ<Ý_ÿAµÿõßoýï[Äzˆºh{çg‰Øp6Û´'ÎűÒ$ìFXÛåÎBß…
+N€ ëHUa®GT»gw ö)”ZËÇHǧsž*„‚ÆÓm`7\ãòó«ÔÙŠœ¦“ÃîÅ! ŒÐ‘8žJ|ƒ|jÕùÔ„YJmT²$Æ¿ Ðe´3ãáUZ9Ø#µž^¯ºT‡­n¼Va¬íÊ—CzhÿQ”Ý^] ö©KϽs.“ãÝæ:€Þ£ns|/Îmî%þýV-¶Oq XìoàÑFYâÃÃ8+Õµ|º‡øM"J÷)O ŽmaRšG¼Xdï¥x««K‰_BJÄ%ëN…@‚HuÃ0ð$.]½-±ÀÐÊÜ¡ß ÏTÜž)e‚Ó†@÷=d%«°¸Š/c£xê;·ŽÕ÷¨…˜´!‡$ˆÄ€Òá6B ¸”ª\´EN
+§3vS/ûRÆÕÐXh:>Ñ2.Ñœ³ \»c”«±!Ø„Ùqm{L Êe !NoÉ¡*’:N¦6”p7‚%`ÈlØC¨kÀø‡çîFð2Â6)Ó ´ Ëò‘…ÒLE¢FȜʳÑ*ØpVØ1Ì©õûSH³IîÕêƒMUj᯺AL<>TQ5Ú9ZÀεcˆ6;ò¥ô/Ð6d*‹iwŠ½Jhöš¤Ó­>cM3!4FЕé»Ä·ïú4Ì»‚j–Çyšf¿>YÁ›ø¯,ؽ‡ *Ú jÍR™ÝÄoV[ÃOñ ø£š²’Ôè¡f¤¤…À9MfŠ¡?§4þ®…—¥¶!‰¿ða”:ÕÊëÕÓ\ÊÓ9•¡ÂÏ ±„DóÉC1— !ÉFIÿ<‡ µ!Cñý›ƒ¹Û²YîFF¡‚ý°æŸAnÃøZàc”­·Ç®Þ¯ý)~l $ÄØ%/W
+²¢B½Hó“åZ½à»ü€ äçî:ìHºÒ¸zþnCµ ɳn÷ùr¬Û‡pêÛ¿…ŒÜ¼EãÏöåÒ±!®’¿ýå‚H:h¦bLgµÞ6òOÂ=aw "¶ê2ˆJ‹ÆÒŒ¢zW»9ñˆ¶Æ)R1µ£3:yˆƒÞ†b;Ê—ƒÄȲð`(BòLUËÇ+|‚¬Oq2wšðÏAj5cxø×Îwä *— ƒP(ÄR[¶ ¨DVa}¾óA+Dz¿R†=ŠˆCô  ´ý±Äºd9Šn;¯iíâå¸Ì¨˜E†eCh ÿ»ÃË8
+«²´TÈü$:†›FÉ ]Bö ò¥3+°(ø4ŒHÀm9H¼AŠE0zE£ ìC)ejÇdÆüpÊ¥á÷«ÜÇ{Òm
+L—J/?VɈs²iÚö0Øø.],^BÄí ‘[°±AüO׬ÛÁ˲(›oaÄ‹Ñ}¦6lh0ßÓ+È Ëy±HV¾yCÞ îRâsMI¸Æ÷´§cÐ|îÌíâ.ÉÁ–¹Œøqƒ®Kß
+­e!Ïät¢ÞU˜2kEýK˳M´6û—€P%ð'L;‡
+p/àO±k¨Ù|(¹,èߊ›>ˆ  ÉŒGÄ\kNл}ì{E:8âêZäÔBÄeW
+P)ÁËÀÜV ZE$‘.•`±F»Ö…½—îSB@d¡jò£•Hn«²•L~ÜøÏóÁR”$Y
+ÓÃRÀn0\üDëV‚ð$¥ËÙO%þ©2aÎ;âÝÏ…
+ÇÓmP i-æyx0ã©;’¢LHŸz|+y›ÕþÔµ./Ë’ö9×Û”+ÁF|xS¦OHži¾ÚwëMê¸jD2Í\î¦ÂðÁe'u)ñO]&~:ç¶7÷ÛÜöïôªÛ NPïôîÜÐPñü–¤=?”¼MêïøÐx:Ì>äíàK„Ó,#7ú¡èç©èÈ×Ï]‹>¿s'çÊv¦2ßÛ$µRG¥ˆ¤êW?á1Är®¹U$ƒq@•ÝòB"@0YT-)VRácÜíhÃÍ–¤=£
+I¢÷Ë>%VÇ@oÑŠ@1ÛÉÊòÖ”0%ô?Ó&«­ µ2ès©SÁÖÅYe!Ë“g£¨-§AV^Ô%EèY¨Û9¤ÞÉ°KênÐFoŽ2– ¡ËKÏnÓšP‰™ZÝ
+쾑kn±²Z#.¿.œ¹02ND-ÑK¤·YÄÑ{÷>ÊÒWZj%­‡'~â[ŸEG†H±½2iÐB5<¹Ÿ#7¤æh;2UD¨”eiN]71¥ôúÒµHú÷€žæôG‚ÖPMö´j¹› ˆwmÄÇ—Fü°M¦#ü‡Kßýãç¨-ƽxŽ¾Ñ‚fôsXvM  Ó![ƒÁ§Yùê!ejûT|½ŸÓª°Pá\œYömôw²¿j%Š!FÜ¿¿J­CÃ#›cŸj,k\ὺ»Rx@N²«$c•&P˜¯ã=º:Ñ ‡’ÁTpj`oFs>`“˜ƒÎáÛ¡èó¡<ƒ{–‡k:Æ™BÁ %£î3ðœº5Ûã;Œ—,V"kWpbSþew9ˆ*bÅψ€óœÞe´fô
+ ÌÝœÈ`f=žÆy©ðÅ
+w³ãbûñ”Âìäæ²DÜoÂðÎÅv.iô¨ã[kØ/J4†ÀõÏý%
+•Î¶>Ñk-ŠCB/P_×XV à™RÐp0+²†¯G!²zR­&b©‹
+qz²LÉáÓÌöÁüái¥GF3ó¥™}$ÀX«;;&á‚ù¶æ”t‘Õ[¢P,90`¯òC.,Kþª‚W/ÇSàj¶GˆIü*ÌV΀Ew ,䲫X +É,¬û‹ˆ%/Cþ;ùm
+-ýþ2/•?÷ﱈ~°~|9oÞ¡@ƒäÐøºm’®è¾w(”.Η±´—ä
+ýäøºø9'€ ·âR<Ø‘°—|˽ÃîõÁÐ_g~ ´¤Óô¦ÌQÎç°ÈP)UJÛ·xç`ú»{Ͻ9 ®$:;!,³Ì=_,+YÙ.–ÉSì‰ý±¿L?»ˆI©³ìŠ†k¨
+n—䔓ˆ=Ù¾½ÍýóX„<2·.ņ)ícìÒ_ú±…˜€»¹·c\n™Ð ½s£ƒ„š¿ž÷ÓbÄôYQm«“$QÃF…Uç+£§q´’¼™V¢K`3½oÇSX+Ò
+$Y^",ÛSé\ ÙX
+MœKÑÆôÆž1n>Ñq„alÖöç:´¤jQå“m™-W›¶NYÅêõúTÿðàýèöAú›êƒZö«R95(1¿GëUÍô^ØÊÔtVCÍx.žXì0 zcLU!ЈlGrh3·K¼Zñ«í÷ÄV„´çÙI¦Fö!ê”°wÈƺ|‰ií
+!µ-üŸƒV1f\0Ø=zM{ë|ŸWÐ+ 90Î'vó’·aê\ &»å•oj=ñ ›/jHû xBÍzƒ^Ÿýª†l™ÈŠLDïÖÙŠ×ÌÇižÔéð_“Æz«†N/“ÜÒ¤¦†½T4-´ö“K³ZmæPî¨ÞÐDߊTq©îˆOÕô¤†wÍøˆ È+†¿Ý½^@D)}£.:¾÷vÎUy´éA4)$mlu¹d!¯­4VLoäs‰7lA‰§Ð¼T=âã$O—ÂÍo™êHeå2isøÇäˆ3µwaµá2L™ÒÎõn•kh ȱW"P1øm×¢"ôW:‹týsžõ­4Mb‚<×£Ó1ÖÌFÝøÞ åÌs˜žçÅ™d‘Жî$ü%ë;/¤Zx 'Š O8âÕ–¿fÿ8ÉÅ¥y\¾àŸfCäÙ5õ`£¤c_5ð”Tš{¡¤§e¶®D7†ƒ]i/ÓÛ‚@Лx_aàeFAf,É—„tò.·2ø›‰†PwÎmymDMëÈyd•¹5¿DÙ©ÃÑ£$æ] ê8d:]ªQw=Œ51ÕäêCŒ³—x)O ”˜öÛÖ|˜fW7¢Ö4_]Ch&a Ðiþórî„?i2%ž¸÷sÿ… w>=AbÈws&Èå÷Ç"
+鈪D*~’T^9àU±þýNšyUê.Š­CùË:pƒ;¡Ây¶ÈÄè-‹yY>SLä„E«æ¸Øê·<TxüóßßdU|/3R©4|%~äæ•3¦?þþFó!$y{6!ÛÐh*vRÓ‰ÔR´­Κì óýÃHCnAˆ ‰óºÙ èó+'²õ_ÿýöçÿ¸%ÉíÜk"6Ý~x´^_ýû÷7º]è‰Îýż–=΢…gZåÜó
+ÂßT=ºìP˜ĘïH•ã«1bà3m7ÐËf_š #Étùv(¥m×ðR¿ z*ÀçWªô˜Lð5ºr«•X°Š! 0“R¤n¥ßÙŽa§e}$AôƵÓp©©‹®ÛÑ'êJ馷…ˆÐê
+a*·%A”n'4™ú0îµèþ!ŽãƸÒö˜yžMò’W’70ÙïDd”kU&¾;e©»4cú2â0Bè~àÔÅbÅV_grË^HX£C`ya˜
+|‚0¨ M3 õ?[õ ƒ‹º#3yˆM`7B7t`!d60Iï%éòÔšÑÆÔ@Pñ6Î(‰'QâÖ)átv<>߀Ž+iA;þq U;¶íׂ$ žx³ŽAÎì$E­~s½¦5†•XãWÖ2ÙëÇz£ò h±­r“úðèþ
+ìÂó#z}„‡æ+$âä Ž•‰+CùË·Êt]!Í-?oç^¬Ìót߉ø£Þ†}¾ d]òõ^â1{
+G+=¸×7îG¢Æ’ƒ6‹AõåÉ}§Æ×iw¨ˆ&ˆÓ¡©r¾í–ßwÝc>¼@'2’a‰U´ôÕ!¶f½Ú/ ã;üç:ša B²ÞŠ„°|;Å…<{:A÷@ -„Ëu™§œŒ§•l ¼š$ßÎæTÕUº›!Á ¹2݉ )¶Ri—zÖ<Ø{Ñ0°<vÂì8"oôÁ›HBëÙö¾!;Âd"Eac’1¡‚²9äp–;nCˆýYo¼v‰ |"M™` ÖEF¡¬GíËjƒÅŸd ¦¡Üê!IÈx!pÜã³­. ñšZNŠæ'V<–^ÕäýIÝ”ºWÛ-.U¸yÃm—‹×y•Â^6LS`ÍÔjôipž¸Ul²‹ÒÃi¨ÂÑWóŽ®sÑ9|<M.|ÞrlÅ6¸$þ2]ÚQy +)ª­#]<óWZf“ñ ©9C%›Áj%·[]š!“3§ýGȘDjTÙA 1P:Ñ[þ£6\+e'Õ9Ú§RYq˜_ ¾“DºQQ¢æ}ÅW,ÿbhs2Pám)!pd:Ê€4m
+Ós-å¢êÅÙ»ôjרŸt•i;û:PÒ[â0?åIãûað>£§—Ë…ð iº|péæÒP™´ïBY¬YÎQÚJF^b (²ê×c=æ^܈à[)nà=sv¦ÃÒ
+) À!$LT–í°aƒTì$‘†W\|BµEÌlyߪ-ÎV8Tñ[Á¢­úÑ’¾gËT˜
+ní¨ü+hJ·RëƒøNÜÿ4Ð:[§Zc +üº¦ó%; G!€!È>„)?àà%ÕäµD6 ®«ÅFY+áT?..•mL;u˜gº²<3]5
+%nQgΪÓwâô”›¹2ä°bÂ-†;3v¢Þh!ÍøXæiü”¦/¨ÖUœEg‹=_ ¾•ïÐ
+\ê«(y1ŒÒbò ø§9Ó_J䬓‹•È–¹—¸lȧ¢?ûlŘ=i8¼/rá„
+>°<.vN¼Æ.ÑÙàN0f†¤€TÐœœÓ«wäbÁôî¢Ò‰yp,šº—ᨄ$9؉ÑѪˆÉ¡ò.áõÈ¡ü9w§ÄvBÛCÆb½­£æÀTÛ‰Y83¨ú‚3¿Kñ ÓLúÊY¢[ûðøHïYÊé1´Jp+óìe¸µD˜†‰„PI{hØ¥äúl«Gl…çmS gÏÇiÚ
+_r¤Ûè^ŠŪaÛ•Þ/õhŽ¢ÙÚ‰Ó0Ç€·)c~F¤ýP!Ègà6œ
+ÛÞ”
+£æ㲊Z®ƒk߀=æ/j2ë|30œW|„ÁŽ1ã¯PÛo×Ê$0R, øàX¦Ž[EÇ&±(ïrëƒ)Š‰‰ž›ÍÂÑLéÖÖù>Ýme3n±FÃ% ´«‰è™L¦üìôkÀƒ<83§xûå–zEw˜Ä:.%ß §°6GÅÀ
+Pû-<ŽtŠðxQ4cí¾VIlƒ\ªÖÚ[DÑ#ššê–jJ(Pûëiâ7øÏÞŠ¡hmB”F©öíÄA &zo_Žo²¿1¶
+ÁÛ”>)5y„¢„u»T\z]Ì8ÝÖÄ—¼9ü mg¿¿‘¸úÈÀôþLñ¥aŒ‡×»ÿÜk;Í8g>hb õ-dåø‹âøÀv>ˆ)Éò(à3œ’OâwŠ¸3 Ï»™E¦Dĉ±™»dy5Xž†»UâÄbÊfB…õŒZý?;ÑNèÙŽ˜rð(0±þá€d#­`¶ÓÁ2 HîÈwÝ$:¬MÃ@–y^Š1QÓ£¹I&¾kÝ,#b 
+(¥¼œ`™¼yM-Ó?L~Ñ8 ‘”èz§Ìq„ꀽ~o ,4“´(zó;¬ó%†G£Y.ÅîÀ9s–6»ÿÞì]‘ž3æ⣆½#΋öÎToèӕ阱2};êò…ÿ§R´ÈϼD\LÑš“)ÿòj0n¤¼ÊÍa‚þõ˯‘uRä‚]ET -´40gòªîMšÍ«=* Û
+{öRAêï­Ž0Œæ¼ú.™H;&~Hü…„ŠOíåV2 „¸žÞœòQƒr¡É›žn;Š‘Ûè·’ŠsIJ+½Ge5;ºSdïÉ"uYï#
+ò
+rÖ›ÿeá'Â)ÁСÝlNo‘
+²­}WÐ6ÚDVtÑ÷sïÄû#-€iÞJ 5Kàm63Ýåh`{“íx å«’ýì4(¬D$°¶•T²Uª(¦y¡¨é…Õsq¸l‚0rŠ x@{{K¾â%QýyrÁþêóêÍ|©ß¨¶›ó1n9É{+ŠVga´Be; îËŽSÂ?ÁòM’h&NÇ9¬„þjÂùÃÅßmÅÏÌ#e3˜%¡Øä½^oEû
+D’tÃÝÛ‰áf Rãm5ÇŒ?:%5T+Ž ¶]‚¦\µιµm$ˆÈW×l“‰Îc©iq/#Aq•x”P¯¸"Òª¿4 tjõ¦ *aGÇÑNIÖ2¯Ýö:|Cð|‡´@Hƒva_Û)ØF’;°˜‡âàűtv"s6~ ÇM}*à´"Œ',"k$SåÜ’‡×üùÃ+òÜï ÝT©m|þ«"/Ã9Eϧ’@hšðþôC%5cð‰Xo!Ž¢Â“Vqú%ÄQ+(0–ÚüÇ0Lq¶?•[Œ£¨gØ/ŽSôˆq”0ce?ÆQ‚_15}·ÇüÊ2fê°ä#ÆQ"“/Sš<ƒ¼Ù„N æ3¥vóЬô¹ÎØá´éçVi»„-Õ6¬Çbþ$Ëo®}òÍ*Qò,£fÈ™h=
+,;y)aÒ⹎Ê<ŠX6™ù.Áxÿïøõ‡*\‰cN“þÚEòŽèvRá:”“‰ÉW
+kµ“">ñ!uÆâ3d¡4gR äˆ5W­0(JL²ÀÕÎê¡ë†©äù1çe£üCCç^» ^©™g™?M¡tj—:†q¦3¦ ƒ+‚(s¶âˆ&w8Gf“eÅB³+N¤‘x²éÃÃ)aúeû0ðì‚GU“qxðéýº)ò1”kǯ]‚¬rŠäÙ‰‡ìžÛè„•ÎË¿Zÿ†J™¥í{S¢¨‚­ÉXžnƒ5^‘Þ¯©Ô•ðŠµ¦±Kg
+,)žeƒÖp3:hJe
+àûŹW“ÑÂíeÐeb
+â+Ò™ÑHkSãz%:E{*ðÁü©¥=ÆJ^h…ÒFÍØ:&7yJð;´P9a4£‹})O2Í…£ ¿”c/†ÕŒâáGkOvš(½ ÿc¼L’ë¸ zßA'`
+õq(/ÃaëQ<>[ŠÎÆ,_½2Ÿ±è
+ ÌoZœJ‰8µF\X7ÙGë¤ ß(}"£ŽëÍúÊu ^E2u©vù`*$glÉò{È´hÖº’ßuÕ+÷Š¼ê Õ¿˜_€* ÁÄÉ
+k‹måë™ë;#ðfÄ€oíˆk„›»nÈ€%õ’¢$ošÑ³u—òE0’áJ·
+”•ùv`QH¥Ö#)J ÿYy|¦·Í’3ÍÚ®žHåÌ#ú9ü†œõzH|RKJbÁºE 4¶ÞƾJc•PÑš,"k«~ú×°ÔÈ'œëfð! ݽă%#¢øU•™ÕBñ„uN™ƒÃ¯¥©í Â5ù×ês.Fæ·ÐΔ ­[b+Y^ ÙÏ@F‰ ýµ&ßš%`$Þäó"ï(’¼Æ7 ææžiö ˜ÏyíÖÁ+bòdÉn?À%(¶»,
+Ç dÜCÜË
+¥BÇóØËK€Âï¥ÍYǃ+½™#ààŒŸ )ï)Gðš& ϳ÷›*Ч¸+ó óéŒSͦý5IÒå}Ž¤ÅÇèF¶·oêÓ*3'WØü³zƒR>ô6ïcä0³’LÌöÀÄìŽò’"ª3(-%ë„ú06ÒR 1—Œ=~H /h~+Ê›YÌ¥u
+¯ŒB©ë!Ê©”{ãHØ3–ù”÷~Ac`˜áÍ8æ·A§ë“Ï3hðÛ CW¸®Q`5•·A‡I¹óôùNŽ1Š8XÕꩳ1D71&5zy* tª¹}@Õ&™ù±17Ðéºô¡ÈÄÈš½ :ÕÜ «Ô1F¸§ô6èÔ˜[1Où[ÅWcâø@CØ fª·ý>‚h6É®d·yß ƒn(ÚqÜL‚ MË5u»CáÈ"À¼ JvÌe Ã "Ïô¢Bnf"j±£!X\ ,f•åîçV”\óÞ'„€È% Ò‚³\ñÑLÒ‚”0Ó
+æo\WὈ\Hg2ñ¦¢¦5þ[6€‡øW¹!³ atÈ ?t6ÿÞ*M@[³<¦ßÔªJ3ƒ£÷+et
+û‚yYç ‡O†H‡–N)²š¦ªžÆUW™Œ“Œ²\Ð8ž„ø‡Û!Øñc„ mH:o³‡G¢6ô)kÅ‚¬ÖÚðgWX$¶’Ðkþ1$Z*ˆl›?*3VJ°ϳ¯ÊòçÐB‰^œ4d¬Ç÷±ÎQÇY†Ç¿ñ`(^©W‡”(f \"‚mŠX–Ú¾Šþó)äJÿb|^µ¦¸¬c°
+š|ùX2ç2Ù±=@ÔôÆôÓâÞA/Û9é
+†‹ÜÁ÷2Wu’¡Vo»Š±4Q¹ª?Aþ”®=°‰Â×Øßó ôé îå%)•‡Ë‚úË/v??HÁuÞ_ÊÓӠמ /8@î ½ 8|Dh8nj"¡°µš_âal4<„Ô Qtø"/Å+IoÎù릌8úˆò…çSZB)J
+¬y:#È(Ù:¸šiÉ1X>€¼™…éƒ^x…s6<p[pšLŠš‘g^† C çì*ß„­­”‚@›Pg‹K9_FkIÕJK¥Ÿ“%µ ûë:„Ž²¨Ü7¿i2?×؈OÇD*á¥Ûì8`zø2ºÒLäŠ Ûß‹£c¦Åþ¨þ1"G÷Ù
+¹ª-H˜ñ¢ýYóòafP[ÒðñLIkþ(ª¢ °ºçX0•ÅdŨzß³7Â$ÿVë:¦ÐIœZîÉ©MÙ£”’ɸvŸ`,b+ó‘ò¾ªà¯˜k„Ú7Óòß×Ó:'c<¨ Åråd­y×àh‹o¦ìç?'ЋĜàM‡pœ?þ´0ªl’ú¸JYØjtƒAį8p¡úð‹Þã,%†b¢6üÌ¥˜†lXÓó¦ÑÛÕ¾;J@²}UßfYC¤¼5Ú:‡1+œÜyÔÁ„,…ç^ø5¬Œ_Uůè6_µrÿDåò:§±Ä^n?òŠ Œ”z˜7Å5±}þ'¼\’´ˆa|•9ÁTNœ¬¹÷_ó©ãô@ÿé¢`ƒè$¶,Éu³^õòŒHgCå’ãaèúxAØÜP¸ØOv­[‘¡"7î;}8: Ä\Gͼ3ÑçwΦ饈û6d>d—³€¼'Ã~gÁô
+ˆBzžõ£B2¿.\S¶èôªÆç‚´DÔãà´iÓ¸¼¨¿iÁÏ#ã÷­ÌƲ›èx®W$B&IŠ´Hd0‡5Œ4Ëôö !$ä”cÂxdQ›÷QÄIôÁßy‡]—…€—ñIöÛ×úD«ôŸWÌ+ Š 0Áï~€
+ zq¿™W¶ï‰ ¡$Áí¼æA³9ë‚à1mX}ŸDu°- +«Z'g´ÎÊͧ/ñC« 356ÿpGf•®HP_+³#=Ÿ¿£®Ð@wÖ*¤3h¤{ôa„ý%ã>5ÅQ䢡=‰nÞìŠQÙo΢ê$j*G”¯Kݦd×ã¨Æ¶TÉö¾ü«›ñ3¤¶ï£ZÁ™ñ*jiƒ ©xÂÔ_ºkGlßÒ5¾È›²ï“B
+'
+)ýãŠñ9†À&Uaÿ“õ_8@º
+ùAxa/y„1¾BBÊ%rÑÓÌp"1dáäÇ2:¦Iµ~n‰Àh/ôÀT²ÔP}ùŒ]\¢÷ ü¤1hd‘cåчÜ¥¸èô;L–'ÐNˆÓ! ShQcSgºRYŒV!Òàæv¶Xª§™ÑO÷Øà<ü• °ÇaCʬ¸þiÄW:ncwš—Zn-à"bŸusVc)²¸{l&ûIcP‘
+‘; endstream endobj 164 0 obj <</Filter[/FlateDecode]/Length 22487>>stream
+H‰Œ—K’œ7„O0w¨ LA
+Ák½ v"畲ŠöOašû` úЃH–g›c’K×h⃗\¾vg*­B]vª×[bÄ%É@sFS` áÙ ÌLëÐ…¢8 q‚”È•„ ‹Mö}AÑpycRÊ’ÓQs’¹mJç
+®ûsèìDµ!ÉëÌNµ^žúÒÚ€®N*÷ÊŒ2'ñõrZôIêçµ–êÄDŽv*ÈÄ †bœTß›‘qgbÔ¨*&¥žLx9"¥ŸLÍP4ª\ÇÉDÔTû’«¹NÍ-05ýdú§~MˆyG~%ÙðÙ©´F–ï=öˆ_Añ–S°&´—´ô06F‡á‹óniì®Tf©_ gï¾/Õ{öƒu«vR½¾ª³¬'ð›Ê)1I”õ;©ØùÄA õ´\a{ï·â[ç<T×°§&àˆn ¢¨¹2Ê%vv•–g÷ôëU/"­),9m¿J6šIIÛ†(ï¡`êÂÔ õÐo|0Yëß,õÞÛñsa|ÜpÆ`WL"²!¥yÐL•?8èOãâRÿÜú˜<Àüà9ï;<M2TÀp†ÌV”"1M!쓉¯5ö“l›øq­Øoüm“ÙŠÜMÙq²å%Y¨Iý
+ŒøcÐ-ÝÛó~ºY
+Lm{šÝúSÌÍd½7åæ÷ª={òøO" v§0Ëp‰Í¹ó§CƒPo»1Pº(ˆÇà˹¸.ôINê’gÏ Üm¯ãø`“Êò
+ŽKAG —ÐíýÄIܾ‹Á%`‰4\cÅÔ²BÈ€,HO–Òµ¸±Û¹ 8ÙË„àsä›7ª\(d‹íCÖ@’Ò‘“§¤Êâ[à©Ý3ÎÏè'ù<SøŠ}A2¥/úÂwâCsÜ’ÄdxKtâëvÂàÏ'ÊŒÃßÍ’ {ß#„oh>
+‰û.!Ýpk(@:½ d¥jæ™*%½}ˆƒ8S *œ ~¿äbù-=Û¹äø™¢Y /'Už2°zM›±AóFM‡;!BiFZœ±ã4ãwˆ ¡M÷õÃÖcv7•rOQo;ÒÍ—1&^w?á)/ ÔÕ†”øÊmÊèìN ó¸&Ìߪp¶›ieO׺3~Éî¬NOY™
+ý$r.ËX 2À:GŒUT·T¾&yAŒf§Ø nìŽÈɪ£.±Þ™Þ@¤Žœ‰ÖueËP©/O
+YûN….1g°[ :‘ÿ¡‘+L>>ÎÒÈB(EdÕ{êÄ„àsxÎ`fv"¸Ê iø©„0>Ø»²ß %Ž¼Ð™Qøæ™!ìÛ¦Sé’·²åMðYܘ˜ç ,{…*Ø5: Ì&šKæܤ0ĸÊfXƒÉ¤æ4= Rkl‘Jþ œ‹t>‡¾cótáYŠV–•çMˆû i×Cqlƒ³¯4EwE“ñœè¶âdZ¡˜\’‡¤å¦Õáò0zÛ&;¼C6ïäýÉ-‰Ûh⤿ödØr=ÙMöÈ]”‹è\ÚËËÞ¡4ƒ¾ëâ/@Å“ÊÑtßë'¹{cg#
+
+K=q¸îh½Û¤Ì(Âmø:t%Ó–kÌvüýª7ÛÍ” såNÊ/®üù¦|xÕ7Ðï«ÎûF‘°
+º§´%B⺃íÐâÔ¥«»¥)!\x^ÇÙ½N@cT²*»ëä!8L4–#bÅÒ©(hû«È¹Î³e©I=ñP_Û?+Ó«‚¼…A?:~½Ã’µžÁ`‰êÕ¥ð$§O8(;ùÝ?ÒÐÙúth°È~wM«Û“gÚÒÓdh‚²EĸàH𦠌Vƒ
+CevôNs5#ã~ù.AË0~á+
+¾³$½«ìNraÐ>¦¸q$Ñ4Vf ¢óªêÙ¥¶3Ávdv,vœT2v³ä÷M~“VÝB…±ÀôpáðC>@Þ¬í ¤,¸óˆ²ëýc0ãÊwP½>
+Ó߉À«ÛyRµçùøuçyz®Üݲ¢`£jÚMÆ}ì`†‰C¾¾ óØ¡ÙØ÷}éÿ/w$;‹
+¯`ö01ÁT¿!eBRV@AdBöÏw$õ5s§oAâ²Çš¿»¥£óà£Cˆþ·8ŠÁÁÃ.ËêEyÚx1N>þ‡ ÐÀ"ë`Ú.I¹¯:òÄܲŸÝ¶©‚V¬Å#­³M@ŽaOéIõ¢\ áGÉ
+¼¢ïJz”Èv‘ÖÑUœÌÀd k\J~W‡dO ù®/¾3Ìq³.Í—…’.Šèrià0ÏEs¢]ç¨ÉáCšïÞsEŠo8Ⱥ§»Ž%nîjÖ(Ñ¢d– ²Õ¯tô¥®Ï¨ßD5èÿRÉ“
+´`ä£d"P+su“g¦­€ÀÈ÷L«.Ÿ$PäE¤
+©!;ꬹaw°üøBØ¿ÊðÔ¦°û@¥>ÿ³*<}UÄ?5/R÷* H2@õE B°TäR§hƒ²ì
+B\€¥°ÅBÁçm¥‹8 «Šja|1=ç$ì4ͳ‹ƒ%R
+öèVòííÏ·üþ Ü^>ÆDé5 Ÿ£C¯a¾¾ßÿzQ„ÏÁë iJHŠöK“Ôក‡$  ä¸Ì;õXŠ=A¾<¤N¿û9^G¿ÚªQÄ5
+ø+Ó¾‚Á*ï
+ªâl„â[…Rý*eu;Pk|e¢Ýç¨"a‘Õ„; M-?c@ö¶£Ó{*V\y¸!!©‚•$%†EÓÏWžUf`ƒ¾en9¢ÄR 3¾%ŸùÃì·æ-9Jð9“еÆ*(ôŒzƒ¸LjÛd¤·š/áÂî ¾’¦†•dt ]!­tùÂ*‰É™r”TEOŸ}IH/æal9ÖÁ™Ïvæ)ÂBkàØìE&ÞHZÆû¿ß¡Ué”»ôö¢äD…f=¾ÕB¿˜W=R¡° tQ’!Y´«Í†Bó
+j¦ !Ïá-›{@IŠd:J ^9vL±Ï"à ö!à€Öãwp¢1ö4úÆÞ…T°~“ßT³ÏØ$DÄ0¯@§!îSl­Â¥‘Æl§dà—È*yOÇ2EÐ[Øœ%¾ šƒ°ïÈ£°nYè<VpBYæy–— åJd=œª•ÕÁ*Ÿ±ã(²V× ±•GÚþm⬤5¬;ŽÃ`_q¦²oùEIV·hú&º£¾ɨ€K.Øý;x~k*L…Dr‹”ØGMÆJ¸—†Òz‘h`}Ðæ|Ò
+94¥"Y÷A@uL’ÃG8l<~‡o5k Æ‰Â{ôyI+0’5–CR‚­®¢üJ¼ÚÇ[ᮈ9p˜ýd
+ ‚˜¹,ÿÏÏgÊŽ£–+qÇá,Æo#7h™†h%¼‹Ó=Ä Åž€#èä<?ÿOGOp¦ã9òECqËK2ª: Ñ¡@idØ9©ÊÇ…A¸˜bŽâ6%m æíE•WcGhlòïÀ^‰ý/ÚÌ(iЕ֥ŸÕ„’Ž$r~\_HV-ó~Ö–ŸFÃÇÿ,ªS•ýb &^Yý°Ä£m"®ƒ›DMM“E™|\_§Cbµdi.¨Î.]9{±²N
+x©ùÕr|*Ê…=§ûËOB
+B
+FÕè1ÖÂÃò,áC‘UЄ¢0¤<ÌYGo SWW¹*$%ŠxtlqÅ£%à
+„æ É¢èDz¨þg™ D°[ǾS±Â2ÂBãظ"悪%PιÙÿ wö3ð¡‘ÍX)ˆq§ÌðöW›÷uãžìâ·ëZöF´•a[¬eS2ÓÂå<.EV‚·§·´h?¾ƒ”ÀÃ:~å‰0ö*š/QBÿ¥•ŠPþì
+ébŽÆÉkªAãŒÉ—ý3ìàTAm§$w‘ß\ÜÆKØiä»6ò¥$:L?afBƒ½H]é2 }¸fËK
+Á>J8”XÈæõ»×éêCî¡›Ã5O«@QQ"O¦à
+ѸԠG˜ƒÍ5ÐÄ'N0ãï5ù‘c $=*¡O!\ˆBÌŠ¥"@Áɼöêl)½øÈéù…³mX.®yŒÐ= JB£ÇI…ÿ®Q~ygÓóÞ/*”OªÜI]_+|?Íœ`kWúËWn@]Ü´NB$…ùÀ£—ˆ ŠÜå„RÉ)!}9°Åu +Úê9 ©Tôâ Ó÷§úªÖ(äœ-P;ûû}–›‰p#îánTûhµ°y=J¤Ñ²áЧoƒ¶åÞEc£7KÕ«/ mÃa§RMü¥lá
+s¶3„W6ª*\àÖÅB ¬®°JEà`©33OÉÆÔN‚÷l4Ë6îsRY­
+4ªóš1áŸ&/iJô5Üvž&Ÿ&ù•u-ÁöêI[4ðùçÛO¿½¥÷Ÿÿxûéï·üþËûÔè Yç™L òÒ®Â.píï©Hû ½` PûK‘•0î ÁV‹—ðⱸ Í(^:¶v|™ŸÎ›³IF¼›µ—U³"…NqÊ2Ò¤ãNÓ‘fr®¯Ì¹}z”tùÚž«À%âHÖ§S²ea% ²è…=}²Þü¼:k>ýú¢h‰úñÚ 'ëEœÅùëEv±åeV<%`&g‘âÒP‹àDÌ(éjÙä!mõ‡› Kÿ0^&ÉqÜ@=îÀ00ky©[pKÞë÷‘‰–X’:ÂrXô'
+ÈáŒTëVŸò^4OÌ—uYuÆ»Á¦]æßÎažøŒ(fœ»õ¯®kVÂéÉÍu«””‚˜½Èµy›ù†mAjW½¯ ïŠ*·´ „€ìá"™}A <¯Þ–—[H°œr•V,V[ £nW±Ž“= ¬g¶sصºJŠA  Ü+>˜Ù;B0NFef¤d6 P$;‘Y¡ Ñ­÷WÐa‘pE ä^÷ÆJö[&&$¿ÜÃÏhÚØ[áËH¤µìݸLõ@Â[Pˆa†|ð«æ•UÌK9€à@È+”Gâwîý7ˆåÄn¢?1ßkUqVܤ€h5 4ù)Ľ–‹”0êÂ&–4NûœÉ½5õx+)[`WºšìR„ªŒÂ8sP=¥”®ôå´ §e‡Ð*q Œ¨‚6ëç3¦°mx4 S¶}¿ÖøUPe
+¡:I.(òY°Õ#uoé!ü0_écE”¨bOëè“• ´®lcÂÇT<ªÝ5›Ne‰Ð
+ˆ] 4,wÚñ|l𖬀[ÇÑpEÄüì€W©ªÌ¹Aøßt|ráv€ø§ ^JXpõîÙ­¨DÖ¶S»8È32śƒ?l
+h}
+í@™ tøÜ¿A"ò’ù'6ÂJp
+s”Â8*
+ˆîàλXéâUÆ¿á#f~pëó94JåÔýÊ%ùs’¯7”ÝUäe/œÆiT–9
+yðOÉ pa$Ä»ŽUOxU;'¨îXš´]|ãR(Ÿ
+óòmJþ8€ŽóÞÞ ªÊ¦Ì¯‚žwðð¹@ßXá¸\ß!Î.u—'ix§Ó¾´rhœ¶ab*©!ËOέ®òîŒ~Þnž\BÓ
+–êmADþ¸$¼ûÉ,È_ò.Ü?á”ÊÝø @e(
+~Ý íÄVÁ̺A¾ $-X<uwk¦Ûæ±-Ä×®‰UŒ‘ÚŲ»$Ìë¢`3hóï d¸P± ¥8w§2‹+”q+Û‰þi ÂG4ÈÛ$Uö¥&ºGº@Ž WBâYhf+wæù ôÝ©Þ@†Ÿ;AX1ÛzJ‘C~+K,[œ•œ“çý0^R¢`ú¦åx^–j)žÜê‚Dí.$IUíÂÀsP¼,Áåø
+:U§Læ" Æ»+áèJËŸ¯p÷¢ø·ÿt^Ã6cÇ¡«T
+šN¥Q Rôu °cYº» 𙑱õ2B.œe/B-á±”ŒÁåéˆ.P>v×ܘʬŽÎOª[-Ø uÂùãv B‚•P€rûƒFu $ïLî7Z;@Ö—A†JFãïΙ°gf¿ÂvZ8&‹ìÂ=Âü0±XÑh•‘ãTÚIئÕý(`6‹òÉvõì ¤Ý€
+™q¦hlà{Fx¦ã2ƒ€FzŸ‰8çÃHÝ¿h;­ó—×áàûrÛü3ÚàUø’ýr½:¡]uK6¡-cc$wVd„ƒù; ¼›rÛxò’6Ó]¹6üp™ëÜu¿Cq®S|¨ðaпuêã••ÑvÛ®J& |£7ÔËy_'(¶€~1WcU©¾«ceªœ›!y0Ù ¨$c_I6›òb'Ô´þ®Ž‹ÿÀ4»XŠÿ¢‚kè^tHÝ`sÏêÐú'Ï¢!Ë¢ w¯wÇÌ
+æuŠZ…±Ð™E÷ûùã úÖúÏ#ëÊ,2²C|gããÌ8®xn*œ©±tÕo¬!ÃÍ2+Ns¡8Pµ‚MØEfÜyVcÙ##b„€-gEÖš£=±ôx ^Ïtyp‹,Kƒc³`ú|N“\Ew<²"÷’n£ªÕç虺î¯âá BËfÖÀg¹2;1˜Ñú ðˆcŸo¾1#Ó@,øð
+wªô§? —ÍcFš†‚Ÿý©¿¯§E!`lbS2«Û(З¬ ÅÅõ½Å8¤Xü×vuµ¢lh[]/´kù ÌËæ:&B§­©„YƒÝˆ(µ ëÚ…”9)¦:ÆÝ9ÌQ@'F®Û@bö¹NÅCLƒDeAY©¶w‚’W$Ãi= .½-·…½¿5.WÐ)¼ò¹
+
+PÓCËgR›Žñçt$ˆ6熸¸ë@£
+l\ò‰áæY¸ér@»DYÃpC=ØR&YÄjgóª!]¤µfAÇ»ŸÁ=6üY
+S"«ËÃ!PÅ(–e#½ö&â‘™—qq•…/PXÚ™6Z d
+‡]<=ƒºóÒƳtno)QÆhÇ
+.ÅÅÒÅ_Óñ\ù[#´Q.Eï/Š& ùÓ Ù/ªt€ßâa¬(¿[EËøÃKpkC¨™+”m$b$ÝO#JðÙy?jœöü¿_ü×?ÅÞ’€H;ñ·=!–%û9IæµÆ.½Öï‡.|¤ƒÉŠÃ¥(ßðÄ^æd»ž†ÆnàùËöa”H  ødÆ\ñ I&Ó/Ä’ñÉw´çv£†]Bã!ò
+•áAï€|?ï%IŽ¥ád]øç?÷"ˆ%Q†§È§¢+k™ãâw\jA”é\OWlBçæ<^Mš˜*‚Έâé¿‚z*À²%4 á%\«I°»9¿ŒþÙäWvbBFÒ‹¬À^ ”<;˜TÃ4¼d(Ž]9\l—ªÃÚ†2ýJ’g1ò?¼KH‚äE˜3 Û•Åv˜¦î¦°)S6Œª2"?V%Sz
+”+ E&ºhA˜ª'-ÌÐöJÃõ/S_Jq˜ÂŠ/¡*(yÏ¿~
+—S*¡ÀîâÅ’w‘20·’
+Ë¡é]6¶Ä> @¼ÊþÀ
+'àôQèpõ@¼¶q{ö÷’hð”’ø±^ÏÑ °
+6öª„ò³ C’îÜf)“‘˜Á‡ßÚùÔ¯˜ È :‚Œþ¸ KÁǽã„ÎmžÀ±r2,ˆÊ?>õ[¿?lF!îÙjÉâ¼¹ –€[}ÞŠ¤œ7Æ6dûêSì‡Émsºt¡µð)øaï©L¤HˆÄ7®K“PpM½?φOV…ü‚l
+ÊU3nw¨ 4 `W•¤„O¥&S¼Ú+±CØêÆ ßÕ$r5
+B@gª^Á6(!pßxûÙú”8Ìy@?qÍXSH0>ÄRADcèW[Ü´þÌ ŸÖΧþ\$*“á04áŒ.EC¼ JÖnS4Œ\0³Ú¯¼M¡/k<è`÷
+zÀ¯°¦uxšYäáÑ~:(MJ2ÅQ"€ÝÎÞÒÚâ;S@ÂÌÁ4‡˜8"‰˜Ù¥$P±?0¤×s´¦ø8>œÈ5q~„CªòÄ£`“ðnÅKºô×:ö@L¿¨ÅÊò¢6A0CÆ3·
+[#cÖ_À‚W ¡1À¾[< wPáa¡¢0 º@G,û9 ðÀqppè5|Ó°Ïà6×wÖnl©ËÕçùÔï©]*@YÃ
+ÞMß»ÏgA¥¬õ%'}xÙFf¶ñ…kP*K ˜¤•ºó.Áava¥¦WÜ]ª€J—íîçŒ7Á•e‹ã6d½b¹Ô4£DK=4€ÐµžëR§«#õ©„¹—Ží”õ”½}÷¢DR0Ñœ¿-ÒÇp¤@¤¹ó¹Õ
+f‘²ßGË?“¾†ƒ’„Izù‹ådVPx)sÅ°¶ð‰,s7E8# /±¢)ìpqºújßÍQGk:¡Ö°[I|ª,FÌüÂdu2"³¹·°s,
+Œ‹©¼W›îA‚àcâ±K›œ ¶…¹6!€é)®®æ W©ä‚b¥>å2ÉåAô0SÓ³¹©8㽤›éd1ø™)S.ô7OÅÞÎËÝS²6-Ò´Qïìd#Ó6œ«Dm#ã —“¸ç žÐ+é†ËA[pk2¿ÕIë½N‡š•NA¢¼'†„ò‹iAr˜ð®‡QuS96)éx¼&Ú“£´Òò‚Põ•'bWÑéd䤪2q8AßA‚ØJÁPx›+l°kyCþì]“24ú`OžÄ’e˜³Ü„
+l1~R;›+X¼
+ül§&“L0¯›V¨BÒÆ'…^¯º$¸ùüŽDF–6Ìzì=÷
+Òµq
+í²¬Tâoƒœ=Ò‹¹í‘
+!ÓÂòôÚƒÞ÷H<kÕæÖûI£MÔµ©¹{¤W‰Ûþ'……´Ä^íq¼–90YÃë]­39¥ª@Ûn‹¤~42ÐÊPôø°HªÆ•ÙîXCØú¾HJ#´ÈÀ¢y[Àm‘<»ÝÙ$ ·è³4Q°1ŸVÉ#(6Ú•ÿ“M¯ ãN· ïߌ©MsýÔN*e¨ QÑ ¨åfi7Aˆ9ciÍ "¤Ñzð$•m‡¼i42fASgÓ2Æv–À×IäU³†»ª}Š~k²‰8ƒùJ똵?@‰Ñ.L0™Sÿ3[H‹´+AÁ¾D9™]¸ˆ]gÕ¬†Žìó+ºÚ ú¶ mG¸lƒÉCƒ…FX=Ô0\-i O/§oÕª\Üy6Ì•öʼnæ~yaBNH?Zw°ØÑš³vû¼
+ cz
+·B$â¸`Ó…å#Ä¥Ğ˰̤9¹éä‰s‡eµ“0–äÃrÐ$…æ@Ob>µ12p½Äê«àYˆ;ã0‚|G6»ä…Ø—<Kg¤ñé„uòP4º¬LoÑZUIerXY ˆª´¢µrº¬LHÇàÜÏEå³ÕT>‚¼’¹n˹g~jž#ÈCåóN*ÿ8£ •CcJàPxð€Ê¡RŒ¦afX]å „EŠ±æ¯7b$¢
+_;nµÁé†ÊÄT–!hcóë • AÒ ›r •’„¢áŒ¨L¦“D™E³¦ô€Ê
+B½¨ðâò*ð-nq?ëx8QDŽTÖË{c•äq/Ro¨¬ «{ο2|0îYL‡•ƒ œö@Áb{<'¤K
+âìÅeå€S4å|ä5\+D]¸>Ý“›ËÊ„dȉ_E¬Áeå3äde/æ`å#èdåãÆ+÷XùHàÉÊGNÓ:Ê陟ÚbòL†¯ßü®‘IØ
+š[›ËÊêQþbÀqÉúÀÊjõZ(4˾òÍ%Ž9Yù<‡• vìQ1H™„ò¹¬¬¡¢t”;D—•UòìQ9S²ÄöÃßaYÉ"‚8´¾kuƒ\¯œ,„øTJ…¼ä§sòˆºb§§\XÚ
+Æ®c²ö]¹Ø.<YÀ4¦¯sÞU'ľÄÄ@TCPøtN«øHÁ¤ÒþY!XÖˆN®ûªq
+m¦_^±î@h)F‡YÙHg3³†WQÂ(L±g•
+?ã@!ù~Nú/¬Qó,ß^±Ä)%lÓ?'#{ ¸9U»qAijBŠr[! NÊö)”‰9€z0åÉ$9É6J›Â`¹ æ½®cxïTæÉ«ug ¨<·0BÞ:ôëäözb’!þο9gÏùÔ/‚ÞÔÀª÷ Û?þ£Àˆå°“Å,Ìw¬âÒÖ?*A395ßOÂ'Ë&˜* êÛ:ËÆ ‰·b{’è*ªçâÖ¿!/¥…‚™-ë+-•ºàcC#42Y[7ËFìCª1WSƒpá à]ö©‰ëâ«|®»Ó/Œ ›—-½ý} è(¬´’MÍÉÃir»Q‘»r ÿz»džáq)Ø9x¡_%üÂ,D ;‰c@“PÉ”å£Gã
+"M!~Õ¡Çà@VKjïÝ»q]Õ‚ ¤º9*‰}˜)ÛÓ‘44FÎ@ Ç´¤Zölܺ׺WÉ´bSˆÌ³éöØ8Þ©ý¹Ô^Ůٹ"¦’Š¦Ì`!YÊ&ÿJó²8* n–”õµäT¸°O1§mwt
+k\oˆÂFUœª±¦FÙ×9UŽ7Q@frVËõ²} eaïm2gqûúã¡…iPpŠ•×¼ßsüÛ Ê
+œ["QªŽj!Räp¸$Ê·™N!“$Šñ©¼ØnlN„µEJÜ)OÇ
+Eà0S.èÓ=ºÃ ¢*u–|9[
+PILžô0jž]")v\^ÐŽ¬—d€9k*â÷ è#c
+q‹P= Þ’¼ÉfØóËi˜9©óÌ‹]§VUQÙ ¡I1™v†´ƒ-I¾‰òšÎ,6—ë›ÔTŠ:ß>çÁðÐLT
+Êb`Os½:g¨¥¯öm86SŠ- ã]©($~iæàIŠijÍ^¥G £U&º8qaAªpl<OÇoàOϧ82͸dÌñ¸o>ˆ9
+…r‚v(U =yª¨èË@Ê•¶¯”(Sd¼kg+ˆ7flqÝä•P
+\ŸgÀ‚}‹¶ÀXHç06›v£ZvcèŸúÍq1ÔÌîVÞÕÞdÔµ¿KIdØŽÂ3€&ô>W®H×}nû?Ž+«y¼|×;@œÄa81üö0ìY“ æ´¼Ëd²YañUЃ&}z_{#>-’t滕¼;öŒÁ-cLඦ@„Í”­æ8)¡H¡pg9¤²dºóÍç6f‹ €Q·A-°A#h€ g!lKkD31Ñ §$» ÖMž›ýC2„™ŒÕˆ}iDîÇ
+±-îs"û>1é%^dÇ»Y Ùøq¹§:®Îi‘enl™ýÛ„%ÈpDá¯^½Ša¢+˜¬ãð«ó8[N½ëÕ¯Wùóú\êÍpi^ï¿=®ž»â6k¹: ¤‘„ÖȾ»Îˆj=øK!Ö+çÞ±Kl4¿•ãUœ3ÁØ9¤~T÷Áñ>õÞsÎŒ+ÃLÇ\6Ê9‡H“—Å-Oÿ6øÙè±üãÕ«’bvƒ…é犤0"HN%º5~‚<öêãÍÝõþËa ú#Ûdﺿ²è‡\„‡›¡÷è=] ×$EK¾yª|_B;Xë u«ò}#{"LO 7Ì=Y–Róÿ6ӢѠ~õª5î ©¤ÿFà÷ÕyÞ,Õ8WEº¨zùË—gžJ„Ìr>õߺ,tÏÀOäàªê·ÞwŽ±Ý±b^)1+M0ùk8z%¼¢gERb ®Oá7øcAˆY8q˜ËݯAdä2xÏUxíí=*LÂöqø«ÜÛR=˜–$h—áÌH6ì¼b#šÃC6äÝL•n·FŸ±•µû§ô}•>áê_…ø–÷+%zõ%NYãž®Ž¡æJoMW²&`¢i,{ÒŠAZWa2|“EJ¸qý²7ý $›Ù¨úŒMïË"éÎØÈ„ù›¥¿
+’îˆÃè.‹1÷X8 2å«¢Ë<Š¬{gÊòÑÁ8äa{]QHÍuYõ#•‰˜HmjÇ®ag™Ã#ý41‰ÚãY´ö)’F«øy¤ÎUÅÁx±BeCRdÕG&>TbŸ
+Q£ÐÌáŸÃì(<1)ò‹ûÊ¢2 ÎÌ <™i듹³Ú@i‰Â,Ûùñæ€ÜV°6…³q¥çWAêzæêÙâ' ~ E)8Š³Å²Æ<’óØ®ÊÜ•Šýèc^u«’ej‰Sêáw ¾Xj͈g¯ ’a®!æéýª[õ}¹¾Â$ÎquNˆ¬9 ùص¡E/hÁB(JŒà¼n.k-5‘ Œ»Y ·:?ƒV”WAÄüõ
+{ÿN)wLРi™¶ìë“+Éšä)4a=A°€­Öî€>/@ÈÞ ¸nÄ}[Tù¯HÕ©ü"´´(Ž¶x+hŸ"D#$ÂàYá0$vAlJÀ±î¦wª6VÑŒ?H„W”‡ëÉ~ˆF~Ñxó ¿v‰MS£ìEƒ@cÙßUŸ ‚ú— 7Œ¸!8«pxÂT"ÁùÏó¡Ä^Pt99[C)pnØ›RJ쎔È* A¤H
+,ÿã…žü6ô¸•FÈ"mDÇ}oTÁcS¾áê®X"ª׵哨)£Ð%ûÑ0C°TóIMǽ¦ïçchUîIÙÌhÖ<ùZŒ›YˆØ#L%÷]°IDq =A0z°Ô„³#Íùxó1Ræ$ÃX¶e Í2'‘Ñà¼b×ɬ,ÏD¢ =äÒÍÀ`³ Çhp´xëâ&5µ !¼4W?h–ù ¡LÛ+ÇÁúÕÉá27f,¡ÝrÅðt°+‹òº·\Båõ‰¯mŽ)ùµ© "­-Ï0ù,Ø¿#Õ?$iéq™éä@äe°m~=.~„hšu
+~„wPææãÍÅÀ¡2ZMÚôEýoÆJ”ä`¾YRqn<¥
+F‚ðÐÐ+¼±g
+TçÁç#»-87<ªqè4
+z¤åÏŸp·¬V~ûŸ 
+2Í¡yD‚f¼05
+A` ¿ÓyL”‰¶¾&Zr~¥†á!ä‚òçîTr+7ÔVïF¼®6qÉvÝ'jPô¥ÚmØÇ7[kqïý­‡åh’µ{ùGsoÀ“Áˆy·KÕÅ­59“ÁË¢iH÷#‘Ò@5­ëd åx±Ñ—Cp Ô‹Sø¹qj‹ó§õÕí°eqÝÖVƒ6Õcâàʲú'7}U:3ƒµŠ÷gÅ)Ö±r
+dÛfg q ‰éôþÔŠVfÚr[FM¯¾àãs¼KÓf2J±¯Ó@€ç¦›ê¥[’ ƒDB¸XT.»Çmc¼éöY®ñ^¼Š±×(Í¢J¶±¨×öLê^Ø Ró©‚ÙØŒ§j%€øK0FJ¹ËBP°ŒAÚÑNL’Ÿ†¶àÔ$ÂKN]öºÊ²!@ÞN©l|L†^;"5¯ £ó§.Æ«; òIßç›®þT«Âô]dCÈ|0e äjDŸ’äøˆI_èóH ó`¼Ö„hMp\3Ì3ˆ©îð²ÄN¨88骷Ã3Ü›§,O–Ó5Ÿ6Gb’,0­Ivù†¤FÄÓ@àóom¤^g÷íÁ~ÄËSù4¿@n)iøü8Eö¿6îZ.½“îoŽù§Ø K‘¢¤u¹–Vèî^ýÕ2s@APûê÷Ä\'‹%ó5P-ÓˉüÚ°i°œÔ«^E†¶é–Ö¡âT¾Âæ§'*úz(vºcÇ
+8w(yLƒ£‡ž¦Ë8„§†>GbþûŸ
+ì…踥â­a ]Ë~btk¨¾ùê}‰´eéõ×qžAÊëç$ø·7MÔ¶V¬^ÓÄ£þË@ô Bj¦òÆ6É äéÏÊÁ ÷v´/‘þ*V¿/‚Ç}u³7Z¢´ü]*äYIJ‚Ò(l[gbz°9+{&ërzMÇé ‘•_;œê;ÁµòNìæ…L,¼NÌÝ«˜÷É%ì…L˜=½0|¥)¬,?1ržKQÀ³›Ã!D”5í«I¨Ÿ²&–q:{‚ùéë.ò­Y?ìö`‰q›>]«iŽ(ô8©« 1lª±üõÅ;9 LÆD,øï ~›T ›žó`ôïþåä0Ü;Å@wÜñ½¥_C³•<¹Iﶡ·!†z-ÍŸf÷@©€¶Ãâ¸K=^‘TŸ!¤€uò2°L*"Oܱˆì 6b^ªKÂâÝgÅ»g8
+68s“R÷à<bJH[U³ä[qaäÞ¿ƒCñc3ÙÀ·â¼.YªV{*±
+]²ƒqgý „уGe>yªüSPgþqér¾ñ¢Q–©uŸ ªAÝx|Oný˵v›™ Bþ*F£ú9‘Ñß å5(b½áã=H”ßž”³éRÉdž ´qWÂQÍ9®!á‹;€øN .ø´~x7X‡îÆÓ+²æu!¼ÙËsJ§Â.fÙv¡¤Æ°ÇÖñÊí ^|*ëAwwÒû1`„?[†]¡XLl÷A§­GÓ
+Í5·câc^ 6 ¢–çD8œa¤*åŒX~{V¹¸ƒÒÜÖ©p}íœýí@&sͬpÌnÙ ¢mŒ€«<+oYTw!Ç*LÜ­þÏx¹äÊuÃ@t+o¾”4v†YŠ³ÿiN‰TÛ¯[׈¾’Èb}°|s’6ðâ‘ðp89,þ>ˆ,ÊGÉmô¾x ^E…{š®’Ñ06³–jqZ‚~°«|GG©ˆKåly€Ã@óœA?7VUÁÊ`T'‡»zã¢1äcÉNEeu¾ÕK0ƒ§åq"!ùˆ×¶ªù¯,ô‰2ÿN%ü°È´4¾Óyc`+ó|(¡ý<<”V^G½ÁÊRh€ù•™
+%ö¡¾öá½H£¤U\Ùm·AyW
+ƒÎ–ó„‡Qc `$Ž>\Ñšöj‡•Ã‘P Œ<¡\¯Á|0omtŠQmÊiب´„„"„™8G£o$—T¢L
+´~Id,9`´—Å*ñtw-H"ê¯.Óf¡ã•W2naícZ.÷ؘ1,÷—qè[IEãaÛ)-zúÎ,¨É„[”)ì0ŽD š²Sêã)…eå†HŒ×BHË'†%'ùn6%KàMå¡ä›iý!oûõ·&6@bMl‚Ø:œ3„+ìšò·ŸEoL¸+8½e0lå8¢ßiy—Àà
+H‰”—Kr\·DW =p¯(ÔcM½ ExDïúN]àÊf7:L;–ØÌ
+õÉÌr›ÿÓž‰þo)üè}úCF›:ÅZÆEëMSÅôãsT‡™ŽémŸ4Â[·œÒÂ?.HØhÍ­}Yé=­E—‚Ä£›»Z³q€üúqlFªÎ¯ÞC´Dͧ²ƒ±ìªš&3
+‘®Ý¦«ôÔq›=cÆð>×Mõ5bUï²1ÓÇŒ˜Ü/}£žÓ½ëè×Mó¡ÒdDwo¤tA² ѬgK{ðc#ØÁwâ¾é¤BøI
+Ãg#$ûí4P“IÞbW‹îSøoÚòk5†)÷(}!òîòNVùäN"£8•ô•CZЀ¶rØ¡‡Þ)ŸˆSáŸ? czôá}ЕA3ÇwAÕ>Þ†Ò˜J-×Ñ1ô‹Î¦ÐçwfgXBnP:IñÝõSõ,ãã׈@<T¹“qµü¸ K:‘Ä*>¬Á\4®O_Ë "Å8¯íøk]¥ÁÓkd2Ìæ̺Ú:G¢WS‰÷}•»ERÅAb
+!Fb°ÂØWÑn¿¦Ðs]ŒÖà‹³/y‡ƒdrÜXçT1¼^໥…ãé£ézxÐêfØ6•‘’ÞŠoí¾ª®nLë¸è·H‘ç@«¨Åõ('âJ…³±˜u®ÁAbú†P×9f“f ’¤NI»X_Ì
+ˆÙRèðzÂòlɘ 2²¯â«£B|AŒ&¤ýçùçåèS÷ûªgP+ÝC‰½Ø!S¤VE×¾µT«iZIj¬üÑS‚lÒ7Âä×>œƒîü!´*Þ62¿& ò¼Îñ™H)_s?Ê$S4M6½þFn«i-€ôÛ»sŠ¾¼"Ÿw4põ‚Œç‚Ì™¦Ý­É†X °™‰îGM:gº²·Ñ a—1‹õ/]$ÑÙ+9¤Øèú€ƒÆš†Õ˜PßDMÆEPqC€ã
+«ûqï*ÿôâ‘N×ý;è´]œ@OÛEA˜bÆü¸]
+‰8à¯CÓ)= @þøå×n|Õœ„’ÊEWY$WgËtË… ˆi¡â\º…ƒ¸U‹+ÆåzyI¢Òhù€îówÿÚ÷˜[¯øF2LW
+?›\ñ€ñ¡Wx KìBLe*°öVÝð,H‰Ò4–:9ý±å%G­n–†r¨âº… ç×lœ_Äv!ëKò›ž2‰ãi¼„ùRñwCŠÄÅë4ÚÓ¡
+:ƒ”»)έaIR5Æ1χ‚ †C"\I¯êLï!.ÅHGì(©ó±_êÉI»Ì\GŸ–¡¾˜™ÅèöKQ ¥N4ÊtÒÔ­_Šyè-„S /ý·Ò"U¢f·_^yî´Ë Ä}ìüRT͆>*Ô äuËë~œfùÍhÚüv¹«HèIý”^fD‘KLÛ‚
+c^XÝ^ýi3Êyt* =b üíV=ù‹£J·† /h®3Dy½¦‡A¼¡’X´^ó’óĆ&JÎíÎŽ¥'ˆ*öA&JÞÁ¯öawüõ—ãáIj•=Î秺>§ëxЂç%•úäxâEéÃV»3jqCb¶wJ«8 wÕr ežg… ìcNß®ÓÂý&\€Qa/£|8Sw1»9ãë"<‚ÍQc “•ÄhüáاŠ]ˆÃØaMOSÞAĉÅS$×¹`&>é΂ÝÎ ÊÞ*qs¯ª¼„q5+C»Ù~‡6õá-¿@Œ6\–f£¨©¹ë@×T^=›!š ÃÈR(W)ŽaÄs5dæÕÁÐë÷—JiÈ%ÞºS)OUÖè’ K4 Gr#&³¼Zñë€HÂO'€à8Ì
+‘¹šÞ,h|'¿Œ)í°é¤‘4ÖÀ¶Çþ“‰„²ñbF!ûr=.ÀŽå%¤ÙìƒOéÒuyëÌÎ"÷0jtInƒoÛ—¾>ƒëv¿wÍÝï*”ÇcǪîí_"³dŠøk¯Žñózp¹–­]]¹ŒŽR¢ž)&Ð ‘3¶° ¤Zª¬ÎQ\%
+8•±•úˆŒÚtúÆY³ ¹¤SûÔ D²çpªÙ™½B¡¡´||)ÑÆHòÅÎD$¢UýË“羑’χðÊFžá‰†r"V÷:D0$ž¾ÛÈ…|ß‘XÖ6ßËK³)Ï%:CöË@$ú™q§j+Ãb>c,CsuÖ¬õ†Äb J‹édn¢â{WÐ:"ñ¦<ZLo*;géS ªJìŒ6ZJð0Ìá¶1 Mj\%oýÐ’Öƒ0þ$úÓ:8d‘rÚ©R–/æ /þ$¬Áõ5Û/‰U=Šô¶“f6%1ÓÎ ,ú¬$ã'šÆæL:¹•8Ú¶û
+õ„!7f©÷½Å4Ã9¶sÆî@/€­sl·­kÁòl²H¤Ä6 £ýgüH\ÈWÂJ-¢:ØÔÙ—WŸ¬œðÛ‘'šHŸ¦‚xd¨tr ®:]A?@Ä8‰/EdúóD/Âè¯±Õ éW3»…]Vé3ðb&ºy®RÁe'óҤ˸³½Å›Š8±P4‰ )s´Tö:°ŸÊfš_d5Ø*÷Ìÿ{{
+>DßšŒ_|Z“‡|ô$¾/ØöÀì覞CW,0€Ø´ éòÄ«×9œê±‰A²D)ÒžÏ{Gô Œ»ÒTK`÷«CÔ@Ø!”æ`>}Œ",¦)›MVã¶Uçj:§šl gö¤–½Nü„§PU ¯XÎ`‘Í{&þØk² (¢„>ÌIâ†xR7¤ôÚ5$Õs5MMI¶Š²3D— ýí\p” O%uÞ\º©}CzÕíòðó{Ö trÔ;¤JÕí%Î:hS @…ºA*ü™Œ'ƒ <•Fšm†W½€LT¹aº^_è†Ù¨Ãi@ Bó›PDØÅx
+šÜúF¶Æ£Q^)úbCcÓæ
+’s¹( LÖµçÕ…ÑηJ"t«91L˜)a» ”@ýÁÜm!¾·sý×`?ÿÄ…*^\ã©‘„¿,šÖͬ1 bJËÇõÊ سg‚£D>إˇñ*!²5êÀ†hêG’™T²•›íšDþtŠû:I§˜¤…SÉxr† ¨}Î Ñ©T°R:ÂÍ¡­DÆ™÷5^An“á¬YvüØ6¯ {XŸÓºdåPÚ]6Ž& –¦‘>Œi\
+ͼ×aðI®¨ô!HGl“"()zC"ÂÉ«ò©â@Ö§úK¶Rðšwë¼®Óqå¨B@+9A‚ÂÐU ZŽ"ÊÝNEÍP’&ú¤m•7:­Ršôìó/çcʘèˆÆø°-“X¸Ø(/“ä8’ˆž@wà ÊbÖì¥n¡-uÿm?@–º2‘Tõ7“}5FF
+l>É2Qœÿ•›’2™JÜ%Õ¿ÞAòÏg¬*ÀWSÞ©Ùqåh “‰‡üíÕˆs€BÊÒ;*ªæÇ|°^3BZšøé~›Ö@KÈk²µq4Ũª C"‹Ðø=<ö–„•ßÐ69œ¶HX½FÕ‘-—æ†!JrÔZÎzº UB$ã§Üχ½±}Ó­ ™ÝYÍ@ßïZKhød*¶.
+¢Q<¾wÆáIÂe¬Î9gp,B®ñ¨Ubã€LBÀ²BIã
+x‘âÚ-AIˆ’+/}þð‹NÊéò»E•3e9¸¡áÔ<fWl{ŶÂÎæ'sˆp7*Í°¦ô½ |²eˆ‚oÒŸDð9 Q+u¡×œë€c ìSÀ6Aµ—#¬ô²’-bÒ÷@A /q)N‰ƒEd8¢ßqwÏ<qî®<çÕÇXé µB"‹Ã–˜£ÂÆüƒAÆ¡ ¦UMŠž ‚‚Wœ,âXÑöÍ…gªÁ<2§ ÌòÄŠÃ bÍùo¼úÚE²çÚRZmüEJŠ¢LžgOëÐÙ(ÅsYðolú¹mv¥,kI¸ñÁX CNøŽEºå!m`›sJGQ§W%iØÇ*ÁˆK†áåÃ)Éå³ÝXš¶KzŠ)­6ŸK~íOAC|fªkwçÐõ(Õˇ{|Æ„Iv‰^…pÂ+æF ÔŸ¡k3ïaœ‹\”ùE¶HÉ1ÝíK‘Œô9æΰuûš×{Ãcd[º‚#ó
+Ø¿!q6M‰(ZQ‘ª¹)ŸoËMp1ã÷.‚ª™Z—ŒŠ°æp{æ—²®0+ ûª¨ÕšKù”H›sW+
+Ýšš(éCæ Lp}UŠV‚ø(âͺ´ŽŠ®˜ŠŽÍsÊ¿qÕ^÷—ºn3{Õ–™ã`,\@kû>¦4ú‡ÝÂÖšd-j/ »„%€] *u;¼3e‚ÉÜÖ¥ÈCªŽ@cqÅYïésä›–™^åa_nQ”Á$rN<&ÑŒÈ>!ÇlGWú€KzïV‚C•¥L§ä×Æ1…žU7üs&óo41·!ŒM²¨» É-3 Ží—š·A.Eî¶K;bLyß)ò()»Ji5&§èëÕ± «ÅcÔ§œ§ø{1?¶…¾¤°r¸ÂÙpKxb¹%»µ;½^#k,²ÙÓ’©5­ñ±T<3”Ìïæ]¢¿"Mõ˜{ˆô†ÔjÆN›„£„bqŠ¾v;(³C[3@[aÈ÷·` Œ3|øtì¯ï&àm¡ð8_÷W¡f(¶}¸´Aƒ‰EpdìÁ³¤Þ,=Õô<gÓ…oÎÁ
+ÄÔ@ìB“ózR~As úþ1¢*PfñëpKˆyŒClŽîQ:5/¡òË+’I("ïa¤ áóqê7jNÞÃ%ؽÀ•I±Öàÿto©5<Å ™ãüppUÙË =µ ¢¯Í¼Qk¡
+«4!«z¨µþ*f)Cg"uD(qXIlà€·c(:ù>Öú Š+°N*ÇZ¾®
+ýM0-{ÂuFùpVŽúÏ0¿y¬åËêžJl)ápî‚Á³
+XK€ AÂ…#ø÷9´'Œ!‡í¸O,$G8 E‹”ö$Ϣńá¶Ã®2œÐ‚iSêç¹¼Û^dÛ°ÑɨHßÑŸDB{RžvŸüˆfî¢6Jl,ñá´ß¸ï…òSzúñ¾ÿ`<G’ßîÎ0¥©´Œ]n­áÁb•|þe¼ÌÑãØa |ßA'ÐÇ}‰•úJ­û§ï/=õ í ØÆ°I P n®ÏøˆG?×N,›
+äVZó÷ó_S@ˆ^—êžP@ZË UMÑ«±¡Eq,cjGªË"—;l®2T< ö6C5fbÒ<.Ïé¢x7
+Iæa°@$*\iÏ$tX€*ôW[h[ Õ~ mE~04]øã—_Äê1ϱ­ëS‘F®Ì¯`‡Yj9L—ˆ\L›µ§‡ˆ—&òöîB+W”³P£„%U d¸—T—‰‹ëÇ·_tÖý³^Ón«pâ¸;gè"Bõ°…gsáxTš‹†è;?hÒ·dŸBáÑÕÙe4ö§àI GQȪve`„W`á˜û>§ðÂ%d{Ö+b ZZÁJF“¢ÏâÙª_nMiÀ“3¬¼Öý©Ç¯á5
+@ë9‡ =6*$…Dæ#óÐbâÞ }#pT½;‘"Ž%ŸbB‘³~ByÐl¶ËP_´~}3á€j0„
+{4è²<`QA>²•“³–“1ű§©“zÐ]˜‹%œÛB˜e{ež…ÑÂ:·ÜªVþťߺ1k&Âái‡¬ ¿nŠ¤`̈¯äEªF(ncíu‰EæìQh»„zÞBßš%ÇR“Z;˜­¦v=dÊSD¥3P_×è£Ò.h­/Ñ‹Ý1ª/‰£¤°œ_ªNÉúÞ*O:ݽ;‡Lk ¨ÉGì¸höµ9n UO<(HN6¿_j´±Ì.¸Å ¼>D§€jsrÖOvÒuñžE@eö4¤†€±{Ͼ–سFbSX›s”¸Ú1N´’ ʈݛ¥lF€¹gJ@%ŸYþÄ„ˆh
+”%}sµ”l‰‹Æ¹Ìø‚v„?]Îôóÿ~XÀ.ACBhvf„£nõåI
+8¯÷eÉì긦$"`MnáSÐÃÞw»:;0i,ô`~7Çæ¤=_äÀ¸Ù1~Ä[Ñ‚pº ö1§¸FOK×Tõ©"_\ÓÜRÔD¬‘íêóîT‹é[éˆ?Õc¾•à\VBáÒdDFbŽT`<0?ùÝ áܘ‚‰z'pn}ëïH:+§EN¯‰ËÈž5¥sGNQ‡ŠwI}q_oF ë:QI†jã”—!XTƸõØû'ó…z=–£{²"0}1Ð>mOñeIä;ìCä
+ÀYƒœÎ.AÇ
+q#g™z ´<1šbãäÒ\oö„üŸY¶=+Ö,ÉÕÓ›Ò4–íé0&œ.ÎV‚#Dš)6§ÄºLSe%NñÏaäa"ͤ–£É“
+)™ŒðÍèvÈ¿!J'Já{:(ÖXNÉ…¶qè5 îpþç+Ü.XeˆR‹ŒÐ3 ÀÜPPZJ?k¾X»5 †gdÏ1€Ÿ½Ò¢¶]B$$ã %1§dÝZ‹­ƒÃRýsXH¸‚Õ‚Î,þA¶:š5ÞÀ`!+²*$g+)d‚Êz½Ax-b¤\6â}Ü”ËJÆe OýÕ"—¼ù\©ä‡®ðú—¢Ÿ¿¨äŸ]ᓽQIÚØåa òC©ÆA‡†ß…R >àÞy-nåîx.ów˜ÅnƒñA9øóæcŒøEB¨oŸ¯
+ª¢Ûay¯râ€nµµ¦jÊÔ#JX‘1aÈ78?ÎfÇ*qG±°Ë'Œ˜îη´t°(Æ+ 9ã®d·×J(Ÿu
+k}´I,“åÁê†!E Ëƛʸ;‡`‡*A¾Û
+$'‚
+ýk¾![_êD'¶*ï«y9g,~—,çh—t¸Á»å]žìžH¤¦è tÉAÃKo®Ež?æ>M*JD)¯•ð©…Š)˜Í Š§
+~Ý ˆM»5 0 `¨¬y¬(”ò÷–¥D°›ü ¬93Ë8ç|š‡’ã¤IdõS
+žXŒ>šc1¾nŠOø·ÜiÎÛ*!nUp(„nÝJP‡qü.ËÒôÖD”KJDY–°ìnš tù|nV+et*‚ˆþ¶J$3ÚíÙÍSw9w ^2í’ªm'yŒ‡îÿ¿Ä>…biO‰}î9:þV6^Тïðƒ†DÄÐ7ó;I}Áä‹R÷ü¯E "?YEм£EOP0 ͸›Í& Y˜²ßEQѱÏOw€ÿÜB÷œŸƒE‰‚%»4ȨèG:8Q–òŒ—9nœG…OÀ;0V@ô¾„S¦>áHtèûû{]Õ#§y
+ðk˜>Q“C £»&  ¡c.»¼)­ÞÝ=eŠkMSI»©wâ@rŠÕ3
+ª¦Á×-),èðN€;Š>/ŠcÉ1L¯Í‰…Â’ˆÖÕ_‡ìi^Å¥±SQ®çBUL„]±ì›Ch?é¹Ç5ÎAàUJ®`ª
+K™A”Gµ­Hcˆi¿Ð„ÎðºJ¸bý­°#ŽÄ¨6«•¥å¾´l·rðo¥/â‡o¥`$/ÔÏ
+ÉlƒükηßåH«lVÒQ¦c¯`õ,T¹m ›¹¸q ðÅ°e »v‡Î™0nÊE‰`ÎJð¶T³»SÑ,ke.È
+:@)ÊØõPóy®Á œCsÄû-š¢¦’9²í|©P›e“àB
+g²?2Ð- 4Í#LMÆÌòÆÈ uÁ>1y³a NB‚+¾¬4l=àÀe~%¹tŽš8ZXöV]¢ŒŸÎ6¶8BVM)û:#cv!òÃn%™¹VzÙ¤.f,äw1±((á°ˆŒeS&(1•…á‚_°y2"ò¯ž!Ø
+k«æÆ%c©nv*æñe ýP²í/B[ÎvµŽÁƒ¯üâE†°ØáöËëŽà§!#Ñ»ÞòK$<q¢°‹8?’Š:ä¸Yδødx#P²ÁàjŠG!¸7 ÇqW3•{Û6)ø@Þ‚8>»R.±ÙS[ýÇx™$I‘ÄPôÜ`>ȧu÷’[°…ûoûýp)ŠÊôhÀ¬+K链þ0q³ð<‰¶øt&œ'›C~à¥óË@ÛòçU¹³”蔤±5ÑøÍÖ0R¯o%J„Â¥NK¸©â´+ºÒò sõ ®­Ìä%ð_—QΩ[ìÄÈ)ÒÊ>¹—ÐÌ£Õ‹_J臧0!Þ~4¡«»ßWª4}ÒÖôK-ñ!@Öí¶ˆ¯-r„mtónš"/>…«ŸMԟ̘|›,1êÏ:3Ë“9ÛÒø¬âµ.Ï–Qrx€¼SÆ<}?Q^ãÔÊÚEl30º±ç"~š"صA–/!æʾG
+kÙF9i¯£K`»ˆ©¿ç£Ý«&7HDI§GECÒM:|\G›v€”G³ÏFØ"v!4@+üÉ«3J'Él‘kr83¦¨·~O'K@'ᢢÁËŽÑ^à,(O¨éÊ<`8ðªXµˆLÁŸGÜ.«1ˆ Æ‘*ìJ¶¹
+ÈuÜTñ™r@E&^â-1/>oÄÅ_c§Œ*?T|ŸÂZº¨r¥ëPÜû·¨òTdâ8¢©Þéë.!>.¿¥Ÿ»aß™R$¼ïƬ'¦1M{W{Ÿ†<2ú®÷‚®€¤Jz*{þcÛ³­î¶è×à¢×]Â`]Ï•#>03¼0üª$ã[á¨õIŸ¡ê´Ø°j~¥ÄÙØF$çBÉ
+G‹+sðhjÀÒ
+Òm†d0Õ7!C©â £wǸÁ."ÀUŽ0h<4dÂPÔrœ¼—roBÝ]Óû:/ <acÏ)1¿K.¥µ‡MÄ ¨D#s~—ñM´Ê\Qq~]Jà|FŠŒñØ%Šød‰>tƒS·)Áû hÍF«GÌP‚YÇT-2e>CO5x#|_gØN
+wÇ3Á³Åb+FŽL{øÝFAŠ¤d{¨N´öä§Áð+Á·»dàúÚÀmÛušruWNIˆ‹­ Œ&ϲ3}`L–à–]Í2Ö|*¾nãÐ<pÀ má‡?—ÈËù‹/(–CGŸ±¶|»îutd ¯6óY_øW¬>STŒ:çHóP‡ ð‡WOë R vÜNKÀá­£ë£<ÜJl£Àˆ¼µeÇ×gÉ¢OåS;¾±¸Ü²˜±[½õJ4›³¨˜‘)Çž‹­™ &ªãÌÈQ ¬ÅdŽîî —,ÐOðá8"ù]\Þæá"%=“¬Ð
+NeßæS¸üu,¾Ñ+Ú
+? Â?Šˆ8z’êÖVf­BpŠ–ž¹†ÊÛNs*!E™)…£GJH\…†:À¨)fm’§J SJ”ª¤
+xù9JÄm¬BÇêzÜj$QÂlÅ:`”yH¡{L†ësŽ[5p+Çç"ÜfŸ|ƒ
+yyüÍð¯?nòû1èÿü‘ÿüŸ é ïÉ[¡»Õú÷Mü‰Ì}¹±‡Ža2û½­ 6(abíi<ä„àB‚¬Ï}ÌÌHá;–íaTÓ—l.Þ¶§‰D×™ÄÚªO+‹Ù iȽ¯sNmsŒêôGU*eƲ9$pecBA`¯Y¦¸Šg£gpHò™o
+¬-§Ís<‰,Nùæûx\ rì†A¬ó™L‘‘BLC^þúõ
++Oæ?o&21ý+g|œÓUgA²½ò)’Q‡çEŒ¢•‰¨£@¥,P¯9®Â7³¾Õ‡ðtÌ <¨sÊ—fQáhDÎýö6»qÂ%XÛÇæ1NÍcZa¸ìÖYÖv'JÁ’òWV<¦ 7C³ð´'ÓðÌ+2ˆD8—¢*K¡`¯«PöĈi0|ÔµR’;²§ )J`Άcy!£cÍ:'±¿ÖŽìÝ@š%Å!øäX{ØMÖcÁÉe^@¿@Ì
+UÄ,umH¥ q•&™Q$¯NiÆça
+j7Ôø¦{DuàM„Zò•
+¾+‘²<
+9ŠrAÓB`¼”%Έ‚Aî ½´jô|òHÒgkGêYᶦ¸ay
+ºd#ócdË2ª, 8ÇäŬÑîÜ%µhÔÕƒ¹AðÈυ
+ ÝÖO d7…ãðĈÊï’7ç
+íµƒTž©·«'}Þ@| Ö
+Ê’‹?D­€åÞ£åþ=–4k´Y&ï¸r& ¢i>CLèáºo–~mé;+m˜˜1‡à¼™#¹±KN‹«Ô,¹‰ææ Ÿ¡6\éç0iH=÷s¸E
+Œ‚Ì€ðm\Wº›I½bèìôëQÊ”øV’{<JKpÁR’s ŠÓc º¹ã4%$cï¬8•¡º°²»zbWÕ²"Ì+ÆÂäð² ·]@¿Ä(DELü2Z!÷¸¤`bÆ\ŠŒêÕú ‚l#N쾟‚è°u´†.ÇF°½z8}«Ï°°&ÿmQd¢ßO8!‚µDaµñ~Ê3ä¸ñº
+òCO;.Ä1KŒDÎà‚s ©$K˜™{t–ðh”ÍçOIÒ9쇽nj\T4ù>éxØÑc&·Ý¤o_Cøˆ ×È<ù°;d°÷”§.1 %¶ýl¢©&¡÷š‚i–ÅBˆ'ƽ‘—öAŽ^æwz¤¿¸X/_ÊçGÇ l\ýUÊ3¬jÁª5+WF.›lù$ï&œÐE_=å§ÁAÐz©’cD0¸gË»ûQ™,-úyŒ1SÄÑ”`ºVñÀŒHâuòeü*ÓÚki^ÙÍ‘-ÃØ9gw¼É÷ÅZ}•’WH¿L¸!χxºeÚôÊÙíO?Å6™*LÑÕ4²ÐØ¢„êa>ðT°".!¾§%£‚Ðt?ÇÈ/Y=JlÚJS&jތЭ|ÿå–þ>¦
+GÉÍ|5 l?Q5ûòýxªŒâNh"Ys¹ª_ú¹-»gÿ†Oœ‹âìˆó÷¹l%5ŒìÓbOØ›'¤ÇÛ~‚ùþú_?¨Ð©cGx›ö_*0îuüÄ|~Q7H£°[´¼öŸb.%ú¼ì‡ ÷®u »¼“ê1?Á|Öñ¿*äu, é?¤™ÊqYÌô˜½"-ìÃï+ˆÔ†ùÄ͉,µ#@°¨¸aä!»Ãg ]gu‡àh?È'™\b øÅŠ?E_Øy¸_òÕ‰[š@¯†%<uFS;¶YD†•õÐf„ÅU8©ñ#;Mú*pŽ'²*cÂÕ¼ìCÄ#÷-YâoˆÛ<ÞoæÅŒJöè§ê-ѳä̯ÊÅT…4Oâ n)²M„^Ì„D†T ì´ó#³€ÏeåZʷ̶oJ_’­„){ˆ~ ÈA¡œæÌ3Ã[§¾é‹.ÐYæ$…¥žòïÈÿ:¦±-ä­Ñolm]—woÈ(;\ œëZ= \ª²j¿ôÀ¯‚ÍèJ;!Šn"‰=k³¶‚§¸|r‰‰ /¡ülž#v^}$AQ¡fYzÝ”%Ç”¸F3m›öŽŸsärí<ê5å»2ØûÖbXtÖ‡Áð]Á»bј#Fí/¯¥‚b,'QÚpø)ÇŸ
+$/˜ÁEy’þÆÛ]ÎeÔ”ñ§çÉ“ ëN3ñkg:ApI:t(—OfMEp•ûâé S1T²ž¯ïÒX`NRešW[¬`@Ë«O±–ñÌŒ˜?½Æ´u´tZÌ(Û/f¬)>¹B“7)§oæJ)êÿt—Yr$! Doä
+ö'Ά”Ž{–(éòG“ Ï%žè]•5Ï’* $M‚¤³éð ©`h>55¤¹C'‘Ÿ­!åº|7$ó'#á«ÁSëœÄP† —Ÿ“Ø}AaäW k¸GMÞÝ+»5ä2³ÿÃHl¸ìÊ~þñô fÑ×p·ù&D LBœ¹¿C7Qh¬Ç±Im)Xðp·ÔPQefÊÌÛ|ˆvHë|Q3ÿQD¥¿ìD‹T3þÕe΂€V!–y¬­ª8ÂØQ1í0PózNj(ÃGÌæ.B5Ñ?ÆGÛöw*ÙwSæc¶˜FÚP$õ÷‘)Ë_žæýWÁ‰` 1^Gç ƒY¨]Þ—É«$°ž%Ó†œª·LOzt°­d¼qŽbïLõT;Ål99 :Ì!¸ƒ‚„]BÒAc‘Γ¾æDIv™¤´àÕåÅ
+ª
+ÈNÎ!„åðä%¯<GÑØŠüΗ ÉG2ép“kyŠ{áÂxùdr„>Š™Ï%•§uøÿqÍ8öƒK¡¤ð(ó,Á
+ït0k4gv˜ýËæÑ|¢ÇÑŽ&Ÿˆ·A§î6Öíûõ
+|[}>Wï®Ïæ‹y0—fþRŠ†‚–&ÖÝÕp`
+E
+ƒGàä”âØ–zÛ"åÆà âÆZ–ðäŽ=[§„g2V`Ðûã¡útPI$VàRÚ€FµÇ‹aªhLùÆa²Šì›ç –žL7Š…‡Í¡t9ï‡Ñe‰[“O竦(€&Ëòà5d€.åâæn`Å5:ïO ‡ýÅ£Ìç(ÖÐB ÑÓ¸ÀO‚àJk¡C«ÆOãøfEZ [‘~WžµqüW:$‘ÿo±_õO€
+H‰t—]®¹„W=x×DñGÏ™ 0OÉþ_ïÇÕÁÉi#Lb—E‰,‹Íú{ÕG·á3^ÿ›2ßC–÷Ö\W÷Wo6Þmhó©>»nˆL髯hÞ7¢7]n=|#¦…4ë1¼éëßÒ{´µºm.3ÆXi Q[£IâM‡Mýdéð0 1õ×Ïÿý诨þF ™Ú]Bû+Ö|ý~É{YÓFLóùÚÖÄ¢ StU+ŸÖ—Oß®Üu ™}%
+Ôd)G Û7Ò-ti'B JÊ1²!‘LàhmV®Ú—q”Þ¡¨Ppçð“¿æAz<Z¾ü‚XðrÒÙZ…â×…cS,!<KHÄp{€T(åCz²÷ý”ÙáFÓ6ýÜ…7"÷º!ä¶Ã”7ëMÂ9R“„hÌ9†wé£00Âà뮂ñIˆkÒæTa6›äÊÚ*Ò©Íu]!ì’e:—@6¡nkÍÃΉ¹5ßÇ´1iÆѸõFè$™.pØ®HJ±}ÒU™…M½XBZÈË,êÑ Õ\è“
+ÞÓi"šRë˜ljÖzUi-‡ªsÙ{„̤UC²åõ7H3WCÚÉMã;žÔ¢•%ð̆?¦Oá=Oš>Ìïì S*Ú6…õ=zò×›„G•{ çHClÕV“ìŽ6©÷¤BYŠVuíŸÎqHoš™¨PÙµ*ðËg½›P a¶ó#¾¸[—dFû’åèI¸ózjnEWL$ÖWy ²:ÉÖ¸ŸôMjÒe Uó¬úëI°¨“¯‰Ô+Rÿ,|(¶ 1‹ø¨ß õ—€B‰@ñò“P}=kõ„#Hé˜öòEÎSùÛV~”‚O"³{•Âßð~¡
+ô1¥ø½1âÒÏi±@›„‘bèp|$›""E°Fùh¶é{qËÅÀâNÆ鈀¶"
+é…Qæ«tê8æî,§r†zè†Pß6v»#”iÙRßÈýFÐòšÃîÞ#WNTÓ2HŽ!¥׳™(1/tÙ1Ì¡Òý$.J‡¤÷=¨á-òÓ¡Ž T'T†UIž® 2èG´‘“sŸs‰d*rëÂœ3º"GÆp9FPÛ™AÁ‡P…PÒbÈ”<"„¾ ›1{ý*-”šÔIÄ]9tÖQÅh\ÿÕÃÕ°:1%G—˜ ÔBȨ7M„–cgã4(—ãP4ç<œ„zš¤AÍ!Ús!ŒtBAè† û¼U‡±Èv÷ñ
+Öðv«Z9÷§Lö3B‚±NßrN<\øÈÎ4¦ Î*šuh"Õ¢4$:ÓGuqfÇ›eÑ×æ(¤Ž‘@Õíäx‘f-¿…G¦±¦G…¢¸Ž]âYÂãŽáa¼k…b*ÂZ*îc>
+]׵嗷Æå G¤éóɸc¤:Œº1%Šä£žä4ÒKé_ìç…¬ó‘ZÜ‘þùJ§‹0,™ÎaTá°]k=ßFßü[’%ôÊø
+¥ÅS‹íÇ/. › !B¿"2 ëW1E:²4­¸Ùé()0GŽøpdõK$™— _ãÏúúõh yWº>`X10d¤‡ªin½Ôg
+µµzu
+bg„á{ ‚÷œã8v,…„ÉEßÉäŒgV ¦‰OçÌlexOÎ
+Âʘk }°ÐYè.†Ë,”’´ Äÿ°
+ÐÎ}r ¢e±v×$]#=É&óœ„`Þ-{xT­ÒP,Š\Y~
+3¦œØ½µ©Ñkl]7Hh‰œÈÙîGNÙYÒB­:G(%OfÙ9òŸöu툟?þûÑ_ÿd<è‚RüжŒ
+ø6·ã=ÒÑñà¶7§„,”¥/|ªî$ œ®C±°ÀJ<÷Úç>‡1ŹХW¨¤ í—æ¤B¥æ¥M±sJº<ãOg Ü¡ú{9£éªW12?¸¦m’ÐK(BZç°È4Éñ7„´ü£¨,îÉrž~BE®J_>o±Ä"HÛæÈ¢§åÜãx^tEÇ'ÈwGù ”–"ሠ¯Ô9š£„ÞÐjöž[nŒÉ^ï&Ut¬*L&Ù]0z‡Î`hˆÁYr&5–’¤—õ§ X öJZ‘„{pZp+3¤àoÌ­”ÏH‘‚Ú-X’šõéœy-ˆ»q žUBÒo=Q=mfƒ¼
+…UaŒ¤ÊV¨¢¤KÌêÿ”—In\IDO ;èDÌú¶ºE½bÝÛÏÂÝS•ÌÈ*Ñß³çÀ\ ¯F¥PB¬§µŠ1Ɔršƒ§ ìciCˆB£TyÅšA?ãá,Ž7rÙbb˜þ]ÈçÏ»XŒF*%”&<—ˆ.$Aë1Éß7ý«æüBž’Éý£Äó1 …©s*ÚÁ°q¤Ää)( >®=Һ꒛QBx‚,°’m é¬LÁʱ‚Ð&Š=£™†a¡R›íAZ¡FÕÙ1˜]ùD¯"R•ëGOˆ<’¼ô8ƒ×
+¦,_BѶ¦¤3³_&æóê ¼'ñ~Qhre¨h\Ddg2•‚]úÔCøèÉS¢wE%›ÀY¼| ÍuNlIÛ¯:½Ã«q_fùÚÏÖçjÜø¡4g à¯è|„ÄEx+ÈÏ?eM@ p+;†"ŒšY5¯³á­q¥qzC„
+»4åQÎç¶ ¨ËoÉ݃J…Pÿ2ß^¢’ªðÚA“(}‹ÖÝBî8ôzŽ”LtÞ$þQTdWɼ™¢úçL¾È@Êë¥_î¿õcj¢0[ZÓ ÕµW‘l·s–À–îb.½~yþ¿~Ü‚Úq´©k×û¼·+CŽ¹çû{Ù0~”½ž—!„v]­Gñé$‚üu tKèm ÅÏAD“žìÿë Ù˜•ê;¿[°eŠÕWó‘!†úsͽ›C-Å‘"¹ï*„¬Ö¡vÑ׫†½t~ƒÞ÷Ö4JF·¶7â— ÆÑ®&ÐÉL’G°ä¢M„ldŘ³| ñ›´WYØÈxwh:ÕÈËTIÙ-n:»?¦V:Pl¹Ë…Gÿúq‚£FÑkgü´ 2eýåì8¤aNbàx(Û<ÍCÐÚY×YbýÓY­èš\Zà<@³¨9?>]³ÆHÒ±Tº,fW$™w4¤´Íx ¯à%“^ò(˜-dðÞÚK>›ìþ¨&Ï‘`ÌhQÑ4Ì1+Ž ©-RÃEIúç¨Dí¡¹„Ä0<wúë:D² ÅY±xe1XÆTBqÎþÚ7 ຄøMZi@ l¿;G,ÝUˆ5#¿<Ÿ²µ’ü³©|‘-i\–*¿ŠÅ %€Ï‡'gÊèmVÚmçt‚N.oV¦z
+…®£½1š80îÔ°x¹¸!5ФQÖ%(ÐÉÇ!bbèóÁÚ€8ÖòC,›ôZÁ¯ø"ÊñHaž¬¯ïž!%à eìþHùrZKfîÓvÜÜg·©Ù„ð#¬íç 6oIÆx ;ÚïŒ>f —œ(-7½–E#ùüÖëPIâRˆYf¤ßLöÊP1gºvÎ ÝR$G‰bšüÁS’fh[È_?þËem~t’º´8å€É"ýß
+¢hæ¦æ} úu "«
+-Ô,Û‚¸..Îðó[b(4Þª˜¬_"«¬§|€Å,é'¶_›Æ·‚n·myx–ŒÕÿ#è–—ë¾Ôă|,°Äég‚®Aøª°‹™Î-DâÁæEç·{H?-€M©…¬Û„€3Y;<'mÙ5]SC‹g ZÊÊ°­¶çòqA ¿ˆ‡P¢²œöB—i§
+íËÎáž%¸-Ñ7=A1‹®Þï‚FÈ&4ö›…FÆH˜Ä½B¿¯¬n›dø9ÒZñ'7¿,„
+ªY@¥üÉ ábKÝÃÈx‘Î6E’¹Ìu\bí7\ˇ3øqÓ¿ÂÅ/cŠÁ`¸üG÷ØY¨<K§„Æ /Ap:»­»·*g š­Ã¾óå²Ïï¼È^¥Û'•×“þ¾„\”?°N´÷~‰¹<ú¯ñ'«=Ù
+pòvØr’Ž6Y2 =ùkHþÈ‹"³+Œe8ÄoÑ Mȯ~?$@´9YŽp‚†V F¯óÛAã!‹ôö¶ïÄ<üçŸócI,š Kþ<º÷5[ ,YòI#AøŸœu7Çᱞrb#ùy"&>Ôùÿ<œ<‘SŽ®HzYÂþSµ›ì⧠}»JÌð¥3fEÒ»€H&<ßö„@‚AA[ƒ»%,(4¯‚ŠŒÍÖ% } ñ«p6KtbÜÁ ,„•ºŸ‚QdIxµ’‘ær4{N é‚€É/Q}» ËN %ݧ{-·™2õÒ‡Óĺ,—ÜîÉá$=iuôH,¡¾s{j”¨±D/5nÂä©4LʨT¡Ú9·¡ž)¬<Ñ÷ÕŠdÎÞô‡„xÈÔB¢'
+0aH\5ÑsÁ gA ìP9}°íˆ?(‹‡`U7!\õMÈEa2²§Cq¯A_Lû——“ŽÐǃœþTTêžòšgnnA«0œÆ-Ý{þ+bÀÅŸ\å©Þ]ÓB
+7˪ïÎ`¤zèJ7GPq¦Ñ\™ÔËšþHqFX×î]ófWjy¯Ó_\Ôþü€'N;† [¤°úMÀ&¨Ó³ßÄK7 oøMèLs·Ãéÿc¼L’à¸(zÝ'``J kyé[8Â+éþ[¿d¥nTX
+mØü,
+ÿz”c:•Óü;L2œgA€î±
+=ÙˆWÁ,K?v|'’×™§ñÌíècëoˆ¿’Ç ä¯väþ¨[bÐ{‘åŽÂùsÝÙUBVöÏ+ˆ˜¡|Ö!oèçÇnÙI ÝC¾¡·©tPû´(W!Àx”Ü3\Æ:-òÛÔ4¡²ÙGb¤yÿ° 0 0?jY$¹ɸ@òË@¼ÄÄ(’'Wÿ±8IÌ ›ùGö¢Z(4*ø£¸ï#IóȶÎØvýHElc÷^4…=¬ü€ÐÝÐÒ‡ÑÙ‘)ŽÛ
+‘¶‰Ù9¤—ÀxÁžÕoÃþÐs~(ùÙGÁO“§¢„3½|¥GlÊÔHæ?6´®ScØÓ)_‡ËðWQáN¿|q’0IF¹¼|C2Ϙ·ÚÚ½~, ÷0œC‰pú·.ì£Økâ@¡£#l U‡þ”Ê~ìÀ ‘i1@=¦bV©ÛÄ=§å~aãþüiB*ÏQXU‚-b|Ìíó¤_êù"‚aÇîÄwp * ”|œªˆ“G*ß¼Ò²óð>L|_QGgÜ`ãIm²áõÿpuÈäýþ³.ëYEÿ§„Ð>+‹Hù>d” ÞƒåZ:Ö^½8…ùPXªýTTÂf êýY2^è 6Œ H-òYFËkLcÀKÒ¤Ó½å:[ÕmUñÚ·ÉJ˸!#ƒʶd¹YxW;F|°EĸriU샤)a ¦Ź n¤çÝZ8ÎVþÔ"ƒB´ãS¿Vïâ[^ÜeÚ·×ï`>”‚”¡î·i»WÚÍþÜæëU –LÆM­—{uà0Â[¾×¸ÁÙxÔªaêo½´>ÙÐœï=‡·Ç[à45Õ
+c~rÚ¹ÚŒáªÌ 8F®ÙR+1vP„ßšÂnák,8" ЯJt¤ˆPÑÃ|aX=¥²&ŸŸØµ­ÚÎt„ˆXÁÙ 4ªx}wÛæÖilpy©ß.9ÈÄ ëÚ „Ž~—¿Ûèú% s¾lIÇRzŽjòâb@þ Â‹XJ.(~ 1A@°ÀÛK`SáC¶ØŸÍ[pã4æqßí'á‡iËÝ)‡ëMl×ìð‰™/ÕN§ðíðï ócg&Ã÷WYPOËЂ® UŬAð¡‰q“]C®ªrsv3\!I©ZóÚð7ÆŸ³®ضõ ð Öã¡
+âæ_+r@èk Gr¦ Za79jÆ«ŠÙì-ÔUÉp¡§#,ÿæZþÓü¼Ã…(±ºgGBh7nªÐ°ÌYv¥Ôåz¦
+ãÀ“*Û¹žM}×+™·Ê²˜šålV¯û;RÊòöv~a¦HÈØóv¾°¶Û«¬è'ZØ$IðäÀ±xK@þ)N–”¿&ë1#
+ÖÅíF’Óx2
+ƒ†“ƒl}ÖÕ%qÛôhú•u“¤•xUõ£ G©"¶Ë×A‰«³ÝL©ͳÿEÖ|xÔ\§óôz<" éþäµãù’Ž³4~Å”¢ŠìˆßGÄ•Ô^ºCP~Â+u‡`‰ŠXᤓIGR/¡ò ˆ’’p¨qŸ²›¹Õ°&âê
+CD~Í„@èc™=cÊ0 àJJÔ¢1æ¢(ÇÊiÊRÑ™Ê"­t5ãO¤F³7Ba!x'|6ìùN…‰‡l¾»,d—KÁK´kLNŠ}øX½ÈãFMŒÇÅûý;ßÚ°×Ò™q®ºýU•2¾ÕUÄÝXf
+ºO`V«cFÐ¥ªuÉ qÅ[UN=¼ èÇTV{ÌÀƒÂñȘY ¬° 'w¯ ‰N@Ê\„ô ½%zõh¯æ’Î_
+M]H‡3̉*A{ÙDÎiý#ZHÌ8v •b\£xSá_¾ã#\è_± e¡4”Ã|BáÂÍ/ü¦/ùÜ_ᛸg–¡?;•ˆŒkz1HRUS† ÒHøʯ,§9p`]8“>äö°w3„žQƒÙåÁŸIWÔ j±¿¸* ‹aFµÐ”hµ®"ÉáÂJÙS Tivº\Zå8Vöác¨jÇ1Ðî_¤¢Úy÷ˆxw&=™úG‹ˆÎ0å@¸?%¤ãuºQBøñJ?󥧳x·\"^a£RxØ”ÂÿIn°ŒW¾v“é¸iñ¼ÅAD®Á¸³Áþ&¬ ,‰Zéa•ÙV–¡¹©R?Ô”o¿APLvc‰
+B(´¬d`—|±!˜#¢ Ô?ÖKÚHM0MÅ+$·g ßÕv×Av¨ O™žÏHg"ƒ$¿!Ä%œ±¡™M Ã>ã(ñ:TÓ}C•ùa)“åó‡ÍÄkÆ4)€2ÁRt‡~"¢+ÜƆW¶kÅIÄ!J#æó\ºÇÇɇüÆS–·næù¶*J@2¹n ‚KDšÂÞ/=a åaÜøLkëú Yá.åz!Öœ›õVyy "Çw2¯Å‚/#›!EOP%ȶZë@ )ÅG¥8o&w‡|çMEñõÄz`VLv¨žÏ¨áC[){ª™0Å?‡ h,”‹ÅrŠ¬
+ ¬¸Ï)rÔoÔÓð,;!~[[žåF“䈳óP¼y0Jåâe†V
+«q ãO¨ ¶.á5Ò9SA7'DAóó©}uê˜tзwPŒ
+³rý6‘…†©íiYÖ ¨‰ÄˆÖ®”€ö„Ž’½‹N®cbhÚYfI Å‚™ýpi“6;$0‚W‹6d…‹kÚ“\0°”½ /9¥é­JqŒ’6†'{vÚK-_õä}Pcã]vãJ 4â£0úVnÇq'Ùî6šÔE²{’pW&­—HDÌOdgú9Ø?‚6u^V¾iZ2l¯*Ø8ä(ÑÜê& 7ˆKoÆká—çÓ9¬’M”ù•!á,ä±!Sr#a*Ff8[vFíòQØ‚Y÷R!‚eòmîRut ~`ÞÚ´+K¹¹ Ê "—#ò¡zËBa»ÅFKn]:¹=¥H}Ÿƒã˜š×TM³xq“a X¶ !Ý"â)3±Y7Š•‚žŠ‡’1h(zI¦9¹K2mŸC÷%: n¶sPfVºÈ”·|„œý
+#ƒVŽ¦¹«W©nÉ‘Ã…/æP<¯)–3eRY ƒr,ÕmC²P·’3Ñ8W¼ákü²Æ!SáÍæq3Vxód Ƚˆ•Z2·=$µc:ª·:¶¹g:“GɻL7;Ð*÷ YÒyOm‹$ù ­û´îÊëÌÀüÊd<ƒíbœÇ–*
+v
+ôIIKÃY Æ©mÙ¼‡N•)$Uãz5²9Öuôt4ÕjÉd#QÁZ1üö Ü"3A”Z¯MñE¡n+Ê÷Q1o ßO B\J  GͬÚ\yŠˆ }€iÞ„»d»¼‰bQ·iÉ!3ìYùá]XByyãRð7H¥ |a úcî ³€°ý¤‡cPÜ-Áʸ!}ƒŒDÓüù‰/Ú[™OçL,*ÿŠÅä¿£p¶%p2+Ù*´ÅOa`KØ"‹Åjúƒ* ²lÇ´Ýí‰Á|a;»"UïL!Ý]¥ªVLsO ÞˆÓƒ|LäaµÉ˜Š«óC§×J‹‘žòp ³Ï8“Á´÷äÅ„ÿúÄ©ÿÄÔÓ&mZDÕ]5_V§6&ÖºõèçôoGC*¤B£œ/a‚P‘•ë¸Œ?{ZÃTui®µÂÈæ
+:…›PsÐö…–”A§¼…ûT¶øÍ1ø¶™êM´ uµÛ ‚L@5ÎPκt‹ÄBi3•@8ástÝG…‘|v’üœ*O‹>dÓýÈr{„Ã4C‡Á‘éØåwR˜Öᡸ=_4î6ùh ‚F¦ZßÇ0—ØIq Ñ&–C?ÀM‘Y?xz‡tuó™éÁ,°!Œmâ
+°yt3-ävö¢µ³Ö=LAŒ¦ ‰À6„Sá4f¬Øe">¬Ã-ÚeQ1v‡X< ]&ö0
+uJfÙhüÆÐo“e™Áí<œ8d× º/¤²
+P"`ßÜ $²»J °‚„ˆÎ€Ë'ß|mêô’ôòÁ#p¶ÈZˆØëÂcâÒé,™<à$æ²C‘R…¢ø¥=œC« ždXFñ}‰„„3-²kÁûC‘Öá¡´ÆùªZÝésBü¶Qˆ‰¤fÊÞÌìK%ÖK†‚‚ÕŒôÁ+&ÆOÝ$‘ ÝŽØj©›Õ¦qY}§Oú¾èŽß|¸rI·IåΚ‚-DÇŒ$2S’E
+Ô“¼pïj9†q8d¢¯s\¹Ò©ŸÙ0LkCfÈßRÔZA®ÎÎê Dn3®q¶ä0…I[i±a@6(BW‚ðZÇü!OE~“²tO_¦ÔfÏüËʱz‚ô YɘëÁîžÚï±NÇ0iem£õ‡s´ÿ¨X^s-šÜªõ…Ìï¡¢øjà4¢ïH‹E:’õÆç7ÔŒ¿lj8AIr tÏ×iÂÑwùå!ÝÞñ)Hß vcÀÃèÆ7ÈûÄžP+•ýëÄZ7}?±_ùAsRH¤ŒÚ]ì÷Ê¢ô®š¾¡Rµ~ »à+à¥siNÿ†þô¿ŠªëG“­zá)™$­z¸  ý¯æ@5è±ÙöZqìKPLþ—ñ:I’9¢
+ÍÄ;µ~X§ =Î…°O¹IÈû¹ ¹w#$wùpàI;žæöåÞéK‘ªÉ4FwJ†‡lÛ|œ3¶>ûF‰•KYÎùÄ÷9\ë}¾x'Á3ÈØp ƒÓˆ9¨f
+]CöÛ¸·çæú4ó=òNms·‹äv¾.ÅZx½}Ü‹ü^;Hã8r
+Šz/Woh~÷í±D”b‚ë¨×Üê­(a‹ †ä½|Xç{}(yÏ£E˜–«¨ñsëXÇ°êh9Ĉ9B'8žÙT!Bt—ªõµÕ[‘ïè|öa/¦ü¹ä‹4þüp«/E¿m´{áIGS—qõx&¤s-û(ñO‹Ö%ž÷ÑÜm¬vÿ­§UúìáLœb–†Ê´x©yå& l–DDgq,ŒÈ-ç0pþÄu½^í¿+úNß%äm
+¶ô<h†xòõç¶,CAÐ$ã--Í
+WÞ‹Oê .êÀ2o1hë9ŠˆhØØ×®e(Cå5èQ¹ÄŒìñ¤0q4Q27S2›*´ÙLîˆÕ‹uê{Zã]×Ñ'¤ÆžŸ÷Ýíº’5,cU†•ÌWX ÷;­”n ìõÝA ¨^møM]Üö!U¼…^Xªùáç’7kû^Ä"Gº¼qXðÇÓiâÆmoº=^Šéçx™ÛlI0òÚ~½bž¡lžg¿PB㞘e»¼2'Ùùì}lQG«u®d*Š²¼ÞðÐ0¨-åîE'>=y*¨¯ã+br$í½M³§‰?¥·)^5{q…½R¹™¸}NÄé5òŽÅhEžuÏ¢
+¼?6)  o½èòZÞ/ó:¤—•„ì3µ{½;ÿ8õ¯\ŸZ—À<œ/Âÿª
+ߊ~*Z;yÅõQ]œÇ—ú·…T?”
+5~Þ8GfÂqÒô‹·JÚgĻݛ®lˆïå±[
+ExïÃí‰`áD¥•lP¯;J–*8wx7E 1›¨cx¡ªñƒ¡ïÆ®øCÍq#›|ó ªD\Rb݈yà4Wùî¨V «Þm½iè(""ìGA—Í€¬ŒnóM% LT4=[ žlĬA¥M1SÂí’Ÿ=½å‹vh
+A@¸Ôuz°êö
+Çk«íŒ²ñ·x«ݹDxh¹ú‰q×°0(ÓËÝAiÆ8žáYKÈìi]Õ< £–ÓÇ3þ:ÿÿ«Èv9¯ c®&]€%qÿõºY {J[“äð¥g•:_ˆ$%V˜Ä³³O;ô¾•f©Þl§Žð¤½t¯û9EÆK ì­¯Ct –Ñuþ"]ײ»FRØyF'¸Çy+
+àgCŽ×¸÷ÕøåÚ©/Ë)
+i$ؘü£oÕ˜v'8±—ðò‹fR¢Î~ >¬‹ÓM»Cwö=e•±Ç‘FdÆÍáê
+ÔуP ïjFMj€ÝcêÚ½+[sü‡ñ2G’ãX‚è æ#SË}ióE¨ÿ4RDÞŸÏ3"Ljª,¢ÐL{ç¾ô¼¹„LbÎïkt¤Ê©ñ{ïÖ7Yî£ÖaY ^ ÇnG›áY¥ÔʤÓlîL!obÞsúyx)ø»ó°îpÑf—7æ© ÂÔQNn=É^™ˆh ,yfÆLŽ¼)æE·Wcñæß{ÃîíÈ+
+)èÚ†°ã[!ÉrÒ`D/("ª.À¤Ç¯ ŠJ—"{@w1p-tÙ¯—r´=ŽÞ6­l„HCêõÉÛf©
+ N ™.W=Â:ÂC·  ÕW©®ìÚD!%ËŸäq€Ø€.¢†s[Z‡„¹Øˉ=+Ÿ2<ˆCÄ00ÇÙ[Õ bP⽿81Þ‡)åÝ4‘õÉMÓÒ4µ
+ã.]®À’`=šìýTO ³/¬ÕXÒÈFÍ÷p…à ‰G‚µr—†o9÷Ö4¨eªR€ááRà‹ÜÍ…›F[s€1¼“i‰µèÑ6#̨ºÓ:Y­¯+.¹–3¬x‘Á[d¾q’“+uw(|‰ö§%¥¶ø¬ÖÐ@d+¾ œÒ,žÞ3nÉá_Uë ‚ÿcf©Aài>ßþzûíÿoáý÷?ß~ûû-¾ÿï4 KË* ¬´t
+¬5*ƒ½ü!L*ró† sPC…—a‡ò®YìcQ+/Œ—œ!_XfÕwaˆ¬t ’£a ¡!k6P[¦P¨0ƒú@¡'Åd+ÅÒØ "£HÑÊ RIcQú)ø´›c±°\¡ÏäÛRÈK\{ÓZß’áq.AgˆiP—by_•àtäRìN8†Jɦ£A:S%Ï5Ó~ÅrA¶8¶@èv” cþý‰"
+ï½ Ë:2kæ™…úUÁÕ&á«7†&tÓ©êêlJÄ÷·ÝjŒÂr¯7ŒƒöŸò6!‚‰_jï1 ‚>(÷†5G 0Ž°4SRkY·IG–8Lß1DeK=4Å L]W›JS סÔÁõ2“6¬3î !iÆÔ·Ê]û*ü tiÃuäHc5
+QUu1\¥æÂoŽæOÉ÷î ¼h’Qú=—vnÈ5/(Ÿ’kññC†JpÈàƒ´ÆäTø d÷—"|ráz^G& CõÓOƒ*“Á”$£AÔ”¸S„$Ù­¨ä
+G#k¶JŒ¥ã?ÁAµ†”é„´Š‚ÆìR–<}
+>¢Weµl1Ƨ•’ÞÐAŒ,®‰÷GÈVAá´E˜ÃÇ&÷5ž]ÙÑ Œ”²Fìi Þte„+n<­ƒ+¦S±‚
+’ w ÿw*¤E¢LÇÊB:/6ˆÂx•±·Bsi¹Ï¶']Ñ;ædU‡’1¹2–ŽØ]9Íû¹ç–8&BN¯»-¸
+nY3º¯¤%ÕÈq%[ÞAøåïÇìÂÖU¬ÑýRUŽºlúA¤¢\è‚QÓ0¤Åz>5 æAãEÅ·±ã°)Ö)¬ø¡éÓ-£ÈÐ#GÉÆ‹F£Û Ç¥ª“'$>Ì.ˆ(¢:ëçãw_g(Z!ná´/¶’P³CP:¤…Hâ<©€!ÃpÞçÛTBYv$®áDc3ÿòVñU¶+4Ë„1ñBÆÝ7Pÿ€JKÀf|…›Ì +Zº“÷JÀžÝz–Í훺ï%FÌ4›‡žšÇJÓ·³-º× `[Ú
+*•>Dõ¶ ývœÀŸ1ß_™Òo6Ì…#ÀltT5¨ð8>ÈìæH‹#š v¨*­@÷h»Þ^QYÌÇúOù¥oÇí^!M]{as’™ÞFü+ i´\ônU@#V}¢ñ—$O&‘(fôŒ¿§rL ’2¼Í/ë5@c6¸µ~Q=©_€äå¸{@ñ³D%{ù ¢t+‹sBƒà²±Š/Èö†ü@óÁž–ɲFÜÂRìU1…Ð¥¸±³âø<UëÚ°ß „Dä¨gþ LÀÀ5Ю…#Í04ürR½ ŸW‹šîâŽ,±¸q\¥À)±=ïˆQb<š˜ß ”¨cб_ixÄ¢Œ:7q(×6|+·ÛèCÁ 夽oˆ°¼fŸ_ƶÂW‘­j=A.úùvÂœZ=ã atT»—×A§ñ»m÷èB ÇѺ‚½¬x0¨XS
+±ÇúãTpÿRôä‚À夳f2?e*IfJ´-‚º²ne› l<•S¢°.C2¥²ˆÏ{¢ªZ6­º@4)¨l?ZÈ “6d˜Òkܬh¤iÜaœÇu€ ¦–vï×ø¨$1Is
+ðØ×¹yBâ,cáÚåÑél’–—‚Že[:ZùSÕOnŸkZnLÒÙìÓʲÑõ¼“ÇìKÃçjd²f¨!R\¶5RnB(½iû( a,ûid@‘©6X¢;wcôÆŒâ@1& `1Ú$$[„*¡¥Q*–b³ù½.Eÿþ
+< ½¯ƒ‚5üJŽ!M[)#ê@(½øûò…ÈØsšþ~'¸x©òIîþk*Ís‡¾Üú[Œ–û†95bÒ-Ob~ìÃm¯W0w·}…ÜͶ¹ò0-ÞͶ ƒÂð§Ïþ`¶eºåïãìµA%ÁÞSìg“ÉG!’›Úâ;-r,‘B§§uèFX Ø'¾˜íkN^û€¹YmF‘—÷(G£­;Aî,žf9Øh{:Qµ+»·ÁìèD.²ìá賌‰Æα?Ûl<=y“"…ù`³AaŒa5]6ˆŠ^Ô‚Û§½¸ìäà²ï˜S‡3…l „Ô_fî¶ÝK ƒËþS8Ÿdâæ¿$rÔeÙ|¾÷Lj
+Š:Q™ºŠ$+ò}È«"*8çX•O
+̆©»MïL^aÐñtV×ô1ØŸ¤Ë’Ù@H¯R/n­T[‡ùŽ™á«Óå,!¯|^g‰ŒÌsÊOt› =HLvší@:9o´:(b_f$¹ƒÚ¹h=7ƒÈï‹A[ƒ`pÑt~›ú •ÉGÌ5bvfέXÝaë°s‹‹á|*Ú òØêèD&EþL? ¦ˆ ™‡N¹·J0bÐøÔí%êÞ
+'këàmÎöîì"lȸê8!°¬™Ÿ(zÈØí.˜†žÓ XÖ毇Ë%p…¶-6¶ªÄü "v&Ð6+Bÿ‡ñ2InÈ¡è rŸ Õó°v–¾…·òý·y¿ÐÙŒ’”«(
+êýñ Céùѽ…Bã·$æîÉäE¡•ÉböÜúb²ÿ°Tðê îz¤+ój!|\‡ï:0¸¯ÎgÆ?°ù|œ燿ÑcY Ž©BoÀ¸• ÂÈÇ"ØV
+N&p!®O…ÌZÉ^ðuÒÕyB=džT…Ù`È~ä0ÏXG<À?P›œ‹Å7œhzÉyN™{xßJ@[b³e¾BÔ&×Æåy›ã
+ƒN’Ÿ•õÕš1ULoc‰Ú.Ñ,0Ññ~µöq]Õäô0â£=¡®RZv€j|hW¿5pF7 Ìí¡0ü^2v“7&M YØ=}„·8%ϱá¹DÖ>gœ8ovÇ‘ù&hÕKчuüvûºS" &HëƒW7Ìž¼Å8uæj¯¢´kƒ‡'Ä¡â~uü³íµ&RNe
+eò7ôÁC3‡ˆ3GwæyT:fóå9?•øVpPJ{·ÊBÇô˜4#"
+Ô$Ľ8ï‹L=ë»ÜÅ„cEØiÅ0@ðÌ ‚1|~?ÛLµ/‰Q›°}-y¶«ßåj¿ýóW¦Çð"W§9”æýÿR<#_SûñPI'j`Q!Ãðö½•©Ñ‚G¬VdxV§YŸ)?wx[5 ³î,s³Cbá¶-RYÓ–Á3&¹ è;¬o *s“±=%2ÐûSÜbŒd%±pgÝ|â.‹H*—¢oŠpSÜSo?¼ˆKáuaëÆŠ#Õ0¨V1 S Yî¹<¬Uô…ì.FºxÅŸ¶“ò)eÄ;4Ø­ÈÁï¶m™¢˜Ä²W9ÿúÉ…Žè ÏtRàTp>fæè7Æ´êøâíFxèÒRH8´_Ñ´ì¿aŒ*QêÍ.?Oå¥Z½‘Â)aÚÈ­낃ÅHÓØ%×(ƒ VÚåØx)b²ú'`øñ¦èˆó$@±Ýë(Ó$%>…»:¨!„¥²ÃÇa92ÌC-1O€ÆOOõ{ÙD@ˆ#ñ6\Ϧüòî¯æþÀ™ mëo×á3J›Ù)Ì}‡BYxÈëÑ((‰aàÈ2«çN2cxr~! †Lš*D}¿ÚàSÐJŒ)–ÃÇŠ@‹«bt–ïƒé$?ÁÓÑP¦ÝÊ=y˜n½ш!Á‡†XÜý¥Ãÿ³(+bu<>Û`q)RP¢;èò
+C&8l9B$W-ÿ,×X
+x€“ó õ ² %ûSÁ³Áž¸×®2ö>3½ÛŠp!¸ç}È37&T'JXtµ&œž¤®Š8ó¼Â?á‡Ò«¬k`")bÑÒÇe \:ÌËH{ù+Ž»¦˜©Õ‰/¦ß ú©z©0*Oä÷…þ!Å’Nš4_ øëMçI‚Ìt…ä3Ñ2¼„>€ Tv®a%¼ч^?,˜ì>ÿ3þNMé>IÉ´Oï%‹½ÙqÖ:ý¤*¬.ÿ<è9z0]ë|“D áVr¶ê|@È©Çz»ŽÍ@S½cÈFÂkHuo 3/(Ë6f)Â`ÀvœŽPÌÎ^Iš_D.Üt< SŒf
+be’d!ÂTo.ñ‹+<²¸ Ä}ž¡)¥ZÎKô¥hU‘çí9ÛÑî½ô:ã9Ÿ`ò`ó‰Óañ.ˆ
+²Íø©`p/Q
+cþ—ÍÎKQþ2‡"±FX5;6þ³DÒ´ 4FfÙ~1Í«°üá²6€)(bÑŸ>É[Ç5¼¦À±d4P=–µp¶œçÔ÷ÓJŸÅ½'¦œl~r#^·’˜R¶âw@3ß×i§_ˆa:ïIØc(ë.¯U~käáçŪkØ&. ‘DOÛŠò‚‡Ò€d›óAa²ê†­VóÞðÐ%íÛJ’R‰q˜ºeÈ“145Õl¸`«“3AàE2qh³¸nØkr茫¹ÅSAËr§´ÌïÅ„\B`KrÇpëLG3Gœ¡íK‰÷˜ëÐ.ž¸¿Y‡ † åvV"Ï[ö”½Ê7 D£1GWF¹k€ÒYk‚%(¢…M«Þ/×m¦>踴9í^„¼*¯?z¾Š?\À6´•uËk…?ùr¸ó$Û*ðRKú¶nq(ýÁ õ+(ÒyLÄšÞ!Í?H·fWÈg—PÈ#³Ôü͹åÀë±¾(F+ËáDÅŸlŒ¿A†Ú}m#6ú/RûSÄ5û@Ÿ©¹1Î/¯™é¨‹ø÷5—ʈT¿þ.\‚z˜Æ“O Kâ ùŽ¶ ñ Ö†³Û•ÛÏÝ n†ÀG.ü >™5Wå葹±Ó(2ð]„OǾÿu)ⱎ›!½1ÔÅ–ÚK ýºHÛµÄt©Ág×"ÜAÁx0ùÐ÷Á%øa óÄÆÅ°¼ÏªÓJŠTçYÕ=™‡qÀˆV4QŽšôØä"ÍÐôV ¬Ï*×ÇxµE"¢ÂaÇùÖ^‚
+¼­€(Ì1jNéý§¾¯Qø:Ÿ]m)P@ò Ôð†fD¦†àZx'[基JGÊ2ʆߘxñãc‡ï¦‹uÔÇÜφ0™È ï¸õÑÿaj(ůuè&q‡ ÆÆ´!É¿Mo,yAÞ´ç½mÄ‹ â×£:sÑh Œ@ˆé ó3Æ$~’tê1à†á~C=™€¼i DZ„¹ÖÑ?Ü»ÂéòòñLéaÆ«õv‘ö*Ô=¿&˜üƪ«Ž.ÇÔÓ˜W*ï›@ÚÅMQ®ä"YÚ2±N9oH"Ž˜hqZ
+Ö­WYç"Y²÷Êò¢ADš¸ŸeØRÑ»ß&)ìBZì¹?|±‰èúhÇà«)IS.ð/õ$òÓXf÷)¤^™ô[g6yÌÂp[ìÞ58Ú_xþuÈ÷ åøäµ$<©¢N
+‡×x&lݶól³ÀP Ê°Ÿ-³•õFs¦@’!T“­<]x‹?a¢K£µcÊ••Fˆ¬‡ !ÌÊás¾h¦ä|ûó¯
+ XÑ0?j¾zžFROœÔ¥Ýò…%Ì@øNÕo—Åù1÷[~¼Â¦ØhH­©P´ƒ!¨6‘Ñ&Sf¢éÏpß1_²¥¾ÌY”T'_Ìv¢ã¸L§.áù2s<þ5†$]‘ªp…ƒxg±Lp” •ùZ *2è¦ÛËH8¢/7³NfÑ° Z>Ûçàº!7å,ÏX²M\ÊTÎ!Ôi`<^B„•/,ØÜ3ŒÉ`ÀÛ¬e /á) ñÖÝé"çàѱz[ ŒYevRjë¼ëör.Oòà’'e4–ÍðÄŒ}y½\ö_—Öá^’~¶° ÓKŒÍägê\À4ó3ø8¿¡Mí•œ¾Bc
+2€®çæaŒ¥ÑÈêö æÔnÊdœÜ„›ì=ºm
+¹!œ ËA(þ iÅíc¤ú¨æ´%Ý’ðÃüŒÝî»—wÐåœG¦/pÈöÛ(á
+ºQå‚+‹T0P`ŒÞƒ—W/ñ{%~³œJW¸üt!­ïÍ Å/ã 4õ:ùéœË>*¿–ãô ¯„PÍêÚù[Ôoç…‡ÆB\fÿŸ½ FLÆÒèX!nÛr÷Û·­û¦{ŸEû‰# ÖZ…wZ†ìLémÏŽvª¢géz…“»É !"¸°ˆ•BqT‘eëpNG$T*¶•"ϼÏ1[‡Æëˆã·Üsëg”ŸX5+„ÏaÕ¸=.U[§3§’ù|©/Í‚bf’‘Iêªú½”
+ ªJ¦÷ób‡Á }!Ûý @Ìådg¹äþ1veQ‘ §~|‚Áý–ùÓ¡ÕF[ÚñÊ|Š
+lÁ÷®àw÷¹LÁ¿…”€õ{æ?Ÿ\ReèQ^|_‡9ÂcS¹è‚Qc›»šrLXdH ÛåPàÍ9Ç0º~+Ëšpú¶| ‘1QB†ßüÌ(½9Ï+þá¶øÒœ~yHø‘­ÏuCø&Tl(šOÙÔ¸Š'¥;fB˜–‡†ܵƢRì+Y @_»<“%%íA9%
+×Að>V™¦bè±™*Oà+Úù ã(‰Ý2æ"°ßÅ{Q á•„ò>¥1MZmfÎ'u’;†ç-‚0ê@‡£^çK7ôŽ^³J¬ö>;Ê{È¢Å!©*»ÂàyÌ ‘ש”–÷
+“Zü†g|-nŸö½Ô+%r›âS2
+RºfÞÜŸÂ[ZäqÜÃ7›Mž1œº•IÐ{~맴‹»]«ùL1›N¿—Ã- kn¨&Ï·Aígò±P+4>"Ó•ø>\~LêÍ?iÖ—1·½Ø|:.- žîÜÿÇu…r¾MÚ·Y¦#ÔûÑä…Ök_0¹ra™Ý ,Ö†`­†)µÐ G¦Oœ¿?}Ž¯žðúÔÐ×në
+Z’QvªŽ"X9Ù†z¢ÎôY—NL2BâµÁX^ñ!­|ÖJ›hJ®Ã;nXhña'ä8U°!ÿ 0
+H‰Œ—M’c7„OÐw¨ Œ‚
+󅘣¥ îé÷[Þ@•ÉaS¸ª¯ÇáîÔ¡q
+ « ºXu(æßuÑ ‚àÚ¬÷O1¨B4~l»sæ„Ÿnmø‚PæÙ“’MËð$DÒ°o‚®ôµlDª‡Cg(.uN TcF ŠÎ]„Í¥QA6ãR¡9Ç*æ;(ƒ%;¿‘qójFó¹"?=¾OF
+<`‹¢}ŒSè@ètÂ{îý{
+KÞ<Kÿèס‘|-çQléŠIÂÕùAl‹2ÒŒ~³û1ª¤8z„Ý¢
+S|Xn­Í ›[2 úÝ¢d¯Ñ€zË$ㆿ}on¾Ðe®·Èä9’_'Ú³ QHfÄ¿¹ùBàÐ榤z/‘Sß²mh eh«w
+Bä°GÅ‚P9T½gi÷I–ªâ“˜§Y‹9Ÿ9†ð.åœ;tí5œÈqÈ:)T5:jG®ž½ZÙ(ϱš/}“@¢ê w=žSG$:¸¼ë ?Г.W?*ž÷Ìó>)ÞüÙ£%ê0Dç¾
+‡Ï9™oo%@ÇšDŒ«BÇP½šz •¿e*bÕóT<ÓœuM¶èy
+ˆõâ;n'“¶Ü è¥î¿?€wT®FÛΓÌBYñÞ$pZIÏ3¤wnjJ‹Ù}¯Q¦Õ¥Ôfrç¸6]ÃEl5­Œ3#ëáër2¼Ÿ½5vú “o¦œŽÁ¡ÕÇS¼&]+rjދᨇ±ʵéVwòJ†c½ãÁ°e$ûd0‰b}D8·® Oçe7;ËMâƒÉí½=á†P;6ßsè…Mò5¦jÛó¦¤åÚ?‡±-1eÊDÞú¶¦^ìÕÇ€xµ*Êy•}ǘã!Y²‚~p[×»^0¿ÿä=ëÙ”¹”ÀWÝ[@xCÁÖ³¬8jFönòa~…ÑÕ¢8„IHºqÒ£)ìµßv, J3ü“°Rzàqðw~]:¢ÕBiý°¸,?ÓÏ3sû=Ø'†±ÅÐWб8
+F§ôú±b/˜“ÉÃ0o:­«å@ÑAÔSVìéñK£G5ŸÎA àxg˜ÍÝ-pø÷}YoÞ+þׇ¼NÞ´ 8±šùUŠä×ê ‹úe+›ñéú²1Iƽ• ãå“0ù×Q»³Æ0‰±Ïk3>'ÆÛ_@fSke¾®6NT'QD¿—Y¢ŸÕÅ£tæÜéßFþÏNõÔýšžDï
+:ðøýIï<þ¿Ý<Fœi-­)!ÛfT!øÞ¤Ôcñø
+· V¶w)˧
+¾¨Ö°ÿ1^æH’ÝV]Aï¡m˜SQ4ËÕ
+:äMí_çÙUùßWgP¤ì›øÀî@šû-CÝ€ f7>¢/+ß7!?«ë%f©S$H uN;31´AòbnX“rê^èýV<]%Êh3#ål ‹±oòÑ‚B8°(ÌÎCc Qƶ‹„}è|˜gv“EÄC‡_)'çÞ*q’îDöBg›¸oL›"¹2–`çŖaž£K›ì ,«¤ }og}©w—Ãlö,\5k5iÝ0ˆ*‡z!ä'‚BtLèrä¿k\K&ÓqüK‡ä2€¶wt2rŸP­ L–º€L‡zÓÍo››;®_¹´ßS04Bmˆ$cÄÞã`Œö)…ÚyÞ”Ô£Ð4Émí¿pPåÌ Ô5úlDþé8M•/ÈUȳòìXß·±ÍoòdjúÙ;˜jÆrõík® T‡³£%9©YÏòUy½+Iàp/Ìríî¬'ܧüt›âÍÆÄ·)~†C{ò÷.²ÐL[ä?& Äq*­²®‚чø˜žhÔ±$Y¬r\YÜ·ÈÙ$kU?%a”¾!3ÁŽ”ãL:›šp€ÊÓ ˜Á4Óqêï?<üƒçÄã…vR‰ì=?Ø…‡-û3h.”ä!ÜqïÞ3H“Á?ùÝ´¯vmäV½½òç,6Ôií$'PŒ8/}CüÚSA¿ñ=8‹‘üc2ߦ «nvV“…€•óîVf©i.K;O™Ñ%ì}Ö¢ì^0^u2ãva†ëmŸ0n°d!ÐÖ(^îÍ}¾°5+4þü¤œ ,§ˆÂ˜¿òÔ„}] & gÃHYÍÜôHß\
+ÍÂužÕÌB°ìå{Øש×#×jÀ‚å]è0çxc›Äéô¡D¨ä¸¯¢iHr°sÃ8Ë"qe;†¯&®‡~Ïz‰«:šÀPΗž@myiŠ ‡.Æ\—‘´!alHÅÔí¡T~?Šm40-iàˆØçˆ{1Û©âˆðqñ€È­ƒ\÷)l ¿
+òÜ 9B]dN„`K‚é’$òîvü ôùÊXh‚Âí¡AÈ=>¯°'èä6 †zü7Ú.¨È!SWŠ½¢Ó‡;°O XÂbS5h7W–+Í77Dd™±™¹þÏÎ:VY›²!S¦Ža¿7¡¢u {uY¢Ur>ÙyHeËÿ`CÔhá\Œ†‰%SrÔËšØ+ÄK£¨5X gísp²¸¼Õ°†!Š(fP£µE ðB1Ç“HuˆX«ón7ÆF›Ãé}…HÍ4N“Ž¬Ò¡v.‡I³‘­ç€Ó™ž_¯Œ˜¦ñ¯3ÿúÏ¿þ»© †”¹ž´7Øo¸-ÂÍ}ȱK,â'`_³|“ú¸!Evœ—-ÆuAßsÚ‚p㬠‹gÉS|%ê‚ y´V´KuXÎ)Ì5LÂ(Æä3½ûåܨT‚/ÿ! Qxrf
+k•q÷çS já­{`3É‚‚s”„1V²ÈÃ*Ì㤙Œ aúSÇßgéù©É2²¥Çç~5rÿì+uE9¤ MvÌž9±{°8Ï|goìRËöok„i¤ÌÁLT †qoe?§‚o–Å+záRÚµŽ€aVŽB Èiß­p ”gâ¡–Éù; ¡ÕÊMA«íIv ¢·¨m§iûSì/ÿ¯_%d™Q˜’ÝL«
+ø§Óu¸‚r±ûÝôJѤæ™F®ÅZJ Aœ §£ÀÄ42Þr·¡ÈÁ¶® •æ@lkÀÈ‚÷~s I–BMÙÓ¹ ã„ÏdF݈?)±è ëQ¨ááæ‡ö(T$³‘94ÕŠ£èÃņûô ;³¥ÃÀÈ\ágZlƒà! ÷ž£Ù©càWÄ;¶æý‡BÒbÔuqC ·­s
+É$¬W“VH§À!õz[S› f$Ä(Ë;µ~* ã²rü4ÛdPÙÖäîÝO£J4Û¤©“¾ֳê •ðî!¬#šŸfEͽŸt‡:DqÈÈWX¿Ú8°|ø·åa÷³/ oúDE¸/EŽúU·—ϽzÚRØŸ@òÙÛ\ç.•#dÔŒ}7·!Æ.Eĸ-”úÊœ †( áRÎ}gèŒ62?ØÂã.<„ò+GàQÊÝ)Mňò¥Íi܆`ÌÙRþ¶=Ž]$Êç¼ÿð@Š4Ü?…Þ`ò‚×{<×áì!ÒÍïF!ºhe´ !"qûœšÙà_¨T,J~¼<á*˜Ûrœ«‚Sƒ¡êyy‚±˜úÞbw]üS‰½,@£Xc¹Ý¾IÃ9E)m"”1ý»ð£A àlëÝ›˜\"ôˆS,~m.ƒu­°ùÚ¨_¯ ñÇ#1ä&íæu9ô8¯Çýsƒ‰Ä¹Œ{–cü¹ -‹ý¸íïZsÎ@ÐÜX1ˆ½ÆçÌÍ ¥Fñ—ëœõ8Ì"é ßà[Þç¾;¾YƒÊÍJ”iÉþ)*ž‚Qzóï‚å•TPMwoÂrb7zn¬nñk#þ`ƒ™<Æʯ°ùÚ¨÷æ©ïŸ7 n3H…©·—¿±xdšˆ +µ^^®
+.K‡3Ê"‡ ¾÷á¢^Wž|VÀËb]Ïè0žîŽÉ¿ÍU0˜úÒ¸{cž µí8ÝçÂ\–Eå8aÈGw!C¡²`™$HOýßÅ\’…ðñK5!¥Z†£‘kq=úãN#ª¹Æ¤·Á,YßûÜ *Øvò±…X‰1Ãj¢ûÑXMbõ7&½M,jD;½¥ZËoorå*ãïžC$“XC%õ±yÐ1ׯÅÚE$“Úf¤°›]faˆPi=äNÞb
+àÀ–ÃÍ9eݦˆÈ‡G ÒeáÊDPËÝ«È@d²I"•»çTLbTõÄpÖÄ]y¬sƒäœÖ±›ž”;—c]÷–?ƒd,•F vƒþ,_Ä¥ñÂL_ùUäfí¢¨ ;üy’"1q°}ÏV!MSwûѨ!Ám®
+R£XqÂpÍÇ_@,8O |ö‚âsFHk*ýFaFˆýA×F%Rä ’ß©ôF²áT.Ó>,Da  ”Á×o:•H\N°•~s
+Ma´HIí¸3Þ™¦"·¿ùè6'Evz kB¥ðäîÕ3ÈíC\Lª
+æû­z=sòç+Äý;’¤å# Wú´¾–Éè"ÐðÝæø4ßhNB/Ôôq‚öŠRkÂÑ®›y ,HmÒoÙ ¹ñ;¢I˶?lRžÓƒwÛ^Ò~g“×uÈ13H;ß””áøRÏîa†#œ^kó2窢M )J=7>…`’ªôóî戉&tÔÇPw¢²Uê"}K5þñ2G’ã¢è æ´iL`_LŸru†¼¡©ûë}d¢ÉîB‘4!µrP@.ÿ¿ˆ¿Šª•„¡±ñìOqàÚ"Ž u¹Gè VI{+%
+Ê!IŠw¤s=›"Z¬yCùJmšäf—mA5
+ÆT`+(îà5‡ Ï-˜èåÃû,¨Ší“–%¨ ÿ…Azˆ¡/Š†ú¬Wf™Ý"–Ô#±¦‡ª4!(R©¤® ÖÛ@Ê‚\ÍŽ‘Vð唦kÓàþL75^ÅŠ(ùD@Ë!d½ –…vjýTâl‚,¿Máv¹«¨.§³IXï!]´.–fô¼P‚†Z•j_Êðï  $Qæ_4Fe@†ÁŸGG²ƒdI¬ 2ó°XñT@!r9¿1ucËáñ[¹t‘­,îÉ¢zŒ/ÊŠºy·×Î
+f¬z5ôrÐm–­©üŸž@#»ï/ýºƒÄu_ÿÁ¹ÿú÷íëŽx•î¤;jÑ…œrè¯Ô0 l'®¾«( £Jù³¿â%h… Î¤C­î_/¨ÈÀ+F²™¨ä’R¸¢çѱJ×#ˆ!ÿsñp{ì
+µGØvš mËVŠ]N;Ť%¥Yå\¬ßýáÊ,ð 7€§Ò×¹6˜Çjò,ªøF¿×”]$_êC§–eUY$Ì`K?}@ßL¯àUáД_!B¾)‘-Q—¿¬R ¤Hœß:²&Ì]—ŸB"µÑfÇzêÝq z‡Ï› ×VÔ•Yb˜ÐÏ«ª‡áæš A–µÖð¯íò®-}‘,Õ¶J0سd] ,õfx²ÅÆ»sxW^>ý6,ž|=*ê±”Š í­m9J•ÄŒ†Ew‚2[™Qý,¨ò¦´g;£€²ªÎòÙÂà4Ægø—Ê ãYhãÞzP÷€Ò…±­z^ƒæ‚<Ÿ²™Ç5É„dIRÑRúyDÞÑyj&ª3©ƒ6È—ò$Šèø–º‚¬ˆRFrõƒpÓØÑZ.2ƒá1°&Ø—ÔRv
+tBwÑc{½‚45ž]£Z=#Æ…±rñ¾`ß ì9¨ú¸;reqÔJº=RÒeá#±y%¿/Ò#1]eìO ´$ïm:3âj‰„hÀì@#l4ð»~î@þ&j![õÑ•6žRªýn>’ÕÇtت¥ÎA<S5¢«9¨RËfµÿ2C¸‘À_ë¨A`mïl‡ô‘#ß1††0’MPßäö$ðå`’UWÅáˆ
+YãET òfm$’2 ÍÛ¸0‰ à }Å?%EÆ÷‘™4ìÓ‚3ÑC8…î:>z¼‰Ãˆ ‚^ÀN—7‚d)µ ÈɯŒö&ˆfíz
+Q!„Ð[ßpÐT°Ç1ÃȪc' ÙŸz z¢»²DIS6ÅkðLõXŸÅnêï!4i
+Á<¢6Ü´·7†‡dFqBñÖŠ 'Vô¸0ÌŒ´`ŒBÿ"ѵ—Ñ·ž:’uoN&ÐZº,%÷ät%NÛ
+ÿû&„‘Ä~ÑcpwOÃKåD ‘Ž,‡ðs¦<®4Úg¼Ê—Wnþ*°VQÆ&IÍ]BÅÇ«ð3À;ÚçHøghA±s€h ^ô5lX9Ù/¹Ó°d´„û^ŽÊ¤Ë“´jìi›ÓøéÆ_ª‡ÄÑ^ÛAøWìO69A²“Næ踯ÑÃø1P°•ŸEW
+ »åý)~$‘¯é~F×N-]Fm!“?ra·3Üë„•R?Gà#¬Y[Xz|èç1Ð&ýh§ÈÌÊZ&œpÐáU2[ˆš(ñOóx‡ÁãOò¶M†Ïê‡  7å6×Çgc½òB5—ʘxØý m$Jmêñ”¢/ã>9×èo&ïR-Í™7'h:5h›L*¹cØ99–‡»Ðg !¿ÇÍuUŒT¡
+?'JIpð’hofcHCû)Dä‚”3JÜ7úâÅ•™m¬…‘· ObÆHçè?عh{×^I#f—{Ú€EÜÄöa!ý4/X´‹ù´N>’ŒS°rn' \ìgò™ƒÎà*Ö‹œ.>TóÊ×UÞ6¤ ŒÚÝ9èJCÊã2š>ít°‹k¾zš?›œ“Šš¹=¦àfQ-s—3¦©¦gh>ºÏ”©ô™Ã1ä•Vj3é‘Ö`Œ¦7$#´‰ž‡ÕßA&~™2Á@ü¤n.™ttƒÄŒo¢¼\ó.oÀpxêŠHôíß”dA§ía»è‰©f²Qfß‘oíYˆg HR^édÜ·ž‘?²é0õÜEfqáøŽ™‘×LÓ¥ã)|™öT¾jiû*ŠÁ¶2h³í¼<~DeΦ,
+°ï(5ûn üFzžšuŽæÁâœÊ³ËÝ“|½vòT¥·SÐK½ÿ¶ ¥¿h#ZùgA/ÎðyÔ
+¥SgŒBš‡Dàrº,‚+`VQJZ}UÂ3ð1¥bU¢÷”?í­+‚|QÖæ-Hæ™™šØÓMO<…x÷¡b1 {F?ŸC÷¡TÜIÎçÛ¤wÆ‚&’žõ»G¥÷:Q -÷vJ “
+Ñ@ŸÌÑ] jµ!£
+¬Û°^Ïéï,s*O0Ö<ܦ #±mL¢œDr}ª#o]²TËC0^²Cð7Y^FKç B.b{
+b …y[-þªËmE!šõ¹yQÕ…ªòþÔ%;`O›òB~ýrÎñ± bwµz
+ñZ]j~=çÒ9×Û\:ðúªK¿ææ0 ¯þÝLÉÌ¿þó¾üõïÛ×ÿøjŸïË椱Uõ‰¹¿ßÉ• ßÍèË
+ÑgBîÿ3^æHräH=ÁÜòeØÇØb©s‚Q«ï¯Îû€#ÉŒ@4K¡13aq¸ÿÅ6GœŽ‡;¢%ü>
+)£.PÎÚõ{# é5ò
+OµÓ;Ž
+²Ÿ©1­~bÝŠþà ÈW±ÇçÔÖ04MÕóê
+Ùc„8©C˜Úœ!¯aÞ8bȯ÷|ƒøV„\ù-¨é:X2¹ˆºh,à rµv2ƒñÇ_Ú°jÚÈkôCÎ6øû”õôt ‘bÖº½!%Žc΢·-Ï™úµdh£‡•[
+òSnŽÈm_üÏ I¤Ôvn¸Ó557P¤P ôVMKrx€ô–Û‚ ÿDB™à7ƒÍˆ£#L‚Ob|Æ5Ëÿx“5¥7^Ò_R‘ð×Ð=Þ5yœcÐ1Øà>G„¢ˆd?Ô^œ»d Y :@Žx\'ò#’€ƒvîRi€K¥±Z‡šâ «Aû¼êG¼ThãÕXü*^oƒ¬íQp_‡b’.‘Äæ[ÑDð$ÕêËc”\dÓñ`¥¯[5Ù,™²¾:ƒ­Ôˆ¿[žøåÀ2~ÕzÏÂK$ñpqã=ÙžùÄ:ó‘Hø¶®ëâ]ËG
+O©‰Î>/±é:ñ­0îxmõJõùËÃ1m9×”^·iü=BMQcjÅ­|Ù£@B%‚Ì3ꎈYÅ/s¬™³€$º…cÔñrV¸!ºbTö_'‡‹(Á¾SI’Gf)/Æ‚ qW<bÝÖ<)ð ùÖ)š£o-º³êR®š¼ ¦U©•TÄ+~.ÌDL¡Â;˾¾¼†0\çî8ñšÜÅ ,B3¶ ªàP+³!-‰³@+ÝòÔøQ®Æg4fÐE°ègæJºØêZ¦b¡7.çë(¡QFÎãÒ`d£§ó‹ Q"Š/ªä4rŒÆ¯Àqi‹?µ×Ï_î*Á(-9ÇÊI³½qžz{:ùxWŠANêcÏ"ÄÕf¼yób >Äú护òïFLu¦)&Ö£Ö1ãt<ËZ_ æ¥yãP ûÄÙÍH(l«„¡ºWQºŸ7…ÒÃÎGçæuGQêÑX} .Z|‡ÒY¹æQAÃtFwEQñ0²Æ*6ö›ŒZgYƒ+Dù²uÌ’öV7 ZÃ"ÁÉ~d^UFÃãýdäBzñÓÌæ¡)nS…ŠÕ²ëÙËÑÒì@©1Ì'qî÷ñ!N 0Ot£ÂSX‘¡ gƸ€>@‡­g \µÅ7Ð%9Ë¡Vé.IøAß“ñªwú;W*l‰å— B¯>.s¼­‡ õ9 ËUœH¡ '˜×åà³ÙâOÑåÀ41=Ÿ×a"jÒRuòsá”#!ãcn,ƒÅÕÖS¨¿Ä‹yêõ
+¼PõWÇÕRæ!/‘Ö:|KÞ1Öm»Æl^å`–°Ý LÏæz!78OÙn*Ø׃^Ab0ä¯)¢a}3R šMÛ0?VIkøyªeC‰´õ !~žèž ÿ$YÓgÅf„ƒT™Zä¬-†*[‘¼Ô©lwÐ)׆™GQ{Ò[ú6HßGâd8u› ûvßa²Ä•1hêëÔgK"¼©‚t9H¢BØKça'ñû1.j,ØÛ6Zovãk+}$¾ŠÍ:¹†ÂyÖÖ2´K+-æD09œžXêƒ mÚœºq×Q•kbV°öÚ
+Ž H`lAb¤÷ð:ååe;®Ù Cuq’2Þ.±Mg¡oKCÇá‰mzšóÅß]„Þ
+¢Ža.:%ä9²ÐÙ¼ÉW
+®‚P0ÁC KÍuÈ~uÇÙ@uÁŽŒ8öQn„rCnÞ±'8’H\ß¡“l=§8™++‘nû±ä-ïî£Þ‹h¨]Ë Ø¯L‚1ø£»³ÍXÄ‚bz^Ññ ¥ìo° ÑfMbÝ“šñ’%Jmìx„‘ÀêY|R ³<…,•{äËn9žÃšÀE Xhø5–ówä=pq=Éû2%ª†µ*ZfxÙ<ÍéþÌ òè"!?hÐËÑÕ@ïÌ´K°‡Ÿ3ˆ]©¶ôg{yŸi©ÛZ…K‰v› Î4Qy·¹š…½gõ,çCÑ籈n±ÿØÕÁd†ï¯°i…eðg.%]k*ÎI:_¾¸JX8>›²Üî0öˆÙÂÜþö›(fŸÔ€HÒ©7¢ã”?Ã|+qÜH‡H·µ•z÷R‡!¶Ê~†ÅÂ#²©¬†™•„²ûÚ:õ•+¦ò<)•¬¿§}VI„)ÒÞT"`)k?¨©mü¡Ÿõ¦„÷¡âñ°ñÜ…×"¦É ¿û›ÁÖ°X¶™ƒô3î70S á<c¬uarl]$¾2žÊt—ñq˜‰øŸ¸üÊ
+ŽMþ¯8¶æ0Áwê>©žHeÜü²øÍ’H‡ "EóÌ‚NY¦nùà®QÉþuº†T±­ûÞ±<·MûœÀŽè»ã0[Ä«-—í4ôh­hàá£,{"1#¶!öèEj7%­KÃÙ(oõZ4Í[“x€·°—1ƒJØ%5¾Ó‹³‰ñeP‚ê¹Ø§ÄêñKùK7‘ë4˜…|Ä5–¤õ=,ÎQ¡£Eß8ι.Ø
+ðÆþÜ|"ÈP*‘nóBçÅ[]Æ ,ÑÅåL蜜 ÕS[p Mtý$lo³ˆ™'ë;EÿŒNlï§Ñ³bÑv¨mȇÒ-ó\ìÈ…æBíùPôéE=BÖÌÊ3S5hŽd³—ÜÇVQ77 –BùXßK¬ üC?6ð&Ø2ÊòÕaŒ—é»(ksp7ðùÒud¶ R€W´9e¯åÛ _
+0Ê0ög zûŠ´° ŒP¬wXÖ[Úe[\à®Ľ$iB¸/ýÞ>ŠMç*·ß TÁta|s_¦ºä%’Ž%ïNuÚéÀÌS‡²ƒÏòf~•5ûuS$ƒŒG’GGæ‡ÌNKz— PI™h«ssð´àm ¬üËeƒ7 ?àkÒ;ñd
+ýãÑ¢hd!© qÓˆ—呃àáØz£c
+JdÅ+Á/w7#M\Ê]6/_jȆŒŠý àûc½œ2¢j*‡¢OoOT^âÐCÑ,!*P«t¿ªÐ°X mQ¯@ø×|°È)È(úÌlOÅRÒŸöéË"„à=“£„Ç&EjBÙ/E×™Ã:•°YŠ´±ö}Ô¥ˆQ<a4Ñ?Ó¢‰}ôÝ5¨Ò¯Uu_Ï(0|‹wñEöW‚NíìŸBºQ¾4¯æDÐÄ Ò3\ø=’~ÙžótieÛirzU<œá’è)*‰ßÁoÿÒäµ</% 'Ñ8Ìð*Q&ÄùÑáH¤ Ü›í®ÙE1'ã0»$H¤ãäÚ>Jþzˆþm½ŽÏb?0Ÿ›W_IJ9ËÆôKÁÎT7§ÁòÁK9©Ž
+#*!ÕvÚÈ&3SºµJ
+¸a F±Ù´‹Húÿf–ˆ ѽ)yD}¡ÿéK#ôÀ—±CÑçMìfòÒuæ˜ìRżþ.<f/efEßaq%‹v—É»MÅÂŒ¸Ÿ®@«ÓÒ.JÄ<”#Ûý(’&,Ëæw‡WQ†¹Øu
+–ßà¦Z
+' ÝJ< 7 ¯Ú–%¥yËw½í“š ¸ku-2jIò„ôP@4òMƒd…X1¢(b“DúØ|O¼VÉÀ®†šZZ)á.(!c†ñ’¬öˆÉ)YCÍh}d 2dôÏ)H`&þ4å{2ÏÀmqyÍV‚¹Ä•¶'„l+¾gâjÊžëµèN¾ë=¤
+*qäVe1ŠÀAÜj€Cæën¦& @¶e­)Á›PÌ{³Kpž"dPd²âhz–4;Wð8 OýJî$eD>)gñ ]1‚Q¢SòkãWsXœþ9iYÝ0Þí¼Ÿc»ËÜ%Œ-Vœn?§à±ùÀŒ‰xÞ„×S#8Ù:Ó–Å¢0fØŸœªÕµæq§€Üd×}°c®¸«Î~mX\‹Ü‰G®Ÿüý°Üß‹XAB
+÷ª™Å‰åUø„ùñš–H;–^çÓˆJ–¯â\¿KØa4
+²èHk‡†nI¸Öm—Ðb)°ZI¯d¹8e¹ui7e’ÇgÛuò¿".Äô®H(
+^»DÉ…ýcue3T’—ÊcC«]…ç¨Xh”-°«R—ÑçüvXŒ°°«û”•Ð¡Ï°×ðÓLâBãpK
+CŽRyz³¡>—…œ.½¦àÜø5¦µKð-1é»;E(›v‹ˆØ“u¢n1z’ÅÄ¿ò窉OBAvQ„*Õ-‘_­¬JÌê¦'Y_Â
+RswŠnn
+€†çdGm…ñšzè–݃¥­µ¦2v—'(AU “>1¯&‹óðË£Ø1¨ÁÏF¶aVÔ©"Tæ¤M"æÝy^Jì*¤":–ùîB$kÇg}dÇbئ
+–‘•¯ÏWü<߈3*ñ€T.mŠqãi?ÅÖBeýð èjËιQ㤱1Ö7%à o#+Jž}x-bž$ÔŽ'W# ú§WWl«-9‡kÈòÌöUoSñï{g.ä°¤R*
+{`TšåR”⎆𼙶f+A@Ø ÌG<»@Ù¸•v¸?Œ Š²ÏU/ˆ½)âÖ­!`‰Å„t[,8'2¨ÕJøëF"á;b:%€ ôÆHçª×"åP˜²EfÃYóQÂÊg;”(¢HV1F!eÁb 7 χÿÁ•sÜArÀxŸü8–èÀK½O¾êë5i­Q%½¢N¢3P`¥ÇJ[î)C‰Ï€%9ñ2Êlì%@ñ’°7ã›c—`†Ð <
+ØyJ Ú O¢äö<ªDoìvS!Ø
+40"yÜlV|b–15ÊÓJXFøºZxº¸õÿxE¸¥ŽJjtüs8ë2ÁDOkö÷¢¹(P²W&ýðŠ„ þ³ƒ#íÉ\‘°Õ‚/yÀhîü,/WÐœ’_øQÝÌ
+Dÿ€ƒÙÄu2ƳŪsÞã€QÁ–渚@ßÇéá­Æká„‘H]ù}¯EN¾\×Â~¨:EOg…ǯUšÉZty»X¢ ^^Š 'îsj^ŒÆ*!(Iqãpl%émK,æÍüžêálˆ¾š3JèÿÉN˜™›p,HSÒ>Gœ
+Œp$æ°WÑ z¿¨DªEK±9%모ýårˆ=dÿœ¸\,Ñ¥U«¨ô!ʈÌÑv…4$®7Ó]0=H2W7DnERq¾è‡Wyüs¿iq/ß1»Q¿œç:$ýlW,Ô¾•B˜ýÝ9]îŽ6´`% ȵ]B›¢@_Š±.$ÌBTÙž}U–’#®|ZJ¶>ð#Q¢Ê‡mÜÄÀöã¯
+d™1†Ú}ZàCKà
+ZŽ« €.GˆÕáaF—¦VDÒ Ò(o ŒÓôCZÕ©–ºÔñ\“ÄÇ'™l…é)½Û1ì¢\£«‘<{,V¸S"á^!—ýþ8aNžôˆšò²çoƒNÓ÷î-Ð…Ž“u‰]þú÷‡ØÆ‹ô©€åjÿ8åøñóŸ)¹Ð‹ ¼=…Œ“sMX=%ékQ”Ù˜¿˜6¿ØG.z–&
+Íþ.èš‚ŸwòdâÆ—Ú]­µ  Ⱦ5¦ˆÁ;@tÓ,Ÿ ÄÀë³!z
+¸~‹Àc¯‡ADãpQÀ[ƒ¤¨}·áH³Ak,‹ êfÔ
+DÆi2N^´ ÒcÉRDÏÍ2="Õ Â6ƒ‡¬‘Á;áV’"¥jàa 1(¼x¥^ž5$Íà‡ò įUŒ'ÊW“A&"ßpÔÑ
+z<墄‹IÉ>ÀfÚ ÖG jÛõjžë†> ±·âóË3¹ôèwéü’ÌawZ5©ƒ¾¥x€l¦ÒK­Ô»sÏÌøTQ>!,†ˆº>B5¦ÏK×s(-–(ïHü’loß©I4 odóê›þ˜²0öhòK¬#ù­C#…2rr €â긡{ö†ænÂZD¼Ü=‚ŸÛ°s8“C1†¹‡JÀ"±ywò<8 ÚɃö4ÿÑÞä˜o¦ŒKG¿±ª­0£ù„“üRF¡g»p‹!F_£ñýq&3tõ#¸€á¾›ñÐI_½±O,F™RmSЈÞa£áùÊšA´ˆÒo}ËUÊ*=ýž6+ɼA‡=Êñê¤0àöûÝ1ˆ"Rä½Ç „ôÑüø)Ö‹ÛH¢@خыûQø?©^ÛÝ,6Ì”•ñÙ½Q4BÈgðnF`š¨‰y*PWЕ NߌrøӞܽé äV{W³HbiÖcŒDM]~‚uò—Bëmm·¹@@
+Ó_ ]Ä®í^Åöv
+åéAªŽJÌ Á°ã¿ æà¥`SŽ7PQÇC#¹µsØÄh”ÊwýÊ™1§/ŠÞm­›E¶Õu:¡ÁØ7ñ1‰­Ëi”²ñ) |¸f+}.ˆ¯¤]Æ,‹ ö„÷ЪÃ!òbkï…c™(éØ¡èƒ(é æM1ÐUWgÄnçðý„ ÑÚÝ ¼Ê@f²•ý’–:!y [+;Ô èJP/·A†qUU&måøª çz(y¦„w-É©€oЪ ó=ÔÄ÷%Ž•¥³‘¨ô%ÍŽ/Ê^ªˆkÂLà¥î”’·+>J4*à×4NâQÉÎAÏÂ*Í3ëЀe„ ±`:wU"‰w¨AªŽÌömoå¾'
+šWÍ«öL=AI:›í—±:˜m@ÊñàœûÝ9d…?m†cNî|È„ÜâªÈØöãØ'ô
+€¨[¨öiJ(¬ææô»&Z£X; `\!š-è
+g1p¶Ï°«R,f¢”½Îm-u4[Ù‘dS1le¢{pYIª^ìDV‚Ew#Süµ2 é =>ºÎ½[A“‘æìZw$%†æç¯í@:ŸCA"² ÌGÔÞƒ¿ñ>f×K2}þû±†%Íí°‡þÀFaN[ùÅvGÙËè³€ë)(kKÒƒÄ-t_H‡2aJÚ]ˆ¡o๯{Ü¿†¦l(6>X,3ЩO»g°+SÃ0«'3Í!&þØ1Äå³Já¼g˜Ðt
+LêíÉ:Ä£á–v€x¨0µzÍ~>¤ð€¦'åßÎgͲ:®
+ V(ìyÓ{“k‡è›§oÀ4½ó9©^r¤ãäjý
+jB¤sç–PîC¿•uÀñ#ã@ËQr¯'I×.ƒ5ñWáð•Šlû-ÝÅR•µ8õ“k{ÃØ}›ÿc á;΢é°cü:‚Ò29²ü­ì¼Œ³àëxøŒwk;ÐHº­ÀØ1ÃcÔf ÔcOç@Æ*J΀ ù¼Ô ê‚P'6Ó€sÝö—¡¡ªÈx«!õ €äà€ðH qf—ikÌë1Z€žÇ¶ƒqà#ÿè†Ð¸ pòÓuW¤€û,4¶b/Võà…4n]ç
+'î„}Úö¢_ÕDýSË»)®Žõ
+'ã®v?‚HPgƒH€i÷3äi×;B®B|ñ¿Ò|ö'LªAm‘0jÛ0ŠÌ‡™®Ë¹˜aV
+‡¨/Õ,½¦G¨+OV0€¨³8ìANaš9A57HRôEçw¡žÜø äOk{†Ð¶MÔ´æÚ[&2+1ÅèÇA#dØKž‚„a›¤kžn|B\~Ä<åï„x. q­åÂL© õïåÔkfÄ%˜Ž.*—Å£Ê’Ý ´Þ1/±‰ö”¹ Q²cÿ*ë(kcˆÿñ]&GvÜ@µ@>ÐöåLy¢ëÐÿ«^6­a´‚95@£*+d'‰oË&[¸=‚f+ùÎ’{Éy%
+
+1C‘'É *ñò~Õ÷Hi*E>ªìÌn1ê.·™³¶‚ aƒ˜ é ÆóUþ@ÖURÐi#TYÏ)OÆyHC:åIß4s–ùŠõÆðã˜$Ã>5ð°#Æ3,*»@xç1Ou]‘“xÕã¶uæ¡qQ/î[p[Íi¡Ê6%«4ÎŒ¤zaÃ/ÃùMHïØ_ud5=)Œ[¯ ¦Ø@õ4}^+´£J¦YX6\“oêòO„H¬üKnR`PYÃÚñ«áR‘,Âl]Çà]ø¸ÖÃlçr(!É ¯Ê¼Ýñ£è¡1g·ô!Dس‹(;‹žO9|_z…(ºŸ&þ½ŠèõT~Ä%ºHÒ˶ðVkVœº›ºcêE”àð'þGõ²Ï‘Ÿ‰è‘¬À*¡µÜÓK²¦“6,ƒnc±»,>–"3ïj1ç…Ì‚H®c°¢„ÝbåŸP
+Ì3Hð·+Hme¥TJ€®‚.égî‹ø)¢0ç>‡o…Y*Çùƒ+‡v9ÖäsDŠ˜ò×tIå»°Jaø””ñ(ø)RóUüÏÄSNŸ#ß+GáuC(ÅñBHñ…ÏBšü˜_*€)kB«B¿õQÄ×á«hÞÁ_̪yyG1˜T”‹. ?Š/Ã&(V½d¨«ˆÌ…š
+š‚wïÐEÖ2KǾ©)a0•Y|Ó¡upì\€ø  ÌèW/.=–ÄÄÏK…ëÃý¨ÿ§1SXÌv°² '»IŒùÛXnh¢t§¤SVUIŽÂϤU‰„¸_0‰gpÑÒô_ËAó¡ÿ)w¡Ùü“V®.UdTRÖ™¶SB©lJ‚c•,PlÄ>¹„Y;¶¾›
+*Š-ãA¸Œ®I?v&·àcXÙÈOx”¿˜rä˜qÐt—dqGâsÜ?¥E¼o⇹ʕì­A0ÃåmF\§ˆ»fÆÎ4OU*Ì‘¢ž·’
+^.@훞E™4ƒq…a²ßµ`x" ÎÆXèC¹'I{×›äRá4fa>faX{™…t·Ï'/XºÆXr¬¸ÂRÔ„¶L¥œ‹É!ïQj"3‰?V*„2ÓK¸ÁØ…*ÝoÖ3,Ì¢Æeôñ†>°°`Ô”¬7ò̤p$ïb5ƒ€li<þfÒ#Søè ‚›¶æ)ýMYܱJd²`ê‘JÓEàǧüzÙQCœ]’[1öP”¤¾SZŽ%ûz)‚S°ªL~¦Í uOÓ”«”æ~É6¤1ƒ¾§m®Ø)L1o‰›WÐ<´jÁ~pôNÿ`BÔÙçÐAö:ä`;xÍ\Œ9ÖrB¹@ ~#ûª5N…€t³²Ì!³+ÅvZ¢ $uvµ
+>–¢9ÑZ”5l3Œâ
+pd)ÃO‚Å0t>ø¦$2AºµÎ¹ y¤ûœïùiišPC<iµJ¶zòD¨
+ûz*Z%ì$‹EÉç¯Áº±ó{}•üh“¾”ÝŒïƒ[4HõdþŒ{.\]þnØ4 ½›Ï•5ZSˆØ€Ã¢í›ÆBA¨NIj¹= jÄ¢ÓSÝ
+¶ ÑËñ€õSɃöýu*Ê— ™¬†P~½1:<;é•8^F ’J–½x©èUV/ÄxöËé_’_éÛå xá]˳SícX°…ñèê©€8ØÍ!›vÎÔŒD´Åöшº¬¾òíXÇ òD ¦¼SÞ#§PQ‡FÅD£m›¬v¡
+Ü7‘>ù æøW€
+H‰Œ—A²›7„Oà;èQ
+ü¹Ø¾2O>çoü™û0ˆ1Îð»:ÓïÐdô qCáòô¸|ÿö¿,•ŸNËeu`ò„}}Π¯|ñç1ŽTB
+E‘5bŠoÐ Ÿ1Q^³Øë,7æ(ù¶1‘wÎ8&jLÝñÂ?1©‹3KCÚÖãïÄdC¹™¨mükPöçÆuEléºIØd„ØÅu Ÿ<B7=Wµœ­ŽN$¿‰uálgd¥L•Ï4 ¿›v?S@¸U¯uè¢ ½z«R©@=bꆌ¦*oæ”Ê»yïg6{roƒAVëøTš¼Dk %‹>ô1„±„´ç/HK¦_áj¾J)ŽÉÊÓ|ƒâ÷ôo ¸ÖaZ&cÂäl‡ NÉàSMœ?vؼ!mõŒôb1Ø1B•B¹n@?
+´Zcú°›Ò¡_Ñö¦5Œý ­-Kæ¼ô`îcCfæIè?Z­‚K!é¥P¹&‚Ro:ú¥?’;aZPÙ<M{aÁb̽Ö]Ñq2ï}¾Já‰hµª6ŽN!0%@8ñšmªÕ–sæ‘_»É.CŠJÂœ/Ãœ’ïýU
+Ïã¦À1˜…4|~z52{e´~””©¦Z
+¢ÝÒ:º ¦ [¹D—'qX¬ép#å¶d0 9T&z3 UÈ{i=©B0”î(¹ ú^‡Êîiz«6Üx= KxŠ—é]¹žW©ß!e䌱äÄý~¯'Éñ÷H¢ì@užH
+ɇXœRIàü'Ž¶1…)ß^‡ÒdG= €ðHãB“Èëq„ÞøÿÒÒߪÿºx ŒRžiûD¦ŽÃF ?oA—4
+é×ÖB Þ>c{ ŒÊLŒÌB¼±#‡ :•€Á',,ßlôöÚxbÈ(DŽ|‹n ZF»DX-“Q£ªäØÓœÉù+v&[-ìymÈÌ!Â;ú´W)²éX©y[, ã@rP×)…ÌPÅÝÖyh¤Fct±uF¸$Mt¿]¿¾3ª»áùB._ç-µéÙpï8ž qˆÈ4_,Ηⅼ{ß ulNì<9¿@®RÁ#‚ÿ\´ú´ SM¨3r_¿?Sd7êð<©ý&ýÏ)äËN%Ä"²11ª}D<…‚PLt¯³ø u¼^¹+ºmÎ[ˆ^DÅäRÇ)õò¤C÷™
+°×Aàœ´¦ O© õxÜmXŸä)dœ!6yŠî’5z)®^6œÏ¢1¯,˜ÍñȈºN®bNî'9HADŒ¦®LQ;Wñ › -Ç)ErDqÖÛ\„¹˜ŠÐÈ+WquˆǺ?!„Ð\ä.¾Í!!Ï Ç•:ñ6Xù¦`ÌjË}nxèK¿xìæ_‡K õñÁ†“Çpö¯Xë~u½,1 zÖa»œ}ö5wŒÊŽrë0»’Ï;wÅpjÚ #}òYÆvOG½ö:x;3múëí”×@ŒÆ}¬¤bå •—‡žx›™DÆÁS*m“WzÅ| ¨CwÂ¥i,p_Ò?èŸ^{Y–yJ}•Q½4’c¥ ÔŽßñ-ÊÙ?@¾húwä¿mùŸÏì1ìÁ»úÍ“äç'Pjc’‚õ¸‡0X±v\Ï;HÎ ò>Ì[)ŽNr«¥rL$Ã?ô×2èù^•¸S‚·|(Ø¿ÂxϤ´lo Áðg@ü¹cÙIf =CKþ5èríÈhÙ®Äõãˆ>XŠ\*‚¼Cˆ¹ö¢ù† ú/½V¾iúÓ>­ƒ\å[ ³ùBºËI¼õc)zD´„èýä"a´Ÿ7@:GR›ÞÒ¾›ï®´¦W¥7¤F¯xiƧu¼e`&™5›Ÿ ¿ëÓ÷‡úªû$‹fødçE‹@Л•·~ñBù‡žæhŠÍXV²á3›n7·pr
+²-‚Ÿ-£ˆVGM´ŸœBÚZ”éµBÉbb°Í·9n›…)ÅË“ˆéFv@4+TcŽì>?ŽÊ|Ð0œé<y3ø"ßXJ9$\$ÙX[GR[z(GOžR(š“‘_I×<ÃÁBéjZÎPóæ8/›?¢ùC¾Eü4uÞ®„-Ì÷>âgÂ<^ˆâDZ¿L0‘ºqM7AôâCQƒ4ú|&ï÷gÔÉ ÎÉø°vcLxîa€ÑyªyË ·ã
+­FîŒs`DÍO2ÅLœ+zmWª”“L(òüP$Ì0@Wí¨á‹dA„J’lI©ŒÙ^g©r”¹pËÞ`4Þ¾„Ķ^ôzo&g4NHZ¹žImŽ4c†iž(Ý›%ZcÅ–*'쥺pbZé?µÕî<M%Z)žÛ$I9ê‹\ƒŒ¯mùO ‚z/G㪈¬ò¸´–A;2*ÃÏò
+Îg.,O¥@Éy3ꃾõòóuÄá ö…rç8
+&‰‘€Î©úYv‹’*|1‰uÞÈ·.Î"ÅšØ:rü¶;â»=4DOCbVâ¬PËT^;½€°#P;,­#
+»"m0³›ÕUtˆ/ºAb_ÒÑÊðú,úÇg=aPÊ”“XíòPÜ°)ØüéΩ„)Öðñ‘›Ïà“ûÝ€ÿzÇ¥ÿÄЋñ0ƒÂÊzÁêÉ{SÓ¶2Çïèhi¤T
+|\Eˆo‚š(×12žµ[ ª„(òðå]Lý¡× ôhÚÒÍfo‚
+ðõN•v1{eà—Æ¢ÞM1O —SõFúOèx¾:êu»w@§·ë5Ð
+‚óaÑAÛŒ*!‰3µ_£ÊÜì$ÀÅqMê‘-õ*CÚ…c‚py4¤R†­³^sRT+ñÀT%™ü™ Ád€3ƒÈˆO5εQ^¬‹Tfë-,JQgcpìN ]*Ri÷ÞœQ Ñò®qæøœ\¦x\JSy›¾ÃeUj¸’(4‘Xx”±ß
+cq"%†x7/»O&4ÜL蓹³ mʃIΧ ¦bð'Ö¬ÅËNú²ò’7…¦Ñ‚Ûg(YC³4n]_/8˜u¹nw¾šzêŒUöèš66îò÷í` ç”ÛâåO°Û©1¸Á5â Æ ¸;fxzF½,¥²îÄVê¹å¨>]ošxê !$%…îñƒôRd*.Æ·¢ÕóT¸ÝF‘†0’n v+Õ&dE3o,ƒO¤¤-¼\”—ZÚç½`Šø§;ùß O$æ$çõh™JÅ®­âá¹-uñ*ø ü•²fºÊ‡óá|c\,ÈPaÁæŶ"„‰–Fð飷ÍOg+ß"vô, j—»B€ ”mEÀ"B…Í8¥€0V2³Ö
+˜*Ùî– œž!"îat[Üv1Ò7¡öHsUgÒRª©ªÚð¦~ ¸Ê°¢FïFë”ÇÄͤæ³7ø{¯9ûQ 6æ‘¡CE£6?®£陶f7‡0»¢þšÝH‘xò@2ð[÷µ,ÜU/FAæ‡èjzñ”ÔðÙ w¾—A’h5¾½7ÍŠ}^ÙlíÄl°+Ì.ÊQR"4t½ÀÚ—¥®‡BËg–dT±°Y ¸âAÕ²E}Ï>(¾5“¨7cX*å;aü¼Í¡F“)Œi¯ÃTCéèÐÈ"> ñÆÂÎÐxçêÌûç?7 ’ÛŒM0srœ‘X±DÃ%øôuI¸Ubòf9«0ªÂóFõ@KÖ€QOôb|S(÷Œâºqõqœ(•„°m o—h~š¥Ø2rXfFØÓtŽ!éL6/™š¢ÊŒfß<TÆVo¾“š”¨¼¡1dV®•33;Åò(Ø;‹/ß"‹>»U:™ÄßÆŽˆ/’ë¹nÔÔj0öÅÕŒ~WDîÛ:4C·‰Ý Is”Yð{&œTšÛÀ#ñ
+ËÇo”†ªƒj„eà„X™ n«Æ 3"=Ì7ƾmÈ\6/è‹<ó;O…ñž²º` 34ÇŽ¶Œ+åG%Ø×i·0`Ø‚`Ô³Æ2ÐøúŠ°° £s»
+Ñ•² ¹Ò#½é'K¯pÉÃim'9|ÖÈÃß@1!)Ú ]Ö 4ìeö«²1¨¹¡2!‘¡Rƽ¶¢¤¸ÎŒà_@°tÅfåè›àƒâÍŠ£è…Ç/è6I,¢Ý k[±®)\ë`ºF¿,¦[ÑZÔúó‡Ëo"|zݯNZ]Ù®ºWÍ&&­ÎÙ¼„lÌh¾Ÿ4}oC@¹˜Ÿì[)ËT&œ3øV<²Q;ßê1vêÉåC>Ê—y¤f5jƒœÈ¯ ¶™‰¯ÐñazÓ“˜$ªz‹êqH£ˆ°A€z¼6‘)3e}øÈ=ÔóÌ6çjvp‰}¾ÏàV ÌàtÅÂÆ…ÊwH¡o„å˜&r\÷ÇŽæpdŠ ýàY]>™› ð؃Ah<yf̤­Â4­pëµÓ“6¹FŒ¤‚b¶e8ª²,Grˆb!ä6>9)ýC»Äò=sÂc§ºS)Z…×dþ'±×Šƒ¥ç…¹ä\,Aå?o«H&©rêð”Ax'% ÚüÆ(J RÙ¡éev…`˜¢ªÑlvQ2ˆAùåÇIÊŸˆÚw"… o$'|yO
+Ú
+‹ ¤Tô¦VלYÕ„År‘ÓéʆLïµÕ_­ÅO9­<tTXA{ê=Þ¤V¶ 9`4­<!’ÒV€Dš™† ÛÚ“èî ƒ5ø‚Ð.È <i»L:åÞçÒ TÑSL‹Lºù"ô >ëÜ6$`µd*í8_† ÉÕ²i’µå>͉ P”%…ªbÜ
+L«aÀkí{HË\—(›3¾¤ _ÂÅ*„Hv!T …Üi\$ròQb¼0…š’Ǫ‹ íeíÄT€„†áfÔ7¤k†4V± ¶Ÿã@‚üôÝ:«8O?1ÜÌD3'É èy@`7[…y@
+…6v7šä90Ù®3~†ÓgrÒÈ!Â"#4úíÍ1»axØð‡!oöy1dÀIE>°–nÚDnQò6¢!^Ã`ÃüF(ƒãÃYºÍ9ì -•dsÖ­uE'Œˆœ‡Ñ)…
+2¦€3£•
+¡I[s±u(ˆ:dØg}ÍöƦðÓ ýj÷6èÁÀb ;†=€ç0
+í¤ókh¨<W /ßÄXp˜è|}÷{g4]ä™}¨þ”g{QvDò`w›ù9&Àâ `­ywÆ<)YNií4”$Ž%£Ž|2v2…°êÕý bJðZ½Š~/«ðQr¤ýqÌtãL;FÝ¿buw oËjAš=]ƒi 4›¶’1Úå¿*òÕ¸X§ =©¡&ÑŽI
+L„¥˜dÍ’?ŽE˜¶*ie}AË—ï—"ˆK&ëÍ”ÀX({ÏÉ¿‡FÀÔŒd%m
+üªÎûcƒn›½gÒ'Ž+~•d¬ó &xà®36+ÙW5Eʾr¡¡6A¦C~â,Ãë —ajY7{qCzÙ¦Z‚-Cűþ#›/%8¤E $_² §¢Çzþ£¢A7H1ô&ÍôÇE´9ãœpÂÁÚáSÑ#ÝžJð78‚z·’OžŠ
+oÊ…9à# 
+›¡ ãTôýV™B;¬v3À”ð0 Uh¬·Œd&‘j߉"EEô‹ñrDY—åºKIŽ;ÒÌŸWÑ*òbËã0õ]Òq»Xb¼HÕoj@±„‹×E^&½¯¨Õåù+1L„§/U;%’v}–œCÉ¥Šl– ΞòΓJ4ÒÖ`¬_ˆÇæEûØs$؉ =cÁxïf_íësÔ•b~³<ž¿'— !£YµƒÈ~{ Ò®DÅôÇa×ÈŽìH—€å×E¬á 'ÛºÅ
+|t虶[á:Mô¢èɨ‡MxÉ+ïcB¬J|}ºJÂcÉ-Ÿ-ë‡Å9YßðU÷v,v¼ƒ=(¹):¾,Õþ~Ujⶡ¨« 20nkå¸6"( çœ/;J[@
+ TÁ¯Ù·™ŽØû¶ošQVth¼€ªHa ³AÐ¥šØÐlŸ…ÓÃ=ͺñ,sƒú@>/P ½à§ãä—Ö h°ÖûËWÃõ,„:MÐTÉà×ûE\'óæ QÁlì*Ý‹9ú6N–B0G¢ÝkêÏc@s~(Å©ö1PTM ¸»Ç!©á¿à­:ì1…_'Æ-'ò™uì&ÄMÉ°{€ÌÈ!ï´ñP—ù¾Ä3&ÓJ—ÏIõŠQ´?Ð&wõë9käÔdŸ&†qfc{u¬9«
+Nñ¿ãðáë*Š”³H·ÉÍf”õEÔŽ}N¬@½ËcY“ ¡“•€,kœ‘žº "ŽRqÛ<àÀ¸Ójë>»O;É·^RåÛ˜9+b4@÷•
+‚¢%ã»Ø=€L
+\ŠªÜBœT»ôP”h<ƒ<Bœ¼gi$'z q€‰!Ä…º[†£¦‚¶Î;g¸…I`+³â$ùÈpqÏœ€ÓéäBKŸÇ¬`J*þÙoùlÓ¨2gCø‡íæÿà<§’–sí;!B9®Ô‰½ÖO6,!)+¼nzV¨}HÜ_Ù`ÿ(zàØTæ¡Á`ÿï¯øåo¹‹F÷*.˜šôcU¨¨ ê8w’¼&½Æˆä|+%¸á4NêÔ¤†ù’;Kã2JÇTJ ¨ª$x/Jz<Eämxx{1çOìÀòU)Ž ØtÛ¿Bôb(˜+/aC'[¢ MÚSSâ3¢}E{;ex,Æ’,d¼‚ÜÂ>ÄM9™¶%à S…vzöÉbK<}÷…LEß/E2)4xh¾ìÖÏ#õµs†d3Ø8;”h‰¢¬„¹ÉÖ ®´B÷vúŠÍs¶”e2–Z%HG/!µ9ð°$ÙpV¢yJ›Yèv^7კ¾ÃÁÆâá4 tòá«j>n;%¸E™æPÝY½™8CÎú½\p·ç
+1ZÓWFµo¢f¢q¨^+¦Ž㢠zÒ>&)a±ós˜6Š”EVº”LA1w¾½íp,"qNMYZ_Š‘H0b=}?eÅYb Û‡ë;jq–ãJ€B´WH†¬Dy—ËØpÖ3ý\ ,g¡àÝun…¼ªo?ÁÈ­ Yùƒ”‚&_š^ä¼ /{0[NK"! 7‡277ôšvñ„*‡¶O³°€V&í‚)®ÿ3^&ÉqäJ=î ЀÀ¼ÖV·Ð–ºÿ¶Ÿ$«
+Ù*ûÖßDÑ$bð¡"ŽÝw†i•ˆÒ8¤„¨|d_ËI‡ÒÀ5Në¬4Žç×·ƒ+l½#³lRçR¾’/É·“• Rkȥäu÷ç VH¾¹š7Š,³ ÐçZzÀ‘´MêcîÖ'ÖËÆ œ ×{m`Ô¨ÈɬŽm‡:"/ëµÑæ²P ŠÅ#<ÉÏ1ùOrª8é xLbÖ`ä5¢€Ø;>GæßÜøIv bö½â§FÿÕöOòý], yÈ8´ZÊnÕ|°Ø5_d‘`¹ç5ÇYf,W8nHœtôµŒEõs –åôú.¨ EæßPd· PËhˆ2öñbÀ.!—ì7ñepEeܽƙí3†¸«@«%‚‘çwoä(¯Ê¦¹á#äoä2/¯øØr@òÚ¢ÑÜ+vò UGIwnêÿ]™ ÜÔò W¶|S) •[“«§yKb‹yØv¦2cjÍü ÚGcÄo;ð²Þ
+FIüµ\+AÛ·‘~vÉðË(D
+>v»¦*«BÖ‚“);Ô0A.0Iƒ± pošö<į‚%òœ€œîÎÁó³æ< ÛùQø'Zа‘ázÔ¾áÌàÈu•aHµ4I
+zN¨
+T†êá×l§lé“W¤@e¨‡ŽºS4 C+ö5?'q,RJÆJþÉ U$çû¾¨+À`˜ô#\;ÑÕÌ.’5ìz”)Nemµç=¦šqÇ›Ã#ëØ„Bˆ†’Ë•Ð~²åå¡-ÛÀZÀ­qqÎ ˆ}€€˜&ö6›Ú‰Ù(rj˜ó½|o€Tž.…V ÏŸ&í†L—âƒ`9(#É«²å‚ÈzÃ^c¾¤±èâ¢UB0âhüF¼Vïi­pYˆ‰ÌÝÅÁ®0_
+7 ‰Ó†Ö÷æ=ä4¿i6KTÚÜše¤)èǺX#QT=ìøÃJÍõ×å“ mŸã$§TzÚuÆb¤ªït£ˆG‹ÁÖ9ž‘þ* OCʽ^†™_Œƒµ¬x<^Á¹>ˆ®pÙßï O1¥l'ýõ“dm3»øF˜žíâÁãlüpQV»¢Ÿbª††–½Qc€H¥]å‡ú,ˆÄ;hÛÝù'~J¼¡§è{V‡T×w !”àZ”âÚµçQã¤ÔµG~n…ä‹/"N¨ë¤ÝÐçäd«Ê¼Äö”¢C‰iÒ´çë*VÃà]gæÏdQ/`œ6•ðW÷˜ª âSó5G¸• Ö7“2#<«¨ {Í|LŠ¾è
+á[Ã~”øP›F=Ö9˜$]Œ¶ù¤–=×sÅFèµ~ÿrK¿§©Ê SŒièÌïb8’moªÌý4U/ 2h2é WL«ãT¬<0$4ŸxT“ÚMñ
+GQ¨Ðå4´íý}PYF˜‰o|ùÍuo‚JðùNV9g1mÌ{3;ýß#H³Ž¹dÞ•Fæ…'PTBëÌNŸþHƒè‘W왇)þ+ –¢9“…—&\ºižslxqqˆÏcxSÞ«@A´d3“ ŠX“€ûMˆ1·ó¶>çRŽv“šöÇhá©
+.ϯÒCv€²Îøý
+•p¦Rõ±åb¾–îMÙ~=-çdIy’óÀ÷·Ašã¡–ŠSÆÔ凘dŠå "?š"~F8B vF€¼ˆªï—ìx`‘jŒ "!)˜.«3(M€ÂzЋCúÌ*ðYé7¹¤Û01öuчÔÔ1nÎáÄ&±Ý^E, 1L"ÿ]W%KønY>b’öŠµÖÏÁø°$l°?ݦ¶xC¥™È÷°µcèhZ9€>ÄØxèôÍe@xA0ƒ†Ûù“ÁÉátGIwO?€žKx‚<5â
+sÜ¿6]IËBT8xyC»d`íšo?Cx94çÓžÑA*âU&Uj¯HXþtZ›bG»o¨1ÄÐßsšÂ%X˜÷.KS½.Á-2–“O§z¦Ü™¯ZWØ©
+÷[p¸¼½¯1…{y'_ç4 ÈÜ‚é„©2¬Ê Dé‹‘DÚÚÒWÐkÿöv2 -oƒ ŠžFÖÎÅ92é…¤@ºó÷aØ[ñÏŽÁ§%0Ђ`Ðs™ৠƒ‰ÿÙ5`ˆ T'é«Ž0¨ŠaÓ0
+RLÙ¢±!‚A•S؃sY0«]˜WäT¡°Ú¾
+…ÎaºêCØAàûŒô/F "tmʽòîév€ˆêIHyp¶¨Â³ ×E7(ôÙ|¯XjˆºÚ7˜
+S@ŒºCø%• ŒaY” é…A<@6Y”\å~p±wçðåM:Ò÷b±Up ${s^Ò$Ãï6ö)zûµ"bWD¶tÆK£#q¡µ?†úCZT0ùMJ"˜*Žîæ$I¨ ›üŸßD"½Î1º;×âd
+ÂJ—4¼J½›ôЙTjT&ÊÎ{­÷žð=_{…ÜÁ\&§°¯bÐ$®ñAÇVdʇôOž ‡˜|[Šx,)®ÔÓïù€.FÏÒ…_?^§¥¬U +Ânù]P.ˆJÐ=Üõo„øœãðÝ4fŸ'³‚Œð^Ò ¿8±’E¦Ç!–Ôi|OŸ.褩I%-ȇ]ÅAÛp®é…g:ð¨ùí7ª†3eGyÂíM"=C"½ý(œ=šÅØoQà÷‰V².{ —ÁZç­ðˆJÅÑòuÕ3èyùO/
+¹|w$woz
+±r@P”o»D6
+•àâ¤Ç®)‡îs$z´ƒG•€9r„EANü*ŠåÛ{®ßÄù¬
+øD~yÿ+F¾´ˆ'M!‚n³(*Wè°§<X¿ kâÁÝA(Ÿ^ PÍïjŠY5ï1BCë'æQq^㇟!°'ç ¾Ž–ÙùYŠ2Ü<¿9 Œìj—»§ã˜Ð=èÕ+h¤à´¸¨ƒmTqÊ”·ƒ)úð¹á ifðd jŠ†·aNÀx”tSÉŸƒŠ]XE¶oÉ·î"«0
+D<æD ‚=ô—œÓ†úø<¶g¬„/+UœâoCsfÜ3PNI[:ÃïÑ A´ïߘ! Û˜¿ˆ@uzŸC ¾¨a嚸â¾ê³ejÝäï³Ï‰VMmeʾº¬QVA¡ê˳/GcB—ëµ{F@»¦]^‡
+>ÐüœÂ†1©úƒôÁ¼±Ü¨¸Èúʧ,Xﲘ]ìêE<kê£oá4Œ-okyq¯6‘
+)ÎQ¥>JB¦VÓ€éQy;óÆD9løÃiÎB]š|‘ósÃü°°qLŒVoÇ‹9ãs¦Üg… ´çu4×ÏÙ8PjþÁ¥"ªbL‘Ûø¶Å‰Üç•„ÂT—¨ïÄ€ë,ÈÌJ~n|ê/p«‡
+€6›|ÇŒ
+û0QJúÞîsLæYOw¬Ë>v¡)/1h©ÕèëœÊ>Jn'Šó›y?Ÿƒ§19IÍ8cË.Ç€Õ8¾´]d‹ÄÚºãï²ñp«´Ô±;`ØŠ
+¡gOÉK¹ö—’…4Á¾PC½¯ú(’>°‹•®s`0 Á6[Ï»d'MÚéBdÒ/RØ«.hˆ6ìrÂù~¤ßÊ ƒ‚Z‘ä
+>‚Øêt¿
+äSäàÏù6}A´ð³âl@ÉçažhÎ8–@Ȩd £_¶+{}¬æ?*R,é°dÚÚÿ]$/M6B<¿Aˆøuicºzx(Y Ð.YÞ‰çQ‚:ä·.¸´ù¸(Ê•ËѾd»(“]¸´?‡•‚%û^ÂÈnC:òR"€$¨¾•ûªÏ"¢)u&«º^Î1ÙðÇëUUº ÕÑÁù}DÖµ&k]{%§•¶S”ÏÛYË7¼Ä¤þpH]ý­ÁÂGÒ×<ohÀ&Õðñ=?Š~{뇚µ—Ë(éR,,h âó“)Aßon1ÐçÓEŸ-<•| âPòè¡¿I†È0ýò=î ù„·ýá¸æÂjqÖŠWákp Î_ ”¶}q«ß7ý¨ì}—jyN¡ƒˆ=.HíKż2N »‡IXÀ¶v6åPäÃÄET©yRáMDÊ:ª\Sq2EÑÏT£Á(ŽVªÂÊNÛÜ‚ë“ó>R²”ŠÜþZ[ª/“¸ÒÏ¥`Vaé¢RéfïŠ=VáG…ßt‘?×”•ßŽÉÈ TýM 8T¡ØE1)‘,œ™Å÷SRäÑ~ÓüZ$^„_“ˆ‡OðY¯mýû*á=ŠLP´#B7 £«oõz|Ò0üIâ5ø¢óè@’.j<´Ã$¶¹îcÚÐà@¬¹àÛ%¥P_^b¸þ©†“Bq@ÿÖ㢖&ãFz‚‰»’k—'þ"¹&— §NhU±´ØKÉŸ~ì×_§š9{¿‡
+a6ÿþJñÑmÊÍNwxòѸÒ40ŠèÜ¿Ç"$T¹ÒkƒP~|àQð€Óûˆ(gPGú´¶K
+ñú ¸ÏÁÀ³’Ô~¤•€vLêè Í ŠU3¨qT•!ËæˆÇÁè*’e-ûœÕD(t¿Ÿ”Z`Ã*‚C¾¸ÛxsŠ2»ÆUBßÛ9Ju+ÝJœ²0cø¢Q½Dõìùí?+56ɯ¼‰V{ÌG–n7ÞYlpÑN{®ÎU@ðÙãòø{Pll@ø=.âÁòªõfdyˆÊ(sŸÓ}Ñ&e_@Ñf¡ùåe“ÜVá«ø*þ\{–¹E¶Îý·ó5 ÊÑ_§¼H,C 4ºÙŸÄ!Ç*éOâjI’ÅUž
+' OFäk؉©€ÖdÍVÈÐâÔ÷ÖÄ@ÜÎÌT¤Íƒ°ÙöÃSFÃU‘ÈŽN´¾(h8ìåÓ(h,G^ƒŽdóÑ^ÕÒNEqáDEº'Õ,`€!…ä}ÏI">œ/àÚ
+–ˆG]‹„þÂ7;SA©'ñ¹—ØHLC‰î…³hËš5ÒiÞOÜ— Gu®uˆáÉ}MúÃ4ôMHotÝ"òI_oB^ýòOòç WrrЉMþ\
+d×è=Äx9³GìY€ŒZ³äØ7èF÷™#èçÝe+Ž ‹ÂKÒm#NŸx虪RØÉpþt)­ð]jÍÇBƆtaãiÛ]ȨXlúÁiß©.AxåI¦ÁÒÝ9Ì=I5òm-ÃÄå„ lÞ@~‡ /—XÔŠN€¯2,?0y¦%ÁáJ ÆÇêï*¬ˆA —íáy•X
+Ø`Kpaê¤ÉÉPÛže䆢ù˜Ê3«íÅv˳ÉLaý2Jƒ†µ±E D… ò–=¨'âüx*
+åAú„SÍæz
+C!ä;±]Žvê›ä·³9Ÿ´.{»&™1nâžrÙlø Úçà¼eБG?‡¼<HöW„`Ó‡æ„zQÏKÈV>Þ\ ²›þ~NïZ!sìÏ+kw Ú;²?ûÝÄXi‡pWØÈP¤áäÓ}ÖWÄMôF0 ÒaÌÍ|UÇ7`“QÈ6üỄ6 ä¶¡?DxânÈú
+bÀ¼CØ_!l³©I5ýD†)‚œË2“‡79‹Á``"6µö–>N—É¢DÔÈI½OÂÅ€rà T{–ïµ6ò¶L„£?çRayRñcœswìÔe5òT—†/[.{NYC%Øà&‘‹î% ›i˜Ó±ÑÅЙ•Ê75Œ%\Üæ²ä8ï`/vPöÖh²rÈPߎ´vnŒªŒžÎëi›Ù”¿Þm¹r:C6@ãîLŸYñµÈ)9
+åË3Z»]‡ Äïh&fÙ—C/ÂζŽ´ç›þû'fý¾>©± Ã>êe{ú³b²h›ÃVsúutÉ·²!•’"Ö¡» d„
+†’•PP˜Þß
+î¨P^Ç$QŽaMv£- ê
+#ˆ6‡ÆÊŒ<Hs‰k¨c´]AЂõ±Sõˆ•â‡
+×@6ÙÁ…áÆñÛÝέið®6œ;1lP¦ÙìÆWî8Ô26À-Mƒ"à+öÂH•˜·{ à¼3 ˆõÇ’;3\œ—í`L»&Š
+í<½MŸ0 j8—ã?é 7à†¿°ôÎÄm “I6g{úIUŠý˜ˆA×Tƺ…ŘCÕc¹ ‘D{ñz¾7ý—­póÁ7E ¦^¸Ò#ºð²¡]\èÏ)¨fâå™+,U•§¥]€»ÿ4æšìë'7ò‹_z•¡ym–›AÃy³÷˜_ǘË|Í ô¾¡!Øñ4„ç C¶··ý$ædaŒß˜L?y7U×*^b¾þ»Ò³ÿ(0hgéègLÈ¥ìŽ&å(oóç&¦ªbì ´a@x0s }û¬¬
+ö†¢ÓŠ@YÙta´…‚B –s£’®“Jëi3²QuP·Âz”…q)—,-Ë'¼Ú¢OœÊ@c«È ˜sŠfn:ñ5X¦Fñ C¼MFe„mße’¡%ç*Û&µ±yˆ| Ï
+C‰cb>xÞkCFµBGç1†3 }ï(~³6™1„h†:M%¤qY©%}/íæÄ8è_z{XÚ‚Ù…äÑöÒ†æàÑ
+pªÕSikÌ“v,ê‘M Ï¥õ‡!O3ò^"ñ±ö‡
+g
+Bù°Jˆ¿7½áÃ"“å©Pk ’jrhá>(@I!’õD_€N_!`!‡|‘B»3|‹îE‡ŸI·±IˆôÊÖh
+fΖ»J
+¶mY3&*(œ æz°¹'
+ínÐë£iÙé™.ÎIA¨(cOã$ ¢Fu‘“ÍwCȪM\!à È…²)õR2û&7éæ™
+Ü¡,óL„DeƲûËù/¿h‹hëQ¬0¸fP¸è¿>´¨ÑTšc+41´}A„å°/À™¶|ÎFi€÷ö: `¾ÖP­†1˜”Á)Øv5í“´J
+¯ã›,/|t‡ÌдŸ#(í„É5cDMÃ×ñ¹|r3úT·÷¸¤BkÕšâcŒlK=´)=ºCâ–:㌌6Πª#HG‹A0Âñn–\m.V 7Ý©>x Õ]õ!`M»Œ уhüŒT㘷‹
+¼@-å!Òä<:_~$î-„š¨Ä¨Wò÷Tê•·IÍç¼.£—÷eô$¿­ÐD“ëzk¥šú•‡PÝ+^Õ”etfnÒ¸¥>W½YÄ(Ž;zîß‘üñÅ^õôëŠÑ<‹jƒ—Ä娧˜ Í™©D‚ƒ™VÍù¸ÒmJä’ÉLM‡™ÆÊ¡‰‰cƒƒR¦ÛÊît؈’á›(¶dGÁÈ#Jh=«Úo~Ï«¼‚{ @vќϗLyÁDŸ“‡ ÊÔ|z"Xª—cš/è ‹G^.5ÜÐ/°&@O¸ô‘ÙÌ8ëΟÝ|¡
+VzV—·š/h*‰ íOÙ™7^áF†É‚sÂV dàu°:5«Í¿e¯`Úa[ ŒlZ˜€ÎIq“QTZ†æšqNfVøç v#Ô¤~Pl:P±Yqé³\C.T{ jØ}P˜*OÍëLjÛP]-Ô¯ø½žÉUéÇV³6˜±6aÅvAIPs²Uý
+¨¥ÞÜy6/L‹³ó†Ø»Õ†Ôb‚‰I7+Zœ‚CNÜœé¢Ø½xúOÑɳ3ÍÀYZÀb×ÉÂe©£u¯¦PUwQ@ ²¤˜W1c+ |ˆZ¹ÏƒÐ‚®Ý°ãônÎd2 ñS¼«d™GUÌÔÑLÇì—¿‚êhi‰e?ÛÙÛ9¼1•C­!Meƒ0wgäK¥Â÷ÏU(H2»^·‚H±¼Õ†Ï?­¯Åu1ŽQYó‚ÍIX»ŠÑ[þÜœñf´¹Fj€è°i€Bïù/#…;½lÚ¼{3Õ—Ðü6¤_Ç›Åg4…•¢HÐ<=@6ÂxAE:†¥3:‹0OËW£?«ˆ„Þ5…— _Ÿ‚ @Â’6›{kÐöÙÙ‡Ôf¨0ìý_§›<g9}£]íM9[,;Y6E=‘A~?‘»=B
+v¬òÍí¹
+ôaï²àYŠÅçiQ[Æ9|¾6¶~ê€ïh`Ñ!ˆ–É››ÃsÕÕ”Ù¹Ê@\`­ª§Z<AP„Dݺèí!5ñ™d|%¨øe|wAõRzŸñ æ} úA™fböʈѳ޴ʂ„u§î!@ßvÏ! ¢.óéR&bLF,_‚8WÂÊøpsO˜}§ÌK]=ôiÀB~^þ5ûíU@@çö¼ü5hP/1dr ãL Þë
+œÐ¶  þ^=„•¢‹~è²@g~,¸Úy8L j°ÏF œ/ªÁ—û9@y# 0O,úbDrUôšã:œÝ((hý»3 Tý
+d LGzY*t݈h¤[ž‘ýQ {ÍUæÄG#ó–S™LDtI ¡ÌÄM4¶4°‹†2ðlÙ­¹ŽjP3v—W¼z!(Ä ‘.µ‚&|!£/·Ÿßþ÷;ÿ´çÛ+ õîÞ§E ͬ$(æïA *ÅÀdg•dÍ–¦ Z(ÝCø ~ ÍMÝC€Ì5Ëy;Éâ·X ¡k©8‡ÎAüJ7ÌcìSJÃ;e¯;[,J@‡Ñ¨;
+Ék{ •¥NôE«QKÈ ï^½Ëžrz±à²Ží;
+.@%üž#êÚ²<„ÅTk@mæ:H§Ó|ô’V
+«4ájCž†g[ÔäÍ“–Õ$œ•‘^„†)&‰W¯!¤Qdkèù†à[€f\ÃÍCRôçµ=þS×Ñà  ‚EEí ›Ú³èýù¼ŒùšÚÚh!—¬:¥Ÿ 5$yÉfC{ö7Cvï¼à«  8æþëÓ*Da,(Ç>¦jïÒZš¢è„‚
+@fˆ¢Öæ Ý%g¡¦Dåq«ŽQE-šGØ©æàÅûÜRÿB êiR–‡FAy‡GÈ­Ð¥=G¯Ó)iÛwÙOš#Å%È„Å@tmOµÈÖ¿+™—1a5|XTÚ¢²+EH’ F†^}xç®O¹QÖbˆ_ |]N²KI‚Æ„WµaÀ$ퟥ‚äÇ ¥Lôö``¡c¥=#%¯6Ž…ÅQ
+³#Ìl‘¾)Ø>úR™ñè¸Ýð«øXf¬o ŽÜˆ¼ô}VçÕ Áüµ›pÖ±,
+«µä‚s
+ ßxíÈÛÈþQœÉ1œRóy•U>¯ò†vŸ³u¶$º²ÆÒÃ&)3‚ór„$i*é¨vÐ宣±áó*6 U¤fÁ)
+¸Æ
+º0¡‹•z.;"Cïßçâ=t¹û£e*P©¨Kàã w¨;l<D¾õ*ÙuMÖP)KÊÚ4_½¡|?>_(Þ£,QAÉp {:ò57õ:"®Ì°ÂÑßGe°iP|áo#
+—OZÅ8¸ø‘¯PJÚv2|
+w¸µ?£Ø1…y”¥h€’æÊ "„Š†…¸¯Âgc&[Ö¹6`|1êæ–¼¯bý¥•ºlmp]Œ v±¹h±gEÞ¿5ßO Mr³Ái²Q¾5œv‚˜ãUuöGí+!/ çŠò]Ø2ŸÄ•[Ë©[’ëãi®ŽY†lø$3ëmŠ«l¶45÷F¬ÉÛ•û\ЉwLsk¡8›u;nH™½Ú¿êW%8F“# øÀ¹¼vËvÎ5ç’eО^@”)ôȶvæï·¼…÷ßþzûñÏ[|ÿý6¶&N¹2Ó÷õŽ#‡¦XØ*§úu ].eC(J~7D†Ï„P¢A2²Ã3Ö&H§S…k9"Z…ß
+øc¶Ãy_GP»õ &Ž²"ß‚©vPxtV?ùaòÕC 41â[¼ÖªU‚IúýÓ‰•9+ 8¨2ýxc„0y?äà™Ä±L!Ï5>7þ¿€=aMZPhF;¢¥ï¸Ý’ïGD Õ|³¬d<oßäÄáy
+f7Måwm
+ƒÜ‘‘+ÌäE©º” ¢4K Ôï ‡›3ìÚ”Eç‘D0Š-ñôÐöÏ#ˆR †DühµËRˆÐü(P„ õ†Éø¦äÕ™h
+™|@=<œæà~¯{}~gG}•Û"Wö} ”kû-D|eg<Z>dN
+C^šlž» Em5wc ëšä Ú´E¦ÊKhÅ
+ÜÆË41VŒl]%{ÐJÖl튛bÄDŒ±sÒTŒí-ï©ŽÆѤv„`Ö%J ô÷ãí zÈBŸGÞžÏÃÉc‡–Û¿~2¤"~! ÀyÇ—? ‰¿ü©‚è^eõà©¿Ÿúð,Y—n^u™Û1êlÇQ÷ÖºpOæ«üK ChKÆÑdz©wá´a°€!Ó»hÈ—ñjÛöþQ®«ÒÖ§ îß;äqåžïãí´¼YˆRâHHNNÚ":¬Éž%ÏÑõ‘sóºr%û…·jGJ:Èâ*1ŒŠw¯q‡´STV;«ù‹[µý3ñ‘¡Ÿ{ù€ðÍdZ9tB óÕ1ô(°>¨yÝ}`¤Bâ›»OM¬£É²Þµ>QÑŽ¨EXi_ŃJEÊ÷Ã) ;ˆ…s
+ìUdƒ¬­GëO4 É›­p¤‡ªxAw j* †/h&üá‹ð91ù9ü³jh! ¿ê© ÏZ÷K¹ü0IM˜&qDvüË@p<S3GÞÆž€J¯˜¾–,†’-ã*œ—O„ÁŒÀµï Á±¥Êãg]H Ã߬ÿ_ã±*SnAÖ@Q(œO!=À”¬P«ãl¡ÑöbÑJÙËûd¡ÿ`
+H‰ì”ÙoÇ€ß è[¤-¶E•øˆmI¶ËFbÉ’ê¾Cݤxßäry‹¢d;Žë&uÝ$@G¶E'ïs)êŠÝʲ¤ˆ¢xì.—”íý?ҡܤiŸ
+äeÌG,æàÌî|¿ùÍ|÷ÝOƒ÷çC $H6l Ø@"°D`‰À $H6l Ø@"°D`‰À $H6l Ø@"°D`‰À $H6l Ø@"°D`‰À $H6l Ø@"°D`‰À $H6l Ø@"°D`‰À $H6x?Z±Ÿ 'Š‹ëÕÂ:>Á/â¾[T\Ã)íN¾žáE­EÅ#çkp¢N& d5·`Õ «ä\ÙEì|§ˆ¯ÄN¾‰AX.“ÈÔ ³KÀWŠNao¡—ÁSÔSxoUá½µ¸A/mç`ŠúUg­Ìù¯î“=j5_%bǽèÆÊÊÊO•`5àáš
+Q‘¥XÉñkFP‘ƒ.VZ‚µ`C%˜°0¾³èleå¥r¬²ªªS+ÎUV¼j7ÿ¸}á¸lþaüÿ¶Ç«ÿóyPè~XEiaÇák)EÕ¯ªÇrÿŽåÉS…1׋Î׉Œ2èZK_Æm-À·óؤPùÑ‚*/œ»PYYZ ae%¥À«¢ +ýçþþ~Þ÷ev,£´êxÕ±ãw/´ÕXUyYYe—ó‹”O?@mÊ´Ç&K8‰Þø’®gß­éK5}¹˜²—ˆ8I§øzÚ¯êH‡ñ!:jÑzuý; ’šø²‚s°¤i¥|ÆÑlТ 6uÚcâ§}Ä@Ò¯ïK¬ŠEcß³YuÛ“/Äõ;Óâºä’´.½,­§½2NÊſ̲̄Tàƒ»Éà{‰à„5¾lÚŸSs¾ýZX˜½”Z¾“YT7ÑNóÓ=~ lÜ~¤mÏôCq§àêî¯b{ºÿ|Ê)nÊF•=i§øåSu1B˜%­ZʯéI»•ÍI·²ñÙ#A%íÒr_ÆÆÇÙ°A”ñꇨ€EÍƬúL˜àï-Ê붦‡K÷gÅWç5­ŒßªJ»M¼ä’Mº7m¦]“¦Ä<ð™”íLqßxúYÛof†Ê·®'뵈٠Eþtf¤üÉ'½ÅÛŸžÝþrðÂÖƒ®7óüjàÐÁú¬Ê¤KÓžrãïÑ“8±™¨c"á×ÅvùÞ¢qp^7˜LL€õŒR!57Odà‘²!ƒ ãÕt¥ÜŠæ”ï=piZÒ>]Ruÿm¦ûôö,·Œ ):ŽÂ&Ù‹˜Õ˜Úìɳ¯%µ»sòF*8Fл!îQ4í;¥õI#6fPæ6,ÆLÄ$Ýu)Ú7¾ì?OûM¢T€x•í¹u‹åèÇ]vÕ¨ÌÆ1%$ìŠ^öKßÍx¤ LPÖDäm/×À÷bfM6JhR;œ!uÇ~EK* êÈÆôB*¬îaI£<¿b·1aØ=Ÿ¥LĨÜ÷È÷\â†LÉ®à£/Vͺl:î¾ß=Z·;²kãŽDÀ,ß÷ü¸,äEÚÇ ×è•›åVo–‹NÜÈFlú,i”å×ôbšTvS¤¦Ÿ‰âüüšEŸsRnM'4ɘ•›bbV<¿n5mÚ'™.È„¥m4)íJ‡$M‡niýÞ¢´ÕõÇŽŠØ}QÝ¡÷† 놜¢úgEWöç” LÄrÍ>F¯ê… ©êÊx%Œ_ÙóbìÕšOx5Ûsâ+Û ²ºimÍŠßN,é:ȑИŽ
+ü¤[Rè×Å=†ÁÇ3D žœ Ã““pþ–F*ÒÞål@TÏø…u¿ªýÀ£îLx‰áLÄaIyMü½¯$W¶><µ7Í+?\âW3.esÎkMûñ™ñk'¢<΢€
+G–GªŸ>ä¼¾7ÛñrØ0Áˆ¬r:bUÒa›škʆm&l‘Q—òÉs¤n%ñá|Ìf|¾i³3ärH›ôêûËún&`¡AþÅ„W¶¦:ŠWþÚþ{çxûkñG6yÆåÐÄçå×v§Ï<ù¸õõg_ôž¦âZÊ-ãz•-sï×þÒw«ñ·ô2ÁÏ‘6<¾È»´ùéõ_m=hýã×2^I]Ü5YÒ¦¥#&I&lÐ!›&GŽ[^l8nçb&1ËA.hòë“wò뎛Lœg¿¶'åÒvRNmW.„÷ç"n>ªáæÂꮌKÏeƒ6TtR)'O‚\E¹³’%-*6:f`c“·¨°M—ðšx)ߘœÛ‰ìšÍ̬›4ÔŠYÅ‚</œ*¦^Ÿ8÷xzøB~Ãñ!ûxâCvcÌžßt|pôÍû¹U›™àÃlXÙNEµù˜¸9¿&íJ†‡ß>ðó®æ׬š4I)pç¤ên&ªì̯*ºó1UoÚ/iØ[à]Êø ¢#òΧÏWï<`V ’„_Þü­[ôξWTCMâ›7þή…]7È6nÜcWïLѱ÷ï’&y:,oMåÍÉ°ž—ߘüˆ]5(A Ź˜c2uŒe£VíÑ.üçß x~g£&9Òpi—è*å7ðÓ¤c<±â9Ûܦã6ÕñwûÏí,¼wzw±ï­CŸŒ³>ÕW}KxæÄWD[qnåž{AT³ñIû¯Ÿ|Ü_œ\Tpò1‹.·a52+úÑlÔ({g~3­Z´Y’ìÎ*jvçU ¿ad?¤X¸ÕøÚöCyC.hÇŸG''“!ußÓG]Ø™î}óÐC ‚ûQÊÄãÉIº3/1
+èhéØÕ–mÓˆ,²„$dß!@‹lÙï–{s3ý‡ÌanÝÇ{ëœïû}ß)•bCÔt¼Â¿úËlßÅ£•‘æ¼ß¢Ø[’5§^óÿ¾ÿ“´.· g×÷0—¤9¿*ªß?xÅ3Ýñ»³ÂÚ‚Ç0”q«.ö]>šã\F×w©¨’‡{•Ý8x…´'§Â§J¡ñ1ÜoU`>m/á—u•cA1䎜……Äm¨W;@øm†œÇ8”þ`äà³ðh¸‡ }—b/n}œºýyx’u¾0oe–õ܃9ÙÍ£Ù‘ºÌ¬¤_“4¾g_Œ½º{nëGÎWÞç]_$^õ^%½FEظ(¨ùø–{%³4p‹òKZ)ßÐ 2 iÇHoò ´4ÄÄÇƘ˜Õ\Iš DPÁÂÀ7dÔ¢cδ’Cš>§íg‚fä?!£ô$"ë®Ä„wéèPSf‰} ]F8”ßaϺÄw³+üêrÔ 8IZÌ¿îŒNÐ1£
+ è…XÀªA¡/ £ó[d¼‰°Ój§¶ÆS›c*nÖq½ìÓš¸ér<2E§Æ&áyÄìŒ?+§lÓtÜñ¼§$Šî¼‹_ûù5¨àFÚÍù&íæUƒ.ÅyØÒ‹ð€šGÅ=dXÔB…ÅÀèþî½g](8•Ürxò*ê˜*úõÃ9Â-l(ØXéÇ|º:a%ãz\fRoèäã·XdÜ^¤DDÒFEF:Ê d¨GDXHØrä–´»4}ŸVûÄS&㯻j)T²QŸ–W+8•°ðüÌy Ø‹ˆŠO¼Ä£V3d^Ö#iCr.”vç|Ò{ûú«£/Ûþòñµ¨‘Ž>[=šWµþ23ômzItƒª8t@ÖM‡U½d
+xýdSÉGýÃ9×@uÁ#j@½Ò6Ø^Ø@ØY§–}¼¬ºŸ^’ƒ/ewÒKƒ×g{.¦ç†®àN5ëÓ;~ÕÞÏ«™EEÓ§wòúÜœ¦u÷ ëÂÆôÍÏÿnû#ºŽ°)ŸEM…¬º½UisÞe¬DíÓeØÇñÚÀõÝ™¶?í½p!½:X“vJï¼rB€nh¸tȬ¡"VƒÌÖ’d€ ë†1?Â!ºÁrÐ()Ã,™´½n&Bý5éå¶ó-$híãï›ì‡Áš
+ô‹Ó-‹å´‚‚–‹^u/0É0ŸIŒC†¢~E}‡ŒzÛö”Ü4éÈ„Ù@&Fíà‹ÇDD+(@ I£º’²Ø*)“‰Þ4jKàŸÊÖÄk:>j+…tÃy×H ÖË+I=Â$u*fS§ b?ç–¶âЩ
+^ôŸ
+åQN”lÜ'¨§Bª¾2äMÖ£dåÜã:"8>JGLªRØ E!ùW #}hH;XÙ±=£·L&
+z³ãøžÞRô6„ °ãn<$í*'aÖ'ïÚž_ß]5б‡ÿ:Ù´X*›5³˜)à@)(íÀ½Üoz.,
+k©ˆ^ÊlÚŸ“ññG¥¸}šˆM¾¥’_æ`¶±™¾/3«Â:Ê'ëd¢&5²=É,Oå<й=ò¶¼[Ü[ãWS~Yd9÷#=ÇNIãÁŠ†qMŒf7,RÌ­êF]÷Ò+¼Ë{óÃÕÇ+êμ×(ü¸,nŒÿ$ä0
+uêN"v{)¨,xGZ³nñíœGv÷`AR{¸0r3ùŽYÏÿò7ïM¿G—¬ÌiWä-ùUAí>ð}w–û·­7Ü¿f—íÀ5ߥ 3—€1˜·ÿZÞÉþº°Îù:¿Î»’_ºŽú5¼ýu„{° ¼y=º£¸WÃ޾ˬ jrkC׊ÎáÚÝ9Þ?·?<c}UÚU7”]‡‹¼ª7Ý_ì¼î<·óCןç„5;ó‚êqIÕoSOG+~›©Ì C#íptf]¢ÛGë¢úŒ[ÌÓK˜³þÝ#ïFXglaâša¾M'5âRT3L„ SaÖ%ÿÓ·DÈî€Ù É f€ˆÊºOS ³‰ Ñ 9÷Ð9|ëpQÙvs<9Ý6šOS2.î빜söTe× Ãz„õ¥’]
+kt̄бQ3v<&¢ωˆc’„NPæý²öœ_ÞEÕTR/§Fä¬wà1›ƒˆ˜”TÌj¬lYGO·­öÊ–QˤŒz: žÂ]Z¦ÂŽGTäÑs*ñd¡œ¤Ì&zK¯"a¦à¿n2¤î/… 2"h0á‡OÊà¸D¨WÙ\º÷Ì, ïʺ%·ñ°UŸ÷jú³nYk)jTЉ‡/Ê›ög̶ÕQÙ±ŒÓ[)ž”s¨m½–Ü2ÐÜD±‰t|ê§Ó]Ûsèdº¼ï¬§Ã–Ê$Ç&pÐ~ö¯ “n:°²‡ð©Ø—ðVÎ%n,úFî¡!±G¯J‰Éÿq\fßI¤i¾œ«¹ìÙ{<g»=Ž=vtl§ã6®IƒšÕ…%!T±&ì„lÄžŽËØÇÑÖÖÖD‡¬¤Ø 1» Š¢ŠZ jÏ2oÍEœ“â«ú¾÷÷{žgDÄeÉ-ÀÇC#ž‘ÿfœ<¬iˆþPÿ)öþ“÷U2 ý}N‡Í6‚4áÉé‰ÆÏ6^6Ú„ì^ŸvuE«Î¾yÒõ·Â¼®ü±™\èëÈÏZÚ€®,ÿ$>úæ±è`9aÑnOêvÁQè%›–¿/VÕCŠËø‚øäÚÓ†?®?•#üýTԦߞT-ô7ñÈx¿;¾®S«O¤_`woWüÅœ½ñó⌽37…
+ó>å™üT÷|V}5?«¾²çëþš\P_ÃÊ«DP[ÏĬÚ|@+Ø’ŸÞ›‘Á^(¯æüŠó;>iUvV^¸'øCøÛÚO?$ŒÝûI£œ
+ƒ ù55ÙÙÞKù9õ•ü¬êÂúKÙ‰è#Ñ‘­—ª«%à¹B
+ä${@EF¿##à„§±
+&ê4’‹ú2¤ƒ³Íw«¹|ÌÍ¥†ïÛy
+à7…°]»÷¥BF1±`eg`]~´¾E„­%ØO¾7ˆ Z_vž]~ý@æ¡à·;S]§³ &ÑÆœEä¿Óz»Ýz¸¸Ð/Æýh]~Nwcç•îêÚ Uuê‘ôÈ΄úÒ~ÊaÛžFjw¦uð%íú¤øøîtëÑìlË‘¼¿½jÏ×^UôógÈîg%¾—þ•ô—`}ÅE¤qåiÃø¿êƒÝªÿdi¤ñwÙ':à´!r·îO[O%'ö1S'6¶Q°Î·“’c›?Ý<´ñ¬ùÏÐøgÈN#5T¨_ÎÅú{Ù¨¹«
+ÝÖU]¦Ûõ©/2Kv-ppœë6zÑÖ›ŸS^ÈÍ´}A$'¹ò
+»¨¸È@ßVâà¨À>¹9D@øûÚé%‹š…ì«$û5l½ówTá~“Œ\t;²S¨
+3E-êŸ3Nׇe°±U— jo¬½ì©.†ì›ýžÂúzrs|¯èn’‹ ûÆf£—.8›Z&å´—’^Èj§Š¨ë‰`Ûq",­&0•€Œ#7˹• ðÅòнrb.ïƒJòÖ“ÊrR^Q7UÒFà]3ì¡ŽKz†J˜«<ÇTYæóÓÞ—‡üØó£×KTôòºœ² fã!gy·dQl¿†]¾J|÷‚MŽÜæRf0HØ”AÆð?f%•0w˜ËN'Ƨhp&9àN@HÌØF„t Å°YJc¶l@qaÏ/?†²ÑÑ»ÿ÷ݨE¼ÙÁB®Ñ1›–KÃ3;pè&ÁwÃØ.íý¡.´üÇ- ß“+N7ßq$fG(`Ôr-=0\^ÏdìV.å°”"‰Y5‘%_Mxk?©Ä‡ïì/;ɦ‡oq½øí”æÒú„¥1;;haã>8«qš‹‹ãÿã¸LŸšÈÓ8þlíßlí–µ;«[Z5³3®ë¸nÍzçÈR â(˜pHL wº;tî„c@•QgÁ‹@BÎÎ
+ùhž=gb&S%®GŠÀ¬4¼ ·lùù`Õ4Q[ÆuE¸§œO̓̽H“²;5¸ÃZÒ>YOLUS&{ƒŠ^„¿;/k®Å ¦¼•m:5¼‚ß>œ<|³ëÿÙ™ÏPqÛó¶l8ï_ÞñèÕÛ¤Õ¾üV ¾kÐ11­²™JÇÀŸ¼>MZ-{£2ëF;¹rQz]ÌDqœÉÐ`ȬK|¥0'¿Y ˜ôÓʦÂÌ5Ü &ÐÜÌœš!UüÌT둬³÷b9$ïüøkÿ¿i·Y»‡p1\ÅE ºJ„ÀrDy-8½ù¶ïÌæû¡k«“‚“ÅY8ÏP[Ñ%¼V Kï²A%oõå­#+¿Üú+í“óòà1«ÏÛ¿Øšºó÷¢³ïRÞ¼B„œs}úö‰Ì³Î¯s.YÛê þW¹ÑÅj“
+.ªØ|?ØTbÒOÀã0h-‰É€Ï…Nþ©Õ×ÇósòÖBX«INv½ùLÞD/8Föá õ0¡©’:)åWuF7ÿ%>þý˳ý×ˤ735悁ë+ùÍúJÃ3`V+auw™”ý¸2{ïÄŽ[tƒØH‹-@…Ldô¦áÀFÀ:8CîSA ì1ªJ ãÊ~„‰húØ„FÌ&Õ¢zZ£ø”A±ÏDCÇ%í9ØA:lÔÁžh}Ñ4ÒÈâJL‡Ô c?¥c\B-.’‚Ë ¶e%åÕKè€iÌÖþŠzËl§ÿ?“ÇžOÛ_Žø–&_IÏ—½&u5«ª‹1VÞËù‡ZÙEµ¨šVK˜„^GÇO²/Ö* w•$¸R£{bêþRHÓ l©äbˆ¨Ð+²óh/6âlÌì`¢&K=e°ì¯`h=­·0 ¤’ÂYì%Ò6\$ ›0٪˖GÕ´ã ¬T[&,õ4ôsR‡¬}\~ù;à“.Ǭ•˜uŒKáš¼w=Aè’˜¾[zÒqÚ÷S÷ù]ÿCç†wâÙê¼Y¹éÅ…Eà`½A&Š)¨0&ËÕ=±§ücTXÙUŽ(y¥ˆº›Šàr*¤ª„l#Ù£bíƒì‡zÒìØO¶ú
+ª®$ûå .)ÐÞ½y[É
+¶|ò®àØ£Û3²{Kà?q³ 8ÛÊøPÑ3ôßå·Žæ\¢¦õ¹¾«3êK‡Ø…‘Q:b2•Âš¾B@ÝU¨:væå-™×}§·?H.‡_tz§¹vh{JÔ¼Ÿ$³¬à`NË¡Á¶­ÙΓá‰s¿O?mù3í•ÝÙ[jÙø­ç4ãA8,ù†ZK â²³=§Wž·YÑñMrºçÂÙÙC‹=Wâÿã#L\-¢ÁÑ
+^Y[ÎÓ}†
+ˆš¨ˆœŸxzûh-$çúˆLR9
+!âzƒmVp ~’ *º× KóA\• hYŸ´¥AÄ°£8ô“¡±§ûð?P$*ŠNv~•sÁÞÄ“ ðìxÆP'·ˆ‚K¨…TTz—Mšì›n\”y¯i‡q€›<äMÃì¢É^KfØ}}Q‡gÝ¢¶7Ú‹Ç(·ÙVŒÛïBŸRQëÿ8.³æ&²3 _ä67S©\¥*UI%“É“jaÉÀ
+iFö^J¿­ÆÕe¿ü
+iFêÀ½<°V öœ…^§béAÈ0²·…tB‡/6_9fj¯Œ|ët1h&Q›Œ>+ǵ£o6&N·ÿPx¡näÜ eÔ®(£ÍÏyï 'Ô,†3»¼nºôô˜BFÁ¾_ÕVŽ }à,C•°nŠ•U»?yâ‘êÜ/ß®L\®§­kù’ª÷SX|awcòëüý/K/äí5Ì¢¦ãfY驶½ž±^êFó«“Ç™¸UD7΢ÈHe[ÙZêÿ“cðË_l»¯þ£‘q-cê>2®ã0›®‘t:Ù„à\q{ðXÑ/8¹û¸ïó*íàsêÉý°ð<Úô<Üg&jB'Lp˜EU@eïצOÓ‡…‡Ìü]†Yì£Â.=t!åMã8ùÒ0V ˜¡•ÑãH÷‘ÏŠv3›¸ñ¸²©ò«Ò•`Oø¤¸Ç1×ÌXÍ$ܱ·?(Î’A‹”!lærĦ,G:2j7 ‹á¹J¸:¿>yqiâ«_Ó[fe3=s‹Žë…\Ò(cýCh'ji£šOYõ;ÿŸd<ÿ+táÚŸÙùèÄâZ»~·shå|Íœs¶ |ÆbÚÑrPs•›&™˜EÆ¥Ô£õ´ áÁh˜36í[¦áÿ÷Â’ ï^HÎ6 } Üí¡ãêA–0H›ï÷|Òé Àáv#Hÿ^DÓ÷a[Ñöæ¹ä|1bæžJÏR1§‰ÍøV¸Ü<d»ËC&̪
+¦TùÕéû¦áVf²iÏu
+÷γ›“͸f¹´Ý^Ϙµò×ëÆž7ϵµ´ÝËÆ‚wq9ß
+¿ãò¿(9èþZÚjâp§‡Ão¬î‡£ü‹Մ%‰Å5x¶“MK:ɨ¢›#ôBèBsÞŸÊ8tÚ}½šž»Ïe¼w˜¤Nï'eSVׯ¬žPƒ§ÚÍìì2tò]Y‰&(L\¨›¬e͆Ã׶VŸÙky§É¸¼¥°MZŽZÄ{AeW~môèÁ3ÉY*¨„9QàN$ê4Pà3$t4ƒZÄE¿ºkCq˜§£¸¥n§¡;Þ?žz÷pú«²_?P‰hû‹ÛÈÕJP?|°­ï{ýD~®´‰tÿ”´èÚ1[Í‚G!<î²»¸KýXa¹V
+hºÖ%gX`ÑŠ_ÛWE­êûC×ï®OÊ-þñݽ¾ßžþVõkãV- Ì쨯cgw;È€º‡
+˯ð„QBáš¡J¸-æ¥P«¬µ©
+[HwòìÝúÀ±Üík=$¬¦:pI1b§±…’XxÀ´ø,1÷=E8Ÿ6Õí»k’³í<a’W¢NC›§ßÌë)p &©2¸f¸ ÔÈ “ .¼Tð_;REUµ”gžníMÌ7Ç&[^cT6szi#£fÐéo?®õ~^Ü’µÁÙ¨Ü(bàû¸Üì½*°Z|ŽNÛ-%Ì Üy&úrÙXƒßÓ ³¼µiØŒfÕ‚€#)Iƒ„_û„œ‰ëÅTâæ 6ïZ$S&EØt,îΚ¹É¦[Ü <gKc6-CøîbNÛÇ º«‘›Yª·ÖŽçf ›´ê¨¸¼‡ÅT£µôìr!êÐï‡\&†¸ñ„ËÎÜ‚¼Ÿ«eMZ.eÒÐ ½ø
+H.|Xëÿb÷éÐßé€fä0ítÓ!eVv’!`þqŠ|Ùý—Âڕߟ ­FA>¡›bãª>&¬ìaPÝ$íŸsÓ·¶ŒÊ¯æWÛ~w°9wCÞ[Oê$õVFFµCÔ$…ÙºWË9çø´j˜Á¦¿¡c‹l\3TKØôµŒÓËÃÌ‚“:ÈIP\×õ’/-S•-ã(‹Ë{ø´rˆŒiG)Ìije쬰
+©°Ç
+Ì!#C¢ åmÁ)x’MÄÕ¸ILGõãdHu•[ä-c¡Kh\ÖEA¿U E/…«À#5\j~µ„y}lîN%~{“%æî‚SɸAÈcÈV÷±0oTÂíd“Þ[<t=›ùyžn7wlŽfZ'â yO×Ì*G3ª‘*.ê(¢’ö
+j3ð)d©QÊ Ü75W0Qe/GÄà ýûÁi:isЙ™¥r¬8HØ $ô
+—P°IÝ—‚¼OzoòYÇ ë ¦fqe/‘uìnMþó£_r‘É8çþOr™5·mžQøoôª“é´u[ÏtbÛاq/õk³‰¢(’â¾ @€«H-v¼Å»5V­‰¬X%qÁU”ÜÚ’HQ\°ƒ”Ûü¾œ^àƒ>¼ßùÎyWDí<<#äî¼c™‡ àÄ×ÀV±¸+Â/eЪRôßò¤—Í:5íé‡9Xa‚Í°fk—p´³‰º@·ŽÒÝiÐÊ5Žö…ª4bl1(0ô šòCM‰‚’Š¨³•Óöl­ôUJãÏäÍÐ`¹É6dU§™Ö‡®…»Äœ‡ºkÉ{CB5µhËÍÚôI†@Ú%/ô¼å¨Çm}B†$dà;™
+ˆYÈšoÕã£çë릫\Ü­«-bCõŸqõÁ’å*—>#3&`Ì ^8Å ÏNÔrµºHŒòñéçl’Â* cçªó†KbÂmU·³·ôU—†¾ØûùûÏEX3Ÿ¤Ü­>Ƨ]Z6aàhË-Ž¶ vŠnW§H ³4>
+¼òÉçS2„« —’%}RæCŒ´C<¦VŠ˜K.¿âóÁBÖëSrñiCK.ÓaÉihl¨Nï-÷Ù[¾} æ½²¦¿\‹¢:!9ùXf"?JiÊs°æº½¿†ì.Ûûv—†ÿÞH‘ø^‹î@·lf&_pÀwâi2ªoºïàÒ¨˜È"t{j³4âÖl
+ÑË2Ø)ã”X´6S¯P°rEÓMÐ`DÈÞ[ãò÷bx¿XôO+[áÙÃ÷។2ònË fáÿçh‡º÷†ÿ³xÄѦ~>cSIy#tcÏöO#§ª«Æ‹Í¤cøýŠîëŽ)Åð+±yͨ ŸÇœlÖ®n1ú¾:mQJÁGBŽò‰0ÈŽ'BÇw—úñÐ;¡K…8ðaž¡H8]]Rp6"rG%†ÄàŸ4УFyÚ©>„}i—¨OcÆ®%xR$¼²ï®'ˆZL{voAý`~·HSèïzcÝx]wꄸJI‡ï·3¾ ›p¿ÿ§úxuÉÒ+@FB?mÅs}š ØØÏùý>t€Ý¨öëÝã¹æÚô£ÚŠÏu°äÚŸ·]oülºÎn€¦ ì¼Óž>XÔœ’iC_´ÐŒ¹5ͨ—àI!‹Àk|Ê9Ü‚³!Duçå¼éÖü㳿ãþö¨¸îÁ”¬çSˆ®•rivÁ×꫶>>³a(˜ éɾVSÀOþ[vÙDZ{©Õži&l}lÒxMè/Š)‡ú nxî>ùë—ŽÓŸ5W1{gÓþ´éñAž»*1TS‰[o4'+¨¾Fƒ¶¢Ž›B,”bÓ/”tp¢¾n¼²³0|âÃÜÀ‘êâð\Š°î,¢·öÞ!½"0F§xÐÎ;F|˜v¨¸´SÕ„~
+>鯧Pc5jëoƒÊ ‰‹]¶ÌxJÌx©–Ô]àA3íM‡A.ãžh¥™Ý‘Káe'IKK;5l1Ë9‡õ—2‚
+s(›¡§lÁi¬g ßÕÓ†+qý…V~ì—Ãq©0µ lÏÈEÿ” ºmo‡f¤-Ü+ÁÚ›Ê[O{=ì—À8´‘¯DÚ
+ç³I»ZÉ"æO%ù¥ì&:7ÖÕl=fºòqYýW.éTòÞ ô „g<Ëï‰ÅÐS±~Y‡usY·½Ic>GyAËîð ÷r÷àùjÓ$0-øÞLa¡ Õ ‡)ÿ¸’õG”<åïäqLÊ"c|W
+gƒOQ„œÿQOTèðC1M¢-Xg#fé…>båi ä‚]ï¾ßHN¿’ò$)dÐ1à£Á÷³ÃÇ7&¿ûMbºÿO|Ò´è®#ºfÊãªn¸uªÛ‹Ùú÷’.ÕNÒyûÃ’õjfÛ†>*¦­@»íJ³uõ¿óÎtîâùÐG®Ô£Ž‰ËxÀð­ tTHÂR>üœÏFž‰…ÐCèÈvD¿Ùž×_(½RW²¾q>‡:eĦ”\–òÇßÞt£À!V6ƒ;ÅœBÊS>àÈ ðê9±49/}Ód$›1÷WÖM7°OM†">.Û{¹øăVêî\“?hÒ>o#åÅ[°.6ç!9†p Yô¬@ IOΰÙVZLpò—iwÓVÆ?gÞuÎœy3§g†33¥N ,¡’=ÎâÝ–äE–-¯ !@ †rÊÐBCÈÒÄû"˱qœ MâX–¬ÕrBzú9æo^Ü7’-]Ý{Ÿçù=ü†—äónG%‹ ¬§©
+øÎûʼn–ý%íY%‹«n'ì—^‚¾ÂÓb|.0S¥<v²@-æä‚7
+=*¸j?Ù²›Ù¤m`ûµíÚÁškP¶—’öA>fj«E ×ù8°uØÚ%DÐ8ºžsÛø„­zHP¦`~1EÉLÍÊÙ©ùúFàv£€Û˜¸î2Õ_î™hž/.€Œqc\
+×sQ§†]C:wšøüý‚¶E¤ \B{©Nûƒ
+}ç…™yĦ C9†vóÀøuX'roãØãá659%ж1ÈlÝÞ*ÒU¹I”¥›Mê/3iK—˜ñ RÚçªg'gkgÄa— þ[
+ìg£DÀu—™‰Úû¨g£ŸÅçnþñ7èžr‡Þ‚I9ð8sG%ïäŽØrÚ•¬]§Ð8ÒØôÏ)[þ»êVà¾R ܃3j”‚óGۇʦÇÏoØþºµ òxJ¤§îW)ÒƤC“R~æ9øãí&ÕÉùŒ—é@HÞU£‚·XúÖ<—½·X£çÄ|ð^ :lSRÁ_÷þe÷ i8Œ~Ÿa2ßÆ+Ùà,pÕ]xÞ­z <¸¬ž'=Ð=|<˜ª¤Åyzú1 ù4-‚ï×(tð0<~¾žh­%Ñþã·¾ào¥ÀÜqÞkA BÖ7%C!æë´Ëªæ°1‹ôƒþ{”<+…À\%cÓT(`žâíAŸ M¯·É†uð9g×U~±^+¿±\bÖ°.˜·wj„¸å:³j8¸bnb¸¦¼ˆ\Ù{eøò`Áx¶‘ó8aq 4½MËF±6†õÀ™?zë†lp«IBÏ$ÜF2XŽ{9AŤs¬ù»2<— #]\¡Ù_G;Þ½F¿ÞyemÝ_6\â¦öʺ¥ý0bíüuÙr¹¼â3l¾0|µýrôŸ‡à?,xy%Œô42^¢‘ò{¤Œ}<:åÔî‚å&óÚªRßÈü'ÅÀ㢠´b›àâÖNÐЕò
+ÚÆ…‘v!fí8Ê9Í¿ƒŸžÀ`Ìšåè¥GÉÚ4Béæcæ‡+úVnÍÑ_§îü eï
+ãI<])B¯)º]RÓ(ЗªÐÕ :b““ÂF2Ǧ^#ÕM`mšÄå6.d0M%f¨ÒµÔwGϯ‹ù©oY¸.Ò­@#µ´öj-IâlêÁCͽx#‚¶”âÔSù­o’MbCí2‹y7x0pUvú;>ð«…ÉûJnò>÷BÖ…À»Æ¥4¢‘3)À¡ê¦mä\ðÑL£tg¥¾3ý³º|Ø(8ÜÓðiä&—²v‰Òǧ­}àY7÷#„Q &çëà)Àp„˜ïÊ9
+ô——u-ïž~ºûrⳟŒ-ÛÏ´ÿ¨®"ת«¦Vî•—ô-ÿûqô¯;Ïþ¼ý}Ï'rÂØ&'Ñ>!n ?°óU.bmâØM9éÐTWíÝ̺GË%¼6!åspa|¸ú Öy°d<ÏÂ9¯®Y¯UVˈ³ûKºï¯Ø;v,—v´gØ°þ"6\ªÂ¹®F-m{ËúsÉGm§è§ÝŸ¼ ÿ’F.†@·5òQ[Öž+¯Žœ’æ®ÃukûÁô›zœ´C­ƒ? 1èq¬·²l¼p¸¨ýWeYû¥˜°våÐO]N5ïvÖbNÍáŠõ›Zíj
+(Š}qIÒ9Iæ$™˜N›Ä]YD»d+¶bsIO¦ÿ¹ôCΩs9Uuïïûý~¾[ÏFA–üçdWÊ9Ý•p¿|’K¢NaO°´ß*í;Ô£ ¸óÙ |í—§Ea‡{ŽQœÙ”q?g{Wt‰Û4µ¦àF­2ªG'n;œx8æxUʈ˜8w’ËpCz™{÷dYDJÙeô“Ý'#éÝ'¯ÓÛÏ?œí=8{žYU°“N+jCïùæ©…‡s´Â½32 é Œ¯‰3[ÊßAÎÞC©1¶°vÕæ›þ+îqV¶€Ôy”Œ¢È\1Š‰Gjv•k’|u{„øµg¢çJÄÈ&ćaö!äÓ4T5rêRËüŽ8˜ë˜EÔ˜ç|ZîmL'löÎrÊ"fÑß<·æp‚qÓ#5 ïnÌ¿w––¿ûžtioŒvíHÉ(ÆÍÜÆä2·Õ«£•¸Õ´¢ˆiŒÙØ ¸i - w|´vs”t94ÏkÈØeÔ”¹›°@•1¥8¬§Æ PyÚÎmIZùÄ€žCpM@ùñE)É«$åzg:/ÅM¬š´]Ð7Ã5ø»>nFZZnu¬ $,
+JÚ®€b&YOlQFòkyàyÌ^U_žOC)ˆX˜„¨ƒÝ„;‘¶”SÐüʬòˆ)'Úþyc@t²6$J:X¸MD>ý8$N9¥´Ó 1”ÍëlFáKHsÜÂkßÔïtÊ!ÜöPˆ/?–‡Ì""îÒ’I_t‘S22oE­H³[ •x5pyô’è¿-bB›26qÏ—u)ówp¥@¯ñkèE « ·»Î¶þr:äñªœ‹/‰zq3¯5aFƒZ¸üH¼Ïˆ6Å÷¢F9)lPô%írn•’:„à×2ËbvÝɆ„/ ˆI‡”r ø3 æ)±> Œ&ˆ,Ë™‰•AfCAÖ#-+» œù=œ{ÂS+‚îÿn‹geLð¼„CBI®
+ºÂ6v£{ªˆ9„Œ/û^}Þ’ñRkh÷ñ¶Nm‰è1'¿=öæPÅ­Ø{¸Æ‘²ƒ !aù)é‚GÙ_|
+üþt™8ðOÜʨN:8ÍA#¿yg­ÚSÁå1“ ÌœGÇkrø{ƒƒgëàùKâÎ,EíÃîxò(j},wM‹ë#æ!¶O¯ ûõ‚–¸•Ó\ —õ”‚°…T€-Ò+³÷:yïÉú“g€§j“k´
+|‰Z™Ø Ã3 ÑÁYQ1#·öp†Y䞆K|*¸,mu,Ëh!-³2¼€6E ü çÛáyZ±_Ù“ãîýÁ rÀ¯î¿îÖrê/ZÿæžìÉ?sJ™13§Ñ“]£ìºP“òÀšÂ(ðê¸YNN9Là âæ‡ì°é!ì7HÚ·ßQØé½°7FÍÙùÐwåH •ž8ÅÔÓRÐ9!jF›3«bJfMÆŒY%=Ç ßžnœn ÉÒ+êÙîà
+¹›mÏÎy^ç_9?ÿÀ÷õý~_ŸËû£¬|ßÐŽõ:›(I4‘ýÆóC·$XÏU!ÂyU˜ëdì øŽÇîHKâ4u$—¹:¬Óš˜èqôÌ¥¦4í\ÁŒ¿œ.Iîs8ÁŠ9™)Ë\îDC-™w»Ê#ž*Š¡gw§f@Í#ä@]3ÊÅÐw7F,‹‰ÛÝôÄ_ÚZàùøã/Ì“”â¿ÛIðØ‘à<®gÙ©­ñÉ&v¥äçßj[[/Ô5$ó(ÈfvìNÑ{I˜î8ËM¾·×…÷Úè †ÉØÉ`ë%þ»,Ü…’z¦ CN@[XßU1Üép„ðúÇ
+ýßíOâ]-ãb¥šr$ç$ïõÓ‚‡ió`ÞëUQÈÐŽv³M¾5öE+„ˆèËYfÖ/=¿ð¯M>ý‡®4÷z© Î6Ið?èÏy±%É
+á¼;ÈŽ³N”¾7t‘}®Ôe/gÙ°5ûÃédAØbC²£ös¶Ëf;ÎS%H™Œº]°Îäåé—Êò ë-dS‚u]"—êrž¬|ƺ Ðaªªs½ÌÃL赺6Û‡©æ~ sE€?%Ó`^
+ëw2‰ñ5ug‚,ƒXßÛ¥rT;îù¥¼ýàMÛ4 j&ê;²Àípçå†OVÅh7IaÜã6\Ø}Û#ig0ÏO#€?š©H·Wò³.Õ£Ÿ*¹É¦˜ gÓŸ0’ÜÿX©GB.
+äçlu²Ã$ê(D…þ©dxý\àaŽF(« è½12do
+# ÝTC'ÀÔrVâf'1h½™à¹ß›ðý®3¤´ˆ!ÎG×B ´Ž•§ë›É^ûƒ%ïôFЂÚlËóÜíc„."xóàAvú€{'Ù0eu†³‚{°,HwÜlÁº{IþçÊ‚èÛUr©=ËWÊzg§ë ÚbîîPyò‚ˆà#çd¸ÈK3AóUeqÿ¶Ž‘c­Sø ³ifÊO¸ùïí:¡U†ö¯‰·_&9˜z®&Ix·›øÒ$¥C› M#)ðz¾¡ä§¶¶èfžr:F}{4D…X†òwúñ
+d n’ÐcLÃå¡Ö z̉Œ½ÓG’1ìd±
+ÝSVç¼2ÊÙ0Y5Ìq€ý§Šf§`g<üRo7ËMp8¦Ä7”%:Ä¿±¿T³1f95jo
+là<‰w ÔäKTÈ…Š©ï!®tÓ“æ[JÞœÏð f;åHR~&§ÅŸ)*
+·ÅŒ7s Ð#óÑV[±Ï7öo}SÝ?×[…ç3Íd«²‘lc'ïûí‰Ñ«87U-Ü~´rÿ°eUr‘kD_Ópu¶YZ“5J½¯ä¤9l¶zê»K
+NÒÃÕ–tÇ9¼Ðœþd½)ßÅ"©LÐ;ؘloe`ëy­×îVع—jr‚y$ß«5ñ±q¸0ðךˆ 0|ñF7ÑÿdŠ›½%&€µB¤Ó‚ ë©´*ÆQú!Áy£ é½×_ìw ãäuSœ§ù¨ðï÷V]S
+â·íÜTKÊž:´‚ÓyÒuRC.ñDN|혧äøõ¼F§Œšç‘à,C•7{Jî@Z—ú—$—™(û=ww’–z¾Ü×0ð’;[$¤¹å˜¸óUl†_×ê„tñr½‹í„z¯e‚™eù¤Œ’wª£vª:Ä„¤‘šèƒi|¡„‘£éÇ>Ÿ£üºÛWÿÜ-m{
+òë‹üÍòqÀo‚öÅÖ¢½ñ¦äÃѦ„ã bÂá>Æ/g¡œÒ¶R-§àúîpe”{ž–ͳ*È»¡‹Â׺kLµ¼ƒ0U2tÒ¿osÁÐØ\¼4 ;÷gpÉËÂRCÅa&ìw›¨òZ|œWÕI±Š)YŸÊïÚæÐ1!)ÂË+¬éS‚(]gU”†Uø$°ÀnØ«ûÌ«£—û ìy唬s%!= ¥AØmÎ?–ßØæˆiç+Mk}Å÷˜Y¿ìŠÊ£VzQ±‹œ¢‡ûcÕ1†vÜ–˜”ó±!ã†NXWüÕÐÕn«‰Ú,ŒXæe]]d¥]³}F= ¨ ojzé Þ…O¿¶Ô_ ;[ab7†ª£¥­°-?ÿß;¢ŠÇ–Ñ’G>)Û<ŽIVòòïz—hH_“Ä@ÊøæÆÁtõ›¢!É&mH<]$Â\Š–è.ÑÖYFiÈØÃw©™{cõ/¾L5ÄixÈ?æ°«nUSV`“®Ï¨zøÓk;³ Ù¡5f½Wä9æÉ1ã`ª*JË…EHo‚k\`i ö@„;çÈ9>MÕ£ ˆ97µÕ_l2ðuz•w­ í_ãRgðˆ­òç!}Ù·ÄkØõ—Ðÿ?6ih¿®>íĦügÿwÔ#97Ñ1öùšøo›}¢oæîž‹ÕNàt‘ŽtBúyâHÝ’/¢½ ßâ‚ònŠ_ÉÁ4̪Kck]Vw,Å'9;ª‚[ݽn=£Ê&®sKp‰cžœH+bB«ä÷g:FÅÅ:HriX•6 y,ç£Ì#Ä—Pî~åüÜ”dÃDCœ¿»7‰K1O6%S×æZŠnÙÅ\”[É©ÞiˆQóÞ‡-vä\7÷GM “s„×m[¹U
+doˆ°ƒzÞ­$ÃvFÞÿ!§§_Uƒ¹aS”´_f(é¿Z§%ê~JÒ'üÊJ:áÂÀ$~7ÓÑ_t”OCÎ=˜A?ÝŸ.~ð÷¬ß7Ûqnu Ò§ááÏV»Ác9³Øô±òî#ûW;?RÝŸ$%ü¤dgÞ4ãâÆéð0˜wÇ.&çy´÷Юë.W@BPϬ=YÄ$¸õM¹£ -`2íóì‡ÓÍë>õdýü«Ž’P5çØf IvIã[§œ
+÷©Á:×£ÀØŒØÁÅ9•Œ§’–4pð!“ ÃkèÀÙÈÙ¾¾1ÿúˆÌ¯ïÀÏâ^n~ªŒ\ë-¿»#ÂÆú´­O~Xî)ŽÔróoúµŒ:ϳòø3>y{¨ôžE„zb“ÓrNí^µ°Å¥`VXD¸x»„‚„xVâ×…~ 9ûË4:fµ§è¦3çºKE†VA²g‰‰Ù!¤ù |šOÏmr*›‡Sèø“ÏØØ㹚n q¶Á¬sC!Ï!%fž©ÈÈ Ž?×¼2òo)Ú2W± |Ð_vÿb™C¾0u ¼a›o©— aµñTEGÚ¦ð±›C¨?M¢ºä)³?Û ûaéxTÔbëá¥EÔc—7üzjÑ©®¹È¥¡œš@ê§,‡J¼æ”3[/6GæO×z…CGUAJßã“ýFˆ+Û|Þ%½4ëéÍô6!ÒÎL½#z8{¹?Yu4Wñhw¢(rs¸èÉ]~÷å– wêG¾e äÒÜÝ4vµéy„3-Xë’3 OæZá{³´ÌQ*òÎ*»)Þ/¢;Å|ÔH¶ŽiöiÜ-gù <Â釲u^(Ÿ&ŸkAœwö©ÙuÁe.ɻĪöêhÅ95Ó)£Ãí
+°l”’÷›QX}4¤zÄŒ|¯ŒUåRp±‡3m¹=uQÖ)
+
+6zo‚€‰XbÁÞ£X°¢(¢#¨Ø jÄ™dfn¾ÿä{çâ\µÎzÖ:û·Ÿ½ñˆÝAr¢mš‡½Ô Ê÷FHQÛåaÖ>RÜ9)ÏX_´Vñ17aỽô<ûB5ß6'¬øÖCLœSfyŒñrì¥òʨŽSRv†ÊCLmh˜NõÉwµ-7üÇ<÷¼;Òr
+ Íhß? ŸëvÀºÑA ]çzì÷–}8!£ÎçDÌ‹Åj¶mZX òŽ¹˜`wz°p4ÙY+DºjÅIîË™'ڲ俖ØEÿé~w„“}:UWu< ò:ÆË0·•2ãoÍI‘®–žÂ€ƒò—Q¡8¯*9à¥ïöò3ÁlŽ´ â"Œê\ør
+¶5AFnŽ²Š¾÷‘0Wúš&»IÕvø#srÁÞ4}±,âÿ\—}¶¯H%æaz’¤$ò‘¦¾(ûÇwEëè'Û½ ×k){ãIûÔÜã)&æ/“DdÓó*–;0þ‡ÓÔ”ýzÚùl]õ‘¶–»;,)Xk¥„‚QÑs’ƒw׋z3hŒM è*/tëÀ:’qÌŸ+ãöºißԄ˱ÞW¼?Îÿ¹Vr<Uòjd%æþÊÔïLÄz ;l³]gnÆ.*™odùÑ}Äœ{K2&l¿«µßUõq¥ƒ˜®$ø|—Ñags[#+m$¯´2¢Og붆„è=0ï\ÎÊèÆ/hƒâã}k&Ð6"ÈÙè¨Î\R0` ¼ðõ:Aänku¦­_Y¾Û&Ï_‘×$h©,E.5à@-+<îߟŒp³Î¦¤l›N=d›ý,<â£MÍÅA³ÒŒ'æ6i¶¥¿‰fî¬ÉÛhâGZ;kÐ-ÒOM‚˜qÚ*8ëW6Á«_òhUÊŽ?’—nõâÃ6{±p›Ž†ú±ÈçÙMõý—¦ú›^Ê14c~_mÅÁÁ¾n›—¯µàaß0Þ;]8ØaEäé0u1.@ ÈÐF• ÜÒ"Ï8ûÚÈ>ûú™²×-H×+ò<Á<˜a_•ˆ/Lu½»ó2Ö椠À:ÉGΈJÏç«WóRæÙ”¨Ì:HÚn/}u6ÊL¾šÆ$%-·º Ù®«JvÜå°ºþR+gY{ËBÌEïG)è«U»}EÕr¹\#?™”Os .—d²s}ãj¹Šv8Qe,~¿Þ†°ôâ^oõÓ’ëqIÔåYîz)ýÕ^¯°ør²N~2¬ m¶0"÷»8‰çšZš¥³ªdQY°?HK:¡%Íð‹.æ%ç3)3Šè'cUQ.ænü‡ ]]ÍŒì€i­•øÚÒÁNÝ3ÞÎ5z«ŸcngÅëÄX]öåJ#ÆØD†¯¶¢ý—¿ ü×Ú ÞÚ×$Ê_–Æé¿7T{ãôSoEÄá‚B|¾Ú<n_¯í°0¶4øx]Cîsc[Þó£)rÒŸ¦jÙ•IÙx¨•”YûØiÿ»~-~éþi¨k>ž(K\mM|þ­;ËïpŽœd7 –>jÔ÷ѧéZNH7§ô¾šVxG^˜þ51òZ)â=$ëw8þÜðzxp†:îwn
+•yCœ„r“þ¸ÆÌüãZ\°€ xáÐTžãÑHH2#Çöû*ÓÆ„8s3ÎÜɈ°ˆ³W;%i“
+6¬›MôVS+Öao
+>~r$ÅÆ8‡¾ƒˆ±ŽÒŒ(31Ì1'ø $ÖÏ@x?¢|Ÿèð@H;õp£]˜~ ‘ã&kÛ2‚±›±²¼ª®Í¯­Ž®¤<릹öSK݆Y´À~
+þY/©øÑ,ÊêøÔ ðrub^<s¨ü{{ˆñ^h F€{ƒsaâÓÎŒ<âþ ·h¹½>£*ð·j8%z¥tcH=&*{2Y…÷š—ƒô2R蜘ðº¹4å® #Ú‘œ€¸Ž òs ż¿ÉB†C±a7LõääóY>õt^@±ªÛZFŠuœkÕÂÁÜ¿7&*Ziá ô*n¨VÆ{;ZUÐMGyÊ âî㢂¯c£?8¼÷qü¸
+O |œqˆŠX¬J›VKã‡jØA”|')6 *ÈËpÄ%DB¢½A­za@~è[
+D’IÀ¡ ŒD²·xâÜþé9qawFR¿ YþóztìÏážï/‡LèÿÑþy³§òlÉ Þ›Ö fÕ2š¦ ×]›[àVŸ\ ¢)dÈ`³A¸“€M ' ¨>>€sÃÂ54¯LÀsu>ù`RŸüîшìãúÇ—=çèçíáÎßW-•;Óʨ%[+s\YE4Tˆ&/†±THºÆaH0Ð~þx<°ÑŒ`J
+¨Ï&»SÏ T}Zÿiä_»NÇÉ¢±àõ‚I|x¯;óNo[PG©'Š ‡8ƒC‰øR¼|P.ˆŽ²HðòþgÒ{- 8 4ådºMÈJ°‹ï‹¥ÎÂÿžO|;²t~>î}¿9Öóqßå<{2¢ùuH6ÜZç©’`‹¸±˜Â8>b\|ðîÀðõCsƒ êB‘–¥ ×1½5UDGÇÈ7wÛ…Ïgj˜‡må+N#wÕaI\uŽä,öØ8sZ#ãn·-ÒÑaÖ”Ëý[rë|4e­¤Þ:iÉ:U´éü¥ýõâ|ïÅÚŒõÃæX×ôçûòÂé¸zæ?ÛÓî, ”­ÍY2–'L¼…~ ßÑ¡b:•ZÆŒn€ÓWg`¶µ‘d…u¾†ªj‚¾TJ0——3ïjÔñû“Öªóå.ÉÙ¢œñP'¾Ü³|Øq˜Ïל]¿­ÌŸ/O*GUeDWGýµÇ.Gñ¼Ã•kWûêäÔvéM/YN5>%† ‘$äå@`‘ƒ $^ˆ7V42î¨õ‰Ï§GªŽïõ|X·7]nŽj?mŒjÞ,4ŽªÊ)ƒ²bïõmìúˆ%iÎÞ3Ñc5µt”
+%¸¤ˆXAÝÉ$¢~ åB&/ÉMœ”áV™Sá&+ið´+ÚBÙU¼ã¹ž¬/{c¦Ë »ìë¶]ýý`dâÇѸëÏCÇȧ}çÀÁ#WÛòÔŒd¤KÏj®®öÎJLÄæÄă8!b‚c€äC„„,¼ªVA7ÉuœE›%ymÈ"<½ï2_mMO^¬ Èþ^—O•WOÛß­Ž*^?œÒíÍKV&zã§ú4l]Ë-j}~)¾\˜ï&䧢Œ³‘w)@ôò‡(*Dlgy+}Þ8XüöÑ„õjÇÚ~µeªýörØþýdzíÇ©ãÎ_Çã³{6ÕÁRwÞî}kÑ‚Íö“¡+dPÖBí©©%uÞ¸A—W³“Ò<R¢b!/1ŠÒ2ݤÂ<¼89#«¬ô2+Û˜O§Œ¢óåÁŽ?ž8-lŽu_nÙÛ.V­µ‡·Õ¼W‹}ÅgΞ­¹Á§¾•ÞYYè%IMô¬‹<T7¤þ•â /~X0$„Çàj%uÔ’âBu±ojl# «4 ÿ§¸LŸÚ:¯8ìvÚét¦Óf¦Ë$i;w’¶nb»¡N ÄÆlc³cÌ&Z@h—®t¯VtÑB¬ !¡åjE’
+ê™EJÏ!bö© "¦ÌÀPÞ-òyG.(‘Ÿº|ÒÆM;!RÜÎÃ"<ltG2Þ˜Ãz5ìG¾EàÙþö¢àа*Šmiy|â` Æ$Öè­5;€­¡|¼BVaôŸ™9˜Â,)Ø–¶N°ìØM&1ëÄ*",³ÛcË‚Þè*<ìZV z6×@deeÆ+Ú·p“–Á¸!ø@…ÃýÅ"½ŒoÊÉyD.)!r¸ä‚e70Uñ¤ªb—ÜBΡŽÙ±·8ý8¾É}›Øa£:Ñ;‡FÚhoì Ê.¬j±ÊdÍ; ^G›ºîTÊ:Í
+øÛ>ð¯U±è‘e}n4n—Ð2Ÿ±s†’&Æ«C-ö‹Œ‘üêû(l¬ì3ÂÃC3©Ý³ÉíXŸã4l*„õjuq^ÕOÿ¸ÀÖDš–%xÛ¥b7E×eñM°ïÌFêÈy#Å P”÷Ï*r¾9MÖ§X­„f5—è°ê£¥-3/b&R³M5ö™mö@'gµº_þŠÁ|¼$–?Uóyõ:©àk5÷O9O|kGɹ{`TA÷Š£†WKA±¬•«û²RP—ƒ|vn—M:}û†™V/š6ï±CÜ­KÃÆ%‰O'q-QìêØ/v”ÌÆ5Ôƒ—@â?­·3/lóèø]!±èƒ8?„!Á{<QÍCÃlÅ6ÉO @_Ú*¦¢=¥ELìžà©áhc¦åÈ„f—¤ûϺ™G¿Þâ´ÿ.´ÊéÞÕT–%õ€yAÐêZ¿Û7*i»\”u‚”ã ܧ¨õ·'›ÿ>ßÀ˸*X
+0ƳZ_Þ Rì¼ñ°Y8n_¾Ú™´ZT³íV5ç>²9¶¹ÞmÅTØHo觛÷tä¦Èþ«‚¢§­|BtiâNÊ€»ûŸÄ¬©ì_°U°6ï‘
+Ó!õ uƒä6¥Í&þ¾÷›Š –Ü<jÊDyqjž|’Ú&>Î!(«vZOÉÍÁU‚b陓;Vt¢Üùæ͵€Út€5µ°x6íââSvj×á&®ñØ8ù$nšêF]að2 „Ên XrÌ¡³ËªíN÷U}Ôá”ô홃5\rÏ)³;³`(iŸpláÒV »è±s¦™W™é–“5òÃÃujK¤ä '¶%Á%¶g§Ž ÐP|þ,gæU]VÖJzý>$”]ÔÖ ÿÜJÑÅÆ=¬Ñ¬5pj†“àmÙ-d–="nÎÉŸ*z¤ÒŒ]e2AÊƉÉÍGFRsÚB}™Ú¦´gì
+tDµ¢þœ}ÅRÞŸÕå} :«9u oÃ?Ilôß( „çW8ïæ“3H-¤ê\^‰{ææÝêå#§fù‘±ÃÔæˆꙥ„$¨™Ä‹
+ꃸúS=£»ê•kË>:.aÄÔmL4¢<¾¸ð’ßíãmWA:ñ*,¢w`
+.1ô>¢´žïÏ™2YMÎk²^©,…Ї2ö™®œ“ƒ)ûþOq™=5±¦aüv®¦ÆqjFÇrjêhÑ)u<‡9u!ƒ+‹Ù—H0 dOHg!;tÂ"‚!A @ölÄ$@Y;[g#¸žÿdÚ«îꋯú«÷y~ÏóŠŸüíh|éÔ/•ÃîPÞIë;Ù#wœÌÞ¤Þ”³²û
+^2rqYûm_:ýÍ/öñY«Ý¿Hø¯k3®áãá]ùÛŒGþ[Ø ô¦}ÒI88¹Y ‚‹_öEà‰O Î:Ù¸€ºëZÖEÇä]à«‚œ†]c`ɯXA´%„‘y–ì<BÚÈl ½ï¹RvþÛ9ăuvŸqènb“ÙïòÈY¿HT8
+âíÖ‚C,)îMWüBaÑEï)»ý%'{0¸„½‘ÒñI'Þ)UÒ, ‡µ d¥ 3(ŠDŸÓe·˜ÿ=GÊÓ²W,„£ä¤‘ÎØèíy*f‹vä¿Íä¦C¦Ê9Ó5ºA{\rŽÒ*¡¸Ëê-8؉mVWTÃl-ºEÀ©O"‹ìàD dt!øÊ„ô©”…ý2¼ÙóSt{v11EߣÊ":nßáæHkÁ36ÙFIÈ]X‹ˆZ´‹G`„9+ùYÞNnÉÙ«œÆsšÑÎë–ÿ"¦¡?‹éˆOc&jKÜDmNZ¨ y'[ðŽ½Bt·5IØ›„Sv ²›=X´SŸÐW™7þ`–ÕÿP´³_f,bæѳҳúN}
+©§äV¼]ò©´Õ ™†ž"ù_ŸÔëÒH¶d‘9¶F±²ÁÚ³F°¿®à™Vfœò©Ò Õ ÕFµDTÚÎGö<6:´J®‰mÝ%çäBÙõòvP’5 É©:¤ÄßJë¹ýQ5³AÅh8sðW÷%0ñþs\Cz%…tq$ëžU„jïæ&ìæQ3ÀÙ#0¢f¡¿ÀùÏApþëlîË¡dÞ¥t¬¿¬Ú[ÆÝ o0mPka‹`øÄ Êó)¶
+Éi2? ñ¾c}~ƒ:R1;ÖP6Em—L`Ó¥”™5p²'| ˆÇË>‘ e¶y˜´C1WðN¾‹o3;}óÝ—ó=—`#²§y
+66±Ž¯NÅtûì˪³$TÅJózþ@NÃjɨiOBó˜+¢ÅÔÖH˾’xï7ê¢ÆkN!y›Üæô©ˆ·÷U½Wýªž«ÞE„Ã+ý?uK%‡;ô¥äÉÅ j°ácP¡,yÅ"Ä·/ÒˆGöW1U[üû²€Íÿ´½&ßõܾ[~œ\c=þ?ÅeöÔ–Fñª~è©©­±gºÛ¶ÛѶ§ÅУÂ(ØȨd5ìK „%„ìû
+
+áç>Ï+%ŸÌò­c„‡
+n+Äúªë¡ks«n¹®`ýÙ(,½ÞDç6PüÒÎÇç&Q2P}‡
+»sI5‡ží ™½öçɽŽ¢ý%X–uºè'ûüW¿‚ÖðqƒòÒ± æ7 ò#ÆWÓIðVÇ í nÉ¥Wí¹_é‡aÿ)­¯q/nÍQŠ²ã†ÑÓuz•yyÓ,lø»YX}EÁ~ò òµy zèç’ñÎj‰©ù¤°’VSãK?YØØ̘4 y™=¡àbø¯ƒN™i3³+©£7$AÏ
+®¡òu×\s 7R;ÄÊ B€v,“ î5bQp‹Rî““+]«”bç2î‘IÜtÛ>‹zâÛæc¿øyØ( ¥­ƒ¼„¾¯7câ‡tý¸è.“±‹c¦QÑGÕ`wÀ0ñ&¨á”\xDE«:^DÞ;šƒCŠ^hT…î^kË5Œ¾¸j›‚Ý8·q¨‡£³q=©1¨ú?Åõõ–Vž‡|v2;›q63ÙI1:é1Í–hbbªÆ®Ø°ƒ"("UŠ ©¶{cŒHPDEÅ‚4•¢(¶äɳÿÉž\œçwwîÞïûyÑo<j|¦]V ¾äB¸·•5)¢Ú7`oå8&¿ï)gWà÷õ
+\
+è†L—›äR‘¡=Ÿ½­á¼¡¹Ó£æÖo+êÒbÜ㇒;¦ÎâÛ"vú%Jç:àIQ]†±-7d¹·ð®mùtR~q‚Ÿq~¾½ ôpšI8˜ojwMR²`¿~ï@«“èR ß3q¼Èå. ©iú•a.µ$°Ài°JÉ©ëØØÕÁÊðÅö¢ÛCˆ(‹ðZȆ2²œÙU²ñV!ṧøª¾­àŠñCéM} ôŠ¡²Ò{àVU«BRòÒP-˜A>´ok‚RâG¿],º)Ä¿:;A{ꛬ«ôél—œQèŸn@ê8´#Ð,`–`.1ꉹ;ëŠòü¬y°*zi°ú±±qgKÄ‚ùÕÛ
+
+Wàž¥ –ÖÑ]3ïƒk–sÏ2ª\ ¯“„l¯ŽTXdQvfY§ªîmnZ±°7
+s‹ò-19m©»üîÚ@EĶ´æµ¾=ÿššŸya¹ñèÈÐÔêaß™zKÂÌ—G/öWD¯ôTÆnÞÚ×ÔÚdué6=ÿÔÔ6ðÕÜÒëÓ6 Mýe·–ú ¯-÷@¯‚^º·­ åoŠÈé†6ÄMë)Á7 m"ì˵aÌÓ)>üÆDb¯(.h›zÑñ™óà)9Îδ”¾ h•ÆÎœ.TÔ™ú´«?Èð‚œ#Å‘n¹èÜv%6Gß•w?``3ŽÌ‚V4º¶v °n%¹`ã3"Ò¯ð§KÍÝF6Í«¥û4ìº=5­Ô;A̳~DÅ[ÊÂçß—^· bãÅÌÒ(AÙ‹`ËPÍ+§„Qâ”ð±žqrºGLÈ°á²fšJîwVÄýkš_üjWÉãz• „†ŸôŸ¹÷ùw7†‘ñǦzÜMÝQèénØ3qczØws¹ÕÔÒ-)>Ù1ŠË}•dÿ :f¨2ÜØ\~œšy‰‰üiŒ˜x÷Û«É7M)ØøTñÐ&D<Ù–á³÷´ØœoV ÑoM#Æ%­Œâò¾,uŒÌT‡°$j}j+‹ØƒEŒ€GË£;d ¨GÅ®q+™åƒè¤_øyOþ1TpVFKü}µ¯0"0CƒŸšyÍGf‹™ëG• ãÙñBŧ%¯}FÄìé‰Ð­ÉšÔ¹ÎBзTä)è'—ŠGÓtV‡[Ä”,©sÜ¿Ò£?]as}ŠªøþÜK_nˆ¹7÷†G‹ÎÙÕS*Ö%¨gn=¹Âoy/:^ã¶|Yç4}±pxûF&έ¥—ûÁ{µ7Ë&HŠoL|n@Ï© è¸Ï$ á”lÃeaÎOÈè}5³Ê!"&láž»Çë²¼JbhŠè)"f[všV²¦`n*˜¥^-›°£!ø Ø,ùúû·?‡Nók1Ù‡óLèÅúÉèýiìå®W
+~Øû„- éíPI¼º/ç‚qôu‚¤#ç§IÜ‹+@ òAÆì0N´½jqç;ÇÛºôß7¡Îˆ‘\¿;‡ÊòÈk“}JàV™Øc³°Û«d#Röæ©ÕA­í‘ã²íãõ·¬#u7æÙåqÝ°ôïجK;Rtž}
+•ÎE¤Çm+:A-«usªé‘õmý-³¸ægÛø럔c–N~Ð äoͱàGjv˱EØ÷eCØÒÓQ¦Ø/^eœe°öÆ®‚T¸§„šÖÆÚïûÕ]Lð&,ÇÛÚ»ÃõIg'Ðiß.RŸþU ž÷É[ þëîñ¬´¢Du÷þæ‘’ªb¦^qÌ1N׈5ÇƶrÏ <Õ4RpÕ<Z[ï:2ËwWDÂ9Fõ‰¹G|l€è§k\RXÃ@ú•˜÷TUÒ®¼áñ¿7ƒûúž¾E>>dê~±AŒ€š?\Äåí|lÉœÂglj*îÝÓ Ø.µÄ§a4ùVØh÷|– ÔÒÖdS²{~Ã-®¸î“ãJwU”ípÃM×G&lOÉkß’ó·åÄ—[³¸§ž¹¶§ûjBÑ‘‘Ó0 L„Ö†!Ó€ôØÚ/=±
+ºc¶.ApÎxI ¥Ê»ÂBh»!÷ ñ|’aB'Ú›né…—6ÆêzdmÖqL²e”úØ-íA9%"”ë#¯Þù‰Zè~Ð1Ý’aŸ®M
+hõ> ÎyVíž’ƒô¯ˆ ŸjÝž',
+°±³„Ë÷(ˆeQ‹¨ÿHÇ'ªy8¿ô·Ž‹‹­sÇfzËÎ\[¶YÜpó³—éYàb\ó|´eŒ™mäæš» ÷–5ÿTÐJ.®ôÀn«kßuäŸSòëxg0ÛÛ¦ÔµÞ²kÞéÆôõ1x¢y 4Þó–5·— d¸S†{îž%DŒnØ‘-<VÄÌ¥ù ´&ï2¾Ø:Qs{©%oo…ŽØW@Í¡±,¢/€Á9¦Q)Ÿ¥ðÆÁ¢Kìý‹›“جõibî.ûüçQdrd•O êø´# pŽö*ÛJl“M©šnxüW+ÔyºÁzT@[ÿðÇ+fê›8_¬ñÌò6§P)ûJF£gA@5Žàžxæh°€ž×Ôp0¡E¨Å¯à ½HE‹Â¢+RêË+‡ËÑ!%–¨„å—½ „W€‡ø°•Ç>¶ó¸Ç€Cw§[Ψñ©¼Ýyn}HÇ@î«Ú “È”- ö±K‚IÛ›iæ™jÉUpŠo8§ÛKȵ³Üª;*¨*Þ#Åæð…‘eVc@ÉnÝ”"ó×ß•§ÙÅe×¢F5lìêtJÑ™›S°›ÎéÊËpå­mYcæ{G 觡  ‚¤üª41¥,ñd½ÿSÔÜÝÖ²1^Yk†­ÿu¼VÕ%Ed|ut ™'±ÏE觾վ÷QGŸâ@ÅD8$m §¦9¤„‚€–Õæ·ð9Á5:*d` ¶g‰y)wGN+ÛG%Û«®®—_[æ?¿h,wN`SçmÖ‰Ö\•¨ä²SŠÍ:Z¦Ôœ˜)¨+¶±ÉÁUAgÈ(…MÝ=‘µž¾SÛÀLÌ&:µv Âfî@/>4vT{õT¸~
+ÿì=µôÊ®Œßž¦«Xqƒˆ”?õÃïQѲ/l7üŸâ2Jó^£xçÞ™ÛÜNÛ4c&MÛ41MÚX›mnŒIlšÜ5Š;.,‚싲+HpßÁ²ˆ,‘]Å¢È*‚Kš´ùSî›ßÞïOï™yžóœÏù#°L-µÌP ‡©•W¥´¼‹.`žÄÖxÄ=|`$×&-ĺ èRاb£±`c†Và^ ì©ÈU1=à ¶ø/þÁÉãÛ„"@##aò“6ÉdÊ&ZÙ䨞PP6ƒüÊ–g!­:¢æ"¼‹ôÒUnkº½6ŽzõÃ$"ïëQÔósýÍà³ ¤ü vQÕåÈ[F¥²·ñî >?Í3M© «{H;ó„—¾%xvt žP4Þ:0µ—Åô6ÿjg{Ê%žŽZȘ™Ò7â*¢ÆŽÚðzi_ÏÄX¹ì]5¡pw—ë™%ÁlcíU!R~ÖÓQUŠýsX𦴤Ö]ÀžÝžÆ¾ð._º§w+íYì3ÇTÝÍíŦA5ø‘lG=ÕôÕf
+úU@C­wÈpO€=½~`ær“6>/´F¬pŒU][㥩;K¿C?øÖ6TžÖÑár64s¬=ïüÀnc'Ð
+j;[bfÀ:.Þ»L½·ÊFèDðžbéß1#¸ÎÂøæ1 ÍºËæ‹o&0ÿûÎ:Ú”Õ/¼òøzÚ¶±ZÐG7µ=¢i|²-+Ï4J*¯r¡·þ#€fœÙ›«Ëþ´Ãëß×SwØ\ ß{Ëg¿wò·»º>lÊ+À[2höÖ*ЃKÙyܘ‰G›¸ä¤‘Ë86pèÿ8™äOÛ4ܱ“ŒÞš?ðÎ’!ÀmeÅŒ’ᘱ‡7 ßZz„1V’ëF¢¼#TFÔ˜B¿ùпˆÍ8ûŽùMcºS¿åèküÝ$(½â®ÉðO£îíHñ¹Êî’+S„‡_nM!À'VéÔAE&­PàVDt$hèq 3âë©]2ulpOl|Vêó¿ìÔ–À}~Cg‹y‚ô|‰Ùð›cVrkÿ˜ECήuUgë9Uwœ€eå­÷c«„R+à¥!äü4õá7áUrÝ‘±WÓuSCR©_~P
+½‹¸Ü š\±µ@*2 Àoî®0ZÌBIÂHk‰jáC«ÍભÐK82s©‡ænVÂÒÍ‹9ä#[·èÈÆï>²_‘Z¾##½ôΞª{~­Éùå_¿Ÿÿb_te[Š+Úh¹é†e(»
+.i7¥—Æ©…é¶qR±€Ï\;Ø+o{â•Ã³¢:ô«ÓM
+îã¯ïÄÝ+M:E#3u`eÓŽ]lÁ‰[8™rJævQ¸+A=­˜oö2·ôgr!¥vê; ¥*¡aÖûfpàášËö¡ÊKžiDŽ_ÉlZâU§¯õÖfÄô
+16V úaS
+{¸¯j~lËÿÞ2”ÿ“köÈ0X2 Ö> «°%<ÜžÍe|¡v¨ùf@Ý…=vH¦tBʆ*iªnË;o)'ßûÊ;{öÞÍëÙ– í2â‹ ž×yêRÿãO~ÚbRþra±w˜|×dóÐ2£:¢à¶Ä´Ò‘«ÿí±»oéÈ&”Þ
+œ°_RVÐAÚ¹‡«Ò=5×÷¸¶á– ×þ~tN„ÞÁ?ZçUþ¨bA.Ž´e}˯Îø/ûõoÿFÜ;³;O(Û}K)
+©‰%q#µ>úŽÖrdS±,±!Ž›8„c;—T’ÊèÌS‡ZçSvÔÜÖ½ån¤gœ] ä4^ím|zFÞQùctI€ôMaAî¡êt³¤ Í9\}u{®äœDeùæQàÔ: Z&—„ hTÇ‚‡5¸ü“ç_A€uâ‚ËZañyßBSö©ƒIhð} öåþ*òqd­ ’4‘á;訿7h¨÷LÜ¡……Û_eÔ~æç¨AÀ8XKBk²}’uŸm{™¦4^Çÿ$iÌ;ïèï€x¨•®1äÝ­ItöîÕ…•®¢ŸÃ*JmPÅÇoLuMKÓÖÄÍ9û5lèD&-”æC+¡!nÆ{ÙQ6v"Â&6aïJnzS
+Ë´Ž´ÜqË•ƒXðE·äZx‰Uã—árLÝiZvî9{ÿë›2hšIS
+*o/ ê(sLÀ2RXæÎ
+îyì£èì„¥wüÄ+ÑÄìz@Ën ®Jøñõ1ʼn«»/jd"
+Î-ïjøòÿ—×WÚé…gÍ9ëÔÌdÒƬ4“ÉDÓN4ÍıÆn,Q0*¥ˆÒ¥JSD)"ÑØ{APDA¤ˆˆ" ‚ ½grfÎü)ççÅ{ñÝ|ïÚïÞϦ1óE5äQãËœªÆ܃%Ä[ëäù±Š
+,´!î÷¬ñHG
+J©©§þ§¡Æ¬¿õÔ¾øv¹×ZòOZÉ£˜%ué¾eÒ;ï
+¡Ø»B,uÊ3wFÀOôÂŒ+*Æësö~è“}µ\-ª¼±.¬ºmF¾znfXGzÿ»•Šúbj,BŸø4ðWÀ§¿ZÅ3Xx]!%2Ã'«K©šó£F6!x¦S‰/1õAïJ×R;AÿõR
+*Ø ŒKÃFX&‰™RJMÐýŽœ·Mã+ü:~{ÀÐÙ0rˆ¡­®nß:mºvœGÛŽñæ;è»Rú{Ÿ¾ƒéXaÖ­ŠŸŒbË®N
+oXû¡wUew×û ™{s8ÐñÍ.eseÔÄ$D78-Ñ-6+²Í`uÄ×üYŽRÊ£fá§Ð†pĹÂlñ=êX߆wª[!5é˜#¸)ùýiOÁ¬Û§WG¶ûWƒæ!CØ2`š?)¢›Âž€ƒ¶}ñ³’ UŠ`÷ ýÀßÚN±q SP·adä|ç4&ew¬á¾­¿6^Ó‘AÝ º9­¿‘qÿò7hÚ —ŒP°?‹IÛüK°ÁïïMÔ?vÌBxÈÅ@?ÀÛ(Ð!jöUß
+æ3 Ê\šáYת¤;`è➘â°©³Ý2M̳MÓ€ü&V¯P!®|®}°ùù2§öž¼ì*±¥2ó;ZÉ«ï7º¡hg|Ë:þþ¶¶»(nÿìÜ%-NJϹimH5Ž5>£ò.XzÙ`¯´‡TÓ Q¶, EHž¹êSÂZ
+âÄØF9VQª¢ZzýÿÌ ÜÀüiå ÛììˆÍÖ±ªûŸÇkïʈłæ¬ç˜à{»c”Û *yS¾©íÊ¿2Oûå "ù|WEâ·«œw7ÜšDnuZœu
+zåç |º{‘XæRQj–zàOe¼ê—Çk"±](öZ|²Î­a@|À½…,ŸQ X%æjûq©n-Ÿk[`AäLè-I}Î}õ©ÿÞüìW¢òCk¸ê!Ra\öƒ«‘w¿Ï‹nq™S'çPI¬p
+H‰Œ—A’œ;
+„Oà;Ô¦B @bí·ô-^ĬÚ÷ßÎÇ/©g^×_žv8íê, A’$-ìin-¬‹™>þe#ù`jož³ùxüú!-ús¶˜]5§Œoƒâ9M[6†…=>Þ€\s´LsôÇ®:ZŒ‘¾ ½Íèî)ÙeA¼é˜S‡-ˆŒÞ9XyÆßë*ï–>øÀú5wþ/á>mÓ+®v¹ïÏœsÌfÃT}A„è}
+Û d_Õ$B,F¿Ñ猜ÁC#ößiIîÇ‚Œn}&¹° 'ÅÚ"Rm]¥Ïà¤T‰z4/"é¹Î!7\Óz}°HŠ¹×ÇY’2§Yæ©Bhtnê!þøùãsWsyr—<–ÔäOòBB©/ZÄPb¤6]Ü€~ýø÷yüÔóÙ©ôÖûÊÓ|’Ã0)¼Èã÷¹ÜîT;o@„¼R[ò7|AH¾AGÒ7dB=>)!”p‡‘yULzôä'·} ïp±)Ðì*~{òÀÈ
+Ý$D½
+¤És/ˆô•7¾¼ 6º%Eª«$/ Ç•¿1§ðɯÏãW9mê ècÌfÏ–0o@¤ˆ'£ûX€h*^ æcý–PmûˆÑ§C¤áÒV: ó>­q‘ûÍË’
+©×Ë›#ÅEü ‚›D‚ƹêääX:—YÇÌ–Uƒ³Ë09ÇQÕ¹!€…Ðü”a$9¡nnfç&àÖ[—SÎ €Áà–+9‚ðï%cïè÷gÿ„ñíb<u'ˬ÷uá—6û½É1›"1–»{À[ÎÔõ¸BxOô>ŽŠ+gPNT16
+IŽ–b ƒL®cè8-²Ùqåt.â3![Hù<~è±»Ë>²S$$üèÄÐ,C[Ë8ð‚зzfß5…©ÃðÌØ#aHSÍ1÷0«QŽ4«­—3¨ S™V´8á¼€þ1Y?¾3~/oÊÏZYRx›¦<,褤•—/ÅgaK)៭Û£·dÇy\#¨Q“O݃ÌLCÿmA¨ ü"ï7¿×UXV(*ޟÊ&Õi$î·²/º ׫P<RP)D'/o½´àt³
+t“,•èÐ9´×÷˜¾{L ¦7Ÿ‘¼¾³-µI:©¼[–®Úc©ŠtLýñnŸêÈò> Éx³—AÄê76›=ê(yVM˜
+›óUD¢™rDãÐÙxN„ö‹)ª…ôÔ+Ï"ÍQ…Ìoƒx)šè¨6èK} ôÅäœF
+“XsO¼"Ìž¬“º2TÞ¯,¢ÉÚßÕâf¼”ôå”^ ¢ri۸厕k’½ÞÎøÂÓ’1\’–廼Ý+Û†å¶Ê„Î[ „¸4?[Îÿk­å“ Ö ´_¸ýÍ—ºW¬*oW'ò7äxÝÔýõº/ ïÄôß©i 7Î` 7Gf‘i“r ó÷ÑèØl3_sê è‚ –Ñ`&#[[fŸƒô IìÛ4Â\; ¬s•ñšK@ ƒâ´0ò¢-DåÍÊ«Ï«g°Ç±[¶ÌßJ¯ 9Ç{Ð!rĺvåõPõjëWÐXóŽ鉾ò]–ŠA@~¢ß>È­óQ›±ÆÙÐá&Âdy[n ’²6Ò¯>BjR@RY¾c<ÙÁx¤2>ÚšBF—ó˜ŽVÛ£aVwcT®MÈ1ËDÏfš+*@\Ÿ¿hRΠ@©q®z¹–•&c×^XÁ`:´dQÏöCùÍqAzuZAð§M¬m¿€³| í)neŒ ¿wª>wV‰©X®äpMòÿïøg&ÿüœšT¾ôª+•wZý{ÓcÔXÎj¥=<'HM®õÐÌ®· ,¢—iA
+G„\«+ÆšRÙAºÇü¤<'ð\ÌB?¡L1 îîbH1¹°#y;ëŠ`µ‹á`ú´73ó*݆N›Åý9ÎU¨)Œ¯Ù¹éÎYuÏa7ÅÛ³ÕÙ^}´öI˜ª¸âsU/¯$ð¡ïxXq˜OÙPøÍ•š‡XÇOŸÈ¤ÆûÔ;ß@ú¨í!êG3^@ã™HS^kž¬sÊcCoÃZíöãtëÄ5
+0šød‰Ý¡ÌÄÿ0^&Ùmå0ÝŠWàþ»†ÙE¦òþ§u (%}þŠ“I"A$ˆæ5Ì-Âpÿh)&â
+å°l2‚‰EltÇ^5ù<<}جs;FŽÕ²á… °i<7ø•3e,² ²DÀ‰Ž2"éH$V‚i;¤Ñæ­›¢]…:냨ì Ps±[Û Ða4F6L8¿Êb
+“¹ÑóÞ¨ÿ’q]!Ò¬Úúâç¼½¼|"ï+¤Ô¼ç¼©Ki§ÒŸ/¯*(ì‘Œí “Bª1örF›yyriåIž$ЃÍlÊø朄¬`…@6|INxúÞš„ÐìxV{_!l±ŽÔk_éq@p²Ã}FدÙê_D"PØ«{È‹J>… +Ö%(^¶{÷óDraT­ |ƒ.®õš2°9˜u@~|9ˆ 
+q•¢ RÊ°
+¾õá‚“—vЖ©`Y(¾0Þœ#à än`*ÑU6É&”\ùFÀ"úä<¹¸€Ö K»° ÑÄK`ç£ÔtOèe]® }Y;¬_ïšôj3ÏxYà· ‡m 4ÀŽÚ$>dZMöð ;]v@.lný¶#&ÑkNudŸ˜$“Ô9íÝ Ç”ëÝ° ó†'
+Ãg™thåUn%©2[¥{#ÛH"dìV© ŒT@3Ô;„ꂇ¨çtPR>žkÁ
+Åaͼ£ *r4:ðJªøîο
+WEó‹—!ï»~aÒºé­CPÃݹ>He7ó4¨:\X±U$md-6ɸ•lÐAÈ‘-cY.ÞD „$’dû‚FÂÑOСÁwÐŽjW½µáÊvÿǘ_¢Õ¸,CÐæò ÛÝòvü&¢0-û} ŸâúÆq£d–ØBóy1’­ù»DAÛ!Qaôy±S'Š•Iûl<&ˆýE¯‡ôûñTƒ `æ«Š˜!§"YA#çáí|_$ X¼®ÅY·ÌωŠ<r?Õ/|®ÞÃtÜk´ÊûIVʨíúƒîo²ùD„* š(S0Ì? ¨eG@­KPp€ÁQX-Ÿ(åæ.§-ñŒp‚Ù£eÄ‘Y‹5`bïg£˜-º‡a{‘ÞŠKÖÒ´cÈìZòqÃU`uo7û P¬&ź¸íŒ7×N_s¹LÌéM—É»Ôæ:¿—Ÿöà¥Q¿²,’«aï•„6Ï
+CÈÌBWð>…€Æp{<£e3)õ -„ &ošÌ–øôÒöÇ1ˆ¶dòg Ù—†mÉ–é
+ è>…̶€!Aæhß!I< # LÝwM ^ÇÞe‚Ø[¦YT:6j"Ó .ö´®î'i莓M1Åp7y×’-¢õ6äú
+øLPFËE&’ØA ^— DÔ}7 rѦ¬ê
+ e->/zÉëbˆµ[¾ü
+Z]²W¥í‘œ;ÛÚûRâÆșބDÖ'E­ˆF7
+¨&&‡„¼Ú}BP
+Ijœ€ˆÞ‘h±BÆŽðÑk#ÆJöƒîÜCŽ.ÀB ÝS®Ñ
+,UÝ!<‡=K]¼"‹„+ý&m9…à2mÊÈ‘;r!¤…·²YÀâÑõ8Z|bŒæMøÆMŒºÄÍ—­.7ÿ‘­?=n‚
+ 9u:j‹
+JUŽ¨é€7ÃSê±™/65O`’þe¼Ìq+;’(º‚ÚmD΃Ù`›t{„<ÒÔþûÜÌÈßàñ_( ªªË|™1ÜAŒè!5äf2ü͞æ¶
+êðZR$;ÕY7¢eC˜+îN
+µ¥ìŽ"/«É|íÉ`J²¬{oýµ4ÄdçtYÄŽy—˜î!ä÷\ºK ö¬Šáh܆±ÎäÕGÆ›EÃaË—AN®äsšn%•4†ú~e{Vd|û· g¬ ú0L V¯ÇÍÖ¢Åw財÷Zô½AðgS|bÄ«Ð(·ÑNªá¯²FŒanäaõÄ;ó”Þ%M<±0afŠly_ÆaŸƒZQN¶¯Û9„U^ÀKRå¯øK˜i¦v>uñÛ©¬–-\r› âpjµ ÁÕA¶¬£ÝƒÿØÌ å`ÏZ×Øç~>¤'6™ê’à]hÌ– UXánó<Z)N)í Ù±$Íc£§ùp{þú~e04Cáf†kT—…`éÙ r¦;b“&9=æË hU¢DÑ«Ô§;²O Y¢Q,¸H3£O Ý\8$Ñ® IKg{(+áiÝblÊ4ÿ_ù¡PŽ JE"!S4wP,po]þ•¤º);,³G¶2V‚"î3£ŒuÆÈ5“^@„¨€á$ V[²©¸‹•›Íâ®SêOح݃€©1×"†w¿YŽþ.«Â]`ýžlå±{ §ÉÓm6
+¡æiçœ(õ¢—üS¼ñùzeÆ4Žý‡‰ü×ßþúg³[ üTb¢õc¡Z®ÁCfn­MÓd2PÑA93óéaš&‡Wòù¹ä̓üNk ¡;á,Ã&x¸ ¾¢4,zßx {˜G>)•gkŠÙû´Œ˜@(-MÌ©àuÌ ™îs¤~k¾¶±Ô  nËööò¶J£næÂÇæ@¾vý(0„MX(·çÀ噜ÓÓœç6]v¯(ڞÑ1nà ,
+¬d£tÑÙb֖бŒ‹ýŒEÖ0±…‹/f©Uˬ÷þRU˜)„²Ñ]–Â1ÉÑl•–wj{’Ãë§í”bŠÑ– "à I,=YK9×ÈÚƒÅG±jŒØ°Qn,0˜ðŠ°¥)\® ‚@ôO‰ïø¸È0c°ÎM0¢II5.\sÊ°1)Ãe¼Ò>$oBi5ű •Äbëûœ"~F¡c:ô;ÄdEZ0 ¢„T+vàÐfL Äù×¥ã.Ÿú|Ä`læ¢|ë™JDèûðd U\ZÌ/Ë0Ò]†‹EÚ´’·æQ-–0˜½v
+›Š®ÓÁQ«™–ì:ÓsÔŠ»°&ñî³6Cò’Ôjº¼yer,ketŠl`´G#x$„À ‹<ÄãǸkœÞÓ$䡨³Se6q¥ó U×NWäxC’\¡ˆ!<S
+'Tê>ŽÿÇy¢‚”ÃŽz)I7ŇQ &7WSƆ) {^ê} Å¥¬9Á5`Z{Û7RÎ[D݃LÔ r UÁWP`|ô$IŸîç^Á§˜-h\‚»£”ÊôzŒ^{ÛÈ“Ÿ‚ÎDeQVBlÈRýAú ­uµˆ?c˜¶
+òwn¼L†5 {ödÿ¥³!6çº<Д†Ëž–ÍŸ3©‹™a`1¼…9OîßÇuµ¡àN“r¯Y/ï»:¬/{åŸÓ"†—1¶Ž5J¸æ`ãˆsÉÊ' ÍÊs‡¬ Æ›@ü ÞE¬;çë o+ž¿ö
+æiOýqÉf/oƒ•Ði&DÂf6¦(zœtíÇ=Ñç‚Ô$†¥~G~³´ ä‰RékÕ¬Ö—åÄb¶2ýs¨
+ù‹×‘×¢Ó¸ a8ƒK1{¤Ø‹‘–.´Ý[„™«’Ty¶]Ê H™kè
+C™ƒ ѨóèŽ(Ê#°­Xk(åãr:¡¥ t•i©½ ¢]i²žbáÎ5òGf|ohë=ÊîP·]‚àe)G{žK»
+ÇM»
+{mÈ…á`Ì®=ŠGChéÈçS Tª4?Ø}”è³48îsâ@˱iØmpJ‘L–¹R{{¡å¯¡@ˆ Â^-ÐÝj®Ô+Ás}ÒÀou„¾6ã+ÞŸ¥kĶ!´™G4Ú\r‘ ¡¦ Ø(ïRKÖZ<¼]\ ÖŠ„´Ï‰X0H‡_ÍŒRp¡¥»-z9QQz´)ÖQªšÐ$4ýÛ1Ï…\U•ýbÝû/ãåŽ›× Dáh®S|?Ê@)ÝfF:¥ÌþóÎð—õ_^[òˆ—œ9s‰G1ÀøH”ŸœºžŽ|“pH¹qüjaäߥ‡­Ÿ‚ƒæ€J ?lý¦†Ï6
+<§œŠPXÉ'ÁÜ(z>……œ‚ŠømßDÛ(ˆG¯%¬äŠ»9¸’ÆdŠ©Sô7£Â˜CT¥­Auîpe”\ß¡Pêešúô
+k693±!ºät÷íå\4Dý2½“ ýîDH„ÔZò¹CÑ»qVZ.É}áƒEÞÕ¦Pªô,wãÞñ
+69Tú¼$×ØBòwEô‰ýA»Î
+CM„?€Hé|¾êô†´‘X¿Lk%Ý®³’I3qß\hJöÄeÏKî@û|N[‡òêè·X«¤(Žj%bivµ÷â%JˆH4£íI°(UÄ}}…$|âÍ
+¬ªæ<w|c4lð†æ
+
+#míf©ñÄN«D–Ž ¦l3Œ‡P—“•@¢(¡ø´JüSœÊØ$ñîîNòͻۀ1þÎÒ˜k;¿jà!k ‡|×
+Ì'?ÀuÔèW™¢kô[Qw•OI\úUV
+3©Ú—PxžœûÙùœtšœÞ éäBUÁ Dà%myyk¯f2ãØO¯
+½_¶Å'Ð ßV¦9€U‚³Åcáz]JáûdùYY:y(ºJ Šr•­".õþ墶0‘›nØŠaâPTå‡"aG ÿ8à4ÎO;s‚£¦ð—³•àºäD±.)ÀŠY)x…¶{O±0+!Z÷Í2¯8j…’$kw?Í|Uà'ŸŒõRã×ÛcðUm$öaú³CãËPòL1ZÉzCìsÇ­„ã#«)
+¬óp—••<ñIfÀJ†‰†ìç(ä
+á
+}ܱmê÷YRÍlÞ^NE§öÅ ¨Ö¸sª‡¢'V~ÿ
+uËiÅo©4’k«@ oöC Y,ŸX°Ä‰üÿP´Jx2§ÃôÛàü
+\d­$—ÈåYÐtç±(bÐcQÚöXÊl¨$ö¿Ú9Pj‹ªíDABž5Í%·Tÿ:é©Ok7ñ´³ë)Q¼½œŠº"¢ÔCÊž}·¢´¶sÖSÉ»uñÇÜ`ŠVIÇ£^ú9Ðzd‚©Ônìf$0ÎR“Uð+•v¼™BŠø ÎRh~ãhv ×,¸ö‡£ìè>Š¶ó‡~P´ói¦¶¿t)ª´8æ ÛeǬaò `íSœSÉZ’³UÂøI5d¯æóî"Yå¤ ÎUÐ !•HK¨LËÅRÒ$vx°RÎàûˆåh‚á襶W¬ÈIåîvñkNf™XÉlètÚÐ(Å|¹Íâ¦Yko^-ˆY¾òÌÞÐŒ>`çšú´k·>Dër#Ù1Q}=!¹å“@éìUõ¡CÚ¨«<A<”xŸÆîîŽÑ—Øò^½BêÏÖÌ× ]…°ŠöÕHùuÿÜ9¹üÊÆù»Ñœž¦íŽmPJeõ…§ë´pÜ”ÀÃ8.„(o®¸!ã >¡ÉŒ«Û9 œ°f÷Íã•lC@w’½³
+ÂãcàC'žn+:D/¿¼CRcΘj¼[ô~-"?Ó#ö32´òç÷y›çq ˆ#ÔY·ÜÔ%ŒŽÚ9
+ú9G½9¤ëpú¨û¶4Ž.É7øªÀ²¼Ÿëø“­c-ÚþP&éÖ)Š„ÒœQ˜AèaÉo«„ˆ®!¦½q V¿bó’åñ»°çˆ‡9!Ó0s)RT¬ÚëYHšC€
+ï.{?³˜¿ü Ì0&ÒHÈd’ï%lVÏeœX÷4õgî¾ØOp:C=
+
+Dp5p}i2:’élÜÆG ¥Œ`*vDG&v°£ÇÄÈ™Ix ²As!ÐlcJ  ©¤£ì-¿1hÞ¸`GÛó]|©Žm­Éó} â©ˆý@ê*7‡¯|äÒ#X°´âaVÑœaG'8N€Ñõâ§HñQ_¤ ¦=.4@¸e;ÏÉVÑyzà¸À&°$xä;b`l_µ¸Šyã®Û¼øgäY@?~7ŸÎ`We|ˆ%qì»QFw%E®çâHVÀ”‰U- [¦Z$·œO÷åTí˜Â{Ù5o Tˆ¬Vy¦#ü†RoÁ&VñÁü˜2IÜ9^™J~óƒ×ÁCäÏNWÄ:…™¨ñù³Dê1sÔ8sßo(TdKØÆÊ‚´Rª…²B#ó!ØkÂÊ'^Œºx“×oa)Ö($•ñÆË$É#†¢'ðú9kyÉ[hÛºÿÖï'”›•%Ña…M
+Ì ø“ü#¬³×3ɲ™ÅJxpEDtmJV+`!
+¼ál5]-÷zg -(aõv0ËÖ -à 7Hû§õœ…’®v³
+³ÏÈ3jÑOB`E­óã4]Uj‹'Å“ºwúó>lR3/(¦îd¼UV4•¨Aßf“z):=sùŒëÄrÛ‹KÑKˆz·{«ÖUà —]ôuSÄÓæ”:ßæ3´Ðz@³éŠ³·‡ßÈ!+òª„î ð±ŽMÌ©…`ǽ3¦ÃW{cS3*…‡ä@¥Û:Ð9œ¹¾ö’]G=“ E†j—"âÜò¡ä§="GÁÖœ4ÏëðεżtSÛF<µ‚[M|L²ŒçKÑ!›è<¸ ­·¬¢ÄŸ¾ù+cÀÎ,Ÿ‰•÷+q0·8”ø#Ãè.:d <­¢ò%†ä[¥(UÞÏXÅðÈÅôU°©ô’¨ƒÖï­¯I„%x‘R›ÉZ«ŸÄZô° ¾Á™™`XÄ|[òmJ×#_ŠNóž`—Š8â«Ú-r.E' ^¶{«è…Îðz)rŽ‰
+›–‘’5Ÿ·&B°Æ1‡¢¤ ntIú°81b¶‡±kĈBÔ*ÑØs&üAf„‡“pøÄž1”7~XüÔCÐÓ­¾ô 50í©Z ?Á™…ì,S/X¹{DI¾¹‘÷Nx Ì$©¯ºY%aà‰ø ÿùˆÜd0-XÅdüC‚`•Œ•ô¢|™Sn~˜Œï’Ï|±•ŠXR2צå6Ì3 %/}N¶°Á¥Ö*Ò»Íî;Éo
+S.‘a«;ÂD¢= KµtF†šÆ¾R^?Þ]%"S“h?Ö9î§iä{Ëd‘¡¹ÈÌ>Xa5O<zœ7%WÓÇ‘áV¤#ç­êߊ¾nŠø@®ÀºÖm3ò£yŸ,€ ­(ÎD?2& VføÒ<$Íýȸ4q¾J_Þß å˜ŒvuÄ@÷„¤÷¦›ßJ|'(!‚Û7^×Iì`¦¹§w!yŒ=ùibÂÝq¾º5í`9×½•Ò– ?í<<|ñ"ÓGòS†åyüqrMhcu2Ç؈ócJòo.¹ñ9ùP©ª}ä^Áí9‡ù0EäÆœ¼§ <úæ 6¢ˆö¶g«"n%_ú|áR¹!K»Ìã›2pOÎIj&ÊÑ1=VÁëÁvI=wfÓPH=r‹‹hŒ±h†åo?«W×öÁ²b¡±Rüª;
+¶ ‡¦m…þOÉ«¤qˆ&3Ú;â
+KðÕ}ÆqtLa“‘u¡ÁØá.y’ì[¥Æ_󩘿C®$´²Y7øŒáG£ËÕKÉÚJz€Ÿ®e¹[‡¶Ø ·­iŒ­Ú,’Y©¬ôÀn~ïºbY 5—¢Áã0nXZ¬ä0Ô\öÒ|¨€ %Þ§Ãý_GÙ^/H-¸D;­AЉÌ#; ˆg'é@o 68r#¦é¾ÿ‰1Úõ"Cˆ%­~ØÂɱeì}+ئK â&
+¦®;hãã<Ÿ­O´µÂu†š¿±"\°yçCt‹lL -
+^‚³n r7H‡ãXâËeÜEÝ2! #ËëÏ£3tCFÙùcÐ¥¶Û €e8ŸÉ0xœ¤¬TLò¯‚¤Ùè‹b”³°­DÀ$ÿ¦ói.£ür©ã¼%ª‹è0ËêE$îLŒ”ûz·HIC\>:tÌ5¶£€aÀí°q*  B(¥½4hÊ œ"0ƒD±*ŸvlÁ°T
+(2Žê%„µšd¤¦•0¾| Ãߥ舯TÈþ©¾]4d»Kᬚ 5‡¢Ælã
+ÂðE®R«æ.a~&'ÄÑõKPzõ’l“Â[±¡Ñ“›“/PW¯E‡^pl,Ù)#w »½˜â¯›"® ‰Šš{ŸŠn“WƨÍmq UY‰­ ÅÎ0«=4γÓö¤§ßoˆ!f,â\ÏT¤  œ7­xq¼ôs’ì2'ýÎ9ù6ÌJ,¹[›†
+mJ³Yft5’«&â_¥?RušaöÉz½Ÿƒ÷-K`“õ¦’}ÒÖÜ}B­>xFöÄd!µH¨ýª„Oé™þ=Éâ—$ìL¬C@#Þµ98oDziâz(÷áËÉ/Á_Eè ®Ä
+lY“Ÿ×LŸñÒáãZË™dàs„úVôáf¬EãÖÈîeX >ã¹–• á„ÂÀB™…Æú-›©ä+&}O#”‡7I—dˆiçèa£`NËÛ¡ñHöµU¯àbZ°ú[‹dq1욎=MP2³`“ÝRÂßÃBjõÔ ùGRÒX!Xœqð©Y ”ÿ]®!D?>Ÿ‰'‰«XzÙé]·[S¤cµŸ¥Ø9 a×»q&.{ NÉ<;¡N@Øà[ÖÅåŠþkm’¸â\E/f/Mþ/è¿2åÏ8¸Û9ؼ
+*qêxL Of£<T·M„ ʾÕüÚ,}0®>ç§ôõ”WœÌ3Uc6¾GºéTA#j7¢̓
+æ„Ruqôæòº³Bä÷îÙÂÁoÆÑš‘(5•¼¿iKëÁósmÄ·KA|ûW vú¦d° ½‡ª“ ÕGsþ„
+|)Š=¤•
+‹K²Þý%†—16@ú×Kè{Åí,¸½Šˆ”¤MJ2ˆ³·¤V,åßÃâL<É`¬¾åÈŒÐQÃ.z¤é»´wƒùCgììÈL¼Ké…iÛ) ™×­Øn~ã2È/Û"Öen@‚¥¸bØuö¿®]®&êÐC¢Ã8ÚøÜ/3¦ÀÖè¬ZÛÕÓ ½$- 9ë/ѱÿ“†–œJ !´/¡
+SÈWÑh“Å §¢.ã#„&ÿ± f©Î2 Kà›åÉ¡-†)”F{#?\H¼`}Š:†ËÏòôþ‰eP>¨H³D1¦ŒŒM
+&8Þ,Øê`BªQûLˆƒqM×Ø!ä18ÝÏŒYOAŒÜœH,Ðôm€9 |Àt͘i5}³cïjÃŒ#Ð->ÜWƤ³³ô5¼º†ATt9Wëñ­„dÇŸGŸG\õUDž‚}É|ÀÃ8µ£`)é¦Vã’Á³q;e{ºC‰’èFûðŽºä]ãY¡ã ¡‹?7=ýÊ£šÙ©Qè{ȵÅ^Rò²Ž¡€ëHüûc (¬ma“6ÚÞ i•ÒÂþÈÿv¡pý-,§]±Û]˜—á·]X¤·ef×J>N€aÑë½Ö-3Ÿ›ÌE ›ù¾ƒäKÑ+Š ¾rîðGJ°rÀsÅŠó°~B¬}¸ƒ[ Šæ%„Aï®@ª]âYÚ{ï
+‘¶&ÒSõ És  ˆ‡/¶
+¤±"ƒ-âjF­Š,iŠmà’|<Õv_F¢ÁË·Ó[ñ&ÜsÐòNzßÒúðG:…2¦^Jžxé£èçZ„±eWX6|YÉÆK—"lmo¼D LJDÖÝ‹ÃÈHbÒü]7Kß%v8Õ‘z¯÷hÀã∑Nùž/àцa §ýZâ7¾ÒDW©<£=(˜ÀV<1:"IáÇN¶ ŽØJ´ò
+<H³=ÞàSË
+*Ç¢W<R‹×áÞª—tÅE4¼èrÞøy}À¸z…™ÂjG*Qé_QY ED
+ƒá ¿íELÒñáw8a¾E'†ì°‡Ì,¾÷·o0jFãˆQiÅk .~3{Á$Ô0yÆZïÝ<ÉP÷5(
+;a©‡h…<±‹°I¨ø@…³o¥à(ÏÀhït ¡„êKÎ>›7ÃÏ”³Ó_üû ;}_±AQg9Šê4Ýÿ†Eó].H‚XqŠ«’d 5üà¤&rÊ‚RÝ%
+˜ÈEöIf´á™ELÒù÷É'ÜÒ!Í”]›+O1q:ï5Ü“`
+T$Œu]÷E’ Â¾ÍyÁHB†p4%Ž™B  €~0y->Í ÉO·
+á.y^ qÙ&1e¥ÆFXÆ1~ZÒ!Û)}^¯•¿ñ#A1zHã«o;#H*êÊÓÍhƒšY*­+Lª‹]«fÌfŒ¦c˜Þj¤ü®êMóOðr9\`€1óq× ôeì<ôã
+LÀƒr•zIj8†·"z‚í4q¼ZP Ì%£ )r‘›²t—qí»¤ -[«¾
+Õà…Ï «}ôò®”ÂÙ[®ÎgˆKÉê¥ì¬8Ç&! #`Ö«
+0Î~®¾ãÎJsLPŽFΪ{ ’FβÕvÔZñeá•Eï.KH;È.A‰o„Ù@Pq|³ÇëÜ^ú~šb¢;ÝwïÌ ¿÷þsðíþùÉ°|‘7ÂPj©¥ù••»á*°ÄE C°ß® .ŠÚò6éŠuM¡wŸŠw‰ñqÈ|zŽ.ï† xŧ¼
+ŽÇ»áj54/èÇö‰É@™
+wA‡{ # %èãÒþNðéò¡ÄÒÃ’§<öñ+.úFoŸa4IǹãzMðýȘ×944SªݼIO
+T呸ãF0«¼Å\v¬MÀÐ(d­D袲4è&Aˆ! d§Ñ¤òúÇ]DL?u2ÅØ äÖéÍG8 0¢i¦ØV³ùT4A“ɨuÛ×JÒ·*žt…á4øÈ—¦ùÍ‘È…]ÅÓNWo”F…ŠC€%3­¸« yÍ ˆ)œÍ·zz‡'µûÅüزÚÞ‹ü,‰ðÓcˆ4aèú%¬QÑ3¶÷Ë7‘´wF¦JæsW$<Y†
+Zò扙½EÅžàfï¢>¬‡Œë~ŽŒ©o—VQBÔd¦Gf¿]2Ñ.}fÕ+
+NñÞ¥ìuP'ÒX«¾ó?” I
+¾Ðu¥soLûJ2аäÙJ”oX@kN9d 
+ ôâ·’§ã=`31ijqqyQ‚PÜ__žk u&¥¼å—xI؉ÂÀ¬]ô0W £„ñ`ÇKY <ezl…C×ûVþÌÅRyUi¿8Ù šçI[uÊx]’aÖº¡N |¼@Z»ÍpA„
+ç÷£BÊ‚Œø‚Ú.Q¶Ã¡ñNG¨ê2‰<J´CCÓoÜØ4§5@Cß<¦íuì&È”Gƒ¿d\…°`Gå6±qäÄ˃Ïþˆ]_‹>_AQ nUp®=eŸ»‡W‡3T>àÐÚ6g!T é°¦=zœÅ¾|W]¸ÖàDJ{¼S¨ä6" Šßò.SöN
+ú)'žîΩ‹—séÀpšŽÃÄ<v5—9™çÄsÂlHPÖtîŽq[}xZ‚W ᔫ·8(!™ð·`|2LPD4eÊdÜRÙë ˆ ‰v Ï0ˆsBLXÇ ”ˆU·+ðâ ‚L‰Iå›L–†W¨ÿ®·HVïyŠ¡Âað؉½Êe&÷Œ‡q6ÒïëÀÖJ`EJyN“-å,¤$Ío'
+<mIm
+çC`äyתžk–)a>}M3*€{IGDQŒz}QRpcfè?\`êåøù£}z‘Þ©îyug§™jÒé3ä¼ EîÓÏôß`$ý!øC¡h¹ S­
+
+ å)ÿÇx¹äÈ‘Ä0ôsŸ ŠïÚ³ô-fë¹ÿvSÊ»Re7`ÀÝÕ¬ø((’ª¼/´Ýr½ûÈ„I%¨ÚÝC*ç«Ê+P"Ä”öä%éÓrÛ^¥ÆL‰rÌÛF®Ä%†—W\DÑh!:’qæT{ ùÄÑïe ŒíE#ï•I¼_eøØîK UÈ›ëôæpt„x»g3m’¨"/³\`ÌP2‘Í4ŸæÊÑep"Òsì6»Ë;F[1È1戡†hŒÑеûËö#Õ¦½iÖÒDþ282Ïå@xiüä6.t¿Ò?³MÎ2AãÀ
+º;ÄNØ×â–ÛÞ­ÃÔC6æ÷½ßÊÀ'0û7—¢Û«H\w^ 2Qr­K+œ ~}§Øç‚šjÒmMñ0? éL I‹î77‚L£)šjÝØéQôÕ é)±Ñ£ºÈ :‡çËÁóWú‰^û¹Ìƒ1ŸŽ’ñîq¡Œ¿\­¤5j þ>º
+Ã'JpÜÌ>c~¼Áp~ŠÊÊ@ëŶÈØZ/sôóL¶è;_¾x Dƒ óÎØÕ!j9}K ÈRQäYqqlÙ…
+Eê°ÉùP˜j#ÖA·è†NkÖåëtºìnKÍŸêOO.ï,7;Œ
+ Ç!ŠGï8´¹ÎGÙcQ²2bà;]rÔŠ !¼2ä¢-ÎIcù:³Cb’²\Ñ»ªâmÉh@ˆ–4Í,.9 =Ù2ªÚ$9ÑæïÌŠ
+á.Ñ‹/øiÎ)ÿºYñ
+ë9›âô¦!”’X+Ñ¢€L]Ñ+z› òAeUÄ
+õdT[Iûéƒ2¸-iG%"’ËÒ”#ËnëMnú“xúŒÒ ”/(áXñHÍ®®±Ð"*qÌH#Ù· bz„1Ii-H¬bšNѶCHW‹öÝȦC$[U‹—xÍ'FÏ0¸š…ú1Ωƒm]¡Ñ9­×ïÎ#Ôu¦#xÔÒ 8‡ŠÓH ñ´z–gF0jd€f±È£¦?èè¹jhp@º¬Øíõ²·y44G I]ÚÆN!œI,4& TSëèâ4 ¯XG݇SÕXÇÔZ”‡ ,ü<5P$²[AlfUzŒÛ]i²­gØê[
+Â}3¸b!¡â—
+H‰Œ—MŽ\9„OÐw¨ LBâ(®{–} ³rß;%=•ïe·aÃ.dEJ ]í«wk¯×®Ñb~ýÇÂ^>gŽ.cfÄFdS1~h|eA¦IË©ýëÇ€ú«i—!³/¿Úœ–"ü—_ Ñ[JHæ¹êc´¡aÒädxo®iš_þ±Â1•=º‡=€~~
+7Ɇ²(A´oŠW%·!-¯BµÌ!B&¬äÈTª@ËÛÖ$®m:xvÛ=uƒÔ± ‚JÒ4KŽµNž]Š¹9@?A\¦¼z0W|imA’ƤçÇAÐa5@JæpôŽ$È"±C¿üÊ1¢‹þ¤JÃ?¸E[Ÿ)›¤¡‹ÏËÓÉh¸›=2ç r˜ƒàg]öxH1txBE4?´‚t*Ïorœ2²&®*5O+ð}o¼’ˆO-KÌe”*å×Ó´›¯šç̧‡>A˜™fÆ?p…Zþ¯ÞdHÇì"AÿCQ¤P¾ýýâí“Ú”^ØX d2ËSæ"2½-ø(flˆÕȃíªçñõZuÈ3p#¨lÇ•Â
+YXì@KÅŒ7Ì“œIÜ•à2ƒWê¿òC>k4v ÅÜ¥àeÈLí!cÍáwЂ/Ë8øu ­¤WækÖTq/5XpÛ§ž8ù†iæmñ«µ` Ûr­€gǪ€@MÝ­“ãòч<Ø4*W³ylˆŒr¤ÝT›ôLFü©Ög'=0#¦,;—§ ™â­4Wj;éA/pKe'å›yNÛ—²²wÐÏßé°¿v#6fz™ÖÐfgàtv>ÆvŸ»áð¨ùß›®T¨6IJVC—›¡jOôâ}n£ø‰¨Ø†T顤ÒÈ}ÙdzX˜=ž#ÉppÔ¶ë"ÆÍÈöO6¤^E¿c©„ÑÌX_´rä¢ ì.ôŽÞcå4$ˆåÛÈýè¡juÛ4ÿô=&?Š¬€¸â´GmÃók7ôAÁ`;b¾]±àùFôK±`w|º‡RLh‹·gü8…à çE#Ú§C0•é-~]ÃL"/ƒBç×»€0~).ðr°ÿFÁÅÔ¯ÿVzü•œ;tèµÖ 4 ¤
+6.¶ÞAsˆA˜µž?¸)·Ìö8ž¤"½ pí@@z8|_¾þØ#&1åCÝ}«+ Ïu~¬*»#- <ïûgS1~8Ëjv¤jíPJAùo€uMzJ*¼õ²
+: ñ±>›ís¤Ü{eæµä0dá’ã7•|ƒ\rŠD²·¸}:§5™è<È~E“µ:¡•ûUKVÝã¬0–šXËyÔ¬8‹1';(b-¾|IO*&™"·¶]eK#3‚†È­íð¹Þp
+è?¦jêÒø˜l‡'ô] ßÀsà‘5¸ÔK‰câ2ð÷s°y½Ë|×]1±M4‚Òà¾,U¾ÑPö›’ïSúµ·.NÈ:Z;÷—ÃŒtÞdÛ†½ý>ãò¹·¢ÏŸÜÉ #ÐZ@‹­DEœ33shŒ¸øë¦+˜YnùkJÀikUŠ¼J¬I’pîÈòCÜN‚Pì±l]—ž#¿øɾE]phƒ§!’f–0—uNàâo^Bö¬|cárª²ÿ–oüš¡Ñ% LxÁá¼èö†pó¯Ç,Á_‚°*_·J²H¶&I¤URð¼±#þ«$R[#‰´”ö§2M`W¹5ÄÍ4ò˜µÎI´ª‚²X¼D|}Ic4ÿ”RC¾u•È_Eˆnʪb/[»Ž#'È©¤ýULÅÁ-Gw{ì<Of5ÞT‘Ž EϽװ~ê nº6¿0n8Q¡”±"—lScžŠ«3®àh¼Þ*i
+Ç^Ul,QN§å0%]m_%“=1s¸ŒU¢pV±%#z œ”•þ0’n*~‡œÅ¬­x 3­*ÃÌëPôkgQ4„³š¸ó¦D`,X
+"lY~‡+‹û›—ò¡èó¦oJÃF`o’o/"ݾïÓ°~PUe«V‰Ò"ôBKÚ*A/
+©uÄül²‚%Ý[ñ°6ý^õý†§”üDf«9ì$®Ø¸O»™æK‰)Â?-i¹ÜC¬èæLÏxýËN[›ÄfÓî#ÃìÛp/ÈŸƒ:•Òsí: RH$­ù˱¸G èéP÷,ú8ú*Q>áV<cæˆS t”yfÿ™\Š*»Žr'ØØ™ÌæLãm-õñTœNòïr>l"œì<Á‡(BÙj~Rd«8LLnö‘+™Lü/WNÅ7•Ÿæì¼5§‰t0fGEfkå›®'*$©Œ=+±q‘VgcÐù¢øBHÏõð<†6´`}¸JriL—wl†Á³î#ìîÝcrA5}aùèb ˆU :K8…ÿ–Wð ÁOáá`iõøT‚·ãoáx'¨CVÆžÅ`”S¸#VÀAEå®æŒ“
+ƒ]±•-A5"Î;éÄó34P8Ö¨\êÚ+³9'Y½d9Í :Eû«KÐ!
+ƒÙ QN;ŸÓ?*¸ÖèX¿ aÐØ™Z‚+ƒÖŠn…Ð:¢dûSaøÜJlf«yý–+a=ý´fÀ¶8
+÷%ð½m…MO7%±¶¹«Ø“:9RW–›I‘¦Cѧµ"¹SZ)¦ïÏSðB~ÞàaVªhÚO\>wEDHÚUrþ³wpò eô—[ZXä2|©ø&¯LÀ¨x õ0¹î4Í—ß9¤›T“øL=ŸÁP@æi6®ÞÙCÙ4}0³ ú5˜" ʽÀù†'#)è¹–½
+ÝEób0k`ur’óË7%/FuZñÇ¿zѯÍxâöê7g¤aÙñkH‘ñüŽ¨=f‰æK²G•·§¤|€ÅØ Î\\ª­Z(NÙ¥4 EŠØðêk4]b±uNp¨V©µÓ,pˆv#¢±Öçy"(¬¸â âz:¥`ÿi—XvtŽÛ2à\½§…[a™A/‹ÀJ‘׺Špñð£2&¤ÿy,BaH4’ŸÙ•þÓe]5ùk°óæWÎrþúÑV_ ‘¥(°jÝÇ67
+ã¡ù»_÷Mä&2}»ºâbÆú?mkÀXT\Jôl`J~D5¬ïÎD +-«3ê9hRÒ xäª) òôî%Z~"›õ='ÒšbHDe×"Š^æþy,R…˜«rÎ(ëcˆ`â9M¨[,ر5EwŠÞA,
+ôO§#‘ _MñЛÌYsbWW‘²‚(S—×9¨;wäŸfgr¡Ê“‘),VëI¶è| ÈJhh±„@îËŒ&iŽþ¨,ŽÜŸèä%ˆ?ýCÃè¡H9'Ѭ±%ߘ^áŽXâuNLQ%£îÈœ ]—]ñ¾vH!6_MÚ_úûnþþ#‘‘qDv»œûÝ_ŠÞBÂ* "ß1Âfðï‰eV`òäN¸Óa2á9óÿÅ¥+bå!U¦²|ÐkzÏ^û—1TÖ´×XXЦXVIË`äÂÞÀ—’ù)4±Vü Úù#FE¾»¿Û2_O˜n«‚ÄÂ`‚?Š›½*ÊäüúçT„ÜBC[€>¬íº|KJ|0¥þ8Ýø]×/ï¾zƒÈóa˜4Ý­2«i{4ná¶!oàƒ,bH=p[=7XþýYFNÅBù9 ˜‘á£ÍüS½š &Ø­î+ÝH–µ?Îè:ˆ‹ð€ÛÊÿ„ð7ÑJ¼nD1[?òÜ×±ˆ-T@­À”Á?fI–…€Zó6
+ŽU*¥Ï£+Û–pÂ@{>`_§J¨õËN- £ƒŠ›w¢K !åLPÌT.Écw<g,¨ˆ·b²n΂°FòNçÛ\ üöª#Þ{`³êX,?4j¢³´etT$±E$m…IÇ*âs ¶¢šÿRCbÚìÁAì Œ4ÄÊ8û3Ñh^WÒ? D"9èÆ@Äù¦ÁÙŒ›SD¨j¨æ§”ôŒ<Á]\3#à¶Ö´à(Ô$d EWÑôCÂÄ69)¢„0𫵬s€ýèQ:êþÁ^“µìqW¼¯Œ\t1Ìý¥¿ïÕÁ ð
+~LSzx+Q$F’¸ISW@¿“¡pŒ‰÷ßï4všû;R#`º•ÇSX‰Š]ž¹
+¬q!§í† )B­•§´MÎ…ø-ñyeµÖ9"
+5n2TÀÁ0/)8²Èλ S§¢72<3ÆŠ6š®æ ŠK‘ȳ&´/>|äÀ¤±Ûl²Û”žæpIÒ®“%,Éfc5þÏx™#Éu$Aô¸CËÊ2#wq ¡Î Æ(±FœûÏóŒø ï,¢ ÐЋWnáË•ÜtmÍnWµè"4EÎ5oÎf^tž™úÉ,ÖƒÁÔˆÓw&’.ãèQE)`à ðóóŒCðS˜ËÅew!¸bÐY5ÈÃëæc£)äú$M®uÍ7c7DÉÁ’LsRÔkìSSÄ-sœÛïæ01G†t®[c’Ždë'±cY=÷+frË´dÅVô£Ñð¾ýÌ|¿cP‘íf’F™¡Úç³x +¨
+®ä¿Ž¡_:ôÝ®
+¢|n¥Ý” |îêa‚äu×üeÐÁwj;ÛÙPùЯg‚À¨pQxàÇÞí!ú"`ñÙp|Ю%ÍÓïÏTv&GºzäRÞ DyægÿÇ«®h]¾äÝ*DlYâ$¸UÎQ´¶>í‚s‘tð «]ýc Ê2þñïoIž›ÉáΉ“ÈA¦/aé}™rÓcöá> bç´œwÃ¥…Ò8jëaepͼn“Ü ?NªS0z%B-zÝêzþþ<žLÿõ×·?þÇ¿þ‡k@ Ê(Ëå-ù—\ì¡©Ç®p×ìye<q½cËÔÂ7Yê=Ñ=FB1$ßø…j­¯]LAªœuV
+\[<aCRBÍr]Bi¤ZPÌ õ2¥ ª# k#òÐ"O§$YäT .M¯3=¥¢R‡VæÛ$>cغf­C/1@4#/ëÀߘÖ0°Å!°*®‚9/ñÖb/rŒæq;ߪ>”…LEªÃA™®Ç¬àò ©YóÂP)ò®¶ v^ }¯GoEæÕûëÚê”±]ìh‰uèKz¯¢¤¥ôëñû­°rŒŸlŽH¢?ÌSWbÝ;ÁI*“ùðÞI,A³uzˆ&ôÄMÙ" !jò¤R½¥*Sc
+¾(šMAø¡ëDð+ú¦ÉÙm²8@b+èiNø±7ëPxl?z§a˜W7Ù·€º$§8„RÑCõ+²+Á&8cr€¼y ;·êŽ1ÎJ@ ÃõBQOÂíÏÊi¼Ðˆ0,¡fþÜêWõd´+Š2_§fYãÉË›CT+“ï)qH
+Ê¢ký÷”ÍÔØŠ¥×>ø—ÙA2òX,Ì“S /¡÷ä½Êæbˆ-1†ŸÇ±–ÌX’!‡H±'¾Ûã‹QAæ*ÖQ²•€ßbîPtå0”©9##|D7÷Zò!ºÝvµEèð<‘Jú9v‰¦WörõHtŸžL2Žc'%Ãí‹É¸úq줙¦²(áÅN7Pa:z…ÑÉA–}„ñÔ4Ð7JŠh4km£Žë” íKUBjÞ  jxƒ¶
+ið9hÁ½‹a¶V` *áá1±Œo>Ü*êIGÛ–~‹'¤šÜ#IdbÞ—‹™«±NMKÙ°Ò˜íØ97HŒ8:B]°&Û(Öyq™yw›Vîv„ÜÜêÎœ~“ƒÒ OJût’H69—‘oc›X#K1I<zR®íømèxæ`åÙxYˆ“¶«öÛíÜ€ÿ雪NI­»e’K,­Dä¤`kŸŒõŒiÈðY÷¸öÉ†Ô rƒ ¶çßÓƒ E¤ÇgÞÚD¢™P÷Ý'Ç'v ñm #V%ÇüO>ñ°¢×JEk,wŽ'P Y_hô7Ûe="Ûh6'Çèù•wÒ“rtèÅU\…S:‹Ž){'ÊÙÏ™¥wj9”èÇÄ8à+!RÃ7ôë9‰…¡ÚQð« ×GèkÉbÖ‘‰õ¦z¯ Ó›³G²‚Êü2h(»0×[zÏ/ð% Ò «  I6ÅA÷¢ÜAϯTîÇ5Íp
+ïÓ¤åÊY¸“¤L'³¡"3~Ðb“1ŸêWÐÓA’™'¼Ù´!0
+[òL‘׸6‡0Ê€ Ócð.¤Ý«T<…ËÖKz¦qê+¦2ɇ¯ù³;ƒånX&K†@æ2Ûáf7+5k«h<ZbX p°~÷[­*K2šóÀ­¶aº”ÈïÇBüŠy~¥XŸ\¨-Q%"šœIÚdÄ»@©¼®÷õî GÐišLdw;ñÎt˜¦ýVÚwœó ôôªàÐ[ŒKîІ,
+H‡9‚R'ñ`}·ˆä¥ÇÖÎ>=¢d|cÒÖ¤…wý‘$êÌädW@ç¡Oâ ›ÖAQž€ÊU]¦
+‹ÙODûüJ'þ$£©xÅô­ÎáßX‹>'vŸYÒ=çÙYà¡ÛÒMþö7Îâ÷»ýœ&öÄð®Ìµ³³Ðz)aÚ ˜õì,ú„%\L]g'`7M2ê8°•ßœŽ_ø/urK{3Mz,‚õW´}7rù!Öã Ôåívd!&C[2ßÔú·ï´kÝœNÔ:ÅeHGgœš…‡ÙÏ ˆxQ¤Y¼šo˜™_™ó–öä ÌFÿ<Rm… º†¦Ë¼6‡W
+Ó$[‹IšŠ+{ò”^é(®ÏPÇÕtßYY›t¬2¿OišˆÆÂ×Ë}c^p[Wh¢½ŽkT1Á¯]:¹¶ Å?‚d±ö|“.“´× ¶Q||SI
+®$q
+Üë£Ð"Ę²Â'1ä EÕ¹&3ÇlŒâÒO¶™äg‘»8”6»)^A…ÆF¬KWÂÜGÖÓYš™¾ñã½~hðî2¨¾Ç'âÂq †wµæ™`hã8ƒõù!ª •CR¶¨ “ÒfŒM±ºK‡çb…Êî´ïh“0À/´Üy)BH‹·Øa^Ö3YMÓ-Uu˜QýR´œ4Ïâ¤A(}7N¸/Ò%Á’_à8Mú¤(?P™:ú%ALa…š‘ÓÃÌÝÝÎ÷˜*ED¸N g€ˆ»r»ÅÂï¨ý0AÄö½Væi•„yŠóTi÷bÀÍ!@â˳9w€ØRÌ^×õÈ –/Ü»îVV_èûŒõB¹½Xc³ $aþ8“ß@âSå$?¨šeOæ£ÉÅ'‚Ùçu ÎDϲ™ÔÁ£PÊcH裹ˆ•²\$î-WÊáÖªýjRµ1$ÄÂq)&º.I}ÛæV¶å3Þ:ÔÁظðz<Y@[ÙçvÙmÄZÂ&·¨ç„ÇM6"Fu¯ç (?è}’}~Ž _¨à Eo_WG69²:Þ!|œ?¬Á?×+WÞ Â£½²S“|Õ¤|ÿg¼L²k9 º•¿‚w€¤{ª¥èïê@I~E–¥íc)DA6Ñ vuÃ/Qš±HÜ‹GâCQ¿] e3„Ì
+o±Ž/,’*²
+ŽðK¬+gi`*ž¸yNP·ªXg~
+ƒŠ)B|2§Èó>ç<ÐñºˆñˆŠŠ#÷AÞIG1½tócÅWcªÆ IMRª§¾`íJiiÏNò
+*Nâå6'!Ëþ UŒh\^âú\ ¬J4ä§;˜‰@Ú1ÐéÕI:Í<YZŽQ@òøÛ± øšÈÛâ¶,I 8S:“1.eß™D©|õgB í€XÇ>¶áíD>=.O7£µ?u!"P÷/èK]WFÓPP´íI?À^Ó§…аÉÖó7'â·ï˜ÏßôJm «­<I'qqï´u á­£†&®¶ÞÏ»ƒ>\3•YëD±ZŽÑÊoAÞ¦¨VØ&Qžb|î€ß°¤Çã !°±nÛ·É’i”¨X3ÂR`hÙ¤.¿“ºLØXοȈ‰L\Ѩv¹KSËePJR–‚ÀðÇW{­éÃEž4»þb‹1“\`ì©>0pDÊr¤ûiðŠ4÷
+þ%î´&JQxÃäƱ‡ö
+¡³~ÇVÁ‹ÅnÐ0Ó{}êÿ÷ó?ú“_¹—fºûp:ÿ×Ãð\êEž…mç½3ɼJ9o'?¾Î¤²,pœ 6¯†Š¸ó£¦™äÁì”ëÚÐ9ÓK2¸,*Ý©Ú„}Wÿgì=/ÈЖ ỗÛöwÄ0¸—|ÉäZõNaL±:´E4t]…-FG“
+•&ݶ%ê”
+Uå¥[‹ˆ–¥’y…V¥)AK^5òœIÕY6ô¶M"äåw}è—reCf oB¡;ùlc;à-ôt%Í-ç2L)TϦÉX}I ²|úº“ÊòhnƒÎ=ñ±îÄøëV‘íyÁ¨"ïe8<Mš üs•ª~üô9ª;L4L;ïD—dj‰oÿð:®
+ù· ·æh-zi¨`NO•:Aïy˽÷¯0ï ùáUÒaÑ«ým“#»§6(!\ÇÝmò :l2æWü1×&aƒx,6¾› ˆ…+8ãÀò¹69tžÕÜtqø[ „/ža¼Â³ÀóS‰sð_.>½ŸCp‰d$¾’k“A ·°Ùv®›g“£,©«µZum265‚º·æÚdAn€²Ç‘lòòlò :l²®L¨äeÒ)×&Owlò½€§Kž]б" sÝ-Ý”0àcÉöà’çTèSæÆ­Ù*x@VþÁ$ƒH”œëô™À<¬I7\Û,»Yû‚‰¨sŽ‹ë‘•ò<òËùí‘£ä1Ed­›yñè¯ º»d‰w5]b\fðÝ%GŒ ±Ýíi’(Ái¹ÁÃ#«ÐÐCÐ /ÏÝžM?=2³ |IØËÍÁÌ1Æßááxcv-r 8Î(qf4ʃE1臚99 dir ¾Gž`gˆ&?xää°û‰9<²î‹KlØ|Ôé‘õîÐ
+†ƒ™,Yå p¨0f×#«t‘‰Áe×ÛžlìxdMLjqXÿÆ
+GÌ>HÊ\¬áD>SI­ôøà‘5ä\Ÿ/Iµ]¬MÁŽÃ󔾺ùX&Ç$ÿ¸•ßB «Ž#Uª™ÁÒât19û€ù —ÊÞ„ˆÎàOðvùAˆdÞÐF^S¾Fè]ˆÃ”„©QÜÑÐ
+<žƒÉls—ÌÞ”80Ð(݇›ãƒ*ÐEU6¬ÉUb 9o8³ä*ñ„ðùlÿð ÄÈSât(±®lБÅRu•øxº£ÄGO)ž} 5`ŠÊÜÓSBð{v V‹éAŠ™ Ãõù·ZÓEž¸Å\Š«Å@l:QDÎb¬i7ö²°¶ÉÕb­ŒfŸÓ©™«ÅÇVyZüã~~kq(ˆ({8 ,Z|‚îZ³†[AÌìRÚ›±Ùhä,]âuc.Î ÆG×Uc•ºPhv0WGϾŸjÌöÒÉŒa5÷òé.îž3"Ò;\é°Éߎ—Ññ¦U‹ÀµS`°)¬sY´w5žø#‘!â2ƒ§Ÿ SÌ]ç}™?ª7‚EOç³õm\UÍñAU>l»1‚æj±:@Ä D쾆ž„ìh±æÁtC(1˜S…`ð?­—êj±†SăfíA‹5äh/²X¯Ú¼k±6…¶ ½ïŠF7->–ÉÑâ·òK‹Q<¼§~ˆÉ×bt×bA`¡
+j0˜gÂþº ›CE4!cÙh£'Å‚èRÅ ª\])ÖÅ!Nª<2äI±JÍ':óTÚJ 7uú~HñœÂwsÖ³{
+¥g’+ƒ€ìùR_"2ú›Ìò“‡We¥‹h'GO‹Ã˲ÔÚY¦òÔb ¼^-øš‹S‹ï O‹Ì©ÅÜ“œ€äò Å¼[ƒNª õA‹gý8$j¯Øû®Æ³ ´» å(WEN>ÕxŽÅ¥¼)_ŸºŸSÈ™,CÌS5Ö|Æö/ãå®#ÙmEÑ/èèXAäá3Æa§” ŠÔ
+øïµ6yؘ¾—…)Ë64Ò®Kò<ö#Ìԫ·³Ï9×tÂÔPùIç²ðNHXëvRãû>ÝÕø׋9Õ¸ôòÈ|SIúÙV/‹%!¸cîoÔ‰HŠªã€ù8aDiÌqSãKZ-5ci•
+ä—A¦Æ˜‡ÕÊâu–EslJ[udRrG±mZ#ø&Y¨W1Ô£@Õü&寧…9dºÒË ª‘©¡ÂàÌýùeµWS*lZiÖ¬¤Õ»FÙUþjJc$‡$_W?`>N˜CãÚÀCuF½‹7_:×hÔèüGYÇ^Š©ãª!Øì˜^Ýû{-À+!Væ“ò[-.̵!WÐç+]óæ’ô`­•Xi‡*Íæ†YïÀħõ¾‚\y`eÛªRm1«Æ0Œ×A‡ã*¬8d½3 ô*èÔ¹Ûq¯N¹–à5Ðiš®m¹‚>_éÝjqÍzR¾’ä÷±S‡+æ·KŸ±ÃKtî£yÃœ*^ƃmBmó³Æ}GÎ) kBŽDˆW1§žÝ~(⯪³jX"î@æ©›»úHc1H`ÿ<Áa#QN+'פ(Åa­kÜ>&½ezO 3B
+™ÛöÜ× ?÷ÉϹ`™ALN±¼ß¯’ùc¡T‘îævzv:ávrQàµ}Î¥,lcGÌ0ïÀ¥¸@È»¶¼x<6éñ&ÅÆÍäõö“®ßadÈèBÇîÛ$gNŽ£§ ”H$¯Ø£waŠcA6<ÅØÞO{•0QÇ ¤3ä{›~̥˃1ÒŽù
+
+J%•š¬5·N vÙHu1RN.5Æs^H••¯xs?Œ'KMgºü9ž»úË!ïFC-u zy–¢âyi_2oÆ‹(!¿ÓwÞn‡ìFN§ –ëDð~SÏq.ãæ¥ZU™ôù@Ð;
+Ž«‹%ìùûž,µ’Ë‹=j&0Ë$ÔcÎÂGt¡ýáyŽ5@³±:õ 5ÚË})ÕÌs7Bl2$|mrñDØà;J\{¬ÃZ!a’ÇtAT„X¨ûåfä!:—=ÐñÇš=1ŸNI£UñÑ­6¡Œd˜«Í±)*NÌÂösS7¡±R«®ó$Ði(ð
+ùq*âäʈ/#¥X`sŽ‡ee\ †@Tºò r}ú¼Ï t)âç toÆíÊ÷–þr~äÃûï½ýö¿·à“§AŒ?O! N­O·Á…M§úô{½® uÑÖŠ"~‚8鵈cJoƒïL5ÆÆ°5’¹¸ U®¾…‰í^­Q2–]¥?§>°º<´J“ü6ˆ9†¾ç± °(̘g ]¯â‘H„Fªí£:Ï¢ ¨ƒ°¸ˆ"ö”îÕ&97>§B )±ç
+&ОC8\\«0)¡$C~Üw”97 ,$×€Ô$ÑÃÇÛ¬Ž
+¢XPæ#N"ª“àl¦vúI 25™QjÑ¿£±ì>Ìí£•éÔñœ?×â5ƒ<z‰'Єp¯Þ,yU\(–lFŒû´ëá!…0Þ±ºu:Š¡Û¤œ¢}„3`r[ÀÐæãqÐç+kú1C_…µð½èÔ;d÷À,†móÄyx¡ÁxNß<Àõ^-açd#OéÍ!‰µ0ý±:ÄdÒ°E0¶os¤µŠ]b¤º@‰õÀ­”îGñZúÇÊ‹bDúÀÒW Ä‚Ð >Vw>ˆ»/ öã°u”œwa§ÑãQ\6c^g (6þrÂPæG(«4!,z°¦ò¯È¥[C„ºGL@P!Ñ‚Ò/®+xõV!Q•§™+ùfÈ!àÁ`ÆNQ^Nooû¨( HÆ3æq}Ç$’ÉzNNÎlicTºŒ£?\a“ùé‚(ñI€Xù²B© …¥'ra¤þõ‹y5Âd>˜´Úy'ç úã΢ñŒã™®!õqÝæþÌ1qsHM¬ï’“1yM.òü&@YòÜñý1kN!Ïáø6Åö.SOBg}ásŒ}™ª¸XC+C¨CµZèÐç|IxÅøÆ´^ŽïEõ)qõw [&›}uá{‰/߆&U‹Ùvž|¦2õ[Ñ/ÈÀ°Š„¸ä‹§”%Sýº ‡¥
+É/Nl„˜w–êÞ…"·3f"Y$ª5lâï´WÉb’µ-3&™¡ g*‡\Ù UØOº€ð?2¶¦i}G’ÈÁä'[~ÁÂý^?ÞMmÈaP¸CZ°^¤‹¹Œ]?… jUóò”Š‰Cq±B‰åýÀ6• =S€gn¼-Ô±§œfdÛò§¯ÈÜÊ*âÿܘ˜²CæêÒqFøVö©¬ÛvÉÊ¢ŠÍô©J Ò∦aDјf.ƺåŠþtµ<kãèŽ-HRèˆò ¹SÍZÚ1D?’ôzµÉH³¡ÊOáèZ¤{_}hì¸+8ýÝñÍ(üXµÃ.ºÐR=`>#WÏÌ[Þƒ%ãÄîàmm˜åLCê«0øJÓ‚ÎÞ$¸ãùè•-Ü´rû‰°äkðú¥ú»1ÌÂcÁ‰¯ŠŸ˜‡¼|±Š¥ñcømè¥EÆ8­µ¼@|<õòA}Ëxòƒ£ ‰œ‚G¯å 䛫SÒ‹ïÿQO±re÷`ËMÑSzþ/ãe’¤G‘DáèµÆŒßb–˜XÖ¶O€±¢´ìû÷÷Â=
+”Ù2@‚W‘>¼Y¨ÔÍâ\Uiß,S<€DA’‹&Ñ!Ô —ÈB¦dI3ª‚T=Ü{˜‚‹€ÐvëE:+z0Do‘ï Oâݼ«=³S¹&Ú èXçÏaxß-zÊ&e“ßä÷\Ã0;®G±®cöTx}xq;@fñtÒ‚ÀUøñ>µú ‚Oi²’MÓ» T®ð~Æy*a0¨£íÄéB¾è=Eöi•pQ!ökv;‡ f\»šï”Ìôꎚhí…P?¿tÅÀ´²ÜÊ8…ƒil•9®ãi(þÿpiƒÍaÇ6f¾6%¾Ä£b“£X7n:DùRÒ›¥‚ðÐWð·3&6šçë‚)™‘éÝ Åbr÷û'Ä‚ðèä_ÂW7ÉR >Î((„ {tdø{‰BQ5 ”žùuîçT¹RP%‰D]´¤°°!1æ24æÉ£$Ñö¯¸R|sfš0ÉëW(Ô 6Õ¹LêÆÏmCt_ã+¢)+à°†Œõغbà\†'/÷c7
+p¬ÍW]ìM†ª8—d/Z½,î†
+&ƒÄôä¾k‡¤5r\o~
+ØŸ‡ÛÃ.—O‚ÌÓ|Tš;LXú^™^ðøµ¸=¶V¯"?Ès=ÓÅó~ÆÔ•7de¢ÉÖÃeeYhÝ
+¯B`îaDô¥¹=fÞâ ©L§@(Ʀ·zO{‚å+ Œ9Ë9Þè Cߣ֎+U_òÆhr8ky@ø—xÝÅêîèp?f­œ¨£y ‚æIâÉÚ ŒÓ@ðe3B)s˜–èã
+‘Û)ߺ2&Z×ò!½£W8¨|°Ûep¸5öÓ"ùì£äÒ YÛÁÆdÜ”}iÀ²2N¼Þ0cnp’ƒÀÒ¦Û<ªÍ—çîႼE—qy€à5™@†¶LሩEɘwªEŒûpJÏËT!ã¤LOÐIJQ»}ŒÝm|ƒpà¬qP$üt‹Õ XzÈxh¶vpߟ@pû>ÐE…>¾"UïrWpÔkÄ€óº6ÑŒˆ¢élé#ˆžáFÅÑs4^#Ð<sû"ä²ëïÇO} „u°¥ºM{ÿ£ìCE–aÍ7IPÌQ#ˆao¬@H}ÈA»$’ºøÒƒ! "Me’=è^,;o¶cèbE9æû膩 Ί(„›ød< ú ÊüÏÛ9~@+ÙÒ´!¡óS§AhA¬,XHc_˜a†bykÛ$F¢brSîÛ*Hà÷™³±I,Ê6ùÈìC[½0*iúÓû?Õ¿³o`q‰xCÏ“µX/OÔ˜Šâ`Àó9 ê#톞ô[¯”fÖÒ!tnH¾ûŽc+–´!ÚÃo˜Ó²%™À>e<Îò tÚ‰Û羺léyâ/ ßxò&¿I–wîø)výx
+´ .ÃøŠ¡ã‰Í„àÖ§Êd Ñ*¬¨b‰‚mBZLètuÆ´d/2\-¤-ç«O•A£¨]©a'¥Á»*Á­ù9 Ø,,q.y©J@¬B` ’ñ 6ÑOEO¾Î3ö§XcNÖÿqcäƒ8¸Š„Ùõç\|†¥`né{›üK¡¢z{ߟº.J·a6ä F¨G±R$U3Ñäö º€Ä=8VjOôÏâM#Ô)N]’v²
+·Ï¢Í"ÂØt\z鲧½ûËËÊ‹C®ÕŽAE1h±ïòñu|`©²Ê. H$¢YdIL5ž½‹#°h©yn¡Àܯ1>k$@°ƒZD2¤»NMWÅ´ö
+Æfk?è΋€@•²Èwü’©ÌI]W{wáAP"tП é%Okq ­ïß Èd'ÆšZ1NÍîsM…9ê)“×Ç.WF…‰4PhRÔhÌÀíé7È÷Co îƒÚ½–ñ‡+Ê £ìÊ‘1ÁRíÛËËuèZÃ#èÚ‹ëï ý÷éÑL†·ßþüöËù·ýÒØM¢u©áª|À½ñJ¹_ˆ§kìxóKÊÃtC×,¨d$º ÿT.ý.œ KDÁ=Òk©ÜFAÂ_#‚Q}¯e™‹6B1S^ƒrî“X¹È^±`ó Äš œ³œr Gdš ômƒh‡Gxüܘ/‰~ÐóÚãâ‹Šc$¡äEBÇ×)ŒU™´º4ðX&‚FG>l&. ¯´n…Ñ·ßu{xÛ á-¶ÌËcʶˆ™_]Ú°ˆRÓxÀ¼Ÿ1J™ÄÅî%L J–¹/{¨R¢R).H–D*a¦j¦‰Wá, é²ö¯Ü ùç@M;Ñõ«aØ‚*KÁ™¢¯ÓÎa¢b."ã…Sb ?UÞVu–?ä·p‚üa%d’Œçm
+@t´º^ÜAù%ƒWR‚äðÖÎIƒß­ó”¸­à†’ ‚eT0É!ø,[Ígç~9Ö„úPèÜ D•×ÎR>oë”nTµ5°#ˆA5¤=Ï…˜²ùå
+šœ÷ÄÃÜÒ|æ·ûî zÀ<‘ }s$;ðØ9,6&‘ÅÉN”7+‘ÀúRµ[M›núiøö\ìýH†ЇƒÐ:ÙÉfëNdÛ)Pæ¯heF”€ÊÌeŸA®ËLsŽ5ÊØèà´Z[ˆ$”±×[3)6§H‰»@ Åw¹×*Gܱ+¾aÊJ°jÆâ9jÎèüñ2G®+G¢è
+¸ÚeüÀ<˜,Sn¯ £=Òìý×¹È%¾‡/JªT—@w˜­ »éxO>+»ñì;£²Ï‹?‡AXæºå kÏž’_±‘=b'»ò¸úÙŠ݃›$!ÛtlfI‰ÓWkr¢SÅÓe§ƒÒ–z2â{ÂZfYþÚ ÑJ¬+‰elN!.ñr'À`Ñ<ú”>Îd'i5©ÇÉ &ã"÷v¡5W’ã}æ·ïxòí§ââô +43PmȪϺæÇT¡k/¨dòj›dÈýHt²T‰kãR“w£¡)4 Ó1¢½?)-ÜH~Òà. re–Ùîõ||—Ï3A«Ð.µpAxì
+baß÷ d…Uõªû>÷ïÖx–Ö·‚vâ*—,D¬É¼ÿD­XƒÈÀUœÕÛËs±ï/‡ƒ²–¤CyP£ Òí¶IN«Éã4âñÕˆ¿:tÎ…ôF9¬hAáãçm´!œ\ÍÐJˆgˆûM8WN‡ORÚ­¤µ|û8$BÁ»&cÍ×¹¢rÓ<4—šŽè4y©†øþ<ê·Cü㧅ÀDŸÐ­ÓVÒ–cÄ´î0o ®ŽyåãEÙg!ðêðlØÎR]äN ÃÄ?“”
+Ãà5š{–.~ W–åÖç<  Z˜!²Ù“ŽÞ¦ãþüh³V†VÍÜü”¹Åz;®Ãœ #@˺ïaàqÇ{«teZ¸À«ÄŃü‡ sà)X
+-ŸÞÊ3–r o‘5>Ø9_B¨ŸSÛ¬yµ…‘o¶‰Æıžšqxß/M=}‡²#ÜÄÂôĤ2bh<ºŽAÊÏL*“ZUÄž|Tï&•qÇbdBRÂ0tãõ¼6’UÎU´û¨ßïÖ
+zÔö¡ÙF< *å?Ô« +çf¬Ä„hHúê Ø–s•¿| ƒ”*`É4°@¨ˆ¬WkçíéSBÅ”«$'ÈzZà:RÏĦ'ÛXxX?³îÑw¹ÐO]&j¡ ‰ž##Æ+ N‡40á|åíå: ´.ãզ… ‚^£f—›CÅVÃHF¹ÁÁµu¯l(a$î,ˆöòÒ±†ÄØkâÿÓ3TG«az †‰Gå:äwêd(sZÎ>ñt¥Òa'Ýĉ~bÈ0I)÷‰ÈÓ¡ øòþì;DØ9ʃ)/À©nH¹Áª¨°Q²NùÀ¿½œ@§Ft8*ˆãqŸº¬ÅûŸìŽ¯XY^+®!Z›4-'gmÅ ¢
+ß_µº`ÐJD£`¯§«D©¢¯±òÒýIÑžT˜<to4²jKƒ½4ž„üwy2ûj<Ùulº3a&|*³0€ãЧÄúÒïów.Ss¿ÍmúN¯ºMñ½:‡]¸Öø»z³Õ£ù0—]?ìúǾQI¢POéûºíúé¸k|w'±Æ_ÿÁ"ÿý¿—¿þÿ1ò¡QÃ@ø‰ˆ”ó§„L°%ëGÄí¶€ëE:e¶À„M£×‚0>üÁ†iÄú,Hoôyâ;«H?¶‡L3Œ
+3Û
+T%ê%òe ¾
+Οª)1òÛ­Ø}(Ô̸ÈÚ ìfÖvÐ?ïíÆúùV»O@•2_ífÉ„a;#5Åq £7’*ð‡¡ÚÎ0&$‚¾ß3mè M¾át‰“–Rõ8‚©`Gÿ\_¹ª&Çì L&.t°{;sÉ3C˜?Æ$+´€—%ºB¹ª·;Ëاˆ}û öËIͳτªDž׃n¤•¸7^Ä ó¹ßbú×t^QäÉ(¯Y - ^bdBbäN†)ò,œ…Æ+hAØ1¹Onâ4I`Ò,7¦p¤áù`pp¾ŸcYpÚX÷(K£H$¶õ
+c³“ØuA)lUÞßñZ[Ó‹C¤ªX&„t“6³&ÒãV6Ê7oZÔ6¤Në]¬=W@Dûôî5¬l#ó]g:€ža#Ø
+#TªÁžCWŠ Õ «9”™f¤"1b2»ÏaF D“bÇ-XYn0ŠC_‚ZDåÁ`ÊêTµ’-=ƒˆã2·KÓ<ÇÔI#9‰Q“—YS0ø: y6¿/ b°A”W‚xWé® QE0Ùn›C |Ó¹U2L—Qmt'NŽ9»P¤Ï.¼\ƒ¦uu64…ˆ$Uƒ¤ Ø!v™Ÿsˆç®”Ió£ø1Ogðì;E»Lƒã–}:C@´%?èñB³4”…¯'Ђ$qµØÙD”ÛteÏI”«ÐÐB3×¥ QÅ÷²Qh”`T¢_ë„ÞO£Â—Q$ªí3Œî-™ã¼ÇHaιjT¨ÛG]@T…r‹‚Š}§çÂúQôâ³¼ª0e”Jµw‡JW òT|%æš–à­SÚõ“…JÛ¿ùÀ¤Âkãxæb*eƒtŠ_²ÜcwS†ŽûÛ¾lÛ7ÑT®ý„2. O@\PúSᶶ)ã¢ç],K›Ã*U3¯Ì
+[¶¿™°…Ç©iP[<€~<iqàL:y™
+¿C„€ÖÀ¹É¾‚Ȫ/,”—FªÅ!üÖïû–ÿbzÂ#Ó„&Ç’NâÃ.Å,J¯ ò|2‚àMø'Æ}ŸkRbD&ñÒ«B¤ºC¢Ñ› Bû¨"˜g´÷x~*öðçä~„‚rÒÃêßIÐ,RJæro ‘Ðd¦bö»éŠumÙô%£¼AŒ³ì'¶†¦; o•ú„Üâž ˆƒ€C2Hç£ÈÊ!ÿ2^.IRÄ0½ÑDɶüY³ål‡ûoyY’;˜n7L°@í²¥T~@h/µå{ô†A'a±z&lÉ›¦~]&3â «áÎÔ ž9µ÷%#ÿŽÂ_6ùõ“žñFòÏm H¶Ð å%’7¹Û¯H‹Ú˜qò~Áç•\æ
+´¾‘ ‡0„µÂ£„Ô8þ_Ïìá;׬CÑ]‰ÓbïÑ0q)ü¿G‰Kø˹K¾ˆÊ¯øÚäS.¤¥ßÀÈMˆÊªç°` ]Éã ]^—w%Ä,Y;üOPý±SÎÌ‹¼KË+ßþºövÂÎ7àõp‘jµÞ¥øÕ^™áwÖ RŽ
+t(ø€>Ïž':œnq<1/m¦â”†«·D< +Ô:“‚iê"qT] ²š@Š•Ý^´ –Hß·ñöKVï¡ÏŽö¹AOÙgÌÎ죜
+¢ŠAARöÁª]&£uyªo„$XÀmfü4$­‹",ödI,Î ®Â(˜Ñy‘%  óeN½lê© QŒ£›ù©ñUE´±w‹RÞ
+H‰Œ—A’d9
+DOPwÈ Ì7!„€u÷rnÑf³ª¼ÿv_ú5SŠî,³XT¤‡$Àq¹Üeta-ƇÌÔ+͆YF“øø—Š\)£ #F“‚Œ«Œœê1FAú%é¢nãã¯7Ĭ¥fÌé¾ ÃµK}Ìæ:Å›õÞ­‰Ú‚„kæO9Bô­Oç9âã'Œ]ü}ôÙ£Íá?7HºEtÉÍK|H37‰û.Ùz‚é b"!Ÿ ß‚–4©¾ lc6ŸÞüyÏ (ºGºç¹ž£—…O5RÑÆ+æß?þóC>þ£ÖÓƒj¼vÞØxUØÏ3&C¥eŸiUÒ¤š“{Y)"•TB² ÓI^Ʊ}.ˆIªúlM¦ÜEyµÎ»{E¹Ïñnj£µ ÿ¸ä—×4²Û‚À’ŸtÏpmjØã
+âWs…/Ö¼mˆÝ—72aw¹^1z ‹#ú]¯×»úE‡w8|¬ç¸‘ú (µÉl‘ÇP•™¢6€v×j™ÞóÝ)M¡¶¦µnÏS"Rô<Ö’‚:u×ßµ|á„^ü•/øů”jsu'ƒã„è
+
+7q^>`¿Æ‹m5 §.HY%ê+²´I1ñâP U¬С ¯ÓéôÖúw1¿÷ÄÏoôÍê.ÇLœKæXÕàÒÂ"ÚÊ+|¾iÍ9Š(dáã†d¯!WÞ+¤$k*=ÖoHÐ\q»¶ $¸6<˜¬•s¸±¤Ä¸gzËZÐû[F}£†ÖU½T&á˜%mßd¸Å¬šb_Ts‘ÉÇØoNÁ”ÏbÂóS’Ðz*ÜVŸŸBJˆ€˜JÉQœS„hÊ%„žóûŠø­LÏE_0·èà­3ïæ<=¥B*ydzç1$aRÓQ¾?~U)áCTŒ²}4ºÊVÉéÖv• øBGë¦h/8Þ{–:”é+d_õ{µçüΙãk¾pïÕÃ_³s脯9þ§Žúc5^Ö’Šâ1C^ÛüóyOh9Þhû+æuÑx½ëU.þé=·\Ü ¦3·'÷çã°‹~¾e ›·ãóú¾ÿ¹WÚ²TGÊ™›.ÈX^Ö1TvAèV”z²‘ÍÝÈXsT®×ýºÏÁÒ¨•»_Ç`F¹¶¦Vßž¶ÀïYî± XwOËo ÷MìÌÞÆUqÂ܈éÉŽ´GoQF‹ŸÙ‚)©ÑÿÄT«F¾½H¼b˜¡„%,L¡U°—»˜I4Š—ëÀQ­»pä4;ùzœl8™KÅÛYù›4NrÛªÔë1=0
+"¿Cᇩz‹IPð£öÔr˜ÏU_HQî|ÈãljYzÕZÈêÖ¨!_œå_ß¡q1¾-Æ—…Áá…>÷y”Ä¡³7‘‡[ÂùDF„T®“5ØÙÆ‚à<³¶J'ÔZ_§x_ÛÖ¼AÀ±¡åî’u‹¿ÖŽ$x=ºOåY(ÿôÆÅ7hc…mùæH8ˆ&‚i0÷c J­
+hzß„§¡µÌœmï¤ðÁÖúÍ&ü½Üà|冱Éa41`tè·1¿kØÏ#Æáëa ú¶Zt–¤Ò|Ý[d–t0ÎD¤”²†iõ#¸ú=^ S86ÃæÍÇ-åU6I=æŒZI ‡š‹ïeKÐÔ
+“­ ÒðØRÕû äA‚Q)êœÏïP±¬ÌË‚ôêŠ,i R.=j2“÷ƒ±*eêQŽhïœ0†F”l#¹›ÆÌlI
+sAÔG©± ±Æ½Q³ËvÑë¢>QlÔnoÕbI†CldæÔœ^W5,ƒž4nnA¥é»à,Ñ,„.l(7‚$dEYLr©©:!áiÎ'ɳ¤¹ŒÍ6Þ{”= ï¶"]ZNdŽ¡¿‰›e?…7JX6ññô6…!HãxÊ‹°ódFy.öõéÌZ2P‰–û)ì¹ØWœþ¯Ãa•Xç´ÜçhͲaT÷8­h¦ÀäÌ8Bh:c“…X¾—Ô†6`|˜Ò&ãhÆ?ú°Í½±CBDÚÅÛ~M5-‘ÃáíQjý27Aíé@7Ý*q€ìB¢>tB#ˆ7çÀrôt*®!÷9lR$AÖ±õO&ŒÛ‹ô ¥ŒqßuËmz8I×’J*˜vŒÛ^"ùq˜åƒ($övLª9jnaqé忾1£þÏ¿µÿ2^&9rI=ïPkðyX
+ÜrÛG蕒˾¿ïf^ìŠðAC?}07ûƒz…y˜S½¿6„|D_ø.ûÓ@CJ͔ך ™‰>`Q1¿Z‡¡™ÜŒpÙúÀ]i‡Ð}Aªi]'¯ˆ…¡p±ÚtÖõð ;AÆõuÐèÊd%fË !®ºãLL:TÆPÃ9}+:§ÓÝC§²>¼¨d—ŒHâhçvu$LÜ®û@ou)Ä€¹K?€¤¸=‰‡AšÆ¶Ë Åjˆ@‰sÌ ŸÑ¢uYâ"Š¥ÎÛJSw:1f”­Ã°Yw?)xö†fZz‚ E0¥ü쎪PG—ILÅÖÊùº5NÝó öý—³Šð
+0äl’¤½\Ì*èmõâ2¡XÆ â´ýÊ$È(B>Nò "ç¬1¶`îý¢SéQÑ5ÏíÈ:FÕs™î37Œ?€HJ5~D†§'»8òM>Á 
+#ÒÚ;GÑÉБ ?÷ȆÜÔŠC-{/4G
+üƒZkð-â…[<¯£÷E¾©ô}> }¤vÃÅ~¾“&Ÿ •ë¹2È
+Þ Jâ…×·r2Þ’ð9ÕaŠ£fR"ùîwÊð›˜rÎè}]ì²K£Gˆ2­:çÈùQQž»×c/uuºmÒÚyJ/ŸÖ©#£tê¹mº‰¥úõV²AŠæ›iÎÁM7
+7Dåd‡Ï­xȨac·£FnRÆðu2AºI!í(ßRˆÂѧˆŒ+G‘Æ½Õ Ä®D/Î7}²Iîþ¹Ù‹ü^7ß0Ú„U¦fú"•çňeã¯ú‘ÝPGnáïYœÈ¡Üt¿ƒR`㦾Q‰'$̶á Õ1¾,4 ïÌ5º©å= <¾~6Ʀ-¥Rª:×›4Bd•)ÅCh_€ (Ùd›P•RšGYj4Ù^è{Ø—{3å%ÈVa€¢-½^ESôWrñÄÿ²¹ºösb®‚
+ÿ
+#Þ&'Ön ™Œˆþ0æÕ>(ÁM-(cõhAè/ Úwƒ$>]Å9Õ¦MMön{‘ƒKs!ô=D«äŠv•/óînEJ´`ê2x€R>ÊCŠPwoKОAH;RÏ®±.~c9ãL9Ä«F]›ÖÎÞ?7É;°;ncÉ€dÐÄÜgçœ0
+.ÔˇïdœcL6‡…Êp‹Á>§Ð½Â5E
+K‡óþAÜ\’€<òÓU¡"9$øÁ£6`eix”¶µæW‡}¸¿–.þakɸ#7õ€ÈŠ;ƒÏýÙBA$­¾Y
+<IŸ¯ñÈ{ßüÈÉ œsæ }d 3yôºòý6ƒ¾“Âñp]xÕx­¯°ìÙ†c¯ÞU­a(6^5&2…B¼¬gcµÅ5dyÂßÿœA?zÿ}©AíAµW‚=,r.ù¢8.<Õ^œsõ§#;²äÔÄô+ëè+ù^d‚é”XtB–Å)•Ý¸èK4eªAfÎú;«ç‘)ok¹¨šLð´¦ïçlÓµßf›ÒÓ£¶iß‹³íÌ^âÃîýhÕ×' j.)áÅi)„Xº=‹=F^a(ŒÃß#è`ø`N¨ »ƒÅûTLu1à d7Ðö¹@ŒCD¸p¢¨W³y=€*û¤&ó`ínÄwALÃ`>Qøn"Ei“y½äM„ö ¡™×4ØåÁ^± š£&æ&¿¿Ä‡ø¬Ä¸9ËøsíÊ*O0{Ž.ˆw–i@äðoùßÎÁµÈŸ ¾ï¤D—'7Þ •LŸ,
+ú–ÉŸY¬{ø:`Tňäšú)æ´ÛÇ>Ýõ<ï7-}œœßBåŒb0þ‡ùÅ!ÏnKÑ ËÀüIÀÌÌçPódc–V8”.âô&¹¯mÔæצü;³ÊéÖ×
+æ™üj2ÉïTye.„€Ù§ª®LBÁäfDiƒ.Y4Ó züNNž^+Âɼë?üé„9UØͯ/Ý@7õ²Ë ØŠKÍ,eâýI«Ô}ú»;G3èØ^ƒP6ÞeÄòU?z¨X¿òCy)²?ÉŽag©&Ÿ
+çh¦^ÆB§YúZ¢™f‹k3—ïÙÏÁ–O 7‡´ËËÞo#sO#+o~Ô|qÈè™Zõy.΄Pê
+»VbÌ&9b¶°¢Ù©¯ ë bfdmLÆÚÁð¶T7Ð÷TxÌ$ÎZ¬„ðpr¡_YUKÄËy¬ò âUNòšÊöxŽ(Û™/Ã;CÑÉ7/tºµÒW y˜?B¿Fg›È óû«
+åJ9ˆ|v ,?›U'´Ž‘Ðf¬Œ:Â%lµ¼?uå,òžL[, S•*Y|«/®–[U6¬Ù_EÿaоÁ\v(²HïʇóÓ£¯0†?±nÌWúÈâßáÇ-ÉM¨Lm!'%:ÓÑ* ‚ûjÄ#:Ÿ0í4 v_ÔºH'ˆ\ %ÈsÚ´‹³À¨ðI8$…¢lˆ¿™T5'§Q+Õ¤`íZ‡H‡V”ÅOÁRó3ÍI>ë™Ü%:éž[ÈYܯÀ<@ŠL<›b¯×§6%$+VÂᮓfI†)šœAf¶{­þjÒÝOµw‡hX1…„š®êA—#X0w®ŒÊH¼z’x~g‹$ûN¢æ†ŠXQXò|M0-ÒÙÇÆZ.ZKƒ@ÞID‡¤U¡~xæMNjܘ„ÏŸÎ(âuNd§Æ4^ÅN¬Òî¶ÑmlÈÙÖ/0‰IZÖdíÆ%2
+uh
+KÛ<dâ{'§dç@Q¨$sÒRñ_mRÓhöë
+jÒ3¶*ØVõW¡àt¢ôK¬ŒD ÍÝÉÛ%ø 7õ_?Yhf$¿³úÙõ×¨pëÜ®1F‰ø:þ)]šG;å`ËMM(ú_ÏÙ\™LNÅ£³4óòÃÝ-ÿúë_}0½d þp¯ƒ8B¤]*Ìn mOMIÖ­Ù´±«¸nˆÍoŪÃÂ0®u>¿ø<E ÙÈ ²
+_|™‡@53=ÀÃnòs
+s íÂj8Ž‰jÇpþB!B2‡6b@D|Ÿì„;8¤
+;¹kXÕm1`d¤÷gZø0Ã÷Sx¢I“[ê#–³µPay+]w÷d"ñ¡qÉ»®:y™Ø?Ô1I¶ÊnÂÀRš KPë-”œJêí•Si
+Dò¬rkɃgá˜â—ÊíÓ S*$r’qªˆ´òsˤÜÏRŽMPOMš ~tÕÉåMqIÇËp‚dÂ?ã…̶õ$òeŒ”Wôœ'-üê_Ú×!=²q=;OÇùcãz!OÔhx7`?nü´–f–ßPDè—÷ýšB
+tüõB ööJ­RFNÍE¿ÿš4PíõŸ7܈q#*i´Éöð¹oÑ`{õÌà4š†¬ýÞ¤¢WØ Q6®7e“¤TSôL„Â3]ôFÑà€h‰H"ÍbR7+!]{lSrW’p¹aˆï\Ÿ¦¢›ëvÛ¡ò2êcfLct{õ#äýT¿GPøÆhð‘œæ?&¶Qª:”µã•ï‡—¿¿@üvÂÜûp»ñ½™¿eŽ§È?ÿ~ùãß½h¤WÿG´³dga'åº&ÂYÌpQ¤qÚÝ@˜Ã˜J9¨dÑ%a×4v³¦´+ˆÆfNó62ü
+'"ša©› wºa,Füe“áþ1JÀ.Œho_¹’îù™VIk””ÀJ©ÿt‡4åÑB oë
+¸w“´¢SÈåÄ‚|Ý<Sz(ÂöÚCøHyOÆU üçÌ®&06t¦ÌŠ· Ò^2º¿ÿ‡R´~Öúìœ]ˆ 5ýnSp q ”“ž?’–˜o2"ݪE*uQž=Iñ?ýCâØ >¨ì a(×drÑ"ùi»¦
+úo›¬¾åFÍ—Ô=¦•­ây½i}K=ú £:®–\ýÄmXS¶Ž£‹uÆÖm`¾qQ.Ƀ{Ôf ™Wwˆ¾×¥¾®w«¼¬0³×ö†Šu•5c (v"CÍæD{Bìfè2q¢u6^»#®ÉS1k•Á<9åAݹ
+t²¢ZÈòdš ê׸
+>‚óG¶‹Ÿ)1(|êqL8ˆþóèY;ªê€bþÁÌq¢%ÆŽ’?qµñ…ˆz¨-Öq¹rŽm4¹#Èq}]–ÕêfÞŠ £}p‘È?.;BfGBÉ™½$Z©$Y HÏOÎ1 ÜÔBWÖ¢cPwQ´l1çpˆ‘¾ QEïâS?}@î S¸þ‚õ96ŠÂÿ`
+Du"-ªô8Bp,"Êh׸>õk¯ú²÷Ú¤1?è
+fTµ$Xä4H[1C?‡tlH{N‰p·|u†ŒsÍ?u€†e>?ÑÐhCh& ŸÚÕâ6ƒF%)Gm©ØéAçÒêáá:t¢LòY烈=ŒÅ·ÏÌNŒXÛÊP«|t“h¯ob#h1bÍÀ8ÉζSeJòÉê¹dA•4w‚°_õmœ˜P@2[
+¢@úôvgPt:a’Œ•Ï"ÀËON;ýðøÈ%i‡»žv’"Åü8ü‰O „p-SyvŽddHÂ]Yî·Ø(·'~¥¾ÎooŒåà .Èce€L…€<áá¹¾ÈO}º>õ¢,N\‰€ózºMÙo²»¾Îo*¼ å›Z
+3¢¬~¸¤ÿÇx™#W–Qt½‡²e00¦¢eÊÕ
+òX¦ö¯s‘‰jñOõî²’x@æÍ;,‹’K»Nê¥Ä?õ2ñÛ9/¸¹Ýæ}·W(>»sÙ…×ÿn§þ´Õch4é‡Ú|Ùu_½)/ÄÑá‘^k.ãüØ3~w#ç ƒÃã“Ó\€ØhDL*.Ô.ŽìU®F~ÁyZ‘,Gê©+ZÚ­Ž¢ÛóâÇÒeœk}³$¬‘ d)ò«‡O½U„ìvåÅâÃ:DÖL¥o!„4Ž‘»h"lÀxJ N!Ý‹µ>N¹Ÿ8%’ßiâ€Û2û¤¦HCdã
+O]’áDBAJoó!tþv¸Ž¨0(V yZ!”üÓyÌÂ
+-š–¢^P;‹H&3'Œé`¥²”%¶ ))žoØ*²M¦1ÓJ@]æflä­DWÒ£‰ÿRZª÷sÐ5 F Ð/©ê¿lf-VÁªZF¦4ˆFZ™ˆÇ+EyÐÊ’‚…?^ÙA3â[æËÏ"K§£Biøu$ÃQ+:c)l@+!f/¡9
+rC¾Íþ絨Q³lOPÄÔ½h
+LN€wÂámF6r™Ø(ý‚s@^°¨él’+«b×us!T
+º€%VŒh0„­ñ¥èÛÔ¿®E¢ì /d’þ±Ž|·zm›h7g-·n%%$vO&^lHatjGÜïf­à
+ȧ»£r4£Œ"i3P@(!Ç°.3àô€áÆ ¡gWª|)ùµZX’RjhçÀ:osàóöªçgsŽm9[|Ùºo£ú|g5Í"ňރbô¾9Ãcbm­Cyr-pú¨y bõè$2V&#™3ÿJ7gQú EVm†ôä[ä“]ÅMÌ'3qäªÂˆ¦mWýPpZÊ
+µ‡´ô»ù
+ûtþ÷ÿñ·ÿð™­""LÚš)5À%‚çzöÀ—ûÇúýl+<6,$Vªs–u¿<´ŸxÚ›‹X€”É=qi …üQ…¬GP¤Ÿ¹|Ðh)šŒJ Œ)kC)á~yZ²• z,7!!¬µÉH±R#¯ãò—­M–ç%È«a×sdyÔœÓo32¶>Ö©°ðSðYÌÙ*È3|>ëážE/m¢ŠYÉöŸv–
+è&ê<s±þuÈ=ø¤$q’,z¶æTÁ6%` åªÂ¥]
+Š£“—²7õšåª0`ÆŠÔ@Ðz)è^i$ÃR”º°qáÏÀ¡´›³«Ðú‰ÒZñgXö›9‡•¨5Iî+Uß0}
+ŽÉÃEø$}mùP€ˆA'¾L’ì,vN¡¾Éd†a%,2oR–d¨Å]Ž¸lú})ù´iΊ"ˆ\mãÏs˜æÀa Úý2°68e·Ð•øô(X»”©ÜÈi÷æÐ:[|è·Q}¾ƒã¿Âd’©HPfñë弟×"®Îúˆ×^8ìKáíXëžG–,q±éãêÓÜB^†‚ÿèZ™ûê¡âÎI‹¾­p7I¬À`â?¼‘ؤÃxpÇ9ú  ­l Ètwç ,!×%J,»{Þ…‚Æ‹Ñl¤«<¼ ‰QdRóµ7”À©ä%P¶TÔ_#Q»–0)<e‰Œ¶£þq/ú6ù¯k>`† bJÿá7EÃÊ›ã pÂr8÷òrD‘<Y”¡–|aádèB7Sÿe7þ¹D|`”6=%>ÇàÇL<]ªH'[x¥Ê—’½]•ndˆ²Ý9u^æ@èåM'ÒÞœûòÚàÛÚ}›Óç;»i)5úCÚÀ/Ö¾.%JO/þy-ºxŠá<ÃTß­‘õ"iQÙ]óò±·Š`Á¡ V´ÀLâ­¨&~,g ¦VIŠZ·Æ ²•°“MbÅäw‰Ä^”Ý|dXl’\£u[ŸÇÓòÖ>üœÐ3%ÛÞ†SVÐ…‘ë^ $›ÈVR'##ʺ«})ñOAN8“&çÿt6 Ta¿â>'3t9MÑ•• D¡^Õ½$ÊÍቢ9QÕpF¯aúŽ„Saç°Œi7¹UÝR­{ðï
+„qw“Yä;(–Éä¹_ŒªiNx×Û"¯‡š˜éVè÷cHh¡Ë:Ǽo\$5<[©ßÈ<-¦ÐsQ%Ùö6"<‹n,\GýDJò»5·8>öVÑËšÞñþRä+Ÿ–.õ S·±ú¿Æð§!’øåôÜ£î)E ñÝÁòïnO% ’xäî6øàcB¹}y¹wžݬ\*dÚ̬*; ž¼5š2AQý/<ÄÔ?4:/¤Â!TJɼŒüÝ
+U_–[}¬/xÞX1t£ê/;á’Éz'Ó° °FîG>úȤZ1ú|á
+¦¨*“ÚñViÝŠí”8í­$-Œ;ŒíÍ }”dÜv[:BAõèfs ‘x™ÇZ] ^«KÍOë\:çtšKžnuèäëëæáúÆ_Í•³<¥`@y£æeîñSMm›ˆeÞ@'6¼mw}|çLg
+)¸6l&77Ý×ñï \0Iµ5Â)Oò¶ „œÒaà4ÚÑ„AUåÜ{ìnMP ©·8@Œ
+.iÒê)F ò逧Ev»°]P†Ï”n‚£9‘ rG¬0½Ar1zߧ¹­¢xO`.‡¥`eR_4ÈL$Ù‚8E7R`®ÃG0KTï K´ýøqÚ¬`÷™\*Æ øf—“+ÎU‚5R<^üñ›³0£ ïx^‡*P_œVÔÓ-åNYÞ.õjb éÂŽ‹Ó@Ç;Çdzîbvùi.£¹•oƒ„@º¡7ÞN­%'C;Èù2¬Gv_“ªb%÷VŸ÷ñãqI^Âç@àóÈYtQÅö†!åê±å:8f£W;ãÎ%ɵ®Ô¡k/'8âÖYf—ì’¬€`cfdž ü£åPÁzP’ h/œË½9îËÐbm¨ÉÐÓj >Í®„Ùê±ååôàU昔™^´|0z…I±äÙ¨,ÀîÔ8*‹|t`Î@X©ÁƒÍýž@œibÃȸÒý"Òf­õ9†9£'Ôq‡·GëôÓ´d^²õc>¸ã‚ð²_jzZ†J œouœC‡-I ³î<óÛþ²^Æe¯DK¶4’â‘EÄYﶯ\ð­VgoºÿÛ+a÷í85•}eÌž¸wút²4ƒü1üÛ?üñï¥@*9GŹ¿ä!ÀJI?r8 öúï¡þÅç€ÌõOÇ3Öé-¬¯üÇy ê‰5ÁÀ†c˜¢ÂõûV2B&‡¤ÉVÒ¼‚œØ¸
+¯ÊÈ;„‡"aÂw>l=ã&hûš}‘=? ŒŽ“¿È.«À€fí‘
+f³5gäêg¿;m@£Èäî ©‡¦/J=ce’ÇSƒÊDå ²â¡™V†c1?Ñw‚[˜ú)Í=—ê‹ŠÿüçhYAŠÒš¥ÁFiŠ[vsà
+ ›ï)½/ß ( ³ìÞ­­Na\\î8;zÄ÷}©”õPŒÉö9¾¢*C^××A‹d<0CVÎùž1ü+]·04ƒ6™"Öî
+>¢ëý¦8–4ûóÇ4p<'=?,$œhã[ ªÉqó—ÝPO=ÓüqÒöîÎ"AÃÕX Q•f(|íl î¡u0a>“u Go &-yC_§ÓÈ­gÊÜÆ?§ {™—°}†™àf<¹—Kü¥ü€8@6ùP^&ÏÆz‡Ye¦kð3P5º
+£?K¡—Srºhè«vÙƒc ò€Y˜ö «î¾P4`wÖÚGŽ‘ÆæAò“ßa²Bßbœ«³—¦ˆÕ‰xä÷;~Å¥¢]`Œ[T¥WR22Ê#!§F¹¸‘¦¶ë› ðŒ¸Ïìö|
+WÖ~b#Öß:q'Ôë¤àñˆ ¼×!b¢ÐÈxinè¢Ï‡hWz•ÌU³BÜ0¼N‚
+ô h÷0P,|J¦ÌoƒÚš=ìç†õ
+>„!kDõãˆÖIÙ
+3#Ãgp£ÂkbÆúA(_,“í1á½ÈÙ5Y^˜%è›±yZN‡!&t[‡ñ„M«Ì C
+A*š §’¢*ÉuÌÈ_öˆŒ #OþÚÊ|]<ÿËx™dW±+QtÌx©.Úü&³ kæßýûH¡kœùìE.‘R(ŠSpshçª ÑÝZqIø—Û¯Ëо[>E΋—mcEÞ0QÂÙÞ•õr`'>°ÕÃÔ¡–ì„X•á&˜«ý霢 ¹|dL’Ô}¬;nDå ðÀnb´Ð ôW„`7 —jjÉȹ/DiQW{ûÆTòÑK
+
+ÝŒb•‰9·sÕ-Á%«4“´äÎ&br…üùð"g LBÖì WÏD_:.È®ª˜$”¼`ʆ'È:URÎö*Ñ+
+‚ðæô£,köÔ•Õœb:IþZ"%î0ÃÒÏÙ)@·Q,òw,m.vý%Ö•xÝ!h,*™?8öX& R_SŸ¡"éüxÕêc~ß'V[3VqJ9§G|g‚0—"òéȉb3†÷ÐÕ9c²˜ºGÊôtžÝÔà…—û¦Y
+Uã
+GEqŸ3ΨQÄ8N«ÐêÏnSÐ"î²æÀÅ%FåYÜÛñ² HoGšáX¾OT!3ñ =;c?AÏ,[²˜HãT-‚‘™ÚÄÂÉærµ„_“ð?*U~ ”eöJ>òé_øþë ÑáU® Üëq Sµ5qì Òh‚UÐGÞ’& °fÔx6;XAmAêØ]ÅÓPC`z3Æ¿³D `÷93«d”5'q‰úCÂuaOAZ‚#™¹ŸNĺ ³¥²¦µ­{?F"¡,¿koªà¦Þ@çaÓ[]q¤å¯~82Á®
+=N$
+ƒ¸¹¤¼éˆÖ¸äZdJn½ºsëø=™Ûäxº à½8ά_Kì„|jÕŸïìÌï9œÞÄõ탘>ö× ;¡˜šr°p¸2ÒáHô! Ž±C2ðšù Åî`á)0¥åº&Ö®‰SyõlÖZ£N|ø¾wýÎ…úLÖZKâíQ®U=O%?™ò¶\M̳<=Š“5J’ÕGˆ ùU ³²0µJ†Î,u6!‡¬›»4b¶¦$žuÚ¤›fc§½Ç|êù»ƒÑ“â†Á°¶oŠcÒ)þvtùÅÖñlJƒ1dóú“«¡|t2I–ÏCWC¨Sæ¤úväÚKÏÔÜFâ~ ƒ…6•¯\XÌ@Ê-ØⱈqNiDZ€ Cœ4_7Aå(~1•r눉„ Êe½I«Âö°³}Xîp
+7Æý§·MË* Èþ|½“ÿpc€èTÈV¯çÝ dÐ/AÛ¥sW¨B ZkÜ(„K*c©ˆ€æ$Àz|"ÇH…€=öŠóŒɼkgF·sP´z ér„Ž"„D‡ÚAÊÒ ”îœNˆ]ճ̞1æ§s˜5P©A'›„ŽaQÇÖ –•ÆãMËy8€Î»Dâ^¬[šøè½"º{Þ›Åe¼=æT«ë&,å ƒÆ 'ááÀfAs©ºO¿„ØÓ/%ôι4BœÅ£©±ˆÓm(ÀDýâ" ›ÄÛ`ÀYI @Š9ÍŸþ mrDÖ‡ˆ%O6¢£õÕ(ÿCYá-D(QO¤åÉ„Ðù‰¼î;/î’ç ýx»«úTv J©m;¼EÉâ$s6ô•z¨ê;ÍC ³ÂÆoŠ ™à@¥6|‰;avNLÿ@\ñ —Z3ÌütÎ-¸yä8. 1ZÌ]ÇZ}˜z¤Ò„–ÚLàx¥!+¨Ê†0y¹—oÝÄþ¾nÀ0<$þgÊȞ̓ÀŸ¨Ç6ßFª<eŸz(#Ü
+ÿqìÇ…3ní𸇶'üŒÌþ9 G„wÂÆŸlPœ0#ëz† êÒ<Õ|È' µˆèé5dðCcaCÌPTf‰;ÛôÓy‘ ,–9܈¶ê‡¨§òýµóÿ½^‹ªžÊ,3ÐM9ãⲜc[[(©£z\?™_„6àƒ²àcÃ6¶†Îr¾”P¦HF^ˆ²©d-.L~:'4”…®ý$#"­Ü–úQ="¸_„¤ÖP
+dA»€Á}UÃt”ɇ°thIqŸÃ²Å&Uwü(^ÝâÝ­?„pñà`8¢¦µ„÷ bé!eðç÷~zdà)«É›ïÄðoªÀäÏ6…91 p)L|Wa8¤¥Îú]8Wß`猪*=p÷W éŸû@¡-•Yªg¸˜¡Ê ƒÎË-|
+xDW¿iÖ”b'Éîùbý¼4ë~έå÷ln£ã½ê6÷ê8Ã~-±ò©U¾³4JRj¸k¢¿”¤J15ÁÏ;­µßè6Á* èAPîš.÷Q—‚gO+ý)ˆ± µ!Yè†üÓ«¨+Ô'ÆÕS‰~ëoBRS¡Ámw¼cØŠF9Bõ“Á>dyð½?JÕʨI+GÀø”:¥M…©£ ¸UßPLK¤^ÙBÆ ?¸¸žN骉KfÔ¼ Owƒ µÀ?A|æÌT
+6ø@•¨š*}è(Q+2¢!"èDw•¨ú€<BlHÓú²åÖOOþÜæâ~Ž¦‹äXUžz²aEIóÕ‘F—¹(º°HíËPÌ×MAî‡a¡øVœÎÍ)j½×£´1($ÔPÙšWBta'2·öŸþRÁÝÒÈ’¬&´¾ZOS¢ø‹Y ÜY“Eí%š -qYfÍVVÖ,$?ÃÕ2J}Ó7÷1RüA?Å$´Êÿ/wܪ‚ ˆ®À{pìÀšÿ'DN²‹Ì„ìŸSÓ3–x¯/~ ˆbîLwuuʆ{j6ëX4dJ+¾ÉDú Ï,$TYU©R|ä}.²ðe'èfˆW¸VÎGËKð*ðù@)U𗟨ç_O/ž˜ü:Ð8‡9g‘'çVK3¿ 41½°å ‚ šÐmä¹!<2ê† ñÐî<-K
+îwQ
+î›g6
+tx×@£6d¹P:Ÿöøª~üª(´uÒÁe¹1¢‚6âŽX<£0—4ôè€,äÆsS©eO»ŠàÔBÙ<_ .Úkuˤg2ömS*¨I-«h‡D~¶`¹F“@j€É³‰¤&ÚZ¶]‘r¯JÂ@Á &ænVä[ŽËL²»E+Q-e¨|uNfWÂ\n| ÈcU Q~3y›Y]Ëó\83 ”šM}>%?@Ø-íûd"ˬLÏÎAûT@ÎVNü#V‚ß›GA\bè]ñ·Ø¿ˆÁbç(Æþ¼\1‡:e¼-ëd– ÏœG¶RÒ"`jveý^û¾‘Ðm#ïêøþª`·•}ˆÈYºl{ø¯
+H‰Œ—Mn\9 „O;øÓ)‰"מen`V“ûoçã“dÀýÔ“6ı«õCVKRVGtV$>þª¡^jëUùχ˜”G·ÚÃT[µ )-¼Æ(¥NHsk^ïûòëÇR ë*ª"¯Ö)½U¯}ø„4)6J—®‰(ñˆ>ø*fu!̵·ÞG kŸ?N öp©UÂÌK‘ŸÔ†V
+MÙ®÷ aÑRÿÕ°B½†Œáí
+$sêóÏùø;«ä"pBÇТ«JÔ˜6ƒ¿4ØC¢u¸²‰ô tA¬çÉ›x_ëP¶QG/Ö]&¤› 1kÔ{q­Ti>(€÷ë耚)«4eLP§ö@¨oµ¹EjµA3Â5©
+­÷ªR#Ø…¦M‚Ô¼o5)3lLÒ: éô¹5êw
+iç^ý©çŸÐ£|Ñõ³Ã<6šPyÛô0ç&…ŸÈ ´z–ElÒKdËÔgµNˆªáÝÆ„ôæáÜdÀ­M"…e¥[[ÕT‹_ä»*mºA]gWáÅ@Ò½×ægDGwœ ·l:ÉqÇd‰tèeŸ³íϘ öÓ1ÓQî:f·ºCƒmRp«tHà½íKÃ+Ô·Ö¶M*¼Å€ #–ü8:;ò£¹Ü»~0©$îèT¼•—ë$#7´ÖqoOŒÝÁ†§x6pݪ¸Ñ\¨<ÚÞ*ýÙU:]„OÓ匵ÌVF
+’úà:Ûw¾Íž á8- ¶Õ(
+Èßô»=n˜fø*fØØúÁ2Þ%©Ø‚Žn78€h
+“ŠË¶Þ–zÍcØؤq‰jïƒÚË,á•¥p‹èÚð¤èYÔE ïèEÑ¥†Éå°dé´n»²FÓšÚ£5…0âÒC&1B*þÅaâ
+ò`(Ú˜ž~ˆ˜ÈÚªº‘¬6Û«u¸!>çdC0µˆ¢ºn%¸xdŠÙ©±æy©ÓH†®­Š§÷Ò9kÇ‘¢ zRKæÑ™t0/ÈYä‚HŽÔë˜`Á·>J8u½¢‚k°m#x”Q‹&8 ÆØ §íž@ÿ¾£ÎŸSÄ9ÉÒß‘H[[(æÈ!A¿_€î"EÐ0alJ}Doõz@zšòó¸Ý[ æRJ›£VE8€¨7ÜÃ
+”ç%â¿iDŠPî¡õðîüý”‹UìÁÕ2 œºfCbÍSzÇ]x¶ØlÙà¡ÇÑD¸²÷Õ´ÁÏròGW1Ó!Kɱ5×áÙ3r`È׃ñÛ°LHgP148p?ÏÜ1Oßf«ëðj*ù¨Óö W ¥¦û:!d1¡²$Ò}q‰ÖójL†Ü@šMÇ"„̦Ý6K/f©‘ \ǼW2œa©VûY;\=:y„ÄRNuu¾u㵪ý˜üÂ-Q—³ßÖ2œO³lÅuB®êÁ߉§XÍ'k÷½éGƒP;±cqôF;;ÉâNÇæà}EWo̟ȹ<«|`  dM§‹-ø?q9i_6íÑ3‡FÎdÇzÌø|.AœØ´],,þ¼ŽÕ¹14g:í7Ë` •Ê´ ›‘LL»s=hq܉&ÌWBÙžßßFåUlbw#i´ÓŒKÈu^Á Γ2! ºEQê tA¸!n’j– $‚sÊÐ"‹ó¨ŸRð¤[W2®‹PÂø¢<I:¸+/ºs$IK‹Œmþ.ãlél¤îж¥óÃs“jyËÞEG&]GÍìç}BZÚl΋6!ø1ŸJ¡bÜ°bø֑ɯu-Ô˜éÙö:…æ²7|]"ÅXú–6&„®-»µ¦FI+”3Gϱ:•¬é<b±š«heE5ë(Ñø­\¤Öe¹øóÉD½N‹œ‰æÈù2 g5Ë: °ä{‰Ý}‘8Z—±JÃë¡gEëâ9±ÕcVa«z…üÌs<MR°®bm¥Yãäùî%g®¼+²Ê¶ÎÌ[.½ª$×ÍI%ž™g!XÎ0çÛâ0ž…áñv@¬n¦6êÒîmz }™ ­éºQ«¹äùÌÙýi;>ZÒû ÷çÝÁ£Œü) mß×ìVßS-“_ä ‡11oE@LÙý’üþTºYÀýÁ5dÀ|²\œ^eÓHI¡è—àÝÎg¹1âéN‹YèfЂ«»ˆ±¯°cT7×Á?Q¥·1»]$‚Œ3ÔëãìÕ¹K`¦üzÇÐ×»‰hõné€Ëqrüso,-þ~Ê·$€påVªžÔòãe’ËÑôxÆ
+f™Ø2{“À}C&P¬¿x¢mr!émÈßuÅÅ_/J~:'gÍù6{à@×pÌèPrŤò¶ƒ-¤‹jÊ®+æÔ ¢ !ŸGÞû5èÔ2nƒGd4kø työ››þZòcC»’KéÝMSB
+cb›•Eï>˜Vð|;²r‚x+:ƒO¼ÀA=¸r _/Uûœn¨+%¢ÁI%mÔËGÜ ¦köêúÏS8‡u¥›ðÉØ¥•ªú!}?€TGÖJwÏí³’2Gö 2ùžµ)bÿ^!·ç|œ2™Ò«>«|)_¶Y °¼%„‘¢ŸÓðã#F:/Æ _!¬EåPËÁ„X³bÞ„‘Qª\Ôv@×c"Æ:Ó}lCrä^œCðE„å œsØßmúMdqS[Ëq%üã
+áÌøR:¬Ú ÞDÖ‰ò/q#b{ož:³É ±^Äšy†@{9A2„Ì£ih}S™>‡åA@ ,Z_†/*SD+ ŠqGø\àÈáׇSŒêòüw¾åX_f9;íòÝãÁÓ‹±£3¹¼H7±”üXç¯í°œâšâŒª`šÛ´ Bc?FæQÆĪ%œ¢——ÿŽW¯ú
+÷ü¾œ38²H°–k£O|€Á×Bÿn\¥^gÉ?‹3š¹ø:ÐU¯„Vîod¦m´qøþÞN¡Õ‘\Cžð̉£Ä˜ñš[냌 . x³P Ì`J>Á—[ß
+ ÁÌaºõjUk5¶.‹…úŽiÀ| –®
+Ö-¸@¶ÌÊ À(ÄŒ§s`1T—»óù1·™¸|ÔßÅ¢Ô‰_†×‡kèá{ÍƇó,wpYZíÎü1HBû>Î|­›Gë²oú™Ô—EïM>¬àÁjÚ&ër¾G7ª˜†s?£4ÐB[לö.©çÑDWº`ÿÅ)F£?&$‡Ú¬r:ó-H ); x›o#±Å䘜Îç xÛP oO†:ªØ Õ^‰1kμ»ÐJÔmú«<'õ†9xtžL€!ú%~ø[ wUÏ&Ñû¾ xÅX’·…ÆK]µé²)ƒfn ´CÊ”Å
+&‰°éß „{‰`Z î"(-_Ìâ×›n Ó×e=T±.©v¿=r ™¶ñáº_°?¼ cx‡…©Z!yCôçL­¤'uíZO ¢ùbü™Õ±.>]IvŸƒ[A†ñ™ñÑ&৻äËN~ãë7óþJ
+Ðn÷ ÃÿµH)â2û
+ cÛ!ÁÕÍHძ,ã×£ŠªœüÓ‚ßÅ82¢µƒ7^_nržlW®‡Ìà_N‰ÿ²Ym‘Ó¬ÕGTR ÍT ÷trkç)åð )ÐO´/>3иÊ
+OÊ>¢ü¹C{Þp^GÈÕr7…¹¿kHv:ó nûs(D˜,· y_»KÈùó¿Óþž’ è$Ë”ìüÁëHŽÖéOrÊFbÖKr¿Ob -ãÿ½8äLV¬ZÜ å†Dn¸‡y[=ÇE2ìK&›!±ýØΠįóÍíkñ需on-$?‡ñU^b–?,‘”ÅQÆÎ9,¹Ô#¿g´ÓÌʆ„ÝtÑ3K ííl°³ ä>ŽÓÁ•7¶Ä›
+ê»yÃÞVD99¶½œ7P/™ÐíS]¦8h>‹¶‰L“Ê"c¾;Ž€ÀÖ¶ù†ÎGÖƒI/þcŠy?%ÞJ…½¤Ýx«Âœ-øj~Ò»ŸusÚ¾ÿsag¬:;íW©È]ëVÃ’X@ìdD›YÄ|
+Ro„BXúúòòàÒ‹jk'Є[‹¿"$m™`.PP"ÀH RuÓ½;BšE*£¶B܆¨SÌ·@z˜æh´œ×1™`HqØZÓpüI¾MU>Chɘ6ÅÕñŽ¡ÊQ&í)3
+’qˆ"žìB,欥ölßI}cÞ-Ç>S?|]Ålr(Î/wv&\d¾jCî*3PƧüy5óaμ:Ï’Zퟢ̷ƒ jÜßiØŒ"/ž›íB“É@¨üF¤ K:D%ÿ½vUä³è~<lO±ÄÓMZ®BŠòúGS¤ùbþ‰•!=˜+Ûxô?Œ—ËŽœ·…Ÿ@ïÐk/dñ¾ ”•=A
+úd8Î?úq)@—0Ë|ˆv—TpVýlg®„Áeˆ9Y8Š—ÐücÆÿos%ÃHÚ7+sG`w^e•ÐrjRYÞàb+O%lvθ è}Ì‘ ÈYØq(z{PôašW¬ó*&f€uÜlÉa,ÙŽº{Ãu;.eMûáS¬)
+ÜtÃÛi†@óWMT,2_Ögqã`4¼ÓÃ?& ? zFœÉ\u'€á;|0óó­bɱ€¿sÄÕ¢œâíqª„Õy$0_®'j;‘ž€Åôd«ž#mbb7ŠCPÈ—/ï>¦½a<úØŒ|@Å,|HdC³@§|T-Mɇ%냒Z9#à
+„ú·ä1¶åˆðÜ~ŸKÑy}{Fƒ_eQK«ü)
+~(áMq¹·#Ò¯q_swÅrbõ‘>èé"qÚR5Z1vÑÇÓîjÞžØOmñOÿÄwù!ÔVïa‘*X¶›LCÇÏߘ™ßüB}¼…ù¿_ÿGPý™ÿü¿ŒƒjÆ»ßþ¸åÛß>ÁùRÌ– €‘…˜q0@Wg›Xƒzvcds’êBEoùW•£úçþ{îëÈ—õ[EÍuóõ‚Sú3×û›ýq‹A÷¸ýúEç`?!ÑaŸkÀ&c &L}™
+¢"ìaQÈ+¶ŠpÜ¡dqÅXJ v¼3À1¿FkDÜÔà «„EÆÞ ‡3D´œ±›˜SÓüºŽ"†p»3gˆåANÛG±Gø-Ö`.%\ ŽÐÄÇ,)/˜Ð8r’XJæQ °’o(D‡GßÁ*
+ÝN%ÞäN‡ ;(E:ÏH¸É>òˆä»lIzPÂC¨·Èúó§sÑ„¼‹þ±ù$¼‡H½ãrÜSEwËúöÌF/Ë&¦ Ð'××Þäá«áEâ´{×/ŠÀQâ‚\&­{í?vWòöãûÌKßþªBtÔJdÿ`Îâȉ ;º®_˜9Æ*Š‚E”H:8¡óǽ®R<Á­ êUB~þ|•dÌ/}͵°Â“Av›°!ÑvÞ+ÄS~ñùÖwP†‚Í"YøQÉò ÁvÉz*fb2c$O¡FUº¶0© Ê)‘à3­á}Ñ냢 ÏÌš—&ß¼¨
+ŽIQ2¶û—æ”x!£ÐZÛ-Õd3f”j_%ÐN®ùåýI¨o]FßY ;5h#ôvŸIbŒY´õøŒ¬Ä´­§õ£©žna„‡ ¶V=–—AB``#`@˜>í§ßð[9ùÔ”yáÌäß!®öܺðà*éG²ïc•y9Ð68>€•¸(‘WÏ ˆÁ}†\JÌ $XùIA @¸·cT%t2\÷T“ãþ h×ü¥èEæÓñ});X11r²$3‹þlÑ-JÎ4|ÜĦͶ¼ß]±÷ƒ”bë;¦DÂu‘¿QýÝRLÜRm[^hl¦;ì`¯Ç¹ß•lˆñkÎÁNE³„~Êq~öÛ$œ6
+wà­‘“#ëP™]{ QÒ:@³o&»Ò¾²d~FLL}&[ywè%‰Jí*ÙK
+úXùœÔ~%¿‘èçé"¬¿ ˜@ :(Ãw¦k±2*I _E¨:®øz‚ªŠ$)gi=)!tÒœ*8n0%Ì›~b{È ØxA A—þÿà;CJ-ɾ»ØÐ(é>Næ%\0êM’غÐrâç,®EwD‘Áñ´ÖËO%-zÀÃqù£SQUF‰P»°®M¸Ù—-ØaÀöMìèX|øN¬ìãÊ1è›ÄD»‡az^›ûQ°5 ¶³
+‡Ûó 2`¹KÅû*‘qsÃZ>”|]È
+qæüØÊ–™í…ûkÀJLj¥~–T–è—ÕƒÔ>ŽI­TX"Å*¤F? # Åç ÔÖAÐ0oMÙå ð¤ÊÎ4@IS0.é<ÿÔZÖ²**$œìc$€@7"hqŸ£d˜BmÅû‚'AclðY[Éü Éz7ùÀ/ òyí%ð «ÜR;8|?ek™»`C*Ü çJ¿_ȈâÙ*×}%H›ès¼ûQÉÖÙGÝÁ­öò’VýÆŒ sÌ_îE7¢UÖ®åÝ<l˜´Ø<'„†[C©BI}Å6
+V£÷mã°u¡ duª:ÓƶkÓ°g ¨,:¤Àˆœ¤è1¨ÑàˆJÂäX´Ÿ¥ï» </Z'ÄÛK
+I Ž+ÀÄJH¡šOèùõ©kŽ!Ó
+¦$?‡=fx
+X§ŠeŽÆý¡kMŠ€Jìž_ëmØ$¸Ðšg+ðRÕ;êdÊp¬ë20Z”I m7!ªt.ºr0h×pT¬•ã¼¢7Yí±qtþ“"\¨p<”lD˜Á~;ƒZ:I\ÉÛIHÞù“% «dR€Ö»{RI» ôþÈO[·ƒ¾„4Jb´Óñþaîá’Z,Y<–àGÐK" ¾­¸oãÊ{$ÊæRE_^ÔôeÔí9ö›õØ[Ç
+at¨ì·§’7:£éÇôÁøIËflÑëý7B±egã'yI,ÈöµCÑ,QfL¨­ô˜?Ã,âª@1aÉ!ìOSÇ„uô`½ƒ@ÊåÁ zð"ÞQ䶬Aw‘YÚ­¾¾ç.d ‰vÛä'q»,,ߊD“˜Fv f±•¢ä@ŠÀ^öCÑ—·l`ö€÷©h–0¸?Éy ;
+¸¥•Þ°‹÷ï@zðà 05ij•¨ðЖâ_’ee‚1=”
+kÁ?°~ÍÎdöYåo÷KGeªr×j—ºÎ)PN†h¶ÉŽ}@¸ÒXºu¨àwù2jÁ…ö—.E.b»0¢ýu¨šK7wÛ¬T Â:ú—ˆ,Ó_™="IÁ3üûÕ>(ójÞþ à‚˜lCÀñ¦•|CçyT'ø0*ÊÚœJžØé­è×±èWEP³“ö×M©UÍ©ö³%£,$a0Ô“µWºCÇ Ü´Íô5"ðv|ßm»ÿkЀM“ø ˆŽöX@;;Vdíã)ÕœHCñ)êUl–?*VG@²þ(½µ¸—ß+óÆa·dI…"Ÿ¥[Þà‹™¶öTÂÆ
+{ÃÎ:
+±.1F¯`[а»Ýãä¿ÿœkˆw02ÔŒ×\#»%ò
+/ï‘iLóL ~Äw[wU!ÚØ°¾zÛÈü=Ÿß&‰à1˜ÎØï¦á™®“¶ƒ³Ddeñ%8mIÐç¾ïÞ⃼ê~Îmà÷ÛÜ€sxÔ~÷ÖÜ0|oðæoƒúïOF»ön½L´’Óá¼ïcQ"÷áúEÄhϺ—lœ”ÅC§Ì1™À¸Ù*á`,w}9˜7´ož ¼¸‘œÎp½,Õ·˜½Ö;¬œýß}îÿ'ˆ‰€¦X}:F–`ýeÿ.wiŸM¤‰µ§7u˜ 6ZÚYõêsôy†[*’Ô
+ËÜu@ˆ3Åè%)³1„ Ûs
+ ¾„r±ëßÎEosÿz(Â+·ØWVX£Iݹ)
+Þ8ó2ÓJ’üØtdc£Ò%Âøb¯Žóe €„Ãÿ Ir¦K«]GʼJFT<…"X–¢|+ÙœüŠû1 ‹ë9j0§äNúÄ™ÊvùËÎG™®-ü9¶@yñÄ”ƒØ¡øqéº%
+G(“@Œšî&ÀˆôjŽ¾é·µ›Ÿ"9àÚþÔßwó‰ÄàI ù<Iä¡Cz¶8õc–Èdˆ,˜ËI€Ó"Q£ñ׫D^¨”±…û®‘¬
+.“Ë“·º~­ºD•
+RiŠ€'{Áª§ß%âÓígX“R4ÕþqÑÍíÏÏ‘—ØcQp}.R+oµ”g/!º(BâQgåa ‰ˆPý°z’•Ó8NÊC÷rî
+ÅdžG~5ð3«Œ§ÆÉy˜Tš¦hÅúmÑ£üNŸîvæ[€3}‰M5kŸ° Jƒ²m|ôD«7&H­!Ñb01¬Ë–ЕTŽÙLRµ ï[Î2|Â|b6…]dáHQÎlÆáAmâBì)ë¨ÙL‚ïö2J€lA³cl£E0²ߊuРß{ž êãòÌ–39*ÎÛU莡Š›åö¢ñ•dìOðåGfÈò+ËÀm‘Á¹i>L+¬&v%A‹G£ mCñDܤè•!ÎùÅ»M\€ÐµÄŒ……¯GE
+¾oªöYÎIØÄe¨x!Ž’ê/À8#CŽÖÊ…K¹yzHì¨GºßßyÍû6¯âó^õ*âwp¼~ “Á£âŽ7ÉÏ-õít“è2{­þ÷) oе1Ýüà%zµºwœc¿¼“™F#%Œib4TЋ²3µ}óöUû>O}n C©°Gô¬ªÿîi¼Ç5µdh„k^"‡D_§ýŽ¦0¡|!—sXÿZy¾b^$-'q0ƒÙÚ±—·¨ãԇЎÃQ™§,`ã|ˆ…„AGÿæëØèô)M¬âˆ~üFÖVn×zÀÖ†Á×ÄåL©ÁYØû¦òJ0#®bNü¹ïæ}ˆ¾oßf
+ÃÌ
+(´å’’)ÌaB¹€çž-ˆZÅCJšÄK¤àÛÌù÷wªh›xÖUm’Èg:¿Ø§]¦&%›Î8_i‚æ,,ÖÎQJ¤Î*g"j‚és㪕ާ}óš(òœT L.’Ä© 'ì[çÇIOÿ mÈÕ¸èÆE‹(½Ç7ñŒeÎ@¼Ç-ÅÇM¹(8[Â!¸™Ò=ò9j(š8 ^±E…û
+ÂwøHe¤øv~
+pÎeè­”Èw]…Åg W
+øßL§B'4Îgð¶›Ä0ÔJ,»Ð™áE<IX€YE)™<Z¾I¡
+Ü(`l'=E$ëètã´'–”Ú¨Ö—ì²”Z貨ý¢„#°ŠšCÐ{aRÒ‰Û~Xãè [Ò«ÍFò„˜‹Ö û
+ôœ“it³#ÒÜHK´êäËUÕÔÚqL / Z*írŽÂÕ—óq>fOÈúîzEÝ­_j©›Oã‚<‡ ÄdGëвÃÏŸ‰;ÿŽPÑ8 Çmårª-=ðÿøl™ÃÚ –Ë2mB
+„^Æ!ÛEBâ|¤R©>G=Eò×ÁÞ"4Ùß!ü];åXŽÕXêxƒÌSíQü3‹fÞåƒa”ë†EOåP'¦­a-G0O¨eæ e1 ÄÀM.¡tKÅK9c.Å‘œš høRCv¿#£¦T)§ºv1]†5Êpl´4n[X[¹½‰‚bıÆý3ØŒ!iª¶­Þ­bÕ¦eV c"åÀÆаŸüŽð×P
+Äã£Q–5꾚+ºÏ¨ŽèÇ D;÷¼E*½@­‰@¬ãø)­ßû8÷©…©!{êš9Ù#Å÷6l܉¿S½†8¬É½PÊìˆ"šA›Ú"EIˆ-Ý«žþ~eó“ÄŽ‚‡è"œ£åÛwšJŠg™1IÁ"šÆp´aÈ\¬¸på¼J„ó)ãW¾Iõ—ªß o¾ÄBÓêSÒEñ‰R¿­í4 fñÄØ8+ô Ìz¢ÍJ¢dÌìÂ,
+øƒ¦ ¦ ÌJ™gÕXrY…V Þˆ…d—eS8øïE¢ó²ˆó‹Æõ²Ë²2ÄüèÈ.ËvZø€/¬ú<–eo­<ºd-®>Ëv̘n$åê³,
+à£u÷Ý›eÉ›eÑ“e¹qÜôÂTôY–øÑîA«K7–í˜&2BÃeY=15ñ>î2¨J‚'ð{dª]X–Ò¢x£ø¦dO´$ü­F`©<’Ï,‹„¦%)ME|aYD,è¥ñ”E“9Òh'ŸYÖ“¼`VɈ¡Ÿv{YOô€YIHf2À³½|†Y5/ˆŠ?ó¥r¡Y¹‰éý0\šU‹³µMŽå
+­·’’Ï¢dŠëqlïÝÃÞ¢°%ó¤_˜–¹Y´s*>Ô2 6=Øöç@-#†¢/|O.Ó6È N*õì3­#y3-÷U…SWù€æ›iQø)(Á¦¥í¨·.3» -ÁSsÀ~˜ã…´^„H»ÚŽs ÃŠzÉ|!­Œ!œ)æëw’ʱcŠgz ­J‹ÞdPççUO¤]|H¨~þï­^”ù`Ú_Òê‚Ú/éÀJ¬±31é3?{ÿß[CÍ‘´AáEG´$& Løôqÿ@!
+³:¢ï7ÑÏ<ùÃD
+Д§—3kîC—èÖaD‹¦šúö.
+žrɵo D‚Uc̉C@ ˜ÍÃ[:ñ!¯A’±êC©tÊÜáÎgÙ+Ñë«w¶þoÒUá£<¸‚Æ|
+žÙY}°ÂBÂÁÓTÒx=§žÏ°ˆåäm9ëg¨ÉJ5g'ª=&à~~ùJ”ù@±ùöhô"͘cÛŸƒ'Þw6B Ñ ÂѼ® éu2Ão¼% Y<
+ÀÚzÜ)IÞ%X'Ì…Ý‚d³`Ó¸ÅòíŬ!X!óÙÅ×q¹VÏ‹Wë±`Ù[TsåÛt[Þ…Cø‰jŒôH®>¿þÆzJ«ðœR!©é†B'øøðØìË$uõ #µn‰v=î2Ù›„nÄ—³75æ0n1øú´ÏÌžY‰š¬Á>ƒ¯c¯8èðp|Kø¡VHÈÕˆIL0ðxò4ùC)¼x0 3w“¿ìâ7EQÙ3Ó)‹—¨È”1o¶ÍöÅŽíE Wú™šŠ˜ lNÙäŠÌ³–Ìá¡Ð‰€,¶“®„Êpù™M°P<¦íÏ`š˜T`ÙˆþØ¢.ÈÉeæmüUx¤&h5]ÆŸjgôÿQ^æH’ÜH=Aß¡e
+iX›HkŠTçc£U‰s¾
+¾ºÀª ¼krßµz#¨Ëi!lRÎEÔl‡^¶]$6’ER¦pó:Ûʧª6t‚`km&±û¼~¥¾¯(ôcÖˆ“”u§•æL¨Ëœó‡Ÿ 4H4+xÛõ11èô¨}¯þ’âÜ¢Ôš[Õ꯺L#k
+%ý‚¢å! ¸Ü?‡’‘mq4–ö®¶_›%ÝšR¬ ýض¦f‡‘Ú#˜0{DT~–íöz€á =ûwɘ4!Í á–³>®ÝoÞ?ÇÐ{‘áfÕV
+q‰9é}.&©Ëä¶eRL ‰jŠÙÖ™UDV‰@⤬ĔŽvåñ.æS?n@‰5áën)³>5b@"#hËÇ _‡õJm6v„´NS"ÑÌnÛ4Å)ÔÐÊÌ(*Ô ï•xéø øœÀÀ‰ÁЈB~š˜—3’HW@p¬Ï{4õŒ!Š6!(†hO‘¾X.@!…ÀõåU•,“ŠS‡ñæ9\Tê‰q_ç°ƒRŠz˂ཻÜ]]¥Ï]à
+Ìt`7öŽ¿, ¨\À0Y+~À: ‡.·RÓMÀŠÝ©¼šˆñ&`¹ sÀ/ÄF¥jûF¯ ˆÑ<µ°€pûB9p;ãfÛ%Y3D6Ç=Ò¯ HÔ ˶GäÚ­ßwýgÂâ4-©8·'»IXê>wüâÎf-É Ts#ä‡ý¨±oz¹D¬X•¨:Š’º o R7dyK̺‚œ åÎÃÈ æó#e7jéåÓ²¥[±ÏQKÔÑè’šµÔ9)ªŠo¼Ö_L†F1°tLV ~dÓÌWœ
+ÚJqmZ‚|Yï›°‘dŒ..¿
+2(!cN1Ü°SªÃNlkp [W“£®Ôñ&è¶<Ð)l‰í(WäaÙ [bM~Ç…)d¿ [ê;ŒDÉpÞ;½¼„-Ã@mä(^C’6Ýdß¼µÚEdâ;ƒÉõÙ.Ï Ê&xaKdÈáuXô}È9lÌË+Cj­V7lÁ£ê:Q3ºaë2ƒ^ÚÒ€‘ÅÈt19ÁK[:‰FÊÒ-eº¤­+É_ið+:i+¬ŽõãÒäµ:Ú
+»;I·¨òL3˾3%Îè1âøXyèØdõ™Î[Lø ­ŒÉðRÉ¢\¬ l€Ÿˆ^Ö: ¼¹ÌË‚@2’iç¢ÁCÙ嚇gúçž@W Ä1"Adݼ‹ác£¨°c`ÍfGŽê>eÌúPÊŠµºs’Gˆ¢Å‚G
+ò6ˆCó…±ä‡³„E{]`‚˜jòe›VP^ÄŸÓ'
+@f‚±áüª†×
+0C3ÿŒ„‹òõ¶íƒ2g`aZYC£n7ʪI›ï©Gë™l{~è˜HÜt„Ž¦™ÌyÔl•9 H*‹®ÈÐ;C®úCê°f'¬Ì¸`œfCƒá)ð¯•71#…LÃvØ8tÚºèãÕü{.0)“AÓâý=`ȽϾ`.6ý
+K(Œ•N6 èz®Ò$~ž”ÌÒYF~PÄz¶ñaŠ~؉›cèkdÃ}_´?!l7‹R‘ë%Ž)¢‘A̹¾D©$±´t÷±]x‚ÁúRÐ]PoˆzÏ&
+ÆÓ%]<àÀyƒÿÓ-0©e˜Kß> <TÓ­øa)Èêã¹slv–
+‰ÀQÂÅ~ü¯¦åÓÃxv‰!t±ó¿]œ÷¹·@1‰
+
+˜$†Qµ¬¬S´"Ïtä ÜNžÚuB‹(«µÜ*S•ÔkúOº›å®œ$¦ô7Å "C)¾DF™çðkÚÊ$ísbi˜ vn˜~Ìb)mšºd}
+ýÃâ")1úç4œÙ•NÏü%ˆâ£¦ý9D
+7æ鵸0s‘W‰£“8§ÉaN_ b!ÄÆá g•APZá6Æ4\Y–!qì*÷•®Hfëéň:Hsd=e&PØÝ9Œ
+Yäu›BI-[0ÂìÀ†­2-x¦ùttBÞe¸Sä>äÛQu@×Íp>÷5è´¬o,´Öþÿ áþïÛÿç,ÃmܶâÒ¡¿ 9!\ÀKèÇç ¨bŸänh¼fNÆv$Xf´È8î›û„@³…J`!Ç„Œó§i«ª|M˜6¯+šŠÝ²rα‡òeQx˜t áE+Ðä± Ñ°ïú»<Èñ)cG'£MñÎÉ©j-¸ÛÛ@˜¾Ôz½}•=,³~È®Á¯Z!¾ŸŠ_còÒ«ý©3¨ãw³ 6úîßBÆtm¶Ý¼jÈ{WD%­}¼VÕÖw*uƒy5–32V‘¿ìn§^
+LÌׄ€ÀTwævA(.uàªjš Œ¦¦‘&HgB(9sà<NÒ¯ÿa¼L’#¹• zÝ' aÖÔR·à–¼ÿVÏ@I•ÕäoÉì7å1ø@Qæ†L> 1":„v ø2ªï~u¬îŠ=ØFàc¿J ×ø.ôÏ PT²ƒ©ÉcQ Œ,ÿ`ßâù¢ÄÛùßÏØÞŽAGŸ­„ˆkJÖ µlH—¡g>Êy:«ôEÞõIdÇ‘÷óóSgþäˆm_¶H•ˆÖ¹øÁíÖO]ÿx¤,A™>€äÊj“M£i+S9Ï|`Šé펱†,$+ls=¤ëXu|CЧ ”ÞÐÚx`p"’DÚh‡ê?p pÀ>G>CΘ"mˆÊ%Û‡;-.D©“Æ&óSöx8 j¤®g¬zÙ¿¼YäÝðDá­ÑÚÊ€Ál“ë "^zhµ¡Ç\ɮТ0›Aâß±½$ ˜äȧ’Ÿ=}ÎF,ÀÝï$‹Ã%p¿Ò£Ûù ä ³”0œs³³wÎä‘…¿²ö5(<†S«Ù6 k/ö*d„#Z¢‡ð¨Ý²ÇpÇ1»
+…ïûœ<Ä’˜×Ã>ü
+}èңߌÑ+EL’v¯°•lœh+[Cò–•]ù¨´÷ÝaŽ_zm=Êb2˜g4. —e•h<ü0ù­eb‰¢,À—«F‡WƒÖ’W<äÿf#Ø?ÑM—vÄ£í²k½€F7…ãZ; ‹ÓÁB4Bc~ò†078DºV²±«
+üìä¹ýÕ9mRäÛ|@x¼¯íkX$¨oÈÛÃl òWia Lñ¡òePgª½û0℈øð¥ y
+£0‹;…Ô˜¥UÚ¤ø†Ûàlî³OfèXQ¢—m)ݤ ƒ©Ùs ”Ïò7"üNÿSæL& Ïte¤í[.“øí‚2¼
+'L­`*Ù}øb¿Ð;çÒ>F‚ˆ›(x·(£ÓQÛÉçÙM—©hïšý”E4ÅŽ¹ `3›²•­½€@pC#b<®úã ÿó0™>³tUÑqšä"dQö™·}{˜•nátȯ-áÑñTòQ(¬•h*h½ûFÀ6xéX$.¡…˜\Hò|w€¶øƒÌYÇbädŠÏ|D«4ÒE‹h­«“ 4ÞȚûr«é +*̲ t—[F0Á: k\Çù– þ2’Évž„d€aoâ«q/1ÖmʥϸÕ-à¸a;&Hó[Ð%ðˆ¥ESH˜%Í7›sªˆâ’üÇfˆ$!Ͻ©·aª¨kê¶Sò‹½,õ$´'æ½uâp(.$&B=/ 2½'{n¤PYÚÑŒnQ]¬
+ –Nkñî öŽcnxE¯k²rÁÀ±ÂÛí—®j/†
+7ÄN); /UÅ8¬C´»`DD›Òª; ÂES–±é¿¼`‘¹Á,ž—ß Š—Ó»^©ô8 {æ9jŒäÍÀª>WÞºé0.É…ƒä{V¡,†¤Ñ 6wáKÐv/ÐN’ƒz!|ÄGF˜Í”5¾( æhÛப
+i "žû2ÜN] 6—Ž{ç\ææþ5ÎüÝ_åÌñµ:Î6DHH®{xZªÇW‹³êßgtÂbn–ùÜ@×]÷n»sÆ_´HãíoA™ÏО-„aBØÆâ¼J0âp@Ø6‡.@Êo‚I@®í³Ì[˜ÌLKú.8Û2MÆÏ¢ëCÞR’²\¨¡‚´“Àc¡Q&ÿ°˜¿}Š‚E£Ãõ8¤gû‹ÀÌÊþ$²®Â°»Ž¬úç " §O-ëqZ¹âñ*ök.U¤`}hZ›ìÈM²Ó`—%¨ÈœA@Ldß]s@àT^‘cÞ—U¶0i[Ù‡!ðã”XvhAJMŠ'TÐÌþEm`>zy<æW3ØjSÔ ¥Â6ÄÝP ûqoØU×ì߫섆{·¼s.=¿Ímv¼WÝfð^g’¯5v O½úüÍÚhÃÂÞ°ò>xZ+8»šœó¾]PÔÅÄŽ·…€¦ J‚½®Áá£bšEÿ0AŽS?_D}+'Y]œºú!H GQ/ûÞzÇ©kÊ‚Éw·éŸ#J£CѤù_ƒKÓ_ÚñDÓû«þ2*–G<ž–ÍÅî««}N#O,bcç!
+À Ð+9tNï´ûïø_Ð6iÒü EÍëXîæ6·ùŸt5PbS£
+¿§5‘zïÑzKÅRÄ8S+3SÍΊ5el:NYéQ„²…Ï,³\9¼°ŽÎÙþ‘¼ïG8·ŠO€
+H‰”—Mr\9„Oà;èSA
+õªÅ8õŠÖ?~|ûß„7­ÅCä‚ñR+MíãçÔø€pÖ•—pÔ…!_Þ*ÿSkð‡V{Û ·`_
+s‰¦<Ámç˜/^é–è ”aZmÊ?ëáD–Êä”v.²×Kð¦¢z@\7NͺÕã!6û}¨Û‡ho^DŒ®ž.Õ­ôÎ Ìg#¬n˜ï@Mœ 3lµ®9¦üR¥u-+ÓJÞÕÞ5
+ièí ò÷þüþí„95ºÑ~ÊíTd<NÃô6{‡hÆÜÈà<V7Ð"yéhFÆlç±¼—’Ì?ZŸîýyÏÑ!Ô@Z9`î´" ríÂ(œY©h…ùòþÄ*€˜c/=Δ"/¦Œ ¾Ù™ „cEhÊÞ4žHE8¹ÔLAÕ§sZ¨;˜6ê™TîE8qÊs¢BY%›¨•ø™Rx•–Ž°EŠï‰ H rÜÍ+ß} 
+)>:\I’N)Íj=PJy!î”ùòO”R^Èy•ÌqŒ3¥
+¤W[×#oŒk—‰@}i 7ósƒdÕ…a$’p<‡Òn5Ébå™ÖoÐÃ7©¤¼ð'ŒoêËÆåÃiH/(ï.ü t›«ó>üª¦ø˜ãðA„‹bšúì3ƒoöb@¤ªf‹ëÌÞƒöEG«OHÃÓɘZ__ŒÌ®ZQ¼Î|´wî Vl­Cf›²ñO”edRw%Fi†ìëîyú‡ác´ê*§àÈ›:}VŠN§µ¢ÁÂçs°üÚè^`’ÓºeBÂ`[¥†}ÕÓ9!:ƒ¿X' í±Å‹aÖ6š”6uà_x³­ô!&Á'CLW$>à†d¹U„ìW®k›mßA§Š³^ýX-ÇëË ßÇïó #z òÇ_‰ÌÄ¡˜ª°Žôæ瑵õz6º Øw*ŸÊ6jÈùÇâY'B ^ÃëÙ:ðÏÌêª|{ h˜5»·åü÷•,!Ü$‡V÷ÖfŒ2©¢iÚ‰1Éå¯ô±7r¾#:µ©ƒ&€äí§3k mÀÈ@Ÿ+/L4ÒGètAXð¹A~×9)ÖpãPi B §«ý¶VHä({°Éž¿–zˆì²ÓÔ*°ñ´&N¾ôyNÉÿ—RÊôý5мËP|Ì B3M—YZýU„7Œ1”Áݵ,ˆ5îƒMmù d9§ êé>!°:”;b·•Û媘/
+·"±1K ÿµ½® ¡³$ç•>é—9ëO­÷Ïüf/³Ù;—
+øAÕâ4„?Ws@}ÐìmÓà~o¼ßVƒÁDÑ0T¾†C t*…•É Ѹhβ(E#³WÎÖû#”ŽÇœnãy‹ÄX5tb.c_ø7[” ¢ÈšM8ÉûÝ\ež/…`ˆËÑ¢ rXyì»\é®È‚¨ò„p l“ð¨5›ÁrÁ Õ¥þB0iÊ$?ÛÏF‡@}Uæ9žUêÞÛ6äš|φëþ
+‚Š‘‰\7'ÑR:
+6Gô^’Öø*uCf¤Ÿv5S‘ÂUá
+s óŽtÅ“)X…rq”mÎärBÜ®ÚSvp,Uø"éÙ9Æàñ÷Êt\B¿ä¬–_8gï÷%'ëŸóAb`jí§ý`ÊŒ‡³EÂöŠÅs¹ t>!Šb£Ùñêb(•å³èfFêd'Âb¦;ÏñL(ÂmºŽa\{&â‘jÄíùAKÜ@H4$‘ Ú¶mp˜‘«0T¶=.„åªfsM-SÖi Pп#gx_>% ÌC_â:¨[§(0ŒíëÜ@7YýüŠö®å²ò’j¹óÕXÜO $ÅÐN?'(RÞÓߺŸ^é*IŒ@0•ì³Pq:)ùä·+” väÀw5K¿[%méÞw£åâ>ÞS\¦³:¤H~ºÕþ+€0„Y†`ÏÓ‡·)ôX³C&˜ÈË (çJ6Vš‡ç˯[Wz¿j:õöpAÂZä­ÖϯvÕ¿\ËŸ Ñ æ¸²ûQëY]í t¸Ry1Œh6_óÚô„ù<ûè÷­ãóƒ‚ñ¶Ì‰\Ó²óÌuÄ6GÎ^‹£]NɼёË4_¾ºñ_V×IEF³4}èV;Ï~¡­xnDouIöÇG –~2ß+ `ägOçT®‚b墶 ì@=ôãT‰Û…¿Ëuâ™’¤Ë¤rº‡,Ã0T¸ä•eK!±9™';Lúð/‚ì¥:šê2^©^—²Œv:Åí\˜¡Ø×ÅÛ;ªZû„`ŠðËUËÊ]0‘IÁ |òt¬‘Ý»z‚­”°¹iY‘Ì(Iµ•=º
+}bj1l¿7è÷o'Ì¡ÓK>“µFíþè>|§hÆÜØà<W7Ðd–Bn%·cT–H[¢—[å“ŸD¾Š±„é–_š€Ç±•}«HgrMNßñö¥Ë¦F´pcÎ Fþq¼Ó ôù•‹¯÷å®hø)ÒpàÄŸ Ò9[ßås‚(ÞƒÛ ö¾ÞXiÞ䎂–Ãâ¹y±|=þdÎt؃7+ý2“lDXS=ŸƒJŒ–ña»µab aæ*Ø'$==”EeÌ­)_Ξ@•¹X½ƒºÊ}ºf8œž<Iý;ˆp<"÷4›Z÷É= D®E¯Å³ä**Ì9vÒ–çl=e1_Ô›n„€·W¤½pƒä”mkeЛAÂ`Û5lp5·ž!«ÿg¼Üuä<Ž(üû+ôýt$Ë0 Àr‰´ŒCðÛû;ÝÕcîü5«¥‘ËâßÝU§Î*$Vð+šY`¶H<)#›'ðª¸)~Zœ;
+Ú‚ÂóJJO¾ˆ©ƒ8Ø’A“ˆ|Eö3¬Û¬X‰qASŽš>0!0M|¢,ŸÆàx¼ÝögàÀ¨_¡žP¤‹aFvI[GáíÏB\صțx[°1ªžÙÄkÑÕýÉŠ®=~ý«
+ó U˜YšÞÊÆþZ!l¶ öŠædø­³Îq¡¬ÜÈŒ Éifß`œ9õï 9Iž)YÁ q3M³l´Ï¨sû3E;ŠØ£/FÃÎBpÞ% £Ùî¦äû’uT¥µà‡YýïTä[1l˜Ú¤ €ãQvïwÉÐGÂØ'±°±àÓ”{ôך"âg ÖmÙœ`Œà#m}ã™
+™µ©Õ‚Il##­c—@CX!õäBš¤0ö^N‹gDZeX Ðà…ø 9ÔÉfxóØÐ8hëÃÜ?”ØAƒò¾ó0nï.ïQã?é|×Ö8~l°SònN_?³/Z­pV«È«bÙVç{ßÜ"h«KoxcKûZ¸?¹cÜ_ñ9*ã%^Ï×µ=7ò ŒäD§Gµ- ïœÄ[¦¯’—É{j ÄöÊ”äúßÍ TÞ­Öéߦ®8ÈÊ!Þë£*þ>ÎA®kÃ>³,EÐP—á§D(2"¶6“À€eÒ«hPa; a)àx¥¢Ð}‰/Eïÿæa*€eŸ‘Ÿ7»ë‹M—:Q²¬&T»W{8ÇάþY`BÕjÃNe4û¼œ¦3¸ÑC§ sÀe o.§ÔäƆË,ðqÄå+ÂÕˆJóP6Æó<³ásd©%©Ê¨–A5>–·|²Ð<§wúohUàÛ„Ò:h€‘­-|¢¨8ž`w¹¬œÒbpÉtúx/¿SLj¿çóØ­žÓ3u¼›öek)íLD /岈°5 !ÆõªK¬’B“ Š¡=“ÇHmF9òØåÞ׺J:×pê8òˆíÅ™A‡ÑŽšrIY§8%먄Ëh, Ü[ž|'Ý2t>ÄMíÜFÓBY@kß%ìXagy/58¬Ì2¡ ­~ÛEP>ìQŽW7·* ‚ía›g-½‡{îóÒ@ï;cà2Q¨H½Ìmv.ã”#,Û\Î×Nz@…ì(­A—K-ö™
+©Ê÷ ¿|yñŠÚ-À¾R¢‚vA5 œóWÇÐ|¦†ÃŸnÈ0¨}sk€æcÌ šu‡ÜI)0NõDv Š¨ ¹¶Ìë5ïQ€ðÇO¿S‘¹Îv UQxìT=c—0·.õnÇ`1Jh>çnà¥ÆiÎD‰³&@žŸ­¹²ÒZw1.§æí3+sws7ŠÊhUˆÕwsnÞ± Üzmq! v ÅÓ'âêT*íu-`%]j)$ Ýws*BÀ¸6L’Žlõà%0ÃþÎ" 1j;. „ßmÜ ï¢nP‚À{9%ë(&R áõ¾†ßi<Byõ<66ãÂtµ4+Q’l¸­X/±)ˆâ±ËFˆSôŽêÞžEÚ
+h‰åŒIgóñŸ8ÆÁTéÆýæ­ J)ô¸µ$1›‚-@?ŠÍó|Îè¯ÞqŒÛC;­ Ï`žñ°ô,V|¼ðB0÷±={½
+{-EÍG6rÎàr“­Ÿî°"£Â?³¶„E™
+örЇ‰*ÚÊ]QYÑ(nê›iyãp·l% «‹3;·»“I*¸XY—YNt›¹ ?*§;ð}EFÚ3¸ór®È-95oŸÙ-­àÿBF~ t€i@8¯„FX ê·zÑZðåÊ_ÿF}| ë¿_þ‹Éý‘?þÊߣ,;Xî‘ñúÇkyý;!4#% rÌ+óÕÀ¶(~°t]N|‘‰BgX‘¤Tí€%àR¸ê?9÷/ú·û:Köo‰@qß|¿à7Jäz¿r³?^cÐ=^ùYçð8€QöSçùÚÁÞ » ‡H-KË
+é1pÇ ã³4
+õQ@D¿o
+6Næ½!—›’*TŠʢ§ˆ'`Nú¸r¯ŠÈ“ˆ#¿>]Ãa ™¡Ã”yáÙ«áˆ)ăÖî;c6 ¤-Ðú]’ð
+ìX%¸K‚QE<ê.)ØDbùí4Ôð¢nßÁ×”!~ÑÛ÷ Dˆèþ\N%¡÷ gTÁÖ*Á%ı:_7(x&•¿òŠV ÖW—«¹ž’¢T+¼U» óFG
+w+ö&Â&•é–tŽÊL.ÐŒ²ôS½ DMz rãX\ˆÔi%™Ááè¯ÔËÂZm•—¢q_Ü}ð&NLM2à5ÐçOÉL?‹€›â.º÷Pô?ÆË$¹Ž#¢'ðxFÍÃZ^ê(Ôý·~Y´ùûWۤÊ…® ‰¾~2£Ë6‚™]Ü
+×†Ò ì:RÃ/çåCQ—Zãïððãc—¤:ðýÚ•NŒTk"·]£…NèKÓJjŸü;ÅÑv×ðÕ+Æ•Tè-;—¶‘¨1˜ò„Ä´K0Õæ Bs— ˆ\µä°\%€2ËzÓ[â$òÔ²ùvQ,‹…mk¾ðËEn°cål+1Q’ôÇÍa°æƒÄËSXI7ÇvÛª’%Aklˈ€"¦æÆ+1½{ž7å%î^“ó3RP”•9ðÛlJõÅ›ß _€ÖÅŒWˆ§jà²g«Yƶ§”T©k‰ò¹ä…y|§{‘ˆçÎj3Úy-¾èð¼a šƺo%ËI’Ä„¿3ë¢ú=¯KqëJ²à³fR"V”ìRÝëàÛA|¸ôñ 
+6r–ƒNÕ')Q®Ëj%(MOëlB¬ÑOÃìI×!…]Â{2Ô˜óá·Ê Ÿ¼Ä˜{+°TÊŒûlÎ…8H!ö­I ’@…',Îïr¤‹’ÚC Ü(ÿ]à¶ÍOœä³p懚¯‡ I°›ŠÝ™†bÁ¾!¡¡[,cµ'#@åÆJ¢2!Tù¹ž˜y¯]®»8Á±2ø
+ç£3pÍ™¼7R¿@O„ÉòαwbåMÔÄz’}ýˆXH[}R&Ú°tt>¬­c
+ð/Κ•ãgEs4îUð,Óõ¶à{;ÏEÚÝ[…O†˜[­e7WŠ‘¡i¾N—ŒËzæäl§vá¦jÏÇ&™·BÈù…»ˆCRF0ÄÌÁZ{:EÀwwŸ?ÆŠWë³/ÓqÈ45äÿZ\~Õ‡ÔT±¸5T»¯lÛm&˜{é/¬aNX'λ›Mè2¸¶Ó¡äLO·¢ßEo¡åPCKÐ/€í
+)²Ðäì^ønÌÁ(¼pÕôdð¡ø†ß–Ïòhs
+ÜJ»cí7 Ó™°å¸Ä9žb pG'ƒ,I*OëÜ8C§iºÕXir3O‚®„’ëâüb§ùûмrØ{ÀŒÂvSæ+Ýšžåj§L~x*ah¦bU¡_»éa)-6¹mʹÕ|kîí|;·jòôÊ;}ØK¡ôÖÞF>R*0„_¿ÉÈ2æs?ñXvú
+°#ÈQöŽÏE³†Æ^&h¼*NÑ7’åZµFǧ䔷ì5½ŠÔ… Èó4o¶zdbÊCIãü°{¼ŒÌ­¡fâ9.í/ÃY
+³É [o™Ä¡òkvœ·¢qýú‰ÿ–EÅâ {Û[ÓÔYcUøã%Ô‡"†u ‰f>.Hø0£ä+§‹ÿ¯¹ÍÄïãf?*ºùϯ‡¢‰‰‡šI„B%®ä÷L  \ÆœÕJ
+r9˜—ë{¬XE´£ëyg=w?|ª¾0sÿÉ›Á
+ ;“Íö+}/1-V #óóã:LÛ”úõ1Ιõ­·ÿ:öë´ iƒ'Ý1‚pÈñ²qÚ½èÌ€ÓS99§ý:(
+€´´³¹Z Â
+‹y×ÍW ¤ˆ‰‹½å9(¢Y"—CÉ{J:ð>
+°µ²×Á 3®=mà<˜/ô|ì#Y¤Ë8y³ÞAÄŽõ@üšo*¤sÅ‘oxÞL.3Ê)iŸS€Õ#ωÒõe;­D®|š€7ÂW#ºÆWª)äÓËÖ1š ‡WÜËðoAÞ­: ù|²q-3”‡„²ââ²K¾Õ½ˆ»Èë²ÚŒvb<*/Ì-ÍûêÔ'®ì‰#K5~L—ÌÜÐð9üý`0€OÙ¦‚ç„hÂ`û½”†'äLqœ|ÍBZq‰xÞ³?Ú
+.Æ ¢ ÆúM^¾ÏJ%@ÁŸ0&×V¯E˜W‚"wdBšÝªkàk2‡ÂÉ™7N2\3+ïÅf…2-B
+©XÅ¿KH8H¶@àõ"D*’ûaijõn«çÆpÈ+n‚>-¨ è…_݆?¸!8I¹9rÂç]¥›w䫘Ð
+ññò$×Ê”‡Qqš8´•øò¢ÄÏ>eÌú"CŽ ƒÕ6ePJJkžšùb7q‘×n¥ïϪ[ª
+ú¶ Ú°Åé¶ç˜ÏW2dqû£BÝ]¶'ÊfÙƦ–¨Àè81ÌÜÏ1ÒïÙãÞ ¿ÛˆPsa)ú¥@ŠF§ (gH‹¸,Nq£ >æMÐP)üŽ'É£<Á.ÝŸ6ËCíMÄy_Òñ°Ž=R·x†ZŒWkÝßsæ{V¾<§Š”9 ϳôpÎô‡9®‚~oàU`³‡ÉH-²ës圂؉¼©ÒlTš=;]–Øo¾i&5 ó²,ºb¸Ç¶’CŠ‡Â
+¡6Žá‘]°†òÒÁášld³ ú·J¯œs’waA0ÊÅÞë<§tÌ —¹é]бÉv”PÓmƒ?‰2¥öµuÑïâXˆw ñ]ˆè“¨´ãjEâTdÜðuÄ"ÈÁÉä ü‚{biZZô®Æ÷ød‰§$°æh“Úùù-:M/€O.=Æ™¡Ám²¿¦òqR1”Hè3dPbÐðÀ³£
+'¼S„ Ðľ Õñ)¨ÞÕò¤ncœ XªÉË =°Kݶ±+€–uSzËåzêp ¬~š>UÓgýî8ÀäCH³:Å£9`Y¶ö a[`<J_ã a_÷ ”9|‡5¡dÆKá̸?‡ åÁø^ab/ƒ
+Jñb`o<{¤«ŠýÇà€”½4c¨.ŒÓe : H òI¾îÄ;_ŸZÐ;|ÝŸ+Ájð+¼öÉœ@qx“]Å_U—hç¸ÝhôµiÐÄ~ÕÊdnuÕ¤–o;2Îã*Žâ—…üo´® ðÓ_YßßœŒBQG-ÔN¸–¿’<6þJŽúË/ȤŸoþöÛÀ.)õó¬ÿ¾¥ÛŸÞ|qˆ‚Æ­m®r&ö#F·ñœÞ,3ìO7µq¿#¨w€E½Mº!k¤ø18…ÂôàUñ
+ø­zab˜:š‰Øh í/¼îϼn=q1Ÿá-Í÷ÎwÿJèÏ7ÇÃ</ñNO¹ýí;©Ö[‚ÓÊÒ©ó´9Z çѽÏi‘ï¤÷æºíwì‡÷Œ*¨ƒ¾«`Åî pD'!Ý
+ÝѺB¾Í“˜/€Ä«RžAŒvD“±‚ØJŸ/¤4—û÷×^þ a\€ª‚q½ð§õÒý¦
+ó_ß~ @P ) œÌ-Wefæ‹nˆÊ¯} Ó‡d´2ñ,Ù
+Ÿrã Q” elžcˆ]‘ßN¶]ÐA‘3¤\–-„-N²
+Þ30¤4‹ÈÛPíœgpA|E£ÅšðÛ€‚·<kºðãÿ0DBß¡î­ˆç´èjDíü!Hº¤Ë´°JkŸY.ô)’«=ÁŽï‘ÏZOüˆž:z=C$ßeñ¡Èš¶
+ˆåцÀÉM~­IØ…¬ÐuH6\“E„àš­ÇTg·p—ŽŽ…2ÔÄ!šæø!?öÉîDWëÒ˜½[&ž2Kë1p[¸ó"v.CAáÛÚû¡’0ð̲Ÿ4ˆim è|ÓKA ‰¡Ê¸ÐË â:Ü¡äh]|° ’¹Ehöb'±2ð:àWšÂ&0 ü¹4ƒ evšzœíýI^ˆj€»ÌË>¥„íÖ þÑ%ªß„XÓ]Å’wÉ}¸`G6þ«Z6 «œS)[|鶅ƒ×Uœò"ƒÙ÷xW°ÓH8irÞYtÎ>­\Á“éã•ÑÒú9…ž×9|nÁ£•«)<A „qC£„T
+Ôõà:CØI^«ì3„`”¬Ýi<EñŒlêbÓ=Òç­÷Åw’Þ©ìç9Èu™¥vÉšÖÄ=P¸v=®
+w
+ÜBr…Ž8©+ šUåÙ(n‚žhñó"Hv«³d/ž—‘ s,¸ `£>ž`’³cv6:j'ÎÖ¶‘ú]=õ‘ˆpgI˳†y ðÖúõÓ‰hNi>ëÓ¥k|±vzµ;çÐñs6'äì^uBà©6¬ ¼ yjÔÇ+3ó›%‡ÔÇ¢²Ø®TÝ&È;ç%LØûá9ð@¨Êb}¥¦ 
+‚ F·º¥2*¸SEm+©Œ¢žÕá¼ä¦2JªÐJ|Å-MQ‚8ŒÒ¸BON‰}*ê¼J,^%Num§›Ê(aX°/k?÷Ãï©ì,rRÙù±#•]W&kr
+à깞Þ
+ R˜T}ðW 9®±?sÄ‘ÊÎ:©ìÀÅÊNlÝS™‡¾#–ý+Ž?$ šÔU±ñùÉEg. /r+MƒzôsYÀIëŽÐÔæÂ3—bLžÂwÍËeju*Ø]תGQ)«Ï
+kQ
+² leÍî)`°ÃìòMußä3—yX¾ç²³Æ‰\AP´‰ÿ»öø[EN䢈¯C%´´?×°“H5µ×Ëô|v¯KOFqc™V僀˜DvUŸ’BݘîášèèhjÖÜs‹ÎîÀî`Áe¼¼XvÀôŒeÎFÜc™SrƲÛ¬Kwˆ
+
+-dÏí]Ãh¯Lb ÐD ÞÄ®f–ßNûœN¯äŽVÏ´M³pØø©'üüŸWƵy7Ÿb¿VQ„ôŠÞ?«¨i½áïe1¢"ä©ë­…=}];(ËaÏRÙÉCN'²Rµ­’:À{M);‡hªÚºzH‘†
+6Ç–JìQƱ#°ÙF11¤¨YÕÜzY±,å©Ý)±/ÕjOÂÍpBgu'½o¤;<-Ž¸J¤âbëw øÐvûTB¹.g7ÜLBEÝ⋲Q:0sò9ÿðÐNÇ!"
+t7ûÂÅQä¼
+iÊŒi‰\~¥!7Ÿè™Åñ`ãy\%&ò¼Î6Ù"Â~¹‰±>•dš`—< ÊUÔ‘–x÷\ #Âü»ŽJvNC q +UWI¶Qû÷fP˃•¸?•É ˜†b¹€"Ö
+þž²y«‚S*’ÒƒUÔ‚]ãÝ©¬(‡ ‘0Ýö%¬¶6c›òþ7c䊩›Uˆ,“KòÖ¼ÎA³X¨-ož¥@³HLqKn´cŸ:Š:C£Ÿ<²Ù§°ÒIµÌ½ê´A­Z¬Å…„èWHR<PШ@\ÛŸ¢å³w‰ñ
+¤È™ä¦÷ð¬-+üëk@ÜàÅ ÷¤%
+üöòÏv+ ˜Àå³U^…”?xs°‹›¸oÄ  ãqíÔgÍ—[UƔɊ{}¹: ¯Œc—öeYhÍ*ATžg*4šU‰0Ö’îç!‚—ë~6 œÐ'à5lÅÙä"÷b ÆÕÒpÆbufùQb°&°rˆÂˆþ9À†”
+zˆ‘™KÛúfŒ
+\ÒÄCh®NÑ—õ‡Û†é]%¬>ÛFߊ)L„©åi½+
+ü^Z|(Iâu2JGÝŸºi ì¨|çþ”@¯ Ò6™6쥼J˜-¨É¹ï’s“)`–áÜ7xIIJmÇäÁøhWñ ÿŒd>,ÐÇëRrÉ1x!ô·ÁCþ–/ÎRWQ˜òÚQþË5 þë=:šc%+ËóFÛÂ5ðVmÌé ú¦®ñ“ýO±_
+ p“åÜ:!ÙHt»çkæ^IfÂC( ïï/Ý‹BåIQ*”ìS§Oå«ídH¡¸¹aŸb7%ˆ![+‚  ç÷DEìm Ì,Ø+“§­É×*.‹W—µÑ³1âOEÓ$àVòDLE¿ŠŽ°rÔÔËè¡HÈ@Ýd
+u°Ä°òôý8%´ ü2¼G_„É´l_ªé!@¥´.
+p1û)"•Éãä?‘çH+,:P‚*¸’WäÑ…n3ézdæÑJ°;]˜äéöªÞq!\ÇÿÙ—ö:s%° Q¡6[wX Öâ×ÜFű„F²fá§Y0E
+éªSôå=ÑΕñÜ%KBmC&¦éà 嚣È{±hs¦ÉÕú£4ÛGéÏzÀ
+‡82$ßÛìÊ€iÈ×αå9‘…ŠvŸ³èïòúõ þ%Ê;¹%O«a©pyn7ü÷%Õg#C‘+Ñ„/ÂÐP¼´g’þCÑÇjüzøÜ7Šnô롈u
+¤»©÷ýX%I
+RÿCѹÎç¾QtãµnEÆ/]xù‹ôrÙ‘ä6¢èô?ÔZ‹ߥÑ^IcA€÷o¬ÖJôû>— V«2™ƒ2 -f¦$#nÜ, •›Åì)b“øÝÉ.§’ÀÑ —Ÿ˜)ì§ô X#µà‰1 V0 >ç,”É 3@¤{UQŽ%Š‰iYY¶•yÉ‹ÞF þ©ðQ`ÙÆ?J4?…«ä—Û=ÆHŠÐÿDȤf64¸‚g÷!N”èß`ÿaGõ.†àSγÕÆÏ3†j¾¿W›ÿ<*‹TdÝÃñ¢o˜M–oF< mÀµŽ@4uÐÙÄ ¼Ø,©â’0nŽ8DnV#­ˆë$>à€vÇIj¥¢¢}‡…䥘˜8K¸
+¿”{œÖñ\ªjXJŒÍã¨cQÅþâ©2aÄŽjð—+n9œñhM‹ÞÏÒ"6›¸,V„¸5*D·¬Q }…´—Ûe¸I¾«>æ› Ý.§q05EÃóAì‰Óº0G`&µñØúþ;Àe¡]Íçåç\ òw=š%‘¸›³vÔŽŠ¼˜øÀÄ‹¡B:§Î
+‚7)ûŸs
+Ë}W¾`›X
+ ngy(±“Ô«Pz¬ñê3¾×ZZqG¹–¥ÄTDPTìËUøª£Ål'Ë®6áà2¹˜—²Ö¶¶ò{Nõ}ÚÙÈvWù
+EƒOìOÙ]ä ˆÃ{ì /Á½
+
+Cö2>%ŠMõ2¬?ËÜšBhíiSô1‹ŠÜpߌ›¢QÂC*.$Oi¦‚tøõê•û(ÁŸµ*‚—š¾ÂaR~”M,¡ùgžïÊ07~XáÎâÉÀÔùžê€ù£Ï’Rè/E=¸( ôCBœØs±ý¦¨ÉçÒ
+ §0_¾)òЧ5pÛÝÀ¨óÜ ‚u~¸ÉÕ%&óímÓ?ŠRT{²½ÍÃ,Š]æºúœfiº ÿípñíð<Œ¸J9
+Ôw9ý9³î¥ho­máì¹ÈCÿl…¯’ŸX8{¾Ù¡Èp{kÔ°)½ô²m Ðx»<²ÔÞ¤\6JZQOaæª nHP7_vi3”QÂIY-œ³G!W˜‹ÿ2^îØ•¬HAÏA#Ђ¯­65‹çªçïö>ä+Ý$W]£ IQ Äçœõ!Ãì–Ep±í%H†*XWKàÏC]¨}À*ûÇáÊ "B‰IW:=ýuPýé¿SHPkø#’/ Z}„ieah™z÷Z÷³pü
+ùçþQ«ÅÕjØ4ˆ@¶
+j
+ñY·§ $ªàºtPnO—(*PÈØ&̓2ÊÄsé;Œöé8CA{T/–rúy#K³Ð`ægåÊü§8ÌëdÈ4¤¾ôÄ$ÖX‡ çy¯Aߧ £¹ 6Ø«Tãz2·§ [¬‹ÇQñÀ£ú»AÇ”ãóM4'=çí ›DŸòôVÐÜæ"ºSàž+/ey úy§v«Ä¦5„Ælld©>X†i"™ƒ~…Çt¾û
+¡÷ÔAìãâGñƸÁß©l`42ÍœwH&g­„÷ü¿Þ÷ëP£“7è(ƒ/ÄÍmˆ ,ñLþù«"òᘠ8¸{†Gêdz¥&ò3¥ mþŒðg§‰kSøJPéõŽ½±äáܚɳ–éshý#[@Žã÷§’Uy_'¥Ï^Ô#кÇTRB&û\0VyàxvWÛ¨lòSyˆøÕ_ÿ9z(d;t$àÝӸݎz3è×üFê5ä_è³È_@ÞBɆ_= ¨%uÚ\%bTçÍÖx™¸: ý^=„âQåVÆu"°æÑûØjËO…¯Zj¾Bk±ËaÁÕûdFšhÚÖW
+‹—¦ºBzIbihxD–œŠƒ`Ì`_ánðõªi¤¡hæNÄzú~ÒVYm1¯DD«Âx1–}!ÆÜNHÑœó¨­íâ¥[EEÃô¸FtxHAûY™ö3ã+;ÐkD>¸`m§ RkxŽ£d€6¤2Ÿ õ·z]Ø­P ?5$ãR–?fÙ;£óþž™¹kšÏ»*ÆE/¤ L>L‡WÌ©ìTÔÑG™ò±´äbÞ½dÕðǺ¥0a“d)Éë;ô;Þ™ôµB’1Ž¦–Š§J
+t²QòüÌ#¿þsRŠ°etvxÝoA‡F$˜«u6
+”"›XÙ¹±žbE½S¯^Œ"1Lül¶_ŽÄ‘Bé·Q~ÍlÓ{úØ 0DÚV³šõwz®ëþ²[,ãIaL ?~Eû)àT›ó.j&—®–³÷õGlrC/üIj¨ÉHÃ¥ÝL~$Éðn7k™'Ö¶’—>Ybʧq…`f¼;Š+' â§âãI¿ü¤ýíï[æÍ'4nÝî oñZƒ9$diwÅ-hy ½+
+’bƜݷðË
+dƒõºR¢;ÌzÚxa†ú—ÁHå¾›‚sÚ%ìå«!“ ?ýçµâ£L³inè\ þ°eK«)Z¯¡)ÜC¼)x ÊG•øô>!•„œI…£vU´¾Í˜“CÄdmÿlÅ¥ÊFÙ
+(IEÃ4QË|5ãi+¹8/r9˜¦OfUò†žº2QÝ»i"NÚ~׿¿¨è×DúDïb<ô€N÷¶`/¡•é%¶§ ­܆¤Mt"D¢cŒ¼íÄš† Y…‡D­Du¡—&J‘ 1+AÈ•œ¥YPÅàN
+©(œ>ƒÞ¡Q$Fëî
+¡D=º‡
+ñ¶AËë3Xé·µâ'Q“F…Ë ò+„NoÀ ò1')dùÊmuW’n²Ÿ…• z‚g9Âj‡"“táÂiZêbÆ$Q¤pžœOTàGu`š¬ÆaîçûA}JÖgH£24 RzÊJµÛjäSˆ^ÝÛ@‘Óõª[J YÚô+3R(XëN*Ó÷AËlZ €•ÊB¾Vùf £à´î.P‹E ­Ë?P+)ल¾ƒ°ƒ¬ðb;ÙÌ iò¿Ì·¦èœœHý‡çrLÎéìhšê K†ömJϬ/ÑÛ‚Fwë~ÿ?éånû(²À‚§Æ;PYM6ãï[ë®â&]°/Z†Ë­BB~¹Õ—O/ªzuúyªø&íE.¬ùüJ²iw.à÷Ñi¿‚.­Z²òwîã!$"i/$hsL%¢ry†ª”²GœÙ
+%ÃÐèpÆRõ ¶ Bc~CôÙsÛøqÒ þK¤Gey(ô%&Ì«IŽm“… (EÊš«I³e5­§OÄÇ.÷"oc+d:Ê¥[· $’;3 £_90•òeÏŸ”‹¦^> Ôš'ñ’êïD l±íÊ^.‹¹ª¿‰é«,k)[ŸÁ¤»9¸jéŒä˜ÍëÄMɆ»ô=Ç™rÙ“Àå`º{«Ÿ¼5š2Ÿ(`%0OÝÑ8Sæ°PFh”º$sÍàSEK¦käèU
+ ©Èyî®ÔA §…F;ˆŸ_\¯š!¨HþzE'ÑekIq~uŠ²Ž9ªý±;‚3L–ëÃW¢€“ÚåM
+lŽ5VÄdu«ëp9îWªYSèG6­ô¯¹ô!„lg®SŠµy líÌ’¨7=„mƒ‚€©#7fƒd c‰‡ Ÿ$ózŠW£€2~è£Þƒ|lzƬ£˜ˆÎö¡…0
+î³ÙùOÊ|Ê1Ë^hRf׬Â΂£§håƧjÞ
+ Žè<²&ç%BÆÌ@›¸ÁfÀ{Œ’ÓX È—Wü5æÐvtÍöð6†m ^ÖŸ²³2 EŽ`¯B‘}¦ÄÒf×4D­¼ÚÌzT HM‰×Üu$ª3½ ¿ü„óô–܈#Õ‡µ ~’ ¤¥ÄC´Ä
+:'ŽŽBXáZöÁ 
+ŸsX#ôŒÏÂ4™yF€<HYH"ø°n‚®µ> èÆë™}DVHæ>Ñç¹½ìÿ!Þ*-Ž´¶èmÝ$D_›hîÏ áƒŽ™KøÓdÒX8j9C*°V¥Ùþ\…>Aàg‘3
+Ë œÜKDGqÌÆ,
+H‰Ä—ÍŽ\¹ …Ÿ ß¡Ö¤ R”H-g5ã €ƒ
+ Ÿ ¯á­xócÀ.jéUÇA!ô<HX¡°MsìUÂnÈqSÜÍÕò$àÕ9½Áh[NˆQT¾‰ú˜÷j2J«åÌ»—Á´ñ‘Ù€ò`ïæmp.”þò¶¹,ÌYBÁºËºŒbŽfÐÜ×94©“hd.+uãÿÇP±d¥^ø³RQÚ¼?‡>4íµ2 4Ž ¢h¾ú‰Ñ9ŽiÂWBDsFôìgoaI™ZñxÎö¦EÇ¢N¡»èqi>!ÃJ0D³˜óÄ?íÆ]E­zÞô}&'éËIz‚,!m¤ZÌó< ®D‡l'é/ ¸Êä0H¾*ÀDÁBâ±ZæI&xiuBjçþÁ®")…z¡¤íAz†@ùªÖÖPO1à:YÅŽ0XC|B 㔊$1[OÀRùVô â$=ÔÕRJx{uLO™‡ˆÃeF ¼têÚ|B"gÉn½®¤ø’X…Îd 4Ù»—³£ð(5-§/ÿ”r†h¸p'V2Çç $wZOOIœVˆŒKªyјøÛ‡Öe&ÆÒÓ3€8 δ!éá3mÊ„M-Œ¥§´Ó2ÏaÒY?PÇC7oÄÿ™9ÕS7hBò“êô äœS&w$ÑhÎiÀIÚéÇ&Äp€FŽö ých‹YñR4„–>Æ1ÎJt°n‹œ³“ø)ð•HÉú­Ò0ê13Ãf0!š&ø”ÖWõJ¥*,ì “~hõÔ²Š‡V2?Pù½DÐG1b:rÍ}Írß™w’º<Ú ñíž7®&ô´Ü™"6UbšPºSŒa¯Î!AF‰•–¥ìk³ô¾Â&Q8io`:^ÝapM"&À±,
+nÏù¶@C–ÃCd×O –‚Iùf=¯ú–™:JüYY§|ìÈø+?Ž%í
+È*’i©B"Gëë½À¡C¨çr0&…ÙFßÄ'DàK Ã$Ú+;¸‚¨ºÅ%ωÉW‚îðÞ3 ЗU‚÷-ßoXÔE$%iö­psí#·° ©i;GE7MÞœåÁ¬e£ú1ª<Æpéó:£\H¬cœ `”Óêì„t ÄÂ7}ʲՓdAÝucЮþñ2Ù,·‚èèrÝ ó°4äU· eè½à]µ2 ÃïäeJù_WVw4D’¼SD\jšÖ¨¼VíbÝ^ƒ3”)«.åtÛUü>W}Iuõ~€Ñ!´h¹i°³¢¾ZJÖÉoŸÊÇ«h!~ÝÎDõú£jhüÁA@°.ÑÓãŦj‹­Qc¼ŠAH¾º‡¡ßÐÝêyú¹)QË߯b¼RNê2ßýž¦è0&¢J®ØNå`†y^ï>Û•(3.mYñ*Ú
+¸,Í„4åXæf¹Ã)“Â^bê_ÕíX'«+ríN"Öæ9…pÕ½ìÞ§è|²– BÊ{}R¾ß/:`JK¬ 
+>až¢Jv /O2£¦Ì¢‘ØìJˆ>g¬u¿gχ&%› ‘PI”¿ Ù.Ü4þͼˆ^Lñ˜5 •æ¦k|ÊÄžš ÷ §£ÿh¡MjÚ€R“w-£ìƧ­P<æz,qòO…¥.RS2bץȹ‚ÆDº`ˆ?»˜|3t²Ý¤´Œ9.Ö¢ œ¬g–¥ÂˆŒ>ÜmC\DjÀ8æ ÄnÊÞb¨üÕ9|¡Ç^[ÕÍ9à±Y|t…ýÕèßæ+ Ô1¡ b1D›ñ£ø^óßhS Ä(›k~‹KOZÜÌ«ÑÇröG[N÷ôýt,ç©Ûy2¾ãÈøVƒ4ñZdé+;R‘[B~Ö\áÿh¹&Ë2A¡[+;ôBù˜ÚX_Ø2a§ÚF~0²–dä9lyfv ²˜Ê"7q»w%ï-óÑ£ìŒ7-Š%‰bô÷é”Á÷ÈFq†ÐTð .Å¥£_c¹ ‹º±…f6&Ïè;Ý”—;—š²lrRœç°Áà™ÔMq¿¶l r–aqÅ#HvˆÙ„!lÔÃh@RÆS¾å½¸Åñ&gŠã=(1–bú™ÉVÖ:„嘖Ü24¹ 5u§ªÀ”ë9gÌmýþ„þ{Z2Ö&µ†âá’¬˜eü?õ¶î@(¡ Ø‹PSb]œŸÄ®¥ì Ða(Þ·×=:ºÏï ‚¢Õšì¼hCR´Ñ…ž—ybØç2­U&ËɈ%;Ú!—$_ ÖǼ
+:Gšw[| x¢¯ÒŠ­¿Ý{­I÷MébWi%#´áòlhÎhIZ Â<6×JJn›Rü¶«×¦ÑôœVd ‹[K"Ì­ùj ¯%©èa>V*:ò¨Î
+PBó+»Ý…±¡ì!—ܵŒ> íå¥&ÿí “s÷“‰çó?´›ÖEˆ\3·¶¨Œê©¸¡»‰B×2¼°êÍ¥d·Âä´ @Ûf‡’äZÓ¿Oƒ6x¾îIÐ)lgë2‚ᥙDVêØ5C:IŽÒÁl@Þ‘kùXÙß a¹ƒÍ3‹9Ãò§Êø¦ a`ÑR6›:…ˆ‡ dÂJ ˆb¹Ëjb‰dP\Ô‘Óæ9~Yì*™i=…@è „
+ô3b\ÆÈ=`Ç®Ni‘-.æ‹— ²êÒÆÁÛˆ
+^“ï³'ïëªÇä”á"`½5¯"<&H‘k¿ÉÛ: Ö‡rŸÏ95Íù5§æÛujâsrN£@ŠÙøz$­Hùr©·ûä±ÃiH-œ¹ûÇê¼9Þ*o=²%ŒãUGÐ÷'Þ3øâög!3æ>кqÚí’?.@Ò6òXäåo’ñãpn[†ŒŠt‡‡ãyB¤XHßvácÞTOÄwÖ±
+‰ê¹——cÑ“ƒñpѤ½$Ì)>Ýþ¯¤½ ßË.×$3çä"]rÒñéWºƒ'*üDHy™ ”r…°½¸zŒéTöHU&5´oÈ}:Úã]rÏX`’®}i^¥Œ—¶¾ž§N÷DÜ {æÇÅï –b~„¡õ5Nb9ŸCx)ýH9m! ZÓ|¢Í¼·bRˆà÷ÖmqÓkI!Ó×Uj@§E¨Û{8‘}µ0_Ö5 .ÞiHÏ
+-IÑÆ£) ‘£·Ó¬z¦–P5
+_VQ7ü$¾Àç ‚½’æ}<z@˜f»Üü„à¡©eàÞ’è]VÁïy@¬)¥2Hr«±îaJ1YF¦­sB§©ŸƒuÓ"1ö`ï•_O-ÿ½}ƒ§éþ`é£Ât{¡æ¥Z#Ãêôg‹måŠììOµwBÈ9V_eŸˆÌæÔùPb*g_äÁ`ÜF—Úk&Äž?,³šŒ2C+Á#X©hIÌ‘2móР足Üð[T™6­=†Ï0pa±j&¤ÜIÃVXçs´±Â7<s"PQ^“PŸ9œ)Ož™¦K÷
+ ­ÁRtŒ—ïY
+Àæ×
+®uí0\ éd:·[“F‡§ Qݼ_ËŽT°ÝîhÇh´†)¸8‡¶€«EBηýkNmqˆÊ®‚YluùX©Ãú%7bC>z%‡’y›bãìl*pbm]ÅÒ µ²ß}<CíR_þŽ|{‘"XÞt#t§ù /ÙÂ:³£/ÂÁ¿á”~½ùÛ?ùÌÀ„Aûd¢´Ûoéö.NYï…¼ǬŠ€y™§¦ˆ±1ŽŸVœN§ÿÄ¿„QOiØ(º6j¢#ìJR–¸<!0P–Ÿ¦%ˆnXat†"x{ùñý•øVâå<¿ÄSûñŒü_@½9BóÄ₹ýþíe\S=p²ƈ”»†(Å…Ûˆ¨D™J/þŸŽ.ô׸q÷já÷{0AÁíÍ“äß<¬†ö ‚O0W=ÇU'¥>Ì«ÉœŸ¾iŠü·çbÿ ÄÈ(C¢˜~ŒŠÕÓ}MîU!æÏë2Z_|Í
+ÚØà‰`”€¤`u š:Ê€²^¦=F2Õ 1X°qò.óéÂT‰ÙIÌáÅIŒ¡8¶WCøIk Æÿf¹Æ
+r‰PqF—6ű_A(ˆuGKÆs Q—mŸ@ÀˆM¼\ÜÜDYѤp
+µÎé„ØËñ—dýž¿Û9—6¨¹$H•`Ô궓ïðó
+yÚÅ×!S4ÞA žü=™Äh yK±ŸÌUwT… s ûÔŽå"²·^h†mþ¹Cr v(ÜSœkz.,ÚÜc~:g5 )Q¹c¶¤u˜¥yàÎÀä5%KWÕ£Êð=3|ðŽ-moG~±ÝÁ
+Yö½ÕX«¸HŽ¥óvLS2¦
+^û¾¬d V@Ò{‚`Õˆëk<îá XŠý8µ ŽAr.Ë)¼b4àz/™e¥ÀÏ%Zl“˜&o’>ßhÚjír@!¿¤ÑX
+í@v;b•o > Ò¯œ˜›õXãÝ Ææ…Ê7*nAŒ6Ì’²u
+Šæ]ŒíœûsÖ^AÕvMš‘%Œfà‹e‡p l3Å( ½Ž˜Là °Jî‡Ó*‰œL_†ÍKÔÄr&ºî‡®f(:!
+ Ç&m3mŸàÓ–r0Ü â(fDA4Ðq³·EP]6 Û¾n0âxš^‡±¸¸æ¯Ë2ah€h¥ism{jæ£WÝ“yhÿÆs‰La¤ópª-=/ÊÝ­,òŠhå>O6EÊIÃ\j¿³ßßXô×û8¼2£¯¿ü°tˆ',F!)ݵŠ•
+ê‘ãr7„ÐD1`ã@è (1T PÛMˆêTÓ˜=L ’P²lÄ}¸ÀµÁåÙž³FXõa/?t½¦1­awBì*nf:å Ήô¢‰wfŇFÄ×”"Í×Ò™,É.À"ñ½ jêÊDCÚ¬ñQ%„±ÀL7 ÄBü6C«û]Èl9´¿ÉÞ©†„c%ùO¿„ØÓ/%ôι4‚lðo¼¼ˆ©Ý†²h˜h\z+¦sÕ<Ìb)Ž] •Ì`ñxGó#&$“@75Ìßý„ãßGb´‰£¡ï<š¼í4í ÞÆT!Þ‹¡£Ð! g´"ع º}[5
+Ø"»UŒö€w¶!¨fyS?6äï„Ž’–i›¡·‚£_ ÚEçÅðS ‚Gö oï‰Ö#w–?_c«Ÿ dj) 2Öó
+j#´nñ2*RJ>÷Þzq 9<§uš$P=‚ÞÈè$×"ÏJ'i/h¬ÀØÑØ»T¢­c°Æ¸õÖ@çA‡¯‡6‘‘+²D¦ùpÐÞåw!>üÁè~
+=E ‰IÑ?P0¾˜¡9rV±6 ÜóÀÇ!R1ˆÎ&þ×à'¹¯ýW§g³ýQbF)ÛÞJ21´«éKéüRu¸-í›hó±QqqÞºA­šoÇ\&ïóñ´)f‚v¦}küòâÅPÍäÛ{†o!£u¡$•°(…Ï£ÂêŽ z&-Èi‡
+J5|2'R‚#B6p„R¡5,
+y€©ýëÜÌ—ŸìªW (ÍÛ•™o¸Ãè"õĉy>@0sX"ŽN!Ÿ£î t”JðÈ’?üÛ4¤šZ 6&?¼Js£iz9õûT0x<ع߄}«pQ l¥A ±v·Sˆté¸÷ËÜx·¹ÍŸ÷¨Û_‹sß– Ï>
+=ðÀ s[qï0,~q#ãŠüJ2¹(Z4,𫼸}ñü‚nGËT;<^
+ƒiËWöù„!ùŽT¡n„Øî„EÒpSËaÖCFŒšÛ Nì FMÀ ¯ÕÉË/&~¤\’¤Oy ÆHò×F%6×ÂoÐJn°§#‘qq
+%î°Aü°fŒe¤•PǶÝ=¦®%9~bTéÑ$©ì$¥v vRźftbË‘÷™Òèžo4{vç/¹'¥<» ·€ü›œ•AbŸ²HĶ9 Œìe-Jjm÷Ã:]!ÎjÏ’úwÔ˜´>ð°ÐDH=M³‹#ß•cJÍ΂)Õºž¢AX&´…D{ºG©ì¬œêŒ‘pûMû¿A,»r.|K1­*cT^[N?ñKØqÆWb9¹M0‹‹1l•¶á¤¹å®c1Øl¸¼ãá°XØTJÇ­:´ÿC{êã¸ó°ª8–ßžò¾‚¿Z.ÛÁˆ¡™f5>pG¤‹SÄÆt>qÇ sÏlÎaÐ߸Ѿ÷ K²Ø¡¬½ôÓ $, `8‘ôš
+J @w‹— æÖ”{¯«088ò[õãB`¬1â±*­ùyJÉ ªò 㴌¤Y
+î;1Žåw1^^p@—¼
+ø90BEù7ü1ÃtïùÌÎÄÝ´þ5o‡€~¹¡k‘?þ)(Ô¤-ˆR¥~ÆÅ€«™™mî J‘Ou^v
+²‚íï5%¦Ñ³™Tª`­á[v¢"ÿ‰‘Äw?ú+÷>økog—Ca³CÑè§ý¸ÆçÏÒ\>ÂRˆ6±ÌêŘu”ÖI?â9>}5EŠ%[~r¤ v–Ýžcá4zœ£¤-^eÊRÓ)³IÝßÁÔ)Á<ÂB!"BÓ¨is!|vRaè‘‚¥=ehñî2ÈÆóweg2[™9ÉÞ•ipJ2.°D©îÓ;~z2œý<ýRÂA áÇ
+ɇ Ñb-, ¯UF³#ÿŸ–83d´çÂIX÷ïDýÿ¤ ·¢\‰ƒæô¥”£î£ úl8"lµÌË4¬£êâ¹Å¥›Å)5„T÷wè""R2Í·#¾mD£AØ=ƒØ³Óúïß|ЧÖÿpAº ¼BvX†x_Ýá|É8Ä+3ÏÒáòíé2ÙÐ þL˜Ü¿LL=ælƒZ¦@3#ÖÅør)p“\nD¥•Öåðû5‚`ØÒ‚xøßa¸Ø@jÂp¿/“(:¿Ñ$1lƒ‹9D)¯@ËbÝGÑc(=P”šÍ³°j™Ñ§qì} çÙ%+ßz6‡Šåó"¿]å\qC礯×S›üÇ¿XæüçÛÿý)Ñ‹LE«¹f¿±1¢¸ãZVBpA¸zÇfÃ\ Ù†ÉrÆõAÔ螥½Ã M>iT}C¢0Bþ®¶MÔFƒS°ï0?0û„,š}‡Zc—
+ƾ„MŒ' 37-ç6ô¦DbGU5 0+Ë—¹ß”SP[îO·i®¬ñæ—‡Wipxsk‚[x“‚¬§þTãäS¯ì¨HC…žXèøáÝË!›%EÆÜW! a88µ¾ ø¹:U¨©¨–u©1~Zж–µeN¯.;êÒsï;—Éñns™@ÿU—IöªsÛ‡{¿Þ«ïÇ#:¯éA´Åñ‚fu¾($",m¯à Ä5‰£I³®# P¡Ö1šM"EYvª*Ò‚×Â;ÒŽzV’Qž
+aÚ^$e˜]Ä> Ô`uÎb( ÂÙJx9¯4§aUÜM“ñ6¤È%!œæ@ì(Ì -¥Ôóñ;X"yÆQã¹MÁ(H SYLJD‰G
+-ÛÃK@r“$¬Jè ߥAúTí¸Æû:ôˆ‚†Zíd4zÂ÷u´øM«ˆ°#Q–ƒu÷刽üRAï;—>p6S‘¯G·Ÿí¤œäƒí‘œ¹H/GŠ×ªíŒÎu#žJ^ ÙäuNÖßG}9Êo')¨"×ÄÝš7”é¢fÿ”ç™ú(Ån†S‚¦“\£ZžBæ²÷²!U®ŸK@Š²|53_d§ìæøjæ‰iöeäæ ¥Z?ø.‰8}Õ€Q
+@Ëù!±#ƒ×Å+’AðÄëymª¨­†íEx!‡¤¶ ¦; ?Ÿ@3Ä0óø=«``‚±Æ|.”åìÑÊz!5ˆ4ö&™ ÏÇsRb#\³AÍùÊî* ¦Nì0Ç8%Žr¡Aeû»üC}jÔ× ÿþ9‚“Òö:«a“Ѹ&2›gˆîþ¬n È„Vã„°˜¸â{ÃÜHЋ
+–õÉÒ†ñ;fZ±âÜrØY,¹¾Ö„ÎA¦ÛÛù ¢T ­ÌÍCdÉ? -\º·5FõiMj†xýð1×Ôm#gÄ~†š‹ T´)m²¤XÚfˆµKjÙšqÖg ý ÜGØx½oý,Þ,uI”§6~Ëï‚Äti(9>Ÿí¼
+“Ž‡H1æ~ô&ÅÄ6Ê6ö¶!3‘ jhÕOs׎mç(¸Š_h‘›¥¡—i²òA‹ÁÖœ#}Ú
+‡ˆyi8âˆA˜„Ä|Ìl»©ú%¶
+ÚKî`.Nħ‹ß±¿CÓ%–ÝcqaÏ)Å@+¯ü0~S€ÁPïfð|½¬MŠsVGŸRëÚ;_8ß>#BÁEÊý¼Ê…F¬PYQ„4¶»8!æ2ÓX·h2+\5Oßatà‰NûÒ1ðQ~SóžŒ /‡Nž c~¢|Ix3\Eä‘1”sø.?È‹##(Í üNÎ,m†»Ï %Î2ì––ñLFPf”A´£°|FÖe¼©}÷ WÃ,D¨0YõɵßíÃ×$º Ø¿¤|É’®žÇµ6°$2¹?]PzÅ:’ˆpÏé@é1h³â<þPÕš &*äÝŽû ÐçÐõ?ÆËÉ’ã¢'˜;Œ ¡,÷E¤ E¨<Z·Èûóy.ø•QœÀôxgeFx¸{|=`ÞÖÍ ©0Œ±ƒÑ«ñ>Hùœ²Í„àûÓ*» Lrȹ¾lð™NФ—TôUN`hó’|œ$ªl.›@"$gû}ßcg†ªðJsõ馢ÐíÜÌ©8q»ï/³[·P½Š»æØKXˆr’«%Ïq½œÊ–º·¸8ë'YFBÈã™ÙUÖÍæÙö‚vóœÊH† ò©õ)Â9OÛØô­zÁ¤*¥Õ6#tŒd}Š]7KöK^ÓN¦ÒQLÆ´Ñzå1¸ÚÔaÞĬÐêâïýõÃÂXd¯“‚¤Ø¶Ýø#Ð9€Æç>
+æd|HLA:\ŽñùfÁ9„§Îµö~eN¶šÆ•{yz‘‚²#…Þ·+%™»”ù¥¶M Si|ZAù¢@Ì!)íO ÀŠêÅu’ÙOû6Á3@öþéU¢`"çëǯWÝkÃW¸­'+oU˜M€î3™iJ Ñ©7È¢ÄÑñû9kî·1Øw¾ê$ñ½8Æ$h‹D~;ªS oõkåÅOï†l¯Ž¢šˆ ¤Ò
+Ž®ðòð¤xu˜Éñ©Z Á …x0*úê– ³Bî‚ðw½b¶Ó—â¥$b)µÓ
+qŠŒÞâz—­H"‰ l„/­0r9¯"Sþ%@3v í¤Ô]ŸŒ&‰¯óë]E&õX=à{ƒТ>Ñ‚¦“ñ±ËœwKïçè• í ]¹½ÆÐ΀žW¸=!<É#R¨þ‚f‡Üæ¿Ø4h^Õü7×9”ÉgLć4à«Šî¹LXÆ…Ðœ¾:•4¨˜ çOb «çaÔ×ÓBô1ˆÏeHÁà°#­ ˆwRGn½¦˜¿ƒ@Æ×µ]ãSÈ9ÚuöãÒ)ÅžK~ê×0a4…YèVS$4í¶Ý©;ŸàJ‹üÓ'Dc.ñ‡a«Î®é†DÁUÃc•Çqg¥ï\¢?Y*ÿ;ù*_z•b½p:[g}/Ï°Â+™Û*/P$„øì|´T^B$Ñ~ðšçw)dX,é¦í9¼K"±àÒ7:jÛ«þ.&Ï6dȳ»Îbúv¥;=j¨Åg`ìc:Ï“ 3m˳ 8;ƒÚœK LYûUŒ¶Ì;¾]<‹,Úf{“y ÜŽpHÛ÷x2€N’é>•-ÔURî dN™7@7™ˆH'´–újé¼ %gòAæ‹­ó匣¦ÃÒùÑ 2¦çr¥5ï‚ñ¼<MÈú”÷ŽU—lnë¸ÃÁžþ—{½ëü€;銽Ýë¦óƒƒ5°Oº-âï:/H-šùÒ^.ø®ó’"{KA³v
+$™´+Ìy°†X—㺚S+‰iZN½S%€ @iÿ‹Â¶ÙÊd±æF‰ó cOô¸ï‚ŽR ~¾ Š‰×‚“Æåü iŽ’Û÷§<¡‰c9ó«4ô(H,ää‚ò¢“umxÔ¬C
+'ý´ç‰¹©N\ãÂóK¿›Ìµ!F(2¡³¹í
+ÓyFýéLjWw×Ćæð„Ž­Ž‡{8ADËl;]4ÊØgÇž3?åµ¾ ÅQ£±ZŽçEÙ 9cžCv—, D ŠÂÛ¥›Áê€Àw—ZGþší4@¸¯ a#(p4í¨ëƾ ›Ùíì]ÌDÒšµ‚Í—G¤-ë{͘dDÑê®±‹ø;ýz¥zK¢ää4+Œ|"x¨YO¶}Í´l(Œm‹äK*x8GóB7¿·$ÏòC\hëbqB—\F‚ëÚI /J,v/EÉ]»qµí¬Ó=þê¾æî}^†pÈ«ˆYei×mê4ðìIJ}æm|o 5›˜]@ñÚ´ÑX¿ëUø*Ñó+Vá´ŒUY¹ŒÛÑ‹^Œvï7I+ëÆ^£šÓÊà~üi änžq*Õ¤Ìë-Ð"f¯¨´S©R
+*(mèi‡Ž–p^Ô÷«¹YSÌŽ{Ñ«Néœyð{ê’RuªÊ#O^÷ÿ=óÖúÇ¿ˆÈÿøÏ?þûƒ·Tå1Tt¨{vW õB©û÷ñ–1¼TÇ6úFÁH}8wűµ ç@z´ô'P½¯ˆ8âÅ:)SœEVÌD}­;ÁbIèÿ/“ô8n%_…'à‡yXËK¥yÿ­ÿ@&JV5ÊâÛøIŠ.
+¥#Ã*oÚЕÉô5k‰‹’Š4ÄÀ(Y…!í;|å j2ˆ”†VdeFƒˆ,!ÝÑ—üÝ!~´:dYg{ü«°t5-c$HìeHl§G$=TQ¡}áÅbÉeSƒ}9^þ‰‰Ö 6D¡Edl üB©
+@#['¸t'¤ ÚÊ wЂ@?lÐÄ;„WÉ 7îî%dÉi^¤D¶N$Æ¥¼ëƒMꔄ)ó–ŠQ‹Ü &̾ӵX„‡¾[*{À£ŒšC$]ìfÉ †¢ÀI»>„ ´Õ/¤uªêO>©Êغeågž—E’ ŸVñßA¯Ÿ¬Øò»:°²«Q_šv©®È‘Û‘]ù6Œv© –ñ
+•$ãwnD¾èì?3¸nDãŠSü8ïŠC€Xø«šá!þ•ø0u„ØÆ®·YGLi×¹Óq´ißépc‰:÷§ný×¥6aHÃð=Nð•C혬*#5÷€à‰UoEÊÈ»B™Œ‘?«Ëê#9¢èa~eQÞn,F¤ÊÒ9Ë'ñ»D½‡_GO¥jh²)Œ˜Ž˜ÃB°Ñ{kQ¶*‰éó‚=ã,nH[l>  B€äcµÖßAÇaCeL¬·UN6
+äM8“#+Á‡Ln ^©ú~ø”­gŠ!,6+ÈwðÝä;ˆÚFåæÄ×äK#b…•?6þÙ3&s×xÙÄ3¼P [Pœ>¡-x‹}âÙ{\ʽ2Aîš)œÚQ*¢œšÉÇ ”*S¢yŽ²ž‚0Ø03%Í>ñÒT ‚;’Ñ,¼f0r «~8òŒeÉ{Ýß@6&àllÝïÄñS¬&ã…—Jmƈ=EmA1½Îu´I'm”ÑDÌ3F2wÊûL¦'ø^Ét…VØÚíÒ´qEjèÁ–uyY‚”}ƒªÁÍÅ7+s.£ŒeêÅ ²iÜŽ»¤ÄO™g<M2ÇpúΔ¥bÏÊ‘EƒéIZÕ©°ÈÑ ·Ó!ú@•c`¿ö`0Õ’öQú~Ï$œ¥zÍ ÉŒ1 2yiò”K8–rš@XÕ”ÚPœk,h ö!\åCÈŠ‚JT6Á³˜p(®Þ(d?$yãDð
+ü•þ2;Á· Õë¨ÑÃE¹Èk²—ß 6–ag~r[uŽ‹wpLJ÷ l²ø»6$¨-²—Í ª1üÀã«K4œb[;*ú‚jZ³ï¤Vjp¢äA˜$8­µSyNjSqÑ‚î¦&Z¶s¸c€'cuý¾,=3 ‘&³AÁ”ï¬H´LpÁŒ@ïÔ Oçlx¢¨ïcæ}P^C'ò»P$ž5“AT£äÛ¬¿ï²ÐÁ,-GW"'-©íà ü D¤dŸâŠÎ^¤É-øg0¸W-ôÖ
+ Î OžG.ÐÒ?ê Df%¨2¿±r„j—üQt mQŽ½zü‘1Bs“Ñ:R@8£Õ1•}TãW?´gs?›€¤¹Lû¾/Éû¹!zWÖ5i_ +5•(Ê$­’"FOßi•5ç©D4¿ £…¿ӧ“‘f4çT|´WÑ–XÈ”ely…aIè"^ŽˆíT^JÓíI€Û`ØÖU:#R¨g×ÄRõË7T£%@¯P‘rã”+ûîVeC&4x;™žI‚HÁŽQ!P!Û—B™xÊŒ«ÆYQ_Źeãt“ íõf\™b6zœå[;oŸäEl±Äyþ“ÓDbX¼í–"s†±d%Œlî<¡Wa
+çâ‘X0’èì®.+»tâZvHY4¬0âµx5ënèlŒ"@(øü8Ý@¯ÙbfspRgVÉ
+ ÎVXDvœéÔøbXæ"D€`{úþŽÂ?öe)íbž£O¡"-Oäÿî7%-.KËçöQ°=ªÏÖ5§„TK˳ñ ö¶ Ra4{;0¾A ˆ56›œ°Ê±ÐªîmA4¤œH Ù¶ýÎ?&¹È2ŽÔl0þe¼L²ë¸a(º‚ìA+ø‡}3v†ÙE¦òþ§¹¿¥*TìAr *’ÀëàASÖ ªØx>Lêp^Š~ÛÀtQ;KÍ$Sê3pŸcœ(+U`€é-™ÚBÑ
+H¨ErcüK4¬ðȤÑ&þ;ÑΆYIJKh+¬MX‡•ðÆÁrÆ÷í¤ˆZžùè(Ñ,M ö
+'û:’N4¨§`Üì0£kM‹ù¸ìÚÛÀû»Çà5µ_c AŽÅ…Ç«`L_{òƒåmœ—;* |dÙjÐá@² Wgã êð (qç»VèU
+™QY½þ” Š+Ñ:
+I~ ŒËŠøî› ×I$Ÿ’ÉçTx+ºµ•Ðþrà?FÄ•¢É:£E¯†©8ó~Ò+|âð&9XÛ%(Fˆ æ[g†nND›”ôÐî¢ô†â“Çé¯$’õŠé “Èe°M¦ʆzàEÏ<¦Æ#IƒpÔnlHúwoÚvM÷—k_ñÍ;9 LÉ„ ¢'DöÝýÂïˆ?,¡v›Î¯8‰¤UŸJ` 0Š¸äÄ­]
+ùÓP ÙßDð÷ïàõ5Ü[ìd‹û¨Üï|Ÿ·s›+nÜW]ñwoÎÄN‡œ›Ô¿˜ WØäjø ÎÖ—W¹~ï§W¤$‚Ô
+H¡A<·E‚Lwjù}s-HüƒÞîÌMî@øpPØeãÐ^¨ŒÛ½ À›ü}IX KD6æTËÃw€3†‡Ç°ƒÑý6¬ ÀF‚ %><Š½!ÖIxNá,Yh%ñÇaƒÜŽ2)³Ÿ}®t‘@faÛ%'„9ä¿gRŠ”Mšlox+ú6ùχ"òbw­‘Ù‹˜Õº¢ !fGê`äsØË#Î ”D9)Ę̈ï&WÜmF²É iŠhH”5òMitÉ"ŽV^ÍîwRÖÂrxߦ°%öh\ÚvµàfKrünò®þì£À: J í‰+¥V…c“¡û´Ú–“rÕ:¹$ÛdûðywM¹¿'ç?¿L²¼Xº²vŽúd’NÑÕ$Ë«åJ ¹n-RŽIv b7/¬Çsî&YH b:oŠÝ5ÉúÒÞ×ä(^ªYÌ»))<xde†$9ͧï© «ÊÜ¢â˜d…¢€bm´gW“tjî&y-r$œë üßäZ®Ô—ö™P;w;ááÂ6;[=']m©¾@7÷heÝ1·k]“¼ŒÊùÌuÜÎe®°qu…ß½7W ; v`~÷Èßæ‹G¥WÆæQó“G^‹,ô„à‚ôÆ÷È‚†Â"l)¶ù`'ôb£¢kÃw¥²”Ëawo» ÞóÈú‚5Œš±ÕôôQé$ܶÌr¿Mã ‡‰#Ô‡75Ô¡`{gß"Û+ÁÖ_žäxµHJä$´–ΠnéÝ-Ò)ºZ$WcEY6Cß"y8.
+X:²3mXI›AÂÒ‹E´ÇâY8"÷AV´_Ì3 ø›ˆGxh04hB±a ×[|Ûß×; ‡åÎòƧï”&(c('âÓˆ‘úluÿ^Ï è´%•$w¤–÷1I§ x°ß·P<+ñ&µTìEø g’±ÑÊè#‚/Š26*®EîÀa~Èì.aÎ?-* ƒÒvÑíN—¢Ï?a¨™Y â1’í¶èiP
+ŠƒŸü´¢´ó9<5qAz´©ò±Jb
+
+§SaÈÉz!Οvrò>Ãã!Ü0W4Ù%,^)¯q¿ ±@’y;—ÜGvÚ
+µmD•’ïˆ5ªû"(TÉ;–‘©/è÷Wî4âùí» ì]o*4}Šp½÷"E–m`}\qhjx~Ö
+w›ù'1¯ÌÝÕîü16é^¼Â„ÈkœH›M ½$Z[$aäË%Xbû}‘ÿÂ<ø˜ÐFýWÅG"‘K¶µ8¤0"+çˆb'dd|WY EŸ 
+H‰”—On/7„Oà;øiHõ‡kgùn`Vöý·ùØ¢üž»ÕŽg€ §~-‰,VM¬×TKNC^sÏå°dÚ{i’úë_¥öcdÉuädVŠCôHÒS³>ŠÈ„Ôοi½}}{ÙÚ‘Z)œ–†y}96r«ü_ϪǑUGk­ÔyŸžGMZ³¦:!=§ZEµ›¥dk=÷äŸy”ÔÚjk9•§Ï$+£J6= –ùÏê˜9D³n©©T ˆií¥Ëèú' âwwÕx9gö‘¨cñQ3Ÿ®Ü¸LHQéÒ*Ë/I©…·þyÒdÔ²Râ2T_½üï%½þ=¡¥qQ)Ü\ã{#ñøaœ«¯ ‘\ü/ÅJÜ\•{h¥àQëÑähÉr™–«µÔÅ4JÝ
+7””GËm]ÚK)C *¦^j£´9ú¡’óÐl]'Dl<ÎJ´Ì/ÌjjD4¾éàjÜ°ÙÓgF³TÅ… “–Ò¨[Êó&J“5')4~OyþЭ$pL—ÑŽT³À×$VŠGÉÒäì”
+L¢ŠÌMïj߀¼„¥¨Zž“j]h<-ªŸC84A·óK|a”~Î| !3ʬÂâ8¬'c˜œŽy׊ "Z‘¨±r~ª¶ÿ ”NÞʳâí×±L6ñ0ËY&få1FW¤bñ‹ÁͤÎw÷Î 3~Mm¼î¸Þ¥à.a>:ûiðâѨs×1ß•O`ž˜)ÊDŒ¹6Ãú±õC¥\«¢ž'Y ´Îxw¡¾”¶TeÄ&„Ÿô¤´#>Ò)Ä 7O"ßV[*_¡»ù¸OJ”yÔâ4oQ »xEbnzÎ鶜åÉMÃS“‡ïd¤tÄYeo9ù`Òx/ãXê“åÜ@;Ëá¬!Œ[‡…²·¿±À…áÞ{Åíå;˹Up÷/]¸;ε•;ù1ân8ò] gƒ¸Îqø·á$;Ð¥Zhz¯ýÁpv ‹á
+ôá!Ú\ç$+ŸPX—ËÖwúÎn(®¾óŸÓõÛwO!
+óú0å”=ÁðGü}Ö†z•Ê›éª9ÜdRjiœªœP’SË„âpñÿØp4÷×=bLi1¬ŒƒnzàÁžñëó+ƒ±Ã6-‹6•šPG4J% ‚$oÔj÷Ÿ¾'ÁHèÇr[´¸.‘M{û5/îbÄ|ß“øí·ñŒóVÄP¼kÉÆŸ|‡[t µ5ÙÊCz…?‡&8Ky!ƒWtA²K¸ùFéßÑõf/»¥ÄÙ³Þc¯tÉGS9Km'b‹>´—ðÁ܇>+rB}*uÄÂé{+¢¸”t[’š‘|Â?./ºb4dp r˜‘%„ÿiÐW4‰Ñ_BhÎ%Íì{-cË`aFÖ9W ¡Pï[Öˆ¯ð4~WÝN7‰ä„PiØ#p'´’ :ðÂñÀÂGšºe®†’cÚGšú 13½†
+Üà?».=‰Ó°EòPÛ@žTé è×(¸Êp¼téb/"j#Tš-tû#"æ¾¥@Ç?¤µº
+V] ‹Sˆ#\kq¸"1˜:Ûæ
+ªôŠ Oqz¸íØA‹\Í‹Ä6ø?!(¢¯«Â„l qTnÆ\f*?}ç¢~œ©Urᢹù¶êš¾žôgÈÿœ–/òE¶Îç’ä.£À@, u¥ LD±Õ¯4 x'J1?6;IAp9Ÿ³;æýsíåëÕçÇðDÖ¢¼Ï#\Z]`€*ÌJ°ÿszýþK[ûMe˜•âá''<{•È§žbÐ-l[÷µ¹DØ¥þô…é|\ž£tˆN)!~¸~#w#\û´|O'›Ôí4ö©Cä‹î@S¯™|2%Å›ê7²{csˆ'á/²Ò×—º¸Žiÿ’»ä¢dŒ¹<­-¬ðp üë c¾½ì@Þ²YŒÉH$ 7'3ÐuW•Yecö`VfCÒ°öþ@ÁŠ‚‰K¬µ²üNÖ(<¯ëºÎ ôÅ\ßâÀ„ÓÔCˆ³$oäûc r[@}Q÷a9!ˆ[¢g°å&,5!Õ6UÏu‚9×¢’®`>ð0{vVi×ÛƒôŠ4TŸa*ÌPžß)î¯(¯–å}KâºluB|i^)He°DíihÿŠæ +iá
+i8³'2ĬOˆ$*5ЉZ6±òìÚ tÙÞ@ì2J=¼÷!¤«3¿…I‘}‚јթ/L?[ÊKáº?‹¨PÖÓ}×ôìÜj ™;2uõ‰¢ÊÞ”?Gþj·*ïìäÖ­Ýw.=ßÝæÂÝ«n¼WgC÷k7/½úç'cóëw.¨2â%ƒ
+J¢‰òtkRhFl”Öfj°²+©acê„8­\©”…„Åœ¸tobôäˎ鶩Š.F¿øíÍ`äº)h€c2£7×6$Ó$æh£¹B»Š6J¼ž'†«s„¡×0%¤„õ9fˆs„`X`I»)~bÛGËlñ¡Qé¤nWy)V”O‰Ö8,3:éMíâñ~ôºªÏŠÓn¤X®>cÞ.0ÇZž:¨¨#¼L]ŠAä*‘Žž•›ÏÕŠ •µÜžOVNص+ š>z‚4‡eˆX^ æ
+2SÛÀ‘3Mw³‘\»ç´t%³šG±
+Í—·¨þË&‹Ba0F¬ŠòºÓ'ÈR>0!öç@wä*î Bòh«ä¼U¼Ý ˆ¡cXe–†“ ¡þÖUt>«šR,OY 覓zõóœÂpÚ–ÉÎièºK n!tãÃzõWYdq
+7äQf&ù}Úè¬ò·1Nä¥]çÜÃ{)ðÉ;c› 7be+·«è>‚À˜?œÝÈ“`øYÔ˜Ì~±ÅH.k•íkÁ¹±šxëê ÀÚˆ.f£ïn{{¦¾jƒo~Å„ýüânU¤±ïjØÉ3é[yM4¾Õ¢æ›ÀûW7¾~û÷Å¿~ÏðwÖ86 £S£¸åŸ×ôúãTèsm¿^†Ã‰^SßÈ
+Ê8‚Q¤óñåîý‰w®çTÖ`žß³/Ÿü ô{ž÷/ûçÕ;½ãõ·Ÿ'ÅÁŽU²I÷”9)ní/É1Ü
+ÆÂÓx€ÜˆŸ +D;—±½y0lâù·Q²@=9I`7H(4Øáh®[DÿÅ©F³@ONmn¡‘þÄϲ´}ÕÁ=ÄOJÅ_Š¿°2ùeºÇ¯ÂÊÄ›}ŠŸüPìÑÉ×ñC·Ü•Ú=
+¦'}þ<—Oúøò¯ÿî÷—oþ¶x¶Sÿ|ùT~ì Å!_¢ÉoÙ x¤pG©‹Þ· ”¥Gq£¢Q"qD-Œ¼ê}xΧAÍ—DL(ëÒètÝ×Aº—
+?ÂîìÀ‘Ĉ>‰ÅcM¦$‘ƒê ‚ª
+’èÙ ØK¾‘eBèx\
+ÜΚ«µI?f-jm!Ž+ÿ•2\† ôJ˘2©I¶3 ñÄ1H±4!¤¾iä³ ì bWÑLlH1{qN‡áµ[(¡“˜ ”}±¨Kq|ð‡]½8G­Y­¼±­,7,Ö¬ƒ5@ðw@7Hg\(´.Í ˜’Sì’½˜K¡`xÁ¥3ÂOh"v*cQ/Naõ9m@öÝ
+i’f§n²„fá#µ»Ðäâ&Ãm t¹‚.b»ßtÄP"ÈuYc|Ý?&IEÖ$2AÑ„ä Üz¾çï˜
+ 9@PÍÙ9§CÉh)Ê{Ïß©TëŠSÉçlçøšMž£:÷ñ19›aÈ"p…“Ü{b¨>Üg/ŒÀàšo¿¯ÞñÈ„š\õÐÇhËÇ뎠·gÞd´fakDi¦¸;ë}‚°Uô ÆeP]ƒ¹á½óBwc7—<jl=½Æ®ÎFŽ•X̨8þ?;£ƒ¾ânÌ]«ÒÝ
+Û22Ȩ­–ˆBd7å¶?‡hU¥PÙÎÉŽu#ˆ'„=Æ{£”¯Q½Ó$TÖNë*œ`ŠKç.ÎÁ+eí~$áJáñ58%Ž”L³©wQá”RçîŽ<-ûsâMŠ¸wçb³À«Ë±¡P£Ý ¬˜ûiÌaÇ¥!VsCDÛ„GжÃÅ]™jÄH~Äu ©†&2a¸Ï‹;]–KšB-¡3b0€ŒN Q†mJR¹*ßÏȇ\‡4“šÉ2˜ÙÓ(×8Ÿ T eCбÌ_Ý}@ š›º…ØUŽ’£IÜŸãaD46"ùûkÙ%>LHë¼ WmZT•—’áœVT€àýL®Ú÷.½D9 !ÂçH–t¤®–àÀ/¶hÁ±ð>ži§0™‘?¤Lšg_AÛ’{åÇ“|f9> Òu$BªeoRPd»Öÿ(/“ä:r$ˆž@wÐ h˜‡5kÙ·ÐVºÿ¶Ÿ/ýÌÈ«ÚÚ¬È
+"02¹ØË‚âÀúÿ¾62HO vî¡ÏA—Æbê1íi^>ÀűMÛ̺ç`KáyVâì1,øó±¬ÿ&Bt 0h §r¶ËRØÏoN‘×þÇÀЛHú«E.ÑÿÁ7Ñ÷&=dÿX¼îõËŠ2Ú´œùè)*ZKîÔûp‰ž’iÊ‘\*£d6Yß”ã%"· û“és˜Õ?ÑNrÉø]‚–h×@¡A%=
+_©º4¯‚"­ƒDËÍߊ\q6îµTükN_-òhÞ+ºÐ¼J äÆȈ¸.Ñ rƒÑˆñlêé5ºXƒnz´ûé5Š&»A¨,ÅÝx~“`ø`x%ö)à¯Cæô‰C¸Ç Íõu™7¢W$I;Žž>ýJ‘7¡ÏÛf݈~å XÛët‰^%Ð&¡yjD+r‡ÞW{b üï‹5Í«¦'¬XÁÑ¥yJÂd?±Ùiú4aèÊüg¼¹Wòcs“ö3Àr/Ûw?'Œ£‰g‹/4/„O¸²ôâæoEn{*—fAø [ñÕ"æÿÊß‹æ¿ÿ£Ò siË°8+!.SeÜiS½S”á-½©—½¬”4x]‚¸Ü‰ü;™“þ&Œ]ÂLð؈ƺ•ÄxT䂳¦¥>Š¨çhžwŠðÔ8Ù8kîs ¶*©»OA„À’0Ì57R+•†Úœ’õ©/hRˆý2Èî9#…>é.ήœ8Þ4ÍJ0$¤ÉÐkÞ%QøLêþüæI­{D<ªh¼ì©9Eü{œCš²b(%½7:H*­Å_é‚€ÅB#;ö°L±ƒìðy:fªçŒ
+Ÿ8Sñ sŽçS+Fb¾{'Þå€áƒmÃûº(0DB×{•¼­l
+ÛŽ¤€.øÎvó}¯E¶›‰
+lT‹å 4ÉÙá^æyz²ØxìW’D†P˜–ãY`æ[¡±ÔN—ßf~ºŒâ±ÌïØ8–zh£§Íó /èÌóî)ÙÆ©ïT×+2èÝfLõä?šÐ®"]Ø)¾‚C96ùÏœiÂreÖZϨ OÖ®’ñð<®ÂÇÌtf†Y[…6ã
+ ®”Ìx´)
+#=¦3?ž³¼(r0VÂ#;X ëU×Q\/üéÍKr àó„Æ´cÖå@+tXƒyOÖ ÙÁgâìé°Umìy©ž¬« ¯“<0¤¾9hÒ)\(BŸ]o@¼?ÑŒx 9I–éÉÊÛM’Lç&Z ù-Vª5B¥ˆuQ47ìÙ„¦ ü‚Á†§ D–ÈpÆÍ9ºF£?”¼!ôó›Säb¤“ð Oÿ¡è¾Îç¾Ptáwµ®EÛ¾s+Þ^ÑÉÚ¬,ñ– iüâ±’r¨¬W¹ª¢¯r5Y ê&L#GÉJB+UjeJ éîÉvÒm£usÚ§ D\œ7#t$·É ‘ìS&ñbG´ö…Ò
+ æ
+ªCÞb;çÖâ,Ë7£\p{Õ[‰¡â6òû97à\oã
+t-’Óø¬x pµ=´ëÇCRÃÕ6nÙí>H-2hÝD*ˆÆ:š9³=’¯Ý¶õZbMfaXX&fÿæ@zÔ?¹ØmpDŒ’—-¾Ì³¦£±[Dƒè0$
+9QtC·gÁÃIîRâp¡µ‘
+n;¬&Jï¦ó““Š±ÚˆÝ‘"qFÛ}Pd ¬,¿5c¼AœÔé{§Ç¶®ðï4ÏO ''»òÅ©€È¬ ?ú0"¤?ŽüË—OÒÇ‹¿üÁGPAÐpžæòÏ%]~ZÓœZuæòAïÐÉq¬ˆöžb^g—ƒšÒô >h"J¥ ïÉØSÍ% ;7·„Žx§Ñs1á5sÁ[Üžç²Ê“g¿p¿Ÿ¹ß¾=/˜xê`ÜxÞüO¤/Ž«yîâ.sùò™Ó¦¢
+ Ë`nJhž Q9-Õ
+É×꧂¸70 [ðëþÔ!i\;j¦Ìß[™ëP´Ô%‹§!¡pèI•Q8“9ªOeË'ÏO†ˆxtö‚-2–fè Ñ19r„üÔWóJ!¬!“Ã"š%QÈè~LAaÆCEoÕ˜V¯¥ñ‘׌«ÄÀŠê[õZ… q{¶²ÖI‚}OZ«Û¡¿‘ì,ƒ¿iìØn±×¡0R bŽ%OIéD?b>%¸–úï+W.˜šòÜ
+Ä•!`˜´Æ•õÌ¡üéÉ­uSéý×]Õ
+=ɶònË¢¼Šb{!]†ñxu–DÁ€¾¹S%:—ÌuÀ•x„кisHHRÖÀ£7
+ùùÉé…
+Õý …ñdUZßéxDID‰Õ*I®‰t 'Ht ¬«­–z‡’H†'ƒ
+kX5P‘€æÍ›$)…‡2U“ªÙ¼%A\lú IBøL)iVuí„$-ÑIJÄi€‰2ÇÞ{’”Ä1UâUu€Ô=I"¡æá$R©ä’äfx¥: ÃÙÆÄ[’D2º¬Ù\; Öã ¿‘¤¤ä4þR8IÅžæ¡þæ\2tDˆÍ…mÖ· Éä&‹¯ž™¬œp$írX‘¿ÇÈ1ÿ1ˆTÂMŠ4wyÔX ihŽY¨ÓFUE<!HÝ™4qrÿÖN‘Âé(‰ëðp H ’\ÔLIÚ!¿³(eWÉ^U·×iä-†Äs–ìM‚D"h”ml›‹‰HXEÖ±š7  m¼„Jxöw HIà»FÖºtG…†w†ñ^Ñ?Z¢?‹“Ÿ‘•[rËrJûP«>áÇQu½ÃkÌÝâGÙvq¦“É}J Z ™UKí'üˆ¨¥¨× óÙ:”1!§Ë\%·ü(#¶ê­©ì!ðÈÃo3m‹/ÁäGe xqÒÌäÇ» ´øQy*P¿|±éúȈHÊÂÝ|³ññÎÙMó{è¡“kú5Eº¸ò:EL‰\ŽJoÕæ•DãÅ< ù~2ÖŒç¹$*,¹Ÿ™A&+›ð'Ûë”NÆ>Ô÷:2~Ž™®mëêç=%ÁÁ,Ñ æVMðûöÛ[‘ †™™šã©¤÷Š´å—<¾0¬¯'"6–¹BÎÊiÔ,^-6œ#oô)¡¹ãåIv´ Ü‚Ë"}¼ìGŒ-? fƒê±_+ä;Õ ø- ­›‰N#fÖâÉŒƒÙü6SƒñDô[}µ—IZ+xµW¦LEÖ„%vi+wsZ43Ó¾“fTº4…š÷Fš†
+Ô¶ëŸ8­ƒ¨ÊÂ& Z>\—äîbªäqOa%ÆQdÆ<á#Ø"’ky}OÓ0Ï&c$ôÞ­9œè úúž*ý­C‡#¸­E£©¼žˆ2æG b¥Ë”€œtnÊr³
+W @eJj#ç*F™·'ù P2Æò=œÀúÛñŸÿ«cñAÊÿÛ–eµXoš –ÑHÜN.’±(%xÉ׳u
+=œâ`0Ù,w0zùJ³¸ïÍ¢Ü4g·æΣF‰ÆOõΘ±—T©Äbfõ:±çÚUøcWÏñæf_ÐXç‡1œÑy2LÙ[áT…ešz­8KH;ž·i¡ò4rp¤x1rKfÈËñ5mpš!#[Nà¸{Ýéa"¿¼ |“@•ŽÉä…uô\ò@Ç8òz"âhÞE}r ¼ˆ}ŒœË?œ:,¬ƒ‹¬ËEµ\åLNF!®“gÍtÀªoWv¾m—„s®€oi'mŽìLðÞzÖ.ý …J›‰íl\Å5Ó&gZ^¢HSµþØN팷¬,À†ú+¨í½"Ó8Ù.sBd{,35OdúãmW¹óžÄ¯QcoEXÔäIj·DôÓ˜˜JxØy}ø¨‹ãÒ6¨#I#q”l£‹€9¬Õ^†´`âëIP¸v£g¯k¬´Hx„GÊ‚ÀÜú¹‘’k#ß5Äú1ÃÈu X¥ŸGUŠ‘êÝ êô²:þ‰D¯ˆ’KõºÕãºzk;¥ÑÃKÁÕ‹n;ýÅiT =ÅǯS¤©M¡¬ô^4$ääÞòUW#Iš Hø>«F=æ¨Äâg³
+×ðpæJSËAöu T ŒÙdfS‡‘Ɉr´Ëp»Z;Kv—ú b_ÂtF9Úôt—­Æö>.ƒ%|°žæ|~€êa:®ywkCr%!açØ&{ÔÎ`Öø
+&›®Ux‚\.¤#)mÄÑûwAú·Ã)¨°cQÃÁ6ƾˆŒuíP1mG±
+a½4šTˆ}jæÈŒð°KsÚ‡ _~Â…¬à'3sÔ7¤Ë &®cb$I›Ä¢ßjÿ ‚#ÐlÃ3PéÕ4D‹'ÏŸÒ=ûÏ¢µ(~ôgšW6 ƒ56$6¢ÆTwðhöt\ÓÌ}›
+¦z'iͤº³”Æ\ã?ÄOT@þÍÈ^®Z (× øì12‰Q^Í<A§º}>€hÚb†ë],s²®’…Aá*à%°.mA˜M§Ð—W$Š\ƒ?öÓ³òiÁZ-§2ÄZL%5.ö%ö
+‚A[Í&ê1ä ê+R ù÷‰θ(/€àmhØgìäRø ”ªÌ´#Å9À'èÓ†õÊFe‹äm‰˜¼ÙÔ÷ýrÀ¬ê¡¶:å ð¹¬i²D&Jzk«NÇ_E–±‹qî==UÐ,š«à»F:^ÐéçÝS&± ß²¥²û9P‡eœèO æ…`w¡ï R[ÌL,bµþï¤iŸ¢ Žµou ÎàýèPš[
+z±2×Öà°]5iA2<BËÊ´–v(*€1Êæ+Ìߌ—K’]¹ DWà=Ô
+$Áï¸=Ô.zZÚÿÔ'IàIzÅ+Ëa;Úe<^HäG+ŒPeVb•á¶âk ’݃JðÛÌ»ªõ`~A£ÚròlÆ
+-Ò$Ìèñ‡uv ãFñG¾yÃHR‡sî™wR•äÜ«£ó<a+ %½Aݸ¥ªl¦¶pŧhžH‚Ô5®éJ%ì[–Kô
+L'>y 4eÞ+X7
+“÷ÇàD}Sšî«î*÷äq)ú|("AÐ ]÷åeWÑ#Ì{\ q±"€ìAQ HH!ÆaÙW‹¡è‰±¢
+öZ*na£Ï® àjï%´UO‰\³ÉDY}Š›üm2mL%ãâ#¹êÆþ)òrßVO¡ðèôFNÙÌv+[
+,IîçÀ×@÷€Ëð
+®mŽÙ øòYA  › |ãSÈ"_«“;_7ââ3+"„\„Õ{ůfu;ÚÿêkFçL“+6áBÿ?N¿†5 Œñ ¬BÁðyÊ=b {Ë(Ø¥zJ@)S/†õ´~ªn;…m§Åv‘Å™#~ðÊ”icª‹9b ŠL¼
+ #ö ¸p Y ë(!T2_/íØÒ!Ë‘*Qq=ëÏC>ÒÁÇøÆCä¯QÒ|a2Ç„IDþËî4–x@®Nw< \‘ðæ©P0Õ‹ÙòSÁØA0.WK·ßß䃭Ç
+kƒøQmˆr;ƽ}Ì'nf…¯q”¥§’"Yâí€vðñ^$½MŠHëvF)zÇ¢® +áX‡k{Æ
+XQÚð—›à½V/C{Qó` ˆ 5zlá…•3†tŽŸ;(ƒ
+À­+@ºaN‚> 3yÎᶉñ›7ßj"VI=žÎ“£Ùaf¨×ïEJ²\Xr¶gß߈ã/kä{yŽ=ý¼×°ëf}ÐŽ\>œèŠUÙ9 ™ÄA箉:]B=&s¹G% œép]
+0‹}a¦.KÈ_•¿´âŸ™INNûù&\¬8fÖá&åI
+^ähvÚ^xÊ·9ǽÃO"ÉnÓP¼øœ¡pdiì&”WÃ
+Œ` zš‘¾¦sO„‚PvËåFïüDú‹&Û·¡¬‚À
+<ÉÍ2Æ"cùqJˆ4€ßƪÜÆΣý”l¯Ä†Á4ÞH‚›®¤ûïù³øÊCë)çŠÔË\SR¿áÂðsUVÐûÈ›Œu=
+X±Y@ äŽY/%ûSõ›œþ$¦õxÎ §hØ3œ
+6ª|9ãäÊŠ²@·yÎÁÔ…ýîäoi3ü4ï k‡L$$—‘£üíR:°˜%ÿçŒW}=7 3ãåŸR´ ƒF7êU2kƒäTî: ØhÐw)^é@ƒäQJX€.§Åó!€ó1FE”¡Í#6âͼÓÁ{I¨-Ãc¹éõÃ9ÌŠ˜¤Å¶Vï·ù‹·Wù§h„±P[A´
+º{ÕÆÆeõ M0§¤ã¡
+ÊÀ~D¯N‘aÝ«Š|†4©{ÁTק® v ÷¨’Y?иƒ»Å ªæ /ß 2"¤ž õ^vdBX’®sýSô·,ÃÓûœ=F?²?‚¸g&øi
+¨{yÍ3äf4Ç#J1`r
+µ;Åì7H|”ü
+;È£C×Ú÷!6Ö¨Õrb]¡ E¿Ñ¿,§íÒÀ®5µÙáuŸèM[?¿"À–5sãÚ”Œ÷zv¡Œâel»[L§›8©´¬îg­´’dø}Ad1é÷«çÎ7–€ŸçšM¯ŽÔ±RqyUO[÷s:œ‹¯#b½†õ’#»ÏSŸsä tŠ€à{Ò`V²ý*è”#O KŽ„²7üýØòv ’@"*C?ã!H‚SaPÞ;Ú1Hªp?a7E½'@ ˆ$Ü:bð$Õw¢Bdµ9žÎ©2_lF;l¾'I 7ãeåïZÑ>¸~—šÌ¼«óž$5ÍŸÂÂÅí3.Qò>ð'­¸‚Ž]¯Ì‚ ûÙžòæ 4è1œ@º¤hÑ­ÆíNÐçW6Õºb™²V<ä@” 5'5[h@ºÒ`Ö²GÀÖ±ÇÜ•
+
+ÅgP±¾yQai@j!šK-xq²¥²æþÔÕ2&:Ú¶æt€¬OåQ6ïWÎçäE°2oÛ9€Ò°'ÐKL!ö.iîû¤
+ŒáâÅüc´/@ôòK×ù.æ(ÛÛº2íReµrò ¯mñ;Àg†>B]¨Wɇ0N}2R˜hCÐæÔåž ŸÎ™¢wÔh q¦Lž}©R‡Ú‡ÌàK%âÁ‰àHLÙØœ
+Mön” “zn¢Ái1C])ÁßMã¸^nP­s5ç2ëìËð
+cu¥ƒÍjyZȤõŽ}ƒøÔ¬Gêþt
+ƒ¥S)ºtš$0&£ùÃ:‰=Ãùú›ˆ£i0±×¾t#Éދ¶é&Š5q€¶/KŒLÄ ÎÁ¤´IŽHXHÏ÷»Šá¯¯(¦„õ ßÿõŸoü—ßh¸..c}™‰.„Š S°CKcO ”‰}C@Ó
+‚À2¸šá Ÿv™¢Æ¢Ó¶‚,ŒIëÉÁPôȦEÍÆMÝ|ˆ¸Ieìº|È‚2­|éèM‘7å¹Qîâ™õ
+ñO!ö™,‹‡íOçTqQ §ÛÈ'¤°åøø¨¦×d@ŸJ#–џê{ƒ¼õié
+š0ÁêÖ÷§®—aC†¤Bõø&(·4TiÒ—ç^›AF¬º Ç%ÿÔ¥Â@ÖxjPb>vêñO]:~:ç27§Û\ÆïüªÛß«sÛ…{¿S?do¿ÿ©jèÐ…XÖZÐúƇ¯˜ô—`^쎼ñ8€¯ÈPqŠƒ`ë ⟪!?LúšÒ¦ü|Ž½Q
+ïÇ­hä\(?$i„èò' ÑTÆ)3S¤ó†ˆ<jbÏ'í(GhIs‰N3ïêG>~>€ˆp^gG1KŸâ¶*DÑîŒDã#ˆaÉ  ²OËExû$%„Ø 9ÍÊà’UŠ3yy ¤ˆÛL/O_1Ek™—ü¯2Ò(œ?¬<l.õMT>æøÔ«ß÷\ã^ãA*ÁÓK}®%"J#¶=LÛÐzä4 oÄd´ü-‰,^ò¾J&;Š¥OÓˆ…”™í³oºƒJbäçiØ9b>úˆà9gÒem"Äy„4<=Nö[ÄõãÛ¤*Ñz81™+9îÓÈ£ù<ƒÓŠ÷>È“bVä:íéq™§Tov˜üZ›óµAú\Ku ¡+Ãn„á+È®"ÙÓhŸ‚I[˃ì!ƒly,Ù8Ÿ#ä_T"t‡°þÄ ½zøÈCƒ'bDö›à)!÷ËV‡(2dfsös ¾Ü´o”ÌÎÏ gü³Ò ®×ŠCRìëp{ÓVù #¬T‹{ßo IiT.qؾ˜ãK ‘*wDú4•ŸGÝ)°?ÚÇ,V߉®°É–øŒóƒú”l“s&Óν™ðm
+cH)ib.·­yƒø§ ù(š¬u>Ck`'ÎêÂËvˆÍú¥@B l8‹±ý)‚àâ¯Ñ{†èsÛÔrR!(¥YÛ)ÿ&¨E¯_ÀyÇ!¤hKü Ò(‰¥…´½¥’W…¹ÛÉAl§lv´s=V@¡],GŽ¿³à?±éÒeÖêƒZð“žÌÄ_GRéo@Èv6ªÊ·ÜŠSÊÿD¯2ÂD³“a_ûg “0'œO?7hÑ#KP ÄÓñƒƒŸ¹ÔY?àÈÖB†àXYÚ²R,dVbmÓ?…lÐ ê*ùüeŸÂ‡²H‰PµÞ•aPRO%N?&Õ%–cbÄW z1Èda¬ÜC:@œšÃÄŒ–v>§AÎ…«L´;Dó_æf›¤ôÄ&ïOÁ}©ðW<l«
+::†çäÅi{„ü¢£Î=—o #·:RqÅav)V…&ÁqjPÈì†.S÷Žð
+CúxL¯qÆýº¸¨Q@¿/¼„ÍŠw> êÔrˆÆž}æ¯éGQÍdå¿Ž¹/Äác_
+%¹J5KïII·F гnyÅáÊÇjÄ]Lë âJ0•´7l,á Šk½ÞÁ=f¹£ßÿ,¾E ¶1]'
+H‰Œ—MÒœ· „O ;虂ÖÊÒ·pUVòý·yð’üi8å¸\þy…!A ÑÝ°¦ÞCÇ÷?¿©öÊfb1‡}ÿWËxé°a'è ™ª"Ísú\!’ü¯Î6³ï÷15s´Ì
+™¯ìæšÖÒÏUctx›½­ ÙldnXç˜ ®'ÎÇ
+qŽ•TÑóCHãÚIÆ­§«~ ¯Lo·®s_Õ-µMï}…LoÞLE¥Å
+Ý›(ζB|ŽÑ*jÆ<W…kÓ9©…­ ËÖZçæiOuì¥f½…Êp_!•Ió³éŠè9»§ñŠxøñí‰ ªåéÃÞcþ¸Æø+§y„öÙFÿþóCÐÌ1»èí;ãäGM$Æ
+Ó-FxøôBÉG§œ½ÇÊÃW:‘«8öÀ¤kŽ1÷9Þb´!ÒãÇ­kOï>t…tò=Eræ
+±™1FC»„ì«šÐítt~:Gefj¸ïcÜZ=
+høŽ Û€äywaœõ÷ÈЫhòU>É6(3Õë 8LÔ ÒVHhš8H¡B²óWt°Å¹?6Œ³ƒ}^äãôóCÐïí|Ã:Ï¢
+øß—Õ¸$‰¯”ç‹Qa “ÉX!ÁÈ
+4¨}ÔT¬p5] af;‚L é¾"dúG¯¡Y=Õ=Ê@vd&…Qç)kέJ6ÃÍÚü¿Q$hOOå·5N¡a[f‚aòÙ×U»j økÎ#Wd‘“â,A_;UðN%WÈ@xx¡1%ºBL˜D@G¬¨1² Pùv®RDAòÔ-ž\ÔF2±Ø‚uN /,à<}‹ÞàÅ°=4ž+DJ“•—ê‘+,²Qõv®"ÿ>™PTw1z ¬ê#ž”4
+-±þô­TŠ`¯¹Cè
+BY±pxå›
+ÝkÁeúfĉò4‹Ú6OàaUñŒZ$¸nivÃՈÂ~ ë|OÜV 8
+q"mõ‹¡ÑrH¸¿«†‚Áç®.í²¯Â.PK*9ïšú wvxÈÝ“ð%ùAcG™ ¶µ×’ø<WeÕ(Ë)àÿº€§£RÏáo9©ñ`}â¿ã
+BJœL+×+Bu€A‹áHå˜()ö„žó´“ƒz9´¬ï›¿Jï…Õrx¿rü; þ›þ2;‰²àûÂt9ÚQ~Ïï^b´±5B㺖Ò
+A
+p/¬‚s *EY²¶¡3?6.Å.{ëŸë*JcÂ5_k`­W³Ö9ýUð>m¼ O [!ø±ò½$Ü/!ÏU½6Eaq´ÏçX¥†%²ãHØ
+hŒÌ†—d‰,€îêªjm呤‘16áuÔwL~ÿ'läap·ÎßÔ÷óÂÞõ:´—Ö[ w’ûk¯D «âÇØB@Œ›ëÙYO:Ã’G1,nˆ]J¥mæSáàªǾXc´øÖtÞõè)€d³Îä§QjâWÈßAy°Š ©´ÛeÓ ^å a×›…ÕÖJ£úIGíó|½FüÒ Ú*º°1ÄiqQ
+ ú#¯7ÐéêÛq§«ÿîNóê©C'ÖR•+ƒ–²œÊÿ!äðj\ý"Ñ‘˜:[ID¢\¯C gAQš­r"
+ηilÝ¥D´š)ïô*@Ìã°ÎÎÕâ Ž °Oƒà£äx¤t˜ë Blä˜2 ÇuÔĪ¤v’z};߆5Sœ{ìéU„Kt\e½ZµEêc#ŸJ ùucå\ÝÜZõbGm-ß¿³g¿ÍFÀãî4¾—æ0 4‚êO"}€|™©_£G'Mµv4ºÏE6ö¢ëƒjì ¬—¡Â3¡÷ãi_1?¹‘i±±Q.Eg-‘›Yc´Ä¥uq­.ä_}~¸SÃs°˜H{ÀhË0ˆpäËSY!*pXxªÄâàù_4æz,”§ó $§‘þ秈’ô‡xeƒéIʱb7äyjŠÖv^9í S^ZIHe…n’“
+‚ªÐKÒnŠþ’’ ¬y”§_'Ý1è0V!¿¹òv¾Læ¿› d}zTa×lZÖVÖQ[m° Hïd÷vã­Â$ÆešfvêÔÈ8*¼:šOt+Èàù;áÅ¢ °jjçÛ
+v\T0»6y '<âüN¤BN<Rn$‘·’„fN*ª¥ bÙãY!{CdÉX3[4§=ˆ Ìûjà7,wJ@ˆƒ
+%Ú&DÉHÇü¥ ÉêªcªÕ†#²ÊÕò: 3¨|ªúdŸqìzXÍÈvRr¾h]a@`'Y¯ô£Ï)vÌJ‰ùqBÈ[ G"Gýsҹ݅Ñ8A‡â`Âü of(Ê„°™Z±!kæ·2aœ±Ä«í¤ reغ¼?Ú‰š< zo‚F ŽQ±p–/IŠH
+i(+Ìæ8ú}Tƒú æÂÇè›âLTA„ß)qæaÜ‚Þ ÿ¸¶3ú çGfxŲè§ÀÏ OßõTŒyˆ~Ý&OØÆ ?•š´’&„ œŠq tM¾`WÕê§'#LE19õ]{TÊÖMR+í†)miá¡.pŸ
+1Ä(Ô¼²C1*¿qé
+oYíþÖ¨«U0¯ÛÐtÞÑÚ0þ͸s¦xVØl(Ÿ_\ ?b” 'ôPEî2Ñ¥Hë š!¼òvÐ0A‡ƒ¸^K›Íx
+ËߘtT ÖG;\ûµe NZà@N¡ˆ­õé;h!"ä» UÇó0–‘D?²¼Å«–/I1ãÀÊšg7Щ8•ÝDïF@jú1( “ë]…¼Ûq êÄëO ßÏ W|ÁQ,¥†³ ü%|Îéb-ägÙk~ê¡«ïGÐÿ/—ä¼q
+¯À{È
+þ"Á÷8wè]djïz¿#‚Š-Qi§;UÝ ,’ÀÁyìîÄ%h´Çþã"² Ø0©œšŽûQ‘fÊ *¨Ó‹ä›Ûe„^Ÿ¦¢%/î$Ù<.ˆ„¿àAY¤åéQƒm9•é_êM˜¨òÔá”d‚BÕ]ÍÇ&çó‡Ùa“в±ñoŸ³ˆTÅbãâƒÉCo”ÁwìL-Œ‰n KyV²˜(Ýî›ôgÔ!A~¢ÇµØ×ݧ1ˆPcûkëh¡H/ÁC§ÖŠ¿¦e¯-â?òÜH"C–!•¹ß}x"fqÉ•0i—$;úú£~Zl#Ô¼}¸¬A4t¦G\Ε‹²”ÿ 48b›ð±– ×f–w}"ì
+Ê4/|]¿@-­cÙ÷6’m¢yt©)Ov4¼ ¬#u‹ô’ Ï:R‹.ŒžM‚—ûLN›²ø¥FÖö÷Û¾(˜Â]&9²îÛ"lIg6{¡ äW†©qqüãæ&:!Æ_Þù*©'òä‘è`Sªí!ÅE¯ÅjÔAiØÞ°Ýƹ3~Ú;/M;s8¡%úìk÷ ƒÏA˜ª:z”‘˜¸q¸rO!$È.ýys˜ã.eú¢7»†Â
+3ÇùeYȯ˜âÐ[8K¾/IÉ(—‰ùý¶[ßKч52 :SÖ(#Tºê8ßÍ]H(Zš%IŸ-x‹P%Ev—õ}Úgƒ…™"·è7X¯¡‹o.ôHCµ°c'·³¼”øQXh€•!Ê]ÑD Ç4pÓúº dC a?‡ïKÅg‘Òòç$¶
+ €ís\0Ø
+RR‹ÛÖ `phL&gþ`­Žq
+ª’e":NѾÌt™ °ÈÇh) °o@ÝWvÓÓª¨,y”@*ƒzáÓ7 rD±¡Ñ¥ ¾*Wßæþ@5(mêq~†Ù'éYh¾òœœÀLn!z šš¥á亯%ÇI…Èbx&þ3>|§¼ÚȘö?¯DÅ]]3lRRq£sLþlÚ ¯@‰É1t­Áñ¤ØtÙ‡Gáð0”dKÇ™r yn÷mݸ®ÌáÞ«UñŽ½3þ]žð3H)œîàþ™ï3
+¸ å¥áËéÞ Á»i]·¢ˆ÷k>á”w㞦@nJ¾†È??Áðû_Ú^º4=Ž>ôï†åó¡¦+bŒ@T4O7þüôß5ˆ¡‰"ÑfIÐ+ØS‹Ë¨Ç¤çµx΂l•e³ÖH
+‹….…0| òq´`o-+Á ˆ}Ú“C­°û,X}p¨eŽ‹.†•m!>…/y4{!hGõ…¨&f  t¡º0CŽaG>GÃ1,+ÝÚ3Ô®(
+xÄœþ°›žó¨-ïÇÀ$U‘`¨hE*¤´Y!+Á¯PG°¨ø¹å@DÆétåäº
+ÔĨõ=[”/Eêæ&o*ü$y–€Íž>ÓáJ@@˜ôyMØ€¬Û½d䪬™F_Ïβèè Ðx+ºhñÇÛî0°“8:Ò< BG”ðåA!ù2—K,D·]‰?»±z¸ænOßA&à'úœÆÒý!“Žó²êóLÈËa^=U$ÐÌ~vìÛ`‘h°IÝ-:y¡’#^È¿ÓøÕYµa~›¦xÂ|•Ž~íñw‡ü
+U…Ä_+Ÿm ¾Çx»@€Lê€co—Š÷îç—÷kŒq:è;cùQî(Ù|ߙڜZË;S”–û Ž¯¶ò¦ŒßdþŠ9š²D_-Ö†Œ€EJ§ë‹h¦è®Àor£¾¿RÇ7&mwç´)òï-[X¤I$‰ÎîZ™aĨŸ-I¶&mÈÊó*t ¹Æa¯Ò(|¡•}›dÅæØNý¦Ä¹êKC‚6Tîã—yy½hþþÏ?^Óò:€N¡ÈiÎx‡kÐÛø}þfFm”ǃ}¢ËMõ³oΈ±§3R{”/As"»Y³öˆ¶Ó1»@
+Ïu¹[‡à|&C·C"ùÁ›m/Gü‰pÁ¬ÓFòɬ8¤µVE…°!±a³«ÔX8·P‘•M×#r
+½„¬«:ÓN.ðFº?§ó©öÃ=ïÙt•UÅÌõ»WõGktpyéäW§‹èL=Ÿb èXØcÜz•” È$ãçUïA\Ù%£„éÃË&0pU­™at÷QaŠKì\ùÜôVœÀÕ|{‚}Š^‰ AúШܟõ{kÕ[ÈAÅk˯ç\€sÍæ@ïU _ŠãŒŒ\ʉ…Ï7/Cõç9{ £ åÆÓ€¯ƒP)²ñŽ.AÎp¹Í#ÿÈhqÆÚ+†²Í¥ÑÙ¿nbTZ
+K¹†ä”…†áhOÈ€$…hÌŸ…À—$+og]è4ìñÖã
+_ãGÿú>fdÀ$¯oÇd-lXÚ<ÒЯ°²Ã8!릆Ig.;šWÊÝ98]ÒFÛû(3ÄQJAÛ!ÔG³7Å츱?ÿøA/nìÓ Â%`H‰kÈe´|NébŠ&ºtÝÕÀv‡ œŒŠB8°UH,ööô<Á‹6èâÐ{aÕîÂ8 Œ{¥Å&ݤƣ€Eò«übý|ëÖõœ÷–_“¹ Ç{Ô×â\p|-±õ—Výû‹™Ñt…=]å–"Lç¸/7(=X@3…c½©K1ʃëc=™¿ÛÖÇ)áñé§Ha1 D}æͦÓ,bѦk¯¯wlº@FÓõ«ßî/<ÃÏÞ¿fÓP# õŽ|÷ªþ€Ô*r@'V‘7€Ì€ –†dþ°aY/¡Éhj
+Ù«âøÚd½ÒU¬f”,ïQv‚¾·þó&¦÷_.“ö]ÊÆ°“1”ü]Ç”ËéÙË9ƒM ´Õ53l²•Ýfž"óꥎã=ã6Ú¯îs@RcßàþvëñåKÈaæW\\Ï]t Œs™'›ŽMf2ëh;„¥¬Ó:Î>@ùpG¬¸çª"Ðd)ÇŒK•t÷3€†§æZz1½J ôÉ}þìA­SŠ„2í›þk>¿ ¥¸%küÞ<å¥ñö¯‡•URžTŒoG–±0>|¶À¥;àm%u§“M±aʆÄ0¢òYðÉ°(ÖÅAuøH
+£áó€‚ÂHB×rÞéY$ü?RÁ„·~ÄÔ·‰ßšÓŠMgæéw_r2 Si‡/¸“®üà÷à¬ÔGº;G¼‡ž!Uˆö0ïâb>–9Ùéö5óáQØWÖ¼wfçïf)yà&ˆ´üë oÁà:Œ+î"ŽƒTÆ‚Å
+ÇaW›Ã®O&;c¼QʨÑ}¾\\záÉNQ ÒZ’˜Žð:
+‡†Y*™]µB!2PQ6A&5Ù™¼N*Ôãs6ˆA§Ùí¢åõLW¢(F`¼QX`ØnBT=D ¢;禟gëÿ²SæCÖ¡iMiÝ1Ð_;ˆÙBx‡„ÆuÙ„Ðq䇈`5¡ ­Ç’ªZŒ Îc2û\­Ç0®Ì‰¡è]y?y¨€%1‰ç}L amùØÙ %¾Éìî@µVYÓOqŽ—2Ä=Û©{`äõ{ ú{D·È­ ¨døiA@|J’eT¥"T‚"-C¬‘Ø;FˆVæe(ª;-$2ßq©ªSå€cänàž"‡eû¢|çz:Ìߦ–—»FýÜð?OŠVh퓺G:ä̆a[¬ZGºíÐê˜Ì1evN+ sŒ.`2б尵–ì"¨Ù”/_Ð,°]úuØ)ìG¨! Øây".m.bÑ==d ĺÜ‹àSY]ØÜ‹Q:V6Z¿Æ\1¨tsÁ}@†gix]©áyxŒg»[>„e3€!{‚»Ä¨,f† 'WO®]÷t xàŒâ_—îlÒ~ÒɆEua¶sÜ!…¯ãÇ1¦G—h¼pkO ·ZjÐÊ9ŒPR„@X{qëyƒÚàA°aÓŠS9¿„e ÝB¤I,z·Q9A¯ŽÄã‹ßÅ ì\@تåu±bGíÂì6 ü±D Z>Ì«V3îšF_‹têÄäõ³½q,³¢×\ÈÓÃT”Ð&F*BÁÀi0.¨uÌÀ”LmUJòIÌú(‡ ðÙE´'Ä®šyÑ ípÏYЙr]A³h6>†·pºÅðÒÜÌ´Ù)Y‚
+ÕìÍëA°?qíl“
+ÄaN{z#iˆ£ÉqâP‰ P™‡Úq\Ä0îg=Aç!2\à\ݺR»G€?©8wñì‡Øð¾§ÝÇ´–Âì`°¿,†eŽ9©ñÈŸŠLñû¹nZèX°–J$ É0ñ,3îDí =9«é}3ò
+Σ ikNùÖ0™ÍPZÔ*;£…àl±©cÊpýû ~3_ˆÍe´êá— mÂeÆj€­øvhØôP ²$œY‚mEþ2ú±ìœkâ&ø¦ígšY6 i£©*+Ï`B0%1 þŠÀW­µGÈQn¾ÖfH |§ñ5&xZÈ@×I%<¹ƒš¨ëY/Xˆu‚Äe$MãöŽJñâig3} ú´r6'O/h…dJ
+ò¡¦N!.rEëI’RUy÷5kÿ€–¦ ÛO}e6ÃL‰ìª¢ƒS‚ó¶i©v ±ËÙÜ!x2ùŒ®Ýë&d¤,‚æÃ’ÏU—  ÓEd°ŸŽ†Eɹ=!•
+önœ-Nœ‘;†ïE ì¦Ä
+Bv(ÀàªnõÃã ¦vž¥ôŠÀüÍ·•`{Ñ¡¡/ B¹‘ÌÌì»Ë«B
+dV
+´Ú2~`̺r{ŒöŠ¦ößç&>ÅÄK²!CQ¼?¼á" ÉãN Úz<k…¯fÙÎx‹ÜÄkw9¬:;
+)… +«•ž¾s# ݦëULO0¼”¨'üi¯B”‹"}}¿êFb€XV¬:
+SQ\­€(rax&æ´<@*É—–2`˜ý¯¶5ÊšEôä>@÷†óΕ hÈ'ÖYm‹yh‰LâÛABvÌ.FaŒ½Z—hW
+˜Ì°Ñ8&š.¾ƒ2@ȺY1âJ“â ‡ût%Nü
+¾¼ÉànhpW”~Tó5Œ²Ô‡å¶n
+õŠZ|uXψ1ËïÈS¸ßÛÑï‘aéa¹êßY@[Ò(Ð$ØmØÐܯõÛÚÖ^pU` mL•oYú™Öw”‚4©mÇŒ=^—SS€`6y'pƱã*Újø6E9ÈMš’–Bëá­µƒ"_ÊîÓˆUZRMlŠd%à p³A:‹†í¬&ü, Ê_Éb(Ÿ]çÀüSd?>£Ä­P¥ùF´¶•ˆkxö¼¤šz%hB9ö›Ú§šZ|ñ?c;18bå>|áÓ¸ÁáIÜŸ4¾ uúÍT¤!Ž¯¤ÎbhFÝoª2ñÐû‚„ÆnFh¹[mx2CÚ'\Ø,ôìÝŠ¬¬læ¯Ï„ÉßË[ƒ}UÎlVtIìÉW§Z–ÍÎ68È S2MxñÉT´Oƒ8ŽE„2È›Å×âÚ}b#9¿­ÄE™EÛ
+,{”ïvO"ß”[lÍ|[“d"5½ñá;R:1;³¶ Q~2Ø\|OÉD*³ì.ïâ†\yÕð
+¸yÛ;ƒÚæ®±ü2nFl㓲œbÔʪ1΃¤Ô~8¬›añøò0>çXœßa¸¥ØÕ:Ò¾MÇVÀ„ìŠ )wAÜHv›u1ÕCò µí£’ØÛM»˜ìpÓãm,> ×n¹Q~E(°5¶ Çâ]‰áB˜ö9¿^Îe>sS¦…‰ˆ Ë]rÚà~`ÈmípgÀ[²cØÉäv@˜v¢Ë7<ÚkÂ-‹_®Ç)<5Ú‡‘Ü~(d9ÒÈX Ú®,ÀûâU#®Í?2‚l[^í„2C…l¤q:¾‡@U„ «l)ôfE"/zGäÂŒTggdÂ2k@rÇx““f·ó•Jˈ0Å.#sŽ?Õ‡±£XìIQüÇïP^*ˆ³ˆû6pdDÊ1‚×mÈvü¤`’g·G©Ç•@Ãú/Çë¦LödŽ~tB&]×¨êŸ JFÖ l:TÕ´êƒÏ)g¾#ÃÒ (vƒ`‚BLp|·~Væ0iÛÆ.1)—5kh¸"Ž…oë3l3C }î†Ê í_
+vÞVÇór£ŒÉÕ0Ä|8/šÓ`ÀÁhMBºm“D$Û@
+ê®öæ» }‹VÅ n™A@ûXíU¼Ciø™Y“ðRô„Of³ÙÒ,ð4í\ìd)+f×ê;X]6a迺™yÒ0òãB ä"Nêä: zgd´V!Ž§ïx›áGì.11R¦¤¼Š(qšÁÞ„¤@}Q&¶­‘„d03³íËbÆ"¿±—õ<k¨éSÜ5ŠÝFÎ ¿‘v‰Ñ¼£”nAðY8ÌߨÄ.‹;±%£ÿ;J‘)öÀ—l ÏŠK,o éÂ{) BÊz¹:Gwq2$³»‡>È_‹ÛqŸ9 õ·ûlkŸ”E´†ançq®}D5klø°\¢û-Ärà¦IÉ tw}|æNºúŸÿ%üçüù7¿“¥,+C§ÁŠáÕs`“›T¹^¯
+}È%oHm¼•¿µ´ MgMÊVMõ2ôµËl Äx3”
+OÓŸ°M$‰á‚À7RR¥5;ŠÌFÃÍÙI¸ì&]Ÿs9] MB©K/o5"öKXiÛEg€:5ÖT–e?åX2lÙ:ª_é‰Ù¸ÖS
+sgæ4¥®¿KOÓûá(ŒxÉ0†×Ö¤ܱ]'7e<?ÚI4 Âw±44g™¥N*a_žJNhóN—ÃÁ#-Û_]1¡§€h• 3ä%ú.qÂ.àîùÏìnÕ˜Q]Âé}‡u¤Z
+«qr§öoŸáÿå5;ɃQæªÛ. šÕ÷·nª¤‡\;„–GvµMÚsÙѾeô®‘Á¸JTbºZ „Y*$*æ»´â)¿º;ˆã6§9^åø™³:‡/:k|¸«³WŽKTÐn³Ïüô6‰™Ô¾û&M²g–bÆ'“ö‚$:랟Š“ ~ýê¡ÄÄkÕ äµüvopn¯òðVo.±· ¿Þª¯{ùŽ8=’˜/kmî"¯×c90OR"ãf\">CÀ"®’?SÖÐÇgîd¼Ñ53™'¶¾U¹JÞ1)M2óÝqÍ #b8£¬[a rn(uGmþ¨1°ô–ç´AÇq¿Å+¬áüSËH~<€4 B’{ù² Øb¢iĉã 6€j.ˆîÜË €{$‰ öЬ®yôÊË$=Ž\Â'è;èõqÖê¥oá­|ÿmÿA‚å.&S.?o^K“1èiò~uÅRF' aÚ(Iš@dÄaq"ö‚iãî†u¦$§À—°ÅÁJìS(± <´‹f‰šŒõÄàXIc#^Rû8Œb¿ðçi^ƒc2 “”\[].¾8I¤3re½i aÙ³\ asÃb<±${­5QÔž¬ù»À^= bcŠ?ŸÁܱjÕMåÖ]Y‘Œ'`]Ç=
+tÓåÐs±
+jǵ`"ºqTyÈ]²Pü|ɲ×:ñ‹y n·cS¢Hø‚“(å¦äžŸÿŠŽ@/<¾Q0òñ/Š®ËwøÜE!÷j/2rIÌ ªÊÙÕÅlˆ1*j¼˜U©Oyb&"ˆ’Ÿ6¥˜†üdÙQübÔÀíâL]y>¯³$ttÙ}àP2F›ÉZ¥ÉYº|sNyàöùš•`"=y`ÍÝ*Ò>ŠŽûzˆ·6Ú×¢}q~ÌûPR»#Ü´önŸ“„×Y)BÈ×M‘² $fƒ”g T¼ŸSb#| —Öì”T‹B†Yh=вÙaõj"­¢´«Ñ• ûÅV¥y‚Qb]Zµ±×˜ùr”ŽÏòFÂ;¸Ú¡Ä>…Rµ ìô„ÏvN⴬Ɣš•ÀŽ^ü¬Ð̽ŽK«¢{P‰òóÜù%0dÍ!—ô „­$Æôužl °ÐújŸ×AÓ­bC;ñ‚L‚íd’EÓ½è8òxðHR òv‘ÿì Cu)¯¢íN[Ñ×;k:¶ùã_•z”&a˜ÊPKÞÈ
+šUU˜ÝÌ~@ÇråÖˆ*H`æ/sÅ© ?Ú“ß”)€#„…‹u¹‰’æ*»U…u´Î’ ó¿²A—¯¸2\’É
+ë¯ü?Íu=j?†ig-+Öª˜«Ã
+¶6c[ŽqäãœìZò#Ë;LõðYRË*Šâ\yNýRtÚ¯LRˆ!gîó_F
+ƒÈÀÕ†1Q ™øʤ¦J$½²r#²Rþ#^µ<ãYã¡ãÚá.;‡ dÔ¨ç9¸‹â –>hA% ØñiŽ5s²þ&ËùPbŸÒM¼xkBètOÓ<?\WnY,.¾o‡Qìþ<Íkçhë2K¹”^Wl ‹ÀŒb¤;½¼°jì{)‡Ô æe5}D¹cò „ÌA®p½¬åÛÏ`"9c PA»*~ˆ‡Ë(v õᓹwF±ï¸Þ± Ø¢nCâo`;Øõy «›±ÚOƒLÇÌ
+jœvSò‚NkîkÑçi€¯Êª¦úE§Ý»|kµ™¢$€¤•öÛ´^"Ó©è53©“ˆ¿!uÔc, Ä‹¡ôWFÙã…Šð@äõR¨püQ‡õ«[©ê5ꔨ
+"UÓ‚=a‹–zŸ†Q<Š³…ÄÜý»Eÿ1^&IrÜ0=ï tpÖÚúÚªï¿õû$XîÊD¶´q8ª¡$ |üAž‹ÇZ 9³Ÿºñ¿ uòDZo=äžZ)¿›æôo˜yžm¬öæðh13ÒÈ"žêl;´‹@9+Ræ°UM 2‘Q¬c—°-\7+Yžqi‘.ÌœSrV5@ò°åé;òâìs³ìEI¤ç†ž !‚0voÚ…3·Å‘½^¤¥ze–cSËÌ
+­k÷Š ‡R9.×4«‹.¯ùµYt(ØÁVˆ&F(΋.Ï>Fì–¹ü˜ëCÕ`uãbÐQB8 HÿúVßi©vÊ8JëЫÃ8ŸV„fqIµÐ.Be2"5©:>BèÒ*$.¢Dš9¨¨”¤Ê>%¼H?~ín)A2+þ•ãX›§qk7þWÍ"šb¯ì+² EÔÖ@UÁ¥:½Z{ðÍlSDøÇFè­ÈsªÜ˜l)°3gÿ\$Y—sf_iü<¼€´ÙÝŠPÒ¬l›8H™ ¨ÉØˬØx$ÍRlÿælŠGCŠ£$Ó=ø¸Gþ¸\†Áª! ×Q‚2ºC™öJ3Gs
+6Œ[2Xï{ŸE0ˆNå-Sùƒe“SBö}N†²"á¤"IÅñë§K„³_vµëe£žÃCx0ÚÎèï~½`»àf²k9×¹~@#¤‡×䯗©™‚4Ø·ãéïoªòù®!dØuÀ
+¦c§MIKÛ˜Á›µ XPpY%0>@$¤¥3)Ž
+ÊnÏYå[ÑÛä{Eð2KïE¿ÝV¹ ï˜ø4­„µÇ­£x°=]úÎ’â ª‚fÎ|+ž§/Õà~é( üДÚj°Y¡ŽdϦHã¤Ü;[¾Ø(ß!qû¨Zb>4<»GLؘ
+Ï—OÞ dXļ—ãI \„<`p .VëÒ‘.f›ku‰ð5bz›,X6fPì;~,¾â€«9À
+α VšùÏ=«úg@ ᶟ{bX¿ÑÅõ­:˳¦:ÔͲÐÀ5AÖÁÓL–ƒ¹Æ]‚Y¤Ñe¦VÊÙµ° qfóv
+ Q¶ƒ ˆê²Vîwj—P“ÿ¸Í"PÙÎmT‡ÄÊKYI–Aå•%¼ø ÓBƒ÷ÓÀ‹Í™&¬žð2`g_üöŽ@õ˜jùÞè yhþá¬'¼À'°v˜çï]ƒÃŒtŒæ x/p¯Ú×oä÷-Šg©i¼ˆ†2¥>Í—"1³Jù¦YŠpLIiÖŠ°OâЮo¯¼näàäàÇ«i_N»DòR«Å)ùµÂÛâŠKNŸ!¬L OùÜÖXÖ™jÙzw¶÷ç?N‘çKý`¬¨ ~´“·"Q×D…%d—]ÄqRí
+k ý¬ÀÒ—Ã~…ª ¡ðÙœ‚÷—(¸È.<b’:Ü“Ïul}ÁZÆkòÞú „´›†ÓaÊŽÑÖV—"ÓÃr«ÄpÌuPþ`ÝàæFGyë"C%˜º
+±¦îˆ­ð_ç}­3L’98²Å­†ÁÔ2dÞïà÷ÆoN¸ž§*B˜Û††ñp`®/®°ùXU¢X˜åšÃƒÌOU^ŒS=âQÞ)¸d<‹ w.Ì—Ž*KÚÝV8cµD‰a§N Ìäà e¾ß…L,æÞRÙ/ $&OÇPèÍCQ"Íè”ó#:ë¤àzß ÃüB)ªÚaÚž=¯;ƒº€ÎÁaÔv„ƒ@ßÙ­ˆ×êM ÝÁ­Ó×V—¢3¯Á{ðLÜŠ¦éס~_-ἡ„tŠ,¡SÏõµl»0 ‹.˜]ì³’L¬÷' AaL0EâS²XY§•²a›’^ú¨yìk>ù¹«yÏ©ÿ
+H‰¤—ÁŽ¤· „Ÿ`Þ¡ÏÜ DRsr6°A
+S&s25Åxvl ‹¤æÎëˆvì@¤…”Ð^£,ˆ’”.>º´Åã‘YñhzòØ=¤µ–fm^åW‘êä* óJ2+¤ÜuQjN.Ü×9CI2Õá²²…ÀŠ:FN«¾¨s *’Y·šT¥)&u
+ý¶ÞvÄ°Ï1!׸ùꊇŒQ“lÚz^dJØæ!壟ÙP£D?Tˆ’q÷àè2!ŽúFjþ
+ÍæY¾aÏ‚î[b6DñµþÃæúo]s4×å÷Y“~ô<TG¯¢/Ðé[[tFû— æ #®hI=¹L-ÜÕ¾L†œÆDã6Êœ-åô•KÚq¬©³S3!Z-EŸ¦Xeã!L`Žn1Ï9º™õc²—Œ5[Š†*C'„!‘­+7ã*
+Ph¨d­íÏAÕ‰‡Æ}G jYzÊÀB4î³–¿ZÙcòy]›-¶¡À†áâ&ê¼4sÓH,Šß˜§"t ®†©3““ƒ>aWâtT
+¹‚e|g^¼ä_͹e*:¬Z Œü Y˜Ã[ƒu—ãQ»«Õöœß¾æ#s¶QÝp“›{¢ß&øñ¡N¯O´K6–ÌÆj|mqÔ5vÇ}y
+*íxÏ
+íÑ;MÝ è€0$Ù%(ë„TrŠ„Šd¯ìW* XW‘²Šém´…ÍDÞ‚2‘’¡2½ÆÌQå=nXVt< Úf›ëhœ‹fAìQ¹h¦+A=[OCzæ( ºæÄÐà¨
+ŽQ|v£¥)ë^ÑUYÍ6¬(a®šçtrÿò:+†_f¯å=õÑ1¬KÃØX`¤w“*k­b¸,É<˺‰mˆT4B \¯ÏèàYn¨½âg9“‘Œ"89h,ß— TAÖ7½_¸¡§¥Æýõ YKRG—ú„°9‘!k±¼Î«éÀT•ñè6œtmú­×®É‰
+ç×9yÇɹX1¥I€ˆ”ÁDrÓ,-ÿf¼L’ãÈ• zÝ'(Ã<¬ù—¼·äý·ÿy"PÍÊŒ”hmÖÖjy!|èn_ö¡¬4Úþæ`";@¶éö*Q’Œ/›»0Þ“‚RÙíˆ~iNsåøùÑ¥Ïߌð2­Ç´cH‰{ ËSb¼œö}Á2虸؎$r¢L,
+ex4„>okt¾ ãI¥2«˜Ó¸{”ÆÞÕÛë ¥_–…
+·ÐFBwb¼ƒ¼têóß{¹lQœYOø!;f´=Prf ¯–J:Ö÷
+ò|9{'?òm¬¸€^™òÃýÚo0ÔH*Än¬–·ö@-ŠSù_òe ‚--IVdC]|2ßŠÉ Ðr",A< Ò‘À ¡êyG­šËïâ… Ä±“ÞS
+¦¥&1ê1ËkR²/Q f¯Öíõ‰Ák{ó‚L,%‰_9Èçª"
+¤>vÏÁÖ“Ýpþ pq/ƒ1c x[ïÞhTF(Ùš_DšôP™ÞÐü_/}²1ŒJ bÞßü«p[ W›#ß= *R-1Ÿiî/Q(x…eÚa+è
+š¤‚uüG zjóŽrá Hq©·O'ˆMÄ©ßÞ9§¡¹Þƾ뫜!>WÇY…sÿµRïkó¨3\Ã׫~·(,Ô(×XP¢½yüŸˆ3
+Oçóúð@7¤ñú¹3èë7w2Ò`~C¨Ô¥ö-N/jú}ª¥æBŽÉËúÁGsïIä¡šT\–ò€ Êk²”FÑxYÂëD窈6—Iyö9¹ÅAvo¬sèëŽn&•i EÇ|ÎãSõ1|#ÿ&„J¦cÊWš¸WŒŠõNóZÐ9¡«ËJ­CrI(
+Ö–L‚@,Ø/éä€ù~hžF‚£¡C*ãþN íJ©ZFd•È_Ç,¦u Ý¥!ZFTí¨?ÞcßåIè*g2+ùù¢ è5°ê.,_‡<#™&À"Á øÜ(ËÐÌï59zKÎÏÒEÅÚ¤–Û
+èí´Šµv®B£É•£|üÞ¢bÕ­ûOl?•#©Ž¼G<káöjç°}eh“.•«ê°ã%M‚°:þå©›aê <´ÕÇ–óœ…ÊÄbÞˆH0ÏäÑŠ“"" Qœ ®mÛÅ0~êÚøjviVÛŠ® ‡Û«ÞZƒ€ /~\ÆSQ^éAy‡eÅ0á›C2N9“•e˜lÿ4¤Å?§r¤SJ¼U ¤[|~ D}”1amÉ° ‰Yuî/åH´y73Áe]Q3i\ÏÔVÄB“t‡ÏËa˜ªèº9×Ýk8$ ùO®GÏÊ$¦Ô:—Ë¢­é¸q‚‚"hS[eB¸”lº:å@^ìÁûúTã¾QìŠú²õ¦ý¬WŒcnÃÂß³`¨Þf ¬,»¡5[~Ÿ’œ< j\åq#ôÙ4üÞ³›¯¤¦ÄÛ›<f"V5V¨tc§NÖ©zÕ—²Ý
+Û<,u:A¶ë9[£ë9ÖÕ”¦±E7/w¸Õ·ÿéƒfe.»Øר€kF–I¶z¹¾+¦ŠÙ裾øv („Ü{I»ìæ5Ž1G]%WÈí ð+äs}idE3È)Ý3{;àÌíKPÙ±̸]fjz!èЬ§RHÓ«Xy0$¼‘aØnlD}Œ”dæ@0P4(Od·!Ñáü‚udaX»0‚Êê‘%²AÔ ²ÂÒçóÝ\nš©µ-‰E²ö*¬GÄ!óøézºK…_ö¡¢ÑJ–öæHŠÏ’Á»«¨(0Oª÷OŠziQÑ+Íë\yõ=#~4éóó«pÖ¤'ü"žJdPÊå°ïņ—gŠfÑÓCÂJK{ÝÎ:¶Vò’–…hc’5ã¢~™ÇÊ6“À W+NzL‘à<ôÒœê”u²G{úT
+ µäìûÝKÃ=ß̈֬qêŸS ¹]Öe$ÿ6C“¡^”¹Þ¾ª<°8øê¦_œòè£Òp(yúv ?údË{‚œºþuâ1Ô´¯wz–¤a`>Óâìùáò]
+£É³ì‡¿ðPêÉI°Âæ­—68ŽàÜN×Yh­Ür>Â9'‘yq¾Røò:·aF{aÓH-Þ½ŠQoR,æ Ýúea¨1õðx1ÞA^zõùïÝüøO®âÚ ó”c÷—ØT’7¢ôkà£V
+!É[ ´q(ÁÄp.o@ÊðâiÆ7oÜaoØKÚÑ~ gäŸPùüÔßwë?Ù )†«0Ö¤q^K]ÛÄèÐ÷ I¿½8 P…Ù5I<8õ@¹Ë&±{ÈëÛ!âà“’¡‘9gŒ#z$GV(esªºFÚxÛ1 ,PV8ÚÊÀ1f¬ÜaõPR>‰Ö7/€€ 8Y·óCGP&²)¾»9ƒñª’“”ÆÝE¢|$?k©Ý?‡åÿ3^æÈ•ÜJ]÷@[Æ Ìƒ© Ûî_CÞ£©ýë\ QŸ¯
+ÕÍ6ZAê6
+™È¼ƒÂC«)qé“‹Ö7½‘BrY5'Ö12[ÐHxÿÁcô¬ö°mb87$esÁè:òIhRšBŸ¥×~ÑjáñQç2FHFY·¼Ì¡×¨öÐ înÖ¯µDîQÃÅñ
+¦bšT”¾^‚+S£o+$:M ¼×J·Åb2dZé`;, Î.¹„’ö²¬vÌ ½°ô
+^ÿ²Û”â« ‡¶¡Åg±»dwqI˜‰2Eß6Áo¹$¹ç¶?q¤èt,1¡5¢C¦yºg%‡5&•¿qU¡j£Ï ’·çµX¶ k¤—OK(< #;ô4ÄÉ®gק Xu)Ø»· Hµ9Ä4Wª«“¹,36æ0Äíl!ŸãÑ5ø ¨‰6œk‡ÍúN™Ö£ŒiNxUÇ e–±tÌ3£zC™¼Åsç;ï¨×!ýÈRߟÃÓ£lÞre}ªÂSƒÿ‚é
+IÁ­¸ÜV”ÃÅñ¼^ ú5A…•¬ê„OЀTD*çZgND*kF‹’AV^ã¼>ÅVAX~Y\
+2Q“Û4 ’ߢ_‡aŽE†Ô¾ 8|rleq3 ¹¯æЉØåH“µ'Àæa/¥æyNt„6Šël*zy±mëSgõï܃Ór‚é4wSñûéúf~‰j™¼TæºG<ÍÈC¬mÄað1‹ëlÊ`Jn2 ¦V>!pÖ
+º`ýá…T¸'ÑñoÊÚ.÷ óUª4…,dÉ©‰¬Óç1,^‰Élq¿ÈHf$‰EdŠק. ~Fyfî8Ï!OfíbekÁîc]±t%NˆÌ1xçW6HÊ
+ù°Ñ*:š]SñzÞ€ v×a¼Ýš?íf¤Ìà‡|B<Ù×`óWŽ9”²ŠbㆵBrŽùk …â nºMU]¤¿­êêZ.ã·s?gúÛœÃð£ý%—ÁßÊ33(B"
+Ž¿DäH}]çzÑ¡çOÄj,$y†áìÀ&ë}M¼å‹KßBAÆuqchöÝ·ÅŠWÎm~zÞ€ŠxgW[4©!Gâ®ÑÁ‘,y±Å$
+Q-ðÀ2¸é(üµòÁ±GH’&ºE^/Ï°qÓççܺrÆ‚|€c$.úý9 W£©ð]ˆûË0£Õ;íZÈé®(ͺœsQRØ3òec¦û@böþòòTŸ^N †™q ¨èWåßóãØá„â }@wIô×”ËÃc‚ˆ(‘HT&èü¹3èù“;éêýúûŸ·¿þ}SEØ•ÿÙ\f ¡ó/Z‰Gø2U±á¿=oF x:ÈBå>ODÁ,+)âŠAé.>È1ÉâJJ¥Ôý9¿„ýb&I?¾ëÛç>H(Ɖp$´7!ã•7Yæ )`JñR ‰Ê¨šI…¡ñ©Ì¦S*¬ÑF¾„!Ç<x¹î4ÏÁ¡’çƒÁb%_&ÄÁ\¸2-¶ °ÄÚñOª~3>•ÐTŠòžaÎD+ _¨ÏlNRÒG»>ŒˆsqÚu:tÑ[kÍ ‘²¾t‘a¸6¦%ûĦTtt@HŠøWÌC€÷²Õͺ3—˜YÑĈVÎÑ?Ïs‡€²† b×ð˜(ÄŒ—9r9EO ;ðØ[.oA—¼¿;èê, G12¨ÏË_¸øþN¥|´ŠB7)¸.Yì(©ySSç@¾Üù{ÿNÓÊBkÄÖrsñYÔÐðŒq÷*¼ %­˜ì1¢_¦˜~2]ÍjÜa7*£s)ÒfiD“j¬…À(p4S1Ð÷ ˆÍ€,HxË}qßG0]ì $ðoüpJ,Wñ±Ll¨‹9_ÖÌ®dD´‹8œotzP³XÙîUcð“øÆVaÕ·#
++˜­ºÈg)ÄsëØ
+ïø|nS *`KmjF_l;“mKšÊW2ögÁß ’ …ªlõ9ê TP<æ í¨¦ÌDïâ°Ò¡cP?ë<ÎÃa lô3¬2•÷õ†÷Y¾\ öªɧ¤Û6’õ
+#YÒʱ)ÛbhÓ†t +TºAÔ)¦>2Uý5aÝ&w²;‰Fu’¨ÈhÛ˜³r¼{†b¬Yá—J "Bæ“ÈW£=zUôãKCãþÎÐõq#;kÖ@ëß`HÝYo P^‰²AÔèY¿š
+…„ &îªÜ@^Øß?/“˜—.«A~ºDx}ÿñv ËS™Ï€ÆhÈÎ9Ú°ÃسÊñ$#…¬œ¯
+ÜQ&>I[*ÙJéh-‡ÂžÈ]µ¦—¥&ظ“a'?˜OÆÂŽZOGs¬ä4
+Þ°ØòöÖŠŠMƧU¦ÐlF¸:&9N‰‚ɉ’ñQÖòFLw_<'LÿŠ_9ŒR¸-z`
+„«e&³ê¡¸Ÿäe™ Üñ±!PHÀ]Ʊu}(*56‚' cùç a5›LíÙO‹Ùå‡[DqÇ©©Ìx÷w Á ñŸeCøJWr½²!…èÖ×( bGUÖ
+¡hAÚÐIPÀò=îmºÚÒXïQï_…ârLó]uШpäyWà à¥Mç˜WŒ¸/üôáÝ¢#T˜G‘KŠÅ}MÇù5EüR¨ç˜6g‡ˆ9¦‘eâÁØ–´?S5drwÁNJ©–1¨~‹.;éÒjï;—q.s™;ÿM¯ãë•æm®åý÷&=nTÉ@¡Ѷ›­„Òtáñ\8üø'µâ€>=d JÑã``èõ¸+èû7wúÜW„‰ŠC¤$ý8\$-€Q!™Ÿ ¢¨³éÕ½;Žñ{ƒ˜Rœ•Ò¨ƒYLðè˜Ä4Ÿ†›¹cxš´!\úEiºAH¶yëÈÆíWWɈׂ
+ÒØÑï·Ôò}rÔ'ÿ „‰i‰T7<ke剰ŒÔ‡žøÞ*ìÕš7ÞŠgT,GS”)äk%ýJ+Éx Ýv|OÆÒ X),b’û4H²ª!6㠬߄årzõïñù|ÀØä 
+wÌŽ'-ç1]“æ:‘Œ^Éii'àT`ëÌ ºk"€ôŽŸ=´|cFâ k¼fÙüïàÇ"+|…ècØ9ªa> õª96Ž”.s[·Í(.zeŽyìÛ¹F þ÷ ˆ7Ã5ƒ£ú´ûàŸø8;uB‘¤ÏUs»¬--LÛh¨!´‘ò–÷<LlE:ûœ8§²Na'
+JHaØ9Øoú‘õ½ÊNdšr*·v1 Q5P¡‰(î.S(…<{÷(F‡m*òx½úÅy›®÷;—V}ýf”?Ÿ¹6â
+Ô-œô6‡×ïýÜ€jBsH Sm#FhD›VÍ)pÊbƼ!ƒS¯1ú€5±l:ª|®!—ŠYm{{h|>34ZµÙ HoíÑÇ{ëÒ("ÐÉ^›ñ€`9b…*Peÿ6ãÁ'b'Rî^5™?C&Ï-eÇç¼á—ؼ´ÊVùº´þûÑâE}Ò̇sã©_iXÓÐzõÞ‚ñ5]—·TñV?¥ä” 1k
+‡^ºð+Þºy…œ™Ÿ”JrÐ½ì± d7Bɧÿ6Ì(ÜÄ„Òo_¥Yo—‰ÖùÌü¶1T}5èf¼¼têë7ë¹]0¨kX!Íf>?"¦!ž%¾`«Wؘ¨þ`þt!ÍO÷¸_¦è˜ÈŠ¨Ò‚=­¨Ëæe*_ܵ„¦.T¶LÜ%]ÖÇ4HG.ö¯ÚDc‚B¨=¨q§Ül-’J æÑî £5¹ênm‹Šk˜‡>Ž,W­(†¾!˜¦é5¿é@ì(2^J\9u´ëŒ„à,XŸq ˆÂ÷< ‚odfq<‚M˜†(k÷×úU UÜ]êÇlâ¬'>Æ©r†
+‡m_IZ§*™YØ—¡o™:¯Ý ^‰CŒÄíw0À]÷ƒ©înC†m¡ÃåîQå¡©L¡Š#üâ
+õnßËÝðÿ0ÓƒwŒZ%<ç<W’m`4™« ¤
+³Í–¥*
+P\´ÚŸdñ†A ˆÎŸ`z_ã‰~!;Ìâ '^¾s=ÐÂC5 ‡!°¹˜G®žÖEjÍüò Ch8±âŒøÌç"vÍËj¾ñY+Ár¦µ!G¤eiÉ¢Ð.^Ø”¢B¡Ðc“FÁ ¢¹~Ö
+…ðn}© 7Á†÷dWe%^Ö Ö8*ÅÚAFÐ’U' j38žz˜,ÊX)h°¯‰åG£^òBß°ÔñäJ•Ž•oŠŒ ’6¶(Øp ˆ‰÷PÒœ\ÀÅ(5îlJ£e8 £Æ bîúC; I¸x'±=ŒNYuØ_ƒg¬2óãì†ãHŽá˜x;Ô¾ûÚ»+·iDµº¡Í¦t8l$*;3XºH¬€ÌͶ`-èðŽ°{®É;åæÄðJ>èè\|€\Ýr¬ßÿ÷MO’â 7
+6ÃúÂó vÌ;,z ´.qƒLŽ¾
+ˆä(k¯ê™
+6 dùÒF°®HE
+/ów¬ç3q"ÑYFÑ='jn5ÚQ®Ã>Fp*Ädç !}
+c8çý~
+R?2÷tÎ[¼¯yëç۫쪷¹`¤ E×D«ñÛp¡>8î¨ñÂ<@îCÿ·I¾ˆé¶!5d;o‰~?€.¶yAòìÊôÃ1Fï¨tº‚@ÐÀÀé•hp~¤à¡uÅÒPW–ö¤­2ÿÂ%+wpøXåDŽw–¢c‰œ
+ªÕ§ ¥Åèä¾éky:' Fƒž" ¤Rf!B°goè•‘«ržšMèkÄŒÀÛE±–âüÜ Xñ{ )ÿ‚$´½'\8v2ĽVLÌÜŸA
++M¸½5uåGD;æ>¤×"bÀ©½ÈÍD[n3d†¿Ûè'øˆ@…Ùð¥ÿÖÏB¨­ìiå¥÷†>ɬZ¯ÇBdÊÁo`Àb3F|"Xæ\¬>ƒ³‘O¦z¾4t5µ÷_N•wò«:ú˜ß½‰òdÓÄ?¹=@h8‚OL9«þ¼^ÿ‘Ÿ‚ÔÌç°¥e7X0¢¦LíÚÄ
+í!š½+"9 ŸO 0&…Ì•Ø­u@ÜÃPÂzaUYøaV
+‚;E‡¯~oPáJþŽÀ’}R+h}ž¬¯1—WE1R hVüÅ„ŽeIÝ®JMöy½Í¶(ð'¼‹:žst+î‚;‡0—Ù©ÆOM7d–
+B}€È.Â2°Éob9Ll³|?üõ
+zÈzr9•=-¯½ÊtÌŽI$¹@ëJ°Ör!ãˆqy¥½7YöV%vïä•»¥é•ùä¿SyðµõCƒS³4Ó>yè'ÐD¼!Ì"DA­_CñH‘ñȯNTþL,wÒ'f ·ÁOÅ0¦ýcüƒ-yæ 4TlqŒa!1’`Œ,àˆ“+[MS~Ò§´°:”c/Çò°TÜ/õI5šÄ<šÚHÃ*ý)A÷o,)B]›^ð$J˜æ0<c3‘
+Õ7™fz”óü©#«B‰!ç Q6Ä-ˆ†"©nõìšAK—ßt
+F ¯ÌX©†‚Ѭcï Uˆ—1…ða»?VŸ»Ì]úW넉±mÌg§)b¨Žáú/eZFD[á’Ð(“2²€3W9WŸìò#Ãÿg=›1U"rP—žÎYÄA‹R4ÙHN¢²‘ b SÇÓÂWrïwnúó½¬K÷¡í
+.äó¬gC¡È‘Ñ¥(AXiO’áÛ:‰5 Šo{²uˆ5†r´=6Ž¯C¬áÁºÆäÁ×9»¯»î¾ÎY‹»¯s¶ëÝ×-ˆ² f†Äèùºµ1Ø‚<øºÿ3^æÈ‘Y=î
+w¶ŽFÂ-¾!Æ[[Ç`ðbÍ\L7¶Ž_c­P»03ÁÅÖ“LpóÌí­¨!+8¸š{²lÝêÉ^ÕU›Ý~Ç’ÃÖA4Ž¬Á2q |9Z’Ô¬ ø11W[#.‚ÚÔ÷¾
+J>ÕCýÝ9â4ºÍØ<Îó¥kl‚ãK¡7Üؾ0Þ™±B¼¡øù)î¹m‰L8 ér mW¹6†—Œ;c0¸P~G?üúX‘^jß÷jœç•^ɉPÑ´Ïd<½ÀòD9nSí8#ÔBÀˆ”c}Jy¤I0jÍ âi'âÁž¯±È’¨³0ôoÈšÂr@ü8!lÆv-/€¬Í¸|î%Ðó²Ú3ÿŒù‡ÇNè7)§ O;Ë€ª çÓ güÜ€¼@µ¥fcØ’ÂÊÇõ='¦&†Ö.ÕIwŒŸH÷r4ûS×s´‡¹¢}~}
+j¥²§NHv™ydE¶Œ…Î%ë°÷ËJ
+Š&x¹/1¹Íc1¾o@¼új|ªö}‡c
+ʳæÛsXiìZ§§Ö•„›‰z-·œ±6¬?üT|³‰ú6‰+×»¯4mÛ$cÊR.¡-Ž×tGâ'oH.“agü’Ç6NƒÄ+}ú« }.ÉθªÌ7'Ã
+ ¢S² bµ¶úÉèÇ:¦Ã€¬ìU0Ù®ßá¸Êdà§Ömt-d
+~ABRˆ!êì 3Jô²¨iË`Â¥,oë ÄôAzTg¶ñ 2»åT[â–X¨1jh‘á_ñŒoƒ×o¢GÎ*s±˜Äv7ëÜO N1¦séx×O`å`a¯Û…TU¡ßœn:á-4Bµó]Gý)wB¦¦Ã>ŠÃ¿Eʸý\Füøý9!m”
+jô ’nÎ9H-­ý;ƒÌF¸µÄIFlÜm·Î 3}ÿ–àÿ1M¯!êpÙî–^PiåS›)-hý ŠŸsÜ6ý ôyb0ùkÔXŒkY §¹žGë].D£šãÒŽt”¬²& æ§*¬ÑÒw@\ƒñ²Ý8å8ŸÑÂa ›ž!¾uPÓÎ7q[ƒùÙN3Æ®O)é°Œl£ €°ÿÜ„ùLþå6Ú-¢iîÑß¿*à>à ÜÏú”pÖÆpË÷ÕR,÷ó2à•2·ð·=ÿxø}UR¬ÃRXNêg‚pè¥ÈnUÛ‘AÁx¼Ã~â=^ O(H=äÙ`œÂ(…[ÆÓ¦½D6Õ´¸Ùy@h UÒô¸uNª˜"-ZèËIUŸ`J”þ"ÓÆzÖÉ¿W#Ç8!Cøpä÷ ˆÝvžÿ©3êé¾ô
+¥vù‘)¡|Æ|½OßETi |ÇV‰Úð2ûݘ,Íý
+ø[¼4üšÓ*q@ᲧÉ2s˜‹šâBKV„ùÚ+š“«"ó`ŸÓ1¤>Ç–îÛDe°,'5!ä­®ÍiÁoÛ’©`TÌlûSŒ $Q÷þÉãÅÀ—Åxàì:Ù¦ln…ü „.þ»`Ò=†¤V õÇ›â DËV±Ð9Of½.Æ ôýf¬/EÝ™fÞ¯E†³;5K~}‹=ˆ2¤áƒ(‘_‡@ì'5Ew÷ªñâ ·ý>£±¿Ê”«çÜ^gGZ2ƒ…6XkµkÞ€ìžlè„Ë3¸^Ïéc‡\öuÑÏ'8˜™Z=gÇd'¬Ûà;;&€AhñшŒ¨aeI69HrŽ™jl™€>©*kÖš#~Š/Fpt²3›q[Œ‹Â†Î1å+‘Qò&鬧“¯4t?±@ò<†]ý쟂~Go¿¦É‘ºØb6 ÐÛnh¾:2AêdÓz`½>žÛ¶Qÿ”Q r°/ù4 4 ¸
+'xTþÛWH‰µ8?†=D’rª¹LL¹Á ]F@G”½
+Æn†›‹l4^PÑïÞÃÌ0´äG¼t²ër«kq¯ÃùÔ£¯øs祜»ÊÓQ/:Qã~L÷fkãÈt˜™áµMjÐ[YE¤6•Å/#Q‚0Ƹ:‘D()öeÞB…"ÊXämDt…ç{,@][…&qÇä>!pSͨéÓ—–_k´"U÷¢X|ƒyL…T¹1â‡}ˆH[ÇnÞ±´!íÃD\+q˜ þ-ïÙÁàÙ;R›ª aU–þÇÁ}¼Ù §¶› ¨MŒ®cj±]ëÂ-’icߤD©¢$ÜÏÊð+¼²‰³‡ÛuéÁJØ™ð¨0ä³;'„ºE'³Y+2ÖÓ1BÚ‘0–4B™A'ÈvlV$ÝÈÛçœæʺÍe<7]§üR›ë®œëk­ÜS›¾^ÙK­°Ÿ+\œWì¾MþúÆË$IŽ\¢WÑ Ò8€Óúou m¥ûoÿsYÊD«¬MmÝ%Ž‡Æb†H-¾Eh[âF›àÈ’”±B¢V’ãO1ÛŠèü˜ÚÃ/q›\Åóé©í/o¤\ÖâØ=«$ $^b°gl»!èg¾MëSY!I›ˆß¾þwȾˆoÑBiZÿp™M‰ËáÐ3@
+¸}n6Öý.:ÕEŸ— ç]Žäó9Êõrí2E=‘@ädºÔZ<§¥ˆµ1jb}úšK5/¯ÚW}Š"ƒó[*lj9ýðå7*“4³îÊ[ý»âÿ%ã¡•èJcÄÅèuÐ7ˆFdyLX<,®NŒPx¶Ù±:þ“$·e*¨£)qëÜq– L¡&ðvÛ‚¶PÌV¥öÇ^P§HÉÒ:‡¯Ä«™"Ñ\“"j5ŠÒÚƒÙIP0ÔÏéþ1õ5tkdœ}rgVó®ò zcž“h@ƒ*¢çF.p ˆLõ ¨ˆôú¡-E#hbU(tUåWM¸’=Uƒ¯Ø\é ÕÏ
+–\ëº q0¯QK Íß«$g¼X{nÔ¶ã[⥽sln§¹¯bôÓåI+„õ„eò×½,fþØW´u•10 ƒC)uwdÒ(¥qŸƒõ –°µªÆÑÑ Jõ"0D®4>  J«š÷˜6æ„I{ÉO× /A¿wÐ"¡¶£@ÚÊЄú{·Þ_T½s†„I§§Ù©ž¦<³Bðeú4°åtš¬õM²èž’–U&ñrTÀ›¯)“ øo²ô„£ºžjvi³ÎìÁ;Dpà8€àÔ« /f’QzÌb±“ü ”¡ïð²S‰)yVÚ;#I0õŒiµû½uÁÿÈöf-#ã觗ZÒÖÇÙ̘½ÁÊ×iï[¤øM4×£;Óí—ã ¢¾pP‹Ýâ¡*¶gŒÙ˜Á¾¹ýË#e§Ó+X–:ÚéÁöXƒ”¼3ì%/°»`Ekˆ÷Á¦ÜT5»Œüظ…Ì
+ôžö¾;q‘ÓIá<?Ûz¬I[*m}=~Ș&= _ Ë ʃÄ>¢cX_ÃÌHŸÎÑš—µ –ÃÍä>Ö¿VDEäL0&cÞÌ@2ÁÔ¯vnúoé|áœÉá£ú,<áœÑ¨Ú,˜íÎyA7œ³ÙòXø€Ÿ8GïSËÑšÉÅ9Bð=„Œ9ªÿµ.bÂC¹­çLžÅÏy÷xOÚO #
+‘ÂxÓÎD¿[­è'<žÃhz¶Á˜\ž#P£çä§fWž#ÃÒ§Ü|òœ
+Ú°¾ÊzrP÷Âsÿ¬ùÏqac™,Ÿ1•žÓ§ÓôI‹œoyÜÈJÔù__]ž#„ïàvžx΢¼L“€L—çò„üÔæòÜ=Äá9/èÆs÷ Ïé“£ô‹Ës<%•ß⟣Õ+Ï)ƒLÏÀ'Žž\žSYG±ÿù<'=ܘ±'œ»ö±wŒª‡š ÉÇ9+ßH\‰ùæˆÉZ^@¡«Ks„0z«ðEÌàáÜ=Äá9/èt÷¾p€n P ‹
+>ЩKq"„j>Щe˜Ù4<¼öt¡"D4 ] #n¡ÜøZ-.ˆÉæ¨ “9÷øt*:ÛHGø@GH5õ'ßtÀðt„ ÇŠ¿ƒúö
+XOÙÏNè”
+dw·˜!&''ëã¬9!zx†Š™ªû~ØbˆHü£$ŒóÁÊe(¦1N…ÓÔ}û ³Ún­õ<~r˜i”¬F3<Iùä6Åõºo]ÕÓû-è ²syi^ ‚:ç® 8F_ô†ëÇÙø÷ ¼<¯e v:!½kÄgÉÉué\_l§F4ñÁí b«€Áå|¾ÛçÆüÆØ’†x>µcÇÄÙ™ým‡0ƒ‘­,wËÌ„ $f•— ÆçЋ¬j{:wí/ôj´µ¢ÞƒXÐphtYèy_sS»†r‡Pé´0J_O—‹7)á°BDây¶kËçéb\HÛŒMâµJ¸Ö×M•9MUÃ<æ_IÆ jÆØÓZ@PÔWÚÃZ@=É•ôBÞÍý*Š!(§<½©`‘©©ZôSsÓÖ=ÁŽF?
+õë;BþùÞ2ø¹ó°ú…eŸ÷Ç ºñ3!P
+õ“k²SE¿µ¯¯ˆÚrEŽµdƒãùp@…3)µÅÂçBàÄØvs‘2ÊÜÕèrïµî.?4¸«çœêŸÓ°` 3KòÙÿšÆ j&jÔÕ•Qd,lnjú+·ŒA1ÅŽ|l'¡¹57D‹˜)ŸBØêb'è£î¿Ý ¶^ékÄÖCZwcI H:×Q)´OjÀ3¼Øè¾=âdI¸(‘vŠÉ߀¯[ÒÚyÈβ ¶Ø>8~&nÏìf•Þ D¼¶‚¯Œÿœ‹¶¼¯¹IÔ{ÕMé÷ìÜúå–b§í>*õë;½9GWIã… ÈzYùgA/#²öm¨™5ÖÎiS‘Ž¦ï˜à7Á6¡^œEHËŒ;žŠ~ü¶ /9š5ýñBæÛ‚¶È‹ >šTW  @K§ý0êà‡a+$Ñ%@%}¼C£•¼Çh|ñr¸?Å$Áûç BЖdŸN¿~M È=Ì¥M¦âš”»Œ¸ñ…\l{–h^jÎcñe…
+ùïÒð< ¹CäNòãÔï„óý2R¢1ó¼:Œ·îƒvñˆ–ãCóΚ†µÆãäV¸‹Æ"<ÆLáàdú4¹—
+H‰Œ—ÍŽ6„Ÿ`ÞaÎÒE‘ ç˜ë>A°{rŽûþûQT{‘nÍƆÇÀ´«õC«JÖÇÃç\Ñ£5ýüµ7yX—&*æú)–‹f15¤kµ5øŸÍÏoÿþhŸ¿}€´ÇX½7÷5e$t<¢15M×çŸ{¹%ª£ëT_Іô®+Dà 2{ ‰Õ=¢hZ»ÌèQu ¶øøó 2ËC[Ÿûr|KmH÷&ÍÎ:jmDØÜeCÔ»õ>ÝÛŠ+¤?\ÜdŠšràowP—°>ל.ýóû$A”])ˆ×f¶¯9‡´]ÂöXª3¦›GÓ‚,·¶¤wõ"£µe³IÝœ
+¶ ´ ×üU"}†²Š×F”´iŸ25ï°!“RvŸl´6Ä
+f›mèñGµ<œ Fä îË8—lÐe锳S,I¦Lç
+bü¡ J.gÓéúZÊŒÜ@»£
+sVÒXd¶FË'‹Û8ÄXПµQFƒÃ2ø¬{:ƒê —¯9—µFÎ ”òª²sž°<’Ì#ƒù†AËÜúa˜/ø`¨Š„¹¦Á¸uhê“]š5?;Á4Aé8Ò8Eö‡8ÂÄßV Å‘u 0´¬*¸›ÅUš}¡o§“)©{Л@
+[”é(¯ˆ‡q F`Ëiç)Uy¸(5åW>U¤¨wˆh¬w
+
+ÓTÁ_ì+¹ìušŽD|µNh(…—ç­ZŽÉÈÊ
+];ͽ “àaô¡Wýœve`Ê~ÜœTµûÂ]ªWPOQX`R„el­ +ˆX‚‚hµÖP'¡4C):ª™ŽÚ]ÏÕ/ FdŽ‡ÑèºúÖ¦ú¢É£&1 ¯†çœí#3φS¢â0eœ«£½cáG}s?pjíÕ6ýyuK[ÔT­ä‹Z tÆa}­ÓW|Nš÷‚dµÔ"ÝnWùµ¡@èiBGÒöÛÇ…m’«È±Îé±0@J˜&:¨l†BÃÐW¶ûÑtèIQ-;ë-æ™KŸâ¬ŒM”jö³J€Q2¦ â9Y9 ³?æÂÈ9 ĤjÕP¥/Pbí!ÁÒfCF†ŸÑK[LVh¡zìPrÝœýÇ#}'U}€æiÿŒÛ:óI»GÏØÞN«Væ@:Á”÷Ò“–;'Xü4|j:Ö4*¦è ˜Ô…•­@+Ÿ(©g•á"zO&!³6U½B^°\Ù1ô…´’ŽQGž|÷S^ëè$ŽJM?,í饩+™mvÏó‰@o¹FD-D§]Ä
+’;¸?î32xÅâ€
+VrÎ3/&}ãÏOƒØ gD»x*È› ˆAÇF ü\ã(µ Û˜;f¦¦P ÈDøª±Ár3Äð Š’F $àMÞŽñ4¤t:%zòÍC±í¯8AkRëLe’“§ëI ÔfM?mÉ&Tçr¶â½ÊÛ‚ ÓÖWëà¨ìÄZqN,é§ø¡”\@Až‰^Û~Ÿä½-Ÿ\IÄ~Tù tëDC>™8ž6]çÏ‚^ÇâûÏÌÎï{Ä,u3Œu!”§¨,¹ÿŸ_€Èh<Æ&ÔÓ,ABøoƒ GÓnñä´ÎYÏ0E"\Gâ¡Rky5î¸Û†·Y8u]z„—¡0žŠèD-Èt¬°@°IÄ[ÚVaí8-}O=‡ì­PH¥ý<wnë2Sv1½~? ~Çûy?y½¥'µ1Lø]¿1Æ5É9¸­ÝK|ü¥Ug«7PîœÊÜóy?ÍÚéŸZø–Ÿ÷[·"Ù ??
+˜™IÆ>ž³oE€I«¬u0gÝ£Ô Ô§:ðêœrmÕ ä°â¥åïë¼çý0¯ü»ÝéBã×Ú\†áµÂ7TeoÙ´‰pŒuÇeØŸ³‡õg´5ýJåß@ïÃ~Ùî&{¦-Ÿ¿%Ôƒ%`î³L|dR@q(r¯ã_@dCIͧU»/@ø?'`óKÅ^ÊO“ø„W éŒ,: ‘¡‰Så °Œ 4$ö­ŒrwDšaYµÌÈ'J ‚Ûy/ååÈ&Sý éΓÉ.½ÙYpbËd§÷u†lÞ–kp"ï„°Ðm$
+D#þ,²ôJ~Ê5ÞAXKCƒj¤¹Ó´·Í°(œFá#ä¶ÚŒIÈw"vmWŸË«{&#\Þ §ÊùÐqr¤šµŽBöœ—1Ÿ~ !üPníäNAñF*ÿÜç…™6H<9áYå…ZBñúÎ?ZƒxaÑ›Á$¾ÆúßVÿ—ÇIùV”§Ïâ
+¯‰qYïÏ+ˆ£ºù½!H›òJôæÙ … 9§Š„(úGac}!p
+ÇL¦ñÕ$úÑ¡A1 ‘>…c`šxШ€Ìwx²ÿÂàñ© {­äçrú•é˜×Þ`‡¯ÖÁÛ싱<§Áãx‹Ò0šTìaœÐÕ8‡!†Iãý) Aȧ]“³Sú4Leu‹Cf4£å
+~°oÆ9õ.4ÍÜÿ´Î%AÙzÄ/Éá¨
+K \Üfñw¡a½î)ðÙ¿0/\ó{×èfUœØшŽ„wv`ž•èüÓØ®²§ÀÀG$®)!î¨,Éâçng¬gƒkýÑi0Ñ'ðSÀw׈ 2á¡Ý Ý'—¢tÃJdRb
+LÙ€vJOÕ)9»Çž%´°âŸsñ;%t›ûD@³õ¬ â|ªÛ³;íf+PÉtšDƒZ)vå «d ìê@Õ*o…³“[BË' c‡d*ßH–Û£¡UµGÚäÑ+}QÔ&©tvâL¦[€Jg»„ycµR@Sl`?'Ãò¡
+C±òeBÂnàuJYÜÅÞ#IF&MtÖ[>0Ïܳkƒì ƒ± KcغˆûÑÀ~73, ’Aòßž‚Èq ¹ñ¹í(QûˆÄâ?‘+Ë€ñ…iž,ÒHý]¼kžñõEôûÄÇᇜȤØ`ÖjÏÁ KQf7”úÉeЕ^¡ÃnÊ ^¼[‰9 ŒÇ¬^H\_RËðb0={wNCRaž‹ÛÜË í;+<J÷(¹^|o‚Y·
+ßÍ¡d2ÂÜr[Äå´Ø)¹ SôÌ'Îmž)çz•—–è€8Ä1ù¡‹GÉ™:ýèvÍÊ‹€Ï‘ßÇ\¸¹/sáÏ{”ƒãgsîexvø›•²
+5„ÇsL§C@”+ƒôÞŽËï@‹NÏf"ò…Ò|öãéÎ1’þ“§x%ûSºN£s(Í»s´ ¶¥zžÅ†+œ3–q]xTlàÁYJ%U=köÿ´p¶RW©BH((¤–t4EG(ƒ¦íÔueZÂH]©®ÀXdó¸
+ïм0E+i9åü׫š„¡$nÄRÓµ‡PZÈ&à丂âQ]𸋢~
+p7Æ.q…9DZ˜ ×É~o.lÝv0úeR?²06æók’—;‚wÞ·ˆ«7"ŸžÒVr-XR<D&Äå2õ1ò¹
+ã,ܘ.õPP¨z'C™þR4Rpi¦œ“ÿÄÿŽùÙì
+ M§Cq©ãš¼GA ¨vþÛ gøçtÌ@”pƒÖæߦ3y2+˜)¾{T¦Ðþªú½é颣#@D‰‰ûcyÏ—%“ýë/¿èËä»EØ~¾Ä&0<öÇ Xf<,×'î>*ºÖn/‡÷Æ T0 ,wŽзór¬óR±D„=iY>h6#„:‰²dNvÊ D7YÞ±j¡RivñOy ˹ÉPïEÐïÎ\ër÷×Y»/súøÉnn‹”ç‹U[Å;Äp7Ìfm°W³6ˆØ†4jƒU2dÖ›rV¯M ZÂÛŽ±K8P¬‚7ÁpWÐÃ$uûS“(Ã9Zœ]Ä1mLéÜ{ÅÇé9ÖË4@%„´#2¿¶K,\Ï8¹àKÉjP
+¹5T™ÕRÿþ~æ¿>ƒZÎùi›¥Þ†ðϾ&«Ä*«æ™F*t†'Ï3ä3ðJÓ3¨¨ =h3|®iViTPjX'5Úš¦@l œ°´,b(ûœ —ŠôÃ1å3 ŽÔ£[’¸?þ»óhY À+Šä•ŒAGËóUtº¼2ä`™S>Þ +)•¢?µûTÁ‹¨Éÿûn&+Š5B+qÒ
+ËÄèÅØ_bì™gB®µùAL`‚emñM »ÖØ9g¼4l>÷Ù§@þéòã]ÂÔÐf²ÙySÄ×GZL‡ö—–gŒÞÍzÖ†²œ¢¿ºuaÈeæîpÂňÜFß&ä*I¼r\¥ŒgÝãtŠÐWTª ¤©m{nÅ£æ·ÕÌ#¤’©±Â[:…y¯”œ@ɦéµf¡¯¾GÞd°y9Œe ­ú
+—Û¾aÈíp“–¨2dôßòŸ¥smm¬¦NAØÜ^¨>ièÏ´Þ„W¨Y76‹Yü9dÝâÚˆ
+Óß`ܺ&÷]²Xí‰ÀÅ\F÷ω\ôw±¶1
+jĸZv ”#&™ȂZð–æs‚&™7¿˜±øç$æWÑ=öä¤Ôçmò+ŽvéÝ«
+‰©à¤(Io^%ËÌ! ýÀØ‹ß²é5m¸¤¯p¥cR€I•—Q³~ýåÕ
+çJgÍ«ˆCŠ˜²&ß[%=&ŒØ˜…ø%é¸=›(«'VDIœCæFúZßÅÀlR4o5a S <lCPÁOp—´q]5Þ$ôP¶]>æÇ5ø`Ä~À¨Ðë<kü¬ÁÄ)µý»¡èéi„
+¡}Í‹“ÌÔt›ÆáÎvÜ:Ë'×ëå“•¨Ê>Vc Ä©­Ò=œ%j È?Nsè¯xÞç²ìDo€§D¢ŒÎ…T]xB
+Ý6êTƒ0aÌZ0¦} Á›H[—óI4‡Þp_.˜¬d5‡ ¤«d}IŠSûüx9AL.*&/ÂÎ!°lw²s;l<©ÂšŒ¾uÅ›„$ÿ`ÆŒéTòÃæ9¡,2B°X±CÅ@Xq“Ql}º %(&Ì ^%Û£„ZÓy—xjÎ ·ŸJ~ŸÔ¯
+øæ´’®Å>j4èìjC·ñíº9Ƙ¿Æ4-‘éŠ7€¦¢ÕÓaˆAB+«Ü­=þV⺓a;E&X<²aÇËPÒ&þ7IuÓãÊÈ”å H%Çæ4),®¦Ë€p‰4€ÄŽ%L
+’Ã7âPŠ­ñ¡æÓàßEØ5JpjtL™jݘïf·qV/n’Ë`+íå=òS¹D+ÁÿñLäÒ¶—+¬à‰a`4×0(sÛñƒ iY«g+Áa%çÔ3YÞJ>¶kŠÖ Ÿy<g×v›¤‡Wí`ߺ³¯ÌÖãÓæ}šÕ/¬çJ’¶ÈîžКñj~“ÉŒ iÞòó¡HV±š¢U@sA#8g6¢¦,˜ÏV’™©¢MÌÑJø!à„Ñœád‡1ÇÌtPÏ”Iïõ*@ž³“
+y¶Š0K5ƨoÝšÕ9N%ëC•gŒ<v¶§sð"À
+Ò¨ÉXÑ•˜ihaâÕÊ«SÓ/­&PÄ['•^¾c ©±öØ<;‡¿e´e†Ï "¾Ì2:–û)cø—"b£2íÇc¯æO 㺠ˆá† {¸;„KšyžŒ´ÓíK8.6KÊÌ®ÞЕDÖŒ.‡ ŠâWðw~c®§ÎŽ5zýÂÌ¿ý¢éÈù,bB”úÿ/“ä8n Šž@wðÜ!1­µÕ-¸%ï¿õû€Yf‡#’ø‰røùÒóªy«q-: mQäN›Ã]‚ïégÔ1b¸Å%áÝ<$s±5is™r2íwz¿±¬!Áa¹g^n_p ¦&œ£H#1|³
+ŽÔc0q*Fi|6-Ë<ø3n!àD;ñi@<D'nK¤]ª|W²•Uö&VœÙ5§‘QÊFà½{kÓ›ÛÅç9I+*µ®Âˆ ˜€Ñ¦‚ÂÅ©º±$PI,¿´Æ`fVÊža‘ˆ¢¤=k´š™Ü‹r[Ú@K!~©W‚
+£®0Ú9=¢$âú\sº×ÑO¢÷-TÖÀ;EÖŠ)»l.cfWST›­òÓZ,Ã(aIèO~H
+ëSš€!$¤ÛSàgÍ,® Ø
+ÁŒdâ×}ŸÌ‘?svxn½\îQ:¿µq-
+îé´œÃ
+2]9jð¾¹ý䑲ӫϱz„#õ™ ‚Ê·iZþ7—<ësc3Ò¶÷)Rm•|Ù¥#º$AFÔ1–¾æMQ%ÐRIÒd;b´ÑÖuzk"º8ÎÖ9EˆC’Æ5­{µŽÁPü=ðCLãeÑ ‡|­c„¢ŸíVC 6–0êuù·MÚ“IÚÒ‡J<·n‹²HI³
+!Szš†Nq}I£CaD¨É“¼ÍOQeL\­%Ñ?gh×ËÂØ6:ÓÕtTW}N &íc˽#ï&Xä¤îÙ÷¿õóÅt¯hÁã7Lg4,;¾¤6¾a:Ot0D,+5Òû!¹L‡/©øhëy×ãw¦C‚÷R¿ä§µ¦C³í©Š£ËtHÀü—e. ÆðëÉ4]c»:‚Èüª4~M#ûç¨ôX¯ƒm—êpyúȦ¨C„²Î‚™©¸P§ŒVA,fÛÂÓý˜ó/¦3Ýr:HøpÃtº–Š •µÌ¾‡„e¬íxĶØïPg ñÍŸquáBܸ[ñ™.Ð0Š#ú“ O¦;$Ó9¢ƒéÍÉt‚±Jžµ‚F—邶ZZ—Ç|ºÔ3Ó™8@_Æ¢Kt™NYíT ‹á» ßN•BU ÛK}|ž£z¡kr}ëB¥ôõ±Iõëu ê‚j×Á:3HŸíȘëNɉu§ÆÁº³-¬“ˆüSnAéó°Ní€Í´ÑôëÔ궭zƒurÚŸñw?<Q©
+™¿ÒzÝ#¶åp„@ßõ¨SƛȆ°¶áŸ€g}Ý¥:$ÌIbß‘9¨ÎÔifUÆ]Æ Õ!Ò
+Bʘëì@ýò==ª¦tTv«U¹"oB†ùò'ÅÛÌgLšqåào2¹áçB,¬ 7²G"ø|,S‚SÁ!Œ„ØWUÐå (Yèt„SäÕ`»¢ƒ÷W5NSßúYst©Wï‡è °3C„‚ÆõÒ,WfÙ¡d¨­n³éŸ58'pHN™×CÁ ³îߢ‘0L‡‰ñ£'¹ /uhh¤Å˜ç1åÜÙHö4_.30WZÒÙ’žPók0^áy:#1ËÌ+"õŽÛ‚L‚ Á»ÍfM¨%š#N¡iÔÒ¶‹²Å4Zšz”. S¶äúÒæãóáÖ°•<lƒsê…>"Üiž=]ÐÕêvÃï¯ósÂŒ)x ÿ6³ÉþfZ) Å»sØHiÖ:3ÿ6d\› §ÔM>ç«(h®o%ûÁ9Ëï9§âï<½½PÃ>÷…œôÁx,mœ§}¸šƒš3· C‰ËïÅL[aáy:]~h¸A-ÍÊêwý©ö2´ÆÌ‹Cž¸ë¾±¹Xëðbóù\Ò8ªY.îžYw°™ê±Jú(!ëÕ?Hဵâߦò/\›”—}áóUz¬: æh~tê,dEhqÇxx±×êJ&²Ã­)=›ØÑ|Ëü»+²Ö%eS™ßBMºÙâö6_&;áHëåð
+ Ý·ŽS»¼™ñ™v¹]åÕeµ– Žb¢S4Ôf±¥®Ÿ³=ú£ëpJoª.Z¬5zsÒ«®ó6G•z¯:ªýŒÎÑ3gŒÖû–«·úóš[°ðƒ lÓ¦Ï9ù15 [­ ÕÂZI¿ôQ&"êYñ«=ì&Õu¡kÀá2¨Ô!¶)f èãö ’ÚÕ$B*O¢—%¸°òŠöl>žÓ¢ƒäšvÿÄQ#Ëd›’†íx»ÕÕ7C<úÍ †×̓yƒÃ»ç ;E:²ïVvƒ dàçAÖwç*쀩²~ÐÅ)•s—ïˆ7Ù÷B™]
+ê6j=±¸Ü”²àrA(g«"”ÑÌœ'Í£M8âÎ4MtF}]Ä–Õhˆ!˜Ü£ßqm>i²’V€PôŠ¯Œ5y§è‹Ñ9=,<˜câÊ×…$
+¶.<MËÇ_Ú×@öNÑ—¼Îáˆ,ÞÆ—£RðµV¦£’Qz2ÙÔ£#YŸÂ ¶âRùî®Ê‹Øw×—Tj9T:½Ì„+I9ŸÉK!^çÆÌ*å÷/Oä$B}CÖPµ.½,"[¸æ”uõÙÇŽ&ƒö‹L¢¬& üebm^¡ÓF†ÙL „Ñ$¥Þd ‘±]ñ­HÔÜl!ÉaP7Z†ªe$\/èŠÜó&[r§®ÍŒa[oÎaˉr )ï+Ù3€A?%tKZ„òšÆÄòØÖ~wŠ¼T0aô D—½¼½ úîÍï/ø÷×v’2d§C‹ì’p» 6X4.§7­ú.ðDnDj‚Wqvfþû1È#suåØ ‚y`Ž—Gƒ½$…V-¹­u°”lLbfléS’èC¬¾nLWg0‹(¢¸R«éͪ-®š_E,-F;&•žûD‡?Ðg¹Çê(Þf™xm&ÊåîWäÜ÷ejÒŒ§¸Ê”äĬVs”e‡Æ\ìð–Ôö§&Ð,P‘»ÒˆJ©È<ÏÝ(<³Ý<Ý£ŠõH¶õsƲ<JŠ(r¯Lú˜¢bb62L|ÜJ$;dz’£ mFm°Úõ%ÉC°Å³ ¨^Þ½pü|~bì2ôxÓoŠ@‰¬ÝµôzEšq™»~÷È“à*‹]fš+á™x6ź”e¯Ž¨ðäO`0‹ùÐkŒnLjfô´]¨$Ñ>¥×à ÀÚÃîÔ–ñÑrí¡e?Ð £­nBʯ äù!’
+y]9¾ÁÕrnF ‚cw¸qvñyŽ=(e-øÙ^©(HFC¾®“…ùQ8ëÂM^L} Úm~ªÐ×8¿xÃVû…aDthÏc(KÌ#ŒÏI@{àÌW&ˆ+¡Õ`µ[ÝÖ{hØf)DŠ‚èeÚ×sW<iÞ—F-¨¤¦ÈÚE”)…9.h&2"L(s 4x23ÿž–7Á˜"<ôãåŽÈ­DÑhŠüBC'õ
+ gšÐû÷¹¬¢ÞS7{,ÀÀһȪºCˆ”é,˜Æ'§ˆ :ù H€bàóá§te´µt‡à£Pm–¡§O~£ $>w€ì†›ÒÓ9tHå¢`Ñ«‰‹Ã ­X"ŠLis@:K£ªiî6(Ôvy K €X³qMVžXáýÌÁp艆ÓLˆrøp‘(Xܶ!˜|TU£dÕð¢tB£¢¸cYg©0ö¡ô}ñ†õ }JŽ\kñI^?[§"ñ*?ý¿A‘ï–§"z¼€¬¬ó
+eí%C‘br9bH‚HnÜÚu¼HœŒôU”hŸ\Ít5#ëk 7ÇïsêéC_pÉŸi©‹™ïBÞï#«É7•½67•È8óÓ߇00‰’Ĉ†ãÛT]; [ÚSêdzGºËñ!¶ÒõD‚£è’="x›9¨'¤ÂÆ™X“üê/Ëf÷¶?ôËÙ‘—ûíO$û÷¿_~û‡?hÁ²$9.†‰Y#Áà0ÉOõó‚ð_(îZZ
+$²½´ŸUžÊ«â²°<c÷xHe«¾j‹UÅÒ³‰$»lê4 ës mä`.0øîu\´¤BnÈ7HÃAÓï*-4`r0ÀA;ûÊ_)9AŒö)*ä•°cÐý0Z‚"wÍŠèŠ#’5uŸ…cꀓAhkW&«+qèSteÕBcó‰7\RRXç”&¡³üpÍc[Nu*ÖŽP½hš _2z=¬.Ãé¿:gð#\ç’S 4¦ñw´Ò_™mZ£6Z¨ûê³!°‘cƒƒê]UÍëÙn¾ Ý/ZŒ’/u?Ù†ÀÈàkŠ>:¼=§U‚÷—3Hþ)vÖ so7¿˜ÚV$Ê}jñ¬â.Qëò%‚Ä7Q™D%ÃE~ó!R2þRÀßp5Ö‡™Êûæ¬*ŽŠUŒJM)å;OEqÚ赉óM”€f0okYoý"*†Kc“­y9LF ôÊ÷Ðx2YÞM/üu‚nCuÏ À€ŸMW}“NÙ!Ò<‰ŒÞt¶“ÅkŒnõ¤Æk“M_-v"ò>sD/Z|„÷@R{¶–fÈchm,-Í7­^…µ`èÛ× »Àƒ•éˆÐRçRÛçÓŠ*&Y>lvŸ ßlyAéá°~FÈçÂĵa”ø0´To¹¼³Ìdø$KˆÉ4÷0‹ŽD
+tNeA
+3ÓŒO ÑçÇB¸J
+h” ¯^ž@Eá/3“cµó"ãp&§)øZÉ䀻ðag‹‚Ø*ôå‰uuÖª°[ie)íUZ2Jm_]ÄÁeEØÒhUÅÐÖ,Šï ñ³£­V
+ŠÇ~^ >:ˆêùmlFà?&É&–NúÈ>ÆpfÅ¡cÑ ’n$ ¶NzS<zƒ̤P_W·8cðzÚ-"—FRfðmø²u ‘aKÕð[3ïË{}<€ð«ËÝA É7öëâ©´uqhõ:ºœJØ7¬r߽܌©êClìŽ
+Œ¸!œŒâàíøx¦åñm–¼Bß,Jt€#èvòõÄ}ˆ¯&4 ÿB!?“é+R;rÛµ`„†ì@Út‚ñŒåÐÿžšR`Ãhx®0üFQŽgœÍIéQ _mÖ» YÉn;§÷È<tÚIö
+:G!œÎùIm´øù¤G°´ý9eÖ[ÃÞOïwç|C•2VÝý<f”ÁI˜·Ü÷—ÊNÖg“(¼ƒÛD~sMvN[^§¶ýUêþK2MYk“Ïdua*÷&¨:å¢;¼ØRֈĄ!Î25;‚Hz1>av 2Ú=°H‚mŠA'8"3]€–‹³_0P‘%€Q¢û© ÊlúÛEüƒŸÀà¸ˆÊ <ïઠÿ€nà’H‘óñO5 l“jy:ÈX9Ä*=U3%Ðòó£=ÝjÒ@~ª°µA—ÇáÛˆ>]C Çù…/ò/}áÿDé²£ù1_k‘„ÑÛLNk§;Ű¸ËºŸomµì¨ñqàNBïîbçHޚƠ+»!?-טOºBüK_~<çëØŠ¹ŽßñR×)><Îuî/ü_+å›G#ðž™úrÝÆm(/)’ñ“½y(—Ž Ëôã‚Ï ´•°0?ŽŸ»€>¾SÓ+½½ÉäÁ…â|*_§s
+®e»Î{éWo…ˆåLHHÓ@×Ï]Aß©i•þú‡   Óiì‰=at&U¤­ú'Áƈ»SZÎA€Dª ³´
+ٌ¯/ÍàW;H!ÊŒxåaìÊ즱Kd‚œC_Ž¥"²] °õ)
+D¼ˆªX‚Çs¨xòŒe?GéŒ×–nUƒ`p
+jŽ-ísôþr!—ìY!¬g·]äÐKƽ±:ý(cvõeÄ`ÊyCe^8Bz>çÖt—ÉA‰2QŽýT~d÷oƒtìO¨i®N»zHF ~+¦K²õá>
+e6fì+wS<»NÖįþ<‚ÈT9µC ~]ÎZáq(û±{‚ve—r6 Õ›a¹wÂcžƒ(2ïQ,+ÐÉì‡à}¨n‰‘¢J´ƒÁ–‹ÄyS-ÃYsˆdò!¶j>o—sM¼ŸÃ³:p%Í[iÂÎï©G?€õ”Â>JÆs“úÔ‹D3ç {ç…·I°ÅÞeO߉ñºdß) ‘s˜œBª{NiªôÑÕ»—¤·mÃ×Lyvåœ:ïí8¤Î{[ïç܆Cæ›gÎ’æTŽC†%æÝ m \tíá¥÷Ed¼Qü¨fç¨Ø!£_¦‡A¢Ëþ¼ž÷&¯6;ˆû;¿^.“Í‚¯ª|‰»çàÆ^1‹gÛA@Ü“öˆ0öb@[ØTòI—B3!"¾7æq KÃZbbÖÑéw&£ÄøtNà&u6šï-0[¡t5«´uyø ›VpuBR•çF@ V„¢q)¾=L
+dÆ?}ù[ Eö¨s¿é!lf$Mš6—âž ¬GhØmª{9A^¨Èæ%=œ<¾ âc ’†íg6Ó±0S E÷ÈGw±Ä#Õ´¬)ÉhÍàpáYÛ®Sy!ë'.´&ýgͺ@þ²¹@·e*Ióé”yÅS'*¸öiI¯x0ÂGÜÚ$½(Æò¦'ÐÉOâŒ1B¤%4ôû ÕH‹™ªøgùð;èã;»ó?{WØz~LÖlC “,¨ÐÖìÂßÁI ­#_DâÇþÌÓø=jÀ¢pÁXÝE‘oFÀ²·¡©²ES®ÁýTM6ˆ¥nv‹Œ0âR:º²‚öÃ&8»¤ÚÎ5‰J§O笒©(M?‚`6ð3¼¹A2‚Óœq¸G,%Õ8ÄœÙ'äbŒ:ôŒXäêãåô-¦V Bvfz9D78››ËÑ”éæÐ:CýËx™$W’ã@ôu‡<,8€Ã:·u‹Ü*ï¿íç$¨êÿaR[wV—b€Ã‡ù`îÔÁ!‰c¾Wl53e´\ãÛÜæùú(ÿÒ&øƒ¢°õ¿"dU&Nl€‹³Â’7½øóÿgî*‘´ù†¨–sw/âê­äfìþB¼},üîiî€áÞ–±´!í#œÀ3­y§Í ;~
+yò“¿E$[ÔFgylJø­,;
+/yÆÐDSu—tÌXå!Å|è J
+,ŒòäˆWO& ÏN“¯®Þ›úV¯^tÎ+º¢Ë¼4zÓ ìô^ç'ü^Oá^Ñá„!Ë„£%ùQÅË âÍC‰¡¸žïånž} (×%ƒjKÐî‚Æ+(fÖŸÅ›‡-@ôI`D•jáæa.½ü‰&×pPo%ñæÝÏyGÍý27ðEo
+@üÞ›`Þ;üÝJýþÊZ_À€¡{C·>d’ÐGsmŸ¾€uÍÒAÑ¿E—x‡Æ%"Þ23*¢ß¨á˜Ú°Ce*)b:~­
++*É’fÖéJa¶KêÀÊ`ÈÈKNse0Fïù@Þ>
+‹Ï%k?I #À”1ºãêûNÀ›K¦¼‚ èiÝJT t•æH£‚’?»…œ‰ÿ‘å‰! $u
+CÚë¹ òÊ›°å^bÄ,ÆU@¬¿ ÷ÈL Fè|¨
+vÂâð/ñK©`Aê§1wä8%ô„mœuزpßNü÷W,áùxÑ\¹‡µÈäÿõ[Mü0¹
+F]ÂNÇçLW 8™–1™†Åì
+\)¬G”Û…fÖ³®ÝìQ\%m íÕbÑ1T <
+!¬=f'ZZVžaõ‰åÒÇœ ?78=Ççà;H¯ºQäq
+»Ð11ÂWIƒf
+†â؃¡­ÇÊ [}ãýVÄ" 0*Ïv7õpi(ׇ¡,?.Ê4•mäH¯óSPD÷å
+ yvøV„öân²®–÷‚BD(iÏ›\ Ž§cúrê»BäÖP›lá¤T^à ¬Lì„)0XŒv˜
+®¯LÆö‡A‰”d”e_Z<pÈmpbßóAñø ÌÂ@iWà-ps2Ç>nœ—<«Ÿ÷¤îEÑP´¤WS?*z£äÏŸðö¿_*—ú45Öažnù)ÿ¯y ¢³T+¢’f
+Šø¼‡idÊ0æ%˜XŸ5îm—ðq´mpÉ WI·™ÔØ&‹"¡ w€½p Ä šôÖðsŠrˆ'¹9ÂR·*ÁáŠ^‚Ý1‘ê¦oüŠÍçVö{¶60 ´êýæ]#2íËüVó¹ÛCˆr%—Q^ŠV ­g˜âù²K„3Ãÿ¶kEŠ,côW<À.y³sö§*Q‰Ðaž_"r¡2eîSp!4N8%°&#€Õ+@8î´$`;ÎwnE“œ›PÀ.íÝ÷…ä Cý#Åwàú/»Ñg1dm®Huþz <!÷Ø¿¨ ª¨XüšcÒ
+7Õ-OT„L¡‘87XÏùK,€²N‹ü
+¢i
+< < ÇŠ(~ÿÔ õ
+„P/£òaR3QÆ-7¼U*Ú‰póý©¾Ì¶l¦ó®˜fvÄŸ]Â'9læ#uÚä‘ü:÷¢ÿ¡ÏÕ²Vì Ži^I·ž#p`½hhÇÅ–>RY1flë{iâd…0v©;Ä`AÔ
+C¦J 53>WæCȼEV—K3 †¬ø÷㢠dFEÀ]ªk˜ù¼;t!#Z”ÞOÈ|‹.”$
+•p.(2:ðÛû«éž¹ÿìeCÂ9Tqfþî®ê* ÈB¼©m¯ˆKx¹‚}ˆ$œ¨¥:4>ßÂËßRdžØazY§íc]lÛ DcØ”¤&©b¯¦4Ç Rf}atHãP5Nlÿ±^h½½(ËÕê÷ØŸÖ”uªJM­(Üeã˜AÎIÓΩÕaÙWklÀ­à_ÙCe¶bjÓẖÀ¼PGÈÂ\F#ªâ`k‹‡k†
+d2áöYÔI¸+¹<?ÚÞÃã°ïôh9/f§àè¦!2¦–ÑåÉ^â+²7 Ûã»QËí>#ÞkÍ•…Q´Yì8AoƒM/VÀT¦$ F+1RU:6±›ÊË366
+¦HÖóýí úl>?Ž¢EÚÐ,×Ýyø‚ƒÙ}9Ìè"e¨1µ’o+=¹/Ÿ‘=K½ZÌsyÁ8ó#Ú]Šµdþ[ñs`9.—³ÌË©uÅÉ’Ceo‡fòälhÙSEÿòç±€¤>–?+žx/ãÅIXh>º-ÛaHè14f,> »ØoxÎMuó
+§Üðø¬_ü^QëX»“5ŽÔ1'_1"WÈ_¥)¬ôÃœ~PÝÆ^¥ 0‚‰ÑFÒ°ÛIP0âK\,Õ7
+„ K¤ JJ©óqÕÕK"÷Ó¿ÞÂí—?Þ~úïZ"§nÐÍ †ú#ÅÒZ׃k½ý‡ß2×ÿ£Š'K·°þÿïÿ½EB+;7.Ý~f~îjB¢ š: 'úHÓ±Žìª¦Âö»+†)Œ‘0²ä\ \tS™Ó+ᆼV•@4‰Äj %ÍÓz‡@&µÑ@¨ “ƒK-ZU‚Ð=™·3ð ÂÜP2VUÖÈ RXé¹k\×—iÑ fV•(uYÕ6¢š,ËŸŒ³O
+§‚à&\ã+’CÔ.âZs€D.ï9åŸq€¬«â]>A y¼<g¨4ôKfÞ e”³Èé¡k‹ò[‚Õêѡ¸ Õ·à4IÀ™Ö îB@–r+¬, 2¤üªJZ'ø0%Ft9Œt
+ Ä/¤6 «¸ÿDdUÂ=‚¤—»8i°ȶdƒYÑÎx¯˜%rU{;êâ)uä…ÑÛ¸qš:Ø©ßzÆuy­$ñÐóÃII‹H¡òÃ0Ëô0pËjébÙûþÙ8–nô ¡]xç©xðèð‡EÔN—f€%Ü5“¯Î‘¶u¬Ñ!UAQî!»tÀRXÉÔ·î±v´òÈãªášÖÛ¯@S×ÖbH*Ó½ø˜ï]BÀfã‹ÛšØ+¨ðtôM1¥ ‚€¨¿–š©@"sªB¦ÁKyäÚ†Ñ ¨Yþñãõt@èoDNƒú£ÌÛrEBP3ðx°^ ‚¯gª½†@ÖÈ|¡í§|ø5DCÑVØå ø2úUï÷×ò2VˆÉ!2×ÌažÑk‡O”W23N Ré±™¬¹ÆðŠš]‘v™–+b¯g: c`â¯a•!Õᜧ4qLƒ¨—¨¬Àçí/'1²‰f±ò=ÍÆ‚ Ú”¦¬LiÄÁ+Ê\Í^Oþ
+ð{žÚt8äk«Oyš˜Ó]&ïZ˜Ã?—÷
+[¤×Š• ¡t»¬¥@‡Ø×Ã!•°¥Ï ŠdRÄ™³k¿„À÷Ô¹¿œòB¹M÷ÌÜ9ä>CsõCƒê’©àNðE Be[/§^>!¶ˆë!Ì”$«³nÒv`¤S"6<$Í¢" ¡u+1tDˆ«{4q¢<–Õ\Î+]C$2»×I i—ð]¾[¨ëàèl3s ’.*$ŒáÙ7ý˜’æáa´– [æ4ƒ¦•‹;ÕtQccît0 \H!ØZ|Çœÿ
+¿è§0‹Ä!+¨ùU…"ój1ìœCv¢8—{÷ÇC "'…˜R‡¦àÕ7=ƒ ?Ÿ9iVòúñ78ˆ.ÛxP(0¿’‡A(zÆJÄ´£XÂZTê%:ï«ŠG²
+Úç¿`èñ
+–bùF”Â0K㜠©(s_ózÁ«|ÉTrnÌkÍ¿8‡jRdÕ¶çfÔS°RÙ4—¦ñ#ÇùƒQ ®­üâ¾
+Bb†ìq{ ”¥âˆh®ÝYÎIÇï(Kg‰T>×ñ2kfÐõ^лóWÄÌÆ  V ©í›zæe’ÓˆA]chDZr‹+ˆ#ëþdþ%£¦!{T9RªÉIûŠ›–¼À;G«OBÃ.&}"³×íüŒð{ˆ…Ú̵ñâf8­ Ü'®äí$@Avåqc(Üä9XÜV7KyЖâROƒ°¸Úä ‹u‹÷`»¤öÁ2e¬Ù6¹?xwMqaj7:Á <u"Ï­e'8Ú yÙ|s¿…202“¾¸LhwþŸñ2É+†è |ŸÀÐ,j,s‹líûoóJŸêÀýÙH6`7[‹5˜ÌöñþúZåIJG7dšáÃæoó*£Zœn
+[3Òܺ o$hå &þ¹˜'æB
+Y Æ‘L{¨¾(V#ÿWa€9PšÅ‹Æ"É#câ®uè,¢£ôÌØ6ÐXÛF\À°g ‡½HíbÇÍs¸h)¿EŸ^²ùA€O²ä¸ Á–$^äYðÄ!Ý$1b\qSÿ¯±mqNãÇéȹ
+)²ëi¹ ô‚6c¢nöZd4æ¹¹"cÄQJw=ÄJæ»Ö!3
+r´8ö·'<Å­QÁ*Oݾ冚èJ7ôÝŸ&
+WVìÕE ‚‚eÙí}—LŒ@ïžÐ#ì`+¸Q¯WɘusK2/–ðAe9â)Â4!%Ÿ!&É|á¶ÌRÒ
+½£ŸÓxÚ"sjW ŸaLñ×ÓWÑA14ü‚á¼EEøðÉ’G™ãÏ·h3œ‘ ;ÔÌw?òíðøù,é\¼`«¥ú£þÄL¹Kç ÌCÔNBì­¢·l6ï
+H‰ ”iWš‡…ïêjzÍd›¡il†›eÕ&MMj4Š31&Š*N(‚ÈÌ /(³"8Ä)'PÄ•IDTDœQ41iV{Wï¹|;çÛ>û<{pÇó@±cýÒü¾è¡Zusk—¼&£HY9ÚÖÂhû &g¢å`^øŽŒ=Róp.%£hCJL´NÓNÍlðÔÄNM`]`…†<2Ñ«Ý&6Õ¡gVVÙì³Mžx}—´.²¼ÚfÑ3—»;\7ÃH½±Øœ¾=ˆŽ=RÅG:f嬰4|¥‡ïš©G¸fÉ°µ~äÓå®òû›2d´]‰Ip¨åZà14q¬SÌ
+—¾‘ëYlâ:Õõ¥=XçwÎ>Ä;Õ”C]ÜTP27¤ôÌÕžºg
+
+ôû^LüµTìÏ¢Š'w:k —;É…If@pë5v%îÐp°.=rdd \jB¾[M/s©é…fiMÜBgÙƒåBêÁb“È>O£Øçj÷Š€·7߀¶kY¨½!Ïgw8Ôµo7äEQƒ°&¥“>[-_mM=>SåÔÂ$ytøÜêùÎXTÛU™½¯ä£ö&ÙpǯÂ&§CÍèG`îLÆùÞZÈwÄŒ«Š†Š­àíTCvèž´r8M}í™!¿:TQrœJükÛ³ÔOK‘E£,ðx­Gë15
+|+`ð ŸQÀtÏ71÷TbP!&CÚ+³Â6»¨Hÿ,«z£§â¾µkîB?Ò±àWÍ¢›ŽabꦜžÍ«J¾Ú‰I»u¨ec‚÷”¹TøôõÁÒ_FYY7†@ès_EÔ®‘
+*“
+".M23"¿ZەDZȧáýz*Â<€üMÛ–sÃ:\þÄ«c×¾'¤ü°ØŠÈúbjéÿ´$æAÄ‘È÷ÌPrvGp/Wߣ£Õm5‘Ý$XØû£{œWkíúÒMˆ]“¶û虚¦ŠûíU‰—ÄE¿}ã” ‹mˆ(cKá]Ï4>Ó«¡WzU@Þ‰,ýd¤õ¥»‘†wˆ(·’G93µHög(°õ‘ª§¾EÌ·DÎ?1Q‘o³X_7x|ŠO èz¤‡ªîÁ\CÙö ò×õnø=cKî-ƒ(çŽW ”©ºË_¢2#ΉÏ/8¤õÄĵNLôf:&ÈôÓýIbºGÃBy´|†©lʸ½?~õÙÂø—9ï2<Zæ2ÿÜj–. ¶FkžJÙùq¯£ÚŸÄf,5ÛCÕ‰v*áD‡‡íÊ+ã—ÚaáR|ü¿-½¸8 %;’{:ÍËûßâËtTÀ ‚s¥G;Õ´¼ýYZ¡C×HÛ™aUêÀñ‚
+é®™FÌÁdfoŒ]hí£BE?“3B´lh¨SVñ»­›nîDÆ,6—ÜtÏÒ -ÒÊ8soq„ERi–†ï Ô>óL°K?/ñ™g6×gbî%éØÔÈÿ²dÑÜ6è7ŠšÝ*nµw–SPóë*!m«š²Ù $íK%+mè˜ *4Tß”^Tô@-(¸©!n[ú
+2‰ Ã}U)æ^B¼ ¹û ÜV°ªì½å¡fIiàœûnu
+؇F*bK^?/Í 5
+Òü½z
+b”‡ˆ æ„xu,ü¶š‚ðÈ Ÿ\#•Ÿ Íùoå´Ô{FQÎï–Ž²˜=-·N-AÆÛ¿b  £ñ--v>׫ŧ¹ÆБ«²ò°ÃYîôe„
+’Wå’á?nO «ƒ˜˜µÁâ0ÏXñ«µ¯°°myY쾉”y`ä`ŽMìí):Ü«$¦©¥GºjèÞ4¾£"CÏfÙ¸]- ±4Bü
+VEUÞy4ÏÂLãb½£èW›ãBÒ\+öÁ,„ ˜æßÔ6•Ý5~¬]—ï´"ô}iuêo}øœ»_J»°­öâŸ:‡ªÞzT@öŠ´îÝ7ÿÁº¬&Ù;æ»Ô”Ôm55Ç®á¢Ü3ꑱEèÑ5‘m¸{*y>½¨yoAÄw«ÙEkBä( q­½8Ìo€ï¯a °*nE…^¨K ¿mí©ŒµöbÂ…YwL]y!‹­¹÷†ø+Bä«_åu‰SPñ= õù¯61:æLÇÀ¬B=Ó7eé‰×%•Ï~é«¿¤¢$ÿ¦ä§½¸Pxɧ!Uý02‰?M,Ò÷Ví¡†Tà£",’’à™6t0-?þ†Ÿv}
+̽­2&ywL¢ÊÇꆂ›ðwÐZëÏÎŒð[lC=€
+B¹y/üÈI!þeÑ¿O°ÒÖĸP×8)Ù¥¬HwŽ¡ÞŸ.€UÇ BÎDÁ¹[â›#ç¸T„÷ƒÄ¨â‡¶àœªšD¸÷Ôz5ŸÚöµ ”C³Ë±±ÛÊš¸½Yzo–O²HL˜ó‡u€?×NŽça_/v¢Cm²âWž/hØ#U;Z Û£ãU·ÚŽ—yt›’ïå¼ZJѱ œ[¡Ö陥æîéA´>ëP3Š*ÒùÌ· Ql#Ĩ-wº jÙ×6Ñ\j^¹CÙÍÚi«Y—²ÓÌ}¤7JVNÐ0qÓ*#Ź”¼Òý).Ö Ï䞢ì/¶Švç8 ;3t¬SälȪ"÷t`¹o‘Oý
+w°¯&éØÔH;4¸»såHËÆëš‘G(™×§ n­KÊŸìO
+ðß[jÙMnQŠ¿„ôoðDcу^|Œß9Ö¯³"òâgb‚ÿŒ ,Ä$’WúIÑ“mØPõÏ K.ÆÜ‹yûè÷RÒµ VzÀ¼ ä©©³*Æ*¦%h»ˆoiyQþœÜwW÷ÔÜæ :Ô1Œ}i#ÿê«
+÷믌ðÓw”=ä£î'„Ý»HO¹¶&®}½ÐZþh‚üs (äd¿½Œ|t!óï[ÊÂï_bã/gE?ºHL|vÑò~Çnt¨]Š~bèʽ7Öwµõ·Ÿ¼îå’´1d+ÀŒ`Cgiôñ<X{4Ç®÷¨˜ESô¼mié“ NÜ sê•[Å*‘ÑŠ#,rBÞº ûÁÜUe—b|ð%¶†ñ SMÝØ7—l2vÖâGjörwUŠ{„øa’‡Ò°bolôç„œ,U§ù´Ä4«¤6(&Î7×D5Hh…;“T4l êûÝ̬=32°çfèR“³aÃÜ·+H3¢gœœ1Æøps‚™ùÐ&©Žr £¶iÉne[ýöpÊ­Üš¶»‚_afæn+¨Ép—ElH÷ŽQzêþ¬Ü¤åˆ«“ïª ßššÛ·Ä¯v±‰å[bájBÜî<«æÈ lÈÉñðŽ`aC“\£´Ü-iÅ‹Åö”ÎQ\Œ[CI·ªÀ<Ø$ùî °pc„üþØÈ©?·Âs¯¦®Éˆq®/Ä$6‚†’y¸ÀÄÿ° {¿®pðÌ•zg™˜ãef{†^}ll‚ÎVš¡Ÿ~dàRS ÅGújjn>_¶ý4ó9gK Ö§‹ÜJzú¼O–¾ú(½¨üÁÁ,9ÓÛ¨ï"EnÊY¹+âº7›2|ØÖö…un—‡?U†Z%&I Òò™•äo,Ù”WGÚú1!9!bGMÎqO“RVGÊà \ø‘Q
+=J6bOũߦ”ÚûП[²Ãé9÷d„ì'«Ãhc°.ñ@ÏÀ¯ðÙÇfN à`ÿ"Ÿ³£c5iEžqBåSsµ¾ó]†G^Ÿ¢çg‡¹‡áO5@}#µÒ­lÌxèµ{™ôÅLGo«ˆ6icÒJ7*Ö£Äeï«)UÇzõÜ*ÿp‹vÔÍyû:JÅé
+·õÜÂå_¬ò$ß]‚öoèÌÆçüáhkûº&êÿφHz §Â/ìñÂ÷§zzÍú:ÑÕŒ^“6ÄmŒ`ÝrLòÙ
+ecÜJVõÑ|;w{’_ëUR V¥5¬=ÐðÕ^èmÏ(!Ý%cšzÈIÎRê¾VD´£MÐuóû²ÐII¨o
+Ÿw¨gaü Bžß,îXQ³–Gˆéû bà_>ÿnù0rjJN—Ù-»z|áÀm3H-‚ÝÛž`C×ä´b›ŸbTÿº!Å&¸G(y®AlŠQR¶)gÁv4]|€Ï`{³Ø4k?ä®­·üö¦¬6î`Ž^µ;ÏE;‡qI>
+!D;È̘ë!<wÈØàåVÑŒ9NÃÜŸ¤ácô\’½—”íè"&›;¢´<Ì#%~Ý$yw_Æ„Ýã•&^Qâó¯ý¿o«c¤œiV¥wVÔ´6ÛÅÔÓ»qo®iyUq'&zKYo­yìCź•è—ûjb}ª¿MÿéC];º"̧¢¼ÛW£ÒÖG*š:ËnŒâÒ¥¨Œ+òæÜ[/2΢`A1¥i! ·¯ýíCMfØÞDS®¥³ì¾Y˜{SEˆ¿Â= èAgkø¨ˆ¥>n2+þRìù#¿®…öÝÉåzeðg¶e¡º¶¼Ÿ;Q—Œ°8ƒÞPø,˜ Šûû·eV˹©µñÔЊܚÄd^…Ê£j/°wU<›hƒÆ×§Þ œb–$›8¸C
+7¢ÛÕpûZáÄ@¯¿°
+ùI#±Ê.€Y¾s¸Úñ¯‹ þþåáÈóÓ0@¯„fWŽZSDˆîòß^ÅçL¿%T[ˆ[󎿪!cOë½÷,Ī{üÑ*ùû¼‰ñò" >Ö›š‡; pˆ'û¬AÔ6Ó]o.»Á±“¨r9‡È ¼Kʬ‡”³‡Jí',¿k.ÖÛ‚•ñ:ïâ¿ÏXåÔ²v9¸Eíð,ã÷¹ä¢œ,{rÁ1ó®äæ“Š.Ç­¤ÞõÏNµT=j8mâ“ÀÎŒI€Kšx¸”ELK94âc÷‚2n’Þ/QËÖZļ¡ÉØ%dl_¸¼…ó¶ì)§!)tq¤ZiDdÊZP4}™ÔN£òÙ’$×Âb.„ 7DÎú„ŒJX Ѥøê@Gï*"
+nÎôW0o(:BÎÆÈÙäjX³V>˜ß-…”šŒ­‡5«#ÅB-Ì¡`(´ÁyÖqZb¦é—¨oføSRýá÷ä¼ã:¡Þ¾ŒÁ›ga¹¦R(jXÙ’ Dweƒi<^Ef¯c³†¼…Þ~¼K{Y£<:ÐR›R;“¿œøÒ’†Nƒê¥z`Õ“t,ªòV9¥äP0ã Þ®šøη0ùcT7ý$oålsbÔ¹¬­ùe¼ªŸÖVróÞemŠ[K~àôýã÷ W}sk¨W»S@–¶#æyvÈ ¦ÖDm±Š!ßÔš\ôÕÜ
+vÜö•Ô›Î…©{G;|\Æ3}ËÌæÙ'ÉØ|ì\âÕ¡LQñI¹%¯„7μŠéY-y»d¬ìUËQD-.ì+At_<Yõ@Ó#¡õ£­™gfå¿V)¥9f€)¡5¨-k‚!ÁdÅ'áæö%%¿pòSÞ:É5¿p¼PÏ×Kæëã"ÀÀ¡6rKÆ0ҜܽǺUÎ.Ÿöëø=»<Ü)æ˜'$6¨ÍYÃøÃÃuÒdŽð-Ö1~¬{xÄ:–Ïé=ð]b—‡Ï[˜äË0‡|ãÓ/Ž¤ŠœGÊLÛØ?Ÿ‘¥ÍŒ[»œ°ÃŒŒ 
+.)ï< ñ°0˜ÒSgÌÌ%'Hª!B:ê˜éMëÇš±î÷¤ê"þ|¼ÛõÏŒqô~Õ‰y$ÖµªX^£~X\.î=2>Š1 ëe]Q§õØÈí? )Tç‡óÿç¸<Û8ï8þ¢è»èBƒ (.8ép‹
+³‹nÞó¬…ÿ4¡LflÈ’p}ö²•‡7›.€7Ê ºAJÄŽ÷þ0-âžú+%›äuÖ"}Õ±'⊕Ïê^êÃ&~°Ðô¤Î±x¿hƒ— n;ëRl.ÎÓ&.eT|¨R*~áfÊ@ýúÄÎ[­z4¢¼çÈrlÂhQ…ôIîbô¼°í6"u\–Ý»S |éË÷9æúeؽÏ÷~V9òßÖÓ§.îÜE„·6J°Iýk¥Ö 'gºêl4rnÑÂz•/߸pIçÁ^71º1p»u ¬¬©ÜØÍûQ‰ä*«´^å!Þ Ë¡6#ï^vbàN7&—Õ½RfH Mø´ò'I‡bëôXžGQ´€¶ ùn\ºôigÌõVýˆù*$~s#¯ß¼}EH ƒ‚T×Ë9íˆh¯I­
+Ÿb{½c C4_«)ôAó]ûH%ÆPÙE¢Ö|â¢\
+¢Æ)XÿÀ%6>‘Ѐ?Ò_ÎþÄÎY»}Õb½¨Þv5ºs.”ÆLdŸÖ´xl6¬elRƼꔦCzß^Ês$ì³ßà[E®EL`}Ä\cÝdÍS?U-
+ÜY˜¡ÿnñ!õãíѯ)ó‚Ÿ[¹Š‰ó˜ÑÞO«Ì\Î[ ïB˜~éÿÃåõ–fž€Ñ¶'™TMÔ$Xl$Š½¡Æ
+ŠlQ±ˆT Í|tø
+,?ñûvuY2W,èî¾k™àfm« ‚jˆç™RàΖµÂ«ÐÔ‰uŠøÅ!h94 ŸÚ¤ýÛËÙ¦Ã@ß\6Ò=úù:·z¶pÅ`l6«WZ!è G4£Ø}â)WSµ(÷&Ø–<
+‘óœXG^[9ø Ljé$ÐPr¦,oE­ÃWaéɺZúýÚÛ¾mq;ÏÜÌú£Åð¶ÇÂ÷˜WY*™Ÿ,¸dG£Œç-d±7P}#®§¤Ž…Û8q¾Q–˜T’ŸE´Ùwùƒ¢$HV€¡¾cŸFx¾¾ ¼Ú”ˆ¾¬rÚO}‚ö –»\¡ÑhoÓ(í8ÚÛ®˜qa§8–‚i¶ê-›Æ/ê"¾l㥵7°^jiOIø¶v?%Î,ŸÊµIçÉŽ3wÛ±¤ýý²ÿví%ÿKçþw!7ÿ<‘ü}yÿõIë¿Ú×ÚÎv Åþ† rY—X0·égTE­ÇavŽ[P•]±Pî3ÏÕûLâÚcïïß5ŸÇ‹ð×íyyÀíQöiµåbZ¶ø•Êœ ¾é°ÆŒÒàØ¡^ý=BíøŠRZTcýìmB|3%g<yÑ’ƒ¡F¶Ô3nÍŒÍ&ºTÊú#'Äü´fµn®ÜvÇ®fѲ;*ZüÒ$Pü$NÎþYÅàì¿t'p†ÜȉÏsæ€9¦§Ë@jU="·èïZ4‘Éh2xþ¢T”óÂhCþxhá°çhÕc¹Ú†4Ÿ<²C×ÜðŽ–Ú–7¥bÝYcú<w”w–Ñ9¸ƒožjnÕß!µÛ£›šõèœaD² ó™ˆÌ.ˆGQAÔít€Éî‰lk‘ÞcÑŒÏ\JMõY@6~±-á¬YçÈ°j¹U%Ûjœ¯Nð63D²ïõ¢é¯UrÙ1a†ï)s–ó§&W²™Ãp|3AxŸ’™PjsIÑ­õL$§›öªVÇN<Þ¥oJÙåÚó¯ ´|´ù½>§Þ°?FTÚ£HwÅÕh¿qæeëµrÑJ¡”çÏåp·Ð”ñöf¥‰õ¸®r$2-ûKCI3Rdzàô¢D+‡ke”D˜F«ýnŸ 6¯sôÆà¨TsD~xMí5ÇwõÙ‘ þqvg¯ãú55$=½5‚Ъˆn é#QTð(¶
+ÄÄã@–ˆ}Ù Þä‡3ÇüéFÓ.7è]Ò^|PëN×gGwÜÉ’=8¯2žsò³º>FàYqùäôŒÎl)óæ;’õVm“!,¿ŒHJí˜b"·r›Ôhh"¯Eõ ¬>°­iÖEøKµP³gá÷m¼š ›®Ñ0f”çm“ò£òA–Ùܾð˜Òïˆíî÷=,ÇrBSQï1 AJdf_ã[AD ‘Õj¯=¦¬Z|+ E‰®©eÇY”&ʽEÕÏOsÆ?>Ì
+ŽÝò÷Û.Öë
+Ë»:£åã4dù]"”ÔÑÙ«IŒ1G2grû5µ‘F¥jŸæPnÕÕMÜ©ªì¹_WA@ÂsÓí?ü
+ÖÅÖÔèŠ檌¾NÑâi#Kr^ÜË=JÆwY£±õ“!u¼PLé HÈxnÞÏ)ɇåƒä,ˆAâAõ[z„hšnU9È;Kê-“ï·Û8°50!Óîwp—µ#âoxGÉô퇕M󡘢!PZÉ ©ÁÉBó+ø Ý ~½f=NliY£àU6 ñ
+Ck§Èè•«Ä Ø2|îƒf.üèÀ§“®Ø•d½ÅÜ2 Ô‘YÇOßÑ>Ü!ô¢±MšðÔb¸÷Œ ^¼ì…å"DZ>Ä¥€è[%CdW*BPù vêöðõW rMÍÙ†zþóºL¼ãÕMÉ„ÊL‘ȉÎî ±÷’êÛÌ‘ÙXQ8¯ŠªnP†§¤v€ô7}!eU¢°œq'¾܌ƀ¸Ä6’;îÇ“˜Ö渻ÌmÚUö¹6Î×4ÊC߂йdšQlÕˆ4—T¾áïžñwt÷Ønü{ú^Bç{ß=B³&¢¨b&¢
+Ï.C<|ò ÐT”NŸÖ 0y´Á¸ iàñR6æF³¯"šK§hÐBŽf‰ò ‰)ÿ^zÍ|]E†¢
+Ù7Pùcl­<¤²NšUÈ}„lBdæÑe×[v <I&ƒÔ6â-e-×½õˈàcžò‘6—u#ß÷4ößNµ|·Mi:ãò•WÍ#3§ÙCœ`bw¿çAI};3§?üI" ñ,­$¢{AbFÈ(b‡g”‹Ãóð†p\—ïÁÐäaºdá#Ѥݡ–³‡åÜ'¢aN9,þŸ¡òàJû@
+PeOÙ{oø󗀊+j]ÑôÚ$½³w÷îÝ{÷eÎï𥎳L _ïdªŽ`îÉ“·ƒî+¯[ÙgÎeÕÖ ¡eÕtHÁƒ1ÈýôY먧ÍRH^%-+§÷MA5«îü¶ã}:ñÞQ¤—:á ç(4Ózd!RN5Ú(uµ)””Hµƒ ³3O±”íü‘éÍ;ïpñk­0Í7ÅeDÈãjZVYÝôZN3äÊõ:h}§øB]ù;œ’·0Q÷c2ºÏn˜í‹DµmsZ¤Ý~7/Ûo!q7ž}7ºÅ—j[ç²+›hçn¾…^¼ZÉ/=ã“CŠ¯Ð†vÍâxÒogD¥¤M³#ãžïLzøo½.ׄڲŽç*RÍTŽ·˜@nâwk:$g/Ï*x ƒÀz.t¢ì—^ÂTÙ¥/é_6s¯cFùŒYóC·ZXµáâ´ìí'1öÈaD2½aƒvA‹Ý¬îÐÚc8¾v£ÊŽ”S˜ÑRc©¸ã¾QÞ0éaö\]ý|C—ð|kŸàûÞ1ý$ÉyG æ³™©ZÑÒ[PN2Öat²}Í3ù* (‰&µy@«Ž«ÌÉ1ž,Ù86åùéÍ[Å_*ùÕP¡+ñg< ¡wŠz!å/©ÐòFäÖ£1HÎÙ£J¥úwÉ ÈñpÁ<?ÑtÇåG1­bÃ;SŸràËV
+dÛ=“ÌT%
+«¿ÛÖýŽDPÜš¡¹ò Óλš¿V"òÀº
+K”Ü'3Í¥}tÀèòôy½–ÁhÂoE5”ÓM>í¿ÎÿŽÊÿì ¥
+Dš”à ÛÀ…ŒÞ±´Å4°ãÒá>ù”„¿/©þ\“«¾¦8¸=7½ëÈ37|š
+¾¤yS;‹œþ´[Œ éØ- z®>(./΢7¶{4ÒƘKŠLúµ„”OOÜZ$Çió$)cü–^˜;]—ÿ½%ý#5ƒØ6÷lé~þ´H‡íz­¿„è­‚¼âåôìDe´5k£¼ª‰ûNéÄ]Ÿjª(b“Ãã>ãD&ÀíY÷ÑCjá—%{ä4-áüky¦ç8¶ödq²î€ôz/Äý¸l ¥,À‡ ljÕÇïKº¹ð¨ýÿ •ÙWˆÆŸúÖžyhO{2Ód’I:™¤‰¦cœÄ,¢Ä¸K\ €‚(ˆìû¾hDMbDEdY(Èê";(:g’Nÿ“ò|ï¹ßý~ß7;°öa$ŸU%ÍC*Uu›Å5ÕSêïi é·\áûÇSskíó‹Ë-+ò÷{&ÕÜÙ®r;e›n2 ÷ì\Õ/[¯úÂ3+ºÝ+ú—íä–ei²Þ¬Z!ªäüBÍ«Òåñ9…Ë-×#Gˆ_€Ñ_щ¬Hf§¨«0³JÃðë—ÙqïuÖA{“µÓaçn>!¢€7ÚÅ€¿;çÛUÂônˆ R:üÞúï&Ÿ÷-,ímO¡vÖÙm[rzÓÆ;zÃö*¯ÙeœAÄo¹É
+\CpüÜý‘ð(¬§ƒ¢rWTOœÙèo2V
+(¹‰}–ÐažGkÚ‡•˜ºƒUÜ£†ÝQ^lDPÉÉDäw˜Ãe7 žµ‘j¾£ ]\|ÒÊMèyà Šòj_Iî¬ãŸûä£|r죀ŠúbÏ(Åy5²qRÜÒ²:RÖ«Ç–yÉ©ŽJ ñ•®›9ÓdOÉ5Ž؛ýx*/¼\Bщ~•X~”³ñ‰E÷”¨èŠSV,n¡†,óŒ€ù=Gûf–áF7ˆÓm!&e¢ÂM˜îœƒ.8ÉCE']»·z×XgÇuøçž…ž;'°ê'B n6öÌÊÛW ø— uå}Ž¸à玵¾YÇ£JTSÁA_ø訢‹?ÙF?>ÞÂ>«øÙÄ«0›•±£nYרVw¨C6æmø¾ÏLR.È¥ï™}~ »¯y»’2N4G– ßïKÁ·vÄ}7ÂKð R_ÅÍLi0ó4蛨a”¶³F"kˆ»AÅÀmÿ‡Þa9èÖÔ±ÿð§?Ò’‡‚ªìó8—ÑÇùÞ”ìH7Ü”u]÷ËzoÄÔoþ]Ù£¢«ñ镬ƒ;±H¿'§ÕW!¡4m Ä×ú+;oÄ4àûÕOد{ôñßx¢¬W Œm1“öxq_º^ /X‹3ŠŒOÈ;±1†ƒzü‹== tâ‘­$v¢v6aŒmóE7›pác’ÏÝôɲ8tá&C.¤Ö¸ò]FOn«eÏ<pÝ@뾓Û`ôžj -Y#¹3¡&5Ç×&Ÿ„”¨‡&N÷×£›5óñ'zrÇÁ»ñ†Ü&±«â õ—w='ëðÿØgÚ®I ÷þ`çöÞÿâò¯¼Ä¡”öõ?+×ÒÈOYódkÞÁA"jr‹?2L4g¬¤Þ¼:TÜÁw& º¸jð§“ÚâZìã„žØzîaŽ•4xÞÆ|“6¡[ã*d]piô‡Ãµ‰ÆŒ™ÚW zdàë =¾%´Šj=ÝÀRT}p¾û¯‘EÐ×áÛ‘ÚNBKZ/ÿt¸Žx‘µrÐéå©ž
+v:Ä»:4ð;¿‹)O"Ë#-iíÈ“² Õ\°Àž¥6»¾ô`E'¥¿äd–wÄœœ}J¶ñ±14 >ÌÚ­y—œñÈ1öé±ÝR°S ÇÚÑÆÀüÀMŸ´çfn ñ8¿j,ÛI}µ2iÀÓÛ¤ö¬“…HlàÚK.²` 3fR_zû¢hÁ
+
+x¾#¨lÈAMy;n¤êçñ.}ä±³ÍágéMX}p ý4åàáÎƒÓ Ÿc’µJH4õ ØY7‡sÏ?ÑFóNÚpîÿ—‰7ÛkÇÏœ3Ó¹ÓV[íu«ímokêVQ W„†k‰ Yd•MK”–nT-)Y$!"$–lö%Œ‰„ÈB,5ν§3ÿÈüæxÏ{¾Ïû|?Ÿ×ÐHß›âc<ëï}–w=»ºÆª-YMÜŽíacœòêXïTmÖöÖ÷‡jx¬º,ªyñ”|}¢s4ÑŠóŒó‹|Ú†ÒÍAbÔÖöÙŽ i—Sw•¼Ü¥⋵>Jœ_ÓN»0¼å~ºØ­­˜ßeÞ™k‡-½Ë¿¿¯däyt-$§ššbFEÚe•ÏýZ40ÃÈÝ•R7‡ªÁk"4!6`à¦F’}—`‚‡Ú¤ÅOöÕXGW÷ë¹ï-Ë©"<ÚfÀáZ({*:Ô*!¾
+rêˆ~OD_·Škr.:;Oõ KiÄÂÇW¡ëý©¡þL©‰™г+}:6Â9ÁÎw϶1tmÌË…ÎÅŠ€â›ããݳ¼òÃiVvÀT‡Ø’b£7D؈=E#Ö£Tf蹇ã؇¬:våsñ#ë`u°/eþi¼½äÞ¦”
+ÙˆS§òr‡û¾ÑX01Q›âÊp×µà|ùm§GW_¹¯¢¥ï ãã]#˜Ø59õÔÜD:Ö×c·‡ª@dzŒ\ ³âÝaRºo’–³%*‹u*«¡612Ö=ŠŸè]9lU>=1·6™š¨ÇsŒb¯‘sj0`«óòpŠ‘{4Ç)÷›¸È9.ît•M
+Ú®Šqi¨P€cü£¥fŽM t††ö»–]}<ËEé¹åG@'Yå(è¿ð¥8t¾»òá–˜ ”ì)™["B´g¬áaÃœ#@®r\”CIMZíÇG:w·iI'3­4»”šâÓ±àþÙº¢}=ïBO+º0â §J¦MEOÝÄGê¸ãi.Â!öT‚7½ÍV²âþ6Ó’v=0Å)òz1.AÊ/¸}2ÅC].p‹¬²#)Ý1‚Œ\ï.øiýCÑ6 -yMÌËXýBx¶¯`¦Ù¤””] æ¡@rr‚¥õdµ§*Ö¥¨‡[ú(‰øß®H ™×g›K¬|*yb— Ÿ{µ´lç$6ÑYöTLË>3½ì*è¯?Ý]ü˜qÓ Ì¸9ßžÏ!ÁÄLÓ³,€G¨x°«sŠÃΖê k_‘rvÆ5 ÷ÆtkÎ 15éêÎ ú…g’Uä˜êPÖ¦ÙŒB×âÖ0‹U|ð 5?&ØܺµÙ›ßg`Âݺ†ŠÍ¯Ì<ÛWìûš¶ÒH?Ô“a5À[YaÔÖ`Ù£ÕäC§ê5É*¦¿ÚìG<²IÃèó›ì› Ð`À•Ÿ[Å•q¦÷ðÛ6쟠wd
+· ¡@k ¬?¶„o}ºº¢}]‰`éÒçœ{[’’žY8tï<fedδ2|ÆŽ®ÓEaÛ,M¼Ëy^­K‚ìŠ ÃW>f…|ßî<ZìèÛŸâ“f^õÉ í31Ñ~£ôb…:33K¶ÅåÑë½esM¬ó%!;`þ¿³p‹}Ó¬ÜÍâG>=«àp†]àždf¨ñ {ʪhó‡Œ;Ü´«v);oµŸòrécÕ/æwȆ·ÈЕ\¸UÌ
+Ð×p§¢:Òü&ëîFoQ”CNØU†­}AÇŸ»{\ªîö¥.h®“ ¶ôá“Ïôôüãibš}³Ò[.¢¥ßê#Co_.··ž.´°\Úšß´oï*YÑ·v‡²C½5É{¬,^ÑÓ¿NuÆžÌ×c\2d” bg…ÿƒ“þw%õûÿ(.ó·$°5Ž?ÏÜ©Æ›–F©mXZZš.¸àn"¹‚‚n‚â‚–û‚¹á‚¢(Š(¨¸¡!.(¢ânÎÌû4wþ’{úÎùáœ÷ý~?1t
+c¢"È1P;ƒˆö°û•./yOŠõZkuQW…: ²ü~›kŒw¶(Š“‚´‡ÚfÊ›km½àJSJ:Vƒ6Eñ.2®ŸÝ”
+úù­±‹ì±ÜŠ{¦«K~òûjë
+ô™®‹à?QùÁéûbeé¿UÕÚT䈽á7ËPF yp2‘s®ÉŽþŸ©œ§n'Æ–î,õÓ‘ÿÙú2{µR×b›bc¶%X7MUÄöÌWö3õ(¯«åÒüjÂû¥NbØ•¶œú]Ë'MßÏrp ß1§_ â¶0й&ÄmÃó13À~]’ÙÆIt¯ xì Çš$ðõ^ª·¦ç¦þŒvÑT£ï­6“ž›G9Ñ3ÍžººTW›ªèÞ¤(Ê")=›dF€Ù„[G©þ w_-µ`]Às&¸‰û²¸¡ Y¨»=[óï¥ÏIp&ri ;¨¿0ÂNߘ
+ÿSÇÅ_Δ’Œ½¹¡óµÄ§Ç£B¾±³0îh,'êPžé¿,Lu[b^숩`ÇyÉ.×~>œd§ìHsƒ¶Åœhë #èX†¹;öb£ç¾ÚAð¶*øtëDuÎ\ÅÝØ÷“3¹hC{¶Ÿ¶í¸Ü”á®oùè¥oŸͷ¥y©x™¶ 6z£‡øâ[wº÷F7nì$½úÖ~b‘`Ü7ûÓüõÍ©Œ"2ìb¦Š¥©û®L¸rüØqÿÝafØÎ`Nð!p‹•¢w'3üÞîhÊ:ÎIæ¢ 5ß_z(Á7Ç‹ct ÖzÈÁÛr.¦‘éZŽ}ù¯ëùòÉtqÚJwl²"æ¡ZoF ™$@Î5Ø
+‚¿£ˆëu .!Y”%)³U‰\Àøeˆ;ºúµ
+ãÎfø£ˆäcìÄù˜:ÓývûIq óƒ—[S=Ö»“]ÿ1—•žéXƒ(Ýýp‚}½Ø,¼Ö76ü0Vº\ÈO
+z¡ædLaO'‘'J:â`”
+þ*q¾í¦iÆ>jc~€³‘n§€+
+ðÐÉTaêbS¼õósu Ñ2\eâ ËÍ +ÍñŽ³ŸCn/5'Üßnc–ÄÖ‘Bk!ßÛʉ¹Ô§œ]lžÒÔÄ?7tOé¡OUæìÉ‹“FJ?8‰Ùȇó­dø†ˆd–Ða«Ýd˜ºà+¤‡9tæ#_Ì•Q7‡éÁŠrDZ~×(Ló²J²ü­CYþ–±lxqWY›}¨nI‹¢´5¸§35ho};>l£Ÿ
+'ó`23è@E„oI½6úÒÜϵܬk}ûxŠ“:}®-˲ªØÈS ?ãRW]x¡æ§¶Fî eÃÖE¤—¦œ7)+æhºš¶%ç!wÆòÂ׺³|–„Dw³47Ä6YŠµ(óà x·Ýþ,ØïËMíÇ“•™ÛâÜÀÙz”ól}Œ³y€³)8‰×3‚¼ñ¢¤©†TWã@^œY^’¤ù„qRrc야XÇ¡"¸½ŒtCSñÞÉÜËŒ8VUà'ɬJvò¡ªŒ`êg…í÷
+
+ˆ(Š`CE ‚`7&›=ù(û?û Þ÷ÜûÜû»¶)fª(:“ˆñf¹›¢i%E›zp‘û"È!¡½Ûçgé{‰‘[Ãä·Wº¶&‡‚–꘡$È„X·¤p8JŽÝ¡ƒÍ#È­¡ò0S9îX.$mѲ:
+ä€x¦§Á>OV&ئè‰.yMöÅŠ
+^!àË(§”“åÕðÑ'K¬e‚ïRР®Y\ü¥Š’êš#%m åš?›‡1¡^Mm±}¾&ww„²MT¿üìWf湚‘å²f£¦¬ƒÜÝÄ&Þ®¶5¹Uôtçlõ[—”1u•†˘0†ƒ:QÕ"d\˜é#ÚÿóêQ
+JöGq/wz‹ŸÚ³þÐÁwE•ñÿÐ6Âü<
+nÑçéš,ó0ùåõzãLÏÃxµ,¸[IN;_¤dÛ2Í9K»çš°¦v¢u’¹Ñ IçZfÞ×u.öF_‡wH«’'JŸ;$ ÷z$åÂFèY,cŒ4ç<'Ç.©|mŸÄ¾¸Z’Ž
+>ngZP½3J‡¬~ÀEHkóÊka>ÆNì‹SmÈ_èçbìÕªvmü«áDUSh•†+ fدqL""¿mБÿÝã³7Ť ×Açj!áÖÐÒp»ù¾þë&{ºDJ;œDEXE%a×+õt·¦–,oÈ tÊ™n çV³Qg: euúr7 ´ØžjÈ ¸^£¡¯ô4¤yfã2.uuÔ3­€è]â=k T¨"jþMY_ø§C.(>˜¬Š_ëBjšsüwÑ‘
+6Ò½X µMaÁVqQ°w>•‡/¶æø­Ç¦b„—4Ùˆˆ:˜«ûÅåý—ôºÀñßÏ·®u:eã6¯¥fŽP*Ór‹¤a*K‘!{ÈŲs²á^dÈFq ((
+"ÈÐìÜÎëþpÿûí/x¾ÏóýŒ÷6v‘C^ƒk“7Ï.¹¢h/ü5¬§BbnKbO84ÓkF݉GZÙ„Ÿ
+ti“{÷Ü9A-4%쩘Èo!Û3*pB®Ä–Ûq‘µÎΘ£ç]`EHw©MÁÅŸÛ¥­8¦£T½Wí$dîÊp7>Õ¦Ê19»S­Ùæ¾²®ýQõ«g¢åQÜ,&†-b¢o‘]Ò
+Q;„G~!ß;ƒ|¸Ü_–¢ï.ÿ‡^Rðîå©­Wr ¤¿ k8µQ·Î?A.Ï·×Å‚V¿’Q±ñ¥9mõCõƒÙv¨k’Vf~ »´õø+Ûù±%oõ÷–,Ï0>/¢âÔ{e”¢ÝÑÖŒ¤MH<T  Ø\Ÿ“}°fÜ@¯Ixˆ°FˆÐýŽ¸»ÒÏ>Ör‹”—I+À,:&do†Þ—µæG—XuA%­dÈs¸úü±‡Ù›cBuRXêêŸõ©¾YÈ#Ç>²!ï/¿‡ÝM˜yè½YFÙŽœV·I8Q»Á'î;Ï /2j"Z!Ò?×÷+Eû8¼9B‡tïºÃú÷}I«´ã‡«³3a¡ÕúdÍÙîaDšOÉxíPŠ°£’¦t™°îZX#ÆúÌꀜR^ –ùÄâýYBþÁ"¥èØÚÅrLÒ¡¶­7‰E+˜b÷ªøÄD¨ùÏ\£!¬ŸÞ\w|mÇ=âC˜tdlo8µspA¡tžUã!§61ݳÀx=H-9Ô°Q¹úâ6!%fä4ìÈ° O.+ÅS}3°Ìÿ튄ß×ù”#©èÄÖÁ?^P61õÈÀoÚW³*ÝsmŽÄ¿=Ó8ðŽ¢½Âö™˜å‘‹à „È’°%ª£UïËñùÎÑ–€v²âf.:¤ïh³~Äd¬üÑx#ºD­vèh þ±ÆÆF,”Ÿ
+ÞŸÅç…M\ä.à-}OýS45ª#{€QZ¢¾J¬q)áUm ¹9Ùј»%"·'¹µ¯äG–w-wTüWWŒÒº´³uùo—¤û»C@÷)•^µò¿>É»ï[îá©Ôô¡ `} ÏA‘eî Ø$«Þ>ˆHsOa@¹ßŸ8¤CÍ5KxâRÀ:cãSEÊþxÍÕ½ñÆ[>9Puvgø0ï<·æH h[N~Z$% äò3 µö§§””!S7Ã>„¹çj¸¶=^Ã9\û`†T׶×3s'«’v¿FØÒv¶ÛåÙÊ{è³´*ew
+‘é›Çƒ\c¸‡ÀÖ)õÈ8Õ†~ÄmcìRX%†GTbTD)Fø&iECmàsïÏ©¹/R¼cÍb&1Á1ŒIw4]ý<g]H;]aÀbzr…k²9cÈþyì–sˆ˜£î¨½x¤¡V&­lÂ$@' í°ÀB[¡g¾>P{ÑÜýâ—–VdR½¾—f¦€j$¢cB&>: ${ˆ\@G¹þEfÝ™]* jv\ >õʈ ßt[nRÇm85IhaaýŒ¸¹5M|[˜ŒZ?Ï$¬}¢ov  ,ôWq-µ2®eÂŽnØ_â5¯ŒãÁÎ)JåéJ·À?‹ùd¨Œý‰Æ;ÛCM÷¢:€ÛÖÅôøŠ„¥íÇܵ| €ƒj)°!%øoVAKÌHªpMÔßÝ“ÁÓ#Z2älEÄ;˜~s‚TàW3!?¶$§k<bÂDª (‘«_ªï˜ÿ¬L]ûÒxóǶ¤Ï¯c"uïšî8FÈà„UÂ?¶ðYq —V“Ë|rd^d±­8¬¢—‡­½â¹Þº[š·0PD/ÄÇÌ"ü±‰?Yå‘¿mˆy^%½lsŸ[–öÄWß5<à_3kŽT¬`ï¾NšÙˆ¿7ظ˜Ý¸1Œy¸1Òœ³ð Jaùõ¯èGç6úëïìN¡2ƒZRebU@Knôöz
+é©~e+à˦ôý9j¹ß Æ¥ÜYAƒB ÿÍ4@ËwÏu7ïÍpËN
+šР†øÜ7OÛ…^õNc²¢ª^bL×/ñ+;±Ž1V鎼z ¡Wyç‰`÷(6Ã5ŠJ3õ½úÍØS™¸.i•Ð÷fY5_1÷–ûáW§Yå)c”’Kë™ÁYZ©±§á††=ïþ‚Nÿní´¤*çXímïö‰GÖšµ?E~æž •ÙG  ¥žW¢F6&¹ÚÉuµä8?A.Úú¡—}ŠÖœªí鱉x(ŸŠ óÌs«´½”€Aˆö-`AÛãM·5]å)KÒ²¹'[ ÃZîl£KÐJƒ€– Œ2“vÙÔóòÜÞ$ü¾W˳Áï›oNÖôˆß5tâËbªk™aí«¾`í­½dî)¿à¨º‘Ô«¦.êæ0¥Àð¶îð}YÑ%zõ¡
+.à ½Šæl¯ŸT3+Z1Úø‰þ€+þåÿ—éWÚW‡_M{:3'¶i›LÓ,g²™Ä8&*MâncŒŠ7”M@ÙwÙDTpÁÔ51&P@%ʪ( ÙdW$&Ú3þ!ó˼¾÷ÍýÞ{?ŸçÙ_¢”Ÿ
+xQ€/våˆÌÀªÀ¿ˆ*tÍ6dî/µþzlâ N]‚¿šX­ÿ rÉ+£VFµí-€¯""z£G+
+-“ÁI-v¼ÁcÞqisœº‹«Â¦ü¸ºƒèšiYFŸýdÝtsOψhÐyŸl<ÐK/S["±[A}’Úîñ*™­ð4­°ì¬¸îâ ÔG_;&ÙIkï¨KÝÍ]€^²Nb@qàHë\ZbK‹¯q)q=·Ídоš92÷tï*˜à
+([²ÃËÐ{¦ÑÒŸv$uiQ AzQûŽ”œû~ Ú•’Ÿzd”²¸ŽR{jç2Œl¼_Š~´..;¿óºù6À‡
+¹j“°ÊgéEgVøOÎGôªÈ<>7 ÝÉ…>)&ÿ]WÕëCÍ—ü€s™^·åéEÏ.ùdО¬ñVp~7(Ç–¸fqù†áæëËšó¾%Ö3ï"l}ÕxÕ2ÖpÕ2Íx/¢+¸šc‹xl‚@~:•„ü°®¿+¢å t¤š„–Tå”4¥ï«ÑEEKŽ±5ÿƒ‰…Ùž‚§¹°…G[|F|¼Ã–z¦!w¶Çk®˜Fª~(éU‡ëÂŽÀ2³Q-zö£WF(ˆ©éõ15¶äw+ ùy.
+_Ó3›Ž6™ÐOvAWjKØç˜$ Âþz²óù_Pkj
+8²‚- «Å1-½.²Ö+ hÇ^™ßЊ,“¨Û€oþô‰¢C §Ží|^ÂÄÀXX¤ÔV'eîÒ=oÉ”ó+.„4äÆ?¼]CŸœ=G66+¤Ã÷õÔú˜‰ÏLÙzú?Ú%fí`«x%µ%~3ŠÅam71¢¦<«±QU[np¡-àÙ|ÿ<,#¼D*K­uÓJb¾cyKó¼ìœN”÷µg‘öȃ  ±Æ'„5½,ß"¯Ñ0T{y†”ý…^˜ûoÖý6èXÓ\JfOÁoØ“rª]üÃ÷@û¦éA9ä•ãŸºç»áÎùA¼K!&íÉ;<s”¼ÝYRžy ’n®»å™@¦Þ 2|3è¿—rö°º³5¨$™Gw§h禩 ïw߀om2`>€‡¼‹ÌŠÈ*^eÁv¦¡×=ó°tïBsº}|Í/oÎ:22¡Q£€ê˜§=‰j‡†Ã«]DÀ}ò’fzsXM.?‰¼cŸl—¨u» ì*à æj@Ù^ÐsÐÁ%\¡_‰É1–Ÿ³ >¹à›…fGµ<”c–U®7Þv¼Â”j;ñ¾YT¦Vðäì#ïïaé·úÞ²z%!5±2ŒH×ô6g¦ÖYèÐ2d);7C/üÇxkÎw
+fáw¶ñæa=»ñ†ðpšõôÃôvLç$|jÊÔA‰i(uÎÙ–¼=À-½ÚvHÈ08`~ƒ-Xé­¸ xÖã
+ NšXdà¢ËÈÒ¨¦µÂ#ƒÝÌ[gat#Õ7ôbðÏÞ9$È'CæGÞªS›|FÊ"à
+$fhG–‰¿np§á`r“‰˜-Àûíi©°]EËã°WÖPë#.fGŠ+Š( Ç63®gÂ’6æÃÜ<
+ä©OAhÚ§C¬¯[2øÍ##ú_ÏÀÜÇm6)ibÀN<Þ‰IIêÉ
+.°žÆ¬¿¼8t ME =¤€¦ãþ±›KI¯ò:ƒzFÅÎTÇý}½Ô­¤ÞuÓóC \dl"øçé%I D
+kèeÁ9\ðÞç¯Å—ƒªæëq£2iéãÃEß8¿äk‹¢áÆž’ŽˆjȌ֔¶2
+ÈeQÒ¬;r@„˜YÐî×ðêTœš•W˜¬EEë9³¬ùÆ^Ä…áö#€¿kög)*vÕ¾Š]½ôâü‚8ÿ+‹ìÑŸV@®ì¾oÌL†
+¨Åhß”¨Ö€ï,þöþâBLÛ
+‚ Œ
+x‘‡Iظ¿†R”°rа™ƒŽèUìtäñ2“¼¯á´¬¾¦‚>Ϊþ°Ñ?´«¥Õ®µæ¸Fê/{Þ´ÜHؘ-»ˆr`wzføµkJa½W#cnÍt5™^"ó–†Ñ·\¯WüsØI©úß;=ý1°Ÿ½ ñÀ h;\‘ÉcV¶t=õªy{3ØܘÙtâé‘|öö¿ÙSw×-¾Ä]õÎC˜wßÀ¼’§«Ýø˜ºõ§½×ÅßÚûÊ.nŒáKV™Ôú–Zd”#/}t‹ûþç—žz’O®njÒˆ© ÏÖÝÜ®ÿ>¾qÜÏÆÜÓäZ•¬âìǽ¾áÏ{Šé¾4f$”í¾GgǬ|\Ì"ćõTPÇAìLÒz”ÝE›J^ùÖ¸á×ô⣖^ZØa<“„×G_Þ å´ü† úÃõòÐ=aá¡VTQˆ0à,ß4íADÍGøæ({è/=êfHÕ–   Û—wäcbZÊ;+ØCþœ'ÇÌfsݧ¢>ôƒ}ìFçú';ž: ÊÉJ7lê®÷Œoygé…neÛ••Ug`UgATM~thd"2öj¼1¬fTÄ´ÌÚ—ˆÔuÜ ªAŸ0 ãVZ5l¦#Ž–8¤O€1b‹<tHÏoM8ûeq§L7÷t¦l<ì}3¨ÃæùT¸‚˜žT“Yå“CfmÒÊj:]åÉ%1]Go¦õfÜ@­HYXèC‹„Ÿ²=é'åyUìú/YÖq¢|AÌC`}{ë÷æ+›˜ýq]þòÐ)f‡ôŒràŦ¨¡PòÃjìc౓¢æÚÚHãµ}ÐÛýFÖ:^PM«›À¬¬° §ëB~ÒƦz”迪57n¥#>¬Ë~M,õË~Úù¥Cãúæs>mp©‡.%jâ`CF^Ëö«¶)Bf95‹ðQ»Ñ?ßQÔv¥ È NÂÊl k)%©E!èeRIÜL­<˜EÝv •~·öºõjÜ" ¸ûëbÁì@ýß-¯
+§;ëäõì/Òÿ}O¨²(Zþd–×ÿ!òs)4Ÿ¡Îµ•sH‡Î=S^`*.VWÆH©èˆW‚¿PªbY÷¶¦)׶gH5e‡„˜7±Pe;»+³Djˆ¾ë¸¼7ý.¡'×½)eb5'—™M9‡[ôÏõ~
+J>Öãø<á`­ÎâÆï2«ÚÛ󂎲o”±SJ^fÇçMõdC4œ³³{KÃw++ltÉ#
+}À|oÖ6ý%±ø¸¦ìç•ÊœGÆ*x`þQ@©(xøØ´‰r/k¦6î|¸›ºžwÃìJ@ó¼àQ@)£›1AŽ|rþM4·°;²fFs|~ vkêQbf¡N×Ôã‡kJyÎÁE' œþè ¡>2…«>^“pRá¶ópåéZxQLN{4Ä?ç€Gò^¥´¸¡¯„dò¤G!öÏBŽ_ןk³ní³ÒºF[ðÉY+¿{v°îpU4r¼)«^,¤lr^hw)¬#ß,oŽ=OÚxýˆ“׋89Ý)+·»
+¨à•±ÒvN{ÞÉlɘ¨ )·S@ƒiÔ—±B˜"xÁØõŸQÝþÐq!>Ýya÷c×¥ŒÞ”6
+{Ó6).e¡'LKnéºÿŸC“0n$– 7RË´†¢KÆ©µ¯S˜Yà5}0;¾„¯/ö‹ØH@c´úí?zìå²G0]„zC³ÔÛ Ç±E3ê>ù¨;õAtfð‡ÐcÎs¢fÙðÜØÀ…½y^GÁÉÇæLÄ;±ì̺ðæ­¸ž×œµ(˜e߸vgžuKG¬B¬BBÆ"‚7AWd¢ÒªöYÒ®âï/+H9‡V±· AG7϶#ö‘®üÛ–: AlÄIïŒÎVÇh‡jMim”›wòû
+vá`Î:Ò‘³ñÝcâ“
+òº”·‰‡‚³¼¦¤…ÓýûŽvò,¦™(x!bÁ3Êø†GOwO?…epe]@Ü·Ò£ ô&mBÊáú“WåU
+ì 8ceõìX]97wQsžQº{‚~oq¼÷û´}„zñs6\-b¥·”WD¸ŠGL.»€÷ÎVÕêãuµºäSðÁîyzO¾²3ÇnH™a<bÑsö'ÊŒó‰2¾¬ œ³Ïæ¯=bºÞ¯³FKÊÂnÍXø]G~ÿ4¨ýù$¨Ö–|JÎ.ì@#V /aÐŒ¤,
+rÆ,~”1²š³f^ÈóÖįµâ„™Çë*p—
+(í‚R6%;k{*Ošd„}¯}ßÀlÚú0|5®gÜM›ù]à\Gø=¾j{šT“1³Ûr6Ÿc5F¦(77'q—§ýpU­BV”Â]_`ÝOÛ$øŒ ð
+Z›`ÞJ. {O‚ã/Ž6$¼”aèÆî\ß7{óت¨S2·U@×ä]rqÞ% –=2î'ÀJY+¥>i¾}‹ÿÁû¼ý‹Íÿs\^Om¥g¾Êdov&“ñÎì$ñØëµ×ØÙ8k\( ¢E2M .¡~tTA`ƒ—uÅØ^lšAõŽ$DH¨ëD1qò‡äó^|·§Ìû~¿ßó¼&”ÄÔMI“œézËnPuÿûëI^]IÊ ìÉY-½ž‡¶Ýž£ß^›"]C]bÆŽVÒ˜ üë  €‹þ!eÎ)åúxýy+ ]h¿úÐrnEõ`ÓÈmW?j>5ñ9à>@ ãØ1Ž¼¼Þõɶ³Æ{u߬ Õ"Þ‡ï#`ßv¸d¢¸àUÀyŸ¢ø_H¦*zmá9Â…}ÀY‡Ê‘ì² +iáµ™cÔ(î¤]{^˜•µ 0V^·Ýô½lý¾¸"‡ +’/õr¤ëa£ñŠhÀI&‹9še×$ÍbÚñæØT1(‘ AgXìܚg—ïê¹ Ùe!ísDª:Þ‰¢ú¾†œ NF.ËZh•¿°ç1µè–óÐ/»b`Շ畈E€‹©U; —Q «1ë“KÒ®˜FØ´³H.óM´œÜ|ßq¾àbc|ø£
+<ëïÙ%nSRÏÅmÍ3«#€o¢K*6pîM „ i½Ái%u}FÞî ØU>14Kmˆ„„„UAÏ.«vtnu–QÒpë¢K¢»»5só6NàžÎ´Aв–ŽX•œˆj÷»5Mû)®ÀÄt¬ŸQ+Ô½»Èk Í0JQ“¤;o•ô÷(]}Ývvó ñRBÛ{1SnÜìË{ÅTÐ#íyŒUðŠ)À¡ÊºÎÒ‚OHDøiÆ͇”óiã¡:í‚y3¤Ë»ZFCÆ*e<#ÃÅ€j4±ÄÅ™ÇêO›F1§ÀÝìL嬕w½?lϳjRF#¦á‹ Çó.…he²ÿGãöo Â['Ö&º«ÁlÚ|­ Ï÷ßÌ[Å}{sß 3>eð§5¹r× h_ûm 2ç”fìRÚÎ<½,e¢c ¿+cÑ—e2ÐaÒN˜3óñèòýg{¾{ãEDÊ[Y ¨™\šêù1¶(ÀçÃ{þ{#:Љ1}ϯ
+V•ª½€Žhmžmÿð<ÅÚU³j‚rX7Öpfs®çç‚W@:ÀœÏ>~_ÖÀê ¼"Ô¾Ü:'n<ù‡¼MFË;xw÷ܼ»¨•^šÅŸ‹ëÉ·P;` 7Lͺ ^ðÿø¬]Ø7’Ë£š®ëG^~OÑ#茊óÇ
+~©`GCü)c¡Ô§münÄ)ae݃
+ÄóäcÎ?þYó2nvë¾x4mà·_¶¯Ê¾²Tc­¹°ú[qäqÿ~•™•´‰û7Fž# +¢¸³ñ¡÷ªçeË™õ™®Ê”‘‰Š+¸¡¾EUÍ_‚SÄÛ+ðÀ¾‹GHM·—X«¿}L¼ò•¢õÊ×ú®ŸYÁ@@–§¬\,bã
+È’…²„›…„YÈz³ÜllõœþýùþûâÞïïyžïçw»ï k1¢jÞÓ¸ª‹©©Â
+èIôŠ´IÎNZÆF÷ ‡ÁYê­õ˜ Í
+؇nˆœ¶0›vfˆWÃZêƒS¿b1A­¾øËþ)LÑÞ\G9øG6蟃¹õ±‰Ôšj,´”Ø펼zeyÞ¯ÍqêÏÂ㔟2À«9DH[¹,t½¿ko±ûVÔÄÅ&­|Rx‰RêyÓøƒmâ—3`¦5·Îxœ±ÑªQpOa1ãØ58pèR*âþS÷á/k/}oV•·ùkíù“ óÔ'—Ÿø岜SЕYã“2F^[ÆØW_&Þ̵ý´7Cú9²Ü[‘ZãbO7¥ÂSŸLZpJzÓ¶þ–ð
+ázd…]‹
+,ÑÊt’ö¨a˜³¯æaü¿QJ“jVmBͬÙ~‡»fÞ<³ýs9‹{sÊ‘´st<¶¦€‚+ôÊíü˜žZÕtÝ‹h(wú®ª½¥žª°QÎŒYÇ ¤à‘ B:z•ŠX¼7ÛS윲°€GY˜}­,²ÂiÌÛùy;„‹­ôÜwÿúøœûUÝň¶ãnÚ5Ç-2FH/ÂíÎsk=ïYeÎIÒåнÌ=ÙTdVÖ^´Õž‰æ.Àbbæã6?¯¹_×_N;« FcDÏxÖ±1ˆß–XU0–g£É5qwHÓ]暬û“Vtë÷ŸÚnæ"ZÚÎïD,ýDÐí/ š³OýÿaÞŽjÈ×3딨½·. KÙ(ÈžÂÆÐ è ª”CÆ êEÛŸØsôÒ†r3¤í(¬Òj"fFí¡OÌ;ô?Ï8¥Ü´ƒGκ¤œ¤EÒ3ððQ»!¤¡WÄLÔšœKÈ<ò©^çý/–NsÌ5£v~OÖΧ„z*œ¯°7¬õÿØ[¤ÕÅM㣃Jì|K«ö~$ß9ÝyŸ°‰iI³€xd½ÄÞ…l‡Ea +ëû5ïRŽ!¦Þ'!]Çí}5¹$¤£”%Ì”²Cëéñ6vÜj;n–çùGÞd
+‚
+²CȾ‘…¬7¹¹ AëLutŽ­¢bI dß²A a YÈž
+ðÛY•9ô…­Yô°—-À]³v„’±‰) „Š¨ÈÍ`ž·€+öí,.^æuFTð`Z?É,2[<ÏQÕËÚÿ¬`W}YÀ\?z´&œ²O? (àÞ] <˜²HyYÀ'€GP;‹˜ïËCWvT„†¬ëÑÓŒkúŸ13LÉØ%¬ˆZBÜSB²&1%mäöî-á*÷WˆÕq=­9n/câ$u´Æ¸–Öþ@lÈÙ}9óÈÝ„[Ñ{v—‘þ°BÔ|;òƒçöoËâ–Ï—á¦3/û/íÌ%„OFÛvT´0?tÚ4ÒSc«ïзߓª3^wøNÎ657I¨Áß7oI5¡w¸ºœŽq/ofu%
+n1ZÄUî®ÐZ“V˜“w ¨Q-¾6ªÇßHþÚÕá¯í©I åuép#iÊ.ÄeZy]<qèYy3½;c¥w%rÔ)¢Äl9¦çõì+Gj7^õëúùþ?¼3Ã÷"Ú‘Þ„…Û7"xß í†á æ|Â&æ—²é¢]B/XùCi £¥ì€H'^ TrÀÄ¢SHˆÙ1Ã8m_=I}
+öŠx#ïÆÕú]G>¡äFFËΩ鴎ߟֳ;²zÁP^'!¥VFïo¾~ðE^ù§À¿Û¾N˜íE7Â,{'åy»¿¥ÄTz_ßû"¾<p9o¡ß);!lÉ%¦§Ì0:¡—¢àNÀ{Ô¤ë%ØÉeFcTÍnM¡¼sBP\äíù@Ïé ¼Á_Ž©™w
+„VpŒ±ìÏP_ÙS*‚¯‘®Äxu´kûC÷åˆUÕŽ‘vW¡¬EŽd­Sã[J¨0€°ä“ˆKkˆàpMÄ\&HØ üÚñjT!ÆlÌ!Cúɾ¿l½¡4äOÏÀî9t GNû±è³v™õq5³¹àQrV„œžU¯ï, ¯
+þé´–Ö|´
+áO@OWNG4‚À<ó&p<úŽÚ˜1cšáë¦'õg·˜ê„‘Õ{`á ö’ÄLœ®¨Þœ¶súr6hx)*c=eÃ×ïkðµyÌ<
+<~zXÓ±ÚÊ1ÿd²&F·÷iÿÅÐËίý¿¶Ÿ‹ë(w>nÊžžåÏ“&»«dµ9öÚù蜕‰©I­ÛŠþš]%¥>ndu½òòÚÔÓ àžøoqãAÑ- Ä
+½É;ƒ¹š±
+±iàza¾*¸€¾z?\±³H¸QtÊå</tÙU)×±ÛOs¤hâ’jtåö|Û—ë/›Ï
+ÈäÏrN˜ v³nOÅlÎÚƘY‡ˆê{ƒ­È8Eôÿ†¤?ù /¹˜ßýccÇëãÔ;·—È5[JFãÚ[È öý¼YH9q³zÿðóÈy´¼ƒØ²þªûÜÚ éjÒŠŒXÅìà,¹J#»{ö=¿úsß/ýßå¬ÊÇM©üSP2‘s@Ø=¥®äAXÇkb!p³ÿ³_fOMei
+ö½!CcÚúpÙæï{Áóq§V½÷bàÏYF•¥oŒaõ`¯ªùáeÿßß,(°­ :um¸ùŒwŒ‘k98Wü—Øy˃Ì̵FÑ®K«û~Q«O€=\p¶³ÐõÕåßÎ [Þëâ‹*™ß ¬Ü™à_µÓo½ú¿îÏË ;Fù¸ºpqÚ7-®ÛuÑâ½ÚOK)¿°Ý*øw¨>ý‡1ûßÿï ü¯@"°D`‰À $H6l Ø@"°D`‰À $H6l Ø@"°D`‰À $H6l Ø@"°D`‰À $H6l Ø@"°D`‰À $H6l Ø@"°D`‰À $H6l Ø@"°D`‰ÀFÇöBùáW))E"V!CÆ 5]!¥ä—d·ƒß5 ©Œ‘*H)íiù˜¬Ï”ñÅ"¦&ç¦ôÔŒ,rZ ›!$Ÿ|IAäJŒÏå‹@c-“!dŸ"Ÿ¡gÁAJ'SÈ釯&5é •šEM¥dS²r(éé´Ü,2•–EKÍHÏ¥RshTZf¹;DËLͤR3r2(”ì,ÚûAÂdPöa[.øŸìœô D=ìEɤRhY”¬wAï ÷³‚ÞŽGj$‰HÕ¤\òÉSä¦F`•Ï&I~’£$åóW̲óÞ}-`ƒŒü7™ ˆ¹LJ+d+øLö¥òæ2rSéZ²w2¡ïÞÈ?Y%3sR©9d:9#B¦¤ç$3Èûy=’Sú±×Ÿ4r˜…v8ã,r²o:)%åp’É+ LËÎÈ ’šJ~œ•^íZahFË÷OË|O%õ[FqsÈ*nŽ{„ ¸…]˜æ\™»«CvŒŽ»Ô=;&IËú$7ß÷LP²ýT\™UtF­jnÑŠB3JFhVv-`–6,Áú”¢Ù;&ª\~È)Zážò
+CÏxE¸‰_40Î6?h¹u'`ýË]¿µ_ã{¦¤o‹J^?aåùÇ;sƒÏXÂS¢2|ZÕ³ê$/¾–® ÷T…-Rºošyqc²#gm¤%-8Í)‹º„õ¡iÎ¥Èlw-á±¢NMOÄ,®…WFa©w˜IÅ =MžÞÞ˜]Λ¤ôˆE-Šy4Ò°]ÆØœê*\i£lq.îLˆ+³¦;dTvžjy›#ª6Üp]éŸ
+Ë´©©+ã_ÀNßÔŽmgtjŠuœÑj¥ "È"²H !!d»dß7‚qêZj)" ;d½77;¢„@öÜ%÷&8?H/Îœ·gþÿßïyN3á•Þ=Š€]EMê´[ѹ» ¬Ú]’ÔçP½`{^X^QuÀlUa°–—ÝÝ̬ ë“.{kV{C#8âp¤\À¿•þ+y÷Ò'¸Ixë ^Y{Ê%ïL»µœBÀnʹ ¼Äœ¨jû/ö‰×ÜŸ2+¼Jb]ÚJ¹ y¯úÞ¬íƱàvp‘ùõ©ÕþÊWM'óßã>qSÑrIØ á³G,r¼‰D,
+1I0Ÿªó@ͪbQ5‡[ôåMË0Zµ€!eÖ­a¥W5Ý„O×þ’KƒUÛÓgB¿µŸ^³µŸHÎX Âº]‘\„nìO³+ÞM¶üð’q_Öa’¦Œ[z{áAÝqÏXó·øª–G¡ur™{móEã—ÛSm§·°Žp‹êI5$jQ⃨€èø8lQP¨Ít·Saƒ !À‚‚Ž9œtÌ~Ÿ
+(zé ¢—Bä]…uMoÑoQþ¡NÌ%n¢QÀ¢P!£´ˆšdÅ UW ;Æ0Ä¢J» ÜœÇ
+áÈ°–ŒZŒDÌ ÀBFYpþÙ,¬äÄfï]Øz͹DÇíŠ[#Šqë0½iŸ(½}NE,Æb@Í)"ÒvÌ/¨£ÃÂV:*îÊ"œê”—[CGÍ:5ˆ19yŸ¼›J;éÈP7–1ò^QCb‰{­àÑ J¨óE9âœ"B:QÚ µl®ºµ˜ß <Ú}Ü5c:¨}ZŒ8§ñðƒçÔ
+>-€í†ŒÇÈO.™¸Ç,$<VâMßÅȳºãgÃÁ ÆéܼU”ZÖ³ög¥µ3ÐõÔŒ¤_“4&æzÎG&[¾yû’Yá{Òu*6ɾJúŒò<ÈþÄÂ`ÕÎëJj‘WGÁ’VÊϯ!ÉQ±“ ß
+à¿P@Œb ¶H1pý›VõÖ6NmÚF©¨YKDõÒkâÆCÐ+À'½e›
+H‰”—Kv\9DW =h‚Ÿ±{è]øœÙûŸöÅ#©²ò1Õj»\¶¤HÀ›†öG÷2ªITëïÿÒê¥t1—ñþóí?oòþï7 ãá:| þW'²¹÷V»÷ÞëûŸ¦<LŠ•æ¥Ûû…àŸ­rB‰˜ˆÆa­×acB¤‰–ÚG>!m˜I¯Æ_õý×Ûuñ!ÒMò£š xˆ5×°ò~AjÕ^ªU‰‰ÐR2æ°Ú‚Ç—¡>”ÛÝ!ë$)´™i=Çi®î<µ ïë2ÎU†MH!¼’Xc>ªKõüˆŠ÷o'P%[V¢©ü”j\ mµiçŒoƒì¡¢5+U}ƒªR–è!¡_€
+i­½–±"•"^ŤZéï¿'¨nJ.ÇG¤FÔ®«ð¤ÑÈ9äÍ"ŽÉ(dIW9¼ðôî¢~€¬rÔÕ£W}g(Ì(µR§u›*£ºWnp¤˜=(W^UuÔ>OºQÕ5yjAFÈêïö Jðwå<=!è/…²P½¢û /;+{PgƃŠZ'a£fÖ‰×bö`<BÍøÚ¸ès!<Ú(Mz«A P>fÔ 1º­µb-V)j‹(!d¹Ä¼7PaâAkNP×’05›q”¾å,ù6±ÎíãÆDa«¨éD¸iW˜#Þ}6oT˜'yŒèç -(O÷€P¿}kYè‹£ÕèÛZŸZ0Û
+¬áÇô.Ó®­«`
+Â$ A¢êûŒ¨6Š,_À»/Úgõ|³¯{ÌtÂëàMÞ®Ù‰}ä·“£¦è€}ˆs#í#v]§wzÊS¶¬§ô0ðPÒ•½AS¢â¥×ýª']?ißךr{É€3V„K|);5™<®M©”ïà[[è>…!Щ&V°i¿êŨÆ9<!)btS6«Ž•ô)vŽ“"W&\öÀzÒ6À½(Ìr¯ýÐÁ?ÞN T;t5ŸY·÷tšFè`VÇ·A'ïÉq˜jK­õ/@ÏO‹UÐ<¸7éÁûcPS ùÆhí¼LÓú–ù~„T‰‚žÇYM©d&Ù9´_©2UÅ
+}†¸ŽÙúÂ8
+íŒI¸¾GÁ“‘Hnˆø õ“q”Ü|c¦¾—ÆQ*•Œ‹ú8G ý*3Þêq`_¥êŒÕñÒ9*Ùo©lÚË ôóèîYn5£ð ^ÀV¡QÎÎQ=[á^9GÉmJ .azvŽ’[b\IH{Q«/+þ—s¢~
+ý8šÂEM¡ÒÆÈ>Iãªi¥ú«›sRɇf"_G ×ÆmDö\ùl@0!‘´€Œãq0Ž'ÐÍ8ž@wæÊjUœzÅ5ßÍ2ÚY¶B=ÙÆL^UË@±ƒ<ÙF*€À1D°1ã,,‡šß
+
+rwȃ>ê9T§FV³—³mTdŽªyK«óÂ7êubä²Ø^"Ÿ|£2·µJ:ê-ϾQ'=§TÇ+ßx
+‘£mÄ+ë½x§§µr¶Ž
+árU£!µž­ã'ï/òhDf[ü›u$NF¦À¶]ê³u¼ ûÝ:þ/ÖQ:æ23l”KSMˆ‹Kkï ƒí_¹»”\OJù?@Ü©BøšÎb‚Ç}D¶‰ß‡‰mq
+ÃÓ¼¿O〖CÒ×ú9±j•É4!5Í
+íÎtÇ[‹-bxK­î%(Ýþ>ßAKH³rÇ^R2Wá²Z@;>9ÇØÞ2ŒtRå›»Ï]”ç-y½¾ú²N³­|ÒH û¥Ÿ|ôŸÂg¦«Ø}‘ý=1ÌEÌ$sãcÔC>º›âMNÏ0|_ß’oôPp¢ìýØ•×Ëì¿Œ—=’d·„O ;ЦÑ ðk*ÖWG7kòþü(ô²_ã-[#¨™< *+3ë¡1z]nFê7ÈOÙcö¹Œt&˜œl¥.ôPr óþTVxQ‰öf Ö˜ÖÀwçTºçV{ó*ƒ\ˆÍ¼–[%•³ÏçùbçI2ì²ûÐ ‡â­:Ä$ydïäÐ Ëäšð+梿RâI8þˆƒ¨)MWYƒ¦æû«n†¶ (Þ´J¯!Þ…Š´ ÈFÌZ/›Cø5…W½vFF†+6žžŸFOîÇ;jÃë[¹m:ô|öj§UË[®O´@Ñ-¶»;¦ÔÂì¡ú›ëÜEð¸Ë‚d|¥P<»`µÒpþSû/¢wLEê;€Ï¬N]’¸ Æw¤áw1 ÕT’,ÃE=Õ©:á¼;-Þ@§–köÐÚhÄàö1È$*l°<—5gñP„¹=·íh+`(R_j@Tâ–¨Zç:§uéÒ´ÄCj A§žNùêÚ‚µh^gbOÓv•< Švê&^œI/J¨uñ tªk [l²LøtQæïOäû¹ñP¢Gg Dñä½Õý#þ\˜Zxveeª§+…³ˆI¨§„éëZÔrÝ Žp‹,lÙ @˜]t!7ï>½Œ4Cb›TDYjh;+v¬œÝjªÂ„d>fŠ ¶ Æ&•¦xæjIxÐ ˜–¡H:€¾n@Ѓ1ëTkW;<Œ›‚ÚÖ)R2Ú™ÙÉX™EƒeĶBóvyMl ‚Ò…i¡ß}À¼Ùi¶ã+î`*+ÛN^ç‰.Äßôê·ÿ±“»ò¸l©Ú!þ89(£‘Mj=&­ÕÞ #B©Nlƒ¡äÚ$œúE*±Ê ¯pC¼§Î&U^äè…·Z²‘±€í­oLHÓ>×k±æ{,Ù—Îdj™Ž)»Â&``Å#ˆjÂÝ8…Hm?‚®DÔ F.íÕïuk™GÊ!8î·óÆkÊŸõ3Å„a­Ÿv…5ƒÌ‰4Œcö9¶ý=mÀBZ@(H:§ F¶¡‰ˆïM¢ Ž×q{†þ¥Nµ¦]•]š‹²AN8µ;³˜+84²î‚bL”âo˜‰ïV—貫ž5ã#÷§\$òVêâňü‘ȶ}fA¹Ï­Å× C ð7niN $‡HÉ_=¹6D9ÜÀÖè…Œ¨ãÎ#ºÆ‚YûX!ªâDóÕC1‘ICÇBDëÔ¸¤ôŽð^–Ž qâÃ)‹7M«(—ÞWAÄ‘¢Ÿ»ʸXWbòC*.‰ÿR¹øäÖÛ°š½BB5êLu²9ÿPNÆW†Ï¬W$¦?ûÊÞoü£¾ø/–‚¤§þS~b>GeW¶ ÆÊ$[Ù¡ 7éÉí(?8–L…æÔç³^¥ý$¿—ѿܘµ•ÔÖJ:hÊT܆°6 cÙñô½@|˜D]šû®N‰ƒb–ZÙá©âu(9N´ ÍH MÞæ“ ð$¥³áòÔPø”Ø!‰ÇÉ…T­uSÜÙðàËν¡jg¢«ýÂ¥@ªÐãØŸº€”tø¹JÉ×ýUCÙʇ µ A̱C(ƒiÚÚ8A~[q}Ò¯¯_fÚˆqoyKÕ?=åçÍy/ ¯#è='
+_êA ÓÇ øœ)^U%ò¯#Ý. §çv–«»Z/ ï]´JžóS"†ÐõŽãrKŠ†I)Ô±ž¦Kê*#œìrëÕ–Žb4Öú:™á8þÚÃHßZzØ>Ø7Ûr"Û„ïÈƺå瘖—@D³ºWTX¢éFT„qB
+5U>d7UzGªÞ_B²K‘£»­Ä˜”ãðëâµa'Á ¶á«ZRÂTö`³]õÅáPTϳEQZ! ]ô`#.ù÷3‰ñecRÙ‡œ'Ðu¸Ýî¨ç òý ã5þùøïÿÿóç_K1¹GÐ’Èó‘&þªÉ80ð„3¤44'G¼c¯,‰ÔD9&„C¸dsåjŠÄ\ö"þ°/HTpFQ0zA¢R(ŒÅ§YS¦%¢è%*楾@$¸:1ÄuN†ÔxMk3} ãŒ_e€ a]£½‘ ×Ä?EµÈñ¡ªëÇsЗ:Mæ"û•ù‡½‹„† .—ˆÕNDˆE±Rµ‘û½ªÕ )³ÞLu›c…5Å™è å$íÎëYx¡ñS ›ˆ€‹bêä¹Ìû˯ùkç¼öA—cŒ-Õ4¾÷³ÎœÅàXiì/½ÒB¯6ª46s^ÈU•¢¤0xNˆí¡ÆD¡ÂQ£g;Ïä§9”ˆˆñºA1WŠÐyDð¢õ‚ìûó„áZÈ™>Jf;"ŽŽÒfñZ'C7Pø¹þш[ â¶eèDS´änêäìX‘Ìm] "¡€1¿Þ JѳÚ_¤’íòìNuÊÏû*έØ}lÊ“-BÖâgçs¦¥¶³ >—É€ñ£IË™y-&Ir× á H$O\ ›DM ª
+§áis~u,H™¹ùu™i¦ë¸ù¥þ)F¦ì·‰øH›ÎšüSoÁÁ™Ý†}&åôŒ„ Žz2ù·sõµ“7ë:Ê"T`]ð¡ÐæÇVòÆM)
+"ÄøÆ·¥MjŒ.RÌà÷!W CYéHÐÂË¿Å5e 2&³™‰é2S€¢tcòãRJ*ð[¶þ tä"ÊË»‡ÖMû¦É@ Š3šÈ
+9 åö¶Q ßGПO§eôYy=nw’W%²_ØC˜´²"¥Ÿ]å­÷'w‚Šœ¦eVùáæ¾Qžm¨Ü„u‰i†, BçXŒ˜¿/#¬Ýˆoi UŒÚ6´ì¨5Œ¤‡Pž–ÞÁp~KY·ø m´ƒaå‚K)AÛ[†ö\F°ç5ïÐ%–¼ ǧV*ƒ_Ž¾yqÅ4ý”§JÈÿp¡iq’Â)—v‘ðQ6LÌœ|hy“AÕ­Õ!çð¡ŒÌôðl-åi°«{`ãéî_äC®f½ö­Oh÷€ÿ1ÂYÁ(V-Gµæ»cHªŒ&ܨ¶“¼Dα6¸ÊHø! ß!IöB> eûSüDÉL’ã>SÍwye\ILÅéiè7èe>PƒÑrÈ]6+ˆ„È6üåI«m#fÑó-ðŒ!JÌØšK õ2cÇl'?ĈÓRÉ. -]’Z zÙ‡3}ìDe…b8*“ZV¯Ãõ½@=¢ð’êqFC¥h²mB]hÇIB9P­‡éF1
+m…Çã«úC©¹*ÕõsÚÂ("GœÓ¼ÆPŽÒ[“Îýøµö¤¶×If+ʃ͢-·¹‚NÉž:Q/tût]ã¾o@Yë£Õ‘—muƒý‰·µ¾ƒ˜I‰ø7DÔ!<›ÙÅìúûÚå%$;©©$ÔvÎ…´BdgãÔõ ™Õaã÷Ä@Š†hÚÓí9ùoÆËÉŽä¢'À Жû"Ò@‘*O
+Ìr^LŸ¹6‡ª0Úè€@~£a¾)©A*öN¡wξ ìè”1 ;Â*f5…ÂCÁ5å´¢ÄE5ˆ‰håÐ ¨œ¼ãVÌ ¼‘ðgˆé‚£ŒkŽ–=± QK—0à«)ˆ‘ÂàÁ©Éª7—†Ã SÐKw@/«O&+Y,t@
+ÿàÁ5\!‰àÊe§¬„?5½b™:%º .H¶ö™šÉuÂìÍRÊÍxÊi‚„@Ѓ} õ'ÄÐò„RV¥"Cé
+ÒåxE«3Ú1¥3\8¤6¶7är)òœDÆYÝãgŽ‰²/!µIŠ%ß³ƒüòiQµÚ µ]=ÒÓþÿIþL”tþ¸õx'¸Ó¦ý±ñèä'jÐËÞÙ —¸Æa5!áD[1ßÆN~©Ë0DAdY¼¶íåY0‚Ë»§¬÷Dæzò¿ÄzI8Kä£o™0F+hJq »ÔPŽjœþ9éòÃk`iíK#2 þ4­¦¦ÃöÊý„ !К.okJ˜}
+©›6ˆ^Ÿú˜9H:‚úçöQ¼&Íeº&ûRÅ[ÍüþÔõPà£1eÓÅǨ÷Ü{s
+UëÝ©aEØõdKL,ä`üZó^
+V1™ó¹Ø^Á€äÝ9`F¼‚##3jÍd£á¢²íÈ á’Óô¯Ð)–¾@4…Ñ—ìÖͨ“Ÿ+Çäm¢ø=Œ¯õ¶A¨±dÛ#ÔY¦*SÂÏ1fJðÿ£${9Ä•o« :¿³XÑô;‚¸T4›ô¦n¢£VbŸâÿ°Þ2ééœ3c·<“––ºÉ Aæ_äc¿
+KÍôâsaþN`77ÂD4tž¶§Ñ
+âs]|PÆÚ*¡’Pk· ¬»
+T•0á,¼¸ñbØ-ؼ„PÆÂC;ÞEÑY“§˜»†A;hçD&— ¬ZºÑÛVÑkzÃN`U1ôc<¥@ÚN'ð$)î¸y=GáË HïUf/:FÅ|
+¶D䄺„2¤„D†²Ú©LÒ–fiÝa›x$Sí¼Ze¿šV× ,ÄØdžÜÅä
+r›Ž¿IÚÞo=†Ò+ÈÍ›_­©¶ù¯ã¾ÿñŸý÷‡ìëÇݲÈ'>,¶@”Æ
+Ü}M^ Cò!z‚LÙMŸŒ<Œ/;Ü…]ð§e%/o¯ÁðqüW*þ^§þ!Þ…ŒXþ}á©$}uÔ.jÀefgÏÔ¼Èë‹nL&E Ñã§Ý¿ô9Í`¥µÖÇŽ;eP×Î
+Â+hŽå…ž CÛ âáNmaé™ cÇÏ]ÁŒQfšÓØ+›å½˜]‚£ôØY7L‹íÜg¬l“u“ÔÙgïˆß6˜Ù¤·®ž©øwÕ©¼]ÝÅG ’Ø™n{v¹]¨È±ì£8ä›o˾ܙ¥™‰tû£-4ã¸x'ØP D™ª­pëúìÊSÞõç‚ 0už ‚£`Ö)Z=8Æ€ÀÜ®aJ`5v)ØÞà¹$õð×(ªh÷æù»D¶ >ò“a>²Ov/ÖvXÖ¤Ã×I@sQùr| SÁT`@)R:‡[3—ƒd.S0¢ˆ\žËMxoÂÜÁu¼ºañüÚ
+ó!Ì_=œùïïL±>¬§?Ø"ïr5—Óþ8Ã%#\f{~ y††Ãë»Î94D²‡%(>je§Æ9%8“aOïk—±©1í|Š©<Zm­š6™%‚Û|ÿÛr»=ùX£pw-¸!v `Õˆò˜aŸ‚x+a‡'Œ…Àµ¶Ê”Mòè'¼Œ3' íYo9 ½XDó8,CüÓDíß]Yìå‚oV–æZÓ a&ÃíØͶ ”´¹+² ÄÖW¬-fcqeÈP-¶kÈCK$©Åi ŽXÐΞòúÔPSAòÌËö%"""FK±E¹`=p%:Í‚9AE%¬ð霥“Ñácû†õH@ hDg·ì\Ø>•ÑmŠÓå…ê<'ƒ26o'…ZºŠ¦"PLÆrrø‚ÄNÀÐviÊ,b œò˦]Á$Ç·V?g³gX„¿HÜÚnɺ‰êí&Ñ6"jŠ³hÐ Ì <“K«L†H!)X¿i!mð9†Ëž}#@¬{Ä­Å´w]U¼å·cAø‡0Šc1)ª¬ y5Åì@öî‰
+‚rT}:ç"EÜKÙηê©z… :fÛïN¸-¥ÆÏ5g;Q(òL¶ûP~ìõ=g½¢±Žßâ¸ä#ØLFÄ»ŠÖÕ[*A±fƒo·¢ÁöPƒ:ì \p‘SS°uš¥+ì¯Ãh²`JšËR_éí
+±nžiÒ=çĵº  B+¥z” $³ÊZVlmÚ_:3? ˆ€$%X㧫0 B®¬Õ’;÷=YoÊ”ÿþZ§Vì‹ó£C[Ô“d3bŸº„A¨úÎç“m€ < §Ã®O 
+E&f? ñb>c„Ú–ñ6ÅÖgœkt!{ž¥WèßØ€ç
+?ü˜¬Î¢ÕlÑó7’8ˆ!“%»¹GlY&²gûâ=ô ¢¢4ÁîÊòL«cq/Ìûo>¾Ca±=,¶WB‚3d*íú¹¿O]Áˆx”ÎÝÞ&„txs[$UõX­YæyAˆ
+8
+´tz¸BeÂÌvý~ùsgxA8$Ï!9ãŸÛpM@'•¼$©9\Ä3-qNdË:ö»d³~¾ eËS1ë!ß=
+ª«VhÎg=> •
+‡&Qo O­úøÆpjŒÿø‹Iþó?þø¿ÌT×':cŸ²¿1²
+<‡GQËÆžŒÆ>ØG]ŠÓ¬(’  =¾KŒÊ»(ø¥UO?J–/ñ‹TòÝwØBx!‰I»» ä#øÉ÷Úý«ÊÆÝ×F~˜c$Ú]…/S§. kÇ_îreÍåEò]
+såð¥¼×Iøz¢<Y)Ú±ÊÓè6—ÍÈ‹ÿÂp™›Æ('íèŽUÍÆ•x*JëH†˜2÷a¹hƇdU0Çùx|ÂeàhØ“n$ZBø”4‹7 kBZAƒC”¬cdRØ2€ J]šq°5?×Q=q#NËî¬SM^€Q[È…ÂCH”Öº~>5TRÉÚKÉ£[—…eEQ~›©ì¹ý¨ æœ‚„Îì¢ÛH´ÕSÅÂ`3T­ùÃ;óqRˆ ‘è%Å"îÔÇÀðBQ2¦ì^EK‚R Kç$'@‚òX¨ŠV[)JƱ{k:@ü¨"3ÏË-ß}GY«!­¸aêÒJ¨Þð8´¢ `pH’Ft"mu7,P`‹iB³ç6Ö¨Ö85Ü%°1ªH\ðúñÒ#K¼¤t©8lÂɯLâà2ŒÉ‘èó”x
+½HhQ(?ÊÞñ±]viv>3~x‹ÔùmBPleá»×“Lò`²#Œ Š5¼ bƒH©×Ž?¤öô’äÓ~ÐoaPE||.ûõyÞEgT\ eg+²l?$J¡¢hOŸÛ8/ƒÏRÂnç\6+ ‘1þ<ðt³úòêÄc/ã`‡#dö*"ÛÊBd´‚â·ëâ¤`ÙãÒX³Óp¿S­qÃÆÐF‡°ã6,Å­qÈ[ÇŸ‡´?‚£«¿AÚ'q4$´ûŒÓ쨓ãô¢UYÞµA]ÐíÁ·#ý(0+ltY…`R¨xäªX÷Ë‘ìPÖX¯fš6OÄþ5—À8]ÀÀsÇq”÷«
+crñï°IàÓ—Y¡Ø4 6Ôº½ìëŠÌº0“VpŽv·j³Ö\ëhÀi/†én:,Û·‰DÌšgÚ:Ñ™W5ùþÌÂ:ž9/‚Kgqè’È_ Ô¨¯lÇòŽßÁÌ(Š¦¨9ÄaUt69\l÷  YÕÝ÷ÅPÁ°³1Œ
+–%¤0œbX]¦5öàRGÄ©’,‰Ô¦kÑ´ññB.d8G6%ül~Ô áñSùÚL)G#Fö$6ÒKû¨¯§ë׿‹'pSË^·‡ø¯ÏAŒïÊ(¸L²«JGêØq$œ­ãëÐ(þR³øž†ä?öë•ÃÀ&^÷ŽÊ1l^cô6­Ò–Ï’Û陲$÷» y#ݫߥÊôQèín\@m
+ýQ…Êb+—n”G´¯é
+…rS^l…J
+$Œ³ó,4†U-¯æß!*u1ºd0Då§Ê0gõn“åÃúã¨WÓáC \Ë¿ƒÞÀLèéà=@ YŒ Á*âzD{XÝ~1L`š·YÕ©LO˹Ãöãå’dÇ­ÑxZA¿ 9–‡Ú…§WûŸú$ ^©«XÑÏñ"ÜÆe‘@"?òÖ!”3þ¾‚ñ_ñ6êR¨>2’NdæˆG0äï²$âHA”( áyø9Ai"«ÑQ Â,Œ‘O\çǹÈ7û”û‡8‘åeùë
+LùD}Ý€æ JUIli(@ÇclsÎ`yYèº|œà"7WÏSp¹”°ßŒ}í™/ýüçTÓf,ëHt‘r½¼H|haÝúI°4âŒýùÃfc°¤®1w7Ì¢'-¦;à„)Kbd¥d
+˜œ_ç^ô·¶¾¾#ÀÓÖ»4²èÄÑÂôð2°›2­ø¤Àã1ù¼*þ‚}… Úz>E ^‚»Ðig/øiW–œ—ðQ0^Uaà Jðš$Í5xŠr¢X·3R“ŒIÀÔÓ€º“&ªâ¼j«œC’1Õ°iRÖŒMÂë¯Mø`ÀS[ÙE×s:Ðdæ‘^Ηé0^ç¿*J¥§G ¶¨°èŽû9ãc64Ýe7üØP(Yô¯$ ¹ã#ÝVaµ Ÿ{Ñ!BR½¤!ã)gÞ‹ø\·HÖ …Pãë¡( s¬Ì²_;Â:ÌÕuv’-Œ
+r67%Ä^pS°æñ°É>-…3À]ða³Š(¶ôõ©®ŸÁŸØÐSŸ%–qPc=–ø§Š¶"C
+žÎý‹8ê ÷†ÕÁ ÂÁK”20R
+ þª¬@
+vÖËeÛX1Dͬ{ Ï+…òÂP+mqó½èÔI »fíÛEj~}ƒ¾ä3þTö0Â(ã`ñ'ËÖ’-Q¯»ÏšE"“ýlçÎÏ™F•É<Ö±èIÉqÚ¡—ß©(ºàAÌa†¸ 0'ßen‰¦pwªTO : ¶JðSA«µŽÙI¤cíÌš?è"LYyÕàXB1Ò~V¼?Zf[%h+n¨àèçðØÄh@þ}¤{ÅüPµT±ót
+ž•¨7~7ò¶q• /˜
+èyßó)”rÖÂØ¡$„Úáy†ÂžüòËÀøÂoÎÕ‹’ð–'¨åµŠpòÀ'±Æy)š%8.ÈÍg9¤ ©ôéYÔ<8O÷–”ðU¬.¡-Ú{QCë$X/‚¸Q;D™FV%¨¤©7_ý¸9ŽU"GÍÔx¹ßfº ·l’tmrõOá{;/5­Ànù‡Î+o' óv¢*N ç§üj¹|ñ~Uñ ËZv~î A²ˆ
+§»çxÌ€mÆ?e—Äð¡ô…?g4î¨HLú÷Á‚ú9rn,9ŸGÊh‹X?;©‹>E“µŠÐ¿cÑýœª0Eï^~ˆM~Nñt•`Ÿ52Çå7y±c q|¸÷"DŠb0Ç°¦¦ñ†HBm«¨•HóÄÈÉÖǤ¼†lÀ¸žD¨Á¾Ó-«þtþB³jÉåPâ]Žro±Fq;ç>JÈ èh>Žmj`àÆI—ÜŸº
+EeEW<Ùê?cN˜Áî—]ah6žÿX%Yhè¨~u·ü`|(Éh`•òö÷§®EµvˆWõücšãꢪq•`¥2¯Ù.¡K5bˆ©°ý©e¤1zy ¡úPû)=j`à þž4÷+(ÿ| ¥º@¢ûƒY@†VÓ0¨cË|µ’S|¬ä^¦Ôm9¬4ÞJŸ*”I:‚,ª?vebKÙ¨Ç>³+©½Uåþ¥¢ézk‚¡9#{H^éIx49ƒ cÔó9†#S¯m”fÞÚhQ ­”ë,lm‚¤òËõÆj˜r ¼ŸÎýÙ&#¹¬sO¹ÉIÙn
+²?¦–®v¢u¿ 0„ðQ«8R”Œ‡EËÉæÎH@TR¶Ä7°2ì¸åc N;X…Âœ[M›Ž«ÅŸÍ u—˜e­Èög17ÿ| ‹
+Ê
+”|¬ „½QðQ7äX$8öÂõ1BÏÞÒ|N+r$>)˜·MX–¹ ë]ÔºÎQùåæºê· ²¨ «C@£µý©—ÆA.À¥ìœ—öBªÖ2ü0¬Ùp:¡ËQíÏÞù¹—ÿET”ùÍÚw7H|E–O7FæI2:f/Ÿ¾B ~:S«Ñ.âß kÄ·BX±(t^§±xpÌ£ï›ó¥!/…t6¢v  ÷§ÕŸÈJœ7hY8mCOâFêQ 5J@÷ ãî• 4±Ý¦ã1ôâ aw=
+è´bEÕ(©;p¯òlzŽ­ liÑU!‚2E6ªÐõݘ‚´ ?È}¡Ø+昰·‚^\ÃÆ/׳aœ…¸1C`²ÀÊØÙ„Ï¿<jáùåQÓóœ£3^,Þë0þ¦i—a] ÖûS/*p‰\‘)ŸvÌ1¨ŒÆãíw!òBí±ˆýsà­/Þaž‰¤CÆÍ1hCB“k¨|÷B”Bødîýc h&ëÒ"ÄxIäB1½c¥œ".rby<%†,¶à!‘09@3Ö1XÞO*§}i°ZâDˆôÚ$“vËÒiº>œˆëC YâPFoéî^”´ôÍj¾nʆíu +‘6ˆÅÖ% ÏlF/NÐ7Iü¸ $‡Ø÷á·ì"¬Õ\nDý¯`®†uÒÊ0™ —ªŠÌ2¥ýôÊ!JÁÕ|{OØ`«åBè›íã5ÉÞsÔê<æµàç]Ž¾ñÞtôß™§Ó_3ì„|«ÔŸ7&æ‹ÁŇ.¥ácÞqg™x:ÛMµ¡ú06â±·©Qçmâ«’‘}þ„½,;ªºoŽöHØÆÞB^U•r”* ÆØ»¯†gáOQ¥Å„†¨áÜ"3l×öjðz™Ìöš5¦¥Žr÷¨üÅDüªT»1‚•Ž†v¬s89_u2Ì—©yšae˜ 9“ð¶õ’1êòd2ÝÖ;A_ ÿáÆÀ+ô2Bد⭠³} ­É N€cÐ1ÚÃÓàQ̹ Ïd5+×L–§€ f¼0îìAW°[¼æ-`Ô>€‹˜ñZLVŽž8¡³8#0¶@å¾ “.
+ãáÖ¡¬b€m‘‘­G•^àss¯t:gR+Î2PÃWáÈ)Yç®í#ÁeaЪqÉÈ/¤ô)Ú udêçá¼<¥zèG$jã‰åç
+"Åä™Îì}a-)Dºáê°ð`z“¼¬<E7Â8×-ôÚCÔNÈŸõ)uv@æs›wçp –§f_.‚Ô1 'mø‰T2°
+ÖöCG$'äúrÑtá
+ý§eDC\6 hŽ Q–å74yiõÚ<ù#¿ëçCü‹`
+iÉ}õóÓ(ž{;È‘{}DG—–;OPïœÒÔ¾µƒŠQEËiObӌ֌\6mV¨¦ÔÀ¬4Òç¸Ftõ~U£’2”+Oj­ðE² ýÔ棯zJ#±aÏæÈå0’êöF×€cRÁ¸Út½Š”ÍÂpã—?|h4Û{½ ¹<5”/·ý©§ë‹ûÞR
+\¢o þºó}® 0õâ.^!™ö£>¼´i+¦©E6i…ÈD‚,ºÕþ•ÖdÒÂ<bº¬4 ;myÔg؃"›Ç:…`Àˆß…¾02Ägý ø®${}¹ƒ&fÍFyŒI³ÊÊ{t‚~ßÑ·CÈÄWW³¤g"HƒÝ ”¸7QÎ
+[‹V¹aOŸ…7´…´B:Ê»†Ül—ÆBçVv •G+¢4÷‰“\íZÁÆuùÿÙ-Ûðkõ¯šÿ÷W¦ eG
+G„£8W4Zv­©Ó|„'D¦$;aÇ)qÕ
+¹ zQ|Î,Ø=]êà“w¼Šªè‚ÌgŠ7Ü«ÎAعNy†
+>oƒøwK, `øú[­*aÖ±ƒŽ;} úxçâ×û€(šN]Ã_öîxᧂ’Ÿ!î(Tö<U!ø©”q ¯3‚åOMF^ÈŸõ)4bÞü…{²UUH4æ‘ömÐv!Ê;æ
+ÑœD܃ ¯ o“&¦y}‰Q¦ žÒöLRÀ¨6Ì딲‹ð4S‘*Üqðz‚wbN`@Ïš6/èlZ=\:‰D‘Þꨮ¬(ÃòTy7:Tixû®VÒ~ËÒR‚ÐTãšøG]!È+
+Ï[÷2û-Ī5¢Œ£FlÚ?‡]›Zvƒo2ÆÛ\=˜¸a@Ô‚©#Ásôp'ñòò3Yg›€a¿Q#'èšësõjBžï}¼3<Ïí§Lñëú¹~7ýO7†fâò²l#ýºBÈYè¶`©jIžAV„¥
+Áä°á1ú6â‹(îÞVáàp(1¢!¶A²õ–/"R´ŒÂ[ž—ÙÐü‹Ö
+s¾{áµq‘¼<©§pN½‰’$B˜Ì4ÃÒ¿ð ˜îPM01eÌ{×<ø)ÊýÙù/Cøa˜åW‡J±o<¸ 3ûÂ.€å‚×íá r#:á¢Ü
+XŒxùæ¯Æ`ô¤ùÞ¶œ‰á6uæÃ_È$s…¯éÑ7-—fzæç2×ï0Zd¸²í=ÖmØuØsòð ¡ñBèýäš©à ÄÝrŽ
+ÓŠ±2ÄØ•mDl{¿Iø¬Mݸ‰ì1öçÆÙ)ÅÂBݘ¨_ïl§9ÑüमجéÌ+‹Ç²õ6ÏçPåS˜æjÚ·1§õ§È ¥¶‘î@ù¡dC£™æ¸[éoöš'¦ÑyV!ÃâT–€§'¿ òŽ#'…åœð=·O 1䂳o;K¾€¾Þ)¦jþ×ßðçþùñ׿ۤ É.&ÍiÔÙŽ0)Òñ¸ZÀßQ“Vªª›ŠútA jEP ”`%3(ì’Éän7Ö¯¸8Ó—Y´@ÉB<ÀÍç†(ú±ŠÜ&­徭Å€XÉ)ÒäÚs‡Ì$ÃAäí)•`Fó(ñÃVl@IÄŽB²šÜ˶;îwØæ™c¦Êíî6Š…³Ü¿*HyáÿmTŒ ŠI‹ëÏÝPÌ6üÌlœs”¶cùŸ7zþqdVçö„&IPôW'_¾-ìºRéT~•x¬ãz&eI=×
+6ìH|š_¾tu”HÙ!vÅ rf-A¸Óš¾ö
+W—fu §é ïPQß}G:B®@»ŠÝ¸‰ˆ2*½;‰¬Œ‘G·ÝƒÜÜ9rŠ§ØÒˆsª9ØwC„yÕ`‹•ÖÁ¨ÚÓáUÔ
+µJ¨6è,òŠaš²õ!B:k*€ô)fàü\ÜSù-SdºuÃ`êÄN -„Z±E`ÙÛYsJš9ªA([”KNÕĈŠÃTLÀÜCqÑ–Œ¨:B+Ë'­;£¦¬PÞ!ì=ã¬Hvˆp1„<±"Ëâ/AXÞ cDY,.Ç vC$´:1ž„bP.&ŽqKÛЉ‰pkÞÓ9 ¿»Á Ìn–ÖEj Á@5!¨ÕÚ‰]
+%Ôà!ì v‰‡KÓÝW…ÛTkÆ\ö;º]œjŽV=ù®Èë‘ nÓZ·’Þ=¯Ä×ÿßš•!–K õd)¹ÀÅ›zä¿àèÙq`{¿®ü%¢ruÈ€Z)Tsy0nY¶B¤C&oøЊŸqî>/!5ÎUí($ ‹/7\«A`3f,~{nž=49”­ì~
+–6{8¦Jåiæi^Gž
+wÂÙ›ï¯ tFTÅr¿î}JÔ’>”¯ÑgAd¡1Ç€(w='ѬsPš´¹.Ù%Øõí3‘œÛYb‹jpRå¬~m-ß@˜Qî3¦ÝH”pŒv—AÞ¼€®2Ì bpËÕ¿$
+¸/w²—
+É•ŒúÙV΢µó»ÄrZ¬3h
+ñ'åª0Úþ Ô§`G½‰Y—eñô,)¸BÏ<"ßècUEh-˜Yäl%愶é,2Ü1›Ð# üQÂc&;ISÎ31˜Ç¿‘|KGûƒÉÙeS¸\Èld¡ 3Þ@Cü©&ШÞî¾€¾n@Ç…Y#R–` ‘eäosög$ÙÈ_â&
+hwG¼Z>En%Ê߶6­‚XΈX†¬éÝÕXÙ,v+_]Ãê®Z
+k¬óê<øyLaI¸ÅC·¯ßX?ìbâ#Ó^Ôd¶”â4 ©îÝì Š81þ³çŠñfou"¾Zä_ß9ÛðzØ[§ÝôÇüô¹÷¼C<#¾±GÛÏ0å>ñ0­–½çP€]1-!Aï4oC¨/77„}b?¢0nH™â…úØN2hÜ”ùôNFeΪ˜
+Ïhþâ ‡,òV@ªÕ° Í~¡°4D‡!.“‡ÞÝ·ïhÈÞ8§±ô²i¾¶¦Õç±ûŽ({• 3Tê¹:'1Ge“¨o•˜¬ªóšgÿÏÕã×ÝGx†ÆfzÛrcúŠ Š™
+H‰Œ—Mn%9„Oà;xÝÀ$$Š¤¤e£fémŸ 1³êZÎýçcJzÝ/SiT¡þü–D2 M³H+-¹êç×Ç?òç¿?²v;²©×¢9'ÿüWnåPëÒjµ®êŸ?@|Ñ¥Ôdžò瀴jU“hïÒK͵‹hku@Äjvm&E¢Gr‘^T¼µÏ?ÇM¥(¿[mU†3Z³¦-•qŠZîR¥wŽ=RšˆÔ\$õñÔ»JÎVû2oª®<®Z*íéœÖrËD‘m=¦U-^Jí>ÃîÎOj—S­ÅÍ{ukŸ?>v 9Ü2ØRKêòù×Çî29L<ÕÄóªËƒåPO¤Xª¶ ü™_¸;çR…û[.¥¼D4/ºPBŽÚR"Ì
+Å&%.Ä’£7Ž,ÞKk²…î&D
+A ^1}Ïâ |„×£ð¨Ò”¿6ÇýÜax¸[ÊÖÉ|>©¡ä¬ä¼­L§Ôͺ÷x ñø(×Âé’Ý*„î©Ž‡ëÑ8Ö‹§4™8’ræ*ž5¬yMB^Ú€DGôJ9ŒOF½*¼¨]¹Ì¹º)Bã>Ó`‚Ô`ªÍ×¤Ö 2?R¢8™B/šfÉÄMטÔAx@%˜ˆÚÀ—óœÆëˆÃà0Õ81UÉ4+¿† UÿÔ°¿6h)v¥êÞÆk©’5è$u
+~?çF›ûknôÛEu£ñ=;·f¸çøû¦ú±(”â@ZÜAŸ†ˆcÒ„<ú/,6S‘y†òo@'„baŽ[W_çð_QO€"ŒÐ˜m&ÂDzz ÀåPb²)ÓÞ3ÜH> É礘›I;©]Æ<&S
+—û‚PªÔë\çb¯QITûVÊY¤Ý1_O˜(|F’í4q' ¥ìŒ¸õV0h©¥³GËY†ÀÁÌ 
+5=]Ð`#ÇØk\Û<…íæ¦p³39ŒU>‘óà™d’ó´Å"R_©ØS©¾/ùµm´fW”ÅÆ̧IRD\e3G)b÷jX‰Ù<Ü S5(-Á<;„Q˜ëŽ®gìgÆF”cÈKç˜íx!¦Xç ›8’=oJÂÝ̧[ÔQŽ(
+‰i6xqÇÀßœ¸•\ÔQó+æÎ@žË¾…_(kähþg:ƒVœkFZ{,€ÉDŠpO«à >2û9|­WTÉJW¶ú yl8§ëZ´©÷}½:ùÇÖÆrÇö¶]ÓN¢ãëxyAææk2e?o,Æ­ÅVˆkUebc {2¯Šm[D´³
+.3²:Ž¡åùŒY²ô†NÆla ¹pB8™È ¼Ž2eŒ©”°î«Åo E ÒÙzX쯽VüȘP-²…ŠVl@ô¦*¿û¹g y [ÑΙCpR ‚YPŒ0Võã5òoÖŒ©‡DÖ´fõЈ·>Î1¶ÂD‹èZ@µ†97~­«j’ý’ù±Ì«8ô~
+°?'¸c•Ï/ˆÁÊ„¹˜qSØ[4E¬'V3t•Ùºˆ!ŒX4¾LJŒEÙ&ÑM£%êËÈiw!`ëmËA=×5L)Ä1osÊ}_‘ãXw"ùu »Æ®Ã ž£å¢ÅqUˆÎ+¬wa¿«ß7zŽáPl¹j¤­~ˆ£_éþ2t6¡Ï¬2ÈÊ”‹’bñãpN0H™íZÖ”f¡ŠTá·lBâÕ”‰h9ËØšNÍLuN" dI‘í¼¥Ã‚ä4•²iá;ÐÅ5} PN™£²ŽÔ_!¯x
+Ö+úì…8cÄ\¿Á\ŸMœŒeJÖÒ$F¢¨ˆ •
+YÖÐODcŒ4rH°Š—ë¶WSJ­Ûéíœy]m9?°:™ÛTöÆZqbÓˆsúÁ¥ìs‚´0]³BÖ5ßðëe¥áºÙ
+7µíœàÏRÆ“Ñüu¨Ó̓
+.kTé6‰qsŒ@H]¢Ä¸Á²uŒwÞcÃQ®)Ë…ÜcÒEÿ•,[Çx×ö»
+Å ¯&´4ÃèÒ]º?nj
+Ñ”0d[Ÿ4©îË·¯Ânj°É19Ömª¥²?†¦pôZªÌuŽ$ÂàÛ Â8'sWŒ LŠê”0y ‹‚q±|”ûvŸe6Щójc1Ò›wØln:.ŠÌ œo}ގîäYÍC;ÍúÓ œ‚JÞ¢Ór_¶Ñ1oÏ è›cG+è?¹AWgKò>1T½°«³O›ýøf ¾–zD!/osܳX?¼OÎ{;äKH"‡ž®†ÝÃ{•…Î'e–q…Ú)ýòG¬"™H&£¤‰¢gÇ«^åkXƨ¿?†oÁ#è`²³sQ"åà”æÒ¯…`$œ³]!;>ÔBáð©0|¢ÈK-Lª5 3ã2MËñ¯RY¯ž@»6 C¹] ="\…²¬µÅ°Œ›D¶ütÏbåã¸ÌZæ×Ò"³†Â(e91ç¤$€­­àâ­z7ŽŽà´cç$ößž{DÔ—Æm½\õ…NÆàUäKº<Ç£9EW1Üý%Ú«zx+͇»VB%æÅag ¥l<½³X7k%°â½·FîÌ\к^ªÈsùŒ:ïиnùØF7h¹yþXWœ@»‚û‘Z¨ÊÚ> :,Ò· ¾$I¢49ÑIJqT˜»6`$è
+Óç$»qéJ³¤¾ƒ¼3q*#‚¼
+Å‚¼‚z•bÝÊ{'…†wBF¹yßBتe'7÷ùÓ´Iï2C¾ãï\¾ÚgÐ#-¿=A݃ào?é4|b“F ³íváýĆ“=LÌH¥côBç–CŽÂú UÒ½Ax •ŽLË
+ ù:¶# YFE
+¬~&"çYPžNwÉÏÕ2iŽêÀüom÷ñ¢\OÂirÊC*…ï¹É˜[ßXés1“©ìG¼ ²ü°Xù±)Žg0{Ž¥‡ é¶u)tE‰»An2 ¸—ùü•Õ{IrÞ}ÈSkœdÇðickÇÎäò3û›N[-|š¹Šòî>æ™ _ 'æœôõÕ€äôn Ú’‘A™Z#²X"¨Ñë@|uY!W4Já¨#}[7W •Z”j¿«øó1ô­$‘·TQx©òÅmò DLTŸaˬÓO ÉPnÖÀBÌWÊð :Š‘Íwµ¶¸øsºöƒm}3Åã¹¥º;Á!}wrŽözf«9&«lÙË*Áµ&½vIpT4Ò1tw —çÀ ”ãQ— OïP¾b\#/çÊn!’˜ EO-V¤{p¶ª(„=5Æê7Åxß‚äRQqÙs6ýÈ4ò›Ãë[-õiЦd§hÏa(¬gê­¬€*O¥‹Ó½æªR[²Šx%R‹Ÿ÷ÁP!zO¾¯„Ÿà’¼AÐL[ɵl§,Å¡.¬?0 Q>!‹…µsZfè(‡3ƒIH²ƒ9ÿ6šÞKJÆB¨¸¼Úd°œïlã´ ±Â÷°R›Â&ÓîÐbù%Ÿ\¸Òƒ,þ1 §c ‰P`msCþŹ¤ö–Œ™³³‰Õ»Ö&o‡Ú,k‚PˆÒW’9=™£¯óå•5+·ý2“ÜO•ÖŒ!íÏaƒH½ ¡nWÆ#²NrJüršãltà$² èÔƒyô S‡æºêåf7§`OƒúöÌ4kèø2óë'÷"y]CCSNHF?B·X´ñ#”¤~ïonüýí¿xÀŸùõ›zªtÍ
+îwúòéßÜÿÇß?ýðŸÙÏ6«ZH¾Ù¾oÞÕÕ9
+úBË‚:î(tÞ¼%‡¦À0påpŸ-U 3kme‡¡fSKí²Ýy|mø<ÄuÚÞž™®aþ(0”IT%eŽmYH
+“,½OɆVƒì§²
+{;|ôðø’7° ´û©Ì}“ø’&Ú@F¨Ê‹zXÚÅ_#Y̔޶+û 1–
+ŒcŽo!^Î[­ös¶Šï¯Ù:çôQ[îÉÙúxOñ!ä[©þý›¡™~Óç+h“Fýù8œ÷õK&¥Èd¶®?vaˆôB %œ+…‘óT E™Óʆ\92¸®È'®UÇô™5ôo´yL‡Œ[SÏ2u¨ü.wôÔfÐ>#6¶Nc:¿¦ñ•±óá1t{ø¨þ"w0?‹¸ø‹ÑH>1_q妿ø£T´!¼5€’¬IŽ…*
+Õ²÷§–Fз:#€'e@:þÒ‹¨u‰€¯=7¢Tí ¼Ö‡Ë ¥ 2ß4è5æjéã4Oª› =ÉX­«þ÷d:ÑáÇh¥¤Õž¯jŵàÿõ7_[Ð HÊ«RW:ÿG´†U¶WÄvן"ò«"µÒ©Œ×ìÓCзm<CªacŠ¸É‹A9k4Uœ!89ù‘JÇûºN@Ð
+³¤Ý˲¡ &wÐRæ1`dÍÒ‡é}pöq¡NBêàîÔs½_I OAŸAWÓ°bLó:˜yOº<{‹Ì.¤É£B›!I¿dôCpýâƒÒ¢y¼s,œšbG,º> —i„yŒ|h­:Å® —ñ”ÁçPÍo!Þ8ì?´ *íé€!¤KÇzM”H «ÃM(’6"
+û§À‡—RBK"Ru &‡…l²¼”ðC…¢ìo¤;N=Àƒp9Å àû|Ó´zLJ¤JCBÌ «·MBßR¬%Le£ÿ1`«%Œ•Õ*Úß–Š
+»¥Ú,0*ß05.ltšB¸¿ùU:#úfÓ´ ûÝšŽ5öþ{ðzä$Ô"únÀP¡7 ’Õ5UôŸ@ã7ßTt0盥<D É&{Æ(¼G| ‚%"”B1?tš:ÙÝcå5¢{«KL #ú“ä6+q%7 ÖºJí
+tÉp>}zO`Ùvw»€’è†U0„3hI E ÉŸ3 Ž„B•ºæ®€¬Pœ]˜ìι’ødÜn—O‹@aYc‡.£b©{B‚Ñ°“æcw¯å·ß{ÏD©3•ËÃ!ô ¡Œ9 ‘ø© >+ÿ ¶P‹Iß{ïI Ã\ÅHñi6Æl$‡ á)ä«^4þñŸ±ŽŽ4áo\“„ðšO­·¯sŒ¦%]ìÑE
+z·>œÍŽÛÉâ_Òè9JO˜[!´é„ûN4pÈñN‡ZιU|ÍÖ9§¯Ú:pÏνï>E|+Ô¿10r‹aVRÓbžOuÿzú“òˆ¤ù*\ÓCÛÂèÁgÉ\Ò¢
+ÕP8k‹Åá¬^…cìýî.NC£c00
+Ìæ»—¸¾7oõ+y™ÈÁ:7€±
+¡)Ç‚fÁ¨Y„Ÿ[Z7Ýú‚/g×å. 0?æÖ]à ‹…1 O!’ V/ª0ÏŸ[ù·ÍÕ(ã`èùã±ìáF…‡ "RÂÏòOžïbÈù¾,Uö™Fzb}–Õ­PsäûY K ¨Š~…_§«Êµó—ObG*¢…à©+L%ëzW_è÷Ú“kS=©IiÓÓ9læTþKy™$GrAðó‡y ûræ•¿˜+ùÿ«<°4ÉBÙ’™Ì4£hK¤§p;¯O‘ßÂxSY›%ÏÒƆqyZnJžÚZ0´ê!z“(“!P;i~</ÒÁ"•Ø6|öSÄç`õŒ,Ö4Q•%ÖÞÆ‘¨Ö®Ú£ ñ,§Á²YDÉ„ ÚTçó™`E¨7_^)‚\­A=ùÔï(B9eÍàßè-ÑdÇe¼€vù‹%W¡1CŠf}ñ(îæˆ:ËÑþÒ¥L±1ÒYe¿|í¯Uìà%È~šù^»‘h[`d5…cêçÎú2zhs¦$4ŸX_ xþ˜"˜˜YÖ”9›°£Œ‰1ïyÊ2iüQÈÚR¦ϦÇ|pusTóƒA™À« y™ î8~0$À–TažÃc ©meZ´`6ê(OÞïµæ°æŽMS2´ð«Ù² ¢²ÔfˆÞnD”·jòu A„ø «WÞZ •yD5„)wøº0éúz–7{ RË’pÛ ¦ß(*´`ˆ°Âƒq{-T^í;ÌÜ¿+”ú<‡9îˆaNv²~Kúë§I#űvê>fÎ(i¢]h¡?SB4åãÚ*eg|œ±S^YÍÄ=ð´ºñ7ºÈû#ÓcWE€…ð
+V:e8tÒØæÖöÖTD4Sð»,:K_Ò"ë~®AïóÌ1é´¡ëÎBÐYM
+ËÜ„]p½±:{ŒŽIêÓÃÜ In”}Ùñc ×aÈs}ág.¬JXSPÑ17¬¼Pþ. oPjm/œKÊ“H$ít
+¨ o&oïÛ´´ô€€ÝÏt¶~:ß/*«EEðç(kw«Ïß… ЀôÇáôÔdueu:£k.þ;$ðV("°9>5qj
+>æ¶Ì¡Ô;³d…ˆð9!sÙ’«r2[JpÀîf¦Ó–{ÙqzõwçtŸªîÁ°\Æ?«_
+ ®ê¨Â]ÏqÑôΑnÎ,ì>˜Øˆ$T]*ÓÁý¹ªЃư…•‰²o"‘Lp´$:ž"-ÑYŠL1øƒŽ eé«ÃêåJÜ×»MŠÖѽ†q1éq4`g^”ºüâ.VÞ—R%®[>6‹ó C´ÈìÂwõ7èè@–C¶ˆº üŠŽŽ¡#¿tݨΨM#n¾?ÐñTxúÅ“¢-чÅù ÏZ®è(§LŽµì2?Ðq´lžµ¢5‘PW:‡ZLäS‡s :ôñ7è(ßqj:Z8Ú:ê†!ˆW¹=Ü/è(äU^SÒ :Ãͬ†ØÉŽß‘T¼ÕUð²mºüŽŽg ZìHªaÈJr{½²£Nêžl‹®›ìxºûé¿ùè„Gì„6JŽµ Ηy®-|‰$º®a|ˆ øAT"¢ªú"F*Æåhí·›oý¦ÐQø‡ÞÁ ¶M"U2
+ 7…éÉEPŸÊôfR1@a#øS4 ¹­Û¨¯¡Ó…öm5êÒ`7Û¢€*•éÇõ%jµKäo£ª¼&%5i*˜©µ¨vj;ë;hQõ³·ã”,„¤«|(vCñÿ~ÙW3Gh^ñMMé ¾¦õ&
+XË&ëW|#(Üäj-ÙEJìˆ?^Ÿ³³$ëá®èÿ³"úfŸSðòÔ³²¯~ˆŠÕ/{žnW:wã‚S«3G´Åeå…%’ßñÝ4²€ªXÍsJÁ“(ò½":2[iko$ß
+ôõ%:ê¼P|üŒD¤ú¤àl8ã3Oˆ.&`wÔEô…ðx១ղ1Û>nD”ÅÜØ‹Ææ„ä©%”£V½cà´%¡…Ù.ãÞhóóK~ÕºRF [êð§/órG’:Áž6J³$~ê¬Á6¾$ÆÑRôÕmC¥Q1A%±n PQÐôX
+`­¨îÖÌÍåZjâDŒC†Ð´$¦±ú™°SCì}ÐK*ëKô/»o x<ß PxÚºŒ§5å}I”Jž$õdzƒZ„:la×ò×åoH<¾Àç…-æŽpø"Y©üž'ë˜K²Ï»\kÆzÒQzghŽ>lH¾åéß3Ýòö¹éçP9}1Îû¸E°dl½~Ž¾HL@8Í¬î— ;ÐØÚLõZ{EàâÂvÆghÍ^È‘&¸©§b㽑÷sG Â2Idèf³k¨˜Åž0k²/“y‚2L5û›'eœ¡²AÒeÑGÇP _/s„Æ{³Zþ9ÃëñSzØ»åÿì_˜"õRî–„StÉúûHàϵ´Ì7už&çes{’SëÑLÁ¢m±­ÑèŠUòg“¡H’ƒœ •˜kóœP’âËáí)lXä9ÍŠ°Î =¹O¤ZömX¼2UWÑЭŽ€!Û°[`Ct‰•u™UÞÈ•+ù[±»½D/e6B­Šeÿr.Ã<×vW¯\ÚIߎ•¿Ä°CÞŸú¹1ß&m»†lDÕ ¤?–ˆ±Jß±%ÛìûÔh¿sXnÛ£”Ñ¥ Ãß!¨”C¦‡˜ì†ñš+„êïý®ñ¼°.ëoýþÒy_aÙe)«a±Ú]åí1N  †dÒlÛæ f9XÕêþR¯ÜU.µo|=&¼0>:
+Cû2alFx0ó(Þ=*²1¬ˆfò7çD%FÕÝRÀFaü ôU:½l¡º¼m–/‚I9…Ùå‡èÂÒ¿ð…Žz.þYfÛdfÐraÅ©a r €<ŠYÈ+Ðx?wF³'@• Õ¼$ Õ íÑÀT(l¶ül•»œL´AX¹jt°ƒdD)óVÚÌK:‹‘ó!!8ÌØHUÜ–9¯xˆKŠîÎ!füo—µügõP m*p²è L¬kRa
+w$‡1B4Þ—Hst" ëùŒ ,Å zæµC,´½×nÂì¸4.Zúò]ºÜ0„®[š¡ÀêSãÙ¹àÚ8‘槄‡bþŒëUÈ*àñVœy†ðª1‚Sû¸q¤2iå§EO~Ƹ?—ŸÚ^DQšp½nÌøʨSD’'Ÿœ³DC"r§N{­Ùcµ’ÆŒ²Ñ¶´1ÎÐcÌͲFÔ:ŒßÊE#’0¥
+óJ>«h´MŒQGõ8mAýì0­œ,@ô.M·#”Ø'†»tCófk²L50¤x#Ú<]øâjÛ¦pb耥4ƒ#¦Å×]öÊ%"eJ0äÃõ¦ç1¦KFØ6Â
+$­ör½=ÏTýœò×ÁK
+ä…üåeŽ$GŽDÑð-·†}ÇJ¥:' Vûþó~
+HAâŠa
+ŒÕBið,ðâÊ.¯ÄJE—BCݲà?t ´ÅY@¿/'{/{ÑY-Êx³@(Ý(è<A±u9`™8÷ÓÅÎ
+&d¡Â³Dû.‡û|¸TÙ¯âö×íY&/µ <(¶ ]ýH2,CXšÈ !¯D­éb™±žÑ›¤Å-·˜äìÏBFõ0¢´m>3O$§5Ï.Ôñp¸«“¼x1yóÜ~§À?QéÇ•¹@R¨ QÍDÐxI49·²€pQѱs½ÐX
+X'®-ØÄŸÕ>™.“
+)-.Ek¼W\£(²£íõ2Û)$Ϙ£ÜöÒ­W~+˜)5‹Ô‹±Å߬"Ëûä‡öAΪ”úvÑæ}ÆuÌ,ƒ—¯Š^Ÿ bÆ\ÕžP*?ÁÁû÷J~ÅI5žé)ÎŒðs!8ò›¦º+iè©;3SÔ0ôruÍ>\d"ÔRã:ásá
+.~”ÈHI´¤YñâD…š–Ü| Âï«éqQ-)„}9a5áe+øqÝÆ*$Zäù»L”ÁÅ|!ó;|Àj|Èê£â¬y
+/5ðöy¡ù†Uì]qìHÏNXÝŠ,*‘ò@‹LÇ»E ¹.½Wͱ}QôúLV£rÃ@®¢;Vi¢¾Å(èŠ ²$õvQ¦UòcL w]nµÏ^fÚ§hƒ•id"þå|ëŸPø[ØñY\/ ­ávˆŸ´Ä‰ANaÇ_Šà›Ìú“:_ÃŽÓܺlÀ)ìø‡Ü<bWúP–=ìx¦Î¥±¯»ÃT d-¤ØNa'<
+†¯±ãÞŽ;Gšªsnál;þAijØS}^ãŽÇs M\> ëë¡ÿw(åÅ°\±žÂ£‡„Áçrâ»Òk,¬ƒÌ{´ÃŽÃÌÉpÝNaÇ=
+Sf<±, x;î‘•ó8©y;ëì{Ô¹×XIg¯¹ÃP«Í[ÙNÀÉ òšb¥ER÷¤ã0`WR8-¯«÷SÐ1F¾Sè*øæXB>pyHìoéÍ Ãw 
+I¢¤ç7/)ØI68¸C/-ÙIgà•t@äå!j;%àÚµùý”t6n·øï+9§:y¾êCÔøvÃòs±ö€€Ëb4 %èZäAX4·¸ß
+ÂlWĬ˜³.º¡!€ldwìcE÷"kæ ô°µd[ÌÃÛEp,à/AÁ‡7¯»}¾³¦# #§É V€0Xò U¤ôÓ,2‚ E¹sFÂûð/ŠHy—ãªØîúSER:ä€ÆpŒ×7Š¤JT`Ÿ’€J
+¹b{&Ax £eçG kÂ^dÞbq/IÕã\#°0£ˆldž‚Ñ\Sí—Á¢BzÏÍòBKuºœ% ™F½‚v¯ß æ5—õ µ=)~;ö@´á§§H¾ŠÛÞÿ×gý0gtêì/QÔûZT;Å"À¨(“¯~ö—)€ÀZÙµ®øŽébnÅ(™/®hžÌs8¦`Ë‚v›÷Y¾½ñ \¼œÖ(aAJ†hJš7b±„¬C^4XmÐÅÓÜ£Îtnº„‚ŒuÇâx?" ipJõ¡äŸ߬¢ æåÂ'·gýsžqÆEoÝXÀ^©[ÑÅ(W+‰æâVX-7ûóP$æ ØRtæÚ?>á™À·òçŒI8
+C™%Bçgíùq“|ñ{6}V§“-=„qû³Õ‘]XÆðÕ;MÚö°Ã±<hQbdé*·9ÛƒRÂWgÁæK\t§„Øò¬À}bŒøl>/a g1éîoV±¢8í)²7}ŠUÈhˆ{*ó2VP64ŽN4– $?Ÿ‡áåD÷ÐÊe30¸ú ï­7ô\õyá•4EW)+mœÃo¾oyQOUè{º5ùV2çy–uÎmäûÓÜ‘c½ÔÀ½9Œ÷%/£úñÎÎh½ÜX/}="¨7㼟‡¢ˆ¹T‡dÍÿºJF!J¹j4Ï “\¡Ê²\ŒŠ;¸ãóÁyj>â²eõá¹(±ëss`]u¬ÆÚl«oÌ}·ú@ŒMêâ Tís@3 K«NO“y#›šâá2!ßÈ©}>úM=BZ†”d »
+gx£¿¸Bm²wSÜ%£Eš<Ç$#ÐCqjÄ‚[Ñm쟇"z‰ß Ý—0^
+ïΠPñ6+пê˜gœ»We¹›Rì²p7v‚¿~í°àç‚c^+¼„Œ« >"pãœ@BtdMÀf˱A”»ªo˜°Î Ù’ÛRþ¨O¼&U'lhJoêMœŠíØz QwÑ0o®£ó$Ä)È-9Ì :A›P¡ã.m‹³„‡ªøÁ$þeí“îfU ¡›³®úz3§ëö\‡™¢E­šüsÖ´Â~ÆâRÛaú9jí¨©¥Øh•V/èUÙù
+䎫'r,<ñÄÉ>ü+ø¡"1Ì4º]’W"nñûÌ[‰ǹ`ù}|³Š¬œt%BF€¬úøv×Å’õ™-4Šð«¤ÊèɆe4à˜µïK)rmÎ1™šg‰ÇZ¢ õɱ°é¶e/ãy1Ì÷25)yT"
+)±cÄf%×Ћf´ÞÊ!QdJ‚JWAôÁ‹-"â‘ÈHkœ"ê¸Cfϵq%À¨+­Æ¹7ü“íó jyæ­Èº>%±ÖÀ¹¿]t[ÀÏ7–ô—ÝÍ]9+Fqë`¡HŸ
+©~€ž¯uv°…¸˜CÝk¾sèe¹b¢Æ•4¨bøK
+3Ùþé²ßl‚{„€Ðøà§7VŽr^hë¹rc8XQ!%5ßGž @çPò¡§ÉW m9u<¹ !K3C Y>‹Icï«3Ç^ô6íQÄt&‡ÏŸ®£l:rÚñ®b>ßi“:ú÷iêþ÷íï~E\³ËÀ¨Êxv2maE8±Ñýò÷¢Ý…ª¢°LÒí¼Ìÿµ%ïç‰ïw4¾YbZd7Ce֠׊.º¶=Ä›´8K"fã‡Cž^O¨?0û¨ÀãÂP]¬žÇnEjq!²Á
+V“”’ѨßC󇆩8<ÉÐaíK®r$h*Co‚c˜M³ ]?cÕ\׆ èûtíç…íº1­ëƒU‘äì#\ZêÆn[B–`S¨”¢¼Ù>ýu¦² Ä\6 ºjíjkÈ:˜ Bo˜7~8ÆÃË%öĈ,y{
+$‡ÑóhŠÃMYt߇I­`,¤UþLKSÈ$24”Ûþ³²©ZÓö}î ?öû'6<×Åcr,F‚k‡©9\ŠÐPVö?Ó™µ.,eVÆÑç:Ÿp+&ìÐ4Ú÷zp í\Ê£Ûɉi)NU~Ãà¹i^³Áu YE~ ʹ°ÃBšâæ)¾o·¹‡½ ¾-Ú¡‘vH‡´=®sbÒ
+ÀAi» 5 ‡é Âßø®ª»£dP±Í/Á)vQ(ÇB3(0£Ï9¿&D… L±Óu·>žìÓXé¤uy‚nç§àW|›!cÑÜŸjˆG¥¶“p€c´ž.³•†ƒS~ÐpŠ Õ¼š/#b\ñý©+f+š²@LÔ«‚"b@¾ÌgTËcš©ájD
+2êë5þó—+é°Æ¨~2
+£0>1¯äÜgCè~*ÁxÙ»RV&­n{$ä…!cÑÇ'¤ÑJ”+®H~ ·~ž‚LÐç¥.\žÎAxš:ò9V]¥âÏ4±tNò>­CÌ ¢B€y›LUPÀ†w{€  …8žØ›¥7* -14d“jHçÒ¦ Ä–…
+{Ò95#pÑ“2“Ê“¹3]}«d1ñXzæ ¦–-ˆ’?§°Þh=ððµ¡r•±¯EÂq¤¨{PÐAõ#ëJÜÓ@ié9Ú¶F¢6Ì•ž}ªH]Âà×%3 Ö­d¦ ‡1„Çœîº_uJ¤Ÿ{ubîXqX2lE”É50‰x {ðH»jÕ/9I#]{Z>B¦,ÖP3¼`ê"?1@†D¿2œIAq.¸—SVd]ß&7ZG %$ùBHä# Á¬ñ®ß¤„–ƒItÙ½!@#2ZÃgj 7HãXÎë©êÅR §Ë œÇ5—ÎÀ"Â0.XŸÎ¡Û‘\Sù¤ßF¶‡°íŒ°”‘þ4[Y?áÎ|¿ÿa1¤Bl»ìcÐP­°Ò}w3Íà 4ÛJTËfLPÓ„’¦ØLÛK#¹1ƒÑ-Säè{ƒÄ2fßa‰¦®PéGÅ0DñůÓÅZ"ñxO&|Õ6h¶IÁ'°à®døPã{š Z¦˜+¶—îçTi¨ùíxŸÝüDø‡zšL*½Õ‡S` :K/‡wJ9 ]ÑNá Å“*¹qˆL‰ÁëüåÍPU˜‡Ö}›û0Ür&ý0iMÚòßãê×Lµ²dhýé—¯3|ƒ<“B™¡ö„AY›´Wç(œF'XŒæ»€à,ˆÒ—:ùG> ¬ògƒB×°gÑpÑ oL’úeÒ`DªHŠîeƒ´°²_y6¡¹„JbÇ¿ŽJ±¦ÂQù
+i–ÎÿmêÐ="aŽå
+Âyl˜w˜ïâà
+U!î—£XÕݪ.ªØ6ChT«õUãLaqª!×ó4§kH°$·äŸÅ”¸—D†n'阢a ÿ´¶õ;Da£a½ÿrþ)´ cpUÅ$Q^V¡’ö§:jX•öò‰8CQÑÛÏÁVM$d?Õ€*Ü&»D}Î Mˆ´…°šsÊqµ3“³˜¼¬¤• Ÿ™kc- )¦µ£§a‰—GTñë0u…ÿÏÿg¼Ì‘ã8‚(z‚¹lˆÚSA™tu†<ÐÔýõ~WV“˜Î††ÀäÔ–?ÿ²Ç
+Ë'¸ïKñpY)TÌó‘ˆ-©—Sl“·£W¸ª¦›µ­ûXR½û`(Ün>•Øpê$PGÈwë td³Ýö´?v†1.g âH¿’n«
+(}FG$®¦è|YPŸ‘©/²Ä»W‘rJ0íñ¦Dv »EkÆÎÏ5š`5 ‡ÌRyç¥îr²Õ*J¦ˆ#RiœxMhöhûæ²z 2+F9©Gð€Æ(ïGNd6“EÛlV¡k•ÿn²=ªõBP~'¨TpÃ2É_ø)ÅѸ²9²*–€kÞ¸ïñ¥%R•`§)LGa Mõ'F\Ë·Ôaí¥}—¢ÀJ…ì0«±j€)È/î¬
+øëìa³tãY3®ƒ—²u‚Ryeû<\(>‰6çƒ7êû”å$W0ªNÉõ„¬Q¶Ì+:J0,p=ö'6ÿ,”
+>HT[ëT\–‘
+£ZE8RhÈéí…žûÅм’¤Ñ›ŸëTÊŒyê‹ð¯óS±§%
+@W¢±{3¤¨uû˜YÁH®Ì[4yIr˜˜™}Bû?^…æÌY® Ä5PØÖAÇ9›ý¼)â÷ë÷Y¸Æ÷U„<Â=¤…˜_.zR¢ïîv¯‰G‘Ò¢8“›¢8ˆ¹3L‹
+pÀ{AûÝ*š у¬¢(˜ðǶ+ Ìä»P7ó£
+ Ic嶮þ\äb0a\Òч9æËEÞ\\¶{±èÓ¬º.ú¾æž—ãc@§û¶3„S´‹!Šf›h7‰-/曢(°£4»HÓ×pN¹n¬«€,À»YýX[ñn(ÕPìò×AÒ©ÙiU5&gc@ÙÂÞ­2Ó_¢ FGîWÑ©Y4¼*D°AÖ}Æ‚ôˆsª}-¾‡€£Œ¹ c«[¢³<!‹$¾=œ"·§ÌH|‚ßÇxµHÛ‘IŠnÊä¯Æ_Š86©’›7ÝÕ:A÷æDNõ™ƒ~*‚e‘d¾c T Û€2°ãn<°¦ž3X³€mL-áßæAAê0Ó•Åh£Š,—ˆ{æ˜6‡ÏEîû$òW²°eÞNÏs‘àÃo­Ì€w»êˆjwvŠ>^™_áµË6â9lëäÜŸ7EŸ³NãôV*!LbêLÛl6¹ÀˆVÂ0ÀpÏðòr Ìï3Šr×üõ]„e =2¢pÇZGé6såÞ·õe_­‹fÎU‚I,2%5T§äØŠðEÝ>üyŽØ„{ô`ü‰ci šzÈ£¤s©ªh:,  xõã”XÇo§è™Ñ?ÎfÏ2îùj8/W÷Œëå Ýu>7ââ¢/ýô̸Š8J×RÙv‚ ø|ˆ¯  ñ¹(Ïȃ8‘૪\èP}@ÖÖ÷V_CY¨êa><°TCc•V®í!j&3•—"8R&ð¨e‰K€ÁPû„ nçU`#žæe-/¹lœœ ã°šœTÜG—sG jØч6—ìñ$}=íž}SËPŽ¨ÜÒ<÷a[aºÉ—yò-Š€ÀQMí<ͯ°ðœqîà¥ï¤ú#üqºâ z]ˆ(¬>ëó±ƒ)O¯ÕŽg"1|[E—A|©ˆIàE¡Ý¡à»‘´+ëIçƒó\ ¡@Ù”&È1v#ôŒÁ…¾š×çëÆ箺ëÀ¨ø›À<³bÕxiÅÆlƒó9ƒhlG2` B]kÛU@$@»2ç;×déßbhÖ29ôeۤɇÀÝ(ÁlÅenôlƒæϽÏדµÜ]o°:Íïš™@< ¿B?%-ÙqŠ+ì´D ßVÉŒnì‘áJ9ö\%¼/øe(̓&¤kÀ-ðíJ´!º!ëy¦‚mäâPLYëÀ%$¦°–VBa& y ¢3ë±HƒWñcaY™ƒ…çÝ*™E©Õ.ÿ,]ÌUÓ£Ã÷ºwêï"¬•Šÿ6ÕÆâ
+H‰Œ—Án¤¹ „Ÿ`ÞÁç¶!J”H“ã\ó‹ädóþùø‹jÄ¿Õ³ëvµD‘ÅbñOéþZLj—Q´¿É°ñp¥Io>õíÏ RZ1>¬ÖtAÌdŠÏøxAzmRK™êÓÞþþqÆ”ÂÿÔVê©vnfV}3º¶:z™}.HÓQµiq¾üR«Çn]ëÛÏÿŽËì¡fJxÝF6ä1môA™o;"çYáv
+½E§ÔóáZáº\\ Hë\¥Ý)Ö‚P¥!œ2l ×Ã3‹M«sÈùœFayÄœµ28X„ö1Â!¯39Aü¡ š¬—ß0G¶óˆQGÊÅ¿ :uÅý¶ïa>õé‘îwPö|…ò}¸CW|¼ÅÇ /½¦p}ˆ1Xø©ïÉYzÌhÆ‚ˆ%D®Ém³Œ57ædh!­è}¶U É4ÄmqPkÕ¯žã*+Ä“Æw`y]gèMÖï-^È(Œ\
+/ ) é% æ
+‡ÐâÞ’¥DOc—&X~†±¼{ô«= ŸùR§’˜œ¦Ð†„ÇÕz@ÄH†äåjü·¯˜Oü[¡Ð¼ŠŽ¹%¤ sbóΫòÉZ{ 1©Éb‰ß:C‚Nz¦®‚GÌhòÈX,®s04Ì1ºM÷Ⱦ 6y8™a’M_§œäw‡s*
+ûÂÓ[{Meì •5dZ^½ª’?æ;õ—þ";ÁSL®ö âÊñ¤òLÙ1–]=@<~T
+Y]zBøUœÂ…Ðû ÐhA¥Š ÷¾.+¾wèÐ]ó0êZõ3[Z3¿P~HÔæ`4aJuŽµñy:u ø–FÛÑß¾ D„nöÐíì c­ŠÎ}´ [p–ç{uø^q,ÉæFKÙJŠ©¼ß@¼æ ˆŠ
+¢áéLª¼Û—t#$tHÏì0Ù¹¡¨#™<ظswËWE¿O
+`<¨´Ò
+´ZjW»úx™®Èã¶Ì‚ÅE 5Ç"ŤÝË„´’â$õŠOÃ$n’Bþy̓šÊöj3’Ÿd×pz“í+!üm ãc÷Ík(jhø‚D¥ðŽ€ø¾ŠÕ ¥ãQ[eþ\óUJòo2~ÉXÍIŽÂð`z1ºÍÕðÅHÄóª;(<1m¿§ËÅc|„̺ áoŒ]±è2å÷.âçŽÍáy&ð“Z„‰éŽË 0uwùmÖ}õwí:ú"¤19´Ù«St0ÿè{ù™$û·[+ƒ»¶çâÉQm´õy;~J‘žt’¡a{&øH]/¥!û\¿3ÌpéŠæÉÌéP(°0ŸgBpl t4z~Y¦„˜e¸fµd˜æ9±Ñ2ÃYOòUQ ëb{†|²
+?³}Ã>$T9€Þ7#[$Ò˜ô¢tÑBB6Éž†˜¥Á£®ÌuèU·HuæúzõIø.þYÌOâ µl±@µT
+ã‡2¤òS<Ä·f,‘ãXæÊ~ø'HRôæ’¾žs°cl\Åz¯/ ŸlÝÏËý 4:F%‚È”K“X„h‘uJüñDizŒÇÐ÷· ‚wb™Ð}A؆8d"rÝ‚A¥ë妺áŒ
+'Rˆp篛l0t¸Žo-kx¢ê:Æ©f o-!PMŸað„>šl<l3v€$•aQp©„ŒŸÎ±°jd½DûÍc4@Kû|Ó¯
+P´Çˆù Çä
+ù† –A×@=v³p©,ƒáBt9ˆ
+ÿÊÇH¾óòþãpWøirK×Y[ƒ´`EÁ$öíîÿ×—¯—³ãðPÌ1£7Ü Jñó9”a†Å¡˜3!@‹6“b áGtòÌ€ÃØ1¾[峜ìSÆ$k#1ŽüÁø´·#µ
+™BÑc!ò3¢1äc[‚JíyÏïHt/‹î埘Ò4õpÜÇ »ÂÕ–Z;†÷í‚0È=¬¯í§Ýö(‚¢—7E†rñƒþ%̘g‚¸™Îœ–ªÉÒËš(“Ø5Ôc‘AÇk*ͧˆbl²#ê¢eíõ
+µ|‡*
+W8X‚©t˜4bÇ"­=ô; £f"ìèv6êo@ FnCF–oF½&µi¬A»càñ,Ÿ[5É÷ÓbÙ`$CèlïqøRŽÓNq¯êñ˜Ï̸‚q¦OA¦ôįx“Çš¦˄O¯MÓèƒíTµ`]éž¿¨ŒËa¸œjj7ã­Á— =u ƒ’º "øó}Õï[+ºðÒˆýëÇÿù‘?BHc‘ó½ªÜg€ÚDt
+í&áPKyNNºîÌÜ„°?ñ ÞS2yÁ^–9fÎ/“ì:rˆ®À{¨èÛ±§žJûŸþl^ée"]:Õ¸¬‚™$ˆ&ŠJÜ"ÖÕb.•U°51§(dì½63º>†/áB¥ç¾õ¬ËÑQýp•$N¦éÀØ’§aràëáÞÛÖ…œ;SâM¦”ªþÁzטë‚Hfä~¨i1¯Å×’=Ë÷I¹ç¼Û½Ì;j¼7]Áç´ÆðµÁNÉÛ þüd_^2Í 1ÂØá!ç¼/¯H2‹‚;ÏŠu*áŸŠÏ Òí%Ót0²X˜åY2^&¾”Ü¢|"“rºd€çßÓî$ÆÂQߘâ˜Çü•ìé«3÷»NOˆ!d|$õ—»¿œ#0ÃCnþ]HD]àhÿÓ›:&{VÀÈñŠ˜V7!{'õH6#“¯&Ëìì’„­g¢ànJ$LÿáÐ×ߊÞÿé!Ce怆“ØÈŒ
+³Ñ÷‡,:ËÖcÞ%L?šÂ‰m½CÙF° ûóp!À^'[«Åõíî:†ø€E|>{í0å]篠pO‰³ÁÜ:½dþ»ç˜
+3Ú^—ÛÚ)…`CdiçSßÍ©*›Ù
+Ô³9ü´W؈4`Å+v:Qø9aÝ)#›„7L3Ê(Êç1{ƒµºf£µî•Ì[ú
+—ŽÁs‹NÁ$Z¨X}²(âNT$×´?…÷
+â.ÉJ'ˆUZ¾‰–†ìÑ’Ösl°4w=Ÿú; 7Z m›\vø¹4ñkõT2»e¾Ñêç*¾¯ÎÆ Ÿž ÷ß+h¤ùæ?ßPa“µg í©™EIù<ÿœü!ìÀ˜©¥“ØôéÙÈn«'GŒÃ÷ä=ö
+ð…`W K‘™.´Þœ’ý%ZÊ®Aæ‡Èîçdæ‚رq‡È*‡úû¾YÂ#£Mu;Ù C)­
+¯G¥¹<©¶ö@d†í+4Šå²}NíÌM.(Í*áÝ8Pà”
+c˜ñ6z÷ã%ÀÖÈHÀS<sŠîñÌ)º¦J :ݦ<DÞ¤Õƨ¤³a·$§/-¾œÂ%ÅÖ?V ç;×Luí¯›Í®crιÛ¹Ë4Þ“®Øs:ã øÚ^§äÎþk]þ gKà¶Dšc†!/œÝŠîáŒ8 # {ÔìÓTø稑OA†Ï£ìVò!œÉÇÂŒÍ\WâÞS\-6ߟκ?SÑZL'ÿ6ñ£Ãâcr„=½Š¬ ˜ A‡|–°‡œù×ñ#×|FIÓòwVãÌê–Ïœ¢{>»ÝóW&AßÖjôóOÇóö¬†Cq×|Ærb™.úùŒƒ™R‰5ó“Õ*½|vÅ…sN˜i‘K Çù\(ÅS 5'=%4¡#«iP…›Ð´3mÊ64knBóvï–ÐþsA—ç ýÝSÌÇ1ùZ5‚é£Ð#OL¨àŒ6’lù6}ŽùXi«BÜÍÿß{暉1P¦øj!*‹µbÙEX↠‰­§GàÅï€Ê¾.Q¦»€äFð'{ s˜±F‡'ÖÃäš)a:EŸ»ˆ»±ŠPø~µ% 7†é\ß!43s§ì¾£/âB=©&ïd=™þûêV1€ig(‘ K½Û› Zûµ 7„Þçè ¢8£-¡bŠŸsNØxt ãå"o$‰ðôU¡€È2âZÐå
+thÌûMM.[+í‡Ã5|Äð;Ó0Q‚ËÆbWˆàx*¬ ‰Ñõ+À¹ĉæìY:Eoäöé‰$1 tS®y¬DMº)'ø~
+ëáA”(HT'Fí‡@IjòÑ!™0Þ¤­Q‘×pÜÃ^÷]>nÃôdH `Púr䟣m1‰Í®G†Ð™e€6B›&>òš·•Ô–R¿š¥:IdZÜ„tÛ94hv³äø·u—зWó²¿N2ÔÆŒÂ/]þgC` ±´¶W‚Å¿ÊW2d{1b°Çà ð!Ó\ç!N^3|4¯¨Õ c7r¼Áû8CIÃSöj/;p;&òF’žºÁ:4q›œV ‚‰Md–»¢ôæ fë/„òg€@8ÝK¡rQì¬øÀ»p功ھ È$ä#äQOIb[»´æ”dlii„ÎnÞŠúŽÇg˜ã¬æ¥.æ6EÅô¶ý-ŒB-ÈMÚ ‰ @~R´wo! iÛ…,@£<#¿èÏ¥¶ù¦@ö
+-êë3y”ÌOMÿ%—¿—¨æd…ne/Æ~í"öÁb'A|7€Ÿ«ˆ+bƒè®‘¤DÊÁ20­>É40ë´g:)¤«ŒÓ/sÎ1åƒÝÀãÔÎ8¸JøFQð {ï°‚QBLñû—S$ipøƒeÖdÍÙþjõÇE[\‹ø®è†eR¤Z%™<סî1N r,„Íéï(­da·Æº(ðR@L[+gÿ®<É(à |hÞTj 0é·ÁUBì9¸:%0Zà™l:óéV‚WìfôÉ+Ï¡“'£S‚'CIe­ŸO1¬N×±kÕh*ÁýäúR‘ÊŸ€ÍD>m•$Ûøv.ŒYÅr7˜ÒþýË)r‡n>0F E?-º®àçOötzä•w!‹ˆ-¢Õœtôå׌L`èèP_4%ƒ8æÙ¸£íy°D°8Kžw ^Ž´lùx`eDv*ØLF‚""ÆYÚº¸ žÀð÷â25Å8' '.—)Ì1ùˆ_=aî{ÅüPâG±5þl§ ©˜1ÿ¦UA~¡¯èÁ.ÁN* ÙTZ5OŽ±‹LúÊŸ^Ñ[^ù|(B²Øø×½>ÆR@‡¶‚pF£jæ Vv +äVK:Ë>£§ ëy7säiûq<¹3%ž$c7K
+ÿuPÎ9×q;·¹ÂÆ{Ô}Nkî¾ö÷^ñ6¦??X­U8käÈØÐâ÷åIT"Ç 6Ý*¢É|¦?p¸´\q §9z{nŽ1Êìëm\€'×U{ðÝ·¹{‚ Ä"ªnJ®‚+,u¶©‡‡Û$«.×QŸ^e,#3&Õ£]2ô]ð¶9VS¸5ļŒcñÑ
+©SŒvL+'Ø™±IPþ¨/öZ„jBX~JÌzs_Ôý)ê€^¡­Ÿ\ã‚pf -4ÝÂÑð@ˆè#ÏHGÙq.ˆa»^uze ð©ú•¹œ†¹
+}>(1Ô“…DŽE–»s¶‚6€[ˆ¨Î§sð
+Q*†äª¼v)Nƒ@Q“–7¡¿»èµt¨ Á³µý&þù¼?ì¥k6g¥â·a8ù®WömÞ ("1SváÚïˆ!ma}æô+ȸ¼íÊ¥e5%^·aÛ;êÒš#¸)†6ÍË&"%2»c^iÞ…Xجé+ÅwY£nÖã=­Jž$·ñ­ÖL`%Àass?²F™‡Ñ¶í`~'³ÂV21
+²é‹ÖY´l¯ïäBåøˆÿ`Èhë!›ë â|‚ÄóN|H8Gƒ£ˆhkÚ’Ç`€°[1JUÉ šC:Î"1d— ÿz
+WòúùOA ùÀ+ ô‹òÛ@Øù$Í£@ ÂpÙ gíŸÄõùáh+V˜iè“©-Ûi×å>QøâEÊp·Ü’v~»Àª¸5ºJ»ƒ¿ba¶pXÕíYE–ØY&.Ž“k)6¯•vÀ-üeý
+¦õÚTD™¹£ýV›‚HQ9ź¾}+†ƒõ77;¦•${Äzö§F}ÝpYس!r£ ø®´>RºÙ¯»«aiÊ…‡îäK†–]5ˆÂ ›)ëîzylj÷h(Æ/¹þX3Ä…àÚ!C|g/Ó¿צjšâ‚÷JŠª‰²5›‹Fõa©× qœÀRåS¡ù+7½‘*o.Yc”fÛ­â·I#ò~óÀÑa¶ð;á2^Å?³ON¤ äBgZ¹µüDOL S$ݶ÷stÄMÒÍý6¤/ÕB1à 8&VÄ~X$Ö£óö©
+-ó7eÄ~§4®'%VÚ9eÎD¹ðíÅYˆ*)niÈ}[Ÿ¢¼n­Ón_ò¨±ª1]<Ú’èâ{ ,ûÄjÉÚ¿ŽlÛ˜ˆ±üÛ' )¸šêžƒŽ@Cï3ú‚ŠsÈ0¡oÓƒWY®æ+»[ü G°¶cȇ\\¤PvŽ¼
+W¥çf8eDøq-Y=ûä"EÇ«4ˆȂD©êÜCS¥˜Ð[Škº øúLKfÜQ$“Û$«ì^=ÍŸêÛeûpš}[†‹©ÕÁH˾1D›™ÉÞ7©³ÞY³_½¾J™I´^­•Ÿ9ý@|_Ó§F~íèt‡€Òض^ádªmÕX6-®ÒÁ¼­ÃÍìdF‚I_6e>§Ó›¬z<0Þª¯ã~Ëžœ;ˆLJÕai~¬OŸG/+Ý®§‹¿¾S¹•?þD”þñïüç5—ùc²1— j: Æï-i³ƒÝК®.Cpipä%ð=v#¦ wù Ô4‰p,W¯yÅ"‰è DfãOóè뤹^1h?À¬kC§–åfÁu3À²›J‚¨jh€®mn'ã73õ‘c§=¥f < ‚«JhÜê·`Uð“öxŒ/`ÊQLYA {È>˜ ¾AÖ§*“W”¦Jëç NäA4óÛ(·’ÉàjxeAÄ^Šn\È!ìQc£šxðãÇ”E,úOûX[GçQý>™¤P1‰xÍf­àeÌ$¹(Æ1 «O@rO°t ÿN+ª.dˆ±¬x Å ËšwuðÞ°&ÚŸÎðŒ‘¥i •â3†Ì»¿J4еÍÓ§‰Âå@vœˆ´¸R E ÍŠÃ\ iÖøò@(!È=íâH‹´•òi˜yWi…õSb8€^ßY° Ö›@n“?gývZ
+òK´v …/
+SŽÛ,kCP‡\”dͼ‚Yò€#Î+‚btáZ fÜ€õÅiOÙäÊR|Êœ ¢L0˜û^æò—Í…ìö£^#ý~Ž\WFykð+¿á8ÙŒaµ#ƒoHGŠÙS2Úþ§üÁüzù°|‡:S;¦2è|LŒíåcÖ‡N®¶î@=:ÃÖû—0NÈ$5L×ÇèÔóÌô(í`Bû6è´Ì·¥k™•ø°¼2T9Èæ ç¢Ø§Èb²w¾Ð¸¥€ƒÁaåÙ !ÉLB]°P"ŽÀÖÇl‚×TÈ­ÙO!ðåV$’Öœ36%l¦˜€¢¼1?0êvM*´[”oT5áÑl+j-H“¿Æu˜Bõ_ƒ²EÉTÙM9€\¸<M†“'ï‚^±æ1›¿^*›fíÞ ´ I”ˆÏ÷+³€qÅÌ™Ðfi<é0$5¬T–Þ> ªQ3MÌ4®VÆ
+EüCßHæ-rBÕׯËÉ¿ZüÎ ‘XÜ|±v«Vy>w͆°±×C:éOÇMùò„Ä)†B^Þ<ä‰ã–¶o%þ%ˬÆT@{;çFºÍЛ–æ„>F‰Óö3w{ð /%5öÎ0xç@¤-òCeû/^²ä,»½”<Ý 2ÃjÖ©èó¥è>ÌÖ¹1p¬äY*_`Ó_^Éý2&f×?ô ëê4awÃlr&_)
+Mò5Ц“¡„åÇ ¼òc½ƒÖ`e¢¬ìRÃ~²}¬NŽ>‰œ& ’3Ÿ%ü9DÜÚ;,Fä=D•Ö_ÎéR3\ݸ2/J3àE¥·ì%ðCFyÕ¶ :Ê|EûB`“KÁ¶µ
+a)ýZxÁŠßÎ+<QðL°•ÈÏ…íZÿUÂN³½\èË…PõíVX©¡ÛjÙG]çH¸ø¥Œ»Jä†2¬;ga
+‹ø׿‘E¸~f}Éè`µšÉÍ"Ø— ‚Ë‹ ñEg¨I+FÐPlÆ7QWhäH¸ÉwXþç°|}‰Œ¢mļ‹Xa
+||Kž¿}uù2ÓÑø—xz*JÊr‰$J^%pI’‡CwÕ’)xlH‰E«r³Ž¾ bUcÄ7»Å†¯J¸”àÍì+FÕþT/M
+©Ç\yæ#ŸR$…Á ÀâãíDœy3ßZÞåLf¶ó½»ñÒ“£"Y¾ Šâš²],[­ 0%î«"ɚ¤wØ’ü›ÛK }„~L‹ß¯/Ý‹DâÒÏ>‡'>|Èœ‘píob1Ù'lr?¸²M­ªY쳟ÃM…5UùNµ¨u²7ð3¹ÂøßU2àÜ>
+
+–NE³DÞ?Â:ßFÑÉ€f•Ð6 bÊoF<è©8’,k{ôóá£ã 2.²˜h
+‘b®o%˜$ OΘ˜ý¥GŽ†œ¤mŒÉÏÁG†>5Ê¡œAL$¹U2Št
+æÁǤ²\bøWXé%Á-×}Ò8 ul
+ØÀØÍ¿ƒñA– ­aóôW#6!\Öppæìj³€Uˆ•Ú ]Œêç¯süÓÕ,˜ƒC×`Ü1FÎ Ú:ªÓc]8Ÿ\Ñ¥úž*
+ši‚rSNÚ—•‚øÊ=™ 58êrHµ‚{*”ÊŠu/Œ<EgDSlÇáã‘h HZ¡rOD£´œÍyJbJù!Ž»“|‰ASA]‘8]É çÑ$'v?à߉Tœ ¬²VÜ€¯çáII9/6¬Eaóþ,ÐÈÔ>×&Ù\ëÙ(¢ÒAq ©–dŒr·'¿á E=ž;n6a‚¢Vˆ4+O ò¡Gt™ý‘ŸŽ+tÈC{:]ûõ“|±.‰2@}ÐI~Ï-9JCÅغY«L i¦9,»{ß@kCª¡›u/ Ì•UMEÌ ;£3¤ÏÒ·ì4¼úàf\ Íåò5m¢dÌ\AÇ×wŠ¦êæ¯CÉx¥Ë#-HUAj¬õC~ÿ:ƒ´HF=0^o.9›1MÛº~½¼>8»@ˆvÍ:s[Ö^ŠÉ!ÈÐ °ÖÆ‚XWAØ‚¶)Ñè2ç3]N!‰à剸¥¸“N Öõ™"~ÃðÜ…¨hN¦…”ú ÂÐÀ£Àµ¶Oº:²È q1­ïÔ9¯Ò¸¸¹µŠ7+åGUž„ÿf‰âˆü(%99m{“ž~(ümñÚ4Q?“¯Žø_“üÅåy©d«‡uô¡¯òV0ÛÎèNÇwóüe¶@ 2˜Ñ–Ç‘^;îvÌ>óTkËn?–eŃòczÏ|Q.Ä~åútTÑ‘ŽâGWrLâfr¯ïã
+ ¸>Xl~†„E*ÓtÓhŸ ˆ ­ƒ4¬!X/Q]C µ™G@0S–e‹óº13Ð祗ç¿X’õ(%— êëÂÒ§ò®ŸÄ@Y¢Ô呺zŘ ÁÕ.ý®üîN«©˜sV¬n²ÄÂÁ¨ür¦§ èóôÍÖ½@×ܧ²z¨EɽìÜ”`b(ÃÆBðn~
+¹Úö˜D5,?†»üËÞArÙW'aÈââhý¤ˆJ`¥ÔwŽVY…§|ì节ˆw¢k×p9£œ@'ÒÐm†…OjNŒhñÑ2Uë 6WŽx÷ü;…Q3“peAhR0d¼z‰„0¦×ïùR0C1å¨z¬–3¥Eå*(@<€^ k7oÓÎ属,_9â{ø |ò® ÒˆªÈ\¾§’1ïÕÃeTªÌÙ¢¯R$÷, †BÓ(@IÇ—+ä@þ™4IJ¿
+©ÏöQ0}–XœS"]dý7ŠÛåøüùÿùÏziY,ïDñƒÏ,ˆ’‡l› 
+Éo{VEÐ<1¯ú¶.aªžì“+ž±"t‡ ¹º¥º¥‘j” !ôëœ@_ÅuSÒ_x:T^ø!÷ ãRÆ=€½M›%­_BÐy•™ç7ŸÔJìd§þ™y+ü^ÞfÿÒô€"Wp½: O${ñ82…Ó„MÄE©¾† #3z”l!` \kÒ|;)FƒÊТèU¼N‰!¢—™†#t§J1Æ,íAÕÕ׃Àò ¬S‰qU·‚¦(v:$á×à%öاi ¶s£pûä"ÄØõ!ÀÈRb0Ë¤æ ¢÷
+ÚKi/ 7ŽÌ!5ön°vlI; ü$>™pÅt¢>}FŽ&ó(&Õ/”/#þ"ùef¿!ZöâA¿,÷Äöo®­ÚŠÜÖf… Å&#†å)Fˆµ’(J]ïƒ~‡;èÐo@ä(Â`vû1¨P‹ŽýÌÚã¾A—ã. ×O6ÔYã22¼‹œ²í7Ä/_ Thµ|kºa70abhõ,jeĬ—~ ¦Eôë‰ÔØŽ‹d ’¨-•H+$ ÀHlrÙvAªþ-RlÛ~š¦8ØÉY³ƒû~]^qÌq´xZx(»ËºoÖ¸-<  gÀ´ ¯^ˆ+µ†ÙŽ›
+„mÏÄÃ~¯¶ƒ2m™å§ï°•­O-Ç×x5q\`^Óy㻪ÅvÆ\n+¯Q<šH· |Ýx~!,ZçE–ž6þ:µ¼N/‚þÁÞåǠ˾~²¥s™ÿùŸ EŽ2³x±y®%ç2=$Û‘|Ÿ ·Ð4oHõ
+=?Mà_ù7#öÈÏ;QÞãaÏ|æÅ«h$yÇOĉòKtHçØ*Š`ní²¢lLAª¹!ì)ae[”áPY,ŒØ{æ“:ÏX×ôtæ*¬ð¶ý”‚rÉ°d_‹@d úü6‘ß {| …"lâù;8zÆÞ[ÞÅ!Œ•"µ›‘¹V—¨V‡àH
+YÙý3l€ªÓ††˜+±‚3¬!ÒW.Öx(»º † ¥„IÖw ‹8ä$²*¯††Ú]‚û`ºˆ‚Á!Aqã´–÷NtP2£Íå «UŒóî;1T¥¦m(û¨MÞÑ›™¹!Ím- gvº€>@¨æè¤ÕB7;Ý@©2*°.¦qó%‹ß¡[sj$—b6WŒïGÜúÏ€BQÓò&ïÒûœ-?ÄÝÿÏx¹$É‘ã@ôºƒNü“ëšeßBÛÒý·óœs¤ ¢'­7ê*ƒþá?É¥½_%KÞÖà Np_ÃÚå™@-Õ)±O]âs [ìÑ?çà ÝfèQ=¡ûF¹…•“ã~÷a£7•Ci “7Ž#Må²ùÆ4˜==”œ&”Šƒ‡\xwŠ¾ŠîÓ<Ð^Eˆ ÃHÕ®ÌÆð,žþ›ŠÑŽjî~yÆ?eìx~›bâº&#_,8ÿÞ^­)êt½æè>½H¿±xp¶ý­
+ZY›UŒ²|ý¡€ß’T°·¤¶…œ£!žN5Gœr(êÒ]p·Ê"Öê//³Ûhõb­¬–É 9NŽÇ{u+áÝ5MbXò€N5ˆIar_ç¨ùS_¿?aË›È(lÓuÙYæqŠYÑß«Vš,䧈DV€w„XôןƗ¾Ä¦Ï¿Yz$€?Îr4¾ =(.òÁdÆÕ&ú…Õ°OïDlÀ™Õëà
+$'Sóô7ŠÒ Üy~8G;ƒÑÆÕ…²欴†çfCi¹#e9¯bËJ1ûS-òÎÉX&Ö, Ë‘yW°OÝvæTëcõ*ü^@ݲ{?o;|+²…\Ñð(¼¬"´‰X"æmÃh‡6à'0ÌFð@”êÆj%N¶H²“3óÝe¹zúÒŠ½ ²€©˜3Ný§Ç“§irzš¯ÀKF?˜8a'V巵šÐÀp,o n¦ô´qü‡­²ï W$# ÓmˆA=ÉÀ¥µÀ¿†+…àâ*)ˆÙ%§Ê€7W@(@°o;Ô b
+¸£~L&xS áŠ$ÇñÍX ¡(¡Ø‡°S Õ÷âKÞÿ“ί©° æ,¸ |;h6ž„Ä_ž
+KQ‚š°UÚ–}âžÜs˜µÉM4ÚA·bsY»©Ø žÆYìO#u½©ý<ÿ.Aci÷mþÖ¢&îB>²–4"Rëu¦ÝÄ‘¸6¯­s.äLy9"ÞÀ$Én<<ćY¢ÅDaÂë¬açª0ÛSžiN/ç¨(|\DÚíô%–ÄhÇ+º¹JªÀàô±}A¦Xì‹Ö®’‘$ƒ8Ë”œ’_ ê’Ã}û¸û90³r§µ9ÆjPD‰?jÛÈ4‘&¤’¤s_?¼"¯?ã%ÀѸÑòqÑa>×çªl--H^Ñ÷'Û3mìÏÿ¨T©‚(…y ц%9HÏ€ô÷C‘
+éÅ^Žv!›ÜagD@ÐdüÞ§ƒô¸*Gö¼Š²ú ĹkXMš€ä¶'ïã0åé}\œç€.HE¨%÷}Ú[âc•T.cƒQ>{É@d¦m”2%X‚—u.ÒBÆÉrÁbŸ®šŽ_Ý¡ÇÀ£èÄq?½µbVÄ4¼ëüõÉ‚þ³Œh ˜ý¨[íE¤I|„ÌÜãôJ%Ȳ­k³’܈­½*@\Ê}|Ð+Jl7p¡»ÝMQ#ú5žMˆ
+^JTAŠ7‰+nŽ
+ýðŠ¼×ÙRg‹øÜÌOXJ,øBEI>!M ú©T ¯·–rÅÖ‹sƒßã:ïؾP½’_‹™ôïe§fÅ"±Ô\‘ŒgM¾Øš(ÐöZV‰òÖVךÌe±M û}ýðŠ¼ö.­i6>ž?.ºó÷'ì=ÝÕ̦»Ú:ÛÂ\6MaÉ
+‚ ¥+‹èNìJhÕ)š%9€y°cÁóܱDc³klùW|…h¡3$†’Xð$IÖŠ¬5 ê²5xÞª}çç}ÃHaøG#•
+¶¾¡ 4aFÔJ$hW¢ÍÅ(س‘«ƒ³&8îP؈£EF$§u<OßéÂ…p¢Ž!kõ©„ÓÂΪį^Q]ª+’òÊ1^Ñ‹Q~Ö
+ÎìOϵ“7ÄêŸä%†RÃö`ë”û0@ ŒÅ±‡ö)š 
+´‡pÿÏ°QÓžz žÉÃÞŸKŸñ2#í TŠb’7îGÌ&ú°«5¬´”Ͼ_ŠP6ŽÑ>ÍXvz½3Çw‹”yÞ&ÕúùP„ºLöcXÉt4‘v£Q­úÚÞMšðµ§´ÈÜ«r
+mX ÿà‘?É´Y¦òNkáqÅì
+ŸRv´ïC¾µ:%¦KüÜÁê÷s€"5Ðw1nƒ¸\÷ËÖÅ%š,EÖ 
+ëÉ7kb½óvQ<¾ Þ¢WÚÇ@àªB†uJ¬ÇZæ ¼×Ãô*QÄCÚ±2}Má¡ï
+™ >²n_*±Ð?iJJçK%°:ŠvÓHL·ãÛ¼-Ï}Ù 4ÎP"I&É-¹`ôë‡Wä¡=,6­eù•¢û:ŸûFÑ…üåºýw3Lù,ä†Í#ÁèX Ù÷¾Æ)jH5f—:—‘¢„¾bØ Æ~4.ËkñÜÒw‰´»`Qr°u¯€9qMäªïцOv ƒzÍFÔEFC!Mâœ:i¤,*"`—AefØÈXwnÆUYr‹rƒoy;Ø¢‰FQzo¦üaGËJ)T$.¦ÒV¸®=QL¤v´H€"›Ó@¯±"QW;_A¶b„™cAJBAò­B|Ÿ À–b—¬dà,á°(w»KÅéäï·ä±¾D ä ÅY-S!Bø?¾³¢U$ñD!%Ò?é¡$¯´ÅæÀŸ¯/]‹ð¼h¥åÂô¦€›õrllÂüFò*š»›'½d'ùs¨eh
+YΧ}ôšA‚÷%ñ–%ZL2ŠeŸÃÝ Ó‡ëP)!M)ùÉé¼¢‚«ìmŒSQ–òäs\F^´Rw úUŠìÂ<¯L€_Ê­µó©Æ:ËL¦pèòjÐ"Ϙû&,ÃáEë1¿Ÿ5Ž‡Š7/üe‹‹8ÐE§èçCQR¾˜“h¯.
+“/^6\=sA„©tS«7Ï·ƒ³!Ý`wsz:§ðnùeèÁJ@§ ¬øpX‚GéÉØÊÀ¹çKy%Õº ½›W.kö¦¤ƒ ´5Z´IÊVc%ûCIæòŠy4~¼ÖáZ$r$D`„‹Ã§»`)o¼—œëá+àól·¡ öàav_Îd¥ž³½è±À8 tœ"®„ªl­ªŒ§†ó©žãT€ÍÌ&Íâ™Xø·¡/ J\8 €À™ÍŽY♄“E´Ú*Împ<Ø5²†)Ál´¸Käÿ§¨š*@hQÃÒ‡ùZ¼!¨½S ,$‚
+âY¼ŠóÐ}“1mBI¥óŽúPµõ KŠO=Ÿºá?H
+›ðMeÖÌQqSŒ#I²|
+”œRÌ ‰3iˆ<lB9yOí3­T£{ø…Ù=ïv0Áíz‘Ì•§sŒ¤)v™L¿i2h+…}^¡øØ£x`,YÌK b@S1¯žC¦‚ç7&“¤&¡.nñKh#6Eý£U_¶RÂÐXì|¯ùyjÀfÚ4£H;!>®— 話`šw·&ËBz9kǸñ%ôʉ±O¾Ämßå2=žd ¸ÔÖ?¤‡Y¾•Ø—¦((¹¸ç,Eä
+~•êp,“Ñ7ûß3%ë­µàK¢©ß½,èÌòž)!€&Ã8Î,¯ç”O¥WƧùø™òÆ^¨,ÈŽ:J¥º¡’
+(±f\Ñ•NÉ=T:E×PIIFp¦)ŸÄx •Eµ?…J^¾Ð4+?TÒ¿YeJ›©Õ=TVhæ‘NŸhz •BÅ Cï©R;EžÈ˸g7UVmAvì{šNªÔÞM 绩R[Õ$ÓºåpS¥WrK•÷¢›™Ömˆ*…aŒÒ¼T©wó_]¹í)TR³@©2ñ¸…J­«œ¡z? ²T¢æ7s‹O©P4A/7ÿ˜"§gËš*!ý(Û‹«ù!TJ^°AºžÝPYØ1Þ£ÜvlÀ5T:%÷PYô@ͪ•ú”*UÄ~ÈÃg?TRÑÁø‡ÉüPY’#t@ÜRå½Ã×P ±)m š=¨wI•Î,ï©¢Í •ǵÞÏÁ…ó
+žo©R«Ë]{Ù@o±r™CRgCõÏu®›àXÌK¬üW«ªXùÛ?ÂÇþüñÛÿ~€ÚR€¼ÜP—OHR ð‰Uüë¡H6EÖ¡Ç]2K–1l‹|TBºc"#,*TI“œË¬»¤I .ilIRM‚žø|´&Ù`ïÉQû˜Îƒì}¨öŒBÇd7VÅLV®>U§Ä>„_áИdwÝs1ð-æ6Ç’üË…
+àî‚x J䜉 6Ù”MãÉs®z$Çúj{+ H<]ÎZ¡€½¿:Çqœrø¸2îÁplÙID*¸¼ß.Üh-*^sÉ3”I2 ’‘Ñ?ŒšMi¤©Æ9æð‹®ábîÊ&mB½@ü!éçÛ
+´¢{98XLÕHÿ
+H‰Œ—Ar%7DOà;èó$@X{–}‹Ž˜•úþÛy(¢¾[ªª™v„Ö”E@"‘Ðfãã_mÙËZo¡­5ïíãï¿ÚjúÒ¥ÝB´@úZ2§úp‹>?~lP“‹?Œµn@Ÿ ê/_}Eï]ít@¦1ÚsEA†ëê:EÆFŒ!Mº¸ÚøP0õ9íãç¾Èzëc,ñ Š¡M¦DÞ´Ñ­Gס±C—˜ ™Íe=@ºËÝ}ÄyÕdæîª}ôauŽ{5 É7„—ÑÔégØfühDÒªÓ–®ÃZ[çU£)?úŒX´ºó¤Æ“µ¢š„)Ö£µ^i±D×è³¢Z$‹CcÎÄßýç/ùø÷®i>ª‡<èx5›Ñ¦ð7Ñ_jsXWµ° o2–?%Ü
+óÓµUŠ¸/|.Š±FAœp5HKÅïlšÀ½¿¾zkÆ›xA¿¿ª¿ž:ŸÙ,H§ «Íó´âï.ë ~q…œB÷ÅÓ9°X0Õ‚4íÞx@X´ ɞЮáÞ*pŸ2B æ¨«Ú+´ ”"‰ÅW/…÷9 Š“-²¬Î™™§Ø0ö¢°®õIŽG;¯º€$9¶x¡ísböF;­µéAÿÅÙÇRîÛQ5ÎÐ5cŽj®™ja# ô›«)—O«¦Ÿ:ˆ)ª-æ N’ä)5 “kÒüPsmZÐç¶Úš~xR§/  lš1)˜Kluº€+ ˆ5 ÂXÑ”/z6î~d¢‘ú¤máÁ† ;†”èFL£ž´>m4O"“ú5ˆ½:†üg­Õ£n:JÒ›Õ9Cé;ã¦U(â+ÔÌHÕa¡¦Ncõ§s¾iF¾&õ˜b+ò£!ÃG燊Š˜áÍJ£=óUÃòn´Teì%O„l½¨¹*ÅpgÑ‹üv>@è™ðå³ïšCÒÌ:j
+ǯ˜ÏÌ÷j^¸Îƒ0i8Øø
+½ß?ê
+Y$í§]Ïɳ;݆d–ê´³nxçåƒ/£  šÊ2˜Ï½‰X3áté>'å.ÒI®Ú/xWš
+ÄáG§–žuÚ ä¸J_ØZ4V;{ñzÎщ)ùç~yÇÔ²,øšFG9qOU#Üo›#7 ìüœ#¢ø.Ú !Á9êµz½Ç`³Ü[y ŒýE½Ì
+‚ÇæÏ8Ó™]éÚû?¡³‡x™ÓáñM¨ü'*.µÖñtü{gÆï²|ãׯպžs©ùõ5îÜEuáà5;7tÿžãÈ—Zýü“¶É“Ýa˜rÚ@ñÐçæ¼_ ñt- ÛŒý. a³%—5z©rÕS@×FdáÁD¢Ý8Ï3Ix:ÍåèœÎ]5ïø(«z0¿qòl§ÞñÊw•ÿî¸Áà qž Ý¥§ ÅÜÌOQüþ,%>‘Ù—÷)$Ôk2Ò½{î:$ÅYzÍÝî,¨Ì rSù¹£­ÜŽVAb¨~4ÿ±Ã9KScÔ¼¼€¾ÔýóÄ/˜åÖÓÙÜ—±[PªÙ¥“ÄÓ)´v¯îŠÕqÉTjÔðÁ9Àäiò[#C[Míç¾r?¸˜ƒÝî'À5Ê$î}Ë¥œwþçŠë9É-gÙ”EYÏ×0à(8ѵ ÑT•Œ¼f€ÓçCðÌíÉh¹b|»Wä#ÒO·ã»_ÈÊHK{&‡ÿgp2Ÿ÷-å˜Mr‡v
+êÿ5gùPÜê‹_¯*—2ÜZŸ9àÚÙÃXØæyú“7ÃZÅÊ„ŽÉ£º<wO˜¿ÓHAIPî:± t> ¦à™I@UÞaóÔÌ¿¹–Wbé}ÇQ¬2õa‰ôæ2r3à׶ÝóÜn =sÇý¹¯bF"Ç@7Ÿ±x+¬Ç–p¡sÓ‘aïúF`W©­
+Çe;ŽÞÞ˜HÂ.GªÞEàÏÄEºÄo@„³²v,ç]‰"0<´WòÃ)}kT‡2Äh.‘ô¹ï"Ð(–#° bMÍ}‰1±Ï¡¬]ØQ{««XUÅ°!¬Ÿu
+Éä0+ÅIЯ­qp‚t&ÛLô\crEI A­*;¬”+é¤ÏD&Œ$íwÛéIäÿÙ[G ÎXiÎ(2©³Rò!µ‡ÔeÞbhvv§¼T
+¡\hºÔ@I%¦$Ë6¥ëó±4»Î;)!ZœÕH›ÍØjÙÁXZecJ·bObËAŽ2Ma âêÂ:Äz‚’õ»s<.š¯t3ø9鳕èŠarû8 "=Ô¶!sXdmÂSu‚O¢^íõôŸ+—>¢ŠÝæ °§°÷{pøŽÄ2:cîs öynQ§\RL’ËŸHOA&ˆ—éébU8•Yý¼(÷²¾òŸ¸3aÁ“!Äk^³¼q®2’õ‚Û ÊA¦wú. (ÜÈ#½Rý‰Ò´2MƒˆacG2Îì¥q%-ŠÆ:`°fµã½Å
+›ã{õòU ÿÁP9FÖ[p^Êâô§_ÑÁˆ´¯I€wÃ|õUõþËx™$‡qAðþƒ^ À¾œ©£žBýÿê, {(Î`_Dº‰ÁÒ]•Õ…³‰'[…viB›¼ãÓC¡Ï6“#H1G?R£éqUiì/ M+’‚€:*Ò!IÄ­O MŒ
+Îåb
+?Ã×áý1Xµú§à‘¬y-‚Íñ9ïIEÒƈSÅ·u”†(Ïv\{Tw Ê4à&
+LÈ#âB6oQö‘ue^Àz¶Œ.e*Ô³¡'ƒ7¶+ÆC¡i ®Î—q4Ö…–\cw«ÉKÌFø2ì¡Cý¬-Y:È~ØÜ‘QD"Ýu Ó€¬•{ò¼ô±¯0
+´Çxùò×—˜OÜšÜá¤Kv˜áÓ^&U ™©´L@’!r
+rý¥Dü2pâ¦ÿ0sÁ64feÄCѧAŒ8ì%9„ ‘
+KØGÛë°h°%4zxqñ½}ðÐfª€~6\MbQ¤híêÕ$a’‚w£´,Ç®Je6 ›Ü˜_Û—cë|)%A
+öŒ–” Û|²è4襲’.¼—01û˜E>l`â‚Q ?k>_jî¯ùèt6ŒF£H•o• åš_ )BŠ‹ä_Ο@™}t‹WŠ#X(f¾“BQÅ$„Ój=!’æ.ñâ‘_Ž5.Úå4´Pg¢ú°Ý0r`ÔË)MÙÐbdVXk%<Zm ô³'¸áÉ÷
+WÙ³è0ú±o« ù*dÊ8ø*ÄCZ•µ³é9òÙ0n<ØJ4–$<Nÿ@È-š} s”kßë0M :—›¿¿Bõõ–Ç’¬ŒÆ7gW‰[}–¢<û%½i0ÆŒî¯7L® †«•æñ‰«k!;8âþ@òæ¶À'Ñ¢eH¾›gÑßÆúùÜ÷·Ð”Ÿ™qÈ=àfž#þØ?/5¬‰ÜÑÛ¦Q"Î6á¾a$È¿ª˜Óܼ±´
+²­‚Íq×1—dOÂùh˜ ŠŸ4.p•Ç^‡ÐZ‘™Ïpñu¬W­>âäA»C;Ü©@D`Œ¾ñ?0ˆ ˆQ‹;U}À_Œ9î §Hèï]"ù£7xöVýK%6%:鹟i„®Â¹ö:²X%7«*\7ǹcÞ%x>Ú[öU¸Ð RMþ!± ßžÝö‹46¯•løž¶@+ÜÊ`)ì„KùX‚>b6€ñ®Ë{a ò Â“Ý ¶•èRƒÉÖJ™døÛJð6–eélâ—«hG=¯Ë£÷°>Fu­@r‘,]Æ^\æÌEWzœˆ„òÿdRí lÞyt’H;¤—Uš:zJf½bêÃLpo6£ "é¡Ú‡`t†
+
+‚ç\£ µÿÒ÷š¼´ælKtm3°.T³q3·Ðh8Ⱑ㟠ù¥šîñãl2}`æÒFZ Ó‘*˜’ §jåëLl>A78‚})Óø\`Àâ¬#’.br]Ã:TlÃL%„öNµã«ÈK‰ö%AR—sÅa‚ÏpôÂwWóø €)»^R
+GÕk˜¹ =¼‚Ä¡èÓŠRÊj¿l7 (§Á‡øS;6lÚå“Va(µNŸ»¦‹*ËòwKp\F,Šý冟©Áã±QctÔJþ?äTÊñ1o%Ö7 ËJ`ÚÛ:„Yô%ÚVQðÌÏL–ùõ“ÿð;Æ
+ʬ{ºånõ¼=êÌŒV?=çÿxq5Gðæ Pòä€V?H˜õFÁE€kÒñйõ‚îÑ”PjËY­*:–ÄøhLƒ%è‘=ꊢ¾£kÜ{ÉÉFLŽ@JxJÛë4%¥…në@
+V¢Èz,Áý¸Q¬Ä`”?þ9éŽ`WP”O}¾ÝQ[N‰7f¢­E(’ú¾ÛÑy1Z¹¨¿W "[ƒ^ô± ¿ê3j’2O*>}dÆg?ùéÝï\¯.Ä…'Êý÷@ ±zﬕÃk‘8‹u;È
+õ¡¦Ü'*’`
+Ð1ÿ|½Ò½-9s …±×Aî95ŒÖÆÇW
+v¶5F›š¸<~bhCóAýËx™$Ç‘ì@ôºOPó°Ö_ò½%ï¿ýÏ3)U&RÆ–µ$–P1Áá 5
+¥Lª­ÓÉœ@:±®ãÅ@›Ö.®riÊ3’Áó郊X†ØaÝâu]Gà]¿æYònDD„øTrFâ)¬$ÀfÜÜÁçàÜ3؈ûßÄÿ()2«
+„?fy8‹r. –Uy¾„ƒ^ yø/Ó„%@“îupʃ9
+ `>”àÐ& ®0¹·º‘ïø‘°ˆÙüðOÃÔG)°]’æÜ
+4`2#’æÞêö8ÈÜ©…²­s}a BìcÖ€ØC£ÞJ6"® ¿¯sÍõ,öîwr0|}g’2 ˜9é¡äm¢ÎÁCÝ úÊ D1.±uØh³:ê
+Sßj,?.òzÆvD•‰–Íþ¯¢÷3á}€>‚;s<
+>-ý)¸:Eomÿr‹
+b¢©@-k3¸|¢¶ä§¾³dPL̼¾•DÀ]#b±lRy)V–Í1
+÷•0šVc3 qž2ƒÅ¯æ²C9àz1i z'ÏÞŠÙcˆñš3ù%´1²DcÁæáxtdQI×=¦Sô女Ö3Ÿ5£ .B¤|‡i´óèÁ›ÕUNg‘
+Ë'ÑÜÚùVbÀaf™ø¬úë
+$?JHÏÎix¯É7bäÉRÖáN¨%*<Æ*cyRhfÙi•4BØ©K§)Áü¢d°·$ ggÆ#¹%¡ù¼“¬€¢k¡Ž¼ N§(â$!LÀ’ ¤vÒÜóIÛ @Û±O
+¨í=°N,Ä=˜nÀ‰¢PÌ93±'ÙÝ,¦*Õ0{ `ô‡hp <×tù­¨!P†æHƒ4ѬithåêóV14¹K³Ï¹J¦r/ÿ£žCu€"£¢ëýPyfƒ«Ã;Æ
+bÆ¿q÷ÜÜ8§V
+…+ úÙ)ú²"$)GyÏ„9¹íi­ÚË2¡ùúÖ:ŠÚ!ÿRç½ ÿ1X8ƒWfújá™^¹è[C4
+瓤}MÏèzn3 ß(ü±'Ðbø*A–ŠyJ‘'"ò
+ŽöM
+šPYezzQy‘wÐÔíª9ÁojXb"À¶F¬UÏ•"h\!œJ<ËØ*€>„K&®ì)>‚.Uÿma’XÂ;´&̕䨓d…d0-²˜a+„~àïùó¹5¿|7< $ƒtDl)N„pÍó¢$Âë³R<Ó—&óM6ˆÅ´€æÞç1".rƒ^÷e¸=Õæq~õ' i@Q6È1å@-ÚÖ ršà¢HĆÄ*%¯„®O³œŠÅíä­fœ›®i9ê¤Ü¿æÏO—Œ/Y{’
+Fnƒ¡U†¤}‹zFF>³œrlž£bMeêÖI®™yDa0ãw«¹´páˆ,i,+vH¢!¥ggÍûSîä‹uI2Vöªh¡á-HØ ìܵe©Ô&­m-­ÉÚBS­žç!ÚÌZhëq¢
+«I´i»ú wTª`i`êë“ÜÑœ> Ô*éáúË:!TYûŒèå<E™µÛ™$¥¡ëÅŇžGÕY>«—*¹D=¤lÈ8–¡"MýýRŽKúh=doü9?'³À˜cªý9(ÁgÀ=ê°†U‚Ër¦Uª¾±°¶ÈZ¶¾`ËØyÄ
+õçzÿøÔgÇÿÚp‰^-r[­)áŒZ¨L%Å‹±ÖÎ)•’áFŽîL# )d£ GãÖ稟räß­1Þ…öe¦u5 ;ឯ##Û梄¯»·š! n¯>ÂŽ¼Î°‚”£ˆÚ€wÄ­ ³ ysì= õÝÜ©ôr;kIõaQiþàÕgÝÞd(Cä«L©HÐ1£ð‡Ò†QpÌ1ÕËÙì´(=ˆïõçÔ?ÕŽjd©ôjSMhu-U["ßàÈ~6_Çõ ×æ1‚ÚF"ö³Ñ@ д""™Å’/OK•t“B[/¾$»Åí:fô·FÖÙW³CÐH)®W##ø*(’ûÒ —ärôIÞ }òÛm×ÊÓ']‹fÙ
+²åá‰i•œ.!õÌZ6a2ãJ8+PØ÷=Iá„ÐÓ9 ­/^çWª
+Ba{4†øÇ7+(³yh/Á•Àñ9|õÕ‘} ¯_2à“ÏŦ]HÜUžƒnwBÃ=7¤5ëM®€sÀ"=l,ìE³B‘ÒL
+*5Ò†š„õ10Í.FŸ-ÂCê•Ò
+8h½˜!ÀÅ™*(:ÔÈë~zâá…õò½Æ]ÖÂBmh¥,U±×‡#Ë·UÐ[µÎsŽšŸ·9zÇzÕуgvŒv¿çعÔê×WÆæç{sÊý…êaGì.ç}<¹†VA-lo}Þ ÄÇè»í½ôPöQ—‚Z ¸ºÄ01xÍÞœº>RZZÍÞŒÊû=wƒôØ_z8ĘpŸðpÏ*ÃbˆĽœ/âà =¤”åÞA …¤4Ð0„©÷A
+mW`€i׶٣˜æ`šØÿú €“ie3iôFèãSükø)#FhîÂ7Q‚àN­4l“âÓàïÙw"x.òf®Í ÐUÓz½\Äçè÷P.#±m`tpˆß#ì¤z\«FsXÛdK +Fh/*º]î\º {ðñ¹y‰¡kûä»üs!ŠË¡Ùç2 i’øø³0v…üP›~9¦&°à7¶~.òÚÓÖÁ ~µæ“ï¯÷¯$T ÈÔQ´ìÕŸ»aEº œé»YJRÇÐ+øÛ_1â€fâ¡fäF.Üua㲌檻b+…¢ìc
+y5ù4êM)¼³‰K£o0Ù£Î[éhiÉ)Yƒ@¤"hã*³ÿ~Rb‰ Õ§79*ñí=YóÛ¿¿yEžóI7ayk¢ÙËEOÖgŽôSatøð7Eßxo(¶êâ,VñlÇe&“e«(Ên
+Ó> ƒy!5ŸÝÁæŠ —ãÑbœ²¶pÊ4¥I¤…$-Χ>FÏОó™ß#PÎñ¯0ÿûö×o Xj%ôËά¿P¨•bùˆw¬ŠÐ3ÄlŠ…Y’]êRÉ&¹ï¶Jö ¿WöAx!pù¬hB¤Ãê.':[Þº€L‰¶CY’Ùà(ù|[E šˆX0R^Ñ*!eæ‘v»M–ïÃè Ã»„Æàó'hûQQæ{u
+¢‡X±(¸áŸ‡£„
+-…<sÙ ¤¼hßg¶•3™’ÉgVƒQ2 Ñ© ”IÂ
+üqjû&EÂé14gä«mƒx™¸WaÂévqé˜W§$˜'*Þn¤ë*Sú‹;*c—`*Ú^+•$5çK <ñDâ«}
+m¥¥4]E‡ ði÷­ˆ"6Àúv™‡ŠË•Tí)e‚’,ƒ8îýÍ)rçÕœ"JýÕ"}Éi°0ü7(dÇÑ/=cXQÎä€ÆqQ{=gáàæ9ç±Ëy]:tÁÄÄçæ%ú@²…¢/ŽGB:8£9m­ˆ.
+2Éœ¸Ùì> ÙÂÈ r*ô eë_Ä—%œâœ!zøS‹q}‚¥ÓÁ>’¸ ¸h dnAíÐòvç»ìK,ù0Wa.’ŸZ\væ¿?ò¨(ètÂTfëáÓãZ`DLj,º¥Á»òá‚"óØÄ+?VÉL$*Uòw8Œ”IÓAfòèbѾ!ÃvhI çpÃÐåéÇ—7àf?=Áø p‰"[oŽë3¶ýVãynMÊ_€¢òj‘¾Æi©"CÙ+ê2B§²Ó»?E¦œŸ‚Oãmý:j$ÇJ"Ї˜Qã¯ÞBÖµÆi!¶‰ä3{ùÒãï’­QDù+ÎúÒãï>”’
+zRÞçà“xúõ65|©t¤š¨à–\Ðùí§ÈÅyúPR¤t¦/y»wûÜ‹>øÀ]«kÑâ–•ÎBÂv÷®PÞlþ{û¹‹°ÌOÌ÷½¢UB0*ce›·FU4\œ—Ú.Œ<„9Ô7á3X™\‚Õo’í8P–ìP>t€û”Xìc"ìϨäuý¼¤,<á0‚šm¤
+í N¹Éý¯’ÉÖ²Ü ë|Ü÷«#]ÖpÕ'ÑÈêÒÁ£Q„œ±?«„Ô qÂ÷Ãv,hÕKhÈg³°š5…ðåÜ"IO,ü[jcÏKcÝf,ÄäýØEMæ öèËk]‹VÉrå<+dó1“]L»D F‹ªœÃö4¬WLGÖŸñÂãè”—¬LƒŸ1߲ωšJ¦}
+ÍSIY›èVŒ†0bO x¾t)A.HC ;gèÉ<ô8}2-²›´õönŒ ~€'y~H·}*ÇM~|ÀÃ` JˆÜUø 5<b< ð8~§ ÜÅek-ù ÎŸV$Ýð‡É‰})KiZŠ†²É3„ÖM™8
+FŸ‡ÿ¥!2Å©³ Ó£àý|Ü ]/Ù3<’Æ£q¡§c‚6‚•`U¬„>ÈGeÃWGC’\¥£•é7¶OuZÊA̲²—ÇBiRš¼Ï0ÓPòyTD?RÁ Ân {œ2\ŸX,ØÏ>u+‚ô„&~Ríx¦AºSv¼ü*Aºpãlé<;ŒÍ€}EÙ󽢌©üf‹ƒ0!j,¶ß€Ê&¡‚èuÛj0nœÜ¢ö®¤Q¦¬^‰ËN×¢ïEèÇCQA‚k%Â)iíØ ŽD™ÎÁS‘·aà÷‚R°]’DÀ. D n_¶jœþ°æPoËÍK
+e,b`-N ´VÌôª b“‘ȺIæÆÉ¡D§Ä>ĦÁ§ˆÉ¢÷œOÆP ÍáMÊ~V‚¤Tø—Y lÅOØú~-̓©7,x×ÀЖ¨ð.žÌ`qH ©…,¿¤Jé }5EêKfÅ|íØ¢E×q^á®wií
+žl‰1Ðà)óÇ´ØfI±ÉÍvP,«Ö[6º*·£ïHŠ‹àØay÷á”è–¡Œ†¤¨ß—S4ãƒàþ­DI€?ÍÎi’ >†J˜€~º”kÉa[Ü…nöÃïçÐ-…žCÊVÒ{`
+øG™öUR€9?Lë W‹]Öõˆšf‡Õ¾ªu8ôØ#olýIZØ ™Éx¨¨ƒ±ÎÆÇ{=<ñQ#•fÁd; õ7´&!ØT/ý¨„DZXTY#u„ùE«§µ…·¡
+-†#wMÓ¦5‘_=×¹]cÉßø7wZñMÈ0Û¨áÜ™ûçCQ‡ª˜F›qÏ´¬‹|\:v¿b<ƒeØ%Œ )Ç=,úßþÀÄ3Çß?AטIû±ÈÕæèe@ºƒƒ b[î[ïëCí•[ân}ñ™Šž‹+ ý4ÇZ­’&SóxôÁ×"ÊÊÁ_!„øzªÑÑwªÜ7æãApnϲ0¤žZ«÷ðk‰µø³Î9×)è6éÆK¯páLS´Ý–ÅÐÖr>õ‰
+mª<y›ö¯­.€cN›Âæˆ^‰LVõšµýÆß¹Óú¢éä"Y¶KcX«›"”úÓ«‘îhÎìf2(}ʇŒáÓKÅ&DÞoü ‰Á'ñ‘¿nž”7ÃÅÈ`3„ƒ‰Y«ùÆ $vŸR›.ŒÈöœë37‰<“¾7
+¹áD¢RHŽ˜øh²Ç©‡yÌÕ­¨¿ŠL ›Äkó6WEÄÙHDËkîD¶>âF’_y.¢‡ð8?œ pvûÅc&²èz?LýÞ!Ö‹Á¿LÂÍ T»¤œY¦ °(Z?h來&›€zÀ… ‡q齬aéMY~iU:´Oi*!dʼnؽ,Nö©ÛB â òïIå¡Díƒ"¸ ÷ûï ‹õ›èœ"LÁz(VðZ³ˆaâ
+‡!þŠ
+ir—;ÃU×Ý@¬+¿À²¥þTrGü_pü›èô_!JÏãÉf9E×E,/rJ2IkïWÖ¨»å¥ÐF¬áã‰Ê+᪠oë³ ½#WõèSTæw¤š›Sas_ã§y–§c"‚Iˆ€èØ^Æ
+‡Âçüž„7)ë˜
+¬J"è b"NŸê ‹%sNª]4v¹aæ1O~|ãšb6ƒ-Nµ$óëÁù²u½âC˜3"è“Èy L3§×zV´R,gTK•Ü…©Dk,„¶•ñÞ1ö{z"A°Á4ÅU4@ ÎbU<Çñ&cɤe-Cdœé”iq]IW
+óâÎÜaÑM˜§µ¶úÇp.
+
+o@$ˆ¸·=5\2«›Q×~føº‰; ž;i„k~aZ!'ò˜ìºl÷H‚Ì¡y?Ô«.3v]4yA ’Tªæ¥W!Ø׉]ÛµÇñÁh`ÎcËþÓøPm:~fnEc¬eÈ(hƒšÑñtarbù|ì}˜%ä ·§E8ÏʧÅ&=ÁXÕ¾;E¸ö‡W)ψé8„ü}¶=zã31Ý}ß QÍ+~¦ÐÃØ šÑî¥>ÍhEb¨ ¬3jjxä¡óËYGº!5µõé0ïCvÚ†N
+G³Y:!˜QêST™8™¹_Í*ûN?£,½3æVæÏè×µLKʽAñxk¼× P؆¸06|³Û™L˜¤‡ˆ«[q£È;óŸá€~>€:ÅA=e1âê!@1EåpêûDÜú„P§>Ahœ€s\¯¼ ~Rù§-ü+÷Ø5ËØf¤ˆ¦›¥ÃGEâ*ï×ëydÊÞÑFšd-£˜©²U·Tÿ,ù¯¬3íp¹AUÉ ÝDN…>÷ÕnÖ,á5AÛoTå-zåˆ Â ¦Fk§ãGMe†_C{ºZƒq´½U’q¨Rò´Û/Ñ
+´jýX$6­0ÃÙ ¦­avi³=<2IÌeàv–"Ü@n/NlˆÆ8iæ•Zuõ(„×®n$Òû!r™'¦Hn°R÷²-LKòÉåVw¤è0u¢â¡=-3ˆc•K—Ïr¡kgšr‚á„¥H)õL¨ø•Q)îÚ'Nj¦C0ð{"R¨+‰¨”µ:HÎÅ“œ‘þá.ˆOϽd¼ŸßÆx1CúEA¥–¸˜*îÆ/Õv«+åÉ×1Ý«‹K$^åÝÔ5 ì@;®æ“×ÿO­x, E-Ûˆ2d¤NÉP/«XJCüYýcêƘ龉Ç𘼠íæ öNЉ!&…à÷´ äY°½¶³ÎÅ‚óH_¢Ò‰®8 ¦Yý?·ê£cKªxFœ *8i^9®²Khð ¼ó¦
+îGŒUè Ñé@}¾Ð+ó}ìŠRDTt‘ãÚ'ÖI¤)Íâv-]$=<À®UµÐáþV‹¹äî¸ôñèOAfš²ºŽ/«¨¯ ö·‡QGá8XÑ[~_Êj¨G°Mò&æD}iêº t$Ö(Ϲ™ û¯•Bh«€¢<-L0p¬„x
+æarFÚä@H ÑaÎ2Uñ@ØÈܪAƒ¢IL_hOë(qÒta[â4Y[-Uó‚¤À£uMï>p¡ÈFö0Ê"÷+H¤V`•Êb>úµ@p1™)—Ó®LâÛêòÍóÈQY”ê&/™êæ­`µÑz‹wľ8A‹.,¹¹k\k0ɳ6}
+3—â¡–J½‹5nWÏØ`vh¨ ¿íÚ‡!òlŒL:ÓîÐAX•Z'‹ŸÐ}lõ> \Ut1õä„ÄŽÖñݨ‡ày ²Ú1ÆiwüÝŠ›¡=¤®V.®Ñõ÷A,Íe¶dóœŸÞt½zq=g
+
+ Þ¨g§¿ÏÖW låaÌÔÉ‹·c6à>âC´ä—›À%û!Ðx´Ê‰øåhÎ-n·Æ6%v7s
+‡
+5|ˆ.6,—âSØ¥èÒ‚2ãÐ{ãiŽ^p4
+H‰Œ—AŽ\9DOPw¨ LB)Š\{–¾…Yyî¿Ç/*{œõÓ(4ІËQ’>ŒŽÏnKËÝûlás|þ«¯x4Ñðµfk¦‰
+ÿ¨Íòl¯ÏE«h×òzK>+¹¢^å["m4 £¢›¯ Û–÷¬N[1:ßñ]P^G)Lù,o²yÑ/:Ó
+õ*³ÀÈå&>ìzuX7ãMÖÏ1¯Eîùf5é×]~í›àQ¬¥}ù›¦·‡s×ÑŠ:cZ[ЫÄÊšNfÏ
+Á½É¦x·]ÂWÐmuo6]¾:¯þ.h9%Œ†1ê±KÈu|“2<­é èçÇ>úç¿?²Š—Þ'³F1€¿ºG̵V|þwƒlÌæâŒÝ€.ˆÂ²·t­Û"krÛT•ºJFfb°À¯ž
+yÞL¼%=Ã`C÷g¯œ>§°yÓ}óÕFLÔã]£þÞðp£=¹Á
+ڸȱ+g—q¡¾ iæG±wÝ¥¾ÐR&
+¾69n@T)Üí»ó¯ &擳ßÒ[ç±¾Ÿ­†´œ¶z÷^Ì0l’ùœ‰$3¿Ám{œ7ƒ!4çŒ_ÖJKX™XX9òAã¶ï/ð5lƒ+rNr—r¦ zAîIûƒGù†LèŸuOÙŸ„“‹ñ¼ieÁõÒ;aái ( I! ÿ•iÂõ<Iè,Ì»KÔŽFÎTu?sþD¡âŒéÐÊŸ7Šñ]2èÎÍþ~Ê‹ñªOŠì„ Æ{2%ô'G3CŠOþG…lC’~‹柇³¡ë]{NÑž‡@¼ˆ:ª^£g˘â&4mC„ñáȾ6$š¦ ó½T»Úä‰Ô‘¼?'¹e'o´*#ÝuY©Sš××ypwIóŸýyUºL¦±¾Ê+3"¢hJPÉ'üöôR â_Gö ]ëwÌ$û²`Ï¡†"˜$_OfªàÈù;únÂÐ3ÔÛ‘R½´‘.øÜ©·«×Ò”ÝK/¸œ`qVN‹£C™‚²c@cq?<q6,Sï Ù²Ãc/~ü„ü™1 t©GhoóRŠ “ZK»?Ǩ¡¤?gã^áŒô±x,2¨q3ÉW/^Awé„
+b¸ÒÛ¦Ÿ}0áæo ×‡cǸ:z9o~P€•éˆ¬®~ÔY³>–eصFÓ¸'mrÞËêÊIàÅÉè;HµƒÁ3s]{N²¥šVò¼ÓPehØä"É;jx–"”¹$K<oú;nº*‰„(šÞ£¶ÏÂ%ßD|ÓõôµÔšóŠ}e\ßAGP¹µÐËußeNàÑ452ìïÎ~!3ýÚŒ.!þÜ‚>N&óÎé“™Úª¨¹ ¢L‹•eG®­­ü]8aXˆ{íˆkFt*'tƒÎ&aÉŸG¤' OVY½ï'ä‡Î¯ˆº¥€1ž:õå”™É4—´ÖïEüµ ¯¯ýqש×A­ú*g&Qæ8šˆYe¶‰æõÙ6Œ)B|ÏVù"¬š¹AÚ‚žÖo õá¹aöœŠ5ïÏl®b!í8c+erY¾!¹¾b<¬õ^6:‘Œoüò¾J˜70‡ðx:äÞsE²Ï±ü­žnTWåMŠÇ-ä…Ÿ?>n@·L—$ ®Óø6ènú¾\÷MЊp;X¯ R—ñ ‡Ò1˜5Ï抆‘3n²Õå䆳41¸«o@Ø<pt {F2n&ÀàûcC0±ü!M$ƒÍÄû26þÚWI®lÒ‡\› ØÉI¼÷ª7˜ÿNÆ0D·ö†^Ç.øÀk~úƒ#=#…ŸõÁ ¢¥‰àìtV&9/–TyFŒÛç>†×#$úpËPnH4>²!0ïÈèt–Œ®yN̹
+þi9f«sà`»¨F—ö9CRœo^y>ÒÚèY+‡Cé IÈI(Žƒ©eHª«¨6µ!ÇžUgLl¹ mCzÚiõPšÊ !Ü57{ÉßO)ñóyÕ+h;Yn ±— $–¦cê:[JP>¢Ãœ§€È²Kf©Vc‡ø-N[ÏUÌ®±(0Ç'Iº‚´‡éÇ>zb¦þf«W¾î¹óûûjÿðVaÆð7öÕ)éÈä$„•‚Šk1±!¼…"#gÖSôX-uœsð™òr¨àÓ³ ø<ЭP ñDôê8dµ²£o _s/ …<IãÐï7 òUšKŠ¯Ô#$~öªŠ¼ììG©Ùkmk }ÁlûÙ9`²$=ë LŽ9Grâ;ԕ̨«˜RoxbAúäè@†VÜöóRÌÉÍk¦ã™ÜŸ“>Õl‡ÇÓì>bRóð§VäWÈÙÌQýIRª‡æci'¤cQØV
+uqK`v®yõbÍOim¼ HsA
+Ïqx¥Hf'reÛç‘Ƈª~)¶\C¹¶EaîÒ6Ø‚ ¼’ ?URS< FÉ ÁV5ª¼áÃ8ViHé©ü$ /N0d"ÏœGÛ\2 ÓÝ8œÈíf¦,xiäå¡°tÎq¦Š†À"[%µÄXÎk6‚eÉéðMJøÉZü»]™ÿ ž7CˆŽ~nФ
+jÌ°Õcè*‹[©¾C [ÍcþOLyÁ¤¦/@“¶†·p7 ¯´¨­óWom/㫱ùŽCb­•ˆf”@þ™(²`ä=Û>2Y‘3ˆ 쯣Α‰thºÕ¼ä3&ŠÿÁâ´½ËyüŒ<›Ž¸Ú›œÇGàÊ<
+5ñßcf)“ˆ¯'æ!†#ƒ¨÷ÿ3ÍýѦÅ}PîÈ_i$g}è_(ªÇ-„ð"™¼,ñš¨lk³øô»@¬&|+FXŸÅÒšþ¶V6}ClÂ.rV«'wYór¯3véMxOBa®
+E‡Åš¨ .ÙÄLInH“;•kçq/À;!ÄxJP¿ìSü»:È
+¢žkon S^áéAêÔq‡kÙ¿Òçê„De‘¦y”;ˆ J âüfÍ ù8+²\E5È{óŽžÊ Æ‹–ÿŽðn©Î’µøt
+Ò:0…ü}¯1 섯åéA\Åš· pFÜ“#ó\AÇÄ'…¢ÐC¦·}¤ i€‚ÈÚá6¿åñ'ÐçwvDzcíü•´E $ÑAÃQ%ÔÕW¬³Ä
+ÕÒ\ÆôóZ’ŒÆuŒ†úúù
+þrµ“PÅÇ4  |,ï ¢U´É˜$Áþô)Éú¾zY#6G ªï~_†"C †E"`w|0iŠÓ 49¸jÍBÙ‚|ðÖÕ¯Wßá?/ œAª¡Ù <¨75+×xËù}ÖúU.­Iƒßë
+L÷ÅC`G¤)gÈeÍ`ÏJäì(²4ÄO"1ð÷QeÍmÏ "]"ÐÂ’mÍ{ýhÊ©
+D¥ù¥•Ý`=d{C:šˆ)ÉƉ@¢~[ÀìñHŸ¯Yv½[…0»ià˜Òí¤‹V$a?ɤر: /p}k:@|Àæ’IPú;ŸD*•:ŠÛηik‹#¶}¤ÇW!þüy#<T§©îqj¯çC/½ÚŸº‚²Tt¨ åý|vµˆ#"üð(ÜhÇ¥³ ùõ¨Kq
+oÜV‰X„óæÉ>Š)’1ڹݹ/ù ²­§ãÛdÉ<_Ûp+!¡c‹©ôç¸x@Juø§™Ë±ÈyñîçÜfë~›ÛŒuõ{mnûr¯ð réÔyïÆGÕ’6°ðçÅ‚æ b
+’óø(<Ny5wü¥Œ—⌽æxš+¼—xÈ…ãÍPŒÊ±UÈyõNç\ç~›Ûü^u›ã{u+s­ñï¶Ê—/}Ìåàèòž¯ÐGÒ-_ÍTòb`æ|Õ3)O¡nz'Ž¢z½<a2Î ¬rÔý~ <bdF4‡Á•ô\E¬l.W¤r±ï 1& €3™Û™ª4£Ë˜ÁM˜ lt“qóªf¤¨ i…NzÅ™luÆ&3K"¼³¹¦„qF– ØiŸT"«ç4¢ø]ÐI^Ppã
+Œþ“jÜA|ŽiÆAPÜùç(Êus­„}³kcçQ`ô†±¹Üo"$£„µÐ>¡î†àdS_%Œ]âÛGŠŽÁtOY=ÖÓO ˜º)² Þõ;ðlzCåèýl;½~ü²Á€°%ÇØ·øtN¥6¯¸º~Ô—å_[É, ˜÷“0[Z°p3þ!¼¡8õö œ¼Ek1šv´#›
+‹ˆù†ÿ»…>*®žKÑ¿lç`[1SŒ_ò¡g~_“Ýv‰ˆ¾ªH;Æ_ôê,­=`„3ÆlÌèçˆ@È`-&ÐÊ ˆ‘‘€ýB<K²¢‘ó7±
+RÍ°ŸE€è¢¦Ú!ÐüPXÚË1f‚%^ñ˾Ä*\I[H¼…y.¹ä{«þwË•@Ãk:*Cƒ½/á$â>䆎¾•ÞûQj…NÃôц±¹7û*3» ’fÊÓ\¢DíIi¿âže› CPÝibäxú‚ˆ8ª¸!¦íîùFRÂØ$–€c¼@m‰‰ÂruëûsD‘¤¢gŽ)«cl_Ÿµô‡wU°sL¨gµ¬+c¦Ä5Ò<«Ü¡ówµdÊÌ:7í5½ž£á¥KYÊâÌà晇j¨ QÆÇú6¦¿DV¬6T3VdvYŸxö¨B6…Ñ·c˜<{;·âÕXî?‹ÐèÑ„ì ªêu6¢¶^0 UARøn‹~gŒßB›<芼Sù/ãå²i‘Dá'ð;Ô +ï—%ò¬ľ5°W¡y{¾“YÝ®?ÿrÑ \ö©¼EŬŽ¸…H³aq§yµÔ©!³l:G‚Líšuðàx±Öh&%=ó¯Làh9üÖ–WÅH7Mb Fƒ•‰ºÞrNÏNER”°žIðt
+ø Ķ*r ùŒéluf¦oÂò1Ÿ Spå,ñ·£(üKîk+ÄmÅÂ,Œ'«tѯ‹Öz|®<z,–ËøÌze„¸k=ÜÁ5aŽž¯-ˆzå²–à>Þ §!Ö4{)(K´Áî$‰–¶´~¤¾Ï(ôeúêHÆâÌ4*þhCïä;¡GÑ׉nh4Ð<òi‰ìÓ÷'
+L¹OÑü2*˜hf¨ðhñlÿTGWäu˜–ð8Ø°>Ù/0!r<ðM3£ëˆ_$lyžPI€å»•‹[ó6sÆP„.û±ÆŠ;ÂÙšØO >ªÒŽ4‹~
+ÂN˜×QÖªòø¶øðÈàî9ÓpËé:ãNtK­& 3•)ĘÒ'•€Eà`[á™p7ØœÊìH‰)Ýâ´‚±¼Å]ë²!0‰‚#ƒòÜK’MžÄï<êîæ7»ùÍ Ö9”DÍк0˜îXLd
+âA àH˪yÓÈÃGq)"c¸l›QÞ#odŽ=¢ðD&
+ã®ms¯…_¯æ >¯!¿¼Vkò¸ÄRøfuûĽ x€1Ûñ[Å7Y–p÷$Š¡ND”
+þC¬d±ß&ˆœÚpøëDNu„<xHl2ƒ”ÅÖ÷ /ïIU}BpÔ¡ç°È…Œ‰‚Yý U`ÈS%eYèõÌ$1¦‚AHvwÚ½Smžy§:Ÿ×üåCƒÄô@dë»ñ±ö€jÁ ½ìÇGé²»9·ºæJ§,Ù@´Â†Æý A³àNiñ5´šÏLÈ\Z!VÒþn™D:?Áíè¡ÉÆ*€£_žv 2©AI…;ÁÜv¢L7Ñ.Í›òt¯†Æâ ìâòopVÆhœ‘ÁÌÉ´„ë\`R°p=ù¾Ä w‡¢öÆÈŒ„)
+y+*›Â´I-Ö!]JÎÑöË4Ù‚LÒãvˆ¸Ê®Pý„dÕDýT!…&/“ZÂÚªè+4}l¶NC‘ah«ÛÜ0w.â~¬·Š8V‘áKZK½fD)ãý*á0¸¾fý€ùèIö¤ñ9†Öa)
+Ôjl°ÁÄÂH!¢EaLyÁ½ºe¾3ñÉË®…¶•‘6æÃV©¸À„•„bÓêŠD8KšÑfë4Òwg`ƒÑYå«_®š¡‚ÿfö§EØ8tÑJMâfZr²ÎéœZilAFŒ›EèÅhЩä°ÅÚŠÃbäxDæfµ¦¦ Æ¥®l¾BCZÚŹŒYqð¶¤Epƒ‚SÜv a
+ɶ´¥÷Þ§R±î`^ÙÓOœkÑwãÁÅ;LÆ•/ï95æd.Ê&ðLÌ“U` JÚõÝ%È)I:†‰ðÑ¿e9Õ{èÈ¡¤í* Y£Îd‡=ÁeeªÓÄ”›~yÚÔh¢šõ9~™/¦ uWÂà™Õvr–¸i*pôñL7±ám‚è2Þ˜Ñô~x=d¢¸]&˜åòÉ¢°ê§Ô ˆ’¦zÂðtÕhCÖ:Tª95u3½INŠXexíê´³8Þu«ûmø:»52vXø†ÉÚä} b-Ç=ì©#!ÂbçRÇk¶ÙìPÂC3¾^v-˜º Ä/ [!ç B7å òÑ—Q¸b5Ò„0ƒ•xË:!ðO_à'DA=aêÅã ¿™Ü$=A„PyuŽ4…0ñ°±2h©ÍŒ’Èd¬qLÓù¥gEX@V}±­d- Iä0­ƒïà)jŒqm•pH„
+åø:7’Öò=¯82@È7“BæaŒ‘ñ€&ã|£òŒÓN&rCøAà¿œ^,´q–JÊ¢ "gcffÇzªázEßR,Ðë ÈsèJXu
+?o"RnŠ¨ .=Bõ”CƒÚû‘ÐM–u5„,TØ‹ÛÚóTWd-YÙžÇK‘y-”Þ—õÊ:T¤—÷Ï’
+íÎJu¿ä/CVwp[Ü}+a<eÇ·d'o =ùÕY!2sãÙ7 +I«øÕFâQ šV5,1xˆ¥å ù‡òrI®#Ç¡è
+¼¯@AüŽÕCïÂS÷þ§}n|¶^2îꨈj "“ÀÅýÐç× øcQÚ˜(T…®”Šæ*uù‘Ö•¼u•±ê‹_¹ŽXƒ $•cIÿ`»=,aCOEêÍO¯qÍþ^ôÆë‹sg"Ü83lÒÈ&Œг3ˆžŒ”•½øÄî
+”UI@´v>'«íô¢k¨ñ5íZ ‘ó¤A†Ž½OÑš‹áv–}ScÕ'€ÞÝábh]y$
+@=óüñíLÿTÔ³ø A.V¸ …! ÈD[Ì‚ot>Áûª@Â2»ú ÊÄ|q1f:àŽ¯Åì ¸}#ƒ !Ýñ·9Îá¡Š>“¡ÅUìšÇ2—X?>K.
+‹çšâ`Ïe/0ÿŒ†~ãÙ÷5ð$ÂÑîx6üÄÁÍ#îÁãš)Ü-DI¡Ùdý@ú«=¤›*|¡Â:œêclO³ð7¬ïܳ̈Pfa°
+ÔOBŒM q$øþJźðGc^gÁ¸Í±–ïxǼ“Í.ƽüÌqxÓHÿ¢’Ô‹*FZãtÝ?Ñn©—ÃK+OEFÓ ßW ‡ê;SŽÌ¸ã;ç NM¬Ž´Â÷ð+”%ì‚‘¶¥eeáðe5††N`†»R@œ‰p#2=÷Zdg™øa¿”›SÖVþZ‹?Kâ*“ã>î:‡[‡ÁG¥Úi1î“xûÞÏã¸Þ,tˆ’s»,U
+¤¹ËÁbuGˆ$LK€yÓ¯ê¶kH]²J~®yÂN3Öy1Âýd2ñ0J7ë“Ç4ÄŸ|•ˆ˜óýŠf’PMì—}•FÀ³,„”ƒ3ìÊ߀•¹Îá¯a 4mr¡Oìק§’/(ýüv*:㢿™¿,ŭ较‡ëþ¡èÎëõVôcq ò8à*¾ ’& ¥EpcR‹cEßÝ°ÂyI•àÏ S´9š i#ñ¨µ]ÄH Ш¦sÆ\Z)a(<†«~®«8‘õ˜`6‹Ró7mÙ¨ÎÉ8ºX)I†xò³^£Åè&ýå
+aÈr¢]ú_Þ(Â_
+QX­¹K°ö%!Oõ@®›°g]ÝêfeÕÀ,UZ‰];HEQªÅfm„aªt/Ä5í¡d$G·:^7½ш„õÁ¡Ô_,ËÃÿ…^ÂÌÊ'²c¼>º‡sÃ6ÂhC`ƒÚ3íöêèo¬„+.èYV×1üöÚk~qt©BÄœ9·+ð WÈ~>‡ñfñ)`k‘ÍRÑÂQ!Э½è&£Ë«¨¨û*8:Uâ­oK j²YÇð½#¨Ø7;¶’ÕôùPñÅÆîö¸¦òì¡è×C¦P‚Û´x¸Ü>´jQ‚›Ä%‹·®èÊ÷䀄áÞqZ IõØ5
+´ÏE¼Ã9ÚáXp2…|b~Ì­÷q¾•p`M”ErXžÎ ð2¾ Æ'ód0ë„šüý@TL´:ˆT_7á8x¥°þZvî.PÈ€m(ÌîžÌHƒÄÜúCIŸìÖ$m &¯‹Þ‹Dr¬KerôB®\°³±àM”)„8j.¹+Ø‘)‚&Læý쩽èçëÀ‚ìECßpù3ÎÁV1'+º{QR“è Ö5…h²ýJÁ²Y §¦=(°E€Ep_qÕ¥Ÿpx‘c[KÅǹx4Å'31JH;Œc•@ÕÚ9j‚üx›
+阿àÇOô,à"„Ðd¨+`‹mFÞ,¾F.(ºÜŽ%¨&q" ,?ôºê½¨\éJ¡=ëœ>åaÎy Tð%ˆô¨± 4Ôäú.áîà¡¿—
+ѽRì•JºHž)ú—á5,]¯gwƨà^I[꧒*X œ?{:„Ö‰ ï_ ™ãÛùF¸s•ˆœŽÍ.‡öF忆æÑó–Ï6¹Âd¯ ;;@YGÆ˹"Á,%ž(l4_[ø¬t¯ù5 ÑäKKÙN·ƒU+b븨qŠ×¶Chö¤€™¶)-ÃážwÉŸQöÜß{TÑÖ52314´Ã½ÅÚq”o%‰:A„µ÷ó9 ¦cú*ª¾¶<l­Á>e€Ð¬^ó—ìÎÅ »=mÂÍb2ÅQQ”ò’—¿[ÕO9ÚïÿÑ…B™l#TPöûÿLaÿ]E¼²¡g­ŸâÜUÁË;è&ìY¤©}Ú¾*X)ÀÅ~n„Uñâ¦Üºž_>º"*„UÅó1<¼žS–”—qA®‹JÏϧd Mèiªù)®ÜŠD“ÿ6Eá£Mõ¬Š~E ‡émX¡SÑU×ÙT¸LÁ—Á¢E9Þ%¬"¦ÒžŒ¸LÚåì èÑÐ;‹ÜŦœþت¤VõùT¢ÂNC3
+Jûª[‘Écè#¥db ˜â†*6 qn+«
+h†Øi\`/%ôn/J³s_õV$'Ѻ
+Ÿ²
+hê0ˆœùÓ9oœ¡¯q½‰ñŒ(!ˆb·aΉG«Ì&ð¸mßøë+ù=Ž fc' 2ÒÅ÷µ¾—
+5ãZêN__j~kÞ'yC:ObUÁtïÄúÖ)=1Ô(£ø
+üCÞ”÷ „Y0¬/æ‚‘`"Œ‘¼„ZEÞpæ‰ñˆZ¡@œº.LYTFS`Œ8IJlW¼¸àœH-HxHËßßÁ‘>”6% sž`øs]…@ ¸—¥Ž÷sò‡¤ÊVB(#üʬ¯
+ör±üœÝ©{Ió‡ â2 îOçÀoxHnêùü5†ñC¼Ô¾å'O¯2˜¦ò)8¿ôð*Ã\ô&, Ûsõ“J‹VnrðÔ¬\ÜÄ ÀÁç·SÍ WQ™Ž<+(Ì."Á±Æ¤,RŠ¬z+bÇh†ßň뫕OøW¬¬+;xdUc¿¢C™ÞÛ.GMæªÅ°Švo¢?Ÿ‹˜³×ÃЯy’Š†ŒiÙªvÂ.^÷°§¢… TÄm¤´¡£Wf~Ow¢DÔ§K/u”²gœá4ÿ AÈ/IPÆ–¤Ìfã+sŠs0¥+‚hÝÊfI©(+ FICŒ´ç‹>&œÍ
+f¹†ž®þ 9à‰~þGy™äÆ™+Aø} ÀyXûÝÄ[ùþÛ÷™,»Šd» )ÅŸÌŒŒá\2ð^&ë½(#±¨¥•ß±[…
+²oâ^s‘1Ó(žïÆI ¾F‹l]é7çëê0ÎÇãm³‹Çø¸óC)ⶈ/õçJIpÚþ7¯Ë@!. ¼D«Y2–VÍ[û:\˜çÙ}&¶šÂM_±ševãU*„–Å`Õ>ÅÌ:Ÿ'Ìyo%äÇ Å -סhx>ï0»Ívb+*
+«L‚µì#êÊ´% –ƒ÷ ,6 rœbG?Ö{E$W$% :Ï«É€„í+Îfþæ½çˆ»$üãÙòìó<˜áB¦ßËW_ÎÑÆ0?P×—KcQ/H9»Ò"À¡:+„™ìA>鹜üÒÑ­žêQ’)]F ¤o³å±}ñ`ä_§gúÚÎ×~«±íÌ•Ö4q[U7HχD…eMËó` ² ók% –†a‚žîáω¯§˜É뜤$ú™¶vŽ0ëÀ†ïã|+1äîŒBæÚNE†‡áá’)í%±$ä+9ìÀ®Ÿö%Ü#·ºf 5xïçvRâ¹0 T]FŠ÷qTê‹+ú‰By3zaäNþ¹›ã<)
+ÌÚ^þ"8­¢r[=l^T»Ìì’÷7éü1–ÄÊOØD˜Èr¯~ öty*ì¡(2.ï¤áߪèÓ°Z,`’™žLñ$-çÏI
+
+d¯þ½Nê­Â¾ô:ïý” 4û]àÛß´Cø½5‡=ðZw^Ðñ—’—}ú½v©a$XGJ©¿lž©Éé”›×~­Ø<ôéC'7þ·Û˜´VŽ%FÊ¿fÄ_C%ÕÛ½·"ð„:q1 ^«èísoEߟÜi\ýë* XËZk!ºM¹¨C† ååFu‡¢—ü7Kز$ÖÃ!NnÈ­|zÆ›"ÈÔw 5ñð0¸Í
+V²Íd‡œxyIóÜ N éåÿªÇÓd‚ 1Å…KŒ¤¨HòŠLØõD©+Êðs1rÛ†s˜ªãÑN.ØXùUÒD.JHØñ)¦[*èå ø[Sãc^ê…qËzÿ¶ìʬ^¢÷ÎpT¼´ŒÈ[§æé+kÌîûC‰uÙaƒJV´­çs¶A ¸Üøz)ǶiZ¡`°QקހÁÓisoøVüë /ùucLu(xñ"??A²@ïèéPPuyÅ“¤íˆà™Ÿü:sd)™
+˜íÊÝK?éwZ˜gKJÆ-®$IÿXÒzCzb>ãÑÍšÛóþßÇž Uÿ¡èDŒÛŠ}TTfä,ì|áâkIgÝ‹o²©,…˜²±Îx¡´€È`}on›Æ)nSÝÏÙ°±ÇÒ c§x»aõ-4•ÁQZ!FÝŽ%Uæ=cÊJãßúÔ¿¯×TÎÒL˜W8ÖÔŒ†Iº1‹€ó×,1Ñk–f1ÉÓà¡ ë¯QKbPqî iJ\Á¹…ñÓËj”q3/&Š<Ÿ²ô>¤• 1D„VÖ2+R"º`™|0J¨5kyš¼ÅúRƒ]ð‰Ù¸“ ^Ù Úæ92t4ž±µòSkÀÜùTi²oÙÓeoº³ÕÌ5¼ƒL°šæì£"¾l
+òŠ\ìó¤FüD/³Ÿ 8IµïG3¦qxi9ýžîù`êÆXi4 XëÙÔ ð‘çÏ·¿zºcO·cu‹§;âyB•Oï.òýc ·CÖ±-·^Ö§þ}½ÌÓahá‘š=|b7Šåqλæm ±´"¾âGçíù"f b÷5JX&ÃȧFSü–u*xz›E|ÀDø´œÎFÛVD7:=Jä àHàáM%I …Ç3žÿœŠN,B‰Ý]ÀVÄç¸t…Z ù},b°Ž¾Êà„à絡o< pèÖg8
+à”ª•ðÛÿ¥Ü©Àš(7S¥²RS"QåYª²†ÍԚ׋â’
+¤±>J~Nh´X‡DôÞnçTÀ‰j‹•Àà ¦L9Ì’1u%‚ç^ü)îö)Ä”@W™²50w€Ÿ‰
+tcž“XbÐ
+Å|\tH¹ûçÞŠ¾?ÙT[h§T‘Ôž"ïéA‚Ep¿.EpâÑ(Rïtq˜·°”Š >UŲ6K›)>ëÞ¶Ln9sEFóçü´%†f»¡ŒÚ8ƒi—yNá0°±dÔSÀ]Hï,Á´d$‚E·OIÁÇ?Î^ŸÂë Ñο'I  åN
+RSCeÓ¬jž°ëØ0J* Ôh­•$^_ÇlÃ(‚þ à8+"„Ò©T‰ºó˜‚›]uVhG™ëÛ­„ÝÏĸuˆÀó@º­/É™Vé`²"Ì~® Ã+¨„
+H°¬ŒÌ®ˆ’¤ ®J1a´p~D˜Á™%.ß<PŠ¶
+B "{Üs€äR’0ÓMOyéóËn3&ß7^¢j)k!–¬N}Ý’½®ÎwxmÞ*nJìêÒÖÎB)ù»uNÑdÕ°ÝJ1n”™ê:>>ˆÏÖV'`ˆîñ–ÄB"…ìáÕev#ªšn
+
+€FŸºÆnnô=$ ôn>ºÒ¬¬—4Bd^ÊèOEM§aäáÀ³BfˆI4*2€ÀxftµÌ’
+V–„l1Ï¥<†ì`‹n0ŸE‚0…³[t–`áŽqÇpõ'k¶ÜÉf0 y„Œx+er’ä“­„$¬{$ºæc
+e=ELÇJØC®RÆÎ&ú̲ºãj©†möÔ ®¼~Ù”Øc°b%„v³ {wF‡½
+%•NCzi1%ør€åÛÑ¿ÓSJl«Ó“ïÖ9gwš
+Òþ*:ž%>¡kÄr[åý:ý•;8;rê¸R…Fk– XD¤ à–úàZ¤•èsês-*¯µ`«éF`¿ñj×ÍŠf³…OjyØ‘¡
+«Á:ä]¦Ãµ1Ë”¨a-G(ÞÞ«5Yfú6%kT“—“J®7ë(Q1qñV‚I( 댜[Çs¡¼:0Þ
+#Pøp ¸ƒíP¿æÕ¹AÎ
+áy]ÍbÑ Ôª~Á«ŽÄ`%„!ؘ–! ëžê–BRæéwþŸÏÉ‘+—ŒÈqMöVxºÌ››‰¤ÔÄx*Œ@ ˜—ÔÄhTŠiSbÏ ¸Cð@nÝê¼/N["cd†ØgPˆ`ou
+3í•nÜ>ë )ÈŽ†Üêþ4XœnõÉè´#[UÏÖá±½zC§‹Ñ)ŒEÈ×YB„°*X™º´anm5þx‹•ß¥w)ÁO"_ð¤˜Zf;?0–ÚõA¿òÌøúñ+¯¬_~Á1}xøÇß|”Q
+¬l>þ{¤Çolp™XŽ>&@w,‰<+­­Ž‘HCW–öÐ%Ý°yIE2àIv5X¢ÅCÄ1Åc¤™æ7¢¬¥>@“Å(LhRËâ\çöbß^þà~¿s¿u*òž¿âÀü¼ñ¼ù?”~x8®æ¹‹wºÌã¯/cœW¢wøb6ÈI:¦ Á§-¥lì‹FÄNE !†ÇÿŸò2G®+9¢è
+°Ú25¦퉖¶À%ÐRhÿ:·2ë“ø¯^ë7EC ^TÕË᳇Wx¡ÀRn#ƒÒXÚ›7‹1(T.fo¼…5D¸ãó•™Ìÿóµ/ÿÇ›® ‰ü.M›¢Gëfø½
+ÀKkoã/
+WCÚÅ@^MØ»é§4™UxÃE<ûE:“œ¢Ajãß £©p± ƒAÆK+„=ÄÞ wÈŽ®¨k¸ i9o¬Çg5ÚÎAýEÄ´¦¹/¡Mü•0ƒ !½°ÒqŸBËeí{£æûª
+¡V gpPä9ƒŽöÇU(,í¯NŠ#PFåyb}Õ3¨%&±Ð,ˆÃÏ!åg‰¹›0 \ÖžöHVmZÇ QÏÜ ‚^2gô›éÚW1AUÍëuGA®•Wššmk'l†°à"OiqAh#ýÇW¶~'%Ì_Vø”yÙ ÷Ô)Fs)n‹¸e„ƒ ìZb8¨-ÇR÷WÁ)ps¼¯Šïg»ó×%‰S&AC³s
+þòʵÔÍ_¬YÅâ•àN)öÀ¦â÷WûLh s^1Ÿ7fòe³*ŒÙúöŽG î¡,LV/ì±Aøw0¸©´IyTü³ Oï7…ÉÒ˜Ý-
+‹¸™žÂÞñypUßÜ…/&ÑÁÕ³¥›v~øUÌ'BÌvwK^WöÚ
+Àçž+#ý«ž¸‚¯â£\¬AÜ7é"X·ÝÁ÷ñ{m<¶aÙõÊ÷+?dñ& éŒÀÍÉ–A&á±vϬ´X
+l/‰}j”² # .ŠT2ƒ>ÂìE¼×é^‡ÈšäãAÅÌ”*׊©8.•M¬¾tt¾ËÏöìdRÿ·Vñ±Ï’2=ⵄ¶vØ[ñ‹°ˆX5eó£òêE–­¾Pø6<ÞílÒ#øPÀJ£@øiÀ6ø{;+šiZ+{ôØ95–=MŽs™¢,Ž¾O<C‘e® &‘¢Ï´2Êiß@ôÏUeǾébœ šÔM±sXâ¨1šÆYã}™ˆm†ì·«0Ä\ƒÐý¤l[zì“FâG9·¯1S`
+»÷’O@)VZB£¦Ó•¢ïóŽ¿ÍšùÙ3ƒ+ÝÊ>ÎY’Hz(’ɱ­ìÀÂÌþPÍ65œøÚ²¿ŠÕA8èi.¿ô…­]fÀýSÅ ð«£ú9pßdJV/ ‘ùšSîìÅH,%cŠ×NA¨
+˜ÏiC¯Â0d?•ãbô×°M²­JØkêd0jÆ1x™O
+†Ž‘0üA&"Cšnj̇—ŒG•“,%âç`XFêŒÁ:¶ó ²™˜09Lä¸;;xÉ’CHpü ?AQf GQÑí«H©òñ—°¢"ZÐüÀ<­ÃÁcÜïÈA¼û‚Wý¥­“_”‚3„Ý}¦ $ÇC? ƒ“Cž+´²3qOüÕ‚)›ßóò泜6Èr–¡ÁˆÁ†ôº4a¸^áî>ç'MŠ{g“¤P› evp"Üæ+Cf´;ißD­]Nw·׆-R8Ð)ˆ…ØÑI»2Y_D òÂVBÃZN‹;.©Ë ½·+¤¬Ï–ɘU{ÿ2¿\à›\ÑçC‹‚…2šµJÎœy‹äÊéåiXLJñÐdJU‹ÜV-È›
+Ê̇bWÆÍ9”ŒufQ_óŠG!¼Ö ëˆBU}L™&nèN:Щ<Na=ôãx[è èš+×uª+ªÊ|@Ÿ/,ÎJŒßþ° ÀÇÃÙìãô¾Ñ¤Á›8‘ ñó¤4…èr'*UÕÛÙÔÁg„z…Ø|!ø B†´n ŒV#Œl÷¶UI½ˆ˜ÿëŽJ€XS=üh6jçrÜ6#€F1Ê–°ê;|íŠ[ãâWAÕXÕµçs
+ß„™ èã5¸(´ )JÙ ó Cèî(Gå%&êò5!Fò*GÀ¯Ö²ËeŒcïÒ@¼Û70<ÁÀÆ´Gú ǯï.}T<@üÃa9ܪ
+ßïÎyj%“¬œÓ©›ÚÚ„<“žú¾éëLˆä1çèV¾Ë` 3Y…òÔqDÀÔ”1C³¦Hÿ„5íaO;›ÚÀ~¾vý*ßÓþ‚L:Ž:¡a=M{–› q©7‹àÑ<{3HRáð¶Énq>>Z¶ïñt,YÉÌÍåä?2V?½Ð]ÅÔëYuèh¢è8zòíxÕ÷û‡RŸ7"Èf‡Ù ([JIe‘àÐLx£ÜÕß:;Ï{ÁæPî 4~v ËR±ÍõUБ6 Y•’Gl÷ X“2ÅŽgóuWPmø=8ñ±ƒVþfßfE%F&³hG ¤6Úá´ç£î]ßß¼,‹‘Ú¾ê ÄÛA—£~Ö[;ŸÓ”å–u ÖøkH<¨Õ2ÏÇ!kP_•$!í!{Vh Á'žF^Æ@J4g °ÏÖ4ñtèqÕŸî×wóu‰x 1(6´ƒ¸ª)V_à èÔÖ„¬ó‘æô@…P
+âGPXˆ_Ep9ðr¹=‡Ym¨!b ËSлtâéÁÇvï—âÈÆ:H  ¢k
+âOØúõæ3ãQ,é¡Ô®Ì™VŽƒ(Ha7¾?BÛDCJäš:Õ+¨|6ƒÐ‡”Ká×¼:0
+®/õ®8ÐJ§Æ¼'y…{Ö02âcÞ@˜}R˜ìÜöI'PÈ\¢Õ6}:¼Fj™³ª êá«A*Aþ,[ÂÕ‘0Xßòsžj,ã„.£÷Œa?µê á7=uütÌen®¹Ìß飞ÇøZ›Ë.PÊI"jeÎtù²SÕcÞñ8Ð÷Ï=;˜:f*Çxu/ k\®{}¾ò¦Å+" ™}vE&¯—›ˆp‘[¨w„½JZÁ>$yÉêž î¿ÉCÅ"ƒ=>á‡ÝT¢º0H ®Ø,Í~TcìœJ…èeÅ¥È@c˜®Ç•‰àfùáã1óò"ÔÌ[ðs K\`¡C9$ûä¥{2“à>|,õ¹‚Ú;ÁC\dgLᯗa[‘sôò”—»nTAD¿`ÿáƬy?BDf!!‘#"Äïsj¦gmí½»ÉÁzÕ;3Ý]U]Ý¡_ÛìÉ£ pÕzÏ™˜(üm­É2ÇÚp.9
+±"SSŒ4[Tð×ÎaOË,k²¼öš;¯v`Ô:#>œ¿j.³à«˜¹‘Ý!¬›‚ø®+˜íoP7•ŽT;Æ7ÝëJ˜
+H‰”—M’\¹ „OÐw¨ ¸‚?
+óc OYÖF©¨Ykù±ÞMäs[#€‚î”n i!'âY ÿ]cÂG±9LÎvtSH È]ÁǮߴó $™ƒVôê^?’9hºt†v›#§tØ‚t£„Ã¥Nχ3*1‹£¢Ï›¤&ä±^r—0#xÚÛÖ’VÕ´>©aîÄ — EÌ=ºžƒÇ?Ãt(E[ ½aè#lðÕЈ0çx–Î¥dÌ>ööÔ~k¼›€ 4‡w«ª—Ðp¥[\Ê#Ùl TR
+O­e{^ ÷ÂtÛ>2*±•-ì_-ïÆù¹ìµ> JC‹úrj´ s(ØÄýuqAÎVÇ.ËoÏ®4ƒj‹~ãá¹݆¾ tøØ7@Tšq$’$[úãÄbßp},ypP’ °w
+.8«ïuÊêeÐ8?Õ"¾)yc‡ä"FjÆé A!byIâ Ü#x[ ß›«¹åB;cé±y
+ùm«þ¾åá;å7;HøWôö0ÕÉŽHQÛêëmô¯~h¬<hDžCöR¤
+¯a¿ËÆ7ADm6¢5YÄ8€X"”_KHΗhÃ
+>Ì`ò§ºýø« ÞÛðõ²ŸÇV86Bü†W‰ Î0þ:óÙ“ÀÚˆûÙ¯ætÅ_$õñy€\s”™}¥Ëû9$da]Ñ«1y›¹0ÂÜh ‹*¤Èy›6É,Ä@ߟBÝÉE8õŽvÐ6Ç‹óSˆ ‰n›6±(„úøxùÂÐÏèÄuY$šâMÿ
+aÓÁ4¢M$4YÒrÀ™6Zpæ± ÆÅÿêþZ¬eƒ[!Ò$V,¶–mîÃH¡ØŽV_ûúòõÓ°@3Óam’ÉŠ;Û× [á3Àÿ2^îHŽÝH]Aï¡mHüaN´L¹³‚ŠñJæìÎT“¯†-EHM&ñË›÷“W‰Œ‚y;”øVY}Æ÷ZîÖI•,$=Ýò~= ‰™7åþRQQ)vœK½{ÉY€
+øº)êb'VâQË:t : þxV´®T3ŒÞynL®]bÑ><c๨9ʸQ·Ð±®«HHEë*ïå³3ªÔ%†±¬!w}Î["©ø˜"e¥‹nú¡d©2Ikðv¾[Q‡rË4ë4­›îÅCTÓ8
+}éÁw*ÒÃbˆX
+9“¦Öµ€¾¢ê±7{‰c"8Å:…l†CCv^'Hwb¶ZP¿žæ‚‹—[9ºÄ 47m®¢Ø?ˆºÉÃþt®…&y´â’¥Ò<8q„º+žØ˜ðšé áVÞlïô=¯Kþø7*ð¯ÿüøã¿ü¢èŽÆ…`(}b ®bI´ÀZS T„6¡Z½Í¶Ì"ƒÝèS¹”’.˜ ý³½*!Ô)2ÅX%˜ÿƀЙz(ù\[ N¢d°ÆÝ:¼¡Ü|´*ª$NÒŒ#] 2SÈï‚ïD>…ŒƒÜrŸ€¼%ô=G®kÃ;LòÃÊö·k 'È3ý³F›‘OiKL6¾)z=vâM£Öt{r” ÇúJÏÖ*E*þ@ A»±òÄÿ Éئh°gõj L@r9•x/dÈP>|dº[g
+W7l&"ì
+¬$¥‹úvÑi
+ÙŽDW —ßN,óõÆäü“‚PK’ïfOðmX4šPx™ºS륨Ê$btÆNQ¯Ä Æž u’€˜¢¸LnûàÐ}0±™™Þž%+³BùÌßÔ¢k:qÃ0ÓËQ"»Ñ?_¦‰ÉɈxØS‰»‡øèu»NŠ‚/^sŸT‰§­.é°Æd7&•HÕÇ áí^ŠÖÐäá0â­<üÃófCœDÐn‡udfŠ'*yƒ:C'Y!1ï«—ñtÊ%~u fÃ0#ìÇu®à4 e€J<õsèýø£lèæü‚Š.ðjVt÷ôó­>áÌo8K¼© I [À'×ôØè[ÿcÍ)í0L$¤êCÍ_¬e@Ci#þR¤‰GWèNë\—ò ØÀ@Î ‹bË°9Ò¦Ëëå|*‡
+gÐzBd:²‡J
+ÀËØ[w¶–5MºVK;ÊÀâü†^Å´b
+BÌŸ´Cn„¶Ø;DWºÂÀ‰×ë¿`±óÕ7é'ƒáÑfwë$ºUþGy™ìÈyAø æú¬C£öåhÌM¢a€†ß_,ê$~}Q™Õôô_M!PöD×–™±´PšÊÏ»1{=,»òŸA
+R Ë×±{«Ø”:2éüKrEå³uÈ}M]ížÂòÔ¥ïo'Щ߫5!\6·Áùè4ƒ—í>zâ…óx=œcªÄãA‘†GÑ‘1}JQ59Ç@3e9¨㲶|’ÈVØ‘X6BG&× ‰„!( Ãgržd™ññâ^Y@p˜ð)ÉIÍŒý3Õaë¨ á`Ђöu®Æm§A¸"³Š½ËÄÚ©Ü'ÿâ´8³r^¦ÜµBkHYŠçÃ
+Hðe%ÊfÙÐÓ¶ òEePäXõ(Ú霾ø©8|ý±5rœóœ (=® ÇÀÇ«$hݲ…áU;­³&Ý+óE.Ì"ËÀÓÖÒ!_î®”‘ËKTî•À^¹½ä¼ HöWµàxG›Ÿgñ ç†GOyf×1õkcòJ7@šU kùð ¼91$:‚^bH!»ò~AôªÓôÜ®¨1Æ4£Y|*€+ ý®PÊ*Êå «1…8•ß*¨oxé¾*zX‡9å—$^Œœ#Ø;ôº˜ÖYW™iâ(!?O–¥ÿÂ|4 b!qèÝOƒïÅáÃæ÷œi”¯fT›1¦›xuƒ$Ž1ñBmø*(@PRhz™wߊv G)gzÇã\È™)Z=Ë
+E*c×W¬Ad†¶î{1\3Š6â½Ô³3æÄ߸FCÛö½®ëÐÙx±Žcxpùw{ä ÃOf†dȃr‚*0e0P?.ÓnÐ8ŠŠÓ<Ú¹†¤­|/ž%¢ÎIïB§¤¥™á’OiÐ(•†ÐYBkçÃ<·Åó¥|'yWÑÀØz Ûfå<Å['ðÞš¶Y¼{¥'tÍ:}§'>ì„Tw±Rz4ò™]"ðÓßЯoA–¡<± }Ĥá \Ãú߬~Á+ý|‹·òÔ©âÈÒLÌ¿oåög6®Hªq¢JË»¥åS™ÚЗ¤tÚº¡FŒVX ”'ß‚êxŠ¥êQƒ; Æ«¸|@à~AjÊ3Ÿ²,¢š5A ÏäÎÁ%CTàý+ü Ü÷èb#û±ôìÊvõ߀þ| Ü-r™t›Ûß¿rÚ!1cü`KºìÃ…`Ÿ<Ë”ƒ€u‰¹Þ»W\¾JÔ@_,úæÀTþdÀ– `!Zš†(¸ºdŒZ@À}ÝžU^ÿ†~¯áøŸ'2‰ÿú¹›ÿ yÐÄ)êh^Îðᆶ/>ó툨Sï?z
+Š¿Ÿ@¬Øâ9*a fy¢\EO¡sÌÚ Â9‰–£4GÄŽˆL˜H^ôWÛ gÁ¿ð ê݇š àN‘aDH•5”‰‚§A¨~!Ï‚$¤d¨÷޸‚ðLiÃ.3Jk«Âqæ\1kv%R%o8>Eëä»Ïðá;×:–!6p (ƒ¹ %$~Á€„b,¿5—û]Az|[óTIÊ.AA ”àn Òeu!ÍÚ Aׂú Q™T4VG˜êÞè#ÆC}•BcG;-n‘B±ªÒ“ ) ˜„˜R1¿Ã6±¿•I‚ŒëÅ Ñ\i¿º¯êâÃ0Ì1 †¯P›ÛBhˆ¦lǺ³aª?˜÷\¬HüDɧ Þ䌭Å$xZG¯YpfL~ÀșŠ„Ì…¾)»eë*ó÷Ô1Å}«.Ç:"E±×SÒĦq#rÈz½¡pÔH#Gƒ0søAæ: BªåùpüÍÞ7Oi!.®í~ R^™œRw” (™È–ib¾¦ X¬ÜüÍdëQÇ ž7i+vš2Sëm(ýd<znз •¨¸0Hµ7æžlbÔªA"®þÄtûüWl.ÙH„í—⎙a†¤Ò£š˜Ãˆí¦± „¡ÎèKªò«B`¥”<h,G(÷ÂÛHû¬Þ7xKò%­•µïµT˜“â«u4Ãt1ÜQü0˜|0oš£51ª…)ÃU4/'wÁ=ð:@÷,H{yì*J˜CèÇfŠ•éG"S¦O½œè ó•—Èjf.Â9{« hh|èêÛ´uºÈÓiT¢JAºc1’Ýjª´§D™ ³wŒÇB E.f ŽÊšYBÚíés˜8ij ùs<8¿öy,g[0† ù¼»Q`ì`ç6B¡©!ñÒš 0çƒØÄàÎÃL3cÞØÍG³Ñø Õe‘yäÒpõЧ{ð ,7ü¶•£)[²™Æê8USffÈ('ˆ£¯‹*<füEšWuŸß’3)?¿¦.Å;âÚʲíÖ3V¬?=¸Ê DŽ–·Äþ׶i‹ ˆ¼Å ˆŽ1ÁvŠÕ·6‹³
+aÁ!ʵ-<ötQÎþ<Y> vK ç^„}X†Í šz4ÏÂCó>QQ‡A= ÀÛ¡Rü™ÕæåГÁ3ˆiI”*G'Hƒ‚žbè£=M#…ex¥{›£È¼†ÉHá¤D!ñÍH[2¡bEÔº‹2)Är©BLi¶ \ˆ¼”1¨g"f怠e¸>Tõ$ZæÝÍFY~d&ëñ'зHÅh!J-NÒîYVð¤ô%vM7u`R{˜*ÌáNÎ$S–‰þ2]Mòû"k¶SeŒB£Ò _ÌÕÞv/r›Iž»æ áÓ 3"¿H[èçe´C|p3-Ðê È›úŽ¿i‹&KD/øf\:N­3£YóÈ(âx#h hpõ¤$Š¸-ûT©qnÞ¦Òx9š^»N¥0LÕ5–áB˜Ãà’· Ì^
+çŒA+‡B/€±‹æqœª .C’hÔyš»µ¡GQ‚
+Òçe0•4I›PÃÞ‰Ö Q€<R!¤ ¡÷±JòDˆ"b[¡oì9¬['Hé6(°‰‰D¢¨Y¬!¢Aoí»‹Çp œ:ª©¹‚H5Ð0–ƒ—H+î@t%©/ÏLŒb×âô3v¦»«@|‰ rú«0?Rl:Ï]t£eÑÖ]7GK](¿g ÿ0^&É‘ä8=AÝ!O ãëì¥n‘ÛÈûoû}®4EÐMÑÖeÕ-ANøø>²ARØHµÈ› ÔAEÂ䌣aMÒ*|1v
+5º1¾ ŒÔ%¦o§¢]Âo5Ò…8† 7yت¹gDZ’/Bz˜yqëäD3ßPöÒ48Å.WFn£X×YöúA¬ F’Ãÿ%‚6 ãS£äûêÉxä­¨#ì·¿ŠA#O‰8=bi0ç¼ Ä„¡ÂtÍ)8§ê/Gù¥8øËŽÊÂv=bEs¸Ë0…Þ?ªÝ3Œî³\þŽãƒQ HÔ‡…Í„C°-áÕYÜŽÒ䌅‰íÔzü\*‡’XÏžq‘Œ°]'=‡‚².TöH u“àƒ¼ƒMºD ·¼êÝ
+»cFùÝ„ƒ„ìSÀOãöÈÀ"J`ȪX[.ã&¶’mŸæK®G=ù‹ù4_ŠÀ@׈Å_‡+‹ÜW–ÏdÌiÆËábvXpÙCs%.ñ«Å$@\#xšá¸t¤ˆ~Zt˜³
+z9Z\Š œd…¹c ÃÄã–džN%€Ž¤±ˆ5ß}Gœ8Äþ+žÄ(§ôøOG(®äˆ4£‰#á%yñv-L…¿;›.KðMÌ?OEÌAT!;„'ñš¹8” Z·f
+PdMÀZ„¨{ýx˜®•t-T[ -¡ËN®4JšÄ „¼ÿÕçàÁ©£ÎiŠ>½Hü00
++ :ö]“'™ÁÐÓ
+ɶˢ¿q{Âk‚ª¾³9f­#!S¯> é¬)ßÉ㮨~à€°žXèqsœZ ÆÌZêãPôx§O{Òz¡ %}ñŸni¨Ñœµz; ™eÃ]Bô­èóTtìÎF¥hH¿¢ÊÏE§ã&ÎEæÙX+¿]ôÚóC žŠïôéßâL' ÚËúéúOEâ!|ï‚o«”r_ŸæXÂ¥N¶xŠt³Y1$À
+K·<<íÔ´h ÓWò@Í*—KE ¬…«©PáEäˆòÀÚóùíeÙ&y{ò,tZêITB‚è᫪b™r, +Ò£B¦
+ýÆã.U.
+¡[â×CBƒ)2®-UúKNšL«4³rí¾²M…‘VÚ¥º‹ÿ=ùOµîOŸ
+‹(Úá%•©Hí÷f_Š˜:)Ü$›Å$óô¯ˆRLpk1ôíÊW¤º[\ô¦NO»pñçð|1!« E¶iÊyõ´pOE§ ÎjÊÇ¢À™!À õdž‹v³.Üd¥z”È t‰°\-%øS€ ýçUƒJä`å¸+·ö&((X‘G¼ ×tûŒ/UT`Œà‰&¡®!*S_ àÏ(‘y©¬­{²§Œ²aöR$[™6b†?ü¥f} Ùà"4:¤¹0.œÀ‘ƒ‘Y0š h´¼"Ó¸fÖ“gE„׸†æJ8¼ö«)ÚµòŽgJ·
+tUˆ¸A
+.˜¤ó‘á‚Ÿ¨EÄW‚UÒÞ‘›ªC”9„­ ÇÇÒE§9N‘õÈFmƇ„I=H"2GÁò0äŸ!Žoéi;ú®í|€ì›Š’Ogs½ŸcÛ$Û¤©!]¬ ®+çÃe20E¥÷wóêc´’‡¸§ì•¨ïNVUÑÔü–W–‚ð% Kñ‹9†µ†ÜzñQ§¿ ‹ÞUcoçˆHDýFRUóv>d\'Ün™ŒwáÂH†ÈÖ
+§”1¨J ³y?E÷,çZeÇEr¿Ñç)v^Îäã75K'61IVþ÷f¥Î$‰N(J¨“Î"~eÛHLN‚Ãù Qîý†+5Í,´~SÌÕ[<¼È Fš
+]Dz‘Yå›;?S5Ý‘qï[+©ñóúå xLJec¼rÀT°²¶P
+½ôF¥Jl?šöröÚ÷AÀ¥¨¯®[r-H*tÐnãùþ:ýés"B0 hÿØ攆Qµ¢Úó¬¹+š YHÃ3ûôî ‰!ÃyæuñY01Õ–þõMÍ@ 1McFxÂ(`0 ßãÒ ®å,4zsK_KxqîGO”mÖ`C Ø|~S™¡P%1V—…†^@²ˆ Oe}\õ
+Æ,Rb´±0€šhÂIoý…ŸÍr©6­ÛëÇŸ„Œw)
+]@0®øEšÃ@Â=,©ÂZ/ 2è†Ù¹ê4䬘ÌA›ÍÏIRgöyî´É¢'L uîìvõWQ:Ù¸fàãñ~HŠæþÍoš²~Z©Ã}ô}Š“É(Î3Ìá0ZQúyÁE_⸋UYQ¼¬3E4ÞŠ £#È(ÿ$t¶ õQ/ })µì²ÃÆÊ´!xDƆÐQbý¥LYI Í~…4q& ÖÂùí¶Ý@<‚‘BÎè“Ÿ£\•”¶NâÁ.Còr)®
+÷‡h­š"L&q å¦EØ\/>|ÎZÇ‹ò.ò”oíù=uâFF_µË-Þ3 F!!¦‚e/ADù[Æ c&1¿üùü×PÖè;=‚¢óLuñ$ùòZó}…ê§<•aJS~[ѱb‰%愇 Œ°ýÑü"Çeç2¹iú#û¶²w^Q
+â½(S¸iþ³eEËf7ûAúÃW꘶>®ú š(U¦ŒËzöOV×qñΨ²Ü LD
+u1iÙ¨—FüþF³>†‚BaÒ³4,¿°îÏ +ç?Mä…óÕ=KìÎùIa+S'ŠF K¦
+¶íݹÿÜÄ ü‰Ý©šL•ÁxõøàÂ:²_xÒ£bŒZ"Ýé ù[vÍ`
+U¹¡SÕ£ì52ê˜AÞ@úÆl¥ù)Î
+9Ò¸ªFÌ`,{;|BЀ®.ŠÎEŸA"êÓ®1zœƒï̈¹Â ù§bŒhñ1°?66íÉÀ—S¶• b=[Î%}[!ºˆ£R°`‹${”èîM—o4ù
+dx·V“TC6¨0v9jª<™"jT¨!sÌÜñ£·¿n t")#Q»Li÷G×-§Œ7ßÿ”#±äø"ÃÆ%‘ù˜þ² Hk³¨[¡™?6„ŒØ›¨·ùÛ³Öš·mŸ¢(æPXJí±ŽY`Âz÷Îò·=TøO¿Içf‘\—uôs0cRÁ’:D’‰U‚ ¥_7þmÏÇ\?!NAYnón$‘çLXùŸˆ%cõ k‰$Wµl*ÕZÓxØÙC4H|D´’‡Æð!
+2à‘Å¢½_,ô¾ŠÄÉDuéâÑÒM-IŽÓöU9Ä A"ZeE¦Ù¶µŸ(`îºæ½-S
+î~Qã/Kc*²Ž¬[ñ.HªUý”LgLëHGQ´$7Dcnx™•™lç¢ÏNÀðÇ–ý|gOTg8+3Ô,=/bñ)K> 'œóX„+±~t×NíÚþ]’<mŒmÝ-cx ´w¸(ê.ÓH?–XYJ¹û˜r²_˜ï äÌßÊ0—½â—c˜"ª¹‰}E¤
+3‘ùÀ,‡°4„‘öÑd{úÀ„'5ÖoZŒ½ÜúPôr ‹É]Mžr/޽ȅ˜Ž Ò,jÖ<.GÒšrøò²ø~-eiX↕=NvŒ·kì8úÇfc¤uetÆ,œ‡.EÿáÖ6_@>åš·ØÚ–k¥ye¶ èý¹K"
+tªÅjë¡U»LCP{rKÍfHªf~뇵 #LAŸÍ>z ñ¢nÐH¸2àÅv4?†ÑÇ:Ëõ¢á0ä“(k‹©a‰qW+åz웆T˜ùœ2H÷sÆOì66?þOÄ-KgsŒðTŽ„óÏ×Lý¤:mعŠFq5)ÉÉÕT?‡O¥ð·º¢ 6Ê­—^¹B0Çù\õšD™Tøb„ÊÏOO‰×:v”NMI«øhC¨øŽ©‡×„oë’¾Ò«s½†¨yéáY¥µ,ôçàæºÂT=ç[¦&Ò#Ø¥ØÚ‰(`"™¦âW!²æä$*Šm§»LOiYSÊ“Ýœˆ…¥»V;·Åfª jÇHf Só=VÎâ^çèFÇÐc³ªÖêºU¸M´šM]6Öu7%—0*3Ac,vüšòrËcúìÔF˜ÍŠˆ‘*!‡lc2; àÜò„QÍ)—×OñFá¥"çÑÃ2‡x¤%J?ºŒ‹”ÁŸ‘ÅÙI´BQù”‚‰åîuœ‘@®ºZ¾ŸC{qhÆ0Žp­T…
+c²ÿÿ
+•ã(Ù;æ7™ù‡ pD „èR†ÇAôÖvôr~Ò؃,E-áÄåæñPcÄ”³bÐZ’&í‰
+ᜪŒ-ÒNÙågp"¨#ïØ<išø<<üt¼.#c%߃¹ÝWbN`ú% L·¿*T>’-Û\ϲè£äà P— v§(reX˜%ƒA<Lä
+rŠÓa* Ë.©ÁCe\
+8ˤ:V,"ØôÛ !‹’Ž1ˆq¿]=Ь3l:ã†)8t–‘×ÙGpÇÉì:ðƒ ‘;ÈW¶ÙõñÊÖ±z„•­¢é8Z1Ï,*M×(ÓÖ’›°2§²fØU(Œ†ê¡~a[#´kO­ý¸ðÌpch²Ø§îý›¡™†]ã$öb`øMõÒúµµ›ÆFùÔï°:çb˜ü<ñ@r¨k(Ç°ËààÑòâ£Ebü=/Ç<<sòoÛ|†f@Cc»Èü cÄè¢!ÓK˜˜ÎL' è먮tWJ<„2ç35?„ø$OühÆ„%¯ç
+¦RšÜ†gÕqæP€¡4êäÎRËÙ)Ì#èÃló /Éô…î%ÖzGcPr; U—NœÅ'FŸäïÆÓ$^)w¤T⫤ár"’[J,‚ß-ˆæ:j7õ Gþ®žÊXQ®¥<£¡Wžžq¥ºB
+õ¡ŸiØØDÑ£hŽ@c«I’šF'þóÌè¾Þ}[!¤Š`´K:_´Æ‚ÕþlŒ¡þÌ‹{«ùxNžwŠ7º°1Ò‘T²ÊŠ\ìÕB®ÜDLX#ÉŠmýHq,CŠMàYÜD`¡Â¯ò½õ2î‚ •SÖ_ƒÀFvHÀ¼¦øÄÐk¬`°´O¦oZRj˜•GIÅ&%a™#‹`/ï!ô¹È>KÑv—*ˆvªH܃˜a½(©y³>°ã™=U<1ýäÄ).œ§ uè°7)(j8ŸÇ˜žM©%{ ÝÌ(^¸(m”ÍU!»ä jM@kWv@1ØöÉRGMPS¶µs˜™ÎE*Zr¥†tªiV©“d!‚¶X®MaÌ=K “Ó2ª¼"VðmôCЧq=c=à1×Õ/Qy8)YêØŠy¢PÆÖôÌ$#|°Vï W¨<MOgh™e-ja-ƒ pë
+ÀÜ\Bí|^®ÖMg^Ùn„;ió¡tÒ®±@„’¡Êc3SEpÐL6€ ð÷VLZtî…nOz9®sð%}
+2p1U°:KÖÅ°˜«òEŠ?£BNn¸‚h!N!©yAF)V’ö1š¡&›Ìÿ$é\ÌdT]RGéŒA7Ÿ Ý¿¥ë—Íøã•õi[6“ÇèEëfæ­õnŠÓ{ó½§ Qÿ"ücä(ª,R*ìY¯!RÇE ¤“”/ÔQVU†pwô4åÉô´%Ï#Ú5ÓˆÂfÇ
+6Á’-Èå¦åÛé¥ \éQ¢øÛºFD\yµA’C0J±×¼L__ s| Ñ2ˆxyÁž® ¶uƒŒ…E…p3 ;ˆ ®þäýíDFõ¡‰¤K ª©/ªçQj^œAFlFŸBXš•÷è‰Kf!wfêÆ ¥ò 5–Šì Cð3
+XÒê<‰€²hpó—6<vÝÚ©ÀD—í6¿„üx=ÚOÿk#Ô}¯7V!s1bÒ ´­4ëYŸý
+üùoÿ¾I)q½h` û¡¡ÿÜÊ헷ȲNUÎÃÀ½¡³Sj¬Ñ§B-
+®—¤«»A§ ÉSÇ"Bb5~¼MÝ] ^ÙY o× ã¯+ÇtÊ’ògžU?üFüÏ·@–‘¬bPZI¢Ii C7èkks(«ö•Vwú˜
+ÉpôóqˆiCÎMn]<ÒŠ¹\öôùÊ‹ŒIþò¯·ŸþàÿöÏo|±M(YÌ~N‹æ †Žúf9®L®18IGáZš¥‚þ
+ÐoƒËrü?‚„nŠ )–ðéºïƒ´Æå«Ð3¨íÅbÇ *Ä$46 ¤e!S°BäïÉøªôè€QH’=§d d#Í–òXA ;*ŸõèAIƒM‡˜¿hçÀ¹Œú@ö~C­bVÁë
+I@ª¨"’kˆ_¡¬
+†â0iIפØTrÍèøä2² ‚y…h8PBó**wérî!´b«…$j‹Ë€Æ$Siv@†AãæTbCÎB0L~¸!â:?9/DÑ*€_“Óîˆý!þÖp¢áÓ)ì]¼Œæòtd*óïØžŸ4>N¬4¿4ÔŸŸÖ[Ýò^—&ý~s1 —Ë\¨îë^n"ç@ç˜Ò[v_c+¿ž±Måþý¢Keº"dÑ1”›¼òv~€¦ ¢E·KÈþÔ¥ÙÞ9Êx·¹PÏ{ÕÂ÷ê8Ãr­ñwóô¾ÆŽVXÇf49m•¤žE™6Y>c7ôl-kµ9 ?=+×Ï]A?¹ÓV ¹‹
+BšòŽú{c:.Á¯çi€J¡C¤èNp^ßKl¸!+f}ƒÐå(×R
+ÿ5!=©ž:œ¤Á˜´cÖ6{›iõÖ@…î@fo•~Yµ"?CÖ¡ñú-»xcï2ú¾˜Fj&¢Þ,9B%¢z«åp}ªèé²E„þñ²Xáe=ÿ2†±ÂÄN¦K2–Ì%#úçÔOÂ'ÔÃý)T‡&·@ED÷ÀjZË {MSNÔ|.¼<&ri,ýC‹éz‘)»Y,º‹ˆJpSßWN=ZµÈ /ˆÒ®K3û«Ì(€jƒÜî—QUH‰ÿO»Fˆ±?a⪖DÉÊ”×9¸fÀ8˜íìôÇöbCÈ*Ì
+/r%"Q¨ú1¿«ÂßA^XXº†³ÕöèÚw£ñè"ò‚0×ÚlJò H‘¢ŒÖF¨Oí” %~oWC1³)Z"¤~™Y
+ê òôS·P&6
+ü€d–Ê8ïþZ>@ÄñNÔ­qçÂk’–#…†&‡-®N^ þlÝÏZ|ƒbªï߆g"\\…¹)O¯‚éÄ]¶
+XÚýâÜæE¶©E¢öHòm´j$tü÷O†sm'9b¿ˆò·dŽIÌ&¢D¨Dlb}'tšV†¨± ˜4ù ·Ìu#ðM"é\Væ­É`$t0@å÷uë\=zV[r@.(½¢"Lˆô+öU"ÚÀu :» Mìa¿d‡¨u߇ÇtÖ #Øe³–TCTÇ®ax©SƒÇ#”»#ÕlKÞüK£3G<e¦.š9Fy ! ¦qªaù„{õ%e,f“ ’!F†y‚‰yٻéMÂZHÒôÂÒ"! ¹Ù²PYÛ­Ê%Ê‚$Ÿë*¥OàܦÏÙtYöB³ ¡×¤>Hž·Z˜VˆÀŠUVV»ƒ¨9
+Q?_ί2ë8òFE¡h`iìéT5^ä±=–ia¤Æ´Ú  wfü7¤’°GQå|Šá”]ScÃð“8!íÜÍj=c©ð4{¾øë|Çaÿøaù_½ýñ¿7æÅ¡ü¢8š:Â9`P`ý1 =üá¿oDûþâ/¹"“iÎQäòßAüƒˆ2ftÛN'¨d)„Ê“¯ªˆ„RGÖ|ýùð¹ïA3 ðס¼G?@Ì)ªK˜kò‚ð'yE©»“Ì ÿ@­‘7$åP 6úÎ%‡$Z2÷™‰¡¾A2ö1† ÎfšÖ1:V‹m_f’\¾ûB”XqhiwÀþL)ËΩ>RQ|STXF— (K•];]$ä€äK Þ½F)“àù¬‹¢a>å­ÚIiŠ}Fã€åƨm0ï'qa¥{ ©8f]¤Òêe’ýî@xwø)<‡ö"#[ÕØ–£
+´_Ù7-H‹!³Îd“·Õ3øQv‰Û !WØí œZMnÃûZ^çÐ\’4
+–vK”¦”©l/ü|s@.Ó«¼ÝÁûÚãÌ8 ûô9Ÿûè¢î`]A3ö“¯ØíHT6Ùá"nEù%Ñc©‹) InJÃMˆÁ*Ô–!ûœ.Î ™%+¤Áºh(uÙCª†cç®ÎÝNÿð×ù+€dË>f$Œ‰>SâÝ6¥Ñkœ63!òDv.ȸc«fBöÞG]­/ò%ö!›úØ ¬Mس¬‹õ
+öË0YÃÂÊçË!RMµŸqŽ`drfy×øÿŒ—K®1 EWÀz­üŒaÈRûŸrnâ´è®0@H-¿Jb_ßf€üñyÁ.Ó<-j‘ß,X0êü™‚/«AÔ)ì€Q )…q[^%A HÑ ½‚´Ñ 9úyRVG‡ÅI>ñ&ßÍÒÅÇ,iò n™VüÓœKn•Pr²ïé¥i-2Õu÷•8Ô$(+F¶oõ8ܘý³¸Ñ´˜ýôò8ýŠ±°–¥Ýã÷ÊÓƒÐÆ÷S{\Çp ×i†ŠZÈD½ŠwèwßÁŸ°¤û£ò#ÊG¾Q)¶½@-¶‡åG5ùÍ Æ®;[µIÍ]Ì¡þ¾/a^7…¤öÇiëäYꄽ5ÌËþ~}yQ¬ˆŸ¡Çnmá"ÆšÿÖÃé."‹n//•w ˜O¤§ß¡{nI¯ò’ — Hûá
+ÆôË×Mx̬èè-úaÌJi[²ñ-I TD:B¯Åþ»‚ & «²ö}?}2A˸3
+ÆÑèíèàx™ ˆ¬>Óf é·ÓúûÔ°bq}/å“*;@’ ¾È(·³t3ÈË4Ìœ·tœØ±Ã*ê
+,˜q±Ä"w+–oY¼µ]€¤
+·Évþ
+oÚòâ‹þmám´êU³P} ÝáêFó"È«b2 ¿³¾I#Ê–u•°…ÈJ„ɳ¤cöq®<–Ì£ú$á™`Šwß¡éD^ßÏ—é0˜¤ÁúÝ£úSž±§Úν¡¢vˆ›Ñ¦tîð¡ämRû¤÷"CF¶¬ØÇãpƒ<8#ãFЕ㛠šD:ˆdÙöIï­1ðU„OB•ÿ>ô— AÓrÅóœ>Jó¾~ç‚š?nó[€
+H‰Œ—Ar›¹„O;è£"H‚Ö™en‘ª·²ï¿?AM,QoœTR‰Ü"A Ñhè°›T÷{-ZÅ}4o·¿ºÌûT•f&ÓF½ýþ±@£©«.²@ÖFéRªêÔ<ÇÛè͵v_¯V«zéªv„ؽ´®M‡v>½ýüñ¿ãe~/sZák¦}Ü>O Úî:¤MïÝz¿}1
+™!_óRgkH>½¹óô9g•wçô9¥”â=“Ì«¦×á}V[ˆ•ª x¸ÊÉ‘mÛˆš7‘àbÞÉõÂpih]û:fȬ<JM|A(oõÞ¬Ô:Þ@”ô’;QÓ⯘gÙõ úl¾ýÐyÒ^»qÅU²r7£1¦õìø|ê¢
+Q•ã®›äÍ„vÞ|AŠiëEÍ©w@Æhfá`ºaEqɇ‹+‘ãNÙáO¡53ôᤠ’ʲÎQx2û,änA:;}2{•!n‡à;_ ×Uz§ætf§Ôó|Žr9o%² s’ƒZg„½ Ê-6úÔY×Ã¥q¨4àcUíTï°}ðJþ?eUíù2@d"6r¼¸!;”h¦yÌ¥,ÎÖó弊b}ÆDæ8Š"VÇ(ãÝ1´¤Mþ¯]¤ÃpTb4Ë*Ð$SŹ(c©D è¸Ý°BÅ}âTz4#Â"Þn'n }!£!–|UÞ@øБ+éeW󿈜/›ó“Ƥש¥æy¼‚˜>7ç_@qžLApÇXq Bp)Ì‚)I
+ÍÚÌW¹Âv‹ì$BEGG\ziÉþ²:ƃñ=èNe‚Æ(£-šTm”PçU›ÑÔ‹|ÄôæÂ"2„€~ì{ ^˜ X
+%û» g§Õa~
+,¼â‹+ÓÁêI¾Bü–¼–?¦ƒ’C1ž!YŒ¯E=œóLˆf@rúIrj<S yŸná‘ö$|¦ê%dè.Æçv;¾ÜkH¯S\—7Ò€RW0)¿¿Ó] ¹‡“õ® fw›†Ó¨riŸø¤’Lò%¯BÅA%êb5Ý«ZÉ39‹ŒòxCŒ¶† N4¦Ç<R;ªßêXŒòžÔç¹èžuŠ´ JRg ßÖë&ˆn•À#è‚´.ŒòoUàÜÆ0«×„`¥˜¸üÊTó¸p«_@OÂøñúKL»ö ¤C—r‘sn@Eí0IˆtFñ°f‹dÞð3ôCÚÎ1šLX¦w‚F¤8z¾Í•@¬S«Œ#Z8ÛtÃâŠ92Ç¥r&F¬÷$obNâ=§ë»s¾ü5˜gÞßô¿×ܼ°ø%ÁÄ—:ýþNÇü1åʵ?(ùXöÏ3÷qÇÖ1VTR‚¦#š)Mƒ ¼ão2EÍBì‡Ôíë¾Èê|„Ñeúlг¬R t° Ú}lkû$‡‡º¿Ê*  è,Û×=Ÿ™ù+äôïhà„Øÿú‚
+Vf†‰ÌWE| GT[v“Ø–ÖÊt‰¯®ý¢ÇÉp„w–¢:G‹Ý
+#ÑѱÍÖ
+ퟅê>ÎV¿`žÊþñd×ÖIË–ÑÖ£¨K@zñt~|C(ë~·„Æn»=4øN³ýnÀ6;"mGò°­Ra“Ôã ï³ÓxQÊ“cÊž„Vªúù¸Å£!hy(%´F<x™õR>ۆɡÉÜæ¨÷Y5æ˜éçbúÅÉQßÕ0Ü
+„ r»BÒ¾Öo‡žâj,>$![I›ÿhÍkBÒr¸IƒZ£ŽÓ÷™˜YQ¯¾›óÅÐ
+­?OÍï2‹%°àokl
+zy¸DH¾OÁ9‡k“¾ØW)ã³…yغÍÀ`ÿ¬h¡&;G[ô…g† Ý€û»òP‡]ƒ?§ìÏ'Щäáñ£r(œÛwAÏý÷ñý×ëZø'šÛ0e/M}ÖP— Ÿ CûÌk?t{Å\ƵŒ.Ù¾± ø!µ²
+V)Žbøµžô³uEv}AÞ ;4_õx!²ñ\b¡ôL5AÓûô.C LŽp¿ÆÊÒ  YyÀ {ò2^9q’-fw@Â~Jh-Nv,ó•ŸzGkPk”Ë3#TB†Ú:ç
+™WöUŒ²VQ:´m¾Ð9%æ?V©î«ž@¸|^\:5ω’z=ä8´#`²ó®×o=l"AŸÉ¾*–H]˜{»qdÌø=WñËÌ^ïú†€ÿ—Æ?þ“ÊÃ1¥;̃žšì3Aä¥0•sº¿Œî€ÐæpYÍ åÀk@5M²R¡ïÆcoÃ&#¬x{¤s“ž9‰«¥Úö,ÊÌÏæ _Oïæè5€ ß±Ùª­Ö9x–(5&\‰yu<‡´ÙjÛ¹!0”&ñú± A œ8î2{ƒ0ƒª4î«8”w(2¹Ÿþ§]» ÅâßP¸'ðn\[c™Gˆ\e(‘Ñ›âáÃEˆÉT: ï
+|o'˜7´í§ò ò%›¢~ò‚Ò÷Gþè×`2¥ å±.…gñlõ@ÌOšfÞƒ/‹±3R P=Ž‰]é€8«Óè×PE™:8e_âôŒ‰áoÞh8¹VŒaò
+Š¼g` Sƒ…Ü/]FgèÃ!Tl¢05­´q¨Š¯Ç=çLŠ“:çÓÙ@TÃfíìëæjÊ´mÝÖñOH^E÷Ä®PPÞwçÃLÆÌÚ–7@3G÷I–ÜcJ³D¶ ¡EcÇñè˜â„ Ô,CYISÑ2xÛØAgäpý!¤ o. ±J^qø9€>N «œ<éÑ G“QnÙ£Ÿ6…,Uk60?«¡wsW
+kÅ:ȤÓÇË‘~RʬÛ×Øf"ç=ß…a–˜Þ’\1D‚X”ŒÆ0KH ËTžry# ùû`З
+[2†'--(ÓÈÀ¢¬ºõìàÛÕÁKMõÝ&
+Îì]¥Ã´õÿ‚ †™yõŽô;a–;ß繃>KìÇ+:,úýOTû·¿¾}ÿ‡¿íÏß|·²J´]³‡Ë’-ZLƒ‰. 4Ð9šQÌ` .‹d÷(CÄmÕ§"0|Ë»‰”Kš¨áDÝ\²u‡¨Ö€XC>µ•Ü×é°¾'©M†oEi`šÝ ”@Ãs‡ +XIÑw1cùî2uø­º:/É2”dë0ÿR^HG4‰¶Âú¢g½Ÿ„)ÑgÓ‹xÃ4D”2ƒSì[¤ÇÓ¯­™{ „­Æ!¢¬E,¿ºáÂÒ'D*d/¿GÑ|±ÿλA5½NDF˜Y60"IØ ´IM œ.Æ®n
+SÁëÝ׉=¿“'³Cp”¶¡¿Ý»&G¦æËõ
+^bÙ«?-çC ¢‚
+諲'æªD·Zž”è:
+÷eè+\”d§M‡À¤4xr¬£öœzt
+8¢/¢ÉÍÁä¸û“ƒt>‚O]­È`Œ*:ÓÇx;ÍŠR*}#ï×çH—*Ä&÷`^¦÷úxª’\Íë£þ,<Qr`h«\:g%ÊŒ2nÒ ûEM™?2-P¬Fé[Fò"EW[‡×…µ–×pš:+í†\{=³|fî±Êgˆo%«?Ô­¹­Û1g¹žžUÌPrôZoE³As¯ƒÅZÐ 8dïÒÄ 5+>2`ÜoêïGÏÐl]soT j¦nõ¼4D“æBU¡ «ç$Û€SgBòͲ¾ˆNà 3G.È[Õ‡Fc†¯ ¹—cDoíÔ…áô•«¢ë†Á‡¦Èâ8ñ´°HO`E_†g(ªTÙv03¹L)¥ñT7=ž8H!•:íN|0H™?XÏ–áôbÉ0ËI_ÍßM]#­3¨ ’ö gHžgÅp6SW@j.,òhn'™p1"X!"òňò¥0wp …$Å[‡Ž?  c#sœig±ŒHÖxê£E¯Àx8$÷¼ŽFKUsØÖ B§ˆMqºq%;··AÏ™(ðH[". “!ÒMKM“a_±>”þ ëª³Ó„«Wªâ¦Fx!Råà«{H!#úp?‹C¨&ÔM±â¶ö\ÙhØýˆì â:Ÿ±SbŽ™àYóx°ÓÅœFe8jŒÛL'ÿúî­A%ô{1ñ;­ƒ}™š
+~üÈËÓ<-gƒP‡†á"}+òYåy(UÿýÛ t*E€G·‚†›p½ºÌÅÇ+óìÛ@ëàB“;¡s»åÌÓh.¸Àº–<. Ìx’Úv–”ˆþhU¾Ð –21Óu¯‚ùë¸Ë´¨.Uådœd>Fé*®>D¼Å3„¾!ºYêU^Ë ()®R­ÛTSú%©wVQî ‹ûi LÝâÄ#@þˆƒÁ84+ï´ j tÛs"a&†,9Ôÿc£à¯¸m~¥çhtR5’4dÖ‹ò®›C=Ô…;¬ÃÖ! òh…wv‚€ÛÅ×ãTŽ‹Uõ­n tš‘®ª³o5S%Îm>kŒ_7˜ø>ì^ì ) £yb5ïEn¥ÎQÆ1Y¨®˜½ÐkMÉ%á€n‰
+qÃ!¸^\°8Ê%zL5çÝŠË_ã’CK‚ʇ Þg: Ý­CÌý‰!-MÜC£Ì(ÖÑ'Ïâ[-Ÿ—”tAO_èÒ 6u!H[>Ƕ’óå=é†Þ]ámæ'ã.WÅÚú@Î…vñŠ) )oÄ%™'H د€ª÷ôØé¢U‡l7\’£oÅÓaÑ6S y)ô:(é„h—Š<9½BÛEƒÐ"ˆ*j0Üýbpèÿιo s™—Yë±á1á3ÎD1‰Ž»–ƒþ—«ñ
+…)xè$gûß]Cç8DÖókͪ0Å£¬©
+úÄš¡ñðñ!`˜ÒI‹\¶B$ô–ÁÙè<$ØçÝ°ŽË»JšÌOV_¾801f~/FV #1¬-|ÜŠ” q= ï9{-zÅ¢ŽL×ñUó”`2 R¨"Ž«K(a‹z÷ ™Å`<aª¯¤¦lÎ 8]RÈïì{éü+‹²iÈ£0Þ®Ïs`!…©§ó6ÆfÖüÁuøÂxN rùÍÁKî28á R¸EøØLø»µ½Ž+‰µ).%Ƶ-‹¢B{ÑPòðS´+›˜Æö—"L*ž‹X 5jkÚ__ø›E¼U“AÀ½µ ‹KO*ŠHß6A†ÂöN€@v¶¬A—
+¨ÒÁÇ™&H°ÙAF$ãD¡;†Ö+‚„½ŽÝÃÄÌÈ-)/çî§êøÍ<åKIà¼9\CÇÚ»uÄöŸ Ùû4Xæ ízTØŠf¶„¥K=p˜R;[9<rþŒ9äÐÄ͹îu
+æ‘¿Ÿuxfˆ~¥^¯ä}%H&²õ2ðxóA•f4²ñ€Ÿ»(cªxQ¤M_Œ0¸¬ò…qÈÌ”iÆ-"~ƒKE»´}Ç?qjw/2Hœ1Ér.Êõ:f®Òœ“Ãghí’ª¾¡:>øƒ¹œß,ïŠ:VÞ”¼øO½:…UT'ã.6í]<‹vÁŽšñwÛAê=Ñ((«ú¥èó;Oðǽ¸ :Ì]õJÌlãe±hû±  €P‘ž™ókͪÀ».dÀâ@…Ö´²K7u
+ð´›“Ç&®ðò{ïÄ#j#¾€’*òNÞû^g2þhz¸IÇÜÊ:YÓ€-¼ìÿËõþ¸(ð~\´î×®B+Y®û¥ès•Ú€£‘ýRD‰ŒÜOn›[›‰&Š2œÙ…÷UM%o=Õr ˆÀÙæ0#ÇIq~ ÐÊž#Jx
+r†¤mWàfH[rJ‹A^*H/ºÎEšû<—ðƒ¼íJgµÓKÀ¬»llÙ%šè*WROÇÿö±“ôš!iäƒ& %™Üxf‚Ǭëwøý+ˆÿø1ǃ€bœ¬Ý|}à}™ÍÚ § šŒâƒ]ÔÈ< f82š5[Ü µœ‹g‹
+(qEK?Cƒ>‘ry±”ÞÅ® ë[‡ýD«éŒÄÁP$éõÕbˆÐ5hÁ ÐKÉ,&wžv0x]§¬­Lº{J2§K¥Œ¾Ý1%,1å•¡ê¸78@uÉrVÏVt> ‡Ø&X[eŒ
+kš |È7¿%T7êþ¦$K>xΆ¦ï­^ŠìÃÁ±&ÖqšûÈ\ I2Ǻ$PÜ•›f€¹Ê¿3Š1¿Ù5¼| ‹ñ˜À„QÁ8E’a˜ò¡Œ’§ŠµÝ`¸ˆ’2,LÛaÒÌÚD;–7<•Ü™é©è×›"ÈðÅ<vˆé¥†QçÄÍ-ÐEkÕ—šÃA2{ [‚p1ä2É°lØYV¨€›¿´ö
+’:ì ^W×hi]P%œŽ/¡ Á'lãÐ<°nA/EØ!±†ˆ ä\ŠºE)Ü›!2´“‡ÏáàЪé]LšâÈHì’9Bf²˜‰—0Çq^j¾èëçwDxÙÓÚ‡$(-‰ŒWdí…ç‰÷“V÷)û‹õeü/[˜sº……èùÚvJx‡QÕH'7øOŒ…•Ú©&gžÓuXs[Ñàïéâèí&±—0‹iÅ¡‚§¢[T Jö¥”ûüí"HZâíPe»—"ô³?D÷µ*íbtÚÑ,IžéßØN/á
+2Кò!fÞ’©æb}œDue1Å5Á¹ÈßÁ,rk„4Yâ ©Î]ˆ ø†—KÉï Š†ŽÐ`r+Z%83dמƒxà;%µl¯#ha æòÜ
+{G"N™¢Œš_lµ¶gg08âRØšÿQ^&éuäH >AÝA'xça­^ú(O÷ßö2˜.%™.¹wµ %É€h %ÔåDF'aòljéqX‰ˆµ7bì CÏaÌ$ t°=-š;ÈQ/”š@]o t;îzÿdDm’áy+ÅSéãbû514·ƒ‹¡4ó=Al¤8Ûm˜£vÅ“‘°Š²ê—àÐ:ë>îIS‡ °¹'·(l<lT^NÚ¾ƒˆÆ1h}<Ì»
+Ö,¶«ÎA¹®¦˜Ä¢ÅÔšNLäNyy=Š¼ŸäC,!‹<)kÅÓŠfõ ø?vÕRz`àyü ãÝd¼‘'%Rì1'Wý2vˆî$—zÅc–ØÜqÄj,Ki¸Sêv"CÂoÐåž Á' ³!5«aÅY߈·Î_”'—$Þ¯“¼‡Lžš¬érÌKÞ®¢,“ N\gŠ¯{%Ê
+Àd‘§SiT|:~‡®S¿,ônG!ù¨1ÛáTV Lz&'~jφ%®jMq±g¨"Y\Šû;¿†
+3p{UÏRr4®]G9hÐÄmk_‚ƒƒ•$Ú«ˆT
+‘kyE”›”Ð[Ï8\¥#tÜïÓˆ\à ì¯=@ï‡ËÜYþ¼ØJ!ˆ–h©ºê ˆ1´’ˤ«ÈÌ›\•)-²“WAe2³‹nã7Õ¤ ©áY`ä¿YÑëU&±ã
+G(0A{•÷–A (vˆÀjÆ6N«)’rŽïDm­õªéi €ÇÐ<rtlýü?6IîC¼°ïà¯d‡¢†„ÂâoÈz4Hb~"*ÉÏã:
+'E]C8î?M ôUûõ‰Ý´×Ñ×nŠ$Ò«´´‚SøQ‚çùÒŠˆ<TäK˜0¦¿t`é -:~äJ4ó$éFËU8UW£Å ,PÜ2gÂÞÐ(jU²øüçŒùæ®ïŸXðÜ4s¥öœ]smÝ®DyP.˜ŒÚ§$K À.ý7f ŠÖº„ Äóã  Œ‡žºÂiBÈW‚–s"ê«ÃsúÈO,§àW$’všþ D GEq½E"é,v}²è“u–³g⪙B¬ §™RÐØÚX¤ÊÜï˜÷Ä`“’ú`)Ö\JæA´ k<­Èû³›v-„‚}¯ž‡a‹ô³þ~6“×å!“ËtƒáoEŽ <[Y¬ç`±µòPrA£1G,Å·óg
+9šüÀ:HÍí.Œ.ub°s›JÍ8m‘†ÕVÓš2>OâgœÃ>[Ëš¢?s•r¼ eXäÆÒ¹eä€P{]bÐÈa³‘wLTV¢þ‰¤èÚläŽ_ˆë[žÞn+I/$vŒp~tHÉ|c+«¸·Ò¡Ä^–ˆ–©ç÷úoò¸·ñ ³bƒv°Î2+Nq‘Æl‰Cfa^%äóhoÜÄäk}……¬µÖ³nÕy”8žÂ˜Œå Äf­ cªÁ·9ÙÌy¶HÂE©8"¬‰¼Mí ô¶IQ¸¦k¹­DƪÓÿy‰=#l(:ayB-ái𼵈n“D¬
+~×8Ð=Ïžd¯<ã´)t«1u(ƒVWúž’NíÜÒ¬ å‘Y­ÊÃw yÑÓ²µÚÀ>ã¹·ïuBø'Ô”(NAÊŽ":í9|b‚uÇ»´ïš¤±ƒUÝ|BÀ3ÿQK͉çJéMŒlJM³ˆáͬ˜üÛ;”ûý
+9Ê»1¥™¤Kl2EÄ#‹A¸`¢hmZfá$U† -D¿ ”LJ¥"U°[ Q†,´¡+kÖú ‡ì¥êƒIòB_;1‹ tãÚ@Øàk-­“Š‹†¤™}8mŠ"Gµ—ð¸ á’Ð0;ÏpÓ› Å³L ›Ý'H¢ú,¿eàr­ÌVxÌŒêÕUæ?uôwß›,Zñ{ ºI«ÕPWão .È]0#ÒD­ó´ª×¶Aoª͹7 A¨ “!é4ÍÐ ¡Ãæìé …bá@ ý
+É,ž
+žüÇé.Ì#b×ÆÒãñM@¼ƒ‡®âTiu« SIHttö¦[}ÝKÍgŸKÝ—tlÓ ²ñ½Û§ïÜ8³]f£ÞéMƒñQ|Er_?Îsà~Á°y©òÓç5t.ðpä¦åƒrY?3.æ '=@¿Ž ƒ^ìÇÝ@ïŸÜÉô"bDH:ÿiá4¾ Ä@¤ I™‰ØA‡úÆË%ÉŽ\‡¡+è=x7ô¥¤±{Ø»ð´¼ÿièsíÊdÚñ:âùVJ$€ÂÚr&@b–Cµ¶jýÈAQ¶L2Φ%ôöõôbIál–$Hº øR€ö|ÀƒÌÞÖ¿$#\Á&ÿb‰<ÒÏÚBþãë_̶¤@L²±¢'¸fx@d¹²8Šž‡ÙZA#†ù—±‘d°æv~}zT#˜|Ð
+óáŸÓˆ%FfY³²ú`kS¯¶!ɬ‘V ÿ
+¡ÄQ~àp¾>Mðò¨Ø˜çÁÂÖXìË <™Qp%òuZÌp@°BûHoµÅumþVù‰[í$/¹éyÍ3ÖPDm8dˆííe‰Â+…3/»ˆöê‘"D;ëòÇT ‰ô¯­S¨¯a˜–ÎVö©ëR¤N¨Rõ‰#ŸzÂÏA“LSRÌÜzÍ7!wé@ÈO~‘HKÿÅAù ů»61uœ´·uNËJJHUhΖ³ "Lc¯S•…¶²ÂŠ w×s¦À™ˆÃ;‰| ÄçxAë¸dCÚ>@èÝŒ÷¥¥dkèC![öë\^ò%NŽ÷ ³ˆ…OUÒ+ÄËýÊ´‡ Ìßi郫¡g䄱ÎúYsf"%r!®"Þ@^}x)Qíq¥/ƒ<¡ÿ›‚/¡Ï û£ßdžø¤ó¹i¦9Píñ ó€Re*!¥ìê<º—+ÚËâJYV Àédу¨iYÆ,#­õDìë9Ær0æê
+4>ã¯}¢=ñ#¼"QÐÐ}/ÒwR¶z[ÊUŸ‰z5á%DÏ—æ—X(5ݨ¢äŸ“P†›ëÂY_çi’«´÷|ÝtþòHFÈå6¬Zydâ ä鼺ê<aÙxf)ÌFóuž´Ìäp4SØŸt^»©þ]`ê¶^”^Y¸Ñwë5y2>!­à'\2ÅøÌŒŠwEF:ŸùºŸ“±.%ß·5]•>¬W Äq¯›Ò‹„ÏC놫ôl h—Á¥ä+=1 ³ñ$ôWŒÓsæ†Å†½€n¦¯ƒ÷@"{Sð'[»UF2ZƘÉá¨Ê­[€´K N˜ßu Ñ"¼5èQ]—BÚBöšâèüäÕ‡TG¯Špá)jÝAŽÎÿMÀ§ÌûWÈòbaT
+¥š+ &ÓT¢V]Zï€z" §)möÈHâG›¯ð=袵² $ šýò@xÊ(E$ƬOÉœšr…å2ˆN£ÙoÛþTËÌ‹ â@Y —áÝ%ζ˜õŠ@w1¿D¦‡u†§<ŸBB}XR—
+Oúaꔘ¨-‹Ô¹¹Ö¨k? |JÎR”W7 ¿Q”ô°Ÿ:}¿g1Fâ£9a§Úû19)«áÃçK¤†‹=IÄ^ìKA‘Nˆ2¨DŒëS†"1aËÙñÊ aǸZ?†mlc…jm4©üMλÀ<’=‚¥£×ß@—¾<€Æ`†šbÍj7Fí€4<u©
+§ ƒÐv¿Í㺾!M
+’uD+uûј«cÒ×: &\2zRÇ;æccÒP"fšöµ]5Ez}{Bl°PPõ§wbgh\
+.³'à´_ïF³"ª4ÆáÀ¢:ò.±|m#øù,½uÓc{D\+,Ö•Î /]×”Áò¾L‘T¹ö…ÈŠG€ú!iGð°’¤fóKDxäµå¯6)X\zk^&=* ÔŒU‡äÖ›ìÜ]»çŠŸw\GÑ
+•E:Yö§à©ì1ˆûSÔ!’É’Û‰¨,…ôX¹ ùlgûK7 ‚82ª¿Ž)ü¤¨©1ñ"4
++(°‘BwÓk%p—,¿?…šÑbnXN*«»¢°ÎaJ0'èdÅeà_xüý½Ò®>}U'lǦ@‡r—q(ÏjÅrÕs~’ƒ2ÙGÜDÄÆ1 ÒÇ”\!X•ªì$œ¹A´” }ñMùŒde¿ÜQ_"&2Oìgºð¬À‚¿øEe 8ÌC¤šÍàjX/“ùt¢‘™KÆådªQkÀ9¬[ °#¦“%ÑyÅ®ŠFäõ)8GÁUG®æ¬N›IIÁ¦F€=Q"keOì32Lý|êâxŒ—(+ŒuõMò/­
+MëÈTZŒÀñowÌcŠ¥­¹;%Xú Vuf"Gõ™?¢ÌÔþ0|† ÏŽ{d > UK^ÀX^C´™™¬ØCÑ°‹s“þ94‚"PåNiŠ·AÁ2Å¥û¼;õwL5³)qpŠñ`î³ÔÝI*‹%)RéêfJB&¬
+rÁ\M‡¸ä#´=ÍèãÄÖ£;óˆxè^â„cçxÖ6ë"µD˜PÓ+¦øÒdKçé LÔ¨2½(7ŽsÞ…n#:(Jß›ÿUMÄhïê .P+¦•hX4[fD âÛ
+ª…ãøÖ1ø¢:ó?åe’]G®Ñh^ûf¬jžÊûŸþ$øJz‰,¿_ÝqÙ!& "lqgððI~Š©©Ó s 'd‚#YnBỉÅ„w7DX‚íoÞ8 &AÑú‰î!{SKB8UÉ’”»2vA” €ÌBømèÊv 懿~½bŸ„§ò ã£ö°£Þ$jBi%Õå×#aAd,Úzž “D‘نŠ8MkÛþÂ{PÜD4ý“-‘ÿÂóæilà¦èŒ¸úˆè‘„8”<zÚçÐ)¤¤¦vÑÐTUyÎA¬/‘ôµ@h”oN‰ïµ‰ÌÉioâhL¶4› ÿ`ÐÑÉ•o>ˆHF¡øv¶–]0ì¼EzŸÑ¶Ç·¨î˘Gâ.òuæ©n `¨™íš×Îœ P8A5Ÿ`+b£€P{×O{ƒ¤±çâ[€62F­ÈlïœDžԧyãH—~{—yâó¨+ÿ.Ź²øRbèß;õû•‰ù|„a Œíˆp¨_ûãb2r‡·PW¶W»U^,NŠ
+~íûÕ`+Ë gÿÈ,gÖfǸ”;4‘¥lˆ=Tß³Süˆ! •Ì³?•àÛ£"Oyä+^„¦&hókAR"BK±â©0¯$qa¢!F#çXIÝh7¥Šl(oè©ï_7 ã—1®VéÆS‹ÓdLþb¡˜„È€oE®º ¢Ïj£ƒ00ÉÞîC« óÀëNò¬”Þj+
+lBöx„{Œ¨¥÷‘Üøµ»Ñ‰¢“x†¶Eꆎ¤â桨4xP­0Ì%©$œ@ÉÈû¥\l‡[qË„n4÷yž;)¿ÉZð†ÿœÍe‘Ì“Vdä£íMU®1_fdðÖ?.H, ™„È:C”ûÜ Â\†ó'²¼ú‘?o>÷HË'~ ÿÈQ{ñ@-0jö±„6ÉÒÃŽÏ"ÙÀ| }ihLÓœ´RÅÆøÑ–]íñwf:©"X _ö)‰øÄ`”Ý…–œéœÈð
+QáºéŠ°ïÐ"f‡çÍ)5"(’°s[¸³`”n§.
+ÍV`±Ëp*«s#’†^äzöDž¤‡
+#‰LÓ+ÔïÚð£šïÎQˆPNÅ yØ@è¦qÄtÒ4™Ú†œ+©Z åÐ"ÀœV)W?3Î.U%ËÑzIøB40eæbt+´ì³ˆ@/ÊZÛƒdm„('‹}mOH{ŸeÞ”¤–=Z‘'ʳ„aøø7!ýXy?°Ç %¤…8§ÌKo¡¨¥°<ÒkØ‚H!Ç o•yò®ò
+b]cQœ0Ê* WèF’)û\/Èöû¹2SÚàJ5zÈó‘‡h#¹ShBÝ<z‹9ð')­WŒÉ­ž8H{'«ä’LÄ.ÃÔ1ç…ÈTîÞ¶òÀÈ[¦l\M”Íλa 2È_!\¸.ÜžPJ,¶‹v~ϯÍt‚sÐƉÖBͳ¸>3Þ¹|b>G;Ôá}AbdžO˜z$Ø›†6¤ŒBã}ûK,D¸(³šÆ ¦^;Á0å}N"#-«°Ð¨´ùŠ@%y^(øŽæãÍ=iò× ˆ®H)#ÉvþònŒA ròœü‡£›Ô“ø•G;Ï~*ŸÌª“USf[h¿œ\ïÚJÏ9Ã;gV0ú|ãÀò‹*>Î
+ݧȑ\Af=ñ¤
+¡ÇM+rÀˆ®Fxw#°×ÏM.Âp{Žì Ñ-X¦?ÓºÂCû†Å³ÖZDÚŽžj¥Á*ûùTˆZhÚ¤J„Às‚¢b>2PG×ÞºE¡ª­튾N0uLM˜ýŒæ¨¬\ÁŒ3A±žÑ¼€$‘…¤[i¿*`䙜zv#ŒŽ.Ë)‘›£m•½†x,øg„¹¶ábwµMsWüíM
+[múø>=TÉå®AÇüÑ t¨ñ#m¸SÉh^¡3ŸÔ0ù¢ÒȲÈtW6õ «@1QpåŠg9x>§3ZÜDäð›n
+êI#S¢ZȬ·•º’ÏH‚Á´‰’äjk
+e$5"ÿgV#Í…~ŠšŸFÉüDíó}L‡+Ô4ëIÁî³nƒÃ„p{Ê´!%…Âd*N›tUÖ
+¤éŠù¼Áh$˜0îܬØê7«Nƒ2'„qÿ‰dÚ¯I+öÒËhL‹†(c!ÑmÕ"A±Ûœ6Á¾¬õë÷þ]Ñ—PÇð™ÏïðÇò™Ñï:õß—Ї9zæï@H?Rõ=Y9¢ ‚žV7¢[Ë࿦/=â7nNg£ÔlA¨º\Œ4eNG=©<­­G…âûrY6ÄÑÊÙkë &á¹îsäe’€cñ;*¿7%ÞîC
+[[¤­ ‰è6±(°ªÒŤu·þò¨˜j#“Dã°‰ÖdžNàå„ÈÀ¿»¥=ý‰Ò·¤‹ùÖÚ軜Óú«[rÁJ„"½*üs´f@„2>¬›{ˇ^¹ˆfÏG€ù(ÝE~^íK´r Ò§Ò 2Gƒí‡:©¸kÞ"dɆà#ÃÓ\%ö'‘ 'EÍXÊRÝÓ~)ñ‹ ºW)9õðâšÚÊ
+LÑTlÀt|d”Ý­køK
+¹’B@·áOÓ‡MÕ°ûá/Ñ-,Dé¹þò2G#7¢è xÙct`_Lùãê
+y¤©ûë} Ñ3,d‘-ÓäïËÏ—Ù-IVÐõÜæ'‰¥"®%Uÿ;ÔÔ@ãÕÆ™D…æǯ‰¾y!~A•ÖlýÙÄÿmð²PNa°ÔȉN>}¾HoŽ–öÊfR
+üeŸ!Ê„‡tá~n a\škØSû, í…ø{ '|d»¨’ á3‡Ç«qíbG Ã
+t_?×ÑÂ’¹tï¾þÎK¯ƒz_ûÆHÖ|2Ix.Ê:l ]Õiš¬Ä­u]‡Mq°§â(õ(9H4Ãk+¸¼F5‘É¿÷IT¶ÎÍÝϤÉÖ5µÆç^¨N‘û4¡­c2«Mkr«•kÂ"ËlÑM>Ñ<™8P+/xäˆ.òÙÇ5]“mw”_ˆ~¾ ¶‹&cB•±žO#W@eFˆ«Ã&ôÒ3ÉèãK¾•’)Ö æÌåAÝÀ[û›%S7<€Ð—Vì&LsæïêÕîò,­'M¤Âùœô«òûäÆ4Ù=*}Ï[i(Ÿ%‚ýz†˜Ëð`DŠ¬M$b=l”c fzÁF‰Xïøµ.{u°Q
+ bM½»Ø¸$ôi*u¦]ld/YKdO8hùç‹æ‰.Ü‹³ºØ¸$±Pá—w%Éì'|ö:Áy`£D SMÚ…’»0I´Rôšø¿Oø'6J
+ÉPtXë\76JT”ÂÌ.Õ\lÜ)ÃÕ'U=\lÄ߉,ÐØÑó%â³,¹SAñ°Qª€^àW“G·â†FOódÆ[s—!· ÌÞ˜£‹ŒëÙj¾=Bò‘Ñ)ç2®î#䌎ܓg+nÖŸö´Š¿#à´–ks«%˜F•²‚b”Ï©Y Ü}`
+?"´g/..JÀ¹,ð{¸¸c˜ˆ¿à¢#ºIÐ ïEO\tE?ãâò7\€-#†äÑâ²É¦,ño)ú´¸šBê¥kÕôhQ’¶†3E;³Gy«¿±tx,„òB‹Ê'­Ì¢2쇺IúaÍG%aA¨ û‚‹«¸ø0Oº’‡‹’ôªðÉ“]^¼ ðÆÅUp]ÏËOü¸¨qlkÒç...g¹È¤“Ç‚_ðÐ…‹¼˜ñÈÁxv¡è‡+º[êܺ7ÕÁªTš©§Á$)vë/ŠnrrŽû‚híL@#x)Oþþ"¢L©»!ò_‚Dõœ'x”¶_'Ú+gÝ-HL©GàeªJ¯ u»†°ê
+X³‰­X+"§o˽D´èº!Y¾,rŒãäà !Dí]ô¸F&ÂÊ0¼¾Ç
+'7ï ¥d™¶Ïe×ë%bµ›\0(2¹ ˆK÷jζ»þ!únáYMš6^?DK¡qhÎvXÖRÀ;Å/‰h:j†D–›`Új™ÚJHTÎ&d™v&# }{’ue8,ž£ V¬V°ºlü–°#
+…àGMn;éÒð ! ç$eTLwf“~šŠUßIWÙM 9LòÙQô †ÿô3xXFrª¹ãߨÍúR¿¬ã¿°˜ÄËw1V¦¼gT?Làa£ÖiÌ‹3QÍ“Úë»Ê"1L–|&Ô2׌šÕ4@繩ž¾2bñ”<ñ™sÕæ8'Ѫ<—}ËÞVñ€Nw<!I©­Ù4ª‡ñ§zZ¦ZÀ½æÍ°%!î¥7¡žIØ
+5÷ZR¨*ph&‹õ:Ð0FBÉç¨ÈK)Í'{:xÈ„Ó~cG…¨2¨A« ¨‹ I¿Ù_$QÔ9 ŽsÔCT(]æ+^²ÞbÝ+ê€4­CÉV«åuZ1‹›eô\sK¢²¯V£P>›Weê@[6+éz`hSŒÖéR„Ôö»Ioh¬FD/LSˆúHy©ÅQøæôýù"bb³^É|Êö&GÃ?IÚwËqË<U7©E·ŒulÚÅö•Åk95lØò¦]ŸVú,䔈¶MÔ;8 ÒѸݞÞ‚nÏî~+3-)I¦fw$vªé0Þ·ï€5khe‰¹*OaËÊÇq›| ñ‘ŒY•=6>«KäH ÐÖ.™…‘™6ÇN‹.œ›Å˜Up¾‘{{‘dr9ÑtȦYõŒgÕVÑ÷­;‹fí]q* f³èÌ…<ø…i=Ì¿,÷äŠf
+&Íün/*5*QZ¹k
+{ßA‚ãpeJ«egõBwÛ7Bo£ ÔD8"R)Ýš{_\W&kŒ=*áeótDyu#ö×aq×…#bròTì7±7Y|B‡QØÓ¬+2Rá„%êgÒxjgæÂ#A/*O¶´“2¬éûŽ f±r®vTg
+³ùÐJFÜò!>)uK(ƒ(*«{©zHì¨,vdÛ{¤zßIX»ô×½ö?ÆË%7r¢'˜«4D},ymŽÒ÷_ç•H5[ÆdklK,ÖgÒ‹{"Ø“ÀãoÐbì
+ÚÆ a~‰OuÚ)Æ,Úóâüú‚ŠÉ©Èy!6æK1ÙÐ?˜Ø8:³·lùžŠ|¬Ù«Ÿ-V q§Sñ¹€4>/± "ªÅµ#¨ì""a´*êf‡àºCРY²*r0‹å‡
+H‰Œ—AŽœ·„Oà;ÌÒE‰¤ÖÎÒ·xÀ[Mî¿ÍÇ_üð´Ú ìîjI$‹Å¢Ïþñ×ÐþX¡!æ­·ÿû!Cõá!n#F·u
+ü•ˆF[|`¦ú2tÉèÑÇšúñ3¯ê~Ò‡pòôùÔÌçÈÿ‚0.ˆåsõàG׋ݺ®nÒl?§õ©kvžc2»Ož¨<ÜïÈûòN˜áR‘÷àŽ¶8ÅêÖƒµ."Æ—Ü>Z› </,tX“äºj<85b¸téïÎák“¤Öë5ݺø”92-z4íÓ¤ St oâƒT\WÍßçm¾´ÞãCDZóXûªù³‘á²!™bõ˜acèÄU* «k•óÄÕÔd c—ó
+I׷磎99Æïפñ1\Úþ·ºLóU§@BÔ¬Áýû*8Üd)­Zɱž‘77« šÝŸ9+È´ w–¸úò§¢ÿ„íæ‡M¾ÓŽ2­¢Ìâ>iÓÇæ/GcV6ú¦öÚ·.yC[(\Q;åÏ`öÔ¹!™éÖbènèœ~ÅH2AFµ×Ü H13ÿ)u³}åHIuß‚¦¡È¸!‰æ24f FW§@„iº8Ñd7þ+ˆl7¸à"F;.ivt~¼nv4äbÁרì ×ºR±ÕÌœn¡r&Ü¡Û„å©ö³tQµçkÝuH¥ND8Îú Ÿç\“h]õŽÓ¥“^ëD2ßè¸<`OcA¾ºJ¡.ÌHÛ
+‰ÇñTNž~_´:´…æ`k*[¸#\(öl3”ÔõgoÁ¤bM_T•Sx[ìB5G‡m!v§¦ò h"NÌŠŒKÃH1¥$T´rž/ Ï[2Ññ)Æ›6("âBÚ´W!<˜ts¬¢`z "i9ÔvÏ ìÔŠÑWÀ-'5µ‰§°%ôg*š=“숻¹×U# uô]s"B½Ð,-™ƒJ°M°ä®9Õ„¡³s>GRæxõ±ºŠçMãSš{lB›*ÚÅÐ LÖ=Â(4KLÚÁL2Fï9ŒZ‚'Õ9Lú!ŸN¯«xk†…Ì—2µùè‘-Š¤³ô}|Q¢“6¨Ñ2žL¥øä1J¼à
+-´Ê1W3¶ió£~C'SR/¹À}´¤NÓÒ‚| A;\¥]r
+ˆÏÁ«‡ñv Ó)¢˜Ók¸¾‚.ã—Zà¤.Ó(†O² Ag²2¸Êš¤„29v뼂^ì {`f$;ŽÔ~„ûS(ÅÄjá¶A\×ÒÈ%û@Ú:ZAßÉA1+G™CM-Q;)&©fPw„„ƒNrxA6ËeaÎ7‚ &'÷Âë˜@»òW³àn‰§ˆTvÔ¬Ç8c­#ª¥©WIQÈE`÷UfЯM4l"†~\d¿’ÍM¿ŠÖÏ^0§D[êow¶ y>ê¿A_ Яãuß $™àBÝ3¼Ï#hâ“gCJiµ¸¸dä¶ Öo9C”ð}(õ6š AS²AlÜr†¤#I[nŸ©lí` ”ž`]÷1ìUù«Y{ÚLÓÒê!þ¶!<¿Ó­x¤8@ê¦4´Œ¶ó9©p!È–ñF¤$úNÄF½ÚÓëøá½?œ@È"™ˆ–)|¦x¥LòC›åטÁK
+¯…æ5ðW×7ssK¶äü
+Ž5ÌB‡Yå“0vÊ*‹¾Ù>§c±ïÌ©‚8ï`e3lØuѧ‰›¶!ÖøÃZßK¨™­áývdä5÷NbêsÓua†Ö)=Ç$ëÍ^5t8r¨l[2®ÄL˜n)¡Ç 0Ô4GͬuÉ¡Žÿã‚Ð%ér!ëÜô>s([î „m —¢é\žW½€F™G§óíûœô
+òÀž9sõ:Ï7~Ô…C1´ÇX”ÈÂ]©ë:ŸC”™pb(_“¯p­ÇðË]é¨8.“LÔ)l\Ly´’$î«02©;saÕÜbÇÈù Kdìs®VÀhœÒ¯–ç¸g›ÜªòÒ0_@Ÿo@4eg—äºB–OŒ=[Ô¨'c•ø^({e9ËÉÄÇ4 •ehôø˜ãÚ½œF‹u/^Ò¡FZc­Æ£w‘~’ÁbôÏn ½­*.¥êŠ6¹ˆ
+Ãb•BÆ*ß‘Aéo ¹L²u± ÝÜ9€~Ër½0ÌF«–+•6Ão9™¹=¶Ü
+ÊðBjï0iý™@Í‹é¿V ,R²É\«Vhä0µB ŽÐŸEÇ¢R<[!xéJ IT;eHî›–r¹¢Dn%ÛÕmk$lï q·’.ôgÀó†WC(‰Õ‡sKº4k@‡ ÜúlˆÔ eö:‡+WEÀ¶£ØìTüh±ÚÊÂŒ‘HúZOé:€F.ŸäFéÇ©=q,„Œ|ÄiűÍúHE36#—¸¯ú"ée(3lNcôqWñ"^'ŸuP"è3pãçsØIó…ÊÎå·•ù}—L­IÁ¼ZovÒTídW.w£–)V"¡_ag‡q¥»Ñd)K¹è1ﳩk<ˆ^ÿV©2XÎ Î~Žv$\ ×m*©Z¬Q^:ÕS›ÊIK.ƒÎ<
+ [Mˆk
+BÀh½HWÐWªä [Â,¥M\‹U‡–óšÄ@Ð!L þpI-£HÄÌ5v3,AiTÅqg¥ÿ=‹†á¿†¬² ƒ¹îB…&ÍÈ/|#R²™í¹½"®kâ1&š½r“YïŽûÎ;Ƭ‹D/Uç1QzÓéèìãšD ’0p™,ò/ãå’GÑè:‚ÿÏZ[ßÂ[éþ[¿$Á¶Õ…’1›‘ÑUEÈ|¹fùZ¤1Í´Fî8÷,«HàŠ(×oŒ!m¬ª«ËCÖ£ }'9ÒN´÷®ÙŽ‚G€‘pJìäc(g7súÏ¡Iã¢`;ý¯¡ÝÌZ}4çPÖÊÈ–@Õu m&ˆýäVgn¯þôuq\Ãœö›’\ÙXj¸­v^õý+ó„5ðÈû«D¢8ûôkž3MxÓÑׇžbk£0sÞ±¿{*„0d|yÖäÊcB³r9ß fF!wØICúΠóÿ¸uÝÏÁÌäL®‘ÐR温ëŒCºl…÷Q±ôPP·?†ÖñT´Çxl¯Là%Ôq3€Y™U16vHÞÌiò§ERТ$9„i»hpa²PÔgôM‘U‘¯XLh’Ô*´þØAÌ7uz.4YEÊ—³`iy‹~²Q/h©y¸áÇÚ.RuÌüçL!"Œ {¶n_ƒ( ¨bÕž0bNÂx!d;UŽòk>ñø5uèóœ~¢«ÈÅhBР÷惔›x \ÇvÖAZY ¼÷¼èÛ­Òþñ%l þ èbÐ…|î¼ò4›BæC㈔°ŽÜ
+MFEº?Ëà*“ÌÓx¾‡_« eÑKÔ¹y„0
+-ò°çÀü­ !ïÁ|[m–­Œ‘:¾…{ìW‰`ÓdµF
+&ð´[¾NY¬e˜¸3û©ö­0Å(ZSðJ@n%.(X»ðRämD!=0"ëñÇE¼.Ã'ä‡TÃØks)ªŠ ØENs'6JV¤Ê)y¶ž\Eë#ŽZשׂ ~ÖFñŸÃË›¤ƒÄ{(–Ybœ¡>Ül—äÎð2y½x¡äýÅ+òî§iœÛ”Þßô¥ˆ!‹z6íAêwañ¨r:E?Øž_¨ òxØ`ÌÛ{ž"ÞçMQ¡^•—¿®’©päÆ6’äOV¡ò”®‘ â5’"pÎì6‡"ãÀ¡WãT4a"š›þâ ¼\ð‰ÙöcÄÓÐUpÜÖRRJoµ–RûÍ„PÓ*š !ò„
+Nðàyû ‚¦/ª»„üÅvs€|ˆí+={E°±F»æ´Õ±ëË`HþŠÉ ¿q¾:_|áÐ˹œ]×Ç^чOÅAÄA
+—£§Wo®òã/,$OV¿ä ×~ÿdˆÿ2]èlÉÀÂ!ÍÈže!(äÓ-âËÙÊÑɶŒŽ’YáU” D5»lƒ;àßò¿0–þÒVéF M`N‡Iˆý|zž™;©´l˜yÓ‚H–¸Ÿ¢ÈÉMrÙ
+^½Y&…jpêäëf¿øðV;“¼|nŽ­cû’ò£Q=ÿ¸ÈSÄ€®0/Ä™1êM‘¾IOâùMàôg Z6€ç 
+xl¨+[x{ÃIÂdë¼êûåúÇw–¬³æˆx4­‚é¥ìXkî{Û›¨0‘DÊÎ/E¿nŠ¸°hl‰)îÎ:E¾2ZUÉóu—HŽš#Ó«$U†Ñí£9|
+£#,‘^ø‹½ŠdÐæûÙå´¤“pZÜ¡ï ýçŠÉ´îF
+Â{ÃR`#þrŠ>Ü"ÞÕHfK΂V ²Õ"™w3M&''Ü_ƒã`XX~1’þ%T õ×6ªóG³élµÁŽ•¾Ðg¬IŸÏ#=oãº`X&Šm²‡ô¿wØð,3H³øÏ× ìÍm<šþYTÂaÐæèÔ±¨FÒ%\)yÄ¢’]—
+Åìbÿ.!`Ôåö¿¿øE¸WIì^þ屃v×Ç`àûexî˜ÓÈæÿSœ'ýhŸœcQç8[ÚZÐ>ÒïÏÑ'ë‡"×<Ë6ie±fe%« G´î¡†ÓÏ+²8ëp}Î\#Ip #aaÚ#
+ÎÔëÉ'_•z5dî´æѼ ´ÚÉŽ0€ —¹l=ß‹±ãî9,fÖÜÌsðë×@õäž ÝÄÄ5r3,¾œç(±„3
+?vI„ܪÈǾ†ýŽ²Î¹ïŠ
+-æçU¨8ވͳZT4pAöyrHÚðï?ƹ(K™• Ɇ2Çth(F´ñ ®5›År
+X¼}-Z%¨_¼ ×JÐ-¶O(vIÑ<òƒÒΫeºÀV϶O/Á'{‚ˆø‚¾E¹ñ‰{˜‰Ü þÙæéEË°jr]Òø ؉égS羿85O&ñk×èa.î;:EvƒÁ@H¬ñOE«$äH‰È½[I[g°©k
+™ËT #G·<5*–ÚƒRûv
+r£­ÝMÅ·Ã¥1 g »V©ÀAõ0Æ¿Ôhs؉tžY󑇦2mQÇÝDÔaA™¿+)‰¢Ó†YÌ$H‹óc +Ü.âËØ¡R›1àœÙ€Û¢‡NÎypUÖ4óæRʸ{ ^3¥ý|ËÊ°M!Ï:ŠÆ…¹ÇÙΤã4Ëßo‚èQ§™$uÖ É¢~Ķ½®
+ œB ¦„‹Ïþ0^æHšY>AÝ¡åÊb_D µUNІD!r>÷âÇ*3²©™a ÿ#cñç ¹€•Ú$5VŽÙÓëKÐ%ÝÛf s?ƨ[ß©¬Aé+D;”ÈÓi¢{GˆD‰É¼rþ¾¯—`(ä¡ÙÍ$Ì%¨³Ö#ÛÙB3oÉ}ì§ìƒF@Õ2E¹@ŽzqÁü8cs¸Šl­¸ªÁëÒãKÝ*3CB n±Ì׫ÞUrÑH $iÞŸýÅ`Cø‚}§&WJ…‡;©Û=ºÖUñší
+Mæ¯a^Ka‚$ØÓ6GuwܦùÔSUí’ªjt:j¢õ“6:Y]p½IÀxyA?VQÒ—¸¶sØVCÌPš)šõ)´ß´ï¾Z‡,à’<òíðͦ°X[A\:âˆ!ôà´ÉDuûTã¤ä°ÒŸ_–Ãœã ûSQâ8e£î+Îm„£ù‡2/ÀÐdΨ®,†‘#ÃKØa1TèN\õ‡¨‘ zÝú‡xÔ4fš‘ž:·ú}ößÎ óÉ„>¾âT?”­Ä°¹Sw¿[gos*G534n­³ÍPÐËCæ^ßãò%”.SÁ|AØ2ß–A¼by^Ù"c31?¤Zù§/Øt"OO;ÿ t; ˆ' b ç鎎˜´d¤*¥1 †IDÒ6ˆ-!•þ  I'êžžÖu4’(½oH±ßG“²º×à`3Úé™{ú+'ëó<<RiðžKLýi¹z˜‰C!Öéi}¢ß⊎
+fL§ûÓ¾TxÆ©¶2=Ê"fXãIÞ°uˆÊôªt‡ö² —×?Cŧ‚0š ‹`tLOëŒ
+g±”œv°+ëutƒ`ö¬B~*å°áßßN G42è_w UBÉÑÇ™,Ås‰&®·“ß*Ï
+×;Ô'È4q½tÜ]v0ÊØ%GÐ@"Ù;¨§¤iÊb+¦–Áà!ißõ0?¤Y!ŒB?DÅôâ‘b³\¦/ÙT&^™(¬ÕÖA¥ÑTjÆ*l@ÐIˆ„ÐðMA&Ïøð,)Œd}jrã™ –—¨×ÕºÌf!aíf°!‘2bò$ Ͷ}*Ü> (n0¤­q…#}Hé¶Ò0›KÁkmø!Xû³)3㉦A(›l ÷MµO~ø%_nð¾Îí½çåTþ© /È]QÏ®
+´™ó™\ Ë€ZLñÌýˆèN
+JѳZyù"kìÚ>¤„Wj‡Õþ>@Ø4zÃYiGqí©ëIy-ÂjºÂD7Àl(gé‰IÒŸKK 1P­‡âÖÔ<Ú‡¨ h6ÚÙDçå ÇXmnL¯¢‘ìd7ãN>èlÊ!Ý2;Zç»Âø,k¡ó:p°†!
+¦•Â´›Êåxe>©¼ ‘G÷U:âOì "Nx=7ê?¬+éS
+£ :1!R7dó½*r’ `Ñ—Al‘Ûƒ
+]+ïAh(ƒ’ô†"+M2™V‹©™ds±§ ë]â’À†Tø3I„D÷´/q$•ˆZz¼x'ÊÅXŠ+LD’É&¾ÎdÖP±ÆZÅ%lð3nÙþr”Âã:äBˆíÊÞ ^.Ù­äMƒ` E¢‘Ö
+ÜÙãZWmlÝÞJUSN‡i!›F‚5Í¥í­h
+uP3}*x¦;öµe hŠÆ}µæºÓ ZØl?Q¼9ƾåJµm¼9¨éùÂŒ+?¬‡”¥®³ƒÄ€÷£.ȼ .€2êûSŸ {
+òYÐJ]¶
+¢:¼i_ÙnAð³ÄvKÊ®¦hä‡À¾”‘£4uÎhë`?$R
+6×ÅdÞ ÁAMò~QŽ f1 R”Xœö§. xšçº¬ªCØnh´V)¨O †¢\WËv*èXÿ8ÓN𨰢0a¹îû«Š™\Q±ÐØyL4¤Œ1ÿ#ߦÏ$&<²8!2†:×Ûq֋Ϙ˜ù 6´-7Чä×h¯ÀîQ™DĹÞÝi~Qʦw`̹h¢Þ‹ÄÈ'¡
+fµ•Ö*(2ϵù§h@è+É™†fë, ¥øõ¶é‡Ô õ\.ø0¸óÁ¿u¾0ü
+žù.BzepãÃ"p‚¹â½“ªÁÚƒ;#qåݘâa¯._Ìœ|†úwäÖ¯e|µkÞ<„FÅãÑÃÞÎåÔ·Ø̃Õs{‰›¡Î0Ò¨ÇU"µ`mñU¤œªiþ9¥E€ã~"5£ñ=‚ûŠ¹3/r¿‰ßPí¾
+hÁËu«¡0ñ7î`·Éìª2`ìî¬'jÈÒ4Æí–4ècnó½ÚG ˆûám‚'…Òîä<o,%
+ã †<KYÕx–ŒIÉóTÑù"ˆ€b7¿;V ® _
+³-ï{÷šÕhèÜ‹JGàLåLo5àÁõÓºí¾ä*•Ô ,ØciùœÏT¤3ñ!CÜ‚!øgu’ô¾ ÓšsJ
+ïl3—ÜI)
+!JüSbÊ‚Ç{ÁnçHc˜yj¹`v….F
+D6l÷¦KÑÅ`{—ag%•£Ã=j+I¢+þ.(>U9­y„+ýkPQ›|±?¦Ò›Bèz
+)ÚáŠ{-2Ê‚ÓÔ§JÂÄ*+¡ðŒ,"MšR þúE#㸵<»Å€ év™"5nÜ6çvPkð©^J¾`ôû·SÑíAw\a ªIÿPtÛÀÓçþ¢èÂ
+çåºýòýAÉzá$O¸ÿi%2Ÿ£àL¶ø\@”öœBà ±«„—€y»¹ ô”X¬6´áöÎ…å%e§rÙ\¹Á
+è*’ûØÊ"Ù'ô ¿a”(—¥‘íœuã†ïOnJdxgQÀÈõX‚5}Á` ”ö§nEÒüÆî+?F“ÆïYá
+ä›OnÄ{q›{ÞQrà˽¥à›ÃÐi*¹is`´N¥ÊRÎ ½fA&g«_Ë9æ~W@—A(„ܽD:ÚØýÍE=Bsá»ý!ÜcH.c÷gãß`é(Ra£5`ƒar½žJ4X´‹ ÷"ÈSLƒé•i·ÁÓiÓvû±‘/g|®‚¬Üd I¿ßË€/À¯ÃLÓJ”ÀX›BŸC”Ý„È ·nñDv3f©Phs„¶ª`c,p)9ÓÒ¥èÇC Ë‹¹°ŸEIɶ‹L—hW+Ú…é‘Vf…t8°ènTJ¬Ùƒ-KE E–”ï6„ 4ƒdWÀD\fgd`BR)þ%’m‡ëäša7«Pì%å@mùPâ_Âdhv u>‡v1n®Ç•Ë¾ {¨³Ùs+È
+Á2›„
+#l;ÎçßÞëÒ˜¨~éz®ÓÄ\Vé`5­$ËâÀ ~(),;4ZìˆA15xî¸}>ñ*j&¯J~Ÿ€b-G`DJ…srÐ^_Âɯâ/§W²S¸Ÿ F¤F þ)Ü¢ÎaÑ|žøƒ ³wÑŸžÄ ýv<¥#B¤­†ªíO $N‚NüS¹áohZ‹ö*QÛ”:ð©á%ìrä H+Ñ3.6+J¶³ÀøN‘_éçsPŸtæ ˆÀ×Orªi$„‡¨Ñœ~ᶴ³gy4ûJ‰W9™âW¦ßˆ‹Tj²s@çC†Ìlj3“Íb†£{I#QÊ2ìq2[l#íîEüÿ'Á‹Á¡Hù´+Jåißbë1tgg‰
+l7¬¹mÕ„“ê0÷±os/ºF’?êïò¦ìî‚`Ò»éïÅÀþ<”œÜrÅÙ€¹Œè–üEwûØK©÷^rɼÐr™_Õ3¯JY0—vV½e^Šº¦‹kà´cæ¥D°•sfÌgSU^Êf¬(&¡=d^Ú·xGôšΩd¿ÈÈùü¾ò%óþOy™$בëPtµ‡¿‚ì›±§Þ…§Òþ§ÿ\|¶2™eÕ QÄ$Üî>„C潌ûTÙ ~¾óì×È«—3Ù‚²Wðb…Šrˆtûöd¨XIÄ'¡?µÍ‡S’˜"Ãi©ž#oyEÖq ÍÜ.òyË+ ÛU+žoÆ$`>F‡­öN\ï¡äŠnE§=ϲ…<+ÖÊ(º#ïð¹oï_è⼘Z$ÆAÈ a¯ Vl³Š&OƒøÉ@«áá%¬a5Òèö”4D’ep#Y‰‡&(°9Ú5T ÷NêÆE|š¯=ɹnøúT”Œ½Pòº¡Œ
+àzV¨´’eâýõ¥ˆ G‘*$pª¡"‘cqˆ]Ú!ªô¤›%½y îkŠTz<¤ÔµD‡"bR›äIÄÂv+•ɨ‘üZêö-,Ö—Å6_$#’zã~cy¿ÆMCw¥'¹n~ŠÐQb¦,©¯«Cýì–SãKP:šGÙ»¯¤Å
+ lɇ
+ÿ¿DÖ˜Õ6"×cnó¾_æ¶7§GÝöïÞœÛß:|Xó/ƒúõÀ[AØ‚À`uì-£Îû<É$wÀÕyl³JÈ,¸Š$}Úæs.È\Ù®Ž©ÆÇB–e<ÖnRbÇ »ˆ’±-ôº;‡í!ïLv·…÷ÉßÝ%;–gÉÎÑ‚Ú:Cbµ°ÌÛ€ÒX°܇osQ
+àb»s¯L3!$zäM(Ö im÷Fk&Ž–ìRŸÌø`ëÜ8bÎåçÜd$ŽP­ÁœhÛà+…бQ|+ú2÷cÑà$%¿Äy)ÚLj*a}“; QäMròÖ(×ð‚Vw M/[8öÃvZbEò4¥Dò¡y4LÆæ@2„‰&åGE¾åAÖƒÄ š.„s<„µb©XÈÆ®úM§V¦½×“_²¿©FçþI÷†¶ g®/­5•Ùs£°;“6JŽ€…5°S6£L—~9rl6’<AÇ2È•Ó½öþÔ¿#s dž ¿Çž(lµ“]þô"ö×ö˜ãz*êL‹{sÚÓ z*ÑÿÉ@È<aF%â¼)ŸÏÐËSM[ès>3V£gàÃAŽÎÁŸx¯h—¢áÙ3Ž«.ØÕ
+áÐÅÿœŠnÑeÁH]ìÌB»ˆÏñ%úäK­‡‡"\>ÊÁ>B7vmX'Òû1š“i’EnU†qX b@°äJ§¸ÁV<—ÝCP3fæ7;’lHHçQ@œ±³½M¿*°œ5@%ŽCÉ/Û €C°Dˆb:‡tPŒ;ÝözA@9·[¿’x»¸Ÿ¬HZãþRDNø›0»·8*šfþ­vW4ž´b(h©dŒÚÚv½ …¤­C_DöÇ?÷’Ó´9Ñ«˜æ·‹.Øûø@Ç™µÈpV.Ä'g½– Ç‹ô'gÆ…¤•†‡‰gg¦Ž;ß½âÔ•U$fª"òj¤—­û9üKÐéíŒcJè!S„ÛâŽoE§y©)LŒïÖœP|¯¹‚¸ÈCÓviz9ƒ¸,Éa1GŽíÄdÞÉ0!õvñaWô‘5A8ò"Ê|Bq–FÊaÀ…õ|NFö;MÈi†|DqF§¡ÂvÙ!'³€Ð2¤RÎ(Î/ô¶² 8q†1«Î«4ØM±O@¾&ž^ Ù¯¨¶þí¢”ÿ†Ñwfew^0ÔLø!EKËn¸°,ëØIŸV„*Cf¡CÑ*á>¸Ýyµ—DºÖ¦v+Q:€8iÃΣ|˜EdÛnC!Ä(Ž³™f4T´ };G Àl±°Zñsøœ ;­ÒRbÉضY§•ˆòQs<^I6”[ê
+ ɶƒêý©[DA\ëRÿ–Ì$Þ±‡õů’©ÍãvÓ÷‹¿ÉYË„Û_Ìæ*<Ö—‡(Y'ŒÂ"Xÿ-@Å´´ò´‚ÿ¾Ê?~§ÉøŠq$!‹7 öéû¡c¯J:zñUÂZ$¾¢§‚˜y!ñŠ¢!ŽÓvë ã9ü^zœ²A+ÆÎYÙ­7æâøˆêñtüÖ†Ñe ]Oí@l“ësÉ|
+ ª@"?!zEF%õ„,•Y%š•¸´5÷%LeˆLñ½§1B#·nÖð’»VIˆŒ†¾xêb{*1 ì£Õé¡D#€Y€D™ûS—¢Î:±„AFpv;‡æIhòœÂ"'ÍN+)r†¬XïŽ6Gz†½1…$øÝ´“Çá7vgs\è…‹«\ à.„iª[6I2.^ŒQžJÎÜt)úùPDtƒƒ€„dÜt(JÚµ.FÝܪ„úë^”øðõÃéË:Øõ)sA•Â°Í¾ì5îË?Ѷ±¥wC4ZïÜ ¨ÃÈ€K÷èlSˆlONV’ÑM¾çŽK‰Jy@T4ÇÓ1hDªŒâíùØ©ŠÈÊyÈÑÕ”]ݾ !Åö† §§
+"ȃž¹Û`m°CØ*züP‚ FP&‰kèZd-”TÞ™àÏ¢‡"ž%âäYÉïÃ(1ßtdß8ÈË…I@ò—ãæDÆ\ö¤@7}ñÍÿ¹7Í»¤=*jð/ñÎ uuð΀9Êa2ÝoàˆÝæw¤FDWÞM†D«ê©ˆ
+‘„V§7üE
+êáö4 Â`Õ}Êl2Ѓ¿ÂöŽ×c¢8<K`çðc0ˆdPR¦ó~–“ˆxVÒ–€bïpXö¥øb‹ÐÏÞçε_RÐ*a…:F!†÷¨’LiÕJv/áI].Þ+´(AÛf‹¯5C$Ž Bí7\k°B´rÈÓ>„,`ZñºÝ™?à1*Ì:a«Ü4½²U“#æ.ÿ±ïr/úSZ?¾£¿–5Gƒp ˜(ì‚.΃=b{°K¦ïEt¨ö^Èn cí`S–+Ð×9ÃXôŠ&“­óÚR¾ñm¿iZ¡‡¬dÜòVf&z‰ŸIV#x¦I¬„û²k5»}%ñ„ˆ¢´>÷—&º[ ó”8á€VÞ¨3¡Nh’•pë®>ðËb%B¹g3£2âàlìE1ÒYÎoQÏlE".v¶(ÑH‡a
+÷c%ìY¸3å4äÒÜ+WFɬ™¿¼0Ü,«züå(ß aG;´t(ªÕö~yÁ}0¼‘%àã„Kïï“гÔ
+7#ú³0
+·pPÏÖ‡’/ë¹ú{+:íy‚Ôá6 ü€9Ý¡÷ÆË$KŽ¢'Ðúzœ‡µ¼Ô-¼mßë$XíÊDʽñ“K“Äñá|îA5pçêc‚òáÌì|(ÙiCF@‚?Y@¶°­¤iYo.N!,j"ÊT^³õFhD°ù"öÈg³ÙBù#\ER»® )ûÞt5ÀHt}’ö9Xȳi]³ª5¶ËQWÇï¢õ ³AGÌùU¬¹Aã6D‘ìµ81Ÿû:s²@qi+®Cò*ó–ñÍý-ø’‘ȸÇ|x8.€Ùº¡i¯‚m!G}=gòÕ3]Y\Ï$/vNàÖX «œ3€^1Õ&B³n…C¸ï§ô¹Ü‘2’‹à­Uâ$“Ú!4=YÀ'ë±g64Ô4®/ĉÈMú׆´I’™Zë>‡sI¨˜ÍŠ°‘
+c©I½œy²qFkc×Ò Òš2HaA´V1ïABm¬·€¬FÞ•訇á與ûô*<Ç.
+ÊlwŒš<-dÓeÊŒ@¦l<§îüÊâµ6È} VHÅ|6PÒÇDfm |ŸÆ›7êQ÷ÈÝ'ã»îìY•.@ƒóÛ‹a©JV Éï•N1Yý^Ö·•Ê$“MAû!½‹!¢l²"Õ)ì˜d>í²RÄQ1Ú§@!ŠÕPÅÜ%KDPü`²ŒdË€å¾Éôà‰„=êÿ
+®Þ¯Þè5kíîÆÖê‰AFf‰®c«\Qâ]¬^rláxmÁ!úÄÀq.£j:^L˜D³-D¿ÓÁÌTÖölKBF°©í ÿ)Ï9íê ŠÆƖݾ@þêHÚ­á¡2ܤ2һ{reýoGúKé‚´<(ötŽ&yPƒ#µÎÞSdCg&.íŒE
+(sÅ{±éƒ%¦4uznì×ýfØê0ÔZ+'`ÿtʹO°s„
+S»al‹œ Õ<¦ S²¶ =¢Âü w®OAÆà8¾Ï}lŽ4aϨv:]˜ˆ³6Ý,Y7pw1/g^6éÀÕ¯~P¥
+Q]öüÛÍò7ƒx{hL.Õ0³¸a³C—™4Æ£aX¶Nß-¤–)J Éõxp‹5~Œ‘fg×.ac`B`ÇîÛ%e„m¹éÙ…µ†:™‰EåÓÓ9ú(ëRrB*½Ï3C ¡e;ËšÖ »06ÎV3|çS4ÔÛ#í|Fç‘3ˆàWIƒ”
+‰–§Ñ ;»,-Êö§…p¨¨œ6·J:AjPí˜SÆ󹃘¢€Çr²Ý‡‡kÓÂ[fµû”!#”ÛXîÏÑGÞ<Gô#»¾GØÇš˜©J©=œ2É7˜•‹¨äS)ïvºhNV³›ð—€ŒIE}­ ˆñÂùúé/4ƒ†â»)ï`f#õ¥&o!jæŒb(;Á· Kº½u úýµÕ%Ü0i’3fX4s›
+!ñ'ï„ÀŸªNÈúTI‰‹Á¦ÇsÀpˆ‘ÙÐS‚¡êN
+a
+˜VÏdHÔðkž>xj§VÕnA0mðÃh‚­ÏÞÇà8–!í£}Ø•ù}ä^¢ñcú±œdO¯TY{¸é-IJŒÑ XÙ“…h9éSC«Æ ŒÅ‡Ý
+
+Em-›e@«ä@¬gý|©b¬@v,'& ½"nœ¢sé.-s
+ª?G’`k d–miÈ‹Õ¨ÛYG¤T)ÅNÐêè®Îðß[!.!VòK=ïçܺ‚Ët4 yDU‹Û]•- í¤ܲ¼t©TŒ@zfÞŸºõ:KeE±WÆuº!Œ§|&aëß߬/çiK ë|eî­Ë™A/ˆîƒ,gQg­09×Ðt˜Ä´³Ðͼ•(¢ÐT%žHT&š…ëæQèÉÇAîäê!=´àô‘²»Ø6]¼ËyótBÖ§ø|ÁÕnÐ
+T¾¯7Ø•¡åæ_Ž«v:·/ò“$Ò'ÐXïr¯_?ܘ7Eüôbðv 9ÞšúþPGi‡Ì|oµ8\‡ŒS£²]
+Qî^¬}’”‹“„SçÙ¥Š¸3óµ7ð,†ËÞ3AÿS&b3ÚÙ¤ÖÔ³s¶Õ¹!/¼†X1™Ž¥½G|:çRïûmn}ã½êÖ÷ìÜšø–b§Íß
+õ÷wæËßZÓæ@=°ï…µÕ݃Uì W$J^©jd€>†dÈÖmܼä2j@~ÈèÉêIRFœr‚.²JHÕª‡øCV®z¥¿éªºŒÏÃQtcòÏ¡¡IFЦy𸠮‡F1Ù3g’1ö|ú02×AÔçþvÿ²6‘‰“œµ<ðÆ–ö1àœ|±`“ƒn#)éï;¢Æ
+ÿéA+t2kŠ09î‘C…Œ hø &žwËóð¡¿gY8!ük6™4'ÅØcy9ˆ $Ð3‰>Y›ê®ïL,[€…Çw¥¼ÓŠz‚¦! Jy8…Dæ˜Å'/pŠQ MyOƒrWŒ”£LJ'é£à°÷´®Qa¦ ™v<©Iå†DÌåô+²Òá®–`þÔòœ¶A8cG70q…ôµ×§þ<›Ë"Ù1£¤g²éy;Ü?”;KY õi°?°I Ý¾´öŠBµZÍþÐ@u×Ø/d½-¯-aëÿ2^&Éuä:]÷à8Ø7cM½ OåýOë\Ìò{É´õDE•%Iàâ6¡?|'+ipeÖëdX¬bDv³N~|H›ßNEóHGXš¬dýrÇU…Ð&â÷Š
+‚ÕéÒ12`¾^ã>‰Xƒ,DñÞ°iAdÉ?åÊ4ãků![ R€…çÿ96+AÿȵÈM/©ýøv*:Í\6Ÿ]¢éÉûRÑÛ~~eMÿ7¼ÙQv:Åœ«$;?þmES¶%°Ã!Š(£a”š¬¸í#Æ>…Æ=–)¦D–dIOð’ž°Vè[VlÑP(¢;ø››Ð§•…ã‹}G쥈bšŒså+A}Aƒ­¢êº(²’<ЀõšÉ½¨ y¸(DìúÓŠ"Q†µƒã¡èÓÚE‘5¡î:E«„W´P÷ðà ¥Zpü,fµQ!.䦃wþeG¥!l£9­¨÷.2ÇŒlß!(–
+#42ALg
+>ôš~ >Ð!}©ÛXÃ[`†‰õAöŒŠÆ)çu/9Ó[Ñχ"¦†÷g¯2&æó¡÷‹ò‹M˜æJ8Aa`&‡´K¯6Š3²ó Om1Íüù™o§Ñ…ˆØÃ-¾CV¿Õœ•Ùr ÍÇúe=Bôäd-œÚB·†t(ñQtÎÌëÓwðe«”/˧lËPAjs¬cóq4x˜îÒ=sg’$à¸VˆÐýÐÙ5‹<!ókÎ¥úȵÆæÝ‘ÐbrP(%Hs,<}6u`ª¤DzñEŸE<‹ AKÕáÞ`1ǀʕÕ°^[ð%Ö´¡1èd[,‚–$Ä´7k†ZFéÍCž[Cc þt©;d‚¦+Q’Ô·$‡þt$&ûŠi/\M·Á½xt?‰ …ÊÈɤºé êX¼£…t
+ö Eßd-
+vvoñ­èeðŸÇ¢Á—”*ßKÑk‚§ã$+Q|^ê­Éz7€–“¾R8ž%Ò™¢/5ED%ŠJ]ÑFEè
+“šAîµ:@åäøb­“?]‡¼7¹NÐqt,—·&5^ Ù®ü·ÖeªÓé´-»×hyNK Nkdùh_»Žúûnš¥ã§ýQâ,–ݺÈg†ŽñMÅ6øVC
+Kµ xZ× @ˆ<\ݽjšLà\ÖY1ŒÖ°àSSÇr–]È»b·FÆgUD_†!®Š„ê³°³vnŒhoËV2’T*qjùbÅä _A7VId8Ћ‚ÑäU‚ûÊü•²Dñ£ð l45<óÓjè7ž-{ ZMG¹ÙlGqÙ¬äfŸ,5ûÁŸÔfך¼õô’Õ>Šh@Üg‚e*³8zˆ` x‘&{µÏðÓÿgéî*¡%€‚—•î%“èH–jO%7©¾¡HM>† Ù%eÿä,×5V†é’>M×–ÒÉ2RÕú
+>{8*¼™ŠQö¢q]q,jXE,8¸è
+®Å¾Ã¶#˜Æ´z“,ܵú~Òë(©€ãá}Î&²îy¿‚‚"xYhM÷óî¨جb€|_Ëu–æM©[¾É
+ œ§BWbûÞqôà=JrsEÖ­ïÇeƒKÂ/`((w
+;Øà{ƒz vx.,À#G%Ê!¿Nü=lü¬YIã·ˆŸÔ}0ì;ôدO4º6mrOð¯>˜¾žÉº^‚—ÅYE†1“•0”ŠÄ2Áq(YGeâÍbw˜äñ;ÃÈ”‘Ðæ· Š§ ˆõVIYjÄ(±åþ(rKƒñ—bz/j+»°L
+ªÃ0ÆaCÀCá·Û ‹ä
+?2r¹Á‡Évñ{óX‚à œM2+¶úûn¹ÃŒxg\ ’„ÈÆWPú0U59¤iøÍâßýNl[B.,§&åBËø+Q•+—JÖµÿc¼\’ãˆaz‚\Å¥ÿgmŽ2¾ÿ6Ù‰»5Nª²‰ #µH
+cãN"%ÏËCò†¬W‘ÏFk¦Ÿ)Å‹hÄÏ'Щy ^ÄÖ{ùoÓ<øfÆDQhsžëp+l–&ôo@_¿é¦S¯ Â*ùV¼Ñ©@êÑ~ kb>ë ©›ØX‡¶ r€‹Xv™Q)bzw{*€Ø.­‰(rçÞ7’Õe¼„½¡ò«¾gâ¯+-e‚3þõh‘A‚LÌkÊùŸ£A¬Ð3Íz
+é/qÓnÒÿjò,>œž0Ziõ ÈÛ@›'šþ›È?¯¨DãY8Q•î¤ƒ}¨`,øžç6ÅËY5n›eQe9³yxTÂ@ ÐC,qʆfd€‹°pQ3bT¦¤{3 œ¢+çï·a©X/Ú¹ôîªYÛù1Ï1s>{ój†þ‹¯¶x<¥í{µ‘5gr ¹õ‚`Ó•»¿i€É¤‰x±4¨ߧûî—H² Ú>ÙÿÄãÓÃzÇñ=½¨È
+Q¦_uQMVD­;s‡q ið0M=B]lhEXyMC hc°‘¡kXgÔ*ãÓ€¹ð
+V(WuœPÓ¤ì¥ØÛ›ä£4]½ L*zAÕ¸ )ì ܺ•Ä®J˜
+#éïÎa%§T¯e"ÐÓ•,LmùæRZiB!QTB/½†­/^ƒIq˜m¶~Û\I§VÚ¾®^X“(0I1”72(_hrDZ{Þ6wt»÷á èõÄ«À°²‘zëìnü$ÇMÓ&á,bz…»6À` ´Ä[…òbq _¼ÄŸ¿£©–n)ƒ8OKÈ‚]…‚‰,=D‹ ˆGÐYÜnC>‚¶U4&ÄC¸²~Ò;©‚âñ
+™Š(§ÏÅmòÁ«Î›¢¨3×lµ+ë>˜XÊè^AoΑb®|KŒþÉ82þIŸ&ûD‘®l<µeŸ=+}þF;:hIŽ Á0üRÓ>c‘D¸³Ï¿QŠ‘„0ŒuRvk'–ÆrDK ¬®7y(6x"æþ‘‚Í$Ó‰²)v•?[0í£É p˸˜9ª‰Ît÷MT©Ž@ükž ¿Íõõ?üW>Mk(ü°ÀS»8E•”?ODˆaÕaõ "Aãkë–Yò:67úJù™å6J™ÈÞ~Cw'™Sg¤G!¥øtQ3”€2©û}ÃÀP‘¢ÂZ¡¿ò¤ !²)5‰1Ⱥª|HÒF`žÏ)ò+žPE¨g¶Z2ù}žyæਭBžä¯ Bóq¶Ôméè%¢¦` gƾ,ã9…|ãëf``•còÚ%ŸO¿A¬Ê·žÎ¹5â¶ßœú)iäPÞÏÓ,=ÜiÑÖ°Kî«…‡;µ”Šñ}¢(ä¨'„¢>#€Ë#ŸFœô[€
+H‰”—M’\¹ „O ;ôüüÀµ¼Ô-áUëþ[xËÓU,E{313õH‰ÌÄ5ëÓ.¥|ü«w»† ­:†ôÑ>~ýøÏùø÷ÒZ½ª™·6›/h™Mç¨âSëÇŸ#H¯á:K¯S‡~܈æ6ël6u.D©Ò„+Y-cÌÚ{)= ã²iZ§um¿×Iνͪ·ž n]¸Œ«È}T»Šyé&Ò­.H+µå KàÑ›K×r€ÜGµkrˆxáýü~Ub>Ûã6RÇœs ï Ò§‰•b”,_å•êðÖbýãç¨]V{íC|”êôи¸Gu÷^jÿ6h^êyi"ôhú5†¶ªÖFŸ•J'Œ/Ý5òkö:jS™“ª}.PþÛ[+c}ˆßÓõ®ª­¬÷‹úÎè٠á‚svzØýØŒ¯ˆìEñl²1ýøˆ¡ÃáA¥åUÜ»7º3“`Ü–û ìÉYUÁÍ}l‚qU¾QTF‚´O)ÀèlõÄvg$ªñwôy„ì6;¥bÂöQ­˜ÂÒ*ÍñZŽ÷¹yè Šú4ξ'0@Óš4‹Â/ÓàÉ Ì§>HÞ‚£IWüj «tÂg¸dEN“Áµ²Ì
+ÉÞ O¹„O*Üíü™rÑ@ŠQû,vŒiS•×##K4¬R·1joªkv^@'2 RÒ(-ß_šð-ÇqŠ%•!XŒ?€:*:ZŒ]­«@ç¬ÙJªa­œ££À__Æch÷ÞÚBȤ¢fGH~¯ƒFæUç«><Sju5—ú¦“iƒSÆx·)ZÊ…ëy’·)ï:~Z8ŠÐ³Ÿ4Ä…¹Õ„dŒn-Ó¹|±Qî“
+5ч-HØIÕó± Vë=,‹­–(ªN›hìr0äŽ Žp>ä*>c—ЊiHtM¹Ã¦DǤ%¤§ôÆt×iŽTúOVG^@Æä´‰¡P]|è׺d‘[´¶&~}.S‚â:âbÐ A’œÊ‹ó0|'ðiž· ¡ê“Ç™Ðcçf{4**ÚfgÀÃ"ˆð:3¨a"7„#ืd–BˆdJ ?>Büªd†2ð=zõê\þ2¿û$úÒÜ“9*EPD±êBP`ó,»ãÂ-Ü ‰Ž}®GsLÍf¹Ð“‰üJkY½ s! ˜¿ãßßyüó!i<¬l½"}Š’L/N­´rû7/Çœ,œxAzP±ÓÒ×üb`t‰`U´ë–ÃW´± ¾*ÆC~î)@Ý¡; ¹£.9\Ó舲öSÜ
+ñjî-‘I`ÿ&û? ’ÃveRöèáxcj[)Öî°×béÝÝÄÓŠG.Ç1¶^<<ä ßEõRð" 6/¶«TºO;#é¦ø‹Ãve—h‡¶`,–ÏmœTaøJ û6¯ ºëçw,8WÍFÂPÄÈGŠS%-2?…"¨ü9‚^Â. ¾lK¡ù91_ÆâכþzŠŸŸo@^ SúqCÂ@+ª±#M,\¢j#Ìù€ªug'v=ò!SÉ꺨Ø"tp˜·Gx*
+
+ˆ¾Ìˆù“¸vh¸bóÕ=„¡žûZÁä|7槻Yƒ_ï*Gš¹ö<í7]Š‚ L@âð•‘™q{5;ƒ ³ú†¹àÑÔ=å ÔMDÜ^Ë<në­ÊU}z¦:"c½ Ñ‹±^è,˜Iá9œú ã1ˆ.rƒÞô7Oa–•ƒšK(GIøDÂksv+ë8 Øü¬ .Ї»
+NòãˆmuÏ™4€ ÝÅã†éÑ¥¹jlÀ=ÝW®Á>"À¾sÊ( ]cøR=öò¥Ä§ý¯B Øâù9LnFk©îœ‚x‹Û.‘,æÉõ]ø"“‰Üä[H ù83&óÛ˜Séæ¬ú¹6W—¦ü€¿˜UøÄLþ:]D”’Äû‘_`zS=
+ŠqÀÝ*øJzÀVû½Ðú—½ ‘ð¬Ö­BCC.Hüí9Ü'_ËàL«à•à*ßÄ¡ã*àòèµU2šG„Œl½½ˆÛàÏ`ÚÐ-¾Èr뽂Q'{Ì‚6‚H1 ‘‰6"qk¬>PÂö¢s¬µy8‰ cøà-ÖóÓ^5Du¼HV±ŠXiø.¢±kgô²,vä^)ÇdÍ%óÕ^°2HzõŒ©Êaö
+óáð¶Šøú0dåMsßðy†…ÐÎ[=ç#Ñ¥}ðW{™ì…0[”­„•á‹¼Â«ÈþóŸS 3ºd©°Ï¾Ôèøê
+Vx790KÇœ<É·Šÿ+V°GþÙb´B'F4‘‰Ë¨²Ì0~7¼iô¦¾ò_Ήö2fB)ðØÎ)À€
+hZ £%ü;þ8ô’’†š³»\PÝý~ŠŠ.àÂ`EûÑD¢Q”ù—l•apW.S¿9-G¤éþ*x£qjV=[…VC‡é½[I®ôžÒ¢z¿
+§Î°GnB¦ä‡†
+×íæl¬’èš-/Ç’•XbòñCïË7ùueV¸“F.AIËÈY`p~Y“’NJ`Õ{4äBP
+#—ÁKïa¥ÛÜT&u
+˜ÙP“¼‘\*ÛðY&P)³®Q´Çp;=&®fî—Ä!%„b­H |CGS¦„M¬:½+VÛYX–JRßC<ý<±7È š“ úd³\ ¶;ùrI„´ÆXöê<%ÂÙGqENˆ
+¼ÄÉg²ÝM®="ç—½IÔ89ˆ_T͓ƪA=wêo×p„=™ÅÌÓ¯Dä³¼á ,UM×ëzåC‚Ó* ÷,&姕°lU¬8a! K"µ‡&¹v¾=ºM¼Æ*éüOÄ…L8¸j2èä”%P4O‚jvÕfãPD¦“W˜Âû±è:‡:rê Xc'È·²Ä…ì_Î^Vv<Íã’`WQÓÞŠçy®X ˆüИâë7¥_ÀBðõã‡èF¡Õ½½éûS‰OéÑÂ^f;?GN7ÔlTÇŸSšêcX¬µJ’ì}èˆ~šæ+Cdw¶ÂªGÌ1ÊG=z*Ð0;ð²?Ö溰ñâ÷Çk×¼i/¼„ Ï‚¯îG7§5)lîÞõKQ屉ì‚ÔfÛõ«h|§Fѳ1Þô¢Ú\¼Ö úxXQœãn­YO÷Öà\Àhn˜¡Ø"×Ú”2L;]¡çAÆÖ7}iõ@yËX¾Sð…áÈÖôÀ°Ádf»ñ3kÉ!Q0·š‡Ÿ uœëȺ‹7ÏÑ0ÊÖCÙ%‹û:°½d(ç€H¿C ÑVêŽGÌWÒˆ>÷šgðUº\|,
+¥”šŽ%(äxFk¾S§¢'=¾‹PI,PÖÈžŽŒ;¬ƒƒQ‡ã§ã2 ð€~„cûÓ_®·b ö©ðqhÃÅò®Í<YgàÂ3°úüÆ‚µ. zÜL9 7­–PŽ…É^ÂGòÑ=IÌ6
+!?Ð&‘*m|í×e£csŠ¸ËÇiç¯N<IiéóŸÓö¾ݽH‚<ƒΊäé]žR,£vVofôç.©!º!2GMRÇùÊÈoo`íà’Ê?uã 3Ì›µ­Á5 È!ñ4ÐýHÀ§v>•ørbÎŒ Þß>')$b^.#ÛpÇ´PY% 8üÉq`©Ë
+–||ˆ%ÜúÕšÍÆ¥alÃ_^ÞshZȺgÖ.»è §"¾cýŸIOvCì „ªu7ÄtÀä‘81¬D!
+‡æÕ ¦¢º\ògµ<µb*~”S¶6RúÎqã¡Äß„<$px9?†qâèº2fÅK *¥Dstº‡8ãñHãþ¢?sÑ—O ɉ#Ë€]W:«†Ô$M·Mò\¡¶8ó‘Œ6~IÙ2•
+7ƒ¸°¢
+m¹§86*Ô9ŒÒ
+¬L?eTìëÄ”¢Q€¡dK‘=4(–É·õ¥+¾ÎÎÝeØþ«ˆ-_“¶0
+ÛÅjp³ ²U~µxŽe·i·ŽèN>Ÿ‰BÑ?¼-º‘Ïú·—k@”#úuO8Ø
+Á£Æylµƒ1¿†èS£SÍWjœÍÇŒy[ôlÅ}ô«=Í4¾ƒ‰æèÚÜlò¨$S{Ð( ¦àGÍgFÚëÃ` è]b”
+"JxªØ9Ð3Ï\)² ½ƒúp0ï ˜öG*Ù’°$†;·æH¦érg 3JªñÇu¢îµCO¬×1
+ GÃ/‰æNÒ¬[ÝÙV˜µ8;agÛto¢´h»ÊGÝÈùm‘ƒd]MÅ™ˆê³è²'Œl´*Çç«i èE¿ ±Q–A¾꺀•ã&Ã,º¶ªç ›2#Ÿ™gàû9äm8?õiþ:GR•1‚,³CBHfÅ$OùÅ+2$ü<ÞLEðñoïTâß Ù›`È{;þkj
+b žOÝDD>hÜ ÞËèE…v'ŸÔ¼4‚®¬.‰¬na{Ñ!¿ý%ZƒÆÄ„Ú©/êh”Âú¸¿
+ào$ž›Á T‡ÀÍ–¨&xèÖŽ3× üõË‚È݆!ó·dÔ>w†ˆ84žmkй…®åOõˆ‰Zˆ=ÎBKäq>u5è†"$#Ò¶Ö‘ÏòTØnPð£hj`ŒK"x–Õ°»†ÊIɔů†ÀUÉp+'¦Bí3)B¬ëÔŒœ<‡aëüÚ…,ìãµóJî‹Âw¦‹è냨`…"à…ër&G4PlX΄bùXmï:!8(6»´Dlûʺáªq„1‡ÆÐØpŠ˜A«h$²ʃƒ «F›}v8Xü?ZrG\YifsTúÍ‘ìOÙz9ÄžÖaZ*I™u&ʸåñhõí·U®„¸îÇ¢€†°³è§c²¼©Ó¿çvènkb†zÌ´cÔÚpÚ·CÕD‚9"?H2n™)!ϪeT;®Ù}E]EÅ„kÜûáÙŠ&-½ÍÚ2‰©û**ËÕÂüOÊ6Ï[Yá*Œî³—ÿkˆÔ-Ÿñ¶±*
+ž5ìOQ'¦x+"
+öÁwX Ø]Þ‰0°¾€÷ÂÚª ‡ÀRÐáe¼®"´l{ãß¹?ŠéÃÒla6Ë«–' £Liè&^ª†gŠâ ³Í YwÀ$ˆmãç?¬ö†ëLP|s\ŸÊ
+WÀÑ—ig2µ«Ç{j{žb$K¥/9»¹‹~Ž×ïïd° õÏÿØÿúë?ÿ7y5|Yÿý—Ÿ¯ð}Ò@USþ‚[¡Ç1;vÿÃU†=üˆa«Š<§“"Ê:_æw3®¢ïKÔU%´Lš s!Ჸ…!VŽuI8žN‰ÛÚ–ÒüLÂAÆ’ðãM<°hˆp1$Ú½BŸèì`ªr»Š^¤`îg']º¯ ™ƒÈv1þÿq×þÜLóà€¤ö¹¯rKÏ„?ñ¾÷’hUŠ|”‰fH8 [)ÂäM[øÎÐÆï—„^…¢Žìǡ莶ErVáBÕuz\ó m¾n
+¤Ù–~8¬PPÉPCHf^Õ¢XU£&ËËM“–½2Õ‘™ä’OÚäŽÍ¸éb‘‘Ê)•ª•õô;(¾3(É@‹†…k†ò¯W›1‘ë:–ПNL-Hš¾ éBêž3…’ Î}XSehƒ4‰Éy;4âÚwkh‘0SÒt߯ÌF-Ú¨)P¢{jUªD$ì°èµb Ò
+
+WЇØíE[1HëØ’ô×,±þõ´ÿí@e;°×|-®¢¦LÆR»ή Ÿ,Pé
+Ó$£’çRRLc)Ÿ6áâÀ>EI°9Ñcp¯Ð(YŽòUÐ鸂Fcq
+Iª>6ø
+:õîvÜk C[n%x t:îÚ–“þþµwKÞ;‘®IX‚Rö?鯘Û)CÇ_ehø †¡}—¯BãfëÃcÈ0Ÿ0„&cPNhpn „®€Ò"›° ¨|}æ‡t¥+ô2‡ ör‚fh¯ˆßvÓŒp3âxú Ñ@Qvˆòõª4! B¤™ZQÂgñûö$%à;#,ŸyFK ”œ¨ú‹V92sá¶CHA¤GÈõÊ°ÅŒÒ&K£°žN¼cµu÷GHc‘à LV,«€3‰ÃÍf•õhhWŽii©2Þj ÞœPÉýñ; %:µ ›Cp¯px(c#~ˆ^¬ hÿ>éϸ(,gÄ—JÑag‚Dtˆ]¡eÔLžàO趇ÝSb.É”ÏÖU ,CgJè´&.ÕŠž
+„Ÿ â“=Ʊn=S‚"µbìž>ƒÏŠËÙç6 ð (¬YŽÊ]*ºïvêC¶?¦í:„Œ¼y9$*͵¤dßA–ù¢Bþ®¨8Ô”‰C BP+ J‰î0“/DÌ­Äs˜S.¨kpé_BèÊ4Jfºg·A¾czcÚ;#–¬te¹qŒï­œ`éë ÏQ)EÙv€ü¶yˆsù£ÖöŽ_¿ÃÈaqJ"m» µfô;7F®mô4 =Ó·øŠ#± ߸ª_ÿÜ1‡º RL4?Ê==Àr¤¹Zv¨véÙ÷ý}[¾<~NÍ#½DBÊ
+oˆ5ä@* E a-ÖDWâÆ3Ì0 E“„‘Î_VsÊßÔÒÚˆ´ÖñqlˆÆ-ð.ÖWÏ
+Ôßû÷â^#árÚÁ·…Àaòé8Ðímz°D+"æi7Gç:¾)çé Yþê#|Ý|ZìÁ9ò«CÕ†›­.†ëR¤»îßÛ~ðIÅ—¸ Š_ÎþY.ð%Ž§Ï¾/+0@„Eš°í÷gc^ñD8úl$Þ_åƒ6ˆöÐÔ%³ï Ìä!ÝÀ ÜWÏ"mrH+,7Œl ¶^Ä 0Ý^ãèGã? øŽw'ìñØkôw¤ˆ-uI°`P(üzyÖ"ÃìÆ´÷Üù“­Ý/òX=MïÁk’º5‹7Væ¿•š>å@•7»£±èÒH”§ÔógØ?ŒU›twë)vr«{DcÇ››?ªñï]Þf(£^‚ÔÔkƒ–UüŸo¾/SM˜W$àšz~;,!óÕÊ>êÏËiÖ3áÍ3_—+ë[Ù†L[mŠ|¶Ã¤, }ç{q~Ê;Ç‘,±øŠaç¤ÀQÌz YLýz<&Ô¾Pü¼æK×a&¸¥›†)*z†fQŽ·é8) XªnŽ©èÿ†A¸ÈÐð^ƒ z¨é"%ïE}×dð‚¶^^PÈVÙ =¤Ùw8©ÁA¹ ÒléÏDÌ(AÙÈ~€¬ƒ
+MçÙrž&ŧïh•ró»pržÚ=ˆÏ •˜ÅUô3‡@
+«Ö óŽYˆÌ;X„ÈØ-nÄÓªoÍæ:¼A^°tðFàÑ”½ÝeT ED®ƒŸª~ÖÊn‹ØMÉ%†f±» $þïÃÝ`R­àÒ¢E[ˆKÖ”œz9>@â"ú’d¨? S¯wñ«A‘…Ìëå@âà;,ûö`Ø`I(áiLƒˆÞ#ì=ÁèŸibôâD¦4SÁô]«pÅ%Lr51ÔÊcJmúc³}{«ðN÷ìTò<h’²±¹4ù¤nÖ \G‡} —‚ ûF¹¿àkƒ¹çN!&9JÁ °ÕÑ-¼Qæ ÛG0%L6zm™–Šb´³ŒÙ”E‹6±7þ:(y¤—|,˜FÜ@÷\W&BŒsC.–Rï–=¤ïyOòÝR^fùn)%ªôS,T6\,å­ç'K‰ÈG@lYÈÖ”uà wb“ý2˜ˆª`+‹A¸ZÚ†Ûd
+dÇ0ôŠöÛQø’„•!¸~´‡!"”°Jo Â7ƒ¼aδ’Úé&@h,A ¦Ï–òºd‰#_¼‚!Ò7ID4kzÃPRš‹Q¨MÛø߀†™æ駉bàÔ¦IŠ&SyW¹Nê9÷HæX{UÌ!,~7W‰º}„e‚Œ 7ñ½D Š I>@–;=
+F€~bµg>‡GBI02Χ8D¿ƒ–m«‘[‡D”²ïæÄ<aÙXší©Q±…"á6 ƒ7#|œÌtFˆ+;8»º¤uZ™9¦|?Õ—ŸÊà =òÌu«ûÆp~ÕÇ97­³ËI~|nß^D(âIní´§¡Ð8žÈïúk9àÈŽ,öÀ„dç
+íÇŠ§TqQ- þ•n ÃÙ"Žeá%<ðmA(3·;ûã Óñ‡4B:Z< ~ÛI’Ö&îýé3(ÜÄh¡R_ìÆRÏÄÖŶ}=Jì‹Û*og=ñ‹m¯ ù!öœ”†¨ú0ßTmXŠñ*èîšt¯ÂÒbÛÓ#äzé€áaÖse£Áã5êdÇŒn8 B‘¸^ vHVQ²„q´}›ŸdªN0ÌŒqâmo¯O9HYsÑPRØ£G¿ JQ‰pÄe¼@ÐÚÕìþ>éÏ3øí£Ü'×Ñï·|ö‹‘Ä &¦ŸÛžŒžN²‚ßãÉ/¨B3îË{ü"~Ÿ©ŒÃ3ßÍ/
+‚ òÖú Õ…Ñ{d(—s=ùŨX85!L^|ð‹'ÐÕ/
+ÃÉw@<úE Ìÿñ´tö‹@˜d,#übTó“yö‹Q ”Ç÷ª_Úô—fûE!ò‹ õÁ/ªéV„ÇcŽGÊ\ý"ö±uoûÅ/–w5jˆ÷ÛŒ—Ir7DOà;ð ÌÃÚ[ÞÂ[úþ[¿
+_úÝÕÃrHL¢rx0Œ™
+r߆ßéÉ7Œ™ù#f½R{0Œ7ˆgÐÝ0^AÎråíû °ÃÈÓêÒAÜüâm˜o†Q=(­Æ«Œnº5Ýã&EÙQ¤óè¼s N.\KŸ‡)ß cllˆˆŸœÇƒaÄÌBoLx®aR&kÄå³3äÂFø5îÉ0z ›ôãG ›e¼ƒnžQ ÑDŠ ®gU&‰s¤|Ó5kóÚTÃ(®kL.2µèš=ŠG“'ÃÆ>™F@…F0]tÄ7šT8SztÊ5"AM–vd>™F‘©F…}-ÇO_\# EÀ!KFçœsq·ô\£¬7¸ÖO®Q'±Ò%7™G×5ê]yªŠð]㟘Ô\£fŽ˜pÚð¼Ê"Üe°S{òàU˜8TŒªÑ¢îïqÔ.-­JZ©$tºõÀ*I…'û°!̓ 8¤Pøȶ!´Ÿo‘Z¦© „¹‘Çf¯ צ•\èTœ~
+Òç° ¬šÆî©jØl+>ûÚEÐ(ì„Dô€Q¬e—pjØ¡–V… ¢¤|°k¨ø«áçv<¼y¢k#ø¹âd7vC rLe§\ÃØwDî<'5´ I{Å>â+|óÀl ”—Í›Ócåö”ò;±Ï"Ñ7Yã܈
+LõcA†œžœ¢Í1ÕV“ ï-Ψ3ÅX¼Œ¶¼Çâ
+r;Ž!c‡; 2Š©¤ð4œÐær£ èû'º<5?ÿ„
+a£÷Ùœ‚e’lïE4‰~mé{x ]™h=¡µO2>‘~Q<üôþ@Â"Q ÒÓ~bI@ÌçI€oñnàÌ”(cãWŸ‚§6A ôBš²-¢ïÅšìþJëûT ±sÏ£Œe¼%µÈ?5…qËAL¹úŽE)~Šäá¬pºñ+’ý‚|ÿ¤¡¿²T้%P›3"—,&ez’smžIÚ ¬?²ˆÛrx
+Þ’NõI¬p¥€8ØÑæwêýþ§@–åñ6±?ä)Š=zªÉõjGBvÉ ˆ¨§@@ÙܦW,“›§ÒD_ôø||Ö[ž„7Wf«zyÊÜó” ºæ©;è6‡ûÊ¢ ®7Oéåøl¸y¦3Í·@u›ç[ ÒöápØTËB÷¶;JÆžÉ\O7u­qǸqcÈyD7PÉJwL²<•¨
+HÂÄB€Ô£ºaê6^˜ÒTÀ‘©DÜȹò5LâçP+§¦ô.R­‚-;ààŸxt¥)ØEֻʭî”ù_a6_™E„^/YŽö¨‡nÇRPøø° y6ü/ž¡—‚ZêÂ\•M¸¬>å`8ÖLîB+–`ë«áè¯<ÞP~“к¸aCðh"5¶aèêîW=l›²LWªéŽ1²%*ˆ@¨¾ÍE§+¸ÑYT­ ˆ#ÌÛã¢û³YŽI¤Zë¦v°ˆ9æõì¦!À:+ø°[M˹*¼â®ºxýt{ù†øg÷;Pq]výá˜%‹³¶½’N.$Ǧ5AL1åX”À3ˆH8:Û—0ÁX±.­j¶ƒ©•iz‚df¡|p3ÂAØE²»H
+C=+U.»›è‘¿=вLN/’‘úá\YÚÉDà'Ú—œ—Ke†’E¢/ì½Õø½€R+L™”)INnšwë¦#k(˜®1´àJð^<¦¼lµ»°¹h>/f›P¼®„eùI ¥H‡`Äã„CD¥ñÎß­ö}[Vœ­eÆ¡oÎÒ™Ê-ì7\5v/¯Û{}Û¾ÐEÔ7„9Mê9fÄö¥&²(‘sœû¦ŠÑb¡Z÷In€|Ã(é|1ëʯ0%í<zê1ðÁiçð—‚ÃÂ’dÇþÞ{ù°¡!NñÆäOýC2ò"ŸÇØMˆŠ­0¯3ÙX%i µÍyÌRÖ'Uo¯/üºÉÆ[£jUØ¡ëÓŽadxL'}Ùƒð†P5sUšËa•›»•ˆB|"’n–öŠ;;R(»M ÐxÒ~Æ3.ëÙ gÃSkö|˪–AFä=ßro€£rË¿O¾¥ŸRÞ¦hÑŽBX $:§­«΂ñÐÔ“ZŒŸ`ÎóI&
+‹˜†úÞ ¨&RmêHæ¡
+mË˪K¸2ÃhÆ é®†×<ÈóbÁ¡îâäOÍ@À>¿@S–-‰rßÇ@Ý„(ÍOÜoçCd®Šîåø
+6‰£Ë
+dT šáY¼ØáB¼F^O•‹Æ%œ/õ†q ðÀf v+G§DÅ·ByùllmžñÉQÑŽ”$@—ÆÓ1úRâý@ØVŠéGÞˆHäõ^[ÞEƒJÞêûKéëÄS¥åön(Q í›¸Óç(!úZ°Pþ!A¯ÓG¨Šs3”z¾sÅÐ"T‘ÆÚ)“à!.äÖ¶yÚht½öiËIàýkÜn¡èˆ#›íµzôˆÎé?“‘¡ì Ò*Û²ÃðòîR`õHY$Hæ4{†•¢dÙ<1ÓèËÉ#â­4ŠCªðý
+jØ„æÁì(·W@´W˜½ÿ>W™úPÿéÑß! ¸¥'åp9~¾·ó jݲ¢W>9L;œˆd¸7‡n"¶ˆnlÄóŒfá&
+nÀVMl×¹y5”m#¹ Hýî.‡U„f»ŸÓš"î•}² ”c.‰Wuw7„/6©³\ÍEž1j2z·&Y,Æ)Ê'P]µsL§ìq[tôž‚õæ³~Ù™œ)ð2÷¾¿ôçÅúMwðeüÓ*¶ub›)ÕFA~ˆ®bPµÆ´ šê4{ÜŽ!"JpW)æ u
+9|M's‚;‚aœ§ðn+‹¶_¬26CÏ“ÿ—íÁʲ‰NwŒär¾rFA3‹†3YUáYÛ‹ (°¸UîÌøûÈËöóuÂK«õ
+¡Uô:mÙéˆ( µÏàóS;NZ)Nå‚ †­îµÖ³2íùiÒD%Û“6-H¥‰ðVp§Õ¶„•h@h*šlËôUÇ'hk%ž})Šú°V3ì——¦x@ãg²sÂè”bã¦%Šeèó DMhšƒPKqÑ$è¡À-ÉÏõÒ,Žö…ÎŽšTXƒK ROðŒ`y ›ÇR´<kd 8&…0ƾêBÄ©+
+>þEO X3UÙ!NJÉ?†Ráiy¿ó:¢(ÊŽa®ýF(›k”Ï6"=h_ç
+ú]]?^‘`9Ô¯#Øýóöõß·˜qáÒ&®®H "”Ðë€hgߊËÃ=×tÌy¢ í‚ç<# Úu H}­kƒÒQü[ÒÝ_·¡mL9³„l‚¿\R‰Sˆ*IHŠRÖ) Ä5ƒÀ…r>Ëu]!?ô%Ã
+›"¥ä#ôÉÊhDŸŠ6Þ,Š Eq1´ ô„ÍRC‚X#lDðFà8è<>n;ÜæJ»Mü÷n_Êìªì`ò±æA
+þÄÒ^þ tö¶"àjØwÈ«ÛÓs'±ƒ âIVAâêC•oäI nR°wðÁÝ1(,k×´ýê¬t¶GèÑøhh{ÏW—,Ê¡›úßÑY¦¨”åfÂVc°¡Ç7‹Ôv¹› Ù3†•ÕšÂ…µÉ¬?ŽN–2X6‰’xö±O‘æWñioȺ7FS€ñÌN×s
+..‹‡áõ ÂKUÒ¹M¼?ŽuÞ\x
+?Cž;õþv}êüÇ¿­•†Ï‡ŒäáÊ¢™ ?̧§7å5¼[®Jdyùs¡õ˜I¼ŒùåÐ9 þ€Ã©aG¶|‚—ëpŽa®œuœo#‹Ï#®´!×WiØEñXˆ’ÏÕ¹ì•jL8g6ì°z=ÈnÁÞé±^O7G#VK/X6Ãn1N5#°Ø_@WƒÀ;xÕœ-†_„<Ñå÷ã§^©DUŽ¸1,ÅFõ€ÔÔÅÊà­ŽEùÝD6I ºAäTqAaAF¡éâgR¬:†öæ­|]k‘Ôž­¶„«€¿`ìüY¼¢
+C¯SM¶cx¢X ÷+v<á¨=íCnÉŽ¢HAðeOç´Î1†¼Ùõ2ýÅXåÈèr|zE\¹†(¬'Ñé[©Á`BW#Ù×à—áØ 
+^Ñš\võˆ½¸\I„jn1î9sÎø/ç~iy—AêõÝäŽù•iㆮheÑ1 S?‡™ì½Þí"zÿ'žß¥±ÿèƒùµHiщÜI4€y1x¦³ä lvoäÑE?Š"”¯N1¡iS»­äÛ!¸ZY^p-Âo0^V
+6´àoÓý®…ÆÁG@_!â{%·,DQöyy
+dY™¨ßv_Bâè€h9ëã9ęέ…6¿MÅ
+p·ÙøTôks&bÚؼêôšÄC*[÷(`¨¼ò¤—@ØÒaÕÙ‡_Í l…«Š”HΑ]yS Mã©ìÀЕ€Pµc°H²¿ø€×ÏÑ ±î^ˆO{æð)ÏŽó1uÑ\YÍßùÖÁÿÕЬtÑ>ÜHðõÔ ¨Nç{ò§m*
+ÙžK¹£¼nÉÞãÊçAÉлC "?ȆLÝB^êŽ/Yî–“su˜ùÜ [nÖ %à­ÑÕA„=ƒfÖh‡©hF*QrÅɸœe‡SRúQ~·\Ëh‰®†æl€U$¥AÐèûo«‰EÆF’8ú¶$âc ‹XÚ¡h•`0ÉA@ÜJ*q%Ð5c0G:Åf¶²]²Çlä÷o‡"5¨ËÙ,-²Í /šÃ Äòó«EbÞØ” ›•DåM†›·§‚ùÂíDõ_ºôþà®;ŒYŽlÙìÅji¤–sø’&„õúÄ– .C¸Ø6ŸŽ) Ø¡äulÒeíù.³+f) fH›Në²/„K6è¯Ðù±
+àÓaí-MÁ/é!ÿ€\Oš²>¥G³t-ω/µâý×<« ïä ¾¤¼vPÓïßEbêÒ¥N‰ÔáÚÃÇ0¦t¾Ö'Yz¡ 8ŒiCwØï w³h\Ÿ~Ÿk ç|Äá6×^_åŸú ‘xÄ@.ItããŒAV½Àp{*ù„èŸ_Áòýá+,Êk‡'ý¹ÝõG}ƒ‡þÊQø ¶°¨Û£æýÑÉ ÔÞÊqÕŸ€a@þüTOâb3Ó§¶ºÞƒþ„7KêlÒ1‰ó'ˆFµË3b%E¡W#` P tÊö€y¤D 0ëwÑ à5:cM_,¹
+˯cQFöq€zÉya(±ÌÐ:çF¯(¸—„Îñ'Ù£&á0@äÅ„'¿zft‡‡M„+l%†cÅ+Ø69BTDåýc™øïfÇ”—.“% ÓƒÌi0ÎåÊ®%g.<ÄŠRØñ’ë„z8´Ô•FRÊ~ߨlƒÎ4w‰ Ù,©LíÌörPÎã§,D1CŒ˜Äjxÿ’(?$£ëPËc.›•4š‡•æè×wÿV¬U… 'cb…d‰<9QÄ°ÆEgù8å,ªÆÈþ.ÄŸ£$½V¢îD¦Íÿz D¤SàÂj%ð”2AN~+GÎ`ôîOGpÝJ¶¨NtÐ)ˤ'W–¡†?ê¢ÄJGø0ïO}*Ù«—Zœ]X9¹(ñ*Z÷eÀ¹l??³‚(c:K¾ŸÍ!Ҍʯ8DáMäÃî^âÙ"f™à“l¥—,Z;ñ¥ñ¡¤éñ9,{V6mYÑ0Ü¥¾• xò#¸Õý\Õ>RdzÝ°/pG
+
+BÚ$ rï$t
+ ÓØÒ-Æ:ÐVe
+Ó¡&¶K;ÇF.©Ø!°åÀ<ß
+H‰Œ—Mrd¹ „O ;Ôz"æ $¸œh/gëtØ+iéûûÔV_[Ñ µTY$  ËÞjM—ËV{IÕíñ÷[.V.MI\Ìr—
+ØL6•HÖˆ¬O‰Ïf5éBTm™†…cŸ//¹À›òÉR0Ò !¥X7™7¥)ÑÅR@Zâݽž’ü YW‰ÐTÎ+õöœä’xu»‰F‘q8ë–ëÝ«h¾Ðøª•rNΡŸS|€|)ÕÏï´rt}š]_»LS¥œ»Îû8"tV‘vout} ¤®ÉÕW–JãºÎç2eSG®[iIÊA€Vä–ykFnËQH5Õ赞uã¥î'ý¡Ss&÷ ¿ÑŸz•äI[b~é1–zY×άðÚO’:nª—s âHÔsbŠ¯¦¿ä&½Ïç2ýx;ƒ¾”ýýÊÁ8ùNnâCÈ¡<ðNS»ÃÓ\¹dL‚¹1töÓ¿fòí©rÞ–§/u
+9B½I¾é€ˆŸ‰ÑDËÉø(‘òŠ¥…°jK;C«¦{ûbð…~ÁÝA¡Ê¥Uú›•áÔ8œ¾E÷˜óǧqN©aLÈ9A@zˆ¦¡yÑÚ0ŒŽ1/ê (¯õ]éz½‡¦éëEïß©è§k…²¸ÄŽ½ÍTvz\"uTAôGñ_AðÏ¡<.9$ç1 ^âSv£¶¯ìÝÂÃðFŸ"F@S"³KùÀ'Ρ†õ 
+0»SERoKû:c,|+ÃÌR†y"¤AH*†ÃÂÔ.‹¶j”‚űîÊŒ«*‰ÌØÝÞÓ4 ̽R+CÊWÉÂV²¡£½.á°"0elÑÍÐx@v,&ëÄ×'”ŒQ?ªöŠµ&ÏPw¸•aKuR¶ý¥¥:Å—pÕóUÎÚÃÃù·ì¦Æ!\Ê>°ŸN—Õ˜ yƒ2ÅIÑô=SÈÀ¤é!jÞæ„ÏBèLËJr|ƒré^cÿ±Ê ·8§ö%‡S¾üÊsãŸôÜ€‡Ô<·ñ!Á:|)ÔÏïpæÓ”ÓÛh²–ç}œ@ÃÙ³Öç‹:B_:š Û)"æ¤#9³b@bødÌ'u;›É‘$ÌT³Äí'<ÊÑèp|v:™ßSÙ_ýñh0äÒRv>‡^®l¹Ä\†ŽXB±m '¤)å#`$q½)[’˜Æ=Û¼* iø2%lå¦ðÿŽ°Ü>„qŠŽ&®¼îŠ±òqån(1N‰B!\ŠÌ„ÔM@_
+ÿ~!ódé×(ó¼Œí5 Ú¶AÆçRÿ|¹Å®ƒLV2Ò…7‚J²“ "œàíËŽºA$˜; ’d¬R¯ídkRùlGW`í<crìä¡gkIæ"ï±ÐénÑ Jîi›uÜ©ã¢k)¿ZTÂJ‘x­;7%UK$‚f,¾°nT¶A[¼"®((ÔÊãÌ;v°I@ªOÿžœcLj´Àt‡ù:“?[-qø^Ò¾ï}‚HÍ%™ÉmÀ2à} Ô+k0Y)¼AAåõŽ}~´vbÆIžÏ)#ÍDCÓMD'ÜKÇ2Ô…hŠ™«Ä´xÕÃxäØ1rŸŒxÝÍ"ðÏØFRý.(®ƒÀ•
+ÞÊ$¢5(6¹T°v,
+–¤y =¡ì_ ·?!E(Ro)ë„H0¿Àâ=õ¿ÌÙoбⱠáHÙIìwA¯n÷ÿðsn¹½Am )e[bc…ŠQ+ÂXsO ø›ðýè{Œ’¡ÙP fËRwB¦ãB¤¨ò€DÃùX`úrˬ~<!‡ñÿ9oBÿ%­Í†>ßÓA›êRŠ\PRŸê3„/µ<j¨Ø-üéÂW• Ð_ôªOm„4(Ê‹‰›ç$œ^WÔ—WSA¦¤I@ìBµÍ0OV4h;½µ÷2¯²+:Ú0Rt j˜…ZðÔb@H.fO“¡Upµ¼@C¼Çð´.2!9È©LG+¶¯âóäµ"E¾½» ²ÛLužáÉ^‰-[Ub‡m.L»H…x=æ*ûóªg›©‘¦r£AÂYåEâèÙ–=ÌxY Äz!SD¹ìŽ ÃÀå’w­ÂIp?ÔßžHÏÜç± H¼QœË¢/Ú.¶S= »qhÈ“€<ŸÓ.Ú‘~‹TÈŽ†h•«ùeB*Vœ‘V ßzÉ
+ÛÄQû&*‰#cÔúNN˜Yò@‡-Võ˜îp¸ÿò·åƒÍ¯Ôra†AøÓGƒF}qÎèÿô~¢c؆0[i
+CÁ©ÑN+žÏæ(¯+dtÑC•aÄYq„CaS„ë{††`e’ö¼ŠEŠi~ä+÷Æt(çËž#xüWèÅÍ)¥q32¸B‰IP™ÂÏ ªy‘RÕZâåû¦lBïC³M˜·TÜŠ>áIÑíº¨‰u ¾ 2En 54{.äó¦g»$f‰©µ­sXUH{¨ø¢xõÈ-ûÙ/›IŽ?Á¼CŸu(ä“™y4¤“¼†~Áyu½¾?VU¯4I–z.siô.;=•E™Áà©‘%c¨Ì|ûÒ÷g_q×Hè7Ížù”̪iô(gÈ»à xðS•(¥u?†è|UÇsÑ¡L–yj±™Ã£ûïAtŒ®y=wGA »½Ž“Î;Ep‰ _Ó Qg3bÁKçÍDPmLâƒïÂ5IÒ{KpaP9
+<Uîóƒ?¬[˜µ¹÷Ä°=„‡ö¥Ã¬ Ô$Å¸Ò ˆ˜«¡•˜¶'}h·’°¥gRŒULÌÉsÍ@õDÊ]ïs<-)Gƒ‚¨Ì [)PÕ{NbšYÑ’»‘&—™²:î×òý`]7•½L<€dqËñƳ_Z Yc—øœÆ<fL0EG¹{ßbí7ö¥õ€Ø0ÁSO¹û TæàÔþmhÚ†Fç0Ïp¸o|&yë£búŠã(N_‚ëž tôQê„Y>ýÄ[Ny$bš†é‡A¨èë âݬ£ÌÒq€Lº5~ªçµÃë j˜¬qžc«gqÃÓ)kÜ:ä›ÇœÇ g´‡âˆ9¹o$W|QËIO2á•n—æ~íˆbwº³ƒáæBXÉõ|9_5f.g’Ÿc‘‘ÃNtïðÌâ†É™çX`ŒHµN8sbDàó*¾Uî-j¦œ¾Q¬ÓyHˆÏ\øzÞg3;†žm]¡\ Þ¹ÕïS+¶QÒ‚ÍÓ¶Î}0ñÁÜ1bS€°gÌš°Ž HãfÒ¢¢K'jº²½.ÔhœVDZQ2Ô9Ó¦q7Ö:ÞÄ…š¢×½œâD&”d=Îaê7LrÌ^tÁ.U2c9NHÆrà›RI-€ì¯ªÛÜ­A±©‚þ…ÏTÊŒƒ©¶zÙtcFëUR©å¢5Ó“Äè5Íé1Áñ®N÷-“64Ô–Ûz‹C!—n®³q/RbàŠ3;xÛ7òVj¸¬©aBr ùͲ[/.¸^•éäìWnŽkš5˜ ù|R¾‡ñÐ|`ÁÕCŒƒ‹À4c|€æryW¨?î›iíøò™ƒÍõ—³ž“£é±¡ë­­»kð²÷¯‰ç a÷Ÿ·tû×[â…:z»áhO\¸ýˆ“Ñý³¢Õ~÷÷·|ûñ–o?ßl]¤ápÙì8ÚøûMnÿxCˆXµ§¶K¶Õ.W“©Á‹…5bçAdl¶ðkIû渂¾D %IÂ÷6[g ä_·‚¾~$¦/o¿î$”ˆ8ûFDÓÃb²¬emp27ËlJ¨:F¯ª]Wt‡Y`Î
+ùš"|¹ÁJ´Fã!KVû« ÉÄ7ÿÛlÙrÑ0à( Þ‡ðldå öª•èœ…ã š‡µ2‰ý ¡
+nèBÅ~Æ\0
+
+8^£ *µfV|e':gá8ˆæa­>C^ òT òI°m‡Vaýb_É÷ Çq§Ïdö*5]Ì
+®$*Í*cÆg«bõbe#õcL¸`<$(ø
+
+(^£
+µf|!'8fe8æa¥>C^íñDíñ9˜}Ó†¸mC¯<¡9Šg#ïlíWI-,[¬iÖ©¥G=aÔ̼R³¶ÚqYñ9ô¶¤liëˆ î!AÁWPÀñMP©5«°à+;Ñ9 ÇQ4jõ‚ðj§jÇ’ ¥n­vaýÈÑBõKZ9Ö7³L¢a5³Ú’“µ't,_
+^íñDíñX¦Ó(eÐ5jwÙoôŠE)[½nHPæÅ´On7 t»J•švùêcÓÔ¨Rš³fâmæ¹øžOf®Ô4mÛ
+qÁ5÷­‹”Öpc%lÞº%ÌUÏ» ƒñ_ð
+kÑ ²&5Çò@‚r{cØGãêä’
+ªí¨ñ§8~},êôbðjŽ§iŽS
+hŽò¡öˆÅ¢lÈŸ`‡*ŒòV¦¾k¡ŽÁG?
+Åûú‘À¿ì·çoÿ}ûî7îÅÒL–­Bëè‚´:jÝê,<Ç&9ë‘t€‘>QföÍÜäv@èš&CçÎ Ö$VsªmœY[!~ž; Œ$)%÷Ö貟ŽWÙf™+ìíû¥úÀÅ2MRîÇ9r ªD{¬']Ö&fWOc*‹ ¡‚áåÛ.½VZfç6K¥7F©äKiôålÄÓóI¾ƒzÎiT=/?78u’½œ"Ç!q@23žžù<¥ˆ`„'ïjߘ™•ÉËåÈr!ÛEéäÍ/vÄ(I[Gìò!O-3}ƒh/³¤\‡ˆ{ š’¨´^/q QJ¡ÜY½€ü¹¯EÿáP¾>3¿ëÿg¼Ì‘ì8’ zÜ2…o¹/â(Bå hezĹÿ<ψl³_•4H‚½øÏŒŒÅÝ£äì%= Tø‡&ø¯FžFŠd×A¸b3Æ¢x-tø%Wª+éÉÕB
+ä½k
+›C:V…¾ÒÚÑ6S(”½§Oo@=|„LÓ »ªçÄÆÃ¥=|žŠÒÊó ’X:”8!Ä}Õ”ؤðhq²º¥j猘ÃHL6Û=
+—ä´>RiæÍÝ ~‡$ÈEÿlH¶‰cÄb ƒ@FµP´ã'~#Ù{ì>yŠŽ(Ë”]!»OK )7Z»ÃÈÀç
+´ÃÆ*)aû+ËÂÚ™|DN(Éjî¿mô¨[ÒäøE£Ò„Ô<Œ`Oä‹ 5to¬˜‘Ÿ–+ò« æ?ª•6O\1'¢`–G‘6Œy
+63÷Ën¤ÇÉ÷ ’œFsíJ† ‚ –ËÒn‹ç¦CÐÇWÄJ^kÁ
+ý…Š@Ò«3A*«µaúÖ´Ç)SÆIýt r2Dq-ŠŽø–ºãˆ@iu5Ôûý×1yèÔæÅØCòJgÅr²=áÐHçpL·A/|–-¡¨UHŒR’eQ]Az>¨÷Ôq›9sÒñtSšvÒÀËuÙÌ¢nYŒïÚØÏ Å„íæ ¤ T¤¹xPft­$××O«3iôNÎôô#ׇõcÈèš‡× ½Ñ(JTMç<é$$´Ë0©GФ˜T*"íi+̯k÷Ù—Ð; ^
+IÉ­£ôˆ,MF=ä-íªv¦k!ev4?'‰häP­ú¨£8¼£…É^…â â3/ö^Ô'Ÿ7
+ï4Ú]B> „¥%[aÜÞ_(iLL2RîwZ¬2Sœfw-Ï…*kUUĤ«ãz°=@à`U‰ ßI¾è¼òw±’”ôP
+O2ÓÊÎÁÖÜC\ZGuÖ‘%מ~k èÜ©m¹ %ÊPËÃ`|t¿î6¬ÐyðoÓóïoüõ-
+;ÏY„›ž¸®Mñàs©LšÅ
+!bFRä1"î'ò0aA¸|’/Fb »ŒáâÆιµÑ°°ñ/Væü}wýXù§ÝG8…eeÔ"îb^™óŽIöFLXx²ƒxaeÛyRdÉñ6“™ S©ÎᲦÛc,zC.¿
+–¢`l¤l¿?q&ý°dË*?¤ !”ü*–6:˜Õbì±üÃ"VŽ¥ˆ™(aV´m_uAva°sØe©¡ÉâÞ>‘£ÄˆÕäˆBÑ€MþÎ hSƒ¸qˆß„a [Nðüt2ÊÁOC=2 ¹ä(z3
+ä3âæ9r @Ü율sPKfÔÇ´=ßY7;Å9Ðêîã7’;CÞÀoºhÚ†x‘ÉTýQ‹'éÐ}(A'fX¡$q+ë
+©˜(å ´EQ/ë62AØ-Έ³ÞYɲâÞav¸ ãþ\·à»œ4æÍAY—aRÜ®™X©4n4„>•o‚Hb9B(i$É%‹°ãçUWPïLQ††óø?ãe’+émáôÞZ‹çai´¯à4¼rkéûû %™¿õÔ€¤®ŠâÌŒaÝ
+ÓÊþ4U]­Q°0ÞHëâì=ÂÃì@ðNò=<Ö²˽,A{gåŠ:@¿¿39ï#§QŽ@k
+–pzÝ9¢-™%µ1`L4ƒ3œfðÞ
+åH™ê¬; HOw˜þÙ[}ÖÁ·EßùûÞê³Â‚@Œ¼¹Ï/Mý|©²È§yWÉ<T¶?­C!pŹ–ÌÓHT#_ë’n(ctô–æ¨ëšXÖæôÛµÞ#L]§™ˆ"ÐH¯â~( r<÷u”»i®+YÍw•ænâ«À÷(üíHý|0àj7”„"öÆ5Ìì EiÁÚúWò̹™m'РŒ¯Î4†}!T$W†=N|0ÊDj*%ÎÃc0‰.¸D™*Ûìi•H–tz¯£‰p—ļèjlm"x5x¸H@–\¹ Øš¼TòaZPwÚŒ¡žËT½¢†pxI òêN?Ìå ÒÙ$óŒ1×½Ó‘P#h8eê´–i”?w^»Ä á.”.Öø4ºÍA>ø+\u˜˜Ÿ?––Â
+‹0¬í ZšÌƒPøüfov
+œqä bÜÜÀœ¼s?Ãu)ë9¹CRüêX‹fw†…0”Ùªê­ZÈ7¥ºÒ›ùõFVÏ»ÝóÇzôBãô¤Û‹B”…d› Wh@pþU^°äµ‘&*ŸP‚² bîÖ†²æ©°!)B~›­\n5=G±¬¯eX¤ÐZ“S›ë/ˆ\ªS½íii!:°¥ érq®ãÁ3ÌjÑÕˆ:¿“çºnÅ‹6¨DÁv64ôà\OD³ƒ Þ†ü‰Ín-?Rž×¸Ñ5Žxk{©´rHE8ð`­@Ú F úùZ”ÝùJï8jšÑdT=êâ)Tây°\ëµ2¤ê">µ5…(ZÃY0 3¨fVf(©)oºJH·1/ÊÑ„0„ç5†Þï­.PurÒ4S{oEÙ Íô×lpGÍ7®­ŽW¬„z
+¸ IÀ êÕqsëZ0œ8/†Ù:l†cnx­5ÁR.8:ÖÁ–›á ÐÉ”œY/LƒÏ|Ë­š\²Ë)<ѶÙ höèMÿüŒoÉt^Y×z2U:—š“ùõÅzÊ€p¿À;»Õ=dÀde@ CZ–atáé\¾KA<SêC¤w%7ôóeæ;—]°×œp BÀanp›µ{;R ‡òËÖxR““Ú› –»–².U†É­ù‘¨ÌkM!![PˆŒM‚N²|õRÄÌ€æ:GÐ9sç%ãNwî*ƒýs,‘›PVפZ+b¼”:^ü>ÍÙ6÷¥Œî»ksuñ]ákþv¦B "Âîoxä!²–LI
+¯õÁ} tlgÆÀ´X_†)ʲÓ£"ô¨qÔõÐÉm‡Å¢¾‡Ñ4€ÒKJJ=³\à;Ãœ 4š„$¢*Ë:Š"u¨îó„F¸4ŸCŸŸÞßûIv KCüÀ‡UZdËÎq·dÇø"¨ñâ<¿,Ÿ]Êo ‰¾ùbý Âc¹/^x<p˜ZdÖHfŸòøXƒU€(ÅïhD¶Í~zI‚ÑlF-e‚ÔÏ–ô`öå‰t<™Ôd­%bï]ˆkÔ¸$šÌßË
+]Xž±tÖ&4RŸ?'¦å ¿Òfj)RqÌ1¥î5©Ur|¡Ï4®,ë€à»œØ3Ëš÷ ‰•Xš[š~é„è²€ø ‰Š7ö: ¡w]”[û>q¦òï†õX¦©FŠbœŽÀ9$TSrƒ*T„Í,Ëy
+µ„ïãÛ ¶ãA ”–q³0Uy2Æg†Y Â-ù ;´EC%@i"ð£¨;Á®OD¹Ú±u~U017 vŽ~•G> „ô
+ÖK4‡
+wJºÊ£”ˆÕ…¨óz,žšîePR6 k+í[ËÃ2Lzo:~\}hžåÚà÷¸ü\ã:- #ëA]SýçÐWZ¹ Ÿ¥ÊàÅ+[Ѻa®Si[ü0þbmUŠÂCã—ÝéôP©ŽéšMq¬÷2ŸR‡h}•ò˜A2ŽqcŽÍÐïo è G™©g²šú-‡y¦\¹=B$öçÄtÜ/4F3´f©Q÷Hv0EøqÚrBÈæaÔ×@$†
+:—ýóÁ<GÔ|æÈQ'U€/x ?èMW‚?ã:°Gy‚,<w]äføɲÎK< ¹D]çƒyèÎ9”)°@¿ˆQ„óãôv€“pª&gnV*Å“ ©õéê|Ä‘“Ÿ ÇÛØ)ç÷Õ1|.ÉêfŒ_8“ØV‘³ò„6TUnÏA¨0vº^ó€üšÏIŽ¨t'¶@âÙÄ‘ 8ò<Œeî‘»¡¼©¿T„D›â»'DzOA%¤s
+ÊÄ¥p@k
+œ«ÂHÎÍ„”Y­Š :Þi¼§
+<®oD‹>GâÆä—&{†ƒÎùkŽ5¥`På¼¹. 6lÝБUdÙ‰ÊG¢à)}ˆ^†ÇS×Ò;ÐqD,˜¬Ú’u½§%}>d;éùÖa"È2N¨ÿ:ã•’Þ¥.¹G¾¨¯'ÏÌOKÚÄ·½ç³Ð8±ÖêƒF\#¡²&›ë×5ŸÇè}ÊÞÏc† iÔ­Åž•1ó
+Ó¦­'F‘\œ4ïõu@tˆŽpècA=,A±5†(F"„¦9ÍÃ!56ÕœÅËÌ
+æj>ÌM pèJFPdžÓÜá!øˆˆë*’¿IÝœûñ76ùÃ¥LAÊ™ íàï±um ÔbF­þ’+(‘ÖÙÇɃQ*ÌJX´þ]óþG9ÿújMv¢ËÀŽÙc–“¿
+ø2•ðŠ¬BÎu.3onø¼Äi§þZt”4
+!`ÝƤÞKÑ»w'µÂ@¯Ê¦è(1Œ‘˜¾—uŽ|äÇÒ,ÉA
+dJ]PJDÙdÝêj‰¡VËC‘訡wÜ%°yÃJr_=‘V麰JûhÛÙÓN€”;¯ºAÛ wÂ2ú9Ì.௹ÞÊ‹6.N' ‡Bå–“Zí#7ƒ|:]m]%b~Øß² !±?JAÞœÎßYBïŸð÷3Ž¥]aB1gjmŒ›5ûpt‰
+Úž8vº÷û9°DO$Þºz¨F²Y óIö&ÑÀ¡„X|x €Z:sZ5<W•Í1Wd½[Ñ*ÊEù9Ø"fw-1÷°Àì¸,ÿ¾„E0Dƒc<¯ú^TøƒQÄG×<Ïô¹¨G¾{ð'»ÈÚz8^€6
+ÉÑüøA5ƒßU+d±¿R¯]L­ ¯òììBr’Ã7Âu›X@ËîkÜc«±#»´0ÉKF2Á!ۦįB¯«:}Z‘Û1ß ƒŸaù˜Î×*A1µáVÖ³ïáÆ_—Ì1aÁ
+6Î.Ûp¸+¹;L«2V­Ž]ÑûCÑuœ7¸ËÌ)bðs6/áÿ3¥QWoŠÒ2¶­ÙÑY ½q3L…?EgB…,“&†dÝÒû ªMÂBϳÌè=œ̽
+K.´¡-mñ߇õM}yž‹y¿9”]Îr•4ã!K°Ó1nÚ[%¸J
+¹ÿ*~Äxókìæüôøv4zÈ-¥Í§%Ð a
+š:¥€Ñ7îçc–T].öleSâWÁÄÄ!<žCa©ÐlÁC—½Ä÷/Á [ÔN±²ö€jÍéîV„+Ä~ñND.O(ê.1›<§¹¹¤½06n¼¤ßþň}–A_ŒxI¼<á&ÀŽ}Sâ/ï¼
+™‡e¬#Ô0Àr£,M²°çòÛ8všpëýœ+6.nt1…ß7¨™ÃÛºéUlŒeÔ¾eÀ#ô™
+·¢ÝÀ«ºç†sx¹èbR,†
+¤À+âB•yÀD|EŸL€´Á<w7‹£dô&¸ Û«ŠXÕòÉÊ×sø@D$‹(óˆ%Îáš'
+mVI›¢wïi‡^ÃU»¢£„Ó Üº.“AÀwÃÒi–yôÐÿÜA³÷œaѽ!50 ÆM3Â&࣠»<ADü`ºÍ’Ž1‹âp[‚mn0,AK„r^u-âV óɶ®2™Ç’òÊ:¹bTC=îš%XÁi¾“­Äñ Vd]…T.àtf¦T”-ÖXÍIO°ºÎ¹#ðg ÿ9ÃSÅ`ªÓúÎ÷~8>0¡%…Šo#>¹¶¨xiŽ2–ŒKí$ƆÜÉ‚ðiÊÐßy´À¥Eß⣤‹<{ÜÞÃn‘i+v©mðøÈœ3’…úq+ø¼1¿;‡8
+»û€ÁËðì
+CL–dñ¹¥^S É[°À,ºMU®pq±¢Å±Ü*Ò—S?„ƒžlÜòã2QV‰¢óƒUG¿â4÷¢âúû+
+üÁ fºQ'1æ?“þqÒÿìTƒxë8ÓAþ‘DfUÆ8Èé-&L2a ‘JNÂϸ
+ojâ•àobŒcŒé3mÈÕ¶—™™`Kž#29-O»ì*¬Q¼$IJ/æ& ñ¿ØŸû~È ê˜hê2E¿žŠ<œÿ®ýØYæŸðXÀ°©.Í-˜¥­[”
+‹ uY¬µïÏAš ô„ªnL[5c>³šªH†ý+í¼Î… ñvym„^2
+J CëÓ:27¨“rò™Ãï}x;ðÏc³)Eç!ÞÁ¡¼hM¬V¿:@àtØÂkîìrvu‘%ÿÛ U0ºœx^‡<F8¹HDœ¦Êr¢í­)éÊ4 } Ž2Œå~ÁÏ·"¡ XºéWgjÊ•#¬øV »I¶UÎq`0_,“;ûCÉG”þüvª9 }\ÄfqÝõÕšÓøÝ6ûbÑ'J8×[‘Ó ~»Éaà —CZÞlTÌtÙôr(J²…*]êC .¹WY•f¬éàqÚ½Kˆ%ØÿA
+½j‰­ŒÌÂ%ÉžÁ" r›Än¯3/RV?_‰–…`é×|(¹;>ŽŒvVî,§l÷û¡CZå·Fï>¼´’ÏRñfò*«Ã.Å+˜íe׉ÂêBÌn¿néOtù¸åUebnÍ1R0Ie"Ÿ¾ÆD9úfö[;ßJ8CžäÚã2<¹bÅ+ƤsQ7«ÝH‚;54›À(PÆF­ Ú‹ª¼FšçŠHãü
+:œv%7UC@7ä– (±–8O+<úk§[‘Ø—™Wé¾éþ*«ú‰Å²œ®‹¼h’/nn<—^A¹T˜ z$VZ“Í)4É1€êÔ‚´† ¥#në\aoæžMþÂPpgÚÍv£€¬UgÆϘ(¸v=y)^DžZõ¹ëÃQaꜬùÏÔÚ¸±]•Ñ[9 /²×Ä"R¯¹•Ðªe®AX
+ã)ˆ2Ùa<eÐVË~šË 4„¥c šÙù‚{lu+’übŽ/è[!\,JŠ
+ ƒÔç ãØüÞ¨0n.# n…ÆÄA
+ý­+‘¤‰¸ù$ ˘5,ÇnÙKÖ0Ã… ¹±§I¸L\&7é%ŸŒêOùÙïÿhÊgfõóž¾å&„ˆS¯íioEÒ° ²ÿ}—€A¾-çR“¿1¨‘wÉLUNΈ¨Nþš¹;j?@%ó°ý˜¬îâɨÉ0ÔØ÷:xFFF=BÛànY’]B¬£[ø¬a‡ߊ=xç!#{^§p+n.%i2®¦ á»ê«ÀÓ/½Âéq­ZÔknnEÌ©“\R݃sÛìžÁtdx§±æ<⛣M<­ªhÖ¢Ò„àÛ*o]¸"$‰È€©c75Ã¥AÒÄ”Ub§7Tˆ
+de¸´1ßÄ-<Y Ò_q(|±ÌõŸcTÇß›8½ØŒÉ8qP<ûˆ†a´å‰Ôí]RÄEY±ÂEIùAš”y‰ào^5mÝŒg×g»!H[JFœ;IÎU3÷(ÁI·ü‘p‹€/µó2 °ixDCÎD)•âUÊGÈs)Fñ¥
+ÒC*0Dí:§§ÿkÞ%#°5†¯6G£!ù·ñ¦¨ ßb‡*ËÌ6Š+xj£0ö ?YÚŠ¼þÁ7ÏPt±@¸œ?bÖSøaÈv“eN§œµ¹Žl ^Z7;ŸÃjdžýb^%L;ì>­_…D6¸ai{ÅžV"ãÚ÷«žaŒÊ©"†q.‘U¦«=^õ]"eÆ£PGÄ¢…/Ægêi-¡8íÆåˆ, ´—ë˜ä‰=J…[gò¥T ®¯+p†`ÊœJæµ»@¢#ÓÔ˜®Î Óh3T7ñòk¬BRfÐ,l
+„³Œ©³™ )Áåá?éXv‚p)_eñø?¤É_¬ÊÜ„‰À×¢$ø숭ÆUñaØ¡¹²ÅóR„ $Å­$ºf…åd$h[xˆ~ÄHv³¬ä¾Ó8”¬YÑ-t“áØÅ9lNŽBIÏ{½äŽ›¸­{``'ˆ‰¢qùÀXãDQ•Ÿ¯SÍ©=F6‰Ž6}ZÓ¦Ê!&Ìh´]u“ášv¨¹G—ÕU¾÷AQÿïô»Šô¬6ËÕ
+1Æèzû§ErƃoòiÞÁCMS8 i©ÏÐiŠ,'ÛJÜYÖ¸³¼t ;—½$!ÃbÐ0Ö°²0%YåÝBYE踤¸,6Q
+
+uäChò¸pÏ m'»Ê8æó9쌡“öv D‰´ f.¥¤©†(µüõzS5ÎÒÄÕ‚˜”¼#<~ ¿ÐŸ [&Íæj@%%/‘lü 0
+H‰•wSùÆÿÌd2™ÉäÏä|7¹ËÅßårä\&€qlŠ1ÆTêeÕV½a!ûÙ±“›øð70EIhµZ5$šÁ4¡•´}%™ä^HÖoà÷ýÍS>ORÓ[Y¥tT∢㠬î8 ™GÞÌ7è¤oòëNÇÏ[&
+uëXà¡pmw^TŸzÒõÇí§ÊV6õ0p0cì|7-=“ŸSþƒYXËcÆa
+LÂc§ã^2>fÆc.m9l$Ã6! Ù$DÌ,Ú jÚ—ïõÈÏ™ø$äÖ—#æ4
+t£AY Õݨ"cN6鶖b¦á½MËûu³JæÁn,hâá!]Õ”#@›%DÒcÝx©¨O?|¾3­¾°1\Ø›.–†ž£yuóጲñhNÓRúpÈx#;-¬Û}´1ßÏ&Ç\dÒ8Œ†eXÛKÅõ×)Ø4Ì&]&&îÒ‘1·–€¼ÖZÚiü3Œb1y+×—"Ê,
+t‘°i¤´ò A ÿpÁØ“ŸÓµÚ+ù9IÃþË¡¯ó¯¥g‰ iàý«ÑºŠsGoõ—ß¿Ò5£¯Í[S'Wî]üÍ꿺>Á–A>¹M â±î€öbÈ.©¥|÷*œ‡Kâó[Ó]Ÿî¼¹~24æƒÀ•R$ãV¶b°ˆËÌ$=ÎjúæM6ã´PIPL%¬r<R°UR‰;ÔNË*tWÒòv5æº>ÇCª*f“oÏ
+¿+ÌKk§ùxÍí>沂Áz^9jÆa§‡œ*‡±˜¾Ÿ@Ìb*ã
+MŽVÜ
+ëº8?ÔU.lÃàÀG¶T3fy•»ÍfÍ*:e–“ˆaä´¦c~"ŸŸÓNAÅÍb2¥å¯ÛÍÕ(eWu‚ý üÒþ[C×qÚÿxÃá:^×
+hè4ª+,‰Î–#Šf1ðé„EƦ ›s ÿm25ùˆLúïPÈMG™Ëi1¦íFcº^<e3Y›ŽYu€LÎ{›H{ýdÒi`ÒGmÍ3v¼áñÕÖ–êºÃÆf¹Î¦¬*šË2“ðßb’·1«÷g+ÙñûÕu—“]³)NS®<
+1‰hÄ®%ãvu51q¿Âu€€ìJ,jèç¸ÔP^Q]Áa]!¬n#[1jÂÚN:åг«+9ßÃê†Ç_Ût³kf€Èê™ ›…Zsر¤EI§'³™»Ï·¼˜¬ÓZä¶ãnÕ²ãªÙ›“—âã_W<¦àX9DBF~)¤¸„†T­eHs Côœc•¾õozõÎtñØ
++61ƒø&þ›öNü¼æö!MoâÇž8tëÆù‡C YDdam14Ò°ýºïOÛ3¼/w8v¿[ðˆSÊóÏħKA}76ðð°e Øwæ´­¹Ã_oLñ¿¨¤mÀû`ì¥`ðñ]R¶cQYK1<|fëyï§ïž‹þZ^¶Ž ‡a÷ò|)d¸^ sÌáôÝŸŸÛ|&üKüÑõÏ(ÏübÉÙw[tŽæuWÑ9y#:/m,Ômh@ÝšŸ“þ«;‹!y[yè¡“v
+—O*e’à°ú*ú?ÇeþÔÆyÆñ¿"mÓv&3i3u2ncìÚéØi|Ù\‰KHHÚÕ ÒJ«ƒÛIðQg§M° ˜‚Œ@×ê`À\ iµ«½vþ‘>ê;š‘VÒ»ïû<ßÏçé¾¼9#þKf½#$]TB×ËÆô²rTÛ ü—q„VL…T"2¨ª-Å4÷ø´¾» 9ÉÅ'ŸÒ‘ñï©ÈÈ0Á `RÖ§¾u@ꎡWŽüŠX£üô î¢!_+}pº;ËilKÂzÒ¸MX³;ár”¢U1~ÃÙøè·Lzü“
+µ¨I8ã"ì;Mh[‹Aí½Rƒ÷ íù ÚÈ'1—Æq.m·ó¸½ ù
+7H?ÚPðwÿsûåÝÖŸÕ~x°Øs%»b¿õ˜ÅÞ‡m"´)® uæ½h}Σ­;˜×~³5£¼œúIöÙÁ¬êúIÊ†í¹‘[nm-ìÜžë<Ÿq·Í.µ~–óJª$UEo¥†lh<+ñƒìoŒß9T‚õCHÓÆtãGñ5üŽ¸ßðAx¬é÷ÙŸµà;hcäQýÇ»ÓÒ '„±› ÚiXçþœôó-Ÿ¼}Þügà@uå²n¤† õò±¡.jê)
+žÎZœ …°®5ž¹9ßq6YRN›TB3ñÉA%A[騶IÚdÔ‚2qÜÊ'‡'™¸ÍÈÆLr.>Ÿ° ÓCtÔØU~c6òëCF.eÑñ)lŠê»Š„¸n5±àŠ¿F ifÀys~¤>ëQVçýÈÝb%“#V´
+ÎãFÞ¯o¡‚Æz§ð?ŽËô©‰<ã/öínmm•ï¶ÊÚCgg«Ö™µfÑ©¯Gt‘Q„„
+ O2ñLØ8QŠ#8AÚ«ìÉyÞRÄ8ûQUð`¢‚[‡VÀ*1TÂDÄ,&,j¯¬JºË«¨ü8NŒÃ>Õ»€h §uÀK†ÑãUœ(GPQ1 W—Ž×ô#Åa¦kÜ\]ðàrƇöÃ=·g¡àAœ áš"¼‡ße½qÞ«SQAóÄÖ"ÊÚ™ݤ}òž£U5r }øySc.¯"â|8$ Óæýìi`ì0RK+QTr\cµˆ/qUÚÍkL.².=jy98<Y
+èõi§´5ãÖ£ÊþjÜð¸
+ùX‰bhÁóx‰öŽ½d‚Qi‘,0+ wRZ3þ|¼ALTÖ0MÎ)åT°`ç^£=â¶
+œa%b™¬FG¦ËQÂR〬a,‰+!‘v¡âÝ%+ã² §ÉG\?/¤}ã3TSº›v®ZÑ*ö=&ËÚGø®NÃÕ²ìT:þäP²iÉx¸¢—%íhGÉ£¥€F ¹.`˜jÒÕ2iü˜Y”ÜÉ’„v罬!³} gSôáhÎ
+zNÁxäìÄtó™äBϵ¼WÒ±ùªï;ÚnPÂì!¥ &/tš‚W¥VÞĻ޺ÝÜ‹»³Cõ“½ç³óbpž¡–¬W_ö‰ÚÀC‹nkãÍÝ3ëÏïþ•vJXið˜—÷þ²7ÝöÏì÷‡2ÜyÕ‹ð(¨sû}ë7‰_¥lâ–)ö¹Ô ÿZÙ­’ œD!oƒ˜,ç’ÜÝží:Ÿ²ñn€‹JwgÊ•èxz
+föé5ðÑ8Z#µ]\j
+ìØ“¸~¬V²žÞë5¶eHŒrh…4©Cj½u´n‚Ü2Xè_{Òh=tªûòÛs ¼È[Ñ•¼ƒP”ؼS
+hŸ¬3åj.Æür\!dÂZ ´>M’rVÚ§–ÂÞÕ"àJµì *úr^%ØRV
+"ü©•&—ÐƧNJAƒ• ÆjTg<ZW¡Õ¸ÖÈ„•ÂœWµX&rópÖƒK‹aÂ\^3>.Ç­o‹ÀJ•5ÜXC>G4ÈÖ\oý8ï¿à3‘Ñ÷ù i¢4•¢˜²÷] ãšãˆJ
+ïzŸÞ¯s>à\9p=ZØqL¼ØX2Èv/ ¬7ÈTRʧ§ÝŠîà3ö—”OÖ•÷ËX9¿‚Cù1 åU¼æ‘ä²^º5'¾U¬GqÜ\]G…02wc‰ö.KZr.´wÏ)érµÝŸw¯‚ÿ„ fàlãÁ†²+C·×¦îžMÙø Û‹Ü3ŠN—GFi?Aä|Jn†TteHùýOK’¦Ä;nÝþœðºoªëÛ_”õ§ö§ùG¼ÖËÒôiÞ;ز7ßqÞ7qù÷ñgM¢â¶Ã塦×ÝuÌ
+Ú_ò¨sΡæܲàVr¾»nýeÓ™í©û_GÞw_}*¾t*6Ñ}ã84ü
+aB
+> Ž–qˆ[R+œ‹Éo üvøYëÙŠWÂ>ÙÄp&"ëè¤ý2öþ"÷ÊÞ,÷rÁ
+’ÞÁ.×HËéÝ—ª~Êýd‰öƒ8ä¬Z¦eÍähãiÒôãéÃýõ‰EáÍ¢ù Êf„½òp®~“qÉÙµ\ɺDw¶æ»¿?° ›Ø‡ËªÞŒüã3… õIÞo°æjÙáCxi»ôNÆŽqÓƒ:ñX’ÄDGQbì(FŒ}ÞÄ-0'’BXØšñô^÷d§*þÖ/‚x®½~[ŠŽ¼/F¬S¥¨q¼–%¥°„“%9—( ‘v©ùÔ
+.bÜÃÀl¦ÇÕ8n¡ís~a€­høÎùU¢Í9QÃê”èR™4›Êa•„׃ü伈 Zc›uLCƒŸ$ÝRÎdiÚÉ“¤²7é5åýˆ
+µrS+7GjðYÆ+cmÎu×µŸI΋;ª«Äh†ÔfH\òë¾ó€÷¬ Ý4©âÁÝœEëÿÀ¬T‡„óÉ.jȸ¤­à,÷³Ny{Þ…p²¬ßó¼§îµèêo/»oV"˜’òÕ|ItïÀÉ»¾7×ó]üyÛ¹ô¼ðvÙ§S^• ýAv»ê4j“‹rVüMÏ¿h¸•KÞÅÒάm¨Áñð§¿áíç~c#šÿ]ê¤<âÖœWÆ.ú4òjH§c‚œ«)[û×);çÂÞtëUr ±´*îùäì»F‘E æ™v£} ÝEŸZ”$Û3Üÿs\æÏMœwÿ:Ît¦3i§é”&Ò@&R%$Äø¾±­û–V«{%Y–0Ì1¦qÀl°1¶îkwu ¶‘-ií®7I¿êïo»û¾û¾Ïû<Ÿ§ƒ 8,x懀ü;Ðâ v"TЩ«l¡“Ô+ãD5`š
+­Œ®ë;ñ«£M»™#o=)…lêâªìlöDH9€{¾VÖj¦àŽýôTyž
+Zd,a3W"6U%æ0P1³¤ ^ óª8àêâÆô¥¥ë§~Ãl›U­ÌÜ&ˆø*g d†%ô×ëT#¤­Há?’ Ñ ¿ŽÞ¼ú—fná)C.®U“7”ã=°œ·•Çæ[Àg\R?^ j{™°iš[ä|Z3ÞȘtt tÆe¼Ë |?,½øö¥ô\iË8ØÄ]n&¡¹ÆFY+ë¹/¤0 n/¢Úhßí(;ß¼^8Š ¢üºì<ÇL\Ö»ÂçÀÛnŠ4««IÃÔa@Ý]\ýò`Ó4ÚöL.ã¾Aãž.kø¬sžÏØí¬Y>¡ØÝ@ûß¼Ðw×3v ½‹Ï{W„‚Ó ýEÅCö×3Vcn¿µzVŽ¿ó‹.ÕHïC6}/F‹k07Æe¤ÝTLÙLj²Ð\ƒõÓY‡ƒÉ¸nÔ2¾óYÏ=6eÃúd\Úêüïk«C 4ÐSíh+7¿ ™ìã!+«qãu:‰
+
+¨ºè˜][‰Zd{›º®Šß~ š„¼i¥TCuBråýF÷Ç»:÷îñð ¦ÍaýÕö±˜C×î)LÒ$H£´•Ö‰ê¤nª zpW@O{~uw-Šö·áýM_9 ½ønmèã½õ‘/˜€vì8ƒ¹˜ª‡ «º©0¡^õýµ´vù÷GÏGOÖ"ºki˜áêA6¬êg£†iÆïs1—¾UôW;ÿp¸5 wC1ÐH¤¶GÆô#Õ¨IÚzXÏc>!£e“³_3qÑ%.¡©“6¤žÅ<h:©ƒ
+™¦Ž6 Ô+ËLuçpE¿QPqý8ÄLmï‚ý‘WVv[9äTH|±²3u†žäH£¤–0I˜2I…Ô½\¢h³YÂàòò­F(h\= =R˧VËI·šôÝ«&înq„ït*y7Š„¤n‚
+k9ÐMº0.å¹#@ÖsÙÿëén«`s´2±@(úk¸äûVN5vœUÕpq×QTz¥µ…´¼• „E ÷MÃ%4clL5ÀF ô…¡ƒÀT“²9˜ìÜR…4+I›‘‚`ó3EŠ/ó¤fŒK®óiðû”ç¶sÌ1¸aŠMjG9\5@Eä]{ÛÓÿ|ï—^b³˜¯V@u<Ãg_±éû àÄ'ÀV>!ï¾ÝÈ{5@«Í‚k‘ÏÙ16c˜mí.Ø œÁÜñk°’IÛ*ZÐã×(ºÕ×$ç@+½5Òé9$
+&Aß .È¡›BÞê¨P“¼ ~Ú,ÎÿÐxíy,·Ð‚¬:.úžëCײ BÖf­·×’Ã<|U2¤z¤…>™¶[E úˆÕ¼¥¯ÆµC|Ênm
+8 åS݇õÞJëý§jAù`7)ظz ´9qú`íÚ'å øR)ð?’Ëô¹‰ûãÿI'Ówe¦Ìš6a†&! ¡!>0`Y¶%Y÷±·¤ÕaK> `HB ¸P<ƒ/IÖ¹ÚÕeٴƇ¬cµ—´’Ióô«é‹}£Ñüö·ßãyž2¶÷Üü-ƒ~¿Ò|)n!úvqS®±FÔ>TÝ4]ä¨ú4W» ;;nw víIÁ¦éæ‘ÉnµÈœe¸ž˜øº3÷‰ B_]ÅGê¯ImmÍÚ'fF¿h³fÈ&¸´pN,Rîýˆµ¯²JMH‰ùÇBÊ‹­L^¨,/)I¦²„«™°TÖF>9|}ë#î,¥¼D3NNJD'$-C"cûín‘@ºEO ÌÒHú¼ •àO>Ÿš¥<*çñµ²P‡jjdœÈcZµˆ#íòôS)\9Ú§æ(êý6Žž”óIÉelliή_?u¸~ó4ÔÿêQÔðm5‚éåÔìm6üC+ãu×¢ÈÍã(>v°î8Xý¬‘ö‡I۶䳳ODÈwÊŽ'̳š/{gˆÌ™È*÷8•Ã­„íšF í‚'Ø-“^¥hŸàYs¿\pLˆEó ˜Á°ÌÝ‹Šù{q´_)úçÕÐó“·¡—jÙ–ó"°˜Eþÿ>2ãÔvòtè×ÀC‘1JY»¦•7˘®ï¾;[Ù4}眣o7ôç› 6©CO•bø™Tð¥<î8‡¶ÉêŒyL-Ê9¯Oú€wü$Hò`mð´Ü ,5%‚K¬×{Ñ›K/ìF¸] ±ëÁá›Æ£&$Æ¥=¾tJÞ)‰ÁM½9lÁ9j‘¢»eß]9OQÕ¸î«Ãí_ ó
+ã¥`þ®6b¦«BÌ¥—þ95ºßÉú‚BÒ5úö_Ú3•5k¿  |:ÑŒS–zÌ‹óI7Ù²ŸëÖ10ÀADwþ`ÅtÎ?¬nøÚ1r¼l¿Úxm¾*lÁLì¿Ñ«­ŽŸm3Æ.Ì'ÆùMIÉÀ¬œ „ÈkRÚ5Ú„Ý#ú¯Ûyóðò_ýáñ÷?)17®rnRJ£úf?
+zòß2bWÝ¥jD÷Ÿ´)Ó!iøFI;µµ„yè1ñéï~qžû€ßÄÝmwèý¶Û~Žűñ£„íFaeüÓ£-ÌPe`¶"Îr<lÅ矨™àL=fº¼¿2úñÞÒЩÊêè'bš²í¯bÇoÐ~2F·Xèä2:Ì85bÆ¥áOA'ýõ4fªDìƒÐÀ6ë!•^¶ÌºÑ£¸éR5¥¿(ÁÌt¶Æv™t7`VøÌÔv)´¨n“T#e׸A-íœÓö[E!SŽ—oœÚYÆGŽ¡îÇQøH Pßšš®ÅîüÜHÜYŸ™:NQÖÝ(v{wÝÑ'q³ÏxÈFœÇ+pî`“ Ì‹l`FÎM÷ô^fÍ×+‘É Í4îT·§ —©Î¿«gŒ—k ÃÅf~òŠ˜#ÉVanEÝ^lýsm˜ÛÎîÔbk‡¤[pw>ë¥ëÚ-B¿dÖ©kl}®06ØÜÞÊ:´*‡ZÞ—0ô·2Au Þ›ÙzÜ|ùݺö¯bÊy[ÍÓAà TbݸÀï)Å©GJ1ôKî-r„ƒgp£”óÒ0ËDò ” ©vïàÿ•®«%qèÙO€…ªÀajÖ?­rþ°š÷ú»yoqè¤ï•AãÅÔÌýV1ø ½í¤p~²ªyÂ¥é0ŸÀá¸AÍÚ¹ð“v60£fÓrʃIÀBÂ5"¦l#BÂ2Ј/Êq?Í'æ~:ŽÒÎjœF*äx3ŽÚPs™C­Õ¤c¼ü¼gÉÚßM‡(iÌx´j¼p¸f¾,Ù3õ4Q- †x1øû÷1Ýß ÆäŒW!ZYËP#:þùÑêØÙâ“+üçÑÍÕM·X­ÀnHi/Õæ¦PAU&ô@Éx°&ܳ·öØ$Æ
+¾àÐÀÙ÷©ù§­¼Ç#g±IÈG·ß>=³5ûÝï“óƒ”RÚdzúêù´©lúFÓÆ탇)D³ŸrÝÜ[³õu ¶àQ%ƒêd†p¨ÜÞ›ÿý7æ {«–
+xfvQà¾ßh²ÁY!çq y©f#G›ÇÓè¤\
+dY!áv4¢ØŸÀ´|š²ŠY l6!§œ#à©ÃbÂã£^{#‚Ö¢ȶ˜A„Ì,1˜Q{ÚÌR.9G"궛!¹àvóÜØL¡ZX£“ö Ð«ÈPìÜu ô­ÍúCMп·/õgË‹š÷–4†ü|SJz\ÕfØcï«m†üµ ?ÒŒcÀ—NÍ0Àî«[Õ7m×Z[^¢›£ýÅ>X±Ýh&}Të—éWiÅÿñÌ·î±çœ9szæh;­3=(Êâ4( ûZ©¤R$daSDaº]Z=Ú®,„,•­R!1¬BI*©¤Ö´OÿóÄõ¥*©zë­çÞû»q§½ =LÙ,å2øyÕÂæîÍ9sÓÁ²­‡¶çÃhO)¨m.ÔWK°µÏÐÎúMeàh)1d.…Ì]ÐC< ë ÚõbllRˆÍH«îÛ•f¦ e#PÕ÷È«óÅÄÜ1CÁTLÀ*+,Ûv^ÉÏìÎ*j8RÝÆ„õåòˆÔlìÖƒBWg‚¦Ž0¾ûÄ’6ðmLßøæ—c)ó
+3VÖ\Sâ†ënyÃ=-¦Ý÷`FF*ëž™ÃM÷OâšÝUZÅ‘ýC3äñGMçI‡™ŽŽŒòÉ[ÏÁoWH&/Åœ˜@¹GDè]EÒ3^ Æg˜ø½ù"55Ë%=÷ŠÐa«zäSSzîúßwêlàIŒŽýLäâžI઻p¿qi<¸LJ:ìÐ=œ%Ê=–‹< JÔÄÃ0äÓ¾_$M=YßàùœOÞP ›n}pz~_wO%í°¸‰;Ç„ôÈCÈ£‰²Ê ¤‹o€þ;Å$Ž‰)÷T.f–åH`žôí— OÐæðp• %ð!*sï M™}=½Œ´3À¼EÂ*c ýUzI}>»¨k`ƒ˜,3o¼´÷FýÃÁ¬æl%a·Ãb<hz›¢@: A¤ffððÃdƒM“ã*:4¤)A Ä°Qá.l¨þ.÷¥}Æv&d‘í¯˜Z·æL·ßö½ê ,¡mÉ­è[²~CÛo^}cfÑ©^{¡®Ý|Ýÿ¯,øO¼<ç3vVbÃx%â²ó1t00séØάþ6çýU%æv}N»ï¥m ³œ! m ¡K™ES3ã3¶°ACëaªûüô3,¬ƒ^Ö7^:ŸYƆŒ¥ îÇ좪Y¶ÜÈ;Ïøø`
+ÈÕ(Ò[èZ‹„öª@j[¹˜ª¥Fû8Òé Èÿb@ßxéÏñG僽gب¢A
+xÍQ^Ö¦˜@Ù"ËÑî<YKÞ'jf…KŽý\€óeQ°”±»U\)†X!ò¿w49õb8†m‰é±ÇÂçh!Œô²”MÇ%‡Àƒ«â÷Ka·«œ£Ó áÂÙ¸ÍÏä£F™ƒL-¯"ŠJÂf>ºUY¿³(mO¼-ox~ª¤p ®ÉJQã5&bhçHcW)jèϺ¶ïÇ5,9:#§
+°N112)€¤äÈ”˜²ã Yí,¦î,|èUE
+º싨æÃ#¥íÃeìáIÝ\Ìp½ÏâýY`ˆéÀJ‰ñû%wÅ”U#¥,ÚOk6 Bº²ÀÒ¿ù¬½›ó†F&4>ÉD=c{KHÇÖ+ùw<…iàçjï¢W´MûÐIÙ(®¥}XßöÚ"'–c„ˆUž[ÔÔ•U#Gh›EÂÜÍ°152Í¥Fîq«ÊÆžH°ç|W—B¸’ö®îÎöØ|ÕbãåÀÉŒWQËÅ-*†t |b?„œ¯Pè Ö·å—Tµ™u 5#;¾õXy2³ «ß~!?™[PËyѶ×êšõ§=߬N·ýiûI×ñœW][
+j(-”wlâ`üz¯†]bÒ¢s×$!Å%kºÕ1KM‚¦¨.EçYQ=‚õª8Å1}'9fè$›:¡ˆNŒÌ‰ <‘ë’“R”äôQ6³ªÑ%¤öhI€~¬pë–x Ÿ,]mg«Ò¶Cs]h#ž¯IEGKÔs‹Šçu<£Ðy¤&jàbÁ;ÕDÀ—$ºðTˆ.>—øõmõ¨¹ƒzhn'…çØåþYFa؈Ô8P¶K çùA/ ÏókC:^õÉ‚ÿûzã?àszGIËô*™Ô Ä]XŸþx:ä銄ƒÎ·µ zîØ©ò©à<·xß,¯:2'xž•‚ÚNÒ¡IBED¯)ñ¨˜ˆU~fi§£ó‚úCsùðç!˜§Øz—0 ˜ ´(aÄ–»¹Èz2²ªÁ?FÁ½Ç̼ú£eAó7Eô‹51ìƒ3·“W¸à«Ê1åGÌBúï»ÏÞ|²Š¹G«¼æÓÍvøÈÚF‹,ñ|àlìrNþÎ
+¯R\ëo¼%_³ö&Ùù
+^™M.¨Xø¥ñ_û>j5ù´œ2 óRç-Ó=ÉÄø•¼RŸ‚[ìÕ å–âí¥Wø+Aàõ'f!.®3‡Œv7®ÝAÚíý!R:GÍGç)ù«Ò«•Ò:) Ü%0Ë)³Ë™Žq8û@cŽm¸³E1Õ¯bgxÕ!- ô|?8MÍòLâ“]ã-· <ŠÖ»»Âüúá?£ø´‹¥FDÏ®rÆ×Lânz„T°&# ¼:ª—Ì à O¢ú§¬ î)ìѶ7lPnYúZw†(É[ƒ¤›n”s¶$¢œ¯u0ÎKÂz^ÍÉŠˆ|²*fDŒíøSÐoÏ7zºÎ-Rññr;åb»» °­
+æ?dÖôp¹}Š˜æUŒVó«ÝSÜŠý1f®W%¨ºèÀCÊüN©_”y¦è9î Zúö áÆÞ%Å1 gEÕ‚GX»D ³)9^µ_yNâß1£„
+Ê]ékLXÛx9<WÄ=¹[ééDÍ=ü༘蔳 ¬o(W-½øã³ú/•¼Ê¿m¾mLƒìð«*ÔÈÆþaãQNVàª`v»’ž½ü¾á›­¸k^”ã×°JNV%ȉ¥[^’ÐZQ]
+:Á9ŠpN93wk€”´ùks‚õMSBHÍ~pl·†ÈÅÁi]xõÊ7#!ì2€7³ïYßá¿3H«>SóKÿ²ý—¸Ü‹¿;Ä.ýr_FÊû´ÉjòM7ßñ(ˆ©n ÌVã5Ó‹ÊKö‘æ›1#ïÉ™åù‹ðb'Ãg“S¼ÒíþÖïíí©{[nš~Ä~±þúÉ7.”±ÑOÏQHåøÕLìÑŠ:^Ñb‹H]È@Ÿ&š“vû½ö¦ú ÷TkæÊ»æÛÁ~ýÉZ·0¨ã׺Ɖ·vë–þ]ùŠËÄѽãï™sÌb¼ÆÌd&ÛK3vƒ±ÌØP¢H -’R¡…±$Û„Av e )»ˆ¨h¢EÖÁlçÌ{ÿå}üÏuýžë{ßŸÏ šfÇÜ ÚM~„=‘”#@Æ!j¤UÊŒÓ ‰Þún‚—ID Õ
+‰¾‹¼ô'²ŠGc?)⫼*÷ëBmþ™¼egDY'(ášNŒË– l‘ƒ'*íWëQÞ×SUð«ùj¤IRñþË=B/,ò´‰ó}Ly^§£Åá§Rj¤¾§àå×…Fê÷µöÆÓù9ÆQ’¿ösöS­
+ò¸§óyêûãéÒÈÀmM|ATä§"ÝÔ0—/¢¯«%ZÚÿvª¿­ÕOçÇŠƒ }_ËxI¨í–‘ãÔp +þ'Ò²Äorü¸ÍÓɲ˜cIÉà ÎËðDÕšýÌ&c¦\¬ðKO—ê‹.ÕõôÛmùMEO7>¹Ö„z¼Õ‚ï´ç¹ªšàO÷„…Þ":Üç›ÀÓÎdŒ$M[¾ûn?ÉH³—ÐÓìgjÎ#ÌXódE’¶—às¥¬Ì¸\`¦Ü(™N§JÂV›RTŸ²]v»ò=¼4ÐÉè<Æ™Œ¿”s2Íãäà]!Öu•tZkÈy¼ñ ë2LI¹§¨Íõ:+K¸VÖâÎæY°£1RÀÑй­@>…˜†‘"à=Ï¿É«ñ¶…–jíHyœu–›ýMÕÖf›­ÊÙéľ\`}¸;W™æ0@Žw,Oxñã(.éd¶Úð`¿?Çãû:õÃÍ
+ðBÄÍ"5áoUê÷qµÈE~Wñ+¯U ¬ƒ¡ÊhÃ`i°a
+c'†˜GîI !_†óýÖúYÆÓÜ7 O,s¥Ð¯*.þr‘…8´×Kñ3‰ÊÂõ=ůÔp`_†¨Úó<msëA‡bB˜u²2EÛ_°Õ^è¾×K„%)'ò¹·žµÞšùØ,-Ôö‘ü´=€Sˉ»=…ÛížÆbÿï·Ì‘#Vøù>êb€YÊkÚ ^Æ‘òh¸ÂÇ€v;‹<i¡ë-Þ\X ¦ðÞ)fŠ¼6Óy–•ò`wÚíÀºëð~çò’˜› ÔZW–¯ˆm§î&Øfì1'u¥µÀGÆÊt‘U @Ë5N³•±ÿ5K ïÍÓ¸À³¹2è/µ ý_]ß<šç»\g¿ÊOv4ô£\ ÂðA_áKƒˆ²Ú^²ØŒ¸^n*ÿ¥ª§Þ,3¡§RÒ[«˜bìá
+½æøÙO;KãÔä¼ûeCRúFR‘ÀJx
+k"ºŠýOÆ©G#åé¶IZ‚y`§Åluãƒja‘÷»p)/îë(À¶ ÎÚnƒyìu ½¬c„ð; #ݪ¢$4!NìÜàû{#„¤3€£w;0>‡]è—û] ùêD§K'óvQH=Ÿ`n–DÔóE1Ë,gÆŽºÑVä¹"Ìú}§5ûÙ±å{©åÌ6çzìô°sìSÝÓ¨¾óç¯mAy͋оêÏ¿ ^~àÑ
+là<±w ”øoKè¹
+©ë­tÒâæ0oíJ>Ö<ÆN8,?§‚Ïäô؀і„0c9þ|º¦f>=‘‘NåUˆã!:ôzšžö¿­*â7yØK1v
+|TضŒšXžáçëü~r²û_ëʵšWpðœaí{Г ÚïÎó9CÍCV`ß_gĘÀ`kYîºæ GÏ–þˆuœ«zïdÃÆ\ªÙY“ÕéîkÍEÁÿÒ 9?õµÌ‹vúV´+)öS s]+Ó~•Ý·¿¡ËM%¡wZ>ãr†‘m:áJÅN;WR (ß>:ÔQÊNq1)˜Ù‹Me€ßBÏ<øí q1OL6áB·»á/·ºQ>W‹|üÎ8=awˆ}9ÇGÛ<ØÉ0.ôlr¡ÄGžn»;LŒµ)EœkugƒyBT¸-a¼«C‚F©¶šK¼oTÜÌë>×ü¹Þ$´+Å«¢ž`aÇï”øíI«õEnªêl‡a2ôžá !ʪàÂÖZq¾GÒÊ4³¬êã0-æž‚“ä¸ÙRè©ëÄ
+râ.À¿¦\ðZCŽ«œÿ›œ“欓‡\ÙÅ>’²r<‰ªïÖ9óòÍ©‚›s>]‡ûªþ\ñuYD?™¢Ç[§YWKõÔSyE–}‚µ')òÓ·Â=®ƒüÔÕ1n55%–^æî r§io¼YsìJV굊k›*{w§Å%\©‰S ¿o4ÖžÞ»'­IÞëæ@ûÑ;˜ÀÝN´ŸuŒ³ÓSúêPFŽ2LTfÌwàÂÆ+rwÛËÃl“ŸÒì
+NªUN7—E[åXà=Ñ{]HmâìT)Â;´"FxkÅ(ïu1ÒÝ>BOºU °‡2F²®‹iW|f­~a‚{ÉûRRÔoë9–I
+øf‰¹]ÎJ-éb•ûcSÀüs¯¹ój½©Î¢ªÊß }0ôÑ¢ÌRz”áÿ—iSšY†çËTWu÷tÆ,šî˜ulMǘ˜EclDMÜ5
+(»€ ð¢·%îŠ"›€ ( à¾ Ê* ˆ&éLMÍ_™7ŸOÕ©§Î¹îå&¤G”HŸ‚S¹((¹¼5T›P3àÜé+]ˆ+K@Y¢MŠ¾»7Ñú'ÈTmÜÜÉúº!âk@klåÇ »¤sw
+Ÿm‘T‚ •_³wA~qËÐ`Ö2CºNªKN-XûXìžE¥ÇÍäB—çÁù¶Ò°@;ëR oÓ¢Z-jæ]Š†!#«: ²RR Î4ÄÜè"d—V|4Gzåž%åœ-ó[l}巵܂¶dÕ)˽ȌAÙÝÝ‘úôss;~]N†¿oÊ»b”àÊ?›»Û]#è”­o“,¢‚K 9 î䃨žø:ªgUÌÑ¡Ý„ÜS=ät™Û°6XŸªhƒ$-Š‹ÿµ)«ù}ûSŽ°Ž\èÅdkDÅÉ!úk–œñâ'#ðêÊÞd}š[Õ”åV4=;Y AüªÖð_R]ÓìʸµGì×skvFL4eD¥7ÔlÈ¥€®¥ ê«Ó d#ô~ÂætSaÜÆm 鯚’çU‘òö&êR…$ûÕµ˜MÈ0 `_Í1`‰¾Y
+<lè¦ FÐ
+j>ygÿÂ1Þ’=D‡%̶–]÷È…È€FP¿>Ü”®½¹¶À‡_vô—§Ž¡²¼³ÄG9Õ.£pMÖð{lI@h(Íá77”¬ÜKz èÚ5ç‡)jîÏ® v…¾Ÿšõ‘ýi¹õôÜÌ%}u°PŸ­,dØ@)Ú›BÝß,¿ó}Ö¯Îv|@ßZ6ˆ§+RàHÉ-·¿¯MÖ² ÖñŠoéù°ÄqòÓ¿kxùW£øÌQôš@üæ‘SAó øÖ¸‹e€[âb0OK-EQk'j–p=jÞ»ýIÌ5Fxy<†zøÙHEDu4¸{š˜å™k~íSÒ¡a=€ókÙ%ÖþÒ¤õa|¦OÃ.ñi˜ð˜Y@ˆÛ»ø!3ïÖR
+Ãk}#‘ÕáùÈŸp4ìüX{ËÖ[¼)kÈ/¶Õ€9ùÎÒS~kQX|5²ÈƵÜÚ£BöÆ`åÍm2Í­dÂUí5!½¤Õ¯âÖlËðO<sÔRPg#ãmÄ@)<˜D¥¯ô”Ý1tÂ/ûuHt M\ÌÖ1'b3ÃKŸ†ÛŸ@=9žiÈ8šE?
+É°Ó5..
+™%œ°©—²Ú|¢c•º'ÎAäv.{OÁ€ïNÓ ß¶;»‚:z¹kŒøx[ÖœîQÒ ¡%zÙ‰‘Væ7PKNì
+°›Ã¸<çHm¦c´úá¡žwiY˜]9}a{?t¾Ù7ø®K7Ïkâ¢bAû×®žóu±h_Å(5¾JÒ `ªÎv%Ÿ¼ Ÿ¸g@¯×´{uÄ"ŸžV{bd¢¿lŠ—èG§L´bŸšQ5÷w ÿç¸:ÿÙ~×ðBS¥fE«VjÕª±ÅÖ(IXÙ‘E„$2ìÕ FÍ›4ö*iŨÖ<8Ÿß8oÎr¾¿óâyû|®ûºï뾯«¥údRŒÝ롇AVÑuGr^²|Ö„l¿.Åg°gßOÀYNÓˆºæÚ„ÓAAÆ~/9T?A‰:©>›åA}nÿ^läTÒRÝhmú·vÔ‚þ])HÐ)êâ×›ØÒÂ8£J¾Í†”<lÀœ Ögítð¢–jÉߤUÈkU+ûH%-SwRƒwzXq—êöŽuøSÈïÜ©¥UÛ]xMy–­¡¯È÷jJØß»!g!;j"Ú1'= ¹W£M'}²ÂYcÒ<ƒã²^ÍðùÙ+Å‹p'c”ˆ‹©ê¼ëE ÷JÓ;q¥n®»\ä㵟JüÔ’']Ÿäƒ~´›©h,8ìæÇñ‡
+Iöa·
+¢:õ½1;÷½qB°HñyiÔ]‘ïÒIÎtZ–‘G#µ™?gꈺAv‚n€m}Øg,ȹÈ!.Ž—Qù¬¥˜ðX• §Æ£ŒJÂÞ„)ñpI
+ÁN‡çÂâ½^(wGûê9ÀGú”$̳Ce]æO•Œôk¡Ep4'%oq¢7 -ïö¶|\iiˆ¬¥» Ñ‹­Geö“¦ï(ä6L-qè"`¬¨0#ßçöà…µ%@½t3ªÍŽ2Á/r_í DCwƒw«å3¯·k(gËÕÅ[ÊÊ åV¬·AÅ+½]k’N>ÌËêI/V¤¿5)5쫈ð© ýT§%E™¤øyQQ9)‘V|¸©¶–v£æ3.Wô«ÍÁÑ< m˜¥ÅTäHÈ7%žÎ‹w¼¨µÖê°yiMÈt}¥ÏPÆU†M°%Æ›âÞEx8/;+óÒŨ&=ÎNÉÌ|©Dé>S
+n4µW+"ú-¤ç?ïXÅA_i„´»M1çBS] í/E~•¹l´ÐCÖ›ªÂ±™æø°`12 ÆII2¡&„›°Ò£Wg& ÜðXç°Ü 55öiKaÂ0Ê͸ÔH8+r¾A%ÂéG¨ÑÚ~|Ø÷Irâf/%hï3µÙÇ——{ôóÍ•UL?hV¬¤…YˆšœT³$¤—±ã“GÀzvæàak °ï¦Ó’’˜?´Ò®ÿèëeW+ ÌÁH~Кí÷°W[}³-o<SC»dŠ›þk©
+}³Ê'üV IÇ*N?Î+^l%¡ä¥nu¹IM…è'ôäw–ØÈ
+åy“êØE­°äc²á¸÷0t@ ÀlH@ûû¤“#ð„øxfi L»µÅ?\
+Üïg†OËÉ/y嶭xs: ^†z>†½©þ^
+‰)©y
+CP*5Ä,æ¢QÒ²M‘DdÑns‘*¥Š˜w«­±¥U>íÙº/ÎÅù_Î{Îź]Ïz¿¿á]ËÉ®}˜v½Õ'ûçNÿs§¯óúMŸy´\,wV͈i냢„¡6¦¯ ×E[àX“H’Dc½!#(hw/òÄ
+ª©é@ÂC²²c¢!%"ÑÍaâ… qy$¢SGY¦÷(¿‚° hŒ>˜é*y3.¾»f‘7Ì=)ÖÞŒq9;Ð*æúb^}=šO‚ b,¤†GB8ä;‰HgFûâ€àí .h ÜÄÀÝàHhɦ»±QoøYÇS’âãéÞ²Ý)-㥱'uBÊ%èYuè~ö£›ým-šû(Z<Âý ñY¼¿Ü €xzC ¢çt‡?ä‘c¡§¶µ¢á„Ÿ­ÊÏÖ¤ ‡6uoôQÜùJWõñ¢òáæ3yñ ³<Ù(ú?¢:Ý#!%4JHdˆÅãÆh¸åâá8`=0åG€‚ÄTÇÂøg}ÝwDH»X–0NçDyŸl¢¬½ÁÝáλ¶^~È„L¤c3=h9åwR€ž˜äxˆ%àÁÃnn?H
+%‚·Ç-¤/<FŒt¨ÍLöœSÔ‘®ìÒ?þÞí“ÿëCŸâ×[¥øjKÎ>Yè(Y`…¯XÄ Fn³3;Ó¹*)ÊHqH–ý‹dëzÉ!áî XwðCÎA>@$C}f–‹¨¼
+YÊBŸŒz0e–ž¯ œ.¨˜ÿ[g¯Õ­ç¯Õ-ŸæuìwÏ-ÂõQMÉœ±;ÑÒà >þWŸ_†ª æ;RãÓŒ!ÞÅ} ¢IP™UâįhòíRÎåçvyËùŠ¤î×òzpá÷aøï½þ¡Óuwk¦#omJ^4¡è
+{"nQ3ã:kë¼ø÷ï{²**1ÙÉ鮩Q±GI…¢ô{ŽtjŠ–’æÀ¬ªBK[› ¯-]YÇ65çû+“ìû²¾ãlEÙ|:/¯ÛyÚFÞì)>Z2u®Œ¨KM¢&~U!º$r£––åʽO¿UEË@LJCRxŒs] WZ\êYSLGIš½4\^Ä„RLÙlKYî«õÝgQÿù ³üÞWiû!ãbCÓ~¶mêÿh7J—‡e™¦®àAk^ÅFŠFv><̧;¤¥£âàŒJqä1*ÐF!;Ô¦’伟Ñq¿.«Û~m)ø—o”Ú/kOž|F.0'K–ž£…ñÞ3iþÎS1eNÉïh
+=ù“sbSž¾êþþÚÔóÃnè=[Ñ
+¾¾R5]nT—o‡×~ì­g›*Þ—%ëÛºVüqUÍ9²«9ûKFá‡çƒœíÑÞÜ¿ÆTôƒ…1ÝÑÜTÿñü¸zÏfåN[ØŸ§{Š®WUœk$_WÛzù…]Úðý•‚}µd1^­LÌŸ­[NV´ÂÏvƒüt¹¿ýp²·ôxR÷`ÊÒ¼19ôxkvZcö¬ë¥e¨t^gÉ—JcL,&æi[[ðk}ÕÇYkû¥Ýjüi·Z~®™4¿6Uÿ¥¸L¿ÒLÏ0þô´=gú¡t>ôœL;é$³¤™‰c3YÝkŒ"Be ‹ì;¯ì(ˆ¢¸¡ ‚ÀË.;ˆ€
+ˆ€ì¨ÉLÛü)}çÃóõ9Ϲ¯ëº¯ßƒ¯ú¹„š`•ÝBö‘ŽÑ^™}–ÜáŒî‰¦c:ѸC#íµ¯*߂˪“b±Ã*—·íÏqïë¨ø¿9Uò~³RñjÏýnC,zjÙš—%ÔœÉ쉴‰Þw´:ý}ÎHìû%¦0V¸ä¸ûäÈLèöìpz·æÙ-;Já3½Z=d\ZRÌân,³-›"M‡–-øÖµÈzÛ’#;‚‘s¡·à¡#KA¡¨è—) ¾yMާܨ†dš+èXóÑ&²rOÂDh³-N}m[¦>Ö-0;°ƒ¯Çšœü\+^x®æóîë¤s?©y¼.ðÄßì«ØâÆE ç^wT#ŠrP,¯ÆŒµCùv9(RT‚|Vá€5vÐG äN/Ô¶EÞ3‡’û(´%GŒZ‰O'Eº´”Ç:VϾŠÑº q°V€ûʾªAï/ »<:þ@Ü"Ä•|
+ä¡"f!
+\öí/ÍuZeÝV5û‘}S1åØ]áx÷”øˆ‘ÖÕ϶…ućÑMÌ^€–µò±1í̽Œýàã©ÌTñ/ÛªÅjÑ#fBÊ9Äé=R—MŽø^øùU+Wvó(©çÌü¾=³‡{V°CY©Ce7] Š¥çNÎTÉ åηd®Ô¦f@¡©GIJ¬‹ƒÉ€”£të±ñ}{Ò„„X~·DPvÌCÞeMÔfGj>
+"^;˜ˆ²{^•ß— Jv€”uð±Ç>6k•°Jn«`"÷å¶g;N6‰OŽ¶(§&ï:‰] útO†?6
+
+ØŸŽ…ÿr…Í“XpQÞ½B)"’A;Ÿ~f“>Dø¦—¿
+20%ž5³FmÒ™¹ÿÐ3# Ǫ>hNÅì´á¨•KXyÓU?ŸÛ ÏïÔÃbeÞC­……KØ’¿•®äœôqˆ¹ØõÄ]¶nêÂ- œîQûãk¨»y;UöÉ—Ž6q‚êÑ/tÓüº÷m ɸŒ´GÄÚôߌê‰h¨“vë!±ªîDwU­“ æÉŸOô3‹VêPÝÅEWÔeXÀ©øÙ„´ùÃéÖÛ;qMï_ýŠ×7Aî“?'V‡[ª>‘<¨ç3Ì
+ăŒI¬ª ¿H\ö2± ûV“àùAaÇçyÛôàuR´VË´åh뙄ú%.Yk†€¹šŸOƒöÌDʈzèWY»sáq/åº4ôŽ¢Kª†
+NÎLÄ@‡ëy#wÓ;¸º_®©x”«%×ÂbÁÁÅÆ4ƒ_¯Án§·g~J›(ý6)¶Ë#Ç æ­B”!f3ȧ]†Èð†0œÛƒ·F4í)¹°º_ª:w´ƒÕ™–¼“©x„¼ªG*¯¹„̲ƒ<Ñc:ÓfÔãF
+‹kÑò{³}5?W‰óx”x­©r^ܪìùêP›ªDdÚ m´`™~zå##¯‚´™f‰-Ù0/Ž7†ZÒºñ×¼TDÎÊ€”o¾ðJ^}_¾Yv½ï)‚˜¾Ë
+y7¡ÃWž8w3}"YaG6
+9xƒE0»÷ÇÀ*ZKÜLkMZY=Çjü³Ã%TÅù®|:㛊$ø¸ŽÙzºˆþ-¡&>+XEä˜^Š7OSÊçÈ—O°O‹[RQÊ,Šlò@«=!-¹-fba’6 ËoãŒ`®ü®¹ÒŠùa£„5S£¦¡Ê˜ _Ô¢Ëêža¥éPËjÙY ? mJ8Ùí ä–‡õlDG‡‡Ô˜Òƒ·7N×:nŬ”fÇ,â×½×ØòŒu|æ"¦,RZÔÈíšY¾"f$Õ¥läø¦ŸìþìvsÖ)–äv‡'‹ûBaÎMé*¸©½y³ß÷u;®çáÏv&TQ‹€à× 1»\±ÈE!“€ô9Yðˆy>1k
+;b!ää¢&*<i§´eìLTÁ5:s€ÿ¶êTˆ×TïÍàùyÞÅ'·ÙØܽ;ëd"#ôŽ –ÖœóˆXç{Y`ó4h$À³¾—f§6ãV怽ë·àê ä¦!r{ jÞ+”ôœž£uFsv{x*fçãÁ]èY«ˆ”sˆ``ÚFhÌ8Miµ}™]wYËo¿ÓñúBZJcH« ™IMa3©!j%Õf\LTvgø%ÐÝbÐ,a&ívÁ#d<ÌþœƒÔâ‡_]¦Ýþ‹EVùcÎÁHZÅ´“ZmÌ@ï9ßc‘3<< Á<ö)qw‰eGëCå'lEØ@ëÈxԔћÚMº¦Ô™wŠ7¯ìe~<wdc1»²¯$–%̌μ›;xºN©Ê:¤ü´]ÊKo hÏÈÜ™ot½x(™H:XÈ„…Ìî͸žÉ%¿Qˆ YÝ}læ“úÅÇaÿy þó@<4p±c„ŠË 8ØÕs‹l´òsJ‡~YîøépºùûÝñÖ½BÜ
+¬+U²¶ë’Ö{—’«¬Ž¼i˜Y´‹(ðt¨!ªGü\m¾þÁÍÆ\ð6ngž{EŠ´› éIuA=¹6n#7@6J[ÊHzá_!ü÷tEŠò/r_ÄÖµ)-]%ÁN—Hbð®&= (ûnÌ·þ+¨Æ<ŒéY/Ž”Ôö„†‹<ÕÐá«Ø’‹¬ »“TÒ éYí»—wM©Î@®Én‰@W¤7tÔºc Ü`-È!—X
+9yô¸‘‰ìâ%m̾¸‰T—¶UeíƒUI3v¸Üuïàmß½”I@M:^.„Í\[Huy+µ 21q¹9a¡ÂÛ¤gþ5b¹sªë‡Ãb­}¶¿fÿMßý”‰ÝT㟜*û ƒ¼—Ù Öçm,TÖÁ¾È×¼[Ê/‚®Ûb£Ã:üSàÃwOõäÆ£ Z£{hMÃ%õ¢ƒÑ¹6ë2foDOiM˜X¨Ø³5ª!×
+¹Ç_AÛ#ŠžVÔR뎰÷lüê¯Rk„Æ3ç°" ˜”°±¢znt™´YHÈÚxCa=¡1°IlŽ˜X=y÷ÈØ—…ò㻑é⮈Ÿù?Ååù•fš†ñsfÏÉîžÝälvw²“™d3IŒÎ$Ñ5c\#±lA¤W¥DŠ ÖØ{ŠQ&ˆŠ‘Þ¤ šü3ûæÓóåýp?ïsÝ×ïºÌ}Ýç:T±WÕ“ïÜèyá‘£
+¼rÌÿ
+beXIkòo’*‚ŸûZ¢ÀÝ‚;´V· Wé£ÞD ú¡Œ§4çÝ8\&6]ÙÆåÖ¡©s³7°C¬õ¨h €!€ü6èᔓÁg2j£KÞßæf7O³ÍÃ-Ý è¼“é¶gž5LE@Ik9^Eÿئ´]ÚÇSÇïÙ13ÖáÁÞíöºõeÊJjÿv̦ûµ}°ý¥®·Žì G£@¶OÙD³W'C³q y®C—w<³ÌÁÒ#ÆNÌ$JZ8Ì «/¨'¡S6öÀ•­Ÿ7P;\RtÑÑBçS·’Úx(¡¾5Íp õìtD;&Œøô„¦Ò0:|rJeHÎhJh¸xï'BIPJ­O¨Xí§s™îÕÎ,Û<<s[Pñ/ ¿ìºe¸ù™cƒÚ`œéɶ͠²\²>„[ñéÛâ ãÀ¾}3Š„.¹Y5\ÿèË
+¦.ð0hÕ¿ý̳݀-Õ 5fX§:_è&»hyq˽H¬u¯ÐË üÖ´]NÃMÍûúî 5 k¾”JÜÒ~ÈG.,ôüöœº¼ŸÎÕ\²GÍ@9d½n9²àh¹á¿–™ª;þ­ž×ö5d‘VT÷ëùgRÇ7 ÷DõØšà"×ý ’a_(ÿI/*¼q2Mª^%u´ŠËjú`—z1©dÕô—ÿÚ)ÁæZ©p|D>W C3¨o³þ&¡€nÇvydDZäd‘y¶ý-°Þ™å·üv²ZŸqa ¼‹jYX¿WtúLG¸611+¹ëÂÖOŒì
+é™XÓBW–]‚«ŠïqÈ) _¸Õ}PÛ'ükß&±Ì+í-p|ì.ÐêšÇš…UÌÖ0Y¢&áhÌ"´Þæà
+lSˆÃu?†×P ϧžb§¤#/iá}vXÚföÚ—º
+=kï@ÇËmK­éÁm*üêpd9µ/šN˜x¬ËáXÒʦµ½%>eïkŸ
+ªÐE1-¡:pÔ·Þ“ØÀ¼
+n±à{|fTÏ|w¾CjpJЯNÄ8Ðþ2¶`¡¿á©CÊ$GÌcóÝ
+Wf_‚eê•?ž,ugÛ¦»ž{VЯ\K¨Î`¦ànqWn`‡Ü°2ú6³·1óÏ|õý”et>¤á“Û¨0À§3)ôEŒÌ;[ëÉIèù¿A0
+
+älƒTc_æ×óØaÃÈLøW'‹í̲ë#íÙ?èà_‚JZë¦ôÁ<©83ªçŠNשµ&⾉ù·‰_wSÑ_øw1!ãšiô3 cŒSÆ‚;VÉe¾5<¨fBJJ}D-ÿjîG'÷Xø¸‘ÏJîñ9WVÀõ dÂDë¸0Ñ»âZ*$ô¬ÀZw®}¼1Í9¹—ØÆW¤}…
+d[hy ÁþEI/¹Q‘»"Fǧ`4Çw˜È”K¿2 °Km>)2÷p
+œ&ù?Åuþ•t¾Æ|fš™Û8S·;3My«)k²¼¹¦KÚ¤¹+n¸±*‚€,‚ì‹k¹¦fj&‹¢"ˆ(*¢‚¢²ŠâV§sÏýGîw~øüøù<ç|Îó¼Ïë¡$^6a¢W‡jž_#î‹Ù0¿º«ë`š_ÄÆŠI Y Ø¯DàØïåÔÜ›;cä E/1µ›qe½úyQÀöÈ)%K¯aᆎ²HÇ乩·ü¾¸©ìîòÛ†‚c½v¹7ÿæÆø‰KU—e“U'íˆQ/üsL졆GTwV†Îò‹ÿðëxüóµŽÑãE6q{—¸5VŸ¸ó±!ãTË"yULœ´ tGÍ-sI…óÛúøzѯ2"èš‚Q¬€o›»+·‡ëó7¥ôò’ø;ßPóã‚mct‘¡µ}s¬4ÔØšqÍÔžûËŽ}ºÌ¦ûô<î»ði6áúm¢!¿‚Ú#cVÛ‹ohš2škJûÑÚ¾w¢¢V, Öe—'ܽ$B$=¼"ðêšë¬ï:QöÏ}ÕA
+nòM¿žŽ÷{Ä«bF¹]N_,·vž-
+8Kôç4:eùÌ.©Š<ÌH Ë>Æ9äôbŸšYmªŽ1ˆ@Ávö5 >þ»qìÓog˜/oÚe¨‚/6A¿˜“ùÐü’Xb‘O€¹>YâñFàiÌ_sÜ—WWúÁ Íõ—äP6÷¦(¹. «ÎoàPOŒ4Ôg
+:`i÷™oöh0׳øzw–PàÑ‘*+lŠsu¨šáž…Ö«˜;6ˆø`/ó«¹õ“¬Ê] 9kmùX+‚ÜÛ“Ðá; éúP°©tÛ2Pö@ÁÏø·0†s
+›z¼Èçڜڴ,—’[ë×rð'KôºóUzÃùƒX&@¶¥ˆ¨iCºOË&¬Ëê‹Œ}Øô½IÞ)üj>Ñ)'å³ðû #óÊ %ó‡í)j¡„ ~0'(uIXUûröjoÕ#ë "â@V÷Bÿºä®Z˜w}m
+¯†Ûx¨¦A<3Äâí÷è$Ë 4|©rÏ2„K’0!Q"èó`Ëp]ŠCʨtH…8÷$9Ç-!änãóç[*úñÿ˜V¤ø¾GÁ@j„éÿZì,y´5‚J:35á \ªSͪë…%H89¡›Ë¥¦Böe »ãø<ÀWé;
+EÖñÚg6)1OÉÆ(øõ>µÔ§ªIÝ„Æ-vܱ7¤›Ú{O—D¢%`±ÑÚø=!ß-o,rʧ*ˆy;¸ë`M侘œå’2×ßc¢ì2Je‚^¨Àn)YÅ¿¨˜Å¿Íó¡a#¤¬ë’¦Ü–‘Ú«C˜øyQÑYNaˆ„z´Ñ? pn`áôl¢i õ§¶»(â|…/<_t8€\±Ã#mÈØ àðitÒ™™ÇóX„=¥Ä£a FQûþ4.u}ªdeý¤kÍýy¹öxm¬1½“ŒNyüýÚ;LÐë”eSÕ®£mË»ýùô*¿(ì;%#ð¥Ü«âÓß`7±>u3&`ྫྷó[ÏMœ&¯†Záš#åù44ˆkžGµI 9n£úØ%z:ê@Ž~¶Ú¹ß_ýò29ý¯E¡—–Û@O>› »2B¦WE)õkˆ€Ž×èÕ6‚] Ø»0× &)`ä²ÏW:‡½jFÍæHY˜SÉšñ@-8p§Æ9CƒlŽÖ%LÓ¡@®ÖHà[@Œ….v!b¬CÐP×dU‚{
+ój_ŠÎ°¾ƒÆ©8ÉW=³5eçf:ik ¾5Zû¨A=[æÐŽôMèÏkö'‹°Ë5ÇÀ躡!{JÑiÐûÌý ~à_Ýr,ÐÏð=1*Å«"Cÿgg0Ï—aÞylîÉ:·ãhãµ<°Â$,]ú?Åeþ”V–GñšéfÒÕ“mzœ,Óš=;MÒɨ±³¸kÜDƒ(ȾŠ€Å$îŠ-Š7Ùƒˆ. ‹¸uR3óŸÌ˯nÕ­zUßûî;çs»Ìq•ËtHdSHGo0½‡ÜßZ`–Qé5³)a”ð3äüÏCÕÿ؇Ü(áiäà±(²½`ÇÙšB?kˆÅàw‚„ ípŸ³ðèq+@‹˜Ùøȸ›|`ÙöÃ/î÷ã Îeà>Ó­@gÄ–Y´ûGÙ‘EÒuê&ºÈ„îÎ’r·äøLŒ’m•’3´¢Úêo–Qªb—žŸ¦\ZàTßt^m)Yu»3Lxt±­1²ÊnñL²·A¿ ­u²÷õm ;jhªk$ÿokÝo.j¸™ç"zjÍ¡E
+÷«†š«Ô_ŸÕÝÜT±›}ºNÜj/ò¾‚”óý@cÆw½Ùß±Küa‘_’¼z½éÙèüŸ/xǨoÃZ."®§W…T-YŽ¡Š{ó¼WצڳÏGW1eÿÝu‰>FIå›ãMÿò)cËTè‰à&\<àÈÎ¥í-ËÁÌ‚®rÁ¼…ùÅ+G?Ýc_íj(•ûzzõæ,µ`µqOM*º°;->4·¡WúËR ݹ—ÌCµ÷ä´ÜŸÆ o®,(;&Í,ýſyð½gä]Æ6
+»uc¢ù¹c~×&…ÝpŽÖþ´¯kzvfðc&kŽ =0p0ÇvQ÷—uQOÜ؆´öBn/óª“ì}õ·vÔ”â]ÐlÆ?:ÛÁ;a{Fêÿ9
+JÍ™õ£ôÌ
+°N-dرWéŸ>¶]· %¹Äý¶ÕÎ’D˜cÕغ¤Ç& íÔÒA9\f!":t®o¢æᎪñÅïë¾=cWw@Ë'Æ­â÷ 'ÀŠèа–˜ÄdMs’$UÎí®
+9›jFYh™ÕZâ |ŸˆÙ›à¿´5Þœæ…ÞòI«n†T„ò=¶2Ðxgs²²«ãá·TäÂm¹`k–ðÒ?‡{¹g •˜¹ø¨©W· ¨ãÖ^ű£GqâŠÏœBpÆÀ9ãv0K.Ók‚KlÄþŠðÍ¿õ“LG?*ÕÙ×|×(ªº²>üî™
+WäE§Ù‡/|Š.¤W.AnNòàÞiF±̃%&Ó­¬71á!^ »~WÇED–$@È
+lnlžXœXd7EuœÖ ¢Ðõ[å·´"ùÈÌfš;^*kcrÇ«¬¾g¨¾»=Õ”õÅMÀzêY@Á¯y"¥W¤ž¸z¦lâ‡+tpª5ÓÙS›²",¼¾©hÈüêéì·c_k%¨—¡µî±#O·z_ßÞà‘ã2ÁžúÄ£ EWظˆÏYÚq ¹=KÎ÷OQò*fÅú(2ÍÙWsÝ5P™¼È}ÙÞW™â•a‡ç„8‡¬5O/)»êU`³é°yâ` jlM(ˆ›E’C«¸+aéê>uöÎœ9%ý§ŽNá¡MØ7KÃfZ]ÐÈ€'ˆ¯Æå×v¦XÐm%³TÏ®JêkHÿcôÑwzfÎ¥íÑÆŸƒ*f¹y‚Y2Ȭ¹9Ö–{Å;‰{y°  F zÔH‡š©õ;‹`/#foÏ­Aý¡}¢­Ø=I/öÏÓk  .ÌøÒß]LÔ§ óØ*égl­I:­Ý£ kׇ¸ ‡ ”š ¦)+ i~½7× iù-›Ó¬rycŒ¹=‚)¼:Ú’ûÃ0æÍ¥Þ¦ì “´‚$[Wmrh¶½FóžÞO*ø«GΨÛ׊i¾O”üíÔóðêEpþ(ºF¨ˆYØ€ŽCH¸>ÈÃævô‰ñ.b$V…dØþ*—¶k`“¢>°¥¥”lMs<
+Z£UJ¨Ý›ç·ìi¾ÍC. k(¥%>{}Œ¥•Ôß6f\Øãó6'©ùn:=¨&m(ð¯²ú‡Óˆïh‰E ék#˜WúØùgŸßËAmÆŒF¿“PãrüêÿS\Þ_izïé=§M{ns›£·émÓhFkÓs5ƸÒÆ Ü7Q¢‚ÈF6((. . .† ‘! Côâ`OÁ‘4iþ”ûæ·÷ýé}Îûý~Ÿçó _x”„f«Uìéí¨‘ÉŒ›Ù,¿ª¯Ú*ª»¥b”&)ú+¾!^6OT¥4$¨„Nõ%ŸìÔ÷wú^u{ØÜ…†‰v­‘jŽ7è0 zgo¡¯"
+äwXOGŸèh]G¯»rwÇš®k)O¿™îúï·¦W/³FÑ%)·“>3‹sß;=AekᾸ*]/¨½Áßû‚N»t¼Ô”ýñ€5êÛÄ·J»Ÿ
+,¢çW·'žÿh_€<ÒŽ7äÆäÝåí1v×Ð%ꉶ»µûÌ*˜?³’0 3¢Ê¯¬Ëôg|)Áe~íZ‚üñÖÁØ—ô•XÄ}O½›¬þ ë„âoëÐÌG'ÿÎÑ ou=·Ï´Ý÷¯‘ëƒRf{XÍÁžÚGWÏ#+§æAgSlƒÜL˜X@é|äÖ¥îM7ÜöIQOÍÂö4ûúAh‰‡ÜŸD?Ò±jÓ@ßOvf]fק}E¯ùåBXæ¥ÃטÊÃU|©_ÑWÑšC[ÄöSg0aÇvxˆ9³0i^¶2¦¥õýƒraeü:6þ@Áì8^ãÂ÷¦èÅ2Fë ~ëãK’ÞÚB+øÑlw®c¢>Õ((N² ëoì/õäÚfYG¯ù ­Û¿†+÷KÉà† (QÏýŠ®"÷:,_3T|]=X–|ôæeö…•Bòh‰PŸ²û™o^Tu‚âôƒ•„ø°CD¼Ý¡ N¶i(ß¹ñ?‡´rT7$ð«88Ë«®\qoÙ•WÏ’4œÖÛS¨²­EÉÖÑ^ë ¡Ö.‚ÿîœAfO£^|·N-ý) Ç7zålôÎ,µtW‘¤jËó)9„€¶ßÆ·˜0-#
+ØËÞ²€¾0кcþD|‡ÃO
+©)^¦tï5,W?ÚjŸïÎ÷l^&¬¬¡C%¦ÉºØ
+9ƒ'ÞLÐÀè š ñ
+[ãS¡Ê•°¢YG‰c¡)Ó¯D×FÍlÛ"½n{ûØ·Åf¾wŽ*b[äOÌ™¨½ +w$¶= HØ1-Ñ°Ð1€A#z?¤aôxÕ´ß± ø/HßöEhXj¼«=OMãU)Æ¡úT›ˆX4}~yº¢æÕÝ\¥V\_Bƒ’Ö %ÉÖ±æ;Ç«ØbÝüžmªÒrIn%50Éq«`!dâ »5äÖCÀãw‘ù«½ ¿2%$ǵE·‡…¾MvŸGŠ+3 7E°Ç_³>W0j®’곿"”þvÉ2Ò’TôU6ÐÅÞ²ãX¡}º6CÇ+ø·’œóO§°9õ‚¯Pñ«¯xu©»SРçƶúÀïxø™ Ót°ÞœÔ kß>ýÎ1¼ôÁÆæFåЂàJËïQe糸‘Šþ?Ååõ•v–Àñ9»sΞ³;Ùd’LÌ11™$SÌMÓKìÑØÅ*¢ôÞ‹ˆ`‰ÑØlØ©"U X
+n"ߨðeÛ£˜üϘÒ_5ýÙ‡süFÛP{² Ÿwuö檜’{K/(¸éžiMê™øÍ‘†ÔÎú——½s\DTÛßw¢ãSc@χ4Tph›>sr˜ f—ãßO±*î ¢²n]8úç£Ö!Eв‹TãšnNö,vd”äj`áÖ{!¿ãó¯íNÁ3m=ºÆ'§‚<Àñª8p›”} £4„Ýï.ÓaŽY\Õ‰VÄé…¼KˆXºû‚Û@·iùØc Ð,¬
+è.½.¨°7XM[½m¿ObÊoJñïoÛ‡!6…嶇ÀÙ{ Ø !÷†WÑQ3²ð±.1fá°£V&3¬%@½‹ß{”R3÷|ŽìôLx6XÄ ÀQ~çQ2À‡JÂlŽ°©§èïÏ{rV“k‘^µo…ÍcúSÛˆ>lþ,™z>†ô\”àÅ/
+DÑÛúX? ¼­ö¦Ð !%s´D.ôÌ¢S]SÐÇŽáÆ»*AáÏJaMÂDgËí¬Ç×C2n{—ðEûóè Ó§ÖDûìñž¤åÙá<øI`…\ðαBŒQsn7È­Aýè’W5>ïÝè é»;ÏÍâþS£o›%8fi@ªýT°w—ïíx¹Îm|¸Ì
+¹n¡êÈ9ÏZÓÏrKNXËÁFw„]V)ºLΩ¸nG§ûubñ©M<±wõ¾ï$ ƒ.ʼ@/Ù_æ¶ú5TôþZGuÔ"8³ŽèþpöLœYy4Ÿž‰ÛØ„€ÞêÛ¢ÖÆi„²ç©Ålß*»Á+£»¥è´/ÃðG–Èíä£I68®5'ñÇ9jù3÷"®@)ªŒßä—]µA÷¤-I9<ãLËE…´Ý4­ý¾½$áoöAXEH'5tQó§™s[—(fæ3¿ï×*«F"‚¥t6f]· µ—G”̦ãb{†VdÁ½ÚùˆzºÎ‚Æ«x°DϽÖ<ˆH1ôÕÄÊé 4Å1 yá‘ኜy¸„ÊÙƒ%oŠÀ¿Y95j!>÷p™qf ´(™ˆãüb›…¿ØáÑŽ7°ÅžUDê©š\Ú TýÛÈ&ýé¾Øò]MmÜ“¶¦y—P¥{ËÄÒ\N¼Œ]ûÐ9IʶÀžèDq
+VÑ5@WÄMi—ç0Ew,°äiJÅ]PÊ­œ£ÐÌÈÆw†Áä»Ñ9»ãˆäƒyHÒÑø¹{¹ùy`Õ´+i/[²ñ`“f¤áÎÍÌ™™†¸°1Pÿ²ÑÑ5¦Ä·ÞžóÕÜ)ˆêE¢sSßØw¿œêYèS ¹þh©-Ã:R÷P)(¾ùE‚~g›!ÕHÙ剪>P’{_9ϨLš§UÝø©(¢ä£ý
+b4i{{Oïr¿ýíýñy?ç™Õ]Gyú¾âŸ]À…LóáÛ£ ˆå=:|’™ý½¾ÚSúf’pÈká#´ÌéÚt¿=Y5èx†úΩ$§k(YvþÝö$-ËÜOOf†ØÇ8L÷J—Î¹Ô 8rýl¹–pb°æÙ{ S.!ƒZËÓ‚Ö;¨ŠS±Ö`ëÇÅX:Ðáz4À",¼}ðøf}”‘ÎG&¼Ç¼½s¬ãb€ÿ”jðÉ«ƒ%¿ŽqÒn 1!þ–>xÄŽ’ Êò_…^ŸbƒÃþ°µ*ÜF‰øðo
+³ žèZ²nÙ>”=vé¹UÝ„¤ïšai_–šú/ÌBÁÙvª£å9•”¬Üëånô£Ù–Ê°NRNÐ-ûæÑ¿ÊÖÜ¥“³"%¿Úìc¤háZ‘ñ×%…O¾² -°SSÁ=ç >Å¥e”»4´\¯Yra¢øÞ˜:aaÆ6XÄ‘‚O¹\j’î+)9«#ȧ' „œ39Ï»DEüµÉáü±Æ¯wjê‰gú.Ù±¦©Î¡®-ÝDD­vB²ïÅY?¹fi¥šÎ²×¨”Ð+bØ‹oÝFiµ—¿òóh½  púé?ùìÔrPN]=aMŽNQ4‚ïîÏ S?[ .ò(®Å:æébû÷ ‘ôxž˜¿1VùTÆÍ Á½{ôÃþ6Ík¦UnUÄï£^yõøœÑò8skN° ÷ok’Æȉö›áçþì11qg‹ Ô™‰ÞåNÀ‡ì³ôÜ}½à@ß@ßRràÇzÍ=/`^,óè¿¯Õ /9x/ }Û0ì‘¡5ç'cgUì0;ÿá 6ùZ;,îJ[q¬O<ÞßÚ…xåžå`m£Ä|­ªæçÝÚ›®)r,åPAÌu¨IP‡†Y
+8À–@:UøôC=zl`£?[$ÒSç1óY[“œJ­õÒ¥«AxLµ„íøD£¸ðž¦!ý†›8DN¾kÆ$
+£ÏÉ%çËÁ§I—Ç\Çðšxç‹b‰ÇØXãÖ×"]JVÁátmáb*|±©*RÉGFIÑàë]o¾½ö§úÏ7ÜwŒUÇ;•´Âq\æö$>Í1Ë«tΉjÝFò`“ eÞRðSü—»KBìã$ˆÛÀ§ýäHÇø ¢ºÓyÝ© ¥*/vä¹!–^ |À.Œõ AÀÚ›bŸÎ اsbÞîDMÎæ>v¡ ¥#ÂÍí•ëƒÄØ­qlNÿEÅÏ»3ÍÉ _î†G
+~=âª|µ®ªx~0ËÅï¿6@uRôç–Šœêgæ¹GèP‡’‘·=.ÄÚ”Ô÷ÆæÊÇv%3s”“{½µôõÙ©†ü[sM¨§J2œ åв‹»ñïÑ AØw÷Ït‘’ÿòéIÐ uY”k¼:ko†GqÄ"ÿ¢´ýd hýµ |ü߯ޮDƒü ”þ\í0ýX•}:²‰€CŸù}‘Q¶£Ã'ïMÑ~#»¬Ä¦{&˜•>ЋÌBèÍžÊسm%Ïÿ£e¦üáѲŠrDhùý9
+{0ÓTîøRy0E„/òkëø#]ž©:¤G/@û§$Ìýio{¢îVÓR*Ú{ÈWKíøˆv|úEqaÜ-2ü+³óXσ]5¡–æ‚G )tŒ<×Rpß?^_åÑÔW;T„wÞJÆz?&n£¿ä¹g¨äÙF/ô¹W]¿k¦dï›ø˜ïf)Ï«eÁü2äÄÄ@jrv& °íqjÎÉ,ïÓ3 WÁN ²f­oªIèæÂV>cŸOŠ³.Õeìô綆ødÌ,M=òæL3þ…KÝ€\n+¢¢¦\’—Dží¬|dU”?°¢&l
+Öûjß%÷ âŒÛ;\òê
+¢Ï3ò"/õRoÎuT†/uÕd¸uþ–¨Y¦æΉd'ËÒ¦ƒy€çe䈰)EY˜å3æå®I$9µµ(Ä<¿‰[îç¡c<ô¦š•ãå#7´Â
+cVÐàû3m½ö¯„Ä!jæÅžªä߇9!Km%á»úš4ðŸQkÃ|&åõùvBú‹ãiõçJß«'C¦iè“…:ê‘E@ö…Tç¿bB†~ºÜ[ù×Ñ<v¼Ì%ùLÔìMuÍçî•K…} úч…^Z9'þ,57ê’m
+·â–]ÉÎ>0s«öôUñ¾!TäÚ°”hj¬¼;%‚ëW â² mÕa«ýÔ·9êN_5äB&ïÆ(»äþBkåCk'&Ü9€{í£æ.õ‘Þª°»«ýµ©>æÒÐ [zÞ†VPêž”ÐdR¯QL^ׂÝs„Ý–;3r¡[Ã+¶uãc†i—šÏ~ï­yw^Ë-îåV\ »ù bïÀÆÛ;ÑÏf¥9×[¡góC©ïÎIá‘JRJ°N„¥Bž®BÅÿÏpÝÿ£½þq
+ß¹'P Gpé;ZJ¦[ǯüiµøù ›‚›ë™­Å{´ÔŸ‘K9_4Ÿ˜ùl÷,-{O <àZÇ$³Ð¡d"¶'€\Û0-É6B€hÙ姆¦Æ}mÝ9ÉG;œ­‘–ªÕ~nš¥‡øAÁÉ
+”Ñà÷ÖˆqN¿xºãkrO/ îÏ77íÎñX;f[EÉZÀEîé
+l©—øqª*@&Þµv•G[ºKÃ@Ýê#Bo«9Ÿïÿ½6·ã¢×$ô$m!Šž¹ÁËþ°7I-ßD…:d˜·V âÜ{ÿÞŠ}[É‹Áz䳤7Oý©Ñ·W$ÕšÑ/ÔLÄoc”¼Ç¼Ì¨«ˆw—2^>¸Tòþ™Ÿ“põËÇ~„ä0?ëWð;Q¡›ý¨WÆŽì§c¬¸€fäKÿ¡š·×Ý
+<t}œ’)ÒƒŒíÅ}?€ê£9.Ù­dL3rìýůԼ¸»–.ä;—’S4@/Œ°ásV0ñ–4dSJŒö‚‡Ø’a“¦Òwb>\± p¿Ì¥e.vâR\#„ø)><Pʼn¹»Þ›r²P™æÕÒÖ¤ AKã¼s 4£”ž¿3ECª<130?-ìê3snáÎIR&h˜g›rbú†Gp“Òǘñ÷ÔìŒ`›´â&@¶é0—¢…l—5 ]
+Þ¥jamÊëËl2v¶]Nƒ³,|½Ÿëe¤îÏŠAz–¤ö«².ÿÓ©YØj—’<:Ðu¦ŽwƒuLâãvpªŽŒbÑú)ì hh¢s”ž½Õ_>ßšò|{´<Ú¥¢~^S9 Ir]j }„ë3ñÈçk`ÝOÒóWqÎ Ô­ ¢fØØ‹Mq÷ñR-¬¹bÏ,»Ô·È®qi•>SƒàlI(81Ö3ŽŒµ4Ç4«ðÈ(›…ÂóeqË¿–zÞÙ€ñj—‚ñyì'k¢oB??˜e 4ݬd}1rcˆ“½$©ù°1€}³5‚ _ľ7JÐ!¦o¡kƒ¢"³´aýÎn×m UFÚzKCCøˆIR–k†˜²<‚~c”–¿?2‰°'\Z>Σ½zà3·õžZ:d§–¶þ]ãPÕÀÝZn馜™é£Á§Eˆ@ v½³"媖_¼Þ[—³ð•œ(£}yhhÁGN ñõm„HÇ3Ý©âoŒVÇ‚ˆ±ôVAœJvž¡ ûZ+,}flêÎ8)Õ£â¹A;­ôpS/#A×ZùÖøµ:æ@SO™o+ ²vc߬ô”GÈiO¼‚ˆQ^×d'_ï«Bþ¾$eÂäœÂG¢üD?nzìe:<â2 q¾Ù˜»×G. $gADÅq2vú“ú‚ðÿ)èñ·&Xñ×Èñÿ¦§<ž¼r*X…ziU)åÕ•\ÒË‹%aÛ™QØàT02#ø(kgæ/š:ø/¶aJþò;{`èÂäœ,p*|`vZ;KÃõ¢ìç}UQݘð+JZüÍõV•ü•ðòö8ëËë=%5k{¸r0IHØ›@%*¸1Ï;JC¯ix©¿¹AG1ócnɘS¸Xå×]X€*ß%×£®L›&?•Ó¡OV†ð‰}@Æ›Arò%/5xŠ›óçV_ ì`†ŽØ–“ ë`@iksCìýU™»j!°ØMÊÜ”ðýÒíòZÔ®ªëV2²­Ý¸„Q*ô
+Î`dï|CÝŽ†Gœç¿°‘ÓÌRR‰®`—a£u Ð_·ú‘aûÓàþzfÑ–œz(ik ulp.aùNˆ2uV¼µË«¡ž)Fñáÿ).罹Ó-Œ_wvWïèxõŽ.¸î¸6+¢ *ÅJ‡P! BzïPzz ¤‘F’BI¥†ˆH,ëÝýSî×ßÞÎÌ;ï{ÎyžÏ£çQb¡ä»O<°©jÍÙÑ’+—¹Œ˜+øºÂ“~ó
+Û¾¸…â#§€óÉÍç^÷ÿµ.–íê)°¯.¡äÑÛC= ¾6„Jõö×ß\•¡“×GšS}ãéGË4¤mŒUâ›dÕì/¶qó‚ºÀ$%oE¿îèü¾Ò ¹èÅeyåÌs)Í3@ÌØшñ®aTªYZrÎö¶4Î(-Ž )°9{zVcÄ(âEl’öå ü ë>kÇ(þ¥køƒýÝÈ¡C$=´² [zlÁ6À~Mk‰J ½žaCVÇ©ENö±IXsi]ÖüÀ7BÎñ6?6IKã7ÆYÐMu§
+|÷¿*!èñ7tàóª´?æbÓ÷M­à°º%o©·&aŠšÊ;M($@2â
+ï^üÙ3Š‚D”ÈŒÀhUBP»µ1 Nèo¸}\Zqõ¸NøüÚXš|Ÿ{£.û³UÄÿb—´Ål"AÔÌlÙ5àÀÛjÄ£|,NÌÃSkÒo£‹î]ßTÓ¨1WúÈÓ­ù;ܾðOP ;²µÀ6&*¶õ$d?6ïæµô¶o“»!ozœiÍÙÓ‘ÀF|É7¥6¤"ljø^½cˆòlK-jÞÑ
+f…WNÎ1 ÏJ®.ˆà‰áib‘µ³æ†‚ž¯å–_³t¶¤¹‡èE®1^éÒ ¸Ä8(.v3
+LlRl…Ïó)IE«Ó¸\¿‚RZà ÂZ!1dP€ûËí2äƒÐ2=¶Lkr Ô&8{j.{GS§é%Æ°ùg ØŸy|®ÿ¤•^-…fl.!v↽yÇ=Øœ¾:BÉu¾'ç„5Ì7»&rm—VkbnäÀÊÄDô­Å«ãµ·ÜÀþ¯O£ŸlÌÑË­raùœ“2A¯JÜ\ Â<Uxº!—Lü¼3Aáys,ÙÑ OñÏ’ e;®ú£ùüàQ•¹[›@?ÜR“ÊCj2Ø;ƒÍÝ8&âˆÌrLaSÉý“Õ™Ivµ4òß>a÷wü}W xîsGwÙåånh’yˆ*O»ùë›ìÛq;KôŽ/>ñСƒA Í#ž;ºò/¨‰™'?X9„-‹„ãžåT/É‚jnýmÍ3*€Þ?ü‘§æXK!,)8C«\žbA© *1ünÔÀXŠŽðÏb²ÂóÄBŸ‚VáS·ÓCú®·Acß{ׂLbíC;¦Æ;½ŠÑÆ £Ì")¼~;8Uwkûju–W3Ì]ëjÎ9³Ü…JYÆ=sõ#nyÞƒ£‹è¢]#¸ªä#V¦˜å›F1{Û"¤lêé°° ökðn9òaXÙò*jÄCÂzB™gÿÒ=GÊŸ–VߣäÇ}в뷕lø¶Šß3³1
+Íý0ÌôL«ÖdÆåv)ßùä?³sÿû©ÛõE“ì'¹;i7øªp áœ¸ù2™%ŠqºQN,¢îÄkNGbƒõSa_<xdû¢[@ÖÒZQò®_0˜· ú8Af µÑ!yŸjîį¥\+’iu
+·ìÈb{Ëôœ]5ëçîM¼ž†G<^óC̨Yút‘÷ü¯ªñŠ­ úJѳÄÆØ7‡º®¿¤·ÿAxÅ£"(õÊjD«&0ù|ÙÑ*‡
+v%¨˜+yJÕÇ}RvÐn—¼¬îJ˜ŽX=Ð\÷—¼ž›Ÿ4 jÓ§áV=µL•Ð
+~š÷*h5[Gˆ®“óÉl‘6ò¹3T:ÕÆd³9¯‚fO]‚§ÉÍùŽ‚¤œ*zÈ@ûÓ}_¥|O²ö÷Ù½ñ›%çì£:*Ä·˜økúÝväÕü¢±ÄæÄõøFϵ«(åÖÛ8õÁyLĮ㋯O|FCxG>–²H_¼K/9~Ïèv¯ ¸š}ÒD§ïµPöÀ.o…D”äý»’ƒóø*&¢·1ÞófP0|NžòF ÷ÂPjk¶£
+(4—ó
+žQÉ$U
+ >á@É=ýŸ+|iû*nô¾M¬/ã+ö¼[9Ø•v[j` îGh/> /s{ÚaXÞ
+Éy„[F%ÜüÞ*É7u/§¿Z^
+îʇAF×/o~ùÉ™KÊ»Ln$ÎbFg)KRû²Á˜Iþ3*àf„¢¢ üY?ñèZÑÊþÇq™7µq˜q¸G¦é43í´“´“fb·I3vœ¶ö4qìÆ‚/0DØ` dŒ1!V·´«c¥]I»Z­î[«] û@ @È„äcÚIgÒïR¥_àýç}ŸßûüºYØtº¥àwz¿“Q
+%`¸–-qÆÕ”zòã&Åk§¥¼º—û(ª||¶€=»øº¨ÆOKjÓqV.8Œ+–1½æŽì˜7^ôØêæ@uc\‹Ww(DžqZ„y/8SûáÖ{³Ë!ˆY ¡Ýa k¤w%càÚqv÷2¿[ÓQÝšÆÙÊÉ„½›«øEÇPø²Ì_<-¬NínÀ²RØŒÖㄧ™Â|•  áÆI»ÆxÓnÄ1d"¢Xû´d¶’Ëiqv
+Z¢S‘Ʀq\sNË°«S1¤ºu$Ù.‹€zˆyg7¸LklÊx%JJOÂþ„Yp£èX½Õê1|¸)]ÞOH•€r¹W^VÑX»¢ 6³Z²± ‚5jíÁÞ†xé0«3¶{\·ÿïRÞ‹Ôêx{kùA·
+‚±ã …[¸üvX ü-…€}U‹áIÕéV¥]nU SÀ•Ï³ÿM^ïë`²™V®g=Âá ›ü^ÌN.û1×< ®£Ì•³±àÛC/¢î$aÍIJ¶¸TέúÉlô+±[¥y@Å}´2:òS§`öâIÂH'0Ç‹„Ù—÷ÀŒ ’`ÄDÌ‚Ïæ¼µß`yâÖàCQ,¸¼åJºÒΰ%„‡%6…g‚”Úîpgyò.~ŒŒ‹.ºVˆoB*×d1MÕ]àâwE™ôûª\õ]YµdÚª›Œé­ãqÄ62j†wBâGUû›}Š÷¨•eÍ×9̤4¢+”˜{>‡‰FBÐ|_ÅÌíÔìJÉnÄ!é«¢ÖöŸš.ÔcŒu_ºÿ¦¢@~ØÑAJ¯Ù²‹Gý*ö’Ëù £3ÛaDÚJku‡QÉ\– ¥ Ü›;váh£çºQãBçÝ.ìÁš“{ÿ$ Éq»VÌW}Zæ–C5]õK&÷7”KûQ!ý ´<P ˆÆÒ.ÝlÈæb;´$-bBÆ’¤i.Œa3aÒ#¦0¿$` ‹žù+˜©ø$M™»a=ÐH*Ø{i¿×sØý„ðI++bµz]â0-fî§z®–
+SGt¢›å †W¤4À¦K8²WI;e‰l?¾ò°ê_{p‡õíœ)ÜÊhàjBÉ*ÅQY*´ðŒÜ
+çQyjX ø¾€Ùøy ×ñµC6‰¼ÿ\[2üqnœÿ`Zq ]wÜE…¦Á°^;˜±€´º_Ã:Ê©Ý$áÌG̪ n³¤µ$7 ùy%àºHž”Š¢G´.z6ÞOâî&ðGoÉxá+ã´•÷&n/þ~a\ñæCéÛ6@×”4;ÛÄR£´@Ê*û6JbsnÌÏ$ñ›ÀÒl•4Яày.©E±[¨ªôL%Þå¯:/NÒÖߢ­¿óUßÒÏϧýø¯ï÷ýdàïßžš?wÈ“qÔ¾pH­t3¬Ñv–3QŠ§Ü:ó &ö]GÎÏâ²÷L{ã`ÚŠ.ÔBVC>èBCñÄ&×]±rµTÏYÏõ]û…Ÿ±M:凃æ8ƒX_W´½Žö<3—ÂÌ¡—y YKyËq§[ê5 4;]s(L)çV¨B™UYB·(Ô_33¿"¹¼KI=:¬_àÿÁ/Q l»ŒÂF•TlZÝ <ÈãŒ/«vå\Òåãn|)î2/ù1Í"¿ÀÍ#$0Š¢9ºhÅznõ©øÏJž¡†üÃÜUòò$mí íÎÒ™Û}Ïû`€õ»ÇÃóç 6x9€˜ÓA«²C”=oÛOðoûØw #é'~K£#ã
+À{ÜC ?t•³ºqî)ÓûÞà í/‡Äo  ßúÓ‡×~ôÑ™ül”¶ú?Ëü ÿãïBŽÍlf›{“c®Är3+„‘£›äì’Rt¨ÝE')GÊ=WcŒí3óù|¯Ï÷±_¾Ïׯ¯^?½ž¯×ë9H˜¤ÊʼMÿ¥[+¸Ý]<ìK…ß·8m×îé¶ãm‹ÜéÜ,/Û[µJ{­V½Ý¦;ѳs‘ˆ­ªdÓø%]C©C­¼Œ¶:V*±†C&´F²:bMòÙ|ÛÜűhâ:Vuù4ö?É/çæÿw'7ý¾Kÿ¾ÑlÿëJçy8ÓÙnŽ4Š³=›Æi]eY4–VƒXUâÐÛz¦u¦Y¡ÁÚ‹·iï^™©¹Üžçýç‹ÖûûrÉòãpAîum¨-¶#‘Ú|'’-ý 2¦Žsz­‘£4K½×N¬a–—ÑBêñ’§ÄVKpJÞ0ˆN¨ƒæåRƒšñãOÄ’D§J‰÷­kW;Vëþ¦×ewœh—Ì'£Â¥ï ÓŠßS’bÇ9g©C®xÝŸÙxÇ4EötãÉ-ª×”fÃsb³6(Iïê@9†çO£{â4‹=¾­ óáF{µ!¼pι,s¶µý¹ýMû¸è6”wƒèÚ‰$BH-†0r›=´d€!ó†!±ð:€,d@²Š¸ .
+Bžf‚\TOPkó\8‹¶üÖ©ÔVÝxeÌ»C)gÇ:O±¨ÖZT²ƒzÑÌnñ$o!”ýÄ E?°rÙ%QÌß(šá¬ÎNm¢Ö8Q ˇfŃš|rh žçtó‘Ûª­‰¯Û«ì)e¿vfÿ>Ö¬ý:¶û<ÛîuƒñŒ©1ž¨t¾Aþ«ÕýÁYíÖÈ…›Ås<O>‡{€ìhž l«c„t4°Þà*F‚2RÐÏê>’àzž¹Ö0)L´r(QÖñ!_WF«<.÷ŠÅ´Ë1,Îi}d¦às6µ××Õo‡ó/Q½Žd6š™Ù#¶(BëȆ 4¼ŽÂ‚ȸZ‡æC¢Þwƒœf
+d_qcì­¤ñ G2gê0{Œµ—A¥ê¢‹ó:žàp“aØŠž—¸r"Ü2/j»÷(Xw³£›ë®jÙÝ)\º®gIoK{¹¾dB—5Ÿ‚–ãx~¹eC Ñ‚_~
+ë2¦‰ö9ŒØë E7hÒKy ü-$¼ïÅ!$£ bÓAräceT…šV(€å¢gŸ?²j”k«oöÔ ßve3GÛúY™@™%®ç
+$G%töi¾Õ„B ÐUHU2 %½dæôC?a…þkå°8<ͱ‰­ %¼Œ#Cr‹Xa ¦ë“kåDýÍíÜ»ÝÑ*/Ü‹‚õU]¬8¨jQùÆ¿{g~"»'NâúÆNã;ûÜáD’VR.†akU¨¢ È«èJ†¤‚¤Ìð*¦’[@ƒN3WàF/eo~õàÒœzENã I•ç ùϲGÏl,Åò*­˜˜V8A×È¡8¹ß‡âq¿×ðHVÁäÓ£†úÈÑÉþ‘ ©ìØÕv<™þR Ó¸Éûkú‘Ÿ§ZûŸ×ºÏn¯Ë¦\¹áò•¤ñ5ŠÎ9Nì؈h «Ÿfå D'’!o3z@"²$"z
+ûº- “,cº])λ° °ß\“5÷Þiê÷¹±«-Iß–Y„5•8µÙ;0«¾ 1§wr<‚>¹ÿ¾®Ë‘ƒ™
+IÏëó/©à`jÅU$Ñ‹Æ^mLóˆ5z€±•0Í;,RKöë7´Núýž‚ÿ†êD«©Ä
+{òBù—{ÕÂÃ7J©¹×‹=`sÏ\i˹ûˆš{·Z”sêÆ@ÎɃGݪ–åT¾Lî 泄±ç~WT±Ñ)Üäʤpguº\EfžÁ-+XŠùcÇ+îêÍî¡ð‰.r¬¥:òÓÅöœSy9WnrÎôäœ<ÛœSô`4·¾YþcJ}T„îÇAmçÂÇlE8XDC-ØA‚ àbo±@³ÚÎоo%ŠVaÆkí}†ÓØ!Ë/ƒøB-ÆøË•â‘¢
+RîÓ顪͉ºeþÓs—/‹ÖX¬ JÑÖc “üÏË
+K&¨e@ž˜LëÌr„†94Gä+e±m×ÙBçíº½ sÀZЈQæÕw.5u
+/’øáR¼ R>*”Hä®G°è‰Áfâ lYiÄ+>vËšŸÞ’õÒ2~»C#«Œö£eº[$‡JhG!‰¼û¼<WöLõüRöOöåÞyL=T‰Òþ½ GÏœG³g¯¶‘¡«Ã‚`« šå¥B.ö2ÌhZúïï„©Ý2S’lPË…ái•Þ•æL™>–|ö1I°^ÚG½ˆžl| —{ôxmÎÙüÞ›_ýPRG8‹W©À“”]…ýc’6BŠ‰„Ï«ÀÓjSA
+ñA|·Ç5fì(ÀèíÔë‚âI¸„Ê Iuþظé*•OÉ •j£¡\k²<u<Ø„fl@ö^RÎü×<b'>Ö²æà1é÷ZB~·Ì[Gt:e…Xh¼Ia¯÷S"WkQºåµÂkÛ”*®$*©ÿCe«ô‡'(Åá*´òX3ÎqOOþÓdšŸˆ#!å¬KŠßKq‰o£TôÛ½÷Ó¼ˆ½×0œ ¬^¯××)Kýš*L—Œp7±ÂÒFÁßN^lÊ=“ךs¯l$÷a ù(ªKz–D´HØðƒÁÒõb5¾vî¿ 2_nøø=›9eÎ7Õí4p‹-V¸_oŽõê ¡v½5ا¼]
+µ½J¦÷Ôsµ©&<ÝyG’^¢°["C¸Ëä„ÚÝnAÌ„lX;¾¿(¤ýgÇû߶HõûšX¶
+Äïæz¬¦—^Wo7jjA³©°"XÀáÛ­ž^ƒA™œ 8d¹as¯WK¾·ŒðPë‘©±ÍèÔøvdr$©#ÝÛ±ûwg¤üw³2ñJ\ÅKú”8¯™Uežì?kQ®h-P+W‰T Óíù8^°õ刦š@7WÐáJº"øX¨CžHôî
+­Ý‹%¢õy£éc†=ô.J¨ù¤âö—Žý}b{ÖèŽm:Èc%[ìN¬Æ·©,ó‘&ÝÌ”§ž\méVŸ®jã<ÇNÞ!q¤e: ÄBzúœk¢~Qƒ*
+²æm‡h¨9'•õJ‰ ˆ–œñ(úmwÒãb]K)`WÙ­j¤Ã¬B0.£0¹R ¹kÙ©ÇïxTÄ_ãê©/s
+õ§$¿ê¢7mBÌžý¤X´—Œ.Oó:S.IG@Ï­E4Ìʰϧr8ÝxÐ`j€´²êˆSÖ‘ðêˆI´¥Û)%ûmBÎØMM1÷ç¥â¯YÉäoI2ê5ЙŸÕw]Þ™¦7¯@Œº7>16PRfܼÖå°œ¶ÒpÒ°íV]rȆÎ{Ô£WBVEKÔcšõñ[ç=´ê€F¼·…öSRÞ¿ÓäÖÏQ\ÙÛéáò7ðÈãÕ
+:”{i{h7&oO31_3
+å÷Eûû¢P´%4Îèk1=ærÄ4RvX) 2¦=hU&‡”– ‰%‹ú)Çú»Çöy¹Bz×i±õ†s9›^>ês‚Þý9Îèý–×,؇ñɧgR꺟Óvì9DÜ£b`o³°µ'榬ͭi)$Lº9 €Qè¥!¿zÆ/{µ‘â½Ïr¿½‘¨¿mLß×ü¯óãèß³_³ôáÏé ̪öb%­Õd€l%¢ýº WíÍ(å»)çCZLÞMs¶¢Ì—›VçjX>ú&
+ùÅ’ õ«h-~%|bb¾NéÐÈþeh[éÏc Æï¯_xåì6Ÿ”ü*m¢@³V"µÍ‚çlŒ¤‰šÿ;zwf‡KŠy¨’×ë‘ÐÜbZ§oTéø€úÝñÿÂ%©ÚSÏíò…á]ñd«W1Ö5®¬… ó³13Rõ—W[nZB[vgŠ{¾÷fåÒ5'>·sÉ+¦!´˜ø”Œmj"cŸŒÉ° a¤Ûk˜uéßñ·Ó0ý©Ä¿)@Ätãبvv¨Å¶joÚJëÉX¹˜ü¼µs×džëlxpƒT¹»ØvïX…¨»pRúÓ66þÄ86ä!~w.÷çܜɴ“C«ó~³Nªó‹Ñ ´…Ò{î`¢3;Œc¦,¬Á¿<u²)W채Sg[h)ðKaŇÈÒ”‰ùºÏ¢.sOÍ‚8ålÈ…oz5ªÆUû–ûï»çzïlOB
+–~K¨S—R3`z!ô'¿
+›Ç}2D¡GÔu×ù¾½ààôÎ]#CÿÛç ¿zsÙ]:úÔÍã\ú-g{S GðRÏBËÏÎ…ö‚€ôõãÓ½ÌEP¸štpˆgÞ1ê_¡ôÊ;>×b»‚²Îgâæ‚€¼·èâöy9üeŸ7‘´ ÆVwÄÂθçÖ3‹ÆÌþŒ(áç›Fá%©jOÉ€ï.¬†>..úÍøQ0t¤ã!266ùÜÁ¢Ù˜„œ™Òsn£õ]̓¢¾_JZ}^ûÛæ‰àŸUŒÖ{Àæh{LA®IªiÍ!)µ:(#”{Åè-§õVZ=Oêù¤c%­iÿíðs`‹Òrj¡væ¶ÉmÇëOÍ3õ7gûýÍÌm/úæç_Ù)=QEǯ¡Õ¦›qUßäžP›²pëÄHD3:p¤ÂU'ŒÔö”y¤'³MjŽ¨úŠƒ’î‡Çùø²’R{¶ËÊY)ëu\‹© JÅžeÔƒC®4¡§CÝ"dÉîBïÏ!%©Æ»†®m’ÀQ9ú‰g¾õGßôÖÁû¾»¾|OHA­3^]?\GT%ŒOD}S’ë‚«¨âض<«'Ö¦uÄšÀ²Ð8Ùò½˜¾–Pt\9&¹6.¦ÁÕd­#½€žÚœT“Ài3³Ï¾6T§â7ÿ#Ê}Öăå9º:m€½Œnµ>»ta+½3kCå¶'9€yJ7ññ "8¢ê.Išµ)—–ØÐ*|EX©I›éýaªÔ5ßuÛ1×vÐ ÊR:tiÎL…äkȈŠX×Q“Ö1Dh“ؘÝa /\£˜„ž
+‰oâ«2,ø›‹Žþæã
+òCOŒSŒŒ}v°rq)µ7¢Å´xpDƒfRÓ‰_Qc*‚rDÑ…sŒœÝ¡öf­˜Ö”QŸÛ&µ&´Ø*À@iþ¼79}éŸ l ??RêÒ+Ï[|BE
+ r®
+gÑ/®iX²Øb¶¦u ÈÁŸ¨ßü¢_Cøƒ° Sr´N¯w,¢
+Ý2êqÜçíIÚU^‹:DÙÎ4ø{ÛxÕuÇtÓ­ø:¡ÐsÐÑMÌai¤ûßtj"ÔÉå¢þg<NÈǧÖÑÁÓ,txþ$ j¸q(nûW|sà) '7d,´Ž”WU¢Ÿ:v>Ãq†#J<(°†*ÌçÅ‚7ÍŽÅŽz?ôßu®Àî¿Ç”w,Á
+|…SØô£†º¶N(û»ŠºþIØrëãTÃwþ $ÈüV&€ÈéÙp@=‰)†AG⎮¹W·­ãÕ?ì
+ëþ±7ßYT3:åØæP~çØÖÐj#2TILŠ.ˇÊ܆›+˜g׫ˆW_ìBá¹…ó¾‡Ü·¿©¼áy_~#c‚=9ÿHl:µPºÓzJGTCiJ˜„½€øÅΡþŸâ2oKzOÃø5siÚ¬´ãѦ²U³d¤T´Ä%ð¸/à
+(ˆ
+(›,
+¢˜[çXšin,Jˆ¸²‰¸ 2B(‚‚ₘ§™®Î¼‘ùÍøþñ<ßûó¹ŸóU.É»ÈÁ»Ø%ž9zƉ®¾xS„m á"w¤M¸}%·üdž’å™ÄÅ:ÄàÕˆ0ëHE—¢Ã%.a²yË"ª†ø¹Õ_—Ú8Þéúœ}1u
+›´#-‰s}¦¤îÍñkvµmt³„’l“ã“u0¯Ž‹?P³0v &Á2Rúp}°ôžiõàÌÄ¥m+ð/ŸÑ/œ“ 'ZFñ©†Yöm‰]ùc£©áDGC[eᮩڼ³•Î·û3 e»rrêÎ>Æ5Žï)ˆI§záXÝ€³–CŽ¨YÀÌ[c„T¯Šœ¹9TvÊ*’íØ=‹?ÕR1[L¼y¨ì±OßÊ;Òñj©ˆm Ì©ÄÆ[EØžYjÖÑ"³äPÇB}‘T>?]cTÞk<_Ór å’첚DÓ@Q¸{
+Ÿä]ä¿ñ­µñ¿®s)~#ç7wõš>Î|ÝèUü×ÚÚõÕ@.Ü–c!¶±òh—²6ðçh¹™iW
+Ù!'øæ[ÉÛ¢ÚDï =ûp¡¾`WNÉ9W“ ε•ÐS )Í.§$mŒà£NÕÜÊã9V±CäTˆ ×uÂeôç›oI¹z2Ë,Ø×6¢Ô‚ÊX'/È7ËF[b¢Îô¢# !Õ1Žz¶Þ›÷ËzwÁÏv!ù¥IÀ†¯}¬~²+¥¥ØE¤Ä-)æ'Ab¬¹ý`­¯ì’6d›HqƒøWDÕiWš‘·Wß#l QO¦ÉN6õ¶è±€ ôë:¸[RÊkãû‚ã;øu ~ÝО{Ë!Ä>÷ÍQÒÍ@³a—»ýË Õ¦aT¤„¿¢äf]›kͼ&¨M¸üeóÏ}½À 8Õ!«KÙ–Ró]ŸÙ$·’†sâ¯)8ÑúvÈ Kî?¼Z¶{¦±Ô2L˱`?L|Žµ‰âQaà[q~ÔæHQØZê®Sþ†`P^[>‡Ù…Å÷c˜H}GÆõ©Æä@ +?µ
+Êžë~ϲ‹kâ縘/bÀÒê›°d-{â’–FŸ˜ÀMÔP¾.ÂÇMðrnì(™ˆ¯ö@Ó€²Šñ/VÞgÜuJÑ ·¬<êp¶z¶ÂÆkzò"ŒŸJ¡ßVxTŸŽšüµâ#M]¦]Œxl̹ã/ù ä"]Ò^¹{¤fTßàó¿¯7Õ¨êàNàÀ÷9%$Ч’
+f–UT£iË»©ª‡^±a®S^ˆ¸%wjàOþ¢j, ÷M7¡<Šª„•žì`u{Êõé¦Ô뺮Ò»“<Ô™¡ƒ·7ÉÌv+Ù“ÍhŒáŸá”8%„„é攀qäÂâÛÜ``ïm9ª}›¸;AJxí”V<Ów¤‡lôD9¤˜XËPÙCÓGLŒ_ÛÛç’÷¶/÷P!‹o‰ñæüK¿š’{<W“²=Ž^í/ "§Þ &}[io=]j¡»¦«^MwÆ…Èè [£¡SU/w¦èéì‚Ç?Ívåƒ}†¬KI„N°aŒôðKÌ´ð¿KII·XÀ) ¤e ÅÂÂ.™±‰ßîîÓÕå9¤…OÖûà!óüW"ø¢þ·ô_vÌ\EKÑ-m7ä×vµøË÷Xˆu0=d‚¾4Ó’qCÙœqÓ.­JÚŸ©Ë4¼C<òéY>Ðÿdø¸-€ÿN)*Á£Ä¤{³BåxÈ¡¦¾hSŠ{eú˜w{GŠ;ÄDȶ„¿?GJßš¬M¦dÜh/Œý ÈrŽg¦®Ø2ZaAGØ€=»ÕPÏ4à7ᚪj:²‚×òÁÚ8œ¯&ðs´e
+€sæøYÖé"˜¡7´Ñç¼&Lù÷V#
+¼IÜfD qîéÚ¨¯Íö‡ÈáÛÝ觓‚d—6
+Ô¹“vRÕeºè/gÞ£ýfEh_ó ¶ÕX~—á±ÝóTÓŽy2)@Þï£Áïh?”@ä ˜àÉÚDÐþ r:SŒ<Ÿæ¤Û•UhëLYæÙ,9þpt9¸i„›0ÍÏñÛ—2S¯«ðû2ø`j'ýq6Ay¹òé:Í…ÝÿuoæA"Ø(É÷-Iò¦C]·š‘^
+쇆»Y­&Jb×›‰OSâc/y>S”t&/ŒÔ‹sý¶ÅèçG2pã‚ìúæƳùòœ£‰’¨CYE²m„å˜Æ cŸ›¤ùŸ%„0›¢†i›k(ÒvSŒƒ¿z&?ÏÐÃx¥æ¹éÛ toCt]h¿õnlð¹JPhŸ+Ï3I‰Ï÷úða¦>
+ÌØKz±'É{bEìa#u¹ŒýdÈõê;îʇ·¾‹õ€G
+#$Dºõ—#BN—«HeUÎÚ»,Oèøµðß5-).Ë"Ø=Û >᧩†cSqW«5c?)ÜØ›nîÅ¿:"!ÏÖwåîöe{ÿ︶úJÃ%úñgsÌäÛÍñ­®­õ§±áýÍFY6À
+T7§xY&h1»Ãܼú|Èïü$ßëå
+êÅ"s9ÇJ¼P2á§S¬X`WYë=y~+˜GÝÅo|ÇËÓý.^tûX §`·+•ù—s•oý´˜ÙêT—S%/닼Š¨SÂu­8ßí.bº9÷ÉŽ$?øЇ.8¹›íX_`Öþ_—«ˆ–qv’Aœï«ïxÚîHs[kŒqÞêÈð8ØæXÎF| Åþ«“ýàh¬(åFS‰|±Ù…y±Ò”æoøpŠ”u,Ô}‘W¢&«ß¸ËÊÓ}Ö»È0S?+êx” ùÜG†,·ÀbfœKoüñµ¶–¶?ÎŒVÔe‚&Øñ®F16Ä6J´Q#-3 X+ îªlÆ'Ÿ©Eœƒ ^’º)ÿéjS^˜®g"@Φ QmrH?÷j؇ÓìûR ðDÏ2äÎlYÜÝÏ-¨Çº(}{ö³s.âï}A±yŠž$o@y+XÖ…fžE%¤~Ûä“.5ÅÉVåÕ©Š ¿Þ,'þenê¼ÔT1¿(ð«µ
+Üß&QÝ÷íŠÂÓù¨Sv0šbÄ|Uó©·ºw厅
+‘y_ÕµT›ª<ýr¥¦àFÓÀ¹^®ÁÝ:ýhŒÙí'™‡‹þ°LpSÎèrAúÑLiüN5|KL 8ž(‰±ÏWc,ʲxC/Îïdˆ
+ù¾½Ç1__x(+®µdz­µ¤xÓ!vEEÖíª¨ôh–‡ZhÍõ6—"åU¨•÷hw%?å¾R€pãÁîOWD9­SÝŠ*!n^”íiS–gŸ©j æ!nœ`€;£urðæÇÂg'ã¼d túnŒº«"iéó•^L 7ÐÁÖIv¢i¤6Cû‘nègÅ~[ki°Î±“­S%p»\H>ŸцXó
+¼­áMˆyæ´ôþC+ _(à«Y,øRù¬nLx0UñÛV[î“‹•ZÊî
+òf…ûö»¶Žy³*dXä¬øuqŽçþ8 ffÄ ÐLæ&Ï5¢ÎÔ"Ü }ØÇbYšuŽ—¾ÞCößêcDØæ8(Ë0.hGœåó¹ý
+H‰Œ—M’[9„OÐw¨ Œ‚ X»—¾ÅDÌʾÿv>ˆ <¥÷4ÑŽŽr»”âÈLʘcŒ¯é´Çr5oÚeÍõõã/1™õ!ò¬G¨é²FÄúú™{ð¿S{LwýÇ }ÄC×X}|ýªÝ D´e7 Ÿýç/ùú;¡úæѽ/Y¾7µÙm­n6l~ýÞ ]Óz›Ñ£ß€žóic„X›áfÒغ 3ælj|© :eZÖTåëß{+oç¬fR[P é.\y¯ã.-«"VˆÖ¥µÙW!‚=¥ªz‹üa¥Ý‘ f>8FÏ‚[ãÀ?7hÎ¥1L[è èWUgôÑ|¸=!ü³M®&q63¯²”{>!Â|M©×†L“` …6»8ãÁ%VÌ6g÷¡v«71s_ë(tîüDpÅ%:ºA¬G[Nuš©6}mô†é(Zo6ôì£Ó7¢9Õ…¹œK>wÚ7¢#üÝšÒ+·s&A{[§ßm ÝëcÊá_‡‘ ½:•ñàpÓÖYçʾÿÏâ¾m§bBÂéH¿™²"<¬hM sÔ(úò¹D½O-Šq$éb>ÖF¬é|ǵ±
+B‰¢µÎN³‹ë’iþºþšAI8N62h"Ï›9çz:g>är3Et4ärêÜÂÑ M÷ë:ã±¢çpFTÓc4®¨ÃÚ(êÌA;bÐêFË45‡a~¸Ã1lÆ€sv® §ô^ëÀqjC«‹‚¼ôµù Âhg;BúÚê;¶ÎßtHŸÅÓÔ­¤éðU“¬2'«çÞü‚1[¥–ȧ€€$Á™^1úbH\´«3õ´–¡7«>lÑüœFÆ/P'©f.zÙ… È'eúúy ²‡ƒRwÓdü¯ z휸÷y†ËƒÂ®ÖºÇ†0ìÙmª¹3ºÅ"&¢jÏoÑ{ydÇ9äªu؉äÜp¦ô_lµŽ M-H÷Ñ¥3£½¨¬3÷Z2Ú¼ÔVCrˆh‡}ZæM1€ )i5V(º¡íi3bc‹làŸ¡ù¦`–Ã8Âè"T:8…_5ÑV§™Y?n±ääFZl*ª†Å è×Ð{?/|ç^Ù}a%HWSL0ÀbíUcCµ:~ªvØN·±$Q
+ƒ¿®Ž€$ç÷*ÎÏ…+cj’Ì|âÞ?\¼Q•4>8úª±p&­™•Us¦ RÎuq‡¢³ŸÌÓºLx>ðõ¯»„ò9u¢lN»]‡ve£È»Äá"VÒ¢ 熌"¢]g<Õ¹¤æPS²ž¡¯ZTï®D¡ŽølÕ¡/‚îdh‘ZÆ0&ôËùé ‹Ì
+CÎGe
+_îŸ"Ì3¦¾ÈŠ;u1ßbÖ½œŠšàl< “
+ZŠ
+Â\èDò?C#‘©µN˜"ƒO^\´ŒŠàÄ•;ÞBnN¦‘Ó‡}€¤ö¤†NBÈ}§¾2sÄð+æ×Á±²Uø#F—-ÓrMÝx†}úYâù Ò49…Ñt ËøU}º!´Þû_3$S—ù‚<È^¡Fh]>«n[ùQE€# ·«À™†¥:·Š™Ï€„KÛkH?LF@ñ*Œ’Å‚¼ÚþLwJ*¨8§¹ÎÁ%`œ¥çS§/ÿ
+’ŽAb›KRIÿ˜øÐCbÚÐ%’³4ç;ùVk}¯CrÁ,¸Û¨­Wù´ Î$ÄI~¨ùLYï7çVþð)xèÓ
+>­ÃDMÞÐzÜŸªAÓ‘ýt+@<F)þªù½VÇP8‡‘0Wëôô}¢ê¢ Ÿf*böülu5˜EG30ÞŸ¥er&&æöNƒ`*<Õx¼äæR@,Ü2µ!Ï_wHÅc?{>6¯úŽ(J¼õû²Ê…4×£\Èww¥¿—æ: -·S ª~ø6O¯©“¼rHÆÓ›Çæïêeð9Ž8¢¿½Hï@ú¼Üã }lÐe»7Яr¦Ÿûè™#(ÏVÚz£+¿?€ààD>’ÅsrxÒ÷žO­`•£aä
+Ù.ÆS
+Šµze2ÓIl«ø1ó‘䄲ŸmP&<#!$ö:0Ë×f½‚¢›I³'„@GÙŸCV2ã’ï<•òò–¦%µrÎSß19Ši{¦ØÏ‘¢v‚:X9ŽªQmðüÀº BÒ Brvê9ŸyW/LgŽpJáyå{¼‘…¹˜žœHµ ã|Í$mWÞ:)š±1Ïg'¼ØˆCžÐÊ€‡˜?Ÿ62#Ÿª¯¡ÿËx¹ìHvAô új­EƒïÇÒèÔ†
+¯šãD’Ó$:Šp]/ço^n7Qi,$[·s¼ö³Ê‘÷ÎõÔÌC„ Ü€VtŒ&Ÿ€¯¼Ü-†©J­áÐÂm·$x:™"°%ÌéhBi'*o¸µ
+̺˜É¨£°{€+ÖuŒÔæ‡0£‹Ç"#Ó\ZÇ3ójšÄ´>cš_©x›Àar@ŽtU(œ»„\±]I$;biX!Fp®'Ñ7ˆ˜ÛË’¸\àZ´ ™4‰¬cݺVµ)H 3ŒSºBшhÒÃûs€G†Þv"š™äÚüÄ¥›±!ð…º3'ƒ"A‰ãAâ z©°B§q™/0(IGD|Ì)0M(e6G@Qä‹ï­íǼ‰{
+…FáÃF±»
+hG)œÒBŸ£;…Áa´‡<˜<>aIs¤¯Ì"Ÿ9Nè |j{ÓÉå,.PÁÞº&i?æäç]ˆ]ÛÉbº´ôËñœ(Q­vá÷ÙDí»¤-ÛÕ£ðlÊNhœ–÷Å‘­kŒ>¢§X¨LJ‰I!Àq£1ÂÙºêä­*‰°N9ær´yÇ'íÜâ©2g×yªïɺžÚôa]:t{sÊadv©Fo÷¤Í+³‚Ó]˜'Äj»yÔw+ ŠãÆn~[sƒ”Ñ=‡­'ÝÜíçöºCÐý•œ>gêå þa[V“< ‚Âj5Û¡Ï(e僚È0¨(âW¡Â;[ /„•ÒÁ>t!¤€{ óÙ…Dø'i»óÕΪŒˆÔ(ïŠ `,'­§#e
+Î(2¤‡
+Ñ„pùõ ®—°¢.Ívlbž|åøM1YTbV~Q£’…IÒʶ±n/c`lA.1M꬞à.­Å\¸+‚ñQÙº…~Dh1é=lBì¦
+èOd÷;©ýJj+™Î<ÿS~&;“þƒÐŸoŽ¬<ix§<nÿüMÉtœfèˆÌ¢4É´£xðömñ<…r»ávéSü(:E€yvðÌ8UÆ3ø(ÿ3‚r•˜a6@k3‘Á/±¡ ùu%'uf¶å…·ÿBX€‹ŽEøŒÙ
+÷T¾m¥|݆ðfcÅþ—@q±UhÐ_U
+07è‹öU¿ôåû
+\¦ôùö'Ùÿíßo?ý׆àÕùüãíkJhXS¸†»âا©³uäeP‹sSlch驇ÈÎ!lüÒØÌ%ÍÞÑXAvÔBhQCðõñjBà,G[8<õŲ.y© ÖˆÛiæGeÆÎ'¿B`tngë h}Šzê&Ä®Š’H]ù‚‹ssé‹ é*¤nfAÇ”ëõ«<,nß]¾¨Ž>‰ˆ•¸¯ñ&äûV­›N1=°ô¼y¹í“Ah@˜Ðu–ïÛ>ªëٙݘ×E§Ò0ôÌ;ŒU$šÏÎŒ £.|ƒØ6êbW=7|{ÎilŽÙlÆïø¦Í+³ƒË¡¾?@Ô°
+%”÷²ø¨ä±S…øç
+¤ð*mäï1–mVú0ßFH€™©@Ía„O
+Mû&Íä.‡ àê&žNåP…²O» B;ö±a ·Œ«rt/ÙÀš5F¶ö!' é?B¯RC§~¼í‚­úœoê ú!ÔúrPÖÎ+ÔÐX£› *¦@1â4ýì)!ü<D=CpzÂ\üh„ðnÞIG‹…0H^@Œßœ5ägÚüÕk?(kä‹Óë­`)@%gÿú·‚(¦îNŠub7¡%³ëüåÂÕ9@†É@àT I>"}ˆÓÅ°‘ [ÈæUir뼩È0•ZrìÞ•!W
+J?'˜“´%0A¬eX\Uw
+±­
+CGåaÇóC1áiÓÚ-`B´^JµKE¡l‘Éؘ à|Ûtóò¯Ùò 9k#¯Î‘örZv­œgàåð»I൉`f9ÕeÍȸhè¾Jß
+½‰®˜Á¼±'©{NVÆnaý9jµ¡Í`Ž”ÓžN VC³°˜5ï·½<„ØØTŒ¯j®ÎÍî‘M”ÿì þ´>u!VMûb>Д¨N]W14üNŸYÃÁæ-˪ÙøT5,K9t-ÈÀ#snkOd-_æ*ÏNA
+ì§DÂô÷ãm4ÚÂ*»î¾as ]’ú,ó®#š”­5†¡¥ÿе=ŽaG‡rež( Ë:¢E[[L•À³^š½­¿Ê¾f@]¬}Ïw?âMÓÊž•Ã#`å>«\†®d‘F¸:Nz%ˆÊ ìê ŸÉàÿŒ—In9D¯âœ“\»—>Štÿm¿ “%éKÐÚVˆEæTŠ¬
+%
+’§ß6°“‰Y1!á§!u|n\|'‚ÄSó…iÌé‰P2'÷n˜IÜñœL/˜(iuêgG×|ŠfÙ“£¾Nž(ÁÒ¼=±ÿtâŒèî¨@§5U¶=žuÂmÁ¦ôpl¹“Fz7Á LÑYª¦
+Yôá$*Ȇᎆ¯ÀYú/8F‘þ‹ueV _l|‹{€1ïbÞ"ö]z=†EU¿5Ÿ*šÙ9¹¹cÄ`YL<›Ûâ]à:4*•ËÂßÏya
+®¬!O5ŒO¢-t—‰n;ÝܬÁ¹^BÇ‚ÄŒcÒùS:<!nÖ@#ŠãMÉv¬ûz
+cF Ôu?|¨;Šø9–qGHÇmÏÁx"SéˆØŒØ«ÑðòÝAbA}I]°u ÂÃ6¶RS>ù|6 æPNˆü]ËÌüçFˆ0'¹ûfqL¡Œ¤åS:«`˜¿‹.\˜utÍ;ÉÒѬÌñDL_1ÿŽ˜—,ûþ
+cCjÌÆþP“hÈ£îµçbÚh’moT–‡àR¼ãŒèp0v†änÎß1cÙXÄMvd“
+å™,úYLACaxâX .jzŠÌDÐÈa¶ìdKƒ&Ÿ¨Qö}Šö£Eã-K9±ð†”÷òJ79lܲΤ-VŸ¼´ýRŠ#µ4ûeîµÖdò¢L?Úæ<A•åK's4„†•»íΣ*ØGqÜZtžD‡"—ŒÇ—s04{„r·}añˆ–r]i¿\Þ›/Ûåñc xg[úJa2dÎSCî¶âÖÍ“=ø®¡s9ŸíI0†9f5*ë6Ñ%pu$’–!èò?ãe’É­Ñè< ó°¦–}‹Þ–î¿Õs PdeFµµ¬Mÿ‹D1¸¿°‘XÍõ¾í!ñžØ׎ô$ÄJddŸ£U•J@wÄ)¡Ëî†h’3Ѫéå‚TA2ùpƒ˜uàŠÖ‰ªú‡]™ùåÛãXùeïÕÓÉÑvƒL0S]Òy:݇ â¡9š¼ËÀõòTÞº+“÷átäv^h²Þ#3âÝò#»<9 ¥4ÁnRAYCdq0{ [®eä0 ÚBJ,;ôhd-âÙhó21W§¾ÞêG€5+ÉêyáKШ ;™i« )DcSÝ/GKè¸
+ös1úÏQÁ8Žšäu§Ê´ýÑÕî„©m¬ ÷Ý!ŠÏŒ ³k~U5j¨ßÜϯ `WCuÓž@% {.ûÊK®‘ˆ0üçWL € òåℬO5nØÓUžL_ÏiŒR”·ÐÒö*þ*€Ï‚8…ˆ¢ÁæXL –Ù,l2´wb´"¢9ÔuÚ;AìcС-Ùur[ªˆššEð ÝFŸÜÀ‰`g䳊PL¹åd|¾›\
+WÓY÷Š–9ÍdîqçOkP¢,mx[˜—bO1n¥òιܻͥq¼WÝðžœ{_|x©Ó￘¡kØ“U>±¨ºvªPœãþsƒ
+ž–õ¨˜;fª73!üÛ³%­sóôqúZO˯}ážÃùÒzÉÁr ¾
+ÍC¸C?Ÿúó|ÚZx*ÏBpJô6Ú5Æðf°*p~vÌËFë‘û²8 îçì_îç.A¿¹Ó¯o¼œ¯ÅÙÎ
+ˆ…½ÈÏó¾}
+€VMÚéáL.µÛ¦iCbÁ d³ÎB×°Í1Þ:°u´µEŒÿ»1žB ñÝæq ®¬FO²ÿ#¶Ü¥çÈvᢩ#¼´ÏË‹x «µ×"‰ÚwSPIÜm7F…WJ¾Åñ&‚µ¤Mƒ­ýouñ
+Ç^9êó[@sÀ¢Ãü"‰º¥ý¯q&ndzòXÅØûAÓðdœe¥d¡Þ<ŸÊ}F0¥7±ã¤ZD
+p»2/à‚ì'&`y5 ýëI ]ŒºØ}™t¼R5aúŸ_RÿÑhs;ŠÑ$ €Ì´GÑG‹ñÒæ‚«î¨)
+^(ouqã}T¯{7âB¶Ù)æ›
+µ¯uúÜ‚ <Œœ² .%.Ða»èþÊ™>çÑv‡¡‘6¼òuòNò®Ð7µ-àÚ§€š,ÕW tø]Ò€7—ãdÝ-/#…daE{¶pƒ“aa¢<AE¯Ž  Â\‡ÁÕ8…î-5JÞ±dݘ&$¨b*Õ[ Ô“ñ 16µñ7¬-.Í#™æw”¸ 6âŸß„ÜAÌi&6Ä\þ
+Á«µêD`
+#lÁ”r™bƒ`•ª‚\Oa=s‘̾ñap™xÚÚª2à‰ŽXœeuiõÀ5æ2TÖQ+(ÓvÊPŠÑüœÔ©H±ØÒ¥}ñ
+9"»Í cüyïÐ,UUcO¡Óq‘ÁJƒŒ-Waºì1&c®Ã[WÒV,Ëoàñ-°UŸ<¼<ÅÛ¹UÅNrÝ€îâ 0,¦Ý‹6¢Í¼á¾à±T—ÝŠ¼^–M6—Œ€Äj[APcAÃæô\e]]¯I4ã“ͼÍô Ê>ºßó±ÍHßàÀýÕ:EôHº¡½í0 T«›È‡i€’ì—ÕŠãÔpž¸—Ç|Ãäl…P]LÃÆbê
+ŒO‘]@ž¬ª™q™PQŽýγ]€BƒÉHJÑa@)–†üë>é9ôcR”ëV0=F@^áªp_¿ž±P£BE}Ïçôên’
+ÃטÎÛ(B¬µµ‹U‚MO:?…uwÑg¥âõ•Tq„ÒÛïJâ 4\äÚU¬|!i9My÷­N X«Gÿ4·nu<Í!é.µ Œ§âœƒç©Âçøzz¨Ķ:¼÷nC×ìNsè¾ý­N]|*Îy^°üÊI¯ ?Gê{òD^˜Kj´‰œ_«w¯ÌJqŸKw CÂýÜnw
+í=rVÜÏ[˜ÝñÅÒ†4©ƒJ÷„âRæ¸5IÊ0BNן=ud¿lù)ÖÈÒydÌ !Ø¡T$¦•æž ¶Uβ‡\mWëP5hŒ ˜êÊ=ÄAÈ Ykðê…È"¿o0Ð_¸¶
+¸JZO+*½”â$ä³™«W ®„)…˜!|Ëû¶ß›œ»ªîùÍÇn&voÎÊ°RU‚[&âP¾Ñº·G™ ãnÌý…)µYÖ׌Ô0—y©)F6GPˆ1ÌhMTn¢‚߀>· Ýíò/¡òR—£qÄì6K㑺ˆzÉØ 8Ÿ­˜šôQîÃýŸ1÷Wj¤RþùçͽÿõïÛŸÿÞ˜¹Ã(1’úàþ«ü6a,"ÇtÌ×ÄD±O¨Ãú 
+\Ui­£Òóå7 NÈ{Oþªï’èÀ®F´:“³Æ Âvq"²ïL ¥Ú §
+ž×9½‡ÁÀ*SB"yûž Ûˆ.JihðµÕs[pqµrê-4oÏyè­tÃ×
+*‡‰é2Œ¥Á2×µÓï,Îs³çË­‘:D³\ÆÖ1"ñAfûë¤4…ƒ§eñe sf‡€¨ <!IV¾Ï£ca2F:R»YêÖvÄðéqrX Çq¤‰) wˆ%Ç Ø2¹PZˆ~­’ñT\ε¶æ¯I9e†z!Öò¾ôœÅ½õb\
+Š;#£AJäh$f´n[ž;á…²ø'´tÑòá›2M¬F°Ädô $ì"ëeÜ[@ÔÚ+1b‚ØŽ't¡ë=~Q(dviŠÈË2‰!”ŸUˆuF
+Œ«@Ò½Ûõ1朦Êñ™|a`ѯÖkÞâaÎ3Îùè›UºL”äJv#"›:—dCêi¥¤Î ëF0• p'HΊ ‹äÎwgë`HÑ!Æ=ÎN­ž‡ÉØlq»€P<¿4&¬­~Ÿ«ÏoÙÉ⦼©Ç7äû5A¨bAæ˜é ¦Gˆ L\§Xø‡Úèåã„”¯¨a 3î„5d´ÖÑ‘«>úŵG•¨tŠR”±Wi*/›¢é
+¢€†5„/Šd›r%X£È)³$:t†eÔôuƒ¹[y¤û2DËÿ<$ˆqæÓ)€PxG—OýÊÒWÅ3¸ßQP)â´FuxGÞ•ôC1¥i ^|LÞ¤Ò{œÈ,x¨„ºï!*œ—Y5§ÇVGP£wIÁq['ñ f§8»Š‚ijS2{Cu$ƾn{sWˆÔ¦­Y÷)°rûu«W芹±]þÞÉߺ“uª˜Hš%Å IYÓKT ¼NÚ3ŒSÝâNl,­ËApÈ‘qHŠmCv«éq„èwOkóV=ž¢ògOvô‹Æ3 ³¥^•vAÇëa¿HÂ-"£TÒ/®ãYy«†ñ³þ*r26ݬô„°:Ú;µÕ<š4,ïh Mî‘ê8ÛI~4Æÿ/“$¹ŠžÀWQä<¬½í[h[ºÿÖï3v™´ÚŠpØ-t2øøƒræI‡+„âàm¶%ô KÎÚÓÞ6ÏO]‹¸]Ñf;t*è}ãHÖ»Ax<F«l/øÀd÷Äå Q}KF«q9bÆ€$±(„9]9 Þ³L™Ô.A`S²ç¦KÑ×C‘⊀Ø'§[-¤ ·‘“*R¬ÊÞ.ûÙFAÛÀ
+EKÚlû!× $âñb•UßSBÂËÝðäaùþª”³Àš„;q÷ˆ‹ ˜GeÆJ!Íšk¢Kô1c-œQÇl|ùªmC8% VvÕ6°²FiÒùåP X³GY‹ê´ÒÅÒ‘ŽHiÿ]G‹#Z1Z›¢¯§"¹c‚ ¬âê¶ö @ ŸÃ.Tª¦¿ÄåŸ2ž HRéº'J@7›ÓÍH(´Ü˜•Ø­;ÔÓø9Õé]fkIs,Ú:†ÛFL$MûQýmäofŽRf®n÷í1lð„H`€…êÖ÷h`ü‡uj‡‘€MV æ<1y°á!W§Ô‘¸¥C#p š=ã°ˆG)Éó±šSX[U‘'KÓ|Ͻ‚ùbqèQqAãZ#/ŽË.8f ý^s!djåQ3âÕè窈ÇØÜì£z§0{´Ô†eÖŒáIš²«ì‰} A­PDaë÷¬»ù½—ì(ìb>mw ‘ÊËHÒ›¤ÌÉ5Ci(¢è
+’&l0€ÂVÀ™ø§}ò›«¹½C¢‚¶ÜÕÊŤ{Ú°UR; “ÐP³Œ˜Îé£éþgÍÅž~ý³ã‹ŸCy²†L/TlŠÐ}(Ï?¾ QR 3´þÃ[`kŒ(ù¦è“Šg¿Î¹¸"(ÖÑà6Š·ôwèù Ù—pqAŠ„±´
+ÚÔÑ\Œt‚¬<vٔذÐ'40uüpµ#Wêù0*p`²|] a¬¸ŸB§’ìzùæ7†5y¯M›H» Ø‘c
+ £y-þ¸H6†ë¦§¯‡¢Ì;¡iÉìjä„6öÏ”:TA…ÉDk2ãDvF†ºÚ lZr «!9€AR–æPûV©¤`à&]†J™×é¢è'Kv%ö%¤7Œ€ýé–…xBt©é€à§8V‰&dbæxÊkŸ‘;Üò^Ô(!ÒYhë(8(ÄPÿîXßäµ{Ñfæñ¦ pÐ~\IÓFF3j÷¢Ëç.E¯,é·«ŽýBÆçbJ'Ùñ<›)ŒµÏM8
+OB0Ö1­ å´´|ëö'ÿåï´ÀT¹–ÏêfÿXQ®WÒfqMUŸ ×ï gøTN!3¸¦fY:v-ð[V‚ÔÐþÔi<n‹Ò”ôIÖ
+2‡T–i_q7 Úµö7E¯‡¢ë8ohç„ )3«gT½ì´Ë{ƒàþ#ÒW8zPþ1«¤PÑ:úc=45ˆîVIp(è=l_NàD(’Ýý¤ÂhƒÝÜéS“D!Й³¯bÇË. ìLÊ&.Çd¦AvŠsîÏ°ùTY&+TÕbœæd /ÛÝì²ÏEŽCÙüK}V‰#¾Å¾4Ák‚ºÊ8Ò%ü‡t¢´9±)¬";žç¾Öe-»|Œ3Åg
+¬\5 íÀãpðMDïúŠL
+¥!ì7ü^Ÿ¢†XWºH0Ä€ŸbÚ×9÷:&ÈeoÏÓ@ñÉåLÂ';&ª^¢{Œ ÄfÅVÕn÷e£qgèÊJm”p /„í¦qΔ$Nµ¥ùwjÖ/°UÍkxÈÖíKâºÁ"‚(= Ö‘:Ë"uJhÆÛ)=åL~e]ãù)tÞ$Ì9d/iW_ÇpH
+¾J èêðùk žæ“~ršv_ašå”¬ÕÄNC˜äˆiÍcç³—ŸØŠ7õZ£žÑ?Õ 8x#ò1EÑÇÖ°kØAÜŒ­•cÞòÄ‚3¤S³?ñ­ÀÈR vEG üˆÇŠz¹ßÀêìÖ*¡Gw0;ö*¦ŠÖ)òúP«=ñn©Šu§Æ)?5ç2‰@P
+0ˆ;ÑõiW™áØ(`à%ü$…N[òù$t€+öV 艴‹) ,Iáö(L2NÊa@6“oCÎEv”[wg6Ùe‡|B‚—;pkNð'ä
+nËa‡d¡Y$ȟȤP"¾ì&dtøÑ=í*[©zþÜL¤äÇg²'%*,(2ÊÚÞúZ¤ä…›FZ>Îa£Zoù--]_Iž=+ë Hëq ˆeàT[Nûhn•‹@ŒNœó …¶sª<%Á¦ÄìfRÐ8æhPvoOÉvXè˜Yµáž×¢¼û˜I<~š½3}¡ÛA¶3÷yL&€Lšú'}!:âžÍ€ã¥øJ z¼•×æ1ø9%ihy(i²RÀ{17=rc-u¦\š_§fT(cÖƒ°K?ÙxÙ‰]B³I H¥ás6žˆ«'ÕœýçIX¿Þ7€%0ùJñÜS‹¯.RIñ;†n%`ä‘u"Þ†ù¥Ä`2›Èþô§s¤ØY¶®Bi‚èˆ}MÃ87¦Ç8Ù«ðLmˆÁÓ¡=‹*ˆ·ÝßÇaâV~Jbºo8Õmhâfqcì¹Ê’¨Y  üv‹²l'NtB®¸Õ»hàV#N5þ¢/)ïÇÃç¾QTUB!äl)Ã)b˜·T¹Ç¢'Jh¶‚ N\7Ò\NIGöà‡rvð>´„3D8QA¼¨EJ@3æ­}`¢ø4̶K
+h°Øßœw ªÈ6±^Á”†kkóµ£&±Àñ÷ìÏ8Ä ÛŠc-;3Q¢í"Zæ|pƒû:šÝá[É¢yEØãB ÌVåÝÐùÜ7Š.¤àïÖ¥èÇ&˜ˆ³ÃÒáFúVƒ´ ¾L¶bó‹SC8
+¬!ÈZù…ÉÉu磴¼©vp–m¯â+l)ªáPK@ÐåÊt ñò ±ZÜ•ðAäÖµ:l!3bHçFÊâb7†/ÅééX_
+¸œI—š ÝÓ1(–d”z|ºLƒÑùkžžEQDhd¹6ZïÍ /EÒ"wº ¡:Ì#°| e<”€€6Déd¯( =B}¬öªÛm ÀÀUR@t_µ˜±f<Ád/ß üÚ´òe›üPÜæèÖc0‰áB
+{‹g_‰^%|7FÏÏ‚]‰þ^äÁ¬Â/˜™Î"¦Ç¥¿yDï]‰ž’"In³?ð|åëªãÍWl#‡ðàœhžQÔ$Ÿ­ö¦¾JèNâñô„‹Š~D…Þ<1ظ"_¾^†ÏóåÅñd@£×'žö.ó6}ž//LR0f­ÉçyJ°°8ù\ÝyþVä\Û§dÎç%ÇSPÈ?4 øOK±W%•ž4™mD£OŒÏã¬òâ‚ÉPßžï~á>‡/ÛôI, ®%vÿ€øFò·"¯;i]:óï“÷Š<’ÿ/ö^$ÿ÷?* /®”Û¨z¹J닶B.ÄXrà&z§¨òLu`V§Â‹x ‘ÃZwI—Y†Ü¤é»¤âHHB©õ]1µ·˜ÜÑäÏý%V ¨#¬ÍzÀÌ@|šd…} ÷H`6#}Æ 2¨¼ÉŽÄWñØXþ4‡S²>!…¬ž´´Ý±wŽL@/`­Û£X|
+
+
+y;çý~("Û™˜(#³>‰ƒ*I ìèIKi%û¼*)ú•¬ÑXÜÄëÊèïipGL®Ç¯áM’Ä´Îd-"¢ðG®Vßl8s¿›–HªÜX/éñœÆvѵøÖÓëmâk¹Yx‡ðô¨ô
+ãÅOþK8pÇQVoóÁ`"+1¤f?²×˜’ÈñÈwÜ%p~BgF¿öߊ.ƒÿõP„OÄ­Às!ïoq}F%H[ÅÄy˜î¾1‡ªƒ2Œa< ZO3NÁà¨LŒÆrøDÔ"b/cvBNˆÿî’±ìw~ ÊÏ› (n§
+$~•bS_ñy…\h÷Îð,`p6ÿé“Xp ª™g¨Ž­užøA"3‹Ö°#h"ÌpwyðhzÅAª;Ï ÞU“øSÒ·§SCE§éxÔNås•$ßÒ‰»„0Fê|Éž$c
+¿Ãߢ|òooa03´‹ÂØ'[˜ËâáSBå"È;r¶ó²Â—"ÛNåFš,?zL™¡ =Ïý±Ð{
+UFÈJÈ^×Íž9LbT\oÎÈ­É«Oä˜ã­Õì  N›s¡É«tçy5•*â‡ÇÎýœ¤I* ¥tæ
+S]~»"¤.Ër»qÍ
+Šéæçáçµæû¡—ŽÉiÅ‚F, æϸmßfÊ®ÖkE-'kŽEJ¿§ ÜÅ° üë0›Ãl-ï„‹º0·@¶ÿ:Iǧ8Ìò¥$>5™
+H‰Œ—Arœ» „O ;ÌúUEE@._y«mNàJVò2÷Ï’¿bÍðOÙY£ÆhïªÖ›Ôbýñfí=D5øUFõÇç[µñŠÑZU´G·'ª¾{‘Òbt ³÷Í[i£Åã× È9¤¨—* 1¯.fCJÝR gI­Ñ¤õÆÌÍuALkóRz ‰ÇÏuU+jFè1d]k‚Ò}Ž˜/*ÒmAÔ­mô± …Dtï¸âQ‰Ä›v]7•÷ðÖ3G<nª—^k«Í`áÜš×´(œ(nXû‚´(«gJg’!”‘iñë±Z‹Ö6&k¢¤Çê¾IºV£Xû˜.R[ËëkÝ]†„œJ¾¯ª][ Žª¶@.œÀ·úˆuLõÚ%HÎÅ
+ÎìüV¢Ë B£ØÐÈ Ý󌩒ɯî*cÇkE¬Žu¾Z߇@‘!m\ɯ¢<aA(²…f©G½®"yYÌŒa’‹Pºµš.>Špµé‚XF×[é]7*Á8©‹ˆdSO—U£€ýîWhÄÅäãŠ&«¯&ROH‡DR;ÌÞ2Ëל3Ä®«F×1Ô»tÙÙ!W=ÿòy/!ÔÞê•cotNIšÜA…®`²õ?ÖUÆ¡½˜¶âÐç H†6³ÆØ ®.¼‰NÓOvwÙ/ûé­i´CÕ}JµšCòKW– æ˜SRßOçï3c5 ®à­eJ6¤µ–j3ªÙMA¿A6w†Y/ô<šr>îPK¸4hó é & ¬»:ïI'xÏFÓ¾hJAµÒ%Wr¨x#£ÉåuŒ·¬V~º{\ø:dB˜Z» 4¨MGMô«÷^@(¹ h§x BÈeØ@Çw“sÀèhx;šÐ††òqAhU¡[¹ðëQ1Z¡ÛPÒºå¤AOžïåzÕPÄY=T÷ÃCKGoЦ«!RV!Ž¶è—¸ñM^F²¾X©áQĸ µ#hí-û‘Ï¢÷‘­×ÕB1d¡>ÚtôvO™)vìë*ºFkRqß“J;ÉBClU\ W¥Üµèˆ=¨¬å/åJñÂqÞú\.å9c‰o®_]^<•Œ®Ñ-óWÐÅý(K–ùôQféV‹våÏÓw åeƒ¬¡A”›)½Ï4% ­ˆ ´§ÏèDZ[œQM´É﯈͉Λ`c–æx
+c³…¡Šðo#æ˜Gíxåž1©MC°_M·{a–Jü6c°
+…^]FÀÑâRRî&¤@»æ”í2C“ó)&Þn T‰<ÐîŒÅ%‘Dl½s:®ÐçQ5MïT÷I°1a¦§X}G|ÃÁ¼ÏŽUQ!οúâCIâ¹(AÆ–‹‰`·9®mjdŠÌÖ-:“£h”ºÏ©êUú¬ÞTódóF’d!ŠÝã[ÏŽ½ê`#iP;™EYÈ`eNïGå<Κ|1tö;Åœ›á`31 [K©­7ovõÇtµ}ääVîÖ5^eÎ`Phø¯3ûRàñå«
+5)Ýó“-1($rÚ†ÊØjF£ûÄÃ/!¸¥O£=A´žAòFÖ¶„0”˜Ù¬tA¨ÍA{T³#äIÈþ‰Ú¬¡`ÈDaØü—ò2Ç®#W‚è
+´®€ó`³ÍÞ…\qÿî¿$ÞoUe‰”×ýP9ÄPC³±(%‰%lÙ·&\0*´‚ ÓĤWùE]B£99òü¦¢òCO"ÎmÌý®¯1‰-#­„²Ôø—ç›Ø>Y„¢)ž¶vŒï…(,[°K1Î&ò­W(S­j¦à€
+‰¬Z‡É3â-mä§Üö9Çóhb7Èšÿ6ØXƒ ¥ô4¦é@ì*Ö(ŒH™¿ŸÃœÆŠòíè"ÓE[ñÃøæ÷&\Þûá5JžM„M+s˧Â]fµ¨"•˜€º[;ù þè/w˜åÒæ\¬Æ k…l™Q¸@ìÃy`•°NOçdI
+¯x[Ùò†vËUïgsJ%³°KsC°ï J“Ew ?w‚<"7‰eÝs
+tÝ%d¶A f„ o©¤C!hŽÉq£?<ÐeyþÝ_Îìâßøqæoƒ¸n[þ1înÜ0÷»!ج®AßšƒÀ±*»ˆÕ2H×kqãýh t‹!c¹“Iiæ7tµB’§@h¨ºš¦yqõ‚“°ü™A-ÌÛSó†à?é:=ÍÙØU$6Äa>ƒq?8ŠXóuÿ ଂMF
+3oH¡M­ò0¸'™!Û@´L70oЊ4<]ŸË«Ð ö ,Þ„Ç €hp¯BÉs xuÕ (YDmk~:§ã2{O¯AÔY›€™O_ˆÍFe7üê ²†¤±§vcS×eÁ=Ž}šAVýÜtñ:„¶ÜfyóC+yT§DçT$"*X ‘¯ò]k#-Eç¼Êw­p {(¥²Ûú/Â.ºõûrŠ34ק8Ãwû"g†¯…q6AÁ²Å==@~Û¨×â’'"E+œôisÏ(ÚβÒ万ûuЯï¼É8cà°;æ; !' q¶óô(÷+ é€Bå/W›gxO/ Mæ÷Øt"Ró¶ÊÝß'LH}Sèݬ¶õwÌ~Ž~ϧcˆýgŒ¬B ìÈúôåU€ÐâIáyÝ\ndÇÎK¹î ¯í¼†¨óùc|äõŒëÐvÅ
+Ë ßßt±Ö¿6¨Jl±u)yÎZ5¤ )Á ¹¸ŽXíbÿᕹnÎZ ¡„RŽÇsT^[ë f¢[$šfã )Ëûn‚Ø6É&9Wýy
+mX Ó¡Óz žûܘÂÊâ´È»&ïT|Dˆu°¶»†…ル¶V&ÀæÅCÜŬNZ³s ZjAÏd«6D¼ÀX-BÝe«T‡L¹Ç쎩
+*9×Éý»íõ]xšñW }üÓƒêöwÝ@YVp΂«ë;ßUæŽt
+¹+Ñyåé:H 
+cä%ž^<ùª£Æ¯üécÅÐeµ¤§RTª«'Û^At0ñÈò ªü„¥gTÛ9×}”Þñ#$J^?lL%í@g”-­BªnkCÙáën5³j•BæËŠ”² bÛÁ
+a «SÈŒ‡¦a £¸ÁÉA܃“º'ç1×|à|Ô-f8µ¹¦§Â—Èã4ꜜ~ßN¹ Íý)·ás¾è6Ã÷Â\áš›¾X§×ÒÁg%á(»—ˆ>ÏÔTÜ>åNׂß@_Ü®óbÓWoZ|ñöÏH+0N„™lÖ%¬iŽ‹øç
+N‚@¤$%v! d¼cAGÂiÍŸ1ìð
+¶m#†Ì²”2X(Âdµ4ÂÌi/—@c‘´TN
+;d«…&A ‘™A·§S†»•6<—h’.Èv€|…žaYô«`ÑØ;ßr¤8olGôsšÞ‡½ø9¹ÀCH^áyÐPô`…¡@«MÓ)_á?µII§ë;!Ô¨×1ÊsÒœñ­ Áå¡Lî=!ì²$Âiyq ¤˜f7¼puBËqÙ¡#Y,½nœ+e†÷«00´CHÒ0£¾XÀ"øÿRp>ÐÅIö^s¤aXmáÐÑGeç%›vqhTvŽ&Ä—§cšÌ¸á”ó8-BÉ!Ót(…µMÉï˜Táƒã V"“ãsÎS÷4ùƒt;º1œ/ê5‰IÖèŒA*Ì° al“m¼ÁnJ2”}-’“æ³)¥Œ@’ ·î’Q
+¥Á8ÒûNÿG¥??¹½ }–#þí’Ü(
+Þ°†’ßJp£ùÆ(°«âK¹ã¬ÉíÅÌÄJ÷¤Éí¥=ÐØaè³&BEjÁ¾ä~æBBÀ{N({-Ošl¯j#¥Ÿ4ùt×d“Ò™’VB7M&„õÍhðˆí¬Éö¢ó
+ŠûY—›ô}€NFnYú›¢z¿+30£\ª—ñpŽIeEáìƒí¤Ì
+†’.,geVu*Œ¤å¾*³Bºb:Mí¤ÌW0Ŧj)8+ó1hÝs|+hWæ-hWfBxZ—ˆÍíbWfZÊêÙ%° ð»23€)³F6nŒge†Â±6]‚–^Þ$µ½Pn”MªùâýBؘxm²ó9 gÄ‘1 ír“fèĬ‚|ÒfQ/3ÒÙ7óšõ›6̨lÐÓI›(ܵù‚F *NÁ¹œµù: ªíZ)§4íÚ¼Ñü‰ ÿ̨—6£Þ€ì4uet‰SP˜¼{ˆI†8PýìºÜ.Ɗ˼DŒ SÊn3y·Ðf©e>Y¬‰Àðå>¦åÕh1/§ÓÞ |³Ÿ9e2B„ü/lÌUpд‰!ˆBÛ1&…û–£­ é¡ØRS¿*`D×m¸7 Ñù¿à“ù €V‰"®†€E(O‹3„/]žeÌÑŠ×ÜÀO`ª¾®Ê/`p‰Rn§Q­v²èµÍsª8Ä´Ì,ÏDÃ8a›OΤS3Kq·~S»[—9ž1)†ŸÎÑ3Ö6Õœ;—*hnˆÉƒ4 C%æ=‚Né}Õ=ÈbVW¨‡yÂø´ ’EßðÔ¨Éwzù‚Þ€°'W€L{µ‡ELºIøÃÇxÖeIërLczA8¸ÈäåÏB&ì_-O‚$ø$‹OB|:g~šòZ!Ìn!e´Ä¦‡.ù)¥6¿*“¿ˆ³«4î0h Ë mËëf
+ÈÚSà¼yNæx Æœ–¢Z joç›fýôù·ÕJó!è÷1(\rˆk®ŒäCN•Ù? :4Mb«>äLö&Æä®°™ðÉÛR®ï*§†Ë¢wz’yÑ»9Ü
+yáÊÜå¡¡_Bü*ÆŠ«¡û91V¡I[Wñ«Ø…røÃoTÁ«
+®¹ íԅRFºuqrZk‡¤
+XðG»Ær¨XÝSF… sˆR~õ"’Y© ¦[ ep‹%?‡7ÐÕ‹÷Á¨–E Åg†T±Ò’B
+ÉWïÜ5e¼‡´x…ÅH.ÿ8qWfD¦ÜʺI¯A§™¦E¤üŒ5WEF”®·ÅØ!*"hu†0¹òÖymð0UHî<HŠQ¤:‹ÿ8R~ÅX ÝÚ Z4=Ô}÷¦ˆ
+#Ãö"ÊBî˜Äß‚4º½"Ä6›
+qñ-üÛ…ÁšçˆJÜÁ t±–Cˆ·ëª4lýáÀC7‘zl»# ¦GÎðc˜Á‚edKê—êP…Ùµ°8õlA§ú°vàš¡§˜cûvÒ2 a|VP‚t¡Ožo‡ ßß™ž_² ‚@œÛX;‰Aå¼Ô–v Ú$4 t²ƒÉtŽ¶C1O«VŸåô
+©Ûˆ¾×Õ¹
+Ek[Ô¶7áox.Õ%¬’ÆÀp6Yµ1ÏapxY á‘òz~Œž‡¨“ xk@¯ª?s £.«cMŒL›‡@”UF2æêúó¯s’‚ò‘W×NA·ÕF6CK™›ajÓ•2Uf„$Ö`Ô÷ʦ~^ö/÷²^Î=z¡ÃÒâ49Tm ÂT¬ËâõÝ{‘þ}oÖ~ÎÖò=› :§WmÜ«s@û½Ä‡/­úç;S£ sÀÎ(f¦ÅÈãpÞ¿A¡³™œ$…›y±ÇR&Ón»vÉ”„T¸Î«0L'¥î(ðÝèïÔkÁòàuq"µdÁÃxC8%ÁµzcYŠNâîñÐû/! f9Ü~<§qCÈÎÐÎÙôCÏ»¶š§W ÄVËfî¸Â5¹B>,OID2X$siÕ¸UYÂX¦SW"OsHÆ·ÂnÅ4έK5· /½ÿ} Âbxm—e˜—ÉC@¿œ†/S÷~í’z:_òÊÀyœ–S®kïafùHyÀ´}¹ |HÅwWTažÃv¡¥¦óò°7ôà‚v`ìç
+¦qAjL²Cbê¢<cß1Áø €¨äÜ~Í$Ñjƒ3Xª¶€lçÙEdtiÙ‚`véº§Æ áÏ„3šÄ®bÚÐã嶮Îé’~zc–q@;b‡b¾yux
+øÝ-ýζ©ñGÊó‘dJÜX^ÊâÂbÏÁ‚õ>–ñл ¼.«”µj Zv0 ![È(`-\–“±§cØ0ãŒAžWç`ù+ XÚtQlH”î`¾n(û¼‹e#B®gbá&a´Aœ aÞ˜^%7L-Þg3²ü>¤?¬ä˜ö/¬xyhÒ÷7tîv2KCÑ/FÂ= {Ý  'Np§ë ³–ÅòBÈd¬–à>õËh­Š^\P®¼·ÖKl*©ÇýG»N 3_„ñÁ"QWä®f;9ÊG‘Z…Z±PäL'¨ª_ßNµ÷1X{ 9åŠÓ Úxrv›À´sRÇ `×h/ ¥ÍäŸÁ^Ä^#oWqð×д¥Œ~ýžŠÀ¨ÁÃeV^¶(”`©T
+"RÂõHZ½=CìªÇB»ç<¶‹Ís×å4ïsrœ bÄsχQzÿœ8¹ÏE‹ÝaíoVO…—¨aè‹ ò¹âéº'ÐÇ+1Y¨™]_[·Ö>õÍ@“üB{m `\ÄCpH¬UëBö½ŽÓ&aä|ƒ¢
+%®aÕ–å2jg$y3ïtN*­ÿØ7Û†ôˆŽöͬâ6ž‚GD>Jÿœ¦‰B¢Yn·ºM©ê˜ ó¸!…¦Šaè!3òˆMný¸
+ÝgoM8|uËöG|ñ¨®ÆBéã(5]=ªß;“Ç ýÝ?gÜ—7˜œÓ-ÅŠ+X! ƒ°ÞïVwÇ&}”Ù ‰÷7äµb‡?™÷Âl¯ƒ¸Ž ±%‡ÝZñŠdLÉ<î©ågZ„I7„­$NÖFÒ<6„?C’8/;„+ØxZ¯ßh9ä<l<¾çH-c Ê³ÛMôdf!¤ ^Õ$ä ¡‹tÆuc RAŽ–.Îiwì)­Cê¡.¢éˆ.n/‚C³ÞáQL£XŠ·ï-8ÚP0Ǹ÷Ôª²Œ2÷9tNäåT¨X†ÎÊ24hM'_ÜK¡J‚Œ£¨,í¾xÆxo;9“Û[zÄm•72Ú1E# @‰fÇïÖd¬ÂŒ4mT¼·l6`—b&26«øI®;f8ºuòë榄f2E1‡‹bA_ZƒQ¶,s5^¨h}ÙÚˆkTsCÐf4e[æÂÈK«%ßÉüƺù2ÈcùÑ·±|\jdÒ <³<ŸeB™ ðÑŒg–gÁ¥eØ6ôuŸåÉ-òƒ×–|£«žŽ—|HËŒ:!-<ÐÅ9éž#„P²vLŸœÁðLö
+šðª=’61¬7Vð‚ãÓ1Q“W?˜ ±07ÓðÅRÃGÎJáâz6dV†åïLòÚ÷Ø¿P“Yñ:‘ü ä5G|B ¯ƒ<’?Î$„Y,2ŸšüLòù^: HÇŒYžn–åÛ1K>ËS ììÀ‰¤ì•}A¨­£ª]ÊZn”`+þ9´n_\gé>Í'­…òâñ¨ËÓƒl^™U#þÌòéNs(rpÊ3ËiyT¾Ó6‹y4yEO;=¬=ü¼ òxžÏ;T‚í/hžwàʉ/§q‘å¸c®zŠùu“Sƒ¶3·å¢êk´SÄ#ÄV\š5Ò”ø|–­+š?¼ì„u4­0Lš^y4ÿ#þ^4ûÓ›ÜÓ‰Ãd³ØnÚ¤± $à”„þ悆
+{º:d/†æ µ8ç}sAñ®ecÒ|diµ}¿“.~ØÆaü³HR÷F›Œ˜ÐO䲧°Öà„3:Rògè´Y.½}zè˜:ß‹"¶ñ¡í‘ÐåõçÚ;ÖEm†ž1/MetÏ¡£.Z•‡ ?š‰bPKÈ©Ì‹WÁ‰!ÀÑ-²‚™ÐLSÑ:·‰ò›EnØ9RWjß^"èòƒÄÙ´PW‘«„åè›ÈÐCí?\PæL¥</Ù—Q¶e"ñ&F†è™þ"㲞Îí73êÁ?ĺX<µÏ,kÙãå”®šã ˆî±f)Oá Ô™ür®ì^ŽnAŸ 5?6†w¾Œ¤ùŸ#…W(aÖ¦%SOÜ©!˜Ïˆ˜á^Ú Û3ŸâÐ|K>6îIæ~Ï Â"7Z6©..Nðg¯C{rålwõ¸êè^ˆ›.>‚˜ñiž¦|Û Ýmw¡MšNÙsÖ”dNW&Ó†ð79S\‰U&¦™
+_¡Æ6úË“É’#œY ²÷óCËšÁFYЬqÁn³´´f
+ÊÈŽ¹Ö÷}<Q1óaõs‹0¥¤ŠÒã Æ£d¶C(ÌxgUl­qÊ<Fb$ž(¯óé9M\ì0RH4aú¾Ø'7qêŒÙïÓS9½~ot*IVGò©HÌht;›-" ¨¯Xf¤ Q ð·U“E–Ö®:×X¹®-†Ú1%–?1TµÚdPï™Wéöz80’¥I£ÿ׺t†Ðï–e#˜q@$÷á‚âZkhJ$xk²Bæ“lüPm&‘>W/¢!¾°ýâÅÍÜüÃtPTŽ—š±`ì(ÓD‹¼.z.$êDÎà÷ÝÇg9•ÓÓ£¶ö®ÌŠ‡|øçhd
+ˆ×‹95O't V†?}_°´óXÜ^¡­ë$=8m1ê¡ÚíF`EBÓÏÑþT0š¥'†¼ûÁ[/O¾²Qv,Ë9O 8”ÁjÕ ®*ï 0b\Ýèé4mBÑÎ y±êÖ*Ê„ÇÂeùj'jÚJÁ=üGÁ¢l#¢  ’,÷fªÇˆÔ.)²Õ¼¤÷\†+Òá×D[²±ÀÏïMN†‘X$gc„<Y¶a/§OÌ îòÑxW@tŠóܡBת0xUd2÷9 #&à[OŠ÷gåü¹Vg맨É3^GÇi&Æeæ-°Ò‘' Lù
+òQØLG”ôù¹+èõ;-o°}>ÃI vÆ}äGï(L¿oÏÎTŒQA8k=€Ï¡`Á;䢒Ì_/¢¬Œ )Ô!ù+zÀnK>ä%q¡Óû{1PPzíxs„2› L#íŸÚ A˜c2Xˆ°s±Spæ#‚_ÚS{aˆñ&]‘¯Dë —.UþS¾ô
+ùaô:Ú†Ý-¤Þý©ˆ˜Šš‰œ²]aí²4Ñ}ã5
+jÚ¤ ÓJ$’Kž!D%"F¼ƒÅ= 1õŠ8p.3}þ”‚!þ­Êß<˜:fLyÆ,õd}€°›èœÛÙû9YÀÒIíÌb†õF¶¿ìG…/Y(E®ä+ÃD­ù}fŸŒAÁQ¢ÑÖTrQ ÈÃÎAhp‚Qݶá`E'îbŒö¡gìÉ ÄœkŸº€Ò¶}VlÕ¶‚¸ ;Qžæ;:¸ºlÞ~7Ïf\1[cCø·|
+¢öwýH/¬!Æ@9a¥E=ÓçPÖŠ9U"Ø&¹*)òüaݤ8)³]áy"¨Ð?GôpI´lzp
+úÍçc*ÕïZ îãÊ«G”¹KìB{ªÂŠÏü‡Aÿù×s*tùÂ1…%…òزèVèýµÊ±‹5ü t¹v‘¨+yg[ ½~Jt4&;P¥|´/–ƒ8ϲC'´oTžz’@ä1™ÖÚŸÎ’JÅ/FžÀNjqç(ÖôïOñw²U¹Ä8=uø§þ<„kVü-h‚á($Zk>„Ê_GPfô
+¢Ò‰-UfJ!,+GíËÒHývt
+SU AR:fÕI Ó
+†+îs”ÕkÕÆl¶È@Q‡Xl™«Î”š¶‚Ë/¢¯S1Ë–ùúèýëbTBÆ%·åý16
+ׄ"w&x{:«Sq
+äÌ"ÆcC/gæÏÁ¸ŸÃxAöì*óý6ƒÖ•ÆüSÚMå{0ûÉ^w|¶Ó…¯8F¥‚<­8ä™`?Öä‡í -(áå¬+1Šλ×s¦KCN¯ú§þ¼ fê—¬2†U~ãà6~ˆ‡‘ÿ8á´¯ *ܱIwtùÀHaEùSœÈysø…ñÆ°§POõ61)Ñ@v/=ø â &°©±o‡Ä?x„Ô¡„Ú3yâ»C¾øù× tòuœYñҭG‡xñ9",åè¨uÛE¼s6Ú§Ü÷µå¯»Ä²yÜ „l[GáQK*M¹ÊGS&1{ Pùûë‘gâÈH
+‰ðè½%©¹È]Oø’“ϬŒðœÂ—–"SÇÚÊÓ9ºÙqÔzÌ 7.,↨锔òWAN!l>ôOA<@r¯óANÂkŒÃaÝ^µ‚|Dçdž$)3AÙ/<=˜4-z̽Mo“ñÁqSæ–Ó·A§öÿõ·ñmíkÖåê™·‰lUõºo#ôѲïZ<¸€$b•àˆÅ!ý¯ðó†(Öᜭ*$ξ0y÷Š
+ŽFÑéxZ.4ÚÚÐloˆxV5T:B¾
+s£×ôÏ?uA,J]ÿc¼\’3¹q |•>‚à›kmûÞªï¿/I°ì¿Šå±Ç£èpCEHäÍN~å"þ-êQ<
+¸J°°Ó\SgïÄÛ™‰ì£PÈÙ)ƒ©@ü˜ÅÍÕR%óêqãŽÁÿ‡åïË’jöܪ6âÛÂÐm×ö¥¢]¯g[¡šVؼGħBÒ½ñ3ã^ñÍÁö°mQÌövìÊiw©Gç!51#|¹.|p0êu ²+¾Cª/’“—`à׫ê‹ÅÈB»»C®Õl¼ÏHû¨ VÄ>:<È•DeäÿŽÖ– XO;éê—PßÞë[ ’ƒíô8ôë¨Ï"@:¯°Z|/ŒwóʺÔÍ´®wËA¥Ë¸JÃ+:€Ðµ”ãF‹^Ä`é8Ü36™o¯ «µJ€r‘¿ãõ}ó%<>’¬ÿ¡ä¡>Š~‹0õa ´†]æ?/E²(*-é~£ŒBÕ1ãÛ+`ÊBÔoN¤„GLb—Y B
+uÎ ef<Œ¸Ìtĺ¹H!¡‘x™]Ë -øÖ î]Pj—Yøg‰‘°¥µÅÏï<hC·ésRDI'ÃÚq
+D¢íN6™;•á Ẻ5ìdñwÏýÌJ­ì£è l6Z°vD”ô/­G·Iz.N
+ûM€„ÅàŠÃ•/‹ÿ”奈â\L¸>ƒ×a–2Ë嬇’“ò½EŠ °ªµ½9™C$\êô¹øŠãJ’±ŽÉ u¢´\íËÕº,äÖ4´„d‰ÑÕc¦Ý
+­Hd¡öR":‚3MÒ³Oº×ˆ!› XóþÌä,®²=y˜‹š¡¯ê0Yì‚ON8¼“™hãâH Áð¸áÖŸÒ0‘ë;È=ß–×sR2I»x3˜OJ+ߥbeSq
++sëû¤®Ð&mó\HIWFp¬-f–ÙÀ}³D€+˲R2­Ö8ïcÞà¬Â({ï@ƒô¦»EåÉ3ü“š­ïä ´bD¼ J×f®]8”ð˜&"“'õ“5@ªÈGöý$nWh¨n´3,ù±ÉÍåÍ%Ry Äƺg¨Yñ”–.œOH(¬î)X’¶éª9?2\K{R>§SæĪ²ýÜð5å².ðšLW
+õüúYÌ‚Q,ÛàIÁqPzY%˜aƒ$mÓ(eû[ȸl`"1»ŸÀnD!†epé m{¬ã*ñŠŒ&í|)1þ$
+UZYü(
+¦ùƒRs}ø1´³è›˜üó7GC(ãí
+“A)¦µ÷÷ð×üýØQñÙ¦Ò €´Œ¡:‹t’q †t®ˆMtÅŒÒuÌ­†¨Ä~Uømo1=_6#Ïù9 ª’Qª]–ùÞ–0¾„/¶¦X?è³µ*Q’J{¥œt/ñ£>Ç|üÎ'XŽ·¹cîô¨tŸÍy,
+n dÆÑ6ê)"q摶_%%4–«áßaS +¶¡í04Æ‘¾•tŒ¾”!Çt½êQTV•‡Ñ²èW–Š3§²ó–h)@æÝÀXØ1°’=¿1C3MAÛ£šðCò0Ã;qb Da5°%Ðåƒ'â1·Rà iÙ¨‡?ªC•p1¨Hçï E
+±þÝäââð“&/Ù^rØÞÔÆdÇàúœç­ÄÊ%NæQéí;T‹ùâ”Ë€Høîÿuâ
+‰]äMÂfJáLžÕê¦n«À^áá×wÔDx²º±¥ÅèXã¿ÁÚK‰iLÎë×I÷qdëæZ˜Ž~"‚Õ3§¸–{h~¾‘&AŠÕè%d¤q °×Å’¨>±Ãª³13w;H7ÿ ¨íØ\(ÚKÀ#k• œG'Ul¤Ín•m8ž½À^;Cß½ÏA PÙ±®Ab0În´”Ø"ß¼¡q+‘ù£ MžÝyÆ(û¨’À´"Ys¶¥ý2Õ°©ÙúΓc·\«ÜfZͽ ^ƒya9jÛ'=j>M¿î"väÖ<;4€(³Ù-o6AW±Gˆg&–¿Gö «÷IüÀ¹ƒ”¼C'tˆ¥Äù9øØyØJ±tL®”è›ùzº•8$ЭÈú ;ùí;x1¶~ ÅÙuS»+Ä9Æ/EgÖÍ@Ù@AM¿tiLŽ=¨LñQ izÄ,AÚWwyD&å6yôóXðm¿×‹³°|mgÒš¯a×ñЀáq¼`ôWK Ñ$Žs ”i
+r>%V@*BLãZoõ«?öu›ð0™Y¿ÀH½¤÷_Íê²ãŒ\ÛŸ‡®V®ýÏKQ’¥ÄäH°t\ý“|¦ÿñ2I®ëF¢è
+¸=` ItÃ
+ÖÓZÂ3jèý×¹@‚Ö_ñí°#D^xÙÜæô„0‰Ã÷nÈ5.
+“€­Mñ;°Îhî"ù{tЦ׃áwù à×TÓ¶ÈCÄóH”GçryöŽ’EÂ\Ÿ ƒÛ«5=«‹óð•R˜]\Ľrn^Îï
+d ÜŒí«dŠYPc/Žš¹¤^mcrð™<U‚f¢¥"†Ôœç½sk4Mià㸧¦gÆNÌXý%n¯€`3n#ÖÄ0mÚçéº+èë•Eõ}–Q|D9lër„[“緵Ϥç#óz
+wF%‰‰A ‹„œoœ÷ Äš’Ñ´º0\lrø6‚TrHkYÇ}Õ!oâÍò!°DÙ¸ö
+âÒǪõ"ò‚)»ÌöHUB‚ª½zݧQOΚzü[:³ ŸN«K !µtLß y—˜äËY1i;ª ÔòIO½?)f›|ÊÌ\ëùœÆ
+nwêx;YUÕ {ùõ$g¾,è$g;LC®ìp\™ZÖ»ÃîÎv
+.r€}Ï;f8PAVËúž ¢@D[¨¡',2?ȬSó«J¥fÔôߨR†,§U†Î'Iã}¼& ~Õ ›dˆµ;Ÿ£á¡$Nù†<„•Éuˆ‚Í·;D¿bpÈduòaaêØÞtF²`ºâ3Ø•C˜Œî5*{{0.3H‰™ 2E"OÙ÷d°Q¾…wRLHË}³< 5­mg§¢µ.8K[ý¼²ü‘ÿ̧Ëe•Ÿ<NÝ$.i‚Ò X´ ˆ=’íéyÓ8óC”B
+ÑÈj5Ý!£ç(Üb áýÔ½q€ÌVÌÌøÌ,ô䣄]žGÕ=“œaBp™D2÷°ÆoÐÑÙ;ñÔ¢Z‘ž¥+èŒæmìU§øñd¦>O/‹±H![”0¯á0µ•µˆ‘Š87l#ªÐTUDøŒÄSÈlF×Â"UãqLx,ü(¥ÂÍŒ*ÊH¬Cæ‰2®wÅdÏü» «‡®þùÊ þf#†g°›|üðELÐD‡…˜u[ãšp¥MÄ#´hBu±SåÛ‘"4Êwàò‚ô¶¦¤„â´`Ѩ©Æù0Aþ†õ25Öy üK{'Iå÷@ÿÈM‘°ã¼Àbâð
+«Š@ø³>·†í# ­ ´P¡Þ9¯Ðd²€vÓ’5B¼‡šø˜z
+M¾ÉYciDl·z S€Ý ™CT#<Yk^
+í{èñkM¯±x¾Šõ‚#ä…]8ë#fòxÚ­r=AMvÿþÌïGØ.ç¹í»\ÜY6~ÒÊ‚ð«`’žý`ãP*Ê»³»€øŽMømÌÛŠð@Ù }N¶ÎQ’"Ö=@CÂL"eYˆÀ¢û¢+F¦g'ÆX§À †¡ÃÆ׃5œ Ëø¥¯–(“‘Ø+!ã†8tݩҳΙø[B…d‹J¹ßí¦™§okߨAN'Ä™š. Ï' Qþzº¦W ÊE¸¬ÝÅCd 2EHËz2`ñrÛñ–(Ã1ØüÛ. ·ä@)'Þ2üŠb-06ÁÎñ¡I¸;C´r€øU«òÇÒZ|vÎ#_Ì×d*EnIä½ïCà>ºÇ <ò{[èKÖ(0qÿÊm@è¿ÉÊ&wrxãÞ&¿Å'ê:ä¸Ø÷±q),…a2 ¯' k3o“Þå×ÃÒ§è»[µ€!‹ÆWi I¸wþ·W
+FKÌ ìé6¤ËRÕ£s
+ðʨÇÕà©hTZ”ÄK!ˆj¿[ç¥ : CÈd¡}VWÍ”¹H6Æ–Í.˜àµqlÏ96º «¤2N`Ën*dñ²¼&éÜé_=Üéccâä‹/ÌÊÏMÁrèDðóp+0=“"ÉcàÏS P¤Ë¸²ò4§\é--óä
+YjŸ|šSþå(àŒ§NÌ
+0
+H‰Œ—K’9DO ;Ô&@‚\«—º…ÌfUºÿv‚`J•ÉèQ¬?éA‚€Ãáè£hiöñŸVý1µk“î£÷þñó[µYeªÆ/­h<j·RFë2l|\ê£JQiͤiZæÔy™­Xo2ÝÚóªÐ|ˆ[•øÚ°ßþû­~ütô‡zëݤN½Î+eº´)Czûøµ@µÏn>£@¤Ô/#Ø}Î(Âã†kíiY§ñWi3!R›Ûlµ‰Ù: !¥÷R¿H÷Ô®j^×9Î=ÚÝ«ŽÌR‘l²=%!Í;™˜¥é‚Œ.sb%£ß׫¦jÓ)…? 7 µ â”þñ™ ZÇ$Û¼8#ªÔ¾‘™}ågð 6Üym¾«á;ꦺ îd“gú~—”Ò'ßÀ]ùé>LdÚ €Ì3éóÙÇ´uN㎩<»jý{Õ¿C² BÉTÁm)D
+å‰WÝéJý
+:×VÍ‹E'"žï.
+o–¹iñÂ@2L"ªÂ‹¤$/øŠnDŸ}¿<„ Ê¢Ùçœ4BgzYƒ)ôKÙìSlØIã*øÿÔ4„˜> «™Ó‚Þ2f
+¬Ga€aëO»¢O 4³ä)øì=ÿË$9Šï¡à†@ÍÌp,xh )§žB™1Êø©ÏyóïÝyJbsS@Fö;¹(8&ô ýuâß‚:®ôxP—™É윌œLGÓç@Y|NKñŽAëÈZ@ÌWÈj˜ë}$(<(t";ºŽA–&„ñ[ƒÄô,½W ¦µB%­6s+¯ª=¶»šÂ ×¥£ã&]ŠcØ…pÈì5Ü–71§ccâÉÚ$þ Gó'„=â suõ/œ‹€JúKÞÍ;‰³ù:&Ȇt0B_`i`¶Î ‰4JߦÏÉg`c)Ì«Ø4¡
+#rÖã±ó ô$¥‚æ¥p4g™7?­÷¾éC‡aIYðÊ5"bú`„ÿö\_¢l&‹•,Ó'ƒFðn%¥–<b@£Ü£îB…ùFâø4|}ÆʳòçÔŽø(V9ª1ÌE[ í7ªÈ'¼š²W÷sh
+¬ö  kˆCæ¯<†×@Sê:3F1©qÝnGË(á~äš'ˆ…-f¹›˜ƒKÕ£1‰'(úôy¢äNÏápwÿN"cYaGØûEÕ)5€ö‰½÷òÅ‹ˆ„Ä¢ÒÓ_D’‘6a)C÷†S£áYÛz60„˜œnÅëÑX½×ó`Ð
+º4Rƒ¹cŸCèZ:yZK‚ÕJfê±|UÉÌ°<"GLì&ÏGUæMF“磜FàL<JKR„®RK&F¦}ÝbrWÛ•
+©0<·nq£`–åwçMa >¶*©ì±¯¬G‘ÑŠ‚L9F!9ˈQ²õ¸˜|yôÐy,FÓàpž¶÷cÒ2Í8½å1·Ø1µ%¤Wî ¶¸ðòe'Ì›¾‚bÖvÂôš q˜Õ¨ÍEG†œñ¬Ô¦s4 Lº) WI 0^¶¯*˜*ÔçWÑp¥Ä<Ë’‡‘Ãk²]èÑâD©¨¸ ß”;«à[tõù&'½AúZ!Â*ÍXFÉb»6ݘŠ¨€Š2ÕÒ+E¤f ao¿ç_ñT1 riSÈ ÉÂð…ƒd¤g‰§BûÁº$¼ BZCÕ¿¯«®ƒäõ§éúô¹A5køþm•æˆ%Eb¡ÉÖ#WC£W<ápà‡o=ÁòQQâÉBTAõgƒÖn³cS
+&›š½G¶hXÝ<e+ˆ@4ßô $¯Â¨ 8ö?ÊËeG–Û¢_ÐÿÐk-|&É¥1;i2 xoxcÍ]†ß'ø¨ë®fI-–Ç£˜b2Af¸üœ”B#ËzŠÇz›ôÒ`Ò 8Obh’³~Lyn"võÝ$nâÅh6Ö+)=VðïÖùÚPKzHªáhrì
+LS÷¶™Ù (_Ñl@‚îÓ‘Ùõ܉ׯ„…†ýáiWéÒ’”jÆýóƒªùÙÁŒžÍ?þÄÁ H•÷÷B­2»¥ÕÅBèÆ
+%JÖÁç H#ÃjÃPÒ¶Ï
+š‹` £¾}ÍâJµ+ÜîCQ»ÝæKa~&¨ãø8¹žo³ô©¥+KžzjÅÂÓuvöéÁÿaoh$§ìâÎð…ÆŠŽé‚ðd¹«vqj0PÛÛ¹áþ)Æ#ÅŠ+y Ësˆ¥æYpMõj¹9Ę}[è(¥j[Çy)-¦©”râßñX”wƒò™¢°ltƒ¨2å™e7ô‡8)(p ´YƒÈÞr´‘[&Ëø-‹1Âfí -BéYùS뢋¢;žÔ•ƒóˆ±#Ûл«£<vÂð8¾]l(–a
+j‡Z\m&½IAáWßÁÍ+Ç·ÕH­…«eÈszHKxãšãڷЋKÝËD$\"±Ns–ƒGcD¶zs"Žá•÷,ó$eBjU·…he°¥´.Ïø³Ñ ´JòÓÚ¨Øq'”©]óǖԺϹN.„<B i¯$Í&§tŒ¤ Òo›ž›Ø+­2=ò$* ÈÓ°63 v¨ÈÆ·6œ/™sXû9n {i:>/@¯©eŠ2ò*Pfs@”@``^VølÌahÕŽNºû•ÁG*›nÔîsBî~ƒÈ[¬LwJ¬¹/®c»J-p"ãIóþ;gÉèÕD4æW?!¤BT€ß'ÎÑfŒ~*ß'æÿl“1„¢¯ú¡øf-]áü@_[•ÁQË?渰Q äßo@_ ók¾0KuSë¬ûp’µ:ƒPb¥ú×µ‘iC “Q¢ôHÂ>"o®ö!hK=Ù€ˆürc\?í.‚F*Àðñc¥aILø½nœ
+|}™'EV^äðè¯ß15°Œ¥\UCH²æ›rëõ¥ä×ø;üѹ9@2ñ »œFҤŴÀË•[;& Zƒë¨3ˆ¤ÇøÀy$ô¾«zÖ¤¸ÁÚöV6Xh ¶Ž:uÇr'NæÙ‡û®Å rÒ­«“ûß=Õ ²Hñüä»ï<ó楖öí®ôÂâ×ÖlfûŽhã†øß ÈÓL}£Ç&Š†ÏÙºøoó=­"$&ù»0$/ ½h<ŸvÂ|½S‘4ㇿÝÜý×›{БÖ{ªŠ¨ÊÄɸ~th?ütó÷ïþþ/~…XÀj‰šŸÿÞÓýç›Ï.>t(]‹z
+ŠÃ¤Fš^™5Õ r)ú…k…JµÓÖq–1Ñ$•âþJe¿PÙ* °yòøÑôB½ÖQóo@¼;ŠòTáʸÿýWSðµ<&4VܱŽ«ˆäéJµmâ”BàÇNlN€'œK³¼®?ÃÅrªÏm–Ë"ð ¡ÃU×É°?¬vvN ×%¹ ˆÜìó¯7
+Ò£ŒyãÞ?ãÑÒSè$n¢ÌWpO×gö³sœ†ÝÆsá©þìýµƒ(ü{bÈ­i
+þl®Kú¼ý›òÿòÏÛÿ™ x—›¿Ý¾??ô^P-©juµˆÓC;ûÍÙÛø6ĉe ÝÛ’IÀzÁ5’I%­Ø©}ˆ[›, q¯e[™Öß#4(9§{ÑŽH¸ø=ø=㘰Dé·ˆwÆEÒ Ù¨O¾@9áôàø6Æ÷«C8L+^åkÁ^H¸á›³QsÒ“läè ·²ˆÅtl)?/žø É=lµãÙ¸ˆ¹ž>Š^>ª£ÇEb— K~|ÅC"ì £4õ"ÈÌE© Þÿø1»ë¥È[Æá#’VL:ÿÏŠ}Û‚*s…÷¡:d}vÅÂY"Q ExÔºð²Èµ¦:÷ˆW­¦eK×ÐëÅìÌì~Ô7tšÉÌÛÕ×IUü‹Ã0¤£ÙáD£' ž Â pÿGuë„Œã8'ˆÃrõX¦ù%me’Ç€` N–Û„zY鵬¹yBÌ“(„ ¯v˜Ñe-˜”ÕuƒÇ é õ¾y‡sµ»Çá[¡QÒWó«Å4E± V—2rˆ”UR7ïTîôyV,wX¸ænÖ2¥…æ}Ý æ½¿ª÷Ÿa–ÊGÈ-ÕVż%R˜õ©ðZ©µmd¥%1J«Œ`¦)è=±…xØÆgLµ…Ösëô9°äÄÐÛ´åº×´7Î`é\Ä h7/ǽ:iÂv´Î Ï¡/ýΠº9Q¾‘{3Ö%ΕòŠ!×¢³lNØwÂâWÍ„°7ae›þ¢ 74îÅúăʸ4^VÏ÷ÍdÔ¼¢ tY‰øäâÊ@ðoQÂèˆNTG¬õa™'%®×ˆZ0ß(hQ±®j‰…&Ü]ú;aÔ£"«öª3¸D°4'1Úâ+„,R“^Äöý¤3¨°ô­ gï‹ávô³à6ZÜ^JI‹&ažÅz´ï©7Êt,yh•r²û®Á@‚y0±…`Û‡:AæIÏï½û̉4»bž¨·¿Ñ _;sž”-;i¯O{ÀÓ(}#âXsu#Úßkø;úSýó¹Ál•â|ØôõNEC)
+1²ç"EžÝ·¾ Væ°Yò¬JªLoü5@"÷¤ɲz††sieÁ¾cí,â²Ó”Áÿ1^&Ù‘Ý:]÷P+Èþû½ OUûŸþ$˜¶^‚å¸9ÄGhÖPzwIÅÙa¢3nÎ)ÑX)èxN™^%Úk~´R¤QA4òŠc—$ÞDì3ŸP‘ˆŽ¹Kö¥1ÀT‰õÜøó˜Ö Llmô/ƒn„
+™ìaÀÏGMR*ak*Í\ÏáCˆ: èÜ+sõYǩЀžtK‹È)Œ’k.ñû(òpHQÖKñÀýw‹ø\#|9èaÙ@ôŠ
+”‹e“OnûÚËÎÃQ¹˜'¼•¼VèÉ^–Ĺs˜‰1ö+óÛ‰ßN§‡äÎ#~Ë: Í×”d³(r˜²FÍûš¨ú“Äæ9Ý‘Ññ$ܯä~=§*²‰>Z<·)#óõu«$`MyEÝ^ÕÉ¥ÜO“ß Œ9‘íɽ°s2LÙQ—¸%€ÃYQže²’Âm &¡X R_xìÜÐx¹Sgýðßòà›â«HЈŠp™l:¶›Q9tE{>6¸BüØ›¼ù
+P«(Š?î»dˆtØôšíº¼(³¡C–íÏ?œ·9MmÆ‘4™“ß-òXþ?éÛX>-!¤‘­GÏ¥þ´"~!PC7–'ßÒE–›î>Íç¼ÂâI†OdùU{,Ê範˜a·„e(¹øç”WÌ4zã…ž —Á¡«G­ßÐQ^Eábãv Qo*êÕxyT})¼@Z`bÞUô„õDÜ×s†¢ÚûÆš§„¥ÁFîy£ùg‘ ²ŠÀÁ2 õªÏ"—æ¢'Í×—ÜX†{φ=Y¾¾”EÙQÙÛËSCƒ¦³…O’gÜŸ¦2OOÛ×@é\‹ 4X þ’À7=jY%§Â—íÌ'Ç—WÅ9)"†Tn+žŸûX®ûäøòZ‡h!úO ;gñÆñÏ"wä™öÔX3a°\åÿYär<E8pÝ”•w9>¿”®’"L¾t9¿²‚IDœ«$ç͵)eùç¤
+Iß'”u\ăäaAòM†NAÞ…äŸ5nwÒºsœôçbÀ"—äÿ‹½ÉÿøŸJƒÞ3p!lù /Œ ·paǯHMÜòDG×Q2B,lY[ÜKÉðe óK°l=ÃІ€ÿgù#
+ðk¼‚œ”g£1z8Ý]2ñ" ”˜÷™¨ \!‹ïaÀ>¢Þ˜uŒœ$ó`³
+@2,¶!ŒB=yI %`g·$3 ük>Ó<p§HÞ£pI8ò¨(¦ÄÂAûº·t 2-æép!ŽwÚ§düYÑt¬Umd¬qÁ)N’Ñ
+9E_V´Æ…Ô§j×KaS v3jJ{iÙý—Ãø ˜K‚xƒFî]KÊnsîy9Ï‘Ó¦A£6 0ö!E{#[óñîóï­ƒÑ/ë^Ñ*i£à³Ñ€x žáÄMÌ]‚qÁŽ³£Ç6³öq²Á)×ó%ÅH$Æi_b_xcT‚‹ûÆÆð:2›;zü¥„´ƒaÅ_‘÷8ŸEOŠûºa«Ð¥p»?–ä¶|ÛI'H(¬Ï9›½ÃÄf5.qéL3wxä<Ö€•é_1ŸÂäJaû±ð­Rjw5äcšž­Í:†Ž]ÏR„/» ´Ð¡ÓÑ‹¡5æ±™¬fו—&AM£NIüIŸ14ÓiI8á»\úg_É•
+Z Ï#s¡y“ÿ¹‹À]ZÆxò…¶á¡P•–Û™|ÔtøjI»D‰@Q‚Ö»Ø
+ ,ÃôY®`RÀጚۨ~=ò?ÿ Q”EjZ¦'ë†IYÒvÌ‹fk d)Ü8‚%Ã×.ÖVI¦ýX­)4Ɇéadܦٙ›/ÆÆÖŸåÀ[¶¬ æ>†¦Â›Š?Ç£ŽD,h±ÏÍ@NÉ’ © ÀFdzHš c š¬½i¶Sô„bSL\ñó#§:T$·É~F-50L|g5ÙlÚ@Ú‚\äž|­uÿ©Ù` ‚d(pRñÏ©hmîðx9þwŠš´³í¢­bßÏm°ŽŒWôcÁê«hP=„ Ð‚ˆ&û>Ga‘]IÖ?¶‘þðÐ@Lv:»õ‘Ÿ5øø×güfÈjT¼SÁO]Š…C²ÝY1[‡>K,ÊôÅ¢,æ¹B¹‰›%8ÐlŸ®XÀܸý.ü‡î‹E!ÄñW,[¯É)±/ñHp÷¤v;5Ü9+ÑA³ñê„*›fn$‹0G> Ht)³®9›w3‘ÁËÝ@Ä‹…¹òIk
+L96
+º‰£¨;º¤W…Ž¹2•çáá>°ŽÈÍü³H.ƒ `òf{îÏo9䤫/¬F0R†&+{w§h/—cHt÷J¬É²‘ðH©9úç0‡®ô‚ÁÇXw¼&c@ø6Ï®nŽI ª’0oçKôUA²²E3d¹Œ”ìL‹Œ·fä–×%QÐkCÎwü‰r©§{Ú‰öþÔ¯€ü×?&ÜeÅÿ/“,IN ˆž@W©8㺷} mS÷ßê8¡Ê ¢UšÕmE€6° Å/…ÿÎòúÔµ­™?€ŠÒ~5ðkñ0Y1–Ó  ª²Ø’„®-Š•md^‰N×ò¾9뎎å7ˆLaJ|½*}MÉU¤»HFN†¥mñIl“ZDŽ‰ÁƒØ2‡4PÎtKmGFøÍÈÈ/
+ù}Q~\Zµ±‘|“8€x†óM ‚™ìªkÜ=ƒþ`
+1ŒÞ„ò±»ø¦âª¿Bl˜¢ÔÊBžJØÚ–TZñpðmk©,9T êG'üν ¢A>#ðT†žeiÇŽŒè¾‹’±TæF‹Ï!ZT§Fíÿ W^Í W¼d©N?0k2<MÍûÕĹ"£hiûf¦ bªñV ZŒ¨;/mGj9õüFQ/æß I,çÓ9xpߦÁðýÈQ]RÕ¶éø€tž“D͵í — ±»|™´ˆB
+‹Ô,mýzSžáåXÔÍx£àmõ D·…7Ð-¾(㇠μKfYSq
+Ç°ÜOÀãOøEÊäÛPØ'&ôA“~9ÊÚE–œˆÿ…Ò»ÛmDZaÓÅÀLZø¤SN/æs‹èÜu߈7‹bà
+q öxŽ1ü>:à,ä˜ð}ÚÄj° NÓ¯ ûq¢º|}‰â¡YvSÃlcûGs‚›!½ž¿&áŽí4ªðHz(e­í öŒÒµ±Éed´LM›Û»¦/ьഄ±¥µªYh'n?ðߟYô×4ÅL¨žÉ¦æA˜3ÕtØ­×aˆAlèvŸ;jì‰iµ¼‡MÏØG)_ GŒ‘ePèÊO  éêßkÁ?…á ’Fö´/ˆbE,(HÞÊce ÂäŸ*_ŒDNkËÃ9…\ÁY¥4êù6…â
+ÿšJ&¹,‡iH þ„¥T3f‘òðn$5¹¡C€X‚‚-];ˆjM¿üK9Þ ­Æ†¬s¬V0 W¤@ØÛÖú
+HQpÛ\K©÷¤ht‚PNäFSãþÔ ”»¬v`›’!㦡܇Ì5¥Eª ‡uß+Z?`Q”<åk#DÒ!WJÄ¡âK{Ë!²ÎÎÀ ¢ O(‰Y<I•XkÚ#5}‚~?€Þéë]@FÚÙ«Õä¶ÅËlT\!ö™öùãà&[Qª_: xÎRÞcLo!¹xy€ ÝØ¡]½œ…!n½¥s„0(o8Ä´omŠõ
+KB+Gz[ÃÇ]%æ Ôùæ±(LI‰óÒ6F¸ H
+¤®Å]¯‚nu)ÊŒ`€˜¦¾©`K^áyÒShƒ‘.if#ÔÆ£,/îä—-/”e™\z°0'C”˜fÌ7[ß.úEl†õ×uf¢ÀÙv+²„¬uÔg‰=㋼1¢ñÚºÎ46ýÒEM¾’šk¶½l6õKß²¸YS;oF,@…±/<*<“Pvl-2|ôSKœL~îQLòÙÜ Â{
+b낾aéÕ‰5Ä7Ö)Ë85üúÔ¢þ¡b—vLÔ‚1oÉn «"R¥AôÑÌ4¥E¸i„½Òïήv¬¸=Š¸â$gIº8‹×á fØ…º(‰Õ†¬;Û`­du»ÜHµ‘@ùaKdù_»à4*¥r‹D¶¡36éH Ηñ/& ø1D1©WaBxq
+®c$Q.» ¿‘n'¶ú Âe1mü‰\ŸÚ@Ê^|˜ÝÅ]Ø«°mUÝõKÈå&Qá%šDE.Ë4F³ XAìÒûú”¦‚ÓQÜe(­Aì]±ÕÄò36p™?ÇRvŠHgó×Çt«±è…ñI5ŧs¼†ÞK‡ÌóXÓ†&4E?,²ù ´CÍ~¶) vƒ­+ÝÂxlb‹‰&Ì–ÒÌN°ëÒDŠêòAð3Y$඾tîЧ˜VG
+À—Xà ¥Õür¾ŠF(à´ˆ´.aTtƒ”ŠB",oŒ³ckj},ðf#ÇÞõáâ¼·sŸ Zø¶zù±O±¹Œ#¶Öŧs˜z58KæmØL„@=7EtpQn<µY£|¨ƒ÷1KeMè¨r %­ûÜ—áf2ɹÕé?)…È‹Yý5=m~Ç«$ì:$Y§
+V
+â”1ÙÔ8µOºBA1xr3p%"mص´>åyI KgÆmÉMªíåeŽè ÁÄqäèĸ šÀ#qôŒn^–“_eíÁšx@á%º,ëÊH1 k[ç *²ðan:.9H‡ŠãL ° z^5áúÔ⯭+ÕÁ#ö*'Òk2ê–BD_M.ÝOÄÚ"¿¨Ñ²`sl¢ßÝ]勹a ü²†=BAÔ>ÍlA±~ôçøê©(¥ÄSúRköPðaÈÂùƼÑJ$Ù]û‰÷éø£JS'„!©\î¬W‰3rAGJ^ŸªøVÞª¬ˆÖ4‰´Q‡Ü|ô2û+:1â-‘ÓJ|@¼$Ü_¶» A¡€@Ÿ F?i$]œÞŸí%©8Md³!¥R¤ÃŽîV¯D'Äd§øá‡p..Æ«ÈÄ]´„—¯dIX xžf“Ó‰cLãü_ý|Øè°˜ìy¬Ò݇sDŠþ)vc¼kW¶jLöÛ)a¥ÿõ%D†ËP^ëÀF‡ ®aQQrtxÕŽ@I²BéUÄ—q(å¸>µƒ´` â¨ñÞØ[ØØv,é»Ax‚²d;¤hOO³ÊÅ‘¢6v˜I5P«NŽ ƒ¥Çk¿Ž‡¡ìÞEÖKÒB$ÃæáýÅm%ˆá¡›tmC ЉàýâQ&„}è\ÀfîƈɌŒ9•AS¯ÂD HAö<›x„ÖÕ#¨¿„kíPr)›hÇ$¼QV"ƒMl©¸©^”ÝR©N±© ×{‚pUãÐק6ÐÝùsD›Q,Wäã®°b_š©@‹{S
+ô«ô½qÐ%M ϵCÜüZ3ãuÉèQl™ô
+ËÓÓ}fdd’ ¡BGr+«K‚u”Šl œ q§Œ1 €q(úC ÔdÔøToçÈ^zÏ´Ò˜e¡®ªDQz5HÅ`ÀË
+ª$Ì¿Û”¾èØ6lŸ'š9_~
+Ò猘lÜòÑè%ZNÁ„ÙG@Ì/òF$ÑOCghôX6Õ›ÙÆñ
+Ã.-¦bº‚a™§ 8õò}|šÿ’—Έ‰´®­pzÃP'b'ÏSl´S¶›
+ïŠÈЙÔÎÅBê…k«é\âäÔ©hoøí6·¡¹=ê0z{iN¼Õ÷´ÿ½NÓXVs=Ž=ÕâÜ:.„Ö dHÜ ô±: “¥\³“pJ‰˜ÿÚ&H³ MöxÍôù“;M"nDPÎ åÊË%Ë͇Á+è=ÜøèE‰§‡ÙEO“ýOûƒD¹S¶œS=º·þÀzÀ¢jnXÃüI±÷}ô ˆ­FÂògóõ˜@˜ÊVë(¿Ÿy"‚¶ƒxO~÷tY…c˜òNÃ`pr(g*Z2müß&G~¸qh„²¨Ë·©|¥°æRó ¿cà ÁÙiÛQ»Ç¨ ÊaÈšJÛ‰cô‘h˜±•B¨“ÛŒ­ºœB
+n—’õ6Ø„ðe{TÊ2 ê¢@lýhÄ&‘òù <卵ƒÆäç3 ÚÅ7·Y6/í‹+¹_ OÒ#šÚn Íô!XÚÏiÆì=sˆ.Ã%‘˜üŸâV,›0o¦Ÿ#Pô! ÛÆÎe<³%›ïeàêJHÞÆ£Œ$—Ñæ(WHß]Žt"+&êÀU[ÃvS}Åüºb(9©¾µÍ?Ú×™K1»Æy]N¢ï¯+¨Žs^ÔÁ/pÒÎ Û„7Lh3ÇNÖ—Z Œög~#cëžÃBчb~ÄVˆÿäª\Ê>­“¼se&7[Ñ-Éòǹø‹R
+Þ’‡âP¼šÉŽÿ<E²Î\
+-;c+F¾,§Ðûq0rdÁ“Ubc‡‘r¼:7!–Ѷ¹¦Ÿ4°ð³¯]ÉMSWØ)3ÐZ4U¦&´š¯MŠ]µ­´)Õ É%xz\Š”¡0ÄeÓ3ì”ÁôE™#ûbcXGpò½?´þFžXÆdŸ Uƒ"ã-ÜŸg£7D‚ÍÈadÐÁAù¹x $Ä%¤ÞBp“•9qÎ^zOKŠ
+ JàJôÔè)5Ë@Uû¼€~(£â\³Q‰A—dÑ–&n­J‘®ã8Ä(¤¥ÑwL†<Ç9³ÒË•¸vöo¬œVp2’D4Àaу9êRžx(·ÝÊù9rL+ÀLg|Z§ï+èÙã4^PI¼ý sà¸T?¥B×0H§Ç“¤ÄJÄ—N™÷~¸M^sãÖ÷ò%°îH>&‚Ö#3´‡¢ÇTgÑo+×¾ƒpûé° ÷‰§¯´ Hn%áþ®LË+ëÐÛvß
+BÞ+Ìt{ËJE8ÊŒ[ñX®˜PG¿R|Cò“¤(ä0n>œf%`4Kã(<™¥`#l‰T9“8A ²«Àß4ðïZúc‡ìʽ*.ɱZ´V'¾e<O²%·ÒÄ¡¤ü{Œ
+–pòü¤ÔG¤+ÊÑ{š™Èã¸\'çfä}Æiˆ{¼àÈö¬çŸn[­‡äÔÜy­fH}¯Å} ¿­~¤àß©üG6¦ôNyPÝlù¢D¿D9•|¹Â? öh¥y‹Q9¨íd‡¹Ðß݈ ¨j@äøªQdZu;ê ‡G{’ž_@!6Ê÷’â éCØ}ÿnRI)1ãù}^ ‡@Ø.Iþ¿”—I’9EOÐwÐ ÂH‚ãZÛº…¶Y÷ßöû$èR„ÓeY*“¬2Á ãM~Z'(*H…ÊÖr6E[-("#C8å¶-•%É­j¸ÑF”0RÎê˜_œ‰
+•Í)ù"U#’„õ
+
+<ÏÁÆ­?”ðhÊúþ´wºqHå­j]ëp;°À3÷rH‡ëÖ¡…NPïÍ9,Í$Ê*Ƶëõ°=\¹÷¼§S¬ŠlŒ†TçD&Å'áÖ|+Û7Ñ€™&ª5ç}”<©Ó[Ñ?EZó×±æ>¿¢¨m&C®¶³<¹”,FÈ0GºìÝéD±²¸‰Ðuá\3ÿਾNÕ£š\ :A^àíÕžóŒ*¹jÖ«J¼X ÙGÌýiÉP¨ ªçgG:O
+
+ å:νèO{ýúŽÿ©µ3¬
+ïiö ¤¨[è&•iק¢Ù3†Zžò¢+b()î¶r¿ÑÈFðbU úIa$îÞ# @ᛲݯµËÈ¢Ã\]‰D0`ÙV̦D:.Šø¢4âúQ\–ædÕ%s#ž_¿ÈìT4K¤µ)ËióAÂf a‘»STÉ3…šµ´¤çVDÚc]‚
+InÒ¤µçuè4žwðª}Òª
+Í2FÖÇ*a@"º ºÍ'&°Z$ß×ÑíÅ>õ¶~¹¸qšÁPç#e°˜X˜[=+g~qsƒÝ’JæNE¥•’{?¯S˜™dh­öd t1u/á:)HõÜKð„­ô„ë."ŠÞ„ñë¡(eåÁÚò×½Fe.ÅÎ=RTíêÌsb¶
+ÓPoÏE´`2èìëéÔÑ4FÔU4" 5À¬§…‹×
+è—Æ\ Y%¾QêÈO1”7=­#Ù „:f.? ü…b†‚{>Žûóج~|ùy¡&à–1 ¡üƒXÔýâŒ9Š¡9Ä£ÊêùˆxQ93J~­nÎá3ý´r^§¿lM¨_Í‘•qàh½®gn9À}?p0ŒŠ¹Š–Ö½RÁò\x½2äU!Õ¥µf€‘mwJKÞðPò†ÑŸÿ;Ñ—½Éàÿ›[чí¾Qô¡
+gr}¹ÂJHfÒÑÂ~ð
+•x.­­²|“å¿âë`\ J´fIÏ`HÍKrF""Ù»X%<ä/ïç[YÆ›°Ç"æúV-£4i8N*™1^ïá¹”Vcü…u󩂦qýŠtصÑG à Ó[!BX÷+At0À—·Oyr"®Z§{)_È1HÝN¿!Á?! Wø±gv„eô`ÀÕ› ÎÊ“ÇäO y’“á+)}NB_éDNXjí¼¯3]"rÛ§™)Ÿ´
+5Ä6[%,¦“ä·yÆŽí·BÐÈîk
+1D™¸·jœ¿ð@@?KÞÃÖO'oH>]ˆý^óu¬á%˜HÖ,^¼ƒ+Э¸ç¸®³¸Þü²Pã0^‚HñäÊC­\OŒ‰Ö¦ÂwªQqçäôWvÍ•qgBC@ëC7ßJ|+`ÄŸ®Xû´j8„\Øç§ :æÓª—|è%Êêx&œ¸n$FH@7ïyã†8Ü(áQirø‘{ád@9.%ôT`«ã7F?Šxv
+äîA‘–…cØÌÞ‹jò”Q´¶Y=B-pDÑ%Z¨ ^¶˜±Ööx¬ àŽWixøã9v«g€_-Â:OÛIÀO­ê´?'Á…£ã_qW¯] 5iô’è„úb&Ø;møÎM>ÕÒŽò«Ðo0ºõ½B#SN0Ù1—%ú¾Pí
+õôûts/·6žm A·B.¶…ê˯¾:Ú tUžo¸ù»ƒ>Œb(àçÓ0ðí¬#Ð
+Þ»•ü( šNî…n×2•ìǃ º‰†¼b‰ŽÉ"º‘1“[íî¶x·Ló!@ågdÞ4ìî3éŠ!6›¹¯î¢Â“vc•inCšFf‚&‘Vµ¥”®UK§²ê&è¹ º?ç­ÛI™mCç¤T=>3¡×ì*·ˆSm5WÕ?½€õƒÎf0VPV2ìà!S f¤_olç@KÀ8—ªÃPq3×q»_E3Qa *Û£_­Õô©e¸ÀQ
+(cF³š±„·Wiê׎U>Bœ2¼Î©Õ?ý~¦7â„Ä×–rB{{ä?XȤÿ$’ÙJC·K£‡;Äò€U$l6/²`‰ë¶¯ wóËh]ð _€F»‘$Þ¶þ`
+H‰”—ÁŽ\¹ E¿ ÿá­H%RZžÕŒƒ
+çÔK/a>š¬xì¦V\Ýml@Ÿ_þ•0É°E¼¸—–°vk¦ ë6Úñu‚,fV˯^‡ZŒ~œˆæáµ(ï[­Rƒ½2!½Õæôn ¿æMzãÚ"c”;Р᯵c\çÔa¥•ZŠÔ…È÷TQϧûMGïâ£öau&ñôŸ¤:ŒKÄ> ò[!:ï„CX³ vã‘ÑÍ\³°bH‹Ì²¶7ÁŒ½›Nˆ´á¢Buú„DéÕ‚r˜ÅÌ¡Àªî<¸»Æ9åãä*ÖǪ…«
+5l²ÊÕºg8”ªÂ(‡Ôº¬«hŠB=e”ñìœC)»Ó>+š¢:jõ¡e1ÃzÕA@0dA™i<£êÛU<´6H8|%0‚»¡AÕ²HH÷•ÞÞ/.“ƒJ@YöuÕÝý&å F£„Nj<€6U¯þXF]îAvƒmM¤ÐÑuÒçá¶÷˜×télæzê’k—¬JÂ*ÉG:
+…‡#g3?‚ZvGŒpðvŽ2 í^:Ìú¢H?)Ä/í=\÷PÜjí @QŸ3 ;Póæ4š©FöGBÐÚ¯D%DuN’§ AÈ"K§5ÅÍ;)ž-ÈM›5ÛŠ9ÕF„¤¬wõ°ê± c ØhÖuYW¥°ï®}vó¡ xäW0ƒî¤uì*qï§m¹6c#ÉZBHb ¢?¥æÞ׳\ öõ%Š¥*EbÕÆ„v”‹Þ“Ø@ÖËk«‘®EŸƒúä0cú]M{Á1'„ÑØÑ@Ú~]%æâˆ%5õë*†n¼÷Ù?<“ŽôBùŠ•yŽ4¤×çzeYê8³…€=¼céÊòhÇwŸ$ìhb|h׃×}
+õÿˆE‰‡zß²!Í}(òÝ?hCáû´lÁ
+wbü0&öò®¡>½õ)Tbäììê׋5Zš¦j=5. bÜßv‡yý@D©?üýEŽ_^ð’øCÏû$§²Rò#¾ †…qˇŸ_ôøéÐãßGn\†d—„ýøßQ¿powú¥¢Üð$¯å»u¯ Tú3
+¡äÚ€Ü'I„}…QT1½”+Cûqý•¸®ëƒ!ÔæGÏn8#úÓ!„¤Ä ’Aÿø%¯!ƨ©ØQJrD<w“ž–€šEi€1¤x…^’%Bž›[Nµ•ont`/Ù=™L©9 bp^› >nâÁÑ(Åi¸âUxÌãu¯‰)Ë2kò·ÿü’¶;›Ýd«òû)0ï Ö«3Ü“+â[
+Ò<ÑïMµí;SðÓç—ÿ¬ò”–_^¾Õ>
+ûŠáë{J
+‘b°
+Œj\
+~¾ù•‘³ÔN#…ÐÜL“ÌÒÏç °DÀšTðßõ| Ð|wÝ 2Ú…¨øç%ˆîdU¢qH¨ŸúŸÜøó?_~ø/ÿÎ?_ò‹âI5* >¿XŒ…­frúׂbHnö<]o¹„ïçhy}bdÑ¡¬<xàã„œŽ[i™¾Ó@ä*Çl¾Y@c5×Ø i)åR"mF:1jOõ˜•¼UÆØ€>oAÂÓ79½ÿç4fQ²…ê!\Å¡£·œD‚êÔ†­O¯01¸ø6ÒH{\éÁOÔ¨ˆèuÔeðjZÞÈ·7Ì\Ëf²~“Ëâ‡õ-„Wš!“¼½Ÿc‹Á†çE¼åiBÒûU"Ä—L«)¥c«`„O£³]ÓŽObàüSm£æUÄžÓY?NãµÅ¸µK–£÷T"ø0ð5l?_· q#cÌP(‘\ Ñ=9±çêð
+ËD².j)?ž»iî®[ˆåžÓ¨HÇ­«@(
+ÏïgdAfÚ5MßÄdkÐÕ<Hç)¸Etb8Z5Šù6~Ý3ºóù´XJæ9­ Ÿ–¼÷THìNÑ èb3—S·QŸÜ•þŸäóÅ°"À!¼`þ½LA
+Þ2{&$Òˆ¡G2yƒˆÐ‹¸Ö,æ¢:ûŠ`¾ª´K2 G³I›çäBGZåäì,8fO ùtI¿µÖ·-ˆ!:ðfAW[å‚pÚ1R[ ›@[7±®TžÊ„^IFÀQ´, ,YÁÐ,ŠÁÞUs2Az´¦÷x J@]Ÿ¹Nr”–ê¨KN0÷tÄâóa䔣CvŠ“MŒCà>_ŽrŠÙÍÖÌbˆ±ñÀ@Ž?öâæ¸"–EžVŸ Þiä¹Of_E®§%>s·ôãp›ªâÒ¿>ºš{ÈÆø
+ŠF±‚£»;ñ%ÈýS· ½€~|eß׶ßv¢¾˜lò }{ÛÅ™ê般WÐZ@­ V„ƒ ¢dZk‘W2È„B™ ²!( ä‰o›ãQ.ÖŸWô±¶«BÅ(Y‰Šxii)ç¢ex«õ²J´häR°#Ñ43ÊY Bêâ 2
+Èý© ýisðw–ŸúŒÄIÅâ$,Ir: {¯JŽó”H&‚²•P~=?EÚh]¿/Ô–”†vµ´D’äŠ?Îú»m§äI€â¹–8øª…Vâ»|ï"˜Ä >Áqd X¸/0Ç|(M{8”WÄ+±ü4{œ Ïjç0†Sâ›Bq3))%#wúÚ‰ÿÂ0Ò»XÌÞ}o·©¯åÑcB
+bpð_lMÛ±íƒÖb1æ4)˜i'cÕ{bk®"ó¢ÿŒ½ü›Ã‹†1*ZãaQé‘Ñã×h….*ꎢ"¥(ë=’ÙQ””#2 À=Ãu#³ÂŽìO‘{0¸åBäæ:T« ‰Ìüu.9ã íÑô»&NfÆÆZrJ;õǨywAŠŠ÷ÝÐK/‘ꙡ Âþ¤db³Ápe&©V;Þí»ŠB.›9¬ûS°fK¿.ܨUëG04ûSZQ?‡Ù¬£–Xsœ·YO8›Lxc@³Íºæ<3èìél®Q\:Cq æe˜4¬2ñâ°æî9gSó”ìÊD1)Þe˜¡f*º4!§%O
+‚4‡ˆÓ'‹›Á¸SŽ¹S—R\ÂeB(yûlÆpà·Ö
+•¤óB”°9› ¿’“rښƚÁv§XÐÓœ²'Ä(Å6ãy¦CÛ^ç¢ÊQ\(A~Šƒ­¡t¶ž˜ nˆ6_Aƒ*JØä“$˜ìö\»Ç¡Q3À¡(Æ~Qn㘦¼Œg|Á²ü¸Dw‡ã«I”H1x)›MN@~æ°‡
+ÍÄÅN·3XÜ•-‚
+ì+,ÍÁ{c:ÍÈàƉ|e,ëŃ`yzÍt“wÀ*= ‚aŒåIFØ›å@˜Ú˜­rV (Ç׳‹½ÄëÂm›+. +ŠQ!N‰|{(ÂX|-u˜²¢kó€`£ˆ–²æ¶qÌxÈÓ>$ —Š9<e¤AcÎi^ø°“\˜©Åa7òø÷§® Ö4Ii¡<óÒY>&Û¬D'ÛÄØÛ³MTÙJÍXxº€6W‡ýa™wxbš œRFr@§ÀúP­e¾âêºú7¢½_A.éšUÛ:¨ýŽ…Ú/ŸÚ—ª4d ÄÏUöîGÝûÓȇ<>uݹOªÁ ÛdôˆŽb£š¬åÄPfÄW÷U.zØ!Å
+{î­IvØÈÂÕ©Œá´êäå×R6옋Hº+bÌ7>@¾oÁŸÈÔ?†2£'ˆlA»1 ©ÜF®Mà ô(U¹Úd§Pbf´Ë<Ï}Ÿ›
+}
+­0n=£±µ†wè‡wÔD­9 ôjO³ ¤ŽêG|Ã0™jQhÞüôÉs‚>¤: 9`̘0ùÄ
+ ¿‹³ Ò+ûYø5ÆPà(mÏËÃUE½jÍâžT¸æÖ IS2[µ –]Ï,×ÅdcÏNê¹’ Ÿc¦ìÊ
+c¤EI‹º]zèg‡¾˜ƒ0¤Ô“ÅI­žZB^9G{:Ä8åÞ¨i}l×ç &Ú ÜÈíìi@\)÷LÅ=eö UtÚ9M„^á“àÃœ½¦rZ©YW¨~S‚á¨cçuL¼Ò*ÊΧz­.d@W]6 Õo* xæBX];G‘—ÏcšÅrQ¤Ñ“@¬©$Áˆk¬‡YB9¹£öÝßÁ+ÈïWGO¸ É+sƒmç>Ð÷òãs†— üö×·€âb…á·
+áiI8lÑVï¨7åÜ@’Y…OÄÀ.A¤E2Jh9~„‰rS6·Ž†ÖcŸ,qañtLÊ1/Pì¬6²Ìèõ%,p÷å0¢‚ðÌ…œ‹ÅqhŒL:4Õƒ™áß:‘bö@6¯È^3ñùèLº<H#S:aWfh1ÏÈYØnµÉ}±áÕ^…‰èòƒϸe)bë!öc TBYgª
+Y¯cˆ‘µ)báVÄxZæÑþ6Ü¢:ÓÿzzÖèý)(!²é·ƒÍGç1–%R
+’MZÀÄ«Å· ‚ñÒÖ>Ý®k¨
+Áì £ùu8Î×& ñÔ½¯‚Lf,"Áe´ÊC÷¾
+:]w«ùWA§Ü®û*èÒ–×7½Ûâü¯šôÿêÔBÊ"Ù\ä1kÃÎ㥌Žå÷CÆfÁˆ’=+L侧#D¢\B6ŒR¨/IÏ°Cz,LO…ëlòA ´C‚®”ß)VJ×û:G¸Bóe…ІQX‚¨0ÔyÈ'!ó*¬:ÂðO]Râ|N‹Ôë¸|…¶ᘅE¨¦ÁÍc=<#
+Šbã.Á¶ʤ!Š$[÷l(
+b<œ÷ûD§™°ÂMT©­¼/¥¹ˆºì%€à+ò×ñXÈRJ^
+é2NèHöi!å uN¨èÑw«B]m]ÅƪTBH"­^%&ÒØx[Ä~eû)
+¦›qC[ ‘·\É è²S½14Û$ãã—X[PCÓWÞ%ŽðÌGãýÝXð¦@
+þ—¥iè7F=
+[H–ùo˜13¤Lê’µÝÍDN¾T ÈjÅ<ÄC*]³€ëòa ý¦Kt/&hBi?p
+'$–v¡ßÌ€´ÅÖ›aÎ õIñ‚za©„¢A˜þË9&¢¥±ÍìGÐ˃ ׈Š
+æï’ê@#ÓŸ'cäá8ÂóA²‚f¼,yÓÉœ2èÉ‘j)Ô~¤Ç*£’@/fý¸Wo0<HÒâçHI}ÀMé¡¡!~•t†à¸¥ÇsºŒ+Z‡Ï<DŠbÜÆI!‰âê}HE2-)åæSÊ7tgׇ}¸(M*<˜ 4<
+;Ídî–
+Zq À\"Ñ*}é+¤€3A¾s™º»“P‹`rV5ד#QˆIƒw@}øU•¡ÚLDÃC¿ƒ²a©ÒǾêDµ”Òáèa?Å:¤7]ÄÄ1UÒg…ä„毂| 4¿Ö¾ÑÍ‹ôeÙš¿Šß#)(bí§üçYÖ²½Úš¥1méycƒèyÀ&?UA{Lß­>h4•¿š­_®´.ôÃ{0b
+A¹#ì½EZöª~ÒÓBM۞Š_Y87 €€dé-É'°dþáíTN!gxºýùts[‡˜©S“TKë>£Z
+ŒêÙàðvkšÏzrR LCŒ¤ˆál¶æ¤’tµ?s åÂN¢N4Ž¸L½p³o™)
+º«ÌïuùÄ/œ”%iMŽâ“5 ŽTt^š†³>¸U¾%t ‘o’J€§:>Çx Á-$Þ!èõôÙÍðó®N!B¦4;uéÊìîâˆá(V¯짋°©«…µWez))Zv5œM!m…Ð=µš³ãˉ@Ä–‰tñÍjì"O`W'
+pŒ§¹½¤¼±m „¾•êç@=ØÎ";åy‘)—-0DçüM‹«¯çLrÀÃõ"å!<xªd>Ä ?ÄržÌÜMÞXG}K&otÀCÅš5FÝãLø²Îé¼»‹õÌv§Z—ÂÖòCuC:¨^tʱâUãA”"š¬lèÐN@w£fÏ*ŸVu´ŒóuiÅz“‰¾×]è¡krDVÇæÜ
+)àY›ZÔá`XÑ Àrz÷ªYh…ÒëF0Éâ¡ i|žÂbý;‚‘Ÿ1¢â¬~°5æC`ƧSP­ð\ Íaâý—ñ2GŽäX‚è pÈ`¹/" *Tž`Œ òþ|^Ù3]eÖ_€ñc•™±x<GÖ+?“EÌ"²ämÚ“ÊdH†5:}i±÷ ¸²w,£vâQïGH
+ˆœ€èf7^#þä“O›]Ü-,&—aÜîÔgÀ—½ ¢¢‹ð€ÓЂŽ<f ËŠð]˜OÇ8‘t3²¨¯îô’Ì©QÃNŠIt`·á…`bã¤oàã\HaÔiZC¼,Ü°eézA˜ËSŽH\¹ìâ•üMU²¾;xXMÓö îE¥_ÿ›tžO(Iu ’<j=5rfWÆéÑD4“eG2Ëve1n]ZÈf*&6]L=ù0#½šøQ´™ñ¶£†tzÑÖíÄ[1S–@bG
+p‹ÍÆ|£™ô¡-;Q˜Ö_³£jÓô'üÞd!tÖÂ0';B<ÙÖâɘ͹P€‡£iÈOŠnèBGKDƒýs¥'5!BÎNз Jwñ{ºˆóÊoAAUt©µû°ðr¹2‰E½kWNxAt›åg–<F¯Ãr¨ âd!ü§ÀŸ™n
+ú²90Í$Œµw÷ùº*ðßíuÀÄ!pKs˜àP´·èõý*xú¢wGŒ9Š¢jv♤xÒ¸öNqCN¼ú¹°¶|4ÆÈo/ 
+wTÖ^‚*ØRQ©ùû
+¡V)`¶/¢ ‹¦"]ˆ‚ÖQ-¤#VÜ®{n"Ü”2öÀ=$vcqmùâ3úK )äÙ¡V„
+BŸ u
+8ïŸéý!Rê]j¸èC2“…PÇ0µEÀ7„B^
+±£N÷¾sjï6§öó_ujc/;—‰¸@ö§Ü„< ÕïÙCÄ¥Ÿµã<v÷à`Ù¹5&'èË ªëmìó.›ôåw
+ú~åN_ëêá^*»¢6G]~n‚¨ š‰Ù«(
+êµn †`cIhÎ;„%ÁÎkÈŸ]:“Ékš©sDíñxˆèŠö
+%«Ã¾ÂÐÒ1œV z ºÂVj€'3™zE1.Ò¦C⊶Bh -VÖ(pÊ®]Ð@0Ù…* Ár¬°
+JÃzðOs% ¬Œþ³-:8H@_hðtÛGÓ³"ÔОì…ÈÒZÙ‘¼Z©2õÕ·±‘.Å•ä„ìþÃŒ©]Þî¾Cû‘Œ"Ód·¡ié~¦#$AAˆZ£˜9Ú«@2dD0`­ž@2Ʈϻ†È¶ ¬ë3¤3K÷H‡y¨,Ü/“rò§Ùý´ñÕÜWà²_C¾ýî^Ò´rxkzi?|$ãiµ¤gHÁ,!ÄÑeFbå*Å‚¡EnÔzuçòÃ]ÄV-†Ñ?Æ0ÐÛ6àŸt$Ô·±—JžBì$ü4Bt÷~hžª}†‰"ñŠf·9ÉJ„S7Ї–¨tU¨°_ÎÒ-V6½Ì
+fà69¨ŽyoB˜®€nuY¸Ç(œƒ$¹ë6 M¹M€êùjÜ4t§4è¡i¨ø—Új\L%è¹"ŠgÝíG1ÉŒ }›¶Õâ+ü¼¾“8ííeÅAè%K”éµR!ñ¡àj«åobÔržµ1 û¨¡ò£¢¶ÑåÙSýp6uõyÐ_°ÀóÖtÊ‹¥(„õ¹Bp
+RYêm»£@gÈ'Æ"æÇÐõü–ûÙB7¸VØwŠ­•¬®U†+ÂP‰;òM¢gŽRç>êt¡.£Å@#®æ3Ø
+Ú0qf“
+§„À2“!>Džõl›ƒ'"$¤msŽ†!=)º!'—û¹Žbth`}V'èÛ‚˜ÕFã.*Ŧñ?v:¿]ZÂ`Jº‘IJ“s¢¯Ø‰¬;6<)ã:V†¤f ­¶èm’¡#”‹>¦¿÷ØÑjY}{-çS„T!èx´õ¼ûŒ¶¾&sìÞ:@ⶭ6t•Ã•ìÞJZžì÷ƒáö€“c0™î(\sHxÙi\¥´â†œPuÁø˜à"Xá0û„OãÕÎŒÚê+„B—Þ\·G‹@M¼¬Ü¸FqGr¦^vÝ'! T€øY= K™ŠãA@FØAG;"Ú2JþWèMŠ•ÛK®WpGbE²“æw¶¸XÀK cÊ„ ô,5Ô1L-´× ¡PM”Õ Ó½ Ê!܆G{÷ns±z×W9–ñš‹õ¼¦øb`¯•:…ØQ§‚{ß9µw›Sûù¯:µ±—ËÄp7vx¡ä­Ü„< ÕïÙc%“düŽçqmö²È ©8A_nÐÉã~¹Ç‚¾_¹Ó׺º¼›ÍN›áäg'›lˆ(
+ݘùc;7•Üeˆ`П`r‰®bÌ ¿ Ûn|È
+‘Ué¬óxì¾sȯ·#ˆ Û.:ñ¿ƒä*Mº¿Ã„ !††ÆB  Ø«ü†B2…<rkýâóÍ‹©ºÛY³™Žœë:MÃʨåÐ_â´ÚáôeAU7ˆó3
+5•r)„Z’çåç]@<`%› <"ø×(˜i…
+l/~3{¾ùNe/rhµ?ŽªrŠü_ñàÂÝhâ1ÛîdP`•½®£Y›Ak–0E~‰Çõ”ÑaV›æ.Jïò$éÝkwª€0×(o„ü|º3Ὢ|˜C˜k¤—ƒ0‹”+ˆgÄ`_îq§ ïWæôPIæSùW£Ëó) ¢“¡Þ¢wkœ3 (` ùfw‚)€bTmóªZ'H…^F,y…D(,§…g¤ ÷ö¹ªV>@V!úˆè+"ÀgR’ÿ/“äJn$ˆž@w¨Ð0ëêeÝB[Öý·ýˆø$3‘Mm&5éD1ø€‚oK‰÷/<fC*F‚DŃ0k|+õÜ6DæQËÊ£»kœ¬I³Ã<€Þ ùN†M¦}¬)'Qp
+›öÇÐtDU¢TŸžNÉ3”ÈZåÝ{ÅZ:/%(¯§/cÝð–6 ¼J{X Ÿß`LÜ`?Û áÞyCÌ¢ëSC/wC3V s%}:‡’„¨à°sp_¡a!ÁIÊü`¤æ‚hèiiï/1uøw¨”¿´vb‡xÓÇ>…j’Ê0€ çŠÞ«'
+wÕís
+ç)N½žµî¿4ó÷–Öð¦É™ÅÉÖ¬ %r[J¦¬áM{ÏE]¬
+€a–Gnçs³C£ÅÍ×ÕM¡ÁâÞ:Ýß^Ýô s²CñMzÓÛ£å¾N”q
+ãÌ_dzŽoTG&!ùnÝ#¾Až‹çUÒŠh0&o«âÝÇ·ˆ5À‹ÀjõÉMÓuD%ˆºg<ŸÍ13Ęڙ¾Âjy’8¹ß¾›iF°–(å¨Î•W3Í(³ý”CÐÏfHìr©Ý}2Ó7ЩçéA¬ÙY¤êÇ ¯ øþƒ%].ù×ÿþáéãM¹tŒF‚1N#S-­³0,2õ`Ñr=€DÞ-Å'Ý¢ 0!T'ñr–’—á¶üvõ^ Ť2É\Ý(‘*Äžû‹§Øó7pL7¸Ò¿©´qC]¤n2³›X;ô 6</?€¤x‰¨Á`Õ²Bɺ4#%Ý .Ü_@ïAÃØ)Ï´_@ BXoV;Gp´
+ëIPáêê¤]‘pøáC‰uB@øÀú§ð*:˜‡Ÿô õV&°²Ð U›O3øí(K¿Âú©Ká³ÇŒ{„.{ö×@Q¦9ã_<*[DJ´ÖçŒ!, évamC]Ä H‘mÚÓäÔ³’ç««s92¢Ÿsý;Ȩ à8„cFZï'Ãà7hõCFÚý(ú·lçs:£9XRd&$)v4íîL¢Ã³‰aìá2“9ÖÕŽ‚bôPƒ1l áLv)C ÅΩu‰¬nn±¢(*]y€TJ®Å âDÿÔ ¤ ÔTf*º/SI+²%Û6" —I«BH¥x”"Ú³žbQtq~l¬±0^14$4¾€0á¤píþR3ÉGY ³a.'‚úúó
+øJÜ¡¬‘¼>´{V)­‡7mE¸bÖãq#ü :>‚E¨S9’Yh'ˆ}©°ïȲLíÓ9Òà2%1&&·ë2ÓÌ5„5Î>á@b—ô±ç‚HFj¡Êî>åÄ#àêÖ”bCqœt°@ï k7oÓΫH#©II§-é®C&²ZV›Ô”+p‚eú^I³#T=Ü#YøF$mÆLEïö)zB}Ñ;œýñ鸑ѹ_ÕÖ¼8%Á³ÅAL0·Çäõ4Zs‚Ë“ƒEq'°*÷8°Y™IŽá+ùWž iOüü¢”•Ì‡@˜²†0²Ýf­'64jAþÝ›‡gF¾!ËqJB BEFµ°sFÏ4ŠVàBÆ¢QQ<>ÿr¶¸`kAcƒ‰ïÂn°üÏ(9 ÇÐ ’ìßšëÏXbö[·I”Õ4Y*Qü6] Ú”1ÉrÏ~Ÿè‹Æ¾ÿDˆ—QÕŒå¢lÈy¾bæ$²£n½î4‘ˆ ÷™§Ä¼î ÅÖÂUŸgÏ ŒegО&~Q„ÀË¿>CVWÛÄàöšÛëë9 ½žLt˜æž®ÑBzAZã†u¨û÷?'Ð=ćÇÓÇsO k&Ø_ë0ömŒo0_oÄHÃîJ_‘þìÆ6u†¨µ=AJt$X…8”ö%…óÒ ÙfÞ‚oÚfšJA‹œHyØfÆÊ'<ÄÏQ9ÞœHæ"0Á÷E?%)RÿÒ÷cø)V±4x£[µíè° cýŸcOìÄ%2Î
+O²–Q~KBˆÍUE‘I¬Ì´ ª„š“íâXx¤ÝÈÕTYV˜-Òk`?ß|A ôœt‡àr8{Û†@䆿÷Ä>%ÓMN@|ωRÏÀ;›AèS ¡¶¼:†;› ‹¹w´ÝH"mÄ)Ãfk7n .˜¥*EÇ(1óßRz3‹9!¼Ú±vÛêÊA–X:wÎœÜP îÑ=w}ØÓ»:“dŸO äÔ’TÓÕA
+l(ÇÂÀ‘„Ùloƒ¡Þ¨¢KùƯÓt•E
+©¢ècÛ„Ã
++|]6ìG ‹Çñ5TúÝ»Ÿ¢æ ¢Àf ÛBÖ‡x(Ãtæñ[+NzpkéýœÛ`\ éiÀxTZã]›ê2¨"²¡ouŠ^~W"ñˆ5´H“e&õO}¿Zæ”"·¬ 9¡g+Ý¥õ7/ÇxjéNÖìÏtjýísÐûOîô!›»\™Œ#†ùÀ 7Ï­|#ŸéD£E4ˆ\S‘VaCÈKò
+QZœºÏ!çЊÌ,Y¡ŽyJñ0ˆjp€Ñ‘kœnŸv
+¯dj( boö ”‰)ê ÈÁ®·.B‚!aÌèÝê_cô{8´22dõ1L¨ÑNâ7$I•:¼?-N 6ƒb°®£{ydEˆHøkWÄóMY1"Æ>'ˆ±œ/R“8ó{&<•Hám–+Çק® Âi|¼û§¤ê¼ªTÓÖža<ï¶O)RNH(x?GTôIH®þ©HåÈ-i3µfÙ¯¨O^œ1
+ÙKQŸ&ðûIþý¡šA—be0±£>í,ãÑ‹ÒÝ0W kUõˆ²
+ò¶‘ïÜ+‹Ê´gÆ5i/Â0ª>RÈL=U^†bYñ¼ò™ïg' ]D !Þa™Î~½v‚*)̾L2uJE"|ýd:Ð-¨(oHe:ÔÊÜ‹Aà+D é­'È;}ýy
+8SÍíXiý°
+¦P»¹ùÉøù'ù9Üi0à¬'Ï(Kom‘3U®ÚzÌ«KÙxUu(_™óºùÙ«_l‰ÜŸC2¶^0ô„Ð #ñTq5ñ1œ¦·
+óV€J®ôbDÕV‡þèÒ¹4BdQ_§S[\£ëBWhH³M¹Æ¹â„Aª¤Ê£·±h
+JÝ`DipËÔ9ûSãöeàb¹ìp5<§AV³Œ—Eã:AÆü©QüàþÊ\‡ÒU(ýX’E6¤cjw<E¹ùV ^THY|ÀuxÙÉ¥ Èù "ÄôÐ]{‰P6n?‡”Žãi#ùê…57µuF%²[µ7•€9{y\½7æ «¸
+Æ­ñ)h“;¯Ls‘Õ5{wq©çÎ¥´{‡à¨G~ávÚ] §kÜÃ:M-ä7^‚‡žÈËp
+ ƒ{:D*X†¦Ë·Š™.1i™? ¿ÿ”©bŸëà-` >Kn>1Û¥
+º„ ÄB³ ¼ —¥ƒz™›1¶\úeçTUÃÿT‡dØ5K
+y¸#Î1+|­‹#ÝZÊ^ó3¢ .ZÊžt/åÜ‘®†o¨ µÚxµµe‰D´s{A >
+™CðÈ<;%¿6[èå¢a_¢ŒŒ‡-Ï D~J?È¡ÏÃidÎb}¼Œ
+«–Æ@šŽÄ;Jb>p¦±l,ÕêP¢›„.¦U¨ƒ¢Çáõ tR6¡z ÔHg"¯Dtµ‡cG~Ù¦BÚk0/ …4NE'k0O è¸$žS„ã÷ÍxE«Qó³ ¾Œ”1Ç qÀ&ašt“gi¿8Ñêð1cN—ãÌ%ÌF°ÇÓ!’z!y+çÏØÛŸµaf}–îŠf»xô} "eA­™Æ¹[ò5Ì6cs;™Bp™E3ÃqðB W¥ÕNo`>U¶îÜTÑ&çÛ<gñ
+毊 %c¤~›ƒƒÀð:èÝ!ˆ›Ìú\‡/àf‹ì³%+M oåAÄ•cl«P?Z4ä è©ðo[C RÁ"Ðòen†wÀá |eI·ˆ€Š#èÝ…&Vfã!bÇ1äaëæʵI†u¬H†+/Šzpÿ,Uï,„ó _~®æΖŸ{⺊‹2ж\9"¯«Ã”CÐß¾²ÿ®Ó†‡É÷H¥´1êoòôHN£¸ÖðU}4úråš„’öÛn¢ P O©©k«gÓs(íD`Edü7qõûe¨'ɾ¥¾Í´;P¼¥Cl,õ* tÚîzûÌ™¾>Þƽp3´úSŒäâ°XØÞï${…Ì„c: j’Ì|RÂm˜¤â 0ëyA4?Ì=Õš
+HV¿G+Œm ž²A¥,¿!WÌÖŠpôu@çxÓH»ß@§™!2@vݽ€DÜø{††F™ï­CÃ.%’æ0ž@oþ>‰åÁcÙˆ…^ç¹]œ¹'ôÖåòã„Ü…“Ớ嘾÷àÝ5öx$ˆ1Íu”àÒ¡—4µãß:Ê Y‰
+æ \[AÈ*2Lù¸ž¯C<ê3®õ‰ªá1wŒ«êÄÔª¯][ÅF8ã ÔÕ=t%mg<ä\‡&é½jÁ[ùçwÝ óPYNb¼Z@8M#´çO …îaüødBà0:
+1“)œ\es'kvÎT­®çO86(ì¶Ò€åŽ±JÝñì1Æ
+¸ Ù ôöt®æ¥Û¹Î&5)éX1°<ÄÜì.”4ȈŽ5V xÈY^׋YõI`¡Ú\æh
+-œ2!EV‹ [·¸½9N§ÛV ̓‘æ†=”Æ8(j†’š¶-~3“³LO¡áêT6áC-Šª40äÈ}ø¨*ψ
+ô&|à"R¾tO”ÌßFÓiDÆ܃¼§(FßÚ$”Á·Œ6BhBö¢LTBb¸ƒÐ­éðdˆº¸â„A¬ñ#ÈóKc; TN›ðeuš9 Æ ­²öbZ"©l.¯£_F‘ÓíH&4S]šÇã’9×q. '}ûŒ
+˦þôw4ûÛ—p·AB#ÝÂQ1<„~åðôáñ+­¤_~ÅÙþr‹·ñŽL¶Ê
+ÿ¹•Û_¾u¤ìôE±ê2–Ðp˜Jf‡éµh÷¦°™ÕÇ€[h¡«x•Óý£ý•£­ˆ ëü•Åã<ì<ôï@¹N9F :Çíß´3¢¶yºF2Ò#<,ùYP³õÄÔ¥O«Âœ$%`?^Ç‚²÷9‰ÆHÅ!¹tܪP¯ —åà᲋74IeùŸúzبoŸ»÷¯À¶¥äœ=¥v³ á‡ë‹Aô®ö¾]€drƒÞþïûã$pšéÇëã/ô¿××ÿè@_¿üÁáÿôÏ/?ýÛëÿÙÖüýË{ñ›‚ÙG—äyk2Ü4O2‚ÃL^QnƒP‹d&HcFM“€yêbOÂg ‹˟àÒË„t£ã%µl +ªx\œqorûu°,xW%½.ˆž´Ãô§ Á»1¾pÜpHV>š*weFe_oƦÉ“‰l˜´Ï‚84®‹Ig`]f†c;*è{á#ÐóÁ¥CGéPx›ª€Tiì¼MP£ÔK9þËx¹#gr#AøsÚk0ð~Ø”)wO@—¼¿»_Ʋ»ZúC¡Ðˆ“DUYY™q ¡ÄÍñVk À$É
+[Ç·V×b혌!æ üsD$)²É•,ק—œ ‚m‡PY¤ÜOO˜¶ÀYáXÚc¢&žZËOiõÐWC0ب¼V\Þ¡ ê˜,N1Ø ÿ
+“(Á9Ë¿DéËêë¨Ü· ¿Í@“öÇœÓèÖþ ,Ô'úçÐ2VJ¡/Úë.”«D-ñ¸:7 c!tvcÜk<‚Ýœ º¿AˆÆjL¬™}H¦.Å8WáeÁ}cÙfãRÆZ8h"váãr˜
+¨w¼®bú¼
+ò÷²L:–:'[vÜùÓ´Ô ‰ƒ+ Úʤ~ŒhPèjUC{†#À«‚ô†„DÖíG£ùb^÷Š|…X?7Ë=çwËÝÛ\¨ã½êÊÀ{qn4¾—ØüjÕç+3³-ë¯òNö!Ê fvÎû~
+e©’Äa$Å°ãhûÙLø·P•þªQ²wr
+—B\‰#»I)Í9ïûĨVLBqQ1½wÅôÔت:¢\8¸‚½Ø-<X’Õ&Z~9b›g7gŽÞF2{,báu
+ÛF´
+OAâ“xÜZï‰lÕ&£eè·†–ëÒòO¼Þ¦¼SbäcÝÛÓ«Ê»|Ö‘ÐýêTEJ®¢mÝ;ˆ_úøã.ÿz
+0<3Æãûg¤:—ÏÃ5|ü` ¶èS_åM!?Mh$ñ`÷qL9&ÿ˜øž %¼”tc_Âòʆ§Ú/$o°¡¥×ÃlÁ“DtÙ/¿<þ‘¥ˆ¦Œ6#6^y#qûÜK Ë”º|¿`Ö¼cžÄT§èZº£@ßûæ 9
+5Q‚ÀYŒórŒÆ,Mãulš:[± ³ú…–áíÌÍsi ‚"ÄòàÒV§*3SY.å¬_ÎH¾¼ )-z»ñ…õù¡-ûö—>ØÞeµ™Šnt¬—¥Æ&Šø-Ãà#Y‘të€þ~
+
+H‰Œ—Mr9DO ;èó ?\»—} GÌʾÿvŠ,ÙªbÔî…ee‘ @&´I 1•÷j£½ø±ù0—Þßÿ£b/íí˜{è˜&M¢F”ªÒmøâZß¾ ^J½G4› 6ªóG%ΫD]ÍcAT¤˜xµ² Öjt¯}4Ù@ÖU®6¬6­­>CìZ‹ÔâþÍè¥WéÜ7ž^Õ_¥ºŠ1ûì
+µD
+ÕƒcϪ¦ªÐt½®7q± ´Sÿ¸ª.1Ap+ \MÎ_¸ÌkŒy€ŒF­`ˆSäçwˆœœ/“óåÕƒ)ÀyÁý¼ß ]´gE숋®òÃ4{oB
+ãŸàÎ9 I¸8Lêl×ÐŒjréc†^^£¨zšcõ4ü/C:ö,Îó^&¼kÅ”ælaøÛªÔHœ ß@V–.ÙAt„Ýdi…Ò£j|Çé[Òû‹1À0@ªÒ#Bò\þQúgòBN´µâ» íô”W…e©¿êò BøÝ ò·‰‘ÊÓÞ(€}ôa–#È’ê)Š)ß®1S„Ø _‚¬«¸–×’1ë»b\!«Ÿ‹º9çJ#ÆF-•)£;Šå£2RH׉“b96˜ Pïv”ê*Úº¨š)w^ÚŠ¯ žˆóé2á/=A1*¥#´ûª»þˆO@>2¿+U6=ûûÔ™€ÊÄŠ©, é$‘ËY¡syíÍ°DmB”¡œˆ¯9Í7Ì4r0#O ™e’“XãÞ¸9j²hžÂ_¼c)c´­f
+÷`nż<j]u!Ü4ÏÁ¿ÉºêB-´Ç¬.]Ûx€Ü´çKÿÑž` hšÍlØiÙïÐE{€ ´¤›`GÝjO¤¡Å¥àIÔƒöDzgEÒûV{€`ë¸Û„£¶š„ÈŒ0ýåA{
+%ái±¬«r@HÜùþ˜Ë€OuÆ/02ËÒÒ‡+g4µóMÛE=«œü¬i/ÑÔ¦ Ä gÓäÅd§[@<ÍcÖrèBaPÅÜ1Æ^ÙÒ÷0í`±:…í˜nŒfñU̬“Ó²éç–lá€:¶ˆ}lkÂnÓmgænSr{ÎçY{w–·™}u¨?ßv³û€UKecþøûNApDt%¼ÅcLû°P6Ä^Ký¸êÿËÕaæ 4E–ÀÂÙŒÒß ”{¿„Ô·C²a¥¬öSZ %¼ýÔ£ªŒVɾx? _:Y\1ÝuD_š‰f]À9?é‘Qã þßiÖh9rFܳcq/$eA”e¡ˆ¾\“‰¯´ÑÊ‹ªWÐn7ɘáá€iHïwAéXØ0ào§OýÌá „qDDkmLï• NŠÙpZ—ÓA¡ù˜æjAH2Ò<–à œ
+L{ÿ'£B
+K£MÐSEØ)Wà¯(MlÛ€èÒJ®‰Â"1ŒQ4ÈÌ–³v“\5sýÔ4¬@ö*ÃÓªúrdɉ±¯”nOçtœo½v®Aɦ‹ðíXMqOÅÂÜŒ "g“´~h,«‚ùé=ÿÇxÙ#É•ã@øºƒì1*ø ’æ†\¹s‚Žõ$sï¿_’`iªßt;«ž,>Hd&^6¥_7 Ä°ÌðÀtíû„"¾¦»‹‘í«Œ)ÕÉÚ13+y‡w”oîRíÏÓÙáfîm'óA9‰09¯s ‚ø‰ÜïØ­ne¾G>Vù ò±
+é´ÅÆN ÕP¦KwI­Ÿo£­Je©ÚÝ£ Î”ˤ¶sq.캖ø
+ +§~¾CžóEMÉà£æó9°K4æiaî$‡ÛÀR,¿„‚ÙÝ«`;¶›d¨ãFâ/##ó„V—|Ôn /½úøÊ|®¨Ô
+)(N_Û,PÃDY;Yì|Œ±æÊð`oÃB}H éÐtR¿ G‹ã.À”õÀ
+ØcËmÊ)lIU±öèÂÑ‘ŒÐJ3üsl ü;ð#«·¡J;Z"1e[ Ø”h´”Š¸KÃœÄ&ÁÒîAy°Ìu§×CÅD¬%WEòN¿;©`‰¹ëæ¹ò°8}Ú`ñ௿Qõÿü÷Û_ÿ[™»æ%c$2\Y5)¨
+\Ø7ó~ Ä ç™êµÍ@ÒDʆ4ά„™é&ºÓ–1ܤü‚ÁƒGÅ6…P ÚùY%¬Ç…éŒâÐ"„¯ch\VÅÚÌÒV0°ÖŒµgAØ”ø‘x² tSQœ4?Š„P/'ô)™Çúôó”Ø•èU³¤ÊO’Á0ðëâ7‚häÚŸÚ÷Iª¹*íwÐ<ôÇÊ‚ðÿF´)& bÝhaA0b[åAó9t¤D»Ì$UêLGâ:'K
+åܬϚþc»ÿ„ös>2¤*ê‹}Ñ´ð¤išPx
+9÷ÜpMHCŽPÌ«s™ÆqÙBvs
+‚oè±b¼?*hÎé¥òðüÒxã{òR?J:¸@ŸoÂ횢à êù›†6‡¢§VGôœ¸7jÞ'Y
+Ç07mõò
+çÊhOfhb™OœÔ¯ ãÄk[Ý'c99¦îÚGªؘ[ÀAݯø‰ŽJqùƒéaÚÆ
+Õ’wâ
+{.ù8/µåŽ˜ŒªHªFöƒ$Làû„ @—\¸G«ÊKj >.4Eß.1£§ÈÇút p“ÏÝCß0ZÑÊYá Y4h3°ÕvâßNÊ«áá(¯á«<= C„^¾ŠAšä×W ÄÇ
+é•5¥–½ßšHÌ¿’±-ø¨ózV/
+'[—Éï4‘³Óz=öÞbȘÏzJ+fòž Þ
+F›Gac!Þ1œä‹€ ÈSÀµØŠCÐiƒ`f[º5üÛ•ø?¾@¹O¬p _£s÷mÛ¼.á1³jx”áÆ4!M)F>YžD{
+ø¼a ›¯×ð˜†ðe;§G È
+hLë»­ïêš¹!9°w"ÏîØ%?ÂhœÓroÏ­á=?Ò¬ ÑŠq§S‡Î_uJŸ—°CüÞîÎi¬²ˆ];¿åGøMúD{‰‡›c—ü¨r¡t5B»vÌõAÎRìγJKÐòÜåÇè ¢ñ%Ð5?^@—üÈ@T­š`©çü˜§òðŠ”ì.>Òr¾“åž­žã#Ú ¹AQ;Ç>5[6¬ÞÅÇÂr§X­)ÞSð[ÃN¹é9>*è@,d Õ½ý]â£4·ËU²s|„€Ú’ÐJkù/ <ÅGˆ‘åôúû×—øç$Ž$E÷¤k||—÷«~¦¤#É&,‡?„–ß „ÂgÍyH;¼…–H/ÐÈêM؈4p ¾$ÚqZv7Ø&ù£ÝˆAzÀãDP Ûù1,ÐLß0sQ5Sdî·†Fq é&.x'.˜C6L,BóÀ•ï2æ£Ù'NÁŠ> ZL|ãBÆÌ­;K+J¢ð!¹psCFu^ãQ±o­9Ý!dhõ€u×|nâÉF•I>ÏþêØô_eqp¸ETD jªË""ô’žÌA?@üKÚÞ”¸rJwç „Ô¾wR p=ð(ºç¬ á¡+ËìèˆM‚Qb{>Š¼œé^©{­xw5 ¤Þ-ºt6–GæÜüS®+þ ]9bò‹СçîÐ`am高Dc:—Q@…¦?{ýúʈÎtm££èìgƒG7pÅKÒ‚ ±ã÷ (•€X£QE‰fBn©XºÍ$JÇBW0œø…M±¤˜Cøo ñµ€æ©g䋨±û
+¨±I%JÓá>mT"v1N«åd
+1çvÁ¿¤.QJ6‚%è&ðÜÞö§ eä:¡!û>sHcÕ˜_žÖ’T¾4žÜ£ØT!û?ûe·ÇqDá'Øw˜’c­úÿ'A.Dd¯DŽ`A@P"­0Z’E;ÑÛç«îž%w¦Ç^9ÎMVËÃîêªS§NÒ— ©QGÈß:*SŽ%ñm)±,É“w·
+¢2K+qŒØªë²etXÙ}ªßŒwç±ú,‹s§!hj,6¤ÁX*iÛ1²ø(±ø17S§2ƒBjçй¬—¸ô‹• óØj&rB游¬¦¡‚ˆ è2iu? ÌsÍ]1š¥Wá“Éf
+¡f a1|j cd~˜
+’72ÀÊÉÁà gÒ¬hØ;”žõµ{ÖÓT^Ëælé‡ÎaGoWç—Ã.àÉp¿8°# ŒïröXÖBÎÂ=Šm¤õÓeÚwÎ:0.gõÚ¥H&,+¢]Šë„ŽzšÌQxÆn?_"©GG«G§ÏžßÞ}qùöîòæúìöãð[ùêåÙ‡÷å“žÝÜl‡Ç›Ëë÷çO†ÏùR_~qùáìÍvüz‡=Þ^~ÿýåõ» úÅõ·w#úä÷åg4í£Óä·Ç~ 4ˆ¶ÝõCÄ°í²¡Gµ¤I¬ì 6=Tk@Y’L•*jvå ¶=,29^•Ì»Uëíj5ŽÝ‹w}Ø®6Ê&!‹Ú'·+æÚie×®9v˜TÛõÑéO4,“>åŒáÚõ…xoãî9#©0Ä+ýÊóvŒ8?åû‡Ýw,û.×ÍOƒ€N'­aihG5´½žÍ ‡=KØßüÂaFÖš–Þ£ÿs\Œì¤íºÖ' íBξ+]³Ø¸ÿ=<ûúæîÕÅÛ›ÛsèX:ô×c׳WgÛ—gw·—ÿâ`zþù‹?4Âÿù»›Û«ú£Úê¿??¿ysqúüE>%èoî>n/NïCm(þ”DZ”ýdþÓ~ª_·¿KC´ì…áñ“áä[>½æOÞýëä7å=„y<a‹"Ö/~õ/ÜÿRŽ«EÒmm:ù8óKÃ_þª†óº¶rPŒ^)>ňL+Qê0VaQc{mªý=ƒ6U~,–ÍÑEÿПMuÿ´=$¢Íêo«oW׫?­Fú”yöÙ5Ål+æ }…ÍUdÉ#ÒÖ™ì½XmÙ]Æ)„»ì#E»²G“˜÷VW׎ Æd [@Ž_pZ€­ úØâÀÓªùlR‰8ÊFDæŠÃ/冈h©Š–ËaÖ1pZ—<ÆýxÕYQ«T¾HX+Ìy~p0$Ê›-åTÕ¥ÌèÍ–Ř¡B ›†%Îâ¹åQ1Y2•KêKÀLmÙ.ÈŸSã±òLrçÊ&& d³˜'•b«?cÉá¥d¿žC†á—‹¢çµ9Dcø½À–y@=e©æÖDK6H|,2¯¹G£]®”âj”M’ÞÊ TÓèa–õ¬HJŠ| H«5_Š't™ŒWÐôºÃ@²UB)—­¬ŒÛŒð—ÝÓã^ Ï€¤ ¨*£Ñ4~$§å›«ÉF)’ ÆÙ*ı@B#«œ
+µh€pt«º]Å£RÙÁ´zL²¢µL[òÃ<ƒ7ÂÔ£azˆvfŠÑíuò±Œ_£ê9EÙQÄXë”C skÀIöÃ=îÖʬÅ0 $ZÆØì´mÆ×'5ÆL[8˜Ê[q{õá*™$î¢A¢Áá¢=èXKq‚oV¬Jè@ÚË=ÎJ€K‡”IŒËÁÂ4ˆ’¼ r¸†
+±€I¾ì^SUi÷ÐG˜ :ºØ @9Iõðx*Ôsx˜oJÞR#wóðh°Y ‡ü<^õ0=¢ÛB?\—q ¨Û|Óëí B·±¦ M‹óG§’‡2©Â‘-Úvµ
+B ‚!ˆ©çE>䦃„™hF¦pÈC#ufÄw í*Å7.rQèÎ9ÐêšÄ‚ÓlØ`•—ÞÄ¢ÒÚ±.:óÜ
+£Œ)‡ƒþÍx¹¤Éqã@ø¾ƒNPßµf©[xÛsÿíüA‚9®J¤»7²ÔŽf’@ "@¹JHÆÝʦ¡êYÌÁnô“!ò+ÄžaŽ žþ2ˆu‰H`a¹*ƒcŒƒ…HÏ`"lÍF[ Y.¶sŽ4
+KUȬSF¹™9ˆ]ŒVÊ}@<7ík§Àøa€”À-sÔœ$Œ‡¡¶‡v"¶ë§C´|*uæîÌÚ2rDCòF0ò$ÝÉÎ A7°ý.×Û£u9µ‰c]_JWjþãéûwÂmò^!Rå=¥?é; ÁrË~Õï
+Ï‚[±\d¯”á+|}ulÆX>4,¶W $ešY¤,¢þ6ÚÓ9Œ0‰$¡‡Ùf }’¥f†^õ‰­†W1o#'ÿœÎ¨³)ÑìzÒ‚°…jÿ"Äyð÷î)ZAÚT
+ñH‘qWQÁ—xA@•÷?Hüäq¬ãm“ÀȆ§A¾ƒ‰÷@„`Ö”¸ª+ñ‚ðX¤1Žù ð`‡¦OÅṡÂ!Ò3€•Žzm_•n´Ë&ïÌ íZ ø8ÚótNÄ·:„&²¹
+„r¢I;Êò©ð"áÈL»Vº#„ï/S+A/%º/H˜³°ô¦'…¿a¼–·]Q‰4O1õr^ ,½•ª+¸„PÉPpÃñPåÊçÜ©å²®{·*zPÄ'?E}1œ9Ö§Ö}‘GgK›Ú“Èß@^}ʺ4«Þ
+reþ;_:ÿë?‚¦6%V£M}¥€8 (8ÉÖzÄi¡ÀáØ×
+¤äOnX&Œ[_ÛuC`ö]Ô¹ iMæG€°¦ðæÂ
+;[oÍŠP&:KÙ¨:G[£8cጧRè/f#25"’0ͬ/e¦B¢:±?35Ë4?u{“d½rÁŒV/åf‘,°+ÃÜ"ë·6ë¾JüņŠõ¹{v1#TTj¥nCŸÑ©>JõšGU vÄƇT%©(—«ºü”Žï1^Æ\æ¶A˜ù:îsxO’FS#£Š[ãˆ}é½U÷cný¾_æÆïM7þÝkscñ½ÂÑß:õ÷OFFÓÎt‘æÛ)=iÎyÿuAØ3šÇª„{!ZFâ œÄ#Š¬»±"9mH¡
+›ÍñUt$•µ
+;SÌ
+Æ1$RQ®vvŽ«¥-2M#ÌÍx|ž0-Iá-èË@Êå´6g{WªD÷®œòþòÝÖ¢7ÚÓÓkePê$ñrLî#;Áõt¢>y‚}HÆrDÞ6Y•‰÷L6™}ª: ½S^*/^0FG›[_Á¹ÒEy‚Iòªı øe3ª|€ÌñSÛP$ÌKÿ¬¡èt ò„^u ¦€„©|(ŸQ§„S.„Šv&þÒÈj¨ú§Ì}¹êÿ”’’²Ý˜©f7›Õ ‚+ƒÛµy9L«]IÔ¤«J• ]9Äj'L!#ì°/ ಊ \jìcŠ¬6Õùl§ëG>Pˆ#„öωš5–ZæÒSÝZ¡U\òÌUe~{R§ýªØVõrAFΧ:µ€ûèÊYd^΄ÖþË–ò¼¶‘œ‡ÍçÇè‘VØùÔC:ãù1Ãï›N\O»$ò\N0âr$¬|ŒlšSøû°e1¢Í&L<®år™ì?~jL³ä^An`1¥ï¿<‘¼çÁÛlz±’ja¯˜£¤úéœÒ«†ŽW¥ÓvŸÆÊ’º1”d8µ¥ä­šö)J))MW£Ð"c¬sæR"?Rƒm\pòFUD3ÈrÂÞÛ8SpÊ‚õB‘ßù™YRL Äý¯œAGÏ·¤OÒÍz¤Ò^­ØÏuÖÆU í.ŸòƒÇðšk6‹”—üÁL²i®Ò²ÄiŸƒb=ðÁó¾óÎßËbCç\ŽÄŸ.±%>NìËb¡­h0ªrÆè
+ƒe‡ÃsU¢˜ôþ¹OÐ×Oî´ÒÁŠù¡¾ÈmŒê@ÅÏJJk¡I&ï„
+{o¢¿èóÙm{- Å•t‹B§ À(3“жÜ0(‹'îÐõ¶«Í«¸ëÚÅbw@_VšŠâ?¶æ€„@/ n2¿’Ф:Ò~U}鑈/Ñ:Yìc¼~í‘T–!ÓÈl¡¦3áÔ˜þä¼ÏAëè(üÞ€Á1H³¸6“O
+ p=­¸¿ÊSì¤Côõ
+~®"3ÂÈ©:oý„WÈWï›ZÅxlÛ ¶&2)úBîHÅ{ùçŽdŸâ”"Ê£þ¡’¸jœGঠCmîtK(Þ"%*s0ó€Kù‹” ¢e réYë*íGñfè. Ž5PdKð,ðDE=ÎÖh_«%É$Kµ¬²î]ì´‹¯5œÛÎÁûÑÌš`óx€Ô';Í°Mê¯IQë †}¤€dÁ˜ðØ8M”CÄY]ì[”®*|ŸˆJÿáMá¹Án ‘&#’Ž°kÏC>’â¹Í'æÍ`¿~âÂv²./IeOk.w/Ô "\Š£[4u@Úw %uÏ›HoŒ{ÈÙ Ôj‹ f­˜¨{miC4(]ÃÐÍn¢$0¤…¥}ŽÊõàG¶s–¬àÞlM+Ÿå—´•Ï׺ôô²>•iÊ`÷ÜžÎùãå’#IŽÄÐôêý?ëœe¥êþÛyt™b:ÜM“ 4È,¦$7£‘4ÚÕ3 RxŸs{M†-‘ ¤‰xú*@„ð m3W¿:@p DÕcØä/h±*}@D̾dÆûxßt1öY±=-+~¼e\‚‘þéûM@x/5Àçx—ï³6c ::Åíœ[…H¨ßä<ÜNÝ FŠ[ÇŸç<xó|̓ÞW=xü¬Ž3 JlS V]Î÷ÝT}½‡}ãð:ç)(«]ìÈ.•>mµwUQb/ t»íŽùóƒ™h Z]®E^J69ˆ>‘6’øà¿ÐóMy•[: º»éoﺟ>wÖ?L’³#üÄíkV@š4eð{5ƒl‘Ðdd]õ
+¡)'ârð~ÝOA¢à×d_TDbÆÿÒ)•8 {*Â.R®Máà»@H^“²žü[Û*/VªîÓÏ@Ôe™þûi‚u–u®g¬·çS*aM]¾Î²ÕOç°ô1¾‰™Ï§×0”º‹Ø}ÌZá…jð脶t¿:@ŠY9Ã.àg*qÏTâ€n©äñ–§ï>¾ÉóïGmž9àQágšxtÊK%Ž{çÜxã½æÆ?ÿ«n<öªó˜†{*ùnª¾ÞÃ×Êà"Â’—8þnî |8CèÅýö@®nܯssÉwoºtƒ½T`) LLrÎúk `€}+¸Þ×Æ?Q½ÌãK«H¯ÄÆ÷a ó‚$ÎÀ¸/ûÜtŒ4‰fua³XÑQ…EtA2:é+o„¥tóºì2(0\—їþ©y^¶ñ
+¨‚ò”·ÒÄ€JTñà*Þ%TƒÖ-¶Ò0Ó„£.TÊdª÷{;óO4+A—ý㼆¨C ™dŠúS3ÊßϨr!ô|OB-ýàa>À… ¨#ÑìíYœ Àñ¢A³o• †·4~»ò‡å
+Ri*7k“gÜ‚@Œ$ýÁƒØU¹Gü)Æêé1JYrˆ§×(ô’)ÇŒç‚í­Ë&R9‡×òg5îúýÛÿ]ÄÝÿ]Їÿ;o¹;Üó“žFéTæn¸N}ï¶íôéiÿN¿½sn¬ñ^scŸÿU7{Ź§û;P_ï±c›ãÑ1oÎmîí¸g£©é$wcþÏë\ÅøîM¦ùEMøq6@®"ÙxýÉüË‹˜ÁO9Í¿°KѤ’péì›AŽ+šNp9˜?òÍ°°-ÆÈĸæ/HÑÚIf+Û$?Íÿ‚0j$Ì¢úæ¦•×Ìc6íºgó€ów0wó/´‚iI¹ûæÏ¿£ %ÿ?æ_^Š·AÁNæO“ÞPÑZ|Ó.Ê×u*ïŸÍŸ–ó'Í¿¼RBa¬|ó/ê8Ýžílþð¯ÔÔÑ°’†oþ™h=PÌ9øÏ7 JωãäýwŒ×îÌ Ò1z­Çi¿ƒÜAþnB¯AþõA#ɯ¶Hb É^ÆV7ªŒqØ0G^ÏvrKÉHzÑ°Ä)vƒv1JÀ„Ͷ pµ-,–Š);çªRÅšŸä{°jvÇ"ú×$ n3­s$ì¸V$ÝdqÑ®AåÉs45ÛK"
+2¦5§/VDf§|&¨HÒð›ÞSû¦&A‘.˵ñÒ ´ËLåòµ£! HÑ‚N0&hSŽ´ÉAa¼¯*-˜FÛ¼á1uR(XõÃMQٹϾïX,Ó ‹ði½ŠP—“ñ‚ho³+¡-¢•(@1£NÌ4Z0¬F쎼RŽÕ ,'½È‚q•}… ­ý„ÍD›g÷obú:‹$߶Ë8;ÃH°#û|6ª —s‰dW:·Š¢cõtNJ†0a?FÝ QßiMe©Å8DiûjøG•¡e7¢bSLgUÖšm7À¾@³/|%>Vó¤†FÄ›¢^¥ ‘Ͳ2ìï›nø¸f\1ØnBÐLÄ{ú064…/HV`òƒâm²Áʌޜ2™ö.Ÿbt¥\sˆ(Ó*ƒK96QK Éb¹^Ì1YÙdi
+êÆ®Ôñ„œÔéôÛa;ƒîþ¹¿,ur@ ¹íŠÎµ#©D„çÄdñ Œ‹Ú!› ÂÍ
+é#o‡+äzÍѼ¼yLY º­¥mí™=ƒ3Fjv•žp`óä4):
+EõcŒØP®w ÖŠÎý hk§SnŠÁ[x>ö5pNeò‚šEyæ)<Lù€ÑÅ®edÑ‚3!;KŽE†Ԗ̠)¾øg@€¦aåOæ€þ@÷v>èÎw1õ™tø–e’é`W`hvq®K\êé]â(‹JŠ’Æ
+h¥LÖ6±À›b÷° 5d¾T¼/W!™@&íï"W*Owˆ –ð5ÍH$+jœ[ß*ƒÆÃp(î «õRÉüsPþzBûö¢TµÀ1C·€wÆ =¶';7«Ø½¯"ƒst.i:ëÏ…°„æ¨í˜Ò³òq‚Ìã
+"CöŠ;¤j‡Ö“i)Á.ÊW¢¡Qeﲤv4V¦nÇ@µÊŠ‚
+/˜Šþˆ×8@>¶Ý}ÕT†ºÀÀæ`çP9ÙY.{<û`úø_Û¯©j‹gh&“ì› žªãï«Dܜȶµ‹0Å2  ×Ú èÃßXzj¤ÖŠj”ù ]âœ\bžÎ!Ë€šî×ÐpÜ‘,„`ĪØýUd
+¤Ô­€Y¾SÙñ_$çd2œí:£ù(_6¾‰•‘åb YT{÷íùU‚&ùÕdù¤fˆDÁ¾Gœ4Z4ßmûÚL¢£†ô}—Âp9nÿvFªU䯔ÈFœsÑ’ýpÃÇ£›^„„&Ü”7Î8¬¸áªDuÕS(œ`ÝYw"ø x¢ñÐì|É>¼Š%œ4Ã<A¨\ÃL1•öòHIEYæªC¼#–wý$µœî×h Žî‹J¦ßZ›Úû£XRΉ13U™Ul€ú¬>Hž!A%¤„k¤(kÕ¥¼6ìõA)'e„in5†]”—b´²ž¯¼D.âòdƒ‡à_[“njÌVØHO_Ó 2þ—ñ2GŽä¢è æ´eL`_LŸtu…<ÒÔýõ>¨QW=AcØÌF¹ü¥â«ÐÈü’n‘ÄF\‹W\hô5amq³Í¶JÓE„v¤R€ë«fcoÊcò)ò'®T @Â#WÉveÍ=ü»,$3yè;.Z;º‡ÁÍa¹Aæ¡Á/˜Ü¼ê§¡(2qÉù[Vù6ŠÎh;`Ÿ±Dë5ÕVq*‚!°È‹«©H.Že`òà×e˜_x‡ÚßI.;*?-ˆ”€•7¶Þ~s Å€RðVÆ‘Õõ2£óœ
+×–H„ü()Ç8oÜÚè3Áe¬4`>»‹r­*ü*#µuÍKÌQÒAmYJ½óÑÊ—…Å^â
+*>e5¹÷ öðŽÀP¶˜ù¨hËÖjÕTž ;c’“Äå_ña34/têU…
+! Öå©fxÖ#
+n6_zÈËt"
+â’^ñ§w„f1šhƒ÷ˆ×‰Ì*YJblÍÕ”^a2@4ÅÃI¨”Ô½é7¢›­›™ÐpwÎ5;…×ð>ݨ§yŠT^³û¼¤"vPPg„´yÆM;ƒ}¥À4ËוFŽ!‹š4ùKZ}†Òš¾†êHD F_îµI³²àH;„°ByÕ„<+Õ#ˆ›ÑŠ9KÅ3H¶d ‰S1<h×uŽÕ«y–™Ä25j÷•Š±bH˜¼¾†ÁÅúÕn= “èq&0°w¯j¦.LU¾é²†ŠÂŸr:¦ÓF<$±îB³Ñ¨½‡!ÌëxPïâÖ›€%t cS­S ‘ ÷€ð7׉dðRnpMœç€Û’Ô$Y®ÉãIõDLÏ!äÅßþ²ÕE!´´› ¯CP¡AC‘ÖòâØ8¾j³ÅÝq«2k¿ÕÄ\Û˜3螌y![%¦~9É*xËDu
+¹çm¿±?(+TÉœ›{½wób©$çà´žÏçð <2>fqjN›†Y!¯(Á«|B$ꞯT²‡<Èkbó
+'ç9¡ÊªÌ\@³¤àXW¯(V¦ìƒA´±B8ºqAq˲m%7K„ÜE˜Q»4ËÇZ16Èqr[^²2tf† HLã²Ad>†mvKŽ³yòl5m6òˆŒ¢ Æv®U”¦º‘9¡3€ã¦
+woD….# ÝWÍ7¡DÒCÈÿíí¯™©1w…;ÖRž1_¶t¢
+8!™¹KпdB¹¸_„º”‰p²:¾"^DªÉp´"CgQù°Që߇  c¦‡‚13„¾Ð'8<ïMžÿ9øœíõ1ŸÌ¢°…dÜ»¦åKo¦ŒÂ븬ÜË—Þ¬+²”cè:+7!–
+™B3á”VOç°; ‘(:œnCE„Ì çWQPöJôROÕ{`Z~ê*`”¿,ªô!ÂÉC¢§+Ó=¨‰š LÜÇî.O—÷xÓÎ->jót
+?­ë£S·KuëøîœÛÜìns›¿ý«ns¼«Îc¨%P
+‰BH½®NmNçV‹@Al]ª3$€±¸”R
+ëM^í纖„£àœ‹|‹ö$€„Ï âõ3¤S\ÉÉnC't†µ¡úÓ!=\à‡† ñÇ…Y ˆŒÁ › ¯Cþ¨}ðõZÞ̬£¸’µ›"i£‚ž2#20Sî®u›ØQL+–UbA¼x¹UBenP*~>˜K•°Úx„òLšyßÌ—Ë„+I"–~8†±D#c?†îĸ”¸8›áJÒ;úCB´÷ Jœ® .Ìs´
+(õQ°æ9µ TînØ•¯ ü*bÉv ]<Ø3B«]»p>º öp¶Sà²ùè õR(›$ÆPFö*˜¨­[§2'ú“@q+†KâYp{Un4­”’-ƒËà•-/LBžaxèiµV5 »Žnò Ø4C
+î
+>bg¸A1…#²T\µSh8'„4D'sgŽºft.B2
+ñk!°-Œdcãv¥!C:XX®)èp‘ƒ°v×1@Ðlþ2ï(±@({«3
+V
+7ñ&Œ<ž<™ þ¦*2z‰@öTo(°‰~ùbÔÖÊ•"ìOi [»;‡Ös –úI¥Èí¥™¡,Hà'<äWñBT‡²÷æ~AŽg2­ˆŸ“To4²¬c"N<Fkq3ŽþÁ †qB¼ÍçÇ?ÌiÐ1ÓŠøúíõ‚¹nÞõ®ÿǼ2Áy¥^1¿§”oÍJ…l×á¶?¢1èn{f¦ñ\×þ¦Ñ…™‡›ÍŠ•Œe_ëY1¬ä?aˆ7é£Ê»£Mï.ÅÔLŒ‡ÚùÃlúHM²Fë‹ ø/Ú»†HCaÜÒÜi·3:”6í¶¿Þ6ë÷úÅÆ®Jý1ˆëJŽ¸€ˆßñ=€^‚é‚ âRÝÚÆ’²›5J\L7ô†,ùÃP±™8dBw ±Êü³øôýEOh~ؽh³@'Ê!Ã:¤È)~v-Ã'Á]à+Â/¢|ÌDÃ[)É,PÒÖÔ#Ì/ƒÇdÍb2J­ûƒ0íIž´»Ã.̶ô³@¤n±1ضƒBVÀ’05ð«™û}…eŲ<sÎqtŠÅ‹›s‹DúÔ}&. S» ƒÓ°x”ôSÌÛæ}þd=çÿúWÐÄûðtTÚ:Â? TåÈYƒVN  É&_„ŠöÝÝYŸR^„Ob0Г=b]ª¦<•\þ;H¥•¯Š—“$ç¦-\Ç ÜÑ(>ô$WBE½I,+#
+¨ŒxìÂG@5]Mìk<. 6«„4Kžòjýô>‰úd nøË ï gÏø ]ôµ#'Œs·xÕI-`ÊÙ8ëÛ¡õWdÈ Ö‡œx£·ùÁ(ó¿;»½9ȆPQ¶uA()} ~‚€[¤0}ß3 ‘˜Ëu^F­fˆÊ[‡hrÑ›½¾}
+èÑÔïiV†bQÝ,¯â5\"â÷Üõ7PGýà“& mîÞ9ãg}1ÃnGsÅLŶI„›4 –ja÷Pt,^Xé/-æa*ëêT—c ¼æ±=üD³ÓNšV(' Œü®cª5Ì;ã™I^ó,#1XÅk¹þ¿†ÅáìX;`|bàbVwl»óGò-Üqxæ¹PÂy7ï‰@:(Ù¦í¬6Øš«0kðpíQ£›#ÐYØ mý:xTv$âÖ k´‡aÛà㱿ª‚Œ£Å¾I}úÄœ±p[­qã̫ɆIýÄ{ßóçÇ2Ó‘WQ[pÁ¶t6v! ÞÞË‚‰,:–§DßnÚŽ%$*sáó8½Ì;mTþͶ°˜N}R%^Ë‹ó2ÛCŸ‡üÔ›c%Ìz3ÞΤp 8ÖzXÝN “ß HâÄÇ`&ÚA§ôÃu)ëa¢Ûo@¯ß§Œk¦Øœ¾Æ#(ëáº^¼Ù84ü å]sHË\ &öĵ«H
+¾Ä{KÇtµÂe²r)Ý“|Ç
+CXi– ˜¹ ÉA1+‰ôçíl"ó¯úvŸ¦‘ÍPá+ÅŒÍ Ñ‚òk=M£@Æút±OЄp_œD„ÒÇEND¯Œ50ìE ÚIˆ’ÙŸiA âv=Ì›èD@Œ!¬sø[OF˜njB(†$!Çé&¤3UHNÚ*A—œ…Øå)%Gˆ,PFå+ÍÐüèÄ6å—q
+J;>o@ï½|tTqRø”FöÝÕï,PwY$E¸`Ùâ½QSªQ«ºý'¿ŠŒGm~ͬ=…`É@vƒ ŸâðõѦ%ezXÓڟć£ÒÈZû¶2 B£zi³¡Šeœ<ÓÁœ\½×`5ZèÖÏ爚»| ½g¶š©/¹µ/<‚6ü¢©¤Ÿ}Ë.œRö„½Û›*ÇÚhèžù9.@N°ï>áþEª%Þ rM4’„Ng‰7,VDZ0ŒÃò&
+H‰Œ—AŽ\9DOà;Ô&!RE­Ý˾E³*ß;_TÚ®¯ßcÀ6\•LI$ƒA¢½ëǺøKF×éM¤º}üóMtÚ˦tû4^n6j•¦ªûï·òñWD¾mÓKâ’Ç5~ìVl~üx2±^Ì[1³+¤L­2tT+dÚT^Ux˜~\šj£Ë´á×£æKKkæ³1û壦}ð€¾‚ZÖëpÅ×9œÞ¼”ê^WHïC›i™ÞÇ
+ÑbÒ«©ír]Õ_³Hm³—Òæùœþ2›“"6·|rkƒzw›QÙ+¤Sª¦SZÉרðu’ÒAm¾;iyÕ8šOhÈTjQocô? ’¨FÔgX­sñÈVË”9ì9ˆÄûœµkm+È»’|ü\?>WŒ‘ºËt›5r×ÑèK[ù»[å º±"ÕÑVÜ[;ËÔ¢³ßý’}ï ³"Ò}:gX`€Ë
+ùΨ@œÝÏ#'¾@›ÌðuÕ ªü¢öÖ¤2!'ÀW´BÄ
+ôâª]E½ß7ýûpÅÊšCyuJ=*_ÞósŸÃC(£l ½øõry™V—R[ó¾B𮌋µi+d4px¡ó
+pjƒT׬[P<n™9¥¡Ï"®×!ú*ê¿ÒÓœ ©B³ø_o+BÕœ‚ p½G\)ø‚–è)O§ð:£QÖJæe®´_åSf©
+‰Nêp†ÏúNœ”Í,knÖÉÃ}ì©pSY=
+›j¶Â# ÆÑèôÐõ;‚¯¨*iqûÓ9ü•âɦÇÇÔÌ1§”ZŸrª/4úmVJM0nC¹˜Ò¾Î©Ì*4‹§iBÍù©µ L1±À%ÅULÊSdÍð-èKã?‚cê…ëbwžŒjôbdÈd@
+¯Ž9ÉÔ!$£Š¦ªKäÃÉ
+v‘½;Iáoªl¯ÂØ4=L¾àrF]Gàäè1<y÷*7\ÜÏ pñaLÆ|;'Þ§>!ö@쎦…eV¸/À]ô÷Uáp½õšÕiA¤­ŒÀAŽÌ ç…1ªÛâ
+:^
+Âú8M½‚]¶”ßWýëx^òÈóP#ˆðÜÌ šs„™és°ú¹‚.F ¹‘v‚<q@¦TÏóG~¨ WÇi´®ÌÊ‹TKÀ.~uœ?ÜèÐÒ=]¿z•á„AÝ£u%Þùx ]Cñ5†®Sà³kmY½ò
+7å÷ö¶±ÿ?ˆÛð篠ykºA Å U}=ZàûÊOe¼ÕBvÞÁÚ
+%›OÚÞ¶ ¬…E—®RçK~b‡ÙN—²ÓqÔ˜e+Þ
+äu8Iö
+J•@?ñ¶ŽÁ¹±já™gu识…áŸz"þ =  ®º=c1ŠÔܶ!ïÈ/øîM­­
+ì’fèæV(‘èœØch±n$Û³ÆbÌzxOØå!³‹?œ!Kþ¾êkP0#šmÍ꼎Y0—méáW:ƒÝšù,mPgà:)éGF¬¼ùÊ°[ÁÿS3+$ž >jyœ¯6ûæ#G‘˜zY_ÚÉjŠ•ÉÝ”Ö
+Ötÿˆ;‚[0böXcpä±ø1Ž9x±ȃ‘ÍÚ NyfoÝü5"q#ÁdÌ8O6½—p°Ý³Q×æÓëÉú¼œ®yíiTK@ÑÀôø9uQ^º ÚëÓ(ܬ%³y+úò›EýNö㯸°B(~m´LK ËMá—ËËÖþŒ%î’~ºBB­v€d‡‹–×+ zÔû. šF‘p9+ûʶ‹
+ªÄ™ٷhpcõY8®Áwð(EZ
+|Ïž^Á[ˆdöVC¦xc•…ãCÉ`§Ð8eGø{r*Ûã8}® èŽ<Šž‚®¥ÃT|g¤Ý!ŒÐÎ &@¼x¦?ðJÉJtÁ’™îF^)$ Tuä9 ÄÒ}Ìô²«‡Øs‰ÁÉkvâF¼’6òœ1ØùXNj&…EçA….ÈóàÚ”KéO#LâH2zÐÆÞßÂ<ü¸%vàq êô®O
+¾f¸€a܈&؉Ñ#M,m âžÇNÈ‹‹ÀËI:£ãéXŒ5©˜[*G-—GÉÔÒèàÚ (`‡#KÂ&§èý´4¬ÞM_Ö˜b1P!|Y·-9CšÔ
+ìÖ¥³"Y2–°Ù «'èÎ)™E;g@¦Ã’@¹GzÝó
+Ó“âSøß
+5e¨š¬¢!°ã!¼^SáÔ¯T(ç­ ÅG~]™'Û£%SÁßé”/“ÛÉ"81lþ4Ä ê%«€°´0ßœ)Eäûâj3@ ósnÓε2æ턤µÂ\õ…SÖ;ˆ‘ñEzLûìšdQ'Hq„$”©C¡€:'Ži†Ëí‡D<_ûa÷…0’Ûƒ½<'¯ÎÏ'H¶
+Yoìº 9è§7 d »x‘ùr2j—kc€ö4>÷è™ìÕzÆ,vátÌò‚«J Åc9íö“^ Kʼ@ãi¸Ab9ÕUö¾z² Ô>¼–ÓÂÉѵIJ½H^€WÏcûB°’è_ŽóœØDëhA]]Š"Ñ&$ §mZv²>Eï08úììçˆëµÊŧ«jPø>;¥ë[9Yjv²N¹6šã¡¤åá'‚1áé¸h‰ªaâ$¨äë—Π‚%ˆzÞóf3òDJDŒÔ..…]ÆžQrHö{3lœ—“éýfuˆDƒïJ3ê±>tzoã”mhöR¶á3n´ðÞ˜mðWUö‡ì§…úôØ;RHwwb¹Î/ÇÜÀi°V5ÙýÝY„±}îúx¥&QÆÿzs·ßÞ°}Ü5Ê7,"=mdVþˆ«ÛÆ¡9ýáç7ûéæoÿåGÌ #Ýý¨øöç-Ý~ч ƒŽœG—㘓ˆWâ³=‹ˆëèEAIp|äW¶B¯ãÚ]6:#ð•u¤¸RÙ¯TvP¥§ó„Z?k5ÿô§›£(OÞ©ŒÛ¿S-¸bÇ­qNÛá°zdfg-5Ü¥GYWúaH0-žT;:N½c¾-%ÍreÈ2Æv¼
+åÔÖ<³BÐʼnD6oKùx¡ =Ê|‘îý30ø-É.Ôà±ëÜ7·Ï¸f¢}ó5—`´Zü7×W2å>å»×¯€sêß¿ÒûÍÀtuÿï•ôþöÇßÇОÕwÚÚ?ß Z+Îw)~˜ÈpâWT–Øtób
+j|n€"ÔQBŒ|,úÙÄ
+•°%ž})⯠ý¹ýã?o?üo-È«½úýíëv`ë0â˜gÕ ‹P:Ü îŽ[ỿ\€dƒ
+w¨/J‚`qk©,H%íŠíùç ÉÅc®åWÛ„ÀˆXg”Ÿ']§]Q6X}ÃÌ5ü#N·¯s
+C¡ nQ6Ä»ƒneñÁáB³ˆA™ÆõöøÔá?µ—ã”çZ",Ž
+Á®Æ«çŒÜ ¼«[1`œØj­ÞG»;@0S2•gkðþïû+í˜óco…ì#³]ȽSc¬>µ×Z„ï/Ô°T·'kÄá>4. ¨‡{+·ÇÔñ`s÷ –X±­Õ)í á¤Ö6!ðïÎñË·A´ª¡ˆ¸>ÅkCè•Õiˆ­+ëbCš˜X2µ©Õë”gó²>ð;¾¦ôl#”R*ŒŸâõÙâAˆ½kø(Y]œ »Ç¦râ„Tyw~–x± I!¡²0OÔÇ£$¥¨ÍC’
+[ éè` òØɹ¶xRž‘Dô›¿6ˆÍ”è<[5ûlm·²fTÝÁHfk·g·3 ¨ùb/ oÅñ¡°9ϯ,ç…3õmdtùIŒ‡:ž}Ód¸/A*Áý/Уå—Ì<Õ.6 ¶3$³CzòNÑÅ ÄÛ¢|ÅB™:¤7G-L/›b;S¦ŠA3« ‡ ~®¦kMb¢rA3oÕésÄ¿ ØuÛ›
+D½5bžjL–7’¤©D0ÜS±LÏbzSóœg fTs&SóVgKhtçä+ŸÖKí˜óƒo¥ìc³]É¿Sk¬1>5ØZ†ï/Õ§¹{çðè+  *¨¥¤ÿ‹ *÷JâÁ, xŸÄ,
+c½ô„¸pHN¾6B|ÿg¼Ü‘ãÌ‘ |Ýö < €¹!—îœ@±eîý÷K Ðœîÿˆ¡ˆ’G!++³ ;ØÕ)ÖÛxƒéؼ[©®sE
+:‰ c· §Ë}~§‘zòQ¶U°™Ü~Nˆ‘“ƒ(>ª]4˜ã.Á ¨R“ ÛÉ  s9“qf~ò³Ý‚f¥©lÐÒçÝ2ýÑû(ƒ×íÄJ™ËsCk«J¸¾Šô×ߘ²ÿü÷Ç_ÿóØÓšz±7Ù‰é˜aÓÉ“0¥0¿ˆRÂbD  )5ÎÐÀXÄÔw FìQ-˜*j°©œ¯©?¥'¿ÖV̼.§^’càStàƒëZ¦\ùÊ};#µt>à1¿QÃrüñ‚È·gå‘+âê.S^û¬ºŽœ ^ìõŠùô
+K:̨ÌDDÔ!¢_6O| ¾È¤4{l"îm!àR•*ö±­Ò˜‚›Öȇ]ž ,ÓÃÁ`Z£+䨉ÔrK8™n rjÄ'^×ÊÞêÊP<@ЊkDÓ€¼M)ÑCÑ’^®Ñ7¤&YK#í÷î˜'þ„²ç½7 Êñ¸É6oxZ¬~,ÓÀQ>«pFÛ~eß¿³øç#
+
+‰ç†°4óüL&ë—œt×ëP±å©é¦D·ˆdØG¾ /›T«=]
+ôÝæÄ’:ßK&N:% Í ŒŒ“t¡`LIºK°·z1Ùàjdxê k¬,¼éZŽ9&p%úVUm©ÄcÞPð
+aq¬!.¡ó€Æg§(ºÉ£G¯¸·"0~hŠ¶u ´È4Ô㶵Ž~ÇåæºçÉ~-ˆÈ™³c¿”
+È¿˜ˆÞäГ=ýøqV‹o:sªWYRWÝ ¦¢fL 7ëo®oÌtú©Dwïô%Ôe 朧S®ªŠ¨ ÐãÌ×B_Ñ‚芬ælkþÊ:hx0lQ¹12TºK©BV3–}à'È–€á$xÔó:"‘k­#ùip3ä%*s ”Àã*‚Ò(^×¢xV=¾dÙ A”~bX}Ã4†(Š!9gRcôv4È„\lf y¬›$~,÷B l+{á€p®ù0" ‚'é¶ó"íWýû7 •ØŠïARŸxð´SÔ<
+ÔbM¥ ˜=Ƚlç¾€ü1<Én,–^@—Á?AGŸàÚ·AñAØ5Àå›í¾*S gJ}¬
+h ÊØóù¨u‚EÁº÷`âLYØB¹ÃÄ÷‚“ ä}7œuC¢”|!ù”‹ë]"¼O ã£[£õ‡—›F ‡l±X–8QÜ$h]èUmÒ#H‰ªÀPTùmAš, NkÅ.BxÄØ÷ÌžA8š:Ó„“‹nj†_k£ª{ˆƒ+¡hž¡Ç˜LäËÖ*ôfd0˜÷*cÈ„£ÜægÕ(*s€øVLyŸ¸âÝ:4\¡WÍáé4¸ „ŠæííîN±Å`§+Щ2J9"Â;‡ l˜%õt¹ð+òYø[üÚê´{Áë×·óiÌú€®óæN1 „š\]zOµ™C¹‰%Åou©0—¢ÓxáòÍK=A6)^_üºÎ…7×Ó\ØwºÕ…Å×ê\zQ̪tvyê©ŸÖ3™$¢žÑ[?j ÷kôà
+:ÈÏu»ÐçwÎäªÑ¡pâŠÃR9j½½óqR JwG¿€:}Ýîôù3ùѱ-á飒“`ÂZ†m…„¿o@=F&u™_åÄ KÎÎn9ªR mÛZ, ¢Œµ–q𹈣¡«
+ÖbYN@‡Q†QîÞdÀ Û¥¯uJ×iãî±²óÒP‰õãXœ]ÏnÛ'v¦[bFVP1fÞ¤¬`æó¿Ì¯¦È0wâkh“Ôƒ.H‘þ5Yò ˆIé˜IºË!X¢ÜK,_;Õ,ª¾ðe
+!€Uéá6Ö2ä Ù²Î-÷0D xƒ¼Â— ¡¦#m¥"®o…å+§¢R]n³Ö™¾á…£Š³òž[#€x7ËGiudT0Tž×[½‚Œž ²µc‰ƒŒ>‚5ãwÈ-2’£ZÞ§C©„\Æ‚ ’˜4®€wÜ[ÉcYÛ·â'Ȩ Òýȃz‹FjÇP'`AJ´dÓI”l©Þ­_()­Ö}^A‚ƃ-È@4©‹ùVòÁÔ'e+˜)“Á%&ìð†×ÁÓÌÜ· ‘ˆæêÛN©}¨”{yÊ_?½kÇÒÁ ÏPWËxê8Þ ÌJÂLÃó)x\r‚Ý›“ÜñâœÇ!sÓô¦\ýQešÒâ—|+ús¬¡Õ«796Ù 9ú½¸ôP”¢ÒãæAŸ ¾•83xSFÛÝ:p– ÁÀìQCÓÃ
+£¢Þ²Tuá W™Ÿë¤LâAü;ø|&ÓìeúŽ­Øþ˜í÷øàKü#º^3(ñ&hmµÕ ÁŒÎdx&W¿¦´RZF,vÛá® 
+^ oÆúCíÂSrÿÓn!Aë²dÚŽ°BtdÞ¼ ÝCål§ºú›ZY´B:
+Šµ,{£è ¼šËbEžY/õ‡†ÍütàyŽþøÜ·ŠØZ/ãDSÊ*Âi€^¨nsdÉ¿8¸nÅóŠBl]Á·Åéðö¯YD4IÝ1èO-º7ÈßvCÛÇ7FwÅ•¿þGeUž”'#K´]‰YxE.ûšòYÄ”‘L"¢—pJ_˜†g¶x’øU!·Å¹ìè¦2 ˜t˿חp‡º61ÁŠ ,•j±]#¼”%“ˆ$OÛ‚X¥hqŒ§­ /Í)h_ûv?'
+ÌQôPÇ&FXh<l.¿CI&])HÔ椣Ÿ?ü¢"Ų\tôã¡èž6þ¡¢üÐMµÀ!Û6%b«ZG݈½»Dó”(³–ýëé`†ª·I«òNÈ
+-ü¨n+Š ¥ÈXëhùËt.ÿº•¿)d´b‚×–îS!¢S!ûKÆPƒÀî*d%@Ÿq­~ùð»Bv‚ Ü]·M|WHJH8ü‘”W]e£¤G–ñKãA ëxE §þ5Œû1ƒ”Õ3æÞ]TÉЂM9ÐôŠôŠîä=ddiF'M_xÕ¤¼bä'%DT¥ÌŠ¯Hý5ãåïzªÑ×µ{y<Gås¸w™p¼Gø;{ã@ýÞa§ä”Ç[™ßä±á3r‚¾Ì‰xêxÖÜűA÷Š«Dµùÿ&Ž Á(X7äïI¹8Zµâ¤+GÇÅÒy_Óœ¹Ò(„A<Qü7¦̸¨ØÂ.ÿ.vðÜ_ òð¦ñÒG@;l¼Ã»6R2ÓœStµQ%(`OÛÁޥѩ9”ñ¨9„Q÷eÒ¢ø´%à]õìB_Rf÷61ÝuQíㆉ7¦±ÃÔ›.jü?4 r­ž¦ÝyÈâ†ó\+KŠÙ.ÝWEp9"tîÄs¨bš¤«/‹ìˆT»Uúv7]<×èÅÙÆK! ;v·…=q"èç*"¡BGÜ095¿¼šHx™LëÄnïšÛÇnEß¹‘]<¿2ŸýĈ«Ié•eâK–eÎëâG«IŸ'‹ï×­ Ø #Ç^Q¾ÿPTi±BÚ.:>÷¢
+º$…)cWœ¢7û°JèIqÞ@ª´Á¥6+Á¡'c& Ú‡7L¸âµÁhK4ÌÂ[Ù°“×1UHÏ‚ß6{á
+0¬ûR-x(@Kc¢SÙ)±Oñ:ØÛhñé ?Uš÷¢ ßB»=ê6‰Û…ºãºÈšÜÐâ(i3V‘Ó)|½Ç}œ;`D8}«L÷*2…ï_ÔÒJ~%v‘MÎ!ÿˆ/ñ³ÞºÁKa
+(&‹c˜?Ý¢Šm­$ì]Z0ÅfH OùkzËVIÏÒbYŽ7ø{}ŠwW~ƒ»oégø ÏÉqÇ0ØpKÆMŽ a4² XqÀû ëM[D’VžÎi˜O4šoÙ•‰ªô0zÊ\%T€|¡¤æ @S&Âáèã’ž³(3ãÿ!"IB>~x“9AÑ'‘#_òº2áKb_,²ž€é`*ÛÓy+ª½{:/À©dðýsDA
+·±X«¡ÆWëêÙ&ЈÛ2xH1“ÀŠžÏZ¶›`-æÄCòó5yÝ·*Õ®>ÞJ6èár K+Oç\« „!_» ]Qœ_ ‡$C¬e€­¤dñp Ü2mÐYRòkÝ ? DEûà9üFŒß.º‘ïÇCQ!Bbɹe0††Tx‡ødU€dL‹h±·OA¨OâˆôŽˆGJfõz¨”?c\уÎãàÅäÜÙ¶8MmK]»ÌZbèaè%^ÔÈ"®|¯ØkŠVà¹qûÝ=…-enùZ§0¶8mu¶¤%ëÑ|¸Ä"¤§ÖòþXü˜VÌ3ȲT~á˜Õ@ØyÐîÌ`×0Ø3$»Œv…cø¯• ÆŸ•œ´€?קØü(¢Ë«H~&*LpÏ5K.­†3ã¾#Âði6;!²›}+ÿ(bÊŠS6‚¨T fõ;g‰u¸˜š}ûUç9„±LS; ±JðCœàj
+Þ«ŸÂ]ŦéÉ—c¥b
+œ4Ùw.$:Ñ)Ñ«•$N¡¦å»d`Ô<æý¥Ô5ÛïÐ×p~‰~ˆ—­9d~…£~Ãß?Âøç·Ù©×¥Øñ¥“K¾ 8ˆÚmâAõÁœ$Ì Æ²c\¸ºÝ ÆÉM-Z²¶_vVíðÙ€ÆkÉ÷óå D„¥O÷K A¼‚®iËý=¯É p{È'í&GÙœVjÞ2sìCH7ŵ„ˆÎõW (/U)¢šû§µY™b°÷ëC8>ÞƒkåæAp"²NZç È™OíS*¸Á¹Nä?¹ôK›#K˜ïÏü^¢&ò\D_רĖì¸ßõd^†ñÇ1Ø6]lLëAâ¸÷
+Ûóÿ*¼Jj5ÒB+Ø ìAóJìK¸ä¢2´×s<ÁedJ¡HL¬ñ³3ÍÎ"Z n?h¿Rø¦¤OÞ¢9£³>|´ûáXôë•«Å
+ÐÙŒ¢ÄžÝ¬Ké®0—ÚÛŽ±Ï¬K‘#ÞH"íf]J½€.ww³®Jø®•Ÿ½Ìô¨9“®Þ$;Ìux–Ÿt©É ÃüYÊz&]*$™´"—´OùLº”„ŒÉƨ˜—¤›Ç¡šœ±ÕøHº”ðJò›4Š›t½’#ézEŸIW¶©ßd7éê¾UÙÊKÐU Öñä]µ<ã8꬯Øûg']J¹T@ù“¥'骈ЇèГ­ÇùSà!Go©7éªD*¡Å:_’®vbJ†‰Ò_¾„ÿ‘1gÝ!S=’”ÇódÛÝeN+ NÔ)èЊȳ«›t)©?çËJ½$]Š
+·çþ\(¹I—}"vd³½àŸY×+9ÒîYtä]ݦh5ø{ŒnÞ¥¤q|í䤗¼+¬ƒ«^سšÝ¼+òrù·Ø¼œºÈ„)v gi/y×!¥#î5NÚujáH±CLÈôln؃Ã
+ùŽ°+WÌJ%ˆâ†]½®Æ.”;‚>RªX”máJc/iWH‡0rlT;çAGÚ×ânha¬½¤Ýƒ»Ž°+PŒ.LLò™v½’#ì
+¤V¢eÜqî»^ÑsžØ°«F
+(Ê¥y6Æ^®Ô3.—˜Ý°+¶(D'~TV|:®÷ô#ìj8ÏT3”èfÝ‹Ûäu”S>3êÓ˜8IW8fpHÁ+ZŒ8e
+ûö]Ϥ~D-/ÌÅgÒ ?È*±©e·ø‘tƒˆ+PÔô“®Sr&Ý£ÈKºA°¿Ý¶ì‘uµzhL ¥ûI7€­JŒ"Ä´-GÒõŠžä_åw%ÝÜØt(DÔ·°ŽôVÑî½¥x¹µŽ9¼h™Až4Y‹"
+FË/KõIs6¢Äªy춱'G#Øo¹zžÊ»Òeáû6Œ€ÍLk•0øÒC­eó¤Jxmiªé‘UÙÜ…ihLL¡¯cºÜ“¢KڦᡋNɇ=ùi«›d,ÝM·§‡qŠ°SþѲÁQU? Ã^Îñ¶,vuõo”û˜ž5’$sÉŠ {œ`œÝˆHæضc$j‚lÃûÀâ¶Ïyšgž§‰Qè¥ñŠd³¾Šà<Ô6COKuð„gÍ Í¤%5¤ä[<p,D@CŒ5PãÝÌâ­š MëɽÏ"Q$ÑNoµst(n3fT!¦ÅT ¹Y n—Ð'(F¨?‹Î+Ëý*x*ËÚ†jü½³hlöÜ»G;aV2™ñ׉p$—²aŠ(Èu¤LŽ`ÛfHÀÕ°4±9”d—¬”ÛæÁ=“ ÄôìÂÛÒ†ï*ás²S#c´/ëÆOà‹{ñ¿82Ìöã2˜6ýë+=´…-¼#nÀà7è¥n8*ØECøí&“£F¬•1‰ð­­T+à—ÁÔb%Ø
+€˜¦Ut|îQôëOîô÷ºzÄåðf:‡s¨å륾Ÿâj!믫„±Ö¨•
+[MHhèàÅJ å‚ÅŠËÄÔ˘%ÔÝŒknªS’á’;˜ÊàQÃ0ËXçà_ñâعa¦
+KFtIr—³ ?˜¨A§³þÆËG’‰¢'¨;¤ÜB€‹q9bªs‚FkYbßÞ'QHwÞªò—“´å/2œÃVÚð  a„¨vðïˆâ³œ÷®ï`Äå.áÓ.ÒÁ¢2z˶&¢Qé‚Mõ¯p üsë%åçùÛá‘Q‘ÇÑ(Ùú ³ªÑ'æ´í ýäg£ä™V! æ'Qᎈ2û¨XRb·U|b™Á3 l¿¾aÀÜ gùwR%«x„°Ý´/1XKG@(<lG$kŸ ¾ µ†…v™æfv>-10ÈGŸå„q4D’ã~”eY'”pŸÄ!è(”»ë…q¥²ç_Ã"—ç¤Sý
+˜lAxŒj†+­iE®’S²ÞýéÖ˜
+ò#â~ú3‘¼aÄxÀ|Ÿ1˜ü 'F?Š_Då^ãë„KËÝw“*)
+èù…±s@ÌVß'Cñ{tÏëÇ´Ö!vR\X+ÎbòNx¸žÃë¡›? >8p
+:D„4MóÍCbq)t8;c§¢'Cn^¾1dSD]cS§07AÛ3vã¾#{Ó"Ç´Óøç­Uu€£Z󃪆Q)3ß;|6—Å7%‡ ü§‘rÇsí¤Zž…AlQù[K¾S<˜–À0îÚy`©Tªl¸!HHQ“Ïäìƒn˜«÷ç.–yp‡°]$Q!6Í!UßÄ%eGàÄ°àIžL"J½ ¾Åµžÿ%H6H_Ll‹›øü)¿Ò¥"}Ça®púðJ] K€îßàçYÇs÷@¾rÉй¢2awV=WA¤SØÚø£—«Òy<OV˜›¡@D#\¡¦Êvq˜§&D™€”Szøo?×AÐRSñaýèÛ×-ÈKꟾCM_[ÞÉN°=þ³+ ¶à1~A˜-> …®)cææá(l¡:ü±çºÑg–¾çrή·V^ ›„§„õ‹ï03h3¶ÅÝüK¬á‹#æÀJŽá™;˳aïçfÓX€£â«5¸ùKt†‹êxyùáS—§ë¹à7 bk¿þû÷È—¸ÍT1!JÎÛã3ÄýÌy@x&aL´›iQ,–¡QK6n™HDoÖÇMú-¹a9°ìOLÈ<ª?ø5"Åнú ¨æì|›3Båò,¹Ÿß$‰Yp_–Ï•™£àJ’'/<!S%• ö}!NxK@Ï£® ”çP£,µ|œos y§7ÝÂâ©6—Ðyªð%ºž:õâCqëøý;·¹¹Þæ0}÷W¦øZû*$â§% •>#~,ÔŸµK„A„9Åx›¿÷ì°¼ä²|Â|0—dûu<ìú~çF_ëâÀúãŸkÞ1àÀñ¡J¯ëâõjB4hrInø¥L1¨,³LÒâì±
+ÄlAæ("¸@÷
+üÀ|¿Q%Õò¯ÿý
+ÿùç×_ÿþR4%ÇŒ†7B8æŸ@ Ydùz¯ÌºÞAƒ 5¬á Ð¥u½Öe·žPÛ» ¥Ƙ ‡õUÛqï”ȘHÜ=,]g9î jV¢x"š6CÆaÈ!Ķ /+ŠV5‡ ú<c¦9d0<È<ùt9^†~·Ð
+:íßÜ´€\Á´¢@$*ÍlÔ`Î ·j ÁÝdœK­å
+t»”!KFu“S üZ™t;Ù3,!‚º¥çIJL ¾½-að"aÔ‡ˆtIó¹b,¾>•¡Nˆ/KÔ7% ÄØjkO+fk‰¹î¶©Eó! h!9„p…Kg;â‚ÌI¤±ÍعOoO³Šé
+6¦t/2”`ØÖ©w/2ûÍ"òƒrÞ°C;ï›Zðe5ȳäúò;©ÞÈmo|UΉ1¡º#æ¼ù¾gÕ%È["Þó(ôœË2q†;¸É 5ðÕˆaY/…N^ £2:Á€ˆñùëŒ 0pGQ o ð(t|¤NkªŸÕ)DL“ìÄñ΄±uan­7f¶® 00’¸D
+Ä·ú®1a% p.‹:ÿãËÔ¼¾S”mlNŠïzâpžÅíÔÎ+Ä'‡šóPIÊ‹ïhi+¤XhÕoƒÑC™Ñ}He™Û’ü¼ƺžÆî£pÓ)+†.vˆæ‘½öa¿¬L€›É´<³óý¼¬^x´ˆ>Só¨âûyYâ È÷§h²V}i 0¢•k×Ä(0WëLíðë$#*„Àýœ»MÊ!QŒCËýåQõ“õݶ'ü{×”îõüÉ’ˆ@Ñw!/ËÇv^!>9U)±ÊãÕw”¢dwãpQŠ©‰(ÚïC
+ß`0ÐùèVÑ€«(Ï>ŠhÉɽÞ#¶À.=jÒªÕâ·!HRˆ‰Åß\‘ 3|îV¿¡à…GòÍjç Ä[©ð hqµó
+ÂÆ„²æã
+®»\àáí|¦Ka
+"¦\ÿHO…h‹Í=ÿx €CFãqÂù¡k/s³lª…'³Až!‰:d67 ©‚mÌ-rõ‚<þ½kTŽunMi‡aæÏÊJ Eg¬‹&ªçŸ!ÎÈ—&w2Ni]'ìGEšx—ñoøîþC‚pÉpœä
+¦›ü{9o§¡l$³fì*ïÂϵŸIýÞk‰5þ{WïëÜ°¡Ãp/ä“ ÙËëÓ´xœ.H šæYˆb±¤^ðκÖeX1jn –Cæbž­þ=\ŸÒÓ—ÃèVP²‰3‡^´Ïû0Hb¯URPxIr³k@¯Ñ²]R•]ÑmYïÍU2e(@#5îéh¨Ô…» §ˆëi#ÅĸלsÒšŸp[ã–¾a¶›S²vêo
+Šµ ói&¡ãQKÙˆsBØb¼6³•€Ž3mÄâb—J‹Tþ÷/¿è+-¾»54e'Š
+âÃö"á"æR(“9Ìy‰¹ïœ¢;M$ Éà€»bu“桨¯‹g,ÿä–hŸ/ïýMà™8fCŠ
+aÏ0㹸o|)±n~oÕ}™[¿ï‡¹áÆ»Ô ··¹øþÀοöéïOæSãZÅÒƒ™úì,÷áÖ@È)è‚Ú–òR2!±!t®†2ó[SÌš÷Á#× ò½õب¯¤zNN96Ÿ
+EÁxÞ¸tôKd+ÓíÀI0d¼‘-C¬Áö¥Æ]|«áPåݲ\aᬸ NÆÑ>.B>™;â%H'¦E¾¢˲&©,fÄöÅàO¯f}"NxÖ8ö<HZ «ò1…C(1mbnƒÇ¤wœˆf¦œþ9K#Q_¼|ÀpÕᄸ«ü¦±Nx–&±Ý H˜é>Þ³¼HçL|÷½%J´MÆÓôå7¹ã4.ª¿N!C¡v™€<DzK˜)zŽGÉNà\3q+òÌc-C‰R+?.‚ž£Ì+iÒ~D§è[Ð[%èw‘éˆc3xe cˆKÄÙ³ŽcÄì ù^V “)`”h"‰r¥Ö‹˜ôÄ£<d× iBhV­N‰m¥ ¹—§ehSÍtÁFß3ì8ÆV®ô&ó¹8£œã2~vÙ¯¿A"ðà‡*/BÂ`ƒ.ƒÁ3qm)t±’
+cª³ÚÐÃ}BÂH`Sì9 0` ÆÿåߟFT ÂK#«7 hˆi>ø J ƒÑÄó
+§e&Ç©®ÒŽy€b4°%z;ñàÌoœJZimQ=¸Å|´ÇS€šõa#M0td6§ë¯^â/îWRüVâÓÓ¥èÏCÝÇç3rÓ,‚Sƒ_Ñ[ÒFLÅGœºé`žÊŠXÁYŒu!™Àx"ÓSùͪÄ9^àš¤Ö ÔŽ£îp¾‹ù0r’ùÅÆÔa‚í,ëE7™ö)ugŒ¢SbÑXü®i<­s! ¥þÏãƘx¨9æ£G¸pþX,‡17F`AÓ|VD;ÎLÝJnA@–ÎҙЊSôþPtiçíºhT¾ÄÔÚ
+8¹‰õ8}|Ä‹ˆ‡Ýš¬nîÙ·ðW›âFåX­‹ƒ*^^Øâ O‹mÝJ8ûˆcÝwIžpÇI”[È4ÏNÌáT˜éÇ0 A«D€ŒšØÓ&Ä•¹
+ekù­
+³ÃÇ1à–2ñv8"iñk9 ¡‹E*FØ‘/s1gYADŒ§ï@ŽÙ¾
+H‰Œ—Av[;DWð÷à ´8Îf9§GÎþ§}ñH*É•v&väI
+7=€¾Ÿ@ÔÌ
+làäûéº;èó+oºžþñoBÛCºk½>o3ÊR½d†µùúL¹Ò%¥×^ÆU> Ò¡œ…V™h–ä±ÆÅR¦µ¡áU`öàÇäR} Ï(Î <‚kRµ_´­·1„Üê„Ú.Ø„)é’Öd]¥¤¬I㪷çH‘ZÀ­×hòÞˆ²ÈI–ò¥nÑÔVÜš=5²ó/Ú¾€`R šMŠBèY³ú(£9MBÆfÉÞ5#=b+r sƒ µ-)oå¨6žÉ1+TY®Î{…¬ÈÂ¥DôwçÜê
+؃l„=uMùNnR’zŠÕÓHí²ó.<#ÌÛqóþû¢;Ȳ­ùçÌù\V¼\|Æ8èá Za ][Fú´7è´ñìMÇÍ©m¹ëayqGˆ{Ö °ÛUÔiÛâ|1ÚDÍŸ•Äh#=)ZÈY›n ïo@Œ
+f–‹8?ß`Ø:Q³ —žRúŠC«±ö
+ú5÷6ñԽ²£ÑWPw½:xòAÕ'‹Õ¹•`l¿R &Ó¬’Ô2òx´F „JXnö”™ÀÖ£¡È*D\žr5{wÎM0ò1æð[m¾¤ çM—±*¬¸‘QÏ~‡¿¤éOý"9®9±¬Ð K­ã&G_Õ ±U*¼êà«xvV«ÞI✰Áˆs9€>߀îµ|azò'Å.8’Õ»¥ÒC9ewfr{ð”&õ
+[RȯI³lŒ°–ý­±®ªY^FhB½†#Þºøkàwß´.ºÖ/¶Zmù¯´˜c³ÕRKMtvhwrtzÐ3¸µV³ó9(‡„ЖxÍýâÒƒ|¦•Y&O™)F¦ÖUiKÙä¡ûª¨È5ŽÈêÉã^ì
+7¥¯ÜnP#-Í(ÍÆ
+šŒ¦˜O¸aô²ƒØ0KÛ€>ÑâèêØë¨AbÌqMk<!t]ƒë¾'¯Àq#Ö1#çdø‘îD·\3äÒ3;ˆ|m¯ ß'ëçWÆï/{
+å!VäuŸüy‚dç7΢$åÚÜZ0Š)#ÂêaT‚&/ü­Ö Á&0¨#‹»ÊÁôcåÉ¥kŽi@hE§+1DKà„ŽÈÑ]§ BqaØ _ýGûbs;VdØ„4¶–Êt£ȺJ 'ûçò^¯Ç8œ·äoöäzqá) vVÛ C,ÇÑ‚ uù<ܬ´©</ țϻڲÈT.C±3…ü\£šn¤qØ1lEž¦ÁÀ”ŸZFž€ºçw^!+r
+—£Ž´ŸlÜ©š›Î”kÒ¼Öbv2Šs@Èû¾êÆ‹«›HkºÞø8ÒéRÜ[d=#rF6ÄŒV’íPþFâïO_
+yÅØ0­¥|ÊÏ7 ÃŽåj>ªa³`XŸëè嬘~˜ÎÜ:&„öWö]‰Ü5 Žcr?›&.¬¬O(NòAݸ>< ºnG7 ÄòˆAÓ~2œ«òöÛã|dhtJ^ê‚àk$Û“ÖÅ÷à l!*í
+’Û× °G®|(+lØš©%ïÁ\ˆÌs¬§‘åÿ±WLEãRjâ=SÆ8ß­ü亪ãùœ .½T?ŸÓQpDl¤¹]‚‰-öÔ:¼ÄB@Sí4Ɔä[aÒÏ'ßþ9ƒ~WÄÏ#Hw›Pxª1ïª\Ë ¨±çq5¢•‰À bùé ]{ËUL,Tn.ϸkˋо8uƒ¾š»ÏxzøÛÂñšâÃâòZªÓ9·‚Ÿ^s#Î)ª;ÿ^róÂá×hþ{~|¥_~o !)ý²q8îçƒcÂ.,ì¹Ù€° ½¬{ÇéäUF
+k¡äRŠºßÝÔÓ%Ê–¹»¢ÚÅöHŸQÛY ïU?**+)¡çS r´–R8J?¿¥3íÈ3êîïbê ·Êz#èÌVTXò?ÆËä8–[‰¢ÈZÀÀ<¬©¥¼Ð–Ïÿí?È,‘Õ(~*BÁÇf6€œî0 Œˆ]%‹
+€sÜTÐ+xã†]ÅNãxqÕÛÄU‰_…^¾Â/AßÚþù„èŽHI„d4DÁ,DéÆ ™‚œ'[øêi¡4 ռħ4!=õ<)˜¤õ´ ¦ËS‡|í>p[íœEÆ'_ÅÊ},ŽçÀ`9°£±ùcš´/V6û„–…¥ù’E¼¬#)fÊ“žþ“šŽÃxÒ4jo¶/#¦ÒØþîj›µùi¦·óÚI&!C´1ůúq7A*ª„L® ¦Oá7p²ÎÂ!ЛB[IŒ
+Yöà­>Z°C€ÀÈ@bõÂCp
+I°uY¯Î XS݆y>'#MV¶3Täw¤ À¯õ²#`Wö…ìçvµ¯1'A˜Ü TþÜ$0À­=QôhAMQMûø)èÛ›$±fFÜÞxǽ€$7ÀKÍäA4õ ìåaùOÛ­qD°Ý
+ +s.öê äh)ò‹3=žCQ …)w<-rlu”¾á€`5AZÒ1ŒÒhK¿êç)ü¢æ¤–h~’ï;x¯?LjšòJðxÕ(­®1ŒL„k“"W&F}‡°à]õŸÑBX@Ñ1ŸV£¨Z«$RÁþpìÊ„»û…ÈÄ"›‚©±‰ 6ÆfðÕºC$»ynJãbW¡iPÓs˜˜;[K›ÅŨ֡ÕЫ¿&ˆ†x]viDgÙ&¹·ã%Hi&Ρ{ÝüËË]”tJ‹ ,­Èz1`ˆˆ7õIâS%…,Ým¾ªXáaÄj|:æÖ…5
+;éF¿éÇ)þ"± "^?Њ“ÑùóJ Ý8s™ûYd› ¨ÒÊÈ0µ ªÛÞ,½S ~cå.ÛÒ‡bÑÑóªŒRø(ÿ‡œ( ð†Û§U
+±Æ£‡ÓDΡžÎIb¸
++‡óÄ“Õ€*Š€öÃÀçwyMÚŽÏrªá8ú—1Gœ—ø*Eã8~ŠÉLEeÕ€dlFbÔkÊ®¶9ˆBà‡%/ô®‰ñìíŒá´"U^”ÑIó‰ ÔRÀe2¨`me—T ÓÕ7n…OXOó%‚ƒ+óÃÞ¿é6§|€Ø0±¾¦ªS; ‹úCÈòµØ m½_õójm‰”䤣‘~ÃQ2”jÚXx
+êsDXŽŽU¥OÎd 5~ÔÒ&9?v‹ñFI5 ÁZJÈsPÙIAh,¶˜†˜ NwÕ¶ÏAžsTnÔ{‡ÀãüàzH!ý̓«Ùœn¯e׋K°
+„*µ3Óþdz§Rkz÷1¹Kà‚àÙŽÁÆQFšV:"W©=šß°[T†Ðõ›"N†ž%Û‹ƒö‘ëbMû˜€ö‚ƒZwÊf‰™éí-ß“ñ'É&Š“é‘…ª[kd,Ì(<‡ïN[-,ˆÅŽÐû·Âû¡±V‹M:‡ÃaGJ|Á
+0aŒæºê”2óáuÖÛžÌ Ñ°#Ù¢z0NeÜ­Ä *}qÓÊ2'u
+!•½~RPZœ^Üp*sdoºú@Ó´ŽÔ/—˜L›Ü­ªXÀpA‰,{<Oâqo;EÙ)ùk„y…™]|DH£Ÿèàݳ'0….ûM´1>h.y*Ť©‹ÆWKÝ&O¦ËVâN½Ð{PÂx¹ûí¦œç®¯1Ÿ1âAÜÌúÐVœKàqöÙÁ Ž¨°V´/”"ƒƒÖo Ì#šÛUá*õ‚^in¦ä¶PÒs–†\Uè^ “Ú²‰ÇNÞClh
+&\¿Eô·í$:«R;äèQhªK±‹t¡ïò Xµ,h x
+¤4èP¶}¿îwAôŽwáQ¦àó$gá~eSÞv@†oó2 8ú^F"†.Æ‹¤ò4”õ²^Šv¶qÞ4B8ÏQì)i,s/ûI
+âZLÉ—ª%Ž¶dfð|sÚ9èwîa,úð¡`"ØgiðcÈmB?þ:f½¼#íÐ; _õ¸5÷ ãþݯû]Ð Ž«u2|),\_š…±LÀ ìÊœo|9QzŒÛB¾MŽ­ÚÑŸ¨Â"³ ˆŒSeê""gq =²æGåìÎfQ-BcÌj)´bÖØìsëÃÄŒ­êB!°ª³Rv2V R‡»JÌ7¥hŸÏ¡W:°½õé5µ£;Ëò&ÏY ÷<8`>§ê[L&ÿ[…á²]Bï!$,ЧNñ›îA<š¦û9ßs#žSRHÓQ±8ȶڮ¤nÅ‘~ÕºƒmØ9·£ê߀ãEŒÌc«n!vÕ­å§snƒszÍm
+zÀï×݃>ó¦…o+”CÀ¤0¦a5&ŒÝ˜Ð÷µì炨.Õ«û6>„0E½aË8X¬‚$­ÐÖ(—`ü*þÝWAr­¸ÀƒPoºh÷9$Ë@ ÌS;«à€³LRÒ™MzRÓñ­fÙ¾ó9RË(»LôÇrÙ"øWAnËÂìúñV¼]*êÇÇ_ç €á ”jÙ={‰ ï4œë ^Ãî
+YËÚ綟ª{)Jܸ@J˜ZÒ»G¬nØ£+ïÐI%¸Ø˜ŽÅE2Q+S7Qð„aØcÐ QRžM*ÇßB¬›·Vι5üôšÛàœ²zÀ—â¼Lñk…ƒþµQÿþfc´\a-» pÉ=¢¹}ÿsŒ¡°AH‰»¥lo+X@Û¥<µÚ p•w›†¿”¯›Vè€r!AÌW¿^
+DýçTȃ]¶²Õ•}2`,†Á‹ „
+U%whü=Äg ¾H$QR:Ÿ£²äêl_¼Ú÷×D˜ßƒ„cÊ*"QQEƒô{²ê°BÔ@AÙUCæzªì+„žóG`bäXaÞMAÇÿ1^&ÉqÜ@=ï 00'°¦—¾…·äý·~HT°»P–áÔ!ñ§œ[¥Ì*HØæñ­èåé¿ŠHYJ2•F—ÐoF‡È’®„¼]…¡'×þçO¢vß"WdaÉbÜ™„íÉ
+†TJ¹‡Ÿ=1j›=‡»õô*7pÒœR°· ¾#ùYøŽ‘b·ôPñ2 î^‹0úL&ïðAâ{_{ŽË¨%±yÑ[&ÄÐbóœTÐÒÉ&³›gJ7Îe/jØwQ‘ÚMuD1³„sNÒ;ñÖD0’P{ÈI¨¬&«çuk\
+ÄŽ$ÉóG 2>LjÛ휊¶Ç‰xÄx*™ª¤ž(5E ÏëT´
+1ƲJøÞ¸'óÕè^ÂKÞÆÈáÂÎÕ£ŒIë~þu*‚¢¤6ªäÛÉ`…ptþã","fåO"Lðlq(zI“³Cƒü‘”è“?F–\ôàÛ*é3e3v\qSðÇ׈)nYño(de»#s
+RùôŠ­?K|«éh¢rOëd 7Äú¯¤Ãü@@&PôU«ØÖm‡z65ãIí²P¨«³í²©UÔ òô‘×:üÚ…Èœä T")züZ€×¶HQM;*2y"P³[ÑéÕ3ø!ÂEhþ§Eï$üú¦Îõ×ß*Åî5LTyªsáÀ¼åðãû¡g?ŒC¶,•î;ø[í`Þ³¤@¦º·Ž“ƒ>D©×›0•ÊŠ)ó¶'ôVC&µq­BLlÜbg£»¶FÍ A^pñ®Ñi¦aZi¶·z_'}Tù;Þ2Ò6§Á:èk ”¨Ïó¼yUcVQŸ?ÿ:•Ñ ÆÄrÚûu¨¸Ï–ñŠ"9^TYA>ÅUò{sŒÍtž1µ¬@½¯ÌüÅì„Ct' ,ac 7µ²Ö‰²õ‚¥”xÎö·îžf„Û+Öy}êûaÞsºÓ w·ÖÜÀ{ïïß?éß?!Š8§Ø hLÑ<vXîûXƒ£0›+t8L $ôKEðå¾2Â]ŸX˜b]¨êÉm÷ÉÁN"l[Mg·éIˆg“|õ£Ù0Úž4+X;¯”y_œ„i0ŸCø¤qž°Öüt©ô¡Na¿y×$IÄT¹0+¬7~Ó†£çK™ÇŠº”ð%Ù)»ÙĹ}¨îÖî[ÑËÃ=1òEÞeÀJW“1e—;ˆà±Õˆ=»šÑŒ"Ø·µãËy£^ÆoÎ?VA¢¹pA´ÂF$Þèë$="ܺú}ž8hä}.yƒÅqƇ07¿†¤À ÅG8×Æ(=ÁwàñìшâlÝÖN`½ýÜñ}?1 CÏ`U™~1¦*@‰âƒ({„1ÇpÆ܈wŸUÃÎVØ ÊùUÃMñ!$¾h:ú¥ÈþýP4“#žÖcŽëHQ€ÒðúÂ;~¦ˆÈ~æ XHNÈ5Ð0WÆ}h°"8§_¤ ƒµ²÷'s‘fĽŽ2‡iš’H°Epä¯J´E€XŸÔñ´ŽiˆC
+KËÇÓ¨$N¸vy¸EEp
+G£€Æ~mõ^”¸b‚–eoNÓ¹À“@èxáè§álÈõmeÒC1Äæ½ð™3vÛP':¥ëH-] íœä„‰%VŸ¡Ð×ÕL=ÚÓ2z(N/wÙ‡)eâuG:Ž‡ÇÜBIÅ<9 _úNëÈ?¤·‘ö¼ÁTÉ‹rW7-:Ç¥QÞæïÍÛ¦FÊúä\¢i ù
+ú¿·y-™º¨Üлs@?`ëõÑJ@¸ïä÷ÁåÁœ„{–Lf—.k ?
+6®!¢µ©qÉ%8ÈÆÉ¡£å­E0‡ãò#[%Sè8‘}+ZÁÄñWu?ÒŒ—K®œ¹ …W=Üq.$ê= ÜCO³‚FÏÜÃì?ß©²]¥Š rÍÒ/‘‡ç‰çŒûo%6áD! LWk±LRílÀó°´U[]\íüÅLÒ-ýÅDkSL,Ó¶%t͘“ÅNåÜc™*^•SœÃ¿ ô"‹vî˜g›Ê^„ÁÇ—~.2Ù¤ŠË”ó%†q±7=JH@n%ýÁßÄ}ñ!˜²H;HÝ{DcNó« UÍ0i0OL]•LIîA×D¤9IÌ’ ð.X 4¯<—kÏë94y7Ëi¦(é"ÿ.ˆ‡ªhõÑûVG¤E'ʉE`ºßU¥6fK*‹´ˆ£ $ÈÏA€‹š:s4X©‚MÒi-×ܱ,9]À÷%d…˜`U«õRô-ŠÕ†£…t/T¸(ëÙ:»›èy)eÜG)M8(J°ÆâË™£9™±Aø6Ô—&›è‹þ@#½[rð[ w·7óü©$ ÃŠL1µå·ç ùeV·aã06­œÅƒgè<\8Ì ­‹L¸Âzl8¾£.;t_‡wIÿŠºI
+èÞÁkÍ-~èc¸ÖÒ$Ùëÿýt#Š¶zÊé™/Wײku»Í8‰Å÷ó³rfQùN’’&»;2f!s”ãV³àdÒkškëçõ@ïÙóø
+šŽ
+…;y}ü©Òú™¹ïG ŽùѤlÀ¢ŸbJ»íŠb÷Ò±hî òŠ…/8r  a˜‘Ö+Í(‰Æ™”ã' ÏÈv ñc b& “¥GzHüÑs?¦†•‘ð³«Ì+Ž×úÉÝ`þ÷XÅk¾¾©ù)ï|‹"8rØ‚LÏr`à~ «±Tk
+ÞóˆcÀF5°—HÁ•UÚÃÜò–¼æp® ž".4ZÌ“îu9œ]›`˜Î»Aýjà"²t°at•ÝQù¢¹ ¹.öѼ©w̃ÀÊ4Ô€$/á-ñ
+Üë 6Jj*<†©'„n^ðp•Å—€
+¡ÛùÃÎ:¬³å?Õ]³ì½ÖlÓ¼ÁÖ €j0lK<Å.Ž*’貊wÏ…qbsˆs8ô¾˜+Á§I8wl/„1w/ôþÊ€¿bÒpàd.žüy>áÖ8V6©À&\:OOé æþÎüÀ@¥Cý]‘zÒ; ÆAo=Þ3õšß%
+Pd‰›[/ŠX¾‘Ø„¾Ï©Ið…<A¾@µK˜KOM
+ÇÖq-áfbqQù¥¦£8GïÌçåOEô V;Q›1Ђƒ2qñð ™[^Û(‘;SÑr¡§gÛN©¨¯ótûDbIM^>ŽÐ‘Ö˜U2Y® 㱟ý<LJDÛècžXÅóîŸPQd=YÁI×cà]^Ni²yÑTPdÓä,ýM`'Q”[ýS³¯A'rJ1o˜à[ew¼„ÆÒ•Jošµ6à,Í|;ºì!–*ËÖ‘€
+eü§ùš¿q~iò/‚Ážµ¼ÁTÝ’A"ü¤ýì^ÁÂ[ËÕƒ,Q 64M¼&(÷N7J y(ƒ¡`ªú9ÚgºÜ‡ ïüœ4KßÁý7/ T‰R^—’ø”ÒDȧÊýuOY-¯vnÃÂ\ä‡mû)Á_W@ £5 G^0΄Ò~(å©ÄeÚœ‡»›×1V^ˆŽ“;?\ö@
+Ò¼„72s•0O7†ž˜Þ¼•ÄÓ±³¨X ßÃ
+ËŸkÜ¥q¹ñH;iœ…‡€ÿ°ýsÎ!sÀ4Ë£Çr°8LXãáU1Žƒ߇cKÙ«
++A:Šx`Dñ§Ü1
+gÉÌÀD–ýS¿ò×Gþ¢´Î5Á}\xîŸ7E‚ i
+ÉmèñÔüE2T/%1°Q˜ ~?§ïMÆôÕÐ-nS•½¤zö"+ȉÛÁM¨<œõy€Þ€
+žÜ[|ª/I«»w¡¨ãQaSt½üv2ɤ«v>ëóRDǬ³Œò
+O°e °<òýìOzã6ʧ:‚Ž&%›¤Ùå%†¥™ òy#V°ðb,0Zq 
+k“[ÃBA¼¼¯G“:ÄîóÇU½¤F³
+£H;Ñ¡øR4>·©Þá°.wFü‰eSÛýZô-ÚcéR‹ú¥h·¯þ€«sD)HÒÍ^2tL76íÝ`íSŽŽõ§(€FWð+ÊKNt”Ð, ¦Í€ÙΚt1eA—F•åZˆwß?õ\„(T™1´ Ä9ä:ãQd–˜^ˆÀ³d‚½D <dë™'4d%’ñ)œSyÎÁÙN û–f4‡Ïâ‰Ð©|Gà¯üå»÷)~+c«ƒ_±Ø:ȯ~0¿}Mã þB
+.C‘7`F3Š°W§—ðTÚ•±³Ÿ$7TzøkØdJ¼ôÛæû–,ó»/eB—Éͯ|§)†´ °* ¼¡;ƒQºòŽ6MXh"ûâm¤9ÿ£¼L’+Éq z‚ºC@ÆyXk›·è­tÿm?'ÁŸR¢RYf¹¨oÉ
+ƒÐöÄZº%¤?<»Ü5Î=ñ´VÇ §èÃ-ºóuž¼h íÉÉ><…,^Å3žÞPA²ÖiœO'@V­PM'±Å‰¥E!Z²— Ç mK6ü€¦A}ó,ø­;™ÌU¬Š»;Wõ(aÂ)õƘCŠˆ­n”!ë+ü¼vs(^î¤âPÈzV¯h+r¦uˆã”Lؼ-V2ÿÊ>BšeiÁü,ç*™F
+AÝ ñ¸¸¸dÍ
+ÐÃ%’;‚B$‘=ÏLç&À+ÃÁùí_o—÷¾»ãò€Æ{†’¸/–ÝÈ è_ 1Ú—ÓT~b¯ ýÀñ0FsJìÓ‰‘°˜žÓ?'¼Íئ1Í¢%ô(Å21i—h¼yàó‚œ[ðNU̶®
+P¦ˆ@gý›Ó –¾â>Æ
+]’·Ùyˆµªb+Þ¯>”ÜCÒ­ÈÃ{y#KYÿ¦è¾ƒÎu?(ºð‚¿^—¢Å1+ 4´wù¿“¼¾úÃO·ˆX…µI)©I&½É€a9Û…Ç®BÕ€ø·]åU™±’³óÿÛ75ZZŒÐ1ö%‰ò2à”ȳI“æðvq•€É 8ò“]…Yä¼°ø[ß°Óô_ñç5_Ü*! 42^¡?
+MqøÄß:kñ¹G†‚¨E±¿;š–N@ENbk„:Ú _íÅ/|`0Ç>Å",T(:¤Œ<›¦m°5IÒæ4”‘\¼ëY0An@@IæÂ/áÎA:
+ð²ý¬šÂrá\¦üºK²ñ6áè6Ʀ@¼ÅÐ%ƒ"‹jàb+ø—OìäÔwÿТ‰{žNÑÅ‘øÌñ³¢Ž…#Ìtq)Bñx+èÓ¡©AêÂ4•cÂù"K—c²‰ІI¨î³ckH®3ÎñL;†
+ø1Í]‚M²ÑÁdÛ¦¤­ÂĦ.ÿ]2|ç4à §åo«Ã¿ÆA@‹B'-³ìX>±R¥=÷VÔ·!«ZÝo]:Ÿ5N§èÃúÖiù”ÿ¾QÞP$’WösN¯/®jq—pQ Q‚“ÌQ(9☣y¥
+'GiKÇu
+¾ZÅE2ÄZžHšqL"@(¥?ua¡Ó‚n¼t1–]’y Râ<z€Um2ÚÐU>Wôø¢ÉìçùtÚÀË“îs˜·hMGà 7Ø
+*o3¥ªdçé÷wp5â>óSd"ëmi“¥RX4h²Ý†¿à²ð/ÏWTEe
+Vfžjci;ˆϱty·Ï 柡ÅiCr!°<ôÆ25ó'«¾0ãÀä¦ÄÙ=:‰?$e§NJ›}äÍ|ÜH• 3<×Ò5eIëCé8„^ÄO(M:×¹A×zò7^1ÉÁ*“™;aö‡q¢3¥Í¡ïÂ@WœwNû;æ-~ú,4CDvŸº*ÂHX%$s t=æ¡|Ô+ä|Ð߸‚%š¿†TèvHaÚ+z„ºK9ù-›WLÄŽªÈNšèFò—™½u¤bç¨ÆeHܸýòúðváÜf9S¦ûp" 묘ÿT2Gí]ä6ü nT7©€S̪±§3•èÜ©ñé;XRÅ&zc·‘p2ñ½òR2Y1\ „
+¡ä'¥œ}MFskÒ X}f6"˜­9Øi3¶§W_¹šÖåêäÚ“n7î,³p¼þ6þ ›Îq?
+Š'îAêJzQ~>Æpv×þåƒ83i‰Ê|z7ÍYHµäî± $†ŒV®NLêC©Ÿïêð*šÜ’6Nè 2G‘=ê<=c@¤^¨t2m‚NŠm+CÇÇpZMPnμ«ìäÕ»[÷w®žß·¹fÇ{Õ5ƒwuœq¯±ùÖ«ß?¡6Ã*¡YAnÖ“a¾}îaÉËzmf¡ûµüŽÐ…ͳ¨TI Ã’²Õ(6’cçã'û~\çÞ,l¨e®'B“OYð$¼ÓºÁqX¦¶X7$z¿Â¦fŒÑwNô©3§Åüìߦ³áŽ*<èáQãƒ3
+<žæßÔ†j¶Þ4Bc˽ˆÅÈŲS
+&ípäHÄ^F–HÔƒ¿çA¿†^ÏÖY™c¼e20qCHt¬~”¬gÖË©R`·ÚŒ¸@×&³.]v8@‹êAû
+ÚPeŸ  ¡£m¹Ô¶+4²•{­¤JžÊ¸ ‘°  ÐYq“\‡…Ì‚1t|#œ2w/\¡ñcDù†1Ô˜›±Õ¤dй¡AP¥Ü
+¡·6bGå,*iòâÓw¸ÌŠÀñåÅ“4‰¼e˜±!Q4c´²I ^!9™ñ¥“L`⥭*Oû’±™ µT:c>KújZ²xĆ jß#F\¬¤MËÖ“wŒ×ïÌäëòXöSÐû>BQcrü‚¦®AÉOL”ô¼çôÀäøÁ-ILÇ‘ã
+éI«Ÿ€é‰7xAz"rZm-õèÊý¢ªXì|ƒ`[ê ÅHí‰ÇÈëFBgãÃ2xlà ÇèÇ@°üζšˆ½ó8±ANNïQžè39aǃÄ\™£è3™VTv m”Ó£éjèÕa"ñˆÊÍdºŽiIsCÊOßimè•|ò™WÏÇRÕôDåøð—s '½S™IƯ¹/²2}*ÉT®Ò—/×ô /e¥SùÇ Ìcéwבˆ©´XŽ] KͪË"4 œ‰l£e´ …€D5Ù,O(½!:4)Í áfš
+apâ¢aìê-rŒ)[ÌÓ
+Û™|N‰lƒ]í<¼k•A×ëØŸ‘BáG'†3쨬ÖÌH)pÏÜèuô@ú=
+þ†¬,ñÚe¾. BŸËü˜Ã÷$Éú‹š©Ôe>¶ß"D,„‡v&½±—²/Ó×C‘T› èJ<bC
+äIœ¾þý
+Q2jæw¼@4†U„©ÅØöÏâ>´‚–šG¶>‚Ê@ÿ÷a‹}IQμQu¤aMŽ$â05'Ç ô¢HÇùÿ¹Î új±Ÿ?ñá½sM&Z©J7S9Ö.è‡jYýó
+gbe£€h¯ù™ÔÃ ÍÑ@R
+é±b„
+ž-r˦Ý0EÍq…Ý}¸P§ÇãFj'u¤I3ñ v; ]>®7ýË-ò¼åy&Ñ™8ù2Cm…=Ø»”ñ'mÍ(‚ìÏÎ˼nÁ–0n׸U AÒïÜdH«yXèþy¬ëØ
+ÑXÊ=õt I¬Æ™a? Sç“D‰¥‡?Ÿ×1õ[/˜s›F£Ö’@w ÈÉáx=‹”™íài„4tý )iáá#É#’‡Â‘-‘ÎVÛîPfóÝrß‘2«K,%È~JO2l;Ã)lurY±öŒ£}ZG'ë¬=]:)å4n¸'.m­Cb¥½BqÍ­T;g¡Nf4²HјÇ÷êlÆíbaά#[®¬Uã»™þPcfB£èUŠj?¾•raŽKS=®Ãíæ‘rÍ)/H—;Pó¶=B–hL‹YÑÞ]«>‚´$Þ]2f¦É­äITÐ9ñèô‘Äà =wD‹+¥÷}ª8=ƒ÷ˆö56ê¢ß«6@{ܲöâ¨KLKMBí7BréNã¬Û3b‰ÉÀD¬Ò16ú³£UP/ËxŽUŽƒ·&€£ù@¶D–ÒtÝ:jíYÏ«uÓ!¨¶"Yr¼=F<&µ;õ :ö’„A DˆÊðRã{Ç_·ÞúV»2ày¾°Œôñ$[µÕ=iùlëH•bÑvÖé|#êpRjg8“I %…XcÒ°“–­>€˜ š0 ^-!êá4¬bD˜'wsÕ§[} ™-
+éjËÄîטôLÌ5 †Àè!ù)ý-ñ€ù:×Þž|&Ý¢G¶½éÅëéñ‰®Ó!²1½Iý©[ÉDø}Ë·ºëÕ0É_$íÊVË4[ê…– ÙÊÊ?ÜÂÌíÏëD…J÷h™°Á©ìašòì4!§Êšœ/ïrLQ_©Ži*QÍО­=.ÑÄš`‰Äã!Kü>Y
+4 Çå%ÍÚQÛ€`ùG®ÛhQ Ó*ã*ñýTŸ>M×::wÚA”‡­‹~Žêp9ÉmÛÚ¾vžµ³Ž›]Û-°:{»ÍfŸÎ+öí› fK¶Òe×qÎéTP+o ª³uÎÐddæ{¶d¯ZK= ³uz}pìZί­³§Yç²Ì‹ÖjP]a›³™=Áóš!uã#®Œõ{—^fâøÚ<|ÑÇg²àµé=fm@$4ÔZïÑ‹%HÂ=Z»wÒ\- L4#ŒpøØæmæ\1†-ý>!žu¬NpÌKKÁ%9¥L:YÓúÜ¥uîÖ)K§Ž¶Ÿ´ÆBÕ䇵ܭ“{ùàv•Œ²mwëDà‰‹~³í¾amö^S^ç\z¿­Ã+vPrL[X¡ Ò“Ö¦W®?tÓ ÜÞÖ dÓŽ<&lëìÒy<òù95í$°´8‡º·"+ëÅx½Ê@B]%(Xø(·@$̪~VQk3%Òñín¥¡M„¯Þj ¹sy'¸Ïå![]¹{\Ê~L.mµÇº½MA—5 þ8·kÐö"õèkÞª†ívÿJ»iÛ7ò,ë9ųy—d«c«c•=µkÔ·ÌkãÄ­tEºR“\hîhÒŒâ‘66Äç-‹QiÝ–ëGÌTEEù‹l'³Ó<JQ¼xV¾¹Ý‡q1”ßãÆ&Ï;•Y`ÚA'ëûhÖX–®Cf¬po¹g3ÊÛµvz¡–b^HºMõÕÒÌ’?ψ›nÔ.ɯµã+«Ä*\|Çþ¾J®hQ<Qžˆ-7Ú®¼=ßÝÞ•Š<örñÚ³2Láæá""“C}á¿Œ—Kr$7 D¯¢LÿäZ^ö-fkßë—P’ºÙ/vÈh²$òƒ·ì-f-»É*sÖXöRÛq}ü¥—5oèÂæÉ úX`¦¸PÈm»T$w‡£ò1ôÔ°Åær¨
+ˆêXn¨x°¤‚‰•åÛ€Ýbˆ–aèë%£ÁUw‰ò•œ£² Z»Ç„mä‡ý…Eû%xá0lœZò|pQ+mR8ôK%F~e#纭àËýãdÎ[XÁé„ ucj¤Âtô”¯_5á±2¢P{´’ Äᙓ<#y
+âºS“¢¢n%4;×Â_P3ÇG»0
+%ß!$PDŽ$î’G:†„—T`eiD¸o,Ó˜Rœyùèùi#“wí¦ñKŒi=oò¢íçe†³±Ù‰~Ô|»W J¶’•”´s Û)G ï€þW-ÂQòQñ!ì
+„:—ƒÃ’Zm¸ÃÅGÌmÓëôW%±6RÚ±|úUÀ¹u¸$9Ai5 È8yÖ(J'œ|ä_y
+ ÊG3œ1ø,ŸšÊ|5—»‚ Ʋ³·ð
+
+y‰Ë†øT9–o)ÒUP3¶‡`gz›Ìì`ËŠŠ²GvôÁö"3jòOíP³+Äë$"8ÔK
+ÊXÒàˆ²ˆì1§Œî¯âã~‰®¾ÅBëóK$) £Ä¨hDÈÊÿH¬ÏjBP!/†9I©Gl÷TÖuÕ-BXAÛ`mùá³ç7%?"íç›ïA1È€‰¸!ÖÊ.¦ôÂ(øº_ý2Œ÷0з;÷~#;ß³ðOLJš™ÒèTGÎç$:FT‘%ß‚`ÒZ¦]"úkHým­Á_†;jî“OÐƱ3žNÛƒ
+Hèd°³Ú‡êãFú×UaðçìË>„&#šaÇtÙ7x˜ûr)R\;«d+AYÇ ”y ·À—ུýû‰UŠø–§`1[ó]ÇÂá!ÖX¾ÇÚNÀ™Nt&iÚ0Ò¡$(ŒǪ˚ŠVĆ"ˆ¬Ôr=Éo²™%í&ºóŒäU!µ¼Iµèé"è\í“ÏŠ=YŠw'W+Ÿ72Ëœ®ùîŽÀINæ%jñ~Äð…Bòßr¿Âovt캯*ÀˆXnkøXr%›Ã»üZ!$¹y‚”Ù2$ÈkÞÆh°ÂþêŽ'«>ÝÒÖ%¦§¢¿½ˆø 8bξ†œ[ÕõþnŒ¾|G—2t1r†Øý“a÷Ä`pXëfT¢ÒÚ„cÖuœ“C°‹…€¶|òdªOÚwòÝ B©
+H‰Œ—Mrc7 „O;èQ‘ ëÉrn1UY9÷ßæÃ#¨ÄöS*3^Ø*ˆÄO£»ùø]{{úœ½¯&¡ßø]ža}Y+Öx|úùÛŸ„™ó©ÑFŒ ¬ù“Me™v·Ç_Ϧ¡Ë;±=ƒÖ3ÄÜmØ´¹WÈh">½­¥;Ä[‡Î1#vˆšÙðæb³BºúRm}qù¯}Õ²>VwéÍo‚®èÝc(Yžs8Ò¨l´ÈlV{f2±„z|WÕHÌ]— “ë*‚ºD§i"Uº(ùgwÙçt®¦]½Ï!±thÓéêŽ÷.$lk‡¨ô9ZÚ3ÎMÒøc„qð2Îè"áCúã>d­n¦Ö‚Zß\å¢ÎImÊãÇî_&ܧx¿ûV4:Ñ9ÃÞ-æ9e3­ëÖ¾ÂhN̤mRqÕeÑG'ŸXvñ&f¸†™0‘¦{ &JBô½[µy„0 ™rfþ9ã ‘B'ÔÂv¤‰ˆÃo‚6’Aʺç¦A8 晃ȅ0 7Tu™jæÃeí.çpÀ “.()üçš3¨ž>¾ërnhšìš¾EÂE;ýJÉž¤¸¢ñEZvFÑgcýhÜ7AÿgÛ‹ôi­Ï\ÓØIMª ˆRÖ&}²”F«s©o‚®÷©.ÞÇëœ 4ÃWÛûCH8Û’­ªŸn¨[²æjσu‘¬ë£Šµè6?uO~ƒ=i ¶B¤GÎ}€¬aKàY½ÕòÐ2e¿ÍuÝ}TP.Ú¸öe={¬
+ÃÌ
+õh§é<ì™7Û)ì½®R¡Öº\&^ds…4¨<aâ/ öª1[BžùäwØ]uD¥kæìd®J+‚ŸOº þZòóÒ>â‚;\¼Ï¡/‹ C‡ÔÀ!ŒFß'¯þ†Îûª¢Z¦Ûdr½œ›Œkøa³tOÓ¯Ôìâû¼šÝFë|ÜÜDÄÅï €±P«ÇÁ¹b;ˆš6$¢R<HMpŠØôÚ= f%iQW9“cúh] ýl e[ÍdO!W}ÎBOשS(ÜÙò3ÍIvB;ö9ëRLxaÂÂܼb;d\?¤M5ð JºrGÀ†ã 4oñœ{;²Bu| ÔZ†‹9ax;É€f@Ì0Ö ¦à¢SS‹p9•Å¹ha.
+íà›t‘bÓhêBý8ÒYú¡ÿy Rht.õÀÔ ÿç¦é¥§ÅûHôLÖ{9õÚz )Ö’'’(aMRzü¡ú±õ Š!9ò`C½è"™Œ­a‚[ΈY©±ììEYS7l"r•ÎጓýœípÁš]
+¬¤¤Ì:ð'ó» ľÆe¿î)— ¥O–ö>S±±´ºJg=8É¢c§Ë4+×|–TSú¢ ¸5°_µŸ v¶ñôæ‹ûgœP¦ÐÃæzR ÿ@7UÝ=56rðVhëX2"iFqŠ¢âŠ¹1YGiFRKö”Ž†¤šÃO>ß÷á Žó} cC¦¶¦WHB€Ž¿ÚÄåpÁ|íºã—DÕê]´ŸJÏTç CÈ.`®”™4¦9ËX§*kh
+Ë'Eþ´3’þsriæ`(®‚Ø2<{ÏÄr².à0JŽÒ-ZDÉ ¦-¥:^b„:¤ zŽùnin} †[ +væÞN’ ¾xå2–'ÍoD8¥0
+©ƒ\*/û
+Âuï× ÊÃŒB¾8öoòðݱ'•®K1;'›|ÑòÂá‰=át—7¯‚xåæƒÇá¾Yž4<ö1Ü€MdÃÚ1 ”y c†€ú‹ñ;O«y‚ÒEÈ’£÷ï1%‹ÊÉT
+m—)èàOèŽA.|^¬FaA‰ù&<+“Œ#iñdÝ¿:‰Y‰êô­~Þ·¨4Ï
+a:š*ö¸.££8„î²ÙíG3
+íèfò H.kÆS¤QAZY[’=m?´[Ý‘”û=R)Ç ·1g±²oÀ†ŒüÐëyŠ}çß:ÎUÀ<r]ç(¿™¬ƒæ
+Ä#û^¡i¬ñL5ªýJãÒOȧS¾Â§®âÀ”J˃÷@Á)È)—ÐdU¸û´©÷¨øOl%
+ÛF!è@tÙZ$qVÆ$,Æ ýb²òAçýPwö(€~£ÚÈ.ÑhVìP.ÖŸiq,æùMÈ'•øñ&L|…lüÁX®6VoÊ!…©€ÞY—é‚}ÐkóF'6~Pd+eï¤$gß\ü÷ç(â’vŒ¯£6×{!½Bx‰€Š¯Ò©‚µ ˜öU¼×؇ċÍS:ý¾¼îs²*¬ Ë=ÏÃk¨FÔ
+Iÿ !Ž£Ù¾‹ ±h¯«ðQH-B{ÜO ÒeÈ}UÊ3Ù _fµšÏ <̶'Rø; %Ž;*„kòч¾¨Ÿ~+AÉ!°
+ªZ³ÊgCz«#¹:L…ñâƒpK¸¿ )ì°Ç‹Û€Üº úYA”ŠÆ}cÝ JjI¢kç€Í] (E«¬â‹Ÿ/N8O:P!ž§ß„ü:|‰ê¤ïµõîãiÆA~ëî³…‰ÀÖñÄ|óJHVÀÒ!ŒÐþëõÃ|Óeýµø‰…yzjäva&ýMy™$Wrä@ô*uZÌÃZ[Þ¢¶äý·züªŸi¢º­ej̘
+
+fV NRTÿ«©Aéq_”jüŸ›±]£òòÄ\Ʋ*• S#gºO#¨Ý ¦ñPÑõÍ‚¬ÓKØN Ñi¹5TGÞŸabáz0fºöño$ºÎ_?x¬?\”Hª
+§T>ñ…:ûW¤œ>í ¤Y酻ߟÌcÕör¯SÉÊdŒø¿ŸSçDB@ëâÌL`J Ñ^³~ÙÏÄ(“bX¥5v %ΚKÉî5_Vƒ%G™Ë´!yɪýøæ ô,‚côS|(ѹhÐùO[¼)Õðœ} «¯´\NIÍf&ÁÌSá]!\ɲŽ9l¬ø&­;AðO2ÁDš¬ˆwJeJ •R¢®È-í‘Q‘
+Aû&°jWÌõ¡/ò¿”vI”ÊòL.‘o
+´3ÈF©>³y&ÙCÉeK]Q6"µE%$™rFÙÿz­¿P–78Ã1µ'”åM¢(­ó̲l£½22Ë‘e3ȉIO¿–¥HFΨ²‡3ËRÂcÑêbªS
+\Y˜¿àÎ$«ùeÀÉd%ö'’ [ I =õ3ɆÕ7â%ï(K‡a³“ðjy@Ù°Fj’Ú<£lÀVÀb•Î(K§#n½€“Ó¿rCÙˆ‘C¨(ä9àŠ²Q-ÉóŒ²W8¢,AG '±8ÕÜP–¹Šœ¤’g”e-IFjãe9Ԕμ¾Òe¹ÂOOSÍtfY~ágÁw9êÜa³lFAvnš™qøÖ¾wQ Hƒ $—¢£¨K!¬é²Pñ]ä–kØEd7¤“váZòSQåë˜7Àm?-W )<*w9Ž·åe„$*ïh9‚–ø–Q¢p+B`QQ5Z.J‚6‘#XõùãîW€ðÖB5Í{‘Ô–Ó§ói±±r­‚ãCÑ×O^îs?0-'ïŒÀ8å½ï]”ÀZ‚ë“D{Iuh=Í5%4ßäbî#‰9ìÖ¬„Aïš·\ô[¬'ﱦyɺIÈÉfŽáXpB´•`tm‘Ëž¤êTQ—°2›ôµÒµ3ˆ
+ä}¥ëf:›XNô÷p¦ŽýB<rí¾ÔínÞžâ|ü$Þ$¨Žé×ù¥ÞJl©€ýó?6éE¿×%þ»„¡/IáÒ§•m€ ¼C_†0ÏÌ+Ï7 ?›úŒ] HQ±ëóë‹ÜI ñþÉ…)Ž| IŽò\Þ¹„U˜7E‡òZéZ£mx*³â+]7óæçC½9†ßßõr®z¸â‹­üçPmqM +=ˆ&Ò2<f¬Y }üÇñcô`yI¹ÔÐsrK ÂcÒ‡H. '6ýQ–0V”\@ÿñÊy‡"®:Å™Ú0Ód-ä‘ÝôXDH™V%–Æ¥Q*â‡øšèôÂÕn±‰¬SI$ñ—³ÝÍwUA®)Æ{Åï½æ×ÃW2Pš§lß×Í
+‚°Ä]RDÜYœëm˜q²^JëU÷wˆ|PUõä…_¾’¬R9N©NUÄ&ˆèkJá&È É¶Ÿ JúAíý+ƒ糸Ì>9DÝ—15‡Ž·šU¸pT¤Úïo$i\gÓ®€PqøµÃÛB•ëŒMJmE|”aã†Û2
+Ò%#mÙ‘OpÑmk²NbÂ"ζïº*Ü vM°"5=€"¡°~®Ànä>׃MÔ2ï¢_J'‹b]:„¸UÁ„³6Ô¶ßb®Ü907°i7YUÀåHÀ¶3dï€/õÂðꥡµWGõª€™N-Vb7uó´Ð =#ÚêB37-À©‡6µ,\@ìxóæûeúˆ³ÕY53“]êœúAwƒêU´¾KïÉ4’òk)äÎq±úK,Ç„¾'NMK
+
+V")¡ÇlÏÄHíÄCÉïÝ6U"È÷[RQ.fŸã[Ot‘
+lÑ>E¢4¶ðw•ù6×ç¡U¹¾!µß+udjceZÙ.‡´É¸ùýê~Í'¦4ì©
+ß…AøËì%ô§ ì˜5m¬ìm48—¾9}y²St÷Îç 4i—geŸ Ve|ØPiçýpt4Ë‘Æú.Á©¤ ÿR^.Érå6ÝŠV  ~ÇíaïBSiÿSŸ$Ûªz,¹áA»„ÇK‰üXƒ
+£É<KN¡¡]UPv¬ˆ†¥Ð™¹÷¨ÀÎhcN ìJ G×q)ñO©?Â;Zñé`\,á×K|Š¸1 Eì¯&­iô"{ ¦úúPH T”dÿÎvÞâ Èô¸H´–ìÛô’ú* ¯ÅîµJÏó„ ê³QŠ®ù–OÇÄ•5‹_ N«Žf-ßÂF¼ª/ñ*–Þ'±òœÃ£h…c§jaE¥)h ‘ Ye}=°£weÜ/?:6éZÒ;‹ð–`j'[)#’EöÉ·­«)†žÔJ̤!~\¦{ÑN•d=Îò/ÉÕ½½F¶Ð’H²Å¬ï ks­OrÝ•«ºþ|„Oa7Ð"^æWÆ
+¶p®w£1p͸ ·wb¶.róVpG­5“9lI@©­ˆrù»,bR6™þ)Q¶¥À:›
+S ¶Î¨Ÿ³^¢£ÃpaàåJksP«Gô•PѼH'o‡@³?ŸÙ0-dU4s/y‘ˆ¿>ÜGèE[ }ŠcÁê°@ô¨Qp•:ýcÄT:q/8ð©0#¥~•¦!û§qþýœŒŸ¥ˆÅX󉲤0$¿uJºäÞ 7Oܾ‚¤@´Áªa(B¯Q`Oå=§`aÐ ™™`1J\ ÎÕvJ´Y'ÓXét$•ýçS†%åQx´Hiˆ¬ZEhñ 7,|#ŒX-Vf¢O3_š‡úpö<«—²mFû^‘J—Y¼õlÍ…Tæñ€ºöÞ0ni:ìµÁ—|)qˤ×ëõ{Ñß^Ä6²Onªn®Ý6­à/`ñðÛ
+{µÀÜYZŽI7“ü#¨Ð6v`~<E®<§•ï¾ž"5eÒ Ñ?åUl•——9Q
+(eí躛M÷ï Ê\|öIcdw)j Là¼JXkÂY‘ñ-ÿ¢…2КÇÁ›¼)¥û}&’ñÎÝ.ç¢$}ø§¶(GîÕ½ƒPÏ@¥fh:,²BìÜ<%2H­\³£u OÄB0ǧØjhÃÓãéP*ô‰L?‡F´ª¸©ˆí Œ´ß¦÷!k€y*¡¢ú{Ø„ŸbEûàÙ«èh€Åöí@äjá§ûèJ^0úãS¥ŠLéæ{~±)%)vˆùѧ>¾Ý'ÿfÂ(‘ë|JŒ•”I4Åç[”)Œ@[$É}¹äÄ’ €ý^é<h6xçëc~,Ì•¼4£åÜ*ÓZVÔÀ´ ¥?ës¯‘2$ÁÓ÷'+Ã抢Ï÷‹ëÐ6v¨ƒ–Ð!ùfùÎLD£$ŸâF⋬Œh–³±O²"I­Ðf”â*+”Lµƒ€5³?kqê"yŠÈa&Œ £ª,G<
+¹À1±Õ¥2óô0$dÃ=Vôœ£øÂËtíÌÑåÍ3¿ß½KXeú÷xšÄMW4âS…Å`—ñ5q ¶kŽÉâ2`Ùc ½b/ªÉŠ(]CÁ¤Ä‚‘WÒˆŸ'a’Ô´‡ÙePøBàˆÖ4öÛ<]x›ÐØI¤·´[è¸ÎÁM+ˆ"/ŒXî½Ñ2´R±·:"h->£<„톔{o©úÿy9ÿúG–ï%‰C B~7¿NÍæ#O\]B–m†çè×!\ü;ôDL›õ”°f:@-îÕ€ì±Õ,ÜYcô´Â ²HgùÄÖ è%Í7«ò«ý?Eš{V”Ÿ§„ñ\kÏÁˆK nç¬D@íåª~kr' =ا‚’Z8PoŸ‚Ïé{“yÑ \t·†&UÐßÊ|ûßÃúžå‰€KÅý=3
+ÀåÅb1ÝËó T@™hã7Ckô”.Sr {=´¯øH'–°á"⺿Wø‡4¹ÛRÂ9ï~2L8Ñ9,3^\—Ed²CÃc6.<ñªF†Ã
+M0¤9®’,ã1Äœ.aÈô–Àp\圡Éɳ€öã×iýî’÷E±¡ïwwsC) ?­©Ä<üŽÝ‡îåÁá¸Gú¶8°3ëáí[Ó„PÝ|(²­ ¦Ô‹¨ð XÌGZò#´¼K˜C”çwþ%`Là†½`UgŠ‘¤ŽVAJí<æfÝiÚæ8¿Ž‡| ë?}‘Œå£|„@Yb½BÞ¡á„u4ôü²6M„<ž®ñZ®17,_ȇ5þù—]ß”´&¸6@7Rƒ8#ÉùåÅÔÀ®pY¹¬ü‡/¶x
+„Ú.ÁÈ2¿¢t&=ñ[v›µ!mßÐi3¤ÕV³£¢a’+ªuyaCÈu†s$x^„ŒÙ­¢ÌmB•˜q£„±ø¥pJVEr´LĪP^ÂyBHËNP‚ã …CîdMu¢2˜¹R…*s<)u jî°YC–]Ò*?î|ÒSÿóåc­ чE0hq߷˯*y$×AžáɬP‘$æúay$&Ú
+~}
+% ØëÆÜkµMÊ{îOɄ›³™ÄÝc« œb9ϸôÿl©á»ÒX–öl)‘7$·9FÑ5ÒM—Uî«Àb†4²ïîquyÁœþ!„(±ü4Ð[ƒíà?д¦@(ÃáÈ;Oï^)DHí%Aô
+Oº§Aˆ% 4Õ Ð –…8ýì"¶W<œÓ>‰‹ÐÜ?¯YXíoÖ·ûˆ7YN@°KÐ)BÒ B:^„@aq€¨Ø8»Ön
+è±î7ÿÄ0é={‘[no>,Z{ àqMâ~¸6\Xu«Æ§mQYÎUÂ<qN ”ºU'Váº\Ÿæ)ïoËp±,º Óî’¬°@†™—A/¬Yð@¹–õ@rÓÅÛƒ7f1eñ¥"a ™Ä&zο‚¯¾Ù%þ¤-Á—$åœãÈú2—5Î]$‰ o¢):rì]Ä£iŠ$þ«­¡ä·a¥6oéT+YD±ðñ´4"u¢rëš9 NëÀù»qhŽç¬ý©Š,°²h÷–ü
+#îÐ`I¤ˆ™4¶çò¦Õ ¡£\&…°
+þ Š°Ó¥éxÈ«ºl%½â¦ø²% JX˜K«D¼Ì Xéy(ÙŸ"q.àY¬~:-ˬ<K3Þn àZLFT—+CJ.ÞÑؽ9vûàtv¡nç¿Â¬Ÿèlz àÁz†:“òOÝ‹èCP¾~cÁ×€AY%ZÛ€Û›ÚªÓ£úq^E”ªWÿ>›cù¼#Ê\ýëÔânŽË@{ð§QÝJp˜,t»‹:Æ¥±®­ìsøTD¾»„u¡ ô¦8D¥áèGõÛðf\pf/pË¿êÄA¼\Ëþt˳È0ø*ÁEibÝ^3ÒÅ´FÕ×?lÕµ|r0¡@3¹‘P:~¿»–'!†MçSѯ}R7Ù2ýHi6 ˜sꊱ>k~þåB¿Ö½‹²-X²!CšÕ !£O!M%øÈ©—\Ç)¤©À_‘"<7ÝCPædþÊï%žCšŠš‚ÿƒ“SHS‰Â^aÚb–{HS ¾!Ê·ÌvNiVƒ¢3#N7h¦4Ud¦Å‹ª¾|HiV‚.Bå8”~NiV4M¬ tÇ”f—‰ [â~ò3¤Yc°ø,`öÝ3šu¸Ëo¢Ç«Œ¦I±X°Ãí;e4•dÖŠñ&ôÒT„‡š °;…4• ÜdQ/Æ8Å4û<´aÎ1ME
+¼]Ç‚ÂNÇTd%Xz
+Šó9¥éÆ&YPÓ짢/ÂSaW §”f%lN©ÈçûÐ?gÅcÆ=¥­å4 ºçSJ³åJ$ÂìÙé#^Ù<ÙT^ÙãÓlƒÕʽÓ'6VxŠi*(ìL`æ9¦ ¥3ͬIÄ6ßÖáä{N³7ãm¦‡Ï{N³"ø¨D5O9ÍJ .£×Ÿrš½
+‘˜ìÐ<ç4›²ÚVîóœÓÖJð.Eµ|Ši¶€˜ÖCÈýÓžKsˆiú®“½áÒÅ3ÄGL³Ë@´è~÷”ñ™Ò ¤äÎtÚ9¥'ihÈõ”Ò–<TNfÆ-ŸRš¢gy#žSÚS)͈T8*’'¿ÍGJS /Œtüù«n)MEöJå˜ì!áÏ”¦
+\k’ÏE!Í*¬ÝGÒ!ÍÄŒ wøkíÔ#£YIÖ‘¢®q
+iKáÖB{ü¶Ÿ!ÍzGA2剎!M5 “GHM?Bš­Ka¼|:›jÞã•Mr H“dôÒŒJŠLÏx<È ³x<aàÒž¼vi†N<jNì`ö1}„4Û\¢’N!í¯NjûD,håRi¢gH‹æÇ‹þ·`yi” ¤ZÞâLÕ)(ÃŽ™Î©(ZÆ óXµvÎV‘_øa
+•§·?…3P¦DÓ^Ï™ÑReÒ¿Ü‚šRˆýåQ ª³TZºZó™Ñ()" !{Å-¢©BŠ
+¨K{‹h‡¢{D£$"—|ˆ•8G´Ç›NíÑ›gD{tøÑ“:E4&>ð8DÂâ9¢Q±)¿Î¹E´(º™¾î~›gDбָàÔ½;·ˆF Í‹’CÏC÷ˆö·ºV/cOÍ;Ž·„Æo}–¬òÐ8k‚:„öÐ…LÛ@VB~ h¹ÎÊgÿEuz¥”ñ°“mº¸¥Ù­)BË°
+ÛDSMT@ýÍDS!71¥Ë¯ËbñXà°JP;-L´ß9¢ÎŒ5J14°1i>^²‚ÂÜEVB,L£ðÑFÂc@O‹™(Áþa°ØÈèA%ôNôƒ[òOI€JFJ¶éŠ©òb–«^%èuÂ`
+·Ûœˆ`Õ¶õ¼Kè'O~šˆYç†$)ÿæÔ±¹¹¸M:hÍÀš}KºŒSÅŒùò%(ÓÁA8ISrjQŒ¦÷|1:¡³éNy+šjrNÌqÓ*OÝŸW RÀœhÉ<äΟ—"Ò*„DRéFCN–=–q-ž VE²)oì|^ù„AV@Ùº9Æ9v™å/;Ì`+(×¾Jè)È
+A‚Cì¢A…mÄ,Š~þeÝ7+´on&ÓÅqÅ…”!)7+ÔošÍLXÎýZç(TÀ•ÊDï5Èwá?lCØq÷²vL.&jøàNEìwÿŸò2G®ë¢è
+´ÆX˜‡Ð%‡L½•32ôþ}.ºñlþ'Ñ
+Tš@÷í;
+þ‚ûÄmÈ
+rOO ­X÷Ið#‹Þ/Šþoj] £ZXU
+vÜH
+Q*Ö»”«¢uAeÆyFÏ¡ä!垎zŠ¹•Y¥hìÛÉ;YQÀSÉ ÎÑî‹ôH $PÝÇ=ä\ÕÐih–Oaïý¦è!çR‚ǤµøðØŽ9÷éΧœ
+1ÂST’.Yþœs…e,ç³Qã˜sµH7 ÜäÜ®üÆø&:/³š€¾xðz'&PP°18˱ÍÚs_j‚!ýoýy•ß¿°îÿ±« À"L—`¬˜–(.߶˜!s/=j_rùXôfEÈŒ”êì~/(I$ tšù²_÷v™¾‡oÇàl ”áþGÔåó̱äCѺ™,‹ÜdoÛíKdºÛ’ ‚4}Fß’Y ¼ ‚BâxQ«p?ò4ŒûOEµBÕ{Â5ÝŸ†f«Ú)7aô—MR?û“–þþ×·ßþ¶¡ó_˜–¡ïj<úôPH,ZD ýjí*¢„Fœ~²¢Â÷³ÎâÀ—UÒE7R¥O”0ÖÉX°ÃÍ+
+º^ªO»䎟1†£„yyÿÄo{NDC^Q¬5%{ÞII`¢•û;Ì`rE,ņ æl,ÌôÛDÀLȘrj S‰/cñó~tÂê
+0l؇Åe"('?—r·Qþj»/ŽU)sA|ÉXcŸ)sÎËpZ›@Ŭâ‚à#±™%(3ØÕeÊ@mx‹ ÊFNàÞŇK!¾R MÖzÙéÙdøŠ÷‚eÀ.DXÂïÀâ%2ì þšþ;6:;AÜêKcV ‡ËLÒƒ ì ËßBîŽ +æïcŽãúQB ÀnFy×—µ5¼š7bØ«ßf­ßÄñ96»8°#y9ÔFÇ&ö™EL…5¨uïjA׉»ÅJˆ +‡5ʾ~4Œ%˵}P 2€
+²Dw±áü±gû ± d‡ÓÆ!›Æ_D:ÉO¨¸afu '–ø«¬´i'°êi¸(%OÜಋ€d² -…2üU„f-¿\jĤß!áiÓœF‚òó=Œkš 8h „=^DÓ»¼”MSÏbûU±@Œx²`Å=J‚H0g&at‚P¿“'6˜RLŠž™
+¹ã„òŒ^‚l%-ä¥D)Òoš £¶}¤³r\Hþp¤Œ˜@ò ®®Y¦ˆÎ•¤VxrRè >4Mz‚f“µöA)pÊNûWô,Sž›/xT¼ •±ºº&"U-pq? ÈAèë<@âÇøfùRì6çó BBtNβJhõ`ôÃj
+CèðkLíÀ'ïV„ežÚ¿|’)2 eñRD³²z&ôÈ‚’„µàYM7¿£“¤`Cx`žù†N¯â†ÈFªýL'‰°¤`L¢ÞÑI¢eœÃ:æy¦“$¿ËôÍ‘›^ågðŽ¼É?Rîò“HȆ¨¹·ˆâo—sI’«€¶ZéwG‰ãaù
+¡U#rl ®ôXß8>ég°)fcv-É>ͲWøT àÚ õãÙ?£^E2p±²rÖÈe´üÛ4ô<ÑF¡ ºèiwÕE#¨r3Óáª(m&ëO—>9•H02ŠežX.Øâ•_FvœØÄ‹U”Qq™}d@q•ša}Ž4C ,*mþfE⶛8w;Œ@ºÃª¦žÝxžŠø¶w,
+-‡U~ÿº_a•&¿ÂÖYÄ4÷²~jÓ‡aÌñy,Þv†Q?YhT®2kb8äÁo^àÖ èt+‡WIÏîSN"õ$ÓknŒ"¤³ÊÖÁn¬‰x@[ñÖ –µ{øê*Áü_E]E öà´lf£/6ÃA¦Uò®0 ëÊ úµ ª#ÛŽµº)a›Q[%œjzú|”:„Ò``yÿŽˆ¥fÏçú¿×÷ˈjh
+$âM1ö쿵ÄùTÃÑkP˜‹Âç.yðß;¾E‚ÛIRa‡&æWÑgÁ¤„'bxšöËoà ”(Á:
+†#*výñ¢8FÞýU}E†T-ôîpXSÕ¾“ˆˆUÈhu¢HXet£Ý”<ɘŠÂÊÍ6æùíxŸ§ôæܪ Å©Æ‘ARí‹ÝíC4u¼‚¸¥¤ãسø‡òrI²ë6‚è
+¼5èÀ…¡ƒSM½†gÍ¡÷ï“@á‰ý. Ò¢D‘Õ¿¬ÌSÔ³¥Ð¶JŸ%£"Š÷a˜®ŒGQ55;kÕEȲ̄ ‚pŒ¤ é^¶˜‡ïfA0‡S¤!sL¢”àˆ( b…Є©Ór˵ȟ‚·ž„QJ/¹ùf â,x¼/í äÆç¿Èøç× :« ΃¡iŒ_ë;9ãñ•,‰û;]nh¬v—»¸ÉÄÐû+?A¸¯Ä$Gf@Å…ì¯<jÚvªX`6[Øò˜„ž!a ¬Ò¢÷²ÈëVðK¬é»iš-¥’øJÂ`ˆjûÈË#>”'3v¿@„D 1]v·I,Ç#9§m9Ìu¶yaÇ´#¬—„„ûä­F·T·#gòŠ&•Y¹¥°9W%tÞÿñðm¹`Núa[¢A‘-âÉ+E(
+mlk“ÔW:ÎY’£…íÜ"ǪXfÌi‡
+䉕7k‡’yöLGˆù‡Zçö4ÌeÑJÙi…–Æo[‚ì|3‰C°×”ÖKÈ?²4#ÇzöD>îSk£¡?–vÃg}¨ÊªAM³#­]#fì+:a‰¦*­BÚº7w\Ð"Êk¶”˜áòÑxÝwâ$D„Ãëü°AwcÏ;ïÃséqañ8|Gš½ÒämГ2äÊxóŒôìhüf•ð‹Ä§Á^s™ 8á.}©_Éð'¢ ¥IŽ˜}ÜÙô ÚÀ¢ °t}ÉG¢Mƒ)&’F¬‰–ìC¬é•:¢U'KC¾9n°Àg¼™xLö=ˆ–"ŸÏÄõ™h)±¦6WŸ‰öPò$ÚÇRO¢ \}T û¾í¯žë'¢åÑV’E¿­î›ˆÂ°[ò ÑRQi~qËg¢Mjãî™.àB´Ñω0áüýH´*Aì´DsÙ>ˆv~%4lXuG¢¥$qp¾ ?­JèíÄ)âØoú•h))Ò÷ììçúJ´”°³A[´·¿¼-EÖ1K‹õL´<”ðCëÙ`xv¡ÑûÕ`Â|K´ÛK¿mÀƒRâÛ {;mä€^ƒ½ú•h㇜„Þ èðL´‘6aªà§8ú™h%O¢¥yâ%£ö+Ñ>ös Z½Wk(™OõS‘K£vˆ?¤Hû|÷ÒKÞ‘öTô†´*1û.G¢Uk€¡¦¼Åw¤•å…°¥œï„´2p”Á)ð¨]ò†´èÊÑë¸"mX­•:‡º mø §‰TùÁiÃvD‰<oH>@¾ ÖqDZù)N‘Š"þŒ´”8!m$NÕÚóÞðii-Ìšûe;é;Ò²_™W6Úi9ìÌuÑûvCZÜ€ñ ˆË±¦3Òò ƒë£³ÍÆi• itöoåEýXEL‰A…c8ÛŽIZÈS` ˆðYˆdi»‘m¢‹©åŽõýbÚ~Ÿ©eY5G%ûË-¿2%³Öµîï`MÙq´ù”0QI?²ôU2é€çb{)>cËn¶Î•ƒé<µÙúN/Ü1)†éY^%„W#Ua7B“îcNubSèô²¼€»à“QŽÊýó\’„2ð[¼-õ0TÝ7ÈÄ žl‰½S8¯EÓò„"–z+b†ZAð}0 7°kú§µô*ᨗ«Œ½@ËÜ$}ûyªá•¡< mé÷-2Äð6›°ßÐè¹å74ú¾ÎÕ¡àŒ/ߊf .ŒŽ±¶Ÿ´Tñƒö\V‰^¦ÐCÑÒÎ6„‚àëš%KñƒSj‡ƒÏË© ‘îr¹^s¥ÝéÆÔÒýÁÑ–„ qj¾b?Êä"TÌ»H&¦7²ÅroEŸ¿Óð._`º‚Ù> Õ°6}i#µ*Ú³ÓûœFQƒèˆ é—"Í©¤z7‹·KÈ0ÖM>­­ŸŠÒq’8h¾}Ž³³(~(8`Êañ6ÏR$î$nÉœëÃÀ/ô­–³vU)2™!“!^/ÌéR®6¿qÙ©€¢|.êd÷Ë„{õƒ¨ñ´Üçï<°tðÇ¿™6þõŸüñ_~b;™‡ŽÓ}H#‹zH@˜¡ß$¯/UÙ”óE̓?㥱ˆÒÃMÍ¿ÜÓTó˜ êµL¤ó©1ÑÂ$mmÿP¤Ù/çB‹àe€ tQgÉ6vÔª‰2“â^B—òN„€DÁý4g-«¢¦Ì¡ª%ŒÚ‹ˆ#š3–éxT4¡j*B;$%+š€ÆÞ7ÎbØX¾Ó¦U©ˆ}(ØxcÍ:O½î‘–æý¼jhZôÊ/òÚךªŠ"j•ÔT¡/4\ðRRXø*BNûà"<4`¥M
+õ“ƃÝ«Og@oe8c¢h«„ଊø¸áË
+È OoåûX7qÏâs¶ýîåe!Ñ܋ˆ‰ ËÀ‚ÒÄ„£ÐCê™ú„_ö‚à0¬¶‘ ªŸ•ÎÛà~žM¬"Üoˆ:ÚÕ·Ùt$x4h:#Ú3$÷Jî«„ß‘ï¨%ùR<eÁ+˜c¶|IÁʼnúƒg/<t÷„P_ß©œ†6²òzS˜²Ãm½-¥RâA öŠxÎC㉴«­Æ9qaYg/êýO/‚1éðW Ò1ôD#uêZ «5Ðõá Ôãhh.$?ºD†ŒE½Œ Œ£¸#^·Ä¬Ë­™V‡§×—5Ô©™—Tç†Õ­mæÇ©Ðá­5³~òa,Ø"ƒèFóþÃU±kþŒQª.õ©n غWdN¤ÉJG˜%¸C'ÿ$Q¤Å¬Ä@Ùÿ’s ‰æàƒ
+áÆu?ÁåLNM \Îa3ÿxãÈð£&’’ÝKƒ:8h¦|-%ÄcêÓ¶<ðàSžˆW —£¡3™¿e’,†°´K’ÆtBO3ýæ+YÑ Ÿa:Sƒ\‡•Ù®">ycŒ›÷E@\)yL”p—쇄xÙ—“t?x£¶Í¬Ù¼+TÕ„9ЄœíÓè2´zœÞ¤
+¥2ÊîöåÀ Ç\7okœ4¼|1Ç5àb–±Éyàÿ²ÜÂx@&`8f¶û³s}¨š÷cŠÃ;fÎ p(š%-Òã£hÊõÅ8¢Ü«¤Ð08j{µð—æÛZ*VÞœ6*7´>AƒQ„ë÷"šVg×aßã;i×¼EçÚÆ ‡©!Ú ¼fVÝ,Û@`snâÉü†·Ns’¹µ QëtB]"¢ûûåKàѬä´*ä­ú©žöv4S’‡œq
+H5 .į6tÒ[ íäãõ™AÌ¡r®ä1¥_tµRùPò}é‡V‚…³’äö„ŠàW/$-`iüf•dñ`¢í¹¤ò!~Š¯¥þ^ªk²yV’ͬUz~ ¥‚ óÇ*wàxßõQ›Ò£ïôÙm
+ ¨cE»·þ…k¼ˆ!X¹»Õ6ˆD»ûæ„1²µCW×¢ZtTx§‡**šl‰‡…Éx 9uFŃbONª]`3dQÑÄ–9gQ†íâ_J¾¯s…‰ ¡äzý ÿ°òrz¢Ÿ‚i•DÙ:ac—`‚S‡]-ÿ¸Á·üúôí`ò|«Ü³Œ)m߶áïU~Œ¸â!Ng H¸_Hæ–¸U4W4F´qJ\*+MÁÙÓ® ¯¹T¤˜Û*AË¥Ë cY%s,Mðî•xë¢î‰y'n¨ƒÍqÈâß <ðˆ˜èžD»¨“#€]^u3ùêÇ\6IÝÏ(¾­•h:*ȹÞUŠïj†
+vkrIeÙeä#c·"Rž¬N|í›áÖð_Õ-ÛOÑ]
+¢,(È>‰Hrä;{æ‘ RBS2¸›T„×j@“õ¾¨—Ø´rñèÇ>ÿê‹Þþ£´Ëº5dL,ij_²FüY¤p¨Á3f:IC‹•
+X¢‹ao£à*uPFV2 wŒ=pvc|«·ø§5‘Ž$­%ÿÛ-zvò-XPØ}[ZL”›“®Ë`ôzuç]’I/CLá&aé
+FO6
+)‚'H¼øÆüš‹>­$cìPî¼3Dÿ£í á04öQ‡Ä´q¶fÊjbYM|o¾)yÀŸ½û¥H8Cök§½
+ÁH²n5ÙÃReäXò]‚FV1,z§=L„zTö0ºƒÆ
+·,Ũ!ù¨?r^šžXJRDmW .5M¾ôM?o‘75? ºèb
+é?*!’õ½AÝPTý±þ†
+ÙDp(’Ù(
+Ü%ƒžÏ黄K?;»§%rRŒ*©ì%‘4Ö™{wIW¬nK:q£f$‚-ëA9J„;$?n¸&Ã÷]¤QÀžµ7w•„:œ˜ûXEŒ‚‡C¼PEº+âK8 P€‚8}ŸŽ
+›îÑEÀ¼ÓøxCEò{ ­LÇ0¡Édp‚1tNxðiº3ë¯È…>¿V|Ø» ÌA­­ß|è(W˜Íg¡Ä„G…iò.éü5ÕÁg¥ÒÊWSl~R—éà*|ÏŠðU<°Î°´M  ‰°Q¢¹¹G©Ãh4+Ñ.C*s:=uhFX–•ù»ç$>˜~Þ TBcÒäVn‹°rS8Ù9ãÊŸÿ
+ BR9ùeøäÞöðÛ²­…lªô2k]TŸ6Uÿàñ2¾ð5À|îÍ ŸÕã8$öCÙÇ>«KÐv×nIt©¸·ó¹âöìçš' ë²MÈYÎcOzÛÚ2¿”ÅqIé³ÞR$Eæàf‰öEo× è9©ºŸÃ~&Éa'aíˆ. §Ùu›Ògóá} ËŠ ¡ ÄúÒÀ0  —âßÁŠ–•Sæn/%8aÌÀ´ @§Ê5·ë$L$ÔƒEѱ®ÐAOoo7kŽ©r_âW$HIÃrôˆ¥ í ^_6Q^EŽE«\âÕ«‰’ȸ¾˜¬Uí!J…fÜ%ˆ+GÉ›ße’GÌøòte²¹ÌØ°¢!g©„$úþ6;‘eb¼FúHÞ*A¥¦tÓñPdÊbîÚ† šCÀÊz;~q[(±¨;Ÿ6Û¢ %•MSWŠìÙŠHñ€’=]Cä¥qØPµO了۹P3µr,®ç6ÚpŠÂH1LpañÇØtù"µÌ’Ù²|"µ
+
+C²“¨ ÒV”ñPbG ‚!hÄy´»ïLÑ~¬öj·AÃ9*ŽÌJF”yïv“ÆÃ@ühT–g+"ïæ­é8L„3ŒÍ¢Ï&ƒË¼«=[£íZ{䦤ÊÙW`ÄÀý¨—"ù¬"ëÜ7Ñn3X"‰ K=¾ 2$¾‘üM‡Î0lÌ*Z.pX…pf•
+K¤GË㬰„‰èà<”ØQð0ÚÞÄwßQ·ªØ¤úmxÁÄœæ²ÅƒõäŸØqØͦ=‰&Cr+úQ0›È&×i«¥l&jã
+vÔ ¨ÖN§ÄØoJ
+Ôœ±¶úYF0–ô©Ù6oÛÀÉl§„+nˆeçŒFñ­¬2x)Í¡:è”»Î:Œ)HK¢I¾Neä@ø¬”þW?`(§¤(‰ ¸‡­>MëÏ´¶Ã>½zÉ*D¥•é–…>“dyt6Ë»Q¼G•ð¢*
+Ž 9Z‰ìÕõªhW^¢NÁ²AôÐ<[5 ÈšD«ZËÓ’Œ
+J˜S"‚ªz¨cª©:PϹ:~p
+-ƒ“;IR1 ícɯ\ôÍ·ÂwÊà õôñRM4e¾3 í€=woýëÿ;!JÑ30²È`Rµ‹«þˆ›4u„nE”T>ŽlEAËÃß%˜0EìËY¢Q|Öìï¯/&Ƈo¥[ç•s÷ª²ÂIM¸ ¶ÌR\Q6¯`Eš
+δ»QÃèàÁNwU8ˆP‰5@cgÙXwCäo¢0(aí^©X”àžÀ\¢/Cc~æ±:Ö<#ÍNî‘딞 «¯RÑç5f£âÁ8:sç[aGh‰É6/MÝ%(]ê?ôÐ?œkãø’˜&Žàï@ñALÎÜWdLd >£"ûvñ7C|’©öB9Æ­Fúˆªf¯½‹$("&ÂFÉQOE¡Ó©CÃ+’ê¨x¢%tê€E043ÁÝ7Wp5¿kfçΔàÄp8 íóú(áî–"P—ê[™àÇ€È\ Dc($ñª}ÝKÔ4¤‚'9ËÃV¸º×%EüôU~ÇRÞ{¤ñŸ
+H‰”—A’\7DOÐw¨µ#æI
+¦C*͘>Áo±9öwª³%fù‘9¸«öÆÙóóßÏ«°huÍù<ä'ûÆ-B•B8nŠ€Ö"¬T+žÞ^æ3óozò2ü»ÎE†„ØM{ÜMèòמCïm´æ䳶AÝ,ø†À+­w{ˆN•¢á}BX:ÕëyN²1zŠÎ›÷ÆQjÈDßß­bt£ç½‘=e 4Tý&‡ÒÔ^Çó¨WP)¶öÍíyÔÏÕÀ‡†|ë|{)h×m̳{?µ•:öÈOó~îïËšüÂ&-‰zü3Îk—²‘l3òŸ†AùL! ‹‹}KФŠÉ°÷Âó=îÚ!^+mÝ­q7+-­žmqŠ '(´oÈ Y…“"~³0ëþr¦7ðF9ËûºUÂNð£0?GuÆ
+ß 0eOáq4è\6¼ÄzUºvܲE/¨‹ÿÙt¦‹EƒFzÇ hÏ‚ ‘ƒ>lˆJ™Esƒ×ˆI³&¤3yè„"mÖàWb£?Å\×À §Æ­Ð EÂOD ›¢®ôéˆãB)ø9roß‹¯&t–é̹*l…¢RËp{ØŠ×p·$# ‘ú7®²WµKïá­6N‹52l›{rÁ{ÚÊGî²ÒáÛ­Ê~—s3&‹° lp†+˜#›kA*]rVtCÈ=nêé^^Ý£÷Ï“H
+^W°=Ê!áwƒ¬â)RÌóe7Kr ÷ ÄSõ D
+›M ö<ꄽ¡HˆE×sé¸7,mÈ·a@B~÷@H´•aÕ’;¶ªé.áç¨ZãÕÐ#&n ?Bqöwp=GŒgËm¦X]è{ÿ<ŽŠGo6ó ­6.mOÕxÙÃŽöÕx@ ?Ÿù”œŸ«ïԆ䜚ú÷+úÝœ˜á„nÂ*0çÔ)<¸Ðþ±2t€xôFåˆn[ Z=D¢æ^àCŽ`¸5ƒßÒ)ò?J
+•¯ªfÈoXÜ—}T©â!^ ÄÙ+EtÚëEÎ.aͼúÆÿª,$H\¢íÔ`*/5¬mƒB„²­f_¿×5…kàYæ¬ë;S§¡d¶zFûé¨èP<ÛXÄ:ò;uE^w£c!ÑF¸J}ü¼¾ uLÍp­6¯7Ê£….†PKæŽWeX)#+\–DÀãAا„â20K$¨”³ãâFêÜ÷-—)á['à¼Ä.~b\ƒÔALÆR#ä˜>ò#4ª’ õužxÌb3(Ô„ Âöú~_úJf(¦!¥kì‘1ZD7z>ÏL+‹Ë^¡Ò’w
+Û_!,§/;†„´%Ÿ±/Äq’ƒrË:É¡Œ‰VÉVŽhgìÉ%÷BÃQ#ÊÀýcàL˜Y¯,\pD–¯3§ŽvÇ$GBÆÊÏL¡‚­Q*½z‚âRk%÷kª\¡Þxv™ÓÖ~Ûѯ\ðš\@âñ .<˜„ˆÏ»zŽ‚¶‚¾ŒvrT˜)ˆsí‡L‰!rçeJ¶˜Ð5V–B<Þ@„TØyâ6¶íP'm‘ΘqŽ3‚qÕHg×_êAçi:†ât ²+_VTºÞ€¾nBÚñ†6F¦)DÞQ~DÛíÜÃœ"çy¤¾ƒ5ÂQ"j|ÙXk‘šd§Jã%JïOòu•šQÈ™Õð¤k{á-4' àö¥=I
+€Ð%†€¿Îöæq(6«Gú+çb(ˆRÆþåHki•ŸÞ1Áw^'¡áùŽùá¡—dË S¬Ñ”žz[N™HÄ0ʾÆ}2‰—,’dt±i¼NÁÔ>BMùØqDrÔ|ÓoÒÑ^PÎX(;9\¹‡:Ðö,¯£îø£C§"²Øì§Ç¡á=‚ãÌ †ýpsÖ}ZjŠÇçÖíFûÁVHh±þØVtD=›ˆ@ ŽroÄŠ*ÚírÇ÷1t ¶ðÕýAâÐW:ocC$>@Ü9¬˜Axj¼¶º­’/=—æ×ð0 ñëÆľNä‘0¸1ðka€:ÝíêA¯pž[UY\…flRB–"ºt-wØ®xåH¸„§„)Š@Ål‡¦À£íé5|¡ðÚ°v(3Ïp‰
+N1~ÓPò‘
+H ‹Åë½:ÉŠŽó
+óËÛ˜Õa@¤Ø=¤§*‚-Ž~ÙƒÀ”Eß™E9r:ÁŽ¬=(Zö—þ
+*E1jõA{McúcÆ(Ð\·¯i †`,™+·8Ð J9Çs r©¼=+f¤cÂs8*p³ölj¢Ö¡§_â ÿÒÞÒŽqLÌ({/Ì!Ž Àõ!IÒK‘ætÒ_?Ðua†£á©‚›á×8¦Ê@
+ã6¥~¾åc¥@ÈU]âØZN‚¨WÏÇ8¦åÔ¨3¡Ÿ²Ö‚äÉe!ìÙ;)iŒ;Ü=N =8™ 3¥ûŒ¾¦1 0—ÆO9ôÇ4¢¬6ª»·ósÞ¦ø#ŽûP1ž.qL îER¾oqLGq;Ì0mwxczÔYÍ»Ä1µ†a F ùÇ
+µ(Í/óêrð:M'j¿Ä1@x˜6¤UálT€ˆŽeµ¸ö1Ž ¢ÉÁ£/qLWî\YçÈK³…„°’ó˜Ç–,²à BÎÇ8B”Ó×RÇKS=)"T·V¯qLk%u(ˆöðâ¼Æ(µ“&áZ¸`»Ä1
+ÒÁ®Q¡rûF±óNyÑcû`·Ï4&=£ûÈ^öF½f1Í0ªÚð8ŽYìÿš©•Å¾þ¥ã0z(³J;ÏÏ ‚Ó›Ò(ù<ayE6†µ>ëóÒ/ EÒ7$ ¢]\âÉB„†­ +Š šfË8n²ö¬-¶£„Îbõ!°VÝéŒY¡«*½‡0?:2Õ¯tÀìGa•aÅŠÛ6áeÉ؆ðàR0¡SÓnIKOq™C/6O"¯Á ŒðþŽ´µ‰ˆš92Þ´ö.V?ȶÈöÍzHlv¢AA‘÷j'©2ìÆÔŠ¼ÛÄʇxxþÊËüøQdN$¦¶ûðR æzTµAf~Š¿.ÍaØsÈp¼e„±Yâ§Ä‡41ìMª¶Ž©‰>£H!ZÜH2Ä´©á=C^”â÷Ë}Lt½Áü¥ûáÑèbQ†³ÃF•rU~eÕnëÏœ·ƒVì‚zf“/K79¡!ˆaR(œ—ï"cÛm¬„üC)ÿ4ˆÌ ÿ›Ç{:„ŽÏÕ’YïÓóÚBFðBõ§c­TtÄhg½j`m}:¢ú²¤ÀYŒÚ!yãƒ
+A|ˆYýë$>Zõ7Ùø0UU!Ú}É8’î S„•!JÍ'žc64Çv”md¤ÐÅ‹÷6ªxÕ<e ßlÓŒ ^ɲbí ÿEÔÃ.qNÀжq€8}ñe&RÉÐ÷IE0‰ô<Þœ; ¹±¢Ú˜;ZZÐÝ&¡ã>Yfô삳äLØqsÓyÏœÜG¹}FFÆPý'äÍÚge!HšI~߈
+Fº(í=“Ûqwø¥öóëb•sÙéxM9fønº|Ië²"œŒ©½Nb:‘×._R=öJíã
+˜VŠd2œÐT–î>E^€ášËÓ¾Cl"h%sƒŒì 65u$…àq”K¾ŒÌó2|ÔI‚=ÔR?ê}†EKì\£híë¼Ü'9µ_ / ¥¬²ÞNØ‹‹ò:Ln õD?§ÂönJ†ô» ïý%e ò•Ì¿@¤ ¤Ï0t¬ƒ&iM)K«ßA?~åNßûêˆ1Ÿ‚Qä÷ !âÈDZ<øíŸ"£2Isîã-¸fì,ÃÕÖØK÷WÄÉÛµë8<<$OòliC¸)¢Oý³ ©íI1.ˆ?`fð0»·M6GVÀÊûixžÆKƒV~Cà‡¦!у¿bdJ,MÜ”d`­Y7‚ëe†A®{C¸A!båö e­I#€Zï®e©&ÿMâØßao1LlÚˆ7ÏJ‘k°“6©ÊP,Ÿ„Ä€´$_àQnZÚrq`$kҙ˴ x
+9'.Ó $ÑM¸43yC83kWÆ°Ë„Æ°Idóþ´ÿ—ñ2I²ã†èUt‚ÎÃZ^êÞÊ÷ßú%”Ôýù-‡í¹…f‘@"‡&#­ƒVÚ±;
+bã|<“Q‚“´?°Zž©l(¤/šœh›ÜœªÙF+v)¡
+ÿQªÕ»h¨·x ¹ù9,n-Üf·Ò0D'|É/ƒœ«ËðÝÌŽ
+žÔ&…èwæ^W|‰»A´ýœ¶gPg;µC’ɎßÍÈxr¯àÔµAÈ©üÉŠ°¢„5¡­rê‘h:Ó´B¯E®‰P(»'êòûYabhž!Š›'…°DB`åÊÅ9©ª§  ¬î¬ -v9ÛóYQ¸ŒEwÌÆ0@‡MŸ"6À×T-ÉdmýR„“OX©¾;§ŸµK2jq‚wÁJ×+·M‘L U|¨M™•&ýK`¼Ã&ëYò©Œ*Cž¼ÁD´ÙI<Í}韼Ôq‹ßþÒ÷€V’m¨>xö
+KÀdÅÌvQÄ<9’׬¼ÐæË?[ ÜФÅÕŸŸåÑÑ]¼Ì°HÁ-Š ~q65¤g²&K½d˜Š)Ž
+Iî%×Ä$‚ Ñâ6dŠNÜ€°Ü¶ò¿¨
+#Ï* çHÂÖüÜ !&: –„-& Iˆe®áˆH_Ug(òe¹i.hǺ1$ˆ#퇀&9èz]vÈ4®s¸~n»Ø«)ÓÚwÔ…)— þþÓüx<Jåfݬf
+kõ»ÅýÇŠ
+~ϲßßÜE^ 'Êg×~Ö‡LïwÁÇ 5tvŽ@X!œ!Ë#<î'’3ð¬AG†6þ jxz^kN¦žüºö‚«2‚òϲ9ý-DKŠ4¥KýK´‚ Õ—wÄ'íäçÀkø£±ŽŒ¢ÔÀ/éÎ"†õ¤C ϧ 9Zgw^ ,g2gçÀIúƒqóÍÂm1¡ É)!vÉeB‰^R«‚˜~m•øÔ¤Ži`„ÙŽE—šm²Mò>kƒ‡YOIÇ…)ꌱ/%Á_KˆE´n5N_tfvr•ó¾UœðkÒý]"%­4º›<§#±™ó-ÂÀ†ÉûlÛug8Ÿû`šÞÙöC•%ËïúöŽØÛ4ÒK
+´ÕÛàB¾öâÿrå›ÞT"¡ÈØ]o€2¸l0!žÙGŠ’K‚]†•ú?Õ’`’n唬Íõb*râ)ôæ÷wÿ°Îh’˜>nkzŠÊ‡~4aÄtÝe?‰;BÃÊ/±j( j%xšÝ3Ð皟ÿg×H¾<• ãJýBTÿX‘<j%›´Ù.E§Ńìè¥#‘­òúR³
+|·!°äK´ûÛ>4·ÈWÙ*2EW,a2­§d¡«,¶xÃó_l%õ6ö„íƒÝÕö%Þœ¡f¾ždøVê—šŸ^?‰ÈÇhÁ8%`KnTx÷p,ýcÕÍð
+,G,3Àj%€,PÄ•s_‰éh‚O|ºêm‰µŽhÓéÔ‹©R9˜ä5÷î J•˜BVáf‚§…äk¥a¹ŸMð ób‚çþSÆ5¤t¢Œ÷'(cM”l¸|3ÁšeF›ªáJìh‚µ„N®0…g ÉÕ^‰Ïу!8Ö „­åïUƘÊ÷a¨ñ7'U>SÛ«üõ“}_7ÆO¾4B‘ m]0𑤼ó× Ä~k°õ™ Òŵlær<$>†¦z«Öñ“O¢äÆœ_€Égð×ê Ià› ‚àDÚ:~@à £+
+~›qbŒ×öÎORùm³4‘aõµÊA4lrÁÜåÇ;ѵÝWôRNƒÇšƒLrKÖVÓ¨ Ó¥uós*"! †iAÿThÕc¹VV_b…!\+iÔ•_#¾ñýãèa¼¬br³>h†6°•)MóV4+z$¨N–xŒ§Ê*myníÄQȈ=Y+" ÚžEDŒŸ®ÏŠü4ôÁÛ‘kÕGk¢ò‚ðR“4ûïu“<6Æ—®µ™F³¥á›A ÙíÏöÆÏÑU­×Nó?‘òÙck‚(×ܹpöئö‰Ç[Ý!SÚŒwsȘîµäº“+jALEHÚòcÖ?eðyPhv³%µ¤¿cÒe¹åVYcÛV«ˆ”¸hä äÍõ
+dê¥Do¦&‹ʬ¯U{M¹‰v6~d TÕ¾"^ôåyùXPa…²@€X ÒÆ’A,¹›®ÀÈ«ÁÉ3Ç ´‰l§¸¾ƒ$Æí(¯†ÎÏ¡3Ð!éÀ!Š1!³1iT'UÒ^´Õk¯x*uä=¡<F6Cß÷«ÜƒãVÕ¦›ãÿñ³¹? nð:È¿ŠÆ„&úâ#8[‡’v„Ń0pU²?!b!¼‹$ËÏé„N冘ò‚ˆ Ú*:_¢âÉSÛW¡0YÞ mŠ#ÖÅyu3*l)‹f~Œf‰vÉÂùM/*Áë`7¸*‡2)u‚æoA½<^¬À÷ú×-%M¦Iû¹%ž¯d¢©ûä—Å–Y@dÈ!\£àÇgš-"QñÌÛɽTgÌÝÚ®S‚âÇ æ¡EÔ•*ù—#+‘Qgc7³ÿ›þ ËÞ1†’&1Är¢M©¸FF°¥#Y’áG%r¿@$
+ÚZTð(âB…{B¸ú$@±Å6™rÅD/b„š¶­=ÝÆFOGòãôõƒ¬ðeÆÙ^Åë—ðu=‡/AsµÎKLß— ¨}Pi±KV$e8`±ú)ò
+îÄg gÇð±–5Õ… ÉØ ´Í”ô•Ü˜X±iq• ‘̈‡ÖíפuãHö|0˜h´øw¬3Ì"[¶#¥²ï†;½4Úb îÉt—IHe¸‚
+ñã|ÈÓpy‘#A¢2aã6¦(ÍV¦­ÿÂ/hÓïÄø¶9"g¾•ˆ!?|á7r‚êJa/Ûüõƒw^ˆŸŠµ
+‰°ŠË/4†;Ç"†ˆà ÀYcPH-PrB‹ÈA–§åóÚ”æL•€_X'aªXo{œ7ÖûîÙóë°[¬Þt󥟸ê—cdIpëÝvïÿNð£xs‹ªvÈ|te#]3‰VAú(H—63«\ç—a2i†µ™°$ÅÞ;@æhÌK ‡-¢=ñâ"§¬sòÐh1J~p­š›Æ @ªÝ+°ÖŠƒä³×y_…IN×Öâ‹·•VÕ·‘Ö9mÞœ”J„õ(ºG†Ñ!¿Zq¶/²Ç
+O…¯FÑcæN _x·èCK™êÆL²%*³0IòUµRÞ¿Û«Œ/ã–j1Ÿj‚ú'ͳÊl×£Œí“¤`‰zÚä¯lûä„?…,“Ð""Ãh Z‘R\5† íqb
+c§ šìQñmêÀ»É16 tkÓ‡}NLHŠï½T®Mç%¤ˆÖ9 t+ÑÚvZ³cøò"€Åé=(°ÿ†¥4rçzÜuÕv³Î9õ<¾buŠw{/žv™ú€û‹“z§ñ
+FŸ-`JœÐ<)V¹†3ô•]ÒB¹¡WŠŽ³úÀAÜ'£qàÏßÁé/z› ­,oŽß!-§8d¸m©ëC¤%W•µ±ïöQ±ïî°ÊØ—"‡4±jó$É„ÃS5‰ÊO/ñô°$8_Ã.¯U¸JS¬DV¶L5G+±Y£ãô¯Ï•#Qn<]è2¡ ðÓŠcd1¹aÝc_ÄÒN
+2&tGü"ri¦ž¡úíË“–¬D¯é.JnL·î‹²—ƒ2q÷ê¾Ì¨=ëeQ>4 ‰
+nÜGð©a XQ_4Uuh´Ç¼ŒýNQ_J~þ|„´?ÿ ØþõŸ?þüû,êÄÔA#*¯fUüX†FäF‡^ŠúÉ#[%ëi%ÈöÉã” MK…›J–š…‚—Uð£L¨ùŸjr›Ä!t.Ž=ñ±t2Õ)ö‰&Pd± Èf’*`œ†'ÉóX¡§
+ÿ…Yª«¼:E ‚ cBk\£†£—þ"¶-ªzƒ `ò±ãK¨<º(l7ïŒîŽ®g¶§Ó@·Z÷û""L™´ôZ+)B皆³ï5CBzþ8ηÛUÖ„ƒ`ظ¡q}%pF—6Œ_zjÒ–¢!ö4w¿ðSåºù_4lñç똞JüS…ˆ&viÏïçÀ½I„©_݆Ígq¥l/_%wE^¢¨_×'H¢Ío÷mÉ0Ö(è7âò¢äËBýÑV5ÎÌÃ'Ê R‚¸²Rî_þø¤uw£]ŠÞ}ØyØD>]EIÇU£©ôµYÑ~Hf;f„z)úø;½ÛÕaJ¸ £Öæ1Óœ5ˆ{GßÚ²«cG ÖÌ.Ž*lÊÚàM™Ê(v«yÆB¢+Å&w+Âút±;ërœEp6#ç%ˆ~aq¡^(uç×Ed<`‰-çC h­Ò_ýJ VCAE™ýXTí½BKĤTßì©óè¹ÇγjØá–ê²ò‹‰W3¾”ü´±El£NÚ¯Îéî—Ä÷¢¤ÉAM÷ÊVž¡AL{ħ6a 2;FðÒA^€yh‡œ[¼›@'°sŽeDøqKýðw#mœ‚Ÿ—Ð&JÚS¬„^ÂðlÿÉtÏ%çå÷QWo±÷DRz±tçS"ˆvÛo\ bd¬V"ê9Næ_NÏ;>Õ‡`×_ßX6¸ Ϲ6;§c:pDv†FÚd¦W4yü¶?îá-æG S´ï—H“ ³‘Ï×E'ªb‹ŠÉämqh!¶!iªëÿl—P@‚mïË2üÎÆ;1`¼H£r÷«;!qŒµ2åÄp)’7'l¶Šz³ Ì_y]¶’–Ž3o»M«@é&ÿÑA§³¢4·²#; 7·êVs
+&Š 7ÛZ[nÁ#‡psÔµd+a `4Æ7Cˆˆ “Å›ð²}ŠP?GU—™´¤Tmp!Û)pÕÒ°2C¼ÜqbS¬3 j+kX/žÁ?µ×¤(èú9ÐoÎÄØ&¦¤°óüI¡Ä±—o4”;ï{…XR–½Ö¾Ìze¡8)LíT/Eïׇ3Næ]×,Ænù{Äd°®>ÏLs¹ñ>6˧'ô¡„@,ˆei€#¿± %“/Ä‘ÆÄÑ»*Û“ÃœHû€pÁ¿SЮ…¬yÝ›“t=ö™Õnϲ¯J°7?\h ¿]ÓqŒïÞÿ¥¼\r$»(º‚ÚCŽ¨Áÿgh”fnA€
+Øÿsà ü’Æ“$¿ÀÆ0ˆVŽk~y•¯ðâêköQÑ\´6±ÝV‚ûàØHa²×÷EeÄ&€‘—xÑw +$‚áõ½æùž`9‡ÇOš=ÐC_@Íh§ õ»ÕTéÎBô"(*¬!-ÿO 9kí%R`—u0a“YÉ^‚h,Ûw~A;x,h…û>í¨T”ýxÛôTœgM¼Rµýæ$A% GÑ¥èéEä“"á®:…s€Ò`¡×þh]šSÊÙGRtkŒÀ,ö®C [ÂëJºnûCQÁaèÓýöñبÌ]’û¼¨,å.qò~s²¨aÏLÛ
+ˆìÝ2,G!W_Ä¿‡
+ÇÐÜbY"ÊÓYzÊin¼J \t^«ÐwkÀ|†“
+HÆeìïȾ@Ññ% ¢­CpISne£RÅ…’<çžVÔ¤°n}ktù,g(Ûö˵áûÉí(ãiv“¹ó'S¦/´uXÂŒ4È:`%—ݬƒôÓfeT¿,qF2O+Â^aj`•¹Dþs…‚<%¬ <ïÞ%—&R’`ý¢U÷5†ØÀ2k.«û›¤˜AÔí¸9µ/?ž$ÅIE@ò˜¬š­oÀF)ìÍ×öZåÏäªÆq)ÁÚUe.áä„L+ä´a%EPmî“BØ-)+Í}éœB™åˆåª„ƒÕä¯ÆΞÚ=HÆ7¯àL=1ÕÃœ>í VJ²ŽZ®”KoŠË’9ÉSQû¶åðØж“Á¥ð–má˜ñJ’É3ò ä‘åÞ5>¥)‹mZd+Ò+ÄÊ’¨Šy**²~#ÆØ<È4¹mPl)âW¸Bùí€Iþ“×:U†9i-½$Ê:[óËÛ’­ ¬*èÁ%k÷ý(ÈJ¶KécËlŽ²²àÝ¿ƒ&3Ý"Uòæ}:ËY¼„éu­q·&ÚB
+í¦J_¨fßØ;þ;-¬î\‹¾‹°Uæñ‡Äq½¡"H3>ŠžV¤¸Ã„¹ØéK«Dã,2¯#{ƒF"u”ÑJà,ØYé^ÑCаRh»‡J¹A8­^‡RHBÑZ±‹•>-ˆ
+„5“½iàpÛuÉöB b‡IÁ’„xžÖµè8-~têÛk6­·­¸=¿guÄfññ“¯¼tOSc½Õ¥¦ÁJÕ ñçM|ý´7^ŠV 3SЃaë&a?s‡äÅß熟S†žÄÊ©ˆMæglj]›¨Ûà'*î‘­c5Jä±½ûmä,q´Ò¿­²TÔçÊ‚06àÈ­"›Zø8ä £ÇóPd»ÑËJ°Um÷!²eEÏñÚ ¬mÖŠú£„;ÒŸùG¬G­ë¬H#›œCI²Uád¤h%ü¸\íh7%oM>%Ao
+³oä_o£ëCk<ªÎ󣤺µóšo'½õF¾kY;ªÞ›K‡ßÀõ>©KÉ/—$9nˆžÀwÐ &ø'¸–—s m¥ûoý’[î*ÖÄض£ ±H ‘Ÿ_ßA²@6èoçE]BI(&—®Nh ±\>Š¼Š xÞì¯ãëˆ1/Ô/‹îI…4%¤è¯+B×RvÝó`D\&âQlA ô%@_Nò£×§’l sÉyô·"ùuúÄqÁéõr:áÞŽñø*’I)Ò,h;ýÙ[s0bt…CLæúÔa"P#LY+ü+')ùyœü¥è÷"îÿ•ŒãÇ(Á’È@²“åtc*>¢ñhçg‹Å±¾°ìÞÝã¦I.à©gp*¹så­H˜àcPÛ4~œn²ºT•ã¥§7ÐÆd«‰|ò+ô:8•HÉxÖ1$ÂY¡ôóº6ô­ä×wvsjÚË-¡ž™"'vÊÇÀc#î0YðNÈ^•õ¢-éP4Kð͈¥Ø½DJNâi•`¾õp~Ÿªê˜áaÝê®%} /ü £.´Ë:Ãzà4gë3®ù”U‚_ƒ3T°ØâPü2ÌðÊëKך¢»é§ýÆ·Ë€c~ ¶ÜÚáQ5©A2ë_ºô†°—QŽ€°øãÔ`* €"ÍöW_u)ñ/á†a˜ÉúÓ9ˆþèˆ:ñpŠ6=*OBøÐ"þœyóªÉ1gÂR©ë˜À?x9ó÷öŠ°e°êCÁaF×’û¤o¹ãåöžî.m9á÷ÒÜÓ|½M?çÒÝ*3À0‹¶"Oÿs¬á(b†Zv#>¸Øo½í÷7n´ÈBŽQB‰¿h³‘™ý`ìœ[/+Â-øûP´(.ó%bÉHû,L
+WºÅ…fd¡Åé K·‰ØÑM¦’`-ä²D™5“e°Àê:ƛ⩗!ÙÜ`
+“îpc¯`%ÕWI†g²²ú²D82>.3ÚW‚¬cÃ&dÀRèó;°²Ž&´æîŒë‡ªž´J †MÛßA2xtˆ}^¨R«ªZõLKÀ„kø!®’_ÕlUVÔ“;Ö!%§CÉÙºÞÏÁœ$’*Ôö«`)’é ¶7n|<ÄQ’¿
+1CìqçË•‘v%¹1û9ì'9CÂŽ+ðá`ðõç’Ê^±´&õ`ÊnØ»_¦Ðˆ„PW¾µ(ýö¨ò![,dáÞ¿téMáá3é˜È?¸2LßMˆª…Òcw?Î(eíèh>”¸+»ñ( ­h*ÝI˜c6´zv(Z·8Èq ÝA,+À3¬WJ@|jè.g#çZ¤ýÂ)5í¯ŸSfB,~¬t¿ºƒ}¢©­F/ )`„Ù‡üú”L £Ÿ£5¨ ¤ø>Œ^ Xsa½$¡TƒlÔ|9Í,0ïí^ðk·¸S€
+8p6/d9žY’
+ðDÖî*I*ýd‰Š—p1nÖI(¾ ¼ü×fbz yfÇ1$†ñ\ÕݱRËÎŒUÒ8ÎQ­XÊ‘aâÆ©Ä?•8¡qÍŸŽY’ÆEý2ï7¥-7ÏD²n¡Ÿ7\ŠˆöcŠÊëᢸ熻ÔJn´u*‚˜iE&¥ìçÈõp—\2Ù@~é-§I׺0gÂB¡›3:ï¥UI‚÷§ð¼©«;k]ä_YS
+W†Ü9Ví
+å5)¢`]ÿ¡0ò͉C¢­cŠD
+Âcõ¼,6þêµÀ»U¸”üüçì'¢Œ
+
+7±äkO¯Âûüy(°欚ä|m=¦€½§wi}Ç*YKh¦gCèO
+Æcã*Ü“.[ûËöÅ”VÙ
+iH(d¼Ðß±¹‡#ç£E^y5ߪiõù1¶îÌÍ«H¼ld,ñ”*¤#}à9œ‡’7š\¦ŽÇcˆÁWþBe탅Î8và ÙÒÚ«±é"âm8IÃÙý
+º’¢ŸSe#ŒÀÍ?eô
+1˜ÕMVÒ¡Å·Î*$9~]S7-)¥‘B4Oȃ➠U£M¼Iø”,¾•ëW%Öêžô¶…šÅ9,ˆ7é_ŽÇÏg’‹©!ˆ¤_Š\‘¡D?_P«eBw.-²%„Sõ¡3ýˬ3´Ž„ãò5èRUÄ
+ àÇ¥G(²¨²/KˆÎ“ËØó‡
+6$ó7æ‚ú`“ 3DbÑ‘+1m+µ^Sº‰È²•Æ4c*ýrß…Yª›wÁ
+E¬¶½ØA¯ìÍZ/l4¥ke˜üR߉À3–5…6× Îj CÞÆlì )HdQäuAÈ pKÂ Ä ©ÌD)*µ ´+¶€ò_í,+³®¸5AØ~Ç&¹¢á½Ñ}ìïDÔ
+Àºú¥°t€±¦eBÈ
+^'ã–ñ(Ð4)žUŠïh:R‰PqmÞ@v•"÷Á1d<mÔ‹ üxó]!Ìç ¤KI;×Å™ý‰Üj9+Ý•Ü×û‘* ¼b[×ôŽ§"iÀôã
+ˆˬ‰_¯s’C³tqAø³HR«iAx_”ÿ.i æ¶åÌ´~€ßOд·?'Ô;eRJ; ž¬€h5B
+6-]œƒûç“,æ´ah@”9´KHö„DºÅ ôæ¤d âZÏWHz€Xl¤‚»b"æ9d«(%”t
+?†ëÙ© òó•IÖлkè·óèbæ¦å"X™JÆLþĬ*z1‡¯ÓÄò’ìetš+}U1b“F‡XLs)ð(ÈM …Æ̵ "n@‚R¬&Áð6ÚÀ‡½T«ñˆQ•+"ظfl» Æ,°øAÀe™¯ÂcǸ+Y-û_3ö¥:ú„Ŧ¶eQ%&ˆw{ö¸æbv~ƒü0;¿–ø¶V)=tóc@`P¯ Pb2¯ ÏÊ£€µÃË¥r0{‚°T³‚@0*8Éàe‘­><![ ‘`—`߬ÛÈ(’Pv׬7Ñ *˜PÜ-3ëJ]’R&qƒ$af`ýTÍ…yôé+âç «y[$FêäÓ#÷eîWG¾¤»¼êÓò€°"ùOX®r0\
+H‰Œ—Ar\9DOà;èS®=Kßb"f¥¾ÿv>ɲ­úåqtD·ZÊO@"‘h}øÇ?ßZú11Ë9zÿøWùð6úlª™‘@Úc†Fk.cAºN ‘àËXLïŸB炘ÏÞÇËhÿù¶@ÒݦFú>GSS2<æ:'¼K5ó…hÓr¸ª  ÑMx‹9o^™Þ¤…„v?7µðl³ÏX/™#½…Ùð+(yL~12uι 9ÃçLáø…ÈÑL[¤¨mDãçڌu“<F4å~›ShXº‡~©ëœÈÞ,»µ±!ár}4uˆE³Hs_åÞÌ[ŸxnòtþÞF;¦îd“¼'ׯc®{£·&± ě czi1ºZ3ëÏ«~Åcºg©çþýboÊá<f.Èp1IÞA¥b¤ÚÓ„œ83àÓ©”H¨•MûÁ­™9Å|EÕªÔ‰8­å‚4ROáF_°}RNQ¿ì«ÆsÂˈyÍ`T‰RåÜN;ßAÛ Q™Âu2Ú¾*Ze˜‚zŽu•>¬‚ö!ÚwT¤IÄu„ë\çôa SÅvŽ¹Â%z7×[Èx¨,½‘Õï+ªJVð?߀>߀šR+hѺõÝä³Zö ¡¿ƒ¶²›3;è>eŽýä†ÁRÿ™e/Z¡·¢ÇêIÙ-Õ-ð]ã$§”ƒòöö¦œ¿"ö=æ1èÄÞO5_NQ¨ÄÕÒs?7[£åB²}Ñ 0/’ü'CVäðÐxB!å—(Ûf(W@R! »Ãų‹¶fMü ¤%u&L58W}!:é¢ÈØeòm)´ïGhQÒíû*2KwÂ$É--É>ý‘O…$j§Å¨ÄšXÝd_Å áHDæˆÀG(ðÎBÁ[†÷~”Ö¡…‚Œž›¦RkdtùCb£# Fs-¢óW‡¡cû&B‚$a—þ­¶Cx9õ8²Ï1 h«¦§íºé¤È9³0$J½
+6÷9P«SIÛTÈ'G Ó72Œ¨yæÏ1^z/µcŠìö•JÌD¯N˜°bÐÒˆ~¬±ITU¶¦”gCą̀$í\%ü«{Î=?惨Q2‚eHïΤŸÑ!æņT[p?]ô,UC“bD¥ë²k¥tœáÚý1ŒÍ~µÚ°!èŸÀ’È )ÐJû¢Ö„êZ)ô6å—èç1r¼
+ ¼yÓo Ï¿yø+¾¨Ž#Ù^ŽìŒOL)X
+¯W|€è¯?Ò¨Ì9-uABô9‘s±"ƒP<cC(sN4ï Uܠผ "÷çPKþÖ¢4þ H¡Ö,܆rÀder¼s2¯ Âä øÆÒVAJÑ«ç0µÃÿDi©4ë‰&mPPžî½èþÐïoÂe'jKB>¨\°X¹7=L’Þ™)[¿r][…_Š}k=«L<ƒýƒ­ºóVÖ³qûz
+û ¾ 2Øñ¸!Óq•×¬(†é@¹® dCp6÷gôçM¦áÅÖ´Œ?r¡k]|1bÿ, R?°ÃHî­åÁ†Ð]ü˜|nb»$ÏýR Jkj±jûÉRKåzxàk(̬5ïø,ÜÈ@v)E¬sèxeôP‘y¶$QÄ
+Õ:Ô •¶v[Ì2÷5´˜ÑSâ\õ…Y_amY’|P+/›Î¸kŽÞ@`(<\¦žWý‘Ç?~º /ÓÄJÉÃŽ0üª¾ÿ¼Á0E±Âh…éXã´„5¹€.8Û,S’a…C±‘¤°5–9ž5òÒG„CÏËù©Þ<53 ¬œÎɵ2³Ã Ã}ÃSÓK5ÒÃç d_$ØjT$ö†özŽ•ùðò’CöUl¡ÉAT9n?×\b¹˜Ý3>F±Xеµ”¬ g´
+v‰‡]ëÅß`nW/ÃyÑMd>ÛÛ%ŽQ8´žù¾›½øMQM¦=[5¦6V\æñ>()&
+Rß„Eþïåüë ù”.i/
+Ø&ìì`#½ °—Jq3åÑã¯ëC·Q9§Üæí]å†ïIwø90|ö×)ù2§ÿý`_>©[@?‘ìsiÞqŠ’X¥²¿èÓ¼ï'>b<mø2À6Ð'èÈã)OÒ"´<êSµúyÒ.¼³…ààs¡3ö“Sí%*?–á”õÆ"mþeâKßÉLÜÉõ|TDq9ž×už&¦u­8rî9,¾D¢±|UNj݆á%,2d¶'uÄÉ£èëà?jÐuèÞ®À1¿UC ²íƒl3QDzŒõòfp7n»ìÔU k„Ïçìýr«hBŸzÛnÅpº “¾ÎYá§y‡‰?}›á0åiWXœç
+Â4Áh`u6H åjmgw' ­xù8Ï™bÅéÔò6„L?d%ŵȷ¥êק7éÍâþÔ÷ëyid.ã¥P»ðv…làæ}n1E
+¯`Šî;5¼Ü@áñ$ ¡íšÛÇnE?¹Ñ?q/íÕãÐ U; øï¬aú½(Å%‡È¯
+˜ l»
+I+áœîh–(ÊÀ¤Z¼½‡Àƒ‰À±³ãExÝ¢äkG4pÞ°U©^\§þT‹~Õµ¬Ì ‡ÔW‰Eá
+n_ù©mÉ°¾„‘kYËÌ.µ^£Sóǯ»øš¬P9[M ®0Hk[ºB¸’É“5ÿ5K¬ÄÎ^Ž´·ĉ­¦³£(²Æ©.²ƒ­Ó• ¡ÙœŽ¿îhÚËAò`~.6¦ÏsX„RѪ?LêÛyÿ~‹“*[ †–’³Ó ù: ­Kþâ_Ó¨l,ãq¶MË6fIˆÄ-l]xeþ‰yÀ€}¦ÆÂk±>MrÐ7-Ž‘ùãuû_W dèö&WÔþú#†¡?”°*t£Šhf$:‹ÚÕ$e€QÏÉ;Ew reœ 0¸ å鲞ªª{wSƒÂP’¹J¨1¨} Ѩ®œzs?TYkÌâ¨æ«;%D DÇp¢«$‹ ƒáÐbœ%2öRÇN:$œWÁðÖý).Œ*ãT·‘j?VkóÖ®£ND«µÆ±(àÉn¼wVV.ÁÚƒ*5w7æÆÏjeþ¿“™˜pŠEó¹ÉZ‡-³
+¶E• „
+.eƒ„ÆÁfyøtá"Â{ò§Ö‚`ž OJ6E²a+•. 7ØPñh-6%@uÚÄ—$ÌA¼êf/š™5É0ÿ£"/ËØË2lG`ÖoŠLYÐöMVä¹€ò½…äOØù
+v6Þä'gËÃFˆŽÇ8n%›çðŠ¡GúÝs ‚ZÇÎq•éÈû\U*X1>DAØ2 “j ª`¸0ÆÂi™ßV¶èïkGwß• Wìc{( ˜Âh1z±?õýzýË‚Y¸Òw 춟ø÷ï¬é<¾Ö‚GSÝ…j„¶ÕGKÒaÎ*€˜°b%°Qyr—"A(s5(2­0¶øƒ§„6ÃÓqž£@QPÜe@)n<4¹ÈU«ž3¶ø gQ›–„80fÔ•ƒ(&íé(ù˜Á`{ ‹{–\¨.
+èípÂÝõnîO*)ˆVžû EÂ7x7öñ½JeW¶\K\e¸å˜©\8¥Y|[¿f‰ôÜðÃ*ù‘cû°/%O´ô¥èÏC `I•Ò@ÊÇCQ nÑC`×7”YSÂËf°•?Ó K³&P "t-›A/e:Ó(u#Yf9~¤¯cº(€¬·+üuýí²W­)×&®b ëxTâSŽgÅšC-¹³4N¹Ñ…®¢h‘eˆW ïÁUóïG2ø{a¾²5PRœs*‹J$’ïkà&ªnJ™ü’[…)ÀÆÍ—KZÐVœ¢ÿ3^&ÉqÜ@=î t`ÖòÒ·ð–ºÿÖ€
+µŽ™D™?ÿðõPtŸåuaP7ïÃg‘VÃj=gÚX\waÝE>¯›²=6ô|uˆ„f£aŒ´à”x|ùÍ¿.ö‡$ü{ûøÁ‘#aÃ_±œ Ã~tÊ»398n8°ˆO{pî¢ý"Qn0´•°íèÝ hcuÄ6H›(³gk5ùw…ק`®…õ ¢A­Ãéò<ó’díëÊ#÷Ȳ•
+˜7áè"j¾¨âV„J¬ dã°X€ë°t„wù2øY·îÁV\Öáv~Y{/;R׬‚Tôj—ûgÐ]ýºÏ^ô]^¿>ÑàoÆ43¬¯v98c¨u€W<aŽ·”vd„ðªì1cV ô< À³Ó/†aÞé,YÛ®QþˆÝ(!¼d½`KÖVÕ/I –yŽ„zÌÚÏŠÈpŸ¢õ±Šº] Å„$ ÉТ—Êþšïæô€†žŠþ}(ÊÙ#ŸI<6{qF1‘ x¯…
+6:Ï
+à Π̉²cÎ*³§“  `çüâ_ZÃx³RÓÆ3£]ͧ3ûF¿³8“Icêi&¿Ó95+šë6
+¼R92KúŒ`×nSZêÒr4é%ÝD/ª74w…K.¨ÈÏQÁJøÌxçÁ‚¡Tå¼°Š+ÃF‹¡[Ñ»Cý÷lj5>«!‘áF|Ð,\lE)j¤]Y+A°9¡sÌEÍ’ýFnŒ.±ò0]vÚµ¦< ‘.P4}Z;š‘«”mßš$ÒpÞ¢a¶ ’ô,á"îÐW{+1\ ÃR[+—ìç€,žê´þv›.\T¡ÎpQXs–„Tg¯‚I“Òi/î‚ RËÉD_©v”`•!âO±‡Ó>ÎýÄÎÁ&Â;ð0'-`x¶ua-¯+{¨›eºÔ”“H$885X$ë0z—5›ÓÚ~§Á¿Ñ©˜—2÷žc½ Imˆbe:y²®Ãùy œ0K˜8.Š5ΤëV²
+ÂSÄdÒÿõ¥{ùHTÊ;Ûºñý2ðfQI>?<j
+׬$âŸ
+¶@%—¼"]Àô¹ôPâe¾R`‹cº>õ^D4@\‹K0œ¯vÝâÂ}‹MäÆKÏb˜ísËj;H
+“El¥„«}AÄ"Îcms`Dþ.Îsð Xhå¢vLD”@}h_k§ðu/YÄÌSüš8¯z±¶X /eX²Ó,éD’h†½J|§B‡êú”öÂ'm!NB
+yeèó™ìˆÄÒ k±âýä—áXrK_¿l{ °xz|v<}=Áù4¾tuÏö·Q ÷= €5ÂÉVÉžÍöiIQr–dÅEÀ
+²ÍåQP 
+${ƒØêÓ!ÖÎ}•"ÜÿTra¢VÒ
+­¸šuÿ,÷ÐLéKÌ T›-«Ð¿Lü#.ÞÓ.i¯ 8…’pK·³ê×ÀÖ²!œÂ?mx s Ëä0ß|¾úIŽ¬1*â¿z(ú²"äQëj“„±Á¨¯q Jä?„2Ûu€y@²3­C«aVÍ/@ èˆ3ýèþ¡Å<=Ð~‹líxnƒ7Ôà| C<Ç’Ãmšo%‹‡½¼
+tíÎ6‘”b·Á"á‡<Ta%ž
+ݛ٧?ÖÑJëÀ@¼âQ Çàvü
+'í"§B¦ ¨ê•
+(ËDÂ…D3KqFô³Çaµ3²½^âl^“u h%yÀÿ)/“¬Jr%ˆ® öÀ
+8ê›1Sv‘SØÿ´®…\ž¤ ÉÁ¯œännM|9­Õ!ÆüuA¿édy͸¦F¦Í!ßèä¡fÕIJ8 7í¹ÊY'Á8]¬LeŠÎ¦“Ð$^?ˆÂó4ö‹NŠ$*2…áug_*èÀ’æP-t’"\ Påö;8x§©²ÐGTIAo=XôõF'÷¢ƒNžŠVçÏ”””ÏB©WU§”A\)wªR_åý™§sV'˜¤óPT§æI¼Ï·5ù ”Û¬¶¯l߯²çô¤ €{k6ï >”ìBù—•ù&”…_tÑ ^ì4÷Ï›¢U(Ë+ÿÁsJŠg¡”Á/z¬ŸÆfÊ"'Ñ¢ÒÏBYyÑVÏ¡ž…ò0øM(1~™]¾ûÎEˆˆC çËÐXéÒÜýÝ£ ßG Èñ¬“”pI"ä’Ž2©
+™1XËœÔ*“{Ñ.“§šE&ua„,Êi=„àY&õðS¯L¢MnZeRý¨2ízÓ“Lj
+ôAÿòÑŸåíÀ•»Ln¨Ø¿#lu‡ ÆžãY&@‰bØÐ[¼“I°ž«+öÓD,2ÉÆp8L±â,“ÛRdòoëyÉd
+\Â=0VŽóeߣéµÅé•G´œ‰±Ü„ܽ(óXžï1p¥~?·}üæNvõ
+øAâ—÷‚?£ƒ˜C6ŸÅ.íæ#ª–}6…/õøÊw†—Ó–˾gµ èî“=!uqî}È‘7ÔÌôíQ‘­ñ˜äA®;5ЙÓÃ0±ßRLx­ô%6Ÿ Ë»ïÀ°-ž¬Ï\
+µN݃·Ê5oGeî¼-;?CÆ¥ ay”vƒv–Ò¡ÄŽBmYèàqÔöÚ3£¶Ûˆ† ˆå‡Wñ3l‹œ‹¿ëN—q—©ëw-^+ž&5Zj°‰!HÜÙí—ÓU(5»*9>=I¦ãؘXý£{Ï­Yðuj0\Æ!ÐB—?j)±£–Ÿ¾³Àæt›~çW-0>ug[†½Ç?/Õ›vïÊFóU05d¸8÷æ»™þ¼©ÁÛbîñCñrÊ”È:WÜò Ãõ…®ÆqíÂ-;”ì ïrp ÆIÑᨠÉ\Í/¢*Ø@$µ§6¾“.YÉæKWe¦€Nø3Çßè;5L³AïœÓ_Á\S'šÔ™š<4ÁèÒ8*4[”—uµ*úÐwÚ)Ï^ÄwÙ'œ>Dð?þ;Åõ*ê])ÑúÛÎÚw±ƒE°Þªn]ý(!§$6`%öðĹa ­ß}ö@íYšd·áÅ\%ñŒl·áþ¤Æ†*ãUN'{Œ?ͱ“|`Fø¹î‚½­“›#5ÖÃI溰°[]“(íå=²×Ð_;Gýˆa)hϯà
+ËÔa<DÏ›¢€HóY4<\`F†Å¼8 ©ùpí¦tXÃ(irZ‘tàÍ_ó9Á$UÆ<oî˜qÈ4ܾü4_‰ÅÆcjÚ
+9‹]—p¶qÁ!ã‰R
+ÿ{hwŸqbâ–-Øë“ \,  áÆ@Fspn8†n[vÂçé£ V|[%ùºF†à¹)2Kyõ3·¿™ž¤¼‚%<X„ÏQƒwlÜ€ûB¢Ê®]»‹Ø™±| ”²"2ýΗ'ä˜P«}„öÆØÙá8%±ø Û@CÌ7åPj‘ú» sB|…ÉŠÞµÑø­4
+Š[-ÔÀ,‡ùÎñ8—}‰ê±™R<òä
+×»)‘Ûàžèð8i­‘à%Y"mÇ(gŠÿÊi(¥°_ç»q“`+öi›ŽtÝÏ“”¤øTlse0’RðÈÐÀyD¤=ƒK̮݀îGä¾}Y¤+Aœ"ÉrH$rùÜ'O~PÄ RÊ(‰ -ç(,¸á½8‘ÍÞJÐPL^³;Iá HW¿!=ã…XWëÝIAá'éÒõLKàKÂØÿÄ\s¤³LmYäôTÙî¤)MzSbp\
+m½Ùw püŽâg<¾œseQÐô™’<ù§ÝµìÅ¿™»lø˜w°Ð×~Ng«9…<Љyã#Uퟩr 2Œ3x1Ì@¢kϦG‰fɵ•`¢Â~ÓmÉ mQ³‰ò Î(oDsmî
+CI‰d
+Jn‡Ž%`S™Ðä+YlXŠp@tŒU§ÉÁbC”ø>4ZjbvŒíÑ­{0£é5<&ÄY{¢b×F 2êIwâoÓCX€}Ę½è»²~üF~/7Šò¢yHhrƒs0ÌØ°]!A?Tz+bf4š½¥ \ü}aÑqÙÍüEO‹ñ~sÜ/ŠÓùqST«“ŽTj.°Q’af|[ˆõ(aü]? Ó8ÑG|=rØLôî/(“•rž !!c6!æéSžÝUx•ueåAûÁ]ÙAØÜÙȇ›¯m?ÛT¦_” fåŠvóå4‡å¶oÇapÆu®|Z¾¢yË]:rÏfþ©$=íl‡hÞÿŒ—I–¹ „¯¢Ôã<¬µõ-¼-Ýë/H0«ÿL¤[¯Ýý¬*ˆLБ,.Ñ)±‡#/ØU|]} ŸI­¨Tˆ¿ÏÇ0Ð ¿lAÄ9L,/ÏI²$Ÿmž<—³pË?¶¨A˜sÑèv .«Èô3n€4=ö—Šg*zyPÂÌFëÿUÑsýœëþ¢èF þfÝŠ~Ân`çöÿ®(â†]jF×{:ž¤y ¦ Äw•|íéGÜ ü œTV*h§àžw)"\Ü$ö³¸yW%îàüM7ïRØ‚åì/£}=¯>™¢‡üt¸‰WÉ’B,I–¬‚¦H“ë5ÝÄK‰´µoí¿Gâ¥(ËïË‹Ôè&^•dàÆŒnâõJî‰×«¹%^•0FƒÀKÿ*ˆ²ý‡¶ï‰WEXg;—é&^õfì
+KCdq3/%øq²UÀhe¸g^·èžEþU€wæ •5'
+u03ÍBĂq`d·N;E•­1¤¼M:X^¤œîò ó %ñÕô’iVè*%¡›AúÁ[Wº0Ú©x$,…Hîœ# ”qeÓç>G܆Éwgõ+rnâÇ‘¢‡Ë+°+…°dóŠÚüØ ¼ºÞTV惄â˜ä¶¡Wx¼|(¨£®0y±°W&>Û¹†>ŽÂùß.¸•ÅÇyo›]¾pftg­„byd꧄k°å9Sªº„XðºsSZÙj2Y,
+ †Û›j‰<î¼ècš6«¥«}=Ò-2g¯'ËñL #±W±sbHÛçœ
+‘< í-èÉˬ„ôvŽ8lE~nCaEÈ,Y ³o_y1 X¥Áœ]‡¹©†~©ìL¿x*Èt…§_»ŠDSøIñeñQr³&¿mwÕ¨$£ï}¿E¸c‚
+ð_l{Ùy™Š:ÍQ±Û å! [L†Ç±üçˆ}œ²"@´^M. KÈ,Ç¥Œ`Sɺ[^½LãÌáæ<œq>üKÅ
+ÇŒ¸¦ør
+°Ö4b†4}+u£ÇÏ9…ævÌÀÍÖQ®Cƒ¨pµÎIß’D;Ô—’8˜r–t´y]u/Jʵ’ÆbçÐr8K|cû Åfô…±ØUp¸!^”Ãú£¤´µ‹I°\OÔ«æ‚M‡ÁSƒá|࿱Ié˜gÌ`æórˆ¦ ‹%h^èéÐö†ñ·ÙÚ™SÃb²/˜n+‚_I9ƒ šó>Áb0UæèºÈ÷(5ô±WºD#±4G}tÄø͵u4
+Aå7fƒ†,.C:¸FI) KÓÌÂÒ¶À„£šqhz#Ú0ñ†¸¢*'ݶ)`Où¸nVŠÏí Œ¥Îi:EßV„ÿoŒ³lyÆ#‰
+iÚM¸3½
+C&Î]B÷hú,«aÿÝ7ag±I|sÎVD$ö„ »©ÔP$ÆÝn‚uåvi7I‚à.åI§ÄnbÅyxšùíœHþDõú·ÒLŠööñþ(æ•ñIoÍ%¸$ÐÜþ=‰g_
+¶¤i½™ø¹ç^\¼­¯¿ü/™CÎ
+ÛY_^Ä¢UmXÃ?\/ºwˆ'¹âYûå÷ƒ×¸™Øó2§»ê>îç1Ì<?æ=ïQw?{ó؃*ñ2{1ÿm~¶. Ð
+f|£jNÉÁ_ŸÀ «óv %·( Ø« )¶¥Ák©$âlcd!y„½J¤ÁɯÃrü"¹,Š>N>ìW"NMsŸ#˜ð× $ûÜ4+„¯!¹%·tûÛöW&/ÖíÎnEß/E$
+¸“­.¹Ø’óçeÓöýfY,úfKƒfá©ZêįDbÐÔ
+׬}=»°4ëmíø ŸJF
+ÖÝP1Ðà,Õ—*ë ÷›îE$H_£Ùú2Db j}ˆBD‹òaQªam€¹ªtÕx"š/ñkã4/2U¢n©s‘5šJÂ5@ 0©Ö¹ÌÃIì&:‡hí+š=RQæÅlyèjkç*X4Ñ6Ó¡QELâ sÞ@40ã# ck´ŽÍ‹þöB)e¥6ës
+U
+ÒV,ÂÚ¶áXAä«T9y;
+mè…E*õî3°z
+M’Öï.ñ"á÷ÉžÞ£ð«Ž6ë]md˜ÂØó)3Ý’Èö¡¨×´äôüt1ýÈÞVÙ‡{—×°ç>é=3º¥yÍž^}_¬Û¦ˆti÷õ;—¡¹^æ2|Þ£.C|-ÎeªÌ
+"[ôÿ;,¤Â#{‚ŽüßîD*X¤Ÿˆ 1ì0fîÖOŒ ëƒtÅâ@þØsÁ/r¬ˆy÷Vß™XØyb6AÂ¶Í QË9ˆ5;âÔ([Ó9 s™‡_ÒI¸+Ö²)èìÏpn_²>OÚ@­s+Äþð†Š‹a.¬™Ù¢ Èë8”žZÈü´=Ï'˜Jì"ä0–Mûv{ý|²£¶Ê%öEÎì™|! 4(ËÆìU._$Uh^n'; oä=/+¿D±nêcw\bÖðÊ}˜Ûÿ Ã~ñåd³OÁ/xý|R%ó·ý
+üû×oÿÁÃõoahGćk-G“ßYRÍ‚«®1⃊9Ú‚m«"öj:[ ¤#XÞ ö›]"øؤP©ªGƒ(…)òU9ð}¶ £f}ÐQµRaê'x㟿|LV”cÄô¨^¥'‘âÀ©“àúÿê­/ràÅu?ÌIÓ
+s‡¤r͇R‘[r[ÿゼaT‡ëRm¢¡Ä¤øÓ^ôЄÇëÖŽbeÈá¼z¤TMv`A˜RŠ'딊­`Œ <¬-HÂ<‘£RŸñúþ±ca!3n½)èú¨Ã‹<i·ûòu‰0ÖòFà<ÐÉÊ/6§Ô
+ ™„I,³ÚV)¸<ÛXs+÷ÁŠÙ`0µ¬ýl2I›uí)+Äõx¦Pæ-‰ÀBÞß¡ ðôÕO5ŽY–nHƒÄežÊ™v?‚)ÓJCnìŠß‡²²Õ‚–àZh¦Øað>•T¤Ü*2hF¢‚E,{÷tÖ"b0ŽÎ@ز)–x¾€£"rY§dW#/bEÆF6 Êðzêõó ²Žê_ %h¬NÛºwýN×òCEðZ>·‰"h*ßcÚZ¹òS°•`^À➣cì õ,:Äf!+D’T¡&\â ;ÿ [M=ÓEÀ™„Ú脉çóBË?æâšÖuS`­åM;‘hØû]ó†à±êc4ˆH¡Ë ó®ólˆ ÃE<õ
+®ÂÒ#»m†Ù‹Ê_d%Wô®½tÄS3AÖoaÞ}‡MÍA!$™?C÷Y ?ÉRƒÚaíæQ©@2h1ìñ!¸ë‹7+x]\ç䌆¬˜÷x[»‚X e³4Ývó²Ào ÛÊGxÁ»Ø¥û,8j¬=ŸÎ–u9…­W܇ÃT/£%Ü–ûD§å§Êy8Õ¾SDA4»n;þF’|mèÄF‡#RQªêG³ƒ³d{ëÓ“Kt.J"² Ü+êUŽMDm{jìâsŽÕ"¡°0ª4lŽ4lCãÆÍã6ù(&
+8›ø:ƒµjÉ’ÉÞ†È5eYtyJ»ŸPÕ62sšË<í:EÜ[ôï®ÑËË&¦ÒÒQyËPÊzÊÕ«Q+;‹cnDï¯ÅÓ4¶,êdµbÙefEYN$ñº¹5|Œ
+õŽVÚ—¤<C
+厞½@ñbSfrˆpCðHÕ˜lz0H8+º?q¿b¼!T‰ic|¾÷ÃnŒ)l~ò8ãbä™
+f9Víí† ³š™8m+ýí8B-؆°1<UåÉÄû¨Þ ‘ïÃot©V4Õ¬ž%EŽ¨)£Áòn½ªÔNÄNBmPµÆ•ûÝwpÀ5Tó(Ò;1]r-“Ú<9ŽAšä?àyÔÒ( æâ‡KmmÖ…lõëŒÜ‚­½)‹Dz´ÐN²×ìì½òäõ¼, I{HzýcÐÛþý|²¤ßÚåÇï‚f=¡!jœMý_‚^ëœ"òÝÎc: aÕ¡9s<óÑeøj¨Bm{"íYµåLø•gÚœ%ö¦Î̤™PêQú¬¸¿Ã}ßÀÇì¨ÉŠâAyŽtŽ_ƃ,`…bfÜ=YÇ÷¬lwrí èû„õå«\'&‹¬yñmc^!fß‹­ñƒGا„ÒT '7oö6xÉFÒTLÕé;H6ibˆ#εû{˜×èc¼½ð»õ7MÕ‡çx#QæLtܵÍGÃúG´.Þ8yõLU¡ô3ÚWÖ¡ñƒDÄF+lîÊ‹¹(~'›Ù_“jP¸ÐqàPá’£û" pŠ¦A(3N™Q{<Hù"Р(eÜ©HT~$mÕ ºÎ¢®œ[ }©>Éðt¬+{>kuäÒC’áÁÉF_.iCUÕ•%<-tï©%‡+4ÒÒÖnL8O Á‹Z¼Ó˜5
+«Õò†íX%¸ªœdÁ†°•˜™ù<J´E3Íö,2õ¥>Û
+`™ sš%†$G~Ó‘{™ÇTåy b#hJ
+†d®\ð£ÂúmÍS>Ê‹mp·ç~©HÜéìâñ‡Æ¢Çסդ‰ìŠH‡è Ÿù9‹/ŠÚ=÷:ˆK©òr¯
+ü¬r=&Ó^·7lJ…²¦Ý
+FÚëPñ¸þHc؉„ w¢‡´Ñï HDœ™{‡6€?ÒOÔö;Áéf…jðJéF†è€CË6>= ò9œ›o„oI&AÊ0qCÆEÎ{#H½:õOªs…Ñ$H$˜™?_ÈOm‰EÒ樃 e>Ž r1Ý–!]w•B“ å„"E.#× @×e;á!í6H$ü}¥¶ñ&@žh
+$ž‰kÉè–½ËíÅ©ô`Ûôø"zç-PÕ
+H
+W5/Ò ÈD˜ÁÖ*!âÏNØW°¢4Ü žñ e33´išA9&‰?D_S$\g²C4$2qZ:/ìOÃ]9Pû”m•µ^A×à¹Ê­bÔû~¨åNYƒ Á3pn7ÏŽ‚"+9‰ÝóT`ÄN„éE¼–„xàjø”S ï/¢ wxRÅ(IS÷z²1í”+
+jJ|?ºÇshÁÍß4XŸÒtk¤dÒ..å×å`79
+Êz!o× È'L¹qGò—½ïBÏ×J¹þzT-\‰~HÃü’Z°‘äk†”Î0)n®„nHvý$­w:Ÿë4ê…;ºyß#÷ÊãŒ=…)©Œ¹ÒÚ;x¡qŽæ$ˆeøq;4utž´Ã=­uhY¢‹ox‘ÇãEâ § xÀý¥‡&ù
+èXsëôÒN’òW¡X’õ%κ’í­ÝÖy;vŒ#à5†´¥råcî5¼1DrdGá–ô§aÞ LáZ+›CÓ×:P?ƒ'šÖ€7jD}F_$=îF騧þ] CÌf´ïÑìMôu=Þó¬u¶D ¡â u500Òø‰ïëvhÿ
+ŸÚ‹äÕ6ÿK¯Oéµù“æ˼Â6ÀXñäËZVaZrLl¯x×ux-í™_¨ *1-9·É‡C3t=ì¶7hÂ(ÓN~:9Åà0•2#‹SyÍ£Ÿ†ómÚ ¯×– Çe¨è§$RlL‰Á¯*ÝYh=‡1ü7[¨ƒÏ³.u]²@Oùý!q?µRvÃdnœlâ¾ØŠh2/C&•–U¼kò(ýBæ`kÛ@.JBfµ¼ÃQI]
+0Vö§àcl‰ú^¦^…4tÃ^§„uë@¶wê–¡kÜÛ9EßÃõ듈
+0cM€ Il†ûÿžF@J² ã9 ¤J ó;ª=£M¾‡YªãŒkem\;¢Ïx&b¼NMÉ8·ŠÍÎQ˜L;M8%M^5ö•4%<N
+H‰ •gWš …÷ã̉™Ñ˜Óm±ÆG$0"Š¥#Ò{Çh4QÓ4vÅ‚ €ˆ
+"Á¨("¼‚=Ùdg?ìÿXÂsî}î¦äZ[ª¯˜”¨xKâŠwŠU²;Ã{'ÈOæxÈ3Gkó霜ºÜ…Jdå]˜’Ǭ b‡MBôÙbkóÙâ+床”ìÓ
+ª¬oš€%ÑÝÓ9ÛAJ2¼Á't³Ê¶´csŽæx(¯yÏ3ZywCU“¾3JÎö ã’öõ”× &uR^3Ì{2°qGVvåfô†ãUv¬û}ñíLúæ
+J8±6”­uVÞ\iƒÄ®´W^Yl}ñçj7ònÈÌ©VÂn•'^ú‡òèç=€p0/©÷cR×z¡7—ÞB.­|D^ÿ2DNY£=ýÈ.¸ô–úëÞ$1ˆàÓŒ¢€Ÿ·>„H÷kj3£J~tž µ}"ähÅðؽIvé‘•Z|h©qæàÎVÄT¯†ý|î &A#(¿Ð q;zN±GKËuÖ%ª…WUÐí€
+9YâsNœâf÷8©pT
+úë#Wþ½­lù¾!åûtøg–VPŒãCY®óôÐÖPº<„Ï$€ü$GgÜýú¥µï»[Ùöm±¾2j%æ¯UÝZê‡ß_ÇfyôB˜gä×ðK
+ Î÷¨øíQ8l"×ð]jn,¾.¹l’åÿÒGÉø§E ‰ ëÕÛc¼wOýãc‡‚Yb
+ýSü2ß8%Í7‚}x4+#ïè¸{'ò¶š]øÓEˆ Ls+¶Îv Œçkƒ¤Ü¥wø¤ÕN|ê¾E„ ™%Ï(+/dc£¶FþμØE*“V¦;>â‹¿»ä²¿Ý2É©O¦éë*B²W/Á»Æ¤4×
+ðE57í_»#ðGß–™U?¾H¸+ƒä”Õn|btFF<[lVœ­¼”]ác÷gÉ…[#ˆž>dÂñ¼œ4‰êu
+èu¿–U4 ðÁ."bžgI+š{ I4¿.¸ãì*¾zlg ŽUîîªÏ þù¡ULX¤$`VFÛtk.éSCþ¯9ìÚ®NZ³9BÍ°wÀ¯›šÊâ]ŸPÌ\øU„ñëÙe†ÖŠkæx*`–â<*zŽg öŽ½½üê¤0ïòÊ{è­3; uº*á, òu
+øõ€ž[4ÓÀÞQl¾g°:3d æ¸úëî›[Êâ]5³×+,½9¢„'mNŠ1€õ%-l!Öûñi“|Pì//°0 Ñ!îÈ)¦æY{ lØÉg+bãSNbFxš‰ÜP‘òÝÃŒ¼ùnZÖ¶ƒ9sIù[£µYîHlÔÎ#í;•Ê¨«¹moQÊZ7HA=5/d¨/ˆšé¥¡v™«‡òØ3FJ_鬈 ¨ñ©žBÊ|+ø¢ó]iÌÖ0.ùp^NäTŸž_ž‘ÖnS’ý”ÌqL¢½ü»¥éùo–ÆÒËÛC¤ÂSÇ«Æ]«0
+*"!Ì?LË&y°C«„à×±‹W>aï-½EÄïjxåë*&xþ5üòZWÝÃs¿RÜpiKopI[}ä´}ƒ jgŒþÌ3@xtìRÓÔ¼½)⟟2sgYÐãY0JÑæ7è;‹¨”ƒÐÓ mœJÀÌlS³½c„̈‰ ê˜ ÏùžåefEøm-§ÜÜ[z_çÓP2¶ÔÄäϽ˜ûövø£yQݶ† ÞT3 ‚ÈáSŸó“Ÿ
+â‘ÐjŽå@o‹°OB˜¢S ¶,eÀÕ}×”OÚ[Ò -ÓÖé¦_Ò­3 7|+˜¢%¥á³žÚz¶Í¥ø¬ær Ë%ÄlƒÏëù•iŽ%Ø]¯²Í#ïy…„§Z¥™€ÝÐŽ@.†ehDÆG¤˜W€/šîÉ?7»wNN+NóÌ·gÆtœîý™Î,ëd˯±ïçì²ðÉ-"$¦Æ–ÛíÙ³€÷KØëÖitŽ¼¿î±W‘02§:fÛ©† ¬÷:—Û²v'ë.臊 )ñ5€'5¨'·-3½ù9¹:¢"OuŒ¶€óÌ)†å}”ëß ½LYøü ’P~´Ž~â¢AÞåžÜ„ŠÖ”Ôqñaf| »v°Œ.ˆ™&QãÛ•Sãû³È¡öD‰«8Q’ q Ü›ôö­T¾u©·"¹5Äô¯"@^!<Û½Ø|ópº%#ª¸m—C8Ùâ’•· ¯ºóƒr>)¤à¢>™1-¦Ü¶ØpË%„fE”ØêÔ›žÜØ[Ääùå¤êoÜþä}ªÃT¤­yÛïªnê_Wü{ç]óµo‡Ü¿ŠÔªk¹¹?‹Í?5rqƒ|b aÂrl©WÔú0²Ñó,,#”…<ÎïåuÅ(Q³P1=×Q¡gÛtìg3‡î‘J÷P91ød{|2¨ Mª9–‘kB
+r}BßûË܇ŒiúšÍ3÷̳íÙ1£[Ê*ûõ}Ûƒs扆›Ž%øÝ SqºÍÄ'Ì<žè•ÝyÒÓïzm±1!5®Ü/ítÙ’å^Õù5ä±–Oû´Êls —t“øGöµ¡v×
+­ôLß×Ü@íÏ´Üõn ŠŽuxpÂ:ôêÄ20h| ÏÑŒÂn
+iˆ°iýIŒ+òɉ•Ac<±Ç¡»ÄäŽ%b‘\h
+pPÀG51Àb&,j¤Â<âgäEkfT
+ÍŠ+¢J\YTÝòK¨U!5µ9¾ËÂuDpP~ê]Þv̯x–;ïGe<tL5ÁõKûóä’O"
+ا Tz$è|û"Û6¿­©½¤®H \—0r ®Urù}g†ize™\–6ßûââî«Ö»ÁU|‰v¸)]AÿÓþ®-ëOã; ÄTZçënxÖ®ûî%l}_j™ëmמjû:Û4Û|GŽuªúÂÇ ðÏ^qWNHÖó$®!TG5t¸WFƒ8%´*Ÿ’×аڼëÐáBË Å`YÚ&¿ôª]ÐUVR‘)ó ; À”^
+¬Ku|ÈϺáçç\èùÐ2 ½×Ïv˜„ˆ†ÑÕ tŸ˜88Ûbk¶q¤ê¼‘WwQ?\vÞ:Y™žP¡+Ouƒ¸½™Þ<ÍèËóÀýîG7 UG"(¸Ž*ôˆÛÿã¡rƒrRE@ÉiÓN¡ó_!Ÿý”«¿ú‰nbÊ€7<J±`ÛBc†}ü‹o­ôç—øÂ%éÈ9’!žù7ÅasNPÖ]šÚéç~sp'ýjÜKý¡W½b8¢¥uEMÔŽ°Òâ^Ç<?–jÚ¾¶ÔG6õHÉ"¯0ÓU<XQLÍÁ9–»óÌS+s°;Iûƒ°ùôË>»È¥I ܹNªHZG'½R*Ôò¾=SË«¼0Þ˜þ÷5RÁ¹ÃÙPbodÊ¡b©ÆàW÷fQy10#™X丑EŽYĘžÕã<(¨¦@Ïv‡‡\ëÔÚ#¡<eéëþzÀìûv8ü:¹ËaþŸ‚Ñt âÔ®Ž÷ZÜF§ˆV•ÜfcÚã»CÃ_ìcË_ã’Ó}ǯ%78×)•Ç›#ý!5oð»öÏfjOrŸwKºŠ¢®±-,eà¹
+e¾5&Ì-ŸslN¹e<ŒCD)Ùÿ€Èü8¾°A-þ‡Š]ò¯„ª·6ù‘ÏuJF1fAEÀ,·-Ñ^¸W(ÏÝ˸ÍHåÅYÄÿé˜àËÇKè'q5ù¥CŒ+°¯ôÕ«P@–Æ«/½Aeþð®ç·ôüÇ?%-,bÀз
+0yna÷£‚TdXÞ‘´ ’Ãsw¦Ê¯Ø™ àAz>Í&"~ZAç¹D„*·˜XÓ¾°¨g[ ¬_„,0W^¶Íµf|°!üÚÞÛŽœ¸šÞúÉâ:b­s¹%ßü¦<ýàäf
+LŽ¾µà“…Ûš@^ù(Ã¥Öù¬ø
+YÄ—»%ÐÌ­Ñúó–áÚ3%³vß$ì ,
+,ËöW;H_Âä7p~;C::bGyÖJÃZzCÄÈÅmÏŠãFZãÁ&ˆ
+óÔ§ Áv¤LèÆ;ÌuÇ$ò×”™ ÿŸ»æp‹CIZXˆ¯NïË&@K¨ kÓ1þyR•é%ìü–¤ån|•CHØØÄè
+’°2°#šÜä÷|r„I+‡30‘®9ܸ@}5·þ»ýl,iyú4¬ïcûUÌ
+¿›½ñæÉÙ Ú#”KG–ø·ÿìzÍL™»Aðèã­Ð#§–ìʱ·"RÔµÀ,4këUÉ?⼿§ÖxäÀr/Õþž]²ýž^èƒg&È»ß-Tèï6Å¡DÝÒ ×ž·¾†_©{‰^y7ä×
+ïî沨ü¸m¤)#ª~Æ‹ªGž”Œ{ªíîÎ1'¨æÀºnòG9ðÐÐý·APýc@‚»_ WîXTK©Ú'äïª-ëïŽqB¶ëì‚OŠ½×±A7âS÷LB¶_ͬñHQY‘eby|¥“¸«¦W9'ê.:ÇþZ€eYu1ãÀ`Ò<2^î"T­y‡v6)µÎÁ—h®ÙÖ<‚úÀ.!ß±OQïí.²b.ί¤–î鹄ŠZ”csÀÝ»¼ú¼øbPÍŠki•{zaGDß/œê(=ªï‡\Û‘PGU´†ƒJSÊHƒ€ÞT±þqÉ-c5†—€ËxGQýO‹½° š§L7ØÅ)M;*a`5;fð9+¯Wí8o}} s')mãRöVH•»óć<η=âÏ›=¢Í)b‘¦šÖð)ã&.Þ¯À,t—žZì-8êW¢ïnñÁwa4L0ËŽÉ»ª~™]7¼ÜVä”4_sN 2ݳ¸› # ‘²õtoOîØFЙÑ
+ zíåãÓ‹‚{Gô¢’¬`¯|œlÌ
+<e-7=ÓÏÆ à¼TŸ¶Œ•Ð¾xð/û"7¶,üó]HÏ£xWÅm-qaa5­:ªaC]3ø{2Þ½¿M®ü% m-O­
+ùc/°#ë¨ ‚ßå¤ïâêÞ"©l}äáYSÉ? mE!-££®¬¶å%u\4˜ÉØÿS\ž_i¦iÿºûiÏž9ÙrÎæÃN6lj‰&nŠËj,Qƒ U©R^x_ªŠh²)'}¢±Œ
+J/¢ A@z[Ü™ÿc_ÿç9羯ë¾~×ñ—µÒ;b†‘ºÍwmW쯯Ä5¸æ¼cBÓÑC*rÑbðNÞ0ÒzlƒH 0”6²ûvÞ÷ÝPAÕßd­´Þ¸…Ý\£ÕÇ5´Ö„†þ8kó›5ª¥5…ÔÔº
+èN›§¥¾%Òƒ¹Á’õ‰–ïfÉ•M¨‡/\"AÁ&áóísÍ‘îÅôF\/ )H÷ögZ¯.2oþq‰}÷JXN‚;Þ³I×,»Öú
+÷õþÚ‘V@ð|A•À¯Äû¹ýïûŸZ®&4ÃÍyÄ8vÈ^WéÍÞ呚ŽdüÄ=&ËZ9ýY¥5¸ÜûãÞÌã?G×iMð„ŒM&‹ÇXûËÜŽ˜N†×Çiq=ˆÊZy„#-±6¬%T‡×Íq“¶p1!¥6mÐq€Njé­E+½çd‹I>TýÛ¨0³ÛŠ®É7jZûÎì@©ã}×5ϧþ›i ³?fRzñ°glß™tùURæÞò(Rÿº§ró-ú¶ã]Ïõ[Ñ´ýâM&áûì×JH-0g—Ê’f:níô+•¾elyÒÂDžzD’ ÿä'Ÿ’õÔô÷½Âœº'¦~õK^žo³ðIåÀ]߇ºo­MW]³ø†#³tÜüµV'ëùÇ™[<ñ[H:sîáK¾:XÔŒÓ]yZv°ÔõÏ”âÜÏfÝKäv…´ùÊ™oâí…ozéÌŽ'u„¦ƒ/è’¤Ä%|TÃG…×
+½Æ=7xÝþ²õ›¸b¸*¡$×çtLıUDÍÃ;Ž+ÍI5³ýÔ!d‡×ˆ÷ÃJ˜'t¤š”™Ö7Ð…M`ä+Ü1’&:¢Ò¶IiÊ&ODÃY P¢ËÂkØÊ W•ÔŒ<9ÞÉ-³=cf#Ï·AxÆä†ä±*¸<P–ÒR›³F6:g”€YË‹×îù‘J¿‚Óu™¥Ñ5nwB…¯ŠÂz8ZBWì}ì»~lsÎœ²×9›˜Ñ0Ã^D&´,Ä‘‚ð0ªÄþöØýô“;ï{oÂÜÒñ°˜ñÂJZ{JkÅÎ!œ;`Æ¡zæÐ !Å@yÊLGÒÿ¤7'¥9›ÌÛ.÷((ï-ýêâRs\JB`#:^ÿ¾œÝ·LOE 2(aâzNoh•XVk³
+g³‘;2òñ!Do¼|³£|,La˱M¥¿w|aÂìÀÿ0í,lD…¼Ÿ¶0ºã—^5Ȥaý³©Ýyê}ÿ*³5»%äf·¸Ä¢SÀ-8! ½É!„uÌx&˜¨U:ß@ #åqLM¬Š©qrBKÎδC:ÛIwå`÷¡‚…øÅ'ýpâ¹¾Etip}sçMç-ÿÂÓêÿ¿}8Ý@ur»k]Ÿ¶ABûGTíÁ"fLsq›Žgʉé…ø€
+BÂï5¹g‰·k¼î Fˆ:ÒJˆI«„3‰)a=ȧ Öx‰ånXÇÞEòCÿ
+«Ñ;µÄÔ¤¼mŒç° ¢g´Âw¹:°Â¨ Éù]!¥ 7 ç4åôÚÐ2¡<³ÁèL˜™O”#U_†Juâ¦?hE5¿ó~F^Oà ¬
+ldÑB눯k¼ Ø›îOÄRßíáÞ"ñ¶ÿg\EÁbÓZKÁHpµ3m7B‹ý%a9¾2·ÉÅE5´ÆˆšRŸ2ý9gðRïg.ˆß¢õCw`Öz’s>›‰;d/ý
+v[a‹OIµùMJÛ… ;BÊHV7舼 ³!¶"¥Á?ˆ©†îXxøÿ9'Ÿ_ا_å­ Ìrm£`øP'Þ[ Þ-c+çQe°Oþ•]g Š–q k’á¬D†Ô£ME»Lš¸(ߺl÷sçU÷LOɪ¸æO;‘·â:>aW \_F2™´°%Ï[™È¤~¸~wùƒVVÿmXÙWQ°³0'n‰$eÒ26ëÄ%gl¬þ˜†ø0¡%Õ. ”ù1åi«€^tI_dlbntìk¸½'["VÖ
+öHzSåœã“Å]¡(bóìËÜ'¦ŸÈåÊileÂ*{žß‘Ê2["vBÏêñ/V;
+œ—­Šñ9Ð
+É`Ì€‚³ôkk¿Nº$ž\yN9žáóV/à¨î‚SÁ+-+¼KÎNZ¸-9³!e \¾–
+<Ö¼öwr}’TYäRþ9pí“)þí¿fMÃy+Ô•ÑA͇°ÿÐ#ç—œ(eæuœÄi³R°=3ð`šF¯KºÄŒòªBuy´¥ø!l`´¦ÈpiU9·
+RvF³žú½~èJpzÙ¥Rí®Œ=º’Ü
+qÖõôUamìÙÁ†LR°B3ó^DÏmŽë¡;»ËBÆA@ù {Jø"c…û?nÉÕ~À[~™<ï•ðÃfñ}ß,|'nâvüg{üÕÇ-õ‹¼ ¡æ—¤Ð¾_&=ÚV<Ú÷Ëe»^5ŠÑkƒóŒ[q³p¸â}ø¼ìQ+AÏ¥0vgTÇnÏ:x¤Êšˆ–]’2/ÿXÃ}“´°h·Dü¬™t%ƒ1ÊNiwI<X¶ úö€÷>zTª¯JUr+ø ÷Ôm¼<¿=ǹ0ÊÈ“Z˜µ<MÙŽ†µ
+Ê1û¬¿ì<±5û"m‚&NcÊÄoß[–ó|ã?úTã%7:œµñ@]L ÇtjV¤LÅ=)=»>m„[Až7ÆáÆ]›ŒyàU‚·T I;BL˜G9i󣑸AN‰êà–¨ŽygóÍÐ…°ºž4òÛÁ¹VÿkrUèíÀ÷)#§)kFzÃsìÚÀÔðåõW¤³·¥âQ)3ÎQaDÇkϳï&Í(9e<
+Lφ¦ Ui=¯9ƒ p%»„±çxô¤ä@i@ïM`·âò®QQÆ*¥úøäÃ5˜X\‚»×QîO9–s(‘•Ì«ñE!îÐ7öto…ºû—"sݧwÞª‚Ó½ú¡¦]°kröqÎ. –—ä¼}ÀJiløf\7t=8I>çzÒòÉúK¹ø"ç^Ê,gº^±[”äKœ„›Î¥ÂûŒÕ–Õ1nå@Ï˶ݞcÜÜœ¢^Í»ÄPX'!­M ·¿6‚VV(ŠKRî,Ùè ±ùî¯Co;¿Üó)b¼îŧíŸÇÌ|.ð²¿,>¬"С¦ø'q§°±¦?ûßÒsž'Ó;@oI:2Q\öŒ %ï
+vÊÈC2eeÂEæ_ïÎ:(Ô…)e…»çÃÄ}£”´ëAY+ò½ÄÝðþÒõ÷ŠOŽ–}Îñ—÷p{#:굈jÎyDtÐI&+Ër44Ë®OYÄôÁGS•u‰$ïôG´ÌÚ- ûVÔÀk)¬é¿íH•¶D¢˜a ¥hG@'º^°Òkÿ€Î÷bZÅ-‡óÇZ1²š#¨6gàíNø=áBÞÊj+,‰©I“”×
+ï…†®{':? N÷)»Øû^NÏá›XvCø(oÏ‹B cÒ²˜„”2Â;‹ìú„íK<¸ŸTqJi¿÷ éÙ˜è;›ª-8…ļ[<”sŽ«âÆg#:5èD€ùŒrêά°që5ãÊÒ§Ö'zN¥ ÂNÀ%`×!¸mÚ½ôoÚyûSÂgà_§ &Þ½”‡ßÒ0ëv
+šÿ|xh•O ÍÒZâF!!iaVTÊ°ÁoÌBÕ!-¯)fõFµÜ†¼…ÛV²sq€{ú3FA'ÈZFΦàîh‘vàÛŽ­úå„žÓ׳îæm9º
+ÞQ/DuPKÖ&…ÊËjUeMù0iâá-š?7?lø x³?ƒÉY¾×”o¶5¬ú46ŵ¢ž
+Èñ’kDä›üSwœ˜Öüis‚\fƒóNtý-¢¼Q²‰v2æž…ŽÖeèѦ\5
+º7ßpj‹žQiÖ!¥‡5Œëi3£!g哲–ÿS\¦OM¤yµµVmmÕÖîlíìT1ã0医«Ž.53Š rÈHä¾ï¤ 7 㢎£²¢“û !ATH9:ÝIçtÜÚÿc_ô»TWçy~¿ï÷ó‘1j5è°¹ŒWIKØÅ„l`ún185_òÈ©y'·5k§Õí.Q.$ôBÞ;¡-†¦~Ž›@'z¬bhä ¥u’«³^f¶Ái?0Q/íxD,8}p× R0#3ónˆ2°®Gàϼzˆ;³ÄÿöOó¤ŠßoÞ¿~îCL{3„„àîhfKaHz¸­/†UÊÄ:³Û¿Øý¡÷‹}·ù02¢4ͶV¾ÑQ®6%Ô÷a¥àCP<”[çRˆÍO$5§í¿Ë»Ô̼GÔWô‰ú²NVÃî ©¤™V“u–ð)¹ ù øÿ„œ[z#i¥Õ.oŠ)%¿¤0j¸ÿ&à³q=·%µ&h’Ós.z}jýÆÙ„‰ôí1è°÷Û¤²$ka$ÍÜƸö#l“L  ¼ë˜CA¹:”6Kq¡EÒÙýzæö–C’AÔ#§Î#ï[Ôƒ)§–w`Õ²â:yëÛÇœjëdÓ§ÑåÞ33»ùà%¯9aUõ¿]¥n¯ŒöﮨH¨UN>г®„öŸ~µ4x¼kvò÷L¢–=“Ÿ´Ì{ÿE—´ÍO"î1qìåpµïNWEÒ(èÀ<£üRxŠYe„7&YOÊ3>‚lŒ©RvùØ*ãÒëÇ„SÀ3Î V% ÌœŽ7H;›†—4H:s616³›ö–¨Õo—hU»ËÌ‹’„94Üø ^}äñôë'¤s¨Õ˜µ3ë3VZãÁÚ@mLÏ©O9&Uˆgj,f`ÖEu~™^ã5§×¤øÄ
+»öæRð~gæWxC-Ú3ŠZ‰ÑÌÆì<⟽‰øÆTñ5N£ÿ.î_áG½WrN/®× ûï±Îî>—u$MzÒÄjÆ\L\ÊĨ/’*Ðõ??^þ$x—øýÞª°Ñ<Ûù àà&Ô)Œ.S«ÓFVâätÂ..iwecŠ¬b"j¶F_rêJ[š±bH3’ۀĨKDË:xxÄ.ê¼JF12¯+…§n‡ÇgC#꣠Zšµ«è˜båÁ½fl¬ö§¤Ói§ˆXA’¨‘ôâ ·d\b2êUqs>í(꿽Š…æÿƒ"ÄÇ×C3™uqWä~ÏWFyõ ÷dÃ_]3ÿÜþWw ÿ›x
+›e]·r¨äá ¡à–“³vÉ Ì-¥7LÄ!%dÝ2RÊ*w$ïÎ9Õ 0TÚ®$më˜?ºú*Ó&A[Ù§d¦@&\cÒ‚W ܓבõÐë'½ö£€>mÏydä¤]œEÒŠÚ !Ø"%fíœæÀîdàfÏ—Àwˆ7p›† ;Æ%¨CËCj!âÜì“Ps^V[Â4øÃpÙ¼ON?
+ÌÞÎzº³¿®ßQAÏÑ»·§ÍôÚ×Køs[N¦Á}ƒ>™ÌG¦ï8U´ý\‹ÒKoÀza[ZϨM†€'±®æì>꜉¯›bËŒï6~ÆU„ná+
+òz>í‡ßôtÆ¥„×m°œŸCBŠ¯ŠÛÞ>×æQztEÖñêIwEôEß׻φÏï-‹›b/”„Ìš|
+ŽM–#ã3¥-•´¼5µh ̯d—‚
+!æSp1б/»eßLùw ÌÉÁ*·6¦cTïë}9§RðÛ–vîoeŠ‚ÖÓóÛ#Où5[WÏÜbÒ­ 6k…mÊaH5ñá¤Ê˜%=«ü« #óòî
+õê÷äGÄÁm‰êˆgwž ^Š,³ðoÌ2:êÓŽ—Á¬gÝœfÄÉm:;pЪÞ5ª’âD ì«;Ký_¿yL¨L<£TåmŒ¶ã‚õ.¢Q¿ÛÖŒƒ
+F°.l$_ȬÑ."f æã‹ÅPÌ3æ–÷çç”ja90"Ä<RbÆμ;d}i›†‘qL*’æ)jWç=™ [¥ÝY§´/ïQP‹¾>öÝw¿í ½âü ß䵿äÜ|ñR2êP2Ó6ù@Â$ïI¼„ˆû:~CøNûçQð­I³:k–à0à©¥ ¥°‘b% äSâ÷ä|ìö´P•6ãOÇt}§sÀŠ¾qMÁ;?avu}µý÷„|¹äöŸìÝz-¼Ì¨Ú3ˆqÀÕ&36%es‘øÍÖbGeÁÉí8ôɇsá@tu¸1òœÙsî•„e\
+₲$ìûF€°…@ö}Ê_2o?œSÏ}?ÏuQ2>Õ!> ~Ø_h»R odm\|Ö15›²Êe1ƒ
+áüò/ ÕGu"|Ú.“äþ̳G2ÕÃýQ=[Øžœ/nKÇO·ùœ#%ô‹k¦ërÞ$
+ 17 "×{çQ×} uAÀÎI#t”Ž8R‘jBjV[Þ
+cóVfwDM¸ç~õè‚ûeË7!%¶*edvDbJ`ß}ð™Ý䙣×8gÐeEr{¦ý²AÖôu²é\0wÁ. Å p÷Ö{T¹û÷Ö²”n°¡à ´…Ö)ƒ*"¦ûâZ)%n|6‘0 ð¾Æ5Óò%ÿÖWÇïû*ó>)e…cÆaðÇæ£nûáÇ‘^ïÿh·Ã
+LEÆÝO[©-Y»ˆ‘»§°16
+¼AžtˆÙþuþàÞ{Fóá"¹: €*JlmHKj (MÅm§¸ùô׌SÄN98˜¬KÄJ…øˆ†ÓV1ž予žØ˜sñh¥mùïyïó•C «#¢gv¤­0!k…¡À¡ÎùyÃ<Ýú“o™ÔÕOM„4ró5©aóæÎÙþø\Ü" % \TÉ
+¼ÄŠC
+©jçuW™óEË¿7æú›jRgÔ4ÜÑ °ž9ò]ÝêRÔ"d—¼£ãy«ˆ’3³{“ëÔ†’ƒ;ÛqŠ6”·sCú¡Ö°NB®QÀ=¹‚îf]˜š‚‡Š8ñ°‹.½d—'5쮤v¨5­…{³.¡¢·ì¾iûÞ$«ø›wæÑ¿:Úã¼K@+mŒÉ²V.ö`U±ñ¦é|DÑýSÖDi,Ù9è¢SHIyQ­=‰ï‰­áîVþOq™~5™žqø£_Zí™ã9Õ33ŽNµ£âX)cDeLØ!,$d!û›äÍN
+3vj_ÆJéð¨(u3ƒ%ÞE*¢‡É¶‘_“VË 2}WN*÷,R@¯£cf˜º6Þ]Q3Û²º!vZÃÃd‚3vÄuøŠ¨sÇ5‡Ê‹‚~ò(™Íû
+zOE­ÏÙ!üïÛlVn“†Iš)ín)úúÖ{ôÕ‚Ñ^ä¢}2r­Wny‰øA-*?¹ùºíàgTÖ
+έç
+ˆ¡£N•SïÇÔð@Â0:\ ¿'Eÿâ‘Ê|‹œö¬ýÁ«Œ]òÏ$Ø£°‰Ù_ev'Ž\HÃîI-C}¡ErýÎ4ð:ù`Ý¡] Žéi+›x`cBZF[PÅîHáð±fk¢õ¯1 ¾þ³E,Hh…ôíé¾B÷‡ŽK]y›Ó¤[[3PO)&:g¡û¡Ð##ßÝŸ%Vå,lÒ<8kåÐ O| ´ú°ZÂJê‡ùÎqb¡JÒþ”}ï$`É¿' Cœ´E,Š­ðÈÛrBÙÚ»®üˆŽÕ®·-í-ؘF]ÞœêÌsD'M’1Ë¿•ÑÛ§¤ÔåHRËê *P×\“µßÙ^Vœ>TâSÑQ#ìÊè‹°AÀð(Éuþ%
+"fäÑ2ñƒŒCò<fb“ÀnÞÜ•‘*¢z>)jäà¬cÝy‡ðeS0|h‡@^Òº~·óùY“xä®9LáÖ,±tý?h”{ñe6g&7}µÓ1_7èø¸±¯Òöyfý]~Pt\ÊÆ8¦`A\}jŠqý¸õUËÕ˜Â~v
+$‡<QÌÈìÞ•ao¦-09»Îe7«#œ?¦ºy:¤ÀV:¹pv“/ö(qµ¶ñÖó±UκŸjÝÃïÂ:B›†—\%(?é’”øÕ´û= æ{cožŽL¯ñèY›·!ah»í+ýñ5îÇcnióO>áÎŽÓw gu˜ ž”žÑž2jFliL‹)‰¯ÐÚ6?Š]3œ¿ê±8½&`æ>A„„ˆô.÷\_y<å™&U¦ub¦íýÀ­9~ÙéøòQ¯Ðï‡å¬Æ,è¾´™„H˜5^9®Ø§ #@v‰£€«#KÄJÇûŠo¬¯KoOµ_Žè TÊÊg ŒKN½ûi†P´=E.ûl†úÿçdRfB£WÝteKZ}ä\~ÎΤ,<šoPéx‡8ëšjºSÒ‘½–6‹8ÞefKÌ( ¤ÍŸ¥­£OC6Æ-m¿¸9ÞtÖ'¸“4ˆ ¬Mò$f„q1ŒË}?H™YØ Çù¶ñ‚Jrý+Oªþä “531_Àüz
+"ãàB‡[‚á´EÄë9}q=­}WŠºúÊ?fzZþ}ÚÀêóÏÓïùik²å/ûóýE€3z³+bvÎ,€<ªÁÚ­9\aHË#$M¼Á¸ÑÒPê7¦P7'Û.d,Ƭ…Þ*Ôµ;G«ö^ ©8¨˜îI@vÈ a- p?³9c‹½¿£¬
+h8蘑KȬ‰xIð= ç ì«Èu;2jupFùå´ºýÙîkÎ1ä÷›ï;/¥,,\Î)NÛÅÃq ]• ´Ã¿aˆ•pŒ<O;$À™vØâ=9æFT'bÄM;:¦Š"¦!QÆ)õ«{ÊtÃ'v¦º®4èAþîѼíRj•öù—Ù(?m}2™
+
+„EbL$å
+…"Qa‰@(Æ4ÿ1¨Hœ/à—ˆDÅbð[1Fä‚„‡s%|¾XXÌ€ Ñ᪂BQ¸¨ è¿}çvÄ÷ɉà)y×xZ^¯;~“\ãµ|ã
+ÔMœ«[™ÑbRÖËÌ $Ú£É2Ôä[ÓÇ[´Z™ïÃg10 Å'@•.‚CbË]à<Ë·«ÆǪÀ…LÙ°>V‹utñ±¾\|c.ûa.cáQ劊óEÅGãšoŽ Ï5_Çw|¯ý÷íÁÉðu¹,Û㲊ÀK.åþÕ+  æ
+ïl9nUÉñKµmÕ˜¤Ž×Öž9l˜£o0:,¶Pxô(„X&à
+"ž¤ò‡‰ESpɧ*æ6·Fg -»óº¶d@×–‰­Œ¯Œ»W’>MC’4v1a»~ßkh1Ý1:7P¹7««£­½é€}€ñ;µÉ›,¹hîˆûLmq¿càÅŒµmë±öê³/&åñYeyrNYÁxU• ìT%ü·ïÆw>ˆFÑ9[×ò‹OûJcS½%‰¹¾·S3ÚjÆ=ØÆ OU›ôõ)¿©+ê–_Øž–oN´ŸM¸Õé0Ñ’t+.Ñ‹š&6dîKS=íÓµ$牚ø<QµõH.b<zÉ«ÈÈGZð”×ÔEûíZ.â0¥H³lgF]¾1Ñ]°ûXqaÿ‰®Žõ94Éy›4>ëTîL v3ž1[ì ð— ^ŒKÞ|þàêÏö&»„켡%íµ+¸€]ý|²Gøì~kÞæŸ:Ïl~ÜY¸ñ°é×±'²RàÐÀ-:ˆ¸GWŸ˜7^cü6E&4leîјwÄu«wf¬»O éÐè(ȧ—j%YÊ¢‡’ Zä)¯®)1?P“X0¶îytµÉEC Ô4ÿe²ùäæc‰€ 46ÕˈÚ ;Í x&[Ÿö—mO©«èÀ™ [¢ Õ»neEÔˆ‹XˆÌšÝš
+Ù”ÛžúµÛÏ2>žð›{^¢>³j·|æºË-[‰tĬ`Ãæ~nÉ$Oú”樂—Ù€ªšñ«¯¾Z÷‹ êÒa³œ¡ôÝ)Êнï¨Mø5 鈩&µ-eUg—†,iÏÅ$ãÂV%²» ªªâr*`ìI/{_.þºîºû
+Ü÷`uØ•^qÅüƒê]¯Yõ;sýGSÃC1ÐkÌÒ÷3Ë·d£×Ó!§)MYUÙ“‚¡ˆfšÒµ³a£,»b7¥ÁšÄ¼®‘ ØTìÒß²‡1»ê<Xc#FyŠT^e(eS2Ø_½?¯¬Ø™QÖy~ÓP¹‡—ï{¯³¤¡{ÏWl}‚Ÿß".³!PË•á!fÙÔÇRš¦”·¿Šõ-/—Á³Z±c^]ãæ”âüæ´ª<AYñÇŠ·b³†vôHpÈ@Ͳø|žGQ]°t>4×ÒäØ(CŽí-€ý7ÛSœ\žKûñ
+Ö×Wžòiê÷´1¯¹;rÙ^›lçÏýç7tžØ™
+÷ge¥¬‡¨Éxm½IŸ±cräÒ±ðï:O½(§ÖÞ½¹žÒçŸT¾±ó¸áMƯ¬äH³4t¨™ƒ`H§–9¥I§Ž%í*ÚoÐ‹êª eèä(cw6â´~¹îf©!3è!}ÜkjÍ™šY¿¥‡ýî;¿1Þ·ô‡ú_ºGê}äT§<.]ô‰úÒöxç©g¬{cë£Ö“Œ[QFÏ«*÷½DíÔ»e?Z¼YõsfÎ,ËPNctFZ²þá•o<¬ûëU”±Þþò4xפ)§ž ÙúS¤Eκ 5b¹æº•‰Ø4thP zA—]»“]uÝ`C`?ûô- ¾‘vë›2Ac{&¤“dÃ:I†Ô6¥<& pØÀ@#½ ¬ÌR H+žY$8Ê®áÂC.2v“&†˜×&M,©rØœ^q²«6½4¨á@ŸçöÑw¯Nvä?è.Ì®¹Þ㞎¾Ç­ g×]·>»~/³ìäBÆnŽ$êé
+9ŒPÛ̺ë6ȶgÚó_L_;¹=ÓvzQU¹:ÞVz³ïÔ±r\fOM¥i¿žš›®¾š¥©¶ÚrªÛéÒi[§AѲ˜˜
+³óV.´Kˆ w03p>ùãõÏ¢[?=bŸ.M;¥¹3oJÕt8©hÌMÊðeyÛÁιäË[§6~æ~zÞóåÚËþËdȪ)öÌŠêwÞò.å憮S°ü6^##òN<õgA¾- ™ÔÈ“tÚki›…ˆjØð ™p˜˜OZYs Ã
+ú±Ê0Ø¡ÂÀ—Hö¯;=ÔÆÈCj}ÄK¥ìF"eV}\–µ\yLgF÷€Ù}V͸Çé”÷)ðž–Œhz‹~A êQxèZ6Àý.à×]ÊŠ`b–â=ŸJjúȘ´ƒŠÉ
+qšv—”íE¿e¸–ðŒWÁ>Ž–‡®nO°þ´ûáîÙìÒp}Ö§¼Y
+A\"tÕÀ£»Š;mLrdd¶‘ŒCCdÌ$Æ`ˆKFLÃÕ¨U^³deg5)n'Áúìë4ÈŽhmg†ÿ]~~¸¾úÅɆÃq´‚-—Cú~,bSaa› ŠÂšô2e…èM÷SrÝf"×ìrÍå¾xHÄ¢rh!mÕ×2w-c³ÑëVcø§¶1öšN¹ÜÄ$.úL̬®¥Í“6é˜u“†JB‚B@yªÒ€~cP«¦ŠXÕdDËÁâf
+Ñ TAÞäƒZv!0j"¢£.:nÓUb%±Hpå4€"ÆáÚ–û½a³Q 1[ÞWô†f°´*i;îÅeO5 IòauÏæ´ìêöŒª…NÞÿÇñºÃQ[·èé¤ÃNT¢Ê.<Äû~¦ïüþ¬¤Š›•Ìºç9™}PIyƉ䣷Túþ‹˜mrbàëÜ’¤‘
+«º™„MOgÜOr G
+AйƒjV1 k), ê(XÕ²œƒÃPß‘O~cÑÀÉùÇ\ùU‡ èzQ¿øzv‘qwZ\w´¨ï.†¬’ÙÔ«;$A ÉˆEZ\Ñõ”‚ Vem¥ ŠEÀš»‡‹¢†­Ÿ‡/ >óÐqÜã©DÃ¥âv> k-U·ögä 3Š¦ô{ÁE³àëß¼×´ýsŠ0ŸCR^Tw—D {€ïÛ“¼¿l¼áÉ/h:×tø/:s0 ^)ú8ß–V¸ßWø—ŠË«(làï­@¼ýIÓ1è‘ ;Êj)½ìí^nYT_X^)ûÄ ÛSü¿Íz[?<cSYuéË«ÚžƒYþ…­7½_n½î>µõSÏŸ¦$õ[Ó¢ºQù…ßfž*nÔ`·­˜A#ŠNptçýÒÖÃis. Ì3Ë™Oýtb
+¸å*@$!ÉL®äw¶«¢nwµzpU´á’˜ äžî 3“ÉLf& âöé/}1‡sLž™çù}¿ŸOsƧ¨¦Ã0ˆ3>¤ŽZÔ…ÄèÃâÊðýÒšcäpÝ>THTtmçÖLýLÊbÎEÀ‰bc ño¦6œSÀdF+s:xXrèn)98FÃ9 ËkMX-àt­•yLËÏze×qo_‰)oåBjYÀÄÆÿÅ&&Ÿ“!‡)ã7~Œ9Gÿ›²; LÙþwç6þϲ¯Rô#ô9ƒ„\i&¼Â‹[¯šþ´õºåÄ6d÷朣;üT~yíY÷_³‹êzðÇÊ×ß/˜ÚªV~ì<½ö”¼3©vç´õûà(̲EU¾/…Éoæ½7_çùéÆßoN‹Ïc¶hvgä—³^Í™ïwÏÕ}aý™èóàÔcwåçæ¶6}–›·vefÑZÜ%½„Ïö\"Õø‚¢êÀÕówʧ¨#¼ÒjÒ¯j`#fîUñög%æÅ°Òꌧ÷êžKT‘^Tzð~‡}sóÓ£˜®ç0®“иGY“^èû
+w+ªðùµÍ×âsá'üS;¯åÕy๬æ܇6ânùÝÁŸ×Ÿ6?x#»²õBrþ¾âÂÏã÷:+€…!+ä
++'·jƒÏ¹øø&6ß70Q\/B÷Á5Î_±À–¹F@›öç{.ÑK¦^6l×QKšV* †³]îVCøØ@!1ò
+/d2·¡•2É‘©|tx²Û@C6ìuç˃IÀe”õ\܈T
+)çdد˜²Ú˜„AZî™ÃTÙ‘‡Ø耕žå0+Iû
+¼týEÛIb±÷:
+ÏÒ*n©÷: }[Š‚£ûdÜôô ˜e“‚ƒì+ÅJ.Šòß{:*^L- ØÒ³(ú³9ëщi®•ñiȤÜ[¤éÝœøâÆËöӌߌ0˜]Kû-ò|À"¥ýÀLa“⧔Ýq´b66«Ó~ÕíײÊ\ÀŠp‰±ïè`¿,ã.÷ŠúµdRrk ³bwÀÙT± »5‡¬¶[é¢ô·Ÿ%1Q%”ó¨(r§™[J_¬ ?(ÆFáÿ¾Ÿ|VZéGŠ«ŠæRR| n=TâÎá|ÐÑž£/­”óÓÚC~xÐ[ùÊÿ
+S ûCX3ž…žá¢•nè.$ú^–Á…€ÿ„%„«ôdÒDT:®4vÑÀ¨¥0ZÂâ(%á™e#*Äq„ áÊb•‡^‰ÎLõUý®qŒ, ¾ãŽ‘|DÕ´5#¿œšBníÎÙ.úpZ
+Øãç…¬  ¹ACÿm|húnmR|jo¶ë&O(G:z
+අE´™õ˜»i"f<º†Ü¼ä|êuÍwÞ5|“™‘^¤]hëúTë™ Ñ?9“ýXgÞ%½º9YûÕÊó›¿Ï¼k9C/hnó£¼è…®Y@Ä<8En¡ý|Æy÷ëüìùù†S´§â[H§
+K¨î0i<µ»€˜`¦-ÀKö¡Ã%Â&ÄP%6ªÊÀK‡ËÖA.bë¥+Ü\Í„Ž ¢pÎ÷s°àA‚&¾ÃÂs¹€IUX°"Õ;º6‹Š6f”7è ®í`ɈÂ~ùdê–U [Ì…Ðã… 0v˜Œ5¥8ª>¬°ZÌB0eüÒš½YÑ÷iÔ ÔÀ¶Z3ÍݬX¬6t–“ö'eèÇRGòÉ~ÉR61#9`V΄_vü|¸j--ã¦ìSÚ£Aæ^¢IÕ½ìa)Ö7VŽNq[_…rnD¼;§ª)E,¶ŒUm: ¢¬·o ã{ün×û³3™*FplßÛU»á|puÇeÖo“=}Ëïµà»Kµ d*M?¹ bšìq컬ڽ´‘(6 ×ål×Àš,†Ü›—_ËΪoå|6óƤ¶:; s {à ´{3§gI85QwlÏÙv©P7~úµãzÁn€»‡ð®ãÃ"°´ iO½m?»ù^òýæÇîªÕ±öS¹8Ow}n^Z%•÷ÀC9¿V´úúö±•_nÿ…ö¨Eð˜Õ—w¾Úš¸÷÷œSrE€3/iÖ¹>y÷dêEã·éyUýê¸øoé)Ù%Á©>Ç¡o)\›÷ªo¯l>•ž—^Õl~쪘ò3ð8Ì
+1ÐÅ4ÜA:h5ÁÏÌ… ´œ° V²˜¡LH 2ösÒ:ÌGõòÙ~µÂ¶¬Ï¢-ºÍ
+ÚgA*³u°Ò½eï£ÿ?“Žþ}±£&ð-7*½Q^(¸mz!Šë„„ANµMiow—ÐË„¤^ÁFÍ&šê¶çÓ‰2A£r×ÊÄÀ•*ÝCé;òC °¥–§ã3köæÐ66hÅ9ÊÞφmŽrÜâ8XÁÐrÒì`£E> „µôæÉÞIh¸¨­WXv<’ýo8`¥Ò2á('¡Ÿc&dmº½jDúÍo€dllh²@õŒ2TÏ0Ç %8ïr”0Æ0 |[xÖpÖó°å®÷±sÃ=úbuήÝtãÒp°^Æ4Å ¦Êøõ­Ôsñ×Å ¶¹ÒŠò!}K1„«‹c7èÜ[´jÖ¦U?–cöþƒ$Ñ[^AõLyPð㊼mÛ_T×ç½hû–GÝì¾w|{JÕt¸þ±÷g÷°$Þsuÿwyüöñô¼¬z}Vr}Jå·88D‡l¶|Ð ÉúôÍYŸ®agN]›z+9»=­¸o>ýÁPud{BVs#*³¬áaN ®ú­™ÆSÁÑó¿M>¯ýíVÝÛ_ì®ÝxÕz–u¡<‰uå=ÝuùEù{3­gW^Ö[oø.6Ùzñ™êÜ‘ÄhëõÃÈÀ¯ÀøÑËhp´¬[UŸvµ|_ôɪ‹!µ8úüîñR@-þü 'ؘ¶< ‰iÅÛ³’ [%ç?*ß t5{ën¾Ä:‹þ§st<À­U:0=«­ó Õõõ\;ºÿ¾³*5«¸á´Õýµ8ï€\y4ÍÅ^g½:q¥Wr^å­µ™ÖÿìÎ+jYÈŒýE¬=ëÁLhdŠ¡úŸBöþ|¥;‚ˆ4³ ¹•]À%·Ý˜z ,éÕqÛðAÂ6üåÑ÷DÍDw³dûypOqƃÉÖ>È«á½ûåÄÀ>>8ÉÅúÇù¸c¤Ò%|TÝ’óµœ+’òÚk”]„’õ
+~ÕÀÁ+Éw刲§è‘Ý £ª*p/¬UoÎB¯Sa£äد8ØBZ¡Ãç꯭S•×:Þu<ï3“¸YJŸ#êÁ·#gˆ…Þ?å^*ûkûl·Lq«ê—¼ ƒ÷øt# nÁ™]_×_ûŒõ9 Ç~àУh*‘.p–¾R@ÓKu‚’ß4~8zæ‰âÒ¯ß-\¯&MZ:Úð%EçQ@tecô›ìÞ…—²æJÔ¨¤#iaMÝ\ LYr¯4ƒÙ•ÑÓŒÜ*¨fqd ´-oòÏwÿÅÚ{âWÛö›ÿ¬¥lsù°²‹Œ¨‡¸¨YSK`\Êo÷žÊ{g÷Ÿv}^Ã%-|F9z^¦q3ÊÃ>3!½:a„‹9\Úò~uü<íµyÈÌ#¯ô:Ìb°¡¤Ï†7uÃä+íPÉ«ø—O#í_~–ß°Øø§9¿Y‘]‘ü«
+OÁùÔ³Zù§¬JTOk&« `±°ÃZÏ=bBókLôÎr)¨ì¿:ýæÉðÉôòäùØý‰ lÂæ,FŒª0cEßÂ
+¿÷”%N*†ŽyÇΓAÑ·T@vƒ'tb*¦ê+ÛÂÎi
+7IË!³"·…´ç ÏöÖ{NenýíaÒWKòAí0]&‰ÙGLƒÏâî(ÃŽ6•Íû«â‹Í<¡—•B˜¶ž¡×<Ìë)p &
+™˜ª¿TK!£LLx-ç¹õeWôTv3tãÛ„]n6Ñð¼žA%µ”zœÁÇ¿û¸Úùy~KÚg£`bº ÞËL/•ÕòàstÒb,DµÂÝçß@.ë*ð{:nBf›²À¬p$y-¡SàkG>È™*¢âw_²YÛ¹£Ÿ¤³†9 ³¦î²ÉwÁÙÒQ³š!\÷saÌüѧl«e¦æ«k×q·›0i¨ˆ¬ƒ*+ÉéÅ\ÈŠúmz†¸óŒKO݃¼wWÒz5·£WÑqTtŒO\ã’F#—5Û?†$ßײÎÅúÞíM>ë˜gwŒ .TTãv'tìƒjÚ6UIÙ\Õ ÝmÔsiÕ8·—ˆø´NÁïš,Ü.æ$Cúq&bA©ˆE ó¦¨ï&Š ïo ÿóÊ[¨EUÄ’ý ¤¥èÑC^ÃLBßÔòî
+!jþ¸ÞúÕ›ÇM¿ûð¤çKºÁu7Ùȱix
+Õ‹ø¸V\ßA„•8"¨GÂ<8Š0OûEkÇ4›hÏÁ¶²½à_ù°ÚýÕþZß?h¯jàS³Ó~y·’~`~¿nŒ|Õþ×ÜêßçŸ÷Ÿ,‘^>®c#Š.& ï`pÍ(íqÛi¯]]Äe7³+M8Þ†ÝuVqµ‘‘!u_ ×K`¶–*ÌÍ'ýLtü[:,¼ÊFT}•¸­¤0'3 Nj%ýzA~]ÓI¾2Ž•¶tƒlLÖÁ'å}dX=HE1}#»àûH‹^“
+8LÀRÒ?q¥¸-8ÇO²q­¨Ñ‹è:Lú7ÙˆQÖ`1º„ŽIÛ(è·21ÙIÅ=à‘*ngf¥uºJQ÷ýRda“%ÜÀ©¤µ˜VÈG‘!2 ìbaÞ¨¸cÎ{<t=›úežê»fk=©™à YG9&ú¾žþ?ÉeÖœFzFá¿‘«ÔT*¹ˆ“¸*5v9{Æ•ñŒ-+ÞÇ’,K#!„
+¾˜CM,e¹^AŸ¤ ¤]öA!<À[ŽFÂ6 f½„ |'ÓààC”þÜÇ¥±ãl®µö—^Li,úì`+mbã£_×–úþ°3ö·Õ…‘oØ5Ó€˜Fõ[ó*È[ÓU)ã÷‡¬Eí}••É3µ•ño1Ó) ž_ðú«)ãÕÒ«Ñ?sÑ —&fîÉÊ›Ñc…ç~õ¯—}‡ù Ëp‹ÂLÕÅѣ̚æp*fqûÞëË¿«¾¾ú%¿fèo¥1#—°ôUߌ©¼üc}M{ººêÿ0oºÐÜ€û~£úž¹tr·ã¦œã̺m°¾fìm&-ÜÓl=îv¶tŠ6õ§¢UÕ)¸&;EÄ,æÌCÄÄÙƆéŸpëêKØhã-®>X¶\â3c§dÚl‚™Á gùáÙZ.Õ–ˆ !1÷„K‘Xuq²§¶`8/%ÝV…v;Ù„e ¶<úÕÞÛ¿”àÌBŠt³q|Rȸ´\Ò<ÈS–!ž²tJnW§ä @ga’~¼òÉïW²„« %çõ·²0‡<bd2ð˜Z)a.ykú¹PÞs>¿’'ˆÏ›ò©ì2}*; LLuro¥ïÐÞÊð˜ÿ•êºþB=ŠêÄÔÌ™ŽüÔÊžƒu×ðþ:6^Y±T–ÇþƤ½ø^Ò‡îB·lfgžòÀwÒ¶7Ò¤UßwŸÁgP0‘EìöÔfaÖ«\ÑËEo°³…“RÉ6ѤMýbÑ>Á—L×Aƒ1w{/ÜŽóàýRijNÙÏzþYÙòFÄ‚ÛÅѨYüÿ>à"åP· ¾ð¶÷yÊtMÈÚT­‚ºŒ±oççñµ5ã¹fÊ1ö~U÷K¡“J)ü\*E^
+E2(0'—³«YZ?РLãJ9x_Ì“~ æÙñP,âxeùÚz't©>,Фö¢«Kv#"q´E{1øOèQåT‚{i—É@aÆ®[ð¥Dø:[þ[b êq홽Eõ_€ùÝE ¿+̆ñ
+·áÔ‰‰©Y%¾ÓÎúƒ\Ò9öþŸê£µeK¿ ýt‚æƉ5“7°)°ŸóÇ}è
+øZcÍ6 $a64 sñzr/ÕGð“ÿn¹l¥=_jO5“¶.e¼Ì%õ礴C}0 >qÿõ3ÇÉ/šk˜½³é Þôø!Ï]Õ8ª©&¬×‹‹šãÕª¯S ­¨ãº[ñ¹§J&x£±a¼¸»8vìÃëÁCµ¥±¯ø4aÝ]B‡öÞ!ý0F§¸Û.8&D
+|˜r¨øŒSÕ„~
+>9ÕH£ÆZÔv­ (Ó^\ê²eÖƒTãÆóõ”®W
+=’Jág 87ŸsÛ›fò¤´ìf€…„»ÿ~_K`Úƒ$¦ÿÁ;)t¡:ô0%;5­ä¦"Jœêp¬•C&yx¯ϧnÜi•‚÷äM/ä#qðäE)¸JÉi&0x¦WòÁ»r>òTÎn(™À´˜ò¢t .áåSÖQ.a`¢†^1>åk&fî¯ûõ¸ÏU[Å5lÓË0s1‡XêI»fëdÏkK'¹'¥QCuÉг·l:] Ø5v=Q)ºô-ÈbÈ÷T6|Èî*1.fHLÑÊš™uÍ·Õ¥ñ¥§—¿ø÷£ácJÂçkÑ8RƒÝÒ$!ç¦RÀ*|OÊxQÎÉÄ-ýÐG¬e\°«àÙw˜ÔÜóVÁë³è$ðÑÈûù±£±™~“œ»ö'!åFXªë߈®™ö¸j1·ŽI£º½¸íÚ^Ê¥ÚM9‡?,[/µa¶mè£RÑŠ”Û®1[Wÿ»ïL=–̇>r±uôµhð·¬/
+á'B.òX*†îAoô@¶#øÍ΂¾·üü—ÙWÛfÆÿœ¹ëœ9s3§g&³4ít’4iHÓ.ûfÆ6¶ey‘e˶löBh“LšÓLÚP ,ï‹,/1†P(`,KÖjBOÿŽyÉÅw#Ùòg}ïó<¿§ÿïµ49.fìú“‚Ý\ËÛL§ÂWßÂ1à„O9­rÆ7¥d=$päxõ‚œŸ^’Þ’3d$Ÿ2¶… *Ή£=®ý7h«š¯$f8jbž£H/›ð:+°/>C¸Ú…Kiz–ßÏQÓ/øôÃ
+=:ÍgÜŸuÚJ)´ïhx<a×I9ÈÓ Ò±»jk-Ç&çEzæ•”ž|^Ûž\¨mùçkß#)cÓŸæ½Ó°!—òO3Ô|HÈO-piÿì^È©;Œâ‰¶Þ«gŒ]õ4¢>X×^;NtºzŸu 5Ú¢æbH[ |gyèòáŠæŠ’2÷Õ2N;œ—V‚¾ÂÓÂ|šœ,S.+ YPË“3rÎMÂòBŒËÀ²|”@Ù ÖÇE±.á2 )Ü
+œg½€Ãu‡ Y;©çŸDfÚÿøtO9‡Ao1÷Ji𘹓‚ËsöÃÞoÛ­JÊ:¬ÐRßòÎ(ÛÞµmò¡’'gaFüõ‚oîd‡œW¶\^>ƒ£‡›¦FÈã1‘{X¦ “ðJÙÉàSç T&ç“L¦I¿½«BùÆYz|ŽKÍ.Wè™E1ë›­@‡=×£”³™óKÙ{MèŽCß'™ä·‘RÊ7 \õ
+ mõ¤¯Ç½.)i Íݺ°·hlgÂnK9HhëIÒ{–'ïŸæ Ë1µ€†n×Ì\
+ÈÕÚˆ Í•ÈÈ]™i“Ú¦JÌÚ/RB†,!ÿ+!c[êÉ­?¤ž~u¡îýTHhdð!NXù˜Ï+@_¨Ä&%MàÀ`~`u-è¿G¦ *)aîd£Î!ié;ç]žòz ëB&›º™è½«‡ÁÁ+
+e½§@fÉ6Y£(ÛôÈésß­ïàÄù{f sö– ×õW/x§Бw¡Rzâ¿rž| ç,Úú–±ç–’¹«$L­5ðl)¡'‚¬FŸ=ƒõ´
+ž®ä¡×ä)ªèKeèjÍGáÑQ!ã‡Ì±h׈Ú°6M`r’¨º¶v—iÈZê;Š£ç6ÅìØ·,\i›F ‘îJBs»#06þh…¡f^îLj -%?öL~ëech¯@; bÖ  \•šøŽ‘ÞZnô¡’}ÈE¼¸r ð[ƒRQËIÈàÐZÕÔÓøh²^¸¿VÝø¹¶í›¯çp î©ùÒÎÅM*‘B:ù„©<«ý0ˆëjt®
+ž ‡‹)ð®´]¯ÐHWquøò»ï½úd÷'ýåçš–ב;åõ‘îW´—ùq௻/ºÿ¼ó}ÛGrTß(ÇÌBÄÚ-A`ƒ†Û\ÐÔ(DÐv9fS—×­­Ì¦KÃEÝ!î±q¬¯üm9ZÑ_caÎ˦;¥uý—ÅUݕÕáÿ®Y›w7ö5—Ø€öK& »Q†¹.‡Œ«Ú«±Çèg­í/Á÷C„ž cýÐmõ|ÈÒÉ4W‹ëý—„˜Au¼ij:zmþº!Œ§ÐE«àÏBúDí(­ê¯/kþ]ZÕ|.FMª“¬ú©Ã^Ë:í•°]}¼fúº4«êÀöRÔÜv°Ô{qû‡Î?±+h³v£àÛ¸’r}ȧ÷YÂÇŒ-ÌÚÀ%n³çâiÎn¬gý³2ý!wF`.¿8øY{þcËÙ–Õ\ËZ¥$ÒÁõ·Š«ú/%ʳÇ0ÝD¦À
+’ÆÖb@ý¹-E,]çÚ)ņýU´©¹-&õÐy M'´}X‰[{Å(Ú,ì[€YÍð,¢š'\µÿS\fOieyŸ§é—™©®éôdºÓIº£mÚ- šqßbB\‚¬¸\öÅ-‰•d*‰Ýi“¸
+‚€ ‹¨Qp
+ÈvÙ.«˜îLÿ!sx ¨¢.uÎ=ç÷ý~?_§BÙ”ÑV!Þõ3`‚Ü–Œ™Ý“
+vÊ¡`ŬÈ}ÿ
+¥ìd‰Zv¬¢•£&>³+°qÖ5ªøäü'§˜žÞäâk]e×8¼ì™f•£«p£WÉ(®BµQƒ˜pºÌ®qÏ’®ìM¾ôÎô_ŽØøà0Ô6œ§WÆ œÆô¿;æ:nuW¸x¿†{Õ
+Û|‹\Ô$zè_áÖÌ0®£:¸.iåÝ‹€ù÷-RKÞ/NQ¯*˜‰Û’Úàvø´ÔJÏ2µ<j†[âVv3fƒ;«pƒ_Ô;'‰ß…WxÍY›Œ’¶Á÷’fúí¸‘\ÑQÊâzzUÆÆmOYø„ ŽƒwÏÐKkR¢OI,ò-ô\JYu› 'a‚ê°uvS·5ÜÚ¤IANšäŒMAeýñ51 áõ˜7}ªb¿š\53ñ1;»sÀi‡ ø9=»Å#¤HקÝ!ÑÙöˆ(ebaV)ÿaDœvH©ù]1½×…ŒÂÖᶄ™×Þ©-örÈé˜uLˆm<‘‡M"f—RSvÉ@lÓ60ïÄ,p›g™^éSCUaÐKbëüΨiÍZÅýŸw¤ÌßÁ' zM@M+ªY8Ì,ì=w==2·%çbë¢G˜‰×‘4Á-! TuªÞg@Zãk‚û1ƒœÑ+R69³HIA-Œh˜¸¸™Ýx¶+a`ëBÊ.%ç
+R@'hOX8Í¡UÚŽ\1KÑ5ÚíÂïA­üÑÙÎøsÀSõ€¿I€5ÚÿÕ¸ß1KP5çÎé"½ôx†VPÁµ¾QSP-ëôÎ j¯Éߺ~&^ô+9Õþe¤Þ­4Y_tXæÜÅ,âžž[t^ç]¤•Ÿ*Y¸°© -ójƒ:¸q÷-éšã?ý_G€×gíÂÞ‚Î< ´ë}½§];ž¸‚­Q«±uJ5jd7õ#4Ô8BwEA Üú“f¹gªô« \Æ"ê=ÛQÃæíÈ*ÒÕóÛžïFV¨eÿUßü£ï= ˃×=N“ýeÇß<³ý%ç)3nâ´x Ï({/—‰Åà™²ðê„INJÛLà ¦1vÄ8ô’®½·”ïw']<œ¢\Ý?pùTC¿qæSò¤, s|Ì„´e·Ää춌·Hús ßæ£CùÝYfSB9?l+H€ùZ„Ô5ž,‘J‚ÑZ~ëé¯éxŽu3¨t&ÌC à!õa·.¬…ëKŒ§‹´Òƒ÷Äï>ÎPŠ<ÓPEB+¸÷§kH 2›‚®!­aT:)|'-r*
+þ{¼0Xa{ñૃ_®†•ìªãiÊîé«î)rQ@ÉÀíÿJ¾zø*:!ªå];¿@%ۯȗŽ¦?ö$cVaWÜ$ ` ÿ£za§WÃÅGLrjfëñhnwX–Ì€ ‡tô[(`t°Æ­Ì§¢ßŠ™ø@ƒ’ž¤EAMÙ¤ä¤ ô3 ýæÖD÷…×Ý_ÅV¡¦‚Çc ÷“[bà#£
+Ì>ʬËH^ç¶ëå›ÝŸû/Xþ¡Fšÿ²÷ºûB dGX·`NûŸn„’Ý‚Z¢€ÙOÔŒÊÍ7]ÿÜŸìý6¸L¿Ö±ñÙm9œÝÆrª?@Á|Dô‚{!-Ò|4C»¾÷Ûà•Óô÷"¿!iA2üÞˆQ“°²Û²ÛHàèvŸ’^q<Å(ó«8ͨŽUƒY$Dàý]Q£ð>˜ý;áeæÍà½Ì3G-vN<úfóyß7'3¢ºãiYãá$§Ìý*;~•½¡{gáªÃIz± -ñêB W$L _t¢ÎFØXâÞ9™üqoªç’þIÓúáŽ/œoŠ<s´[ I ' ÜÉ<ûÆáÛ¾ûfüË9ÑðwÏ ‡†¨^µôaÜ<DEânÏ"çv ½³¤¢¸–q'¡cÞ=üðµg‘qÓ£„ñA5Ò‚jyM§ ¤k¡%òOè
+¥ÕÑ*]ÓÔ놱ö¿zgqŸ6‡‘Â,¹çú®x‰E¡zUHËÀ…®QÒY…[NU´ÊÄÚ+a~¦êGÝsüÚ£÷HõÁ$óG×ñ¢{ŠòCx™S7ø— êŒ]ýŸã2ÿf3]àø½wN;Ók´¢}o­QLUÑ(µ4±$È.‹ÙDj ª±Ç±$„&$¨5¤BA"–¢è2÷žû¯Ü×üþœ÷<ïs¾ËçûíïåüÍ@¦"ÿv 5°ç`?·jW•øË5`·©˜7Àù} !Ô8€õÝé+ 6 ‘Ÿ˜†(O¬côØàÍNg8éW‹Uù糕pÇ3Þ1E±#Âù}ûDßMðµËØЛM¼‹µº¢c Ÿo
+1>]oÍéºQ^vYÉŸQi¼‚ˆ?S1r¾k«K~lUÓn4œü‹•âDû>d_”ç¹-ÌɩϵøˆóùŠ‚ŸÛ¼óÅ
+¤}’¶?šïó¹ š®ˆ¿;X~GV{(-Ëí‰JŸL°“ôBr€¡‡äoÓ£tBrÐBCæC9ê¼7@‰ý¢¬Êÿ¢ªÅ+ß!-VÜÁ$-FÛ…vß À{bjädy²Ór=2àbª
+~>[°H9 »#ÌXƒ°Ð×>Š ´ ¢ücE1Ž‰Òç†^¼ßUSéÕJ{“c¶&ooŒªëÌuÕ ²êÛ }G.h”<ÏÏk»iI–±ªTÓ
+ðYœeœi
+ÄZ.
+ãö‹AˆJüù¹…¿3NKžoÎ|t0 >šB™ú³A–LÐõJeÁ;ññ™œ‰ú ð¦}†5“´=9àÍn˜ÛjóÛë”—°$ñ.lô=û=Å8R¼Ð
+jœ¢%<ÍKŸ/4Ð
+Ä2Zfá
+æZ
+B¶úI›u.`‘(óÚÛ*Æ?ÙjGë{IÑ7‹M¼kukÍé\Î>Ã'Ú¦Ê^Y&(ÆA|€¶í¥d´mÙn—Ë•˜½IJ”a 8R×ÃMXÐB¶{(Æ>êSã +fªï‰óüçÿ.´ÿ=ŽŸí7?ÛØØÜbÈe˜Ë˜KÍ5I¢‹B¦D¥¤_‰˜rcÈeHQ.¡”h®%·’ûeì÷û휳Çã<ç9ß?áóy<^ïçó© bnµBꮤ*N+Jþ]+‚þ¾Ð”þHÍËr0‹)!º.R
+Ô‘ ¶3´•gÿ2´
+.Ô• ²wÁ¦n¢—V€~:^•f÷¥ç1Õ„•$ÿ¶,"„Ø&™éúv¼ïz!ÈÐó–³Sßõ@B ¾g‘bü¢‚ ñZÄ‹S%~<Y°…úØFÄî ÑW/Êy:ÉŒ ¡DÜ׋à Ï5HI :Ør_ˆÛ©?ž`ÄÉé±[ý”Wrf¢½¼b¸v¨YV pöíù,c›`§)«a·ºjø•êÜŸkÕ¨½Q\î=êÅÙL3ådº¿/eB·È!_‡Èa¶1:äPZѶ€9¹¯ì'yÈ—×s¼¼ÕÖtÇŽlWS¬âf:ZÒÝOÇr#lRlü…†÷UAzu­á⮶Øzr«¤ä¢&Øp{]Cžóõ -áZÇÊRw yy­r>ÆØψ]lÁ¸-µ \NÆ©ñÇ
+züî`iÀn?)`”µ3D‰Ù¢Æß-¶ýq©•ÚÌÄA"Ø<DôWòNE14BÔ‹Âs‰
+xôvw øk/Ñg··
+¸Š€´ÑUâ»ù‘à½×G
+\iF>ÙîÄ{Y%äp«‚÷¡æ È‹}²ÕMGý2¶6žÎPãöGËÃG€ŸQC—š
+ÜŒ]ïüåŒ{f8èž²6'Ø¢`#䵧Arìo*vªý;ýáçòû9n¢ãÉ 5¡©êòžøÚáRÍÆY´˜A co!ÈÔWä»ö±ÐG×€|¾,Ìó²1R>RÓœèY
+v3S•õ¿M>õ¿<Ò•Š
+ÝÆøý¥o¤]ý¶-¡GZd,è‚š¯Ç<ß—Þjoo—YH½RŸúðë7k­³"BÅG=Ñ7£@‡ÃïB=§ZåÕ©ßÔÔŠ0Š vGJc.Õ͇ãõÙ‡ãLÈÁxyôŒ
+x<-y¥‹e‘ÑRGëУÜ\ð±òì¥6¢ºí¤mD9Ï ÐîÓ¼°²a’Òß–#¢’ü\þ1T™æñc­v³À+¸|Î,!úí  @»}yà Ð <\-!Á›àw®µ$h ôê‡CG6°£ìg‹ï¡Žóü8'›œ¹Z`çLÖÁ=V;¡ÿ2
+9?¬Ë96|³ Úù/QnµY÷G¨o=Lý•°¥öâð»eójŽ‰<nµŠu1Kƒ­÷àý>WÁGØ鮇JR×þèJø…’‡¹]¬Æ^j¨i‡ò²pSÆg³¾Ö È[Šª”íQjìÕ¼€x®ä¡de᧤°ËYrôжÛ2*ôlVĹYèi³Nˆ
+Mbæëù&hŒ™ñh³£Ø÷›Š‹ø·¡¥þŸkíÂóÙVʱ²™bc'ïûž+ÍwUÒAV {`î§Ä+¹èÕÎ2¿ý‘Ú,«”Ÿ)c@(9©Ž ½ =%€÷AæazÂí¼°ò¯e!Ã&¯Œ¹š«#œÏ Šö)¯ŒÏ%!Î]#Àº¨ëð`Ë
+(‹  þAr7Å]CvYEÉ\B”UV—jºçžû¯Üß}ñ}û=ÏyžÏj`×Ûå¤7Æ^äcuWUÈCdÈÈBøõ¬Ú À9À[:fÑ<2\*¨OñÖ ÌÓÍIÌsËd]Þ¡’R¥Jî¯ á±ÎÙút¯ —Òã‹ÏWèØ‹UÜ«nÌP²ò.Û§q¹ç+ì¿šòÖ%!¤®K¯™ù×WøÑ:nÁ§´þíò
+íÁg_]DBB+,Ìú2AÚ‰Ñó‹ÿµ#ª~`¯¸Ðò7&Ñé*^q¬‰Žõ5ML˸d
+@ˆYõÇjtŠ×Øü.¼*h›„,§’óá`¶¥À>…Ï<žB=ýf …5-…ŽyBšSÒôÆ-§BZ
+÷æ[ ?mÝŸ†ZnŸ"<·‰šòˆßH-;1´”yt”’ @éªLá!R¯ºå¬¶óÍ1åÉZ¿ÐeêÄÚ¤ì=1>=¸
+re›ÏûªbÀó]ÿGsAVÈÒ?æ2𨳸ç{ÓÈøÃ…êûÖ©²¸ÍѲ‡?­üÞ‹-AÿØË´Š‹ÞÈjO{ÈÈ#„ô@½GÎ*=^hƒîÎÓsÇ©°[fNó‹ d„áóû"Zº}‚–圥C½rfYÐÄ#œ¬uQvÀÎ æÓôS=€ó/rP-Yæ’üKl¤ß@/wÉ©¹nêT
+.æ`®ýÝz6Þ>C+pk…-»f‘¹s×Ô‹NÚ›j) ,Ä¿×z:OÉУ¹ºä݉ª»»ÓõI!ƒ€r,&eo Áo+ÛŠþÔ±+ï,óQ©¶Q"Ø™ú¨Š.BÂ0ºàŠm”†øÏvïPx©)ïDYŸ|,­v(k‚ø4´òƳåVøöüþá »Ô£áí}æ”­
+·AS¡Q‹íEѺΊ„1üÛõqj‰¨ËýÅeþ”öµÆa4™Þ4w2‰ÍMÒÔ$š4½jj½Qc­{*h4n¨U@ÙT6ÙÙ5Šâ‚€ÅÁ7P‘M%`›´ÿÌýæç3sæÌœ÷ù|ž÷Îߛd9*Ë«oJ?P#^z xH` ¬s[N;þ.ìë„L< àÂéidÆéGDêné÷øapŽ\^éæ챊
+ÃÓC=aƒ¸Ý¥iNsŒ ^ûgÛ`WÛòáȶ\¶t‰ÏMlÔ™‰QÞ‰.Í”+K'É¿€ÎuM6¾ÙSÁš¦_Žt¤âž&Ȇ0U±f!ùg†Ó^TˆÏ§%-‡JJŽwŒ^t©—‘œ£¨ ic¢w’ñÏ K,Dhº\–,IòÎuæÞq¨q¿†V]_9¤AÂ/ÎÚ»ÀñN¦ˆyG:j¾c¸ýí*™°Ú‰üïv/%ßÚßšb„%X>@v†ëÿÙáK¿8ûLÈ'<óä»›í_—ð.mó‘=ÙHd—M9ÒãÞ®öÖ>³ªêž[!Ú¢+»´Ïoà7»´´Ò¶úƾl|PÞR œ-4Ù‹žíª«~ò¯´B"vÅ©%æîsËM2zššŽ¾;Dj¸%n(û±(ç:ëMTÕËPæ³xPܽ[ Û7®ƒbo}J{|7Šúîõ·‹Ü†Øüϯã˯û¨[!¦.ö·¿2ȉ B|܇øx˜ˆþN‚€Þlî¤Cò¢x%à(9´ò^øòÛ5jåo×
+SŸ‚À‰?F÷cjõáË.‰qÉÇÚŽ2ߧÉ1F-tŒR²]¼jÛ(¿tQBKVÓñCDì=ù-û}ùõ–‚üèÆô×Q\pÁuaEþ jQÆõšÔWQ?=eÅÊ}þ–™5ŒƒÞ;æ”ùôbÜ颌}¼ Â[ÕíÙ›
+H‰Œ—Kr9DO ;Ô& ñÁo­Yêm6+êþÛy‘
+„Óoo|â2 ¹K³R=§üúçljižÄ•ä604+5Kt¹ùX¦@\h|÷±*5z%U&Ä3GÊ™óê2·ÒÄ%¸4{Z‡æ×L5 Ô<±¤nνÌj@äh½ä’r×:!µYõÞ$³ôàí “:ÿg÷NËGÓØLLÍù-2@Î]¨©Ö×<27Ê­HŸ}¥à=Õž<7›WgÍÚ…± d^½0H½+¹>­si©Ù¼dîV¶ýÌ“ZK¢^ÇV7^äƒ5Y‚‹v+¯=ƒ­Æü?@JNL}6f]ß[ý•ÊÁú´XãÁ¬st›ë©¤TBW[¬¿€ò‘¨k-½0oó\ÜÍÇP›UbúPÕ&RÄT,ªçsôá¯ÕN.¶Ž.Y½4 2ÒÅ!fG0Egµ…!@‹(øÈðbfða@r£ï]/EûJëªÚóÓ:ÉX¢8›ÇiZüCSN>iÁ™“4”’s¯µ¿iÏøY°äIõäpñ
+³¼~´“ÆÛ”} DÄ‚²Ü¤½'ÉñØÞ¦ÂÄű¨®Sp' „ΪL1¾%†¤¶íÆ2»qéê}787T¨qà\¶3ŽgZ[ÉV59vájˆYóÂlàöÚ1ÞôÑ«x˜êÂ)rש§¼wúûtý±ëG­j!Á¢¶Q¢ßÔl¬0pMÙU®Ò¾PEö, BÝÐÚHéšZ7í}Î*VŠ*s6å*ê]š.Ïg–3ÔËVÜÇ:Ú ñk…¼ 2HÎy´,!<Tåbó4œ\01hŒoüü±áÚ¦¹ˆN2tå^´ÚaDò æc–·ÏÌêPü æDð3Ô”¼3…/5¦—Ñ°>Yé×®:7ŠHU«ô„ݜńdÓf¦¢Í¾2ë1+i\<˜ÆÏXè”rò :Þ%¼ƒà…Ô…­’“÷NW$óZ™ë¬E©è2:LšÆýì8—ŽAºÔßf"Â}|må±(_²·a¢ß‚ÌSÀYv‡Ói#;þý+þñžt¿jKÉOr´ŽÜrŠ¼’n*½Ÿ³ÚË$.„À¡çsKnÚC=lA’EV)} l“jHÆ'åÉ`ÎXäðõÝVÜŽ< &EðÚzFÔˆM¨¡ÙOÞµV3&2?XM!Î5Ê9ƒŒr¶8Òì*ˆŸÓä·;‰ðP„S‡¡Z;‚—RåusŠ rìhG3¶†Ýš|y7AÃ
+nŠói¸Æ„´Î,´é«€…³2XV¼¦ bMD¬º1¥!ÊÓ÷ˆ&Š¶Áœ˜¨Ÿ“ÄÀ«Æº}<€.í¼1ó*²BÁ‹ö:§—ÜtÖ"­ü…2óØõ|4Ä8ÈY›¹mäzÍäRøU¿¨L´b@D#%$iârñ/¹iîA Õ
+›ù‹+¸Âã§øA¾Þi}A¾F´{@ÙE=x™ÈB¬ê>êa <#¶ù¢(š€(q×9 (Xx5R¼î³Y¼p÷¹U<@¹-koBî‰hFokxÐ\&£Ìh*#.åB:ˆ¡ÇÞ—T\@¸0”&p3A¥. |ì,!õÓé ï@-k3ŽÌ±úuâ6OÆxãå9¿H³fÜC–ßż° rVmçúl®ßqàOù´â|ô‚,€šlÞ”¿· ;z µ¤
+4á5 ¢$0vÏSY›LnTáÏih;ü.¹¯aïƒæÙX0¤¯3–5`áô€25Ëä§$rÄxöž/%%{FB?!ÔH*Öß2÷2·Š)±ÌÒò°Ná-ÕÂÑ©àoaÀxM9ê€TþšB—óï
+`'¥æ¡>76˨ÓDD® 397KÁÆlÅwq\´À¿úšGxäo.^c7w_"Œï^óæñˆ-Á!ñ§u.}
+ƒÝ‡ç@3J]ÉÒ£9¼¨Z¼eOˆôè1þVNcûš\Þa7Åÿ#×̆À´–âEÎ ¡ñ
+ÃÃ6òrîă:J”‡u8 #ªLÑ$‘~â]3ÎÑSJAÕY;¸Fá ‘Üèç=è‹ ~<€x›@71
+?7#AòM÷H!Ãâ:DJ˜,â1 X&ó½šzIjŽ„óçÞ)[‰Ÿå¶÷vž–‘âu$O[‰wO˜[«vë\ú½;Í…7»[]éw/ΆÃ×o _ZõÏwæ“ÁEØå%nþ”ên RNÐC.k>Gž ;F‘Õ¾Þg‰LÂ9š÷iÔ#¯¯v|RÔupž¨…ÛµìÕá[–¨ýV oßi*ÓDÄ.d¿ŒOx]ØËŠý×Ó0ú ÏCfˆ*—"¿+¨HiVó‡m÷n"cÂ-BUxÝ®FhwÈ3Z<!^ kVã9É]"­A¾¾4þc ŠqsÞMd4nl†µÒ*^uB¬Ç;EðHŸƒÌËp#hNm¢zÿg¼L’븕(ºï+P oÆüCíÂSjÿÓ.x«²/¶ÂâeÈæ61¬a¾9‹b"Ž4Ñ& Í¥&ÓÞLcB|§ï3nýôüÊm.¼ï°± CÙÈ_Ç<…Þ2ö%mİη‚Iä.¾=÷ALzÅÍ`p0HfåRª2QÄþLÕêÁ•!›— ƒ’· ì:>ü½ÓQr¥&ùõór.lÔ€Ó»G—¶Ã©6b¤™x1<,ò¹f;嶇¼Z?|!2ÉbmRˆÄ`8=ȺvÚ‹Þeç‹ÿ„·¥ã}"Fѧ‹ÄßÐ
+J¢öí`ÚãÔrÜó~Ãx¦0áÆ!Ö6Ç÷AÐD@Âc4¸jãQ(rï?®÷N¤˜4ɲú_ÔÙt<„ÏU”ÜdHûùcàë{9”pç'šAÅRÊÚð'ž4i(ÚÍ›Ÿ¾“°‹!úñ—¥Ò¬ˆçéqC(KžZ®0 ‚çÕeöûõóþeé"é¢7EÀìŽ?>†µeáòc!Ô´©|I
+͘ª¦{½-С:È š ,9t`§G ¬‹jÍvB#­Œg
+ioF€Âñû0ra4ßÕ)Z/G» UlÈ”Çóøo;(±äœÝgñ@ ‚ dÊÏ3l4
+ÇÎÊÞ1/@Ò¤öä2¨õåä—ŸšX:Š¸VãÂœ5&~Ê¢a7¾þñƒËðAôyð©üaWF'$ìóÄÒ‹åéL.l {ô'/«9?V¡<}çÒi qŽ}ki{±[;Q˜4#14þ¹OÌ…È £÷áΖ(yá2qúɃ ;ÏtúqŠÿ²Yñ6‚C:s>E˜Ùkh³‘NíV•ßMêk³§A™Ä7DJä² 2†&]†ëÐzÜGÌç≰˜[`®ÒQBFV§j§Òq*µ/§ÅJš\Lm|’å€Öwz5à}ñgÂFhÕž= ´~ÊîÀó&‚ݘJ¸½= |'=ÉšAõŠ˜¿7ˆPŒ‰SMoƒš×q´õ„žó Š›À:Éáï}gýñ@¥Km ‘`c…ÍBædb­ÛÀ`Ͷ©åNáô½¥h(zr Ö x™ùŽ,ÚƒAÀTžËUy`gkóæ õò©Ò×ræë2¦È;o„irÏÙÆô2ì’w:æ`j‡ )J·{F‰Z稟7k{¤Ô)<4Ãz‡nL—äÜùµ*ûçáæÖäăn0(µ³¢üm–cʽ"ti ›[Jix1”uk@Ì<§Ë&l JKáéÃÔR¤öK³§3^fýz‡ßÃпA>ÅF³6ÝÎåL€Íº€
+Ê gøpƒjÇïr.]û;ŸŠ¶‰7„‹tzG#ª]†òrr_è0.Dƒûå~Žb[©ú›â_8¸êýû;„•fM§A(ÇÓˆ_v}¢Ë‰YšÉ<’NöQ+Eàc¥vvå€1 žÐ—R÷w°OäSÉ‹)6yXŒi¶ëÁv’`ÈB稈¥PgÄ!Ø;·g=Ø{Ûq<Ð()?±ú)ñ06pƆP~~Kí~•O¾–fAgó",pÔ8åCe”Œ{ñ÷ÈHu"—çɦÅyš-Rýï° ,‚Ö:çzn34G}°R•€Ø”pÒBœ•ÉçM3Ÿ“è§0ŽÝ GéÙw¼ 5:9  Ð3(þrͺ.ö4OÞ4Ì׆œÇnCS¤V[]R)ƒÄ‹¬•U‰Õ¬¡níA¦&—±ETÌ´žå´Ô ˆ¢DÕãmŽÝ˜Ê‘±XŸ ‡‚Q Z}á†÷`7—Õ¹·ò±©AÜáXäk”§ïT~ÎH–wE)ƒÖ®EÛï Kpa%UR¾!¾¨„‚b‘¢ÙNoà"ŠQI-à«á$3Û‡T…—(ýÒY.¬+Tb6Ù‰ 8 œïL’˜I‹m¿a™(^bƒíUP{`ï 2c‰À†! “€pŽªøK
+c_\›©&• É5yNôŒþJÀ קï F+5…q.ÛQ ɯIê"
+i—«( R‚2ñŇz¥³pmï=ÆE'Ѿ^L-°ØA‚Þ†yüµÃ2¶Qì3 Áý0囜—ªJ™Ù¦‚È¡ûcößFôóãÍ:Çp"n ×»oû®g½‡ùÆþZ]@Æ-|^b…¤fßR^!\eõhs‹JJså‚5ª@4
+jžp¸Œ<™;‚€Ü$ÑÏ+ÏâäÏì$­È7¦¾S# ŠXY[ä©ïÏð#ì¿j‰1Ó!}Ú\Ô H)7t v._éI&ëé;2É*`}çv^D
+î¦E9/ë×FÙÄŒs—Qf6k ¢æS9(¹5¾@ì¨K¯¼ï\îÝæ28þ«¾Ïß­8Þ_JìA¾µêßw6FËÎr²¶¦é÷ïýqA2KqÇéö%L@j[œÃ4;‚ì'>S £¹!—êô2ð‡p(a¼.>ä4"¿hudà3Ü1RLVê„­b¹`f®Îp̲r÷Æ_ gƘ•žlë~g3ÓL—øǽ ­"l«kûÓDì2ŸÉªG1YXx4o½ø«„æˆVíÝcʦŽ=¶MïW _ÁiÖ(.Á¢lþYäè[ã¿\:A@¨{¶EnÊ 8a8Úˆp*0ÿg¼Ü‘+¹• º‚ÙÃØ2ø
+WÃÛhŠÆÓӌꪬüðŸýåž$ÏçäD÷žö &Üƈ14/Â/ ™ÒWgÂar÷Ls ÁŽ_çyHW\\Ï]H.÷‡ý(t¬™”2m„2ÁOåoÂq$¹"&¿1ª¸ÉB@®\bé(áƬsJcþY‘ÑK
+ÓÅVjÐÝ‘25¨XYŠn(/SaÛ°¨«DZ€[fò^R,Ã)T/‰ÊKta¨W~•RA<ÚY(ÁŠ"Æp‘+ gâ$§1´›|b+1Àú¸ê¹HDÏcMû‹Ùwš‡aÞôÕõ 8c‚úG#XuÓ–ÍÚÏà4îGû¾yÕpåŠÈ¶pÖn_‡5yF$ñœi½á~³ jD•;Z}°ïãî¡tI³÷×?ðÝ8[%À5ñ'ùsÄÒœ½o›D`mqÛ <.´Š£uMœq ¢+û"ÀÚÒ4“£Ü”(çb³<I]‹9è?ýë%^kÞoj–Ôºô¹ù³Tß•àjFÄáö&"÷õ†Æ U/¶+l„¥›Ò)â{Y8ñ™ßæ!’ŒÅob
+gú×Ttªá'ɯâIøƒ«ì^Á$0ךù'cB"„ÂCŠ =DÈð€Bò¯á©¢¥òcÉSô«.E%ë ´÷-i’Ûù¬ m½ã…}4gÀ‡€»ì6 s”ð‘pô[€Ü
+ÅeÞMêë‰ áM½ÃáÁæà ëˆS\าœæÑñ`$îÄ @ýHZª^‚]¨l Œ‚³\à!E—â³!dÖËÏa"`RÀ¬s¦cŽ6|y&°d¥‰c ‚–ôùSäl¡ãP¤.áq:˜jk𗢑•$q©q&øba0«Û[¥¹k 1Kd öËY’(9|h ”þa¸c*{1Žph_þøêÄ/£?9z@¦t&¶X.æzK€¾‘ضxAþY¥y•@“…ó6x2\Æ·º¿®"úit´"´m‘°ÄÉaøM
+f0f…¾®^|U£YÄ’|Pt„¢Xæ½ë—"tõLÚѼvýÀß+Ú6­wÉOEUÎe°þðtØ$¦?Dæ^œâÓ s÷·ÓT"úGøs´#/ %ŽÜö´ J™-Zèç0=¹y“‘‘‘˜Ægár‰ƒXNÚæW5…J“{¼ÑQaG"Ž÷Ø%Ï6„
+^®ûfÑ'Z8o×SÑÛÃ÷‡Žé}À;ÙI?nŠ0œ„Ž†¹­”L¢LÁû‰Ð€â´ «Ôa&2âU+ÿkÝŒøèÊŒ÷š%<“¤e.PÌ_ö -Ìí¨>”°IQ^ÁÒŠQÔ0c¸NHÿ¬b” Úô`”(0Z2ÖÏ9×¢¶`y,à_Sk˜hNZ0:ey8Y%lÎÙ¡(Ðï•!Õ?§(åkîeóX:D)§U"ѣÇA˜&üÈG§ß^Že§&Ò—Û"ÚðKx¡—uOìFå®M~*ñ«ž†u=ç2ñë×\szÕ3
+G!ʃ­D[rd`gk˜eæY‚ÌâïÏí8
+Ⱦ"ø¼þ8f^AÏ\mÉð·‹žðý;[ªeþã/tùÏ¿üñ¿hÊ—ü‚a›Â10ɘf!ؼ̽>ò ^M'ÿœ%Þ‘Š²*˜¢*ý«Ñ+ é&ßÞVÅ¿Œ—Iv·DWà=p<hÀXr)Ôþ§¾$žüªP’ÿ™ ¢€l¢q¨/KÞòÚX0 µ‚ÒÔqÅÉX(CðcðÓÝy§¦mïDÉh‚ˆp"lfŒi»ÿ~~F§Ân‹:Yú~‰'¢açkð>è¹(Õæ§×¨JüY¯Éò¹& räø£ý¡kaOÿ7hé
+ÒJ4}¬ã]ø¬Ëdb9Ï/‚ǧŽ¶àlp/‹L†Až­Ú®Û{eô™(hë¡=€Á¥Ç§Sn“r½Ë}àîºíµ,‡Ù¿”öO+ôc*h ¨Z+R¹¾4B†žìéP²å‚ï 2¼ž¹2”—&ðÁ¨tEã² ²,o•Æ¾öG »-͸Zåq¾@4¢«ŠjÙÇ‚èŸQZë= ”)¡YX_‡Ð˜Ö{Ê^;Ú=Fã6Í;ˆ¢ñXÌŽOéj`¯2^³­s4+E?IÉ!82Ní(A]ˆZD‰;nˆŠjp£À{ÊùœˆÄ"ÕüÊd<ÆPr³C#®þqêÖuœ½Êb)lc
+ÁïƒyÆr Çm¦;=½A2HqH>‹XjT‰Eô*£ch{q‚øÓP Ù%Ôöt6QV®Õºo m!¢dR¿LT_òíŠKæ‰×ï/%ä’è‚?ðE&ïuZõ_çDã£ìmÚS!‘•eœí
+¸LènàÛ`úˆ„0Ê sÂÜ7ïö©?B.Lp\©+hùrëŸÌ¯òòÑ£HTÄÅb{.¾º$…ƒhB½ ¤Ô^SŠ¦
+¸§v^!ÞNìhêÏçs´06ȵ½nCæáïÈJ{BÓ\]fÎüMU>L–ë¯Õ¤JZ8 Zã‰ï-ûK—}-½
+€Øˡᯧ<#`ò–#9yÎò˜ÉòF‘‚pdR{Ã^à[;ß þ©<HŸLXi'КJJ9X¨î}€o ¿lÕ…>R>˜´ú»ašÁ¾ãkrÛ_âM\¦ñ0ïD”‡úþÆæYÛlðö‚H¯¡.¾\6u®&¿â{W3ƒgéÞ»yÁD…Z–«BÍönÞ@²ìܧC£¾·é›ûæ}~ËŸ˜DÍ7G9S0Ûü§ÑÀ#@NØ©j0ÜÙ›‰*Áˆpä6w½û½nNÓþñ¯>hœÏr¦ÙCK§ÄÖO±-¹.׈]ú^á\™bÈl÷=åÎÔý1E#! ¬
+I„°iPÿåAÉ!úA¹¤IÒ°lðrZ­7Øœu7N‹'Ð׋’>ÞçéT{Më•»(‰ñ–’8S.$8ú-(ßhË‚PžÄ¼VÄy•Ç>‰±†`dÒ™æìS6An¡¾rÏ¥Yjºæ#¼æäKä‚tòÊ>ÑTÕ€TϪ­¦#{]¶ùô†÷¨K»*NÍÁ`³Ò‡¨éóÁßw&
+nðûö¥c³Î)ºŒ9FhíYCW)-Ëiù‡ Z#»xl¹ƒÂ¬7‚ÿÇ
+‡'Ð}Y=lˆ²Y¼V–˜ @…üé‘BÍ䧖ÄÁ 4>ª×ûéè]ÐÉ+dJ) Õc:I¢Í·ß“%;µœõöÐû»n3f\¦ÒõêÓ9-’­éÚ~›¤p˜¥r>fì@êX TË_%+Ì” q›‘`%R*:¸ÇÒáæ’û9¾-ù>^¬W’80¶-ŸÆ”½¡Ã‡åTÿŽéƒ\u§ŠÑֺ߈ãoAl¾±™ÔÕö`Ü@xB¶õÃûN *CÎæA2 L) u·±ÇU2*¶g¯^\Q 軌~DNr°¦Öy¹J:@|*`6…¯ötNY×g• ¢i*¤œÝ™PœºïSÔh¯§±¿DØ`"ìéǼ’úÝZóá⛵(eÆè¥i"
+
+Þ×Ü\çOFÚ!Î9å5°tè(NØÅO§1Äno‚‡ßø•L±ƒø!»Ù‡’ŽçÀ?qé•z âÁ¡¨©Rkƒ}ƒß*üUt£Ÿ dDzÃ{ÇÔ[ T¹À±¸¨ʪØ–Ö!°YàB!»³“"ƒ©\½
+é\™ ÐaI«W—퀴Táz*ØAæœUÜ_¹BxOÇê”aû®—k`*”bˆ1Ç·tv§°¤öãUµ÷š
+vßA×ùûþ›!ýú•çøú‹ÍF…Ü éU«5ÜÅšçˆó‚˜¶ñ>„Í,ó„ €d2æ 6^óGË‚g‘(ILø ,ê*dÒÜ u)x¦ ˆÚ`ª¹ŽÁöN׿ÆGa„Å ¦Õ„_%´žûæÄ¿„Âr©ðp!óÏŠØ9-Èdpç¹’‚7È62êƇØKyØËÕ´(Š[ÂtGïû½@ønÌë[ª€/â÷,K~eÚˆE5»÷`Ìð]Ÿô§3–8žŸºö‘6sZ{:ç½ ˜þ‡t¤qlgœêSd*61ߦB• tYŸ_¼ÍV„º´ÀÚ„°ªÄwå×àü~¿~eT-¹ «½:5í?@p
+¾ÿ”è/X_ðøãå´ Èy:È°ýŒª‡m±C^“ŸKlž‡å~çiäÞmž ã¼ê
+ÁKw®@¾´Ø+ù0ªoŸÙšZW—¯
+êW¾|eÒâwsLË®HL¶®‰:±óí‹Wä8HŠJ¦Ó8PÚ§‹`gpüs§¸SšWô!ï­9-¬1ß~h «T©¬V’¨GÄgŽŽ³¶økÁÊt ¨
+“5–h6”kð XóÀf¨¼(CÓÜŒË4·$¾²
+¢yLîˆç¨KQÑØa?ŒUÜß“Dp˜¼Œ²J0>p9m¯”¼Zç4Ùµ³u„Iºo¶X¡‹“ÒØ2X±± ƒÇšO`#pÖô 3¦”YË´±E§Ä'§§¢?nŠ
+4ñcdÕ÷›¢”ÔDÿÁrl %òGÙþN‡a¹g¼*Á‹ i‚º@€eL¥<°Œ²Ãùh“é2²Ç›ä[Ã)t°U€[ üläi»œ•ö€qJì$È~
+K£ç»ï|¤ud»éŽÅJWr‡çÝW—p¡1šÓ´C‰®²éÂKM6tÆ
+Yö›&2.ÚlVæRƒã@„Ð6&éÝŠ”$³ŒR? ÉP·ÈvÖå)µ¯øÕ™ÝÌ»‚Œ&‰]8ÁvTvšá´skÑÏûþ!¶À©U‚Ð`]®ª&ø úÄfâ/ÛÖëKÑÅﮢŽFYË|Lþ3E?/Æ7§ý²æÙ¾ßñz†ß`©´`O ÿ·(ŠÅã™WÐv±Ä$â± V1d×ð” E%CaŠœW‹?{`Up¨E<z ü“Í"ó(xCäç”ØQ,1ä |»çÅV ´\!Ý´)^%¸ ȘöâÌáùÂoÞ°\œqK…†+RÙoö#ÙÓé¹Üí7ÆHTœ2Ž†Øç•ØÓy¾£¸~GÚ¯D[âãÊ´4¿è§€& DÂÅ×Ø…QÃ$;%f[GQ4¸}—á+Ç[bŠ'H
+öwD«á?ËÆ2¨£ZÜ'']Š¸S#«‘ÖÞoÖÆ«¹ìŸwØ'Šž8Á]®ç¢Å/+”.ëÎzxŽ…üà¿ßUàØæÚ /%”ÃùŠIǯ6aÉA—v e´CRæ¬ü·}ð@0ÁÚqóQ®)6¯Ûwä<¹BvÊGð[cÍ
+¯Œ¦ÓŽÊ{Y½".ÆWÐ:.d÷¡}`/lzÈ^.ƒôö¼KÐ+.Øp¢V’ð1)Ìe×O—)š ²0—´\
+j ÐìédÊ̶ Q¾[}n²gV/³r>s™øõ2äxº ðÚœ Ž¯-vJ>ŒêÛg–Fûö~5|¹—ÚÏ}÷kÊl
+¥Ç}§À?¼“{2
+¶E˘!+á°f­MÇoÅI¬Áßoî[ñ¢@³Nƒxxc„¾EtÆ~qšÔÀáø:×¹~ˆr8„;³X‹&t%Cˆ×GM˜FdÄ=Œ‚¦(¤ävTEÚkB7Õ ‹¢VM6l—Ðb ç+ÌC/¦ÖÔà©èiìï7Elëà?¸bû0 Ñ rÑx@
+k€+íå#2aLÃñ«„~a. ¬Óä¶(¶1ÓAþÅèóÜßA=¢BÓÕUe‡*/â~A…ó°…©á KŠºKÚØÖòh°àÈö&LúÁys¹£AMä.“m!ˆñö¹)¹½Î
+H‰”é;Û ÇOd$²‰D‚‘ˆ}‚ –¢–Ä®BVRB„Ð!´z{ÑV/ÚÚÚªª¥EZmu}\zuzïóÌÌ3óbþ“ùͼ8oÏ÷œÏ÷|Ï—ãí=ÛÅU{KÀZ[ÐÖN´3¤Ox: úå’Ò×Vš‰1ä¦bóD}V’Wg^2Þ,OĽš0œoXMg[6ã÷Ý+¶ãGfåÇùÇemòñýË9_Víõ/nXRwÜÝ †zbWú[…³œau6­IƒmÌLñHâ³A@'CFH GOa&}¦½8dy°:õ莮ú|³Wó}kÀøcÇaù¼l-ÿ´Ü©ü¾i7üÜì<Ýì®~u³Yüt¨.ðù˜1ö™«#qD]L¨MˆA5%' :ór±úìD¬¹0Ý«»8Ì‘ñY¨²èH¼>_æ;¦*Àœï*:Ûttžn9­—jÞÍéÓ_ݬMx¿¨ÍÙÒE¿¾cÉÚ6Å?r¶ðÕVf:ÚEÎú
+òªßSšï+ ™>žà€>ê1nÅÑñ÷WC“ÿz×?ü}ËTq8W½sC)úëuo÷ù¾säëÆPçû¥®Â“õåù¶µñ÷ {Û§e[Í»»–úÇî¶,gs·¯,—èR)}ŒŠ’:9Š0\§`®ôù=¼È=š3–þóhpü?'à ‡«öÚû.£`ª»‰êÔªñÖºjL]n6dEE@(“2 ÂüÀó£€7¾D ù JFÝД‘·Uœ?w,5g»Ö¦ý{¦Ô½»ýEëSŽœ{#]¢kFÁÑXŽ·U—bšr3P™<…r Dª„XH å‚î ŠÈ`ˆ  ò0Ô¦„£Fkr}ö®ë¥ÛW[BÚ¶F a¯§ûs×'ìÉ3–.N_]“·¶äª*=Jbã!‰Ï™qþþÉã@ ›T‚' €â‰Eæ&@,› ˆè¶zÎÁŒ)þh¡Wy´4jØœ,XqõDÝ0éX¿¶ë™“z ÉZqS“–„RFI¡":ԱѠŒ8€ Á‰84xâÿXÀ ZÛœÐF¯é³¿më ¥{׫9§Ö†ÏŽöçs¶¢¥QsÄ5C³oWy!¦-'Õ&K]V
+d ¹ aÑ!’é¼7=1L#@ ²,œÐÈéϯ7„y¨Ïz·Ôûeµ=÷ÍL›ôàf{âŠSrÛÒBskj eæRVT%H ?R
+i¦êíxŒ°‰8°îÒ
+E"
+î÷řڙ …yèt‰âùPŠ% b±Æ^à‹ÃA 4"ÂüÙ ˆNðÈ‹’bFj ý¦Ûå'k=ªãÅŽœ÷ ²×Ó¦Äý©®”…~#ﶭëÔÔ“jåY¨’Äx(ŒŽ…$
+Dl1XðöFxøC _T¢/ò/H 
+P•q¤E{•øìI勵í;ú~¼rØÏ÷ÌgÛ}š+Êõ‰–ÇWÍÒ1]3£>3SÅâH$ËL !Y¦y⑲î~@ó!‚?2wx
+$ñ9!7ì^®å\|Ïíõõ_¿ÊÌü² ý ¤ði>$ýN:äÚR!¥O_%#;n’Ú»Œ0¨Ï ljîʘ„±É¤[
+e@šò‹!ï‹+/•dç$gÜûò&73 ÝT•"êHË<䮕…:ö20±&wÇÙß¿
+â¾ELŽ:„ô=»kÚb![T;£>‘|Ï wlÌö°‹‹[·³k"huû'eˆÙAúëù! rÅ0Ä[›„f†Y­¹:vl“ËÎì
+›•­óþ®b±ÊY s?ãåª^ÉxF'~p,îJO‚rýéŠt2î€Ç>6=:GGì8)Í+Ó„²ÙÄÿÙ”¬"§È_šµúõѼVüÉ­!ÌiéUæ~ê‹ñk8ØŽáA”YÍ/÷jÙõ«>öhžËøÝÏåý¾ÌœyI¨­Ìë_¸5 4‡­BbÂSRÀHoôip9“„Ò câ»D ·µ„×WfÐKcŒ†¹©i¥E£‚™xeî1áǽ‚¶Ë.Nïæ$ªÄ%(»¾¥ƒe}^8ëJ_|‘Òuà$5Çf9Ä ;«ËoâwÙGùµf5¯Ì¢”@­*F¾cìtÎ 1g Š¿ž Lõ/kñyqô¯‡³\rØÊÆ5Èg»Ó¨—ÿÚ–l'‹àpÌ+æ‡|â~‚ v ½å6)ü)uõÄ
+`ãq×Ø[µgê.Ù5`‹¢ŽDWí¤Æ¸‡:ñ Åû.fç‘+Ñ»yµélQe<_ÏüBIØÍDïÚ‰õk:Ô‹M}wɺ±§!Á
+­‹|î±Gĉ;e‰ìÒÛÎæúšOç‰ð];îí¾“{dýf çÈÁí ;Ù˜M ¶ŠèG=j$ÔF&ûJ·Æñ…kÄÒmc?k+¡ÐŒµmôlNsÛÖÇÉ•Q»óÔÍ£XqMÿXâK/UÖóÙè‘›Ž>òÒÚì4Øž €ïLŽ=|ê±WÀŒºØ=G^±8b—rœRÞ®ùi]/ÞÐãŠÃbÍ®¡±Kc@upXеZŽW$ÚØ<“Èj]ÔI„Ålè’íÉ–ôCæÍož0æaã#1¾(VE—ÀÑu¯L½éQl¸G6Rº’X˜â¶„LbÌŽƒ;õQ±ç‹\æ…Ãøï&WþŸm€î§á£nâûØ,wäH›Oùm™ÑûO?µç|–ØzᣢÜÔÖ°‰Þb#ÚÊþªå"›CÎá)Ÿ…ßt߬TXÈÊBœ,°óe™îlY¨8ðâZN—ùêÏAõÂY@<qQ>&˜‹q¶”ஹ„·zס‡ƒÛ6êVGº2´®ø¼T½6ŽÍ÷©þGq•}5•¤ñ×yœ93v;ÎC{qFlÛnŠJ+ƒˆ‚ì›bÙHÈJnö´‘M‚ ²ï Cزçf»¹I€nçØÿÉ\žªN=|ç«ú~[ |{ %<òiÇ"îhÌ!åF]üUiçõ=„xÒF)¨Ô”줦âÎH]Æ8òøDG¬wØ=%‡ˆT´ ñ•]©°àТzìÝÓµ×5á…¶ú¦Û¯[DO¯D{ï½ê€NÂ5NcŬ<zé“Æû&”y7Ñ×nI_üÕ¢hü:m&tŸN,gv§–¶çjfþ÷ðär9(“C> €èÌ›#¾Î÷¶÷?¡•ÁšlH,Ê~Rk£H WÄ(e’œO0Zô³Ñy'½+k¡µDuÃw×1?žÊç!·æCÎú~-g{·’ui–òN6kfµÅ Œç! ¶&e¦wz1¿x4Ø1=³)i¢5åœìÁœƒÙ š©ÍEw¤à`÷Áîàà[+ì×.9PI… çø@ÌL3Ò^¤,¬^›¦çƶ´ñÖYhròÏ®æìJ^ÚÈhŽë1wܽÄ&­)cCzZ'î¿ýHé*ùÔ ×ÜbÎ1;Ÿ±‰Èû Ýß/£nF׉¢[ãf¹É¥¦t§w
+®šZ:Ù2Û„úª—…­
+áÙ¹O&.ØE£éÁ**i¤õ€6
+UÞ?g(}š\*Èg+ad ɧ@·ˆ^«ËÙÇ_W<Rl“þöÈE·Œ_ô ™¥àÄÂYDµy~$Î{
+¹è=+µ7ª£ü7¦“a£«¼^pc¼¹`d·gôÔúØê#p Ù¨ñµ7·»ÿ•0à‚f ÷xÑ—Ûâab[¬öC=¥þp^ŸÞ 淅ؼƒOJš¾KîUüsÚ3$×À>1òWduÄMŒ–“­±úÄ6€`yB ù%B$sp@—ròNªªö›ª›Ò Ù±µ)#þaÔ@zÕkS*ðŠË¼+Í3ÃçÌ¿=“Ó$§K¦í9í¤mFÛ&¦VS5*šE¨·ˆŠ‚²ï›€ ˜Æ=nàÊŽ.¸!‚l/« Í$™2O¾Áûœ÷þ]÷uOQ·¸1Û<jà ÀkHOï¥Tí)ˆùrBÉ£"2嚈Ûe#•Ù2t¿
+Åȼo.åÁefùþ_è{Îá¦ï첆ow$µ_9$U·.”ÙA«Î8ƒ5—d|6ß]ñsPÍëlŠ(c>fä´6p¥‡su÷|*t~Ü&`†·ØxÀ.AÄÌnë)ð˜‰P–´t—E ØÒ“EdÎñl{NT/¤G¬Íù |à-xÊDoˆëY¨°žú2Ò~-å¹g• ³½Aþp²L®´L`^¸fÚEõÜß±ø\yྗÐЫRf:iå~òkQÊÞßs ¶Âå6·Ë¿A|zø÷sµæT豃¬©øTŸŽGöhXÈ ðÚ¤CÄ‚Œì¶€ŽVé9è†]TQ_€¾.‹lò0—6S›¤?n—OÆÙ…ŽQåSÓá§s¸sOÅçÑURÍ•mPL‚ÌÜΠŽ¹[&f‘’fÁ¯#Õxµä—=§5e— ÿïX¦x »Þ÷$ìltÄŒ-½ÐvæyV;³}*lÁ…ªûqPM)‡4ÌúÀ:µ,´ÉnŒ·…ôÌfï±Ü£À–D­"Öþ IoȽ±?K©¿v¨.w%£3ÔSª|Z&ð¨øÛ(È×£¢ÁÏÖµç*N‹|»ý ò¡]Öø³w—{<Örß·Ô]Ô0çq·è-W®þ‘ôa n§µBfüb«­À§k~”Þ¥¶½;°Fö+çLÇ^5uÇ€Û§]Ò‰ëcÉDÂÁÄD̸ç'
+Ô}Çä«{Q›Pߤ"Þ¥ƒÏY¨¸´K ¼vqh +u¾‚+>˜nÿÍ«aÔî/2^n‹ê‚º‰±¨Q>˜°ö±’2là¢ü*zyXÅ­OĤ %ùIh…Q“ÔòÛN'Û3½óíY®)dæÖ@ÙmCß³:d ÷Ý« „m¼ó¡k›u¾Ænõª{0þ .îíM:x®¦5he5?ÌuW§A†AV[Ÿ¸
+f?8Æ+¾ lt-aŠÒ껑M*ê𞘅PÚhÍñ*ë2Ž¦Ÿß±H oO6Ý‹i¹¨ {0OÌ‹د®,"JÊÜÏéXç+¤"Ï"!d¥Ì½€y •5e0^f}¶H‡}7õÒÜK”'ÇS­™go›~ .·gy¿Ï×d\Zé]1#ŸP+â ÷áMVëùzwY|—ÖqéâP »Âa{º#ëh‘X‘ØÑÒ`_xuì&—’Tä_§<»XÁ¸Ð†êíòúŸ -¯ÎÛŽ;úAÖ[Ü‹Ä×hë¿÷dÕ_@KX˜OÙYêYDå¦}`ÏÊÃ[<üÑLG¡o© v8Û’±7Ó|/´Å@^ïͦұäv/ÿjoPžÚÐCFü¿_äW`!-®8n$¿õ/wþ\íÎmð‘—;}¼˜…×ÑSžE\þ±‚sÎ
+¦9ˆßÜ+<ZÔ.Ÿ
+š…”Sðý~°"f.åŒ\:å³îuJùé:½2K$aÛðëS5iyÉs¾FçWhe§³íýkا€'eGŠ®œ‹ JuÒÁ¥'d|›X5Ó‘ÉJóÕ½óo‹
+ºâ;b~Ú5ø:` WBF"< !½ëMq{oßÑ2±4jæSÒã–Ô¡l.¾Ë§ $ø¹ŠüÔ½H(9UtÃBz6Ò9ƒÍµO²àyz2È!£˜ÕsšV!%fdÖ…´ÄgG3¯2-å_Ï ºÆ:øæpùç3ØlÏ4¸‡Qd†WÑ‘ÔÓsÿ§¸Ì¿’N÷8>gšÛ4ÍÔ©{gZlÑkåÒªe™–“{nhŠ²(ŠàÈ.« ûânî[¦)ˆ"¢"((".È&‚(‚V§Ó¹ÿÉýöÓ÷—ç|Ïsžçy^¯w[É}lñý_ljy'ƶ¯ZDñÌój}
+kö–::=‹œ=eÔ7Km#o @c½
+lêÁ,>Í>Q¿ÔœyÍÔS~jbQ>¯7÷jI¥žÙÚ7>51ß1¾Ô2Ð=*LöŽ÷àV‘söGŸ uⱎƒ< í›'å»”¸ì1t‘ŽÏ ®õéü«ÍíGæÆ®£µÆ>¿`©žMtβoÈw«ð™îy*اó=ù@/¯6uúÔÂzÏ %Ç)#¼1tÀî™:¡w¥üÜ«´w1gWÞ#2RJž¡õÝ KoY´ýêŬ$÷ŠRœwÉØ^zódM
+Ûݳ´BÀ× ´)°éîèG&>¯ …–qzŽ®£:Ê=M‡…V 69õíö6as°úáZ;äîÎ0ò‰uœô÷¸
+VY`¡}²,`œÎd©Â-C?7w„ӒΙkâÖÿyjhGÞÛ“r+ê÷ï=3ÄÆ
+Z‰±½â¡¾µì±kþÊÔ ‰”Ö—…¯ö ƒzfíjwÁµÍðï<æí®¼:Ù!EýX`c4‚:u,jVX|7°,~±´~ ®pëlŸðI;£¸$Ç81ëTË!ûçÙøÉzÐ-5’à“Ì}¸D%óÝŸò:Ð% r]+ß4wBÚ†qÛ“LHIâ­Ÿé ×wG™¤c}SËöhi”¡)ë’©%ï?ŽIDÜé*—y¨ðG¸EO»°/ÿúß®d0 §¡ÜRdüzKñUM}ö õé¿ou#NæéPã
+2øëjSÛçï«‘ùÏþ :eo
+ùÜ.«Œ|ÈH#Ç®äV¸ÌâC5»zk°:^/]×ps.ɉÿú„}ú‹’zÍ.G~ßõJyÙ÷ÌCð”‘C=r}bCà?35oø©×zÁ1GúÜÁ2Ÿìšk@ìLÓò¼& çÑO Ô7µ"¸Ä±†øÎ7G(õ.ÑÐ!k˧C³¨Ã½Ä¨ð.±jÜ€_;gI…ËdXhKÛ_âb]ó ˆƒ¥¦Æ-)ÔK„! —Ô|œgŠsʨo-È­á–1Ž b¦®tÝÔ
+ºií/»£f…YÇ؟ƦW„|»ŠW»9Îxëã×´<‰‘‰ù²Î$~±°¡UÜ6YõÄ1IÌ<ÔrIrÜ;C6Ó=%"ì+Ĥ€ZX·¯ çY¸­de_PÒ²³MÓ‹d|ð$Ê+ãTîɨ9ëÝ•Ñ[U<rÌߺö’pµ8ÿ/K?2þTßØâœÆg˜zaQæ¡Ê¸µþª¸žê„=À·Ž5”2û4%×.e–|5µ|37÷úµ (Sùõþ²pKø6àK1žFÉ®”š«oEFÚ†Éiþ9Ê.Å¿ÞÁ¾˜#þÛL?/‚$žÁ¿½âc€d"ÄZQü¹Åføë†Umè,ºÑ…~r¦>çöOÓÄøó®Qècï4r
+t‡
+_¤ë*Ž éù¬S³¤Å§][_\æà½*jéÎòq@Ë!~]oêøŒ-ê×ð)Gjü@YWlû€N¶”?4¶Á#¬ƒødþDRþêºu“âšdÁ\“b¼oŠšë“‘òlÄ‚ÅFXlgU⯠bhÊ¡J$<P±qæ啶’èTògS=!¨çÓ÷՜څ2^nÔçòªéð=91Ëù‰øU¦c ð˜áꇆ¦ÊØ)zþUèñ/uéÑß×¹þZéÎǪöqäsÏ4±ðH‹/únãüŸâò~J3[ãøäfî½Ifc¶Åì®IîšbÊjLÖ˜¨1ɵÅÞÅÒ,HGzQ,«ÑX£k‹
+PŠ Eì‚ (¢¨Ä½wî?rÏþðÎ;sfÞ9ïœó<ŸïçáÌÀifðék“øâó•n鱎Cs~ªŒÝͿ阂Æا`±A#ãÕ63œ³ÌR¯Š_ëQ°«?âÒ/·Ç_Á¦\š¥§^Û€ÄÕtøksÛ©•Ëe—Üý›J”“pfaQ}ZbÅæ2îPO,uÏÕf.õ@€ßÒP_€?¹TÍtM6z}†šç5÷Hk}ú/k|¡OŽIÚ,ŠX(Š°öEzµ¸B¿žŠØ£<z
+"°Þ9}¶)l?ß´ž¯ šŒl¼G˨
+Ï<)ׯ¡WyÔš]LÈö*˜5'`– ê¨=:~¥¯êNÍ¿/QÒï]D]´´çÿrndœÂ;ŸŠZÐ0ÁEÙ§%—ztu;2à\Ÿ1IA#ŸZîñ-0±[£Gû
+LFÐÀƒ½ààìþgzÕÖXmâžœ\ÅÎ0K#
+9ÙäQP¡†È»Š^©éC?uÎÒ‘Ç‹m|§˜˜±Þ_rsgr×9 ]í)¾½;ݘåÓó·ÀŒcŸÆ¾ðʳÁ9A<j&¬|jÀÄ£ø–X >qñÀ
+·˜÷Ï7Uût,ÌÆ4>yðÒ£ofí+› ®ÙòÇ+C×õ])_Ë9‰—}Jré‘Qò\¼6Š{¹
+d|È"D»ŒU~ fãN,¢®ó5ÑûÀbÊÔ ¹«á—„[zªî¸fIÙn¯Æ8ÐçS73Á°6†ªõ£/ ½4G{óO-/ûk´.ë¿6aŸc¡Õ‹¹ê˜ •†Lƒ!qf$Vž,Õ9ÄåÏL}Yæþ¬ðÐJë‡s¯ÔµÐ&rʧæöÁ¯éÌÈ%iŸ›f/vI«_}YkéÙ[lïrÎ ¦ÖŽc+áWS˽sø ç.i¼15¼­8æ²[×ÂÞž¥å{4ŒÏmûÔ˜¼ jÉ>Zk.¿c,ŽôHñ.%µRÛ[}o{Š q+ø v)1sGJ|g—àß8dõoöÔ„œƒ%NƒßÐ=0öÎLÝ'Ëï'N—[ZCÖæðn9ÿ°
+Ø1#‡œÜä²âf6ýÐ@oñiå–ñº[eTѾ–ÑXà ´£ò¸~T ¼¦;¤°kÆAÐy1:ãg×$:×&k/|‹/8íxÓt7¾Î£G×xôðJ ƒ „o [alùs¥–òÉÂáŸlq{<jÀ[¿äc—õÁ$?ÖpÆ3G,rIZÓKÌfR@3Žà{éЈžK‰®tµ©8¨Ã….„oŠRõ€.JiÅCN»SÚ^¡î©ºàSË
+R¹W†ËÝšÀg«„õ×ðÌS.1®Ð=M.²·¥ûÚK\R\¾e¼þ¶k¦é‘_E(øH]‡z¢î¯K<¿ûƒã¥8 póHOƒ{PÙÞlgó̧¦7X& yÀœ^x¼˜©›X&W[F!¿.sËΨ:Á§G1~4 W¥h™9š6Šz6d· ¾ àGù5-aÀ -èžg>÷,qÚ>Ä-§„ Ž
+«ð‡÷Ø{§7Þ6Ý ‚R_?ó•i´.û“Žªó\“UizQÍ/<è  ©ßydõ?ïðöu´ÆÝE\Ðíæ|°òŸ\]]$䶼:×1 }è¡žxq3Ÿ^çÓ×yÔ˜ž×‘\á2ÿ±²¨Ÿ] BÒJÅ8$ˆGn)µÐVvX/ ë{» Â×GÆ^ax…Ï8PP€ŒÄˆ¬’j‚*,È+oËôÎàr€œ}×ðºñªU„¸céoüm]
+B ‚P–)j¨¡bcgâ»?å¾þagvÙÙÙ}ûÞçE Hx—ÚþÁÂHÚEÒØž`,jäà?Ú¸,ÿ&±*¦c€þÁødçÐNõ<òÑæYïC¼›b—nrZÒ…-ùßÊp ŸÂr>âd•åmH3IJSc éî%t–c¦óéÉrgNRÏB®“*Nôú°–ÕTaŠO·º ½ð­¨ô¦f üÒÉJ[æ';ƒæÓQ;*TQ`‘R#KFRÇ;­ó˵óó7³0mzÓW~ëøô3½Hrªæ“lÝYR\ùÅ dQŠ–ßòï)Lù5IKá%û®äp…ÚŸD<:˜éʜƼ¹²Á,»T’›üJvo–Y6MªLQ‹ ÙŸÔõ f24nÁ7GM@—¸ò ¡4²P1›p4±Ç&^NÚ‡×bVñxÌ*>Þß1בah½ooè”âA#¨œ«
+nÅí œÕè•b²}¥)vÁEÛPí]—ž5O.IÙäƒÄÎçSâªìÓ­÷ís­÷60¯"»t(Ð3Ø1³pêüP¢ŠØ84Ÿ†ôoKxQý¤â|¿o0l`À³vDó&Í\ZÌÂrTæ ÃàdXÀù·ðeï–áY†¡Æ´ýyTŽo›Ö–´÷ŠŽUx°}]6ñâNÁLÈÈÁ…L¼OCoõ'a ›E#½Hp¬ê„u^Â$<·ô‹BZv—KN¯Ü—qê]Ë=Çëäjë$ìZ̓Ša/R#Z2:´ƒ­>Qt¾t-@ŸZÇêÓO”Ä·‚qʘí
+ :³öó‹ì:ó1?°Ëãþu0´Û¥e¦Ž˜…‰KÚûcæ~IÒÔÏ‹é¸Ø¨¶4jÃZÚ¯a¡ÛT(p/]uâ›ðµ:¨¤Ôú×Я-#Õ·L¢†4Ç$µp¸£ø‡E|ÉE îç5fåÍ%lIÊåí%û0ä®gXªF<pLáJº>šWÅì:3ré »d!lˆ½ZzË1àñ®Å®œ£5\‰ZXu+¬$AÏÌâ±ÀàSÊ-’ÖŸ'áù—4=ýf‹S›JkÈü¥ì·omƒÍ9¡-BUp[ÜÆ•{äð¼ýiP†^{YEþÝÁ$ãPN®T k®ui®©Žç@ÏÍ‹íêÿr’-xðÑ$#¤Å‚þ|úO§x鋃×w¦ìÈ É›©E <ӣĔYF ·Odt°w“ƒÕ!ž @ /C²ï|7ДÁ&lK?œ‚Ý÷¬¢^Ocr¿Ÿí~™r0I(òË{s°ÇìÊŸ4Bð‡õ\;ØõtOJkèD>-ìWâ*CZ.aâöœïñú’62ñÌ€ïï¡Á(¤£w&÷%+g{C!Ÿy°Ò]â^iyR!òÃZl¹qU8Š*KÓ‰‘yÇKœ&ÇHçC¶àljöç?*H¯®z__=Y€fÆ t¬j¼1“Ûðä‚w‰Õß‹Âz9ä|DGGŒpò€IZ)íNöÍ,£2}¸+÷Ú¹K¼·(〖O5„Z÷\ËCÏ*2'¨&Ö
+ºVŠ{uÅ«DÖ$, lÂÌÂ'ö˜=q;ÝŵyW¿æ(©2aŒž™Óžm>ô¨S=ãQÓÀÇjf‡`Ž¨U ò{ô½‚Ñì^¥6Äícš¨mÒsŒ¢¶QEÂ*D ¬.'Ðß)™¥zÏ0ì­ã‹M³Ý5å“‹<‹Ý™îÙ¶{®±¦[ÚÞ¢‹j~íinëõÜ{—þ6
+AIDqu;§çÜä~ýöùüö|>çy¿žçåÑ6ÖøÁ¼m™ß$“­ S³õ}¤T^Ú´1ëQraw:áÏ/÷ÀSÿ㪹4Í êHUƒô72ãnþKÙ^™sbiâ†×$÷<µdäÜžªöñžžylà“«’f«œP0Ç/º¶þšê5Êd!›¬?èhnóïIzƒzÞ<ÉÎßV
+ê½za[ÕP¶ˆ;#Ö~ãgëPÄ*<Ëècê3±ë=K¬2Ókt
+µ éë€NÆóÌòª÷Ì<·œ²Ù‡ŠµtÂî¬tbc‡y57ê3c.Œ³
+ÜSä´8J-*¸âDĸäðxßêiÄ À -€ANxË¿ý¥£Y0Ê×|Æ¡Å°¹kìÔÖ,=1‹Ï÷Ž­YnÙ¨™ØM¿féÁ5µ‡“´÷
+r¸#§íNã3íãȇjiÍ}K7¿L'¡díŽaŸFLLÌ‘¦}8ÃA­p)g«Bàp‘”·7‹þ+¤cT©%×xôϲ޳Uï:Ô%¯OÙŸÆÿíRÒþî$gF)xœÃô G?2Î(-º1Ï…\ÛⲬ6å»q"䎥ùp„Yôsyâ­8iÁÅs‡!f»§™ö×è‡;°øUM’[Y—ä[àÖÚGq w&‰Ù‘5€|jf#f
+…»oëSæÙY×W¤EÑ[#˜ä ¨
+ê8ð…–šèõ>Zªw¾ê] Û†Ik=µ÷œcˆx·
+ûä@î=Ôòþe‰À5Ë©óš…þ‰Ð£3bà7œ8„àGpÏs*<
+ô„Sf_Îʵôá)hﱩW»PÉQ²º‡·»ÑßvSËÓ­
+Ég`£Ý*zÅÁ’ ÁkÑ‚&6Ê«!•ú4,˜WÃ*·ÊÑ)ÆnØýµ7¤¬Ã‰Ì­gÒÜzÒ·.íé¹·–‡Ú3¶ˆŽAï;Ðà
+6&*ãü:6É&gQÞÛÅmŸv$}Çf.íÔΡøuÄ¢mêÏí)<DÛ¹¯:÷~ÅÁ¬¨ng‚±vc~QE—°9_ â2þ­$ç\9Tpë6dzܗ—öäøŒ£9z¾žúâHM+ô¨ˆù;JFáê03s ¨|à™ä![ŸÖonƒsýÄÂ%›ÄŸ^ÂÙS·ŠVjF<ïGg^à!7úê ÉÖÌ/:^ÅkKå̓·ä,ç륨þÙ•nìó[GZ>|Ì«&f;Fj~äå] ß[‡êâvÄ ¹ž^ö$æ›NNì'W‡*´Ü*;ù6СÖ7ˆDí«Âë®·µ:>®Ÿ”yy¥š÷ÁÜ6|¶Ú">ÑР–Q꟧Zú1ñšWèØ^Jñ㌢|Ó"œkü—^R²m€údkˆ•»$©»×QŸöMkeâ?=$ÈÊ+hœ©­üŽŽ˜XbÁjFIÄ
+L®J’óÓþæÅ{;˜Á5-°&‚kBÎÇMéÀ‘‘\¶9‰N’óKòãoìÏ4äEVè­Qdš{ õ$¢#ïNÀSW;Š£åÄÔ/탄”ÚËXVñï—æD%?‡M
+âÚ8NEêUSìeÄÖ9u°È®qÊRw„çA
+l2LŠJ¬i,Ý÷@‰ÏrªØˆ¹æÊ × äž`ì«)`·†qkXÕZrJ˜é»Ù‡L:7 k.pO²÷ Ô‚ï&6úO«ôË‘‰÷X¬­±Z”NŠŒ>Ðs*=³ÜÛ !Ñ,)|2%ʾû—è×ONýus
+Ï—¤KãtVÄ?›“H=æα‹8P³ò÷ƹ…smÈ—sMØPµ
+zú}CCîßg>UÄìkxµgý†Œ&ø±&j¾°
+xn dFDnÈ+Î̬Øÿú
+è2–n\¼ÛX‹>²Ô<ólü)ýžzéñ £|¡»*\ßT¸9L†^¬Ie. ³pk°:n£˜¼ÚKNÓŠJ_ Ô€üf%…/÷'YðfZî¯U©a>º\þ¶Š׊A¾“‚„ÇS©K=£O¦´“‰x[ÇAS‹ÞÝäfEþX6xfüÔ’³íòª×ÖÎÂ'Q†ŸA”õlkœY@„ÆÜ¥äÄ=uZML”¥òl„wK”|µ­8äÊÊ'HÀ±‘QîPó‘¹ïŸ_VƇœ˜X´¬‹ZÏæYxû0<d­öÛÞ6ùÂ*nsiy¤Ñ:Ès£úübA(:4sÑß ,ø¶‚’åW¿–¿Xë­ ÝP0³YÐhobæ«ë3e‰nÀO7åèTë—’(SKaà×ÐMôõU%7åS‰LÝÕ3íJdô¡±è[­}çËZ`f§V~-“
+š4¢üp·ŠXþÝ.ï.
+Ì%ÃįŽ–=4aìS¼*)£*Â1JÍ>Z` fÑàÝIdìú”€ oCEÎó`¡³øMmKù–®ÐÚ0ðZ+BުɼÚÉûcšZvÏÒ‰º¿Ò‹yä«~åS
+X:" »¥~}CžGQûæë.q[|ðM8l @»ui܃ßUýݾ¯¥ ¶¤˜”QØ%¯KÙ›o*òÏs ö! [JËû¯cøNßÑ2ÅA½X#AÎax¬oà‘êÛZ קãÔü°óÛMœ&§œY¸;Ï®ÝÕKŽÍLàÜÁk;±rè¾yRþž†Ü Ôn))ð-枦:ÇHï¸Ä-}j ÷µ-d’S¹%ïflN´×­ 1¡¶~ÂK9#/bœ¹é&¤x䜲} µ¸É=¸¿Ø&Úѳ¨ÛsM(·
+Èû:\°§£Uú¹¤o öÍL'[›É‡f>{GÏ#i™]+,z‚˜}]Ó\tkMRùp_ 䞘¸Ôi#Ä2T“¸3G+u)H™{zRO‡ÏrHk_»Õä‚ÃÁ§¦”œY['6gßLÇýtñû~¸DcßÞq²ÂámÍÒk]³즜žïQÑaß7:¦÷L<Ö‘•Ï?·‹eç+í_έ­œS î7 ¸N#×­àtƒ]në©ŒYéG/µ ¸Çz!*z– [j+¾íÄ>[Ÿl‚X—:jcÖú…°UIwÕj?3}c¼)c¹§,Ê".
+߬{ylàÔû ´J§—².%@ÎlÂŽoËBáÁ’ yßÈmÜž£û—x”C“Hph÷û—lï «Ì«d•9GH[wå!¥}º%!•ßd—|–>E©›K"{1ÉAc à qUÂÅ/¸÷Ásüòk±<@HšiGxˆÔöt²­·âq€~$¤‡¨Y¡ üÒGVqu²£ü^Û‰{E.H f忾¶§$¢×G ­qÔs{ì~u\Ð
+\CeÕ¬”¶D¬WÁ(&Ããí£µkè·¶ÎÊÄ !Ùhbsó^Óò1¼õò’s˜™³ØEÊ5uWðNàÞÎp *øÆ×¼˜“¥¨_‹ƒ:$%­Hñë[Hf ¹x{†„ 0P͉µ õÃFÇŸY(¨s‡æQ6äæðñ`Ž…óýŸâ:ñf{Mã
+°sežY:ìl‰ŽuÏ‘gËþ…EÈ?7óȧf6Ñ¥¥–œšùüo+BáÕª¸å§•ÇºX¤Á½zZ‘{ŒüqÈ“­o”T=>ž%ÏtSÓŒí 1C ˆEŠÝ¬ sªàáyí³´êÅrg]ˆC.*]ék*¶õ0@;£œÒ!dÌf?ì…k½7‰»u ™«ªª0s_Í›Óeßd­ç"<~ƒ×ȧ­´õ·¶+¿[Ûd&
+Ü¥Áfìë™°-5%ow„˜¡JÒouÔeþ¢çÖ­÷s
+¿âS•ÄOL-¨˜i!ê­±­>Æ5BÉÙÕ0Ë6†1‰€Þ[ûÑñ»ôϦ¶ÚP½ö¸±Y{£¸,†YºØÉÞOËXî'§Z‘毘÷Ç3<ÂB쉭»6ÌÞ[­$gÿ>Æ*zaÒ’ä"B(’vk
+ÿÛ)ùÎ85ÙwŸüW)óïs⢗»cÔc:—ùòf/âCðµEØva
+vÇȹ.*ÎÖ‘÷p†“ñpSA€®ªè…ðô?S¼à|‘QwÜN[,Ü(‚<@ÇùuÃÃoN“o¯«¨`VeZ@eJð¯£ÔO¡‡à2þx²>åp¼2uŒùþq;,Äw†•õ}ÀQèû;JJnüwƒv½Æå\[iè³9B¡g
+™=-Lû]M؇P©´Ü09>íþ++hšYðÚ9€M?Ö‘ŠwÔ8Ð:p ôìÂÛ2tÞÁ”¶ÔËÛRÒŠùål«Ù•NíþbëF¤ 7‚héA>
+<èÕª ¶÷×Ä訓eûÄÌi:Þ» àìÍ°tbèÓí|öJ®ÂÐZ•²­¬M0@þNYù«#-ð¾‘RêTקúàÇ}3Ón ¡ØÚS·ÜQ±­Æ€<Óä²ri6ýÛ)îÝ›ÆezfÈÅçË\Æå
+Wp½Ê“üt›¯ìBñ…UÀùnç󬋥ÿÚ÷(å×6aÓÖDmçlc
+â?ÍrÜÕ¼–Õê× \ÑO/Ú¡®o|Ú­È
+Ðz¸!~æ]žhw-O´nñ[ÎÜ ûÝDœ2±[ãZzcZ?Þ3‹y»Œ•ƒãÈ÷»B ¤›¹mÒwAÞðá"öÛý¹¯cëC?köK£M…¥˜dŒBœAø§"7}nUöýRØc¡B „+¡¤"Ë#wâkãûKœ†¼Mð¼â’Ž^Ñó&ÖÀ»ˆTqæPcmñ-ìwäþ'´”{IÐåß”u”ÔÛ
+YÕ/ n·
+²NGvwôQÅÎê¬À€{Šò£O5\_°(˜)„‰­ñ’Z~Gd‡ûԷƲ¿-Bå]*ñ¡VÐ Ï2n% 3„q^’1ɱÑ-öã#§ùãžœúe¿˜[°!½Ô ÷ø„¢ÀÕRa–1;2tÌ(Ba¥CTXÚÿeáRÖÈîÍ›Øe'€ÍZ¹¨„a¼#¼ <MX%ä¼kRyžZM;@RÆÊ'¼ªÖÞÄ• ŸZܙ㴓D×:óÁÞü`]t‹I}8¹ø>&‘Ÿ¨=UËHCÙÌè.X¸øØö%´öblG<ú‹cšÚõ!"_(#Œ‹o`°IZþ¦c=ü‹ŽÕp¡‚ÌÉNrÒ =OÌ#Ó$=‹°$g‘§vÅØ£m 9¼È¼^»“Üå÷· g¾°+¦ƒÈUò®Û“ÐqŸåMÐ ÂbÙ«žLØä£Gvp`š¸Ö_üÛk¢Àæ,%®“ú§F¤×Ù­e _´‹G|[Âv »÷¢ßøià%÷YFt†—pW÷Ô _DVz®ä­|LÒ6ÉM;§d¯j"ï–г619·'eäœÒÑŒÄl¬¶¬ž|?ckÎyÀ!ï·U<Ú|‰ÝZÿ§²QL¬Ø¬‚EL,»Á‘<, 'í1a•’‹ð¤²œT—ÂaÅ#=†…¤š[D;õJØU—˜–2qÛ÷—é·“;6iS\ÓäoÝj\]èöâÚ×b›øúŒÖT‚…ÿÊÈ#ÿ"å?5Ä.Ú\xyðzh©õ_ç>ìÝ×!bãI
+ívѨÒð”±ËYU¿JsRÍ@ò»bg÷eMÌöŒ]ø<iRŒ=šßÆH«s{?·Ç§ä\àXÑP²Öñ‚CHÎÙ•<‡jä†GCTvNM& blìØ‘Ô‹Ð1½
+„^˜M¹Ìr€Vœ¶–0ì?t‰p_yx¸»yŒKjÙNöÜe’EèÆÀÃZÜiÇ9„ÿT`ÃU^ éÆ9øAB,$T®iñ:Aœm!?Vm«w‹¦µÛ¬[Õ¼Jü”ñÂLŸý¤tŠùæ ç'[w/lødtë·#²7ŸaãëA˜¾2Àò¹â`.œ›é‹u7iã}Šºñ!ÏØ»Îò Z˜Gªx!Œs)ÐŒ¨ôÕ òøÜ «˜ÖðèW)6ã`¾dÝúWÕEzÜö3×ûÎ^Ë·?]±nÞźßX/°ò÷²ùù_ªöµïz~Ì#±®ÕÃòº‡ÎÙ‘©æ3Z؆õ²ç¹SêxÙ~ør˜„DW¹£Ó^Þ„7ü¡â¢­w"aë âÔÏ
+v;ÊÜn¹»ƒŒ2xîäl¬ÔYì<œNBÀeø¢wYñI?-ÖT#œ’ïàçZ„¾Ò:©U?uºŽl~”\g”¾÷¨*|•QØ+¸‰OòVx5¨ƒ^À믗“ž^Æ!î Ê%·Öj ¡Lµ1¿éúˆ/:Q¹,làβqãŸ.|ó§ß= òUVƒSJW= ÑsÖLê”û,¦%Mð"o}ú÷â剛5›5JJ >}ˆýûÃ3>³ê–ó&á›Ô©h>|LÊ–?¯¸5äp®ææ¬4‚ƒœ ZÊ:Žé)›lµ1žÕ¥èV‚%¿ (zx› á‡s3kµäTò3Nûi@§'…e¢§f¥ëRr-\Aœ‚coòYüî]šº~gï]aùÞO©Cí0w«b=œªÚ˜¯{!ÖÚ(F_éGhËu?{µ2¦J`£æ•0s§´Ç)ÉÒž—¹ÒÄN¤t"œíz€½–³Ò&Ó˜›÷ÃBáUJn¸Ê€¬AŠA¨…ö_5#œÝND"®¸DT¿w«$Oã®8’¶ÃRiÓ n£ü½¨hñV¡¼îÇ
+da3û:ïd/tÏ ÖeŽNdöß”ƒR0ëÕUB:[3ªväÝÚ#Fµh«aåXH­Xðñ¾Ìj9¯:åÉ ¥03Ý0)êq¾›áP9©e˜WFGE¤Ÿc3+ž'e7ñE=Ò²°ѱÆÃZÆjÚÜÁnÄâE˜‹Ï»Ä~Z¨¼,úy™»™”èëq*"/«AÎn#)Sõ1®ûÿw€ÖŠîÏõÄ—£ “<ÊJ-=T‰äíÏÊnúÚ #³ PX1Ì
+Â|“¶RÆKáÕAI»®rå­$›ÚN@À° ÒÒ°x˜¥nŽP¥•K“F5!¢³Q¼*Ï®Q¤b¢óÿ–Qêð%“ž•Ðð&¼"æí¨zP8Q®ÌVaÌbÔ¢iDþ6 ïŒ_§åŽaFªoƇIëyÐÀ{0ê‰Nµ§‡•?íoø8ŒŸv…h‘Š{QPv –ÑSù¢Oªt
+ÔmíS!‰ýùÕôoÌŒµ;½°Jß «M­°Ö‘¶IñA½ïVé'šµ”Ý$r*OV­bÍ”_í&&,KÌì=ñh¼\߶  O¨k´›´YÂ-ÅûŽ…¬{èZ#Šã7 Døˆ‚À <áÇ }ìT¶ŸÎ…†¥¨Jü¼äá̤‡m¾À&ÆuÊ&ÝAÄìïõ¯)5{Úãä̲KD*!R=ïP‰áßE™cl¯Ú¹Îó¿¾Q-*'ŒœWN!é =•òç°æhùÜ«
+UÔF°¢(.P©ƒQAF BÙ#„²÷"óÍÎûfïY  ÔU­×ßõ¯»ïr|‹çñp°{‹Â©½0ÿÖ?Ý´åeu&ìŠßüf;Ñ*ƒÐ!­ª3i‡‚:]r²:Ç« ²Uà ù„àV¨™Ø *û1q7!¢ív/Êx¿Ì"¼?ºÄA‚=±?²ZTDJº=ƈ#-¹½Æ0dÀëdPµXh®`Qõ7IÃê ¤!q¶®ç»ÙB™U.í˸Å#û‹¢™·KÂV„ÖûyCþµ¥N~Ý»?®q؇¯ùs{+JÕZTNy43>ì š´¸Hƒ_hØé ^…tc1£yfQo-B iÙ)š^óQ0+6bÝaDLý˜Ôº?¤ŒÉ/Uè´ þs] þg[¨ùë “û¿ßyúÿî‹,o‹M_6x¼÷)>k'®R¬tó!«nÝ'¥¬¤Œ%;³-‘p?¯sx{‘™®M¹ý "W~ZÑß'¥òͨŽ€¼¸Ï{õI>,_ùq”Œá~,'êošæ¬ÕV–¥e¹ž“§Ôˆ! í
+½Op¤ZA¦TÊI“ýÆ#%¼[6ÆwbFÛjÈ ñÙô£fØ;Ái¾\2ì÷ †³* àC2;>*×¼ŠécN©·ËÈ¿äQ‚O0虋=õ“ùcÁ¹‰.n®™¡¨}3Ø>%U¦­€Œ‡y­aH7äÐy& }”hÔ%ˆ®·V@qÞŸg-¼%éa 7ÜH›µÝâ©phêù5S'Šo¢³J jŽ5=ìÍe Ê­ü(6ZÆä¶/IBǧeROÊÇÆ9¤Ží®é¶r ÇøÈ©wö9UdǶü°zÕgýF〙¯xÏÉJ$£„Ÿ‡jžå˜ ãUÈÆ?©¥’*øß²£c0è»ÎþGï‚-®J¡­¸k=bsp]jm‹ŸYÚ¦¸9 _õÂâ€A²lUáM‚ù§Œþþ³Ðå~L ¢”c´KŽ¤)c×0÷} gÃÌA¿q0ÚWõãO7-¡˜Ý!Š8ôS»aÊ£“6¸Uü
+¯ÞÐfRy;@pÏš‹gÙ×…u­\ìAÍÍB°hòUtÃÔÕúšÑÚ›y½¨‘b1QôÈ«Ò">X¸± ¾=rÛ^”Ò›qS^ÉxÌÑ=&I)
+a W³ˆáhÑü¤ÙÅâÁ ×Ůٙ–&öqd óøµÂg@ÑÕ_²;гg飬B-Kô< ƒƒé€š¹½ cF¬7>r÷f€ÑðÃb—ËÃ4¬j…µI­òwKx®JzÂUþ:;Bÿ¥=zc´“v«»™tU?r± Ù™7;„½dsÊ-B)Æ!3Qb›æ]
+´þ~ä’/iáüß;bÓ×Mžàsô\ׄ—5–L”,/Z@—ÙF‚A¸SÇSþâÐZð“s’€µV‰¬*`šo Ùõiÿ<í5uøkZïƤâ°Û£‚-q®
+ÚáŠä»8"5qo`Øœ79ç è¾GÕÏœ¨~>’ÓÒÈ?ƒê„O]/~ü©ùXÙCÜÉöFÂiÞ4ÿšK©hL9AâzÐlŽxÃn«ãµZ½ždÉß´2$_ÑTþ‡ZyùÆô¨û2y̘›ð\%›òð}úË]Êó˜vÝYT»údQ)¸úS3P]E;>2*
+!-TN¦DK±íìÝÍÄl+éBCÍÄÉ[×+ÿÙü¬ ¡¥AMº9Ö53“o&<ËÙ0NÖ…Ü#lZ ë ‰I¡:Õ5Ã\º‹0ô ZzúAï€ã‡Ò»¸c%%Ù¨Ins—îdñmp>¿È+hÊ*éYù?÷÷Íüƒ8*1_S~›fgI¥Ý\àOÆÝzÍš* Ûd†8Ó0H_yZE=Qr»7»ò9ñÔ«.óéúVýñÇ/èY…7{‡OÉYå5ܬüÂ>
+:€ìl€@Ôeá¬y/êا ‹±¹/ëg/A
+#v?)W~]Ÿ7¼_â3Ònño1—Gãw…õûk­Zã‚Ð;S´Ñ05ë+$L;ŠÈÔØÝ)Òâ-NócEötCÃÜ·µ5øs Õ(<ÏíÞIH;QÎ¤× S”†@/K¾ÙBl? ¤Š}æÜÊFê±êÚ7Ÿ—o¿N»\/B*é@Ñý ê~ÊfÍ™KÌJ&nS GdÈj!ÃæðœH³ÜC‘ÔÿŸ¡òúJ3A ø÷aPSMuKbï[D#¬T°aC¨€ ÒAD:R¥‰"5–˜Œ%‰™9“Ìî™Ý‡={Îþ3ëë}¸O¿û»þmÉë,cpf?¶±[V'o -+aU làeÑðì®ë×44W: dÃæÀì²™{C’˜u…·'h6‘¯|jѵ_¯>ñéÄ[6nÝ´Ñ»¨>iÃÍ}LÀ£ºÆÝhn ˆ~…R²F€êz˜Wµ
+à hA=Z‰ÒC;ð¾ÒâiþòÚyQ{@ l:—N+CW>Þð{3³Þ,ሹ–báêI;KþEâݾ°=yÓ, ¿Û¤!‹+˜@zÎ8š=rç::PÔ$’a H\!,½”©ï²Üo;HÄŒ™35K×up‰ûe{¶ùÆËÆì[#:‰µE¶vŒ]’ÂP9ÇE´‹”ᙳ„~ÂîÓf”2,«˜ äW0 Åðði\ð$"Ú—#àõÔGØ.Zò{÷:ý* e:Lëx½i‹¬Ø8›YR]ô/J¯ÞiÑ Ùñ¼¾sùAuóB8¬‘q/&ã-U ¤ŒÞñÆ… z—Ÿ0HÚ×&åÖdÈiš¿öK(gvVÛ±m±=d¼Ý´Z§†"O¶ßDçnf‘¨®øAÒîËÊ6ñÝMBÒóQ
+=N¥ñNÊõ¡q¾4Ô0>mOª{+{\Ú ˆÈ«¤ƒ¹0â#`BfPRCK„À‹¼q îî£
+$
+íÁÈ./ØË÷ ʾ+oàk€=âQÐ˶͢ɰMà‹œe|Å%z^ùG7IxY30ãÉAã5ñ#SÆç“T×+ä€öyf)VK»Äáõ½Š˜æ!YúÔ‚£„'Ùm2n„¨Gñ:(ÿqºÄûǧUã‘O9ow%Jë9[ ù€e Ý•‹,S.K`-¤0Í}ãí²”–^~jGŸ ™ÌóWøø4»bYj«qmꇂ®uÒ¡KC¹*DŸÝ¬®+/³ëÜÉh=rðÐ…©×š{µÆ­A¡Ô^Áà[²É<_I'ÞTݶöKz%ë~|6,~CG`”ÏXC4†vøË:Îꙵg½ãûºuöcîÁŽõÉ5ßñÙ>ZþÝOüóheùܧä¸\[kjÛ{öŠþ¿(=~Cæ_WâéÇÉÓ»q¨ASdZÁø0 $¦ß¹y RÑLL$Ðä0ùª¾îÀ¼6òWp|³³:r;ÕÛ®-¹Íî¢ôž!…:Ø'–Úxb_5}Þ‘M¦Ùsð$ó«&´è ¼‘ÛÖ-~5BXÏñœ­Í.ëÄé5 é?DÔcÃTi` ›úÁ4 ;r/zœšFmì`3ù) ÿW¡ô¢ûk†Ð¼li›xD!É^Ì2¬)¤ËKÃY-^²w™Õn¼oC‡»ñ³qÎþëhnàÇ.µó‹{®å«‡Ñv §WøM+ÛÎÛtØf6ôfŒ^ëìS«|½¢%W}ÑM¦ÊÓghº,:S_¶"Ñ äZ \©36Z5Ž‘Å5³m`ýÜ—.üû„7÷}o¦ëÊÏ%ù Ú}¯Ó¸ãÝ”8\•JV+hó©‹¾ÜQj ‰QÅÀ‘(²Gö  1^ÑD»‡èCê0«õXYjÂM`îét's{žÙ±MLøyÀ!ÝîÒ±·æð_'BÖÇ=Å¼Õ iQ«ÕÍ2ËÇ9¾úK¼¯ pBù“óÁìÊvþÓ¸ä0!¥(­¦€¯›fbpâD2É”±ÌrUíhŒ¸ ûbû……X~ë[è¿q󆾤Ôî•A«†SfÜpª×ƒÃ*ÍZ½áÃËõNܪÜ\/Q;Z8ʃÓZ>A§RYú¡ÆÓYíèÍMÃ@À³N<÷+iŸ ÿ½ærÿ÷M¸öŸ+‘äÔÅî
+¸l×µêñnrÿg¨¼ºÒ@Ð0|µ×s³çìÉlÎ$“¶³3“lb2›˜Lc¢qìbEAEEªô&(R•*½÷. E,`k²gfË?YþÀwñ~ïû<*iŸN"þ¬^6)dÒ¹Ê
+–k,“2•´²bí•j…ÍI2˜e “U—¶Òzóž%dÁ»„Ùñ,ÌÅðºy¬¼Î¦ïG9¬ŒŸO Z–'L2ÒÙÂØíú‘H©ï¦.[?LãÕ&hÎîYa# /{‹ç¹ð<ç»y±õý¢ÄðV¤6 º^G~cUz!Oí{aŸ‚؉JŠ§©d$èªÁï\ë*”R­ ¥æ¾rƆۉÜÐGX«]Âo?ôÐv€žÂ)ì×b½ísIð1ÝÜç„°÷¹“\ÿýŽ ×Óz“&öLÜ*BEŒ¼Ñ€F4ÔK&|ñˆn™ûJÍW·ªÖ>ß
+Ô­Z&R$¤ ¥µ’É=#æÔ/XªÆx‚ã m2«Ã·ôÄ‘JÅ<
+1i­?¤[ìsH¨MV!±Ám±ð5ZäbEÚ¢q=ZN_À$ž Wà·‚½Z&︄rh‰XÙ`³.“‹ gAT寮ÿAR2tφoÏè Í[8éXF¯hÝi7—r )aóâ A0uOÙúÎ(@<r©x]^£t*j¡woqÛ!ëȿ檄ش‹0ªûÄ;ñz×6ýfË<û.ë Ã
+{!¨0§ì\DÄ8èè]î5^¿nUó´ÍÜyý NóLs>ǵ?à‰üïiÌ•7‹ËºVXñI%_iO95ËGaµ«ìã°vlDàe„·|“nóÌ#/¬5&ü»O¼ï‘Î>wkTh܃ÕºÊW§–•8‰¥xC36û†€&Ç屟i•k ·FOL˜”‚‰Þ{ÀŸø  «•S‚ëý ÿ4ÿ%¬ÿ³²Føð¸éÏ1ƒTˆ‹¤)×"4h ´8ä„·V á¥kÞ¸nçŒo'—h¥$v¶µ(¸Ú^’ßäôË Ìàurr™ÄOŸ„ç€Y ®3 #n9'ã3Oã\þÑú2·âPÂ,T9L…½Ä‚‡ÔŸus[~¹<äQK1&¾¢ó`ßOïyÑ€¢ ú:§<©®“_s{”½i4年$õˆ÷Û6ȯ;>âHÊÃÇÖœÕ
+©/>ͪÇ4ßé×àÞÌ‹½QŸŸñ³`9sâ(Éá^å¸Úã0n¸ìÇ´Ÿ§ôë‚8z‘“„Ï6ÙâmcƧfõûÔ´îx͇Q‡Œîµˆ`Vd²šTF'M«±áÍz Âmæ ®»­¥M6·’`±·õc/cܶ[1Iÿ»œ~ô©“¸[F7ô®…ÌiáõQaß½„xäÑŽy¸mãÂ#ZZ¿–}|ì\\Æ„ª› :áÀ
+y]Ô€~,êAKvxá Ûš3£ÛŒ¤®ûY)¤å÷v€·œz1'^L×y„
+ê:NÂ^E³~ôàu ü²Ë÷”ÀÇflKý]ÄÇ;|ç£S+±ûÀˆútbǶµ˜Æ‚nö׌úÂIíü¶bgÁOÜ ä¾Û¶%™zyjCw\0}AT×¾ü‹ŸÓr‹ |ò'?­ûé¿ãLÆ×z°lìý[QÕvëÐüùÄ=Ût Bª!®ä ‚w-3Ç^L÷™7X "ÛK`]A3ðó~íG#üMÑŒnºŠ’&/Bxð™4|è„54º´tâÇÝLý±{°©„¼ˆ
+‡îÍÈO™5hÓù±¬‡>O þÏp™%½æqü§¹gν¶x›Û­îÔ”“eii®•¢!€Ê" ;ˆÈ¢b˜Z¶Y™¹€,n  ln¸@
+Š¬Â—Í}ºÝéÌ?2ߟŸÏyÎsÞçó~¿ÞOÅåí5׶ëc·Á™]»@#*<g—7Aýóäív¡g’U°3JHöLP²ÂjF~pŽ‘gÃ?˜ï)¿$f¢|Ê6ø©©GYì zTÔ¼°¡ ¨Ùe~%ÔòêWÆš ¦ž—ݶ‰›²¶‡qy^.+²@Ì jÐ9ô 2pjÆvBDßÓ h{EÞ…ç4ÛæšB¤úµMù“°Õ·,jµMѲ
+r^PËit(OÖßÕŘÞVÆ
+ß,
+hZÊÎ6z^žXº_Ù&H{“ô‚ N$
+ñÎrj2´À(þsG<]â5ÌÓ‹¶?•ßqŒÕ&Y?WßÙ«Žýïnç‹S³@àRÑ
+lã”’®Z¤U¯SàG&2Ê£&•ûuÌÊÈ
+sjuùf™¥æDÆú—H@ËÀ¯uu˜Z›÷g°9ÞtŠYJÎv뺇æ¾?mýÒË‹>ÿš¨Ã¿ÔÉt,Äá*—0p±€^@sixhÀÜû*hy9°§4X%MI»bt‚S‚yè–6&4”üWþi|ºwŠYjzÐO|¥À†U]X`†WœãVo â­#˜»»ì}‡”œº'ç™6?‘’BÊn꙾§õÌbß\SæâKØ¥¥nè9ÓËÒk^9½PwÝÓ䧎qÔ}‡q/4G„,Ћö¤ø¬­‘ÆôÍ¡zP'|â;0
+ˆŽ lŠm¤øŠ]\yË;IÔ¬â®ÐPóÝ“Ä4`®ìp$×$ b#<
+.n¼«½éWrkí2JÙ.øfÏL3˜£ç»¤„TÏ81Ù!kÎR‹¯‘Ó£l£M…ßVúúŽt\´e°:nåõ³+æÁ¬+¡tÊ‘‘Qz kAÕ-p·ª¥Ô§Ñ÷Õ"Æ·•NöÙ:Ÿ\âá|ZN­žYp`dÁ­bLÂ×!LœK&À
+ܳS º3HžjDܬÏ~hŸàŒ}!æj¨eˆ~¤*ŠÙûD
+2‹ÈOMeÐÁj¤«˜‘à¸)¢í*Ʀ¬D˜¤´ð¹ÆL¦â¸#Îó^ûX&}óˆ–ðM5Îïr¼oWR£W鮳M°;ã5 w´­¹Žññß›ù¶±Êô#;ýd¬–`æ¦^Mðr†Š¢ÇkaN#œ¨ o_¹w²(èù·ˆ»‡rF×é²ü@]sŠûFwVО,/Â(Æy¯vå…_Í ;­
+a“^Pµð–^ï¡Ä\Í–½:Ÿ¢Á,rBˆ¡;×O\šàÜCwùg¥©áëRË:No‰tf;ïö§zœ¨©1ûjV
+7Ë÷Úd+2ôr±ŠdUÑ!rn’;ÅÏ¡îwSÆ€þn‘€Na£Ÿ(R’§Ãªˆ÷`÷KmIæž °Ö™ì>]ë$e†þ®kKqÛWV¾RÖeߟo'_Í·Ö]ÎT•¤(“(Å]Î u˜¨KuVÕ¦‚vdTèñDIÚbÊçRÇÉ¿\øo˜¹ äÿ mWåÁ–…/Ùýl®"{KFŽ]íÊ|¸/#‡î Ò£,CEàã)FÊîX1ücYªs&âàå ûD ÖØŸãoì#ø›;) !öñ" ¿KQV5 2׌pý܃ ýiæñþZåP€~1ö|VÞcŸh[2}ûüšy ô™¶®®M¿ûu¹¶úõÍv )~oéµÿ)/rWJˆ8Q$}™)Lüw«†;ÝIH®!DÜÖ÷ÓRÿ6˜»4´tØ'*ÐÛƒ¯™úøÛùOoͶ".WªKðÁ·ôÝ„¸ËùÊ×yñLMzñeŽú}:U7 =uï Ž"ºÿoFÄ­õÁ˜á¤âã}v†*“·ËÀë)3-X¯éF”ûLÊås;ñÏÝvâl{ž¿¶%Ëîa¥ï ²öËbÏÆñ€6ÁÖJ8лOõ÷C%°sÔœŒyxµ;´Øç8ÇOúCßø
+|ÓFõ—Ç;,µD
+àqnæ÷•æFÛxrGVµ-a'Z¥ô¨cy®Ÿe ÛwSŒõþÜ…´*y4«º¡H'${û~q&µÚY:ÏG9¯¼Ëó^êÈ XzöZfûi¸ùvujSLðÝèÅnö’ÁÆnâÓ.Ô£ýA´·©?;|©=ëQD
+;Ÿ­gδäxNÖ¦ÝrüàñpË#nGZm¶…ALìf@],#e«Š1ÄA€šÐÏ“£o¨*“œ´@>¬‰IÑÛ£tæQƒñûïÕBéd²2ÛЛ6ÎOº?]—â2[— š«K}™)Ãðñá΢Šä€Ãé*âþXr®>ÃUÉÿ5䶶5Éiºì`UàâlòÊ­šrøÙ,lƒŒÝØ ­n\¨¥Ÿ2?zå}–Ïzo¦ÇÏÝ×ÕgZ&~U„ó¶©i‰WËí‚«¥¶·?Œ o.K3
+ß)‡ ÖfÞ—ów†™):A^€s½»0òÚzs” »©kB¹D|DSaò6jŒó‘Š[p0†MQ lZäŠå¹Ö…¼oÌõ±kèñ‹=Ôg˜¨ë my`sê?`ü¶û
+Ÿ¬tä¿Ð '˜&‘ Ç2æÇ:µì¿ÆFÊþ%ùLÙˆ:Ñ“‹ý&%'üc³ æ­ë„ùé{sžŠ‹£~Y˜•æy|Š¨ öèPLÊ:–¿§ÛdMØëõº²sme걸<òDFL¼\g ~˜;úϵõÄ# !ñ³º¦ø—©…}k¨AŸ,¡cNd¨Ø½h°é#ÂÿBS‡½Ñµ2œò°‘ùÖ.c@ÎU¥WÚ6êårc ÀÖƒYhg¼,ÐÌ«xi›£¥*Úð{"&ä@X´=† Ûà üçªâΖ
+lrÒÖH±¯u úªïr.5£÷§ª¢Õ]Ùª»Òþ<äáAgâèÍJKõ”“wç=ÚåU§Šêaªwðû’º´{&Ø}–{o¡&措)ãþ!·2Ù)k*^jÉñ´K9 iž¤%îxçÝ0&h}ýÌʧ§Ú€¡Ósiqšše'1RÏÁ†™¹øðcå/Ó4+ku¶5NŠ¿Vwµ/RRç«ÏDM˜SA þ`’2s‘þÆ Äó­1t žCŠ>‘6·x”¬à]¸ø×ÿ2"ý·‡K‚V{P¡¦ÉÊD“€š>Uº"ÓÓ)£A?ugºëûÓÜvGr¼ ÝÉÖ©œS!.óËj3]Ë­ˆîǧ¸)ÚŠ_ýÔw»”älã0Ü{k ÏÓ<ŽòÛ@‡nŒ—GÈúJýÐ/îÀÏ|[­-¹Ñ0à®%lÂÞÇÜ`Im¬Û&à7eÛ»61)±§ü÷쎲öm•‰q‰‘៥ˆðsIQ¸¦=ùùª¨¿oôäù¸T¬ò.1Ü8‹²K(9Î%*üLJÍu*(P 'Éú‰ÒЉjðÝá
+ðCÝ >|¦1ûÉö$&Ú:GLߟ)O¿RÑŠnWÙÄ«•&‚MDJZãäzZø¤X3°ÇÅ›LK]l‡=²À÷·ÆÁN9óx‘YÂømŒ¢ì‹T˜W¸ÍzmöÁïŽ=±-^]hÞ×4â #eg
+zΗöÖ˵VÆé"9ÕÎ/ Ýþð—ßöàÛ
+ôp¶"Öʧ&8¤µÙ—Z6îDR“á’3²OD@ÇÍá"/ÔÌk³È±ÈBìÏÕ¦\ªÚª¬zÚæ‡2_ãÚß<
+XíKóXëHõ<©JºT¶¶‡°¡–1|äU3Á%§ANÈ v!%Y7ÿl_€4ñP6a5ر܌Ñô?Rw<6pJCö§pQÇÓ”d×B=âLHÍ5 …è9…¾çŠšü3y]žU@Ž?˜¯LÐ`^júÑ/vF Q7š6ò¨±`kŒ:šëÄ™-pË,5Î2‹\ïÏl™, µût*¥§_iʎ汯ŽøĤsygq¼.w‹ƒXiÏ÷Õ'ÝW4¥¹_-wЪΚ­éÚ yk¡ÇéBMÖÀ¥—Úº¢“¥ŠDug¡·²é£j/ò¶JhYÇ
+j†ulsmÉízWÇWMs¥a1EKr—4A<w§0/ÊzÔ­®«ãV÷¾Õ<Cˆ´‰˜ˆKuO»KÑŠ7ŽWÅ®ô"d=ØÀ1ZÎ]U`áZ¤u¾$xŸ²ÌGç³M—Gœ/V¤ìL•‚ÄÍ9žÓÀÿ¸¶üZM‡ïqaÏÖßÇy?@ž[&K£÷&QáÎÅJ°K]WÄc¦»ËÚ __¬°ð_´ŒB—œ þÄùð1ÿ‘°!UÝ~š>L„¼\šúüž€ ¼QW½Ý†ûmöþ?ÛÞº®ÜGÛc%AgËŒÂéÖ|ÿœp¿± awR&îRË"Ù¥ Ý ˜ßÆ
+[Å%
+陚žÒ@!3ÇýDZ_~´È€ì‹ªSèðùú”'3LðóY%ôf£Žq£oì0
+i|6ø¡UJ„ÿ:líüia×٤ؿT]`ÏõÁ·Ç¢Òø«µªl‹‡þ»ôÍÔÅœ¦÷»Ž¿Pã“·yÿ!»€#ëó\FØ…uY.% y¶ÂÆXfÈ1ŽEJ†cs%¯Juˆ‰‰[c0_ãÇ|ãxi€KÙPl“ÔÂv'ˆáÖ™êx €¿Ò!
+ZÖ)Ð5†á¢@Y#øži“p»ÖÕv*§¦ÛªãBXß
+9Ñ¡Ne]Ñ™¼q$bBõ>‡|Z†SÆ.1Ob_î ?ûÅeú–ôž†ñ·3çš™NM§™œvm,Í=“S©i(‚¦A. €²/²/’©õTf¹äŠhÊ*ÈŠ‚¡ "Šl.Ó™y1ÿÇüú ¾×s}Ÿû¹?ÛkÈ¥%Qñ_F …ÒwÂRBJ΋mYÄ=Ü~/i—Уf.*¬g>ªÚËb:p˲À­8¸ E¯Œ°z§éåÇf>¦gÔœÙ9èc3¿uožøÈ7…Lß›ÅdhàÝyl„9¿9A/ ,²¡þYB‘Xáwö¶¾oL•3Ê~8Òs÷Õ¬Z0ÞŠZ±1Ž{äxƒÍ^Í‹èy˜C
+tiãæ®Ø=I}lúH.ÚV1Q§.!Û7Ó\ä†]ŽY;p‘•ÎΘëUßMH÷¨Aåwwi/é(U@ïA]Ä{^î¾ó}mʾ›çnÍ5õ‚ϯ¼©úÉ7‰É‰›ÄÄ°YLô+ÙU!­°yk’˜#<ØEeYÀô]ÓK«
+zYX骸uIrQx¡£.n´ŒJçtºã×ú+{ó5ž)Øô~ic¨%ÈW®û¦Àñ &Û7Š/ˆ¨8ˆ]¥Äû©53i÷ÕÄÇ‹mù~96÷`Íø2½:¹ÌC†5B¤îdšm )÷HË©+)eI À,:&l{–Ú‘µ>ˆ.±ê‚
+Z¹¸ç1ôÇ£evû3³F×Oq¼E¤øç …>y[ÎÚꎵž–0ñZ¶çà-9­4n—r¢Fv½_Ì;‰Ï+Õ­ø,i
+(Dȵ "h}Œ
+éúºÂúþÞ¤¥GòÍÓÙ™0Ójý2tîæ(2ݯ`<w)DmŸ¤2aÝ•°FܘcBä”òð"ìŸ#–îÌì))%G–—,×½Æþ®õþú0±Ä6ˆ-Ýk.=6ªß ·$WhHËûW]1 ¸á•x_#&:êOÖ8¸ Žðtg¶)/ªÆÃNìbºo‘ñ|˜ZþcPÃnþÍÓ;· )1§~KÖV´(ùùŸ
+ñýÿ,üÞÿ¼"á×U>åPE*9¶KøGV5aS—ù;jdós{‘k ùoß ´5×Qi"fû䢦½ÅNBdIˆ‰êhÐ9þûæ.°;Ùq·%¤—´[Þa3mo®E—¨PÀÓ
+çÛ@ßVØm3¥Þ¯Âvæña#å²¥…¸l|Y“Õ‘`Ô…–¨Ï+\JØ!¢ sa7¦$ ùr!ê˶ò‘œcîäªøÏ.zêÒÏVyä?<Ò®¯.=` @vuTÈýÒ¾¯îþ"é© èC#Àú@ŸF¬Üà$# ±6ŒLßœÆþ¶ùzôØÕó.dÐ<ó„Ÿ=s$OÖ’é|_yag¢ú_Û 7ýr.ì@õ’àåÃw¸Õ‡j`·åä‡!%©$±L®83Sk¿gjOAy2v1ÖF°·Ý#õW¾L ®¹G·öfI%qmâÔÄA;¤°!¤ílÜå‘­¿æ咽ª Þiä=ÿ¾Ð3ŽË\ç©OÆ. ozá—Â*qSD%nŽ(ÄHÿ­d¤t®™uNÍ}raw}7f\£Ø ÷`ãÕØ÷wV…´Ó“+=SèÌ1àö/ˆà7Ý#Ä<µ¤ö⡆
+IZm £ %±Ü?Xlì›iÉX¬½hêzòCHK«nB?€K_¥€Ô,XDǬIù-
+R©o™ìQ~@ɬ;[ëé jv\$>Ü• ý3íùI·þÄ(¥…u|¤eycc†ø(fœŠZ†f–^ÑéÐfú³¸–
+‰k™ð# v–xhÛ䞦@Nl]‚À|[¡_Öœ¹3Ùúe¤ñvTpÛª˜·IYÚlšùW(¨îRŠ?µ01©Ò3‰HÛ–5eD´dØ™MÄ;˜~}’TP3aß6¤’“1a$A¨"Çhªé-$eåCÃo_¤½¥ëkLu‘A ‹”dæ³âf.)¬&ƒýrTADÙ^VÑ+–nñçš×ðˆ^ˆ™Dø##§éØÁ#Ÿ:ż]¼>Ï‹Y{^ÅýƒA økfõ¡ŠU øîó¤‰üÃÉÆÅ–Ù ÎQl–s 3ó
+aÅÕ-9眈Tïtó½ –I8´¤³»ÛìÊê8³ø{Þc6)¤§V­@.ÿÏq™%½æqü§¹÷œ™9·;Õ-»5u§©[ZÖµRº¥¨¹á‚¹‚ ( ¬"«ˆ
+Zèuiq+\ØET6ÁRpAdß0$[î9sæ™oóó÷ùáû|Îóy¿_¯ ·œTâ×q1a½y c7H¹ðó†qrŽ]ÞßâZd<ZBƒw¦`·½KXpØ@®JîöY{ûL/Yº¡¦«À\ûŽÞuwŸìrø
+Ø/§–;8¨à£Ê8Gq3³)fb4y¤ÙžE4Јô˜
+ž‘Рsb+¤’˜–‡õ+å-£1±Õƒ(U! .Ï»¿á˜©ºè™o½S pñµa¾_Õ‹Þ™¥HhU>M'Ä£À=´Ï oíÏ o¡çõe§C
+sbéã5ø¢ð–‚JJ±AX›f(<åÃoz¤˜ûÖIøÍ„‘R¼Éî<Ôu·Åt½íGf.iÿ-â–i°üŒIP}Î8Prfwr9¹†ƒ|0ô‘¶§ˆ ÝÐÓ3Àÿ݉­v–$èì›ë‘¶üæ‘`ï…–»Ê‚+Üfýîá&ÿ¯!5¥â °?±U| p‡ÂŠPµÿ¦þºýMÕ%Ÿ•ýi›Ï9øÂ¥@eÔè|ÿºÀ±Ð˜R·Ÿlòø_üq¿–ôÔøüŠWÚUu¨g¶¾ŠŠ®Ó`n%¾0¼Ü MêéÍ'ï8ŒÀJu‘]yMÐŽk¹$Ç|;È2Q{qo¦é¦GÑr7ªÃä}ÞáÐ^z²
+ENeWYjwhÜ«bÀ­¯ZÒõÈYQýåïä]OÙ¦QÙÉíÁ ‡¶¿gí9òÊö47
+iiðã­~—’
+Ž­<zÜDEFWp¥î9øíÝ—5ÿÚ¯þg@E«þ`pË ˜VX{Þ+%æÇ´´†˜Wôç6µõÛ\
+[úAßKð- ³ôü²³rzÞß×¥§ƒŸ½rbQXÛƒZCeêY)3 ^nmŽCÒæi?¾lÏùÅåùÖdšÅáÏî^»³Ž3ëŽë ®Øqlˆ"UiA”L •˜ÞH‚0J ”@I õ%%BBé (º3³ÿǾóéùò^×s½ç9çwîû„š]xbµ¯áRØ""ØÉ÷ÜŠãÀ›Æ«1£ˆžœ1ö[è1#½nc“· º¥×Ä…€—]Kƒ„‚َʳ g•„t„ªä"—ö!6 E—FÏ+=JDVd†˜•‹3÷<½dé®úÙ;†¾ëS¢ó#3ä§û "Ö¾½²Äü
+v6¤ãÀ}“dÈ›Çgýã·b`vÆ ¼Æ]@@Ø·K_ì­Èº]!l]%‚»Ô¢[2Ã5Œ¾ÒÑa1€ƒ
+h)öl|ò‘Sú2¹ÀÃÅ6ìß–‰p«1%añaØÈ€F
+óÔ§&ÃÝÍ°•˜ëÎaäåÔ|sãïž®±Ã55¹ÈBm…_VÙô¤…²6ãŸ&C¬ïàçÖM÷â61aç’¢sŒºÄ¨°äª¨ý“³Mš\âÑb–f¤K‰Ë‰Ï³QGóâ×_ $;;Ãæ®_Ó\îWao¬üZ›&§ß<&§^<6+ºó×,35ßÊ jØ·”ô‚m­xG…½™@eÆa×ÖÞÿtßÿ{jAH è%4Ç·x}ˆQàhÌL¨‘÷þX¤Á~sr©Î)ÔmCÏ“sKý×C: É«#@~-÷*q·ô²Òïí½Ï2¢º¨®÷U`ª ãÁßs²ƒ:<lS¶Tì2Kì?–¶Ê
+Ü͸–Q±°áQ#²3MÌÛѵ5-1óƒÄ®ðtßöVÜÄÝHDÛµJ¹~]sÕöêZDO*ϵvt Ȇüé…Á²ó!-üFp†õ4¼|“œïë[‰Íóû‡.9µÌ#géå®ñç÷·Õ´‡‚’ã¡åîÌp¡1‹
+ Wo B3’v!3±ÚñveŒôh~ .}ožŽä’õvJÞîY™ ÿ3ª
+Èã¬ÊOk½[ZjÕÊPC¦½¿ö‚ó<+1Ç„‡­"²×ØFpNð«V-µŒ¹1Áxfìf/ô!oØßC/ùU˜¼]#±ò7WkG Ìg^Œ÷ê…É%Yg à!#fÆS—ížÀÜŒÍ1Ÿ}v¶Š¿y:>¸§›«-=ØËž)ê³CúâwøÍÑrsSlºáŽ{ èG«´ôÌÚPÓÃ
+œŠæÂu¯lc¤­Æ¯ioŠšÛ©!³
+ ¢¨ÈfXb!+!+Ùnr³ÜBDGtœ©t\Ø„„²ï@a !d¿ÙYu¦=ý7ú㸿{Îó|—ϳò¡2:CûöÔ 3ý
+(aáwn¼¸žçÔ¯Oö^ò?úmJG¯Më3sèR°Š`Ç)=÷aÆÀk;^‘ bK´š˜ð„y u°[RV¦ä ž#câ& >ëU£µ
+µ*èy§˜Ñ®Æ–HÕû:rmÆ4Øz¸*aÄ—ym9‡
+nˆ™¶ˆHq³·¥t¦œcOãV œ¶Ê)i‹°'º@»3ÐònQ?è QÖÁëI˜wóvà2•µ²š#ó}U+¯›þ¼öµIÙÇë£/³D:ÿ´ó¶Á}gEXY"ȹ@7ۤ䛔µÂÔ˜{üõšþ¹hú)©’t¿â‹•¼^Àn"ðÞ¡ŸOŠ/bk²NnWêÜ«V:fyö44Ū /ðå}r(ïƒhå€ *`QÖ+¤Æ̼v0“þ„Ký4åVÂióAÒ@«MÈ·
+NjstgvE=–tkÔ!­¤kOÇÇü¼«~s”@»3„ŠýIÂ×k¯;®…§×}ñyÿ=~s¼)ƒ#FF[pšÐ˜õÀrÿD_ÃÎ °KÿÃò*§ÌT˜´È)‘E Þ»¿þžv-²$îÚ7Éû–•´ŒKÉKÚfÌ"%îêXõÛ3´Êu ãíÆíð<¿i{
+nNFŠža!èaYÜÂ}r¹.2ϽÕJ;£zYOD+|¸¯å4D稕97·#íà=>ÐÖî| V˜‘û¿^VÔÿjû-öRh42/j>×j‡ûÏ=Sr °e'»=e¤ÕoO“¾^ÿ7­b÷#ûöæ ízx–\U²KHY»¹dã´§É ;ïZ®Dgp_Å´”ê‚"'L즸وÚE¸‚GØ{®÷“ ,(úØO":â ÀZ­…À³w©ÍxX'h)ù¤œ”m ¡èe¶|Ú œDTÔÆy[¤Þ*»9˜¢G
+AÚÂïÏõÖ®ˆX'Šárp|!aUðBïû.mMSþYÚ~·òº3^gÆÁíHX†:rÀ'‡›š‰bè…6l‚ÉqãNÉ'¢an9 æ
+Õ¾‘Ùî|‰ÿ2i”²N9tº%ùe’åÜ,\ÒzÙÏíþ´-C¬ßîA_8^w?ø¼§úñqÎX†ÚAž ¤íjIÊŠ€¼ðiLŒ[Ÿ‚ü
+~Ü"%˜à'1“¿§·oNÝ k¹Œ¢Îл&ô¡¯"2G¬FmrÚ°Ò6))¹,ëOYTÜ´m|/ZwgÁ]wÁ”˜I‚Û™£ß ¾é»è{‰¿¸ú=ñrd–sÎ[XÀQ]y72Tô#PÎ+g'mÜGYó~Ê4
+íû.Oÿ~ÎÅ{y¾oÎ÷¾ïó<?¹¬â¢fjÃÞ2­>nW}?”½c*À²”™ÕÕ±Ú³.¡êQ².)Íñšvge})ieR~Ýñ³ÂÍŒ™†(;E„ŠK<T¶ zÁîýê=öŽ–Ö”|À=¶f†.,±$Œ2bÆ4&ÌZ'FR¶‰‘V9ð)ûÞt~¾?‡>—6Ñ ™2ñÛ=rþ‡Í'/O6GŸ”Öàá¬Uˆ3Е1ñbº1f¤JÅØ”žÕ”6ò¾zŽŒixÈŠMÆ8ö©À[*¡¤Â',#ì´eR7È¢:*ªc4nÿB¾RÓë’F~;øîûbMðÝൔ‘Ýœµ@=¡%VÃîìðÀ[Â×UõŽª2ÎaXÇm -³&-01ey
+’&3ðP1#§9aâµnÍÓnÄ üÖÒšœS]‡(©¶3¡ÌW±•ë»ó¤« «%xjG uz¦ßÁ½“€°;‹ÿ:8‡«Ië¹-³
+¸äSÀÀSÿ ÊTU^Â}srÖñ®r¬°. ¤VyÝŸú3‹{ÃF)¡â…™…U6}ó ú®ï§®T7åpySÂþTy/§'¬#}6Ò[r^0ÉtÕ#‡ƒ‹¬¦”UL=Ý›œ­$’¼SÐÖ2öÕ¬ú¨‹*¬ ©#RÕé¾H3 ¢Šv0¹®°Jmø­Àœ9Ŕꚜ—ÿ4+FfKXMoÈ­
+0 3¥1ôw%¿Êl-¸Ä¤¤IJˆk…m¡roªóÌÞ\ïŲ›ÕqäccOü,|yŽ9Ý‚¹‡>˜“’5K)#¯#¢a5%ŒpoÂ
+Ð’¼UNI˜M ùvÚábzàVsqUÜtu0evl¼Â×FÕÊ..æpC0sBdóˆQ“l iaÅÌ#´È„Ú˨3!þšÇÔd tdl™…Œ›%}ûFiK­è ª%øœ"ÆVh÷ýS}·g®‚³Óû@Ïk9ÐC] ÓSÐ÷7K ˳±¬ã1?¼<T·öC癄–ÓVt*ØU¿B6‹°{zQwÒ©’gÝ%I+Ô~O¹³û{pFMÖ ãÁÌAYÀ°=kQ²A{ÁÂïJ舃YRÝþ,ùZpžz+k‚ñÅU%3²Èj ¼Æ]ÜÁ_ÎYhMy+µ1c&7Åt„úð
+£1¹:&É:LJ5Ôéö¿§t,dJ'슫éõ½0çtgâç´[Æ;ÐòZ²îQEÆ=ù,ë™|‘]{,‰èMž——üÓ˜û›„YQy~¤ÕDm ½r8¡§!‹vjGROiô¿ÂŸÓJ›ÿ´À½û™ï%îæÁ{nÓÿ).ó§&²ŽÿjÕÔþ°µnéZ匣;®3Uºã¬¢È £ á6
+JDØŒY0“´.ãRÐrîn‘6g\2jÒ&~D¸$Ù%93a—4']RJlQÞHÖr¨ °¡P›‚ždÞv½h9.ªóˆ‚™œqê$
+°'ïaÒM/N8èEÇL
+¶g-)‡Bð{Pûø_¤ò Òýps–_zÏ/ Ž
+î%Ü_ïºä`›=À¬âö½€ÒðÇ*¬Œ›Ä;Óü’¨‘yw}ªóîµïÇ„{?2I¾üi¬ãNhœU¿f’ÒqD«Ï­']œª„ƒ[¹<pàÓ*ýeÎ s"sì’OZ/®6ŸŽµßH[Õ9ë0¤Q†5=Y¿œ[3R¯Åç»o%,ÌBÂ.ªÏºå´4Ð3á’µ¦çä}*(ïë·„·1Ë0»´µjq{¯|×Ô'Ämª®´fb ³±EICÒ!iI»åY¤‡Ÿ
+fStäã{amÿaX!Ù2Ò*}Ï›.æœJE†¡ ¢J¹a!jÕC)·AExtÚ½ ZûǺî)ð=²4a—¶®ªÕ„OÆŠ» &°U«ã‹‚º¼_Ú}”ñ÷üP{ÊÁ­û2Öö}ÔÈ(:ZÕÅmPSøCËw«£¤‹…àù€?uÙ¥Áᤳoph)èQî¯÷¿zå­¼i»<!ª9… Ñ®¤W³nˆ’r‰yÄ’°kcºûfÌ&nÄ]Rjt†vge¤ök÷pñIp¦)»Ä¾Ÿv3Ë Ð§{ˆ’}àÓõìù ZÌ!}ä¥üÝùôç?Ûû
+¿
+½ª:sPpÂÍáªF]–u¥RjÚ*!§­‚l¡ízd‚|ecŒúÏÝNIÒ)n<
+©äGaµ*¿ sRnaCÔL¹ºkæWÅÁ6Ï/kä¹e,¿ ô Øä*ï7ó~NÙx5¸jŒ-J?O2Šƒ£”Ÿ¶?2Js^QÛæ,åÇлƋ‘æÝíy¸5fémÍJH«¿Òîà³¼ªÄ,·bíMóe‹êÇ“koIße%'0ô§–†P§Ú4³JצZ®£&Ful®«`wŽv;:ßU¶1C/‹Z5\Ô¡“¥½:8¿¢–í̳ÊVGÛ®mŒÓK¢`;'<àQikžyw×,ªÍy¤9ÔŒšé÷ü¯îŸö¿¬þf×Øq;å€þOq™0µuaødÚiÇ3É43qÜÔ­]Ûµ`
+˜;çB81+Ü»½HºµñSÛÕ¤™Ösó… ¼Ö³UQGÌÏM£¼sÛÓ'ñu„Ô1qÞç¿^Q–}qºH,ͺ•œ$
+Ób¶AðÇæ€VÞyüóPŸÿ?‚ò°Žr'å¤?ÀPþôK-ÂÀíÉùÆÇ€7L&Üòƒ’¶¿(j>þÈ­
+êè¥ÁjuÈÄi YyMùÊo=þ!åQË’nˆ’öª¥q›Š1B„ðª¨=¨ãÖF,ìÆŒW!(ìLþ”õÿK{l”vE,’. …Yi¦—Xµž—øïí³m74œ‡QËÌ“qñ¼æ4l½§T\LÍŸ;NÜ*'Pà%(£°s©„iïô¿³Þ‰é˜…ß\¥––)%ÁU:îÜJÇå7…}Å]ˆwf¦–Ÿ¬PKËCÿÔ\
+°UÖ)êɹ]1³°½°±‹»ê¡üÞã—aÂ=Ò+{Ïôbf>¶L©rÏÔ}e­þÃöÛ®k§k<À¹òþƒO‚Fû þOþ·äªà
+½½è†r !f ¢¥ÞMÙå¤:"͹'F¢v¨cUâzE¿í™ë½ú‰ûu·`VaSÁÃ0©à~ò4cLY;‚KÄ»¯ WOè%çzAfáÖ\2RΫä¥JfÆ­f
+üö=íÖÉâÀµÃ÷×À\6
+BÂ4>\4l¼ þÙ4ÖúG¸ä‹àGRŸ¡Å­‰é8:õدQt
+B|}XŠ><B<Y"Ý>Zê»u²B«Æ<Of“ž©Â6+‰ªEA½š~ª…aV+aì>]¦Ü9[¥—ELÜú4ؽ¤UÖ{näÖDÖ¸ GŸèÕ˜EŒOÙ8ÿŒêÉåAAƒ¼+ CzŽ4ÊÎýwœï7ž‘¿Ó©~§SÔ^Úëù{<Ê{ jÔ,l9YáVƒþ $¬œæ°ž\æ_¸~ü3£,ivf邏“«š½ÿ ÿ¾ÿ£ü`R•2ò›Ò6QGpË‘†r÷TÇ®J˜åäÀ'¸Ëþ”r%´Â®^ÇÍoAœÂÄ?·0#F~;†ÊÈq§Š“pͼ<[ùæ9{è%%R)†
+ð9Ÿ”•Û”ò“ÎAʸ©‡ZzeÊ;¤Û`Ò‘†Q\fVÆ×m¯˜üë¹ØUG°äØ"jK¸Ôƒ`'ÁÞRvß‘o»_àoùˆÕI à&Û°jï#»뻶»Än.îÿhŒÛ‡eØ÷æ ×ÃË„À™ZÒ¥àóþã—¯Jq°D¹Xå6ŸÛ’´f‡Ö¨•!õ^ðWÀH-=Õ3ª ÛãÀ†ã¨œ‚9ana[5šÛPˆÒ6^gÒÎë8wÂÌKÉ
+;fØ$í:Ór*w_÷\õüøðo¾ùþ¦à§;º>ر ÔÍyî=ó éJÔ¡’ücSYTÍËØe} ¿¡à„>5”w*èY—œ²ˆÛÂæî™~œòÌý^ÚKÁå6ùÅM)-ïE„×äTÂ(ëI˜Äm˜ îKÕŒøªðáÞ›GYŸ¸ó{ÿó–oãfAkÖ‹
+¾ñ‰4*§jIw|oš¾Œèzo¦×yDÎ{T¼¸M15©!°'1POLϨjÁLêø5!½¸9jzÓ®Q8ëÓ(ÂŒ™$íþ·Ô›a½ 1ãD¸ç}F¼ì˜fÝ؃tD—!À«ÂŽãO7ƒZbyhmˆXEú°õ ³OŽj¡vÀ
+DÄ,*fF˜{¯•KʺoVG®ì¼V‚7œÙ”´¯Æó¬ëJÂÄoκûòRjѱÎtÔ×lÇ•7ìrÌ5‚¤|CpÊ+#'¬¼fð§÷kÜú¢¢^€œÌºO p¯ÿƒà>p<^ÌÈ®IÚh5aC…u÷Õ±†Tµˆºcë’~À^ê°UÒ2óꨟr@ýÀK‰I䔃Š;3P+Ó… èŸ~ rx,lµ6T²‹m¬üNßlÏõƒ¹öow^µ~1²ÿ»76{±?ñâܪ ´¢ÐÇ®*HÙe¤°žÑ|¬é)hY¸ˆEÔ™õN¶&g“€{‚àß"fþ£¬f…“Fu¤’ *êÅ<
+f«d§6TÒ èiÜQbAg~G
+ÆùÇ(e‹ ×É[K6,|᪎^‹šX¤53ò«Úª}JVmDÇ!&HÅó¯o}ƒL¶”­…ü°ªƒ¾0€Ër Õ³¿nHw /ÌÂÅn…d†Ë-(kYF)ú8L*HYäß­\NÜĦyŸ¸ßÑÊã"fD#æÙ^‘²”¢š½RVé.%¿h;Ù¨Q(@¦¹”9”;û¼!#¨f6@×[ÞδÔwHêÒ]o°9½¨1þ¢Xæ³Ü
+jÉ–DTLŒo´þ”³ÿê^óã¼] w+i«:.Ø•îG-¿mYA)ñLP+—³
+{bVÑCDÏ"ƒÝ<·$#ç­jxäU›`zјÔ³¡O¾xÿ¤5üaáñâfi«w:GðYóäËs¿a_PKCSÌæ„rcÓBÇoÚé-!.ßÜW¹îyS†OÍiõªÛ©öWøÌwÂÂÝ’¶3ÛMOªN"j¸yÝÆmعDÇh\’5ŸCJ|® ºYá èð6uç¹=þÑæ¼ [;'îà —„«æW·#3NÜõ@µá?¨¡êInÆv%ÿÊ.§”xÞ3N»Ô0±`¾g?¼¥W¢³\zÜÌ"Œ[ÖV_´½¸|ð)áà6—ôæ· º´¦fãÖ4ÌÆ5=Œ‰jÚj¢:¨8¬k¾Œ¨ðçCÓ´jÇ”ãdWy”÷…è,Ÿ‘xCa ©re
+sfúQåîår>ª2Ì/‰Fx¹{BS[w…~- g^ƒÛ‡Èa=T¼"'ä¸GéÀ»„« W'HùÖ—y;MO/o_Ôªáú¨‰ÇôjÙx§üNÑûA({ABÉ]7ÀMÚPÔ
+}cœzœVòq¸ñ”íEå>Ç˺cQ#“° ĨE(¹m«3¢N¯JÌöh;™ak×CÔ*º
+H‰ì”éSçÀ¿w¬™~kfÒvÔNIâ sKžÄ`À`n°¸%„®ÕêZ­n„Àv×MêºIfœ8áÔ}¬Vˆ+v‹1` ¡c/ Ûéÿ‘.¤É‡N›ÉÇ­gš]í>ïîó{Þç}¿ûî'ÿôãÿX¦ÁŠ0 V„i°"Lƒa¬Ó`E˜+Â4X¦ÁŠ0 V„i°"Lƒa¬Ó`E˜+Â4X¦ÁŠ0 V„i°"Lƒa¬Ó`E˜+Â4X¦ÁŠ0 V„i°"Lƒa¬Ó`E˜+Â4X¦ÁŠ0 V„i¼9"o-Ü7„SEEõÚÑ: ,ሮqŠj„•Ãôÿ‰–AœNÑð…®SIa•N+lÜjúVIqY÷B‡Lrßû>’Kq[!•B¥¥ovJ% ì4÷z‘>8%ÜRnÉÉOdãœçñ*ùÅåü²ª2~EE ¿ŠËãó+Š«Jø<A_À+/åjþk¯¼¸²²¤¼²¼¤²¤¬œ ñé{ŸÏ«¨ªª ƒ*NF ¥<A ÷?‚þãsàÏÉ ä(978ZN;GÀ}ï4Wtƒ¶ª‘q ?Ê•ËÔ¯Aʪ¿¿¬•Ñùw1éQtÌUÎ…:™Y%•]¹ÞÛĵpú¹'å<~Åù“+:Aå*ü
+î ·¬¤”[ZRu\@åÏpüð‡A?œùÜ
+:RþI¾Ü“7pŠŠNR<žÿj.¿²¬ŒÇ ‘ ûñ°Ìúª”îI.º^]o6¬ëÍÇÁ<$¦Ýò«Ù ¦=‹@ƒx̦?ôúv5ɵð`YׂÌ#dئÆCmÖg‘dp:hìM‡ìêÝ%sïó9mëÓ/åõ»3òºô²².»¢¬Çý*aÆ#¹HD¬ªLè£{éðÝû©ð„=¹bLÌk…/¾­NÍ2+£ä–´M¸Û:L…Ç O;Óú¶\È8˜tK/ï-Š«vfú.dÜò&2vgÝò+X@ÓIDáQµë± ®;ë›Ó^°ñù´”‡{ô¢×ññq
+1Ér~ã ²i©¸Ý˜C`ÉþP·=3Tš˜“_>\еA»&뵈ÓËåþŒu÷LZR ´Ï”´lwJôγ‡­¿9˜¬$¼†nÒo“Saðlv¸òég=E;_ œßùj |ûQ绩I5íÐNì`Ú£kËx¡xÈ"ÏGf"æšHùÇ I·Ø_2$ dtb‚Îg‹hEÔ¤¢%1Is~]gÆ«nÎø žîz6`è&"š®¿ÍvÙ™•QuûbQ½ŠÛÍ…˜Æé9yþ¢vohÄÂc0uš’>uS­¬OÓ5¢â&0¿i3ç¢åžGݶùUß<h‘eB°üÀ¶å7l¶£o]÷¨53HÆa9ƒÔªQš *¯å|Ê"¬jÂC@ëëuú{q«ŽŒÁRÕåPÃÐaP}=Ò´“qã(†h»)Ô V1Ñób”P1³’ˆšÁ„OÕ¸ï‘7äÂÐ0¹
+¼Z³þ±åº÷šþîцÓE®»R!+ðÃ’d8î? uŽ¥è^ÃWo}’_»ó0›¸IFF5«
+ëF9Ž‚]ªë#b¤°n3’ô˜ŒWׇ-*bõÖŸˆ¸*lØ­G[ÎI"Isˆ²G•Ùˆ¢éЫ¬ß_R¶xþØ^ «;ôßtˆaèÀ-«þXv)16Qº–ëÎ1|Í8J šÎœ_ÑHÁîWkô\­Û ”_×±3/¿´³¨ªË fÙöœüýÔ²¡Ð=3`X’ö*ê=òº¤Ï4ðd¾Ž!“829yà£×ßòpUÖ'¾H†dõDp´.Ô´ø´)?<”‹ºl¿E²ÿµâÒöÃÓû3âÊÃeI5á›ó~ËH6õÏŽ_9ûóÀYz-J±°yä`e¸úÙcáÛûsíïà!¥B`1±xÔâˆCKÐ9‘ˆCG 62ˆ°
+ âóË-‡“@Ç`º‡ôi¿±/µbì"B¦aœî¿äâè¥í©ö¢Õ¿¶ýÞ=ÞöVrÚä<.]r¸²75pöé§-o?ÿ²ç î–×b^•ðÐ^Ÿÿ°ö—Û¿ÅW`Iu@É%±`ëó«¿Ú~Ôò;Â/¯%üŠ:’ÞkHÔ¡Ç£E1IñˆC—GÇm¯6]wòq‹‹Zºt…É»… ×-"J¯ç ¾;ãÑw`n}g>õå£:Q!¦åmgÎcQa‡«;0ŸRX@é^@̲üª¤P›†Š™¨øäm qR~‹8pÄ “ë+±aÑa«V E÷ùñZÀâú¡Ùþâ'3Cå…M×ÇÔ“‰©Í1gaËõÑÑ·7ä×V*
+ Q؆…eµ…¸¼¹°®ìL#CïÅ— ëvŽZ”½çdCÚ."vÖÔ]…¸¦'T4ì/Š¹€Iv„ÞýüåÚÝGĪI‘
+Í/¼²~Y ¶È_mÝü ½vmÔ† 8Ú¼yŸZ»;…Ç?|pˆZ€,´dÂ@s1Š ›“ŸPk&®¡<wM’1׳ëÖ¡ÑþÝÖa€ŒY
+ˆ"9L†
+ML—‚ãc¸Ï,üê>Â'é*G¡Bè)
+¨G=Dø¬ºœ[?’~§ïÁÝF>áV±û/FŸÝø$0}óÓÐó|aÁ,ȬhÙó’ëGs£ ™9Q=¾.j9|Ëú*úâιäO=_zžv}Ñ÷éÑËŠý‡Kܺ÷¯Ù—3ËC7(Ÿ¨òŽ\#ý¢vÜô¥¡ß@K#•ØØX%j6V11ð 1i*gZ‰[ÆP¿ªŸðª*#òkP/> Kº«Qþ:2Ò’Yf]DWÊg·eÂ;ÙÕÁÚrD';I˜Œw,“tT¯ÀüZ>æ7«PàÔ¯b>“ƒ7…ìß2Û¨äØCjkÌNÅŒj"¦•|X¶C¯€G¦éÔØ<*;ãOÊ)ë ³?ïÉI¿¬;ï¬Å}ƒu¨oèZÚÕóMÚÅ©]
+ó°"¨à~%‡ŠÊzÉ •
+ !£þ±÷–y¡à³Ë¡©©ˆ}ºèÓòrn„]Ø”±°
+v”ãÈH)†° ¿õÈ%j=vªú?¬AV„m“ÿMôw•b, g¡^5§’õTCüÛägΣãÂ^Tlò91¡ó²nõKÙh@ÜóŠï<güåýKA3y²v´ hûÏìÈ·éeÁ5: è¡ý’n:¤è#ý›
+™u¥Ð¸•XT˜Ï()ºT=„KË)ý_ª=Çè­™Îsée%‹ðg¹Uý9¸=çà6‘é÷• Å@‡Mš‚OÙw
+jxyçhk%¤•VZ¤’Ð(*[Es.qLUðÈ€o4ƒ”_/+õRÒ/gá^n#Tô—¡o²n93ç×q 6(J!õëø8ô_1„ô£AõpuÇú„N pQeÇþ” 6ùM°ãn<(î*'~Ö+íÚ^^Ý]”4Ñщžl™LÕ-’ŽšŒä@) îÀ=ìo{/,ñë©°V\Ù²=%cãJ1Û zM%&žç`¶ÑÙþ/2küÊ+é¬D J:e}”Y™˹¹ÝRFÞ%lÊ­ÖR>It9 ÷!½ÇQóÁªŠ•qNZ²›&1æRt£NÞô*çÒÞ¯öxUÙ™÷èùïW„ͱîý„&ü I¿NßPtÜЛ–‚[ |²ûG«ÜúŸ†kP‡vè$l³•êá‚g´-ëÞ̹%wEõ‡‹£×o/i¿øÍYËïÑe3s˜øÅUik~[¿ù¾;Çþ<ùŠý×슬rMÁw)`æd 渒w°¾.lô|ßà\ί\E}*ÎþÂ>Xä_?ŽvVcJìíûÌ:·.·>r¥èàÕïÎsþ¾d¿ù©ÿ óËÒ¦EYÜ”w.qjv^u¶ó²óÜÎ]>œç×í,pkÇE5¿M=m®ú¬†dm‡› 3ëÜ<Ú4f\RÈ<­¨rÆÀyÂ<Ë–JLÅ«À·é„JXŠ¨xD:f]ò=~Mmv˜Ÿ ¨†ˆˆ¤û4¥SU¶:.e:x7—äŒÓ¨ýÑé¶Þxš’°qo樂£·&» ëæ7–‚rV)¤æÒQBG-F<dHD&Ÿaû LPæ}’öœOÚE”CTB+¥âzäŒ;ð¨ÕN„ r*jÖW“fËé¶ÙVMêÕ•”^K'À³¸‹@ËTÈþ€
+?xJÅ-–ã*)£Nj$Ìü×M•¥ NBt¢JhâQ<
+L¦É{Ï8î°ÄøãJblàgÿ7èá¦cBVö^«àäßÈ9…ÍEïè]4(ccdôÁ‹R|j¶4k³›ZàcÛįQëÄǤɚ÷Žv„þý?ŽË쫉4×s5—=KÏôxÎ8N{{ltl§qWè ²JØ’@HIª²’}a°»qûØ:ÚØ
+:a &*{
+­!|Ê3ÄT÷™Ü¬ú*1«¾²ëëþššW_Ë•WɶŽÛ´DP+Ú™’ŸÞ‘Á^(¯îç·}Ҋ쬼2x_ôGìÛêÏ>$Ýû)£œÆÀ…šªìlï%¯¾B̪.¬½”ˆ=Ù|©ºZžËaÎçÑz¯º¼5Ùö·•'w_õœ[.?yW}êש;•€…!+Õä
+ëàl Ýjîóðé¡ûÀvýyð›<æÐîÃ}é°±ƒœ7ˆ³3°® -F‡n“˜±¥û)ôBëò¡Î³kϯXz$úýöT×éì¼I¼î·Šw[âwZæ-¹
+£ ,nl/`p†f‘k î2PaSÛæ¤ôËؽšß¾}ÞY±3¡8•y 9FÌ]ûI§˜)díf1·©´Ðïæ¢Ò^Ëa½ßÀZT¥„]¿¿ä¹•Åô-«ð¿d8010ÊÁ¹(âÐ=s’Sùpˆ[5(™Ìнbbp²ÛLC6ìu‡Áäà2šZ.eAÈ8Úgù.ñ>ãî/ÅmÀRú6ð
+näàS£LÂibãf—žOÚÈi 3ÉÊo¬&~ÉbâÒ6=Ÿ¶÷Q1ƒ¬€ë¡×fX1ÒÖ@‡41À¼D©ÍúUr!äzAÈä¨ÍCÆgýʱQSw>Ïe¼ƒlÚéd’&åþŠÓ]Z¼+ô ¿Ô»ìWZr8™´Y)ôÌþ’àHÞ6áq°À³\f%ãò@?ê‹ £,÷Zß ¸Q>j–gCêšræ/9ü€ËŒ<âWúï3q›>FwÚ
+÷ö—b·ÈySG.ï
+zMß ^™_0¶y°Ò5½ ßì_íN©«È9S›°!9Ü"ß ¢×â?¶ÚxÖsŽ‰Z{²ÓŠóä,Z›Ÿvtf}ö¶Õg¶ÚÍI æy;ÕùÕƤäK
+¼tåyËáÜœâ"ŒéÛ~ɘTÌ9ÔÔløäÿÜžÔT±¡AWÎo“s†úíW½—ßMiköþ«©bº:&ho>—œÀÇD¿Ùï< óÑF4Õ4pÌ®¯ç\ö•¤‚˜–B·uU€év|ê‹ì‚C Ü纕‰Ø{ ¿òÂÞLëTPr’+¯pÅEú¶œ
+?“f%4woƒƒ¸ÛÁ$Ǧp6åíN@(ÜØJ†uõÌ,ep¯=T\Ø Èχ¡\løÞÿ}7fUo¶skLÜ®å3ƒcðÌÎô ›ºaô!ŸùO\hø_4*X¡'—]¡ã(ÜÐÀ¨¥ 0ZÆ;TZ†Ï,9l|Úi-F:
+·i¢?I¾š©þ¤œº»¿øí$—ºC&ôo§4—Ö&¬ ÙÙ+›óñÀYŨË\ˆŒØ8ûî'³Èé˜eR›öüã2}j"Oãø_°µo|³µ[S»³º¥U3;㺎ãÖ®×xŽ,"Ž‚ G€Är'Ýé¤s'ꨌâ(‚„œû€€á&äìNw'üKöɾ xC*ü~¿çù~?Ÿ²P„¥³¡Ä¡Ÿ`ÇÝüË[.þÅí¹Ákt
++»É0&%ƒš¡JÐ:’]4ÈÖ>J~¬'Löý4n­¯ ÊJ\ý ÀD%?Ò»·(m+ùÞ–WÚ»{l{Vrÿ` ü'f²g[h*º‡þ»<uûXÎ)hZŸï»6«¼|„Y¥ÂFc)¤ê+ø•]¿¢cgAÚ’yÓwfû£èJhªëô{Õõ#ÛÓ‚æýÞ˜e sZ¶mÍuž
+Mœÿ}úYËŸ)äîÞâPËÆo=gh72Àè`É;ÔZZþ˜ë9³ò¢åèúTÇ·‰™ž‹O%玤&z®Ć_ã«é˜R@£<’¶œ»û,é4‘a)7þìαZPÊ=ü„átB>
+˹Ûó}¶>ô¯a68Øåiûbó:@ž,Pað
+ÖÞ ›às÷ê©á×lrd†Iاؤy¼Ñ%l\Ú]ôwŸ# a3åÓH7.¦ÃÀl–Çõ4n£€íKa\M[Qð»FÅŸ>Š›–¦Äçª~«¥G¥4¸ô°T ë ¶YÁ´øI6 ë^ƒ.Í0EÖ¯âe½â–rX-„Å Ÿô=݇ÿ$Ad²óëœö&fŸ¤§`ÇÀ3†:Ù.¡ä“ñ=&a´mº0A惪vÄnòˆM‡™”ÑVKã&Ø]=¥Å².AÛ[Í¥ã¤Ëd-ÆlOv¡OɈe´š²<e“ö©¿®ÈLDzù%÷ûôoÿã¸<Ÿ›Hï8þ"oóæ&“W™ÉL2É%—Ë —„›#„’ƒÎ ãŠm,Y½¬z]I–% SÆßáp°qQ]I»«nѱ¬²E»«âÜ_’Ÿîž“¶<Ïïù~?Ÿ®2~cå]Øky³íVcnG#?·ÔÈÙå°vtoSöm-¡ª—\;Ú
+æÔþœwqðži‚Å,س‹kæ Ÿp!å líÔ•(2
+™ƒò‹0‹tÄe B.¤²a§6תA³(¼<v éýì“ÒºÃÂ%o>.†íêŠì_eX!åîqú[Y›…‚3öæGåi*d•±¤ÝR‰ÚU•˜SOÅ,’&d1<WÅWÖ&Ï/N|ùkfË¢jefo3 ƒ˜O™ä,i˜bIÝD=cÒi›aç¿’³Lg…ݸòçfnþG&¹°Zůß/Ç:`9_+ε€Ï8\7V i/3ó$·Êù´f¬‘1#8sÆe|K Ü/"=÷ö…ôTqÃ8Ð$Ü&¡æH£¬•õÞR¨“‡Û"ƒ{QíÀûmeÇëçÒ³¥¨Iœ*;MÇQ3—õ-óùyÈv—‡JZÔU\/:ª» +ÓÇ÷×Í#íÌä2žë4áç²v”˺æøŒÃÑÈZtŠWk¦¾×ÏuÝõŒÃ —ïâó¾eaÇåQñÐýõŒĮ́‡'n®ìG”cïâóµ¤ï›¾£È…Ux6Êe¤ÝTLÙË“1t¡¥ïOgN&ã¾^ËøòYï]6¥Ÿ÷“qi›ë/mNÔ€§:L­ÜÜt²Ÿ‡®¬Æ4n
+C4ø ÍbVI) éÙ_Wžæé*mi:èŽwOÅ'Þþ0ýe%`ªFuƒ¥mär5d9Ø6 ¼z¢8SÞ@zJY ?íXLmŽ€Á£pÙÁ]Üå áZq¹Rj{Ö¤§8`Ñj@7PÃlšÃ6»C×ï®MÈ/ ÿñíƒßŸˆþV
+FÕaA+iåôÊF
+X,îqÖâ ß³±Å§,~s¹5ŠvŸ_;öêÑø‘ܲò$qwæ—ry+ «ö=ÌX%tçÝ~Ì‘/M¦>§NRQÉ7tDqI MRšÐ^­FÛâÞ9³Ék1»º¸…ô!ÏÞ® Íß¹ò×CÒfn
+®*mVÒ¤]Ïè¬Ù[\¦ÍÀc°· n×±¤ïn1ŽÚ?„4=Íüìb£}íxnÕáâR6=Pôq¸z¬ž™[*Æœ†ý°ËÌ’7Ÿð¹ÙÛ÷þzάãÓf-“4H°™ |Æjå v÷‡˜ì»fÁ»Ôz{}C(x¹´µÍ…êFÒí…Ž½ßȹfëY—¯‘G¡»­f>§¦ip‰DÈ™ÔÂŽÍÁï ^*fžfpaÞÔ­´aqd|wKüïbPÕEÇÚ
+f•í®#]•€òfú¦•R ÖII燵îÏ_ýÐñ›÷†>cÚÜÑ Rí‹9‘¶§0¸Y"$ÒVדˆ¨ óà©À<íÔÝ5 Õïm†ö¶5½å ôÜûÕÁÏwŸ^ý;ÔŽfP7Võ0U7曦¨ÍÞ¿W/ý¶ôläH-Š Iý—P°U‹é'™€ßÍݺ
+¦¸\XéøÝÁÆ8œ E#¥—6ÚÓ]­bfÌÖƒzõ õ‹OÃÄÅ繄öj=i7Ô³¨W€™'uRa³¨´¦ï§6­SÕ-ÓG(ú„Œê*×Ñ8jng¬¼´‰éˆÇÌ!§Â3ç*Û¢ð$—4Jj ³„‰Æ©°ú2—°*Ú,ÆA—0„¼‡†~«‘Ê~šPGjùôüJ÷úª¸ÿn5qgƒ#ý÷Á©äMÂ(päÑ p0otÒr)ïmºžËþ<OwZ;vg+£ŸHE_|×Ê©F³êÑ1ÓU¤UÌnÒNÈR“L ­Z8o.¡ecª~ž4JÀ÷ƒ¢“LÊîd²³‹•¤Ey´)è6oµPÉ™K|R3Ê¥ô|ò>å½%䜳 ¡±¸v„#TýTTÞµ»5ùÏéy6‹úk;&„ƒßðÙ…M6}/œøØÊ/ä=·yßÿI.³ç¶­3Šÿ}êd:íCÝÖ3Øã6vãiœÄK¼ÇÚlG¢(Š¤¸o
+‚«(9µ%‘¢H Rnóôãô/ÎÅÅwÏ=çw^´@«JÁwGÊ‘4ŸqjÚEÒs°Â:›A`%ÌÖ.âhgunÅ׺Ӡ•kã VÄØ`Q` è 僚’óÕ, ÎFVÛ³µÒ{T)Ž?mmËM¶!«:Åð,°>t-Ü%g=D³»—”2¨©ÁXnV7 O²Ò.ÒÐGð–£³õIi’hßµXðð¡ZBñÃâðÉFÌ®îîu7bí-ÌŒ«-úÜÁfÒz«úGe±çOÛ³ç_žü¼±jê“’¨¾4«‚¼5ÝS^ª±÷ì.­,|^Û0]–Óàù9Ò[No^ý•H˜¸sí¾:‘{tñ7¿¼ê9*¬[n7ÌT^:^_ÕœNC¥4nß›»ö‡òÜO…UCo3‰ù˜¥§üfðØîë?WWµ_—W\#ïgM—¹u8ï7ª¯„ —®Õí¸ çH}Í6P]5^àbˆÎiªu;Û;y›ú0oUur®±N1Kó­Zlô|mÝtUˆ¹uÕEl¨ö3®>X²\RÃgZ¬ Ø3ƒN ³±\­,£blúŸ °òÂعʼá’w[ÖílÄ,}•¥¡Ïö~þîSö,&(w#Š‰)—–›ÆrK`lƒ‚ÛÕ)þè,õ¸—¯„|òz•4ájãdHo3 sÈ"ÆzÊ¡S+ÌÕ*¿sûR†ö*Y‚ø¸‰!‡E—é°è4Ô7T§÷–{Žì-ß>ó¿^^Ó_®FP”˜|ÔbÃ?6S”ç`Íu{ Ù]¶÷í. ÿ³ž$ñ½8î@·äÒ“Ïà;y‹ s¬ê«îB
+5
+ˆ9ÌÉgìê«ï«1¦¥x(e)¯ óìx,åq|w©ÿ˜½ºTP
+zÁÎ[íéƒEÍ©cè뀸¨[ÃEhBŒû'¥”?$¯‰Içpî†ÑoåL·æýãk÷×Gåu¦d<¸˜Dt¤K³ ¾V[µõ‰q˜ KÁ\HOæ•ú˜~òß’Ë&3ÚKÕˆö ·õñ ã5>®¿('ꃘià™ûäo_8N­böΦ'ôqÓã…<w•£¨¦³ÞÌ/hN–7P}•mE7¥¨?ÐŒN?WR‰ÚºñÊÎÂð‰÷sG*‹ÃŸ Iº³ˆÞÚ{‹ôÊÀ¼ÿ~;ç•ðaÆ¡RNý|ÒWK¢ÆJÄÖßl±$.wÙ2íAÊQã¥jBwAÍ´7†V ÷ÔA+\*x§U Í(›8QOXúxÆ©áSˆ¹•uX-!0åHaþæ‘­ylh澿FBŽøýµàøÁú§õØÈ™à~‚°l¯¡ƒÛËö«bfòlTÏ’ŸñŒZ`ýRv¼ëÿÓkê©DÆÎ5’˜CÙ >áóNc-cø¶–2\9ˆé/4rcׄ,Ž7óS ÊöøL«à›jnÛÛÁ™æN7aï\š¢k)Ú#ÀyI¬C[ßùBf¬pO0[3mW+Äü±ˆ"¿–ÜD'ïƺš­EMW>,«ÿ.$ƒJŽ@ß@DÖƒñlà®\>‘ ¡5Ø·qÛ93ˆYŠ-»ëÀƒbŒ&ZÝo€ÿWb˜ö ŽiÁðd
+]¨
+=LIûÆ•Œ/¬ä(_'‡cÍ 2&À{%ðx!1q¯Y<hm’ÆÃoC%çv*:ÌÅ0x¦W²û­løy+íŸPRþq)A¢"t >æÖ!>fî«G ¤¨æbS÷×hG5J»*+¸¦Åô-˜¹”A,Õ¸]Sz Ù3géí$Ãä$j(/Îí-™.A¶F]OTò.}²òý‡ÝuÙY!F¤…)Ð!šió@}MóEyqäTáùµOþýäö %FÓMG*p7Ä$E´2ã?*à‰
+z §H´û¬G-½ÐG¬"c\°«`í{õÄôËfŽ$¥4:|4ønvøøÆä·¿‹O÷ÿEL¸‘ÓõoDÇ%=®Ê†[WO¢º½¨­/áRí$œ·ß/Y¯¶a¶mè£r
+ÑJŒÛ®ä1[Wÿ;oMçÞ/š¿>r¥qô4Yð·4í†hl £RÒjæBÏÄLø©œ>€ÞèlGdð›íyý…âKÕq%㳈¡SBlJÑe9,y|íM7
+båÓ¸SÎú&š9Ê 9^=''祂wZ‚ŒäÓæþòºéFΉc)âò½WˆMÜo$¿Ÿã˜Ð}ŽñÒõ$7`_|ÖC
+,á–2^èY~?ÇLÎð™Vl`’Ï’>‡»ªiûPyx<‰ŒIyÈÓ5ëÀ/ÿã¸L»›¶ò0þA8ó®sæÌ›9=3œ™)íte ¥„„ìqï¶$Ë–eËk6B€@Y†rÊÐBC Iï‹,ÇÆqHâX–lm–ÒÓÏ1ó⾑léêÞû<ÏïY¶wW³÷Dfþ¹”}¢n;P7ƒ÷Ôbà®´a7|s°!Ÿ αô½ˆP¸ñ‚ÏoïD\†½8©•|¬±aéodÍîªþì!t¢cÐÕÇœS›†O =eð÷K-{¯µ§• :¬n¸°_z úJ¹­eý³ÚsjÁ?/ç=~>ÈiX¶§0.L óqb”O¹­B†4C7›’¶aÈÔ~!îÁ„°åB„† cÀ¶„^
+=Ì;íj?ÞÂÍ\Â6°ýÒveÍ9(ÛK |°5µU#†«µ°uÈÚ%„Ñ8ºžuÙjq[ô€LÃü¢n‹’žš“3S õ ÿFž°±1ÝE6¢¿
+ìg£HÂu§™à}ô“Ñ/bó×ÿøtO9O@oA‡¤,xœ¹Ã¢Û{ü– >n9p%ƒë†@›¾yeËwKÝòßQ
+þÛpF‚b`ápÛOÙtûj$¶·nmƒ<ž™©;š²±©à¤”›}
+þx£É@u`òZÚKÈŒ?¨@ïªÒiŽ™^à3·—ªÌü¢˜ Ü®B‡mêQÊÛÑÂËÞ¿ì¼¢ ‘ÒlúûX9˜®ºÏ›®ÁsËê9Ê ÝÃ[cüSåäƒX™yX|šÁ÷«4:x?[M´VhÿÑoà·¢þ(熵 Q!ã’ Á‡G uÆiU³Øˆ˜AúAÿ=JŽ$”¼¾œ¶iÊ40OáÆO OЦÇÓdÃ:x‹œÅuå_­WJ¯,Ø5¬‹æ­Æ!f¹Ê®Î¬˜[…(¡)-!—v_¾Þ_4žndÝ`XB@oÓr¬‡‹b=pfÆ߸ œÆJ‚Ô³q—±,Ç<ˆ'bÂ1Öü] žË†.>n×ì­£o_¢ß¾{amÝ[6œb¦öòº¥ý líü°l¹XZñ6Ÿ¾Ù~>úÏð¼¼BziÙHúÜR,\:±³h¹ÎF=¶J˜Ò7Ò~ßqÁó¨à­Ø&ø˜µ4t©´‚¶ñ!¤]ˆZ;³óïà§Ç0˜»f¹zéQ26GºkQóµƒ}+¿fï¯Ó7”27) WSØ1wTc¦«2mêÓúöji/%CÈÿÕˆ¥'óðÒ2¾=Q‰})¤´­2xŠ¤ðZ"à /T“.«’¥H`° °ºô?(Óæ.)…öqq—IHÛ†›¼[£}^èºÉÖ6>vf/<~Z¡ñ12K¦ dF íÐ#çš¾ÛØ&©æ:³9;Kæs{‹Æ3¿}s
+èHHº1);ó¹à¿%çmúƦeð†’6]URÖn<[*Øa‘ò7Š“€ƒÃxTOW
+Ðk
+.§”Å4
+ô¥
+t5È€Žýè䤰„̱é×(uX›¡9‹ iLSŽâ²–¾Oó̺˜›úžƒë"c×
+ 2PMi/WÁ%ï¾féùgïcDЖR˜z,¿ñNr lH`œf1ç®ÊÌܯ%ü>5?yGÉNÞác>RÈ8x׸”B4r28TÝÀ´¬>šmo®ÔßÍü¢nî5ò$÷4µrOZ»Dé«¥¬}àY×÷¤Q 'êà)Àp¤˜ïÊ:Œ
+ƒô—–u-oŸŽ~¾ó|â‹w?[¶ŸhÿQYE®TVM­,Ü+½Ö·üï§Ñ¿¾{:ðçíz>“ãÆ69ö 1|@‚þÀ…Í—ù°µMˆa×å„]SYÅ»Ùu·–{lBÒkçCÄpåW¬sÿµñ,ç¼²f½R^5ž/-Nï½Öý{oïx·h¹°³¨=Å…ôçÙáBÎu%biÛ]ÖŸI<h;Á<îþìýKø„2òQbº­±±õ±!í™ÒêÈ)!aî:X·¶ï¿B¿«Ç(ËtÑ:ø³…>ÃzËËÆsKÚ•—µ_‹qk×aÎýÔéPs.G5êЬX¿«†Ñ®°½G{v_Üú±ïOÜk¬CŠz0ðmRɸ?åÓÇå­E,ìÊè)~}ðäQÞaiä‚·eæSî˜à\~³û‹þ"|cçñ&Žª9Û¸”Fzù°ñRiÙx^¢=$sêxè&
+0­
+VÔ†Ü÷-PŠŽæ©E‡*Z1jdâÓ›Ûg¶G¿œÿ²%¦§Vy„Ø„GÙÕ[o®¹'XÅè"\ïQ2Š#‹PMÄ(&«ÙÕ®)RÎÎ(ákÏd﵈‘CíÃðçziÔÈ©O­ð;ã`®cQg`‹÷i¹wP°Å;ÇÁEÌ¢‡¾níÑ$ã&ª‡k6Þ½0˜ïµ`ï#ñÊþ8õú±’Q‚™¹MÉn›WG-u«©Å ܳ±1;ÜZ„ïú4HÝÖ{âÕЯ1c—QRvø^ÂB¯Œ™È%a=¥(f —§íÜÖ¤•Oè9x×$½ ¾$%z•Ä<ïlו¸‰U›¶ ºâf¨[f7ÄÍpk@Ë­I˜ä„EANÛô˜IÖ[’ýZxó–WÕŸïÓ #&>ê`7cN¸=åt?§gÖx„”éø²9(:]%ƒ,Ì&"}§œRêÙ¦˜žÍëlFaËpKÜÂkßÔïtÊé˜í‘[y"™EÌ!¥&’þè§>ddVE­p‹[M/õj òè%Ñe~{Ä„4glâÞß7¤ÌßÀ•½Æ¯¡4,fvŸo?úùtÈ“59[õaf^[ 7µPù±
+xŸiŽ- îGrbØ èOÚåTÌ*%t0Þ¯eâbvý馄- I‡”|ø3 æ)±1(Œ&ˆ¬È™‰Õ!jC@Öí+»œù} œ{ÂR«‚žÿîˆçŸdLð¼„CBN® ºÃ6v“{‘^s¿<~ýe[ÆK­#=';(µ-¢ÅœüŽ Ø›#·bÿT蚀q‡“BüÊ3â%r ä øýè2qàŸ˜•Q“tpZ‚F~Ëî<R½¯‚Êc&A'˜zpÆŸ¬Ë¡ÿí o€ç/‹»²lµÀ˜ãéã¨õ‰Ü5#nˆ˜‡Ù>½‚ä× ZãVNcp‘VÔ“ Ãb!ºD«ÌÞèä}§OŸžªüM¬Ñ
+ü¯Úõ‘Y€j8UÇsôÂÃIZ¾_×xgE ¬Ý3#¨ÙzCþ~ûñ’OÉ©ð©‘:—JÐ`{Ñùµ_͹ƒYÅ]A·è¼Ö3G+>V²p! RTójz¸~óéºó?½ÃÀë3awVgîYÚͬ>Æh×Çûs°%j¶L©@MìÆ€a˜†š†ià¬(¨‘[w4Ë,vÏ@¥>„K[Eݧ+2jHˬ /"Í¿èùNxZâWöæzgú~pƒð«nºµœÇ˶¿»§z ÎRfÌÌiòd×(»¯ÔÄ|°¦(
+¼:n–“RxÂøù;lzù ’Ž”6Gû.íSrwÇú¯kée§N1åì“”tŽš‘–Ìš˜œY—1cVIï è·g[#ƒg›Ã²ôª„r¾74ØVó±
+ ¨ª?š'´ £uüæãy^Ãá4ëV@+h[ÀCêBznmH×ùçeÇs´Â½1âÕÏ“”<÷T× îý±=(™MA—æª
+FÂåti
+p‡Xë+öd¦<{¥ •lÉ‚Û5.áTÁL:»ë8=É4J
+Ò¶ ]ô8wÓhq䊈¸ÓCKþKSü#wü…k”öºð»b¬Çõ,;ýïuÉ(¥@¯”¼Â[M[Û…ª–h’ÑlfÇíö¼—™Ž³©÷ö»q^›„p);l™ 'üo…½PâÃÎ$ȉ‚ h ã»&‚9YGñþ?V9¨ÿî|Ýhëè«5ä#9'u€l¡BLCþk¾åf›(~c(‰Qà1—³Œœ¿t¼â¿·x´Ú²üëå¢xÛ$>àp ïŶ8 t"§Fézñ!Wª
+ä¯ízîÕBÂ6N
+:Î÷Øh‡¦*bîõ•ÛM|„=••fƒJ¢ŽÆØ ;b²·¡“äe–ÐÃôb²¯šŸñT^–äpÐK‰üª¬Êÿ:[ƒ=SV#Ì£¬è£qZ„®í².B$ÔÐñòdû¥:„÷õdUæÕ n–•Åí1# âOÛ0ÖÇ܇ò:•FœŽ•Dºð/¿Î6”|_ni8ù˜w ¥êÛrô¢ì§;ÍpÐNk.èp˜à§ä‚u´³´
+jì%ûÉÈ!¶qrˆUFÒ÷½5MHç1ÎçDNO²Œ'üXp®çª‰ÊJ˜MÎJ|m¡†
+sÙ—äy]ÍÓÓÿ³UÏû¶\C>a½?) 5ö|­£Ea¶»Ž-‰
+÷<ÿ¦äm³Ÿxú¡Ò„#7÷›¦¹Ù¦¨ÊÛlǼœå¼¿7]žþ¨šèPšäñ¯)î݉¾TŸô`·7ÏýûJÉû›EÀ=¤ÈuIÒ_š2įu>ëJÍ…×ʯ5õœ½ò·ÆþâPcî¥^Œr7“ ßç+à«í¸0t„ó1*þ×F“`o„–¬jÌxv4…ñ;™Dû{²Aæ!Œïír%²ŸÿüRÎDýxÓ6ÍJ2‚t9à͘óJã‡'k"”›¸8þq;6ü¾mŒž²;Tà§æÃÍTeÚ+y9—PO•©¦‰g›2ŸÐSÜ_m@@.
+aÎñ³¼~.rÑG£dˆE
+ôÞ ²?ˆ º6À:šî¶&Jzj.Nûªá/Õœì3 ƒ¶»if #ÂÐUè0H‹
+¿ßu†„¹(Àúh[ÉA–±ÊL] Éë`¨ô­NL^ A[íž{ýô°•Oxo.,ØN× pï$ª¬ÉrVp Vø™Ž[­7C1à\Ys»ÆB,wäøJXoí´¤ ›BT±7\™º(ÄûÈ9Y.ò²lÐBõGEyü¿-c¤8Ë.ølš‘öS+jùg§^`‘¢|jì—)Æ^„«QœÞë!¼4Jh¥<DÝD º^h,ý©©+¹Y`§ŽQÞ S æá ÝÀåEɆar® °ÕC‚üXã  3õ£Ý-ü«­´ßN)üÇB÷V#üx1W‹³M ˆÖÉÒDó%d·ï­kE»iEY ]s¶óÍR%æ`œfè-
+ÕwrâÖD´€íNŠ÷n7Õ·1Ù„wÇD¿øm®:+âZUO5HoT‚ø{*Aì=5?å²2õ¡QLñŸo%x“??(Žrÿý|º*OUwœ©H±[¬M³×
+³Ïñ f*“›¤¤× ”ØGôÄWvŸ
+ÓÿÙhª>SÒÞJ‰¯¶Ú1®ªê‡QÆ;»åÆüç“|$ÿêÚß:ÁLYúŒôX¡ý6Dùn²ÿ3\&\I·yžÞ·Ž•––šŠK–[š+n¸"¢,ŠŠ"‹,¸  .¹¥â’Š¨ ˆ
+¢ îâž ŠkZ½S3óž3çÌ™ÿGx~Ϲïûº8©€sÝ—P^Ý3JÑ~rQ~àxüÅ™’³NVÛBy d#l
+º§¬Ê~e”sà²*¸ã
+á倭Êï[ðÞêZ”ã|=ÒiN€r›â烕u¸°m)=¥ aŸèëüAjšû¯µ:ÚÍ?ÿà¹C Þ÷  ÚïÍI
+!öˆï³Í%逡V?e»o¶½rôî™îc‚Ã\uŒ£EFˆ½ZàdOÖÀÜWÛ
+ƒÿerêY—³ØV'´+.ò["]«²þ¦¤¸o÷Q¡‹­Å¡wËæÕ,a:áZÅɺ˜¡A×»q¾_* Ãœt—c% ¡m}ø 9ôBÉGßêؘK %íXF ÝîE{oõâÀ×ZiG^‘¼;B‰¾šàÏ•|ÔÉ(1ôl‚r9CŠ¼
+½ØGŽ²*y¨Õ¢¯i¸*Ë,­ÎeÄÞWrS6Ú <7»K
+ÏgEä C[¡Ç¢ë¦`œÕ58°±Ÿ•y:õ©|g€›¼ÙIŠØl-òYmÉ{nhøÚdäÈ«…jìú
+O5¨~ZøÑ03Ö¦à¦Û¬ä³ ô|ªšøc±Žs­¯£´P .€WAÿÞk[æÙ
+Âu£“z(e%žLpÒm€[Ü,Ô‘LSÌT]{I°Jˆ{ä°äFW[|9_‹¿Yl(?þòXú>èLQ ôÓËÝAb˜aˆ±6Tšv4ÍÆÍ4äøo´b¼,RRœMQžr3OEüXâ‘®p162]›æ`’”§üXª+»T±Ó­´è¥VÔóåf´ËR3ÚM#‚-“¤týçbHKI¼½QÁ£ž)©)ÿ§¸J¿’Î×ø}33çži¦Û¢VS¶\³&³\’ÔÌDÉ} \
+¸‹K²
+¢ÕtÏ=÷_¹¿yñ}û=ÏyžÏºæ_ûîwsWAÔBã›è°›Ãž@îò*3þ9IE|â·[èÕiÙS·‚Qpºà"úNZÄÈ'ÈIo\‹TDÐ ht/Ð>)>Å:\ùp«·ä¨uémäð
+íT1óö¦éç+ýÝ!£îSR¡gKÄ ¯›t¾†Ë
+êÒÝ .^®wsÝ`ïµN²s¬éé‡cäÔÝÁ긽Áª‡. 1mw´&þp†r$e!´¸çó´‚+{ýõϽ²˜OA‡ºHoìóØT×ÜgUœu¨ì–WÚRèVòkA¼*,]–ÇZ„e1¾9Ò»ðs8CÎÙªKö):©¦Êk1!ý‡I|Ê–î‚ÛNñuÈÐ^6‚o•‹÷먨/ÊW럃A‹p.µíO4AŽÆšR“¤”£QBBPÎA»em¥:^Áõ½‘Ê8ï" ΰօ¼a
+o÷ôy ¬*»¤>É+ŧŽxr"«Hˆ¬QÞŸéYë
+h„³µÀ!g[þ¬¼«bå^Qsóc5ðè)rÊJnöÍÍ |Ò¥wœ
+Ò§`¼w]w¹
+ÃvíÉ6ÅkhÊ ™ºÚBFÛ¹Èýp4Ó ·MÒO&1Ï¿è©ÈºaŸ#¦9¥ïÜr, ê<*Vi
+Ð'?¬ôÇêøù7ƒ:VOÅ®t|"@v†KïYÅè'v9q¢h¯ðkD-»Â*Æ';¥Tȳ’ ž^ÔRr?Ï`Öz‹h;×=j
+4´P|ËlìÞ,1#h2~“[Ù ?šÆ$Ÿ|Â%:æk^xõdøٻΠ†<—Œ”}¦¦ ÂzÌ!©yeìÊ¿¥hËþUÍóÁ@Ùý‹åÂÒÓå7ŠÚË}\«§j&Ê>MHÜFÿn×AetÄÁ\3ô»µ³Ë§¦Û&‰/­âƧ¼ê7ЊNõÍE-µàÔЦye)tê5·œÝz±5ºxju69ó@B€M Wv„‚ÏJfiÎÓ›ÿèk‚gœYúF]zíhÿò`ª:îx¾âÑÞdQìÖHÑ“ï{žËí®¾]°Vè%—›=ýaSwÛ™A@<Óµ9»ðd¾¶?ÇÈ£¡î¬q›’ƒÒa¦["DŠéÛ8=Ã9Ày嬢 Q@<5ó¨»`çó)ä\àý*.& áÖ…Wødÿ2§Ú¯g»ä´l÷æT
+=ºaÁÁ'n‘©«ú¨ãÑ솪 ­í(‰ß%ü±1FËà 7úk²ÿõ}]Ä;ÓÓ@-¯Ït+ëÒg±‰.mS^ÀÔÖ0ñÈ>€õjx˜¿q^æÀ,œPÔB|rl²uuks
+<¸Ì®˜¹×"9Û.%@òÿ).¯¯4³6Š¿“!‰‰šbŠ5ÑXÂ$š¨QÇ^°&l€‚ ‚€Q,±`ÇÅ‚EÅAņ5âL237ßò½sq®ÎZg=kýÛÏÞñ?Dl}SiÀFÚËØŠ ÜWRòmKµë¯â[?!iA–íq4Áεéd²k½Tb™$¥î”:Q0ü³÷zg^ØEö'xw¬fêÚPÞêê÷ÀºÕMY’ä¹*ËÂLjˆ‹>ír¹–a僼£/g¸˜½~L F”â¨æÁÕ‚d×Õ–,ÿSuYÊ_+Œ¢ÿt¿?ÆÌ9›i¬9™y`g;ËÆi wDpgS?ÒïhŒ
+ÿ¥—JÏ&kJŽ†ØûJN˜Íá¦al¤^‘¸Ú‰€íLáÛãô¢ï•èkm]«Í ï´üÇÈ‚„{0ËF]®ò9?7Åõ¶5‘Ð8JI–D=Q5åüø.í8
+Ÿz0Y‘|8EÎ;™¡¡ÿ2ùV-»bµík™%§ŽQÒ/ækÕ ¬ýQaáF)ŒŠîÓLœ«–OõÓòi ‚_o9Ò¥ƒt'bŸë«ãz¹éßø`Ó!bs <èp’ þsƒðd¦ŽnV‰KŒƒÕiß{h›íŒÐí.n¼±·,£½ÄØ r¬ˆi°ÃÞZÄaoͧµffÄl5Þ뻘;WÉi»*qé|KeÐZ5æl¾©yg„‡:
+ñc™Ã¶š¯ MýV­ˆ©kCÿ¾Þ ûB†u^P¾ÑŽƒ}kF{îõba–ÁŠ¨³Q
+âr’‹:£ôrn˜©]’yþµ…qþµžtÐÇÍÐJóÝÁ<˜i[
+. ÊýE1}{š[hžæ ,süÒ‹ÅZêõ¢ˆv>Ã/3“£w»JßœÓR®çø£ aI{Eæ>|ŽóºŒ5ªhºRKèfeY°±»èƒeœ„º^“wÙÖäíW«u’ÓYnÉÉ,«ðjE,¾ÐÖP¯Wkª,S¥Ñæáâ›(?“ûvg°*¥ ›üHQžíªQÞ(yÅWÓ’ÓQiåv;5ê°—™t¡j¨2õÔ”,ËŠý‡«’-cUÉçsœ¢ËEnÉÅ\Eêœ4æÙDM´“±~©i¬û‘=° mtÞšºi{`ÆÛ!Çì Òb]ô
+ªXùšnrÐt+ýZNöá=Fxd÷.réiâ|“™¤Â!rDÖ-A&ÊJþã-ëñA^
+ó‡tá·ºxG* îxº»;%Æëûè‘+ Ë늆¼Å†ÚèÑjÒ‹>R‘ó ¹Ôe”^å?H½PV?ù‚A8abCìüŸ»
+¿>
+Â]Rÿtn÷ÑËðyäD½r³c§Å<êªÊx¥æGû ùšêr뢀t ò¼¯âdï©è©V Ÿx¥ÒO5¬|Cw lAŒv[i ½_–QBë
+3P!AlX„O¼Yz“šy›•ç¶özÉ
+|­LŽ¾ßP52ÒÏ4"ú颔cV ¦ÊHC7*d{Ÿ S7ú™±ºNr°ZZæÕÏuè¢T€Zq|‚²3“ï$Â|n<½ûð< €×CG 0vk\TõÓ þò¯©Fb]$#6rµí©×Õ¬ ½´îpô’1FÚñ,%õb‰ƒ9™çãöT\¤i˜Y4#ÇÅJKÒ_ð²ïÉ
+Rï’’Â ÃÞ:HÐIOÇ«Ó]f„9/Œ¤Ì¿ÂÆÿK†6'ø(°nø(XØR|!”ƒÎ·G'Ʊoýï§Î€»“#ðÚå1àéâ ÜÞÜîߢý¼€‚ˆ@H{y–Ó’4Ïݦe"Ït¬~„±:\“>«%ŒÔ1ZH"L6”›ŸiMŒ‚Äø{‚Zu>Áü‚÷@„÷ ÀïÑ} éÍKàýk7Àzˆ{ j9ÜRL¼»ÚZùn©¹Ì{Šy¶XG|½ñŽËôŸ lãO$±“H„Ø#’ ¨%¶PKb/J‰JÙDHˆ]$–No)¦•v(míUÝQ¦õiËô¶Ÿ™;í¼¸/îÿrÏÌ‹óö<Ïùþžßïœ3×ykj kÞÒͲ·¶û««ª1¹¹P%L‡Ì¨(`ƒ -4
+Ø,HeRèX
+³¡ˆ|’è!@òõ¢¢)ŽÎ“ŸÀÄO)ÅÔç7Û>?Öþº*~^7^~7¯J>ºc¼´6¦ŽY´((.eK NRŽ»Q(‚Æ >”%ÅN82 8D“ˆ@ö
+ =–tóALhPšœ„)æq°]•yäy}5sm 5áxÙ"y±`ÎÞq™ø{îÞô½Ùþœ»’5kÖ„NÌ4]s³ŸHÀƒ2bâ€M¡“ƒ23!„
+L2‚¼ý€H„ìÈ8è(ÜT6Å¿˜ÒçŸÞµ–ŸÞë¯|uw´éádoÆbŸ†9®hô›P¶Nh;‚ŒõWðbbèa…æL@§AvT,ÄÒ˜F  éŤÒQvС˜Ï…Þ†2üæˆ:æ|ËÞz¾Ó×òΣη%]lZêN×מþl/ÿÅmO›4émÒRl.ŸéQ,ðøÀe0c?öö†*(ADˆeBIJ†W© 7Þ" 9š3Š¿lX›ÎVLÅï=¦üÃ9Ã¥W·»³=ýzö¢Í1¦”ZÄ…˜ªKé MI¾
+òpµ©iPÉKB^¦y™âã‹|È@ÜC€¡¨ï„0DЀ̄æ¼|oSU õéTWæɽÁºÏë?þ{Çå<Z²”¼^´Šºro÷ÈÃÔ•b\~R $1è ŒŒ&âKñ @¾ B ò"ÁÏÿŸý“‘†¼ðhà0XÐZ˜ë5)«À.©%þgËúÒÿLþñÒ¦ÿr0Òóac¼ûÓžÛuòhT÷Ë°.z¤½ÉW#)Á–ñ¸˜Ò$b“<Vངê†A|8¢–•©—0= uD§úJÜ›;¢g³ ̃ûÕ+. oÕi®ºF —º8s ãN×@œSÝ©«V_/j
+ÐUµ“zš”¤eûtÙ†ëçŽ×Kó=gk³öã_ÑŸïës—óâ©{âdkÜ°½<Xµ6gËñLZù‹ý6S­aºTƬqÓÛdfÊËä$YiS ¹®ž`ª”úª«™wtÚ”½){Ý©§Sr²¤œÝ7ŠÏwÇm·}§k®Î·+³–gž)Õ˜¦ŠèV7‡?t;Ëçî"‡ÆÓÙ¤ vH¯úÉ
+ëñ‰<ˆ %¡Y9 *RDxKM ã¶Ö$|63Zw¸Ð[òqÝÑz¾1føüxL÷Æ3Ø2¦©¦ ÉÊý× ÜõQ[Úœ£?q²»/Êz]R)’àÒb¹ÀFÙÉ$¢|‹âA.?ÍKœ–ãU[Xã%«¸æëPÊÙþá\wÞ×Ýqëùc‡ìÛ–Cû}tòÇË ÷ïÎÑÏ{®Áýn¹gzV2ÚibµÕ×ûç …ØÂħ@bd"ˆPšš‡×4*éV…‘³4`K_¶‰Žïºû.6g¦ÎÖe¯ó'Cª‹'CïWÇ”¯ïOwçG$+“=)Ó½ºãõÔæË•øjÑe/‘ y<Í.ˆ~ÁÏâAM¾«¯n§Ï[†Êß=˜´_lÛ;.6­¼q|?šYûqì¼ýçáÄͳÝÍþrWñÎ]{Ùâ€%ú's'{HvÚÝÐHÒ_¹BPT× Ò²|2â¹P,Ì€²¬\/©¨/NÏÄÈjkýúTræ“iKþ©gHýÛ#—í·ñ®óM‡ülÕÞxpK˵Ô[~òØÕ½97Tá2µÓõµ¥~’L¡oƒ8ßGsE\+ÎñDGBjL"®QÒD­(¯ Ô—KñÖ9iD£‹]t˜…{3Úôá†Ã…请cÓ?ŽGÐû°éÿ—éS[ç‡ÓN;ÎdÚÌ´iÒv:î$mÝÄvC“@¨76ÇØlƳ „Ú¯®¤«]´«@BHh¹ZÑ. Ђо€!ËLó§ôæÃûõwÎ9Ïù=oÖÅ'Ÿy¥¢8"aX˜÷¤”É?ûzõøNÝÏ~vû½W÷›ß{Ýüô-õ ¿¼ý·ß{öߺŸã_=ÿµd
+sCÒ„7“)+Wö
+ê¹EJÏ!bö™ "¦ÌàpÞ-óG.(‘Ÿ¹A|ÒÆK;!RÜÎÅ!\ìþ®d*²9õjØ|KàÓƒ%Á‘aMÛÖr£:ùäá:ŒI¬ÓÛjv[Cù*x…¬,Â87˜Â.,)Ø–·Ïœ°ìÄM%1ëÔ*"®°;b+‚¾ý5xĵ¢òl­ó‘ÕÕY#¬èØÀMZã¦tlð÷W‹Pô"¾%'繤„Èá’CÊ/»ÁéŠ$U}»äG:fgxiæq|‹ó&±#ÂîëDoi'¢U¼¶/*»M°ªÕ*“5ï
+Àzmú†S)ë2+àoVyà¿×Ä¢G–ù±¸]BË <|Æ 'MŒ—GZìç#ùå÷û°±²Î̤ϧschØRëÕê^オž!þi€ÖEšÖe€Ç¥b7íoÈFb[üþs©3çaŒƒBQÞ?§Èùæ5YŸb­šÓ\¡Àª>œ¶Ì>™HÍ6Õø§¶EÚœÕJèyñ>ƒùhY,¢æqëuRÁ×j.÷_r®øö®¸{hTA÷ª£×JA±¬²/7Vd›¥ .yìÜ›t0ú ³m^4ÿl*îc‡¼Ú EŒËŸN:êZ¦>ØÓ±Ÿï*™ë¨/ó‰ÿD´Üî‚°Ý£ãuZ„Ä¢~ˆ@‚Â\QÍCÃnŶÈO `Ú*¦¢=¥EMìÞà2©áxs¶õØ„f—¤ç/ºÙG¿Ù:~Zzöô•eY=h^´¹ÖÄoŒ
+FÚ.e|ÊÉ&®Å)jûÝéÖà. ÿ*®
+–Œ‰¬ƒÖŸ÷ò©ÇvîDÄ,œ°¯
+_î.Ú,ª¹«¸¬ÃãŽí%ŽwG11Ò;¢ú™æ°ŽÜ]ÇUðBô´•GØ_žü"eÀÝý.1g*ûm•
+CW!TvKø%Ç<:»ìáÚÞLÕGIÙIßœ;X#%÷¼2»;Ç/"%íàN,<BÚ*aÝ"vÎ4û2³9ÓzºN~x´AmM˜”ÜSôĶ%¸ÄÎÜô‰Ž¯ÓŸæ̼ñªKÀÊZI¯Þ…„²«€ÚzéŸ_-ºØø¢‡5–µ³ÏÌàHÒ
+×Òî…Ôøª°ûKZG®?FràÄ5ŒùËË^¹v+Èì>„¤«XOSfV[Æ
+ô…4äûûK¸º“]p& RrJÇi;ZÄÿœÖPï—­b:¤—‘Í3ŒÚ9ú“3‡o‰÷*;2qÖ,Jl`­öÅ´ôvÈ26)6ŒóƈÍg_â_i%#q£”’43ž$MCõ‰ü ªÅ×D4}7ãF˾xê}K¿Û’ò
+žI5ìãz!1¡c£cBõÞ›®ŸŽÖº®BVF«ãæ?¾×ÄÚ¼ubö[ÌZd¬¤‘ߟ4ݹ2Ò³6ö
+èI+€p‡Oȹ„¬c¿XTÙña;7Ϫù›kØ^ñOë+¾oìæ’BÚ¾ßRÛ¤†´c¨¹äf`>Fç²Û"²‡Œä<Ó[i»ÌX…Äœ/ع¸Ä*¡:a’03Ï«ÞÏQ+(ËØœ–Ý’ÑÐ…æ0— D‹©á–=éÎïLÔŸÅW¾K!y›ÜäöªI7÷Ô½—ýêžËÞ„ÃKý¿|qˤ[Œ•ôÑù z áCP©*y%bÄ·ÏÒˆGö–1U‚»±‚Íÿ²¿¤Ü÷Ü<[z˜\a?ô½Àýäï<ïR´ÿÃ9Öò½{¬é»˜[•ü?Åeö”–Fñª~è©©ž¤&3Ó]éôt'žŽÁž$Ú‰¦“H4î(î â
+²ï«¢¨@Ôĸo!*"( › QDEÙwÔ¤¦jþ”¹yº/÷á»÷ž{Îï(˜õúi,´õ%ä›e\ù½€’Ûåß#ú¾Þ˜žôob –ê3¼
+Ô³¸™Ïm³zwñ#VgHK†Åvð¥I#®4¢Ãž¬ rŽ;s¢Ú~ZÄôvɧãn!ÃÒ;´Æ¸–ÙÒRêÂzZOM.q­“ æ ÄÏ'k¤Jã4ºÂ¾Ðù4ªå´yå„·ýÈx/¡¢U¥ lTÒÄùÂׂ´u¨ï
+t…”…ÓãÛ$ƒþÝ­¡ÀOUt¸u
+hMÁ£x5\’KÅD
+JÈëÒÈ2šECqëØL|O$9×Ы¼Jìt ›cè+ÿkt¿4HbÀ“ÂNw@ÃC§@—‰éĤ÷iˆpšTçײ‘i«hôÇéE“WúV*bÀž«»ó\ëݽ
+Lþ¹÷Ÿ€’\V1ü”Òà«)ÎÔ2Z=rB™KŠy5 ˜r&‚Ö˜{ý`‘ÜpeW¤öEï"no@K®òª5À€ßÞýq\
+*ìLN¯u+Øm0»u‘m•4ÝóÌas'ÛzWq¥£éhûG`›Övi¿8êãÇ­TdØ@„o·ç{5­O/ö)íŸøL¿žÕ²·ÐõÄ£$À¢{#£1ÀövñôÕ±h:ac #lɉ´ã¡m¦%#jîÄ-â´MÀMÙx¬ ‘‚½°óû¯ìljÂDïpË°‡s<*zíÁ
+½Î2%¨h¦'£ú±‘„IÈLê؈ŽÓáSÐÊB
+NCR7@<ÿ@*
+Êèð¤š×~:Ó™éYî̲Ï"2·‡Kÿ®_³I:×é5æ©îlû&Ë-g!=Ê>´oS€M€ÿöÙ,q+©j üד%\õÈÃЪû‹/
+>h¥ÔùýH-i†Ðë²¾Y¡AoÆw©ÎUrÑñ,2ól¾ù·ÀZg–KÚôÛñ2’2ÑzbzÞ¯ ”ÇîC[L¤{Wߧv¥ìlrdWÈÈÅ[溲+„òÄ®€zú…GÃj¶ ¾ðm‹Ïe½ùÎ÷¨|Ýpõ¿¬c ¿†ÕÜÖ0`–˜ed4nZos®òíïw?Jª¿ ¯b ÞÝ…®•ŽÜ´Mú¬d$´Ííu,t=÷®ö@Û Z3‚ÛtÄÕÁëÅ‹=ñdÒ2È»ü82–ÞçÓ‚úÞ"Ÿª÷…O‰‡ÕØ‚¸žT9ê[ë~XÇ= nò©]!7fäöD´”×
+öÙ±”
+~Óp?ð ú¤™Gº<{)£Ê>z°ÿ¶åÎÞxk†g­¿åpžS¢ ny¥Ô
+·”ZâyÏ;]è~`h¹½=Rûœ»>ÍÿÚ1Go?—‹©‡ï±yàíï{äXhx‹ÞÖ€ÌP³›æQYãHRË&:;¤M÷v†Š¯éú˯Û'š3زÈû´ž…tˉE– ä]—ŸÓ*}2z…k•QvºLøùˆÏñÊÈE'Ó¤\Û(ቒÛ
+±½îzâÚÄj†[~T2 ÿl–Üm sý먧>Yç³K3‡(¨¾O…Ý¿¦l†^ìú•yéÝö—‰ÝŽÂýEX†mªðû|ó/>%­þlRéXóùaÓ멸«ãùvÈ:·øÚëöì¯ Ã°Ÿ‚*FëÜ«»³”Â̘q@|ºF¯²ˆ‘w,ÂúX„Õ7”ìç‘’ _[F¡?ã\r¹L-ö­2A ŸRÑàQ ¾ä“•Mïòˆ ³—Þ
+®öÿ9褅ё²0»zz}ô¬À**Ç1^{Ë5[;¹M¬(hÇ ê^%6)eç
+r…k…Rä\Â=5KïÙgPÏÏ·øØ/~2 h)Û /nèëM›‡øA}?.²ÃŤmÃ’¨Y,:Svûãoú¾_Åm«iUÇ È‡G³Í²Qã_ºWÛ²âW7÷&a·/÷8Ô«CñLÌ@j¨1a±Ò£À•Ö½1 Á–8×p ·àÞÿS\§I¦{Àg¦™NãL3™i1m/³r+-˲IsEqÃÁYeäAV·Ì}ÉÌDEDQT\•EQÜêÓçü'çéÅýö~w]×÷7ñýžâqvu
+>;Û†H°‰j †–¬€¥î¼ûÖaÔ³ Aê¥q>äÂ\knàá“p0×Ð꘠dØÁ}ý¾&Þ!'@¿gâxË]RStïË‚cÔBß<§Î"%'¯ b¢VúËBZóï® ÃÍBÂk!ÈHxfWÁÆ[„„·¦®‚뺖ܫ†÷E·uM°«úfXÀr/ü¡S”¯I‰‹Õ`ùÐ"¼­qJ¡m´òÍRþm!>öÜ8ím g¢¦Ì£°2Fžwª}¨åÐŽ@³€Y‚;Ä触Îô«BÊ‹s¦þòˆÅþŠ'†Vä½- îUµµmËÄr&RD‚þ@#À"Ïʨ+›CäDE'1®“x~¹÷u–ÇrË(9s­ð}K^˜}¤è¥±3ÿ¶¨6ïÆ|>ã@O¯œïL¿²2{äTV%oHËb6E¨×Þ)&fOÍ!ªÞMp³ïzµîÉR˧ƒYÑ2Œ}±>TýbSˆO<Ò
+nâU3hŒ1LÜÁ,—mUÔW®iÉÎIv¥WS;œ£W,Òñ'K šožPd‘”†oJð »aYZeèÂ$8Fy¸ŸàUq‰;2ÌÂõqFÒùqJÒ¯–1j¦˜ »3ÅËrŠ’-19e±³äþj_i趴굮5熊Ÿvq©ùøHßÐlþ5v™>”D,ô–F,w•EmÞÚW×äYÇjR­"zΩ±¥ï«©©Û£©C{‹ï,öæÝXê‚]½¼-§ålˆÈ©úämË
+Âœcäü#ð&ØT`3uÙ|z6ãÈ$hv©@£kjáZ
+¿ô7TÅÚ%ŒB»„u’S]bÄ2€KŸn(|Ð^ýŸ)~A쮂Çu+H5?ῳïrbŽµ¸=›º£*§:áÏÅõ©AßÍåTQ‹¶¤øDÛ0. ôUÂægÐ1e!†Æ’£Ô´ËhØÏ#ÄøûßY ž)Jîú§ÒGV!òéö>cOƒÍüfê½FÐ4b\Âò0.ûËbÛèÁ @µ Ãס›#Å¡#ðpŸ¡pixtÛæR²«œ
+fIe¯üì§?TÄ£Åÿ¹Ò“ꛦ!NM¼Æ#‹Å̹ó“R
+úÉ¡äÑÔí!f1%Ýelõ.wéN—Ù\¼<f½7+ÀÜ“`êκåÒTfîê(¥kôs§Ž\ê5¿¯r›¾¬q¾˜9¼}çÔÐK¼`_íÍ° ’º‚[>#ŸëÓqj|Z.Å5ÁBÚ¥„8ë`qý*b_Å,·‰ˆq¸ÎÑšt·‚M±#EFnË@ÃNÑ
+W匼 9³È­avÔä\›îÒ¢^û³•)^ &ãpŽI½X;Ñ{0%€¿:Ðv‹| M}`ÏÚ¥U¯tÍÙþÓì´´|D~œ ¢üú± ·Ü£¬±þPHzé'¥Æœ×6¥^”oÏËéñXÊbŽ |ÁêpåÓ 1Ý1ÉÂl+¸Õ»Jj"Î6Z5Û–qÍ:Œ?16wÍ Û“ Å>UF;¤„t—¬&kG:UALÛÁÆ®öU„m‰ÈÉv )iùcy¸UJÉ0Ð3'yð€I ûo%3ûÒ4·øÁ )ù¢¸rÙ<Xùz±¿<zZuy¢>󖘽¿Òˆ> p¢pû:Ñ8„z¦iÏ
+=YàòO–x-v°W6†a#ÈÈM1èp9:æØÄáìê‚CAÉq«hŸAм%ÇÆ-÷Áƒ&äßµ¿æ»àÁKC5 ÍåtlðÙ¥åÿ§¸ÌŸÒLò0^³©­™ÚÍ$©]7“Ìĉ“˜Ä˜õÈQjŒI4Æ#ÞTTDDN¹ÄŒ÷A"Q11
+ r(7jPÀå•Mjvkÿ‘íù᭮ꪮî·ûûý<Ï“jº¯f4zgiºîW?õ5¥ŸVÜù³šUüXÒ}-™iÓýà
+»%j€È¿o
+%1 Ähi5þeò« –^ç×hÛ3Ä¢C«ùdÉèµ?‡~¸>\—0ÒüìÛŽ7¾—%ž³v—Þýbb½³Ä—%êë°–…Œ®
+(¥Ú¯o+Û™žk¡%+jâób¶Y`……qŽÃî¨Zò£6ìÕ
+0–hìG¦m½C$ú‡Ê–¼½tþÖâÁ”}þh‹Ù™d×d}²k¢5ìA;³BôÈýuâ}ù,ê÷/³ZV×wÕ\ÒEº´èÃà^çÚ@=×%ïN£ž–:ÿÛaqbfJ}@ÓV|²Éÿ-âè‹Ú8ä+ð¢fvðqGZ*ìh“_EEÞÀnm/ÑkµÃèT¯’Þt¼*á{gHùŸGª~Ú‡ýêjHÙ¨¼æ›&Ö ‚dœíiÌ£ÃyB¸'˜_ÃB‚ybÈħ†ÍPGÀÈn
+!ƒX°=dži8­'Vqï—Mq_x•2÷Ã~Õò«â¬u »JrÑž
+j6¶ßh:YàMØŽ·uw†’¿“¡Ó¿]¤åüE]ð+Ú
+ÿë{VÚP’ú{óÈÉÕ1s4f†˜g&Rí‰Wᙧ™‡ ¯ZF
+ãbë]ƒG–!ÅîŠDìcÖœZº¥'ˆqfâ‘#Z&2 Âä¹'«“wÿ½)Ø_íîõ.
+as×›c;Ä j¨ðÃE|¾÷ckÖ$!7NRyï»=½ˆãRÒJýZf³…ƒv d»@-m7§¸Çà niåu¿_¶«¦Öê†o¸>²`{*~û¶‚T°£ ½ÜžÅçxæp9ûbñ‘‘Û4ô˦!eØÜ/?±õÉOm¢®˜½SFQœ3l^RK­ö­°‘º.È=Cú#ŸdÚÑIö曫âÊË›£õ=Ó¸BÛ&Å:B{ì–w£œ”ë#¿Áù‰Vä~Ð1Õš¹1U—6Ðü@óìº=X‘@~ Ô¶3O)>X&`ƒ»„/ð(IåQ«¤ïH/ jøø€ô·ž‡­ó˜'F«w—k‘6Þø<Ïò,ð0®yÚ:Êʵð^Xºˆ÷–˜µÿTÒK/­tÃnij“ÞuœW øf˜0ûÛæ4SOù5ßTSÆú(<ÉÒ_ïù
+Ü9枥E¼ˆ¢œXùìc 0Л}Ë„›¬öÖþRkþÞ
+±¯„ZÂ+ÒéãUéø¼c
+•úYO0_žÀÞ¿´5ŽÍ^Ÿ"½Åç^ø<‚L9^ÐCzýHËd }*\©}¼9MÛÿjƒ„g›|±G ´õlà³cæ^ÙøÂ`g–˜¿5‰JÝW1›< "šqÿÄ3G‡Wù!-^„ZJ.Ú÷\¼(.¾"§½¼r¸ ‘rR©Z\ñ£oø
+ð±ñ9'|Þ à_ÐÐ%t+˜µ~ˆ¿;Ïkë™È}u{‘c™º=}ìšÀ¤ïÍ´?õL¶¾PrKœSíeŽ”ºY^õm5Tï‘cóB „¢ãevSPÅiÛ’# ÖßU¤oH˯ElZÄØ)tÊÑY[“°ΩªDëPÕÍ馬/­ ŸCf’ ªÓ¥Ôò¤Óõ¾OQKWODÇÁø¦Û2í}¯ãu¢‚«.9"ó«£sÐ2Ž}¶(Açø×zßG½Ê5 á˜Àe‚œšî ƒ:6.`pC&*l`¢vfIùžiò ¯‚^¾9†J±T_]ª¸¶,xvÉ:Pï”aÓçD8›¬í…ZRú£SŽÍ>Z¦ÖžZ¨¨S ±s(¡5‘0lK"æ®îcSw&f— žÙ:E °J(94vÔøViðÕIÂÓ÷´²+»ÓLøνDÍ®Œ@¤þ©~ž{qg¬ñ®OA/3NÒ‹‡éÕ×ß3ò.;?ârŽ–„”ÿS\ÞOiåkß¹wænîÎÝÍfÌd[61›ìÆuÓæjL‚¤ib°k;Šˆ r¨JW`ïbE£‘)ŠEzA4›ìæO¹'¿ïOç™yßç}>Ï‘– éšøVg­O ö‚<Ô­`a½*{ŽšïXò@eD úb Wô§‚ü`ãò’fÔH¼¸Y<•0 EÇ&Ö+¼ò&ˆGÞü, £V…””k™V²ÎiI!À¯O`^ý0…ÊýÏæù…&èù%RÞ%‹°òJè-½BÞ×poˆ—âœ%W•½¤ýEâK÷
+2+¼ÌöÊnÚK£zZ«g½«=a͆·è舑\ÕãËÃúŽšàf7ɯeŽLÖ’Xp°„ÏqΓæñöÊ€‚ƒ
+È?ëé(
+ˉEžtg¦¢ÔÞà#žß›Å½p-u¾tL£ïy×:`{ó¸gÖéÚ[{Ë|J< ô#`˜À<Uõפ™Ï{¿Û7›½y¬'#×0ÏZ[Îáö•WE©³JðOÀ=½qdäpâf7°ÑYn¯¼¾Á.LQv•|;Ž}ðy¸,=¨¡!¥,xúx{îÅÝBú®6P?ƧîjŽA_h8×*íõá: ¥"o:ç:KŽÀüŽèY„ãMf›{± ²3X{EÇxñõdÛ¿55f
+®>¾‘ò…y¼òÑAi©žìIÊÒõâŠkøíñáiçj³>ísüZrà —ö;poy¬÷6.ÿã^w÷‡]"êÒr讞µ»€Éõà.'bàR¢×sèI›ö·|Ú£â“6
+Þoõ
+":.5(ê@F¢½#V„”m)ú¡g— rö]㛆T›yÛÚßð»_rÕ9Ræ™ÅdìÏrä=ÅW§‰¿ÜFAOMLÒ™•‚Ž›:àà­ÎiHð(Ø3¢`fD7ÙÄ3‹x:iæsNÍ<fâó¿,”æÈ}]W³q’ô|…Qÿ›u¬ *çÔü1…ßè®ÊÒ²+ïÚÄ ËJ[îGÖ‰%&ÐKÃ$ØÅYÊïƒë@퉾OÑôP*R‰G†}ì• \ËøŸ(ß]"ê‘·Öè-GF8¦§6‡ÕÈÇõ&h@ÑZ
+õĵ„.ò¬¢söeÄ¢e.üú½ð×0}Z[N…{7舰‘CöjØm
+FOÃj5Žb³w¤à Lý/ø¨è5‡Ë„× æs™é\ÀÂÜ
+6J&ÂåR« ?ìÌ úM-ãyßm çýdŸC<Ò UC C5Oƒ
+\ñ'§wg•P nºåUvã’VñlÒJ#&̘²€ªòŽ´ëΗR ã+×âÙ{·wOÚY`‘t¾ði¹]gÖaåßVÑÔ§]ùOG'"ò®-Ï>Õt7°J¯
+É8Í5Ÿtbx›tô¯œ˜bï[b¾mñKÂÄ;Hë#ÇHeªs²ú†_†aiN³î‡„ؽQ£MnÅ
+&ìûÑÖÌoxUiÿf½þíŸ#¨Œs‹ÄÒƒ·ä€²³8ª§Ô…ßQ›OL|AÂ*’Ķ…#Q›˜´p˜>9©4¦cv‚ýƒqfeÓ›<ò¾’Ór¸ÚƒvN°òåì†k} OÏI;*~ ¯ðÑîiÄ1\•jç§ØFª®í-´ClS˜L÷"šØdâ«@q@F‡‡5LdP…Ï (Ûr=k(¨F”E-(ºè^jÌ:³2h^éWá^ú×ÑC­°¸@þe¥aþÚ¦bÞo3ðÇ[L¼^ó™ŸÃ:>ýhS$lðËXDÒQta¬õeŠ†ßpc_ô“¸!÷¢u æZ¢TØÇÑ÷v§°Y“øW—Öº *È5>°=Ý]8 ”¤lˆš²ý*>%¨ëBÇ·ÈMÇ&b}Ôˆ÷²£(¨ïB L\ÌÒ7ßæ÷%@^NXßÆÌoFcæ¾Á}pþ¶äó"Ý4Ú|×!!V á ßË8Å׃+ÌjŸmèÉOQ³r.X^ßÜ‘  ³dXŠœ_qûì|^EG©u‘nA¤ï¯áŸGÞÑ›ÀžÁŠmõMœºÄªˆ…MóªY­¾u1/º9.;µ÷ô‡õ ¨õ&¶8´˜‰æP¿ãúþñ°šÑâS ‹(ˆ~ :Õ>‹ƒz×i +Wt "ÖZçÛaa#_pìN… 쎑Môªé/è¸EÐÞ ù7EÂUW]X'äÅÂþSS¯(¤aawVè%v)¾³ØU|°J.3·< •ßþêMË£ï"r{HK(sË0Ïvæš2Í#ðkn©|OÆÇ;¤ÝÍ _R“–Þ>ÿéµ_|¨BåîË[
+sµÿ§¸¼¾ÒL×(>kÎY§f&“6f¥—‰&1'šfâXcÅØEQ0J¥}ˆiŠP4{/Š(ˆ)‚±‚ ½8ÎäÌœùSÎçÅsñÞ¼ÏÚÏÞ¿}¢
+.°Ác†Í=Ó^ƒPäP1?‚o›Á%HÉeWñ]¯œŠ lŠ\ëí”cµÀÐSó`¸.ío=U¯¿]i-‹j†%ü“žûcou²g…Rì^òܫ令.u{ú\+L¹¦`¾»°3€x¾/¡)»JomËïÙF0ïÀž›ÔP*~·Ò°¿áKˆç
+úôW«höK{g@ŽIñHªãŠ†ì°ž„@Ï´ËIù†~ÄÃ#1îXn´Ÿ°oÈÌkˆ¤è ‚ª´‹Æ®Úûû#è§öBÖ()å»q|ú•aJ¶S҆ݙ@¿\j)º±Ö¶LÞ©zq¯M“Í0—º[p¬¢Ãrr‘GÅ%‡õ<ö™©½3b¤5tx¯¦ é^§@=jf}d»g>`|òè;8;óxÈîüÇ×6Í«
+6†™Ÿ ù÷Ô¢†ÔÃÙÖ*K}œȸ<„zwYF}S×–uýh™Ò1Å`eöê¢c–‹ iDÝ^m+- æ¼OMƒû6(ðȇéÞ¢£¬2 wœUt¿—róÌ&š ™ûå!PË'k”²Ý‰qö…†d·²©d#ÒJâùye{ ²M­ ̧ŒµƒãPqЖ)rê˜Zéu¿-e l3¤¯†ßêÓu´øô\rÀÔÙíÙ
+?6…£öUV£ìQ'Ú’]Ù ?Tr0N9ü[B˜ßŸ÷d¬êÝ,dXó‡uAË Îoü, o {|:.Î
+öÅ/rBÞ…|¬
+DACG«e†œe›¡ƒùM.=Y¥Á‹¤Ì¡†W+ܪGÒfè]pW1¥©ßÑóß~¿ÙÎqI
+B.Øø¿Y„ÿZ¨è°_ìQâs‚ ¿ûÖšávIc¶mœ˜p8Ý\
+qKéÝ1*äÉÎ,®lwRb£$['H)»ó@ö‘ŒQúe’”ì\":ÔÊåÔ I;ìÍÉz—È»!y@­‚>YíT1áðÞ–G/lŒ‘3ÕÄD§šÏ³-²áRâNoMÆý5‰ÿÞ…ÿä•c³ëDØ0%7*ýÉõ¿H»+²Â&+dèàÉÉ%‡ ÏÙ—«ßÙ¥5é~ ‡Úìh7Oá dœ¢«[#øÄ­@´Öö.÷9'©ATsqÆyFÞ¾”‹<QÓðûË ¥!S[oÄ<¨ýº#˜[èNã·°Én=é\£•éG0oÉ/þå[°KìJ‡˜
+9šÂ¿ý2€Ž1õ"îlôbcÆØð(dzô_gi…ÏŽHYJ~ñ EkÁeëpmôÞTM¬[†NŠh¸8Ÿ¦“®™ÂçÖçÝþ»µUäÓNÜÚÑÕñÓô©¥6¶2Ϲcw‰U6ÉGÅóªR®šúë Jfµk¾1ëhšžc$½ÞìÁ=]aÕÞPµ ¢í³Œrc&^ß]vãPŒM´MÖÆÛÆ/íbdääC .}{§àÃ2õqÊÖ;€÷‡ÓؤˆžZçU21®ÅfôÙ 8Ûl¡»V‰û&!¸Þó­’Kþk`Sþ´ >Ÿm‚þ¾N«Ú›B¾uHpù{ÒÆü^Rú 1»üÑÎ%Õ:ˆz¢åEÉY9W@Yü ¨~{q–sÇÔ‹Š› Ý…Æßüfg¨69°zÞa™G øôíLÜÁ"öxþâHúñ…{…U½=Y_°zãÁ<!3b “NTBÄHÇœYšq¿Xx÷:!ϹRŸþ«‘×Òñù§[ÝÃç÷Ô±ðAuìXR—d¬x¤lƒ\ÿ2‰O³LSʦ؅Ѫnhì‘(žk.Ž£—<
+jÑÚ:0‰›=j~µo†WÔ4ÔÕ"ÚF/5y½HÜ• K–ZÑÑTh¨¡)ÿÞœ¸è¾FXpC/FܲõPV¸ç¸èm%)Í9ELßgp)™Û
+ o}ÈQË£X𸫦Ž²¬ã•öñ½YféºçPàRõ DÐH+ ÈEûÓôâÅ.Ôc‡œ ?6µ}
+ ¨)à(Õ‹sa¼<g’¦]_|ÿúÚ†¼"æPËÅ-¼k›ëÂA6FÈoOA½üÏÉkúËÉküÏ&ºL.ñëðKï‘Ñõùq¡ôì˜ÇG&öÓ‚€~¬á¢ýJ
+2XÆß$îÍž’Ue~‡Œp ÞiÜ£¢¼õÎRò¼³Ì:Ÿ†‰R 3¯ØPÉŸŒBÈUÞ|–[O…Xè/V‰ìÐÀÃÌ­ NV‚Šõéê‘›àÆ'ÅEwÔYWeؤkƒä´[ö!L"ÈZùø«Ë)‘aß1à/NA]ɮYlòž
+“èÓàn9XH[“”ÌÝVqÐØ"ñë4ÇX]ºOK+s}ÄAŒÍÙ7±/.ZK£ZIÙá¹±÷Ï~ ¾ !fž¬I8£c¦Ÿ×±¡¡Ã¸¸sÝhȵ¶êÄ0mcáC•ñòàê?PÉçÓ ÜÚ81yk¢&Þob`¶g)ù+#˜ßW'jý oÿëlhß!¤{fùÔãåÖþÀJÛè'{ûìé–¨÷³E>3jg¬úé¶ûÊÐQµ.'¤î“Ó·k^:åÕÇ@yÜ懒ßõ $»œfaõ“)n^øfœqw†ùöÒ!í¼‚tvšštn©9'l{
+?­H¤E>ýØÔÈ;1‹%cSý‘ž]åS1 ÝSì"s;꡹¥6Z%¨z,C§_V§\j.~u~ÿúò|SáÝý±º¯
+(ÚÇe;&ð™û^w®™ý†ËÃ/éE ã÷Ö½öiZ§:VvÒÔ2ÍÔÈ‘9Qq
+3n.v!ƒ·GÉ™GV!cà“=“ æÈ*k8œ3|“dðî$:Ö¥‚/õ
+Ò a5<hèb* È¡‹¬$ÂÑS“>ÝML”¡Áw>b ÁÛjNÍRweø´¼<xN}³ÖíŒãNgø„ãÙ&™Û$$4ã2ýtòÒ7?øÔŸ.ål ?›'äœÚ‰€ˬíèHNÑ;¿~Z^Ä¡]Üî BÖ»+BíˆG:>øFüÅZÆã JR¬ß¾žQ6"£I¾õ’Êwô”­¤€nª˜¯nÍ´¼ pö¡bvuœ:¯‘O`•ÆÜ׈ÀÑ¿W$M?—D ç6÷ÐL‡o©jç…áfQf ÏHƒ àÑýôü0ŸCØÖÒà^ñƒk¨:ÕÔ\ôZÅȸk–æÿ1ÛQÚÓó©Z92q©MøkEÒr¾$äûô„L×:fMYq8ÃÁ÷_":)|°©$¥y'y[c4¨kž·3)Ä:)L-èç #kœ{¯ {ÉØÿp¶¹üÅú )˜«Ü5Á*šïÁ½oB%øcß?½Ð]—üdW_]W•Ey&k²¿OsÉnƒXä›oì8[•´ýÚ|üß&WàDü lü¹Üiþ±,ë:qˆ$Gãxž^¶§Ã%7RK|&vq›áÕ2л€Y„Ðû½è¸Kí¥ÿž`¤ÜôN0‹Lò’À~Ò‡+Äë J4€¹2DȾg—V‡OÐsoXy97œŠÂGË=È=ô¤’ò×GY›Ãµ «/Í°¿¦›áa®/E‘‡F"ôtA"?[j~¤Ûk¬Gxõ|”Ï(eXeÜm}ñ–ŠšæVR?8
+7M¸§ØÅS@—±wã“|^õ¡G<ž¯'œÙ<Ë(;še¢º«^™šËƒ×G(°ó•¦Ám=«xc¸6qm€”â짤$eχê2ïØäÅ¡{:6²…žÿgUZ„¿±_è™ä ²Ì[:áûÀ©Æ´Èo=yoO¦…ô“Y¹ÌcäTÓJÞÜæfÇüZKm@~(9.eUÔÒ§âGf øŽY’´¡a‘` ÛÔÜÄ'>³Tq`eaí­Ð QZâuIaØÅ6Dø…åèÓ# åÖ
+0ùqÏ.‹+“ÂO¬lú?«ÅÙ<›àA†¯ ÀïNáRΗdmÛ>y¬úÌ"ƒ=;_Kf¸Õûf6Ò£¢f»•Ädg/êùJåË5+‡ {ëGÊzqyöSy²ðÓueuÚÒçÒXkkqpo]æ5!,ꢚ›zϫƤíèIY.5æí¥è[ŠŽ`gC§K“
+ähV$;[ll>´I¸îqF¡A^jT”…Ú?c^ï›EÒsGëàÉœ˜ë3s*¼“\”[ÍEm¨˜Ï8±>!¬Ôȱo,
+jñÁt{Ÿó+!q„’u­·*ù¿£tHÀB{iؾŸüsùê(†I‰½ÚAÈxujeS~~kàmëI™‡V*êl®žrbç“vMBŠ[Ë«ÔÊP/ûð™¿]-êÓENÝ®™’³¡Â¿uTÇx”Ø×€¥ÎõQA$Hü%JnÔuÇP5bgŠ Ó4$ùDé¶ÿ3\÷ïhïÀwíÌÎ\ç\g7¶kóu¶ÙÎ9f;¶9Úš™9Fn‡“›"IEEèV·*•äfF%„ÖH*‰(¥$r3l¶æûùýýÃëz_¯›Ç³ñ‡m
+àwI¹ÿì‘!SÏÌôšõˆ'–ö÷qÑ»kòº'? Ö&_Ò’³щJãóžÆ\€ƒb/EôÄúïv&ᇃEüfe5ê‰e~"Å%¯ŒŸ•"ã©¥×eؼkFFÉ- © fš½íÔý¡k-»œ“˜Îê´hvaJÔ¢ñØ (KäBŸF5g%D÷T¿úÍÀÊ‹Y“aSÄ쀦6{ñæÔʨ?¶Š9fØ»•‘ùæâ€ÿfc„
+R¡šQü?÷09c¾«9}Š‡þg±™èQŸ‡>#Ôì˜HE!3÷Í%’/óh »4<ÇŇMäŠc›tîtž8xÌÐ¥dÏÂ@†·~î×ÒaÛŸ¥žQJ¦gœ
+ä†[ILhxUûF.: ôäžE@Þ_ì”ìÎsZwfièm=©xCYÚ33P‘E>å Á¾Ø˜ÄcGõÐ&âîÎ ÈG&6Ö,„='^3¶•Ý\—£íHE'ËüÖUu Ä®Àwg•>-%wož ™óÝjüëmz¸ † ôŠ3‡P|âðömLÂwŸHöÍ'ý
+ÜŽ“UžÀ?ÃÄûfxu[fI@Ï„}õv}Þ[pŽ"ѹ«gò|UúéÜ!äÚ̈MÌ÷L²Š¶µ<`op«ý¨„Õ~øƒ•Ñv¤¥—ðd¾ý`†¿µÔY~Û=\÷ts‚±·€—ºð 냰5y_íÚ ;Ë;FË^鯊·÷”Åz‡^[xM åÑÒ7ÕDÈ™³£ëËJGÇÁ’¸mßÊoÙ™m-, è‡Ëñ¡­g0²$æ§9UA§Ê3B8ûP›%°85ã¿›rJõ nEN´œø_¼¡­âþ
+Oq©ðÐu%ú­³öʉ© ˆ­1l¦±½ ¶ýâ’GÉ~¿øR´ÜWŸ'¼æAâô¬´ëCÅ 'K¸¼ˆ‰ç–W
+Ï1kŽ—™MÁYîØÞ.8[
+Nl|Ú‘Kñ[áG6à‹C(<_K8ùœ³%:bbT5´ü`ž\ƒ-`‹uÿ`Ž›h}gé%‚6U¬’YÓ‹M%6ikýÔ=‚M¶ÉP öu‰îQ¥CÞs}bemOµUnªp ÏPM‚_…OÙÑ5gˆ9«ã¨$›“|d ÂÀLM¼ú°Y@ŒXŒcG÷Щ³wìÔ٭صÒÑ~}$db×xÕô¢À$bÁâdÄì+}u9—M<̃¡6èÒ‡–Ç(ïoY¥xдÿÊÒM
+H‰U÷7Š~zúžÞWÏmïépµ÷v*ÚâQJkïª Q!C"CöŽL´jÅ–ÑX™$F!F¨º´úÆýSž÷ûwÎwÎ7›’d¤âߦ˜ '†jƸ
+_ôoppGƒ-ÜÓ“jN–9ô3‡w¾Êÿpó;¾;ùÂS;ý‡³½ýÛšpà_Bɾ >wðEÿq >œ¨ ë#ðd÷
+O6‹7¬ªn/ˆ+nû§1…&2¸ à­¢Îe9>×2†ÏÜ[]èòiô‹íãØÉŠ@|baµ ˜Ò]#àÕaaíýíIhMF)·K0i&~ýïT’gŒTèF¥™ÄU›2f펶›·=˨ÝU£2V€÷ì}oîlJöç¨ïó¸kâÿŒ/ùnp¿,Rê·T¤r÷&Í>€ˆß”ã³öô´º#ôÅÒ!òÌ2êvtêAÌÞQ± ·iQ.
+&Î F§8úyÎn|ªµ£ã"+ðàfñûRFí}neò¦èúÿ}[ äoÌ0ë|ja뚺›¡$fö K®ë¸ïŽÍÔ&·¢)qe¼á‰sïQÀ_íihõévÃÐǦxM„_Ez¿§e¬Õ=2wUÝGg†J`YWdØ‚p{4Á&g‚•áIw®ÿåcCvÄîdk­«êUPpK…K¼Â<
+é…g‡iy°¨¥~N>47ñR{í‹ÇA}凋ÃñIÁÏí«nëÛ î‚Ä\2uÖ&%ðLDéó0 á¯ß-̶33½åÄH‡nM!³Gq¯ÃùobÿÖQâè®y>ÙJlN¿:ͨH92³ÑZ>fck•D Ã_]fWÆ„LR2oºGÀ‰4`Ü/~eÚ—xðÛšxàÌÁ¢š°Àmmkñb_}ÔgJI˜[ÙVÖJ¿]wç²k
+ª`é¾ñº¨-)øéæ(0j ùY¨øíÃÐ9~ΣýE2„P•p_ÍÔÕ˜õÍ"hÿnuœY¼#3£u߈îj›^þéa²Ï\l!¥>õ¢<þñŽ–J9sôjO]=ºÿnwªÿÜâIN­­àMùÛ¨]6€)Ž•Sªžyè¢MiËë­IláÁx¼€ü°’!~ ¡tG׎ô©¹Ð•rv@+@íéÚYjÕÆ(<ÑÖ]óPÅ~9Ž)ºêìmJÜRq =OhÂñzbf"N­,ÜÙ
+‡yhæ×gYµv°©3=s½ìÊN¸OßÛ4vpԔ꠪­â«‰ٟÖu„Êàœà”r–{à1óÌêƒMé?ÉP¹WuÔ¼k«Ÿ
+MÃmiS¢æ‡jACô¶’Pné®2M+ŽÐsª-u·¦8GhåŽ nÕâ°°0,¬pÈèeÇ&ñlµëQË×”¸"ï4ù­_ÍnÚÖó ~£ˆ|Á_m“À’ürXêÙ2µÅ1‰²÷Ößw#“•4À¯˜’ëFøžo–Ù0ÓÕ /¹©צïÌ@6IÓ[ì¹s•º6F.²‘
+·uŒ÷û&&l]+ÚVêÏœ<ѱ…°k2ÈSçEÿ7”ˆW›3´j‹”_=#F'ÊiuÑ;jØÕ]w×ÕúÝÔ^|ÍÈ+»iî'¬ô4$z§ˆ —ª׋«¼Û Ëùýâ£j¾^än]ŽxЫÿGq™=µu_qü©}I¦Óédâz2“i&MMë8ÅfL2®íØØ8`lÌ.°dH Іt%]]-W»X,vÄb$´/èjmhßÂ@ˆÝÉô_éõÛyù=œóýïç{ò6fo\?ùì4 OÂRØ»E~NzÙøÙàý†ëU›ù¿´xþ÷›ù{hzeî£ð|×ßBó Þ5Fg÷ÝþñÍÛ×*>@ù!-Y»sfò&ü£ð\Ûuýþgg>­ä—ò£{üAß­9gƒF>ysÞÄéAµor‰û¿1òú¾¶‹‡rzvh—7°Êê»n•ànÕ>åÄà3{äýyÚÀîIÛ@Þ5§Ê¹5+Ë’Ô£Õû۳qÃ2œÒsºüÒ.”¥¸›¹ÝáÆ’qòIbOðz?ôíÜDëŸCs„ÛÉõéŸ#‹øÅVzoÔ÷‰U·€ž0 ñG»Üî¢[–ý♢ * ÌÞŒÚÝk*˜)Oênj_ÁE늩-Q#£M'üas¦íÚ™)›A\ÙÊÃÕ¼ ù4$â•|2èPÏÇ9”øæ÷!!÷2&Q\Æ`ùeD(.»¸Ãy»;c`w¦u`_Æ"$„–§ïƵܹ=å­ÝrÌ×G‹ Ç[÷²Î/–pe'ˆ×ÃC7¬RÜ­D­ûôŠ“O<óÐúþ#c.ðϲֱ{ŸzH;4óÞ ^OxkúÁyXÀ¯ù¸ÓçaîÔÕ@zd¾);iu?{ø"(`%6)?åôÔ§e;µ#¦½Ö’ÌZ€þSv‚§³&NwÁÎ+»e˜K›E„ŒE0š4‚¸¼$Ö½<ÒÕ¡Xtð“˜Pò«çª©¸€Á¢G
+&l¼×9+³3·7ÙRuлªˆð¨ˆ?ø¤¦¢UJK¡¡ø»5¥ãtFwY¿ø78Owø}·BÑq{yêݤqŽ—4i„Y³ÍB 6¶Íxr¬g¶šÉY@Ì; XE;«ý+ã¥}¾äpõ ˆ—CÄÔà®7ñ1%„O,# ~•@¹”31ú fFWÅ`s6V_Ò8ÓÞ~IÚ„„‚[.; «Ö3Np,kãà)6.²¥¢_© í.0ƒ:ù¨[K»¿¯iˆmÓÈ"òåq!ü>Hî­Y'Z+jOÑʎ行o§v“ÿqªÉÝ£ðRe\bû½]øü/zú£ÏõôÖkUTOÔ; ) ô&e’ÒŽÍòéÊ’¼&¥÷Øã =¼Lk¯Lý˜Úãô†¶¡Wþ5°;®‡5?úÖÁêMêY¯
+fheÌhŧ”'íðä±C™¸níÛ±ÀÎ?¸5OLèá‘€jò~FËè¨X9Ã%‡`¿Í{9Ëèÿ+<üìOÁEÖ«¬è
+¯ànì+[¿Œ®õþ£`ã ¥ìrVÆ¥}
+IÁ#œÎÙ„ü¾ˆšw‰&³6[´Ó_ä „{YÛT{Þ ŽûvY‚Éö댎¦?TL‚Ѫ]J/Z£8Q@¸„”MÚD„"—ÕBre%(d¢láU½üÉ„7V÷ð)g>!£æPÒfÖËÃÕéæÔ.„Ma¢[MøΣÄ5¼ÅÞB³ö­øÖpSÖHi+#<|`m¢%°L|\÷CŒ’À…WGV:þ~îÇþtq0úì4PËÙåc»FíÝâŽvx—Ñ9ï1åæyâTÝ”UdüI ¡öœØÃ57€=\!~Ÿ5ОŸbÝÃ诺X˜3²Ï*XfúŽÖ(Í%'8~r¤XÊ (ë€éµ€böü@¡ùˆúwÕÁÈ™i/³Þ›”Y:QòÎ.ù7':\KØ{ù}1ï§Jn€˜³Í¼.:y„¼CÆv*&n{g§[*.•<i`ãïÀΔ‰¸˜„IDNØÔ¢cç‚"j€ñv5÷á‘is5l\W§¬b"ª&kb” é4
+¿·ê”±¢z°W¯˜¸a_˜¾{¸Íä,rºg‰Þ|°>ó8þ•ƒ¿<ÈʘSt‹QýÌ‹È.£%k—Ü*iQ‰rû
+°°/šª¸ fýP *x1ßæÌS£’ôo3LjŽèä¤À*Ô–6@ƒõ
+bKJ7ÚßkŒ¢·UÆ*ezµ¼î.æ‹„ÍhNˆ­O4§u”ûk„Fd÷zcÜ©¹¸øêÏÉ=ðul‡‹ÍšèÄ‹ ›xáQÏaYÆÓ“Vºç³¢<²¸‘rj–bV9-å9Ì}„¸è ýŸãòúmë<ãðEÑ»^´EÑ EàÀE
+sw‡yuøÔ ¾+Û鯈÷€Ý”H0Î %ï Rã 'ÕŸÅ@r5pø}#Æ\é¤ùô³ }¶‰m~y‘¯óêÀ¿pMô*¯tÖ1þ&nf=*ÙáÕ°z¯Ïý"© <¹LBÜaœKí`œÕF›¾ ø¦ØÖ+äQ3÷°5ñÑÂß~÷ó‘E½*èñQVíiF!fÑÅyž5qŸ&ԼɌ^¬ÏþRºüðfÃpÆD;L ™#bïÒBö™—·\²ˆßdM’×Q-s"._þ¬îÙyØÀŽæ^p¥-ÐRÁ¥efòmÜÁzÚÀ$´ŠWͯ弊O°™Òï|sjå¬VÝjaÞí4… (%*—<9·*i=l¹Žá:¦Ë®½©slñÎû}ý2 ì]ó}ÕE.¢ÜwuûÑô™ƒ=×pÖÆ æÊ ÆXnuÜΚ®úx ¿Œ]41deK7ú~öÊE„·ßóiÝ¸Ý kE;c*G°ù *_eæ«<Ÿ3̲v‘ƒ—í¸Ûɤu„Tð'¼Ù“¤M¾uR!QiûùÛ¸žt7.Yü´Ñæ £î¤¿ŠÞÞÈë6o_áý° Ñö2V+"ÜoÀ•¦Ÿ>[óïuˆn³$¢#ý#¤&Ý­bJAÚjääœÐr姬w}0¹âÓÀ5ŸAã—òsæ~[tB‡½"bé3\‘cãŠÔÚÍò9DfçJn`¡—†8—EæÎ0ð¦Føÿ±ª18Úq«ä=VùôšÅ©fòVß‹è” áá ÇàËnLmf•ÖQ^f!e3É!õò mXDl£’:>®+cƒ"À®ûÈjÞýgÍ$ŸQÀx+1g"z̺‡[t‰·’¼ýó(—Tòˆö9±ú²¬
+ Jro;#C›Iª`‡/ÎÂàn+#× ˆ^þÏ<F'~0?Hí¿çÙÔq±õq5Vr>­y™küÜ6Äaå(Ïc×1ö›œ6Q­ ËlÆõWÑÉ
+ðêËÙŸYYk·ûQ Ú‹ê,è±+ç@HaÔ@òj !£~-ë´HÜjãª]ªŸê¼û)[Ì–°ú>½Ÿk:Pžù}q“ñjçSå<pÛF5|çÛcJ훺 Úù€óy?–âE!<ÄehÂ$_ )Ló¥y)®‘ÎT}à벋òÝ9ÆxÝAü6Ñë¬!cRàK ¤ßÊê€Y¼u¿tÂÞ¨y$”*&¢4#0ï=.3ÿ§"÷ÛëEvŸ_—„ÊŸþ¨WHS'àK·˜ò9J§}Õ«–OýJ^7!“·‚Ü
+L'ÔôÉê çe“`Ý ˜ôy^Ïxˆ(S+ýy?ó›ˆ^ó ·Ê.9e/•ÝÜÅó°h÷<ÈYiøöŸT<À\Â&_ó™m‹ }Ð*çb¨vïÓ-ûQˆéÜ\Æ*Ç_#dág ƒ†\ó+Ø͘r–€˜gÞG9«Ý °×%\¢•
+‚5F¦édf³3›½Ø¿g½}/ÎÝû<çdš¸ŽrŸÌ×ë_\îÝ\R·uvŠcÁC0ð5BÖj±y2¶³v,†BÝ%¢Ì\yÕ ÞösWiüä[änÁ¦€I;`׺GMºMšA»M“ <U"–#kž·VÉŽe‚@=›aË$5O?"7O?,«¿žšÖŒ@ÅW†`rº¢¸ýú\ëÜ&i²P.|Lü?»Ô¶Ÿ{ôÎÃ>Ù.×cµ|âØrÕ³†<‡ÎÑíPª±Û0Dùä…U+Ë×`è3ÏÉ à©Å Ù0õù@eI¤™:R~j²Í]øU í*áÿ/^5—óÅÑ“÷cu´ñ? ¦O[Î6»À©‚š-Ri‰U¤Ál™}KXzìÓËö¬Ê^£h¾˜ÛÓsÇ4ÅÊ
+* œ‚ÂŽsÏÊ0§Ëê™ï+Ðì±y¶ù³Ûz )>±ˆ‚ËvɆ]7¾±¬wkê\ʹBN7*=m´ßË›„Sýü1KUµ$u㦦<R3óisÝøÓÚÊáû­jtn(UJ“äy”ìö
+,>^SŠ¿]yÛ×MVש‹Vè‘Ý&ŽÛ¸BWHüD×Ù áÚ%lo!±žÚ?êŒ%t.ÞjÄðð3a‰I% ùiQx[3ãg˜—¤áIJ0ÔäSÍœ­-Î\nˆxŸW˜'>nǶ–:î½ÞÚ®’[1*¥·C&t¢g™¦Cñ–1Ä)ên~1ÜÎNïh ¿ÀÕÅ°íÑŒRœQ:›k/í‹FVÐnSÿ8„¬\yÉ?GâùÿK¿N„¢¿O!ï¿>ªý—{jËé$Û[·@N³Cp»V¨(²k,½v£cÒ$ƒª¬²ÅrŸq¾Þgà×yçÙÿþ 
+ü:Z‚¿¤—[ [¶JÓ¹@²ô…L›ÞÎì4G Á1”>í]\íäõŠÒ¡ÈÆú¹[¸vøFÊ›ðøYCÈ›rDk=õ¦pb.Ñ©×: ÚÇU³yÃpYí;ª%ÓÎoésWö«yzî¯**sïÅÄ°+Iq!§FÝOiƒÆèÞn]¡Mñت½ƒkUE$£ˆàé³PQ΢øã¡ÅƒÞ÷é2©>º%ƒÎù‘-,¶,oˆùšÓNªà,wŒ}ú²kx5‹_ˆÄ·io:¬QMxm8êÍ"Ù
+G—Òn´Ì7k›taùeDRZÈ)f"r+ˆ˜¤n€DÑAq5²p%–Ë0§›—à§b±f×ÂÃîYØ5ëݸJ³OÊÏÚ§¥‡åÃt?ß±øˆ4`éð=(G3CÓR[Ñ
+AJ¼Ê¦€ßãÛ@x8 ‘ÕrŸ5º¬š3)•USˈ3É ¤ï»KŠ_çõ¾Ÿã¹¤ï‚N·Úë èìË;½éƒ
+©ÁHBó+8 Õ~¿b=Jăô¬1ð"›Žx‘3ÖA’Þ×ÊWš×aÓÈ™žûuоO#öXåD­ÉØ: í×éG±-CïoãúQè&Õµ´b6¸û„ž=ï…å<Dz> Ä¥ ‚g¨Q[%AdWÊBRógÂsг·F®¾ª“ªjNו ŸÖ$ü-¯fV2#Åã9rf涊(ŒÝ¤úvcD6šw UDV7ȯ¥¤u‚ŒÌþ²*^X FŠ¸_nD倸Äv’;îÅ9ôÛ´IW™Ë°£üäs®Ÿ­ªä¾Å‡ÍHÊ6kxª 2G÷wï ÿªgb'þÝønB×;ß]^^T! ¯Â(®eL <~ RQd”Abk9yC!ÜIRÇf§¬Ïe_xCN¬A Ùñ"ù~Mú­ôŠùºŠ?H-d\OÍŸ@ k¥!•uÒЬBjèCdâUÞ8¢ìjË.aƒÇÉDVÂ@¼%­†cz6å~ÈSC>ÂƲfôÛ®Êúljú½/à²È §,Žü?*<ɦ0·ÿÏP™x%™
+qPI·k–{ZUêuŒD³‡¢pן᩻y#ÓÛwÞ–n´ u?–’aÅUô´ÒÚ9ø¬&ص›µðúéÅZå*¦›š»´Ðb
+†ßiÁY d­c{Z¢ß}ÇR4Oñ·ž ‘ý·]ÒË5-sô ™oá—®—ÂòJFÏyã¥!ÑÒkt’é¥S·0‘8™‡QùÔ6Àn_÷²:€ð­Ïã™ÔÚ6‰|U²‰Æó’(`öiénu»ìüEiùÅH²wþbÆy¹©É(©c\ªkâßĺò˜³ÖÇ^­¸rËÃkþd¶Æ¸#GÙônH‚9EÍN«¶]ú­>7RFeGKHÌåÂ.œ7³ Áºü¸¡¶‘‘Žè§·ô‰~ê7ÞAO¹³ ÔP—|©—,¿…Œ é4®àEß·m
+x¯yÐtëaéRÅ+2¼±[–@k3[†Uù“sþ2¾|©ÉîHPÖ =ñ0.ÿº%áÿ}Oi_ 똀?.×yv8Bã†#
+V³ØÎÇl¡çéÃUÐ?î(èTåµ¢÷;û…¹d~´š ˆÕ~,VIÞ:ÐgŽƒÒ*hœ:ŒkÅûAv÷AˆÑ½ ·­ùù}n­¼Ùjr¡Mö…!‘¨¢ ÜEd~¸¬ gû¥¦]ýçüjöÙE8xékZF=J÷S=ÆvE]½‹a¯öÎ
+Òú&åRc¿ÇçÈGål"0,‚ /
+rN‘j$žwµ{H“èåta%¥dŽ¬FX)ñˆ±ámÝÖ¢*Âì—y':jÃÃDíd¤-H7³æWânÝP0àãný°W¥xáR»:mQCƒ^S°hö§l–=ðů&ýcY3ÿdžRó=É#|ò2:¹á³¤Xô-%ø°·ÀëOy¥èE·ÒÎÕGƒAµÛã#ØŒæ6@'oˆyäèD@OJúäý¨Mv’R±O
+æo©ù¹³M™øß;RÉ?“3¨]kþŽaàÁ—r`¶ü5(Æî,ª(«>^Ï^TAÿÑrV@)Ƨ™¼ï–OþŸ¡2ûJûÀâøӼ͜>tÎÌIÛÓd’Æé´M&1™cVQbÜ%nDP‘}ßA(¢I Ê&²(ëYÂ"Êê*;*±§Étþ“áùÞs¾÷ûù~¿×.àj,ò¹.@»<î5ðº?j©q“TtêPX
+®ny›ÐFlböô“O"&ÞHr{ŘØZчŒbœG+€8×x]VÅ\ßÚûˆlN  4÷©TÕM×|ÊPÿHcHþÁ¾k˜ž_k]XZi’ËÞµ‡ÌªùÓm¥%mŸío2 gž¹ùJ@º^ „§
+4b vîn/J=VÙì®mI˜ó‹%§îyqÚ5Ë>ÞÒÛd`ô'l̾ˆUŒÛsÈd‘­9NÊ'¤¥\<FÌÄ„9XðC€IêP£*äí¢›‰¿Œ.«™Á>t1‡cVÎPPƒ{ßD>Ú·3†B6 ¹Úé(µ”Sç´«ÞÛt‚N‡ŠÚàÔO¿òÚ¥´]‡µ GOƒ³âó¨XÙ¦¾N;Hí¥0Ÿw‘Xò–£o·ó;3Kq;®õÙ•Ünµ½¦<À°ˆÞX[‚é6ôSr­™«VmÒôΪŸp[è­©q! š‰kFê|â¶+¾·}O¢šá;fä;ß<±1©%ØШ[ï•ö^, ÕìëÐø¦ëQsûÔlÔ­ŒùÝ™O*¯|äÑ7“*ØOI ìVʈ}vb!·FõÄ6-³ëFdÙò».9±-9€Ô‘H]%•v1à1äÈ%™Ë\Ò‚|Z•ýÞC3æÉ €Ü4hÁÅ*zXÈø&¥5eãUü<Òe€«ø9“§
+êl‡Çù[tž‡¦¥ºáú°´ãj@Ú}-®~ýï³]IÌȳ~î|—Eú#5£¾ÜJN̘¾ÄZï¯eûµ¸fðNå#ö[ˆ>þûO”õ „q³?ådw$ëÅÈ"PÜ›]Íø…¼#;c8¬Ç?éi#¯TžÜ^\Œ9DØ$ ;°ðE›pág’Ï=ôɲƒ8pá!C?H€Ä*ô‡ŒžÜRÍþ®èªÖY“Û`tk MY#¹=©&5&Ö&í*Q÷ÍœÎo
+F6kåãô䶽·ãu¹MbÇ™“Ô[Þ"t­Ãÿã˜m¹"†Þþ“ƒÛ}ç‹_È¿ôÒÚWÿLÊÛ®œ ¿d­“Íy'Yt‰¨)~`˜hÌ
+:Ô§øí?Ä•ˆGÑ•‘¦íÈ£²ÕX°Áž¦7;ýä'ÀŠ.JoÉÅ-oMqrŽiÁ‰ëp ”¡ÿ~ÖhÎû¹äŒW@Ž°Oµè¦‚ƒ2t¨­.ô]÷Kº®çLˆ†¼U_vzª3dÊ€ŸXH­Y ‘ÜÀµ–Ü4d%È@g¬¤ž“ ìó¢ ú¤ ¾D¹‚ªÆS`šVô‰Å9w"o' ¦ŒcÍXPÊ„åø¶S+¶9eD?Ihw*¡ä& –\èÎ<€h)oá;3fÌóœØþ[hêͧ]ál\7^w Ÿœf•[lÆ0 ÊРœÝ”TÞ;ÐN<>1Szsvú@ÑŽ{ù9@G]zèCgÀdKô]GÍ¡¢÷Nl¹§&¡è¹ùG’#º 3™)WcZ‹NêhÑí©1¯.üèÁcëxGÖ‰ï*ûhðËðÿ).ó¯¤×<ŽŸùa:÷´[×›Õ­[NÞLMMMwsCY”EVÙDp´¤,ÍÌA@QqaSÁtDdSqÉqî=Íü#óà9ÏyžÏûõzÚ„Þif‘ežº:X ,0p§+Bá™™MÚŸÄfz&ÑÉ%Ã¥2Ž-¢žÛ:e!ë;‘o¥­Å·ØZï×ÖÃM\B@ÏÅúuM´½YÚoéø´~èÙÕ4UoIkw$è8§ï’Õ$fërþp?úTx°g¢º2Pû¼“øòêT,þpJˆõOòJ‚3ÜòÍ!BìÖ0æéŽãQRvœ|sáùú7râºz®{Ïþt±w¦büðúöb{Ö5ó‡¢{½Ð¯i%ºT”4Ç(2Æ!…?;˜!BCóôü]>}s¸¼>€rÂ'„ô|\ÈÐDtŒc“mÃvIéc
+òkê ´lX`–šãRAþ™ÀáZÉ{JÔ6Bxøâ#ã§âGæØCë`MÔÊ
+ø¸€–²ËP©›CU‘–þªßÖÏÖù ‡
+÷Ò9|ᚬI éY°]üb™ƒý±ÑÔ20›bx”{ŠR|¶ò^ä×4Â=JjæÞ(.É=†NØW‘ÒOŒÍÄ#m#f{¸t´@Ï2+Ý%f§©y[ .E Ô.F$xÇ1à=µ+C­ð'ÇFaó¡¡™r´H/ è Y.5l“ _øféù‡‹ •6bG†M<YcáîqÏ-o[z>Ù® ¤­«ˆòNáÒƒ‹‚·Çkm‚ï>íÔÄÂœZ;ºÖ¿j¾ot«þkv|_¢–;”hÐöhu¼[Mãš[ì* 3ÔÔ,°jŽØÈC-»òè$› ÝWc“–¿–F,uÃl‰IIûJ~Ùž‚‘½5€óO4Áœc¬,׫ ëTPR×úpѺÄ­!jêñ¼êPÒ‚fÁÁB}‰GI+<×RKÎõXȉŽüÚ®¤¥o ábO´|ìÑæ”{:‚Š2¼ÏS0ÿ:ßšq54ÛPâ×sZ16YÂ+¾u<ËA^,7 ÎMÌŠC1Ó9†ˆ±tÿbé,ùÙ>B}¹.æd¯}Å?õÈv 9mWNÌrŽ‘!N)ÙÚ‹|¼ÖSà–7X¿‘Súq¿$Á¿¾ºÐRvõsÙcÇâY`†šëš¦eM‰*žˆ©Ùa§†wü]9í•ésÉÓ§ì:Aö¥ö¢»Îtâñ-Ç
+x„’“uy±³4òÔ܈_DDËXÙWÔüüës¼ëbJêå!Ôsÿ4³Ä0Õ©¨ËpÈéoܲWÍ(UòÀ×U¼ø0c;èæfoѽ ŽQàÕp«6…öAbÖuïtµ‰æÓ’²œ*€·Ò7±[C×z\Ê·D›˜öj³öÐ>{äEEßåÞ˜âBÃ
+95Çf&*h` tôòóUòÔÈ(ÛWÆYz+…›™gf+dü¿³°KƒsÌüÍþÒ‡A-³Ø7Ï*öN3^ï«pÉ{Šê8cgöí)vÆe‡„U¸ÖG~aþTý›ñâ¾î="bµeÓÁ;&Ä>ÂH7´—ý¼ÑÙ£¦í+ëÒl#UOÌ]9·L¹·¶%ÈßÓÔWg Br@Í«Øã½*vžWMËô(q ûJø³à4:Ý.EÆ͵å‡Í
+*îû4<äæ6~{¤6Á!«Mòª‰/£èØí~L´m„–.å¾  g^ùg?ìSóÊ÷U ù6 !I×V|{ºrÅ>€Š´ Ò^Hø•¿²Ÿþeš :žiBøTµ©+]áÚöŒ3M™7 U=“͈³¥wÍû“ ^5« 0Ù‚ô)8¹§^¥KFLiɸ6Æ]Z…s9”$ˆ^”æ'§}]à’×ÄßåÜÙè-‰uÊQÉ›ðÈõ¯¨¤S}w[ÙÝnE$°õîå©–Vt4GÈpŒ#ãW{ÿGq¹ÿ£Ý÷qüñ¸îܛʹa§Ú6fÉ¡œ'Í©ÒRRJ
+‰9ÄœO™SFD¤ÈaE!J,9'äl®]÷îÇ®ûúKîïþ€Ïç‡Ïçý~½žO‚gO^¤S3Üù§¡¦ê»^X`›¤‡NÖÁ\‡ Þ8m÷¡ÜŽUô«ª ŽŸòòÚt}²ÿåB1Å6ÎDÈùÑŽÜ8O‡¢XÏ›2òÖŽ„t
+k¤!(Ñ`“˜ö `÷K]nÒ® ç½Ò㪮 uàøßškŒs±*‹•ÂÔGÚfê›+m½ðRSB>RR‚ÖÅq®rž¿Ã”å4^mÉèÈ£©Üø…ŒÇå/ãrà¿alÈÿ=1Ø>ž±Ø†vĸžÎ¦ZdÔPSGÒ«Œê¿+eí eþ²â¶Çrb¿°QN5¸ÀkÀ.'اrñæ¾^æ^’×ðχÊ,„}2Èï<ŒMÅ@ÌÖ¢.w%ûÿ³!ü0ñh@?¿5wQ< ­ø纺¤§.—r.>ÓuTî_¬(ùï·ÊZû%|w(bL‡mU™Ñgš¬¨ÿYÊøêvRL)ðîRõŸÏ³—ƺûT!vSŠƒh*Ãï¶g¼º3Sö¾4”äUßÜYê$…]jËhßµò©Šòîl–‹ú{ò•»ÑÏ5!n‹™^HXwV¥¹mÜÇñr¢ÇÖPQŒEʆ¯~¡ùhêðu5ÆUS…q^n&¿ØáFÍ4§{éêRÜìv¥‘V);ôt’Ì&Ü6B
+ô|¦’£©ûž®ˆ
+¶‘áV†óü×Õ|1åxº(ÕØ,~¤Æ9Ï“@³ÂxЙ†+'8‰ c¼÷ÕÅdëXqòleÂC%`üRÄ]]}´£Zw°¦…ÿZäÛ&òcOgT³˜ìkîÄûZ:Óüwúȱ@æZS<V»“ÜþÙ.-9Õqˆ&qšûŠuµØ,ºÒ76ü2W}ºXÈK
+à­Ë@ºOv`¶7ûrƒô"4D]êlhIE8Óg’û†,©kIó^“d‡¬Kh¾+"¬ëj3þén/Ýï@‘¹Ð(xa«m”@ûX^×€-¶ž–%?n¢"r‘n¦J€e$?BZ‘ôH.H~²5̉›¥ûŠè!×;³`׆8È›
+nÄ͹Œ«Q\Ž®ÉŠ¹×Hq:çg^
+<ô®Œ >Ws3§ p'*fÄñ±? þ*a¾Ñ4ã·±>€‡
+Q€+
+~¥)Ÿ¨Š>šÅ´ñ’÷Žûc »Šb’^DõÕ7ÀÆV’§¶6åéJÞëà¡ã©ü”ŦT0ðÖ/ÎÔÅ$ë;Ò$ƒ Í@Ææ8§ÙêÛKÍñ6·ÙV°cêÈ¡·Z(ÁÎ[ƒÙѺ¢T çc[q¯45q/L]€§ôÐaGSÙ»Š¢Äá’÷%…¨Gó­øš˜´-e@—»)PuÑOÄsìÌC<9Ÿ+¥­1‚•ehŒ¼g¥zÛ¤™¶ÁÌ
+"µ5øg35};!l­=ƒ~.æ“}°7åìpûWÈć_(Ðãya7—ëŸèë_š’ž* ïþ^ç³,#ôHEU¢Û¶’¿7U[`(ϼ\ä‘Ot¬¨=%Õ‚8_,$ý´Ô´œèŠ»cYˆÓY.áï5aÙ#7c2#h‚ß&x¯õ¦ºŸiy™WúÊ£)n"Б˜3mi¦m¢u¢¤_èªòÏÕ‚4€­Q[ƒYÐU1ÙÓÒŸýÆ*ãDNWÑ7|ÔÖh.r¥;ÓwIDrß–å„Ø'KpÖ±<¤©“
+|’bA‡Tƒo÷W‚ïé{ñ ÉºœÇÛ£˜XÛ 1Ã:Y‘q¡¡#ot|âÅ’€`—’W{òý-Ó¤xó8!ñ‹t2=MÞ »'æ}·†Ï=*J¦CÎÈZíÆÑN9 f/ Ýî>Øì„?Ü@>¶Ï^­
+³Ø«¤€×z`Ó̸IùY5íEA˘He{ùstZðz­%çîöÃ6?þßÛômù÷·‡JŸ/2‹' ŸæüþƃFÜvÉ8¸óÉ.BÇìŽÀ‚ ÝP¿Í¾ÒÀ½qbôîLuB#Õ¯ó›kž
+9UÔ/P3Ž$Ødó82Ö)~¦©L9[¡ÁVq‰€„\óŒœKmUÖ…†”³ÎÄÝlÖUÙÄŒÌåt¨˜“çs$ãVÊ™YVIu’i¬4ËM}<É)ª ×6óÚX×bÒ§ùà{6þó ±õ‡…϶˰o5m`ÿõÞÜP‡p±JÎÙÇÆãÀá¿Ö—Å=û¶×&6ÍÇïzüL‹OÙG<5|.
+Û)羌tŠÙÙ^5u¼ÄÇX&)q.9âšÃÆ](Éi®ybÒÖ,Ðô¹ð©iâU×–Ø¥5°Ý"È6Y
+Ì“¸(›œ‡Ý™áWïŒÒÀ«±áâÚü{²Z¨Ÿ¡óâDÓ@
+T7çì ¢"
+­*jä6Å×ùÄC£ÆodÖžlñS+ñħ[Úà˜À¿°Óò ß(yûJòÌ*luM¡òlUW£æ|x½½=jízï_2ìJAC`ñ§»4F5Ô
+`÷*­Ä ç4þÉæ—šäC&Ë9‰}lè)ù×úŸ¿ºÆ›Å bRÈ(&y[+‚j!joœøÈ''æzfͽ%I+¥ÿ\‘T
+bkŒÞ¦‚ƒš÷¡•= “´í‡½½=n¤×x§;†©^óU!ÂHÒ¦…µ×C*1Î'gUúeԢЭÄ+'ºg‰¹‹Ô‚cSÛ:Á€X>cŸl
+Vû0…ŽaT቞XýŸ:±NG˜¾¼½aýÖŽéºÄ‡*1ùH×RwºÅÁ4Äb÷ <+²D¨:µˆ®æ›ZÑÅ€ªõ—½§/fR£:NÝÞ4.o¡íé…øI²wšñ?§Hø}ƒO=R’ N,müc³€·ˆiGZ~ƒ{‰]î˜kγ#þíšÂƒ÷ä-e–~R¦K&‚,´Ã˦ˆ†^é–rm#M€ìdÆ \tp¥­Ùô“¾úgýÍÈ2­ð4ÐÑ,üc½6Rë¼J<Ø=KÈ é¹H'Э•.ØU}$9¢¡
+0ýö89ϷĪú±#i;]ç‘âzr¹_Ì[ûZyÇð©<yýký­»’Ÿ†…Ô¼o¸c¦€ã& ÿØÈgÇŒ\rh‰Râ•!s‹ͅ!%£4dêÏu×ÞV½ƒ‚Â+BBÔ "ë9ð“5ålSÌó(%Ûc„¬¨YÚ[ûÐPñ€ͪ>R²«ß}“0´"þÞlÅGµ­õ›C˜‡›ÃéQ#Ÿ¨–Þø†~ta³vÇ9‰Ê¨Éåñ5=±ÙÝí²²1Êzñ³ïÑU9¸B+ó)°@/ÒÜs´RŸVŒ?ÒI¹{³‚:¹þ›¾žë˜ëlÜŸá–œ
+ÛhMŠg÷Ô5ÍtORž;Æé%[#DÐr×ë_"ºVLb­kmʲ}©ºdé…\ñʱYAeó³c-£*¢å¡¼J.Ô5Ï­<PwSýZ!Ú»€íŽ5¤¨:J“–¥%¿;&°ù!5¾Ù!ò«ÈÅ Kþf‰^
+½¢ïzua~ß#Ççl Âï˜oOÖŒ°–hÛ‰1³øÿ—é[Òé†?™k末9sjššiª¹N›•5VJ‹»“á‚š²
+(›ì²‹
+.ظd©e¸€.)«¢€ @ ²Éª"Y:×Yþóë|~ßïú<÷Mv¾ƒÝZé*9½"®8kè|zzs|1¹ŒèÛɶQHÛ]yXßø¥$(ÇdîªpÙ;
+äo;rܽÝÚ³Ð{B7„ø›÷íî<µôø?ñ%ÂS`»jb¹s¼æªk¼ü‚•ùÉ&âÇ
+›e­ºa,½ºýw`⟎Ξ½U6*ªaVT¬Š]ÀY<è¶!è} ûÔ?Ëmð. õº—†z½ób‚[Î(²¿Æ¤­õ–Ÿ™cåÿu™_ôCr™I­IDe7Á*–mȸÅΉÖBï4£À;I~¢íŸÃÜÿ‹ž[~><¼§¡Wºä'®ifYx¹ ti¶QZúã
+>ï|»ð!À†ð˶—¨Œ= ö…ÉöôTˆg²þ¡u øâÖëçÿ ¹j—±K§§–„ÏÎÇTŒŠè 1;(CÜ+Ðù~9.÷}{ÅÙÕ~Ø¥
+´£¨¿šEÞ )ñEî)B®q
+}/öN@ooWýj¬ø%¨fT¬ŠÁV½FòüGŸ‚”×0jã|ÑŸ6:ú˹
+6Fà÷vÕäŠÃU'a’tÙg˜M99'±*b&L¬k
+ýÀ§Æå‰à¸Õp¸Î‚Þµ§6ÄÝ.€I‚‹øß_þ­zOC…D—ðù‘ERa\Ǩ‰®t‰ƒº—£–·ôëæà¤ÿú¥ªOŽ6ÉSG[Bþž™‰Û·²[RnÊÒÓ¯ј¡–]k)õÿöµ÷vµuÚ9ì°ž
+ÄÀ ñU6N?XyÝ …üâ›Fƒü
+tnô=©2µ.d¦¬".À¥úÐËáÅÖÿ,©t½¿ür@¿²3¡áÀ÷<|Ê*î9°I¤îy>Ô©6¸UBØÚ0ò¦[†~^¤BãÆVTpüûÁ—tâ÷%×9¸„‘Õ¼_AXGCl«ŸF4„¢ˆ–V5òpN9¡ a¤ÖÙù¬„…H9¸k\pWȧ~©a{†µ½i¼ë!ošðÿx{§?mrZ’f&âÄÅçÛYÔ¤°6­10G*]jøusû(±Æ!ìYÙÄØ
+­fÏBÇD-Ф]ØñÑ!'-JÜÀ@º¸‡  ubj%üËÙ3’4wwGô]ìÀ<Pb2l£ÕÇ©÷¾o¹öÍ’0ó[÷;èíCS=4Ï*÷(¨y;JJá®ó :ƒº”CÓ7_ž7JŸ:\瓃˔­wìBç;Úÿ(.Ó§&³,îššêé{œ±­±UDmÁ¦UE¦š„,„섬o€„[…¡U0ì„,d% „%‘-dÏ›•`@´zzþ¹~z¿¼U·î¹çwÎóä;Çš3br̽?× 8ytç"öŽnèñ¶Ñæ[Aµ„â^£¿"ܳÄ,­´ä[ûp}zXýTV?÷-Šp®IÒ½ýIJ¶_Ío Ä´½Néò@ÖEg|2bfTÕ^–0qÃzzy@A~P‹ë¬<ç[òíÝ7iž9|VÔÀnÔň[zy^uGÕÁö¬¥”DÍ”€º½|{üÉåí·¥—‚ªÆÛþ%ö“ˆé×—‡+Ã3!m7Ù§l½ìàQ“ëü6¿†‰Øi½ g;d´»ŽIFN`‰‡Š,CDï"£(n„ÈA%£Ä¿€ÏÙ»b}^xÙ/o¸Õ3ËâÆ^lè}m¨½¹/c ÃJ&*e¦×'MÌZàMˆõQô®yv]HÃA­ ƒ;J«¿[’4¦éúk3\`'u\ll™ÝäœnË6¿Â\wȨ ßúúb+Ô#;D›©e¥4µ!äÚéyv²Ù#Ýœ¤èÒC:!+ X1jÚ¼ò¶<•¸èÜ’$ïkïb˽ã­.Pj¼ãÑ7 Ýå—
+÷ &Ç«Æåy fWÓ…Ù˜á!ä]¨owÆ wS6þÏíÎΘž†8²0ê’&jõö[Tú¡]ÈŠmö nLS­ŒÕ¦%V8Dàp‚Ó]éè‰S2˜°°
+°íšÂçîL ®ûI…„}?N¸á‘Óò½`ÛG0™ÞéÖüÓˆzbëæõ5Î Òm×<#Ï!k¾b{Y~–·å†”‡‡:2eé¦%ÁÃ
+&"¢bUØ»Ø~uë=¿ð„Ž”5Ñ+`y´Ê%ŽYæcASÌÚ'Z¥’¨¡»-aæãÜ
+Ì-¿—í‘ãs#rej]@ hYUq»þt]
+.6£'Ö|öÒÚrVÚƒ™þ„€3^„»c”Îô]ØŸ‡Zsv>.c ÝÉH5 gÖ?²nEuPcÚ¤`•¼£ÚÝyöýí)RjS&ü ¶à’‹Š«Úçq«Š°¬ glZÅþ2B;ºx¶µµçå×m)|€9¨Ñ¶3Û_] ×n¨5Å5/kçwç¬ÂþŒy¨5cœ#â?"ÃøÇ».n½ÃWì-q‰ÿ"ßþó$¿î«Œ‰Úœ³1±è
+sèöŸ¬ÊùE—”™²ð°y׈8mQ vgÈ׃Ô$ÌôI˜QÚP¨OCÚ_NÊgQ£5å„©Å •6n’S&¸@ª
+. Vǧ—<juymô9Е4ïUˆ3ž—yÿèÇDš·1;P ëÑžž‹‰ë™ eŸqRýh~‰ûµAýga¹æ8x+ˆÈsëR~Ô"Øœ…â&nÇo»Ú‰³°f<çI9·Œù9ˆÈNwcŸƒr¤¼. ˜éõ; ŒÆ-BêáúÓ×¥U
+ô $efw¬°Û3NþÐ/¢eÜ2†sœqoq´ëû¤uˆvñ3|5jf4•\"|Ù-¦”‚'GÀ{g«jõñºZ]ô*ø ÷<| \ÙãÔ%Œ5i„ëSeÊþT]VÏÙgë—Î á©®oÒ&fSÂÄiN™øíG>9ÿtSûÓɦZ[ôJ¨«°h
+Ôr°ÂjØþ8x5ªcÞMùíà\kð¡"2M®J93¸7:Ç®MRonMà/£+Ü–ÃUµ
+u)…{+<Lt}?i‘RÀÀg!¯y}‚\¹5E¿z p=r>«¸IÐZ%ø¤ –˜‘û0a‚Ú3Œ›1¿­è•s×`ÚÖÏþýÔs)¶H¼š!U¢6&úTpîô½c]+€wQ“
+ ^Œ³®ÛÁ¦£ŠzG¢
+$Ôu¯*Ŭwÿ=·óõܹó¾ç÷{Å(bU@k/é7#J~ËÉúèä¡æDÕ=?Z¿ -á®ì¼kÿ>ª!ÖäA× ™±ð9»”}X)¡'Ý‹¨‰%;ÓÝEŽGuñ¿ÂE” qƒ”îxìStÿøù4§¦(¡ã÷¤õŒú”šZŠ
+.ZKpwùpÖñ¶|$½Æ늛8­ŸæÖ ;‚:qWÞ 3Ò¦Úú«–;žÍßÖ¥pn]4ðé nV{PM¸ÔÑj·€œdºà’ÂyfeÜ(¤œîŒÏü"jãuUôòÝEfé–]—^ãS>†ÄŠÓ] ¬í«ËX àdÄ’´‰Rþû{~d’ N)ý´+:Fmp‘VŽ˜xmQ=¹b w 51êÓv!!¶*ø û+ÄÏTÓ™w—r&æÈ3€=ñ1ñ9'­ítfz`pLrJ/êŠë8˜’YÕÁQ-Ô¾ßU°‰É¿û‰ÂnLu…—‰åi:…DÄö`8¢ûõ_Aõp"À|:)!4ϯÞ}K½aŒ¹àŸÂ^HhùM€K@×A-{j¸Õþœ|Õ2‰; îú6½ÊnˆkÙm»‹ôû!À7áU¸a׎
+ÂT²^ÿ¬œ¼5'íoì*˜'×Et|\Ì,£¦×†û¨mcžVP±k«‚ö«
+5²ê³V àžÎ¤Ž×²–Š˜å¬
+jï³;Kù)ª¨Šh?£f¨û`…S˜££QwÖ,êîQ¼ñªåÂÎküÕ˜º÷:b$ݹٗu É GZ³. #ç’€C•Æ4Å9+—Ô °û³´;G61ëÃö#eÒs¶ç×Ô´º”YL˹F† >ÅXl•Ýf¯=g«: ÞfgR/e¬¿íýno‘Q™ÐËh•
+X “Ó¨ü?6måwDõÄÒ°ªëÖ‰›ÛSpñ:£VùWŸm ­0jcjVý/DJ[H1]GQDƒ¿v:ìtCÌ˃,ARrT˨ )‰Å „ k@(™5“°äj_\ËÇxŸã‹Ie;»íÐËëElp^÷Áª¤7fd†õƒÔÐT·û†^¢©új¶íJRK«/3«#zQç®NFØX”uExDu‡W¨÷|S—6gz¿wõ%¬²= §vO5GW‚¹¿Zˆ&FRÖ!np¹¿Äùï¦3Q«!c“ |2qP/Àîh­1›Bšr ‰bF¨#¸D¾½ý{xÆ•”ƃƒRÀ1BJ~cÊ gF•¼Æ´ÛœÐÒªöf%»3ÄëYÊÍÔ*ŒÏ˜äŒÐ<³Âÿwiû-þ*b V¢FJERO¬ «»Jƒ+ôŠ˜iD”²•”2ÿtã×q5³:®æ7Gi¥Ý0ëtkìuÂ!áì©8µ)Ç°,éŸH¹Æ'SÎ!QHM¯t=Å|ç›n»—6‹˜¡y¿ëµ(0'hˆj䤨†Z±P01 ¹Â÷^%®ùóûΞ§¸{KìJíx〃«3¯w–PWQ«RfzcÂÂÄDܦ¤iHˆº†‡÷•ìºýezYa]>”÷Ê¥i‡˜‹X8DÔÄlN9M;LÎû'
+¾ÑÇ'>Åø‰W*9öHø¨QDÊXÅÔ,˜kÒ@­ßú )næàr^1o_…ÿ)e"Õ&-ÜnÄ.b¤ƒ2ÄõëRÆ;ñYrRNfó¡wx,©ã6ù_´~£‚J>³ŽÜÿÒ2Vyyã5¦ìØÏaÿ78ü22+nöo<C\"FH5ðËöûÞ®Mç·æºÊz:ph[Î õ­(*ÿêŸÁß;Z‡\b¶µÈ4xÿ«ÇøëŸÉš¯þ°ïÖ94dyÂÌÆ `ZyÆ"èÉØ!B`‰r;¤¤Ü¬0Ë^ãᚘõ?Ì>]sN6±ÊªKhM9+ÜW°IéȪ
+:f µŽŠbõ`Ê"ëÍ9¤td6²ÊoMÛø9‡¨§
+_õ¼©G,‚.Ä"&—3åØq@ÌßÓQîy¦ÛÊŠkE#“yX1™qHf”qŒÈ²ÎaåO®ümgøðYš´
+ºƒryÖ#d v¨ °*]xTò
+úŽ}BÎ"el¬GÛ³„£:ZõIP9‰Z ¶À‡Ž ÁlÙî<¹
+ü#ìÏáÂúÄTzM=ZJn IwÆÞ½²7ß.Ís›¾ƒ')—sÀ«Ô•±óØÙõÁÞÝ¥¾q Ÿ² ˆÑeJÅæë–ïS?gÚ
+ëÌ9½> úô
+Í =þ‡u3®%]É­Sª³Î~L–q² {Jªa°Ôi—œ6ˆ{¶>rî‡æ-åzDG®Š­ÒbVfãA@Â?ð>͹e¼Œ‹OÊ{dÜ”MÚ—0ñ;âzNsD˨IXh ˆuP¿*Ÿ-‡L\\Âá²N5ïP"‹Ô÷ üUûTÓ?v—èÄ293©%î_éõ¾¤['Ûco“ =e`—8{±€íðYXÊÎ{&^=#¨¥ÿaDO¾¹§!]‹è)•I+¥ò`“ýøè3Ÿ5“o†uäë€åù‡Á±×9ÀVÅuN[ fáP3»ùÐǧ}– |}‡%ŒÝq;à™ö¬™‡G5¤
+×díiƒ²ê[ÿ î⾑ 8Wصý‰Õ`ŸÄŸ Î+":Jó‘[Î/¹¡Ôd™\ž³ ¥ÿS\&\M¥gÿsÚsz<gæœÎ™Û±ÑŠƒQPAvÙIB²Þäæ&$@—v´ÚCGQq’°„ì;Ù BXB²Üì±ïÑ—oðÞû<ÏÿÿûÙåüºB·BCž9jµógòU×L˜gÝç-!«¼!¤–|0µ q¥õ'Ïræq^ÆÈë +1•[o.ìÏ‘«V3j¤7•œ\Á-fdbJn]2šÌ—41["k¤»µ-¿Î7)ÏÖO™%Ô£Uà·HWöç±w?`/‚½lî2€ÚjÚ&&%-&¼Bió¼ \±w pñ2¿#¼¤ô“¼°’Õìy…ù“~¢í*NõáEÜÍS¡å ÅÓ¤}úq@÷¬ÁI‹Œ><‚ÙW⮆”ƒWöWHõ¨ëÉ‹´kúQ3LMÛ¥ì°FJ>TCP“„š2òz—UG«ä1=½) n/mô'tô†˜–ÞúD®GœÞŒyäǸ_^u,#}!•¸kçýÈž—ø?/Kš· 7žÛšé»”·³]1nmÝ_¡×ƒùaS¦‘–¨#0‡­Øû8|#½ÆïÊßÉئ¦b&)mçæÀûášàávFÇ|5³;ã€[B*µÃeÚí”A„?ø$ì¶>#œ¬Ð×Ñ‹ÐHÉ1FÊý˜ŽÙÚø¤C2’r>}¤g{gGnn/«”¸ë¨Õ[ðò©Ÿ™vð!©»jrmÆ=GÍB\H5|=¼D©MjYí97ÿ9(FN·¤“q›»gd·§œR¸Ã)p·„­÷ø«ë¯z¯æ0õi#à&³L²½Hk´Ï ^ÜRÒZÊ;?é’V™ ¸@»œ¨ˆ. TgjͺĬ“ǯsn TªVé- +Ìͺ„´ˆ–XÑo¥
+>fgÙÇ'ÝÈhÉ95Ò úRzN;ªfuÒáäêèÃí·¾·(ª~øWëwI«-ïFX%ï¤"kwÕ¸*ïÛ_Æ–û/g-Œû%'„/º$Œ¤ÆÆõÒḓcðžcÍðÍ°ìä2³!¢á´ÄPÖ9.̯˅Y;B9Ös;£Öýœ¡çclûKÌ·¶§ÔÊ·Hg| ¼:Ú¹÷©ërX©‰hdžV‘AÔ¢@Pë”|W u
+¸=¬"]¬0cZñà‰ÿÉÊ~Å?ó`RN—uAøÜ™ ™`BÁ,$'µìöƒEàu«£mŸý² ÔÁÇ}0³´)b$-‚„ÆäÈHÊÈlÙïÿKÆDoÿÕ3!ËYäüÐ"¹fÿLÅÎ<®2¸Èªßý$l‰é&˜Ûja‡ÿ#£&²Â~p¤fÞ?õÀ¬ÿ¤È‰OÌ;y[㵧
+QÞöxlû³F¯üZ?<Xò‡¼}R\ôLŒgÖ¥ìÐ*£Ñ;‹»–¶Šð)àz!±zg{)øq¨r_Iº•w*žd<¯uèº Žé8mg9’·ˆ ¶jo¡õëÍ™¦sÀ‡êbz^'ê‚]™þwÊ.Dt춸‘Ó™qHyåÀÄ“r@ñ2ã„Y`7o®°šPÛ uˆi¾wøÊ´SÌøoPöø³_ò’‡ûÍ?6v² 1ϼso‰R³«f6l¼'¼à<ÌšEÔS÷ÿÙ/Û§¦®4€[¿lt§³j;íÜiË;¼äÕ$PWÁ
+vÿéÏÁÞÚÓÓ^Þ0Ò=t!o"ö?öºØP_õ)‡Íäï´™–îº?›ïæŒSÍ%û}ÿ8ÕR­’tJùݨaB݆ïAþ'Û©ÌÅ;»|¯²&Øã²Ú…â@;¿¡ î2+ÛÑy:ù­ —+ž¸Æ|ú˜÷ïÕå¼ûà®uÆC]n~©»’}ØRš~ïªI=Ýæ0?ît”¼Ö¼éVêÈ`}AôP]^Ôbåh¨‡÷*ûÉý«tê8¨×¦[„«­ð±œÝÞ²£3m4¨û+ô‹ÝU¶Åž*G
+®˜Ïr°WäàE"ÁWgT _ÆSnU¹¾ï¯rA7}Ó »õ÷´7oÔîÛ5ë)+^ùôü|¿ƒŸh¡2'É# vú|yÄý×P/_ì` A>ŽôÁcÆ®39  .ê?£÷Ÿœì7ÞSÉoŒÔçJŸ1Ä"„âí^Àÿ
+$H6l Ø@"°D`‰À $H6l Ø@"°D`‰À $H6l Ø@"°D`‰À $H6l Ø@"°D`‰À $H6l Ø@"°D`‰À $H6l Ø@"°D`‰À $H6lGX„ðÛ¨¨Ú¤Ãy\rü$*)]UþÎÆ9ž`%’¨¢ø$–בFždhœub à’4N®Äâ³ œÂ¢W#1„e²¤™¤ÁE½§ˆ=X Mß)&ä+_Ç’XµZ©ŽSÈ•2F~É1µF­ˆS©¤
+•Bª’ÊXy8H¥‰Shä{å¥RªÙû|Ò€kJ­V£Q+÷îU‚ åÊ,­V¦ÖJÕêÕ çÞNTÐsog‘äKhÉ1‰‹ÞƒÏ—ä®{ò¦ ç-™8K΃”Ð?%³(ƒ¡³X’æIÚ»z9™
+@Û ÆÊ#¥Az“ˆm‘VË‚$ÊjÁ#¥(ÝIp¼IGØH<¼ Õ9ÿ`
+H‰ÔWénܺ~½ƒú#@Ôs¹“2Š ˆZnf12NÐ -ŠGqÔÈÒ@£qš>}?R³Èã±=Nƒ‹[x,ñ,$ÏòñٟΧ'ñ¼ýTžð ƒgÏ’®,ú¶; ýhxV׫eß¹¡ço_„TO„â33[ ¾/»eÕ6§!#ꙹÓ~ž7Õ<Ì»¢ù‡¢²x>ÞEÕ×%¸ïšÞ½ÍOØ‹Íœ0’=˜œþBÉ/ŒP…éN™pEsS,—ÕÀ¦ŠŽ1Û®šyÕ\ÙöߧáIž(F¡ xû×êm¹¼O„M„fL %8“^<m/W×eÓŸwíe¹\&mÝvËÓ0ù^4á«â
+œ"üPÖuû-´uqù5€ ä,¯ê»½.úr·÷øŒ²™]UõüõêúS ?P-Ü0Ÿy“ï–°³îÝ ëÙÙ5F¦eßc™˜Ðù/yõáoãuÀÈšž|[^Uþ8à­¾X[îÚÅuÑ}uêØ"e¡ŽXHæEy½¨áV爫 O8qÿÆkYlÇËÝ5³óOyS•ßNÃ×mSNˆ»~:Œ„ ¿çíª.»wMÕ‹Ï¢Á ¯ÚyY#`¶úy]øÍ{¢»ßAà¢è®ÊÇÙÖ«Þ‡šÙÌ
+vÌÈà6„I-lΚ͒W£Ì!“WSì›NÚk«KW$\4 ™êöjàmß=ê«Åà‘!nÖç]Õ8›ÁkÏ1³ózÖo]»Zœ5ŸÛàùP_VM¼Ð3QâüXÑõßÚî+>Ïæe±«“¢Z¼xÐäôkÙ_~Ù7ºýq³ïËKjäè<|óé_øp6\Ý /ºâ[Å÷Væqs8†n³shúÏÍÿǵÓò3–½SF³æ¦¬ÛÅÈì ÷¸½óºhŠnë¬ÍÙÜ€Sà w`Ùÿý‹ÈˆÜámÜ>ŠGF¬#&*ú/h'e3_nmŸ»U» cÛKŠº®®ºbñ¥º m·Z~ /Ú¶ÞÚ>ÀßÎ3æy–Ó<"b/]Jv‡f»ÍÚN´þƒÍqîš7Íp&wgZ ìÏ„æ5èüAçÚêšÌÿ—9¦ß¯?µuµ¼Þýhäµ±º¬Ëé÷e_S3ÖÎæŠÞ=Iþ Ìô[šü²úô`ZºM~®š9"tºªúr—‰íõÂaÓpú¥X”~ÉéÖ ô |Ô‘NNÚfÔ¯~ëŠy…VçuS\£Â_­‡B ëCƒhÜ<´óàcð— V±ŒEÌcÓ˜Dy”Ei”D6ŠÑ{M¤A*’‘ˆ8:7ˆÉMfR“kbc´QFa¸a†è\g:Õ‰¶:†¶ÑZ+@¡¹fšj¢r•©T%ʪXEÊ( d#ĹbŠ*"s™ÉT&ÒÊXFÒRK%¥ÀDLRID.2‘ŠDX‹H¡â¥‚ &¨ <çOyÂ-y„‹‚æŠKÀ*Έœ°œe,e ³,f3L3à,&Àg€X„æ4£)M¨¥1¨¡š…PA@£”œd$% ±> ˆ!ØÁÒlðƒ_kM¬uïœ`šŸêÜ@šŸêÜß˵DÃg3ÛÁËIœD‰It¢™ˆ„',¡ÐÎmfS›XkcYcµUVZa¹e–ÂvgqÛ8Ž£áœü‘%IbÐ`§;ƒÞØ=Û}pÃØïá`Âç†øb{DïÐö±µë>dtqP¡Ä .oàCÏòì2ÀED2œ·î$„JïmI¹3r”°·Š‹&âÕ âº »è e&"^g²VÞ*Ž&ù]ÌiÓm…ÝÔÐ#Ëjt¨¬F®¬Š¡¬Ò€ >¾ûòƒ^ßÇfïSë»_ƒÖ¸UGøoÿÅîo[9Þš+Ü|¾Ã¯£LÃâ\ñ'öH„Û!<18_ᯢ.¼9õ÷Ò;~}ḊàVä`ä>%ŒÞtEsUþ9üPÖuû [Ý€9¹éÊHÿ#u˜‚Ñ««&¨b ªYfó„ º1T9j§Põ ª_Œ:˜&Y’§$¥)Ky*R™ªT§&Ò8µi’¦i–æÉhÆ2d"“™Êt6”>HOâq
+F¯¿Ž«ÿb¸#ñt
+î Ýò¯ßú±D_ÖèÏú´E¿NÑ·óˆ ‡3ts‰®®ÑÝ#ty‹nŸ¢ëç1`@ˆ@¡ã4Š # Ð9²8·}„¡Ÿô…þbÐgbk‡ê'‘zŒ‚ƒ£3Ùsò~ùißàCgø y×
+ Ë
+„@‰æbRr,fÌD+12xŒôÚ.s"’å$QÀÆ’JMŒäÑØð1âƒe¢œ(P½…üÌ„ OL>,·‰7ãšÍÌR¼Ã|
+Jš®eNÛÏ}hëâòkø¾ºjʾ/˜îça.þ_ö«e×q܈~ÿÁ›
+‘ƒÿTÖ¢/Ð{葉¦ 5‰@x…i©ìˆw+˜E.SC3]APP^BïõhˆTPäÇ:kØÄ äÊ–×x~Ë3’,AØôpaáê=¶¥Å¥„Ó!5@ú+Ä ùOúÔ¼JFfIÈ.Æà\²Ðéù¦Ç^¶¸yƒÜS#ÿ¸Lß³Pó©Ç.·L ‚S
+‡§Sɽ¿3×ÛœC”¼ëÆùŒ/9†äœL02$z9ïô̦ºÂ}š5íÿÔÙ¼¯h%g&ßÀ¸ÎV0¬p¹?®¼r’¾]Š°+y>ØQãåùj×ð‹µUîr6ütÖç&w:ѸÝDóÞ¤Ówæ½I§õæ½I'uæ½I'zóÞ¤Suæ½IÇz³$«ÄFÓ…,GƒUÙ&7ÿá«x¤£€êAÂu2®×Ắ?Aoîç)Ù5E:S–{
+ñDå­ðÌÏ^WÉàE2^¨Ã› xà bäðÆo±`v£Å®ôØÑO&‡óعˆLØÉŒí°³vx2*‡-÷Øûˆ€O¨G‹ºô¨Ï¶¨W…ºÔ¯FÔ³E]{Ôw„2ã}QsÚGô@2h†Œ¦èкdˆàÐ5ÝÑE Ý”ÑUºë)1ÏÉ­€##œÀ‚3¸À¡ºO„Ê V† `Ú„¡Æy Œ`b#3˜Ù¡˜:aðq`®ƒ#˜œÀè fw`ø
+}
+™…EÊ£™IäR˜H&¥“J(¥¤RZ ±”ZB.Ј Ç„eÂ3ešpMØ&|Æ ç„u»Ü™Œ,èÈBðЀŠBF¡c$%z4D&Z¢+è †‚qÁd–äeoàn¡‰Ê²Šk’Ú'¦M4²|öåz™h :Ü5òÊ?°“`Iló1‡T_NÃpmJN›'Ï»T|LÆk:Þ&äQ‡£›Ä¸‚¶‡ß!ìWhÛî‘hN‘Ï`–¯í#¬5ÜO«ÇÄ|“ŸÍé4óq ¾±ocöõ ÐLfþò$d¸…y¼d×÷až]ˆ¥§5üäñž nÚælöúþ§.¸Î_ÍçÔ1?™Ôƒøt–žÌÏÆ'vê;ó¬8°ygžÃ4?›g•ˆÏpöY±x¨,¯ÉØ]í{J<õõ~WŽüžÂµ¥ ’þc¼p˜Ó_§Ÿ‡§É~ – !*QS)Õ¢¡bdªFKåè¨=d Š@G%iF’¸à „E¤%P^"%FDFЙjÓRq:ªŽèÎ@íLT KŒÄtˆ‘§ ‰$EÊRÍÙN¦»Fû®.F<OûÁ—èw;#Œ·3Â< Ì2ôºÝ‘"ÃiàC)šÚ• <=‡Ág÷Z·/Õï³}«m}Y]Í^^Ï^i¥Êß8GêÜ(“£÷WÜÏ_v#åÙŸ9Çâúùb¯÷ƇÅSʇõ¹,—a5_± ›±ö…sxˆsÀŠØ.¬ðûü4Ñá¯ßÂò–Ö{¼pŽÞ#¸
+ Såj|øTGùˆu¾9 ‚¶¹É 'á.Ý`þÐþ%þ}üñíÏÿüåÛoßüKè¾ÿúÛù§?]þø×?~ùÇ÷o—_ËOW1§¿â¥ü¥û†"²-+4dVlц#°BóÕh¼-7¢Ý*tZÍ.ëÐa»+ ¯¤«:é(ô“tS”N2äºõ’’þ‘îQ:ˆ/«+‹'«#«Ïn\¼x5âc,z-ÝÆ¢d(Vm©a‘&W)%RÊT3‰I”•JX’¸ÄÀd˜™$5inj¨©-Ó“ä'IP’¡¢˜£l0+Æ) T¡Jb• ¦«† +«†"guÌZ=óÖÀÌ¥˜H_– LQx…A(SÄ‚zA*h6È Ú º†¹n‹G&yêfÓºq1÷!ªÇ0üðo@P˜ùË»ðÿ Þ`š}R)Á;°eZ$)Á »"J7²4Òö<…)ÑîÄì`u^'N§>§Æ­7Üloëèp;8ìÆs;7Ɔãà°Ž«lÍÂLÑ®TZ[bY dK«JÛ¦¯5wm2—9Ä­9k…EÝ69Kƒ`ѹ®h]OÁQ¶O¦ˆž-§ҧòç93*⢃ª…Š¦ dMyHCyTì™ì±œ±•˜iEt…“ÑÔmPàwfþ²CýÒÌùÏ;4¯À¼¶ü=̯À¼¶ü?í‚$Ì•sæÅ̺„ßkŽ)yÉqÈÎ^¾0)J>Õ,º|O,FÔsüC}qþ–ä»ÿq^uMIOµ»u›Ÿ?›ÓèØ|Ác‡Mtt»yæfš)³Ìù43ì§fÌÍ<³h¶cÚ:ÓÌSM™k–ɦÌ6fotf›§6Î8eÊÑ9G@²ªN;j-‡ÒžÔ—Ô„YOÜo‡—PŸ§¯·XÛRa{úÆ@ï€{Ð?à D%6bà$â%â&‘ŽRÓUþÍ}ÙìHŽAø ø}YÀ{iˆIQ†/ú5|6|òa±À,{ðl¿?™ÔO•ªJ==X,¬8ôL7KR‘™_´t–Lwéè0=]FU&k™+ÖÛE#:Êߪ¸­œ¢·l*§ÙðDU‘JTk‰UÕQ½I­îàh:—I èì)¾\µ©1S4%•ó¶_»7ïLýªÁ4®ÚÜ`…beGgY­ò;í¯æ pPܤe{T{§|ªîLnýgÿJÛî/ÿTõ 5Ίà±ÂÅMnÿŸ;¥Hk°uåu× ·r¯—êþ¥ÜÕ…Xzz†Ÿ¼¾Ï weã^TÕ‡õuCœ¡AÂ_Ü þø/è¯à¯ÔŸW⟌ö•ô)„ïøÑ~&Õ{Ò| Çg’û@^Ÿ éžXâ-±»'_ M 9ƒ•kòo$ª
+Óõ`ýqš¦yZ0°‘¯æfp¼OÉ!=RÀ8O¬TZófÌ›-SVK¦!›ӌ͉»Õ…5„y·æ°´&±a—Åü]ëyì6Ž¹»<vñ8´¯ôìÕañr²|lŒ=œ}—†§~½ßµG~ÏÁµoÁyú¾:¿áøírŸùðgo8\‘»¶ìð)0LµÈÉVԮʦíêMêÑT2Øì0U‹ª ç
+ 5¦`Š¦d"D;þȦò
+åL£i2ͦE5ñ
+s:ƒÏÚÔ˜‚)š’©`|6•ï^ž=¸A¯Ñ4™Ê>/ª‘¨­´«½]©pJ!óqÅñâ
+à» n·+]“©Ý.¨ÍÆÌ…‘›•‚“e¶lĪ¹M ‚±Koµkš]„S¿(1n r[”ÛÂœ:ˆxÈ!Ï9îp‰tj(ÇPnB]·†º±„º]¦kÜI¤ëÌrJœ›Íx4ÈÕßd_k²±BmËCØ`æÖ{Ë<[Þr»5ÀŒÜgÝãÚ­¬›Ûݹîkß=8¯;³Þó~Ø{ݹù2«~›û^£¡= m#ÿŸ®zSy(½5Í»”þ?ÿÝýðÓ£?ÿqÕ;ö¢{«Þ=ö ?*ì©ü¨šÎ–Çê­‰ï]ŒëÝ>ð>_2`AÌëê&®ï=þÚø·ßqˆõöˆ|Æžá¶1É›…ÐzüH¹7‚-ïrýCxÊ0¹ú¿ÅŸæ¯_þúüöË×ÿê/†_~ýíkùÕŸßþô¯_þ×/_Þ~µ_½ùîGwú[<_à Žè<4^ÐôLŽeöXË#=?×ùª¨9U(rÛ?™ΔNÕžÝåV›Í'†{o½{ GÓ{Æ«oÔB×8ŽG‘{íqvOÈÛÞ÷; ›\5®švšW-E»×Þ®z'ÎU·úbXݱ8d2Ÿ,Ê«¶R(`29?®šLóªEµÛÂò:ÛÕ˜‚"–Ðâ‘ ’œ•žŸ\™… "¥#EÕ°åÕ*÷ÌÞÙa½”‡ÃXÆìÆ€“ ×bçžùdÁGHÄ@HOÊ•0òáÄþ5w¢J lî08Ø„¼B†i$˜‡8j+ñ©»…¹L0™pÖᙘ>0!1ë–äcX”˜úÃêC'îÕâ.²&ÀÔjœKH˜aw ̯ƒ ¶0ÃSl°Y^Êü1Ã4G˜g]È0ÓS â¯5¶¸ÂÖÏ<'Õc“2¾MÂiÔ@ò¨P83ÊiD­õŒ~·ðŠrw‰88’jgCï°ÛºnÅlÞ“lzâÔ®d–¶ïx§°3¥K‹9ÜS•;/³Ùã‹úh^†Á­^s˜éÖ~j”×þl”ã·xNSFùŒÂRÄ4›qX3ƒE/;º@£ô!\m©lßRzRT¨7± …,­ä`H“ÜE/áf%xiµ
+ÔðH„InDu,Ÿ‘Àj-*'­„­´­ì­$®—bºÎHu*½3¾WÚ/ô¯Y@“A\%JX°(A£<ÁñAåÒÏ«ZS 7%ì„U%­É­™Éo£´ä*h^5­wÚ»ßÆíO¹ŽÖsô§£ƒÝúÜÞûæ™ÃžûñjØ7þØó9_‰Hq]Æ]Âœ£†gº¥¨ËZÚ Û$²7¤'*vÂȺïXë‰åÝ° +ðÄ‚íYŸ-k1°î¼”Wñ«‘U£•xÜÅ™*s¥‘Ž$ž”ÍŽ‚Ù‘§©îàEɼ¨1/'R/’^vVt4£¹8™# t$õ$u¥HWR_ò‚-ô¦ÍöZÇLÚ“r!Чԩ¼ DZ ¸êYÛS|KœK¼+Ñ¿ÄÁÄÚ¾ÐHåhebf3 mâÄÒ±ÒÓÚÄÜ2 N,.Ñæ"3d0x¨éx"—£õ-´¿Ù,p2FÑ)¥sB»I§@BPÁ"Ã$¥¦†®©*—!׊a˜m°¶!ÜŽëöÀwháƒÚƒŽP÷Rò 'jèmòŸéåu Û—/ë\òymÜ ÕŠÐÌ£QñBúUÚ ¶­¬@«Rê,D꣊Ÿõ”P]RejNjod-ÎR›xªg¡5,ßÈbnYÜ }hF‡º—úŸ¥°óR8R¡ û%Jk²‰2ç¿4–4ØÈf“¦[‚3”—–·Á3©1¢S;VVúWœPºYŒ^z[(­Îªê•‘”'òÃI.Œ‡I‘91ÔVÅÑeŽCg8]›4û³§!ó-8“ôÊNÈÚüO[iAp„|ÓÎ&™o‹Uµvœ¶tcâˆÉÑ‘ÒcN&Þ?—«oÁ„2Ü7ï(Ö´zš;½çÉö4ÃÞW÷"©~8žºG u§ñ‚Vªq;À¹¢ù•Üë%çbç®ùæÛƒ3Gpì<. Ö þ#êOÊ%ã}zéh|^0H=L¡AH™§¹å,@$T[Æ®õðæ=÷ æj ã è„*ÌعÎ>‚pçaÁüõð•ÞQô-_íJ¸AÒ8É!W3ÜtUBûHBÉÞçdÅcUݼcàdY½ÞöÒjÞ·Eüi;y<3´kªk}ÝM_/ýTdjÎSsLÆBÊ 9€R˲ÌÈL#’IXÏ #-`’Öðñj^æ1"³ô(¬Ìø¼$tUŒ[c–D¬ì˜­"#•Ä©Š1jbxêšÎ8pzL‚î5
+>áÀ[
+º7$
+ý)ûòSîSêË+ñ5J{N`OIoÛY)kœ=@­hŪ’2`9ÝÖóÓU,¸&â¡àŸaS9m+öõûlîâ·_¬:üîs…O+1J)ÖZŠŠí¸oÛ¶Y‰¦­D ˆ†„‚ƒÑo…­ö‡)"mßüÚ¶øVmz¯
+K¨,¡´„ÚŠK¨.}ô[˜1¸gj¬Ù%¡Ï„F:foØÄ ¹e3wlè-W¨>iH'y‚C±6\,Öz¾+íµ¥‚
+˜0€fHiÙ™rkʽ)7§ÜÖí©¡T LñÍ].R“ºE›šÕܪ¦fE‹‚5—¬²j- WY»Ô¢~±hêa³ÌFvWnO4=mŸÓýï„b
+8èxçÚÞNë£Ûð%*¥›ÅðtU\—Æ3rçDgwüê¦Ûí³wÓ_ê gúù–àP5xQ!E8¸G¶àÉÐ6Z.°´% S#* ÔF;@é
+yë’ú¤!iLòQ]"ÞÀœ”à³N’I*I'5IãmRþíù³;êâÖ' Iù:û¨žQ;Òn\Û™2§d2ï'Ï <cwÆm3Ñ535EmLÌœYNܤÎf±ÆÞ‚#¢ho5IYT¸˜¹ÆÍEn®rs™‹ 2dÑ爯p®t1P–¥N­J›J]ŸK]Ñé$íT:—"'×¹1O,ruÆ·p]kf㵆oÂ|F¾ô"uÅ—Üð厦çë¯qMÓŽ×mR÷ùÜ]$/íEo‘¼wg/í‡/wÕ—¥ï9*ah¶ü?Qu‰Ps‘òF ãíè«7Gowÿ¤êŠká.ÕUà:á¡Â5 •tiw]]ts5J4Óéî9†??SamïXK=}-𮫯¸õüw“>ŸV]nÂWSÊ<4¶V«ƒÌ凜?ŸÒ ôUû;ýf|z÷Ûoß=><}Œ/tïŸòK¿¹üêOOoÿþðîò>½„}M»¯âGá¼ÃMü–Ønö4ž’_‹xE-%š7YH%éIMa=šdxÙô¢ñµÉü¢ýE ëuŒ68a\»µŒ›¢ÂÃR^›b´Å¸°Kc,­QMÖs$,tvG^ìÙ}Zò³5ê„ܦ0Æl‹~ZþlŠ³!F˜ |Éà¥DØ5Z;{(GÐËeÖ¢ôÄnäVj u…úI<ƒ´Ä4b›¹ZÎÓrŽš”—<BTLÐ<?ëéYÎN=ÍŽJƒ£çÁ¡Év'gžç†"fDœ‘ŠP­&§]LÎXÆ锥9I[ZÏN¼õ¯Ûêµ(=‘©…t¡ýYJ#CÅÔlg¥˜‘i@–ÃQß@ZÌE1‹èV45.ˆJ”£@ËIØ Âv n’•ê(ÏÀfÔŠnXGé´²ŸÉé“nó _ÞjiAëø˜$oJHâVÍŽÌFv#G û³Ú•º…ú…†…Æ(JOü¬ÅÚ_{ûËŒ­V˜YÛÓä\@%ñý?‘J0XY«93Õ]î<ŽIà‹Í{`ÖÃc£mX ˜“¦ Ç;y©]>R·ùè.Ú‚Ýä 5•éeöˆVö,ÿ,úàŽwÑëSlé`´J1»“bþvŠ¥6È.›¨¬BvY…vËÐA¢Ð‡Öuè~FÚчhECû$´â ÅÜ­&‹že f•vÏ
+*c‹y(0TÌij ô q‡¢&2U¨ç,¤*,dä’ƒ¶ÀÉž;n¿>¸ý/¢ CGÌssvÀf6·af1ûüBè²A–’VvIejˆRÌüþ¼@?¤þÓVH /Ln¸ä¥_Ú‰€;Ö)eã+¢ˆ0úî<î/U׺V÷ñÒtÈ«xÉîá’ ´¤3-½¬Boë¾¼bì¬ÀO¢/'ürÂ/'¼ã„9XgZ-ËÔq¶„,šƒÁrôì÷ž¾fO×ìã–­–ML*ž %Ó‰f.±‘ôKD"‘ÎM&²hF
+G Zô˜Üdˆä6“û  %(ÍTÑ4²I “Xq2£ Ì)c„ÕÄ+UŠÉ˜_’½*®@Qé¼&o6É%µIݤ~Ò@èMQc!?k vYlê•páÉÊ…ÔŽô¡š­¨øÃœÖn½¹ÚÜѹÝÎëÿ÷„Ù'j¸Dðˆ:ÂjxCƒ‰ ®0Âjv'è‚ Àj^ü†~Ï >,w–9ñ#,ì°¤ÃrŽË8,_Ï‹6·Ë+sî ©/ðs±(/ÏË¡æoxäœm¡Îöv°£õ lÔ”¨9šW¼Á/t®uÔ»ÁÎ;þÄ(*[|¶Ö«m±gÛ¶Ô·4¶¾õÌè‚¡5®`]šM$¬l|v8w׎
+[ ÐÈòg°Tˆ—ûZ(_=[YÏN”ÌÁ²«¥_¢çóõyXc’š:ÃÔP‡z’œ¤hP“t¡¦YÉ®äJQzÒ¡~_´yé•áßø)EŸöt¿ Â'ªÜÕÀGOB«°ä•C?ÒÒV&<±Ý)%Ô¨f§ÂÝq Ê^‚š‹-®y>ÓÎ;yÿk£ñF#ÐㄸH…Ú¨Õâ¸ý=–ÇœTt©««¬Ù9~½Çt¼1ñGT˃æ—_Wåno”_ãÖ¹8Âé4<OÂûD[Á G,àÖâJ¦†uJX¨p•õ°ÔÁöñÎã`0¢ᢠ$BàvxÐä
+\?6Àî:ø¦,Áy8³‚m×°ó
+6?Â{DA‹l°ÈŠÙ¡$5r¥BÎŒðÕùÓ"Œ,‚©AH)ÄUèª96”{$[‹Œ³H»ãIpdz€¸kº :ƒÖÈa‰<¸íù< Ä:$©Ä·FŒKĹÀPx„û€¨ëõ‘oü
+Èv‘Æ^wÊU
+ÓƒB¾~ËÿÿøïøÇþÅOEúa?þ‡ÿü=žþõ¿¬—[oWUÅ¿Ê~ãÿt_fßô‰‚$^$Š1¦A
+¦lÒÔ¨ßÞßš}þ…´E}„BÏÙgö\Ö¬YÃÃ?HIø*üøS çëËgbËÛ>ܾ*¼ãÔ¿:¾¼ïÔ1ž/ï»è_Þkÿ7þž<ºº~rñêúâò·—W…ÏœðON//߆žîé>ûâüâúòêìN¡$gÏ/Þ¾>{öúÕõÃð)|ÎßÛIûÆ®Y2‡_P®[™ ],ùÜFH£o´ÀÊI‰Ûd„¢¡Ñ:&C6s Ô+úhuÄ ¾ºq2ÇYëH…¬£ÐÐÍÔéØhŒÅ\Âc·Û—]¾´š¾¢±øʘè¥ÇAvºwÝ\×Í%ÍÁ‰ÊÍ»¹DNŒ >Ù펭ç K”É:À»ºÙÀp-ôcOîËÑL0ùºOD8ËZO<øÎÍ” š ºJ“Oå߇N•BÕ‘ËÚ|þF&RZˆ%Å2BƵ¬@Êè“•Þ”¥ø–ˆ +å-óÛyÌbH‘¾ux‚M''ʹor+¸ˆ#†Xˆ$¸“¦ëÖ¦ÅiZÉ#¢F</9m-Bnm5÷&m؆¨¹¾¸¹Òv&ô;Ý_ñþöi•mÏI1•ØØ6²
+t)]D®<ÞÑDWÈL¦ ºÔ“…iÆì²CéáÖÃË25km,œP v²OW¸šO I\<Bh²]rjŒûÍ §„¯ý‘88oFí¨nqdÉ%$ƒEZ{ˆìöó^áÊ&ªx±×š,&cH KsˆØ`i
+Gƒ?AMXЦzI³'UêO¦
+^é&t££€ÎÁì$CH²’ZeZYvÝ h”QA ó…XQ;‰hŒSN€.á„ÉXç
+Ö /Bà!<­ÕH4+ø.‚àÊàÄLjÛÌE
+„ÂxôüØ¥tèrÔfŒ2I¶Æc¿Éf¦‰“Üy‘›Z%5à–®j@ ¾Ñ½$$Õ¾|I¹+è ®-ðœ Ò“ŸXT¯N›¶ßÄgÀ^3ðXS2t—ÛPX!í€;’ºB–
+r$.Tµd„»¤~±YàJ(£C„S>pÊH„NA§d ö§l”xL*'ÒFcG $0S
+ lŒÄ ¡Xìx°8‘º ÓÛÈLÏæ(3/£JQë‚89ÁÐ:%15*î !™ý¸Àà˜½P4’z÷ÀŠD¥Fý’M–‘Î)[,¥Ú@¯‘º)zî3ÆÈ8Lb'H
+ nDòi¬~þO‘ÁÌQÀ„˜#éD–៑4 '?ýß";ô¢I²gB0sGçÈŽ±"{ãòôôô~í{òáïáäëËkdîåÕ9(úÔAõ°8yöúåÛ¯^^_]üÉáðàñ£§Ç¥çù›Ë«wëÕ.šÑ×ç—?¿>{ôtžáÈ·×!ªß_KZ§ðâüíü?@ûøÓq¼ç£…ËïßKùO~÷˜ŸøD ™
+tùÔìNêChÆC²Bª&…Bð“V%748u¡Q»Œ´E 1PY0à !ßÔê·A-ÉgŠ‹Ìº+ðÅLÐ4
+T`
+ý Pv¡ifH‘
+l.݃ås¤w‘\b•]>°ü`L‹F¤¡ÓO¦”vïj2»·)§™¨K8ó¦4³Ïtú>@˜4š4bY ‚%
+YÑÝn >?/GFYj ê¥~ì’°?ò÷§˜7…QÉøÐøÔZ£ú»¨.¢BÖZ›á¹h3u2b‹14Œ4‘Óé±Ã‘J»t ¥“ë˜:{543˜!(5ÌKapq>Rtw¦išQéêsÕÎ…d@ h`kªc¶v á‚¥†œ0_ÓŽ4Æ
+l‚3°QæN
+‰\c ¤¦doÌ{˪±dlÓ7í&81`-Ú£ˆÀñŠ¦L›T9ò°h/Hº—¨l¯#ݧÿÓ{¦ÿ¥óÁXIâ*µŒ÷“£G Ûºk¾É¸Æ+‘dsÑ ²ÊÓY"p²ÉWèˆY~ا<LtF빟í~B¼èN*£&¡Ç£7£„¬Mt"igpúÕ`E:©¥$ fÒg‹ñJÆCÑc˜â
+ŸEŸ¸ƒÀZ€-·v3+
+ˆÑB—²ŒÜ&é‚âQ^4ik_¬³Ðz'ËzÑ÷=H„ˆlÙ,É®ÚÒ'€©l•CÅ¥H!WBÖ(êâpwŠjh½ÂÉx¤tV§n–V.dݤ~ú&ªf&½áî
+‹~ݵ"ŠiÔ~T\ÛøüL,¸M¡²ÂíÊ/øÐ¥íjd³0‰•fœÀ¬–PøPs/5ë>×r•uª³÷™O4Ŧ‰¦R±2U5‚vˆÄŒ"'U—(ŸälAÛËYœ[ŸÇþ‡Á<àËš0Æv:ª
+ÀX%TprŽÆ$ò÷óˆMr£rƒZ†}ŽØFLk YgŠ‹5Q C¢ÆËI§ V²Æ}B-$ùF節 Brj÷­{ôq•P6*b"æ¾ÆˆZ«âv3Ž¦ùÉ$$Å¡¤•^v}Iئ¼(´Èí
+ E!S«ŸWâf–JƒdY_MÝÎu&Xš‰_‚Z\ºäÎ `Š"Û#¸ýryKËÒ” L¢Î—‡“²þ7Ýåv-)®DAWÚ‚Zz L¹ßãõ"R@W3_=§@¤ò±w$!± ¦~\Aå…7'Ðëq˜MåqPŒžÇßÿüÒãÇó"¤š¡7»Ü¥¤¬›w(›LÏØ’ƒù“®c®:¢Ý^IF ¨!w»ý«|ßù}rðU?®vœ%éç¿¥îèÇúAR¸ÂOµð †pþôNƺêaÈñߎ3—Ø'ËPbb8æìQìà¸?Pƒèýv6IÈúI
+ Ìk¸9Z¡cwoÕ~$ë/Z@Æ—ztµ'ŽÕ•Ko:®šc pr¡þ£R¹õ6rÜëÒ¶ÿu‘
+Ýc±DÛi¨»«:moaËdøkM€q<Œ¬`קyøÕY\qÇøáËrðu˜§Ñ—ä|ç§QÁ黂xiÔËÚènª‡»;jß>è[E5œ‰ï98Ë<»Hš1z^ÃBÚå¶æ«j6ºeéíÇ£»‘ü&ŠËÙûIïˆ0V/èVíä•^LÚ«šSãG†lœ´ÁŸ(ƒ‚%Tò|"Êÿ#††bˆð“îw˸é ô®m~ ÐŠz®¨±n²·ìç3vÓ.Øbœ?Òs¨8èÌç&Õo±‘}1]G`|é­¹3]$ØÝ(´,Ô{ÛK¾ØññÃ7q>~<9•e†%lWuf(ÕI¶êNì^$‚Í¢ý`°¡W‘¡s^Æt¶jÙý¿PüüÛÉíN)%EBÉõ>þ’¾y+ "éìºÊ÷~`
+šja ø…W…|üÙh¿¤Q¥-ÜÌQãßÇ 9…ŽçeÖ Õo-‰ôA:tÌ‚ô„¥–¥5fâSå̃˃‘»—¥ªUôpô&!Ú{{̺´0cøÓ.fg”õÙ=q/jMî†íMc¬ò6)šúÑ,4laPN(Ž¥{‡sÓŒ¬˜Ä]çL <= aØsW[Œ.‘ˆºHè!ìL²BÎ×¹üš"ã9*«Hï;ôÅÙÀgð.FK§Ø÷Pe0-¥Ñ*‹½sÚ4»‘µ K™ƒñ‹Ç—ît³ÛÌ.‚à/·
+€ƒ[€Ê‚æH¢
+£<¡ 7º˜›
+ÌÈÏ\Ýõ|™~x|¹H5m½ËEÏ€*OäDÇ Þ3A³S<ö$S¹ -ã/+æ 0Úÿü/¨ìV >óÙqm—?þbÀ÷Šú!lÉÑÓí¥3¼REâ ‡%n?:ãÞa,˪ÅEo˜ŒGsb@q±Næþ¥·}¢‚#D›š5øçœìïÑÈ͈á?n”øâŸÇt!-üƒ onlùeHIÚãÜ¿m×þ»¿j‰ß)ðkmáõb–ê¥%¬c„PÒF;N~uùå._ó¼„Ûæ‹äáôè6]Ži£tí©}´
+!Nn:¸]=Þã—ÆãCL¶Ùݼ*͈ØI[f²CgqôÅ@Lû懆dÉ™eß·º4%f`$,Të“„~ä©ËWð儸5Oí:(¹HPü0™Yw…—Š†Sw œ±b¸9¯cýµ†“èãš}]ÓcšCâvmuw+»kˆãQì"žP9|¢¥rÄU©Ý<GÎBˆ“n¤eS9*„ßQ8þÞégHB° %U’ÝŽØ'ÿ0k1³H|É
+Vj·øÏœñ“Ýõü]_ì
+ï ¤å’Çbñ26³*Æ¡H]”ãA‚<>DYQ@ˆ ÞÙF (B”A(N„ºÌ& ‚>¢©âÉ|$˜¥x°7baØùÀpJ k±w /Dó6¦…K\€À¹Imö9=1–œÓz›rN=24Hƒ@2û -ª‡2J{Щžß>@”ÚÁ’Á5ÓƱUF¶ȇ¨n2¦fÍ&€€ÛÀf¹E$L3•Ù•<àH°Ñ–›:ã.KÃ%®„¡:v.%º#íG3¸Sì±Q­+A–+—mÁüE(X䑱éBÞ%4šǤ(OíIê"! ™IËhz9©ª~€)[¯R ÐlA<¢úxà CÊ"{·KYàh§pÐ4 ÎÄ«ä÷›Þêü±Ôy²±äÍqÜŒF&»5X«~²œÀH¤ó"Þ×%¡íÜ£ò«µ¦–»¾¿Eõ—6ûºqoê OÎàÀ)iÙ fín†Ò„@B±Åù ›ÓƈpÒqˆÓñ¶ºÄ‘öj ’G;Î<‚S$‚Ý(: }®õÔm0r%5‰ºK¥æõ ŠqR™bœöQLiq»ã²Y~yBB¨˜¦¸ËJØã©û…-D,dÏQîô6L†H ŒüNvrF5ÝþЩ°#[´S·zÌ E>ÉìÎØã¥÷cpPÖ^Z´1gÂÅ#çoz>õHŒd¬ï7|g¸™<’«.vºµ¹¸¹E¾ •êWeú« ÑEì+ÛKSšóÚS4²§Ýûq°þ”gû±àoŽGÉÆë0Ä‘\v!ée¤° <]`Ú½>§Õøø.™ d«÷éÞ?E ÑÿE´C†¾ow¯Zž²2‚U½Š¶åÿ'’ø©xÝVÑÎ,Cße TcI ÆS*ñՕȧÎRáhE,¢Ôô&×¼ñÑÛ6Çãy*>[öÂ_·ñîq]÷¯[K{Ðhä[–­œ=Úe]ÆèÖÀ¿³ òî|c²SÙ↳xwPЦʈ½_Ÿæ‹kHòaC5ßÞ Á/´ªc¾X?“Í ¤"Üûc¸¬ýËxÙãLAô*{‚•ÿ=ι1D¤œŸ÷Úó­ÄÌ AÀzl·»ªº
+Ç‘ÊÌýÙ†0óÞ-sÀ ƒ{µ3c
+¦ò1@–¦/µ´…ô<û'¿Ê m¤\|Ø0}`[®®×ørp¶Àl*L&”yöC'Ìã€Õ¾Bº¯>rî{”óÊFë@xr7®qos©x£',¬ßË°¤£|~4ÞmóŸ¸V&•¡ou.ç»ý`}ïÕ¹GE¸½¨HÎ<
+î_ÖŽ{sWq_…:3;YÅF9|Q.ÅäÂòf}&2²ƒ‚LÙ»¶ý,)a¯¿ïi3À ¿¹¨Ž‡]Íjðm³"´Üsª‘^
+¨½b`(F<"X¬ˆù°ŒEÔsœÎXNÞ€Íw ü&:âÅ®ž›¡3ÉÚ6òêàÍùÔBLY‘G¸Ò™õPp¸å¶?Û40Èì°Ý½‚ÃVÁ‘ €À°âô NôWM‘¬¨íÞ×Ð1‡¸‡ÔÑšK& ê6v‡êе‚³6Î}¡ñ nR#þ
+æU|¹¡ú;Må|
+ï!P}@ÂuªXÖ¹DõðÍ]Nbo.ÞÎ#îÂ1ûvÙ•NÞ…Çkñš#•6ægb²ˆSHçxkÂ/4m$à Þó*{h¦ðΘBö‡*p
+Œ‚õ è·qè(u!ä*8‚ÜÆslEˆPÌÕÒ¼t„súâqc¶jT¸Ác
+ëYQ:JGj‘!ú‚Àƒ5td¤Ø°/ˆlØGï—ÎKÓêðß5çh€Oi*@JÇðµR‹2à=¾)€/:ꌮN/â¼]ÕDÚ˸V{Aâ—;±GÑû‚÷‰lâ=õ‹ü!0ÅIÅ}8‰ÿ¡|I iÝ!QaÝ>qæð‰IIÜ\?G›.n؆Þb¦‡âCÿ„D4''AmaO #~jhKÈQÔ@AÚúh«#ŠÂ؇yiG¥Â$¥˜€5€+¡0iÒ²Â]@µ
+À͇&q½ªUùñø „"„fÙ‘–žÓ9I„CMlny}}.máz8ôk7“ö)R àŽwLP‘­¢2ÌOL\ •Td–"Ä“¨öº¡S!fŠßÁͼSé/ÜXÞN(ßh•q¡Œå%«¹Þ=yg”‚ŠnõüÉßôúÿþŠa¨@ã8KùÕòßñã<>Ô[ª ÷0—ι˜"§‘Âîi¨ŠèäLøW€
+ endstream endobj 208 0 obj <</Filter[/FlateDecode]/Length 3675>>stream
+H‰ì—ßnÛ¸‡Ÿ ïà›´@³þ“x{°¾Šã­Q`uOqîšYl)RK‘ŽÝ§_Y¶c9ÙFô¦(W š(ÎŒÍ3ó›*˜jÅļõzs‘ýz¶þ&H oZo_ Z¯SŒ`ÁˆfR¬_jÿò×ufÒúãU{Äèúe¢VÙoƒý[½çÌhHsK¥È# 1(Èß±×júð
+²ò¼V˜@³°*ê^†a
+º¼2ê[ý79aýêž³y¤³“žQÉ¥úã>b°1JõŠ—´žÜÚyîõÑ8F…„”ª§F$~€%M€Þ˜’ú
+᫋οŒßp¢®¤H5x´§Žî!;¶”.)à”{GŒØû¢³g½Nö{Ißзò­‚`Ÿõ-PðãbÓâY×&,ø‰qUá(r+™Ð­û:~9ÊA¦ÛŠýk;cÔo:²lI¾wزóíIdŠh‰^d Ω¦Ò(
+—<‰>P=‹HõNxªH£®dœÈ´t×ðQÐÝâkÉäWˆÇÚÔßÁô+¾X¾VQ+øˆ\àA.¼ŽÈ9ä¼2I+’DŒžJ÷$Šé('ªSµu|ï œé[ÂÊ̦…â"àK÷•a˜‚rSRT? +Åsj뛬ßHd[j'’ã£Ú30®ÝÇÚ#[ƒWíéçñûÜÑ#év;ÿÁæé= t„NÕ­µû©ñO›Gø&·3wÎtùáîJJ>T
+HË*@,ªj…&Yẙ7bù[É”_ŸIÀ >Kwæ­¦—<‰È©,¦ã¤l ¨çRŠÑ‹—7_ò^†Ì¹ ÊYª$’\ÎÑèÏÚr‚êÖhš÷š6;5MC5šæblÅF#ÀO­ÁÊë´ò\ÊfÝ“«x4Q]Jþ& S@ß¼?å*B5á×’¥èf¹qFFe÷Iþf˜ïÕŸ1kRý},0ñM– ÀÎEç`ü>0#)¼Wð·Añ}ô‘—s@!§šia)ÓÜúã<ðñ¸ÚêÒ™>53<K´fûÓÎщF Ç÷¤­uÓ”\”‰(1=@éUÁ‚βº4X<‘µˆ9&ùˆY^EDàSà@µTh¬§ŽÎ!/±«—B>u¬¬XšpB!¡'$©_OŠIöVËSÚ•:­ÝWëÉc÷àK?áG¾¹ÏBé{C¾8¹&†&ªË$~%¹T„|ø({áð¼TÐCxªƒ,YÈb}-:¹¯šþÉé
+à[É QÆ9ú*6ÆÎÊ/®=×ÃÇ_çÇG>òrNª xÑAÀ4[Xð=88GRà¹(5±áD[\œ³~OV%3ìšj¢¬ätcïoû •Œñ*’;‡áL
+¨–
+õÔÑ9ä%rõRȧŽ•µ£KN(Ä ô„$õëI1ÉÞjyJÛR§µûÚþè~ïK?áG¾¹ÏBé{C¾8¹&†&ªË$~%¹T„|ø({áð¼TÐCxªƒ,YÈb}-:¹¯šþÉé
+<¥&6œ”es‘¬àâœð{²B§¦‚T¥-ênkïœ+M8ÃGN'Ù+h°½ƒs²n®ÀB"ƒJÄÏ2ƒ9Ãô[k÷Áiu½N«ÛϾwZÙÿAöœýdhaQó'ü,³3¯hm!‚År÷LHÇj*¢pÉ“ˆ ‡g|V’~ï° ‡ /éÐÉ9ÜŒ—ÉÙA£2ܪOåæ^3å›2ù‚Êä „11iʈ–²ù¨
+Vñ\Êη'‘ (¢%~\Ø;8§ÚèöX‘$bªžE¬z`Q'2enL‰pý™«H®vŒõÓ…6&_»èx¬Mݨh|Å|­¢`ð¹Àƒ\x‘s<ÈyM$Ì÷JÓQ ßjê×K-w :uRtmýÊ­´Á—.ü¢ÐZKLE!€šÃú2ñ!=Þ9ª=ãÐÚAؼjO?ßçŽ%l¿Ó꣕ öÇõÇ"óµàá\f/?Üݲ%ð[NVw%=¡PŒÁ›~±
+päì P=”FÙÙ†riµÌTÛÆmëƒ_òYA,%âpp5ÜæNxqg"€‰ÒNZ zdð^ÁÃ9RTöxŸ} y9ÇÌ®˜ŠŽ! ¦YY&ùœ£ )ð\”šØp‚Ÿ \ܯWüž¬Ð©™MÝš(«)}c3¤D ö\”p:‘øÁ¯ààœ¬ÛA‡+°È qijÌ`n±Gl­óäãæ ×iõ:«Ñ3ÂÏ/;óŠv%"Xl!qÏ„Áq|¦Ò(
+—<‰ÈѶWÇHï° ©F°`d} 4Ò¡“s¸/“°ƒæd¸UoÊͽfÊ·5dò•ÉAcbÒ”1,eóQºè†ÊÂФp%E6×|®=ñs?5ØUÑ4pðÓÐs´p.ï±|œÍ#ýýŒJ.ñãÑc7÷“Zæ
+³EÌ.‚‡N~K¢çýx[ë§Öµ,±ŽÐ¸|é
+b¹@_DÈ8G_ÅÆØyl™ d‚•MôŬM€è‘Å~YðpÎg£ù…%gw€ëœÉùÈË9kvÏ<Sr4d0ÍÊÒ¹È÷ààMHç¢ÔĆ[,©.ÎÙ¿'«Ô¢ih¢¬ºÆƾ‚Ò@Ð%—t’½‚Û;¸Ÿ¨ûèp:T¢4Ë æØÖº¢`0W
+rÛ†à ú‡^{J›E
+8u½ŒHYl(QH'ÎëKÉv-µ84`’rr³Œ]`‡»;3‹6„ óÑ–÷¤—áŸ-®``ä…Zå¸níâÍZÆ&ÜÈK©f­ÍÂGîH¥tgÊlëøÆ·
+¦s2%²&å&”î—å•zÀwሱ9ÂUKJ^8p_<·ìgØc3a>Úràžô2ü³Å Œ¼ðB«×­]|_®?\i°ÅÉØ„w—×ÌŽ­¿?G)e±½“f[ÿ:¾uÞ]zsÏ ¾Ð¤E"+Ve;8zxö ÞQ-¤®Sv-ªœà:wèÔy
+H‰ìWínÛ:}¿ƒþh€ZÖ·ìæWœÜ]4ÉÅu6ÛÅbб•E•¢’ø>ý’rËi¶µ>\!H"ÓjgæÌeôϘxÔÇsÎH|§¼\F±ø8”b´ÄGʇÁ±òžÄO›ï‹ŒãT~1:a ­”Å^H"ŸáÜPWFŸb¾{:_%ùéÊèµwߣ(Ë¿~à Ìîð¥X<R`î~Ø£Íú@"ŽÔ…Ñ”ãÁh~3;Ï E€F_.>Ë«”gÄã„ƈ­~öÅ›ƒnüè{ÝÒÞýÇõñy½Ùý¡vD&QˆÉ]ÈÁ6ÛkÇtòév"Ÿ>ÜPhÄ?z=‹‹lâ7€….¾bOiû·)}„"ZØÊSpÄvlj‡:Ômp*–\CÓcË‘¬ÀHV°fÖ®œÓŒyø$JB®Â|ëÖ^3$
+$åþ¾'H:†´kT;¸E”•ôè->†Ó,‚w‚ÍöÆ´Ø eiJP<-ÅX”Bm©¤14,>œý&xΊþªåµÒvR£Ab.+ƒa¿]w®r¤¿ þ»Ó„ßÜÊiÛPPóñVÞh÷x}­f %!ñú¸ìÑf}ȧ*¨ £3(ǃÑüfvž¶ˆMN>ÝιЧðdõ^¿b–úM4½ÅWìñ)Íb_ø6¥%Âée0ÅVž‚ëpǦK#\ÀÇQtIIZRBÛ Zofó¦šqyú¡ˆ7ÏØ»X«‘®AÅÙòJ¤ç=†WbѤvdšjC¡-PŠÏþžá؃B/¬jÓ9'Ü ¡(Ó|÷5‰*DpǦÅå–w> qøÝê
+ /é=¸ˆæUé”Qa%±"ú3à Fü,˺¢Eíø*ÐÉâóû/s@˜/¬j‡*®9B8ŽÈ÷ 'eÙ\Ä÷lÐ
+µåo™[$4Á q
+¯Ö­Aí¨æ4c>‰’ÁUÓHo€Oé2¡i©ºÞw“ˆcp2ŒÎp Fó›ÙynØ¢L×´wÐ,y >Áyò´»öô¯‚(Ää.„k¿ÍöÚ1|ºÝvŒ[\ÖþÑë™\,g¿<tñ{|J³Ø¾Mé#XØæõ#¶òUÔ·E›ú8K.¡€è±Õ8V`+X#i Wr h+HâÜ*ŠŸÞÓ
+üÅ¥ÓOýø»O`ÐOýØO¿ì
+†„ü.)Iû9°ås u¸s Z?öc`8£û1ð—N?þâ¡É>¸1°¢ÿ¢Ô¿cNYý Øü 8Ôe
+¬‚ä`çÀug1”„Ä;ž*RîŸá{‚¤CwѨvp‹(+iÓÝ›p«`Ê›
+3:…­+d—†È§§‡Hy§t™Ð”ppmíéàq‚A–
+¨qÊQ Ï·ìjO<0ÄuiÌ=TAíØÔí!,Mº-¼ˆÜ…\|?´º—fµƒ´ÁJ6còpµ
+9‚gäf{z@Û»ÚL˜¦ŠößÔ›#Ê.
+X×
+j†²4%(–X»WQCpþù`¾È·ÖžkC°´õázÖoBľ¥jÚNsWAbþ;ðÁi÷˜ ²òi{Ê•ù·EB̧`ú.t¨HlT˜Ñ
+OäëÇ®©üˆätloOWu×qyÅšjYòòtá­96ÝU][~t'öD¹Ýµ&n4™.OY¯˜šîÚbESuÇaXœ‰mŠ— §%KçÚbÁÐywò~Ä{òÿ† ÅÚD\˜ ŸÀ«iÂuÃR Ãrä{4ǶLå÷%&JÇï±åˆº¸XLWÕ,]DI,ÉËÖX±d[â
+釴â–ÔGU7lX®v\‚®µ®°œT%'Dζ7Z£í^ Ø–Weúð9}–Ó
+W³t")i"ÔŸ~.òqbú熅„‰ÔV0Yrékwc—Ò?,ñ껀ƒ‰¨a½Lq ‘ ¥tâ¶Â«¼»ÖÁ jYjd(Àø#±¯ÚXÜòû‚©ºu/'§R ÉÂè9J±-¯ÐSë9sòÞvgBå¸í†«*,&Õ¯ÖÞåðp^<ì…Ù¯›hþï8ÆŒ²ÿpK7Ku3]ÎìÝôÑèž_¤­ü,«Ê<Mµ“‹pωŒ—]Ò<ú]A·wÞþ7n_Ú˜gÒcΩ%årÌ*–î
+u(yQ@‘ÞWdÄZl
+,ǵqÝ ý¸r— ˜ vås_|iÞ(¥Ãýð‰ÿfˆ¼TÐ4û¢¹@Û^]œîèë˜pÁäÁæ×Ï_p{å-‡\ßMN¯u,Xãäd`ú=é¿ËÓÐû7É¢(ßTÝÒ`˜7©?£ _ýv 6½_
+׸´i»7ÌJ4‡RôÕ9·^C›*©pˆµ§?Y½ÄÓ ©¯¨(>7sŒzrQ †KÙ$–¡äú;ö²¢g&º€>·aõ ÷Û‚y­Ñ`XõXû…ÉL¶O3rº±¾í6aÅQ =¥åü^ôM;ûeÿÏØ’Auú˜Õ=í-nS»)°*”ú'¿”¯¬I 2@rJYì?r~ý‡ÿ 4eÕZ¸¥• ‘'Þ.Xσ䈫•"í§þÙöµ0.Ød—™&Âë¤845’ Ùôw enï72ü­Aµ”X—3§[t¥§Ž)Uë€RˆÛ7-YEÉ°?h:ºÛg¼’…í"[¦~a¿ÀßVå‡,ÿ-Ò‡$`§^«ú 
+À%ÅÊ‚_צ ãpÎ.üBýþÛ/—¹'qûÿøÝyoDÔÊÚº*[S-l9j:åÞU®‘–ÄXÛg;…
+ò[©!†ýªXÌb5(ØO‡z¯õ5s¾Ð…¼ëýø&]®}·²68qô²¥r4{t>¿HQšÌ-̾´dAe TÂÜŠ²m ‡x¢¥QvÅJ†]">Çä£mÀŠ!]ëžëû·7Än¨¾£~rh2ú(#g7ÁAý¼
+¼¬ã×}ˆÁçkMŠÜpÿëPDç9'¹‰¦P)ƸôëÐ}\„bÉûuåP(lI<võ—Ö¥iNü]ɾï‰Ä_ðtÕ‘¾×Ô·î=Ã\Ðøɨð,ÐDÜ[%TM‡zIDÈË*RŠÆ&4ßGëÄ36%¬dÈvP! ÁÏÂ=Ãø¢»nìyývãØÛç<ü+Ã_üÆ54
+¤¥€|ŒþƒïDZiñu¢~  ”»¨ÕФ°.æö–öN ´í ‘Uü’_ž45WWƒ<³o $óÖŒŽ4¥_*dVÍpIã¼Vµð¢ñ¿E_¡³ýªgD‡4oµúRÑU‘åUTYeÔÏ+{;óM RÊòrV½°¼A¯“¹‹ÆÈPîÌC6›YÓ]PÔj¿ÊV¢ÀÜÆJkTx{˜uzvÍO
+Ýs¬iéܘÁ:ÒÝ«VíYe‡Y“ëöb*¯×­1o˜,¯_Ø?×WZŸwQx)ÒÓ {±(êNT´þù-pyŠW6’Ú¯eîö(Tíáéo˜ïlT…A¿/ùa=°ûNQFiÅÊÑ=¤ ò2Ûa(¿É!èUÏ'¢O²“ä]ƒæ!‡/Ù"
+:®eg0]+-CBfG:%á§ÝfŠƒ_ ÄE¯ˆûñ).¯íøýø£mŤo‰WÖ˜žêjÉâÝ"þ#–EÍ‘êÖœ›å@–ô³¢*ÔÑ°fN³ jN3ÈñÀP»/Äùá^mgÞý¾îmåüâÀ9&g§¶‡­Â€½œXѼì³gc•™Z0„¥L¦{Æœ­Ëšó. ïÿoUD6žô ϯˆA_ï¹Ò´ÔoäàÐ=8Üç=^ón»eë7Vüµ¸¾xµz³—>EJFŸä¦cøLËqvfk†ºï¬ç¬MôͯqxÙk}GÅ­;ŸÅ«`Í
+0)¡Mª,ü+F-FæòùRj>H[’uÏ Ø
+ Y£’}!·ìø£x¸jeôáo5R­9K8c$ÿ·Ø¿ ?û×&{Ó/ƒ¸Ïê6Ñg¨)’O-Øk¿¯ŠZ瀤°²Éò‘dz/Wɸi­§#¢úÔðï«jeöéƒ ÄFE¥>b-ñüijø
+yÍ«ðÏí}ÑDý'ŒÑjÈ•¬¬øÓÛ¢vvýlÆ‘§:LMcµØVüRyÏEr¶í5…Ÿíƒ‘Kö²⊗¯U„W‚H1­ˆp‰|ÊÔ™H^ÌÇ…cCPÿ5$ÿ­¯>N·±Põ¹P¶S…•m;)F¤RãR°ô‚]y°é^…F SÁf=~d€Ô8/òÆ‹EkuÊX…B п‘ùK.­#‚|´1[³.} nùØúÛp®$Û
+Nâ;5¯Y
+¯³ˆN™'§„OÃwð_N‘íé#ú·ô³Ê®Ü7l_¿ÙþL\WÕ˵4}«”0•ë ›Øs¨6]6+T-n‹\”oì}96r
+¯’‰V¥ð3d1ÿ-«å_ßþ|ÜOx»ÃõžÆöÈØ{¨Ôæ~5\VÁî§p’¶¢bB­U,Qö03ÃëœÅg´-öŒõŒäΓSí¯áUH™ôáQ¢µÅPÞIâ•>Ë J¯¡r×6ýÝk§Â|ʘšÎQ*–µ}Ò ‹¿9TYb_N@ËÚ[Ù<'Ù¹üë•ß²§#0ЮíƒXi¥&ÎSj{Ÿd¨úýPALû)x…ä=4›J
+$µZ³-#¶Â@­ÏW„úÍ<ýnêj c·‰®šâ‹ÀÞnMzµs³,–ž‡ó!ÖŒŸˆD÷ëÁJé(™ÃKû8ayÛß®]òT²‘q÷ðÚ;,›í]?Í혹§VmU|$%úÒí[šó^U‘)˶ë sµâõŒ¡ú1±ÑɾšBš9ˆ\ÛDBŒ;ðýð2Ö‘ã‚èÜ?\h 8€rHN(@á
+™Y9U¨ÈêæÜ>”l;Æp€QÂr©6™å ùbÁ«ºo´:¤Ñâ Ê­Š¼kÊ™ír{g"Kud™K€r ÊöFb »Û !†…CPƒݹW Õf´õÜbEOè\Ô½ª{13T`óÁêÁkÚ›pß›ÒÆ“Bqp1³T›Ì)ŸàEyžø ¢OÕaOëç¨UŒ†ÃÛì«má šÄ·°'dî'—-,}Æp+»sèe";hj(‡Øáj¨^ÍBÉz4™ª÷ƒ7¨GI¬òR+ò€Ãý
+Õ0ú‰ Õl1©PÖ­®3¾4x¦zK[§ †ªh¯ñé"[Ó^/J‚ó ’h2× ŽE"ÉÈ2›ÇÁHµWÉG¿-‚µ‰Hžªló»‰Þ°ðOÐé [–ª\”ZDÛŠ¤ÃÉÉ›¡<FÇéCsÓWaªÇÃÓð›Ê•Ï¦“BxóÛXñá´/š9™ÞÅäJ†éŒ`ºKÂt#›lvhÁ}3»ÛÓva«V oLfFvšrÂËNîP-˜
+†p0<n‰ø)"i¤\ÛÔ&î†~s„·+rؼ9ܤ@’5ˆ÷Õ¸„³½Ì=0Ò.Z`—Ó¼I™Ïœ"Ïšöýq2vQÝ{ôøt«êÈm"#¶äQek›³a+SBðëwötSy,ì¼Gé,é@×klžàÞMÀ@S¹~ÔëPCDº«8©'Hf„‡láÅí½)øqŸ%z?^û”wz?˜5µ[l)¢3*ë
+ ÃIÌ°“6Né±)ô—¤E¼Y•îèR>(¤7˜F‹n”¦ó¤S]( ™3¿“k*[6×ÜôÁøþMd¯ÛÑp ©P ‡·X¹˜8Œ)¿ÿ˜³ nÜ‚8 ÁJ—·{|ô˜»6óÙ†>Y1h;à(ksHs³Àm ßÎä³õa
+}4GÏæéÙ V>Z‡'gñ$`oV´À=lÌîIM1áD•è“,edzp}¶UÂ1p½J ¹\¢©éÍo—JíœQ®Ù ñ“R7Ñýw­¸,íh²ŒÃjÞ,ˆÞCñ_b„'<QÏaâ-n øÉŒ£À,ÒŸôÑMRêË÷PSˆ©¯ÿèïo€xÀÍèê1ÚÔEØ€áÁœ'ÿ¿0iQ}€cS}N­xú+}¦Á¯À=²‡Õ<¥_vS¹Ôå,NÁb÷ü×ÖMðTD´fÈH’;…§ÐÙDt2dtm$sØ>t‹üS€2ÌO±n•UGÞ“W‰Wmäúô¸'T¢VïEŒ‡zÕ \ÀÉÌÓ-À'ÎÍfQ$
+’Ídç1Ë4iÉÖ"”V"ÔlW*c•ù,icîœBAÝi÷5¯ŠÃZ˱øSTU·ø¨Þ„j2 Zëúé¡è*|räGГ;16çZy$¥%4ˆyL.++íKUrnJ:dìewé4UKœ%Ðxqï¢G\C00Õ'×…Éæõ–MÝ çñ%¸³[’’Dm%G'„
+µBÞt„ðù ¨X±ïö
+?þxi¯¿üúúãwýüM(Ê%wKÇd‡Vv@C[x¯á
+|Œ@÷~˜TOPªhÉ6ñsOÒŠXvÓk‘ å5ë”+0¿ãÙÆFé–¤qê*Äñ½+%Ç}®Ðºð:çéE·°¨¼<ï£x,ìnxºï¯«¯¬@™ä¢17ðiu2ÙýV+âY(Öïû}Q™=µN¹÷¬ˆ,K Æ) AÝ·=f`…˜bq¡+´n|ôô¦[Êþ
+G–mà˜4Tsýb }Þ—é=8B*8äÉ=Ô¦X{Øx­ºÎ?òMp¬vrfêdÍ÷4̾í¼ÖðVÆg5k½{dŸcê¾k­Y'ŸŸ¾u/Z4\ÎŒQÐàáÑþÕ”t-C+Ùd®ýaÃúïuìùùK|‡ñÊÎ^©Ì©w06ÙÓpƒµR¤ÔFn>s›~ô1fI›7ß×]_9úmßi[m&ÒÇUp#ezÁ(L´Çù°Ný­†Û‚€Ûní!´åmÚ´µu-[_8òÕÿ
+H‰ìWmoÇþ÷î‹
+Œs¬´ëXó)jƒ±±³L9ãiH‚ëDÆl3æSEüt_c2æ&p>FNcÛ˜<°­1&v±Í§Lë—]wÑÃå-9»ÅWéÓ}…É
+j ±k#iJVî$zYçk9¥[ãcH
+TkwiªUª³¬çìÓ}bα‘j…«’7Xyš,²HåK¶IGw’]°Ù´¢w›æ#)=ä-ÇzÓµbŒn­¥d '4LA¶Ç \J$δ?# ¨Y(¸]Íä·(žƒr•3EòtOWÖ¯…(þ°ñ |ˆA)QV“Y»cÐȧD>åè IÎ+CCÆþT/:¢S,¹ªb}zV¿þo'×OÏÖÏîfë»ÕòæáSýWþ†¿þÌÉùsR×ß,o_}Z¼YݧÏöz2{·ì(§Ïïï?.î–7ëùmýÝÃÍòíü¬Rõ9þ^ÿ*/óêcyP}þïßá÷“~_‡àå_ ýZ“ª_Ö?ýSÕ·ÂY¼Vœ|P’Š^âÖѸE=R!=î$Ó!ª{™IàÀNJ³ËÚìËWO,ì›—ò•Ú¼Îªb@OÚ0¦fòñ8½Z.oˆÜÛ‡›Û»ùr][}–%F9JåÿämäðÙj[M(„:È3t*?°Ú³>x݆hë׋=Y(½þ8YÖÁ?âz21ŒPûX{ň?Ö¼ Ì‚µ×Ê)§ÙDü.%ø6 ”vº'û¾RPk£”[Žúp¹Ap沇ô˜Üãc‘#1”qBD$Q9ëÉäO˜ù¤¾f~—ùhè>úà¼9¦ý¤—Ä„ä"6‡'yDs3Œö¦¬ÿ'¹4s¿é¾œ9å›Cs¾)Iß|6ôˆ=’É°„ÞgcFÓ¾)y¨¸ý†0Jâ×i¼ÕȵìG›”Rs­u] „‘!3™U‘<uI*’"ä8ÝñAI÷Úa¢ QÙñVÑF5«HGÁÅ¢-¶,[ØFtôôe¢ÇÐpÄz’ž2cåß_v'­†(LÌ‹J*˜!ÚʳIßȾV}_T…–럭‹”Dw‚åòvQ5»_6»Ü͘ŠfÏfÏÖ'Õ·€Ö³j
+Û×±á¼üOÔó~oüegõ$$²kQ r¥Ë®a®ì’z8ìÈ™Vß"›žm‘aâb›ÓÙ$–|ÉùCA £mJ‚@OÙ6©¬ö™+ɱ&r=ô#.†Î&J†ƒ»PDªï #RŸ»ÒP(ÃPô„d‘Ù9¸“‹Ý MqO®° m
+ýE[”aÒÔRT È
+¬¶V`I`è“ë÷ÊÉ&¥½G›±-¼Óu„}ÑC9£ÄÂÀYÅX”‚÷¢]«kqÉ!a$  P#Ádƒ 0E-Xð4ðJi´z!YÁ-¤†í˜Ü¢•z¥ Ú(Š¬W€¶(Âì[BŠ¨„-¨€Ù‡ad#aÓâžDY˜ÌÆù|/!Œ’¹x”ŽêX9›uáÚ( .C),„ cd@ìk—µÊ×(œÂ§1­X™a´à<JÏ×­ÑÒ<`¶×2‹ †l¤è‹o£ øN£]¶Fy éâ)äd3)Ž;Ù7«>ŒÃïôÅYýôÕúánù¶>}õîæý|r?_Þeï6
+_F‘IÁø¢ ·ÑhÑ`b‚0#º
+ÐL%3¢ÎâòÈêEÞé\U
+7 vO@„›Bý ÿá¼j{³:Žè/ð¸_"ÙU!;³ïí'£ôCZP+ 
+R!œàd!þ}Ï9³?ÄR9\_ïÝ9sÎõøÄAÆôäaÑö9B¯ÁÛ2b®ÍzQ‰éŠNF(JÎBpsÒ-€V{Öí §À6røiâÑÖ:YàcΘDÌG ¬ä¹h‘dÕzÁ»À8ÉM€Æ-"C5PÌ=˜ÅLUqˆS•[2t‰hr‚};XalÔËĶRƒ mÕ~gUCbkGbyüY)j(ȨIo²œÐ®@xT
+ÆÞ £ä0^8§ádf†LQcÏ (‚¿¹Àf–vd%†ô0ì^ÓP8ŒÝ+Ø•ª~νMX9#’àôK5@Åàm{jW®
+
+‡¬zQñuƒyªm`™íd\
+$Á B¹$ÇõÄ}…3ͪ=Eéš]æˆôÂ$²[aÄ 
+šä®ÞPOlHã…âðcBl&W#2ä³$ôtö*ò nª‰
+›@ïLV ¼T]¤oêGEôðt\9­¥ÎøäUØIak.Ô5à8œ…”pØÆh–ÄÆ%ñp ƒl†ifµQ‡×É·<Û’Z&ÅIFb% v}†eiÖ˜³bjZ64ìFgVa<¤Ø‹´¸ä]}ÆPÃÁÁÚ‚ 䧧ü÷ÕÕ)¡nêĆ¥¤ûË•pä¡"’âÙDz•gv‚L:°È.¾ƒùèB,.žÃþº¦4vbÒ¡r`^
+á§›Ú R–’4sÙ€pà.™¤Æ)Ëyd˜iÚCZ©åùgÛåÀJ²Wm`p•1L3Ø(¯›´3† J/êEnbF¢ÇIDár¨QkÚ¾ÉÄ Q‰ö¼Q¬%ý†CÃZö4W NÈ™[´OI㌆I£-B–]ª™F^eª4Ëã Φˆ1I[C’y‰tc×/¢HbŸÉœÑ,k€µØ6Óùò ©‰´ÙBµ”æ–˜õÓG®Á‘òsØ ‹Îñ.üq(ë%Õ€1Q0Öôpx„ž5´¾j2z[\Uèõ
+1
+‰2Ê<
+ì´ M…EP :Dd«ñ™kLÿ̘ŽÔs$täOïh<1ªlѱ”@©ÁúÄTÑÄç9ÍçΑ9Ä^Ñk˜VB) GêrS*Y‰^êÝlM}F6ö˜Çï‡æ/µ-üG‘ÿ
+í ŸÍçœS4âÕM
+8ÜÄ=I÷ë;€ÞUúïÿ1ª?c‹a1 6»-+ì*(ËJ×ÀÐÞM[ bWzIË£¦ù~åQ627Pp’^^ŠtÝâ”{Ÿò~×lcð»$—w°'}1qk)ߌtç•Ïß&§qÈîy€MÚ)ÐàœÓ®¤ÊgTԇÔ»šAPç$ uÂrÀîSÁÍæx3ô¬!5C Â·¡.ÇT ßõß•¹àð2Q¹èƒžïdõȬ–MFY5Lºj?ò¨æ î#v¹a«Pƒ´T
+eýƯiÍS³.Ë*ó@¨Âê¥t×33e„÷ZÛ,ýqUw‘•EÒæÌú2" ÝŸú@Ss£ ÚLâ?ò²sæªx”Ѽk›Ë+{<JÊ=(9e5þNGvÏ4þ|¦. Å£²ç¶ÎHUÙ•¯Ëe~ç³Ô33p[cÌ·‰þRªÿ×ö
+§ÿ¾Ã4¬âµËÿJP&ÀM?³à ´Apƒ1£A´ÎÀñyd £ÏG+= N šd\Ðî඘¦pëïa®-ßå–ƒ)ØÉM™Û”6= f2&‚Mšðk¬1÷qÌÚ”„J.ET™ˆÂƒ˜<õ°e€ðè
+0 î+¡
+¡ÔØÚÛ MJ
+’Ñž‚uøêÔbã W¢7¨ÿ§¯*9ãÑ2+ŸÙ†ô¶gfëÔl³" y—‡!|êí@(®u ”*·ùÆ×ßûçù¤*µ£YF`Ò1[h$´Ú| Û÷Jmg„æÚC‰2S…v¸ç°úù¤%{íNÞpm¾û¤z2ô>¬4ôåÐÌ7|Ú«Y7}t0Kkñpgÿô,—®˜ÁžLkˆr$¥õ„J²Håtס<ZÇÏwTŸ»(\°7Û~“x=¦‘ 8 é
+½]¢ ÊÎn+ò)N{´Ö§†AãW­« Äߎ0ý¼úÓLÆçíê°ôWí9¼Ûd¿ \,OW+h„Ͳ:Ü‚r{¿1É€/×ý×LRˆä]
+iŸf‚Fù¤/‰ën&U.¶õ¼¹m¾3XA_™pÖd4Lu…˜Çgô›1É¢‡"œ4o&Ù!?tsC›•n0ÉË.KZÃÙ£ ¤|I·ÎýئìèC«¨ôàpò“l£>‡{áõ¡}ë/'Ÿds_Á±EÞZÚ°þtÿ«^þ ¥Z JMÃ!•’É~ª‚€zº~꿯Ô~û ÔL”iH¤huÒ€P a0 :g@zV–õŽAëÈ,qô°“ˆq¤Aò¹$ÔËœXƒpYñÍïó¨o<à+WšTl¨’Mpu>ŠDîïPttX­]O(4ûc‰î$ÅÊ鲘s¹üº z5Î'qbio¾!7ÓJÿ¤F¡Úå“@«ýÑts°¿¾˜ >“ÉTí)ýŒ|^Л`4»ë>ƒ0œƒ ÐýõÌ S‘.XÌ…Â/tÓgÇ´rÂQH*æzLMƒh¯¨“ò¤¸¤ˆÑ”Æ ïÝSÌr@¿ž8˜Þ·Uä'Øl†~nl…Ò–=$i¥y§&HzÞ··Yê}¥³Íº‚rÀ<‘'ÄúVý‘ŠV©zã“T®åÊóž¸ò³L*E)z‚¡%'JbˆõðgŸ§M—u™§
+lƒææÅõ˜Ñ1ÄÜ\‚4su«P_Xà¤:wÈ}Ÿ¬4øÉ£BKŽ@”• U°¤Ì°ölVZ'Dô˜Æ#<¨›r—®lŽ”µy#Ô«‚Šåw½•ˆZÙ²´ÚyYëùN2¸¡X™i†«œ\É"n9ùUm…qä[GPZÚK¶²€çêˆ'´Ç&ø0ƒÙÖ¹ÇQ—Ø{‹064pbÛXy”….vý‚ühWãóÕó]Ó
+£ugá|!¹Z¦…Á¥Àº5Œpyh¥Ô,ÊX.
+‚ ¶«¶‹Òõ0À¤;gí'²Ÿ0ãw”šp´¦u£ÖX¤£Eö·|A BHu«ØxŸ@¸šqÙs-‚9•z´w‚pôc,·{VhãZGŠû|ÏùxŠ N±u˜f»ºå´á<ÜÅ”¹åÁ9^‹Fé˜Í^:q6#›)ŦŠÌ=þ{o6œw®wf² ä,éè
+K<äŒbSv‚b-zž'2{­§û†BYlÐËë¢# ²Ã.kb%â¬rç®Ø‚IÌÝu]ú¬r}³×³¤Å–B=±=¸(¤a‚¬Ö¹od˜5Ž†7ecè‹dçnžŽÄk Q¶uV¤{¬R[cWG¨ºÓ»?M+]ç3;'a; ê¾A}ûÈ«)›G…z]1zRë|Ö8¦Þ«3‘”TJzšNÎ
+ƒžU!_UU_ÖPjê
+0¡TQ×Í QP­œvŽµ¡
+Δ68š]Q‹q—g,/ö›!e¾ÄØUæK‰Žv•ùvJ”gm”ö ˜Çädž[¡ôQçôQúÖv–>êˆçÇŽyCî”zBÕj\\]LÐÐ÷ïPÁÒ6vÈ*µÅͧò‚ºr‚Ä£Vñh©v扂$Üæ3HœïºXxÅa°½žÚü÷k¡å~ùdCÁwôšUò´"1ì4´æÙ;
+¯)0„œµJ¡¸ÁØËŽé¦ã/?Òcý¦%˜èsæ¹ÇI®X?‰™}Ñá'ÊMtŒüýôÛ‡¿þþôúí¿?¾}ú÷Ÿß¦“ýø.½ÔÇÛ^ðê#:=Þ÷¢Wúú%ÍüFµ%“œÀE»Æ —î‹ *]ÅWê«–;MAAÎ6ÝY§Ö³6ÙÊTÛ ÝY1ã½.™mÖÆË,y›¡;ËHUͽT˜á¢Os´"Žè[ ,ÕwfAÐÞYzVç¶m*ÈJ !Öš.‰ÐÜ.Ú ûT®èò‚ v—K>+ôå%—4äQ#^Kâ5c õy\æ¼Ö5u®´OF†šÁŒÀvN`AA¯RÒ jIíèIí…Ålu+¹R®ÀbéM‰,24XÏ­âÿºu­p]7Íå’‹§¦Zd¢ÖnÝë¬W Õ‡¥hB#&9©ÈÊûëÌršÜ 2²¶â[ äj°Ó)ε »²PnMZV, „fjFÕ‚]Ó—æ
+y°Á¼Ù»‘\üU9\µ.àÊKä)×r5e;­H½ ˜Ü]y¤r &L¬pÚ¸J`Ò@…ÃLˆ†K£`u㶰åÏ’”Óéj*rªßÃ:e\^›Gµ$÷+F׶M¹L¦4¦,? dÒÖûaæÌu)^>_¶åvÄ-;b{É°!×W¸±/'ƹó%ÈDf&Æ`—sr}»ÍOåÄd|ÖáfÌy5c›a/µ‹ºNë~y%£®GÈi}G³+œ#f똇– ¯£ ÉHêBh¸´@·¦:Ú†þ<²E IÌQÚ3(¨íT'êfWX¤kAÍÛIQ«6¡–Ѷ–6õ±cÞPÐô„¢Ô4ôýQt¶„õA¥Ö#°hÓ·±³
+êÊ |)ZÅ£Q1™óÄ”“¿ì³_+%‰æ–òô šŒ×k¡)¡Þ>ÙPðÝ•¡¢ŽYŽÄ°Ó°kŽ­|¶­ ,~GÖŸ°ãÏLúN¨Ô{¾’ÇÔãvå¼v éÓp­éX6/y›íÉ^ÑUî:¶|Šû$‚ÞÈí0sp¸sÇ!Øfñ"h\}öÞé^S‚”•Ì~¦·7{Ù1Ý~‘ñ'J4=>oåjÒVEìúÙ]Îö¨q×éñỂöã»ôRYÒþÀñ¯>žÓãýw¯y¥¯oBAZaý‚2æ¿*ˆÌlQ²S &õ(‚U¡;(®tù°šÓM³ÔƃeŒáò·A¶3-Ír¬+}V=¬)"ǪÆ¢*êq®Pª\Zçh7T†_ê`©¾³‚öN–s 9ÃFPr·uY <öVƒævÑkQÒW*Ë—•tvXSopµÛÎÞÅ2fÄk ëÒ0uVõŒèΖ ^ËZIci 55ƒÙ€mm²
+*¥n=Ë@9c†zws›Pre±¸tT_âœÿ³_-«–7ô î?œ¡3ð¥^ªÇ8‘MÀžB¡ Á¸oiCÿ¾¥Ò£Tµ÷±»“IüàNö]§^’–¤%ÕÊ£òiÓÏ*©k–¸LÕBÐPóSEÑó‚æÖª‚ǯËS”Í+¸þVn,ôŽ¢î”â”mèDˆ¥X î ¬/ 3‹g.Èi0™÷*ÓÝÉkrÓ&O‹<Ρ/“\ ôa¡&†–² ñÑhì}[‡g«
+ ÿ$…ýºR*S&4¶¹lÄ2;+¶fáGî]¨ÛgÓDd^qPÏÝX/ •£ÂËZ–.zWH/ú)su”¥Hvטäq„F.Ga˜æKí}[‡Pè\ðª•ì^´µ`¬o=É:hš0QOËÅ*ªo¥ïX2hKþ’f<„¡Sÿ¾É13,Õ†!öx6OÒ|”ĨXt¶(⢥ûi¸j²ÎTäM:¤©ÈÅAªÀs€ê2ÅÛ¶¹NU:¯Ð±VmÂ6!ÑÏ*d’Ê«í@oã„ȶUA©}t¿Uö¨—é½›µKÇ*ÍØ$å¾Ô&šûTYÚ/$œØ{J@ÒÙ‰CÖªX+ç;ƒ Iiœ •‘P\u×yKfOm^6Òd˜!~ÈS0 ®t˜ ÍÂ?#@¶9¥FÝÉjŒ –}T\†EZ+AÊ0¨nÝ{¥±t2ÝŒ°Ã®@H}@ç»®«ÜQNcAé¡èȾÀtB˜›ˆô¡HEK!EÛ©åVccI·X¸Ì$®¢-úCRG‘¢>IUZÞ¬V
+JCÁØAâ[ÒøƒÔù²„ä”ôÍ9wY»<­H±(غ†ƒd«Uu·®I×ieHW…œíVS2ëu¨¸Õ†*6@ª)ÖòÚUyy¯ôRÚá¾ò*¾Ø1S ‘¨µ"o‘JAÑöæ% TM®ÊL•OÈQÊÀE=xAµìoD®
+o^âƒÿ¾øë7ÿøçw~øÏßøîßÿúÛð‚¿|û^áññºåƒõêðøóOÞöý(SÄ,gaïM”ÀTù†ÚðC‚ÆPÆ2©á0e%=Ó2z'ÖØHH%"8ù5 0Õ»gX¦èŠúÝ6w˜Ç‘~ק6õ;­—½ÜÓÉë CQ‚Á祑†ÌNh8LÅT'ªâlv²}?öÁóTŒ¡Œ6¦öYÊm)U]Ùø£Ö¾!»tÓÓ–[ûÔc§û{ŽñŒSìOôœÇÔ s^8ùPÙ¼0R
+†ncØKZ ?28¡š»ºµL±M£-ÔåÂÊ[1²óWœ“í̢눘4Ió_ÄÑfCB©µ33V¸­ â,©êÐÉ…TUOb)¨©4¸mñ5+òÆhz ²`%ðy±¤ê³†ìêê7ƒ¼ùF%žÐf–d™oqìñf…øˆLêùŒŸ¨Þù
+s_ËN­Tƒ2 ù¥Âçp„zGÎu{BœPëݱ€Aûh:G–è‡Å5!‚PŠ½æ!ïT{ã†H§It£êAé†>’Y¥ßŠ8B W^ Sd§Ðs
+»'¶ß[êTH‹¶¤sç]žÝ¤tÙM–YºáJ•…,ã¶ä6kft$KØ)¶c:•UâøÀ€xÍ…°º„"áãB(LÆYGI¹[1
+YÐÔšùfyDÍ®ãVØYÝÚ!›Ðï1ÌòÖ‚èGÄê€ÙÉÞ 3”xL Ð^Éc¯·ä¯ÈX„®CL–¨X뉹GîŒ}[f[™ ‚ŽJ†¹Î±Pë0t ·éÕ‡½œ+[²®Þ†X®G $¶ußVÕsºÜ[(,íÜ^‹\žE‰!T“ÜŒùnÆÔÆÝ(à…MhÍ_¤KqÄZàЄ>í’ÝítD“·xÏbÇåšr°‰sn¶…óDËNåç@mD=&^âÞXˬoŒõ™PSöjMÎÜ®d®i„>ïi½Z£O(Á™¤Ÿ¹W¼"ŽHgu¢™–ýy šåñ5PUF̾7ýƘ|õòíË'¤•¾í—1H™‚þ¨ÿòï¸0ÃE%b
+èù¨UÇ‘fдB;Ü#¶7¸'l/ØpÞÿäúç·?óU$_Eìá謦·¸y²nço¢$Àþ%‹æ×»©ÜUÌŸ´&Èrþ—óh~¯åî+뙫ølûããr.ÿ#N ˆ×õjN¹&‘â+ÛÓ|ôSq–ÎoxÍeNc¥’w)Ê#äœî¶œÿKç÷Zn_ºh~Í3ýåq¹G,ý9Ö'½~+Aüôñð—ê?ýt‘‹[¸õ–7gªw\XŽÃŸgEà­¯·—=Ü#¬.-´ÑÇʱEVâlW¥D]àÉfá¥å>ð7›ñvÇ››ëiÁF;{ûÌ å R—s6â8—íq•`D¼¹`«å6öp´• ßž3ȨúØYeA å>Â7›ñvG›ëiÁÆ/{û'„ßl˜?­>üJÈð%ÃD;Àù1˜÷r!Á¯"<Úˆ ÇBi2±]IVVœ€¯9Aßx®&ôÜIžãréFrg`ªAÚXdË(9 aÍõÍênK¼»ãÎÖËnû·R}oR¶cÙÇ•²Ì}0Š2·2u8…ŒC·DÙüq ¾Þl™L½Ü1Ñ»a;y“Ø^Ó–*e{m†¾è@}û¼ÛRnï¸ñÑç ©ßùþÿÁ÷ÏÐz¿gÅ•Ÿ«9Ÿ»ùiÀÏjÀOWõæ&Ÿ*q&Ö}"^ôÉuÛJó[î³â¹$Êõà3Áž¤äÕËÆ»ä¿u‘ê¥[ßÝd«öÿ›¤|š“OXp›5s ú“Œ»è¤›7¹}ËDÖ`—Œ¸¹â ê“Ü»1êGöËe·®ãˆ¢_pÿáL HAîQ?ª_ÉH¦ÃI –¦® &e0,þ}Ö®>|[@ dyŠÝ]ÕU»ví~¸ñ—ºüóö«äüoñÿÙÿý‹ã·¾ùŸõͯ|ù|2óŸªÿã©õÉ¡õÝî³7Ïž_\~qz"ïÇWË0•åÙWç—Ë“ç_Åüòøòòpq~7Èo¯~:<]~ÏÂ8ÚŠ$³QBˆ$4e®ÃJÓôÑRh´áÒP
+˳oÇg__^œ~dç½ÃÇ«³Ó“ë“ã³Óó¿¼8}ûçÃÕtÀ¶Ïß¿?óÕååéÇÃÙËÃŇ“ËWWï¾öâüøû³Ã¿®WÇÇq¿øøÓû‹Ë;ß9ðfŸòå‡Ó·‡ÏUäg7–'O—×Û}ÆÒðæÅùÛéÓ¿íÍç$ä|³<ù+½¿XýÝá)å}ÎÏëŸõÇa÷aþúÝﶰüÈOôŒ°æŠ?ñÇ?1ý¼Øòõò÷„å-èxýôè
+N×½®­×ê$¬m ÓúX­ù«·¬–Á¤,1tÉ(
+¤±¤Å¦5-âj”…
+çóZ¥$¦õ^à¾v†¨ ̵áj"iSž¨I÷4fú æRÉ÷®+ç¡v7¥ÚªÖÔ§!0q–Gá)fA/Åìm÷Fb–i¨¥Àz>KK[Ì2TKËí&ÐO;íH 2¡l"«th÷áúqÑ?Z*n(+æ!.K’I»‰‡~ó½ZdjZGšY¯Un*…ï¢-VÔÈ]jYÙÜ2ÊX
+ýç_}ÄÈŽ¢Ëç˜z¹Ð…¹ÎÐ3 Í÷HB:ýLsµˆ.oY”·â¤ÄPÒw-Mzð-|í„ì¦"Ô·¹'Œì†Ô„3]jXš›Æ‚Pœ‘Q¯ê&Ø1‰e(I¡rI³ZW‘6µâ»ªä6&K¡Å
+'èRV=2²®¶ÀBy8³­MJtÏá!q(GM"+xm3edjˆ$ *t4Š
+æ2F)ÃÝœ™pÖe8Eƒ±@ðª]ö¤qK+8ô–®ýÊ‹š«¨38Þ<ÝDÉ:ƒ’Yλ¦’zVDÚB´]y-`E›æÔÂ`½OÑ{õêÈ67U³â¦>‚LÏOCê÷ð¼5:cOg¶¤B#yjˆ>®HIi„²G¡‡$*Ñ…Cni^bÖ“žaÝ4§Òàc’³’éÐœü¦ehß#ÞŸLNL\zðþl À'í̤ªŸÄAʆó2ØóšB”%Aì"¨[„rr:k9òdÚDþ'çûÌÔ2ØSÓ¨à;´ê]Á}ØŸi,ÃÌL>1àºÆ3¦$Ô> HÆw€tÕŒ*Õ6®`‹ÁõšÔJJ§"28r•7w,ÔcÚÕýX¹óœ¤æ–ÁË%Ö*‰ÑN5äÂl÷=Fµ™é½#P#;4W ²s‰Äi: °[±è[ÐÀ&?’*?
+Ê(…ÕÙx2ŒAØĹ‚
+î"}½ü­ËqAòL½¤#Ò£Ž}Ì÷¥¨¦7%‹Í×”Ñ<4x¶»¡If;OEï7Ž%Õ¾&ºÄ·ÉɺŽ*õ0È!“\©vWßi Ž#ýnÒ ó;¡iõ=4†ôÍ I@âõ¦#/&àg"T€k íùLb^%µé™’Tk4HßFõ Ræ]êµ›¦ÌêÙð7çö²ä}—ÕSi¬w‘v|èC~Ãòü°û I5Ä.U,÷îŽ)αÿ—ŽNŸ¼V2¥(7,–&¢oeh¼Ý3ŸŸ”O’™n!ˆáKèïÁª1à+&˜‹hIó‹p\£ÒAIlälh݇¸G­ÈÉÅ;툂,®vˆ2«_K˜r™/CŠYS‹BìdªzïdU,o’BÌˈÛEéî9!B¨$’ë,½èO:‹ÉÙg‹ L´gQ8U%¡*…9ß%@£RFK#DxY¯Õ8뙫GÛšS_’Jur1m¢
+†Þ†_±že…t…Ë·ä¹Ã÷ÆƬñP»rìOÍet§Þà/vH¸‹2”´üYZÔü9ÍP`›\ýÆ’¦AeEν”²÷4LKá¯Ñ!K¼l%d ‡“jBöXm»ù ¶MÞ °0¦ƒ m4Ok«¹Æ\YŠu‚R[ÌEE QˆsÝhS‰9¯‹ ÆÄÒ”`v oÓ,¨S…s—µºõ¾ú8шö‘·ô}Ñr»»¢XWE£^YG˜þ‡î2ב¬Ê¢èÄ?< ZÜy
+Áî t×ñlyÊ[3Ø
+¢ý2šÛP¦sª§1~òMvÈuùœ®j£Û2Êó\µOÿ¨±VVô™½uaº›­kžÑÙ\²œÀ“‘øØfŽjJaì6ê„9YJvo¼‹ê0Ÿ-™:ü¨ãz#²¨œ’óŽclÓ2\Š¤ut׌ŒØ`D×c£§i,@æQö]º÷ØõÌq®Ç©ÄWY7»–º“ª¦O#{'¡€77o?&IÁ.±l†n#s­ölCcI%¬ÚÃâÈKU£âN9ŒQç´º–qFÅë6çû)=|{äŒmû¦
++R)’\ÑnÚ½9Î2d;((ŽÊ WŒ¥aü™çq@5&Š‘…5ã8yP×
+63+¤úݸ\­#uÓ¼ŒÃ^"|üeª³K2v<e;L“*¤ÂÚ`îS€p(ëN†<Eö]S=p&³Ö„”)Ù¬P…³òLe¸‡n¼§Û©Çëf*S„@¹â2† \ºÉË«ˆ,Õ\Ï×Eî–¬ÁN¤LL™Œ ®ƒÂxÙÊÌ@VÄD¥5²¨£²Ȩ«”ñR <’fämk³nFòÇ:1~@”ô •ÀS„Eôùp‘z™´-—RÑ©5:#9â+!ÖPà×TIï²})E<Å,ÕªN‘âØ‹bÕ£çÄx•`‹«+ÒEíUƒ¦Â€ö[èI«„;TWÕße«‹ƒ@ÓU/çp´,S¹7
+!ã€Ì%*ĺÏYÖYw8Ò3W(9Ó¢µ`iYqj$o®©~)«PÈ©
+±‚µÕö½Èâ;jS
+å DT6n4EPaÙî)ëVÄN h(¤ºÙ€!ï·Ž†ëâ¾*PÚ6×#¢+ÛÂ×P±>ƒ¢T #I…Ó¨t1Z «X©3Ũ;ô µÆÆÍ>P
+†¯%É&*UZ…l€.Ñ’zKˆ7WŠûúâbuû\ÇU.OV3PEVv`ôiUSCÈHšÛå|O Mke¶,ïT
+ ¨ð§€K*AØA‹«Iň‡Ø¡óÕmúàþ0’1Ư{ˆ晕±ö4„@+
+¡Ï%1Q¬©%¶P¶¦L%ß·î9Ñ‹‘ÁgÅ–i—a`×æK–ÒxÚʉˆTž5ªù]}
+Á,q· A\ˆ±d »‰~ÞÁdIÓ0 ®qA…®®ÑiÇ-·ú^ñ¶àêÇJ¡¼ôÖ±”å tmY­„*h·[è¾s….ÃÆ©º—ÒÚ²ÑWuŸù¶<¥š"¡oµøà÷©Ø±\¶pƒvpÅã#X\#ªfÓõ9O¥
+ r i\Ñ•|/‚¿£ê¤ÁW—‘e¾"-¤ó ¶®ŒbJÃW*þœÿ²¿¼¤Áˆç—Ð>Ú±JR½Ø—Ý€;ÍW;C™@Õ/ÀFW9 nó… *fÍG$ –ȲR.7Êuaç„šîRëè:r&˜pUᤪq •í«Š6t‚­®Ç ªEj:/YÏÖwÅj;™>.„“\Ê©F`
+-·w5¶Ñѹ÷FJ­¾ÝºR8Ø-6ÖüN)Ttsòvæ&ͧ:õ‹f XWoܪO¾w§Å§}>tu›_Ĉšß#FB$%^1݈;‰È8Áž‰6´³VØ¡²î®oÙÅ~H”âzÈm9%‹%vC°È]õ¡Kã+¨¨Çw±ÁÓÅ6·8ƒ\DQ¤°…êÏGðs/·G L„Ø…Ò×÷ÐNÍáY÷D7Ìf„‰~gAÇN˜hT ¿Y!Tê<›|hžTkM‘a™äø&ú¬}a?N)JÂÞ©03þSŸè0ø_¨ñ°Ê9®ìÐzê&n¡KG^Ø3¸ÒU£úž=Ž¨qfÒAíxkÑz\líò$èÝ; ¬(ßÞzòFz¥ù^ÑCÐn˜¸t›8uBÓ0ßÀǤ¥Ñ&8Ð] 6]zCŽ ûÕv®è"ÊQý/È´è’pª°™#+ÐF|ƒú;ô£ŠVQ—'*þ¬#ÒÐ9Q{WK›*;ÊŤà§Ï­ ¿ ”r0b4˜­ÈD£ a2*‰L¢(£ØŽèOcP)+VG+/jø<ld¸“ÊøïÁôÞHÊ‚)ˆJRúò°ÖÚÂj¹‡†Äô’}›¸LL?¬¿tCc¢ØƒîRE+Øź¶èè©áóKu!©¥á®J.a¨+äßnð|Rä0–Ò$æmuСY¯¾L²"Ûb=f¨s¨Ì(]R ^eX&k`çq?èÁxg¼V² Õž —Vµ>¬ÛI‹ÚȼØ2ÝFÎ(tæ@4t¿?—a@ûÛdÔ± fØ]ÞãþäÓvî†äWJaí÷¤‰UTæ–•_ ï
+^7ÁðôSj7øI±VRr©Û»ëúVAï2'É°vô]MŸIƒµ›ªjK ²_³ò
+h’PÏ$€ÿ[¤’WXŸPÞ=c\¥‰e {®^Ä;ÞO¡–Å|KñôÖ–…×Y8Ú€YÌF¢w4"=Z“Òñ$Œ- ®¨D-„HvOú&ï‘#KPdh–Å:¬O,Ã6ñZŽ©/øØ/ÒË$ÕZ†¼s¦EN~΃^ºâÉèPtÈìüxàjßвÐÕ¿ Ê€væO9DÅ4û@“3ÖÑ ÅõgY²)<0Ã5O VȧßZó±ˆèȧŅ’d(„‡¹˜ý1û¿xcÖ6*ï2l=³<z¢œƒ
+H‰ìWkSÛº½ ÿA_Îd¦8~)vÚááÑÃá•!=\˜žãÄJâƒcgd
+¿þnI~ÈÁ)&-´.SH¤¥­­­­µ×n_x‘7ô z×h÷œÈx~L(zßhî¸á ALÂÎÆãˆÄ-¤!µSÌ»††ÚÅútÁ¡ï'QL8¤Š3Ÿ·P»ï'/€EäÔ™qdÉ(:ön ÚÉ6hòbnNçûøg4ƒƒ{Þ(öÂÀ¡÷è=jŸ†ñ9…Ô%®p¥†>Jm Ó‡A乤ŶÌ>¶aÞ &¨¹çEsß¹_¤-Vâ{Øÿ=œó¼¡"ñsŸ´ôóå=|ù >ü‹4ÅFw0q‚>Q‘ ã—ç †»tÁY2FP#sˆ›eÛ|@üèC"ãи"ò=Ÿ.ŽˆÑßzIà¿—67VJU:aÇPËç(PXXâ¿|”Ýp6“À-N³;u¼à§YK‚5ÅBÍräïˆìß’àÌuùų-Š-¹ìŠ1 ÜuoÙÚü; ½]4¡Žë‘ F¶ðt«Ë`Âbö»7µ½žä܇Ÿž#:䈵ÑùenXS…«¹á·S_cX~O®ˆg½€F{ÿ+%Ì>Á×6ÚGAx¤;C `Vëb(Ui¹lï€Û·YaZÅ>¶0ˆÑÍËIz7 ÜÄ‹WYºÑbñ¶4‹ú„f9Kâ—ˆÅÂy™¯P.¤²ªè²¿)é’qI-\6]Ö:µr©“DJ’¬êM«ó¥ÛJålQüêóo¢Ðÿ‚šN×j©[•úµÒ}±Òí‘[׎ã7¥uSm·òúgŠÂGŠnå<ýnñö ÿÍ#Tmõ›VÎ*ÎÀŒ4U×™D× ¬¨ªªw;ØîvÔÒÝÂÖÚ)V4:ÉÃÃ=:q¢›uµEĉ§,øyôÍPC¤ÚçÄXŸC4’ègh.q¸´‘ëƒûëŠEÉäjñ°²p„ã(n ¶8„iþÄsöÝÌ
+)í§`ƒ«1V dáJÍõ kS[Ä4Gf1å5ÒxÁîòsæ!3J{§ÊÛ[r<l¾­ª˜9ÎV³ÝMhÉ*Œ™ã0ßG‡‘Pü(ü¶
+”–@Í÷dç<a¸ÚÆŽ!u,~I8‘n:Cê¸8®&9WdeùÎ$ V+1†Hq÷aÖ ,߇ðP:EŽÃåÔäÇÕKOU/%ÎNkæ©Ç6ÖÒ”‘fz_JDŽ5™Ug{ã"MùÿŽEœ?¡Ž*ÇgÀŽðB€™fg7Kîš)Xr×Ì¡yDS,9¤¹ V)¢Fæ‚-ùkä.Ø%³ÝÅ»ãÐÁÙ“6d°•ÞW´ŠW†¥—ͳÝ拈Y¹–€ö† ÇŸ¿C‚ÁQÆéR³ ¿{Hƒ^¯Q6ΨL`<%õ§¬,À ; ^ƒ ÜÜ?iC‚¦ë³Õ›2SƒdúbŽcá-ºð&+‚OZ^¾’mÔ<}ŠJ«dDü|–,~AóËöA|;n˜Ð•–hÁ%ÍÔ¹çMF"W^ñ3€TëµbwáŸù×-Ã,@Ùöc˜]†u˜5ë1Ì*Ã0ƒU8×Y€=Fà2ÂXâ½Y†éK¼7Ê0m‰÷z¦.ñ^[€™Õ›âì¾zÔ›LãâÆ
+Y´]ð좰„‚…+@Y’-H©*W×d©”%%-c‹%¥“R”
+ÿ ­øÀ×t*–ô{¹$Í”g¡Ee‘Ú8 9Ëg2A{ âSVÙæ çh0…÷
+IJw×F|,]õi}o;Ìèà ó @Z#é¦ä>傱6•J9I¯ÛNÅ)È7¦/j"Ÿ(
+>*pÌ:¦ÐEÆÄA,ô¨é˜«ÊËýŒ×ÏbÓ¢¦ba¤¸–žx1XÜU,{D‘¥ " ¤\…©÷ëm°Æd¹ZäJ¥/oßѱ屾ЦŽîÏ‘5 @f‘¥¿PZ-e±ÑÙÇúö=}^ûPF‚~)ø&ò™Ÿˆ±ÕÑa~À-<FŽn¿ŸŽÉ TjÞ¯ËRE.•—î»;c¢\*.ø'é«–£G¨Tþ•Ù„ýèKD¶æîÇs¬g.ô1£ºÃÕ_?Ì몱h[¬ga˜$!4(† ‚S‰șB1Xïä‡ 9kþ"]zqáئc§¼YžÁ!5##¸üÍ…Ô(úú_Ou:Bz›ŽÎ½ñ¶óˆJõ8=
+CŽKÇqɦåbêÁ (Á„ ’ç$7U˜0ÈsSÇw0È€Eæ—ó ”ϧ:‰9–Þ`w²5At+GñˆV©¥aíáòßRû1Ÿ}4<„°-2rlÌù%Úkµùµ`h
+ ÄæÂH
+¤ljÑ9nAo1ı:~3ì~Œ×âRZqðDõ}Ó±‹š‘ gM Ю<ä]j¡ó»ÙšÝKC6?‰4|®PZ×A~µ¯pØ÷R)-Yaš:sh,e+8ËÌ
+ ¨°"añN“2 ôê:eÀ4EµèÙ]t}>ð¸ü°¼>ÈØPÄ£|Te@`:ä,„;†
+àà - []'pÛ¢3ÌÖn—Uïl8\Y*¥ÎÜ ïÖÇU#ºRוŸ÷\R·ó‰0åå?¨ÖÙ]µ‚²K¬…âf‹)4œõŽƒlÙYéßÚõ:pF¼Ô°û<1YêÍ -—{Á.Ûã\^À„d Ù^Â]`0¸µ‘ÒñžK¼qázNùÈ@Dgé«"ÖMa¼+GF6 Ð}hýT-@ ¢Ç_äÃ{3ÃØ/PÙ€+&>õ›«ðVˈTÀ…  Å}OFÈQøöÎÞVÛÛÞÍ€m-'¬1šüà >µˆöEqö€\.”6ˆÖ*ƒf§S)µ0÷†”^]lÜ;¾z±s„>쟷/uët>­MŒçgíçû»;M‚rl³üþõIy£Vúò\zUë~Ú9¯[Ž*·O
+ç•-Q’6òyÖúÖšìç7ëGŸsÖ÷MVgo
+‡Ï¶êGÝç–/tf7&¯ßuëÇ4É‹—j+—Û™<0ÕÕþöäV{«&ÿuj·¾]7¤¿ö•9í2¥3°§{/ËN»%m^5¾é;W϶ZãüÙh¥²M¹:–/ß}ü¤ ›¹Ëd£Q¹ÚuýxÖ¾®×Xn¾×ÚßrÚ»§ÚøÙ–›¬öWXI­ñõ•ÜÐëú‡Ú¸1µ›Sù/q)_·[ªØý^?~µsåé—Yóóä3…_Ûß[­ó¼qPù¶© 6 χHsžmU¿íî©'jéÝns*}9:V¶ŠÛ{·û_÷êÍ÷í&vþ|yy¶1=RU4ã¿ÈÞɸ;õ,‹ùC$[dók|>ÓúÖ«kï“£tÛß¹ÿÔΦÅg[å£Ëëºb¨;ó½çG‡òüÓ "ˇl\T,µ#îÍjb Qm±KH›¼ƒå«b^«‘¿¹¯Îõd±-|^„QŒŠŒ‚(*Ý[ÔXbÁ^£÷vQ@cf¾9s~?<À^{•wu9üüK—SÞ``&mØê[Ð)‚œç]m5Àž_ò=Æ•fåý€ä[Ó^"2võÛôŽ
+ˆ "qÔø%EïdZã¯o|[-br9 Ž0³H'’¡ûA‘é´ˆ(™yêʧâ“ÓÕû
+çËOÓµápsÄÇÉycU™S‘ÏBíN‰ydÄgJûÞPð#^S@tø¤´ç¾ºGÖîØ›#pädß„°ÅŽS¡”‡E O’#ÍkC"Å7ºŸ{ÀcEîá`.:7Ó¼žƒO^0úZ%K!ÍŠT
+#T
+§Iƒ½eÏÏp‡ÏTä«s/=4Å7ӭ˜–é¬\à[š*dé5'2tÀ+gÌi놃°(Ñ_ø)ÁR(£‹è“©—"5xšÂ·odøOÂÌD>¨±± ¢G†Ýƒ
+IxD ?aª'A¢w‹–åݳLåÓæ$"ÚT‘J¦¹"RÄA 3±ÁP)¶š+7à¿$bfIA,!º©ü(}šüêW)æmt' Ï‘ JDŽÔÃ(îæÉš AáiJá\¼ï¨'®ý/ñà†«|‚eñFf œîáH!«¬OÄÌ”œ}¢ƒðÔ–ôß»«ŒÞLŽXèý' Pù Œ_×L«¬Py
+:
+¶ý¬Rb$W?C&Vôý.MÝ]@VFnÇ‘p‡{qvR*Hµª
+*KÌFžÙ§\5,mB: ˜ÖwhìpXâ{3ÞW‡¢”Ÿ;…£4ðškaƨºŒ›
+^Ÿ 7fî£IbN¬ALp/IÃ]_<MTÿVI?cØÛôÕa( „–û|6%—€‹çNæ\ÒtɱF(xwôê¤ò½,eaöW¨r¢¼2ŒÄòµV#]@Ô”NÎÿÌ´;ºé ’ý}ïó¯ˆZ~ö}’¬<$gßZž/þCy•®'ˆ%Ñ'È;»FÜpWP@£¢F¨(²t÷Ìyö)ÓÓó'_êVÝ[uêÔ)J/¼nŠ"Uf `ÆL‚fèyã`„–ÝîÌ0?PäÕa–t·'!SÅÞõ×ú¸ú ˜·€íñdóq
+,ta»V€¢·í?}éIæÝz)5¤î!RÉ6š0_Ž³âôR¨%¥½z­èØùññš1]¾+Ø‹I>ø^xÝí]â~0˜‡–ëDgè?ºÚõHXÛkí
+=ùF€Åé±vèU2?ñÒ÷ÀøÚÏ,¥TLçÒ>jLœ\3,{èúàêÀ–>_6|ôc×¼ ƒ\+ÚóÀæajnBõVÉûN××ÕÔµ}œýÅY謓ĢŸÞw"šÌì·d£â@bä1l†ñ3ŠÏô‹Û"lñk¹ü´8âJ kU0#×Ð6~ð¡©p0”ËhÅ ¨¢ÆŽè%j)‚W÷x©¢zݽx–AðweÕ£3¬2JSD&Öî[D‘øÅ6²/º “ÌÝ™ä¡;2Åedˆ{ÝIV€È»4Ô`úF(Ä:x?
+d¾ûÍEÔº)t#)˜¤Œÿñuê ìOuù øa/Ùž3)G hbF&Ðd•î¨–(ÅMµ ‰7ÕãÙ8ªX‚;©1Å%BæG]DÊ/³Wv`êÌkR²W ÈSÞ‚õÆð °iñÅ [—´ËKA&ÅBÕÓŽØm†Ðš$©KKäîaÌ5¶WÔ
+-Ü
+Þñˆ>+ƒõÖ Û¢%JÇ £½#VJ{órk÷|±£ø)΃Ía“yÔh*7h~Çæ û[੸>øý¸fî°«º£
+ÄT#zí& p3µò¼¹RßÃAø(²eÛkœÚùh*¯ˆÔâ};‰Mï˜/±Qïcç0L‡þüÕ72Š
+Åa¡L­
+‰Y¹Õ‡Í¢–žÅÜš,aîwé
+Þ9VÏq[!DÊÝb<{ø,‹Ùl\_§k%"ûB—Èä¿"T7’‡®‹D¡‡â*Mp5ò«Oùõñ”ßL´ܬ™¶vA0[ΰîøŸÊƒï«ˆ‰V"‰¼(+¤§¢"ëÉl‰Âׯ)Š„ßMWÎÿšÈ eV=™d³Ù oÉÆGCñßÂÉ*HðÊJ@ÞHyÓ]0žwÊJ9™…øÐÐDysÇÃ+{.Wq‚äRá̃
+HüU1§h¼ÀÛŸQÇIœ5 âÊ4=.Ê{I7ž9Å”““SNHKÞ#Q7Ëièìà—„l•?›"/|Ëä™ýCèš’!ª’@hÆJa5^w¬Ò×Ä%¾?ªÃÊ“Ý@ÎÕtrtì;¬nœ}µHÇYî6XÉÉ"ÑBË‹–GVæ‘® o‘ +’i%èt(…þ8Ôeçö!FøËøqè6R¡Þ†ÿw¨Ó©ëšÈ<"+ˆò‡ ©€e„Sª¢‹Æc]̓ËÉü;¶à´ÅdAsèÂz–À,[B6D„DV?ntòW—D©ÃU$á/½9AÚn›Æ
+Jb`š
+TªEQÒa6)€]O+¼×¨ÄBÜ?ìZÞê2–Å¢¶ û¹•íJ
+‚Ø=,ô(Çl~”ñêé4¤d’ÛœQÞ–§VÔ±µsù×Y“àx"Ù§@Ù…?퀗D+KÌð «!Ó¶‚—ŠûÕÍ,°‹”«(ª °—º5ØOž6‚²â%¥Ø†守¬¦ì@“©_ íY:.½æ¤¨rí+‡©—(È6ÑQÇ‘
+vƒ•Þ Ò-­£‚¤Œyô™Ø"Ø·‚ôŸ†JbPêüf/ÜëgÔ¶øtÌž6‹+šcŒ½®â~ì}+‘[ýÅ—Š†YñÀ®ˆ!Ff¹ã\…÷扣ÅëqÐq6gWÛÃÓ°cÙ©®‚ò_îwB…k*m^Œß¬%/³òñ*E©$¶!CW†´s-²éÆW0+Éc,D™cX8«\IpüPŠìï…F*p‚´¤%`“ÇóyâZw9Ë'.]Þô˜_ Aæ1~6ÝuìÉ1P·hÃËÑ5g/yF”6o§w
+ –Æ}Œ£r £?ŒÍ0KV™Tm!<ó «áÇæ̤¼`áô
+ì«FÁÁvÃÛïÅÅ”ÝhÃ5´´AØÒðÁØDI1ò¾!xx¶cb»£Ò(ÿWŒ.OƒêÑP(É:ÈÇ’ä'bäGáô.(Ÿ>ûlp@}ûÙ#a[³¥¤y™¥9–§ŠŽ
+âÊFUT
+X𠀃¨–×?[VfŒ éÿè0kö°wö1¼ò*;Ù$ðM®÷µ9ð+›ŠÒ0°¦dƬª+MD]Có¼ Û=JUÔµGÄj2Zù«-ÃAºþÜè—ãYçÄß<;cT*‘ŽP9Š$“À•çÜN€'c"*M£<ÈàŸí±”<2Ò³ÚÿÝÙ &P·Æ«ðÎé/·b1ç‹2å9ËÜYcWf_©§â’Nøx=ìá”ç|aÿe¸FÚ0+ótp@ÿ0øÚbEŽ)Kpl¦¥5(sÜ€Qž°F!Ü9o»‚ÜgV‚´†±TrxÊ­ìü_D5Z¦•c±y6R~ï«asÜ*¿ŸþâÌ9o˃j«•IÖ%ôÊ®¡br‘•Þ–·äm¨ •¶r\ùD%ò½\ühè?©†»xi(Wj›lc×¼éèÚ†V*T觶D Þ,‘[_ßá!BÅ]žtÇY"¼e¡i±‰¡Cn@„;jD„ìPämaäWé“D5ÐK
+tàáj»DéyQŒW2ñLjœÚó‘E]H¿Çɵi%›s¦êðHR±°,‡ÅîãýS3Íü{´.ŒoÒdLÖÆõÑ°^(V±`9Íë,qw/Tû¯Â¹«9·³n± PHÒB’p‹¼M 47Ì“L]~£fÂÎK®½1•ùÙÜVš’ ÷ÎBÅáUWóRÛEoA¦‘È|ß}Á¯ ®ÕÎI'Ò´3é¡IéY2ךE‘¤3w·íðXhMÒûÔð Ió„_1„&}‰M.*4I“ø†4¹õӾњ4˜„òÔ'ÚSW}–pxn^E®ò•¬Wžî1¤©7/
+ÒÑŒ¬oº“úrBÛ òÞØã|ˆ$m4©!6¼Ô¸8\¨¤°—ç9}‡•<9Û
+mà2«þQüƒ‹ iB¸(¥6YÑI_|> i2¹Ÿ‹&©YÉí\šnù!†ôžN¥ëî’tVZôq¤M‡Ç÷ßMоæ‰)¸Ù2}4i¯(~»÷mièŽËMR˜—óR
+–Æ÷ÏhÒÄhDÖ³dIꪦÝý=õŒ"uxÈútZÇøšºñìøNGJ“ðâ MÚ Ë>ÆŸ©¤5ÀòM¸¤“Ž"~K€KÝDAïÃdW?#çÉv:SHƒR‡¸šŒêÓ
+Ò¦Eký¶?Æ4†4u“Þ­ë3iì§Y•T©1‹¯­ïÜý—Ôí#Iw¾8–ô‰ÄI©¢ü‰9˜\(_ë©Ét?Æ?’ôÍÇbIÛÞb©’:<—¾~4È·'1&mÇ=¯õû|M*>ºP¤P“Ú·yÃ%cüñL¾—žjhÒNña>ëM§HÒé󮥒*ýåÒׯQr]ÇN2äp4i÷KÜ?g3q )dQiç­ °ä„ éè•|`÷HÒL7â"c6÷m½4‡yz®“.ãË¥ ŒÛtP%¥|EóÜÓ6¹æÊ
+iØ$…,
+-ÜöëÛý‚d%‚· “Ê¥ÅSbB4ÒÊ(Ö:°^‹d´ÑKUjET_!iU¾Â¦+¥‘–bO‹†ÅDWë4qw®ú¤’*,:­[’è%¯’RI*3‚Q¿„…$¿rz§)åzQKx]³:ôù¡ç©óC5_½3!‡µŽz±ýκ%› ÏÁ´^(?”Þš³æÀªçúbÒk*›u+Øe.neŠßºþ ìš(¾´r¬5Cû ¼uKÏ|Lj]ÚË”w¼ÂZÛ!¾Dá­ËçÍiµD,uóìZ-›˜Õ™¦·™šuãûÎZÖ¾†Xc8ÝÄ\¹‹ˆ½.<Ê®©\-´“°ÖwÏò–À['µ\Áˆ¾ðÌÒn¬õK~›XëîªôLëEÄö»zq†[ Ô»Kb­T¢ø1ÏŠ_Ú¸Õ^ÂÛš±Ö‡rgÉ`­TÉÃG¬LPî@cM6ɇBÐð9翳XCÃ(éÖj4o½•Íá¢,›öH„ûç/°*¹ö}TuýYx8Å*êÏÑú<©IOE
+üÿ3»Y’Ý°³Ù`¿ìããæòÎÌ;ïÀ[:äÒá&b¯óþɆ;v°jM[àï÷‡À_fïÏÑ]Ø)í¾,oòoº}Ifè–^:ˆÓƒ ¹s.äN÷‡ç¨SX"NDñ¹ÒKuJVÞ/ÌéˆwºßÛ2LÎíû¯µçtdY™Ð)UÿÓR^¢þƒL½ÿ§Ù!½^y·ÀGEÔ)UÿˆS¸Aý_…N!!×KÔ)
+¬Þ$ꬰ¯„ìw–÷ó99òRÜAÜœ³N~5òÅÚy¹¥ÆÝÀÁ©'»N=W®H=%”zŒ¸Öu6_x
+Ó¥žÇ÷sÃD“†f ?5s±@×’a&©¯G0i$WO²Ùy"OKÀêLÃÅ«iQm¡»òäŒÅ£#é $\ЭJg˜z,o©…Eœæ*ød*…E‚úyÝIhÊïäWë=iÄS©eL\(Iãò™?06T1I’äUÝ«»~ù‹ˆ‰Œ–0.º_Bª¸y÷²v¸.*ó Õq+xx²c´Ò]¬ îS1<Æ lùT.ªé¿6•µÁóV¼Ü7}DÑÙùtçJ*ÙØ­:í/!6†¹ :ô¥{|Ú2ŠNe¬eÕ‘F5…\6"¤ —ø2Uæê/ëäõPbX@+ˆ¶Ü “˜±ç!ˆí÷v‘õo£ðû8¡9H¤ÏŸ¹Ôüö{d‹ÁoŠ—ó»<‰âkO“ô¼›ÀÁþTŠ(Á”BÃHé¦Zvf’ 2€È–dä.¦z-ë@3$
+¿ôPÃoH˜
+îJY ­Næxó6½ðB1-Hé˨”†>H¡'kˆi‚r;*¥“`çë1©ŽG­„9ìªýwv¤#¸[,Ñ"lG”ðfórxšU§ßçípùûétUŸÏÚѽ‡%D4 ÚéÐ;âÒÛ„
+ö ›ª‹Ü¶¨8Éð©I#ãäúNŽ<>À/†u ÿSÇ ÃŒCòü/À
+H‰¬Wy_ÚLýù,a K´O¡
+–]‘*(n(¯X
+UÈ÷g&ÛL˜™LˆÿLýQ8w=÷žÛ(•oíùÔ¯YS©.> ßBõäEñ¨_Ö”Ú‡^W_bZV©gRð¯«ôåbõâ©¢vž5IVϾÉØSY'^®•Ê¬,ê…h!:_WçËyJ«Ý–ÎÔ\ñª
+ÑŸÝsñqÄÍØþ$Æsø³Í¨ä4Ëéd7ƒìtâð;B’ÍžrJ°#öÈendƒºÎ>«|ë½S/ ³çúv«éB™÷þ4”=6C™_…ÇPæ¬Ô [‡MBéÅò> cðÓV(ÝÔás“-œ—¢vAc.—Í¿¦Û0 ðeF9|_lõ¼¼Å·X¤?;{ËæôbX+—`õ­,çz?Þãjîx¼ÛnÂ1`ïõȶIM‚c'ÜÜîž²¼_£Ê‘ö§ï2Šf22û=®ÿÝÑ'·L£z¸µÌ3ª­×ßWäõŠÅú=ËŸMÿÇ2ú‚-^E1£?~×®0£/±Xrß2«GsG&\ ®l¢ov¤í„Ñä„i¤÷X#T4‹ÇZR3Œ~DoÚ#ÃèäÁeT’‰ëE¶ÑvúiÄ4Ÿ'þ[Ð…@'³nÇ™F·ú°b <d®quÌÎK–è/³ÉúíËQ}Æ÷woïüïX íÍcs|á‰ømaö)&k æû_è{Ä}J¼9Ó¾,Z»-{HÙëßíP̙禺0Ù”@
+Æ `èÖ”€8Uké–ê³\Ñl+`[Ìûž0Nê"@.¹Ô¯Û% IPÿÞ5Èmï¯tÆÅg9Uî÷¾"O?SD»Âê»=ô'a«'v ¨óå|ÄÏ““%ã~áé«›ÀñI2Œ0ãŠðÐøÀ½;áòE<é9ÿ.»rß©zöîÀ<‘³&‰P`,Ö´MrÖPd³È¬iBËmÇMP}ú ™Œ¡î ‹åIú“/I]£jb¸b5hÞB,eŠÆƒl?#´Ô¯Y“œ0û7­ßÐ2~hÖ-6¿ÌÆX(ÈrûòÍ;ª˜¥ÏQ'ƒš»ÈwP­ÖäJ`^Iín “ä{ej°ïSç ¡¥›–01Ó­Ðiêu†4ÑÍæ@sÌØò)¿vD„™»™¶qÅ|àL~nù:z+Ygï¬)|ÌYs3fòs¸—»äLÏÀ÷ʆ_ÚF«Ý–Î\AÚz,]y:î¥ÍÇL‡‚gÌÔzÖ²ú±Cï®î¸~;$ÚÇ “ýʉ6Sv‚] (¾&0¥DÖ÷¥í)»\YdUwõc¬xì$žn%’5 Ñ’…R%¡ /†^ÎÓ©R˜é_J·˜éÔ"ÂrêÄ.Pýìio³roçÆ]dÖ¯P]÷øõ“dÁ
+nmùy@3`:Ùóº1„;k›OÕ–-eÍä `Þ/ž±üs4ÞùªŒ‘³6PÎD;(cÆ:µM«'غ¿í&î@ª4 =v˜ÀØ/;&ÙIª@,tˆ{^¸ 
+ÔÜE¾C:Û‘S¼@*XÔ;èiwcÌU^ˆ–6E~Í]iÁ¦%™˜éÖ;1{
+( ÂÜ@Âyw2äm#“b¹P½þTI±ÜuIJ5ÇÜÄÄr¡:T"Í É®v ^wÉCƒ2
+Ae@tàÏ”$ NÚ«ú‚8™ Þz ád¿$ªçJÊ->”c«‹¼' IC /|º–0·ëq/çpŸGC ½Rn‚Ï<
+á"!v¿¸h8
+BC«Ù'kd
+²28 IC9Ƥád-JCŽ‡ùöw/R­yßpOŠô¡^¯ç èPrb[ÌGðFöŒ<Ÿ+?W‚•1ó7OÉ4úR¥Ô‰.m怶CM®”Ná#c’I¸F†9aÔ×|˜:ü%ð9<Þy\¯l¡³6 û’9@[²„
+8@dQÄe@q@.z¹£‚¼ÿíÎÖ ÝIGøÓßL¬åTÕ©Sû¸+A-SNðžw%A¨`#;Ä}à³?aCBaz¡{‚’†^°–:܆µ0Qž4ä•và& q*
+€£ZÞµZ*êóZwéãÑ[£+¡‚ݾ±@™êiÿÀlÃbÍ,ädÏóÃõRSÛÈý’ „]‘2AYn‰„IöË«ÏÅ6ò‹æ|›^5i>–?eN•ÓÙ•“\P¤𱆯+ËÌš¾;
+e
+Tßùÿôl‘(mGVüb7
+2ÞûˆcŠØcñ]^{Î> ¤ÆoJpà öhÞbŒÇS. ! T‘PÁ2ƒÚý
+„cä\I—ôq'¯$„¼›zÌ>¯¿<†
+ ÁÐ($“Ç„ƒ¢B¥K»5üú!NÈ)D E^[;àD^˜ž ã‚SöySmù¢L¸ÅÈ‹¨¢4×ÔE” .‰½ï8`Gx¼äÜ• Ý…îÊ×n*Âãä&<.±¿u&Ú¸’Lr”äŸM±ÜbÎãÉ0JKÞ=µJñ¦cü-¨ ™¡HbcH947äs²Ò[‘@˜»ÅAÍ¿²{¨•>X’l¹Õ;QFL¶ä•‰^ä X"À3ËÑí$£°±4 D§ €µÏü–8Úã‹ ©G2LñæÀÝ’Pð¯ãì–-’<s„²øÍP¹WÜ‹()É{% Ÿ'Jr›ó‚z¢E‹nv‹³E7•’ܦ‚åwº[j¥˜hbzŒ…VÞ?\Pq%^ý«awåÏ
+çZ3à>º­­]ùƒÁ]¶€—·bôÑ (sÜ4D‡ÐÜNæÌ/©eàY’a.WNV5ðoÑOnΰÀª³j¥w?¹sç^I›ùj¦:ôb1Ý
+M¥‘)K)1>îzËìÞc5ƒûvì±þ-ÌཱིJ²2«/hg°üa4èJ2ìì<†ò„uØ’²#9»$áfŒT«ìLS&ÆH©YÖoçÔæ3þÍkK'Õ¤ùÀ^¦eÎC`Ì·Âãh~#Z2ÃwÊ;”Ìºà‡¤‹ˆˆÅOʧÐ_ÇË=ä•
+õ˜)–‰ speOüú݃‰(9ˆíJlâÁ¤¹7_Il›joD´% ç ƒÆº»Ïþ=Rðþe€}%AÚ]N˜VÖï¿]«/hçMþêûŠÞ•,;ž2^({]9nVl;×7N%½í~k ¬Sø‹Ìë÷=¨‹µdE´|,ÁÃÖRC‹Œ!(Dj—« x1Ú]^ïi Õá=9ž<ÆCu8î¬ÆÞ;Œ¡Ýhƒ¥1„„Rú©í1ô{½v|!k‹A;»!´BîBg'û’ö¦±Zê‰eŒkʼ+-c¦„¶[
+|§úôÈr­¾þ¯óÂ8?èñž\µøNUõ^3œÚ¸ ÁÿO:¿Ì/W›x)MVŸó]®–á~g̾í{/þ°˜(.¾U´&A΃<-:í_² äd|yÖеMHö¢ãžOäÉ@=ŠAÞ¼Â4LÞÍôU*¶›íÒ׉N–©”Œ§g* uø®1h½Nk^×`'󃪭¨ È$‚Ê—ì½×¬aî Bi]w¥ Bjo¸!ÂLœâ¿&*'j³ –ÎÒ0DP·Á½à´@+Ý®>½ÔA<˜˜ä·€~;w ÉD) ÖOúÃb—ü óÛ*êóZgŸþò#u7c^„A'9Â#¤@Ø-¨Éz?}
+%yÅ9qav¿ÈßÃуGL£ìµ@õ"Ê€Ù·Â KpR]‚<f'Pâ´b±%à"MT!>4{9aêŒåÌ©È%BÕÂ%…”½òÇ8Ÿ¤™ûVNÙ‰— IN%°NIÓ¶~ËeηܯÚrÅJv²çâ¶ÜÚƒ,¶\Ð4Hù}¨wLW„,_÷ê‚T`³ZñÌ‹zSŒOK Jʤ@*—ŽeÖ _ Chª‚UiÁ&4Ú:4ñ²lC¯efw‘g( í/û¨|bTæU r®ï^€˜I¶lªôƒà¼rÐE¨ûPU½ò¼Û¢Þä.v90ç°Hƒ2Œ0¥gƒxt =‹©dغfº@‘ìè›h¶{äô‚½nìÆdRÕ8N²G³½ çÊbØÖ5<†#€RH¼Háòßæ‘z¢°™”æ‹z±&aZŠ¾<4Xcºàô¢Û¦B1Ž¼!*e¾8¯P˜óþ梀ÄÞ7f‹{§vCëâ´kÜÔÁϼTù *¥“pиht ¶Ä«^ˆÎü`¦{c¡ŽN[BŽ4ê_tŽºk]M1æ²\žgrø'˜Y'«ØLŠ CÁ¡R¢¦ñÆ ºÕ¼,ÎV]³ƒÆÎçÝe5ÑV[ïÇ5÷]¿â²M ƒ³´Ãòåk¨
+ÈCU°ÃžñnÛñýY-¼\¬$±¿§|Ý)€HÁÆ6XcQï]½q]ÏÖQy­P-€
+¼ X[q9µºÆ‹l'ü+Q™¶´‹]b‡Åo¹«M0-×–„Ì7 Ô ú6ŒhÊÓÒtM7YJÄ´WÀ؆àžM"¬ÛPiÂ>jBI)ý¼ G[rÞE:kC`ì’644¡²‹ÉÆ®oC€¶q[ü/
+ðì‰Y{
+VâÊ‹qX¬ËtC3îgï&|& ŒÍ0V…¡¸½b¥áÈj?ÓR:P,&r$?\¸ £p±ƒ²ÀDíôØ™1ðáŒÅˆ)QÃHÆÚ…3–p`Ì‘†‰äGnŸýÔôØ31ȤÐþ2˜ˆáŒaús~°yæÃA£.LœzÙ9ªÛá Î}Öd<<[i´Çj\ñ
+ãâî88…¶±Ö|ÖüŸ%<ÄC¹Û%9ïrc‰·7zɾ5´­]P
+BR 532 ²pr‘ÅçòrXô,N¥Â_¡3L´
+ wŽ=Þ×rìaqWNzÖíÒ }°}g„Ïþðå¡’ æÀN'›%?‘šáƒë
+äjôš»k{ÕÃ×VòC}0˜Kýaþ·?ÁðŸzÀXê>ðæh6'Ž=Ò ø;9ŠLÌÆJþÅÓ ¯B4@äæü½ @ œêüM‡Ãx(0ÅÆ{p£ÀÈ–Ùr)Ò¼f+\°"OeºR­ò!jõUz[ï’›¹ñ#G¡sù@¿+ü7cyð Ô<˜y i)?*„ÕG‘üs/+?¨*çյ煽Օ LË(c³æ…†{¦Ü ª/»H^xeÞ”Gaa›âà=VÒGñøÛö}ñ•D#
+àÂÑl
+ËT=e
+àH<‡‹ììÞ—ú÷MõÊ÷¥Ø‡†#ņOZik¶EIàæwÁ`ÔE^m6BeÜEÙ¬¿vû”¼Ê9jÙ-ViBb~á—óÛ¨y‰ø?'©žF³˜ œrLJµ1 £²—ŠxÞc¥²Ÿ9~Þ¨úÁ¯1ï’ô ;d’ÕÈÛüÒ«t+q¦ _÷`”%dYd ¢ìÊ& £Q‘íœ÷×wí_U§³À8Ž:rºÓIUu-O=5ѬÕ,DDÐ  "1@ˆ(l»ý׸“­ÕP±­y€nw•"Öà]Œ™æ:2ÚHqwu\]yé]Œ×3RçZ6ªEó!÷˜ûu¦ßd_¢§Q×´˜Òw/„éš²ô.ƒ‡ïm¥Sš6Û¡¬• «‰b­fªóîÜoûúÍšð¶säÕy.•ˆt'U}\õÆ0ªYÍ7ÚDäË¢†X Î(þtåÓ¿
+|ÄÊ`CYäz(  –ŸUìÍwÕÉ*`áfˆupÓ†:¿Ú¦Vòüy.à–#!?úWd‹¬/Õ[MÈôg˜ <²cœoj¢:Ø%ËÒSwDC|Ò“Ý YæI.H·yî\W~‹>µAKdýÌ’8@Xæ
+ê‚Œær7ÉŒ]P'„$Ç há8 
+Áo‰8Ì1Û-?Î1·'~˜cnOüzYwÅï%È^Ží‰ø-M]åú]WÒû×hpŸû²‹ÏE| ?@zå‡ÿÕhpN4þØDà.ŸZñ}ü=€á´<ö³k8áü¼bôÿ`ÅŸ€ëË6|©#3þü}ŠP7Ã}ü·êÓìÈÝCv^þІƒ>äB˯z‚wgåÏÐ’ÿB^~Ú‡ø²òžüI^òj¶§”]ÛÁ6~él5O<WÁQ!‡s,rÕ’è Žê渌õ™@4Ðg„i°Äˆ7œˆ$0‹ÃìÌKA:©Wg¶a¨ò|›‰vhO¢Ã½‰oây½×GÜ].Ü “‘êiDÆG`Å
+ʹßàlLø–üö
+†}Z6[ÞœO•‘\y2y‘ ©¡ôG‰Ì7hÏ=™sé”›
+±zA­¢ÉŽjš)ƶëºÁ}p%L¼öQÀ}4ŒÌíGß@ó$–¾Åq \Òû"KÅsÞy§ð9%A>Ƹs¢ëhâÉS9År+bÞ½ÐY)Ï;8h(èA)¥8«Ôy—… ÝRÍAqê‰ÄaJ2‡±º$‘V¦sœóêàþšïU™¦ËèºBÿ©·‰Xxœ&OQ3¨­½f$¹@G€–Ë-*—Î$L- „œFö%¸à/jÓÇ«|¥Ì4AÄešŒf%Ãè™CaÞý‡ 2Ó3U®¤'„ÂôúïbëWç¶Ølx[óÌ‹ƒ~tqÑÜyž
+ýYM&³XK±ã;V»a†Æ¥7Ô¬|j…\Nȧ#S+7nÄ•j¾žÃ2¼•¬´¿•aÖp¸RP‹™º·*¿Ä•f¯B¦ˆBâõ ¶}*q4Õ18}»rú²½R\ÖŒÕ᱆ܥ¯¹ò†§05V1Y2žÃÖ]ú´ÎeΕ՗¦· Ƹa&!w<ÄÇ֘ɾ˜ÙlÐ Yë.
+èˆD×®ÔuÁZªæ÷“lú_ê(‰…#ÑhøXjì^æë›õÓâéíX<JIeEi¿Í–úz>oÍÿÛæ—ÓÝëüm{?–.š¹r9ÎϧËÙü˜´ðØÉŠ
+M—”;J÷³lPž7.µI^o[¬lJdzç¿W¬¶tË•¿W¬0»á!ð·Š8‹W®¸ÅÊ]ƒ”¼S*ßÄb'
+{­„óªs”yB€Ó@Œ<}Œ]nkô"àŸsÊ€l.Ð
+¸@ßMêâl“}©#‚"gù?jjžÙ©ù}i™:U¸Ø3¡ân­ 7/›à%?3°‹?c/e˜M­ÙòÈ(uLviø ‚«èÒƒ8¥~
+"óªKíD·í*F™éã¯(ñ³g„žßÚ]Ó3Áµß  5Ü>3Â4õì!¯ûŒ f‚·® uc¢ÍtcRëËš
+
+i³3±˜°¥^~]„9'»]FºWã¬^tá§ò9Ö2–z¸IÕÏßÃÄO‘«;ËL¼½·°²mãä y3ŽRg×¤ë³ ÷ß«®æÅÃ-u/ê\‚¨IëñÔ=ú¥ÏY4§²OêÈKæÝšs]ÅÌíQÃä£Y[ã£u·G4,hEiÐç#íÎ$
+ç7%g´Îì‡rþH¯–!\¢¢#S„¶uõlATµzŠ“Y©o²®”À‚òj„q¤úœؘĘw÷Ïbd xwi=£<Ìg"ÎS—Å·)ÞÉ•T¢4ŠHÏš ¯1¶´ªæÈÝ8Ô~‚©RˆÅDðXAÉÚåF‡@ùXÂÅ›e%íSJ„‚ÈùpÐq@TE ê4aNŠðd Êò˜¢Ñ4çßlš#êçälžrd”“g¶ª"sxœ£±Ï93´JÎQæ Á¢ö¼¿Çü€Y¶¼ƒúè!ËxŒ„KÀc2£0ÆwÏi•rÙ%yQ)ÜN&4«
+h¦ /&™­ …(]ÀR 6Pà (ˆ}õ`±rîG«û§ù`ñ;&Sz­]ué
+ŒÉ-A¶vàQ
+ƒßý•±e*–ž‚ ÓJjÌò·Ó3öuMøIå¦Aä62m]×-Ã…};Ï·±4Ì‘Éhö>§vˆ­áFˆ!ØßTHZ†¢›(©' +¥ÓLKA`Š¤¡Ù6\Óã»kL%‰m”Ò-¬HÐ%ifÒ2MÝL²%†¡†™‚•l…¦ëØ0‘‘ĦÆVhVÒÔ’º‰MdFt'lé¦ihØNÚ&[Ûàÿ^É•ä =ÁÜÁ'¨ ¬{®3÷ßΣTÕí/Ïlöü’Ì”<MˆÚ ³¢ @e#æUÉ£4ô®dW–O›ê
+¥ŽahBV=äà!±2¶:­¦65_ŠÓQ,úð¯“Æ×¥ª½…Ÿwªÿ6Ë6Úß [Ûj( ±ßÇ F‹ö¾Ü¾:Øø’ñÞ‡_2{øJ>xIZÆG¥¦»ñ{ÂÙÓŸu`( ¹ÿ4N6Y:Û˜ 7¥ò¬#EuS35‡œÿ ²5ö]ª‡sè4&L¨}»™%Xˆˆ^%cz«¡^ˆz†Â`ËY¯;>¨S¡ë( Å ”QÖ6Ãméø» Œÿè9_‡¶ÄØŒhÍÛÄŸ ¸Õ±Š¥Ú²ÛÆŸ ¿Ú
+qÈ„ ßÁ„²:φ½,‹Ä\],^,ÅÕ]?ÑÔÞÌnµ4l#Æ‚µŸròÈ#yZ'nG„ØñÄ…¨•…3I›™”báy•? …Ö¹šW«bÄþÏ\3ÔËÛŠi!j3Š¹qø¢šW|L8&ቸŽžRÿcÏv2«»ºE¬äzlãƒoeªôõûÏc$9Tt$tG¼9w –OÎ…vÖ¢ƒuCrÌë…R½Ëì¼ä7||7=ð/–5§þ>‡'haº¢KÉ5xÈ Ÿi>?/à ¾DùG8Ÿ×„\F/.ʘçSf‡ááÏx$—'aË~˜HnóÏ$!ï-{ˆV+Ÿs{âºE+»>[Óx\òøcE»ÌwHx"Hö½åyêcñ'ïƒÔ˜‡g\_0 šO¡O^ÊûZ¿»ÔwrÉGn¯„^zÜÑ7È.Õöê딜ã9èEé÷ ;äØ͸þ`
+H‰Œ—M’\¹ „OÐw¨õD¸‚
+ÙdÌFê¿}Üò)Ñ ÒZó°Ç7 ïÃx_D¦îˈÛg'¯q CÈ„Ê$ñsA„Fàîz î“·.ÑFz^‘RÁs7FýGµÂuÓïû3[nˆŽ–.šc'Ç…& ÕN“Ý@öUô%}ÜýÍ9¯%ç5sR—–.·­CP½YNép%ÎU³Ik´Ÿz‹“'¢RÛ=
+CF´éfó¤˜4nKNÜuz>•©ƒ’Ÿ+ªÿO™ï«-rMèÝ)ho”Löqv–1’_~¾Qq¸>²óß‚¤y’•¡:OY%;ç3õ… ]‘úä ‡ñÔ‡ÚàÐõðùÔtë­Úeæ¥?”±£.ÍæmŽæÊ5ÒAf!Ê]å_ ;G¯½úåœ$(TŠöÕŠò¼Æ¦ÔWtõ‚ÔUÖyŽ·wšÔ,NÖUT(ƒŽn4QØmÁ7×b®9©ß).Öi…]û5ÂKç䈓b~©£.¢Ó“¿‚bµGr9½Ø“¿‚üéH2R¢±eƒ'£:&ñê½Îå“LQ~3RÑ·>уž7ªl't$žWêœÓ‘>š }ÊC³¨1æ9†÷Ô†¿‘ËOÓó¦)Üìóöº+ÆæêãRæ—×̺ʋ7‰Î¾ ŠfgÐ’:=Žì¶„pLîëœAx¶Ž,ô“b‹B•¶í«^YP†‡ñ'o窿àgQ9kR%uX}8òfœþ|êÈ9e-U¨71>$3È£x^²jI÷Àk¹ éŽí‘Lþ•×³ ¶)ÿ C½æ´“Äv_ð™5myAþ4
+‘L
+š6C.Ÿñ:*fFø"ùÝ)(}ѧý7ê—§TÞi?¼ò8ß„Ak
++ã'¤¯1mç8çôÎðൃÖ8 vk¨D—ñò©Pûª¯ Ïöéö5Ÿ=ØmT¯^î6;45‰.°¾ õšb„²•–y¹ ½­Ô d—*hÛd€ÃãþææÒ˜½y rƒû¢þ&¨2Ablê¹MÎ^Rü—œú¶¨××ä«›0,ç²INyN#­cQO1¤°ÆšÛ¸}¿È,î+VMddÉs©!G{–@ÑÎ!ø²{Ћuü¾N ’‚<‚IR…GAç½F÷úñ+)X"e¥e©EŽýÆFT¦Újbu˜Gægð+BˆyÉâ‰Oñõ8–0å èëI_sΛ¨¯ÀÛæó'uc0ü,ﯫ“Ø4ºáÀï@?~%•©ßþ9ûû??~û÷‡²'ÕæÜFñŽß3Ã8d(eך‰Å/œÚo@ß9©£*½&~SI«'[‘ñWζ@5¥ŒcÏmU^A?~åM…îî]þ¶eÁäIƒ£<•¨×ÓkâȤAbhørŽfŒº°¤cvVâÛe u««<9.]Kí´¤¤¡-í@xuÌ[š$Ê g_Îç‚L-‰Ç ZÖHa½
+ \}Âù8¨µñ°â¦€È:±Â¦–oJ%=M«ëÇ•Æ—R,GŽ"¢Ï4È]^°’J
+RÂ
+Aƒ©Žu'`-DÔ-Pz{”hð’P\Õ’ ™|‡‹zòU‘œïT‡l§úáy:íiæ‡I‡¹nÃw$²\ØZ¶§G ÛÓ|Uvâ\T€  ÏõRô²$Æü0‹`ÄQÍÆÆÓ‡_xm¼K:-AÉÈ·¿šP$¢ò€ƒ 5ç’ÔICXÄÉï÷"MgW¼ 䤋þ‰»âÌ¥§¥è€"±úÛKäy
+ß^ï¢܈ÉûÛÚ„ö™µÊ\'GKŽ‚j¦f‰²µ†Xÿ$Bð‰ÅP
+—É ‹à)Zì¯Sú
+=É8B ÙϽ©„=]Òg(+ù`W?§Á³ñrVŽwÓ²µ_Äü?Ö—/ªÛ‰v–§ÈÏLKÄÀ¡>Ÿ:’¼»h‰7‚˜§ SjÑÚP¶Æ2þþ¸òkæ ˜Oa¾ö‡@öñ7;ø“u-¾®šžÄzìkýw’kƒ­™ëO˜C’”ú *o¶ÜzÙÇZ¦xzZ|%Þå2ÙZt _›Í¹”Gö%†
+XôÍ‚È×ôùN?äÀßñ¥­UäaæêN*$9µèù:^¤±5öÒžnŸ‹êp׎m™·R~æÊ»8å˜ð å&ꤓ¶ñ¢2îwÜ©—Wœä~¨•ç9[Uê‚J½–÷³Ÿ¥†ïôuÌ[ƒ¹å;!²*ïü®(ÛbaÅ¥ìîæá¤Àœ¦ÖÊu¼î³
+*×)æ,Š„C)gd.C`ù L8;Ûü3 U牺ÑHþ×1ð"©(™F2Yc=ciÉ"%uþžD
+#b,›±Óø"´KÒmÇ¿3`ÿ%ÿ_V– ô3‚ä{ ÀŽ3—Qƒ&)`½¢Ÿy'ð ,.tž²Ì_ y
+Û§€F‚\Áù*X˜fH”—L§~,BúKD2Pš’Æ椈;Í]g}m)s¶„¢à]ºW¶ÜÉLìõÿ'ß?Ãó?áé
+œÆoÙ¨ä é7"?ûvßGÑ@äÕëL2;œÏ\±-UKØed³ r]&¹§Àì,Ùö’Ã$0X÷¬<b ±*Í‘L˜¬L¦iŸïÀØvÍ”/“úm˜+IŸö¨E^„æÎÁ£x_2^ïò©¨\sUݘޑRÒ˜ôû^aî§[u[PäBµ ^ÂÝô•…aØ>2DXF …
+Æi…Ò%È~ u#|îòH9 Å!رlðã‘ìý¾_±‚?^ºÓ½²ôó‰çcW8ÌÅ:\!EÅÄì™=."0œ´‡UŬçŠ.SIÏ Z0lä–yH„¹õ$Ä-ËgY±È
+Ÿª›Œ#—N,¨%Ñd”Å“ÐÆo¾Ã!b'¬æNJ€-=Êဨî’=é}ðûóeî½ãMõ]toü¼"ÀiXÁC£mþZ`Ëv‡…
+ è|ÄvI88–\Àäê03`8&Jay·)¦œ2.>Ý UUõ¸2Þ’-2þ\ÓrYàkþùÙ rz¡0|Ö~™ $]=êc!A´}I†b%Š‰™±k'Ò”7‡dVf,òWÖùRü%ÇGÖ1˜ò<ýŒ¢­ÅÂÂHQ¤5jÅÉpß"¢›7ˆLËëþÌÒ's¨?ñNÒLWVUaÔ*6¹Ü}¢¤Oâl°v— ê
+tWùE>ø›"zÐÇÁSr×M«ÈV²KŲH!AÁá/ŠH“|‚)cÞJÚšº=Êm¢Ý¢Ñ%‹(Ýõ¡–(軉Ù?¢¨‹D¿}ÒðO9>e’ÃÅU"¾Àšñ—-m–‡WPB€‹úßપÌôPòË2bUÂÌÍÒ½üåÐÞüñ<š´iDûP4±¼ˆÒðj!Î/—äºnˆ® {x+Püsœ ³ OåýOs•ø‰7åTªËÉ 4úÿcèPÇ:¶uLÅB›Bd TÐ8äà÷—Ë4œ·Ž%Ù ¦ÒÛÕü³°¬ô¢K¯Æ†¢@ŸüJ›g­ß E Êf‹?A†Ä‰éž Ö:ó@ÖžHÁÝç5ü>9z-ÞdlŒä
+ÖMEnYU
+8¬*§ º>·ä×d]PšK‘Jƾȶ¤~ÔDAIEf•ƒ$"G°‹L©¢ŶaÁTÖsrÄ8žLGs[Fx‘Aáß| 7<XeÌ»«Ýg1Læ¦çi•…$Դ¼„r0E@¬3Òk
+s7˜µÅ‘pâ’ d@gZ^Á_1àLÆÙ«²ÝS/ö˜¡Q"If0{Þ¸,t ^†_^wHðçfß|(ø3ÚŒ$xi¢]™†
+@–Fc*Á£áð0ÍKpXy@ šþ.kñkÌžMHE°d{a 9VŒeíà Qž©ÜVìo?‰mÂ=gQÊ- |zQ®¢)rSEãC/SXê*þl¾’ ÄηZ¦b©A¤t»Úþx§¥Üð\m—ÀMa(Ë7üøã2ì;=§]üg™ãCçÈLc„l—(âÉÒUA^“¥eĹ&k¯_Y¹>΀èžRf¸¢H‰`fØÑÏÉ0=¤Ìˌ׬Áb!߆q¢“i]b„vӌȡ_5÷²‚}m£>piÆNr¥’šEve上-aÑîËKä=š|sŽC
+Àäuüô2¨
+ l5®ªîQ XÌÓŸÅ®ƒöUÔi79Šƒä÷)ÁСnˆÖÜ— æ
+J»É þ¦¢†œR¢ù+qý!†
+® r3!Î(špl+j
+‹/…ØÚfBö¸ðUl8´U(B
+Ô!»E 'ðˆâ½]J^
+¸½FðDC¾"¯ËGºè'3_ƒ(Âã,·—.†Ë$xÉŠ`ÁÚÒXÚi€äÂÌÖ Ã&þG÷8%nú^„©ÆÒY×¹iºãC1ƒSaTÌŽþ™¯Û.XÑÄ«¨Ñ¶¨‚q•ðŸò¦‚oÌâà$çC Ù¯˜,Óœ¡X¨Ñ:ûÂ,O
+­”àþø%ÅÏ>¦Aˆê%ú— $àS[^Ž½Bf…(†ZL@VSA_ò¨JjY}°ð©µKžˆ‚)
+>°ß¹è{‡ ²Ú2Šþ–*}Ì¢(©Ëõ—¥ìÈW³éxæ4R”8C–EýÜÝ“'ÉPÉ<™À e1¯ŸÒ9—qËÖ§ÍÎÐhÂôX¨)e~\º¾›÷V²/‚ôÊX"5®ç4p›,Jç*ì(€eʼ"÷¡k³iíËnßww¦Â‘‹ñ}Y€¦‡«p¸%¿ìÓY;dŠMШíˆ$^à1UTïkG¦cºxÎѺ•»Y²mÑ3–
+?цEC¡þ Ã` ®ä‰ëR/Ε¿¼ô÷"F ”q¹ý
+5†R˵`€óƒà—2¤L
+eò邶yÉ›¾TR  †R¤@,¿ßXp~ä]Fç’¦ôÚä0œQ7¿*Ë…‚fF>r¾Ûº¶®*Щ„…"(ò¢Pü„ñk­7,íÊ¡ˆZþÓ?ª ÂðÜ­<
+¯ÛMHã‡î²˜—ÀžÐ
+–èxå¹IbɼÉYð€!Æ"™΄‹À¶¼oª´”Ëé*š< Ög™FW¬K¦ý(Å
+
+áÎì~~2ßaŸO|?06MF5oïx©1Ï¡@)#•±4“V@ÆŽlŠJŒÚ™2Ú­^Š>‡1D,öú‹F¡,,& ÁüÂk‘3VR.ñ絈ñÓjzn AÈ'd¡Õ˜#ìÀ‘C%ÔYÐ<¦—
+9aÀ㈀šÁ:0½5ƒ r§—)˦PûYâv¸ Y „©ØÃÍš˜“èC[˜¢•Rö2‘IŒç£º”+´ü\§|-ì—|ØzŸ›!€ß•yÝ%MŽ;Z8úž‹ªéº¬·Ÿ£¢ yV}™Ñ¡AD ÏØ­`óVdGV$è——O‘S€\¦CȲèÒžüWO*]çtÌ|²…°ŠK¨
+w8#È ™ÒêcE(Eø\̽†?ð'Fâ(y›þ ì°÷˜ÁSÃ(úˆÞÍfu˜1÷±È·ÐÁ¯õûƒqÎ^~“¥x¯¾y±’f}sÍw{¬>z×u_kUÒã]ødyâf½¡m{ •Jb³·´æ8æ9ñtö榶ã6ºÅ
+öãqEqÞ¾éáø»z.²Z¦ð;Õ7µEl•`VpdåÎmB&¹ÄòåÿŒ’2tÃzž/DúG}Š|{Q l95¹ÀUkãÒÑñ•Lô(Z‹‘pXï
+ÊOÆîÏ÷ß1'W³¬7éñˆ/æÅâ¡cÎse­JnÚ'ì$Öâ¶Ëƒ˜NáÄ1»±Mðz!:ÂWß~O|ÉlLBÔ×êÍÃÌ™7ˆ½ù(¶Ha±éãi˜üœØ‡R`\W6{퓸çS—îV¬¼|Çg[tùÊ99G»e ~‰»¤3I®ûÃî–ÉAÂÞê#í Ó oZ³}úçW–æ|)ŸÚ"åÜ®<E¡ävÕ´õ]®ÝöptÇ#k ƒË/†F J‰®„uÎ#ŽÅò&ÞûM¨ qݦ¿0‚µÑa×ùQEè˜>‘0dòbúRÒ9Ô+¤MÀ_œLÝmý–ÔùÁÊhO«¸ çãS²2Æ°ÇÙ^IBÇ«•1Îò»²õ“•QȦµÅ°2¿ÝÀÿ})[f&¹…%…Fü«:I•è7·í³èŠá8oŽ£Ú¤]ÊÁ€“Á)+ßa›…NEÖ¹q¬ƒ%['\‰Ž$¹{¹9™¸¹•~­¯¾9}ïaŽ-&æêŠÄÛ‡9ÚÜyOàÕÉj:eúßœ›ÔcS¯Eµ®l»pé6ù£ÌaZŸÙq¢ïÆË¿Î`€€]²<î
+©­² ÷:
+‚x €Ûé²bÞ
+Z™þQ²†vís<
+\«µe,fó4\€äõ¤ÎáCVˆ¾þL.‡ÅÝ£„n•Ö¹`¨•ìLùùWˆb÷4`b&îhMUWö_@n½‰ÿt,W<`ó±{|*FÖŒa}ƒ»ÓïÒÙ¿Øue«5ÉX4ÂÄ—`e,êMF¡_%»ÖB ²?®oo¤ó¯’A_¶J’ÊÆ þUúJÎ0êð|2 jÂ…çS”8e3 §‹wÀFÅû[‘æn‹¼ ÕݪÂÓ5Cc8¼¶s ãeÉvtÕì¯ó¥dî;]qoÓ§)ÚÉnܤ´XçˆÖ¿Oæv—#†G
+zݳ/:ES5n½ÜùòD»3fXeë_ ÇYG¢ÚãÍZ=™=wt=Éx¹uY~¿x³’4ëpÆvî—üÓ›eü.s·óZÏu~òf)9}ŽÒå £ ÞÓ˜eË
+Uðþ倫S²Çöå4%|ƒÜÛÛæQÉea÷ðÉL%/û»Õ,é䶗)|EÁa¿ì(Ú§’ŸÐTQòJZñG¯êsCý0ÎÄ–0_#_Š÷hJRGô-%hi«tB]fò@ú­t;«d§ÓË-[µ}&Í£i8‡r«á8¼ÁÕ À´ gÌò)?ê±N–ÿ¦K5@0Ý°IÞŽ˜ï˶½”Ì6˹æ]ªñáÿ^·Ë.ïO jžÐý¤=‡Äëºó³a
+ZÃJÞÇ”ËI)uo/%c'¸J•daÒ×sŽº1)Ž“|>µDsÊÞ®×íó*†:{ìÙüÔ¿·¸×4Y&Ô°ßßÞc¤ŸÂzJ~ÂÔ€úhñSæ|-OÜ¢ÚE&סwŠ8•=2´µ¹‚‹TCeêÙŒí+L¿Í
+E .®;k\Ä¥˜]%]ôv½¢£hüJœ‹±[ ô‹ðZ…‹^\ñ¹ö¾ÏOU^¼«ð@™üšýŒ“í£„u» ³Û\Ó5>•¬Ñ•ÉÙ74pãšÔ:Ǻ¹Ãù(‘˜(DgKâÆñíy}â!ÒD´ûù”&84Ùr™çÄ.'­žÅ\k ¥ÜÃÓ:\§ÉÛx6§©wà°´'Ûä‰iAúð!áÆ—¤ʾÜãMÁsÛŽ©®-ÆŸy²ÎUBŒõ*³Ý—Ž*šñLÊ}¬Jc=¦að€;ºÈDlsâø1ò¾ßíÿŒ—Kr]7 DW=x*þIŒ¡v‘©¼ÿiNƒ b?ñÚ©òD2ÄKþÜâÍ~_â 5À-ùÜ|‹7‹ñ±œÀSKܸ1„©©Ð/^tW$ºxó’Ù(šÚ`6©Ãô'ú%Xˆ=NqÎÒV)'d ? ` £±Ò)!Ç Xg
+¦‘Ò ñ©¨À«`ñ|Õ/5»FŒnR'‹¢Ytægxÿ8úaZ©*P¹x½tyI5åT
+Ol¼¦cËæ˜Ï ’ª63‹ƒâI0³l
+N‡v3‰P®&²°™EÁ–â=©[ ¦Š¶Wmqs~T,⨅ãp÷öKCÓ?v‰{û´måö.«SHF˜‚ˆT?K$æã͵ït.k2çÂH
+¬LIµsãÎ5*Ùih¹4MŽ•b2m+MçlÖÛß &–~J)åãçeŒ?Ü™‹¿û
+î³<a÷OB‘¥­#–Q³È6ö`<…±‘<#…[Y쟌9ïØŒ*î’íU1‚øÀK›ß»ž®9l]õ
+ó”$
+FFÿOJº5Ñ*›ìapû” “<›È,Š<.pB[Á¿@“Je0¾€rà8H:IÃC»àÍ\ÆrþmÊ&H
+HÌÆÈZÁâe—Ð-ÐÊÇ®/%ÿø§àkÒƾÔ#* .` éT÷sLGÇ ÷yJX“ ¤¢m—у³rǸÀJ¸Èºó}÷î/ü(“´Šâ H’H³_.ú‚ Á_?œ?H@‚[íë(Ъ‰ô–~‘J
+cæã\jµ»ŸÄ'~£r‚úƪû`“Žtø»?«7Yá.³üP ‹·KÄF¤MÜH=Ÿ’>ƒ}aF‘Ü ÿ/?¶üœDXá¾pØwYzÆFûÃ)¡Í×p* n)¬)\z—¹2Ô’ÅbkÚR[EÅüD=}½ôe{^FÐSNÊE¢2fˆ ¿-ôÇÿÙúw'¢oG—“ ù@¤¸¡deËÚ.å.Œ÷³OVæcÑ¢#õ£lÌ^E^a’]N²>ª¥bÒ¡áÙ¸Á¥ÍN½=P5¬&ÐAOÈz¡†,;¬ÔñŸ¤ñB ($­ò†Zþ@ YnœMc‡I7WjPš“5ªªÃf/ÔÀ0¸FVèê…²”‚
+9àõf7kK NRñç³çúÅÚãhò'\ófm)a‚¹ƒ®s.“À vÔ€Œ—°ZŠŽÅ}f%;k‚ó*ûS†öŽYÄk†â+ø Ú ªAŒ’ÖÆ&Dš:'€*]žôZ²Ô–‹Þ{¢Q‘ì.+¶wù›"1¶¶uñ®"kÉJÊ«øeð
+4,ÿ¦h%Å"’WÞ¦½*e¡5@9%`UûÂÇÂ’ëOde«Xëc‰ì¹Áø
+ŸÂD£xI†ƒM¤±QW€ïÄ¢¯DŠð/rÔ•]D¸Òß(󘣌K³«tþÔ@Þi*ìßB³Ü½8»Ã—(g<Ý+P€Ì—j !Ý@•Ùµ-/û
+·Çil¸à°£@ØoÞY󷎱¡õ”1–¯šÉ+7Xfë¨{ÎÔèý#û± —Zf OsÇÒº—,FÉ–V@÷E¢:̾æú”òªá‹xÚ<Ì@@cãû þIŠ;ÁŸ½F¿¯—,;r +ðjî“ÉO~Æžz=Uïê$³Ž¥ÎgK#U’$€@DÀ¤_3ÄÐc7ôSuÈCÆO\gÝbhœ8{»ú¤xøÿÇÏŒUÚPö5êl
+D¬F«Î»@ÑÝû³õ°¥«ÛÞ¦BxŒöG%Ú³3álÞ1í+ñ°°ÊŠx>&Á ˆ(á…QÀ‘UÄñÜVÅ#aÖk†üÚBð„Ä
+Ú»K§{+p3,2c)œÃâp¢%ÛÃ~®s¼¬Bö¨3Aq\[ÒØ_BrúÝ#ßßϵ„ Þ3š¥wœ=¨§,£Ä`Ǫu?GˆòÇ]ãúª «Ùbd`¤Æ%€`…5ìj¶¬Û¯kš&È.ää^¯¶¿Á±Æ(œiÁu´ÇÝ`:Å ¬¶™¸|*°™»¾?¸?QYà¢Wâò Ä×4ƒ€MÕ$œm´
+ïé>¬S¾<8˜×9¿]Ý„ÖädÂù–œ[ûê5}‚"¤æ¬ÆsÇÃ)È1Ðú!´n­ZçÖañ¼ú‹öü5‚ˆ® ºB,ËyᢥÖX£>Âu ébŽÖ€ Ÿhd¢É#$»çNŠÊq.-,Ù$cçÍjlžŽl{Š÷‘­'AÊ:¸iæcÿľñ`¹oÜÿO ) ¥UG–ÿž3M¤ð²jƒâª¸,Ð>ÖšpޑȘ¯i¶ýó䯘¬j\jȹ$ä`ï¹e…îƒ<“Õ6Q’gl
+ÉÀ”'$öSŸ{YóÌ ¸† >êsŒî8•`¶pf”ãŒ>Ç°rpÂ^ÞÛ>BbzÙ!ô^)¡Œ
+€Áñ¸Éd^¼“é4ùki
+ÆÛÞeœr˜mn§©ÇâtECR+¢ÇžÑÐ2¡¨"
+±,׺ÈW&ÅúÈ&MPûÿç­ô×8§W¦–x_ §”`îYcòGJÇ–„vù-ººdØí/ÏUo)Ù,¶¥@ z• Ðh­P¾Ñòc¡ ‚´mî#„%é˵Þíƒ×"Hëe•»Ž¤mè÷~ »Žw!U6Êõ¾ŠÓ¤ª1_¿1ŸcÛ­¶Ð» =Fdz=VadŒ_ƒ`DíUg`T¢¾£(ÊxÍ–*kX¿}„謹Vžc˜­,J:µq ä8©P"TcYÿ{ÆàS®wˆÿ+!v×ÌF8¡Îtef1à5B œjöx ™Wy…?S³¶rÚ:G}cŸyŒô®öõ'íB!uœ·Ô„PŽÔ™Ÿ˜ö:9 0úg”ÆMö—â7­/ë9ì±°»)ò×¹† §¦çJê€-,¼eëúb$ `­+ô\õsÐØ{3˜…ðëå5Bêh”ܾ%%f´aJ[åû¥8‚809b÷¯¿W8·9FˆF¨¾5ê×yc›•”µœQHKOÁöÙr›=·¼îmÓȹQEêzgˆ»Xæ
+³\n•mã¹Úzø-G`üO[äîÔNª5î G† ­=¶ic,¹é3¶FHkèŽDœ{Yæòrbjö6BÀJƒ³ijÆÚsÁ¶â8û-ì#bAÛõ¡è]yŽýT‡ÑÚ£«¥¿Uòßÿx{ökP­QZÛ*6™AJˆ’™Üf”š2¼`4\F7†"!GÏGÒ½¶µ›ªýÖb»JŸed6È»“®uÞQe&<“ûç¸É7gˆXr똢ðâx¶lt5‹ F(gB²Óxvdo„HjÓÄJþÏ—?:˜â¸
+[Ú‡sb¶-þ¡ÞoFEˆq&+~ÜÖÇïö±ÔûXWýo°NH§ðq La[s/‰äé¡Öˆ¿F ,ŸY¼ÈGÿÐS+K˜‹ènOú/AŽõ÷;⼬QCØÜŠØ&ÎöxNCcï» rh=ct¯ÄôøBk+:ZAC…¡ckµinG}FtXÐÅ ÞYÁ¦ÕJ实Ñ<çWB€¤Æ³…GgÈpé—S!±Ía?LT^BþWM“F¡Ö "¦–`}œÓ7·ÈÿjÛwQãê®@&!ÇÅeÐûŒ`4N©“´cL½cz6 H赜ìΰS^me®8`Þkù^>¦WkV«{>‡Ïb¶Ž,„ç‹Úë)ŒC¶±¶ã%$™“PLbÜa¯,²Sö͇eœ³ïêbL·Ç±ùœî²ù55.Qü4< î½X*œº³B%¦ÊM‚N³“•Je—pHÛ´ ˜ÿ(äØóÍÀŸ«ÆðV0ðÉ;!¤Ìƒ¶,
+Bú~ŽsÜvRB]<fÖ ¡â†!V(ÜgÍüãåŽœ× Cá­h’à³vJïB­½ÿ6ß@Môëj♑ ]’
+™7Î%yΛ¾AfEÑ$½»gg8*µG!÷Ùæ¨Ñ]QUn`}w5oK½§Ù×ƪe S¥"
+æÚè¡ò¯1—#š6ÙPT‚ƒéñXgy;QØŸŠ¹_+ÞãYÓ}ëúüÙ[ÁVö¼¤ßêÒ|ÙÓ-Ù¥b"a®%ï%£ ±M½‰“
+TÀ£íØíÓ® Ìñ’ý‚ŒQЖxéTÚ Kã3iºZÍÔNð&»³"¤é”Û/âi䢧)Ç5@ø9#/×°kÀ§Ö(Á¥p#¼IÏ+-ù„Âxùk«6„V@Ìîï*
+ ü8-M û @TǶ¹ŠALS|÷ Pï>O&[!<ÕfÙ>~Ë÷cXÇY|¸Ž,a}±^ì~£9O(ˆ÷{aÄ
+bGã×=Š8ͳOùô‚µe¹÷òÏpDf'ûàs$i
+z±\º(ö% m˜zË«AÍ“´9$1±±Å<»²+âÄs×Ûó²/PŒ?g ëw%Ÿð Ô[:ÍWÞy?×·ÿGÃþxìûÄ~ö+…Àˆ çL±¦Áõ[YŒ¡íD4¾EªM3TÉp¦Ò¼ìê2ºÄhä>ãýÆPùÌ‚KÞ¬¬?”¨‘ibZ'µÂ…çåpv¿×X¡%SƳKãÏý°ÝÌŒ=K {*š…gq—)?õ;Šð¹
+F<m@f?Eèˆiqti(EßïIUx`5Z8LºSX,YŸóá#§‡üÑö’!<áû¾ByW9*:2î<ñ|¬5O Õ©D…‰Ý‚ž†ÛµcíG3ûD ÊÀAðR,æ¶"v{?ø¢b¡
+-Xo)|Åæ»oy“ýhp×j7h~iJ¦Ð„_„ÇÏQ+&aÅîË%[
+:â¶àZ4´"ñŒ‡7øÖ%'£ÄÁH—Köf™X‹̯pÖ'+´wŽ
+1Š—ৡ§e×l“U.Ñß.oŠ+° Ð¸ÞLòè×äæÝ_ ²‰5JÕCHy:íiÇS¨$2V1i²¨ ê©—ào!$¦«3œ09ô¹^NR˜©f&Æò[šzfqÔTÞ"@¼íêh‡‹%Œo!1®Dã€h¹‡‚‚âá/âAS‚ëMP°lƒíc<Ñ d˜¥IÔW¢Â´DWjJ 1¶™çîÙ!*Ër
+||ü¢|C®YñÉ ÑA® ôî¯Ð&SFªF¢O»ƒ!Æ÷9@¥ÿüš%®éÌ9@`¡¥`lyf¨º
+n·pã|­xwá;‹¢¢=Ö©¢E€qY…³¸¬TÛ^B
+À¦²´¥ä$†0‹-jÍ{
+0~Áöùá=7Œøˆ`•Zö×Gª XNÄÁ¥ BûMžq¯ûÓ‚˜›fÙÓÑøº.F‰ëó&@’ô÷@ÑD˜óPôÛ‹àþC7Э,¢‘<ŠÍ’<QR8ˆÎ’”Ìt·¡i½‹þ@dST¾OÆYL_!dN_XŠ0€l<Öú¾ŠÁýù'ºjþ’„üé¥äQ¤«Â €*Ì•¦Ý<Ö”(ùyœhÏSá±I"8ÀíûcÑgû®”ð˜üè̱ó|–œx—£¾P{=FŽ‹ Ë5(.ìûrVb,Qé‡:I+W/òþM+1U ²ì‡ û‹%”€ßWî #Ø¥ìe<€$öùV´…Â-ó
+®†a¡j?jñò1q·çtËàXv¤)¢5ÿŒ‰"Ø2‹%ætòyÖ?ŽêvP àp}cgWÀÔzú› m˦p{¥ž-ÒŒ5'tp½
+{]æ¢ï
+!4|k¬ùAi¦BkYÄs«ï7þz¼òй.QæôV "Tu%BtG:Ë~ί—,±i
+ +`½‚KþH3eL;ûŸrŸ,÷ ‰s
+ñY¿‘Ð’¨˜ñŘ­.Ò³¦·¹ù.¡C½Vœ·¡1g;
+D¦¿ÝP¸D]tqµ§Ûì´2KdûZܧ¯þœ!hž¶ÙŸíâSÝÇ“û€1îÂÍùô ^éFœòùÀjF›’þÔ1+Œ;§:ÎUgM—<ö»#l¼ŽÆCnõ-™¦wëè¶ôÁ‰¡©-÷~•$l!GARœÙUïƒþCd¡Š5˜ç€:$5åeßÿ{Œ0þÔý2Žåœ¬
+ñ½J¼ù‡\ Òïnk5¢K–F*5ö½-¾q¶Ð”ÜIÍ"¯æÓWðagèÎb—]ue”æ=÷—¢ÏY!û&‘ ìEOøø¶<ÌÄGJZZmÖfºJxY#ŽÏWßKTˆÇ!3eWg‘ÿÅ•Whþy»Q3Å=VÉ•wöøÏãzƒÅÿÄ{u õ`Æ–òœ/òöýµ•? ”{à’ôjYœEÚxCº®Äì#¯^Š6ðÕ4¦‡5Õ¤ë'ŽòúåŽèOH ÅZç+Å 
+¸'Ôå¹æ-">
+ÏߣÈõKÿðyt3n$yC‘‹à) ¡k…ȲMž ó;&Å„Êù+BR›-4‹MkJè•9³Oð±ä¯'wég.óç<É@Y’|ÜYá`_ZÅ›“ï²c Í–4adc$ð¦à–<¼rD\·¡¯Ie¨Ve÷%d£"~5±ê?ö õ¨ñì°¯Z‹8Y»r=.ÿ¬Á?§tLüa ÚŒ¶üò›Ú0†C.Ä帧𳪜Ž1ÄýEÏ1âŬÑ8Ε\â’¢pZz¦uS;|E rîγ 9Ší7Q…MÜÎåˆltÏÚØÞ!ù˜ö%€ñ
++N—]M[úª ·~Xðµ[{dçÀPòSš$±_7%ãÐ÷àáë2',à…¬Ø•Ýr0À@ V_\ð¸q
+ø÷ìÇ{‚T„µ:FÓM\¼öÁÞ¹à>K.
+Ûµ,ÿÍ>L^§D Ë=æïµ®Œ
+ŸËÂÆ'°gykK òŒÚàïv®Ût¾ }ñžÆ®ˆLÃPBmÿͬ®œ=*Øø¥³½5*z„<¹’íÑëáøóÿ€ý¯eõ;?;nI³Ž¥5"Ì'Š}-“¹D²„v~(Aêén™Þý‘œ¼F¤P‰xbi±-oÄLø€Òß>ew‘dn·[ö\;EÎz,áÙãïþ¥ò){Âñ$…˨]¤1â°÷))Ê;¹Ä†-VQõIk„«ZC?á`K6ñüc¡Õ^â &/:˜
+vµX> ÙÊ]B*]ˆÌ¹ñkÉ¿@ø÷oE5q¥ÀTzhg?Á~Óˆß{o4.L{²¯ÑD·a8}2Åaö8Ëìܳ?Ÿù1¸õØZ<ãk[kOÚû¶Ù ´“i¢êAR.(i߃\ïï,7ÅøòRÌ"òf³ŒîÌW<Þí‹ôt¯JŒBx~–x’­—0ŽåÓ,¶„ÄöQîsæÖ´Pa¿‹bl1Mâ”;|¼/º¹/£Î'ÿ¦ä_XxÒV?îuçŽö ñWýúž‰–h§;±!Û#ƒ?Úf%ù£ˆw ‡Ñ^<¼’MWÆUV‰Žú×â£è¼ÿú–ЄñÀä,k^…¢má0üPbÄ-ÞÍ Çš×•’teëg‰¹…fcý–›e %„c>5°y-‚Eh3±d§Ïyµ”)D"êeUa6¹rC£
+0#A*àh £R‰ãµôFžˆ ÙÞ{5~ʇ5Ö¯Z}‰‚!¼‹.o«Æt‹•m
+Â
+°JÒª ÜNΓ»
+(ŸCäA#ÓVÔŽ›ƒMTaÍ+~åK1ˆ@{ ³+U"F‹p þŸ&X<;‚<ukqëM¯ú8ÃÛN|")"-´üP2nSg'o’Çóïä’åm÷§"³!v~:%΀ΠU¬y“½öx³£1›×§þÕ;Y4ñ<­ŒðêõÁŠƒµáSÖé­w¾üË‹+Éõ„+m­È?†­,ƒ‹–A?#¶¾Ö¨õ?—4Š8³I©RÈÏ4M™7¾Kïû%xŠÞFà‘>aª -u?l˜¿‚™”„x|0æ趒ÈÕ;èÙ¿( ýž(…–'@(Ô¹µžÞ_e§Žf%Ï#¨`ê°`¿ƒÈß÷,}”ük·±7¥Ñ•<"=”ýÁ
+þ~凢#ZÎå->æœn1‚Má÷‘Þ”DÖ*ç¶O“DZk
+©Ë†y¡Š@ç©×éosuéÒ
+ÎíŒG óÇ¢ÕåÁ'+é€Nh¬ôiò€æÒoÉ)jqèHÅ´vEs¸ÊšÙæwF3 ߀¯¦­ã¦ß2J˜ª~‰'¸JÖœ¸QÕtó_>Eæ€\%qKoe5”¥ib(çEÒ®‹ê¢ÇD¹/ÃÑ…†Žá îµ:g–†Iž•MÞÁgËÍe쨞¬ò2gŒÜOôÿ¼ïþ¯T°Íî+ªuÓæ_>Æ–è¯õF=î´÷‡h6›m;ûC <âuK< À÷Û2ìU¯g|WJÀÝâp173KH¾ àsµÆÛ*Â…žX†ò®Ñ0/Žssg~FëØgŽ@ÏáùIÒàÐû(9£J‚F°5ññUì
+¿¾dø1u¼ÂL.{¦ T½JIä?[à\I*gR Ü„ 4Ý
+_ò¢åb­¤A7¸ªÞ¯E Õûð.`= kHn#Ç)r³<Å’ÔVnâjøtŽ"K7ÿQ^¼ÐO€$m݆F¸ïU³…õ¶«˜ÐóKõzz‚Ǩ2Z“H©¶…€æQÇlj³éK¿=(C1ú(øíG!ÂG·h‘WÕ @Ïjì¦S‡ÖsÓÎq–õ ³
+$³{}-73},ŠÙ
+‡É—é† Ý«Ã架N?€ $jPâÅk(ùõ¢(AdÏËîš?Ír0Ú2iZšÍ0
+ ·‡Ðo%Ë@ûa~µ]%áÐ$!d¹õ×Lh‰‘uÚIÈ­}IÂXmL)ß6‚DÖëÔÇákZÇ«(Úš@—ë»>ža Ü\F‰%¨·ê²Ý*›G²
+k$éz8~h<Š…Np샷ˆ†‡l1E[vAFåí’… ±=c™Œ¸¥õá/„5¦¹Rá)òh®ÙÞÅÚ`øö
+H‰Œ—Ar¹DO ;ô¦ƒ ‚Xû/çŽø+ùþÛyÉby!—#4^ŒÔÊ& ‘HDvóÞGõ×?óÝçŒê˪Ò^?>|½}òãUÝú-kÃÍFšÕëßÏ·ÍÞÖìѺÍõ Zï0®Yµ8( ¯wóâîྨÞe­z†UÄZe½ŒóÚÊÐuöÎZ6‡½>…™5¦åÌ>3ç…q›
+¶2<^ÑÞ-šqMŸœ}!úè³–·œîB8IoÎýmÜ‚ÁýõóL³ZMŸÑ&-s¾øÒïe5,Ú̵ü¼e´$šƒMè$j¯¶îSr6ZËäS]Å'³F>m¬±ÓÜß$¢÷ÎñTÄš¡¯•B 1y¿©¿ cÎn¹âªúà}œL½Túë&ÞNÔæ#WÛ ·ì¹T-“V­—[e«uA’|ÙLó°ØAqDõœ«— ñF™ë²sÕHò™„
+WúZTRDá©sàßâêeIÂQ+’ÚÁ‰–ª¬ŠiúJ™]~o>(§ùºJEø¥Êsùoš:óíKçœÐ™lÝJÇ5Šµõ³xZ ¿Vˆéˆîå´Íÿ?ìõ¿÷·wáKiqÅ–Õ‰5´ü%Ðœs4_zAúI@£z­Qæ/ <¦Yõf„{ÓL=ÇÓV¾<Þ­¨ ‚qrí¼ÑI]ÍLöéÐ>< køU3¯².Þ4Õ]œD áO’È O=:¡%€0ôÔÑëÕ|Ó£c¶ÆuÜ–ëœãl‘ºï¸F¹1Œ¹ Q 3© ÞgóÖ[ƒÍ‡‹Üâib(|
+`ÕùÒ¬0=¸ì( Ò¥"ÎNU^@&òByœatI+#(ç‹b@Rk%Ê£è<¿y01ê\…¬L˜§sPt"5\çÐÀ:g-õä!£¡¤3SJQQ8¥¦µ[Æ»bUàªZ^ùKl‚¨Â³¯® ¥Ì JÞ4q7U‡Ôˆ©×{;ƒm aÛ@}Ÿ¤ç d‹“—áßi{
+†CáÆ)¥Ñ<гϵ¯*YZ\ÅYãØ¡ ]5Õ¿?t•Ú†2Z;óˆúþVDƒH0€Z@£]LOœn`V©â€°å©ŒÃ•#¥òý²sý¼ù»”„€i ©¾ÓcЗQ†ó»÷…ܦŒž%àóf¸º?Ì™Ïï £™[£x
+”Z+©îÏì…NM¦—b'ë8O™—´‚¬ÈñHYT ¦0ïR_¬BI™©x Eç
+ž± j™®(¨±Çj¢õŠ!¸f ¬~TÚ=ô
+vqË¡Sdf¦œb¿#Ò¶©ÙT»s°¾•eز¢ˆ nè?vÝ„© E©‹óÊŒÄ_¾†뜒ï×"7Gsdö䦱ÿH5öCÞ¿àì¹ê ˆš‚†·^jž×Ãk€PF ¥êA ²a;&¿nú’0’OшØþš`A
+—B‹ÒpãÏ2}l>”Ʃܨuh„Å ¤#¥MPÆøþ$ ñûÇ¡ËL\ÑŽªS8^ëí±WDí×â%úvòMÈúôd%´³p&Òýzèå…^ª7ãà­ôãê8tx,™6úâÉIÐqx{œ*3ŒÝqݦ쫓À†ó#Ž„´gõg± Rì'cí=ôq°~çM[,ì EàRW¦ÆY,GBDÑ”Ü_á<î(ËcÍ0†ìW‚µA¹G¿¬ŸÁyM¦–¢Q¡Ð΄ dĵ,¬hµ|4&’6š1[2Ö®a £.š˜OT‡§x‘$ðbž¼!¬Ü˧ßϾäR“)ïr{
+Ð×mpQ0Á†6Âë*¹$V.‡Å·åñò*œä\E”âóÀÝØYã‚(R¥eå9:€µà?Ú˵·Î£ŠÂ¿àü‡÷K¤¤Ð“¹_@|ˆ 9T
+Dµ„åÄN0=¶‹ëù÷}Ö̼Nê3Ž ”Viã}æ²g­µ×r:Aë 1õvˆXñJEº9ßäz؃ýÕ©H!ôu`5áé%¸ºHx¦[±
+‡È¿Sf´û5‡³{KâšÓƒû GGQ$(ñ­€èÁÇ{³†4D–Ñá§Äµu%¸ ÁJÛ; uL……ó˜­È ¬ÞÔ‚¤f¥H•Á[Weç…ð(Õ)ðÞËØpòÑ‹I™xU0Fk%ÂœÕ V¼ ÿ0vAÿs+‰P<R>|'š]s`h%b8#6ÞÎá;œÙµ"™#€ ƒ{ 8:¹µØ°Ž¹gM ôê=åíœ6¶
+~„± ‰ì„Aª&ˆ„?åNFÖÞƒ§8Ô¢í¬‹k<P ´Š
+ä¾z³1˳³Í?øs‘ÈU½&¼§‰
+󚺱ü©:Ñà¾KM S[‡qÉ…6ì%Lã¨ó¥•°‚o¤Êƒsp41Ôž>](B>Ù
+V­·ú™’ìzQõ/… ØAM‡d-†Y¬m3´½àQÕqs‡d
+µ™¹?å)ñ’€Ã-¦^ˆÀ„gÝ=žƒ"`ÏœKÕM½ %ò;Ò~Z:u@*Éše9öñ<±[1oAž¸ ËÝ"§0ù ¤`ä¤A¦7Ñ…ÁD+$¸}úz¹wÉ>ÆétH[
+6"êù±×(`J?1^/ÉnãH@Wðö  ”‚ ‚»†ž×zRƒWµÿaŸ PÝa;ü“S@f"ó~&§O
+)Ï€‰ÑZ®A}Ÿ° F­†çnÒA!µ<¦s gŠÏt#P9(â ßîˆîòI¨£q+f« ªA¥ÎðEPÓgB@:ÉàçP%Öži_B05š1ÆeD„þu*ÆnÜd+ãBº!©ºH,÷Mjsç"Uäcjƒõ`ÑŠ]ÍŒ
+ôù„âl#c@ÂqO÷Ü!ô6``®Bï™~ÚôV¤Vh Û@-cÚ¯ÂI¦Ô¬Syw:…P¾½PÝäªõå/x
+hìëxùªà“c@mâKkôd— t*§&‚èë}Scq%D&Þ+~-f†³M×ú1Ö‹šÇlíb)üìÆvö€pÄÓš‰{´“rð Ή"\–’¾–]u®p’ŽxIC_ûmqÙ¡Leë!ª
+U%w6e|Z–í¾j]$¬É+ÈEWöʾô(†—¥¹Ý­q 0Ôòë!šrhq¿L)A{P¿áðò2p«Å‹Š L$âòÁHÚænßÒ7žQØu«K:$ƪÁ’rÓ!šjVµý¾ ¿ø#¾Q?%iì=G÷¨O°U`G¹¹cwŠuRÈrŽ#:ðçBNÇF쌇¢ìÀªí”Ôþ¢xÍŶ-*e¢T#BS â<êÂß5;EpÜƵe·;’$?¾þþúëë߯õñçšÉ&ÉFŠ"g1ÜâI¶Ç?Ÿ1]ä˜.+ë²=~~äg;Bpà³t8 Ì+&ÊCK$AX"kfàêö‹“Þƒ>Rúþ´ÞEz}౦CZ`Ég~M£99
+þ¶”Ìá$æ»ÇlÁó€ }%d ¹lS1Ѻ‰2g#Ää+è2þ:Cšà:¤MЀù²]K„ñ|.‘nø öôs¿Yñ=û)eÃ;yó‘ ôѱåЀYÈþhg˜—|5¢“˜ïyL€6ÄE0ÔÇ4™b—ErtÜ4‚ÑÈŠ †xië3ÊÁ»»Tf$H¯H“+búÖ±±18Þ/÷¼OÖGˆ‹*,6ßÙz¯ÍΩ«Õ‰ÂÔ¿î^$c|°‚îÔ¼\BàSé–( †”Öq`•ÄîW‘ [L™:—³ô ×xX¨£+ó4x•Nʼn‘7 1è¾Î\%^BHøÚÜÓ†¼]òeyóüó•ÊMÇùŒ;””kÆ1Ö%"’ºr݃*4|º‰,²2B9TP$ÔÝN—“³ÉfAœ”´vv!jò{Q‚Ð[¾øSÔÙžtÄ–Õˆ”’r#øTg—d‹ Êá*6²ÛUþ5ÚaûŸ“ˆ¸ÕbÔbÍ¢Z§Ç Iÿ¤‹ƒ¶ž ª
+yÞHIÍ[J©Ô^S± œ%©K²q Ü6ú M‚¾‡Øå
+j-erÌ‹ð×½si×4a{›)%µµiá].PÁÔe#ôÞl€Ã1ð'ûýžL"x×%伕àȤp5Â‰à•°ÉžŽ ŠTìLëÂø#2ù„bƒvrÈ9…z‰YÚ¢iÙ“ÿ²]'ÉÑ«X€·â T†B õÔôí\ß¹"ž“Áß8}¸Ýiø±Oœ)1HøÌýýžcƒõÉ Ý%Ýjmîƒ_Y’йœ3¹ËA¶yéD†'ŒFÿ´+f„Õ»G7‡¾ˆvÁœO®ºbG êí´† âD…ô¨©q†!·ºËèoœhðë7ÎWFq£¼i—»iÕ+Êøj» Böc٠תÜ`ßWÄA·1ÿÂámÄ¿°|ñ‡5èë2 5_[ÚØýû®mÈ¿¼ ù›÷WÐwù
+?ˆÒUwŒèŒg¸JbV×·îZ ôü˜nËœ¥$pÑÔÄ#€|¶ÁUxÄý#ÅÏyÞýÕeõÀ]+GÁoRä¡áª“4ëÓÀ¨´
+“Uq
+•á;Ƥ¿YXòÄ—ÆÚNÅR klÑ'ßù=ÂSÒ–œbDÓ”üèA½Fìñ#bëoÀâÝn #ÒôÝ!×'.ï„Yäh}qGlïSVHTKC†ÎÎŒŽàÂM+ÛŒ§ ÷¥Ÿ› fPweʘ¥±»¬ª'iÛz8%ÞäëÅ´M#òÁÖ“Vmó.`^Æn†½!ÿžR(›ÀƒÒº¨ïž"„Ù<Ÿ'Xñ³Ë»€-jñPÁs¶i—w¡´<fÁÕžuY˜-hÏyYá,ŽbŸŸ8†è[`< Ô§û+êûc-Ýœ3s%~΀#®xz‚Ø ¸•ÜZ¢®Zïñg§œ•qFÙ…ß–?$ ¹ÆØÔ©B‰9 úíÞ\LA@ßÀ¶ñÔPŒsú]kÖA¶WŸâÞ³=î?§äýקx§Ñã5Ö'c¸=ÆFAW¼O–k=µè¨%³ymmæyh06ógIë+~QÉÑñÿ— S7A\¼&ù–€Çmw|,ö]oãëîÉav—9´¦¬uEÚæu{LÅA(È#îõ8,ë ´4xÒÈxñʤ,ÁõTñ(arF ‹ï×”ëW<«UÛ%õ7bqG„‰²jmwLÚ€6ýºöIÐyŒú¶š,[I›¤¨ŽJ˜ë™ž#—rší(šï V5õãðúî² qOÊ3Ö˜~=ùk7™Û‡;1V¬—±=Qu¼NŽiòW¾C6íÜ©W0à¶Kå\ç,6È»¾B¦h”óiÞé±s£ÂÈO ÛÄë`ÜÎyʽKi4‹½ùXº€Îî'<&,Ÿ•Ñ•Ûˆÿ #IgϳZGÈᑸË;xÁ—àzè7Ô´N”ô;€, Þ,„V
+êK{3¤Ò‹GÌ㯠œ¯Ó}j¿|๗’Î9Z!ÅØã;q¾WH;0[ã¥zÉŒ
+Ýñ5Qpë&6Ôæ°îÿÅ|sö!Žâ½d‹öŽö†˜µ3¤ÍehT
+é™’ÿtü^厹ã¸oÔDB².l˯ò†(9F2„o3•ÜH´,Äâžl/Wx½7™ˆ³Ùêç«7ºÿ*è³`@ˆyÍ6˜’W·@ˆ˜@ãXã'iìLÂ#²£ìMþL1qÅCÄ ýg*gïTQ×t$ª8dñ™ÚæM (Pj”þ_÷¼ø?ZaÒH“šj-‚µ‘ý¸¯%}Î)czŠaÀ »p%eS ÐqŠO8¿G†ü°a†úŽÂ'¢úŠÐµ|›¾:§œ¨aÝ®¹÷=Ÿ‹m®hÔ0Ýá½ÝÊEÝ;DzΰÌRÎÈÐ3Ù °²^^}¹ÚÕ¨*Õ¥ùæUf¤GÃr9%µC7¶¸G ÈhɃ„âzö9ÝŽmaỂ0 p»Û•sÉaÐþ Õ<³º‹Ïòêîº,$¤W%tL¯y¸¢ƒ¦`N#uGÅÌzL´[Ýæ½2€z\c¹¤ˆÀ’!V¿‰G‚ÀI\Så“ëØ›H
+=ž>!kÆI<¡›H>µѕ31}²Z(i.:É·*m(çGMˆuÚÈ¡0‡±ÄÐÈžý»A®)‰š(?JÂf‘92
+MgcÔ>/´Á ãœ#UÊ7Áj‘v—õn’‹9¤l¦pŽ Áû4
++Ûjœl^!ºªIÚÔ°lE"ÞœI1jSs¯ ˆlèŠÖ›SOˆÔŽíóTÅì¶^Âh!‰&´
+Î7˜ÉýŠ Æ“±†ÿR«î2V³ÊN dú‘ZWÊ׊»ÒA
+$SÊóðÓž#²eÑ
+Y¬¥î‘¬=!Ìù–öT‚'D
+âG–KÚ¶¹Ë" #Š’RºS¾1ÅT>xAž„ãŠ?‡yí"ëå³aÞ&¿CøÊo/d*÷VP!ÌTÅݵ¡Sù Ž5œí•1ô^ã,XÑÖÁT¾÷‡u8!¦;§c ™<TX•$vMWŽ†E¬²n’ÿû§Cb o µìKÇ|*`¡ê‘Ùý\ÆÍ;6{´ç2øny®èD¥ñRúÔ‚²Å“£[< 3"ˆR:N†çšYz/ž°‚Ó ½Æ»ÈÚRø`­pLLpÑB WÙÌ®,iÖÞ-Þ£,^¹€O²Ž½À*0Hbƒrê]ARÉ·òëØLDÆÅ?ÔòQkywŒÎ$Ó‡-ËwýÐ-4eO-0{+þ>Ñ0¥¤H_‘ŸzØ"â¦ý"”M€1õHº yxVìÐâOûvZdýuˆ¿»Ëdß*3ƒ±šr]WÂ7jÝe~è¨$O.îídÝGt‘™ÈºU}Ëè,_6ï‚¢v1>ÌË´e3^Ô%+™°­õ bŠÒN2EùK!C„ÊV=/SxóH„¿„T(±ëODeƒšiÒF{|¹lаI¢SXÓ% ˆ®ðbß<•Aj±èÎÙ=D•CïÜÌz‚ð,Ï`í_RÙÓV&¤¯‹@YC³e Ÿ¶sT¹"Y4L Î"üÒËQå*šßDš°¬Üz‡8GuŸs³Ý•Œ ¹k²A?ŸærT÷û^ŽÊ5“/(õ.§SÏÄ«™¤´å.Ù]¦v‹=Ãnl›² y—n‚ÞO´ M)‡wÐÉ5âÈ»ŸÌ:›H×a‚:í)lk+ÜìC¶¹Ü!wM6hÀ©z; âs›ÒifÙßoÓ“–|J|ž"zâ騡
+»xŽQZLǤǃcê¹RG»CANµäF¨}J@D5«~˜øAöÅ.íNÆ]«T€S?„ Ñù**#×áÕOá‰W´¬mNÿŠ .ÕGµ('2™ÁrR1ÀK¹âHK–måœî%/Ÿ‚‘!é ‚å$/Jy¾!C+ü‚{Be·Zr÷¥Ç©Àð0£Åy!Jï€G¼ÖšS‡@0!­³àU vPu édì[Ǭ"ϵ§D¿dÔ>ȸ#!÷a{Œ%˜
+dM¿ègdàÚxóUCKÅÄ'퓹:bB°¡fž¬šIµé&±Ó\" }ص«¹!ó9†ñcôûÚ©AgÓvùKÈ q\Ð ¹:@›V’òËÚ}ƒ ƒ§ÌmÉ!¹ ¤¥?Œ =v¶ÇÐ…ŒÂ+Xÿî’1!wQ6èÅ(dªù@?«þûýþ ªìÎRvwâ…•è‹ý¬-ñWKŠ'( éºàÕÝ¥.©ˆÎ‡Ë؆¼+7AïÜÒ[ôQ¿'rHRG„ã´úE7±eø—Ñ;[Ôs’xÂgàäwº“q!WQ>èÇãD
+XDNNÅ<q„$9 ¢j/¶Ÿ\Š2¯»ÃoHf'k=AüRdņ9Âê‚v`ó,.eò.ݽŸì¯Èë.¼®Y.´:¹!{9É÷“ê> ¦ßÙ*!¬é‡[(ßå]2&ä.Ê á˜8ed"s‰$´úó8Ð:?ã†À!BÊGxÂÂ=ûÛÆ€?t¿Qg\…J@¯n´1 z¼cd÷bþG㪒ˆEÌY|ØÅñS!"ByTÖ¹êfÞöÃÚ5™Î^‡e$—H†*8†1¶`Í㛦‘#6%•@± 2ÂŒ/­#Å¡3¦Jæ/dWm=Wïõ:žsÐjˆa“ÿâÝ`&Ðv’œÛÐ4Zžæ“H¬ |³ýí“¥+È™7ôÇÐÁÂáS»aû!¥þcÕ²=ô™ú|¬­%¶l?OŠĤҋí$CÄíHcÞTzÈ°ý”Rl<Íf5 TÛÏ™%«ÅÑÒ‡¯¨kJ€¢«++<u7®±Dµz¦‹ƒ…òl9•Î"r‡]IÀxä:â¹flhê1¥¤©Ø0 µ?Óõ$ÑûœSø‘9Zm}£s$;:G>âµz.èµÂ¨}1#o‰^¡Jß@0C“fI–¼j÷|öct$j¨<wŽg¦aU1ÃÙ&rWeƒ~ ­Bj¥bjûv¸Bö‰`²16¿áäE³1üSÊŒ÷;Êö¦‡„¯ÊgiÜ]
+‘œÃƒÀIŽ|È»pô~@àM̨ohV\ZÿÈ®†t­ÓA¿®ü©Ž)€®–
+É‚òÜOÒ¡PXnK¥žFÖ ×—(‘GýÊ
+ªgíÈ©£íEu¨òµXUž‚?ÀV
+©´¯PˆˆpdݾL6YÓ„åѺ´œ©êr¦4¡¶ÚF§! í9`æ@ô³©´'P¸‘
+®”µ"ý†ÕE-Þ©ÅHõZOúNÞÃí»Ä€ÇÙ`BÎr_ïtho ²dœ¡¬»Ã(i
+’×µ¹Îðbì®Ã”!@š\°åa¶åRzð6jn±.ýÚ©B¿P\;ÅFÕ9üs–ÐfpX_‡± QD“™%žÄ½‹¥ëYbòØÐîm½¶Z¢R>‚Ä׳ȶŒàmE'¡“SwBë_Ía+{Üo|é,I~¡x…ƒÚÏù£Ãí¨$҈ͭp…äºë¹¾^³®+ìyøÄl§ƒ²ò„j}Ám$FèêµÕv„‹s©—+ÛÉp¼Û¡æÚj>•ïMx=‹å3ð-ÕWÐû¸Ãâ&,
+Ë9&r;"02ŵ‘|„°©1—‘4»†¹ØîøF®í±ì”d¯íŽÙ²“[BOž
+~5ØÑ-#‚¯
+Ös¶$«HWŠ­‚Ø`wCG¿!!§¥Óšµ% C×]†/ì&.°É¤ë$¿M˜¤(k¤ã5[qù AËfs­X./±ÂámÑáy–= ÜñÑú"‰#aXš¬qmåâ=ãw‘Z–zó˜1RC·ºJÀ¶dŠ<ðY‚Ñ,ЯùdnÂjQÓåÚ*™Ì”r [}‰/¹iñË\ÆXŽPh4ïâᆸæÑ×óÖšKëY#Ó}CùçN!oäg«öÒ—é½ @Ÿ[%ʉ‘É å¥c¦Ã mÎx•Èu{ÃbíeL=!²ãd‰ÔØ%ø-/å`»Œ,YàÃÎed=êÝHk¿Jjø ÌVw§ï•w}žY´”íj_˜®€PÀP¶¹÷xˆk xù
+ËÓÜ;BÛcíÌíî9ÇšaûÔÍù¯˜îycYË4"qpGŒT¯pgjö6ÝËÁ.%
+x"pÛVašÖ¾×- ð­äËCsãÿ14ÀQ·ë0W ïµÁTÒÓûiÓ7L²òôôöæ3jÝ3ºq‘·7Ÿ5Ä Ó&º¶»½üQ€4éïNìõÖ¸>?Ü{{qîBÆá¸cZð÷e@Ø`ÓLXh&q¡‹ӯ̒ugâæt¹ÔZ Nõˆ˜±Ï­ª`![×Ê¥Ü2­$sËL­0êRÓÎò[±AXˆÄ'B¶Z¯¬jp&ÅãÞ ò¶5îLˆrõiTY£çãƒxê%_" Žv’möPƒ13%Ë3“®8拇l©Ý’@šöd«Í›Nm;ž0a$`[[Ë”ÌVSƒš;–Ü’›ÈjüÌÂ|~üóñëã?ŸþúøËc|üáûõQ>~öõg_çŸ= ÄÌBk²m[t
+\Â~@óý[ ‡€ðÛ&c¾×ürÖ4Bë×vé+Ñ&5^(E=i-Ž^þùÁ"X‹IDÉ9€†ür{«‘¶ýå¦èëÜí—Ç?ôâOüôßÇ¢7|//Ùi WϹ$±‘ÿI¸<GÚaœ½e^å‰x±·"V…²H^û:Iu#zÛ>‡Ö³ç,ãZÜ£œhI%HpiIQŸYǸ»jz¶üdÙ• o¢j®imúí†à…Ú&NèëRñÿ—ü‘#c!~´:ãB4’­ E#ü%´e2ã¦ä‹­àÖŤî\Ëí:ÌYÕ2­kNstÉ¡Ä]·»Fä”çÍßjÈÚH’Bs^ú}d•û<²ãuàB¦„kËi€ å9šà;YO 9 ³ýËÜ|Š,~XîJ¾ÌÃxÓªöq·N8m §-6ÏÀžåÍI¬÷6w%âWL ’ÞÌK|óMÑñÌï#|kR¯ž}×hÖG•&ôDÚªW·]ã{âà{É—9îæ urSÇLïëðM2”‰mkN3žŽÊ˜Ën¹•Æš N„·Eä>¼‚›×IFÒ˜Á2*{tãú4ÔÞ¡ïý‹ò€‘k3Éü‰‰÷"À(¬00K4ÿoàHÚJƒoaüéàódŸo敶S¤7 ”¥Næ8¸@fqçØÚd-\Ç2ëÌ’)Þæ4†VZâ_;yÍ#F‡ Ï2*²ìËL>ò^’— e;{¼íCp³µ*žõÔ—ÏŽ¤· ÄŸ`ÞaÎüAõ÷hði^Àg#¹¸÷˜÷ϯøu6Þ7£ ›C¼†·§Í‘(²X¬‚¢ôÓ“Á‚j”ÆÔ¶
+B*]Ä99¢Çs4^‚aìi½‰=›—ÓêÔ‹ÁÖ…•}"÷¥ò7Ç=DWÉóÚ0;+¿„çÀ •¦² ð €nd;‚, ăY;>…Ÿ÷S˃íúçýK_Vg. ­†/a¦ÐŒÂAïîŠT*ºìRÒuï†Îæ­¿ÿö¶Ç Ì¤ï´päV• á¥( 3')lnIY|]J4°|7†Ã 8P¼ 4ŠZX2@ÕgnJ{MÀT¥'›H®AÀbäÎÃ2k{vªÊÎNIXª!Ž—¾‰«dŒ.Ä2lÔ»Eçdô.?r Åëž5òèªõ€ZƒšÞ\)r¤ëò«¶ Ê$).¸EÙ€ë„ð $¾í÷Ž~
+Œ_Þ~u&QhŸÈ”ÐîÑmèm Ãjf9?1àé«í“s¿ R­+?˾‚ÿrS
+àG&“Êu/ÓR@”û@/\y šæ“Ô¿=‚þÁç€'ArJ†¡Êei%E!rdßN­¦á÷¼1ü‰UÜÙ•ËaJ½™`ŠOLŠði#Õs($|¦J*iæz{¤%š(«¤4‚åa… 61ŽR‹-ÊVå¢à:fš'é`KJ°ãR¢("ð‹Òkx„©Áp¤vµƒ–ôÐÆü"4ÀBçHBBñ »Iˆ2,Dc_$X MÑG“³ â=a@ÁÇ%Fr¥ª‡·Æ C¿á鼆@Å…s˜+–×ÀZXtN‡eÉ£Ž«þp¬ðœ.°‡°L:úª`yÙÅɯڂ ª€( -S@’¨øÖlJ…G’©8’\M céEqÒ’”ľøÖÜÏ¡›£.Ú»doÒÂò\Ô ¹@H¿
+Á—Dá9SîñÏî@ÏD,ê“=ÌC¹$4Ùí%ß!X%Én§>Ìàô
+Ÿ‡Ç cÇÒL8wk[À_ˆ%¹Ùª»Æ%¯2€Mlî!ŒHp˜ÅCJå&”*ŽÈ‚½þ¬x΂»{xÈ0Š\ÚVo§’³&ËÁ¶­Qˆ¹™•BE–øk »»“]~kÎ[u΂îñåîká#ºî5èq
+(LFœß~òækÎbdž±µÇTö é$8’ªÕð]4%iÍ’•9e¾¶¬+¶
+5‹vÀÒMÑÇb’Æê$`GµðaZº¸Uz‹ ¬¥„I—ÎÃ(3^†ÝÚƒ®>ÍósQÉXlKCÇp`OUþ,‡b}hL¸j²äb¢mH #ö jRî€;Å’£oäÍJêå —#ˆ Úñ9KVaM„EmûA¬088……¤·|Gè´Ýâ{ó|^_õ9äÝ/^I¥×¼86øÛÿKWêü?NÞõåGñqVÅ7êG鞌Äÿ£t+bô™ïâ|æ{pÍ—ÿ1Ò‘&V‘yÌíBúãl‚ÿvÀ£
+ýÿ‘ÜïÇ%úï°~4šËïG€ýàš/ËZyF€;þ쟳ñ!Ø´ÃØ*tÔÒñx;"Ÿª™Qôûq‰ÞþëÛ_þ.ùƨLsaçxIòL‰¿Hz5+TÄhSF6™Ú"“¹}DA¼…]Åø<ˆ©Ä}åŒí­+Ÿ×á’Œ’РamÆ`“l® %äeš¨¨
+"ÇÔÅú+kR>ÂŽ|ó8éš7×Ê•™ôÊÀפQš[Œ!h# ¶`õ:Í݃‚¾™]íe¥:Úwš»ËëZbÀÚ™½ã:hºñ/œgå8hïÝ^‚£ ½ÁAW¶Þ9op®ËÍXgkvò×:Ñà è`9NZ7a‡ÅÜ‚$é ¾J"¯ßÊ´_WÖ¸¤†fG|Ý?
+
+z·_w´·%¨ÀALpÙÞ”€ž?ïœÌà\Y‰Oô§V"#Õ.i•–á5’úÆ¢½ø“‹@Ô°p›RPí;qŽ‹ÙÉ,{ѹ«åQFéwé®éõÑ;Œ†(¨åŠ°j~Ysjaï3ˆºj\ÒÂRTÖŽ3ÅŸÒ'©¦> ! g‚`Bh!FÖ¢-¬CɧøUðeÌ7y>)8dT\ˆ—I‚ñ6‘2¼«L$ŸŠ:Ô€c™™2³Mëâx!¥0[ˆÒM鲪#xj“tTã[¦WÊx,|Ò¤µE`"lD5ÖÑ|Mº°"ÝîÀE<š³7O¦É¤õìÌ~Bí_fªMUg&ãQðõ]!¤N/‹ò«èæT2½qACP EO(ðá˜Ï«^ƒŠk `—Ý)—12[ÖÝ<}±ODhENæ]¥©CÒq³¦׸0UT ö»QÙ±eäÈmõ†»ê™ w¶’^Ò¤†¯Ê)¤!"ù¼ʹ—ž| DW-0Íbïâ›ðœ‰5¨"å|û,¾RQ«J‡Ë…t A…;b²¤¨oݧš©É€Q&FñŸ¯Và×Ùd㽬|…`òZ¹¹`^ù3
+ü˜|
+'dÞ­ßï
+Sß•}Ðq¿Ê(:¢-õ~”ÕQÀ%7ø‡F-™¨¡˜Õ{ÓÑpR)¸›V[Zaˆ–’¼ð`Æë0ÅkÐ# BàTÉ$àrWºÇMUë­DØ"„Þ3sT½ù)<]üƒE2ñÅ“NJk<¢Òú¯Šx2ã\‹t§“ì­’ +ϦaV6à;„ÎKˆ®ªWí¦¨é«x9Ç<‚¦î_eUÑ.ÇÝtgy£<€Ÿ¥çÈàhZI¨Ì™»_EoªH *¨iÞÕ1±äL*ÅÐÌô…«…‚ÞDcö:r_Rÿ- )('¼CFJë9{¯AØ^Š¼phxzÊ "Œ,9=Ÿ”ÓO¥‰×Óýªiê&0žýf.ãµSÖö•Ž¶$¹nLÓ*Û tæ¯ ´Ê¯çæƒ%’,ú
+îÊš™Ù™Ø„•c#ßLËp€œ“Îùx\&3+ޔɗþÁxÙäH’ÛPøy‡\Ï" QK£fÙ[ŸÀðjrëûû{Td•ÁB c
+Õ¬D>¾u¢ô &FU ò­ ˆª°Demo'g¶„Óä[chLÃuf„)ûêùÃi•U>å äzØ´¾Wš£à¸¼}ˆkÁék.a 0dÝ°Ú<·ü³dwRë/)Î<‡õÅo˜ãXöª`ûVýU ÄgÛzw×@
+¬4{×r/{§$K&5k®¾çJI”˜ÌÌo“þý+PÛ’vw‡Ûä¦6Ë‹¬-Ð2sÒ¨œ÷ƒØ@Ú ŽÚo§{žé:O‘¤µ‡Ö›K™¾‹s¿o[G5^ÇpûZæª)
+#,ùnÿdÖys‡@èÿ=Hˆ¸õ¾{ü— Ñãñ¨ƒ²‹ãCyt¾[Çß±K‚«×í¢Kö‰ZpÉ>7ú¤ì“Ÿ?ÐTÄ…`A›g*ÁSAÂf©¥Ì¢Â¸5ˆsFEÜ f7s¥‡•¨òHAæcêf>N7Kº!) ÑÜ`{}•PNTÒ²n¦ aÆ€õä¹ó³ˆ›¡¶¸<a6)ÉÄs¬ZaÔ¤.(üMÙŸEH\ÇIàYäg<"ô‹ËCøq­~XÄÇ›Fí'•Žƒ,áÛ¦´ðu§OtAÀ#«|¯nI—2`C’‹í̘-¤ùf†Þ©Ï¢_Q‘˜6g‹k‘R;Yhx¢8Œy·(hBŠH]öi¥u© :Ž‘$6°Y“®¤hsâ¢ë¢^p«¬b…ÑG’Œö+œÉ÷š×¹ùx3ù€;³£@|Fg¼‰m™\§³¹þÀz×¢ë˜ll6ùàí!ï]Ãv1,¿ î]gw«è:– 7j4]‡õŸ'çd-åTS2êãôÉ êC­ Çß°Šðl
+E$7r°CQ Á´…¨“¤òCŠÍ2žºL'E(xR2Ëõ„É°½»Ž-€w&ϘI©b.ø»ß«›åý`Ò1ü3¦™áÌqÂ3°¯pÓÑ•U—çÏÈÓnåU> +w—žÏLÌX‡þ±˜È8\ŒŽÁ¡MÝo^(–þÍû¤zàaO1£¿)ó%‹à0 *ÁŽ`£0ô£š,zémªŸ¨FTB_øõPkHn8™ ˆ ‡[D-P2°
+^:piëܼk ’[«Ëò´ŠžÍ¡à“™7!ƒ¨&4M+3a'1—îo?K›vp/k,Oö_?#=CËëxs9©Û1¬îøä%¼i™ûM"Ú©\t0|p_½…F€CZeÊŒZlÜÈ› g¸þ¹ &ý,]m¨'bb=xŒ¦É…9ד°“›.>Š^^„)k:=:ï”<j˜üÕà,{F=M!'ïaN p„X ã%ü3O4„¥Îý(›j:+G*8;ÜÀd5þÁ÷[â$—KôF "ìh׈r§Èõž
+Zp1+7úäí$ÔU-'Ø[5£2ŒxjCªøC* Š‚›_N .þÇù½aŒQA;ä³Öéêj
+¹—Gí}&Ä ˆ—n%P–RxÆ­Ý/Ç*á*²ŒÎ¹ÒX0D¬!˜[Q :
+!ÅÖ¶f2’mJèPÃäìÎv%1BwÄ/8!Â,˱;âpTœ˜38:¯è;<0ʈgÅÔ}öƒYƒ½I>Îà Æ‚]S À£5ôÏLGÑ-S2]BIÆV挛ä¬íè8˜¹d‡§ï:æÍF‹QoÛ%ß÷…_@U,š §fÉu‡D Ø®æ[ÉËKðvXQð ÑíI&);™ÕõÜ6Gò7e™æéLK‰…)+\'ý‘I“K™ÚðÝß:A+KÅ欷9¢ªT<sÑw&þÄ.ih$‹Lfàƒ× ‡«7b/ÁÔLÂÏý‚ýd9Í-¡ÞÀu!þÔöîÂ3<вXûݵI˘$_>ái­À8ÎòöFØ-ÞÃKpT ¦ÃJ†iî)h3` Œõ,^Bkh8¬AjÛK—Ä*xԤÿA‘¼ß톃Â8kžAÞh©½•ð@ô+wE6½Ã­·¼É܃••ýépF—-äµíôNGî>Üií°dÌËjµ·7´žâèß!pdå¡Å[BnsžmS7dëC磣æv:Êæiöú¥À m°â²G Ä–h—,E |m!Yžö¨T¹Fh{î E(:Ô°x$Ú_a`ž1Ã,,Q"!›»6Ìf»[T OK„1”<›wÙôš× õ”ÆþõïGëþŒW¼ÎY1`ø"7~øçÑEµC¸†Û‡‡ 1 ÂŽ+fy‰9úŒ±Ä€°Œý
+Š@–– ³êŒlªèzÜ¥èuçNzizþë¿¿þÇ÷ÿþy
+tttbÉ»[$u§ÁDiB”ý;4¼'ÙTÔ·îƒw±è¬ß.aœRo-à.aš>÷0Ê×#(Z üB”]üÉ}^a‘;Q¥RX½ì§óU&^úi1Æñ¤H@Ö¢§SÒx(n%ó§ý|úG )Ò´ù3|»Cƒh"òµ¦»Žÿ3^'ÇÃ@@Sq*·&•Éÿ:ïÐEĔ쓤jDwÿí3Œ„Ý!xkŸ'ü‘2,ÓXú£¢oNž²òD¼Õô)vËÂ`_B¼ïWaUÊ}FlûŽ
+Ùë-Û¸Á2:GïýJwwh‘¶µŽç,#
+H‰Œ—Mrc7 „Oà;èyE‚Äד¥o‘ª¬œûoó¤¼ð£ÊªÙÈ£ 6€F£âMK•õñW »ÌFtåÏbúøüø÷£>þþp‰«‹úhÝj :Ê5Lºšïaÿ>¼•«ºªöQBš@Ÿœ4.­ªôÒ%1á—‰šD©ut|½s[V20îÔ0‚.ÍBGBå"‚nV[híç•Ú[?`2.¿´ò¹Jµš ~u#¨ÖÊ褀¬x)D¢ýˆè{‰æEšF^z•a¼Ú*Ÿ“TYQ~×M{;cÚU«¶üÞ†Úù²V¯^E£÷hí
+îqß)øýmßí^œà¤u¸—qn÷׈¦½ˆQyqnw@µÔ%{YÏíþûmßí^Æ©ÊÃ<<^´{±+DÌ:Ïonç~Ô`U º
+*T;W˜©Ÿ@Ÿ'Ð)ôr‘bt¨¡TòB<ï ûu<ëÍZV)|tOË[ÛüÎR’i¼eŒÂLcˆX]”3&™ÎpyÀTš¡Ñ“­Ñ%푈@¥‹yˆ­ÉW¯–ª]Ѥ;LíJ©æ AV›Rdt²?þ™õ‘·RH­ôÝQÌê«Ó{6Ï!aBëw ÝÝëTV^í|ß.Ëž®Š54™"œ0P ^5æ=B0Ö™B®dlø<Æpæ ç9Ð …Ymš‚è^éOR“O‚…’¯fdÆò!˜„°lMÊ—åU¼’Ä Tœ³ƒâ
+F ôò_yOü”Œ´.MI,¦c¾ùŽ`ê#€$©ºYÌ‹î »|„ ª²Î€Éi*¢Tõ©”>Õ 6‚”Ñ0Þêð(
+ŽAJhÞy
+*t2%¹t„èX™«åx“‹àbe*f]eÝkúËEÞyb<®{‚öaÌ×™§¢)…clÁJA¦Dè¯&ÇTâ$bO!Ù-WÃÃÄÆÑ·~z–ãHçÕfçš+xH´%Ö0e0Gñ¬®Ì9ôÕíÂxL'õ9t·œ!å)bhÍÞÌqÊ>ã©ÇŽJ¹ìÔ ²¡KÔN8lj±±4í«~‚È\Â!èÖjo½ö¡øÆYZÉ9ÅÙR[°ûÂFç¹C¥„MÄ %1b-{lÑÇÀÂjŽü·—J£DþËcÀ=R¶u™åJUËê„žãž<õ±*"}…Ï’çcxcÇsR9ü½6xrŒÏš`jÌ•pð²Øñ
+©¥RŒ½cìq™žqËóá|‹s–­±Ûó•å¶ ^«YûüpB(VšÙPk B…P‹üu¸f ‹€µº×
+£+
+Uƒgisî2ñY@ȱômÈkn¬4h¾!•n1–L
+wÿYvƒòLkÆÁ'ÐׄÉB§fáÐ&ƒ97¸Î}ûcº®ñˆ\²– ¼èÙZôýxÔJgõ,·Lè^I#¬u–M®™K&xÛ©bž÷é³íÆ©n~ –æ›nBôø‹cnö“g{rFÅÔ¬ß êŸ´±Óy±ŸQƒIÇÇæ
+Чô£“§¾ÓÛ–TuÖ§§FÖÜ@ ΠÓI<¡ŸæSäÓt³û§î˜ûÛR¾ø¶eV©±#èpÐÉÛnñÛs·ˆzeë7ôå?íª$ÅÇ•æ Ư÷ózu
+¯Dw¡öÿM JË})ýù9¶ñ
+dø‘ˆBÈÊ¢•uV$wv
+¨ Éø·¤üÙ'#•_Ñrg5&#6„}Š¥¶ç´e±ª œ¤íżW6ÝTiÒÊ¥§s;Wɲ* ʦ÷¢ÜÀˆ-2!™ë”š†nõÇ;{î¬Ü/ó*¿RÉ5·(9 #Í•¤b¦8¶nÏ¥ŽãÎ%µû02`ù7}dš;ü™3|@Žà;& )%­m×Y_–ãms6ïâäJ9sÛ[—t22Û¼:U—gzŒØMÁP¢˜IÖ PÌþ3eÓzn¤¼o’;Þƒ¤-af§ŸµÎ Ä!P,ÔhæÒ³d;á.Áûɲ©Ì—fYÊíL÷²ä°1õ­ø’†1Ó‚_5œƒ;£)cw•çêÁ,¥i²³øÙÀõãá¶øЩyìx󄤈a͸u‹Ü—h§’>Æ|ºn®1ƒõbËtf3Xî\7¯©ùÊ®jÙ»-_Òg¨^®xpƒ;)¤¥õM ÑÐÞWÑà«¥ðâøÖžKÝ‹Ý6ûnx¤gÁîì­”í0ù+1Ï¡($°Ãæmsƒýg1úÃJ'•”ë Ç8@òªrñ êt …CVy úÌb¸+”My\•¥˜g‚‘obè”’+ñÊ–
+#ª‡ìŸï„m 3T]¤Û¯¨´qâ<x§Tf…!o^$feÉ3+`“Ž?S„a”ÃEî`‚äú°ç—¢÷ÏH°+u09U%Gz³º]V u¿v,J„./b»sq·¨Ù–±§ÆŒÕ¢9•€9¸ jSÕ@kƒ
+A[zøk1Y#o{†SCI
+ŸSáÛååÁä„{Pü3ÑÂÇlj‚ß ¹. öVe0«º×€·ì÷wÿ^²ŒŸc_k̇"Ý _™ÅÙaJÁm™LfÆF(*2•£#¹œyÎ_ê•|3²Åë¹M4¤˜Æ`WÆÃaö¦%ÇÈéÚ¡èý3MR?ú–þòÇ—Ÿþò¡Óq¬}a[(©ó·\×í Æ¡_ÿübè
+Ia°ü,'ÙágÇóEF†ÙMpª)î.—ˆRs/‘£–·ÆÌÞ­”¥v/cÄô6ÖYB%iA>²Ã*Áúš¤M*©2ìÄ <¥þ¼]h¯µY‚7剖#JMI~ƒµÓpov(ÑQ,Kƒ¬BÎ/ýðŽIZð0/\õe´iFó()òTø9D·¾žM4Pð’«g OE N€4–îÊã÷4œc)Š²²C†·{ÿ¸1—ÃÃâÐTÁ]`‘ÊýR;¾üR2›|íàí;÷9°:ÌšûÉÙqšòs]´`6<sœPÁE'?QF°Åý¢˜ƒ‘+¼ž!*è õ9ÖýªÿÇñæsc')‚“Õõ9ˆ#°Jµäê¿©'0?Š!ø—J˜0± w³G–¯(ÊOÑK°®!桛͊ZŠb c¶.N\MAo¶>%: ä[™ `K’ĶE‡ LŒ¥>‰U½‚)pÑЩCÉ„|¡ùpð²züN–;E»`µ1Öàå’Ò¨F–ÈGÈó(³6òò¡sD§Á$K«"èQ„‹‡\øçŠXBè~Dpý«ˆì5*³úXƒp*è"‹7ðåL󼽄l¶„õÅ?²4äDÜGŒÞ!̯å‡Bõû4Œ\"x­ Ò×a\JæØ="’œ>ãfˆ#æg¸ qŠ4 €šM|IˆX§(ÀÍGAºÐÖ ùýËÄ©‰úÉ•q?k~çŠv¬¡‹$‘À±DXq,ü·Nú`³´„F
+‰4þ¬·(ˆ<F°Žî%lÛeªk‡’ßý¨€3ã¯Ëù;¤N®:ð‚ (ì]'ƒ6©Å¨ÑK`+DÝÒd Ö˜ýboúÐZjî@­fHÖÁÍÿt‘¼ikHâ/"² (’ˆKEMÏ=Œ²¶­euÙz-]ú‡}êÐ&¨ /V¥VÞfð'äÿÆ™¡Ü®
+q¸ðŠ‰V/:~Þæð‚“úÊÓÆfº– 0Ø­ô:£+(a2ÀOY}
++£dÙ†òÅ4Æ0¸µÎW5aZÖ¦K¸AðC(Ý&©× ´óbš¨°±¤²éìG…R ÀHeœ×­h³V)y¢L(Téþ1ðŽî¦G[¨'|’®ÞVXç!Û<çw´›/ãO’J¸/‹*:,é¬Ì> £TêÃw±€•ì%Œµ¨xðË¿÷¢íW¥÷ÜÍmðpûîwÙlFcªy[ >$ÐOU€ÅP\[Ú„€©™EíýXQÔ)‘Ê\ó:è^Dt„ˆH¨(¼Ô²ÆÀÁö®ÓLŽb¼ÛK ƒA°eýÂRwñPÃ*ò/yï:™…Õ<é™LBDÈySŸ;ÁjöÄEc å¯äÁoW¦«ŒÁ ò*ÙÂ"ÕèéRôí¡HíáNK»éé^Ö¸A ᙜZe£<î2ÆL’(ÈŒê%Ú{°œÓ2ÆÅ.¡f¬/#„2@K;|yûh><?ßáȼˆ¬g Áñ°:¡S–çCÉ…~4 H:~Î@4MÁ"ÿ#ƒ|·b@Æ„z¥Ó!èõ*.W[& •òÏÊüÈaÉ5Wl$9™P0†G.kêü¡w´~ć4N–_'–MTÒäÚû¡èý¡ˆž+¾Á|a‡§ÕÓëÖ@c$'°”˜g/!xàÞjÍÿ6ÐEx9YbíoäxÞš·yÄž° îšÄLG£Ö„“WE‰}Îg0ª»²|Š]³É ˆEm˜±mlL¾¾MΩ~—ÎÚGÌìÉ> 9ü¡aU@ò©d‘­Á;`>Ú0鎃®ôcá8Àe-H1fEÖfKøu­¡²ÄÃE•T‡ƒ7Øa’µd*YÁÆ¿c˜œÄ÷ °2ò*M©çT& , -8÷"M²_y&³sàPK*½áÌê6iF{Y6Èr†·P᢫¤ÉÄ`äL„¦eÖ"§‹,yÐQA¶mìûŠþ«°ïŸ‘á}*ÞÜ98Çf^ì € ±½ß5ÅŸ—d&‹-x›ð,Ð$:” §ÝÅ~Ãm*æ™HiW'{I.â“æ
+ -à³CPЈýoÊËI² ¢'˜;ð4ì‹Ü#òT«ï¯òyD Éú‰46G³.z±øœ8vB#Û´|rA¼3 d!Àµ­òa+. bá “>1­‚76½5ENe1AX¾ŽHcƒêÛÄüàNªÕO®Š©-bëë~—¢ò ‘O´j6‹KîêÞ‡*£Í]ûPËwmÂÊÀlhù®qj9..'Ùí~ÕJ‡BÝXù|>zg#ž†àÑx3ÞÑw?ŠŒvÉ‹l7,€†9Œ<Ðx9»ÏR2Iò@ÐFØg;)×β“~åž‹(@àíÑVòÄáV3~Ð¥åxJ&ƒÉ‰7sxÅ<vïëWôe 3Å¥'…äJVam— åfb¨]øõ†ºSvEe*Çmaˆà¬‡9 $kРðc›l„kkj‘RY8(Êld• :8‚ÔÁtÆMEÆ[µŇ²ˆ7¾mOƒL²¥ŒœJ¾Ž}d~õCÓ¸ ˆË!'=ýðbC,¿)bè èË«“8U^38“Ð× l²
+×!¶ééåÀ^ÀŽ¬¸ªJ¾ l{ô
+
+öÁya‰¤ûüeË68€ø'0ÑÒ#‘п@xZ·Ëæ°ËþRF‡ y\v»drBV˜Ø9xÝ®"ç5Aü{. Jìׯè°eͺ9‹TÉ‚K„TÆ÷4GøÓwлße!ÇÉÜU½þÀ^’•W®×ýˆ²ˆ‡¤Åšrm…¬ÎûŠvLÖ“ÄÖ(¦|rí ½p5ƒ>£h±ªòšG@UÑ–,Ç¡aomÒ+;g£.©‹ Ú‘?g÷ÀidÓïŠ5Ų㸠þ´âG{’â ÍŽ1{À÷i´Cš,&y‹øÛ­yýáíbZù 5+óäñ=h¾F2lr<ä²T@Ì? ÉU®ÆHåÓ÷*ÑQ®»ÁÔ!0"Ÿ>¨}8GN…9À"–“ñY|Y¢h1Οv¤@ÉìÂS1ëâGxB•gžC[¢j—ÁÂÏYËy®ù–¶Þþû{Dz".C¾9:ø çâ½ßõ/ˆ' \·é rJ¸4ÊÜ‹K(o‡Í±•3%ÿùò,V’™²_Š²iFÂçipwŽ˜ò9ÜÏØ‚t‚›µrÀºìF@Xñp°Øª¦ä }¤"5M°$%¤OjÁ­,¨kåükÃýÛôL—ûÁËÌWÎ1æí¹Ù)E)5¡,cØàMxMc 0Ù ‡ÉÍÔ%GT…Q’¦®ˆŽtS3_@ý ‘í¤‘ýÂ
+TBÁ›aŠyâ"ò ˆÆ›w3K›e“k÷o‘3LØ >VÚí!©R`=D-=m ¨Fˆ‘ÁÞ¶€t›
+4¤çWˆ6?¶z®z€²}CM‰‹Ÿ#“‚ìµåcx0´¡¢‚â¯2cÎ+c#Id«D›°P ²*åè” ْ@Z¬ XTZ‹•|31L bPé¦ß|ŽO¡Åë~:‡/[“uÇLjƒÇXêÉHwô)Ó¼vÜbÄ¿pÈ@tÕ„e[¤¿‰Šèø=þ2íÌq—¼ Róæ´¯n‘낶‘_LµØRP.¸Z«B`X±ÜEy•,Ùwä&èS»Ðe! 24òCÞ'Ÿü KƒO¥êëÔ˜_5mü«å =œ´È³ùvë9¢­Ò¯¡èÒÎ÷TÄT°f 'öñzƒ3g’sݹÈ·ˆf,!Ê+¬4îQP“¿c&É7ùº Ý_…ba#8eÙKn®ù@.ºÈhCvqÑ;qD(—ú-*^ô+ÿÂBá¿Ël“B>we Ÿ|A¸h óÒ—UΛ¸§È#à·ƒ`y \Bö«øƒÂõxqW#åòVÅ:…bmHm’3œË²ð5ŸÅÓR0£‰eMí†Qñ”ƒƒê,‘5‡ô¥ø¹ÑRƒ´Ê‹™RúWq®i½ms!71¡JŽP>Y|©D?r…»… p™ÄÃÞÙ¤ß QHæƒ ßAh…æ(3€9ù£è-!¯#l>ˆ= ÂÎÔ ‚ˆ4ŽQ óƒ¥BøÐ}n¢L,Ø‚¡Gø]sÍÔnµâ¼ýoˆ v­wG7d£¡–ÅPÜ>¼‘D©ÿ¹’½ƒ¯¢úXfâ•cˆ³“qµëÛb2[|rч…ZPÓÑí£“£S vϲúlls}©S"Š€ú#-°ëÜÒ•ö>@ LnÑS©èW˜Ä”$¬brÿ
+OîÁÜá(œÀhTþžÞòª âM¿‚ÑOë2¹CŠRHG/,0¡Œ,˜Í·ÎГº©ì©µ0 "I© ùâÍÎ!YQ–,
+¢ž›º"‘2O¾ÌÖ(ÄT$ãGýâme]AãÒU~d( 'Ë›D‰ÉÆBò>†á®zžY]‡E)D«W1 žüå ¤”” ãæ•ñ9U| /²¾ £-£óu¡þýª£’\¦Žà“ø3¸
+£ÎØè;pßÉù.·xy“!)OÍ£ð˜(ëE¦(ΰ¦ß@[ÙS‰”¡Ÿ4É°;C½È5äy~iÐs…ç(k°ªò|½,©iC¤áâØ5â3ÄT
+}¦.·Oö@ÖÐâe“ÌÿÇA†`•hmoƒØÙJUÓyòØ#Ø«èÙÊšþfZ¥Ä„hížæO^L’auA¨½‚z4£&–ãž¡PŠî¹ÆšÚ›º,y´+‰•Y”n»4 „$P¯t¥UTt¶¼›…,¼0Ë
+9‘Œ43¯ôŸPvéS7¶/IÖ„ÀS’ªß„¡âOSí+±§i+!e Ö M†TY¹µ}Ñé´€LS´ñð§Åt¼Èޓ܆o©ï‚’–ñm$rÖJ=®»ƒ¾ÞÑ?>É°oFí´¢J£: -à8Až6G ÎRøTâ'7ï§Ã_BÓÔ@"ø?@U²Ðô¼î P•v
+ úr†|NßM‹í¥áqT!ŒWµ§^ŸµˆÕdõ¹²¿†”Eúä fÆNqоSCÄÊ·¯âõ¢L†<ÀΖi¢B~JMm®väF+´0„X:°dÚÜÙD½ÈOPÀwÌ»³x¦{¿ö®·@Œ®ût×…p¼î ׄÐ3—•%ÍÏ ¿7ÚeòÝ6o½jX—¶Š ÄÑ1QðÔò•(ˆ4¸IV«“¢WòöŽ{€2b¼q&TãDa# ›*¬õ#ïb›à@íkA „ae‚ Ã‚@ ž¦Àƒáf¥äãõÂ9Ð3P„ ŸRØ+“\ψÝ.b4®¶Ñã@ˆD[_g›ÊQ P#ia°p‹â‚ üac×jLµÅ‰BA—d‡ÉSÆ\Âs”]$º¢ÕE
+ ü{í®«÷8Rˆy‘]«¥9ÂL!oHÈ*æ;Zµ(TH&’œxRö-˜ÏP€‚®W¸lÃm}åWüy‚nó÷õÎîY.DRjBhç}<f%©§°ËóBÂ]ÙNÙu»XÂø§Ø1æA,mhüæšyC’¾<§¢}n`Âhñu•¦n8 “C')ÖAx©ßáÕ‚0µ&œ«éìÔ!!Ôc‡°7eùNØȾŠ¢Gl’'Nç } ûi›åÅk˜I®©2ðùò«ð!ä¦f\¡žÕ‚ÅÀpbÂ_}þQâñ£Sç¦ñ4$‚¤žëGü…wf5nÍ裀hç«%7V¥u®ºPf€—Ò¾]œæ k)ˆÑaEÎ&KŸ”Z$  ‘jpÎ
+ û*ü@™.‰„/ÎáÇ)<ýî+~̓€ÑWED¾U'š†[ªŸáKÈ',MX|¦ý{·C¤È¼ª¼Ò'虂ëÝøõMÒ ûøÏ¿FJ©4'™õsîç3çètóÛA(~e Vé%ÀP,^ÃBøë CUâMüÞt!ŸÕ‡±ìýÈýšø=45µ’xGõVÎG¨™oõÁ0ºáç”ÖrRYÛ­ÕÏû5¾,B+òêÚAEˆˆY•â4i9û{™BëºLõú‚ )’Åø§;¸@(]g<DÞ ªž¾Pˆ†¹TI@Ç]Ð ÔƒûrDRêÇ¥–RÚ.7ámåvU!ã&9âUæ‚ésT'é2¬°®¹ÂfýÚs1;z ‚È4ùIûÛ3Ü{Óh)ÎÍ»-•
+É‚Õ¼Qµ (lréÛ>EéÐË6%zAoTÊ07ͦ½*­±'îcGÌåV$ìpLo8á‘BrǨ°le
+.›¨‰›Œ-¦7ÈflT §ÝýÅ1ÊÒ8#qä/Uב$g®€Š4ÂMgºsÇN:*ÉnsQÐÅþkº›vþoÓ©ŒõCz|nJE+¡78oê‘JÂò»]õ…†X›×:”`HŠ@I/Gþñâ-ì(ËÁ8ðT‡ÿT¢}c¿Çp¾FÞ%€„Ò÷«„zŽH°ÙÃ4à{qŽH…¤UùZXÁ×Ä9â Ò !8dŽ›=®»ƒ¾ÞyÓÿr„ÌŠÀ…@0£íÌ!"ŒðùÌòwRÊGëŠ.
+
+_ÇÉa?Íâ;ÄTâBÈ(Pó Æâ”ä/®g¾ØÅ´i±6NGðFŠ‡gÛQ;MÂùG÷Í4‰þD«„¸¥u¤Œp”ê’ÛöÝ ‚7Ù”è2s¤A‚•‡Áã)Ù&{[¨/g×ÒãsÒg& ±5õcü<¦›Âg­Ívb:[¹]Vࡳ~Ø>µ‹-ˆR,^ab0™º‚?äXÐSƒáz t j{
+k¾Â>óÕ³AN£§¬Š¤ f,åð˜Ñi…V*Lê<¦@4/1™›`eÁp™a»¾ SdQA& K›a$ŒEJãÆíƒR°Ñá:ã’ëGÄv’–ݹŠÌ<BóÕy)Õ ù\õÏ“u9æOXÈ|œeþí jÌg2Òŵ AdÖØo¯ŒDÖäcm\P6‚üòïαRnú!ìƒw“hÙ8ãsQà“Kà3q–Æ/"Œ!•G$ðHõ#Ø4ª;Áµhf"-´“ÉK‘b¾}2ž òÙê£md“ž7|C
+èyvD¢ù¾bc;RˆÁAE>ö¿Œ—I’7_ ?è4ìË™W>¥õÿ«<@sº*ËfL2“8ÌAaÉŒðX%P>ã\¹ü¬9ÚŒÁ
+Š:¢­RW·ë!ÉÀóTºÛ‡Ì¿ˆ¾„*ѨµÀÿÉ ­$ÈĦAÒÈ%ŠˆÜŽ3ËþÔ½ˆŽ×à 2{’'¯Îàô1ˆTIWfS«„¹í Åæi&Üq
+ᆲªlÛm’µ×"Ë(v !¦¢f™ÿ ‘oßÑÛg¦TCƒ;g­(©)ÞUµ~õ+aer*¡´ì]u€£Ø³Òfpmï- ö{ÎTI I´fÐø:ó‹TË÷§ˆ’ 5^I˜Í(l¹X†5™âa,ã½YÏzZ™.Bq†»×Ö “A_>nÐR«~UÀˆLPS—sî!w¢çÇj ÚEê§w†)÷ÉuHýQEç÷áFüö˜ÓWßö*
+\‘φÕ¼?t/§0xÞ ö³u0ê„)æ§xIngb¨ˆÑ­D²Åd{>ó'G"VÑ»{
+ÎÐJyÏ̧ˆA܈ôÙ–Võ-”N$‹ôSO’œñ¡„ ÅÄŒø‘½º4–[í.<æ£èõP¤™§Ãsa7|ˆú[hÿð`ÛéÃ$æµýÐÇY 6þ^ §ìBÓ™ç>:CNðá¡ãÜ°(/ð«4µ-SL?“qàþŒšk—«8€»
+È)êÙ0‘ ÆœM8w.ºöŠ¤$–RëSaö[aļ+?6%?H«„~Æü¥\µ®®¦éŠRÁ
+ ïP” qÓ€&mݽ]E
+
+¥ =®‡Bk†°²­.¥ÇÆ€°×;!ŸˆBPFpJÖKñÝLq3=¬Ã]#ª¹r÷O›¹tŸw(¯‹/—ãÂ势©ß{òpD¸Ê¹=ˆÏ…ìÁº%ífwDã^ÄÕÓ°
+&š¹[ h!væ5·Iõ>äuÌ ”ôû§&sk8s“dG»mj2`è*³[ô²+œ|9 Ë;Š@hxÖúí_•Ð6´©(®•U ±Qn%BEð*²ŸUÁ7€þÅír ìT ÕÈÜÎ¥‘ hv\låBÞŠÂãÏòÌ:Á°ù¡„ó®Ž1›eê^H)NDõÛZG1ËÜÜNíRH“A㪠£?|º„vÜ96±—âZûSˆBåïy÷º»‹Hȃ¢µ¬S I Š¯·¿mdk°žÇfé&‹‘è>¯öÀˆÑµdЊx@È7mwÁ32qG ÅS®³¡d«ç%þUMô&!Îõpmyé=E˜%[üÚÜãJ¶˜·ÇÞÖ: Ž
+FtlWž.5ü];ÊÂS'§†À>O‚‘ŒNzŠÿ&µ6’´£‡¥§¡ë2UV¨jH<ñjÇW²Z •Éíc·qòö³Å¬šÝÒȯ“ãÉœ ·­ƒQ×…rrqÜ´•à]€6§d½!A‚OäMÙ]É †wÑé÷:,„µF)í’\~…`¨{=§"Ø.üž˜O KäŇEŸKz’’^'òpÒ}Çüfê y|()h¢‡È%Ë2jdä×z®­îº½Šp T*  aw;$NLZn¿g¤­ù)îk€C¨ì/÷0ö“sw•óÐ- £(ê¦Kû[–$@ãÊAEZaIF‡–M†|_ T<X¦ë_OD#û¥bfw8 ×sÆŠ‹â´?ÞP£ñ¨<DÙâÆ8Õ©I/e:ŒbÆ<Øjœfê•Ôæ”l©íÈ_KèÙ¨ëÈ£Õ´ažq (0óX½7TŠU$Ö©ãl—æãòYIš©/œÖÀ9Å>¸†’=òTµÛ:´‡¢°ç±KPå(Náþ¢[BKð@&äWßÜ‹
+¸‘7±1¿‚¼ú=öaÿ„¥qWWŸr{BÚ¸PõÆñÁ(Oš3ë»äÊñwir@Þ+º‘¼WtAù Ä¥RU£‹òReˆ'$qÒÊ^IRÒ¢‹ò˜„¦¥s’¾&æŠàÒRaôˆ¸`}@yŠÐ@¸·në ]L¾¢d÷H^²Ó 㺄Ç'yGÀ®$¯¶àúBŒ#nqº’¼[r%y )â…n¢OònÑ'É«Ûy5NX²z(OIåqéQ½á‰T”×LD¤«憃òT€P´Zk
+gÊëäfܽ ñÅGyy.Ȇ¸°Ó^(¯çL@ÔÕGù  ¨‰çæ'”§‘sBz15 ñaÉ_ò~èsQ>êyeEœâl÷†òÜU¥LìÐOw]PžŒR™Rbê.ÊßK”¿9(O¾Å–¢à£<=€àum›~sQž!BHxO^j¦–w‹®0ÿ­ ÿET¤“ÅpЛžiÿÏŠð' ¥ÿŸñ2IŽì†è ú:‚ó°î­o¡­tÿ­_‚d…U„¬ŠðÂQ ñ“@"äË¥8”ô…Q"øä hÌ l&~i ƒÜËc´"^™|ˆ"pVÕ‘ºl"°âF«Ài Æ”@<®•_Ó.B™[ä½iÝFd³’nÚ†OÙ0É]qšqB1hoÍÓ)úÇ-â¥p
+ø6ŠØðùiw‡e¶¹©ëö!ìÌ!¸§[&YŸÆ˜È/¨+ÚÂ|ÈùiV¿Îüaç(…p
+.K<%;õ5wÖ—ÛÊk/l8%,êZàõL®šdÍ‚Ï8¨FûÅ”ÔÓhYyVÄ¢¬W3a¦ŽχÉpðAbì•x3$)í€ÕÉ'moË)šÏ‹WŸ©×úMá—˜N>¢eÿ‚hFH„ŒÇ¦p-4‘kÀ
+<RŒíé ­ëÒÕféAMì8n/[s0^© 5fYLp×Ð/¨³qR(ÑF¥4’Ñô¼Yì'‹;dÞâÂD§]XJXfÙXš…U@q”#çFÅóÒñNN@‚ñï}ØÈM8jÊùïeQoÉKD´P¥È”à FwJ>ŒFãÃMy#»Ç ³áÂÜ YÞ%e h×÷e’ºÀŸQQ6þXnd7¬¨³×›m‡_³NVI K~çi†L’–…?¹:yÏ9¶f³Ù0ÐÀ«•¹Q>Â. =‡â\yûÈh'Æᤡì"f_Mæ]SÑ«âû—5ºÈïWýûcLRœ\¿lŒ%‘fÕlÅ—[”–ÿΊ½âRüŽ•{Ó¨¸7‡Ð+|%‡Þæû`§uïi1ßØ
+vØ™æA‘¸5vá°íM„H"åè´ƒ~“ƒÜر» îÒ<¢ÐAIÀçÐ&öof§DŸ"÷ÂÔ á½¹çàϱ¨aŸ„3¦†„ê°Š¨iÉeí,•ðôú8`/5y§Àh¤EÑ „Zƒ|˜Õ¬‰……C
+$ØýæÝ/·¦¼Wίˆ,…ݪ˹È<1—=-z_å‹Æ°
+ltmèÏ.
+þ´£–´»³Ä@ÀL©¢f¯ûSϘ@Åbƒa<w# 7£P$*¤Ñn‰¬íÔÖ³Xõ¼êÿQü`Ö`¹É?©áÉd9E8wË#¦ž…§ N­\ßã`„1‚^­µ@Lh˜»Õ$½!KÎVö}s6´²ãªÛÖGxAE‹´Ù:
+ª³pÉ÷=Ǩm“5"]QçžCó1¼,ƤE×”
+"Öä‹ÌS•˜aÓËE|.°À… ÂÉÚä½"m´[Ä•6 hþtŽéùJšé \Qu<û À£ Ã=¦!­tyâLNœù>AàßeæqÌÖCìß?^‘ÓžÎàCž¹ ç«5Îò±F¯0
+Þ‘oa£lføvX¸sF-‡‡0Lµ!¬t·sæÐ6 ÀcöIÒn¹ªßsÎʥظ1œ}JÂÑL‘åÐÜsð=†1\Aøbºˆ:,|Ø%™<€@Æêµì-|/7ù÷_#
+ŒVk#»‹ðgVˆM¾®ÚÇô.°FÓRÙ.!FJ²p”Dœ â–»EÕU²¢™½÷O &5`!·éD{Å¢°yÖA¦ÇläEëfÑ'žœ( oY“ã4[Æd’S²æI– ëLFu¹'~]æFŽó¨Won_öÖáÛ¤>^Ø™‡.ó½`_€)wKÕ9îË-Âöð,¤¾K‘ÞTR{ÃI¶Ÿb†Ñc½±«:BCrÜ>±%Üæ8—F±Ž=—ÃQ±d‘'´³­Q`c˜M™ž³õ†~›_ŠPØ©Ù#½Îa6|†±²^'÷`l'†©×…䤉E¾/\ë`ùSäٗ2Iˆ~Êgör’îlâ)Ù~CÃs&ùr,€—/TR`K¦™ûbýA
+éÀ/VÛa¯è¿CÿtkP{š éA̾%ÛLŒ)ò'ÛŠKðÀq¤²ñYlLÙKódž{åÆ¿Fj=6â»yÖšó¿t¤®æ\~å&JÇ÷
+%K
+¤[è3i’!ã.r†ŽiƒzàW~›ãÕ"'NÞŸsâäï[º–9³8I`뛞5œÁ 8ºiËìI&Áð”¤PC¡àF!aÑ<†E™!”U‘“" <ÍÚŽù_ÆË$·Ž#¢'Ðt¢æaÍ­Žòuÿ­_dfæïjˆ6`Ùt°ª+‡`üi+ù|Ô¼«ÅÂÜ"ᵤÈÌuÖ@8“ªulÍ®ÁuIº…c)6@E¾~éy¹Ž¾ÙO]$Oˆbƒæ ’Xªâbvœs˜)‚)¬òÇpò§)ÊŠÁ¹!ÍLlãJ”èÄä“-¸âj¶O*=ã{[˜ºNY!äÿ\Œ½› $Q]’ÓÞÛ?¦T%Ò¬]‰9„ñ7\Y‘Ðo’ÛC(˜Þ4/3×Ù¬RV¼$© |Þ*AZ²„Ï‘å9B$kD1V‡¶ÄUo lߣl9Vñsd¦‰CK¾-vC+Š8†`Õ¸•ÉZ5OEQU+\O‰›à óÎêFH¤›4ž¤fÊËle
+ˆ“ƒB_¶2-Q¬ÌÌôA‡Hi\ùõn¹nÉ_DW1×¼25ùÌy¥
+: ”%÷wü0X­K‚!cÁŸ‡¤ó²Kkh$ëÐþÒ ¥¡§c—F ej̦²Âtüb÷Œ=d†»³r‘GlQekò) ºyÏYMÏäë E‹‡sJWDb–K½4k3HòV݈ ¢ÈôVڧģdŸ¼Ä²ÅŒÂ60!“žg~ØtwØ7ç/­Ñáõ‚íòó-_Ý@M!‡þmwz@:U·ìËÇÈYKf4jzRêü÷ÆE*J9M "ú¤
+‚ĸÎE!ø
+Á4J›B÷"jÂuÔ¡‰­ÁL’|3Ù[(61“3[öh)‰»Ö‡Î;ù¾Ö.Å ± ‚q1¹‚0@­ª”É!¼¡A˜Cµ]HÌQæ¨|$Pœ
+H„¨×Ö!`ýt‡xȧÒ[(²Ø1‰oH’Š)> >²˜õ2ä}Ô‡yaÛ!´“”±Ä²£8:ã°ÿò|dEç’…KU(È%N¡±¬e“¿®Q?àÌÎk†
+À?ƒ/ÎZY¡£ÛÇÔÓÌìÂÂuv鸧Í.€wISŽ©‡é£F[ù÷Å›lœ
+Žƒ½ùª¯JY‹|nXD¼¡L8ü^}wEÃIÞcFBÁÃÿ¼·ò âWmX¡+ŸñÇs¤†Ü‹¡[d“€Ð2,ݦ{:öB®W‰”a lÈž1žJ-”®iõŽ›p2˜\AûÚÄìåÈ7£ú)?[•a§<-ÉoèšI˜48O ‰xåïm”cVbVᱨûÏ1Ø©(šìÀÜ/û¨i‘rÏJ&)k [ôÎë
+´høº&œx±\Zš,‘!5+btWê8÷ P½r5¼œO“¤™ÇEÐ×€ŒWf2—Ì&Qeø!Dõ
+ŽÃÝQqØÈ È‰º—tÑOTiå[pÍð3›³ ¶w=Ÿ3ÜÄ¢â6[”ŽC
+°"Å>fˆ;«â.!J {0 
+„ÓP›ƒÑ‘ßl±¦°>§+©t;‡Èè96¿^ƒ³eñ¹ºï3¤‰<Õ^<
+ýýüu¦¯dRkOqÀÜÖïtÙ¿AïŒp\­wÐcÑ:ΑxÒËrÔL6hÎvr9`–f‰½ÁtPG--7!ß©…ƒØ"]kãW BƒS’±Ê>„‰aÙðhAÒÝaDíQRbqPf‡0 Å+v6ÿA—ÿv“CcCT Ò•9²¤mÕįªJ_ ül»<œS¾0À#\ûák²ñ÷Æ£]ñêð*…æNCÕª“ØÂec[ö¹ÄwÄ·FùMw¾M¡œÔì÷ùcš)PAÐö:=
+ûˆ $Z`…㪷â
+ºA/Êÿîÿ~÷e †ž4u
+{c€Cˆ,PhÖkíÙvëÒB•ôe|ÿì‚Ü—&ÐïÆ[‰-æ4K;3¢Cæ†ð}Á?+¤¡ïqB'ñªÂµÓÍ¿Ò8~©†øuõŒ~²îÛ7Š<‹UÆD˜
+éV=® ò…/ìB)èü9a`ÑÅiQsidHù:œt³Š)zTezó«î þóú‰ršÀ–¦¹d¶¥n–ùIÅP#þ’ÀA¼½P†ˆ »É2[ô[b|࣑ôQŽè¥$Û<šJÄ ö!ÕŒ
+<9ñY|g;íÂøJ€µ‚`Nè
+|ß 1~dÁt±ôévÖJþ[.—ÅZ‡Hrª™ðGgõ¯G ÞÓ”7§‰ ÊÌ LÛnX9ÅÉESí–`S|Û°\‰²¬®`5 ÜÂc®—q—6sáµäÁ0¿wÌëƒkÕ¶À"+\~OÁ¢_£­køÑðÍ$ñK1èQl¯Ö®à”ÖUb'1·n7‹ÀP/Ü|á
+¦¡Áq‘FH,¶J@(êÒ¢™â
+R 5L8kXcn˜Øå2®7U˜£r,ž#@RMV
+‰’»æ>¡á‘Hi•¨¨Z|Úq²$°E“ùÑÐ8Ù€8XüÁô×pûÂ¥•È…À„›tˆšwí$t‰¦Ì0”ÍÏ!åÌÏQ˜ ÿA|˜›Á-b©þ¢¤gQg1,cHžÌMvu9(ú<ED9ô˜g778° =˘Q–­>$@¸‚¬ÚqX|pF#*)ó&ƒY Ñdo†6‹¡AÓÙ_z·9§Rå
+Wó7X½y|]Bøi§kà%K)ÙbO¿ oÅnOð_g¸ ‘Éüf²`Vßåió‚ÂaŽ©(3±•Hu!|Räi)‚’h+ä™–ç/0¹a*òÉbÞ⎨ü2œÕ³‚‰çI” ÚxVš,š%ò²B.K¹_8µ¦53x©'><œù&<Ǹãê”ñ™§ ×-%Z.Òc›…„Á…õgë¹eL•N‡EC$E¼ ‹ö‹ÐS ¼q9 ‹0> žg[„‘€Š^Γ à”Lå6URHDEB~Y®a$}9iš¬(…cîuù¬à;™MmN?ƒhºœî­îç(ËŠ½R.gV0$ô«yµ”|,eK¶¥¼8c§À2X£ë5U˜Äø4¯v:?ÆŠÍ Åt
+¢SÊ¡2iœŠ³*$ïAQ
+±oí÷Æßb‚FwAɺ¯ðœç̯yb'øª'Ýy"ùÑãh!¾Íêã[£ýJ¶_ü1B8Äܽ§}E5å‰$ÂXbmUКΰv3d*Ý/ Úyľwb}°èj¼7ËDè‰_Š‹`¬©2¯f1ˆlʪ}‡JŒý©¸B“ÀK«±9<0K„øN;”ÿwYÛ„)*Oña[ƒ©£aW4T¬’…ªŠ˜0f"!Þí¥m…Ù1ùvJ urjî"õ3¥Êx‘
+d±ÛGEÎü3¬iÈíÜ« aöQ`vˆŠáËÈŠL*"e;ßÜpäVÜ!ðçø_>„(à+AÂöê~Ä1å¬"lR¬ó$ÁœèrÏQ>s‰011Çe
+°Qx1d$Ұ麃ц­Nâ
+œ=™FäÍ=3Þ©C¨›r‰&£­ BÁôä f±…›\½ä¾sZ‚,å.Ù/úïµüǼnáǦشÕdÊÒ&!e€œmoT¤iãE詺S&RR2u9[ƒô1ÀSBÿÐt¾l7ß;`‹ŸÂ`µzÅydQÐÞx¦ÛaV†PèAևЯå¨%Âå%ôs'™§U­DiÇØ™âV¢«ä¹`6½ÔÔ_œÃãÄ7E³ñ–KØ µñGe‰.;­T›wØJëŒ}c±kÔá¨âÛ ü¦G¤ fvÛ¼è1­“@§E½|UCc²4uûM·ÖPÄúì† ‡\Ok°00ÒîXíì%Pá*2ï)ŸA¥¦
+H‰”—A’[7 DO0wÐò‹
+V'EiŒ‰@Ñ-ÈO_gÀ¸Ì¹º/N>zŽÛ1ýr‚]¥¨é%pSØ¢~;°²ö1‹7ãK0œ“a´Ÿ@“ƒLA/ô-ê±oƒ ×t¬±¯YÔB>^ E%…¦‹ðÙ}L¹¼R=êÑ |³laYƒçLú‹4[ÐW‘õ©‡/ÝõˆNF½(ßP¨¶;0¤ð+†WR-¦D‰Õµ0ËkÚ„%ô|Éx)9UâkñYeG$0-H2I;ÆFÒ C°ÅÌÄ©àô[] K•A„µ?v¢ãÝS(‰{Ÿ\¦jöúRÖd§gÔn'ºë…‚ ZÖMÛrêm3£¹Ðè>ê¿[+›Ðc\x(²HwË|XúÁ2=?‰\Ï ¨@”νÆ-öÆ2À2 ,pp»6~B7Šb1a—¤²HyXÞy˜eNíÈá‘+Ø‘Cö l}7ãàøà&3™¹¼!4)~™1Ì&D«¡5ÔHu,"fúübÇ8ýšŸN_Ý·)°»´n÷ªÎüÇöàëÀvÌNGE ´€I?¥ø„ø¥Rë¤W§Ó8QR;_ÆÒ¿`U™Ñãô¨ÜÇÚˆ$ß}ÔSr
+Y¥",o‚Éò. t:¥rÇxs™'þuâñSrNÍð”âß6ÕÝ{ùàåä/ÿYÔa3td°ŒÇÜzæWЋ›=œö„ùþàFK3úU:?ynèSH~ ?Ð>/Þ°5ÝF¦mýNó!ìP…ýë–Bk¦Š=s_©7gŒS›Énä s×Òrº ÷yTnZØo©Õì'ßÁ±tfš€Áíq=<D.6 a•„‡Ñdy5d×0…,y9~| ‡Z°SQx6HEícС`œÆgÂæó.81h¼§kO ·†žPp6cÕ_Qƒ©–‘#ÌZ—ü+1³Œd
+a@; ÀYÚ /…©¬çA: Ê„ÊœÖôMú+δÏ5dAZŽ¤½ÉUJÊünÌ­û' \De2ëXh1uKÝ ÿÉ“ÞÖp{òlf6ÁC·wÅ8XiZúgÆ{LÐé¸@XõìZ…ZË,ì 3ÓàZ
+V ÃÃz¬1](VwA0)8T2«ÿ…Å옳>Ó]§ƒléB¶/†Ì4Íf|C;,Þa‹Im•E·›ËqJPðCrc…8Ʊ‹ÑA䉈ò†VŒqÎ ·S%€”>¸\G•|v³ÍŽ‰‘ëk?têJ2„o¸ ÌÕÊ ýämjyß DÈ!´Èi#˜ÉaeÈþ¡ã¸$ˆ€Rð«VOABh˜‚ÆãY˜GæÛ˜k
+eEà&,_Tj/ ´$MÞ—aA£ KÕ´®;ƒÌO¾Ç%C3Â=J‰\.vrkäi—Ð#’öôl‚·ýãë:Ð]’iÆjÆÿ
+ØT` t&óVJ`íLàuh[›§Å Ñ:F—;‚ЛËøàÍl‰¹êå¼é8°ê8¨¶Âi¾•8ÂAo"R@Z;x§Ü{:Èq£#¸ x(ï’¢9Vþsa‚›Ò'cž£(ÈÒo,é Ñ°ö«8¥®œ?'9ðqø-?hÑ¢VFÍç {}b'?1?H¶Üv”éy °Åùc –ÄQoJ’<Èl§DÙK7Ñ*]‰K˜©TÏI›•‰“0ŒŸÔ
+°m«ëño¸qœ
+î‚Wõ³eas(á½&ýíQ‡£ŠOƒ:'ÝŠÆøZ©?âË S6›å‰E b
+?i¦&£­m=|†‹ôÄKá‹^æ¶~Ñ£¢5~kN„…·‰© z[tøJ9´BV x¢°|¢²ze2:ƒ¢_abhü»¶/ð¢ûqoEß¹Ó/®žüŸR—”E+e+‚3!´íí¾ý½‡
+6)ó —Ïmžî«Uv8ZòW4:,±—6o©ÍÙsì—k¬…O{á³,ü0ø@Þù|n*K&"Zî¿ñ`¼Îý–xSÒõR¬ìù{
+<Ûd¿$ÓÀú( WžG¡§ZºÎ@â•O¸I–ajòÄžMe I!­â”Ûö6ß*Š˜“ã³Ç^¯õ\„“†EP²rH‘að4—^0Ô+ŠRb-^DÒòƦÝë./ˆP¤Ó€[$¸#He/‚!ö!þN‘üi 5ûÃdì™k°C
+Ú1,Êj\V¸ƒ‰Š)½ýÞëÌ1øÊ
+¦F¹¼è¯òÚâßyßøªŒºX]Dúlü9£‡öBåœôºD‚¸­æŽ¸Ò~Ç—ì~°/AN ã¥ý!Š’烎 6vöÊå±fìmTÖÁ"4¿”¢ÆPçjûû!ÌÁ
+ghÃv ÄhÝ š¿V2`—·<Gá^¼•þÌOY–‚„$&þ¾<<Vz
+ß`<k)~|~йœ¨ë‹vÚGZ‚~þ/*
+fŠ‡ ‚O˜¶oqÜáãxÖÇC‘D–Í÷I@Ò“½Oè`‰,%M®ghkD®ë÷Þ ¡Ñ?j†…ßauø3Ws;$ ‰®…-ÜÈæSß9Î,UÜ
+’ïÞ‹‚ö 8.dX–òí¢
+ç6HÁ¢ŽªœÀvMH„¨Õ¡‰vÅäQ‰nyìÓ
+òóŠZ³ëéXç‚<
+ãû;ø 9é×N1˜X
+öÂÝ%Ø"Ø}öË,1äu„ö­h5‚¢`êe&‡qñaãAœƒ¢»\~R3¯tCA/»^/¥«¡Ò‰ æ¨h*ô ,ˆè]Á‡‡¶£l¿@m¤™5,^‚[CÕ€Jr+Xà¼
+W¬Û.vÑ-¿ÃÖ¡˜ïRê1™­ˆD%|Û kdN Ît%-Ç´]È»R¨:(ÑQˆ¨A?WláwÇ,¡©ò/=¼ Ô®Q´Êº- ^UŸÄš‚Ÿv‡hœèS8¢GŸ&uNºÁàY™½¯?âËð“ÈcÍèQ”`„qŸ¥1ÃuŽzkExæEÊD)³7g)Áá>ñë”àéqB¬SÊ>ª"Ùæ J|+PñLÐß&–è;Ö¤ÃeàMÂËÜö/zT´Ço͉ÀðÖâ/Aõó`¯"¸‚räï ë| ˜ðÅ¿â} „{ÑÝ'ÜO Hã«9gdrUMŠ‚<ûÜ ñ€¡ß‚êâ& aB]¦ýz(º½.½d®à2 3"ïiºUcžð‰w»ø{ÑÇw^·›ÐÒ ³VD³º#ïZƒRq 5U?B*ømlάA·j(k«C™@v6¾zcÇ8¹Ã™Ö_ýë;ùÕÕ>Í\
+ž“õY¨…‘,%wÈÍÛš"BRˆ;Ó‚ôùB^O ƒ ÑÎ53þg§å¼3 ŽB]°÷pÈzø‡ñrG®äØè
+¸Ú2nÔÿc*æ™rµ‚ y”©ýë$
+=ñxï„ 'Y]$2˜
+·#<GÞJìƒ
+œ×ÂËðJòäÔÏÒµ‰ÝÅ:OJZ×ê
+‹Ãu2&Þ{IËs…#ħFýx @‘®|+GWû\£ ¯èJ#ùkHo[I¬æ !#Uî:çÙDÓ‹ G
+@¹¸
+L×Ø.vS­î[¨ (çö=S÷F¦D-¶öE/?AÎ\B¢•™mâM Ï)JÒ¨Øámùm6Q=ËZP
+ÜEZgpËüÕÌk_ìd-jÆy0 cÛUÒb,gŸ‚åk±¬,oAYÈ8%ü8¤Vì½}éA*È£ ]±VÞAJ€K:F´nÍŒ@zjIJräàÊ„Äa^¿ú<—ÖÀ=6®íZÃ7&F}·WXªW9Ë잘Sa5š&HÄ«•Å*j:"a 46¾J”DÓˆ<;>DA²cýŒY6Ê3¢ðVT¦ÈOgâiiRã`4ÕlñBCçáqtùx'¥ßM;Ä«8+¿B»é’AîþóñŠkš¹Ö  âUL#¡åÌä@FxÙfU$Y§BeF
+DÏÆ<—¼ñ@ÔQ<—ÿÐ`Õ°ÐO¶28\L¥pÌÿЇAFaÖ7¾îâ´3Ácäæm~qÌÚ&§Ìá%<˜ÒÊ{È­”08Ã×æßùoþ‰¥ùý ‰L$þZ˜‹r†gb¹”ŒŠ4cêÓlâ;¥’ AwLñMˇy †_ÅÿªAª5ÁÜÝO‘Z2Øèü6õÔi\†vR:ÂÆhʹÜ\Œ(uj_«Ûæç=Õa— >»ÅDŸÂÅ°*A¯%<‡g²9³ãʌڳn‘P’#àÊÍ[s=å3ƒèH33icžÍ$
+?Éð!kL•ˆéaB _vÚ±p'lwëÛ Œ€‚àŒÆt@ »"{ñṡŒ%>bÄucAAYt¡ñDÙ!±Íb»Ÿ|
+ah’%ÆwZ¼¸ŸƒThê”ÝKwÈ¢(ˆ/ÎF•a ÄŽªrƒ¤¢°IíKÛ×·ƒPQ•ÕÀH%
+nû¾µ,ƒTÒ~Ç6q'€œOexƒ
+"Mk†ç­¯lØ™Tü܆¡k°gN»â†§ä_ˆ,¦4\] þyHƼ–Ö^9CFÈï
+vLÓj qˆ¾œõuþÇ ui»Ò€
+fSA¶ &Þhq-Çr$Õð›—AOøñÊ”j®çHÌEcJ „õ¼ŽäÀ¦
+o ‘Ìjˆ¢YÙÐö±[bPÝEY¸ªs³·‡„8B¹Ì1¦ˆ«Z] —j- TÄ£)‘-R\‡^â3\zlݧI(ó‘ªû-Þ§w²mß^dnÜûå;ö)ìNžâðNê´ùC~ÿå”\c¦¦ƒ$PEœÃN}Ûqñ:]ä€ñÜŒÌfË(<ª\SîÍÝ–“câÊc)v”€NËl$øý¢&
+OžvGZàÇ6[
+чŽÕ|<'™°^¼‰0+ ¼E6¥M͵v’àG¢?#k|i™"¯.Ì8PZ>R®4ö)“èá •“z%ÕQ6“Š”®ìCñÌç"m*[é¿Ú»i³I¡•½£Pöý9\‹bü–«£tá9Ì ¦µ$#,”›%1“"‹A¸‘/Iu=2F½ç^Y—¶}J!HÅBÊ^4®T'»ý—ñrÉ‘+Ç¡è
+z^¡/%=­]xZµÿiŸKò%àÒ@£Ð•ÅžÈËûÁº#FœC„Åâ5F
+ûœÜ­*x2WSJL¾Ï>sT¤j„RŸç{Á˜Î6ÏX·.ÿeQ•&XÕäÝÉ_‹ì|Dw+¸UØ@ÜfÂ]ùŠSŠºt à&ïæñ%„Ä™ãN`¼®žÉÐ|HQô©ÓÍŽ«'Á<Æð Zèe{ Ò½«àSƒ/% ÛÇ¢5ΑAnGe ²áµ‚”:0Øßã+]B™ùàÙ˜ÈÇf£‰?'k1-­9QíA=~Í„”YœB6§ÉÄÃ*½ér
+~ÿ –ÿù2xt«‚"¯‰¯záßÿ>mÙ| ?;üCìÒ1çÙéÁzR VÏð’.DQ
+Ñ&ý”S; ¹_öiÄŠ±Ù˜Ð/,³YZBpñsÉÑáí´ùiž±‹]Ö@nPº i ¾ÃpÚ‡¡BK]© £¸û'x à ’#sÞ•¸PnŸ<ß„¤ìN‡ZŒ¾…¢Ž>}:+¢Ï`³Ôß(á{ 2(å^ÂêWe2Z½£„›– f FÄ­*'€¡È§
+uãÂäK-Þ_¡.™_!‹óßµèòU„ºøùiýôé·¢£INvüDÍí¶ïk°³áJiùÊÜŠp0ŒHfß49J¶èU*8´ˆ1ŒÖð
+á.,yÍa¨£ŒªsauÁ§¯L‚@Š“`b X J0> ç$-‹…z/Œ½VIca™‹Æu¢Ä{ŒdÓ¬™WU è‚Ž¬•¼
+R¦…T™Ì
+é‘Æq1³ÎÇì¥~¦—À%X.›Ï×üá tÕÆôtVG^zaÀˆ6Ü$—á%ÐhÜ×üÒ©#²pDî×SRåªçª·¢? „2<¥5²/æÞ69SåýCtë°,c«âQeÕ Îþ ÙÑ.‹ÓRH€Fw£b;æ
+*CºQg y=GÀ9
+
+‘ÖŸ$E”n·¶ðý|,ä¿Ÿ Qé8\ÖIŒBrØøëv³Ó*!tÒ Éûɇƒ¥<g©JŒ½<bš‘W½áj@,\;Î×ht <˜þŸ‹èÑŒW!ÛL>î3™ÁÁòÂضó*ñXe
+¢àgÀ;ŠÜE4}#™½Â" k¤±Üb[å¬O%x„!©œL'¯z-Â84°HEÃÏÙX†±g"ÐðœèàqŽ-ŸÒQicŠ¹ý<ôANµcsó*O”©¯ŠÓ™²®È^ÌŠA¢ÿÏx™$Éyë@øºƒN à<¬õ–u oK÷ß¾/A°íîB…ÚŽe5ÄŸ945BßÀ^Af °8„ü¥Äaû±R– ¢sÄÙ O#Çãþ£Ÿ$*VöìL¥Éͦ¬àˆÙUœx£9üY&•
+-òë4«8Xf›èáœC
+žKÀ¿áXˆO†x8tõŽàŠxQì‘ôg Í<HŠ™¼¹{Æ\°
+ÏΠڥ
+<«F¤ñÇŠ@ N'úZ!%dŒ‚ºÅçÅ·–ÁÅu´íTäŠ0Wý2œ,våäàt›,.~ÐÑ~žóiÛ
+nÝÑdÉqCgØÌ}J`Ʀ–×SÁ>°6<Ác7 GÜn1l(0š²KAÑãMnxeßÖmVá'ŽñË ÓŒ'×>EIÂeÂ"4ÚU@$Þ2%[f¶œKgGn¯| R™ù$%­7·a²ÖzoráÒ’õb„YðQÒ$²ÂnÃcäÿš¹ŒcÑ Zòõ¯¦æ £êêµb]úf¶ŠØ…×]rqŽU°?P뮌»9~´“Ò ¶ÄÑÁ
+Çå`¥Šù>¦FZ·V§yùˆ,ÞزK*Ñ% UúîË…ìÁ½Iª|Jpýäj¸/ýÌ!#¯cØ@_‹ØÊÒ‚›5øø#ìò7‹2ÍÑè³Cãµ·ÔªoX¤¶å‘Š<Ä~ ÉÒ
+—;^—éBÉØø¹ì¾›ZÞòß7Þa¶HŠþÛ@^Ó…›(ôµä
+ü+•ŠugÞ¿ Ãá»´@ºaܼ`8GÔ7WdadT¡B-“Œè#üÜ—¢çwîôa'²Es±a<É¥m†(:ÿ²ÑÞÅ%‰ÄvPR凅”^\Se·Ô a|T’Y9™~”ËÓ|êÔi˜¥H=€\ðeå*¦NàóäO ”;bÝ×–Ëæh0|iY ·Ù[ÕsP¢O5L—Bïüÿ~9‡h
+Gyšù²ö6χ2XÏ1”ÁŠj>O–.NR/Jp(Í
+³»¨Ûàak|ïz†ECPòàyZ8ŒCxɘWt`ÐŽÔeó„ÀÉVM¡b%ÿ.” ÀÊÀj÷7çl.WµÃë¸ݯ)W²ûtÈ hÆ ,ÇÞ1?’ù£
+~ÿˆŠ‚þ,åÆ}`Àõí¢W˜ä
+Å!ÃQŠPd‚UWˆŒòÁ¹ä‘A|Ú¬á.Š­ÓÃâB¤ÜŽUH®8î
+õ4¯Ñ 
+j¡d)ˆIÞàÛáäH Ýõ{ö®VŸY¢úSÂC*ˆ¿°’V¡:…‡r“W˜^4R¤3¢¢Ç£sq4³…Ë«~»è6ßÓ3Íã5ÍÀ¸ê]Zä*êø
+wÂK÷Ïhø«&ÄQ"G •ds4×ùi>7GPQfôîæ„ß‘Ó톥M½I@ä*á‡\6¦B—„D®¢Š[™ø ¾8¼JJY[³”Ò
+üTÐÈ+1m…H=ÞB'Çð»Äsû~ÑÉ£¢’«Jo°$âm•ÌÚéa]ÚuöºèÙ‘%Òã¢YR„äÖ<#K'qžqÙßHnM‘Ð:lò
+7$Š‚û!òæfûuÆ]CÆrHXˆ
+æHÈ?¾3=²üó?”®¡bbÎ=Žœ÷Å‹L…)²A{a1hÝÆDc›*a>2½M™­¤£•øªÖÝV‚id™Ó•ºe°;4ÔùŸ-ÅþzãêðÏ`s°ݾ‡š?¿bÕ™šÅU„*œ_rº¦É-Vsáøä¿Òñ“ø;‰ËÞüÐÙ?¥4ÃYéš•­¤óš ·ËÛ5‰ævÓvzäYtk¤+šl˜Ó'榆 ©-Ó³8$mv5'¯—ÝÀâ7á läQ®Ï£ßã3W`Z á,‹B1ÂÇd概JŒYû<æ½)ÀR.OÊÇé‰{gu®pÀ¹+Ï÷¦Õèùà+ý£ÕñÉ:ž¦`Á¼ã{•W­Ù:>*ÂmÑh¸o ½|="Œ~±WתŠòcÇs’/lë2~r—´ýü@ÀÌB"Í·.Of¨ÑÉî-¾ yqž£L%(öØv Ý'¿&_ÁZ›×W.–_˜¼6q2vCp
+ÊØ
+†9»e×! MÞòˆ49‹ÙW¾ šž*¿Zž!E€ ¹v壛˜-H¹«€ôŽ™ôY’”ßÊ"ßh&‰ÏéúV =t£¦[ÙG$À™ã‘\Ë[“ð€5uŸ´s–,>_²GOñ ÿó¤Ì;ñGà~‡Æ€Ø³È¬u7 èP
+,¡Ïþb]B \Á`K#u‘‘#°
+RMFaðYîê¨%)ߺ¿Æp³:Æ\Ñg6’8þŠ*nõëGPs{qÍ:‡ª “¡Úgë[E¬&ôM8_1þ k˜ò]–ÛåÈe˜. núå 1—¬fÀcµQÇè\Þñ<ä©æòùP ø“yzе̊Þ»P^ÞŸ—÷ÕjƒŽxZ6Å"XmJ…\LI㎆`žøîf¾†&ƒçÌÞ‰6ïO°‰Ý¢‹™PÒÈ0heæft¹QÅßOôëGTs{ëxº !9z´>Flð¡ZCàm!˜&'h;¦+ìaݨHÍ%OG+”á]¾`åÏa¤ï¶þÏ=ÙÖç|‰~«þ,Bƒß§ˆÐ”DýueWù†î"ƒy×\ˆFÒL’­Î‚¸͆ÏLôû©’Æ/!¦D–CÅì
+¥bçš›µ9.‚Í„Ÿá®1Ö½t%ûʌБ=K¦Êé…VN
+*ÓMIiŒ~å”èÕ¯QÑ“ØO“̓‹5•7±)(j¤Ñ*™¥«ýE°<ÇÌ0@C•Hîy癎¨byê†hjVŸ.bÿŽMŸæ¡¡ Ÿ¦ˆy õ§²\óœ£6s1ç-&)oÏ|5ÿ=ŸP ¶T·“Ø3çP$AŸRŽ~áÈã;\2-·Gñc7% ^ùËwx”˜GÙªŒÐÌ8¹A_Š÷‘Ž¦‡!æÁO†ˆeÊFI®rú|w刬,Ñ$jwY•öôÝ‘i„ɳH¯>hçÖeÈ…wýó,ºàÇwæT㜕/f{¡¥ð¿‚Rwš`ãÝÁ7ÜPD£ÒÚ€!rP¤’}ÝTsÉÇòVb-q*°-P “ÍÜ,‚™½ O`Ôí£®ùÌ7ÿ’SšžDKd4Tv¬+É‘s 4ݺ^«òãB77…4¦þ!v‘Hô"Ï"--ö*PQ®vÙl™±}†ê`ï­èÊ
+&…”eSñ¢5iMØÒÑ þx§/ÆM¬Äÿ² «`–²¢Êé&Ä$q D†É²Ë¡÷–@1ó´«»SÑPôV‡lÏwP 1Òà(Á×–w…„°‚À²H‚ÆÝ}¡[ ®ª’­è_iJK òR?‡*š €›Q Õr~¾wÛjú·úBäž•q1zizÛpH­écöˆÄh×ÕÞôÞ?zø힬Ýû·%²»²é—ûmEœ ºîÌoßQÆUI —åŸt£
+Ý|`‹—a‘¶´¼U•!ÐßìüÜÌPJ•òÙnø3z<ËqEá&Šš†èÿ6})úoX„†p=Úm´)*Âè¡!)H§OÑËG"pQi!N\Jÿy4²å P¶ƒF†Ò³")ä<Q¯¤”R¶ûMÍÚYãVŽEpW\4ô1œ³Ð¥ÂÁ@üqšHÖ¸wä&(9K%.žo Lø^‚¶XuÝ
+H‰cØTw<ùÅð¸Vµ©ò£J)°
+QË”Y‘súf6Žsé`Éóó[¸(ûT³yQ6–Ó[ Jô)Þ‰u˜˜ a3<'½˜°š_VJ5¼M²À5 DXz~ñªô’±(Ú®2JÔ*Ð\¹á#ìð³ä6©ó¥GÑBªf.'Û®çex?¨k2wÿ|Tr‰0Ö~½éÞ›ô‚_)“›½7›”‡‘A°óÁ–¥ˆÚW*>©Nbco`Ë Â1¢ŠDåé_dX*0çø2Oø=ßôñ£5ѾÜüíJ½Íz‰ÔE$û ›¬;B†€ پȫϢG>„ÚoïôjÇb¸08XLÜ@õ­ÏÎ?ÈÌß°¨šG ö@ÃR0Jø%t‘©ÔKqÇÆδUÞ‘’!&ÅS‘-½Â¤Ê„KÍåSƒ¯$®ž{=DŽ„@›2:è´J
+ÂE£æGM!‘*sžc2ÊÁå
+æãÓ=ý[¢/MÜ]ã¥ðÖóçd’B–­ÀマeÉÃÒ6¡¸*†næqúß­p³ºY–  ÙrºþsË¢ÕFîä±WJ$Ñ=–jäi×ÁÂ$Ù•¡œì†‘@”Åçåø´&5[njn%Þc¹VbʤG;<ç9TžÃT EÇhšˆ)dº*9=_ºƒÍ£{›p@&ü!«Ó?Ä–—³®í‹36~#¥×—¾ñû•kÇ~)pá0n\8Nb_d§³!>*¦ÒÉKÆ™ŽN2cy¶3Jè) •Ý<M¼[ì Ò‚võMK8Ï™0m'Ø"`
+üð"FŠ+åû<ÝòNK4ó[%€–FIJæQTäÝM°¿i7#yÊJ¤²},>¥x’‹·§½Ð öIÝðÔC— ·ÝÛ š#ÎÁ w᤾øÛ'O#¤£È
+U¶£dåàH,' S¸ M3ƒŸ[/\<BCâóBÓ³W5«çtÄŽ¿Âô²šÕ½ÿÈVZr'úw}P
+‚Ù³œ¤—;Œ•ø¡—dÆÌ ‡o¿¢– #Õ`
+ò€Å ˆæ›Ï‡M”ƒTÂN=ŠDû óÍÜ1FÆ<‰a3ñAy|èkqGôƒ‹ÜLG°ò’ÔF<ÍýÁ‡MJ3º6Bž#UGŠ®|Š&pg‚Dµg·—ˆ·ÉÝNÍÅ·ãdبm_¢ë
+X°
+“:í“_Ä5CRU_êØj®›Ä»g'fà¦*‘f¯(·|Ñ:sB¡·²žÜ×Û¯ æÁ…Q‡X”FFÖÔ]»¢"D U‘Ýt&ä‰pý(ë`=á™8’ÏŽŠU7Vôç~^É_Òò|Ìócí°‡è+!p’v— œjæ›…TIàÄ-zšÅé7‹
+Ò÷6{Pâ_Ñ°
+¡À¢Õ\‘o¡# ßèq9*ÑÓ2ÀÔN«E5<¦(ØÐãŲ­CRs¾=QÎKø ÑIz„>1´¸~9ì¨èÑD]ÖàÑ0ÆXíÇEX
+œÞêHô KÑ…ñ+ jΣi„> "/×C9Ò(Ñg‰brZL¿;´=4ÜJüSº¼>–Ë5¯Ç9IJC&Böšx&ø*Ü|m-ÆÂZ1.+Jc°vê >E‚  š92ó”ð ΉéJÍ<œŸs ïUEM<QÈC ÑÊ û¼ýŠŠžSo 8#¹ÝNŽ—0*ºíàÇöÔ·ybû•fÄ)Å 
+Ç>à€ª¶Í A%Qâ–aWT6„ ÿ¸Äq Y­ qåÍøµsFm
+$¼fzTáâgò¥ªÑ¥bˆ›C3r"Y—ð&Ü V²/ÿT6W^”L{P¢O 6Î@NR«á1bCîŠ.à¤jx™ñ¢Áü·MŸÒ|E0AnBkkQoð¨pžŒ0‚¾Âþ>Kncò/=‹°¹rY„ßÑeXY;ÄDÁ£2Ԉ͑E:_º÷åÓèVf„Þ@ݺ å)AûÀI‘Þú °UYK1JJ0
+J
+=—þà±ñoÞÒÞè6Oø=õÀð£5Á®ÜúûÝ6½];G{‘oµGjü×q£ÿ<•¿ ‚gÑcÉ£ÏlñíÞ¯<ÓDá°#ÍF{Úag˜º)ñí‘íú‰lc£¸t'Eã ±‘ú·‘ç¼e±?ء쀰cüâáf6›Á"ÍÉb,5ØŒ-{ÔöÅòL&M*¥ÐŽÁâ±¹OÉ’–™Õ+*î¬+ëŽìZ[I‚PÓeü•
+=Vu»)¾½QT„TÖÚÚÖlŠøO¢ý€ô(ÊÄ¡TEP E”ðj")B„?¢Ã ,;ÚJ¤ˆ©¾ËéŸ}
+Å“ÖæÀþÍ!w?e’KCbL[2 ÌeJË¢£Tî“ú~âoW¡ŸÈ¢ÐÙ}ëÉ$Ý\Í¥*7»b*$4(²‰ÀÞHÀ™ÃKäIS Á+²Ò¡l@ÛÇaóW;I–«³oE)•j3òÎNÒEýñ5Âû)‘!ÙŽUGw3Ïèd|ô|JÊŒ—Í: „+H[ÁBÿϹ¾R6ý_ß7½lY A›–Dr8œë–tÞ¹!•%Uä?Š‡$ã`øß7ú•Ä…¹Àm¢y›ß…Â[üeEŒ• eNÖü€èí8$Á¬¢;Yw.ž!º£¡}&¤¶c
+šÃ{½œË¾@šA ý‘UE2zbÀ»³t·œjòâËï<Ä(9‹¨Ç2å  ü~‹LZøF&±Ÿ¶wFÿ¦RW]š€V¿=W]ªŽ4à¾r1ñ0’ˆ<“kñ˜×Ëž‚¾~ò¢o-Ñ5.’´aNÅÓæ¦Lb |DaáH“ÓpŒO ÕæÐzºèið©‡ìí☘Äà뛤½ñÉr(gÈGÆ1¢ê1dzÙÞŠ`ç áÛ3ó¦½óô HçœÜâ3q¯‹s‘—YBØÌæ–¼ŒÇðøN)I‹Ý ²Tk
+zµX™±K(ÁˆÑH‚¤¼YÆZ_ã$²-æÐØt,Î~Ñø¢Ú ¶³|Ï£ËRµE74LPõŽá«jSWRkµR¬ŸôéʺD´5ΈøÛ»g
+1’Ȇڪ1Œ×<³JÑ<˜lëL~wœÀ77ÉúarÂë±Ñåmñ7ç#ˆC ^”ë7˜ÿ1ZšÂ%ª@<ëª*ðÚ¯?7ëUÔÔv¢@"ýÎéΛâ%1¤ú5ºvTi“ã{µ“‚1nVeÎTKStÊJbj«˜+=ç`=‹Éj
+÷ñ–"œÄB;7…Žœ^ÌúÚùj"ˆ¡¡‹øæÓæDkiU¦
+4‚º¾i×òkaK¼i;ré€N¬ÿeejÞàéjibßCwÖå D Z(!èú2 JêÞXZê÷\bþQÐ-ý„»¿Ý_¬Š¨³½Ñf™½üãAbMávN¤ÃÉ4PÍ!9æQõNsDvŸÃ­=0ë5¶ÝbAì"›GÈ45e=®ê<‘¿¸¦±ý(£ ò¤’B²q 2sj—›‡LùÒJiq2^Ä,ß¿’˜ñIwÈ“²µêzDOfä•õžc&A_^æio!J‹ ³ûAüRœêÕx f±ÑvC µ T“GÐçÊŠCÀØÊlIÒa@\^œªáÖα"cIù”â|(â¬ÉÏ
+H‰Œ—K’œ7„O ;ô¦$ˆך¥náˆYI÷ßÎ’¿Âîb…¥…eUe‘Ä+3a™‘cä°ïýSuZtSíóã?½û§ëœi.f!¼Y‹!j7È÷oÿû&ÿýæ]?=ÓÌZïºñÙ3ºh÷Þ¼üÚõìMGt j)³ó§ñÍÇ‚ˆÎ.¡ªc#D¤çð1b,€¥Iïn£í'ÅÐaÚL|ÆÇ_ë¢>³yNã¦s[Ž9Ml¶ÙÔÖ׈FÛ s³i3e?²ÛÐà²~ƒÔMýS´‰Ï òë9íÓ#»†ð?'56zèÔÙl!F½µ9ƒd?QGŠn„»njŸ-ÒgËÔ1ŸÀ‰Ï+t±¶Î •™ÞsgÏ?u&iDË~…™ƒ#BÍƹêTïÖ¬ë:‡y-UÓæ"]SªÄsA
+þ…®æžñéT¤ÓN>tCàŽ^$v’L+A?\ÞPuV•ˆÜå¬×ÓÇÜœ×0
+QÉ ù‚d‘’CÑôÿ²›´Ú=€®æ¼žCÖ[P*èeÆ 'Žê@ƒKIqä†R2/Ð<ºnb^QJvz4as:Œ¬Ê0àÞY³
+eÏÓ½² ½¾Omé(NÓÕ9¯ ÿD¡²ÇlÒ´­Î”•ÒôzÄ‘¨hnÒ%Kaá²A=­(NrC&åu2O¬û=6¸FŒÆyd]õ2iý¼çú»ºþüþVSK¡Ñ$#rx°1Z4‹·¢+„ºM(Í8€Ú3­§b|›£ ‹,m©x•7µ¼ƒ8I òihµ·£%4Ð29ÎAÈYbÄSî/_OÂv@Iè]‹7 ‚c C’0õ.‰"ò
+¦n8"Š7Èöæ$´•M³xÿ¤„ïh*Þ6a{p”
+”_Ñ7™¬9á¡´F¿€~þI᪾­¼X¤9备þÎ濈›1øBÚM
+"eÕÙæ3+ÂË8[!ô³,IOdA쑺RÕ h8³˜‚ŽÈ#vïuDW‘ëfÍD5sNô“«ÃÂ`h…H`çÜáó8¼" ˆDל4cN†MȲ Ð7 ÒÉá«?7ˆÏÆXÚå‡&¬$Šg/ 2ŠË»Zœ°À—iä«-G“‘B ËÃG\…jÅ[é1D2¨myQ9ç,¬âÖK)Ä\¥/±µö¦VÿRóßV(ZVýEÃe\<ënÉ ubà «›±­¢Ù,W(í˜uFnBšÛF|ýž€Ûñ¬|5ñAX†±t±ñNƒÐ¶v\kÉ_‰ƒúŠ¡,#Y9šqLk+y­Ši;ˆVv5Éöñ£å§…û«¿»aàÕY.õÆX…U7„ %B'Ö]ôÁ@öXŠŸSŽ´(še;p_Éú 4śТ˜íŒÅ׎FÉi)Æ}êθ‘”¬}¨ÝÄõZ÷¯"]-• jÊõûdÊ™?zqŒ£®÷‰~á‚VÜ•t†ï6мc`Š#ñ°¬VË´Âwô(&ÞÐÇ™q v—Y~®@ÙØÇf3!(«”éÚx@k]g-0Ì
+Í621#ß¿Ý@ì %Üt 樭iÍò‚ZÙxÊ/½¿‚|âHŠðb³¡gñ»Kn¢óš"/v„¦wc$V¼ 0¿ò³¢i™BþÛ×Ny=Œ…ãF>2—«êUwr"yŽÁ†ðX+YÛ½UÊgdþÙWA+5T}‹—sà0!¬’¯g<]!t<&9¤¬f¨Ã‚¨ÇU·ØéARÓŒÑâkÆ|ˆ±rÐTsST]¦‚¨žýµãáÈy“nÕ ¨’Bœ¨˜Ó²XX]{ú?Ø©mi—o‚‡ð—ÎØŽC‚œ1{üN2ÏŒÔv
+±<Ò|.g.>‚u¦V¹ßšýwµ Ù`F‘“í\^Î æ-Ø÷jÜÌ’k%ül¦ ¢,½ô:æ4+DZÙJgIÎ ôê¤ÄkýÔ*»oüÌ«‘ªËhAæ^È›‘: ¥¹i=lù¡1
+kŽ›¿¹æÈ¡f²\ Å'êõº«ø3¨G+y !cˆUðÝ¥DŒqŸQÀ’]ë™eÔÌ)~úIFMk•ˆQMÊÈŒ†Ù†žJõþÏx¹äFrÄ@ô¾ƒN äÿ³/糕î¿õ &ËÀT±¡ö°¡ÌJ2Œ°³ð02P™øˆ¦ŠŠR]þ°P°Cçó·9»ô ©15¼"%ÄÀwRS|SL ˆ ì[9ßu¼Ä ô;=<­Uí?Ê8ß%b.£¢é4”ÑýH7<@¼Êf§úâ29ÒøÃß¡ÁY§É~‡÷¨å óõF½Õ•¾3ÌS¼$ŠÃÔ•lg[["ÿ£„‹¹ÎëC‘HcZõ¡®òPM±Ä p±kQñ£CØ„¾-Fq¶Ð¬giÂÛU©SŒšsNAÏ
+BÀßÖVŸÁPû G££0Ç$-ÐÝZ|
+ÝrWˆeyñ)ès(3séËãILôÂGc>óî=, ‚ŒôiYZ9,pù«Qçª'h+&™;ÇE_ƒ¾ ¿KQD¹#z½æ䄪Hq®ºWç6`Q‰§•˜ÝÕµÃNÝ çª{Ãç<ióøš'ý‚W=iü¨N4 ·ÿ8TʺØÐÏ•$òl:ㆿ¶&1’»´ÙK"f!åkঠq׃¸±b×íÚI³(BM¾çàØYßÕ°oÊ8VRòh°°Ÿ¹n-ç®×$L4Yu¬á{y]Wla S÷*Ù£hËÒ„jsëЧ’G5~á(ò@¡¨õ⯠jídv ýþ¬
+£¼:dƒ°åÚàÑšDW‘æpPð´k©¿8G©ÎðÏp§-su
+’gâ¼K„ˆ¼ÌŠbŒ“;ܧŸ›y8<cñg9ˉ"³úXQmÖÙÈé'v
+LEMûd$‚?bÖ×ÿáÎ3
+LÇ0¢ñPÂ]uíÁdwN…ûÒ0\#¦>þÛ3MÆZÉŸÊY‘E£"ˆ­{¨?ÑM+”ËÄ•Û¢HHQ"‘ Ó¢¨†€ùU™',sÞœ£o‹'Cy´„iC#‹Q¼&9AÜBÜ#i\ÕØ–µlç‡M v'¡Ë§Æ+'Ì ÔQ½¢¡B™)/•!æÃÇÓ¼ÝÜü˜Qg&ŸéËœ¥ðˆæ°‡4Å(°%‰Ÿðôk¿´.†
+·Ý• Þõ3f`
+@”†ŒÊ^Žä‡T3ÓŠítU’M®Dk+=8 -åžø€jÓY…ÈLptÈJ{à{¥ã@†9gŠFi5€è*-4hÖ-É•çÈJ³-äjø5 e'à&Z*¿
+Úñfö{¸®¨8 pSL §ÔVø ¹uÊoz€d¤‰t©,­öàcÒ'’†ÿB\ŸðQ ›VO’ßt¯M‚qEv+k}Ù1œK'<‚CÐ4œß Ñ“.ô|¬Ñ rHÕãþ‚1¼u;GÆÙf¸P„~Í“ÏG=Yü¨M40·
+ÿ8S¿®Ñã IÕé3ïïÓÐ=ø3©¬
+¼æfD5v".—å¼Dùy ¡äsö!ÑúMü¦‚:¯‚
+˜eT+ßWù€´Ý¨+¤&sVˆ‚ÅX:yíâ®n²pdC1ºJ9‚ü(S3íÛ§-IL{a8íªò9xèÐ2u¸;¤­‚9Û9Š'˜g¾u­©X <|wƒ´¦H³ñGÅ!Ec“j.Tѯ"Àð 6¹Í+™¶"‹Ëc—à Q\æ4_‘Zb!ÆܶJ™dÕŦêízÒcßÒùhÌÈùÜ¡ô¥ÝyŠG­Ôh\C¯Aɶâìõ)—:š‹;=`÷æ†OWF„rˆ"…§5Ö&‚à žŒÞ£ˆdá$œQqÒ„YuY=…½è”f¼b_Z~M§ˆ _`­ØIŽ£Åx¹š±3þ&ȹ´¿ÑE&‘lÀÆå1jQ°£BeÙ9]%HòG”)0390¤5Y›"» o’ÓóËÞ4ÄÅ…ξÐ× ŽGV‚ëòù¦ôOÛúÀ
+_GŸ«OœDcGÊr‡ŽÈàÕ8§¬Ýí%Û#Ó‡£|~4ú[X`É.#è•|®·¸À>c«‰eõsu…8%#+At Ì÷V¿ï¬ƒ7h²k;–„ ñš´Äšî½ysúZ7—šx¥Ò,,RŽƒŸ¸°UôƬ”4,"¢æ£Êø{`¼$^ï¿¢¢§Ñ¼(â€Kù…‡Mû„ëk ýxþiU|ìîÐbù.Ô¡8A Üœql‡ÅÈ%׶ÝÂE¬K1;‡.™èšb;æÝÖh/äùi©((< ^ˆ(%Ñú9@;AGd²ê[Ê“ªÞ¨víWaX³´â²O 9 àwäzt5/Š DÇårŸŽ‘v‰ûe)Ù4å-‚ÜL{é ßn÷{€þþË®¿Æ``±ç¬^Š0 ›
+žãóEÑ%+]4î)B!@>Ò¹Äaª¿c =Õ’£àýò¼T0I‹á#õ6{Š€
+Hm+ì\¯°Q+‘­˜Xâå!¸‹çü‰oX^L¶Û*tzÀ–µ”èKø’"~–}î%< c(YÀž•Yy
+èºj«xÜ1…ã„R9DÈHXJÀºjPôûEË€-*ÉXâÊ`MÂÜúñâðÂÜhªØ5=ÀÄöÃ>W´M»µ’•Ô)äëM}
+c§ö`Ӄˌ
+<н‡4
+^-ü¥á"=8¤+|;¢þ`æï_}=´/¼ž˜joG®2</åÎlflvAcúVÑY»
+`?ˆb$»VgÐ-l˜Ûmçìpj›1É”<´oÆTCÐÕR·Ïwða»!¼ŠðÛ1Ì“7`fÚI<OF“<ˆaÌÐ.Dö¯¦‡h
+Œ³ÌlÂW<¥—ðpÑ*,;&÷ Çfw?8
+ž­³´¬ w
+|ÝE‹
+Ù"§Ú|+X> Ls!üsá+R®ëØlŽ;Æ~•Ç»Å¼jâq âü9ºï˜Tœ+JA`ñó,8ªä®O+"¬’|A_.n$.‰êà5ã¸,•%Jå…”¤ÃGä>+AixÖ"\+(ïaçÒ^CÁ/ÎÊ1ú°ÃpIªßeÁ­«—.‘6]r h›¡³?É÷^4v)¨?GöºŒ×jÄEˆ·þ¸ènCõ9‚)‚FS‰©ÑEy¼jš]F\ã6¨ˆ¸ â]ñá¸ÃÅáîžv‡FãvÑ‘­gFÕ0¸8‹g3³†Ê¦ Q9¹ƒ
+Îé$hÄ#%(ÄP;€Ý[´b”Ìu±.Px9Ÿúfå Yä‡ò„GÔêÏ]ÄYè \æMp#:Õ+ÿ¢&ÖÁéÿ¶$žGßÀ:Á¦`‰¨¨üNŸFhÔ)Yâ‹$GY_þ:…z$ŠÎA×SQ6¬’ ¿ èŠ
+lbNÖÚqO­¸S”ÈG6‡eV2ùsPL'ŽQ£U<¼‰¤lZ¡'8ÉÉByë¿Œ&LxDJy3WE’èB_k¬…eŒœktN•}À“EÈS‡ááêVA×ÃSÒüBa£Rœ´˜C–”åμ2jÝ̉è€)¢Œ?;¬îßKmý”eø®èføýWTtŸ¹À'Ü$³ÀóÇE|Žë är™ÁRÚ6yÃ9#5÷T‹¤Å`Ì,6O÷ÝúŒ¼á^°²Fùż¸"øH¸Òþb\ý¡üÇ|mæãca7) Ra%P7g-H.¹Ú²€¸%Ƭ ðþ+*
+ÚƒM”7© ™ÛŸ=óÇOØ[$Ÿ”+kŠ€H‡ïþŽŒŸV+tÚ‚aè#(¢Ç`ÊÉK£
+órU,Ý©[<ÓHäæ±-ˆühÍ™Š}Àaª)´s0ÛIDE“}&|;ó6.WvE*ð‚Ük+›€ØèêJ‘ÛÑHø©ë€|Û×ù?åå’[É‘CÑÔ4îÿÏ°¡©§½‚FÏÊûŸú\2RöËäCUF’©È’÷w+úãM‘a1I$ ÖŸ^„,ã‰AõrAݨ Çt#þjtÒ¼üµ$l˜<H [ QhÈPfï ì…}X»4/*SØ€,(‘’‰6ñµýá¬~9sYÖtÖ£W ¡koänÿ´¡á›Ìµ_^òn’mhÐ"¿Á*Q’h¡\V1-ô
+Ö¬PÕŒ P4ù‡‘B­—,!i)t£”´ÆÌ“À\.SÇ«qCèy±
+öE¾°k£)‘„bdÚöÒú§F7Øuô°+(ièõªúƒAÞ9U?ZG4‹û•½Wǯè„K3“J›)dŒ9ùõ#*âÛX×ÄÖ(¾ÚŸ=þÍ",>\«4µ]Ä¢¢8WÞt6äŽUób»OÌe ¤sæì{1]Lñ¨GŸÆ'6PÇ¿GžÐ¨Ž¿³raEÞ@n
+Æ©žcÐ'.Ûu=çŒ>hÉ)õVâ܃Tb=âsØœJI(òZ§„É#$ZË™»f5ÍƒàŽ•&1‚’ÑÏ*ì ¼ò)ý‚yK}ðü¬èEIÆŽœ\ϧj$Þ5;题*¨h_¯Ê(>ODì×^4
+U“rWpc'xVÛ’VA yU¢ ޛ̳ø‡åÝŠV!þ’J¿,yá4TÌîÀ‹Ö Œ2T‹L yã>‹ž!—"¼KرXÿG·iÀκjž_ûu ûÜ¡ÐÞæñ%Q£'óf>?´B”lì*HÁ@3zR³æ<åE`øk…Òb~¸Êz¨%ñTöjÁXךÄv31ôqØ1°'~îëZVœ>4'X.+Á‡4%”zÈûVâ_R6•MBüæ­àzÿØ2r&fC/Ñx~†
+8ël+ç°+˜ZIG`½ÇØi¨YÊ·ž5Ã.6¥$Ùe{ýg›ÓZ3ÜUº§ëu…‡­³?†l`0lKtN%î`Aá 9Ã+/R€
+øŸ A,^‡ÉN!ø¼D^¸Äœ­¤i¿ä™0ÆG’!zn&t˜ªz'N ³P1· Ä1ü%Lž%¸UOû_ Ì­3Ì/÷Y!•À4UF <Ñ€³ž&_iîUbTê)RâE¡³ÂPuÃIƒF9žÍ#@PÂ÷ßß± ‚ü.Èþ) Áƒ:Ü8Î9Ì»Èl9Ü™\1…¦5/“*ï ‰lFTÂñæH"iŸŠŠ^Š]¹èïðúýÊKÃ΃Åñ
+ Æ‹HGéØXQ2#û_Ï£°nô
+'Q¾¡3*ÈZlòò‘Ã] ®õ»Dµº¯˜yÁkÇ^W ȾnÂÔ\5*24T¬$×X¬s­'[ƒ¤8fYMKSÚ>·¬èÂU•ü×!É:’ý7iÈâãñ7ýP B¯4—Ö6 4i£ŠJfEl’dsgã0ÐÉ:L,!&pE?ßAÉMε’Mí]E½á¦@ût(…4IPs˜ã|$Küí¾<<Õâdö@'-šœ}Ž/°¦ x6(ä 
+Rk8Ï—ÿÁ@HÿR{s4
+qÏE¶tÙ),ï4óâÚŠ@Áe ÄÏö$\@Áš#'%%9EØãšSR¬Â/ç²qG.âe݃!‘e¦×.Ž,Ê}"iÇJ`D܆æ`“¸˜ºh•×t‰$v©]DÚˆm„Zþí¶ZÖsžê9G‰`` ‰ËJàj˜{x6 B]’†&¦uàe™±iâê^¤¨@—²²§¡J³]jÛ'mq-¸{W±åly®?ºÕ°„;h,)¼Ø) »¢VŠR¼DÔ¾H€§s £´È‡§õ’,²XÏÝO÷ø.÷/ß;1ÝH3>íÃ¥U¾+)JÅîÌ£"?"ÑNÆO—§
+ueÓü­0ÀnÉ Ž5¢øH …LˆQ¥ŸËP)L1¾~–
+…4wÕú朼i2c‡e»— „Ù•¬$Áã(O›½OÑD^@–·Òg¡ªŽž”ûÐ2E¦?˜
+žÞ­t(2¶I<v+R ž_À(–ÃÂ&¨í<ßÅø{ü>³ÂžO:ÁfìzºCDÂþÈ»Ì"
+Cd-ÿ6+Ĉ—ívJXRŒIhúV
+&pÇEºM[¿P5'}N´r)ˆôò._òt°‰+ìo‹Ÿ¿0Ë—LÈŸ²ƒ9Ž—Ïš{º¤BÛÄ×`K±_Ò¥vØÅß9N—Z)YЮüt‰ökº–@–²–¢GéR«¯âÕdyÃtIþƒ8É©9•(]j†ðý$|Š¢tI‰,ÐÒIß%÷tY¤ýte¢#-J—Rh Nf‘»¬].mYt!±¸|Ü-]R„°u=V¥K•@iü(+¼¢t–ÜÓeXôê¦ÍâpY”Êuô–-ùÿ
+¢¾RØ-[j
+
+±Œ‘‘ÖâlI‰¶%QFÍq¶£ øb:˜vxζÝb©ùyï([R‚òf ç8²dËÄ šZGtkWìyÍ–ÉXºj·wÚa¶ŒJîÙRØäd6'%—Çg´Œj^“¥*H_[bH—£d)ôvbŽÈ£Õ'KõFœî~}é5Y
+áNXr£a° ‡y–RL1jÎa°4¦g×$úÄŠ(XŠ&8€ÉëK‰ƒ¥¬„bR®†ÁR%–Gê¹FÉ2,¹GË°è5[ª[W´kÜ2Ê–Ò¯1ñ"t<½Ë–z:4‚€°¨}FÙR=§yâ#W ³¥ì§iТ«äž-%MZä;N‹²¥P%bä¬aœ-îƒ ,¾~A´L
+ë¨a¶ŒJáòYô°Ó°ÀÖXðsEáRÏ–óà™X‚‡K‘h’öÀ=
+—‚±MU¸®0\
+U¤¹,SfTr–sÂï4Ôž3±0Òˆ|ºÝÃ¥AʲÉÛçý —uFQgÅáR…&ÔmtFá2(y†K]y±ö^ìq´TÉæ4–iËÈ>£¥„
+ý”¯ï»¼$KÁ_ƒYæ QÂd©Ãÿh8ƒk3J–JØpèÄæ(³|FKí̸ i
+#ª)â”èwC|-…]±å’©-Í¢[Îwö ‘}M–¿´ª
+–ÿúÏôñïÿýÅx™äˆ‘QôºƒÖ^œ¹î^ê½-/}¿d
+®ÌH—h@*ýb’1üáÇ¿þó£õõœíNòòºš²"9vBz—›ÛD.KK©Ó!‹BIJ¶É!²õÌÞo:B@.³š²Ø|®Ùㆭ÷À ^æÏ]UYÐÊ€ÀVƒÏéA³Tà4À6^åàmX.€ð%@ЦFSrd/çðw˜œZ—Å—!dðÏ8xÖ2|VŸqå‡Ýö½0 Ñó<Ãê†/]Ú_z‚P>Ƨkßç</Ó‘iÈSm/Ob˺bÀPÎÜ_ºW¡a
+Ñ­7%)©@˳Õó©;¨@9Ä»ž ¬êçTK)lV½6«ué ª¼¿D“›OOJg­’,ŸHgl÷¨iç~ìl»•§É÷Á“GñrSÆ…o#Ê›a³AÂëðRöËÐÈÆ?Â
+Ô°HÉŒÂû_˜é+æ× †G¢ôŒII[ž ¶„‡hØ•Ü7—JõúäcC3•Iu2Â/wrôv¬uM*MY\êš`,D-r…;¨¦‰´Í…&…»JåkäÑW¡I®²G˜¤Ù LÁ¬d·‹À¹È$“ùrzƒÓV0*çÆY&/¥²•ùrŸûrZf†ð#µÿÞ–/ÜŹƒ¦QöÚœcPTQQßS_èï…Q¬ !krwªŽœVo8ûÂcæ‰I€>_@£0Ÿ}® 1ø»„ qM?ýæú C»”µ÷7káiÂálžÉŽóCxüÚ)ŽEÅXóÜ™‚¢°|9×ý%¦qŠ´l®u"/òZ—Óê–<ãD
+vÇ!~éNÏ|ÜÈi×P,“eôZ> †]‚XXJ¼ÁîEe“em\ZSµjÔqäåRE—ÚÏ<{
+ä1Æ·Á·ãÒ ‘,|•±ÙÔF‡ìð^SB¡Én#v± mA,o`Xû¥Ì‹M-»UÒ:Ì:®,‚ìOUV‰#XÛ}åàîKIQ=V÷å6÷ _õä[u¢u¸ÕøÛµúëlŸòÔ×+ÞÓ®š7¤³œy8á z¬{ô¹€8¾½Ó&Ž$OÙÐm—x?l
+BÖ—M¨2!$ü‚}g Üë…êÝhv5ü»
+>AÇKÞÎñu}À·$I•è²Ø´òîâ1Q<˜Ü5BU¦ãRßÖ߈œŒ+#¿õ’Sa¤â]gã¹Pfèrc•€VT^*î!›R·œ1qÿ¬BŽ;l—OÌ¥:Ć‹G§­"°‡^ÃÌÔÊÝÿú`ž%®XÅ%#ž%þ#ÐSõ5œ"³Œp-{ñì΂Ï1í
+¦|¬à\frÕó)äBËÑ(/-x‘eÚêMÐ õF™2—$¯H ÿñŽ#¢˜KÓ\„j¬¡ÀöUþ.ÞˆjJTÜRví9Z ðüP q>ôÿÇOCj?ÿ ³MR þÀd§÷¢Z´5IãžTmæ‚2˜Ãk‚¾`„àMXD>‘#¨¢o ž3·³Ë(¿ƒ…Ä{øµ!ð^É0Hɚ瘱4VË€ 2ð*•Û²Ãª&̹x‚ÿ2^îHvÜH]÷@[F˜S1iÎþçÜŠTWå >Éؼòsó¤m ÷ iŒ¹¼$¢^1/Ö†¡ã40ƒ§¢¿_ˆ|Xhyl>iÑ€i&ïe¯1D‹( ÎVó I›/O»Æ ÃØ®¾sIm«±÷P®µÇc ‘¬™·Ê½O‹ªžŠK’¨Pjòï™úCÂÅ×éÔOãP†ZÞeO#t< äNih–š˜w^ˆýOÍÎó¢L„ù(4pøºSûYÕ4협־½ѹYŒôZOqXVŠÙoo‹ñ02Æçäˆ0½ Ì™·ôe)ašo’ð Ͷފ±s›©̤>•Qû˜</gFÊîÇ ¥Êæ;ÔVü]¸M'³<­_E?4y·˜?¬Âdùêƒ`0)Šh–óô[Eóö%¦ûT“{ViM]Ít~è,ÏÄEQ¬ìDvµðº€ÁžØÿêÅù˜£ivuwg¿¥þ†õzjâãÐ°Ñ  ŽÄO½ÄÆ5ÿ­‘Ü”¬ ?"ä>×·ïhìlþ­Ë+§kY˜Ð)Ðè[¾Ó}ÈÓùuÊ’ ƒÝÓ›ýã÷4â«®*HË+Ò@çÄNxn»Ú'ÁÕ®”óÞ˜x*b–P
+Ö(Ëb.z|í • ð/cJÛ' ~íÏÖ¡¢ (
+¬™aŒ“PJ¶òš-añò‰ÈvQ,؆a0wÝŒ†u%E¶\Ý ‹Ì¹ŸhqY¤ŽÓ^'ãUY@V˾Š@šEŽ~ÞŽ}“|÷ð%¶JÊž‰kxNvp§¶9fµ«¸:uÛ”Öú5J¦a€¢ÅèL"~\õ„ŠÀ¼'ì‰+t5À5ƒsF:ZÉr“¯s>—)ñ£¡ø8ûG
+yǸàt0%_· ”¥0ò†×6q-Zô
+žP#ȧ_–¼°¦Ò׌_ŠYÔäÌþ OÆDOÆEŸ_7&­w¹b‰_/ï:Z¡É9fü žï¯4Ðá™$BÖ!œ‰B¾jl‰«i8DÇtŽ¡Òƒ8n‹Ÿ¨'yêËC¾¨ 6"îä‹ùus·A¾$|bjb@ª1ä¢'ÀA~StÇüPô™óÕbVÊ6]çë©P¡¯šè1çÝwç|YÖ«Õ«Æ|®>×—¹2?ŽV]ªƒN‚ùÑ2à.FJy.ü})>a>ŠÆõ´•{…ù²Ô®»Ž"_
+0_ñDÎÀf‹0_5Há·?CÌW]dVm[-¸ð™ªÍŒ«®€óå!RÁÔ# ü“‘:ç—Èbi­Ç °ó¢5‚Þûéš•ô¤z›§û²MÚc¬z¹Qäž²v°‰ h>e¿0‚,f^øв²"‘ô,ÂÇÃìº/YaSIGa™Q—tfµâMåóåt¹í]tãØ¿ý:ü;$L±Z~[ÄæiŒtòCZww>E@œFzY’Ò%²ž œvV»Ê^¸prs‰Y¡DA"6¼ã^¢BÏHØÇÆ
+žcFvùå?û՘{4\ÁIf`Ÿš¥çº„¢¨‚,—y
+T¦ë&š„Þïx¦‰ÑKHŠøyô#JŽu˜ èç”Ñ»ð>¥<(€Ï’ÜGŠ¢è‚à:öð>4A3®Ù¸µ­ó¨·DAß=¾öŽææqCÝDr•¿þÃVö¯ÿ~ùë_þñÕ&Ø:rtB<ª ø?É`$jÜmd
+ܶhßÀ½;ß–gß 57f"¢‰èªŒ¸úN€ü´f­k.¡Ï¡jáå’.B*øýÌ‘äû:‹‰Äž6˜Èkôð£Ðyv¡æ¨«¾èzÑ!Oq‰Pšð˜xK—qÜ°—ìŸb<30wäç
+Ïp V˜Y[ámʇÓ.]O'Ú‹WiµÁ·†_:Ÿç0EkŠéò¡¡Dà•ƒmˆo—-áŒBBMÖ†d©C NÂ|¡ºÑ NH$I•ÃuêD—¦ÅºÒÜ6ݽ%âsDŒ:¨âe‘R$ÂÉ MIq'I×ÌUõµ-aûH ´ây®iAÖ8é**%ª›Ûé*5e‰Õ³0­“S ÃÐ~Xü^ s­-H»2J ú—¤—•Å1½‡0µ¿8§ÒøËšš¿l ÍÈ8K´C^êJ¥E"|¾éUÄ„2Ñ°ù]„P«“…ã
+»DÓŠMø9¼G!¥…|©z† †ø)EÇc¥
+
+
+oj,$¬ž—C1ø€N;œ›¶DU–W«[”Ó¹ eÂ
+Ã,MyͲʩÐâŠÈè”à‡ôD3X :–®ÿåªGa2‰%qBÓh,Ë(x½JôÔ2]91 е7Müß;chÓZ· ÍbÖÚŠÜúW’ñem—:§«ÐUY
+–EæÐïþ6è޲ื@ðZd6%!¿'O%¡£ÏÉ:{…^}’±ïô#ñ`û GäÀ„*Lƒ`Âa/mæÆþÉ'QAJÉò«Þ€ˆ˜glçå€d»—ÔhuûžàæÉ{ç‡MÕaÉÖ,}*AMCñ1€¨µésðÐ>Q¯Y>Ós lR>¢ #óAòß2ˆüK†u? WƒÏqbHbDZºáέžú%Ö€ÏsÛÎ: [t^É¥KvÙÎbx¹Zá;ÛÈ SŸ™Úƒ vmæêH#€œw§nugOˆ}ý%–Œ61âJ~aÔ¿Wq4%„à£e¤µƒ¤F=<ݨ…gáÚ‡æ°Õ‡9 @ÁZÜ{ôºª¿ßÙç³ö'ÓHíájÞiHUóÇ1š(ØCV¡RÑ!ÞøP©
+(Èâu™osCŒè©ï¾¾ƒf̉4˜!¿Œ¼œÂ
+‚#ÄæŒG‚¼÷è…ÂÝz‚Á0%¥mAw"ÆÅcžs¢á‡`"&5ï!&^š¡b넆rròãZZÚ[âMmAh²ë%wx§•G%*6 ?e ï¬S”„ÝkÄÕm7Š%ÐB´ÀùóùF™ë@hõ”@·¾j
+Öï~Ü[ »+ù™7D/ùã¿@J[3±–Ûnc: E°¿ TºÔŒ½ªWù$AŒ|¿Öz•Š@MYBëeðYŒL´â¯•¾3#ŸªŸ˜u~ÉÌNvÐèÈÚÄÎm[ ÊÀ–%ÓPØãHyY­¯™)i cwZ§Ü[nf-Ü,ÃT­»XöL—ö@RF @=€ ¤²ñ產Z¹I,KejIΛ¸ƒ­»Ø›ƒ`U˜ÁE€Z‚gš0´ywƒðq¤•í¥bG!iüvêCB ¶ä^g¨Ž*sMmòt 1p¡UšõCÓ¥œÉçchm‘æ•ÿ0È?ûÌG’/†tïtº6XÜX2‡ ý=hŒªAôO3¤ü狽tÇNaŽÇ+ .Äj4—§C¼,ÎXU+€ÌŸ†<[Ïž1å¡øÔq ]»ùî6†M܆VOÅ¡Ùm@n z?y‚%0;¿@èKÞ§mÒ:Øz_sãÑzš=÷y9ŽB•ç3>@µ
+—óü5|5^‡zÒFnÜùdx–0“AÑ ÎwwËãUsØúˆOë”eôv?ƒ1D§aT¹Ûå—ª¶°÷3òk ȾRê_¡#©åÒGqeƱ­LÌÈÂú$òÜa{9¹A*&›‘F›»ïÎqóï²ý@89 ¼éÑBšÀ°Áx¬J:d~ÃÐòŒÙ„1Øðfï^ãwA5kÿVÓØ\D fT©f+‡u]ý&vt*âÄIJØaL>ÉÒ¬!ºA¡ãÅ{A¿­‚÷ÝÃ,²-‰ú F_Ù »Q–+©Š<ôŠu2È4?žÑÕ ÎIüÐḦ«0ß✖/s£8€ñý@u SÇIõ27º;ŸaÜ}þXÒ äùCÕ e–¸–fŸ™¢—¦°‘çU¼K/³ m'ò?/׋-úOêÕÇÒ›Ø úWFpãCðVÚ!o¸ à;ð;ŒqøãBò(m‡ ø#“þºD9ïÏL+ö
+Ô` ¿@S! /Å ³¥‚°78[¬Çö"1ÌË ù„ŠV¶Iѱx%¯"‰z‚! 9XzRš‹t—W§ö\¸
+€è%t¾¼asû†(g j}boŠz¯MßAI Wb
+ŠaÅQýé“Y•9/µSe„¾L,a+ÑwÔ–dÙnt_ŠHFÊYOCÇ¢ $öÙ†lÍTnYÙ¢ãInΫ¬§ãp óÜ*Q+/8]ãŠÊ<@ˆa$¶šh®£þ}–ÿº¼FV–ƒ;àödÒ.½­ ]PÛWÁiì0„Uü!.½ l}¬ËF1ò R5 Bó <Ê>÷F™Ö.ÔV<YýÞ7bº¶œ†+ÿg6®Î¤ÙûsÀÀ”9S¨“@0 |vhå"È™yxEe£=–m‰[I]YW¿ šå”!µ·™·àRyzñÙHç²qñ™ŒO®¹¬3«AÆÈÒWB U¯Kÿ RœƒP¼©Y·í¹ƒê§þ.¯EDÊvmþMQoh†HŸ$<l‚p "ɦÄhÏÿ¯—ã0n  8‡°?,€³¯EÊÿê×
+ô‘ÇêÍ’S¬EšÏÜÓÍvSnvþúZ±ÖÔ¾gè½NUþtJ¶Ô¸U:ŸS4]"Ám–˜[3s_ZÚzív'æò(Û\`{Ë@r–
+<f¼5T‰OëB¡í{œ0e]W¡O<ƒ”l4=ÔÏ~‚fX—y6oš%>Ú§—»ßCE
+7É÷=0;ÅTQ?@º'¼NóØ(drJŸ¨Þã,fIÈ
+Íð³‘%©å@»ïë”mjµV*2†òµÈÉç^Ð: Ú[úí=j[hø~)ú1ŠŒè¶F[lõ*"öšÍZ>žzû?öƒ9êò×@Ep’ô®QŸnVÓÛ²àøWo«9ý®"‰Šn–aPg--PgÁzJð¦Ðøí¹*~°­ëö] Á=c‡ÊsÑç-äªÅO{Ni£åWèt…ÒôÙUC%&µõXÿëcæÿóªšOPû@í4)±g5oœöÇQ¿Áßÿàø¯ü¢«–=\‰?/{ösùl2Ök9ÿyAŠW'å—ÚyÊýØë,ñĪIä7#MIÉ/„%•÷¯>°Ñ? ßBþœ =®B’ä©î1A)a‰8Œ6"Ò›çPÂÒŸac×ïÞeŒ Hxõ@J QFC3¥<µá~aÜTòØãô‰ø¶n
+5÷›j¶¿ÔœsÞ ~Içbïq 5V_ÝZunCDû®„(w;Òö¹êsÑÆO3ÕÁ£s¨§©a˼¶Ïìb `Çw3Å ˆüv[rœ³ÓùÚŸ¥Èo9»³¨t£r¬3—¢g˜:d}–P•Æ û먓+%=çë:åŠä¢å¯ìô¹èï×¢6ü¡mïTƒ·"¾îoq›“Q5ªè—̵Äú@¹Â_Œfx™Ãä¶î;f YAÌrÎCN:¶é‚lá‡K.Á1‘¤iâ=ÎѺ=&½–±4ñ‡5F³ÅÊM°ó×  ,ß]^JæU0yÆõZÀözNZˆ§~L€YŠOG ¼(××d¯³¦ë«œûRnùØ™_(lØ„«äƒ®x”Q¹‰À|ØI2~Iî«ß”X0GPÇP¤ Ù­¸Zôz>ꗢߡhŒã*ý˜p¿{OŠº?™º±ÃÞÇõzTyFE¿’èò|ú4®ò-#äñ&‰—€eŸt¡¹~†N¯
+H‰¼—Ýn]I…Ÿ€wØ7H Âþ«ên¸Šƒ„rB¹³<ö™!"Ž‘1óö|Õ{ŸsìÝíÉ0$Š­œSÝ]?«V­*¾Å uÑ¢®ÖXjlÞ‹Kâ‚×ÔÊfqó‹_^iM®5õF_½ŒVZ‹kRø¢¸*žˆQK\´%§1ñEuµèò®_w4n®¶$M[ 1¥e|'F§Y2>”'þî-º¿%8Ï5ù\sœÝ£Åy_JM!ó¢báþx,T$)Ñ¥–sMQU|}ÁwüóË÷ü”ƹ¤Šo¾H[¢o|PrË%H.m¹›[eç5cUy¢•EÈSh¸,>dá™è½ãôð9ÿYO}()ö€_>­.†\jn©¦\fï;ÿ×û÷V!¹"R[VOc÷³i·hÂy,ÄUpÐH{ɱN"$åÊ’LŠC陕]ŽM±J©éôž}.G_¾V“›ç5ŒùTÝ^-p™ªj¨-Ô:‚Cp*ásÕVya0žvh ]U^
+FÓ¤©²_OL{é|j«ó;{¼mÞÝL[ß8®„e‚t×B “–/.¤P·þúìxjŸ¢Ó;/äîØšª‹àÚ@ ¾—îÜ ŠuŠÕ×"•,§/5dJQã‘,AТU )¾À±>¹
+ä@l™œeªÍ([.yÜ $ #PÂ@ÖšMªb­Ôš+‰âå^vÊŠ}ÌTG4•dÄl>V:6™EØHŽª¤ n€%Ø´¨Õ,þ$'ɬ¸å8¸D¢Áì4|ÉÚ™
+#s{3Z§ïØÈlI(, Ý ÁÃ<ܬMÖ#k6‹
+B²mD·ûI+<Í—9vJûµ6Ñ©‚cHØpÁ¦’§qøm5â5_ÎI`ïɦ:ÙG§NÒÇÀd34 ¦@~ž|#¦­M|æͬt¶oM nÛ¤üˆ`
+‚b.>Ÿ´ÑóDôý!å¾?Ä.Lv¹´]á„bIé®ì
+Á ð•æim.C=m¡¹mI&ö pM[¯É¶IMð„«¦p«(g@=ƒ%›Z1÷í­&ü  × ¸Ì¢Yä“Î`Ï0ÁbÃ9¾´ï°ñž}“Ž¾ì{}Óž)ÆÜìÙfHïž«¦U8o(öÀ›^þánäñ=~'`×û¹ñn¹/ìxaysyÿ™QøþOׇ‡/WïÿyõáðÃõãáÖÆâ³1ØžŒ«·~ý˦!òË£yQ3©zV|w>£h”Eè2^&¨W©L³‹!ã?ä—YŠ-ÇE§’ß]¢o>-{ }ãxþ^ëDÜï=‹*„  $Q73£9Í>kwij °¢QÁÀ&Ÿ‚ 8$°C6ýñUP@¤ÕYž ©’nJ³,ÿ÷X\>ç›å»ˆÜbšn/ŒœŸâ3
+sõïNª2÷I¤øÃVycæ9m%z˜¢e"œG(~Ê`
+üÈä¥ ñ“"áŽ[4LQ ‹‚‡±õšRs`jÍs”Vôc^€ÃŽôj´a!¯ëîÔH5­;¦Œº
+Æ¢Pi,ßG˜:ŒFÖ>Å[Ôòò­’5<ÞvéÎð&ݮ똗2YG3BŠË¤2&Ѹ`¬ËiÂÐ ¥[ùÝeP©´j`Y`M®Û9”!µ?c&ñG¦†æÊ’4õ4öoœPÎœžuVv¨è/ÔÙr¦”how:ëà¢2¨L/Ôˉ€¹%ãÞHi‰Œe ciå{¥~ ýÒafÜWkÞˆéU2Y×õ±™rZQŽ%΋2êÏ>m½/Ù1›b#©zRŽ%ˆ#q/úu}ÕœecZ×ô®83˜¦f„S­Á
+[á뉦Á@r‡Ÿ(Tpm<‰Eö~š}ؾ
+äZu<´' SÄ‚QuDáÌ0)ÕÈÃ\ɵ'åñ"· –ľ¶zÊÍĔݔ]ŠD&æhŽqa6ð=µ›çárT'èDá¤Ê`Ð}ír”õbÒòÃÈòeÁö­^_öGÝn¢
+V§®e¶ã¥µN’Ä4úÿ°eŸ—ø—LÚköóÒ«„M+°ÀOòAh.¢âÆÈKÌàjw2NªB±˜1Q1
+ .‰¼™Ï² Uo™Å¥@Íœ»¡‰W8 ¯U鳶ô´â«#ôh5cçAÙÏTRû§?¸s?;×ì'TøLð`OlääF¹ÃÇ©"p‚ïJ©Ã’¹ç°äœ9^9§L7÷†Î<Æ~ÃÁòü-Ö¡‚JHYýdn±|«Ü÷7ã÷Ë­Iî¼
+aºx“9)ßñV1š£SäN
+=AÁ1%åÆù¢sÇ¿É840 7ÂQ"È£´2]‡*À²T9ÎQðsü%#Þ€Í á·-y£`0æ¹ñ—w•Z<ŠpôŸÖY¯‰óò ¬à(s›ßæ ‚h"þõL¼»î¼™C"AåXw(¶96£ˆh#çrñM7Dy»¨ƒ_!7´
+!Ø^ 'ŠÃͦÏ|ô .±+I#´QK°%)ÅﬨÉJ±¶ ÷ǧû°h‘Ôü$yV€5
+ó*‡îCltÑ(q²û‚F»"8€pe%ø
+y£‡ŒTÚp€ç>=ú°I-NÃv“6í˜6zÒƒ½r»éçy0åªUBhšU‹AIļYÕ{DMžªpüÇŸ´Ç›ÿ=ü)oˆZôCÎl$”ªQ(
+_rš³É·3º!,
+ÃUŸ.2šèw‡€¤f>þæÐ’¶Îö:É:D£{OH ¼ø|ÿ ðiÛQìiˆvNÍÛ‹nà7âÅÐ lþæK®ÚŸŸ¨’L!oœówm†>q-ÆC±ûv?Xùý—
+!¤50J‚ È
+98‹aŽ¦+õɳ«[Ìñ#h¸ø Vdí‘ã 9n.òí*%*ûÉ9üËZèԆЩ˜úûæ+úkŒ½¦
+ó‘QÔ”‹@ít€OÓ±Ó“´=Ìe†w|„^O1¦89[xPf˾„HDéwª‰)
+émˆ)×q¡Aè‰Ã°4#{÷Wï.½L[m¯•ŸUy ^Ï{R£ía
+eˆ+‡z6=:Å11§Ó^bŽYeп(¾¹}‘¡i‹u+u½ØÕnºŠ§LêWé“âg£Á†=Œ*ÝL“JMí?žçrQ—
+€[—8Âû÷1/ö!ÆÅCíÌùÆ>B¾LˆDúÀ&ÞZ¨ÑSh׿
+¹ù+
+/NrP*ø3Úo[˜
+
+v•66)>L¤j>b.ý!!ü4 ‡/¥=Âh=rÜB«ž|9ͤÿ)Ïu½ëä}ÿYgi²ÏLfî!bœJ[ÍÎB¦û/÷ ”פ¸f­j ÊK¾6¦–Öfº•€%Æ{g”ß‚ä’FCjA>\ œîj+äØU„ÝòzŒªˆí ÝnÿÉÄ@‰eôØ[^­zµÚRcöx ªK~ ”
+ÕÀÖ¡O=P°;9Vm‹3`X“gØqÑLCD9`·O!@&Qg4À™›¢7†zcr :§ÚÙꌪ"šP•~è'ò“\ I³–T”Ú†»Q=¿†wÝngm?×ûŠŠX4=M'ÿ©¢šäØ0’ÙñPå³vš4ˆjdï<0Ž¨'Ya&óQ$Ì£5¼ê®àK°Œ¡êê¥/Køf!,Ë5k«]·Ó® cÃ
+lìé¹æUµî²ýá‰61Ôt€„i>ðÐúåv;j
+S†¶íp܇˜Øþ9ÅÆ´2IŽ#þ!UØUNFÉR߶4äÔ7¸·Í¬Ìiõ¡ƒÈ‚P@9´úÑL€%°.ŠÙËšÛ)°±¸
+7pu™”/I¶Úÿ3–²¿HûaD–︂À{|@>
+Sõm%Ü@ãÖàjƒŠoFÄ“ÕÚ9YºRÅÝÇd&½GÓØH¡w d´d±?Ɖ$ÒýÐæ æaœîvK´Y>ï…6"}ÝœZÖî\º)ônôwüß᩾|âË{n“ÅÅÚäÎ$º<ñ¼Co[ú˜Ý¶¼ZU:O'(¿ãÈTÊÓ¿\¸Ùh9f'˜0.}0ÓÃ…K*Ò?ï™SÆyø Äfk>PbÏX[àP]Ûá>¿æ
+ém“Ñu(¡¤³¤lb’–PïæVéÝZ mϪh‡×®ªÑŠ¤˜ì@Ë1µCiŠ¯¬0z â(:qW®á?ýjÙ!›Be¥
+vÕE«9\Û"í¿3i¡&j˜Ü¬ô¦ƾr¼¾+ƒ&Ww‰®…eÜ "G»‚À ¿¡«—˜z­¨X{t@©£Ô 5P¼µµ ¢Ëç°0o~¹ƒ5•
+eEØfEY9xÕµRR"uí)‹¥ÂN|b7|í
+ç]Q n< äЮ~É0>+<ÕC³ $8bþl@AFxȽµ±ÅLÔ§ŽîÍ,pÄ_Å{€rìóÍj°·Œ‚8Ó8vªù2'-V†6àöni|œ–ÑH®,â½9"Ï[jsC°z‘1ÃBÙËÊkè¸ÉîÝvE¼mŽ(ñ_7myÅOÀˆÁï¹\.OŸŠÁ<|ªØ¾›Äµ9„Øp³p53þxL©/Ô‘¦©»[ÔÿF}m¥¨žF_À»]ËI€Ä/Ÿ9Έ›3¯^¶e±SE€€ ö´ç2nÌ¿“…ÆqÞo‹/ûm0ŸÄ
+û ¯é9FøHœõ‘ CbOkXlÀá¾Ökó„þñrëë8‚ð_9R¯ÎÜg’'Ñ=$qžZ\+BD1` þ÷ùªçì’{fÖ°e‰àî\zº««ª·©%K¼jMð~ã·†6–ª8:{¬Rô:q/ÛkôÆ»-èaä7f9Y®1JØ(7!–M„ž•Â¼zš¬_tšV"éì%X…(G@',Š JÒŠD’x¡.ÚZâA%¤³¾4ç(ÇFÉLÊ\Û¢ŒªR²^5%ÄÏ–U‚¢÷é(8y¯V8¥ÁÍð¥oè—ˆÁD„Ð=|^
+ Ô¢\ø 0"+ L:HU>=Ø* \ê]&ÎIÈnEô‚ÄIÓ®èU/‚‚Äìx¨¨dC‹#âo¤]qJI+#ÝÖtŠÈ1 3#VÀY$L~|ìF²ÈÎÁñ¦)b?XNìO¾±[VYåTÈõ’TZ _SèÍp\ ;ƒÁ€¶«•„z•«æbôJLx27­?¢N€¢»@„¨z쬡±È‰&s±Az §Åš¾` ü¨<-ã=këæ˜rGIÅ9L0o C²F[ïooÃÜ‹ °ÁÈ­¹å}j@"£ç:•Ê/ÿ0³½K1¼¯q¨ Ãçm
+NÈšÄI?9ΩD7i6 Š£¬0Ut
+ü™¿ëòýûi#ª‚Óƒ¨¢ع²÷Vuóì1„U íàH„Ëjœ@ü•+ÐØ
+ â“Ý¥Œ ÕîM‰œF¨0®°g‡râ}MM09‡žòx™P ‚è8Ú­Xä€Y!¥høzÉîKˆŽ›™>oœýŽx¸AILŠ‹“‡ìWtÐî2œ3$•ˆg•‹Ã™ƒœk5y. J'Ç`“›à)Ÿe€øýÅ—ˆG–¼cÂÁ¸Ñ8Ü,-kÈVwL¥ŸË'ÙN&¬˜ïõên¦H¹B|+W×ٽÊ]Øýüý*È…‰ æ»xÓ¹àmE©üoÙõEÙÂòÔÉ I0ç­â ˆ¼09ÞR•uª5MÏÙR8†p%ñ/êS„(Mº/:
+Ó‹ª»±æ¡|šÀrÅ
+>Iu6(ðyå|Ž†‡F–‘°e¤mý·,cT\BŠsмzÚFz™³Z›¢i+[Óí{ª{í컑Z¯äÄ ª45X÷0…+'úØ‘C‹¸·³Ï¯ n¡–‰³-XÄ3]ÚyÓžÏ× t:r åáµ£ŸÓ³×‹¤22Ôd¢¡¬ƒ¤MÑ1H〱A^tžÔy
+îA܇& ÂÐhÃc§ ;–¡ï¯z1½Üüdγÿ¹ù§.X^ýðõëíýñnùôx{÷ùøõi©áõ¶„¸íç7˜ChC„4RHQ ‚D¹åæÓÖí°ÉNMZÙ7ï?üÑ©Ö·z €9ÎYi^QÖUâzs¶Ç77üøÝüóæíãÓwŸ?>}~øzûøËò}ôò÷åÍ_žÞ?><ÞñŒßÛ«~5ê7ï·_þ|ûôøù,^^}ûöÝŸ¶ÇÿóÃã}ÿêµõÇåÕÛ»‡ŸŽÞ¾käoO¿|9~x¾~[Å_‹Ú-?ÞMíS¢OÿZV·äåÕëåÇ¿÷ª(Kþeàˆ‡RèHt§„²óÀ 0‰ª>bæ î >xÜ•˜R¾VdycO‘³dhˆ¢n¶‡Øl ëD
+·˜r»Ì9ÛûXÆ^öC÷P»1'ÅŽß 8DÚæ¦há³ÔÂ|8H°ÈUr|;Ã×T¹=@õìšN¶f· ÷èp1eåJYÞábØF-bÛb<:<€Á2‡ùW/—z¶ã—‰0Ö¦KÄÚ§Ñç"—!‰Nqhƒ…²¯„óÝr—jkí\’ËŠŠøc6±'PpjH;&æ D«)pѪ“âUq†ÄÒâÀ½–Úõf¨Çbè œÂŠFÚ‰%nÚµØx̾IÇPö½>ÒFCFnÙ'u`¦imNÄ6”vàÄ·NQ6pô€Ö‘Ý÷ˆ¿&ßn
+{EYÝòææáá ª÷OOÇǯÞýçÃûã¿·OÇ;)à…âµâôöÈÿò7ៃ׀A/‘è…j‘1º7$¨
+ð«ôÒ MS••Y—%6O
+a«ph;[ ˜N´„B¨bÐHÌ ØB‘€#¤Nìwuìzë!ó“Öïx³œÂГ³tn'ßÖ²»"»(„<¶Âù”2;á±TL Uººþw‹—érÍóg¿¾…|?‰Ôï©üYZnØÕtu+dÊà(~#E‰bvv xØêVÆ"+PaH«YW ÓÔó¨^Œø7†^ õh-g ?-{µd{|.ù^g«ùäÖcOD¸Æ…eEŠ|c °‹ ¸BGl µ>ïEve§|gs;á|‰³×­Õ=Ö¯–ä°Õ1-z¾b¹$wNÕæS„êÎqSmpE•‰¦Ñø³6ð›]¹vhe»SaÂ-ñöp–k 1Yõ3¥*e(.òpÚ)D²&¸–—ÝÔ“oŽÇ_U ù¯,§ð»ú$ŒÇ“aB̯$£)O ÑBþ ÀeÀ€fý‹uMÅ9VHµ6`>{ze·ÒhVG_dþäÂ\ºægd]cçˆmˆÙÝBlYïmg/ŒAÌÞ¶eµ=iZ0Á–?ö}nyV@`{=ĉŠ ŠD.óñFý€±Û¦Öø´yûËo^ùk,qÅóïàå•—¼^¡.WüŠ@‚Fx,n\³iâFTܾ>°m "œ9&¿·­~>ñ9Ô2zìÝ1ãM”¬ïæœ!=”j´‡ûÁÛãiºæ.Ov}hJþÖ-èoÔ/ï8@,̤>N†ûÆ8àÚVÜb‡dKL­…HeVï8’Ìm¸L–âá;Vƒ/°rà¦#Ø÷U‚†dÑT3Ž¿’}·ÜjµŸÛ,qdûÈ)uôŽÜ´CÑ-²µp$KDi c¦«ç$5U ””Àîš ïœ$Ò‰îៅ?{Ê®¼«?)¯™µí¸*„‹Qr‚9ÏÒH0ï†cõsK®…¸­‰trf@=g ûµ·¨'´¹ÀÕ¥›–Éjö'êÞ¸ÿ%³ ÎiMï“÷ƒNJ£òç­ý‡3c¿_2Xêï¥2osŽ¢Áæèb÷¨áyFwöì•Š4tü“d[v'èê,W¢èm
+
+ò‹Š^OPa¡‡8vÿ~èåÐþT“³©a+@6ì„—oå¢U¾¥ké5ÝYUí}ûÚ{sY´‡µò[ý9ÒQ”éQ,^9¨£E©·õìŒÒ¼žhÑn(£âû=ˆ/§Œk)«2£q:¡œ\s…u·GöódçNýD)¸¸ˆ ¨A°ÇÝtØ/äÁ>G ó•aaÿš|?c°E
+ûV'¦|gÈ1Ò¬Ñ s˜ÚŠâ÷ªÆ%›Sh¤úZö6*(YÕëaì,¾°ËoÄÚv³;ŠP
+öÛ%?¾)F{d4[¼øÞ¿6›ä¤Ù­»Í)>l]cÇqÛ±‹Š”*dS¬J•s3¨yic]Ë#G¾MFÅè ïFeÚÌR5+Ëž:,©ïÊ[°P(q)Æꈭ_u¢zÞ\‚€g (B"™Ü\tiñÁu$Ð_R’…"91ÐÑÅüú#×—´–æ´h›L®l^±Tp)¶{ÿÒ[÷Xv|)Ðz
+|Бv0Õ#Óõ~èxöaƒ!¨ò¨{ígüf®1ÿð@º?ÞOíK7£mmvÂA#ëEYȨEb©(â>è[âË`ÇRVVt
+(¡Â²àˆšûl Üðð(¤O¾/ËÕ³ežûl@@¯2½‹·eÃùiJK}ÍH œÒ©A/(–ko&9PÌOÓ†W׿떻²=)RlO™u‹™`dŒ±•l²´]Þšá1/…­äHŠT¤R4Š3‚¬HâÊêR¥
+S¿0ŸÀ[¦_Z`Ê
+BöÈÏ°òiyÉÂÇrÜÂÔ=ëÉõÌ+lÊ^³p\2´Þ;⯯i1GäøëJٳ̈¯±…³PÉ×>$“:æÄ6w}<‹#Ù¢£">‘ä™ÐQeÕñ‰­˜æó˜÷gËCq”µuIu‹E¤ã«jÛm,=‰¯Zžä£RÃ¥Ú *³y^)\uR:zk±“¤X\oxüúB•z¹žw-xþM-®ŒBǵ¢íÆe›QõLŠAía5ÊÏàÅW³•Ïˉ“ýضl|¦§]³/§>¦ L-6¥—t/'xýZ/ed¼‰v½ad ËTŽkÚHÖš¿ôw^Þ~˼¹Æ´³\® •÷óM(/'Þ¥ôzêci”BäÈJR$ÿ¡¼6"fn5ÅV”ž}æ}›n:¢.+оi÷W c„
+3)ô«Éö%@Äy0Ûr½šõUÄŠñaÖx­WÓŸ)ÅL1U)^‡™õ1³FBﶎ ع&TË£<^wìøÌZ#oÏeeý¸ÿ„HUd ‘ö˜åwkÔàº6´•Í®ÿ›ðr»²7‚ +mÁ=Ä0Eßëƒì߈oÏ.Aýh5Ýh(TeF–1CÖ‰\šçà'æÈo犷x®zæÉF®X -kG&UñA‡n]ñßúšh½n€•Ô$’•ï·aLÔ¦Ôó¿Žê‘nÿ~aùÝ}¿ƒŒ}
+®†¸¤BGÇႼòâ®XØTQ2H`é“<P¾8 %öá±â¯ûÔZ2§¾•ö²Âtå¦ ñÚ´Jÿ\h ÌËyÒÌ¥ìÓ5ü+˜‰Bº²ÊˆÒýÒ¹ôÕfå!ZºŠC‡­§=m^ <·®žerë¬`üI4ÿQºÏ³¢È°ßa±*Dúu•|ꉙ¶¦Q%‘?Ÿ|-»Ž9gfÓºÐ^"Ž r°D×Î( ÉåIi_Ìì~r¾N q`va²˜¦åØR3dhíç«koŸ5ÅÑPâ©—R¹½{á>”²¶¯"¡b•yçþ^ùï–ÞͱoÌ
+òêÔý›¥ç+ ïoÔ• øNÓƒs¥‹OÔ†`Þnê‚<(_\àÒ¦iÑ×òá
+:mã'Á ­ÖêÉCJŒg×ÜÐeFç>&~Ö
+ín)Z‹¢Á|œµ^ñ.kIsBm© 51F j›‚ÕDo&{cãFìÆt`CSC¤h¨Û½ák@ '²Ûi“"²á3Øüô£)¢¼ýU6ˆ÷€\ÝBl‰FßHØ‹ÓÙ@%)àM¥h4a'‹EôKŽz«ÞÔ1Í4$}©’€-é43Þ)ìd§-/C 'NÁå:l¿wÏõnÞå Á¿ˆ{nêè¸)\1CùVZ¼¬€a.<5rÚׂAYn‹s˜{ûç.t;ä®c¥§ã)„£ÆSsø17e­®TøN%Àoy²»&l›ËždÁÙázÜ£ÃKC)t4ÍÚéM
+]|JEà…ÎW^ú)J/àš1Înñ&Ò,7É3ÝÍòlºU6u\¢&Ós4n¿EÌIy)ñì{W Åô¦z'ŸçôÔKR¥m—b,¿=pÖÏ…‹kSÜ¢½Ì1•ÓøXÁ¾èÐ*UâQéeoo!Ïù/OEP <ýW~¨8'kì‹-åï¶Oõªü Ó†\SZíTO?`8D“Ïpu®;ú»lÒR ­·¢tÎS·«.Ìëó[<sê Fïqh0ãÜžÎQ PmšƒÎ(Ð<«0Î
+éÓ¼ª3*ÚÚo2ü— Öä1/ŽÉ¯’„ûôÑÊÍøJ3Îu7~º°7E‚â¦é+©‡™Wp0§Á“šòØöÉ$+è  pü wÌh_ãÉ".B#~Se$¹ƒ—ûN‚«±è4¾Ì¨ÆáŸHeµÑ)
+ŽFQm³Yd‡‰ÚéÒO‚cb;ã»´©ù%¸':“´8“)¢ì&¹9 ˜Yab™ù„Ò*”.Æ“‚pþûK7ÓÆ8јSŽ5ž4\/þ½²]Orh/Lu^Z}¢èëfê'š«„ñÅNb{â½]Iñù¿1Ò¼* ­üPæëžðgܨLSRvüåÏY J¢›Æ¿ãNGô¡ÕˆhªòU¿yä™ ¢ò½•—ŽVÍ‚t” ™ÇÈgš;Vüu'Ÿ¥ÂsŸ;Pú´íò®IçžÿøE§‘T ì‹·ÿW ­xG¦gQsæ÷ç½ç
+°*]Åa2}I–þÖëjû}u˜ØÞ ²N‡â¤Ý m{š“ù᯦½
+Þ²‚ƒYËOŠá±"œ^䘂{ULkÇLœV,ˆyïקW2« Y¥Qø);•È>\úÒ”yÎYC­BIù ÔÜÃa4!ã@C¶PgäA?Ó^FÚ„£UV SÅR+è[hÊF¸ _ªH4jKI˜¯ûK¤BË˪ih`Õü
+Ü]ŒYq$Ê^n3Ä¿I˜gë±ËƒnJS€Ì>¾
+y;Ä„Ÿk41¸nˆã4Ì@ò4¶;j`%#-íý/`E&¤ò-š6ô
+Ûñžý]Õ†ÊüÓ ž'Xæ­ЯØìÙ|ÝlöÒ¶~%Øœ¯X¹÷î]‘Põ&ÏëmŠv)ƒðXÈk9'ÅøøÇ”€Ç—´Þ'›“n„
+µ2+ ®Á}rÝ”ËÌ:ÃÏßo#ÂUþf¼ìz몱0üWöe‹&§þö6sÕ€4â.˜A”«*$©D)ÊÅðïçy×öIŠí’‚ZHŽíµü®÷ÃÉ h‘"Í´‹c†aTciúHEØ !”çÃ
+ÿIKÁ€¤ÌYÉvGÃ? #S»ë|ÕÉæN#p ‘õUJïu°ŸÑñ%³–äyd´Ÿ”>اz„Ôž=GÄ›I ‡•[â@0äQI¨>p4ýG@NÌ×7«ÜÉ.(‰hø5>¢‡t4Ø¥ATª$•ãÅb‘£x®ôýi
+r“Db/€fÅ]¸ãM-OÊž"P]é o£®\Jôl¨ßRöɘ*Nf@K
+<¤´H¯É>NQ¨=<¦µiçÚÉ}ÚèÍÍ4ëÅ„³ØË £ÑÌ‚f³48,,
+”õÐ+°`Ò÷è–€ öa½­fK´Un¤GˆL'³¹3C~„ „Ý”œçdü±´":¨‹îéaÉù|P¤p04²1«øS3‚†"=“ŸV­Ñ†ƒ¨ˆÃ‹0¶ÉÙÃ"Š0··ñLŠ Œg=ÛA¥O¹[šyØ{§º½K ûu’GÃ
+gÏ£k„9—Î
+®ÝÞ² XãäM8¨­ œ|Ì<ÁØë !RpŠ¾…ÍÀW×½½p;ìM“Cx.Ý+±Ç ü“¹À”4ôr+È›&‹A0ÐÇâöíÀ8bÍàœ’N¦¥œr¨Ð¼rVÈ»(ˆÍwQ*m/fÆJ`7Œ*¥Öˆ åN#cCŠòœf¯J¿ë¢¯$„„}æ ¨€_übûŒïi78”餽ÏðÂÂ'Z sð2m
+Š2w”Äœ h+bhžW$“‚ˆx
+R€;Xï7þ¸í[ûûw;8œðÖˆôMd˜qqg«jÏ | &\ÀšÌRÚ]U¼TˆRÍ”=õËik¥Ä-H\ÁÇù+]c?¥¨`!ïé[ ägVqh`¼Díób:€†7¹*Ô{›·ßazÁXä6§Û+´ŽÅMûÌ jELq#Ú¼ÜèççÑÃdŠ| P‡ý€H…KÕ±{ ÜÜ­W!@¤,:l\9Ë;+P
+¦•ÌŒSÁ
+7Â#/þ$ ª²ŠÍsvÑ+ZÆãw.(Ò[Þ~WΓ‡Û«®§ÂêrZðôdÕµKªn¼16Ô¯»¯U9;í³Ç#V —ÿ}ñîºBMÀ8 –®-á£ý),kÿªÞM(ÌÊÍ=3Õ.Î@&Ç’ÐÉLJŒi9Y!׉ÇèO3{u SFè2õ1-^¦zçòV3œQqì6ßÎ)e EÀ7@îɺN^ðIN\M×/žö™† +Œˆ_ÞgºKÕÍ¥Ætt<—"wb—Äzä–z)c#Ì¡ ~|_òÐSñ¬±.`o¦gdQlå ²V¶EAQõ…ž¼À郵…€Ðë8YÒ‰[òŽ@¸m3’‹§aÀÝq ¾|$ÏX+ é
+}ÿq°²
+©À­ÑØ(ÄŒ#Y,ŸŸ™$v¸
+|$yµï{Œ?-¡M© Ø·‰6bv'ˆÉðj-3ýßN.óF>×Ò³Âþ…Äû D8_eäÓe!÷òg";wÖeãgÞoV¢³ ­4 ãˆÄY\0Ͻ‰Yáû@MÖ`ŹÔÕHÏNed„/p;/º&±Óå¯f/ÿË~{õÓÇWw·7ÛïW7n?>n{|Ý—xþÕ/¼ô„j9
+« õ ® ¹…P,S­sUb•y ±8ü‡ÿäÐTõÈXYs cY’䨂l~-GБ§¦#îUº„iƒ‰dÒɈ¤ƒ»@I ñ,×£ƒØ€ÏNÙ7çÁ^‘f̯· ¬SòtL3Œêù(òè»yRñ„ >Íø'Ü„¾Õ
+´9µÏþEˆ /Ï™¢”
+f€Þƒ&/=™Ñ4ò$’ß%²K£/wÒ£„}ºLº'
+ˆ‡?)aXPrUæÞ2:HiP.¥M”éM JqÛõáEØÚcÕV³f÷«Ã"·'WË3h8­ÿ:í'rWç$"çÔCs–e…À˜sÆí‚‚
+Ð)ˆkl ª€YF®âç¨è‘]L£÷²Ä´j› g(ô^•Üö›
+$á³,òœŒ:Œ!ëB«~,Ïû‡¿Wª˜÷"Œ="õ©"BA)> "êd5åãž‚ìKzo,€«Ì!‘U Z?åCv‡aQD™&$¢& Ŷ ±ä‹ü­ÍÈ8•¨‚©Y›x\ÄÈǬÔI0Ññý¨\f¯I—û‚÷ŠJ
+¥àéR,©÷rÂZ¨ž‚j….»ÁZ¨ €ŽÈ1N:a-¼„kÛ¹
+ZY qʸÁ|
+F<vÉ›3º"2zC~–ÓSOteÐUk…ÈIéq¥«—GçÕÜõ8³Cö¢Š¯Ôus="m§âØ’@k˜ z|à$n°Ö³}‰Ž¦gtôs#"_¿ýª lP ,Ú¯2©Ö&¤ßÁX¯
+ë„­þ°þT¢úõÆùæ)¤¿a0º°ŠVIØÉÊd”쓦
+và@5ñà gª‰… •UFÃå JÕioüfØé­üû
+ÀSg
+8‰FÞƒðŒ3ÐînÚÛS?mOÑ@¬ ³À_Áoœ!ª˜Pk•h­ÎÃ
+ùÒ3¹) Ç¸‰À<Ýu] 4"2‰\[By$ZŸRõ„Êœ¼Ó®qAD(ôÇ…’SVT3ôQkNwG]¹1V£Æ¨èh‰N>y?êi2Þï]#‹L3ýb˜¸ñÁvoõ˜ã=¬wŸéºÙ6{¹Éïá6`µÌE{Ú~”¾0m9`ËN6VZW" ^`\ì
+ÐhL.‚?jŸœÙ9΄)“?8â0RVœw°sDòÄ´}çç á‹èÖMù#¬¦UA&F™x!Ã?º7IúB„1m¸{WhAÎŒéxï«Æt7 „œ«d>>ªã¬xb À›y£3؆L‘"!MEÖ°Ça²t8Uñ¹¯Ky¡&:Ü $ú¢é€{w“”,OÇ#'çæ#ä®D B1L6È$Ç™ur÷ª+ª¡2Ø]§¥Iè–âõ®I±K³Q÷ ÑâÙïhôìµK–^®@Dº¾Tªâ­Ûò¤jWÝ _’nn²d®9‚7h¬È4:¤ÄŽ6h6Ž ÆQ$5†Â$C “Òߘ„Ù¡´žü
+É6ïŒNz b c•zÎ芣uÃ?--XT,}A§E»}‡u 6¹§³:¸l¼ß)«²³:×q ç’ô¤]hcut‚æ„cJÔ«ÇÌäXsTÛY]/ 3ó-Ç’3Ù0¡ ¡CLýÕ%£ °|‹;«ëÞ¢VKöò.VTÏTˆew8õŒÕc1—Xø˜Ðº>XÌÅ8* ­Éð¯´þ¹Â.ÂõEc ²§edjb§õcàzÕ²¤‰’¸Î¸JFe‚ · ˜@j“%ò_ZôÞ¼\Ι̠GAL°rÂ:ÅL²Ë„õµ¿’[nU°Œ¼Ý©s€‹8ü‹×ÔÓ×jÝÒ}ó»i ²=`ö¬N{ªYÞÂì“ÕqI DW¿ Ò›u  ó$ux·IêׄÆk$riRöê2áOú þÁ¿ËéÐ’+w
+H‰Œ—KŽ\;DWà=äúB_~Æ~CïÂ@ªö?íCJ×hçUá•®¬HI$ƒÁ`ý§‰^Z¤ˆXÝçK‹]³«Úú& 2U«óQuõ×ïR3UµV¬.̘­¨ÎênqŒ_…ŒcÕ{_nÒ*ßë.5!Ý´ÄWÔÇ 7ùe>jŸÅ§ë8SËÕ¬KiS›ÍûÅuÖÆæ‘‚ñ^}
+ßq³Œ)΋ã*@V;G´^§'È®R‡t‚ìSZžãcø˜µÌ¡mAº5ò%•lè3ÎRíõóǤõêÂUzí]^ 4Û 4Ƈ²@:[«E›¶á\V¯RÔ½4!?QmW1©DÛ|D@jUÌ}Aòª6§ ×|Ï 4Fon<ç~O›côQ÷Éôëǩ؃ú 6•Ï6JE½Èko¯ÏͪTM¬tëP@S8ß\J½Ã75²f­jBŒŠOeÎÅéeòU$ä*³4ˆPëð}ÓˆŠµÆu7ÉUã"‡Rmšª|’ ʬ= ¤°E\•´:#‰`¼AÖ©¤Hëó±0TŠAš¶kÚùu¯p²åUÚÕárÔqG¥Ãà ù²¦ ¡]F„íc—]¢ýÜy¦Þ;pŽÍÚ.<¤—^hŠæ+ÅÐÀ½6õÍžIêh
+«¥öש˜o¸i\·#jYÇsù›E‚>Ùçp(šbt„bôËFë:Hí²âvzš\ôhÚ¸©CS™ÁÓM-::j EÜóŠ„.Dgµ¾Šà°
+ë³h-¦Eç÷,å$~qÕª£8Åý8‚ ‡Pa{=ßr1¥Ò>:u´SÔ(BWkœüï¿e/Ά†.RÛ‘ Ói È?zK-»¡òüµ"_è-””:ŸÐÏçÐ ®5Zm‹)‚SâéÝ? ¨ÓSälbZE =Ó o~æM¬+9$K:ê}ÈëÐ-@¤FŠ“ŽÕ—o=G¡ªzÓNŠÝ˜oÍûZù&¡ÛÕHÄd<ùºŒJ*AɈÀûN~zü»‰`Œc¹Ñ¿sÌkiwRvG®1­H”Êsf«™ÔÍ÷UEECj2ËùYÌ …”6ÑÙiÇs‚9äÅ{Ì¢…h¥¢7Éœ–ˆÁ‰áØçi|0©Œ^꾉©y­´ ’èÝ„- PÞAH„µŠP˜%ž‚ŸD"ºŽWÑ•(÷ü<õBô/騭bž@/ÜLÌËRÙ âö>––4&ò Ž¶¶Âîü
+ <fÁðÅ
+D×I i>€ÂÛê­#¿d¼EÏè÷ \…Û
+­£õq€¼“¨B-iBñ6»È,¥CêûX䉟£ÓÇò;9Q¨ŸÆí'P@ vžâÔ¡/n P ŠºmRé–4Ó÷
+I¡ôùH“-ÄÃ_a·˜'…‘²sU
+6ÙÁ5áG–çpªÔ8¥úI_(:@›„’©ËWÍ Ý†aWúùœIï’´-6»ýäÆ·áZ‚#Ö ì±––XÏÐÉз$É„гp⠵͚U;¨´“œÍšÏa]ÉjWÑ{d7èG­&†! J3”þØ›ÑO¢zZ3ð˘P¸cZ잀-~@²Ô2•B5­Êi„ÜQq–ë8W©Š¥¿±ã4>üñ˜oN1=ø÷L̓Åüž•é÷w:&š«ds…ôÓÓxzŒX;œ÷ù³i‘]…~¯€Ì¨WŒžq;ìŠbÖ@è‚Xê>&†°3£¥u°±&w’˜÷´›0ào[ö6éRV
+”™ƒu`Qºíù_vøTù‡­&iÈòUçÀæîji÷kØlö×Åf-»çì¨Â¾øˆ©±H†Kå¿‘Ž¢Ü?Iœ.a
+^KŸoÙ!LŸ…©^Q;ûFos«°+4ÛÚÕ1ŒRFÜÓCqqjL†ªY&c"Ñ,Iv6=O™<˜*™nØOÎ(y%8Â0/èâ~MÇ$ÂbOzzÍÕáevzˆº2—ò¦»-Þ’M¥—­Ú±%b¢ ›ØòœÐ00Ó—ý$½\=ƒ326äï~
+A†ñtJÜ}Õ¿tæ¯4 |“¯÷¶ˆº^DgB%V$ž Ì k˜~–WP¿pG„ëÈÖ ô¦à[…tçÑ‹
+‹]<ˆ;  ‰Ëõ 뮂1·^aË(ÄVç\“¸£ Œb<^‰O0Æ—aüQf? ìŒ,T†®Y @÷Qa軜,tÁŽ46Z/]Äœ%a¬è±|’ð„Ðß9a›¬’¾Aâ&z‘"SQò¸Èü81—›0Ï5SsYÁ<ò³ˆÄ\¤¡Ü~M¦…ƒˆ>€bþЛð.l}Ô!.C9<6Ö^viFÒjÎy=*qˆì ~層Aè±/ŠÜ²"+…Ì؆SuC&&öƒÁuWJ˜XPÛá¼PÀ)È÷º
+Û:Q·Ü
+¿Ÿ$¸„£ú– §`!’1rf 1±ÁZ¹Ùce$*ùNïEóxå’§—#0´Á;ÊQí€ùøNweZø4¢Çºû­ç`æOcÓ„6.V>¦D.Q¶sD‡Gµ£õ³fH"{§!w¶qKP¢ŒH$Þˆ»èFнâ!IÙ,,« ᨘg®÷†Ç‹‰€JSþÌãT—M7Zû2G“ç ¡w è7@-5cß¹-3yÅØ6‚ÒóÙó‚?B«ÐEu!45¼t„ÉAà kŒ2xg¾Z¸ä"&Ç?ÁƒûÎ3ƒÌÃkÅçyN¸ŒªKܦ4|Æe!(*¯oTô罟q$# `·øù™ Úá(5ë®'“Ši8'ûH ±º 8Î0ód(¦L¦OÒµ7„ÈXõB~k. €¢9ˆ‹U ’6qì1€€ âETð;Ùhi躱ÆÒ–ø4qÊ~´ daT
+yº¬þÀ)"×ѤØ~^F]ƇÛ~°xeƒñ´ý8­§þÏöØCÞxèbììκoöäÛ¦6e‹¡%í÷ÉÃh$P(É‹héÈk˜a¬©ExaòÓ‘,~ÉÄÈβ3 ÁœÙˆY @°ÎàNk@xÈâ2›÷¡3Œª™åæ%Œ[ƒÛ,?°'ÝBå¥F†Gq¾ãj°47qÉÚíKÚ
+ç´ºƒÃ{¶Ð»ñ\°™··s¶8¬ôg¶0 ÊôòC&8 þš-XD2LÃ÷û\Îü!?4²’‡Ü“á«° €°Öµñªà‰MÆu•Lôe5ƒ™_x<È“ä(Gg¢€0§éA2L°XÙW•Ø0ùµ|k]Í/Hh_ØB®ak@ÒX‚ñQsM•‡ÿ¶H„$€äçMŠG@b³i!•´®Ù·U’TCkžt íêƒ(ƒ Õ·âxü AâG²‘Ë0YO—Jv‹Þ0©™W ”Ų0I>”,æAl! ›{;žÃâ°0Ððc:Àe¶(O]¸¢ cz^‚Ì·c·à[xîKi#œs$µ ÍŽ©SþŒU[ØÚ\e€¢oæ•Pøš—X˜¼f_Š¨ñ Y î8\x‘;æ±J~ðæN€IžRä_¬WÉÜC»ÉõöB?Ò¨¤ëXB—úÊMþ¶¢¦” ¹o›ßÞ'A –2 å8€ê/c‡´Äò+%ØšLØñpÕUL ×¢F³èJÖ6ê©/ Åö©÷8U}
+®Ç‡!;WT&@
+Ùa•À×IY¡t4ÀCôO·ÙSP ™]†þZó´Û…fö{ðîðÄ’£€‹}JN ´&ÁÖ.ßÎB1…n%¸v9,™97áÏŒ#fbߧƒI–£&w|¬=ŽnĵXu7²™(µ¦~çG‰>ÕñEÂ4.÷ã9¢èPmû2ü(šéÈ<ôö@ê “(,ù»-}È_“Nj°æŠ8•§yû@Œ†Ù6ì˜Â"yŶll0 FIÁÞMA’Ñ ™)ÛŠDÈ}ÈÅÉ5G浈L˜ž¥Ã¾–:àù(±¤Ó»¥2½hx<=Tïð{û$V¸g–ÀŠPlÔ,oy’<Í2ñ÷êW°ärNá. æ,P8K§Àa ÙäÈoS´
+¿ cPt’™C· p@ïgÑ‚æ H¦‰±½ýä“—ð!R=w%gã³Ùxþ½8‰ß%1WÛîömà»Ç°¶d£6÷Éì 4§øµ²ˆµç˜ÛP½9àÃ4?JÖÞ@r9€rqÃñ'Èrë¾C ¶ÂÁèÄ:¬„ Éèöòå
+™FõY ¼V¶( ‚0<×Ü9$Èfê.ðñ$º@ƒ1ÕˆU´Y^ˆôBk”iÖ(5ƒoÓ_hµ¯/-/r&[\ÿo]ôfìV {šÆÙ¼P„„L†+ÚNæÅ&€W–ÅíõNê~Ì¥¬õ!­H
+‘ M®ñ-Ö_`>ymVÑeŠOÕÛ†BCÛæÂï¥õ(îÔêäf®¶çÇÄñòÚÉòÛ"ˆ‰¥–é‚ŠpÚÖçrà"¢9î‹
+§•î£hûiES?`˜rIGÞ¦‹Ôq,G…qä[¦·“Kš:wÃÛLuŠr2'ßœ3e,
+•ÂH3ˆoše*ö¬ÃÕÊxú”y,iÁ/°~N ͺõ;¦*B&…‘i2d#~R
+]%(ãd_qÊc±˜£ãTøœXáPtZUÒ9{ž†éÿm?QOùãàaÏcÑÅL,8[*¹‰Ù ý•ÍMíN¢UÔ8JþÚf°9ØÞ ¡zsÎ CÍ<€áÿßl8ŒÂú6ý[Áñ–F/—¢Sƒóóø‘ï:}):qÀв`¯
+ÎTÁ¼Ÿ§
+˜ Ÿ,Ó»»™%ó€äƒá¬5¬Lƒ8YɶÏÑÛ)ƒýg”ˆÇ‡ò4‘< ¸›|iEŠ}
+2Õ¬9VîêxŽ|'>i °/…Ήuåå ¿²JÈ°+¡v·8?Y}öÏ$èZôzÊâ‚LW-‹õ¤9YˆUørÛd²0ìñÀ3[I› p•wdP8ÈôýåŒññ w¿d¾”¬Èׇƒ}чك­òïÎO=Æ<r»Ò!¢³ƒ´Y)Arø<;ÈëÄ/—¹,ÎéMŸûwmÍe‰/ý=U¼éïo
+Ò+׬[3‹´wÂ<Ä+Ép[æ«ÏžéÚ x2^Š:êt}†iÉ02˜a!'r(I‚P[Ž†â0ø«¡Ð*’–B GC¡}9ìð(yß&ê9¥”l°6 Á(>ù Ä®Ó2$ì…>6}ôfLB©J8vR9“äWý‰a5k‹¬„ Ãå ñ¹£ æš^äÙ->\‹>gÿ¼)‚0H è7™Ñ>†ïììpÎ+¼‰¬2×ËñÙ#Ô¬÷¯
+$QV¼
+v£8‹Kµ2°Æì‚ÛJ+Ì—ÂtlꉈƠ0%¨¯Ké4rV”ù´ý²iZ%¤ƒjéSŒ§ÀÀJ¤©¬š ÞæÕ!GmfÆ“,2=6àpy!]5Öe±ËTh¡5K³&¸Wã:#ú‡’B7ýÛØÍ ¸Sµc"€v€zñ’Zh¦Ìu6 *ã²yŸB°FÄk“mW8êFF·LuœùØöZ£| 6ÞKØG”RˆÇ@Ñ‚’oûS—"» .™ZWnŒ
+Ä:u…b!"h¥­¿&n“+X$‰GÀvEŒ
+gó‡«Vö„¬{SÒiñ‘¯—¶¿t)šYDÌ:-SÂv2<bw³šÚÎɤV2z y'vg•Ðš Æîisd0b+zæ¢ L¦ƒâvkŸ…|n*øš™Ý°’ª`p™•sò¸ŠÜ­°_˜œá<Ú‰W
+‹Á\SÜÈ[Ü7ÝA6}ÛÛ›dàÑä*íß âYÚº’7Ý°`xÐ˺mtÊ«:É.ìÚQ¦!„Í= jüqÝ¥I‰
+ÂçÉ«z
+UX#o÷s¨:!Ö„®ëÕy+Z4Á )úžZ¸ð2«d¹&“ÿþ€ÄôqIì*
+þƒP|<½ÂZ~
+z×ÄŸ4eÁ7ÿl2qýšé4î¢A]6ÐkÝ5^ZQ½Ë(¬(Sžv^5¤ðfZÇ’ed³Ä¶jQ¤=øÖ ë‚ðK'\¹œ‡Á0´”k0ЗÃsúKBÐÚyqa6itF’1XG´äïtf?ÂÜ‘wë±v,"'c#DÓ‚°/‹¦òfa…p7ˆ©½ Ô?å)LyóûW
+¼œ ì.ecZ»Ô ¨R¤¹E<F÷ùŸ¹ç£„¼ÿiòº~ê³V
+}‰åŸ’Ûð×p/넨Ìéî8_Å,E¨RÂs€@#¸eHŠãÎ'CËݺ¬¥ ðp‡9ÉPvì2Û’ª×\P|9“ KAÀ¼óç„&ÃÈEÛŸãÏJ²cm„Í£ Ñ[[õ #û/+Œ×®*”gb#j¼Å8Ì@ 0ìʘ^@ÓÆñl%>ÕX²C¶ÅŒ89z¯l(ö½6ìíœ[ÇosœèM·¼Õæ>ÆïôéßOVFÛ•|»k«`óìËÛy¿@¸˜)æÖJô¼kØiŠ!k*¹ÙÒ-T
+í±N¥‰›ì¶`ÚU$î•I‚Aú±c„‘Ù9‡l¹Û?¯Ê¥|Aä8‚Îß‹fŒxºp’ùй0ð™*ð««\_ƒ,»?ë{œ ¼›ô·Ö5? Æ`GXC²žy(qJÿÂíŸêÈ™Ê`ÃÛ_‚Ð!E»Óåëp¡beŒBæ`oaÉCš,Á€´µÉ‹)ûþ€Þ{ÿó
+™J,óÒ¼
+/E?sߺ†’h¦áó¼¦$¤†ûM
+¶â~Ý' ÷Mýùd}ë+¡´«ŒüÁCð8]Í·í3ï˜ûëê"´i¨²ÙCÐýu÷Û>À 9§Ñ5\}í$a˜ÌIJ¶Æd9`²ÎL;}b%¼Ùðèl„¬]•Y&¡»¬ÑÉ”VåU <«"*‚…%ŸÈ8Ì©÷Üü~„zçö+/f9=dµÊx
+¬+=Œ˜.ã,Ý=ž
+•Nchy¨íw¡r=Œãë|3€ª_mh¥)„ÍØHÒ÷uÇÜ|x?9÷VwÜX}²ÿb<¼ƒZ
+¶ï~ÝG 7BˆV볩§Ä
+tÓ¸a[1I¦éüý
+“íñQøÒ¹ ø¥†ÅB~`âÓÄk…%Ž ´ê\u%,·É¤ú} 5Ç/‘‰º©…¢æ|hê-1ŒíÜô^Ù,¶kPDþk—XŽœ™[@¦ër¾ä©ý$›‹R¢’vÙ°? û¢IÀåSŸÒÎÁª°[,o9ü–ûôoºOñ­6Ñ.üYà¿®Ô÷µy)+ž Ýb+¯faAW×$äç¯;(âŒÛuï ŸO¾i“.’¨ÙVƒ֋[S#~µQ1=þé²R¸Jüt½wÉÀVW>¿®¾Lã_9œïë0ºZ5¶CÅ,r÷
+m\#MA¡Ð8’u_!#LDO—¤Ü(\á!v 6cIxJr@”‹VËúƒH˜îƒk9Òc€©aì%á) ãS°ò‹Ò #-GK!ø8¢iÄ«(Þgh½ä‡£)S€Á !ÿÁZ¹
+ Äÿ2D³0”?
+%åS:bBw‘Ö‹õ¼ŸÍš4t™®r§cia㎠§—ªÓåe†›£2L¾¥ckÊ÷¸àhäŠÈî°">(
+¥D½>!…˜W*:ŽcTk?)‘O£:LÚ&ÜúblÀ3ÓádRY)Ë~úMd7è¿Ë-­‹Ü‰WvTµˆÿY…&ºåg
+vòIïÿ¥¼LräÜq |•w‚‚f‰k÷òÝÂÛºÿº¿ ¨l8%\ ¶++REÆ茙ÂÛsZ€`uÒC@¢¯~ùVä2ðHOOýÚóB%ÕèjÛ¼A<åDgh¨TüZ('zAÝ[ŽkaÙø„äOŒTi+)@32dÂ_ÓZíUd^ŽçB ¬_tMfcb©1a«DW°3—dz½µžïùÙ£ w3lrw]_ÆIJÛ~úC@LSO꣙éb}‘O±
+Õë&Buì.%2p¢¤€¤Gßà‰Ü72Š†NÐ;£œŒÄ-3†•Ü97ëÜã#«oŒ1I&>œ\èí\¢=@~–f[Åd.''A #r¶oÎÎôfÇ‚•
+´ R¡~øJȬ4ëÕCÐ42ÔÁtö[¼¹Qí…
+NŽfÈÓŠU¤S²A
+ò¡-JÚå´ótˆÌ:þ/9Ëeö÷VÐ,¶—d”rûò!ÅI»z²Œ&¡êm]Ûï¯m¬$’¼ã3ª’¨·Jþ0°4`DÄA5ü²)4qß݆R%$õ„t4©ø›J ¨
+µäË…+ú
+ C[sõWÚ£»`“Vm?C!k1,‰‰ˆUè,eZyæ3U,R¥²°äÚ l,<&Oú©Ãï•eˆR½¦*ª\´:‡ëÀ}l~Vù\«î§(—}X‡)ƒ“òhœ9ÃþL®ªÆ)Ì/#-g{³­º½|'h“–¡uÈhùô:uÃ(_gd%^Ü Ö&^j)¯Ž¬àñ"†×2NNÐ{4øh’_09!VNX ¬âÞLÉkˆŽ<ˆÈÐ\¬÷îÁå~zȃo%oÕÂXÝ@ì÷OTØÝu¦²2{è:Ó;wÖ¥\ŒŒƒ3—X_@4Ðl²!RO4y}u. =0à– b2¬Ø
+ëP¸ƒžÛý$•èh4œŒ»Çùj2²sái
+[*MŸ.ƒPR©—ÛÑ[غCÞSÒtköÁ ›´OÙ×úè2€Ïí~z#…ël½ƒ6ÁtXYÑSg=Ú>+“I'˜'ˆÀÄÜÐ?iHB±¾tÈ(&jï OF‚#È ‡0° ˜1˜;Æ kH#æ€P”÷ø´¯
+éA
+ÚéýÜÔ[t-Ç!MÀð
+:]|,±uˆ=QËL.Ǭ%cèV’W>Õƒ—Qô/ïËàwy[¹’ÙÉ.yqoûDà\DWµS›´}tõÅ
+`§Êó½1"6T”Ñ
+Ï^ðÔ°|[;A0—| ÓŸ•"ã4,‘Å51Ý]œ…#d8öi ê\Ñ‚Sá™øA³q*uÓ0£89„©C ÈVñÚïoùÙC×d¿pmüóa <>–÷Ñ $*égßI8 ,yQãùKö°àªL“0î£ð4¢•d†'C¼ xÕ_²´ :D ›¤£_6–6ÁˆiêÞ Z
+ Ú>JisK" æe"èÔ
+‡÷ @lbÂÌÔ
+!Êóêà L.‚"{ºÕ'ã<‰°%IíºŽ Î_Þw´Âthš6„à´•OÞbuÞ
+ö(¶ t½ÇFE ¯)‡)6.ø;HÛÉ!2FÐð¶O’†WæPjjÿe¼Ì±äÈa z•>A?î‹­1çr¥û»ód¶TIätyR "“@ ë¤/@•sl]%ê {™V³E¤i
+Y{J_ÄŠÉK×…†¡àôhÎ¥é*
+•MåÖ¾‹”rzÜí4
+žB (=| ¶iàx9§¤ÇG%HŽøW1ný¡9ÕB›á› £Å^É˨ÖUg‘`Òôbá}L¥ç
+™ªm¶°…Íiy,DQ³(ÀÇæ·Mâ«â”…ìô"1\iàÅæ¡Ë]»%º*)ñÂ4dÔÝs’RÚÀ(cö£2Ú9“òžr:b4•ÓÎI‰]Šf(ËKœEŠm)žªÉ`¿ŠðkpÛÈÚLû½*A­£m­˜¦$ø©YIdÿ†‹ÒË#tå$X¨/r‰Ÿ2ß“A²[»aC #xïÃúÇÜ2á€PÑ· ]å4%Z-Öbèà†S²¦‰°âÏhó—tßÎ9~|ÌïM7ô9|´×«x™ÒÏw¶E‹X,bà!Ö°…x±ìœ÷û¡(D¬*Yã2?TRi^É…¦,¦¿Y•`A;kÂXwŸ£¸ovéâÕ"(“F"¸–Í̧c/ IìÍj|:}ÃÞÇæùkgî§O§U”Q¯°{ X&ûåM¼¶H¶ƒäF†¢Axþκ)Ct$/ÚÊ›6|ÔË‹
+x{ÁÆÞKÅ)…¶BEUùFqv’ Ö¾
+I-Û5÷9XdèVCï>œ9¨¤²W¡í2á‰!€LGL‡ã±V‹ù4’Ôi×p/a½e_íUn¢úÒÈûzY÷0®„ÎI,îšÖÙ-r%,6@÷ÖT% ærÌþb=JÛmš]TÔ"tô‹4"†˜@…â"6ë*¨.-Úçm¯¦îFm:¢ 
+“pB8º@¡¡`åQòøP’Ôt6•«»õø(ò°N>a‰§8w=ë½"gÿÎëÞ*ºq‚»Z÷¢Ë€×Ù1·Û1þÕ5à~QW"bl9XC1Ü-±!X‡yéJlê‡X Š‰Š”öàÀeå3Qf‹i**³Ë:¡›„ÛP¸G¨‰#1 }f’›¿d F¢ðË
+@¡~àÇ‹ŽsøW< ®c_Õb
+©@¥ëkdh ¶:¹€ô7Õ HGQ
+hײê2>›%‘­¢ls¤Å}Oe;\Xã lÉîÓï%«É·žçÜç c ìr1ÚÌÞ8匥Œ ƒ·Å}Ó u²&ˆxŽòဠ1Ô·WQGLý¡¤±MµB€­]W}ƒä?æXŽý!â.ýÅó[$™Å0ÖÜŒ›J¸
+þ-Is܃$Gl±÷Ñ­¤M\>¾¶ÆKx唕²B‹<1C±ÿ¸="vÓÁåXý²:Àù :÷¥ò/¦V%¼t
+MælñAGò `jWf°õ—š›Ç8È °ia-ƒF½” gbysƒ»¬-ž´+ŸÍ‡+Ã)‘§Ô}Õÿ¯Ö—òŒþ©=ˆØïNéNX]uDÇÈ[~[†¯ÎÒÉ,׊½©„.',:Rt¹V:Àñj#X).àùò¬ ¿†Ž‚Ïõá£ñ\õ¶³ˆmß$°Dò`ž’JÆHÌL®kŽIЕéÈQØ[%lûTCj+«ÄH1 ^ŸÝ¼U14&]¢Š¤ûs¥Ð,¸RÔÉMR¿¼™HŠ–&˜} œ†•ð)x5oí© uÈ.EÉ
+%@nb yìŒq¸g{VÔ²ˆ¢#Ea\š¡e£Ê 5>cçè-·‡a}3ôI%ö‚kàÔÙ…b-;FHã@o‰ljØJ±CÛTò••Í"|55Ô°³2±{‡Ä‡HÐljsRÌP¾¼@íƒ×Ð’hÇ †].ÍÛ»ˆgÜÆÈ舕Ô*…
+tö ×~Að&ïm?ýjÖròÉpÜÖÒ|ËÔmž®8£?õI(kÂÎQèÃb`pªòQÍ—@Ñ^maµwã†v_n9°¤ÉßZZ¡"l ¶Š·B——ÝÒƱ!O;§Éz NØÍ¡“(pÐ+ë*‘Èñ÷b±GƤáUÖx™¿£ä´%N‡ß-’ulAÝ°8‹€èL¤(D|añÒ|Ó¼|/ăI<t S>jBÝÛF9“
+Zæúén®2¥ §Ç.­sZa‡9¶ä²Ï ‰ë”ì0LÌ4€à6ŽsJ(0y2éL<<#MÇ£X9ï¯awY›œV °2ZŒyì-óS›N7öM´²Ë J<¯%çàTe,4N@…}êøç’¯æ°àòÎ5nüY0ª|NÛ%æï ˆ!oXæœ/¿?œ/þeEJ{Ìxb3·‘@'8ˆ‡@‹ß¡1™I.¯.~ˤ?¾D9Ó$OGôbò(ü·Ñ
+V‚ D/]žÇju–«KcuU9}SÐ’ì¼BѡʘQB&#AØÅUåÊ@<\M¦ áMH!>hrA à)Û¯:šìšL˜Y—ø'8¼jr1ÀWSb®&ŒlÆéauG“ DG‹Ù ,ûö^59Zb ª<Ìê›™ÿÑäÌ8°>,,W4/®1ÖÀkFsÉH*!Ic–Ëؾj²|7ÿerV
+O¢ÌOhÙdLaƒÿe¨s¨à–gˆ®(«†äÛpÉéA”"O”½¢›(ë¹#Œ£ú¢ÌÓCË
+*sQŒ'Ê'ªQÖBΘñ˜’Ù;¢\°>”*ŸÖè©„dÕÿc¼\’ë¸u0¼‚ìÁ+8Å'HŽ=õ.4•ö?Í÷ƒ¤u³Ë'÷V*–`6 ü/àtÄúÑ• ¶“¤Uü-{råú’O៕¡]™‘Õ /£÷[Z.®\_Š{äô±÷Ê»-ßjN–{kò»E7_>]|­Kò„žúÉ—QL쀅sþ³ž‹/ßÙwóåÌæ‰fF,eô|ôSˆṄë§_OLÈò@qÕrz<Ø°_’
+Ïïés RšðåÉá{á«ÃhPüÚN jÒº5 ¼ˆ<ÈÛÔ5‘/s@‡%}9rvù%Q1j5‘"MB$hT;?…*Ï$X?Ç´¦`
+c«Ñ,½‰” S¨)½®åP1¿D[gnm§•Ë)Ä8*ùùXl Dé~ø]èà+È6¨\§
+ÿìeP£DÕ˜±¥ÒÏ×C‘¤<¢æX­ý§§F­;o`¼ ©†³S‚
+–Èá¾Ë{±¦‚Yî3jÙbÓJ¨MZ+ðýéW¯žóÐIh?
+ýjdŽsÈÊ©KƒÁûØ¢û3ªB58T%…¬
+‡Èûá¤iü8•ú ×K|/Tüœd Çk ƒH# ËB³„¨
+'˜¡-êÚ®ì4äIâKÑuîŸE4¬½!Ûd±¨ÁQ¤¥¬=²Jˆøg¾ˆÑ(Ò×Ö7…IòAI}½;À’›LoÓHqx-‰–’–!M FÁ±õ~ZPî"y©˜ Æžµ_ÆZp:ÆÛÉx!5DZ_b/2¥<žî¬AˆM Q´„J¢TˆÙؼRÂ÷ê+2ý^Fä ŠÈÓ<©³ü¡
+1VvÅ&I‹ Ü@уÁúÌ_8é9Δ¿ˆ•'`ê@7Îê–µÙ¢î½èBŒ³pª1‚㩨+²#]h°`òçø¹wŠè$Àç÷ÒºfE€Is=TXBP 5¶åŽ$ œGž+Ö¨d´‚έCŒ€SmÙ¹M!ˆˆ¹ÛB›y
+a–ÅÁhGGãb]> t¢höÁVÄŒÝpö^òá-$€!)$’nýáÍ»ÙÂ!ûŸ)GÐöë0•@~ ®¡Éï9-¶Ì…bíc?ç}€3»Üÿ¦Â.±"Úš?’KðP‹|ä¨úg‚'vŒÙ=”]
+®–fJ FH §õ¤ù“¨Î`Éôù´hü ߈
+b¡žü_%ÈæG¶#Âв@„Côó,ñl<Ç CSÆ›fh¾vE.mÄõÜ"Z¶Î{‘>ïI=(FŸM¼õ—Í¥xO(Þ!“Ú)lLKõ ZdS¨J^Bj‹¦•f­ýÅþeC¨çT*ü½=ÒN×ð‰_dÔu¬a(2×JOÛ‚ñeOgÉGÚ5*xƒEÆCɇCØÇ® …<œÃGé<4Úz²… É‡ß†u
+*IS@ªsÖëCQ˜†¢‡x½ß\šý«¤ÈSEŸ^Ä…y?_ L¯"’/ÍFÍú|<8“4[-~9¢F,°µVø¨µX¿•‡:hÈrwÐRÄ" Oy_‡èÂ,Z(9š}¡®ÜIºïආ§’6Öƒº¿s-¡ƒÌOúˆ}bAÊàê;“u0_=7/!Ý ”¨Dê{äÚtÈøÙòþëlSºÈЂ‹“2[È Ž"8°.=àï/8þ½—Ü*€ÀšD:qñkÖø&J%-Ù+‚wÒÃÄgR˜PvúàÇ4 ˜ûD)áBA&Öãº
+=c!ÞØPÙ‰SóÞ{¸3{mä “\ ¬)……rÜi„¯VÅ¥ãqí™nxpž0Óñ’b#|0æš]9ÕúÊ”¡V8eÍd‚n½®OIšµÿ‘Š=vUB2kúÇò2Ú^ ¡1íK2•`A¡
+¨RÙ‰=K¡˜D*Á”ùsŒvêZ¤MRz%æ°ª„7Ãb§oö5…t%äùpâ¬Ff ÷ô\þ›sȨ6äC¾
+ßü¯ÇYDº
+ËKrù/­tu=P(€Ä±¾tÓ0 ¥êA%k=,
+œÐeø°OèŒ"»2\UÊýŹP—5.âBÛ«¶PxFd]#ˆŠæ‰’è•J ˆ$a£Zá!D Ç\'ƒ|
+‚¾b,ss˜°`œ[¯ÁLið÷à ¬y:ÿæ£ó90åÝùh&ˆ’Ø\m9Ù#Ÿ¬%;’$ƒWB`bù¤¨Å€‚‘¢›“1d™`’*Ò´”E°A«˜ämkXõä$Œ‡ó]˜$s®Ì2v};UcÓë†|ß(qrïÚ×\¿êÇÝtjdYL-I‰L[ØMyâ…Wô(b¤PþdÈa¤ôàŒ¹Hzniöà¸[Œ$Qê07Æ>!k>S¦/¸e‘Ø™Ã6²%œv}RxþªDp¸˜¶K6y9„B¢$Þë'Æ'7EªT£‰Ê뙧1s`¬4 /5÷͈.šÅZ 4˜<Vr ‡08eŠ«r(ú Dq.‡PãÎÓÇÃ9´‰!*ü¾ŠÑ¡N”Ïekˆb5)èûM6Ã-ÉDh‰ cvYN vÅm–.c/g2–ë ¼3¢8Å!渿ì$}!xðÞ¶/«,.›0jâ®Ü±•s·ÓP-+‡uÕg5ø]ÜH{M?;nÞÐÔ\Ëçèn‡À‘Y’(Óïè²ä­år˜«AæOYª'@Ú¾±Ht÷&³ÛÈ1#4cLM)fÕ&3?‚§†ƒÐUDs'È×;ÛåKXØL|QaãÕÿƒëý÷‚åIO:Z™¶ê›
+hb¡t¨aósˆ§¨Sñ9{×%Éø©,=  #øôDWᔳ,#"ý<Ÿ£1ÃGáþ×þdhDþÛ¦Cp<ÒpCu_…Y#Z züÔG56s{û"µaµŠOšVÙsˆîw‘å$8Þ7ó»Pž%Óµz°8í!´È®„ÕhM=†B(ò`å ÎMýx6½Š_z–‘Ü-¯Úqæ…¯<BâHßä ù tÛCŬn
+ºL{}t_ŒÃuï€õçŽÅçxøPm¸”%” ¥jdz ­G«¢Â:ÙÝ®{}½óMúô?þ&üù¿_üÿW—É™cðJ0ó„™W’¶uX_)àˆÉ•e…õiû‚ Jyyc* y†aqäÙà\©½ <»öwÆx
+„F°-„îIДU .¨ù@l·éÙD5
+lðÌBPòÃ9M;ÁÎóÌ|þY *;ÒÎOò$P“©~* ì^/btëóTà#ä[Ÿâª;HdʦÓ‹sî_ÓäSã½ÇWɘäY~î«^‹ƒ¿€T{“)"ÙœJl^bb‚+è±U/¸ê¥ã¯Ç¦æõcÓwÔqŠ¿ç´
+ß+üãBýÅv…‰¬tkúÂ=:UöV>¢ùÞ@R2ý¥ÃÈÓ窔ˆ,ƒÀô€d/ ,+A°G‹ÿ°q®Ï@àè¹H—ô®øÓf°Ð«b‹_ ”©îV£€Œû9Ä;:Q$^ ä#ÌbÚ“ppXºãÞMéòA|óÈ#ä5^¤åv¿-ú ¦REFo’¦#HÃ"»HȪ0ÝtHÎrahmñ „|ƒ/UšÍ¾8¸å[”‡”[ âåK“0 ‚L•aÉR–iEî
+Å2d
+±á;´À†V£'£^+~}sm"ÒcvA´ËÎ:9#)™ÐI¶•Ì¿e­l’—}•Q€ûÒ¶.Ì·Ô9áwÌ{À‡™¡Ùˆ~’dÒs@2¿C!Ñf;Aö@tR<Ë
+õã9ý³HѲRK¹¾fˆ³&}ûñrI®ë†è
+²¯@Å?‰q2Ô.2•ö?ÍitJïR¶S•TdC¼ü
+Δíéí47¯ÃÆ~€“ÜìäÁÔå%2G X|…–á㵟Kæã°K­Òa*ú³,ÛÓÕ!úRžÁ†YBgüÒyïçc~)Ù3ÇfíÇèº~¬3d@$;Š—JS™·‚Ѷæ[Ç Q|;ñ…»8&Žæ[VÕJÛØ}ž€‰veƒ%%õß”|UñlþñßËN¾G j#L‘S%e€úç­†!g\Õ(<»ºî„A:ƒËÛ僨ýóÝõœtëys^¥A/sgÂÁˆÛ½÷sEðä”-If\’Œu¶m$MÕpQ/ŠTæ'oœÁúR¢OAøÜú‹”æY‡ Haê¥Ò#±áY«9ÀY²â€þǹIˆ«Ó» ™OÍ£HÀ ¬K…tÄ:^Ôi—A†wòà£ßþ±‚¿IXAÛðh¨EIÒ‡ÛÁ_Kö¿\àm—gÐf
+J«ƒïÑz<§GF…0˜Œóß¿nmK7ý@ ¹ÿ¸ôVrÄ)’Iåˆkc&íÇGGŽýº‹ßé÷äýžÄjà²Ëî±O©Ž±"Bì ÿ,ºþ)BßmPÉ—"«1¹
+ ÀÌ删*’ø|—
+áÅT>ùkÃ/¬àR&…/úˆ+ÿ¡®kˆ¨‘ʸ£1|kÈPj^RŠ,>+fÐ]ÅÐy­†ãRÄ#–„êd 滧BÅQàºú¥èË*¼ÄUÀ.Û)ç¸5*UBäíê*‹+Di{:S.‚þâÄ`ú‡ôtEVèâOZÓ"³QÄ,bkC©-ôU ©IP :_‡W@•Löf—iØ\Èx­ ËøNkJšñgI§…ÁF+9-“ZŒ¦Šà/“Ìk当h™î¡õ~'G[Ïm:üO÷ÖšçìûSü¿Â +×[“þ¶‹ÿ>®Ã«ëݲ U»hÔçn ¾ F+ õÛÀ«„ ãʈƒ9J˜?`D(þ d˜
+át±+l‘ÀÀµ–høõ¦.Fì•„æQ:äŠW vïtK~ºYòU¡(¡¹ÉMÀN½Eœh%Ã,Ò]è(ß'ÿ¢ñGS!iÚöRk¨$y2)ÎÄDÓǤ4Ì¿ìƒ4†I«åâà~°.æ­eÎD¿ª±×nvZ£
+ò›/ÚL0-˜û™<Ä`ZQÝæg’‹ ¢L^¡b) R*ŠàH™¥ÒÖĺÂFh§Ûžðæƒ~Û"Þ.fÕåü$‘Ä¿‰´ÀÏ’Ì]Ñ&HýF–^ŠÞ¿)R&j '$±eéQ"ÐER
+­%fÝ—A,–šÓŠØûlFÈ‹ãH[iyxŽq°s()}4çŸãòE¼„Õü­Â—”µT’!ê%˳q‚dÀ…1¶n%z(^Êv"ºx k¸\ïRôq+ò×Ìz`<)Zoóä–|^³IH3q¥í Oè5óŽž<Á]-äƒÀÚŽøgaÛf
+â輶G"1áV
+2R”àPÁ~ÍãÖöÑ‹nñkë°!þ|\!‘Ôèíô øÎn Â!Æl-~в:gׂ¾dç³ uKh–<9üp]‡^Â"ž·éiÇ¢:æ‘Þš®í uØR„-þ.I,Ð ˆÁ­h&ÎÖO_ÔDW ABvŠKUsÆOí„Ì—Øò(QWàpžY€;'ügQQÑ 3ŒÑÇ.â˸Ê´ÂóRË>žÄ‹M•Hx€Я»„NKÐ"¶c{?@~e‰Øºò«’½ŸgÑ{ýøþŸNADI:çöЗ<ùùMzqê=D
+H‰Œ—An\=„O;øó J")­3ËÜb€Y9÷ßÎGI/ÿ¤v€ q»Z¢Èb±8Ú‡ÕvÉT«¥L­:?þU}^£Ø(M«t¯ÿùaµ^sºTífm Q.)R½Z£ÚÇ‚”ZæhÃ}Ô ÑÒG³jÎQ)D®"2¦‰©ªÜW=@}Ôj:´ÐǯÿýQ>þ½ e¶âÖ¤VrÞïT®ÊkÌ«º¹ââ½T-6¥íxÆoJßã õ9¦JßN%ª^zv‡n¥“7å˺kŒAäµ4^µ²Ýk«£‰ùÜÒS¸—s, ý*¥ym}ˆ¥¸ª_:¤iá âLÏÑ«[Ô¶¿£iFEÇ‚´¡f]
+©“ýª:k­2:dðu•^ÞFï|ÿûÙ4ç|Éö9Sfñ1IÅГc?ÕZ—¨³K‡RÕ‚3lß ÑÇÏè¥ôŸ)ˆò uêQkë2WÒ×'¡vßme¦D/Å©¨õ>)ÚU‹Ì^Ä!J=/ªê(56ȤM¨1«Ê\µÒ©<‡ØlB± _!ÑÒv9eÀ6ˆÑJM q´h£Ñ($>-r¹v'çÝTN4U4ˆR»nŽÖêE`~-z%F+yë>ïN®î½nEvnl˜ÁIˆ»Î‘RtÈDûž Óúâú yvÕ6@Nw;|ÑžÑÉ<á*.[ĹÃöh]œóÕÅðÉZ#ÀF‚ù•`Üh ƒüPƒš-Ìã²WÐçw"Z‹Er
+é´¤Å>ˆO¼ ™é2²V¿ZEY
+\$Œ¬á jß\N{.ÂGÓ'"®ÉOÏ™­EåFœ•® Òëè¢ÐU}ÈVLÚ™Pgë‹8휀žE#žFnè€ }¾â:‹N(
+·’˜(ùPw„ü# ¼¥¡®}ê¦H̺­ Ti.郣´…<j"1a1=|’È°¨œK
+
+zÝ'€ú¤ápÿ¬o%¼jFÊËÄJYË·@N‹¡s~*Ø(LEwþ(=‡#5îGî›)ºLÚY‰vŠ•â`bM»˜ü–âzHqKyÔû̃7Ù‹žü{dæÉáG~3š¿îk_7ÌŸ}­ Œ=¼
+ˆ‡Åòâ;×/ûZd äXþ?³}-
+ÂИð}Žt]{Vþiº‚`-¦T˜.OÍ[pß‚yÁŠfÁ3j1“¬[ù¶ˆq$Â{›fÛ"b«Áªßõ׶ž¢j¬~ù¶–€žÛZzÝÖˆ•ÆŒT]-ÙÖâáxÒÀ2QF¾­…^¥`5´l[‹2Plò çŠd[V*•¯ÛZ§Û™ò¢)hQ Bb!äß»ãÿokÁPÄ„Š`‚Dòm-˜ÞWR¾ÍßcY‹v!·ì<˜ßò÷²–¶Ýë²öuoþ3"e™
+JBïÚ~ €E±òRJ˜ÕqüMÇÌÀ…zÌÞx+Š¹Wš’NÒ|ͦ¨<9Á©ûŒÓÛ17…‰=£\˜ÞÁ4Ð]<G–@â*>j›ŠŒ IÏÁ³±p ©hçá¬Z$’öñ±¬E Åá”MCÞMßUþóG
+«8VU´pÙš¸+ä-z Ÿ©£ÔœE릭»bSéÎúP=]žOÖgŸç<ÊÑ°Ý”xøX^åQÎnLbØ÷#|—ó•ìq,l\Äv"›¯äbD_k4 »ëî1èL9W}ÁäföØ"ýŒj8ýÁ!0^ûž]OЫ²–»xžŠžÝS 1VàÍÍL*ýÌw†æ–Úûè'p‚FŠc‹jg  ^Ö¹›Ãö9xDç$Yí›ÍhW¬Mh§‘Avåa¯0>Z,zé9—5Š³8Ñž=\HJùx/Æ1à8XZsʳ'Òå5
+Œ¯ ¤c؉0“‘Ä]AfÞ°Àb—· ”&<‡‹'£g·!iÌÇàE-=d1\;¾òÑó¨F6zh²‚P”áaé96®0ñ[,
+÷è¡7zsV× ‰- ·ÏÊÕÎ)µUÒQX·‘€©bËwÖÞÎä¦T¡ª”luü“î!B8¸Ñ)’BÙDô z_õEoE"× Æø2’¸DÙçF¦š PH/rGÕÖ†ú
+úh^Ý¢—0NT:HäH 3?–ˆ¼JcfÇmt¥ èó;1íÐcàB†½Ÿm²¿7ˆRbí¨Ýªm4‰ ¤Èĺ0Úº…`P§å…¢×+\"…¡˜¸€ ÝD¹‚¤cBpì°ÍÒ¾Çà0ÇJh
+*¤#=…~Æ “ánØ4§Ž·>7d¶F·`§ÿØÑ—áÂÄB c#èé9ý‚!ì°
+ƒ’F½¡QÕë|ó*|ºÄFK·hz rBcÃMFR·TõØÜXc ‚ÞÂ×Ê™-ÌFÊ]Àj–ò1Ó:\Œ ì‹yšÔØX?sÌ_ë^ ˜tt§‡µÚkcƒÀ¬¨…,HxÁ"š‡Sˆ:Ä*µ¨¨ VÕŒó7($œv†Þ…˜±Ä`}÷~ñZó(gx‡ÝÅË{Z0¾s÷7ç(‡+Œôqæ
+Ý-a·…ÀÔÐUèqß· U§ÉΣ‚€•Õ€ýLow3`dµð¿eŸ#ä)`ür¦)R‰…6þlMpsaë©‹OPRrzOB(¼3óù• Ž uL6y]Ä
+{Ÿ±Þ4êø]Ы*~GºïÅH‡]ƒ˜˜)î5]Œr¯Cù,T?
+©Ñ¼$È¢!KQEtÿÕ„½£ÎK–
+x¹N‰ƒ5÷—1~)‡• dÏ“ ÅÖÃêyLüy™r¢G=øèÍÅG@›Ô³27©TÞH´ ^VpÞ¯°ˆÆÉ6Šp¶ü^ï`¥Áè¡DôÃo9}/Á$t|,ý½¢QI¬&Ý-Ón— =9Ö•o›Óäáp;Å› cbç’¹jä6‚É?M EÒÚYÏ\ç
+1ÒÊko Ü‘ä ìv¸CÙ&©o·äs똶Q4λ
+XMOAz) k²Èˆ9 mpû™0(˜¬ç¡–`×dž°Iï’$Ÿ%O'³­èT4ùT¹é•Î`6Ýß³ Tð-j0®¿Ñ#2‡1.ÍÏ¡«6eŒËíÄA@£qÍöm [PÂïÌttcfr ˜ò ø¼‘
+Bg’Oy©‚±ä‘t½+´ÒÖ%/˯³°ÔvP'²ãÌûlÜ ¶S|;Ìø±„ôpœÛú9…!F£Q>°ÎàXŸÁ±¯=<‡†‹¸0º².Öµð,0¤ì%ÚàÁºBØçSäE0 lÙYÿTj–~ÀÝy“@¦b‰:‡ÉÊòËÚðr¡Î¶¶&
+Åk TŽZ;DŽbÛ—^Ùk| ‹à%fù3åŒx¦?;|us6ÁZGƒ²‰{Q Û¿Ô÷— 8ôìf:ø "rhÃsQ¨
+*ëþÒ美¨†ìÐð¹½äss?Š¾~D 34ègÂÑ®C
+Â0àÆæ%Šˆ¨ð:R0Ò•qD .wB—,. °9/=ô—Ú‡*U¤Æ¢uaäÇh8©a&¥dÊ;Ž½¦d‘™4-X*ÁðCkÓêÕ­W =à%ìOš"U©}w#²°<6¼Í@h‚§‰eß¼jzÖqKX{ü*fÓ [öy:Þ£(çÊ Lé¸oBÏ¥ÕàÐ"4»Ù4fõϨèªÿþÐ¥W_@´ÔëÃÿ¢ˆ}Ãx´5ùoŒø×7Eô¯ilK1ïKâ#Ik^÷CdÜ;Tâ8BŽ#®Ç0¡oj ~Ï{80Þ8~¥Ñ¡£ø aÉB›â%ÚØNôk©SWì…Z©}ÿ
+FÎöÁXP%Ý©ßçY.8ÒfÀqA‘ü¼Ènöó|¦²dþyk÷=ÎŒ«!S8¶¹ý$(`lxL4Oµ°‘
+×a6âaaSVn²PØÙãAט 'k^2ø ÷
+Ô\ù3rrT¬
+3 nÚuBÐÚi
+ÀP…ePŸëMqtÈ–ÒZX@ê+ÈÔEžúçGTD§ kyˆç4É°ˆ^ã£r­½‚ë~fØàÙY±<Ú•ßið{÷dvD[|_¾ãµGÁG©ö»äCÎeMÖþ°s[À;›´z²Ÿ¬z±²º×9Là*†Ãpä OnKß+ZYö£hºÂÊxêS0_jW=‡Yax©ìcYd{e˜åW´t¼Óð¯|Žÿ5ßÌçú~}ýˆh@²6
+üÏX›)HŸüo™ýú2Ó¬V÷bæDÆ@„¡ÑLü6™éö²(=íÒ+!}mzlDØ
+± é $Uj*0‡¼oî§9ž*e¡³y  æåpYóQR’”&x¸Øó&‡`µð£
+…ƒ'(0*Ñ䉹’¸ª]·zæ§JÔ|È)‘så–×>T±¿@Nôµ+ÛâZxq{Ö‹"átž‰,§[*°wbƒ_
+jl 5Ûƒ-”@1§ÉóØSùçy 0<Æ!œåš<4Ù¸• xxêÀìáøš±1cEH=µÓûCØB•˜—°’niwÌ߇ø›Ì>Ê ¢õÉ›+F¦)G°Ê¤¶¦ ö©B$'Ó
+I_R…;äà7u‹ØPq ÉÙèY„̃¶ ø•Ø—4VÅ¥—J“ '×á…*°êB0Tï%` .…9û`¨†¡h͉A(¯&™ÐÌm©¦x”f)&
+? v™š7™ D ØUÔµST¤’21˜È&€<‡™¢,Ücf ±Ä³Á&딀JH&£ìåÒ†Y
+Íʲ¹É¨%ªÁ5&€{[àG Öž>Og3ð6àGž„/©„áÕ£Ø|/™9;âÞˆ¢
+ùaƒqÖYº4”#Ç¿—é%»(è@iy BXñrˆª§€[‰¶âG ÝìÐu©Û2lÍq}Íÿžøv®€
+6ÍÍöd\Š%u\&¡®°9S©€)€y°Pa‹£’//å[=‹ ÁV+âñi@Ö`HÁIêonE³Q×UÉcãlõìN’e BAOÛÖa`E×hÛk"øjÂðɪøS1µkˆ®A‰£ÓÇ»X0XoÖ­`e—µ+:MÀÇ­" ߺLíÅßÍÔ¯kòHTœ@1¥ÜýDZ“¡£!*¹ôæKÑï¨("Çv÷¢ÏŸœI¤‘?þ¢fg
+™CL^;y /Spg<Sóã?‹Š‰X€(
+J¼Á`¥(ÑÁþf™wH
+~ÖPLÒÀUmopVB`û¨g<©JR¾|+0AÈIòù§Á(~Û¼¹™ÿˆ•^M±N„¿)A 'íDY÷ïŸÀXˆOñXrŽ=èvj^šâ’YèõŸ°CÓõ;jïAšâiPÙ§I¼žº{™òàxÄ«M$^¼‚qÍ…‰3içàıÇ…ÒñûD2³¸¬µ¼×²ŠÐ¦|°— >)'"°þbp¨Œ4hYA…ç莖s¸ vw¸{_ö!—.'O‡»¬OÓ<Î cìºeôAßø…¬
+OÌ %«:ã¦)6¸ÙðæiœpSº¦ž)P}íç¼ü_ϬxTÈRW¼ûƒ¥*…)ȇþºkdÜKéÒ%øk;,ê ‚ÀŠˆfù#Øq$與=&¤±%Ü”l´KsLZáׂ'+P!IÌé%âÙdÕù €ò&HþíYâÉCCÕt•¹×é°Z mîÝK€TÚ24$€j
+Á<@´'€{Ìqè=±.ã—®°É2ñ4gÁ¯À˜v¢jQ,{ð@îD'".Ȝ׋Š “—F·‘Šø0@b!|Á^Ñ¥ZØŠ–°¼Ž|v©ÈØÉéJÚ‹^Á™'»‘t&—âÈzÒugK#7kø–Ó=%!?°j*v> ç[¢q¶ó7©!~å#ß H´”_S—‚
+¤ Å÷#L<b¯•B`!œPGÑ‹Ë´ìúE.”ˆ9øjÒ®ò
+T¦ü°­D
+
+ß-4(ÑVÈ ËÀsb@Âu³‡ÂUZ+>Í€WÙ…oÍqmõ¸â&›héZ »C _h[Í+îqTòå­ÎV"ú‰VàQ¿ø4¨I^X¾ÙßÜj-ˆ`°d¯|«gwø¤¹¤«A‡e/épÆÃKWƒ‡ºU8$nï¬òÍ—ƒDÐ{\'‚ð­-Ñ Üšûí@ýŠçNìLdaöaý‘ã¹£Ôá£+W+5š;E$x™/>r^py¶RÅ/l—j<wÆQä*¢±S8Äè­#2ákÞJ±{®ó
+”êrsÊn“ýÚùUdö-æ”e% ËÎ #yVÉ7ì¿Ì>ù5’ü(ZØÜ~¦aEñš§­tøe–—=% cO‰­·EÁ;ùYÒ‹£BmÔyã ðpI»y£AÔ“ Š¶Né£È17ÕKðј1rXOõMIZ¤µT»qvúZ#ö×q¦Â[õe Ÿ$˜ëòQqàÇ\š9¬„oڦћÇS`ÕØåÆËG²c‡¢+¨=”-#ó`
+’Ùî_Aã{%Sû×¹ ¾*B BµnEÄ#y²*®åW1Ãü!‹·ã"ë±’ö?¤+¯Óð*’5(J1„—PNb^Aa!Ù=¹[Ÿž>{lm<ˆ¦¬Sm´X$UòóX²³ÎzŠ¶XØϼŽ³E(aÑÐ`7í`º¨io`Ã"–óh/fœmÕ®vNƒ†È(ÿ®Ëke Ù¡5ö¡Oö~ Á8ÛœxY¹æX€¾"BCÛP)ŸëðxEŽQ¿ìOžåÅÑ^kôfÄOrÂ}|$Ršð–ÍK * ÍÜý€èj}g>™†ápäªÍè|2+R³\qëåâЛ$”,´vE AZ"Q23ãÐRo©¥%Rf¯®$’8†ukíñƒ ó:Š¸š_Å|  ¨ß¯ïþN…¢¤ÌEh0G{æjXtæÓD¤“h©ؘßtZBtÓX4;'ç¢fRÎäC!ÚN™vz>ŠŽ°0Õ™ºC¸"Ñp¤zV¿Šê%)¤b·K šÇ¬wrÃù*ìùëetIöˆ 6ȸ B˜ªN?Ä”¬±S sR\´ë•çméÂñÍŒÞ`.C^iJ\5Ž£nt¹Ø*(±ÖPIÕ脱!ƒU¡ˆCøf¸Œ+HdñÐJÞÛvY—w Rˆä»ÏÃ)$-¥LGwêÌ3ëe{‰¨öv›ªßs}Om¼ãéhúÊž¶&–Ä_á¼GàŸâ2„êó2yºße.^:\‡aà÷ö8ãÊ[(Cý<~
+³[¥GÌ+/áeK3O—É`lðë
+€¾3†¹…ç0ƒh )p+Ëøkª– v ~;w}•ü´CZ–‘ß<4Bù8æ˜ÁV‚¹ÇH³ãMÌÔ—ª\<zh’[`’íEõ5f’IÁÚaê¼v(Ç)Û84Übiíòuei¦
+¦“Ž®à\ŠÛ„•Z£•G½`ŽÈÃXÜÙãî«“zºql-sxZxÚ˜ˆ~ þšœ*¤AË`Àø(&’¸íªG8Æ”âárº„P,7‹ÁmëÒö0Ù—’§d,”qƒì&îÚÄouyœQþ=±ÄAˆý šD ˜°íºIsØ’¤;4ùƒ‚¦vÜSÜ!Ñ¥óýo%ªÄú©M`8èùºw@’32
+¤G8ÓQñ¤ˆ¹žL;T¤i3DDR ËlÞÙ»÷mê/+x
+
+€ÐHB¹¯^tþ–~@´)©ÙJ.W>Úh¢Ø>Ú 6c-öªtÉÏ7ȹiV¬“$åç`µE±“vö+…âäR%tù3h„ L¥¶ÇÙ»ELªJ»Jösä+Cn?ÆôZeY˜Û’C™
+x¿î-Г(„Üzá“«‰éÛÖ‚H`î àU´`m‚?+o+åmPP©ûuï€"‰@O„ ÐÅÙUW$0ü
+ß‚ÛPÍ4_ŒÎçVRʉ†cSÎò¤`
+çbr²XˆÔ^Œ6%¢$ ¥wxçÖ&ñf(0·FDhêïXåf-/F·¯,-‘,†Ãwe òmÍ¡0ˆy+
+‡ÏWûñ{EíþêÖ¬,qaús¤/ù±ÙéøjRÛ®±¾dTŠøÓ»Ur¨/Y…(úîºöõ%‚ÜôåŠfü0¦8Ÿ¯zðï~Ý[ @_~+¦/e>”
+3Ûbš¯ ‚¶Ð`µXC‹¯Iišª>C~Ú` ÛTVÙÅíå¶^’BΕFEÝ¥–í¡á}æ¯ÜÙHæšRÇÑü¦¬#B=7ÎÔÄjÇ°Ø1ª¶¡ë‚Ê‘š¨ÎóL»¶Ê0z<ªQ>
+tâT°½
+øw¿î-Г&ÄÜzIjòçß@ êÔšývŸæ2l„{B ÊÔ»iL"* ¿‹Ijm Ñ#Y¸˜âÔE)ç(,š¤A˜ùÄ •ƒ¦¨¹Škb‰&¥ù{*”bΙ?¿ªÃ äd*k»r@
+¤–A¦ÀAW™‚ ÁMñª’ëì€uZ ‚n|ì7§Ùn Ä[`­vø#’úä Ç}7¾åaÂë…<?w`ÁP \ÄcS_Õ0ãi0ØjÁgh)B>Ô,s•+
+¢ÛAÕÃí1w¨r½š°£DÞ]b¸º´V²=MÔ‹”Jß÷4M×c)Xe¤í%?}+z¿•71Áâó“-s~ºÉ•˜,ìaø+y¢­¡tJ,D&—¦»[kr`»DÏðØ<ü”Äí$¹þ-†@®‰½W_~Ž 5-çé6¶Ê)ØÈ“`³7[²=©JklkÀCɆ2C{Äv½:Æ°KºWû‘ïLÎ, fî̃$ñ#ÐÃÍr"/>áCºVH;™“ olæ¦95ÈÒi1HA5Ñï¤!%vÈŒÜAJfª"Ør.ü­èãEœ[À2”ìH ÔÀl2MØ¿‚Ôq¡¾Â2˜8çòÕ=|$ ÕXð%FY"4 –UãFu¯§`&ú' †ei˜ø àPx9Çmâ^ãKô—~'9›r@–¹s4sçñ@æ–û˜Æ2²ø¢ó¾KJ“Ùf^˜÷ Þ [÷±_J¡ÌÓV·y=‡WN%Î)³—á&$Ê‘Ž‚o!sÐnÎ7]ó/ $Ì gÕGûð_¸žY{÷s )l¿ÂBë1¨º<òLß–[ÅÀP+ÈNÏE
+˜¡Š ‹Ä?v„ •Ù-Rèß¡w0ÝRã)»Zøªâ†¹ð ‰©ôëh‡¾Â˜+žv_ä¹ä)”ü(¾Çœ"Èçú
+?—ÿôé(ßÞÈB%‰žé--Å:ÀË佊‹O%coà”uø²eØÙÜ|Ð/›S­“î"¸e`[_+ºZ!º–hIþÓCù 8¶ý)Ù˜ŽVøÁ[@:4ÊD9EL0Þˆ,ÿèãRôþ¢c½’¬3ªîtAÈdûaÿ
+S$xx¡"¹ÞÆá/¡Ò•mb'Ñ ½C3¨\Šbû RéÆ¡Óo„{úo ^´³Rq•–¯Ç ì~U;W$Kj>¤[|=Ì´Àé®
+µd,g§4Ø…Iáنŧ8’EÊãl85¦ØV†Ÿ3†|Á ¬ø˜…HÈq‰ÐÄ»ô«äÓ`´"7km,8@±BCårå/B©†Œ
+Ê*š[KŠjk7yÈ2Xô8—uå¿YT„+¶0wC;l‘Ed¹F¨r²…«àQ–†®å 4Él“z䬈ŒÞ2O zÉÚpäL
+—-<.ÖýR¢a˜›AøX®/Î)S>^™f¬Cp<"E˼BWÍè
+/8núkîò®¿ÝŠžÌ
+Þ[Ô ì`’õÕ蟋°•UÖf㼈ϱÙp°žöºˆÎã3'ÿœëys–!_ãøÀ/Ðba ‘A†MžU*^¦7
+š_‘Æ¥—øæ/R¬l—ÐtÈJ¡±Î«ì±†K¼e¾€Ø‹…/Q4á,?G_.ÒÆ°Îød.)+*•½£È¤zY{ %±£~æUÔÔë9ì¨"‹r‚xc_ùw±Ä†N×ø± Ó†‰–hY±c#ÐÄÊ:°O_î«`Ol™S lu{bÀŸðªsŠ/l‘ G¤X1ú.¡{ˆªÛ&èS€ ¿=¥÷Á4÷Þ鈪K7wkHLÊ1-¤†A $gÓ\’r+u‡Í¡ü†i—ð ð‡r¦§Jö@eà±è™‡®Û9š¹V —Ï‚=aEœNö
+ÑgA:¦|â[̧Áÿ(7zょ’=rNÁ„ð¦ÚoEÎK0?–VÚóé. ‚Ö¨ÃvôóÛ“þuXX°Ï}°ôÅœió¨t„×˸o榴8¡uÿÜȸzPj`©g|éZÿczP_È¡ažåtC
+§hÍá,2”ï¹½¿(*2jCD‡2|ì"+2'²O9rð­d¥îp0] ÍuF¾-œ«¬›è~”0®Êá—„ò! 6îàðPXM_IGcÄ÷®Kš1#J£_GõãÈù,Šë3W©—åøô‘-ÐÆÐÅkfÔÄÈ®,,vLàDàs—è©X†^‹…Ùeâlع˜]=?ùU|”EBcƒ&Í`(¬¸7}%<€I§âߘ]ѼlE ‚T$ðgËJe¹íMÏÏE¬PVÎDËûfç燲Àþ©ÙŠr€–ú$Ê¡±wýýn:•štªþÇx™äÖqAôºƒN@Ô”5¬å¥o¡-yÿ­_Ô@øwç`‰VUçÃIf¸D™Â÷±—â:Î2#‚BjŒöþ5TBÒušz±F^ßoÖHqr~#ãÜcpœÙ°ìJ¦ÇòVi%Ž õ‘ýXNÆi¿ހƌ ËëÁZ¨ ©cª_->M©•u’Ã=ì7Ú[[ "^doê1ØÄšQƒ÷þüºCnVØ«îCPdÈy?Rƾ¡Ly£†qñä$¹™·R(³òøAZ#Ñ'0öÐÙuÓéÁB,zß#qY:²!j)çgunôÁ ªàX‡}Œzað£¼È¢òwY|Gr '(bªUô¡¹çäÙLH'Ôökº©bœÁ›è^JçÁ _3SÍZÃWäš‚üXˆg¿Á`xú6Ïa¹Øö!K´ETÚg
+lX»5´Í°îprÙ%.Ò>ªÊäž¹P‰ù)¿å¼xÑ:²Â´a®ÆZ†ŠÌ³©¢õUdˆ.QŽÖÂRÆùýÈ¡¢[~fÈLTÖ–"øBúš ¦"%n„ÿº“š¼g+
+µ”Ñå†Á“SdYõÒ­hx'Ì"oØ݈6AŽDša_…üÊrôùKÂËØ\zÜ·³XZ_™“Iµˆ¡oP _ÒfüD£ÈH+O1\FׇÂM=½chIs°xŒÍ,^‡0€q;>›ŽËEG&d¾˜™S€ÜZÍ|b0ïe2 F„beRÜ6õF`ªòÐîÄ`ø ~¸{q•ªa6­DTNa\šYWQ<ö¾±\u¸ç`>³,B7V”
+èE ïc7ÂTÂÃÉ°²—r]W
+#Éâ4ªäIš&y,Æ¥ÃR•$)·Z{ÃN¨Uä\@œsq9=¯:¤}ãCPdJ¹3zL&Kt½îú|²¥ÿÎeƶ3àt 00F¼[CèÀó\æ;(Â&¢Îo=Z*%¶ù1ˆæb øCÉñÈÿº×=©”O£åˆÎ¬‡!ƒé9Ù´U‚àŠ”6)b¨›ÈeZi ¬ÇÆ”²h}Ÿb·‰¹l¹> •áP$ýH3=CÖ0¹²¦jHªOÑù (tb"†œ³Y7 XÇL²ñÍ9¬Æ°²çbÔã
+ÙþöúÀOP$>$̱Ö'p0º  gb?×s(KmE=áVÖ—Âw
+‘j†„¤OGœ^•GÕ«´Š¹ÄïyÑöïì&Z™%z©-¢¿S ©®hËð£T"cÅbž´U½•3߯‘ÕdÜqÒ¾JÚÑÄ”½ïÒÄ•O} ‚Ë¿m[»1ÃäÓOßAàþÎ×Ú,ñâŒ:ÒÍ÷.
+vAÎúݯ{ºP‚¿ZФ—Ú>J”„¨16ç¯*rÚ„ €)Œ@a˱j†äìç8†‚s¢¤gYkŸ–«¶ç$”W'
+;œ•tWÕ·Èéy¥y˜ ÉöÆR8 Ë
+~>ÙÓµÎP?‚ÁÈ{½­­‡$!Ï6×ÙEkY(X>Kx¥¤ò£löHÍD&sÝ„MÒ°CB즈ñé6iº*Péò)cÄ X}¢—Ĉ8œP“fõ'Ä0XD)&³ÊºÛX¦þ¡‹°
+‚›7Š[ ó¶-?Ó;$øiÍ  ÍaÍí]0æJTÏçÍsHSKcªëÖme /ÄN¦ê tÓY§‘ IHîäÉ,Qû&ÞŠ?—JKR€àáoÜÑvЯYçÏ/“>¬F®ÒÆ¡Žé®ˆÆ 3 r4.Ã[á×û¼«DJ‰ùaS]1½ø]“úÝŽ¹wÇã|8yËí&rË
+ã[öUשH
+.ä„€î*ÜG+ëÀÐï}€²‡à9—-üq†5íaO;n…úH3j[Çq´`1Ê{ܯ „…„™‚f9®W©QIªL½·Ñ*®®Kv@@\˜pÜEÊØKÆ£×ýpò¡ mgu6Ì‹âj"i3rçxðXì5ȪøΙÉ—5lx‹ÅuÎ@ªâ¤¸6V<àùeÜù¨ÄŒB70åpç]ÔÊ`AœtÉœ4ˆŒÒ
+ÔAzòXS×1„ÈÅ~ãÓ…1Å6 ï¶Ö´5¬)?…!m¯ ÿ¾æ>IéuYÍõù8JhojIór®ÓŒ dí…¦‡“-×ÝsšRܨ®[ö!PŒœeÉ瀑wù¯‚˦Jz…râUø5`,»¨HØ,Wh(RMÃò:ç:í$È +¢AÅæw{4þÔŽ°¯úaµ¦Qµ ÑEÊÉÌýÜ)Í„ƒ Épæì’;%ŸLY芗;(N”
+eúÛƒ»aãÍÝ }……§[e®ðî1´‡Ö X’ôa^ì Ú/ÖÙÈgɉrªÀA÷Ø逮±SH ¶š=/v™nØð”»;1„ÜpóB§:QƒŒ/ѳùú†ïàï• †¢ò£é ¸–frÃ+9¤–Ù @$wÃXBM¸:™Ó
+%~Qjä…N èçdp˜;5íŠ+˜UZýØ逜ž'†¥Bßþtw?¯éÚæø*HÐc¶²Iã3)†æ6m{*©Œ›! D
+“§#‘Vé’F‡‹TÒbý}R
+bxËŒ ,ǵÀTÆ–u ªºî€î‘€ÏÊxR(ŠíŽñ1ˆë"`×3Š«®; yt¨sh[ºÍ3ka.Ž¿øfbReáþñß/C¥L–=Ðœ2-TàÛÚ…«`û‚Läo_``øYím¹fìwä\}혛sÝˈ¾hçÞd/ä¬+AÊ­h7%ÎèóÉÞ|´RdK™–ÓÈoš â‹Qã‚sDBÐ1i4ÖJY¡•‹ú5[Aé8ñýŽhð3¼.‡7Wän¨2Þ)Æv"šæ¾ßIãÊìE6ìew®Íz@ð] \äU ãœ1Ç–ˆ®ªL(f@|Ä4÷œúeˆ¹“òÊ^´.‘ã=ÓBúDjÎÛ½™sE^ºë€Èìa¡m•‚Íõð@•¡¤8ø”×{´äö0Õ¡†C“ÉDG8šA
+Cšhèþr2¿”ÐÔ² räÎŒ¥šç°ˆ0T˶ëÜ€;d²(Ï,2T¦ÈÛw2x¬~Ò€BƒêÍ9×–ß^sç«î#x-Î}Žoö /úûdi¾#aA *A|ÀÃ6ç¼/”ô¸=B—c½‹±„:ðDÂW/
+&ÑlžÇ.ø~X^ê(Gèxu]õãe’YnÑè< 3ëÚÖQÈûoõ<
+SÉb`É á×ðæ%·Ó)F ‹V³"ÛŸÿE ÿx¢`ÔWMýÆ( žNjN,æ>2ÂþòÅ$aã‹æþM•»È«ZaÐÂëÕ¿¥JµU"þu³ÞãòÈ–êòÜžóˆ<á1<RÝ–¯7\`þËغ÷¸1fÊ$œryÙðHKÖîv1áEÖÎ?îFLÐ*ã¶ÜG±00,Ð:Æ]ÀE¦™šöí¼Ì iä¯÷6üºîC[f¦T
+E÷3AcÃðâù¤Ç3ÎT¬Ž—1ßzüØK „ÍçƘ.‹g4ð £ ¢8†ûðåT<³
+A™Â„%-©˜±‚Ì u,«d‡&™„ÕWÞ
+
+©ÓŒ2·´+á1šñwmƒD ™¹7)° (-3ÓQö±Y!¥!Ö7BÞñ0ˆ;@쮲WFúàëùà˜ú®R±=¹rÔÀL>]A¶³šÏe0Ï“•Öè¹û+ÏCËʦ±#™ š€nß[¶´A¸³žÑb6ɨ`þ±¬ÛéÞ<ƒ»Icè`=„Kb2Q-]ã­i ðf+<Ýè$Câj›zè8=èšùâŠAˆ#¦EŸhŒ?ýŒ u&‰\Mà´—AÁV<~î%У;þ}›¿Üq…š´ÓWà^>Dœ]é²^IýnqªŒnå솋)×pa=+“Î,O‡$›KÚÝNHEÃxznNU{kÓžazꜘæ b—fÕdke!r .5s$zÌEV6$;Ñ"Ññ8u^ždÖ9…öÖبD†TZ
+rù:ÈE Å=ÑE9TÎ:Ñ „„¿“µ’ä ºÜÀ–h&Š_P^ùF;‘?綅¾¡ü˜jêñ<€ê;uÝ}qñ¶?b4ˆ¸Æ¡Ð¸GAó³Õ"O Â^že,÷ØÓóüÓÓú’F±iŒÈ‹†ÿéi ÆßycÔ9<GÆN3¬óÉM
+Q O[|AñuR‚Aè¤bçIükÃ%çq@M‚Ü#ëfÅá&½µú9”:ûÞÌ|–‚¤Ã–#WSr*ˆ†SÓèn{CvL CˆŽz/Aa&*ñ‹ vÎZ‚uÆâ4³Ö ]yyÓá
+‚Uò1€ÒNÊNr)Å»¥È "
+¼Á¡åxöáDßÞ­:íF RþF$š½9$¥Yä5EŽ¾?#A¡c³’C—lªÚEP›*o‰
+ïÎ#2™¢É¸²|6•Di KÀjpŒö»Èxw*xLÛ×äS ùî¦Ûª_u®
+HC?g
+´½ç¨ŸÈ‚É®Hm’~þ ^ÞD<y©óoÑpµw¹Ì«è¨<dÖ„ýLìƺŸúïIþûå5ª’’Ô Ñü€~?cŒ„©â%´‰oBd&Ãä£lž®’9Øx,RYûmkˆš%‡¥äÂèÎÐbœ‹£Æô¹A å:f³À8¥Ý¬Lg’µ®|—`‰›ÂR »ï—Côè2vá9L!{†u"îcç¹(,Û´,{ä!H–‚'5;ïÖŽó¸AÝ#ï+H …¥î•¿Ç¾ú.§šù J“_yr”ÝEa;,íbùsÃ^=ØŸ³†‹Ž2”>¶?”qHq‘¨iú–ÇvþG]]âvùŒØG‰DEuL\¿iˆ‰d†äV×^þƒ4Jýš:X%J‹éŸÒ¬¶‚NO¨v]&[2†I è-x cÜ”F²²î#ÿÃ'›îZÛùÎo–v‹Š(ªrOË×b~˱ŸÂìb¥—9Ž;Ä[`:ϼý qiøHiÇþ±ï ‰ ŒÈ
+ ÏãšxíËQ•tQ ¨ŒñÄ­–[¼½‰gÂs#ðgh¶û@ 9¾Oǘ» ðíV¤4¹Åä‚ÉA
+ö"Å%PÀ•õ»WA|Ž¾ jÜE|1v}4,HÕ2x…H"i™ñæ_ñP™žâ. g1ŒüòŒ˜v
+10ð
+F`x´^eï(ÌÐ
+"U¡Hf›9ˆA¬t •ä¬2Öá)?}ý AE³ÍÓ‘ø|Ä A—B„®îñÚÍ(T+ÇP8S¦èçÒØÌÄRx:õ›iÃkl~Ò$gц¬§#»‚ÜÅÞ6ÌÏÁÕáãÜ­³¦•B,ÒØl ѳjn@ö$ $ˆ±/OΡ =t¿å|oþb~Ç |·^åˆ7¼ Þãh¨ç.ÍwÃ'P]L9\˜6ù$Ñ0ÓâX‰fü™q)ë `Šöpóè›»­LZ”¥¸ZÐǤ[²Ô—ÿöI–– üÌûj¥„nRè~ÞL%#3M ˜gÚûjÌ:×¾Vlâì!InÔöz¹h/£MnHÇÒó3Jfçå\:¤%ŠB»Ät“
+)kÒ5çH
+¼±Ó}h§ëbþ$~U°kVÎQî"D™Âœµô Xq Å°bÅŒÔú&‚ó8÷\+žAQÅ(¡Ç\¢ôL,»e»€Fþµád™,â3..l9rŒ² Њr{
+k` å¢
+u¤45/è3È€>S¢ *» QÀk
+RÈš? £æl"v™[±õЧ@ñ¾¹Æ‰‰hyArÉâ¼I΀ª…$sÚÄ{xÍ´Õ”g4µ’öžÐ÷~ëŸ?°Ùüù÷ÄE¸d™ZPÓ<¤Š/H=ž,ZÃf¨~ ±KQ¥…= ~Ó¤°ÐÉíx­5Ø uË^x‚†¯ ^j§ª˜¨FŽmM2G 5©×™Š‰EI”½#И–Þª”ì+‡P÷ÄQÒhÎ?ƒ ŸßôÐk5A áÂ*hqÕ[`Å*OR@¦/s.q¹-‰5;!u§›†:P¨
+‡O˜± ±ÒFF!¥äت…,ÅFLÞ»Q‚àÂ:S[¸ Jõ5ù´Z±ƒŽ5 ÍõýÇ1Ë+Z„ÅîžE·1ÌyÛ!P=‰É<©Ÿ{ã]€ƒ-Öó(¬+|[×ñ®ßͽŸÃ¬
+0ò—ªF§à%SÞM8”/fÚn†1¤…žjã6roc-zã—¦Ó™;Ÿe•š¾Ží·
+H‰Œ—A’[9DOÐwÐFA ®Ý˾…#fU¾ÿv^’üž(é+ÚÕ½p© ’
+î½LnÎsŒ×18©DïsEx«½‡L?Ï­‘áÑçtrÒMþœuÌŒ,£WŸôVªyT[7ù“k¢ÎæÙJÛ!T`F©eT›+$¬Íž1ªû9¥‚8HŸ«,fµ3Œ<WPk6[¡`cÇ)N牭Vçª GBøVñRŒrO«dßwˆŠ^†[Pçu•=‰¦Èfjì ’ÝÃ
+݈öPˆŠnNæ+DŸÔ^Ò’ÄâCHï>Õõý\õ¤÷PÀ9ÍÛ~r8G’Ä)`¥êQGváfÐI8"ÒƈÒc¦µ ‡YO;ÇôN²vŽ¡%­”MĨå¥tî³›×b Ï»ÊÚc…Ð~k@dÒö›ƒ¿®H«g½ ZdhePåê´ô¼f6…üF:ˆ­Yf~r S®~íÉo£X‡Bí<x¶è6i‚¯êõÕ¹´J•Gî{'cÒàò)ÂÊQë*J fêã&èëCoª,Þüä5’çxoÄÌáÃVHáœ@ö<‡f7¯s¡§ÄdÈ›s (ÂÅ#Å ¨Â@^Å w1Š>ç‡n~ ÙWAæ"=Û‡sàIfÂtD伦–Ê›ÄÞ`¸ó—žv\AHE‚’zˆ$¢R,lXYãQë9‡r¨ ¡e~¡µY¨q«1¯«Þ‚²xÍ°Y7Ç}7¸ c+ Âà-­ØÏX! ›ÁßBöQ
+’ž!ÅWVüJ-,Hþ(¥k 48º
+‚É@"s‰¤uæèæ¨MÎF$K3∤ÄÙI¡ k‡’ðÇ—ó(WWÑ+ø+æ ^š
+Q[r:mƒ ðª¯*ôHò;tÐh£C´ ö§­H/é»W3]ÿ1÷”îH•3þ7¯Ò=™ö%7¯^B,Èé•ÿÛs4áD:žƒ>× Ø <%<\!‹ª£;ñÙzsþL"q 4Fb¢yûɃœh)f£í†7
+­©@Vž¸nò™Jmú<°€Íè$ëÿ¯²ˆÔ‡è“:ç3)¨oò‘¢{0‚Z¡n§å¯ý| Ù:9j"Í;¾9gRðå¸þœÎÁöˆÚÛæºø«ÂÏÉê2Þ”­ôƒR*
+Fh³œã=!^Ý&_Â%B
+
+ÀçE¿V¢ ÁíìVˆ f3fmˆÉ|ñTóF‚í }†+È»UyÌϳ˔³ Õ[‘WÄšHhXñ @ô@‡¶B  kXÈ
+JÞà«t/[Ò–â‹ Qƒ)µ»sÕ&ˉ¢œy»sî^i¦³Üžíìæœ×Ž¿½æ97Y½#ðµ8ï0~+ð]È·FýüΈ^åЋì©¤öv×ø_·A¬°2xŸÄ¯wYhu¨ŒÞÞ.#„عØg0hÁ;†"å­`<˜½ŠÄ¸¶ÈE=ZMh!ç´²‹-Êày6oœÀ}ë_ÅBY7ÄJ;j½ Zô2Ö¹~,åeoRã0>Qˆ,GIµ.GÁ&ƒ²â|¼®Â±k€Î؇S9P-Š˜ÐœMÚøá›
+—–{ûó.–7öTTþ.×!ØÞ£½€Œ’´ÀÅõÆïpr¬¼'XÁD^º<C+«à¼è%C ëÍÎ&3}ù(£%Níe:Ë©›vÊ/w¤B_é¸Z#@«þ…žËŠfÒ>tqf±˜7“ç||= ]q7N}•YÒÀÞen ÷¡caû
+AoÙr!qX¿1%?×Uì ,’æ¼óQ„àvgrAk)fcûì+d™×Ì)L5X:æ”\àËSí¤C(x©7A_;(ä·'e¼l—B°,løˆèÍA;O敇 9]_¯™Ëo,Wâ“/±uÂ;yw Ï.#÷—ÃöH1Â}CŽ,8Éw^þ®›ïx'¨ê‡¥¿#•¦~ÒHÀljñoM©g®^KIø½_Hý‘~²è-¸7PlšÙòìä¤f2ÈŠ’Â"Ïq:Áùnnù¯Û¢§à•Xl†šyô"q_·AG1“Ì òí»'£·,9,({¿Mýe½Ý©¿Tðe»]m€÷‰>¹]>äûQ;A ;žöÛ~?Œ ¡Bž±ýÞ]¿Ÿ¸ öA›Ø™WLJfcKÀo£)­ÿc¼\räHr zÝ!Oðÿg]³Ô-´-Ý;ÏœŒTJ »!U[…»“F3#d7[W™R4ÔçhJ:G±šÑ äa…r!f™¶·ýæu]3míŠýˆÿ}ìˆ*h+É“+­“*ƒ~}ÿŠ„ œ‡¢8è6!à_‚E›”Ù!˜ü“5—¥ªrºÐ· ã^ä9ñrU«^/GÈd{ù‡‰äyŠ~í’?ó`ØÏ×\ ™¤uhLZa®uºvÎÒˆØmÈ“L‚_Iéç†^0²]i9óÝÉÛ‹Y, ” éY{ŠX«ä¨[æáJ°Ò’Uø ÑTR‚½3½>Õ\ª€ŠrÐW4 Zšª ¦X7 ëb^Íj'öTð®Ý'Í㺰۞=ÔqD†[ºÁv=¨*d^&'²ˆàFWúà‡ô.ý–é(ÏEd1øÒZhxÿ4ίã¯
+ꤞ“\Mr^-·ZœÆOþ† ü¬ø?qq(òãÕØ*¼hIÛ†ÆòcÌÀtø‡~0û¿Ãã>á²b£à§e'×u*Z¤ž!°IÜ=qÞˤ+î&Žålâr0ð¯th4;dæ°Ó32-²’îK]W¾À…ñÐݵá£õ0¾:d25ƒ=©é®ÐŽëŒ#=€ü95„ƒC;
+iª½ùû.JŸI™D¨øˆ¡TÀ>°R^Ùˆ@Œx"}¢5++S›5]l1§È\ÛÐè#Ö—§³8Hv“è.i£T–Q­5L°ªŸö%ö‘´Â°lEV–žZOY‘Þ|‡°ʉ‘ IŸKfÙ¡ ™bâ,ÅoCh!ÖrŲ,ïHÓˆµJYCŠ–4Uל* Þ¸Ã;¥OpÔ¤ç Èžá…ò„î2ÊÇ `
+f1nƒ>ˆ†]&)/H!`ÄÁAsSD4…qgV𬭠;)Xt•©Q´Ê²Ìµ?I *Z•œ¨4@pö:´‡/E!?eGýqµ'¢ÁÒ['ÊO·Û2µˆ@I3x• ¿"µöØåGý¬Ž@,§üFe²‹Ug¡¯|
+CïäÌùjH±wêH*ÿ=Ä8¡¨K=Ý•ß|fI#ð]æƾèQ7ß‹s›…{‰ÿ=S_×è‘ÔšJí‰ïE¾ÿyðLe¥êdýAjÜ{}r§£“€³‰ÉLÑÙ£†’óf6Ýsõõ”ÜP…ÒX
+ÜÃXʶZÒ{דÄUµ“²¤ÎîïËhd™ë¤) ^¦Q wE¶2£›´’âÿsÂ{š¬Éß9gEäÜ)ñ®|9O&®cFâÙlOàÆ= ZŽ
+eXr*Ñ×Í)k–š¶ä<@Xyp#¤±¸Úñ/âvnu.ƒ HŽzã©Í’1<]J¨E÷ûúÈéÊä£böÙ[g‰Á3þTÎaU:ÈnÉvµ²ÊÓ„Xf·Û•abAÑLÆ8…¡9¤}«qRŒá$Šª‹¢þŽÍÜ£a¦›Ðr Ä…Ú±(À
+^TÔÒ$ª²»¡’Úe’v@X¯(‘Éy“m|TùWæìeªºž…ç#=Õw;iì‘­ó¶±Çˆ»—–Aƒ°}°ŸðÖ¬•*˜™ü”•LD9ýœLCDÕ™†€lf†´¦éËûÉÝ("Ùìé1ö(×"-*LS+*!ðs÷."çWµÊZ•3ëS¢X½\øÃàÔ-‚wS¬žíòÀB¸ó¥-ðÖÐĨƒlÙ+é’YJÎJ—¯F0SM%:=×¾Æí¦RüÕˆ©X/𣠱Պæ!‹jA$*_±ÃcŠ’Æé9•>p ˜L$×jr Hê¨ÃòЧ•Ñ‚0N?ï Š11ÔÁºzúyµ§6ô–öõnÜ´ÌB\ÖæÚ÷’<®eßpr[üz­Uúk§N+±'1%ÊÄôŠ…¢é48¸£õ%PÛ@ ±š{Pµø;“¬Ç*GB¦ãn}jÉ
+â‘ʇ¥AN”ßÖÎ{È4´ÐÐ4kyó†i/¸G“»A
+¾Ë±ïz o]™©Wä#$"É 3ZÅBù7r·)±WP¶N“AŒ9Èxš(É]„P.#¦Ëý¿~ˆ€è$m®ù“>݇ï~Ú'˜9ˆÇêdÒ‚GTÉ/Ž\œ÷×@C²EÛjr3\0e l™àt”rÙ.R™<”`>ºâªðø!Èb…#‹q™æ“Ã3[éý/™ŠÄ$»¾@Ôx|·'b²røÄž±!²84¿ÌB±9ZÃ3„¿ÖÄ;ª?ªÊ†‘bÔ,Ž ûöÅ×£Qí½Þ¬hˆã¨Òh#?ŸÞAM’Ò³ E/!xà=ðó¿èB¦@„KãßØß5&ÎQ]Ú¸´”‹±}²Æ<´8œ^ãK%R¤ËQ(iÚ ÑãɃFÑ®Ìöùs˜±)é‰,:{øV³ÒEV|µú«™ d·A¸6/VÜî›·%]c«Æj"9µ'Àû«*Ì–q Öå|+Òâà4ɺjŒŽÉÚ²ˆc )ð6ðMÔ»uó¡ÆtµjŒŽ  &¶V}z™ÁïOUóœÿš¥‚CÑŒËù¸Rû*µgjÖ™i†s9fÔŒD§FpÊÙs==\~ýr”œØÌî%O`yôZÒTjTwU^SO’¬™F’‹³¢ÿªœœ„¶ÁÄÿg1󬤣ðuÈÔ¾ƒ&ãAžÞ*FÌ㢶Gy2UªÛ-¿`~Çþ´eV\zžZƒ!%bLTr6N9.%Ý* thZjñµf­'ÑŒYqïå«h]îþ&¤e£³Ò@ÎŽé‰öTè¢=, Ú’ŒûùÕ<i“—ï7úG¿¿ FrjpÚùYew6j(–'ƒ¢hháêAùM£z €YSŽ„#QXâéîÜîËœ5îiÜà*üÉãÒ•ìÑŽftÙFMꀇhC!Ùê³+ºUÔ1Äâ@ýb¾½|*ÊHÐ 9ÑíÀ—;#¤Æ3¨UÙ©
+ÏLHe,0<œÒpû«Üz©ƒ, …ÈßýJgæmNRD²ñ#-0'l®WW_\.jüÍ,afÂÃôÃòÆty$ï V)»Ð71
+µ`‘ÄofO×íMz’±Ë%Ð Û¶Ò5.Q°<z
+¦Œ@¶0b¸‚Ï/Ã0J„+~^̀ǺÌÚ­7þ> f·a,ä‰í Hf*Ò÷ÿ2^.¹•ÜH]AíAc’Áï°ÑSM{†g¥¡÷ßçò#”2#¡Ø°¥Šb’ñ¹qîJ2
+Ï™ D°7ô£”JuÁJÁCÚ°LøœA‘Z2ùLœe'èà JC.‰Ä¢)dr}ÿÜ-è÷+wšÞ €š— àù³‡«ãËú: ®~ r¯~ýœ{õïô…A=¢ÁpÌiò)ˆ »•ÍÌ~ñ¶kAÆÀåÀÀw "„p”°ƒ¦ùƒ*l=>5šÞã "ˆH×XÚVˆ+)êã"ߢÏA D"Œq>¹AWRìÁ(„ñx’ˆãNâ¾¼Æw"$rš¦Å™}¢ü¿rŠ ôê‘!­RL,&ǘ[«ŸJþBDR=Ì DÛp¦÷s–Œ Á "1»*0KV›”¬·=*"8Ù)[x
+Õ’BN?_AHˆååhxêxÌï
+eOÙv©y!Ïáä`$ŒjÁ_¡Ao`0ܾä‹Û@ \g§ó€8^!¨WcCð–ݦóSt;â·¹¯Ê°Ñ¾Ìì›71¬'( ËËŽR';“gPe{I,ò8Çó>× 5ž)À òàâHù’õIY”ÄP–¼U©ñž¨qìÅ©øÉ1×u`;ÎášgŒÜÒÛÒȬ¥†TƒÝj~ Y#‘¤)U*î9ýÜäCl¨aíxŸ.Þ7Æ4ͬÓÐ× ¤mŒ…Ï ³ÄCÙŸ²,”¤ìèÙö>Ô••9Ìñ¤á=X—Z0ô£Œ$åŠÜ×’”*È#Îñ¼Á1RMF†Å6«éU6œÞ@¬M…CëY±ß(Fçj|š‹Ý§%NŽB"¤C1³ ìhžNvÞ‹síWn™±jÙ8„»U϶(x^ûµ2œÆ^©yÏDG?²rQJ¡ 1´è#žfw‚x #HìÛFPr¾-ÃR¿NâÓ‰´|Ë;ðLs&!Ì ÂidÄPÇCŒh†ô‘òª$5%U‘)H^”o#z†?œd<æ’dÊ‚ØÏ  ½Ú¸^zx'1ü¥²;K~JSf
+BÓ2U gÑ2‰íÈgV™´¹Ìs´b 3(4e·T?–\ãvwÕ$ɇOsÿI\«;ؘèO%Î|¼£ *4;PH³± Ç—Š–©dËØS\$Êöåcw¨¹8£òਤŠ’gþMãØDÓiŽBžçÀô
+Aš‰`rÛ!¬Aš VG·vgÐ+QfU<cN”¨•=«ÎÊù¢ÕÐÇÎM®Bó
+‚ÅÕƒ410Ù$á;Ãh bHCÛѵš™%˜¹;7^OV¡_ßØ‹pvZ9Ž20j¦†g`_Ó‰]†YàÂ`?ƒáÒÒç bF
+·nÍ× #±ƒA!iiÛÓÛ9¤-`˜"JqÁ¸-<hß‚J@ËF@þ‚2”‡¥Ë÷ ;oqiTNÎhˆ<_ºû4'£Ægx­A33Cø¼Œª ¶Äó'ˆ1šSҌ࿠7 &'ߧó(3Ž¥a·°Žj ªñ,eÀÔ`ƒêÙíM*BÏ  I°ØE-LÛè„ü=û¢« Œ.¶°ºç°ëY:Š¾@Ã$ÅtÓX¸163rdÇ|rY”—MG{í/™NL Z:©ù¾ýÀ)#fÉù^áLZû¥Ö"1eéN4Þ% –ì6Ûå¿¿¼ §âr’àhŸ-<
+GË×ÌB±Ž…ò¬J÷éÝ:HA44\1¸£ßeNŒ˜õ L2¡eÇ\?öRʦeÞÛ¬L²á±ùb° ØŒú6CߨVKe²‘ga¥³ Vˆ¨yô/ñЉ-á2¹’˜WAZÓSٶܕw­*Æá‚ib ³œl-fB†ü™ä%ŒRß¡ñ^Èút&G‰žøpŽþ‡Aàk‘p.‚J´“ÆP«ƒ½
+¦‚ÂS4 I%e ˜÷¸aÉÄQâ‘ÿ®D4%¿#˜Õ­dÃâ÷™ßϹ!ç~›£WÝ|ïN¸4¿÷øÿ÷J¹ÉG
+ /‚yÚ-4Ðy¨ÒÒ€¼ËÃämØäaA‰>µœDG 0*òbªñ£<sÍ'·Ñîaϸ>ž¼
+ Ä~u.50vaw">ô8*ùmVß_@²0Ÿó0ÌÔ11µF£ÿ•w@ØdßE±o*ÁˆâX ñ.ëê#†Ä°Y½›ß¾c=¥s³mª›!ÿrÝsóX1¥@m <jHÿ9%uï5¼ SpLí§BŒ<‰ÄƒÉ?”l±Qb%Õ¤øÒ%Ñ ú”ʇË‚Yo8ö‹¿©(Ò*EüuÔ›¢&7Ïp „«ÃMXeÉÃ&5þ“ëͼe0*úuða¼6R¿$t¶ü[`ä ÌëpO…Ñ9ÞýòA$šSX9¼:é Ñ
+uõÓ¢t‘rÉ•2€šêkSÞî=¾Ãg· ùÔZPòý ü $ÿüçËÿ~™£ Ñt\@A*¯85zÅ®ÃÀ.££‰M™&u3­XG~
+<š~PÔéÈÅÚE“lfT¥:Ç.bK•µÙ²Ÿ•áoü"Ÿ¶KÆD7†Ì4ã/¯ré
+Rý5ŠAÙÒD­ð2Ȇæ§ÄUé%g¥)ã­³õ)}:„ÇE¡qA(P«êBòk%VNÊeèÍpi‰$Sa¢ñ„T¶GQáÎTóçª4‘•ŠG¬á)È[àñÚWË\)C!J„mÙOÚÏî —B÷Ï} ¤:Ñd* ³dÉešo°JSbÅ÷{+kiE÷‘•ú
+"ìƒ
+Be«Wy¨
+Pƒõ¬Iü„Ž›± Æ=ýß’zq£ùî!…ï´¼X­žÈ~ßÊ~7š™QGdµ-LpŠì©Ä6Á“ÉÇZîÊߊŒ.æ䫪p"àvÈ^q «™Ø<nÃÖJvÏ9û}Üæäó¨“÷Úœ$>êëA>õ韯LÌGˆ)d„ˆKØ^nçýrA,= "^)|„÷²²Â šSÐ
+‘“…°d3ÏîÜÖßmS$cG”Ç”Ý×ãØÌWàÖû‡m"Y4+˜ FŒŽ
+Ŷ‰w«2´™Ü;?EVÖËÓˆtcûf£^Õþ‡khIeYy•˜HÓ‰)/© ö™±V«à˜(ÇŠTf^:A·Öÿ|
+Ɔ
+b!qÃÌqùZe¾”éLþ&*†8}JYK)JÎ(ºç°XÅ€®(þÔý*F:Š2úã„pžùSß#ˆPújyÒ|9 £~ÖÝKóHAJtd¢·)³ð%~ÕÒºO“``…¿.OŒÌ˜ì¼®§3Ý „ì*›Ž`oãòÿãœ{#XEäÿ$·òJðGt‡EѦp¯"vuþ›G.Á$†j‘ ©Å ¤ûKo˜üÛ¾"„’V†ÞVRpÒ¡’ÌgEæ1=>ðÄ3Ù®–%„L« ª8!fñç"Ç‚t|ˆ’TÍƾzÒßÈ Lð–ŽA—’2ÅêGÇ)0,¯º›l‘býÊ+Üœ‚…d½4}º¤õv¬§ñÉB C\êËþÈõ¨PX¬G³øITm/ÁSÎÑœ°álÖG’4ªmòˆý©02"ËøÙ@í¥Œ„¶$´„Acºèwä½i‚îCö%Б&Ö$bÜá™^šPvTŽjn pÚq¦‰ÙÖÖ’B?ŠíÆ È1ªÒºÐw*)%w…êÔûšk^é9æý(dMëGñDfÀ0D‚þ²É¯ŠY Îß<Æ“Pá1ŸÖ[« ÁYX#‹.›ËþÒ›éÒ þù7³ø׿üùß2¢šé1Éœ5±C-~ Ù„cì²³fr!ÕB]Ãp@ðø…za‰ÄÊÉRbL\)´–Œ7-!±ëø|œY•†ò'ˆ •")!·yNVþ×æ’¦âÄùPÀó†4âÏÐÖ4Mr¾Í) Jec“áÐä€~<€:\ž>Ã1W 0ËN›L
+Ðò‚àY¨†zV6äã¨ñ,‘b6$3I'=N !šÉÅP,8þó$ÑæAü‡.Î «´ˆ{˜J«®’Ph<±ƒAïÆ/ÉZ3N.wGdª|}ÏÅшÉ€ MÌÁž”Ðr_MÐ~#â0±Ñíû ²)Ö¤hˆhŒî1åUB%%tö™¼iZG‚nT'‚…E–Ì< ÛO’!LÏi)©uøÍB®_e
+#.1–/ËêmAÈAøƒ±ÿ´iŠHKÂ.«¤z?Ü #oÒ ”¤¾˜GÒ—v§¸ˆ[øwÅå¸% ±ÜOñji%}¬L±)\Ùå ¤î'îSWù‹´‹mcædz‰*öˆŒûâ.+¿[Z )|§ ´½;Å µn’‡sè¦Ü\›è~ Uoš‹V•NC«¢4»XÁ…«j\Ä0Û¬ ‘¢á)Ûê5àì©3¶øG
+`\øœµ}#$RÔÉóüMÛ%Îl‹’
+/R1˜œʹñÒöFžÐºÀ<Œ%Jes Á³Èh{ŒxL/¡¹ê÷VE¿_«¡±JTg˜É|G6‚XÉrŠ)š§ñ@°æ<X„ ž#›-èAš¨üÒwd@è&Q ™až<GÂ1AZ IðYˆ‚B¢U#Ç‘µµ šW?Cv0‡ƒAŠ3ŸÑócª<@iµ•å5w?Ò!et¼¥ú~ ÖÐF­(ž)Ø\æ‚ÍMOï{þáǶÒ5ù§
+ä„úðh`ÕÄÔê÷–\+Œ‡¤d„ÁîØè %góx~¯0ÛÀä`K‘>±íÑ/ Vyóåc¯ÝÒ <”õ·A˜ÛšÐËâ<í ŽS’ؼF ¨lÉv^œ\L„^›ý®ˆž/ðvØ6Ã.À^iw"h…¤žC*U'˜þÒäW”v'8˜éžøæi/¾3f’–dó¼ŠqÀÿYÿh¸x7cÌñ]?>'ý0¿}PI°—bÒ@iƒV<B6ƒj0¾\Ü­
+yÕb`yÊx´ì~Ü› wã°à!êkƒÊÀz0þmkv¦ÜÚ/ê‚û/ à=R;Üè;cÃ7‹CpM#E
+ßt„ߨd»±ås±É£°¿³Õ Â&V—ªK+T BdÂgŒÝWqñI~¸ø†a%©ùPT:þó ¢“ÈKôZ«‹€Xøö²§¥Õ,u×´Òy¤¼:]+ä2–gS÷EdW…jùS_f<믓¬öSé.å7aÚ/IO(&¤ÙË) Î
+‚Á&·áïZMõζ‰
+¶w¤ Æl°ÍLÒ¶w
+@wí18¸+”&HaÆUŒ@÷öë¸Ö;š@¡Í^ƒ0š9ói,s¨Qz?ëm ‹ºf4JEd{3Éj‹š±ø#š%±‹5
+¸akés˜>4µP|ô¹Ô ò¯Dóu—¨Ÿ‡P³š•^­|*ÒUäW†ûné/0Ü™î+Ã%˜ÿô€F©ì$Ê®[á3:E£þ$+Ž…Žëo®y6ì¿ß\{Ððµˆk»¬6 h´u²®Ë¿Ó©Ñ¯[gd´,<=ädÊ3±a7c ›&…]ˆ?Ó `è›T’N0Å"“@׎ªõ aE©‰rstsÍ0fioÆ„“pŠ:m»èÄE & UÐô¬¼¨_Mé¸MfI ÓŽêˆ1U):QÖ!r€œ0;9úyxC«$$¸ôË´>ÍÃ0PÍ¿Ùi¢­zˆÞsxcÊúÜ5ÆNM¥H©Ú²ÛITE ˆè‹ï<wüv›û䯺Oàsqîc|«pùÖ©?o¬Œ–+åJ½“Dd:F>÷xRDTäcËöÍ‘Ä©‰É.†Æ'i ÒÜr'\ly;¯Ï£ÎY:3½®
+U™ÜÊ^ž3±EÜu†ºŠŽCŽŒvÔõ€çL{ÍŒÊÉÔø;L{æ…˜=fþ/é¢åÚ½µ7 '«åc/y'ù(Á‡É- ö BÃÖ·y†Çù’ âM³gJ̺–«Ø)¯e‘ææü<{¿¶éȦ 1ai÷?ƒ¾wý+Ä( B(¿Ÿ…F@N8Vº»!h{ÍupØûå(2¢˜q’ LJ[À ž—ãúæ"ìô£lãSm¤æ\½d_âÖ×cp.‚)%! ¼+$Ê'È^blÆ@Ëá”ÛgäÑ'6ONs]wA0y;½Ø‹ÅÀÒÙ¦Wœƒ˜Üžè0·¼«0ÎÌùPMOmèA Þ'A0‡
+\N…sÉÅ47ÓäiŸ äR”ŒúXåœôÃbº™«Ë­4CE-²4t·˜€`%ef®½º[šà¸7AÏÎA³Ɇª‡ÈTãÝC–0ÃYÒ61ð™6$‹C Ú©>å–í Bˆ!_£ö>
+_–E‹âr¤µ8Ä‚“i"¨) q@l–ÂﯚQˆÂttÖzŽÃ„÷'“
+[¢UW>{q:ŒÃQ8¸v%«o!NW®³ÐÀhQø‚UBÃK­‡8•PÑ+\ø¤3ú3+9qââBÐÍ{órq<öÊ ßA÷½Ž{ tq?/ô_c\ñ [ Å"9Wrü׺<ÄV1ö ýM­ŸScD»¡øuüqfæ?B–CôÛ‰›…bÏû{\“~–Ýß
+gX½œ®1e^y@a{–›{l¹Xñ1µÖ«6
+ø˜`’-ÜsÜléD&ºUÓ+ºÀ²ñodŠùX5üŽ\&üÆ·&îã\˜ÙF0å)„¾àq¦k¡o±V
+oÊ·¿þ‹07S£;+@ÖDl:g½‚+$ÄÿL=ý
+A¤Hkbwt5í øAJ4Û aîXý%-5‡pé¹AûúaBÙ9 £`»†x:Æ—éU™.U7*3Ìèîé”,LéÑ‘WÍ<Ó!È$6€ŸÔAþø\`õ1/.h7ú&³6<$Ü/‘0xu ‡@NÌ?1¯˜gq$‚”¾'LÛí°^­‘ôQÄ*ònÊmŠúR!$¶û(b[.ìn&36ðÊ© h4нëejœ®Ãö6èi¿ÞYÓß¾ÍÃyÚcæI!ÌJÏ‘2k CS¦ô«Jâ€d:ÔUþwÒ jÀf³Fu:„}c‘™_ÛµÖÒ-MïR.ò†
++A¾ujuå5`±q®í#¾MjH†
+ %Ð
+4¸’VÇKðº:|…W`ýù,`W…÷Ì:É;ZªAÑ÷7E&úôƒÝ6§ª"°0^D¸uŠ’”Ù
+þ*<‹
+wÝG£w ?D9%ܲDe^EÝižÂ‘âuçˆSÌ…”ìuÖ<I^.1Z˜ÒGƒlÔPT{¿É0Ê"ù¢Æw
+Á9kO(˜ÍÍuxc[x6H$0MfU¼ñ‡¯¡7Á«;&PìÛtÖ]o¤Ð°eçp
+kö߯‚i ñ©YƒŒ®pcf.}ñ£^äù—u19fÉ&ÂÝ‚+j‡U±”òõ!­jÅ€®u9K >…¼ÑBÿðWßB!\ÅÆÞ•’œ
+Š¾‡E‰Æ"
+Uq¯hù/+j˜ü*2o7:üQ¤üAɲsû2 Zd‡–o[ £gŒT”|6•#Ù” ssÁë+wºG™6Æ„=S‰–i»ËµC¤¼Äç
+ý?%¬1LÇòîå¤Pq}4ˆcàµÏ¢ì IœwTº¤û€;†š”ÀjPôÓŠ H-N×$çz1}¹NU‘P–ŽY<&È WÕ0\]Õ²féuql²ŒÉ­¦Ì*ÂráqÅeŸ"œãÙqZµszb0[<ï§ðrØ_r ï K†åE­Ÿû§žE­lzÁË0€çœ>µ´¾ïÀPÚ…ådUxõð
+“²Éõ¾ŠFh|¼?U—9þcðjs·sø2º"©¬oø$ÿó©<¸JL?–LxlÇĘCÄ€*VJ€im‘¨œƒ +eH$ä­¤@Ü“— ÷œ‰W¨vóô .çO»_§á>Š~L«ìq ÝsìiJ°£VyƒJMcŒ
+"”ŸÖHð3»Ø§&ÛΪg^}t1ô-û¦åFÀxÖÅÆÿIw\Qz„°Gö/½uø™”aLù:» 0dMJjnüjCö(’e2Eí Þg¸0\Ÿ;ÑÅÄ[!®ò%ž,ŽåQ»žM׿øa»ôÌMufœ§
+ahÜ~ÕßôA
+ÌÓùÒbC°†Ìâ8ëŸÍY±D7Ü%Ã-ò¼‘Ý3Ü ·˜ ÒÚ!®‡ÝûãeŽ[G Ñ«è6¸/±SÝBé÷ýS¿êæöL ’ABäôR‹Q-_,Yχ?ìâàº@áóÈôòÍØ©± ¢ÖBõ˜Zȯ»!÷` 3s7´ù—ÏMø~š7íª W$y&ì[=&zãë‘Ff‚#·ØlO¶OŽ¨hUésü:nÅká9/y¤sLrc\ªßʼnŒíÖ;eÓ
+.‹Ù*¢ÿ)ð P×yüMÖ§Ëþ>!ºªÚša
+9?µðœús¡R„QE_±MÍÊÄ(Ùà«
+/œ­©@ÈwX7Åvb) ¯Å“êx6¸J(¯«&ÉeSƽ}qlÚ1x0uu ¥Ø /”§O)£HwJ ^ieºÅ³¶Âë¬f—œ¢©„GRA! Ad}¥fXèr}øbši™Œ$WªÚÛ‚yßϧ$ZC…–Ø9÷ŒÄAííPÊ„Ô“Ú|nz"øOSö çæsÓ„ùª*'¹±³sDáêqöKÐ\‘ˆ TešÊD± þBÔÖµLÌÆoiûãÙ2‘(–Ì')£„¨´ÂS+' £5sBgDÅ$ÉûñG€
+H‰Œ—K’e· DW =Ôü‚àÀXjŽð¨´ÿ©O’¼e÷+VHÒ@­×yù™Éfý5¢gš÷Hß›i/9jë…ÿôµwП?€ÊmÎQ¢[ýø¼‚Ú˧EïQJ¶þ!ÈŒÌV‡ÇÈ£–飔(mAXw”™9kŸÒk³¬½D ÿø÷Úªó—…_»wÛ šYê˜eÖ™kZ32lŽq ­VK0mòÊ9ÇË2.
+þ¡íªòXëôp™.°zåßßòøw(_åÛ‹Þ ‡ƒ¸ ã_›!v¥ß Î'ðBøÜ,تÓ~ͬ¢Ac#HP^½mg'ØÝ Mxº»ß»#°h ¬>;97Jʘ¹'§x*c`Ñ~d–†R쎌š¯ûcÞ£’ÊiÆäðG‡ëÓ¤z]‘­ðŠ!Ñ‹oø  "G@ò§æö¹8z:h™<H[Ã.ïÅœæÙ‰æ:”¢$ÓÖ2µð·-Û°vDÅKò#l>}G0ö]™£µ³Ñ;hPõPìä²­®uBŒ°ÂrƯ
+Pcù_,bdvfXqž¸E|ÍÄT@êLiiÛY½ó;älÌØžt¾I38òw"¼¨4ýÛ2©Æ3ÃN©. ý®Lßcüôã/ ÷/5í©ÜAW¢Ýb¼4Y΄.©®÷/uv®Êyé·¯Ëgi¤dm^c¼œ†œÚ¡g@…{×=%+½÷Ò~X‡D‚¤ÍñKŽ—ÞbU¸¦Vñ{Ž¿È×{Ž¤HèjyÖù5Ç_ —ùlt\¤”ŸrüwзoËGDnÜz\s<.Ê€º3å§ÏëQHåòõ-Ç£ci(c´•â=ÇëæƦŒ%ü!Ç«<‘Ž9 v— ¯~kªÄœö„ç_¸xCŠDd™÷/¡•G=+Ê5ÇË©@²ðžv òÑ×óâ<òžäµdéåñ=oIÈຌÖ“O£~IòÈ÷$}Kò º˜fÔ¯I^(ÊóÄ8DÜ’<,¢Á«
+ÊÚi¬hÍ&:}@X°ž©D nHÉdñøOG" „‹ RE
+IõÜ&Ü*îtÂœ­¸#É®|ùþÁóù,«8|…ÔàŽÜ~C°vAà«,HðÂ)\#>ô“C®À®­pK—ó¬TÄs JÇ×CeAg
+Èh¥LÝÚ—~¹ZJ|-ikØ©f¡³Þ”Z(%`>ø•µ»‚¹ÞKä•ÑP¤’×u|Ñ ²OñÿœÚ”õkìqè®ó¢äQÎVz>ÀŒ/–‚Z™—“ò11Aæ—ŒµNª^ëH{¬ÞÝñéËE Š–’ Yc×ÅÛ1/ Ï+a€xý`yÆœ_ñòG?G­¹-öÆ%ÖK©ð
+%Èãú4 „-ÿ«2i­Ë'æ“Ð|ò1Ó}O94Åì–Rnýüd
+<T~ÌœýÁ¢‘Yˆ½ôqlŽ=Köß@ŸDG\w­û‘A½`(³ˆ‚)é˜6«~bcׇ‚ó¤ÆHÛ9ŽëÑÄ öh_%FæÊÄÞÎÍå$·äe¹OJ,]ñäM‚öb‘íÞÍ7ÈÖG…RþeÚüa¢—™óÆèýÄ_~‹uçØl2yij‹ É#ÎÁ ן'ܱŽiF~˜†ïIóÿ“ö?¬¿¯\+›ä…Kº·ÿ2^.Ù™Ý6ÞJ¯@‡oãdØ»è©zÿÓ|Ňâÿ¿%DZO[%^(TfÙÚRA¤âi}æZTJ£}„<  ‡l´4~ôAÅeA)pLˆ’kïuA8€¯IŠvX‡¢Ž²T;ÂnJŽõ›®-Á(HÚŽÐ@”ßñßlû6&iN›ÝÊSˆ>EÒ`Ð2ŽGgÍ=‡-’ð+eB2̽ [¤)Y"È«¡Î£À$¨js‹“ÔaîŒý’½Ý{—V­OÝ ØGÁÐ4³’wF¹Š’!óè!]%ÅÛ_zÖ&ð__Æ’·­3äL+"Û>‡A b ÿ²Õ)†5‚†è†,Rpéz¶òŸsLÑ*5ÅÂÜËÜôsåÑøQoþv¨Îìñs¾„Â#ÝÎêùwq‡àDLÄöÛ¯ýÔÁ6&þll#y‚îÏ=@Ÿ?¹Óo]½a¬?榭S]´¡°=Í«7ÄŽt¥¾¶ö*±£DFDé· ºßˆx­rrxòoåÁ{1áÚHBþç~Âbè‘Ô ZsØ/øixSófBÁ@r]"ý`¡˜§Ø ~JºZ§dòë$ˆCêl_>æ”``‘ȧlµ;ÏŸtN Ž¿þ 4Ô”ârAÏú†2Dz1|Ÿ=ö0l€Ô…è­L#H&_¡Gq« €B0sFAIŽË¼ØƬ۟ù%ÐÊóŒãØ.Í<CU’8o✌×÷AèÁð£gä‚Ð0žÏÃïù^ß´( ,h…ëõ@Š"¥ÒRûÊEA9R|í>2äóè_Z*Jê!\…Nóa“•*×`Ãbµ$ÅÏžy .Bè«$•ù±LfÈ*-áb#jù5™þDÌû+Y„ PúJ$>bõÜ.¨½¢J^7Å&y¨i!jsÍá-“³ÆMšÒò›þ¾9{´xµás7üºÌMçQÿž•¹9|•×ƒ¼´éÏæE“ædáíÜm IrŽûûDÖ̓ÑaÄts²Ë+̤N+ç ßà‘†o,ˆ)|bNñ´+bÄ"~ÍN J#,m‰T×2ÁB¹Uhì°â°,£+VPzÉ‘ º]@6ÁôBø?ÒºÎudÇæѽŽQl›Ræª=[ƒÕ ㈵cÝ›±Rf“·‡™î;o Ý!Í£®Ð oŸ?‡tAŒ(ÕlôlX››ɱ.ûdÐ*CÛÊEòÒ
+ÃðѳZÅAÄ›Q6à1Q(rbrPùniç›ÑüòÇÚI]ˆiäîÁõGóê@¦AÓB:T=ƒ¬ã#ˆ“d]tkø (2QFÈÎnùb@ø$¡}t-‰Ž¯PF¦ˆ…I¾?Vc’èîð<Tâ aƒj„Ø={„-ŽJeëí4ãaè¶Gôªß@`@W‡?Ù1(¤îÛ!}ñ­P)™Ò‘²i«gI@…IÐÛõGÕ8“÷Ðäû# bjÞóì÷u™›7Σnþ=ks“ø*°yä·óeB%%î’š‹þ¾½$_ †ÔW°¯ã/ Ö¼%´å¸É«Cêâ†8ÉpZÏ!ÕšSç=gsú~;¤(†ìqE"hvRdfÒè}BЇçáC¦Á®jygì= ‘åF㋃ ‹À`µºþ‚÷fº yÚ¼A·?ޘ˹ðà.²ì>Ž¼ú#ïNò5t`úmªÞ(Eê‰Ø˜gêÍä M\{ttò¶GqB* ÏÚ ¿ÎaøB)„òÄS’g"(Úø«çyÕÃE"oÒqɳÇ9.+G眊gÎD]ùýhþß ùeÆbxÔ¢A¼¶¿o@þÁ~Ùtã°ŸÐX7Ÿ§ÏFaó˜&ö"ò£¥£™›tù3?C1d/Õ¶bÒw
+;±²eNÃ*.u6 D<Ìð~´ É _•°Nè~èS’P (WÑ=†ûUô‚ÜÄv³¥‰ôBeQùª ¥lŽy¿ÖöNâ
+iZä jÔOæÌ‹›ŸÄ
+Äèž™q–¹}k6(>U³ø²ÅSrI*»ê
+òQÞjXŒ°Û\οºÑ»·ªzá#ê Æpîã;ÿ:W_®SúÔº¨ ËÑçFç¿Å:ƒú1.Ä€+,Ÿs€#ÿ×¢ÚJ“ ±&"¡±ŸxIç EÊär]O…ªÜrض&:òŒjEù.t­Hʘï$ˤRU›• ‘ ƒ€Ö½Ÿ dÐCb–Ü›Ñ(ìw5¦ÈÐÊp@¿ß€æ®I×؆È*ÆJ$QwžgÂ)5ÿŒÚ[ÝR…zÞE¢R¶æ“R_ YÛ'>H
+Û†«OñÝduY% žªÀÅr°kˆOö(­ÃHf'(«7ÁÞ4뛦ÿç4P
+—è<lv¤jñƒ2ŒDÎîÊ¢BŽ¢ñÌùÉ‘•J˜¤”NOÄ0äIN;GFy{e:µèùø$BTéÒÒúŽLnÄ™_‚à‘:o$¡©¨ce!pNN²mÝÓQI„l=„²1ÉqcÊfJ¹)zöÝi yÿ@(æ…™À¬‰ÿŠZ¯;Oƒ?R¯‚¸º;•Cè§Î ¤LAoÕÓ:¯ï·Â0ZFˆ!Œ«{ÎàøÇF4ê>–Èq¹Q›
+˜ïÎAS ÔuMÛ±ðed Öê4!|G« 2¿%=¯Z¢ÙŠsÇO@Q÷ʼn ùíÇ ¶0dó)E ûtAlsÔ*èº5y™Ç*³ È!¢b2É2k¨Kk3£µGØ¡ j¦­’]ÈÌ…Ôñ„"ŠÊàòwÇ4Îã¶bÌ;‹Î#· áòüZE7Bv ëK‘Ùc³Ö­¸ç$NSˆºøO<Ù!0ôÁú„ ¨]e°éÄ‹ÒPlíšm#IŒÈ$»ki0‹îú«úuûãe’G®Ñè<AæaÍ-o¡-uÿm?
+Ha¯»Ü{®ÂÖD¬;H¶ûmWjXìè¬G†àeIƒ/a-%®Lu鎌 Bh”sŸ´¹øJˆgl¡êZ†{Žh—ýC¨dÞ×@Ðr€zKL/FmÀ÷õˆâ¥8@¨6„…þ.È­Ää©UûªÈ¨O9ê}ÕåkPß(Q‚ Ëp¥TA2ão-Þ7]ksÙ ¯Â}UX ØévêYºvÜ9ç:7Î×\çÏyÕ}ŽoÅñ¶áRâ·JÖ$*f˜°³»I›™¶ÑÆ}V.èbûç`rÆ‹[ÆÁö£ü Ã;·öf€ßŒè0A»‡ãô­½˜åŠA&Mƒ
+´Ö8¢_êò¬…ŒÇ!'‘CZÏÒ!85þ0SÏ/#VöË1$žO8¼óY/§ 1Ì+¿÷ÎqÚ
+þ¤GJ”°O³®gÉÑ9ʳ™Fk¸{†‰o\_•’Ù¬¥Æí‚X)Ø›ã°ìn RÂ+Œ´Ch§xŠ› Y=Ož,‡ƒ#uÏaÚs“ÄÁîoi‘¢2Û
+;£QΦaÎÑT€k„˜Ñ²—¬HÝ´Ô®Òœ"ÅОvsnAqX~žšó‡7설{B*ÔŒÑÔá„–´¯ú÷b™ÝK,w!ÏB$‹âÛ=@­qo =-ý¿P
+‹xþ æÓß‹Bÿraz0B£¼Ø „,ŠÇxLõÏááJ-`Íó1ZþŒ µ¤CH],×Ï8³Õò °p6–,Eö ÓçoÖÕ´T𾃣 ‡Bø\5ª›
+Y ÂœNêNKǪ2 +kÉ°kï dÖ›H‹´¡._ör˜ŠÇW—•ßq1·J‚ˆ¥¶:w” À}°/a½Àúàg†ÆsºÒUP%¥8ô8¼I#¯“Iž¨ºçÔ¦6†XÓ6\!ecMTrîÕÑãÏ_È©Gg”Š!dÈ_UúrØŽëØ~ôKù¨: ïw¶çëغ âY»«ÏÁù³1ÈiÔµhÁ¤Ñ–ªI¾ƒaÅÙÊ]ùt.„¥h¦ qä׈þÇ \#  ³Yåd÷°-¥Ð´{‚˜‹U«cœ aÓH,NÌ PhT]Ú#ó2ÿHPˆÖ¹;¨>ØD ÷±VïøÀ’ÀM©Ez}[}`Ü©Ïlrù „ùÄ¡M h ꈮ6¼Y/!ó˜Ud² ƒÄ
+u‡®ÿú‚3½… °|oÄ“ñòÙ *mQ$(e÷ó
+Ahs âSœÅÞÅ2IŠ<:r!:‰Œ0!ï«î B\²ÕA™Rö;ÅÖÔ_sIÞe0ˆ>õëq@oL¢®‹]ž‡GÒäÈFz¹3I 鶘¢œhzÁFùó¸;º*ãÄas²g,þ¬ù€.¢¾ž2x¶KŠ-#f„ºÝRŽÀåê£uDÖ˜e\tß7áã`ÜŠp…¶‡Ç
+$ĪSö¿KÑlyå³8½Ð©2xµUǼ«–e3aa¶`û¬Š/ß$-d¬ö$¢9ù‹Ù{ANÐ× P`"ù‘“ã
+Œw>„A‚uB@¶£ŠØåRÚ–GbS3(´AäÏHzP\ß6²@ç31ë›ÄðCŒ5ï|•Ì/QòÆD¯·OD"Uvj!œ¬8¡E„=©o~\p,Ê(nE©G/ŽaúÓ‰0´}»*î²_Ƹ|=OÆÖãz«B¥UËY˜ ebBÐdÀ)2ü‚àbÐøÓý1¦ S@ðq!t*ƨDGQÍJhŒÑX$A.²9 oÄeب‘§vbÏz5&`‰âî8µ„Ý‘£YÖŽg^íý抬ÉçÖ*“¸ŸŽ¡¥:¬
+½@R²¹`Q妽,}Ùù©šUéõr8›/„NŽÉ|Š(«›±óPù•Í'ø#þH>9Æ57,=&ç9ÜPÅÜÀû3=D?T‰j;6/*¿?œ!¬)0ñ´ý¨Ö¡2’þÅ Óîxbå0%×£¿”°
+óœ‘2ñ§»ÊêikvGgƒK š æ¿ÚÕÙ i,CË3?¼K‹Þ¡AºQ÷M?LáV¢)åbø±Å`+” ¤!=ùã‚œ:cê™q±y²wARÛXº¸>c=¾ÜëÞ—¸/Àâek¬ªú4Íf)…@þ†l‚ãÙvN‚`„ðTLΞ-ìS†\„öJáí·½ŒBÄ!éäMhÓŽ®sd5P<hú¤îÁ®4ëAØRøŒIȺ
+;ÈH Z1öç(jY¾¹Ä HÁ
+SzPüðZqa×ÏÕ/H (@-z§E}Ž…ÙŸ(ÝÎÊdò5ÔxÚ]„"„Znã@ž<õ›Y)C-®/’
+!õÆË¡£kU±€€ÖÚçèŸ+#I»†£È‰d{óD8w–³ÍúG $¸.²¬kاÈìÓën¯¤‰Çø²a'^Ø0’t2ÊÎa½°›$Ÿ³sh˜É*"µ”=
+ñE¼
+_KŠ]2ÑЕA”iÚ4³6êº6ˆ–·³ÄÈãå»fèå†hãÇ (áƒ<¡ã™ƒ0ðàíУ›LEb¢—,q¡‚ØÆóöåd”†ß†sø/JV›BB\Øèò™)Š>_Iõ‡);›
+E‹%óPôú‹’oRã;þ\$]€!+щnƒÏ‚;ˆ¢)Ò’61+,¥W-T¦‹,ÂïÊ|u¬Ú “öLÇUvܪ§›9`“º¥9× Ñ!ßÇîÕ½}œ…C§”ŽñPf‡;*p)¢
+ÃíXÀävZ! @–B:J®õ€~‚–®^Í […ff0öÅTj«ä+8‰›^¿“˜ ži€¤SÐZÅÓîí‹ÇeZV­áLa¼À}‰–£ÀÖ¶ÎËñ.ÙVST+‰&‡lQ-ÖÎK´lKKv%´Ÿ‚:ÁÝvJ¡Á
+yuÆQINI~…½‰Q ú“´ ì* {”ð¦ ,›Î óµD`*
+g u@UK¾*J
+2ê°L!~.õA"¸”ü1\ ¸YÂw¤ïé;õ å†ßûÜõˆ¹.?Îa
+8CVó+©°x1YöáXù5 ½ÅÃÉküidUûNÑŽ²„³œöÁ8U ›Üè
+wð
+=ÏEû÷ù“%ý`—óïÿý
+|à‡!6
+'°p»°Œ=|È«™-Êücš¨ï~„4j‰·åIJbÝW³€žËK]dî6÷‹\1|5ûǬ^È.1¦Å
+Žð˜ÜE–>éB"è уÆE0kË ¨W,8r,ãøQ[0HãE
+9NþÎwŒ+‘Zîl…aühû2YPÇÄóÚ=Ä)•t N¡lÌØDžB¬“å6ÏP,s­q)qP(©
+´d“ÛwŒ¿’è'ÊÞEIOx ބɶ’Îõ±€ëDÄ5Ôä&„õ8ŠÂÔú5φwq+ƽøQH ;Ä–cÀ!˜D”ZÀƒf ukE-á¡DÁ |¶
+£wñíÊŸV„»ÖápL´\ËĶ…V±»Ž†ì`½òß?yôýK’¡"Mæ– ~Ón=hF¹˜Z6‹L$^Ë—¢O+Âþw:€ –y)RÉ*d(¿ "üEB†Š•ƒjž ýÕLAh²dÞ¹—öÛ%…x4ëQð•*)Y@¢ð‹—$~ @NïøÀ1;MÈOz.¢› Ö¨Ò0û‚\ÃO#.–7qâ‰M9e‘e¦ld7dp†Ì…Õ-–kBŠ!Ð4(2|ûŽø4‘H‹ÙKdµ*üCºò£Š’*ôؼ}ï×™?}þ²u·²¦yU³±(£áç¹è;>ìý¯N\¨
+»—"bFV2W¢˜ÕÉò]»¬´F†üò©È
+¡ùŽžxï+ì.ÔQÆ•|‘¤Ñ1ld²”â(‰±¾Â¢ÅÀ iá¨r‰~Ÿ€„p‚í„”‡DľqnãÊ,æôò( ÷Ë€†9q!üR<D),
+îÖäSkÍ/J–Bû8Ý_ô/ø~‰Ú’s“.ÜãQÚÍuà·%Qÿ{¯ÉrÍ€Oôo—bõXÚ¦¤T
+‡3½Z1³ÅJ:4•”{.s
+̃Ð×¢XâWÆÞdqáåd ÊÇ”Y]bƒ«(8$ó¡jQ´Œå¾RËYcØJÜÈxSÏÌUôt¾õ“š—õûüÉŽ~ÙƱ`Ñ%Ÿƒ<$÷s¼„$<mß¾‘¢ÉvtgÕÚ‚"•4™fõ‰¬æ%òãpâÀaì+8Í`™³Ô€ ¡¿2ê \ME80‹{öû`õ" ž•")ù€Gûcâsø‰ ûô‘¤¹’s ™;ºÛf:Ëú,ꤔW(†©KúqJ;·+x}î¢ÌÆMÞêÝ‹XM½]Š*rm³–û-‚Ò˜<µ“´v ɤ(ÂÒF§h–™ÍFßê܈¥÷A’‘Õ®æI. !–’*á
+'µžÙ-Ô‰ª—ÀýMÁÍbªêYÄÇ™ /K•Œ¬+à Ý|XüiU‡ôVpü@IçöýÐŒû*`¾Üø%·èX?úSÔæ¾Ïû èÿ¨ã ÿ
+ê?ë‡.`$>JÙ?Rã²2¯¾$GbìZÊ‘etŠO^´ÎnjV„¤ìi‡› ßZU*V6õ¿ù!ôh­¬Áù†œ^Šþ~SÄ ‚4±N[ žER0 qÞí0j'-觚+XWtãžÎ¥™‹²®× åY[;/;Áð<—€ Wßî[ä‘;×·غÑfÜø7›»„så»`ƒÚƒ’3 ZlI߇oÂs¦||ÂF½%•ö°O°Êá/)G
+7„ÓL8³A,cƺr¼QgòSÚ#¡÷‚o@úÊô`¾Âzh@•‚™ä”ÅÅXg×Ew™·¨ƒ™îE^Z—ÖFP¢OaHpoEÖ°Z Ï!ÃL10½Àëyè‚X™‰1Û%¤†©Ø8Ó!×.CY¡¸ºaüAQ“cg•šìY×ÐÂ".Ò$ݳÉ!é>‚+”‡—pÀ*hNÙ˜Q÷Ëå¬+ É÷3ÌÚ!˜Ãü嬿–«œ}9ªrž}Ÿ#Å×BFd蘃PÈwIþ-4†{XD6R„ðÿæœ×‘?nó„Nðª'_›óÄñ£ÃQÉ·Iýóƒùû&[*Ñ“9å¿=8îß7EòxØ
+Ì(,«Çï¼3
+>Í Vñ/ýa9·å5UšZµn=Ð í0’4C f,JØEŒ
+ùÍöâÐd®×À·¨Ïy€y¾ÌnŒŠh%Td ó¾¡M .NÁýí¦Ô±´Ò½.dˆd¤ b¨
+sFG((È6®¸íi¾–°ºàtRröY9 7ùþ•%Í€5Úé
+9…)7áóH oæR06ºÿŸñ2É$É¡è ê:`ó°V/óڪ÷iôD§;¨. :@¹™‘Ÿ(—é@Ô5 6íb½6ø~A‘’sù¡«¡¼– kˆƒÒBû«^~]á³oÚ°ªìP¾„¡³¨ºõ:ö˜"†É¥–4oE*aø8¨3ÑK`
+Ûó.7 7ðež1NÑÀck«ùZµï â´}ÙŠž’Õð;„2.—Üôìõ,‚8YI^ÆCì;]ÒÊÛ¸LŽ–±@È&^*QÀ†¬æ¡ˆ¡÷-«½%î~Ôd¹øŒ8;¤ñôô§¨Íݾ£à¤%€@ê þÊ_¿CaúÄïm½—ѺGa»ˆ9S›ÍPR·S€¯"`b1!sÃààSl>”sJ*ƒµ_¤Úu (!!D•¶Ý”'F^•¼pëê¥O4†qï/Â4’fÙëD¸ZŸôÂÿ d̆ÍG·ë [e!”11{¡­¢„i‰Ëõ¸Ëä òŒCƒ·•`ñ*“§^æ¬fYw†¶»ï“…LJB€D‚rE( WiɇJÔËÆîµÎ,ˆ‹  í¤¨¢ °/„8²Ÿt/ê$<š
+…@<˜)sí”é+9è¼—¡Õž=AÐçÒ¤JB!tÕSB±€M„t‚Úp ¾V`ãü(¬t‰¡É£M6S›JhDD¨L«ÃØ¢Ð؈P”Ùº,•—½º}‡I¸8iÉ4¸¡=¬”ì³Up·%µ"Žþ(€ž–^ÕÛïù“ÄnnÅ`1û¤}µXäUà}Þ–0ªœ‰7³DÓ¿ÎΈ‘k Š~Â"ã«K¿ôìpGM S2%“äaÉLÞ?(¦ÊhàüéÐX%å·ïnú ãUÏËYQ,èïž`ÖcTuú¼|öj ¿ÏIØ%R$Âiëj²¹^@Z´FV4P¶!“•phîA§¥0IÈ©ði¿Õ8ÈÐiH4 $ ó › @!û]¤N¸µ1„bJˆ`–ÈR9v‡»íhd&¦˜›KŸüÄΰçûÇA™ë%øýµ‹™úkPô‰U“ó-a ˜(‡!á/ÅÙâ^„+‚”’v‘¹àƒpf#<®ËDZöI¦ Ô[ŽMü'ÿ@M—ÌРss+ØJúêò “påsº¹
+‹þ_aÞ‘á_(6`üÄ3‘8à¦y±È™
+yHÝ2
+7bn×–x”yåYÆ¥x…úPÉÒÌø)-Œõ)eßÚ®RÖ ü @„L8>È!€ú°|8di°~e?)6 §„­.ô‡yº³ÈÖ´.5éÎÌo€1Údo=kPTe»ÊFÕ¹÷i…Ç2±íá}Ý ]oVÁP`F:qá=®RÓ×DÉôºæ„ÊJÂE
+yˆ ¢Y’”äUî-(E0BkÅ’+HØŠ çI)§‰(í°fÞ 9êÛI••`·3ƒ$ìåÜŸæˆM¬$³– ¤A«Þd¤h•$'ÑÇ)J¨€£ib(J°½I´€'Îô”ä…q˱y2qŒÍQÉŽü Nõ#üNV/Èš9e¿r*Ö~pÊ”cBaÂz*°{+cn7 €§“UŽ ËŸ#ž `ìü­ DK³K5ú\=¼\Ç!˜P™1K–1«…vávò³æ笌l7ÝË
+IÌÑ.{•b¦šÉmw|'ëÈxÙ+ R;p}=œPÔx šÔóÕb„Ø—— 5Ä8d"˯0(é9d,¤lZL4
+ŸGA88¿Ê íå/'V ½ðTºh@‰@WMçåÐ<>VÜP¸
+¶ïyÜ[E7>wëVs˜E²ŽDbñACA-Ï¢àR˜þˆæB¤}¿]4êyÜ[E¿DE7‚QZÈl¬Ëh!Á˜Ea{‹²O}A0æ†%^!Áà†0\H¹ìE™AÞ%P+‘V~[s‚¡r"‰öPP)ÁåzlL æ9‰€a(J“ñ­¯ Ã}p£3†¨†ë$Ÿ»qz·Ô¾Ææ¢ÄÐCÄA§Ç²$S?a­_|‡Ü¤WÊDÎaðë¹ÊÎºÊ ‚Ál༰èŒø:éF0 šç²ü^1¿zyÔ<¡^qPͯÜf½]¬ßã´wjnù+kˆ\òÇÿ¸ö
+¤&†2òù^§ÝèÎù¿„5ø6ì(˜êJ:”Ì4PDþíËE¾ÞÑP¬Â¯$“+lœeçŽ
+*Mª„ Aû¨G2»Ùðd$Etüú'*z¦‚°ˆ‹°ëJ}¥Ùad!öŸ½†›?"F”x8«UtünœŒwVY‚]‰­$Ÿ:‡¿ç›4'œ"øS
+1k—¢//š81³õç^= ÁygÇFÿ³=ÞgI‡[våœ<ÛyÆR3 áø’eFgž´ìÜ|ð7cŒ 8ΣgGԼɀËL,]ú|Ï à‹Î‡ì ¿Í/ë”Oe»„¥ÂqÆL4¸XdZ c¬ÙÚòJª­ðÕK*œìãxô"
+ÞÚ]ÌN¼)rÔCï@³ÖȲñoJºt—¬‚òõ¼ì=ŸE/,÷õ¦•E0Z— ú¸™¦ât–ÍÝæõêp7vˆ¬ r4ùµƒ¢p ÛûÅ˧Lƒ¬–Ô¯ÂÎ ³C:,ý¦2\•<Y«çë2Ìÿ&<r¸r„±%8AíÛ§“ÔŠ«f)Öò+‘$²íg©°<5`¢÷¦Ãò(É6¿ ìغÃd÷Ûà}ðˆ®5E{Íç¿}}»QF³¥,5 ¥M93‹°áÐø€‚vÒ‰i@ïH‹ØñòàÑå$-Ä•kBüê„f¶ìiþK4 lxJÆøfïy±”Õx²¸»r8Ë”æãkG‰xˆY ŽŠØ_€¸¸wJ è-½h`TÞŽÞ”¾W”ƒ¶#V¦Æ;
+µœæœ9O
+“E'àí²m™ÊOÜÖ3à>Ö¦&yŽl%EÁ
+*’!䪿)ÄX¦.göE›’J0äÃI’;M9´¹ƒ™TLHÒ5»•P!á¤éAnÐ!Ÿ,z•æ:–„ñÙÖÍs³efÃèñ°:Ç0A Ÿ%½fVï0c{Í ZáÙe8W€BìÜ´QÇh=åºm&&}b±Þ˜&(îâð|6`©1B…8œO–TÏ<ŒK4ºëÈrªo³ôêÉ–Y\® '\èœq¼)áþ3Ô#8=‹pÐ/sÄ2ÅX&±ðgÕ«±HŸmBż <q°ATM>4n…}£sSHªáo–žüO×zfjZn‹Ó¼Æ8J˜UEJÐ÷=ÚP¡fLïp_lñHªa«+Ép8ÔWGºœ@ÎjüŠÄysU¦µå@:´ÑÝ4c+Œ$â©ÑÙJ¤Ñç$²-g+ AQ^<[A‘hOÆ&G¨”HËþ‡E‘“Ï0ñV±Çš21º%ÐþXQ œ¢†;arv¾–tº@[Ro¾Û­ˆV±©£Üj¾n5Ú
+¥%íQ*)ìÂ%@œ— ì-hsX%¦tÉ!ì¿­-)€GVÙyN±nø¶
+šíjY‡ÁÓâÆòWëËk¢”SrÅ>n‚7ÈMŠ~W;êµäň˯ÿõ¯oéãÿùö×=!1t¼³¹Î_,XCM¼ûóZ„õ”ã’U2þÃb]ĺ<ýüã¢&
+8œ›ný¸îö'5L^§]s“¯"n=‹ q½ûåÄ­_¢ ˜òªL4£çQ wÜ–½°äUMiEÜô™ûRêEô[Ž‰ÀÑ|«)åguxoF ßD\¯’mÖ­Ø=Ÿÿ¶&Ÿß˜·z]æìT‚—ƒpx.·wg`¨YvIÙ¿ûcaÒ°õPJ-^´Ö$‰ÊNo2çaœ!A ;c3@,rã2‡eÑÉüòI²1R ›¤¹ä
+Æ©©¸¡GzYFN: B¤Wܬ®0 dÕ
+ÃQV¢k>ëÆeõˆ •Ì›hV¢_o ø(K_“¡c
+ ©¨l{ Èã$mêSe‚I(Œ66¯¡|
+¦c+°ˆ"Ÿ.³Xy€ ~#W! T×IBoHú+ŸëHªé‰ø O­ÑÃÐÔ,rVxƒÍÍõhçÖœwá£ñCGU‘ÿŠ{Óoh:É(Û:ü7.IÂèOöÚïJzmHç?ã
+ÇÀóš¦l 0Šu¹RÆÇ3ú|`§[Ñχ"˜!áA2dœ;yE OùºÌ?”:"³K$š½\…å§S lŸ o±Š-ãyMåÉ —2vÇ`‹ÄßR¸8>˾lk$XË(l%‰^ЊÀR®ö@)U6LNÉFråë,r3ŸÎÉ”¢-8ÆK¼ W*D›sõ(\VÝöªÂ¸1üµ47
+£;ƒXI(Dè÷JLúŽ0 šo#e#bRÏüC šBäJ¨‡e¹ˆEBØÇNÑÛC={ø;ºUWâ])•½ç™ßòÒ„úëNêÀ˜hË4¼—ÔÒPPn]†»yK[²_€Ç(Qº®”…ÎQòýrô™ìK¬T­`¶½šÌM+ã£tåOÌG°IL¢\:x’ bÝÚG DŠ¹N²Z«d fÂA;%æ1˜g“5èç@ý0ú²"h‡Y1°3 –}Uh‡±W˜Ô$‰QåiL|çFŒ3­÷Zû018Û¤Ì:W(ÌM÷Ň«Ã|c`ŠéëÌn  à}¹@üݯ®Šò{Ð)²¿|¡ŠºŽ^™áC°P GOàÉx›ßVTþ„´JX´2pØ Sšõ©"®û8E·xò¹ ˧~ûÑþãï—oÿ¾|hš¸þú„gÌSÒl"K¿~Ä!è‡^šV™—%‘w4B‡
+ªˆqH~­¬ $F?~;˜•é$óîÜÀ+:®‰˜ð`6cTe·öå¢ô˜%Y•‰üÏ}©%‚Ç Ám_\’ÁC£…ê&
+®ÕKë¡©STq(,Tž÷Áɲ‚h…§¨ÙEðÁbÆùЂ{)zfðfþö…Ñ]ùü.d©DSÑJyh⺦ì1e‘I#³ª}*é`¾XH#Óœ†¶¤±hX„Uƒñn²ð%ÙŠ±§,Jð’À–FÄŽ„ÃÄÌ>E: á°"еJ2É!×XÞQÏŠ2=ìÉ»OÍeZÖ5}*Â%LçŸp0¢X>Èvš5Â!³qXµÀ^®‚/Bƒ…—žðˆ“€w¼ø5±¡™8EKY3;‹êwéFR¢éì¤J:> Hƒiâ.a˜(t(¡R ~1Óß-“¦Å2ðÜÚíå€uö‚ ÝDg #$&ƒÝTɲ&ØMˆé’·ÿûƒÕä$«„Žµ]Ÿ±†Å°>`¡—‡sî#¿ßÆÎù*‚÷î8@¾÷Ø]ˆ³úë+[óÓ¢R‹âvÀ€!W.uÎûåUÀ)–C~°ƒ¯*A@ˆyøíp¹1ùâg ”uuLjU<ú4MÅæs+øXÀ®ÞgTD‘¡07è
+ÒP¡î=œõZÞî™
+%ö”˜YI ºøBIw$}`XBt…’l ìÈózžÀÅFl'¹<%Eò3*"Èùçt~9lRJÑJJ¸:‹+RÛ3;„Ò­¹ ¥Stx_ÏJJ¯—–Þ¤€Gñ‡4èA()âò¤ÝŒÏÕ•¦†àòÚB¶©¹yG yBhœuQî](5¬*Ofbî9çÈÛœÐq^uBðèÎ ä£ÇÞBBùéÖ¼ %ùo¬æâýI(Ï¢C(%lŠÆÿ\¡Äcéi}¨OBI—`ý ‹+”9BI ¼+]éÊ`žÂ9³?•’"ü\©"‘]¥¢¹h.|ÝUJJêâqé^q•’†Q5|Dò”J$%°LÐMÃSJ•àŠ§hC}p•Ò-º+¥StWJ]¹ 9Ò¯9=¥Ô»G'¨IƃRª´)BŽØçè)¥¦ÀM
+×]}óÈò®“„0„”öâ-d1·¢m³Ý…ò?
+H‰Œ—Kr&7„O ;ü˜
+âEkÏÒ·pĬäûoçC‘Ç´Š˽p?R,ÈL$"^]üš-g9›ú|ýËt^6Ô‡yDfýõQ ïÞE=ÿ/и²‹ÍÙ¬{Ìûƒ m¡sA\šÿäâcCî?[ó¡é×ã;SUö§ž éÃfLnþúóã?òú7P½Æh&£µ1†lèT×tŸîñúûŠ+
+$Êÿ„Õ6¦šXAä:8Rrhö¤>%—‰g¿xÛ7ç´Ö©a϶o3Æœœ==R€4:ßhÎ6WÇâRí48dD÷×'Р|ô£©š½>o—‘чN‹±8ÔÌGŸÞÍtÝÇÚðáÂ"DÃ'4šµŸî"a=Z“dUNA²žn"Çsž˜W¼÷ÉoÃŽ ݯwÁiÑý©¯Ä¿OïÍÝ_'j
+(I·gïã éœ* “{t{èx\”o7åí
+.¬ÍÒaß>ÏƈˆÓô¦üTR´Y_ñèÅh»ÜÂv&Ú‚Æ ó7zC$ l4þ~ÃD1:Û¾ú¤®~¿÷Æ ÐÃ[zÛœ/„ Û_’ûò)'ón|ú¨çCg=Aç]£õÞÿ}wN³ò,AÚ÷mø™¨öEy
+¬–#”}TiiMù±±)_„aTÂAaP Oúó£·¤\j0Š/yþ$ˆ2\Dd:(ìG ²d¥ú · yáVÞ˜v{oR ¶*äÕ´Þ(xAŒoµ@=Z=<6ã dµÝ§AËRÝñ˜‘Ò©­BÅÜ·Q œç±† ÷*P_¼çQˆ™ô„{÷§Š©)S(‹šn#›Ý§
+Hü:ñ=a< æÓ¸§ÓI7XNéÈlêÄU:ì­_Ø3Â-r #/,5yÊ@:½4¨j˜ÜTj†<AÅy}qDˆR ì-ë\ǹø"‘Ph*<¨¥@Ÿ?¹Óºz»J>T³ÜEWßRh";½í£@ˆƒƒ²ÛbÐ
+€õ\–ÍN0™nïö
+ÝÓÆç°¾†ã#z¤q⬉ 0TOt¤+ ;#¶ŠdíxJŸZ¥–|«£ .ÜG=Ç ÉágžÇj3¼À¨4Ó„B±kX›”Úýx™
+05¿¡«EÿæQLZìQðDNÓã9Az@í˜0>´¯lÕÑ
+k²
+EWRfv
+ôF¤.›îÌvš~[“í‡FIPmŸ31Dø‡âlа6« ´õ8ÒôÔÎÝõ*Q¡@ÆM‘RZà‘3÷—2²²âí q§Úø›än¸7Ä(MÏÅv(NÕÎe¼[—Fm&£•5µ¢¿ )=ø„—3yÍ o +!jãÓì7ÕÍè7‹û<‚Ð#4K#ÖÓ¿^Ã¥P¼Šåóøtl›sm+¡ì§-!4À<H×
+£VŠT–,q‰ËA¾µÉ?uñÒ~eTÿÔí60C®UZãáUïŒ@x¹ù§^«Ã
+…¦ä¶ØÒbMm"S¾¨CŽ VZU ’×N$°:(ÉwBaUˆ&ñ—[O'½¾ª/èó'™Ù‘rá!Äß[Vì8èÛ9°8½”yËŒ˜_fraéââ-´
+ðçÏ‘¥fP=™dïe¨Hº.
+ϲj¯³ÕgWl*Vqµz™Í\RÐ^”S€¬$‹Ÿd.³™É>8³µ½[h%S+»‹s½Ÿâ,™hÙ_kþcè×Yô—® ’{“[©úëq0dPY ‰…Çt–¯ÁèÀ›5r@øi4yù)n.F\ÿÁ¦Áà[Ý{šè':œ§•¯Ë}bÜH½õËÞ}¯0?`ç1r;§ìvž:
+(¿isqÇ-g÷&V¸›‡žoƒø[­Þpv¶¹
+œ0yL?&?N´KéÀJxÕÉD+–¯0„È·A/¼üùyÿÇÏq/°D‘ÌÀý5â‚ÝdmW'³Ë_VùjW¾H•ÒO´È.lŸ¡°‚ôµœv$Y
+¼s! ÷¯kleÝF|Úv“ŒXÃ½éˆ þ•Cñœ™e™iYÄ ­ôá»ð÷2ËÖ2*ùQ¬¢ç
+ˇµ%séx“®9•AÅ%ø¢ËíA!j(LÌ""͇wÔ=l«XKðó>bs6\ìýëG "°rËÂœ©¡ŠdÁXr\`_Ñ•_Òlôt( ÿµq}°Ø©òk 1EÚ0
+{] ElÑÌûƒìýC>-IMÊ!êÏZôTüÎ[Ö ¤l"aˆ®I>Wû0‹µÄxü‰WE@@é…]Ù†÷0iûËåÿ˜}F×Ù÷IïøT½»Æb# :¶ÂÎi–lr’á:͢ƊC—4H&* Hz¦Ã’ã'N,£ŽÄ¸Ã€MF7ù¦{Ï{CÞ¯ Å~BðÁóñ±ý˜Êƒ°šƒâƒ (Ç“p@~
+ô¼ÈCþhþ©¤Á¦Lovò¯i(Ç!º1”HP@¥Å'Î9„R$Ó™ªuÕÆ;\Ìu³!ˆÞ@”
+WÂp“#±"jµiçPË“ëàä-«®K½Ö¤à=6\B ‹êô’ìUI3S¸èQ‚ØU¡uÊGiZeÚ®˜ZÔ°‚óê±ÿ¬<’תëÇf)Y8qŸ.@™Ywƒ‘W(U<
+Cç4àâH-܆£ŽK/ B½—Xƒc³XSå…øcņÙàŽ‹j9 ³KÖó¥…$.¸C¦/àÈ‚a`-cFǨMlW’[/íù|€ðÿeC}ï³s{°ß°ìXÉíã
+t75Ÿø‡&²žÓ?õ@ûäØÖæAEs£Ÿsøú
+T>Ð(Ì]{€ çFJžOÝA´›Çc>';þÒ@„ÌC
+ÿ"TˆæÌçÝ(5fßQ<wQ顨
+û6ÿŒÔ‘†Aëüx‘ÖJ› søË:¹_j- UbxÚ‹*íô”Í åHæŸi‹3lf»·ìÀ•'¢÷íTMl3É:Üfû£4Q–™J»ÔE‹7åï/Tª¶ImïG]d C¸*{…ñ%k_dybHƒË‡bÅ1ŠäÊÔª(@ò'èó€0<|¹U¦ÎmNÑO_à¢qd¨’ßg7f’ö¸Õ277<qbåe¹éW•[Jx-$­z}`,F g¦˜˜Êy»°ŸßgñhÚ»4÷uÁ1|b#‹LR×¢ìÕ„ª£A[粫R% Ñkù²ˆ ÀSËÃ:Ü]æ‚
+¶ïT®Á1‡›à­!„Õõ—ŒDòëGº»:¬I†æýYï`îÛ|ì-Ð #Ä«õ:샫Yú¤’‚“èÔ²h
+¼‡ZÁ v`3–‡^Š´ÿé?—`–ý2ñ¾a…¥”$‹Û`1݈¯ÂÏa—ZêRyï ÌÀ“zà¸÷7ªxÓ9çQÔ”Ôjb £«Ô†ÅÇ¿pë‚ôX33ýÀϹ÷¥¼ÀØ^9³/ï® ¤ÓÛhÖX‰oEœ£!uÒn¾æñ,ðñWnÅZ?ÒÈŒ+µ=d|“'îîŠÐûÞ–hn­ýí&ý8 ‡MÃJÁɘ€³ù$ 9Iþ´]„üVôOXpÅó¸[ÑÏ?¹“¸"ýM)ðNC2EÜ')!w4cTͯÿ,[¼ì7¶s—`¬QgÌÀèOÇÆò_6còÂë#Üe)ð!¦;¸Q„&°í
+£ïåyÖ¬»\Å£mÿhL‚A·>YDͳâÉNCeó.ÁC/À›IÕK0õLtŸÁ„g›Û‡¢f¯AšlóÆÜ*F3l,ï²¹ÎIäZ Re3l KZY>ÔZPâkJ
+€ô¾~•ßA¢ˆ—üÎòùrr=ÒîôÉl|¾. ¹6üLÁr_lHæ¶BÓk e.˜jZæñ/ø`©vzŽr‡á’]¸‘êÁǯw\Ec›‘€~Nbs‰%DœêsÚ—XàɇÉIè7»í~Xivbá^ק9Y\wZ#V!Úåô$ѦæhA‰O“‹@ªEh…ßaàPžt¬À…~¨ÉfÙŽÉBX['° –êyú³èq\€E
+y+À'iÒ¾zåsÐoˆ}‡$#mVâ¦v¢{Övƒ,5õ øߦ¢-Ø.øJ7·"qÓÞ6ôp&1þ1¬d24[Œ?wQ~5±“4—E?ÿäN~u™ÄQ¤g½µþáêýE£é s+cÆW×ûø Ò(뇫ëV©.ØÙרèçŸÜɯ.¨}Âæ}³¿>ádzÒS‘/§B¾Î\Oû‚u)¸9U%8(4Øæ]Bf$ºñ¯"ìJÏzÉ¥ÌöÖ´[sG懚VR^ßUN+¤‘²K08;ŠÜ·¨DGáöäa³&yŒ¾ƒô¬> ö%Á ocð-Œ¬uŠ^…G™;¥ (µ†ÝA+&²£+óÛ"¾µ8ªx›”Ÿô,‚´uäÈî'=/C»‰jXÊ+|”a}ˆ0èÚ’cò£îÍ¡£¼‡Óå\ì+j±íƒ\%–Fu+qTÜG|çœÇmž
+Û‚é“I祴Á/¼>¯Âi¡£††k1É=_Ç*ùR— %°y”ûÏᘽN6èôFw!ï`´±ŠÃúš^‚£S–<ãTœáî bØÎR2}$’%¾­%ïïps´-¥~¼Ž½„5¢ ·“¥Dv—Æ+Æ)!ôñd…•C&D°†¹­“PèEä/Æ9µ"cG3à_‘üÊlbÇ1qÝ4ÒüPRÈ:˜õ¡~\GÝŠšß‡¬ ;ùQXqh§5/{ÒÈ;ä3Zä' Æ$ß9v:ܦ‚¤25¼3(âíÄè™ç›ú"|R ­ºÊ”’¿Ä‰ÓK H©™°÷]2§º «u+9èCšt¿”[T´WX8ŸYÝpr›Q÷ÈѼJ‰-× ’‚.«¤YóHS‰Žª/B
+ ‚½WÆ=&§TÀì&C²@JZÊ4§ÃsÒPbåLq œÉ^61…¤u/&°éˆôÞ%??”ààÂ’„\_oö¼‹h×·SÚ1”ÜÄûw vžÜ¥ÈÛ X‹2p'àâ{¿,Ë ³Ë °e«Á­n_Øo`i}ç:Ã’ròJ}{Šç0o%ŽȺÁ
+eûðfJ
+í:jnݬò—Óë-NWœðW±…½q]ÚvŽÊ2VbÃnBÖ›x¡bß8›°‘ÊrÎa K—!1ºdàô(/K€Šï7%t–•Ã]õ 8Á¤€h¤—À…Ë°`ýt–HÌu‰«ùîáG& ¸LaÊ‹ ‡"˜×xÕa¦
+ÄC’iŒp"—Éà
+‹ BlÌ¡T û0µšôm…þËÊ*©°Œ½Õ©º£_ÛêõM„;Ùž6/µØ0pK2¶|†vðgbø—¦Y÷Ý.áç€Ãtù©·…©6¹1óånßÁ/wÁXþ©Á@«Áf»bEi °™ûg8™L'7dÚœ h o‹…ª³hs‚ÃÀ<yrÈç(ìã– ½Òá
+õò^6ÿKHb4ï *D“#ÈkNn‹D­tJPN ‹
+‹v̪úBEÞ:4F…Löh,ÝÁIPV —ª˜ØD¦œŠV{éˆÂ'žB¬vOQê*UFPöá‡âè„C¶•,è‰&s©à̯‚MÌf%MC§Yí¸ÔøtÜy]á3¥›ßrIÎ"¬Ïà˜Ñæ¦Ä8*š$·»Oú»DD¦ë]#F»—従âÂýjáOätµàx³†é¶ñ¤
+'æ~Ú ‚s ®ÌñRr4¦Ì4ãö6!ÝAM:¼9c|½‹yBð>ü€®æCè«[Èjuǽ3›ùl„O(+Ëe¹Bß.09–—u%¡¬1Å¥žÈ:©uQœéC2^|GVŠ´Âêñ¢bóÌ6Rû{xÔL€¤Ifdj¾ \×æÓÛ3ªEÉ mÚEF
+1\rûÎxHÊdžâz–¼c'‚»jGùDsf´îùôõò(¢3Ö ¨çøK†·¤Sò‡Ü.Ž,¶Iµ’L؈þÔÿ:Hœ uAüáà<‰,”dW•ZÏIŸÖ… ìRÆz„üñ(.‚ñb}ÖP\3Ê2(€lù¬ñtv¬èœ#ž…
+\mÁ|‰ÆUÍ¢«-wˆ£-wÐ}Úƒ\ í¤¥ûYO0ûî‡=9Úò+јÒbä®ÖÐ~Ü–Œb²¶$-Öævׄð‹[\Õ”…æ„ 8¶VeWB½Z?SàÂÿ§BìJ¾ƒ4¼ €]z6S8Ô ¡kÖ…q³š^5wAV©Ã¾oëWä:¬ñ!LÜ×/èBêÌ+?" É·¤Ç Â¦6%ÌîP/\ àïÌC– „4¦múìí¯ 5ã± APb«Ô"´íž;„J°góä ¬¿Y…"K}&Úh«Mæö‡|†•%Eý˜1k³ŸH£VwîfÉ|Ÿs¡‡'å½ß‘æÓ:ŒøT
+µ`=줃;+R <HTÔ»;]@©©2N‘J|õá´¼2ËÅ’›íí1ˆ c¬½}˜mÐå´ æÇŠŠÈüûK eŒÆ›Ä¬?2.Ú¹ü‰Jòß¿¾TI\fZÄÝxÜ]Î5æH-øù„x¥*Àò›У)M–ãèíú•R'„–$1Œ±7G‚¿Ï£:Î6ijÛz ÓíƒXŽ ß/T¹­Éç'XÝ–ä»ÉK Œ™–F¼#tÔ0í]ì.ÀÿJ®,/ö0dîU:#®á&ŸŽÓûÛ“ 3;—Ž!#º¥é“€ª7ºå؃|jÔ:êbÿøT´‡ßüÛ4èÆëš¼Ó‹W‰¤¬¹Ø¼ºVç2ö^‰û,±3vý®úŒXqm÷õ+÷™¹]Å›½Û“¼¾”ÆcÂ¥À¿dÔW(Þ# _*6"®lîýGV€‰£°³¤ŠÁä•>–‡BȉQÅP$04ØIz£ÌxD=%ÜÅôÍn…_Šø®.ápŽ»‚~<¹“$(¼ýùŸ/üýX‡,È“³…˜IS<L…Ÿ`!°LCfB:ƒûçì ῾½
+Ü?-þéaðœTƈ†¬+{‹pÑ@J9©õ t9íǃ­{ß>uÝIºø`¬èµ¦Èrt@ß^€>qL Š8Wæ&2¿ºw}Þ#ÌÝÓp⬲80û¿ºú,§”Ð'õV[âÛ¿€æwN„×–c ”Nd¥ÚX­ñ@²R„´KËC0p®]„tAÄ"÷ñ³ ‰8lƒg!†A‹ƒoǵÊ‚€Õ)D¿!!‘͙ߑ®±líf ‚*w­É¬LãÆw•GÔ/ã­çQö>¥ÑB$PîÎI˜ÞÒpTo‚ðUæTÖÃ¥QжåùÑ„P%)5bSuYÞ™õ\lŹ di V…Ga…Æü1 „ÈÂÁ aETS#G›¢ë* àZÈ:ŠÚÑ Š?Žº~‡“ðšô
+ÚÌ’ìê˜üö3!tP~ œšÙ!-)„À ä¹c…ÈÃ{´7&›ß‰JhœCÉvÙ «ŒÎäu–(ªÊ¿ëûÁ~W¶ã!§W¡ÐòåŽ{,‚$ OÓ§ßOrÂø-öfoCà“B³XL €°ç1oKf™ÀŒ‰l–—ï(2¦Ñ^šIÆ»§Œ­fñÍïtVæ…‚äºùPz€[,/4݇h¸"V8¥Ý«;gd¼«4µ®\äz5¹ìä€/ï™e‘5Û^YS¨‹*D<ÌG¯"ë ™h+\È 2õÐ/Íú¿Æ×›À d…A,A=ÜQÐùq#`Ã>N*7S¤ ÑÚì'S<ê C‰ä4Ë}Ÿ„q ~V×Çg«VFc¤°ðJr ˜N\ÆͲ+3HyÞ"¾té*:i¶üÊË%·Î†Â+ȼ‚@oJcw˜]èÈÙÿ´ß)¹Wq€¶H\ú—Dž ˜
+*ø*6ÛÄÀo7BÆ
+ÓuÆÉð@ÿˆý H[d/ŽF¤¦Ò®u[Æ*gÔdk
+p3gsÊ!ÓŠyÅz—’ z”€ ¬8^|‰Ë ‹(ÑÏQt93ã¶#Šè„?&EL³Û…Ã5ð$0\”Ù¢óÆ°€qö£àY
+Þ ÈY—ÖÏAOE
+œJ|ð²h€¿s‹§±â“ѳÚã$Ô·³s˜"QB¡ˆÄ?}l!['7Ùã(¸ñ AvŒ‹ö
+
+ˆ/t{úeš‹ÞÙâ2ø"’Uâ¥ƻ4<Wj-^relyœþñt4åuáùóî‡Ø}J6--–UE÷ËŽh8a õÏóVò¯ÃZàA=2ÏÓg¨`h\á Ɔ7‰êTÞî8_Î1^Æ+â *öœÀZ9¯RÔN`Ìû;m ­øüW t¢Ë<‘Ìu—tðC!´HGoL`è3Ž‚ P˱Fõ<C>˪VjƒÂ¾Ëù¬Y\†=¡QtyöÐ„&x¼V¡)ùI„[ûEX MWõv'Š*ǽ[g?—ìÕFkèç9é„#nJ››@\
+V$ ´H  ªÖh˜X|¦hêðc8í´gÞaq®3n†ó îäNŤ5µZntŸÂ€@‡,“ÂḀk€Š„׸ úf=ͱiB„¦e3Žy-å]ŽØðeb_ŸÅ‹hmÎlñt[Å"Vz#³a—o
+<3ï‘£kœe¸‘jv©ýÄ@@Xд^|F¦ŠH?z¼ ŠÀ¬åNçú¦D*ƒîŒÓc@Ò·µ È:F»|a"é´.„¤é¾œ" 6„•ølZƒáRý˜ªGsÁ8zÄáœù§ð"•£0Jº¡ÝKŸW«²@ܱ§ãJMN­“ÃŒ"QÎßÝÝyvCÀµvêX~*–´ùÅþªqH”ƒ¿;»1+Ö._ù²0W á>c¿;™O‹’¥ëe†s¦5ÿ§¼\’½m(¼ï¡7ß Ç=í]¸Ê£xÿS‡
+s‰ùÄ^"rA’ù‘…£Äâó a_—’»%úøÎ|8ÉÓ,]ÐoÃ>&õi»DG-E ±â+èÍ©há+æ£C\¸“*+VÔbÁ*d¹?ÃF6¹L!_–ýVòFü?»a;QÒ&'hsïè­†­4…[÷³°À]cÂXÖѾ”€Á©n•6‡¢Š…ÀÒ ;–œè´@þ–k$ö‡]ýÜ^Z‹aí¸ö€@ÑD
+äXFŸˆ›ÒQ,‚ù•‘uà °µ­_Ó
+%ø¬]1þ%
+Ì%¶”<Øå²R¾TÄ’¾-ûG&š;}Nâ “ø0¬ˆW¡ŠX.ÜÕjzóss^Jü(ˆ–† ËÉMßÙ‡JªËzÆ/LÿNcý6h0|n”Ç>£•3©ìÆ *,qöÓdÔÌ7ÐPwœÆÄÿ†ïÿÈM¶'…1Ç"䳤 ÜSÒxÝ!OÉ°çr½…ûmš¼óÜä¼c‡@²{R¸ëF'ãĈԆîe7U¨:ùH?²ØQ¾GÃp:â“»'¥ˆ@ àɹÜp˜Y\©ŒäI áq²¿üÝn^›,ßÝ
+ëWÎËÁJ™hÚðï(Ðð8óT[:iŸxsÖ–¿ ‹‡Á@؃uÝ›OG ç`±Yï(Á‘ász‰·’Ÿ¿ýÁYåQ †k¹xú?)"Ù1&è.·ìRôëKQ–k
+`’ô»8òÕŒTƧè`v$ç¥ÀZIü¬Co_i:?…Ü×ú,Á·¡Š¨iÙ% ÿMBâ_.×ý}ï ôL3°íÜ›ÁÒš²¡t oÃD‡M?$ÞØ.Qš¤Wð¦–
+·¢_ÚfùÏ¢7®û¯cbÉß³ééWð˘f¿,¿ââÖæ·Â«è®ÐŽ”¾;‘ö§öölÜÄðWÌó>ÌúêDš<¢Üóù2,8(2ŒqîójE¹¢WVxM§äÕŠTÜ'6XÑ¡u)ñÕ¡5J]5zõ"úUåp³=ÝÓ«ÐP†` 
+³y³¼7X]¾“—UÙ"¤çË£ wÖ±H‘ŸS°ÅºÓáê*¹³äB”)Ç s4ÚηÓÒ£6yÀ@ÈèsT}ç[|ÅÜ
+Â5ÓþÏX-†
+÷»)aø0@ÇD‹q@ZJÞ(‡¢ù2ºaØ’,êªi'U*Œƒ´ÖÓ¾ \D¿íÜ¥šÒ,²ÝÏG>’ Ep MàE_
+ZcØÑyuè¦Ú—
+؉¹ñihþœôÏ&ã×ö"ü‘7e•ò÷8-óF‚]¥±Û‹ÜŠL¾5‘+1Û?v abÂü8à~ ´‰Õ),›­QëðŠœYÌ!—øû>
+Rx$_Ö%fº°n˜X~éG‰öÙf?ÚY–2_ÎoéQ‹Lu/Ϩ RÅ9Ý8 ËÝeÌëAù˶«‚u„”0Ï…ûP:dùS?€ ö¥ÑgYð+“ªÚÅ»êçQƒ”Î@#^R%ò>¢l xhòïÎQ%êSÓª/»Tè$Ò#»™Ñ“IÞ>C¦ãú°+NuÜØM%}2#ŠøÇ{|T˜QE³]^®^gÂx†W®ý#ŒéUܘá¬+çôEÒÒú&.tFż z·ÚL9D©'¿½Ð‰Jp/
+ªFºÁ·m­¶’ü¾Ä²—`õ“œg­Ao2õVáÐÕ®Ò'|ùL‡v+¤eç2Ú{Ýe-§GÜ"ÿJŠ–½D—oX®sîraÒ¬y¾ƒ\gÅ͉áÝ]Ó¾‚ò”cì¼ 犽£{$Øl°Xžaã·ö‚ßú¼L(¨îÀâi
+‹84¬BYjc -<G²;ê^*Ž eÉi(">®ŸA õ„¿(/—Ü8o Ÿ@wð |6ɵ²ô- d¥Ü›¯Èæ$óX9’jØd?ªªá¨RŽ5I"¨gôô=Poéƒndy§mïžhEúîßíÊÜ1¤ŠæhòÉ #‚¾*êXÎIÿEziÚš(kXwîo]]ãý))ç£Uï F‚Jö.§f<2Lm³£¡a(qcpÒp’™ìÏa£@Ãà0|l9Ã÷Haže¾W ëNˆF &B+yS»³Lz4Te&ÊÄ·å¡ S˜N)nÍÕ1±2 }[¨¡ôõÀÓ=38(©.P÷ ôkW©ãs¸‹Fƒä!Z«÷PÉJ/âÂe <lž¬ŒG2~±DÙrÇ@‚4šôx1
+ƒ2<‰Þ“j0º«áPhQ­]Qgå‘‘GVÝi7k„ ÓÁOªÖˆÊA¥´XàÂoÌs¤bøD(»× !ËUcˆF<5Æ‘Æâ"ø§IÁÿÜyv£{GÚ¹ÇÒóœ&³¡Þ/Ã7@§±•au΃¼(͇}~üM©*ãL'Ñ<"‹µ“›½
+MÓ2^ñY‡§»€.‘%)Γ"Qt£oc\wáAÈlSš}®ä«›]Ù” `ØkíÌ'åÁ£á Àüõé³ÇÞ@Tƒ1"×eB>?N K#ÿ”yWS‡vÛoƒÈrÊÀ5øºum™(2ͪkŸ ¡÷Øž1î WÏp©ñÌ`Þ¡b¤4S~ÜGÊŽÒýè•-ˆØÍ“Ñp7jœ™”·n;Ô;j2Ì4ÝÍ9—=æ7ˆ—æ.’˜€Šàîbº9çÅÌß@þ¿xg0ƒ¥ª× ¯Ês»˜¾Óæ0!(„Ádï9¿\ù¹>ýzÍà q)Ãr-§@ìh4sì
+X\¸µ ž@Ruî2ßAZF[dcÛ‘LI®HþÓü¼®ÜQ)ž¼ Þ?ÿtÙ¢v(Q_7šôrò&²'kå
+5«~͈eõ ýK÷ \ÖšDMã²BÑ  µd›õæœÁ£a4^ºk…˃fÞ WÙCr€•¤6Û®¿´ºB¶)©‚)óP“1ÿ6zŸçdþ ‘´à¡ä€Q9Ô¨Mÿ;¦‹f¼IåJõ¥…wE’Ç{7ò:`q¦¢<[‘´ŠÑ)ºµÐÖÄ£™h/Mˆ¬.3-<w+k[µ¨y(£°F"»+N$Õ£ºŸz…€BÜ@
+í1VkøùqÂ\„æì˜ÞÔHMv°í\^ VØF¹ÚœûÜ´hï  Y{V£SÙd 5²NˆßÅ\‚}}çFëâ×£x^ˆìž5K°˜î¤ä­hµ:b~ž1WÑîZK ¨¸R¹Qö#è-ÚÛ㾺ØÂŽµMŠBG†ö ú8å¤`¿Ëö¬I×F‚$(âI!/w¢(~ÆÃL*o'ïüóŒ¹^[ÁøúÄÎl3
+Ÿ ¯4d?ÔÓ&½(”2ÖZ¯9ˆ}OYéƺ –J’‹ò¢É ¸Æ¡Fˆ;b1tšŽ˜MjG¯DÏ1Ÿ·ÂÖéÉå¤gK O`­h9T¶ËÉúƒ­ •xÅ*ù5|NèûUVdø:®0 ¥:˜Z'>C1U†[ÏsÈU1£{9qE¡á¹˜£8!,³‹9 +V1ƒ òò9€è’ÐæMÊÐA‡4JÙFÉÝã
+żTyø†Ã8@V¨ëX½Ã¼¢]G«ùø*Ö¬Óê¤ñ ©kÈ £™eÝÜ'ªæ ¥(ŒÅ'¤'ÄÇÂFPIQR¤¿'‚†.‰þZK&DôdŒ]š=ÒE'¢óðÔ9vùD Þ k{~¾[.¿¹…b‰Ý…ÕÀ!Qš!Ir@ü Óʯˆ¶Žâ®Ú"[¶#쩣ꯂ¡‚<gÙ·ÁÐ÷¼ÃïB#Bš…¬›y €ðˆY³Åãø‚`<ƬBÙŠÆšÊ$‡\$ýÂ׿¦\O¿äÝp´Æb„š8]Ì;§Žõæ4«y!3 òXRÇ1}sþoì…\Hüñ×k8p UÝòiZ!™%­—r"¡3°P±ÑN A ­ye¤½†¼ì§‚<6YÛû‹[1ñÀ(È@teÔ UtC3›uçÄTåï8{c0Ž”mA(ÔÜ®¸¡ï!=Ù‡äÖˆfëd_‹ˆ¯<Ê—¢ÃÄižC¦+2ÑÁì«
+Y-9ĘŠC´ÓA‹Y[¤€ºq&ÎCqÔœk§îçÀ˜¼«°+;4.c„‚…Å:µÝ)*8B
+Ã9w †D¤ ’L•äøPÃwÌ× WßæÖ(>›úâW|¿/ ÀﳚìÆÈ#Š¼Ý/ƒ¢¹”tÒº ‘mL[c:-z@f-¥y¶4 î⛈¬)¬¼³^)® žPŠ7TH¶ZÔ×<†åŠ¸¼rH¡ƒ`Ó„ÄÆÕTÑí=²”hZ‘dó@AÎFÏÕËz€+`m‰ë,!éÍýfV~3sŸŒg¸OØŸ¦0ÆœDO½ƒ—!Î〙óÀü6Òž|û*°êcV¥><ÆBÊ͹L@ò>¢J9ÐRb09§7ÉLkžDŠh'{3ûÐ4£–I&ˆÉ Ñò$›×«¤ {ÖW¤†˜kè ½ž¶}Ã)…ŠusÈÛzé—¥Û¤ +ËD íBà‹ø3%ÏÑR`Æ[ÆÊ‘¦XYþ ÷½ h°׋+R”
+Y-óÜ9JN6!oD« 4<£ìPo -øaþƒ
+]ä‰rÍçIÂ"Uï
+2ñ-†Â˜V1œç­ÖàYGõR VŒƒuG1aTEè Ç.´Œ–o¸g;ùaÍLœÀd„½F‘0 $)(‰¦OHLÿ,Œ.AÙSòæ°tÊ®@µÃÞP€÷KáN–<ØFá³
+]åÙCÞÇ–œsàòŽ…P&ÏÁÖA\‡Äm Àšô
+{HñÐì’{‹ø9H’
+£óÛ6*…“©0‚ãz1RÿãÇþ|’Ug·xàâÝýc *äëù¥ëv+â•8¶?âé_¬5t€iðA§p°qr®VRh«œ×Ø‘4ñ>OúW•GÐòÀknØ5ŽÇ"Ù9x'º-®Éûb-Tr^Ve–†‹È/òi\Þü*Lþ€åèÚų«$WH#ÉŒHh? JgkE¿Ì‡—»^1ÓÆ/
+–ôk9Q‚ÎÊÈ'Ü3§Ô/]€o0sXÉ’ÒÔS ïQåEË
+&ýco²tó܃ b»È›ý"|#>÷ÌsŽ7/%Ôm’Nô¿Lù¸Îz|=zÊ^•n²Õg«â¢ÆÎð:ÔÀJ˜ªLó ¢ø u•$‡ìø÷”,ƒÛ•^¶•Ð¶*³–ŠU$" b5åÎÔ\
+šºÊ}*Oí’×å³À#ÔêÝ«r¤|¶­å(a½1Þ„ˆm7ë$FK£™¡ºK‰«+ˆX ŸÐs¾ž\ñ!Úè#JxaEÌ^¬d‰Øšm\ì”3¤M¢ˆT”"%¸‡Oè-R
+Ïøp¢˜Õ ÍV1ñrž
+Ùq)ÞHîà“Þpœ`{ŒyGÕì¶<æ)á IeHFòÙdlßз^)§®å'Ø_º.)‡¦º~ªáü¤Á‚ðˆŒÃÏ©^]ç­¾æ"VׇÝ~Át èƒå\^ΩK–P®×«PM¨¶
+Ùíõª"GCÿÐûéç°S97{ š„æ gõ'Vùoì9-ûM¿‹° ¨;ôÀÑ/çüH¨wVÿ!‹®õ(ú¾šèG2ÙW˜•µêWèÞVÎ)üîÕØVm*0u_l9 mzuUìaÉøî2mËù‹É@½#’ÑÒA@ç¡h[@nÑ'ü.qøPË9,Œ‚-­-Øf’—„¿ŒÔ‰FXP숻D9ãì©XýËI]BáÑân§}¯Š(ßMnWy`
+r,H~¢g!°1Ã……ÏIØüÈ4½ã[¸–ßÍK¦(qáØ)OàGÔ‹¿ÝzŒÍ,ôy‡É!gº“\‹Âf’…ÇøYsè?ÿ*b·
+pðÀ²Ã·’‹³½áÈrÓfõaÍy¾Ff¼Ë¯Ã“®zϯ"
+¹8eûEP]¦’HìbmK±Ö(Ú`'HiGò‚l'#H޽΢TÝT#2¡$À‰9¥ð Y:6ÚÏC‘;¨uÔDúƒh¬ ?äƒÍð.¬]‘ K~SaŸ`}±ó
+„âI6÷0Ø$G˜W¨ó|F[‰±CÞó!•ÿÞò£á “†û‚©n%®Ñ
+b›ï_i½œŽøCœÄìþÝÒt=¨7·óólE”‘ò4'¹6>,¿ÄŠØî¦ÍÓ´*Þ’2ãÉìÓFËø“. D£ª•›Ü°?¹(åÀAŠFh%„‡›Wh
+H‰”—OÎ\7ÄOà;ô¦!R”H­¥oa`Vöý·ó£Ä׃ô÷:pÀIª%ñ_Uq„Ž™ÿèhOÕ¡>§X ŸÏ¾Z³VˆÞGæ}
+ýd 5‹nc.{|¿½ª?ùßÃlÉX_@N„êÝú\u™ Ž0 9µÖÙÔCÔ'hû{JLçkˆ{¯ÐUZÞ.Í—P÷&£õ¾bÊ>GÚ\œ9áH†Õu¹ñÈx.ªÐÃeö™¦W­1–î«Æ3ºðEÛèÍȧ •%ÝçLþô¡kõ.S…ÄÑdCÌeõ¦3c;¥b”««¸ÔU;UcšˆÔ{V¸F£Qd'·¡]ȳ|Bø¢8Ú’©™@î–ÆüÓKvùþí¿ß¨ì“cçl±úÔ}vžhø¢õÇï[ÄÙyx¬üòƒgË“0›Uçσޮûõ'oú±Ÿ>(
+.e´Hc— ¡«³*»±>h~
+&Š{éZŽ¾xø#!ÒrŠÑó©•@ìqJ(Ù Sñ`
+v9›å¹"uUR"2ŒÕ«æ-²!yeØ>'Ó,>y|‚’¬¶Ö¦ Š¦MŒ|]µw;Be’ºŠ)AåÒRã•6![‹¸Î98Õ`‘…Ïg½†ÞËíŒÖÝäô"س…t’a8þºê Èré G§äÊyódyÊÊõ‰bÏC²9%gX¢yF€ælË×Ut:–RÓàøa[’øÒOØ©9õ„>Ù çE¾g«“¡ŒìBzeÝ@N‘3 ¦Îɾ¢ÑY!´žì¹JÀi¦Vs…»à&~wFøÀÎUÐ(Ãä·ö)ªž¼…EéâuN*„âªüt ¦²¤lU dΘk\ɺ¢âçú&¥Q»$F[ÒYXj„ß©‹Zí—¨±@Œ[
+Úí8?Ü–ÖUïTJ[`¡$U<Š¿p6éÍ.á1÷ˆ¿±úwø¿mþ—=´“¹¢Eôfû}@Ô&EW“!¶´.NŠ,<j‚”Ó±d1¯-µ}­µÝ½’KÆPPdMõ°bò=)¤qÎaãÚZ¨sH0Fîúü„À‘ ö>ªµ®›’·ykW§Bœø,íœv—F¿ææé1 [&„yŸqUô“­,Y¯ÕoËb—d"4kÜ#<[wÈœŸ%";' Ârúu@p3
+ë\CL!gú}ÕRj^‡!6öÑVA’H¡»Ê­Ä’ÝæšÚk>U‘äO­ùd?Ä<Jx¾ðŒðÊèܯjã-Òk Ók#žÙÕ5(<ÀxÆ•bLÊÒ! ¯¨ 8ˆ®åûa¯‘»%)HŸ9)™g®XwÈÃß_=Ìü¶ÁS¢_Æ!¤ÑØÑ°âq¬€|cº—ÒksËì¬ìàÎ:G!J!ÞÕó RºGR‘j&ìÃ9i‹s Œ{AóÙü™ Ù\Wr'Š^ ÏAàur]åÉN÷_öÓœ¨@UìEîh"ÿ¨Ç@,:X¾ŽAê¼j¡ú7½•7$HMX…hŸKh8Cö²÷F£©6w΢ä4õiôtÇ $BF.‹%³àzÙ-p®Â@Ç°;ò\|ËêA«qÕ&J 1’o"—¥C¥\ÇIðŸû=â‹”Áä‘Ø‘»NHïOÙ­$§,j܆”ZJ¯ Œ]7½§&û±!4²{îq—àô¤ˆÓj¼Èí¶P؆9×DnVK¼|;ÜpdïœÖBvÒÚ¶Ë!Ó<¥·åÉ»ûÒ rJÒCmŸÛ '3Í«ûhMÞÏøÚˆZuM‘ *…¼+$+÷X\µ—Cf¿`@ÒÉy ÉÄ£g~9㛫;VÑåöœt „~L|Žöó;r\\B¡ U’ÃÌ‚§yÒVõå„riÄ:úº^L_™<g`!LBLú¸^ÜxrÛiœô¨ðZPOŠ÷!ô•mÁ„T=ÃÎR›2t›ÂÒ2„m•a,&‡oXCûÐð0ééªÞ;È$›ÿ/hHÞ¬±ñ8Bæ’©òFz,Iª2L³!Küôò/oBõ¶¥|¿SÍ7̯{ |”+®Z~Eà_©¾Òo¼o¯Ç–Lyy2Æ.Ùþ?ÆË$I®#¢'àxYÌÚZêmÖ+òþ[=)Vfün™L’±ˆú8|8À*²·
+$ýéE|ƒ £]8¾‡$¤ªKhA{™¿"PIê"Íþð4`aRŸJ„Um[s?…5¢Žýݳ<|§o“ÓÓI_áîK֋胟#tìï™ã•P*̺]žÿUQr_«ü6 ·¢©t„¯ƒ{‹ùC0m7¤è%TÀ‚ôÀE»•é:em•#¬X :Ü6ca!?‹À|ǘäáÖîVR`í©"%_,øþOÿ KŸeéûÂg+þ!çÉÍ™ð›ÐrüNÂØü²" °a={FÁ„^nyµ’")„a'R^ŠTB’Úø5da¯(©Njš_§DŽ*ç[åU¢áv1o×û(ÊÚ%ÔQ„Ed
+CIMÇñNM¶À }’
+ÜpÏ0óXW«´°0?´žŽ+å/Y!~m­xºq»R½;ï~#Ö,ëG‰Þ`)
+›èY‡/%w?ôñý‡^n¾`œ7‹
+LqFÍJðm
+¸øÀ³œÍ”؆§ØДR, Î$bá­ ¼ªePJ–t«C(«Ö Ôo%oÄÿãÛ­ÏÉ¢6Ù@TðçC  `ÕX>÷·’Ù5&\eí¡ÇÈ,Ih%,E8ü$Ž¹Ž!':± Â}‡ÖðÜ_Œuµõ”T¹óNb8žý#P$æWf¬ù$¶ˆ£ÈEÓ¯,Žà›ìZº†•Pq‘ Þ!k"00lÒÞ0C¥"þ9cS$#f$ãWÊùRÂßL ËóO.â.µÔ-c?¼dh­Ð‡–o%~T!ì´Ìš¿BØÇwªpå`Ïe¶
+?g2V4€‚±_ùÝŒþøv­éK.‘õ¥ßŽj°|M†•
+y™ÞaÑÂføzœ„þRU4‹gçaqØÆI¨~#(ð:o_Áoaød¢†Äu1âÃÜeÚ@{;ñ¯‚0@¦i¿† `A
+·ž§h ×!ôÃED%`$OJúäjÐ_.Ñ‘ˆºñJ:¿—Dß þ‡X¨éHîŸ)@·`^h"ûAjë1à¨y)ñƒ0Îm2»Lƒ¾SEI3Éiœ71<[Æ>û]6ä!Ÿv¦ý{¢ò“²ŽÙژɌ¡Ly·ièSIVJ›ý(ÃG\Ú>(.ƒDÆ}é7
+ikñT(¹©AÙK’<XQjOª“øQ“``éÆ86™š—r:üÒ¤ïHɉV|Ç
+<«„-„; I¢<¹qÜnCYΊl­!WsŒ£Ô&<n~S%Íd2O
+ĆacÐRo5‘²ˆÂ^ò(R„(V÷02VFë륡¿ ¤!ž+KË?î«öݶïKI%²\ä“YæÛwDÈ'§ëŽùvJH;;-Ø÷WQ†¨½Ï[o( gu™ŸýšÔ×S’®@šñ8)ŠÈ[\Y^„òeà ë…¨ål(!R^
+ãíŠ>j¦\òвµ|±JôÙ.ÒÌó¶
+—’ ÷ߊ†ÒVå½}Nÿ¦ToNm[ƒ Òiš7Ñ£Ô)¶3ßܱßÞq”¹BW3^&¹uä@=ïàdr^kë[xë¾ÿ¶_pøò¯Ê‚…†–"‹9ÄpÔ~d9€ÌRŠ0Tá ?K|Ôž¯ˆ¹rUYÚI4Ãïë+ó@ôòÐ2ž³ïNñµò¡üõÒ†VÕä,èc)#$‚ÿTNËÛ¤ÀÇÊbÃÝéS¶kš&9žé»Nñ
+nòG
+KÑøä&ÇÂþdµ¢§m MΆ?céæ@ÖN5-&UD²{ô§h#ÔVݯÁï!ä0S›‹ÿ*‰Ää¦î5¯:šz‚@ÐÂX¼‹ÿh6£ƒs·è÷j¥âkg•ªÛs±q#ñÀ „
+wrDê)`X‘i^ïOàd— î$»:ô¾ÿ–ª—÷ÏQ'm
+£ø^æOÂ0ÍËçÊ°)“]=sØ n/x›´\é2Y‘]Ç›tϵ †È‡Kæ»@P% ›1FFÍæ ³E€dø}šË‰"—D“‹æ[íÿ*ñ{0ÑEÉ”9õÒ•T–6óC 6­‡i•s÷ž 3:qÒQˆ÷ÄBÍŠ¯¹ºO(_ËàæääW! œªßkÎ"ðm¼H*û€ÀƒD¹ÙLmÎEÞ•M¡èØØç >ˆÌ³m2ÔÖ Ö¸L¦zR™RD¶ýx£ñ8#è·ž6ÁÚ«±ëOx€_
+Í«ÝD«!ÉÇ%¾¥MÕ¿£±?Íh>ç80å¸ÄÛ9t÷e»œTô–g´P²«IÌy à5Ïh1•ì¸CZ…Uv“ðÏ»áÈ€? Š/K`…h¶HœÈX!]؆"§éƒ¸®ºr~ !¥y°Gö¹Ï;ò€²í«®ÊTÀ"$!9³}Î…ˆ¡zXXÛ‹‰k.ä)ÑäÆž“èX.yÊmoT
+7ÊSþ[ äq
+O
+³¯„Ê.x‹ÞŒ£}+ ¢??˜ÿv‚#sÔEnÇÓ_ Nq*› »7¤Ô±£n½çó
+ÿ…ú¢ZH–åñ„²céȬÍ6eG@Qi7÷3[EÊ98]Vw-ýñ¢VòñB„ YÙ2ÞòAÁYÅ™þx•˜•A*ô
+¥«]›—ò„Ê\òÖëãU9tZɶZz8†Í©SŸ>›FOÂd‡Ç›È«³ÎÁWWÍðxk[ÍÈߣþé]•û‡–Š4 ÀÏ_ÓPõ
+M æŸõ]È¿&åU öŸ\"Ñ2oÌo¯ÓšMoÊÄA²[§ã „?~Ó¤‹ÿld+Žú½n‚í¨âó¥ŒtŠ A­S˜m6«×ŽÁ«2]”°Œü
+v‰Gõ=²'aíñØ7µÒabìj/„¾ªäDÊ°nês¶Pbîž›,?É‹êQ]5Œ|¶€iÔ¶€–ÏUø£Ê`°üåŒú{À¢Ð*Egâ]'èAè‚"Áˆïûüá.û)’K= <&í»ÍqW?±›Œ¤w(¸Ú”t1X_ö“®7ÁhQ=2Q—f‚d7˜‚“Ó”:*Íè“ÓlG!š'e£3AÕ0Aç’lWH›n=LyŠïgâq¹ Š,;Còp€¤íAíu¬/wžJtIc×£G@ø$?3yˆ7Æ^ó€n3ªø®–ªú³@Ð]ÓÍ» DNJH0ñð?HÒrqU||¸ºÔσ\šàB®½ô@üÑ'iÈÛ:‡R $/oOªÄhÒñÒây¸d .vJCZLÄô¥ÔsÕ ‘`àD¤Ç=‡¿¡-­¨©~‚¤ø ~÷IB«X™áV?åçá¾ÊˆmÞgH˜Ç.ÅM¢I9Þ…w ©†ZÚ8lñ5
+‘¢Ð¡¬³t¹ÎsÐ'™<ÚËcàG}ž-€LólvÝ2E½qTµ.jÃ…s<‡Ð„gW ™A,ò¨[î`iŠS’ò
+&7b²1sT(Êoº F4âðYB M
+¢¶/³”è'†ÔDiBYÑn(ïPe¨‹«°£Êˆ!¤¶äÚÑ\_„?ººÊžvŠô¨dÍË„@Uè &4Öc뉷†œÇ}•µ¢e—û?#6˜‰Q1#Ísè±åE
+‰ìð!ˆœË-´1‘Oñ)Ð_ÄÓ¶ý[°‡éAQG‡³uQe³Œ)å]5FÇ-MÉ/ð¦â „ ¼©&†äãÕß‚Ìç*ߢtŠèžÅ£Æð9T9uF¬0ç íËg›â*t&Ó
+„›¢¬­fBMTTùÈŒ©žˆ«ˆ²ìÙÒzLC.s¼*Œœ˜X1°î«
+]„m=FÚ‘.€] ·Ìî±3G§/aG
+ÑÒÇGÍvp\ht+ó±9Ð #gaâ¿`üÚbJ8–H'§ó]ã¨Í,·‚ÁëqäÐŒSb¼Ø]l7\ ·E 4ÀïpËu1ú&Ÿ*â\>Š)ëæ¡!ÿ6”áâ;^ëkAUw­^Uè±ÖȆ¬ÉºG}+b㈡T"—ñLÖÀÂz7³µe
+Q•ùááúìüTf«Ø!—ücçqFqÈÿ¬x¿•!xv7øÅ$,
+]?ò—W€YUÉ1‚Ûw ðØ6ÛׯEÔùøR‹£¤‰}ïïWhDÕPÊ=ÊÄc"`›™:A>üq˜G Vþª—ÙÏ
+XŠMÀeõ .ɉhl\6©JDôBI%©ÌWÈ8Ù>ˆ¹FÀv ÊñÞˆÎÀS–°>ì ßþÄ †fö¢7]1ãÂeæ‹
+¤jáá.áOUm((ÜcÞJ0ÝKúˆƒh©ˆ[Nµ›ÉÖÅÿ†W,¹y•Ð"So..´sQ0’x5<®­DÀF9ئÓf‘ø0¶¯î´½r •þAçqL…u¾!6dªœ£ÞÁSî h@;an”#y7ÎòÆœŒûAêÛLÉì°ɨ˜5\c’@ãÉ.ȹ:ÅN–ëæáYJö4HZ.ú,ž(*ϲüMRÄ»H½•ÄÞb˜A´EÆüð¨kj½IY­ðŠÜåœàÆ]<—áˆÛxɱS»Ž£œë~‡ò*F=™Þ½5ý30@|ƒ¦—Фʫ—¨.'U0y»ˆvÚxI/8Yëë>_À%‘ ½Äþ­ ¦¥]P,5#Æ¡u»"R7.É-4ÑÄ NPŽ"=ÞA "¤pÜÎz 9EÆ`°»#² x%öü·’K°qH&^ÏÝ!ý“>o‚¹²èä°JÆ›ÛCŠùÉ×5¯û%ˆ:2®þROþÈ&‹µ€?î°GÅ´býU£h„I`j¯W1•KPé_@æ?·ägÆâ¡c´B‰ìÞ‡ã]÷ÒÚ§dzo0¿œÔ‚òy)h|é®æ‡%r$±È.”^C2k?q;Óî˜ÎÔÂSpø…½êøD'ìCW£{¨TAMd·I,œëá—M9û'Ð@\˜Ž²>¬ÞKÉu¢ôa!êûŒÇï,™"-&½ø
+Y¬[‹¨‡7e´r^’y>\¨â(œÀd§œ<‡³HG Ga å¦Ùþ\±&%\pdz±‚ºÌûÚkuOˆtò ¦ y¶Ì yëÓÿ ±!U&]ëÚtÚÝÄÈ'5‰¨ Ç_%–Q©ÃÊ4qïï¿=]¯C†Ÿ—.òâKlòeŒB‘ö
+G
+!€äªF{…¸¥i>)Kƒ¦Z„&”"=Õ ¡hÐ5`/`Uû…<^ =€‰A(A…¶Ž™×å¼Xè8¨I÷XqÞzM4ð<Zô£Tê%Ю‡¼QÁ0ö¹JÞÑcÍk°R‰˜”'—sM¿È—­geW>JAÒí׫ Ûtíl_ÍãOYñ“îD.åQÚ<Š
+TXH¤§J¸Ÿ<­ ‰R¹}Ý7ÙvÞ$òë÷¤u´,Î5š"%–{,_^m
+¡¤qmÛÁ³±h¨LlÁÛ6ɶù°¤r›÷+÷'›YRh¸%D‰— Zäã6•µŽ\Õ¯EôDb ØAjƒC¤
+É(•mb•q¼*ZkY²ùfC á‡ªxˆ_„“ÛÛO_
+žý P“6Â`¸:®ÎÒëàw1PÐb}^[„¼€Ò<·4Ž|’ÕdxO¢Ì¸¯|1y{÷f\N1'‡t!"ŠYÂàЋíå—"/‘±g÷t|†µ³5GÆÝcÉT³ÊùíëÚé$/ÕüÖ}úöŽ’|µßCŸ*¦pJq¸YÁ2td½ÛŠËleè Ÿ%q‡Ÿ#åÀÿgŠ…¾±-ŽÂpÔù¬g&PHžyšX¦?šJz9:ÎøÅ÷U®˜¼ü—»€=jñgdXá+h5M-î à¤.Ã
+ ­{™¦A¹µ^“XA Äzâq£ÈbÅØàáß¡» >áJQRð\
+’Z9Yd¼ŠÑó†
+BÇ"ä;-DÞÔЬéƒ …´kâjdŒ‡
+y `ÚH<G7ñQ¶ó´KócÇìñþ|Ú i‚Ì[ÆM\»ÇhÙt#²rX2- ÜÝð…œ£P\¬ÐJ{…ÁÀ$U,©¸û a@¥]2½\>•^ªÍئäl²±·%©ÝoÛIÞêåì µarz{!oÉp±ô $zÍŠKÏ,É®¤¿y 캡®—!•Š-)Ùvº*”½+Fìÿe¾ŸÓeƒø¤­ ¸a˜$'ΡªîÛlÄ3ï²kí2˜7AgÏ?Ù<9´C pIl ³—D´ml:¢Iô€¥Ä‡†2ÿhX´º*•kkP–>hcØEG]Ð.Ž9•<ækmjdÔÁ`”Yöõ¢†¥>YŠÍ{h~öŽÀ}p
+NKÔJƒ³Ý.{úz#£Ož™ÿüãÇoÿåÿñ/i- É¢j ½‹ËEüT ˜žr ™J°ïí¡`Ê¥dÕô{îZL ~ô­t¾æô¥VdKDaÿᦫAÔ‹‹ä›£Þ%Ir&æ¡<(ª¡BOiÓÐïÿ š‡$t/ýÍ™Z!Lm´3Õoªò}ìkÂÌí Är²ˆÅP7«Lë, «z:.£âRð7@é!(ìQVŠ_…‚£1= 5ý*EŒÈëÒä¬ÄÃý¸ ÓÄÓZ„`¥4ºÇL¦tڜº¸ç9d|ÈÒàÎúc;­",}¨øi˜0[R,zõV ȶ¡µäY1p~U?7Ëñ/‚’„#Лš7ª~ ¹ÐP 4>!c¤ÝT5ŠB'T>ç–CÄžˆ—ÎBÞo‡c”ŒÍëäÚ"øì‡¬^ѱÌfï=ò52§•]XäW
+Z˜¥dØ~yå_U܃º0 à93Ô1}†‰@óø—˜
+D¥^™‡º‹½œ¥Öu‰±áKf}YçTæý §JªD2“EHË!‘ ]Š®…BæQ  n• $°ßI cÛ“O”ÂòVU$‡\ €k­(1wt),ÌzR…`YmXû¦{ ÁöjyQ¹ž Oà…ìo›‚æd‚Ç,ˆîx”ºÏÆw¥‚VB Á­:¢HÐpLh²Ä½K¶P'«Â
+ háÏ(B©‹ÁXÌ}ÓsPaÁ¥L‹Ÿc¨M~ÊñîŠ[’ø2VhUTÈzñ…±"Bà]Ô_xlCVêBáŽvjÀ ©{p.›™üIŽ,°ËZ6Aà0[XŠ€+ÍCÈ TS’H#­ã9 h’ƒ §f;ú²ô¤R}  AIMœ ‹6µ*û™ò˜›]ŠxWÊy­O—Ed5…€Ù‰ UìæV
+Œ>«"Ögh«‡€=ˆ6ZÞÊî‚jÉÒöü¡yò3‹ š b@ÍàL„4žé\ãá\.ZDLk½ñ æú÷PV”¡i–A_/‚æpGCK@—á0 uŒ”õNB茺a@Ä
+å¡ÁÖáUÑPi/U#ó'‚˜+aqb&+RM¢ê’d úsï±ã4&Ó
+qÎá”»À$_ì^8Psbø¥P•——ërNY½\˜Èö0$x½å·£g«X\üŠZœõôy ¢<6ªÊõ5ÉC1?( ¨{¾ÃR@œšÖ¸¬±\j7­4Þ ’Îa „—ˆuÝÆxp#àç°ñ^ÜÇ;eª<Ú±
+€Ã÷-¾J DȘîXcÌ}_nY¿³>`L[Âw¦lßõTÆç ¯wjí-É,¢e!i^¶)‹£Pp*j AÔ ¯Y%+ru±ÝÔ{!̤¢;r‡é‚ˆ`ÁZªIÆ!BrZäe;ÄJžØ6ÑËt9³Æˆb Yò–(U¨HÒ)ë$C3d–ÎNB$óL©<¾2³BtSÂGPv>…ê铢텉æï+7a&¤p…— }Ý1§ËÌ%D²Ô(î¨Mg@sAØ9ynGª%$5^ÎË(×–XÏN£!K\•*L#£Ð«S$9+R÷ £!IyºÊ8Íȹ$Ù€ºó)p/¨€-˜1¨Mª©Ì4P
+˜Äà °|;„ Ð**âƒÒÚÙ0œ’,dUF¬QCXì OG¯Åj y§­P(o'ᴿγ÷ƒÃü¢{1›ÍµÊýœÂb¡“ í®OɆÌØŽË”˜ÐÒÞ&¿!´±à$XôW± ]jŸQ.â8²›|á©š@† Kq¡¿F¾\auaÎ>¶þ8¬{5®F·‘xV;yÕ?Å#Ô9íô;#³Ë®á8·1,Ú1¾iˆ__š&`y]ðJÅ&
+‚ u Äxßòi <¥ÊÝÏa-»©ãr ù;ÔMJ¬™üG>„è*ãU“Þ
+¤˜ÏªïtPO÷Œ1ߟ…h™!_˜æ=àtÂsñJö—ö6¤ùÁb'šˆH+'g@Rç#fðò²W5¼¿_wÈü×9)u{ü‹PvÚ”®pœBKY9|aGŒ)} 
+ræC.¥ Å$`œPâOA
+á—•X[&MÐD1_=¹F&¨€M©à`–R`
+ŒYöþûÜ °2C(Á€-W…Hf|î=AЀ%ŠÆ¯·CƸΓ—xÆÏjî, >û(BŠr?l†Ü,u_uÂ:?ª½ðH?‡qIIÈQvEn,ïùs †ì†µ ä#ªÄ=èó'åRe“WVPHVHu_[³ IÇà©^×çi· _aУ™X7øB‘¶è±ÄÃE Îüc!K±Âñݽ†hbÆ@¹–Žg;Ó Æc?˜‰žì91³•i-¡µB€ Yéí|6¾ñÂä0wzIp¦€à`VªË¿Ü) ÚÌb I\@u%Õ È­ù‚<,ÏœyZb/ÿh©Éõ\u¢ù鵤í€-ÁÏ!4dÉe¶S*¦e„Áó×ðá$@µòÙöÜcôMîÍÆJyV¹lÉN½´(A™lC^‰0æ.Z奂ÁŽ}þ¾/5Ê‹ßåÅBÚIÎÖbI»xBÏüýMPâBAÉjï
+IÖ3@Ä5È`êW`ST‚ú 9à]Úí±^*<NþR©î‚Ók;#ÆÔYX ÀÀ )°ît±©ˆ3'! KÑ&¥-â‚é/!º¨ª¨š0>²Çç
+‚ž_÷X2ƒ è¤G2Ÿ8ûƒŒïÂ0FüeTá·8Ð2ICÛ ¯K’û1œ†d•±ƒF¡Þà´P.|‡¸À¼üÎ+ÞntÞÜ´Ç’kÁéy?'3¨Y—«—¦Þ ¾Ñþ5ÙÚAU0ËÃu:GkèäÈ”‰4qÒêUŠ ,™±¶ÎñbgÄLŸƒÒCbX*õèç5‚b™H8=HÂø4¯ôq
+¹
+#ìŽ1ù£†v‰uR;81¥´E .[%„q§YÖ8Î+eÃf;:8wå³Ò9f­ÀV?Þ‚ M,`FþåW"ç(ˆÉ' “†ùeX3ÔR1º 1¡#äФþ±Ds &82T}ZmÌ]…ôP¾K»Ç¶ð,®ÑÔ &œ¿DšH=ù•!Ñ+½ÌX[é r
+éâV™ðžßÞ(ä* #ÏÁ#Í<¥ñn÷J̓™Ä´Š"ƒ ÏTµrº¿þv öô¡!1²WD¬žó’!aúk‡´Ç1´ÿ©ø0b¹XÖ•dD.Wšwž÷Pæ{ÉšWßÅÂê±´`]+ÏÓá}Œ¾Ë‰UÕQÑ“5ž{:ùK€{Àc­G§ ñ
+ñš×Ìh„Á0žtÎa_­ZX rÐ (£+ê`Ú<ˆFÕÖƒ¬UíÇA°+¢^‘þÞÜ°&{‹ùü»]Ïâ) ©*¥û†£&GÍdZÉï7õ
+Hãy]@¿“?}Pȃ oƵ‡ ô‰êéaæ
+Î0 ™Pˆn[r>´ûôRå=t`ä<ĦÞXE¦§'Y_ˆô íÔ“ƒƒŠ‰+_+ž4šF«f̉!À(«sØØ Ð8B  YB”J²¯ÂIqFÔV ™aO¨Ú¾ò%ès~óUX.-Š4¡Ê=‡Ùk·²0
+ÀËM½öËÀ*¶ÖÆß‚ ]ú*x`‘HAžmà
+‚Óœ(TÚ£ ¤ìš%)*1É[J-fˆ|ýÔž"'¾¥\P‘µN 14ÊŽ|=ªPåPÕW»ù›¡
+Š·Ò^÷Á?0C÷ú|ÕÉ)’˜£YREX¿Â~)±H6k‘±Yr·³Ê ’;4ÓŒ¬ž#º*R“þWëÐöÑ“UÂÀ£Ç¸§ëz-9lÔf ጠfz °éœ-s…·¢Ÿ¯Eƒº õî2ª’˜|$?s®rÒ—8ðDJX9lŒ$?gžwš!*á›EƒâtµhõÇt´Ì<)V’"ö?®}Â5(\Œâ¸Mè’
+}'¡\èBwÑëðj¸ÙAt°ÞD€Jß$(Š‘¯ Ÿ}
+"x[™?¯Þ–Iy+Eq•=Ð&¬Wæ–vH.64ð½^Š²:nx%%ÖéSÂOÁXa »klü gCË•„tv”ß&žeF Œ<j›E[C§LÃ!Zä;[æiÆl×> 9Öbž¡•;½Ü‡ññæ¡ÂJºm:"yê?õiÜè…Yd@±´Œ Ø)¯rTל%畽ñ/î’Šúµ^Û*)\~râ|ΣfÎE˜g[G¹Ý]â=];ßÝÉÓ’cn—ð.÷Åß”ð82Å5|À<ê¥
+ð¡Ãã6æVr§{_²º ]þc¼ŠO4y¯ìkG¯­Ê©ÅØŸ£Ò8˜f¢ïg×Ø“ñÖý|ŒÉôD…y¾y‹:#ÞJÂïNÙ¯äY§~ˆs–,6»w£ÙqðÚós‡…8Π/pgGrÉDW¼#¯¹“S¡¢ÿŠ$&³Äý Fr°¹ó¤«‘¾à ™uÉ\2ÔSmð…Üîý^_±¬1’QÄÁŸ½vÐq¿TŒEÅ­Å4ÓÎóý3
+³ñ¸н·³|¯ùù›š$F+Vïw™>bµLAü
+Ò¢ix¿~ÄôÀ¯mÜöþªeŠºÉ'Õ‹¤MÕ–c¶~ç;=6«Ý{ˆôZr‡`b·£$ɤµ»Ýš%
+çI Í3Ã{_E!Ò¼ÄÆQWœéÉìAÐrµà@ivo>êò¿\~êoCéùë³·‰Œ¹°zqü/5?G¸)õáÍvŸSOh ãµÔ·)ÓýÅî§"¿·£-îWý ^Dxn0ˆ="€}Û_š“’åñݸóUr×d¶Srß\ZœÙÑ·aDl§¹äyTœœ˜çÐwY=$~K¶“/ÿÕëÆ(¶ö üKZºf‹5On¸Vv+Â-WQu+wA9 é•Fr ¼Ì7ø"ÜB]m†«_£`s¨£ÃWP²4O*u5%cžÓ¼†0P-;t¾q6æXïxßç:éOl>÷ñF_ž%3ÚFm<ܵnh¼˜ÒöÒ½ñnâBüÿ,£€;ßý’÷(Ó)^Úúkñ:¹(¬NŒË+nȃÉÛ*¯÷
+g¶’ØŠ$u
+žÚV-½jy0ÌelEHÕÔ¡D¥¿-–¾½ìÂ8
+Ô¨}2Ñ]Ÿ ØJ˜¡„ ò1oLåÊeÉ’Wݼ ¤¿fÒ¡ÑçöÙû¾|çEé•X¢=†J°zu 1º„ýÆ(e[ŽÁŒ`E±åy•‡‹ƒíâ_nfp軟ïø)Ëäœo>è{ÿl–þæ©öÿþÕ¥6£*–”ÞÍE>j{H;á-¾êµ¨Dαê^JŽDXÙFVhÜ®\ìˆy¹F ÁÚÄûs‘¹B’`kë5rÄrTlµ>MÓà\¶Ê-ß‘“î3Æ|®ïw&÷
+ÔÄj—áðŽç+.Ÿ_É›}gø$`ÛýÜ–Û=¾m[è;мßÜB?÷UTpghãò/Ù3;:áw—õ7k×æJ5[`ÉH/ïÍËjZ_°>GE¥ÆžðLG@ÿ¶àæÄ‘@,ëz´W¢8ˆØ•0Ò³õó¨ á渽.NúN[YÀÊ^(j¿)ù‚¾¤Ï-LyŽ[ ïz-RýΔ¯E´Z
+·ˆô#ƦH 9»¾§gþš¬hëFÜ4¥ÇÎ=\¸F–XòG½G+ò!>K¾œ’è³}Œ/Ù&.D‰M:¢óDþ¿^ù/ÓŽâ1c1\i{,Ú±*)±éñDçq>œq.ñ܇
+þT.öv˜ýK‹·¯ÖÚÅAþ¤¤eÑyÛgÏùwŽð(ËŒ–çQ?èt‹)æ­ !ÙâqÌî’WúIƒ~tš~¨[®¥‡,/k–Ïà¤Z4/–p”øÑ‚Œ‡¶¥YØ„!—#žI¡…ãŒ)w?
+g‰¨vŸô‰‡œì²Ê;ßY­ÄÚÃØcAÌÌZñõo%~dóŸ5¶C¶ˆqòô~T´‹òž ¹fÁä|(­9Üm‰õ/è`8ÆôEAR\뇒@K«2ï1ªIQ°_C<KÍàB+zž8ƒ‚#-.óþùzË»Ë@ºQ퀗Èwž}â[ k }fÚAṨy‰q”›ÁìÎñ÷RÒŽ2%a%äã?óïàz·‘râ^FII«žo]³T[â ÞǨ¶¸äÅŽ»áUûþ–,5 nµŽ¢=€8kRʯي“Ťâ?ÐéŒ*””›](=¨M('³)1%x4x#.^Z«Ò±:%ÀúuÃ9!‡s¼jB¤W!Q…9ÛÎÆnï\ì®vúÓå˜Wü`ô¿qÿîßòmz™ç•þ²ƒlÅÜÚrn!ã¹¹ô$7¬×¤([Â!\yÁõd¸pIß¿z2F(Âtž£Œ5â ¸lø±8 5š4Ž"XhƼùNM¦°ÜqÕQRÒ±ƒý2æ3³Fõ*e\¦ÆL[œ¦éNªI¥Ø×—-öÙ‹Ôp[NkäTû»-â.¥—”Èg[]+aªts=@_x¨éÚx·£0ÌzeÏËðƒ;æ1dð†#ßiTÉ)”2ôw3A+wmí(ÊSNh¹{‰…½«†ómkìÖàì6„KjëE»ù_ñÜæo°E|jœPÛøÒeO¢
+뱦GÖò ”²„šî¨Ïý\í‡R4±QŠ+ªh(u^îÚYG{ókü4†ædPu+ JÑü‚(—a^õE§íFñÄîOlã‡ÓÎÇÁ¹Çq1¼î Ò‘ –¨—@5®Ã¸>ÕºÎö([ËPý¬ ÔX:s‚üºÝSÒÙÛÖ]ƒrèω¤¥•{.w´;j|ûJ&g'F‰« M=ôË%@¤ŸÎGMŠh"¾òˆ²O¿cº° †ù³ãCI– ùÀåþpTÈNuu'y­¸â5«[$þ=ù®—¼©Š%)èÚ~Ð{Md¯$¾ùW H ˆ¥YÎJâßô£è÷Ô?»±t£Ãžy5¥ZQF³Êdp4xÙ‰öl3S›õaöàac†ÒkÝFX«xz Rá*Ž,”>˜7¢SØd”`WU.y7Qà†â€\¢LKºÿ{UŽ÷ïhÌŽës›xLÜŒà›_7݇3öý|E´®xÚØËNÕgˆwnñê£9³ÓzP¤G¼uâ •¦‚—áyÒ½^SUÐ Y¬¶Gôµ«-1òvˆ©<þs"…f<šÔyî#ïÊûpe®]½¼KÔŠ0<:¹Ž“`o lµeÓÅŸ¸ñÚ:“DD—à_Öö”¬tÀ ’SqíHÍ÷V>”¼šÚiÝ»xy,¶ô£^o¾Ä]ÏôUkäÚ0×±U¥V±ËM°ëHÀ±/q}MUëÎ>Ãd„ßX<›u¬]ããi ¾yˆ<ƒ ýaø¼{€ÛD‡n(Ê×}óš9‡·Îwd¸º÷©W/ »oaÈ­k¼Øè6zFúk/+ože(™ÕÔv8ÖQ´ØO¿z3R¾¶nS»À›¶!$(]»×
+ŸØˆ¸èkVÒµÙ>è©a$¯M¿cwöt+3®S΀Ɋµ…” uñïQž¯h¯ r®Aÿ<x\䆷Z,8Ù;“Å{J,7Uóô-½÷/Äeî,Û˜C@v¬ž]Ÿ×yy‰?ÝÇ4K†Y»Õšè³Š+aø(åÐç“ÑcÍ]ê(9Ù:ñ±ÖæCQ6£X0»&—QRŽä0?¹Ï2Õ²5Ž÷ŠÍ”vÿžIÌKÍï5ìz"äuõTõ^ÁéHb"i}¨à>äÉòë#wQŠÂAÎóìÿÐ]9
+ùú(ÂëW„.ŸÅd
+–¥O
+H‰”—KŽ7DO0wè ¸@&?™\—º…¯¤ûoý‚d R7j/dÈ­(2¿ÁnÅÞ®ÖSŽµ—aõñWmùò4RËQj |~x¿j.µTs+ÍËô}‚’åZ«•È}lPŒÑjªÆUý*#EÏÞ¬µ´O)%«=¬¥6!QJ1•ë„°+ÕîÑZéVëãŸ#&I$kµz>¥Ü°ˆ‘Ýψ–=·f–¢Œ•ô3¦]‰ïKj}DÔ•ó+†BQ,Ë%æMµ÷j-Ò±!­ë™Z ,’œ³Yu[
+˜æÎÍ#îa-+”Z ‚úXçÇZûaœçM RПøk'Rá¿’çF4Ðo•é)(ý÷fhÇÇ¿BþÑHä m(cù℃x ^9nˆÊ0P‚Þé$¢Ñ¡Ý×xçMÞ{Æ×$È*võÚ$‰Ö‘¼yL@·hj§yw+qD¬Yí ¶W2䎾Â÷M¥N,(eA_N XSóaM29çÓ¯!²à³¡à7¨Êy5mÈ,2ëÛK` ‚û”O1gŒ„ ¸xœŽVdgCh5i#¯ÑwêZé&±…W7((pÆêY+«‚µ2)X°šêMô´¤ª8fVÏÐÔ0D†Áá,ÉžWU'Eò§ô·`˜¨¤:ã¡sJ°©Ì+^À7Âð3°6¡ÏÉa²ØyÖN#ð
+™71|Mþ²3¾qƒ†¦[uªe(èTï`˜¢¡>m. {¢f?™Ád®ÃËV½žÃÌ4,‰÷ÑOYáC8d0J=/-WAé–{f”ªßSÑÚ0›ÀÉ&ø3PÍ5·÷90›ªÎÝ‚¯.Ô»ÉÄn·Š¬Rq6¨ì¤žÄHÆm jÞÆ$Š” ÓW²‰[±©Qïs¶)á!éÀ‡ï{ð¸U“¡Ñ5Mœ?0íʼnz›¸…•f
+í¾.òRa]| Üç`Zd duŽúƒuÇ=¦ÉLòuªpпïJ€Xd^U#Á4MR\ÏÇH˜±j”&ßÕ£bKY§>!ô±bLjå6ç"‡êþºGÏ33¼égùÉ<Dæ¡SPvÖ­Ó'»I ‚®X¯!!$ ü/asî#2T×ð>y· FÖ$ºLÌ>8–Ȩ¡Gsé»<ÓUâš.»Î$ó/ˆš>a~l_5ß?U~|º ´’h#r¸|CÌ¥ÿËŸ>ÏAÅ8JG¯Å*Œ>b=£C|gˆK^‡n—}Õ+¿¯õÀ÷¯¤œI
+yÜn‰Jðjí*q>×…Òk†CóÏ1G9™‰Ax?_ ¿½:Ôpj•5Làm‰õ»§é{‚Ì«szEñó9¼äâIsÜþ³,Š`Fm"ØÉnaØîxÃBì›B„¯˜Ü[›«ô
+@ª'†X=ë7ԡø©ÎsºO›‘Èð M‚³šJŠNÐ[ƒ VþŠbo:kŸ¥dï;)“5•Mr⣿fõ«¯ ÅqË@˜˜›Ë˜s7]E c×/éA†¨ñ"ØI¯êýf€ºŒzj@&§dÌ*¯ ô~‘@)*DÔyÑlP=$Ûµ®D£€PÞç$Jcê]F<í'Õ,šÿ@05VDD#WºO
+ÙeH1»IN¤ÙõÖÈw<RÇžØR1ÿËÀ‚¨Ñ+ ïÚÑ¢±ÔC1JÚç°Zr ÿ4Ï™m'§Ñvö„'+·/Þ¡”õB ï†ÿŠX´£•† i>`Ä)ücÐOö=îP }q
+elSÉ+ÛÈÄŠüí² H™A¯¨ÓýæÂ_©UH<oA†XÖƒäê.  ±f=Ä&ï4µŠeãxN±Q±Ð|ÃЉÄúm.vÌÐá"–‚g¬ÃØ>Wy҇ȥŽ#ï´¹vt†x³ŽŒœü
+»/*hΓ¥ ,‚Ôƒ
+Õ}¡ð£ˆdú„ €aEä¶s:û¦§9žóô=Cž^¤_€p+ “^å"‡MììÒà…‘JÛg*Â\aÑ‚±â
+"+b`oöâ™Ì2=æ˱ZèSùãõ’$6nôºƒN  ×ã¥ná¯Æ÷ßú%
+ê—Šø–re­‚´øŽÚž"`<¸ÅfèÃù[8C×öY" ¥Øâm”€•)ÄyûòKÉÔhf ŽX¦úþ–c¢î1,«„yÁBcšwÈcT^ë᳉+××ó¼
+.Zˆ'Ö:2ME±«e]³RÒ’9ô5]ã¥Ï ÄoJŠ«kÇzÂį\Y½¦Lߊ³ô´5Î’iÖé¹^TZueç×EþcÇÎ Nèdíìêð£‘àÛ!wòÀärngF åUÑ`Ô l}‘ÿG…øPô÷WE•]±í×þª4îÃ~`2«Ò¿,6–,åI+'˜ã· Pîçéet™3úiu¬’)«¤Ä뱆H÷µD—9øB\'Y_ËLîÛ³z ^4 æIŒHhÿ
+Ǭ‰J ;Üð%Å$ÄQ\p¬£îr#NŒx­š+¶·ŽT2fÅ<'ØÐÉò £’—…!au´ÏÅá7Æ¢<oúmÿúvn0À>»#ÛÙî—¢¿G¿rÅew×XEí ÿ}ÿž=ͨn»^Z“b…C‹û¦ÿä÷Ø*§{÷{Ql!í!îöÅw˜67.F·ÞKŽ)q»p¯‡,¢Á¾PÃ~=üs‘lY“álJ¶¡':}–å:ÏBxîlÉsi¥·ÉÅ èÏô÷[\±»î}ñµñAˆfb+Ö„‚8[yrÜ×Ä“©
+|^ñeë¤CgjŒ˜¤™Ïo ‚8ï8W‡ß1,+/ )‘R :[ÛŸkÖƒì—þúöV„:0fKB+çÀ( _oتÁÀÑž$Úüô°"™•û ñTn]¢bAÏܙ췔Dbø²auž¯˜µg#ó~®§S«O|>‰¶kpI<=êì ‰.@ Ÿ+si%ƒsˆ(!-Z·‰:ñ q¼mUN®”E½¾˜uŸÄ/õ«ç;fM®¼ûX†X‰Úãª9Ñd:Êr=tñ¡d€´óVmĸm?Ÿ"ÑŽÒ9alZØx§ŠBææ) רL ç{q¤þÞK{)G}Ú«Ïß1]Nã‚¿úßÛüþ*ÝÚug
+ã`£w_p¡‡Qm¯EA¨î^!•†3Ömà)öÈ÷7 +1 p£|¥Ï£(,ÒÞlS/¿|e‰cò–|Ç ì~çêë¨ÆˆY]Ð9FÉQæàN ¾†€Óv¢Á¥ÕyÔÞ1+Nd{(Cº2ÎF~K¾CˆzRG¨»<¾£fx:6Jú`ÉözFµÅv-Cºó¨‹0
+¶†î°…?ˆgB|íû;WØ!NK[î/J®AìŽ)®£þç„ž¶ÐùCîj_룒ÃHÞ1Ù{è©ä—?œ ™×K‘’x½8_p«¿ ÂÿjÁÅî³ÅÜÛcž>¨maW’ ó;÷u¿™°ò#RÖaÈ¿Ÿï$ôš4o¾s4MLŸm;ÚZòÆ{qjæÀ8J¸:í£=t¥¾Ýy¤Ãü-û™ï 
+G™Ù-$xÊâð·Ù@G9míWN&È×<ê¼C4›ìc>b§ÊÎxˆmpךl°¯ÛÔ‹g3Ë«]ý‹»~ŽŽ…ÁæQŸ‹6$É£Ï+o‘í»‘Æ³ÁEèÝp±Ù¥‹,íˆT×î÷j à‚¿Áš+^0kaJçˆàD 91¾º¸È˜5š Ö0NÀÜb4,ë"o7«Ði« —ÑÔôô:—Þ„ï-%î.ʧ±¢×’’Ý`îí¦nyU k°j-¾ìZ+È%QÔšr/òþÀÌj”ƒÍžà6(un fnc©u[–HžÙ_)µF8rÞ-©äuMùNò«1?_‹v(½Ñ©Ea¦7x)" h®à>‰ƒº"Æ-À%äø¶æqƒÞÀ´­Ï’á0< µÝ‹15å½W‘ݳ›ÔxÌË"â ÚgŽY’¡Û:µ¦|"øß_ªkjD»Kr¨ÀÍÝœQôƒËJI¯£§n¯‡£™ñ+S*ŒŠ)j|®ÐÉÉ™GrJ®,¢­Šv[ÜMc†ní‡æ‰¥=­q äópŽ«°èNö3\u¿”L½i<?1~üþ¾€êŽ­qÊ"ÄG™ïWO"*œ”?—ÿRt1Á×äl‘pOŽ
+­Š:ì6¾ÚpD¹‡{Än•´øK5¿¹1Ÿ,†"Ñ+²%M3ˆÂx3+píëÆ”Xd‰~ßï~1*//žé×Rë¿ÁÙÞŸ‡qd 3—ó“%‚Gu=§¯ºÂ…—ðÆË%GŒ‰‚'ÐtƒÅ?ך¥oa`Vöý·‘E6Üj
+@6¬vv+™ù^¼´OB´3r"7ˆóP6t–Õ™Oѧeùûê222é²ì…ú¥¡™e„ÆÈ0kÔëTݘFì;tñõ*‘H´Í ú´ãøÒ6»9ýªÇŽté‘ÑKH5ÚÄS¨¢5¸…n£y’>Å»Ôï«HnÜ“ºE„Qo)¯Š²îç‘m¢„ž.R:þNÖ ¢É]á˜ukú—™ð÷2 Î0h8Äö®ïL -öWƒ(Ywš€¹Ž§”KɈ~~ÊkÊ”±
+}A²ûþô\k×»þ¹‹”ó‡K%¥Ë(m`0ò~²ÊYJç6Þ‹¨L}6"|;ðŒ,ÒTê¾PƒÝ£Ö)BJqÌrÄ‘‡Í!±6ì«œ$ÃÊ«€¹‡VD”ãB1Óu©x÷áçiÿ9•Ÿ°[ôqàÂõwæ®k¦’”q©ˆè–\‡–µz+¢æÃH$òÜåtŠaz.4äÆ@³|.êS¨
+Åö¹XsA«'VÑɬ™»‡L±ÅUsnn‰)¿º]àÚ÷þ’¢ÄÞ/xÙxFðêZÍëRôb¯W…›
+g‡§”„4aÌÁ¢ÄœŠLˆÝçÁ¦@|žò:Ž®cÃSë#v\ o'¤üEùòêÞ9¥%–åáÀ8¥H³;H˜¯*àÛ¾¡Ì[‡ a&nåL wVª.´£Ȇ›Zjº­”¶¹&^Á‹ÊÖ믫€u-¦Q
+LTŸc´Äarö:ö•Ó²"GBJ)ñ—ɳAvðš‹_ÔÒñm‚½ êÞV”¥ˆjFúN Òü ß°òœÇ;‘Ä<Ä9o‰ÈÔáþm—d$$B¥ú¾ª£ÏR´ÞÉÐU
+°F/!Áž¶ äÕO½öz»¨|SÅbÆ>ÿ98ÉÞ¶7r¡x à¤þ‹ƒÃGûÖ|_õ¥¨¾Þº£±Â^&sˆËó{‡öÉ!`¯ÚwÝîÏÑ<>Á4
+e<—’¸HþVÈÚõv¢Æ `uåºýU¹ZÈbk¿Ïcu¹ÔÞ0@
+F
+|®¾ áfÎ¥Þ´˜£F8 .6ÿá¶ÈR:̹ZF42L\¸GßÓ(G`3\_™Hú×Áª€_¢)OJ~;žr^,ºÇ†rªuЙ
+na‹:²C¶ßÑuú˜Ë¦¶&w ‹ªšÏ‰{Àÿ‘ʾ_…ÿpö¶—(©\
+;ÃOW߯j„ ½”À‹¼54И‡!ËC”$<+Ž\i¨k8œ» CZBŸ»)Gc¼2dV*F~”ú…!£„뮲~= ü7ƒß+xêÕ?¬H;oú©ˆ|N:Šµ½oBY{f!§MeHäZ¬bRã»9*þõÆŠ
+#'e«­Ó>¸˜í¬óÐê'µðvç{!
+™@𙥮÷w ËérÌPk0䇔ÞÍ۬ƒ̉QÛ£ÙQ˜­‚(Ï£vaIÁ&QŸ|Gc’ ¯\{Ê5ºÓ­¥QÆAJqß4cÉ•GIÆ!q]ÿAFÐM1¯QdWЊ£ )eé¥ô·MG¿„‰Í²”˜’t¹OÓ_Dˆ<`‰^Ž£l“µu:ŒÊG£:›d<‹ ÞïÏ0x¬W¶·\%Ì¢}(™
+˜'½{Ô=Ú j>]†“¾BH5‰´<>ê“õŒbM·£¨=è=–Þ>| V ÖsT„à}¡E2ú¤Êšàyyæ9/çWµ\넺u©ÿµ„{ÉSw&a{wÛJ½Ø:ë0n¬ÄZ¡7"8Üâ‹If.©Í©# Ç™ôAf•Nßp<ˆëDiæ“üÒæm(¢îQÎUd}b
+9’()kñ•oè„8ÃÎa<’òãÑYüfч㞳î§k'ëZ+JÍ$­cm>=>¦êJSíkÙîKjbì™ÔJ݈ò2(Î0´Õqjé¾”LQûxûéP’n9 }纻Ÿ$KÜüÆ=CØD%'§ùÔ:Žâu[[+¢»±Lwv(tÉuÍg²ǏָÅÂÀDMëæoyƒô³Y›G¸Çk®•±MK»Ö&>Ú`jêù ÌltˆßõhpJŒˆãÈ—òøº4êC©kiwœÛ³ãTÇyFQ#U¥ w=â¢;fXµ÷n£*óÊi •M€¬öVÉ–ÛBsoÜ-ŠsD=7!
+úu’´_û¯dø¡(%>˜ø(ç›ý¶%Ùo{(éÆ>&%4‡‰Ëñæ;¢”Š`yùu›Ë_á &%%è ôÆýÿ:Êj'®äf•,Y´«ÝZâxÃ…aËXš4(At«š›ëHéM~˜'ÂïÔ‰siªZØû9ó.êä–hP¾œÀ^áo4ÿ–5®æò²ÂºÍéfAoqôï"åÞg£$MÁ¯§È&LØ?Ñ£e £™*Ö»„Oˆ1,#¥Å¾Æ£ÂÒô9L"n]Ó繡þX6È>fO^<’T®a?‡ÜòÍÿL² ǵ7%ɳ&,m1ÚÿùòÇ¿¾,_ÿñï/ü÷ ?ÁÐ4mîfzVµ›ƒ<gûú×(²¶Äª;jP‘lhHŸD§
+ö¶€wÁagäÿ¥äg Æ:¶üýÍwê•ã¾Ë6¯ (´ÞˆyÐ^’W»ÐG<_UmÍþ·6Úi¤à’$°Ž¢ÎÎU]ø¶‡X{)óF‰Å½"¶lV¯@K:¶øÃ9Ïc§0Î1pñZô0r_(ñb‹Iúí¢OÛ÷çï¬èK …ÙÇèQ²F/{r¡Øø×›¢zÄùïY¡ëkJr§°`üý(9i25²D­Ž*G Jþ%À²àÄr¥‘?ûQf¶Bž·ù«E|V2RÇQ"#*ÝÛ5^#zñŠÇ6
+6™ƒbF§?VŒs0/kïu9Ÿ¿¤{R$ó³>ÞÄOü|ÍJ¬×›E›Æ
+½‡G½BØÂã6¢p H¼îb^*{]ÞT|˜Ó÷¹uÇÉWkÄãiÍÿÈÁÑK@ÐÞ0Áç’—:ê,þö>,êñmÝøjvŽåî*J[´†ñ3kïýëMÑÎ¥tWÙÛ”¸r¹µQ§à‡5®Û|Ä«ƒN¬£díq†BÏ™˜"œ¼$¢.ˬY@ï‚齆ÇÊ
+íÝg²ä(Ùêd?M%[2ðï×(!Y<Bѣͣ¬L™{hSûZ+À”—սǙܠ¬·¢SØ¿á ¬þsI%ÿ&!4Ö}õZÄ]dV¥óCÕbÒT) £eŒÌzõ’CÌ †õX怫æÖe%`K\ó6­^L‹4]}æ(Kžëÿ­ÞG7XãˆHƒÄ…%ÙýåVŸŠú6„N¬Ä—y›²H:Û\Z1®œ´Í-Ž%¯J‘ý rvæ_ŲM ²È¸ÿev[ÿLL4vÃç4D–
+s;’ Ö8Žd~å"Çä„eÐã'Yuö~ÆHRѱNv]·¡j°Ñ‡‚ ­éV¶r<|KǶ4T¹Üw=b8¬è~CX4$´ÞN³%›µw&r?~ !7ñ5& QË2
+â¾_ƒ6#.3Lý¬9€ÆÜ üž "a^ĹmoùÃ8,¹®ÊJú’ßèâG ÙD¶†­Çˆ}^AHd’5z,:‡¨oŒ#‘†ý%Ÿ±¹›)ÁWÂÁº„`MLÔwõ˜
+–ƒE{=ËÀFQ,´?/ÿ\ŠSÚ]þòëà 'Ž¾Ü”m¦ cŦŽ~—?æF$%Ô§J-ñÇl$õ‰Ø‘Úð’ÌbJT‚½‹“˜^„ ·SWl/dΡäíÖ%±jÆDÏ~äþ•ü˜ì6}ÊGÒ”$–²˜
+ü|#ûµ¾äÚ$™{Û¼™|R¢–yZŠGáð厇”t?Ši›ŠˆÒ…ú¾¡Oâ6ýG2M=ŸÛ°*K¯côIJ€’þ}ŽëúuÁ²ð‹Œ4£“FÐßÇ=@Ÿ?¹Ó/¿zuZ#9 àýÍÕ;ŠDb…äl¬Ë͈ËÈ<àPÍ_×Ã^@Ÿ?¹Ñ¾8²PfÊÃÔÞñæâOj‹ùå'?¸oU}"!MÂÞ±,?
+qc¼·†vú!C]LÙ¬Ž|áVaú€p1]‹²X‡Q&„°-¦ &ba*Àwš8w@ ÜjC”rñ ¶QbmUµ B'5~„_&’q+{óͽRÜbéÍV ©ôš,qèÌ;ã÷E×uòÈ6 ã¤ne—ÃtHcóI;ÃýÜÂ4…±lQ`Ò#ïCÌé,÷ôrSÀ€@ ð ŸÁwr+®Üˆn
+´(–Œy.ô#7õ)ÅIX¢«„§ÎË«/­l2¤˜†¬¡)È.°¬ Sjo>IÈîÀœfç2Ì'Ž†ßsDa¨Q©|$Žd<°@½ÇAHRu Ñ’]ÇSã0¨LTo!‘x‘š-+DÖ‡1I"¨¥øzìÕQˆøü–ÛA—=÷#Ð ÷|þ„ œÇlb­ðœ†7°ñ†€©m,Šœéíx€nÚñ8î¦ßßi_}Ð-4—/wöæês-ô0}onþ‚¹^üõ°ëÅ¿½‘_\¹Èìƒ}„ JQ¼8Ž[ 7.¥À?*ô™_ÄÑÔ| B\²6¾œH†UÈ}اî¦TA¤«Á5pn1ã’¦ùJ2Œp)ìÕ„¯š l¢,‚`ZØf61­pŒì6Ž•È»fuÈ"‚±‰r+uC`±¥ h¿ÿý熩°Á «Þ¹¦—›_«èOk^@Ÿ»<¥Â/ø¹Qn l1KÏå:O–ÚgMñ&uÈÄð©xÆ€¨¯ ¾Iº¡ÊÇa1r@ÒþnÐâ¤Aqȭ˿ÕyªF ï.³Êªvçç;Ä°|
+qþðÄïÐÖþµçb;ýÚýšsíØÌÁÊr\¬ÖžRLÉXœõ$€1ÃðpÏ›'! vJœŸˆwÌôÿ˜_WL‘®Cú8–²,ˆé â5&‰a%öÔ裦͈™dÊJg«|ÖØ|;L®œÑÉÇ0o®°Î3À•íÄ”]aì»´†Ü’?œZËüQภ$ÆÉô“et©µ)Îj5/}R"ÉQŠ¡¥»~‡.`®—Á2,ZܦV¯àÀ9„ú'ˆ¡‹ºâM-‹‚PŸÚϺ°¶ü
+Â3-j#óY&o›Á¤˜v6·ˆ+¢Â8£î´·yB:–‚e©£-FŇ…ÖóyÇØÒ›áÌ6öm`ÍÂA´% 3„]joxÖÌ¢9¦b=Ý~xÑþœD:)^¢TLÂëß!N™èyZþ /@×Z !ê":L˜$cC:’‡ÁÇGcÍöQwYü–•Ùê] ®MlÆ+ùnÓ¢‚Ú^ÏMŽZ_}ÄÎmþ‚„µ@`Ø‘†]×ïHvùœ†Â@3m dJru„,:‡ŸsCÈ€âŽj2½hgǹô¨2~?Í®9õ¯4¬¿";‰ppëilDS:bŽc-•,é'#þûÏ"D…2ÍCM|f^!<Pj<äªÌ%
++K9Ô~•²bÞ»h™õúõ$Š«CŠK#?7ˆ>óã5ÎÃDz챑?Q#H{NÒ%*ˆqe‰ðŠÚGAøƒ(…™vÕßÞ tß¡FVN¦”c
+º bÖÞe2I?#J^ˆ,{š­PY8,åù °ýì×a†+q}$OX~Ž½}QÊì'ÂqcÜKÏŸÌ­ñÂ|ˆd ¯ßü*Ê¥Ò¹ Œ)¹ÊÜÛ!tˆ„Ê@Í@`NfÌ¡t7®`ƔՂ2r‹$¢Râ¬\þæzM
+gã8&Š©˜D³ö]…ð
+æX¡b3;žãôVu™|SŠ Û‰aÆó’õ¾£Pq-e”I†ìY¸í"¿À ùq¦„,®e¾‚ýçR
+I`r6Ä·J‰wRú ¢6`í‘aX96_¿Ã†À'ƒ¾XJõ®·âàØa‡ÈÊí#`vVX‚…šó7â z¸ö áÃ*›h®Ý|Ï}M%*žÁR¸†Ò˜æç=èqqEÖ¨I}8niX6¶òê»Uk‚ÊHžÃ ^ z`zª~Ú®ÜýÛ;o²V #0×»ï`ùh舭óø:³ìf®²Ï!Sn3ÆJ‚¿2‰_æ±,t¨Ìé•ÖüsC‹Ü'mš'ˆ,‹i©¢štmµ•çp­UÓ ÔÁjAäãþ~ó%±Ë,#Ø‚:pd‹ 4¤&\†»–CRóX¢$ B--}YùW:Ì”I#!ö7´úãe’WÄÐø>Aça­­oá­|ÿm?p°õ?ó·ÊÑ·J(’9HOŔǤ¥om ò24Kn0ý„PN§¶ºå-yZ”!F«ætX |&KÂ}š&AÁlÂÙó®¨î®ÒèíÏ1ÐQ›%zóËŽ {ÿµÞð!R Û¼#œX?šsi]E Ø—hAòÄvÂrÇ,ÚË)."Z\LíÞ€Ìjú80_±»§sî¿=Æè›3&£ýî¹1šøžas¾ê÷;óko ‰<ù±öÇý11P~àlÔ1„]
+r#eû¬«B/#ƒÐvóŲ Ê4&jc5-¨{yçee[v¶s<«nýÅK6±*óZØ4hq?&ÓŽ?u J!Ñ8Iæ~÷b&_ÎÛ×M”œ„yaXàX×`DüÉOɉëÅÉ7®îª#“(ŽëíÆÜ=+ñ`@-Ð¥èŸ&]€¡!Z<öU/ 6«Ú‰Êö„™ñpª¶G¡/8/-zóIŸ±6“+pŒ;_BÿÒ&/JšÖy•C5\$µžÆ É/¿Ÿã;4ÏÑédõ<B=…“êJï·³j™ÿÊ°r³1 ëJ”œV¿¢)Ãÿª¸aµ&À
+šFÖ£WT¥ð}/míë*êÄO{߶½g`[t$Ð%ôA ´Å¡jƦrcÏccµnHëÇ d”œ+MUlµ¼ ºßç#úÏßpBÏ(½s{ä{‚X°èŒ&¤!Ÿó!ƒ^åÅQ4'¾¿ ¼z#do‘”–8ªªh¦
+“:” Ó²{–¿Ò4o¼Ð±¾,cŠ
+BY"Z=&2Íl6‹ß{6 ºŠýÇËœΩ4 –¨êŠ»»
+C9:a„³ïQñm‚F#3ùñÃÀ„Q VH¶!ú÷s`jTä¨ iô« 4+Bˆ©qÉ°3pcÀH ’Äd—oæ9ê`±½¥¤ü¼›Ù 2aëš{Gpª‡´/ø”Z}¥õ–°1 Pk2!HR ´T Yb÷û&þç9%2p~dìíÁsž¹"8 ï…gPü«â£ªFªîZH«X˜ø`t‚`ZžÊ1Ûs:â¢Ñœèf¾œœ‘ ­,a»N¬¾“! f®›6º¢ºZ§²ËQ’YÒ,g:û׸¢a¬Þ´jBŠ­%B߶³kB²Þ°ú]–
+oYlçxÿð+4ýnxì/rJW¥nòZW®wÀI=½ Âbñ~Œ6…ý4Að‹"c“Æ›a®½¦9†&„F̲àÎñJcvô÷['„R¶Nê«26“H_j9ª ò©Øn €V†ä®¡ ø1Æ ¡ÂʦÏÏ<CeÐn£McxƒÌÖ(ãÝÇ ™çЖIªØ¦Ëå1Vcዳyë¤qòan˜hpç~s,» ½~ L’¶@n¬8èg3GVLV‚LG¯äT@d] c$˜7Þƒåm" Q4A}Fc„ádÙY2M·+E§$7šrR!o¦)±}H‹ßµÊǬÀ)¥¶¬€I›8ϸ✠üA•ϱYN 5qÐa¶@‚°X°Pñž¸_ÃL“Y‘‚¥™ºàBAHbµ5
+ÿK±hÍq¢ûœº±r6žšUÈA£ÕZ[D(Z°<•ý+ —3èí-Ã.‡²ßT¡M$%™ýG!!‰ˆt{ü«1…ÝI¯¦çam!2'gֆΈ^ÆÚ¢*MDRosMïq!¾>ö–ïH}î-îÕ™Q…9¦Ä²â¡zê5\lÜoh_r™ÊX„ë!>Ús²¤S;rwèZܤæNßàü\ÈøR~´(~¯Ä­™T°=n§.ë6¯*£‘˜à„À
+䲩‘šÃ@üyNÂ1/ŠXØ®%ÈϦ9OQÏQL\o}zŠœ~Gö[ ±²âéŸúøh±hÀèßôßr©Óºê
+“¼‰Eocù˜7¹Ag‹*l7LŠ•`þ§àÁøúP§ d^u–û8çlšã5góQMŒ°K´™ôÕæÇ$ÀƒP·¾—B}ì¹#/N[êÚÖnkÍœ;'„[Â@=ì>'È° çuÆ‚ôí›ex+ˆL!£Ú¬µíÏ
+£À0Ä*†ý§¸íA©JDܦ>Ø’àåá[Åm³2Õä‚c“#Jx}ö«GPeÁdhËm'%·V ¬¢±¡vR)¦ûñ¶úÒ¨ÅÐÆYv|_ÞÙòŸÇ¢Òýb¬˜˜¶ZX/FãI2O vdzÂc œ [FrH|ˆt»íLÒúÉlGªiA a*­%°@Bà†r`uŒ»­Dú˜Ÿ»Ÿ ÅØ€6P!sJtÈFX1ÄBÛj4ˆ†%09ÉqLÄZ&þö°Ò!+ØkIƒ}à–¸)â™W;(½ö‚yœUBbõËmAÔäÌ&ÛdþiU!k4±³0mÁt|˜¥ºÆÌqaXñ*ðlŠuwrîó0ã·çÒ[
+Ûäˆ-cxgn ©š(TÙ¹ù˜aãë+IÇ×v@ðL¥óˆJJ±ìYÇ|u­’> UR“E:&¬"Dj‘¬ß?
+ò¯ÝùñÃÂ]ÞÛ«CªTEïñímÐ1xÖuo®T`NÕ"JáIØ×RRÂW0)¦µA«$ˆ#÷x$¡X† HHYóˆAvu{»«q„ï²Óíïêwñ \w­ËY•°W¿¯&²Ã¸%.<1zˉa«Ãà0 ükO„èaœær´^R_
+bV‰Šæµ$=î¸
++1õ•iÙÔ
+bË•VzMÈ͉ڠ‹µ_sq¢vT7×fgçâþì_,¤Y¨›µË}=Æê™ë[ÌÖ»Çd¶ðW'jÏÁW'úÆ8}Ì© '¯GÁ2¶U!Òc@§!šŽÇla\wx7Þ4£¼¾ç±3’¨IªJÛöe<«Æ) )‹¼eë«ø}
+ä=ËaÖ(Ârt|Oª½.…’¿$2)Ω&\M÷t),ºo)ˆ<¡ÜÞ©j=¾0Œ(‘Ù.û2{ê‘Ad²Ð'bD<Ësæ…1'rtQd*4ãD7Ô™ô*)äšS×9ÿ1^7É‘ãF€Oà;è
+Ip=^ö-f«û¯ý=51­B‡å‡=š,ÈÌ÷gKq¯ÖhÕ”›Ò887%[åÌIÝõhÄãkwKn ÿúϪ¨ŠQNFïlOEÅÉfpRËž”Ën}Ã
+31¸F¯éà®ÆÓ›¢ÕK&m݇˜+‹þ<Îl›_Ž­´OŠŸ¯Ô®À®„£®;út¬ƒ©•€¤=Ö†ž«"%Á˜ã¨ó6õ1³ð\å‡Ýs}²3:ðÂ)uúÁåùÔÉ †Þø‹òO¬Ì.áMB‚éµ@ðl~@ TÓÀ`Š
+@LÎ^ü诼j<ݶñ'½/Š¾F@¹ {ú}hV™–vjO¿ºÉ9ªß×üXÂÉÕ‘ÐÍÐSVzm®7íÅl\çù¬òØlp•Ë¼„ áßw¸¼äÈ=‚ kÿè}f›‡hØÀ&4Iòè‹ŠN‹áhc–õ1t&æö˜™y?Ú¤8¿ë)ÙKeP&Zæ<FԎ󵣚‹ÞíúþzøŽ9@‹·½+ñ+lC<fV#;1”ÔÃ9)‰^Y8^¡y¾uG8Üûç[Ñ>àÙa¢ñb_¨¹÷ëN¤Ðò±ºñ·š—Ã;%ãhmÊääFïë‘uM®¹Ý”ôž”½7<3Äs6)¦¡õz%šóÛši¿S ›^/¤Óø›ã*«s¬•­ Ü„çeðaÞ8¼Ž5÷¿rB¾ûäÑÎÈce8¦5`dƼhìŽþµ,Â¥ýlÙ¸Í;¥9þ]§B?¬©4Ïfá´’ÑüZ
+ã·¢¯Ÿ¨gD¶|ü÷?ý¤”ሾoOª^ºÔñ’¡UÔŠ>ÑèãžøùV¤„?è!ëÊL®l?‚S¡µþ d
+s§(E<ö µævEoO‘OÞ$þ6Þý£§Ý@—ðÂó2rÔI¹<3IÉ%û™bcYö§Û5]Åq²ifÛ¯ÏáŸî ðx,ß·¢_(²1ú÷´;EäD´dÀ®gó+çêR‘ðT>”ì<=fáÉkýÒ"žÒŠ=%Õkò&m˜OÏ=âó'§?×':²m¹`}M¢ ðª&Ë“>÷Ín ûj¢?züãöì¿ËlÔü±´¿Ùš±Ôÿº¼Mªÿ­$ÓБa7ûëåÀìå}nè)ø¼Ê>ˆ³O‰¹qÍ´¡Ög74f³/%¼}/¶ºG/°<àÖÇÄ«—zíã9—%Š•¶#„j]5™†c$É5ÉwUô¾ˆa›ƒ¬ó,×l4óóDÑòt{=ãfç,ð¨xdÏÃßÖ™ÅÒÔ#}í˜!À ûZBçôÞ%¹îŒ
+\W9VçØvƒ³q’åQæe®øÞj÷žŠ«æuÅ{iOIÌa5Àj[Ÿ/Y€½°Û|w<ÍUbÍ· eáèìMÔÄU5ò{‹œŠÛW°Îp4%v!V(9ЗEvâænz<M€¾¤ŒQÑø½vëѳoEô둈ìû@ƒC%@wœkJ¤wíç•i /Ú¤ý^ÈÓßz:ÍÒëa?¦.ß™N2§¿æwô;Ù_±VðC\ë5¾Ä1„vÚ¸(_Ò ¦¢àÀqqŽÕ9‡ÉBŒ[{©ò
+ì¸XÑ –@—C¦ U{Ñ@!a»{‹w…\E'~I Š¼Nô9UÙF2Oè±-7Pƒ™þQР6÷‚§¾hRÂàä6ÊR/›¼E7·2&jÙë‹
+•]í3LG¢t—R>’w
+ó®´ÛÔéÑêžxB‚öþì¨\þ5 Í™kŽ` öÿ°Ën~„RËäÿvÆ;s85k¼,9ÅRÂàn/8¼a]LâËI:¹Íž|âJZ™Çø|°õ>Tx ¡Þ3Qùik&ôî“CßTéÔ™Z7Øê¶CgŽ©¸
+YúyŸôh*Ú-JtcLŸ¨Q“ˆkhÈ®{°
+Lø‘ß~*ö©ˆQcŸ/Uj—f†m
+}£ZÛǸßTõ·(™1`¸¤”úV0Ö!ÿï>pM­¯T÷ï3²„ë¨}¥Ìø ·CWhk¶ŠyJ*Ô£4
+{¼„%“ôî÷œï1bä±ÜÇ~k¿‘ÅŒ§¹fJ¼¤€ë‘°E À$VÔHl¨Ñ•ãzú}µEÍר!_ømÛ®¤–QtFný–Xﶖ&û|<€ëôØ‘'Ý Dy«h&Ûÿ”Ü?§²õ~¼ZlÍ­0Nºf‹ å°¹u{ðävnŽ¼šì÷Ìr ÊŽ?Ìò·’ñ)sD¯Öãn«šì̉£éXøu™¶F¶ÆraÛÌ0óQ9÷@˜ýñ>1†äü°ç½îs=
+ŠÀLècí.Q/}Ú9ÿÀ¥þ3˼ã”Ìó8_A' µá0Ó‰•]”0 I‹ÈÃJ¾¦Äúï,/¯Ž*ÿåŒ×KrܺÐxZƒ$
+ª¦\õ˜½ØÃg°B! |îÅî!TTmjƒù–;íl[Nƒ|¹ ]©{F맓Sd(_¼‡vZ.’Qj–qvÜ™uæ²wÖóîvÊ´å¬p„ ÍG]ó1¹$±ÕNt½÷Ûa´yÞiÀ¾÷Ú 8ü^àa/üùNÿ}§_ÒZSZkåOL—Biï™ôºÜ¯!fGç¸Ýicà>@HÆ*,ÉwË]
+OkòWñ<Sc?å
+›A0½<ûçT­ÄÌ-ùƒCçÈÎçpKÁ ÛÉ ¨(€ yoWonP2Óç.oJ±'ƒÅæ_%&~{œ‚¥·>¥ÞmÞ2ô-œ6Ÿí¥¢iÛcEòe ‡¼•0ªníx.Tz·¤=¹‰ã>Fó5z¶‹še-çÐ=ÊÖmŽáe*‰“s=¯ƒâˆÇÞG'j/œ*2m³ù·}œ¢ŸÍÂc+G/\‘Q-Î?ÝG¿í|Ý1S;^[ý¥)Ó¾çï*KîàÇÐm0aÝb"rnS¾ zˆÑvß½ûí1æÅo²Mj‚KÊ4òÛ-fo‰ààòq[‚7ÃÝNN2 ¦w`¸AP¥n5,[oŽ½8eDYãV³÷CÇ „<h ÁÐñ:® Ð}©S8îÑK<,÷ôæ¹³n¶#&MèxîÜ ùÈŒ ±ÝÞýÏöR¾ÃÁ"Ø9lQ–Ú•¶•L*êh l•Ê®¦å<°ÜͳMûLðHÿ~?Ò›åÚ27êÌÀ×åÄÓÎ3R¨KXî1äÕr0OžsŸN¢ý]cúmþzöÞ`»oÞ-÷ß%#ÂRw¦Š)òwƒ¶8zÉ©–(Ë„¦.™Zý$d3?'N¨” âÕ5’6¡Ùà•ñlEn릒fƒ¾ä]rÜ⪞¾tЄu7â2 ,¼1Ç$i^Š©Ñd[“Ùœü¨[,:V“W¯Cå2ÎZÙ㥻`«N=[nÉ:îìNÈ(cn¤YZi¼àvB´ÑS×–Ä›ëGηM}+¦`%ú<)—eÒ÷sæI]s…µ.…¥˜×1n*Ìä½ 3ÃDytë|²ÅÜЖlµþtræSÑç®;±•EïçfV„
+(è®n¢u¼œŠÝ/ kõtÝ«kí[=AŒCËõ§ëÈz§ßW½k,o)_®·ƒÈpw^ìr­9s¹Êg zt&†“ê14Þme:lÍ:hH1̲8ðxhc¢Çª­Õ:#7yÑŸ›–}_v?Œ×‰[“¤£Þ Þ…(ÏÕ G
+~TW½ú”—‰öN±íõ8Bá3éûô${¡‰ÇT,s¬ÞRß\oŸ--{Òfûm;¦è|IÚË'!R7d÷}
+|£ç|>¬Ø·ö
+H‰Œ—AŽd7DOPwȵ'$Q¢Èå gÙ[Ÿ 1³ª^Îýç…¾pU*á´ £«:¾$’Á`°º×î#[»ý9J»—9¬Œ>=G»õyŸÍf™Ó£ûR[†Ï’³º âuö2jŽu\>ª%#›ÅíטQ¦YÔÞkØƘà‡â1»Žéc ÎÌ:cÖ Ò=ŸõÞF¼€¸Y\4G±ëªhz+½V~¹Î!ÜУ[k󂄇u#ìuјÔ‰Ô¼_€>gO¾ïqn´’V8#…±{á€9k7ë+3Ñ«•¢“ÈÖ©½´ÑÆ0òü<yZ+ÍÚu“Ý›UúÌ•½¸{ãboÃ{©vúh£÷$åÍtNŽQm$QmhÌŠsëy¯V“˜øÌÚ†Dã…sæèº*ïVfBˆÙCÔ量k…o]çXºõÖ/ôqAH§ósÚÌWQH7¹Éaû¦gŒª]àH˹ŽßZï0v 2¢Í½9)¤4RÐÉsÞ1›ºV˶ó7Ó¬e‡ƒ½äÝ¢D#´Ê_Ÿ0=à¹§í«¼Ï–¥–1(d‰¬ï‹ù¸AႦȚåpƼóv§Nš¶ßÑÒSí5T¤Iÿ™Ú ZÙŽ‡—SåP®V‘üÎ%bë€eŸCgfQAq¿óúsðo«ýÊîì^(a¥›ë ˆŒçÉA·Š v˜8‹ÛŒèsx½¨GÕ äÄœÔ!Ãlµ\%n'‰ÉÇû=p¦¶Ùô¤ÕtÖ£<onêe­¤–19=k‡¹×{½ÑÎЯ[’´F–ÂëF©Ñ‰Ç‹b~,ÖæY²ŸÏénT¨ ¡ €ÉUI œçץ玪×icLî÷ÝàYP«ÙоC‡3š[««¿‘žZɼ´pCñ&âÐû È@b\™HõüïGïTš”ƒô­[ˆç„J¾ß~ ÄPB;üòÍ ”Š"(b»ý<‚ óŸ;”¢=ÙºNÈ…oƒzæŸPô‰§¯{ ¤èi~‡ö‘c†~£vW æj²zg†P
+#n ö0ô&®søƒôÉ!/M[î$Ò]ë<b_…¨ éjIš¤Þ1L@¦ýÈ<Aè
+6tf9õ&%ëòoÛ«Aáʘ«¥µc-€ ‚ÔÓ°1Uê¼­acùõ
+FC]w-*º,¢¶N
+Lnô$CºÔÇ°Šà¥ØyŒÏFž–0#q
+ªMˆ>Ø}¬cæ]óo±½RÛ‚‡tß ncáÐŽÁü‹¥šPôµxøµ*Þ²34OeT|8ÿ)'öŒx%LÇü<bÚõušŒ ™2XgzuÐç`.-uxÒ"ÙóùMA‹¼žLµ™Ö|Ö¢lÿÐV•Ð_‹‹ÀAµåh‰íbÓ˜AÀáÉ·Kü9Ž}‚Jdo{Jâ¦å™Æc5yŸH$‰É€ ë* ÚO¡[kã|žÇay ÿaX¡”‰«â©iˆ}‘(oû°œ5ý®1¶ûeâ6èã°m­0z¡,%]ÐæJÓWÑÖ`0¿Ôc£½€0Pú:´Ô5Š|ñ†S‹§0Ÿg 9'bLƘë5ä#u ¡Ú†@â©<ñ¨ÕàZ%T[$¼mF »P‘–iÖ®°iUHÁ<aR?œ°Iøv¶ÕSrñ%[f+—6b3yíd1Ñ+VàжS·½àà\0c¥W™ðUÌ¢±0eõ´e^>ÑϸSZQõv^‡úÃÁºË¨}e)‹Tê´ˆÆô÷b1~/Nç„HÓ+ñÙ·µr”„
+eD2!Ɖ`ôý[´*·¢E,`Ö
+œ÷
+:cˆYŠ´:–ñ'±þ(0,†<t½ï©Ó¯Ët9\o#ƒ/J¾(œ}êYô¥Åví>‰¯m¿ÍˆH’•¬„¸† ‰ì§n!­ÏÉ‘§9p6ðí Ì…‹Yºs“(Ÿ)4¹xO©ñì?æšþÔ-·YBWüQDáÁßB°¬%°÷Q­n.öŦ®N]~Ü çM…p+\m%´|i¶Üfœ¾$ÇUZ÷ËX™é» à™;ª6muaЄ i‡@s„tˆºk$B~W4z
+â
+Ÿå„˜Ëõ0ÊƺU.¿2ØYÀÜæ* œ­güÐ
+kbFs«È¿Û¸ïø¾üö_æ9ðBd%ò ÄUø5¹œ8 ©J4~\ASʱaa¨qsòj²ó]~`ÈcÞkT[’ÀüL(bƒ‰ð<nߧ%ã–ç„ ë9‡üU7kã,!«†zütLü¼.±ÏQ‰}‰¯ÈÆHøû‹sÐ9öÆò—°u‹­euXáµÌ¢ÔX¯hÉ£à nO-9¨A¤6vË ãø>ÎuØÔ!K5¤[¦‡ð
+J
+öp]žñ€Ã‹áQU¢W©ø}¤ €/9Ô­Žý£x%ƒÏL¦y"d¬møÊ.£ 3®m AÒkûò¹ŒK¦µwWllTU¨$>­²¦Ðª\T¸{d·Mr/¹çœð$Ú›“Ž»+A­±Ç9Ú?ƒÒ€3d\&¦Ò Û©/iøOº)ùòB©viT=cŒTh‚Ì¡MF?Η~)U?>m\}7"`t£½pq˜˜D~ÂxSEå?9‚_~ç«%â\û€‰­ë…µ"ü…?ÎÏ¡#æ.ã}yA b\cY~¢0­åt\ßé/¸ÇÇ_Tô¥E/Š’DÜ?+zwQ».ÇÒT@/Ê°˜“‰’…r}áxšxª7Pµ»@ÈoP’ó¬únyoLÙ=÷  ÖGnb…=¾•üy¦©ìÈâñæ|qÿ^j#¬2ãË°¶NÅÏZÖÞn¤ PxýaoøÝT<\ܯ@ü‰+ïYï€RÈuý…‰{qo€6ñmLY€§e8*hX-Ÿi%¤ÂåKþá”è´˜ýn> ÖXĺ5ˆca ÇÔ>¹iÂ1>œÜ‰ < }£g ¶Cëõœz`á
+:b%à|I•UN‰D‰™"<£%¾£3‹=É!©…ç°£üm‘ ’ºü6z"mGÄ :Ü'SkuìˆÓØþ™(2.
+­›1\O—á¾N|º¹.ã‚J¢
+P|žs3B)ÈlÇ"1çP)@gC´gïXžL.."ªM–`5°0ãð£ôj‰Hù`‡­5×sàY,(}Ô²_(bÚà4ï’ Y3 Žê¬÷Xý?Ÿ‹÷é „ÍqÆp]rçkñf^ä›n¹âe%ô¬Aû"⤕
+
+"¦jÔ´…#Ié8`—aá\žY0îEÎÌ P „ÂÚ<áâVsY¿×Ovt­2©©
+<½- ô8ùBUÙ¹9Œ‚#1û¾ÍsçxúY­tym67áŠ<ÓËL•à`Ë›ož)ªâN„J-ß¡ úKò¹MA‡bÕšxh¾ØkòeNSåL‡"vÏønjöK-üa‘Ëœ
+rç΀„CA\ß½9²ðMüËZ†•4¹ƒM´øÓJ*ðIqå$DòÛÄΧ¹t&é&häPæÚ¸£Q¥Â¯°aßÉ
+7 ‚þšgó#Ä™òªµVú ‰‹oîŠÙÎÝjî\.& nÉ?.â4Ø–Q#ÔHù롈OÀ
+D´vÀKmRMÙRJ¶®Ôpý QÛZü^òZ%ø¦Z•™fù!bf8ªh’rd ¾­м¦œuú$¥G÷©Ä@ÕiÞ;Ù©¿è0ÝjAº¦;ÈwÒ¥$èÌ©ëNç8\TMa3Ë·îq£!¥ÉÅJrc\€Ÿcö7¢<V˜ØLKÔà¤{O±„¸ÙR>$`ùúÖ°,ÊÈL{@¼“™!XtË-ÁQŠó°©-kïåšA¤`lŒ÷"´EâÒÖ*çÆFæ³Aœ¤,ÿÝÛµ~íߎÝ'pu€ÎïNR`˜ $’3ªïHmKêd+ÀwÜß‘`²è}A“|wŽ”ãö£üE‘øCžyC „ýCFÊZHâ
+æ ƒlöB^÷eŽÄ6.DÓvÉû¶¡_ìs笊`¬…¼.í{ÍÚÈ„ñ=tŸÄcRÓ<Ù ;)f> SŒp'#<y…ÕêòñŠ™Áž@"Žï'V£cüã‰ie ´¤e­d§âŒœêŽ Ô++àíÝ÷i^JÖQ|F‹^à°ê~§¶J{£\ß – eMEB+AÉC4¯öQ™Aȸ„Q7B{À&,v<ÓdP×Kqq@æÉ°We#WÅ`ºì Ô‡KÙú‡q©¯â½¹Ö—[TŒ‰B[‡a¢sÁâÎosF§øu@µûåY±’–—,võ,ü<¤$@BbçÀU4™ÍãËazspTîjùËDU*Ðd—!×¼/Ke’7ÕúI°¡o™Àz’çÕÊ@^¥ašÄ Ƈ¢ú‰‡ËŽZ䄱«³«*H†ö—x+ŒÊä‡$§;áÉ ´ØB{¬‘u¯R#¾:i=葹«‘•kì8Kýé0.9`+9†ZŸNcÚäØåæÒÃÓ2ˆ¨Ç(~{h’ü^Õ‡YòèÙË×O'Ó?þ¦4²J<=‰Ý{r¶öËŠ
+^&´€VsW;b(é›zvù5¢NØTm6ÃÛ›Í?¡v
+Kú#Æ#Ì´ Ë`‰Â×<ýhw‘Ú(% ÏVÂ>v%ÑÙ¾»Ã5TÃ;–ó¡§$•@ÇÀéVxÅF«òçź ÏtéUu>Œê#×ö‡ƒŽŽˆB/üA¼y­…$*‚Œ‘$ÏŽSyžI(ýØ1<RM©ŠN“k'nw©᧲mI ‰`#뤺ùqòÑLX­·ï0*´¨”¸KŠ2î%Ž$›{çÜÀH¢AÃ+‚”‘(î Îmî÷"‡p¢tŠÈæ3^‡ŽãšÉI2LÕÌQ”yì‡_ÑŒ@ DëûÚ>Ú½>yòÝIݧî82àÔäÔ oüî~‡} \…ga²Úq‡Á ETDS‰”ŽN5þn¬&1ì²sû(1$­©·ýðzŒ‚¡” Ò‚Ù¢8«,¬0¯jüÈ¡´7uÇ8ÿúË­ah ï„­µ=÷ãGEÈ7âE(×¢"Ž]ý¶µ€"œXŸ”\/
+Q JÍç"Mí!/ú¸/õF3™îÝÛYJºG=K¿Ü%žU.‹1 1 Þó
+øïjV«L-ö›™ÚÇE1Éì–PqGL`¸„„ÑÑvQšB0ƒW6èË5ØO¤HP
+4Q„Ü2Ìãì\‡ÞñwilìáÈ’$ƒ´¡7{ø+H¬ÕѶ&ê<£¥LËÎóª~÷ehØpõŽ`™+‘RºF˜=Ī%Åøh9 )vGhNT6̘Pí”BïdåÅÏT<wS¾ÊàQ?þzËŸç²àQS¾</κ-—%NlU:T1©!#ÉÎc6¦–xrG6aíyÛ)™Ì³ §¼¬Ã­ÉÀÞ#üôR¼{:Ž‚Âé‹C‰ÜM—‘eÇ¢ý†µ€7 &&„<ÓÄ!ÙƒŠ7Á¥äÄGšt‘Î,c¦))nší yŽÜ4…òÉŸ|’‚˜;—ZçõøÔI9P<<ûÃ@S9ŠÊî1¼Dm2tS–@|‘•ˆ¨1–˜Hv6>ÚÐz•ÙÞb²zggg¢AÑç3`Hç–9’½ìÞPX¿ Ñ–üII’IŠ.¶Û{Î4m®Ÿðéá^êY³F¥ÕoEQ¦üÍwèy“DŠNÒ5’ ÞkVèN‹ó¾ê­š³%Ýfù4,dÒ
+5V׌ԬE‰˜!2lUdBðÌE$e$5,kêXÌ¥±Ó <̦‰#›Æ‡a»ðÓûvÖèP˜§õMÖÞª¼3ûQCMk~û(f{Œ&]’… ‚ÐïÔÙÖp+ÛL0〗6"GºÛxª "®pðÇ0.oÝ-\Füƒ?µ ºy—!Ãc“ŽV¿ZÞ¬–pØwºq Ë
+5FÑÈ"mQFš-Ž8þ¢Ò˜'v$Â1‘q.#7àÏVd¶¿q ”¡S½xDTV!ÁÎrD Ï"þ1Ñâ|œŠøÉÎzCÎo97Va[ÆjÌ›èÇ›¦í#oÞÝ<Â^«Lâ›vuZÐþk •Û@Д…ï2ï¾9ø×$Âc¬N‰¥Ì¹‰tk
+‚Mô'½Âc1×Ò«s ÁR’ŽÎmß©x´ñ:·!~4Ô6eÙä˜$?ÎÌÀðØ;¤¶–~CwÀòcÄF¹÷`ÈänÊôÑÔ+šVŠßƒÅYÔ‰9oÅ—ª›:®Zwõ@ƒ'ÔŒµÞÓ¾S Í yQñê"Òˆ©¼­C^ö ³“2'úQÿ½”ÇÈUL;…ch§5
+ï!ù*ý1 aL0РŒƒŠ¯Àû)½ƒ¾÷#P“Ù‡©?™êñ f6ÅÂÒÁiÑ"ê6ë¶C®…)«nNуîçáBÍd=a“tj H«Àv ½÷
+…ú-úÒì;p4³*‡¸p 2þôeB$´Ä'ð»ä%æ‡ Ai¶ö &õaµHˆ#“y‹!Úì’SŒÙ<Tžlì)òmc?yÖÝ®’¤ƒ,q:%l’ÉãØÁvQ›$ÍÌæá†V^°HÐAm¯K\r‘A=Øó|…Qõ´!E[
+…ᬙëºÁÛ˜yòžòBþòy<ýa‚9ÏoÞƒ(rÁÿìÞëq?=ÓA¼VϘC,DR$,KÖ®Àvþ6›„,´²çmüoštI<½È¹­»ZŒÛ’4×eGb´ˆ.GP)'Û¦œµIŒ~¶ÎÍ´^SN´¢†Ì{)ö™]$˜H]iÞ2Ö¬2Qk¦vl3u'8[ C¡§`M¥¦
+6|e®ö
+y¾”!„÷‡[ÿ‰ô„,Øôdˆš;T _íá›3ZÙøV€ñ€@¤þhÝ…‰q"`M7÷Ñ>îSÞÙU;œê.Á^E}|ÞͤÀGøYºnô
+~XÈ+\NÖ<4mþ“‰]!šƒ­àÆ¢Àª.† '§ôAŒÅ¥¡ÐùÜ׆ª‹1Ù²øÝ,3,‡…Óp/ð×úeÙJìl#Ï´àʼn¾62p´lrjüg%y®üÍwpÜÅYÙ…^†‚.à°ë<Ã)Ç ß'nåâ½NaZ«•ñ\E,«|se^ò)ÕH¶‘¯›"~’/–qïyÞ7² `Ó¦“J_¶öò8¹s—;óÈÄ[ðar´û,Êj¤7zÂíZÎ*ضà&ж'ÊÙ´rÛ_M(c€)p;'5­}" õ›m¿„É×^¾†RfUØ<ÿÒÃP
+dlœOâÒLÖí±‰ßTˆ2F§˜Abo([K)ŒÖý(ñ¸¢žÃŸN_&–VæCMZK3ñDÿFÓº0
+ÃcúØåÁ€g
+~Eÿw™A³—Ó߉Õ#ï›a¨LiæêýåÔç]RgÝ PÍ-ÆÇ3¼E}Dîbù MÍoÿp ‰¨ BãsAWˆµaÛ`´›¿t~M–ê
+UÝ zÞ> ‰zt5gëç ðTÖcìýÍéؘÚWÎSùdç7‘¿Z)([|- í‚d‘:ÆL
+ER¡ƒ¦#TÐÄ?`µ†c©–ﺈ‰%gÉz±÷Èâ¥"ˉA±lX<ù3žRõµ $Až§•”]€'ù[Ôo”üD&´s̳«…'1Þ«D{/¦˜0H¬nÒnã³À[ïK‰*ÖA¯_ôQ´÷›ªd‚vVƒŒ’Ì”vÆ›Å|@,låÃéÀÏÇ…L Ë"øíÞ±
+†G`ÃX˸…aÁ”m\†"FáB(|Mß!"µ#e•À‰Øû¢±€‰[F苾ÊÜ @”ˆ,˜0™“·ÜˆYâËF­5_ýšÊZ@ B¬*)¥ØÎÁr5ØC’$!”` Ó€H“약ià¦ò at““5ÁÏ``OkpÅl’c¼AQ*
+â,®B¯ëÚE6,ˆƒUEŠmA"à âÿ
+DÎŽ½‰3¢çy• èY–ÙÐÛÉ‚ %ÒDF\Òª¡?!q>bõ™Œ Š|ô8;‰ý
+ äUІîÙ¶#—“ì*ß7öwŠ‚„LR³£&Á*‰z˜ÇpJ X
+yqäªÇæ}ìhìÂ{‰14à”ý`UŒñøh=Fµä}ž(R+Àv¬£ªû»Ï~
+œbe99fνì”O®W…p{¤Ç
+N ;ÄäôCD4kõ `<‚¸’}˜íå"N[ÑŽ5Å_ü|R„öÈ.±•ŒX%²]ä=T©l'ëñÒ|R –Ô‡ahZÜÎ
+á[dVšZ˜”?ñëØ/ÂÜÑë¿‘3 E˜…€ ì2üîÀ3!ós8vôTzÀgS÷>5;
+þv=‰`¾|#¡ý÷ãíËï·HRk†C$§e)ußyEîl¥‚ßøE^Í¥›J‚à³0[#¾‡"le³È•¸$ØN‰B.}‹8Z©E¬+Ö4ÉæÍÝü2YA~
+¨’}K}; W/yä2$7H5Ë vòÔÿŒ—Kn$9 DOà;Ì
+úRÒÚ³ô-zkß;/ôiLe²àènOXJ‘ÁˆàÁE™ñÇK“ÏP¹§ð8nda@¡‚kÙ=‘’:!%q ÿ'Xí"ÐpÓž¡¨ýùá ]&$©ži%Ôe $_Vr鉥À¡pÔe3bÐRéÌv«8£!Ì © ÂDàÜTåëd–˜Ï ž89ª–¼sè"Œ`Éœ‚û5­" Ét^5¯*1êTEöÖ÷>#ea(Å÷¸EÁ4ì±+QÄÞ€‚q8ñh_õ ‘Eÿ ÎWEO¾›—E缟 &IåÓ0ÍÕù Ôoœv$ö~0r]
+Å“X“;aDˆÐ™r’»’
+\S·ÈŇ ¹4Ïè÷êHÌ@2Ž qêgE@Iy-­R9xŽÞjK ”-a$n ~oÒ”ÊÖx§BÙŸw†Jó'Ï©ÄèÇb±â
+y¬Dpv…ÎB¨ù D
+ÙŽñTi±:‰ÅáÒŒ*ŒAk÷9M±´±þaE‚`kLê eÅļ‰v‰j îé€(óÐdøxV2¶º«àt¤³wöKRåq[MOŸûT‘ˆ«]0Ÿ–W®GÁ
+ƒh 9t©ÍìvZÀ&$3$´žåù5¿5ýóès=Y»öiúÑWasèpŠY“쀀P¾$AcnÃÞ:ï¥øºv~8œ§‡Y½=+IeÄ"Æ•É¥*
+³«Š…ažc‹V[SôÚìÃ$FÐØÆ9謃Œ]žÉc‡5L5ðï®}e¶€h‰ÇóE­Û—˜h6½&Ö/ebX¤m d/:JßrAJbðR꼊ÑÉüHÂÓÝJ·ÃŒRœÃË„²ÃZ[f˜[Þ£ÀÞwaÔ„ÒX9‰~« 8¼XÃcCë>¬‘—
+ÑmÇlD%]-: ‚9f ;ג“{h®Ùz ›ÙR¾,íUSb­®Ùjºx&¶7ä<žÛ2 u‹Ìi2‹žÝ"ˆ•œdK®ßJV€3?H]éÅñ[u“»˜Y
+¶W—‹OJäp3V.ÖÖn~K«8éÂ(͆gÊ@Ø3©8Äêã·@ˆÈ‘µ6P¢vþl¸jhQîìZFt WÄ@¡EîDÇpÅ.*ˆŠ•@SÍ1\q´ko£=h¹† ˆ‹MÄRÒÍpå6l.܉ÙêÕUÜ~IéiM´Ø’~N;ÛæªIâ+j$9*˜‡èqh…ÙSÝ™Yä‹WdeÉ?|9þUÊ» 0›†Gâ_÷H¾C`Ó61°ŒÕG÷4G]¡]³yPÆjÚ—±Õ‡1aÏऽÆmMƒÑ|“Éø*ÇÎJÉaj“¶’"ÀQ–@ôÁ¯Ržo‹˜ŒKèûö~‰å„ &åmoDR͆’T¢Xà‚®Ï“ü#  (§·A—pòå^÷èÂÌï †)‘ù¨Ã‚¡àG9Ÿœƒà3ˆ¯!mUêˆA ÂBtüàÁŠæ ÓȹÍR9ŠEV`¥bêÊ<¥ó°ÓEGù¨G2²$ŠMÖfyeGÍdÞ$ î
+8xòΡÈ&eç¶Ó0H€ 4]ˆ(ƒùµ¤¿ÿïç‡2›(ÙJuU˜ AJ©mc™|•\búy
+«ûò«d ¶Ö›Ábs >
+{#mc,£2©ƒQ>±k­=»6$ΔEc‚ÄƦB8Lõïö)&­'Ü燺âžRü.æ6Þeo‚žÆÔgû¤‘/x'þ"À®ŽÈ
+ä >jËòADÚ^ÙAˆ@jPº"©3>uA/îÊP iü.²(v¥± ÿ3í0ôJ}Ũ£È„Ÿo)L™ŠAàr ½H—cGÚ’)q8…¯D&Ýá7€7ÂUÊo„zN*¨/ÎáëÉZ“uïk:¿‚Ù°«Õü×¥®¯ê\¤j­!7L.ÞªdDI8'+Ð95v!O½ZW]@ô=2ÆL
+:Ekœ¯‚§ (¬ì½
+ƒ¥$%«}Õµ:€JÓ
+ßÊw9ÅéÁåCî¼<gÞs#Dz`挣Ë3ÿñh•X熣És>¤£2cБbûªß8,ºÑÚ²2£Æ!fç¸C±XCIK…„ÑáŽEH¨N¢åUìg©Q#A:Tbeå,š± ìŽ9N!›_1»‰‚éD„ŽQ$‰W›(Ú]˜dqœÀAaû $XÍÒ= Wâ@&Õ¥:³wì# "¦x±©[¾—Òç44%ih(õÉ,SèºteS½1©8+ôñ"#ÙCÁ¸ë`-uoƒnk‘ª¢ãk8 ²c 1ê¡_ yzcA XÙJ€¹iÂÝ’›ðLDZ÷Ì
+°*8ºjÈÍÐ3.ŒàïÐŒøªr*ÝüòrGÒã†ð |‡l‘Ÿ¡K©RŸ@åL
+}MbTÞüÖÚ.Ë% Ë!F?à^Æ©hÍŠü,]Ý=NUÞšCP–”Ä x?§ÊXåOÁu}JIŒ/[ÚkC2íŠ<X÷ì‡ð$€)œ
+îêB1€EØÕôÑOEÉq&’ÀdÂyVRè²²ÝK t
+gŒ2–+yÿŠô‚†RŠ÷cpp6 ãE Y
+/ÁÁK/ô ºo$øŠ¦¸ž‰ )” +Ù÷·”T`j‚)zµàcäÉyôž™JP\èKÒæžg%"™b©2o|΃më Šl"Î!eƒ¦¾4©Á¥õ%1?#á‘,›õSCû24š½×1$»Æ˸;!à_÷KÊ[ 0ÈU㇡È¿œýB¨vöËܯ¡³t“Ù¹N•ç´Œ~›Ï°¨È"LÖ {ýF >·i.¹ C¡ŒO,‰ÀÄÖYÜÃKØ"æï­“’ð §Wô‘\ϘÑa¦sèÓ°Q¥œˆASáCðP-ÐÅ f±ÈJøTUQÒ³u˜0>§Þ-è.X÷Û”w11¢£5¾@zUy—Õ©«ìu¬Qw(IOîF&ÌQÃ’³:ŸzÁâˆ,lE¼Å·Wô Ù^¼jBuœ]¡ó©Gwä mì(·dꃳW¥²F˜.‹ÌêV²a±V†æ3)®\ÔôñS«­ìµE— xTäÍ ×ác‹½VŠ~¿ÿ‰§üã¯ß~ÿ{G)î-–:ÑôÙÝòMÝ-£$ƒ]T ;^DOSíY£
+ȃlHÞpÞdÍqrx\ô]ΖÖ@£3»ûìJQP=^F¨h½¦ûÔåþsÉ\óƒ—÷9øÆ!^ÕxÝè* …žy>5­d=ÆuJ¨¥$
+ID~ÞÌ‹hB•6ñÔ¼‡@Ž‘vÐвâ1ý÷°¿xäP%² S€õ9#‘;¸Èü(Û¶´ÕAÑžWZ6 äÐÆ8,uk6¦£Ä|€ZP:/hg\"1bZu`B®jL7úØ*eN|`™é
+1LSWÚ5U¥Wh2³éçåX[>ÏÍã ûŽ?&WX¾vâŽf2SlÅšTélC¨Z¯vHæ–”¢É?×ƘZL\ÔƒÃsÀû⺠K‹á·a«Kö]Ò‹\ªU@î%
+Æ‘S3G"#
+ðËå”
+Qæïó©.qÏ䪔œO‘*
+¬L²Ê¹D5)ŽO)÷<5´°¨Ò†,aQ.äÆ ß5PÙk8´—5 ä\o’HÃb4=»ôL=
+(ãzËy88`…–¦ºõãÆš:RÈ2R¢¡ñµe2ºOÛ¡‹ˆ;(س$'‰ù« ]‚C‚ißo æù¢
+P,J }‰º´}a{n/Ñ@ ·!ÙE„;ÌýáJ0&ÓÓ|\æóòjŠIcóº‹A¶êšS›Œùq‚ã?áSPŵåÆØÀ‰N¹ÙB<üéÙ väAΤ뜮^¼
+÷gÀcR–t—(ë‘ÄäVkèJ¢¢Ûä¿¿(’ßH° lèchœiÀLárÆÁNêmûå]ÑÙÊ,œŠFBà•ôÖi²,æBÝ(Δ¨YÎÙ´»›/X^e·•ä: ‹˜òVrHYí¢§HH‹Š„­‚ŸÝ­°êW†aHl&Z´1J·‘üf2Vþª¾vÌÒ~Ó6Œ®l4ÒÈér6
+ÿ³ŒC;ñ]^ŠM_méÖiJØøgài\LÁ‡Ó6K*{¡=±ÅçÀøC¬<:¦2bv3‹Dä\NQèD–ÖpTðטð=—J¸ ÎlYÊÈAÉþ#çMžg|NI›™ fק`­½²Y%,ˆEìJÉAæú&ˆ2_þi8^³‹€þ±-K½Âæ¦ ¸!ä§Øʵ”@åΠß$ôK¸ Ï™qÈH8V þÙ¢Àì>?˜Ý_l¨¶x.ø> :CÎÉE{.iÈÆòS?T§(ü°Ë¬Œ¯f Ú*])¡ªD/d©°Î+,â$N^É$^­Æû3'cK¶S.¦o¼*ÊÐÔ„2'0×®¢‡ñW*˜µŒ$Ë«"íñIm@Wy/Ð~±Ó³A'C,fʃ/^ב"ºK@Æ?ièV4ȹdÀ•."²­¨h m¬S$µb¨MÒøâsÖkâ¼M2 Š¾fÀ îQVDîôwq>Nj m8Hïĉa¡†?lµé·¢Z}ŠO…=dÇ‹_§Úñ ¾ßô1¢+=gx²»mÆ×â®Ö©ñ2uF²?„áÅÊaM†¨•¦B-bðÈ L–fþEC¦tÑ”rž±çÈœh¶J’…#Ÿ« á‰ÔS¤’®¦¢ü¤ ì/篆ɫ éïTCø“âÇp]†€Ö)á^Iv[<éƒà£´"ƒ*”âý¢¹'\ì
+Ò7èÌýQD„µ-²ÞÞÆ"ÒViÔH½»åbÏEðjPVŠâõ,¥[%n5ÉWæí ôrGpëñSø0ô Ksû|¡ÂGñÀrJø¯©ñÁP D˜ñd€>ýí,JYäÄØU¾9ÒH¹°]Tibtˆ©Sć» .4siÐ^åÆ;ŸÓ»0¤X²”õ«ã½É®ÖÉiÐ%%E¬Ë“˜ÍeHÕ?|\Ð×y:™‹6ú5²‘m ‘ë˜À¥s°™²‰UCvêà·Påî³…%Èÿ?Œ×=’ä6àôÚ–1A$š³æ¸{‚ y#S÷ßï(E¨
+Ó–T9 ùòý”¶l^yFë¿Ì‹þåð~M‹Ö´&™Ô>t†6z '@? ÞodIUöî šOe³Fà1H …ÄD÷‰¢;|!àv¨.“ÉTlÙU`]¤ZâáºW‡Oßü»cûœŒ3Š˜4β÷ÌŸ± jßå¾é¹Nú]l!°Œeü1Q­,¿ÙîX[|84šy@èMæHo"†ªn
+È”šê3o v{$qÝÝñTJý·¤³ÝC"üŒ$‰rK_Øá¬úúùßjS´° `Ll÷0n(ßµíjÊâ)ÌbÈ~­Q±.Îÿ­ž×«U¬v$r` ë‡ã<ñ"{;ÆÒ½54…!Ö 2ÜB_¥¤F¶Öðs¼lCÜ{µ]FÐK8Š5£ @# žÊQc¥;à« ¦åÞdÃZ›ýxSÄ6HÁrÄ-5KüRpùQ³â¾gw>•¸ ™[ §Œî˜Äb ù’’
+¢¢ò\‰–ÝÝô˪qñ®Š
+Î!`D:±ÀÆ€nm2ËßO;¸Xn\œz‰Ž0ß:ɱ+f\’³û>)Ê4ÎØ( FvÛCN”ž²)¡¡É`ä«Žptï±Ve¿‘aiŠéq({º°U‡¶¥fÎüƪm(Rk‘kÏ(g}S}FÒD‹‡ûþ1+Úº;*­£îÈЧEÏ(ÜÜ«áƒ,åD?PX|—’DÆZ!Òµ*-Iä2ý±/hƨ¶†´<éÞ—Æo˜æ,C"Ÿ²îlîO%7À ’¾Èòüh¯q $ÓC÷@sT%çR £cÐåÌžmÂuµÞŸJ` -3Uû> kJ¸+Z‹ñõ$$í?Õ–d 5¤b«H­%Ž?ÆÙc9~æ©oúKQùÆbðMG…ÚÄ‚Y—¿Xd=ë~bõýæƒiQ<Ãè­ã³#fàK àý¿·H`£C—ÝÒóDŒá-žpú^ûRdûX·S±ÈqY“ÓFŠ¡¥ï{ü×iC¨cû¢ +Á’®1í‘özLJú§²näï³s '‡x%G¾<>•Œ¸XÐ=†Í™­÷¬É×Xc(Oµ>í†FÙ‘W,1+ÿÏ®#Á+ÌL»”ìÉö$vsÄA2ìþ,|NQ¨Ç åoþº74öÊŽ€üq7=c’7Vì&xN†ˆ_ºÊ(ÒLʆ2£üfw ¤Ìhð÷tæ­rLc¬k¹fñ묿çË褭mO'Eq?y*Ï·Å„þ˜}î¹è×WX· [±édv+W§{«dŠßÈßGÏWŸ½DÝÙç^¢îŸ¼%±2–„‹Ÿ^}VD~5*†>¥&À\Ò¾s¬ÛWj^^7ûØ‹,¹;]:|®×JÜúè“Ÿ,ü…0›’Xm\«¼_Øž ,H4ä’’Ò©~Ïm%§e3©vD…~æSBU8YØö
+Œé›r§ž…Br±n|<Lô+H£…YÖc€­&©xÞßß”Øûƒ‡Ø’ÕÒåiÑ3¹èO$+2½–òÕšçUŸ}ë+5OÜóë+ûã¬ûþüøãïíXÓozZs,á\')ð¯7E x ¢ÛgJD­ƒÉ8ïe‹ãÝi9œŠ¶©°‹¦*·ŽÀ•ðã©ÜÝz±{ƒ»³FDoô¢1Ñgß›r~¦¤Ea궦PD*ጺn½â¤ú†‰bŽIÅý!‹_ØÑRù)\°Ëc&‡=ò!nðo’5;æ²®3^„“ΘÏدï“šûö=¡Vÿ îþ”…µöäáT<ŽãâGõ»ß—°&ðêËÄXOÖPÙ›þl¼^M§¬“’ûÝ 8™ÏHË6='’‰3ˆr¾¹ûÆtï¼öìU??n@˜œT„—3…#"S¯Ï¬
+ÆãÚV­ðÅ7%ëZ‰DÛøÔo0üc$ÖumB"ÏÀšø˜œ÷×›¢jA0»071C‹¶ÐÓ1LÃƤÊ9W6¾_]“ 1£äeôšö1JÜär]ãêu]ÃQQÝ8Ç7-¿­å;û9B〼÷‰+ì{ƒvÌÿ\gÞòžýó^LΡżþ‡AÐâŽuå£6ÃüŽ›Hþn))Îó’å’må³òCÉñM»KÒ¦<¿ZóB°ý[œK]â®÷59ˆÔl÷b å3)A©ÛXA–È‘àôH¬¡5ØQê½^ëên4]LäÞ>~Ú=š7©¸çMãs('î{-ú¿
+H‰Œ—Knd¹EW{Èq~ #‚¿¡!5õ
+ö¨<ôþ}.É'T§˜°ª&UÒ}üEÜO<snW1ªuϹÔçßJÎWêyDîáý)ÈÈfu¤>"Å‚ø«=%ç>rîW¶è=ÿeaê©KQ²=1µxægÖ±+³¹óÝÈ©-HŒ1JÍÎϤ§â­¥R»õ½Õ+ȯœ}xÉÑ›Ùóóño`é*ÎbôQS,]c4k\³§°ç¨r˜jc‰«U µEköü51m´¨9iñû…7˃—Kƒsç‹/’U/Õ‡í½ÌûàU{„Mˆ®™Jí]-_`*§1ýð¸ŽÞ¬ç<’·¯zñxf©{ø„¸Õ\«åˆÚjd+:âÜÉ.½_4
+e¼Y¦w®N‘s>Æ/^XoÏ^îo.WJ•Ñ,½Öã:qy鹔γûî°Hƒß·û÷4J®<š¯¾ð6,¯Ôáùñ8aâ=yuÚ"s£ÏÇ<p$ëÆvföc]á­Pì‘ÇìŠȲר½;—[¯“¼pʈÖû‚¤ÂrŒ² FsíV®‹â‰EŠG]µ¢½|L~ÝMÚ¹§rÐ…s> ê—àÆFÀ›Úø“WÛ ¸ÉÆìœêwÄê µ”S§‘ÂÏ«”F‡ë¥Âò>®Ë£[›8H ÓåeäMrj%…8<Kõt¨<&ïWíÇV.V ù ³Nˆåè}Øób&­§šHàŽeB S¥Ýâõ¦Lù2íkT E9– Žõ:¬Èxª‚ ª@I>¹_øµN‰ekƒAHkm§U¬ì @F`w%GÊn–ç ©©"Ih²­£pëŽèÑkhÔâÔwÐ÷"¤”¸±jo’蟂^Ôø×O${*{êÈYªþ±â†%kÞf‚¿HÙ —µb+¯F¶üSLÆÒ†¢5ôìó¸Ù@~µJ…Z®´Ì”•#hd¸¥RÓÒÑÔu=ÑÛzîd ^ð^Ahß1< ªlHw:zh:¶@0°"–Ðs¯Cµ²Xêj`A×ÊÝi»!2Aš
+± i4´uõc‹dmÕ[¡0rÙîoÖ™"‚®
+KZ§]½&}`iÜ%ôõ’)‚-Haeò¶ÂÒ> Tz‰Nüœ´Dž¨EwM7HÉ€$…lË­:åky†z®¾=OVëŠy! ÇnM¤Ü9»AR¢Ýìs§zÕ¦|F%Æ×ÉÄ„ú´Ëg€%6®±«kÐ&úä:Ál!hÿFR†îeAäÐ$Ô¨µ½4†ÿ$„žwPŠ”´,—êk'gšà°µrû8¥ËlÅjý $žßébzpoõ
+¢ÿ]I^ü´}äL7"²¹ºó3­#ˆ7!M MO$h¼ ü,(lbm…>`¯tDœj5l±•Yq›Ëÿz;ågA4DE^‹½™ÔxzÐÏcÄ
+?\ÜɃB"Œ's!
+¿§˜-îÉbÎ!ãXàγ‹
+Ø—”(kâÎ÷"™ál*潊Áñ dý.8l&éæ™®æ:³±ÖØî‰
+¬˜–š©@ÓPWAøÝxĉÞÐñv;˜¶¸ámëZ-HB--ã`XÄzÒP]¶PC¾NN£Ž i”©uÌŽKlÁ÷™èÌ-#0Ž¤š$ËÒjG4t õÛ|êÚ¤Éonsô”,ƒÅd‡6Y(nr¿‚â’áI$ŸëLKxPºG7ˆƒ‹‰C±NC®1œÛÄÍQŽkPƒî»ßÏç‰
+µÜãÝï9ídª¯ÑI|Â×óExÁÔ¤ãÔ¤6ë•¿­ƒTÓv‘¸+’¸O£üAkÔe™xÚш±35ñ‹øŠÐfo##Â’Ó©™åští<×Á´`ÄewŠe <“NiãaP@”•U–>å‘#CTŽç†i@¿Èå¶Üž ‹”0™aW‹yÔáÀë¾üŒå|T|"ëô¡´ó)ŽIÓ6é~þzd•ºcÊ{¬ˆ À“±VáW|§¯ì1‘¥äŽËùY;I44» Zv\‡Î)Yµ£³Ó}˜àu$ts˜æ£&©p˜½•A˜WÅÊâ&y'QR^”h¯Ã`‘õè,¼Öy ™<9hîoGÈKXýÐTûü²<O”5Áä[‘×~ÅZ>F[Mú“Oþà¢9±ù—?4T]Ü1ÕÐÀ¡k”Û£©R•Ê­È *ª¶h_ù….AÆ¥*-Ïuðqx‹·ºÅ”Y†ÿ!ŒÖ×V®Á€ )²m5%r“€L9k63lkL3]3®0ŸgL .ÁÙ8æl÷%!rŒ”ïÄÊøH¿É’ªê—’2wDåvpÃ3“«ÎÅ' ©R¦,`§€øç܈ ñän_,š•åQùŽ’;)‡h2Ž6þÿŠ­¶Hw[èI žì$s«/®Rg¤Ýq”9•«(W—¡ ¶dNò®¿ešŸó`’]"H”{E=døÝ-p:ÒUw^żAùïšwµ|~Z´7†™:È >'›#–ìžéÍ2Ë~½t¡ÆZ‡$„;”"V¥’¥úêeôŽ±·™›mN0Ú LµžoN¼v31Ö(ËŽžVÃÃMÓø(r³ø÷Ê2=ïÞÑ*|6öàùm
+¬nç¸7!')[xšhA°Lq ¶§Ýð+éˆ{þ*ôAK¦né€!vABrS˱nÃôWA º¸u—sîy‘%„ ºxËÇãâÝ™}r)H>‰âóøÊ?)2¢$š­'ûù†À×WÇ3Ðf"F._fiÁu"5 µä’a%·g¡s»TsìÖè(c.zĺÉEj«$ò‘³îø3vÈL›oâ¼XLb°"F2†ÅÉ%Wkàbätæ5úáÍ:u¯õÒ팗I’[GCOà;茚‡µ¶} o©ûoý•Õÿ_ßMEH"Á²
+ªYòˆZ'P.;¢3p…ÒvÿßÔø9ý ¯(LRA•‡d•ßA—í® ÷'gú²£‡—/Hù|ô>¡D “F˜G?€Ð!^ª£¹áë¸ÝôþäLvôN
+ÌF9"–‡£ßA80…BUÕÉvò.bf=+9k~Š¹ßî°Ù‡ »«Ö1ú
+T”8¨V};²qÿé<¹FM‹£Uz>3gDíc‘‡ÐèøXU.DçvÂkòrtµ³i¨-ͽ4€ Ñ˜&3àA«y½¥v  Ä_˜Rg?@þ6Š0-`“·ñ¸„œ§™ðšCHxIŽ“dœ@èjâ —(qDhÉ€¹ûV\ Óã-øyˆÙ©¡×Ü6Û:r6-W(Â
+<päó0 Ò™0à¬Ã!ƒuð™WöÐ:hc$RÒpnäô]åLü˜ñ^çÁ8³…Òä›1V Y<ÆÓÕ/J•éç`“ÇœÈzPøF“ÐÇø°‘˜(W5±Ä}þ7”Ä3ƒp`q{˜Î@ÙÖ Q«gß*[ô&ÐÅ4…^ OM| BfD&P9—¬¯XA
+]«ò të-êSÐk]6.Ñûto÷ûnŸ`.úóþD¤––‘;q\Š;”°´Œ´J”²¹³7ü:rßîà ?Ÿi=¾`1V¹”æáèv¤ÁIwôþ¹ Ðéè·íNGÿñLvtÍLm¼”cá^bºP#ÒñÚ$BC9Ú( ²B¿ç=ÇI‰ãÑEU‚„Qg©R _… ‰×ŒYK"¨—Ή8’?2©]ó£ò^´uo¤ÜH¬,ž’˜I4δÅ
+Ó_Ôr’ÃÐðîc QƒHN
+®úçŠoS;>Æ )i~€ C6Ê‘÷NW)”À 3FÚXë`-òëÄø³“>:#•áŠvܪù"%Ëy ´¾S“â…Õ4Q±”D0æ´uT[“PŒÔûÂJ©ÁÙ>4—cÚ÷†×fˆÀˤ:§ðìÌÒ„Is.
+Ò d®O׆^d Ô*,H(¦ôüÔ!UCùŸn¶×¦¸Ë…çð:*vTÊHc$[Aè$/j´þÓ©ƒª4Cüžˆó§Bcî®öamUH=¥ô-µ×˜µžU¬$ŒÐKÓL P¡”,|´F•éΞ§B£_*©%Dâ_‚(àóåHþf‰ìp“Ðâ‘×+¨„eðļ Ë+³’­3¥¶öþ$ª®‰×°×.Å‹¤Z
+yªØS%âÀàŽ¢PþîŠÊ}f‘ "cä ØUÓê.biŽe¢%* •óNNXèž%“ t°™†[sµé‚ù:cb)$,ZB»4]0ñ%7“ˆCãÕ:–ž£â]h 7©^Ô<»ø×4‘²{g]VJ ô½Þ7Å,R2º¼óBFÛw¶,ëæU j 2
+áfj «4ÈŒÐiwÄz&¢fžr‚˜\ Ž+*Ák?HQÓ±¨®h¢ƒ*&‰ D¿PE€Tzw Ý„-R ‡¤Î¯
+ái¢(çå¥h/”¡éýayE9È~¿W³dÚ­ÓÜÝ&‡+è}é)É¡CÎ4ÏÕDw=Š?AW ÐIW¯æ•P6â rOuëâ²RîÙxM¯s ´c»VÖÅÙ!cí#Öâ;ÿ;Tê¦Qvs„Mb¿èåCD:òßzò­ 5ÊR¤IÙÓj´Íǹ²ÑqÈx¬}CB R‹ŸL ™6”õÄù‰p`Ç°¢Õ‡uìh/MPø‘‰4Ð
+3ŠºUîë,UÃÄÛ¶-0šÀ$
+ν b7QC£FY<Z„Ä)ÊO«3'B"].õúÁ`µ–V ;ù‡àDÓï¬Ú%Èâªv€ÈBˆ «—íNä¼GñóøWk¹h›
+º@U4s…–ηèf+Mz1 ¨ª¼ hG£OG×*ÉΫÏÈ(cAjopQ¥„Éþ˜6î® = ì!ÙtáZG©îØ1?îQô2[â´P!ËÞ¶»ý'ÿm¥SnÜ;çÓ‹éÌ0Wé˜2†€û?Pï
+ÿþŽ:ƒtdJÖO}øgQ£É¦†y¹[wÂÆÉÝ–j…@›Z{7K‘Åh…¥-¥·›Ÿ»‚&†ë‚ßd'²TT"Œ¾#‹Ü¾H¼Òj+¤ZŽÈöý5²?A0nœ#‹^ƒî aÈ]Óqd[ [Ú3žÆ@ZZk¯7­f˜§W¦·@qQèï;eJ+ÃE,ÿa¼\’3Éq|‚ºƒOàГ’ÖžeÝ¢·®ûoçÅô´3õO¹;¢.X)‘ ŒƒY„œQbXu™%
+rôÀ Ž˜™<*”`nÝ3ƒµ”S«èsä:Jê×@¬ s‘tð±;ÈAPµ—­nÄ—\aêŒeL`š± În&î€ß‘¿iÈY˜n ß/@Êx„JíÂô±¼¨câsßZŠ³B¥ùW ÈPšÅ—BøâDÄA¿
+H
+D{azY#yq¹¥k³ã‹PrÖôlûñt­nüŽP9–h4C$•mUwÔ³>û;ØÑ‚åâg«œO)Ü™E0¬Øu“¦±“%J[k“tˆõˆøÆU¬ä€%#^ÅÀp}9SÄ?@ƒ3Dn“Ká±K|W ÿJ—lŠç "ðœÈ^$&UO\¢1Äá>dŽ™ Ï#H½D£99·\gĤ[¨Ôåf´iù>ž¬9¥DX¹ýòVTΡ€=ÞùAj‰%s½ªB†Ó©»•£Ç¸Ž~yʬ]Q+Ê=âá”’¶A¿Â¨º hŽÍÄPÈ@#ír)¸ªÎ«§ì–÷Þµ…ø·~¹ïνúüÊo£ ýE€Ät£‘G/çsX E‚YÂÀpåÓyb²eŸ÷6y¿ˆ‘ww’)èŒ/‰X~ÌÀ<$A¦Ôœ3ê‹ZìÆ¥ñîeÏ¥\¦—®k¾y ÒÏW ¥¸ƒgv+Ål:†<A øTHasïûÀ$ ƒ™]+VS«c_gMh‡1‡IW®‘Û¦0Ú娠ïÖÏŸ,`w¦ gù&Ñ°ÄY7ýgO·Áâ#>rÈhG—Ë¡Ö´³÷HIí"—Ô¯Ú¥1ÕÇ_7וz„úïÆbÅ'rÀˆ1^²)õ2-[w’2T¹hº¦:D,+l9¼JßXÇ\¬‘ê#Øô[8ŒVæáDO—tÌ$Y´/È•Îx$Ûp¥¯ü¸o’.%\o}ªShv¦ãÏ_œWÜbâoV@LNalþªŽ•—0©K H‘ô0¾‰®~ü:º·~°±<KývFŒ¿:_´T1ERçƒèÜ`ï—ÝÓHö4÷ÓÅËõ1¦¥ã]uC¤ðÈJ[1ðþKcjÞÙ(Ñ
+m0ü "ˆ1Äo¶(N`yGÙ,¸(~”-x!O‹|f‘Ó!X æ_N~ÛEj±ŠTƒ¥žvyÌÙŒq#ë—ýbfŸ¦ïòdl #¶ú²W”ï²æ
+­¥Ìæó'¶çõ@#8Ú—X&£!Ö¡ö>‡M¶½£v_ÊÉõdZ ú(!(H:¥Í5¼%)Æ«vòMâJ™XæŒA9@þñO±³‰†a.v<+b°ƒ£÷„º'ÞpüpÈÔj¯dJô#Ôµh°!˜ïÇôP*²·ÍCö :4M)ŒÝ™²ž÷J§žwb¹$b¢³ûªDK¨ ƘvX¼‚°²0ŽX_Šømª¦ÙÅâ®ÍŽçNUOéh“œ¥½8‡¢c\I@‰°”,—ÍŒ;Àà}ŠþžÇ§þBCg«^]X.Æ&%Û‚FùÙ›YjÅx‰±G†î 7loY•$oVZ¢ûp¯Æ—%÷é]òŒ £±W
+ä·sêŠUm lzWþ£kÐ:–",ãiø®Ô²Ó‰¸gÙãkC¼
+âQç ™O>ž@”Ú† :¬µÕ"“*Ø$ƒ¾’/'†|„ÞA_žÎÐ}¾
+Yn†÷ijL‹Oýe>}MÖùŽ+†‡뺶2d’aalæãèîG
+jM>Œs ;ç&pˆØÔÖw†±±pñF9’Û”;B º,î‚'ð¢rÚä¿N ›ƒú|Êô[ë\ýx;]?‡—ê¥âUO'Ì-² ¹°Ær¿×s©We‘©íß{p·¨‡^>­®8©À÷@¤Q^œ3q¤ÀÚ¸" CG3Gþ"“Vü˜ËÖÂÄ2M„$ÜqÞ½„æ ¶GNñ’AÜ Öh!o§YÁGÒ+1wƨÜG»J(`Ø;mÏåsxo Ï ÒBåÝ,£0ÌdF3n‡8n÷ë,¾õÕÉoÑí¤H4›*(ÚVµ¯
+3òìkVT€:æ™ß£Â¶ë‡åÏ8‡~H£§^>ò*”˜<à1¹œN4 ™cåä÷M¦Š9f­¶¹‰R.º‰±´‹¾,J þ¾Æ‡$甓Jä«QV¯L|9柪%í`„!r!R?¬³_W?HDñÒÕ.«Fú8Ls›­ñiìfÿó‘2â•y¢2¡.Ë&õƒóµX¸%†€å£qHÃéSZˆ™Öhäó0G"CˆqÅh$<C§± 2 ¿]Þ{kî/ëòC[õí?|Þ°¸á>ß°)þ8†À,.n‘Ö©å™u³äY˜Ýr;╺كYj8cÛV|R–!_ð¼x¢ã0›CnÙQ~ÂIö¶‹ŽW¶9<g<ö—+Š}`®7„Ît1m0ï¹(¹¦LlØ<`~Ÿ1TñÄ>ϱ‚”FPpKq,²wÙTG¹ŸÎÄ|/$˜Uzu€ø€™“.EeÐýÕX@¼2Ȇ‚.åå+ï˜á´É
+
+n˜-. JÎQ2\‹%à
+‘šz0Â3éÄ•«†LëÙÌŠ³"Y¶€Í.Û•­îyy¬C£leùym:,¸ÅËiØwÚÆá$¼u¹ò™%¤s†(¤Ç@‹cçñ’ ñ¯y=îŸââ«óû@wp$s§îïZ¼p‰2Çy¿œ5¯Òà/éÔä¸lÊ2à€ÓY'ß è x¤_ëRÔ•nÀ
+Øó"tAŒPJÕR"%a]R.ýò_Jl´hŠ¨ ì{“ÉØAÉ7;I÷ØR›áWÖç8Yói_ŸAD£ŠÔT¢'A=¥õËJó·´
+E×f3‰ • ç
+NHiÕþQÃhAƼÿv‘lÆTB—Å‹p‡™¤¨½×Ü®¤eÂá,5ý»U,芭5û¾ÂSÇ\¢SK¾] ÄãZÏØŸˆR5ª4!GŒ£»ƒ'5käp<^"Ýat¸lìD=KA ©–ÉóG„.JpZ¨" ô£~Á¿ ©ø*²ÀãÛ<íO4€6Ž]!\C꣈Ó…æJ öÃJ˜!ëu* ]ho‹®!–2ØRÌ Ùf²o§„~ÒPå\öM·¦(M=4Må +‚ Nrᔇ}G.ŽsÔr• ¢U,Œ!±0ÛÈtT£ºì 6^Û/ßÁªð, Kp›&'­éÍòú(BªúY©­/ÍÁᘪX$êð£ä>)?êQ$l˵)´}·¡d‚= ‰³
+(|ØNËöîÂWØoßmÂbŒ8«Uà2°¦‰$»Ë³Baà¡VŒÝâ¯4Ò
+–U%,!6š–aœŠðSÈŠ®W@üh–¸i°
+3惾ŽÙ ÔÀ§"ó kÛÛž
+@‹-¢xÛ­%M®v°`†Ø‰¡ÝÌ EÜ]!_j3H*AHg4ÒqJØ©ÁK<ÏQˆŽ à}#™—QV4‹»¡"BÎ"¶ˆŠ²XÃVaüB´P‰¦Þ`Xzáö…àŸ¤ÿR‚ã»s‘®²u/ÊZÄ B¨­ÚwP/RM¥Ù3¨…¾HCîyx¥SR¹ÝÜ÷ö‰Æ0Õþ”a'’öêaf4Ûˆ[nš’…Câ’º ¨?ó+ãlBI…cGyáià…<XÖ()þgnƒßQžóÛ@Œ¨ÄÌ˼o A$[»¨·‹Q£aû°'E GÓj»Vº²@b¿²}FÛ@[F7§Å
+6¯íÄÍ•l¹1û¤’êÜÍW\$‰ƒHìÕ%}EÝXªåDÁdÙŽg·ám夶¸Ý(Ÿ˜zÈ…Þ­~–¡t “Sö’M4ìxS.Ó¬¤™“›íNêb“ ‚¯~-~´Èê(B"Í"¥ÕøB¨ÃØ €“èzm/% RꂱLò9ê^ÔL®ª
+É(›;'Ò$¡¯ 爭[ªsΙ¶SÉW*áèñ¹ _êí¹ê™Ü§e¨åÏühxhýãeŽÈDÑð´et`_̉–IW'èGšºÿ¼ŸHp¦«P"¥…ÈÎF™?ÿÂVk F[a"g8ò§Ñ£B'\vOAßbGðÝNNà|)Ö‡’^”H1¿!Š!uc¾MÈåd¾y(z(9‰Í–âQ‚&ó-ö z±}*' ɤ:¸Ò_ ñaš<½TìfæµÁah FOeÒhþ¸…*- ³³JÖ’C¢²\lÞlç\\7æ*L«‚‹qª¸x»Ÿ8@f)ÃRK©=ôáŸâp"‚Ä!|<.-#âQJðE Q{ß-Ô $a-ZÉðÛ õ8Jé9°Ô~Öd]î´p`ÝijXý¹ ´ƒv–WÃ9E%äÕñ'iŒ3騨¡yTIÑÃ9]_ÆHÃäéá6ƒ`Õ‰i9íI^…[ÎÚbî5ÝðREA°’£ÕcO%¿Íjm轊V(Z{=ß//—-ñ®¯bGðØ(9Ò篺vòêÚDFC–{=õ¸ŠÁ(
+Ê»Ž³º”¬O!Œ„Z
+µç`ÆÑ.˜u†~¼Í ·W|éÎi.=þr¯ÖúØÝ%Á$w:òO§0¢aëGî€Q²œ9oEÏ7¥oV„“ŪM”=·å’y„D ë@+*?01 làÐWìÁO°pP¼6vž‚®²„Z¯€HA÷#2EŒU™}\A›ßsýoôºFàüc˜Y2
+Ò¾Y·!ËÜá*üÚ%v›·µâE°3/¥)ºeä mÄV–èW¢'S–fôÏVÍ•;î5P/öJ.±¸•WØ)ðÉE½î%!Ál¹§:ñB;JÙßÆs*—tË)x <hò‘
+¯QéK5\7Õ
+›LøˆÀ‹ÙvXOÉ9<}ăõZäÎÏ—ƒìúA£ÂkbK©=«@]4ž~lëú;~ɤ"ÝT™1+ͦaÆÖöA”ƒ‘"½ÈI6ÂÍUè»<Æ¡æíPƒéÊpEÒˆ„ÕÜ>v-zÿÎÞìâ8–@°ë»Û·{#xìcçG Ð.~/‚8miêŸݾv©yÿÆÖ½kVÅÖ<ñ3˜\/~/BuéRŒ‘ºª+•)H¶Öà‚TÛwko»ì›E¬WÒ²€KQTbÁ‹±U„Ÿàï‘ï«J"ÊMZÀÚwðdA,ãV|R‰Ä‹dV‹ÌÁÝ¿ÿ²OÕÖa¢a»ãPZH‰/~G%Hƒ«ø‡ ÄjêÎʾjòiˆþ2Ë4¿ 0CÁA5å݇cRM¬ë~’<eAÄJ¸$.Z¢3~[âôåÐüSC¼OP¼6/jp ,DŠñS€°‚9ìÖpœÈ{V‰ýd{¦ï˜˜‚ah7œƒíÑÃÚÜÉÛˆ“Ž0J™6MMù²ø}pù8Fl˨OO¿L†Ç2qäv¨X/@¿i¸PÞ(Ø+DƒI1÷e0:üTûš7÷…Leh÷£º²ÚLsÜ°é
+D6k[c›õ^¡Iü‰R$0˜ Nág„¶‚G,á¾ÊoÉ£U’¡þêÙ°3œ¬ßü|9‘M
+‰ƒ<M#ÓÇh›8è©ÏžÆ!‰±q&ûƒ!ðhå„!µ’ð…óøðKÉjñµ‡s®Sà6„!ü&
+tpÅšJ”.97¤Ý?õÅnýOzdi=Þd!­Â;•‘øŇ•„
+kæ´žî5ä?W¥PÏ[3{ïð^£X¯¨G Ò ÖdLÚ]lahù%"Sº'{™ƒ mvNFŠ®C§ü¿#¥ëS¬®²¡É/ŒE)´™§(Z(¨ çÛë¡äíXR‹“"*¾¯Š†[Lغ¹‰5B™ÚV£_Õ;sÓ7™`ƒç‘6OÌV×G³Ö}7æÿéë—M CyUÚöþò¿¨¤ÍØÎaÉ_'œëaH_Múç'3Ö_ÅκÍÓn}ج°?¹v­WͧűYá´&SƳ:!ïú—m²6 ¢^J*n¤ZÌL_±ÀJ´é' ׊7@ Y‘ŽÉž¾7ørÖåiý¡Dˆ 2á}ÙùC{“‘`¸¡­šú±èA®<ð}2µí¡òÇ2ÌÐdh•6‡8Â.&´ ךã^ˆ+”À¯ †V‚³ÕC)`eX9ËÉmðUacŽÅg'éÚ ®lhšŽ0“ûcÏ‚ - Âþ 1ð  >Þ-žQ–Yj S7Y0à<2º¾ÎéQ­ŒŠ[ö!ñÀ³ÍS%¢ÜÖ¡¹TÜŽ -U¹•2ßòkÑÍŽœšüÍ"öYè%–ÅÇ"ò*ªŒ¾I¬½áN•Ó]LÐ1V—ùE ®QeáO³”-ùNˆá‡”ßãȘ6ÞQª¹Œ3ßÆ"yí;CZµ%ŸÞzÚŒK—˱MÏ  'BÛê¡dA£1¬‘¿´ïó_ÆË$»Ž†¢+Èþ
+|Ø7cgè]d*íšû@ðÛªb9É ²! <¼æv:¯…ã{m—46S&絈¸¦ô®È“?FûxÍpd°?Źy?Š1@bÈÐlìDÇ>€4½ã‹hyÉÐÄ„´dÑaýbÚÈ€…§–[<³nÌ™Œ«¦³ó{ñu ¸}ˆ$L” 6Ö³X&ƒ
+;â'x¨_F¼#“¬¤".PM5¿é¼dKhèµ¹ŠÈŠ¹Ckð*„n{|ÿ8 ̘Ÿ™{z­+ƒRh
+½Ýˆÿ3¸êå`0³“qÜ+ÖÃù¨âDb/æéfÐ[o@<ù†‚†‡I"çYIÖT A.³®>Œ*µ=Ë’å:fCù»u$¿:³ |Àn W˜<T\½ç÷~G@d’X
+Ø[¦²)«„ášõ¸˜WI…Ég$å4§ vgˆ‹!$9ÿÒω¯²c0íø@>+,Ëc‘-(Ù’œ·}(ѧD"MØhQy8‡
+Ö«ÎÓ«(irTYXÅ?uéE5b+-Äs¾=VIÅxÉ Oc°Û¬®% —™ßϹ!ç~›+
+=*ÑÔ2vÊû3º~ZQn¼-à§YÙS¾¥DYRL‡â»Ï*ü 4JÌ­ÃJÈ£6™Ù™¡°Iܱ”¦kS¤0Éõùgˆ(YáÞB°c—åÍ®ËîÓÁ)Î6¡ãV†òSÇŒx„AÖñ@™'T ˜©²ÐýPô±Šº‚ùµVw˜Øá‰U—&íŠW¢ØŒuʧ‡SA&â™A,è´ÑdT*¾5- Ôù87Âäô½9èdÖ»ƒXS=µZYîrtÖ‡qÞu„>Ruã‡sé`ûZl›VÙü¦ˆ&Z [ÅR L©;r°8@ô,cŸêh±&,Ó_…¬êÚì
+¥”à¿0ë [ò»Ò 
+~ ¾:—$"Ic(üüçTĶÉôÁ0¸áÇCÑWëx¸2TH$¬AÅÈãÓo>öÐÁ«>ÌáʇyÞYE¸uK˜Z>º€ÞäÚ£Å}›Ê 84%CiD;9(ÌÅM<
+J!7ÐF§a½ô\$}+‰nµÂ¯ÓÂDî’DÁjÖë´w°«„‰PÐy¥ ó¾Á—¢UÔdDe…ŽÊE¦×Ù»é
+
+‹²æêÜ>D] €µžŽ´Ä¼É I™ëón1_³žxw…“ÆÙÖrfPÂÈ1Ñ1Q8dN.=úq–_+jFE•Ñ´¯ûõ0뤜¶–s°¼+¿e%ÌÓ™
+ ”ýC¢tTfÀM>Iz„æ@óÈúâ
+¹ûF6ÍÁ¦F Æ—Ó¶TÉíC#Sxü<×\èŠ-WŒP‰®Tä/ÕcêJ±­`ÉZ²U jv…KÕÅíGÐ2ó"x×O©ù&ÅëpÅ“"kè—U’•rBâ3u•Tìùª_ž”a2¤QÕeç¾JxƒÚÔ Ôü†=Àyu¨„œDŽ¸br"6Gy¾UtFÀUáÔMÕBJH Æ)‘½ÅNá
+Ž”8™Mhèq[%XZ–9]Ê0+SB’»S‹A{¯ëS´sòðÁ(à>#§‡’ *A–FiêReMä `¿äW¦çØSŒêf-~aÈF£ÒÙJHS]én„ÚW ñ¨æ¤öOM|δWçî‚Yîb•j#ïœF⃼TbT†uY=ÈTŤ2¹È6Ûñ>1E‘¥Þä°ü_Ù’
+DxÊÓš(­G±&„F•†C½ÃélwqnÚ3,Ú1·#Ë*ÃwàÈSÉ=ïè¹U:ÇÎ×x(ú8EÅ]¢,†@ö—~ÓÖ¡ù8Gà Ô :ÃJðÀü+ü%o¾…L74®º{, žiáØÎÄ°.ÏßR¶Yaˆ@S¢¯ï@ôEcîÓ¼ UûÊ<kîxq=ª±±ÁÜȯ‘œ•D™xe³òÎ( ¤iî/±ÿˆ ã†{é×\{'de‰ß÷î±,K–¶KØ;iàÁ“ͽ ·"Æ!nhézncbÚ‰
+ë-N1)* , b˜Øa]b\ ~;§ü½!½
+ÁmÒ¶¾©TôA Ʊ–1¨üÜ똇¢_E"žIËÀÀ3S…ÉÛ´F…¸*Ejš%I‰•ØÑDƒ$×
+º‚+„6ŃEüÏ>Tå¥8“WýÏxÙ+grë@ô ü"Tÿºœ*õlÝLÞ÷÷i£²fð•d¶v¡™!tŸ¾Â"£–…óˆ¡?§&9)kÓZèãßµ[ƒ‘Î`°4eÁ'LplO†͆*ü­Påè¾
+é$0x-êòôÚk@À*u! EË2ÎjßÐ.*ã -’â"K9둃!´R] ùï?¢"¾PÔŒ_âeæ»þ¼å ±3€æ(BT„<@˜Ü›{â¡Ô$Íϧ_˜$÷CKÿ)[0a:Îγ7j1¡•cõŒÆ¨
+L\"sL‡Ð’³reK33ˆÑšr-Îͺ˜Ü` t3_Xô°À¬Dš¥jÑ‹ç rÄ^ö‚A;%¨Ù 4k[¡x†Á~b.–«Yß·_…i !…~årí::¸¤ÍüšZ*¢§ûE„,RÖ?Â)äŽ-®Xð›¯ÑŠ`ݘðåÚ‘~a•Xý‡ex*£!âè]4áð)Ñd8¶Ä›œlÌÄj†Bø­ ~š² ìÛùv‘Ê^à gá„Ü¿ü;,Rï7ó²%>°M£+Ü­¨ˆóÙ|jèBi¤E*k÷­s†ÃgdŠ×+D³´™éØ>s@‹MŒ–‡wÖÖÕŽc0n=«Œ±ÌÄW”Œ
+’T"» µé,œ°±ŠX„…%yc(²J„*jlP„éj^I€S õñ¢ífÀ¨!õ/&0Paع[1¡sÊ0²®=@æz´·«Ç \û#ŸT¨ÞR;Â
+n#€lfèÏ)Ù Â:ƒž{3™vÒ©V9(ùõ“Ùy¿,ÞH‚ »;p¬y"E¬N¬ú¥Åš/Ì~“ûœ1ûúe÷¢=ft
+/ä9xLP¤|ÊPr9%ŒlÄ'u)> )•¼ÛëÎñÀÊ!ÕgÊ3dĪ×Uº'dÀŒËñ§
+J‘_°cⶉ³Xvgó_°ã³(`GŠøž20Ç|íÆWt¤‚p_ÆÂXˆŽ ë„P-ÇèÈ5Ó
+TMïFê tLÜyó!3{ØèÈ©ó·‚´+Ô¿oeÔÑÑšø
+u¼+—4áéÙ½ûCÆm±‚ö³lgÉ'"Úeê0/a¼õ9@;¼Si¦
+$µÏ¢ò14Æ&—˜›?¬áe0 KC›{óÝŒŠ*~[Љ´_Nƒ8Rõêè©(!Õ´²¼„ÁûæCrˆºé9ÔëÜŸ˜’#hZ!EmбF†Vvo%34( a J~ùHP²ôŒj{ñ>»æ>VÍ!8ù{rd)òÒ§ïW$J@Z»ŽÎ«Ñ.¢iþvo[Üé© ÅpÇ‹]§ ќӄ%[×ÞM_Ï èÙò
+g±|Ý áÅX<j ‹‡¸ºˆƒïÑËîE?YÏwßb«$:1ëB„±šf¦of*©L7`Ønqz¡h"r|>UõEâuÈ6! õÎÃâ; ñ5#9²Ö¸tI¹ÆÈ›O5œåÉø‹ò¢'Èý‡š«¬)¬IxÁ•ydÒ«Ó‹DœŠþe¼NŽìˆ €Z@hK¯gê(/t¥ü¿ê%€&Å™ž.ŒàšP••Ëž3¿,²Þqìwii­ôÞ÷zZç´ûþ³ŠŸ¾T©UˆÈs³ÂŸ‹~ý?³(Ç|Š^ƒx¦{dÉ9òDȼÉmëÄâh„´(q›¦Õ°°ÿöÍ |ñŒ¦ac\ÆzMaÞTÿ\&Í‘ÝÙZEgK'‘ÇŒLø@Ô
+VÚ-çkɇõv­ g3Éx]zÈÐù&g˜|[þV”bêbEÏÈaò²wtÖž-Æ&tü'b
+é)‘aÚ“(ܧbÙgÉ;Ó[Ãa‡•r`ø´~iä=¾ÓÑþ–§ÎYq&Ò²(FÑFE‰v7_êÝâL²Zá6»ì¯¸ø=ÎfÓJTBÔ'·P³¯)Ùò:‹V¯s]Æìîò¸QB( ÉÈóé2qå…2ÀºŽŠYCñÐÔ×Q0ðãv{ß1ÝÓþW¶£Ï’‹œ8³m µ7›ÊcØ„’~pðqàã¨ü´Gÿ„‹s)`²Êž´)%"Hóñ¶ø˜jZÓâ(Ö{û¢„a¿£¾ƒ×QŸŠ° kÅCZôyåV8ÕDÝÛˆïù.až:JH£‘ÅM–eûX(¤äï<k5Ð>ì µlŸ
+H‰”—Ar\9DO ;Ô¦‚
+’` ž¯ šÅ‹a•ƒú¦2![Ò *“?ª™'Eqê«“<í©¤ŠŸS,_|¯îô
+s+íÌé¾yuoµ&ùE—}ùg™®®C
+u8»éò{^U™L9Ö€É7çÐDetƒ<ÖV4°¼8 `«…ðé¯=h¶=ókOe Oá>îÕhYèF3³òSÌ¡dWT^ÑLSˆÎ {DÌ é< £Œ³®<?Û Tî¯mŸ4* iô > !|i0úùäâ,u±1‰[UO.n–”ih¸'ÆoœO•R)ªÇ$ÝŒáR´$î•_@.¦ ZßÊóN®>þšÓ–_ÇD]$z1XŸß€RLH?ϵŒkR‹SÓI´5µÓ1ÎB®¶^ÛÐÑ@;Úöf¥QH×_…ܵ‹m4"é‘ñw™çà!sìSÈ"'ï$DGï4GÏÞIÏć8ã…ï§(õ"xÔ'¤Û­0°
+»IA0
+ß|bù—BýþI¿dk•ÙZȈála7ä‡ó> yâÔ¹ªYÍ$±Ûª0‹6äÒçÑ®”iÄ„DÚ\¨Œ^_õ`Û€*1›+KÔÞ2·Øuµ‚ùg¬1yt¦ÀRù5Wœóºzªü«ÐÁ±: ñ‰VÚIwvUÃŒ »z…‚¥0ÒŠÕRqÐý§KlÊgŠ©Q_OBcX`¹Ší%vO»M;Tç9ÆÍ4„¤Ú .XÏ ·Ú_L$‘·Õ3èKÝ?Ž vL\%Z‰fL:×9±Lž•¸È"øÊŠ˜úz99f°¹]‹ÊÇ^ƒ:Ñ;Çd¢ñŽ,ݤ¸?+™Fúi&ol9Oúß;ÒËtÊÈâ ‹mG,i¸k®ßÎú/_ŠéÜç0OQ¸Nc.Š:ÓTsøî7Ay,¾Ã×Pfa¬g+´½¬â¨_N¶Z«]òŒ%Ê ‚O" …–¬ú8·{* ­8©×}ÕzsNÈÀºŽt®=ôÚ9Ø6ðó(Ò2¡wÐÁŠ
+kXga;q>”±¥WN¯XVÍŸ¥S$f2ÓkwF…3š>‘]TgBk\æ[Àb¸ÁYX²’9+ü@ „:«$ãR(š‰Pé„XŽ˜Ê°)ÒO÷'©âM…î)»3ÊHÍBé‘üùt‚–\hhnÄk÷FãèkG[Y&5¤ZúiVžÊyèTÖ@ìömjÝñöMŠIþ°Q×Ä¥T$]eO˜-”)톖}
+/ ‰ÜSÇ´GÑž#;ÙÔ‡¯§£ß´FZcÉO‚¨è
+\è›J5aIË™{€0Pñõ½¤Õð¥†'Ðõqá-ðL|ä·èã2ÞB|Nå6‡ÒýåX ŠCíÒ¨{éd
+F²¯öuÎk^\ê¡œ7¯›¬à8Ò
+¡äŠÓÙC«5²´
+£Ã×´ËïìGw”ε‘`%×À¡x¤ë…0$Ð)˜sQ£„¼PÖ~÷÷ÅRmßõ¨é8(}KË7=¢ŒoÙÌrWþ¬ƒŠ×"l;wÂ;£Z)û R•£c¿G¡Pð x:;ƒçüF*Šs£É¶qCÍ¿RÁ+&MÅ© \¡T°äø”ˆÝùwÅFE2Ì£¤D§€›&¢RÀé§ý”â(Çæ¦
+ÀƒœµN‰‘›è2Ú’/þ ö£Õf¿+^d– åÒüunðíÌ“Ÿ$ý
+Ð"=†
+=$°ðWÚ
+ã@=Žˆ{Ob€TCLP·Ã‚Q…€Òî)3×M´¨þÁ‹ìkÀ;—/}Á_‚ªMtÂàƒ,‹¢ åõƒ¤3˜_÷óMM3¾†ZÓ1®¤˜xÉzìŠ.´ …/f£
+Ä] ‰,6Î!¤I€@»Šph¨ l´'J›,º¸M04 Ûä³lÆ)a”E´Ìâz Ô€m†¶‡oÖk‰>e?Ð(möDY.ÇzsF¾ÚÊÒëùæQ
+³(ºÜrÛýl%LÛŠ&6ãG%ê|éQ#‡Ån£¿¾èÑe2½6`ÒÆ›G!è° ™†:Ÿz6K5ed¸ùAƒ'AÑ' &X4œÓKÉþÐë¼çD¨ù÷.øO
+0œ¥)ÚsDD‹Àã²þAß•ü=¦Ÿgë0örnŒ8 ÀÏ=̆„¨¤Q1M>k|~ì¥è÷7nôëM“nNع ³më3,ªžÊä‡çJขLc ÒÜ%U¸ìPz–é¡a‡Êð=×ó0‹"@Í{¹ßƳzô<&ͦ.-ªÙQ°B»1$õ|gjAñ)+µYÿ‘Id8 ä¯úPÇx0e¹“hƒc@h’_e7®1ú;ÖPA*Íê ¼~†·5¬üâ×\CŸEÙéÛãÿ|Z|É$CL°ü!wCŸ°Y>N×­p?Nn¦#|@`U|Ñ£_*vw_{÷8æ1€™ ¦˜±#†Õº¥|>ô
+†¸*Ç4Å«
+>Ù—Bêè‹ÙH¯òéPj9¾üõà‡ÌÀxêRotäÔÞ+–ÐB¤ó¤”Ùï!æ¶ép»‹0^^úãô5~¨Û M
+ã»EYòµåѦ‚¼ò¶ûFÆ­ÆmO@âÎ0NQì¸ÛGþÃ+±è¸³³M„ŽÜüù•˜ÀX˜Ð½Ï¿Y"ÅKÉ¡7¢†Ù‹œƒé› Á*_ËMêâ·xj³/C¥—ÞŸON…o
+~äœÔÌÈžÒVFIe”¨® ž
+ƒðõ ³xo¸ ­$V¶í ·ÃOt%N´$X
+/i)“¹
+Jö§š¬O¾9§t”¡ó6Ìü)±*E„ÛÙ•ð$å¹ÄbnÇWpÙH™jjפ€´õ
+`^ð«ÅöÐ@J°ð6èítG$Lã1æ2–*¡
+°Cº”°ôoîÀ¶ŠHðgz‰ô$9ÿ´˜‘ÿÿ“â%ÎÆ?€?Øoä˜ê]ŸÇ¬¾˜ùÏk´8 -Dz@=TË €Æob“±&‘úÐlÊç8ÂÌ5e#ùì)¨fËIîÛOã$‡’úJw§E m5 Øx
+ˆuXµåfì(á*V®¯ø,ž%…ù•š4ÃÑÇâ‘ "©a9|îÏ¢¹°l¼Æ.EƒKÀ$³#û¬w§Ì#ïXRî­xôC)cŸ¦œE ”ÑÔ_„RøBê±F\à:ÙOë S`rÙ®Á$fèÝKžyØìX*üàRRwG ÿ’±çP
+óFýzVÊEWª,ÔÙªŸV;®fWànØü_:kÎ;ò¢¨·×<*zI1a|«ˆX 7àyQÇij¨¢DØ4ä¬áM}¥žÆØW¹QZh2¸:/ðaAh÷x,ŸñCx‾%I<s¶a¢ÜB Ú37RÓ«ëkìeÂ0«­J£Zp<E³íY°AÁâ,æg]?
+QŽÄWÛemnb)¬ulZâu\‹žÎyL¬¡ 4¹Bƒ~&klx}»û­È#J.ÍÏá×ÓîD>/b à5­‡ø£¿MAë—Æb"Ô³Ÿ+w¡ sO&'éá´r<ì'w<E”Ãê~W‘ƒL~rß—úÓ}5týÁ})¥­ ¬É½–o¨NµÊ Ü«:lÎS”„58°(Õµ¡.bãqö±àè–v‰ v±¨+3¨øð/ñ(º!~ÎïŽÕJ@ صKnìÙHÍKx”Æ Ì£ç<¹òvVôÌâYôô=åsw)(Ûwk¶Ç?¦¶C"Ð\_ôr#H™³3{B³7:ªœ´L*ðÇŠ¡ñ¸Vy˜åÏK£Ö©º">Õ@ì0@ *ö(Ð;䉘”®{=e‘f•Fç$¹¸m¢C[]_ÑE Ê…©#¤Ñ>¾Á?¾±ã¯±wÔ®©ŒùU·X€d ÷"”àú„&–.ê%®É¾e‘%\Tk‰Á±C]íÒe—j
+ê°oÆå¡w¡iÕþ§ÿHê[H+'R
+~$@4‡®Ï¨
+2œÚ—½ñÃì¯5FªÐ.—ƒÏ²S¢&Ó%ìÙu–ßi ²ƒ(r÷|
+ŠØ ø­²?½:–HÍf{qE›BÀO†AN‚œºø`[/&Ö;Þ’LjÜÌui¤àR
+
+„
+$D@ì—÷QwsÖ®¥¯7=;<„’,F £&wR’uÒsâÎw.Ø<ïrƒÏyÒ b\-Zƒö ‰{d1ôIòUÉ¿çôyöŽMðnèÙ¡÷µw9$WºúBœš;.8‡=Š¾Þ¸Ñâ‹dÞ§ÂMĨìhÿ·¡7$^~!¢¸ÚŸ>F& Úâ;OüE׉Ä*BÙ®øSÃßx@ æů u¨>M™°:Ên%ƒw¢ f—Y¢éãø;E÷,РÂ5Xëµï”pT—Âo²G6§ß‹f²¤|ÎZÖOà­ym#KÖ‹Xmš§•”.û0,‡lG‚¨y·/ƒtt6|ÿöÌÄE<$â/¦ð°Õd&F¹ŠtÝsÞ? |—æA!÷;éKÄþ²å#ì¨ ) ¤La¡FžÀlm?¸//â"eU¸0K!ìî`£ø[ìQyG%9“ñ¨átc@—ÉLÝÖø:cà{­*5áOwî‘ã°¡†ñ eaôOõ¯Ã<Õÿã~Ú²š4ig›¬€kÄSÑ*m15ؾ^!ç|—¨`L±pi[¬!S[Së-¢°™= S±•4cRjŠ6°
+¤On7hA?Ogïg`{ÇqÞˆGWtÂÊ–Õeþ© ª)»æÜ™æmÎ)
+llļîw°Õ$¼‚M΄…}–qH<sZIfe Ûùo~fdÃ̆P±?yÀE%íi5DQë##Ïw:*)P’
+d}b5gêÌ49¿Äî"ÐŒåM¢j‹5: ÀAFJÛ2ö.C‹õŒvØkP) ®Åuž}[\§}ÎwžCà2ê?Ó²\áÍòJNN2«qõÄ$ˆ?Éö¿ªÁ7°àÒJ÷âr_n K<i D.ü#Šå'Ã<4-Ûe¥W)ž #øRѺÿ,‚\ e",v°$»èAØØ@g󤂒­„&K‚ð|rßo.w]á¥ñ•¯yû=…j¼/í{J¬(–¸ €ÚŠt+1þG#‰ÍK²‚ añHÉõ7ŽÞ»J…òÁ²¤ª{·èŽ$: H& „Ù_ÖTSkun€JD; Žüµ€¬¡Šiׇèhe.ðw,ö|^Ålñ­ø÷ž„cq³yÀôî~<kû!¦¹¹‰û4¿¸è™Iúá8(K%ËÆVq‘ Šž°Ó4Å¥
+1Ò¹^”On¨MnÉC!¾³V–èòdk
+­'ÇŒe`A™ÌKz‚Ð÷*ʘp¨†ö3‚üõ¬•ÍaQÔ`J¾ÌÓ6×!®¹Å:š"cŸð8N£=÷Yt6r%á3ù‹#ËÅý‹þúÉÙ¹JIð\uÖÂJFªAÄ»GÏ™‡4p Ûœ»èÆ2_Î(êÄ!KïÖÜÕ-"_á"Õ»u‡p‡
+0zµóN•tx‡·Óš¼U) î+§)óþsáÏ<,þgþò±¼!ÉôÜí;5CÛl0»²E]Û1¥™Ø;+)zÑ@Ö¹âƒh öÿüË+º†žñ–C •PF}·æ±|_ïlè?Ç;æföHQÄÛªsEµ–ðcËÜ>dA55~¯N‘JÚ$–-p¶iŠaX³z»J(†N0à,üvbl›d‡ù ŠçÁà`Ʊ)±iŒ®Ã¶|§g9téÌÖ‚
+aÓ¨YxŒ•ðzX/!ú–Î)JÊ­t³B¶~·>Ía‚À–œ¢/+*ìE"õS¯H%p~dt|ëp+ZFáCíJd±
+" ùÞ²ïUC`€k±ŠåÐ8鶃:¦¸!6Pª¡-«[oq®ãøW ÂIÚ¨lË{AÉ3éõà=ëU
+3*ÇÆÞìՔ׫
+½µÄjÂ:DWcψ~›,ÞA¸!¬5 䔃ž Ô^gA˜ÿý1\F–0sAìØ{ŽÄEÇtˆÑmˆ^¢x”³`šþYŽ«º€þ!¯Ÿ Á;gÂäÐ<@×Û-Žþ}Q#7cÙ¢Jc2“Ç3¶äš*Ù@I´‹¼/~Y=Å# ñ«Œ‹;Ülò?•‹C<nˆª6“JIR5éüíìÑy•ÐæŽyýÐü1Øø¹¥¦áˆ`QHw8O‚Aûá.ì%„ˆ€5¦?>`@0k(Žš[/•Ô}Ä‚q׆T<V æÞ©¤A·H®¼f'ÿ¬|Á¥“FˆIùtP)ÉóW3nÅ5™Ã¦îúaY‹òVQ¶r -[ö9€š¡0–bõ` Ãód2* 'ÉIìïÕj f·¶¨pKÚÄ;™æ³µPÌêÓ!”¦ý³ÄçâÙ1¿øÄl±Ïª$²mýTáRêÎ-x»Cb²Šë¸×%ÙCf@˜³&ç¸Úv,Žf½J?Oǹ4î’IÚÔÔ‘X¢ƒuƒ"vÇõÎ
+9A
+ôÞx'‘"i¼Aô¥éef<0ù&ÇRŠiåLCHgU2Ö];¸ÎÄË…f9ÖBã|IJH-LóÞˆùc‡®J¼q/Ô¡ƒPgÙàfòm¢í¤òpXÝ‹~$ñnk‘u!¶nSA<ˆõÿF›â ؽÅv)êr+íêð÷`@#æw|ÀT‘2Šs´.³Œá¶³8°+£“ (ìÃ?…øpx–+§ Ÿª œDk”‡°Iynµùí0ãáZÆ3ò¯ æóOÖË…ï%þ‹euJë £óØöʬuõ–w¥bp3~e‚‚€ÀaîË/?§ùQe;6DŸ%A½_ ?ýS’6M_üî=Y¾q‰ëΑ±´Øy=“šCt+¶íÇåÓb Õœy8û^@ïÎ'k¨2,•ÒçB. ó€£GÍRÿôvŒ*MÉŠˆ–÷f 
+Å—ë{Í~æ93Ï+=GïQ™÷ñ}T÷9ß_zôó÷[¢uJ¾N|wS”lòv–ÏPwe¶<Áª:ü€s±Â¥d~ƒáÖá+‚C”&%<©n1D²£hƯƒ“dÐoæ6E#ȤX­Ô‘š²Á@ÀüZ£|¡¥[Ëß¹ý˜šPX“¥º¿W1äΡè|Ž’]¸V_ž¹s+„¯yf‹u.¤ÇD|õ/áŸÂ#ç9cœ5õø„%Î;ð&΃ôE±k”G_6“ ]ææ»M2BÀ73ƒôñ×ó¥ëŸ7L•ÅħLáSÌq5E:_ƒåE°Ø:o6׆'ñ&U,|„›JÊ6,C˜ü§!2ÉôÖÍb1Õ°åænè%™o:Ñ7¾¥Ç¬ŸV¾Ñã$x˜mBÙÏn×÷P.ãüšˆVÃÉ
+1%¸¨´ç-ÔŒ!¬vnÅb9x+Wøé«ÀDÈFtQ?³Zý=X‘*_K+ H
+n¾yS¯äÒ]Ò¡˜QRñºµBº‹Ç¬¢–¼Iá új_w‘'7ÆÉa¹ËˆýA;³T6r-¢fmùºbÔoROløÌë›MML0Ößç¸a„Àøi#ÙÁÐÕ1Àe±<Œ·$^#"ä` D/CC5¦|sÄk1¿–0FïØݬÀD¤j‘»jô›ž
+ÆõÎo _Fôã¯è9ì€ÒhãÐÄõz_Àëç~z'…ën½ƒœ`òü`Ãá‰[×útŸ;)£c>‹£‘f1†ÏÏÎÕ…´8DÅ8&^s¶ ÈÒhôÆ.æ#dŒÊ„ÀVþ˜¬®®ñŒ‰cî3¼;j… rBXÖ!"cȵ@GÁ°Ø(tðÃ?5K“Ò‘×ó¹1ÜÁX¸Ì@Æq
+ɳa‘ý[|66#ÏûÍñ£’šÂXL}24Øš2Þ<7Çøp”‰ž
+GpFE¹¶‹Œ°7My®7µ¼u󹦙à7­VïÞ]Pțà I®)NÃè²;°î0‡”Šxɺ­ÃÉÿŒeSýSý‡¶2ÃÓãX‰aÕ-1U;»ŒÄ0J8QÑÐSzIšÃ×Hr/ô4!ÞI^c:^A_<Ô甯ʆ…X²×åÄعìN§5 ÒåÞ9¼‰C"A=ëÇÓ·Ú‰\ìuë›E½4óat5³`Ê­ÖnvÙ÷%¿/þ:ŒÂ7±Ø¼y–= Ž 3ü9T!äøâݵb@v½Š2‡æ¿3c 9ôõº­Kæ0‰cóÚ«ù¶u™ °Êð
+c2^ÆëX\iu'èà §eøS$.Ôø¹‚JBšƒä)îŒ ÕŒšu £ôÙ;ÎÌ£
+Z°Ñ©"PäÐ×h||Êö"敲vË°k@óãl:<.µ øØ9ÕPiüðwý§–k8Â9aÇX~óÂÄk:”$ÄË\ùp¡kz&pjÂÖvl@,$H½{ëQ…#Bloº†ñÕ…ñÉÊÖ²Au{Ž. %zé«õY<ÈQ±–­¼I«Ø ëÅ=$™Ðƒ#Á)nzÿÇ"ù‰~ Eûýé9£hK
+Ø„Å\t•u§±)§9Öò{JùþÓ®ÓQc®ûá×‰Æ ¢ðÄò±þІ*Í`.];m¿²5ó%–d/Bò)4¿RƒÃÄò]¯ÆíXÄÀ½±Å ðÜ÷0B-ª
+ó·îÒ¤¡«ˆ¶W†!Y*ômìX”:"ÄRŠGé0ò &©+„ûøÇØ,m{ÑTKx݃ÌÀ¡È{Eĸõ}1HO€ (ûO7ÝNRq2éùÚ††G×¥2]¢0‰I4
+C¢Î'
+N#p#Ò½>QØ·GPÛâ¿GüÛLq¨dMÏby¦¸w
+sÃþÑoÎÊ;_¸"ƒšL[[¸Ä\±½Ì;[ÐÊn û&\š6Ñ„çÙï$½%Ý윮V‚pÊg—& (³Å
+¹HõÎ
+ŽŒ%νGÉÎ6Fp¢
+ÌÞ‹CHÆQ"|d"Ý{!ß;µoºÅÐ:Î Û¢»É€1ì “ÉÆûo‚Ðq µoº—95¤bHüÍ«/mð‘4U$æöé²FâÚïÛ9ÞÔüŒ7|·7yCŒfaØ™ná­~!ê/g? ùÞ§÷³wPùÃñùÈèoøµº9À…&–ì>N:1wt.»}¾ÑÇñ™¡‚„+z …õåeódŒØlf^ÒŒ2ó¹ÕŸ@è0s”ê!„.kœŠ"X!4£ÁÙ€óZ¯úÐÿ™WJpbúPÚ‚»íI8AÑQ£E%„(Ó[бPõtBtUC!ãg90ä%ds:£›H³TÇ×\f4)u©ûÖ¤X±.áEÃx”c«aÜOš¼)Ñ;fê–SºØ‘yZló~œXH(4÷Ù—UákùnçÜ›p¡¯—è’ÔGäf÷U×™ˆ¨M¹Kä¥L–3X*®\èçé†`&fצ‡‰¬=7ýûkàƒ <N©²ÓEÛwPÕÞº›màïAQj–g`W³ô!è´MÒǶEþ‘ BwÉr2õΘåq<µ²R7‹‹ ÂG­‚“ÃcÑ3zj…;ÞB«Ù—+LÈ5¸œºr…ˆ¦!Ua²#Á„³-ž[wç=Hú’~†wÞAycã
+Ž§£½ƒ$eÊBh~ŽÁªûQ`rj€ó~Ù ëL°Šòƒ[±³ )ÛúæÍ:67F®5oÝ´|oàõ¾ê‡ÅúC:áÅ)à‚¨õ,U2p‚œ/ ‚¸¸¸yÐì¯ …¸€Û
+‚ þ I’;•’¦ßÕùb¿ì*À¨*†ÊçJM#fnŸVeëEJéi¯~èùûoˆ-0E¨ÕY5ì2ÿ€ž^¢d=‹`*
+KÁš£71!)r‚õòi|K&6‡^ñô
+-CÕÌ*m¼obqK\è{äY<2ý±LœÃJ2 ZÇ‘ËÙ-L
+,ÀF]!MÇXŒv4’¯UNk×½ ‹*ñQ㥠ÄNäƒÌŸ¹æâ”hº!µW*k) ƒì)Â%[­¦•#Ó^Š$`ƒ…Ü„!¨Ÿƒ}ÈËÆi÷4üªÂn錒ÖüHÙ9‘—$FC>äY°HŸu“ô-W`'Ýïë"’¥ODR\ï§H(IÍÍ^ðRf eç¹.Ae9îÝ„¢ÉŽõÌñÌ_!  }üñ&Ì7G
+—S±c²Â0užÊ  Z˜úNuú ~€)g*ð©3ÁâÉœ©2®.¾Eù6¼wñŠ 5¶q #¥ò6Ú‚÷D_ å²+"~RaîDÔ ñ@e¦£S¿¤7
+àù™<JÈ b\¹/ñìt‚s(¤^œ5sº‰fRé9§Œ‡9“&]Ç®ï"T!!úyÙÙòÎœq„¤œ¡­tUŽdÓ#+¥ÑÎ=¶Wc¸ŒÏØXQÿù$¨èîñ½«:’ßÀ1»ùšúƒé0;KD¯¥™t'liÀÞAÖà
+q9QAÉ:ªÈïÃ_&˜©AúmºfR" GÒ}xç`l;ˆØ”£R/êQ)øË,”$ÛUô=ŒLÓ[öÓÁ
+ Œ}ªR´,?žgÖ‹ÌoZvq à[2ªvu¥âô˳Š¼%[#GoýŽSb
+rŠvŒñ KÄ„truÑ×áåÂ"| dTþ¾çò„ $2°ˆìR uáow °¼d¦Á;ÄͤvG5€|è(&Zÿà_mÖø;<ÈH6Tç C؇Œ[©=æÒ«\$ TÛºÊÒÖ=»q‹@Wʃä'´‹?]-´æÖ36¤ì*[4^‚®7ºÈ§*M1Ã<ö;ðlÜ("ÃQd›Iv‘å¢]t’~¡Æ}†N]—òӱɼYøæ3¬Íµö£ØZ…Æ
+F¯¾^€(«$C&¨>æxOPÑ'ÙâØ}y®…4c-@”T¸Öý([3Øf17oW@ÜX”,¯ZÏœ15ºþÈú7¡›I^Ö‚ä‚i'ÓŠ{ “ÓÄÂ&u’åòš9ø
+†sÙH3ÊE[+e8xï¨Ä .×3[ÒvêTÅál\¬Lt BÍL¶“ù@™Ae.Ðk˜Ü¯CIda÷”,pfz áçNÈPcQY~b¨?›âò,‰#sOœ3´™L„s‰†Ë3÷úMÙ*E+ƒéU`<ìC±à¬
+Ìö˜î…|BÆ“ŸŸ³ì¼&6 ò[S£WÈeÎg܃†´ýdß5‚ãfª™O!ìÎgøAŠçÝ€S¹HOºçŸâ¾?³œ&ŒÍ3§…ÞFð&b§åèf?Y¹CþEŽŽÁdi°ø¬^>ý|MSMæþ¤‰N4Ýdt á® z(GÇüÀJ$XÍ#¯ÜºÅw)åR¶t󘓿ë°bå=u7øZÆ0=µý3U¾$ƒÇc›†™K¬ešp,§ý¦.9Ë”Ñôr¢)
+†øµ¶=1¼7°’Å“£Æ”?é–’¹U{Þ“Ê(/ 6 ¢L*ÍÅÓî1¢É› Ä"â)wŒ@-Îf„2}/gÔK´ Ñâ€cB1ñU†
+K«_‡+â¾´Ž‡ó“G¼óÀe ä÷eKT—)êÍÄßMÀÒ†J<küY×ëEr²ûÍn  ¸"‚0\IÍåì|v€¹ ¯’F:aÕ3šüt]Šð¸€ž÷4÷[òø÷ÍÔf6€/ÁG¨„é˜UÉÁ—@ ê»ÞjÙvXòeEIWwŠ@×óÌŽÓ"|æ
+ÓP€Ñ,_Pµ";ö#¤Î“sµ²R-ô¨#¹²Ü˜£¸sþ'j×µ½ˆ/±…Z<nÑm—ðqxÄÂö—(.Ï+eðÞ¸K‘ ¥E5g-æó'}óöÚ;¢êÒUJ#Ú;ˆ6U"°4õ§+Å^AVÙ?Gþ²Ÿ|Ž@ó¤i1i™ÉŠ :Šx¤/Æ«çø;%<SW`ýô8hk‡˜qc4”ÅfÙª…_ þz‹@·J£ÀxO,ÅàÀw#ÀÜ{Ïa”N/y¼]o”Ôj;fBú¨ˆôàK áYF”,ñstrÒ*x4>ð”Ä?§ÚÅСG Äê'õV,Z+JIëà+ > ¿Ìì×q":
+ž ¹ÊòØÌ}lz9Nƒ‚±Öü&âjŽÀÀi¼•y€¿CÓ?°ª‰—qĨyÌÀ­2:‚0£¬k cqÇby!ÛøBLB–±Ü byñ2{—K¥>¸¤c#Œå©·s›ßB‹ˆ]â¼µŽ§5ç æˆm 5hc®8ê5äó'­õ `Ñ[μÃ3ð«_Âd¨…d“êˆ+yÇÜãSpØôùƒù½ÉAr§ßâòðÚh¤gˆˆ}³ðÚwLpíÛYÁ­¿»_Z]¢=Ì£uŒª¾´Þë 䱦¨®nbšeñjC•êcȧ¦Í.…3H'ð$‘.«êŒ|Ô™«y ˜pµmÇN"$I. Çåˆÿç¾²žÄ" âq¹²çîËøÓ×¢C°7®"«øA׺+äã­/%î¢=«=À€À!Q–\·ëõ2@T[ŠL¥ÍÃÎýQñ3üáZ+( íN_xvH½Ž!öÉ
+0è0Æ…\¥ÜÞ…žtq=z8^<‰ð´p6R€zœ”FfHƆ‹?‚òŠ!ð˜¾\Â.] >·nß¿ÌÌŸw 'ïò¢x€ó•eäí«` ¤õúåyëûmúuìœ:4ÕP¿1…Ú
+%…·T€èÃÜ%ŠS¼?%™J¤Â/É6¹%Ðq¯Ú@7Äæ5:Ç`52ã»ÒIO”lŒ¡ªD¾ ؃ÃÙOÚà˧¹KDE¶†Æ÷ñNôâ]EtƒO”ðBMÌÆõšv¹ê]j#%=_³Ÿ'¢0_þT²^n40“4jߪð\¤9=øPÒoÏš%€!%'ïd,“Pèàžç ²D\‘s*3°eÞ4™ €1Fi¤ø>}ÊþÒO@æ“0/ªyr/çù-/aD3É•açѺú
+ÌH¡‘@iìuG‘`93;r²ö”{¹æÌ‚’5.¦¥%tzQ’þ@“8ô”$¹!ä…M\ÌìJjIÀ<‡°²Œ<k ~(*Ÿö£ï"|’$„Di XF,/dÐœ¹ìÆe­ìFÙ5˜¢ì
+>DF2ª
+p(¶êárl °óp¾1¤ª8ˆ¥ì\ž`·Zó bµœÃ4ÐQK×—¾ÃJOø—N`«Î‡,!TLe‹€Þë,W)9—Îßh@ÁÑË>ähãô8[ÄüMaXøÖ…-ŸËA)þ¹ž‘Š»=L:ãÕu³õ dMœÿ ññ¶lôs0!©K’„ê\uÐ&0­u “†Â§³í/Aâ\–µ*­uÉ{f}ùóWq-Tˆ;¢©i³ä“_‰9Öð†¬Ýü±Kª#«ìò‚rOÀ;*‚;ÚG{ú'Íi¡áÌ@Pý!kh|Òœù¢Ë"Ô³QZ?8óE‚x*4qçÜÚøkÇÏ¢¸¹xÄÜÔàäY*¹ÈOùrÊ@yVèqç‘ÀˆÉŠ´Õe’ »åwýhq¯´¡Vž·—¨èÙs™
+NÕVåÐÐ:G5| JÁ´1W_í ‹h8]0µ½«9L “À\ªt46£œi­ þü–™)£ÿãÈ0ì™ÒfÙ ³°!kú< D´Ùá6*»þ;Ú"Gg`S\5T:§?R fp!Èâs衉A€Žòi¯%X¾ø–4‰´ ’·µËýkק@;rf$0»Œ¥A™­` »ÎGeag¡§;Œ–.ƒ%‰¥JØ!¯ü„´'·Ö³U ‹ÿx{‰ŠnC‡:™0Û‚½QûeÍ-ÀübC×"ò ËA¥Ð JÂz¡Œtù¸°†+TÞ¦xˆ“­ûJzRÜ% ˆz'ˆ[%2t8VU»„hÐe·r]bBQ!aEHt§†SëbD
+ ±²(ä‚ æ¶æÑÇî„ñã_4‡á4')§©v]3xò
+eWQ¢¿ÌZ¼Ö,×X}ʱ|ªñ$ôe ÈBjæi°½œœA 3ËÌ̳À0½çoÎÁaç@"Fè<€=[[[œyTÓRÔ4vH §""Õ.†}{ jn³ð’~,ä'Åó
+jîóÊü?ÃVŒ–òwEÏ­
+Ç ¸Á
+ƒS^)I$Up€h÷m¬å¸WYOIÅÔ³ÛYçÌ]ÒC·ÔÜTŠš"h…äÄvQ‚†îï¦s4?Ø^Ñ`\ù&~$§1ãgM‹ôEÏ{B-èFZòN·S&ïD
+Š€«á?~TS 5
+C@ä¬üNƒ[Ûm=Ènr#Òä„AB
+œ@cJZ¬Ü•µ&Z!x nIy«äD!>:Î{‹¬l„šXÆZ¢QH‘îœÌñr¯z2<ê“
+`¦!U0ëôÞ(+„ÿl¾Æª¾šR›hDc´k "Ö–Lã`Km¦#>æ k$¶–3Dû—e™ý᪌x
+¬Iºåï:Wål»ÿ°d€”´ý60F.†F¸“ÒèÚ(¸jÝ!<,- ¸eŸ-³ÔDÚÔö­p\HÞÉ!¶tPwþÌšB9bU“”5tmbzÈÞ.•èÞ(駊m
+Ë|°Ž’ú€Jÿ>„Ô çwü $…ÐO È,ž¼+缦%³½† Í‚õ)c.‘^¹Õç`9ÒÛÏl€Vp•;uÁ0Pœ*ìÁRµ>…B7¸w¯;Ÿjà9ìEdós¸¢,’_–Êb` ªÈý×Å(øÇÞ-ʧ±tžÎN×üf¬_Ä<²ºHìZdÑ<¬òŠÂ°s Y@!  ƒ~劺?°Â¤ƒå¸`nÛ|¡S¦f•c`eøoâ´HÉØîËh±÷¡
+à{‚û&A83"­ùx‹ƒ H¦kŠ>«wó5ˆvîìSâ=«_‹­¯Ñ '.¨928õð{¨¨à÷y® M¥+§Ö£usšG\!Yû'À
+H‰´—ÍŽ–Ç…¯ ÷ЛH…¦«ú§º“ƒ¥È‹da'Y! c„b@B)¾û<§û'1È(–bÐ|Ó_ýž:u*b̹Z­ÕRµ‘×è±l-Hoõëç­z¶>m®2=Æà‘ç:çXneÖ5SóÈÅ¢O>ñá3ÕÒr/Ÿk‰Þ/Föʯø„{òÕ²Ž¼h³¥§òä=Û(xò¾zßfZ.3«4¬Ô\j”¹ªUãK;’6»"YÍ,5›¹x¯ÊgÅâÁÌCù ·˜—›–k7…k‘eµžËÄ„—VêôîhE/œ(HvkÅѪÍ<}³í¬L´¼²ÄI…^•QbŽÔjä?Sß¿aæ;™êv=ÄÚ8‘§2+Q¢Žz:ÑKn£Lj¯H17,ÏXê j=µÖs Ú2)*©D‚²Ƀ:3ÁÄ¢Ò‹ö–ͦ-+½‘í©P3µàY£ãÇ‘Y©8
+úL+¡ÐXʼn%ìŽS‹¹¢t>¨Q3ÁÛ*½72ßf)]#[3¥&Œ(&Ú^=ˆ²mâEɃ†-¥Z”V-yš“’ÙÅÓ{žcGm¥X½ÌÔ¨±ZÃ?eÇ3iŽ]°Jy†<÷A(B/iÐÒØ85
+ÀÁÄÅ.oJ)µée›`ºËÈU]᎙àsî!ƒêöPÐ?pÒJ ¯:s&C@|ž©åÐ ù öÞn09d®âY
++8úbØÿÏÞþÔå²ôˆ,»`%z+øÿì©Q¥Né”zÕÒÍËO$…+x<W1š¹_à*ºØß;$;éÏJ7ÿ·¬4Ÿ™• \bïd%Š-éæ†?ùp÷Å›—woÞ¿{ñá‡ô;}ôŸ?§Çz÷ÕíË÷^—ßnôü,uûâû?¾¸ûðæŸ<Nž>ùòÈþüÝûoϯnS¿Ož¼zÿííó'_®çòõÝßß>ÿ·ûëvÀ–ž½ºÇ°ÿ" ßÿ}
+Gm=ÊàÛ‰Še¬-loyè‚×QÑp–Q'º÷Ós+®xcbëÜ],;\3véxÎæ‘ßìoî VÌŠIª6=í®Ï–ó^>³K¯—2~“¡ã Q”èÜÎ!‹fm+1žvWBú1-4FœZ ºJ¨û¾Jª³k`ÙìcÓIÄHLÔ¨iEiaIé÷±kà,MÓ¨š&‚•ñ½2BŒq¹×vDZ"~NksQ{MõªRŠ-à <ÜÊQ·§ʼë6©"9y‰+´ 4¹±ï¦¢2D¹s2²ËÁD…Ú>cÔ>R1M¿‹.‡Èéé=@Ù=Ÿøz]ãêògú\('ZÃIó´qicJŽšK5B]¤ƒæZ—ƒuµKˆPžRQ³7FÀhl\‚á›JUÅBë—bi£vénÅQö{åRመ®p~Õ¾Õ'úõ´œß‚Fì è€ ¥ú&O4S2|¡ÎP†–§Ü Xؾ.L˜OÑ#(¤ýq6±$oÛ²™FÄþ6‚€k©"‹>l(4OG+°ˆyË<)˜¥hU²8§å–Zæ¤ uJŒë"2Cqó‡Ë@¯8À)É)(þO>rc$ …­ÎNŸŽ§?rü“[þùÍ?6m±?y½õ›ÎÄ
+\lJTuäÞáµ}ÆuÝNEŠÄ vÔ.‚ˆs«mAõ˜=Qzr'‰à=¦¹¼ Ø#ôBZ“‰”Ûæ5pµlýCîˆ8)ud-U‡ÊØZµ¦YFþŸzÆÙ‡ê,z°¶]Þ4#— íÁ–ò7
+À@1-9ãããè#; ×xÌr¯}¨ii
+GÑT…”‡!b%áÄ”úÞüuÖÎÁþ
+²zS­òJ¦†Œ~¡j#e³hÝ"ŸåÑåøtKu)ò¶’=ÿ!À…¾ï:~ÕîAÕ9&}µ~ž(Î,»ç4RAüë&êÇ©þ##ÂWؼtE#–Ú“°^NP›ËvÈ?Á²ã¶Ë櫓âNcL@è{4ÙÕK@¦‰†É±TsþƒµöÌ3 "{G%Ç)TLÕ½Âèò³(Û±¯îY&§i[‚qšX¹[_¾J7Ð`º¬Âl"ìÐ1<“¤ÌlÑñðý_œØ’Îݨ2'–1¦)lÀqYËmP"¦ê V¶ŒMã¯@¨jaÀ«
+ÔÀàâû0
+ôÓñ¤øÔx°ä4åô"æ¹úÒUöƒj¥dtjòÓ¼J·¦eOk̤IÝ’¸°í´^WSñ2 LQªˆ‰LìòW®%àBtÇN¨t4ïÜàæ@þ.Ã÷3¾3¦ÒÌËb`gê¦ÀÍá%}Ñån籫
+n{™’ЖdäôN7N¹ûžð<f¶e-ârQ0Ðå~Ü=Ä;©‹a²ã½æ
+Ç]aíï‘Á2w­ O‘þŒ<qÓ "ªæ3¾È‹ *É‹Ílù¿é‡„Í/Á:Áçõžä0ýLžN¯ÿæ®óÞbÛqê›úp—?
+ã²tAÏÀX/}åªtð‹õž;©nM·eéñ™g|eÄaNØ:~=þ¯PFæZü
+úë†Ê§¬Þ ñÀ*€…ï€&p!MÊ°‡ªùCLVz7U Ë‰ÍóD܉€F@Y ^_¾¡ ÷:)¢/άCÞâ1$yAÅ‚}°Aì7ÜCÐSï¦á@GH%½kì"$§‚Ñ+¨zÞ¨Ç/i!û(ÔÄ *æ ;)ˆ?Âêra1Hë‹.mÛ&| ã)– oíði¢Ã/Y¢*lYe3 U|OW@À‘:ìÜ0`2e´i÷Ôlg²|×JPŠRá³#H
+QŒà‘pã»ÀKŒ>ÑQìH»¥BåbJ¼ƒŒDEô/k!ضÂI•}áN¤FY­OüF¡gä@‡oð
+X6ëÅ8D«h
+ †PHÏmþšP=²&Ôø4â^•¼{îÞ㿈}¬%üÐÛžQ.†œ‚p<°íO6§Bž²]ToXþÃ÷b’—æÖÌÃòœ¾¦²h­o–ÆÿܱÈÞ¡ôXŒÎ÷{Ïø.y¿j ÷x
+ªÈù‰²éOŽ’
+dq‚Œ6×Í#Îzj§`ä]Ï/ nð€p® DÎÏâ+1‘Z“f09úÛsÒ]"°êº–±åDŒ±ƒÄ—îµ~¯KàVMQ 'ybwh õ
+è}ÕH;
+)å¥ Éßxè—n
+
+ð”y,2(™ºÊ÷κӇeàÛ8‚åpÓ.´K¡I)®E3‚y3n,¯R4Äáñ‰\ €ÊbLðœåÛ „?áwQî¡ò
+À Ö<cY#i›“¹âôó½*Q
+Ÿ@8ã¬gÌ´q–¯¥L?zÝ~T©a"ç
+J.aÔ±HΩàmœ
+fúJ;¹Òòz‹'«VX™¯ÃX0ôrý×/^£ûúå‘Ü
+­ Ç9üsÞ×À§¬A'} 9 ïŒ@o¿‘w~`G†œÑ@ÁNªªÒóè03Õ¨šÌ'Ýᣣ˜Ö/ÉÆo¬YÑ+é>ÀÓBÝ6éòÖG+NÙ±Ž»MSŒ#b²„À•ßé>Òä5Ó„­Ѩ,E¨jTÛÅáSwxbwæM¶€Mp Iæ†æ="ü`‹¸…•ªœzIº8Íi
+v’ Ô½õÈ0$ Ã[~ßÑañh2–ÿœkCe!¤Š„9oãq¬xžüµÒßWèþ¤x‰¸ÂÎ?V¡š{ü@–ÈCó÷\§Ž¯kÙyê¹ÝiêQz:¨n/ "Ô=™](‘áHÞM$`èCžLž «(¨´’†@Dãeé=O\-:à†i*7uœ§àðØè œ ÇÐS3Ä/¼GÿÂy=ñóΠè!°uÌÔËçŒì' ÿ$…T3à!¤
+¸Fwae¯XTÑå4r3 qrj­ÛJãøù‘r©îpj
+êÁ?DfXl70È,@#€“´˜á܇ŪŒ!¶ -¶4’.»hPç­hèQ•°Ða‡PQâåÇj§þ‹®»qQÍ=ÕF@()gÕ›FAŸú‚ïaÈf,Eœ^·¸];PÆÅÄ2R*V¡„H{ÐEP37N»¾l-RÅæИZûBuHj'‚/O²þ,¶¼…0€?ïz'te¢™ õäV¬$'2<ÝB]÷d`,ᔂ [;jäªoå…)Á~€Þ¨‘}e>‘<¢“Øz¸§8p¹ík|¹ ¾„¨ñÜŠÄ(Â7|Øqtãè7㊳$¥Þ˜:QiuÖG…ئ*äVÜ3XB½¯Éõ?‹U`Šávƒ
+¥W C©>i(q“p=/a(ãš‘)Ma„»u4 \ãÛù}Ô9L
+ýr'ÒfVXÖÜñ£eþB¹bB"Õ0ÕÁðÜ:nq£ÃÁph”@ë £Ô‡›Í)|ø‘ÃOGKx¬ôÍ*ÏÊ
+?ýÀæÅç϶@„Î=Sÿ?ÎÖò
+ÇûŽX1c€?þž¿~ûÙãª;Ëþ
+†žºÉP5>Ç{çߣŽëC§¶ÒÀÛÐsÖ›‡uÁ<0 œ@‡»«âWˆ2M&ôœáŠ­ÊþŽÊá ~{ûúY·#‚?•ÿçïÝJ †Ï`÷ò:l.6(f¥ÁLÚì'F”þä†(Š¯eîqÔšÆ`D^phXÿD¬ÿ%=œ÷À¼«y¨k]縨ƒ˜-¥˜3}¼‚õ¼å1ºg Ïé?z#‘gYŽ[ÎÂ>Xìýy ß¡hæŠTÙMdîé;Nu—I@£’±h}£4ƒ¦°„Þû¯_
+ažeß7³
+N­¾´À¦+H&¶|n‚ŠÀŸ‹ÿºƒAÄS5šÃ T—6wæ"·A´`gúg–»Ð„‚hw¶+,/Yt ù¸—S²G[ V Îq(š÷r€ ‰˜È ä¼?€ÜC·D$²Æ̧Ëo™A¶È¢¨=`k?ÈGÒLj«ÃˆlÛ—Cò‡ZqOÑR¸¹¤XŽÆLr‚NÛKûÖ­¹Å¨à5ÆYnžàrdó ¢ƒi#"•e ÙÇiûmâIˆÜ<ð)°Q²¢Òñõyq°h¥9ù
+«ÎÝîJ¢<à5³`™ú¢Ëúåý‡§FýªíE44À –’|,¸buWïÅþÕ?þðšÿ¼xyÿðÕ»ŸÞÝ}¸¾ÿÅýI}úo÷âÛ»‡ïnº»¿!?ZV¿õ‹ïn¯þËõÃý»ÿpØ={õò›¯·äøÇÝýûõWÏíª?»g/oî~¼}ûò›ñ–@¾øåçÛ·ŸßNñ×¢îÍÍa¡ã“
+}þ¯Uu«AuÏž»7ÓK+ë¡%ºK;§†w¢r0;…[4k `Å[AIyUØ)š:ï‚¿V« ]0†•„GcÔsl,Y“cübwA
++éž ýeú"(ÞsB ÅÆùˆ¹àz
+7(”
+3Å}a’2blȈµ¬¡’QÏçW2-$£$õù–„)R°Uÿ;€¶Pð8,û
+V< “˜^B¢¬¨7lé’„5?eŽÀåÆ1¤W]¢Óž‡Xª0xˆP€‹3F‰<öBmeÿ¬ﱩœPƒ
+e<RKƒèªÍ'5¸3Yêlx+”\ÑU+Ê"†¼&¶g%M)>w Õ9c@K»×Þƒ{Àw]
+QÒZ)7^‚eÄ,IÃ/༠¨"ƒ¾™äH$œ÷1‹BC£÷m3#£oómAÒ·«±äæaoؕذìÃÄäH…%i‚¡hU2õÅ*F)<NˆÇy°z
+‹P°DÈŽvEF”žÝÃ(E6œ¡&2VšÌ˜êÀO€áòr¼úd²—ºÅ„‹ÊŽØaÖÇy‹HlÐf»{iÌ€nõ:QTO)ÝlRW;„f¤³s¨l’¥:±†”Cd1À%ä‚”o–Db-Õ"…@ï;<-S&Ô`)¨)äÏÆ8–ŒL´gÀ(NÀ€g¨
+¡Æl!p+É2G”di÷&[2:²H}Ò4T~2Önª‡{Š¨ X5%G–ZøKÀUÖ©u Ú'‹mÅp| mT¢Û†­S
+¦UPm«)v/rq•<o÷4@X¥¼ TinFEDA—¬x|
+NIïJå«xBÞ3¼!êc·ÚW~ÄÕ µ_rKàÆ”"úI"$ÅËÇÜ’5ßÝ]ÜÈWgms¤SyîN~ñP8“à ј/f ü`-x¦
+¢Ißn4gïa5 Ä•ù˜æ€Œd˜iŽº.<!ÚòâÌrˆJâmò¡ÝK“²œ’ë’hXÄÞÝEÉÌx*ÉøHwúªµ8á¤~Èv|oAê9œ,õ=±}†ÌØ7”[–žØ³ÚpQ"4•PÙ."ÚŠtªH3Ûé!
+„%Š*­Â|y™ÖÀ2Á¡)€œ«@vò]XÄ
+Ê)w…½’^J°¦ª’~¥¾\v,9ª(ú+wh:‰wd mø†ÈB Ì„þÖ:‘ÕåºYM·ZX[n«º"#ÎcŸ½÷)´™r³÷'z‘ë~ Ö‹:±½FJ­X`p@W® ï T€Ó…†9hMÇR“tEþ©·Ûêe_Ñkm1oòËCÄ—E)¬„©Ú÷(¥Þ¬:göe<T9J³çÚì'mzoH¾Jz
+qUÆo1ƒtÁ¬/ÛÕ‡7>ºúóh¬&Ÿä†ÏßüS
+Š —NFV¢Ø€Æ›Ixþˆç&žï ¦°)Ôu"9@â`"]"ËVœ7_’çéåÈ:~fX)ý›žšÄãlN|G¶/ÑyþÔª ëºÍ~ã{ZQTžÂ™cv.áùÕòs^QY½â¨°ÿµMë³ùŸ÷ý5‚ãqÖCw<1$¸C¦:»ñ`Íq° ÀÎ]h«”£…¶sØa$zñc0•f½VJ˜+œtÃߺŸÖcÑ\x…6A¹~:0ñœX® ›$ ¨à X
+„0,îuë3ˆÂ•ñ¨–:Ïw© ¡
+vy‡²ô6¤ÙèDQ(‰„‚~÷¶·oNÂï}p¥"º†‹Ua…Lú
+|×¢€‚íü±*¼Ž¯á]ÈK:*R‘£`&5»‰”+“¶W/L3•‰k&¥àú©êóî²~0×
+¸ÙÚa¿­¦Œk¯×Ks·ï[Ëe0ûF|&+L?RëPö²–’ÂJ2<_”—iÂÛCLs$€ ‘žš>¯+§S“›È ²žòœ÷„λPŠ¼ .b~a¤¸§^ƒQ­0ûâè|ózôb«%&Sw§¢±³²•·Ýh¯F™Ž.³Ôl'ŸàIÔb”ÇmßÐÊ3”‡dÏ$ÞÊß¡Þ6·<à«Ñ›/K“=WÉ™¡*‰Y/ßöÚ˜„kàʳdûº7‡ûb{ѹ–²Ðußš}n2Ux\{ѯ•Ü¤GŸ˜ô Çó5[Ñw¨~Sè~óøÝŸXa~þéñÝ?|ÿãÿñÇþ믞ÝëÊö§ÿŒ¡ÿëí)Ôë·#É?Äßü3]¨¾ZD÷JYáòÑ›lÚ{”}=¡²=Ü´†
+ÔPém!¾v“=Jh9Ö‚ÞrfÕ²àP4“´É«(ÄQ º…ÅywðKÌàåªíÐà@iH'4‘a¨(ZÃ?i¦¹¾. !h"er9ì‡ðçPÓyÉ×ýÛzn Ê=þˆÛû^)š¡ÀÅhÈá
+²°QݤŠks?TîQ‚æ²ÒÜ› ©–À->ýs'ÂgI÷ d069ꜹ:#`Å£¾3 `¹8­síÎwšEî »`ièH:›æj+ŸV.].”|äs9 kSËhç ruî¯ÒǪ,Yk UZ4¶²½Ñ²¤C"ÂÜ+@¡®`Š
+ÄÂÅpªº‹Ê ­“`¹Ÿø1(2í‚1Ìó~ Ý¢ö¤ÊbH4'
+>h½s‚E‚’BÒx½s;4õÅ¥k·àCÒ¢‹:ê|?€kÛf›Ò#ØÔäÜ6™Òêÿ?a¨ˆ“6Ì:kj0Ã*-×M¿•KÛë/¤d0!°ßá¿ü2»Mu'795º0u²ŸmÀ¿ GÒ3ò1N"ApÜÝ '  pwŸŸµqÇ^1¥8µh.˜»¦3Ó—Üù¬Å‰ˆ=q:MÚRÖPNÆH-è}DʧâµGœ‰À‘p¦`iAnÆ— €ƒôÅÃŽ…è0ÊÐ&ˆƒT˜õÉ;èâØ3²Ñ_ÂS>ƒT¶«áê·ûÌ–¶Îè3KõHø$¬ã’¹I3V¨vº +^bwM¾TqJ¿\xוnE °iÈÃ
+‹êi…edµ)R Jçwœ€9Úf}ÝVTY¨Kí`éæ¬8xJjöVÑL gÜ kèÅ]¡>|Ž’²Bé{b%åg}ÄË%š$~Ö%zá}XbÂûô÷œè—øí¿š9&7"Iƒüv èJÀ¡†*1:Š‚9®¼C™VH˵®ºyæ“dR½`g€5Sˆ®–÷@ím—&ꊜS‚} 7”4lfÀgvFºíú0ã”+(ã8éSù¹‚Íö9l<s3‚›á˜y‚(Ç™eVÑŒ„ÇNHâ´¾A¢åÑû .lÔ²_ŠîiK¦†‚Ö -¯ú™ô Ð ¼K'ô†Ôƒbf¸nç©¢TWÚ>‘küêJÈjßÏ\A¹+
+?}­æª(R –yp(NšnÌÞŧÌW¾Œ6ƒRWl,i†ÃÌ‘ DA‹¹®q´]^„ǖD®·gÃ`× ªBSwÍþMx™IŽ#QT• ؉óH1çÑ¡åŸ÷dT‰²¾´Ug€XÜ¿ÿåµêù^»Çd°ô5«: jq틘=V¨·TÐ2±¼ºÍå3±9€ÿFA]®}U¹6û Û¸jV@ð=V<ïòZ±}ÓkÕ«6Ú¯ì«=;ˆùYߪós(+Úsοõé"«N÷‡ÆüÕo\щM˜…S¦¾¡Â%ñ‚|ʬK#[œ1(kÿÁK%í^‰TkÅ<¨uÚ`i+Oú+†°íè8‘d@2vlFö5‘ø˜]\Òª$ÖZªù ¤Ü²!”m}Ž5£Bzµ 3Rï{.C5‰%íÍ„ƒëµùæP°‡úÏ=ŸEÿ;Þ žÔï“t0*C¬Z]äŸc=‘#ŒÉ™Ûü‹vøAå[ÎñVòžß¢Å¸GßK]s¡¥¥$³1oíéç(=mºùäQÞúuŽ¹1ÃŒÖöv¢k›Êùv#HOÍ×cfój;ÄWtic£ôîÃ!}:0ê6¨ëÖ¿áµõ/óÇ©?¤Pöɤ²\7|&3×A­@ÙˈF·ñÛ%V%]íÜÚƒõL¨Ã™{Úâ¼%)ä¾]µ&6Õ!w­™§nø.+DP+e {ƘaÿÞ;V@8ÌÐp°¶uŸNu?æ¯H½?s oÒÐkÅ6L½V½²˜·1E¨h8ÌMŒƒ‘aÜCFîêÙ6 òÊn&{FIÊö`˜f ;ÿ¾`i_‹4ø©SAÇ:Íàt¦±;Ùì&óP ¦CÛáA *=Ä n^ëõ\±x½@þ`()#oö)„ªSæoÑfÊAP`òaÛR§w¡UøvÐ:17”[T_…ª?Y.é`6JKÅSÎãÔ.Ø;f²(¾•Ìƒ2á”ñ³ÌÅ]ÚŽqÕw,èô'SP,ÁKðH¹yOÆ©izˆ=Z°oÃP&v¦ÕH ÞBr¥"U¿ó23)`Ô×9\ïÐÊt¢«hÈÓ4MÚö™&©&pæÚŸOˆõgeIYì’¨Á ˆíˆÕq­vÖÎé¸RUëÄìR^v‚ qÞƒP‡éð±bY$G ‡²’m—Yi·Æ-Ùg
+·¢Wo˃%îÞ¸õ™~dž½®@Ù<p2Êu Î\ÂÃ='´C )ºBÇÁ…¸
+SÕ£Àðw',~¦ vTOÖ¨0µ¨#”l8%âÃñˆ5À1»’±
+O9ÓØðH³®@ÆŠ+´ŸÙÌ–µHÿ 8ïg¨Öþü–“Ó‹‰ K{iá`dÝœ»å¨Ρ °QþŸªmÊß¾’uÁŽ©†¸ ?ÀÊ*63uÒ‡3VàðzÄuzNÃx„`§!ª<á,˜w ¢©¸…õ$¿öÖ’( §Ó8©µ¯A6nß·]·Ã"Hñcˆóª2#pösJ # Íà-|'CA]2ùŠaÖ;4NŽM(Rgìû€ä®°^˜¦/¦óïYÞâïÅÍc7®«gà ¤²ž|Y—e€Š?];Û˜*ÿ_¼Ð˜œÎK‡?õKÏ´9~T"ÍaÆ¢ÕŸ>x%EäG(NB‰q°«Lå¬KÐüÛ‚?ZÖ 0 àÙ‡…öàÀ@@ÁXX¿~«.Ü "ò±Î VRk À.-8Ö¬îVÀíK$îÒl;M,S(J;ÆÆ1g÷Ì "¸l€ò>ã£|:Z<>×H Ìá*:’V¢K5¯»g(0²Æ¸Ž«9Žã5 ÅÎyPÉùÅ€ˆ Ö¥z,ßF†la† 9}s}Zõ·iy!§òA8/Ép@ÏŽ趨D¶rÙX$×s¿ê”­o‘3¦
+áhÐ_¢q5š^ÑV<%;¤ë(æ¡àLT_ý‚DNxÏ­#c€€.ž3¶êx'T¶A·<Ë,ˆ8 ÎÌͶ|„·ÉéÔã2CÎÃZ¯ý‹Õ£Î-Pž¼
+=Ìþ—yçø¦G œMVzÑ%Šm`¦¢l‡l¥w™­,^ÙñÖD’¡Æ‰£µóÅ~ýðȽ"=y3“ÿ¢¶¸$úØ÷¬ 0¸?cMäáíMÚø'>ü1:œ]¾4K`ßÊ’ÀÓ&ÅŠ§‘Å6‚Bôˆ`ù”"/2p'^$…ì”,ç‹Œ0ŒD aÆè
+ÃMÿ©¡¹dl^LGÁ”Խ㾖Ózêv†o ¡áظòV|ï@XP
+ˆG
+È“w ”~S(ÀV:T¤£ì°–˜~a$tä:ˆf³ê­c¤ulƒ »þÑ=^ùžÌ]tMp'áÙ;z–.áN‹èPòL¡¡
+t Ñ´ôy2å„3bwlaÀ ¿«Æ
+@ ïò¯ä\Þ¹±€bÓsò1ðñ
+xÖuêú•·}k¿ß*+I¾ H*Ó¹ü­LnL
+q"ÙÍ„¹ j²Y­È¶ÕÌìWlÇŽËAâu¹¼>¹yúâo¿à¼ªhH¤(ÕañžÑ-[QjÐ Æè4Dar‘ˆ}ñR *5±¥¹{K†»"åÍ®HËsFîæžÉø»Ï
+S„©¶¯;ˆ3Ñy?—Ÿ3KH ¸xD¿^fJ¿„¦
+ör†<I’‡Z£ëqWﲇãG;>Äò¤wŸ=¾ðD ÏæåŒë0ADá®Ï_6…´(>ƒ©-z™Ç²ZÑlëà‹í½øŽ¿Gtïžt]¨hiE£³TpL=gÐa#l>‘­‹æ $¥Pb•cÐ=µÀtÊ”¹)Žgr{ •ºä°K>×a¯a'H‘yý€ø!F‰‘(㸡]€©¹"^¡ߪÑ(;YëΔ]¿"“V=fZ(M?I3«óvŽ·1+bdÈ>bÍ`X y¢™,¢›ÌdâÒ³!¹—¢–%Ïôón‹ø‘=ñÀ•c‚èò#0~Ù
+‘+‚Ü+ö>¸e¢Ã¯™gK^>=ö#ü鑤••hØ¥Uº(h,ã":JöŽùÂóöÅúT+0&‘>qµùá–È{S îyÜ„uÈÚ®—PF`Áâ$ñ *ü dŠUŒ„>g4Ë …×côÍWv"b’q­c¡ ù šÀœl‡Æ€²Æ!–1”LSÕà@’|6“ÕJN>%Kß"ì2FcœÄ]îcÍé\¥%ËDzUø1$•^~ð™÷ìr»¸ÓLUAÑ ,)ÈåúD‘Å{SmpU":'î_VU4C1¢˜‘AÖ¢L)ú"³ö­iÈjkPE‘ñ‘ØI=€,f?GuóVx´>Q¬›ƒyqÏ8ï¬.“@‘AyU
+Äê<÷âùqËŽ¼¨`B3̕゘3÷¦¿¯ÈÅÆ=žQöÈça^aüåsΡB©ÒNÆ[Äx~‚ÅŠ‚õ|ÓbvÅ㘚¢Š~ÎhÁ–U=V“Æ\W)mÄÕ»\ùt;
+ð—cÂå4š`€Vë"=6_dÒ;qÀr\@w3µoW»µÑnÂ+Ç÷›+=ÅÍ-bJÏIøš
+^€-ÁR(.¥Ÿ†UÓùü?áñ¬P -Nˆ?á;† =
+—X)Ìí‹ùüyÀ3„:!Cc‚tœaÒË,ó¡h}ÇK5[€^øšÙŠL@œ[P¦’#Cј€L†Ù±‚é ’%¤D!©{‚°nÙåðÈN´SSð•›HÛ¾W%—sØA´¨´%&#hbæV·ˆ8Eœ«ÝGz0 P+T² ¨ü«Ì@'º
+¥7Vh0Ò¤ƒ&l²PÃdQ÷¦7aƒJãè%=³Q G‡2 ªÕ©bê*=Ð$¸\öéîÂAððVµKõà+nü=
+ÕCeh ËYb}Ùma8ŒwݱØ?ß]?
+ä,É);͈ì2’hÃ>-’ZãpÉŽ–á—+µÁ—³w-¸¦”okóÓ³uA4•ù4-a‚]ö¶Ž¡YÄ)Üx3X$ÿp¶?þZK„%î*¹[
+RéNîÙË‚÷–4-"%ZÄÑÄt»¨:¹h!CÊZHœ-0G[HÁ¾`6šÎm7¬_÷N²tìeH ëê%ây¢„¹bp²h!cê¤~ õC‹RôjƒÕa— ‰!bûv†ç‚óA8çJP”9Féê ¨(ɱ ĤZĹÂÌӈৱz£8öçH—ÖjJXK-â´T¹¸"Ž³I¨5‰Y„© ÷Qß*¢úª`tÜ‘’íu PçÄt‰×b&-f±ÂfâHŠrÆ]Bb¼ü‹ʸLj4݈“\Æoí¶AÎ…áE®™Öáâ$ålËmt•R‰æJˆ4fÃá_úp¹Ã\ÔCÅ; 90ÿ䊯)³›1ËÎYöœÚ<›p+Ù˜}^XÁ %
+vDQ
+Š-`<ú;Á‡þqt‘MÅ¡ªŽÞ©êˆ1jÍˈñÎ>riàÛš~±ipÅú¨ÞóÒðn EäÛ´…£>Í\i`nÂsrÅ#šŲ¢â0ËžY‰ PÖÆ6<Ë‚RŠëôã ¥ÃÜ•¹uýš‰åö˜è½-5Yå"ÒäYH±¹ñ‹0"@¥EÀƒÈd£?°0"°íŠ;Ÿ`Fm—-Ù,üƒ|
+¶ãø¨E1XÉ#¢ÐþŠp2Š
+âÂ6±bñswE¥Søôäà>êÑ…œ,Í·ã’ÈbV²›–b%Ãz#¶¯gêÞ“îÎùÈ2vÒ“Ö3EDÙzƒYj½ì©¿q©Eí¥÷,U]Ö,V4y·ȳû·`\À…» B{%.8V†ƒ’Þßá–±ˆˆò¸FÙi‹YU³åÊ
+ÔX[ÌgE”+ø-Vpb¬‚Sò¥¬OãKsµëK܃DóˆzvnÐè#£‹b#þϱF:yBŸËDÿO#üsõ 6"†k’9ÞRðyXÕÓ)€8Ù%ȧ îŽè»Ë’ cE€ò… Ì6
+êF õÙEE'$©
+Äôqã ®¬v‡…#è]Þe!05M­!±qüiýXy‚Ý©<@œ‚}§Èu9Ÿï]Xx&ÿfPƒ=Œ tìMq–˜0v3cJ¯¾ív:eF$œ;+Çïö¿³Ë£>A”ÌϽõ{Û->¿N›P‡s"1èê´.%Ÿ]KÌÃ6vû
+€'×qð›`u0„:Ï%hÃø›»Çß°ßÅðz}y<•«8vÔ
+Œ‹õþ ðÆw­}€Jâ<e9ìñ”ZƒŽ^JS¦½“Ö¥½€xaAÐv…!IâkWAäO§Å
+å¦AÊÿÀ'£ù—À}‚d3A‹ìÂ¥dï†Ý®òkE?5X4°æ™*Ð/5F áÈDZ³xœúí®][4#‡Ë߯ÄÔDpô9X:õ ŒÈÅqHd7ó2äÕ±Væ -VA'›U•}b|¹¯Ö^/Ǿ×Ö%Åq€Ž²€mø¤}wÂï’ª¨s²—ìØ"³i«•7bNZ÷¹õ!]Þ:g€(t$]g5Å¥Y[ ø¾Ú€ï5æJ{\u€…ðÆ·pe±kIË
+GF|`M”¬¥6k<«ìø]߶^‚GÚƒtG´
+F«r Ò"Ø0^gWôKÌeS æ¨†­$™Š¹«:_ÀÍ„nbW! KRoÞ .“÷1
+H‰Œ—Mr%7„O ;èSAâ亽ì[tĬÔ÷ßÎ’5¶^Qn…ívØ/‹$€D"1ÞÿãR./jÅky«x1µ¨aZDµÊR‹ÆDxTq·b½ÇñëM¼]%Jê"%Æé”vq¼y¸E×°¡e„ñc­ 1Ž²â Òk´*¦:jß7 ­£ªºñ[‚êUuhïR‡™rNç1Z‚«Â$·è„ Ò,O©½®¨å«C¥pwèû·3¨Yµa:š¿ÿ|›ù+BöšrÃ8€>HH{Ë€}ž¤WQµÅˆÖÛªCW^=”(lA„ú6“1!<Ryœ´ ÄÃFQù‰Kk-ÒJ)}´rB¯y‘wŸçØ(­òW »!ÃZínMªMHSþÛbT©r€ì¢·TŒ‡=žÓ. Xѹ_t_eŠÂ¨(á«êÅÜ]]}N)¬fìw)j8Ïu¾ßÓIsu4êÌr»zo­T…Ý:ShIî¢E«{kó2c}X¡< ANI^å|Y4Ù"¶á ¡T¸)\¨åæ Tá!‹vÁoåHëLà yQü1ÝÒ·ûî«íÅ„Æ;B~¼ý—ËŒœV+{c“Ùj§–Å£Ôñþ{b„*ç_ íƒ×õRÚLŽ^#‚à³wSü’€Öœ&ñJ¤º
+’`rdý}=¸ziP>noúÂÕgàÎ?x8çµ ×<ËyðƒV¤ÍYÖ÷³ßl]ìMÇý„xšÁ?Qøo/HlJ¼‘OåpÚï#&•Îzéa–lGZ@o¯6Ú†Ðp¨„³ßÀ/R†Ø5»E>ØJ Ѫëᩳ¨úHѶIÃ^–ÁM´Åj,úhþ,ÑiœÈ¼)Ð:Ž> V†85§¬½ŸePAg_Œ{øñ…ð@>-«ˆ&G—æ \šÁx« ²¾Én­ç %ÊÛ™¾(öv1~‹Öoƒ>‹áÇÖ³Lô÷„Lj3êC-!ÎnCásáðôƒ¼™n¦cèfÊ‚x:‡‚7`oÙzÑði#g¿¬Þò‹rÃT\Nk‰AòZ¬éæä½ä[FˆÌB ݽ„ų
+ÎÑZ8„ê©ì¨ÐÊ«pr¬Í/h&ìÌ*W>¸'±™¸¥Ý T–<ÌnÛÄð«QKHš?Øb²GíA*Ü7$Xos5$Ú6! o(]`i ‚ eŸWhÖ&3¸Š·ó}âÛ #¯‘k»ætï–î=7Fi²U™‚æ^Ÿ0ð+tÞ+˜'ħïsØM£tÚó§üWHßô]ˆB“±…²izÛYΛ¡LXšÁPg¼×ÕZÐBràÆ‚TI‰f¬KXøœüZíË{~FìæC&r݃¬z:EgHÑ%µo³‚Ä öH~èâÕ(ð¶­j5 í$‡÷ÍQì?mŒ"Ó´;{šÖ†]Ò¼–QÞä¨Y~FÙâý<ÒŒ÷zAÿ4¹¶&ZÅáòHl»’Jp-ü)+½i•¢zvÜk¨@J"ZÚ}Êc?JÄDZöá¬äxÎSiy ù§A°I¥]hhRË°ÝŠƒ+—[¦Ú^"V$87Ï‘ ;X.a°ß^ˆQÁOx™Õ/Ï1äÔ2[• R÷Uÿ>«æ†¤,~„ˆËU6_]GÖæ`nr¾ÿþõ¸Š>N‰IH®±%ˆ-Y£ËˆkdЫHN(¢“9¬ì‹ƒŠT箕¯ÄJ‰1|c@¤Br ϵ !HM£¥(ýi ™NÄÈ!A…U‚²àÆLá+"óS˜Xø%…dåËcˆÇ4÷Wôìô 4‘ e­ë¬ú!(@žzDñ0wõ” OL_Èà9¦øùTªuÕ䨚"ylZëÉÏ×°Âä£ùû1(ÊÒ›§H!ˆ¾ozMN&¹3¬˜^3<®n Ï/Ž…zA,J¼Öûõ˜k^Þr ß3¤#‰?eæØ ŸÓûçŽú‘—U -iÇ9Ažödõ[.}˘ëí`a~1/ô¼ì°ôýéEK0ú¥¸•ÿ1^î8šäF>ÁÜ¡í5~ðý0…Ys\` oÇÔýõE’ÕÀ_ÌR÷BíöDÉÌȈȦ(3/n5¦àð´Ñ.~€œKš¤(Ä÷7w@De<¾“Ö¾_îqß¡«mTŒŸ®=Ê¡—MfJÆv+¶]
+¿¹ ò$ÒbW^*#Á΂ý40iÉ0“ßá_zþ\2Ùv\*n¬4„ᙃ•m^â4¾IÆ_wé„Í#þp"ÖA三ù#KþW°>À4´ø‰ zks5Ë
+¥¢9Œ†sÛŸ?<ª»Z`ÖšUalµñ¦œiõ6["TQZ.³¹ï¾û±ú¤HA2 [>øzî/)!’„N÷; RBþ›Èv%ꀬ!Ÿ=-­@óÓŸ\E\ Ùž~‚6êL(ž$Œ'šž g*Î㾺OªKø;hM=;ÏTƤ&DÙ‡˜àn1¡¾´½¦¢rÝéˆþ¯ L僣æj+N‰Ø
+ê1RAìȆè‘'UH›sÍê -è’Ôi]œ×’f˜WÚ‘úè)°+1Böþ)¤žÃµAÐœ4SšB'á.,X¹œˆEx¶«Ééýð>¢y„¢hI.ñÊ,ø'ÑpJ• R9
+ÄÙ< ™¥¥€P›½Û
+Æž?ÁÔÊ F£ìsA¸j“”Ö>Z“Êf 1rl„F—§x§dseå Áú²â_O²]õ>ˆ«fÜ„_ÞŽè°–ô=áþ£5t©Xî;‰iGl#þFÿüÏy5ô/ÃÊRm›¹§GõžÙ 8Ècô‹£„– ‰_î•Ø…¼µÊŽr@•?d,ðo=´Þ4I.þ«ð)ý"?0ó«Ó§v¦#`~!,%eÕoÕÂNr:~ÿŒÃ›ûeþÝåòø½8î4¼—øë©ÒF–ºFLƒJÒ"-{Ö rd §Y-lüy
+Z*!=y§-LA}ùÖ"ÄS7nXŽ(µdF òjL±?÷á7ˆ=ü(àù£ òƥ摅Ñm'&œ™8¾; ¤Žrh^C› ‚ýøðÈ_zCQj¦jÔî™w;¿f²’_X¤g=T:’–tð½d–Xéq‘Þ5ŸE;‰î‘„>úäÙ¶6XÈh'a2Ò³xŽ¬Ÿõ°›J¹bÀ¾Å»}sV6XÇZ£ü…møWJ<ÐF ümž,6Tv-(ó%áT–£Œˆ»†bÍXë{m„…AâJ/÷ï`ꞦbF½öá¹è¬Þ$+péLß]çS½úœOã…"Ùüý%(U̲V±o‚L\Hµb(‹ŒY<)=ºYëaUs·ÍÑL*ˈAGD†€´‹i\l)¨bê©2öªÅˆÐ>/-ço ÔÀ
+AG‘7
+À+¸{ð
+Q$õgê¥tö?½ß¡(#ÝM#F
+Od“ë+ƒ_Ïi‚DìŸ1÷7æò] 0A© "Ü3$gËß\Àm˜ºŽÔIsáé³ß8öך;s£ ÂJÎÁ5#Dó滷Тwñæ+jqH€ñù
+—äþÝ­ÈŸSÝ"çlÔÁ»iíýà ­^½ññ›’­œ%“üÝ™ç¢è 3,‹ìöe…ŠFB7&¡\sa8—/ÿ‡ÆË¿vðk¬ZÌá«ô-æù]Bƒ Íme€¾Râ±3]Æi¾_SdåZ>
+b2àòºeŒ[Ï“Ñ‚%1™x9â/Nõí1ÈlÛñ&q1hgâ3«áž[¬ºŠ-‹õüR2>eËoó<báÛúœ 7·õì7·T Õœ {€ô–ÈšÖD÷ç zZUõ¨×Ò0{Pm‚óƱ6qwƒX"n D}šÎë8‡éé’+ÊèŸC°écpE_‚äÇoŠB”‰l¢ÊE¯èô•ÙON¦[³„z^æ•¿;¬œ4CÍÖ½&䳓YÌá»ìý—|Fe‹lÓi”Yõ£$Sý²Nfã¦ñZÒ‚_÷'qõ{M÷Í î½½Ô-‰Eí 2ê18u„2WÚ'/Çr –ªç»¥ßÂÄ-óërö(rNëþ,iÚ>=ãínfóˆ’®9 ʤå+æÆò¯ þ{MÁ<X8VÆ庈ÝN|e]}¤9Æ…6]´¨QqÄ´á¼7+FÀpbÜ‘ŠÏÆåÇlžÈãNÇû€Æù6ª´ÑSŸ¢= ·¬>çœqᶅØúSáÉø6é( \U|µñ¡ï5š'5©9%—pu_>ÊkÊ÷Áy5n²CyÍÎË
+;~=èj ^„ö¸_Àvp«<%¼—{DNæþõ(þ …­N¬C¶3‚Êë~?•§_ÿuµ§haã»WŽÈø:ˆ\ÐwÏløÝYe^T²"Ôb}Îø”qÄJ½Ý9m,SwäG®7“ ¨öî½°Mݘ[žO`§<ȳ·ÚçÄŒW{9
+w‡…cˆc< lm Ù"ÆËŠ}LÁpÚ2¿´(ªÑÌzF {Îê†nÐýð Õª" mçx”ÿ¶…%!ëš*ÁM­=Ï Tÿ-³[¼æñJ‰P‘€T¾Eª!ºç[R™ö3¿¬Ç`@jå5pZUü†–>Õü\ÕðŠ¶
+Ýh=3ñ±®‰Íg BžƒF¥›ÝÏÄÔÞ§w¯»Xò—’è—…áûõ(]j­ªîŠ¡¦R"Î_:™’¤Z" Õï&š«¡Ç¾4&щ>ÖX…µõ84Úb#×çôLŠRÇ"íïm<ë5Ã’Ó°P{½Ž±¬´ëåZ;uIEÆÛV.%%ò ö96nå(—%|£pøßƲܷÉý_Š>~S”¨7hFc«0<ì|ÑxV¨cAî”$¸éDvöõ¥5Š7ÍÏZI‘H·¡³>ï§ÆˆÖômP…Azèã˜ÇXÞîŽ,æù¼\ìdCåœóž)?5ÌŽGñÔh2§‹„Ú®7 xb66+;Ø óöØ¡ó\ÅŒxûûøˆòFˆ¯I’wÄ‘LeîÕ9ÔŠŽ˜òödˆD,ΟÝ>ˆÿâÊ`tãѶ÷ÝÔ'pD9Íߨ«å’{º1ÄU4QŽšÝ1«õ˜öÖ
+ãèò¤:´E÷ó6X[ÕP^BHç \}ŠÕß¾ë|NZ]øKNZ=üKÉx8ÜEOnÀ´Vç…bNÈíý+CýÝÃKcœ¾r¶çë‹L†wÔÙŸqŽ$U'MÇ´FŒ%‰e°ˆâi>ÞgZMºépýÇ
+~ñ'z"uhà
+¯^)eÊ—YÝe–´âŸÃ¡ç ©„RöÙ+ñÇYf4+ñž2SËÐCI>Æ:k§LùÅD™k”°$—Žûøþ8
+o·´‡w”D>ŸJ(Etqh¼ðÌoŒs¨‹vÞ&‘¦RHȵ̈çIfR™D/H¨aŒ{›\ç÷ع>Ô[þ‚lu¦£c÷œèV±Î\9'VÙÀã‹®™ß•ðÇø¨‰Êoš>3àµ-2UÒ¿çCÛn¯<0ïɼÌÚã‹å³ ”6ßqJÏÞôAh(¹Í²„ Hwøò©eÑ'/š7Q
+Z«-‡‰½ãëØ“‘ÖD0P]]Œ´>'NYs7nà ö½CŽ #K¶CÆÔ¸g>*ƒº°Ky”ÿaê
+w¶hZž-i´”@=çø;¸c¶¬ÿÌþ%×%~|&`ÝÙÌ¿ó*TÒ[e9ý².Š>~St§§è%zèWœÈñœÿ€‹æʼnØqµà
+ 9TêΨÐû÷¹ÕýhðM4–Ah¨šþÕ­û cØ_7‡zI‰P•Å2dJnøyÇE´ DêÇvÞKb§¤L›e•ÎE G1—ß³óœ×a=†5M%ùê
+ý÷Ê趦Ú·µË4¢d” yÐ\Á.Å_]%³#MUZ
+Üj˜çÁ\~clæG×3´%ÄíÑ›
+H®éË»xÂ7&¿¸æŠÙes$D_V˜QÓæYŠw,!Œ¤ ØzÀCΡà8Èœ ­zæÃ
+4‚6iò,œ¤Á2c_
+
+óERS¾ÞîÍ2>Ãv¯L
+\O“‡ÒŠ»˜®ÙOÙñØÎ{Øì
+dÅʼîë0™#éx \„O.…2ö9‚ù› ÉûDÚ@K!‡æ{ÈõJ$æ~_\œƒè.}}ôš<Œö§?©øbY¿ËÙ"¹Y™p¥ƒêù®³‚Ñé¢í_OŠ(™Ð4ߊËæ8Ÿ8a‰¦
+nkH:JÖ2 Öd>xm,2"p$u¥€Jƒr Ρ$¶Rš1FOVAú»8§¸ìÔý,•npxŸýÙJ6$‘œŸ„Ã"°ö~zÞCÁ—&ÅF‡"éÚtaÏÂg×y2Äx¼¡Žw9‚©¯­Þ†¢LoE­Ây|ß©…¹V8véV=tûqÌ<žå½Ó•–r,ŒðÛy
+ ÌSÐñxRò¥Q:m†]f¶-çÍ¢?Â…­,<èdèÔ n×À%-CÑS‘|v¶$a‡–mÝ·»}¼r¦=¿ýõ­4Z€þ›h8™ ã/%äˆ(‚©Í¹ŠJ}ÇG)õâ• Éí*!8÷Ñy• $¬“ø‘¶Ç—u$;ìEð.ë LýÓUF˜Y¤k4 Å·†\ÛÎsüXà4,JtU|}&?¶í¿”å”`$8ß¿•þ²Ò2”uüPôãIQaÎ2B&ö5ÈÝ@+`“+lÈ
+Mƒ½Eµw¶¨¨ (%ßÂåOõˆ†!c>¯”¯’š!µ”
+KdŸ%\»°q(›WZÚ¨ó©¶kî8¤UFC¯se$\°B o–U‚7%-œGÝ=5îˆ‹í©¸ã™©÷Œ9§mI×:¨
+°Y–¤0ºh%äDŸ®šKù€÷Rªé©çv— Í¥zÀ?pÁ4ÄgiæÖ•à”iÉaj:CÈíÁ­°ƒ×Õ”Ys^¨µ+sÜ<³ˆ…^5 5 åd¬èNP‘renÀg<qšÃÅ"V5N9wÌ4I_vx^A©$÷Ë僵Ä/x0I‰"Á´±½]!3›œ8ba~D O,ʆ€ñظàÀC{É__.ŸóC¯äˆ¹èÃà°Y^“E‘ŠgôZà”ñ’VmÐNø{* ;¡ä„ã.B\9Û { âp(©øÙN<á_䋱³¼+oôã´Ý½èã•3ÉNå[5&_Ó©8zBŸXg ŽóZ‡¢ƒzÜîà„~&]ƶ ÃpZ=?ú¡í%âÆ«~°5Â%£„®n¯=Þîq·k`ƒ–¡„.*R ÿ¯qe5upÀ?õM&ÁÞ©0&¶Ýr2³Ž©PXÒtrbæk^¾^î,¬`l)bŠ '¦®Í+³ðò)–Û¬jL<PÏCfgC†C>a,èòçBÝi<sÅBv(ù)|À¤ƒH‚„.Í<¬Ãù±¤%þß·JîlŒ™èbF´Æŧ†æ¹¡/FƤ:öNܽt‘AÝË`[R«ÎÎ"Œ>€…y÷¶V÷fzŒÆU§J€ ¡ «²K|ÂEœ¿•à¢ô.ã‡KÔ½z»’#Î…Eä_„g܃#{\­bDöy9“ïHÝŸ\üK;¥Äü7xèHá$ÚI,c
+Iyð„QÛ…OX¿¬(뀋Spñs †"OY±G>Ý™ ÂJ•1iíŚà?nöZÑ{>^à'±ØcÚÿüçÛÿ~kÄ1°—§{ÅEr>Þéy5ýa!´†¢÷V1°j‡FM5t–é˜J—ßiŠ i+3<šŠ:㑤DÉ{&’«Ëaa £hjp”“°\k¥pd&·ŒÁS‘a©‡‚É ¬ltI—fR5ì 
+óhsá íÔR?}¼
+~W ÞŒñ%š
+ÕQ45Þ\JÔæ*rQ~Ö!?J¿¼ðk®›AÜ 3$.NÓ@û»ÅÝÌU—±žôºµ¹¶ø)ò¶Š€Ñ”q†Â§Ö1…ÏSw»„zš±»E%¬‹°LIyo…$Õ¢‡Òh«.}CÆ´ÝÜECm•:xª’
+%_©‹úE D‹a…ÖÆ¡"v*""A›æœŠjGh1«LÎ.aî‚LSß*!DòÄ9aáZ¤i, :g§¦ÑÀö’^Fd¸‡‹×ˆDI$ƒL÷y=Ÿ¬R.dN
+%QÔód-yJöÿšsIÊ@û£1@cº]&ŪºÑ¢kŽÁyŒ½ªÁfÍD$cß·g=Îú§4i§Î—3\íÁüɦ9ç4“{éõ,Ñ0kpø¤¶ÞŠ~SÍü ÅÖ&U|“•¹îtp?¿?†x¡Á÷H º¬rBè½¼­±`t…„&›dýî˜Êë>Öi÷£€Ö»æ9}eunó ܪ¥,×\¿(´
+ §P=¯ú,²25Žbc…û9š¹QÏ;x%|LÀ{€V/Ù般Û(AæW"—7쳨 5Ä,ÌšD%4à­#dДlNs'¶è·ŸÍí³lÉÈ‚~O±àlmÞä_
+žWxq¼&œ±—^R÷ÞÕýÙçט Žµ”“”’wð+0_ãÙ®feƒú`ü’›Ìzß¿”}œ*¾žyÕg‘v“7
+-ù½ó|ûH/n¶¢/ÔÚµ¡ø·Â
+Á}Ej‡ÌHæ-W]1¼Q üí.¸B.WwÎt¬‘fÎì§èð6˜Ï¡wzàsFóŒ±VâªyŽéã™èrtÃ14ªXjùÊ7Ñ’NÖüÚ™ù3=×üº¶½µS–d, _ÛL©~ˆz•sÿé|Î8 “vd bvw9YÁ*¸ÅH)bìM’Í>?š©)‚ìaêRÊŠhéndŽA$.v槛ó“æÊúïèOJWÄôvt„†øKzåí ‹‰\øÌþp»g­Ä-«5/:x– 8nÙsú€–½úò̇‡Öv.ÙWwË‘XV²ìúóBÎ@
+ç,¼«Å…í‘WmÉ",s¿¯±§(n•¡—#è”ÑET{$(a[\š–ì¯6¿­Ä¹éD¼LM°³59cÕrU¸!.Hk¶o‚;ù/ìÃG?'ªèdìÑî—úQøS,¼ª¨aþÖïk:"¸½ÇMhØ»›…ÛÚË’5^z‚
+¼QGvzîkÅ£¹Yà °R‡UI¿©$ÆCu[Ÿ³…{Ù³߸ø˜=Ý;I±]jå—7Åõ ‚äBlRW½ÙuÏ1Nlo[5X Äw…î׃ÚYy^wàŒRWW"Z-ÒXVk³ÿ žŸø%ÿ…úì÷e1HqYl±
+gÞé+ïºB²ä/D›>‹þN]‹Á(ÝÝ,…
+p´®L:^´æÌ ¶¾÷ìÝ»®üRBá(±ò+UZú öŠ§Zç)T‚ðnW˜}\u³ßvˆ›²£èÞºŠ\QkC‚ÈâÓÌï-ñ vD»®åúd›²ûÅý±b±ÅŠNÚNd|wË¢3Aø¯…¡GTRÓ áìIûlìÙ´ûè¾õY”ô«ˆ uæÃβ>çàŸ_óA«WýäÍ1=Ùf+‘bfÓð™ê öLdõO'¿š\X‚ä|Ôåbø'Ÿ¥ž5ŽÀ..ì8åäÿƒ¾ÎçBÆ“Í~%–·ì-9ì%ðo7^¾ÌSü,A+†ú7é¿ÉÒÏ'yoꙀtf/Ó›¥º
+$;ÜÛŒGÏ…ñ&‰D½WíG›èð¿v1QûxOÿ Ŷ£Ž¢»vÕŽ»Ì‹NT;ðtæ©åÙüôÉfÌ>ã56
+í~ˆêÄ&™øs¬×¼áX”#Øþ`9Ìr`Iœ¼•®RtFD³âäé LIôFI)É«æözlË–¥Þk|ϲ™Yú[ë¼è£FwÝk]áûkõ)°qÆ·YÀ;pZ<ÉâÓØC´ÁIsN­±Õ„ºøS¿V ¶°œÁyçÕµ.çD(X»,#K=½ÂǼí¬hÖùsQçCã9Ÿº
+íé[CŸœÙ ÐP…¾ÔºßèþýL[bóŽx|«ûŒ"¦|r!¯-õPÉN‘n[½u"ùÈ›W ä‚Ðêó¯ö,Oùàˆ¨5Nšd';
+× ‚oœOJ,³4~íe>ŒŸLå£ö9(|Y«ïù±Ô–XAÐlÚ¬KÂÏ’5}#†™„O b¹ËÄ÷šÿ®kŽÿ3^/»vÛf€ŸÀïàq)QÒ°H‡™öÚQ:ìû÷[åÀ{s#>^G$ÿ˺Ä="é{‚
+ùúóªý‡ž|¹—˜cCp-û„è4e5k§z'zmw†|¿Ôjå£RÅaõ-o bj] s˜¶G~:íÏ_¹RnþÛ¿Èî?þýí·ÿõDyâ›g˜Î³[É£°$;§´Góȵñ±Y6SªÈAB"eµÛÖZ Þ¯#èFö¶åùˆŠªL;±Åã«4 ·´T™¥sËÿ¨ädÐÓºã;áÈXvtˆ¢ß„üêVdQãȱƶû(ÚªZ¥vóv,äDáK[²ù¤¤.3†rCtud“A¹4ÊÍÚMK ²âô×VË}’<ráI÷±ðÄG"4iáêÅ©EcuøùÎReÕä…¥¿ÛÌǪ-Ê~nH?Šöql⦠³ï”Ѐ.®P÷Іcg„R
+wçЂêMZ­Ô9ŽBß>AhÅ™qŸbéö¤×¥íá»ö€Ù,ϳcáÊv¡lè™´Ö}ôÀ8ã E Žûœ³õ¾†èÏuŒ„J‰;Wt¾ö Ë1ï ±ÍXàA—)¥—¤£8û­[î›Ò_”Á$µþ ]{ñ&TŽâ/LõÙŽŸdê ”çöÅè©@Êû\Ѧ ‘Õz,öÈÌ¢ãLcھȺR°…Ëè7$1òÞõÜÊøåÖº¾tJÙ¾¶¤3SG¿L\s½Îfm¡!$xù¬å›uE?\.Ž¤f=,U=ÿÚÒciÕvÜ'• ŽqJt¹1{qCµß®½_ûèbLë6F£7 Óhü6m»ª¬G8ºî?´“…ŒŽ,dzúÒ }•©2fèbõÌåÙÊ-zjÉðÈd×1ô£HGW¯èû6ÿÎ’ðeæÈÁ3ðš(¥ÇvÑS]
+ìÞûó*Ã
+&Înå¡4ÄvÙ¶ë‰UòDYb²2†É‡Ú¸1›hPL‰—tzówª(…°óú¤KÏj[ÐFq¤o\p×Þ5oQ/’qºhÜR””JôG‘2Üxne\&78­h'ÕVZb“YÏwÑ[üÑ5Djá{½Fù¬Ô˜¡Ò¦‚¦/‡¹ßâÖÝú´……01)ПŸ@v<L’
+ÁN¤øüáßi®Ï`¬~dÅÍu‚¹×|ÕÜxÚ?ÞM/®HÔu›d&ß)‘Æã9‹v„„zÞú
+Š|œH=°ÇÂŒñç¼Çá“]ÀÅÅëtVýÃp̵[l|.yÀw4˜¨‚âé8³~ Æ`Y|š]Î í'#¤|V³--·+«hí !œ =Ø%ÊzÒér¸Ú°EMîûQ¨%Ü%Ú^.ì ©gc­ëërvÙ´´õ5aØ3-Rê|y˜dz#ڣ̵‹H¸,ß»Üvñh±Ìk£ YMyçÐ.=Jüª—ízŸó2oOŽL Ø…‘õ²›/3©9L=©¾{è§#}.L`lA–„FªË¶ÐOƒŒ6$,<‘”U÷sž.‰Y&‰¦ÏÒÅÀ¬g:
+Èñ(x »nz™þüÁ\WWü¨2¶AtÈìÜ
+1CèvƒAœt?%Vx2qÞSÂüB2L¼Îë¦Þô#XÎ8
+B‡¡^p6ý˜¦ÝàŠ>{Ã
+Hzˆq7%ê7é¥+Í´(*¨ju®?ÚÉðÉD]=¦„½›ÈËŇ»ò÷Óz&­'sÅìlÝk“3f.gH\þç›"(°°ƒ/¹Fù {¶ó'2†!Öâ½âS*á5Ø2غn,Û¬žw^„ŠDÁ<´¬fÁE[“Ar ¶kdHÁÐ8$«‡@ñ˜Š>rÙuQrç8àÒ®šŒºòA˜‰ä§ð%ð6\ò‰e’%+Ÿ­)‹L>Þ@¯sŸKN)²o×Ux¬ÊÿË.ð'„!t:ÀŠ:¹iËå»hÐ>‡U¥¡•ƒ³ùL3Ì
+j³i‚ï‡X^¬=”Rk‰Ï¡4âjkŸçH©é•4,*ZU
+er*×M/À?Âg´6Ê°8š*õI#Ú>: w!'íå‡ –ÙFDÕøZè‚“|Í-qíÄÚpڞ夦HPÍ7BDW ðÁíûÕ,ØТLóؤ"ª@„퇋Ï(DZ™¡”¦<T>1 >b¨Ÿsœ’$½1ÄàaJñÂG+‘žW%ÈU–§s©Šø­`ýYœýÑ°&f!#Y¸åP^–:<÷ÀKÈÕÀ ”ñó§ú9©*âá­—S¤&Óï¼l›I¡†ÓIA:ÄI‡³šúþöIQ@JS‰“[…C·=ÚÆa
+Z¿[Œ& ` ë*'`©½ú­ãÔtr> Ml,BóaÒ·Ò‡–|W,t
+— D.ÃÑ@üμIôW¹´L• ÀÀÒp—}¼)€‹ÆÇ(Sƒ1Ø'ù±(Ò'ÜíÐ)äI÷«”žÀd(³M4JÀ6g}ù¤›ûMl¤¤´¶¸à+EðÈÜð'±,¬³;Û”O{!
+xXŽKq
+GL/ïa`øÜ’ä5²·Fæ
+^“ PD~ZtØbÙCPÚ>Ïùˆ¾c
+–WœéßKÂÄCLQ^dÜ8¹$S°}»v.± `Äy|Ž~ñ€ü7Gy1Ü„{Î —î™›¨ÃøΟ£h†ðWqja,9F(€PÒÏ£qQÔˆËæEòÿ%Š‹Ð4¸º¶až½¼ÇE5ËÊr?¼ÍÖ+/r,ç’*¥×ŸÔwË‹:¶uœJ™yFy‘c)Dz ©Æ‘¢¬4Ã
+ÞÒb`üÞiQ”^õRr•Õ(.Šü,‚àè6N¬¸ÅEQ(Œ<™’íUx¥EQqC7`ÐéÁïÅùÄ
+1$“©¤Å@:^a‘ Œ&>‚°¨l¢kúÄ„Ũä¿)z„Å¿ÚKeEÝšó.cæõX^¥µ¥âBi<eíM;½í¡/_Áæ´ÂQ‚
+!å&êÀÁÛ‡rY¿J”ã¢Çm¿þ±Åm ½¢;,rûiÂ%ÀbêL|ÝŠÄaY '
+˜þ¥6ažô^ ýÆ+!¥+,À±ú$~…Ë1çê<Oy‚Š¶]Ål”ä±jÍ×I<¢Fp•%èÀïŸLN6VJ2&
+ÿGÑ­ß]÷ƒ"”uè­pI’¹DEGK FÈe×q¯e ,cx(€Eà#|ÁøtßætÈ:‰BU‚Sãç™èÇçóï2¼¦Në³î0è8.ô”—I’\9DOPwÈÈ8ƒ\W/ë½UßÛÏA0-õ?Ó,k!™à
+%’WHíšlÄ“GÃ
+£·eТݰ‚%e©Kò=4·+|Æ,˜A&†Q(mïÄœˆË¡™~Šš›=Òm‚UDú¼$\
+bj­oìÝ*
+ËÌf(­ž—¢½þþ‰T¹¢¡Ž$C–‡…²…|À
+ß3Ø4ùêë*¯Ù~ŸäÅï]¸¦J¢¸‚“¡ÓQƺñŽyá¡âÒY&‘×/½97âW•F²3îÄlá¨ÉT2›¾UY BC-X‚÷n+áÏÆëŠc9ª\"|³Z€FÖËg>gs—R
+/:|òYlEè){+PU§ 2ÕVÔ¤¬ïG¾èsËI–U@ðMÉ×ú1K3Hr™Î`¸ö0»fR>Ìz°ÿ9KŠôÉ®uîˆó¨¼`hÌÕv‡((4ÆÁ§#Þb0y6Fg—HY!¬å8¡m &NC¯ŠêðÂããÆmí×rMo.'.cÜQq@
+ãF Ã"á/{Ê9*£Iâši;ÈÆàN"vÝ3<T`Ü°,»„׈`0ï­$ÍxWr" l—`Š!.Ñ4ßJ—¡œXCíEŒðÕk†)ÀÐñ¥A¶ˆ­<.ÁÇKR]ä¦:-¸UMòã:m¼©š³ò´©Ì8ÊÚ5\±,Iwú}%™DXI
+27£0ž\ÀÄÅÉ€çÊ­ éPÂîU¢5!y<&ŠA/˜°Ó-ÁäË›Sø $Ý9ôŒuLºžTýãF)’p l>øxrÂû:<–™zÔ¸8™™j†y–í_€hÚM߶ÒSdÐレBʘX0¬Â,&›ŽÆ:ZäÜìlÀ+À¦@1Š[_ÆŸ€9 o§ê¼_þ
+Ò†Ü!2Ùíó«¿D!€*y„sòí™HTr‘uh<Ú÷zí$‹*œs˜á;½T>¡Æó.;-?ÑHeUS«‚¾ãÓ›²ÊZWœWn¿([À8ßDÀ¢
+H‰Œ—MŽd7„OPw¨ LB¤DRZ·—¾…¯Ê÷ßÎzz t×K =°§*+R?d0"4>ÿ7ª½¼ª—Uõóµ¬"kÔÈe~Az\Ã-ú²ÏX¯¶ú˜±V˜¹]ÝgfÏöùÏ ¯ÖǨ>MßÚ Èá«ÆZ#\댳ÍÈlYg«²ÉgÖGë!H´_|4zÕYÎ.ÙݬÏÏÚ*\ u[}Íx
+ñ½S‚½ ó@œ¿çÍö>leãÜ~¦&$îÁÇiU6:^e>gœ@±º5Îþf¶]î1=W½üÂãw;ÍÉ̱Zôf•Ãà…kˆ!öjToL0>O;¿ú«šÁÙBÐà¯GÐxœä³1!¼¸ÃæÙÖ°Ë$èBqû›ì5ZÙ`ïê#.Úá-Åb&[ççÅlS08s2›ÍÖÈ©eŒE `NƱ×Á@ “”jÐþ²ŽB=@~|üûãåÁ a¤Ç2»î>¼æ»êÙç Ñ„Î Ðy¤ñïàŒ™´Ií[ó?ý¶ÝןœéoŽ>p‚@²fo6â^°dö“m'´çè…ÇžÁìµU*±MA1}¥N唓ZÎ`‚ Ç#hH0Ž¹?l÷õ'gÚG¯$iƤ3ƒq”¢ ꨎþ ¢§œ‚:p¶OAš~^¢NŽk;÷ù‡œ‚Ì>G±¨½¸ žxž8X áÀT-74ÂÅ
+nZØØø}zVaVôwchûµÕ6¦¢ÅísÅà8ŸYh*ÇÈØÔêŒãS¢y¾w<Õ›R¡b¡UÁòÔ¤|3zi±È›E]úÇ•–Ê—¯bEÍcW}ºw_Ê
+ v
+ÈIaÒRÚ5^ûûøƒ<ã@†I· àµÕR¼K>ªyKů3žTpÅrFæô(¤H—dª¾yÌaÙ~M³¶Û™/5Ÿn…è}nŽJÑbWdß;Fb€¢$Ûq³‚S—NÍçÁû±wÊ€w8}›?•â÷eD™(UÐî©RÈŸ<*æÖ
+ýá`bÓ!cê¢6° !ˆîÄE ¨^Š2& ¥™¨§’9Î*ƒG'|„*÷N É­é¼RÔß Ä\rw0tFäbÖø…Ô~.%oCðëºÌ­Ë•ÎðA½9
+£¸c·ˆÎy[Kl¯]±¡QÞÀˆÌ=Rü€õb¦u.O”H‡$Qˆ.ÊÒq43Î"Œ.R‡êu¶w2~h@\ïç8„Ʀ,\G%('÷ È=±Ñ$‡µ¶ yNŒ ð†ÙÈmêÓíhr®š¢Pㇹ£ìŒßÛ2Kü2ø©HqÖá¡]óh¡§ÛÊ0>R\Fñ®€Ï¸!5[:Ö±2†’ò1­u¿ö[ûWS·•Æp8Á¹·a¬ ¡ârÔÞÊñ9Óc›¬ ‚¸ð¼ä©#®­¾ù‚¨8ë"ˆÛ 4,—gŸ­ÆPF%<ZƒpRE‡9sœ~ýöúÑ¥HüK½T?Î[Œs 2ÀxŒ< Q 1 øiS0Ñ•Æ5¼S™'JQÎÚ¬`jð×ÈR¢¡d¡F:¨'Eÿ ±é§õ¼èªù¼Ê7½‚¶ã
+*4€í!ưĶ«°Ž&r}‹Ìcæhnl;[]UüyšüeŠÃ5¾òáVrÁ²zÊ¥ýLúóu~ éÈ÷®è‰):n^Xq« 3è8*“VFÔrJÐ[)œÄ±DÀ¨í–]¢çÈ_4Žÿº¸ÑV" ófxÒKä~Žh‚’ŸCuvz×üL]Áa
+Ÿ$9‰í;=/&™ ÈŠºoõzœ"žVï`ó}Þ(8±T…/y ݨ¹Š¡¢“WæÜã`YDRŠæÝ;[ñNœmb¨
+iWÎ;$JHlÀ[vÛµœÐ22XüÚC+TÅ d¸ rÕ w¼b“ÈÁ2pUëýwD(’ãDâ4N y¯0!zœ’~xIR6i
+O¦ö<̆5+£úyI% zÉì»zr
+EjmV(Î) Mï7s¹í¦‹<9=ÌFIŽB$úâ÷»C¹ê_îïÔÞizÛ}+¢=æÔ­`˜IIZzáG¿ šARŠ Ä8|`-ÇDFU°8L'8ª+ô
+‚ߨì^‰çd>Fª"eçí^/ÃGx(ty9²ñz^r\ÆËÑõ’Ã6‘§äAѦÿg«W»ˆ¨Â¹‚mõÒ÷„•B’žkX'‡Ú0ïS}§ª©Õ@w$àŽmá•qw’Ó/Æ96à GôÁ;QóGÉ™\e|–œÃŽ×y‘§AÒ =hpI`ù„Š–¼WPtq¼nvâƒñ•§8Vö"&¾ˆÄÎi¡Ðò"Ebdb+*´± ŠÀù–>º Ϩã9¨ù;®Á
+Ñ'œX×|‡pÖzËüÅOØD5øfD’Üþ°Ê€œ¶Rˆ+:½Å:53g%©Á¶5] £Ì?ÝgôlØi`£ÁR¾ðl2¿$%óXq ÖXéµ”“·(’mÀVÉ;úy€7ÆM…òQ‚‚³J±œÛ.hàßZ‹4êS ÂEân«K·”N`
+J~`øÓNØ6žhËt~XGœ.Š¦7,É& ¸l³n;ŸEˆsBZ˜çFǼÏ"Ü#é Åhvm+À€H:ééFº@”+ìÐc¶¨™»ç (³¤y§ÞÈÄÅeîGáÑO Æd¢)ËÜX‘GDJØý¦ÌGýS ýë×åßÿùU·f Î$åÁ½¹z¢r
+AK¹çŸ°EØÙ?)Ì©„_ä–É,ÓåsÆUãÊ(aªÀk,rüu–Ò¤ÒøHpVïÑeÿa`—a|01—6ZGw°;J1¼„lÅø1
+KH F´Œ¡Œwù­-ƒ ÌêúâWiÈæŽÿ£lÒyxyãa¨@H-ì¦oÂ…Î 4g¨Iꊽ
+
+W 
+¡ž"Sg§¡¼Ò‰L6o®"Š9IÊ›µNçö’¿h£\VFň:¼áV‰ü ’Ï{®TØNœ„ï9Ž+iÏeĵŒiÎñY°ã\ªBùZ‚ç&ŽÝäyq9­Do3I’úšžõ‚ž_ã FÁ2͸O±sŸ7ty¿7îI©Vć†óa«Ãý]ná78ùlÅHHCðУú*¦#|À€µ³USúÉ ½¸y#´‚,Æ+¨¢jä:Zèº6|̤ϰâ1Qg£wC†gäcéwtE¥‚™˜îÞ‰Œ…Äð`$óØÑÛ@!"!ËOÙ¶z½pÕHÔºöv
+oD,ÌzfÜåÙêÕpïRe™¦­
+wR oºoþÐMÚ`³7™×Üø£[.QãöÙ…Ð<°†xx4CÑšü\™g29Y×y0yý†!fËL/²•ÔAæe¸f Ä¶’;@>Ù)Œ×²ð:<2Ìø4“Ž£¸æw¢')©£ï= ”…jšqÒeô¾ó½û0è³ß?Qðù}.<QJÐÏYø³JIÐÒ4M\à”ù“ EÉÿEø‹=
+jEÔðÎjçeHV„JÀfïL›P£oXñ”ÞîÜpx¢Üž£ˆR(ÉS•Îf0ÒU?U<-(B^9®žbêµtb¢ÍÊ
+*û*0Ô–,Ä>‚†ŠÂÉâU¹ænÈ´d¹ÒT/ E$ÀWn®Ä±'šÇËîß±9‘§( ¼ÍÝb7õ£â8Dä¥á‹² -ÃLɃԥëÏè, oÏ2e¼y:è{ßi+ h.¡yLuô6g=_øÏÜ'š¬í3BDš«¬+4XõžYˆ±‡";kę<Áš5(úåõã¹nøï;0ôN_êÎÖ¡ïï¯(j°3Cû’ÁbQ?‘ì®®ªþó$²¬6§=[_@L!."øƒëü  ¯ÇYºvs¿¥{™]|
+:Ûßé9KA­@<±Å›ýQóö@‹mÛ8îk1¿‚~þNÅÿÔ˜Mÿ`3hZ›•ó¿/ OïV ]¢ŠXjm\¿
+çHáÔ‚ÒU¸ë‚½Ï@ÎLkŒØ.ì,ô¾¹ikÒߥ}Çüüåâû—Øðÿüñ·ÿý±ŠGR±ßNEYú@Wbú„I`ºö¥‘@‰`ÿˆ Aª/Ý•µð²xÓÙ!,’p†vü¼½­Ù8…
+ºŒC—uKDÀãçfÎ&I€2¤’í2 Ñx¹ƒÁ‰aPL»¨Vë8É£èq]üf¿âè»»mB_¯)ψE*ÆQóëß™šr¡c½!r°t,OºÆCH” ½BìIìá8 ©+”þ*FEø(‡”›S")b˜2ʵöï0?&OQseVˆ]q) íHŽ$ åº#éÒ’o­7 ¾†)m]iÏá\¹ £"ÙüIý,HEŠ¨Ï£¶x«¿G—p ˤ.8žÐzƒ„sŒËÌ­?Ž•­—"Ò¢ösa9KœlQñ«#¬XRšŽw´Ò„Ãåɸu"H76¨µ”vï”LÎS“©AÒ'j³—4$ÙÄ×[‡ˆT13qžã¾õrÛ•vaî}Ô™Ha¦–õì÷Ac¯6>"Å’NÌá(t¦[– 9¦‹‰/ýPÁ„ÕµŒ£¾ƒ☦`n!ê·g1Û_x\¹$Iõ‘ZÉiÕâ{âÁÙ—(­Ûwí²ŸtYÌ„e>±tnÁ„ãK¢µôG]-ëÝêZoHzöbÔþ( W‹•=Mƒ˜yÅ<ýé "ýŒþÂq¶sY0¬¥gF2ÜrˆÐ÷ÈSûáîk=2¸“nV$6Þš¸`_[χ~ÛE6d |<ÇQÈÔ(ô‹™…%Rá¢ó(_‹
+[7D}٥嶞]·éè©Á
+£î"þD; ú°Ùü¡‡ô´#y¡FëG¹q¥rv¦Ëu8ŽÃWÞÄ®ò]G™
+"1vÆÚópÍV$z×X¨°·­¿ J„[,3|Ì bL@‚W†ŸLoýeˆí
+ˆqŠE®ë¬z½ÿ ¤ú'çV[»gfÍÚ¦?$¿½@º{’Î3qòŸÌ@_ôÏ?öS×uÂÁXØ©ó[ ÔÇÄd‘MZÉOA‡b\ñÝ–¾O!{rŠm¢$S¾@ìµ¾bQÿ~9Ê‚¢IëÕ¿³óíŒq]Ï17+c ÔÆFˆÁÃ&º¿8ú (ŠÅ:¯2ýN…‰†¿A>Çà̯1øòk žC¾Ä`Ì0î¶VŒY'˜Ÿ/˜_Cðñ)€ÌŸsLXº¤G:§›û¨^b²é€Jg;7Š”ú‘R”«†Õ)D›t(S-´“&˜_û=‡XÉ…œ.o'}’·û(±Â Ó)ý\‡(9[[’¡&øòÅf€ÊÕË£˜¬]s¤xûÉΞÐnÃÐGz÷Èô
+Óº kc’
+}„îkÙ÷×û%Fz˜Q2•¬2br÷?t.cØȆWÁ½}+Þš[CÍfW¤œŠ…x˜¡iÙJõ(L¾ªP”ù %6A:€oQa®r'ô%âP³¢åòv WáéuQßIlÅoè ˜î"bØHöjp¶˜;fÞ¸v¤;Ô®S¾CÁJ)ªÃðÔÇñnìÆfp‰ …êÒEØÚq9D¾„ð¹8ŸÄµ Éíþz 0!〠D‡ù¥?½f¯WÐKö$Écs°kð¾G/ù<“´™ÜøCôZnÖ)²†ø+ã~‹^ÊYœûÏ"È÷è¥Ò@+‚}ÕáNJ|B+UäVâÊLß’c1¼åˆ‚§%™¬#^[ðâqSO®«ÿ¼œê 6ÆŠ·
+ƒ—X
+r¨c&lekúCYI€L£Hµ14 î*É÷a× dù™ƒ Ép•0’ù6°A.Ó´äSv‡øF’ê]© 7‹×A0™'¶’/”E{RÑ"Ç@QN\Ä°²T¦ôá$Õ0/¦âA®ÃÎÅ)'2Ã3OÄ
+óSR’ØÃ4ç—-È"¯Rµ Æ_ÚʽR¾ª@ I>O
+:â×[*YÙñ&¹ú“ÍxL|~‘g= •¦§šb¾YsrVbàò‡[ç"ÓìOŒR¥˜Q/­-l#?sj dïúU<î ‚ ‘匔è•Îµ1#M¶ë@\’¸V9µä]ð ‹[$ê»m8ă4íá %Tù÷ö㱸ŠÝ¿NÃ¥‡<Œr…šP¿"ã\›£v´néë ƒX0#ìœá¡-ˆ·Tß0T yÆà¥ò¡"EŽ»1f@šÂA&3¢Ó+€øVY³±‡&JŽÖ±îX9?íÕœ¹ý™&ÎF— ¼/=¢Ã™'5Õ/;2:Û0ä>ä¶é9 îöZ¯ƒõ ¾u­SY2a˜Iœ«Cp&´Š: ¿ðë-
+fg̺)î…Õ¢iîàRKBÂÔïÐ.gÉh?)V€E8æ«i^®ï6èœ@`Óšü‚’‘ À,ÜØì ¡• JSdT;ö]mÈ,QÙ³L‡Wè qª²´å8Ë°'í0»~)D×Iõ~6W€ðZbö’UÔ§á2%3þ*L²áD“¤0³x¨j{ ™I¢”¾7b žcÙûy9i_3¤Nˆ+9ÞÆZœ£ ‰ÔƒÒ1…ïµÉ@ËHÊh׳
+>Wá•ÖK~¥†9C)Y7ÚÖ.5Oýc-ØBë07²#â“O7 ÆU°R2\‚½°ó“à44—òî­`™Ç ¿ÏÓU\4u«~dpî#n°Óã:¼~"3…õ¡f5¹«SŒQGwŽ$SægQÓÑ®ôHÝ9ž†Ëæ’¬^
+ŽÜΈP0}ØW57
+ÂGø™‰AšÁ4ݾÓm&ƒU(:bJRæ¹}ÊÛ¢”ÔÄô ²EÏ­´skµ uæòs3A’„ð¸Ã¹O<|!»ú:™oYï9<ÜèyÑT–ÎNE°dÃçJÙ¯Óà™m÷§å°k#à2æñ•K·(²<x,svåÙyít·Ðq£kPÓe5$rÚstyJ\p­{«A ÚBP\`ú #UAç`Ž…Ò-œM¹©Ó/4-IÈ ú„ ø6²
+0Rˆ)Ga–i0ŽÂ`‚§Ÿ ™–C¾¡Æç­ÄtˆÊ0kgÌ´ƒyÝâ¢:ec“HQD7A0¢ñcÄ ²Õ*îˆV<[ \Æ_ºû=€¸Íð…®f1BÄ€eI§§7]¶µ
+=)õÈGð fɤnõê@Ø‹3NþÓ:£¨ÄðTïA³ËZH X‡µ®y@:¹7ÒßÛÞŠú*C¤Ì¼PFh´=çÞQDÊ' ]êâÙi®Ù¥;ÄÙÍu½,ójÝ¿+’êÕöNw+©JqÁÚ‰°ù:wCú20w[«®aëÆ(â׎¾›cu¨q!.°äª"‹{‡«1¶®ÌЪOJiªÒ´U`ù'4ud¶²þ§ ‘A´LÆíò’Uªa/I~œq ó«ÿ_“<”ºJ
+Åau%g8œLF{&ö8öo±]#¤ Ì¸ü°?X²;åz/≹4&ÅÔB~N*¸
+¡>Pê7%˜œ¯¬DŸWy ß`„ÛzÏÐ"_…lú8ç†/¿ê1Q¨û…]I]íàj®-›>?;Äíè8‰ç&úFðc›¨Ä,Š>…]÷2Ž±õ%./ÁcÎ2Žb6|Óm؃³ï¾x´²tãÌ0çM÷¦ÎS˜„9Jdó}|'…)ᯖ?NŸøt,hMô]
+.ìjéo<³æ™È†¯ÈF% K Ñþ,êU±%õ¹Æ«Œß …)æ\Ĥ%gÄ”9”ñ=¨É™¬MH‰ÅôPí:Îw ¿}\%<î#«î¯k§$Ùb/á©B^Ö7E½“Òþ×Pz±]>ëoT¢ƒCû¿ÏŒ”"‚ÑF<èßàåŸqÑ,N;ßøQÉN€9êg! à.Å“¯Ñü@#{8Ρä6¦Å°/iàð€€öC)‘.¬ 蓆õøk<W3Ðèä(+|Ò¡sÌ*ÊþOšùPôów¬âßå¡÷•Q$óÍV«:ÙYè`(_k> ]%w îEíC*g’â“(áÑã[¾‚ð?¹‰ÍÙPb8y­„ q±¦ ¨Jà1I®êv™W‰!W4^*þ°Tlø”\6ˆÏáVú\…IgMÚ]ÔÎìçrÄë
+\LSAOó5°m€1å$ã`¢ú® ÄÛ²­.ïÇpXïÎUÌðröºö©F^‹AJŒús0ƒþíGÂÜ\.F•MmK‰ÎTã;cìêKɸ
+ÔÉLüo¿Ž÷s’ŒÜâ¾ãXWEüÍÝúpYIæ !ú¦_ ‚¹£tÛµ#©K
+TÛj_œ©•µê¼õq£qîÀrÎs
+ÏBxÀåä„;ð õ—²˜ô?Nÿ°èùnd@ïïa9' ê…&{áÍK‘Ö@ ,ŸËm‹
+8Ì;;~H‹Eï1Îum6²»ÃF‰ý…ênÞemÞœÝÁÛ5§i{aIúXÛ©½ð´óþ
+ê–Ï‘sû=!aÎ×6Ôݦ¾É ^­SC¢~«ÃZ{îq Oà#óeÁë
+C?&_±®
+›Êâr™.“0½dÚj,õ*²²9uŽ¯ìIRÑ“:L¢ ëŽISvœÓç!Ì-ŒUî÷sÓgS„¹v=ž«tÑòUúØÖclD£@ø¦äCn{Ôòs‘®ÇÊfmÏ©ºÂƒègIÏ>­*žn±kýœýûè
+…Ç4¼X(FÆ“GoТñ’ŸëI‡*ü…ÕÏp_™üsÉÃä-' íïç|¢éTìjNW§¢u“§Û–góç¿ÒÚè9}8Ç9õ251á~ü'\nñszö”H¦wÅìo´§yî>©ÊЙÇéʱØÇž×µ:œy]wžDñŠCEèó.ÛÏXT¿†ë¾Séø|ž‘ï£HXxyÜ{4îöÏ“8ÔìõVÍ1^) ­Í~LÄ´èã!*èBOÊPÓ‰_ÿ™dág¯˜§þW‰ω΢O69lÚcž¢=90S¢Ä\ݤ[>οD›k!4Ç€ÂFIiãF±«7Z€$b-fƒ¿p¹Ä
+5pèàÆ"Á¿·muµÆx¡ zØ>jìy¢êzKRžv‡ 'Ûã2„å–_é7ÜlûÖ‡MƒÎFµÑoZ(§;\pI>ã6°ä^?¶¶éó,-ý ó¨ðº×ÀÇ{©÷sâÔZœ½-púÖÞ#÷ë5±|.y !'M¦=¿µþvN}ä ¶ÕòÙ¾ñŒ¡~+ˆn爥“E¾Ér8A¶Ž8ò™hTøÆJé× r£ÿ¶®Mxæý¼õv/›@[bÊœ:ïáñì‚“¶Ç¶3²Ñ°Ÿ+מTÔÛ1x1öÝ_ã¾Eä#:Å•ÏU‘_Ý*q’u]ñ±åWl;õª‘‰²Ï
+`rðoü Né2=@¸Õw]i a;ŒÎßñ²[X® 7}Fèíu’Ð*i[%W˜=hƒFø½SãJνB õ¹¢a–R°ù`|‘ð&Ú¸)ùô
+oO LI§8­î5¾IÂ+ [ú¼jä+Ï3Í}ù4áÐ4ù.KºƒÖ´Ãg¾ì0ØD/T¾†øB¯ñôð>Ózš¶áD)ËŒ
+ÐÆEFfÑç9Á^r:dÄê…9{Œæ‹ƒ}­¨Gƒñøš
+j5àÿ …Ö°v!häì¡÷¯sIfý‰z2lµ»nñ‘ñ¹ž“þHôøRýæ×þû‘zk¡‹Œ†|ÜàZXL$©GÉã' úPPÁ•!,µ9 /„Ÿx¨¡ÄZìZ_ ëçÐóÎôÒðùç?ü¯ÿð˜*첶RVýâ("%'»Ëc*H.@ØèÄ=kÁü-å‡qi[”¸*ì*:û僼“Òc.æ Ç÷îsˆ
+¹|’?¿¹Ò‰9ßw l=EiÙ9•¼`žwª­6ÅÏ¿>RÊ
+ )iv£TunÄüMUcÐLz¦8«U‚…CoGWØ¢+&i¿Y0”ÏŠÜòm,,æ¤,HäÞÔW¦]Ò$P×xJx¨
+ÔøéÀTl† puuË‚(ë@#Ú÷D¾¨ãEO¶ì@ô)rt„÷7ç`ÉK‚8L–lߦȼô¹
+IƒÚ®ÿW\Ž‘Xç9¥€PW‰áå6®Ö É#‰2°B©-U ê";$×!nÞtÉ_Ô|8 4Š«@ÛhjócUÝÓ3¬ÎHfbTùoÁa9ORäD½¹Õ]åK ©Û4±ƒA# bþC–1yð zAßsŒ«ŸpÎIbŸNÄšœljáøúða´ðíÀÞµ×Mðù$0E£5¢Ø/„ܪ…¼_„©“P׋$A0;eÀûîs0¸Jo dhsè<NW&¬¥]ßÞqÎLPÞˆß7Jm‚BdÑãŒ"7Vs‘-[\á’ªA@QÆâ»K׺ ˆ“UÍ”+-­á!W-s ÃÇ]#ÄŸK »‚èV«ÐCؽÀ®ѯv_½7 j;l,JÚ{zĈ•Uë,;N.¥/ª†2æI*gÛ/µ[¸ ="•{sÏiL‰%)#Æ}›
+ç"£TÖGaкú¼^%«€™cVç ¢ ÊÀ–ì71¯~—
+|
+RÕe1O›æILrÐ`ïB¸Á*h"»W¹ë0@Ìs‹ŒZ-Ñ%F:•¹Å'ˆÈhYmìËüT$ÌÈx$7uÈ&3™c>œ.tYœ-¤@©ÔöÕM,)F1ˆ£n}ËTšCöiqC
+q³
+hÄ„bSÿ7ó ëÌ®u(¸;ÅÿZÅ‚Ê«Ô•=ô1™aا¿ë˜+6y*¦Ë=ïTéÿ­
+[À¢xÙ¶ØBJ(]Xª"Œ ½Õ æê€ÔÄ„çìŠcÆ’w’ Ê\ïqA2«ÿñM '–” §Mfƒ)@!©€P7”#ßÿœØ³@‘m}‰C˜á½½lˆœ/*$ïßß@;Æm2¾¸ìO]AXk" Um8Î4Ï©rœð=7òÖJõãÅ45þª:^#.˜çfýÚ>I Êá¡j\& à%‚ÍtÑg_¯Ç]1_æœÉHùS€›i¢ß BQ{¬Æ®ø4F½»áåñ!=眔²r$vÈwÇSR k2;^!$’7…åµ€`j¸3k“¦<ƒ¡± gjÙ^É4"¦FtƒGŸnF¶z‡~¡ÉºàÍß@•.|h ûSWÐ —V ®µž²Ís²ì"ίmÏf³TcÇz7Ã2Æíª ‚aM¥sÌ(Äš²3ÝÒ+ ÇRNœø¦½tÐá†GÂ4#¿a¢ïçp*xT`m5FÈ¡Ç|6õ§‡á¨ÚGÅØpy,ôsJ…’‡’\q˜g$å$1 eùìÄÚ#àÙ&„1QµWÀ0õ†)2ÄKM‹U~³Ëz`qw%É,Eª•¡ ©ÚŒˆ…áå‚È ¶<ò]´ÈÏ1/P…+ƒùç¤G&EÁÐe`’½ËˆÄÕ‹Ž;®ož4íf§kÕ³ª4ØSD¦1t ÊlXaŠÎ1¯‹³EêV}Êܾe¢9<A'ð(“ŽQg71×=]Pz„NZSz(L¸ Zk¤! âû]ì:£DæÁ¨ :ÑA£îC0¹‘þóÚw«2DLPa(—a„ Ô‚„kZS ƒ¢§±Ø’þF2_Ãé»Cñ;Bb¢f¼iS£Š!¢ì.,g÷*›QÅ(ŒHožT¡"Ò$
+8•©ŒÍhÄ%\Uص DÎ.Â…6¤Ža¨¯µE—åýñá€Núÿ–)&Ÿt‘ÁÊ3Zí9.¸A¤EÔ;ý+(Æf Jio7
+D4k¬tø` XíÍØFÁž`,Å% äYå³`m"Ó2¸pbn*`Àñêº| 2}å~<–Úÿë•6Ö·VoÃC{À´(Q†Ï_"{eŠ€ÐåX`Ö‚Ìî9óÛè:öRÞW–%g’B¥Áüè!þÌ\†×ÙªLÈŠ$!”ÉA¤i°$³#%ã•Œ%ÂœWà/¨Ñ^ìÞ&*@ÆåŽY.LÔe›µØÁÔd“‰ –4'§¦'¨ºÏ¹p@”]%6¼9²9Ÿ• Ob(òt¤¶Hcö›w‹’•G-
+Zaü3»É€°P8¾âᲇMnQ†+ºçàYYè óÛâ¦H<R(rœ Ñ]“núŽ= <M±>=µ–!H©]_O׆S<Y-œŒv*ˆIZ–_x™é5Òúç¹vWKýcm¢ÄÀ }8 çQNâÚPÑú–~ØeÛ0+seJç ¦°É‚ë°ád[íøÚ*„‰ Nìç°õ(cÌy&²²‹Ì×> !Ì/sÎ冷†Õ,T¼á;º->y"">R· á²Ø.¶<±–SžÆÆÞš¹ÇTÅôaµ±}N×å?i«F+×"¤Ðu¿Z.6uÝ7íIÄŠ
+/îÔBs¹~³ÅÉh: #”öu]hlö`NÒ„ðG„³–åﳺȃ㠳›Hž³KT`+…¼§ Š¢õhT+(°W–„(ObÚ"¸õt&Gš¶n*O¶Y Éšëé&·ôÒ_ÔŽ¿"€…‘æ9 1ö›R”Ü夙H8|Éöáh«>Ä$YEMØÅ;¥BabS*ÝIn¨¸4t}Aà ®…LŽuÒ Í‡ŽøAˆ{a&×d-HkŽH¹ _©òÈéµYAj£<kwAd¥ˆ.Û0Rœ cÑ/˜ç ^JÍ$$9[ì˜vM??(2“*S* €úò@§[<¿v:Œïo¤‹#æØgŠ'Ñdƒ·rIj‹6Ì‹3ù]»°99 /ä¼Nú{¨ë¤”» £L胅Ƀ¨ºÆÛÃÀ‰³+ÛŠbú×¾ð ž *@!Ë¥¼‚žwê½ÚB„V¼7óÄñÐ'¡ $*¿˜"gÞ_NÓ*R–9R˜uAÞIY±‰)É#ß}q®tbη)ÕñÓ,_Ö²r†à¨ä±+7ª=›òùŸþe¼Lrãº0|ÝAë
+š\!<²€NÒ¼Å1(©‚÷GD)“ì)¬ éÊÂzßö9Åh ‡"Tæ®0jip:ã
+´JÉÊ~:œ%Ñ4DAü
+ƒÕ†Ð¦½ž‹0( ' (£*C'¶0Ž l‡,äæ6\‚¯ÈÖliCiPB’ý¼B4úÐ4” †®„×ånã¡V:µ9l”ú$GÙAIó«~¹›ÎÅ£=²{’VêOL®rBÀ&?œ‡ "g› Qíù‚\æ/z€e¶‡D( n·XOŠ‰—ð18¢îã.*?Ãh 蔵6eàM¯ %IVU»ô½4UøÊ)ôZM/òª(Ȧý;ígY!K»6J:-¹®êfÍ2Å_ãxN†²D‰.®ëªÏxÒ±5t’‡’ܵÁO°Ô!£Á½çvQÀ'x#¤-C㶠¼¡M&‰š0ý§˜¥7cL`G$â··C¸ZCËØ-Wi‡ ñ@³%˜Qºûe@œ®°DV+Lâ~vg%¨ Ã…àR†…þ |ØÀ5)F·ðÀ/ft–Ï Mè¬ׂDí¸Á‚2&‹-•¹/03Áî"cÈ8í›nÇTc¯öpB²ôUŒêJ‡æ²Ý¨nï@¦Z^ÝÄ 
+[Û}´x¸|, ªqÔ1l òdGÇ8S_TB¦jôrtÉu1cªØj!lB&ÂØìpÌIã î)k=}ì ŽFòÂ1ÛæÒL€7®I¸’åÑKA”·K
+NÊAõó=EÎ ¼
+æk—`’ojU3ªÙR«—‰eê~7îþ­ðÅ*1£½ð†
+Ä„Ù@j©%ïåç€$‚7®ßŒ7™uÒ)èqõA! Ìj1B#+]Ê ,€vßÞAÚà±
+ú†Zm!$˜ûél"5f;¯i#ãžÚÚ¢Èà·ÜA—¸P ” Ç«^dz€Î·XΛB¾íM"3U®¥ ÇKn§qôÔ¬Áb!ÿÕçI­Øš„aI- _€|“5&à"TC®tѧ4)×V|H$ë ú¡4¥~+ï-™I²÷~ Ä¿_aM'×Xà(ÁEÐö2„@t+œŠ\»´~å_†;­‡˜ï‡x½’Yzæ‹Ž+†±`$´ŒyoÖKA‡Û0ƒÁ¡2‡öz¸·¤KålwÚ÷÷Žùx¥F^ÊdÑ!Fœm¯ãð:JÙ@tÌÖ‚nç܃î‰ßo»'þëŒvâðË\}ÑÇÚã/Â
+V`0óä2è{ƒõ!VDþ8MȦkp[¦ÚÔšÍàÿ8F€oV‰Ãw… h»1+èû~ÒE)’%à!×Y_aH°ÁmØéC¿K%¸ëçU )RaÝ‹‡ Qi&\
+Õˆ;I”–ÌAÜ€l)q¤¸ýX$'™cØêGˆƒ(ÿ!PC`É:˜Iµ±CŠä@Öl>Ãp4]`Ýcëô,°”1ÔG1ë]`°ºFÇ œÅax'ʼÎzXt¡J«H×ðùIÑM—H’&|¡°˜
+^ç§(¿Ó1Ì_IYÈŽœZ!°øÈ$N¦í•Nr‘u9:YVH›­ÚvW«€³d ±ß-@¦r88iåVÃ*ü¡9 ^'CÍ8õñ~X:Q6š”¢1õR»°(/ÎRŸ‚>vÉÓ$l 1§_B’ð ģ߰O][¿Óa½E2,ø^)CK_xGèVùÀ.0QabXnÈ}ï‹€Pß*_ÚBdRïZüƒƒ.R3i"Uæ³¾b(Cƒ¥Ô<D˜BÁèi^°J(B¼
+ëÊŒ=X”¯3÷ll'EÎL —¸ˆwYb.€©h•ñëAú^O…°þªºL]l2•¨ož;„;
+ÏYÎÁ‘ÜÀ$:Ã:GJÒZ<aÊŸB-—¼¢w]ÐÀx¯¤¿³‚\·ƒ2"ìDd dÖ6}7}ÅÜ$vˆÐ`Š¨µ. çl
+ú7¶¾ØÁäÄ0¬‘­2gÙ”¯…‘Í‘qìéaˆ-Tº­U§Î{SË-M£b³{Pò
+2Å ë¾î• ¹˜RŠ‰°…B²Ý7ý)èãvª¶„!d/"2×Pª
+M5a`VŠ–&a@J—öö$ —öÍ ±«ÜÔBFfŽcè½”“ £ZÓt9^zÌ‚h¡å¢›„ç|´êç€ëÒòõ˜M‘½’{@=|õ&X±H¢¨cmd TÚY–c…O!Ÿ:µ¯ºá¢JÉòI8¹S6¨ª %#‰¬ÄUO’Dah’}Eùžkƒª¼Šðe4N6Ïpª’ÇN=…ì«’– õceajš{Sæ>Ï+!Ê!÷óôñ¨Öaì|ë1}ÏSLmÐ(ð9À›ö ßwA‡sB›ÚŸõM›WÇ£(]
+-grV÷mC_ʘÖÑ‹gu‚qªÐ|e˜my p‚©S¥VwŒD\MtýõEP‡º&
+äÇcz”W¤:D Þ2ù„)cȬ²ôô¸ç W* ˆúí¯·ôà#š ''’êõ×%7Â_ßÿ}+²PÌ":ÅÍæý^ÒbÔjŽÂC
+
+y ̿a³Ü Þ‚¾Ÿ‚Jy`1è0ŸÀ)t»î9èã•œôÄôþÇ?o¿ýÇ;þ2oۥȮEúÉK6›b21dÉgVxÌ„C“³–>‚½é[Yíô݃€
+ø€dD Xz€Db7Ý¡&2¥yúx!%½“‰dOq:’T]ÈrÈ\Adm á½Ûñ,Ý·¤"Y9 ¡|‘95‡Ðµ[Ú™ÿ2''Ê÷?)íœì‡Zšw AÓ ¬g×wÙ»üÞ\¸ÚŠ%=yH’µk²oQ+À/aÓ܉Eàv€!k›»CAŒh—r¯½]냠pû¢bt­ùŸñrKÒãÖað
+¼‡YAJ÷Ës²–óäìÿõ| ©‰Ý¿:•TR1R‹1ÞÒ,òÉ‹Rð$Ro°„¢ó]T?¥sºÉ¶Ê¬¶"Ô+°RµnÇ$XÔ•·öùÞGÖ@øo‡$âk•Pרý%>/ea¿©Cò¦ƒ6ãsdò*4K‚ÄDqÛŒn!,ø*ÏìM7‰v²h®fKížVcýžTòúùbs뼩˾A{±ÊRøx¹~†Õ ¹dcFút› Ÿ=e+öné5|¯Kµ‰ŽOZǽXévÍÔE,néL£ W®Q3)ù WF‰Ù¸hnf\ÅÀtÒ
+ÏXâ³ÔtùÐØ«&¿‡ð8„ÿÃ÷«ëêa Ä4¶ì‘ÔÌ™U*®""–“¯,ñ=¤å£ÉRª1oVä2ìì#ƒ ’5-Uw9nW9ü±«n vÑÓ>9UEd¦„½&¤€o…ÄhŠ·*['·~ä„ç’}[»Îx-Bñ(t/1{’Њç÷q¶)R ë˜d«’¨G1ˆD 9 Ì*Lš|ÑÊqLÅ·….±765&Õ½ì¾bH»•¸ÒrF䶪+)l¤0ä±B×
+ f»-1|º|ˆÓüéÄÔò3¯»ùí2-VÖ©€yœÄwÏ!ÑÂcþâ7Ñ·ì¥_Ïû©´­…b•{Lºƒc† œ¸ ÜŽGÑmÔ‚dæÐ.F†Í‰ÛêI4 gâ‹¢¥£Õïè[”˜ŸN=5-ÙŒF‘⮣)Õbk ;‚]µ úK2ùš‡L.ÆÞC(Q,Øe¯d&ºMŠ=˜(lH º92¥¢ëqݧ.ɈT§{OŠfÇÐÛ—Y^vø 2ñ‡¸ž_ jýfä©×2Ó»‚Q&Ñ1Ë÷Ò7&
+ª‰5n‘Ô
+÷N&‚2ë9ÌnJ>è,¹×spû¼Qüë‰/¦6è/:Z|¨¬~L·<]Ž’žSÑÔ:ÈîCëN‰¡\ #ІHB[¯õ1š
+Õ/]«
+€«<”Aa’<pZPÎMb ¾€¤k)ŸKòDÑvÿrHR–Ÿ-”T5›¶»Ì ó\R‘>AáTbHÌK%€ÚsþÏ &{…¢…röϯ’u6†MºA“šÐ*…ø7È“ƒ71|@uÕ¼œ£KYÿÊ„>± p'Á\Aä
+„Z3ìÇÔj2ÉLœÅ ™¥ñy‹ªÏì’óX â¦OæQš+¿ƒ(W9„E˜bá`X»rl9Ä€p ‚ëîù
+©‡Rû“`dÕvПeçøòˆ ãgvÏèQoû úH&×"“Z¹S û†¿½^0žÿ¨º>‡…gÄ×T  Ý_Ebk~á „cÄAXðiu58ª°§Øùk{x™dg?<¯‚J#“ó15‘¿ÃU|÷á(1c+ýv›ÞJÈ
+?X\<ÚÊ”bqk4¹X›øiˆêIXë9¬å zðؽåé¼dÿßüõ×"ÈòÞ^j¯+Å¥ÞÒ° âëouNƒäFE©e«æ¶uËëV¦©c\0BÈÎê@z’ÇAˆ!KL«aQeBøÉÎ`_Ú… «Um0—BWH3{h<Cú9ý¦$>e­?gF¹YDªI¤! (B˜59×QŠX¡þkÒX&"Óý±B}0Ìή1¹]ç
+H‰Œ—MŽ¹„OÐwè LA$¥u¿¥o1À¬Ú÷ß¾/$f ¦+ 0¼±Ë‘¢D2‚A³ùùW«þˆµ¦­Ù£ ÿ¬s>F‹Åc¬¶ÑÜbš·±!V-Ê*u–ÞÒÌz+µØçß‚x-ÑjŒVK=ç€âÖÌÃö)¾ª·¾Æš5RmxíQê:w +sõéÄÉS¬3}8fÍP³zôY­Îš a1jÌÁOkŸ3}ŽémÖù¦îkÊe¬Ä¬ðQº-ã‘BZ±9ÃÖÈP«ù,3V«Õ¨z_Üe8yÜçpê´Ö­Ï’ç+eñ
+'(³3²+êZ*ó åÊß\5Ý’“äp;jÆÃ
+PqZ~Qþ~1§Ð1T„OcŸ3gW{wn´0‹
+/ꨥ¿ôý¨êhêDkǤ™)ñ8WæfÜšFË.«ö­¥ñÝÌ(%l; 4ƒ«8yW­MX©"A†Q®Úæ)Ęk™ºñ@œàµÏÁËë)§Û ƒ?~ Ö©'Ü Õój‹™P ï=z ~/°§½º(k<Û…vSú)§/2Ó
+ 6gBÆ€$¡
+® 5I;|„¸žWîôÅàg(pćD–Ñø™v:©ÃÒíŽÐÐÍ/ky•~v$«~~½¡(wƒSeQôEïAý@¯êPæû4KI&§ôûÑ\RÀ?!þ¼’~ôÙùè¨%å`äªr8F³Ç¥–è6Áþ ' ·RB?©Qö&i6B¤r)÷¼Ì„bª.ñý@ôy¡cmTÏHá3HŸC¬<â‹ÙÌ}o%b–ÆmÚ ÞØVç©9kèWúÑ*
+“§@yž@òš_¡Í›D‡ÚÔè%‹ßÎÌB褤9S¬AëÁ«3÷‚NçÈ…¸½
+žhµ¯ŠbòU†¢’ݦ<=Ï1c T4Ÿ¢®0
+"ÎA½öý©&ò8:³NÔ=J<ˆ ¿Â´m Ǿ$PL¤‘¹á?§\Ü<³‰î¨}#5ù(¨ÒÔ5#™fñ¢œ3{‹²0cyê'Ã4ye¨»(.HgúYšÎ%‡ü?ˆ ý6"ÿ%øמüì‰þ=$.}™NHSöæ£4ÊÛ UìtÜS¢ Õórïƒ^ÎY(3Û
+ƒ3½ÉÜ×
+«!õÌ ¥ëò>H6„z3cax½Î1íê.)Ôÿ_øÕn'R•B®ûóQ/Ç°5(¸i{žu‰Ìtð Áv¬½²¬kmøýú¸ÉYOD¸úö
+Æ£òÇäµuU›y¼¯º©zA0ëlÔ0_ŽÄQ²D» rÐU>0ŸNñC(]MûÝ)î" ;ÉíŠÎ5„óÚ =òBÃÅÈZVíHíº '4d
+¢×«žè
+ X”+”vï4\r|±ÒG\iôk©èÞVðÓÆÚß8ñ«ë’løÑë/{œ
+CmŽV
+RÑàvQæ? ´»Hµ(¢bd³»v0ΆµÇËÃÊèâ‘‚³œºa€èïã¤XÄp L!âåòǘ£³‡úò ÕÓ Zs9î8Lr@1Í®.Æ£r¨/Óêtç/o²Ì8ãVDú«_Å‚AKc‰›tN?¶î©¶ƒÄ¦l¿óž ¬LXbw}×7¯¦«!IÆ­ãmXzœÓh¿ƒ|}üC,ŒÓªK;’ö‘‹¿M.'Â<û ¨?°)ÑЬñ|µ&ß+Ë6Ÿ––ÅFì«ê¥‚Š¹–Q*rëžû#te™¶¹Þì7U— –éSæý)»÷XN‚yu€.L{$q<ãÀJæf\‹ 4¤–·­x”†¶Ô–Æâ'L;+ï„ágP /`ýŠ„ÿAÜäkš
+‰¦zÛvg¡x”´ÐĹÏÊ[áõèýRß@°.U}=…<£¢Änž 0þSx– òHL¼d®½SŒUÂúÅ;±Ô
+ÂÔ>Õ³€b¥¥…ˆR¾Tm]\!pêþ
+º-샨;-úÇ Íñý'
+öKBl=° Ù,²£)
+”±EÙro×VY‡Œå»j/£ý>Á׸ŠáÏ-×Iã^s´Ÿ
+‘v÷ëöW׈Ôú{‡˜CdžJÇõ4ÁµsícضxÚ¶[—²‹2³Ù,‘$A*þ¼0
+ÂH¡0FÇ`@¿ÂØÇ È†ìsPb#¢ÛñhöÍtŠY4ï!jW:¤ªEœЫUƒÀ~Éøƒ~Œ‚ï[2=Ù+ÖÆ°;i³ × à/8Ü´ÉÆ še¹ós
+Ôæÿ/“äºnŠ® {ð
+T$Ávœ ³ O•ýOs.ª¬ÿùÊ®$eGÂ#H4·‘lÌb¸ëV©}Ú©©öœ)%\Îä!CÎÂÓ 7Ôs&çÚ#R©[&<?
+a˜»ÖHfM!š\,‡å³Y¸SöÖvQ!X;ƒ ³j03¦ÆN*Ƙe0Î9 tAd>âʪ×+r]äDþ7Hz¸JÎÿ¦C#†€`ˆ¥“1U{,šŠÎ…¨`sÍøäÍœSÝbÍÀÊ“
+#qjÍÎG€Ð¤¢Ö"„Í2™íäÕ”^ë%P ™ÎLfšzº)2–¯á´|)ÎA·OHV:B$2&¢KÁ*~“ùÌèûh”©w6î©ä>+Z÷HJÁ¥\Ù¶,
+
+’7ó»´ gJ€’
+€
+Mv×Ù"É^‡Dé.`ù¾ð3Äb—OU˜¸r_Õy;Ç1¬ ÔÇÃmಥ‰¢©jZ#$ xU®Å)
+^C¾÷áòÖÏ÷ Q·œÀ
+¥qP&p7©Åe'»@ï¸ütáÎÓ‘˜äçkìsÐ5KFs¤G›ÐSÛfü„£Ñ!r,5–†Xê°­®\¢ë fc±òéú2¾º’3!L5‹Gõ×áØ¥nÓÔ¹u{ j¯b¿|«kü {F*,
++üQû>á&É ê{ ©3ÁÑËà!è@EšÑÖ%D©ÆÌtÛªÙ®çŒÍo ËUlÄ9¨)œ`'›¦ô+½•¹+Âì´T‘ï±ðT =‘Mñ(†
+™ „u›_fâí´z˜¸£Ñ¾ã“ÆLãz`î¸9ÏÔ%1YWÔQÜÈånÌ$ à“$EOæÿàœæœïLúA!¼cƒéù¡~,'ÛÁ€9" ³ìÞù1¯N§2s%@›Ã®Hñî.ˆÃLÐ#Žž¶á·˜fÔ¶ãyù6~•iCåÚ·â­ÝÔ;TÞ‚ø â_Qð½ÙôŠhŠÃÝ2.MâÃC`8ÓÚÔÊz€;F¼"mm` Ò¨6ËéÇJüzB®eîs¸à`6øëÑ+Ô^<etvR¶À£å Iz"£½µ²Öãˆ|ð_…tûHêGJ¢fƒÖa]~¯•Œ^°5ôÅè'©ÇRc)íô+n02Ùd!É$ñä\N£$†ÙnZå²|ïšGK¬ª‰Ó®ç€XÐL\ãz¾¡ , új<=Jâýl˜Ê2®µQ=-‚²k%3ë–(˧>H6ñ4îÝÖÞobâÊm]gF{“m¿iõaöø
+[:œÁp]gXà€^_A<×M¸…¼aÿ-È$gÁ²R6Lê6…´YlKŒ°‚rQžKâJ¯bdlRtYUžF9—ÜA¤B­ hK
+îì܆B—áà/
+²d¦º:ŸéíS}¥ÑSAd¶£$¬­9›S¾„øò6‘G!úJõzô%—‡y¸Íú`@PþxxÔb(eåë×Ú
+€Ò…(ÌK r -ŠˆrW>k#3œGÎt RºCÒ$¡1A¦
+Jº–<#âv@R9p?íÜ Ì©Ø‰UìQXŨP§ö&CK*mHïÜÜŽÉkššOC+„¿uAx=Øõm™<UÍ!_N?Ń“`¾Êy#U:Z âK‚"•lT<ê=„EjS€.õ’ #Äíª]‚>‚2üÛ`ä¦VÂ"‘‹§Œc]ùž³Àê°(t;%Qñª$qºß]d«jE×A>qÊÿŒ—I’¹DOÀ;ð4ÌúµÔ9´jÝ«ç/v~¤usE«ò1ø@DbŸ ~ ”£^²›y#‹@ ñ†CÒà Æh¶¥
+pPT\Õè/@Tgœ©h51ê‹)mvý®L¿kÑpÒÅL¸Ú± Bbâ’2Õ½€€ÇÖƒZqîÌš"ÑÁ°˜d¥ù£ZÖ
+VÌ–pÞÈ;ŸC×ÃÐgÙî&·“‡AïXPd/\öFFðF8äav –ó.'ä\;V—>¯lÇЄNÉ.Š8ÔFÇ6^§`ÄG†}Ò£pëSÆ—ûk«*Ryh[q‰çÐ?*jǨ2Œ¥=Õwý€@óžò äiÖ¯ BR›ÐŽ<Ÿ3ä¡àÚ1ì'>•)†T¶¿©Éa!^¥ÆòñZ´ªÙÄMÌ?¢[ØÆtH°'/Ä,Îù gÖ³Œ€X°]Š Ýß-R‡=(ÃaI&ŒcU.šàW©8ß:r‰%N;Ëœ¶s?†®¥‚sä3öâ̪HDE·ácÁ19‰g…›7.¤ºKŒŸLkSû(@ä÷ãs1¡.CÐB Ýzrxºlm-N«}»»uq3^tyÑ—sX9à$¯([UÅ©9£`öãµðë'ƒÐmvYÉ&ÇU»*?ðì]ÔŽŠQZ^ŒL&–æÇQbxhŠã Ób#ï× §cØ!%NXrñvU¥Áü‚‹úG¯<Y¡<öV’ÌÓÕê؉žüªŽ `C’ÜXȃ|vV¾­%®BA¤ÚÔ¯äu…˜b¥jǨo:›?‹I7F† *oL\Î.¢Èõ/ X”§&:¶Ìñ¡Ÿì„0Ö¼€þ|ñÁ°ÒH-¯:<~A³”¯+Õú°« ŒcÖš:ê•`°}éL²ø†4Ûº)ü„’w94'lȃ1‚{ƒj¡.Y“¡Ü6üc$VJÞ7!C˪;;£1å QIâM Ä œÙ€`¤s¼xÓLL)V›¶ºéšÔ»)âÆT
+º‰Ñ·sÈ
+ˆ7¡‘ÃÂJªføzâߤþb $ÖæøzyE™‹Ê­ãeÃÙëâž@³ke¼PÔ†å5“›ØS¼1âIÌÀK§ î…Ø&)\?gtȘC0¶©^Yà!B>ÅTõ'ÚЮ
+¦žsÜÚÕKý­'“}C
+O›Z¾g0x 'W D¹e9AJ“ÇC®ç5¡í[ƒè×}Ï•a„Èžäš}ÜÿoéT
+Mò‘# (ÁRsÛIWì
+û¡ÊÝLcña8‰ÕÞçå4båú™uŒ9ß"O_Ã{$®‰s.F‡_?¾–¿›è@ùÜT˜kî#D6ås;}kÌ“Ÿ“¹“R@•Å!XK>Ò™67™2(I "¾½€Ëùoe¨žjÊ×­ j¢"&”,Æ6Úß@¼JꉟÝ^¡oHÃ줌ÈO9¯;ä9ƒ7V|0é°7Â|‡Ñ
+›§öcúfñÕ…sÛLÕø'92[•Í]óÿ=ÄMß †…ÒÍ•ßÎa“ª4bÎ"˜‰ðÁ@Kén¹– èÏtGÌö¬Ÿ/Y%\
+¯Ïj‰ÌHÜôÍÅ9^Ƥ®Îâœ9ÞZ_‚ß©î7¤Á}°(–­ç˜'è1Åþ¸éïרÿçGþù/ ¬ÿ /h,³<ñü…QY æÏÿªz "5p¥3µ‚ôˆºØ•¹”¦èÕ®± C!²-ÅÑy 0ù’ ·lF@3(s“¢Qà+ááe宺Åî0xó\… `æØ’éW5 j"#ŸÌE ㌜´bv_÷µH§«Ó{ Ý:Pi,ÞB|ßÆ99œ–:²S L0f@¶&é“ÉsHêtB›ÔL&Æ/h2i«0ý窌]÷×5Äï„°òùbL'ÿ&»î¤,||Þ_ ò±,›5ë¹ê Ô”ªŠö ú'SÛ®šR­æŠ
+ n¶ž×¶s²ìEù€ ÔP\‘Yœ!*"îQ`%‹¡Ý-®R7ycEJÏlabù–Æ\ûUOª&Å*ƒR¯–¡&p­í¸¿¥±S2vbÆPT‰Êøþ>j–‘$ÔñéÎNðÜVŠXRÖoÂÃJnɭІ‰ÒÒx#èò?ÆË$W®c¢+ð¼!ûfì©wñäýO}"ITu³ðeÀ€ôÄ—™— F?TÌÜÖ#Ú…3õôòMÏŠªÓŸSܘ?ËTÎ1xeÐÃÙyùcÀ|1"§„5ç×
+(Ì^’e5Q"å.¿©nœ^Ò›ºa/*!Aß4Ï9r
+,#åÛ°’"b‹›Nû´\-ùÞàód
+뉨v9¤Ë-êb¹ÒU#…Ónq±¨Æ±*DŸ[>þþR‹á ªºYâ¢ÏrD€Sµ1•ª y=
+ÀTóÊ£LáYtgã¶oøï/Eà‡ée‰¹gXMf•z3¾@
+!£ŒÞŠCgëø˜y¿Œ’­¾c#Óñò·-7?¤¦-ÿt²¥‚ÿß‘QØq!.ŸlF…"k<qÝÝ<ú'§¦-Ë52Ì{& CHS‹`1”<h¬o§ [{‡œ\ãÉÑsÍŽÛ~˜HÚª†_…3 ¤cJx:žKwùÊ]ízÎ7ä(YY>¦ß§7Œû
+ÇD’ÊCöœ€¶N…b+v“Žîö¬0jÃCJšÄôvÜ2Y¥Ÿ/¿éU‡Š°2„0¬KŒ²‹”tþÅ
+—’¿þø‡»û]Ïm8‘ØïY¦¸ jþ{-ÒB¯Ù™Çï3õ[·a§Ðìrö7iËp&SûàÞxáC
+´Gø
+cÈ3ü™¸Ú»¿s=& bÓJ`kvZT/ﵫXË— @䶧@ZËÔsŒd¨HÐ"·q
+S
+€*€nDÎÌÓ‡@òPµâ‹@ï±"4·Il=H²k2PD<Š{L`%ƒÔ´˜,õ¢£C2b¤gÍ‚ÿ¦fa9ª †Ã¦ý[EÖïç·¢_ÃÒµB¤&¿]ŽÕº–|¦ŠkÑ»YU Ù,1¬éÀ"¡9Y,9¬ ‘«Z.Éïz±‘Kb_ßÎÁk£x 9§/%%É™"1³}¹
+ö‡ž;pi×s(âh-L¿•ðÛòÌ'Ñ0°cÐx£ùõRôÓ‹”AñXðéõ2Jr§ñ
+•-‰Åd q•§žÁ °>µÔûü)¢Ó ØÁZÃ×ëÏÝ{Óp)aß?€ ^VñÍMRÒd©¸)aU¿¸òCn›(Ä÷öoçˆèˆ{˜çž¿|U‚¹Îô°Èo&OWeÖ›tÃÑÐغ¡š¸€hŠ&i.V›
+®è¼„Íh¾ƒ[6*ÞE¿ £ˆŠbòmê
+TÅ…
+óÜ6ÌU0É˲‡ÿ^'I–ÜF†O ;ô h™
+·CÛ®uŽåÆT÷s /æçkýtFüöÉ|¼‘ÐKÿ—:Uýú÷¿²?ÈÒ§^׋ßdù?=ȺKuÈàþ¼%„l!׫T~lu ³’¢ñç¥ÿÍš
+q=«/@‚J¿%ö´f
+zj$$p./i3¢yÝû¼J™€©®¸îÅØ̮ǚŸ»ŸCÊH+­½–Ëþ®ÛÒ·X²ùÌÂ\:Ž=e¹ÕŽh¿Î ,Ÿ…šIìp!Šäñ[i×rÇßì<3¥9Ó5ZíD 4 ÂÒíz=‡2iĽv©šF -Ýo¡x†NÝ$’wÌo
+Øì¨$ÅÚ°’p}°ÔÀO˜¥îÓ~ Žä‚~Ü·ã çèÒC¸Ž¹+ÙCfˆá×1ÇͲÖUà\‡íY±–/þ®“O|‡×²´º
+n5U}qôYxLþ¼¥p[RšZžöPרÔcSñݾÉܳÑ5NHõÎ┈#óe¤hDtEÎ"óÑaÁOÓ;pü=ˆŒÒì†:½ÿŒ
+@&w{ úûCSÎ(—o.œY4d5ȾN÷|zdï¼Ï©IŒÓÁ–Ñ$põÔZ´é©©8~ËÈ7«g›Ó +èØ=°Â$†JÈ”<G„]BmÎøÑIÇR¾’›m ν…–Ô}*-:ëc¿/, ½ÜФµc>Ø {]QŽkG£8¼‚Ï㧶Àý¼ªA #Apž:õ:ž›tþ¯A‘šëʼîó ð:ã®ã«´,YpÛñ±L˜-¤,DåÃ1ò 5wš/–ðMEË$%Ò cå¨v»íX“uÓœS)dϘÑ>6s“„‚&þ¾f„n4 ¦bßê›|s Ñþ&¸h^îùCWÓgz€› ?@Q¿»Œ4Iú]Ò'c4};T°ò´yÙo®GDóNú”€Î+y{geŒ¦P팻‘¶Ù~ÎDé ílSpJ´Dnî}Øü–ýLõïóêw™fb#ÃcÕÓŽ¥ä×|HYè¦*öŸ°q„Sò;Y®leý«¢¸ï{¦0[B«Ù¾$3’Q¡º Ú;Z¯±½T\Ïê#ƒÀ‘çØÝ^VsTk+ä;Jý’…ÞbãQp}nŽ·™ç¿Ê
+Âè‰Ô9á%_uzö3:ô ¿>unfŠŒPú¸Žq¡è"™š/-ùî¿™…ÇúBæYÔ ²ÀFµ÷az XÂû_+Å6²þu¶çuì¾…Œ«è»î²n_PñýœÔ[d„Ž¯Iò¿>~ÕSúª!…÷þšzcG|Bêzð5ÅB.âL0]ù©Tè]Còóª—‚ï-'
+ ÖÑ´äÙ_Èn\d¥ˆÐ¶ìo¯È KÉhí–üæAo!𧷛µaÌÏ ì%w0µnSÓùgÔ"œh|á4@«¨Ï‡G OøŠx´écJÖÇM¥öò¡ ;Ù‹s»1TF—ŽÞìx ¯×Æ™Xû×P¡ x?}ÀÏLˆŸ½jô{Ξ£ÆuÖA+ª‚æ
+<õ&>-j”J×Î÷ê+™lë&Ì|ÏøÌ=—'ÙC¹Æ •o€œaäOáh¬AwÍù=m
+ö½ªt¦CK!X­~!ÌW7ð ˼êG'fðqãá— =³C ¯ÀÚ¶Ì'6´5jR꜖'Å)Èå’¬-Os[vZTfÅ¢jׯ·•".–žÿ/ãe’ç’áø:ó°v/}‹z%ßÛ_$Iáù¯,<{aH¥¨˜d Œ7&î)@ ±XGš$ ?CE—€6AÒ” #i
+-0#Ъi˜.ÅÔÃ…™ÑAvUe{ozY#&
+HѬC.‘x
+Iµj:vØF€ð`8 ±<
+«b1|•¡"aJæNÛw¢ôÜ)Ó@[èUŸðIžâA¶’'=7"Óò =¢±vòÜä•+nÛ
+e¬f•³³–™†ƒšGšoNsl6Gæ··’î.r-?ÞTg%ÒVGVZvŽ>BÁ§¸MudKý4$ˆ5UR<•èƒÍðb »$¥7ÛŠpˆSÙܤùÅÅJ42>m«­ä)¹žcÅ`ñ£â=y4}bÐ1“F‰}„Z JŒ™éÓY ëP)Å(Þˆž¶ )iãŸ?n Ç|þ: œ×PM£¢ÎÌ ˆÇÆ(}½‘„ap÷ú¸CHvJ©Lñ~ƒÀí'UF^í0
+LL#œñ_ûÞé bÔP3œ<öQ„QÜôîý4ÙC%v¦¿ÇVxÓĈ`ͦ*­ž5k8|[‡V£•yéZ¢)c”xõò¢Ø£ý™o .Ù¦Ä[ÿdÏy fVÈ%o6#JRMJú^çydºè˜¨€)õõꯠ—^ χx…\ô ¢1 ñŸRíV0_Ã
+,o‚Þ“ú‚®cK‡”¤[Ñýj“ŽK÷êð2°Ê”aœglÂÞ}äºVÁP­
+º7›KŸ’hÍMd‡Ó2™‹ÖžW603êSÑÌ,çwQve¨g|ðqP7PRbZY’ÓÜ<Aís«ÊH3 oœ+Úúæ6hRbªµ¾Œ-ÂVç™-Ûqh,Úfp  wÀõ† [5Â0^ÀíѨZ!–“?K—µ€©Âf};‰ó¶ å–id –O æ,ˈÕnd Šá‡\ÂA4¼¤À½]i°zÅ´ÈH MOír+#v"Ñl ,:›Äe˜l£w&#«Ñà¤Ø
+
+HÜy¯VÞÞ'%¸ãà«b#X ÷eí‰âñ öõ@„ÐMúâ0ü6ôÕZœúã¨éyËá£òô€ oŽµU#ýU \¹ùªwáàUc”þ´ˆ Æʺ¢,^X¦ ë­ éI_3+]üq3Aô7tÀ(wêmü0Qã®Õä;AˆP'Ž•©;C ¥A–X_./ýÇœ|]…ƒópbNt£XýÄ;ˆ¤üâÐdÅAlÞäaÒ]–wo)^fàŠÆvúN”sa|s)ÇÀŒÇ‘/F5ÚF©GŽ‹¹tá•{^j¦í‡‘>¥¢¶È¾S•È¢˜<Ž×q ‹xÞ­Æmá`ŠÊ>-^Ѽ©Iš“+üÓ…×Sâ¬ñoòì¢,ÆdÑV+¹ ‚ $#Xš8ÛÄ»‘ —gT*š0×r7A/ë¬Ozwj®©¹oEo’)¤>‡eÖÙŠ&¢ìÑ ÐsoÔâ1»¿à¦E_±IË߉¡*ÃWó¬3P‹ª¬·>¿ TÿóÇ£wãסBšûºc¯Í¼¡góºˆM°”ƒLÇÆ_i¼¶üÒ‡¨ùmzÕ«è>¬Ù*MËfˆÝÄàÅÆ/sÎS‰çž@Px; ñF‰ƒ²Àôg @ª“1›÷x„w®Œ:".­Ð•4Ú^Ng€Ð->å[ó€ËgŒË®g¼ºÌ?fnÌ€†¦úªZÃàt˜ÜÃNë±­Ð(c9âÞuö§ºPga¿×aj'.¯
+B—–Rž‹x²%@¬ññ…Ú þ†Ö–`«L1a_Xü7Û@/ Ã$—êÔõŠœ§“.„¦Éâ…ïÛƒ’_ýû¯üñ/î+ˆ"l@”òè—LPˆëãŸ75CöŠ®Ø+-”B1úÎÜôý…ºÕ3+!ª’«øâðÁúà››òëétáåBÈ
+W’¹´Ö ƒ€ñwo„±zK§O#}=™D•ÿªÊ`óbݯ¨eèÛ¶ÞGü?`—v°º©ÊŠð ¸¶þµ8"+è“ïov‘IÂÜ|o,Ë°¦ÉH°9Ig¡m%ç*0‘Š€ÖË~s
+f ÏKÔ%8·¶ƒ6EÁ ^ÞõYq.bÀ<¶Csŧd} ïCŽ¾R/‘½/õ 2oµs LzÉÎ…5…¿l¦l*’ó¼Á È”©˜e3 Dj±ÍeyF¿G²³hKHYYWáÞ'°ô6F×Ç!‘)“H½f±X{@¯Ú¹é•³
+×éHçQÎÓ
+rÄNW8my ´M×¾R®uÉ”¾½¨a÷iy®ê
+•²°nÿ¥¹d^d…xÒCi|)q-'CÒN@Ïi¢aä¹o½û«’¢×7Ýú»‚"ocî{´;*)<Š’4;à öíÁö’V–t%œªiׯ+àã0×4à1èË6þ—<µ%áÁêû1ê¶B""{ž¢UfxlBq˜oÂm€KœI(šuœ·»ŽH׫´Ž_<çl0,ÈÞËÕˆ_šäMTö]ÉÃÞEE(Ï2Vûœ3ºÙˆäÚ ×à±r+~Sfƒ#¶jÜä@âY]Óó‹0òH‰¯\…é“Ø Î†\˜uWÔšœÅM§“E…²Ð5šJûºZ$Ž¶Yo¿ŠÉ±X9Œ+ÞRœØµsäÓ UÜæö WdÑ:à"JZ‰í%âV1U^ ·& 3ùU‰ü”8w¹‚\yÖGfd£°•àosŒÎK‰Ç þë“F¹ÒÖ
+ƒDXû~ó+-"D‡&Š¬É«ŸYRÂd3¿ÔÖ—/u Ì}?*qtfCÓ §UäI½„Y¢ìáŒôj&ƒþA¢³Q5ê¸MæA¹’-ªùèÖ
+Ǭ
+a"t›öoeÒ%-‹SÐP¼»•TÝ3Ù%˜Øƒ2H¶EÆ:W ĉË*×]Ç4ª ®ç*¾®“ûdo¾äùž 6á0JôŒÌôT¯9gÃPM¬p®aH¿ƒãñ÷ Ž•åàÿX0Jª²àýt­"­„Y$ZÃJè7”5dúÒ
+J¸jVîòDðÚˆÎY§;üAÞÀŽˆ)©6¹qJØÖ®×%–ÀÇ0 `‰Ã¹ªÛRJ¡Hÿ*ng)+fL \\M®[Þ§ÿ Y>Ai¼)ù@»êQ4>ëÀFÏÑk¤éÊ_dˆ!ü*$*EhGeÏUî@††À¨ly"õXÞ‹«ÐÚ[ÂÛ€%ÖÃe³bÖE­‚ÂwPb°€f8hÉ蟹 Œ@¿ÿš‡L=¨-†À¶ð†ö§ûàÏMát8»æ2.Ý‹”øp$c؇†W¶Ò_>%£
+꬞ÔD{}ðdPÛÎÊ<HauɆJ_OkÃÕ|ÛG´åÌŠ•Æ.0¿YC¶ÀÄAÈTfù bq„‚çUöä#æ.2nÁ1úkþþ‚.t‰OáYÄI>$­ ôŸ7E˜V¼&ÿÛÆô”à‹äö=îUa-Ê)Ïà&š y qÚBÜèÇã'¦üÒ–ÏöyìÄOÉTÉä+!¸»Dçe—Îà9PG7+‘V†“Æ-yxÔôY“…:D¤]ÅýéQÓ§|ZÕÀîõFß=*­ÞZa4›Ýš±ÇÑ©*oDGàQ…y½tÐÆxËh•EŠC¹-9:Î(r÷ôaã ¢Ç@N¹Š ¤P³Åµ eYø•õf}&¥9Ñ0ÌA‡÷R•eAK8(jH$ܼ8‚SŸñ‘èU5@ üôNÅÒ~^À§"îLPÓ¾Ùæˆ)Ážò‘YV!.yåÿ°¨ÚEÅ3½CÝF“ö­dP•àL¹f;
+lÌ “ü^¾€ø9&£Ø$ªÁs:G¼LÛ¨:á¸åDÚ.d¬„¢¬˜¼2Bè™*¶xÜãøöÇÚòcþ@£$g›c˜Ã¼F«—'¾Ûœ?vçC $À­œƒ¢ßaÑ#nìú©¦J“™õŠ‚K\ô¼#:ewZSÝ/“äJrˆž ï ¤3¹Î^Ö9z¥ºÿ¶Ÿˆj“>¿•V9"€Ã‡öã¢ߊގì}ܦ>™ìòî?«P†Ëd*™ŠJ.müVôù“^ÿȈnî­6‰èÔ R°ÈRädÇ=]‹ðÇ
+—BC¬Ãº‚ï[‰Ã¼Rùuõ[‘6U›`oÏcoci­½äTI­xcå)Ï|†FYã&E'ƒL еŸì› ¢òÛzã:é
+I(`!ëZ^õB7ÓŽ-Ek}u_8‹AáJ—x¼i–¯Ô7Õ+ ¶w…—¹2(?ßr@\îßtáa9b^²EUoJ¾ðù.5S°YP€à£Ø˜$O(©b~ é¤m¥CøVãk®^ *8–%|¨É! ˆŽäÝåiLÇäM¨S—Õ`±kÀÔ-%T_·Ž"í‹lâÀaSRP}²†È«ç9ƒ .xÂR…R%HHê³6™E>Î5fc÷0'4v`DQÔkC-":Oïì‹~¼¿ó.´Œ§¡ *ÁÚË;‘=“÷·,š¶¼ =â·€)µù`ÃœÒLžÉ7©DËGî$|
+9© ¦ìš—ÀQ4}KêÂï³dK
+´AŽäðŒÃãY¨uíz) Æ"
+?×ó¼]X’vÌ…SÐåËAÏÊæ ª‡Y Ê…‚}¦-˜uc‹·0M;]¤Ê-\«L&øDÚº”.ì)a†gA¥ðкQÎr¢…žð8I9|îl©Y^Äc°²äH 6†×`uRŠh&JØ|†3Újd£{ MC€ g”W½¶Bΰð‡·B› +ŠG÷͈½ä«ZsÕ„Há–%“Ðjœ³hKÏ+S†Ä BI±q'R‚3j\é$(nEU<«eýÍ9_¼ø½ä‹(þyóU_Š>¯ö™ïp Mœþ÷J5o¸‚láF¨ønýêiÝÆpzÎÕS’%‚¬QBRÒ‡VƒN=>X.™€$.Ñ(KÆ“›K[Èh<„S.%a–¾ëÇë9BŽÂ€¢=_#Žé¡|²2£ùñ5¦ èï™Êp„ë
+»–á‹x¶‹Íwi`×e°ˆù^ƒ
+» i¤©%¡‰>¨ƒSÌû)ø$ZNد‚žéK>Xg¹ù;)‘9©BN“•Fmí¤­€}—}SòÕÓÞk€#BÇpj÷î½¼E.\"ÁÍP»—oÂîÓEZ¤2¿ ÁÄÄK;53
+ ÉÒ  JpÁ¾ï[I‡ÉÁwLgøk”tØÁñ§G «CŠ`R~¿
+thùî¾3[HBÑyÜ÷p53*‰æ´šO6¥!qäc™x÷"™Ším¿LÕ’Ã/iðÄ †Åcû¢ˆkÀß_Âmhˆ•²Æ±QT jbm
+Ëp+1CLÊü¿ŽA@Å-1ý|y9ˆ8ë9Â2LÏÁŨ‹ÙA˜¡A¤8ãù®V8¼fDóªÑÁÖ[¦6gŇËÌsYˆôZ¢IÖ¦<´Vµœg´~­
+î'í<¬pPOÚîçˆüÀéQͨ.±T‰ApöVâ°‘á¢mØâ
+.n+Ø tøÂ!_‹S‡¢ùöÊWüõk3›Z1KXGš?~Zóí²ÏŸ¼è/=¼hýMöcʹÞ~)zy”ä}bH›ý]?­y}ø¿¿H/ÿùµÆoÈW¦‹á”øÂm%(uðök ù³`s›öñƒŠ‹Ã‹ÔóåbèAUG¼áĸ™ô §bB06»ì*cN†q`,ÈlÒ¯¸–_’ÞOÓDûG;DVf%Ί׀ahEFbë…?ü*,¢6•'õžvÎ ¨RÍÕ98¥‹” ²¢À1JÈ?*1 ™‘÷BfÜÄÐP(-b©¥r÷ejõë‡JØ[~Š!ãf „„º³ [ÞYÓ1™¯~ÑâÃaÿÅwöu=…$)ðs¦RP d Iar®ùI—„€V¸©Ó&úÊ«¹•?åÃX¬&%Mž·Ê1Ì’%øÄ—¥G«½¤Kp48%GÙË0Q&;WU¾K-¥IþŸ‰9 Sñ?pÖt'j@$ˆã*ÀÒdq»áO•däæšr\~­…~Q2ܳ£ò³"M’œÎfF‰’.K8ü°÷’¯Éæ^#žÅÖ‹8×"øYÐ;Œx
+vä<£bø²ÿð…%ÓinƒÍ'Î|°ÊÊ2úȈŽHÁ±³늾o%~ÓVüÃâW)êýl
+ѾÛzs&dƒ‹BûÈî}ò*¶{¬QÖØ]„¦Ó<4¥eM²¬|ÙA/ëMØ]Ò-dÿ”;MÐ>؆~£µ–W½ÐÍôÓK\ý¸qƒ"à‰ nÍòÂ}SÜ‚*sÆMåç[q¶ÀW"Þ&Ýeš°{Å:—ÔšˆŸiO[ÕíÒE•ÿVîÓ:Ì„M­ûR$|±…J;|ã?êÞLärº¬zj%ðÿÿ`
+H‰Œ—An];DWà=¼ ´!‘¢$Ž3Í.>Ð#gÿÓ>%éø¶Œ¶ƒŽ]O¤¨b±Ø^ÿ±:ß{Fó6|´f¯ÞF{/}ÖÑb¶É×EËéÝ=f¼†¿§ÍlÖgò×7$Ò²ò©Q†³V¯kÍ(­õ:õÁ¦@Nh1fëÙslP3H%PuJdãS¥äµn„ÛŒ^½ò½/HíIœ´Ù7Äjሙµø‰ÔÚ°éU´Ø ’î£{î+y¦×b£6/ëJã=»>×¹â\Ùø(µvÎVrC¦ÍÂ2ª½~©xÀ;ÉTnæ}c†E Gï¯aàÜŒXs´sN¯¥D­“_‚ Ïj¥Ìì}<ÙLëf}ÌB™ñ ¥ ÷SšÒ²*åè%öSFŸ½Åh£•qŠS½÷VKoÆãÑ!œTZéyΩ³ÌðÂ[× +³xmÀ
+¤L*¬éÞǸïºLuØVþ>Tår¤˜ü 2sÖÎ
+j—t úPêJYfB•¡rx€Õ§žĉÄ`gñ ‘1=G›ƒœO} ?âáV$¨#Ú´R‡ÁÍj >
+’"”I¨už’KrCw/+™sÙÎÙcC ¼Ïap8r‡j=ê€Ôæö°lFrM.’ëœÙg‰V)ͪÁXYÚ7¸WRÂ8¡¾‚ø> Å‹’ñÍ9Õ$Ò¿è‘hLnµÛîêï™âbéÝDt TtxS5¢ˆ'Š^b…ŠR§ÊãALÞȉ†æR\0VÛà+¡öýH×OnôØ¡wêü®¥Úûz£>o¦z\±9ά!Rö•¡jˆóP‹nA¢8œ'_ÍЋd—ªŽÃPÔCÑ@ßmGí”Rû9†FÔµÒm+ -†RrK6DŠö‘1%)iˆcã^WÈ
+¥ž¢s „¼ŸCîdËø·'›¬õA„ÖPàõÕ-bQ=
+¯̹%Ih>zJ0uXÌ !?t® /=?ƒ;3 ›ŸP(e«cò^Ãw(k°aÀR´ ¢±Å€\’Âh12¤Ð¶îL…è<.$°ï hœH«ù|}ÅÐ+L9K\åû’ d“°•VïQ÷åNâZ£¦µP‡s'&<ç­IÑ7Eb)P¶5a–
+ÎŒÌM- ®¾3õg¬l <WíRmCø
+¤èUþd.õ“‘)t´ÛˆI5™A¨œ×̓cf¸癚PÃPDº^7È^ 1¡ö{NyǘàJ©â  @é‚yeRDÙjˆfoáÿ<>a>¾Á`Aƒ“¹zB$\…Ž±ÝÂQ
+†±ö¿œ)í¯Èµ‹=·®Éô¦7c½3?‰Ë…¨Î©"‚ùÅ^´þÄ‘’ 3;¡Ì©g‡5ÑŸžâÖ²ñÛÓY®¹Â0üdC ª33¼]°FÓ#[ÛÖx2¦aå7µÃ…Kñšk îDâBþš´ËBtuÒâ¹µïSëò’7qF-GýúX ØÙ­˜»žÓyîÔ¬5
+ˆÆ‹æˆ«ø­6@&/ij^?iIˆëNÿ¼]1Xh†¢ñÞ˜à+BDÕ`eÇêwFëe…ÊüºÅaôb²L¤§9÷­¿bB-
+Éy™X‘Z—ï’ôÌA”³…˜ëÒÚˆR•´ö×5»<(=ÆËí[Ã:æ#Sù; $½Du9*vñ  ‡Ê;gwQñÇ6ª-sI¦VÑ£žSœfffbÆiœ²•’›vÖYšGT2:gy$6%š,Îzˆ€­rVK$´n¡l4b;[‹ž,‡ÄÆ1Rs­gU‚òUšÄ¨ß[Ý€o…÷ñlAèÙ¬ˆãdM eMõjíùõöß·QౚŠŒ˜÷±)
+©‰ƒ²Ž1_® c脘Ìø‚þ¿ßFÅDZ¿hÆpýü1èS¸Ÿäô[©_ÎúdÆIÝÞÑ22 _Æôû
+
+ƒy5XW¿õd"©¤Œ¶RÃ~ úîr¿äXNUR^}‡kÇí ÜAŸ¤ê»‡ù¬gÿ¿âz˜ŽEÖdäíi×>.Yý¹‚¾–3¤ÌØI—š?Å|-ý2‘ UVô›:]@_êt‰ö3 «€ê!g”òŠA·p˜
+ó—
+mAð2[ÑÑb&̵øl/HjAÄ i¨o<4\Ð|ñ¥WÙ>…Âì¾]#]R«ß#g.¡Eo¶³6Œ!îA[S Í@&c x©ijΦ] è\ \ér›†öŽcb“µå»@`ÂåÎ}|«#ŪÂZì
+‚Ýg›ê÷ySà_o7¿3ß™@4&^ìü ÕÂC2jÁ(a™²c‰é‡X#VªG¬‹ÔÂÜÞÂp4ƒØÐØv1ÉaÚ§= \&GÉÉ2aIqŒ' %ÆÚ÷UãfMÌb ·GâþY¡x€¡ðøËû9{`â"á¥]R¨l S½=¡à=}Æs¶J„Á,T\EžÞ¬'ë+;¡/ŽrqŠL­8þt¯ól E[¹`Jðì/D˙ÞXË‹d”Ò¥ îú‘ ‡|ƒ¼G] L6TG>Ÿ7jKûã­!  H9:™ðX2øx'Á^æ …Q,°ûú0‡å5ÒI¾:’¾;#æRŒ‘læôYfñq˜J¹[îšßèõôIù?~2°Ö\[Õ‡…éÎvuG® Ì)ÁDíÛx±Àž} ç5¶};9MD¶j{¥ãºúo|èƒÀ^2›Q,¯ µgCjèyù‹¡ zò%|uÄžÝGPg»]ü‚ôIYÃó!RMë ¬$VïÇÄjiòv–<Èõ4\¤§81‡¬iœuä%ßIé²MIÐùjð^ë˜ëD›ÅVËDvYf€BÝDÛÌ< ¦^•„P“ª2Ÿ.ÒQB^zõ”Ë›+Táuµô~ÊÆ
+öŠ
+tý9ÔjØL‹ÕÏΙ­‹ ëÞá°Q£)áU’F.îy^ê7½,ÑôQ±ôžºŽkZ7¤xå‘‘«?ÆQ{ð;q¼¶‹¹bpùƒCQbßïÝÄJÝ^¹º‚É.jhÎ(áfÈóÆ¢- ž¢ ŠË0æ»0Cç… Üð¨YñsâßeôV£¤dKØؾ¹â+ÂiB¨¡f‰ñ0ʺ¯X÷‰³Ä­ø?aHIßä× ™yÖ±Pj%> ‘ÞÛy-Å\QÚ¤Ç^kU¤dt½bñ׶¢­Ný™¯ž
+qÕ ª~í÷ èÃÄ´ÐN’RÑVôOß^û”6=Vÿ”X7Y÷Ø8›öš3;,…ŠÖ%¿
+ïSq4?±ýÃÊø¥d¬Eq—„¹ðtYg#4{t¤Ü÷ê2ÝBÞY¯6˜|ý¨n,™¯ÓÎesœ\¢¨¾¡Ë÷!ë,ÆÞÏöø¦ÏIõ¸øÝ/¤Ë[[MÜwc‡ˆ³¿ºW°ñY»V,a´ïZÂ/Eä—†¶8”¶€±’DÈ‹%ó­sµ ë’¯ü¿,‚íJÔ Wæ6È`!ò‹Ó=lEC´’†2H #|M©Ž9å·oPš£Ú²LHd˜Œé
+’.}€Wº’´„Ħ~<nÔIµIñ¿E¹¢5Óx±´¦u×ç ãÁfþ‰NÁOä9hüýH£-9]=1l]0igáˆÞ±ß—À8`þÃ5íäÆ6ŸAy˜”ñýgÈý«÷ÏB‘veßß |Dˆ!F]AOœÙVEч*ç…Úëý3Ïür›[§` Bøˆï…mø?;#Mà/½¹É¶%~Ú }Ñ_̧Á8ô¹g9%z×áŒ2³ Û4ˆ‹®7‰ü˜°y2*HVy ¼¨Â0+*½ê^
+ ‘ø­ŽxÙÚ> ý*àŒ¶ñ « ´’¬;©8ºÇ¶°k¿çIWG új婢*|FØÊ?G‘}æ¼Âu}6ÅÛ,W¸¤åMV…¾
+š$u0ÌÂ †
+„‚—sÉ5F&K„  VU Ñ6Òo{nbàYTP?›*Y­-³ ñ³tšg¼ ÐÇr(dëñk¬šŸç43?Š€‚9¡S›ƒÄÅnbÿ `cÕ/»+kÆÏ€,¾ê`Ö¿uàÉŸ Ú/2`lRŠ9ð bG»tÔ´sàoÙZ²?x®fƒ_Ú¯ú&¤HN-½fæ¸êÿ(‹¿%@2…¨À „‚ [Z„AüEO, KPî8 `zªèµ°Söb…rûúGAO×}ÿÉ›ìé—³žøÈ´S*Ú-´$ž#_‚þ¾=-A ¬f¤Ž‚ê]ôzÝ%¿?
+z•4KÛä
+Kí¨ l¸%ðÐ9  œ.úPdÖ¾nÍÈø}z·–]äãæô«>$¥Úâ*†l¥H¦Î†5NÔÑ«P$š Èà…p¸¥ÈR#„®¯…È~Ü’TQ̈÷PÒ) ‘cDù¤ôâœa%3F”Î
+ØÉTÄ1ð ï™ÈŸðSPjÌU]]ë'ú-}V4v´
+¹Çm’Hc½:ÍWÑð<aò›â½ ßSˆMêA
+„Á(¿ÍÉã94¶˜t]?üŒÜ´(‹Ø5ƒË`#+!Tìêdñ‹è”‰„D:‡Z€˜¾»%^¶[ƈ —BÚùŽT°id‰JŠ«^ÐfX¿áø NÞ ë‰æoÐ7Z8f“
+²E'­ã†"¤±¯xR6Ñ0ÁÊZ´7 †ŸR×)ÿds* (»B¤¸ÉšXµ8«ëifé+RÎq~Ž¢u NEXNZ/á„Ð’sKî1Ö<KÓTAyõ & ùîYÖ…ï
+ø?…FÀ¢v™ ή§0¬G°DÉ´q•Á½q•HÐcÒfäX—R"BÂr Wh};˜»ii¶ȆAU8‘áÔ
+MÁ‰¢ÀO®Æ ‹ èꢰ\B\+=‘Çë1f#àva@d‘‡Ošÿa@¨0ÿD
+Árî IkÐBR÷¨)(‰¤ ²n¼@/PRÐÿ8èæ™C®èr…ìy
+zþ„Àñ G·fõ«¨ ò¡Jì¶Ôý6Ô®3e>Z÷‰èñ>¦2•w!OŠöö@s(‡B–··Hƒ'ÉkàÚÉî%'Ä>–€Çr–M4PÚ›bê™{ê³›‘óB±(AnLašXt‹n»=F6§Jtºç!€'Ƈ_€‹1*Õ’ºbN=(ƒ¬p<6¦›!`ØéïMàI²BBÈî¢hÁYh$²O_ý%¡Sd‰àpùÓšÔöÄ5ŒégZ2‘"Û-»!üĘ0*>è %JUÇ6_˧ghdQÌ?ìvŽ(š¢#EÉ5súР룆€Ñª*ì8§L!S6ö% ˆÇAÿE
+ß(º(¯
+êä![иô¦±¯ˆôZ@)AªqÒ ½’1ÃJH£˜ð‹®n¥ƒ#ÅÍõæ&n M¿‡Ô?(‹d†–LB ,Áƒ=bƸ%c¦~€»€¶%† êr$så2F´1fY*¼üºÌSÐ÷» !|•uéwâ=Ô‹~!˜]1ÜBäEÐ7¿Y\h/t³%ŠÌMð·!Ÿí‰C% #‚jkG½ãMæX
+˜LÛ9ÝÌ'kîŽ
+‘°»7‚ … R;Bê,¶†ev¿ª˜(ÏB¡a.SKn[W'­˜9l/:Cîb­å£žcnçuÇö¢
+ÄàXA&ÅU©)s:ãáª)ÉñŒ"“ÐÔùD€²äÒŽ¦ÃÝhÌÒ]zùúøïGþüë£fl›&¥Ñjè–RÚôùÏ=FðÝ•Â×d«ÅXÂ(º" Uyˆ¬4 é›<`‚Þ½‚È%¦]Zî bc¦üQ©3bÒ¬JFÛ¢cØ+& cà⹚ƒBé‚è ªèö!BÚÂÐ5—n‰/U]„ÐÌNhH!ùÀ"ÖìÅÏ‚<N–8gÈÇ Ì ¦­YéD<h=!‚ŠZÄ•1$áJF¨¡é—¨Jʇ”z‰*•Ì~dETIQ:’{Ýñ\¼ì€÷×Ç-æÕZðø¿´p´#z9TL4Õ?¨4-Å©s§0J›¶Ù«0bw[ôµzo‘â›%z P<¦bÖ8§!©ÊBŽé6WUVs
+mÄUŽs_Üfˆ²Ù®aÔJ¯:œz®RE6~ƇuËMŸ?¼šb-jRQkß!C¿SqŒ0µ!Ôk3A´rÝÔ3j¼ÆíéÐn_ÔÛ¡Ýl¼=
+ÝÅ,¹ ü“®!UU Úu_õÄ]€º$ºŸ,Fs3?,)$Ã
+  ÓÈ'q}CÇ™Œgg°ë7”
+=­Ò'N£‚tGwB4¤„ ç;„9¨ô¥W®8ȆÀùXF\UAöÅŽ20ÇE„!åÙƒnz‹GmiÎ&ŒŽFéI\kC!ÞÏ€xTC}õ®&ê9”=Ȭ>â,6Ç9ÒÂÅd‚d›Ö`K1)œÜ–Ë_lcš‰2³LõÝ ÑȇAT]´þi>þb
+ª1@ÞJ ®Ríymǵ˜ð¡†ÙW)¯Ë:_߃
+'vž
+2„.èÿúêw
+—²$¦·£žtÅ_ úqݳ×}y¶^—­‚¥‘fùlÍKòJ*´,Â+·Ä})¢â¬ƒ@=©­h*ŠK q3¶T„£`zµ}¨B.˜ 1„˜ÜºU˜:*ÕŽö­ê‡Í2JN„
+E”C±ÕþáœÑ(zr–Ó÷k.Ñ4­ „76åû* P©x8WQQ攪å ‚ [”ºý. ¬î¤²+ºµ »Âñã빡豊 uCF, ®5åM§3üî¥%êì
+ioƒ ó/?XMÆG Ø´mÁø  #”›é ¾lÃõ¹ªSðM/PjP,ܬ„R¶:ìŒNÏHÿ‘ïˆ
+Õ,çe7g¢ñ誑!ÛXÎE"?“³ ÙP1ì&—B£¿ž,nGÖPJã6CP¾i¡A•ÇHÔ?~ýû×oÿü•¾þþ¯_¿ýï©c2fˆæ:æC SoÊkØدÿ~rS“å,LÑ™ …Ú“yBP,rjáP :Lø¥Ý#$g3Iz’JWFð`ž®Ô­SÅ`X÷9‹Q½Hÿ„x.ôװ6ì;Œyö5Ä«°€®pmÄy:®Lû¹J„òøB˜ uD>Êè)+&OÁŸ6+¿W‡<€¼ýcŸB~ô*®z *¿óø¦k0ò×Ók
+œStY¦<fEˆ¢¦G§¶¸êµ:…µûY¹V”a5.¸ª¡úÀäÖöØ«—3¯=8çurÞ^ó>Y½Oò[uÞ÷á­ÆºWn"mE4¥7‚cDKeSj:ðRu¯ßSPe¹–?›× ŠˆV—ƒÇÖt")*W…]TʲPAJøª^'|À)ê{'?€~@³¾µDï†4+ç*Ápeq™'€*'Rfž”#@;Pü¢Àéxš«¤mz;à¥@rIÒæ÷Í3Ü16Lá†%ý'€‰‚7Ûu];¢©hÔ¶¹DÚ±‹ZaMÛ}Þ
+Ä1PK²Cº…ÀEÄ~ƒ¦ Žq¸NVu¬ skÎ@ Nw¢~'7³j‡„ˆ<QuñàÓpÀ& 8à݈$ÀÚzÒ–{5,P³œ ¬9õ»Q‹WÐȪé e—p–®Ãt²ARušÄŽ>!sj;›)‰ZƒÚRðÑëœý±vºZF’G—mÆE™çÙ©,\m£,
+=FäÃádšYê¸é=–c}g‹6‹Q yVNñ\öPpL['mŒ&–o­ß,?`4·úáÜ«%!ûq«Žª@t¨òק7È#@óZ¬«Š_Õi”‡‰¢`oF~<[òiñš óº«ÇÖUúÜ•IŠ™#Lß–&ìóÓ¼
+ëY¤%þ„»"múu:ï†<s]{º[¿GÞ¤™^úZ;þ#H™è uv>²yïŽC6€c=~@> B@mý8Η’µx•õÑQ5‡»se‹ÓHIF¿ìæ"c#ÄÜñƒó$È¿
+éÆóú8¾B •X<Îûuö˜ ¼I‹Õ²›’'¯*KýËÙ%ÜgÑÆ]¬5. Ú7`BNŸ7E¨Ü„Sp’Ihê%R €¸?‰ýЦ™Dv’+j‘-ŸÒ$Máj¼V Ð31¼Å{MêœÇaçЉ")Áì™á>@nÕ?VÂâ
+)f¡º/”KÅ0÷{™§´+R<(É>uÁ…ÔÊJü]¶½¸€K"K•"ÀíT¢\@‡³SvKÿ-’?
+Aír3 Å5[Á«H|3¤F ¨ð\ö
+v©·èÃ9I>(HœÆ¾ÌPüµÏ²¨P© eâ¯s\%'Éä³Á†2ñS«¨y*âe kMù `Ã)ÜÚ›ƒ’ó€6£!ü+ô³’ %0ô _†t‘*Ÿ˜«{5˜qÊœ%Ùã‡==„
+Û-âu“í¥Ó´5E°èç «š”P-*Šž´Bd³[¬Ô¹=B!K@<% âá™VC,ÂsbÎ0´×š‡Õðθi-]kÔd<œâfdøÓ%™¬Àï ‰ %¸hžŽA€õ}ªÊØ8kÎ`WgârjÄÑ®<ÑPHô_%°‰ÓÀºJØ,6‡GP<–
+xcPÌš½/71 ,B‡¢ÇMÜ.Ò5]X`Ç`àÖ1tÅç0!nÀå!¬Dd‰µâqæÌÕxnÈ]a¾üéØÿ$1½9,ÖÏã²$J°­,QKjg
+D‚OÕrÊk²(ÀJe8;Œ½æ>á8âX«âii7çÈêÉ5ѱ}eo!7ð3üVŠØÒàc6ÐÙú‚§fÀ ‚×—ñuCÞà-òØ9ÒÒÂÊý:¶ÐFb³¥UÌ‚Œ¯_X&JýÂ*“)ÍP_ŠÌÅø8,C}*bCdE›–Ô>†˜“²0ôi«ìĸHöštÑJèí“%q#œÐz¬Lè½E¿Ï¡èw}}üD„eQ™wbmJÆ^­ýëØ6„‰}‹+’Àùðoû°Í‘j¥È6ÿ¢èi1>n>÷}Ñ«}Üa1È’™s†¶Œt÷[ñ’ÝE²ja`祣”Èe°Ëœîî¼eå& Í¥ úíM)CÖ,—í x8;'ž,v Š®®²Âýä TÂ.Éî­JÖ—Ä?xB@§"•£äD€Ù%¸¤É»á¥öë0‰×<ñ~× iÜGóá¤mW²Ä *ÖYïÒÏl±/¾ˆþ)rÐ@ðrç¯Ú["Ê4ÙÜýÍ9"ÞIøòW4cp,úNI}ÃÄœñ3žû«ŠFÃó…±OUi+k€ÿØßàiH+ÉŽéÂLƒÌà—· tö[0¸)¹Ä¤KÑ îõ 
+H2À‹ñ/Š.+xúÜŠ^há¸]¯E¢˜h‘€…M`¸£‡šà¥Î\’¾c4s*"÷M–À%õ\qŒ_,lØÑTî9k©ÉVBo£r]ÀöûÎ [ ±ÉµýgŸšÄ¯Á"¥¹‰MpL[(ÁÓ"O“÷
+¡dMñ¬[øàÜ\Ìø}­Ðï%ú5$&øãy>F¡†FöØ›3õs†S©Œ×°DK{O0ºÉ&IÏÁ/â¿Ü*ߡ̇˜œ§<:„CêöªÛuÀ//Ú'>£u¥¥xzøkÉzøsÿ®Ç\† LOØ)Àgå4LÙ1œr•«@ÿ|˜/ ˆË8AB¹¬c^EÍM@[æKNàƒRº^È:¥ý¥?ÃXˆB|&¹ ûX,ÂSóL$K‡ÎÅ?O5
+C¯Å;bhíZA®ßÏc¶?~ò0”`?QbT·K؆^3tPýæü¡£H¼·þÉ)Z¯1¿Þ6w<[7@‡µ ¸7\ÌÉÝ­±“vèI࿦»sØ1IK_®UC¯7i?À© ß ‰#Ã@eèœ+i€ \}[ûIÑÕ,©ˆe4¢!»ý¶(Êбۊo®Ò«Ž‡xX˜(AÆë$怆ÑàaâBI½Ðq®´£Ò]ÆqRÌ ÕBÑéþôxÐÐêDú Ëúmäc%-$¬1ÙÈF‘¿J¦šC¼½†`Á—Ì/'E}Ý7sÚ‰ÈNðÐ jùX†q;þWè¢y­owˬmƼ _@úB÷¹Š \@Vå#V„Êá@Ë°²ù »ÂžR‚¶`Ôñ{eaŸÉ{UäËîö™ÏëCø‚I}mÌã9JbŒ°Š÷*?톕ðƒ–dPmêâ;ÅŒÜYöQµ>×¢ž³"'¿ Àƛ͸ésý?åe’]WnÑÔ´ôHŒ9Õ.jJíê‰mþw$×ÀEƒÀC6ÑÀZ“ÁÛE¼ª&FÒ79/.Ú†ôã³yk–ñjJc‚@ÛqŒE‰€,Ûàe§†°ÿ$)O‡q ^Õë‡^|W':jMCÁª&» Ø¿>pAQiÇÃ1½%RØà!í7¢#n\Ÿ´! ’¸†øe‚òΫKÜD¥(̺Vhó-K‹2RcA2ü…òÁã)TN#ËÍEBëV­A} —/²š0Üz”E>ðÁxÝzŽùSÁCÏu8ìÏ ×üü›=ý²‘µa•äÈI%,É%úüvP6ˆ©®d_¦û{>Bùû„‡ÙÔù~Á6ˆ~æÔÆq÷´„ŠêMiDº!_‰‚Z8À^p!¸"äôsÞB;ñ3¥’|E¯þk"\Ã,`ÒîÖî‚QJƒ”à[/uS°…hç¼c>we²Ñ¦„¤óŽÁ"<‰E]é‹~ù‰Úpla;áBœš¹!¿gKZ²µºRÉ{=|“«LZÁƒkMqS‚ ø¸EÂÚƲ#î‹ñÁTRfco
+.w 9§±Ï¡€NÏå(SSÔDƒáìî(ef)Åx7áû&Ìtæ‘|êIÔϤœû&Üëp~Ê£=ÌÞføãËCÒwåÔ¶ðë¾Ð¯;¶Ç€O0
+¹Íc&† ùR‡=dX~ÞÒ±Yáø`ÏÚõ^KÕ#b`Çú¬´¾Šqïø‚Rô§îu:…èˆî–Ÿƒ¥¡7ôˆ÷Ýü5’í¯¸Õín[ÔŽÉkÈ
+mÇè¦D¼a¿Ž2Qœfyín$ƒú`—ºEYïnEýáûê¾
+ïg £ÏjEÊoŽMÉÒðtškù8æÍ4Þ
+*Wõ'WéÜ7½bY ‘Ó̹Y¥3
+™O±ØP:Çî™RÚ^QÖˆ’“àF M
+­ð¸³ì¸-
+'ðY<]ºèâ½gøs$™52¾Èü­ã/ŸíÔtb¥ ®(1¤N¢Þ»TJïèš5ã¦ÉÔ0o,EŽFà
+‚yœFG%·!IGçðÒñ=ÐÿJìçßè°N=rÑטBI\¿ØË©˜ñûôÍÓÂË”I 9aŒ›4›Äÿ:¢Ya (PîáÁLkÁ,XL]UõÕtDjÐñŠ†Œâ>Ë>GËÄÃ4¹…"IÏ•ka'AD¹Ó¾ì—«Q­ävÏg
+ãHyôåa,;xkgu¶¥ü‘Y™Gµ¸ÙyÑ x–<•î*ýTva×;öb_4©„\Œ¬Íˆ‹ 06–bÊÁ‚ÀÞ6½zõ´#½ iâÐG‡PMcûñûG²ä^©EÒ훦ØÔ±VL3î[•í¤‚@ÏuU‰j@HŒøA8¢É\!üŒ+à&œÌ¹ê ô}·ôÉÒáÙ‹&džJóØó5뮡waǶd@£– ¹¡9¢QDÆ­mÖÛŒÁ#@e‚3â·p#Q4éÆæÆK1{®#ìÎœ÷s(ggí0¯uûv}ŠJ7dgdñÔq8½¸¸x¼Ê\™œ‹“SBg‡lU?ï–“ÇRÑrO5ÌÌE7]+Wi¼Ad¨³Ò‹.²P{Ñà¢pÙJ»€>@RsÆ«):B2„l°Bñ5&A²l’+wGEOùHlÈH qk•S⤽åO¶¹ÕªV¦Aôfs—8KÓlhÖnåÞÍWãÿ‰%e1yÙÕ Ipð,²r³TN|m™…–Ï»5“,'‚ ä†û¾Z<IÓ€,¥»X*jeQƺBàWèã(êÛW½ƒ<6pkŠ û­²ƒ<E«°Ô¸ ÆšérHsá$Ï°wÁÍ·º~P„ÐÑÒªDê ø³':ÊïsÄ7ÈÄ‘Ž'g2–• õn24ûPÓã5[ˆi1bâ‰zð3X”Gr­b“>Z8[(¾ k·SDVÍ·š³wCbaAúp µ`ÖÉ”{ñØVòÙ ¥àôá|ƒeœ€,08¤º¶J#eâî6yú"C†bP­ç¦7B—uÎÚ!d¬´”jÜâ« …ÅJƒBÄ“’, C¹2Ê7˜ð1ļ%Â)–Nqƒ í[_eõ5šj® éb3eîW3!®U¦óßíéò’Ãé嘂‹0°o[`Ü%`kŸa'úÏ>—`}&3â4om·€’ß“³Í>èËA
+[ôªµÍûIéCJ~EíSä9+nrôE:/ïÊPòØÂùn2iø+BsÖä›YýpO;4“6•·>LȈ°ó‘Ã=í;Hv+áwü5þX ”¨*¨å½¿}‹{¿®û3Hïc÷ùö”€ú$Þ@/cD®•/c†¨fÁÑ"¢ÑàÕæC׆ZK€(ylƒá³ÈÄÐ{ÙE?‡:ð|ê:í ZCEkC~æþ>mÉ¢ëýÙW¡E0(I#÷p¾ËTjøk›¨ˆ•°Þ[!,õCLÌ÷ýôŸô=‹™‡œ•Y‚é$è–äöeÛ>Efv%C
+(=Äòbaû©“Õ YTèäáΠ“ÿ&>åM'KíøÍO…b)­‰C “Ué¨óVŠþsÊ Ðgä$ú‰ׄU0—3ÜÒ)”Žè<ªcq°‡oSúñÏt›÷Ž‡„]jŠGÿèmo×ýè…®ëõ
+úåÓä-2ÄMqJÔ4›²Š¿@l!ÖƒŠÒì‚0!~_}€ ò›=6„oD‘B!6'åñ]båý*÷P5†!Îr™Uœtò<Ö¨_†}´bñ2f‡×v|C2±%³ 2DȾ*ñ÷xfåÎ|=§²b?™Œ•©×¯©?y€Iü˜Z{x ÜRcˆÙ„y­NE²LfI4»ÖøùÖ«}Õ;ã(¥ÝœVo_ƒ€)‰Â¾Ö¯¯‚m¹)ŸÚFÜôZ˜m*5V¹fûq+1æÃ"Xs¾¶ê²[õÚòË9¯ƒsùš×|ÔmŽS…TÔó<÷¿oC/òÿ“ñ
+é*DÅW‘ÎPt†Z1àÓAˆ"‘‡ÙÏIµCìL~aú~p „âó¹ƒã[×r¾#Æ–løAÔYb
+
+‘çdóv ŠS3]mCH„Q¨‡ÀMú~^äC)wÁßÆ=6=8¨÷SÐ6"+8XÊ×oA­ w~OY’=< }]XíÌßõœd%Û*ñ‹&(Gà=PÞ¹!ˆ‰ÿãer^×­áœ#¸æa-g¢-•ÿöýÕ
+Å&arëEYÓ„_,ûœŽ¡ŒÐšVb×XÁŠ$œÌb‹h†Û½
+Òµ¢
+;ˆ/Mÿô0Ó:Ôï¦1´ïPíM›$±,³ ¯¯G£,™ÎâÍ6å 8T ;Ì5"€ð鸔‚á4°TÉê[3Õe$b®cAl§+¨.>vHò ²fÆ~€Ó÷U)ÔÆRc» å#ªqË5Á,|ÏZóÇ~NR™­ñḏܰ<le*F1’¢·
+ÒíÛ%î3'‘tÝ›pï\ÕÄ(qÙý©ÿ^LË@¡áàÑL<{øe Î¹,l­a¹žwBÙ43¡‰òQ uÏ3(®f·IÏ”•Þ”uëNæÀX±^9ªea=´vN‚åF؈$îeFT
+g¯5[Ã6ð°qâe€ieV»·E1¿vÿp¶NYÇë½úYÍ·ý}­ÕT)2ñHÊ–¡Ýx²Û×ɘ¥æì˜*‡“ÔñPujø»ÆIY—WÃ0ÌN |£ëîŠí]gé® ôÚy™ÉöÒkxjƒ<œc¶Ýiá˜
+HåáÜÇf
+Îô‰áÇJ ’<Ëî5J¯rKu»hå< ÕÉkÔåDt˜ ©hÓ`Ç5NM
+äq¯æ;—°¿Ê›²Î½œ7HYeiR\Ã/ÊBCÒs ##­fÒ«ÔÖËYz\CfÈú1¸°¤R¬LdŒA>¢Ö±9UV
+”3…MÍÆd{v•g`²cÿ„Ñm“_åÏì8 Ó<CHáÁ¨#O”¹2Ïsïpâk’€pDYÿvl“ ÜžË!CÚKÏ~ d×Ñ+e^n'Hűâxúß^/ÁT(ÄÆ aŒÈuùÎ`ž¿FÃjc/nÌ=§zx„Š³3À·@úZJÜ™bÕfôæ§Aô»×½ƒ ;Â…»R^5„Ž²ŽTë1{_ ?m.¢ÒÎȪìtÏat tY)ù%'Ø‚Á•Û¾MRÓÉŒ-†l5¼@Þ²¨.Ä% _~ÐM@ö99 H ¹: Ïï쎭ØÇ¿@‹~»q<Î<ŠØà[„*‹»=€Ðt¸ ç„kü/J±™¦¼ .vŸX­8l=
+ò"ì!Í,Òyù:tÕW^­Ñ$¹¥²K.bb¥Q7²¬ ˜äŠijMï½Õ.N¼s%|‚É!z‚¨O¡á!-bÓ=yŽ¬ f¤Œ­½8Q¦c9K\%0^÷F‡µ!Œ‚NM›¤ª¿0¬gFFsƒÐ09Ú³&ͧ\¿R·ÍDÐL|F˜jòPª@‚Ÿ¹^ŽpCœ0ûÿíó`ˆ5C0±Ãe¦LyÊÃs‘Vdm/Ý‘7w]¤5‹‘&lmrϹZ~ßæïUïxçã»ÄÞ¤ÿÙ©ŸßYmW°íÊPyEúpp#Ïû¸_FÞÁÇ<M‘ù‡ ]|?l êñAXïÀwG\o£Æe³F›Ëq„d Ù´=§D1Ș¤ÓvÂnÆD]½¶¶ÂxYÐoû››° Ó4C°ìÂÓ9ŒW¨dP,G:·)ü·Þ5³íxá‰ù˜-å
+.¢½1Ë©”ûгeÅɹçÐY¤S éôë6$sH}VoA'.âL
+ôªª5ºæ¸:”N§âü±)ƒ{+c¦0W)×= MN‘e‡QØ!Ð/<šWo쪚¦“ ^±?õõl. 7°1´íå
+"!ƒµ–èíºQAcýÁ†aVë0.ÄÄÓÊÉìA!3 eå¾)DCHK¼ !} Iÿ×l!…êqNiLú
+i!Ô
+êòLH´S‚²ÃƒPæ¹i*ƒÊÐÁ Œ72¤ÙÏ}&¬#ÛmÃÚy
+ÙN¥pA\èŽ`0³F/„l!šƒd-Ú¾+3‡H>Z¨¿ùA‚§¹–T´"ð±&Úf^{Ý×a}I|¡ä¸ªÀ»bž„¼åì)Dû m+⤂Œ#H\-ÚŒ0û€¥v)qÔÉ®"`øƒà>&ð  
+šÅŽIÌPo!1rÛx@~È+ Î\[blôÚÕZ²qYúšëR8š‚m
+zfœ‹©
+‰j²Ó:Þ!Õ ¹Cªt‡T]¸ëë²£1y”ª‡ƒƒ|¡ŸÃ§T¥O6 ñõ±ôëN©ªÚ”á#‡Å£KG*OJUO$‰‡Ä]ÚUgñ_ì쨇x”ª%çøÞQvÈI©êtú•lñ¨æAªÆ…(Ÿ´Fñ Õº;¤~;š¶$¨3ô9)/c‹
+“q€ϵ Ï sqtüÝÀÜý8dh<pf ñ>õ}Po×PjçóEõBg3ç én~§¼Ð!ÂìjÔ\XÈ’‡¾BÐmý*Â_{aK†¢J˜Vªñ'Qˆ,Ðâ{ÕònÌJ—QxSŽUÔœ ”]xdºœf’4hØ:Ï YŸR2¸Y
+ðâ°„(#q_i“‡ç(*¾BŒÈÀ2’Kî!Ép·K\³ö¹îb&
+×lIŠF@ãêúÓU€K2‘ÜÁ"w9áýŸÏýÅ€Ê<°ÄHßhÙµ‘„Ô¥š)°x÷ÑCS½Ê]
+–ü0÷mÄÃ*0¼P÷§˜EÊ\?ÆO0ˆˆ£ë&;‚q”‚¯Ñ;ȔȆÚÌü"ä©Cÿr‚¼^¶scn§ÅýEÐ1}Þç~tÓw´îA
+¼)„™XãÎg‰1k Y†aH5¤ýÚ;•…K3¢É6>ÛÒHî¼Dᙿ 1~cþã¼f™_`f«þµF”x’KrBô¥É¼ÈÄe6ÂcȞσL4˜˜Å©ºLÐFnxb­HŸO¬FôÛè Jú6†éÃþ~$ÏÙ°žl§m«èrúZÏ´ò+›$‹qÝ8×¢}Sƒã½ü²rüœ@ï˜[ÔÓ °¼
+]P¼j
+‰Ùüfq[¸ªùÜ"bVeBƒrY§ÜK@œ# N¢4·÷øb—Ì6¹¢Ÿtñƒˆ»<üä¾úç â3FÀ6䩘<!§Bè~Ãú4«5¦ŒÄh"²$–_nÓà ?À×õºyœ¤¾ Uwªå2Ë¢Æ6Uw£‡²]¦†ù•Ã“G»«ãI,&'v‰‡ÍÖ…´á¤}@áy݆2X\Ñky½
+´œ ¼lÔ‹–o(ðÈH[+,Q ,£ øi›ÖÆÜ×ÜûÙà ö^áK´ Ô‘üýi÷‹L}‡‡´J¢­â. u7æY gcª¨†·9Í[«Ö¸<8œ[ox¦-ø2‹%ÊX¨Ã¡ËLl¡CKûà ÞB:µËaˆÒÊïA~öÍ ˆcDBQ –Ý oÀ?…$Îý¥¯Gë¿­ŠãÞøÒ—­vÝT ÒãE6… 8Ì,IBI‡DíÞÉObèZö9ƒ—‚7Ì¢$yKŒœ#7 ¥…¦ ìì0ÓV3nOH—’®sÔÌpä>·Ï« *Á1õi…€8Qˆ—jhK¦F‰`5› ¬ŒªÎÄi©;A^!ü/KAð.Ÿ+(Ó¥¦y_‘,™è¾)•§Y²&“HÓ*ˆ=m
+©l Ö[€VKñtìÃ*Af@š@³î$—1€K¥:Ú)쳌ˆ csKõmÉ?$ZFýºzР¬dìKÊò 5î
+H‰”—Ar9DOÐwÐæ$±ö,u GÌJ¾ÿvHVǸŠ¬îÞXvªH‰ÌDýø—š¼j‹^£¨•Ò>>ÿ*½¾|ˆ›ÕR¢.Œû(@iÝ?¾Î˜ ñ24ÚGš÷Ök×àˉ(/“ZúèU«.È(Þù¯jcAj ®R‡ŒÖ?~΃bæM$¦¤Ú¨­òiÑ.ݹJ« Ò{·V‚ä3 qiZêhuÄ8@ò$u)#8Ç”Jœ¿ÃíÅEjõ~}§rõ¨î¤½D¥Gójüî¾p¯£˜PCžGµWiÃ¥öè¶åAµx®Pèù ^ªnåªÍ¾l¼²-çŽ)´ßmªbÞ£¶¦?æI½‹÷^iSì6€æ­Ífò¥Q=ʨœ¯ ÒW±ÞšD+Ãc=Ëkã—ÿÙ‚¥áÑ!]m§rV“>x› ?þú‡•—´>¤šÅ¬²ŽWãß¡Žyÿø51¦B©£jeŒòP=ùzªZùªŽ±»D¥™Ö6F›TZ¡4BùÉ;$[¡¯®#óÒÄŽß±—P85þ¾2Õ jo¶ §Ý¡% ‰W£›fÉöá³Ò¦=¶áuŸ¾j*õï‚ò8z.J¤×ÙÕˆÕÞ¤xÞ)!F‰ù瀠º ¥@¸0"&DGðµûz|Ð_g֨Ѯ! £íÁ´/ÌàÔÂàÑxÓ hªŒy0@ev”ö:ŸfNçpÝ!?'3šsÆ'F/o¾ƒ ` Ïn× °>ï´ °Ûè®Àž}T¸4Ex¶î£¸+ôÂhìâHk%GBèíüN©‰hÞªÛ‚(¡†jhæÇî1™ }(:•øq‰SËÑiEA}çÛ mÐZ Ü¡÷çi
+&¸$,+1dk]u ÈZægè ^°ÏزÊ©¨L@
+KB*óhí†H1h éivv Pë‚rN×èkxO7„ÞµožäU-Ð%Žuñ#Ú¯ç‡GÞ/eLÝ®Ä3ѬÂ8!Å?çI(STg¬ƒà?0ré/³~óIÝÛ8É÷¡™7HÔ_äÍ\øü™NÉQÒÞy]^2¼YÚµ·2! eb\µnF ?3 ¬ó¤öBK¨#\çôeÇQŒ!“Ó$
+‡-ØX¨GòÇÔ‚„\ÅQ`˜Í<ø ¦> v¶òaŒQW¼n࿺ns»pj
+žŠìhªîéáw#Y%¾pzbFÇ-çóÙ…‡e=›y°¾»™êЫÚßX0aË×ø2"É͸Ÿ¯yQR^ÃHlìË@VkÉNç•‹Ÿ<É©Ÿ¦pŸ â9,SJùfň€‡¡»»ÞšÌÛø¬q>Ki*±uÛ¸œ²GQfé|ÉÖĤ5’½"ìt‘‡&=q–¿‚JHì¶+ƒÕP¬QëüŠ§}1¹‘¦¼
+õ _Ñë›nþYG ¤ÂîÖãwà ñ²:2O„½Ú`h(ç>’æd$kå—¶éQˆ*-Ýe V&mÔ«W|VͨŽõ-¸&¡“íb—Ï=)2O÷“R
+«y‰1-–]+Ykä"r
+‘.å: s'§è·åŽ¤¶ŠØeŽ‹ÌÄŠ”©r„lŽQ åíøD›Î’œ*WØÌ®,c™cÇ„8¬á•Eìb:%§.D6ʾ‚1iç8x\$¥6>Òó£ÎïDÔIýíêfšc¤%''·‚Û žíñ…®Y zÄV‹h"áBwßBð±:(ÓrJ×aŒ<ܦqÛ®²àé{-1WPÁ-ˆ(ˆÞØö€Õç<§Eíe÷‰ù_{ýúŽf<m%Æäz›¦® b” @Ó©:J(Î%ÚTJžUS¨½è?
+F½I&Ð*‚¹:ÚÕv„)ÝŸû!vÜ‚\Éý÷pENÈ´¹bó×:)…‡@ôŠåï0D!ƒHA¬JôœÿÉÁGî{ÄS«Nã0E5Ж°+¨XšÚÈßôu˜¦aÅÄ’zLD'ë“y
+M?g7¡:ÛQ„htü­¡Ó #Ø^cA¼£¢eNBø@ϲî(£Ÿ;‚Ó!îë¨Üp)"ãsÕ‡„ÊNË’È0Íï`÷Ìlú†Ûµg)¢,¼%ì ä±=@'²KŠÆî'þn"N ÇüŽûè& §áºc¦¸x$;‡ AÏêr
+ü:óg"4جJä&#,ÎHµTcÍ
+c]wÉPëÈ?Ê-‰à)bÄ?¢Gë¨{qRÖô þv›¤ŸyeÍ»¤L%=ö½(êñª 1Q‘ÂÜch
+0`LCôrª£ñÖ<–+LÁ¿bŸá`‚\=æý Â@=ÔÙ ŽÔ²ç˾.æÀaËhì*’¤+“µuá D0œª€°YŠnL$E„·J LEX1ôæ¨$«ÆFí\zÖ<ÖsTkðFžPåÂN—ƒžlm.®¼v5¡9czÌ»úÌŒÑ/EŸ+'Šd~ëoA)r—úò\3¯6Žò‰G°øÄÕ
+~rÞØÉÌ»5¸i– Œ‘›bO1¸×÷Ä‚ óä‚~¶œ»M¬#_/%ô?Ú']k0rvH–ì3¹' ÌvI©B#7žVÒ
+¢l
+‰Q’¯C8’uP 6}Îß!Uƒ1ï»$ȃ'øë.0SÂ7ÙjêMøL Œ³.,&^„õ5RWgпBX9-Ü°¸À*Ó ”඲ÖEÂ÷P®¦2”H˜ Åà!€bÂtŠ¾Š`uÑ­«.¨óâÂ.¢çY $G˜|]¹p;Ëv/ -¨cÔgS½U„èR7‹)ª.Èž¥Ýb!sŠêËé ¸âº•dý‚QéÏõƒŒ¼×qòÍ"Š!}mÉ"AŠ^¢Àiœà¤´màô–8hh-ñß­9›faÐÈväì~a ½t2²/e_XÈ/è@hÃJ*.$iÈ*©ä
+¶¿ê×û(ºÆ¿ðÊyšuHëg±ïp¨ú0¡”³tˆâúgK«„^Ö¬ªåÄäúH/››(.EæƒðõÌ;p/"ô$–¦iCí0„Žó¡Ñy¬Û¤]Ò¼&Q”wEÈYo%Ö´Õ#É£ÔÛ}Ü¢K ùQ€ÿ¸RÃÇñ‰×x„ðmEŽëˆ„]Bðò
+—Ã[{-ð±Q”³¹Tƒýœ¦„u¯)Æ÷9Dš,^ ´à yÙŒ@›)!4ò;ûÚ)Uö]ý‘«0<L{• Eø
+Þ ­Q¤0G%ð³%É2òÁ‹„ÜLvûËF1F,ë[7ò‡"V—nGûŽŒ*NÚL‘;­§þÇËQJ;Ø
+Úºci¾mjSW’› ÅO·š`$—Ê„ 90Ùñ±0”!ª¤TÒNtüAÕÖÀ 4rÒ47ö»Ûe\lZàtèuÚž±ž˜]MÃ)áz|³àe´„·<“ðú­Y,¹y` Øj,çL‡‰jl1·èÂË#3àä0{røl½ü
+jȳƒ(’ŠyI›WÉiÕ§`oô7*Š3»2°sþwDM1 äŠX™Žö
+¥,ò$[ሢ7î‡ûþ²Õià.tê¦9ãB†œ«‰Ð[Åü>íƒNŒ¹™ï¡DÂsƒ°¸F%j™ÂÅØÛ~/¡ÿ8¤“ÙضßZüjš!:ÑÝ¢¯h²é¡Fl@³Y5ÄŸV
+ÒÂë ƒËüD; 1I´p-öKCúà–,pØÌ!ÔŽWà2e—ôn$‚Ù7@2À²Ií@vJ,è×…¸êôŠ 9¼Iù¡;%EÙ5Z™ *䑸w¢dûÂJ’„dn\Ħ%bÑÚÎ.ŠQälžŠ±è@ˆ¨}¿Š¾ SYšÛ=ªÇ„^.¿…R72š ±¨Ÿ$i'³k›âùtãëb’C_YgŠÑçz”‹Heyl—$Ó#Ì×#
+fj1Ö¤1F!öíÞkØ 3YÂÊ©^2g‡ÜJ¨ËK\¶JhƒhûV&’âNöÛd‡³Ò”rB²ó•ÆÑÊwE¾ãò<4™³ºd--¸6¼÷‰³:%: ë¾ p,üãw¢90V#¶d/†Pƒ/ÊJØôQe—Û‡R`Ç VÁߊ<‘jj¦ËFð·ÃD˜³ÓuÑ·ue¶§3[èx²´Ú…y=¸
+ˆŽ¡ž­€hXáû$ÉðԖβ¹'éßk¼ó›?"‚ìöñP;éìVœû¤Ãøó¢X‡øÔrs¸÷Û-Š|Ž†‰kÙ´=˜ÇÄÆ·´[Í» “^”{í棧
+9g.OD xCwƒx•`*‹BÂÌ}•à·GãßÍfþ²£RÚa“QŒKT4€ëÅ—°å™äS¡ùÌc$Jô|pŒÃ­«ÿ HÛxËpJ8Š"˜NТãÃwø] ©=ÝŽ‡‰pÔééUa>4T|B›^wTÒJ‹üej}z=vKþšÕ>êVåí 4u¼ù· D@ÌfGîÍyUS×Ùí¦ô¸Oº6§9fsƾ®“®-¦„p@t”1º£º”¬£®#¿~ÇÎõ6
+œÜqú¼¡Q„1pÉ(R}ÐÄ{‘”iG8¢Y~¼w-úzåNÆãÛ‘Ø…º-,\Žg,R&]}Д ä{~ZQÇ/D+Ž‡"l,éÅ`‚Ïf*ÂÆ ¿MâàG›°ëü\¶ªq|ìh/¥VTqÍì(àAªXvìNÃæ„ñÀç¹ð+¥5FÍùáqE‰F–Š>„ôPTar ¿¡Ûd…’š|
+Êé£¿Ô ÍÃÉcPŠ{|†Ur>Ù6Äw9†u™Ágaÿ™zKÈ: Îv} ‘*/¾3¹— ’ç).ûÊôâÒ Ap÷²Öæç¿€Vdy*@&M;ƒ$ãJÇ*:4:ånKý–RTŠEHáâWÈz9½#HföÆË‹ïp³š1Ü,ÕN;¨qéhiÇè )†$ã{ï Ö©8gO¾ßÞHLxvö¾±0ŒuŠþB‚G>SÔ;‚””;âÓˆþóãs›uƒ©H¤/^ð7 §ý»œö5残õ
+vùùïx)5¨jR¸t›é?R`’†@Û×™RM „Æ´™þÿÀ
+"çÄ•hÑn‰¼²[
+ƒ „8‰žöujÒK&éb"ø¦ÁˆìÕp¢dJ0¢ÜáˆÔ›sÝÇÎ>cŒaí0½cx¦J­ ó²*:0ýóä—Ûµ¹ýàFó‚{€žæùŠ[Sqˆ¢0ºçIShZZˆÊ?7¾bÐ_ó<OzM›,ØIÅ´eG×byˆw¨`[Š”äÓL˃°’¨[ÆžÎQO ’­\ãcm}Ç;G#sÉ7ÝJü7© œŸªæ»M”ÓË¢t»øƒ†}¬l¦áÿ})ú(¨;/x1y_L°Ì Å°O˜d°J“*‡~ ¡@ €•¶@ˆOa {¥
+k¾¦ì +ME6Ged=Ý-ˆ@Ö!ý|=e’ÇvŠLIÀŒí¨à» !¾¦‡’d»1"õFª*€ÉÜÃ5Õ^stƒï²YÔ*_¿Óã(‚ŠÍìÇ–¹Q&]ÌÕE*¹ÍùÁÍ,'3Aåœd1¢Mvf÷ƒÔG—øó®\P5cäÛÅ©N ǨÊV/ ÔŸÐaØšÓgŒÉìâ¬xbW˜Ðe&Üâ觽æp"‹'õ-3 …?òÑ,™YëúwlW>+A|C63—ËÖή4‡²jEcÏ
+È1ôæ}A8º'Òö‘V3ÉGÐAÓñ ¹Ó#æ×ãYs↛™ž0IŠjòóÑD–Ë’¥±ocd<™vtq-[À¨“daö¥HèòìòIneO1ç
+™›Ç2/ õccÖÃkiP/<ÙÚV¶ÞdÛØþBcðs¢,Ú²Ž‚:@ºûá­¾c´Œ±
+ù\ŸUy4”»8Í„ó¤«m‡†I4 ÜA㬋l Ÿàݧ6¬‡c•òšfZ ÍTÛ.0#T´-Ò½¶ç/ -ú͈F:ƒ\S°ÿ#èý^áj±ßú7ø¬íg± LrR¨ˆ¨™X½8•õô"GøB{ÔèLIúWcE—MÆd—Scæ¤î§8#ÍbÑöà°fø¼.wØýÉNƒMü¤·†Aàzs¬`&ܱ!:éËڜƗyŠZ/ʹȸ¬)4ïÓºÖ¢ëûÝÒmÌ|a(G@r—ï‚ÎæÜ%®ôE¥3q«8%÷XeæpÏ(µ©rò‚4¸†Màb§›’Æ9•[^ñ'gìn2³1Èì[£ó
++Äi74¶xà"ôdÖ¦iK×a¬ž„mÛ
+Ï.a¦ ÒEA°×ôc6m›{ª “šu¥¡uŸ è!|-ÂaN³¿/@Ö:µõ=†/V "®¡ÕŽûRshÑÊuc&ÄCt iµ3¬w´ºÊÊ'rz1AõMíÂhIî“ØÃ.û*ÙØFËé9•9‘ÞVïiYÊhe.˜Lf3Êøz®îã2b6/·ðwé8©¥d š†Ü@…dÚ™šª; Rpc„·M?È‚2—8; Xƒ)7#ßôƒp1ϼìÔfħñ¿n»§C.¡Á\%ÜÜ­³A–%JÁS2ÓxÑ“’>!~Ç`´Œ”z°õÅg<Ü2ŽåÚ—au
+\Õ‹ À¨ä³Ÿ„ʺ„lμO"Ž±M,t9¥1h_‚‘ôø ’:;$€E­G)@$îWëzöã´Ïdî–¹ÁZ÷'ЭåñÀ×Á+˜“ñ]3Ç ‘§ZDÖË@ïßYÓµÍøD†$?ÖK ýsð`=T¶h-î”ߤó$Û,Âý Ð'™ûu?íKÌcŽ|¿c\fœÙƒqÕ[øBÂû•7»Öʺ!—mb (.ëÆÂä•ŠÆ‚áF1hDDXy‹m‡ÇÆ"÷°“‚d|≛ùš–pý`ݪQ.¿@ÖQÐ%©‘uX«qûNee%šÂêLí\
+UyjCÄ;Y#¯3ý ºH÷éd^Š<¦^dS‡ô¼®Ãp¬pïNåo­Šœ?ñÅoIJ/G÷X^Š“øô=nEÕ'=G ­ž˜„ÉûÎP…õ™““ðálIõÄw×Q.Ebæ…Ý,ñ)¡=é9¾SàI<C{r¾ÉÅIu–O3úÏ è6ì Ÿ {‘þô´·ã¾z „Ûr=b‚\~þûƒÄÀÔà!g~ L"/N¹MÂ];¼ð9=
+Á‡­^Ìíï8
+gÃðmé„•Ïâ Dã‚u}îÚ­¯šþãa{<04I\ _Öz´É<Š}æu÷£gÖ1¸Í&+.ˆGè$‚±ˆqÖ^}ó+OP Á§>©REè‹-¢‡ïU#:¤þ‚†+6ê=›E9nÃp+ÄÞ ΕÙm.¯ .9±Èô‚½{¿ž'‘ÓäAìÈÏnªÌ¡9Os½œ©"&M;Îíÿ¹gíÅãDcØù&¶‘f£ &ÓHý(þÍhßúþè×Á`XQÝÀîŸa)Ð#&6锆åˆ<ce¡î¶òv$;˺îïØ­ZÔ=»å‹M„¹¢Ûp) ¿7+&ØrZêb0Ï €®N‰V¦ÆbìM†PþŽö0)xõ¹ÂßaD$'ª[tp‘ëDh¼£E«°+üF϶öcÿ†ÂL^ˆ††x±B88 u%)~ßú
+ @’Zætdn tN ù›è8Ü9´hœtlKgëPbµ' ²"S.5~„¬©à'Ël[õhãÎìpü1?\…(CDª‹âXŸ,ƒ¿s.–A*Š¶6÷XìxÒ-ïÛö6 Æ6õè9«hS¤Çé»:èv‡ØÎ~›@Õ8gêI!œÁàÏƯ8v1cïâïH”pSn›‘4ÂàTV™‹Ýµ XŸ¾}è~E¤¢Ü” 'Sf§i\ÀŸ‚`4¢gß Â)õª(¯!„öxLå’ý½£µ,3Ízüÿ]aWµ)·M‡ƒ‘+µ˜_06‰$ìa6ìF+‚Ô 36(ÅΕÝDìL 6 #Ãñ4•7Ñ"QåƯß!¢uIÞXsy»MAiùbže'ÏË£œ½6kÔN¬zýŒ/n׈ÍÓLRgÞù}_OY…ï[ šs!7†ð t ž€òœ8^Ù¥Å)ßqƒÁ<±%ZÛ÷ Bo0ÐÍ׃ànÙ¾!üÈàp )1”I1˜Œ²‹ e¸Ð\»JHh¯ˆ-ˆÃñ„… ÀYCO@”÷àžviº -Ü”)â•—sÁPËò™:^|G&Á“±Þû3A·P^í?ÊË$KŽ ¢'àú|˜‡5·u n“÷ßê›ÈfFx¾JJ ±JÆ
+¬+¶æâòZίºœ }˜åcŽƒMsVÆ" DÚÄgA»ð¯];Î’„œ5v«¬œÅŠ9×7ÝRÒby#ãw+¢áAb2zËÓõˆ*gù‘‰“'h$ Ü Áj5¼a¼ò„Ÿ©öB~)Û›º2óãú~殀fåˆH‡C=j‰gÈe 7CL,PA a®; ÂÂ6%˜žmxðÔÖѾAÝ+̤mÜ¢K
+'ɼÄv¥³°!&ÄdQžW؆¦µAUvÀ”„dØO(Qqñ$4
+ç)1uâRÓôõTÚ”å@`«Ç2‡YÓ%E`ö‹ Çqøè`Þb1.ƒˆ-IJ3™[i7½ Ä!ŸAÎS„5ãÓB ¥ *ÊÎì·ƒŸCò)Ê*ƒÌ´fA¦­ ivî±9Õ ¶ié2 éÍwÚGèÀG¤}ôOñpµA˜ì¹õxµ)_Ƨðþge(:Î;Ìpœ9ØdŠÅƒ3ÑlõUQ6JýÞ@!.?ãѬåÍF‡¢28±9 ÇÔ.ÎÕnÕ5í,ô¬cŠÔŽ#æ7ÆÆ'ÍȲˆ·£æ9kÒ©zö—Ø‹å£8ŠŸ+Sà,‹fXŒ ðÿй:w5šhë”Ffs ßN~å OÈUßf÷’Ó?)©)ä¯-iìšibmn
+.DA¹» bFp§âçÖÖa7s6WÎÁ̚˹%r”$¸´…Í¢ÿ¡÷÷uÐßÒúøDÍ›Å-Ʋ˜et쟅Á"eÎj5y•~hˆš0úQvèõfsx\ÙÓ,óœþˆx43¶#ÁÿùÍŒUžmQ.+sÿNÅ°1ÍU„Ò6„»rYø•m[F‰QÆ[„椤_?“
+êÝI'ø# GF"dL&¦cYÁÝcŽîÑDÓ @$²?ÃbŠ‰"A½p á'AVÓR™4.ˆiž]ZB}Õø;è6ŠºqÔËø³
+9‡ÂÃá[½œiZ°Yн¦-Æm¤/‚©>@Ú1Q`HÍSC¿õÁÔ”Q­uB宪N-
+JÇL£ GSù.û/&Ñ"Õ*E]âo•ÍÀâVÁ¨p_1pà TJâ™Ñ¡iAàb|„ÀÛönÙèÀÁÍ ^M¶Jb¸Õ*ËÔ\ ã_Bý‰=üZ¦ýË+ñ§ „ Bs";#4Y!ÎJ©Z¢
+Á­ª¢{QÏ؇ìD2HM]Y…ÐÏ$+£1çp{ëk,¢Òƒ
+¸$#Ê‚Dùv͆>Ãhê øÊpöŠK±Ÿlä«n&6ªà¶
+ƒ+•Hž¹¶£2é•ÑÑg<ã "%M7Þ£|óÌeŸ‰¢¹ùΙ)E¨¢V›;ì8g $Æ…È;1\œ³7ë7ç쀜Ž“ØlH&A—ÁwÎ(5†pà.&Ë„Ð}¹ûw=>YRùë™`Ä~"Ì,ÛÜa ¾”‹ˆ­i—ÐÍ«ÏLYPļ¯>Ç ü†ñ#‘
+ãö=N¤”|‚ª¸ $—Yƒí “ÿd¨Lš¸z¸µÖŒ9êü† ¢½Áé)[ ²&‚áJ5 5@¶;ºÖ6CóìÀlɯé+s4ékÄVÝÁ[A’hwÉ,s YcÕžùñ[DÉj
+œß’ÿjN¼a$J5+w‹{„PJeìž&úŽ¹ÌêC쎠{ê3“èÙQZ13ÿó@^4‡Â «-Ó
+‹gßqéÑS¢‡Ð¢ççRÃÛ*AºÅž÷÷áRŒ¢‡Anë.i]Æ1 }@\
+ÚÜj?d_ö㱤üŠ_ô_OKöÛ·ç¢ ¹™†!*z€aÇΈ_(Q<ÇšøIp@á/ÇÈÐÎ{´ã^-XXYP믗3®Ü¾õæwÁ0s°YNòÿ‰BäA±¥e³òÏ£ÿ¡ä™)$®–uùdªÎwobµ‰K»ÓQc¡JDlp>m•3=똇$=ú±,¹ïŸáD6|ãم̺÷‡ ª¤&?ôÚ ªÜ«5 #enK%He<â»~*¤rÖÑòß¾=—èÿna¤^ýÚâŸ-u«ù‡èÖ E6@v¬4a BoÑÅë>%¾;ˆu¿”’têlAÿ§Êù —ÁGlÒÅ•¦¬ÉFÌûíJ—°9ÇT¤¨Õå;ÒÀ«]Qï)9³:sú¥õ¡dÀ=t°³èÚÓ9ãÛ¦»°)ëgÀr_ï ˆáA(ç~c»Ö‡ÔŠ.–óúÔÊÃí¡uKãpz…—ëø”íA 8ëø,ÑÛðÃu›W¦ÇK4jOF\&2(i_ˆ¯=¾AïR.ú²ZX­NújÔ7ŒiµÇ»Äž^á€SÙžHðŸÉ4¼{Ht R³ d=&xt†]Ý#úáÜÇ"óe¿ö’~¤DJ[7¿Z–!\sgxWüÐm’X.ضOc\ p¼õŒrgÂc]º5él“ iKŒ'?sßnäCÃ/hØ@š ‰¬|5&t13ú4e4xgH>5¸ÜÉ&hí*âõÈ:—4Ñ+p˜¿LÊ’”@GÙS¢Y&ÓšpU&åBºâ÷á.ŸJKý/[ÙgQžnéŒ_sJ41z…¬5qj61*`!l)Ù¶£{=âÅ/™=®±Ç7WžP2Œ%çÄwà nç„ÆmÓŽ5®Û<”x³í¹ÒÇCÑtüŸ:i^™³A‡¾~éÈóRãc$RB•Éâr¬³„ßá8„TrÊŒ= àÐÁxÕfÄÇÖ8‚·fktÏ_H¥^%@7åæ1+ñöE2Úyâ­­%€x>_Ôöçsô¶dþ:\ú¼M¥`x†c8R"UP¨Jl·ÛÇImq`û%}ÍV/:®ïWQ•hàÑÉ>J4—.êªÞßîûléNõK=%Ô•3}d@¦Âð@LÒõ¥õÍ€mQÖ樨ڙ4W3ªö+ÕÛî‰ç Rë‚Bz}W¨{5@چߞ¸âµèû›"öz8õ’³ÓÁsMo°2H†²$à2ø=»ÑÙ/ÈÉCçæùŽ9Í<\$Ýâof‹×±s>¶ï›Tk‡v²U$é!_¤ÜÛ#n^JDÁ÷¡‚Ò×ýéå:ÉBdsTDЛ³ÁÁMÛÈÂ/ñáÏÃLn”EÑ3á+ÁÐÓYãcf†V×þ4UÝímoJ~ãSEiŸlѾq›Ø)ƒ¡v[r[âʵ™Y¯Ï˜†;̙ۻ]ÖÖ¯/}Y_ä&p;þã>uØ‚øÍÄ·çj;ƒš}»°ä¾|LKl,3>a„)ŒÔŽ ˆ0tÎ7a‡hW/émlža†UûÌ„áS¥a3ÓÂÈÖg:EˆÅi¨}®•LNÙϦ˜aÇØË^â,ìÔåG:ÜNã8¸CÇc=VäC;ÿÒ¡ëúÐk åâõÒæIãñÑmâï°ÔmÝ΃ªjù1Ö{éñ×]‘íU’îÚ&ã>ö«y‰H¡^LP¦ó@¦¡¼eèóªÁlqëç“óÈFA)´©\èCɵQ"\Ëà݇sbQÍp¶hò¼Í*Ùïmàzôšm]ʧ›*€cÓ„¹©Ï|e9(S½íÝ×VÂSŸ½[ÃtÙfÿÄ+ ­^º
+ÏHÙ–6K%if¦x"_Ù`Úo—ÈVphÃkòDFà¹J(MÞC÷å±ÄýÒláKôq¬Õ ÐRŠ¾?ùO™$äìq­á€N ‰K[âgxéa]ü{ؤEpAªÜyÛc(¦6årÙZÁiɽlOnkXñZb"öí£²Æ´&:Qïx±³_[¶n¡
+Ù<†÷P’–^œ•ØGɆwbŽ»¢'Àå¡Ñƒ?Ç—ì¡ÇeÀƒ›QAûEí’:G‰
+÷nËRí¨÷9¼_:Øâ…RÂK'€øÒ¼LX
+NåúgÆÊûgY‡’ëK¨I[˜û|sf×u]DŸ³$õäЭ¯I-;:Ó¨»o£3ÇH EÂœPµô¾ÌûH·Ãg‰•ã˜ÒJ>‡ÞgRaäÆ0WÉÆ7wÐœ· Q´Êa÷—¨mÒ„ß¹#_¹c~^Ýó£ïDîgSésÕ æcT ±ò%D>_½%Khw‹ ^*¡-ërãÜlW*¼ *%#ÚѣΠ7ë!c– ‰××+aÕ†l¯§¢w3|Ñ¢Ô¬§ ”‘™~ªFíÂ’îÅü~S”´˜”ŠúÛÇsÉ â#¾ú¨ïJ^øµˆbò+'¶(Ûã9â# ÿzQÞ•ì1(þ){ÿ)©ï8^!vžcº+ŒÕU"û@*bì³D?—Xç½W‰'XiÍpoŠo¼À¼,Û»s¸jÖâjS⯱$2iç2€N–ÃfñÊ×î½}SÄŸä]‡üt~¼)á lß–ˆkQ ]Χ-ÂÐ=GI{Ç›sÐKO¤<%Å7%n¡ ‰hÇùù©¤ÊF•×þ0õ±6€ùÇöLìt«W¶£oJ¼'šÛ«FÞ›þµhM€tßóØÏ iË´ ów% ²9;^¼7¯ö ©¢Õ‡¢KamZ†Œåê} ÃA!žíâ8' ™F5ö‰åìªKž±h<€Ý›…ãœk`:Ù´Û}OÐ’‰Â=•÷›ÿ5ªï CëÅÊ*ˆ.ûnK/eÌG$ˆÆ]±P8VEü8n1Â\
+í›5,¢$Ôúµ3
+¶ ¨-ÅäÛìŒ`ÚìïE:TÏŤù\ÃË:Üúš­¦ÍË<¦¯K¤àÖëKR)ÀûyCh:œ­{µ8?\_9ò÷u]ÜÎX ‘ÐÓ*!£ÝwõAÏÅTÿg¼Lr#Íq(|‚¼ƒO`ˆšµ®ZÖ-èUÖý·ý=Š2(‹„fh"ß´¼êrÛŠiئ}Ë)pCòC6’ZàF@w/E <G[iÛi"j¢y
+h‰¹b>Ê;ÀgòqÖ÷aø#V|(ÌÍ‚@âÙ$ßé°âÄNñ¸\+íuh*¬=±¥õÌf“bLSûw Å0D'-¹£O ®ÇVRp 3–yM”·–æuåX‡Ö1óCÉ‹Ëüë×­èÝÖÑoÎCBXظKt»×\¢Û­èÝT‚l@~s@õˆn” ç}ˆ¦Ï*oÙ" _i2ù×ìF /«èÃ#'‘!0Ò´{tã- iÙªöSóšÜ¨`]¾Uœ oÉí¢é)g•·äÀe|>$úšÜ(©²Vó™®GâjÞpé`ɹ~0Îï„tYGq4ã»N†y‰e^BÒ,0 |—"º ˜(û᾿ÍqÛY.(ÕÖ™šªÍéÝ°k e̺
+ ó
+þÍê%’‚ Œ¶bä¹ wÌ2^5¶ÒdcÕ!žzZÅùàeÌóš¾Nž²¦èXH,SÁP
+|*ÞK¸·z/Ú‡S´(_·ÃTèÊ\ü`¤v½Î4 ‘ŠGçýžÓ<ï‚ëå†ÚŸKˆ%E±7I8íÓ¬¹ÁÂP=JöT`p2Ü1H뺎É
+˼$+ô4½SH’¬=b+lÎ$k%ÛEÐ ¹ˆï¶Íÿ
+
+&'ÙZ€ æGrpjÖö¤
+7¦w.%&Œ5FÁy²j>¤,uf1y÷P.‚ˆÞ£å±É]d€õº²@„"’XšWü=J‚*¡h-Ú¶µº,W𚘑Þíz˜äf‹†&àÃ¥Ò¦à%ozäøõqlí8l¶F¾¼0â2 5üÙç½Qu¼±’†Ú¼5œ’Ê•BœÐá¦×±QIQÆò‘ó>~Éî,æv¬Vnc¬ÎÖ%@^Àp-yÒÿ¥¨pž¤1€›l/á©
+n„! ý¤ iiøpß
+wàÎsD…
+3‘Öx`zU4‡>\I.^VuåH—Š>ô7C`×ñËNÒËô#iÏ)†hm“ ožQÓΉ­L¹¬KÎ5÷{´xŒüV°‘‹¸0™ÚŸm^×h;3q¼~= øÈX½ß&sž`=íö&ƒ`'h\6ƒ½ÁWÔ$»7HäYY&uE†vk´(¸Â÷5ãwÒu\ÄöC«\ ¾ŠºG?2]·é½Ë(i ‡±=/ÏëB|ÿz¬Â æ oü$G*x0D{ñ²=˜†‘––{EÖa²ˆ¯…ú ó3‰ÈˆeÖEéqf@·F”Wô°K ƒ+ïNæ ú”»w : S‚æ¬hF‡YNPÈôˆK¶¨Wúkv“ÈÀ|fÑË^§â‡Ts• ÇŒCb‘AŒi»„‰Dxk]v´Qèú’¥[1}1:“ŽCJÁܯä¯#_©ƒ9Z‡dÙÓÔ`p%ÏkI SI}âRÄ`ÀËY§ô¯Ûi/¹„õë­Uƒ£tùÆ^Î&æ”ß¡ŒÈ1 •ÇáÝåaUB¦gø?ª¦ ê·áæN½jBùgôàƒLÑ݈­àÍ1£
+:‡Í¾ÛPOr´ñ1MdÖ.@]Öˆ®ç<óa$Åæuº!WIcÀ°Æv‡•` .\ÆF"y8«™lÃ.b¨„SÓSªdÁ}ÒA2Íy9¦‰§Oú %ó[9Š yŒuž:4Ôßj~‹‹ÕZLj;Í>n™Îîë dUzyZ=…-Ž\—J€:ZËc×tä´te“ ¢Jl¥ÇB;F#3x£ÃP´n¹,SÂ昊Îà·†
+Ì°©€>ùÒ*Ù×a8ðyœÒ¥êéñZd‚µ·¢1e_4ÙE¶öVx9Ùá„”†
+/eÛÕŽý8&=äEå‹B#YF‚8ê°%/ì µ¤å,„gxàRôûCàG¦pe‚Jcê»þ ܤ#¨d3v LS\9Šýð·É jkÐMÇŠ0n¨6úïëÐOs''ãNd1“ îÊÙK¼¡ò¼¡ï²®"„)ð¬'jÞ°³Hy÷e0v–b[,ó?ÆË$¹’¢'ðú
+à´ö¶oá­î¿öK­ÿY¶¢ÃÝ2DD±‰˜À¶KÀ8| Í‚ýo³}nJjãèXHyËpP{X B…'ô‰óaeþ{óD,é¾£ïéroXF©0?åFeZ‹©Má«g‰t QÉV$¥‚ØÜ»:©ÞX…ŽÍ«
+×Û»áö~ë]>!éñ081h›¬4‚ä+?C§ð u—tr}–Ývoñ.Avü&ÖfêU
+0;Ԣøø€ÆŽ2 ¯`ƒ
+šÃÛÏ?p:€˜½Ä¤¤è Ö`ÕÓŒ!î\‰êŒ~ümÚf'/å³ ?RQåòh7¨q¸
+°±²œ˜–å”tÅSòظ8{·K€Æ€'7y–«àÆüöà7ù .Ç✥œ˜öÖ¹É)€­7°e+òÊyÂUL¿ªB à‚žƒ¢IUüM˜<ŸŒçiV¤u/áë™ef5ݹ5·›ŒP^ò&†Ï çÆâ³ÿ²T)âˆ5á´±ÏÁF¢>üjË
+¿å é&4%dÐ.%®¿&A° ×¼"©ÇuV¶àF(¤›0jÖLÏþªðîîè))xAY»a!õ†²ˆ;úx¡N:ț윣$Éå ÁÅŽÜ«k÷ë•^È¡ÌÏ‘_AÌÏÑJU2Û(Õúñw´´BM> ü쎌×ÕΆ"úLªZÞœ"K‹’¬¼ãLÐÅÔc¡û1&‰¬³ÜG;(Êr˜svß_Þ oǪ¥qhg(aa'z\ÕåËáD8~9sá
+ØW8ÅK†‡£pÞcXºk·¸(ëµ¹r‡L™\½¿{ÎFS™©zº'Å•|S¨™ð2ó×L(Þ×Bñ32ßÍmý¿Û‘0&“½‡šúº,\[gù†L)ËÖn›õû¡è{˜ãI˜ŠÔNà¦üóš·Ë FÚ×’dÎÚ‹ò‡â! åsN`5Úë‹`GéÒQÝEo|©ùüA·ÿI¼ VáRÔ>-L+l
+Bš|g³ë'ØḞ‚Í8Ý°L'x<–\*12úU,EpƒÃ!êÕÂì1 á>˜€† |˜ýkdp ÉëÇ¿?â(°(I\Jü„ò®
+
+ΑÞº‹Tå_“:>§ é,UKh-¢ÌGù“¥&S ÅU†%$Šé®ùð*]/@ É :J J†F9%E êD½D–‹q/D&X ì/ý ü–/oÄŬí%§X Û·¯.rç¦WUZ¨m;Îé¤ôÎÆ;ý ¶XñùPòÕ%Ê)€Ö°ÕìVÉÜ <Y+!
+™¿ˆ¼ÈC“Ýf*ø‡R"mìŸ4;RíI’5b €G½¶±|LcÆœÝÁïC úÝ3Yê ¥¹a£¡1\ÚÃPY
+X
+U#¡¦è½ÅõZ*!â³HÒYc ëíÇí°™lîQ3¾C)ŠÓ}ÎZiú&£OEâ×^bv¹
+¡ž–5r–Å#Œñ¸qJúBd°/!F(äc0»…aT6s
+ÙäwŒ Ñæ7–º¿ÏAv IÊÚ9vHFúÜO —P>¨Y—t{®J?N¸¨V~µPYtŸ“6YQö•òx ¢ë"é«øÁÂ7!ïR¢«´“ 'J{^×s¤
+ ¬Eñ¼Ä.<*™à”à,³máZ3—0‘ͯ’çSÄŒì‘M_Ç@ó¹g§Ã¹8¢úÀ!Ú‘äs §¤B0Ø rVŒ;ú„û°÷ ©Å
+ $˜b8ž °ãyaÄêó§ð¦81MXkë„›³ ’#1uŒÿÅ<Y@ä5óE´MÈ“]X¥ÉŸ:€*-ÇjžÎÓÿS×Ègû` ºd—Db'bÿý
+‰âu!F]D°eìÄDÅ«ŽjþÃ9lÒèû´·`ùÑ\ îþŒÝ uhãÐtG¨æÈÎ,[…• •>Ê|€ð\>®Š:¾¾tqY6lš õ"ÊÆpRŸŒ ~‚tˆÅ±‚ŸŒ~™HÁÀ#§Èû‰—z!ªyo û2û€wzPbÚD Q<VÁ0ÝÚa± °ƫD‘]¤›MSºÉtH^‡JUÖ€ m“¿|>,Œ‹¬a‡`/6I©É冖%6°‚€Fñˆ4¶<˜XU÷âQØ2.F.{;©[’Ñêd‘½3ü™¨9été$×€=ê¶ffÈå•™lDD{-ÖJ/ÔÔžv…+”nC”Uñx«x7‹óö»…?ps岧#úe,šÃ ö]±3<™™™X„^-lÓÄ(TE™QÝÉò(‹õðRØ=½¨u/ºEòÓ&,c_ueýð0€P¼ ¾b·é„âÙθ„ËÑÅ0Pî·¦Hž‘‚ð¢K<gk]Çd1øÂyÄÜÑcéÈtn½ÐH
+ýÍm³ÄÅ\²?î]웟=dÚ& v ›‚¹Ãx8„Èד&ÁqˆÌi¬j|H<³T°}:¯a‚ˆ_cSóbuÊ^[;NUî!‘¡˜Çq®Ì€W ÷î7Uã™Èm~]G¶Ÿ‡‡Ly#ÏÄŠ²§¥&ËàÓ&Lñì<†KV¸a{%?ÎP«9ÇjÛßàOÕc¢á’sYLÈtSÃÛ‹õ@SΊù£êb!Èiù¾k†w`vMÍføLÙ
+ ä,ó…)€ZÂüÈŽÑ'–®Ç§
+»4°DI-9e
+ v 9;ç`[GêkaÆäÍdþüqÝ]éß2‰Š!õÜñ7˜Cp;>’›ÉA/ïØià#¹Ážqaædç¿[rDz èrrjÇäfNH<UUfà/'„ßçCr3]&ÄÏ0!Çä$‹!!þŠeïÉÍ$$USL2kÉ øÙ*MÎÇà‚Êao0*}ó¸ y䨠@ÎùNI‡s´XŒ© zHe‹Aq10r¦ññî,.„œiËf¿O.¾2«H`hy›{pö5OGH¥~F1YjäjMûô>É®/Òû9ìÿþH_¿
+©pÁÀÚ†ÈoI…óB°×MÉ5iOÃ]jºj ˆ˜·nÉÈhÊŒòž¹ÜTþ†PÍØGN†õ»ji©år ™¦^
+˜MŽDÉX²ôQ‹]Ø`LŽØ.ÚƒdÙ‘j~æœô=±tÈ8êÔ»C…\19„IÐÈJ:„Ûsw µXŸÄge†Åâ>ŒÒ,3hëv¢*vac£ ÒQv¯ª…†˜X—õð/}b¡&yX¡úŠ§ëÌ"»†nñÔx÷²í›R@Pvjä›íúqX.öÉA…§_ðå‰F1‘En_° &SŽ hËÒfLUÊ@üÿR²Æøë¶wâvL•‡€wôθ æ“­íxZ¿Ìçœ7)œ± åñ)¶–£/Xõx9vJŒÏBÖuŽáìù6þ-…¡ÿJTBª˜ä9ÜÈ=O¨ÌÊëQvpÐã7& j3ãçÀS$<žÚý24Üð‡𰕺¤Þ\ÃÈÆø ™廹¿¤n~Ï)ųtDQÁÄ^'¢è²F—<^ËV²¼FÇszùþH8â¦kqã#dzXïÚFˆo$¶~,bb–i*ù1!&Œt…r@—O &ïG­“ïUƒ’à mÑ,}i`(ÈEôåqL¦™b†±¬^ú†mÙ,Ñ/1[.‰)¾Ò¢)S7â Z€d­Åw˜üdn;v‘@Y‘_KÓé;@rÔpY|ˆ€e±lûC$€«CýWÏ{ª&‹QÓÝíEâèEÙ›¼‡ýÂñf™‰5¥@ˆ$ú 'Eeàå
+U©¼åa
+ÿv’ê5X 1ÑlýEy2C ­Äì‰)˜NŠµM2µ¢RÈdw§c@¤:òd¥~5䌂gsžqŽ¼'C¢Á®'aŠHNs}ßÍÿûϨ‹vSÁ“„ÿ8³ˆ¯¢e—+0B*¼ro&V4¢®ÅÆkäu†\Ìÿ
+H‰Œ—Kn¤9„OPwðÆEŠ’Ö=˺E³rßÛ_è‘Ó°ÿÄL
+(§#õ ƒ¡þéÝæH«Ó>þüe³~ÎV<¢Î1Šü«ªÃ›{Ô1">Ä:
+—ÁÎå\¼9«=8òdoY­x-Ôh¼Y'Já³QÒû›Ãxðý9fm¾½T“uz¦»S›”yfβ‹SÃfÏ:̳È Á£Sı!6JT³³ŠÑÎÊ
+v·2ªânÕ»Žµ2fÈRv«¬–¬uævXQjºUÞ—*³´ÒÍ»×Ë›1``·vËWrŒ#ŠÕÓ)¯½wŠ£…ö:͇å„ó&
+k¤ûœ¬¼ ÑkÔMë9 ·Î½Ìhþñ[™ØƧÖ9uàhVNÇ_ä-[¯|ÒOy¸R/ÆØ„«@:Óâ*D¹Åé|ƒóÒBt-ifõÕñïí´OèA}¢°
+Ä U¯Û¢µºÖYÄ)­&|Þ:kЈ‰± ”cL&Æ|C¨DwÈÝr̳Uzc®œò€²NÕ˜[¥¯uºÖ,eP›i­hã\Î^é:ÔU¾b\æ|£ìo™•e
+„Úd¯-‘Ž>³ž[5Žì­ŸÑLΑ£òûÐ6Ô³Ô2ùÍà®kÐ5‡@*1âu†¦A·fmA´ (–õ4 7Ÿe0^µÏ³§,b‘ÏMb)&´ƒ9° ¯u&Ó!Wž?C®4ó ÛÆâçOPPq–a¿ÖÑÙ¯GPCL VJÏ›™È¥Ê±Eô ‚^3‚–Þ8WŸ’ˆf\Õ汪ÚE9W÷†”ÑߺHÇ7\í¿Woùô&膸ÊÃ÷èLÜ­èówî:L/,R}–´gzj›(äتöR°‡Ü@¼S–‚o1r»=v€†—âÓÚ8—
+ÍÞ…,ôµŒ¹–b‘»²Ìg’“½GÖðÃœf½Qe¨=o¬ã•pD˜ùZ'Ð’9`¶oÈÄT‹d¾ÜUøã½C湕í 4e^§|_„îcU ŽLHÖ`ã¸öbš¢¢ž^íG5Àù>1‚V1Ï üOA‡Æ¹¹M /óY^ ¤ýå(û®`KH‚ŽV; Ç·zîVJlË =t°žn7Èh ͹ÝìÂâãóÒ´0´‹lV8ÌNü‚ÅI¨„ÎJü¸Åæ(ù…šÂó¨ÃÑo\S‡¸ØC®u¸ÀD@¢:g¯@³2T§¨?{£6°Ÿá*N^%° ÊD“Ûíwª×P§û†¸ÜNÇÉÛî ëN¨O=;U Uç
+Œõu¹>¦m›X›KÊ\'8Å5S¥iQ¿±ð™wÀ›Æ”+rö£mâA
+QÎö
+S ¯7 |9äš]Ò ÚXô¬÷^ Æá1ÌLD¶ŽIz´×Õ;ÿçîI××Õá}šÀw›ÎˤêÅös­³ú EÛ‹cY ÖÕòÉËÎXDIò@ˆòˆ5·Êz¨CúSšçkóœ‡W¢@m3‡
+„Ÿù#O!qô¦èa¢3›ÌyòV8f9S¿w^wG%îÌ54Ø…ª¡f±šg+R¡æ Z´A,ÍQÙûZ†ò"¿û@DªÆ-T¡M?´²%›·¡€0Ã4€éßág¬g@«N´ÁK“f©yÝÙL$Xï&„í@xî
+½Ï5Rq”²@Pö¾–¤SÖ#?”®Ý‚çR5F²xq6åð?WÃÜÐ
+Ú $¬HunwÌCÖL(éDjH+3ßùN‹âöøtÛN´‘¡É',¸y!Ý5M(/|â£é"4ŒR–z¶i.ªM„
+ó+õ?–ì×wÄJhy?´\ÜèÑL ¯{»q¤É
+$`ŒÚ‹ ¦âB4Šs/«àTžÈ•ùr”,MïR_o»áš±ìõò2š¬33"ÏDÈKc…Q§>d%¿•/ µ¥YU4‚yhnd{PC‰7ÇQƒE²¾ó
+2$%ÈnR‚U 6mË׬0e?Bší´h?¼#È×G¥- ®À×Áx€­¶ðšd³.6—ë¾Vü=ßè£flˆ+¼¯2”×NJè/ûhú3ñµ"2±Òf¯n×<¬=â
+¿â9œ³;ùG‰ƒœl;÷ ˆãeî£9À›”—Ã@åý¤L²_¯D°½LÎ\ñ4©Ï#&å˜Mæ Ò¶­Þ‹ïaÃM¶’ oZÜm‚s] ß Ä“
+_•Ã Žœ!á&¥Â}×',EC[Sq.â¹'ŠÄ¥z0,Ï&oÇc䈑D'Ü3HÛûE3ô( Qebæ[IEXwï˜ÂØ ¼
+Ò'ˆqR‡»Ä£h»më$Fœ+tÆÐh€˜ÆVÓäê›ñËî…SÞ4Ëž­²˜uhÊÓ•ò—Ȇ—úZaùJ°¶g ²F™Â>-gn<D´SP·}èoÿ•ÙŠ{H´gïRÎ2ì£ö±qØçAîY:¿<®J¡µ!k¾_Jl+­ü6²µÇË:N²9ž©Á`6PùS¢¹?š“تÀ&È J[A¡HÜ&º³"†ž¤iúìÉs^þ}q¸…ˆ‚9uÁ/"‚ÆhùÅ{N±ÄDpï*n誾P7 îC¹‚ÏðŠ^ÂÚÍìz=5³+¯€öúF(òÜûp^'r~“pƒH:±/%š¨“•ÿ¶ú(* >¦ †«oëüPè{ÉŸJõ¶2°tOtãm‡þ¬Ò^Kž3u-ÒpC§ðä|[ç©œ—’?£â½WÈëÆÍbŒÑí;³S²dB‹üókÉŸnê—+0Æ âs.5¿ÿº%ÇóÜ4˜f!õÈî9÷›”®RkÓ˜µ`‘dy‚ƒ”!_™ŒO°
+½q¢î¼Ä“hε~¾˜ÇÀØF˜Y¬Óq%ŒÓ”²À v^ù߆MïX/éLƱù¼<#(â`ù…G]€eÂMý`œãþ üy¥OwŠÄhr~L92³_(ò8c:Õáä2æmJ0uš,7f£b,i Hí…¶("¤€z½N¸È6FÒ ðs–‘C¤CàªÜºDNoÁQhyŸ86¹ŽÁßA‰`êkçõ¾qu"›ÕuÖ©„³,Ÿg^&ê”4iê»oY…K
+âøŽS•|)ú篛Û}¼±‘Ø2±Ý¥èé¿ç·!%ÒCäÄ9ŸªF ušÏ/„V‚~JÄ
+†àö b" 6³ç$E2¤Xi¯GÚ°A'«ºý¦ˆ÷a3¦}9éÃN€EX˜*¦ðRsíH†âGÌa~vâC^T#½_Âw 3V°ºmšrò7,ýêè>K:xFçõŒ²îE4[£¶o‡‘AWÔc²v[/Yê‡ðúV·¡ˆU8uå?†÷ç £ò >ó¨pÚ¯º8ÃOL|dà— Ð7åæF€?0™T«Ù—²Äð›Åi`78–fÄ?øPƒ4²ç¥è” F•Òèù­  ÅPZo¯[ÕÑØÑÃ-¿¬ÓôÀR…¨ä11¯|cÐf¦Ý°`\ê#“eƒŠp2Ÿ‘^&¾Ÿ…ÒÜgÜÒ‡‰OµÜ!:ô[Z+°Ù´¬š@• pÀoÊ
+ "™øÜ{ ÇqÍbz¥L?S€BP…£Ÿ«fa€ŒY„éãÓ™Õ[m+
+" ÈYŽkƒ(E××|]žùÛRŒm¢ù²®¨¹¬ÈΨ#ºž!²Ÿ-BÄZF[´î!–T=F.¹Ëw¼ƒÿà (ñ)žŽ*á^'‚’ú¨‰hÜ‚Ð ô?7:8¾>#|¬)}Þ¯Ñ眉˚´{Æ*ô <˜‚P_ªúnÒHYz8_òפ÷`.§–fhû¶¦ÍUâˆa‚uóuMˆým™ƒ¶Xg¢ ì¼° 5n¥_-³#YºAÔ+ZA;ge.÷sÓ³à 4Z4¨v6 Oºh,‰…óþDðépô²Dò @ÂÌÄ{v1?ûaëý1¶hpåÆöuŸñª5¯"|¹Ú¦¬Kˆ_ÅK¹é v·sä™ðû•T#}jW•–q]û´Ãgþ$mx7LÂœ¥r*…"±µeô–Ð{áÈdT\…1`«Z¹¹ MŽž‚6]¦’PX¾´F‹/ùË"„SßK ð²nAùJ$²,Λ;„FÈI¡Y- y‡Zͯêà-NûÅM°på#˜‡æ75üthùdŠ‚ÐçRIUü%äâcŸA¦ÏL”…[Köo|g—cb=DOea¸aþݬEHÔ|ç
+F.8^³;ïþˆwéU&ÀGô|=æFè"¯¥l ?Ë{Uåµz p`áôñY!K‘øñⳠС@<#•CDág’« ¶ÄJA¿ÒÔJœ²W)£VEî}ñÊXô^>%®Z¬tPÈ8›µâ‚@cl(¢¡a0·ž "›¦°“ò9¢³d„‹áþMP2˜"õXÔ%HQ•ÂRû~>î¿ŠÍ]ŒÎg­/?Èßý›–€½€7ü%kS ü¦ú EÃË×®Aõá"(¤¯^‚p7ÉýôK!(yª¢¤»RXG;íŒCÄ ‚ç˨bXBº’N¿«š¸x2‹ AôI|ë¢Ä4Ql¼÷2Eä# š)tô£|_4ufZÖR:È«‘œhÿÚbÒt3¦€Vh/Ú!h9f쫶Þ`P·)ͯ9ÞRx:ÐDÁû*‚F¡v].ïa]wË*9!ôpaî$+BÈÉTã»!úAÖr2Ê%į2ÕnrvÑË9Ì kÈ¢wçzy ÄÌܾý$ðòU’Þ*ÁÉÇÙ!7”†ÖMöcV#­XôÎøOÛ Üã5`BÇvX/k‹«g0œÂÞè‰Õô:¬ù1»à<²U'Šº×
+ÜÌ6íH¢¢®%4¨ž‡[Hã&æAÁ<!ÛTÇè=“%γ
+¿ÜÔÉÆP´« Å'š³è5,¶Ðxr`=ÛyG{.½Üµ=e?‡d‘=ŽýΟÌ
+‚n‹,vO<">ºÏ/zÄh£Er¥}_·—0ûM -¦×·b<¿‘AC±ÔºÇEŸ™AXz©UÊvÏ¢¾Ÿ‹Vc£ Å`£*}KgòJ"lc¨s;êÿ#ÄË„°Ypü Áã–³„³ôü'újÑ/˜•õoü\2èPv§ÍÑþ'ªæ^ÓŽê}Ôêïh‘cŽÈ+ÃÌX´ü-­d½¼$ ™Ñ¬ù–Ï‚0,‡_õ9ßÔJ†ª=´Ô«L\Èÿ)7UƒHß9õà›fUnGÐäͬÿ¨}¿‘É2©G±ªÁœÓ^eòTIò§-ϯ¤“èMÐa‰§|™¥uØF+Æäq„&ìÕŒüïÏ7¤‹q¦|lvvˆ¤U’nYþýFN8S{¼mä¬ÑÙй•Çiï‹CúUrÑ‘’>#
+ߧœŸ÷m‘jòÓ–YØf¸¢§dXª™g:Ã¥g"áŒEÉ
+å:ÞI‡PtìÊ‚Ï ¦T¦6Üç4N×–‡à«
+êÌæóxÁççÚ“jrÿêÁt+?»æ±¢ÿ©4k]óJÝÉ-Nñ½.å¡Ð!gèy^ËŒLÃn 2RïÍBÈ
+.·ØKÓÑÍH»’¾¡Íû´•Çü£=ÉÉrŸLJJ3…±æeM%Bˆ n#¨|OÑÇæAB+Açâß—B”±Dms¢óG( 1ƒ}‡àZ]ÈQ‰SúŃÕóLÛ!¿oü({ ëÄ’¼ª›ö1T›D
+Aùir|*­8§d€˜¶¦«m‡ n@zÞ\÷A\M³Î„ÅU= šn˃L}Íô(AûfZÐ:â‚YKLªä¶`Ô´_"ü&Š $Ò;Ós|9†t³­
+4ÿKy™$ÉyãPøºƒNPÁ$×êeÝÂÛºÿº¿G€j;“¿UŠ°¥L$ bxƒð-ÉPÌ%H!°Õh{YG½>Ûd÷“&º‹ÜÂ`e„•&ƒ{ â“&ág¦.ƒ«ËXÐRY&.‚@˜²eyõth ^ŽR0=©üÊC aIÇ?_"üáq8mëî[Ю ²½³4ü·>…ÈêQõÕc¯WM*LÂÛƒœ(øzØ[…x̽F;_vj‡
+Þ¸†øM¯-;‡¹`à*çz
+aWA3–Ñž®bDá8¤¾ Ÿ=œ£—!ù<Û&C:%9}3‹± Tl®¾.#á7ñÙ¶jžN¾®Â ©BÄ”¯·ðè"’ûP}_&ŸˆK' /°N®qÀ‹÷hKÐArxÄö9(10¾ 9Z„´&ñkx
+ýgÑupw ÷ÓÄóô—.÷ÂïV5mfT6€=N,®"CĘv*h£t^g‚ [#Œý–[‚ÃtÜ$â\˜cˆç!Ø¤Ò ±«‡ˆ áä¦Îã1õð•áÉJ¤C  AÞ”œ8ÑÚtŒÛñ 7„Áí\Þ õMÍa)Æ¿”¸H‹7
+¤×Wi㛈*¿‰eà*€½"Ø@dàán|$Ç8…zÊšð' ²¥ÃÔÜÕ@ÿHò&].ÍìJã]ÀC´¶õÓÖPÖ²¤¡kˆ0• lG/+ÖnÐ÷*T]é%‡ZBšÒa=£ß„Ô)}˦/_S…JMGØ6Ž¡é%µ?W½½Ÿ# `#zyJÆè :‘åËÏâŸu°ž­=ÕFÐÂLC–f¦h_–¶¬õØ)v£Æœí8C±qÐ yÅUÀ
+*P®“’†MùfÐ?®ûúNNžúûY—‰ªàžp ¸ÿôùô:- Å
+IVpZßy»ìýuß
+ ™ ¤P,®’F”m^¿ôŽ®—R¾ÃëŸë½Ûòó??pqð‰dR‚^í"p¨ìi¨Ì„ÞFÒ–A\  x¯ëN‚&ŸËrKõ¤:d×yBæÖhEÊ„€ùØòzù;%þµoÂv€aÛ3Þ\øA¯Ó>!†©…ÛR;ìËɆÈ
+)ûá6ëô‰7´…q´ Œo–…X½ø»- Ü+r·7»„øUÂÀ¬<œ„±p)“Ù
+“eb"›×9ï[m5Fx
+È5Ybç­‘:(\îfä~j§Ò˜íê±óF~äY— Ù0sA9 g<JÖƒ2£3‰‰›ð”B24uõsào¦Ñh§ÅœófòieJG팒LÐœG83Z#fí\Äîð1IäÆhÙF4ÐqÌŸW˜°®S›{Ükè3e:°{í\ô¯`#XJ–˜†ô¤¦‹*º@ë’0p—ò@.Â4tÕ.A
+”ZÇkHZF>‰0ºYƒa¤v€\ã.”¸}p
+,—Pßôë}Œ1'H9°+¸BÈVTZàmG
+ÿèT€$*ŒõƧ™r» à °åC- ?Zц"‰c¾9“¼Ä=²)²Ñ‚Á‹Ôlõ¸
+H`RÔÌÚ."n‡Ð–Ýa‘ -` âzäÀ!P=jÃ'(ˆ>M ’a*€ÖŒ*§Ff]5®NV…õ`?Ð&af Tö†3 \%‰Uû%$˜sÏ Õ±ZÎ¥ )(ÑêɈDsaH{¶ÇG™ZËl÷zŠŒÆ¡ÌÜ XìsºØ’ûmPi=h#!1#‚ìïpÕQÒt³p@EÓÅM¯²‚ †ˆék¦1Ù!hÙ@4ß
+8(¢ä›D$‚Oý-Ù^úÀŸÇ°ßP=°ÏA?o2ˆI‡Ô‘
+Ÿ°ù{7…l,ãN‘í²1_Wþ Ÿ àP±ìš
+‡ÞÑYïõÊ„ƒFz÷l®DÊו²¯É!0T«>{¤e‚èÏVvˆ "ï],£_1ùqÍ‹S9SÎ^!GJ²ˆé¨&#ºÐ„=tFbTÏ„©…MPicKcš pö ÆX&R&H”üQ0Œ@ :·YH‚{)2÷ÉçpÁ™ÅâlãKð_݇Þ@&ÒÙ©Xv˜ul–
+¼D¢·'¸„X*¨@m‘VŽçM¤Öo»~YÅ:Tâ>ø‰7
+V§/šˆX<‘t*‰Pq—©ìèȺ€†"BE‚[¥ i»±ø'¤“ŽW&‚"ËÈOfÙÞ NĆ0²º
+¡’¼E4OÀ1™%N¡ï¸~{j¸§ì*-hÓ3 šû1]TdàDE—êÕΩÀ[ÆñL(oê 4„ÜŽ!ÙŽÇBZ#lûÂÚ÷ ënþZ1œ([ ù¿äÛ˜,ÝÈîP> yíï)(2kƒ*Š‹~œCnžôrŸ¿÷ ù%ê
+”ç¬bÐp°"†§Œ'ÊV÷òœJ˃/` ªu Ý œõ‚(v¿™Œ,´ÞP¶P‚8žnð$Èê*Mêžê„þBñÏÓ9 RM¢½<„ð5( ˜Àº>Ð &BùôõTQ¼kQÂCj$
+»‹÷ºŒ.ïZ o
+õf ÕDÆVàdµ(r^Sƒ
+Ÿr8|Ôöð÷ ÙµåÄ6pŽ4 ï~M‚b«½ˆIb~M‚jF¡ÊQ_>›€©Ü³Ÿ,™„¬ÚÒ¾”™¤•Y
+|TbãE:œàøÛ®‡ƒK‚ ¥oöæK‘3ÕTKAJÓcD^„=šÅݪ…n8(Ü!Ð2+’%-O†­fa\ÇFrƒŠgBÆ:¦TR㮥!áÙÃf!ìH7:{Óp8]‹¼èûQx—(%«÷ "‰Ê"_Ö9ØRZ
+þÆûè)M…„“ aé.³ngÔÕj^Ü%ö’ "y!’d®@,ˆÎÐgíðdK„:fÔzÛóË2FIJôžÌ"RUÞr}!mòŠÍ®ÂS¤>ù >°€ì$òKœÓF2·êIÁN©°0&
+Ý!réì$é¢ ÁèpZ~ܤ–e<„\”åÏSл”£×ÜH¨¬Öøטƒ];Ýì!l1x>•£[#"w•
+H˜íÁ­„
+'ï⯣[+†:…®‹Ìô¾à‚âä»F Âõ3`ŽvV¾ºïj׊
+±¬ÍÈu[›»]#ˆñŠúOäd׉B«„{ég»ŒÐБ¥ §3ÎÑZsÒïÛüß-ø”aI軶M†ºdãã ùn8ü6ÉD„"n¡Y}O27c÷`Š!RaUË Á°¿qË=è:È_'Ö½ûïøã¿ÀœƒwY&žß%ú³‚º¨•M€[Žu$ ˜F§ƒã%Æ.]%D0ØBf!Ÿ§ƒ  )–û.õuÆÀ4þÞjÞw¹NªB9 ‹<·z¼O<A‰Oè³T}Ú]-ÚsXCìKè™ms×&ËW‚=ü±T4⤩ø›P Û¹uöTu
+a*ˤÒ36/ ³
+ ‰šÑ'AŒ)—n:ÏKˆtJUâyi·@Cù–(„—0ÁûÜ/sõd!@‚ 2›J"‡»ptòTx&’/{ï:š`ƒ0Ú:1;Y\û¶ë„`¼Twõë Ü,SÀz&‰Þº‹pVð­YS®h=2¶‡ùfó~²¤áaIÛgȈ@”•¾¤(Ô8º.š¹­Å
+ˆ€k›£œ Ÿå‚~CöTÀ=É€ïK$›²!´uN¨'yWüÒɆ¨U,gR'^²žòiº9ÌôAÂvªÁúÅ“»ÒØLÕœöÕP.m¡r@ÜȈ¼ X•5AXPã¸9‚A#XÇÖä¸4k=ž6íº´Hj_ª•Â €S·¶å
+* ÿ"XŒ_kbÀØ—ËÀ ‡ ¯‡ à–I£Bsœ9©ÊöP Õk
+-µŒZBÊŽ=Áˆº<kDùÔ°"
+*”=òOþ®(ÓÅd°¦Õv˜±A™À‚Ù¹7IÔ6,•üÊ
+Ù³Ä8û)…N2°”q‡Ðˆ$Yk.[!hD#‡ ÝPGà\9e{äÈB
+Aö}·Uâ­é¨$ɤ(î,†¶(>Ž–>6&;©o™´[ÌkT•¡¸6ìÏ1(HTZŠ>š ¿ʵ‡å&û?ǼÙÂoï³la–BÀMÅ!Ííwÿ2^'É‘#G@O ;Ô d
+ò<Jîø¨<Á^ã ±á5@ª$ân?¾:ˆ‡Ïß·žw§¾/˜~+%6É×|äÄèž¿9LÚ< 1—¾˜Ðö–=çF8QG³Ý²ôw4³·ß}ÜIA@âie¹Næë&‰9p/Ì̯W}¦¿52KzYþKìø4¸âÛžÔYÖV2ÜÎЋ`ó4gÜ!¾3Ò½dç‡N{º‹¸ín¼ 5ž°€“8~f­ó­è÷,Š’ÜÙïk3Rx'˜ìgÇ (ÆR®m_1ä{RQˆ3¶óV‚‚2+­É<wÏŒKïãåyz ÖJH g–D¡ÊÉíu”´ü?®Ù*6!Çh=k+‘Oö{Lÿïì{&ø~Æ¥Á3iTšxÍy{ÞøvKŠxOleÈ7³[ô±œiåQ—)·#~HBÝƉ d·+*r-²…¾°Ê›‡©âš[Æš,eDÛ-%XwNùÕùÃø]í¥è÷¤‚;¹o S¯ó\¸ÞcH¯ä•‰ðÛɶßuÙ÷-†[×ßÞo2©¨–9â3g³<WdØ@ÆT¾0²~"ä–áÊðu^7 þdÎBŽŽ”pðó•_ÏÐ'ØŽž$³X t>KJ,¨ÃíC‰6–Î̶—iš·oˆ.ÎÓÐ1?_ᇫ/Sðæ4ij¤H¤—œâŠ'œÍ,´ë‚±õAȌս¾®ñ)ó)hñYòÝu½Ú%<_
+œÿSƒmVl`“¿ „¡8ì¡ÿªÚ1…b\pÔ‰›»¶Ò—Ìl ÎݹhøãPÙ¢;TþøüÍØ%§m?LèG¤Jñ[lËåïߢa†âÄ?ÐtÖ¯ú€aÜÎÄ`’Za²k•x­„¶}‚9>ÑÝ¥û™Ô¯à6êÑɆ³èâ¨h® $/;v"M%#C¦Mf×Vh­s'–†¢ví™Ç©àCVXœkl¦ËñˆÝ,ñŸvZÜt÷¤zæ$ :*@Ǫà~'x¸&XPb–nx¦ÊQâÙ„QN•€iŒ3gà
+ݶ%´ß­køöè)¶ÜÛ³ŒCq‡Ò¶/@µìdžÂf­~6^kŒq(‰'aÛÒÈÿ‘ôŒp5Çu¾Ú‚P¸0Cüpm/k % †V1dý²ýæH_¨Y§HHdÖhÏ9¯ãàú±E&mÑã#ö7T4Ž 2†óLËB‚ÊÙ׳
+\ÿéuõš–Q”Æ3­P1(¤r±BÜñL²‘@€ž
+ÇŒA€Š;feŸœmëS7$fÃÝZ|EŠFÉ>¾ÅæO''pa¼ø>Y–y×Oe{†*Ä»˜f¤{NX4Od:—o#ë-rBƒg ÜÝ'8¾|›8‚¨·èE™\42s¿†‹„.B±L…óÅû!¿}Êâ]ðƒÝηŠ¥¿Îç1€¶ü°LüóëZû,lôÚ(îÛß@ÜPÝZSáI¾®Õ51píUs®÷Ãœ%™ò®eÚ ø’rÏ´¨ [€BvË |èÏ€±û¸º‰>Ž"ãÀ<Q±:ªˆ$hŒI_OlÝš§0£ç˜N·çž:7KŒ%ÎЦ×<M€·s=Ÿ>ò 4j[¾íAaÍ · @ò ÛFýÚÚ¤œ#lâmîYÂúŸæ=m°Zߺë¾FÌã‚¿
+˵Í@F5.³å!Õ=ó€jú2õL
+½ïûë%6Ïð?ÓDf(uî*ËqP›˜N/‡øÑr*TïQÎ:HÎõ¥j]%Ÿ6êoìXœ[4\ä䱉æ9xÒóš†Ö?Tõ×k‘O
+g»ì{D ¯±‘êC¿f·8ù=â8 Ã8mPkÂOB?KÎèfI“ï¹QtT1Û¹š™¡yg>ºC4#y½7”~]pœ=Gø£$[ÑÁrpØp»Þºž’Ýmø¯Èá:xÄoß¡%šŒâ¶}´î}C¹Ëûl ”¶û¤ÆÑÆêýyó” PÖ+pqöÇûÅ‹CúvÀüŸM;ãÜÉ›ÇIÿÖ™Ûöe~í mË3',7ÌH+½D+ËÉÒí_ÀNï]Ø«¹•¶Æ ò²wæÄÔ—èÕb@²¤3æ¾t¹g¤ Qa–W 7ûÙ|пÆó¡¤p^™'®ý%¿'TÔ™TX×Xþ¯×Ù$¾¶eÐÊèUóÝîiŽ/^Æèâ%~ŒÇ¡¤ü•¸Tž9/È£k½jóæâÊ]CB‚Öë½À‚务
+Z^¤(ØJ’FhÄ¢?$X?Hq°Ç,Ò_©AŸû­`Tœmäã+˜iÛÙìî§0T4ò u|‘ɧgGžo+«¨ò4aî¡zÅÇÝâög¢J Red»Cx¼’±ÕÅ5ˆC­œ_¾âs´¼`±ôüá4iUΆíÇ[=Ù¥`³¶íãu0N9f _ŸXI;Œ”ç§VUCc:¯XÝÅ‘-W’tÂ&¿/)ßwí4s`a¸E'ÏþâîÆNbE¸¶&¾½š%ü”l£S«U*ôVB1³
+>Ã8s«¢HÞ^›•BçV§ÐêX é›°kâÃõzï®K‡IÚy¿j¤ Ìyé÷>()<9­žŽ
+ã‹J™‰cúxGÖÐ홨°"Èl´2×Á
+Èö¨$½ÉÙòS(çdê¡Š¾în¢‘å+£†n¾cp;|G6Í…>+ß¡ðÇ4 =2Ö©‚ª
+–žâ•{¼©
+T…îöî!©ˆ”ÐûmϦ¯ðäbÈ Æ|œ!åã•,ËÉ…¾pÖs£ã ñ| ÝkÃOèû4’g $ëÈÎÏ]­”hÍrˆ3sNLôûÐ;<ÓdÆ[T™)-ܬ{÷ÍU²dð“í\“mÆqT¹N?G~Õ…a].U86jÎD §¬Bmÿs6òµð.×Pª[˜Üí¾oÉÍ¥†¸r꛵ïf`¨æ£–&a˜#¦‰‘Ì#@ÓAq0ݦ…MŠ¯Nq™J`ìÇ’ÏëÖ½AÜ„jµQ9t¸<œÃ(V]‘ŠîëtÕc¤ÿ<ÿ¡|Ì-µ…¹å_‹Bd]ϳ
+‰ĪA·<€ÕÄôkñ¡÷D¡á—ðæ ¥SáB
+™¼LŒó@}X4vÈU™¼Ä‚ӧ$"Ø
+ªålÄâj©ú”ó8&¯@p.o
+=÷gêÃ9”!i¸öùp›cÑèl®QâË«¤¾Ìš›c¸TgiŠzÇ[ä5¦/òÜI&]MtKý6\Žjû[÷Oáôe±!Éá£#Ém²nçŒÍ6ß F‰©@Ïf ²e;´ÅcÅfÑ6¨u+£iCRÊãqθºr´@:Ù/³~#f=„6Ñåyà B2`’Y@vèø²OÐÛ~þu@›ÊHª¦ÇÑßQgÚGKårÖqx7ZKÇ2ú×¢í¥b)Êy¡`Ù} eè‰^øVôóÌc'¶C¿0×¼an‡@ÀH·æ¡<@”Ĺ P®¯O½ƒ¦ ßÁ</”ãaj{@ –8_y’ZâC¤Ë´ «1|P¥;t5IõíxR¡MòåÛÇtóoÈÀdVùy*¼|.2d”À+ó‚±fÓ" åáS8j|^Ǽ_˜¦ðHìÚîýñ០÷ú]o=øD\Zù ‚¹àC¦´ÚÐ0‹øÜ/’êˆCÓ–œ|®ØTIJÂA€d/X€áBbÉ?@ôž-Ä“Ž•Î!n’$TÂõô)XæR<œ3–œÖAÉ”£Ž è‡ñUÇaLW, Ü!ÏzVóPi&PN8/µ¨ñÜ’OèÓY;¥g@ óÞM  %Æ6µü9\GŠ¨ÛÛˆçÆN,õ0ɨI¨qÁ3Òx¸”K€!S¥•ë9ë{Te#NªÍß-Ã`ôS=ž4
+ˆÍù/ÇÜS¯j¤ ¨*"Ò Úó—* áéÓ,Ú$ÍÈuE‰Eþ¨¤m†©êægX¼2CUhÐÑx})É™ðÜmtªÊ}@ü&z@JQ¤è;†‹"0³Œª5aÀ“F™a,4ãxºcõfiVv÷ÉaöŽi_&å@dúÛìˆè±=EáÐôõùŘýùÇ ô&2wø¡Dr¿†#•Ÿ‹‘éT]ÌJ!÷ó×óï9’p ª»ÂÔ¢|Â||+Ó2&Ž—µ”oÖêÊßKT„a”=8 1<ܵð6®¿ ¢¨©A æêŸ{«ãæÇoÔútäë?”a~OUÌ9 q1$?ˆÉbÝÒ’_s>»*šÈÖÿ8 Ü7¼Ä9©• H¬+¿æº#-MQ,$/DÒ.pHqK„_!ôCUihÑI=ØâÕܯi‘8–frAA¸Ô!MÛî³ZM˜¶¹±õ}ùø“츈½µù‡0¬D'vb·È@ýâc»œs†Øfdµ[¾¾TK2í´« $^Ç™q¬W±ŽP“ ŠáÔ% ”G F†çœ~è^é„}eÉ¿Ì'dsyö“Ä›Þ1°"ÄäuQ©Ý­Å^.?¡;Pff¤„°ÑY{býE½¼|>—[Ï-OOƒº§}‚þø5¾®ãÉé[±w³°>¿öºð/ÿÚð¡‚”‹èâ톘 žê îÚo3¹?™bgt™s ¶‘—P`´OAÈ>ÄÕ¯P÷¹0´cCƒíœƒ¶1nô&‡à–<&‘JõåàM‹ª#2÷šçç×£ðŠmüœw
+<V$Òç˜M<C7½áè&{Q¥i‰Þ±á8T?" CÊíø`"4ø±—ì+I j_wž¢¥4¼—ˆ$$!Õû?|#jJ‡š)åõ_ýâ~Ú8Ã}ˆA%gܼ)§ Iv?D2D Ø€Í=‚«fý°Þýâ}l˜³l)‡YSh'K ï§$†iòïÊ=ŸAÌb7qqú¿„‡âéz•˜6FÈçó9†)nÆÚ¸Û˜Ea+õø¿>¨ {µb#š¦‹$°võOá™êÕ^¹.ÉPâ¶û™Ô~è‹g!·!¸¡†ÑRë¢kÌ憥w|ê1%í}*§~@ÀKAø'AlÙöì¼ìUЄ˜”Êœ‘§ö“Uc/¢€{ ö5c¬1+¨‹wë?Ábsçmm(a4ÏìԤ؇´à.EZQ
+¥°—‹]E‹` Ä…Š\°]yPÑ©ì’¶XH•ËƒKÓèÕçþ# YÆk:ÀýS·C"ÞX¦sñ&êÕ\Ô •©ðaö±~/ù¢‹Ý®l
+„•D¾ª¾ôçuGÁ`9>,æÞÇ?Ý@ 2Z)º¥Ñ+]ßðMKÛXCan–Ö !椣YÂfR6"W/Úʈwã`uÃo¨Ç.ç\
+¯ öpW€¢oÆÅ] ½Q±ÿéûŽíH¸™ñ ª‚Lg4Ÿ®¸9)QÒ¤(}âCËè6Ü_št>ŠhÞƒãUoMebéx‡”ÎV8“´<渨5õ
+]ff‹LÔÙŠAïпðïCŠìñ~¼¾Æ™[Ìî%Àgè!êuX Å -€Ì»» ˆwÛÚYcb%µ`Gc&€<=ǬիO¤Œ!Id©þò‰ ]‡ù ‘1ŸtiÒ­óu³BLyb Ž¿µ—àøBI±WfZ‰e cÿÓ© ƒƒÓâB罿¡å×U@8â'nÍn(ÙYi µÈ¢t”jBW
+†ì ­@ôÊÓSB‘˜'vâÁgÄCþðÔ¥ßÙ­8gçfb»ì%–{ u±¤«¯´Áóz |1Y“±^‡ý*¼&×Z¶mœÕb.5ü©žSͨL¯P²ÈJ>-xöÝŠS’¬y8àq„þûDfÚ‹âMg,…-èŸ8O‰P*ü8
+Ž¬mÚçú(¸Û ·5ÝîS¸ÆaÄ&Üã6zîV¢mxŽÂ§Ñ}Ò•iÂ’¢j£Å—Ü"Ý_%ž¨±­ttÚ:½¨¾z›ðkÅ7ªÿùãRÓLÂ,ULØõ×­CË 0„nßîH;Ó\“3祊–cÁd–—6V
+™®SÁ·ß1Ç<q ¯%š¼‘`Mè˛̢ … ¬'+ŒE^bŒ“Ž¤ëûz,³üpÇ£v¸æõž8_bÉ'ŽnA£Øåm­¤Áœ¸“¹Ý«)¹TÅ p‹1Vrƒ«:º|)‰!}›õ´,jBE2x#JÐl¤~ꥈ^¸GŸ¾ºd6jl÷Uàï^ŒÕ|ÑVޚљñN ‘Ÿ&#µKŠrþäÊ4“)¨%º™‰Þ,gaxäJ O¶yËHÓJ30R –oI9|¸á¥HÀÔ
+£ÛLähâAÛƱw7Ÿ1%#%'Œ·éoî ±pÀ¾³5Ñ~™Üݧ=¼woxñ–Ì"ƃqÛq dÁäc7ÜʽËk‹‘4.!–í (´$ÌÚÛ,áÂUòL³\0eb¹ x‘"úö€ÌܪC1í¸ÌÖÍÉ)ža;GÅP÷Oø4ÔŠÕ/%?üïGþúýd²ô™P‘g¤?¦VF†¯¿ŠÄ_¸RÎÔô¨”@J¢Xýš£‰YQ<^ÈKY5vÒÞˆ½[“`¢<ø§mÅð3Lãâ©çÀÐL%B+1 µiJw'“ ƒXŒaXÒÆ”ÂÛ=H£ .IHã(V!ú ¶B¥š­#Ñ&V?Uh
+úä3³³U{ãCQ¹ÒöÚJ^›’Zé/àl0ÄC²|µuè ˜AÛ±–Vh@ªQ‡"…¶u)ñ­˜ŠT4jýðöÇ:4ÿlš¼òp+š§ÐvÎ3‹¢ÖÓ\§oµ”ädîèx«¢nb²ºy‹*h˜z-1X^ªª(í^A3µ
+€q\ìp›ëa¬ 1oèÑ+ó"¹éG©aýv<ü@ΘÛAï²f¡róĶ*ú9OÀ>jV º¥
+#ÿkMšL7ÿîö¦·’¥/yõiè¼UІ— @»~¶|Ðä÷Wêê6)pXöu`YäÍ`ɪX•NÌ4ÝJtý^
+)+Oxá, Úè ’H¨'ÀÆ3Ì‘c°+"f¼£DËpÁçÇJò`?;÷¹Tg¸³Vœj2! ‹%K}J`¬!Ét3ði%/ý+šZªHÖ"Â-Ì«rå€`+c‘@}ìÌŒçóJæ<7fN¸š)™ø]ÑÈo9‡;B‚´PÇ1i­[Üð
+û²<]ãt³_Å™ˆ'l°ó4ŽŽ½‰Ý[ѯ§"°Ò7Îz7œœ݃šèsØèK ½!pdËÞ5pUXu¾Ù@è]çZß<¢U$ºÇLãv£9s×$°®ÓäKÑ"ë@$²eët$Ó¼x¯yPÍ -Š’"ƒa%«3äâø}Äù³bÑè@oá¤ð KÓMÞ9ö™ÀѦ\Ã%ñŒd8$¨Ö³Ê?\øŸÿÁ©ÿ§Ïxú½Õ•ÄO´ûšQø‚õÿz(%E÷C~Ö—J4.©§o‘X0áH6…`Z ¬9qŒÑ
+9bz‰qè:¸àä*"òba†ÀsÔ¦Y”L&Q”L:’AE¦G¡Y´ËKùÌJ¥UK¢"…ºhFü}«a.<8  VQJdkÛ ~éd>TmŸhI̼z¦AU%:š
+×Óº”°Õb –^ªÙ'~_gys˜9ä|DÿPÏ Kð¡dÕXؤFÿ`ÜZ]šo%:%qäµç¹U‡ÌÙXFpiÄÙF¤œ8 ¶¦ š3¯%oh[]ŠCBTaïúu;L3v‡**Dx»j0?¸ŸýûhzŽDu˜¸”jÍ1çÅVèì)ÁÂÿò?É^“û—" þûRbSÁ±H´ãÿBV`
+H‰Œ—1n¬9„Oà;øÛHŠ’â·áÜb‰ÞÜ?¯$ý Ø-/pÐîj‰"‹Å¢âÅ?ç|ùèæÍ£y«ýó?íå3óÖY7$FΘuð]±imŽVj³ÈÏÿ}
+*É훟ίл¡ÇÉ_†ÕD:Jz@6c /üt®W<—; ܺä/µ—I†è×U(j
+òÕ¶ªm/TjØjSÿÅ8…â
+•ÌÉ`™ñì»ðÏÇL2Ø
+¤­‚ ìsû<5˜FãÔöUÇ|áª1Ú‰ËRå‘Èžé_Ƀ4­O/"õüŒR—\¢—ÓlaåLßvl Žµæ¾Ê$ôç’˜ b`P4 c_ç`j— F\Ï9%I¸¾¼i}qãZ®Áj^ \U`¹¹²&I½C¿Ê3–GÏù£Hðé¡ü!“€y&ºÏ»=õ³’®u9éT&±
+Ïdã†×悦c2‚¢ÉcåO†%8ˆ8 Ñ$5~´ô§–A`žìþ¾Ö`£ÙOj$µ3ðm¬€¬ÌwòLY|½4Ýyö‚¨Ü¸³!…>ô› o »ê¾*0Bu,Ô|ƒ·³.`^ÚÊ^ð5š0»]0.üË–û¹C˜ƒ cÜíÍè
+¢í¡Êr¯s¨¿RßÄéM¢\žÊåײôЬ€£ú<•*ÔŸa4ů³aa%HŒÀF‰™T׌»íYæ¨owMðÌ+ý¾AÓ«“õŽQ±HÍPeQa4ß ©`Íj˹‚£“qdšös
+?a
+¼7)þòEÒŸÍR5E"ø¾-wÇ·¯.—§]3jà9É–÷c¾aVŸ“õFyÇÜ<í2C]^‚}d5:îD¶¦è˜sÓ"6š2rœ–X~Š½¨v@rbŒ³@dt6 —ì¯8ç HЖÄWÓ¬'A(èºÝˆÂÏ»(7Õçˇód:…ó(ZKE‘ÍO œtŒ
+:Ó®òœJ5´‰akjK Ö€åhð@4*p•Ltò¢:¹úŽÁoùÍVJg JDZ't w:•ø­)ΞÆ( B:m5r/Œ¤q…4ül#Y°’‘®zQÃý(_?Óå¤hj¸ð‚¦áxxSõ/Â
+¹÷Àpf¬ä.ä›6jKž$.µ?]@Ve)hÿá˜/nüù2ýð¤/ ßWÍ« •Â¥–Ï2KA‹k„ü±ò™·ûÝÕ¶ÕP°bå©eÕ2ËŠ8Ï3€Ùfè…‚[ëËV@".f@³t¶³†™ØÊû½, `hP
+ÅÀ„ÆÅAœ%ŘØhU†d?`- ˜Pùl:˳1j™¿«RŒ öˆ¹XcÄ+VWH0Ǿ zOù/*ºÇ‹½º–GŒrËuà ×sÎöφæÓѬ’ø¢eL ƳjDíö5DñƒÆ ÜCt^M.(8—DwQ~F¬–å_„•5Þ-Ÿ‹àQu!Ð6
+äcc–ôÝ|"ÚÀš ·KØI”*¢ê
+G ˆë­•ÂzYéK×Öb¿A=L¼,5—ñ~¶—n
+Ä¿Ì$Ÿ­CзA  •(½]Þ.Ì ƒB †2Q×-ðïV›| ‹a®¿{G:luPNÿ|œƒdÌÐÜ,-²íR¡!Qˆ2{Â/Cf ÔË‘ù=þ€†p€#ó{bT ÃuH|{Í+¹‹~=Œ6¨0Æ«Hs¢ÊÁêìÈ¥WÁÍ-¾Â²Dê€ÙJæQÒ
+¡>¼´gV¶Îú1§äP.ýs65@B%–¼y¤0Š ä@‡[ö«$ÀŸ9€…+Í2k½ƒ6^[Α‚"$jX[˜O(œP’Ø4(0{5l+‡2îˆpøܹÅUÂsŒMi¼ †¡­` Hsâ1h«,ùŒ`·Ç¨qT®éûñùñïÇŠÒIŠs¸$ Gf‹}cÉŽ1õ/‰MGRíÇ×Çšh9>E×Ècöwcþ¼ëû÷|éÕzãwÐC«{|õ!æéEüÐ)UY™U}7æéÕÿù½:?þþ˜(ù$·aO¢†¨GBõ“1ÿ9Å À8­HyˆŠš¿Áy %ÞmØ €ãº…ÐéU¤ÊÖ¥œÐùŒŽ0TAFH;ÉxÅ9ÿ ‰K‹ªÎáÈ®aƒ¸W¼"Æ`ªX…h€§v p+ä°«0*ÚQîo×€”lUƒÈ˜ºá;#”[[PFB¥Ø>Ч{€1nB<£(
+ò"äæjÎAì5cz·lõ+Àœ¥?—‡°†›<Õ®z, ‰ÜÊŒèH¦•Õ)Ô£4"íIá
+™iˆ"‰ ¦ —¨33‘a‘2“:ËlçïbWÑ&u®m=žƒDá5yéêë50ËÕY• KM¥{â*(•4ÞÓ÷—$(ŒR#ˆ™ò—Láã´â|%{J§fG¤àòL숾qPº#A”Î}ßÞnQŠÅƒqBIý=áÛÊg‹ÏàŸÀ¿'e*¶(¶Ê,>ŽxM‘J‰Ï ºx6 ûyb6¯EvyHûGA(ÏÔ†”Eret Ò€!'X3Úº~©½AÛ,s7Ùeãª"M¸ôØÓƒ,ÇCYâ*u dÊ*ÝcB< $ȹèQb«]KN–AY¿R…,Ùi†ŸíÖEÚ|•‚uãèéA©€äC&SÇXÚl¨sH0·!KY,ÁE|K„ËR\@nÍͯ’ˆ\ÚrM¥évð”%MçNB͹‰¿\XÌ=^BÅF楥„èÅŠOH½FSUã!Ù‹ÔVâ=ÜI©¨*Ç£ „€:¹qÛr¡ÆI£0„zÅ´vÊ_b™ :–ãz†´™Ó²ŽOåÍX±{QJÁÖ v»·“Fº2¡ñžYåxØ6€Ïp‡CŠ=ŽE]( Ìh!dÌdk½Ú!À –—€2ø‹1çé-¬ ‰»Óo¯äå¶.NÕQ‡æŠÙiGÛsu¨°Rb¯Ú€8SØ%F2L¡þÙnÄM@”35S{PÕÚùëG€è¬=G\¨À«Póxö¤Ó¿]G7, ;I†
+´æx¿fy¶PgØÞÁlŒq]:@²”)×
+“¤{v½½•Ñ8]K(V@6iUhða"¬Î&º{u¬žÀ³I©Gê0+§ Œ†„u×âîKQP-Æ>”â9±Íë¼ Ñ†~Á
+ø „]’X‰v"µ¡1T{hß$äÅãó/ÂAÁÁvVÐ&“´ôñåMaʹÀñpÕ¥±Hb5‡dGâj¦n5þ‘º {°
+©`n6Êö Ét`îI ýÛ–šfX<dt6 ƒš(VxK™ÕC:34™cV:&Å$G]¹Ä{ð=ácH¶»49òšêäBHc`Ë&«l!BöA
+zBœš·V5Ñ „Òù´Q·9×õÒ4ÖÉk!· ŒÐ<õ/_§€a|†p¿ÜÇ“% H
+‘¶RÝP‰ÎÊhí"„êŠB™õ¶O ô\?Ö£‰•++ëã}`ÌÞÇäþŠT<ÛZ‹›Bv–†¡ç<’3 Go29ôx„NgÂa¾„Q
+6µ–—^Já‹`ÒB•ë!èÛ‚˜Ï»BLc_³ÎÍ3{Á©t,Ù¦z(‹Vmo×NÑHÊ)ñSŒ™Ja¬~ˆ¨Pè'e)²s‹1@v…uÿ<Ýõ‚¹ò*ã<é{
+TÔÂ]¬¡¿…Ñ€!WBsFˆ(²ÊŠ¤ÊvÉâ1ñ¥ýJfD¬ˆjÌYSÄ<Åòà_(Ù <@ªsÐo™k¼Œ?€Ž(Ìm3 {2÷©ÈàÆ)ì}ejb6YTÜÚ›~–Çi® .¶L%¡)35ëayßµ„¶qi^ h«2WBñXºE‰
+ÇÎe!›QP>Hg‚¥T ðè.L¦ÙJ‰fdº±€0ƒÓ]öòùñïÇLŒ±–ŠÁ÷öèLG™Ÿ&©ÖçãçE~"ñ"º„âúú˜ŠyÉþþ?‚þ¸îû7}é釳nrœ§‹çº
+ÉÆѪCÐ׋ -¸¥PÁöõ16Œ¤ŠBmúðý˜ûe‡ìÞ
+b]á'Ð ò*ïq€ŠÔ$¥ñvÐ §Îmy³ÿ®·Ú2X¯$ZÜ’ c^õs zª&?ärW  õfÈsج (˜$C_TéôT¥ÃmïÅV0ɪö$owŒá^€Ì@ÿ(
+ mI›Y›
+›³¼~oÇ:jL¶FÎLÑâ :âBÅw™¼tÜFvÈ¢ü¼ÚcˆsÅÓâO«%\e|%TŽÀ"˽Äç0š’ŒV¤[’ù‰Ë*ák‘è|}OŠ/6)B“ßäªù¥h&²&Ýöá«0†XÌšÃüBç¨%Í¿ßmSÉ“±+ª‚™4¡«ŸïüûóG\dعDÙÀ ŸÑ]8üÜ$BtNw%9ŸÄ®Ì>NHCvÖ?Ü÷‰È“’Ú)Á‹cGp—:ŠL$€áØg¹EEhÊt©è‘2ÝB$ÍîU@d ¤,JšZ¹PÄÑ.´žJü*
+¤”~Ýhâ‰RT“U‘·?Wñ°„“ÊÌõhDBEüyD¬þÂ~qI…ë ”
+ ¤aÍ+ÑÎ/žÑq7˜ýŒ½pÿï¿,×5Ì°(±àÌfí]þ„5:Âà#&é¾°h =Út‘ÍC%@^ª —ó$AïÆFkÝy"AJÎðð-ácqØŒÚÔ̈ŽVAŒmÿ¹¿ ‡BÓ%µ b¹’$ÄW‹>žà(1ø°ð
+J¸iǵơS1 <—ŽÑEuã™’ªÝ«¼ÁTA^H|&³š}Ïõ‹ôZbŠŽæ:GFéÎ@,D·jž%2”p¡k²3sçB€, 9×½oÊÐo#tdlQB˜#Ô9‰Tœã„ÉŠŠïÐ>”Ì?Š9³‰´Ò8Ó¶„B@#+o N‚?–áøÎ9ðfqPýÅr ‹ ™ðÅ1„t"⥎°¤í$H…wj·‚¢7W•¿x­“¦‹­nPC“³h4ÌN\„ÖÁÔ ”†}¥áK¨ûP’>’0hÃáoL42?‡öVT¥™ÇvAˆø0ôÁÞ%bö^¦„ì”d²KÔûöUïE& «¾ÂùÃ9Œ¡+‚æö±¢Hd†¢Ýç›drLSùôàž•]Ù’5?ÝôÄ“?u+)ú«ò25ôÿ*BfP=„m®_†`°{¸8‚Ë
+_T¼xTôÜ¿ âuAÉû0åÊЇ$$åKN6‘‘îZ…ïA@±&a Í W Mвs•¡ö°,ö{vsú€ D‚~!¤¶%ûQëÙ„ÑøŽžÇ§ŠÿSäž&¾¬u 5§E¿ÝHªXoX};Ÿ0QðE²M¤YqÕÇWœ&—&K„“—g% $¹³(·9 i¼ –†lQÇhpjyžCZ•?¶n.‡þVÈ®v8ú­À•AÝ“kGŽ íC™iäÑnÁp×;ÓļS‚@°J¸L~è"õ 4€õ"ÜŒ±°Ké æÖ.áôøûvZqV Jrí^•ôŒoÁ¥ SøJg´&I`ÑRW*<mã
+=¿ùþ©„é)¨¡7uY€ÄÁ§«‚ÿuî¬è^¹b „\Ø ì›hÔ‰׫,$9ù¶*õc
+¶f«:Ãõ{)ñ(¼Eé'îÌù~î –®è1ö…Th·†ì\‹?Ê0D±nKk…ͱ/i;ß ÅÖ5Ø\ÏaÏlnÃ9,Ž 'Ðä4¢yRPeþ1D÷˜gÐ &ÛÒ²do†àS›œÜ
+Î4°ˆÇ»2JdžƠ“È'þžïZx#UyY¿P' YopMV—Ñ XïŠ4· ×Ì+"jÄücVeÿ±+í(‹¨¿M…V*ªÀ‰d Àï¡F”F‹ ›L'aeEbL‘¹?¡jdVØT.£A”h¯g“kKvtÃ0+àzNgae
+*K¯QøfX‚íŸPkàNx˜¶ªæ•”ŠŸb/u€¦]éjÕ|‹ø¤èq2%néé‹„úô 4‰ûñ] 1aŠsmëv_ÌJÀ¾É²ÿ©ÿíܦÝãÐa—Ç‘©˜GÙh`Ô<„$‚U$P¢R!Š_= šåzá0ªî›cdÍÔÜÙH9K•–; ‘Sž¾<
+ö ÇþCíÂSyÿÓ.ÊÎ|Ìp…»p
+ ÑÜF¿C*~ˆü­”=T
+‘ü¤«lhÛ* ”Ív*t‹_ÕŸß+m,ˆÈ­‹ÎéìwB!ŒCÚ/ÒrS4˜=„ù¡ÙhzdE„tp’ õâÔE…(â¨lü;‚€P e‹Wñ'²jIT°ÙØ'Ä O(²2µS©F»„ü¥É€‹œã˜ÝÎ1°ÕWQ¥>„Qa<l%ðBI ¡/@Gé H.— {*à€oPe ÃoÆÀÙŽŠ™£5§è‘4¹GÔ˜7ây°ûmÔXü­hí¤¤Lb€Â ÷ ›öKAÃÑ„!+ëTÅÌêR²É
+ê>¨8EQúðèåÀ® ·™øeqª ïQÁŠô3žˆQ²ÁdŽ(¡„-®Ï]BZJöf¡i$a7^@CšBp&Ò«ç6r%4ºË4z*<!Ó€Ëae‘„ΡÙÂtú•j¾ ´fC£é¶ƒo!>¦(%kšÛ‘6u+h‰]irÞc*)*ÁTê^>BP”EŽfzdƒrÆá±öŒðD½zœw™#P©ÿ\åõIè3fMÈ<Ž`YÆè@“÷N$1Â'òŸ=€`IáÊ]¡J¾¼oD;TÏ#:—ÖË-*5ÓÕÈ;Ú„òg¬X*—Á7Žà'Ö™Dô¼êb:Tq8#_GW™mOƒèMh£ž<zïܬ5W§b¬ÉŸãd%ÔãÕ(XžA¸urƒÉtŠ¹ŽD9éß²<DÆÅʱ‹_”Š§BJÈXh$[¿-¯|Rœ¥yµ^áÑßàz§rllÒŒ9Šƒ&ëØo˜ÎÏÇeo)ÀÆtW&I¢GÙ‡hv¯5Á‘ê?ÆO ‘ÌÂ@V ý‹”+›Ï% g‹0¥b¨™Í!¢Ø¢iJ|©Jm3ûÍ —t¿¾s'¿úå¬7Jr •Š¶+¡ìО— Ÿ‚þ½bĤ¦™9
+‹9¿óžìòºo=EMÆÛ6–dC¹·øôÔY—R¾ýúN½Õ–üõ¿?ê„lpR@EÛ*§CU
+Eä§/…
+bW{ÑúŠ 8d¤µØr²ÂÙ±ÕBý! ¦ü8Ÿ´C²lÉœõ¹C
+ŸˆQñ-y§[„H²b-R•,…ŠŒWáF'ê(Vx‚5oƒ"yˆS]"K ƒÌY`ºSÁàHÅŒ¸O¢ðÀ’BÐ9>A”¯öÒãÑPÜùÖkÌ!ú$£ ª]B<ÀG*=<*¿Ÿ#v.4ì³"-Ce–èâ«|γ3¿ iý¨
+°I¡;”ÉÜÏ Ù¦J}^nV:J9Ö1X¹…c…Ú
+R¢n±]”œ›RÛ\f˜õè¥'$mÚO"ˆµE~ñCh¿ú£UEW–:b !Hê*æžCœtVífk‘ˆñ[ì<Ìtåjp Ìć¹Fõ˜HžÃ•¹³Ÿ“IôµIé¨'$ëÐiø=éXTsZ1"Õ3¨O•4ZöúqûÄ…Œ­%èCšÒ|pêµ€ð¬¼æ([Ñ)„Ù´kc^܇fB‚ŠL›ßDïmüÞB|ü*Í_•Y³y?{‚”ò‡¡Ñ¡¨df÷mx9 9£ÑWdâ}°c’r¶‰FÁY€ Å
+Ö¸‚Îð­ƒ×˜á:t€â$›Â‚D*pMF ÷37¤°Ío£@Å«Ä Œ4¯!˜RšËlA2µDªgèS¸"õlŽù·+½G¼¹Ò{X2.Ä“p‘ˆ²Uì0TÒ¤hÊîäGå@ñ‘Ô’e<‰.AŒ3çÐQûpÌ‹¿‡¼p⟞ôô몟y“G§
+¨ä÷Q
+³>jÔOZîâéŽÃ(LäÞ¨Þ”†fW°6ÇÓš5æÃmN¥Ù°ØôÂu“„&@»fLDÀ/èXØìA€ãU yvKPD³”jYœ38’é’æuQR×ï‰Üâ”n@ŸÆŸ ùƒê¤¿Ssì ¾3{Ìñr# Í¢k‘°Ò0>“…«svfTËpqµ÷ò-d³3"¡©bŒj½#z–«‘~›éœÓ¯èlž9†‰_ð$B #Úé¶>X‚¡ƒù/o
+bpD•)u@ƒüŽ~‹®n¥™<56h½³3ýt!X6âMÿg¼Lr,¹­(º‚ÚC5(° ’C£<¬©W`X#ièýûœGFÚù$,À¶ ôýAò5· „€Ë9h¶È"(ùŒƒ&a 7çÎpá .ë3v>yctF´™7¡¬ÎNý|˜Ð_˜“ÔÓÎ7÷aaIóY©€`ꜷLŽàÉ÷Ò¤<O²/ßÒz±ò¥k b¯ðgñÃ/z5}e»£$åMÚTüíG3q6˜J¨$\ÝÒxé.PÚ»™¬boSs7¾€¨¸"#ω’4ŽNÅœ–Ó$Ä »ŸNì¢=y½÷ÇÆz!dE&„^f$Ðò°¼4sÁú 5#I}Ë|
+^ f¦jHâÏÇ£P_ÜÄ% ðÁóòWNT}á¸1ZÜg°D†Aˆb'ªÙATh—† H‹íLµ¦cö1ðKµº˜¦ýô«kT2n¡Ü¦—¨Ay`4 ~G÷Úd¶=éîbмi¨Â^À,Mßq߆]‚§j˜÷Qe¬ˆƒä°½Vˆ
+Ï"1uH)JˆQ24v“îɽÐV
+¦bn£„M£Î7EÔ:ëä‚Ô»|@ÁËÉJ/Ÿß~ÿ–¿ÿý[ÍpÌäÝS»[Ž³àhTgËq>c.è9ØIÇŸbµè\µŽ³€ãÕ[¸:mÝ¥ìZßláÊB«Ž¤%¥Ûašê86’ûÈgËÏL§š˜
+ûÇŸŸÆÓA. ÆKzOnµn¿”ýFˆeÉLq‘“õvüuµ[ð᪸$n ø†ÚäۚÙÅÈI…°°ôÑ_äÛ(Ò"¶‹_¤åx‚Baéh=Á6t?R‘ ¿mà/¨ÑuŽÂ±?D¼'a$é«/ÄàYŒm1ÞÆIÚÈvñCnxûM¨rÖ1¾ƒ,6½$_¿!Œ:aMŸ—AÕ'I’¯Ï²ni”w˜fÅ<0(f´C·/ö- tÛëÕv×˜s²ìè_@4 Hò‚ñÆ}Ô;(¼…dßãUÜfoHZ9
+ aJb„9npèÉ%yŒQ?±ê7Öi- J7·1‘dKÈŽäÛ¼áë‘N/1ˆl=r±Wü%§œ™`h©$t¾ƒƒag`õµöl±xÇúên’ð–ÔÜ eØ -|ÛÚ „uÈ•ßâ(Sg­|Ù: ¸ÜÐ|Ä•i.K€ECÛ”ÝÐeÞrE§Þ–Ê|6-Ô5d“þ•ÍûÅ‚¦­4³<.Ïwˆe戸õµ¥æÄJPZ¯žº”0 ndž¤X
+ÖtªY·¯áç3mÏsb†Ýñ+Ûçû+Ü•Jc0’4àw.öˆÒ3 L̆௧¹ÎA9ØhÖZÓ±p-ƒG‡º8 ¾kH¼:¾sDÿ¡ãýØž<Çæ1 thå›QY,˜2mA…©âîî R=öKëÙ1H—¡”¨¿6=@+û+xŽ‹‡j ¶–åÓyÔ²”îñÔË<
+ úÍ4ËzÄ»gµÁ£Ñf
+?Mý~=ÎÇ_qœ¡‡×Õ>‘-gSŒÍ¬„Ò‡á%L¥EG„‰23èjRx•]ušd¬•b™ÚÇW>Yؘi”¯kÒÕmfNæ¿“Ç~/Æ ÉšÿŒyÆÐKß ’A¶3\4Ës>rÉ÷Ù Rb{4{~ƒ¦Î` Ë úT—ß¹°ˆD<>³î)%×ÒÞÄø–8Jg ^©Þ²ÏJ]ŽÎç¨fѹ/6-ß[ƒ÷Âî8ºÙï°„P0}Ž‹“‚“Ž-Í.bö6ªk>ê±õ[MÊ2Ô½ÃÌ\’›źûIm.ÖK»+¥e4Úų üb\åà r(î`¹¸ÑNÝ4v-«Uç#0
+ q^ëh šEb;ûMLðWkͺ=*>à‡ ù"€¼¢iüsš©3ÆÔãè#ó­™Å–䀹¨ÌK°7"ÃÕ ‡qÔú³Í{ÞºOnñçãj6Ô;ñ—³›‹(5¼?Ùê $„.{ŸýT¢n[û¸í09)ë@ ÌÂXˆ¾ßm¦¹ª¤Mš8 ²½$tíò1ó4@¢_ã _¸ÊÃÎÆ]¦Ï8\8
+*a€ñÖäÈ5¦ÀöÍ}e£%ߢâyóMÑê ´“þèvê)ù!òÕã ÞV¡ªqFÂc´ŠºøïÓ[µ6‘¹kΖ‘ ¼ÍæÆru ãWÓžPH‰Ó^²íÚ 8Öø1[Ø<K¸j¬k9—i2žª°žAI¸]‹Œ[È·½ÐÝ”üå>Š7"JH7;s<Ã9#„¢#Á[†)èƒîï3Cã\ŒJû
+Â:)fÄØy^õ
+󮦸ì _Ow>ú´7Úh´õ2£Ž3ÌEb,êQwÛqÚU8jS2_ØI
+Ñ¥ñª*œ@çà³6}÷šZ©iHPГeÙC!®oÙ¬+j×tTõ\¹tS¡¬ ?N‰|Ô±ÉlKûÂÞÖòó .îSÕêÅAí#~ áCLÔÝëøÒŠ÷«Æ¿ò
+Zâ8Š
+ÈpÅQ:¬á8Vò /°Œ~%Ž’ü›blL(ã4ªPŠç˜ GÀRdGåçžÆ'ðV†ô÷o¿ýã[úþ·}ûíßßx;A È„Ë'«pÑIÒ$†À@~b@½‡™)^@½D± cCœ_¤¡q2W,^?R]sÐ`ZU¥k%4:sƒä Lâ™öI“QåMø‚zmH’ýäUÖ†}G2÷À¾B<ŠÈ‘’Épö#òþÄ2Åuu åñ6@†¼·mwôô*ÓBeø*¹2dù­8 `µ
+e–UÇc…Ÿ Ÿ:uNzaŽM¨e¾Œn w]–çGiÕ¹
+‹Ûó9ê½8ÆörЉ=–x%˜ˆÌ¹úúÀžˆ÷v¿|ã}d^îñ4zoïyšà—º<íÁKuÿï>¹¤zZ
+ˆÕA­&zY2ó—¯Øº' ÄÍy8gÑ)ßdÇ/ÓDÙôˆò$Y*“Ó3ñg¬ `1Þˆä\aå
+ÊqL“ÄäÕHXï2­/°+qªÔ–&zíÚΧO…k%åë9L„¶7õË#
+Ù X+ Õ9ÂΣØw°ƒ^µ³ Ð#^þí :@ˆ\Cµ³
+?-[„YVñ™ÿm’rå(ã*ÝÄxU»‡ð@‡EÙñh
+´ryÓÏßB|÷Fé2ôozwä¼¥”ö÷V¹äU2ì(08xÌ7Ö¼#Þk¤‚Á›ØB»|L ¼QÉðØÇEiª€IÐ
+ÖLÊÐþ(µàᮄ[vøÙÄ&‚­(õ Î¬:ðã©X¦¢ÁZ¥]B”ª’ Ád
+
+"q
+UðÞùFº—OlFA—¡´Û-ÈFpj!$v¤R“!^™bÞW—–Fwî£<Ñ$Ü™N÷ó¾óµÍ̬ÈÄ7DÛˆ£A7Ä9(ŠRd™ˆŸ‰I“äWRW×z³Y¤n,ÓíÎÀ4õ‘ KÓC~¸ Ù…±²íÍÔâ.3²ƒ ‡KÐ_(õ€A‰»L+R²y EA/S®6=ËàlyÅ8¦‰Z—¿ñ^¡üw3mçLñ+J @OcÜåJÏ ÅKë܆ãjñY¦öxvRZÌqö"ëV‡vû,)×ÉU0C=Hž´jvyŠOòâÆÚnÅáKB8,‡P^ˆèqcC‰™u ð
+ˆùX
+Ý!QI±»T );€ß°~rt‚x ýœÀ§0CÒŸ¾%²Ñ®XÖ’à³î/B.ëÕ˜—ïg–ÀOε/çÐòÖ: ¹¥Ö<² îìäJýF
+ËUܱÔ…°¼ÄEÔˆ­Î ¥?Eý„ í FQôê) ÕÐV=Õ”š ÿȶî’"“IÅ8’}· ™D
+ÍÇqln— ²]¹‡h膸¤•Èô`J³ôÁªú1(9N³À„*ÄXHÓÔ°Ȫz70õ‰Ú£¼ä
+”&%ê7,SÐI@¨|²Ÿ ž§Êz­þæbƒÿ“ûI“8"̓Á*¤¾k°Â
+ö˜DÐóZîi!ÒOkd´m
+;ŽkF˜ÿvÐmNËAg!ÜUe(ݵüñK‚Ô@‡jFÿAÔ={£Nfv¹¤u ñN`A`]XÑ~=‡Nd)%&jçynS¡l.Ws¶-Æùfë©WAÏðTIíráù…ˆžîºçv y&¾#%ŽW;Åap&ÂH
+à]ˆ Å2¯4œ’¦ÍNÍÒ s]‚o‚&ÿ:ÀC]²£2$,d âYÔ
+ö¥4\¢¯xœésÛ¸jûP$$v<¼ ˜¶y½`a£¢£­Mš·0A¤†¢ýáEÔ½@?åÉ×y"u‘V¤
+t†’
+ 5|×÷ŠÕDVR™çx1mÒ)èuzGÁöº„Ø"¤jÛå­îçHðI;çÊI†•ZŸwˆ®b‰SêG)ïæj.຦-ã¡Ð]ÌhÉl ÏÙ¢B€šÖñ@§™Ej§–pþlÆ…éíæHõë¯K‰"@R„Å蚬¾±šƒ¢›ÌP€Ñ‰«‡h¹ ßB¹$!B(/åcgv
+ª‰ÿ*%º„x&áÏÎ[
+y„“5KÁÐÀwá°ØCø§È{ê$c}¦hÓ‚†qjHÿúJdT»ìÄ% ;, +9%¥{ÑíæÖ E†NRúvÑaïÇ}«èŽËõ^$†Iž è/.ÙŽ~í¸ƒÓ‘dï¦9ËœŠÀ×hï/!ôvnìéT •}&ÿ a•ð¼å8ÂŒâCñ 5ì!{„Þƶbà`t0Ê«ùN¢™°;_ËÞ €§èõ®^¯Ëø=7èk‰NJ¸63±{óü™Œ©¤‘=qð&ê—§rÏa‰Bz8ºaTà 0Žñ„Ú^tI!¡-’hð/›A….0ðþ¬ÛuÀ§-ô7+/õ|zø[Åz÷kûn¹@ˆÆ´Šd›;ÌÛ$eÅ FÌ$²>FLòÝÝǘXˆxÇ•ŒU&†a¿íS«Ž" 6mî“þÂû%¸—‰C&Y¢·È PTrõWôúý¡ˆq²Îh½Ü1*+lsüâ_ªHû2q28 «”e¦ˆ©¸¾}uÃèuï—èÍF;p—¥mæxµm‰hQ!ùÆýçÉÙ­© IxÈ$ú΄QMù¶ç§c…úÑ\ôªáΛºFo„(q†»A¿Ì¦™f§±ŒRâãP–¿Ys÷I*¢C:[âEHP꺡í]¯xBô‚&³JïóD˜y¿ ìE\”‡.¥Õ¡†Ç‡óÄlí(r·aœÄ’+v¦q‹ãw
+¼vú p0»S<±’ÙˆWuQ_XmÓ‡ Ùb–óöPÀ`?_óø…0Bš‰·YxY /Qšåím]t—”*§¨Ã#Ľè
+“ºªPB y- µ¥ÉA®·ö¼Þ ¥t Q…é|ÕxM%"@ci'ap$[or²?¥+oèûŠ==$“WFÅ£AvزxÂZîÒŽ©].”5EY/I”ldÝ@3Ÿ©BȺãTÁQY,´VP6œð6ø=ÃoãýâMâ;)”ð7Üöó¾“á GrýÊbsŸôî[4ˆŸõuÍ>|F']0%¶•I9°ºì4/¹F‡šz÷m¬/Ú$<~æoÈ]@á+=¼[6• ö§3Üß!£ØTŽC‰ÊÚ8ã¨{Z5nžü;P5-'‡Ön/!€`Ê2z87͘ºÚb‰qÁCûØ^
+–|Lœ(ÖvYJB¹–‚g3:z-ŸŽüò ,ÒÓÒ"ÊÄõ8ØÛ¡ä=½ýý¡ÈñÏÒ=½!ÿ¸äJ?Ðƺøúä÷¨…EÔs¦nÈq;+³¸‚ocË@‚ ¹èÙ´0µpp»<»4Æz<.,õ„¤néÆu1¨2§U’è æ‘q(Y£À¨&%ÍwûŒJ|lÑ$··)(ö„¿óæ”&|Æ·K ”ä«>9—¯ l ¸o–¨Ä¾ TöT”møO A‡?•L‘ .¿èCgi Tƒ¹T>=>uð2 ÀN»ÀûÊÂ+1¸ñÆÞ_sáô
+?•çÓÌ]Ô`³P©ÝdŸ˜¸ïGAøüž·ÖÅZ*R•ÌV̳DÇ€^k‰
+¯à¯â$xS<Ɇ
+î”ào«Þ ƒD•Û¨Rã<¢„ëãÙ¦ká’,Bi[„2¯£ºÈÁL+%(Ôò” ’Ó¿ÓQ ì}Q’ˆŒz™é;§’î–“hû¨[ÑëféÊDäØ0&[E ZÓâ0o Œ]n%8 Çîvyi 1[Ï?‹o¡ èkˆ›þƒ=X¾‚ËK'ΡD¡ÆV͉–~®#ìNïçï° Ö58_öeVK™˜Ñâ%Bfâ©ø¸xb`Req—§®Òä«l?¼@¦d¦«<'Â1òQï%44ÑpÁšÎŠ,´šhpVÀ¬¹ŠÇ"¦‡yÃŒ ]u­¸dˆ“±áq,Ž hôØq: ©·$$Œ
+Áþ£Ç£DàÊ‚ÁÕâÊøHRlKt¤|(Á::FCç>ê½HK”³ÈMaq}Ò¤£ò3vœYB¼8«—TN±G
+:ÁMÏ!å?Ž¬5YçÇœµŠè7‰ÅtøꎧóÑT7â#
+!$¡2kœ f´g·í£M…*¢ãŽ‚@E=˜”¦S“Më;Ljb
+±z8y—Ww)Q9LB@-¿Š6þ¤1*zß¡8K|ªÿã ®·€š—j9g+§’€…øÖĉΧïHž§LŽm+$érÁ¾zý§{®‡îÔm…ªœí56,X‘Ê1ƒÓMƒÑjÈÜB:þ€mú³n¾žrf(,ÎÌN%Œ
+ùH*H짳$7i³"e.ßúVôˆ"ÜÕæ+ŠP~Ž¹`ˆ;ÌŠI“'T]‡ze)‚åÚN4šÏjuLJˆœúvi÷ÕFMñ-m/Éz‚®²ž¥Á`€ä¶›| dÄqÔ}œ/% 94¾Ã·§qþȱ&Âaè)X„rvŸ§/Õ¡ ‡Òóý*n,¸.`où«‡0®ýtÆϳ°,6ÖQoVS ÄFâ… ‚ÖN%oŽõ—ûÚÆ ÿe¼\’+Éuº‚ÚƒWpCÿϸްvÑS{ÿÓ> ”îç3ê:¢Ë†• ‚
+2%ªõ¥ÁØœûæ*`LØé+cU\G…HÈÔH»¬|ºÃCqóv
+¾ E#²”¶ŸK€~(äèÙƒÜIúû—rè^_˜ˆP•[|äŒàù¹·@7Yp§ëúcS0È:öÞï³p$ZŒ'FØ$ÆMÚ*·5‹u­ˆ ˜~Ÿm|ªZÍ Ð"Ì×B€gß·DWÄÒ`p!u¶àn[–1Ä.ìc`qVk_ ¬g¦9q¿­wI£ÌdâA“A"Á…M”"ÈúTàï±’ÿèž“¡o"ØÁ‡Ð³{›ÌÄ5\Á^–ñð*@AYeÈ]u¯8ùÕ-‚Öán…=ÈN­/ í~ÜZÁ×åï2U>ŸqDÙØQî£*êس¢ ±îOÝ‹Sá
+¶êY­º·Ü9çNç6w:¯:yLuX8¸ˆL@XT?§¡§‰ˆIüÌIüuª~ïá3mÕQqGÀ¿yù1KYíºcþ8O5ŽÝAŸïÜÈT#âÛ’8•¥•É9ëk2JÃ’Ë9îÔ™J'àqY<â§aضH{éæì ôQ²!,dŒJ6ƒ_²øêeoðÓÔZ潂=>´ÒˆD•KË,JìçèÞ1 ,)vq:uß@l­ŒÒ„_´Ý¯A
+­ûÖzÚŸÝRƒ:á_JºQ©a„è^%¾øó:´ùÆËo… ˜äaÜsr•l±PÔ–~]zê º¦Ïì÷8W$%&Òsdc/Áãq0½¬cŒ3ƒ8Þñ5i#ǯku n¤`ÙQDS¨ô
+Øä¬ñ®e·o†¦á¡²Í`|)`±iNÛF•Î’{Èf$Q«a„¶Œ-áã°?¥D"åËÑ,KD@ù6Ãõ¥³ëB”pöAñvú¼ éñâ=c¦æŸ©T‘ò,¦«hiÍs£Ÿ=©kBÝOb:X#ì’8/¶®Zò‚ºAZKÓ\‡CR‹±JÓÂU`äw€–÷õ©nê cÚ´@Èá 'óXãÅòZÎà± ñµ2+Ov€ô9ÊÙi³Jo¼8A<_qDw–\ÑŠÊîí^³@”J!(%ñ‡L„70n˜pN/©dJqyù¡T]Óg®jb¾(ívŽÒÈVqÝPI<ANq
+FÒh×\üTf SK´ò7ùAàc…—Ä0ihêî)¸ŠFÜ©Ê&³¸wÁþ:§Q/)=¼‰ä–)h€+}øçt&‚ð1âêÂ}$›¡©èeqõýÄx SÔ©™
+Öô.ÈÑwt×wA2ì Ýr¥äé;ÌéÌ_œ´Ý×÷¨HÚߘäé»zA®Ä›™À{ÃŽw‹Z׊úÄ
+~ÝÕ(æ`„`
+&RFÅ“w ð¼c§e0†/ïâCù¯4OÞÈ9ð29ƒìÉ» L)®¼×¾N9åýygò˜9‰AŽOvÇ8â~bm'@ˆœ ÎÈÙ²Ô/°!Z ΊýÇ$ ’I’‚å™ÎC’DTN2L_ÙѾIeaЈ—³8”ý
+±˜´>„ëƒ ÇÿáP¬
+\Ýž=À.ˆ*„˜f =†Yk¦¼p"æ:„Y$¨ €fw<üY¤A *µcÛ÷ñªèèôZÇvn²":ÍÅOÌMÖ ÷¸OáöGv¥½J<?¨¼¶ìÉDÍF9ÆLvN-Y»ï1’Óº-ˆsž”Ḳ„QÙŸúËdZþ ÿN4äLVt–Ä—zŸT“2…Ë÷üÜ$Aa'ò3óªÝå]³žum²Ã€lµ,Ý[#”’®kcé™ òEG ®%Ze7;ZXª“B¹„6•a0’ Ð Ágó;È˨Çø)¸J¢ègIü‘œÆè€> 4HIHK'o)Dé;#Sìë: u‰cÞB{x9­°Òû+MÈÃJí䯗´ºrUû¶GpŸ¢óºÙV‘Ù5°!C»ä2ÕëçÁxR@ç&œ×Ÿî9x|n‚»IJ&›ñì” ǘ†AxºÕKO×ë<
+¥ÊÚ—pÕL-]±µZÎW %uÙNa΃hÉŠÚd†Iof¹= È‘Ö5œuóý¸Ï cWä’F™çue‡‰ŠZ†•øå<Z
+Óð´¥ýè[í¤ü 4â ‘?œûã줳‡Ä†…ïÙÂpÏá‚H8BNÖ){Ÿ)¢&-ØÒâ'‰‘Vïöúeß4ÈÈãæ¦g—ex׸Â%åSVì{0ïÃÂOBe1<>¼¡Ã¢i.Jc{2ïã{­ÉL}ô"¯ü¨¯yd¯Êz9!dÊh9¶Ê‘$5 ÃóÖ¶©P“Â.e^–—gHÌc=®©ë<V ¥^מítüd{é9ÌÔ'ßOÂþ+Bu®àW´QÖÿš]$8Ó(ŒÇ¸Ì1›Å’ÅQ“ô*¿T·‘Æ81–Q^£Ú10vè0iÛ6œUå#÷è©%B,w7öhÞAÌ/á(…϶góI"ٻą±t ›k&s•¹7£YÛÊŠë2z9¢‹mÈ°¬_îc"¬li@—úq Ì6Ó+‚©›ˆmÀ`~üþ`
+H‰Œ—M’›9DOPwÐFA @®ÝKߢ"få¾ÿvHJ1ÒG…Ëá.•Sü2ÉÚÄoÿ/wîÑêè½ÊMŠß›7:ÜÌëòëë¿_RäÞkDëņvÖân#jH¯ýöïÄ„ U+^º<01´¶Ön q-Í {©Ö ñ^ŠéÐ6&¢ ÿÞj­~E|ÏjjÖuD?-Rï£YmcŒ°n Á‚Öšy · É ¹V1IH¿—Z£Y+ü׸÷Dq:­k"õö{‚jTsöSþSPó{Ï#‹ôèæÔ‹:*4 }½<î2¤íÕÕÆíÏA;k-Um-4¼Û°Ñ› ™u U)1ŠÄÞ«¸ÓL/#|µ¢‰eGÔx‡¬^xƒÜÔ4üÃ:t¡6TÖ7Bº–ÞªÄ:Ë;¹@¸ÑrÑ‹ï0ð7<­cpfSíÞµ\ÍhÔÆá4_7ˆš Õ¬=I²@ùÖŽn )b>F¡Œc¯34 YO­~÷
+Ý5|çñý•±Ñ eo}´ã2q¨£(äåÿ›>Ô›{{Ñy˜àtÉ% *ûR>¼¢6î¤s«XÇ-ðrmè ]ðg®ÓjO1Vï‹¡Hƒõr´ ©Ð¿åͺT jÓùͯ¯æÂÒ¼xm49`ú1ˆÝ
+Œ¡À*]ç:½k ìXàaÎÕÑ`ÚÀ+Û×Ó(Ì­C.©ˆKÇuœA‚“#Ö}Ë,Qù¶· V»‰º ¤äðÀÔ}qä
+ÂrØÃJºN³i'ìÐ4Œ*\#<è¾A’Þ{[Ή÷4Cù°MHŒÊ
+"ÛœL‰¦Ä¾b»Æ\š q켤
+š—]5¦àS‰WHû[Nfy‰?Ðb@5pt´×ZŒuF‘Þ ÓpF»§"'E-={*ºS8S«ˆ“KÛX·‚ꞟé(܃Y¨ˆÊTü¥D ‘=mx68žÒ0½$…/ó¨‰ùhiº·ú‹8W­œÈè39\·ÚóbÆTBFK‚e‘#Z%Ÿ²”òv £Ñ¯VýˆgÔvAm’£¥ø.ùÇ8Q§sTA¢ÔŠi¢:óÜ-!NÎÒÆ2p—LÂÃ3 c,Â;ŠiÇ[Šë,ˆ$›i(:YŽQï’o~æmȪ´^ahm•O1t;ðç± È¶¢l2wÉ´EHAäcä3$â
+g6ˆs\=‚^ã*’¾kêg?eßó*ôþh¥´vΫÐƳqhzÕ#³¿æU ¤sj>º­2]r&|îmÈ”Ï7Í[^íO7ˆO
+„<ØðæÚú9°f‘Ø™o¥½×Sd¥5k—6í§<zjý5²&Ëi±r 9.CŸ Ÿ0÷·.y€Ó8‚oÓgßßójÏ.—\¶—5v/yµSÍ’Ó AÛ)¯&„¥ƒ$èe¬—¼zÀ\óêôšWóÄ‘))ߦUN5oN2tÁžp£s`Íúå“€¢ýaa¯5›<E~ÑNAóè–ï5I!Qç,÷z ¾I-âs›1]Ÿ§ùÿÀšen“M»=!ï5©Î‚P…Kù)¯¦\ ˆä†òêAQ×¼úwmÎAÙ• ›û‘“t=OÓ,“`Ë?%|]§w7ŒÁ a¼ý’!dºPlÖý}ÜêG AŽ‚„V\fP¸‚’ˆ¤UÉâ&õÎ/é Î\ÛíÀ’œ1CdB°î†Afö*¢ž9ØJ¬ZóV©¹u%h—MDMçâuÃ<Këµ{†mâ—4Æò†ð+iØú„+ш6íY[%é_füOëhzˆ1*±‚9¤?ð‚i·K#P8©¥À(įk¯2Ôæ,‡CxV˜f#1ðõ­.Às@Hzë,T' -ä¨,j§ù€(£Ó¿
+Õ0záz|RáAÝ™!uìuPâ|Bê|Ã
+|œÐ®çêIãûSÛðî<èõþ0YÿI>›ÇŠ^œé`Bx/,Ä°!ćCò¸½q(Š½ i•ôˆ®Å×)øk±î Z úÙˆŠ™]ÁIœ‹ÜÅ;zRèèH¢'g³Á˜Ix
+ÐoüT¥œhì_ë/ƒo"ˆîGF‘0°È{¶J+˜>ͲxlÕ[þ÷E+¥¡N¡üÍi‚~YËÐJÚ@5Ç RË`¤6ñ†yO< <Pj.MG KØ)Û†QçzͱÁ×G§´•£ €d®1Œ8×t ãQA#š™?U0£¤LZhиÕÀ$QJ$ӫ釚1†¨ çÞP\DÔ`BôëÖPó²(u[„ÄÀ$Ŭe²ï`F˜4ž “=ÖDL Ù…RóIsNM?ÈèÂ$T¤›Çu/^9qc«·,…Y—êª(fx±žÝÓ@0µ€;–ïi¨Ò—ÂvOUôgF¼º­#»B&£1a+œ©³q!Z‰…·€{ãæ9\6:Ï€ ókÍÍžøg5åˆÜ"KÞ皊Í`oÒl\oÌA‡­q_îQ'j8™à°JžRPÓ¸7‡âe%ÓÍ“$@vÖNl¬”‡¼øD@
+çž<bム%+A¾R,üplƒÿ­d¢ƒ‡iŠíaøUÒ Üëð_±×±è/Aò X~\P‡a½ê˜@æ*üKø•ØAÞRT_lT
+6vŠÒ37 ‡(4ReÒó(»Y˜Š!‰E~œÐLÌZ›Ýû
+J4—tFþܼë¡hZ:`)Ø„Tù~(E& ZUfÔ‘IØVÀ²× ¢«ÓÝd?)[>.AÄž–Ù5§$roÄIðþ œf“?þaÃ"/CF€9ö¡ I‚ @LiI,) ûÏÑÌ:E*aX€¬Ls`„±ëèF¶
+ø;¸•¨à;i^ñ]£bׯ/¨‹–sá—‘EÝÃ*a&RŒ2Ê´ÈõŠDÅø!ÁÅ$’˜&¬Kìž
+1˜13ßxÎf¿1“(,PŒB¬¬ŒýŸ’Ã2ӡ轞GFKL—Wï/E*aT`-$·í1Ÿb$u¬Œ´f(ƒ’nWI$CÉs"9ë}
+WM|$Cy%”Š
+¸‹ºÅ–h"”ûåÔ‚tN>‡Ã;#¤ÈÂùÕ“Ð/Ž C‹/È+ÌI‡¬¼ãÃØïzXC¬dFRÿå ÛÔâ$Xäéì©/"ær$¨ç5Y%ãäŒÚ,Ç4t†4o%R|ŠT¬¶ã:ð¶"dOƒ½dÂ×80pa‚^yQä† yCy‚7i²od$èHýÎb t~r™Úˆ_ÉÁ;¼0ƒMðÏÉK@-óÊäívŠl™p°^²óÅ¥È\<)É‚œ
+îEÌ&‚À­²['îÁçŠE B­Ö`LÐD°ÄW]Š1ü¥
+‘_#x®ÊVw`ÌAc•ˆÅ0ß4£­öÈþ²\|´cDŠ°ëÐ ÿlöj7&#’]ê.)Š˜™G o%+‰?*iŸt×eÀ«m-
+Oì@ô Ú>Ã&'GÐëQïO ~ìÁÀNÂÉ Y9-{¾ìs!ƒ\ íßãrr=„å"•
+M†<ã†TÔwEüMJÛèš}Ð@HŽØH¿0güòötÈL„Ü·’‚¶2”R\b ~»åᔬƒJÀ&ʼn«éùá;üµIzÁÛmpyM’Öƒ ̘°Nu7¦–ß1÷¯'ávXÕÁ‡}/†ÕÍ‹IY]þ
+b{Û754
+"Ìå©v‘–J3–UNÇæ¦SôñP„êê¹ã[°Î‹Kƒ.áóý,Œ²ÎÅÚ€aÛîå¡…u~K}6á[E)AÒ\½ÉÛ£às»Ç@š^=¬°¢ä
+½ÇðiþØ`Ñ:äa M–=Ø!k“á4•}§*ÅQeß^Qc ¸õ%l”ȖЭ¸ ¬„$â#’ÙÞ¥ óǶWütÍÉ)z(™¬B€Þ9ìcÉ…`Õõ–Ž ÿÍŸþâ¸ZØDŠ›Yäo†Y2¡1MÃÏd°ÿ³QÐQÌa‹ò›»ÏeFìà2ïeØ‚j¶ÈÖSÿçæ(í"/ srLͧMmêJòs¡øWSƒ¶É%‚²a, †€dQ£•dxʺßN|ÁL!·¼v§— >N€æÆîØ]ÆõW`%›Ôi»>á–DH®G?‹)†S4þB]K$—whônÑF¼Æ:¶6n#Ò3ž 5®—GÖ‡gCÉ¡³õôWP›#`'ùÛJ8êzƒfæ¹wø½Ãä ¬êÓÐ[Hþw’ÚžF†™Òò|’ž ƒÌUQP6”²È“l…c’¬-Þc,qJì;b`Щ›Zøõ‚ ›Ò(û¢'6à»i·Ÿ°[Ü2ÄUÊE¢ÜÜ Øø¬$‹;öº¿Ö`R;ù¢Ióç
+£wYÄ?ðÖI¯(Æ ^M'=`MÁ‚M ¬u~k"b»Œ &«V ¸¥óPN;y! h¬bSgbàû0J8Ê’d£V¶,nR•¸MÙ%
+#Þƒ$rwÀI²JB:lã -6Íl§` Ÿ"`)’",²È.Ö¾ßD `ÃAfÈÅ…à”NÑ&¾ªÃ70Ä0Laô“¥`dúP¤3uS<2ÜPa~³úÊ}3†uXãCcÌ”K‚?’éÛæ‚Ɇ’¡jI; Q±Œ8lˆåó¡(E9H!¨q+J &sv8Àm§dâÐOþ(0Q‚a<÷Tð–]¥~Âo£è_1§ÈÐs”™ì3l%¹­3ÆS’Õü¬!‚äaø5€8ë]¡ƒôˆF¾bFfD¡á8pRb¿LD1Bã¬$vî˜}º@óÉ„cñû]4Ù6„$)Du£÷ë,Á%GH²âŸuaNîL¶Ÿ Øa0Ô»‹þ9[ªS²:¬ë+α†ÑýÎPê‚$6s•$»‰‘·–×,g: éì9ꣵË[ß'I„§6t–Í;d†€àà$ÚW„yOõT"f‚ÑðB£í“~
+Ž?µ½» ö›šç³·pž¡A°Õs>j"âšBNžc¹‡á8Ÿ{¨÷w.h˜óA°YÅÚx“õ•‰„$·ÍtTÅcCfxJS–•}Å»‚ÅÀc‘Ë|¨hò¨];ßæ>é‡Ý²<X²+U ì¡C+˜H)ù—_mãW‘3ùë´—šßÜh]\–ò•Ê§ãJ®‹G) !Æò±‡‹_EÎůӜ‹ÿx£uqyš)¯Q °¸>52KŽ
+\(Á‰¼ l 'Ò
+P‹÷W»8³ø3þ©² ¦*}ïç&ØÚ”“•`îdÑì:œŽ¢ÆÃÖÓ¡ãÃwX:ô<¤öt›Z±1rÑééUá84Q,Z›NsT!·Ì…ÈšÓë°[òmRû¤«
+'xâ¿"fØ»LýKÂ…YPä Çæ<ªò9‡ +„ºzmN•CUßɸqõïµÅ”dÙ3’JÅ{£z)YG½Žüõ;p^oã
+oåâsˆ1”þ ›[•;–õÍrIoW¿Ȇ£¦©¼1«¸™3Ac•0ž,Ÿ2,ÕŒÇ!±R+:1ÞŒ š±DcˆþísߟôwqH“I©5Öï
+^•7¬j2ûWÐ+²‹¼
+)sò¨•ãÒü!Cj…4·ï­Ñê>Ç-ž¨8™56ïýräAa¨ª½9'wãj•°š"æP*ƺLÌötH¢“üDI3ú 4ôeXYÿ¿ÄÐN­}?SQ`ŠL¦c€'0©e–3ü”çC
+’Äë„þý×suLî u¡OŸƒ.ë÷øÚ'˜B¸îÕ+ÈÉå?ÿý GIÓÐeÛHÿã E%I¬}i üýAbúÏHÿÿ¼
+"ëÄf¨œ–pÉ’F-ËÓ ±H›â:ü°*Õ`%†³P Œ¾â =_EšõZÛ_âA°)Zå×½tö‰áFÚåº ¯Ë”nÌÉLnÅ¿Õ èÛAèïT¿%| ’ªÉ‹¢°ûÒ
+ ¥öï2>@Ï
+é>•8£˜‹ñ½å¿+HŸ«ä=Iºöéû
+bÒLŠŽwÑaËÄi+¿ýàEdÝ‹ë_“9Xò3¬kpK›´Y9vv„Fòþ5RœSQ¤‹ý¨íÚ ¶g±¹rEcwå廃พ€ß>x?¤X*ç2¯‡Tw_t ›Ô• ¼ƒ›åúeü.FÙ'„iêb"¡\¶ÙNa8CT‰$~ ¢@ ‹ÚŽNdIIbD÷›Ÿ³Ž+kÒÔ›ûT<@·†Û郑d¦f›Ÿ‚ˆˆì½\/œ0ó¼ÒŸ˜ïOVtor’(:< öHÿ¹aX._£‚È¡É¿Ó©š|Ö« z‘¸_·¯}‚yɑߌؖ1+¢Ru»FÞc·Ê:^×DÐ$·Ã@P[rb®I\J€x˜-)…@H¹X96u
+‡yV–MÍ~ —˽бø/Y©°ÅµÖÔ’æøÙŸ‚*©'nh/ÆíœfY›eÒË€
+Îñýî—6x¶ã®U‹êu=ä‚û ’K²ÒÛÉ€¼X)I¡4Þ…6Qs¶k¸¡~ ¤|þØê IµïøƆ ]A‚ÈgÐsgj'$5FšbÌ5Â7TasRZʶ[ ÌŠDJ‡T­ŽìP2Ühû&­ÊÛòé^ÇðAÂsØ ò:¢ÿu]f=¹9Â!ˆþòÇ Ëú=?÷è…n»õŠqnÉâÉDl ?b£Ø/ì?ìâ–+f@Ï]v‘ ë”›hO£’²?‰Jú!vŽÝQ>­@µ¤Åd“û‡
+†ÿïõRüìP›«l1~‹EFà–Å]X
+Þ䀆o]F›“q©@(xr
+çÕDÀô°'Ò+ÛÃGëª8Ù>£0°M(U¸É×b3ƒt¸,’æ2éI=»>‰¼tã,÷žå¹æô} miti´ª¿KI³±¾íØAR‚MÖ×ä¯|ÁU…ªá³yw{*rHÌõ1HaV"Qíç;
+jküŒMwUfJò¼öó²?ÅX`ÒdªÏ}^Îérép*/IõP{QãñsnY•~"—41^¥x‹Åüže”ÓRùâ £°#}ÉÐÔðs˜$M-ðœÃ  ²Šì¯½,ÕÏøáó©WÐÔÒqÛ¤Î~uC.††£ÅŠÓ5\“*V7„æÁèŠó’j‚"Ùh×4ËQ‰žìÛn„‡¶'iZ°’¡
+dZty·SÁÇ:´ÚGnÓÄ#È"G¯ÄƦÔÉH’
+‡A´q{«>ã©+ ³&,æŸSe^H2ýE_¬ÛÄAaHD_“7'é
+É{HÞQS „"éY¡sõBÄú¿Éµ™&è;rV}®õbî\›Ù*†ÀMîÝ=®Í$ ¡å&†À½pmþh
+³þg5»\›‘R­FX¦us¹ÖèÆÝ.v½¶ö#»¤4„°uò¶†”RX-€e«ÿlÑ‹¬S™k§ø¶‰&½V®mŸÙ&~‹&A§ˆì’-;,b\ð‹¼¶"‡l bªÔþÀvsÉ6ëܯB¥¡u—lχl½ Ù&-±”o4y–K¶é32+y¶zñúɶԡ#;+QñØ–b‚+7sגˤ™‰Aµ’¢²ú×æv2]€ç,ðàÚÉG(ÃeÛÌŒ#£´º ì…m ÃjÊ•RÝ‹Án ™àˆ¨°°w‡;Üž!Ü2œ À1Ñú·gз„0S˜¢‡]ñ;Ü2åRt¹g«/l›?4DRɲ¹l˃GÈM|&=ëé°­Aa¶Z_Î{™XL¬ÕMÚw¶¥»‚èyÀ¼_ØÖð“³?õ`[›Ý¥'*#.Ûz!ÛžAÛBÑhHìro¸¶5€S6)Þ[*žlËÓE Å芽=ØÖDY ^)Ô´¹lk¨)åÛ4Ëxa[º ÏUd.Ú2WhvŽ˜nhÍEÛ,a@ëš‚â Ú2zLoä‚XrѶLÉÁ³•°â¢­r ít¢m™†&Z¢zÝEÛ f•œ_jåm¦F« «â!—m{=™Ô.¯¢µjžËŒÇ¶t &L´+ËÞ9Qm=¬Ãe[laáARFza[ íb>¼:n4»³m‚=@
+røF?ØöñØ–+'9']k^̯+FÙc1b…Ê.Úš(5¨·¹È¾Îm= δy¦>^ÐVIÖ)ŒcÚˆü@[FÏÄj]Žá#©WÏm‘[¤]蘋t9ãD,Ö§°osG[´èHÀ$ùmó¬eÇ$ªK¶lždû'fdûã/>Ç(у`sÝÍ1€ß3ˆ+
+µ"BÖ<—T9ã´²ÆØ–Û°n‘R*Ú€…ðCö0(nï«3Œ¡ þÑó Òv ÐU1o—MR tEî•2ñvÞ|†ŒýL€KHÁ²lrÔ†Eš|9i…ÙÍñ#—;ÂÛœ Ÿ/Ag9¾õë
+Ê3ùðiYnƒT'uÕÓ‰˜äPàR$tþˆ47ÆPnƒ@0é
+"eÿž…èÐ-jOÇöbýhP‹Â<ti‘´¸ŽþÇš«=ÂnòÁõÒŠ'd¿g͘U<`Œ<µ›5ƒtá²±ÖÆVáFã\p-u€øÖø@4=¦®Ö‡rMFf‹óM(6]Ø©íQÖ’Å¥bœV;›Ð‰àZµuùhÖd81-´Å—ó¬¹sô``àMc±áT /žüªGUºœ­N¦IC†–0òëÙ^§uãh| r‘³Ô2‡ìBùYrîé.-Ÿ4°ÞÝsâŠjRXvǵG ~˜ID)W#M†„xõŸ|Nâiºïßsb´Aš,=s0X!]s—hëÖ¾˜˜E‡i”x…@ ˆIcsÝk#[„Œ;\SþŒQ]‚ä|pÉ¢)?Sü½˜É‹à7!y6…ÃF:½”Iha:fj­k µmÀBAÆK&aý„èóŸ-ï$‚qàoò–I¦B+ ¬Ë’Pù¥í.AÁ;§£òìz8±z6NÀõ¬IÕ^É(Þðr ¶8/g¹õ P)½_ú%ØG¹^û©nËMMžt¢¢]÷਴,Ÿ/ úÈ1?™Ç0  *’6ê « ¶€Â²Û}dŠi
+,SU›ÒÕb_¶SÄgÓ"ÌíibÉÄ%êê¾’Ñçº]–IM" d_Ï>¬
+Ÿ·h=(ïú95aâh•&ïY²>ôPÙçô`…hÅa§ kE ¦‰ëií±´ Þ
+\‰·ó6R ¸¨ë˜cOGUNVݸròõXõ„183`-^Ðì
+NÂi̶CûÐ'«ýpZ‹€* ÑÚSÊúжßÏM‹A«,ÐoÌŽPþöc„Uü)ËÌ–I¶5w”M§0 -…bå¢õ“Y'mI#5@Š®-‹ ¡ž“™ÂñKV$wI–QAî?tK[DÎ[â*HNöû” Bàv“¾Ñ ѧ²Üˆ‡rÇPÜcØR‘´
+Ô•Õí0D‹55:\¯ùš |ÎŽî\ç‘|…·°(¸ºC¢{b¥˜­âr õ4Ä«©¦”ãEw2ï¬l’¡5–Î@4iÇDÑ7•²…bÐY7·ÛyUSá±BïøÝÎß
+‘'¿™Î䘻ŸˆŸÙà‹Ã5®Ìï3-ò Ï-Ž‡;žsäÏ9åQ„ÃsŽZžžãõÄÃs¼Îº›Žñpotñ¶B®´Šp·äÚŽt³Bxg˜ Û¾–›ïÂþŠj¥¡¢®ïèêBÌ]]f¾ïH&z¢øtõ}‡M³iÿC%ð–ßAÙ¦ öRYáÜsèAAR<¾ÎyøŽ×ˇïœA§§¤OŒ,…P CýfŒç)ñóðn¶†noÆÃÐ좀{1ž¯jò)ŽŠ®ñD¾d-B•\Ã8ŠáE…ûw)Ž9Aj ú±–"0Éû6ÿ6BªÖMtÌÄ‘®ñ¨U«“̲‘Çx¼†¿ñ0žo ×—ñÐVeš3§÷½8@¦AøØ’Ãö‰)
+Ý\J‹ÌŠŒÚ¯¡C˜EŚΡ伎Tóºå;!v£8ÉŸjÒ¶ÄM ßí‚w3ð‚:•§s¹qâ'$‰ $\J"ü+à ú¥ ò’¥‚´Ú5Р¡gq5 8ŠºÊ:F©ÀY…Ðɼ?à[ëÒj™AÂ~”Ÿúá‰CúŠ¿¤Ä>k$(Ò³órŒ‹àö%…Õ!ܽPbÂaýø{RÉéú’ÃÝd…–43+šù­øEdJœæ»Q0$$ É]秘‰Ò©:ÿN{í ±˜É‡ç›þÏx™äÆrÄ@ô¾ƒOÐÈyXk«[ümÿûoý‚ɤ.6,À€m‰ÊÊ$ƒ1€N‹MyB%ÿÈ—ô ùÐœƒüÚÃ<e˜ŸkÕY ËJr:Á…ç£e†2`ŠŽ0¾2ýÞMº)ò.¶³)?^“³ß»•bÜ‚vÇ|®Ì…k3ÃËØÂ[YF@=Òze)Éh爤
+îÍ#Ù—x oÙÝ[‚…Á\\Ap q‰S†iQ7àÀwÅh0(z¾)¢SÜŽÔ›D·@½âLàœ®ImÈ—UíÌW% óÌ2°Wk5.¤×;,裖•.^ǵ^Ž/l‡(šdGŒÙ‹S­bdzœ½œMÅV‰ºç—‹ýæ©íSèüÆ"Hز›á‘¹ ®kVÛ*Ѐ[$ƒ±¢=ðËr(•]V$K'nÝl·P ¶ÜH;²ÝR,¦ŸÕ/£¤À„„œkŠ
+$FKæ¨ê{ÃÏIÜ¥ŠïgÚör :êÄe7ðÍ—îm»Ô¬%é0Šïx¾‹ó…iŽ¢Ã‡Œ†ƒ±Ëöàñj(‹xiÙÏ%\¯µƒ’ƒQî…ŠðòZ£c¶µÇ‰/¯ØpufÉ´Á]²##³†w&#TŒ$ñÀ âƒÏaiÛòɱüÿ–~lVûTà`/áæàO¸À))æ€ðÎųl78çKÿEæ‡àH©¢ Ü„Eì%ΆGUµ˜’Îk©,·C©&Ï l©y88Ð| :Ê?âŽv®Õ|—×ço4XueÈ Pb· ¦Â¯f÷¯m†³„Ô¶œvè dŽL
+ðÄYM¾Å¥³Ÿ3a'᣹t• ÀJ÷óÊ7°&ö©Tå Åõ(>ƒb7Š¦D4.îEÁÈÙ½Éf¢úöþu‘>—%j[äÛ„‹ HJ&ˆËž-Îr“¥éym.ó”L](¨ø#b’x¢˜˜¶œ‚E§Â¤<!|Š ®çìx×…‘H•€µŒ9¬=çìMMrp›LÜ‹‚æ䬿 ©~{³~÷¢WV~þ†ºá‰[BTÁƒs ,ñä~î‡yž¬ðR-”¼}¾)ªôÛÅ5³]=üÜ¢çog²ä”IÂ0¥Ê׈üì_I\¯·ƒ¢IkðÅì¶{~¹U¸`Jt• SM¶Ÿ7³C²5¼LRE2uvvËê ¨Ž„* ØeÓÙZ9.¼dçEþ »•\¶J 6ðÇ·Ñ=¢€™NÑ&ð4‰`@qܼµ èóM.|h’=­¾dÓM‹<|A¤`c4ôx8‰’|#@`Á¡£)Bh*1ÇX0ÖÕžïnê&1!ÆÌ8œ·™ &¼’çÒ1]6À¿j4Ñ_ ý|$Ç0ª¬îªžry>bͬ(ðWC[êb‰<õ F3ûñ:I²ÇÁ
+òÓ“ü…eïšÚoÅ<PØôÐüoN®ý„°ö¥,%²x„qçì÷î4íI£Ûj”t¶<¹’’ŒÐ# ™¸þxëë18¤ërÅyeŠ(1Nk\Ä©ÐAi´D6 ü·V0¼qðtø‹í( ï KF¹Š|‚PfÒ3_‰‡0·±wkì+LÞêØzŠ@ F© ’âŠ.ä›`ý´Æ™qì¹XúÞN/jàîV/yz†^
+ë]ÚÀƒƒýGÉ4ðÏRúëqeQGRôŠj®ó ^/®\>fôr¢»'§B_æúà”¤e®\üÝ~¥u­ŽÇ¸_]Y`âxæÅ„ºÌ• r÷ÐÙXfϤP‰ »-—¥î¹+×#6*v¶–{rRòêÈ’+Ù ï=Ã9CVÑ6“ŸG¤¢Ì+´Û;Û”¡?-ûÕ+¢S:Û‹XfÈ2±älú·mÙ0¿1ïOCŽ4­N‚2ÐÒrC.AèÍì˜c^î4ùúÕÌ‘ýÈ¢.5žUöÅ‘ƒµ c ZÍy û~´8,sä´äÕ‘“¢wGN‹¾Âp‹4DjT™#{ùêiüÀñPëÅ‘8¿:²9øÊXgoýÌœ4ý»#×QÃ{€ìÈŠ‚<£„›zUK¹±Û éõ®cæŽlo~owô®Ì‘Û)¤ö±©hFæÈJ\m‹m t=uä¤æÝl“³èÕ‘Ó¢¯ŽLå*0qd9ÎÌ‘©%Üöo!õ¹#ûvÆ£‡“ãfŽ\L‹ÅIP2Íl™•"úÔ6’+n#wdÚ"!Ò®óå_Îa¬-RÄX6ñbÉt.X¦©bãzvbÉà%ÏÔøŽø83K®àæbWòëÈ,9à»%žŠOåmgnÉÍ€7®“rMÉ,™Â‹4çÞøT›=Á?‹ièîδzÅ E&bÿEˆD
+… æÙ2EÓêÏ]Ž@Q0äÇ‘ÉÁyÄ\€Œm5•ƒý”$ ÐŒ£f)^‰®X£ìÔîV0­¢”£Ë‚u•¸ ·¦—k—w¨Úí–ƒ_?ÞkôG„Á
+J—ÿ¥NxzC<ò§Š#,mxÞo>(°ÄÃêø™#=’-{"]´àWF‡dàõ÷Ø(8ëg@ÿsÑ0ÈÉVcçUóv¥¯5‡ ¤œd[8ÀörE»©\K)‚ÇIrâ[­D[q©ÝTk,Uc¹„ì[E&K‘XøJ¥ŸûVÑÉA(þ´)ÅöøwVúk· 4BãUÒés Üî¡Ø¥#.ÌêV Æ ­†ÜnÀbB)á³ÖÆsuâêù¤¾H¹{ìk.眑UÂU¢íœÃUöÈò?õ'üÛ
+⟔üŽ&"·@Cc÷ÈÏñÄÝ1{ì^Ù—Œ"JlEüM×ÈƯl^¯ý{ÝÇž7‹|>˃‹•¶Ê׳jä0êLqÎÄT¢;ÛGh]æL«Ç¤žÄjq§æLjt°')÷…]5žÀ (1ÆCÔ¬^nPø.Wبîy}IV!EÍ<Ÿ:)XŒÀÒ:E=bZ6'"È/ÂERò
+Ñ_?²¢w°w:rºõµZ}»è€Éç¾Uô"
+)·^‹–ÀÔŒdºkf‰À$Eï·ì`?ÊI¯÷o½w*ùÜ·ŠÞæ½èM`ÊÇ¢N+í©¾¨¡Ë-ö=×—”:›”ØÃ3}±7m¾ïÛOtAºãšl¿²¸–IÇïè¡»Ci!Âl~™8ââƘéËû$}I‹^õÅÇZ,Œh_j=3ñtOð6­<L4Pp5²g´º,ô‡HyÇ•¥’säƒr]•-S[Sx‰€õT`ŠMᜑgD˜G>¾*Œ’¶tNPûô‚¯
+ó^’(LRôŽöÍJ´#ÛΣú·‹Þ˜|î[Eï
+ógé…)?ÿóCpŽíN3‘a?ol{´x •QDòíQÕ?sÅ—¢àÓ«ÏùY$+)Ý”«à@†;Uv7”4p¤( ¯sú38tçJšp6ŒÛŸ"ÚƒGŸçÿ‹[ˆ•}¸æ*©œŠ¢Ó†½^%v1.hH~ý0𱕹ˢ%¶Ü¤è¯)’S€dkÈuê·"ŸŠŸcã½ÞEaú±Çã•”B0ú~cIVf;~'
+Õ›ÉN;ɬnË1y~tù€S’m4LߢbŒ~“«œuîvS‹î*Ñ%Ԫ綕«b‡¶ê²c 0'%§¬FHw¤cmÁõ¤Áß,*ÔØÜçÑ/T$EºPà}˜ùšÃ¶M“£\s8?Ba  ï*)ì¢9)²ý‘(J Fë%aˆ!Øì°7Ž½ïe7Ap QóG b?q"ö18 ½ 6ǼJÇ^“’… ½¤Íž”ì°©•Å_÷~>ù‡¨cŽ#
+ìVØAªÄßqßÖ3@.\[COÚç&RB}LÜ–TÒDí:’r¿ixªW¶KMß৿èp´£>¨°å™`õš¥±¥î>tn;q=G–¦À2C,™ÕR÷>FÞgò÷g Å]6}Ò6¤ÖûÖáIú×)H µM‹¨&¥<×LÂRˆDR­æóÁ;y‘Få£Q‚bfe"’å푧da”¯<ôw|J‡}Ø«¨×íµ¦K¼¶pÉ#Î.r„Ù•ûÿ¥32¯ìòst/Ýè>o“ƒn‘ŒÌdcSZøêxï”àŒ›ßE­eŸ!C3Α?Ûä†*wIƒ¼ÈÁ³G €¶Ë0·K—0@ØhVO5I¹ƒ<áÖƒ[‘YjmøªEÎi”^.°ñm»·Ë¹®”+Ï´x%?ÙBižS¾h×úÔàîÜì~RØl Ã7Žæÿ¡>2¯gÆURz°Ì>‚fY-ÆùËXAj}&)òOt‚\hϺ®äEˆÂö˜aD,tUBNÁ”d{3åkl¡óìלPP¼àsÞ+®.Y ŽèÏ÷kÑŠ£ÜU“¦*f14[ä£ycÛjR²À×Ȉ—HZYQ|Úþãì—Þ·‘QûÒ‡¶ðÉÆ,a+žK!ý,c4°o—æìÔ£Óc¨ò°ûS¢7LŒÿ2^.¹qÝ@]Aï¡Ç4H>ò‘ÈPÓ,Á#kêýçœ";€‰ A’Uâ§xë~tE¬sCT´ ½¥Ó}lSm˜cì éi —¡ÉaÚ¯
+¼¯­`Z}bB7—càï0GDXL¦và~iŠø‰;îà &Pày*è`œG““R w{ ‰/EŸÇ"¶*r­rEû¸²œˆ]Ç¥×\2Q§h§Æ…˜i
+„98_lu(Rëé4V6/¦0üu­`ZF/ ¶%f|Ù$XÑß6Þ`8 ?íZ äM‹‰ð·¾í^L»çT½Â?™'sÒ´®P¥“Ùs…ÞÑø8-S_ÞåI¹Ü>Œ°É¦+°>Ì´†ÿùÇKIצ¾6—˜™MtÇçÜnöý€IQ$˜ ”º}$cšòœM 
+¯ºÖ‹œ×¶§¥G4H^e«3–ŠQ˜rÿU÷KñÞX
+ö»c'¸Kß!Ím+OòXIY:—@fèÑn”kpðÃÊ ‡¢Ïßa9FBI±¸õP®ñ>qâÚÔ£Ç|©MTyÔ·9Fpˆgtz¿¦
+~<i뢈%)3Ë*b`kX2]ëÐÐQ+)"ÏUÂ(¥0‚èm” ¡ ˜k—°u=s> •÷{+½º3홫ˆ0úÆÒšcôÂ"…âzV SlG’h “pwaµÌ¡%Yë’ F{'Óª­(I ow)UŸË0`HämØk»ÄL‹Éìœ!JÊ5HµA¼æ¡Ä­ˆE#”3Ç\Mί¿
+H‰”—K’œ7„O ;ô¦‚$€XÛKß³²ï¿|(ÔUüg<rX¡®ÎI<2Ö{¨¨{úUÍ_>šk³ÑÄãë_ÍëË{·1¢[/:!fZ­4«­mHÈüÏÕu|ýù#AÚ]ÍG/e$¦½j3+"¢}†éc´ðhnAz«Åµôâ% £•áîÜçôŽ‘Wë½µcð¯Ë]„‚û‹ñj»>I^.„ÞTGÛ'½§F^QƒGÙêcÆ fnµW“„ôW©utUkÕ2ÁãUC†¶®Öùà’G—ÔAdÓüü!N—æ1ÀÕý¨)½ÖZJ¡RÕë(¼S7D›F)Åjœ“Œ7IæÖdƒ
+ÇtmUÌf/£K¯¢";ÃC·)ÑWþ€ðj5¾^ò7ø¥ç/—}’‰w-¢ôÅ
+“¥uºÍ*•[•ªM„{!¡Á¿#cí(B&IÏîºOŠ6hÅ^5ú~y£Bæ¥ó¿Ï8Ñ ;ÂÝdCŠÐ\ªDêr…|ï¾ß~üûGùúób^ªEƒ"ÿ¾b80è:²Á_9X@¬òëA_î·qa¦B‚4Lˆ#Ô…¤Rœ•!/Ö»ÔB’æóqJ탵SááLW¡}fªítÿ,}—ݵªJÖlAø—ðklu`m$Ä3óLç:tålrº»´ ç#-LÄzRõÚÈ…g,Hç_ù½œÏ•ffÆm0v Ü•á­t¦ìŠ:ýgÒuÈ>‰ÑpëµØzÑHâ­ÐÊ{ô¬Q<Ëy}½o5å‘Y£0…h×8°…W§2&üzXI#óþô(5&¯
+Òüš•Q|î[äš`£I;ôÐ
+
+Õ–TœS¯%‡ˆédc\ÎçwŒD¨?4`
+C@è>rHn}|S ·aø_"•r†iy!·"°YÒÝyUgH*u€5SËiëÐ NÃàáR`ƒ â8œLk)ð U þPþ1'§¼Ò1þ´gë4iü`cÅÿ9èrœ¦¡`Õ`Íú€>Rp;î€dÉ@Pº$ç¿ž@ J¶6ëëŽP\@Ë÷Ë´Ó7ˆµX^©ÕeÁÃ7˜6vƒèM&¯4õ&)ŠïIØëR™_—(µ7Õdö`€eŸÔÓ;¦,m –jƒ¢]ºÕ˜7œ¤ UõXnz:ý¾ÏêÈ ­ÑÜðãÊß].ÂÊÉBZî+ÓJ^°“=ãШßáÏ1ÔT·¨¯w§ ÀDþ‰X1ýéX{>ê%p»d¼œ«|7îŠ"Ïp//—Ûþ9Z©|F7Á¦Û38h]qPa<?u;qí”Zš¢NHO¡Š¡'Á""_1Ì+Ü@$ ß2®Tç90­SÔ0©Ô“BȺ÷+JcÑ4½Â°tÁFײpèšôž³¯¹Ú‰5Ý/‡„ ÛÜ1Œ˜Ž`i„hÖÃ1o$&ÕØÏ]ØbÛ4WMWŽé4˜Ï0w7G¹ªé­r Ó&xÜYYÍÇ/(fç˜/ˆj”܆ÐÉ`’P9E¿AÖ9ù¼’ èã9¡MÝÍOf{’§A ãA
+=¦m^CÇo¸)&Ë}ì¡{›¨K6Mx­K>^5û‘»e6─”ð{Ô¦¬£˜fD“™«¤r b‘23Žƒf‘d‰8[FÒšñXã‚Áëlf,ŠcGáÇR’Ø»û>ê]! 
+—p¡m¸ÂLñz™q®£?•Wî¢ä³ rºŽbþ¾ÀÈÉŽÂ1ÁÌ c^Åé=˜Ev´¸ÎoÊ5þ¬eÕ±q¯dšAöQoŠþF×û(<2¯êZã°>êÈé¶â°ÑL„׋ý¿CÈ:‘…>ˆ~Žúïã4"ÊúÉ‚BöY™ÆE„ÿ¾aX$z ãÂA–’—nL^MÃ'© Áv*Y¬¶„!!ÁI"f Bû§w"’ï‡áT¡“tósŠ„NÂvôÔ8
+L¿O]AfœŽ›ÙŽS ®Ó“n'„5Œ¾Èœìj‘>´=Ù'ak˜Ñ l§¤\?‚—$Ϩd’!8
+Ü-ã¤+˜‡rh<¸u­> pJиÜ
+&m'‡!äp´U§gø„´W65¦Ý§.Cð º8dV&hËÈßöäµ?Aää¾µLgqÃŒ¤[ÀSî7¦ü„\cÆ­Å®Ì]g¹XÇZû•ÿo¹Þôè
+áªð=Ìþ
+¥=}‡äQZCԃ݂ä4š“­ªw»#FjEÐÃÐΙòÁû²Ú:n UKÖ·ô0øR9OJ•ö5œ%„4x¨œGçE¶¡¥Áœ¤ 'D¥¤ƒ5GýõÒZS­øB®_zö H;™N½²ØRåq9HƲ…¼µìh ¤pp6 Œs—_7¹ %e³ÈÝŒ5”ý°¬–Ññb¢Ø赺1ZG2$+àW"CQ¡³LæÇaÐ>!îšvŽÆ“Ã6hbÆè}m‹€,EŽ@ýtÁ<KŽó„Òäe
+ðm1‚ÉÆ¿°~ÅÑ,P.« %veEUèg'egÁ圔ۃí81¥{uìTàœ`±Æ2ø
+·µcå| R€.W†vËTH"*³n!¢j0U™Á½–P¿°tw83ðcãtÚÀ,;ovð¾åå0‹RU+‚~Ù´ Ùœ‡Ð`À)ó4W\£.ئcvçÁû¤ŒÖÎS J<é_Âèè ›®´
+éK\)fôñ2\AøŒ«èU)A±ŸåGA´)ž'ðŒ ¸ÛÁöÝfÓv«“ï!]ò0ØW`ÖsÕKÐí3êIóc!£äGˇ@˜C‰$´Ò‡¸‚`q^ÄÒ¯Bº*£Á¹7Î:‚lT¯ÓÎf¨½5ç3…C·1„Þ8³ì‹ ïá­ªÆE_SZ÷S¶o*¥Õ@÷Ñ°ôMÑK^½ª«™Ä•GÛE™“æ’ð~ú†¾ã&a„li2¡¹õV½žpÅb³0€vð]ûÌœÑ5±é)|h‰«ø…᜴WCÍ0‰¦¾Ív “RØX«ì4ÊD#Q HõÍ„þg4ŸôŒ»;¢Ö㦦EaáÿëÁmÀ¦1Å9ORQ]t²}>ê5D’Û˜Ÿ%BÿÏw$Gê”Lè°Á E)X7wûmAø‘ô¢)¿WïêògvG¤¼¶@+ÛËèï)“Q]ÃC+DÓÊÅjõôöX0%ý\ZÇà¨0Zž¦ñkmLKî_æ¼ØºBÌþZ¢ áþio~-Pi\\=N1Ö¡®Ó}©iª©"-ÆjîÆ~‚¡!cXˆeÇéÁÀIa¥9g‹àYÔœDÇ'dZã/jƒéž}¥Ëû&âšú›~Зüæ w 2‡´çÕxqÑò®¯)jJ쯻I²Ù-7íN=C‘ òOŽuÒ‡Ž³£.²| ‚t37úÌéUà+=ÂaB‹²Ä2[éÔ’‰ä;
+ÿ6Üh # ä>WAç`HZ=Z´< VÞˆµÛú¤ÖÂßø7„°O‘8?ñ#[]QÀ Ÿ„íu5SZN÷½J2AHÛ¦“×®ÚüTÊc !
+Ôé–·š÷Ž2|h4|»ØŠªñ
+‡
+ó&–‡fÇH1ð'Üì´ÄÓ²4Lò©w±mχ’ºlf’´æÀbî-È3Ô“Ë%(ˆ—â3¨Eö­@?kàlIñKú-Þ#“¥/º‹ J9e™ÇYÙæjB„¤#wåÓ‘9Œ }Œ«°C<ì-ŸÙABv.ÚA®Ÿóšäõe~:Åd—L¨6²-õÞ‚“œ/ce
+>‡To¯Bhô†ÙÕ¨7BŽ‘n ã-¤< %ÁC†fËÂ/A1èÚ=QZ c—ñí ’ ©T-¾ã\cÖÈL&NZÊà-ŸÓÖK˜5ÎkÈë:`AüB:àÜ
+,F°OƒJý™xZcZ}ÖÙ ¶=ï‹ArÈÚ€¯q`ž ª1 T8ùUègSß<>[‹Sl¹iËCøs9l:ZBAº:ÂWU-:ZQ˜âpFž3Á -4²¾™qX|YPîÕ) õåMÈ,ûùãtaÎÿ “ÆœuóìŒþÃxyIrQÔú0t@‹óòH/xåúåû@¢c»*+fbuo6DâçÏ ¾~»ErH´´³ nléZPûA/!RVá§Ew²üþLûè :A‰ö ïÜj]1†q‚$ⶹÔÀM5 $R¥$°%Ú‡ &Ú ‹Ô—+ŠÊí¥0†ááÍçY…O`ì)
+V*'âÜy•3€‹mÅütÂ%¹c‹Šx¯zç­Ó.’Œ– G„fë ¥¾]BN| ž‡«!ûü<P†‡pe¹œ­p*ñâÑìȉy™HN¾Ö¡å£êH!ØGݘ£=VüÚ°±¿3ï†ÎÆ€§Ïá«hÉ i¯ØG-žŽ¶`˜4ˆF„h±¿ˆNq&Øw—ðGÉX%»Îä`[±™XjL ÍéÎ*QÍ‚X¶³¨£Ò£î’,ŸA¾LÙž³@gƒ×!Ež -e?ìŸíT œ sWÜP åŒ/|
+‹h=ËÀu†T{¹Û‡õH01ðá
+2i¼ðGOÛ*J5qüèˆ+h¬‹Ú*K”·yÃ£î ‰}W
+)€£ÑLˆÞ»Q~uÁltFa$ëݵ1YïÖ¶Žö±–; ¨ðs˜¹ƒÅ†B+P´Wa[q8%{«.¸TnúN;·uxgø”LPÃ9ÍGF¬½‚®fÐ.ÁÈ¡ØQC„¼h%+Èû[Q`ŒÃÚ„-îÅg}Ô“u3 tÙýcœ¢¬X¡áó©K ‰¯äﶲ_j=×½Îu¸yª(ŠÇLmcw㈌7 iÐ)åሠՀ ž¨!¯üÚsyå« _®ºòFvK>Ñ÷ ‚ ‹ ³ÎÄîL_ Ó'È{MyTE~Ó\Q
+ˆ0 Ÿ¶n#aÀu`öâ:p–cíÛ$EHœ‰&bÖ‡éû(ÙÓ‡£Àc­™ÖÁ(ÑqÒNMÅ=MÐu­ÓÞí»Ý*È}ŠZ#£»Ý /%šÚEÒn@…¾šÆ¯Æ‡—
+¯$5‘ä§7|¾x@H§üS¢EÅÅMÀG$ú0ûȇ nø£ˆß¸=Îp$Çi¾HŸÄMÜo9cü9 NÉüÝ™ý,c½S‡Á_
+¸ß§[Á9$?DBŠïw'Éê&l%$X›Ûcø¿3ÇäžÞJ¨ˆ2O\܇‹'¤EcdI]ÜÀédÔáÛjïà Šm(ˆÎm#¯(ö4è2
+ßÉ”-¦Ó²2ä’‰°Žmø½/ÃÄ ÌZöŠþq‹Ê" ÂT‘ʯ¢Æ|2½uÆâçEÎv",Á“Åùã¢ði«%òì¶].ô&†W\Ô&bEòb%éþã5óZôßO:þŽb îÇp&¦"Žž\§áÖ|D1U
+nKJ«ä#šÏÜ'á”1†rOµø9æ³V«ûäK)ù!£?}à@õÏ:p¨ ì€H%2#F€ëâ˜
+8ê³™²; ÷’;÷{5ŸtErÂWgóÒ˜®T¤ÈøyžÁwÃj ö¢ìÈSó\µ,…ƒ°©©ž7×CÁÙP
+N„áEzc¦ dU;³a±kì
+T!ÙK”è'ÕL*Š}‡ „t…•@C‚;ÂÁˆ@ÇKÕv‰œ$Ì nèw>ë eÈBX^W^Ò:´$Ûñ_W–¼¬Õ+KRD°`.lè~óˆ‚Þõiá)i cÙ†ž0aeX#r”hêP?Ì 91`øºÉ¸2ßÄzyn““þBÖm‡¯Ê!R`Ruš(P% ï0³ÄÆ׊1à/  e%ŽêK‹Ži5Žªà¯£º0ÑþÌL©p8¬™‚$›±$3/™ÚNÞ>,Z3dMÇö¹qÐÚ÷Ço¦ÀŒ
+l¡â™m‹=FSŽ€겸MP¤É€ÇK¸Û±ó`°1†&ñÕ)èß'áWqêÐ k S²fD4Ÿ^„> “Üâ0F5{Ùܵ_EQŒÁ;bR æ)1•UÒ¼åCzfgãQ©#ê$%,Ià†½dÁ´TéªC”p3"%Yi!Ƕ-ä ]^¶K±z<ª]*ü¤ÜdÃ=´ñæ3@fɯ~¾ƒòS¤ dß»%Òîƒ}‚>Óö6cÅ'ƒEì„‚cÌÐ
++¼ e»î/nY
+`Ú2".‚,K½Qx%ù+n@v„9[mâÊ!p ;O(àS©­âð{†±¤
+H±(¾á"n“ãúPÕE `m¯Ã&Dy‹¥}ó¢cÞCáâóÛm±”¦±¾ÈÃZû0>Ðèxý%ºbù”PZ›~ E"2xýÜG®U’•xºL?KVûìšèŠí<OßT«Áóµ0poåG܆VMXCprà¶<l@öq\Ý wR&³ãÝ´ÂoLLCë¤f'+Òó.‡AÛu!& Êv9â
+ÀèL/?ÅQ
+âÈ6­C2I!…€ÖäbTÂê%“¥oqæe°HI'zÔOèßу­îhœ6â$„`*ÒÎÜbh
+|ºÖscú¨+bºRÀ‘FŠ„õµò¦ÆÁEÐKõZ„Åá‘@×äWÆg`pìÙn¹D­IÒSV=¦ùÊœ*R8[ŠFîàŸÅgŠ<ÆÁ«ÙA+Èá4dìŠ%}bUú㾿VüãðKøiµkžÿþPÌÿ"WlË<_}Ä:éAÿ¸`DºÀ
+†âã—ĸŠQnvÑ ³Ñfr›Øõeœrg²=ö/aù
+Fì0*ûq³B€\+'zA†¼¤AÔÔ‰†bU ¾–Ô‡½™P2‰Xð"Ë—eù¼ê‡)ècÎóIQ²¬1nÎËbyÛò¥ƒ"É}Cª—ßÍŽDl8Š‰8©Ñ¹)
+(Ñ@.Úx‚z`#–Cd¤üåYZ®†î{ Sá«â;GˆM¶OMÎrë4Œ5÷&cÃƺK€E÷ýÖ®^Üv‹a}Fš¨y‚ ÎÛÄðÃQN£H¬âÙ]$ €Áb&šUІ1/%w/ôò‰b3¶žŠ£`À¹Ä—Õ+t’Ô‘ ÐWÎ¥álÐ>i"ÐWQ7gÌ’”á™ý´ˆ Ë æ—Š'ºÿþíRS¶ŽiúCïó^Ãåy”똷“¨X‚.Îê›
+üÊHŠ²QâÑ›€ÇxX_È‹MÛi¦‚UV
+ñÍW7?Ý@ã’R
+¨¡÷ ‚ÿNú`ÙQa6¥ù}¹ì†_[ãs¨PršLï"—ÈAŽƒ4õ¼p¼üÓ±ts¯dkÛîNvaE®œ%íc
+0·8Qfg?w_.¢¸\OQ]É9ú”ÔÍ U‘¢{ û$gt0k¬$kÖ⺭©gòë¹W#ÈK,^r´]…a€å_ M¼ œ¤°å’c
+„—µÚj91vü ŽèÝ>àæmåR¬õW3G €…÷¡Ðåò>0=t4Í5Û¥äû·¿ÙÇßHJãQKjDþK‡¥ÅŠ|ü¼W;<¬#)Qk³Ìá~PI HKÄí%ÖL¸47‚/ô€™¥À|wˆ–Yø
+šm)!mš1¡88R’êP¡«*NAÅ$ôt¶5eçÐP“
+'Š`*(;g‹Íwé6ö­`* °¸–0=9lÎÞ¯zÉ+Ash¬‰,%<¸É"â NIã­•<ŠQn¿¢ãܸhj|ÅuBƇ˜£”¸Æ9Mü‡×,¢ìvMBŸýÌ3‡œÎN±ñXœÂšA:W°Nô +º§ee+¹–k>*š0”"Ç TbΩ]Frô\À},o %pänºýk˜öšÄûæÈ÷¨),B
+f|ƒ—TÑìôÅ´i ç]ƒ’sU‘ºïˆ)ëÃ9Y_T!¼^Á
+Æ¿\Vð€‡Nõ|i8n={ØK9‰%É7~À{àu9c $ɼ•æ”«X[ O'[¸cÙ¤¯â{
+©OÿòTÑ-úŽ·=Ø1åf=
+PRdNTè^å©‘o%®êƒd€óßÎ*sðI¬ãâ«\0¬ŒÍa£ZÿÔ@2Q[;öhwTÐüд¦!̈”q9 ½g2ü‰è²²U°@°¯æ]Ë<`ê÷„õØv +0?ØÙÎÁ•2Š™l—7N&âký»åfÖ’׊ Iã)˜àš~ÕRŽáêÞ¶U
+À8#ìçÌÕ •½—« ‰<Ð懊‡Ó{±µ²¥eß\Ï9“@IZ%ºå®U¦ƒ5jõ4xé¤%\O
+ÃQà$ln÷sæ”Zni0*ßšF¹N™%Ã`N±òÀ°„°“6–ŒvoY†í7a‡€BÉÓaaÍ
+Rfd_L™™°¹Œ Ä£Š‚ËmG!Ó
+eRlD÷Ö@–€›Ÿ‚{Ó³f¡«v?žœ·osä½^رM|šP\—M†¼Dk&!˜ýf‘gQ/$!nËgšàPÜ]G^×Cw’¶òÎÜS¾zñ¿bØÿàí3Þ~o6ÓËõUæßWœ>……µk°oKUÜòKR&©=Êâ¹L(ol#J•tZŠ4±2k{´‘ß”Ù(†bÕB´CȹBÃú× 9[Κ–€ ÖûØ%R”Bh×¢YIÕ=8YHÙ£ì–_I Áû\?C0©rݵKÀÌ“
+
+î­j£[CÜÁö’Ém;\>ñMg"nM3XbJ¸’¿! å
+ •<È?¬éäE†'/³ìÅYoÒ½ÕŸÁSxÒ,Ýn»†ùU­‘eÆ"O'ó` {Zƒâvë T3ù!í;´$£!Á¾^±1)ÉBQ2F®õ¯ˆ‰Î2vg!X)øX˜’ST±Ð»¸L¥™@…ó˜îBñ262 î^&ý! Wù“sÕc‡óo…?èRm‡Å£uà&õu^B"–1ËCÙÐ*ÿ$­%ÇænÁ$ÄÏ`âsŒ×ª©Ï^MðC%ÿðUF7!»8›tÇH«‰¶¤)걑ß̼Í»†³2šM¢<§óÄ·™]ËÍ”N‚Ø%X+ᇠz¹6çÛš2Àøã¸ö÷=Ž%è ÿ­RÒ³ÝËDŒôÞ­^¦øj°ýƒß+ì5pmŠþ„E¨±¥ï ^&
+N‹BK\ô¼®ýFí°;øU9²1j}/»)ã~®SŸ’ìòj?+ÊD|BFUòlä÷¢~ÒíW“—»Z¨Ð.ÎTs
+å|ÒL6˜°3¢[<”eÖÐ@Ü]Âàm³±E°5€R’½gBdTIj¤Å€5ñ/'_D€‰K.ø:Jä¤À¬´¡8QqÉ ÝJPFhê¼ø Öò¨kŸ«
+w0áÞv?»Š®»ÒÖ¹ˆŽL¢\P.•A˜HÌ€(å…“åÀ&b®¼1}ˆ Ó­¼†_¤Vb£ÞY~Ë}US8&1¦ï„hC¯@cç ä‰Ö$¸Wn[o•þ¢Ò§DãÆ¥-´¯ßƾ³*ÿg¼\rô¸u(¼ï¡WÐÐ[Ô8fwäìšïP”WéÇ5‚ q7-©ÈÃóXå|dlÙ• 2üˆÚåT‘4\¯Jø5^º6¾?Î ÆrN¼ï^"d1r>pÄW½Šê7ÊRŒZâ"6D{Ó‚z`Öƒã;ný«êºS•mˆQ%°‰£YÂW$-4ñƒ… Ë–•ŽˆœP—VEÍx‘­+ü%Žt¼(ÆéíV¤e@ÖÆDÀؽóšÕJ÷6gGºæŠð3ب(A”²zÕS\¥ø”à“ŒoµóUÖ€?›¿™âµáxO˜hŒ<¯LA 1T÷U/ÆA:Ÿ\ä›_õâ-F…PÑ2„tµýa`Ù~ 2z0Å‹D
+cÚƒîäͳO*Æå"×s`ä!þ€ÒOÄÔT» |ó¶Þý{ §)>,W‘?àÀ}‚Û:Ã$<j|Ó ûÎO™d™\ÄáX¶&[“tLÜĪ<M‚f6RÝXâÌ
+¢Q¢¨3_ìg“‘~"‡è«Å9L‡¸‰×a™UâßTz`”° ` t¡±µi†›™«ÅW±¤D0¤„$"²`ÿN
+Áò×6áË©’)ÙÙ@Šó›•1P@zî«
+ÉlD¯çÓË‚Q Ð0"C–€Ž®7ïÈÂé‹}÷
+È/+
+¦ ¯ ÒrþÎ4SÑ=¯Bψ9´o@8ÐþwYjú¦°ÈâÄ9£&ú§Ô§‰‘Øcg/ç1Ð ²ú4Ñu†Û®¹Æ{q’xtÂvZ±4öfóEïl$Ip*õ`7É+N?X*…ÝáhOBþ
+€cd‹Fj‘fê¬ÒU·»žÁψ13¶Z"ÄIw´ÓrŽ?[ƒqK¨zDA©—i–@7l‚ ³aâ)R„¦±ªe;.6?,ƒÜâ£ø¸B»Š+¨‚é¤í[—’­ÑMwáÝ°¢å~ªJÂbÕ/¦× eói.Ò¨tß9ÅÓBÒLJh@Ѫ¸Òg$\º‹+jÍÍe4Uc I¿‘Ò»}-7/,~k1N? l³ó¨B r[µGsR¼Q®͹ì  nrH§;%>
+ø”qUž†¦dOÛz/a“1|³T­y]v[?M# ÑB4öMi ì}´o˜pøVûTRÝARSŽ=™,dm2µ1*ÀÆÊv9¿M*Ô‚O­¦È«|(ñU<Œ+€ƒrAބLjyÔ´ Ø”'lë¸Ï›¾¤q@Œ*Ll?žþñaWæ“þ½w—i–ïÑ¥¿dSŒš]Š~zQãÑ3Kãz|8»‚UîYÃøRIUí2a‡þ~ï %°< \ÿZ;€­9,]}øµ¨ 2²C¼áÃ9ìûÍåRßk+™%¬—_þ,BµabZ_þ.š²XsVÛ/C=Jƒø¾ÆC‰3±è Ãë%ꎾƒã²Q}¼¹Ôa8£E'S°uaç3¼ šŸ»¢¾¡¤… —­·™J8Д†8¬G¸
+댃FŠ˜SKƒx Ý©c‚ãŒ0ÓN×9ÄÎ.ÔI
+cܬYÎδO.®ßÒYàÁm·Š£Kq“¸Ÿye\|^¶›|ÿ«"^;d%» b‰@Uå“~¹¨¢
+×lF,á\vIÏçÁ9CŠ´2ÏxTˆÃZ:J°!&Äàò4 <¡i‚E¾rNÛK'ðW z“”³aEÔY#%M©ÌRrÚÜeÄHœÎä(ìádâèOÿP¢æ‰ÏÄÿqÕ»±w߆9›Îb.%¸…“|—¨w,"M®ããUú Í×Wo ¶Ïüñ2IŽ#W‚è xž€†ˆµþRçèUéþÛÿˆ¤µ2£¬iê…Lí cð6ÀÑÍ!UiùÄAET
+EAH,Þbï}& œjCsk5¦l“ÁHLI¶ðž›(þ
+¿èz…šob8a¦iwÜ”’*g~Ê'ë"‡°Îƒï®Vœ
+“äƒæãzt»%´d‹Mg_*¡%;„Í`
+È–XȪG8±a§Ý*¹ZŒ%sEÜõC°k+î:‡0Ì„‡+Ê ’Uضï–ówæ
+]§ë@0 ììÖ‚ Á ñ8‡çÞnG½$Ÿº2òëÇ@™ÚÔÊq[˜¬¶°¢|üðÐÉÿã„-Ï[ÂÅ' €|ôŠ G MÅLIÒ³âs°G}:eõ'#w8Aøº–ý kÄ#_§@&Uñ±]ü€Œ `nºS›„>vF‹ç$:šÔò€•žåC$›¤™ÐïT) åÍEN^S]NÉgþ¤v£Ä
+M¿GgyY>âHôd‰¤ÈüçVˆ’ç]¬ÄV˜:`fÄ?¥ìtw´ªçP˲-è\mÎüwu¸a^o0 oh "á-²2¼•,Fà\²1p¹ÔÎ*=Ã18ªÒLŠ3Î=$Dq¼xKÓ ‡b®ßA궎`Š×-ç#3Ó¯ñ, ,mD¿érÍD(­‡?†Æk/Å\å $cl¡dDgùÔДŽ}œYäá (Uçh8¥Ðx(œ^ç°˜X:œó<¯Ú:2EµÒ‚Õ¥—Úg+$]T¹ ×%eæ‘ñ)fSˆ"Þ4ZßÄœC>;‘DÕ²èeÑòÖ«p%0e\}y„éù 9g|
+ÑÕ†5%½€mÌU¤ËÎWß1Hï@Ê´þlÏùè'fÊó%Sn=7µêw¦Õ–C3Œ6AˆÊ_|dûöÍðe¦¶óhþÿ”ÈC~nœ±¿˜P)Ò)ý€údžç•]ô`âÓTö Û”Ö%1Ýe¿é=j Qšó Ó,öÛ´ueQT‚¸P¤éŠ2Ip_Ú="_øÄÆÖñÖJ[MC}áìÜœ©ùbR".W„ô¨dìVgå‡eÀw¶…,úW)â%ÎÇgl6‡Ð #{É«_ÿ|ÌÄk§xj¿Í?ÉòÀé´"þ‰@à ®FI3ÌóùûC{Ïš†Ï·Ÿ‚î×½~ò¦ßzzpÖÍóôBté*¤L‹õ
+QDÞüŸâÏIbt¬UÞ¿ÚœŽ¼V?¶%Y˜È„ ™bŠˆ¦Òw EtB; ‡ ̘ô¶Jó•Ì
+'2îä A`´*®¥ÕÇZ§í [B8iŠn‚ŒáT|^@;º÷ߔڠU,XÓ9D¬×ïØ“Do#Ÿ ÎuC:|=yöé(s¥E˜çª)oS­OÅ §XTÑ Ã_t]d&¹q{A¤†xSD}}ŽÉƒÅÖdKæ ®š06üLD›÷Bç y·¢X3ÓÉòuô‰ˆ ßK¡ u;­÷°ƒnÏû«Ö·LQ6Qñ*àĶ ÏxtŠ³èËB¥ž®ÏÆ÷aòˆ\8`‰N˜V~E$üë#
+ò3æ‹É°jÔX»º7Š¡S…žä»[•0¡£)‚hÿÙd–oŠ™'rX>›À¼+ÞЪbIhß"íÐ9ü†‘M^W‰»*Üø‡Æì R°Èƒ§†^â1{’+oͯÊ|N*›]S£" Y‘L0‰8ýÆ|1*,IlñÒ€†rgÙõ¥ÔG”£ŽÙÞÐuú‹ø_?Ñ«-kÞ„§JBÜ Wý AJc‹)
+i£-a
+>iJPìõ`
+PæïU*¬Údî\EùâÊ"9 ÒXžzÚÔ9iÁrü58ŒÁ¯´Övþ}m†É¨¬áÍfÚõå¨kò« %di/«Ÿ£Ð¸Ö6úmŸ ñ#ªAròÉ‚zq‰¼ÓêÁ†fŠ(†–+
+?Ödœd¿ÞœƒP•†™X‘7¿Øò—®b3E‚Uf¦†!@ ¦U×à {|— ÄÇQY‹Ÿ@žŸn% ÷FgCeÌÐ ©øÈñ`0]C³$3íÞ›™~5m´7ŽeŒ3Ú|Lm2ùÐmï¢éZ]Ì·rmçÉ$‘Ê/Ø’êÀ.£ACUùWž~âÎDŠ¯|úÚ$G^­Y‡´®¥ÉØ1¾ ¹9tª¬0DZÍK#ãd%#@y3._§Ø»4dþÝ Éà^ÜÔ1`‘Dü5\ XwÄ€Jä+ò2S s@Cå0êy-/£/i-z°ïZX'ŠUãc¨ýPxB}Úá_ yPò?°†ä7—p§öMÌså¿É0®kÐe´ª|±úT±_¬IEDå•¡”p0ZÔ7‚4ÆU×o*Á2¥„}亨IØ·›ÕïñDÍ°‚çÏF¡‡ c‰¹FO&©œš3­èÊ-è%Pe[¶sSVËðí?Æäoµ;0‚`šª\ªÞäšÇ0»SNë ¤bÃ:b?`!Mg
+æÜóº×“ꔊТ.oçjâýWDÉÈY¢ç˜ïksþŠÅßA0ûv-×/E¤×Ïø’üÖç+ñ€ýbSÕV`X•|ÿ²F¸¸Ðt¬Ì5n&ÐÌž¹OÛÄ‹‘AÍb݈>¡§cjUá×âØ|ïéÞ(ݽ{1ý
+µŒÌøñã£Ð ówžw†Þ÷Usî_À¯íD¦Ü_éë·#?=F£u¤žõ¨î(.6æÖįÅÄÃÄÐ&„à£ëíßokF§Ñ$ZZmûzý¢ VKT!xôs‹×ôþ^¥¢g šœ.Ó˜¾ ¿ÿ¤h‡çëû½¢Q%þ™@+_/E^ÃgðpdI·¬ÜxNŠd¸¡Ðá#MNhŒqïáô}’:{w
+¤Ú’mýéß8¦+ ýÏm¯0l§-KÿJƤ_“G¹Ýü"ôŒJû±ºÍ5Î =f挩nÇó%£‹;Û¶$¬‰`›ŽPfs”œ{š@Ò’1_°\ÚQKɵ_åÄ&N¹î5ŸØc»ú™”×V´ ˆÖH<¼•kEn P}’d•-šSÒç%IVþÎ]b¾È¶œ•¯÷¼»áQ–iµGu²R)Ñgõ2>Õ$Aä!Í
+/uù}œw±ƒÁoûU[}— æ}î},¨ÂnrÍÚÎö'Kêc?Ÿ/¹WþèyûWmŸ8aº5ÇTyï
+ã½+ѮӪQK’š’;‘ÅZqð“Eeèn‰”Ïwh³ÿ´!‘½¹{´VjMè(z׿Sæ’£CÁE‡-Î(Ц©íñ*“Š¹°ømM91dúËwÕLÚ_°{”'œÿüsq>WõÊćù1·ãÓmåMÀ2’c‹Ú?ŽRÄËñ3ǘv´¤‘K¼x"7æk§ËýlÍÅq
+žß÷@v±]¸Q%¹î1‘眂^)£µ½,»ÿ¢Ô÷j€½þPòÍ>.j°F,?áhëxi´˜¨}öÎJÉÄÜ–%¶¿•ŒÞcd[WŽõ9öe@Ž™ìîsËàÆ.Ñ„ïI×ÙSb¯ ƒá°(8sºx¾ÉQ"Ö1Vïc…#QåÆc ¼ló+0ç(wÜ_’9 ªÞ´@^lý%Àp&Ï–OzIxJ¤øó+P%2èûYà;S²Iu¦Ã˜Ô7x4É%­]ã>º×Y4gßÇTC,nÞÀ è>Oç«Z㢑3*m{#dΧ‡cµ9Ð,sžÞpÒ+ÿ“Û4½Žy­Âp
+ˆõf0Å8õ³âlvØ“¯Ùâ”n%
+ÓæÚߊ# ^)a"Ì^,ÙgªüvÛñ%LpÄ!¡ú%GØcãrNÜ™#Mß&ÌÍÖ ü¤5J(ì•ÕÆ~/É'/ùvTçÆ «¢o!íÏñ5V+¹Û›äöÝàøährt“*4u¼\‡=Ú¼*¨«’Öþâ÷ïM›/×IîÀtY‘YtÆSŊΚfK
+Ë,s ñ>’›ñ @¡ëc¬_÷;úi`–°*=i†‹LI„®œø;éoQ2>õ©ÏsÈÃA¢÷ã½Í÷Wqf»æ ³óÕ£Ëß[Çm~*F¤#~¶öüˆO·“ä³ÛÙvYå-anJd4‰'†´QâV-ƒ Ü󾜞ÚãÊîAŒQ€N%vÖãvƒ¦ðË1×æoþ+À
+H‰Œ—Knœ9„O ;èS`>øZ»—}‹zå¹ÿv¾ ù hØnØîR“ÌGD¤»›µáŸY_-{ÎêÓZôñùïùòæV¼õêÑ>ÿû¨~>mòAæÙÈÙ,jŸ:§&Çt›£ŒæRúðR²´ºBUíQÓÂæ†fZá3ú•£µ°2Ç°¬ÅkÆÈV‰Å-uN¶,Õ²XÚ6dTâ˜eë±Be%f+á^›mHoÖ¬[|í„J>à¬n}ƒ¿lô1Z¶uNzZåâcÎs›Ú IàŠVóHw'¸Õ™'Ô÷ûØ«—ô2-‚[|þýñÏGÚ‹ì%ù¬Å8A°Âcg!;­•bŸÿ»Ú|õu–ÆëzrVúkL/ÝW¦jÿSÐ÷p¿ÿäNëê—³¨[u–Òl®««Ü4ÅõÅ. ¿¯ \9otZf Ê«S̳ûheü1è=Üå}z« RsÍ
+—ÎÎâÃNkÑ Ó‡ë¤‚–ÔSOƒ¢Ä.3ë¥rÓÍni ý&ìn”ÖŸW5GˆC{Åi?ø<­„1¬sìÕÉa­–º!¹ ¼Ñýˆ:‹’óÀv^õ
+„Ó2RêçœNÓóv«>ÿ$ V›£^ó‡NArÌUt¦è”ªÀ'…Þ×Q‚ѹL­ž gT§=LW&¹B9ùìÚ~ß «ý"Æ@¯¹¡Û¸Ÿ“šfhÈÆ—BϤé•e[
+¥Äl“î;‘"OwZ¯åD¢Nˆ&iJþ<j¤U6Q¼ ¸”~Šöé ëW¢ Cßèa<w‡z#”~Â$ðÿ­Po´õMéoôd«jDèŒz˜âEÕ£­èdìóÆÅñ*¸ÓºrWÈ7Nÿý—MÿÎg z§|¥±¾&sU’0c›þñOt™L•º€Ö¬ó¬!!ÂHjØ(.Ô±º'Æ-¬ä8‘(Dx×ÏÜ­*9|ZN¤AóS Ž¦c¢£i<V°s4ŠÚMõ(‡Šy c»úu²L' M_ÄÑ´’"ÊÖ9ëÝΕç¡Œ*W+‘¤y ätfÒcçÂüdšñ&®¡PM >HÄPµ7†~ -dgu d†µ)s͙؋q_
+0kÅõ®
+ðSy?Íò€õ¯.‡$T r_Ükˆ:GŽË…·eУÑRæ¥=¯¢}ÄÑs½ª * |ϯ¶rhH+&ggG ¡Ð ; Öøq
+]~l6˜”†u°4H.–}bQ¶Ôµê  O%eM²v¥œÜ#C×x
+E¯S;¬¼Ah Ž6­Ž
+EbdYìhÇ-9ÿ«3}³Ì¦Âgí"›Î¶C÷Ð7È»¯½‚0æ³PÌfý¼Ý+>”<
+ÑG\_…çïÆ/¦|”GW™ù¦U«>kz´¦h”?j[eùˆ¸µe$íhÚ¥JMI. <ªÕƬ®Ú힀h™Œ¢Ê B/Ôûðm]{xŽ6‚Pd?¯ Ù¡/Ë‚ èM oÌë9…bÖ¡R¢ÇaA(8¿éÝ *òU„[-×bC­¡äô@R',…^"ÎÊ%œ ƒ6/­ÑPj¶·s$Òx ì(ò_žsĘ1H¤S‚â
+<¨„–Ò<|ü¶
+ªê‘&þ‡sh{oÑ€ß ¤2ŠÇB~]#¡¾ØI”ÜÎËßA]lW¦–׌°¨±4ù¬9ÈzaÌØ\>$ •cø™—ßë[¨æ A‚W ³àåxlZ£Òä
+n™ÏBÊöÁÚàY×9ø$d¢±Òͳ aÄ àc[lL%·AŒ¿_¨Ó ”<£Ù5bÔ—6íçœÉ<@ˆݳéÈ'aVHóƒ`­À‚³½Z°¸¢ÎTß¿Ö¥A~}üóaŸ}­Ë9 ·ߦAÎcy Oýßãò«¶žVÖh±â‘B%°
+1dÑbE~yó~°¶jÊ*A«ŒY–kíÄ¿Ü«—ža…ˆpš®6/ż’µ‚<™ö:¸‘kJ\“/Z•†>O’ï’CEÉwªÙn?ðe Â\G­j¾8hJ»¤ Snã¼xÖŒ¢Ô‘+ì;Ãèf"ŠL¡9=ç ΃ó!4 ÓÔî'#ÀÄdTAúçu°é¼aåÎl(ÁáC·"ÕGN˜·«Ö9ëÛØ25&&¥ínBd<¸èy/Ó**ÍxTœ …GÀd#{Vý B9]À;pu­ÙâWR ÀúÓ"ù¶ûÎ×n(×ø0€27%øDYKÖøyÓ8&á+|”Ð9úˆÎ ³e—0Ð 1¤quŠ )±¼V»h
+ýc>œ…ÎÓbÑý6“ÜàñZ絟FŠŠ&E©.S¿1w?Ï°”fTi<Aù&@Ìyð
+ÄÀ%5‡¢rÁ·‰“cÊ%„¡ÎðIgÚÍ*3p‹dfK°üÇ7Ãæ/”H^œû·[­U8?µ Âb¥ &E×iÐ6ð`ŒÕiT7ðW`ŽŒ4@n˜‚à@Ž˜WI4„®ñçZ[A¬F
+zRVŒ(öRÆÚ\ðƒfð|í VÄ7n¡¹ê¼wª0<|Óv_=–ɵ,Ê嚢… ø³Ç Z™mìþÔ,Nwe­áö¥ªë:Ä}¥¦h¤ªã1ÕRSµ@,Â6 ?Áã[El×ýÆ-AC-¤Q0Mb¬¿.F(”~àÅ–šb8åê»D<w(äÉr:kàËç*_ìÄt4(aÂ-mE}F
+8£:’¨[¾Eq·œÖND`~qDÙ|M º‡ {Êá:p ¸‰,{jªÞUä\an+{“XG5öý`<$M~ºg8œ*s÷ÕO6…e³ê÷JI[23T™ê—Š“ˆùû4ƒæH¬8w+“.uÓæ!&.íE r æ8Ô­$¡B‡„ÊÛ™Ò«rY?©zÑ£xìv? ã
+ƒÅ‚úVêw»¯øçq6ÓGÓeHðÒì%O;‹ÉºNE–Ð…Æ\·»À®5¢ìP|&Ý 0Ò
+8°rgŸÌ•,ÕŒ û,Õ1™ùl…jÁëû™¶ÏyšŠ¸®0 $×áY€7Ÿqêy¤Ï¢gõmä£âx¼J°nD.ðw¥º(
+f0‚X‚U”±ŸRøž H‘t‹ßaî#gs&oìÝÉ Äà·8åö¤¸ŸÎ4ÁÞý®Aièb¥É}:›T¨Ø¯’èÊè¬cr¤JèA@LH™åL%Í´%q w$I¼ÀÁU|«èq»sÊ}8¶)—©Bý
+ÎœGæØ%ÞVUÇfñ?{ÕæÛ­TÞGƂǦeCGg«c&ÜšÅ$¼p¶‘©º†i'+ÓW‘öîPø¥ÈŠÆŒ[QR˜ßË”LJ¦§×ŸÈr‘¨/ÖÁæR!–Ã}\| Ác à—Þ0þŸ[Õ¬U‚Ýï­
+ì>¦A‡Ð[³ÞB'ÓwÒ«|¿Ñ2ØÖXny†¤ð w°cPÒ‘ì’ê—‰kMVwÆu… ºJÀvN€ûr•¹•Üvïºm &'ûU(t.sH¸xÆhæï/Jð×Éhˆí¥ÿ¼ýñß·ðþŸÿ½ýñï—G;‘rÛ‹ð G>`2F?Œ÷ŸÇ"ÔHåY°;DnIÇZk`òä)Jð„Ìx’}ë,ÑÚ ² îïV—©©úˆÀèeø°UC
+𤓹_ø¹ä¡S{«§¢¤ç
++É‘KCyw‰ MÎ#­’„q™”î¹øR²îmÀ*D¬@>®Óè N¿QØ 'VŒ¦r’fIC󢎱Æ}à$áÇ¿ÌdA‘qà¦{a¢äKà`ç2¬G^ xÁkó2Ù
+ ¦gòË>?+œ£Ù8nŽ{«_H,¾‡ÍwnÆ ð·¶\ëñ ¾o¾ßAÞµ!GOóX|GÒ†2÷]
+õsŠÜ¸ÄurÚ¸¡oH^·chA,·³}rzT&2çgO¬Õh‹Ì}ôåÉjŠîä ^ü*Þ1oo&X`<¥,r+—y눂MÿÌ{7ç0“owré> K§¨‹‰’Ž•9ÓhtþhSÇ>9²©íB¤¤>[óA
+¼à tÄp„©]äÃ-äÅ.Òˆ@@B¤c3Y¦©6»*$M ×b[œ"î„&)…›Ëð¼.)¬’ctã‘ÓµùƒŒËæñÃÍ®_ÛjÚº‚íçp’vœµgÿ¸ § …ÆO VÇ»l逞ØÙî#Ð36º kl„¹•áì¶Ð¬c$‡â¦FA˜™ð´%쌗´ªŸ2{;KÚ¢S¥Ü:þ׃¬­ü¥G<!ö¶Næ ‡aÅËü75:u¸§Fòô5Ú‰Áy&ϱê—Ô¨K‘£2u£<-œ¯G?«¹Jˆž¢®{—9…šNåEKA8 ¥ ´`vS#nHñ)`ªÅO¥2ÖI¨ÜÉ—ÔaŸÞ½Û±¼×ÔèBî©Ñ9T¯u¼)´Œ)~ rÚï¹ÝG gjü]7–¼ØKbÈ( t%ù©±”âdX«—äF!^«nñË´.at)ìxC"¢eSë"ã´™»£®)·Ë=4‚ ‹™ý|4äé8´b>¼Ì_ÂKÐ’›Ð÷Ì(6Œè€(äègFä5ãÑè]£½“•AÏÌè‚®™ÈŠ4Tô¡ªE1é.´¤D?29¶Y¬¾Y…MÉ=èå4_#£ˆL#b¨‘E?2: çuìáõÆYâú1èµ”µL;–ßH믭ó36 ²>Ç™¾±Ð¨OQ£«0Z˜AÄÅ‚Ê!.›‘™á›ìωݒ÷¤;ã™P"~Ãhn×0 /”CÃP~ä L› ’¥Ó\¥FpD ±6NâQ;ÿÕ—Ô
+^n*X2"õeu0Bà€²‰=m"„£Y R^H&7ÁNëéT˜8ø9Ô›ôð@—4ó킪Æ9nBb%çfœ7cà›ÜÞ‚Bw!~c˜TM8Þ|,'~‘·ãï}ñhš•|†£»‰‰¡Žù|x< ª–Çn÷Á”†ã˜ÝV× C÷¦LY«ƒX•Ä½F=^"ˆ¼Yæ^lç07Î<¯äPïþ4ïì6Â¥Pÿû¤[~²)PÂ$Šó‡³ÞTi$R%Ú Â¥b—DZóÉRcXptzY£©ã úÔnNÚ¯”°¤ÁÌú^â±5Ä g0Ž’ý7Èxu¿¥!ñ õ¤C"ZÖ½E`ò(™ã"NÉÎAðG2¡d¿ Á;n
++gx?›Mì.eÿvAA
+|Ïs3Î ³û(š$ô«1…Ǻ:•F¶K{0 -ÄEÖ‹Ü´Ìh=nÁ•ýnëcQ2Tîkž£ñdÒ1=P•%U"kgÜ\×±¸ Û®˜(ÃWéë ù&?«2Ö'”íуâD¡)3,~òqr#½Ÿ05 kmÏô |:®máýqìuõð³çĬ ˆO{Ÿ_úrºÏ\Ѧ<8.a©v?Ü: çX„f0¡"›| zútg»@Ïpë‚®áZ ¾+þ¸áVDŠ´&:d7݂ɱš‰/Ѽp : ±>·cç.™„1¦1G„Fdm„è„ 9\Є ‰b×ÌN¶uÊp϶äiÀ´q”å'ádŽK¶Õµ9 '‹X4¯ýæÛá6ôªû
+HV upcI¶WÇë ÈÈ I×l ¤Ñyh7Õ϶€ÈZì¤+„ád[Fº‰Lbš¬zÙօܳ­r˜ŽƒG‰uÔ/´AN÷=·ûô̶¿ËÆR—ò’ÇçPeô%ó…d¡™”.–ëö@FLƒ¬ZfÙ€¤”0+BV5!&$µœx^Ž7„š5üE¯-.s
+HgU%¸¼†¼ƒ›i[ˆ¶"à5ä3BmoÖa®%< ábT÷4@¢)ñfKWœ[7õ
+·¸ ÷u€ðz-Íš%÷=È¥V{«ˆÞ…C•._þaH=F’±°|œw)^ל¢Ž½wz>Ž§=t†/ÿ‰ÝÅ%\éM©.ÅŠgÉoëxĹÆ#àãV‘ù´Wj ²~ùíÀºÄZT?OMýµ­þ>Ý'9âs¶÷$üϪ(Ò<ðƒ*9 \#Ïín ïOδ„#½hu:ê=-±»Ùô¾s=1ZTVâÏ\¾ŒÂï ’™‚~Æ{þøòš]Ï™bƒcÃk2w´qgªn`ª¾QDÁHv©Ðfî:i¼!AC ¿-" 5ÐQÁ”W¡•¸bì[銤€®ÍÙ
+xˆ•ä)öûXÓùù…¹œë@»>Lí·”ÅÆ»s÷Ö[›Úòˆnjx!Þæï¿<~HÖ‚j`©§Ñr@#ô Af®{æ”í¨LØÒú¤Ò䟓žÏµÌ<"5 %,X«Ú÷Íq)f‘{‡œ]} \»C £ƒ³ÛÏÔ“/0Eý.àxK¸RpÅCÞ<s èZ¶tÄNЫê)*‹+™û4b¤< 3|é*T˜ŸJ¨gd­0*PQKsž
+mÇVé î
+êÆ/¯iLÙ3†ÝE*¦åˆÜ\N YÌÖÐ÷!æLvj]WgÙ‹ðDW©¡[^7'Ô ”žÌ·7ck½‘w[ñp´;ìÞ*¥t›”cZ¶óÆJO]¼ÝÓÐÔ!Ñçñç2싱PÜÍgºÅ@É›œ”­jæªÜ˜ xv «;x‰.`çñfšl8½ŸiKéꌺ} A %¢]3˜îKñ¢”“ Û¥Ä*K9Ÿ†;àÉiÄÓ ·Ô#bmK•L"ÄÃäjŒƒáµZ[mÛFFo±LZÞÍyÝRÞ÷PO¦G‡šG—®'&r5+¦.ê8\œÃÒUºçÖ¤ñ,Žý#éf;w°Ÿœ$[Ü¥ÊkøDpaäšqó¤ö©‚‘’ŒTtErÒ/SqŠ;ô: ëò-t3.
+ÏIÀ~HíN‡êeõ`@Vý~Ĉ¡Ñˆ{a¾'!mY3š©‚“ûg>Ϙé‡`§ €*ÕãÕÑ—Œ×˜ g£ß@ߟŒÐ9i“;&Þ˜ôŒ Ë0æäIóïcÐÓI8Û} 0t¢Üñ¢þDÓ³5ñ/4i ¨l–®Kñ¶ßR3Qím ’𞔟‘÷Çtv`:É7é¹ûdîÔ˜/=ÓQƒ˜hßL»ù¨Ô i‚¦D5QAŠ&æ[€níT_RæIÅ6Ä7ëÐ(oâÌé¬ÃFQ;ô‰èaÈÈײéˆ5#
+–LKõŽJ¶>çÙ6ÙJÏÀÊ¢SÎ1`À#Ík‘Ô£Y¡nB C4-1Gå×1ÕHô(?Þ 㪴Ø;$DAK<?÷-Ñ­MãjàÚ~üÔð*ˆ]NJÆ‹ÁN(ñl›¯Ÿ
+ûö9¦­©*b׈£3ÛZ™nÆw¼INÃô‰š&›…ç˜Ø$ê©æz݆SY‹Ö¹S¢C(¤¯]²Í®¸ˆH™^¢yáò‚ð´|c0:âê#Æàq$}ðËcÌ™¦-²Ÿ.~öŠ«ÐÜ?ôEon6<„ý¡ TZÉÁPÿ}Dð›i#ÓAó}l‘J’+.0²DÍgãe¤a2M[_+èÍú4lQPvŸ ² _Ùš+jaZ·¨lÅÜ,¦v^¢
+‰#™ Ñ•Ý)CãsRC<$²Ðu1Wì†(ù»>xq½NoŒ‰4dƒÂçmžÐQá¸#sƒgùˆ0£ç(8ÍJI‰ÖU7n‘Èœ“AîTÆ==Tyðª>Ód,rª& sÀ,¢E–سm å;4X¨›HΧà—Á$ã,û~Ž&,K«µk6Ö.J HÔ ”•:ƒ«0ÉÝ
+×ê
+…o–ˆsM EÇZ=NßOÎÕÕ!ã¶4OG- ARQÆ3µQæ`Ø0d)šB5“j•É•jºHt³2ô™kVÜ8Í2åp“cȹ¦\ ÉüçJ"¶šúc¯1熢;ç¢;çêÊœÛr—©×ˆsõòÆjH}ãQ+æ\E.Ñ
+#QÙåŒÇH¤µ”VƒPª®„¤^æå–PÞ1Nä¶%‰Lp@?„Py8Ôèûa'çH˜-µyv?Dpñhz×.¯ôbØ2~èÑyvÙ
+¢b<­‹%b'Â_r ѧҋU&¡¸ª¼9Ä:Å“ê›ÛÐï´¹Îg© ^• ÅOñ½Æ \dz4‘,Œp$ù”)ÿÔCTLXÙ¹âú_FK ˜;¯eڻ؞tmÿÒ38¢n@a?Ÿz†8iÛXC9ÌoRõIr>õLù휨pn·y–ßãMQçBk’%õGÜ
+Ü‹£WëɧDý¼:'gv<3€áß'8Û^”Ëb~Š0|- ê¯n´#aj<£u ®á¡fç$¶X:)ÑÅÑóNˆðdUþ?D]®"S¤dÎE÷Ï}K49L—Zª Ü7¢ÎfQ¦¸Ó–àØxhÖ~àμ­ÌöEKl‰ÑRÌÅ5¬^O 
+:n 0g¯Ò
+çÃ6iÙ,²:HjFÍ6é®ØaŒ¶çï5ïS=é
+Û= í S~C“:”
+öë2ÛG¸1¶˜ë{ÉÉy¼IíS4T¯Ô iǺã¼»kñÌ5}ìØLùÏo)ºPõ ¨;ìÓTGÑnIÕr9ú¹á̪%ƒQÌkwxÅVÀ&a>¿)+ÖH
+Ú Ñ W!òŽ³‰§óTv1I(ÉüA›c¾ù§ž"vDÂÕâ.û%T³–ª°hõ@"rG²ö%ÏçâÙ *®ùzI
+ Á¤¢¹mkǤݹV2ÝkŠ¶NI
+B\L2F~K—ukFÑH]~~Ö¦þj¤3!Œ «s½ê謔èóMD°çL"“ü3f:ÉÉÂÀðIæàÌoÎ!«IÃN%é·É{Úà²%Ç¥Á˜Pp—ylØ4ç(¬iW¿ ÇSfà¨KÕUw9.ˆËË…Á0;ŠªHÙŒèüFÒ0¼…+V­óºk‡ñ:AЈ>ÞˆÔ•”(Qß–K¥“sP‰ýh^ÏÒïëåÛ§ÔõT饼rzŠ”«ðÙ®<U”Ð*´ÏÃoù”‰jìH(~b‘ƒv¬dH• Âõ#!xb5fÂ5h¸…âk–åÌhtkê¬3;G²_N/¿v"Ü'>VëV«<+
+7Y­ à
+¬ŠÕÏd$ï+¸\Ì0£TcWTå\À×›©àñƒ‰ºÚî]‡@E69Œ±–Â+‚óz©< =]
+£ :Ä:÷ÉQk ‚’%¥D'‚"Àœöð<îøA™¶ì¸x¸µ K›êC\É{¡ˆê9(µx(~ð).íÅÚ=KšKC§bá|óë¸o·¹ÃÆyÕ~·îÜA|ë±· §Yý|²1Z®°–+?r#ÓÁÏxæê|ïŸ[Ô5 ä‡u$]=?VmV´Á²Ëh8»³m ®·¯ý–¬ 'ÙÕ[(°>ÚÔØ­ŒÒsûhat6—|È剢¼É_‰ŒñÉøI©Éû
+hfé9’Í㸠 +¬uY%sö<=ºk\H׺:Ålº D?fÁ³ŽÌ˜ iÚ@’kúNƒAI¦à¯bBÚ$ˆä$‘•d„ƒnCÇœŠH¸ÎR]‹ìæþt‹ÐßLu >¯Ãø7ô'±% "üRi0WI hÁoùPÈ DSÓµ#LðkÔ×]$ЧþôÝÀÕ¨R¤I»½¤.¦gŒ|%ÊK‰12–>ck{|óÌKihM0âá2})8™mãs 1MËö(¼#fß5ƒÎÅ<P(2lÄ åêXîŹlKÏ*)
+i~öÄ”þY;È$‹§Û*t¥VŒNÉ>
+Ùè ¸qõß÷í6wØ8¯ºÃïÚÄ×»Ëp•öß7æ%íüÃÛâ¦17Å—v§è*íÚ6hZH²/ž´‹áĽäúJ'Wi_
+ú7%§7/ç¢Ð8p(݃ƶS b/—'JÄÄ9 ;à¶M A&Ì»É=¨ƒÌoºÔ™¦ƒu1U«µëÊþÊTv‘›à°x§mÝf080ÈŒ;=h ¤@'`ƒzÔ`- [ë Â’°Váßn-æ×0C·È¸<t‰HwùÙ :!V·V‘]`[hÿþãøíéÖ¶gˆ1}yWü’&e4pé>®cƹ-ÿÅn=¾vö‡æ#ô=´/g Wºó®CJQS&†ÞGx!f­Ëã[ã"4E>«À2Ÿ
+>²‚âŸý @Óma?ŒNé)`BÕ&n.cø³6ó¶,mßþAí7o]wŽ³1t\0©ä÷o{/EÏ]#©VC L"Bc¿[`^ûÒƒç©<FÒ¬“¼óåÕà*4@8ÕŒ &vM:\êúNLìãá.&ÐåÍLÖÕÁÆ7“U‰£çE0Ù®ŒWï³b×£ªlSBmàˆÐ#t±ÂŽ$>
+}í0[Ø`Œ=¸Ë ¿€ÿ“í.X6}xDrkè.ItµtfPʦW$cÎßÀëót‹Ù¥.³ä¸N9íÃ=äd4ËE¢C]4ÁÑ㌯N)¶Ãt°çÀ­HŽ÷Ë%èj‰åÈDˆ~À_€ûÎu
+W±ûM2¿_Ñ3 U‘;ÈWÄáLôß*b#²4m´-÷·±‡.ˆOc= wù²¨WKãX-½¯Œí­kð·ÄDÂHÐ
+ìÁó?š
+[ÀB«$.'‡|sשrnaRþk
+h&™p¨«ÖúCƒl‚«úkf€g*½¬)ÛõWXs•TrRS^J‡¢ãâY7¥¼8 
+Š0/öfz¼2ñæ?JbU.Ë“é5ª§e­¹%˜SÜ!¯Ä*¯ýð‹pùD4Ö·÷Å N‘F2"s•Ñ=xêœûjWA¾ù•ÑýÜè€ú–D{¦-w´ÖýU°¿ÏuøL©ÞW"+‰4s4„dÆ
+Ý ºéÇÒœõ"Í°/9ã#³£(û r'È úu#VÔ¾x‰ÇW@
+jPkÛ<˜•ƒ”«‰äè˜ b$‚o¨È£â8,Ùûðãe’YŽÑ«Ô Ò8ëÚê¹UÞ[ÏAPe²T÷¦;ú$‡~ÑÅùL´¦”¾ßÎÐ&î³eB
+;^½…UŽHœ2ïI/)€
+„ˆunÈîŸ/#×4A_GÝÊ.ßbCžäs¡ÊþÍWÇY©tãÃ×*²{V¡álñ]7”…Ñ)Þø ŽÊ›¡³kà'%ʶÏÈ8J)zÍ~¬ÔKíi%üh©e¿éRy†¦Ã½fLƒ¢`Þ@þC Õò(žE‡ ‚%“¬¦"*ÔÙ{VɶÁÀÈÌï½âY59Ht ßÓjTòÛH kÛÙ’Í=£‘ª’TÔêÿ»ûWK þ“Mj±àD’ÅLX¶&>‹‚þT Ámà[ èÇEoœüùâþ¸‰k*L¡|‘ÌÀdü ‹ Å ¦€Um@ÕñÉ4|Ìå8jž
+äˆ(£…ËœÍÀ%„÷ç%>çl$wÞM~d— (¢•³Š<…Œ4¶}ÓV•|—»:/‰M fgðL¸¾•œIBVÒ$çºÿ·ï<‡ý¸Í4Á«Ø{4ç àG‹£ExÕïŸlËÇͪÏM˜,yÔ–÷
+¾÷',BBP2¢Wçá\’Uù>Œˆ7ja`ÃtkñØë:§G^ãæÑd`üí I/yMã:taÉÒˆŒF4øw»‚ÓÅ€‰A9,´+€™ñ@ŸLl]¥ ­‰¸›•ˆuùè£_„‘ÕPg~[‡+
+T(“«¨W¡TÅTétÝyùÅsò‚AöÌ‚LZj¥Çq-,zûgX„ŸúªK²øvc¤Ÿ’:sþŠPD,½rày9“žÆ$.©6‰z£GÃ.G !°9½y ~òš´Û&5“}tµÜkž4ùVát¼à².wZ£"[>t _ÅOù^>o {‚9øÔ>O˜‹%)ÒdøJ¦ç·­øh¯ õxûf–˜D¹¶-¨ÉPÊžŠœóšjÚ?ñÒ YØ e<?è/‹iâ8Ð/Ј3…kšFªÁtÑõ½²íoTT¶Ш²C?Ȫ5öºzÆÔrvÅARI¦º&Eü%¯p"Ü&YC?2p–ø9—6×q£¢öL 1S¹ƒãrù&Á¬LW¶’.¼‘\‘æ÷‡nÀ¸z*×Û§¦k—û6$ð¬ðÊÌ 9Òø¬xò>‚Œýûª­M˜|‚Çóïµó'
+Hù˜rŠ °©W¯¯ë¢À {<fÙÙ¾#Áü@õgঊ³ª«i÷OIN¬!
+çønÈ(Â@BËI„;J0lñ¨™ýÂllg{O{ ÊÊ6KìîžMT
+rø¢Nj;(úø¦ö‡ˆçÜ)¢­¹ÈóLW4ˆ‹ŽÝK—®L¾á"Жv…œ–raþj%$߆»C5søÛæÀV/1âÊÛbò¬8ìP,4aؤæõͬþ2r¡#]t¬\k™/A½pØA
+›„<§‘ÁÔJxix "À [2º*+É›zFrÒ%ˆ±°#<âè ‹h7Ò°û
+A%Ø©¢„bl~ô†ÛM¸“1ÂÄouZ-ýÇ FE•]'Yà‚¤Ï°(€"ÜÑhLÉ__
+/‘]:Wnüb¿O“™‡R º‚‡?ýÒ]ù§Êcp)ßAí?äAž‘&ÿnéÁ˜àñBf-úJU#0HÐÌn(;ìÄíÁAªVÂr`Q¤AÅQ(äC4#]¯¿H'ýÜ7½8`•@ij…ôŠ£æ‰4°5«ØR+¸¯·›±n°X+Ý7ýQ3†Ö
+Ö/@ë#ìï‹X7,ö
+ì x/‚ö1N[+”ÆÁaŠF&LJ:ø ?Àýe à™ò¥YŠ;Z|äÎ>*sl[ \~bŽ°Jgí;ÓžeŠ¨è¡luH`‡æÔñ´ž¹®+(¨Y̬Sà±”ŠFqÜ佌 —àÿÐO—6Œ Ì<— o‘˜TwÁ{ß
+&øAûLãÀÍËng&,0ûÎËOzGíÍ[†ç:ªƒ‚‘@›Ia¥_Ï„¼ Åu;±K¨eÏôAç-ER˜²m%¯âoÕ°ß_IÔÔx$ìN_JÈ›JMàD¸¶ó“¬24*AÑGXÄc¹‡*Ã2†åçqoEŸ?¹ÓÇ5ƒÔ…zÉý‘6qñbM6±ë?‹S03³SÌ »B^*Û¬ƒ;
+… –÷¹"Å!Ðî­°¥^bãð®KlwÖ™¶"3›Ë9ˆmf9ëÚ¸¥ÀÏF“ë2v(?;„p=Œ9J‹1uúõ?.sÔe»!¥9”lv † åߣ#¹†ƒ·¬MhèÐâUGµ³mUEDÍàš]Ò}܆
+ÑÐÿ¶«@Ⱥ¤Œ¹ØŠ1Š„»y±Ù ¹rDV@äg0,zl‰£-q'í N Œ¶ÃNQá<ñº `SÜ®h˜IŒDŠŠU¾òÒN…7"d¹3ñ|LÇÒt×y•øã°þèß÷ëæŬäY“$(;™5•¹DÖ2›tâͬ }ýÊûPp2BÇL–fM«E(cç®×!ƒ#gfÕ‡ôuÔqk­£Ì<²æBx%LŽud)ÜÖüz¯þüÂ*-KlÇv¨l>í°Ä1`Ƨ‚׺ìÀO AΆvTøä ˆ\œy¶¿—Û¡Jøô|ñŠ—ý,…¼ª •o«ÎÂЀÑMqÚWJÝ’Vèò.¹Á„4‘ÔàŽÂÃñÇ‹™™•Ú2‹E•I£Œ»¸™XÕ€žÒ«ÉO8æ`„Ð’’ÊõB¬Ä…·ê(2”MÀÞy¬`.ùsg(xYvÄvÌa²íj «ã”ÛXªI·ï˜šðÙE#üíج>‹=ù
+§¿ïs,8#ØZðRÉ´Ð9¶cÍ
++í<ÍìòôͺßIaÏ‹VìP9”Â!™½F
+,\ÊaÜ0çì9yà°|Âp­«²°“
+ébêˆJOüwÌ€9$ëtߪv*o`¹p)ä»>K¢D~ØõÃw0…Ódÿʹ BÏê›)4ˆÌ±œûr YQˊѮ稊ÝÃó÷~|+Ë©$‰2w°ïdéËF¼ÚU‘gãȇÏh–#
+p ôbHšòèy§sjðoÿùõ±EÜ»ÿ+áÉ TƒDPH}öÌ’þáo‹:”Å䲋t‚õbرÈ* R˜xô ‹=e@†É;èŠbVN]2?è¸WÐóÎÿýßo¿ýÿïÿ§Çð^m6Ñ¿Å(ñ¶B!•Ò!zL_tDRÅ:C”è‚&ƒ‹$Á}x ÃpOXm˜Y’Ϲ‡ ÃÈÉ»E…Û ÄÙ¶à7ÄÀÊûV€WÐóN•TÞb —`B´ƒ0…š %N’
+h$ü‚Gy‘™-l?Ø‹ %'oÖ"àTEÓåýÜ_› £>y¯¶óg„¯¦¾ÒúfjÁWä
+Ø ²ïhîªf¶ûQxx$u
+¿Ê‰ö¢±¡¤0OV+všáw”­ðÿXÅÒú‘Ž*³^dûçô åZè‹ÖÎQ>µ‚Οí+KaÚy¸vèÝOûÊöñªe™S–ôÁÜdß–¡Ð
+“¥sÝ9ü~C2MX›¾ ;“áÅ,Ú´É‚ÓUì-:Ša[µì
+,Qðü[ Ì$R>ÑŸã^[òzÞ雵·¢£P&ë
+rÏà}´·ƒ6¨#4˜¸ï Æ2iõæ6Ù­Bò
+#v(
+MAdþÔëŽ%ÇùÆË%¹¢Wñ TÃ/Èu²Ì-¼•ï¿Íkr*\öÆU² hô‡DeãÊ·"Ó([±œNá/¬áq¦Gidž‡<['JŠOGNid.M¯rr4-²ÒÒç´@¯,z¯ŸÓLQ¢!!Å+
+ÏÐê‰,N…¸fˆzñ§þ¦v3&jè"Ä'5Q¢„¹È‡ä
+‚‘Ó„‰AæJKƉ#{mVD¯K{‘É9JiIÑ=-š>ð!§1·Î3ñ ™íhÁ3m&M~¥_Š°\L˜«öqtdW øl°ã:-韘tbîv@ç›…ÐÞ”·ß”"Æ Vçîf±¬Ýø­kÍýH‹ çÆm@ttH~CƒeÃþ›°ÕH:k¢tÙž„ö‡`ý6(×Ñ+b‡Ë1­†Y(è"ØE9T4 ƒ÷ÊháI@"׃óV¡¢Þq°µIOJô"<1ÀØÖò«ç`© €åŸ¹1‰ p6°Âȃ·Ðå/FFŽ$¢×±ßÉ35VëÚáB·Õ1&€–ú©¢oÌ-˜Ô‘dáeS«{Y•hKJé¨d ÂTp©2õ» óIæ¦/2ÛØ„ù´Yê¿Cà;癨îèŒóò w±p³ÖôÞHüÐ4qÅÇÔ%íÃÚD NÁÜŽ·3üc“¨©µÑ0—f_öÕí k#Pð‚§¥;*`a£IqX %îJùjÊÖ;@%§(h…%—gØáJ€^dvE#h…~â2Qą?G/-Ê™{†+q')ª¿ì¬ËóFAŸÊ¢9ÚŒW}³›ZãË×,Œ7w¦VV2ø´ú#JÒ‘îáB%ì,A‡ß•=vX
+iì2%Øn¹2²â3Û²å3EöâèK´¯Ìyj@”ÁbHVÒ{ÝÄ¥˜KW2ùWéˆb—Š2§’>aå‚Úi–݇!F€:EAJæ$5Û
+v9Ü£:Xm¦=ÂWE~štš êW‡¨†ö²aüvT}5qB0Ø¥f‰k÷#(¼þa½[0!2dúk%(pfû±º)/?•äà1`XŽ ŽHž#p5yE¦y¼Šä…ص-j; …̘
+ÄâÕ­&ü`
+c¤¨wß"(
+råJZȤŸçñ28”®ÐmreÐrCu‹ ,)º{Ñ
+ÓE~¾;ª€¼ÿìâŸêëóžŠþ¤E/©
+Ä]ðí` Jž_k’<¤^á>qy8½Ç¦ýWt?Ó‡"eÖY£ç"•l$Œ!›î'´±ú ¶Ïþ
+0
+H‰l—M’$9
+…O0wðÍlÝ„„Z÷AzÑw˜óÏ÷GduDZY™E:!~ÙÚmm]‘÷œ¹.ßívÈXÖº#h÷üþ:ç=û×?ÿùïß_BowÚòkbÛ{ZƘiýêãÞ}æ5mÝö\{Æèû-µÙ1íFkΟScÜÞ<r¡Ò–]=ï†ûö±®1ïÖú1Â'ni¹F´Q²mYºË3,®î˜Í^‚à^ |Ísbz¼ÍåÜuÊöæ”ß{»Õ©ÝÖ’ ¥é»ü®ïü¨ï{JóåÛÄ]Ç7;®nO¸FÜÛxêr3Ëyáj Çšû½2ß—O½m®¾ÿTæWÊW³±Ö¼Ìî¿œÌ}
+ã¶Ñ6§âŽm¤Ãø×Çeûî9SÑñ“[Þ" ÒOÀäqk¼±{ïî%$ãuŠäu |Y búî;½¾§™¾s«½­ùî«„Êxow3ZÔ5œ–ÀÈÞ1=çv¬ī¦áƒRMid¯ìAi
+â}•Í#÷Üš :¡¾[ÄcóZû )6€&š’Ì<Єo¶–H˜¥d„MJ“ãeHkÒ
+b0‚Ò5ˆÛ.…ÝÚmý\„VBt¤B¼´F™«.÷âHÝc•ñ)“'N*Óä,­J+W€ii¤º³nš5¥gi™†&Z§d0¢¡_7í¦›‚q%ªb9)Ø•“kœ Eu”àþ$»HÒÙÆ
+hˆäÃU) WP¬¢\67ZcW±~j4†¢¢Ä
+8áÁð­!;ë0KZoˆÝ*Wpº
+.T½2jBt2º9ü“‚„x¡è¥Õ;†Vˆ“xÍåaÒ°XãhPÅÒ`˜yix%_øöÜԩвßßtx
+lB?UÕ´/á0DóɩT)k )MÀ£«HS³ƺ4_‚ƒÜæ}
+ü¡ÒÔmLÛˆq‘OÁɬ?™}5ë—–6Œ­Ç€Pòû¸[[
+
+¯:iƒ6£Ó¡Í
+¬/<î€üð_4–QžÈÜ ÍëM_Z¬ô*;(ARø9Ä4á³Fã²1
+*§†ÌøÒ@/Pþ%øç¡E=ä:KývšÒ]Z¶ªEeACT$f†ü¢!<8æ¿dÌø0+ WKÖ€ZB¦Ð`øÁwMÁŠh׉%Ä$„.¤Aƒú[ã
+ø€@SðPá‹Ëã<ä™:Ñ.¸™±…»¦V’4‡p×Ę`¼ƒq¦³,!CEºÊbZ²Óà¯ÂbxI_»F[‚˜bÍÏã©-@šeŸÎŽÚKŠƒsš
+Òr`‰ž¹zá³Ç4 õ¥ S5µ¾5©Á„ÁÎû®›>µ3…%¡k_
+¥Z¸ÏÕš§j©ù›†ö– ´ÃÌü+ßZC„ȼ¶¨º ŒEº%Žö°n1¢ê)^ëøÇÔ- {5<Â%ºµU2ûš– vV*´ŽŸj ù\Éže9¥‘àþÑ NJþT¹
+R°nÙÐ{ç/þüä¥yÇXÖ~Oõg_#•£±1×A²‘¨,ô3î7J‹‡ÞÅã
+8·¢~[ªÚ tˆÃ]Êñ¥»Ú¼‹¼V!•··¢ïcŠü@gžú눧¡Ê¬j¨„ã/ì³8ÉÜÐU{“ýBwzm(Þ_E|νG«~`A26ˆ¶Ž
+ÄÍF1neéìh)¤a[ƒô6ÅÔgæ›±ãõj†Ä£@¿W» ‡øƒ¼bˆunDÓ•^œ¦WÚ~»œW‹2?Ç ]öäy ÞkŽ¹ÏòÝ84Îà™UÞ;tÄÔAŸ¸ºÎd±z©b1nì]#Ømà@@sØøEÐ4_({.48st û_üþÃßù#]o~ôï¿Äßßòg¾Ò£\)~ýã·»/ N_Ê´voš»S ØìëÔ à7ýÖ"ˆ³³A¸¼C`ë1GP.Ø—°y=ƒ„4IF4$Ò‰H[jEž;æäaƒÐdeÆ” Û†$> ×ÃÝç:”ïzâõ¥D›g'Í-v£wYj¡#]GgFTX»$Ÿþ¬"
+Óê:‡O×ѧ AÄÞE‘B'K|·û,#"ô–ÏsªJˆ(ŒX?Qâ‡QÊN#ÐÇ݈jÇÄMp_.¨ãb!Ÿgðw/ˆîœ÷ö™p{v7È5 …ú
+×bRÜ´W8#lŸ¢$ƒ >yJd ˆã&Á¨_Ësî³R
+z„"µïòDa~™
+,,,ÇŒWY—­@¬{S©²m&“/⚯ºi ÐŒÃU‹Ü‚Áçnëÿ,eØ4
+ wN¢»QT✄,*rNj` ÜAÄ
+p“¸±>)_º¾ñĸ,ÐÄZ­pµkü;>Bÿ,’/¬b  *&ÔÄ–cYH/Óï"€¨^ñ<ü÷èæŠcWmÇ‚}tš "q×®$¢ÂåŒ
+Ú¼ò €Bðƒ
+ùUÆnIlGc¢¥² ôøt¡Z³X``\ÐO@õˆ©{3Œâ¬J»©EqQnŠoV¨Ñ20q
+ü:Ïf«ÅÝ q·ù°8#J-É<ŽHl!2W‰ü(“Ú„«¹¯ÿÚ`ßÿ{5ˆ²`×­&3Î/ÝÓÿÑ!£
+Qt¢¬™QÖ‰ˆx€H;û ¢wˆí¦Æ€…]
+ 6j[o£Ha5*6g˜&ö’,EZbù\eœ“ ¨@¶{Ðbó(YàTÍ°ªhVœ8í1àLgдKSÄ#–&© Y —ÆvÍž‘S»®
+8È)Ï-$UÝ¡W¢ ËHÞ#Qp=y„¤°môbñ! Y²/jqÄ1 v¼ÍªªV¬V)Ïz Ng0wQdsá9À¥Ê °Å>Œ#½Ø«™±¡d‡}€<
+
+xúÄ»0%vÙ÷‹ºç|çùHÆóR
+äKÁ统É®— tyi6œÞ¦ý Ëè™……èVÑݲv/FYiÈŸ®–L6|ñ¼~•¸2>+5®¡{ Š8 ²%m a7#øD@ëTÂÉ,³ÌÊü¾mÖ.àiÆ *©æOÓ2V¶$z³dšœBj
+Ï°òýu ï€ªW`Ò6'±ç¡,æ[lÄOŒ9Ä,i` È¡7ëí
+f³c§’§FI×Ê©ÎÈY„ï &¨¾j ž=<Dx'†õ‹u.pyÞÌ:õeõ·Ìz¿#`ý}±a)~)ñfÂÞ ”äßõg³¡u"éTuîãÞ·þ•Ù™/@/3ðf0‘‘Ñ+’±ÎÊÎÊ#Žý£P‡’PºÛÈ0fäbæÿX²ý4,}UöŽ Ž¾Ì€Ï{d uó°„K3fE2/±Q…=õ:ëªW:Ò0´°½RJ_C«
+fóãCxíÈÚ(/³±N¯ º•×2Îßéf¡MV_`ïßecU‚\.b·)Ñ·5·ÞïaFüý®ôAçx‡Åe3£(“éÁŒÐz„Ž9ZC
+u"Ý”TMélê¨kNè:ê,aƒ>WÎ)6×Rðky:îÖ³0ÀœwF ‹| ÉŠ­X‡Á„ó̺Þ
+j¢CÉéÕ…ì±½Óœ™TõÄ¢ ÄT+Q/ ­tÂ(.þ¿×Sfj» Éûu24½f\‘„Œ„ãB‘
+ÂfÄÏ2¢?SºüuØ 6ru8@¤µ5Lõ€ÎÐm܃j#TpD´`¢Œ\yÁK‘·zX2š%Ü%𦒼÷¨bB;AÁ]hÖ‰ÛVUž†ø7ÍP‘°›Á
+ŒIm@“J©©Ž„’†ðŽ Æy¥‘fgÍ¡ÏAj‘”&—•@Zt—ëz*ËÓ9î4Xw⸈/ÕeqsSÝšQÁ§â 7¥ºóݨlð4”€&©ßÝé6Ça
+ȵŽ­ Í§teÕK*_vŽzÁ,m'Oª‚¦‘|¶Ò¢éýã:hÖ¡€Ø`§–•G £Ë}þ2A´Ul `<*æa‡»ŒŒM {·ý_ÖåÊÊ$jyÇïÁ$d1Î5²¸Ö4k0ֱΤ!Ìà1Nf¤ÜbXlì­<ýÉ8õíÄ-Ö eßNÌ/N%Pae‡Ú¬0²­é…ÆJÈ"h4¥RŠÎã)“Nâ,GÕþ ­nmmAŒ”ŸW‘ ¡AôÍRÐæ¼vU§#²2e옌€ô•«,hj…Aé´ƒ„£þd :Èc…dIšêHnnÒf’~Óå‰%ü¿ék\•â…°b$<ŧà(í~‘{ßûû/ûÅ !²dj@k*l ÚUù¼*¹'pþÖËdW¯ê£¯r†€’Ëîf”(R2DVY Y&oŸµjŸÿ·“«4Œm|OÕF…¹¢BZ×R3ÛC$ujE‘TìÍ©u ?¹ÂAÐç‘-0G4í°oCŠÍó##³Ý*{¿dÞàZš aé r¥Y…v“AYó±Ÿh`Y#|œ—! ‘Ûbž‚–3ƒ<Q‰ê“•sdTÙªöOdôcsjžÏ…ÚŽ…xgKÀ$5ˆrB7iâ<2²'‹Œ\büA?g³¼gÏ‘Ò€Œ™o0c0TŠÂ¤*
+¦Y³M]iiŠÉmJê\ ÷Yê8}9Õñô%5ÕÏ >PƒW‚oN5ŽäÙ©“$ñî€Ñº•M)=bž”ÀÃ6Ÿ}ÇÞ¸/™f0Y¸=®Šßº´äÜmvÄÝŠBIÖX£i§í®jÇѱÕÂõæÈ
+à=ævÀu“(i-µ5â©*Qì$œh·“¼ÓsÌÁ! ôÚ!öƒ:ÍVK«HIqÎCÿ´øå !’­Ï»¡ö:‚vØÖà÷îR ªMw/À£5 o–$N"âù4HêžcÆÇök€¦…£!ã[
+u·óƒ_L&vwáõ®I?ØFðÃm*Së[ä?äPhÇ*®üRRU7 !eB‹³9Î_/•%:ÍD5e&РVßôE/vˆ¾c9Ì4ÊÒ¥< ¥Ë¸”"ò‡@Ja‡@½PTżþ|»?Ž!Ç¢†•C/2 +€PKÍ)©c…BÍüèXò¹Ïr'»á¨y«!n FX’ب£ÃÐ+ À
+V"–:
+ËA'ƳklìÎ4Šzˆ
+}S”¨·ýÙb
+¥v‡c"8Âo˜”©&¢_ºú:ði!¼
+BÖèOÞh
+M@þ“QJèêò }*ÚiB]—,‡$-r!×—WQoÁU€à­À“L³"k¯Ãhká2ÈJ°aÌS¨-3Ú؇ SÁ–qÇÿ“uÿ«È@˜ €öÿ« rˆ
+.Ù§º ŽL\ß`F1HöEY”l¯xµÓ)ŸƒˆzLg#<§£’A„C `(â%îøž‘ÈÖë »)xÙ K‚UòH¥ïŠôµ‹ÿðÎd«ªk9‘NE²]c7+³Ü2[ô$
+7+a7B~ŠE8³ê&vÊNǦ°¦­Æ*À…áà”ú}u5 Kóeõ£Q’¸h l×V=E
+á'cI&€]³tòŸ*ëÛ_±ˆ`Æqü]Æ™æ¯ìdwìàvêÜÚ²xûYÍÖ#«)9OT àBd €°§ø‡­6!#kAÈèŠÁÈ ͘«È‹,d YUü4‹#‹ÊÍ1O­ÜÈbù]ÚÑsd Y‰ŒP–dLZéd¤‘b%àå6Q˜‚îBm^YÕ:·TfaÔaMSÇñ襶atvÕ&Þ4Ó*mB÷«Œ#Lq~(9›Ÿ8_g)=©ê¥ô´®Ùï’òצÇ#b+ª ¯lÛ2‡¥';OBÁ½’Y[°ñþÆŒ,¦if†`7#z”Œ¡$6ƒæ«f,‘A/*Ô&³´“¡m$ƒ´ü\©‡q©ì!é *›…ºŽyB
+¾©S›l`Ã[G`y€¢:
+wD£¶g{4û¸x§@Ø!¶Öù³¡#„£­ò¤â·ÔãþÈ™Î9àïOD¼û„\oV<Ø”ýU'þæiQ§ qÞÁ¹Ÿó¾?Ný
+1o¡Æ)¿–‘ùµŒŽYÅ£3ªÐ)i»† \¼9Ã@+ƒè)ôÉÚï @u¼ªy[¢h‚&ÊÆËuŒ;"$r 7ª%ÅxJÇrr
+ïÊŠð‡áxãˆV…uXºÊ’ã%§ŽßT£ÁIŒÝòLöŠW¢s¹
+uÚOíù¿Ý’ðbtA×›[³`ÉýÆÆt8ýdeá©èIxý~Y¦hHx¾]á*Ás¥ûå†lñú&«™*ø‰Ò„´åÛrsæŽ4‹3ÂÉÜœ7Z›Ú—]{'Þ]ÉÆÈÈe ÎÏ…~Uø³¦Bºåiî„yöuÖóü0;rbx@Ú•FïߤPæ­j·ÖÅG|?VåRÙÝâqy£é…Kd»ƒ¤ ø›ÁköøùRcø¹¦ÇC"VbQ1%q„™ÂÊ
+X‰gP2rY s0Í–‚šfXd
+½W"¦”
+Q§†M=áEŒ^u¢—ˆ©Æäeæ7Ï¢ÙფÌ7\yZÏ# ) ¹(Jà0íðĬRQ‡ÄÏe‘#8ÿyýoôÿŒ(3,J³¸çJn˜/J„2*·TøߢåqÅjlUdpnQ){˜Ÿc™‚<õ9t‡EÞhÙnŠ„+ T¼¢ÛÔ ÊlQ¬¨bb”²'ŠþˆuhÉš6üæFIlD €á#
+•‰¹ë)ºà3‚ª&¸šÅWÄ*Î ßámÛ ¡< ’´ûHD70Úíå‘ç@]ÞH´(†IYÉãÂwRít—ê?Ý™¡cãˆAÜ
+ f@² ›y䯯S?|³ô”°QÁˆÍ@M¢Ž>²O`õxÅpÇÏ™@)¢Ôõ¸@íÝñúk$¢–Ø
+D„0y
+P\EáÅ…‰uXĸz‹mX²ðX|nœˆÛK °Õ k¶ˆíˆ¼wâ]N ¦n ”êlã”|›ö¶ºÍ³THLÞ®>c5Ôö–w¢J  ç§fðQ„"ƒ]€íŽ. Ç81‰æ„cÚ)v:¤f•up·CèìQŽIûcÃs§&fŸ,rÎ
+‰/ÓB<*f5p( aYG£ÁØôOÄog·¥Á¤ê<o¢fP„È~Ì&pÖhlj éÅÓîèKѲ»wîD]N¼
+Ñ+~´kT–±’|˜×ø¹àœã²®Å¿·i…)Ÿr5œ•éåô–1¨ª¼'ÇZ/Z3--ÿ°{˜%œJcÃ@A/F‘à„ .5Q ×ÐáK °¬iß‹"Qä£(ÊRD‘·N¬ã;‚€ç|Ö¹GM²¤b©"Hc¿ÈØ~Ëâñ‘ˆcà êë+¢GÚNãÈ ¼…h–
+Ó9yMV±œ¯uiy©¶(Gës|A ·å£›Ì–¨(ØíÅwø0úF ´oH‚í…|qœ'læ•°EõçËI7pf÷5môkcOsiØøh8|
+ÍÆ›UNˆ Nà—¿oßÍG,\ó#ìÆGboüŠ&-$V÷Cu´ÿËz¹õØuQø¯ìG'‚q_vwï†'›  Jaž,+qñDf‚äÏ÷UïsÆÌ1o(±=³«úV—µVíŠGÎÕqOåÜÊ •q.Œ-uᜦTd¹†ð×€Ë2DhÕ1ÝSLón`¯ønF¶3”É.‘×ÑI2_ãäq
+NIÖ#*Ê·µFJ i„Ç2¶µjOv¹ „’À F C=¼
+ )ž‰ 5úן+ÓÒ¢6&¥ð¥Äã<‹-~/Å‹(˜ª†j§]n
+è<sGÛo=VŸÊâf¹ÅYd!A0êÑIDeD¶w‹é©Gäãºï#óM¶×µöóZ@-¥ƒ‚& I~Ž_ ŒìÀ'*ïD`ó«arÇ»A\€L¢ fÌméA
+RLñ,8=Ë
+%`ßJQhQ.7x…ö>·{jd{M\#%\àˆfºCQx»v10ßÌv5¬íÊbð¬*W!Yd½Þ`P¹ž2`1ä5fí NÞAŽ"ÓHO„±2±hDÔm<Ï‚ö¸{ 
+£¤ÀÅôñãï…0÷ú8nò lÒHd È4škC0¡¶XmþÅêÉÝ·t•vt"œ.µw®CçgE˜ð†yR¾Bo¬j¤ëš BzÂÍZv&a;©ÐØ¢âí~Û~·ýC  eJ¢É:
+ÔÝ2õ2;œM=Mº~ƒ˜©‘`W”N¦sˆ@G—ðT:ØP1¦ÜÑÅcªz]”1ò¢Ã‰ôÂ@<­Ú†r„RæºRE¥áRÆ$<H1•Sí.î·:þGþ<ñáá«wß?¼»ÿæÃÇí7|zökÀžÏòÅöüÛ‡ïÞÿ}{öòå‹ï¿ÿå§oîÞèûÅö+<Ëþÿò;þúîÿ´Y¢AˆjŠÿ^}\_¶W?ðCßž}±½úëÿ>,oÏ_Þßÿs{öâ뿼yxxûáýë¯ÿõúOoÞ½ý»ûŸ?¾¾ÿñõïx÷ð‡÷¿ü¼ýüŠoÞþüöÍÃÛ^sÄ]n^o¶oùç—Ç¿\?ÿÙ¿);Óùs¬Gý#lùÓÇx¢ ’f²ëÛdN`ÎO§Q
+¶ðàz $JxdÔ”ˆâ}yðSì±¾z”yîÏ-ÐkÚzŒsØè„Âj´ý£‡L§ß\»xÔT—Ç@;áAoÓ &¨uhçL5k¢
+b¢ÂYÙbHª 埭Ží%$ ƒ
+ÞØ:lüc%Ž~ùq5#ס óu ðÏ Hˆê¤Ä÷
+^Ò¯Ç(ë4Qµ '•cP‘¹¸:Þä%‘bû DaÓ#)AÂã rð
+
+˜š$¡Rz(ð
+Ød“AcŸ"^€m×k]D|ôÚëî€ã&N¡ñwÊXÇÛ‡ý"¾ÂÉü┓ˆš8¼Ä÷Ø<ÐÐ1úzP†z8Zè@¥'ÄéuÃglAÆ΃:=Æ´Íå
++*SqÌÌò¢]5[P!¤ÎÝ%ã^šF!Ï>1xfâSÖ`~ny!Kè1áh®+%äJZr…ö®K­¤“zµÁTa(Bã8YiÈ°­ñ(TÛþCx™$9’ä@ð+|AŠïîqž?ÍûGˆ «™Õ2u©d˜ï
+ò`É#j¬ãô¨6¥\ m¡™ô |žŽ xËá( ÛO6…„Ì!ΰAf}Is<3V½ºtzPžðXÕÃ~»±ÑhDˆL×F"‘*yp¿)«¤Ì
+} ˵+
+Ûò|O'Pá0XŽðRí3I¶›Ô>¹s¥bÅÉÀß$•†Då!AØŸz} Z@äî´
+±³i{ün]Qó5ˆÁ%Uöòs]œ`¨
+´gÉ7F9),â}Lwßg¡d)Ð`ôàF
+˜)üžÐ¯pyaûg͆S³OE§&“_C¹Š…[v%Ò»q×I}Ì'SÅ,Óê[й‡[`±8‰ZÀ™Œ
+ªVÚÔWp‹N —Ü'¤ƒn®Æá¢cæjdc3¥È:MÔ^…iéä¼ñ®zðÔt’àĨ‹™u1p/§Žk<§·Å}fÙ„!±j‘öPCƒËþ ½ Œîå¾Aøx.Þ{È3KzÉ®e6 ”!]y‘—o ï8õ,€4¨ûY¨0H"ài|ÊNiê#¾$ Dó<Ù¸mR¶s›+ŒÃgŠœ»íÇ¿ ÐâH>ßÀ“»¦Ò{pãÈ47EÕbùùû«jI•K|ƒC%`"±vF—þ“® m0­EzÕeÁPrØä9ŠÕTtBíúÌZúÝ!³  úÊ®«Ø-¤4R ”§ÿ4ú
+¡/¤Êˆ×I!€—Ÿpè‡|>€ý
+Å¢ZÁY¢ äo£Óÿà×op©ž³PÆSãe£E¿ŽÖÆhT\q£Ë‘*¨+´Ãì·›âö?Ukà 'ˆ´î^º4o…gÁà’
+›'«iaT°8à ‚A†ß¾aÄËo-Ø6±è%ªÛ¦c`w מïÿ wØ“u Ç(o¬-ÚÚ梔×QC–P‹zPb}ž|E È+ç6®-ÙSŒÂIlÕœŽV€äZ7%0Ð/À1žå”“‚”4M…ÇïD"
+ÕÊykR9×R˜£d%JåØs.»3]2¥Cß<1 p‘Ä˺u õ»ÙU‹®
+‚[îDpÇ,`÷\‘¶K;
+5€§j[/õ,Vtíî•@I€;  ÎX<‹
+3â0iP”¼"?çÛaÏHerý@Æ nÒ-ĺh)4¼³ÓÐþà®e4ãPß š‹iè/îSíÆ/ˆØçƒà4ô!mCƒ']v %ACÃq¥¥~+ûN”¥AprØ©bWcƒµQÆ®O%“Ý ì¶Xô?a?$1ÏÀ+§vvà‰ÁÐÆE?GäE„lb¥ƒÐ<ËA“é±L*ä—öË“h1‚<1BÖv‘k” y͈…}ï4 ¿£ ÿ±]æ:ŽW}Æ
+µ/¡‡N ȱag
+mÀoïsn9IHõtÝ¿–»|˾×Éñ¹â0#þUh›Xhyhjˆ³YÒr·C4Ñ/D9Ûí(ìØm¡òý1KúA-&)¤a:¸E
+7½ÏÞj Ðly^‹
+®p·#•É~Ý ‡„¢ÇF›nË3QXüÞ~ Q¨ýsAnåf¼½Œþr˜QäTñ"rÉÖ£f‰³Ñl[ îG‹£X^YJ¥ÕÔI  t
+ÚI«ÝŒ‚ÉN”þƒ¨¼T1D
+¨™^¾Ep뛪5Ì„¯r—<ˆ¶lÊ.š>‰Bx‘Ю€·l7«.ÀΑß#^ÀKÚaÍèÛÏ}xàu®‡4¦‚k“KQ]@-¢ó#Ëídä¿‚
+A[‹oåÍè…wÈH¥—p©}@XÌ;쟋4‹E9R¢|ÁiºØÐÝÚ×ߟÍæÑv G)ûÛÇ oëqƒ¤e¤qʺ£¾ç‘Y¼ó–.¼Ì™¢xR5
+?W>£þvo&1±ŒØ:ܱÛQ×jøìµ8¨%Gv(Ò»ü3…oy/–NæçœÏ( S½O¢@lŠŽ¿Ið.jK›`¯ãƒ8ýËV*´Ïõ§‘ÊØ?Ô¿ôU5>f¦ %«´^H0óÞIÂ@t}¼3nœóNÁ,¶@¶Žêk!îr=$øu —tŽóAÁŒ+ïùe‰ùÇ’"~ŽF?z4*Ò´¶
+L1Õ¾Dî8¬%ÚܾOî¿léTž‰#—Ü­uN2*,J̇0EÔZ± ‡O×ÚòxÊ*ô“ôYJDµ +h˜}]'8k„žòyNU
+)t2CŠ€øéÿ`õ¡K XH´¼‹ÞØüKò14äPCC Æ9%\|À
+&¾ÍÅ:Q´Û<û Ï] æºRf“•\§
+2Héb,Ú£­ÎÐ9³à[-qÇ`c«ìƒ†á%ȸòG··°9ŒÂ6D$@È!CÑm×Èò š#½3† „ç„Í©äº`Í
+«T‡€>’àäá2»r9éw—ó…EÑhmàOþû òksÙ‹I0ŠþÊF5Ò¨Ì
+5ÌÊÿY/“\Kn#Šn%‡`%›$™öHÍ
+ì504ÊïÞç\æ{å‰í‰€„ÿ"’M0â6Wßpo2ŽK$ úìö=irn±«AÖ–‹\¯ÃÀ‚fìeF÷ÒHž¥G-âÕï´Õ6ƒÔdÀÉÀ•yÞ£=³0ôº˜˜³íAé _ëpQÖñsÑIBƒ’tyïõË)ø3›\/ãÏd:köÚƒn׹ȽÛY¡Ì€)ܽ ªxèìÉ"Íàlð—윯k‹œncføPýÐ%ë-ïÔK¼ ÁòŸ°c¤Ñµ¿žL€V·{ø_
+ì¥è¾ûþó—Ÿ~ùôå—ßûùó¿Ž¿ðÓ7fÚÀýZ¿=¾ûû—Ï¿üöã›~øþÓ§þú·ß¿ülî·ÇŸÈü+ÿEþýôh’0RA¬Ü¼[è-õ`û9¯Â‰zï‡Ö,ÍÍa:|††8†nÀëÍîƒÉÚM:9lßñÔ„(“7¼ãï|„úY¹&¢'"œhwËbà|Í~‚ µËô=Éÿ!ô™¿iæîv€ZOÀÚ †™²D9ÄëÖÌ r†ÎŒ²;™èãZ¢r‹+ÂWZ¥N3/Ï¢_{ÜPSLDÐ ÔBž½=ú´«÷ 8šØ}@ѵ8/ÕVY¸F
+ÚÞŒŒ
+¦Ü®’œãÙ‰7}Ò_U[
+({£ªrd W½ÚÇÈÈímÐaŒŠºi
+õ±žVO™Sïþ˜tÞª3˜Ýë½oš…¦Û6˜§SlY…Að$Xµo¤ÐÍþŽ´û}QÞÇ‹^å‘–¥ÈèÁ.lhŽ¦Ó ¶û€¶ TCž AM¯JE>êå±xT-®~Zés´×Ùq 032h.5~¡u ‹<< c’€48: dˆ)ža:cç<ß°¹™ÆÿX·pGŽøA+?Õò»eÛØ2lµ¢ž;?Tˆ7ãµ( M­½Í.43\èNF;ÏóUGMñNEv)U—Y8/ >ã)ü6-‚ˆ†ØTUþ©ê¸´œ’’©S9N]ànªw;¡Ü±åTÊѢøºÏwníß”uŸEšsòú‡g 7‰¦Ï] Ö;Fp=;)œš÷E9
+­‚hat
+dz¨åÙ‰
+ 4•¦¨aBti3ÀQÜNW2‚ʧÅÈó¯¾î„³‚–¹8oF©å(„çA„4üö`´!ÀE[Ì°°™¸ŠèÈ!;=NÓî])¾óz¿ é›t$Iתûc'•ßÁð–@·ÉøZXJoßÍp¦“ÑÞ“Üž–ñ-ê^Wç¶{
+ƒÝ-FSMD™¶|u9pW÷Ñ•«'€W3@SÑÞÄR´³5Á.é|"’—
+”eÊŽNW} Mĸ—·|^ƒ¿
+E#ðzïÀò5 Ü5–À_WA»)j¹ÌÜÁ«•|…&=  Yîì}¯}($JIàÙâ|§‰—‰¬R“bgb_«ÅÓiwG¥7Àà[J¼*ÆTk^ÿT¥¶^ßÜ}2oPÑ4Tl,áÞ>¢|i††õYþ¶
+
++ÕÄGÉó#û÷j÷ÜðÉ\bEûqi_ðüB½C8¿9õ‹œž»®ÎÐYÞÅáy±¡ÀxœŸ4LõZ¯Å»zÆ›’r~oŠËƒYG>®Ík(6y ÅKåX ”yèË
+fàãÀX)˜Þ4.-ÈÐ)µ1¤ÏL¿„´ŠÉ6¨9šz`·2ræŽã8 àµ”Í+C >£ý’Ôƒ}ˆá
+7X•ìrÎÃj ¥\hv)¡žGFñRœÂ@á$÷{µÍ
+ƒ©â[Î"Q«p@£ÐVÓ(¦ø‰udr# ¶[kñèC·Ê¼6uj¼Xë}Ýм,­åWOc
+![±ËÌŽiŒ(*‡áj _ Çêî^8“þ ;< /
+|™Þ˜Ž#àHwIÊÀç=Ü´Ó°0í…®FBLŽsÉÔñ‡Ô0œàÁ£ «S $‚Eñ»t©x'€ Šƒ ÃVB"ìÔ¦àÎNˆž
+
+w‰W,§xƒëÐ:M [âÉ5—¯`Î(™èDÒîhµêÑFm.h]‡%‡Ë”‘ˆŒ˜ÒOÆNhÔ؉ÁìN#¨P;;1”Àå£ôå*ES6ˆp)DÌ.foøËÇLëÌÇx?vG.Oã¡M²íú$¤2RÕ‹0eHÞŽ)|æ4©ô¹mø˜‚oõ´DLsHÊfsè‰ç½”]V
+£ðrݨuÇu«:O{J8!Ä5HÝŒUŸÜmFDçŤj¾(Gªø²´Ü`¨¾D¬lž¦áÏaöØyJCAÔ€Š€yÖïg¨{·ÓO© ÈMôà¸ú]¸E¢ïú8ÔMLPò®‚†î9Š1&B·•Ë†NcOø:&=Ü!LÀ!À˜Õ¨Q(cÞÁip"`ÈT9ã
+JÁÑï pOñ˜¸~ÐÅã`‚«CΩýM¾æúàl˦ *ìíMŠŠI*·ƒ=VŒ
+7¡ð$õ®^—뼄/aÈØ` ¬eeEqK™ù⎆;ÛúËB
+%ùŒ÷õ“Fè¸*LKAK„ôXgÚsM뀆Žˆ\ÌŠm]È¢SåN<h±­}v¡·eƒXàðœïªpkš¡^Ž”ë®Ñv!¥h»{¤“< º}h«ìbº ¯¢ îLä:£É)6×£qÆÎÔÌ!b„“zç2(VøtÄ‚8K¬
+kXö’p—R®‹\85R\vss9lxÜÁó•Z&Ù 1sz£2DY#–iø"œÓŒˆV$¢›(#zÐ*BÐLÀë°Ä`݇‹) RLÔô“F ÎÐÂõŒ¨-–Á!̌ȳÊôy£D¬úB2Ô¾® Îðiu”ЉqU WU,«^ûI_Ú±ÑåÑM)¯}ü^,G©CK1H§°w¯ˆ""<Ǽo©Dg!:ë[fµˆ•)Âl2ž! ÏºÊH1hsŽ¤R¨U²w9 ·% íÁ²¢È.É„4ë
+[B‹3ÚM¶é&X05ðɱÓÃ*’pµ§Œd—Æ*¦ŸuÂØáaÃÖ’eÚ`CR <»Þ°x½3÷¤Ú@ ìUZMCJ è‡}H [6/†/Å/ô¸ÈÔc!Í“Å‘Eµàº¹<QK´¶×Vø]Ôžr˧3ÖÙJj²±¤¹Î#ŒùÝ>)ODp°š¨e"È9p¸«ƒQÀ_îÔº ÙM8d„ JDßÂ\ Ö×VîÄô´Ìˆ:±v9ϼ#Qº€
+<H|êÄÄö#þï™6”ŒÁd®¶@
+•ïÄ2ß!Y®?Æ»É=VÞ8{ìG”Q<÷ˆ7ãx€­<ã2 Ä2ò
+h¿%ÑAôὤÕ<?,sƒ3ŠÂI„›Ãº> †ø€’¼/žûÓ`mª»µ¤ X_°Oos9gðè š—úºe
+˜ªM¯ˆ×*8Š]s<Šæ
+£–®
+;.:Péá…ÀŽ‹cÐñ+Q@x“†Q…,. xKn=„TU\ƒ¥´ùˆëúë1~…2ðU½-(=¸CNâ¿°CÚ-d*•å=„_ÄòEOÕÊr/8Âh”¶ Po „HÓ7ïË)
+H‰Œ—AŽ\9DOà;ä惔(Š\»—¾E³*ß;Ò/c_F•m4º²"%‘ ƒÚõÕZ¿lÄh9Äeô׺äÕ†ûÔ–üõ׿?
+”Óc6™£‚¦…È&:ƒsìj}š› @T.³“Ÿ†‡!zu3u>RÑXW=AíâšY€H.¯×Ìà£lmön!—è"M=H»"†«¤kòÁ‚¤K÷Ðüêõs]5Ôà Ô{ŽÍk&¡sl7Nþõ(—b,L»,›N1žôÄ|€ÑKæÚ|ˆÅ:Ç®Š‘Í3ê²ÿþÐ×??[Ÿ“¿ãMo1==ûë7 ’@jHïìSúÄ¥\!©#<ufž@áûgŒÙv¾S©ê¼Ó6dxÚŒdelˆ» ¤i6«n€¦oç/‡oujËŸJ\!ÈQƘí¹’ÐZ)ô:Bôò>}¤õ4‰û¦'H}6H2,´½öcÄÈ6Y¶ÉX•”zÇ4 §U³±£A²4h?Ç}S#Û¨È{lPãŠ$ãܾƒzÏ°\*£ Ó¨ôkUÊa]vˆÔ|C$y‡™´­¸x¨ùèã;Ä(É_8DÄ„b´O$™ü}=¸]i¡¬>½WŸ "Q©L‹j#[mô¤ë;hÓÕsH—çȨé¸LDm*µm÷9¡t¨ !&¹ 9Ô4EÌ{ÛbEÓ÷j¶Aó¯ÒúeIIDĹaƒr„uop_QF jÀ½ÑxÓM"®1%~ñ3¾¶æ0¢ò:ï«ÞA(ZçĈÉ×á5ä«yëˆm¶è~ŠªRJôA:еuÙQ±ôÙ£[dz›Ôw8é±×!ÇïÄXµBHI»©ê‰;ÿ~‡`ôLª‡e -1hŸ¯
+7D_ê(.JG‡’µy
+‹ÜÚªä„--å|·UʈuÉA즾NÆ:FZðJ¹ (÷ Ÿ±ŸŸ¨U~JÍ‹8nbKÐÜnÂÙÑÌƾ+òZ|P¶ÒtCpÞ5¼ û½ÓG)„—5±d“…²VÆ»yÏi¥o~zm7•_ìùMáZF.Ö‡Ï×@F¼kÔúâŸíBØJ?°ÎÝW•ãc ê•kš?A›±XJ{©âî»ï`ÚZUI…ÕÛÖáÙäo o á5ªÃiÙ²P MÕÃÔgT')œ¤»ÚñäfB¯`(Ã1²²§š^(kùd„Ï¿€Í2ÞÔ‚õ“V<®ÌÓò.;ž¡•#.¥©!:ó :ôHäs¥ù:Û«&3ÊÑŒ´Lžœ!5™PÙQÞôè˜Ã»Ÿ—Þýå‹ö»íJLq ##;k=›™áÅ(1 _GÐ366.¿\Œü1~_cž—9¦„X»dþž}2ùþ)_dèsIb¬Öâˆ×Æ·v»e jöÚ2T³’éð²¦ËŠß ®ôàö9³VΨ ñ@JKtlC&ŒD‚sC°Æ´Ûü"¸õ¬u¬%°@“-ƒpËÞ«mÙùÙÐ8Ñu
+”eŽØBï¹·ÌT]Wž!ÿoNöEï¦0‚ºlË:¦„]&±G¢UúPÇÚ[¨¬?ux}|§XŸ+fÝIœ¥]Õ‘÷,ÆØ°q±Ae¬ÕèpÞè×ôh
+‰ŸÛýz*çM÷µ},Ó¶! žûrŒé¦$ukòÁSZÖ¥ü*:Ú˜Ú.}–ý( ÏGr¤ÿâ“ç9çüÖóÌg\ìò°Å­X½,Ðw~87¸îtWM3â×kžÌ”¹ê[{ñ ¦p+íÒGS 
+ýÝDͱcG¶ìãžgØè“u®ÌÝNÃ9÷±•sRÎÿc~Ä´1]Xso]ʇ!Kòà1Ÿ¹`¶¤«.m:Óîï2Í…;ï™fq3â¾ôd”cBø¥Cw°—‘OòÑ€+
+¾"\
+cånʼK V¥hH·,«í¡6jà1¼E kÉò1ǼŒ­t/% m?Br§ÈŠnY;½c¶ø„MóöPÍXƾ±º¬õ¹òC~Š-Ô½×¼T,~2hmËõk‰ž´{e•?Fýø~ý–ºœkl©;õ§±£k£–¦œV{Û3[n§Â(xyo
+õ;dnå,ÊÌDO­þº_#Mšùfïþ²ìyugíD—0 N»Ÿ  o|6Ü-ºs×=Ê»®î,}ö‹ìÔ8¬˜â\s@Z×#W²ŒsĸøÛ¾NŽšîƒ¬ŽÌç#Æs²¿=Ý÷c Ë]‹¯÷:°¬j5«Ä·BHõ椵íõM‰#§¥$D¤\¤L‚q 9b¾Ñ³É2iâßyX€8…åD—ä-†¤ÖUa‰£[ÏÜLŒÇu¶Zc¦GùÜFC:LŒb
+{(²~P$®ö„ˆ^<§á¬k£/˜œ_’S¿alµˆdë­<ÛñJ_±üf<!l@âkÝ’CqQ°:±rFo×ÚI©ZÍï' ˆVzOÈ<÷Y½k«g6[
+¼;P°ØX¢ð¼–ØE—Œ7AA³¹Pç—“”vpYôoølA¶ÔÃw5ïŒþÝ\(6ß5e.Óx¥»d¬ÉÑ:?8~?¸ez`ƒWÎÀ5ÓÎ’_ Ôå ™žÒWøwW
+R,ï%d«¢A
+Ù-¼Y‹‰áÇÉm¤UuÖ½ƒ£ñ³% ·ÀÊ>hâ\->†Ùáiˆ‘3å8œ|§Ø ºëSàä¿ç‹‹4ʸªEžþ”í‘»×*Ÿ꿃˜"—ˆ÷NÍqÕTŠ˜97oU{U^{‚¤¨ ÇÝL‹êWÏ@#¡<(i At«rùzEåXIñ¡É} B,æWšG$åF…Ûà>« ߘw^x® ŽŸ6ìÖÖalyÈNÌ8uˆ¬¸%†£ÄV‰:€š$kóˆaTr/¯þs}Ëi²A”¦È}适tþ#ƧyÒþg—¢A-e£['Â?ZºQn9]*Ê@vϲŸߊZKSTj<aà±U´ájÎNCé¶Jõ
+èÌë±
+¿.}^ðUpüeBÓk\ùþL=‰{ăü
+³\6q’û%öi,IÜ)¼UðŠm°
+íL½s{%âûGnæJ¦)fÚ_ B±
+®^ÆäÉâèMôbUæÆë¨õ§Âs2 ûPèŠ'ܺØ:%ÉOÓxIgô.; äGÞ*¤qX
+G§j J¡oUùƒŸ‘,Z(öÂP¢äê¶o ‡;…åÊAAˆœ”˜ª:’ï4-j,M÷HûË:ÈIgdLÏÌHÎT‘tÇ@šÒ¨¼/÷­¶Þ’2ÇwÐRÖ£³(Ódçj$I%.°é²–&¹«'fåôDCà›M?PN™¦½2öPó ÜuÔÇÖ!$BírŸØ3Ã9úmnpåB⭔˚
+ œ­–â½Éëé oÕˆä¯ëBi¯‘G!–@˜ðúyK›¿ýr]Ò^ëQU¤”–ÿ º4¸+è­Á Á3éôÊÔn Î î*pÌ+ȳÁ dT–º—vkp‚4zË*_¯JÀ{ÃŒ’ï NsƒmË»ó¿·'@ßâNV^»58AðQ´•‚plï³ÁiÐQæ¶Ï“}ßœ ›hš¥|«gÑ“7õ”Vî úªL n{/åuŸÁz+ha<•>J‡È$QÜÀTFèí§(RY:Mpw­Q­˜OŽˆã–V¾@”®—ôb§ùÀ|òØæÉŸdÿó—üãw õ˜æ:½²'¿ÌåÓ4h¾¤¸¿ „!c‘IYjˆ.ÃèÈÓ6í¨³"¿ú
+ |´zŠStɇ¬T‡pSUòÅfóÈö›& #ÓYú? b³,†0FÄElÓ$`­ºnRª€K–æå'rYÄxèG
+þã ÈJ+Qn´²#<A¸tã9jÿ Õ»Y™Tn5‚Ìg8›¦Â!X2z¬•#oC W"¸úQJµy~ƒÁ) ZÌäŠk×8il¥÷×è.ÿ@ù’¦U £ó¦†¼ýŠôÕ5r¾Ôƒð×µú}Úã"îby¼èð¯a¸‡ê#ÍïKX–1Í›»ÀÉC²H˜7#âÚÞª^”çK¯Þâ´lBly ö ûÜøf³•¿¬£g£wˆqíË×äI’“ØŸ…ë¡r)²ž³W9yde['ÍžKgÄ:›U+>!—3!.õ•Gj7¢†^uY>0ÙB !üAtÑóØ8Ä>é5ag´Ã‚û#'^ò?4D‘Š xèG­úÙ^ž¨>¢˜™Ot½ä€ÀØÑEËØJÞ©‘¡±U›N” ¯ú‡ò2É#¢è tÀàLÆZ[ßÂ@¯äûoû}2Xpe2nÀ2 Õ/Áˆ?À¡Èn®‡‰ù>é‡ÎƒÿÃÌšJ´è+Sç†î;!è*ÅØ/ð˜]OÚâÓs‘™SM°cx;HÆËiíDãÉ9ô‚èë:œ¢éÒ_"A×3Esåc4ƒLLòx'®Ð¥ÒAiØ·Eqý\§µ´có€}a ²É8šq hóâÞ²·º¶EÍ“ÕàÀ´©”=ØWÕ7¤ÒXY#d‹NàµQYILu€œíÐm† Qq^¼íʇXÍ.¾«1w’ËxÑ
+Rw,ª²’ØÌ·2…6Þ‘HÛß Y·$¿9סGaV}ÑöV˜ |bÀ¾éÍ;T*®ÃŠ4눶DUä-Ôö°´PÃ<eÞjάÕ546 Œ)£ÌáäG¿>Î HŠ¢³=5œ­Ã^¼ŠÉ´nc £7íƒz¯Ã(íhî KG°ïÏwlAè, FoïEæ´â# Ê}oø^¥Wö2P+ )YŒ«ÂCóÞ©½¢ƒ,ƒˆ³¯„M_„íøå+V³â_o©má.ºÇAÈYj¢[Éý§Útw³[ÿq%oØ&«PZ9@|n~ÉCMÁS\òÄ}äR”#•’Ö½ +qF¿ÖˆµÅ.Ö”iÇÃ*´Œô•1ªc†"d>YìGvM°·ÌÅ!S­¤ ’&tÇC…y|.ê2†$1f(Z·c`ª“ö¥ˆ1ìÁT4픽Ò)n™Ñªï1hã
+¥Ã&9f^ƒÅƒTq@P¡KŒ¶š$v†Gç"°!—¦Zal{üžQâ5¨lm»©7ÈÚ*c4¹BÓÃ::9Ám~õKEFW5ôîøvÞµ9"éy¢9¨Ât2ü¨â\Jfh¢.¿wTÅÉ/Íé0Y¢´ÍIÂ7ßà±€÷UÈžIv›d!É>gS¬)gL[ÆâÂ0ñSúŠCâ)ì…,<ÆÆ_›jAAzqó­¤û²!òw Ôªd÷‹}-Ãád‡ûõeº</Ê“N½&‰ãˆ_е‹~ÐÐ<£™i‰¹ÀïÌ[fº#h
+ì>Ì¡ÓpM'Ì»]BÏDªH‹õ‰ÄFÚ:Ò'¡m° ÅãÛ%|øN7Îã¿—Î
+9§ŠòkĪZd&¼×ic×Ö­èNÌ –þ9ùÅA=–‹¼C.éCC‘6 ™ž õ ïÌ_àõä›1x2÷Y
+ºX’cÛ¨Ú>"½1s6F‡XŸ¬¢¾à[5Çø¨o &H5Ù7*keÓm\FTÄÚȯ¥­Ø™2èyÛdpY')f1r6uoÓSQä¢MD&Î&P¡éÐëk§"#ŒƒÂòûÅqÆ4¤ 7EÞê2ÚÙG†p?…¾)U‰©’2àøy.oR¬
+^/¾Qgv¹4‡JÞÈÒI~Å‹¯ ?$ÒLûFüÓ º ’;ºOðâb%¤(Sê;a€hb|o® *ãàG#:סºbX± É
+P«ð׈„ÁÓãâœèª1G£t"œY๢<3šÖw'¿™œYˆ
+38N=Õ“Óùù
+D‹ý>ás¾hÊî5FüiÙœ¼ d[¢Sƒ!YÖD69зº(…@I›Pü6 ˆ‘hŒÊ„øCÐz¦›éoA‚V I¹wAä–渢h¾Uº$×ÔÏ×ٱɔhX™ëhÈ1›(àð øI¡M
+Ru….ù‚ÑÜrâ"PMÊ•ÓÚŠ9Õ.l×v<ÔÕ»‘×:òQ C¡ÂýëuO~€¸&Wä©}=¯Ó4LŽcØ=ù™z )£¼bªííß“ Íé iíSô r#4Ï0·ýĬ*
+'óäD2ú¥¨ ÍÎÃ…<¨¤<Ý°tHùP§-ø2ž}®ƒC#0â~I`íYîdA¨lX£Ÿœ¸¨„ë&RNŽ¥X,zøÃa>ÅŒq® ˆTmYTóÔdˆ1-÷Ñ6øf_¥!5].ìKäí©&"mKCB—° ™ɘ™‚
+cƪ²@ñ(5F+Œ@,±* íc*™«N ÿ\£âIYª€öz>ŸãÂðY¨½ @Šúì'øl=â&´‹C©uû
+ȾfýØŒ·ÓË`α(J Fpcù﹕Š½fƒ§yöW vbåHD¹,Í(PDLA䔯ÀÒÄDšm>%°7n%8Îp©€ÂZ¾®3Þ¬Þd:¢XBȃ-øéÌæ¾gõÑáçTe‰S®Õ Sá¹s}èm’ª`ŒÖ²]Û&Žø¬uU±`‘¡§eO2.Á=Æ9IMžzŸ¶óYjz_­Ò<ÍÁd³‰Æ°¾ÎÆ&cÒž¾îK0P@Z‰5evºøhÉþhì~aÿòÛ??f—†ªl4Ø\ÀEú‚‚{ÖvpÄÝšµ6æ¡h66Ž§"Ëàü^ôO>2e§%œ@I~ÎèL; .…Õ 9 a1§  ŒªM\ŠçÀ#¨¼2°UB6lšÌÅ
+>óz}.ÝQ¿ž{tÆ ¬`^!CÎ. KÍC#xn¶Ñ7u%†^tqOSc†ž%mÎ~!þ¸©1μø¿¶¨ ¸óý.ˆÞ± ð¤T7rÛÆLš°é­|Sò¿S4˜±'¿çPôû›"ÖAÆüš,éÞuã«ê
+e„MÀÙ³ìZLêYæÙ(vÈuƒ÷íôÖi&õóYÏ9šyÌGcKùeÞ ©Èë=†ÙÕ8
+Y#Í
+êL5^åO:n¬mäŸl¼Þ¿†Ÿ„”/qzü¸G[šd%p©Mšô»˜õ¨`k±ÄA«;¤õ%…ôý›’ÏöãP„ß`û†VnŠÆS•.{ÏÍ)MôÌR/Ï›¦ë—ïÅ:Ú$ÊüÜ4ŒV, ‹ÚŽÞ¬â
+4¾ÄÊp"6­äøVL3Cèà÷ÑxK}Àý¤em}›…~–XaþkBˆ¦sä×hœX‚z, 7(1u;ÂrŸÏj ƒñÛ{`¤XTîaÉ1Œ¸ààO^âW ÷5‘=‰.éÚ–àÃP ºN "Ô™þȬ1Ø.ZÏLK@)¼…¹Vp'¸)H¹×þ\ŃÀÁ躟~bÉíb¬HÅ[lΆÇ;
+Íÿ¢º³mü8䦸
+‡1}ÄÕGŠDpHùòzÙµ ƒ“—Ë ³„lßÇ’‹~ž]½sÝæ_ñO|à¿nµ»bŠð}(úýM~ê)ŠèY©5ñ¸,èƒy„ˬˆØe<÷Á"?žàbvÜ솭¦çÈס±É<‘­WŸ°zxC¾`¦À•³bÓõwÞÆDÂ3󷄶@XRõKXõ¦nÀIè̲ÚЉ›Ù§°n0„õ©sÑ¬Ú AóŠ´Œ+ _§7²5qvÐ- ‡xHZå!Ù¶¼3ÑG¿.:uည¤°eê¥ä‘`Zž!ùÿǯO§
+>\§‰:,±ÃÏðý¤¯‘CÈï,,/ƵF æ§(WPŽ4ðªAÏ# ¨y­p(ö˜¿vCÁ
+Èþ}ÍËe¿ÿæ‹þõÿåëÜT K)ÿjòO!üÅjÒE
+Ò0½NEô)À‚"ÜõT„ùc™ûµ('Û¸-U¹:¯Ì\ ¦Ÿîr{Š°<Äeå>C’¬l×5\!3”0O"% cÀÈ:ó-°Y[‡ ¥¦zù¨=Ÿ‡‡#€­¶Œ¢9Œ`­a›ç(LT3£¢üÄ›â^®°­ov¸4~8³ê±K&ÌŠ·£ÓqSòëÌb É-«ÈXÂþ±©ú
+­²^jÂoÒüSµ—;zÇMÕŽ` ”˜òµ".BÇø;,^*§+RfЩ:¬
+Í
+ñ'ŒTì«P>zÁ¯nÅŒ¢ëJ,ŽÛ*ʼtúR+%<gp-ä;®º§
+j‘6²ë*,½ä§½>´îÓ±°Òö-óL³)ZËæ”ùµÅVЃjÎá#×  l
+ŒAwº¡3I ïš.VzÖ‘Ÿ«¾ [Áœ_ç¾·3¯!ã„©0Rí›’—ý3¬$YòŽ¯b¿ IýÌ’Ç"(À¸g”€0¨næôLÞ×aÍa3Ô~XA‚dß0š£]+èêdPW›|ÿ sa³è
+FÔT.À½KôªXMôZ¡ÚCµ^›ÕJƒ7¹÷B^Ç<ý$<ô꣪‚‘„»lÑÂÇÁ-¬ˆYºBÕ’VÙ–ÕîDoHY=ý;A
+ÇBÞZ3nËüšÀx)YCë±~>B^‚Àt­û(‹ÌôúeO$¨µu÷ÚJ¾mÞ¢zíÑ kºOKz˜W°’{[ÎØÝ
+¤¯5‘àe©.Oyìô_œ«G1Ãå²çuù×EiNíÙpsàúñëMÑŽ|–‡h’=®ß.d$c‹Ñ×u•5[×KŒ­hk¸À²,:‘O­ àƒÕ¶Ù^)áÙI!Õí+S:Ù aý(œYQÐb]1yK¤ H‡õ>©ÏÊRðqû Þ6$è )ñwH"ësÒ±Ú:£äÊk/IŠÈbÝ%<˽Ü%˜q!˜&?Þ„Ìæ9Þ ŒW¾é¬gŸ{Ù•ï‘Ýd¼ÈØ`Ó†£¢G«H ñØCW7*ð·õ i˜|›ýº‹ÎÐ"š>¶GÉʉ¨Ð` £ŠGl×¾Œ³ö¾œT¦ç¤5º¦ó•éÛÀ`yS TÎ:éMJÜÌqFçº>RÄœë¼Ð
+Zxk¾–Çp°WD…áGÔTÚ²<Wv81Î{«\ŸµÝ²éÏI-¡Éò½DƒwJ½6VœŸá7Ê8ˆp‚0GÀ&Ï4o»§‰hAkŸ±2¦ “e}—s[bbi”wc«Ãû1v•$Ê™õ˜ýº‰
+?q£ÆflœÈôU´FE)LËf’Ë«lÈ>o²£H²»kJR‹˜ì®xM–¡•5hÑQÈßéÜÇV-më2”‰‹.¼öþÉwïF\«…fLÜeæûIÔš¿ÙQ›æEééj6èpŸ6u JLÊ]y³3ãõŠµò™å±¤Ú
+ñØRÑmÅŠ˜ü÷¸+âu78¨¡×¿sRÉ^‡z0À9‰r-FBñ:®¹Óßq5-ëGy&:ÁÛÚ³^2£X%/¸®û(é+ý0XÛ>Š®º˜Qͯç;ñã.½TSÚï,yöE~½Ä{ Æ­u|%á
+cnöÞŒ¢(†… ‹uMBH"dÀ±ðÕd,@¬7gI¡~çWða Þ"/£Ë§fÅa1Ont_ð;üS;..®½g‘¤’Qb³Ãó-²g̲(æÿ?žÏ´(â1•ŒGã…’òØiRl»Á6„Ù£³I‹ÕûÝUNôóÕ†à‘ÜZƒÊ¯öó;GŸàSŽúõ¨Üê›QJΨ»Cí×»9×ë:uG]ˆÝI¡«òìçïà¤ï‰3ºç_¨``Ø¢Eü”Ø‚TZòš`‹=]PŒ—ð%î…5%¤+Žn?Ô‰™“³–q¨ r@B¡Føx±•ül÷Q 0B—°1D4à’cBýUÕè¯ì º®wI‹ i4¢¼)y‘ôyQa“]-Óñ1»ÍÕoƒK ž½êŠdÞ†Ft§\–dÏ=IìµÇݘî±tŽ2½É¬”øÁ‹:»ú9sEwØ],²Õºc#á’ ¶/wÉS…=Únf9-HKˆºKZL‰%kqÒð˜gÎÛq^QE’»ýò ¶¬üÁ°·B«þp{ß¼øwK}˜ÜV_+úA+Î#ÎéGH¥™±V¹Ë¨  5©c¹ÍEºÂ Áîó ˜ìðY)W7¬xÜ/Eîí÷¤Ò[[Ìã’,b,£1T¨í¸ºGñËþXÅ”åùÊÏÞ5bFµ'vŒÞuù;ÈA»U±bÇ>½³NÆX7ðë‚=°3¸ëËÓ[Ü^Ïú•ÑœÚîÎú܇`»%jz[C¯4L÷FƒK¼:ßU:k½
+ÕÏœòçL8ýzW”-8ö
+î¾všJt8’Õ7(A%<_àÄýz” §!Ê 1×ÃGG†OFâ˜Lù£¦È ee§,Ó篃ÉP©¨Æ<lXB0¹UH–ŒDqºÑ9°mYÓ‹ØìÁ§k-JyÈèìØGŽM/N¹`œGC@ÓOC<­8X¢ ,Â"`>HV²Qš³¥±Å¸³©ÓoÌÄM¸¬­ó²ÙlÙ†áaT²˜‹*Èœhж¥0cdܶš4Œ— 8Ãgu/ˆGÈ»‚x:T…ºÿoAñxA‡&
+0eƒ`$¸[«j‚ŠèO·–~Ò
+4-Ÿ»UREea ,iÈ{#ø| àp:ÁE&n£ÛÒQ\"@C ëp¬ƒHtÐoáˆCd˜7éÞìo5˜}£ÀÓ#·P]›OÈOd½¶ªºµ¾ZJ&“ vd‚¦—ÄgÖ ¡øLrUxxÊq‹¹‹ü÷Vß óéÉœ04tqUnZ¾IJÑ…>߀N6­e(q ø"À FìwA/Û}Ü9“ýºÖY‘8z¡BEd¡´’úýô2`€"—Az‹#R€ÎÛ]ïw äšHèÅ+`^ »ÎËy˜èãNÅõ0u"²´¦äEvèZ¨OCÀŠ  sðSñÒPQPº|€P!Œaè;§á¡°Bˆ%$!‡-ÌÖT‹ ¢!B¢š™ "lÅe‡¦fç=œ29Ž¯·ö¨<J”ƒQ‚)ó¹Ô@ ’ D—38¶â
+6Êa<ÒÈi¹1¹ü»!É.D[xSYG\ƒ‰uql[Á)Øf™œ[åáð¢˜$­ƒ¾¡4ˆSã@»: Q$–$š€Æxó±k,+ŒI˜¡ï­`ìp\aWËÌÐfÙG;rà8¯AŠs¯S°üE3oÅ-M9œÞf¿¸äáàÕE×ÉÁòXŽÔˆe1½`·eŠôL>€•‚"”fê“ß ô=‹hx1tx@wÂPð_Êð=H!߀/輇ºÝQCYÔ<<‡¬¿Kß F¯Òfú$´UA„ï‘WHÛ:<V•Š_êÑqgT$*,H x?´mƒ6à4lfäAÈ£2½ƒpä®Q%«jµ8’  q «Ì7›`V2F˜óf "}†éAŽ}À¿Ìg½0pá´v:#y¢G†–À#ÄanÏÙj0Ù³Ñä×\/í€Î¥ó §ò;ë#ʇá±x¢'·¦ÊÇÍÓ.„œz²ºÅGȈ¦ªÉÏÇ`#,=+eÅt8úÚÖšÝ €cÄâ`÷Y&îŠúqHVö 'f\£­±†Ó`ýêñý‡qÞ…0YàڲߜQ‹ø=Ýe.ú ÒêÞÂ&s©QH|³˜šŒ@ŒE Ãýœê
+ÜrÍ1¾…—öÒõ3L€
+fFš&TëDK,è)5ÜÒÌÀ)@ñ€‡‘L5Уè¬,žEºª†¬<å¬Pæ&K]“ïƒNþ½Vt¾ÓÊJÂøÐÉäß8“ýºÖÕäW‚-ä„'àY‚oK]ÌY§ÓSDŸðÅ^Ú@çÝ®·»ºº÷šŸ©ÀB¼/ÝÞîcNß{”«‚}_m=J©Ï‚‘ƒñ0ŸP­s¨Ï_¥@Ä ¨a–Tü“û ÓÑٮ²Š»5bÁß8c,b^œýXýį0VE ò¨=³ñʈðKœ·A×í y"{Õ8æ0縛Ý
+&ÚÆ$ô¹¶‚Ö—`âŠ%3udHRvvd‚‘¾6dlÆdÈÄ> Ò3"Á‚äèôµmE>H
+((|ÝdšøÖP„²#ó?Ê“ôX­{>pH¡ÔŠ0 dFj‡L" ½8?ê LÖ#sjdÍ[§ë|§¨R—~@òÙ“Ö¢ ÍÁààXÇ9°mU0F:H!÷VQÉFV#«:ô)œÈ‰”ÚQã¦'§‚U$§J ‘§(eo9 Öˆ¡Ì
+L>ÛœzDŒ9–Ú´«qi/ž.Í£Ê]d"òoeÚyZ’¥=Pè i*=lƒëR—-÷Æ‹ð$4‚¸ºTf—†~G¹ë ÂGk³Ì¢Ue+}JácÏăx"AÔ³%lÀ؇Qü‡èòzk«Ø¦=ÈÝ6A;e…7­Ã[d¹v]æÌ ³Sv¾\Vë d¼cÐ7aœ!Ö¥ƒTVd&Z8(ZB­×V—N“Ü6°¦û=‡+þÌü·z1D~ø“bq ¶•3Xçu2n—Dÿ} ÆùVpÜRyŶRÁ906¸×z<¹)Ë~~ÂPQV4Ý·ÂJ¶®Ö
+h$½oah©ƒ«u*üV¹ɱíDzÖ'Í
+Ñl£‰‰x&EÜ|,Vé¼_"HÆâ[^¬cys¾/ðûZ2à·ÇÍDÚ9®ûý…›: –D'´ø£‘ Faæ¨÷õ%¦]+v >Љj2“<tŒñ¹ñŒo ©G]dÅ„¯D¡„©¬áÊZÖ£¾NÏÀ EÇxÔ7Úú"õoô×ù-7óë`g~êH4’Wæ•_ÿ@„~õûCÅœþýo“þktñŠÍºêèbýGœp;B„G™ô 3Y­úR46Ý«žX´J®¹öŸ÷\‘‡-Æó¥Øiâie"5>°ñ}èt[_2?HÅ$-ÇÄ:‹-[µÎÙ¨0ð¿u\f<ª’öºÂ•æ¯º%(É~ãS%ÞØT-߾Ϣûˆ'€ßÛ˜÷k¾;I«OöWrùû›²çw$¯fÐüâ>[SD? íxàó©„IÎÁGÀ;j죠à¡4-ÇÜmõàç^wÉÒ„†’ØR@qLT®;Çž«Ð$FÓ`Q„‘† J gã¶Ûó$†ÔÒ:kI~¢c³^D£®ƒîØÛ͵Y’®ìä¶ç2’«­Þ2ÿJëCa™{–4ÄßóŠ 䔓Þhd–p]ïÌ"Ï64/#èÇÁ÷.²Ð<Žá¦›¶k¬p]ìΨ/%“t®à%J
+ðïçpÙâºÎݦ·pëÂBŽ¤XÄ­¶™¾\xz†¼ºóhö¼Š©4©¶ß“ßD’D/ãü ,¾Îå}¬ÓЕO¡‡²*èCø…ºË%Ä´¨øo︪1mAÔõÈ*ŸQº.ª
+Ž7Î "Hñ³¯öuT¼%§\iÖ(²Å„ •6ÞĬéÏéË}ÆÂFò^+’߈‘ õtï­ˆ á%-pùtΩô½äK*ýP³-–{=J¬‘§ëѪˆ4J
+­oLš’\oK®K^Š˜ú=ÁÓo>ó‡!ÿPòߺøóëþ(úõf¡sé4³o£…qK Oœ4u¹x|ØnmÃ[›QmhàT”²¯¢Ÿ;¼•u ؃JÛ4¾øõ#’êèU‚CM¡‡ºß n¶ï9[})™né‹z|?ÆG 9ÂýÇ*!Sqê×БYk±ëQØú’o[ÂÐc{­}ßW÷Žc‹­@1ç Màp ‹ ¬zÀÌmGixÓ˜°1}p«ÑM]ˆ½¶B¦Ò~;*²‰)¶AJ§˜U»ÀvN“Ý”Úãñmú( Û»
+Oÿ”XoÁÖ[)óS:“¯{ê>=ó[7v(ž9ç ·™BjW‰ïˆ#ñjK¾úÚ—"|‡|PŒ»Gw¾ÝÞb0\Çv¾>
+Ø`¬Gº®ZWÿ0#0J¹ç
+yÈÜ$Zѱ)›…u_™Ê0Ì0Sh2^~IÉ:¸÷¦d÷*IÜ £xûrÐlMôùÞC”³(æSâÈ øñ2lŒù[üu@ïW(òˆY
+#:3ã6¡õ½‹T¶ê˜Ö‡ˆTœ*â}fyL]µh÷”Ö‘tÃÄõé_ƒXûb¯ûSIÂå °ç$Eø ".Ⱦ×Ƚø¦áZ¹Êzgä÷u¸F¬Þ`“‘³ôY„€¾/¯aÊŽç°WÀ'½ýEíNìÜ i¶J‡+d—8÷‘A‘ÝÖ6Ïmý­9#¦¥¬oÝ™°´ ‹ôÇÃ_k.ô±g§pç‡cTÔjèÞùZ‚;êÕ÷„‘9_Š¢¿ÂÜ{Y/ÿ^Ä@ˆn§¥-ãYî§RÙ^V[çkö1HjuGÆ<ó2ü;ǿņ`ˆùtôíô
+Ø—ó5p´Wz§37ÜsB‚‘®lT‚[ÝR¢O¢E‹óxnÃXbóŽ•œŸ²;¤Šßô¿Ú“I#D(¢mcž¬’<çvç´m‚­] ag^5
+îïÇ*‘’˜‚—ù¡+þ62I‰ïU´UX¡`¥7™þÎ ‡&ë:ÇpBéC&ÎX¢ÝøÄÓqOÉ?¥OÅ#[ý%Nfû%£œ©‚aƒ·Ëç á©2ÒãžØ²GìÉÁÞ—YŠ‘<‰%)ñâ{ÑK¼pŸ=ÛjÉÚ²¶ÜêÞ¶á²ÒsÑŸüÙòÇy¹âq"JclúòµÑ­qce S7µ,®)¸Áö@uRšcÞpEÌT0øHù½âtÇÕ·uo¥~ì¦Èò5çœ@\Cɱv*{{ô~ ÿSXWª?jŒ·l4Áö8³-ü‘Ôéa)aäÍ‘ÊÙ¥¯ÌƬÓOW„†Âšè¾$¢¥ ªÓÁ”d @`ÈçúT¤>rÁ³ŒÛ0’5‹Ù=קJ–.¶•6?‰ï˜YOYo7GoÜz*¨b‹•ôë§Â]=¬9î2®Ž-Š}Xíã è”è¥ÕóCÐ@ó’Ñ&Ù~5o£Ä°#,œØzSR”Ó}ŽU{/É*žÚÜ®«<ŸúVÄ
+H‰Œ—KŽœ9„OPwÈu“ERåÀ[oçF÷Ê^Îýç IiÀùÿ…)ÃÝ®G¤D‘Á`У<Û%gwŸÃ?>ê|š÷¬¥ŒR²øã_.Þ3Ú˜5u<çðê“¿}øÜlÖ<,ù¿ 2rXµˆiéç”huôÓÚ]5ž½êë3ZÆyrRïaüFç´ÚÚœ•cfžsjím–ÓÇ‚dÌÌ>{xñ±!¥OÞÓg‚ÜW|KæÃÖ
+HÉ Š:‡ Þ«¢q#„±!™|“5rÎ||[ œ9‚GL¯Å6(Jd¸ó¨Ÿ‘›ÖŒ€HÚë¤â^ª7#+A¢Žiµz?J"xy³…h³Ö< ×sHŠ~zŸ6w=úõ*óõ(Ê9£Göl:Å³ð„¢°ÛIÍðQkÍ^³„ QÈ)¶9ê9e–(ÉïgÄ!N4ΈҭB•j•»¼“Ž©sÒ#õ¼fyJea$”DǺŠç–RKO·C-x8Ìbõó¤®Ò¶!®ýMãÔh½¬ªX§âY{-mCÌZã»2ë~Ôl…”:Ê|bâ‘;±kóäP:Àb¨>w-U>(åhó#EhôUŽ|ýÞ¬ŽJ­ÛªÁ$ ¥ôÒàE=‹ëЯïg*РHSÇP:„®eÂõì|KŸŠu š|ÚÉN1é:që²®jƒË¼7ÞÞ^çèj‘­åª%ìã,ÔìDÓdiF-fuxpÔãM7/#ºëcûªK'ÐôFÅÖ1ä~ûPÔ±Éïxéê])4¡ÖD¼!1Pº¡Õ­(BkºuêÏI=í¾Îé°qŒ€Ú¥ž`hƒNgÀÀ\êX”d¯”pCÌŒª 1°o_• 9ª³©eVÉ;Lr·Q0û’-zw9ÿîsú³÷I›Yt½ó£¡o¡Î¯WÝ€<{JŒR—ßDcЙGF] ½yU§ï¨05h½£×,e0èR¨Iˆ9*z²²Ã•ð
+í/tç†ôÑ](.ÖªVêöAå`In}!Ã4.6+D3£àÀ°B˜£¢}Q«5-TìDCP:ôoöMÀJš¦œh46˜“ÖÛ7ј­Zãý/L$ÔA£ÄHé ‚IŠ¹þÖº‹H<äNL)1)£T÷b’Ï©—ÌCÁÇ÷g2$B1®Æ—Ao×ý(]s½Ž¬jkØ@ÔWÌi‡š»oÞ„¶ÓPNfþï—ý‘C7ªÅ¼¸9Ê8%Í ±AýÜ눉½Û¹‰¡ Þƒ¼ÌI ˆ¥«´";ÜA :7 ¸uCC›ç&(hkãö¡cÔ áPŒ¦>Õâp¹ø%ã›9JÁ˜[¶’_ cð
+çä‹´·kNO.’ë» ÂAÝNïŸ@‚öåá©1qù±®J9'òÎÈOΑ!ÚP¹¼¢Q‘mÑb!ЉÒðû&)=®ûX÷Mô4ÅÚïQ#‡…½¤%NËøL•v~ j£ÂÜ0_I¾”s(Ì8”›axz†#‹æzæ°
+Ã3 T~á ˜D0^ÄÑ>þúÏGyüûï¿þûAÉŸJ#](1A2q0 D¤k<~Ý‚ê“q‡®Wæ.ýüP}ʈNÆò6¿ 2FÊ„ t½î‹ è¾9¦Î¿I `†CíR‚`úpŽYe6$Q"tŽ¡ ‚аLyü‡/‹ „aѤ0¥‰) ‚L(¸Ÿ‹¸`ˆ©Ä³å¬cØ1|.¿v65rщ:c
+½ÊKPKé;Û0ĵ`tèdÔ¯O@XÚj ûêG LJ1Ûžˆi¥ªêm\ú‚0+9rÕƒÍÖB5¤Ü9æˆÅõm+HhcÁ¦^Ó×9œÚ
+êÝÚ d_…xæ`:"HöÉ9\KùC×~ ã 祖‰þÉ«ÆÒ4ÕxZ»ÍÐìÆiÎ%h×ßAþ¨Õ¹êŠÍr\Šäê6›Ë0æÄDÝ¿ŠÕ3dcØ.í$ð=;€ñ„Çuîš¿ç81.&/ÄŽ™·¥ú±/z¯øõ”wÚÜ„r¥ßÍ“®4¾¤æÚ o þ¿MõmõGSCÞ‡€ë9Й:õ^#¢‚(«¢õ“ù]µYÈÖ±b¡ÝŸ€ô\‚bøHÁpth]ImKð¡ó,¬Dv
+›—«Õ ÏM/Yƒ~u©&A±œ_V*HüØ8[R&»Z⻈¤‚ÉdÈ
+4¦Û°Q!Ùg€ð`”꼨wae v¼ß)‘Bô3Rs ÙA÷°Ýd.&Ñ% Û1Ï^CúX)ðCy¹žSÂ3z‡¡v¨ÅeŸèQz:ùÔ²Iµ1 OÏz69*z™üWXÔ”7v›2Oš•nÌÁ°ÚÐl<æM¦éìvö—K
+Q§8ärª«Õ› áãÉÚæaž.¶ô^ +å#ÝßËìQJÓnÔý†+_Jl‘¡qlUÇ‘¯ž¶ƒ—÷ë20 ãðf
+ZÃÇü2E\Õ¦ty:DÜØðU\Gˆƒˆ‹ƒ«GÚb:½Á'núÀŸxÉc鸞·€ÁÝþ¥?,çÉLBjpØXyë2³áþSpEú‹ž†$ÏÏÎÓ'÷NéaÚñŽAžJZ‡ŸûQú“bŠ0Îû 5,Zš;Ž-T3)Ùj7q®ô‰LýàÃ\}èÒð;ÄËczr ±žƒ×áìœ|ˆ±º$CÖ²K.y¬óÿ™[ßçŒNkTy‰$O”ÀN ê
+9Á^ÌÈ?Å¢Ð
+8’>û>sÊdÊt`sªZÞa΂7ò%…ÁgÅ ¤¿5Úyen3Ž²øøÚOjnœ¯Ö­ÈøE°+¹eMV…r±|äLüÍ¡— †&¥F@ÜÚ@!GNŒ$Øe+‘
+ñï\ôŒ½Ÿ8ÈŽžß¬dK“ú@/«ùoŠ°Q¸ƒźþ3܆ÑSYØ`ûù¡ å4†!Çœõžò1uÌpI¥PwNJô)ò‹?éR¾7çt™é¥ØTßÝñÇ)r£i¢¼
+nCAƒ,/>ºC !¿Â)m‡=ŽJ^FåŸzuÅ}k^‰nÓPòÝ:A£7¯ª þ¤3üoû§îÝ¡ˆ×T£Øõõ˜ÔC‚·÷¨#‡³º•Ø§î3œóDÎã6¯ŠŒ?g
+bSúG¸tNÄÝ=jþi©~_«—æ.´œ¿ ¨ûÛæ q3>_"~ÿ;,
+8ãñµ[Í×nd”{Å8ó V¥x2%¢%°xOvñ¨ˆ9C¼Y!VëUX0ÈŒV¶6ñ„CÂŒ-@|J&=äŸðöSðQš193™”OlUÊØpÁÁŠŠ„Œ?cŽùœÓd¤‘œ²–ŸÃ3hlrîö)ÒæfqVö<˜6E
+ðÈU3W÷ 4Ösa"öù…]Ä]a+f‹+æ`yIÕ­wAM#<`ÜeÙuOßø›KC!˜Š–Ï}8µ*ÞàÚæÅì i¯%HR±umÛ`ÿCŽƒòè´ P.à—‘Ss&úM¼#TÚž9SÐc¬8¸$ê|sÎóâcf¹B/™ƒAƒò%4œFó g\»¹É [Ù ôŸO1}8‚Ïå¦+¤6KjìœNø#ˆðWÕÈK BSyS²
+l°—‹¿x3 6W¬aš-³9•¯×m A”Òe“¼XbÏ©ܲ­7¨îð Fï¯h.<ƒ½êÍÏ!ŒAÈ"×:%U)èìKqÂb™€lâQcûøë ôju†eã[IJ]ÇÖómt…±~†Ž¬¡ôu[©ažœr1ãòP›ÖýC"\’
+,â >?¿)a!š\Éñ ö©gÑ&ÒâÛPŠ¼Ï9GÃð"qâFà˜½ìÕ‡d`GÖÇcS'" aµø—ï(3"ñóؤSvjÌÆWå.¨§ „âRI:æMµ‰Òµ-sB.W€5’Jÿ¿ž«(˜`‡Z<ÄqÓÆhØ”]/mÁ®&¢ð"Þ8!–y•#Q|C×Z;ÛçR9˜Âö¦¤"f.Ø›CŽ¨ ¢Çª"(Æj·¢/+bw°ï£Ð[Ï•…;mÉtŸÀ6V­ú9âû5åE‡©(Z 1Ç¢øÈ“˜Ȥý×dö §¹¼ƒú¶¼{ÃìÚâ8›’Æåë\¥Ñèo^oæùRbÐá#HtŸ¥ø˜Qá˽¼ã%I½ˆNÌÒÁ&Ð16çQ4
+æÂ-¶ËÒ1Ö;i=¯æ€Å®4Ñœ*žV¦Ÿ¬oêóMÉ‹Q=>üã¯_øZ­eÒûeìDÐS’n‡Eͽ ,Æ´CTÂ7îµ1oÁ²«ó´À¸Òý⨠‰ 0æ¥Ñt<Óô©ÂLS&f1(©üŠ¢a-s‰ÆAÉÍ
+ð#u±‡pÅ®¨
+HJæKóðA¶°áðìK?¬çÇK+ylpðÛŽÌÙd¯è[hP Áuê£ù‹§þN0* å¸f9,Ž}¨a1û&¡JDP6Düë¡zö–ˆY‚ÜÖ:GÑøbìê‰QîˆqEJ$Âäž®% É)ѧèmNb‘"6¿9Þ!=u¥*+*Êaòî}•h÷΢ï’ÖeаuØÈ¥•×"4WäL«¡­¾´òú1™)™À”ä‡w勼_Ÿîص05?¹± ¢VKLSmy¹\‡/[%k•œÖaÆXL0eÜ™«Ø‘Œª%<5 :­¤#tÁ–Sœ”G=±k¢Ÿ }ø
+&YN²÷sõEy@º™‘Ø„ØFê»KE˜ŠúQóùnyo‚‰.½ˆ¶Qgv]Q枣öƒK6ܽÍÐo¯òQ/
+T.˜ `wÂsže€èåzöÂÿªIEt[
+3ÜäP¨Mw`•^pÿ‚Ï0»™9Ý%'ö²Îáp–¾cTCó¥N0a b}ø›#
+`‰®†±×ëK"°!­q?óøÛJÿYE=À×Ì–«k·Ã“„Á)C<š€·fóBo ÕA`Ȭ:\.#”¹'|´çžm´<Ô<L8ä]©L†eSÙh\^à$´Ÿ¶ÁW=ìQ0e$¼jïx#¦\y¿¶ƒÕ
+Ɔ$Ç+ú¸)B+«„cB) ®,p 0ˆ=lÈ HYæÔ`£â[“ ­/Ô³_XÉÚ°#c•ŒÊ¢°ùÕÌð!¿¹»ðh ‚"§#«°¡;²c똪€òa‹âÎêÇ‘ÿûâiJ™°oÈŠGzÖÌFÇ@4™Èí.ŒÆ@°ºðâÐßÆhô«1ç°V ‹2uùlªÉ¼±+=à\¥esK7hÑRSÄT3Æ•ÊxDm.ôÕ‹é<Nœfq.1æ¦$DA›ÑÐq^ïeY%Á”¿Kbì^Ñ×q¸4OÍÍW¼››iM`Šy“¯®€¾"S@d±wŠx.‘]çî"k1š;²÷ƒè£8ÓÞ}!ĤMbv5P/„È
+p{<O°(ŠÆèä’Ö1úv‚±·¢þ’Ø>÷—H!ò¸¨{öÓ•WóƆ>eüª/Æ3K2Âbƒk1-Ö‰¡fÁŸ*I«Ù"Y"a妱eìL~àåÌÙ(¸@2…‹QWféνì¾@B[CÕE®
+è»ÉÊU3ÀH•Ë€?2©HÂÈ’~¨ÿó‰_pj‚\ˆp)ÂdÑt2„yŠPèPFUâ¡"N!°iOƒ¥ÁÃók2
+‹y-ä”À¸ãÉz‚J¾“òpÏOÉ#®]<‡¤vW%ëQ3 ËÙ§h]á–´,ÊuŠˆ¡èªÃ!žfGÿØ °”{=&üEªÏ->«â±o‹®gè2\&þTO—k
+.Ÿ
+V§r[À™frëúÒú# äx°C3$ö|Bçhºœ‰=H!züÉÇÔ3UÀÅ8WÖßY9/±‹æ_Òˆ3a,¸Cöaá ²…ÅJ0—pj+jø*áû©Ã³ùØ~Líágl‡aS%xm¾¾…FäÕreõ‘¯1CG9…/|Ƈ
+þ]²æ
+Ô}zq?ˆœ™cÌŠÒf¿)á@ú24Ñ%GaAÒd§èó¦HB1 µœ-´³­‚7Á£7šÀ?ñ*¬u@m»Zˆ(œH CK|Àl›{«äJyÿÎÇÓšN`2£
+±<XCˆª™(Ú/\0¬7Peã÷
+߆ԳD¹£–<´[˜‚’JˆV'TÂ{,Žf&’b^Öï6Ç)ÂÁ‰E¼ü§q̻ɀa\} N
+Š’T¸oþ¯Öi%Ÿ"@°Cá£ôŒ!àRGxÁû…«SEÞÁÒ´õ+Œ]
+"¦ "Šh`¬QñÖ®óVô¹Š`®¨™õ¬§²XnJðë‘à&ö¹y8·
+ê;{|¼Åª€üñÝÞé¦D世†¨Øv‡ñµ8P|_rœ…?Ì7‡Ba ḧŒ…êC¶%DJº¹`<·AVØØ&£¥’";x7Zh%Ò/À<ëM°À´
+s÷²,0ìɨ”ˆ‘Öâ3eÇ%;XvÙ|x‘X³ôj
+© ÐHBÖ(¯5ìy'Œâ´3hzx×…-xq^^­w÷Ùpd5K€ôö³/í»â›Q&>^ÞÞXÒæ…m
+E$pAªÞ9Z²KGßãˆE ˜¼Ã(zpTœr$8€÷†Þ!‹e”'Èþãæ^OO
+…äËÞöf^¶åM§½­ËOÙŒPIŠk5/ûûV´V¸±!Mi›<8O-+÷õ-d»œê®€új€H±'1ò@ü+Ú´­ÉC
+ 0JýŸñrIŽc¢è
+¼¯ H`¬7ô.<•ö?}çR”¬®J…zâ+²)ÈϽ'÷1l<M«'?®ªÕÈ *ꈨ+ªæºZ Sø¯».çàáuÔRØ ç8« Z± Êdõ( 'Šü1-
+
+>w zåNºz*Xt|k¶NÀdYs su‚ÔFFvÉæžC&Uû°¬;u±zCð„i5—8h<˜AfŽž Q<¼S‡ï²LS ùö]=ÂvÉtÒ<{¦Y€jš&K®‚˜"è—GpáQxM*¹aIÒÐ|Äð½"à†å-~ÐŽ åù#!1ÜVÖÎÙçDLèŠ<FƒìØdÆ7¹ìknÙ6†RЃ ÷WªûgÃ^7ñ&gð]êyñ‡‚h¦ŽvÁ>"ã'„Äá9áa3X¶º ž‰Ëq÷-ÈH)ºc-ƒ (³’@sX’,õ–q"…Ð)XÍàó'† ŠÀB‚Ó
+IZ3+ ¿{€ñ;¦:i«œ¨v/Þ‰æÊ‘zôç› £kJÓöÊ7A0+œßT—D »IÇ êoBÐÁP¶ÔM+˜Š ÝÛPAõ§›,|ç‡}GmÉ
+°òà éOö‡še@;ÏÚãJ™Ð9™}ÂÐVL.Ä«ªþ¶YE¡³uE|Žå“¾¯þ¨Ë{p<Ð'
+ZE“#SØÄ)ƒ Ãa ýü»Ã,aRS£!”|’ Vª`$]ÓIúø%ÎÀÕ9,½ U‚D¸Ñî~ð†ß mMß„0¼…‚à7EÛPTŽ)‚I
+S郠k3rå¥îpðs®·_)MO/°&±™ç€=SZÔÔLS!ÖW)¡}’Ü^E¥¿ašºŒŽGA1°":G–MƒA•4o?eÚ8f‚‹B ÒÆà2eî‡'ð]l…ók»ëÂxŠ‹vJ<NÒG±_ÒF– ‘­›V,6ßãE¾'Ö—”
+…äAi2T‡…˜]=–Ž—‚& †¼Ãšu©p„èKE®”âIÌ
+¢¶º$|;J ï
+,~T=å¶Ýà¢>ú4ãbÁ´¢•lÏxz‰U#=8—L<¨FB¾G†K¨Iö•A5øœ¼¡ñ
+Á\”÷2µJÊõ8ÈU° è†o\š­‚” Œ—ƒø¸×:*eGƒ @’6º•Ç)CÌ(Ó%còÃ1xy2ì(P»KëÍ¥¾v<{œl
+KûpH ßÕƒìd9‹Ž˜³}tÑD“VÕ1¬,Ìm‚£ìg3å$ÃÙµ;%ar|ÐÒ}º¦†Õ–…PÝkÞPÚ±'†ÿ(èFÚ/ÌéIÚŽ|Àt- S¯-$mÇUQŒpR¾6ƒ B((É*øDý¬ÉSƒ`}&²œˆù'p<ƒ¶kÇ…© m
+Ó-
+’6ùæ(¼ ÔBûXU#gxÖÚz@ÚNñ-’@ŠzI› —}g‹ýÄñ'Ò&¤añÒ+š5{@ÚqÈ…´£ iGA×näÊSvÜŒ ¤­§WÀˆÄÈcÒŽºúê™Ü303j¹‰ëê™Aíož©6Pt¤&ŠŒ•˜„\±?4Òv
+RÛÜ{!m‚èî
+”RéH5!UØߨ#VÒV=0‡h"yÚaÌ¡cåx)èÂÙQÐ…³¡Éy+é„À¯œ-Íä7‰£§c&nœ½ÆÏ ¬Ÿâ% 8›TÌÙæè)ëhkÒ‹%qÄÓ-m‚
+]A ú˜¾9¦Î1«$t¨œ-1¤M–aè5äl‰*¶’š‘#Îve‚p‘$Ý\ÎŽZðÆÙI¸‹Kvhû³ ¸Š©ü[fž8[ïb-P&«l$•/¨éâìüÁ±‚e-
+|]¦Û‘œÝP!¯ƒ–ÉÌk|ÜÉ_ÑÊòü9‹P†)Òœ|o‡`É°,;žÄéÃÖqf@ ®Ž_CÖ§¸*ýI£Ÿ3pIò ÔdAŸE¥ „<a›4r]ý=âʲ8Š‰Â†ì³ „Æ¥PÒ•eæ€gá–’>“Ê ÊƒõtLZ¸ÍäKµÂsRbüÔ|ò¯Hâ…1 8œä[7ä×¾Ì~®z2&]Y÷u F™~®uŽ‹»DíHí©…É\›{réÒ·_QнßÓ#9
++ÒÉ_¹O`ð±—‚.ª×%èDÿ6H —¥lôĘAÇ~((ó,ÑJ§ ?"DP»ÆÊ‚ž%¤’z˜b–ÙÊ®3 ;Ï©âÚÌE“ëãQµá2¯ƒoÙÔ9m"¡
+™†ÜÊA0íPyŒ+Bpè €k·°¶Q+ƺ¸$†$éεԂÉ_<z_é¡<"}aa‚Z€NS`Ò›¥äƹ'üXp¯½)‹êÇÎ @ñ?ãõŽœGŽøºí1F¿`nÌšr÷Šõ$sï¿_¢Ñ‘CŒgþ)¢ª¬|~YJŽÞÒžó+ßb½K;Ë1ÌÂ"«HéìÇäƫϳw×;âDt÷¶~P‚¬†Ì¥÷—&E,
+Qåq³B)É@W®Ï¬JË(Ü…îç¾à{Úo~ñ•SïŸÂùùeÛ“ìØŸX Ýû)XêV9
+œë­Zùt}¯2)éŸjlü.>:¯ÍŽñå᤽üxÔ𸲡æ—ØæOO,ËÂnùe‰¾„"0ä ŒÍÈ¥%—¢õϦ %ü\;«Fr0Hçì:šǾœÆ6Å wºi<ô<ÁÔñKŒÐ1®¬ûz3ëÍòmãÅ1J „ÐwåaR%aʃæÓP/€3§ ÄÇ­fÂÛÄÅN»”ñ8jrÁ.Yš¥"#ù EbØ ÚQ×c»3ŠæפÍüÒ%˜įe[ÖcRò=rjj®}v&JT©éìùĆDBŠXËš’D¡’&ȳÇÉŽºÜ’ðŒbRôλ(*p„0?]äp&_bÚÚ^¬°$Yž½¿8™Ðed›òãKw©
+­¡›eð†’•;¢0ÚOøǧDOÉÏPÛâÏÊ„É”\XáA.ƒìlèš½ÈbLK(eüŒáüj gE@g½=ªÈ>áÃY X¾ûº—~eL¼¦EDå.A6d[zÙse9wÉìÌw½‘³°Î¬G“Çåå:¨VÔžÖ… Ú"û’™Ö ¨=Á+—[
+¸D¦´œ±Yã2«QŹUÚ•Žíwgõ¡„­ÊfÁz‰K'ˆÞ164P9ä?ü~a
+FE9§)¸àËlï¬´é £ª¿ó¦c‰ôûCï¿&E?úÊœ™U¢åv <ÐGL½—÷Õ³–§¿)ZóÌ»ËM_ÝRÒͻމç Ü ºùp×Ñc;ØT «s´Çº _v­U뎧ÿ8Æ}qØË+ËñÁ0_•ôÝ\#ü•+ÚÎ:+‚¬–P¦É®<¾Ô˜Ñ-‘5Ó>y"\ÏZ½h=³ávWÝøܳc1qà ^÷ð3Ð!
+vœCŠ£½šâ#H€½œ–عUO@<!áï/³šÚ÷’›GœHáÇ´ˆ‰t5%ñ§_˜ 5ãßžô³ô ïÝßMðB²<d%þ¾DgÖg-Å-ÚæËþ}¢4ã7˜1[]bž ûñ‚w]"ún7§ÙW%}”â›—
+RLŠ >÷¦èÇgú”Ζ—+å°¼÷3²\,½ÜPÇÝÒã+ßfÜg\ï1)úöAQò
+‹ ’lk¿Ùû¢µÏš¢­¾ô°àg#!ƒ°)f<œ•KɺÆÊTRú¸ö˜7Ìæ>YÏÔ”ˆª¸VG®–Zö„AêÇăXè³ Ä€ž!<ÄØÊKÚsÅ<øߥ]mRò½÷“ï
+÷óž-Ù‚àv²PCsL
+ãYY,ìß
+w8} $øýž5²7\@‚ÞPe¡ðrê'oé^Ò ’’E+VÑë’ÀŒvW-þ_„W›ß*©„çЉ =£R
+8zGpfLªœ
+ÂÅ2ü!â/+Q|²˜x°ŒÐ’O“2‹¶üÇ_QK͸ ”«Ä;<‘c1y~»¨J$´m¹au Ï"觘h³Úé\Š+ãË–“.&”pÀF Û.XX¦ëÂVt÷W}wm:èµ–eÐ%]×
+ýUA¿•Øõ´üå5ivôŒ‹ æL Ðo›¿”dqà 8vÔžx–dÞmÙ·fÌø^Ûô(Ü9 b+~
+ò6ŠbÍÞ‡ŸžEÁ$XœÞå+ñ
+­»ˆq‡–|? Ç÷øµH㪠:ÁŒ¥y¶´°ü†²Ž+™•¬"ÕÑr<®$¢K’…mF8.(ckžŒ|¦¶™¬tv'çëÍã‚œÐnø‰5ÜQ‘Hnt(a½.GÒøøÆ,T²Ð"Qºê­™¢S>ŒM²í
+Šž“ËuËÿÖñÝšfþü}ÿJUYÉ8 ,1Êìê.Ðz0ŒéÑT
+ïS±¾¨
+KuK°¹DÏR f›È³¨ÚÝè'üÙþ´"ÜãÆ„ò?©EŸ§‡/B'JŠTÂß$„ø¡æ—m‰ˆfŸG£@Dû\ýËA ˜º™‡·‡ŽŠ[°äÛýO]¹ÛÄå*1 fª8‘ëú@# lèô|S‚‡çŸ=ZéW=‹¦,
+Ž©žs
+Î…q&LÝ;\ü_¿ÜÀL!¢ä®±v¤?ÿY
+v¢ò17!E´´ñ÷VB6”ãÅâû¦õÂ¥v¹åS‚!éâ•}Ñ0 E¹
+eIŒä`*˜Õ™ûYñŽ3~¯ùÖ[uôƒýÕ)ãY¤²ñ °“œ¦À¹ò9F;é%÷¥ƒ¿W²D¿ès
+!ÀàU ‰üáþ¼„5ƒ(‹ê”ÅŠl:¡i1ÅÛÖÏňéꤸtͼ„MÈŸº}W‘OolHü¾u™3³H¯¾Ë9>Ι–íˆ¤¿¦MÍÈ“IÀ<hG• I?…„Qíêj3é)ª¦Iôâ-¬PÆ-¥iW-¨”‡¼´ÛcŒš\ùP, Kv¯ìôä°}üѳ¨p¡~zÑÌ„Eý¨kK”sS€èó¾·/ÆÌ4¬‚9i}_ü¢ ç5Ϛߥèórek° ¡O¼`Y‘ûÏŠ: '—éÁ´X˜å=„–Ñí¾b#¤û–öü¤[VøQ?˃TÇWÓ0fº{
+4°õms¾<Mk¡Ï ÏÁ0Èž›å¹¾âÁ꣆¸éS‚ï/< pBE‚Á]<»uúYx^ ;Ð>´¾3ÏÏ¢gê Š^S§Jh0+PÄ›QŒ¡¤Òâ)³»o¸x‰1CÂ
+‚Ì·Ç–¬¯¡…çMÉ{4¨lÒ¼®% Šg±îFÒø>ä<E¯Š‹$©SÊŒªãc~†×}«H{5¦.YM‹`î‰P°îȼJ”¾$.LØ8Þ[Kj±@%\?
+‘@éÄ 7|Á$PN‘ºÙ1P)à?m— Ä©=Ü™ G¸ýæ3çQ$ˆÓB‡çzsDSÉ$åqKðÕ•ŸµIÀ‘i réÍ(_ü㯨¨›øm:{1C¦Gƒ'ctÝ‚3`åD°…ŸþêÒ5ª9Å­›}jÔ HÙÐ{xŒÄ¹ù¯zK°ö]<zN£Dåíæ062§œŒ>üY@ƒÃXEÍüNŸEÁZ<¯ûVÑ˪ƈ):k´CŒ8‘¾v½"\2° Œlëé-NXfg]ž5ªÀ-ó0¨q;æÁ\®fÓ+˜Ìf³Àº&„¶@ÍÆg£h*Á¤GEŸoŠÔiþ‘+Q¢oúÅ›ˆÄ‚'óØJ”(G´ÆVŒkrp7Ø– °ÚYeÙM\l»€þâsô]z ü¯o‹‘H‹™V]4\½A4ñ«1#„´ž:Ñaê÷1|P“Í&ÏX®¤jêÕŠp京8.Ço‚  ^®Úyz4åÒ‰"1.ÝD€äOkã4úð’¶É^ˆ5}o§„‡†0‹gJqOcwZê–0Â"Ä‹cÙoê3,RÖ£Ð2˘í»RìÛ¢P¤O‡1ºí|óˆ–AZ&£U½ç|:
+3ÎèÆL•S¿°z8¢ë›:?™ôŽU¬Þb~Ó4ù« ë OI_öVpÏÎêWŒ“ðc¼oú°”™Wß›Vbz*âyŸ%¸Gœä’®Cƒ1!7êÊ9… Ôˆg_*þY7H]ÿþ‡ëò‡:Lj{Ö§Z›é-e±1b&±¬ìO
+É è盢"º•p2سHù[¼ Sú·•tÀ„oì%Ípý
+tÊOzåW¹ÅP¥ÆwuвCÄCW&Þ„†îM†(É—xT½ðÍúeùH¦Nê¿àõˆVOœâÜûš)Žÿ¬ë” !lgmù¾nàCµ:cøUjmtl´ÿ/w$;ŽŠ®€{ -ãEþ?æ]º³ÅxMsö?çY’X…7Ý!J¡h¢+3‹û©ç>Ëø´a›Êøî]
+©†?4µÏ"<ó»ß¿0tá#>èZ˧0û%Rþ_~+x‘¢·#öÍ™å`yqû’½Ðà
+è¯ü¢æO‡ÿDSc^RÊx0]R=ÖgÞTþí˜ëã¾âQE¥:ÌX7‰X%v­ðG:Qº}ã¸`n«vS°~p2¬Åt™O¿Ü
+[IäÊþpá.ﮌ—®tPµxÅâ…$¤´Ä¾ã<]b
+¾ÓÄ„4Bd /³_]*¦ÓV/oµ_(&Î ªÊθæP‚!D~:ÒÂG%¿Mêõ()‰˜ô8¼ #72Vü(¸ž=ƒIZÓeü¤{s2Ía¹zT¢ç[±±‘êVâ ØUy–-µ„ßY=‹V6\z…ÕÛmžø ^ÀøÖœh~ïð§+å›Ç :“"ÞÀGÔ&š†¦Ë›• ŠHŒJV¼¦55ÑÀÜÈÄj÷m¢ºR6[o0ö4ݲ¿G(д0{dô|ˆ€p›eŸ‰cã8# á¡h“Yƒ ‹çétW3   h¬+ÊÔ­¤Áx”b¢£Cú,¬î»ï \E^<sn#iÛÚ˜š’‰—ç$ éHîN)©ÄÊ*)7òWÍDöÐ@$à¼zá0Ù ÿ‡]eK¸_\J=EøŠÖÊ2ºèðqûkh/Œ·?VR˜
+‹vov+ñ—7Y³¥êo¿3’Œá"ºx"¼?Ë¥ÊaIk&9bä/ÛÓŸE7
+¶vÊ?b_ÏWLŠáE²jõðTy|O®ùx/À†ëD›Yíߢ"¬žÜ¶ˆ{AoŠJÚ,ñRê˜~üaén×ãNù¶dñá÷™
+ƒÀs_/'ŒÉ¤1¼“Wñ@²˜èìOgU‚È:æïñÙâgΤrÈbƺ¢,j£„uĸiïÞ¥¿H¡CKÿJ#7vŸ†á½ÃÞDà»u8*ùmR~Ä?¯(Ú0ÇìM’¾ÁÁç~…EÜ\ªÏê”:„w€‰Ô2YuéJ¿å1.…e#hAÈfœÇ(Ò_ÒEÅêQÓã¶ÔN6gÍ(G=ÿŒc‚*›EÜšHøˆÛÂÔžj†—™Æt£aFê~2)P˜^v¹^h¾5g*|‘Øô<Ã?*nƒ::p¯ùçØ?¢’FD!=¡1C¿Êý¶ µVv˜ÐÂWw’Åè`^^çÕ÷î)&@J˜­³Á÷ Üýÿs·Šx¯Ÿ!å`m|… µƒ«€Mõq2×uåŒÇƒ„ql³Üؘ5lÌsSÔÞ¤1‘|FKbÌ2åûõÉZš`Q†åƒ¹2/¯}l¡¸HÿÙg{É’b4¼Q9ä„¿œ°ÅQQ™9f§Ìëú³FoÊ—ãB,ƒÁàóöTd…;<£ …ÉÞlÚk}uNø1ó×zööÕĈŒU¿\ôu;Î4Hkãÿiô˜¬ÞÓ
+–Ø[$Á¢;8¿ÔB2`´ko ÈÜ!¥4 ßæÏÂç´õ†š „ñQRELM ¯Ë”‘Xð¢8ÌG&Î`·•èéd8Æ8®£˜©xaç¨Oô·3Jâ ôÜóÁdÇ}áèP™j`‹Š$öNãJ9”(UÊ©Îrq]êiâÜe?­„à×±„ÈÀ%8³qP…¥”iþ´£ºbNÕúõ£'}e%à5²}§‰ƒ0Ê+§«a‚ì|[VRÜ®WÏA‰\H’%OT÷ïÔýfb»Î¯-ƒº°Ê°H·ŠÙÉ;8y
+ÎeÀI†#˜åÔv50^|¦ÁI
+;ßA/J’÷€D%xfºˆbV® bS1˜Q",ÀìéÖ8ß‘È­BÓ2f%Ù÷Ûœ‰2¼Ãõ’—,̤ a³“´ymHkÅé¬2æ'W‚¢ŸoŠJ›p KNþËð‡âVôÚ&SxWlßU¢Å`Å°Í­\.«6ºbÙ²ê '9íô‡<!Ç; eÖÀÈä™ûî©QàŸH=ׄRŸÁRÊFp3¿™Ö'SÿqÄÏJ‘ÑO‹ÄÄR€*ŽúçHN|j̵_4åH4#‡‡d+¡A‹¬‹ÝXç(f®DšÌ<9@x((TVÍG”°ßæì…RûçbÌGhó¸ÎBÛ›ÔË\iºäY‡µ,¬ª#Åfÿ,
+ÐX§ùØ=ö8æ†siZâOK#¶\0Šþô;ªoÑÃACDSÚaôˆfÿPƒÙ„©³¢f¢‡JðŒ+kéȺä¦Éx u½Z >F5J;¢M¨ ¢ZH}~ÒÆ#!€\gžÀªÐ™,?YøÌD£:ñ®çQ/oNûY,Ο»zIî´¡YœðQ‰[€¤™›gTÄx’^ÎÂGÔñ¥¢ ¾`6)î>ȸ)ŠA#„GÙr_Š)g)ìyL#C)µ’ônÆš•5a;ùç¸|l†»LæÔ|ÿDS4q¹²‰l“ÀÎéuØw€dE ئko ]¬X‘“tdðÜ –êÜæVâóâ³Ð_Ù¦ÐÑw†¸DS§onD¸Íøãå’×ÃÐxYQÿÏØÓì"S{ÿÓJºm»»6ð
+9¥°Ç¤1L]” VÁLéQ߈¨ô˜ù*[ÉZ{ÛššÙY<iÎæt=”H„KÔ‹ãB$$åøt c­\
+ô#Þr%è[Æ‘®”CÎRùÜêqQ,’ã…õ*¹|~êû9¤¸Í·“l{ħE¸¬ejgƒ°ÅV펄ȀȰGÖ¶{|
+Õ!1>´#ä‡Sð
+Fx-;9®< «¹by]ÙÚÛÆrGÒ·—è@wf©Ó:ª)ë¯A‡|üܯ@w²pž®;­UJwìSFÎI'òˆ½G¾¯
+(œG+Baà;ɾ̸x0˜&UU}
+…”óÏò¢‡ô‰åŸzñ†¡%/Û BK›üvܺ•·z!"Lƒ”¡¦Ö\ó-®û§øe!ÄJíÛÅFHS„°D‰4¤èÁ¾qðg..5ôžúµ­u£·ƒ€~8ˆ5Dé´Qšð{<ªë²pωV¸PÒjQBj1•v´êIHf¡T(é+.^اÖ3$hÏ Ž,;e­ëSY !AÚÛ˜D‡Jù¨°@àmë.7¼WjµÃvYÒÛhëxÎâS„¥Éü¶/¥fK^ÔÂ!0}‚QW»
+eÇ F8±Ÿ¡+±ÈñÅ@-fÍ
+ØMÊê†Çò—ö/ž5¯‰`¡Ëk( Ä7ÒðB÷HËiÊ¡ÅØ(‚C
+Ã2y>ŒwÎ0П,­
+Ò‘2 zFØX|·LùÃyA“ŸM—É¢E
+Ã8-3\"/9£Å¤¢ ƒ  Î"@€y4â³Kˆ‹ÏÂ"•íÆËgSMqR VH!±G´¥HÊ„ÔéϵŒš…Ò˜&LRPâ΋Ç@Ÿ€¤uè9²ÃD½()ÈLÈv´±ð²©ÈeEoFZ„cSÄÆRtçA¸#'t©Â­:_ ûÏ¡%ƒTÄûwP¶LßoY¦ƒ2±äñ~Ê|ìÕ=¿e9 pYTšì‡Dóa-£üø^ÝŽ oYa®ØEGaXÑÙÔÑÒl4k0ó¸ ýæ³D*ü2È!vÕ‰ .‡»¼‹ë#“‰·¸©ãj²2$´fœ *ýÈš}cÇ#¨B*¯­ñ ¹ mÅY d´u2+Šõi:¤,¹)ÃUjæO¿§tF)‰z¨–ãD6+C:ŽBþØùG!´*'“•K>ÃTG›þC„CÇiþ ¥¤fñs²pá2 Ÿž—$ žFÀ/ö¥ÉÁÈ(¡z¥(Ÿx«äÈ0;F±·ñÙ}3\ªÏÑÔ}nÿÒÔâ‡Ü}b‹”¬W÷fZbØAr4Ô‰ÖÅ°ŸdãW  ½”Äñb †ËÖèq
+b 2Rê D¨uÊ
+H‰”—Anœ¹„O;ô¦A‘)­½Í-¼•sÿíû(©ðÿ«aÉ8íjI$‹Åâ?ÖÚSEÍ«öê¥?´ú³†E©¡]m<þ¹AþüJ{¯•øÿ“ˆ^KãÍ,|AŠ÷&e×(2z×áU¢”¶ ÂGÜ£k›7ųX“êÒ[Ý -Q‹¸6«„p^mµX-e^UŸCj©Ýù¬/ˆÁWxß\à¥Òø†E<>æUaS‘÷yi½4Õ!fýñ9A•ïÔjEú+ôæ%L´s¸ÏËx jã³¢.ªu­ät&¹òbîjÞˆ_ÿã®úLP´b^J$LŸ¦ÒÃÕ½éxü ®Í8
+Ã[KJÍjpP0©«/?³îÚƒwCÌìù‹F.Ú/HSJ1š‰Ç‰b@z„bâûªoxø{ÒUž>Ü > äI9þNÐ(BxÁ÷ÅŽÒQžÒM=
+†"ùÓ16híÉ$ãuâ2è-FFŸæd…OLê†ð‰@d%fD€ ¶02ðá‘5ó‘S(æ9…Y’
+¤oAš¢€$9?BŒ9v‚6bóª^ 2²˜"ªôˆu}œžŒµqŽÔˆcè(ŠEˆª·ú5…(
+oVƒ“}êû­7!¸—ó (°‚øF6¡Ï¡ÐûÊèÝê~ŒÓÉ$ÖÅP:E™m4¤® õävu_Õ™Òœñš7üL2‘ÍÉÀ{¿(Ú
+ëÓTøTÒ{ßÙS˜P 7
+†Æ¦Ù 0PÊc=/Õžjeq4ÂÞœSÈœ (¡­¾ê@Á™U8¡2!’ÓŠ¶¦[û+>e@è&iŠ:Åbý§7!“ bÛRàÔ€¿"öU4gmA Ò:Gµ õ4™ñÝžwÌÀ: dô–ùnÏ+¨N•Ô4@dÝ5¨Â_£ê6„éx„晑óÈ‘]ŸÊºD‡«<ùWQº¯®ßòU2õuóÇ©·‰÷íäœ~Ð{%}d5 þÁñ0`­=`–ѽí î¶è
+±Œ±GÉÆCT©*³gY‹³£¹z±Ö žCõ˜ãäK­öU7‡ôy{œ_S±Ã˜Gbiþ&*œž•îÇQî«®Ù‘\ÎrXJÚÌÇ)ÇÌsÇò1Sr¬Õ²®ºÖüvÎ9·×œx‹êÄddjKéhs?:ä“ïàEß@¾ÔêãÕ~Ìü6r¸¬àÊA½FÓ¨ü‰úN9î ûšw¸îúüÉ›–rrIw×sÌmKÊ„$Ó-­Î|ya\˜±åGíÍ£øˆ"ÊôÝ߀²pt îù¬Ä b"²¥5.í Ò‘žÁÛ˜Ëm;þÅ2“ã°.P†i®¨°âµEÜNê9Æœw¥ƒo@ñÔÊÎ)¹îÖ7)
+YJ=Æ;¾<få%*Ë r(~¤=(üq¬Ö¥=VŽ1×X,ì¬ÝCH4v“(HÛŠª¥ÅÎù† ÐDZ´ÚÎð>þÁÌ-ÈŠ_BJq÷öæFÌmÅÉû~2Ë]˜äNS&D(ŒÓ$§-Ô i¬rý\-gžTÛOVNa g÷f
+0wjËÆ}KG®hœë~„\Húñë:ÐÝP*¨ “X.ûA‡¼_÷#ÐEÎÝu-‰Ád ­0%Îþô„ùj!„‹¦·“ûâ÷­"œø5ÈùÆ›jú&<QŠk¯Go
+ÅBózåä)à`XSáÏ&ÐÝ›*iS
+’àÖßœ#­ÞR•ÛŽ¯)ÏÑÓ–äþåo¼i‚”e‘Ûp€~ÌNÉ}’îfÖñc‚O«7=‚¾zÓãk¾zÓcTWwÈÎÕ r|õ”‡Zݽé¡æ‡s®Ì9¼æÎÀCT5¦§FøêK¿m§Ýtô.éæAá~¶¥Y‡
+ÏR˜‰êý¹ƒzq¿îîH¾ÓÒ‹$o àDf¯!()ùh³&þNP¦µêà?ñÃüœ ,)¶­°JÅ*ÍӢ𦴖Áô‚™#MRÔÓH¢Î·,_YÇB]K'’¦Õ39üË9˜MüiÎìD¼^ƒí €Ê ‚‹¤·dÆ&¼f;9SIo‹•Ï«âÙ¢Aü–ÛÍËÔHîg2;%ôò.c$BsŠó˜´¨Bx“NÞ$Ä šKzzÓr2@”žÌ"ýsþ@¹tã7Ìû¶Âb” ¦/U[S nJ…Ìó¾"Ÿë*ö‰ìl #ŸÈ
+šÙm'y6»¡Ÿ;ò«´
+î*a|d·r *ƒ
+‡,©}/›AOCÁ:gÿn+ü&ùÿ”—Ir$·DOÐwà Ê0ëÖ²oÁ-yÿ­že]™‘bÉLÿ›H9d >”qsÄR⨻ÆÌ(¿šÙÒÏ·ñ,ZXëYLØÔtï±`ÃX颼¹Ö3P„0³̬ÉÁ‰~8 wÏartöç¿É™«­AFÙAäuFº—äÅø#Îp0lÅÙîY \RPM©Iµs`ŤbÂãûÖ~òĤ(² d<¥E u­bÙy‹¶ŸWP¶ý¬Ú¥Äê}¹ "eeñ†ßæ=ùLíÓ‡öpŠ âv²8f–1§½3TpˆÎ朇¦û'J;d Í éªFÞ|²½0 ËÉ’&ñ@6€6l0ÏÞ¯™kŘŒ´¦8BvpsÄ»üø{BZ1Ûä¯ d›!?þ_ES¿+(#ób¡¬£ ¤/#÷'Æç€XE6±OŒPÞ×wýúzGEMl#Â
+è1º_óˆëX6XÂ5>TƒL{ö¬‹Ö§_¦ K
+¢ÚüF~©1~Ë©RÚù²'mñaÁÐÜÜ¿Kˆ¶ŠMíº
+Á_ ÕMšÇUÿ=Ãb¹`㎣¼šEè‡ãý[,¿]P’ YpýZAE6¨;e;·2£#J2Ý|úUdÇñŠBËu#æ¤Õ yx­Æ`m^¾YF
+Š0¢•
+³ÃD˾‰‘Ñtå-¤J›ˆŽa‹0Ö;ë@°µüC¥„¥>¹(ñéÌ^DuÂ.‘x‰h+£±«„­ÌoÙNÛ0U\FOeÙ$]‰<tœ ;†’ÈÍ$ùƒM l?vÞ B÷øhØt75?d §ÖJrÎv„É"bìh=ÌPПP¢Í)>ùZ ¢@Ê•ƒcñYìû;åê©à„¨ÕdÌó¦j%š¦…Jà p’lY‡W“ÃeŸÖ ¾ˆáã{Û!
+ŒÜ$ÿÁ‰’K Ô çšK†æÜfýØôßS *£>´vÁ[¢oë<Hëõé_—H]£’Q~ó¹¯7ûàAÅ L?é‡_ çH<LЗ/ BBŠ´w¶ãÕ €нÉBXöŽ%bn“‚a·nxÒg¦!H¿ùý˱DÊ­¨FÓå_.è2Œz1^$“»B>úÚF’…c}9d‹™ò»üÔd`ž½ç¡Æhðítö”WGiLpò´ÅiýU£4eÜš$ôÏ=g"¢MK©ó©QÅD€ Â2¸6²±¾*À—D±Ü±ƒ)ž.‡j–;ú“ìœN4ã“èt¬WA¡D¥¬¡qs˜ÏHÛŸÀ-¥É³÷¼þ
+:ùŸ:ÞdÙã ž6WÜã6OQ Ø?Š;ߪš{ÀØmÒ”I©N’×V j܈F#,Sß1+ wbŠ·‡GR¡Š&[ÛáÏšØOþn﬛!7š×dðR}F¼z5˜SÂûyùÍ9ˆâÐ=¤¥Ãö·¡¥=.6ÄþÐñÃÝ0Å3Y/¨{2Ô\––²·q¬ºŠ)~ÎÅÚžn˜¥ŒÉÝzÉôA{P á!%æ¥"pÑóž vC<¸­l…|CM‹Y7ËãZŠT4ý"bÏ<µ]Ef?p`IYÒõ$?Óé3†Ì;™‹,›:ª Ð90/Ý‘Šz‰{‡2Cò#a€!á3†¨gš{„@8³Mû{w3aœéæΙ:ˆeƒWs¯î9Öâ‘xwº¡0H<~ĸê
+Ð%ê®"+̨Ja¯¡P†Šd!™j7Í9~ …NsÎm8§B§—XxŠs*tÇï5ºs*üyŒŸ©hÉMŒ] 7©ÐS!›ÙÈÔÜT„G±‰*t<òÓ)¢†¡C AòR¡jM;« ápåTƒþùSŸr“
+Q0…‰¢‡»çT<bú:½TèNó9: kà4ñ»"pFm¼ º>]߆tåM*³Šgá¤|“
+U
+Eó6|¾¶ãš
+µe TÓÅ8î9 f+˦r|üK*Ô¡ÔÝò® 5¬Ð ëÍ?Õ…ÎÈŸc¡»:çXøó~i9ô¡øÓ
+§db½o¦¯\7l =†­2#„ ©f
+½?ÀúC^%ÆhçY^$>‡±×ÇÜ«¼V´ÌƒYž¢ð(îDW±Q )“ÊAsÞœƒT•0æÔÝ×
+¢öhŠÜ{êy‘øõºèë7‰9✲ 2OÁŸ‘çÅrééŠï`§s½y»Àü ­xýÐ]®kÜÝ!IjèK‹@±'–™êíÔ‰o¦?¨Ìðß„h<H9Ýæ6äpªÔ%ø³ >Fÿ\¶µ/®¿w0²ˆ#Ç !̸l™.|ʶ¹`‹æÛOœzâÌ(k|ÑÉ‚6ôXiñ‘@¤&r nóÉþ¶÷BtbVòIs8ÙO)oJ×XÉè¦ù`œàêƒAÉ‹IûuT‘(Æäþj_ÌR"‰•¤òÒM±‚Šõû—zQ¼¯D骂b¶Ëð£Ã³×{ð˲U6"5ƒp)Ƨc¶ë®xD÷§—j¶›Ìz$‰H^Ó,b'ìÈ“2Te‘ vtƒ±È«È­Óò¨Àê V7é-âÃ\Üsjøå-×¹q>é:—Ò8ƒ~ª¯ƒxiÓçëräØ
+^âVÖ1‚&"7ß
+¤¯”ð6¥ ¡÷ÝÃmÙË
+s¶…½ÈÜÁ›³³öCh• eÊ׈c*!E’,ì%(¸
+†,õ¡äo߈AÓ``¤õb‚ #Ô2øÎU pÄsJŠ_ évclBSÂ\rUû½èàV¸gg‚ 0U&ùnÑÁÒ°ŒÉÅÂ×E·ƒ :}I(€ü‡¿v™ô•ó¸ÌXš-±ÿ2#r0k âiGr¢‚”)\ŽõFr´w3•\¸à‹uØÃJ–żì#¸¡¤»™¨˜îˆ@X±ÓÿGáo/§ìFFdª »òBrNEÉäg  „ç¡n¨Qœm¨i3 š¼|ó’%p¬hvô&¦€„j?9á£à®Io“rxÊ],§;E! –q·6Â"Ð/Ä >ÙD²Å»Âfú}(a«‰ § ÿÔr=©.¤²vMG…ˆÅbŠQ^‚ݧ{¢è8 <=¤( ǽS(ÁC
+·}¼¶Â7ã8Ø”ñ9øæ?ï?øXâ&â¢À€àž},mH†ÃË1qš51O • ºÛÙ°„°FßHm’7ÜœþPLà Ã1ä dÅZT¦ÆÕ/¬èăõü8£oáãð‡|ÇVlõŽ»,ÒeÆô˜ Šú"¿Ü‹ \=äÉu–Εßš†'.-2ÖƒcÃM(•ÈUcÒ§ˆg¬ð\ËÛšÅÑž «Q%ÁŠj3†2Û¯„Òó¡w;
+*=%qæÆÃÔu*ÙˆŸ„Œ)®+ó(Ì‚¡_“ÃÍõt˜;šŸîtD¼1Z\TèyKke”Ùx’ïÔÜi^{A˜C€×]4,ŒÖ©ünÌ qIv²µk¥Ï~—ƒà•plg£šÞ³ð BÉ'šßM‡¾ ´ÈòY ÀEŸ2mÖ.IÁâ Fv%ë†TEÇyä‹ÁÈC.å4'˜"´Nw3QYÅIZÖ|Î-¶ˆ± šc'Ôl¡¹?ÎCƒÃêòÕÂø}9Y®;“
+}%Žãdͪa_âÞntÊ5DQéâ;,¹kO8/ÃÂLæ
+.…îi5ošJ=vó©d ƒ}9ôìöbh…á¢^¾³1„šÛgd E©\ ‘™$É綋£ˆVÈžÕòkàk™òŠ¹òe,(
+5°-ÒÏSˆ~,«‰<°2=¸„ï S¸ú¾•è†>HY‚Ø/hŠpƱ¼ÄficíW ã$ p«±¢bîPq±UGÚ ºIq}¦*gã­Àl0¢"åÖÖ.™Y
+LÌ)èZŠÇ§Iᵄ…mĤÔð¸˜+|e|Ø3¥ìXpªûÚrÁ¼T]%\ÇŠ!Ã
+U
+-aY…)ãe«ó³ªÞÌ&5è‡üÂ('?hôíG¬ìÅ:I*‚!#RÅV4r¸¡.Ë)_£ËÓ \qmÚˆŒÊª—¸,-!a˱7da3Ï­ä&ñ2œT"ÌÎàÆrj/Jš±éÍé‘£I Gf¦Š>v‘;ŽªÌ+)“™|àÞÝsÍ•W$Kñý4hmmK
+½ÏyµßWOâ> R„막Ùf«CÃK´”ÓßÄ9Ö¥Ãç±ÏáS<+?˜¤fv^G{3uÌ ('NÓê›lÖ‡Ld’°²Ñ+¸iÀ\³GüÔ„ctæžúõ:À˜ãqSÛêqw™X4‰ÏÜãEÉ'·ú§›Z¨•Ë-™ì¶½8Ÿ\‹­ƒœæ6µ§"TJ‚ÁÜr·8†9ÅJÚ.Áá2õÌäp—çIŽ–#*»D\Èñmû)1þXÀ+:áꚤ8g_§nÐãbâwb´«'®AرÞ%{+ô‚ä Á·uð"•1©O?Ÿ†¨eã€ëæãí(b $âߎ£Th_ž)m~{âSɧVíîE,2}/Îõ8ª8Â.ù|q'4Šdþ™ÐØéùm(â2•ŠÞ§NÍlWÞÈÇN=•ìN=wü°Î3n§¹ãïv«Ž™ïÅ4jtûã< |P¾í®iߘªkø䎽_„§àÿ)ÿÒ¦"ˆÏ½(à€°†ÐÙ¡èDZàÊFJüG]^tÛí©æã'úÁ¹ÿøë-=þóÏÛÿ¾åÇß–è\"È˔𭚤¬GcNhüÏEl5&,F%ß\Hr2‘*QœQ9#mU Â(WÇéf*»¤0JMÑrxÜZP* ubVfŠuXQäP|P‚Kj᫤/úÓpp˜•teAì¡ÏΡķ⹱pŒÀ¯^f`BÁÖ•·v­Óa{&GEJ()ZÓ‰x8¼)Q‚ãáɃø”?ßNEL™Ž®bƇŠ°Lõî†ø€¼Ç1g¯¦kM&$ÁÒ%DJ|½’T=^üs…ßûö~·UnMà(E‘lᾚ›)NÑ2lH v:€ÊÀÀ˸—¸NÐƃÄVðXsw‘‡lPìôŒþ´·òµå†&ÇzʸxõÁ’ñ‡¢ªañ»¥sÁIƇõ-^
+i«ñУ”àTþ§ t-f#ëaNä2M ›g€Kõnp'R,p¿„0¦ù\ÂÙQ"\6µ|=[CÙ‹4 5þŒ•QV¯é]ÖÂ:²s¦¾¥1E”Ъ2¬Ó¯ã
+ µĨçÓGÒ‘Úê±Öï‡þ×KÓ„BdcŒØƒÇ~Ü~©iúy·Õej6Bj¬õ\"p¼’Wþ:Ï5ò‘'×z= ‚îhÿa‡Ú€6øHQ¼Ëµòœd…§+É£Ï-ê1/ؤe‰í½-9&¸†]XÙ"–DÊUʯÿø¢èßhte¾¡G Ýs²yCe%¶blµ§ŸÇ9*çñ®†…rHºæj|Du~äa7ÌšÏØÂ
+ˆW–|_
+Ðzö5*¾Qm©uå;O‘¯$§?So®Þ›ß7ÿËcH@¨ñ©8»mÏ"ïãC‡u¿¶(ÍuÆ€M·uëçõ9†ÁÐÕSs€gnL4ב GE ²¬OEˆ…/ðƒ8¯Š>Y“U‹ÿ´ˆXû‹-¬5¸Xé‹Ã
+ÏT"kg=[ìÛ~LÑàtk¹ãX®;G’@þuoíaûX¸“Uú¸jz8õô—÷±!²øHh¿¦Lé9ýsÍ¿ÒÐÀ Ót‹|Û¢_«Š
+ðÅFƉÀ¿8†LXd`—ßËXÛ‰…¶0!±Æ¥ž?eP£âƒÉÿy<ŸÂxLrtÒ´ó§ÁAßuž×à0Hâ-‚æþl•Öì;”Pæƒ^Pƒ¯ƒ·AÖ€÷àâßû§›Â¾÷sÎàX[3Íãûîdž?
+·Í¢¸³2~¹Ú5ë*«Š.<úŠÏ¥¡Ý&.:žÏ1ÅZçNì¹€<ë Ü‘Ùî’ä¤O–?“Qü¨Ç±ÿHQK‡Lßûßÿzd«/ l,¢$pÕýÜ­-6]‰Ë©,bH÷’1Ú¬‚±ºý'«sn¼·rÊ&/ÙÕüX„”\R•_1ê½´UnRsk/ê;u;WÇ´¬‘LÂmý Nÿ¾LKë2Jøª·@Ù+ï½:§{˜Ji/sÓý²‹
+×ÑR‚èú…D¶×à€;®Ž‘8}UôÉ;+¢”ÕßÀèlk¾**A†ÙŽPi±,
+24Þn?/ó
+ÛÃñïãÙ F˜µ ai"[ÜîXJˆ¦²Å¬íiÊV) árÇžõu†;†TsdaŒ#óÓÕü2vÖÁ?ú<€/*Ƈ|6zèq[Ÿ߸r\4aqoänÐr
+Ä-âþ‚ÇoD‡ÊYrn$tX)WX"ð78~£¤™ø)ï°ØköÏ(*¦“­½úñm5žkA8èx­îÆH/BÊfšÖú(añ"ÓÓ6ýZM#8[¤üÁ<IñN’G¦©§Jæž1{œÕ¦Ž §úàØò~öÉ®R¦ýP2:ÍÏunÅÊùµ=O8Xåìéük‡»¼$ÎB…ˆ–̆±¿ï¾O0a5$Ç|‰ d¿x›¢Ëûrt­ íÞÇ1zÒQX„ýœ±Ãö\†º~U’!H¤Fý|çS ¸ÇosÁBN  ©a]ÜZ>‡ó9%%ÜN—IPÄþÈdLûÖ“{cñæFx ª8ÇBÎx—dÇÔêV{Ω¸¥ÞÁ÷SRÛéʈ©ÝÉÜC£Ùc}%knúPôß/ŠhWϵëQ‚eÑfvV2ój¤VÓßavÛ§NÝž…‚”;%د À›¿^WÞr—Øñâد³é‰ÓÖH ÐŒtÈÄÑYVB¢cÓ¤fEo"‹ÑRkw\©ÚÎEɘ„…‰]¸íèq¬Ï9¨Dg'Î÷.D3‘™„+iîg‘ZÏ7é ÃÀ÷¹0…AØÝß
+¼Î2ÞÌÚÃL`vF0p›¨ØBÙº__””ýÐ’ËOïä­ ÜUŠª×¢æǺƉ.Ü’®êÀº•‹„ÞåþécjVàK•¹"`í-e>‰dºÑ’w=kuï¼&ýÙÆt”Öñø÷JKq›¯ÍaZKàÇ.×ÓêNÏ ¯½ÍÛaApáÚö¹U¬iø„)Vf¶é…áê’Tzu”éKg¹Vñ§dãÏŽEWIë¨pcïî8üeŒBûú]u,T5AÁ2@ß])a"®ždÁÎSŽ“C¬ä‰çSì:I,`"m…P¢–ßZ˜Ì“á­¯Gk!ˆKJ%¼žÍÛc
+¦W†ª°(`C>à,Šâ‡üÌÇ.9Ë"v
+Jö
+‹«¢Ïó¾#tžqä÷ X}Jš°¡c‘Cv&O
+>;¹R¨Fg¦Ò–'Ý[ÎÞdå®mu§ÿ椽è€ÅÌMâY¹Ä"ÍYÁãFT•!bÇ´ËT ƒË#D7oÞÍÞ'@Œc*UsPJJntbÎY”º?%çaE²”çÈ´Š˜+¶ØYç3Ê¡ÚäNÞµ Ç®{Б<OWBÖËFA‰}JôWuaº%ãK£Ëä>æ»®Îa?Aâöù(P¡CטÑRo^ã¬÷Â4‰©Ñ³eQt†
+hMÁîY“-ÁÀœúSd¸lYÏ’µ "/òKhÔÔcQ¤$^ÐðÁ1ï¼UèNAFqà–ÖHÞ3Λá—P£1O{ÒôŸÒfQ(õ@kP?ι¤ÓTë¾MJÍ,tñ¶qIƒe ùÜSrmÕϤ>"í9˜OdcÞ-tå
+sѬƒœ°)P×Xöt¾TvÆn¹?~¿]c9†Ù¯H/ï×ì7£Û“-‡”¢ÆÃLÖg‘錑[бn>ÔœÇK½\מ€hw¿Ý(Ÿ„†åËu”{Qb"ú#jÖëXŸÃSíæjèõ§C"ÎWQ·#ñ¶t‹5Œ(&×Å¡Y,Š>“Ýö=Bbû¡¹}AˆŸk>ÏËOâèêéyͯŠ>ÝH;ä«+x·äª×ßCX°oy…å_îùŽZqÆ®“ÃVÆ8³ˆ‰ãÉúÒ²d¦Ž`rk(reŒƒ ßD`v´¿3ÝFB¬qpõÛ`‥lW¢Æó¥ß€0Pýåõ’›7®DxÙƒW`ˆ’¨Ç8=Ì.2Mö?½ß¡(ÖO#¾4v™"«ê¼ÊÛ?¶ýÝwt©ö|ã’3D5£Ö¿_éêzÕþãM ¯1ùI²pÇÕŸ)aí›3^C±ÝA×`‰ÏaÒÝ\ÑæÝGúq®Ý¯çÃ(¾x¿Š3@µÏᇫÂë÷ð˜ WqXŽ„Ÿ[×Ë„>J|ˆ¡ÈxS\Ö<:‡qY <æ&O»JÒ˜˜uþ¥¶’}jÌO«jííC6x?îf†ŒQÊæ5ê<µ0cÇEQÑ$
+Ÿ+yWLgÍÎû10&J2±ÊÓ·­›k§†‘§xœëéÛ\´þÁ>þl 7ÃS`éú„‹DÜŽ拃œãzZ“uwͪ`ÛcPÒ¦É\z ^?hõó9¯^f°7¯oìß³7ƒ-~vxXòiR¿¿™ k
+º:™^±’¶¯ƒóþ~QÔâ
+ã—x6.b«­§|ÜÄ庅
+WŠ¸ŒP¥q¶œ‘BC,Å•çXr“©™ˆñ9¼›eMt¦G®‰Åeù÷üUJÔb’Çz“R¼OâÆmd»JB ´´%à]E¸¹ÂÙjŸ?Zr°êZé [N›¥cë%Ÿ–óçQÑëš[Wt#Q¹ºœÿGÑxÃÏ}£èAcT=Š­pKÔ˜¸¡¶‘ý›¢Ys‘säSCY¸⪺{£mÔL&H£Ñ.FØ 9nûÆhii¥á/£]Á”°á¿¨´“ˆÙÃàžs„§•í
+îÇÍÆôGD‰¦…SxU¼)çO[ÞþûQwJö[|£”m0Ó¿)ÚN# ñ-ݪ=Š”Èe%ZŒ÷–
+ÏøÃx %¶Ä#“ô–síý¾,sÜÒŸ3
+EyxÅÒ×L› üIùä5çx7>5T<3û7fžõ˜²gT~åŒpêq[„Æà\r·AQ›š‡ÍˆÎ·"¡Q|Q뎢໩NwL‹ ±´M¼mÄÑbÚ}šc%"HQ•T.~Öðm·Nd]n*Z„Ç%q{æ׸ëQª…öØH{{dôâÏËèÊ ’¥Fe|EŸ+&óSƒ=¯§r ªn)€³p µh q´ÔåÝ´Ø/+[Pæˆj Õw<ú‡pº–:±Ä‘oÃsì|ˆ¬v à6Z“¸ÛÉz—¸àÕoB`ÜwK3&ƒbÓfʦ~
+ïB¬P¥Ï1ÖGNX“éز‡ÛÌQxf^“§© ÌÕÏ£"4?‰ž3Ïèè×°Ãß-Òm·DÛq‘¾8ln1/ƒ°!˜-;Áaz9)÷ˆm:†‚Ñ°g¤\‚ßîë@0”dÿ &Ü=ƒ œ{’/ÏdÂePҶ…±˜uóù2>gåÌX Fkêoª H¨Ãrg<º¤«dë%²Ùž¼×Ó¾d·Nt²rOµ¿ielÁ­P˘³íûÚÏ¡ûG^G¨Ã¬5îÆÄgí‹¡•Aè±8ªß'1&‹<׌3'Õ´¿mW+«f¡–hÅÙXM“cŸ¬¿?ðßLÒŤf —Ú¨ÒaN1ãñhÃÚw{÷ÿ1xE3·8Ìæ‰ñmŒFoïGÅBg8ùÃ|75²*°QR²‡©ä‚96uPò;ŸBm'êd]ÊôÅ9¼;¶ãóMඩ>Zi›¾¥"Â:¨“Cè(^ù9aÌûãGFE4âŒ"ƒÖz4øÕwŸ´K%³Ý–oa'ÿªk®[mÒîs2QI²¸ï<(yÞ/£öøYûwë ¯3KÃïn7é–ÀSKÐhÍó×<ô@¡Ð1
+B™E“½ÁYÆ´l¤Çy`D{Ž‰TºPÉ,îè}Īoã›ÀÄJY°y¾tö_[ø+Ëíåyⓧ«
+T(xðÆ×ìê¨Æ¨@ÉàE¾˜MçÔ50@—ýJ·”p±{Ô#®¸\%K$S?ZÔýñc+`GÇõ*Ÿœ«Ä"園4ET-ýÑÏI_¼‘®¯í6H™‚{¾ X%>ÅPHy¡Aóè|¿fâàhŸŽÑm„V>-Fž XŽñ«’lý}ÝYDzͣî,IX5ÛÃã,û ÅÊOƒj_zᬓÙÛz\_z^&D\£à3N‹ýz}Tè<þæ؃ÓýúÔ³9)¢j¾Å¨È ÅáXÉ—«J€<G£z–´­xŽ|pÎsq^n󺀃W½.rºƒ>”ña~{CZÌõñGòŸúyoI<]=nË€ÿ¶ÕYZNÚ®³‡\9(z%ÂÁçE¾s§_w脼BßÉÅv™Ÿ‡ÓúûEQÚy²!sŒü„©‘KÖª—0O;ÙÙÒ+ãVš”g“ý£{ Â{»
+<mI¦Ì’³GyæÈPý[B›8ÒìË+Z·ÛÛœ‰…ÈöH‚+ s‚œýEÝ%>E<õƒïåS¶2>戓œÉé^jeÙQ´Á*:)Øóx 2ö1z:(šCôT¼ä
+mh>f|Ç’Ÿ3q·7Öæoîíù‰ö¯¼Kw
+y3y†_âaçÕ9ˆjÈl{ëK‚§eίM¸3ë$I ÐVÚË"LpJ8ƒ78ô%†QâKh¿%z²ãÁ:ìžÖÒ!4» unÇ9 “a|(¹™n;E“V¦ç@õ²d…¶‡ÇW©
+¼ {ï;ó@}æž¼ØâYZnèKAjqÓÂz–ö&Kiãå8hý6Ã;Ù&äËn˜_”¸ÜFl:·|a¹²‡ûi7mè™e:Çç®EZAüïÙrÇÀÙ¦z¸_oba€M=æE§éfÊF¿È3ŠbpxŒÅO–yžÙ7NDde!0eÄ'EdxÃÁÛ±ï×ü$ïm"¨‘4®w*¶5HwÛöùë¸El®cþd‡EQÚ(M ï~«ë'¶Z5ØPúëL…“:Î(Ø9?é€Ú_£þáù™ù€²ûe@Ü/P'†ã<ø&MT£ ‹Àå–´Í÷2)RÂBì:ozgpáι°©{)aÝJ×Nÿ§Tôl¤ë¶v’T$`ºbèx¿Sä{»^H´ž9§Äú¸Hv =g½k»Â
+½Äj-Ëú,B,1'³Ë…$=½-§¶½ÕIÑ÷Eˆ£^Bn¤ˆ€í£–×Ù¥‘«ö„Øy, 0\ã¨iŠŽ°”\\3ú¤3ç³Kïí¯|é¨vdômÃâÐÍÒ'¦î9f_¨="+ÉF³Yý~æÿ~äz}Û
+KNUY'4ÙááÖ0¥†×cR”쪪nGï}ÃJtöÀæ5%èºÄ@WGˆX<—1g¼¼¿„á8´ÞøÒK¨‚T6œŽÛý{`?~Æ;pËó’}MêÁåˆkœm}‡h¸Ò£ü¼èû½³e–2\HüÝwÙ¹=Á{êÔ),ŽÉK n"®g¹ã¤ Çné±Ù[ßA+˜u2ÇÇ8¾3óÑ0*Š0£,2lÇ‹s˜w?÷2-FEo0D×4VÓŒb"/l–àX³Åkÿ¯¹­îJ_ˆuyL÷E(- Ìç}YŽSräÏÊü]¡öŠ#âê3Ð3v=´bl@ šgEŸê¬Å_-ªÓš´‚m¼(Ò—DYÖyë,Æ-Ǥ]DѶ+Áå&ºãl¥‚F<Úp4‡”XÔæÙ§.µ.OCX”1JÄÀÎN›Í:ó§—Å:xøìy¢„3¢ù礤ãÂ{bMû<÷ù9îOÑØëŸXg[,(–÷Îð¢J«X½§bñkláJî/ÙWZPÁ²?{Naá„}ì!9ýêÎô±UtûkÙ¦Ôb8ðR.¢Þ‚LzÜGÞ݃äôâGŠ¶ÐMàÉÎQDå×hE뼫û¡^|½îeF‚¿'Óðn9ßm– P—vM$þï^¤—´p– g §‹åÎ/10­Î(CE±h}:ûp
+V] "n¿%šSÊ(UÌ­wœS-À^Ö½;žÇ¹¼ .)Á&ì¬0ñ“Nñ:–¸’mfEŸ¬›"X++Uµ°~¹ÈçòHJ$ÞöN‹VSØòÒÜ)%$ˆzs ¾p¿ “j!Ž®¦ÄTŽŒÚìËWÍÞ—¼lOÕéæ`âMñÏ'Ó¾óPóaÐ*iÒ–½Ä’'µ­íåɇ¿Vô!ØxÁeĦ§kØö¡*£¡„! t¨ë„¼ÿ
+LýϺš2þ¾FÅâ1¹Î9©¡5†æ“~ìÃÙà¸DŽyë%K)ÚOëÇ ’
+Cæ\LŠ>ü4º%©j¥ZË<ÌŠ>yì/lé㱋ç ^Rú¸ kH1†kO{²ÏÞc)®m“HÏŸ4þKŠP¿PFsëþT–+ >.A/N—‘ÙÐf<…›BX\QŒP¢'Úâ<™jû›sh?ÀW Ó–Aô<w¶¸—øO»X¹ÜÁ­Fjök–5#™½eu h·ÔéöÖÿ~Æ!µ'½+úÑÛ³rÊê0H½&E®Nà{Ýú^‚pán #²¥oS”ÆEG¸ Ý¶ø¤²¿¥?HiucÍíû]Äpøs«ÊÁäœ\9ì»<äýl˜ø £tøE ‹ ÑØlÃþýSŸŠ4ñìÑÇòÖûS)~±gmŒ¢ä=,^æš’Œ¼’Åè™)îŸâ-wN”¨–GQk2çá[ÎmÍ:.e
+Áß
+`_¸£+„»ÔœA¤XÖp8Á«WA°vupQ€õ0§ö
++ÚÈ\ë‚uŠsÈ$f6?Èqñ†ÊÈJó$
+ù\$îЬƸæ˜öÁÚa²×ÞK|¥e!ávø_ÆÆZŠëìÏ¿0Ú±¯Q¥¯hSgn¼Ü¢p¤dÝË0¥BÍJ ­;_”Üi³ÄDˆçE õNnÕûΟ‹gîc¹úàúÇ/’„…·ëq‰wŒ¥Üïv
+M0Œbï$â~øU“ '»‹|Üؼï¡bLo ÃϤ¯£Ùú_2àÿ)/“ì8r$ˆž îÀðaÖª%o¡mêþÛú8²È GjÕÕ”%ðÁ~Ô\u\ ˆÆ!楅9Ýs&d«x%C}Ôñ³  BL Ž²ƒ|Ë^•4I Ékq`)¢\p1£xÒ's…)Ñë“M3>´óy>86Îä’b³•5Lô“=ÔN$)쳈ÉKˆ‹Â¨ d±’ZßE~=Œ/+æµi`êÑ8¦›Ô*M]ûT© vfPvƒ¿À¿{Ii·¾£ÊNË4ì–„éh‡V²6_ä˜Lˆ&.Â×ÃÞc9z"ìóÌN>p²Žwqö“ç
+/O¼ ˆ NŒ •â†tù;(C¬.jC”µÆmœ6`™vá±]¦]úMºä'{/£¹1:Rü‚ãJ{¸–`è2ÝŽŒCЧBÙQá-ô¯ŸŽ±€€Ù]Ú„ÁÜ/‡€º!«¸’
+'T,­¡¾#Ãœ>þ€#E§Q¶ÒBM°{'ŒÄ¸ÎídM¥hfºu‹ýì9ÛTÀ¬bÎÇ­\¡§†jk©“§ÇáNKæwK*é.1MüÒÅŽ'ù\È€ÂRC*YÂpÏa(I{ÒÀ\ØmÒj %ÔƒP‰)šÇ¥¾,{¢/1ÊA?þ)º
+3K6Ÿ—*æŒäB—“ñ±ó¤öNW"oBŠýcðxSÓæäæp— …xx3ñɘŸÁºÊÑÕ¼4ä
+º˜Ûuç.kM¿Cý9ˆiBvöŒ5(³Ò˜²jHV (ƒoXŽˆŒÕZ*ºü‚Gfê4ZÃ3¡sŒø*! Ñ11°†qŒÓWoÅ
+h†E#(‚A ¨”·=8Ë4ðHÔp {,zEîÅÉ£ç›s•Ðt¡5&
+r:"À=²¢!G/Õø Ú¥ ÈŸ“ÂÐã”s„DLx­hÑ’hÃôñÒ/¬ËD`Ôžb¼é )QWžÝíWfÛJ›°óš!Hè0 k¹z­ø½¹‰òq¬r¶ôå¼&Ú”è’Iºx+à} ¤Ñ<-°l?Â.yÊõcsýãœVD*&-âîÚuÁ¼óã'ìýLTIªÒZ€ŽqCG•q¸%ÜYäÏ¡Uhg!zÌä€p"<žc0Ì06›L@Èu!¤ÿü"§r#Ȧªß—ÉD×p ¨{Žå؈!«Ñd<×9Œ“ƚ壧±O,;lÖžI~N, 'ɬ7ц¯-k¤Ìàòº„¡J©?H>œS;ÚXÐc×0…+§á;/½€Á¸ãqñ„5²©³BÐ[<‹“ù¹–) E.VÖ1ÂT" ÄjAÜ+ª@öIQÁ…
+ŽÒ,ãÈ´`ëW'<òÌj³ ­,‰s@ÔPsÇ*¤jPŽCPŸ\nÆâ›ñz¦7 <€$˜)£Gh{1RÚÕÜÓõˆeÄÎFZˆ»÷ƒ?UÔ:îïÁéŒ%dÁ _bA‡<™Y6% ¤gädu&ËŠT¿ÙwÈMä72÷ã'¶ ¦Dê=¯åÔç²ë, ÀåùRÝsðÖ¼‰™GŸö:sQaVz“¡‚ÀÜ ¼™m¹ÝTçUƒ74ñæådV
+APdKõ¡Ž †ˆÒ£9gbôÁ,ÏêC˜NrÉŠ º>ä0ÅU<ŸêAÜ:o®Eo·•)"cž)%„¦U…U¢Y¨MvŠ!¬ö$('‰jÓlˆ& ˆuwÚáb¬…Bqón²Ž®ñ³T„O/ ÐÚóÀÃúˆFWÜAÿ•,l¸:•šrÄø SÂU–¯CFÞ<¦”Lj´Ù-þã̱,ÃÒF8ƆÑïêg3Þye8b-\+…#•Ì]ž%ë¸ß’šÙŸŠ#Ñ1bK=¾ùrN“Vûf.ž–ºˆU“Î|Ïå}4<ÜŸÁ€*Jw@ÄÓq0#K(ÚÂH
+Ö™ hZªµ‡:ÈT6<Tò„+æ1à…-b#°žcœ!¤àRwöñÈmKœ€9U××»X=~ %ÏÈ«Ê _›Lõó€C€—@X$Ø>46ò\F«G—ÇÌQÆÚ-^uZN>«5èYд¼QxïHî`…˹0œ”Xþ®ÉÁc`¤ŒÏˆÇX³cÌ(\’ ¡SðZesˆÛ]Ah>ßè3a)Z[–ÆIùŠ.
+¥µGØoóþ‹vì»8 Ï*ôøR-w•ˆ/Ìpú?übÂþlP’y2Ãq Ä|ìÇ2߀x)3Š£ƒÚì$–Š¥î‰*½ "SEþ¤¶7óÕÞé $’QñÛùj< }h:jþ9]ÞFÿŸU² $Iõ‡­<K¡ÿj|Êí•¿²Dj-ñt5»ºs«¶Ê·Ý8btÍ›.èkÞ„QÁ¡Â†ÇÆÉ/ ¢<,#"ðó ‘^($³ÜüB·&F‚Uƒs«›_ÔРᆩ¹„Ÿ_
+븒5…/ú^Íž5„cžl ç‰Tn×jŒ
+ÓÛˆJ×)™U
+É£óxæË›
+ùW%“Ÿy
+¦:¬N.Ê<‰tËìá8o\bt ᔸ€¹×LîBuM¬¾oñW~2ôÁY­ Ì<Yus2Ô–h…:Í„ ìC›ÇÑEÈ'SÖPP†¶Mý9ç¢yßhç/IìÛ¿|pYD,$ɧŠC†6é|]*[ßUg”#ŸÆóqƒ!¥2ÞyÉÀê™ÊÔ-ª,Ý› t9VÂôö¯ŠN'5%…Ž›Q•ê
+ÕCZX¹g²•%àk!îá
+É 9ã yµÿ/“ã8bŠFàŠ¸œ}U¾Jù_ý>‰v•º1%ë¦ 7|ü%¿ýÜqa#96&úÎütÎù‡¯]½N9mÆ*4 Ý‚ƒá\j.§òÝ0ºèÑP˜Y—I»›ƒ
+„6a¸&ìæ ªFì4úQ<k)kèCÓéâ’Š}C˜[•ûúý+.bkn•†dhcùYôÙŽÕPQXuùca•.v¿8|
+er“éÜÌ„T0E„p«Ç2ü¢¦köa8qnaøТ¼J:`
+:JÉ/.Àã".«okU˜OÞrÎÅ_˜¯ûÔ†óT ‹«˜œ¥Wðà’K4À¦;½{Qe$˜Dd HæM_ Å”–­jÝ‚šÏ3~ 4ÁAÌ}%c]Y|ø!š=K¨ÎÄ€@´_à+ìL(_$r¹.&‹HÔ±n½û 7¸JB«
+×±wƒœi
+g4? é®á©±z»dà(-(¾æŽ6ÐærnE—.9†«Î:6¤˜ˆd¿ü6| ÅñY»öÔ€
+ž˜ð1$É)Yت{ÉAS…kHqɆ ¡/$CbáYð‹îô€ñóm¢¹½ðO3u&Oñš¹È“¹\É ¡j­»…yÁ”äbbö¹¹)*Bò²,=<âê÷¶ûH^";È£}§YÈ—BÖp6íÀ€/yF›­û-I=7›ë6þÃòn¢>áyëSâÖ’¶5>ðs j©%g'¼G¥ÃZz…ë¤s.Á[L/áí¦f³Käq8íI×*R Xxv—aŠ8 ޣМ•™!ˆSéõ¹‹`]‘„°¼ˆIhaÏmß }‚ÎQšä¤ŒkÄg;Îy*¤rîí8Å[ɹ9žêm/ÖAÅ!*ìÃj¾¯ždá¸~QR5©Ê)¯}ógÑ ƒ1¼nEWdKϨ¨ÉóΓ\0š
+ÈäÚ“ 1`x8)ì)•DEؽ±½ó¢/BaQ' ’
+C‚>™ÞQC÷Z£ öýžÇ„ÔÊÑ\„… Õƒ¶²-]*‡é0)âò`£¯þ"dJË`xu֞ðšþ
+0
+H‰”—AŽd¹ DOPwÈõ
+I@·Ñx§^µóî!ÐÐüÛ ¹„?¬QùÏy\5¯¨Œ¢úD¤Áª. äÀIGkPfeÈ4‚ܶ¨¥.P-¼­+ùµ˜ïo]´ÃiJÓ$yÙrõát[P$Éþ~…¬êg±xÍ¡rŒÓ/T¢Aš|´ ñ°âÍ,ød’ÃhøQ_‰ $2£.uõƒ&Ñ
+ê7Š‹ÉÙib¹2XÉ”ž1t̘Æý|LHj4c,
+6|# ¡Oó­øÊåó킂Ȇç4Hg IoçW˶ߚÆyÎÏgT~ëÌr3©ŸL7‘´e}Bȱ“Èt~€¬£°´h,E•QßÄiô úÉ›š½¹Mãý¤¼4—úöU”}È·='‡
+ã±-ˆV×rïê ‚çTʨx¿¥©ØçžÎ´Ð–±Að”|aYXfü4ìÕm
+ ´ÔÀ>Ûº #KaNgIJŽª HQ3_ËÜ!à zøö½‡Û ¬ja!òöQ©åü
+W…u¾6ÇBïtVYi3N¥ŠQ-?˜>rX±”jB¼2©aZY†—jæû¡:²çLàéÔwHÜçŽú æóŒ!¥ƒi€À Íl'†‘‡GXßW®½’8˜½—®]TÛ¾1÷
+0Lôt ÒZ Ÿ¹“C+³`acºb@ø_PŠ{i;ƒXXC«ÃõGI%æ{ºDó¥T_–<‰]6;P!8SœZ¶ƒXìÈL“·ôÙq
+ËGI˜UØ‘*6¨lŒ OxXË8»§~nÂ2Ñ–ó=PZ.ʤ[e1Sؤ¦ê!±ãt#ŽªSû_ ›fŠ¹!¹Œ?}gtŠÝðaú?‚ÏžæW³ä 3˜‹Þ÷å䲠׳‹e4;~”~/oaX»ÏÅ ñ˜aP±œçLìå7h.8ATØ! Ñ“4ˆH,Y§¬1i™Õ|é¥EŒý*S€)þ.h iÙ&¹™þ|"/«Ó»Îba/R )a<÷*|]íiZ·ÐQËÔBÚ¦ÈÞ™þËx™äV’Ã@ôuŸàC5¬ÿ¶bßÛ/DÉ€3•° h ]E§$2™ª¢‰j[¸¨ˆ/m¦ÄòÊÐ%¨ƒÈø›Iß$!ÆÂmÒJDUÿÊ`øå:ççIP›;”8.€ÃàÒ,@®ß1©„YjI;6™”ÞKWÅt¼˜ÙIMV«@ñë¤^”
+6FÈbÒYRé3œ W BCuª,L³ÇÓš•5ú4B™ª»7Š:Ííü(Z©r×èù0§ `rÖˆ("ûáM›%\þŒŒÑÆ¡DGIZejØÅX¾ƒsÇC—1Ÿe@´±‰mÙ@¼¦ÂCº<0|¸á.ùœ÷¸ìÄÞ‰•6IA‡…n“븲ÀÁÊ51±ërbAQž+xùÏ
+øµ×¯Ü§ÀUR¾ÃðÖí8MÒD†?˜:u}MóŠ
+‚@ASñ(‰Åû8a úYÝH y¨$.÷Y”ñ+Žÿûö°¶i}è~r”4fn¨×Ô1!*R* ¨{•bð[Æf±œ”n|bƒš”Ü}¦ÍÀ'oÈ— !ÃlJÛGsLNÑæwà>ÀJ²àB êºl…NËãApÅ8¶Ã'§úôH§õ¨ºoÓ|0Õéy^ë2|à‹÷8BÞD€C–ew½ª2F"²˜ýµèi(¢…ìM +?)˜é &-]z`qoa×ä1MÙ§á|qR…·Ù"ë5îgzŸÆ¥ÄÏ)¡ Ë4ïø°!­ Jq
+
+‚&!‹Cæýz(b|¬<'fI
+”3@ªâNïÝ+(Eÿƒ6¨z sbçhWXÉ…Åà‹&Í[+"Á
+E­x ä;ruz;?Öàå8œ_ÂD*é §^ü2•äKÀà¡ÄO’åUÛä¤¾к¶ :·Á õî±ÇGÉx“d<4'uúÍo2ãzîð½âÇ ü¤KkŒ½#1ðª¾Nº\†¶'G Ì äÛ£(iJˆG›ÜÖQ—æ¨Hý†Mðqh1%DÎÞ(ì4ªk‰uùé;?qsºÌ~çG]`¬æHèEWbÏÃ.¨ÅWò©°÷SÉuTï¹zqúÙ,—;F<0å—c‡«È_3Åò@§÷"¤‚?x•VªµUt=îRôù—;MÖÈj]Už$õÅß7N…B̵®~(‚É`ÌðS¨U’eØAy;5ÅàsI̘%ÀPüC/®“gA<Sš\G‘¡^\›­"Ôž]à/RôÏD9€€8º—”¡8[ ãæ— ¡F‚Çs5…VY&ôe>E–!ƒÀ¦Ï{Æ›mB^*ÁñMÖ#ä%à§èãÀ8ÎÒP‰(¡uÙPŒVÕõiÈ:‰e;0{µî” 
+^D?¥ÎxW)ŽJȤøØX»e”š åˆ%È ¬ƒE‡åöQ—¢«SÓ«ÇXR^vv:0Ö»£ÙŒIÎ2oy¹fþËôÀ•Ý½BE”=諆'u†ëŽù•F“
+cx2`Ya’Íf˜}=9ŠHM¦€)À=|§Vâœåº
+–NV§ÛÌlÐÎ|ð‡Ñ®¶dÅLèƒÞ9 ¢xA¯½¾ÃªòÕF‡gZ@{x]ÃRÆ°_ÝÕê.°¦cEzAX2,è6óí‹ b×Å…ýPôùPŠ`fD_ݎ߀„µ+™Ð,駌Õ,:À«`wÔÙ“¼@Äî1‹$³¼«ÇµJ6Ø Ta~Åå\…§°L7x"ÍBţćqþ(qØ (1ˆ‘Òçå;
+ÏÁvm±>V*T ëÚ=eƒÅSªK`°Õþàôæ›Å4øüŽ*–» ¼KPMZ5¯º×Q÷¢KDà6(vú«;hÈÁœVQ€ ê@Â\9£ÛÐ/(%ìµêø¹†¼eú­Ðyû(å㤫×\¤I¡R•äS×]îùJ+£¬¤Þ­œzûN‡Â5´!÷¼GQ¦‡ÎûÀu%Çõ¨(¥ÈÜ8Æ­0–šþhÀ^$N¨­MM–•7£&œä©6¹ÔŒ©OÇŒ °GU˨<à=ßÄTÀµÁáÃEŸ^Ôå¶!)-È<,fq¨BàXnHFïpŒ.‰EãeCXâîïÆIðI““_ˆsÀ6¥È±ï›žŒÌÔ´ÞmAKÏ–$ß_LV÷‡ 0çë øÔã4/%Že›Šß†øÛÃw@>‡`Èqië6,ó\!æéâ S„‘Ùë(,sÐåð£ÛØé ”T±fM‰’þEw+:í*Þ[—z(ùáV§ÏBt«o^ºä//Žl‰Æ¼ʤ×òiyŽèr`EÂòb&‚K…¢aEöÃ^î*ü3$;Ž¾Á^ʇ<bÛ®þæ?ê‹ÔâÝ>~§a0Ÿf¼n» ¶< Ÿœ')iÊjØpþrQ;ØYQwLìûß©èE(‚¼b”
+þô?]”äó¡(VÉUt8¯'¥2Êåw?uaÕž%AHÅvÔ%Z¨lTzÌA¾m6Ñ^ì„+6·Õ¡:¦£é“ŸNèrœže¾¨À(Ì SĸWøAȆwhì_‘°Ãô#mwVÂìØøÉÊp'¤Þ$Õ¹ŒÏD×ÙœâbŒ¾­ ”+–€>e9¨ŠïÇíààA|
+m¤YÒy¥mê9†æ‚nóþw*:ŒÞ#w 
+Èÿ½èQ_S¨Ä2 YG5yßdMi"DÀ˜!›Û|*â>˜XE*‘&xL.¿U¼
+€@3+ÐHd ¾Žþ|¹rÚM–>ÇA„7²´¶¸Fç#pÁ
+ÃübÌK—î0s‘¤„`ABU¦õ$
+i¥åt.â0äûh
+HÅïT”°A(šéâºmfcJD‹½{n7•±£ÄÀ;žn• Võ ì“,-%Ø æ­Qµî%˜h|)±s ŒP”ð¦XHäÓ][ŤDÚÚüNÈA 1@»J´
+¸ƒ¼”9-.¯%;–É>ÀÕ¿“Ìèÿ”—IŽd·EWà=ä
+ê›qyøwQÓ¬ýO}.Eˆ'œß€a¸Šñ$‘—· µ{ A‡™³-¸+ÉÚ¹
+·“»Ò¬?ÃðÌi¼­3®öÀRúû¨o+¶Š&ŠÌ_qv[Œïÿ^°µ…$E‡à+¨Ï X'GÑÛbFœPÐy)Z“Üô² EsõüƯ"ôˆ3ÛÖÉ^!PZ&•4œ!>ªËb]J~ÛQƒ‚yÊû]Çg¶Xtb®»6¦E0 Ρ™Ç07EóZN*I­*_"Ú(΢“)b§ùi‚%üqÑe`@jjýÑøi¨ç• ³
+ðh µYÞZ¡ŸáŽT€ÂJÇj"±ÊÉ#›ßsŠfAæ^*6ÝóŽf*ýÆÕ.ñá;#³ï ¢õ±Käå‰
+jJPV‘DE»dU²ÿd{?'ádÛb²ÛB›0Û°JLƒ"ÄØ—y+ÑQn…8‚ò@ï×ïðʪÀFìMÃKìrTS{]%}tX“1¼ü¾V.J¶gAŽÛâ­HJJ;ò&–ù%Ûƒ2²š.‘F%•ä™%52±+V¶\
+x#‰Ó¨>4ÅAà —-þ €\>˧²¢ZX 9{ÍD%ø–‚/ãy¼¤K3䀢U@òhF³±ë € q`Qûý8<RàÙo ƒT=wÖ¾nC ulžÐb|p=,íê/C6®MO¬N‘…å{^ý-3‹ÕÀy»­ õNÓÀ¹ã½æ‡- /Q ¡f.ãö8¥„J¢U›3p»­‘µz˜V‚hTcÊj¬§k`(nä’ƺ5„uãO¼¦£.úF`7í3ô3 ?Ì6yI)È à
+MQðZò†Ï_ÝŠN¤ÇA~MEnÚçÿ£è¹}×ã~Pô`„ûb=ŠŒ]¸ªS xU¹ áE¨b—kQ™j¶$7«ÈŠ.sX˜þbiš•(â½–îÁZåøp ÃK²Ñ*Ó¿PÑ|˜1HN)á& ’ W^ÂnEY”PÖmXÑdøp¦”訬xÖ@!¶ëwú«ƒ×!8óòëmº© _{ªíë:âÉ€áæ&áè%Ä· 5dØ·ß*Þ&å'½Õù"­ÊJs™}Òûe(X•¨
+‘©ÜE µÁt?êÑň/Ì(¡lÄÙbJš|”;RŸ·Q=K*#¿}çœó6
+ X)xZ$Ö×D-Ð*\%ĵğ!ÄÉÔ"=¨GšîG‘ÿ@ñÈX­õ¾0iÉfŒòÁЩDì[´VtP÷ÍwßFQ@ t´w›»„ð¡²Ø” BŽ(àÖ¦«$¨©Muöp¼'?· j!»ûC2É—Ðh'!YË`jCO½p>9š¢b…š*‡ñØUÒA4þ [ Ø©„>úA'Ë4“ŸÄ7ñü¬üØé”´¦¨ŠxDšÛ4·¾L!Ï5;q7ó¡$JÆ«¼Ï¬~гˆ¼Ä¡Ì±OY*{R X<L¹ %Ye'Žl¬ÑÀNÑ‹ dþÅME>ZvóˆE‘´vŽöÒåÌàÝ" bu9ñ)án@ˆŒUCºÇMa¯D^+X÷ûwØ„¢¨«£óôË`·”§¤âVBÒD|†¬¯?;Ëï¡üv1a5Aóì Å_ÎlvB(0µï
+¯1Ö‚³ª¬ùqz—››z~^ .°eéMñ’>ØMPx“Y(YTjf9‘Pp`kkÁuA†‹¦8nd¼Åù³Äã|+Y'hTêj{VÇw0Šè'(}>†WDAìÄ—æÂt¹¯G¤ÎûòI0»…QŽAÇ’~é÷Òf {…‚ ëWÍâ–æEZ~㵄Ń›`‰"ÜGE`-G” ™_¬ *Ú6Sä1á,!´uÔ¬cj_yœ3ÀŒŽŒ3Ú\Ìûx„Ù¦~Ft*qôÕö_«Çø’§5|q—-™ %Rä4Ù
+ZJÏÇ’Öã306Pë ©A'~
+Ã0ð.¸…8.Eß«ï=Œú÷,‘|€L; ‘µw 8ˆ%)õqóF^Ÿ­gOžÂ«ÑðäO*9±R¨<ûî0q½fêÞœŠcˆ[kÇRð×SÄê¨ÑÁ­ §Ýfù¨X'¡¼ ¿!ÑûÂÇgpý“…«b<¿ †Œ…žšæ¢}”C³ <Ô…¼5›¯sI³AàBZŒþpQYžk¿O'jnµ%»Ó‡’7³*;¿þæ¼€A…Çjdö–cãðW¬$w3_{+âN]JsãH
+*…¼’÷ËÙz„¸ŽºU¸3È2LÁ’}Fä BlWO@“Ùkx• µ}×á-ø#I2k QúÎsâÇmNä\^u"ðèΉã£Ç·’·YýþÉÒ(3߯$Ò@Dqµíò½?ŠÌ^Le7 …áU¤ª çÎIÑùP±’fPE=ïÙ¦`EõGÎ/\$G…­‚„bÕq>xö5~ÑEóLäjïo³?b~KNn§ïßù‡ñ2IŽ3×ð t@ÁyXkë[¼­|ÿíûíV*äŽèè– ñ'D ºIï”×Ú¾·¡/(\â)Á=Óå)•¾ªœE󘽪IÃE IIþ)tv+;HßU^úBš0>XYQlÇÒ…NIWÄâWº{+üYâ†P8‘ïó-¨y˜üW\ 2PX,òÕþ]R~,S!ò"HF­þn4‘¨&à_éÂë/E¨<½ÃÐ"E•OŸ%^zóÝvŒ=˜D…/*¡ yfËÀÎ(pvK,¸ÓØÎ
+@”TåEh¼ûe²ôƒ*šÐÏ]Ø©"Ç ®Æs…>4eè³tœ˜Ò£S&Šk,¨¨ûe¥Ù$“¸È(ÝJ¸=TÆ•âÔÌ.$ÁIJϷ¨µ%¿±Øøu¾ýõ}Lyád ZIzÜøQ؃‡?ûõç"!­‘3´)hŠ˜PÐz7+ ±¢íôxÂT„Ê¢^¯ a@h³ŽåŸ’yD¾Ð·}Í“d³YN;Ÿܬ)ˆonÁØÆú€¼ö:‹ öôOý€ã?Ò•6¯[BkI©·Ø†ExwBÂfI÷Úxî­\»Ó]hl­ôøS•ÐFžÏÆ;µžùÐþÝîÕeõ%ï¹{0 ¸&8(ïÓ¥±+Ô¸²%ņ*×_„70„°S€Zíf@!5iò
+‘³!ÆÓÉœÇOÖA½´s,xò‡mæëg;•`Ù:JLd)µöSBœO±¼iÚntvµdr_ÕrE¿^ÁœØNÔog`¥¨K†‡ƒ_š_£9ljñ®’ ‰C ÖwfL©ÊCºZ·Z— ñnŠrOÈ©Ùg´ µ^D?ùSŸ_sðýT ¡bqãVݾÃúaèŸhšÒMmK¸Ž¸êà#™e:_sHh£7e_Bc÷`J4-/+]8%±»û·É¾ëç©Õ<øÈ‹§Ëvçå\NlYè1ð›ÍÎI f—ç'¡€<z”Ë‹ЂJê½>ž‹ŠšOR"ÕG}TôÆŒcáù¬GÕž^iñòóRÃc¸
+@ýD‰ ‚q±rPÙ¥¡.‹fÿD‰ lá¸%¶Ãs:‘‚cÄšûæ¯ïœØy›Cß ;æÄŽ™L%é˜qíÌ)Ë´•M)ÙÄ’­RŽ\ˆI$\±=øukÃËÅÉê¹æ‰£ÿk‘2“掊ç"Y‡ÄzÓ$g±90ÓXI†”dW&ºØèÌ—™›ä Áô(ÓP7Ú=¡›Ò6w‰Ðå¬r“æ¡õ[>å’£¬Ðk6Ùn<îTZÈ/<kã D€†Œ­U^œ#<vÅ‚ÒÜACZOX~­Ã„ìwÒª·ë|¿ÙÚƒ‹"ž_h¥ßâÀkÂEØ";·6Ôtç%P C«©„|0ý| Q9òmàÉÈØgø
+2*èùJZÝÌÌPë’u&¬Ôö✮ø‡Öò”Ëð2b’Hxõ=†Žk@‚X+ÿÔ8¼.’<ò± ~(žÞ㮽…>(©š @ed› Æ÷hö(Tሒó]åu¬ØÍJ
+*NÒƒý®²¬˜ÄS*j
+»d,ò‹¯=‘ˆÿï;=ì"Ávu§-˽ œR !+á•U¬‰Kqò`ç¦,Š²Qj?äoÍ 7zd—ÎZ{ 3Š¾N{ Až+(RÉ€£õí.b%]—KHÕJôéUûªÓÄRVNÂ6Z[o7F¹Vؤò÷
+mçèÊlì— Y{­4¾àEɆy1çÊšÙ?õXD<E¯«<•0RèG{v§¥÷$ÂC­ˆ6àGôÀôOµŠþÊü‹ÎæÏÐâbç0_“¸×®ÃüÁŸ€|±†:¦a¤cÙxè÷)ªæ£­¾½(n´Sˆ±Á ÝK)3’º]19–ŸÔ1^k C,§$µûÃ[ä׆óü1/Ò,o´lAÑØuA•à±$„”Eê£×#^H±:¶£GO—€g‰mqO„ˆü8Ûų§¬Ë°S‚ê)×à>ÉU—IB¿\Ÿ`ŸBuÇÿaµÛ5Ä^3Ÿc:Ž¾KI®‰b
+i‰O E çú ”âÜ·tÛ;¼Ä#
+ÜBô‚×{öûEÿUÖ¯‘ß¿æÔÒ ísý|ØõßV>
+WåÕúý²Èk Æµ}ƒ±œñ±•°éZ'´¡ß‘àmðüX[IÂ3ÝÚÇŸ³„Øb`GóæF~)[âÓŠÓá
+ÄH•i ˆçÀda4ªK¾^ßgÄ&j5±”1ú$žH¬
+t|ƒ
+IpvÐ`é˜6œ®,Kv‹æäõªµ5[ršþU§f;jÈŸQ™‘Š±V1ÜדD,îwè »ŽFÃF5_É°j1!÷1ŒiAÆÜ°…„8…×BTJÞG‘$ûd°Âh;ÓðR)œ\ª1iÓ‡´1­í+«0w–òÆ“óäp ³zÞŽÃØe÷ŸZe„’˜;áƒ_aÂFßEÆMqiÄ,ö,Í'ã†{ê.ûýH¢â[H…õ¬C+/÷¸oÄuÅŵc.š„Ê ü+î¾€~¹ Cþu\`Â#ýš¥zFÂqF$£0È–@ƒ‡sæÌ©]¼¢8Å|@Ó­__b÷›x0–ø Ž§y\©Õ¾_W‡¼
+÷õN½—I^1ØT îì0$(5³ÒB¨«-ˆ2±ø7¢êBdI´dÁÒ­ÄšÂu+À-¬€¥M•€`9_d5wmçë Uu þyƒ(%`ø Ù"‰)$x­oÃ@³Vr
+¹?¾ªâ/‡;bñâ(…+§[añÒ¨}Ò+¨Îz†Žòªqôz £*aâî—É8¤+RªÕ÷Q·âDc8‹Ñ<§Ä@Úâš4+½VÝ!vÔ­åçwŽÁ9osŸ?ïQÇ«8äK ±Ëp:» SM<þFZðóN}^«‡@ óÕ7ŠúmeŽH_ÐQ|"»äÆyÜ ôõÎŒ5Ð$\g—†øtõü
+£5±—x°ÜÇPF$ ¢ù
+[³m}£V®p˜Å yæ/™½Â <L!e2³×íab Ó²ä2^ò—Ðø/¾°Ë«Ø;q1®usÕ ôµ@€Ø³%ø$e)(´bb6¾"† ‚]¯ˆQo½Óú¾!²kì>…À¡úÌš$Z·¿Å%óïØN\÷úŽ®ŒÙ™ú™A/hxÐÖFzšÄPù}ÔTV ÅZ•¬Œ¶n“=Fƒ mHÖ{ ©‹f¦JQ±ܲâì(ù)”tÚ5=,—žiñ ¹DQL«Y«3¥?ÏñwÎ¥óòàÜnŒóa],¦¢mÛÇæ
+#‰uÛ©+fȧ{«3g¢„ð³à~'¬“rQÖ©qô{MƒA蟘53.»ëtîÔü§«¥´&Ï —ngžp׌¯}%PZ¢ZŸD‚=;C‘…¡Êµ
+‰­×êÅ®“ÒÖ?=±ÇD3£&H†âðì³Ad{kB’µ9&ý5Y•[ˆOM7ЯP¢ûº¶viQ“
+h3VEíƧS«6ˆ]e !^¢Ç¯—`Ã5°]‘U 3»ˆÂò5Æ]>!ô©À»=ÅÚÛØwÅÊ)(äyN}) ž|ˆÅ'h;Ñ0ùß¡ç
+/ìµÅXݦ0Ž<…e4Â¥Û8;©Ô>ªS™©§Ò£«ë$É{·Ò¯êhhÃ(6<˜*dí›æÀ)±²RgôòÕ‰<à·ÞWÓee*¶d2NèëD²åÊ#…‘›Í»´ŠâÐèý,ÙBƒ+ïÝ[~[É+_b
+·ã±WdJÇ)xŠV „&\Rl'AÅHĉ57›ÙÈŠ×ÛÃåñಔ¶Åb:ƒ’S¼Öjª(“Âþ†–•iÜyljp#Æ“çn=Cr
+ö¦ÚÔ@HpË×ĦYö”ZŽ¢ût¡©1´P÷“ñ LÃÀ•£|”ÆìlxÛ_QÀÁßƆ䭓҇âÆÔžCâ{<!­ºÜO3‡Â€`ȹ¶XÊš$aUƒÌRb`S­xŒCê¢ÐŽ'È›(nY¡ˆA—p͹)àÀГžØŠa*E ŠâGÔõ2þ
+³Xã¾úSW¿ÞßåLûD?P~L%Tåd†ß>æ%$ж@T±Ž^ÒA¾&¿k~bíËÉC‹–#ïï/ø¦ô@É;€Î ÑDÞ~
+ˆL7¢´$›¬g-éeêX:þi\j–ñ_¬”}‡k`5ØJB“Ä@ küH.iÄai8B•Ô6#±*\ˆ²ëFhXQð´ ˆÓåÆ&?‡}Àµ|º:UIס¤«,ýÚɨ$e0R¶
+cº¬N-¥záIÕ#é4ö´ø!¬7ü#þ@æ îs¿Ó>:á
+3â|¸Ö’§)->¼ŠÁ£X<«òß­i6×RtÙG¯Ââð#èô#ÇeN?r<ÊSî£8§8J|úˆ£Už9Z~~çœó6Ç
+:7ÏGðö•Ôó^&­$FNSï´–ŽõA2úŠ¯ÈéšR%Z®éëá}Çõ¸vgÑEÚJëEw„máYb†™íeDíæ̺£ /ZŽ¢ï:ó]ŠžyY±]L¸&ª…³ïï@eÈM«Kä½f4<~Æá° _Iß6Ò‰°ƒ˜t²´Ùzõ¾SZÃTÕyM}ð2. óÌéEñ‚{DË·üetvŸÕžÄ¯\þ_b({˜yÇp‡õ™æ„ÊÖfÆ¢¾ž;–bA
+ÄÙÄ1M“y%ÇPܲÌÎç?ÈiyX´ QçÛ g›\ÓµÍ Ž‹ ü–à‚^ª-:•ÅNiôáÉœ øPX[öå²¹ÃØûtÉ÷‹ì©|dÊ·®hyh7ˆRõ†±bªï
+)Ÿéöô\­
+µÀhº‚·—»×›?&õ3niœYe@¡+<Û Ñ˨šHrüÃI’“á*ÓòDƒoû;iðó¿œ'¨Ô€•VÝñ.#ð„ÉbD"Èc„\˜ÛŸ‚â Û™Ï*/ž¨¿`bzœÆ¡hŒ}ØZˈ¥¶¥€Øÿ·1t+¥>˜úr¿~wžÃ­Áš6Üë*¼–ù ‰VÔe^ûñ„èªübÇ+P µ´öIçT«d‚&1¤í×äÄ¢ˆNM­2È̦…„²óa æhËs@l‹Cûd„pi6M—ÕÁ‚¢]«)meõD`m^V”!²†Òvó›¶Y²t†|Þ—ÿŽX5¾ð~ÊÙžÝÔÃ3ÌífD6‹Òt×÷M7R¤EAOPöV3ïÌâwZƒÃ=“øäÀ_÷Eß°X„“ð|‰ÚÃϨQÙç¡óT2²´|=€dÁx’e$î@HÐXµº
+
+LJu¡Â×*`à{•ÖŠ„¸Â·ùýH€‘ÏáÂõ |KAoj…ÛdK}†!XZî9
+rD¯ŒqÄr¥‡Hüƒ_P»,Žµ„Â~¯n5lú¥N1lMÄLôFazya .‘ï©,'á©Vì
+¨‡Ás•Lˆ¢ØÈ]!wx€¥’”Y½,üR ü¦éxh1wxHLu(ó7ùš3B`†Î²ç`°…wÌÂÖ𜠇Íx<z¤\«¿{ÄuÖ¯âìUC„¤Á¡6I2Ÿ­5T`ˆìVûRkWX!™ÂÌp]íB6Èùq-S슶†{`¹ô[¦GÈ
+dÍøÍ@Tˆ¦"ù§®gÞαɮ×ÜO‘Gó5$åËÀ. ¥L„.ËeÔ/ìV3r@¸>) ès´«4ÒXÌË›Î顲ck¶íŸÑ1&Û´bL²“c3GÚîTg EðW¼p@gË1åLzз<è¥:Sä·Cúwˆ,U9 …VÂ-W$c*‰IC“ð51Š¡Mò‰‰¥1ËY"P°wn*c}Ú¬dƒªüiÌìC˜Fâc˜r›Ì˜%_ûrÇÕ SM¤–y¿d¡êºÕ4²hÑ}d†!O·æ„ºQíê;”™ÖT˜éYìöŠüNQœÐç,”—°#¶¥9 ApEϘª}Žö¼ «}WÂÐòãR±Œ­Ñ qË]ÄO³>õ•˜Ê:m¾îG£müœI-c£'£ãhÀblfNCk•H/Kó!ä!˜!ûª;ˆ"2™Zgup¾F-eÆè×Õ-}äš¾NHŽòd4Q9øŒáë*&z1vÖâÅt‚GÞ0Ï©²c÷ø]!’–Š–ä BQóòÆ×"FLœA,Â¥Ðé5â
+¸HF½F@?ìº UϤ©V&rî„àˆB`ö¢|’]ìëUg˜„0ÑÕmMFªjAðâ†Ö[:*^üÔ2{ѹ(ÄEBç^¡Õ‚(p©”a¿µ£6]>2QVEfg¶á­úß’VCùÌŒÚÀù”ûõáÿŠkB ¸«Ü,îŽÒ¨Ç +Oõ€FÜ÷Ü!p©î6¼ìó”Fàÿ²£,^2¤O«c+ÓHÿ•UÐëzÍ]Ð<óÆœ—Æw^žhoh‹¡=«
+œu[±v¹¦£»-Ê𪮘|Mï âëÒ ôñ
+¼§ÎLµe`×]&¡h)á»öPqúÍ‚rµR“/ª‡¹€ Rv+™Iq[º¾›„‰SqÊõrT%s·œâ5TÚ|TõH½v,lüÍÅeÊŠß'm»»Ô9½H´ Íl‘-dxÃ<Ðô…J|A˜»î^Oæ{\
+Öü2ÝZ Vi3+¬îG;¾Š ï‰CÔ§:» Zøè¥ÂØŽp]:ÂBG6m ©9†Ö,šCŠd’PcXç²á€…")ƒðË@Oæx ’”æCó2ŠÎ?('J°5LÖg™²oxG‰Yf‡'ng€k´a¯q¿ÇýÛZ?ßñ_eÓ?þ‡[ÿçÏüõ#C¿ÙºÔk
+•GÍP¦©ˆïØãŒsä› çº7Aþ3ÝÄ‚¦Év@mà•S£s:„"ãHLzN+ R1¯ªÉ¡–]¥®=-D$ “ L¦3Á:Öås²û\w C¥ÝñgN3Ib9œ“Ä:­‘¤¡ø‚4†‘ýÀºé†à¦ôâOH+´·šýSºi®ŽŠì·P›Q|…€D)ˆ‚ÂÑR7‚…
+²eëLè/]¤O‚´_YsMeú”`¬aûüá݈4‰ LvÓ]&Ïcþ-þsN5q›„dë»<Y C³™N '¹Q":šüsXHéµ}JK ›!M@Â
+„`C5ñ+÷y}¤qñ’Ï:W'äN’R‘<
+D¥ém®Æfÿ/÷i!倶±a¤†C„ÙÕ-ÅÊ1-–ÔŸb^ÇEP ŠÙÚå N¾ñ%¦7J Œñ¹:gÿ1/ùGEí¹*¡Iˆ@_ áPìJ2ö:!½ÄqBMú•v‘“=~ç*Ãr¤6þV.»å°’cNÅqtä଄'Šé4êøzþÓxl%ògû¾xmh¼²ø4(ãáR,¾‘5fçs«O &Œ4jNZ÷@d§3AÃO·ˆ·åªerOo41Ÿ÷SAâJ`Ü®çS^ãÿÈ
+džc¬›Ž ù]eºMZ÷ë³õ[<…šÅSäéUìd’èîGRŒ¶E8 Ëõt>9Ò*±Àû6µéPs›q±ççè+Y7ˆbåÞêi45$gÇö̳ßå?¨sögó,U÷ÎÂlÇòœþƒÃnqâßæ”fLtÞÝÓ_Öý¶&>J¿-¡ê£ŸRÈÙ29\¡{Š…'ô±Ú-çØñ 7fœf‰w#!¤•vŸ¢ÂzgÄŽaTÓÉ$$òóÛ$Fí’AÖ˜¢¥l“)<˜ß#&œÙ/Û|=–‹às3ø¬²Ø
+^ÙÎ{"œW:BóÌÑràDý·?‰Ç쵸iÂy=غRe§éB!§\æà:Ø©Ÿ-©À÷æ´KZ"yá ÍIyúÂ%žg_@žž×râX­èçê˜>Xî¶Æh¹îóÆ÷¦RwœïÈöòjÍ,óÙI«ÃÒî÷Ó—Ôçã)¸…(7C1Jl,¤CT]c}®É®RµÊcºz5æsŸ„‚ÞØײo†,ÖïJÀLy^œ#F5z© ÷ón[¹ÇÇØ›?¤&ž™›mH€Cý“uð’»ý7K†Pip¹2LÄ°M²øäÿ ¨2?"­YP& µVÍ)Ñw˜fÍ÷›p„=çA2¨«$1±@ÒÙf~±/v8~ ´…õ½ä î'ŒåQ¨iYŸs 7U?s‡É<u /‘†@!ö3Ä2Ǥ™¡dÇË`‚Í»ÏìÏÑ’œ§äêægm3ÇŠ—Ž¿Ìr^k~#™ÚXô’$µ:‡s)ùûKÕhA^0.¢fãᥫ_¤éÄgˆ¼ÞnN¦_D.¿ë—A>gËÆe¸Söf ¢ŒED²~tųjõeÀzè”99⊌Á.%Isê• Ý÷§õãéò»Ú‹C§Vîj£¨ídïjÝ^Ö©FÁ&«¦¡Ù{Kì´ý\@Ƨ¢1[(­@™}Üÿ
+?ÌG5Á¼4Þ>ÊI±×Û|ÕHK,wøç·è­Y›m€Ž¤ v¤[ “—6ÒÏ3 RI€ÇÚkƒáùµ÷÷na¶Ði›:òÖ-dpG¶óÂí­-ºråwØ c¿ï‹*ƒ Bã:<¶ºìP/5k…Tέ¬Ï‘YÊðbÆg6´…Ž£Ö½ŽÛ Scèõœ“Ä»Øk\¤[+Ð{#·N%*ÞöáÜ/>óﯰ÷+T륺º½½·ç¶Æ¬†èû¢Ô“0ù¾/@
+]®´Q @ùã#zÌFOÀÉ9{&SVb!§¶Gæ÷p™×±st‚‡`BçU0&%ï[t8yÇÔq—=ÀîSë8Gʦñrϱý´íÔ­‰#ÏÎhFvIÃÊts,çªê:$±˜EÆÈE`æBñ~ A%¥¡î}c j¸ÿš×!âiiSœcÚ©ƒƒx±i±vi^Èô_ ¶´ÇK%÷üÔ;ˆ¯eÛ¤’vsBu$¹&«™øïÙz…7¥æ½jh:¢´ý1…jVX s}?©“› ¨6·zγ¤'ÛL8^ɲVlH´:CÛÃ6arb&cÜ·ºŸÏ&'ÅÖÄŽMvå³.…Úïçì„I=ò1-[y­U‰>AF©Ç4++Ix†ìý#êou§ŸSs[òëAÃyóï™QÃ} ª³~5VñPùçCx
+£nmû
+âͦš~ô«üIš6ÊHgzÄs÷÷ôæ¼hX ^©òóîsó[wœç}œ‰7˜¹Äü;eåàYÚ^dú!·øT‘IAe׋‘?å „N|å†? écnq, ¤^…r÷c•7‰NDƒla]E’ñ©Úl£WúÛs•2A6}Áë=n|ŶG4Qße?Ž²Ž- Ð[úýã¦Ë'ËxŽóË ÷ØòßK“ÝêçÂ>1;h*·-‘òîfp¬Öó~PèâŒòÚ‹/€T»Ôè±²àÐÿ-?÷%ÐÎgš–žÞí™×5¨ÉûÑÊ÷@lNì Q™Æ[Ÿ3Ϻo°‚PB~†S”öýW¾Tá‘Bú+h>Ê:¡þ3Ç쉬òYôâZ6jf±þíJËL„¦ÑˆxÁhÜësŽ$¦3êÔÏ×/Þ-Dg‚`u‘ó0ÆmqߟßV ,Ly˜­]O‰»µ‰Ýü;AÒ­zQ wùòO¦<5¶íü+Fn—澓®ÿïáìÈÊ܃„ÜMVœÆ+Ž0£|ןø ÜsmjÓ„5¼µ•èßÏo+ÐûvUFØ­ßÿ2¦ ÐûV,>÷ЧE]Îû'ÌXyzÏ‚ªe<ò>Çl˜9¸»²·v>1®Çñ‰eo H†]s¥özáà.þ D“`ŽJÛæ¬ê4q¨™ØÔºéˆùwêy½c~ÿÓ3â.gF¯ï ¹ï¡÷%»;}xö^Èm ÂYôÚ¯ns¡1†,1ú•w'ØÕ>,øË’|°6y•½¯ØÚWÚó>‚øï^‡U –N27ÎèësümÒ§6ÎÛX•g­ß{¥À´@®kÛ¤ÔD܇"öœqÖ@ÍB\!(1[•:1®ê‘säÛ"a]ŽšºÝïsìˆJÁÎVôx;gмC5ÔQTJ;— =ƒƒ5jZõ{ "ù´]èQº|Œ#åÕÈnÛê*Nåå5ŽÔ²8|:¨Öü’â»Îx¸òóÝa­öʈ\ËKÞžÛÔ—\gåùVí|ó|«uø|Žá²½Zºaêg,úE‘dGk= ¹LMjcÓ§-¤CÉõÆëæ8lˆpéÁh@ÀsrL)Nÿ×|$=‘ s²l¯`÷ým¾== `)’¼ÁÝœ-«UÖZómE‘i“ \ÎPDz¤~”²gùÊòV3Ï…¿}_%ç]Î2<Þ9I³9jôZëx#-'jÒ‡M‰…ѤµëÙí\¹Pcì¥çÝe°o,PŽÚÞüø)*AúAAZ`ð³0hìŸ ‚öñcãúoÉä'ÅÇ*«¶mU¤Ä-ÚÅyæ~®n£Ä]¡ !¹lëW‘‚šÀé:¥½¯’ùŽt¬#É„©År³&ä¼Ë€Mm¿wˆ»rv{˜GŸ¸ÏN•·éé‹’Ø>ÜFɾ/ ð-weä%’(I(½‰)x…àY§”ÄP‘×ÛÚ}Q¿s$eeæÞ>©r‚Œ=ŠÎ@¤àv÷–,ûSÞ_ÍŠT ã%¨š%¢<¥èxcLnVã[õémàÒ®n,v™§¨‡—¯´ù&v{‹×µµ¶2»ß›æŸ¼uûö×Çõ‘šÀÁôû~71’CµMœòW¤>;N{S¿añ¥èï_e_Mx&Õ=[!Ÿó™ß¨“éJÂ×dF•uE¾BL£p‰IõÕÛ¯0%FºïP
+mwzæ'“%ˆ_‘¦@K³µ–¨Áš|å#ÞE V{›ìÏßñ¨Àëå'Y ÝF:dS2ÚÞ­iÈóª`oÜœC–X~æÕñOØ›žîÙÿúSÌwF­9^×ëx>Ü…aÒB©àL=
+<þ ˆêSšô è˜è&ÆqÚKõÞûú©e++6…¥UgÝ’OKz Z–$ »ÉMÂ@½´
+ãϘM å\”Ì£2Gj·Û®U‘`›ñÊ_ÜF7[vYSÛúUã£ä9¾CË÷UsÆÇønǃŸZ¼,ù4ªyÒ¢¨E_Kôýš^ôóeðw.ÉGýÕ›fÚ—ÕGÝÿ`
+H‰Œ—A’\7DOÐw¨µ#æ €
+a_ººxãñT"And º²·´‘® BÍs™×d29²$ü2Ó.C%/srM™‡ö•bÛ3f˜œ!;eà:…‰d¿|©™P(^ѵ:ži}÷àe'„xm‚Öq äûéè‚5»@@ç~ûï›ÙÁÇc®¶œ†Ý)š£ k3?ù(Az(Ÿ´‡¦R7;è•FNäû„D›ÑÉ FB(‡™çWb®B*I
+Lvu!åR€Èœ]÷_°é„²@Ä ¹˜ Ñ‚ÐÀX?¯’c
+½¥s ÍT– ´ H?l• K" \ÝñøÙ¦ÙE;;ºIªb»v<ôö ¿¼u?µ#œÂ ÍÛíz:mš DW´Ô»!;ƒ(ÂDÕ` Wˆ$³ º»‰—I~€¼g=‰–
+ý›7m ƒôDküG•›’_3\B¾Têý&'é[’^Ø¢Uî­ªüG "ô€ñ( £
+;J§ƒšµëm9QšÑ¡ÈxBv¢;/xv6â+Œé§3n=æh>UÈ®Ä5 ½3Ó:ºØè¥Ì¢!€Ý™tz!Œ±éÑÐý¦eÙ ›`2: Êé@@˜¢´,z0fÌ8ÅŽûg0OòCzN®µš7Uf½H9‡|bÏÙ-
+ƾÑ+ ¼S t¹ ö”,W€ É8iêx÷ë* Ι-÷ã­áæ’0Ô)ux¸/K¯Ì@ ?A4”sÕ"ļ+¹²(ŸÓÔ£ðùp¡Ã•Y ö»ÑÜÉ( `Ëzu UÈÒ»´* þóºIñ¤]L–1ÞÄ r‰Ë0“æG¦
+TÌR(°òÚ–ì*!OÊú?QÃ˦Åòââ¸
+CàéØóò{‘<`<9)¹×" ÅðAÜWƽ8ºï`7ÓkòD
+Tçeóâ;^¹# ¿&å¤v;Õ¹6ÒGƒUÎSJŠ§ìaèh9O«¦x>UÁÊ1Šr‡¸¢ÁŸ¶•“š“+.ãJâÈ#]ƒï© φË<áÇYʼ„>ƒ¯‘•W1O"Ïeˆ¤ƒ™Bû~ SðX]—„ãÎaV†ž;[1¸²ÉdL»¬ìnfÞ—Aíâ! 6€ðB³¨sC ™«VM‹]÷¬%%ëIZ©ÎL&JÁ†pAa,Á9l W¾b«F\ÂöįG^üž<Æbq r‰d\òÄÒ‘kÞ˜T§•ì3òì’SF %‡9QvL*¥Á¸‰[<oúEWeÿ©óÕdh§p$Q=•D ;âä´Á©"€”í¨mýQb¯ŽÉÄ‘$>A×½ìoP—QßüÁÔ2µHTËWË« §'Ê´h³¾îôó•<e:ûEûý¯·ßþ÷†,C`Eèó¼{1\%û;]@ÙôÜ*ÐúHëŶ…^÷SêGVZYM;QnÐóu/ðìÝkÝh#5( %-`·@"-=îíd2Æ4Hllˆ·Ž Éa×!i;¡1Š˜z¼1Ž1¦”~b(¨²7å,;oÊùO»¸Üg,ŠI´ÌL¢ÜˆtÆ0ŒõD*ÈyÓ{XÁÃYŸd 5fcCßîEþrˆè­ªü–ÆRòã
+ôàºÏ¯Ü¦P»ÔÄ2¥¹KÑãã|wûBQð¹Å
+¥=EÕÞ7w°¹Þ‘+9´rË6I™H>½¥CÓÏ}×Ø[iyêA¬xEï”áîšØY¶}E47-žAEÅåàÌÀÐ3ú-žAÝ÷ó•ÍNîì@8¾#?–…+ú•Kš‚e…U—NýØ hÖ`CìsÆÿ”4™îbb^öÈ 2zn9Ì#½N‘É&e|«Ÿ
+‚MËØïÕ7ZŠ÷6úT÷1Xó©–+ß´ Ô]™” Á?#7‘uN]9þÏx™$ÉqÃPôºƒNÐÁyX·—¾…¶­ûoý>HÊQ™Huya‡+ÐIøøÈE„™
+&¬­—#08èµÜur­ÄÎWÔöMD›oÔäeHoìŽLØ5VkW&9M 2¥ï,1K‚,U2èæëç6RerÈL[Ü ã0îÐÊÑ‚‚V vHÉ*åjÊ™‘õl抵#„¢ðmï¹­çaØž{E?c¥¸öÜeŒ÷ŠhK¬²¢Ã¨×)’‡a‡ô´Q28ñ`)Yr`žnÞT) ÿ°Ü6óÕé3çºqQr’rÑÂ~B?ó—ÔEûŽÄ˜ã6Çi|¢™ÖR0°ñI5c1Ü¥báÀäŸöè}FÐá_
+ ðÄŠí´Î[I¨a‚ŽÊî’ÈÝfÇb·} ¸eËÞ` #´Ž¢E§eg0]8½a 3]è÷
+ˆdøÛŠ ž×¥0Ó3‘”€¼Ö ‘Ëg^áJIDZ¥•3p§×¿ì( Ï)øå«JðÉM dmØ5^Ð'†®’Þ¦
+[¸¿‚ÃÌIšB¤ÕÌòdYà9ÖÙ¼¢¯UÔÕüý{úModãˆpo–™Hhlûtr`<©‡Pü×¥%r+¥xÌ¡.“ò
+.=Žòz¥±Œ)Þ!5V÷;Ø„
+Å"Ò••)VlWí`ha¯)ÉV ×£ÞŠB¨ãŸ84d*èCýk= îÁ˜cØ;ÈzÁk,uKÈoüŒHaG¢ñ˜[ô’)¿Ü"œ‚ÖEï‰Eñ®¬8+{¦Ü‚1÷ž­E15`ɻŗþ‰õsR±€çÌà*µÎ,ï’-L@æDÀ×âÃw˜*ñ }ž‡à»^ÍJƒìPLuI¼)å-Ùð Û$iHæÕ èTEÖ¸žôè‰4ÚnÞ×Y•¢Ý\q­Ëuígh‰;'ù»ÏÞþ¾Ö|­ÎõOZ5•S8 Üïâ ~ð­UÂËÔ)Š.))]–"2ZV´U‹3~¯TÀŸwQèh@Œ´xD­z€Ö”íuýÇŒqxî0/% 5³H,ÿîg€MŽÚĪPz 3щ'bØ»•¨ÃÃLsöœ4Fv!…œÏIâtšJÝ1Þô¥ ’šuTæO«ÓrÞßé3ë ²%Åc VN»‚@a*š Ó©éZ% ±aÞj²ñc„ŽQêf'UQ4@>Àa%ç *¯ËT‰@’0ÍýTTÆÿÔÇrÃŒ;o¶Á#")júÞÌ˵ûF5?M\1¦wø‰ã³j¯"¦‡!’íÞ«Ç*ÓŽ.³öHñcÑš÷p¼;Z’—ù©ÒAä™ÄÑâqSe[-ÖA‚ò@'¢gô—Q"ŸN yòª¹éïìgÍM€ûìõ…J0~<sFƒÅ½ènu¸ @t
+çÛEw¶ðj*›Ä`Z+Óºø'.°Õ6ueÞ! ü|±¢¼4…ø@2Q´9Ê&x%Éû(É2ñºb‚—°AÑö¨ÖYœ’_†
+¾’†“4öôÊ{©
+¦Ú
+CB€¼¶–¬„éÒ|ØL›$!Mâ\¥y½ï£Ðj
+_fupË´ÖGƒô°„­¬";2f?ÚW’Ì(î|ïï þ˜l>=ëºKÄï}ş䔬£¯JÝБ÷4¡JuRÞt.C ˆâ¤Bô¥"ù~P.ôZC †¡Aȸß½»%/ƒZGÝ‹˜‰bÀqs÷6ô“™Y[üð* Îhè%Y²ì£nÍÑkDÚ%˜Žx]vD>kö‡I½”¬IÝ'~ûÎ7·Û\Ñw}’‹ah½7R%mýé/Õ,(úÕK^æô¹÷ŽŽ‹ÉPsO~/à
+$¿=DÀþôW ïaã=Ê=cçB]î\Žg•(?lÀ_‹ÈllŒÝn¥áÉÅ·t _€j,VQ“${*óɈ Þ3°©ûâ`-ã唳X~9(80ô¨ªNOKU(Úpý2%Ôb+ÉÕ÷Ë ÂVQ‹ž§Â¥|¨ÖÔÏeäÝk³Àá`ùÅP»poCZ A#L„1#ºþA@åUxµ’Þ.ò(“ãXFü³ÖîÁd©(ÉÞq­trRcF$vŒ³ü [I4;§Ñ¬LÌ„k·6ÃÍ 
+’&»ì³:§ÁÜd†êNâR²i.À2° ’;Üï€ †=švnÃÁv
+X.#Ÿ¢T‰©…FÆrÌÀ[þ£¼LŽ#É• *Áè@ Ê°#qæ•Zô•Ôÿ:ÏÈš®D¤±æÛüCÓ¼€D,¾ð„5_8a}¯c…HüÀP±Z¬óªë°“Rí2ÞÐ\s!Éò*3JáùËŸw6ë?Ñ‘yfÂ!
+(e™tÊ<šÍ9~MK("ˆðhMòüHÖ˜X¦éK^„I"(€LZpikQåüŠíÂ\ LxÄ7RT*ëÜGm, «‘íØíly_DEJÌ”TY$“$5ž I¦“"CW¦(/)Ô ³eèë¤áårÖÑÆH§ýGÒ‚¬êhbîÐb’äŒÃ[ÖÓ cIÀ"G™Ä%4XÑ)QÄguþ¦±?vù3AÆ(K^4’!øŸ²Û«_{þùäh3Ćj°³³s<ð÷¬b‡@Sr—ˆ†š‚‰m籺L¯l¡|½FZΫð_8¾ÀÝaNv #KŽ
+Nl8faÜ<ª*rJjOóã{q€0l vÛö~/±yiÕºjA(ã!Ïž?ü¯IÄ"\{îæ6ÜW‘Ž†Aý”uÕ^=GT‚xÓ­qà=m ìÃè7½zÌ^í=ßÎÙgû˜}þ¶Gysœd†JÓS>üe ^Â.˜¾~ yéÔç¹{YJJ“i´ÃR?³¡xlì§õ;¾ÛA;m8×]@ßï|Ó¤òàa2ºÛÛͧãt›ä—ÚOm¸~új‡ÖÆ0’‰
+c×U#ZöäYqž#‰ éLÑòd#"ˆ²h¨7\”1~Är]µƒ¨2Ïl²ïóªˆM¢€ª˜OÿŠ/μ½Ôùð¤ò‰sã4N—@7¯Ê2ÊÞÑÏá‘ŸÌXÍfÇPƒˆñ+O/½ à/ƒü ½ô”càGÒ¶þfe…C´•äIW¢U´bš\¢ ýˆ!^ K/³ìdŸn1C]×)JÈCRùœyv¦%óÌ‹Ø”h£Œ=׫hž8dôâ?5b·Ì Æô\ú¿!³Ò<R‡k‹î9Á®BÇ¢3L”>ô
+lÌ@YKuÀIVN¤jaæõ“Fcx#°>!=r*ÿ¬eÕXªáþ4&ifcgέb¼q+,ZŠËŽêMw*˜ç°ðü²ÆtB”*;mçÿsrj׆£4­8EµÒbmÉÑ?âo²üDSÆw™ÃcÆ*š1Do‡ˆ„QoËc*é Á²Æ¼iˆÑeFj(AŸÌ•,sÜ¿׈ª˜Uc\c1_J{kešW§øg‚˜[§€69;?¤è†-Èr ß7 šÙ`N2^"ÔG]Š±‰a~Obî±(ä¾¾dˆ:e±K>Ö÷ì yý~GƒÍ]¢_.ˆ%œa_}?>æ5/
+ÁÚ°²CŽÞK@PiÜÃ8ä1üô
+Hnh„
+xüG‚n§O\ŠÙ“v·ï@oΔüN$ëÔUµÈÞÒ'ÒTÙWkÖl2ÑEX3Ë4Õö$Qz*Á@¹^ÏDŠ’ôÓê+€üüK a ¦p…™# ½q¹9YÑ,ò~AÚÄáD ‚gø*•–ɪ|>× :‚¾S›ÊœAcÈ›ýÇ ÿoóâÿñ«Þ¬2®Î‹åÆ5~1î¸Wo îù[
+¾xÚN8Z¡²HæÔzuúhfù¤ó“-“©Yû$2-‘fQzÛ ®ä…Éð¥Âw”ÆCˆ±Ð !Ý †•ßôg.2m¢Ö<_±”æG¡Œ$Ä ŽÄ×Í6ˆ'“N'i4ÿ‹jÕF‹Ðç !óî³ÊpˆA.ü¬/ª³!ÚLmRå–ÏI 0Õ¡ƒk;]ܯÚàÏæU¦Æá8ø†@
+²=‘“ˆÿ
+:‡)®cûÆ$.ØBoò•Â&±”8†íGõ9‰Ýó |:‰’dˆ}Ô¢Ê+R²3ï¼j(IøÞò‚¹sl2[A$¢3Zh bw]æ-Z
+Y˜Å¤Õ«„ßaЙ
+$cÈCÑ<6˜lGër22ò|Þ„žÑ]¨—ûtuw*Ä¢†'øp¨i°øÁ¿ƒeÀ9†oõ“øŠR7„a*æDbÎO|„Pøc³W!µdæ+Æ &¼‘g[뛽‚b7l;‰¯bhC W8rò"U¹q•8©y‰+fŒ±±rÞŨÚ4
+›á³²k° ‘ „›h²Êl3ìæd¥ì‰«Uñïá;ô¨ÒNÿû@ä×ø, jq^tÞë+ =+[Èj—š$q)H¦|¢c½kZ,A› ,eñ$4ñ
+𸠵aÕ-óÒd_˜,p‘á†Q\Îø¨VU¿±?Üàù×eЃäNˆµîGAœ)…„|÷•ä($ËHQ`îÃù?6 a,óϸްÔ|„-‰Ð¹Tâú¾ hf”<2çÑPZ½(’.Õw-V’aÂ6ˆ!‘ñØ´g ž0Cг¯#´ˆ,uCHbƒ©z;¼š]ˆŒo¿šüˆìr¿Kh1\Yd;/ÿ ë-‚Ûq²¬]Œ)@zûÄ|‘Ñ
+™Æ9éRzb²‡Öü;’iÈR`ÞÚM“*6Àw꾉ÂK+RX ñ²¢žŸ£`Jb̲ ’3 ÅÀÚ¶R¼+–3 O)Ìà؃.šp2•oâÌ£W;ò~Æ>5GÜ®Zéç;¦œ°<VlH›ëuÔáMµˆ Ç_P5-ÿ:ih=Ë4ó¦ ,`ª¹¥¸2mz8>¿ì¡»ÔüÖ–ë#f×$ºp©1Ð× “BÙORT£ –O\pSxó¬†3ؼÿ];™0óò7ŽKç(ÀLÙ¯c(¢‚y¼ÕËâKÄ«µy[¤ûŒÜ© º#1ê­ÆÝ|A쓦²&jLVZŸ!NÐ8ÞÅ•Îep1Äfúºà£µÖ2$±”t:¥ŒIꃠóL(!‰€Ã‚PÛÉut…÷%-qÆ”€R)8¼Êä%«þðHK÷:oG(ȺQhÿõ
+‹J!…•x
+¢-WG4\š™Ó!«b©ò®Þ½.’M”ñáU„åž \®W½U¢i’rEXâòÒªsÔ TÉ£Ì(ÁlÔø6ˆ)UH^õ¶4ÆÕyY>㿬°q¯^ {,î=ûN49o·‰&ðöª`!ÒÐ~´RÿˆÉ€±+Û3—NýæžßY± ]&òß­ó×n(*Mx#kØ WÓô¶äþ÷úúÎþÑÕç„*X–"e¹^rO•æ¸WŸL0 39mÝknp«äѯÊò0´Äqø æ1Ô]?sèlè-¿QuuÝ ×±©Ø6H™¶$_é µŸ{vü(¤I:t*~Ì)IÁwnĬ gs#ÂkF
+Ûû²žÙm1äAÂóï@~ÈÃgÓ6/r["B1–GäÚæúŽ<¯4˜%ã?yÅ_ѲŠ®‹¿v®2‹²È²ÂåáÏ(ý¤J ”œ% †üø+5ï»ålÐ7{8¬)·™z¹@Ä=Y öÙ¼ ¼«j)‹[
+"˜g{@ µB-þÞ~_‹
+ËÂœ§€.oü"çFBE»v ¬¸û ÞA™im^ÁµÜ,¹"S0e­"⺕¿L,ˆjÊ<ñôÖ7„ºOƒÌœ˜¯§Ë.@Uk‡óYû˜hØŠ ˜ËtT:¡ Îjà.rVÔ«J#€ì~½qæ*Öð;÷–¿_æ>9Á›îx«Í}ŽoŽøðÒ©Ÿß!ø•œ_™ oUÖM|Ô‚ÏýŠ0ù“Í”‹Ók‚î‡rPÖ(ÞO0s€‹çêEϼ>c#GëX)°çüo3èÏíúìÑŸ.í'ã
+›¤ Õ#Í,Ù|(Q÷¾Rû‡ü ó%"<|WZz3Ö›¯Û¨°„Eå/&˜A@–+•êëñðêìb­“p}âàU§zH~Õ ¯÷¯P6²Ì¢a§À™}‘›ÎÛ†P², i[ãÄ÷*öÆ4Åè¥í_!hï8ä]ºøaôIì”úUL ñÓÚ†`û}qkÚ‰ mr·LšóÔ˜³y{W-Ž€¯"CÛ6¼ÆT˜¸H)°üÿ1^&ÉqÜ@=îÀ(0ky©[hKÞë÷ Ú]…²[¦¬f6Èáη(FfÜëõ+_B–›˜¨Lé|Ã5Q鼺8ð”%;JÖkF‡®cüU03âcòcM³žMCöÿ½²›ÀÅ ¾ EºC2—.Æ!ñ1SÞÓ–fÌ ”8‹_óß‹¹ä\àCº+cEh¼y†8ú:´ƒK+S!JväÝ ÐµÂc¿ÝA×ëÞ
+óElP-å\³z
+’kEeÕÉ" fV€âïZ£S3.¤âº…SŽfyœù%æ(d¦þ±‹É´¾è)RçÔ`®›°KUkÑ%:WˆT¹Ð
+Æ.}Ë]‘Öfðð¦4 æ%n§í³â¡ô'Šš `?Dõƒ)ÚÃ9!iØ9el^”ž‰dÀž%5J[ê1¯¾¯ÎPBÛOb˜ 2ŠÍO‰qùµD=ì”&37ÒÉ!pðÐA¢#=„¼Œç¯§ û ¤\°+a;Þº/ßáºw‚®€pÜ«kKÇÁ2A ¼Û
+£Õت”µd—cQÚ
+Š_u¯Žž#)‡žÊç³Pø”|ë½z Y½º÷üvÎ}rnÙÜ'ðöªÓ$#U{¢‡öq^ù ð‡Ñx yiÕ/߾ j3ÇÖ+/
+¡0äÑCÀ6´¬:Þ»…°l ´Úß–¹†®A™uu­þœ˜V †ÅÀw(.ñcVO*cŸ)Ò WÍ¥3rŒA[f!’ª¡du<«6‚bA6“M;¨¥ ¤…“¨¥p0ïK‚Š9Vˆ0ÓÊÓìÝ”èR˜EÛCÝ@Q÷ˆÎÄBL%¸,K*éSƒUü9'Íá[i™%D°˜VÁ†}…à!zªè†à ‹ž8éý&X €€ŠÓÛ–&¶BIÆfÇdaZh,Yð¶"L¸ˆ¥›!`Oh÷XöU· ¸žˆÀÊŲ2¦¾ŒL/î–:ÃøŽ ²E¬è$VˆnêUR ³®šq¦@ÅíÞ’d]Ñ”Öò”hÆ"-'“Hnr|)ͦP€^€Ã2ëñF}ÐO œš;µ¶öPVDÅÑ¥Æú‚‚rŒZfùâ"“Æä
+¹ª0“ÛšSP2Ñø ·­¹I’V«àœ&b¤Î¡R˜²AC<¡ e¼
+`ƒ—yú‚êNC XÏÑŸ^ò
+Õ5Ù)ha<—ÅØŽr€ä8‘MC^nAu“ê™2zÌÿÓ9׎_“¹ÎáI÷¼•æ6Å·úvá¥MÞØÙÅ`›… F•Ö´¾§ã¾ŽA‚¤ƒv™Ú-©fT_–Úí’+ÂH’xÌM7 Hè3»¨RÀõw/ÀiVx,ÁÅvëF-kEÅFEèÞr>Šú{Ûæ@ÖìAŒ±*gs@Õ䈪*sg#õ±Jæp´5¢ËÄÛ‡L‘¹ŒÑ˜vìC{BI’·˜äKˆ!*:ì˜":à[|àzG)x„8Z]!¤ `°.©àV¹È‘é”íð!æ¥ïŸ§˜ ÷¥©ÌÉn‚¸1,zZ º3JÀ}aºWH¢Æßh—ºvBcx…»ÜÀˆ•tð*< ‰Ÿžn. Ý1€“Îòã„“7ƒ®FERŽO§ -&vŸ›†•M1•}® •F7"‚ýQ3ȕ̪cÿØ. Y9ƒa„û½8X6†8!Û×.`ßXvÙúchÈû¢™ÓÖAƒ¹áöYü¦ÿYÍߛ۔Jï*¯ç->½z8Ä4eêK’~EƒrF©m‹X‡Ž} ¦ÁÀ‡˜NOg²ØÈ]d;ÖMœE†•QAP¶ä ‘¤\…„ÖMø:€ûÌÛ­¼„誮˜Øïi{¹Ë9ÙÇÑ¿]'GIÞ…i³…”´é QòýD1
+M*ð"cÅ Ÿe„ºšÉ–ý¬F4(:«ôýô)mŽE¥¬ Ù31]‹LQð`ì•ï1t ;…ád<\FÐ-„ÄhÀ”Í»F;ÕTÚrèË©¥tYý8¯M~S¦®
+ÿyg·þ!žòø¨ð´l ÿ·vþ²  &1ï7k¼
+lB"ï¬i)zA2A˜v«…ö†aø›ñrI®#×è
+¼¯@A‚ÿ±§Þ…§òþ§}’D©­[¨^G¼°eˆE‰üà½êõü)‚a§²O†c‘“S9f “…m²b¿iû…ì]{àÁUÕK)¾p‘Ûi
+ ãëaR_Lü×GW\#7ÖMëˆÎÈK<B¸'ÆÈk‡Ö›sÒoì»
+Ž {t•s¼9l#~
+e°0Ñ¢ø$X Ög#8ýØb#¦´¢~5kW@Ø-™/&ýS%ÈcoM¬<]q
+¬•ôQ©Í®%¦óK6~9¾ѠĦ`Ž0LÇ…JïxÕ]¶úí¢À…fÁeÔÑ
+Â¥ú—¾Àᶠ//îFþ ò€&…a¥yé\ÛÜÎÓhAîq«)ê-ºR‰‡yð9ú ¨ !ø$?E™‡Þ׫ÙAQÇ^Oàî$UÔÔK"!±y8 ÎcdƒÝži>Ô Íè?Zvç!Q$ÍEõÊÌE¢Æ ië¥:«b¸öhÁy¥ÉÎ=µ²¿‰ËÉ
+€9ECyÿÎx?‚DCt!NHsQ#çùwÁ¼ü„~ñÒÈž6Ø¡¢‹³Â«Q „Îr!“_Êq úÓ a´ JêÂw ´oÎ0H¨Ò_äCqh|ƒÇ55܉°èsP‰G¦Ëcj$hà‚ßa–©¤ J°Äk`«¸ñÕ— Aì­Ø‚æ[˜$(aõ“Ôò‹gõåÌ?¢¥E‰óíb%4{ ì¤×oɨ2§%¤Ýj·(JP6f¶ëS¯Q¢m‹(Ʋõ(JP2õo<oÍ:£(”Ü£DXô%‚¢ueȈͳZ%ôt¦LœÃ(@ú5Jhì΄¤YŽd&ý]®„²Ö÷¸g Ïó<)Ëã(J4¥>ÌÌ2,ê¥Ô¯Q¢mo×a«T‹EI‚Špd“(éQ’PÉ*ÆDZ~Éâ(½Æ„7¾Wô’%‚¢×,!ªÃÅ°Y˜•5¢,AÉH\Èkœ%öúÜ¥Že‰&;È&¦ª"€}-Ü‘ߣ„¸Cy(Û]Îá=äÜûC”f4^’‰a£„ð…³Ç
+¡&cEQ‚’,‰@9éêÍ¿Q"@à=JÑb—#ù%t’Œy墄…»Ä³3¼å„opéŽuÐ .Ìš¬<ÿ{j…EoŽ‹Ï„Áë|ãx×Úd¨" Q¥À¶¢=§bi÷Š¤aFΕaÕ%ßÌã!/®ž³ÞXC¡˜ùÅ; [i[õ‚ÁMáßeçÙÀºjz¯YEwÓFQ±í*.x}»ˆÏÑd® N£šÆ ³ö¥m08T±uÓƒ}cà bî.Á±æÈ
+àuö'N¦Œ³¯íA¤ì&?g{"ó ‚’(àÚs— 9¨*ã´ýRòg£¢A‰8ñ,ýpB.†)%2”°X,8«ˆl¼}>ųג Îî$V¯ŠÏç9‡Å¬Š&,¥w½'R%.Ä^ é|Å$—½xk@WFêV?¸¸#H‰öoe<áâ^t·×_n臻®p”dÊÇv±!‡3þ$<üÝE
++h?õ8¿—"•`B…4Ó¼(^l&‘Ál—°)Œ´á21&¬ÔДí)BÙ™˜¤j¸}‚–r‰Lï>g"Z,n€~Æ.*á[=ï’%ÄàÒ{)î°¶p妀ûëGTdb»%Û+°Û->æ…aì-*zßEˆÁ
+CœA‘JRBnL°ðc0àQthº3ìm™æg.Ú´œƒ(d›Õ~‹¿ñ‘ÎrºG@VgÕßk>çhèJïjÁ¦¦6eäS‹+Ä‹ÌE†|ú‡n5´˜Õ•_Hç;]zÎÏrΗð#ÑÌ…EµS!‘eŽÔ\ÿ×
+Ÿ Î$+ÑžkTÊ…Ä-t¼ïcPL¬~Žþ< ï ä…Z•µ HÑšÁ’À/É$«Ê³‡ÌxjˆÉd4 \+¾¬ÈGÝk CµKù-nå§`Š<„‰¸ðPÛÀüžk®Â@ÝÁVg·ò6çI|)·àÅbw$./(ñVóÐÅm¸ø Ï1>…M »Ééømø+9ÌRÝ%ð˜µ5~a˜»Å¾+œO%DÅ(¨¬w' µî%¹ïšî”!Ç£‡„…_Dzl%{ ]øÈ©QQÊÜ `낤^‰È0Ý
+šEímâÈ]$Q•î|Jj›E~¥!æ×ö‰õ™rbÔnãQÏÑ2çÎrÀ:p0/ÝN ª2 ÍSµ¾MOMó^ñDMÿÖükГ«j´3Ó½¸u¤üÐéÀC®Ðç¥ÿ ‰“/9Œ #iÈ‚º˜v>¡çq17 åŽGþ\”+ ír¾YƒDóp¿’ rY“+ÜTÊä)&0(9ŸB`P.eõðæ€ûÒ1é—E€Ð0äØŠ2áRþ¹/6Ð_5`,Á6¸FNBƒZØ‚«9r±¶©ü|©Û¶|`ü²F¼Ñ 9È»ØCIWˆB1HNGŽÀñ˜4~Ûß½?AÑE”;`'†L®YY¿2XŸ[7ÊÙrÑå eؼÌ*L{–ç:7ÂORܪÉ= ’ía÷Ça–Žþágñ\›Ü“,Õéq×Xç«€¿à!€W.×RMKvrCLpëo–‘l$=|蘹›}GŠ4©,a‰sm¡mƒà„{
+Ϧ8vLmon*êDÇêv–°.]ƒ¨’Wò¸ gÃûK°f#â¡(=]Ñæßø£
+b!ÿŒéÞÓ¤_1.é”
+¸~1¥´%MJ ÑŽ{$G¤'MŠŠÄ2q*QÒ ñš)AmáOyJþlXLX\¤õ¿b}>g`™øK £^‰õSÒ¤cœ$ 3=%M!ÕCŒ@³å(iR‚+Ö@~\rô)i
+étø?ÆË$IŽ†¢'ð|‚
+ÎÃZ^êÚÊ÷ßú}ìPe"ÝåpØVM2?@Óø¯§¤é9#oÀ?ÓúY’¨æÓ¢{Òü~E¿¢f†,à(¿Û‘ä?Uû_+Šr,õàJ{u‘2&5£w!x°Ç(Ñ¥}H’d\jÜ›Š„¦eux÷]
+8"ð‘ÞûËöF¹—
+ˆÐXíÆ·*2÷“Ñ/¿©„—e€’άnk çKk,tþ@"4˜Úf}ZA4¥çdYúpøëOßL_Ð`=BLzðÍ÷"Çú šC Äoö?.ºûf¯æÝ7Sw¬RhÓµÍü
+² 5Ê«rQÐ/y迼"êí%s¶Ðë:?.rÖï~Ý'EWJp7ëZ´èÓ…ÃV»¯ÚÌÐ"üô&va%Ë3l5™¶xƒ]Gw‡²%y±xY°Ç6ÂÚ>Wé.ÅZ »JpamGë[[%\¬íÆÛï]U•CðK6’{‘ì/&& ™¸f=âh–% 5eö‹Àe€†ª™º»E¥OÉZO){v~½ñ§¯ Âj–&}G&¬‹…Á,–¯þtþ¨”V ¥¡¨¤½…™«Ó8d®©ðÝX礤p²|E\%%âÖ„ÚiÜñÝHÍþý÷áȉ½ÀžD'£üëå!ð‰Êœª Ih™øæ3ëêLxÀ
+Œ½ {‡Ò¬<×Ù(¨ñ\õÿPÝ…z„y$Y÷y §Ž_`³ÚFýµˆð aBüƒÙ|kWÐÍ"â- ,jÂÚ*Æ+¡_0p"ä„êx¼õtt,-5ðò˜º ›(aàg½t¥’‚KMÁÃ`á &¾É=‡è¤¨EÒK[Åõ ¹¢tõoÍż㑑 ÞÁFMPgù¨Èsä‰HÀ¼°|E™ñUÒ(‡º”•ØÆØ{a%^ òÏuh-ª†U$¿Y£W!>øÍ麜û(·u9^²9/÷€QÑ¢Aûû)!uE[6-.€ñ–¬}™%Y\Œ%ÛоÈWš:¸ËÇAóZEY]7]ÑžY‰Ú•ä ºæ–°`R0
+qõ¸¯úfµ~퉘vÂlÏÊy›†@¡–‡56ç;ŒÛ˜ºÙªW¤nd󣸨í’9 œn»o%ïͦ"a3'ò^ØÊ áêé‰òØmº{ë"5lF¶sPaÒZb¶q/<Ö“5©*«$qwÄñó¶ ±QšŠ)ŸÃ"¬ qŠ~>ȃË6
+¬*)’Fø(zE™JB%œª~ÍYÒn`¡ëÆÿA:G Îrhf#õÓ?iì—]…g^`"®ƒ¯È ¤µdçd¬&ä[Œÿ½Y};ó‡¤Uª–¢xXsÖcÁƒõæCrà­™e<ú–çYè¤Â ,+ ð¢Ä–ÀßëE~¶-kD²
+!móî(£E'íX^:f°rKÒKK¨Ø‰1òt‹rÅ2A™›ý½è†EžŒ÷´…²áAÈ”ÁHsÆWÍrZ(wS¹ràèQóX‹q…4‚
+êC ´‰2¥
+üɘÓ+YÈÀLÉä#s}8GÍÂSãNâÃhCÑòÐæœÏúï(3%8k‰ÇºiÐõ¬1·pß‹ž©Ú´©2bak g»5q¨™©¦ä"þrš¸[Av×
+ÿOÀ „Ì®¥ä·Ža{r”ÀÓâvHv4?RD„ÙŠëÃ9(õ°ËÖºP_jê¿`×@èÝ¡.C
+-!˜¹POf,àšà¾9çÓïÐiáíœû ®Ðè=:À¸B]×@è¢ô¿‡òW Œ yµag„NÑ5r%²!©w/R’
+Ü€[Ñé~ ŒZÞð½Å} „†9!~72Ö$çÈÆMšý ¸…ƒ‡ràoõáœ)ÓÃŒl¸@_á½ÄÉza(y3Š›ÒC ¼9YO×188Ö\ësQ–=
+…=B}}N!t›jñ¡z˜ÄÁ¼´ëRð}÷D¨™F…\èäÜt9`L…½¨•é^ Àè±1Ôr²çŒ—InÄ0 ¿’Ú—s®ó”øÿ×);ˆM
+“ã âb²Ùýt„2¨\!. IÑs„θ?¡»6OGø~·ÔFñ6•¿8
+%þâÛarûPg(bYã%#˜?ül[Î2-:É^UPTU ÙRÎP¦9RÜmlÄŠd¨¦M؈‘Ü|§d²ßÛ¼c§Æ$c§ÏÔäMqBA£8kóÌ&À•ðè;Äí3}]['<
+š ‰A¡n²âšå å#Rœ>ˆ—àJu‡é÷ `M¹1‹î›F…þ)643çÜ•MJ¼„Ÿ¥"†ŠüF½ïÀë’õ¡ š¹Äð{Y-µªþó#À
+H‰Œ—AŽd7DOPwÈ LB)‰\·—¾E³ê¾ÿv^èë{P™*¸à¦ÝŽü’Ȉ`p xüǦ=kµZZ¯mäxÔâÏÙ£d´:í‚xËÙG›eéÏÚæhÞˬ3/ÈnÓ½ôäóC –VùV+íEfïÙ|Zñõ^Í8=mØÄŸ¥ÎÚëáÝdFä˜År¦ :j<­÷&öãwÆ“Ïœ¥Yæ~ø(çzò¿ ™Õ昭–9i^³ÏîÌã×ÇdÇ÷9£Äxü>‚ê3[_Ì´X‡õh4ª”d”Q(‡yŽº ÞjuÚ“Q÷Wl–ððäĺŸÞ†•œ£zÔvj ~t±­Ïç&´†Æ…(”sм=®"O>z3¿úð¹úÙ  —Š}ó×–¿^æ9‡7½3ð­6•šsøMã·¿!^útô†á.=«O¯Íü÷£<þZHîÜÊHÇŸûsÕçtja§ÌK\uÔ@m¿ŸšA”ÎÅ«-Èè³uƃÖëË3{Ò Yï^P!/^s¶Ý/Ì Vð-èø¥Q«ü1Ð wAÜQÄ’R±cÛ_ ›`fÒ']O;~º—Í!jËqßÆú(5ÑãÑ‹ë”h?Ê}¢À>"×IóY{ ޵ÛÎûLü×E‚X6c@•¬»ÂÔSWémô R'²ï4Ñ®F5îfüÊèÔñó¥ï¿O{¶9§ùT™Û:©N”E³bĸ “Z¡g¯¾µ‰ ©8TgvÂ13KÄ®ð¨=Ôß ãÈyR .¼g®ï4d³#” Â*÷À”û7FùriÒVJg£ø ´¨E‹¯óÌz߆
+•fCiPé{ûm·Yº5 šmŠJWŒ”Ú-öŒ˜mâY¶ZoÓÚ¦ Äjˆåó4'Ùa«q¬”ô}Ò¿hS2¦žO*˜.æ´[")“§clüY è'©ÀíʵÎÉ/Üz¨>&¡A¾3ÚöJ$o¤(5Ds…‰Éj=@>×IЋS¨ëhÇÏ4RMö˜ >$ð¹ z“‰uý|‡F7”i±ýDÓK&Wvü÷ÁAœ@‡[üTxjˆÏÓò µ. Ñ¾½Þ ?€ƒÎ ¢
+sI0øRc}‹¢9uÚ*uÓ0Áõ¡k;ºÝ€‰Ý*äÅ7.GW}hj%3w~ói°£Àú†ŒÁýÌø©?Nãé…’zø¿}Ò¿Ðp±u ^‹.†5'1fØŸ#¨>ƒjsû6ŠLSE3<R:ËMj¤Ëp…|ãB`-UUê~#L´#01ð¯aY8›wUß7«CÕœ‡Øú®|´ÖVîA¾#=ò<“×
+€zE¥äóC“|Ð  ÿ5^¾C`Eñ¼
+“ï—9ÑùåQgγ"Ø•®á‚¬>ãI,†Òrc¿Øú#ЛÕë¸F`K&¦e?ÏæZu*"™‡Ð{É0ðh(Î\é‡Ì ‚|!­ÂQòàâ@¨áħËi`\mw2‹œŒéœyaÆè^ÙcèûýôÔ* Ù[\®ªÔÞ³oHÂRrZÑ3×Q¸™‰ B Û7 Þ¨‹ËðB¡$ŸöŒWòj,½¥?Ϊiro­˜ªðçO¤%&±ÓNv6î½ÆÓ ª" • C@‡–vú§ñï½ç7ä8€pzB€²#\Ø ·ã~R Ã5 E‚}¢ÐD¿Ä`þ‡lläðÂX¯Aüƒrʘ1ñ¦üK ³­Cƒ” 힟:ˆØFµYdÈ4û3)SýöI}-xùLß6Æ¢Ãu«¨‚Œ„Ù”bÙ8@ÖQ¸h‡Bìyå’÷ï@-|H:ÿ¹±®f"+zœÄû±×õXÎq
+²`ëà?ôõ,Ä”#Pæ;k~ñ:ŠSÊrCRÒqáY/g¢ðnݽ£½žŒBÚ¡ÌeCœ)ÁúÃt@¸É¾S•„Gpi\~ßÕÁ¾  uÐjJ«úíÎŒHõC)}f*ö ³ll¹›]£Þ8‡Ÿ!_(úëãz';‡‹¯„czz§Ÿ€Þx8î' WS8jëtÛÄápqžÍ8´¬Ç1?ª±túQ*h±–MZ'$l8˜ ˆk€(8&âÛŠ§m…ª™0 Á¿7Ö:q'¾ ÉI,F90…œ^;ÒÏcÀc92W’Ÿ¼s¾Ã衼¤äh÷.öú™”.»42ê~7f£t öÔ üsf?Šúƒdr?0"Òô%vý>‚*{X_L™™î³¶"¸„‡ìm±\Q
+njð÷Mùö”ÊN n€:2X>7ÿæ3ÌéT\‡c‘÷eP­¦%¾ u‘ãµ÷àÝì{ûMîLT´Âo>¥›®‡ÖÄ™ÊØ# £wjCE´à]€¡y¸Žª«ô¦A('b/ Zä÷î;¸Es¶™€Wqéø
+9ƒßµá¡u¬\b€ÕÊS´±ì{Dò¹&ÍQuaŠ|Ÿ?‘¦T“1½0N8ì?Ál„êÔqÚ™ÀP¨H¨Ê£íEÀ8rÛáÜöþ¢cæ$Å`‡á§µêó#òirK¾
+wâ‚ë ÒWrõ Ðõk¨­ØrI&4ÊÙæL?ùõq½„пªyKi£Ü¹ï Ž£È\›9µ
+xÄ Uì˜b€PJ¤S,Ða
+J1%ÒW±Í‚•ÛHÉÕxŽR° P`¡UÍbñÛC+Cv²”~ìcMÀ­CßT<
++—8_ ë$Cs¬SVïÿc¼Ìq3IŽ(|ÞöÜSh™íêylS÷×÷"£øÿŠÂPf@ÎcVf,o‰Ïa¤h §y'H?CËÀßAà
+")*4»1¬Ã0%ÚU/㥼©°)®Êð÷l#@‡D_¢uxvØÊ×FÈŒ+þñC½KæX@©.Efud'"fgÖö$ B «Ö+Dª48¼È÷sPr¯à[(éuÜõê3I"µ¥ÌÍ sXöC&¢²Fe‰³Qicp`ÊɈHé½ rq s™u¾‚3+uDz]Þ–±-Š:¼!† ”¥‹ñ7æɌɷ—€¾@pE­zxë¶yš<'•o—¯ªž‹ä´¿ì)ÿY[¾jL¸™©`Ç2{I„r,°Èx¶ãdý*G!+êæ-d-ÅT ò_Ñ9 J.pRÒë2<å¤ÍÙvSÆ‹gÉ•{aØ\C°»“‰bœœ\–/õÔz“K‘0Û{&ý¼d«ha(GYŽiÖC‹¾ wŒ$nåÂ-ëî-ù‡r _q¦7é¨=íKd‹6±.-p‡‘iÄB 4£?‚ŒñþÛž´É1üŸ¦õêÊ=Š#[jQX
+d&«Óh¤å?Ð!M×aüœÒqŒ’ ™ÛžGÖæ:2‚1$XbAøk´V¶Y<¬ ¡¼cµó)zï$–w;h+HÀêè˜Îh©¶ò›ËeJõ„‡\D QãùF0Íó¥
+ÆîľÄÂ7ènÐÁöp¬J)2ó¸÷ˆ/£àUª(¦zà åcJ-9® (o1ŽýUXá
+¦¸°ñ£aŒÐÚp`耳çâ¥M×Öñ*Lé¥ÉÕÖ®ˆS3îá›q¼ @·è}î ôõ;ýâêýç#}þë¿ýïvù!g‚ÈIa5b@F§™sBà~?€†A  ´¤5ƒÐr¥oQ¥AURø3²øLìÿÀ^K8 BjÄl’
+Ë6iËLHãÚ`zçŒüôWxCˆ•GÈzœOÝ;~;ç>6·ÛÜÇïöª`ŠßŠ­Âk…ÿq£DXw·O¢âÏíÊd3Ü> ¯YÏâ5î%f<CiæWöy%Ø¢dHÙ¥14iSåd5Œ0M\/'1±ä"`%ƒ£ÁkRWÈÃn´(™Òß4~³ÒƳB…÷&H–äòñ‚tx<-|¡*)ˆzÓ[ž€šñ8îÎ_dœt³2Ë
+mJog#<0hÙ€óÖuÁM!o˜ÀåB¨²k+ ¡0„*É2Ô;â|ˆPºvñëåát'¡‚ÅôûŠ?ù +d«WñˆV¬L8«锊¢@4É!ë6¼ÿ²6ð1¬wÅM–“C*ŠZH¼Ï—ð{¨×®É§ð $HSÅ·YR?gáÃY#Ô²žKãOùÁLmÞ@ªd²¯Fð‚àéÇL¹û¥ÔH:4Äž|$k€×(vN••;„ïîL®m@AÙfÏè›Êc“<èWZ×úqc”o¡ØÃÊ£ @×äÎË1ÖÁ(3E¿ÜÄ•`¾¾³\¿l•Ý:c(85BS[…(°Vºùoaø
+‘†:¨Hz9ˆ
+3²ÆhÙüŒ–ŠNM¼5²¨æg=ÍÓµþÆËI²Ûˆ¢+è=”M£ÿ©™ãj Yì1µ›
+v‹ÅZøÂl%øÔŽ˜D‘ˆUt-ãm³œaY±-=¸!ñVÅLúí˜`Nƒþìh
+(* Ê£q¦Ó-ùŽÐ^õ;N ql³¿[ä­ßísï](Á]­kÑ¢¸‹L 7
+û>E–]™sÚÇ@ ‡
+]QÂÂTï’ŠÜÛªŽ´…Ëe-¹nƒZÎÐq|¼”só´sä0ŽTµ‡EBÀÙ$¸°µ%˜"^£ç5Ï{ÑÅD}¾(
+š¾î¯ïÊX:úIa ¤>ïéXC@“ Lñ~ú¥ƒÌÈ«ù猇3†»M½Ó³»ÀB–¬7߯¥)eìé8†Ù$¿Ò<'yIøßTÛׂMÁl÷ý)Š9J9嶥¿JŸc!
+rî+žò¨)Ñ­RÞæEu‚MH±ó5ç}‡/EŸkgXX‚…Ûij”YúËÞ¬‡“̸M1;Î#& ÇÐÊWQ¶†5‡âåÙHr·c”ʸ
+Ý‹›7ïËéäÖÄ›­0QÍÏ­
+ÉSÇãÐcå¬@Út.5˪]Š~¾(*üòÇe¢íºŠjÁ:ádçâ'¨`
+6äM ª9{b{½#ÚÙÀdÖ°E÷œ¢oƒ”<»6œ¡^¦‚ö¦P­„_€~(1[¯R$D¹ÉEóB/D
+»ÒùMór_ÈxWÚ9 Ή<µ—#Éêb¤j™•~Â͈©#:þêLJW!³E2
+4”- ‹uïE4(ˆq+\”ÖVT2U–«¹½[¤\q£t8”¹ä½=AR–EOõuÍõJ`!ãX «\lÝy?h ©iJýd*‰ÛÖó» Àsw“f!w›´IÙ+Y
+¨•ñ¨X_œ“²
+`‰ýð7^{J$GJ;Àôî7ÁUXð¾¿ôÏ üiP-OEH ·SMQ #PPID’¥_/j ƒ® ¼TÂì*>"õ°'X/êƒJ*›‹Õ
+žØàØ2{0É)Ó±Z¿^)£q<Í13O‰…Ý6¥ÌÛï‹Ô3­ÂY Ê”CF ÓÜMˆAŠOGë b„„A®]ÓÛ. pª ¨kd¿‰®ØÑÆ·û ,L$´aÈ(ÐØx/Xß!(¥*Kבø~}È1¼Öf¸!ÃÉ)E~®ek°byÌ£Ié½&É34ÜV€QÏñYìnO'žhÚ$¡² °‹ß+û¬.ée R&ì·G_*Ö«¯­sŽ¹à"8Þ ™~™—”5/²¼‚ŸÕ
+Ù€,yqVܯó³€äu»WB&¾ ¦Øvø·ÜÆ;X
+Ê$#¤´ÏËÐ÷Ä„P6ÜïEQYhˆºB±{|¸‚¶zŒV ­LÍ9¯×‘6n0FÇ°¬«cÝ&é’©…“ྺÖe‚§ÌstFÄÙ'µ`Œ:^9ÞÙ‹Rá(Ë¥ßÏIO¼5šˆ†¥Ïeh›_ñ<
+ˆ&9dø‡8%ÉØ2¾Ý‘±)¨…p7Wæ|«ÈãÍôÌÅ¢N°_뀞ϞúÞw>:$ÔöÚÔ-Aö½ò#‚HV°·¾Ö÷YPÕ "Û8®%kðäM¸¤¢æ­»ç€:È8Z@²oƒ2¢ÊysaL; ‚¤Z«¤BZ¹1EüÃþT¤yLjNqõâ]ÚŒ™´­O]ŸX‹lb8‘õ%ò®œvìOýf½´‰üçƒ+1žRüdpáóGÔ‚ò¿>§ …Až’YíÐ{A„¶µU¶J!VÁÕÒõè§STœ‚¶8®¢ëçnEŸïÜi‘Í¿þûñÇÿ>Ä”Í^†ĺþºˆþ„“áÿÿúˆ[°B¢‚Q V“Œ
+G£
+Ýüç/·ÏRø;q̧åSºåtš1Ê{E@‹-Â{õ,UxŸ{³ˆ¼#ʤaEã™; 57w¾]tiÁç;}2g“Šô”צ”Ú*#FÉB&e:NW;ÿOy¹d·ë@t½‡¬@‡_gÚ»ÈÔoÿÓw‹
+џ룀ˆëZ6žs›Jâaa¾¶é^ d…mÑðµE  ­ªö}rIùwWWc•Í±3äÆë«#Ó¡ T ‘à÷Aªê¹¯ŠÒè©*AØ
+é,i‰ 18;éÂFȳø6
+Ü8ÁÚg_ðšY5›;‰²WX‹Fò{»Î• ]®
+î3BåÚù Ø­;„_L8qôZ’dgùO*v"¾Á›xê~TC93w%¨ú1ê üCJÛÕ÷•ûŽßõGeY#Æ»§ðÖ’åŠ/F¨,ÃÁ+ ¶î ÌÒd¥dYÙÏÁQur®‹™Œ^ HÅzÕÍa€5¬`êgcàËù¦É—žgЇƒèˆ°–|2- I9ö>å9x>Œnú¼°¶$˜
+˜D’Ú0Ó¦ÆuÈ (ÎCâ#Á‹©0±!ÓKv6„Õä«%Ρ‘X, ‡6œP´´-v'º²F ŠgiksorI$ð,³ÁqQN1=B'Í}–õ«ºRäxMzF[å¤-6„#ƒV²¥±Ñ8Éy¨ %z µBøcÐÅe>Ù6›U‚Qb^d¦¸¬QTG˜fP„}Æ…3hYÑÿ©%ÆÊ>4JÅx)™i{žås™Y+z¿Ü¹K³1ÌrñÕƒü1Š¬tù”é[î¬" e*°o6ä × ·':¦”¤iÒ}´Sp:û)µ†Â×Û¦±†¶6B{‘ƒ49´H0?tFœ%ãT‘¤E±åìt®B6”
+ÐÇe<ÔR…h}Ú3NÏQ}Fœ…w 'cü5á3®L±w*¨BÙê%DÑVíˆk«|ódµ¼9åIæ…X°×So^Ì31ÚÀV³0䓘/\á</šä.¡Ï÷9L¬G,/ \„q£ñì€^s÷ï6i»©L h5±õsëogýï
+2=6Eûñ#»×o „¾4&‰ýOÜ´ÁHfò- ÈÀu˜~diÛm´Kl=}|íÉ¢$.W'luv”bbmBÊÙžÒfM®äçHéÐ)u¸º’QM †Ïp>I]ˆ[K ‚Hâ$i!K¸fÊ‹1Ȉ~Wz9‡qÍP
+e§UÅï$‡õ†ÐZÆÊ8/0}r,6«ïÜÈ|2†|±w›ƒ,NŠ)<wº@<RC¨²„a®òæ:'75
+¯ŠS
+¹ŽÚGI¯Ù³DõquÅVã«7W
+Q ~hŠ&þý× ô4ž2‰LÈ’ubòú9ˆ<“`耿àöw ÙyÞN•Ä¤šÆ•ÎÜìC4y=DO{ÁŸhéC¦M¼í˜^%ÂZ$KûåR e‡;„è[ÈßA¦”ÛÔáã3Ô3ÀÀæA ß…b)™&™YÛk^!Q<¾Pô@š“3X.½%wî¹aÈ4½ü•#7KŸ!jÓð
+ùºüÞ‘D‚\¸»{Âx1qÐâÐzò.$jâ[ĦÞ/Ìë’*¹ºå·ï¾€žó÷
+y©Â+äRÍ ói¬
+™Çø9(9$E;&Eò‰Kqhˆ!7™¬hQÅZÖòè’› ýÍ)U
+–¥NlåÇ K
+^ÃýdÊöYmËÅ?Þ€ odúÅ–þzñu$pÈx“úÊH×¹ûV Ý«7ØñÞL& Šûy®,Ú„»óæ¥1×4
+[gæ¤Ú§[!4|™¥¡øñhZ7#”6Z (ÄCq3*tRkP µð£DgsÛÕ:f˜@7Çì‘:zcì:M€û dÂÕíS l\¤j7Ñ›š{%{úd¡Ñ$-õ Ä#-„‘|¶–{z:gÂTÜBÄ
+„¦ÓÕµÛú#a3|EÍ"«q[¢Áü/~÷i"žV1A´Ö@˜iñ}~ÑëÙô5Êuî[H
+ c|0Ý$ý‰­=¦ˆÄQ‚u,_Dqü“m§¾ÕéÏv½s5=ì‚*Q4í-v"ý³Ãp#RiÀ1&$I«œ^ÿê>eDÊC¶A,™ùçfQ°ï‘½9R8G 0äJ÷6¤WÍf™pÞÙؾÒÛŸŠFâà‰QÐÙ†8§k‹ÛçdU†Â³Æψ0fx3ë’`<¿<ýºl
+
+•±ý ÙF ¤·—õÈq5™ÙC¶ØF†!J²Ž‚0¿™§iH¢¢dxè’Ü$B‰Ùqï¬
+vü%ÉÂÒ#E£ìs ÿ6†`–á
+‡†³ð`œß@
+Îú@ÝC_Aý!_•2Ìüëv¶&Tœºá`òõMñG«|^ˆJZ¥0ÊáN÷!æDr÷9ž5·Ö’&³F“Â÷Ã+U}~ë cJN䟬ȟ¨‹C
+!Çeó>uä>†«jGé9æª=¸: Õâ¼ý轚`&&#üæT C‘Ìz„B2%i… †}×Ë·¶ç®BÕÿS^/É•ÛJ@W =h’ bÜzžjÿãw
+ÿ-%ìWöí1œ… ZD9
+âŸ×™3íîð›Gf“÷%‘sï<ªuGMfÚ®»â÷ؽ_L‹`¶$¹ÜéL¦ÓÕ²vß»È5`”‡0DóÒö*ùhR/ÁÍ(ùˆš-¶S¬‘)unE<hÕ‘;ݱêw’L‰+eœ›n½£¿‘î°o*Ìè–þ­Ÿúñ%0˜¿„Ý·e‚8¸i±6h©¯suËÊêÌŸŽwÈ MýP‚Âñ[†¤;ÒÇ"~nñ€ëýŸ.¿GÌP
+Û¸Öךjôéˆ;Ñ›ýIÏøŒðnìyé0^Öæûèæ½È{ÜaŒà< A•Û(2̤TS“çú8pš8ñßÔGL¼1<0GÜ Z‹©6Z×íù+¸±<èbº©`ÔeŒ? ö|¡ýÖ‡ȉ Cg›[a¢“ÏvCu1%qâœW‚‹ CͯŽ‰Y°§ãñ¥s+ HÜ(ú‹‰Ü6Þw –úÝ­g4ñ㹪p”ý{ŘLHóF\˜§x\å`%jlz»÷I°S+LIGùº%ñ\SéJh>ù¹kì ³£–¯ÓÑA‹>d¶nƒWb=Z)Ÿ1ïñ3ø¼ž$ðU€†ë)Ñp°ž½ãKf
+?¶žª±¡°C¯×yæL"]àÛÚ^Y‰3A½ó0îR6Þl>*0›|Æxÿ[Ñ„´ƒ˜k&"-ÕŠ#ùgtÃ<àï˜Ú©ß(SPľµLÒ¢6ô[®–"‡`¿ÉO§Ž„™roåÀXÌä>Žrò¹Çœ–$L¸‡ÃjnãÖ ƒ¹]Ë×Tõôà/©*À⼬q67{2ZàÅbÛâäS™OOÏ!¬’K奰S±lE[Ð^x£+Äs®5êBËù}ÙîãOÎôÏ8ú·µ®ŽÖM€qô‡"YUFt¤5%±Cg™¨¯³$™jMŒƒ€”„nA#=§íéUÒ•w#-`'±7×ôµ„ðÇM¾ •ÈÁSÑQ"â´˜G¤×ã³+hIãRÑú«ñæfkx@2gH×®Ëë5‹H¥Ñµ„þ£•«…™ ›Ÿ£„z¸#ÒÞ»¢À\
+V 8¬åÑœ˜«Ä˜×k >GÑÅì})SŽ¢´RðE{ûjí/ Õrðv{uš-Îyoak--ë[mü¿ç% ½=0ýÒœ~j³e²z¹¿wXE¡Dv ›¶|(E-Áh£¶zp%uˆÕøþ5*ÎOœ³2%+쩱jÀ[zÆ|ᔤM.Ézœ«AX—|æýU W]s@®a¬Â ‚°÷Þ)š^Ùˆ:/»+ᇠãÓ¶w1î¿é|{v¢jBÔ`Ï)e‚¯/ž{¹®±S*Õ†ôïûþ3ûñu¼‰lÉ7uª<g˜+Øî–^ž­Ì¶£•Ôõã)ê'YÀâcÜ·ÉnçS"ÝXªu#V–Øc{ðÛnÖú|°÷ Ã2ØéWœñXgÐ(Vuû×JºS‡y=Å}õ€ÇYT<þ¦Ýæ2"$·®—´FX¡çXe75Y4R_Îõ° oC`€òõÇŸ[SDÈ=ÚvXü½õçc>ÙЈ6_}ùPaÐ>ò"—z/<4ܱ,L–—ù'lÂæà
+ûÍ:“¦c4F’4Ê|ìê—Ö[ê€; óŠÝ#¿ÇCnßøØSžEÜÒ&©Ç‹f öÊœ<âP=7/Ê;Üó< ;z—Û‡5ëXn÷0³~¡˜gðÁ1tèêíN‚qšk1
+c«
+Rü=Skéé¹.ú•‡È¬3žÛÄ;sÙÆ-âª÷
+ì¢Ö=/=Bç·Gh|^¯7¹¶Òc0Û³*äÒ|\ö§î€ÂË@·’{7™5£ÆmÍ’º UžªÄ2Ó$ÄÏfß+ltüG=Ø€¿«`ʈRcÓ¦=b”Óu¤¢D3I<Žßæ>h¹FOÜó~6‚G"ÉåD;g²] "%g|Âé[­³y²HþWA+%3»½žÕK^{4œ9ʳUõÎ=Ps¹yM`ÉœZ/²Ò·l„qÊÈ0 ´÷%nˆª(Ù|'Ðcg¸Ï]gûó´‹Ç¸÷¹¤10Ô¿g°Z¦qOO›hò`φf]òg˜yvúZæé;#‡}Ÿe¾¸/À$êiQsÅ+]žŽ,¦NGµxïó©d<*í™BD¿ÎÜ1³'7?’'Ëx¿Zeã™36%àž$¡l_T ˜k5 øº\¦dÜws€K·7Wé7Õñä‘ñL”€bjÏAÛ á|f× r´!·ÞV—RÛ"À|£×Ÿ.4vñΦ¡ë@„m€Ïy-¾Í ±¿¯Ë¯cÕ¹x",tïKæ‹õ¼‚èX•óÙéÅ™ÃéþÒ‚†5’çb«R~(ùDçÿÄüÛÃü-ûoc(JòŸ§¨'½rç+lnGƒAÏ’ÙÒËá&êþâ3ÕBîû‡’O¾u4ÀC! ïÅ•Ïó
+CÁzHydæ®?•0 ¹¾áJK»×XíªŸŠ~¢¡!\ô~öéd˜¼3èöíÏ5aÇäÞn‘YÓ«ca]
+l²·£Qá°9¤{$š·õ›évàŠ´(m×
+Ž¸.%Wxðgî5yl‰*>ù‘Ï`ó÷±²’ éünI‘¿S°*Å ëÒ’òÅX#ˆöûµ¤néhüv%zÖãiÎ;—=T¬¿¥ŽQ8]ܺ›ñÞV¶_7s¡.Àk¯‡Æ¾pÑ*G‰Ííí¿Çû
+£¦2À¸¹¨EæƒaôñAð»%Þ–í±éJ>0fFž‘BBìl7Àã)[i
+¯¥ÀÏõ:‘>|%ýY’a‘8[y¬Ò¦Àh{™ëh³„Î]a,ºù!lÌ)|Ü
+âpiy^ZŒéG”`v‡»I,`Ÿe™žÎ&"¹»®û‡?C‚¼ûl7ßÁXº$Ó°dQ£ð=/ xJø½Ë[щ”lºÓHyçaô<«°"}Æ¥õh ß]g cF Ùñø\êÑ š/^!Ù'€\IÔç€òÏ¥`~®ùýSÍþ_ÊëäÆŽ °ò¡,r%™gÍQ^40'ÿ×ù‚ɺ^ñ¡Õ€h‰J’ÿ ܾέ’ÛX²²EØÞA¢ðž>úm<dŸ"û<£nô
+ÁO e»µ”G«bxñé0/äa\Zb•OÙâ¾äSgóv"k4‡HP±3õz ø»ÿëO\úO†¾*<sÖ ¡pRÂÿMAáÅšzøÞVçå;×{·üÛú/@½FÅŠ%þÌqW¸ìÌŽ­åøcPC}G ˜ÁóÍû#ÐK ~ýIRÎU>ª‹(z¹-c·*ú0ÔÛ™”I+K*ºèùJs«Ï¬çöIJ璄œÒ>öþjöˆËb @¶xiûýþ›¶Ñ's
+âÇ·ºÞEÞéßܾb~½ÁT­‹±Òc´³Ñ’»<ósêp¡¦iq¹!B×%•vû3Îv°§ÆóìÏî£J/¥uTgOÊ1ƒòëšï¤" G
+Mé¯r”ñ:Çw¬¼
+½ŠýÂlèK¬c€Ê]äϘ_o0]-øÅ9¦
+\´¯%´y.[F»T³lI7“ì{f-~ð¸§8ui3Û2¾C:kËæ{¨Ë‰»ÍÐ1X‹zñOjÙºÊl»‚£ŽøA³†_¡‹a¨úŒ–XÛa¬äyu›åû6h&3µçÓud L¤Ù¬ý
+ÝÓA¼4â*² 5u¿OBÊà&«ml½¹-Áøt“è¢ø²Å~_Co„3oRt‘uÝ¿"†þ*”Å'Ç6ù
+¥×Y~"c½ Q™x½#Ôp[ŠÔÎAë# {8ØtÒõv/fFw/aËGZâÞ Flûy{ îC9û±àé
+DIóó<Ê–(ÙŠ)ûwÂt&¥u72Š³&L&¬aL1 x´ ¼æf È쨮´rÍâˆ)åûÖÌå>ÉTAPïÚû5¤•:qù¹û¤%'d”ë6Ö
+ÖjëQzZü[kæx†y™âŸßJìNô2}íAº ;³å¿Þ64ï™W¤~1õéUrÅö²DøÌS¶4œ€bzÍ×\량Æ­GË
+WÞAÖ5Îœ¡ç®~䨋„Ù¯ÌÇô«Ï™<BTeŸ¾ 'oVöÜÎÙ•§×§OAŸK8‡|jÄòÚP ˆ^ÂÚ¹fƒ.i2nh@**ibƒ)Ä”ÄPø:ŽrÿÐÝÎa=TÊ6ªʘ‚vçòÌ3??‡|¢É{ÕE¦D"_ßêÔºÆZP“¾÷˜ŸUµo*=G1ÚqF‘ùe*íÝÄ;¼ŽVݯš:ŠCËkü^ˆù>¼ÌÈÅÉÄ!S«MÂY-,7ÜG’ùòºÀ
+²ñÝ ÷Í¿£ %-Wó'|ÒWØÔá5nÕ)ôqí]|šõ~T%í¨ªdÎê$ ‚pËçË&·I äª, ÑU á IÏw;×Ò¢Î*Ù¢q~ÜJ4ʧ?@ð®¹Æ¯4¶<DÉòŸü»í› –bÁã± LiÛ”TWÏû(…"{bå±>Sª–.ÝËÖ|‡Ñ½6nP1ÚàdóÆR¾8Ì9¤Æ˜™ƒ¹fJ' ­™;¦/‚ôßoëǾ•ê!M²9ï!âÂIªñŒK›b²©eÏ`Gr@Dû}ÄŒ»ûIÕIJ ògÒïÅë£ê¦9òsòWNòÿÔ7m^Êð3'Ò¯5ú’x˜4%ŸŽZ3. vlôÙ!ü¾•ÝqÄþ¬û«ÕÊÑK|Ó¶?ýäŠvŒà¼Ø² ûpmõ¨§|”Á¶Ò2Œq>Ôcݸ_è¼¼}·×|=âÛÊ8¸û!?Ö¿R‹íZq'¾Z'r RÁZ¾Êãw^]8ªÌÐA×÷ã1_¯ß±áß5|ú˜WË…»³ý6ÖJ‹²ëíyvn[käæÞ-Ñç¸8Jœf¿ÇÃOæ²?5’|®äݺ'-üvh!>iñ_ÈçÑëM0EÏDÏÚöÙ]#ßÒ<2”0}b<UiÔz÷ò}©=Š™ì%4“
+—äL¤c÷Ê$9‚°ýöD¯YÓc.Óñ-¾/:צ 4cc@,YDs¬ù‘ë¦Ëu_'ánÍÝ÷­5U©Äòº§\Ü!X5È6NŠ×g ’8¯¾-k´›ð©ú8j³ï‘óµ„'÷>#È5”÷¸à×úíÉ–§ÙÛb¡ÈP©Û­Ùzk•áÂJ‚ã~Ni¢t$楊÷Q_ØÆTXï=ëxl}w'œÅÕm³Îå äïó—»„$ûR
+ÈÀl×”$§˜SÌI–Iôü
+å6D´ Eùlp±¤>³Ó}në9•¯lƒì¶]±•«y—¯2rˆ–o^úmi
+I?#8ÏJ,Wo#xSã7_žý}ƒ•ì¡ùÉ8c…ƒeÉñ/j’¸xR®Žk_1gߥûÇ>eÓ¿zφ êP“¶åI÷ù˜.–4ôvg_Gó¶€à Çxkíq±[xèßa¹4Êù”ò‘M7¬D<‡9ù‰æò©>-é…i1¿mÊfcYI2¸¯òøÖÍ›"*Ëw.¼:{Üt¿86Rq„»÷Ç–¬0¿në0½¥ìcËsc¼RêÊõ³Üt?T³Nu LÊÙßm™ÀûÖ:sï÷“‰~¿Íþ•>‰~®}\ëGí_<`»ísIäYõcÝ[Oœíºw®:¼Ëv÷âÚÞ֓ í6G?WGÄ•ŽÇÖÕÚ´
+T¤¬ß_ÂÉèf eáþàé¸þa8E¿þPô0:ö°~!2Öâa¥½×…žÐT¬ö9§ú£¢=&Šo-¡¨š"¿¶ÅC]œbÝÿMQ-çaɹ3òkÙÌ·¢¿Òñ±nÕw«„$Ϫ…&ý7E5ìq„±ü¢H‰{{„õ2ž§DÎÑ[ÆŠz
+³Ü²‘—>ÏöEñèánxt–ñ·ëOÿâö͉uîG¾C¯(™}/…O°‡b!ñR‚&Ž,>=¦
+^6=üœ/Ù5”RÜǼ]°’^g=%ý”ÉÝûko.àaVDŸ~-ÜA6‹Û‹š¶NËÈùÅÔµ¬ûØЊƒ!3­‹’q’¡•›ËÍv¯¿³EC w™vn(ÉöÝwP‡^1
+ŠKRZ`úØ߈èÃ'˜–ÅÎ0w}ä)’!ú €åÎD.-íçLNîžgÄÀ´à`¨&òö8ÓòB¥*V¦Ðè93r?ý¬÷ Ít½Bu1Co…œû‹?³
+\’³‰€)ê>>f+Kßõ¾½Nj8yÇ4²ÍY™“÷®Íw ±Æû¥ûq-czçøãs¸Y–•Nù‰òÿÝ^Œ‹ª{¾ju@Ncî t¿6çÓ‹ý“§‹'oÞ?ÊC% jcaýš%RÜË+‹¢_Ë¢0L’0®3E@ e Šw>‚÷YäÊ,/i³®—µ=B~mPDKÑñµç1b,OPî}—}e¹ºûãšÏ,ûQÑ‚ÖE8ľi-œüõ‡+^–JÜË’3plj[§ (EtîÌBÂËÜëªÄˆ½>%, 7Úm"1ÊQî^‘[M d“8ºÚ¶{¢¬r²K²•×Qña(ª{íƒèÊ‚Þ Ü{GQ !8^}‹ãã"qÎ(±?º
+ë¢ß2Úß)2Z»J¾ŸcæsïÌ¢×áÞR5|ÝÃvå¼³^~–’D Úà‘íé±¼*°œÑ|ù–ðgšk6ÕM$dq4Ð@»­8§—I öð2¿5zÌ’`ä£CO8Õ~gYœá(3«#ÇIȶ< ÖÎ’‡øÎ|Ǩ‘¾wwÚ¹ çlw“Tv>tñV2vTø9a#ìûRmE<^á¶{Ä+KzçúÏîO +@sõRò#q*Ö%ã¨X}~‡vY@þ¾ÍÛ«jïf>»ÂdŸñ71´¯£âEB›àØ'ô% µ¤„];/»ã<—t<1iE„M /Ó3*=÷FLÙ˜Jß¾ÇA ‘ˆ  £Hæ3g d˜h{Ÿ{ãR2C9-à¸L¤ÝfüÅIyÎj·óuT¿üü.IeòŽ-´%½X–|§‡íÎb^n:m Fï(Ç(ñÕ{¸ o:þ¯2NjxU“·¾
+H‰Œ—Mr¤¹ DO ;è®
+?Û>ª·JíÒ£G=Gñ†ôV{4ÅiÙ¢sý–ÊÚ.ÛðV¨SÌ9„ox4!=¤Fta×I•˜nP„¤žëXáÍÝÚ˜£+ÌâÉ ^{”¬ Tr®w¤PaJ1.u”à(½»<Iþ‡[
+äU¡ôל¼ÚrÌÞúóìFú{æ½ë$@Æ…ªL?Ÿƒ3æ'k›µÆ´YNx‡ð*Ë0AFŽnj„?O¥¨ÇX\³ÜGh®Ø‰S›Mh
+ÁǺrçÐÞ‚ç< åî4féªØ‚Poo<kC”L>µVŸWñÿ4Î_qò—­AÆAõV+´_ë­´Ý1ÅÕ¹…¿ˆZÑÉGlV\A½4+ æ~Õ(… SlH&mM㯸&p¼`~A TÓ8µ".§!¾ 8^^ël=&([¬à,JnTЭãDç“nW~ƒ,òÿœˆMt·¼Ç©è .–» ,Ãy¹_ý[gPµ¤U‹s_îÕ3x}ž“(T§ i<µâ‘¾‘6Ìëêß->àh8ŸtrW©
+ÏCÔ¢¾~ª€}É>‘À(«‰ƒ@“™©`O†¹XBÜr.Ëâ3µ;$ƒ®£xFßž
+‚4Å
+HpcÆOún ¦z+çoâ¨åEÿ¤…Þ@º„f0ko¢þšÂM´ã¤©Q'‰=&¢Ÿéý¸j)´™Ò¢õ˜É ˆÄ¥0Cž7q~3åo ÿ=½yÕo ¯«æÒp/761d™Pëjë“eÄ&“‰¯»š[jÅ`ôj§ !¦¤z¸Ø‰ƒV4†îÐj´º’sFZz ˆ(jÁ˜ŸK±Ú‹ØtIõ d[¦oäg] úOÉÿ±CS¶{Ù—¦“*K ‹ý( 6©§µåd Ã%-'}øߪ •F£AÉ
+\H÷å©ô6 !ð?áÏ`ÅF,‘³À ¦DñZ†“’˜ø~Š`‹ä\eîÑ0¤ö\„Q¼!œç¡«éÌhû(òB‚¹;Í<öƒHfwµü¦fÛ°ýtÉb¤(z…|·¶ûb“ýÃà¼>o·‘wm‘9¯¯ÂöÃäæ¸ôI Úˆ7gxV+FEk
+y`Ö+õðœßO
+žZÙú™i­’‡Ë÷£Ìì?øÛ6lCèxÚkÛniýñNòFÝù ²G4‰“êˆ[ÍhÆ FVž8SÍÐK˜±f´ èpH‚ È\:ÊLiþf5Ы’YÉvâ±W×»ݱþ@˜©xt\k«&ýL f)Yat2,ûÉ26/ÖÆ6.ùÓ°UµJ='©U€h\G´ê]6³h<3ZF  È~®Tml `¶ ,bÐì!WW!ÅEŠ‹¤7-q‡ªÀ£û߇Ã7Ð×;y
+”‰j×!Ã}XeÂ*ß!´É¸¦}?ÞnJï•2E>/Gr8QvONã.ý Hƒ«SÆ1ºD—TŽ³#¹EN5Ø¢ž¶+∼Ý&èdüJtØG>Õ®êLµêx‘$t™¸ÇpÑKh§‡Z½‰ÖS³iÅ¡Œl'ˆ&Ô>Äâu‰Çg°C0ð¢8ËôKïRËI¦˜S´&ùõ¼€¾íM-‚l¸ÿa:&|Ïtp¶ˆ\©]sö’ApäM½‹œ@3í{ ºBè’"Ñç¥ý¥!
+$\·7ÅÒEÄ:¯þÒØwŒ(ÀãÏ«¿ƒ$@4?ÕoÜH‡‘n-|ŽFÌcEµj²&¤­°ËV…³£«Ï^'žR¹õl
+›ly ,ïX„ÀÄOD Âmf©Õf{–
+Ú˜Z%ÁLa+ª ǾŠêO³R@¬¶réíÎ>²û‰m”¹ÂT*übå‡Tzaˆöm×ø’30õ½~˜‡så6 ô¿·^¤…0pÈŽÄ/r‚xÊ' Ægk¶­Ÿ¨y"Ébí˜PÈöÄød0k9‹Ò7ȯ??ìó0<ì"lJmÛR $U2Þ?ÿºcäLJj¶c³¬¦‚ùLeÒ4À% &I‚dо˜²¶Sˆ3ÁQ² ¶¹J
+ˆV‘‰€9ã`K´<³ª¬“h(øEިР£•qƒ¦²ûE… ë ßv üA…&|û¤!¶q8¸G.höN×£®0üÕ-H?a4 Öp q§¨™S±í|³R€:Z‡= bE3GC
+î°bÑ'‚07ì"u÷•¾ %Èü<÷…Ž!“¼’õëãú¹XpyA.Þx¯? œJáF¹Ÿ>4÷yøÚdb½œQå¼båرm7jôci¹1sžÙ;©JîÊŸ:é1Øx^<$N”éÿy¥–z„“FUóTTöÉBÿÍxýäøQ
+¢©ƒuÛ’ð‰g,óüÎ؆œ_»n¹ŸŸ¿—ù*3e·¡ú¨7)Ajû•x°~¡7ÌI‰A ï&ÿ_©q˜7š˜m¡ÒŒêµ'–ýÿ]0¼Pý%6§óeµšA¼ÎYb\„ß]ƒŸÖ$5æ}ÿÊÛ!½&¬.ÑÄwu£¢—I\5¸ß’4Îvƒ•ÑÑõ £§„‘X{CµçFpŽ‘bßrTü^>bèÜñFâèŽHà®ä;u«dº|Ý0å¤óú¥Ä¯8ܯ٦9-z%?zæQþγ¼ËÔìнèH?*‚aq¼ú*ÓÇq2ñŒ8öìG!æÜ&1¬¶GAN‰U CÝ;,™bšŒðlc zSíWî¶`Õö®‰kçïm§6rìöîOžt0ü Þ꘭íÜæG²ü4ߦ–žÕ¸–Û›ºôíñý#åXâRrëzó ¶ÑˬMyÔG%¦¨í…!˜¬kbÉmŽ?n^ââŽÌÊœ¯G¡0)¼\óJºÕ5€º¦ÝG¹—Av’5HǾL)3?a!™Þ»ìØ›x›~B<µüàü–úàóž÷îƒ_üãq9+õ³b–&YjÌòگ⟜x½žŠRb âæç7 DÏÞOëÀl÷IZ9ÛY¼b6ó¾ÆÃãW:
+Jeë:íE·· Ä…ûQ‡%Åš5K3=îf·ôÕ%:oÙÏ*‘”m´Ø,ÖùXËW%’ÓôÜø\$Wêhˆ|ïÔör›=2Æ
+¯õñUŸÌÿ ì%®¹Å‹,³(NoMGIÓcð„û5¶¬v!«0HŒAŸzÁ$ rÏc”4Ìt¥‘öEZÐSܳŽ¢ór„¬ºú[wÆ<Û,a+2oï¼mr ²M#ÒÂiMkÄÄje™f‘eô ¿¾w̦Vñ”• E³Äég(šx>òIéù ^ë—/ø¤°¸.âI°Q9‚'gñ‹EŽ{Ž»Ÿ®¸k¯ès¶ŽÅùôø˜*Üp räx_úScÏlÉ&Âm™ÑF âœ\µ›<÷l›ÅÜYædcΔ°©¬¾³u{–à”ÈØìKGíÌÀµóyÍ“`”ª1¯€˜Ïd-r™*~ ÊX¶qâ‚%ýtöþˆ÷8`ͽ:Ñ,W{Ø›øhâZ“QÏ ædGΖ.K*½Â`8†üŽj"_w“æhgMÒÝy ê®äÇDPV‹?šAölÄ›s&U{ãöØ©2ïKË8“P2¡~›—ßð¬ö…·Eq¡eöºû”(5‡Ôö÷dø¡(%>hû(ç%{‚W’™x(é¶>%,g0åøâ;¶^E¼Ü·!‚¬4Áªê!ƒ°ïÿ~T&øŸË<Jú‚R.p}—Šp%(©¯Œ§Ö¡•YRÃAk½wùeœ”f³ô‰Ltåvè_îçÌ»v ¼Í2°£7gvíŒäOY3a_i±¼=‚ɤ¬ë–õ¼µÑ7Øæò>ŽbÔvìv$%Îû@ÿã¿o¥çÊ`çX“#׻䂿- Àøu$gÁ­¼Å?§Ñ±š ²±ue¾*Ô;-®dÔ_û¾–³ÞžC.%×Þ$ÚV¾(šô¦$DìPúŸo¿ýëÛòöû¿¿ýößoZ›´
+ikä\ìú÷xÈ(å³þ÷E¢Ä%M¤Ä(5‘ŠN [È"KBÐî"É´Wh!—
+iQ‡¿úI8˜.£6Š"ɸŒö]ã;Z„6“kç,a‡I몈ìåûÂÏZÆï^%9*â`Éãç}þ‹ï˜}=<*òõp›bs„¾_øåUEöª:
+$çz=5G…&'œçc‡ŸJ>LjžôR¤“‹`·ÁÕüÎËe¨$£Qñ¤°øü¨ëÔ}4ã=Žzmâ¥$Ûe}ëÛs‹ÁÈdâЯý‹Q}(¨xù§ï<çÓmž
+{¬š,šÿc\)ª”öŠUMÎ\XeÅ<‘³ñ¥†ÒÇÍî6ÅÔQâ_}“³m”ø*áYðRéþQ ¼x[ôvÍ¢}`u êìßÙLuÄŠ¥Ž’=Öô¸ˆÚ9Jˆï.%}(qÔÎ@Æ×D"zVzýŽ‘‘†Kœ• vÂÚ®½„Éll„ÏÆ™v¹7ŽþãÛS·Öv9‚žZ¹Œ"‡ ¹à€
+«vÀ>Ñõ-€©5B•ýqK•s="‰ vÙéQº&$Ôë³_zPÂCW7ß¿ƒ¡ãD…¸é‚¨Ÿ[þ¨¯’\¨4?=P_^ËP:¤à€Ëz’òåz(ÉQ1òäkK ]×/¾sÙA“"´ùn¼ qËðŽD,4ÐDµ2J¤½åÜó™ÚW㵆ò%x'š+†OEˆ™5Öc9ÆY‹]¯Ãð±v¤^(f %>¸ù=//sòBGâ”'ûãå,88ºl× •'Ê€û83 ËSÅ®cò†ž#hý¼Æ˹ˆ °7ÛCÅg3´Ã6¯gy*z˜øëe^óô¨Ï
+¶Îƒs@š^Åõn®ÖðkÐjrêBÐ r™!ƶ:Ì¿!tzgw
+ì“éêFmá—ûøIÞ©*mª%>äK‰ó±2—f³ŽÇ°Um4¤
+ÆjÆæ·!=52§¶gK.KúþëPtZwññ(;Õ xÿÜŠ.´pD×µhQ A·Ce‚
+€ZeÀ `e€U]qñT4!†«aÕLJŠiÈhÁï‘„Ük´áA˜QžË!Ž2¢Âî«øa_âËU>J i±•…*üú´s@.;›îœÃÑIÌ>´lòæŽÍùP²¾$ù%“Â$ãT„ ¿‰CÐKLú8^F%ÒÄÌ(EW˜Å-ùÔ•`¼ÑÌ÷l§K^&基u+A"§nÓ‘XižŒ€êúªÎŒ£v·wÿÔµ;ÜlH€s¬A\{Üß
+ ‘íÙigu)Y³ºŒüpÌuo—¹îßýQ÷5¦7Ø
+zUð;é÷ À‘™R“þPò2©÷ =¢RÇ8r>ø×(?êrt¨Õ¡èÏ©èÄ·Ï]‹>r'c<äí1Ø0w^šu²^xvðS×ÕOE]¹–¥â_„0ðD“ ü¢¡¸_ 
+OøïíT‚
+NlØK…ûS·¢†ï$@…–ue¦‚{'LfWS£TBaÌJè觷ž=œ1)ô4 ø§&üÚI¥3ì}Ϙwè`¦^màl@"}²6{¿äD*Ä €(:¦M-_ð}žq:e˜Áë
+:5o÷]p¹ì#ii•T™ƒh ØýED·bÓþ§–BìÂ?yóh?WœC<gçLº” …½¿¤“Q˜Ð:•(‘f¥Z\u0s)`Nq?^m†r¯ù<Õð©GÏYeïÆÂ7 µƒÊáå×°t)µ…ožŒZ±{~HíݨŒ¸ À8V-vwUé Ä=âšã(¢2Å°à̓g±†|åa—’…í¢ŒE===œ´Èz¨š˜|]¦(âÊÈŽ´¶ŠMÐ6ÒŸTŒ°ÚÆvG§¢%æ}_§)Ž Ls}IkÅz&˜ÅÕ9xGþ¿>”0[ 2eî/½Öh’L#êïÓ%^ÙEêðé¦ÔE# ¼š×ðd³Jd“Õ/‰Î¦Æ"¡'“¸-‡F@cJ<m=JLÍFVÛ KÑBgZ%Ú•Â6GümDŒÐªÂÏZ ±0&«‰Á@Ć³íµ­Ý£é|%ºê×
+im*„i%Ò#t;(F9á3³øÆÆ[¡Üà|ŸMI9¥®c&“§3À»y ôTäFd€JˆF Sº‘§êZDÚ5rÃXç Ã~cKv¬KfI ÿY ¢sØð
+(9‚ýS™îeæ$<A±Ï<iJÆ—6_5õšç*ÉiœÝ9j+x˜×üðéˆ:r?& ÇW¿ 66ÑcLÞ"|Á—ˆ0t?E‚‘•dAÛ·¶ Ü.­~a¥Mø
+“ºdW{wd7SŒ‘éÂÅ)´c Ž@a©¡:îò¾”:
+s7ãPô¹ŠpÐ.OØög"6¸! G xØcô(±²ÝïòM˜'µ°©ñÓ 4 GϱYÞÄ Âf”ƒ^uìÍ^J¦…Ä,àÉHÄb ò’9‘>lJíaš/%ëS¸á”Ó÷•/ç(ÜÀl9™ùö†9ÂlJ¬‹ôñÊ›hÊþ*ºP¥é­ì5mBë~zÄYCÍ Ï¸vôj1i ¾‚­À­Öy,¹XU™ñøû>˜é5 + «¹µcH›†~}=.Q%9Ga„š-d_Óì*as‰eAÈöØUP¦ÁÃa((|f‰ý—KŒ,’ƒ!„»„ÿxGA¸¡åˆ[:·±Ðd"‡<ÈÃ9°r41¯Õ½ºøJÐá!ÑJè×£ù›ä$|˜SšAçVo‡)[ÉðÈÏs LE+Ù (aÝ…«q4qºPËìÉ)ã ‡•@‡x‘®„]>ae~ Õ“?¶-rýXP—a9㪸“m˜å͘ŒC9ùk0Ö$K¥NîcÍRÌ
+Ìé.BÝ ¿ŽÈ> îÅBñaœLý}ì÷hPÞx_]†¶´ó)ƒ…9«æòW4”+|!1”Ô791iX3«£)~vÙñºð[‘>E ˜1l/ÃE×b¶c0—MAør—'ʸeR¼D S`v¼Dº+’UòþëTt™ùçCii…*Ë°ošmbó²3WŒŒ±)˜F8¹¯IÍÓ–ë‚Cà¶1±¬Þb¡(g9Ñmwè¹ÀÛ.ãA/ËŸú<:GÞŒ +ÁmeTѨz<èaÔ>ŒqÙwÁ°ùTK®üJ4ïÖåUýM,á
+Z÷"IlÑLZ0´nß’)ÀÕ± $C9÷û…ïb~{øÉÐ@ÒAPûâƒ)` ›ÖyCûØq[¬Fóq¶CZ7(D8¸T-.«ÃVTc0^5ãviƒ}ÍzÚ°Åa»³¨º÷}VÂã±™5ÿ>­?¡-Ä¡¦MõOýe‘ÿÓ, Û¼…º³!<!145a®{áç±Àlc_WÏ30xPÇ‚EAxÙLÅ›„¦ÓçÎÚ÷é7‡« |¯&'2d
+BüÃ~yö DÁÀûÛN‚Rp(HA?Ƀ¡pE)|Z]&‘±K-‰“Fõÿ'þëð3•´bÔ(+\<¶[àÈŠO,‡¨É¥2Í,0#rS?‚I½¢)ö©Ó†cÓKÎQðÖÄ0Œœ7<2,Áô#Ýß់x
+nÖ1c
+™·2Iß4Æ®ÀËÄÕ4#Ä›i¤„n0 IVó<£Wq±Œ÷’»côj.ä¶Q Hwz†Qoî%OÑÊߥºÆ;’o†Q›¹L-Ù ¾ÎÌoÜDM§­&µÝå&á:s_ MIÙµŒ/²&¾ê–‘=K¤ÒÀqy–÷xФ&OáZFJd "î Öñ`ïEw7èpŇEËèÖ¼[F±ô”˜PïžQ WÚ¾å‘|Ïh+7µæ<ÏÈ4ƒ`6éj ®ÙÓvóÀn˜Ùƒg¡4}s™ÛÃgw’Ã’çÅnŽ¤7Û^xž1˜;å?à0¦ëÙ1(p›¥ÁwËxßgAEâ_!JsÚwµŒULÐH¬y–Q¼}”ÂBs™ï[5ËqøêolQ6ú °†ƒŒïŒhïEw»ëDBÅ ÚR>.BH¢"o€Ë°¢ûqŸÑo >´1,W~¹Eég¨ªIŸ@D ÏbЬ²ö,2—1×b%²Ã³cá“MÎàw ­Ôà1ÕÔqèxÔÒ®}†jŸAr $œ-/Ú%,WUÔës• ³Ø^À¸YãR²Žšl1†²ŒÍýy‹´¡‰2$gÎ$T’Ä|ÐT±õè^ôæ˜W“•ÜüÎ-N~«
+‹I@P Ôuäöé0[E®„]1v’~‹§$êÉîw¦Ü/}n²ðÝ» ))í„R}> xÜ/–#ï5†
+œLUàœ¹E/ɃwLŠ«¤(¦õÌ·6p¼rYmýõÃ+º˜ê­MÔ³âÀŒ}\ È^€–I»I³$ᄄ†fJ
+Ž˜ ‚ûÙàê-’nD…q•D1’I[Í Q9bwÅ¥«…´‡^
+yÉó©âyₘ*Ã$ÏÌR‚M+–fj›gÍ’™LÖuZ ºItcšµŸÉâ6ðvÀ}q8Â\VpEû38‹ÿ1^.É‘ä8=AÝ¡O ãÿ³®Yö-z+Ý;ÏAR¦L"M¹)3•\Ap<Ç!Ù``’=†§€×BÅ€Ž¬u©:š„ÇF®
+MR³b*ßT«I~Ã"C¤åhþõ5p$7 âa=vÙhh ¦Œë±µ#Ëa¾AR†šôáÔ£3|-¥3¬EͺOÃ$ü&
+øªÕ¯Å@ŸI, þ1nw&6á0UàlÄéVê׊ÿ=ÄZ\s…¥º<
+Ð1‰Ô"/Óƒ­J rÆdüº˜3µ Ó#0 xÜGÝ…{牷%­ÃÁ—jÛÐÑ
+‘/ÎäÑ2¹¢âåx2+EH^ªŸ_î~¾ò‹Ê ¥ñ½äáÔýF(: v£T {v©…nç>ùf4nÅ|^ûjU-뻣öÚ°ÐZ“ÞÌö‡’-À â‡NsGõ¸g¬õ“#wœÏ\ñ:2EÑÒ_ö€Î­„áçGtÅVÏ1Þ±~a­FŪ5…§a¶d_dÔ¾ ,sÕ£@ÄiI¸ÑH5ÙqË(Á\fƒ‚…=wtÈ€s
+ê» NîVé¢\vüK³ue«®W¯Â@·^©Ô¦ˆi5˜E±Ñž3ù‹)ŸÄEÓ€ °2/½úO÷Ë`0bY
+gå)BâœN&#ÁºªU+²R!®óšŽDµˆëzØR½¼zë’ôY»vâq7¾NF/ž“ÄN5Õ¹gƒâX¹± J+Å­q¸‡åÌ©™Öê‹xrinê±—‘¶ ¾Ì×¢Ç/’)3ÓE‰ÌgÍYµS«†|œ–gMÐN_†ŸÞt)•`VÁÖZò3 
+Ê3ø°ñBSPMf€Žn'$”€=Ö¼æòY UÆ^¯¿tà¡F&OÓÉAòv°ø‰%b FƒiO"¿S£0>'>0£$ t/DÈá´Ø3b¼¬¤©gà†§ã˜Ñ$ANÈÛ‰¢Îª–„‰"R
+~ Ñ¤ê©Èá .5ZéùC€—ÓeÏWÍ(sfÌO üÉŒ
+úÞSd¡†£ò´°‹Bw)DV‰
+ji «NÑ…ý×WƒÞn=Ló`œ«+.‘Wp|•½@iø†“÷~f–ßW—É&º¿éIôù΄KO5|Û*õˆëQ“[kŠ®“ûò4W`‘†abTpPüèã‰(+U„÷…-zzÛLS}:4@œÎ.àÒRª$–T´‚Ö|Ö8UÖжçŽÉñ•ôx1IæÍU«¢ìš%soÚŒ¥h†f"üœ]A¾ÄB+ìª=¥ 3tM÷6Uv!a‡%Ôç’T|§Åi’'Yojƒ_äji¼x»‘öIì€qVäÏUáTA’Dp Úgqå OôЭëŠ{$¿cyýÞKST
+À¹åäaŠ¦eG’#&#F‘AZèÚ€"´BË}ï%®|ˆd1Úi’Z@vv«ÞŽ\/‹h8%RÜÇ(ªÑÍ÷Àœ¼o!ˆÑÛlþ¦䟨1ØQ——صÝ{
+¼7åv4}ÿ?ng#jM„L}MŸá
+ãÀžÂ³ÅOGto7Dt,Ï Ëz±Ñ F·Hk¹ó/ó*éÁ$Q¿eTJÞ,ÒÕl:j–9q…3LîwŠzÒnŠxb”ŒòÑÐÐ
+,F÷1H0æ•¶Ë çâ‡bœØ›KRH ØÂ’Äå=fÕþÖ€\ìŸÂ€ÖzôDÙr› E
+¥UNÄyŒ[žQ>§6µ^B,
+BîSíei,<ƒzÁäÛ>8ÙöªðüÔë9 –—>&Ý Am± ZøèPƤ):Vfj?E‰,Z æ½jܘkÄŸ²ïQ?vV}ŽÄB+Þ›½öz%)Õ‚+Q„õüZµGòÇ´¶%s$bjd¬ˆ,eÊw¡Ÿö)u‹“~–ͣƩé HVFmG¥dvˆ«\9q· {ô©Ãd¿Éûx¿ÉÆúÒ_fÐG5? ù&%<µâÏ£éÉz(q%«ræñ”*Šq~ :ôëòµÏ0üñÄüš5ô€¥Êà +݉] C Ñ.—±Ð]á˜Æ‰¢-#ä1ÈÃÍUÑSK!±2}8hF‹ŒÃ@Il%†`vÑŽÁŠ°-íWî}]ñeff 9Ñ]Xî˜;¶9Ø}©>S‹'ñ“vwL¦
+•÷ÍÀ€ ¶\1‰Ê èg’`I£ß7)$ 8´±u¡ZGç* KíÒPrÿùuþ˜.ÇÉ:±ÛÇ©€…ïc—x’°šAYÜ„šNo/rW¾eúéÆñ˜ò`cQžI_ý†Í‰IN7Y0&´ÙËO Ëôñ,Rf ¦Þèt ÄõsŸ€Þ9zš÷«¤Âö6ù!ÌRÚ•+ܧþŒñ“ìî¤nÐj¹ÆÍó";ÅÄD|öÔƒ®Ø™3£
+øÃkyÉ1%,(1}Û—ôû˜3Æ¢6…^;&m³œ‘(íÂ25jœ„w2߬8Ä”Ò}jX¡ Œ¶rwN‡N“l­€BÀ›¡`˜Ð!šÄ§T.Ot@’ñk—¤‰=€²wžEh$Ô} Êë* Y ~¡¤ÖÖ©f ;@*Í$ K<lñ¤’ÏÈÿ4Ä! ¦b`(¥'LÚiÔÅù§Õ rCŒJ‘R»êø a¢5;§¤XIuða
+ïlÊöŒFvñˆ9¤ó)9¥ ´^áõË>%?MÊ«Üb1£*ÖO¤#ÕU^ˆN²1–ØÏÓ¬ÇW˜öN¼øù„aNDÔi èÝs;'ÄÖ²}š’•7O È@Ý00F+oÛ}Iv@ÔûÖbgØò9!¢¢=q7§›sP³å;¦ð\'ÿŸèUŒHa3<Ä+äýZC)_4³ÌOA§–ñµÆ¤!i½Üƒ^®tȇz<!½k­l3Ÿò¡JÝ! ¡>Ä?k(i•<_Æ1 ªç‰¸Ñµ^¥y:…шš:¿/ñ0]×€ø÷´IýýÐüˆÒQ‘–Ø?7 1»
+«Ð Š\˜«á_WXW‰ï-;B™Œ+ÅɽõŠ\˜ßÉ~s„ ÃTxŽÁ®”!ìÐkè÷윎4hfÌÅz,HR¶yÆB0eJð}ª ®í*4»Ï›sf"ËC2<$û«PÍ”¢øŽ¤Hp 6¾µ[2t™cšãŠy[-n@è(R6èc¨ö-ÉjW*Eм­6©dZöŠa²\ `BqH—uV.SXüå•Ÿ³<@‚9÷xĤŒµL;'“ïÚ;GÜÌ ²aÊÔß‹¬ QOˆ÷é/”“×~<çÒòëm.£szÕû^‹sãK‰O—V}ÂÑ+½ÒC«'v‰K>œ÷ç„TÃâ®õ[ÄN)ƒ°ËVhf<sšÙEz̬P<Rï»ÐEч&RÎ]"Š<­¼Z˜“”ú˜W7TAX]Æs}©k߯RWÔA¼Í)ˆrŸr[j¸¡hü@„¶"ÍÈT¢ì $Q….שÎa¶[úØ‚XEVYªÖ<äVK› Œ1.…Ä—sIüƒÅ–!_&Kô}A =Wäë× ôÖôŸPSº'¹+3Ø鿃[„¥^”
+:FíëåÊèÌ\Ú%&r׈)ÌUßávTÖNÐáGÑ…šXÅ«U¾$G`a1’†ªÏÔI%_ >2LAMSšÇs˜*’
+’ ɵŸ¦Áua¦Qóy#SÔ4¶…|BKrñ‘–-)å!¾ò
+# *&ÚJYÈ%cí§Q’Dê“<×þ’öIÚå¦ôªx½ˆxÊØy®lÈÈò›”)o„§ÈþKÔÚ¾[% ´Å ]=Sn傈
+æ°L¶Y8îæ®k»íe©6m>\0߇NŸ‘¦>zÞ=^²¬_+Z=ØS6бÄÐr/r³-kH”Æ‘bÍâÔڵל©Uw²#ª{ÄA ‰§³îô´¤ ˜ ©Ì š¹Ó•Ö7¶ÈÛÜ
+ “C^U‰)õÖ” fÓ3Ž·!ýúu
+˼`ñx›ARa5˜
+÷!žE¸vU–ÀR¤è ‚4
+üŽü¹Þ@˜fÅp¦q3î £VvêFðBg®ª+±¤s‘{Håºt¤û›”…B×—Éð( o,OiL„^¬&‡¶>Eѵݢ»Íˇî‰qšäuŽ&Q#¡`$D­Ó†h"˜ÈëêÔ7øO[ÝRІ²MÝOF-Je‚8A Š­FQ”}¿V ‚IH둱°lƒ€H´S/ž¤CëõÊ‚ ;, µT?sdS‹ÁnË¡ò”Â-k7ÈC/ey®/½ƒˆ­D-t轟#£<$´B‹ÊÙµ‡6ƒ°†Ð<Ûmvº›ÂâŒûQE®6!Ì
+“ø
+Ošrq§Ô»¥¾3QŠ¶HÊh7ñN3;a”b71 5ÿ’äóQã’§SŠ9’d2r;´Ê0²).º½E)^wûŠ¿Ì<‚5†ñ¥7xŸ’ÀÓîp€H sͶÀe¾ÜZ˜,Œ¥h8€~„X‚&W;QàF™ÀÑÝ¿›6¹Fèm= qO$lâíâ&£–ÍŸÑÞ•HQSÞÄ5Cz™Ë©VÚ»±£ð'û&4â—wø%6`&:vnç ÂyG–WäšûÆ—cP—BŸþe¼\r#Éa zßÁ'(èÿY»—¾…·îûoç¥tOe2áÂ` ;:%‘Á`vý GÊfÓŠ¸E€ÚYÛ‰Îé˼acc2#}_'*±© ÕÖ÷Õ`R>ö £âuº“Qý0?Û%:™dzm®°½(]Á‘Kj5?ë Ä„¼Ü×؃ªÕ™'<ÍÛP © _ÇXÛ@ɤ†´-E4C ᓽ½òa¶ìÇg '£Ë«èa•g$Â_ e»>šy· ®ü1‹ ©ݬ“hŠ0§õqóL¼=ß\†ˆT>êí›`$áF [›Ê¶ÅKKsįÂä©Së¨+ˆB”_nsu½ Ã(ÖÂVÚp_…mgEf-Ôju*Ě̈́!«|ç
+c_[@Ùôê4ÝN ë¤sÇïœhs¹Ì•}Λ®,¶HÃ’¤XÓÙ›Òןø—Øo O:F/ÈB4ù®°n ¸Å
+`ŠW”¤©(ÒÁTЧ’ÍZr­¨¯ºw}¿r§O»z͈88‘¶½%ÄÁW RoWgQ±»XCdÏ–ö0^-Àš¨)Úˆx]†6u/AäÞ_“ÇŠŸC
+)cHD=9YEf
+6Q¼,/ ‘8¢@=Ø1Gö$‰2Bø"Í”×
+ ‘á‡û¥Çb쮢\’Yw _Æ ­¤QFµývýKŒ!Ž‚Üzäî1åʦM<욡ȦÇò“5Nñ)=jC<‰ü«zdBøFãµí3Ÿ<šã{†j‰îÉK½ûT7ËÈ»|xóàµ<ÒÚ[0 !õWAh‡¶[` îm ëN ïWfÔFùýÏSó™‰lDÑq0ä)ýý5Pµ€I^Vë0èø¬ÊbñH„¥CWgQðÙ-QøÃ÷¡²jÍ2O©=·ÝýFs•×Ü–î„ü±jȤ‚ÁáépgùHS9q—)Ç&ŽW7¬EÙÌ}Þ€0… g+·@د
+\Ð<_áÆ-ÅÐب'¬WÂ…ˆ,¡XÚN+1a ÓÜ÷a´(­lû>…MËz`^븑¿_dÔbA!ÊHÜ*SšbÛ#¡Q Q©¦¶UÉmÛ╸QF^MPHV‰ÁAÛÏ.MhšAôÈCñ\Öÿ!_vRÂ3Ó
+¶Ë¼ùL¨2}Ü1þ7…Á(KáM…
+sÛ¼ÊgìdㇵŠ¯˜«=„¬±Û¦/bœ0ýNê3ù¯Ü‚N7:;¨o«|Ji@×-sç”$gURê(®uú°F0=N Z}õfSòecœ(´Ÿ3ûR8!`EÔZìqÝäÌ- £¡‹G—±Oú…€fKfnY!œÀC““rÿÞ€˜vn0«Æ¬ÜÃäâÙZëNÉ!ˆ69@x3K8æ‚`~Φµk“=*«æû) 2n£OûÁ wÃkRØÏ—o¦:2ª#‰c•GJ2ˆŽ’mIPLM-7ŸQ2AvÙï3º—!À°\àéÆÍ£p?2ÄœÃ-ŽBN*Zwí' œJìAžZµº€ÐXÛØØ’öîÝÆv‹†‡î£Î¯"7@ÆŒ”Úû>ê\.o̼¤ØñïN‰YtšV{ušn§NEŠsÇ/ß¹òær™+ÿœG]yLq`=£„Á™éÝŸ†®eÊq&ýòÔªcøX÷
+Ñg¸K?ÞÃ÷<©) Hã¨ñe3ƒ×ã^tÁ¯3È4&wå×)Åîizð¯Ðo< Ó‰ßög‡i®J^:PEÕamh»t©ÒÈ(™æŠˆØ#:á³ÌêGÏé!j‚æƒa_Z ÄõˆY—cä`á^SD,¥d‚9ÛLo†×³.—ཇç|õãÍ]—·ÁÊ@EºF|´+ë–Y(Ö°+ˆkOŒãB¬«<­^SÁ8´-¾=×XÌ9ä[TYˆq¤9–ó® [R Jù_RaqC„Àø¹
+™Š|´5o~i¢ì<ò´Õ•_ì ¦˜X v§PÝ„WËkA3*Ô1ãîd”\bÃZda?Þ<ŒL†6Pm뼺páª3‹ùPD!áïf\·a)mDVÉtöäzø‰Ò×=I0ZÈb&ÇtoÅ]]”PŒ6ÿŒ)ó¾RØ,î+u ‡ÛÀ V9ÑZ«A0kÄÔέž,éÊÝôf'Uf Š#—š^õY2ZÓÎË"÷,ŽCBxä\'±ž%ªTjn5¨d©³Gý ÂvÊS E™Ù¨_EãEŽ)jÉ@îMŠ+†á’‚¡$}kØŒ—Ar! DO;ø.ÃÖÙæÙÚ÷ßæ50Uùƒ¦ü³I*n3 u·Zg–¯~Æ
+„—¢4%‰é•T›l…ÚÒ]ÖLtM虇îpûÇ•÷‘"g2wÓe0œ‹\O¤“å“<®rf®Šñiÿ óSÄB 5ÅÎéîJq<ú^…_`:Ķiƒ¸:s‰d©·ÔOY¢Ÿ´`g¬¨üµ@ØÖB¡}z%$ ¿jº¯Wiû\Zvzc *Œ<È/¸…]¼h>,ŠPqÕïÿ•jš;ÖÒ˜|.~OFT–Yžë:¹:çÒ°ãw˜Ÿ}T– G>ù1ŽÂªå2ï¬Ýv1Xe·€#ÿÍ&šÚ¥?ÊŒ ’^Q…á †zá)¦"¡Èè†*{”‡Õ ¼Œo› ¹E‡
+±âg̘7Ì–—A Rt×µó•(/›,<ÓH2C>Ì€ªÅ.¥í1ŠDAîAˆ%)^Εj˜Õo.ÒÁäá)t?¬Úá˜LQp­*¿ûúÙ{—Á,aÈÒL:[\"GbJf2ÚÅåå÷¼¼ƒ¢†³RòÒ™=²b±Ó?Ï&yDÿ„Ê»¾Þ‘çHÕv’dœu‹ÿaÙœgub7v¡øPñÚº®žÔJ“üxDo‰•°øíŸ{„iŠ­M*â…£;Ȉ®Â˜<˜Q HU"&¹|>»ä-pö©°†L¦°z¹áß ;tDlìÀR¾‚%âÅ÷øåžê8ç¬1d¬%é‚0$YéNô0!Ú)4¼h›ù)îF¿È›=œÓ«ª¥åµÁ¸Z!郱ù<ôBÚYeŽŠÔˆki•°+ÀB|}V r=äׯF¼Ž…‚²¯W½@æÓ97Ë–áø"+©Ì—V¯OAgæ6±§i©02VÇ70Ô²ªÌxôñiΟbà’x`RE[«[ÜÔÀ)ÅÆ9ŒÒ®6(_.bö‚6øÓBȦ¿ ˆðLnªYeû“(6L Áýcon¶ªëš£Ð†‘CùƒâNä>$´’!úý
+H‰Œ—A®9DOà;Ô&!Q¤(®=KßÂÀ¬ìûoçQR¹áLúwv9RÉ`0è¥Öúú–qE©]£« ­¯ߪԫºy‘QšÉ8€~MP´0þ\,
+$u¯‡p´ŸêyC,Þ ¸)èž9`&³M+¦ËÛ0ÖS…'A““eÉ{†D´B[ÖÖeÞ”DïÌP$v´-qƒöå$¼ZáÖ-@Hd#Æ°m¯Sו+Õ6kBÁW1í{ÃüZå¢5̱ue)QÖVTˆã@º•² «ˆ“Ù¡.'EÊr£6éxxû“➥¤–s^gäüq8òºÎ©Œs/ZJ— Ä^ðê86ç²hƒªpó ííÃ1š²¯='ËÛ~ c€”Š!ÇaiœÆxsxÀi½È¾)Aèdq?'».Yà9û‡óœÄËî”+‡0ƒï¤…‚®#!Ög1ŸÚÚ`H“1‹y¤B¶ê”Üm^Eë0ºrºÄvÌÌz0°z5 ì Wƒ Ü:œ÷P\zöñ«dyvLÈkfX§—‡Oëu/ÁsÒýëÄüžƒõõßo5ËG~QŒå¨‡‚þž ™1^gòdO3 5ƒkLÈ_Í„¹€ô9zvÕ)&ÅÌ£ LÇe`ô]tl·i¾acŒ¥n@WßUçj´ ´fmA4‡³uo÷§‘øˆÈ¬ñZr,Òv v9n @Ê?tÒØ–j£ÑXyœŒ×}]v0°×Dð4,5ú&;te>Ôô£T5Å¡Â6UKÞÙiÜ‚àY:Ó“_‚×­ïB(ù¥Üªügž“»ˆŽJ
+ßWÝjõ¯5Oz”MÔs¢'³³ø÷,ZhÇ%¡éàN{ ú¡têæ>
+ÕXJv ÎrÛð×جá%•£¦‡d‘ ýÐÆß›+ƒÛU ’Se¥¿“L¹<5?…Ÿlgå ¡rðu3š4!O4S+pr—ø8 æ[­;ð¥³)KQÔ¥sÕÊ1
+ÿ×ÙoèŠàs°žÆuŠ,>jDùÇ9HÒ7c6!Ì™)¡ñv …HËćSêJºÙnéöý=µÌÓ§öäï<&'Í…>ôwcq¶“Bƺ)s™|›lÕjõ;¨Ò²p«uˆ…)ùqÊðWAsÄØ¡bÓ’14W*ãË—†1‚`õÀpµç¨H©dO@!h‘öaT̶ÃÐøú6¸O
+òÉÌJ!å%ý8*¦~hŽ¦Í{ ý ²8‘‹@¦‚iwš'“6J<²ä†`’r©Èi¶nLÅðÔ?ËU0»¤]M
+X‡¯²4{þIeµ„Gì5c–œ,aà|$•wrŠä@·(2NüË+¿Qtñ+x,'’úÝ:Î
+§P,mWɽ­Ž·p9ܪ©•}¿¥M?Imì¸÷ü»ŒÎŒœ y(;¯ô}´ŽgJ¦Úž@dQ)Â0gÝûÅp
+ܧ”OÙ‘¡Þr “arü„üU«uÕé¦bÆûëôÇ1ál®yǨ¡Ä“`ésðì«îÙ„s‰Üeb¬Þs샛ï2l‰c­nuÕ½æ‡sîÌ9¼æÎÀcTw&“<~Q% ò¹Ü’5X &ÝÈ_µZíwj
+ÎrŠëÛì<@¹}¥XKåa6w¿ˆÝ4%ÇÊÐÕ8c7ýOè‚èè£&5Ô}Bjªkn;5ˆL!ªð+©!k”<Ž1Ö¦´H8¦ö>†ÄŒœk2Ç‘‘0\³E«sDçd¢'¨]v+nƒ'¬À¹kÒ§ ‘ÖˆL ðÔ4/‹Šç-ÍèLÝšÜñŽÅ_g½h
+¼Tø²¨QssÀŽ~ÿpžk2•¸¯b!‚—)Ä›…L 㘹T,ˆçÐdùd>·³b$¨A¤ô­<Ùø ´fŸƒâ×Æà‚Ÿ ¹4ÔôRÌ‚™åèÎÁ#½î ö»Æ&ÂÖš²ÐÖ°¼¹šß@šZ’ oŸ ÝÒ×ö4_,‚{¢¦ÏðsÌOHË78Q“½5ä0ˆÆfÄEÌÓŸóª<  _ÚÛÀ4”T[ZŸç¤a*2ñýìZ¨4Ï"dU‘O®E/Kb¦9çúã9
+]S~ÅÛ²„0ðé¢Y& ã¡$‡·ãƒá®yLŸE{bðSƒ¯õ\~}
+ÿÜ¡þåÿŒ×KŽØ¶Эx†DŠ”4Î4»ÈÔoÿÓw.Eén6œw5)VÕýe¿¼ãXb—σ<»X§[»Q)¿Û=”`³é^uÁÜ»aœ6ÔË
+4Š~v£?ódèIP±-¯õŽ>¶ðº~nÒ±‡…°Õuú|ãEÑyÙ•s8>á®øš~MÓÌÈH³G±«õÇjÿ€VW6óʪ>Wýi“_—u‡mMç
+Äqè2Ŭ‹Ð±¸”&P%öâá8§©?w2¢D£”À²·\gô”1ŽJ£ƒèsn}ئ¦-14“74a
+-å*¿dÀ=‚Ñêõª)Âb<iKΑ%¸&ùì(÷jOÿÃ*ÿõÊNåkmg}ãÉcá~ÿ7öãNö`wüø\D£”Hl[fÜö7a:â™ïýYÅ®7Ћ³Unµ8Ë?së-¦!žg=ß­?™T`ýhH
+~<Æ*öÝßÔWà®<;Ie8¶ øYlËékæ»;;I[ñóÜÕšä7Þ½Ï&£ôŸY 1ç óü/­Ø_ùÚýðZ–%IdüEÇ>W-Š*Á¹¯mà.ç„}M­&t” À“cIâ`SÒÃEd“®ë±òm»²ˆ÷DàÞ]c…û[Óî8kÌ—U½]C;Êô!SCdí!KA2ñ+­´EÉwôô¡èïoŠ0ã`Ží =}-Š36(™ÒÓM+œšÈ™Å~å¸Ç;sçdRÀr
+cÔ¬ÝYýzJÐã4aÖ¼œIÂìG¶ï|ÝSlv³Þ¦
+5Ê»ûO<w*:_ÏÉ9.^
+lÐc¿¡wQSyÿÓÿ; ©(Ý EyP%9™'OC®pE.^î¡ŸŸ f7úoÕKÑø\à¹*7Ûxï&ß f2õ~Tò­7Õ²=MF™Y®HÉõp='!ϱy¶ œDã'm‰ÇCöÍ8¿”Œ/Ak¬?¬NŸãàšÍßž/™¥HVбf­k½¿þßÖ´rct2e&†»×¡j˜áW—w|q—[þÈôüNf™U¼xÔ_œìúÿÿã
+!P±³Ó¢šÓ鱕÷6%B¤riµÜ%4—A¢Kí’-ßzuøvßvbÐŒ}ìÍ®!À_V¤ði·C°9BÝDNI6ȱ¾÷9–5Pö>†A‰ÄþmVâS…7ÙcÑ´ÅÏÎ)?CM›Æ’gÿ¾ P چў”Rïwí•ÀðÙ›·šX² /vxkãSÌ÷‹³î#ˆÓ?JRŸ
+Å:ên¼Ô}LI¶4èë4y÷kÉhñkÿ&ç¼N!—‰!¶l%æi2ÍÈ´¿?ÉøCðÏ *"Ô\Â%çõÎ+¶(,õ:| zË7%ayF Á·ýþÔ
+bfåR’ƒ<[wW
+(­ýPz¯Œ ½…Èïî1ëˆAT …(¢@p¬÷9ÎŒ#¨q³’ j¡þyÁYF:1Üø LŠ>fEù‹Q£>ËØ™!5Ê_êc…m¯i›Òé—¥ílnÌÉÓœx&RXÐëåhaËŽÏP×R¦ý-7WôŒ*¼AkÖa„•<Ü“mV#ÝGøéKÐ!]ÑæíDÖz/Gl}¹èMCõ3Î|›øå% Œ¥Ð ÙLM·]ma Ô23æ¡}“®mÜv®Í“›“<.Þ8Æ#/IË›w=*”ÕåC$ù­¶Ý´ëroÂ>,œ¹Tº­$þzmúIa§E‰¸õ(å¶BŸ9á2 ž˜Å ‘b¿U ùñM¯†%ŠíˆcR¢{gë³·9¥tµ7<…@RR¹?ÃÓ½OÕ<dê`‰ãºÏ¬èßêúñ7üéO+–9Àioúw–üóMQ =°×T•ØT.u‡òzy$€ð1m8”˜Ž\ÂZ‘õ[Bí]`ç­¢Î8mÛKÃmCk6Óv5"¶0yÈSGÃúo±qh*%Æ`ØHtÎI‰OuÃ^°xììœÎu#8Â/±ŽÍ‰M³:^‘õYG‰‚†
+gÇñî*ý˜Õ¼ä…oŠ¬F\5›¶Ô| î"4ÜÞºÞ¼<¶ñ=®Ñ£tyïƒÛkWIôÛ@©KØÐû"èãþÂÌ\W >ö̳¹FÁõ[¸d&š¼¯2ìaŸ¯H2Qòƒ5&H˜œJÉûÈßnóÉ«Þ!øÖ _{<-ù2«þfk~ßv¸̺%„/Ã÷rÞŸoŠÖ˜+¢Ö‡q¬‰`ø‚­ØÇCx>Y¢y*v²²Ez}– +^7?Ó ÚZn^\œ¨ùM·¯y´ûÍ*Nh|6ùW1PCö3¿*­Næj‘–„¾>ZÛžHA8S’fÖ¸òaF¯%ï0v-¾r¬1v€ f Öân /-‘µžŒ«„ÝÖǤžv9XL¯ØÄ—ß(á¹³¶Ë~=IIò"a””Œ=~+zûÇ7E­‘Z{ÀXç[i2G¬õ˜%;//GnÖÃõw?Ρ`RD?3ÔšnÔÆsü i•­öY™2åk®ˆc×x+ñozŽå[פ)nýè“<x²ÄÍð)ay ÷²Ç ¬×—ˆ³Í‡‰4þnËcè¶ád»Â†@*œxçYD¡ƒklû~•¼®N®L…Ž(ŸúïÅÌ+ƒ-!ÇX›ÆÙ¾ÿä<A6ŽK£¦‚;)ZBèhÖFÊïÙç^‹>þæNãê B= äïŸ=F!6»é·©ýI  ‡ÙŒóñ˜_Hã#Eµf½ZTzŸqFŒ]œ,þõ7}²î<[ßd’¥Ä:å ÚÚ}{e˜œ[U,Z^Þûíü™ö°MmW T?.}]î¹nùYf G6yRô>0kK¤ <—šY­iµCîéK2DÚ÷V]ªMõÛ4‡%¶`G‘ïÜæ|¾­':O‰m‘ÿánšãƒÏÚ÷«%œmùyÃçùk(69§sP2–‰«Å&)2“¯Üw/û¤äŸ`BøsNK_gçX§f·…a¶[äÅ&Ÿv» ²,q¬ö÷Žï£ ëõ¥röL Yz"âÁ °ÅÊ11; šBëÞŸˆ¸W€x{%qe8˜Â<Aó‹;øõcRô>òÙÞ¬ta9Ž¿-z]¾¿XЬqë?»,´• ë-(Q†~ ¿³Ùãv
+á®Ïšg¹cu‘vdŽçš{Æ0}x <éêÔ
+4%í“dp™Ä9!Ÿ-ç’Æÿo’¥gÐG"Jà"«Í "¡„ô¾'Ìä{˜i8 ŠDÉ/…ïz £ÍÅAc©!âv@,$“€akbS5ÊQm·)¦‰!*`þâm ä,% æi!Â!ç ]Ûâ'’OÖ´ZöË )-g`Äœ/Jd8»"ߊþ÷ô|§µ/'¥2õü
+¶ä}²†« Nt]ÿ ¨c/˜©J0±ž€Ò õ‘˜Œ€1NÑLÀÖ7„Z£Ò?Óð©òfV6‚d9agW6–[ ~rGxìÖÍVXl‘ø“PÃÚªDdS²Ñ†ÐsL.7ó„Lº8MmÓš¿êX/ÍÍèˆyñ#£Ø§-UÒYI8ŠÒ)ì»ê·JE;™¬™r
+ô>Š"hóæQ„,˜ù”E9œ0‘“àæ ø„¹æ08ÖSâK©Õˆîl>ÞFˆ%€Ü¤T–yñì‰ÉÏ»™ƒ
+9‚®ÿ AN—õ¡#¤ˆï‚HÏû\õujdl+*Ç´ˆX³ŸªK Çn{}(L Y½ž£ObÂt¹nÇxRô&‘ѸìZg ü;û@y (¢üEÔõ do‹ÊµXZ>iPᆬÉyŽ\4C×kÒr¤Š-ôyœ;é3ÉáÜ£lÊ2Uã/ƒpj#ý“V-) P7Á•HÇ·³Ð„,*ÑÇ8ˆ{À:;§¨QLäh"´ùç·
+z ^ó¾ƒpqÌ›x¦§æ¯šh½ª¶/%îb–2_Ìê®ß€Eñ˜µlÃ?$£°×©pB³¦ÐJ=ªNñм^½•"9|†
+døÆŸÓ[–Ê#]é˜>™Ì€t|CXN ¹¯~ó$wÌÕ‹>CÐô|G(U¡ÐO,“8ç B$Æ¥Œ“öyËÄ&"Ÿ‚lvÕãrVó¹w‚@ðtø¡z$ž4“f–…-^â.
+àêkä#ð.d]Ë·  i\Á\üxgx>÷Öðë˜ûÚñ=’ÕŸæ¾#2F…ÙÇxäXTT€ª ‚ãFìï!Îy,Î:^:Р8câØ°mfZ˜2&ö®ÏsÿÜE *ÅïßE¡ÞeÄ씚"RÔ1T|A¬âÝeÏ—Åbpó΢n„ÞÄ‘mz8“O ÄyMO®wcH'œùô‹ßA7˘;¬Wö—±IèûÀמ3´®IkÙʾ8Ä3Y€q²b“ §‰Ý83†%f]±Õòn'¡[%suj|éµãj¦ŒkW>²òãÁq‹Ð&þç‰gS$ÝWÇÁéN¶å‚Õ¸–V¥è$¸
+©fg—°VäÖp$Œ8x:%x\ ·©‡§ï-”ê2mÍ®`h×@P9ü¬=IŠ(‹Wæwlžü>ŠºõÔ{ÅAŽ‚ ï¹ÂSx#~*˜Úu]à7Ðëb%P …ßæERÚ NÅÓõî_‚ÏQÎ\öv“€à
+›Ì³`Qkï´È¦©)f¬cÑi\'‘£HiCR~)9»5?|ÌØ8÷s´‘ÐL 9Öë6ëâàåƒQ`E#`”ìïfbc‚F$ñF
+"îûéU—¬dyžxŒyA~dÚ!Yþä[’+X{i½kDdÏï4écÒi¼¨Œ–“2cŠ½mK‹YíK$MÝ,I+s†ù7(âfi¾É'uµª~˜ß©d)Ì`‘¹½›RX+ƒdC”,Œzã>ËO©²X2øÔ¼ EµÊ¸Ñ––ü>©ÏÆZáÃF¶s
+‹ˆƒWæª~í^±ÆZž½DeqQQè²UŽC%¼ª —Qô<Ç®o: ¥’|TB¸špR€Å V.–ÑR…UÕÌ©ÉôZµ™V4äY¼8`ªºøCÓãôÅñÙ*ÐMÄRë"Õ?Jô%Òˆ<|)ï“sÀèÆDLÞÂËÀY[^ž7Ö,÷ú(9ØŠ?K^>êÐ!ñmú^ÃG%Lê|ê^´Ä謼¶ÑmÊбÓB²êõU ‰n
+B 7ðµ;ÍÈ€„"€ÏGÔãfWÖðH.-œÕKÉùTÂö¢’iñÜðñÞ¢yÈè’x<§„aåâGÒ¨B5ûpü½Â˜æLÌ%¿ZF:H¿/ÃRªdm·ßå‹úi«—Ùô‚ý.D¶œÁ¤w5ɈœÕ+
+“Û<q9QÑ“"à„Dó4À4sP¤’Zri¹ˆü‚Å,Î@>­„Ö¶oΨ`‰¥—3uâ.«‰Ðt˜"¥Z
+íV;†
+ ÂV¬eVû:´±¹Ò€Sê—ãšØ9|cj6'ÂLlò19„ºµp\q¦Íà¦| 4•Äûv;§qAÅÑ Ú«¿©ˆ•U‡VZ‰zÀ«±ªîÛØ+_ì°ÏÆñK¸[Á®[´“uÃò éX–rÐ*˜|Ó,ô±‡c•ãiê KØm±s¤¨Å¿ôZE ¬°Á=Ëλɾ*NW$ÛZ:ÓÇÈ[ \*u!Ðì‹Ñ2­šøÉ–>E³Äþlœ`|RFF *
+ByÅ-Å™-L"ø1ûŠF¢5Ÿ'÷Òˆ} Ê°pMd@ã5n½ªAt;ºÍëÓšÅ;™Q©•ã,b ƒ†/hÞO:‚&ì7æjlU×x;Ñòv­¸¾JqF½ÞHf 0ü”3IˆíçüÂĪ€@†0ÆfŒ8§jSà+³Ä†á7xì6¶}tâ9¸ëÝOºÆØZÀ ÑnL Ù¥·K—ü$láµòg> ^˜E˜EûkÐLXj–¡m?¨êméÞ~Òf5&Ó×Wi×ÏL5{.’¼ßeZ“x9•ùx ªßôK&——Ú°?¬¥&m­~-0KˆSË8WåkŸDPà×–^–K·ðZÙÒj?³ðn0fYrNYá6^=êJ²xíÁU\GÚæ™_TcFVQ¸D{
+coûUn&›Xú”?G}€*¼ŒNÀ
+Ékc^’ù…`ªCˆ
+–Øf‡È£S‹F»šCø;Or3à¯Bq)9ËPâ+Må¤\
+´qTw'“ðíËAÌ€¬j¥…®¼"}fgÉy:jžšs·^ÁÈTé5šG`§$³»ƒ8•±€¦Òt…n#
+ÅK¶ÛÙÙ]|]
+ñ]ã%àfÿ
+¤@
+Èbñiï ³æêå}¨M‹“¨¿tWUö†K»QŠ‡'aÙÐøÊÆ…£ãIKg[ѦMûq¶‰yÀ¤²º;üZ™‹hrñmj #â¾Ö1ÃÁÂÁÍîˆá3Ñ —á5h\G.WŽ£fîx|«­øŽ &åÚ´Ôé{†Jo4lÆmeeᪿ*ŸÊjw %é yšÁÁz¸ÖÂŒ­Öeü(§é
+TŽäRÑÓ:ŽŽQùø!á7žFïñ¬ 5ÎQUiI“5 O,å—U¥1"áÝŽ…R¯%_· Âi¡ Ðý?œUp  NÉåÇ?5õß+¨›*ˆ]T7S…F`ùè³
+o¬XíçÝ/©Â µ²Í>O
+z8`˜
+2í„x"¸Uñ?6ß]þ.(×<”=•:`õ9ƒÀ‹Y–Cö4²Ê¡
+IäÇòNw/oseÓA-•Ý&µ*ŸÊ[ëvH¡­U7ˆe”¿ðes\?“E˜™ËB$=nÌO*Ô] õm9úÜfiöÀçòhü³Ÿ”¿ØAFî5Á8L*%‡8í;=K’°aõ|/Âß
+u$,­éÕш🬵±Û]A¢lWÕä›ûùãz˜»õûP!¼&EÃ2eLÔ´Z$Å4*l1ÙÙ-¯©þ(¬mÍÐIpß@¿® OÙ´T£LЃ-@Øz´§ÌžÚ•°5[^å=ˆ£còñûO!—“öréwH3ýA—×÷G 
+ aFˆ˜Ùf=úN!‹ÑïÛÈT4íFþ8O¯úf)ë>—z&i‚6ý{Ðup{5¹Í~©</&Q¸9åMUãÌjY )r±ö¿ÝüñÃ
+£vFTk¥\Þ,Ó4JÂ^ fWu!íCÃÀq ïr^ßJYà-ŸáKH­rœ›ÔÎË”}F˳Î'LL½èÈPÉôÙïÑP4ÊÄå5 ϼF3”a/tŸÂfÜÿŽÎ³­¡€PFÇáø´ +¯°Àje”úå-dÒk<)P²Ÿ1¨`Йɤž›£¸å}ÈŠ§cM†ží;QUœŒÿIjôC‘,­Î‰‘ò:‡aòÒdȱ#–=éÙuõ7½ø²[RÆ%üm¦;)t”Í gáìšöFÞ—ߊN¤,xÌÕó Ò^ø/>nëP›¬Hòc+ðmËÉ»÷ݦ/иZ+¯Þ ÏMõº
+EFbÖBðÖõJ Q `©¡¯.â;U¦8’Å<uÈìC|:/ìRFQTJaŽIØh Ñ\³²L®@¼éœ%ëÁ5×ý¸™ƒÈ¶¦ÅÔÙº¯"‘ƒ—˜Mg¾-_lœé¯žœ<c­ŒŠb1`ê÷qG!èŒ „úâufRg[´qÀ÷yô’ ?ïDá_úÖ<ZõLúz9üÉ‹,R¿Þ\üI¥c#4òâ…Ò!Ú>%ÁVŸ¾Nã™òR®—¦vL\ß„@x…vä43Ÿ­þL‚üõBû¥hÖµˆ„vÓtF·´„[ö1ÄÛ©² 7AèÄFú¹`7Qb ¦/mØå¤VE‘;©>ˆ
+Z
+z‡Ú#Uq)¦‰ÍQP±­­^…‚*¦‘y4Þ{Ök½€Í&Š ±ÖÙêÏ‚#mJ¦MTÔÊaj ëgºÅ‚8ú/«fÚ† ¢ùàǧ …
+ÕŒôW‡ÕZòk²ðDʯ9ÒÍ gˆLK'êaáø|˜ åØê_GÈ
+]2_Æ2@#϶ZÓ7öšƒ¯», ÖèµË}0„8Šb™a‘ŠÑäÖ”7/3dFð u¾<„M`:bRõÇD¡ÅùIä!œN”¼Åø!ÜOªLU!í¤yÃùÈA¢e‹ÈB(}¸‹¢œW-%€)D(S0ÂooZ=¡¥$VˆÞ÷7Aì[ÀPŽ*¯AR,áÎ@FsÑà]+Ü0‡—_“ðKÔ8<$éM`[$ÒCD8,ÚæKè4¤H²Ç°j+%ž¥¯£ÉœsEˆTNN<†ë?ƒ"žÆè’|$Â3ø¹4Xóaì´¸
+ŠV±å aXΗUé­]øÂw"…ú¥¢ç8ˆÑfë@*jË ¹Ê:Z‰e0)òÇy
+ÒÙ½¢ˆÙ¦¶2òYè·Lñ½ÉcÒÈaÉzò 1Z¹†ÖM·C¾Hh7¶J8Sdû¼ ¯iüBHK××ãàLs‹qciàØ›
+~y
+=•ã
+±ü5ñ¡¤Ñ= r =ƒBÐ/¼Kºð‡§ç„øš<('æ‹¥šâ±é
+]ýºJ„ôl²æb/N}"[&œµK
+U«gq¡ßÍ‚CbêøÔ6 JšÜ®*"ë U‚ùÙ†×+R1¹
+üR7Z®‡B2éÆá#æ³M³Í dQ‹û:íýN…Ò^U
+ÐÉý
+Y*!²‘
+ýî€Vp>Ü}˦錖ïwLsð€$ïOE ?ŽT6Þ^Þ[–*VN:À«€’ˆFQœnY§@ó¤~ž±ÝŠwcYù4ŠFïð)§ßßÁ~÷±»y  [ HÄ6D½Nº| ÒLÌ6ɯ¦¤…³-<ê % gÄ/!7¼›CCX–9Š]¯/)_à¡r¹¿BFŒrâêÜ"‡â ±3ldMK!ÿþDÞ1$nOp„µà=¡«*3MÀÏñ´T O€°rÍ»5HuÑœ±Y4µ ;„—ÎJ#²!‚S¿tu }´¿³.M—æÐG žM7C˜‘s\•žE\:¢ÄÈ¢ÿ®rBŒfk,Ç]ó"`r*;²Zl» ÀGN 5G:JP'ˆAÿhNý°=
+rÕ¸©©êø=Ïc‹^:æ.â¡yü¹'H1Y¦>›K”$žš)‘Õ<}pI_sXíyx
+9§iéb|ôÙQ÷„RSÞhÍ=¢m 7JÊbD«¡ÌÜFÊŠbŒ‰ aœ›
+`¬*!tÎ@ËAj`“ßN&²8Õ4)ù"È%޵țq㎙ Êõ©(áO +ÖHK5„ž dÍl^„y£
+#˜†¿U3“™ƒ P,HÅÀæßVÍ7²K‹
+Å"Øÿ….Ð' Ëy´åÉQ¸ß
+ÏB`ñb- :Ã&ÞCê­Ä—’MÙOqDº|Õ7‚lœš‡ÑI·Y"Ž>C¨
+6/i²A<çåèÖ9@BÇÉ3i¤ǹ‚5%˜ù$´¸wY]€BÀk<FƒÒ¨ uÝXZ§³¯ ÐeÑÍ >Ç‘ Ï™4^<¸86áø ŒŸ .do
+Š%Viþ©¯a Ë<§¨¯„D;fN{3Ç]Ç›ú OIúc^B'`é-irõn!*Ñ~¥AÆæBÒe5,õÙ<}W™`dš¬o.¤h 0Е±¯Æ—ð-TÞ*ïë)%yâëÊ (áñè)Lµø~Ø¿H|(±s–^‹¼âYﲎ*âŽþ] _¦Gº‹wá¿šP%J¼Þe+ ÃdØKtoãÕÑEìŸ1‰l$†¤œãØ5á‚CïÉNÔ„eós±—á€ôÍž^4I­ýÿxòà&U@ž,³§Hø† 0y(‚YP»æ J’qÚw8üYá  Så s­ûWØ NËÔqSVwNàyë8Ÿø¸;òq¨JouÕc³ô%SÈ垥чûçBO·tI´ 
+c"¾‰à»/µÃEsf/±áL[EeãØp+{0¡9ÿpýJ^]²¿wgp`bkD8 Ïh%z,Ž{›ì£­Ç. µ0«±';Ýd$Ƈ»qÙ¹¼&— ÐÕvbªN´ms@|ð0-€Uä=6Ãix8à‚³†GTð Ó ra¡*žËc‰pæiA.šdÉ#ÎÚ˨m£—#oBg}!|ÈIJŠwüTï@3øBÊÉDƒ`$qÁ`,Á!Š;>üfÕ’´‰©Ù^÷¥&]‡"@ÄôD +d€–¢[ üÆ8’"»õPÂËéUxŠŠãÿ󾊇ޤ§:Œm bPÕþK‘ܦÖÉ…5ß·š·tþöÅÖý OÇc¸‹I‘M%m…`êR¼dr¤ª4’£À”\–Z¿$Q¦Ši#?mú³èrúÏåþ¨¨o:†Õ’…|}(Z{’@Ã$Ú½Äd‚:¾âà^‚÷ã)à¦xïïXjO¨k Ñ˜m•x•–¥ø]YÝâ;j æ5f¦:w ½–…K§—€*K6ã&·kˆÅd4Wï±ß0®‰òögXZ=@s§ø ÷Íý±ÄK4ìFâ·[e•1 ¬¯*¢s’šŒýÅÌÉïô_“Ëú¡°_‡aQ¢Æ×3Dîñ
+H‰Œ—Mr\7 „Oà;è™"@$ÖÎ2·HUVÊý·ù@â©¢™7UZX¶G=$ˆŸîƱúTó¿iÄ£Ùh¶¦«Ïþñ‡Š?fÄú%DVêaCl\o±Â|©mH×æËf[ë:„ÿ­9ÜÍ£n²áâºB.ˆç-"Öǹg¬5ƒ?&VkcŽ1Ub¦L¢ ÷Á7b}Ùò5?~ÿºÍG—naÂåfŸäÝ'@n4-Úä‹Ä,z¢á½™É…è±,ÚX¼a#Œ×ó5³ cÎæ"ä«_¯n2–‡ø°ë_ùÊ%3´’gf\:®`È ‡P”>7„àˆE—Äõ& -Æ/¥n’Ý´M˺P‰èÚcœˆÛœ1W[#Óµ!„²„hYÉõˆ¥od¥ô’W­¥:›¬qJ• ¼kq²Å>g†åI¼}U4&Ñ:]á ¥9=ÓÆ+â\4šðÉжîO¡*WÉü’7O"Œ³»ú¨ò«Ó§ª\OjžGNô«ÞÞ]$sæƒ_öhôå9å"›æ”6Úé,oÓë %É‚ð¾h>è²èûîV ‰N”I<ÇLÒ6Bmô^%ÞwçSû†p£ªò¡Œ:¤¹©0Mü°ºi0Æž#Jθ̶§4¦ûœa …"¥¤á0  ©§†üI!@7šÃ^¯›lu
+·©~7º H,$BÂC‡Ê`6ÈØAð\ò`Ä?‚^rÊ”õ]×E4<Oâ0_ÍÖ†‘yÎé¡Ôm2ºKV{P¦ÙFQ‚£ˆfÊuÕS<F3z—Yžøøë×?À:)Íi_¥îJô‡Nš•?:çúø÷¤‘ç@´Oç, c¨È%%»þcÐÓuŸ?‰é„þzUƒ3áíäº?šZB"ï@Ý‚ž&,A
+1;ç£>ûA7×½¾ïG —ú%¨s0;¡òcP,R'¡bÞÞæèó'ÏÂÈÇŸ@Û#Rj’Z˜×„ŽÇ€»Éo†sçûÈ@ÿdmå
+Ã-žB1÷)ÉkèRƒÑ–ä‹B·ÓZ±]u¥$ÉÖIÇu“1òDC±WM¸¥‡áh²¡û¾O.ÉŒáâ*hÅ$ªÐI£.Ê^ç"™c„pÐý)m!kpR}݃5IÅZ’kÅD(HkAH¨Öè¬í±$Mâ Ø’MªÆGNuö9;R’D_ Fxàxëšüd.RMù„U%±Aé…ÔǬ«T³Ž*}U!e„‚ r{ÎqÚ®Kêš$ &jeuUVÛÚÂ?žÔÐ|‘>ǧ˱ JDjÐ8 íô#VgáUÏ9ÔUIòu
+Nˆ‡n›"·€ÝUœb±®[žè[Ò q€,Ûò%DFKµ”©ÛÌ¡OéŠ1ˆ[}‰™õœËv‰ÍœVxÈv,´ƒÓ:YÌ£{×wOÓxiŽ,5ŸóßœCM©"Wí@0XFO'‹8^œ:{± >áÈ,¢ÖM¸bŒ2Œ@¡
+Ó¡¾*«øái°Ñ÷Io§3
+¹¥’ÇÃmx˜v]ôÌ2¾KMefŒ3³ÏTõ¤î7Œç,>ÁYÚžsÑ+qòû¤î‘óõqO¿ º ’Õé“7o4þÆoÅøø¬aûmgZðÐXdIkÓIüaüF½°28º¾n@{À2jewåi¾ìp‰ãÓ•„ãðâ1ÀФ¬êRŽì´>ÅY(‡¥çж„0tsãP–´ÌmnD¾ “G
+Îì@Jðû°#åeŽ g«cf#¡„ƒ'| …&àÆÏ2D Ò£l Z¯Z*tÊ;çµ”ð¢ÕC8Y¦’–š£2Ã…’¶—jå\AYÎØJ¦‘{òy8´k@“Pßj>É=‘&ÏÅ8H*„ÔÉk¿ãЛÓÜï@›NhMdX™ÆêOªJ¸ '8Ž#ü
+G CÆM¼åP¤Ô2V£+bB±»Æ¹ÉSΙvÚ:G¨I×¢ú—M€–­üRÆeìŽóË&¬¦éÎè¦y8&ûãR|BØ >¾Î¡‚‘ @¯Í;Ê™›fa;:xÄE91Ð'™›Jk‚fÒÃÅÅѳ°Û’º‰¹o¹x²—ÚˆîäÜæ_ìö‚Ð#Ãhe o ß×Ð;ÈËú
+bÇ$á CÖ:g1¹•Zm‡\B›œí•HÙC©ÝÊÉzõÄ H“gѲ(i}…|³à÷o’øûÍ«¾>o]3ïRäŠÙˆœ³Ý£(Œæ.곃qÁ ´‘e¿5³‚Ks+éÙ(5xŒäM¥¥H NʇeeY$ Ÿî—ã*æfQ&–û†EÖY’ï e”¾«ÇÍ1Ê$p ^¯‚Iï9-å€q3ïZ>un¶Æ­q÷òºG±¶T¯aj„T11p }iX,³xÑÙƒÿ ¾6ýV艑þ2(KKH‹¦ eò«+ä_Y›“€PÈM,£„eáh˜0Álñ¥…+,*o’¦^­«htv¯ÅVx¹†›)÷8¤¿ŽÏ s岎;a<ØÜÞAžýì†qAçpéXˆ»XÒ}·4ÖT¸ÄîùMØ|ìÁbë×õ&XÊzfµIÁ°p,
+;úLIÐ)ÏÍ­62æ’TBl‰§R¹ádxæµ.¤RCßD)—KOl©ªýº
+’~‚ÇÙX„äÚëZnAÉ‘£| ‘deç±HÞÇË(Îö2@6r¤ûNãtÞ´Ï—²Z³g/¦(ÎBŽ=Y~V£Ã%ì­Š/>õ)}¶A ô¶Îò÷|Ì–gKí¥‡×u Ó9]éÛ·<ã±htF¯p‰t¿¶x³
+.Ù~2 C‘£r–ÛéQßš; $•VpX´ÜA8òi41¾^Å/zžåvbþÊpÁä#l4ÇYéL<ͯ´ß„ÐpU˜R¨Ö×M/AÜ…´k“úWRa¹a„2—!Øÿ†O“”Ü’/î€ jË+–1.nÚZ(q̪H2‰åø†nSX´D1;­¤µÑúŪœ¦¨ªTÅ.ÎS ÚåI½¹˜3èL.pt?õzþ¦P‰KsÄ£ºœ ¿¦ÊëWÁMF&ÐÙéR&VµÀÃÎÑ%„)IaIS.Ÿ†ç©’G“3q­óª¿½ŸLhŠ}#‹Xä×jëÇÇ
+§¨ûæ5e¶ì9\–\¡DŽiYÂ\h!S>•¯÷‡Š%íì­;Å õü\aB¡8zV–B¡èýŒÌu!ägi*:ÿÔ“‡ÐÚîTuÇ)ÌÐ’Ëëeœ«ê`þÚ4&q¨án€y°•W±s² FM±„ð­
+òq (Â~¤M{à¶å’òJ!e¶iä”ëB¶ôáDFöRÚQJ§œü3tËÏ!Æ–Gê½5Ò0\,IF'žÇ”¢òðP^„YeÈôf ºfbÈ°ÂÛg$õÖ¢? Q‘k€„Á\Þ$N‚æÖIoªK[óº# a%t©ÊyÖ :ÃÂa$Vä3K:5}+_—! .›>Mh0Gl¸+£EAn;Û˜š`E’#9,2¶-w¯Ô¦j!¶qŽ×É{ÂÆ×ñìl@ìÎ’ j^OÚHl€:¹ª<Y¥®r4c}ƒè,XÄ5Žzfð‡I-"¤i"31r<} ÄÑNR<¬W«yÕÍþtúßV%ü!|ó‘UPᔉu—Ë%įâ@R»Õç@Ô"aÿ²_ÅE°><Å«h+h°HÑçz:¶1APäLâªç ¨ÈŒV¬ˆÏÓË”%ùÞ°Q MÂo`Èe‰œk?‡ÙàÿÐפ{•#8ú3mÁj\!Bì©Â 9vˆ)m·‡cè1íH5¹¶ šßKZœ"Â¥tômì"T ¥“{M}œamS=¹ÁíÂ¥a`£Î¯¯}¨šZiŽ7!´ȶµ|nzŠMµÄ%½{ÄMO#Hh8ÒUÓ›7=Ñèu2@Å{#Ô£¸ðkò˜M¤øEÍh!{’æ
+e±'I6hçô*<€ÖÑæщ|A\MaWà9pÍ?€V²Œ2°V€½@€QåÍe\1Š€ ¦` :dŠ[([¤Sビ‹If`g§,YÌëÌ…Á“šÓnÔi^¥¤˜?à ¶])o¤éd%µ$ˆ1x‹oývÝÝð¾|6†—µ$9ä×¼>¦Züƒ¸îMù'†¢¦_r$äZ*ârÏÇ?À }ª-}9ˆúp"M}9\QÃm;f¯Óè„mK†Ž“ô±nó1²¬_¾W›£"­¯ JÃØAûà+há!©!­=ŒÄ¥ÛÍÛö!ó‘ú¾ (šÞRk¤c.7“)Ãn¡ SòÏ~²|“lÈ$¯ÆŽ ?"õïð+G9W³o&R'Ëäi¥Qv¯€r¨¥3—žÀÞfËP«ve[B é°Cæ¶mÙ²ào¦Oüs4Å›±5É{ ²q¸›ß…4ú£~¬Kˆc½ô ž¤UZyw^"' I«'dkM¡¥©xj È€T#‚/WC
+â&MµÙ¬ EñGcR4ÂGÆ\Š<Îq²è,?ƒ6ekõ[9Á±ªÕµDFÞ]YŽ¦T1i\µåˆ:ê_Fóy†ÕŒMªHÚõÀ‰jæ ‰±Ãœ¥ˆ«Ý¸‹TW›:…¯nÌ[ìz®E†ÆÈ­žú† yÏ9­ì:½{ g*;Ö+šÈ6 0œý¨5Àð®ä-Ñ8NŤ´â*ðìpûƒª
+Š866Ø:îkPTƒèX‘æWbr¹€†áåƒ|wvý²úC6Àrb>»xØ='=”²ðò%5×TS®5Ü2î¼ß˜êK‘çŠhlÓ|ÑO‹<ÎðŠÞLµQ:äšjИ”ü>Ôç ÁàÕIÃÒך¾¥7‹73Œ¢2CÄÓ:¦š©s[¼ò››{a±!‚ç~nójªŠ6”WÁÙ©&$‚öŠ°M‡Y^M5«Ý¤´ê›jà.åf±Ô~cª/Eס3âÍhª@eâO‹ÞWðù“=•_Žp^dI\µm?ŒùTûø×ÁJ«Hê„Ѧ=µ;E*Ñs;m’Þ%A:Yä‰WIo( %×±yˆnÃ>3¨© EEXDÎarÚŸÂæ&–ëœ3r’ô8’]R¢îÇOee­DÛ•€™}‰ jÙûüåÑ7¸ ĺNk7wFG‚¨3/î|­y®îðw2 cÚýV£
+Y“ˆ kºßÒ ¥?ðLÖ£š4WRE¯ŽbHÄEÊaÌiÍ!QE.dyúþW 0»’£
+fª‹gÆÙEK0u£9ÙÃP!ÒFŽ°ÝI‰~ „mœ ˜s?×Æ`%ÙKìý,NÑó¦fåjµãFœ6ゼûžÞ»æ(²ØR-”C;vs
+ŒÃ°êÙ`¼RUôâøm ÓÅ;¥UÀµØÝ„ê•í±N²eQŠ]/g™'¾:ìIÉ f…`õ=NŽáHºÚÓ1+¢)BYÃE1Ž‡7ä FÂí:]v³€tj£¹`*Ý=ÊžeNÜißFQ”x¥X:¬„ùƒP
+P6¸ †9áÙÒªÙcUÅ™ ³e’(÷¾¸âµÆÌPà6°—,ËÓ¯éÚŸlXÑõ%ÖY~~¬IQ2qs’¼&MT ÄLƒgi5‹ÎccBïí0—Sôom}þD€eOq¬옞¸§E÷¸ºˆ¯4® ú
+[lšG°“h+¶¹*2GNÈ\mSêŒ bÊ˱ȱò!è ¥ôuq\f 0«š%‡Ô¹?=rK€µ¬g´
+¬(º
+£ùÝl½HƒAhº“ÚMÐ
+ 8ŒÏÃÖ,ÖRìV³"Ãlâ8|  Õî¾.«E>Ž,åᔬO5uÇÊQ¨Ë9(ÊøXäï” ³“wãÔÛ‡3 •„lhÄ ±‡Stµäú˜â—¾’®Ø,”Ää×ÓYö¢‚ŠGxj ¬)FLZ×ËI»AèÃ=¦=B ×JŽÝÔšððŒÐK1)Á ‰n’¾ÙŽ.Áƽ§&ÎC •îéî?ì0K”ì²­°Tw2BL8[~oæ›’Œ~þrŠ<´W´¸2‚”Òÿ(ºl ÷¹½±Âߌ—KŽ$9DO0wÈô—¸®íÜ¢¶Õ÷ßö3Jrg ˜ºs,äi43†Ãum…©ÄÍ&Ã&HŽHþÙ lK™¸ÚµGÜ-PÇŒq}|`Yä @øÁHâhÏ‘à3"äa[ÄÚÕgíDío,?ŠT ý÷U»0Bß^3|‡hS!ÔñÏâú¯ÿ À|¹*b݈~ïÄð=HŸk*<g½ˆ¨*œ¡gÝW üsã/ʘÉrc
+ý/†J;/ ¨å…EcN
+ÌÜ|¢ÅsŸ¿??Ò÷žº%Àêä†e^éÊO)¦éóLXD—ñOŠ[j
+Â4Þšÿ~hñ‘ÞÉï„9ÕOó0:“,]-‡ì¨6º§4Q6„K ¡e=«
+Ë%—¡C¸áiUbFXA©à:Ë© 5„ÞòZÈuK|×63»ŒÌ¢maX ΢Rˆý¥Å²Cï(ìüt kŠTDñ¢_Ë 7!J4Ä` a1q½IgSZxðWηC Œ<–nµrÖ82ÎÔìSj?§e^CË{ãáišÌzÌ€€ªpA6(;9ª^À
+ÆÉd9
+v«­ïg@ÌM?;¦6v<ﶟ%§¶iFÃeæ[%•è¶¹€ñô¤h’Ï`!šFuvGx;M> œA]C„Ñ]rÖ™Þ;O°æ($­ÅŠEÚ²
+
+Ö"}N›¤ç}|Ý.ŽŠñ&™…!íi§
+B:>öŠ¸Èþ…Õ<…Í?E\ìú×CEzûDØçÅÂR
+ª¾`G½r]QÓ¹sª^Â(ªNEëÔ™J~Š‰ä‡5d>¯vÜéúó“ÉÙ–¼UÞ;£xüÏÆ +c0W”Ìô¾`sS nJ¿#  _Úl¿h+%¼s9¹VAQQ_£‹¾5 Év5B?–hï½æ(“¾9‡•Ãúîa/áö
+„ŽD-x–Q©þ
+e¬ñ1¤ hÊŽIb/%
+’@²Æœî?gHõ¥ÉX:U°HoÑVbx™]v1wÄTæ±À«#zv
+æ…£ äV¸4úúzŽlŸg.ncétÓ ”ëƒ(Ð{
+ebPyÂ\çI˜eÛò.ñDa{-çÙêZ“‘Ìé’½CÁqÚÍxUØÉ0´öòч¸?9oò
+ÏaÐ4Ò0ä²vn¢Êâ À!‹ñÂÉ/»’ů\ÏüS k%Ã@=ØTNe¦’1)a‰@(,É“!Ìíª/ÿù/åe’$בÑôxYÌÃZ½¬[p[¼ÿ¶Ÿˆj)¤X’µÉš)0~àð¡±äÛß}+i\žE©J¹f©¸rÀLã5óZôù¦¨h-qÈŸõÆS%E¼âÉL4G!–¯wÅÔb÷D¦þ¨ äi¦h§œ&Ãæ¬&ªEßScMo2ï,Bq ƒLs 0¹Ö°½™çßJ6XŒŠ‡ÌÎ<çt%3Ñs=ΖöÃÙ¬a×¾\ÙH!Üí£'ZŸ"ÿ`w2gŸaÁ+9ÞKðJ<+h ’¤}Á±Íõ¦‚…Y{QŸêYÔdŹmXN¡„hVœΊƒl´ðe%øÑŠVn‰ó˜%O Þi ëUpIZ^â+*+½üÈ–/<Àaœ@¢WVÔ*ø*©
+Á[BEe‚Ш€rù ų (e$€Ráœ?™ÉØð%›d‹IŽZ SLX¾Å)Ê°Á$d›‡SNMr±F ãΦ©¾Vl8EÉËQ²¬ ÅÒ¾VdWñ-_êùÒ£œ‘èÚüCÒ±NßáŽðmŒC à˜æ;µ4œÁ(ëËJMå‰"=‰î!rìiJuŸ¢Råá‘óMUq/’P‹ƒÅQc"•´æ»\J,‡ù²¼Ç›s2ß¹ÈwKÆ
+±ât!—bC`ÄA‚'FÁHÅI_ú¦6<,Ë~•}S¿fᜒFºhêÎÞaF[ŠUø¼–àÀDx2ŠLJ³’.‘÷¥èÓ‹x:dÈÛGœСEØälÂ.)ÑòýŽ«â˜%+Þºï;5ä\èåÂ%›H4¦ÿôx2ãÆšsº Ÿ¤^êY;1=msGçäjY@ó:ΗGŽ(¿(ஓ˜^Î9°J¥;%HIÅÁâ4¸dsâ™p!fîpàSF=WðV6 írñ:OŽ‘—ýœ÷ãî2™8¾xA{¿)ù›[•©Í?þ €&X1êü/ý+ýÿ²"Üûbe¹z7èºB©1õКÅÛ°87%«fšÇ¤c» É®+ÑW÷fãÉ22vÀRóÑX)!ù9´Æ3êŽ7ËÀ˜HA­ï‰ýàç£ÃLY^v@÷õ‡ ·lÅF¿}¼)Z„ Ñ m5c "ÖÎÅÑœK+puHv˜jQ‚¤!8½œâ<
+³=™¡õŽWî¦ð@T
+iLõ”zç°¾ƒ¸ã)Úœíæ̯suø‚ØÖ0Ë2“};‡¨\õy ? ´€É:Þñ (ð/-Þ4°ø]÷§íXkHÚ{+/¬’UX6p—cÌ…º1,«™5îèöKEp„W$VÜÅWýYÂG1M|àÀ>nþn‘\#,'®s>¸mÖ<©õÖ@*Öí–NJ&±ž
+F—à@à·ZH;
+Íe›ïÒ¤ÍËD…¬îPÁ![AÐ6læ…f4™ªvVæïꥯòɸ‘Ýö¥Ä?ÅIm2·#02n™ °Æ1#Ü„ ÐdÃŒö& »¾”}Š6Ü°ÀË4iÐ[¢„L +'P‚Øb;ÿ>çðgòGU0™7ªÅ¥ .d*¤ê
+œÞ$kbñç
+òKCl ø» Ð;V]Wü‘ŠrÅ(̪Drd‘ÝEPp@Â2¾mÀ%e]{_Š>nEE°Ä@2cܵ¢Çç^‹>¿s§»zý|àN»’ÚíVºzaÜ
+ä­¬Go`¸/©‘cyl®ñ%þïP
+-]§q.3%@âçj%v_¼Aîç”ÊÔÈ|Íø€’
+&„e %Ætž®ÿY _%Š%nÏK‰Š-ÅÎðïõ¡XR†</!‚
+ðÙ‹ŒÊqôñÃb09áèQ£ :äà•ñ
+
+p<Äük·kñ)YgŒv¼!hl"¹Ï—‚𙚸sœ¡J±÷¢ÿ7GgŠœoá÷“yÒ³9KÄÊ…àÏ[ÎbbâyðÁ¿hè%¯QDë×
+r˜ vŸŠI쬭 ^j¬
+ísÜ*—"• °ô¢è‡î–\ÓP–‘m£¤IÖ{‘3 ~ÁC'ïN4æ`XÂ4Åí)ÁW¢
+ð?ÊË&¹–[‡Á+ȼ‚Sú¥¤q²“LíýOßJrùv«ãó’T*±qÕ  D
+»`<yŸê€þr’æ^è}Ð2ƒÈãƒÞOÒ^Gè¹@<’RЪ$ó9¼üÖO ?
+±ÑŤ "22q¸ùÜVæ–Â,±Ò’T=­6há
+Â7°qŠÕÞ:²;AšÕ"ÔÌM‰zdÜW`§PF¡vCˆeVýãÛpqØèˆ>Uhçð¥&Ô‡sÈÜŒ«$¡­`nm,GŸøò²,• ‘ìUdO¬…¬­žÜoöB–)«JªÚm?S¬±Y0Ï!´½_¦œƒ¯÷MJQf¼VPÜ51î \\nï¾Bf‰/õ;sé‚ Œÿ ´‹.§nò*\³‚+v7/¬
+D ëXa!³ ¡TT`M⇠2ÃÖ÷zäžcps‰D¤Ôñ}‡—ŸÉxúŽ­šË&Ùåm™±eÊÁöm”NtlÊntîžÉ’IŒÎgÊ›»2…pñt)«/~‰´Säì]ÐI9ùšäwÉåAïWqAâUÆÉ0zŒž¯1dØíÜ¡åy}€T AmÉŸ½ÇÎá‰ÈÊPKùÔ‹+d «TS±Y=ÎAÙX‚§h]FñY1’KL†Ù àvm,b-Æ@[ÒdûW 6Qæ:Ax#æF=Rû8Dd$0Ù ²|„0`Ø 1Ûq¬/ý÷h}ûŽ$Œ­®:¾sõFHl]‰Az‚cÒ®<+©[Ñ€Í5;
+/¥Ó1E•/¬Œ):U'š¢dàò „Û*–@4ëRù1òTÈŒÃGðúÙ‹ÏÆ+ß•*µ<éÂì9ƒ¸¬uÊ–„›šBAa•C°d#È,$b[C‰5®ô((R‰³rú^œ´®í`
+w ÙL×|^¢‡´žw/¨Õ0MÎ.ª6(7†¯d÷F?££á•ØßúÑ•Nm¿¹ ãîH*½¨Çp»@\&6ô¶/CÍz×È>ZI[TÄ×õ(ì€.óï>ÃòI@ ô¸–•Yô?Ê„¸áÇkÙ@‹6žXY¤èZœ_j¸š¦/”ºc uŠ—}ðòG×? ¦:wu\¶œüSUÙNþË’wô'ò7zVê|w'ëêOÅr0Çùl”h†E/ßÝéKW%'Rã“õTònŽ¢ÆÈVðµx:FÄâ›øš}ß„âETwœä4ÄƲ$eɨ¦› VxÊdg÷•Tq™=Ô–3’ˆ?¬zkЉ€Yf)Ǭn#¥s3ê7>ÎWE2*¡e¬/ý÷Tj~ùæ owDnw@û¹Ý}M2Š¢9¿X¬¸é£þ\úÓAƒ@lëý;Æñ¬ŽB§¢üš
+IœtThå</I¹
+ÉDôÈ1¡2ÕWä³Q¹©‡ó9•T%…d@F[‚LÑ‘QªH²tÙ6%éM?o.€:ÂÉŠû1æ;ÛÑ&Ûñ2„L÷_;ei}¨q.5¤x 6iè#R ˜¥98¢ž(‡b;†‰Ÿ+/Öå®ÎÆ6°júû÷_Ð!»Šô6ʵY¾ ’ÕÍD^&¿8/N ˜Iü¸¡ó¹½ÈoäÜ*YܾǦH½˜â%$
+?‘›?4Kë“ŒJ ˆ@Ò.´M6ŒwÚúb‡/B&®ä†·Ìâca]—>"þ†U¯à s*N†<œ2T)È› «,¾£Ý.ñ‘pŠ¤dÉϘ֖ÝÚ6HÄì|9ó!K›Õä V»`“_PzÉͧƒY0Gmµe];2í1ªo‚H…/˜1/²S'„ÔÈa+ )¡CGâsöJÞ1ćJÞ`æŒ{ð<~„®ñ®QþÐ N ‘6 yÑ’B[J¼LâK BB*IÏÆÎ|ËhV/aom™¢ª«ûZ :RÌyÌÔIÈ`É XS5‰Õ™†MíŠ9â0[ÁtÇìë™ÍþÒÒ¿÷Ú1¶Œ€/“Íúyí=‚p ¢+™¯ø„ÿÊD5xg+ݨF9#CîëW¢ÏS;4„D´žt¯rË·N‹/$ýrçÛù’X•Uÿ8¤…!,î óSüù¨­g•úvLÅ
+$*™Káø2(¸kCX›Cᓉ³¾ºÎÑdþD u_<Ê«™Þø½ÒžŽñbNsp†²åÐu
+4,C(í]´ ŸCäÿ(/“ìÊnˆ® öàè°oÆ9Õ.<UíZ7@PÇù¾SU5±¿!>DCÑ„ÁóÀÜÔ5ߧ«¨LW1d¤Òñz^ƒ6áñúñz&¼º6‰s>­hË‘Œ œÓþiQ ‡ÕBÆòHx\Ÿø“a¬$Jß Íw~Å£F‰R]ò
+¬ø±n(øœF)5U`ÀØ™Há9ôCŠ·'WB`Á-6÷Ã
+Ʀòé$ÞR W%O –uõ7ÓúÃÔ}“tÅ'\Ø^‡_·ã
+jè6AøÝ,;s@ñIrä9T–hôeD>ü&gÆç4Ò,ƒž’1¾å2)w0Z5¹°$Xoþ v‚cñêðR>ªÛÙ÷J"Y”:*à÷Q,Œ‘3B3ä`jÁÊ)û""˜|g;ˆe ËfT¼˜’ ¿?-ê@…Za ˆŠ°Qà?¯âS(Rüs?[¡l À.§¢Ñ”–¤qûšô½¸K[HÂtHtDGMÏõžƒñÊZÃÎÁDÌʬ*™ÃÝ5?°ç\rL%1—“j^K$,ÒJ†YÞœÓäªÈ§äCOƒ³iO;”oFTx„­$„~áiÂJÓöOñ(‹Ÿ“?]ÉC‰ 9ŸœÛ
+ƒ…ˆ¿rü¢‘øŽ(2Å;÷7Z‹~À\\†>¨ÈpØìñ®t•¿) áGÇ<ûŠàpá|-z%<R³ÙÇ|F°ÙTž²o~ÅY£K|~…c¹!’1ØeŒ×O‹Dg
+{ù9üþ)gˆþlj¶Ð9+‚åW&ðÂKZX­$µ†RÓgõ”T-ȾnC†>ÅÆ`µéëôQAú\*ˆ™×Õ¥‘sèÙþt¸O`E úù˜±sW»%Ю¹ø½ó!pþ
+(UœPÞœ+Ö…îVFj]!( kjŸÊÍ.yÍ"¨ÔƒPÔÉ`kÇ
+3•«_†•£Üg¤ƒåƒ3½YÉ‹ ^(J“ÖÃï\xãFñ'å G2¶ÙZÎa‰*oE hÎ(,¢áòƒ¬@çd–tĸJ½Y‰ˆIXüº½*Iª>¾îÈ“",Í¥üƒXìÁuŸÚx§Ø ØRLå øþ€á_ߦg*ÚâÆ—úëVðàœj3¸Sa‘á€g¿äƒD"ǘÕÝ d
+àŽi•#Eá‡ÇCô¼¬„X³Ø¸ë¾qI}2hXt9âa8TCVéê5!ˆÈZåA~&Øê|OÕB‚07£1/1¡ãGÑǤžÓùT)–ò]¢øµÀûÌa1
+7îb}½VÇO•ú¼º¿Ù°"S,jï¬ÖbóÁJñ‘u óƒQ £ú_É ¥‹Ô×dlòÏmŠüÎ1ðÄÅöÌ»~.
+NU`E=V>,ÉÛšaé=( ©éµèóMžGÖxÃ2 ‹²º”ööáÊ–µÒb¿W›YÞ¯æøœ™![¥ â‰Œi3 œêÅq‘å^4,»]fÿòÈRûÀ>wõØ+&Yv&¼Ã¶IÁ¥  Ê¦­²‚’crD%~½ûãÒÐf?{~VÛ‡øÕsì&nï÷2™]ã$ðt÷¥ 媢õÖ`ÖˆVCžö ŠO§f>z¥@Ë7µ.R¿7%ʨ ÂŒý:û"à`üÃ}½)‚ÙE¹Z¬~ ŽÂA®xÚ›hkÊYþáìo¶
+•Û)8 öPQ|Bæ¦ÿ$³ J ,×É5Hs§ÅЧ( Öòï@-ØYÆq”‘€DõGó&£ß’šPƒZ• õ×<âÄ'|n%0}k´ðœi.o1<áõ\8)j#ˆ³V1´I;vAmÓ”yÍ¿€°•
+Á °„gäJ4s€½üU©Ù!øFôOa§(¡]Éç©À™°2ƒteÇ`®·Sîç¦,ùÏÄàw}SòHG¢ìåc¢PFÂÐÿ¼æ±}ÑÇ~PôBÑj½ÖjѪLý_ßð@Qä‘0 üö?ÊË$GŽˆ¢'Ðê ÎúµÔ-z[ºÿVïƒ U'jÁ†!—ÃL2âDzqË©è%'©¤Bõ}ʘ‰À6’‡jSáŸV¢/3üæò¥@¦&á@…a+ÙªaÙL¹ûö°x=@D¤M릇)âË©yôC¿Kõt„
+=ðŒ6¡HÝ#$nËJÇÂb~Šò<¸¿ºn|‚ë¡Vv ]®\†L<ÎâõD8ˆ¹¾Ät+Þš¿ G&/o§/¡dòÆuÂÐL~ŒÑLFA;U1ÌÁµÛ6FS ‚È2Ý*éS$£ÁÁEæ!ù¬V É¿Ô8몛î61Q{LŒpdí¹_q¹•Ò,X¡:—d"7>Äû—®E/²mbBP\ÀÉ:”ÍHc! ºÕ>ÌÚ qA7øU$SÉ¢ù Ò(°9
+r3¿ÍºŒ'ƒÄ<`8"ží Xd[†bNÞW¹Ø" QÛ¸v>Û+Dq½*yñ«¨uMÉø ‚ÒÓLcK#C W>îØ &EØ @§Û´Þ#Þ bD)*It Qaövtܧ’¢„¥Æ^,&œÎö éPó<×(!€-¶£¯íÎ2~üâ¤_ìE,0Qg¬íŽš­ v2"‚~Á£%oqb
+älmu¯L¹,mèŒgm7¶™P¹AóšhNü$#XÃ\: T·‹¹œ#”õ­às1 h¡›Œ„ßó¾Ä=hƒ)tQaþt°¯±1,h¢£wö¬]Û"_3nJ W؈Óæ¬k $aN¡‹uDWºâÈtž€Ã¢t[/±’‚%-"Šý>ÓB‚ÆÂg1`¬;Þ”¬"è“?#j}¬sŒm†ì)ajš ´Ä5Ìe›£˜¶:¯
+ÆË£jqPˆˆ+±8=Š8Ø1íâü¡œd«çDœMYYDA_»€Á5H ¦À)Ÿy0b >ë^»Y%Á½ÞÒalCiæ%Ù)¨ÓÚ¶ºLÚÂ׫ŒÆ©È"«k¦ˆç_º±[Q/$|Ø1ÚâoÄ6»I† N)k£¦JÐ jÜqNœxV9*o^¼¥³uÑk’¼§(‡?NŠzñd<íŒ uNFG'oG?«¼2}òÏç$(¿VüxˆÐàÚ—¸hy™+hÛ¶–¬š;2E»Ú–± D–»š¶ƒÆÞGýÌURûd7¡¨xLç’ÐÉ£]TÆmÞ—¸àDžyI‡¢ç*ʉ£ÔÜöƒs¹+\FXdB®àŠ¬G
+þ.9nfɆã/lí`X Ïž,›4}Žésëhoo´Ì³c
+$[CMyo]V!®¹ŸÅæ0 á´õã<¿”,äà&šö"=Ã#YwÖÞßî¸gEîÜ-3ñÈÆÍä‘i7Ù èwÛ x6{QͬöªpÞãì0é&9gðÔ9oJ^œê;†–…‡²¡²
+§t3
+_šUÁÄ‹€5?!Í›“Ê›ÈC†’0EÏïŒWy6>~þàûoCŠ°è'ï÷ÛŠàþGV‘xr(RI‘™á„šmù¢à) +A£BaÏn¶P€*B‚J,”Q ¨ hѬŸö:ˆÇ*䱎aáâÆJ¸SY,ìHÙ¯r.]·­S"Câ¿MÌènt‡ïÀ퇢_7EPs•µ'Y·)"¡"z…åÌÊÂ
+2”&ê%Ü^Ô¬èé#v`Jî ’I•`yÆÀõ´´»ówFü°/)àâŸÐ™ès€B†‰)ó¶cø/ë6e?nFõ‘‹#‚£ƒ‡3³05ǃYèÀV‹qpqGGdij.«¬óòÞS$9xIoDÞ{ß&O'_*R<µÉØBü·-PE-x<9q×aîNE¯%Œ~ÒnÑüûs`¦«}´V“¿]¡ÈAÜPeÇv4…ÃÑ‚©ôª’>8WË!*Xó`ˆu°å¨¾/ÆH7z úB
+$žIÁ+lºÆY$<ËÐ`Γ)q!âÑ,\Ž§s„x(ÚÝî B5| ¼Ÿ`!{Ùèæ,ÅàñFP›®ûaì*áÀYÈ®ú…xM°·)^'O eUbs¾p¢Üa\%¶Wœ4-v2(ÑÊ*†­ú©„î—H³ U«~ið7ka8ñœ±Á©¦†«ñt>„(óÒdkÚYþ˜È þSbå*ª2 #·/ÁÃñcwDàhΟ·E'ùF<ƒU²€açðƒHÙH÷à[mÃÉDƒ›ðét(YàÏ Kòé¡F Ž˜—üé´qï$ŒYÀŒáàt0
+L>àá¼ã ,¦`]J9‰ËEytúïÌÅÉMd ,rOlrämpå ÿýƒGÍ–.&…™a\×þbJD·ç7~Àh·ý¹¯Îe„kê–œ3\)Øf\"™õZóG€
+H‰Œ—A’\7DOà;ôæ$¸Ö,} E̪uÿí<ü
+u}–Ý
+Ëí.g‘ H$ÆÇ´ê¥M{wi5Ü>þþ«F½†›ŽhRKoßi»†h”(ÞŠÇÙÕtôÖŠ4ñÔ®>J3ñ!îy›\Å{Q Ž?bNçôË\F˜¨qÝôy=ßö?`åÒâF५¬˜FcE±Ò?~1}¨ñ?¼L‰^kQ]ˆ6šùèeä]‰¨%F­î7„ÀŠ¢díã缨ö<SKµØçxµUëêó뽚òm a#x½ñü¶biÒù,´5õdÝÔ›©…Óßœ|ãMfo‚&+xTÔ7¢È;xZ÷crB¨;føùR¨}Õ H/)k
+<û8E£WÐÉéhC¯Bí†õÚ`ÔNàkv’^Í+4¥ON9VHÀ ]œíX«Ⱥê¥ä‡c^ysæ•ÇG½Ðø›—Vx$øßêG¶]ïä†ö¬>¼µ¯¤ÞÁÊëì;@O´¦èE%Sê†gý}=5¬£*­‰ðTAɾ BVšD­1Œb×óuß‹Ô]Âu*]‹—´:¸³ö ŠK;Má‚ôµõºAV„’5q©þ—ôN éÝ}•2œÇX³}R+•¥BÛú&q…çó½Œã
+$4ºRÚõ(4ÕÐ^ T÷kTiÑ;$ŒØF©x²TY€¤½¡ôí¹Ù”(ýÎ÷ãõ–]Ä@ëu%’/Ð8Þ)eŸ! %­ÔqCP #Ó5ó¿ S®¶ÖW4í[N>@§ús]±|}©®ï˜ô Ž!¼òDŸ¥%𱋙Ö* Tù=¤S[ p²ãÙÚ]V-­*¿º¾Êá†ðüà Yåh
+›25Žç@X 8²Ëª<Ì4?ðúq&À1aÖ¡ðÏï01 +ÿ* "èjŸLJn7†} GÚ$í Ô_ZR•L§¤{ÜO¹üª0!f®„Õ;ʸG°6ǵ,Òæ<-áà4¼íáÉä$rF¨Ä<'*Ûèjk{¾öž*6¤{ŽòŽŒ—FNhk<@ò*½è„¢´Þ³üq äÈ’v)£/HÊ1Ü#½& ¼»(À–l·*¥„ÑFc¶Ç T²ë+²Y¦}{bè³–#—.#û®b¼§hs0I²ÒÒ Ê2&¤× Î‡ÛîVz}ð$Æç½h¯Þ˜ð昀xÙˆÐdžS3»hj¾wAît …R$óÀ È*gÞJ:k19žó¨ø3šsN¯z0ð™Ÿ9>QýÏRýüNÏd{•Ù^¡áõ1+ŠV?ûuÂEàžÜÄw¡•á%Á
+Ü:mñÄËȘ `òùw¢%ûöÒ<wàYyf&d©ÎªtwñU Òˆ÷2“[~¿ŠÔ©î±ƒbœ7R{‹½;gHÐÔ=(³ßÁÑšï©õ"P¡8t²ßb6"ÿÆøåU5Ý¢ÒŒgß©¡àöÀº1ii­a *¹ËžßÉI3º¬›pùµVŒ¡/Ù¡NÆÄã;³‰O/Uÿ<‚ðßt$9ÏÉ«ó*ÊT«½½á\2_dÝ'DÉqOÞêÊ´8çÎé·z¥¹µÌV‰í’i+΀'4ÂÌ°cée0#ÉÇ6Òè›;¨>5ù)”/­É6i’©Çs`®‚«ÓnÅ Ä^ºŽÅaì!U¢.µì ‘=ž› ‚¹Ê
+AWl fk;rÔÙ½àÌf Œåz§·¢#¿³{áÙužœé SR»¯úçÖœ¦®¥\¨)b²'
+ þF×›h”¯dšÐõ IIsêZÖ•¯jø"T®ÝW!ä öÈ>Ú㕹@&Ç ƒ’Î-Òã´zÛzœŠ¦ßZW ÜbÅd¯[ËòC‹S2&û¿ Y±ó*ƒ…)oýåu
+ŸhŸÜs’ÑÆ!Ò@e¿,Û›ã Øo‡@¸
+Rn­Eœ6D Ô—”òë2—‡M#œkP•ÓÆ
+¤Pß–‚ÆBzÚ{3É ý w9½ «žÔ oKOqÔ›s^JþŒæAÓ«|fçAägŽO\ÿ³T?¿Ó4Ù_e÷J=($~÷ë„!*l
+8°”U–H‚‘©Â3ú R'{Ëáótž¡ÜLZÙó€x#ƒ D”‰BoM2ÝŒy
+„šŽÍ ö½®!»åS EÞz´RÐÑ–{>BÁÑöAF,3ʧ‚ |[ cê¹çÓrϧèžO`kà‰–Q>ÕÃ9€ÿ¯‰ ó©
+Ão¥7È÷|ª607ð•6hF¹2`Ëg>ÕXQ  ø†‹|OW”OLô~m3Χvv{ V¼¤EùÔVFsÝéßQ> 7ïžO¿\Ïãƒ+®a”Ç%'…¡îñâVÛâÄ–Ðä¢>‹[ÒQ7ð9×sÛæ‹¿‡KÚIð$dËŸpŠÔÊ°E…ü¢¯®›t
+ d¦\TòñrgC@y„A`XF†<Å¡\,HÃ4hºÎ«ª®FƒÑç bGNËU?Ü'õeçÚpë}bˈmssôTNœ>43iÙPCàJpüB)þ1š ôºªð¾ FÄ(+opÎÏÒÃd qF =ãMÓmiµð8º£A°3 ªƒŠ/ÃE4flýª)Y£æˆ‡Sñ0¾a!qlg«´Î|5+|)™TŠi‡ˆ[ <7=Aè\fÐ9ë\„¢áþÄmn”V±¡à”¶Î«eÝ›ŠWݘ€‡„I8¬_T”1·î¯nM
+ö¥Šu(òÏHTïG+…FÁ} Vk±QÒH ( Ÿ3rx;&¯J˜Kã$X¾†EeèÊ<úbÛKoÙC÷@˜dˆB*/Òç'©é¥`a#"’ésnžwÊ\¸ßÂ!9µ`R×Hš™dˆáÒDúâ-²˜“;èÏÑ ¾Q‚Š›2]É¥‹‚Y 3H1»7¼ámòn<ª´éì]Ò¡Ãvæ@†T³(µ¼Ö®lyŽÌÎø1dø$õR¯µ£ˆ1£t9͉¡¦œÌé˜a;os•í–ÃçýoΡ×[,Å\_}@lª<%¾öغŠØè[÷›NèD±}FÙ^ò®i\ïp%.7•Žn>=& GPö¹÷È'¯úK–¶K²$/ ÐÜ4
+ûò×0Œ
+¿„X ã%ùyåOœ+«§“¼X£®lÄÃÞé T,9ò›tˆÈÇÚ3üÎKÁ9üÐe!寥‘¿ååÙV˜ Ã5Œ%;1¯¥a…`ŒÑa.»ªñ=¨]!0bZ®Ù‘àIÑ5;ª3/Ò
+•¬²_õ)B£ PvŽœºQDo'¬gA
+b4˜¼¿æ’¶~À@D(y×›ul+|¿<è&é(V†oçj#d†ª ëâÃu€(¯­ À¢N‹•÷L #HeSoJ›8;zŸòÎ*e*ˆT0QnJh€ž³†}§÷=;ù¢ ÄücËð¶L¹î¢ÏdżмF4?f«zRdƒ™°´ |š³ùÞ½›¦Ôú@‚LÊqèê*aX˜¬ «gÝì‰ê@¢éíPr$§÷¢ß7E4¶Â”,Nø}SRL?ÿ/˜¢¸¼+ˆ‹~ .Ñåd¼­¤Ê$t8º” W¦Wç‰Cv$“Až¤{ÍPK ü¶L–—ÇØá“܉ƒ
+ÌÐÞ§÷f0qZ@›CÙ”QÄ “Rë;TFK¢  [¦Æ¥ÊC‡£É§RF»èÛ"Õ÷’µÓ-”© ñnIÚD…hçØëäÂxÓÛ(0^;ñ(>Oí: MçÁ
++t~æ›’÷ t-:á½!D t1OµÞ Å©è2ƒ§íþ¢èŽãõ^´8¦>žà½7ïñ Œú ”Æ1§¢—Ød%è^5Ÿ´BCxÌa‰„“7 byRÂæÒ󙞩ÈnWS)Š¬ñLhÛŽßδÖ!É«`÷‡'AI,(«"Ç9d:°Ó^Âÿ#/‹òC,R`pZ´ã-R<ùü}¨‚-'`ä’1»/fRm󲼙ɨr¢îwÉ‘ÞWnïÄÙŠ¦ðp6
+¸w[††!‡˜PîæšØ”!œ,® 0ïÛY9º`òxEªXÚwŠ3Êêb™¯Ó†"gë暬„0ËŸ¹I¯Š`AThÉãTܘk}}ou)zp¹ã1'>i¥DË+¸jÌlçïGª¤™¼ypÍ¡SS&D^Á·âW'6Úr[ÉAˆ !ÅM€­n/Ά|.R®ä8ÎIØ£-°#@*å¸N}¨õp)>!º³Ézº¦Àd$WY,mÒÝýJÐÀQ–îË&Š(“Ðîú|šÛ †a¢BùÂ:–‰¿¸ïS 9, žAê>×ðV!K”K>}ß)0
+ŒÐf"I^ë@k@¯¼3m­2Å,̺ßLxöUئaL÷ûDlû(ÉAƒÖ ÜÇj9„£ÑÃ'%;1 ˜¬Fñ|$OH¢;m  wª{#è
+ºcbž³éýª+\æA,šØ5ëL`A9̘WñÒŒó<´œôø4o"(Z¡»b(*ݬCZêj”4l›Ž’”-j]$‡3ÇÑTÝÝŒ
+¸Ú2˜S!™tµ‚Ž¶D™½›
+aÛ­T¤Žµ]˜÷€WÈr™6g™fÊð Ê_õ©ÌˆÏJ^B˜)!' Ç.ÿmN)Â`²B²)Lƒ'èÒ´_ë>mt&›cÙÆÁðavÈT]8Y.¢¸k?$ŒR 0¥4'ä?VС…‡ì1d÷œk^(Z;W.E€5üRP1îšö&HkO`b
+aIá o[!\
+È€T‡÷Í.e(¦ª(R;¢5Ó9‡¼#ÃÙTŠ­VYgØNcÐÕ) ýÎyù¿YìË‚h|‚ðaäkKåmRKåÂÔ±
+f°¡ºø£þöíÈ…<
+ã$!>±äò¡þÇ*éô4\!ìªÛY×=¹°_…=«zâÉùê”÷sßâZrþ`Å‘i×£+ƒ„`A\GåžX2 &œagþŸŸX²t³d‚øLמ t¹–̪ª©Ì]\[]KfQÅjûE‰çé7KfUå‘a¨öÑ·ä?Ñ;ô~%=)ÖEÿÇ“‹¶îÄš[ûKf[5ÎåÀ<ŠÛ‘T5*ÖÍÅ·dvŒýCïÚWKfÇ!P€®z–ÌvÕ‰bßÒ]K¾‡8–ìÝ,ùäõ"FP¥eæáZ2/¯Ò–I—Ÿéº:ò½¥oŽÌb ¨ò{¨ÿÑI½ºß™£!Y(ÈWò¹Î<*Ê#¦ëÈn¸båÊõ™%Wf©U
+Ãõä‚Ñþƒ¨v&æâ¥Ì8ëMDèÒ¬NÄúó
+“ rᘔ5»kÉÈ ­OºJÄ žX2ÝEðL¡×’+^ªí–'…|’óhÉ·ô<™Æ` ˜À¿иzreA9S¯æz2ïZ¯æuÙ“ÉŸ…T’‹¦Ó:µf@@ð³[‡ÄT¨Kljzë5ZD ¼ï]!4†Ý¨y=€Y:¿¥Y,„zRKzµÆ ª8-äÆL£©V Ò*‚Ç̳U°Åˆ>ð»eÚ9§btÁê æOcݹ؄,\cÉÐvÑ¡nÇÄ
+bD´¨dᎃB³¨X.›ÐÛÚehŽÐß1Ùn%%£ä#\-äر„GA½¢VÈgísôtĉƒ‹Ã?cŸ|zl]ç .CN÷X©ˉhš#^ëCôSÑ”ŒyŒ–A§U£G!\?f&
+=1&Ã’Fo);!«ý°*!C­üs4ø±Êªø|Ú—‰’Cà UYÀ¨­¶š@ó·aÒö§¦ü¸jŠãŠ¡¯Ï„ÈuSѱû€
+¡­,êá—S(ÅB-LM¼º ô€j—õ¦Ä"Êí§`gìËÐ`à¤+Ú1Ȭþƒòªw€' 8ô#Ôå<yòônâv“‰kÐד þÀI²îgéËìcÒut_2Ñl
+
+±EáÀÊ»gÄváƒ-÷ˆ:bÍöÄ!¾¹‹Œ×lËÄŬWŠô!C(Ú¢ì« ‡A¶¦¡±Ñ
+rh÷Œ)Íð€þ×Ô ¡É&€ÁìðóéÅTº‡MyhåZŸÞÇ®A_/Üè“÷…÷_ÿûöËÿx$6cÏâ÷a+û#"  ‘?ͦÿÿùFAE:Ó8º@D…Œ•âm+NPƒÇ¨p
+½¨> Èè2v¨èå • «jÄÑ-èþ¹ƒX™9j¹>Ççë”ïÊb_ º¤àë•<)ûñýwB3­ÄDjÔ§©­~"YÇ$AÛf)MÈ"—@ù ?/ÈBXfFB'›IŠB ’ g1›&øÉiNŠQPE´É, Qïd+'ídÝ‚>óúTÓ(iç61aÝÁP(ZŸ½´ ™6)„QÓ‚#UÝŸâT € EK¬  ÞÄÜYæ"bC"´€þMy™äF’+Aôu‡‚'\׶"ÝûŸqL(kÑ@WÊ‚Nú`fÞ&³Âô;=C±]e•$× 1ÙIV
+„ÖFùú®d¯sLsæZiǨÇñ&úÉ Ž<!üG5™k-«‚ l˜8fÀ÷m¸>¬Ê—Ôh…2£Wf,HÕÍdyY(eîFŸÆ™(”‡.$
+F曄À.K!Ÿ¡Ç
+‡Ge÷v7Ç‚y`®kuœ#gc›‘.A òª¿g>,'·óDìKœ²§æ°´‰›97ŠãóÕá¶ÉkuMÁ¢Êv
+ƒDE³…µI}#=š nxýá‘¡ºÑnhÊûb­Âø‡1xËæ˜h¬•É$…rŽ’m›{Z‚|­|µ­s8”ŠâRB_º
+]æ>ÄIMÕ#çŒw/VhÚ æh²%­{<@–k¥m©„½9‚ èç’×m`^Ê£j:}q„ÅeÞ€$þ)sç¶Õ^­Œ_áîžd7Ù<GTÿA;Ç´€*.éÍG&¸‰Ðìe® ýáK\÷ÑLT4Öu¶) 8'f¨·ï,K&"­Ñå6ÆSt- «‘¹±L-¹êqøMÚŸz£C2…»TÚj92lùÐŒ \
+ûÌ*VI2Œ{ “˜,ŒmVÆVdÈ·ñ¾¸K:…›ö/ „V»ùf@ˆÁâ–¾Dœ!ÊQËÌ_¢6±æ.Uk…ìRR”`V?Á<!®ã
+Rd<&Dä€ç×^63â,ùÈ}!¢î (y’1%eƒ¸0ÑÆz*g§cø÷
+ƒ¶Ú†p Ëž ×ÁDÐÑò•–…"YEúM4ïõÍ9­ ïº]ÝÚˆ!ÁUÕ‰uKck%‰›Q
+¨‚¹©3{4 ’‹Ã>§ÈŠ†J×û8³‹„GTý‡öqÑrÔ­,ˆì$Æ…Ë´ràà¿Î 8í‡ì³ýõçŒÕS «iþVf«—¥U®}Špï2ŸÎã£_·žÎ'›qá+Érl,V´”Ç J‰½~ð4’ÌåñR\É6"ž@“Z(!ÃŽ;¥E= 3kF׊ÀŸÊ›sÐ|2&¯:ÜX ;Å£44ÜN mÏ̘2:CMóÏžç}_ „CpŸ¡˜BΡtq7)Qp×®‡Ïw‹’öK6Îiz#.Û¸B±;¥.ªPÅi:,í<'(Ÿ„cf'݆N–˜­!NDûd#K]ÁqVI{ò¨R§ÀÑçäA[êPü Rú߉Úoôw†`9±PH1”ô÷¨ªÕæ¨%oÃ[>~‚nôÿõ‰j qKÃØRtùù:’„‡dpö4fûûzú ä¯Î¢c,–¹æø »c$Ö?aá-mÂüSi{6¸ØG„s°@·|}’¥‘ÌØØUqCvÓI—¿ ‡ ˆ\ŠN ,˜£?Ä<M
+«Ñ~úÕ'è銑õ†ºO¹ù@®Îb›Iyû¾«OˆZz0¤öÛ~ã"ðªUŠ¤³Ó¢?§ÜŒ‚ŠŽ=¢ý™Æ³á
+‚ä¢ò“S„y‚ŽÝT÷îoÃZƒ¬ûÉ)¨ýS8bîTK &:ÙåÃÛ;>>€žNáwÕšâf/ø9º WO†âûz
+W~ImŠ8Êç|}‚9èV†8ráq|«€OÐA·žá>=ÄíºŠˆ
+mÒ¤HJ=ŠŒN… ¦í‘ïò–™×Òˆ¬Ô~”7 8[‡ÆÙü(oö’£qÖ Ýwúflrô n«×dG}³—(¦hisøUÞìÅpËcñ¦zV7ãþ¨G©èEÛ‚rU7ãÑœH‚e⎲T`±.:âõ¼,´xæ鬒åÅêÀãÒ¾õäªníðŒ£ÉaÛ⛺O)h Ûµ¼ª[¬œ[fá e{ƒ«º¡‘¤.ÚÒö}oêvÝÕíìªnº²ãI¹§­8Wq+&«—”¢þr7X˜ É
+néGßP¦­wq³‘?ˆõâDóÎ 0ñí(n 0ÉŒUÞ~7@ .Ä~ÒÒQÜà[Î êɺWÜ«¶ ƒ¹«h°¼Ñ6Ѷ(©àjf’Úödö‡¶ wm;aLKr^YÔ—ƒÚö«hMm“Nª6"›¾½†Ö²Ã=>´íº/¸Q ðÊË&I΢Wé8øOpm/u‹Ùjî¿—Øá®5Q
+‡,uU6‚@fŠ^
+Ÿ
+Òç"8Ø1%À³;z‹ÊZÚ«é(OfAŠcª¹cMAE }屚‡¢†D¨Ùa¦™ïÊîíWÔµ¸ &\æ³Ó(ŽØÛ/Ó×!‡¿~x( vQƒ­CÏsØõ˜øÉ1Þd³ä;¹jˆ< sÅ9åÆ»JíÈŒcŽs{s+ÃPÎÑpC)Ô‰2¨íÊçΙcâl)½0. ïbb<–’¯oñT˜O\WúC÷õ¶L…Øç¢ô„ÌžM„99Ñ> ®Ã¬s÷õòƒÓÿ†þÓ¡v:ìg£½×S+ƒý›
+Â6e-j¤»©$?<bA•‘‚UGTzNÆHc#©Bc°‡ÈÐmŒˆ/ãím­¸þƒüœr¥É:êir¤zÓ7RçâˆÜê‰ô
+„¢ÉBô5¯ÝWAè-Ó¡ð„Ä6“Dk/Æ¡6îÝÔ³`šo‚hšÞpn|Ÿq+\Ô
+­Æ8c±uíò&%Š;™m^¿i-û¦XNKã̸h\ªùŠ]#![íôUIòžŒe¹²ùÅË_AÅ3TõÝ9ŒO‰ jw"*J,ìÀ|
+PV}iñòF£¸8 ooa.È“z¶VÂŒÞ@“âѵƈ¯7çàâávNKõ^¿²wI~bÁ+o#ñ/,šÖ“rUõŸ 7f~ùÑê_CevI|<\‚o«_¿6MFÑ»©| ‚€p‡fÕê÷õû ²C šFÀßB~´«WÊ1d1§¡¼¦Ú_j”Lgæã¤~8 Õ ÏIn︦Tà†ê§ÀÎ ›´â˜Cø¿«„,Vï ÿò˜ÿùÀ‡þ±2и"‹[3ó:*ÖEј ÿÒ#‚ä
+<Ã}BÁáÆ*Þgߥ߀‚#Ø´ì‚ù ¨ãéÛå¡—’D‘¯ƒdåñm±e¡áÈ
+< 1 ‡i¥µ°ý#NAšè*æi”é)RUEÚvq#’8¡ˆ´¢fmXLêigP~(
+^éqo/¶íB=¬¯u9RIi\pl?»!à0Ô‘Z`Ë!©gL©X@0þp4.ç¡dU3f¡I)n³ „Òv™Cy §Ï®½ÏHV_71aêExnÅi#86!CrU?åƒ?„¶÷Îa”‡¯ß@hÆA5±m=ŸPÿß\¸a©eiè{Ó-¡øûß ×ÍDlr½x=dBý4ôª¬¼ã@?Âýþ$'OýyÖ‹¹}ÂÛÕ:’7Я7 Ÿv­,L;™Ø+Qñú9æìy»@?Ãr¤Ø '{KþtñXÏR¾€~Ro=KþúhBm˜ÉÉ€ SÞ¡è°Ørosûiž ºmT)ƒ-m+„uU6¾8dò;, èÂߨ¡\w„V'“8§áF LåXýG9K‰÷@_“} ¢H0WsÄÁÆèZMáÜ)hqˆÈ]zÊž‘#ÒØýÀK L–}Â=ŠC…±¡OHÝ
+Hƈ1ãpLI6§ ¥ k ßd1iDje*DÒ¢zIFÙd(-ïsdBe]­¹ð58TÈ \&k&q³*þ„x(D‹* %õæ6^(ž*×ïPò"¸Ö Êg =o¸ ª7J@r…Ö2´Ïç
+%o1ã°EÆ"á,êÖY!¬éùÅ´Âés"®ºdô`#&î9®Ÿ…²±qÒÃÉï$ÕxÙõý ü–íæ ú®f<føºᶡf“g„çF”è×S¬& Í®ØÜÚTF…¸¿EÆ“ë29û98xušŸÒp<tbº É€g,EÓQÝw_ ÝÔQJ>{åHœÏ¶8› ‹é¡êµtèSÃÒÒ¸‚uÞHVI±Ó¸-»#€ÎrÐÙþíuo÷ñΓ?BaYmËzsNËÆ,Éê‡ Ð˜uoÎÆ•«fÇòY~ÈoÈ,ÈJz¨nt$”·
+òÉV@U»îËp£ð´&¯Ûg7† zŒ:N÷?ÆË$Ç †¢'Èr‚@#%­«—}‹
+d“ûTžs¯Cü‘@ub1«k6..a˜dì¢e+Û†L&š§¶Z³Ó–² ,—êŽSÂÓv¸ýlm¯C”å¹xÏ°³ö£ãRÉ´MÒ!y¢ðy®‘-žKΟU¾œ!sËxÛrOƒ€!¨<@Ôš#3f•ðyò¨
+»œEâ‡v¬zŽ£.%ò"® HI¦œÌ@‡.BûLt{æFI´.‚%×uÐ`ÉÞ0½úPì:ÐÁS—p›ã®ù^v–Š{Qäœê¬C[ðEÆüÃ:jÏ–é[Γ›¯Î:d¢…­„&×å¼a¤ýZ­óœÎuIŠœt¨'[Íiüqh4â`ŘL§z˜8@’‹æüttô¼ñAÉ#%.‘þÁÒN:G’¡)g"PÍ(m'zÝXÇöØ!h4q‡u2´/êm¯Ñi´µvN©ª
+?ÐYhL-g«7=T¤95¸ žÂè ñFo |/DÂi빿£ê¤”ˆéªrQÇW"%Šâ%8kâƒÇFï iT*WƇežLøò¤ˆ_®ôúuõÍÜŠ¾ÓoÐ’ŸG&©(‹Ú9ƒ¿rÛyªÞílßã„¥±ìÔîÄÁ™9G¸ÀŠ0
+ &¾•Â–fÅò1‘–å„É™DË‹
+é)ùª ô¢c(¿ØÑ‘‚lêmD0„°lq}a
+—B´F ë…–+Y„.ðÖ¸îXŽCD,¡Sæ©¢Íi.›[¸
+ä /º‡‡wÚF<Õ$n+øHN
+Ç5>@Þí;ˆ€ˆ‘C
+œ÷ÑÆ÷u }¶7¼q
+Œ£®_j9Ï/äÓ,ò®hdG§ m®ÍM¼Œ®ÞX/ÐfÞ3IŽ<ü½.³¥¹Iwéáy–醈¤ [šñX4:âRÎqWà–ø¯õ!
+ÒcZ¦ŒÝø
+Xù‡ÆIt™ì1/ήª™!}XL/QÏ:O _ÓôÁœ›ËºBÛ–ïÍ<˜ÄîÅóã‘©­Æ÷Œ÷aàpºÔÏowBYðӾåºNEƒ¤?\[ö"ñKÝø Eüºn…ú¢&`ÁsóNTòÂo ¿Ÿ‡>¶Ž—Ž¶BTò3³lë@‡âÂŽqæµ¥U ÿ¹ù
+Lþ;ê›Ø è^÷ŠÄ…3Ô‘îŒÆEñT  i[ŸEÆ9Â
+H‹¡IÔÆwBÐ) ‡›ö“´B—µ;Ñ’\½,M"„0,´–¯Mâ‘x¢r´nŸÖ¦ZÌ!‰IXk¥ãᲸŽG©b+L/U´í`þ4qŽ@ÂML¦ë ¸Àþ»’‘ã±Óh;Œ<å`}9ª f. s¨Øܺ•é—‚KxmËýØä·x
+ã4—\å Qƒçñ#O -Õ¡"ɉá°EÔܼV¯S¥&j˜6Ä(?ÿfôþeBS¶r‘Øjë'Ê2(ÄÆ{…༃˜‰E/d%¹M
+S¹°ŠMzPTÚSÁœNÉ ¡ jœ¶ûtõMÎ0<2ínX V4Dâ
+Šª´C
+¹4_GŽ žë,^—O…C~ÞCòNUW,ßf“-í­ÅNÕ@î)Sâ ‰rCÆlÎtY®“šÂÇáâØw5*÷™‚UŽU&+ˆŸÚJ^h›|Žƒ0Ñ>­ÇÁ]¹†x‰SV ¸Ó$O™š«˜8èfèEù 8x5*`øBÈÒ(ý­?þ
+Äv
+?Ü®ä~yO«QÐZ‚N”ÿÎL¡2£Z0&ó—ǘ½œeŠ|—`)(*·$®Æ
+c²ÚU# ™›<&Ýsä„z{F[ ÅPmÃ"»jÐB}uÀu`j˜|<˜´X O|8^¤¹rôEÁ¦Ð¸œ pb ‚ºY³›Û» Þ“iüºNgC
+D²εýèW_4jùWÕ³¯ï@çVˆòÕåö`r;h`ÙÊ+‘¬8„uoÉ2ÊôCŒi»}xXŒ&ŽÀW‘.þFæXʉ¬…5Á…Äwq_Ÿ`2û¾Ü ö×Ò(JâÌ¥e@)g¼Ær›&«Òž•L¥.‰?Ó¹®ºáä3ÅΣï_ƒ~±ÚÍ´`ÏãW½³ÿAÙÉB‚Ü|œÃ:Á Û‹S?ã2 µí­‰bÂ(Óbƒª%‰¶É¯^!’ EL´_Îÿ€46®:o±óSLFÎÝy«äŒâIR<eQ’´¼IdßNÙ" Ÿ½}›`´euj¼xdò‹Ú5ZÏ®V€¥ê®‹á1u–Œð‘M²EÒ£Ñ3› RD¶~ÈÀ¾­Å‹þ¹îœxoÏžàÿyüø¢}ÅF±Ò\÷¤‰ø3 ‹§æ‰9šGgÅQ¡»<,Cǹ3®%&ØIvÇJ
+Ädf¯ ˆ¸¬ ËwÊf!Îñœê!ӜݗŠäym’§˜r):qÝÂã
+EiÀ++Ô”*_W!”»+óªí¶±áê%
+à¶Ù¶¶`R±âпéÞ)åÂX(˜@ú¤„Æ™4E¦?Ÿ¾>ÒËçïO¿t@fŽÞZXý¢9¥±/ ÔË//"âá•JoC}èc;è$VG¤©"Hs°+Ün‚“d³1¼‰«€ñAPa¸ŒFBœ|ú”hí˜!ÈFÇ¡äÛCE(c²´ëñ°×mêÜþâ‚”‚ªf‹—ðéúHcé‹}žÁÙ(&½: tz³
+stˆÒ´{2N³`ì¨L© Üzˆ<4AtóÞ2ïß Ø\¸¿.¿œNAÎpôúâí;¤§4Üœ••âTBD*J<ÕIŸ„ýèšD7!¤Ux£¯Ñ .Ù  öfçà•ˆoòj¶õ”à-7KFš(ÝJŠ¨r›¹Ç){HŠXbÌ¿áâVt9ÖPª‰ÐÍöG‹Þ/àÏlé{_¾<ê^¯k2Ÿ,Ã5äxÉ'ÊÌý²"A É{·CÌýÊîˆ.yn=áC%,:ï–ͯ5úÝÚ’˜°0ŠŠ(&× •=ˆ
+€ô†ÊTTºY·‡rÅlp4׌
+1ä2‚É/bT¸îª“íó÷«Αï%0&†ž,<îEj,‰˜‘t›ü©è†EèË»äÓ/ša9YІSUI…ôvHôs æ
+H‰¬—_Žg7…WÀî R"ÁËUvÙð”LV
+§€LƒÜé
+¹»pErâ| EÃ¥lcèyã:΢1{-Òhº(ƒ)>©Ë¬} ×8ŒŒýÙjÐtmß›‘“ÁS‡Â@ç—aðÁN”–÷l•lýÝæÝØB`B¹ëfËãïôÆüù…Ñ5 É‘Ìnæãê$͇*±ÁšähŒæZÁûS·u ÏֶŅƫ‘ZÝŒ­¼i5Ão®ìo ÿÕ¿4ŽyO§o9"ˆÕÙŠÌxÚUCÚ «>°Ì}M¯ïžž²P]}M&¸
+rÑZw1í½Mh*ú
+Úd £Úè‡{B* ÷&ÙR4ª9x# ¼:Ý 3¤Í~14 šZ| q–عµñ¤NFŒ*ˆŒÖ2Î*°¾VéØât´ ‰~sð—;mž¾¡"ôÓ0é§A¿;HC,¨Ö–¡¿d;!GåiÔ'Æíê„lƒŠ‹#—Ú‡"ª¦ÿ£¯>üŠ- C’rµ
+ãë‚u{?ÃÊc’ky”ÌÄcҦǣÍV;ÍöH¢F{IüÄ!´5IÅäðC¤ ’h¤ÖëMÑ™µiH2$áØFA@#\x.æB¼ãQ¡k
+h–—Áþ¥*—Æå&¤)ŸÔóOWF€cšÀ¥Ô•²©§Ý¬vcãÔe¼õ8ÝÊ£„`€‰Êx'N Êǣǜ8Å@Ÿ¼5„^ȓɑγÁ/XðTm¹H*HQÊ£æmð?æ-ÍëHy16,IÝcÝ»^{‡!µùéÚ‰µê×ù”bGâÀÞB „²é9ô¶Ax÷ð<(Pp’ñ¥jÃÇì½ÏNh7½ÓTÝfkè #5á8ÈkUðU˧8†åKO%€–WI“äÖ².[ÄJ”ij^ †ëí쳃4)ê½-PÀÍd‡E]€Ì£êçÕ ¹„0@ ßj¦NC€b3žêÈÉ$>Q×zÏȉygÆÉóÖI¸/@¢û8‚à•å°E›8€YMŵ-Áìlùº<«ÓpA…¼–&,Æ’6,°òà÷.qyŒ¢˜Š!žRŒ´òà9²ä¡zœÈ§Þ*¼ü\ÏK)i()±)a
+^…'ÐCkßÉçwU=‹ÜIDB‡€Ú¤‡4ÂaÁ‚¬àZðLAÑͤœå´•ˆ ÀAârçïI›2U”fDqµfRÏ>ý|žU˜j€ªõ)@H\2šÂˆª°µ¬ç
+èŽCíNõ"èFkW+J'}µî¾Y¥Nã3×±>ÕõYˆ+"º²nQký~UÈÝ+´“#òôGÆ—„Œ1"0Á­×ý¤H°JY‚ ÔÈã±}Ô^ß.J©Xá°hAFÀ‘'/€vX—ˆH7âj)pèhµ
+YÕ'ª­Å~¯"æ6êO/á<j~ÊY¦d˜ÎÏ2´KRz;ï3(YLé©åè`} ­B0bKœÜVK@.J©LÖÕÛ:Ù¿ï&™â'y Ôþ²M]àöªfTjm­—71®¦ß: ŸKÑ rw_͉,QtŒ¿$úó¹£H„
+;µ,j©hécŒ´tâõo¨A+¯é“¨#GòhÌ üñ5U·È-ï¯üe^0®ëª-
+àMŸ…Ê€WОvÛö½¨¦-ÞêíuƵšb6›2€¹HôKä*£…Üø†Ïˆ÷Ü•x6ƒ“¾E}?ÁˆØE›
+†iUDsmT)û,@]|N{ÕAí³ÌÈýt)©<ùyÀïÆ>˜Ù³OÕ»y ñ؈/Á¦5Aˆ0*D€æ2Ú-ø2òË
+ƒË(Nb¯ó7JY6,„xlù%Éiʘ)”ÁGÏê„ð£^?‚j:|PJªÚ©äwXÚa*|òª>d3Ò¹c¨Žé&Úüîßß‚
+¦“a"w…ˆ‰}‚؈:ÓŠ”Ë2é²OÄ®)"Ú9ˆ®™@cë9híµ"¨
+]DÉÐDqËu:Ô œ«äø¯Íª;µ1ÖF·e„ôfg_MÆ`³qk§ ZJÑöØKw³BµñÒî£TñO¨„oÈ¡„Xî´?‚üžô7jÓµË
+’ðEÎÕ‡L»úP-A_ï}°IÑŒf°*¤×gÄÓÙh@;›þyï£Ð"ª:ê¤QçHWÜ8ád¼1ŒÍIL×Î
+'ëâ-™.ÔN
+‚|‘Qæàd¢è[ù-Œí¡lbîÜ¿¦Éþ&U¨YG€3z¥döacJÿ¹ð¯Ÿóî@zœ¦ªíËçP
+ØCY82Ü$²1 Í@Üð¤–zãgP¸Qy
+æ¼yÐ/x¸gÕÔn ÕŽ¨ë@’4£^J0"ñɘ7¢½#wFŒ÷AÊÈAtýD჌W¼/vMCe„œfÄJq"@Q#h“u"ÐSFlü}PUÌR’Íi ³L% b(þr[,e‰ßQˆþNrK¿»Ímæ¦hŸyìPN¤y2v “s´m‚^’•¦° cdÇ
+^_#jX¢ Á2Zq
+D‚¶Éõ(ªnU÷ñ5Âñåž¾¯øv-Ó,®Ñé-“%b+&,TTÑrÁܱÀ žÿá—[qÕ"³L0d™Ï"ï‰àÉ
+
+¼í7y:#Ö ×€—Q‰êÎ+’—NxC
+cÜu_þœŒVÌjF×xiÄ®±œ_ÏÿäÎ@y¹Àã¹I cqŽöðú€zwõùc8µ ™iN?‘:À¹)Q~ìψ“¸«+>>gNCŽp}` HM:… Ól¥¿Qgß?‹øó^«k¯ <n¯JÎñïº R4E 5‚¦Ü¸Ïg±8Ÿl !uIÑœQcÔˆ‡ ä™N@åâà ]5Çœ.ç†3³Ÿtè"Þ¥ñb{}Cnæ`àRÑÇ"úÚ|Dl¾¸pQN±HÉÚ !á~¦ºÀ1˜×•§Ñ¥óhæ¼WÒDEÇf²¼¼„F,.Š‰E˜rÆW3ÇWTM<¯¦öü>»83K%çüŽõÏnçÉÉB·°X!Žøj¥
+¿Rö^Ú‹~ÉOË›•zH
+þ,ÔDÙ&ª² D{„LCÀ‘˜YBVLûúã÷}x.6û»?§n”ËMv“O‘SüOŽr°ûèò­ú,<Ã…ƒBý~r#x¢â«í Ø‘~­-FѾŠä¼¥ÿÈ5.ZôXÌ1«ÒHd9wþ_Á}Ô…Æv¡®5Ÿ]€…GÈãáTgŽ¯K!vðX Sb¡;U™æDçÇ’â6À¾ÛEÀ>ò‡,P†ÒB<
+ãGÁ±Z¾ü>ÏÎVýˆGJÍæaÆÌ
+Z‘No=3ª1Ô øœó> §†t õ|‚ñµdEmÈ™Â>.5ðÙä½8Î$tƤpÌQ”öœ‰Nfü…ø<h~5çLê
+Š5ÝÇAP©Ê(ž¹p?<kíP Î AQÖîX‘Š?+‡6È´»ã-Š`vM4Þõe%.&C +ÐÕÊj'@
+Ì0Ñ/à]2à£`D.X7x PF©EdšíTG•ë°P›‰ª\ô߀l û:ô†MXøä
+éÎÔ˜1EÖt˜ª‰úòTmÃr
+}Óºx¸|±-æK•²õÁ;„IÚÍ!{+<¼ýÍÎÒ#v¾R| ÜžÁ¿Ä¥\(›g©x
+ÀBè%5‡º 0j3ÀœDG2Œx4PCËÚØ)[;Që:hEŽqP@²x Õe7#B@.!r%ú†‘qjÙ»ž%£¨»‘^µs¦)/Žzˆ*FàOE¤jÁÔ¦Ù¦Od­:NÞ/(bA ÅÙPѤ`•ƒuÏv²-¯‚E¤r" †&0)MItô®q•h(Vìð&³ýÛAÀÐIi žN!"]ȃ4,®„<©UŒRÞE{2×h/éÃ"E°‹ zÌAÅ
+ðÎÔŽ´gpk͆üŠ\ÚšM5z bBÄŠŠ$ÑáóÍsÁ;é$P·¤B Eº}p:ò¹_‚<ŽŒGåu-£î /
+Ú×ÉlËH@iJñË7o³hŒnSÝ%AŽàL!t"̈́ДĖ!¶²…„|h3˜1¢ˆ;™Ó„
+ÛÅ+ ÒiÖBÞŒZjˆ-K B‰:±Ç¾pÓ’OgÉïk~¬+)^]§11ve!ˆ>¬•`Ãa/.)Ÿ€£XppeÑ#Ý=‚
+pg½Êë;¶€q™·6¶’p°ÎmŽ‡oø4­‹¾šÈ:¹ÑÍ“dña½5v’´hß'ÐÖáoÛJÜßp¼ßYì7z¹·kLU‘цTŒy $¾;ÏÈwÖ?8c±ÆÔu¯î¥»5%êæ}òÛ7{»½ÍÙÆ¿àKìe”óc,šÆb]Ìù©»Ô’omÓGá|¼sËiܾ!ƒ°láƒÎ6n-´ÏÄ¢AŒ>è
+`nô
+Û‡^Iê
+g
+C!gòpSj`G#½‡ù„¬Ìr‡G‰ÒÀ6LN€4£¸ü¢Ü^ÓÍ€š,Æxß
+ø Ê—Jîㆊ §HÂÑúŽœ"É)‘qª!ƒµÃ¼«BpX8Ü-¸#E Ld€;‹@¶X›7W¦j@ö²ºf^‡®MÁ.ÕkòÉ•ºªÏ@ ío7æNÌìk‘zAµ˜n¦w?…çPÍý?t—Ù•äHU) æÅ}è°Z¬+ÿ˜!Hfw²öu}tˆ ‡Ã=¯½£ô—mí£Jâ=HS®0[¥ ÇŒõöˆL…õ¼ìŸ·GtÊÊðÁƒÌÔúÛ>Óª> vîGwmëP‘d. ¯„üŒ½Xö³ó©Ê@–·å5 £Ê“íÅû®t‘/Þ6¤»ÉQin7iz,1ŸÑC‡–ú‹ÇJ²h=7¤³úÛËt¥“ǼÕ-ì Èí·‡ ÖS »ÄA:º)ƒ
+™ê©$àRj©Ä@,™uA“šó6Ä5™þ¡?嶰ÀÏ*HM"MP_ŸßÔMË·´¼¿Ñ¨¡gv1±£*Ta¨=]£­s81;Ãë¡tèn<òg<kŒà0¼–X`›§+1²H/6¼Z£ý¨1Q
+µ*·Ç]îwg‹ïMhæ{£ç4€1ëÙ­"¢42vV“Õ€x™6qCMç˜lúzeÏs¹˜†g;ª­X2µ‰åÑdYi²À[Ä‹4“Zóç4@? €Çc8I
+×.ßFå¨Gj†Â¢¾Á4qäL#nÛ€So Ä–ÇpÞ(E‰r§aÓǘá
+96®ŽKnvTpzÐC:pÆìîи]½¡ú`…š.é1’,ÞSv´êbÂïç%§^ˆÔqÝ%Çòq¢ß“¬NàX!Š»"@YIfØ”åÚ5VU3•!#©´â –•y
+ä“ßÓÛÓ+™¹TìæóØ-9IKºß(ÎæCáú´|‡D¢GFde'ÊvdÞ¨°°ÅûóŒ|Þ¿ãìi„"<>€«ØMÿù¹CËœ¨Ô@cäß‚ê62´C M†S‘vEø&S¼ƒW𠨫éIÔR<oŠx9,ÚÛãDÞÑÒÈ7~ Ô/û˜øADŸAÇZnXojoý4A>¦ëô9krü·
+'5 òć43öyHŸ¨:˜»¡¥iŸÛpâþ5–ŸU`ÜÖT§F3PbÞ/ÃÉg»òù´Ô·—xûÂR£à¼Ö¸®ÕM0ÝÑà5¹¥mNå#¡<¿ŽP"¼¹‹:½va4÷J}
+
+$·pË• ÷( >Šƒ‰²ƒä®Bøè¤3^Cu@]tBšî'½¼`E0yxt_´p ¨Œý€è½LÊŽ3Õ}CŠy‰aþöøïER
+¹;¥µß^¨a¡ÎyB×eLÛç;tìDåþ‹-H?*¥óßµw]ý/²Ãœ
+d¨§HŒ"%e
+h8ÛHGñnÐÑ– ëM5Áó@ÃwnÃû@#÷ ln:õ$pø¢SþëìwM™áKƒEÝûª¯j£h®ß0H£"EJIútµ «‘Öz1ù?ßMwåTáuA2Ö~9™—&è7úAy‚ÐDRn•vtÃ/"¨µ2Ž.ÿÅ ŒtU cˆÝ%n(Cƒ\'DUç…;F§ù Òt!<,w™d\*0̳@MÍe×Z yoÃ&rôã ð‘³rz&ñŸüû»¿ñŸûúú{ÿþSüý½I¿ œëŽþþó©J4œU9Fò%m#•Ò­dïúx‚D4ƒè½ATl1hW=ˆËð×X¦ìŒ ¥Œ ý-Û(Ëšì6È/"(6#ªT‘ºPX¢7e;&±t%«–Ô²¨à6쉮¿Ý
+ÚZ³Êm´¡üž|y·äå÷@OäNFõƒC î“Ù³Z•–NÚ &<cƒ¢«ˆ¨kEµŽQÒ5¡ z-´$0iëD…%*Ô0¾Ûˆ;l'‘wø>lNO½—£ßÆñ=ò¹î­¯Íª°0
+¨ÜÉru'þ¼í$ŽE«¬Ü Õ>ŒzvÉB)ÑÊÌ:A@·NŽ+Ö(+ï&#8n{ÛéÉ꣕¼¹IÔ:xWÖQ¹ZWà=í
+}lÂÀndbùHš^wP»Rœ¨q²aõ&¢œtq¬ ³«‡½c¯Cº3ÙªC†Ì§âØ©;ƒ'­-vâyb'Àöä*ïøÔLÜ::tÔ"•Œ·IÑœÔÕw2îk<O$¢Q?&Bká¾¥m_z»/Wô¶˜2l*EŸ3"Ey‹–‹È$H‘ÙÅžìð-"ël%ø#µàðÏÖ¢‡É.Ë ÅxÔë߱̄›HAÁ–F‘Àbh’Y|néìFcõ\º‘IF’E’©œÜ&îIÑsÿ$¢Bl…=gyî8ËÌUÔÊŽsçѸ“€nÄÌåïÇk¢ñzÛgy½¨˜uÃ9lÙ7I~—Éxä¶GÃÈ\"Éh®[BCÜ«”šøw·iË=O=®¼MŽ¤†yƒü’ÉÅCnc/¦.
+ê%Ð õÂÍxûšÍs›MÙÍÆ Çº[ÐïXÛ|Mˆ-Τ‘;þh¦ðØ*”ÐŽpí*B²T¹ÛXO
+3Äu7¼9q¸ç>
+:žfY|t´FɦH€÷¨5Zˆ`x(îØ0,G_³éj~Qlþ™ºÜ%–Ÿm¯\ls`-šË/kGï*lÅÒðþ\­‡øÜ*¼1t3$†RÐ1ýj…ýù7,fTéRîË{˜Ògù‡×ù˜c?ƒ[¥Ã Âó ®b>%$‡ân~ïf
+o
+«Ä´›žc"…G,£E• -/Jƒ×ºe5’¦¸˜Å°P7g£¢Ôoï¹Ô~4ãR¥À#\•¦
+ålÄS±'#jÙñãø$lx¬ñ¶<î€ëjBJN„Іµ˜Lÿº=I8׸{.ŠÍMû¹¯âõF9TlvˆgUºíLûZ–O4K´ ã<áˆó0§ûòLÝ]ÖïÙ^§.4ÿs !÷DhÅîO L…àhÕ„µ.ÊRÔê$qD÷¥£lŸ´Ó­[Ô¿ð £Ö¡âÁ"JÆ¢ÈJ¥Þ- M!‰7æ
+üR‚`(}:`úýÞNïð‰·*ñM{Ùß-oÀh4Š7%é”WNV£2@-§Úvv`XJ)qî¦Qi®¶ãd¿F±¿¥&írÓH+ë&¥ïÏ’¯«qvÐëêMy7®'ÐœãFô;-—wòر›ŒðŒ_W—ÙÀ¸®$  {ÄùšRæ·³.¤—kXº];õä>[Ì™ZÖEÿ"%.~ãé8+å hhÈ•GíÙ)ƒw%oW¹µrlиØÛ§t«ÕÔ¹í>Ö‚oà·h"~Ó=~o2âo@*~Ïù6g-oeTŒÙf¬ë­ü gÄoLWÎÁŒ ²ÖVêL ¥¸O»³!7Z}%¿Hâ  ¥¿$<_…sW´ E³W_Õæg6o†×8k°v8‰)üRËC9i©VÛ\¡ñJ¡ÚSQ¦Ã H[/ÝÍÖv.½*LD[OÂNäÐéõ?t—Ç‘,GUi ¾%'ò¬îÙ °—모$AQDMA„CŸ_ ¤Ñ{àh%ÚôÉÐ4 d¡eVI3Pä§×?ªÁµâó(œS–j®Æ¨ Sá2Œ Bå3w´ƒªßš"€ñ…O%…ÿ8!ï¬-šºÈ5±Šeð‘&k9±ÔG°æ›Î°*MÚ³ø)—„1£=¦â“€™¥hån,·C££+?‡5”øö¶‘çþ=“ƒ”M~³•þ^~DÂÁgÏbXã›99%;ÊßxÁܸ¶KÉX2b^íP?¡dS·¨V{g2lá Q^‘­Ÿé_¹k”„.V0NX:Þ<‹q¦ Eè7!SyLm˨O›—t”KÔäÔ$¸/]ÕÊç jÄ´D¤ÿ%yÅ‘sd‚„Z-º!NU¦*%$šYÛ Do_1´¢8kisÄÇ µÒ§Ë3¶Ü0åGl–-Ø ÙðuáÒ®ö£v'IÉ­"ü´®ÊÔ)o~1v"?Mqœ=Ñ·ÓŸ´kT`æ ‡sQ²Á}ÄølLÍß+c:’Âß5–ìe~¿Á ÝXÞÞã`WHúm NèÐoÊ#%` -™vb@‰ªqØ z[3_ëøØ@Ç¥/:½ùÌ |ÍÐ
+:CØ}—é:ò' X %;`%‚a¨MÀ¸,ßèD̤hZùÝdüf¾ª¿ÃÅø[{ß ÕgU&ãÛ6F¬ÿÊß5ÞãBöïDPÒcÐ: NÚ
+j:qò!‹ÁÙ4mUÿ{4[ðOT`™1U­ØœÒ50 Î!óôì,Š~Dت0A‹a7\=ššIVë“màÿ°iJE¹®¨wèÎø_\F¼
+8#uUZŒ2Ò‚°ÏDÜê-H™€J+Døúüõ¼EcW©uu‘–`%æ^gK´è|'çTáÒÈCÛ‚È[5Åb^ÇyõJLÇSŠÍÝe&â¿¢N}Qý-Õ!@ßliÀÒuD„ q}Öƒéú·‘õ&
+Ö#ê0×F1Mo§{C¹NØ.Èt
+ZÚ(ÞeÐ*B¦Á¬F£P-0ï(SZaÇÍ€²ZtRÏmúw‚•ÁóxÊÛdP-M³4¸‚+@MWéÖßöFš€ ÞcxÏáå®â~óª¬Y •“©ÑBPù³bÑ,à-7-7¤e÷±>,„¶ñE"Ž­ü˶$)ý d5‡‡ Û Å¾˜ oËrnöÞË›‹ÌŒ³ÐçVˆÀḺ‘PžrtQ•”¿›:Þ^C
+èò[$æ5MÛÑšCP«|`Ó0Îwu$•È#‘RÛ‹ú˜ hª#,£ÿnr Xòƒ*Âêàãef–= óC묣yŸLfn´3lÿþÓ?tPSÿ
+ä_5<ùk¬sÐC¬Ì
+t͈NAï·@>p¦C/Ó¢E©€ùž ,h=ò7D£&’ˆÀÁq•§ÉÓkø³RLÚ1Ä4\}âvcrËâ5´é$oÃáã"AŠL͈¨nfƒI+)VŒÆjÿìä¹Ý)¨]=¶t B3µCâ/"‡ÊópÇ3
+Å&Ÿbûú÷¤Á¤wwWv ¨dⶭÞ–VFD y–UkÈ~ >C¶|ÁÍʃ^Z®©´ ×2
+qbTÛö,Ój¶¦5KWÓTy¤PqbY’¼ƒª<˜x&äµø{AÁ7 4D8VçÖ^\Î~WjB5J¸{’:‡ˆ
+–Z0ŽpÔDB{×þæé(¸zpÔ)
+E€±–ïxËdtü
+£åNuô„„j+2»”
+¤©#®ÞãÔè ãBgëÒþh»á ¤0¨ $¡Q ˆN§(¨(6¸ÒÛñÛ«5²ü¢nZGW\‹å !åVDO1÷ÐÜB‡Ç.ƒr,¯˜³óP"±C€ þ©î¾ë{
+I„"¸hW¹°F´L¡\Û
+<´ Y7WC˜ r‡œàd$>ŒJ#¡ œHÛË¡Æ6
+ÕšoÚí]Ç[m7VŠZ·#
+"ñÆõOȸ•#ð‡s OÕ';èÏgÛE9 Ty‹@Ro‹á±X*‰íù¼*Yx‰
+DgÒi£ª¡¤ï
+ªËíUl!ïrÖjrÉyVm<u 4DeV”eiþ£”#Ø›BøI¡É=ÍÉ”Ë@H«X…{7
+“Ñœ·³x ú±m»ÁøÅN¤åûN]÷Ò
+^‰ƒæ½Ž#AÊeìŒR5_¬{§aUºo”K&&€<ĉü-'¨r¦¶èL‹ºt ¬³f‡¾àƒ¥¦ÉêQpØŽ
+Ã8$j'JGÛÑŸÙõåkË‘¥rtµã)ZÚë–3ÃJž…±F;ÒBiÔp2àXU–䳿wzÈÒ&E§Q<4 ÖEkÀY8æ) Bœ‡320³^„7Öc`opî[Õ•ó|̲å²°iGÖˆ#„ Š@Ý&E¨‹ô H6¾äv+ogIˆ)ÌNK¦¶æÝ!§æ@…åšgªVf±@m5”5$"+$`£†Þ‘dõI¢–;+¬ YÜàØË„Q"C0cCT–z#!jÙÐÍŒ?  9¬`*hÜ7z"kLG™,ÎY©-nN|¡èù3Æn¯¤}%ÀŽe’øÃÚ©½A»Ú”žbÎwA¸ ÂÕ tUüA4®…òÒ'Ö´ôt÷»2ä9D‚5‚Ô®ÞÎBÃÑå|JçÑUúÞ€cjFÛž˜#úc ½-" ÈÆ hHc$<Í5s²]^Ÿ]µÃõj‡eÁvºÞC
+hür;= ˆ™YÄÁ½îÂX¶Mñ =h‘åòÎåºwPeT¿»­²—IÖߌÓWª<„´(½Ul”—xaçyß©;>—ãà„n4ÐöΛ1²Á¤ñFòl³…„"£ªfÀáײ õ´ ßD'”¤¹b,ðB|U>T*
+ TkÏ»ûÿZ½OWÁEª¡8@X Sˆ(¼¸²3ê‚a9#dꑺW¦žùÉÆáhSIzDG·¨¶%ÕAœ™ pe0ƒºÅ° J—ðc9<¸£D —ýÆÌ×Õ¬yD}l$WËâwzÙYίJŸÃç>oµì‹bÀŠ8˜Ãör”òdíã“'
+>±,tãr=÷ò|Óœ{²UÎj¥Ÿ3t›ÚIªVÑŸYÿPÈ¢¾®lm劷8–Šàtu
+2
+CÚdo ÿ%u¡H\ó øTlVa$Š½Ùl)d3_H9cD-¼\_°Ýap@{X0‰¢d¿•¿¡sÆ"fÕ€ª9
+U—öý•ô¬ô62ƒu#sÉüÿ
+¦pÏa¯²u€WIwá0WT/ò“X]z:ãpõ(¶Bš,#ªÃG¥ŠV)Uj@.hR>¶¶“½(úf}熰
+<`Çn„FRWåˆUóÈaúÊ‹
+Tñ51+8ªY¾#þ=éÖö™!Ò¸Š)eJi1v–‹4EˆkË4Óør]UüEŸ¬y>ÙÖƒÊTîAþ:¹UjйF<f H»œã ð÷‹d8âôHC:¬¼& :ð%òBõŽÛ#Vò1‡‚R*r½#kÄfƽ>¨7¢eõy°-y)€™u TbÓ ú–Õ'¦æR“tåØ3òàð|ªFT-:Ê,¸’øDµ…ãÅRIlLJHS¿‰Å–®œÒaÁ¢Òaž[
+uu¡­0!P/1;—-À(ç$õÎtNI@Ò¨º[PزŒ°×ÙK# Öé怾~Ö…2«f¡FÕ õë·ÓûÁKŸÑ®Óº2N
+¤ÃdkpÎF`:~'ùj îö{!S²–Ƶt®^>ˆëóÂk9¯šMΘChq
+‚º»Í¨¨©:EªÅbÐzâR<ÀÖî½Ê{VN”.µ€NAb4;ÇäGÛù¶ŒRþ]‰eëLpZåyîU1ãetÇ®´Ü12¤
+k…1HgSAœœâ¶'g ¸dUD4}cóbFá’ÖÄ .¹f)C@“Ϭås’#dËnn'ÍB‰(¯R´(ÍC'©Ú#öÑ؆u!UAâØuH‘]ߢ9tmØIíA²ÃØ•¼¡èEËÆr;…^vç‘}ññ­OO«ñÉ“rº
+ì³’r ÆG¯30£¡ äecªïÚ¹þÌÂÂrÊØD¤¹[V?Ïù†%#áÅÞŒB½²<zãTkì°]$R6Übk"X¶Öð¯ú>Êp­•?Š¡Â
+ Qb7E{¡7HWBbÒa,¶åMOÔ¦dÙb½a«fè3f»p5a ìÿX/·9*Šþ•~t"×½êƒ';A(”("<Y–í â‰Ì)ÿžµN}=ô@^H2»kw]Îeï}º\€Y[jŒJ¤õš‰Ô_F9<š“Ñ8tþÜ~'
+÷² (&Õ%åÐ
+ÎŽbÛ’î¨X[L„J]\ç[~ž¿øøðùû7ïï?¼þøãå7|ôì×Ø7–O.Ï¿zøøþÃ_/Ï^¾|ñæÍß}yÿðZì'—_ü-?ü÷é×üúúÿ´Y¢H‘Åÿ~óãþäòÍ[þ0.Ï>¹|óçÿ~X¾<yÿ÷˳_üéõÃû^}ñWxýþëÏî¿ÿñÕý·¯~÷öýÃï?Þÿðý>ôéo|ùîûw¯Þ½}Åÿq¹ãñéòâÿûá§?~ºÿüyüþ£¿©3øYûQ‹µüïkÒûЮcœÓKÑNT•ÄÆå»Uq K?Þ5?G‰€¤†r|)Y"šžUDw8ÑÊÞƒrÝÅœÔø¬iiÎðý
+;”£:àá0ÔfJN„æè.Øfä¢f¼Tqâ[Žxæ&f.jz‹\ƒ¶ È"Š©€ò¶sE2’:Eð=Œˆ¬.ÀäãÝ{ôˆrœûs DÒ5f¶kIƒo¯à¸|¿ { DŽæ:o€›M'¢µØC°O‚à f‚~4m!$Œ¡a®–ðVŠ9¬•Ä^B(‰79㘔“’ƒè1¸ƒ˜ø|®©hp¢g÷ÃwwÆ”´*…N×ïàŒ¶Uª&ÞpOùãp”˜ˆ Ë’d‚)È«lUa¶É?GÒøÃû°ÔŠ.ÈSKxDA²?v-R7уV¨
+š¢´ˆUœ!çÐKÆ>ZM9ûw
+‚>êãAP¡å(ç$
+4\L4&‚6"Õ"¢®Ò¢yb‘¾I.ö¹¯‰‚Áñ°²f
+ ëRñ^¬ÇEÎ<1'òl3ò˜F¶1Â"†RJW%Šq9²ŒvÖZŸŠHÑA­ý¥Uek
+ªoÄ8ÌmÁ¢´ˆÃ³AÐG æXQg¼f'(>Q©Gó‘_ˆY|êITRîž„ÀŒÝ4ì›A#‚lm¢m¡ÑR»úA/bÌ} p ZšÑ.dG+-ÒEjØÚ¹Å,è­9—’^ŽI¸ª”8›¯wÇ´M‘` ÃNÙ*;vGËÆ¢œÍ\Š¿JÝ{B9oõ¦=z0øÈæ… ¶gЫ×ÙïðsQ;X¶‹‘f #VÛþ5
+‚Hîo‡ZáÆp0±Î}»ë[è!a˜Øu¼Äã)Ti`ˆ§O£stÏ€š¦SÉSdÞ+LlnA„UyùÔƒPÕtŸ„‡ÁEDé:‚À½CÆV²;›À2'ëQæêùåûà³³m°¡B\“tò,¡èÐ:âµ;Îw‰â÷ Ô¢3@IפÛ}¬q=v­%4DÑ¡/´DP c
+€Fܤ$Šý¦¨A8E6u(p"øB®'¢@NŒ@ÔÐ2Á©î=ÈýŒ“¤ä8iHËP—sÌ€›Ýoiw)žÎÅaâ¡- ³[4† Zߧa¸û-"ÀdÐ;š¢©Üî#áv ’Ò f*È®3„ᢠJÌ<G³8.èæø ÊñÕ§Eߌ@™B@´Z
+…ëv3ëEBª¢áû»ãЗê¨0.èi€ËœÇLhÌëñ? T¥£E-ù„S ­ÅyÐáÜ©Ó}°HŸXöASé³kçÕè‘/©ã@qº”Š3ÍWåÁ½œpä,#Úd*鲈..BÚĬ2"xí¦¤“IpX¤‹îH¹—¾U¼\´ãˆ~‚¾¥k阡Rô§”K¡³˜g»Î»7(ÇÒÕõ›$bpÑlŽ’ù)#ÑÂ…I
+ç³ó$öR¬“^+ö9«€²ÕXË$Ŭ£êÞÖI…µô‡äùÐœ”<Î$AD­oy%úw2ÛrÔ¬N*B‘ztf&6*rŒY̱Ë4±Ï–#èär9Æ«åPÊ}ö«uȼš‰`í“@¡áÈn.B3¶†7?ƒš®9IÉ̉¬XUi°3³>
+õ=w'â>A)ÐF±°™á}9F­˜EoŠ¡SŒ~Ù9]GFxYì†ÀB¯°±ÏôðX¬à<‘'GNˆýŒA8(NDü±Qwa®Iܳ=V¦"@”2.ÝáSªD¨¹ˆdaþ‹í2±‘É¡ +mA#ïLÙ3>¬ýAªj0-a1ÀþÖ«¼H¾D¿í« ùIÐÙW¼(r‚èÔX¦8Œxå‰/Û±2°H8 <±KHCçÞh¥´FZ>¼ ¦ÂµíQÌ(¹Æïˆ?¡!ŽÃB i÷pu"*zï„›†ê@1Ú—÷¦©æv§Ñ¸,oÇÜ8",:Û©ÕJú¸•Ñƒ¨W ëU Uo€B#"¹@ûx˜b“‡¥‹\À@Ó\#¶AÚ˜?ÎÓ@ t©U¨)Wtæ;–ž…aûM¼¢æÆøƒ¢éW NpÍØ1ðhù÷+EW®Œ4? ‰ D¬ºcR€(0 ]JKé¶p‚„Ë` b5¥læþXÞ“÷(<ÞRhË
+7ü¶ØÑã.¤¢–œ®HL×åøú’´°õð½vø–¶Bç ±ý†èº’ý-Ä?Ns퉸E¹q¤3Çá·ø«“‚âpøAìgš
+=R‘zÿ"b›ÈUd8Þrmîs¢·æ}$¾«Ã¡“–áƒ÷¡Û¸6è OÎI„ÌÌíÏ)sˆÌò¤¬C=]–ê­ú™>kDÉ"bð–Ž–žBJG¯¢[.V³ó@ÄUº D×’½¸íe*Z²ær*­3¡<cEŸ„ζ_ÝH€Øc}ÈVÿv×Q¸ˆ+l6³ðÿÌŽ29
+>F„0X;B¾ýÇwoqš=üË@ìƒG ‰$8§ò¶
+'
+“D-`˜îÞžã MñîE;¦ÎÝûüE!(cÇ<•èr¥O%»Ñ&žšujÐâƛٖ¨¼ >í&qØn#Dç¹îj‘Ô¨
+R–ªÇu˜Kš uÔu¨”'ŒòT_3î®›…8óÔþv.(…)׉ùf­õÑ+ â0Àš,4U \¸E`Múw§njEèX‰²ïpÚ»ëp0ºVq'u.Ì ^¢åNaVA0­y§tRœ+zïÄ,Ùr‘5KKJaô¤b‡³„<;Ó1ÎÄ(7£“D³ï|¤œ÷öøžÛb퀜Dx,¢g£ZÔÙN Ï7ûEO3ß8„ªS¥ŒçÃ=AœÁ‹¤É ±Š œÄ›Î„ \qIø‚AÇ6¶ö÷s,ÍVÈ%¹G,ASáV¦lBºXq¾"BË“ñÞاbEPíý©ÈÕµºAÈìZyØkŠ`d±?‚n•Ça:šÙ¢öÍg¨&­'à3¢µ¼|ÇßÑ¡ˆâÈÌ—?›²PðHYü—ñ*:JG
+ÍmiM³B&V
+"bO½ –6’k`íDÌõU— ÙºbœS .N·¨rŸ«P¾—Sã3·eÜÄ r±
+3ßãœ[[‘l-G`½@ЬCDƒœî¢ø\ÊMĶñ›Žè®Ö|F¡‰qQ~,‡ë k‡òã­$E³ÙÒ'A‘y ^µ™|^Ô¯v¬ ¹\ãŸ;ƒýAѧ
+âĪ̕¬öÆ“i` ×Žy3ìÀ¾w‘$¿¾ ÌèFÓ°ÿþ
+ï(0sÄ©¸ùðTÌ%oØ¡êÈ?SîqwºÝZp $l$ìK#é- |ק÷(Nµ÷¬Šö„È®åKoÌ$F‡S{ª‘ä¹úyžˆàÄCœh¦Ðm‘Û…ùu”HUhÉîA´A3íß/ò÷u#çq*BÛX†4i|ÃN×%=39#ìOÛb¹‘,l$—¦kusZˆ†Þä1ù?ñv8¹_Ò Y¡Ð\ÇbÈêKb™M˜à­Ï©R0G…Ö¸g¬ÚløÛ‘'8’0ÆX˜­-C–®,ÒÀÚóLÛ;m:¾wûƒÄ`ˆãúûûáþˆ Î×júùþªcnh©W(p$ a𥷘¹_;‘ Æ
+’n—“OÆ*—wÿ|\ZÍŽqXùó=‚NOÄHþþFŒDø,(5
+½0Û"²ç>¨*sv¸(Ž&íYñzøàcbž…lÃåÐCLp)ü³oø°ØÕÐqÌ kqYÖûaÓ´–õ)LB‹¹=&Y >N‘¹5ˆô}–6wŽ_}‹®P¾ Ž Œþ<ì¾}àóPþV°c;Ú'¤ö™Ýc"˜$ø‘{t€ ƒzÁH•ó·E÷»ÁåËevhQ+×o\Au¦ßyñ“s]%þéÚ+‰D @\©K,V¬a35%ú6þ¢ˆMrrUyZQ´Z‹u ÿ"‚…{"0·"¦î@E…®¨¾Î3vò\ èªñÝiÒD¢PÎqŸ§ÆÏM-<žâÄ¿£Ù’Hãý½M C³—Ëá¼Ét6\Ž¢ãA¯†æ аh#…õ »’G¤·x?±+O t²JÊê¼Üìg÷™YèÞÉ.ÂðŠ‚Õ>¨Þub'¼,*‚†]ðDÆ,ÔÏÓÂð@ž•ò,åΑêsˆ;(›·‹æF”76Ú ¯ˆa¿yF…Ä3®žëC”ñS«û-AøÄ|Çt]õ·Év’[qôICÁ9w@¥oáú7>høÐ0~åÓMQ“sp™æ§f±!Næ‘£š/$›ù,«P”iÊ•Ûù×îý‰ˆù®YˆW~Ynåÿ
+H‰Œ—=r$;„O ;ô¶ƒ?
+GOíSi† ªJ¥9yü}ÒÙªOS­5ÒcOëEH¦ ÛYD«N²Q6ÄÝUjµî]€Œò,s6™œè¨URFdБ˨£Y5'WÊm¼flD7¦Ãë&ŽÚœV¼Íý˜+dßdÆË„4¶á/ΙB’ÛRíxL§˜IÔW­Êì¤Å+åìÇk9À‚æbz¢Iíµ÷ÑDW”NÑÉ¡¬sø#º-ZDj¼ˆh+µtIùG‚i¨  X'/¤ <î³øxçÖ 1§­jr!”"µ‰QQ’iÒHiÙ—ÕfâÕ{µz@f7’áVç°c!OÚŠxyûï[}üÃ…Bzеøî
+úZ<.$Ï@È÷ô©#„zÁJ’=l#d¡|ñZ]ˆ.ƒfpgè†ÄóîLþ­zȳU³áJÞä8Ç{£’”„>[çT’Æ×(‡ï¬¼¡ÑÙ4À܈¦ê}@³ýR+CQ©÷*‡>‰†¦¨ƒön èãH””ÙZ5/.ëÇuE
+ çcŤ–bT̬É‹O¬õÅ!}
+íæÅt¨õ#=5´ÉbÕŸuU¤S¹\Îs‚–sNëëœJWw£ošöµú¡æA²è¡ÏBTJT©Q¤Mmœr¡ =ed­ ¦Ltç! 4"UF軆¶vtDÉÇURm(ùÜÓ¢“Iã9Q=]à¢Èg[ÇðˆæBª´Ý‹”§V¯ÊªF©\n<—4ŒÅ;QªÑ¥×)»ôèBFžŒHxaÂô“ÑÌÍVa3ävät ¢Iªí_ÔáûL¾“ú6“éA×x$Mg:Kï¥Of2T,†lE±ò™¬OSB*A»2³™¬¼Ž
+£e1=_ÌäA»wîòFžÎä±E²1OèŸt*‘˜IÖϧò“ Ü{Ž ºMå t™ÊH]‰†(t«z:•‘LH¶À‘%™ÙTŽîcÌurH’Ò©,TËâ?¯™-§4:_Ÿ´•nîdcY™–cBÿÞ©â‹s„Îdʵˆ<ËúDàà;m/Ò^Œeè…a!ÞÑj:–•qJù˾&÷e,ß)˜Œeˆµšá6F=cºŽå Î
+M×B–ù=;µš
+³±èêÇQ(€/=? Æ C®gó •B´9ù°
+÷à8©ô˜µ— F.EÚrjCèWÑx<`G·Ì Ö¥¹Ï¹¤žf܆& ¿¿©ïGÐÀ-hw–aŸ›€ÆíÏу (‰Ï‚exüŽú·ŒE™Üƒ
+ËzSvÙ¯@±áÀ±‡5¯¿(šNK¨² „©ñó
+§ùmí–í~@‚"Ô(Ìñ¹#\v?@1"¸yp\¶ú .è
+!z·lí£šøÞÌà&ÉÖ5 1°Bet'Yû
+2…J˜^×ó¹—µ/Ä”úk˜µ©ÙÚ7Òã˜úuÎ÷µ/!à}í v…B¦Çæq²öÅI nÎ þŸÚõm틸4vU¬˜çú÷£Ž¾Md¶¬AÈ“5=DX•Ân¢òùÔ*éëÄÌy,H¡UÂøú9H} Átdw!{Êd ·½¥).R<p¬ ÖE5ŠŽ_ÔÙŽ4A%^؈„pFØb;måÄÿLt±-¾”ŸébÜÞÁÄ…Žud"?„ OB[;eÝ@ÍÈ)®ñA(DŒ`ïêzÄ̼!Ï·èKÙ¿!\Lh sö÷-¹+8HSǶëzÞŠ4XˆåÙ8inȸì°eÄë£û%ì¸c3=ä´§çPa2 ‡·ÓÏÒàŽåàö¾KÉ0 LáUæѬ»4’Q;jIñhú“Y{D.³0kðã‘Ñ
+éÂ{Pï ±^AB—”±Œ¸ó¦ÿÏá/‡ÑЧPg±%ºûùÄ@eŠbù—¡oÏRZTºÞeS¬È\˜ÑíÜè"c) ¨ûå~cÆýr•†áã›Zvø©“5åø|Ïa­aý³Ø%¹êžD™ŠnbÙNµXÈ»
+!¢s_%Ž0iŠb©caø‰>…d'yH²éè‘a,HqÄÕ¿©µl¼©ég^*áuw¸ØJØÌ•¥ óäLò
+ö>)D®ø”åš¡Ö(R¨4[Ñí.©Ö(äƧº²#ûÞÊò´œrŒ1ôF|lòE¨[|
+f§Ë­J¿ÂðFΆ¬mç0–1’üáñËàëe]çÜJdÔ?õ\ôW\µW)Ðò‡ž5G»¤ kb%r[<6sEIfà “‰‰Æ—ˆft³düÜŒÝc¡ké)Óc&£^rý5ïÛþ
+˜ ô“úmÃ~X€F'Ú¼Ã*°Ì
+ %¦À]JÂÕ­u³tºÃv§!yJxTuø €ƒ0/,S=™ÐªØÅR!Ô/ÀjãäFVyR z©P4ʶQ¨êÆý,&ò±ð½³×v)ú¼aQ—” Ú¾àȨ-÷q®CáVp1cÃñÞrϼ}]Òœ·xp¾€áŽ°yðžtf¥Ü}Rp*ëkZ·©£Ã€0$JræC…‰ã::vÚ~qL’ß´ÒÕ`llèrd±ì¸.˜w¤p®pFÁSuå¬
+´tOýê1eHr‡G«¹ÚÌFðOÙÌZiÆ×Êhâ Ë˪hÆoÎÙ/E/Š°¸ôùf3 ðkqE:t›pàE>zØÓË;0¦ØÒ’ãY¸âÿ…‡­D6>ÖžîüéÛ—Xl<4Ú F—èVO±vO,jÐÝüsäBG:è`Ì~)^HÌÑAÅÀm­ü/¯Ýd³Ï'D¬@'Ö…ûÄçh"F/ø}q#ÏsEOj#–`æU/¤ >€…×>·ˆEBe6µaÜJ2¤‹W@DÛ0t<!³YÁ‘ÅÚÍ+z€¢®l`À¨Õoo
+uc²»WNÊeøÄ·˜)SÀ8•f´ækñˆh¼ôáó·µ|/¸Ë’_Ep®†üyîcÄ&È™¯×c
+õ!Æ)¦¥
+c :cˆÑH\½Æß»¥h¢¶¸jM:ü‘‚˜ËVíœ-¾¢ßåØl¯°€ÂiƒÈÄO-dÍoög‰¾„ü‚n6 A)/ŽÑ}içÓÝÀA ïK+ëÌËhŒ¤É_Šp°ÜXä54y} -Æ°1·£Ù”nL6’ˆË6ust!\
+3 ÉÉ„Ô7ÁõÂi:xÝ&ÙmlpŽ2'?ñï<"‚/ÃU|Õ[ŽˆG\ñ€*QΫ÷WC²85…±ãKÿÀðÇ1cÀO0!;ƦÎ8Fi©ÃHè׋"òEâ+3e±%fzãûvO ꃽߜùÂøÓ¢‹Ew”›#jÆÍËÚ¬uʵq[j,}Û> &CZaÈ7…dêà…à[ÅHì"´µÑ%M÷â>ƒýÅ#ºÛã2PÖÎ@MwyªÍ}×<Ø©p'«Nâ2§;h~ÜYšt̃à.»52>¬œbñµÄ?+‡‘Z:Ö|Y> bÈ
+¶ä’ÞT
+³sËA´äí-òcR´‚ f°BýàrC¯I˜æW¶ïª¼GÒ9hÕŒ" µ¼pÀÓì{–‹ÆÂ`ÖH‘2
+8I­ú§
+M-¯,ÌIÉz•&õѧ(b1¹Öí¼÷á–©D [‰[›é\9Â[à›(y-Ѫ2†Â¶ÐÇiŸºñ¨!*áæqӰɸg‰á†×ãEëØ—SIuÜ°-› ŠegÕ (¨Tp3€Êh² ‘&µÜ¨ ³u^
+Ï­)6Ί{˜¬º>ÌÞW§äŽž^Š~Ý\%¶‰€™·K¸aV'QöšF…2<7ƒ¡…LC¹PíBƒ Ь?Å*³pLÝ6™ ²ît§×£ÍðÞ2ÆV
+p]çœí6x"ÉÇ%nzš\†pÉõî”ìIô$ÒËÊùæn`6¼iÔs›Ì’dLmŒ›t?§ÈˆÛ)µ ±E"{87+åÖÒ,o– (¸#Tþ
+Ò£BÚ~:.ž95]Ò¼>ÂÉ ÅÒ#X”¤´SÛqûMnm@"9ÃÁ‹"¢°HðjäYX+ñD܇Wb|KðèJ¸g÷Ø6åPÄóÊ´êd/–¤+îRåyή|!ňx•«P‡Y#Ý`óœ,¤–ÖÄ:Ï=%Ššð¯É*dú@>\f£Õ‚pV/}}8EËA4’¬
+ô¾oŠÀfӞ会L Ê!µ¡ˆ-΄LþÑWE–V’—ÒÞ I È¥…b·qjþ–ØïŸèð
+t¾%F^6eëPÒ(2BaI®—Ã=jÇüËŽeý*è­è·„Ãû
+>ÄÉsºY1) ñdžäúvÌ@ú ž(×3½4©
+ÅÜ¢èQ»Ÿ&¯EN"áÙx¯•üÓ"'M:EïiR¨´' è¬µ—&E|2ŠQËÐü4©_s¼à9zM“Î(Þ‚ þ%@ Ú›nš\t4©0ʉgï§
+°Ê•íå YÀŸÊ€ûU,E¡_TÎá%wœï‰ƒ¢ŒŸFï¸àôŠT‚ãÇ¢A«[W˜«Š\2 ‚éÇKIX£Ý¦@2rWHpYŸJrEÖA¤6;'òœÈ˜u¹ž´¤?lñ86+Þ˜ôj@vSÆ–ú¾ÄÖ)峬 °†éÕ€JZæ§sßåÒ0¦¼½îPry÷»”ì¿õoi³«™“Fþt¦p­Ë4=íc+ðµø1–g¸Ç0‚\FlãqNèŒK¾Ýð…Ù«<ÚHy³ôàm[!´ç|…·/9ô⊖wÓí îM÷¾><ü:âb˜.÷fÈí8s¾R 7l}YϪr×Ì/Y%sðM—¦.%¹°’'ŽôâÌ!ódOçG„,<éèë¨Ú’Ý?Úø’}œi^3EUF½¡[éØûË9Ç-nÇžË4ýw½Ôà‹Bãá`^áä#ÛQ¥Mt®™k’Q`o¤´ð•Ñ
+.ˆg¶%’>%ÖvïÚÁ*Î8÷v÷¹¡¬ÈJ@‹›ñÞj¾2^­øù¥ OF
+¡ó]ˆ0;úR’Ú$½^*˜t*?Ì)úDDo7v Ö=‹Í{±N#ÂE±¿ÐD5N»>p/¹Î53¯ˆ‘æÅ% \%œÝ¥f-tÇö«¨92¬juÔe÷˜/iìY1•’<Uí>ô»(8ä«ÏùêqP"þf_:4*2‘,eŠµÜó6ðëe.‹ã=꺀—æ\×øÒb¯äeT¿‚Á+,xÅÇ”Ó HBœóþÜE«"bž:QéCÏËí)ž„±–y.b¥’<dr3”CLì!åçÍÛn#a®«ãWdÆØÈ!ñU- ×^u€Z±†&ÐÄ?ÜcØfà5EÚv.7á<ï¼ 2dÏìI’ô_9Ä`LD`9°Âœn­!‹À’󈃆ÆñÏ2Ox‘ý¦!ߎ£vÃJ´ml"¢Ñ®Výëëyû÷Má ×(ö«0¸Y³ÑµŽ
+ó"þoÈÊ qjª™èªÒ½XåQå{:ÓRT†:Ƭ»éL›Å”aà<Ïe¸+‹Ë™{C™\SKçM5…Dðju[Ð(fP* Õ¬}‚rÓý\h+ä[ N1¥á«r›5õ¥W@Áʘ{ÎlÏúÔ?¡)#oü2QsŠv ™d
+°ß4¿?«(w ›çc•hEá‚Ø]›’ÆÃ3ªÝH­."‚¶2‰ú °”y»E3z,î1ñóšÛ1’“WI C2ÇD§(¡“i…a¾>œ"Ï"È€YN6ß¹¶K‘“œ"%¥£ëN*Á³q:Ìýd'RY€ðäy•pñ&/Þ{h~v¢Hþ¸ÉÀ”½ØxEW(k¸5Iûš'»¯¸Êuc¾Vü^kÿÁàéâ¹Ìû)‚hëÍ$ë*Š+q¥AJU¬7Ñ3>Ó .¯añLû— ~w:ÃRhoá¤w-²š8'Ù}¼Ä+AµXÇ]õ ýòðà <ì!ÐÖ\BÌ?-ªUA ’Að7¿\ô½Ö|ÿ¡ȤýªJëëÉr¸-ŒR‘í^@öŠ´©RRªF²yÁˆ…æ
+ùÒ'ü#¦£DVœ ²‚Å\„rn¡O¹¬¡ $¨íÛš„¨C‰¸ùu_éB^éP‰ebÝÓ¾M@‰QZÖ¦ÚJbI%ÊDí=¬Ñ'4‹ö©åQQ þ¦AQ Ö¬FÈ‘ðIœZ%± Ayf/!Kk–ó"ðŒ¸ÉÇîý49žxI-Ò9…`@ÙÓ8·Ôú³š¸¡Ì\\Ë[ë¸Ùùò¨s‚ÆÇc.£ü&ƒ@WI E{
+Ÿ@wÐÚ #æaÙ—Þö
+½S-ûþý=SîÊŸ‰’a ìA>¾îDÕÛ¶ø¹oØHfà`ya.XZ°|&ƒ§É‹ÈxµŸ¢N’+£GÅæ€M ù4E…rJàMYuzÑûAÝ…eZulÝJ
+
+>®8|žþ-…!V\CWu"ÚRçKýò‚4¿$µ›ü
+#Ãì"#‚rMeùâ5šhQ0׳.Ë©Æü<Ær¥»rb-AÒd4Tܸ>Z¼ê~¯‘Ýmæùò!
+`ÇóÝÜÜ~‰ ±5+Jª„4à HÞ®4€"{‰×L'"h1Û’h³½ncДlAÛaHI†¾Fª„@1nÐ<ãý bià<‡3÷©¤+1"J(—©
+¹$>¹_S~F¤êóò]ÓèTÒ¨K¢I\lüQ®§oüÌÐCóQÅ ¦y®r^YÐÕÑèl1L‚WPDÄ šZžÔhŒÅ”K¢›hÒæ}Œ³Úfáƒã|Š3A"4‘¼Ë}|SŒ+jBá±Ý¢eJ×!™Uƒ¢Ï‡"\G–¯m<‹Ç‘eßÒày £ivÉ;$
+hs‹ƒé)òg¸X"­µ¨*Ê|B§——ßsáÑ‹DP{Ö”úØ* 7® a¾FfÑ8Ý*hÉÆ®½ƒ’6 ,Ó–«$x·sèÍ€™ z/A¢ä¨d+UaGªÒñ&ªÐDÈνû—~ á,¿ÿõ†ñí|Ѹcï°
+ĺöó¡h*!Ý©ÿÄ8¨Zòè
+*7†sa)º•@·Xmíð%j¿”èê
+¦q$ã”è¿´ ÅrD7.<~_:ýNd>>}ÎKvùðVŒÁ Ú9>Bפï×nÙ'lÆ8·1²›Œ±”œOUivœcÚÃ98vð?•*½¢áÏ;£H¤MÂb-cj=¸îÇ[X³Ho²I€X‹¹ é
+8èq…èÀÍnóÛEÁV¼~î[E·M+:[nJläQÓ«GÔÖw S‰>Øœ>C?J ä†àÂöÓ{¹f—>p‡Ô¬‚?wçí[°ßZÿ}µ«Ê|
+;¸rPôùPD”
+öÆkñPú
+>ƒöokËÎ{²d–G³`~ø ]H};-‘Aa!!èæ`ÉáV3Oï,ù‚W)ô,% Ü̬šœ5D;‰¬D~‘g°!VîO„eé#R?[Ù±‚ ”­²žÎaeÁ4>Ûøp›JBƒx±òc<¼
+ÜͬOÖî€
+$;h‘…Š‚‰#ÔYN‹
+
+DAY¾¥¡W GõYÖ`d~ØOÿð¦U¯–½T‘Ì‚=€SÚ Ä‰àÝ€­Ùê1Œ’BA>~@’âSA2"6‚M?>w`?’v?L.µÎÿ6½°ìˆÛÏ,b¢2øÐhN‘J23‡Ø“‘]#û°8|•0‚œ´½8Œ¿cÙz)3 ÝkÔ ŠâÓEÎâ‹ÝÅòhöq‘XE!•Æ7 è×üˆŠ‡¡¤ç&„\uU®þ°5+ÛŒ“‘Þ©R-”h5ÁתGr”@]ü±¶?<Ä(†ª€ì±Åc”D”6€4^œ‹ÇÓpïY¡g‘g=­Ñ8Å"¸†ý¡¿ ç×Yaß¡"D‘œs/@œÔBsˆny‚Ì+ªiÃvI¡¿T=ÉÙKMú*JV£U²j¦|ˆYò¬‹èøQå;Ø« cÏks°\ÆHŶóáãúƾ­uSà"1á`ö§L’Ê&ö* aLÍ
+—‰qañ†WÄV(¤@yA££¤“=Ð=6ËŽû{X]LÍY(Š°³OÁŸq-¿x5É5“ uý±-út#P ,šæ90/hÅfVkžk1Ã`»¸Ÿp໊¤ÝIÁ=œƒëž8cÙ·¡7'Kö«³„“Ú¶º…
+Géõ©ÿÆò¯“o w«gì;X;áö7ýK&ñÏC’!Âà£È_*‘Çú¸ä½ C ¢Ïïû€A›ˆ¸:.ÝÊÀgçÔ¼`E‰µ*¯0øÑÙüwÇÁÌF—¢ã½=8
+!Ù3z¢¢˜DŸ:_w(â»äV0œÁ_Îéjá"ç€Ë÷T0‰Š0m\hÄè©)èÁÐxx†Ü±ŸI<¨tï/Ýi©sN“ôÌwõ¬ËDØÉͽéÅýéŽîÜ[èsƒs™ë0/Z_º‚B½ÐI£Û´’´,jÌü°=U¼ù÷'0~©NÂ&V
+ŠänÕW·è]un–·ÀasÚ<Õ¡„ýÀ†0øÞÍWŠx-
+uÿI î1żŒó¤kkô VŒ} {ƒ+$ÍJð¿¡XwN—Š…ˆë¸oÇÜAs»Ì|Î£î ¾öæ¾ ·þþu£þ‹ÇØL¤:šYuÖ|/^•(ðÓ>ÊÜŠ¼¬qûÜÿ/s,Éj Š® ÷Pvy4&§1qYA¼j“ýs_H*Èüñ©H^ëK1¼Á£ŒOïdœ%C= AhåúàDk+ÁåêÑÈO×ÞãέM¥ãÆu«+Èy_D¤Ñ
+â!ôÜnŠpQu/–…ªwÿk_Â Í ¡©,ëchj23c‰7¿tô™6h°ÿS2×] 2´±+ÄŒ0}N‚O˜L#žõ9>O‹pÆÔrŸ„àvVÝÉ«Òàu<-áVÀuççí]SÀŠuökòÀ±5sL~ædU·!`9¤ŸÐ
+´ÐYã±4dR’C=æ‚нB§úß}ut0,léÿçGSß~)ÅBG’"Åe‰á|Â#|e£æØ`tX——‡ÒYöHŠ=ý„!Bö™²
+Ùˆ<Z8·éâ•sAp“ĹÎu62jÜAd<~|ó@/ éýEþ qÑjACðÒ¨›±˜Ö²‹”“AêÀäá«r|ûÈÚK9¢ýô‚–óìB²Ù±¥Ë\gIô~:\a±”Õ;fšC0Qåðªü
+ùi C¼€Ë7çÄÇ …iá±Í½ =¯Ø„ÈìÕ˜n^%×ÌœU·:×ñºÔ؃<õêçWfYclìÑuÚA~ÀÏåäœ÷ëDÀ•mTpÒÕ±><˜ã#±¬c€dj1ˆjÍôDFÔc¡uu6µáJKjÕ%!OL8Ž|ã“ǵõ 1­´}J6bî9ùÌCœ æ™Å½ ¨¦ØREÓ›GýȦR’†[œ,w)¢G:_JìAžZõã›ziýû ¨¡VHdÔ,¾9WýŒ
+ÏÝïŒ,—cOÌ@9 kÑÇ*C»ÆÁTRnƒùá »q¤$ÆZ>´„'±“$àúðÄ*ñKý.§\š
+åÌ”už½<êÅC\›áx5•XØ¡g¦´ÜœEž¸7?uÌsfTˆmMÌÄÜ*{/‚?˜“BæíSLjbŸJi2 „W*ö,èçÍ›wJ1zÂnQ÷;„’& Ã¶¿ôÉn™i…Õ ‰>«²žzþZ Ä* ô³Küä›ß 4YAx óŽ3¯Oþ»ÕýBI*¸i
+R6eM²˜»»6/ežªÚ&ò sÉ®0[VC&±*îbcv¼«P8\ÆËVÌ$bc~Qž¹n,R•ÔKõzñªM‡ºN,ãb}'KÞ
+úTGõO‰hŒ,<³Ù÷MÐÙ‰_á¾Ã \lз?©Óªf1sö%?3’Bë©ÌspÂsùÓ÷}効€ß«!d¢8¨¤Y—c+”€Å®6×ðÂNÂø5ä¸ÉÏwT«¼,d4“Äcsu¢¸84yç—`®¥è^A‚ÀÆ“Ì„×m›ìs¨p©ÈͦŒ˜—°K9èûqTIzÎ\›šX:.ûÊImºÃQEèfîvLæH¤ŽçõÍÐP,KQôŒõ%ø¹È¼ÕÈ׳uWÜŸ‡†3²æðá~¨YÂ7ôä€Þ­<@Á\˜«; A;An£KŠ“)£qÎXDr‰f°-C¹#
+yø¬-)‚¤ Å]ùäm <v0§·yòùc7¬d·2
+›…t2„T¨xŽÄ¦‹'\!³Þ˜µ£‰vYÔî£r„ú°cg³,Óœf=84iGÛΧ±½•êØ—Ã>°\%o–µkÅ~ k(KıoLƒÔ¬Ël8)M(„,ª8÷§® Eê#yÑT;§6þ“ŒÑÚÚΩä
+ÉGû£Áêr?´lĽå#±žðìSÏêEÈrÓ¥,á¦j’ɵ<R ý=o"`ªX>Ì%[ݤL
+k¹È5=þ¸MjT‰Ãš® ĵC…Ìè->e^C)zÉv>pd(àÈ ‹r¡àÙñü´5®²å¸¥:èûžd”r*›Bh;[ÀírPa(U›bL¬ÍÙÒŽ±E˜•¸¸I:E=)Ò¬dµ¢iŒµó#§›sx¶¯˧ÛdNÜl\­ÐÕè£Ϋø®Æ ”¾¥])úîâÔ!P¤A‹Y_èj óxeˆË£vØcÞšÎ(c LZÓŠz¿uô©*g£]æ±ÂÉ‹7DCúäñ²AÙN3‰‡ã‡€:1YôpìÕ¢X–!¤Ý¬„«Ÿr¼¥l B49ª­jÝÀþò“‚Ìzºx”ÌC!ç ¥r’È@™GmXyq¬2Ž_iòi#SȵZ""AÅ<] ×S‡>{v ›o!qDÏÈ$‚2þ4¯íÛ°Öè·\ŸÉy"-ÈásHûá8ͤ ÄëS< åV9{!]x@fˆEÂí©›Â7ì9mX¼;ÿšÏXpQVœjð)ÍÎdžˆ³¥Y•Ý{¿±ˆ¯ÊVåÌ e/öþ¸8&IŽ3.ÈyjXœ­G$ØØ ʾŽƒù¯È¾E‰eR¿ÿ‰nÿö×·ï›_…IŠ6Z¬–Ç–fSš¨ÍNý(eVŸ äÍ ’3¬H%+3íøAJŒh9,‚oÈ?Œ—Ir¹D¯¢”aÖÚò½-ÝÛÏ’*ed·Yÿ/ʉbðÑÈ*þ0U5Ò Gàdz Y3°7¿&ˆQa ífª ù J†«¤É€q¶ŒïÑ°žAoBöe ©Ã»Ìz
+
+7Qœ¥tô’’žq¤™ïûb}•­©H"”èNEF{>ˆ¢‚ÖSóUá‰ç¼'N ±TzGL(´"²$vL
+8!Ø&õ=Ðoð\ ‹“ˆîS>wìOÝÎIr¾¢Èýæ kê„JÀ82þ!: SäYß™‹"ŒŸ6Fu¤¼”"hq-@QþçChÓä™é "©r³û‡î(Û‹ÝJ#Û)L"bEžQê{X4Ô“˜œÉýáøÔ–!£JmLQðkHqöò¢l@¬î"ù®Ä]23§9¦µ–/ðì|A’kÊ8æv€œùâúú
+²!sUÆæB"] OÜÐ
+ÃË©hûkl±õ4-Åʉ­UoC‰µgœ„¯jåˆÙåê '¼÷¨ˆ÷½C˜äÅòñœ
+ÃQš6ݵ` ¨‰bv 1‰²Ù³°}7ÈIÃ3Çn„š‰ùE¼òVIt´Q¦Å­Q@ýD¡ùñøÃõ`Qæ¥Ê|½Á ~N£U@‚© ) á ”¸ymÐj6ŒR}©êc­Œn½ÆXwy ÉÍó’D¥É†t?ßr¤è”‘‚ñ‚ì¦lÊ-JF=†„̨4á‡E¦|tÖqP¶§"·žÖí¬ß@5ćQÕžÔí¡{ AmAh§èDAÍ7Ç€»ÃAÕå6n˜»‘`H#a ÍSµøSxE®†àÛeÚ¿ìs}=&î0½ì㤓HOŒcÚÎï_º|ˆ;ó)ºS_.ó0ÓCãE/ر:ŽL—ØmæRc6Vî:0fzÀhò×,B?ck=”se<ˆ4¥:+L¦õr0”° ¸Z:øM²‘é› Ú¶"&Ÿ±Ô,NÜ‘JîÉ(Û±3SB5¡”H¼&:GÁ&TÅææÕ …öŒ2Eß@ÂÍù–ó‚JðH™µÇ°¤l)¦Î pë™ì·Ç”¡ÅþR%ªñ6È*·ìüdYð^fö
+ògL¿¬U²w©Z¡V˜ç*OhSlŸs:`„À¬Í&/J„BÆi°ø«:èm³¬—wxÀ¿C_D\­WG¶1$ )<@“—iç$Y¡ÉˆÕéuÆæR¯3„u‹PnW ÷§n ©aÍx-ù#»2#qå [ncñÍxm©vDšÌˆðº­@oìðg(f€˜íž| Á°à  äà³*ë
+³ÈbxžÃÔãù4RÏ9Es"
+õ;„
+L†[Ù¡Hâ¿·%»ÜΧ2íÇ DwœW¡¸¹0àÓ6wÃJ§ãTGZKð—óL;?ð#ÙÅÖ.1ŽQæGf×'ƒƒ ‡\‘ÅÚ˜_rnEÿóàý䊘—Ú@Îst[rËŒ™m†Bµ‹˜øu:Ž×…ù²ô^l9]‡ s;Œ0§09õzùPúÔÎX`êyA3†ZRÁê¶^Χڂ0¡t,yÞ’ÄܲåEþ.€œísŸ-±ËãÍ9PêdšÍ•„=2½²ÙÖ¤6å¢6Èó*)#‘•¼´ ÕŸ³Âå”/³ã¢fÆ7’- [É­VB‹G€£ŸŒÒ±²)ªò®˜«Õ#lN^ȳeOSãªÅÖ±Ôìb™aÀ¤ "déporª©V„ÊWÖ»cn\ †îHÐÅýg©Š|LmW>ûóks?ì<Y"Û4 o—!vk:O¢ Å æÄb¯qù¡Ôø'[ã#DKicÌŽØöó©oäJÊÆ7_p
+ %… ÑkÞRò‘ÿ(u‰‰’éªXwq®<±X¨Qã{õtµI#w…üDw'm+ÒôtÄ~iVaXGä­C‹QCæ†j_E|‚HDHPÒv…¬ùKºôŸƒ"íwfÕ!Ô1ƒÝ¸K©Ô‚c³Ï" ÁhpLíýʵtg’X-Ûý"îàîÐô–fdùÔR8Œ?9µ7ÆLÑŒ³/†}s "çk >¸"×ÔLK²Ò¾ ævwôYÙNHBA±üý+
+’o˜"#HI,¼ëÙ.c{ÁcL“1Um·£¿x(¿©œnsƒJ7ü'dl}ŸÃb/µ ù P
+êKoùžXаO7ÈîÓ­ÝÁ1÷™ .sŸ½àQϾ×æ±ú~·M¿}çèB嶽ÀÞ-Kþy®#/-&Š0ÿ˜ m<?‘Å·7Yde͉³-ÉNS ÄÒÏ7 2»ÜvÅL©mJn­&„¯·ËLT.%ÎÌÂ%!Yl–lCpËè]jîÀà  ™ÍÝz‚aW’ök?EÓ‚fWIÎ~[)§µˆ9˜fA¦ÂA
+ñú1‰A†Rå# &û¾|ò?òßòrÛRª
+Åà¯WyRÁÅiJ(„+Å$Å
+ËíÂNÞ2>Æ v¹ˆžÖòf䎿)™Œâ¶…¶X#ï/4òQÀè˜{—y6óö¨ý©ûPÌ—ó†Ið]~Ž^e6ä'Ç;Ä{ùç'c¬‰O>ñ8lÏ•ÐyZºŸ÷ùDðÀ)2ê‡ 4:AÎÌÑåûø ¥à’ƒß÷¤ çp·c —É(ÂK‡MK@2äÞkÌËÍòù÷êF¬ÀCIÏ£õóZú¯n¶ø§x„RU‰Ý, æ9)áÁ+<‡9Ä@¥¤ f—·Fƒ€˜­Cè1Öš”2çåÑ‘,q³UÎÐWå¡ =25"3xQÞÎâ!?ÝÉìïúW€
+H‰Œ—Mrž7„Oà;èóA€?X{–¹Eªf¥Ü;O“|=É'ªÆq$ËR‹F£áÑË(ÞÚÇ¿j·—RKÉðÚì#f{Õ˜žs”aÝ7dôÒ­M`BÄ+{·9}–ÔW©‘=9dæüøó‡0}dí9:¿?6¨fŸÖ"øðuL1Ú5JHx/-š_
+”œhÞ’#s˜.M H¸!È+eR…mðM,ðÒ(&îÿOQ jÃɹAòRÈömì«ÞE-ˆc*#w~Õ5mYµwÈ.Æ(g€ï4¿£~À*%àçQcj|Éž¿B&&§p4£©â¾¤È0w/ Ï+ˆË°rpŠ!›„ ^ÇËfÑôì•ZäÖ8“¡f¶pÐISµ…Ì–ÏË1iJ¨så
+ºSO‰±Å¯)€Í1_®óZC‹_=u¨®
+­Ç|<œ-kß°$¾_ÕÄQ%« »Ç/º¾ÅÁ± . ­h¢Ôœ¸tú 2¥ÉŒ‰HyÉÊ—~yÃ|Þ0PUËIŸôÅJ`—â˜Tû©»Š^Š»Ž\¨G±i æ~ì3‚©ß(c/s·s°.M£Oce¿tȾÐ$A˜3fB´KjöM¥³rl·œûGÆŠ†I´uÎb1m„=WMÚŽF+h`ý’ÒD$§È~«Þ@o9ÞшÀAöêY 峓ÓñëÝ®&FøVzS«Þ`6ÊëŸüI(ý¬O²ŠËsý溺YÎ
+n¥$ÀœÖ»š¬|;’Çw†Ú îa$êá(Šà-Hu;:Ð%̃%aÕ©‘«žáç&í`(§nw½žL‚*+ó¬±6¤Õ¨~<Ý€£ä¥â€L=mk+«Wª£ØÒGyébß 0¬ ßµgœ›Þ@Œj#2.,ŸñqiÍ®±àÊQý·_nÞ1<qOòþ)ËÅ }ïÉÅÇEn¾:‹/²us(ðu–ÿÀt·ë9γ‡ö:ú%3c.$‹Ý„)oš²Ìû‘E‘eí ª#ÆQH(FH>/o“>$Yž{PÕÙ²¦éú“½”É¢ óÌf!™Ãå Wû,*ïæ­HºleÕC£8µŽˆ»<4J&ÝÚúñЂ¢¬«£nºB2ØUÜŸëMŒÉ :î7Ðç7 Íx†¶4vŽ34Ë
+ZîW†½!£)œ«ÞèUžI6™oãûrÒÊZÄ(¢oZ ëcg<)„WÈ]ù/åuŽÉ‘Dô¸d
+°ÌŒ5Å1RluŽ0Aqî?Ï#"ÛȪ,ë®@õ¯X<ÜÿY` žƒU*¤ÈܪӔ˜ÍãÅ:~ìÙÓÿÒ×ýÎþýöïú›–®‘$ÖPø4Å1]?s€÷ £‰uRݨãç€4Ù]Q§ãj! „'@зº'G£^M¦%C3²¬äúÂ&Øþº=iðÊ1,s£ )­?Û2ÿhôÐÑ,–g_ºG6¢~é;ízž¢°y­]´ó°Îþ ‰WÜél·§¡&Í¥®·xºÔþ“HLÔ•ÓþYˆðXuãÏ®K=øò‡Z;=h[ê;%‰Ö½?ŒVC k—óÅ¥»ç({Oe_[=§ó*›…J“ûkÂÎpÙ÷õ7Àlˆçç~Xã©cŽq×xO×¹ë߇²ÜMÁCq9M1w!o‰±c”ƒA±×õã)oð/ÛçŸG#íxStSÖÌæPMÔ*nˆÉd×"­ÒÃÃ<‚~ÜÄC‚ 2¥NºÙîôýΙ"VnŸÿúÏÇoÿýˆ‡ªãf s–ù£8ÁÔO¨ÜÿÿüHýø'Ræ Jîñ@A•)LŸ5Q·›ÞRâ.U[§žX& zÝ2âË[ ÚGKáw]_Ò
+WÓ›`ˆ¨ÄY¹õ¡cB2³M!CÄ[;yø$|Lª W]³‰[±kš‹=»ÊWM:gvû˜ë bZv"MˆŠ÷Ö¨° êJáe¸”‘ú5ö$þ–Go@ß/@áܤ)ZþÏh²Y÷–¿Æsö!M‚ÓÛWu¼çoÉ«‡  Lñæ§<–ÒZÆu•©Ê€8ØF¬¿ŠÃ72[gÆ<Œ(ƒ\"xÖusñƒ h¸ž¹UDº¤•Ò×VÎïWÎ?xs@LŽšó‡“Þ¬¬¹ýžq<¹nˆÓD­×V©ùžwØÕ:: x9J¶Ð/V+(áX§©î`ZîÅÄübò†¼RF<¨$Ô" Í!Õ#†Ð 率™þs"<Ÿ¸D]¹þÙd’™‡@y}_ªª9BK€Ðé_, f=&ØKûp6k ÿŸ¢«F
+ˆaàXY(!dB˜vV'”áˆtÔÓCeÊ=AØAŒlÆ:D‡´šÛõª‡æÕSò ó4„ÖÜ
+[T?|+ÄVMlÁW‘vê<ò.gùeó´5z5 Yb2Û®²Oˆ5Œ(Vi¹½€ %¤»ªýµÕÈ”öôè‰ç*§Ò¡ÅH˜‹˜hp÷œŒ›2APм ¹‡EÀÁ4c•o7UÊë¥ E.»Sì6_<EaqÚ¶¸`üœ{ÂÒy>^b± -7%G=Õ˜ÁµÙÛ™úiÖÏÑmáÐ<¹ª'¤v•MÅìe2®Öh›/Ä¡Pµ4e)!ka(ßñEív/8‚ÚmEŒ¶ž÷ö‹—ì}N_Ù2R:œ¸Ü@æV¨=߶ónà¦ðƒÊ.ÖÕiuè“í“Kõ3*g°êZ¥zÄÔxvŒ´èK7Š
+êã]WýŠ'Š¶­}Ò`smãÀµ¦‰ÀÍÈÖîQ®@0Åv)_”¢7±€¢çÚ)•J/5z Êía„©}¾hÛèáŽu@vc—Zû±ˆ2Ýëó9R@Ú¤Ðó¥F>ʈBóc똯m
+¨•{A,n²×ôNÖZÄ—!|· Ýhö4ØpaÑ€½Ú¼Gâ½Á|¿ÀD—ã…ÞÔòVˆw­N¢¶ÌÛ”%ç²Lá¢<Âãê“Q♳bê¼)ó¾¸mKü€ÁÞO#|ÿðzm1­ùûÈ A>QeT²¸MOêS¶kfX99Š=-:Öû•˜½9yGÄ/ïREÆîÏ`ÑE;Mûæ·êW‘ê‚$–(þñÓ¾åH0(üÎâk¹èXz$a&¹iCÄ ­+±m„Ôäok4g4FÊ bI°<ËÚÿ¼_…gÛP–ãNëá¸Þ
+1œc@ºáäˆTÄÞ;xT ÙÃXyç•êΞ-YˆŒêõöaÞ€08d¥U#ÌQHJ¨Û€l
+Qb„ëudÊÌ£nÑ'sÂSP'¤Wc±e|‡M¾˜ÂΧšu ´àv#Ø-¡O¸DqÎu-ÌÕˆç²XË{ ¯¸VIKî¬p†:ï¡ tz¹Ìž€Î"Ó­3´‚Ï[Åa@Ð w¢²ÓJbJ7$Ûe^Ì …šzíã£)“žMeOs4½‘coÛ~¾pR¿pdaÞªGƒUùžofæ¯á4‹™„îA?nAŽ]‰»ÏŽ¬
+ŒýÉbmRØ» pf:ñO”¢½x˜Ð÷;SÛYØÅ
+=>è&ŸQÄèð:€!¸¼oþ¼EÖVSP\>ÒqBYYIA*u"D°¬Ýã]·j{ŽÄApc+m’ÃýûÖ¹]þ;ÿþqrv)ö[mtéÝfÚM+*.ŸóÄžhÝ0ŒN³6áfÔ®sp×SèR¾Õ9
+¨6Íå«€ì_>õ¹V˜ëýpÏÃ.ÈÞ™[¦&Ÿ³6;Ëq$cÆžß@æV£”=”{¥Ûu´…ÆáÞ£ÇÍ‘"wðÕš?Vçx_®°´af“6Ž)㣮#³n“Ë˳G=er|´8q,ºh‚qÀyßk8O~»…Ÿ;U^3,aš¶:Þ7éiŽÔâsÞÍ‚lPû‚°H>qÄ ‰Ûô™&)µÝ×(ã™×Nc¾°@=[›-îæ­É†óRÔþH€÷8M_F”½=±mXƒè¿ðÃiôÈÿßïÈÖT7ù
+0BE–õrÔ rØy¨ÛèÆ ÕüU‹·Üµùù€mcM‘6±] ÏÝßÓ@<x
+»Ý{ ‡|¿S§(çþùÇñú
+çeà0Øô_»†Aæ»ÎÔ×QÒ[™KŸÈr~:®:ÍÛŸóå¢È3¦²Ò*Ãcx§?Ë{I¡Ñâ
+á“F©ïê–rF€ª¾¸Ö©q1q[– ɵDìj²&d3{´ö QÿvîaêŒöÜŠj9§²Ž|E@ &cR‰„Õíüé !]£Ì!ßѦʬZÇ]wÏ’ß/¬éºyXV®·C-›x#ßÚ×¥vêåÙÌÏK0í…?ò dnÅ£mA•Yn×É"«€êq8¹t¦éW4RÛ„¨¶:rEÍëV;Ÿ \änn$Ô2äùç`c3NàŒ—I’\7 D¯¢tp&±ÖV·ð¶}ÿ­_`[]Å’¶£‘Ÿ@"8t7°}°£µjt-ó³bM«æ%l † Úà?1M<ˆ~ËyŽ¸J¡rïüq|²Òç¥ÒxJ€<ŽNÉ´„¥Å™>wÑ¥—´%2oô=®Bjx5êÖj«:ž„e´,P!Ê•}Hyú'÷ÝL?³/CÖCzZñ{3“cò¹èµ,`à&,œâžÌù›jqËÏø¾ðé÷ÍPR{èÌII¡ž[paKŸÏÎœP¤½áP`ë×v˜]Oò2^Ò“œ$MgzZZ>,ƒüK‰CO–SW÷úÜÏ©’@œÛyBŒ±'è?sñ«r9H) ¹Ä¿ “Ä>ÉŽ—r}Ë ÷
+ÍSyl”+IÐ<¼üÄtm·_õJ6Y&Ì!¸À¯ý¸QcjH.úŽ)¼S_†ÙK˜p¨ï•BA¼_—§•wîºFTÝz{(ùÆç?¡þt¨_[ªsÐÒK êǃ
+w"À¼”ó'ùf4çòp¶ÚÄßxº{ÿšöÀ¾,.zñðªö‘Eú
+-<ñQHÀ9U¨íòú,mðçó‘¼¾ˆeCp_$ª„E3=2lß>žÐ֤¨Ó!e†»Ët°JþH˜³óÔÙû· ȭĬøõ© (;1úM[•‘Ÿ ÞM
+<J\õ2q"ÎZp¯LÇ,½à†’Ia6ìÆj7üQƒdwª?Dn‰ñk‘
+¿=Þ4'ø+"ª‡sX9P%¹†˜½—|CúÏëU룘¸j›yýøEÑ"‰ f0ým‘¼k’ÁÂâN>jí[5ÃîI`WÉlµ81†UFÁæä•–— 0ÞìG=žáw#ô_
+5¢{}2M&Fé1З¢Ï‡¢% ™ÍÉ4ö<¡í&Ñ„Ü¢;XøÅž¢f{žX %NÔ:Íx”¶Y‹ç:³ŒIJ þ$Ža ÈX¶€NÝÇhœHu)_d½d·!ªé3çâ±{Mñr6 Þ€žSYqÕhäà–rÜĶ‰¾²Í»2/Éz|qð-!Óa,+›Ôª¢k ¸C.qS_`°èÄ)ÂÙà¯@Ûõ¬ï“Õðåaaþ°xÿÌ÷ÒóþïƘu0fjݼ;|UŠàÌ¢Öcð—Éâù}µðœ 
+Zlà"µ Ÿ&=}@³¸‹uÜ®
+®ô¡¤rÞ¶f8¼sÕKQR3ø65.’_`T¨}Ð`¢3™mS§“É£L,Ö8ŒdʘûEôD¢Xƒb'š`BºE'÷9k'‹ÌZä8³þWÅε=ÌMí8>fÞÓ°¬€hh4˜×Ë=øn .ƒoIó¸Ïï&ü!¾—5ºy¿IœlÈð˜w² Í˶Jv1¢+Ðp[«Üý}–d`ÜùJOþ6` ÷pÖÝàCMh* ,“v\ÓTJ˜bø]üÿàºA$|,¤<vM?$W3DNòØ=c{ø•à%ìHòµÇ-ƒNx
+ÞȯÂþ É¿9ÄšfÇ1öW!VŠÚ@:ÐiPí*ûœ%ÙŠI±0ìËFµÞ+„t¾«²»Æ[É$,Ù­myHk[õVÞk>j„qc‰HUvUa @z"&ˆì7Š,Ý¥›qˆ%‰RóÅ8EEKºÓƒÙð¦dNÆ
+;íåùPwVN]7x ‡0>2‚E\± dú“|z´¬ÖäÆ‚ËVÓÜ‘}w#ëÆAGž+¬Úá]¸Áwõ¡ä”\ΠôNìùÐs
+1aÈÉV䃶bwT”›T§qÛŵ«„[I·ü]dìjPæ€ÇZ'.tG IÛBç*ö Œ- ·œÔ(3W
+xȶ޿{UkˆDø‚Ùíîý)‚¥å§F™¥\ϸá¬ØDsÚI¬«8BÚ8¦5Ž
+‹Ò¶¥£óà&¬šõ+ÿk§x8ŸAH,HP@Ÿ~Žjz¸Lÿˆ"„æñÊ Šç†C÷¨¥+S<T-8égÂ){ât“•î~ã'k1©±C“8±^ÙAÀòQ¸%RÞ'‹æ:é£jÎIŸ\Œ‹á`còlôÿàtÑ
+úG¿
+jw‚`ty °Ê×zK±Bd›e­°=Ƹ4Ù¥(+гr„PÚ†&ʪ´y) ‘Å|q<ŸÊãå;ä¯2ÔÓUÏQ†­¤ªß¦"ìÆøŽË…ƒ{xéN›«žû‚˜œPü¨}2l”ói – o•¯~ÊXUbd?-– þPÉ€ÀÔ½Fÿè'³oˆŽ ÈVp@ÂcärËœÅAu]¹§nÎ…kîùP]„Äœ½†_”¡£5x™}Ϭ”íxqž—|0V § ×;ÎQE ª¼Jlj¼|‡ÛV „ /öRB ÊJÃÖëQ¹h­}½
+`%ðÏ¿¢G(ðîóN¨¤2¦
+±±£—"éQ–ùgÉO1õ^ò“<þúòªŸŠ~\ô3 ¤(¤U„£œb‘©´·]ímQžÄh7qÎ) 3E§ð£·ã´ B7 ‘M6z𛨔Iqcsb‡ÝæÆùøŠ>ÿ. /ø‘Ëw¶rß+.ƒ&!N vË.! N…7eÚ.y.ô¡“óæi»$í|Ëvh-佃-®êPdT•lÄÈGŠ ÇÊ×õ5LI’åUtõ‹8x…Òn¤ ’¯.T´:o:K\€'˜ æO=ΑG†
+D]GËí’Tä T;ý[&ߺrrýµõ]š‡£/æ’ˆq“7¡YÕ+è.¼?"*½ÎV@t`dx‰‘ÔXc´ÅŽh°y%ÉŠx ­SŽ“åp/µ`C6 ·(©Ê¬n
+»µ‰ÝÚzü¾®«á
+L¢OËñ*ÌNRBïW†LT‚L%ˆ5F߇~?ÔYÓ66™Gê¿‚ÁDl°À˼—€„²¨#(ŸÕZ`¢´H¦ t4~ÐB\žd<a4Rkh}0þSE?ÞŠ`±¼šõ«¼ppú›äâV¢GqW|¨,Ãi2{K?µ iF(À1–>#ð¨/¬&M<ß7¨8Ìec½•T E&áF'èM¸7‚œ¯aÉJ¡0k¼ªNI]—4œ‘›6ß;êK‰1PpPäúÏQ4Sã‘g‰"ÏÄñÜË¡ƒ³’Š²y¸`QY©hŠD®»§½¬¯æ9¹_âGx-³~)úáEhzÊZ”¯ë
+`hÜÜ%Âø cRVEζ.:K#Žâ9ŽB·FàJ½¼g²@Ž\Òª¯â"’ížãx§.Ö‘ÿ.Q‚j±xlãlã® ›
+`Iqù¬
+)Ì‘Nkð
+ ü_Ú"qþ¬QÅRXA‚@X €ºyá.Á`e±7ç´(OC
+¨ìŸalº]K.nòV”– yw‹ïÐ'ˆfÑõp¿˜#Ì=÷ÎÕ[¬Á£Ù 6¨C¼Ì¢Ë2ûQò Ýþ1ÚŠ»4åŠþ H{$&3JPb<=ÝÓQÁÒpÃ"‚½”øQX{¢*Üž³½|ÏŒ"~«ÛH ÿ¾v?‘N‰ë—D„ìuP¸lËœûy:¸Hæì.Ò(xÙ<ñ¬ßVøÚ%C|†+Nq™Bs•'´qRm %óÄ<ºÉ<Á­ÝŸ‘Éc}Y™'±ƒ]P³Íÿlxá·­€ðo'm$'íq%Cx>@ÀS‹ï|0Åàv8/&žúK‰!&KGÏÏQÿÉ8¿ÃMis½ß>
+ÉèIºæŒ£ K²º<a¥RxÉðNãý…_›è¢,a@^ì–q}+2ÆX=„4
+Vöº÷ãh¶é@š”í
+ñœŠó66žTñðrG:I
+ "Ùõµ2Ò[—û·Ñ/±&¼âÃ]PÔ0C$ XÙ™"Ƀ­"+Æ/dl‚N½zEpcú.ŸöÁ­‰m&7NâÏg;n ­.x*î‘›ì$ % :”Ý
+º<PçÞ”[‰y]&#/?
+wyà4•Ut¹u@°3tê“bülÓëùŒ\˜€³?¡~-xcý_?.5h ¥ÃÞöÐK ¡.&™öí$*Æ»žô¥‚±r%L# ÷'Wðªu +®H0Õ{3Ÿ°>†~Ü =%RZxBü’ ¨ÁI1þ¤DÑоÓ VM‰·É5ÑÏkHi0
+=Í3™š¬©t¡îH0oyÊ$em‰2”'ªZò
+{`fÚÒ@›—’_?þýƒŸ³Õ8'Zœ´^þ¿MQ0¨HEŽóRô×­H2Îs¹…¢Ö<EK/ÁNq“šò×¢º“ ®á l¬ŸƒØ°p\ýâE{àÝð$Ø–òÇEŸÇ5,Ý£êºÿ¸èÖ‚ãþ¬ëfdÇðÛM;t/ZpIGóºVúR‚ËÀ€N5@^ù^" $y¿jžRE(8î‹^ÇⳜ²ÎCgßç-á͛рÜѪrÈ¿ìT.6CGmÑ›†¤Tg³*O^xV Q<Ö¦ŒØêÔ ÃÐeXH+YMÄ½Ô ÙI¸(Q//‚Æ,ñŽ=jãqè$DI‚ðÞÌH•UdͤŸ Ö·;jtë‹vùÛN–Mëué<ºqÛ£`)Z¹·üþåÂò–WNrŽ«ÃàŠÜ•´4¾ƒ
+}§¤ˆâiÐ:ydé1Tì×íUÁĽ€Ç²^a ¦ÁÏ`V†½ú©éŸ¹PEýä 1ihq êàk\ÏJ
+SâÒù%0¸(æÊ•[*5¥S“A¤ý‡ñ×1"ƒeè|eÉý4X¿H½èú1"·"˜¥³øzÐ<ŒxœÖ"òî[˜¥„¹‘ÖháÛ:Ù:6¶nëEÐþÒ’·é}˜7’XÑÿ8ß)š9;ÂÄf@Î$ƒ–Ãn”¤¹5—&±q
+¢…WÕrJº¸wàXÛ+L¼ó(50=;Õ„Éà1¿œbïv ËH{ƺZËÚ0º
+
+(
+Éý|‡ÀKkP†úÿà•
+lQŽÿä
+U°e 8>Á*•Ô‡PY† IÖŸípv[>– Ç¿¬{ÕgÞÆÞA·þ¢ÇŽRÄPÄ‘¢ ÿV†ußkg¾ËjËa`±±«âµ!ÜßÓ"RÓÅ„•ë³Àðìr«ãe
+â%»"³O
+5Ô2pªz‘`ÍZqº}†‚(ôÅX†— 6¼3Ioõ,1ª
+c„ÿû„Ÿ:jî\%eEéÚhç¨Ø€0§íÓ銑Ž-“§cðÈyY G¨Y dnJ+-%Fªò!c½¼c.9ì¸2 Ô«‰h›Œ 0ÈjЦæí±‰ËP3¹|G„¡\reLcÓâ ÏŠv5‰CÛqŸqÀR”5ôãælLzQ\«‡X—¶”£†÷ÿ÷ƒËŽˆ!äië–fÂΡ¦¯¿]ÅukêQïôúMØ|§‘F5Ø¿>Å\.ûþ$¢ß+pJ©/¢ÏZâ¾aî!¥®å„ѪJwþäþo­¸ãÀþѱlfp—Ý·ö29†Æ„ÿí‚2Í ÆÑ0¢MAÅþ¥®fÓb`¶²º\·Aaù©°ØáSÐÕ‰¹×}
+‚¸qgZË‘ï”&v"Ù$EÙæäx:%¸3· õ¨Ú'Àà“´ì¦Ö›¿ö=2 -¦$µÁïAÁìREÆj0ÀYVµîE
+ Zc`Oˆ¥ÚU}™µBHÅ@<Q%@&¦6èÞ q˜R¾ªøš8EƒÔ  ÙA覉?Ïòº]ŽAb%—Ú©BŠ”UÊ[DÒ@äÄa\Y”Ÿx£ž ’^¼˜‚OæŽy®B„±çÒ,•äÞ´øå*;i¹¡Ð¤a:Ь^1Ó ÒZ˜—7ä‡]“,ÀFÖòšwﲡµŽ¥ÝYwѽ:n?/§p\EÚòNÎÐYƒÛÎ!¶LÞ™-É]­5Ys=á$­Hl¶s¸5¥ŽÎ"H!O²âsÙ•
+=iMÛÕÏ)ÿ„ì«’vSf,…ÓÉ·s0YlAð#­è„¼ (\áýiõÑhº&£ÓÏUd‡µûAu 4%æe-N«GqçC:‡µ
+NÅ nÆ ÙDpé –Æîq*‘É2¢€°1Å—ìs†¬&{ «š-ØüÉæ ¡¯Ûúèìu°Q¯QÖ¢œ›¤Å)øs;&iU@ö%'/‡Û¯ìçCø;Ë`£.„÷ËÓ‡jé@Ö,ú¬Ž'>¾ƒ®ôÿý‰nmy»pÇfÞäír”+)È*Šê[O?9ÊÅw¼•çqå£Þ@žrÝ®ût“7t‘7 ˆÙÌò¼¥¹òdöÜ#ž×¸Ì/½V1iiÓ8 P_WNp®À¦Ê
+<)\!­tÊ`ch©¸
+ÇþÅ ýr8ü"p,Nðlµ…ö oìM¬.øÙŸŽ¤¼ëû“á`¾Â¼ S%ã܉e+\÷ põ‹•ÿ‡|còu’UšÈ’Òyå]ß*×bˆRÄ0|}ŸS £œb¾ë[lð*Ù¬ì3õøƒw}Â]»buâ½è› ºê›{Ù›¾)buZÕ²u4ç]ÞðÄ‘ž—V´Ÿ3®òFþ*Û¡„ ÍäÊ c@ÚzgÊ’§]‚ä¦=jpÑô”k_•2G0ãÒ¡‡s"r¥“ c/òV1„h?i¥m^å­¬äàçP¯tây“7aè˜ÒÐWÞ
+ç‰3Ï€_å ƒ[Ë콌äÊŒÛiÒ¦”|W·¢e%%q %÷ÕM¼-Bª´îŒ®ºÝ¨ý®nä¦nèÆ´th[­-– ¼ƒ<uûWÙÚê&¥$±”æq¸Oåd©›z›@E¿˜-±ø€Áû
+Bü9õ±6C{UÄ'õ"Á?WѲžŸŽ³…СhTĈ@ñ —¦•`àt± È8šØ#XÉ dK9蔾›%ŸE.ƒu+˜Ó&Á‘E¹A0ÐMv % ™Ól8IÉÿ‚¨Þx©B…­ÿP[D3vµ«V« uˆöÀêEüSß!c_6cܳq“±hî
+ÿjâ¹ê¢=Œ…}Õà p2ûãîÑĪ€¾µè¾i.·'³\6€J…*KpÊD'´°´ö0NK%šLÑîä?Ë=Ñ ´FeÓdvóEhöÛ]_!ûª¢Aí5ƒßÎa׃x;?íŽ È|•7Ö SÅ9ÉãÜ}k®cËë3:ac…6¾¢…1Èì.M=.ª7FºÐMÂœˆì
+ßq„}Ö‡cX$Iæw¤'(•‘öqú”M‚ä5ÍŸEœfÓòJ†Ûîwnª²%KÏØq—+hIÍ=Eµõö3è8ö,¹<åª5-ÀŠ³)…Càò¾v Ð< C¾I‘ÂóQMï@Œù[-A’œ·ßÎaƒCZY¿ø3« \fç’˜Å×e XKÚ±LlŸÜŽD EëœDÒeÕùý¤˜¡à”®Z,~Hy‰t±‚„9 œ\ì&^]µî2³‡’+Xm:†õ¬1qˆ
+œfŠŒqï˜Z‚åUÇ^ЂŒš­flglbD3áÅl´Ã»G'›ü¶ÎaTÂëÆ9•%6±Ö‘çæ#nZæ`³ÓËË ˆ,$ò‡òg÷Ih¸˜¥ÑǪí¾éš<^+«bxyùÅá ¢7'ßá–)ð2¤½í4ߥÜ8í1˜ ¼AØNéÖ4@R(ŠùÁzÍ„Éó
+lþ¾Šµfà†,µ™z9™ÄÓjŒÛ LÉ/¥#ƒ$ˆBÃˇ۷ ‘߇ÙË@yŸŸõázÌexÉ÷--íÛ¯¢¬Ô³!Þ˘B[IHÖk4áì`ë 4#…£×¹ßü
+Dh‹”_p“£JIÈð É ‡ƒ(’T*
+¹=ÞÔ('ý—xØÓ£9Ì«DOùòÖé¿Ü«3$®Úz¯ß Dù+NW´”>ɵ†¬
+l¯ïL!}t%Ô¶Q’#­jÑÔÌ(ÑÕtî? dP`ú|âA•zó@J!˜Õ×Ôÿ{4‘,OÌQ[öEÜEÒÆ™= p–RØVºÚÌ¿>ñ¢¿±­ä‰]€
+òðÈ>`[gø?åe’iŽCáä|‚„DÍë¬e£W®ûoû{"e´ÿPÜ 8°_h È7`HLĈŒeÅópHzSS=çó÷£g}YoØgcÆö9PeQ®| ‚Øe&à¤TüY雌qG7hþF#„Ó€¯ƒ.ÛéWøîA1Õ3?Ý*ð²ÝÏ@™ÂAûäÌ{Òo@Œá‚n—¸áÁ®@wCÀH¼Èë%fŠ^–wr™ˆþ_Q‹®7µˆœ¬¯ÃßÕ&ÍuIu‚ÈSÂ9¼Ù
+˜šÇ¯ ðXgý†"04ÔÄs IŸ.ªmH1”³lB¹œ×w#wù_“ë]:éQ‘é¹Þ`lº±¼P*Ç„lÚWñh›„£Xò¯~Ý@b %rÃK5oQx½ô!‚žÁ™ˆºC2ƒýªî舢Øa´{#àáÊ}p(-RMa è`?׆þ&Dr9ëôÒ¦¸ùŽêU•|-kç0d wÁLþF$¸‡Š^Bï”;ªh’ØúšK^¹âçö2L~E§›çÄ0Žšœÿ¼A*Κz*»@¼Aé©Æe\|D>œ:Íѯ˜©íÐø§É˜Ñ¦Š|mˆ¢×䔩] ¾Õs¦.ë0Û4­ønæ7·2å^üîï&'¾UrQà<yêVèA·BH;h/œ~(àì•XÃm‹C8k¡½ ³¾˜î¤tÁ€ì­^Tß'3S'ußÕs™¨+ø†¬ÑƒEýâžÀ:[aÆZ¬¢¬4‡`½Ø
+ògÔ.G´;ÁÇž¹èØë4µÏ…±>ŸzÁÛ«9¢Ã.-eE‡ÐêpT†„Î¥(R`¯dƒëaOE*ã{A¢0 _ #u¿÷SÒ|[ÑÒ\ŠÕz0-WâW ù KlHY‹ÊC÷#1\qðÏÎVB5$UƒÇHålõïÃH¡2Ó¯Øk¡û°ëÉŠ,Ì?o@Ïg«2\œGÕ_þзí>r&?úËZOMr¥_±„¼þ¾‚^\›-z”Øšx'űƒ.Û½Üïg ‹¯q7èCVÆòOA7¯õú0ÐçO*®‡ÉM¤I†r ]È•÷¨ Œ3 ä}uÉN1¡D¤­ @øP‘üŠù Ñ>ø—£1]2 »ƒÆN‰ű'‡œ!/™<K9HŠ¨œ:ݸñ­©‘I¸°C°3,‡þ ÔX¤`ŠœHZ±Ä«rÃô50cÁ÷UÄlè’·[fSŒaRÅ Šƒ™<ï*‰‚qXèìTmè4KŽÏA°Ãf2|e¯#3Z²ÞѵJò=ù†ÐÈmÑ.\´^ ¾U&TÁ’IK½Y'ÁθLxýk«YR›¹N¬ÒŠ8Wq+T¯[@°i";%(R L/åÄb9ŠÌOS‹©ú{º…„YÒ
+Ë_¸²ÆQ *ÄO±ù:Ñ¡âõSÂŒ;c+„Uˆ:œ‡h¼„árü Òé<H›“ÒÉšY
+ÖåžáÁqNÔâÔ†Íy>4¸ºóÈH®”½#óR8*Œ ßóuðò6gT˜QXô1
+bZ”Ýz;[µÉ”!›šø
+¹Ê ²£CPÝ:3,Ó(ˆ.EFàÎ- Yžß½†K ypöi%¼1 º­I‡¸ï^öÁWf:¡Çiì‚3fÎ÷Vr:sNÒ‰pÁFM|ãùVÊ1X_8^ÑÊAŒÄO¯"œ{bm-H S[hݵ$º8$cÈéLæ" ´\Gað3mÇRÑA®Xã"‘‹RhcŒ ó'_ Í‘ÿ‡5âÈ8s}®NÈŒ–¢!þ>½ï¡%£”PÆ5‹ŠTR¿7`Q¬nÑÏJ¥²÷0gd&ˆ—‚d$q[«ô2¦óBJà|S±Ò‰z†—øf*H}Qp<©÷h³
+ýÉTcLGgòf
+™ÓOÓøæ¦\—ó†eP¯¡i¥Ìsâdz+Á|§Î{²loë£áõâQ,Ú‘‰Ž<órC~LP2Å<ôo¨šã$ªOºŽÁÑqžg>ÒèÌ s£²És^­žÒ!ÝL!=m§øFû— d±TÁÍe£%ˆ‰<ùbâ!Ž‚@!Ùg«U+Ñ cÞÞ¬óH¤7ÈK"½À÷C·_·š˜j9oƒ…Iô¶7.%‘N¹"©L?q{‡8Òâ½_!ß¼øòMÿ¼¹Õ7ÐçÕ>s/Õ ‹yy‡"2¦PÚGhõ«¼)fÝêÕÕòd<|sšt{J(¨á²âÕ‡.O ‚}³8_
+åÖ¢lÝqþrºAÚá(1È n黀\–á ¦çáÔq)¨YžWœÓ±œ…Öq"l !<›ÏN&bf‚ÑœH|SBÐåÞšû®-c±Z­ŸîZˆj[\µ®€i˜LM[>Ú@aLf”TrÞ“ÄĈ.ʿ׋¨Ax@Ã/á{ð…}_i*?Áq|¶§ÇÑ ’6}èó,Š'Ú„³ ’pô&Gµ!2›H:|rœ³ ­¾¼¸ÚH6IùÇí4òXê ”6…Ü=oE?RH†ƒÈ_ÊŠÃüA!‘©J“Êk
+³—H*ô:ó u–&õÍ_–Ù⬻(ü<ËPôÎT÷IœqYt '´s\à
+x(ñ¸§0t(<5Cœépö^Š%Q‰ t)Ÿ@ §’dzF€rI(DÒ¬àÉeñI@¦¢Ñf¡õ*Ïzì.÷ÉB Gže‘0I°KlÄq5+H¹öÎÝ pïI¬œþe:Ž¼<è\%·.6¨ˆýáü‡0<@Ÿï@IMϘð«ÀpŒi«âÄVn]Š³âàdN‰éhyò
+ž›“¡wÈ7«âX¯ iqx«õA ¬júú&×Ȩ֔6Ôx(ù(?wòmŠ1ÏswM‹ä¤¼@Mè­°MuðMA€Êb4È'kyÛ,ÔR%¶õcÂsÝL² :…²Ýà¼Ì®ž“ÜG¯á¿ää×ôé 1 íÄÕ{¥2Diì½&nYR>j×â’Õ!|éŒÝÚ}Õ†y÷Í_@ꊞ%G…KÔÛ:@X†¦9ôõ×MåN¼ÎÍ SL…)‚V;7€p£™ùäDüøÕñèc˸­0µ¤MŒÁ`æ—9§@‹âÝÁ6‰µŒù\qs½
+CÄèE#‹L–Æs$ŽûÇŽò¦5™X)²uB+\10ÈAZÁ£Ø$r®q„€tyÕ!ô­˜dl"ÒÎ¥¾Aþüúϯüñz… ËT>eþìé,+©¦
+ûW á?o@²[âj¤A‚O+àMEÜh:·‡YW>kÝ!ò#•ªBYÿe¼Ì‘ã0b(zÞ±VïKè’C¥>ÊŽ¨Ð÷÷û
+ËEXߺª"^OITiwì'ìÒlè 7‚;ž9¶j\K¦»1½ÿD˜àk1Jh1U/v‚ª-ìÆ,QSel°xh›Ÿ)]ü}*•E á=ñræ>0…òé_“ÖY峧¢(I…¹¾Æ‹Xþà¢Ëì&yÓ€˜ï÷†¡U Vß*dFàî*lF‡ÐÈÝÆ¥è1`è8ð.+ñ>§ú®J¦Êzö8äV¼¥áQÂÍ!'f½û Õ•µÜ×61Ìf7D7¹03Ê7Wøã,Æ>“rÓ[ò¿ÍoÔkÉ'Œ
+ΈøÊhV!aÃTâÍ lƒ²˜ß ŒiŠùÀN³¹z£7 ¥UàVhŽ’9b´¡ÐìSƒöÀ?²m—¸
+”ÿÜx㊘zàæJ¬³X9çÊ“E _§ÿUyÅKÄ<ù@ñÆ=}01.û S³€;Ð%d_F ÞX†?ÃÇÒ%ÞÐâ«zÉ[cí~‰*Uj2`G‹‹"Ò×ZS^ƒ,’1´±(G(”‰ª'.Ŧt
+j’©ó­ðM<X–+:šždq…äâ[-é,
+®Qwø" \ÓwUJ:I @#tã‰Úè¹b —È4þ† /%å¼.ÅåßÑ™d{]úœI(‘ÿL9Ø’é#†¬^Î:EzŽ<—˜SŒT…¡Íë†S(i¢Šãus™Ö’óaedTÑ
+ÔE»è‘Þƒ3 +Yç«ìÒÚi:G×éÈå#âp%ÜQ`'‰hdµÑ·bâ8‰Þyœ
+q‰aY‰§‰0Ìcr!ú$?9Jl·Ý<{ôÓØ
+T0ÀÙßçüQ(Šòs‡FŒ]ˆ,PÙJ´"º™ÕjÇû‚‡…²"äÎ
+t6e%öt‚¯pheyÒçÕé=NÞ'Çøý:žt¸‹&¬cÒ¼Ÿ[ÚܙĹǥÈJh5ÑEnø¬#/J;ws»#È ~ ;”¨@Ôp6i}¸¢Ó!\¶}j0CcR|™Eð0•ÄyF Û’¶ˆŒÛÏ"û*ÍÏåRâ[ Yåñk‰upÍSÏSá!o'ç#¿rîwât2 òÜ7¿ƒˆn¹(ˆ¾‰’^Ç">ÂRC4Ã]³‹$eÞpLl&‡¤„¤ì’·ÈÚ(,æ~è†i…^”EV¬APr?Xnç
+‰?ú¥H%¦„«¯vÃb98 Òi繑M[ùÀºO‘H#¢\^´T±ãJ ¶dÅ3ÝìN¨QhAï±±V¢×VJE–½dØIr4Òz2ß8ª«{¦ç·¢OŠdo˜zŒX{÷"ÆÂØ^”%íJ©Í«•¡D1CÓë@‚(&l‘˜+A@…kÅÇûà÷Du{Ÿ‰Tq­yÄx€þ|Kè3OÅ™j{Ò«õŸ
+H‰Œ—Qr7 DO ;èÙ" ¿•OÝÂUù²ïÿ›rfí`J²ËIiÕ;CF·N-½K“Qßÿ’Ñ­÷Ùµ–êVß?Þþy+ï¿i³Ç¬bƒßÕÚf@Ç£ˆÍYT‹©¾ÿY VEdÖ¦Õ[
+HÑ"C[óªŒQøRs³é·Î±ª‹ôº!}˜«5½´÷_oê¥öø
+ŸëÉæœp¬çh<±pœ. bÑùëcÎ9î â£6ïÞËp
+úcçϘ¥Myÿ}’×*E¹ÿzYã§N­×±«í­ST)ÓeŸ'^;Ìjévô£RÊZ‹7:ôk™‹‹rÞÚñ˜bS欵7é«Èê½ëàÃÝ}P§Ú'm¶b 1ôkç_ ñ¦¨(0é\È㋃xåEó8J¯­ªöV‹,ëô
+ú´P^Ê­›Äaã=ãֵÒ®Çc¬q%Þ4D¤QJT«ìòVªÆ?º!|Ýa®©û†¸6djôäã-Ù£uè•WóòÏ´Â?I›¥ÀÑ
+]+2 æÈU„sí˜JóÆä`1'õ⬢LH ÖKsqoÇÈTÁ4<XÑh ¯§†Ó6ˆ¶Ñã(äج`€èÍä0~Œ ¿¤€¥Sý ™­òkº‰ó‚ج¨j} È]wÓ/áÕeÒv¡c~œ¸Ñv†“Á·Í8ЉÕ~œ×øˆ~Ør¼ÊŠÖÉà BCN-‹5Pös\'jÁ,Z= Õc Zå#£ Óþ[:lòzò‚“é\|ŒãÄ´SùX™½ÕMG©¥NƒP§vAVÞƒXù¾}4F¯›ø
+äñÓØòÇ\££˜ŸD+á¡úÍ“0Z –C:o@FtÃ!°˜Çv×Ëñ V HÃpÌÑn@4!\ET—(¹ leë4XKq» _Ÿró¤ù ›pÌÐï´÷3H ˜äÁa*6)1_Œ …ïLÖŸÐåPhÓdàX*¸¶»“_Al>©Qcñ]_÷#ªfßqx{e& F(Œ\'¾ÄcòåÙì€Æ˜n¬¡ Â=£ÙBu·HEn4Ñ%$€Sö£Äf=§»ÀI*^[—õšÆÿ„Ò<µ&Sk6v¸êS4„ÑGn ä×*"oAb©*è›ç WèI„ý–hMÖ
+n…Ì0ð(:rþ‘öëeB~ïótay6ùN#Pž |F»ï«Ï¥|µÕL´¢€\͇~=S­]e¼UÜž;Ôvó˜»Ùc†N QÌ–ÄÖ”Ýs†{×­ïqH:Ôèxf ƒh´ëäN߉ƒõ:vC1g´;¬J9ª¬D—^"ÛVO!/4ýxË@ áùsÊYÒ}ü” áõu?}†|¾^@ŸgðSy°‹ÈT riσ ʯ„ 9‹@ȼÅÈ:mΖ? L7ßÊyêS|²"¹(oUoYìÂøSW~ê¥gn; 0µ†ÛÖ3¾æ> ¿3Â{1¯% ‡Ÿ7 ×ÜH£Ñ,¢Y¼eÁ/ ðo#<³à„[à^ØŽ3}@¢œ•r²ùkû¨0Jg†_e°ü¦Oßôûû€†1`cîv©¯¹P˜4¾Ê¦­™<ì–•ÑQY³Ü„täÞCòóàˆBÁåêYðR9e>²à—B^ƒ_º¿t¡"SCWKœR²àWçå˜
+šú™—à—Pú5ùE#ˆü(48lIï¯É–1®D‚•[š c,¼pdÒ·,û1ҥĦ©{7_³ T…•±›fÙOãÁĆÂËK·,ûÈE(Tóì—€®¹.©òA¯é/}¡uP¥‡ÞÙÐ,þ…`²â‘C‰”•Ç¿5€†‚m§_øÿ€¬lÅr[Û/Ém1ë´¸„WOcò’ÿB^ '!8Õž>öĦZ=#â—üJz×~:²×üÓ¸E¯*gÞúšÿ€t.ØäžÅ¿„„×øÌ`%ózNtf›×øÇ“EvS,IÒ_(<±·2‘øÿÜH}+§çR–ùdDF€¶#J!=˜
+a°ÙÑýØÈpå™j¡ºoˆùã¥î’¼}O^ ½ñ¡2ˆµ­—›œCÓT9‡éÁ©y34°Ï€ñÈ®±–Ðs‚>'ðõ9T‚•Ù—Ê“ƒèDä Ï¶ÛÉWè¯:™J+™›^ÿë¦#3ʯŽ›óNø‹ª„|'ÜB¿p#˜˜C›#B›„a²°ó¿~ÂãϧÙ(hE¢Q‰öþ¹¡ƒT%ŸJh 6# Z?MÂ×ÜX¨^¥:¥>ÛÑ»E›µãè‘V˜&˜øyÇ¡…­g|W©q]®‘Âfšy€ H#Çí=ƒlÎ#資µ¶íŒ/Ï¡¡°,Xxf§ÑÎÆ!÷X°MŒ„O¶“>äY 6ÆÜüä<ƒN‚EÏû%6²à„bÌ ¸ó$?‘Û@<–}NFìG ÿsÌa§ø4•!™ÿ‰2šE.
+Ÿ–úŸ¤Wÿ“´5yÎ+7¦`éB¬JÊ1ü›‘Ͳ]Ý•«HT`9Gœïã#\ðI|Äê‚¥êÌø4©z¼ê›ñŠI„-ôˆ%˜qßÇþ—ñ2I®ëØè
+þ´FõÍØSîÂSqÿSŸPïK÷C²ÃÖ­Ù<¨á뛢¹ËÄ‹+Ž°”XÑCº8sðÇ$Ô©‹rD*)ÓcL¡ðãƒóÐ%Œ kÃh˜Q½È½ï *Tfð ,¶é&RK€òP·©].]M46Ãä†~$%°x<[ït®>…-a»ÜÏ…eƒIáÑ<8ߎa-Á…µ5Ø Ã¦PÐõcJ
+ÁßJMÛ‰ ˆ©b]=ÆQ3ñ
+MÜGð³3Qƒiv _XCVa´øÈæ&š_ÙVe¹À–ÌKÚHE3wƒM¤W·)š{$,Im/R&ÔÎAèÜÞ¾~B ÈÀï´j›u+ùMNãS¢G‚µ+OíøÄ æ³éŠn̽ßf%Α‰¬D^H€œÑbR©eLÏX¬£Â:÷õ±QU
+–„Óòu‰±t™4”euÜ]È€ƒñ߸k,Õ-0©B¡–ýcË`°vŠ¼Ñ­d@ßP9”™Ã±ÐÉãš=¾DFÅKC"鼜ËwTmKŠ”à™¹‚ž4ŽUÓµ‘“Ñ­Dq ÃU«>¿MXN–Êååm^Š~^‹8»Hƒ¤ß}ú#GüÇ']Ýe±kßßVÙç:ÌRíK‹&ÃCò†À?ÌeÁõÔÄZïé;Žo‡@íŠL l›ñß#_Çù(qäôÌÖC±¥Ÿ¾¦a¶(ŒwP›0³U/)Â'6žÝŽ‘s·Åzm‰OÉ]A òÌ“bÕà žó àç0~|ɬ{CÙòZ·
+/+1B¤éµ Ï’,yJ·C@ÏãË‚)À3@“¹¿ˆÿ%‹2„¼UE«°¼ÿ'H°Æ‹x|‰OyZ×ø€7†ákëÄÇ Š(zš|äïµ¹qîFÄm¼hÒ'Ã`i'ª5XÊÇ/£;®À)×áI­†.`tœ«¯ÂDnK•ñ}‘>ÊŠ Ñä| ·¹ sÎV ñ€‚ ¢Üb¡åâjðBw¢/„5£1k~W‚+Cþ‘¨€Þ{ ¾ëÔ¥ý)öÉ” ãÀ2„ñê¹¢äI¿9•L ¹­'ÌÌ$5•6iÁªŠ³€6…¿%áÖÚBÜtõÍsV“)ä™UÎ7[ê˜
+ù™¯n×g¸,½‰Ûðœ®@”Ïb‚èRº¾äúÄœÚ:Ï IKçHÀÙJ·³DÛ,›Š9Ž‡Ã±ð6¸ªñ©ç0%þ©-̳Ë"ìë9àÆt wG3¢ "±•ãtU
+uïVOAÌ2¦×+1
+’¦†‰Ý>Wd* -Š·Nó‹¥D´õ¼d¤ ÓK'è7¨„}gb<¶@ÿêü;Åêë» ¬v
+Ó÷˜oa¤ùs§‹ýÆPº1â+CË¢„ÈG–
+ÃÊQŠ×5ì²x“fG¯õFÈus«ö•ö鶎Êñ¶êLàÝ–·Øø¼=¯šËÌZZ ÎõÝy×\ŠÐ€¿`»z+r$fÆŽ‚§u4wJ
+ŒMÁÕ)êý$éÀ«gß/åœ,1zväÐf‹\¬R⶙—.í
+^É^ 2Bn“ƒÂÀö-}/‚^Yí$t(C|Úu@-T:$;õ¯‹º´£ñE)œïû­ˆ-P Óˆ ž"wØ›¿ ô°¥FwÝJ°²OyF°hÂ/ö’P"ÞV¾Î Àk†ÔbA7¹Ù^û:‹7{T
+ï%Vä‘«Ë„ÀàuÈÉ0Þ‹.3ÏÞÄ, èokû÷óo–ôóĘ$-b/ðÅé Ÿ
+Š×øm­35ž}q¼¨õ·"•4ÉW)
+%iø¤uM(£dXWj£E öˆ©AëNx9•‡ù{'<͸²«v
+ÿ1^&ÉuÜJ]ö 0Ð7cz¨]hJíêsÄs¼ª,‹v„ÿ—˜D™7oÃï¨DV*€˜ÀbÑùC“‹b€â‘/É+Ì(ªÕ”( ÀŠüNë·’¯U’Š›î†Ro%*Ì.Ê\Ï`æÇ
+0E…¸(Dε-ÐÑ3mɘˆÀ¿«1c9ݬ•(ªxüt ÚQ;§ÊšðÍ2¦•°¡ˆ&žz¨@éÐì¤åÉö¥k‘¤>(cÑ«ØÖ9 ¿‹gx¦•Dí= jÕ*5È ö|9¹J§ì¥}
+gÕÈ
+
+œ‹;Á´ÐÒa„’àÚƒW“ô;%mM!ð
+p*|`¾¨‰^P¤x3³èrÀ±Èð´NYŒO|‰
+)¾íî1@PNüˆõ÷c
+ãU¥¶ÑÎm¼¥c•$Øšæác °/¤á2–H2¢Œ@…N
+œ³w¥kï÷}îEoûõ!^a3zOKØwi½V…©{e—^W¤ƒ6v‘TÊT"^$OÄ ,çÊXvœ\ò°!
+㊮ËÀßà h&!2y`á«£ÄnÓǬkú¤5즊äÕšB'¦tƇ“
+ÑÍ:b²^é èQ ŠÎƒ™u¶€?5~G(c T”GROØÂa£Ã€si& ª’¦w ä©Oâ*}¸Rö=;%úôXØIl!ºçÀÄ€¨ÃO/ñ³°™x°+@L3ýl°ÈõYyþeß¼"œ@‡¥Yfør®‰yEìÔÀœ,n^˜²na¸Ø~•ˆð—¶áOyÙ/Ï:$³f¥š0¬cýÑÇ:‡3¤Ìæqþj2?ÇC}%»Ú±‡[…HÕ§s®#¿ÝæçUwÞºsƒñ­ÅNÅÛ¤~ca´ZÁV+kX¬<Jí þÏC\¡{£h°ŽJ
+8̇öÒNÁ€˜‚\%ØJ;KøÖèÈdÐ&XîÕ"2jÅâ%Û lê2ñ‰î^¢T€E/:æÍüÍ.Œ¡ã¸.¤¼{&pÁ®ãïЄ0Îm*®,(Ð •Ì¼íÜìÂÈ~#RâoÃ^äü¡òd›=v):tV[ÝÉú-– Š&4 ëFjJyàäl8´8fýó‡Wt™ü×CQ×+ñù½ö´>ÆfÁÏÈOjéø–‚펩õýp0Æõ &Õ ¬ËçpvéÖãΉvSnÂB—eº˜Çº÷˜hS…V”K²ò¸ò–Ï*¸nƒ|ÆŽ Î1dM6¡ÇÏ]H‡¸'Ì\Üm8©*@œ¡Ž¬0
+#·åB’Au… ›¹€¤–”\×9ê.%ôgÓ&“6Üe,¶ ׂ–é1VÍó©¿l§y©î&ÄÔNYPz‘ðôDŠ?«ˆ¤‚$^^[¹€ÃÐ-±ZV•ò†¢Gó6‚…É:Nÿa³Æü@¢À7οíìt;g~p1f¥5«“W @•´“g؈6d[ç¼St÷H\¿Ìܱ²¡<ø6§èŸü¢ÀnSÃZ‡†ø —žÒ´]¸¡6%T¸d•ðÛØQÞQNºÄ'AúàŽLøÊXoÁÑŒÊ.ÉXĸJ”Uv§d
+¬$D}hîr cŠšªå.#šM‹/*0¥¾ÎhÊ }òùõ¡N4ÉPy©Ã¬uÎ!™­s*­Î› rB˜ˆDÌãÀý"£ŸîN83Ç
+v?e˜°Ø9€²@ÝÞ@œ¯ºÃVôf% O[ƒj÷@Í~J&FOm:.¨ó”(êh›<5¡UWXb›(ñ!•F.^Kš½ñë.Œ ŸÉâ¡èãZÄÇ §"ÞYÉßÅIžm¡\a@ ²¦;Ï ”
+›È¬®šMì H$v0Šì·Ä®¯H’ìºP”BCœRZßÜG{ä% §VŠWì<”ø§qü5Ë6W¾žLG£ƒ­ˆ¢íMñÄ×yÒE`¼ãzžæÉB` Õ™*ø[Q‹Î­õóÅÂNÛÄT£„ÍR©ÿ‹X‰00"O|걈g²¯´Œ_6ÿZ¼Ú6Ÿ?ŽÖ ½œÕqòþª¢4 á#µD3ÚþàCÉ;ÜŠX£Íí¨Jyu¹vx’‹ñfµ[‰]˜ e»â6»
+ôãG,Df‹ºÈ³‚·¹á¤}2"†.¶LbŒ±üô„üÐ&åXOPÃjNô(„sˆoSÉg÷¸|òÊñ)l0ùllcÿ!O‘›Bö`‡|bVô†6ó«’΂ ®r0NÉÏEË8™„’ÝðÙ¸<J0iÇŸB´¹’ ’“×
+05ä×4ì愼U‰dG à~|Š™ª[IÕe±(Ö4F®â.€Ï4Š/ÄCÑÇ‹¢IÀWš}£ ÿ2}â7/‘²6X”â‚ác}¦œ]
+D…‹î5b×ÌZð¹®°y( %‡IfïÀÒ—ór-Pà饾X†GÛÊ,±,ààCg,Ãûe–ú6¬˜S<[h­){¹D1/J¾Xñï8ö¿þó–Þÿõß·¿þ÷–ßÿý‚¾±«U Ïãì3–Bڼѿ_VÄí ®ÙТ})ªnMZI ùLî–Ë–åôMµiØ%Šûï¨ 3Ù©€ÃtWºc2 –
+\©£* \‡vœ(Ñm˜æ°’¥þ­k ¤q0bÒ’’î÷·{‘®C·8¬mŽÝ¹nYM\j—¢ïáÀh
+2©|qU(ƒ"^R.2â…²×aÇ&¹pù„åÖ¢'R«…h K qÿótÎúÖd¾1¶%îR»ßE¯>SF*Í•rìè”g&`ˆJ|)I/ʈwpÚÀ©›M½ÑÁReheÂ’ÑÝ<v-Œˆ7ÜUð7Ýj4\ÚÁÊ´3à ™cmdJi·òŠ•> {ðôÞg±W¨5›ãQݾ.q™á¢ ™ àÜÀ¬ð„€’F
+€Îç°ÅsH•å)’/Ä#ÍQž&é‰×5@:+9IóRâŸÊ£Ë§°£¿8²†àr—ý‹+½Aû߯%Ýì,4€úi£
+ÓG认YQK† jÓ*W®«JªŒ•–¥õŠ3ù• JÀÅÚÞü±>C@±Šs[iíh^ÂËÙ%[Å(a¦r{mDbú-„>ÍÝTH£MÊ5¹L²¤t™žm-&Ò,¢®v)RÉFÄ*
+”Ât¢¥¬8JR†d7v[·VT4RÉ0ⱋ'hˆ§AåKi+ÈlÊ6U9;EJªÇ2ùÃ0U¡ÌZ[I.6Æyí¼9_:¾'ÈþV¤ë0vCi~ØÃA¦÷§ øgч·p·Š“ƒÞ×­H%ºmem`àP–’̲·¥Q«¤£bÅÁ ù°5£…; üiŸjä@pzð–!ª 'ÿ¯fŽËJ1ñ©ŽoÚ9i|¯J&öÛ’„[ãKÔz²<dÌoœÛV¬„mû TüŸñ2I’ãØè þêm1kmy n»ï¿ýÏHÒ˜‰²n3I&Q¨ÈÀáÃ7èúë">‰Äɘ
+K$¢øUõÜßÕ(n&ÍŽ¶Ù1è.£UuG<Ë>Tù‰ónáæÁ&ºôð胫#{÷h2$ÎÀƒ
+]
+Ö•p(e){XÒ-yA8uxð¿ƒã"ãLƒÒû­è3,âc˜ýÞ‰ºì˜éÍš B~Ÿ¶_eÎ<™ƒÚîқȣÇ2¢(×þfÈ£%bM½¢NÑʤ7ÁéºÈ ¥_ÆBãcEÄù…xÒßÃB¤DpÊ©àE.?“Y„!mVˆ`ͦ&¿.3zìP¶OåœÈX’ŸÞ=LÒ.¨—fá/Ó‰jP›ýšeÊÚ1ø]½{V° ¬Ü_šòYƒÎ,0ó²øǤ5R½.!ÙÅ>TÙ"v¸—‹ücKX©s´Ô& ”ãÜåYô}þD¨þš+¦ÃúNV§ÿ ”d°‰8w”öëM‘¬ é _cÜŽŸZ
+gg(C"»y‰`Y*ŸÚgwØO†»%xûYSáýf‡5 _<4Ÿ$ËœNûÿØÉ‚Û`ÏÇuÕݘKæàÃ;d%i‘¥‚iÍ°sŠžÆ·°ÇÞ8nnåÝzPN–—>¤íWá8dVW5D
+Š¡:ë‚G$qEá Bn‚´¯H^«š›èO2üSß•4­Nb³ƒ±ñÃm4úeEE±¬ÎÉÍ/)ºpbßfc)Rà˜L/oÞ»h„]¶Hà- ;ü)gŽPJZgeë'‘ev|N!1%>üý•}ªœJC»‘zÑÓ¡mì\§CdSº`·»aõYôðÃviÆÉÀõçE˜t`™9Âá|¾)Ê$î=ˆÓ!z‹
+S½ÌS×­›'²ŒìÂü8MxÖ³*R‹ÔJÙê·Í oƒ¢gi³[9~Tõ˩𧦠™|º=ÜŠmA®tøp ãrrÈþ›shŒFÛæ×H¾R©ävnÕð‚ígùµ?›_Ú¼žEÏQŒ­¥«((lòã¢Ûf|þd}lËÆü`»‰kŒûÈDÐ2bjÓ·¤Õ
+ *%BZ ˜'Ö…¸S…BãIIê·}w·áÏò‘þ‚ñGJòŒ¨Ù!A6QìÓKÔ~È›R‚q'TM‰× Jô©¥üEH›èýñ¸sÐ>câ?ë oƒÒ3ì™aÄoB¨PYZ€%kqc–R'Ä8ÃöF%ÿLÉ?u+‚÷ñÖÄ Ö6¿¢Ë`‚ØÞ®´ZWŸ„•Â&’½Äæºw Ò0çLþ¥{±@’©,²Øñœn%÷yçÜQó¸ÍzÏ7=ühÍc îíýn•þ³…cëLs6Ü7Ž<ºõ¢=£¢_aÑ3gŸ{rÅ÷wWd¥Ì³‘»ë¼kŸáßé×›"E¦&òÃŽTÂ’r
+¾ãoå«ØО&Âo@,šBà är- 8Ë7å*Ð][9õ@qb‡’dl)‡PY3z6M^%(Ñ—ˆHüw7Ò?&"8‡ùƒûU€•·ñk[zÇC­ÂþsÇüçQEé`ã´M(‚É(!Pvw–e#ã[¥kŠTNW7“k8 q¥×¹q&%éikGÚ¼ü©‘Aç<Æð¸Ìsš·G/ÝAÇØrTK̵_´èÄÐÑäºß•üã/ÿÇ‚|2ÈÃ'yí¬ô†ý ÎûzS˃Dˆ¾È% ¥À©÷Ò´Ú¼IIY&:ø}ràâsoccÖ^î~už
+ÿbÖS½Üì¢c«‘›šu
+$‡^c ëÁ9V>%„MÿQFÝT’¬ Á sAlüé¥YÉbì<ÊÕ>pj%“Ò|Ž€3³c¸ÿCÜýÏsV¯`›ÌS Óý43ÝÇLìâôìøLÖç¦E³˜S:584U¬œ•ÂYÑ©-y ú¼°RPÍYL’C‘V^”øÖ%ÌXa„LjÙù*îs£¶ô ~Ç<{9õ@yú‰k¼I($d€í_Q‰Ï°˜ÅÏaüµŠ”™F(XØ?‚Œ’àn{„%,ûÎÄë(õ¦Mžg2Ö©¹¦‰¶¸…ÉÃi—Õb\ìÐ,úЙ,ê7¦/ZmPXàc"€ùR [Pr¦É>Mÿ(ïιÑìÔ&çZ…[s„O¶ÆŒêÀƳh’/L-s—Ù–ÓQQ0<øÅ# BQ¬ë_/_õ6µ¯H^àœ±È>üSßÕ_—?xq.8g|¯·ZÁ”EXEFäËŠXÿ&Ã&B ŠTÒhJ‘7˜sº+Bå¶Â˜?˜LD¤hÛ]LÑp.‹‘Ù%~$KýrNä1–­Š4ì˜IìµÑýƘIa}Êã”üŸñ2G®ä‚è xÚ2ØSA™ruyS÷×ËÀ»«EÎ0úÃúX
+Y¹0Ôä’2ê ÌUxÁj¤fHôŠtx›ÅÊ4 áÌA..¢DrŠ>V{²Ä»+ÏyE*‰²8(D k–40üq•°xÈ 'ì—…7‰+Ä8Èú4P•áÌÇO©¬¤¹ƒ
+2M5H·½ŒqÌÀ,>•ðþÕF¬´³Ñ¥†.×Î+€1çÎÉI¾j»ŠoÐõþi®"Îíñ§«¾¥!jZÔÓËÚ—(Éqô‰ZƒÕUÂíG€©è\]%'%ù¦SÑP1à”Ñ­zp¨Ù™ÂÆÜM*‚÷¹~Ý ct .šË÷9  ÏØ„&wð¦ácvzî‡'›òµz]o
+uw&´}`je®¦ò®¶ª͆™˜j_M燺.oJ‰ž¡ˆ¢iÒ™ãI1&šl¯¤»°díëRnMQ
+ ¼Ò–9¡Ú¨ÀÕ-ÁuUà>É z !ògdçh£9En›¡=!xÕí¤ U»„gI 
+ÿIéÇEöÂË#$+ºo÷£"<V@O¼°ùt·ˆ®`M’º­ß UCh«
+$BìHŸ¢Ät²è„—–(Y 99Oÿ_s©
+ì0Fü#ÿ¸ö“š,l* æù°
+RÃ'e|L,¤3Ô™Ú–„EAh8ìPv9í"°{Íëð'ⶠ,‰Ù™ë‚Æì"ðE´$ïMïÞW÷@‹‡ÌÂä‰à1ß…P¤î ¬%zãæ Ê¤à(°÷ àxóVb’£(:²•?C¸Ž••še%ƘCf‹€N‘ƒ?F[ve\äÌÄ}»}™Sî—¢5óí-ÈŽ¤Z9q@úÂ\Vׯ‡¡ÕÃIˆ8kå©[é²—iÇh¾N!)®Š€ž±L>JÆ53Çeù0LÃÀQáÒ½ï õ³]H¶JS( Ëy¬c‘SÅJrÑÁÈ»¨çŽ&¼:N»©¶vÂp<¦€æãçàbrWÊö‚«iÊ2—¼s©ÐËhoV‚é©2¤HÈ*±q4+ÒÞ
+W͵ÑTd[>¡‚GÞÑÖAÃI{œ…ß®’Üý™-O>”D‰¶Â&m<[]Š®ö‰é>ú+37<¤„è‰fÈô^¾êm•wCÉxLìböt»Êä€ýêš*ªR /ÁiŠo"„>‹À¹)»ëðÀè3º—~%LŒE¡-‰ Æ‘@.…­h«½ï­ £°§F`7aOüC2£Ëì…ÌýðmH~tFÝ+¡¨\=Ž`¯ÜæRóáÕÐt†#)Éa@­*ظQÓ¾¸Œz,â\Ã3"aøÄ>«S²wÃ0Ðâ2–ÉÀ±ms?7ÍÄ=gµx=&Ô¢çŽ]ºqïÌÚˆr~9j=ñT#cËÃ𗎽K”øxqΗª[B!\âp ¶8ÏN·¢/^‡‘PÓæíöÌÈWE•Õ`èÕPïæ^%iFkßÓ=^¨©bŒÔI džt#F•s «¤˜±¥á€×[ò |B9'öÁ-S‹IÚ
+ÈàþÄäηܴñ0CTÓiß…'äc6¡G6Ác››µ¸³–cQ@
+ôÒÛ­D 'ðLyÛLà[ÐIøK õÃÝyéíDó¤‹øk ©!2}ì"|õˆAsjëäu\BMù—ñrÇÍã‚ð tÅ
+~ÌûJ•ú‚3*ôýýÕLaîö‚4 ?ÄæÎLwUuÞm—ÀRšÕ¤U “ÄqI'Ý‹
+KÕ+6rÝxLÉÚ FÕ¼SL‹ÄF6ñ€ØÇ3Èÿðý¨Ù>k_¥zPƒabuÜòúNÖ€˜‚Ôö>ÁðOóz)RmêpÇþì"iìड़Ý<¾Fôe
+aŠÁò–N6\“HÇ „]§Ãûr2SR HTܳ<5ž=¦s‹9JíX#›Y[§È†V9vca ÏdˆÐ~׶ìPU0¸ ÑýNÞGÁ(kÔZI0'Yá±J +K9’x›
+—&¯EØ3ÁU¤Á
+•KN…œ ²æÀ¤øRo»„3q»x–“S²GQeuø,ãá;¤šÕ‘ü8ÏmPrD "mÒàDðwÌ´&ËK Wô)a¤A¬*=ãÁæŽÀ Rà)ýCyL9AFž åî%t g:"s
+O2`nu‚JP]M6M¦D/ ù’¶üvN¬0P Rrõq†±s«‘!BìõƘ·OqjJ`í pƒxI^wؾj]KXh5ª$2K¼Ym'Ô‚q8W¨ˆv—kɇõúö•,wúão6ö_ÿ|ûñï·’Â+5­*®ßßµ®¡’l¡þÏ*R€•Ñœ¹}4½$y~ OÍ,OEÂLšÚ·×éVÅó¥&BÓ|ÖûåëNè/-Ue~,ãÔhrWÛ”1 É2~µ¨(Î×rós–`wº)’Á¸ ØÕ*"¥.ÏÁ’!û¯ãK`¬èÚ(XôûÄ—
+g{˜pS%Ϩ1G " Ä&œë(úõPTF‘8¡eYZêá!½fŠ÷RIR¤ìÒÆwúý_“W »
+Q„ÓÕ8<k-“ĺÒ×ïuTÔîf· K5È6Z&c‚«Ýß âߺѴȊ.TÀ*=ßÕŸ‘øÏ€!ßNÉïÕDtŸ/àÌæ9ßÁ˜.øÿVÏeBËP¤Ræç×S4-åQÈŠ7œ„Ï MÉÓv¬‚ÍoÖï{ \•àH“­ý.Ü_•ï_˜ùñî*%…é4©qs ìŸUT¸DÀ¡É)·¢º8LY¿yò bÛƒ¶_¨«¢ úÌ5"Ü1ÿŠ ±ÓKÃϬ÷ó¶#›¯ÿÚð”2'}}†€ž*„E#6žEŠÏH%ô‹PQ—Æó½"vK“šc¸AÚB³W„ Ð8
+N™¶cúß!~°ØÔ82;C%)Í
+2PÕœÌ ¹á‰I]G xÌ„E°ÐwÙÅ*É™õýhõ‘2œ fG+)S_AO«™8Ã_Cö9­yÞ‹è²ØÀ`ßâ
+1ðß¼ I¯É)z3ŬSÛ¥©»ˆéãpCÜ£ÀM£Y<µÙvA=¢\nÓ*YœÁÌójFÚwÅÄ%è:žÆv|SÏüÑÀ"K´w!•W®Ï@[¼ŽðÓ’ù…”^-rZg­ÿÜ:i'ô("{E*Aäp–8Âa6CžTC‹¼+ˆ!p¨ö(¾6dÚ p¶A$dzTü}íÇeÄa0ùÕ·UR
+Qy‚W¨@ iørc”?£äŒ¶¹Ü¡–ÖÔ¤Ü /" gÕ¢ÏÁð’$ËÐÅf·É’V”ŒD—w ÀA¿ÁÅNU à¹Iœ¯‹;÷¢;˜¹4?Cgz(g¨Ÿ× ®xx¸¥Æ7ká­&Šû
+a§7W"\ü)Ÿ~.Ú)¬àC‡däd“<7Ú•†p"ŽyÆ1¸Ýxîç(Ƨw’büøwü×?ß~üû­²PX,– S+Vú
+½ïËà˜Lg¹8%:)[€+ôã§.߉/þ+V@Æ#º{Jz!/ÁŠ*’3ÉÙm%¯ÞH
+ñ¼êÒb¯äèì¨[QÇèù
+†Q ˜QÖ#Z9Sq?f ¼ÄY(ˆþî˜0ëð
+¥Ë"ò„ x»jx§¦.»Ç+‡¶”×à2}‹)™º!v«ÂÎK—ÂÖ¾æ W„³ž•èÈXU{E )ý% ázHÆBH /Gu˜°¢á×~DŠ˜ýåˆØD‡éc€uùŽÉY®[E÷A€ÚfÿZ"§Š0™­¹âÙ¬jã¹`["º?Ä‹q `®Ž˜-boÞ˜e`˜ž"¨¡ƒY›S+”ãÕ”1ˆ"1vÔ°-¿óo
+;pUÎw ‹jè×ùÒ«&7©8ž‚×ù1Ä«%•É-@Qdƒ¤{ ÝÕÄ£tyZœRE³¸^ø§l0Fa2 ÎÁÅÁ1¹Fûèmã~Ɖ/u¬%z6\©`UZi7ŒÙax’Úç¶%AýÈy0Ž<›Ýwh)ïV¬‡.| ó5¾N‹|kÁõ`ãqxt D´9¯³vLçF2Hú&æHz†ï7Õ ÔBH¨ónÇw%x¼ŒÍ“¿‹/=kÎP1H›Îù1[ËxzI‘Pzb!úßôl<%wûW\š²D½ÖB-»R}E(¡±®‚èÇMWqN1¡€gU§P˜«‚sÕ.%ð“ôÒ¸Î圬.ñõíyÞ†v+¢2 E#<¯ÉÓqÆP
+™"Ô…s®qh £’M×) >…‰Öè rˆkѲ®y-1% !þ¶ÍŽìFÒ«I\é]óËkXC¶É @çB¡bÃ2Ü.
+ir|*+D½Ük4ˆžícØ'¤ ee‘¢Ç¸:,Ïô’,JGÛ¼˜ô]jê'Ž©ç,¿ƒíü{טW¯þÇE¶ù¯*ÓÖ^ï"öŠÿoEfd_Znœ0};(EKhÄDv|šŠSS’Ü]>%?7*4%‘µ/ù›s€1ÛtæáZ, fÓê^
+H‰Œ—KŽ8DOà;Ô&AJ¤D­=˾…Y•ï¿G}Üp¦H4PíÊŠ¤$~"‚Ú¿þS¢?†×&cHí­|ýóÃ¥>¤»-µÐ è{¿õÖ½Œ²@M$ji&U‘þ÷ÃÆx´æÅTÖ&Œ/ªõEÝ¥ý~]\U­ÕèóVò(­×"R¥ ²ñ‹ö6š¶
+èvÜG ö-š‡›ä‹¿¯ þPn Eø|ÄׄD‹È<™ìŒ³2Ì¢™õ é5ZQsñºó]ùµzá:¾~Í£úhãª÷ᵆð~/3L„×(U¬ìƒ¬!ÓÅ"â+³#\½“}7ȯ™BZGt~ôxGûàWÞéõUlTžMÚíëVÞ4¼·
+¿~^«ui4+â­Se~&(x†z”Ágóåƒô‡Ñ #lCJË(•Õ•ˆF'¡ãY9vúÞµòïQÏqª‹Q(VÝÙÕ‚påÇ„(!y]›Û‚t˶‰QÉÑ>ŠQ‰àJ}ôÝ9ÞLIc¡]V=¹n–¸é°“B©L 6íWÈS“þüq]Ú=¦.ùY¬ƒ^Fðv܇ ¿há>]O ¤ýú/Ðö`‚zĽ4íï r/•[ŒÁ÷/ „ÐÓäRRÂKÛ&$¬J)C›D;eéµÊ7J›å¥ ÁôÐÄÌÉ>ª(g:›]Ò³&͸r;³¨A®³wÚ„Ð@Œ!ݯ^ßT÷’Ò‡íª3Ù<jX¨fH{|Oˆ1O…ò0ÙöI
+3ðÿÍÄ8$Å9c„ÙUf—,À3Ž¯ëú`¨m_7›¾R3'ã†èœKNœ2Ô}Ò3ˆ”rK @mÆ™¥ì 8½kžõ.Iã2è×AZbC8&y‹ÄXìj ÄÓâˆÙéf»t’ÖêLŽvƶ¥¬^ôƒþI»ËlwîÀ* ^¼çïÒJoð^Úp¢5­•Hèê°H…î!MUp Mim7a`ø^'Y›¨ˆá‘nÕN»›Ó…½C »ÝÃé :Á˜Þù:fY(#9j7ž=6¢ò0­±tðÂÑY$ï1Æë}åé?­4Fás 1þcKåöÃk5¦+ÛÃ÷QÅPmÈxï~:%õBb—tû¦pM!ìEº#ã¨DãÃ+¤Í2HvKüyÕ+m#
+£ÔbÁ³—a/ñ¡3áU§mLˆ'Qñ‰U›¯"[*Dè|ë<*RBhp‘ i-<m\þ•"²¤"º`A2 *pgYÅDNÊéqÜ™é ôÏB3ƒ—Xí>ÙédÐHQ¨‡)ë‹NÑ—D ÙsjÔ_e¢ÒÉ,Æeúál|Øâd{ mÌV-»“i”YRd·7t;­$±.*„©è6’z¤Ò³RšÚ¸ 0b.°\È:Š00¬eÑÚ›8—rŠ ÖáÜQú³·X·B2é&†íÛÐü±‘ )gh”g®aÓ;Ù1¤ˆ6ÄJ-Ne`ê¦tg'FÃÑq¡ˆq…8›œ\‰-ÃgÕ}v_S¥\@ßW‡AC$T(Úì%CÂc›þÁÂÁpµºfùuÉÍů‡»–läÎ;wvÒA·ô‹c=*©\Rö¶°ÝFæ2c$×»Jä½TúiAÄIN Ã%
+¤!w&º”ãr¢’_ú,:™ PŒÛ‚à(1–€Y[C3î;\ƲٖÍAðÛ´ä=,ÔFª½´íc¸ JHØžÆdB á&éhfÙO£=Ù„çQ=“9G\|7üÜ-g϶†°‚`a*ÓzRL‘J…7ùRYT“„†´M2­_MŠ^tñ JCÄG–¦­êf‚WñJÜVz{[‡Yö-Œ_…c##
+‘Ú˜B̨|ëÈmNÝ÷y=-'qZT
+•FJ‹Œvs²¿ß€^Œ³¥pñ<Ìx”ñ1èbæ_ûôdA¿¯ *‡æà¶â‘ÍVSòR7Ù¾ÎrZpÂŒ7|<¥”wð×
+5Gi[JiLƒgI%ì÷k…5Fï¬åÔ—I#!†Y\f³±¤$)ô7N‹ œqO'tƒüšILÒÙ72ÞÄár°QŽÃ ³ãáDdvãk)žŠŸ×z]ZàsÆæ¹¼ƇÎLÿp×zDª4Ùàê’rzz] ¼x¬š^Àýÿ{Ôsœ6Ydò{mÇc9”¹<­šS !š\c×ΠqXr´ÂÕê8Ç^²H‘F|Ïtûõ¡Yt^ìÌ<“+(íWÈeSz]¾<<…
+)û¨\p5žãLA¤7Ü!f‡<9b¼ÏaoÅÅaR¶UÀí°L,J«3K™¥¦qémÓ NÇ-`®Wü•iÂ:”8G=žõ;ïF¿°²5¡¢Êþ•Ž|åNÓÉÒntÖö8sº!'Åv•r/é”Ví˜P¡L3,G©³Li†y"%~u6ÂþBàôQ}¼sH´žnÈÒ‹^â0‰áa*Ç>¦ßl¥¸ó aïµ\ ½ãê¬üªï£FzkØ
+>àXxœEE¤ÆOfG#¥;
+£Ã.
+áÚÖHÁÊ Ö_·üYÀ"SuiKäZ˜+šÚ– È=}9)ÖÕzeš<,‰Ó} ë‹Ê4ý$#…D‘7¼l-!-ÑßA‚«‡"O»ó^18׊~ÁØ.¾ÂH®}ì‘cÛ<ŒÖêñT­ùnܶQÚ±0P“Q\Ùi¹g?äb‡¨)iïÙŸ_7I}1f2ŠëÒ1Þ< gQ+½<aC3†Âa–cÇ) ]ÄOã~S ³–cÚµq6-z“„ý£dä¹ö¶•7m4[S1—º° Ès»-/
+É7b-ºže5Ò¾5ò ‚Òi÷B"œ¼At²rá
+ŸÉ=Ù,š^ÜŸ Ìáa1Ù ¥hòNü¾îDwŒ^©˜œ¢²ˆGW¤•wC9Þ‹Dig«Ó…B0e¥ÇXù)§ YQßyø²~-àíœ{°ùÑ¡%Y„r¸Ý,ú¾fä$°Úye'“šà >”Ú—Ç-¼½@CH€á Òm¬˜:Wý"k ÆyVDÊ“µíÔ¶¿+¸¨•aqÞE³“èfµï"¼Y¬jã¼îêË g潊ÈiG<]£èJêþtØ
+#kSµÄ#¸y\]•¶ Bä³é¥úÕzfq(c‘ëÃ9$ô„°s:OÑ6T¾ÅäQž'±×à ô”`ãR>ñyáoBeš!ÌЦÊ$QÔò1‡äK‚l´‰ˆÈLåƒ<m>ƒ¢H óKØÒ¢‚Ñ¢ÑCèË…l½A£Aƒ$%¯K\:A)È¥ÕÇÖ^ÜãZ:Á®xíÇ £i=ÆýxxÈ`aQ0“‡¯Á’³
+I*‘¶ÜöMØâHò¸Ýtå°oWÄäOßò
+û[žæÛÇTµ™’ÈÈFV0MÞ¨c%)$*óÿyD³ HUÞ ïÖ¼5O"ÅBh£ãûÉ”g•}±í&ô8F)Pè{CŒˆÙð.$;&*vÈ?Üóƒ†ÿúQhÂ>b’¹ZjÎl,n`<z)Ù½ní lU-6%œÂö’fïB
+†°_E*×ÓÑðT·N)­kýA9âÏâ.¼ošÞeR^1П3]”®pÿä‘ú’Ï }ÙjG†¤¸º¦ýº¯Ê‚ˆƒ!ˆ½pÖ¨áT¬ÁÒ…¯fD\…Jaס% ÷ÌúYîK2¡ BRÕÕé…Ÿȸ©!õAÛÙh°&mƒXÛ¢Wb XT/Þâ¤Qç!)dÇê@3˜<]Ì…ýá5
+Tá'ÍkëTÿXZˆV*RÑÆ !¯2çdf´oê
+ÕË
+§:b㨄4;¥±òtö¯w}«"1¢šã¢:1•^ç1BݬÐ_Iô™YcÅ ãô›Á ”–ÈÂ{QÕA
+ÁŽDô3RÜAê|`Jð´jR ý‘%—‡A¹Ô8Á6ÇŒ>=õŠ%1FÕz¹{Væ¾Ï}UãwÃGo¦AÝdÊ&¼!³Ùå쯫„wŒSžðâQȆ¦þ}
+rþ¯Òm
+ßêkJ µ•“Ä®
+/“@¢,ÍWøÖHD i´èèϻĩIì&øÏîªaS–`“ј3_ ›Ü‹Ï•ª¦áJ<­‹ÈŒ¾:yÚ î@ ÈÎå1H7±ÜX“Ë qF÷˜ñ"j0Í£!?þÇŒ×à`8ÄÓR|xKñ"Â:ìg¢5­ªã´o0?ÂR'ò•$þº“Œ»2ZhrÔñ)è.ñ.è]âÎ’¤zøõ®ñ R@{`ôÎ]%¾i7¥ßØD#ƒyO'` ã/r©Þ¸Á’%rýÈ‹k’œ2gWâdþ*)Îx çMâØ£¦æ!6_â‚Q‘G¾4ï/
+€­Bñäj%QÒ’iBï;&ˆb_‚Äa"y–‡/%£JBdä†?ªsÛè`—",
+ð¯ÝÄ×Wø³M6:Á×
+ìmCÙ:F”j×’ŽD |ϵ„eÍð4­8]E”gP QÏî9(-ƒ0gJ”q+" ek’t/È/“#;n%ŠZ@Ú˜×Ôò{¡mÓÿí?Èb¨«²‚½`H|ÌÓÀa*ÍQ¹ž¼ç€ åÍÝþgPC§À ô­²vÓ¢ 2´(S©A…ŒhÓDàj†+MVÜ °uÊæÓ8¥t:Ùž:ã]YiÀ"_ˆ¨c4ijŽBL½# ®¾±±‘…û‡7tÉuΖ`§„œ†"I—¥};çÞóÇkž³dõÁGužƒü¨qò¥Wÿ~gk´`i/XþY•'¯ÄVöà¼ß/A~ñôB—D
+Yœ•2›’ò¥%ÁvÁ6·íi‹Ÿ<pº>®¬ PóO•ø^x
+\î@CcÈžœõQnàÒ EÖ3ê} ]36Р5¤m|-!. l‹%¦Çjp€"¹8¡n>ÑóŽºY½S{&e–ð„–© â÷²ÿ¥L…ÔÁð$HÒ‘³Ñ³)M’ ¼rB(/›všó!ä€ë«‚Ÿ²—ùtëýçKÃ=¼ô'/Õ˜!‰ãx(Îê3*㤎åLÚœÇø*¹Xj^å(îKR´9Jøa3Å:ËL*/Âð¡)q OŠ*TBȼ…8:c¾Ø20¿¾ÃÛM¯5O»^ÃÑ)—f>cZ…`5Aàž¸&o(–†2îhQ‰i`ȳ2m²˜
+™á%Dƒ³õ²2Û4q ,XW,úÜAœI]µ’—ÀIÒÛ¬Ùç}û[ÙFÞz”8!øBWæå2Hã,[ÒÊ(žx.8Ș„k|øg]êJŒ¢g/ñ¸%šÓ ÏyoØ‚Æ=yFA
+
+‡`öQ‡c¦´¡Â¬xLd- „pÑ(…(UäÜ6âAlñÔ¼)Ôp/hVBFVv.²îþ–†¤Ôi¥œ'3y[¹Œû"pK;;.
+Gõ1Ö ÀÊ2Tgƒq.[3SFáM ‚>¿±aGíJéóì.Œ)Ž¾Mº† ö"”^…µ‡<–¦I€©Í0n›ò!”»¬ }9¢ ’óVPFë©3ñe´(DýÀ3À­ÜK ÏÉ?¹U|+ªiŠÓ­Z¨ÈÖHýEù!oÝ\ÔÐÎíÒœ»Ï ±ç5Iöÿ»Ôðr± `÷úvPÐ4®›h]’$
+º½‰6‚?$wçÍð*
+jkêG4dE:¯
+“à†éWýe5°ùãŸÜÃ?0‹L?v©ßž ±ã÷û%¨u„žM¾öC!½“¾ f:mÎ ûeAxÞÓ6Tѵ~™/©Ì5ió&AKÚ¹T%줈âi2°â
+ΙŒ>஀-âMBàjFiHºi!ä¨H‡qêXá1ë'sÈﳓÄåÏÚ@!¢'˜¼‚Ì>éØrŸG™€ ij9‚ &Û5Œtl3fTˆÒÀ,°{_fSv )UZw5Ú$± ÊæUˆ6€N©¥¨Q¥.*Ù£A /é¶Ñ’î® ¨i)IAçiDÍonm¬Xkîfá‘Lºâsž-¼æ9:AV|ç9ÅG!_ZõïwVFÛ•öv¡q™ )ùל÷û%f×Óá$aW"’@ÝFr¿pg…¡¼§Hæ
+Ѷ!
+*ä)›åžA·Æ¾¡¶ä_éá8yaz AÐåËB° 0?Nêð D8³uÙ"äWž8c‹2–¬®„ˆÎŸ¡ÚYcê͘H€^Z=amØ,Õ§DXy‹8Ív:#ƒp´ø& ¥\ˆÈ~½¥ËkäÆâžùìmÌoÍW3‡jcH¬ù€&ð­JÎäŽÇ´Â"
+"c)¡‰'3(æ3 b™À$ë†YüPdAC9WÛh™i4»FqG0îVq»#»ÇNPÙ¹ýÒ.wCÈ$5–7&€o“IÓ³}Ž³€7@—{7SjmžÎ ’¾' BNgE:jÀL¾CtÐg—B0t'iàò#jIiCQ½lJÛÌ}Q´Ÿç98À®zm²‰¿“l?3€Ý)ùÜcÁ(tÃÓ¿ÌÁ¢68pHɼϪ»Étið‚cüA¤ÓpéTáêõƒA˜-x1¿)/‘ Íä3ßfô%Ÿ!Ýçi'Ñгx ó«°Q$‘ˆÊ# ¹Íè¯QP0íhòò¾ú·ƒ‚ |^÷Í /¨/×-è ÌÖï¨þIï7䙸Ó@<* .þŽb8‰&ãÂúÐv¼¥Û~ŒƒÔò‘eG`3/ªØËa’³[NZÝm%ÍWÑc%çmcÑèìf=‰Ê n<ê'„QÒ8 ɶ¤+2c戤„œ«*w#0!°V_ΡS¸‡–º`$~ É0‡™)·úš•…¿ŽÚ_Šc$ÄBzÓ_*|¹5ʯzMDzß7ÚGô£¤ƒyéLëÖFϬ ~E©bUäîWÝ«cÒK…
+/Àî³w&›‹ºäQ=ú_ Æóºÿ3^.ÙuÜH]÷À¼ƒ?cy¨]hJïê@âY¬B™r©Ûì$
+ÈOäKÐçŸÜi)F$'äUnÑU¶‘3$ë懘®,°EÀµ|dYÐZ¨©¹w¥>4ИGš!òj¨:Ë|ŸÂ"¨$˜%‹/ˆŽ>ÓVîm¡wÒ®qžgö’ä:Ÿë4“ÅúT˜¨
+Ç3¥?0[xU™Áv)Î4Aïä`ð<†FMȃ3Ý@ieò´©g@â–Ö¿Ñ<„$
+0;Èó8‘Ïųό¯eº¡=øLšÀ!¬ãr6šLOîr8=8?0)°?: åÌFïÉ1!8u“.åê«ù’ ÍôÒ~:ëC¾ ”›è”à^°7Ò׌‡ç˜áÀ­ˆøÒ1–¬™ Xʤý˜¯ãH´ñôŧ— ÏcP‘x²²äbj_#)UãuÙëÙ…rT&å8Ö„ZEPY¼R­€ÅäOJî9æ ¯Ê¨..HÅøfãì5àü”ée'ôm[¤ƒÛ[<–ó²:¤„‰ÙÞ\ñxÃ)¬¼›‰p^A«—¼"ª!qºrÛí‡d±ã"³÷ˆ³vjK”!m`ìQ>³+«cžSHe’`lVˆQëIóÑìÂä!¡R`}é'sÛŸZ×1­ BdÐg¾™`nœÛzÊàk­ W
+I…©+ßú¨¦æQ˜µåÄýBÀœyöŒ!¤;¨höËh­Ã'
+ê·}#rÀžíêÑÓV½y¹¸¶Ä8–KHKdQ%ãœ×0ÜÎa%¢æÈ'©¯þn¨ŽEÇßÅVÎÓPFh§†æ¥œÀ'UoÓzˆÍsC3o™4ÁÿONBqJžF´ËŽÖ$Š<„€-ˆ™Òh‘k» …”Šg¥tùô˜ÞQµŠ›ô¦#ÒŒxSÔz‘‚õÌNÔžuÖbøÙPwô±3Vµu÷ÁOÜX;±ØÎoAØÐÁ6–Æòlö7CèX"AÐÊöw£±ì}š*×z,å%du k†’ W{8GíIXLïî£JÈ YÛ
+ ^Ø×áïΉ|W“áÙ’ßZi™`Û“
+ùR§_212Ša‹Y·Î,ÖQÇýsŽÖuq¶¹ÖÀÓò쬘6Ù¢®ÀØðKˆŒÈÅŠlÝ3Í6ã ÑÞ9cUqÎEvyBœøéf$ìé;$uBúCÙïÖ@ V6$÷PÔñ“ª$3o²•`j“¸x†TQ‹°´nk7ËÂÌOÙKrÊä°8¶Åu Ú½­Ø<Gé¥
+­èÍ“
+ßdEÖd kY»ÂP·€?(žìc| ºTþó!¨k·€R½öõ.œÕ
+–ÔˆmöñâÓ8ɪ$Æ¢”Ò•­X<DèK™ Ø@WîÇ0DM/JaË
+…àA8›˜@“¶B­ºQŠ"‘˜ÓubÙ254 $ƒ{ûüëô±.ÜD³FTŸ}œ®|Ûë·—ð€2m*&ÕÎÇP,Ž´ñ ?‡*q=îæÒ)êxýÛ—7ôLý¯Û.'¤Va¶æÂ5üôeÈf©· 7$ TÜK§ñu6={¼¬Î¹¶êÔÙÞ4Ö¦ù§¾iäß—
+–³58½>‘á)ˆ—&[ËDø
+Mµ¥ÏŒ3åÁG’ü¼Ç3jÓÐ7O#õ¦ÌÔêÞ§—†vE¬. ¬CBÊ”Ur-¤a|2U:j[‘EŒQÒ8´.)ø”Kkîá¾Ð$v¬Êq¼Í©¿¼êÜóƒñJ™GÐ!C!4W·¬1ùCh^þ%Æ)ì;Á³….ŃãXUÌœ6ÓýÎk£p Iz/Ü FAŠÿ- ³ãúç…ýŸ!^\áFPQËL
+fÑãlÇYRˆÚ£:4§"ø!(;œÆÚ¼iA‘m¡V˜
+Œ?Ü%—#e¹ŠG}㨭†N2àùøÑÓ1x% =OÅŠe¤ñDæÛjœ"Řkž]_"Oð6]×¢`ÌÁÔФ̩͢‡0b¥5óØè;?â6‚‹c^`õ…¦¾EJAû•)gV²˜¾©ïqæ½q>_ܶ“fåCf_Ï’ÉQ–ÁŽ<÷”Jt%Ñ0{$ª°/¡ÂOÅå7N¬)%Ÿ>пÊJ¡Ç)zW7iû Ê#íuÌ/äTSœ¢, ¨
+(n?dHmq5߬
+ßoC„?“β—qÕ/&ñÝVU)1ýµ\ÒÞ/@˜(Vœ;›¸»¡åD?ö b ö€÷”rëê_vSçßÐÒ\GNH #ëQª©?Æ i€*¨Ù²:“Hx†‡LH»=·s1:Ô‚Ô‘EªôØH
+N ‹
+o¿ŠŒÄó¸£Q³Ó PI¡ oåT¶Èj¯~ÕÌ’@d|y0Ít«d™I)µmÎCR&î.ì…‘[˜Føa dJ”O‹ÎeƒùÛ3°J³ËäðZÒ?Ϙ„[™=ñäL¤šºšHâHe¥μ¢ÈJ…t[Ž/J]Si#¦*³4äv, KVvg §Ò$æ}ìº-BG‚h|nöé74Š°Ð§}ú3h˜,"¥øp+{r“Ä ;È¥õdÆžOóê
+†(ÏÐ@w3+ËÙ9‰U¨)5cƒ°‰÷AªÓÆÐHf#Zp„ jîv)Vqb2ãi”„fþ}dYœ¥~ËÞB:mò؈Sî~+ÀŠÆ¶@ðéÈ÷êLÀŽ›D¶pŽÙ,†ƒšì´jã|ÌHD\Íl2º#ºÏ®eúU@*
+_²½“EÐÇ
+5õ¡\©úI¼).Î?Í—áñš
+ƒ)Q £
+ ÆÚð[©šèµØ‡ªîHi;
+H¡/”zg;GÍÔ‹ð>172-”kj0¢|;‡²Á
+ˆÄaâ¬ikÌÍ6³8Go=º©©Á‰³ŠmÙT`)Ù%µ¯8GwàH*ÕG‹Ñ5LßbŒ#¡—6X
+0 †–`ŠÔÍ3è`g!±ÙvÊÈšF\Çêã‹uùÅÚýiÄxÛКxAáÉøÓÝ΂2$I²›
+ýˆ±•(œÏ>@eÝ´[<‹7jm–‹¦»#jšeƒ@<Kê-§î³Ì0Uy pŽéÄZ¶c;†5Ó PYSAdfÕ˜,ë oÁƒk¼VœR´Â´Ž1hqEFe,,I”Ñû’ùŠ5í$œ°\ ‚® ÒÆÃßëØ,9†n$üt ž4ÉÀÒyÛO@x
+yÃ:zq NÄÑŠ— Q_à®´âÞÁ=[ÂpAhÔ7L$öjA\ôR‡(;|PüÁ>4ŠîÕ„RaÍ‚Ù&ÃTÿ&¶•e•JœB!qßXÕE!gÜIÂŽLD˜½ß°!åÁ‚ïÏ1Å®aÔÜæôƲ0Ôž¢;—› ¸«"Eíz×ή[Se}álÆÒgBσ/ÆçcdnõøÏ{‰ßÂû`ºrŽµ‚”5-²IˆCÒ$±)©Æ‹39Œ•…ð{èG22|Ø¡~ø…b`­ÄZ(åA†Å*ˆ_%¶¥tjÞÏ)2Š èžHk|•2",/²hN¤xšƒ€Ÿ|k®DÇ5‚$ #y°vNá1¼v $K{ÙÞuD±-ÍÃV–AfUfŽ@¨fÒMêÅ·Z hI¹ê¦ª»^I²ˆ}OÐãŒi^*E¦ˆþ
+*ÞS¼çÉzLÉÚŒ D[gƒŽ„WLŽiÞ¤`%£fšXú¡foŠ3çôñ¯_²‰ä g‚œ³;ü§°ës “Ðâ9J
+x`BÑñ$zl·p칊z!*ÉÙ²0Û¯
+Þ¢»S†ÍrÈ$’±
+|GpQˆ‡¢cl3J{ywŠ,ú@P)¹Ybœé.ž7Ÿ’Öx"Ã"26y‘ÐSøžý*Îå÷Y‰~ÅU "iòj -SfÌ7Me`¥ù“ÒÙ ­š‹Ë)RÈ,ͬõ V:á2<Õø✒sR Ñd‘ËD—©l5„Mºô“¬ûg9mI5ìI´
+%výÅ—Aä±0Þ>%^Ë‚ Q.4ð¤B>Èò<h<0W€X%¨ÄúÙŒVP‰ÕâEÑ,ñ —[sÎá—85¾bµ3þ¥kVXáˆÙ•{O í9Ûy¼Ûâ/y©*Òô¾mIœsp…ЉœOT°2 0 þg­`®‚%a°…`ÒZ5ísU£`P'½:=×ÎìªzT¿
+³@#à¿q¼IDzN¦›òøUTBÃC1øqñ"j}hý¹éR“1¤öÝmâäd¾7°ÛÝKýG&ï† ÑÁß4¾ÔOKóÃCÀf³~Ðû 1ð­TÙ4LÇZ(3`Ç«ˆ§‹&;‚aXúöSå_‚nqw Â
+ó<|E%–ðuÌÓe_÷È"ýSN²HLÌÿ`}=ÿ7@ˆçb ¹û‹¶<€>^©·µ¥oØ ŠbGÇÜóòªÐ¥š_Äb5+Ì|ßà'Ì­}Âg³êûE˜¿z¬Óõº@ìbf*°õldU1¯  E]³¸‚ ‘Uq®Øø=è|Ÿ˜‚‘ê¬a˨”j‚ ˆÈ 9"]Ä6Iº·i…<œ2Él:Dã‡1&„Éï
+xaÊa›ÊÆà TÝÎÑ7Ê®Ê|:„ªl'þÐüZѧöŒP@Mâv¦…O(}]N«à5[ç<%Y‚ ¦!):»eJ‚ÀÀGã“W‹˜Ʊöæ P·Ä…ç(~Ó´€HÏg9êÀVãâ4†P™šÌmõ)~ á?¿Ý@ó­Mýö¬%'áç»
+øb²ËFÓoI£Ädáú·Œ Î!¸Z]õOç¬?&Zf|y­EF†ªç=X$Ö‹6ì’ÒBª±P³‚§m&…õk4ö—®ˆO v/¯[›¹ßÎÑL°©Ø>ÙÕ}y± Ð ÃŒŽ9éeŠš ’_ÅÏü~2´ý<Y­ZJNÛÏÑ︎Ñ?W ¢I³µÛÆ<¶<›ÉzÕ*³=ÛÙzGЬÔWa³5GØ<_©FíFU.ÊÑ©A2å/ôìê³k¤Xv: ÜŽážç£ô|ZâÅ¢8™'r÷þØﮘ°&HXCz=é–bq‡-Ç-}ÁÇWÐOôÿñŠj¹¸55ºü—ñrÉ‘cWbè
+¼¯  …þc¿4pGöþ§ï0$5\™J¸&îî2KRüHF&)Œ¿$ ¡N^<ûÏsòA¥BÁŒ,³ ç?8ªèîKa¿0í]Øþj‚¸…x¡Ô[ÛÔñºA— üþ KžËŒ×E-P‚ÀZæV¦5„¿úÌÌŸ²AóÐÀ` .ui J祩~†¹]öû“͇³VqJÈ&Ú‹¿‚ŽÂRA3(–f
+РãÓÿù&zÊ Z‰âÙœ¥DùÔ*#«ƒÎ~麎ž®£F"Öd Å‹ä÷n›œ`ߎ•†éúX DÄð"‰ÛÇ Ãu9µÜ$b#¼îè–‚Óuÿ©0% (2u¨xgLOø¢^":øó ©*¢â§Y X3Ã`líM y1œª³úÞÃqô*‘›çÐnÊmF &¤—B\²l24‚ȺUÈy Š‡Œæ`sò¾jÀü8QŒâX $3¶‚ÛÈ‘sX¼Š|œ<¯-‹ÑŠ†úé$‡D9^ *Ô‘[‡®*/7™¼¢æ D0¼8R^(HŠ(‚ËœìÝŒ\ÀKyä4!´tЇ%Ÿó&L%ÆÄ4Wñá˜ÆˆÖ!‰e¿˜o4\>69„Xˆ ÉvÃ}{ï—÷ oaKP½ÂX Òñ¡ä
+ôÓÛ4s Þ“.Ýç$£êptÊÂÅhs&ïßù Zã0"ã_?ΠJ•AèÕ»”Ë:žg”CYï©‹€“Äv—ù_<FEnû‚°á`ùáÕ6XÞŒ‚#«TnÀÈ9†+®,Ó
+¶ú‹¬Öž ¸f“æN °vu” A³ðÿZ
+¼Ó3û’»#æE÷©z?%¿h^¦Üýa?†”_­h•Âm–}H­¸z
+@ׄWü!ÐkÜQÓ|,ŽÊ/~Jq",²}$f£¼pK™´E‘ _¸­B*pqˆ¢‰¯ƒF”;Ñѵ•ö÷s ¿=PWO„‚a™d-˜!A¬µCéY‡$#Å,®›b"3Ì%fy%XKÑû\ôs˜K5:f?n °æØ U§z:­â ° kŒÚj^¥½ˆ,Ó’9§»JÀ
+J†‘â¢Lƒf-³ÉC j¸uè;‰ü
+»²+òxMã{ÅáŒÖJ‘ñ–Ôs©=û9 Š†3kfßòœR+ R-Ú˜cl+p£4l»aq¿H„X@:|•ý)ËÕs·#*_‰½‘vg`´ä¶¦! 
+UÐõë †ÎeL‰uQ• Gù~0ÇÌ›+0N¢Óùù®À‚`ŠüZiEÀ
+†e +7‡s PLÒñ5¼0S„<µ‡¨4l1ÃÉ`{9&È ²Ë<bg)—Rt‡ @ Z–Ë\§ˆ 4ÊÙº*E²ÌÊ…ñÙM€ÃǨÍs’¦§Ù%·¹qD¯Û˜Ù=YòÕÅe2ÆuSÆ/ L<a¬6f(é,z}òs¨¢lºWoaÇx°âîîAš[3¤‹¹¸‚ŽÙ^z ŒGÒÊ“‘¾‚<Í.Έ¶´æ3|¡`Hª¨ìwÈ+Oç
+EqîGî¶Y®$’Íå¨
+Øþí `©(šGÆöU7PèjÐEÁÓ²ÐåâûÂPAór7(TÛƒÎÍHÖ`Œì
+:^2¦ šJÿ焪Ð
+Ü æuHäpT*z
+R„†#H‡àž“R¼Lž ³Æ |s)¨–¦¶ùæ(7È(e8Ýæ9¦LŒT&$ÆqâW©ˆ”¹µÎ?½¯÷ÂEv,aÖMÄC+t—’™$êZ}Ø«Ísu¨§ÔÓ‚° @M8¾èH â&貶!,|DøSdqˆA¦YK
+ÐŽ²zÃË*„·íòÖ~óªwÐ4zM.­É?ïqÓ‰4‘ Tºw Ê—ÕÚ4"(Ôºé=7N‘×r•:ÐϤ«hž-n+å Îôq^%mgpèÙy:ùeÜ®àrmcŠœe 8ÒS“£ƒç´Qöq^4ÔÆAÞþ-jìàËEžNÄ&†ï-Bþ²L¥OH›BÛuìUî–@Í&å³ÜxÉ¢K~ÍáÅò<ç}½VZ^ºt?Ÿ˜âdÿoŒã]A6d¤PÄ™ÀwÞrûO6ëa‘Ò?øïTœ*»¿ªÖ
+6G8¨ïi$ÄÀX#¢š¬
+u²2L”Èòô~›0ž1yt…­Ÿa0-ð%Ç×q¼ìC™Ä;þŸñ2ÉŽ¬ˆ¡è
+؃WÀ‰¾CvÁÔìÊ}
+ÉÎøE ]úÑI¯ËÍ,E·¢ª‰!$Å”˜Ö×ÅyÄ|ÅšM.y(ªl—5v<¸Ó–©¬1IPiûB£Nà±Ü`½>Àç/´MÁ®fF4CÖ4 >«ïêö·ÕF¤f)]URD%–‰ØÆ^ˆT—ß#ˆPÈÈL6Ñj…HÊË)êÔcÔ(š³Ë‡´U§ñ[ŸÁë ¿JXO®VáÅå˜K­ª+±Ír 52<|:JÕ¯‘dÆ}'K9ܨ÷Ðl%’2Yüì$yO]vØpC@Kp0*ÁÒË®°à87o‚5!·øNÌ7¤Ð¬”áv™ÏN÷¶-“ bôë¸ä'bÚëû¿N[“õÁ*×Û|¯Vè
+kD5BÛŸVó&ÚF9XÙÌ͹Q[²úºqB…›ŒF'ãå˜)
+&(Õ‘t¬„•6Ô
+/
+|è
+Å•eB›þò>ÅG¢x<vc|Ú)²bð°eÆOŸÚ²¡A™Ê3„ä5ʦŠ•ˆŽï¨:[%š#ñz—’!¾» æ*ch˜¨:ØÄüì),PÝ-U °BÓY€+Á#UOÌãòt‹ÿt»•ˆÍuvï&ï$Ÿ
+Â!Þ³ s\Û€ûhq,À#eß*wøGŽög/RNÁÚ
+i½Šx·­ƒÉ&5¦0çÄüòÒté-Ÿ ]Lb‘wýF
+ ƒÑSs„¯Å¨Ó qø’cäp·k¸–PB~Zˆ *¹|šÉ,ð^¡«Á˜n«®<÷°uT±í£áÑ”³3 ¼Z–¤„O:˜ÒtjŒe,‘ßJž‡eäƒà=”3m] '+Gæj³+\¾
+Kùg‚{M}í,Yb‹Ÿ­¸Œ Œšï0Ü›,0ôÐÛ±o”p¡$ŠÒ7Š£g+vÐnÅaIŠ¶œ™ÜÆ:Ðë2†[Ùç+>½ÚvÐI|Á8´ÁÛ_J\…1$‚1,ëlä/Á‘{œfMÅ'šœëA0Vš!R"„± ¤‰WO1‰<Ëœ;Y†=rðY‰8¸vÄ4Þ˜$åñYÙåÂoJ䣜é&{§Ó%H Œ
+8ú´"ì\Ï`_"AAItJNí@´,A¢þëG†l¢<N yLy—¼ÛCŽí2c0j_\È3šÈý›ßœ9¥àŠ÷‚•Yºµœ¼ª”À´Åí@F+’èiÇNÀ‰ß˜äK !òñêõl5æMóÎß:ؘïc'Ùš/ïñé{ƺ5ý[ÆbºP=l =¸©Ÿ{2¹7áæ¼iûˆ—$"ë‘w8%îc:¹óÄš’"°}¨„¸QäHÛáüè0
+Ž„%¹ÂǼ£ðòL/ò:¨‘Ä*¡å ‚-w +ʱÐE
+¾¢’™àœëav¤D8¥¹YTn’È6»’£ó€‹Nû
+kžU
+)vm­B¯ðãÈÏ‹Õ>Òaå™Õ%èE
+Îßå&ä;¢Ü%õôe¸Ó~r0¶‚¦B®PôÇb0x .ÿ=×t@+"%¶Ï‘‚£ˆÉX0Ú !UB„]O:#™cy)2!Mï3¤â°H
+h†lN´¯”DF]6fû ­)i´"·R©Ÿ”äöû?®EM«c˜ÛI ™ÙÕHû\AóJGwÛ4äaòx„© x '7Ù+Óý J…"l®Þ*²§µÂ9F·ʘH2‚6í;4“¼ætðçÁd$¤(Ô‘ç…ô)‰t zS¦÷»($‹K8åtÑÚõz:•s`ï¼7gÑü¼dYÕ°Xi¨ (èÃÀU*èKëäU(|ÍÄÁJõf4©w'm1ß2ƒJ‚oþªÄ¾ÀúÅÁÁð$-0š&pÙª4ƒü¤&Br§¥O߯üdR  ëòÔ¦8š›'ˆ¾ŽÓ‰³ w†:H7ß™T’Á <3nÎ&Hq=*¤³;›êÝy{¿0H—Aïü„D$ð„Í™Ÿ‚Í)B¸A¿Ú&@Z½˜B€p›ÝBª¦âãBÏ"L”ºÐÂ}Ÿ„÷8q71øIUmÄÄC“ɾƒÔ%I"×Ù:‹ d´;k¬XŽŸp¯i<éÝëô/ïGq6Wá³u»¯ Ÿ’¿’3ê©nÒ£yG˜rè9úŠ ¸]Æ ïaàHD³È¹D[Ó]¯„"ûéÝÃ+™B¬¥ØU¼”ѹQ÷QU>þ[-+¯A­=…¾1‡/VÑTôÞš ;ˆ÷ Ói<.$¢^m3ä7É4é±î„Ö¥I«mº8Ê Ö½ƒDXlqÄdIµœ0Ò£BÖQˆ^×ìöºÉ÷ò <äºqwž‹IRÐ5uÌwPż/ˆ­ ¾[‰UÅ,W—¢£:fQ4o>á8½`7ˆ4®rŸB¼ÈÅôÝû$•Š Z›KΕ > ̧»*ƒ%Ê|0{‡ ¿„¬÷ƒÇ(.ÍÝöº»|ghõ ›™è;ˆ¶bi1Ôá$º°é~< /z«C*(&èëÛc´h¹ÊãÚÅkQñ|7å]-d„ÚµçÛœ{M +>®i`d ]1äR·œâÏi£ð>Të¤$gÁ]lƒhv1õ.~ß$o#V(KoH˜ñ¥GG÷“f7c‘TBÏ›ºéí€Ôü‰“d,Jeª}Çt6°‰fÛ(P“`¡ÉlYHKÈf£à!¨;•aQ†e@$‘ð¬è…ónÈ€=+¿×•Ñ Ž™2Ý2tic&ÑóèíX¥×pºa¯^¯"%âÌ$ †o˜š¥$²Î…í~CcÿÎtA~Té§<·ÊÖŠï^ñÏ -¶½}‰ù:ÇÐLYoÎç£Åè µÿÑ~ˆù6¨“ZžZÝÁd²ÿÔˆh¿ó×´ m§ ¸@™æÇA‡ãP‘A“Oîñîâ§ Ë œŽûÏ ëüÜÄ à—YUï<Î!¸\Àœüñ7!ª?mÇ(2Þ¿ü(ú^+>ÜuÖ:Cœ×w„³GÚÑGµÒDú²œÇ2n3òoJ–\},e–mb8ý¨B¿:ºÊm® 6Y4€ø+„È_ØJhÅÕ0êWµèK+µF˜§ê/i¬kõ£˜l¾’xqÀ 1£vi},WÆ@Ã
+l>œĠ_?Ö2ãn“Z? m~ÞdØ>£KÀ±„1?OàXÙâc[ž—û®“X¹±¡=ÏË kZ6”õ±š”5ÊŸwF`
+L"œYЙˆ_û|<PAm¤Oý8½˜´ßt¢îZ¢Åå‡ËÑYZvm¥ øa:dÀ¶×ËÜh­Z^x„’ŒS,¤L Ó%æiC|£Í(Œó F³ÁŒi–ê¯Wh.¨(mgÚt;àPØñX8Þ’Aœ;§ÎjÉRëáúÚÌx—²cTÿ*¾Në ^
+ê¤pmûÎ]¶¦añä”U©tYýIKÁùÁÚ¥YY­JëáP§/‘úh;g"?Ó×ÐAð¬*7öÒú±ºÔûW˜k:•.é#Þ¤Ä5¨ZbâÞFH‹E¶È¢_Ñ&PeLoO$žÖÂ[…ªÇëâ°ŠÎÊÝ3’ªM9jk!æKs£#›¥‚€èpˆ’ˆ_‡ý°ö0S
+×ó°Å—!HfdpAt$:à Ÿ™“ÄB™ A®A 3×7Ϫ}¢åZ˜+ž‡šÎÚÇAoÇýþäNëêïߺl£EOj)iˆ,Û!èë&èû)&¡Ì¸<Þ/å½k>‰¹öžÝGAGœÉ,¡Št0U˜‚ÿtA¬kYÞ‚~òÞ*K|üM¨fƒ‰ì…Š}™Áa£‚ßiÞU§ †(…ò
+H‰t—Krd¹CWà=xÏ¡%RãêtDª÷?퉪xvÞœTÙi¤>$@>ÚZŸm•¯Õú´µZ£}þO¿,ªµ(sz؆„é^ºÇ8ˆn­U>iËãóïéƒ%Vï,u@uÙ(ËlõÙö2Κì4Ø1×)>We™hµHíám¶f{‘øZÁ
+Åú½åNsŒÑ‡o–˜RV¸[ Î'Ĉ±*‹_ «Þ[Õç )úÆ*}”šÚÆì>zo#w²æ:Íüw@î#¼Î±ê^‡ï{¯TÆÖLÈ0J9–·~îÔøGœµ{€œ­8^D·¢¥Þ¬S¢ÎT¹ÿÙÊ×ìf½t•/Ö×ZVW§z³%$šOkî[ T{[µ°XÍ"ÇŒ2Bõó¶× ›£v>-äÔ¸;XCmÂ#ªOˆ²jd/{Ÿ£YïQkîä0K§[Ù8Ñjå.œpu&ÄëµØ5!M ¨|oZB¨‚•è´3·êÁßÖ¤4#r+.Ü©ˆu@ƒvšÊéÎ:•‹Sä»Ê\‘¶±Öxд29üd¥»ÍÿAzQo9ÚÁ%ü¬áªdW¹ÖpxÎ^›sí‡Ò BïÛ0ƒqï³Ê`F³ÌÁÜÚk¥6ëLe™Ì
+•¡!$«6dcësŽu·¢P
+A ¿ t¤h kŠÄ·é"&Ä‚¡¾¢½jÄ._@øiÁ©¯}—èv1hÇvñù*X»S>Q¬Âyæ«ì Ò'ž\#7ú®ž›Tj¨šÕ¾šziÓ¼úA VcÄ,p=@D=Ú C0ýó×Ç?å󯽌¶¯Vw}:4( ð)Rþ»A…~™ôpôx
+÷¤ÞÈ@OPU™åó¨ý­^+B6ó0³.ïÒþ… ›œbÅ„Nã@ø¥£€ÚZ ˆÊ[EÎX/¨‡iŠ ²½NPÞîF[n&ìàRë@ÐÒa
++}+®bý:
+YMQlºìÔxLæéó÷ÑkŽ\ø7¯Nè0ÒZ³WÃ<V¿ÇY¦a,åô{5ìƒnb`y†™Áb”$·Ìx#bI= *€ ÐB<oSu·ÁPbhŸoò(G*ÓïXMBón§¾ARt`Eg–HO ­(´×° Ô6kÃ'‹Òe‚ãâü ÇA%×Ãy3.à}ò3Œ)O '†™Í¡l(̺Åážôº-pEÅÄ$#Ú$ lE$΄­ÁÛZ–'h³{aðΠëE“ßî:P]Ðkù“èÔ=u›_Ñ©¨æ§ÚPLî„÷ôºŽº1ít
+1`áç¿o@˜NïøÌhjW4ŸE«ü™Q¨íg 5CÁd2n˜]´Ì'
+–¤Kdd›'ôŽrP{ËzZH"ªõìÊzdè7D‹£8
+FRäùöò¥"4‚Gõ
+Â96›åšbÔx"ªg¤’™ÿc¼ÌqäLr(|Ý¡ì6
+±/æ@n»s¡Çj™sÿùÉFùG¢K€
+Ii§
+nÓ/þ:U
+iL‹˜\”òã+£÷'šBrðí<Œ][PK“KºVùžŸoŠ`:G—‰P‰baå‡øˆ Ù™1ûPST2TaQN°ìLºln‡UÄÄò‚<@ZîWx, äÒ»­ƒe€B¼âüƒÜ³Ë†Ñ¡Þb%MreâZb`˜R³Òb+òY¢¯fJ¼ñ€†5ýÝo•åzp©ÉŒ¬JšR+˜5OgC¿1P¢« öUÁ‹n%] É„{[¸04td
+ðgÎñüb"ÆÕ=¢¤)rL¿hŽ—ð(H'šßh^ À4'Í oÿȋijøÏdyÔÄ PÃ$É^fÔˆŠz)Á˜Sqp®^Î2²ô¼TÄmMæMÚ¼8Y5¼b~é9v—ö§<ëH8!,, $zØ\\àåJöEQtµv½À!ƒ#§¶•|1‡+!}=à“%ÙKŒ”mH_¾•6ƒÓ É+A´Ú­D"ÉùЮ’Œ—,æ5°Û±ünŒŸ»7™Í™ŠLÁÇ·Âl¿÷ð
+ÄÝ›È`^ÄÂJøžÎCt®£ä VÀšññšYÝÅYÇ ÂÀ>vx½@Ž©{oV…PŤät³{ÏÁ{±ß¯¿Q@ DÔB z<'–7M—"+á
+yâ_ë`U
+Çü>V”±8¨^*ÙÓK’J
+¾ÍK„Ä a¦Qs?•œfä @w@´±$¸
+Îñ”] s€{æa‰R!{Œ">
+Îïl20¹p$Û “‚gæýRÑËv·Ì{96™—†~HöæõòE¦vË:‚˜ú¦‰ø3€ñÅÝäh"³Ê Šº<ófvål§5¢¶éŠ¸+˜Ûdf¯ƒ å£,¸µ[5±ßF…O–]R.mÅ-pOS§•k‰eô®a*hpPéà'¢Äì8`ÅôñÜס‘[‚F:ù’Þq–…ðÕðãG¦žŸ­q‰}n'µ»òZUºõLÇš¬„Õ¯=ž“ «Ã ½)¢ë4e"vßöVˆ¼5Ý*q-Þ£IŒúÊwk%Pú–mÀJ_Ý­HM Á8Åq4Ä«‚7ë—"+ôkqÛü®¤¡gÍȺ”¸±Áa)‘ÙVÞ­Ô2H‚øj” 2Vn˜b/  `¦øìÄW WÍ«¶Ø‰Kó܈+CEÜ`o@Ù|•i1'¸JhH&â
+
+×K·çKElW§ÌœH XoE¯‡6à~f±á]
+c|eôëYáÁð•°J¦8§y]_'i/x¬GÁâU5ºRW¯dsÅ5QÂŽH:Ê }ùáÄû+æáêÑS)Å(5ÖüçÔqºÇÒr¬mf«
+ØÛ@N*5?+|#® µ’•â®«€~´ fçÖ£H‹x{%¹Y,ŒX}Óf Ÿˆ/N»½ið³ä·‡ò­žEü‹Áâî~«çià¥$€{¬on…RAÄ$?
+ßêÙ<9|"œ|Ü[œµ;'ÉèÍKýVâ[=ü±Î6Ó<áw¹ÕÆÍÄcõï6 M’åúÂH}·Éc+d׸(­Û¨ÿt쥇.6ioøàYôõÛvÒøÇ39i$EE°ÉÛ#2*ƒm*b‡t"DÛŽ~+ª»Ê±‘pFEª)ãæAÕ+ÊÌSWD¯xÂÏ…3>ìÕK˜>ÆÂ&1éÑ(šK‚©³Ø "žƒ+ œÜÖáÑGÉ %pADu8¥<|«‚þu@Ò-Y¨5ÉÓp7mÀÚBS*§E0|^„î7ý²´*ê1)^¢,KÜåʸS•tæºÊWt—ÀöipQ6"ÞÄV˜øLá)΃ÅÂû…訒‚ãwVʲBOëS•E*AIáômÅ*…[Ž]b+~¯ EãR*Û!ÿ‰«ø:9c<äÜK(ñEÉìì|¯…„—_"£Ø赆'ë
+Ÿ3šG0è\±Îcªƒjñ“àYà&>3ì_2XtJ!Ì7’f7.•ö‰AJõœý¹¹šŒ̳o®Q%$MÌ̉g½K²eY BnWc Îå:&A¨9rÐ@
+‰5ŠøûÂ}lı €‹1ì.|9ä]Å®ïù{…oD¢ð©ñÂ}•D,bê
+Jûð_µ½}.ÍRZÏW4¦p½R$G@T߃–8,rØNÃÖ1lÛ‘ÏVfO;~×Þ”ð¯Ì59õ:c÷,š@ "kìç”´@JNsVœF!$3i^±ônn\.a$øQ—Wîn@¤†ÔBœœ #Î&"õ=%^YìOù?ÆË;²c¢[éðä<Øú&w!—½W7
+
+r.áoœ†˜Ô+j†´ÒäÚ¾‹"fù3~‚ߤ$×æßEu(À@HP×’éÒ<É:Š‘纔"¦ÄZó±ÚuÓ¢\–W‹#_œ5oNç%]”oc+4¶á;)q¨ ™¤Îé˜%i߶¤2–’ð˜…Ú0%³È1#­½•%0†7ÄYü¨#£Ž´
+XVrÈçé]ò–âýRNÐÖd9fM‚ÌÝšÑMØŠÐÕ_tóK‰OÖx.(¥ó‹u&s±ÁZÉ8‰ÿMKã)‡,Ê• ™Lu¼¾ªÁéíu˜[€ÏaÊÇçÕy߉⧿îsèt
+pBÀœª¼xþõ?öã˜jiÖM~[ÍjÖÎÁK»©S .–²Õ>êÊ”ãLªÒT·xkNËõ¸ ¢‚Ô`«ÛNXzå±µÕæÐÖÂÝ ”’}+ÂýÚÐ:ž¬‚ý"`N/ad˜
+Ü‘Ë/DŠ¥ vŽÂ™ ËÌ㖣܈WÏ—¢÷EDFƒfàX?¼Þ™PZÚ9™?‘r#±§$¡w¢Å½Ž¢1ýMOZš—0W Œp’ÚÅ$þm;Õ±y¥åbe8š-“1ÂX••®­úï† É ¡q‹‘{k7¢sltFPy”æ+Ñ©c´l˜² /sqÃ\EÊ„dwã´¾ÆVb=Y¦Ïµ¯Ù+V&Š)º‚*šœ.
+°ý,à’y¢7åVÁÎSšÂ£¡¾†ŒK œˆ"0áË<à³äAÒ!câ§*”cÀ$ļ»_éïf Ûqý G<e| ¾C=Q0úÂPnŸ½©+B–«¬«¥öübéiŠ€Ñ*
+?·u†üSÕÅÚòœÂixú©;´¬
+UW OšáØ `óa§[íH¢‹<àc ëƒGG¸(®ï¼heVÙ–r ò•µà100ªÌ'7ŸçVЈå3þµvN>q/­Ç½0] ¢©Ùé–ñeå$ßv·ydѵ8ó¸ž$¯T÷‰¿¯ErÝEÀ-g=%P•œþîSþ«žKÙJ "®!RëA¦ÄÑ¥‡åP²ŒŽÁUÌÔQ?ºF ãи†­³ÈX‡íç¾\3Jà4e+oEŠh¾”h«‚ÁçF¢µóÔe `Bê¦Ý}_ÑÓ@À+ÁZå(„Xg„ŠxçŸ58Œ™˜/ *SûaE‹‡œI;ûJOœ€ÃiŒ‡¸ô‚,t¿ö×
+`È@¶]´ßn«Ð‚Á¤š•\Bò—B«D~_;‰ÐHKÕ´ ‘ûFßQù×M„”®ÜxÁA›.rçDåZÒÌþ3öì=?·úo¿ ‚_Ç©cDš±F–O•)–áýY„ \"AÀ¿T²FÅ3‚Vâ‘À#ô–ᯄì¢o€l…¶a›¶n/{'0Ìåæ·ùˆ”«UmÜyk®B+Nq^%²h#ióÂL•R«²(
+¦K·"•(ðbÀ:ŽðÓdƸj†ÁJ6x 9û@Y—~ò_݆w>’LðþØ•êë€wñp1À¼[ƒÏŸ×ùs¸o‰ÁPøq«B!%æ3‹ììÌ]-aÖãá%DP´Ü4«_Kƒ3•€V‹’‰ëkÀ‰4ãêÖd…§èÔ'yBHÑ´p<CŒNÉzÃ%Ãà¹6/!‹àŠdüßJbHÙª ?ÛþX‡)¤(
+Xô|¸Þ dˆü%
+Q J;’дÎÛ %¹,S×3;e‘ú:·¬%{Ñ’±v‘z[‡@Û$Ûˆx®`ÔŸX
+€eS‰†Ö.ùšÿ¤u zžA‰% ûEx„· «Ì¬]Þ{n™Êh
+ÃáF¡k ­YCëjló(!_a¿³ø0¶¡•r¥ŒW¤T˜²y±!c¯³â@†¤íh
+¸@ž±„c÷a¦ÀF
+“­Ø*ÕF€êPL¾"ïþë„ú9„
+%;ËÂdD D©‡o
+·‰È4(Ûç`Äz:gt={YàÍSKOÞ_§ VlÏî9°5î€QáÛã "p{Áü¢$»„Mƒ !Øv—€8$†AÐÇõ)q<áxôc´ÿÌ<*à ú”ÁÆ1Èø8ñ‡eW@öšÅÒØ €%dè&„úñÃ+’ânL6ÖâÜ‹F¨[N@Ô¶?Ö¡ §IìàÒ%'4~UH °Âø—l$ª¤ŸŒêó:÷¢/ºúúŽøîlØ$¹…z’í Ìˆ(G ý½Šˆ]ÈNôV,çH§I\ îÔ#2ÎvqýôC#M¢EÇÖ>3êå…V:duΧ.É‘’!ß>õ¨öïEN
+Ê.e4Ì”eE×Ï]Š^ßéÂrêì8(!ur‰cÍ›\ XéËi¼ËfÉ>Îpœò—"•$™_û½W&£ ¨c‰â°DB­æˆmŠ¸ž¼ ó/':¢ôvÐ8×9MŽR·®'€¢G6?ƒév †ôÑ-µ€ Öå5 -Í÷ÄʤØ?sì—¢×.B7WRR3‹¬“s9å¸)A¤ æ)†ùðr|3¸Âë7ŒÃ›¤+Àíµœ—“=(o«‡Z‚NEd+V“{W!ÌÖ¼ˆàÎó5("ι<ÃŽ]à~0©‰
+ì$÷BsÔäöY%mALÓ>ű¬ðDÕÖ§xCÔËá‘T­Ë£NÅ„áOë‰?܃õqâ®S€í
+
+ÈÂÆ‹¨µF®ºM¼$%¦"Òé.)ݵqõÉgÂlj-0ÿ%Œë˜ˆùÃ݃Þä(g˜·
+á–1Èj–“j•}-$·Ü$| ñÈN8Ú_ÂóÜöл¨ªo ‰5Ø *)‡‹y¦CqñrÎp9¢¬ÞAƃP0Ö(½"Œµ¢?3š½UÍg­’6iÝ8T¦K^ÂëL(²êžûå¥`{
+ô¾€¡YæUQò(hÅ ¥7§D_RìäüÁqÑ=‡ýA]ìêñ2p‰¶¯¶Ò·ªI0b˪*«äMÿ÷"ö!ò¦‰Ë% ÛPëqŒ=Á {®\™yjƒËà˜Sçå7‹{ïßõû x
+ Ã΃;ÛÊhÇZø{b̦W‚?Ø-ÀÒ® €Mo€q࿧²*ä‡pEèx\»y$ú%ýâ?-þ3ˆR¢5bc†J\ Mâ#´½ÌÕ“ë=wȇ…J!Ä‘Ιå£ý -»Îà¾Ë‡á/ü=(P„
+ÐÓQh™ü¢{.¡(Iæ3ÐHù!¼èNLçqRµ"Ze bÆr@ˆÅÆA°ËÅŠ
+¡¿Ç¥ò\=⩬J%»öô>Çæ2ÖŠÉnøôCc—cØ ¹xØ
+†ÈíÍ[øºP%ÑØ8Ü’‹Tþúºv® ,¹–ñ´†Ù,`€/L’Õ©éAÁEÜÖוؙ‚RÇ3³*‚ ÏZ¢*Ìs–Ø.%Ü:N’˜€µûÖñÏc¨
+Ø ™ê·‹Ò»V^í´UÄçh³‡vÛsÍåJšz­""
+ƒ{—dŸúÿ5üyl’€GÔ!öä8*„¬ˆˆÚXMI-è  ÃèéÄ3˜…oÄivaÊ3ãˆeNWÉÀ.ó’%-V‚ÖöI%ƨŒ
+øn·tœ É¡&–¡l%,k˜´h[dìy
+œÎ;бÂƾmöãºúH9v–Ñî*vé%²éS ³}æ^ƒ£$×D ¢}‰Y†Ú3&¤ÞÀÖµ\Þ¶¿©øÚ±˜¿~lcÊl¥8Ÿþ›¥Ni/–TÁ‘Ê»÷—þ8&ICŸ2
+†ËR¿w Öª¡¥CÁĤR\SP•÷~±ÔMY® #2ˆ‚,Ë¥{<% n°ï†™È+&**þµ÷cë&7àÉÅL
+¢ŠÅ@^Ymðš#˜>˜@ú‡ìÛè†`dŸ4Ò”nêÞT–ÔŠjŸ¢J,X¬=¨.Îá3£lûôµâ–þ,ùé• ÇÐ@–tI)95xØR:¨Îul%«
+Õ½4ŠS,’Sôz(Âö‚3åsµç€KDFÌ1&°„²&‰÷Æ.ÎÜ`’Ø­;˜¼,×]LJP+©¯Ç4E±hUälëNÕ›{6ËÔá5´«ÊÛlîÇ·Ëo@
+Ÿ@w˜XÁ÷%tÉ¡RŸ@ålRßßßÁ±»É.•dôOxx‹itQ€Ãwòм`z<½¼cEÙfí˜î˜RÖCï’õôa^ u§5M/B(É(%+D96bj½šŠÛ<s"v YQWn·"• ê„ΪYlö.W¡æ4+ÿS„–Ê~±Eô
+q¡lðÛíÆ¢ö<¹
+
+øŒ†^À½†`pÕ¥f)úIôžjú¥¼(i<?ò¬ÛÞ¹³Åçô\8/Ùm¦µd•Ý1„P<ê"P’3J Ù‹yqz28·eÛ`ùkX,½RÂŽð;Mrs–‰ÏÐöúÒ1%ü‰#8óAËtÄ”ì‹
+–ÛèñM
+‘õ©î®7¼g†9§B‡!¤o¹^ ¥§¦>'*ÍI
+E—™÷¸'3AbªFJ\òõ;ÃòOVjÙ9a‹0>‹ñ‘°TÉa±»/ÑXyCá¥óS[†„7/9É•Á±.c jA1ÑÌìn«'ÐÆå@lzQ’iUbƒà€(rÔ•!š>2fa­øSч È3ÿ³vŒ†M(qúþÉ0Aýý>°¬Î622³haúN›“eUjÜ=&Š0
+˜yð‡Gþ ¢Â×®‚ƒ¥G4+Ï›÷»Žó¡dŠäÇ8j¼úôŸ`2;ÌKØST–Fäµw"“*ñó¸„YM²¸r<‹¶Ìré )ww´°#Œ£¬»öît˜4åB//JœªÚÐa¥H‚Oà%•Eö¡“q{ø
+Úk¹¹Ãˆ³[}ÙÏ^{ n•í,ú*—á^ÒÌ\TÙéJh¿´6w!Ãh(Ê.ÂÂM=‘Ñì;üÉ6yA0¾OÌu6‰(VÁ”ù†Øö¬ÐA +ÐÅ8ÈWºÔ¨‚ŠAFtÄûU(1ãœÅ\éÅ“X{*@|¾¶†âS熮 ¾•< Ê:Š p^ ”Y׫ÎÛàqIàÏŒÔõUP$Œ~€I?êìŽ<
+nŽþíÞâˆç²‚Ùð6©‡’…‰sàÇwNØ<Ýæ¿ãU7gT¹€ß¶Î](H‰â€òçVêsóØP¬™/9wáp‡‘ÝÝ6i¡¿²Ó¥èçµ(½ãÐ
+z´`@ã)€§±¥íÅš5¬v Šœ ² ³ã^E gl­¬±t|^Š¬Ù0<žDtY7ÇÂ>/Jmøü£2𹻶œ%a3á
+éo¨Ôý*Ë VZ:•Ð½Ž­Å\õz» ¡ã-A»”üúz„³ïµ?þþöýŸoEQDÉ âû^møPZ!qàV4p[P"VÝ£{"Ü¢*<jÉîÜ/E +×®.K¢U„ØU­(3Pú°¢@£ ªÝË*²½…}o!¾ËsÀ«°Lm1À°œˆ
+ŸÌw¾,âKpoÂÖÅCDиÔ[DŒ¥,tÛüÑè:ú8ÅÔö~Ö’L`»¸>`[pRä]`k%EçQTt)ùeG±Üìè‡m_|‡…‚²ÁÂíÏJS†%“ž8ôrЂ`n«­¨ƒ “ì¨ß"h;Ì" €_³Öò“4‘j4’7ØÎ"D*°ÃÔ^]*òç!È“º®+Ô‰Ôµn%´=Ó¦1ö‡]]ª€Ð ëg*éA"×µ“Ó/ƒ8uÚÒ*PŒ µà öšuø@áæló¯E’t;'ûÝŠPJè.D¼“åÀ6kW«qv²n|Ç
+”Ÿœ¹ì Ã_óÁ¨EÛ¯†ñ€L?f7U§Ê¤ÖbÝÃãÞО´gJPû—ñ2IŽ#Æ¡è | ‚çµz©[h+ßÛïspwe¢Bå…#,CLøøßAmbãÞàKÉ÷œ%¿Ÿ9žŽ¯Î¿çÄGX‘Ò¹ ÿÍ+ðü5–¯’½¨´¡£l=:½ñÀwé¯Wò4§ïw@|Œ.á­T{ÛáërÞ_·ˆ‹SYñ(ç‡*äê ü´ckòKy–T„‡¼
+¡ÃS¿&gŠøñþÔ/Û¹’AºØbÅL‹;úb®‡šfs‰ïEŽG°—zk:Þ.ºPæ—û¹·ŠÊ̈ÒQlPŸ€õŠ0IÖÀ=Dœ6ýoV !©žŒˆŽ8²0ˆ¢
+¬‚TVX½žÏ?^‰¾ ö"â¼
+¼½]ä,Äýso]–ÔÇú¥H Ÿ†¶ 0S ѳŽgÚ1Ý1 N‘J”Š W‹ ›Y`“f‰ì †û”Øx…H»í~àËóo!:E?/Š ÛŠÿ j²aÞ¦Çò”½8ŸÐʱϼn+à%¶±jꙬ¬ä{¾¥ü2„Íô¿Ôy°ž…©â_´á q6y¤š€}Ñ“&}ª?”#·¹øçÑDiÝ·iÌ:`dø5JÚcDÀÂ\ê\t‡.ð
+‰9®ᘱ%ÇÊrH‰yúEY±T®­fž^QB©ñIÖü˜>.#ÃhŽ¹Æ®g…¯§ãl»ö½ØöaƒmO2xÈìîrDY€‹Ù¦Ù‘a¸‚åÕåÒˆ&
+£{~ÎèÍz+ᜣl‰[":Ú.G•©·„¦,˜š ×®Ç]ŽÀú$Ú2ÉPp'©Â\!´ÍRø0òÿdi?¼!¹â¹bÔ»‡_Bh(lvˆ¥±9Ðû_Š~Ü¢$¥gÝ8š—ͧóQ4HݨÛË"©¨¦RÛ%
+¢/Ô¯Ûüÿô<Zs®b™ô/u<<£3¶ñuvß=§?Z‘b"ý¥u÷6sfŒ¦
+¶õÅ«(
+Èf#.ÆÝ ÔV@¿`Šéò»ÄÃU2’b‘ÎΫ"ÞSÓÛ¶‰Ç"@ƒCÁcÌyzESùÁqÿ¸Eå$áħÈÏ×ÇjÇ€å´Ù²UMiq
+%
+°ACùôþÝ€#sý(¡šuÀݤM’ >†òNgðÛÄ…0±Q¦ºø|ÇûwÁÕÒÄÊßÝ5?2 œ[`õcWž @§“'»Þ ˆ<¾@½h²kxmVK!‰vö=5åúÏo»%P‹øý­šøÇ+ÊÊVà²Ñð ç{ÑMOær
+¿Ž/rs¡÷Ók@\ /¢A7غ_^É}¸
+¶z!E¿"L|ÂX“ÇÑ>t3øºžD
+5”Wþ€M\4ÐCvax\¨
+›$·žã¦æŒÝ)¼°öŠµkLø¼X·’ˆï€}ØÓæ\NÔ
+µZvMŸW-µ-JtÏbæ½®ðH’QÙÿé©dO»¨; “ítÏ©QÕ 4;ŸŠ‰«€ØØg «*M•êl½Ñ‘Z’^Å;ø
+‹¼U:"çJ²,õµ¤
+§Ï.8Ͻ‰XœÈâ£Ýõ„Ã7ŠLÒFo‚¨²Î"~Ôå•`™¼ÖÔ-ÒIÌ”B»åê÷…ð>µE—(ù%þмåo '2"? öŠ(Ñp”Ù†RIó“a$1nt·ðKt[™Þ ­‡“K=´]ä9‚º•mêô| d}È"£Oyj?‡8- jdnû–
+€NNgy@ZcêŠ,;
+rŒwħGiuZ%Ch:wŸÂpQ1”2Ö‰’Þd˜±˜þÚn££B p¡î”èì~øØ£gÏB °ã06µùÞ‡""Ñ(X‹Ý^œ`$.*¦ý*Ü(W–ÉoPÒå‚hDÇf厙BÉWÓû8E—XûóÇûC$ì2z#­]¯ŒTa½p-è÷é—’õtSÚÈ«œs‚üüÁuvrÉU)
+ÏKNZ%Q(ÁÒ¼CkååÑpŒg~ªÊYÌL”øöð•ùeŃ”?| ¨|Q¬s^I ¥$ãßï`ùëDÛ®àX°
+©%¶ãç~6GÏu'ìïE\oYå£J(” ±é‡'>e˜®Û³¬ÁµøQˆ"ì>‚¥N¹y‘Š’#TÇì3æI,hÏXq߶¸U¼1þ¦{Eeèi‡Îm¸KÕñ
+R’#2‰2oÞ¯Ú%QLŒî Ì>R«ÂNc’yóÔ€pIZ¢j`†Uó¯qǸ¬xÓ$.%~ø{ÓuwµhîO}±\ÿÈÞ¨Ñ
+¥‡¸5”Ó…ÓÇ~UÊXû„áâ ò•ÁI;UßI@Eæaq*}~»è&*¿Ý"œQýdÙ¥,eí2M…FsÏ«¤ˆmdÉ*‚8S¦q«:‹w@_{Ú-är„#pÏ9«†qÓ
+Ö½Ô´Zó¢—fOQÈå-4-H¤± i¥¬[‰Ë„Î1¼wjv3¯Þ‹¥@s¯)ˆ…¥õÊ}Û)'å¤Ù7
+ˆK²
+ó¢Ä½§`—ýX\GÅ,L+´Šh¬Êt*Ö—F†!Ý\¬á#ãmËúÃ]`¬,cµôÇ7ñ )w.Çèô«M¤ø€×`¯âÓœö—Ž"â \$2”R¸—a?ðU0?«úð¨Éˆ†c–´¿tk .€uPz]º÷
+ò`j^ œ'†*›{™þ…ÐkÙÓî¿©¿&´<q…=]X¾µfÈW™ØPýþž·1ýüá}ûo·ˆÁ‡Ä_”ïÆNOüoï›Sîã! ˆ$bš÷Ëï d2tùp¦ÀZ#Ç!7ˆ³û4y+ñ7ë8h Ô„.÷2j»!ý£Ï‡G 錹XÜæœëB¶à‚³ÑchÂ-)t ¬ö©/wÓ RÃþÅ õ›ßY3*ÉÚ
+ÃX<#
+v±^Zz·?Sš™÷Õä™÷ÛI`l¢°óƒkIÜ âY¡LŒËc{>QÉ Ëo»YZκA1Ü"mAÝ
+顇«¤ È/ÞVê‰ rƘ?hÒ+:à¢û°e|®Á•é»5|,Õàά…N \W
+a‡$kOq°/üñŽ¨dòpЫ¤àÕ¤zó}
+N¡•±;˜SBTd‡WV¬šYæêO‚™Ó»*lÙÆɨ$!ƒž¿ ˜–Ìì\ºŸæqo‰ºº= F×A{²'ÑN˜¦ÀG„€í$fSѯ/e¬-㯲#cÌ0R4bˆ—7£‘öýWEk†FäÜ—†šÃX g‘3o$Dꑳ›~^óŠŽþƆ^‰„…(A6YŠ}‹:Ì’"†_Ù2ŸEõ¾e`ñÈ•ÈŠVûwÇ ùç8Ùf@%øE_‰oi‹,¼¶µ™$,Åu®¿“ͬ
+`¼º@G*™ û\aþÛ°Ç@—Ù'–AHdØV¢¿4œ}*¿´ëA¾Ä/* “6£]ù¨ÕNn(ü˜VX ÂEÅ´IþÌσëÀØÛü½¢ÜÇ„jòdymjg _&51&{vffØY¢æ`M%Dš¬Eó¯uASY"ï&óW|Š2¸¡ÈB¯·sŠ¼DjzæÅßUš”þÏx¹äÈy1ø¹Ãœ` ÷címn1Û™ûoýQU2Ü-5ÜHØØz‹E"@¶Ó'’å#牰jB$E¨Ž”ÄÛ*g½£œ¼¹\éäßñ4'‹Ÿß÷Ö eúz§cvúAR,P'Öp+ûϤØë èø‡8lì\òë:ÅjÄ„Y×ÉÅÜN£ñéš~ÖÁQj^™ŠÄ[úYÕ`NDšÓÝÇäYö˸åí1CUž4v]¶G˜Œ.smNAÑ©R½ ˆ7f.ü Z—’QÞ`å×êæºÖ€®u然d†6æc­‚
+Qå>½ðr¸MoÛ
+Æ„æ^1³n±æwñ z¨ü÷„ïG®gÏlž×^Ø*’/k
+tp0Å3õo¹,ÙǪ»…ÀVŠà’§âG˜z Û:]‘œ!¦.·jÅ{ëwJí—ÜrWʧü³h‘¥i‰\Ðïë@®Fþ`¶ÓÉ;ÿ,‹Afx`†+ ¾óOI° ®Á¦?Æ‚ þÞŠéWýÔPïóÑÆê–•1c,¹ÃHyͶ^øÖw ßH>šËž½ÓœêãRƒý²($­rF¬E¯ƒGóÕÕ ú ²`0‚há hœÆÀ¸hÒ³„°;/% íÉ œ1"§áÚhØThô0BŽêMR€¯Hs­S±ˆM>­Dß
+Q¨â±äSjaQedôDØF‹ýF•û*ÈF×SõÖ^œ„?NJK“™¾Þ(2‚è^n¯s¼Ì²,šCõ¼'ä¡J¶Õ Â5¢vzV»Ôyª2øJ£-nÝn•hJdçšou<Nìò´m=ýÇý¥‡sj®–ºÕéb;å>Ö9Isœæ$ßåR‡³2*û†d¯w´AÁ…,'Fãx¨Ò/ï8~À¾HhºÙ`ë8ÔŠîG)^xåtØàËn?ý¯-¥(+“™É­{@‚¦±òj…ÐÿÜ0ç‰ÊüÔ\djIÜÛ sP®›Jˆ:v{£„A‰ƒ ðuÿ¦+QÂMR
+ÿ§–)vbžŠ.÷÷£J™ˆ„gý$C(l
+”}§ÓÕeßIå$Ð̸+õ:t^z4E ‰WA!…”‹–DŽú©ñ_$-©mÚ$|¶:cV"RaÃáï–ºƒ|ÿ ±l@X|§ê3Ñ•î|åÒ4¨uÌ°uè1z’HÚŠ.UØ<¥ÄÒ!qò Û¢ UÌ$©„—‹Ùïaj{+ö-’J=’ l¡µy¢q×VÂŽÀ@¸‘oqÊÙ£
+Ñ:ºþ½®ƒˆ…Ž„¥ªyëG2ÇbƒPYôÊ;ØÁ´BðŽ¾âõ%s³0þék©¡éÆ“qs¯æ2óS¦·¢Š6™ã ¯]‰VQcêç*ñ ’ Šüf€¬®Ï =N–²ÙføkfXŸîLÄ„ØP˜Ö kÁjuŽ—}(ú%ù[€
+H‰Œ—M’U¹„WÀîú„-ɲ<æ ÙoTìÚŸl:¨ã Á_U^[–R©T£Õ××/f~ >¤GÕ×?Zýj͆hVJ}L ±â>ø; o_þL¯n£E3©C%azÕ
+ÿ4î+»¤hé4—óäk¹2e –׺Èñ ôí ¨Vs‘’œ™3) ]vÌ]¥Ã¼ÞéÞWB觑«pÒ‚˜+G´*b b]ŠÕšDÛÙ¡ýEéœú}^ãÍ’ãwŠ­Àçkó T„:–lö8×é÷Åþ
+-JÒ‚³
+ü§:$¾ÙêT—ÐÂ#觾yÑŠ@
+åu> Y‹JƒR$lŸc¤t4m!.@ââ£K÷U|ºtuRá’Aïd¤H%¨]èI…U­öyŽµžÍŒȆ¤vdHå±+:¼Q´Ôàé×/g‘dÓÞkxý€y°ˆÉõ¹…Õa&ŠTF[/׬ou§Kv9ªðhRÑýn‰OdFŸzJJÒÉúì>‚G‹#ùqÒ•CáúÁrDÊÏúT.HÄIŠqGCúÉEÊqLÈhNu»ù¸å{Ðù"LWpóªJ£3–Êš!ëåB ¸ô­–¾  ¹ß}…(ך£§.ÍÃe¶
+¥Jÿò‡ˆÙç'ý<•K–}~TŒ¿Y@úDÃ1ž veGä¤ç«%HFÖ*“¶ ³Ðxóº jˆ`ü%)íê™~‚*ÜZÙ
+Õi¤P—¨´kô.Mž¤óÊÉhe¼ßã¶PÚaÂfµÐ<X8tØžOE ԭѽG¼;&ÓC6Dsf ÝèåRAËä5ˆg ƒ=YIå÷UÌF"¶IŽÝç1rF8óœ {=¿FÉÉÃ-•Ø7}¦`»MÜ9n|C0€A׎Me"FL<«Â¯)îD¦à/]¹Ÿe ŸBHd}©nC¤0Ô\å$‚Ó¯?Çq¿R„Ãö}PºÃƒ¦JŽbÊî£×@›PðìÌÔ92‡üé{X8™A†FŽOßÇ”-itî™”>ƒ«ºÅÇF´NJè:£5<©ÍÂAy:IÄ‚ÜÂ+±e^'BêäŽ<yLÀš„ÎÙé*èÛ%ƒ~k%ØÉ:–¢.È4!d¥x¹Ýƒ¡¦†ô5e?€>qããËé2ķᯪËëñçž8<üÙ[™?ÆSżå×›sz
+!lq¸whœYMÜo’™bÞŠ€áZx¥/Å€ì ž»{”dà{¡Ž“[Äaòðš¢mQ‘ÚÑ2tÒ¿Ž ÅqcÛø¼oú-‹¿Ý>dJ”dö}éÏ'åýq5FSÊRVÓÁµ¥~â¨b·<{ V‰} áŒ?´ÍÛ·Ïèéùøí»#¯ÍI$^£ßzh$(˜üŒ_¹¦ÓhzåÜð:Eá-jñdU¾¤sC)þÇs("Þ€‰Â;¼£yòùӫΤÚK±S¬ 9§r¾1ÍxôTQ¾þô\¼¸‚õgº¶÷ „ÝXÑš>ÍÏêÃ^¨®6ß{4?d‘îA~³aKUVƒ@°â°§¾1?YU(Î ô`FÏ‘+^Îå"'ó“©lq{R>ÍOr{
+Ÿæ{†mòåeOÃÞä)Ã,^±¯úC{ý·VL k
+YêmÒfÛp´•È±ISBêœàùŸŠcØjÅ;KVêÏÐë5R?ŒÉOQ¶êåÀ¦9#—^Y LžÕÏLéöH˜¬²4x.A¸  r<&­û ±TÉÇ~7–ËMˆ2× ¸ÈY‰ßÚöP-]‚ƒX»Å ô‹2~A ø -sXeÞy<Ä"7‰5ß|Pz ›é¤™Õ™¡=ßÓ
+­«;ÇÓ“b¬™roŒ57z?WÓ™ÀžŽšB±Éi©$ŽÑÕ7ȱ.æ––a¬ÇSžå~„ò¤ÍáIOú=Ró$ñçüžzá—2}ÿ›†ùoÊaHÙÛ\gCßغ'ˆ’õ=)ÖWß`F3ËŽ7jÇ•’u']Ì ¡Æy¥$E¨ ú‚Š×£¨J~†Áê$ÒÇQ ŸU?ˆ*üRZ„õ ër>‡°¡Î샷b‚¦æ” g9!é°KQÔöU#G;¾3Ò`¬Á~„#l»iR¹T&›fÇôÜeÇø0}çSûBd#ðŒ$?o”GÐ/uÿ8‚°,Z›Gt¯Š\Þ°Ò-nÇÆc”]-Ü 6+ ©²­]Urø—'ÛïæÛP ãï·Ep:tù¸Yª‘Áwœ‘jÆI&†Vp.”øx<f5ls™´w0­-Xë"(‰gøOÆ@eí…JE7? €Ž¼íZÌ+±sÌæ‚g‰ A·#Ö^±FˆÏôžZ.¤ÔŽ,pûâçû2[˜ŠRYö¼”튡=8ðX4È7 èH*´ ¤D,‚ƇosÝ+„Eç±Ð’U*Ia‚›CÎæÞ1©È)uȵa£ÒÓ$q;r9Ï¡—9šÝ¾­‡¥/‹ô¾¯«JîlTEñ—ç «G#šÜ+ìæ:Ÿ±ürÚó•Ò×+íÚé¨aê H¼;GFB”þ Ÿñ¹ÝÄL§„\û*¶8Ò•Ÿ~Ær{)X"L-F
+!Á} sÒ8•$ç
+ÍzàÖëzÔ=h2Ý
+¢Ð[x3”²Ñý²K@ÂQävóL~”O±O"}PÀç倃5îÓò¼UŸñFu7Ú¨¤EK'wªÛŽßÚ~ªLcÛŽ¸LNÜ5ox6VäÈU ,Ž’¾ ºÖ s±Å½±zµÿ
+&ƒ:åSÌuð( •wsp1ž1qrtIk€”F5Ù´`Q{õÕ|ñ¾á[
+}Ôü@ßeÄQ÷ìÈdˆQÄóïçËaФh•Éß¡P~ҽܷÏÜ›æv™{óuoâ
+
+ÀœcìšíÏã8ê HhiNWûvP‚U±tc ݃îÇ=}~gDm’óFW…ž1 ;6“øeuÐ< rÆÐjŒ—¥‚~ƒîÏËSƒî²°ˆß:Õ«É0‘ü0ÿAlEõ(DÔLOxˆùüF–<—êR™0R¼¯Â~Ü «â1(©Þ•€Î1!EÌS¶m^€“(™…ݬסŸŒ =à7ôm2õ:oà[W½üÂ@¾‡™%5»9®.œ/ÁßÉd‚‰œ"u1Qœ®ŸBü¨É€F,/¾c|Á&`ðÆ‹Û,bèc^õÅÅ÷WaMÅþòjçälÈ*•…Q¼Lâs‚ïuŠƒnA—<`Œ%ñ8ÜσÀÔ Væô&Bho(³+óqÔsn4” ŽïÍSóœ`"ö’ƒ„¯h£S¡žBü¤ç‚¾óÜ6÷Ë<wßñMÏM|ÈÍ}nþÍD‰¤~üõ–ÞÿøûíÇ?o,3Þ’2ªsíƒåùuŽQŸÊÎv쬀]ª1òbJž–ƒ…°=Ù7”¾ô‘ÒòÃβ$TYË6ã¶Ñô`"ƒÁÂCòì;™Ä.+È‹%úùã@Àt”Ú£Êúµ–K÷Va–9È`¥Ee)#0r¿‚¸[Ó¿`œfß)…ÊòÄuԻ،g§^,‚u SÃmî!FÏ}Ú®µ“X#•s¨Ú©y›<ñ«†V<•Ü[Œî!hy£AH²Ì !“‰l U óÐ>°)8‰žÊØ%ŽLvÑ«€u\®ÒzÛ¿3@kHê(A+áL‹ç8‡ÀÀÆ]GÝ‚'®
+Xú¸ñ„Õxíâ£9,šž™[ž?~Àuaœï\þ!ȯfi%*U4J´£žS1ÿŸå)Of_ÁÕ¬D;,Ö׉f Ù˜|ª<܉›½ûT
+AIUiºµXK³I{¢äÌgZ‡ ÏA@ìc\y´¦ˆ·,vˆ+~ýìÃe R”™…P5?1¦’ÌQSèEÚ‚U‹8ˆã!>â´ØÌh¶øžSYh•v,çc„·ÍDÁxÊ•Ëù+
+ŒBô†¢aþJqÖŸ6™\÷bUÌ:†ÏÚ™4ÒÌô•›±iÁ¢öê/ªùâ}ƒ‚VlàUÖñ;4Nâ=ÒtŠ‡ÐCii>«Ï‰ ÖŠôíRD ‹nqTWÃ0e~=½ÑùæxxCÌ¡ÿ¹5¯³#@UdÛFF“Ð ~Hë7wžä Ó¶›æéƳ§ 3
+¬¨^Ý•…7Zá Ñá`ËVóó¶é!ÄÓj)Õ½â+ ]Ê/*o/ÏÞ‚[™vY"8D™Pβí;ˆ‹@™Ü{æi|µÑ,‚×JÆlž¾Ç?ˆÎ‚³H)}xþ
+ÃÓÙÜ­¿ºJB—§DÓ­ÌáE ¡šÖR?&†ˆ& äe–czO!eŠ“nA¼Óœ¸/S¶Ãe4êr‡Ë1êð$´­fs 9Wîn™A¢97š?§7WÑ:ìYMúNUzñ£îž}çÞ2·ÛÜ[ïðª{ W𯄲yGÜç€Qe–M÷oÇékêªÐ
+úüÎ~rñ½¥÷?þ~ûñÏ[~ÿÏ[OóCº%g»{x¬ t­-'ù‹…«!Ñò'5—{ÌÏ1v£ìB¬Í OAœftDÖú¨#Üœ,*F ÁÂüâ#4=‚»é9ÁÔÐ
+êÚ›™Þ\)ÌÆÿ/“ì¸rˆ® öàäaߌ=õ.j*ïúo
+ž»vìE;zú§»TÉL°U—wW3¡Ç©Àec¯!™ÍÚ(<^k0¢uãQ§LÃÇ­7mâÌp³‰d™„ä©ÈD£€&ŒkS@ã)j`œ%¾2•6üÑ+8ç8þôí‹I3O ¸ø‹27±n½¤i£X¬kw3É%Oš_O%Žc&ÎŽ±¬É£ÍË9û‘5íÂ
+Gl¡˜+É¢2(+ÁRV…{+Ñ»VEÇÒ·}j³Â ®ÒZדñdè§û1lFj
+^,BÏ-¦da·•˜Ý'þ0žÈYP  ,Ë[ &cax¬¸Qä`¬4v+úð"öJ—Lk’ØR–‘™-î"X÷IŒJÜ;» Ѐ™Ã×wMÈóñ#Þîc[”h˧/äç#¡„%x©X …:H'PaÎmh3ØýÕögW±§ÿ¶q”s®ëzÎvvãÞðÓé¦áß+Na±¤kKù‚†öòŽ—˜œÀÀÈD»„­n©6ù®bC%åÙZÅ"I±DÅpRgq|Aªú¥}d510?4¼cb Q)aà•H&£`7sܾ™‹S‰!•T/F
+ ®Ã:ûzÎë3<e×ÛsBuˆ,Ü\r¯#žó Üœ P–
+ŸÍW ¶É8Œ<ÛåV¶ÇO¼s¤‹42°t{\ØL%üRÞÚÛVî&L¬ÙCV,ü¥Äßb™ü70ÓùÍ9p!ÎusµV¯f®p % göÅÌ9âѬDM#¿áºl^@wóúë¢ !¾¬×ßÔ°J£?Ü>V‹Â3ø>ÆîïƒÃ)äêûEÁ˜I{®Š—˜¿‡…‡ÞX1^4t™7^×sDŸð+Âêœf¾Z1ðÕ$i™á§öÆŠSpK,ã_ÊaË/V °wÖ‰ÿÁÆšiÞƒ]6’»-MÝ vŽ ({|é›Í:’Cı˜8Òñúìt×dÑl–°íý MpUîr)²’½Œð˜\”°¤2/© ƯƃážnѼÞšlÆ¢ÍPQÁ]wmÎíBw*pªÑz;ñdT¼ÀÚrŒV2(Ã:õ #þüçVDDiòöK.µ2%kºàKÄi|þRôáC4}G‡ðŸ—"•€f8p­Þôwª„dÖ 1Ö&*6æ
+ãÉ©µÚxÖCaR¹3çtÈ,äàY4
+åq|";5Ò¤›íƒ„Œ;Ö•P“nd›Ñ‹¨¨²ëø-0¾9‡Þ¶÷7,+
+‡Õ×­HEŠ³0'ô *(Ð1LPìSóQð;$¡¶ÃI³ˆ)-îåç,0H[ÇÛp=ˆrëóZ€Ã¯|¤‡ñ™çh€%š°|m}T½4’6ÏòA¨µ‰x»·±ù»xŒÕa%` BÒƒ4vL Ǥ@MÜÄ‹˜v•'@n8†ˆ‹ ÕVÆsÄÀŸx@Yä:.%ïèâKѯkQîܳkF·ùÔ†5݇ášbôk{I—ÕäÀÔÜx²šÏªHTò|kEXf0ÅËŽc¾‡b(§ÌåLùÌo”&Îàás_°h5Iù¸”ø;È¡6Ù NºžÃ&€W.†w*ùXxö{HÛr}SòE
+ÂÅÙä/E*n4naœ5"ügÕ6©¤ŒM‡CÖ)¨ÇÃÊe[¯×¢—»14´‘ÄÉ‚•£4ß×v2L°ÆP¬†À‚ûA©Ñcã/E¥0Lù=¢mÄB”ÜPÕK³qœÓø,zÆ\¶m·‡\8@^mݬ¾Jx…–{$ôÍNí*x™d¸4®çððÄÏZIn%»Qô\ÝìæŠ ½ž›÷Aˆ€`x´øÔ7
+EìůëSŒ”0qÊËŸ™È [FÝ…Ð%Tx6ž|#W¤Îí%œÈ\­vì> AdWì5o5,´ìó‚܃³ ©µz)úð"Ò§Î/¾¨©–·¹ø;#Xbˆ‘\qMú6ÁXvÜeš S— b¹5ôóââ.ò!èÎubh‰(7Ø3`: ?¼‹ÄERÔÃqO+ÁÊ`§á/öèR/Þ20‰\oÎ1ŽãÚôËõÑ
+‰ÉR$$2¸·*.¤ÝžwH²È;Þȳ‘ × £lO•I½ÅFÌó1do3é(‚Š4 V  K R„Ƴ š—FÓ•pïó!B>?8ÇL<ÉjŠ›klš8ž…aâÀùP+.H˜û ¹v¥·oiRŒÊë>˜çÿ/“ܺ’#Š®€{à¸
+- äû½Ž@Ü·ávŽxœ}.˜>æi_V§çT¾®1&]q À’Ï£i‹G$µý)¢IÉÊjc[ø˜¿Ágµ”wg]~GŒzôpX‡Êp½ìËYÌëö^@ÄõŠ¬4‡g­1•")ý·ÃÌ$…Ó4¡Kxkv1ïS°T/<šÒÙƒÌðÉdÉ>¶±Êr²è;C6Ïé
+‘ÜŽŒèº³¤s¹>[ÖØ8./}äÕ‘Ç@$HªÄP›N•'—‰ü++*e{ú(®!]g(ò~T³¢96~š×„²4©è{ǘÑTŽèFð‘$Y9F›ˆ¹™i]¢ÔñײÏ+ùÜAußص²}ÕA\…Xoµj]z•ób“¤¸¤„y×>%:aÐÌzì‡G8
+cc³úMïþ(›?N*솳ë‘ø¯RS½t±
+;“Ã"6;Øóù£aIÞx¸ 6Š| [,„„´Ó®ª· ²zƒSÀô T"dE ÿî<FN“BŽæ- ®5X0oGÎ2üYªkí\ùrŽáUs—7“=·)8†¬)fi¢Ò® Ú÷ çÊþƒÝà%Éö®·azºx-Ïsh ´ƒ8Ñž½€ìd‘<%¹‚?vüljP*Ò†{!µ˜g=¿æ¥ˆ4VåîÁ5@pZ5²ȱ*ßÌAïÜ€’ ~#ß
+sªèðpAWAÑ•ù[…ãmt7"ééUÔ[5°ÙMZª`ÊøA|¹µê6 ‡(Œ’Rç᩺æ™ÛF˜Š¡zâ´£ ªf¬¨YrŽ!“”–j´+¤C„»Ê´`˜&å™í1ˆf¢»;É.°Ê,
+f{Ž«Ü"î)üîxïÚI<ZIGPv … ,Z—š$90nžЩ„bVÚ—û ß »ã­2ƒª§³ãPL„0àês~« –3´BBPëFeÈö»éC¦â«Ý¡bY}hS²‹<.œ¾=7‡²43xn*H7™²6iMήðz®g áÁí‰mK&àyIgçHðl=¨-î—óëH‘\[˜žº£5|oé*‚Œ3‡n>z%E¨ZóPá<>6Ú±¬ážqiÃå0¤øŽ¾;qѶÇ¡+“œ‚çÔH”µCOcÚØ;F7N Ð,dÛrC½Vzcµ&ÞAMc*ý4MóÜšúåªYØR’½ š…â±e› F ÓS˜1>Å̃(ú@
+î\¹ê‘b`¤OvùΕ”P™ûÈκIJ­â"F¬g\Ù>[´ž§ŽâC׃Ò¨q(·"èØÑŠ²Ñ»™ž˜qC’L¡‰&Ò–¾ŸžÏ9ci®fu0¿^ ¿Èä2p•ÂÈŠ0ÝÚ,!‹¢x@–|<m¥Ö.|dðŒ¤òt¯<¥ç¤½@0hôb¦ÞÅØ1©<±iÑ=‡|€f1›–Ø—A6 ÎA•ÊXH‡2Wlßq=ð—õD6ç8ßAΤJ€ fljiáu^7ÊUèfј’ta~1Ä™)^ÂÛ+øÝÓնƛÂö m`He›F…Á`Zn»ˆ”‡§b2Çñ!·«51¢¶¯×½8åƒ<fɬP|Ãrò?Íü\“Ag²ø¦<9‡£\4d›÷møæ…_‹yB
+œÙ„Á\ï‡W¦RÙ@9ñÇ›rZá}¸[æ.ÕW1—¥x¼²9sÁ‚Qä é4ŽMÅ“¢(üˆÌù5A"hÆ™Ûz€dUšf…ˆ¨m T%{ªÒЋ]<Ï:xÂC7
+¥@ܮѢ£AåÄ•‘}ŸÕJ)[«ˆûä¬#{ OìÙ¡†4†îQ£¸ øa´ ƒi'áP'–Ûñ‹³†w#¦a 3¼‚üx‹áƒî¦ÏÑD–
+ = +øîÂÈk}†Û¨ dĵáÎ9—©¹Þå>{Γî#|+·—ÿqŸ”PÈTQÁ ‰$ÊÌqþˆ$½‡÷_oIÙ:Ç ŒIYÿ!PÆ2DF¼6w3˲Á–rO5½‚>=P®2¹¡B«@Îç® Ç+w³„÷¿ÿûö×ÿx'i¾¬Û4§úcCªMoÄ ëÿ½‘IÿOyÝ$É‘*A
+!a9ûœDË‚~\ Ì¬Ÿï‚¾¦àó<EöÓÏ”B%s›Œ9¹[«Ò0³RZ.ÖÝ–HD~±=º6„ô´„Âbå Dç'kçWŽtnáõQ¸ªàÛ
+yB‚8#νsÜõØúðá|yø‹"UÖ)»ÄÎ Ž.Fœ½8ç95%eüñî›*u ˜Ù«Â÷9ã¢;;ÔSºå•Ç¥üžÅo-\Š7YÂÈÔ:§hþG–}/æ»Ì--ˆ»„ôR™QT4Ž;RŽâ
+Æ'Þ{]4aõ3±h(¸ÏðÙã¼üuî¦
+PªBh—sé ¦IÒŽeEsiÄ‘¡fu,ˆYd¹’Þ«Gõjå¹Ô²µ ‰ê²X9ß"aP†â]uz˜Lª'V(v‰3fì‰ a=jØÁ£Õ5’É} 5Òd {Aöy„ÓÍå›sªesË|»^?ˆžÆ"ËHp¬•é÷…¯–æTÅÙ¡ì™aO»y½¨OÇ"…8§!ÝD"Ð]«#då²­"ì É”š3má³v9[X‘+È/"ÁìËVèÙó–Ð?¸Ä¡.‡uF»™;Òu„ŠÆ4€A3ƒ*pî ß¾L¢†Ê;”'&ÔL†ZÞ­®uºú¥ØY&$$·…kABÿ.¤1ßAÂ8¤¦opsˆß3ÈþÔŽj®4à¯Ù:9|oaøž@Ÿß€8Ù wäý9Öéõ˜‰M×âRóK(àq-Bá«õHl énå%6·âm‚ˤ_åŽ!öHPÕP˜5Âzò$ÝvM¸.£X¸h¯²ùí,.b£Ò¬÷|Î6ñ‚¶i27]̧âÛyL8FBŒ„Ç ±q¹‡±¾Ö›$ıÌ}+›líLd%6̵"™LËNxŒû:ÎÄÐŽÉyù ¼æUﶛ×I& 'À¹4T”‘ñtO×bK±'“÷V¿9Fú¥V˜mA¦sAˆ˜â¶ ³×…A<÷}Û­kKÐú¶2á9S Í;9Le˜+"¶B…céØØXlÑD6PL¿\Ü+|Q¢ÕÈA€ôä»âØñ÷ä½Ó⇀\;^Á\§’ÂÝÌᑯ0û:JÁÙy‘ÅÉØH]½“G¤¥â åã¦
+Â.Jèî ‡XãÒUä˜ ÉÀÈû~/ûÆ‘ú16o¯¤±uå¶~EÐ^TúÍ#|>k× akØàeš.mÍ=²Æ·=A[8‰Æù·Šà&”J/ç¾ ê62¡·å6‹V<@èüœ<™Ö9DÛü· Öúè§þêË‘ÑCŸâ-ãz˜™°o-Ø•c*(-=`~=`âÒúÔÂÒC{&¦¨—úÙY#+ï‚ž¢± Të’~íoƒŽK Zd²¤Ž‰”¸Öú@ÕÎvªÚ´ e‚^SùôùN¾Ͳ„|Y COo»’ØgsŠq®U•ÌÃR̸€Ñag~ô%Úç7Z÷~=ê¡òGe6ûQË7Å{=ôJÈQ'Z±4½wAOá^ž÷†<G Þw,&9ö„q ãw1aÉ:ÊB³$èÛšüú|'Û³(áÔp›\¢û‡;ýïò”ÇÆ’’³#|{ô€ú‘~ëšÛÖ›˜×$={D)½³‡‚Ÿ‘ÉGP¹8UFüœ…ÍëFÄ&rŒ‹¨¦ a}y² lHJ±]Õ“é?æG™{̱²”5‘±‰È"!ló˜DªÂÕ´G+\ž>Ç®7–8Ö²î3qõÃä^Ÿ•¶@­Æ+—XÒ"> Ss‡"÷‡ïÅ^± `p -qȸæ&¥Ýî7ùKÖ”±1>"Gƒ~ΕŒ¯¸Â³0_ RÂíù³¡ìRÂù°`C#>@"’‘C¤|•ÔŒoÎ1[Q'O?îḸ‚¹ñĶÚ#}ìxÉ7$‡c± œy…²
+0 vj}Þt~ö0öêEb!2SÀ^ ÅÙ¢7•}©GVÜ€ØwˆðuxŽ~<¢“˜è¾LÁç§X0µÄ
+i=`Äæ…+.ð ó¸)šÙ2ÑØ<[ëú8«J²,¿O›§‘¾Ý8¥³Œ#jÇuÜ mU#ÛC¬[òï~±KíÅó˜Þ.ëŒ]qË«ihÜØQ +Ô†˜ùÖßã›s[…”ˆTn<WHv±¥7ŸÒ¤øšjÖ;’†M'”ïs˜9£Á¼žëœhå—õrË }ƒ»´3Žõîã4
+ü\?ö!É a³Û‘ö0˜wUèsWÙD!Žvv,á@cÅËLΉF~q=UZíÉ'ÝDnBB<:O•S¿C…y ÓYîûøÖ´¥æ‹“¾pÿò{Dx
++U“Ìíõ ó³±,Ò‚PZß|ô'õþ]®–¦%#œï›8ýf² b€Øyᦪ½€ÜO.׈Å`oƒ^]bαZÎ¥'šæ]‹Ç¶¡Gµë1Ü» ?RðùNž"éç¿?Œ‹6½j°¿¾o¼ôJý2æm…GPV+1Mø7d[OjõEb‹q–Ke­’ªù6KDZ4#+ï(ƒ”Í Þ“#µ¼[g“Ò‚]kžçÈÖF†§úX×åG.WŒ—NÓhų&aæmÚAä1t¦ÍP@å$¯¸­+#¦‹Õk GZçx^µGPîÛØ…éB&îPÇ„ØEKÔý>ôöŠÔ-rH3øl¿Ü4âõHsY‘èfA3Šv¦ ÁRæ…ô>!Òg¬ºÇ×ÄŠäºgÂ/Ä»|sŒ?¡UL!ä†àæÕ39qQ[è 2}_æ”’„nÚ*!.”µÛçK§sº‚ü'$«lzö>«§Øp½ýœEœ
+2H¶CýÈÙT(KäÚ&ÃMº j½¾i‰¨øÙã;UTQ›¤ïråQ‡Ö3!¶)ÛŠu–z¹ ñðF.
+Ç„`€“D-ú÷Þ|… ‰¥n-–-³Ì9üý{•2%{r!™°}Ôûȇg¤W´ýï¸Q”
+áHV¶×ü(öJGÙ³²`ø¶iYÄæó$©Ä¥‘ ¬ë{Ìσ;GÈÄçãWaC²Û¶n"6Lƒ1ÃKÉ^^Ķ k¯>|çÛòª€™%C,qÛ,7
+¢OS–™áI9&
+d0sbˆLd• 9!ÉõYÅ=
+‘šHžÈ·?
+(O¼óÍ\FCh_7ÎRx(P’ÜÃ:ç“ûæ¢ÇåvÇ‹û>9ën@ m
+ýäá6`ˆ¸a¶‡’o|þêOAýL“¾2Ò1úE%6õ³°h ü›OÈ]€Ã
+ÄÇÊœ­G‘+`Zר–!p¨mYÔhŽÑˆ—w³ØŸÝ³Ñ'n[ÝO†Ep„ø¢ì7îS ºF?;oÚÖdv¦ZÅ©#,m⣅…ÂÅÚ‹f§ a¯haz `o¶Æã2ì¡Àt¼›•±;ç_Ìüµ÷ÊíhÅxúŽLcÀ»vP‚FƯÍÇ£rBû4ïù S<Pô›œÇSI’ˆ¹(úù(ÔG™ÌãÞJDõÝ Êr üÜìá pCžëËÏ{o(ÁGA6ìozºË7”ÿ¼Õˆ’òÁ Ðë¯_ež)ƒ‹¤!]½°']2Ižùúç¡HØ1…ºÕ ,KºZÑŽWgâ˜
+q¸:ˆ/€ -Ö)ƒA£%»b™u("˜I££¤*¹%f“é”'ÔHÊàÚÓÅAzF×qJùȈ&3œÖ‘M(¼b1„Yþë8¡™‡Ê²êÜAÖê
+‹op==¶bæð¡’ú¶/¥¤K꣓WßÞnÉ·i¶t«I üLʰסé ž™)d=©Ý=‚Û¢­ä!ð] ÖtÛ{Z³ƒÈ˜ƒ^7DÌů2 Â@ëø ³<Ÿfôç·Æ ö(’!B£7{A«"==G€
+c ;Q¸Öš
+;]i5 u²&ïÎÁ‚^Ï$Ó1©ÇÍ6âæP/[©½w*`43ÿâÛæ< [ÌÃ$qíà
+Îl4 ò);Q}…çU¦òS‰*,&3¢Ø¢äQGŽŠÒ05¸w'Sž”3­TÂtÓTX´þìCuq•.)l›J°’bb‰BѼ0á’¢¸½yÌÓ£f ýfhä$£VrR!ç-âRÄa­ÞÇa¤L6ñ%H&þåUñû(àŽaשmnÎNÿ7…×Òɽ˒{“¯í€øùíŸo,nJ¡QÎ8Ч‹ÿ FáD¾ w2çòë¡*HRS¤Õ¼ÿò­–Ò "õ¼á½ 5OdÜ
+i”‹#9L@P$Ò
+<áÿf&z]Ok!nç=(X9 ßHá+a¯¾Åõ‡ÂÔu
+"ó¶4Úe+#Ô„Ÿ—Ñi! ¡eÌöu"'ß
+½I²0IŠ˜ KàQ"!"µÓ†ãd>‘JbÀærÉ»Cþ¶®Ð +ê1d' ª$IuÛ¶Br’µ`e™JA( ¿1Ƴ>ëÉv8“ì”÷'T*GŸ÷… |¸ »dÿÇ9±ª„èõpÊjø3‚—Xý
+c2.øŽçÀ¬Ø:$b6iŽ¡çêO¿¯Oy®ºsÐ-Á˜&™¥ÿ0»
+œ' ^O _'Ð}Ä*t ˜Ñ%BÔ¯‚NÛ=ï÷%ÐÓÈT‚ÄEûÀØ­¯bÎêT–O ¯¼·Ê’¿ÿ4)uP+Ô„QëºÒÄ$Fèè÷͂Ć¡Äß BAT.“–"¢#© ù£3ð‚0ƒh!¾Ð9žãúúTÝ÷€!ƒ2l4 Ÿ"_·e ímÕX[Ò a²§Ù= ×´XZA¾y€:Wì„jë¹á–æ™íUG/¾ŠH-Ëlò¾aš‰ZäSK Ëh²€)ÊÚrRTp±S+C§YŒÄo|¥n™8¨­#óÉITž"‡~ASyŸä‡á`—e)*ýDøFø4
+ÆÇcaèu7·Ô™%$ÌP
+g|¢®Tv®ÎÈüâ|Ð{
+· ¤B°
+?J2ÖÉøÿÂm.Ï ù‡ÂýÔ˜ÕmJÔ„5¤“7©‚siÌåËÈ3¬“ŠCpa®£3§F—bÛÑêæ‡9M«=¶’ïfŸ«†Ä€O)ÐðeH>ydE¸‡áoÒXÏj3 Ä–Î)p®ÌÚåZŸM£¢Á¶“b f
+ÙR’rBÚɉº³Ëeë°'÷$Ž¹Â[“ºHPÝ!y"ÐyÞfÓ¡ŠdkV
+Èqê1R‹ÐÁcQå
+èp¯/“$7lŠžÀwè#p&¸v–¾Eª²jß›÷ PeIT%N%i«¿8ø2”O¥ž A;S“ƩƸ6§p|\mQ2
+͈A…†“AçWxJhr]Î^C+=«Õ"…RrÕ
+Þœà˜6m…å)Qt”)°†+¡‡œÖ£%Œh…$uhã0©!|%+7E0Hx‰Üe.7„sIФ³ÎdÙƒ<˜íB;u;™ŒÄl>>´CƒpÅ®·qPSºÄ(@;N)U€à,ÇF´'ž:ò¡›&ií<–ä-6>¬óCß ·zúöø@9Ö1•Íš>pH‘fÏlï\ÊøàaGÒìÖS© (§Â?’¹þa'~‡<ÉâÏ·z}_3÷bV;å$àøÊ&eÑ1CŽÔŒ[,-Õ›ŸU!àwè®J·ÎÜ1qŠ‹ôTð
+9$³›8¨+Ða¼ñ:âÀwŠœhj§ž8“¤¹ß¤dÊ÷Æ°Kp&>ß3|'”ê%‹”c5ˆí2;2$YÚt—[x‹e89\Yª ‘ÙDÖa”0³^èaÖûy5µ7 ­ÆÓ ²Ÿøõ0Xp²(Py½^hèÄ&«Ÿçã\ÄOƾEœêš^^¾É…/œø±LfznÔfy¥s˜UΙ¡péÆCBÇ/’tµž Ez`xOƒì‰Py¶Œ46H$Ù³{u¾Á/ÕHË´GE‹ùÑÊ1Aø¡™8Àô¾PΔQ¤a·æÆKc£Y±Iy¿d¥Ôª÷Õ $ô¹©[k2€¯ËlynÒÞ!‚ HÓ”A\9;‰â©ÔçL9Ç¥NL‹µþ!
+íU‹3ψöy=(NÆ Kc7Bº¼ž@Ê©3ˆ‡¤¹¼äÜ7 ŸH…ø$ m¼3ë»<«Öd#Ä̘Ó|äY Ѫ £ƒ²®ƒ&Òpþz;úŠkŒW¹~ãæ[]¯RFw"ÅU¤…ÒQ†Ð÷ -wȈÇ_ xÀ,W;ÏyÞ Øy{=t=z×5î"Äñ¸:„¸øO!f£éuÊhÀâñ5+ʦt Û„9áq1凕&§i{+ôˆq–þE‡b5—KnêDyÅÉõp&Ƶ
+ K Påu¸“˜É×A.5Pb‹hbåM_‚_dœx Dñ1/ήʙéÚD6yùu};HLC×A;qu¸Ð$µ\ÞöfüŸòJìQ¼¼Ž 2šß$ŠS\¤ƒGÙW¿Ðs£PXóÑ>¬£âÁ¨¹Í¸;!EÆü\ý$…F*º>8W5™t‘f5¿Ï5·—£ô;oŽ¥?Õ!x9=kÇbãÈ^u÷ˆ›®Ióó›zRN†Æ²t¿9?p8)׌ȉµƒ„ªß¼m}çÈ0˜-FšØÆVtqŒvb+ N‚ʽšH!½ŽUï#‡
+Ë6|…ï›, Œ'Iž—ÅGD#ë½×–¡[‡$h‘dÌ‘â“wã€ÐB| R)Þë5üÌâýÜé òóÇ??ò×_èUÅ1ò¬î>X^¶Œ"öòõû
+Bt1 ¼<dÊšŨE±8ì0‡@±¼;ÌŒ•u‚#$è¹…AÁ
+Jt¼L§ŒšÒumC®QÏA ƒ¼ÕK}â\d¤þÞ[aA`½Êqq nMÃ\Ö^‡RPwÉ£î
+[WÕvL×%ÄŒrâ­jöu”*N†òaqd;JX’H}M4œŽ‰ƒåL l<nʼn¦‡ÜæOç<ÆŸæ8¢N#ãȘä¼>A('œ%}kžA˜ CýÐ%î[¤È!(Ðä®ãéª3.•Ü ”î>ù=€iÃç(ûƒÁ«Bž½”ϧi< ,.ŽaÜêhñºÇ0 ­_²ÊiŠªJ59°Ðb\(RH+ï¿!]èx•  P JFšy‹ÇxènÄ¥Ä(˜ù” ÆØ
+@`UõìÈ>;¯"ÑŠþ3é,JÿD’ÓÀBem_·©ÒEftía¸ÿ½_Lh
+Á1ùH¶Ú‚0Eä"Èy†à¼‚ ‰!aÿ]W Š…µëJýP ˳:2T‡í>]PfšÜÂlUTÇ¡¥õ)(Š¤r1Óö:% Owøg*
+áQ­ç±!p¥ô²®X…×á¡üSZiPdƒ)qÐÂ>ñ/*¸œê²\ãÜÈb|p˜1W?MRðcàø¤„ £‚8ß®äÄkt"¶ îmáÂJ„Ûa¦\¹¦ˆ‰H[÷`ÂË0bšäu“A°è£äµÝ5G^-17•´Î¯[ƒü_c‹´RbÜÎV/ºšO´Î“Í
+H‰”—KŽ¤·„OÐw¨µ
+š9äð­FÚ,¹·*$åg¿ì­+% ƒôgø†[À¤æ{+6Â=tðrnE÷º±9îFH3à[;«° hëÝ ñÏ7rPEk+uñúDXÃK݃kGDضT)®¦ï”‹Š9êˆËp†qç¨cª4Pæ¤Iy»
+oµÀ—6unÄèöNŸæ­—
+'íô¼Ða4ƒÄ]M§¡EÄq÷p
+ý¡Á…$è‡I[ø;I`¥b˜¹âb²Q¾Ï‚Ó]e¶•êä]Dç!»$IíK5Œ²¬
+ò“Œ‡ù6/Œ19ô>3›dj9Dö™Ëq¿‚¸gòKoPfþ’ÊA)ɾ Ò‹Nóºò¾uiôD­ädo¤°Ž­ìɨÇìâ8K‘•“ÞF±…@àFœ
+ãÇÁ:}µ]Bž}PŸcÄæ¼KFw@H¯ÂVÒ¤)Çyå´í²wªMse0€®¾¬ÃëÏ!ŒŽ7 ‚‚2ì”ñÝ™òÞ‰QØd0˜Ó5×|é©^‹1™4Sõèm§x0„ÙHè;®û¦±2-ÏÔÅŠ¯ ›†£l×Ãc*£Îï‚bêÁ˳†äÀƒè€^¶{}~G¤?––}¹¦»Rƒ`E¸)(ŠKË_AöDi¤)”N§bÄPHcpB˜ö7@X›ÞvÄжíÝvß
+ßêëAþ~¦_¯´‹:+Xgµ7å;ä‘êã¾Üï ¯ÃÁÕ˜ƒ äY©¦%È’0¡^”Ò4Æ
+3ï:CdÚ®+vœ“wºÓ•÷[Ä­ÎR×chøÀH¹ÙËéî»_ó¾ÆELã=rr×Ë\ø£„;Ïi¸>/ùýO™‰Ì ;pÊvâaÕt‰²²úÒ &"}bêc²ÛAsÒ¬³N¼¾ [§”Hʦm¹þ®qÃcÅ¢ÓÚ
+ïki2¶ÅB…ŠÄÌÉ)‡Ù­ƒ¹¼üÇÛn!I*ûÚ+““â3;l$ºÀCRpmëæš2¸Dþ„à%Ü­wÙÓ.r'eMk±ï’KGhÈõ ÊíLxš@<Cv”òn좢2t&Nô°„¥¥•äç^‡¸ƒäÜFRL#Â.ò<—"ÅU¨aZ$Õ¤³X»Úq/̤4…¯u¨e»Ä“òh<™ÿy]…(GhάˆmìþwZúÎ\”(’L®{nûÛÝ}.4ábvÿ
+±øAæ@dÀê¯ío¯Æ¿dŒÝo“¦Ûé µ¸!4D©y8#þMEÙ#õÍiF«*UÚQ¦øC~aî±uB TPqó3 Ò+\‚P v x4A©)R©cÞø r°†Z´Ú"—ƒq¸¨Æ+¼ù²yZ7§1¸
+"J›IiBøgZf':‘“¤˜ÆÖéÊmȺ±×)x:–E/Y&Åo…± a„¹ä—‘Dшkô¬6õ×)•ìf³Í Qlñ!Å0ž€TP5mÈäÒˆ4ªì­ºZ]«ìeX¤à„ØßH¶Ì€c´êbc |ÜUÕN ­é,ö^°6PfS¬ƒ° ™³.‰@»©$g)²Z{Oæ:„4w&%Ÿ¬äìŒJÅ»ùý=Ñž0,_b×ͬ÷œ¨7v¸xÑQhäk]‰T§á¯xòÝb—L'¬¯Âµ»¨‹àê+N—=°”;VÆY{!hî¬d‚ÿT¸ã†”‹#Xo§¯` R¼•~þèÖëÎnßc.êóñŠD}ŽtêÑ6düê£ÈÂô'¯R3@]‹é»¬HÌ´ª¾|ÛÖ¨&–¼d™^‚ ¤ŠHä”<GX C©šù1XOtcå¤.¶LW%=ˆ¬¾&É’µ³!ÈAoÎÞ‰ø‡c3^æiVî€2ÍSÑ8RÄO»7Þ_‰É+9 ‘j
+¹½Ãôá€ÀÐ“Þ +è
+4+uÞ­ƒ’=7 »)`¼0Uñ¿Õ5<BJ„ˆ”®&5¦2°dæl Z™^'ëÌõRC!IÕ|â@|}º€~>€r¤‚ v¨õ Aú‘d KO‡2Ž/Ó¡e „Jè²T:„¹rͱ ˜uÓ $;‹Åh2Äãº@= JæXµ]ÜØ@;1«õíoD¥©ÉhŽU3<¾…¶ŒýYÏÀ™$mæŠë(Ýè6¤£Fμ7b-ÕÈéÜ
+ê#õuO–zðYÖ™·¶SœÂìY`ûn» NñÏØÅÕ TT'y¿GñÅ0Dg~_üÊÚ´WÅ}<€ˆ”²H·7ɑЩ„‘ê~
+@÷‘Fˆ•Â\
+@ÂÍR+ao•‘ÞĪ’Žuožì:«p,öÚmìòÚ'zLϹ“S¡›f€^—¬,s8ª©ðÿ/s$Én$ˆž`îÐ2…4,M£JuNÐ6[œûÏs
+ˆd•Æ.F¾èëÌ– ÍÍ5ÞŠf8%›cÑb ®X±æ<Gª€ÃÀùE™Íý1¦¡Ÿ¶1K3¶7é+W‰Mà }Ó¯}Õ¤L?$6v“Ñ®ž™*r?ÏA Ђ¡ÝWMwMÑŽµ–’d (£“6*,„“WĸIâ,B¤‡Œ¾pûf€»<*ô±-MßC/0U‚÷ožÕÃÖÔU›%“ 1±¶õ‡xB¥báæ×Ü%—1ýRySì!8¨dÛ*‰©LB%ìMcê¡@xH‘Ù\PÒôf覥md$hHCÛÏ4…ÒñR¶Ÿ/Ö$µA©‹/CýÓøð:È ÉuÊQjF Dí63_Òá®ÊÅÈ©Š¥
+x£º~ž¶T¦~=yèžÀ8° ËJrrÏá(…˜M®ðÜpv„ç*ò4…†e^Éé€ê:]Ež¦È¬²hgõ}šƒ1ã¤Òß:§M×þAõŸ…‡6ŠæÙ]ž›]Á¸Çq Æ
+
+°‰üâ#l@ý¬ÓoÑÓa _Ì–š²;…GPí¬3¢Õï§ð¸%§ð|¹[¿…§¼f|j8ØjÄÈJHFÜkØ^‰¢HRØ}*b®¡¾
+û’ fž=çÊ„èŠÜ5 5ׯ¯ûÍí b™ G[ä‡Ú1, ¤ç—ᇠíµmߢ¿fQ9”€Ö¼ñLA—Ø9˜·÷¦¨BÙŽÎW­ÐÁ¦t¬ÃaŠ¾‹z†¡+ËÌV¿)ê0ÛÌ°…éÍuíÖkP,kæ}Óßßi“:úÇhê¿ÿû¯?þ·ÆÞ`÷Îï2àZf+¿
+5Á@bÇßœS ‹‘jm<d .¡ÀµJìÉõÃa0]ˆw¯’¥@Ëx uXsÓEV©W6ê*š”Ân
+DG\yVásôÑ`°—ÐTÌ4/ãBY‚É„#¾9í ²&<TÛMØýˆ,ô°¬
+yŒ YË“hb—7JáaàŠ¡1É cM«‰$F†E¯‹xŽŸ¯s@=“ð…o\%•GEØŸ®äÍaÝ[}>xèÉØ›ôÁ0BÍÁ¶XŽ"™Í" Ù&še`°˜µ«;}0zÌä(e^RÎ_¥P«„Ä€”WàŒïøs]Õd¬1`Ú©Ë0 •ë§- HsíÓo»WA$LSæêÌwñD^&jÞç¨;‘qA¼cu§à”–jßL†CôѶ_Þçt»G°¥5`š¦­åbˆ ˆëØè‚+®ùØúh[§`s{uJöþ±£ x—Ñ‹{NžÂâã˜òVxØU„‹i–˜ÈŸáKö·¨o3®y_E¿YV†j» R½à2G´
+†5ssoĉèÐYZ-ŸN£<U³õ­úwØ›Éײ]ÿ¶çAÛ.ôñ„1/J
+½Ì?çQ=í 4rDaÊsÊéÛ'M)ž€PÛ›sN²åkH 8s€ŠKÚ „k0(i©äÏà e:ŸeÜÆ Š)y3Ï$šT«ÛØõ@GEO‡rân-œõóZ%Uc¦/ˆŸ…º´’"ýµŠ
+¶”š>ðùt?ôå¾î¢Û\룅Ü ¯h"ÌJ ƒŸ¤u7ñ.Ê,
+õ“Ášçñ±ˆÝôÌžF
+3(¥è¾i¤ˆè•&~àç: RÅÀcáä •€Âž™ÌÚÒvVÓî€h0j^N‘3ŠÆ:±È
+©Ço›ñ÷wÖgmYÕ[
+Jq“X8KdÏaIyŒì”¬«€ŽÉ¶wçÈfÁó%äiyî¯iØ-HEâ7ÝT{á‡Õ)üÑíMC- Bbm4·ÁWÉ9¨uÕ]©•¡$H
+ûá| %üþÆAÂÞ£()ô@_ïÚý;šC‘šÃ{›~8-V ÊZ†(£»£:KÖUÇȽsàx_sàÏÕgßÍñæhñ—;õç\=&Qu \ß]_«‡&'A‡½Ö7„pݙùÎa/¿I¬•8k~Å•ó5º#œþzSDLý6M†*Ä»{³ÇR
+IŽË‹+r÷˱¼;èœsÎáúš{šÇ«ÖU'*”ŒhpØÀ9¡…k©†i`¡g·äpš?¿ƒcA>LÈãUàÕ*æD€ó~¹E2J>f×2U‚¡ffü «º‰IïµCj³¤(]°š}g&¹Du
+”IW' äLÝ_/*³)ðw~pI8Œ©®%2 s?(
+L(½ø©$ÙœXqÚ£Cyâ=äòBÍúC½•ñÆéJÿ4èIÍ>^€š]›”Ž ¢Î§E¦#èH<®Qø Tçd’{#»pˆt%È?Ü] £±G&mÛ Fª‰| ç¶uy¿Í…„°Ùðžµôó^è\‚£®
+^<EòÆ3}bª_d#|Jšu"Ek¾Œî&³8ê»ínFQb‡ÝÃ:ÅW«hÏÍï¸få¨ÊU_G¡ ŽçBÌ·Ù"àTµAb¸CÖ(E€pöœ‰
+K^ã/w
+q(XørH¡1 m1r• @óÊ8 ‹ÍÆ“«“´¨£ÀËÔ‹G
+öLD§7õp™»Þvý}—6È9BÝn©
+ªù´}l„ýB
+ë,æh©Œ:4±,oNä]ò P™Aêè1×3ZèwÕ:1DÊÒaZ\üSÏ ˜Z
+^‡)qˆ³‚+^LY¿Ï ™'Fèb›—F¬]b˜‹Ø¤£ÎÅ̶
+5òÑKŠÂp«$?T“Vë'¯sê–ɾL«0ÒÅ•€õ¤DT²Ö(¡*!QcûJ`°Î.\ZÌ(åÚ _'¡•uŒX•©BØ®ƒxóC„Hˆª$æ6€”‰´Dq]A•°Óó©|¤'&®\åJ™;š‡ïÂ8ð (g×óœÁºƒpI4¬m˜ä™™MÐ?‚Ún›Š‘`8\–‹,ñɵÉÑ
+“´#±ýÜA·þøKËRÄ‚X4§@º§7
+šY›¼ÎxÈÙнÕÂVälQp(kyüˆ:Ødð$‰r@Ñç>R%ÿ"ˆô83vá˜/BŽœ!ÒO¦ˆ 7 qVâÝ«dËËȧ­ä m|?ŸšŠBE–U/oÊNh±£ó!
+3vS¥ô086‰&¡Ç+J \ ½„¾(ýÙÑÜ0ÅK5 ºR¬zŠ’Âá
+*S‚8`«¦aÏ øC
+µEN¯ˆ‰qg<'#ý‚˜¯Í]‘‹F>HἨ^®WKÙ˜P—–LBHˆôª˜dŒà€‰Uãt{(Bás2a3Šc Tkgd¯âÖüQIM0űçIò•¼FªÛ§¨Ô\ŠÕ°Ào1Ðxü®XGR…@œê$?õ£Á…œÉ6‘< ¶ÙàˆNS[5×ÐÝhÙ¼SõO%¤uéžü°‚É•ŠÈ¬Ão5ìtV³•Ò‚E@`ÜIñô¤°we)»À;è9Ei7c*ñv6S#»ÔÁ‘Ž­ªHômPS]ÿ®;²o [q®)»ï…
+›:Æ,bA”2ðRŸ;€Ø§°[å.RJŠóÛSÄÿeÄûJüò×[zÿãï·/ÿ¾å÷?ßHÁ¤RÙT"^W„Áã—Cà$³¥rùòO As†èpaÍ͉­KÝxÉ}p¿ãOì·ù"è7É•“ª‡}?_**xO‡xîY †»­CÎÀ͗†C¤¡¼\¥¢¼É†åè.­Ü“9¢Ù¸
+üÂ#˜*·€¾½e¸ŒPwj'¬•’SjÞüsH ¤E.¸¥÷Éu…†—n„CŽ«L»i[Â…¿÷~*âP 2óh÷Ãì3£ëlír]z¬¤`hÄÎ:*¨„À5Ùæ‹ÇúÅ£‹*éðC‘–›Ÿ'uG²füàëÔæ˜È^ 7F‚æ¬^øÄÎZ«´  cÊf.éšÊŸ4KçgŸ9)ÇåáÀÖàÊÂøžuèüB“ž_„^`à()–A¸üI R-(s~D Ål®ÎËß17.fÙ<£= x¹ž•XBœP-ØvòC“ r¶«_Zƒ¡%ô¦á“ñÌi‚/ôÁ§Èi3H!«Ó~jŸã—Šá‡‰|¥4ú?ÆË$I®ä¢'è;ðe1kiÉ[ô¶úþ[=)òg¤±%S“ªFEü
+n†S—p—Ï'3\ÞézEtض¥””^q”‡¥§^‚lÔ>ò+œUÒžÛôåVóˆ?¯Mþ—E$Lv”DÄc ·"ðMo0T{8‘Wñ%üç('üšð½ài9g©,û}Ä ÚŠêǶ÷Ÿôpí£äÄ¥šŽ ìKWÄi;5„1Tkkãb*øÜCnõRâÈ`ÈäT3(íÃ9ØN¼ê”‘‰¯ࢫA
+*Ñ!) mZñÁd[Á ÙqÞ
+6W6;6}a°‡è¹8©äN¾ñ˜Ä*gYùœ±®à
+Ò^)CPz%?пb#„/–ä%}¿éˆJ0‡8z~P=ß¾é‘á‘ír4õxˇ± J8F±Î׬%»N›•Ô!ý¡ëë”HµY Ù ×£v’‚&
+˜Ž‹Á'œì¬“ &RˆRféí:ÔÅ!%nzVH± èL£±3Æ:즒ªöªûæ=Š¾?1L¹4-Iögn
+S¹–4‹E¨ÇGÇMïE­&Lc(ËŽ‘ŽMðÞúñ[,`¨³|›?{7¬CQ’ óýVð ëæ¸Ë‚ªX„ÕežpÆË•}NOM}8[&>‚ƒÍ\]Jx+l8»™¯Ç ‡@•‹f9ñ1T™ÖµEk«•áýؾ,ƒ“¸ÿh hšš=zÊ&m2‰ŸÃ<‰ºè`Ê)zS Gô§¬v-À³HKÅ;Àf4eIfíq
+5_Š¾½È¶0¹ÞúÅAòÙ_¥|‰ÙÃ<—zì!»Ï^BÌ^²•Ö4 ~M“§Ã½`ëº~/Þ­hĶ2ŸíKg;–² ØÅ߆ùf¯aÙ
+x5Vß aS6šUTéÂ’[[a·±ñ˜k ‡‹‹Ïy/úMZ¿ÿþþ|ÙS4QTPQñeÙÿ±¢ŒÄrñ£ž¯Œð?ÆËIÎä†Â'˜;У#÷Å”OwNÀ×4u}@–Ȫ,5C£è&:3àá-é´|È£ÝÃÕd: ­õGY»Lô˜3wšeWœæ°RӜ֪æ#-
+¸XÝtóáÖEX¯`jowRU Áb7H²÷w›¶ø‚ØA)77l°“Ög¼f|\9$’Õœæ c½‚1ð@qÕ@|˜ÈI‚…ôrœÒ>[©çoéïf)…Ÿ²¢Ô¼Ô¨‚U-4Y‚<0PPÒdšÙ*¯ €w62všŒ)‰vU™g5tL¤±ÓT/êDº‰üÀÆÑ%üN &ƒ©ùƒ“V¾‰$˜óÏ¥‰½™”ocך*ÚZ,
+OÞô;{É‹uf7gìÄÌ ÌEx‰ƒx¸ˆPQý¸ Q <pøæ0bÐÎõuÏ›@ al¦&Q#å=•D§ÍõáJm×s¦®¢7ôúæð`ì*öy+!
+ÆZ“ì‹\>ÖÀ+>jK ª‹H`sŸÐÙèHsû¬”Î0÷—’+==Õ|¿×TeK
+¦¥Û[…²Ã>݉2k_aX$tbg²ƒZYË°P™rYØûðù¸åÍ7'‘Ž#k#£úHl…Þ ©tE¿©öÕ+;’6-ç[¸“nL*ôfnáÖ¯bpÑ8º±Û›sŠd˜MDVŽ7‚ 5¼ÙùJ—…ùÎW1¶‰ù «i³SÎoçÓ\à@½Kl‹˜.kßw‹ô¢¬Ë.oJŠ‘
+ä™·¹'AX¬.¸¥¼.EŸoŠpÄ
+wÎQÀµNÎÄ÷q
+šm´N˽×ýt٢ɉz^£äÃôÙm%É6<Áà 6R ÿN’â½~ Gš€øï19‹Ïàžä;çBøÊ2y²˜t¡‰Kzc%"å¥H°ƒ$ÄÌ('<Ç9I<¡Ò\š ó
+x-"Z)| ½À.cÞIbËÐ>ô^Èš2s %P8§¶Ð…¤¸¨5ÄÂY¸ý¦¬Ÿ ¾r¦ÿóWKãcU2/²S.Ùîç­‚Áí}uÙ¿VÍWä‡S4«?•ã¦•ì xòlõ’3pÍD 7ÜÝ õÀNb?E¤¬Àú¦Á“ýÀa>„Šsa!¹µj%x¶gQj»”øUZŒ®}÷7çL@Ü•G*o^ÃþcƒªÐ›ß~œ„ÚNè*åks𠤾‹¥ûÚâ[ÉosÒU·"YR¸¸hÑ¿Ý_CzÀ«€öj¯yý* (;l’3Ê­;À FšâDDûÛ­Ç”l}ÖÊêàuVO%~•8S·•ðA—s
+<+ùfâyV¬/…ÈKâ_°S^‚c8ý䲆‘ LaÖ/B¹Q­‰HœÅ®i¨o )Q‰t¿ÈçëAH
+M¬^ ô±Uì]”?ÌdÐlg‡$–¦,ïOÕ<£Òµv˜ a}Åf‚¾6ìS¥vÛÛõ)ÖÓJ\$?öºµ {ëÂåfç0ÚÚN´7öÅ„S).˜Ò¢[xy(Ï›s&jšOγÛ(ð0I©—ëiËÅ­Ø97¤p¢xÛ×õ)ä¥.òãív Ù4Œ
+i묡á%1çn}`<˜Ä†–ô¼!ÌjÌ•nmÙ癃DJ[¨J\Ô9A˜4Ô‹K# ÏP ™7P/i… X ýT·¦I­.Œ`ƒkeCä®t¯up*¤½«„úi÷9A_Üõù½_±ÐUƒ2gK;ëÔçU,õAøPÃ=;^VÞ”¹OBå
+ƒI»4‡l Âàt¬Xä ߊ¥‚àõ(F ]/C)ù;”!Rº,Ò
+]#ÂÇ"ËDIŒ½K2ˆ¾¤õ­(GtÜx¸çôE±Ž¸ä–.ûü;Y ‚äàI­¹Ø!ÃH6ñ‡Åo|.ÎlúµÔMt±ƒÀo Vý¸2SPXç%=К"cL®ûòÈ®ñks^Û€ˆ Œ ½JÅm&Ó5!8‰P)fé•<îjóRÖ|ó˜…Ñ% Ä€¥öÂë
+:]™²>õ-ß-›
+š#Ü”¡‹¦òLhEGЛi„?1J‹dÒ
+ï„pƒ ²Ì8yDr oŒÍˆ5 ƒÆ·cìvså›™ùGm>5|ÕS€wZ’#«‚P,ïàF®< „ÓfE߀¸çtNe™52uºn“q$üV‘Ö£3¯âj±Õ{}ÎçI²ëʤgJúh0 G‹?Z¶>GæÆI;×ø ¤xN*)¥:‰Ùæ@n'üëײ ž! 8Ò*
+èÍ ù^;ŽeaMÙšv"[r7ŠEŽ¥PÈD¶/©>œ‹&Í@$*\bGšbi$FRŒcT† }ë­^‹@a1Î{È^ ϺJäa[­šÖòÈM¢–¦h_úïáú4œ6°nÒS€wÆã^ŒHSÉi žk<
+Æü>×*Ñ÷DÎJ«®íãyƒöÇ“ožt"ÒÛ‡çLúJ†Ð²I¡€éæq}d5¸L×v(kj+Ëo~µäØNVjR&Úå\ÛÉKùVDg5rýâ|ºã;g sŽ6¶s´òt“‡ëœ´:\ǃ®ó-‡?]DúYôØ.òð]Çü¸%Ã]*²¢²¸®Cym„<mŽzã:”„è*ožéê؋뤒—¨aľ½Ä/ÈʴЮÔvã:™~°”¨Iž5 ‚bt„Pëcu]çd³ã:È3¦)aoü‘½4ýäJ~ ­ª5ðoé· >SJ¼ >Îס
+I\åc Sp´¾ô\ ¬ê+#Ù^@‚þ
+é|ƒjW}' &CDÒ MP’ÅÙ¹~m/Íã¶ó2í/ ç (ì3G+Wlª4¯±¶Äk'/Aý›4G¥•’~Ö˜p§¨Ë/­Àw
+T ¹èW¼€nb+S&#ÉÊÜô=Ð' <,oÞ·¡àx‰ö¡¹ ˆº”Ÿ¯VãÈ”
+߯+…¼™µŒŸ¹Á®rP¡­øþ:‡g#9ÝLÍ]_€°Ð%áh‡Ñb ß“V _¦¯ ÜîÅ¥“q˜œ ÆŽ9xgß÷á.ÌH@ô ¡û¢ÙÀZYˆ¡×áK¨W4Güå=òo»Î úb°ÏŸ¸ðgJ•³3!Rlg¯üsb2PÚÈâö¶ <†Êò¾`!t,‘Q)oAx-²­¯DrÔ$•å­sYëižAòJŒ
+ÞWò:¯&p‘ìÃå}ؽO¤Ý.²òaeõ9Çâ@ô%Î¥e“}É ÂˆÖÒ­+<aÄ:€n~„ð X©9Ñò×?èëÊð¼Á°›ôNâÃ~í[Aé¡‹äYãGRYñS±¬êö¼<w“0抖P°íåF y3QÃÔ›]aE_Æ:†Áj9³ÚÆâù„Ú cc×"F]šqX‰zE”QPõ›s^þz™WÖ8/:¹wTædðQ_òw›~ÿdZÞ¯$<Ò£ Nh,“ÚEñÏ 5à⊬xÀ5çJ”Dšöa’²¼.=™ 20c¤g ÕC»yÕ¯Ñ5ÄÃÌ‚àI¢%Ÿ¬@H/o”…ééÉõ¯í‡@0^Ó¹ÎÙ=¦(áèì[!^—áõ´^›$I_ÐÊÄ{TeãúdÀ¹å¢>HÖäi&-~Æ+ŠƒsñΩ¼Ûj╸‘[b•ìOÁó:4²Éð†qöX&pB^Úþô1“A%Óƒ¾?”‡vUîRt·:t:°¼R<Q̉ö»À’$´‰ÿì^Öµ E•á[f»aíE¬jõ·šS&­N” #fËlÙ=fˆ¸c¦¿ÃÛæÄPÈËŒË4mW홨0#½û½†A6h${²Õ‡¨‡âvEª}ª€Hãüu'FjŒéRŸU±7o¤Pdm€´&ÙRóÝhjˆÙÀÚ%+/eH–ª„GÒâÕ÷*ë€â.µWì×&1<øE‚-¼Šÿô%8¾ß|î ¢ ö0ZÂ<o@ˆ%Ë!ƒ¢¶7e}™²»Y;Sòñ±ô AˆÙ*•Ëì †ú‹T›@„7Y|ždèÔ¯dÄ–ÇoÅVAôKk{ }$ãÎ]éwŒY? phwr ûSìHxEëHX¾9‡D2¸ ýk$)—55¶¾y}àQ 2|ñ[NÌÂtªÝ†w!"Å ¸¦Ïý,•ÛŠ¦ƒÇtQ?¡Grv3¥Ð Ý]N9¼Q.#<¦4ÁeØmI]4[ëÂh ƒÊ÷/åe’ÝFÑð:æaM/} muÿµ$P|fUÒ¢{×t¨
+¬KÙXÖÕp×"#"$c Ù8Ïjãm È¡{p§q<ê,¢b ,ÐÒhàd7–§GA|=ŠšµhÇêc¿Ûª¡L¨~mœ„&Y?©ð­‘,8úÙÑc#S’‘ö†:«”¦à¢°ÆŒ£8ç(yøßÙ¼[ÒµB0áޥ幹F‡ÓfŠ³¤ËFñÞÆ4§Š7éëܘºÖX&¹ÛhÓ¥¬^­èx7¬•£kˆL_±Àê~‡w@›‘'‚ŠÑ«œŒ‰ªŸ%u
+QùéÀk\®ŽPìî7OtÙJuÂB~iבÇÛ"ŽËôCfðû…ˆe/€3 ±Y,BØ%=À¯iîå"PNjø±$vLÒè‚õtlŸ“1$çS¶Ê;ö)òNÇ’÷ù"˜a ñ¦¸Å$d¶& ‹³#ù²²Ð½»Ú×v¿ƒ&)ØG…m@
+æ""Ù ³“ŒG—‘T‚q0r“Gˆ®äLˆŽÈ)v‘/#š,×P_ìL®èÒ€Þqoˆ®„ø³sÈ`âǯ!ùÔ¶2»Õ£·ú`2m’)¢ƒéƒ Í+l$*bŒ¼/ýZµRм%ñLÅ£®CIì$Dü²“€±¨73©vÏdQdiŸi XÄ;C:ÚC¨B=1öéMIèìÀ‹zóöÓûí*É”+4¡‡­H#ÉhŒÌ¨ºxâ$ú6­U´Û)ÂK"ÄkŽ-ÁÀˆ}4JÒŠXN¹…1Èû˜ð4ê—%ŠŽgº¬^—¦’Ê4Ô!1ÛW Ò<3hæR
+H‰”—Ard¹ DO ;è® AÖ=˾…"¼ÒÜë’¿mÕgYšU·ª²HH$ÝÆcD©£ÕZ{×÷µ.%F“ÒjØûç[?‚Ê0iÑ­Õ÷„xw-ÃL,!õáÞ9Bª¹Æ„„Y-üjŒ¡ b1j¢!Öß?¸Ê%*?Ñ<)Hk35N*!ï mEj©šNH3 é¥ÞbBºò­ZïÅꂈj+y›ï«L‡òNm®ª=4Lt´¡ów.ÑZUdŸSBK÷ˆ:Ê
+(†:Üð}Óÿåp’½l²_8JRÇ’(NS4‰ŸXßt¿ƒèPGŽRqfLômcZ8×î$BZ¢JjÈ
+›ŠçÛé8ÓÉ>v$9´+îQM0újxÔ“
+Yô•iE
+QfC=D¤óvO&öY/x=KÐý
+ºÌÃÅc)Ô@Œ óiª+²º@É”tı½ñ]”“¼ÆjCž
+¨ÁÀ.y à°Æ”ÌU@†mÝyd„nhÓ% 1=ÇzË*DcšNo…™ù˜7õN/ðQ‘¸”¼f=è—ªëz•ZY¾f8n©Þ˜bâM‘yθ¶t…i¥Ÿi6Gy2QHwAŸ ß¯@Œž©©¦“­%íLäÈ…E;f†ˆ $8MÏ–œX9*y»ís°Š¼¡¢Û^'„ÿS#¼‰ÿIÏÿÚ¤y%…˜X\»LdšGMÉ%¬yNvÖ‡zÍú¾æ¿þètIªãTÒ¦ÊIõ=W)XÍN’–±$z_’F†®^‚ŨK!—¢ñ¬ìqø=»UqÈؘâ$üÖûHú)Åð$¡€heó=|s8ŒÁ¬-îGH{0ß‹e‹0«’GP¥°ìûé6˜3âB²>Û¯²vÆÑ ‹Ð„5a}½üIWc<QúY³
+Uè½9*Ù©ð7E„c-k^S®^ÃN…­EqìR篂Ȉ*Ò+,\ý… ²NtrÁQ½0”‡³–ÌìaÃâ2b\­…g³|3~AHCZZXº›Yi¬5HÞ\˜›2ü3 Y ={M·7IqÀÐ $¦g×®‚3S ykÙ.“}“æ)ôBó%–ˆÉè…EÛ¾Î1”;efs‚ÙÖÓ ÒC¾ý!¢KçÏX¤ ŸÝj#˜vv™´xžÉŽKïÉ ·Šª`WÑ«\Ú‹s 'J#(LÞѤÐÌš-ã™ô"%ô“¡]Wåì´3Ü Ì˜Á)ÌÙ1Ô“»z¾¯bqÔ'íÙ‘€OnÓ‚•ºIÕ1H™N™êÎIÈ+vŒ9ÜöW„®O±ô±¤p¢n9¼–î[MÉŹ>P¦h.Þëâß”ñõ,éx±S@ J¥š4d¯»AO×=ƒ>Óï:F*“ ?vŠ*Cg3âïÍùP_„~Ý}äáº'ÐçObZ¡7V„Moò"ò¦¦áQÂŒ·éÀ$Á°áŒöÖÿèöºÃmßc !
+F!¢ôèçÆà&è P}õåj>«9w[Ž‚Úc}–!/¾Ã­ð)ÿN6†õR<ûÑĺ¨l†°Ä Ód[Eæ|ƒh:c¤ ÊsècÃ6ánò›“½Ñ¸´ªÕ&ÄZUpÓ¼<#>&?Ø[™Rr(ÉZÑBwã6$[0çuš
+þE4…œB8bG–QêÍoØA7óÑÒ˜0€ô„qÁ<„NX®™å;èÐY0kçù”ä€nÍ~ºî 'ýùüF-%c£•Áädý…”esAâqü/Dø:ÍÛu§ùñmL3ôî|ntFf^¨0 ôPƒáþbôÝA‡Ðï×Bÿ>¦ºÑºxR![—7B…1€¸!¸>#7<.æ#; Å¡0·!pHeЪ’yÍõ¯6‚Ø?Rˆ³ËNNƒvâ#– úƒú5doç°“àFæ.³ßUÒ¶æÈ¥O;Opšx$áè¡õ(¸Ÿ”¯(¸Ì›z’[€»ŽµŽòIi9X$)ö„ ©ùµiC°Q2!
+ÅX)*{T,ÇŒîåð BŒã¯·èÞ“ùÎYcuê¯fë”#0EV±Ï³òwJ†Å÷åd3‡XÔÂÇ/‹nZƒÇ¢ÿ¶ 0¿áë©s“9}Y‹8ªùñËít £—0bÛÓ™ˆ8:ÂÉ“‚2}tA¬·•Å×"ŵÇÏÞA‡ô öÊpŒ4dÖ
+y
+ÈËØwÕþÂÇA·œ®û¨¤ÝªpªÅêGKIþE•Ñ„°Ð,5cšÔŠ‘‰ ¡Iæøâu­‡l­[‹é–Žv ‹ZdÃ|B
+‚d1ˆ}Ž&•¸[•™žKoá*—‹ûê­@¤µÑlŒV_x´l)ŒÃ@ËühõzºJÉu2—È òÅ£AÚ‚/czœƒG[ÊP e'Ú4`ÏFåóípY‚x§3(˜M6ãq‘4Á ª"R2u¹ZFLÈ4~c”êã
+‡$@î«#¤HŽ—B¹Y‡D‚ü2‹†l[1¨ÎÀ².áC¾Äû·_Èá ÷RYI[èÅÍ8å‚.}ám÷Óöß6ôêû<–i"3µõéž.èzªÌ;“ü#èéþè¹Rîv?
+##á”qv¯ïVš¨¯Vñû]CNGûgŸNßóYTg [Ñ/ »æ9n9Š’zñ_“ )ƒ¼ŠPµ»ux=ÎÚÈ1y¯[’ÝÈ°#û}/ w" aÈÅoûëV—¶WµpfœÎÈäõôº+ CĘžý¶Wqmf5BݸY†„Ae&< ÃëzòÜõÈa ×âOŠò±t# .èÒÞv?
+š™[É–@¸ïštyÞ¶FÀÞHw‘ÁP²ð„Õ¸¿´ ’QAeq¦ÖMkò kpA‚õ¨Tá3s±š888 C+ßZ#¼ÊoP{_ÎçÄõ‰ÇÕh§öš‰Å‘
+{Ïõû'£æ
+Ö\ämì€#©×å>n0 v’@êšÛ:U–Ì””Áv—ˆ^`„ê6Íi‰ñ#–m˜•é<™l;5bTi#°T¶'#«Å1H³D©ý,˜™eÐ|['LÞgMc¡ß<üˆQŒ¢(lÞýu`3}Åy·£‰¨¡8ƒXœdH;hP=Ó†ÔY×"3ÃÜŠÑ_#>ŽI“…ºÉ&êHN<¸ˆALQW”Cì$­«¯#GPÎ_±²0E’¸í©rÊ xܸÚøŠyzù÷¬…$µì{/b´ hh3­Ìƒ´[—£·}ó†™SŽù€`ÕԗÊL%4dòdÞ2¸uT…ÆØLšp§¬Ûü˜ÈøŠš‹+–O“eò æ túëÀ.Ù?¾§^¶Ó´:ùgäP7K™‡Híq„[‘ð$Š˜K þu`iƒJ /*èÔ¼×ao XÇhÖ‚^¯.©ÖÏm….Gx+wM¶ÓßÛóá’‰Tã$ë©ïå?n@˜VSäQ5¤§©¾6²”טH2]Ñ¥Î!ÊŒ ˜„;98k¢ŠsUHÇÈC¬8ý©Ð!òEÁ2ÍÚªˆ€ ÷•Æ‚zø‹¤¦\ˆ
+ oÁmô
+…¾Äâ1žKAxB+5 Åe¼¦>9uNšDë
+û°Žz]ª—üSÐ5ì   _ЗsÞ€8ÒÄj™×˜–Ž<6Ý…iî4Ý]Ó¡ˆ¬"9*f^³¸>ÆÕtô¨½jΑOoQ£ª£Ø¯´ÓP n?7„ÌK(h>c"Q!)>oŠAUf²þÐTc2–•/‰¥i¼x|ÇszEo "ÍzÁÕ›òɤ)l§¿÷ÖÓih‡„‰,bgâ§ð°«Ûtš¾B¥qC„Ä ÒW`â8ã L ”]Ónîq!dÝx§ Òl©jÆ Ö°}9u
+[ø0uŸ£ôQ®›"ÑA;lšNDâ—y—Bɬñ ’
+N×PÉV¢ï(óðuÀÊ’ØÊ¡Þ˜‘ÁT·t>Þ¨2E´Õ2'} ¢¡Åë< 2«Ä_ãí\¨âHÙBrf<•§òŠR-9á4ÎI@'=_
+B4üŠ; z@SèÔŒâB°ÛV Y‹æNW’ 4t °ÖQ~â{“1“f<Ô
+v«Žµ£Ñ«6H–+•€å½Äã¿+„Gˆý©Mü!'&CÏV¨!û3òå^·¸¡±¢þ^½¼,ÞÀGâª~—»ÅãÒ»ö¹úë` D-بˆ‘‚–Ç®¢&¡¹ µé¾b‰Q.üï³­H¯¸'«šÉPeÎO ©¤»«ÆÀ(TXfºƒ ^¦ËþJ‘ˆª˜g«TÄ”â„Qü¸T2“+ˆNÃáÎìû<¸Ô@$Rꦵ:¯ÄŒ7.+z"
+ÚJC‡cŠSaDC0|û僾Øëû÷ü'ž"ÂQN¼éÙÓ™5"Œ\!þSnãêA‚‰‰Ê¨G
+·'yl²2ï*¤Ð¸ª‘=GV:Rû-rÈ«ò CHcÊÚ¢Š’RÝëd%´ªÎæì‚xV>äI¨ÁŸÂOŒÅ@‰8ÓªcVõé¯BOÅè€þ½E½ Bâý¾A#î’ðf‡ÎÜ‹\GÇšˆ83£x~TLóMWhqAxSØ¢,ù¨Ïgºþ^[UfV¼-µÇت&–§MkZ…ó£Oc¸oõí›ÿIr@É‘]É™qͦUFž’ÜÔ£7£ã Ú”ÇcÀ£>RÒº¤SfI\ Lë‚ “ ƒ[­ÛsW”U€DÑɺB¨ÛÐôÔNd Hdï
+ý+Æ^L½ifä ùæí—‹ ,æxâî÷ äBBKðZé„JY[®¼/ú˜6•ƒb ŸÓ8¢úEÄvK<“‘‡7ƒÌˆLÖÝ|Uz€ïÎ/ºë½ùE¿aÉšªÃ‚z·þÄƸ~Èv+âX"׊€Œ‚E²–éüÃ@"\Fi›C× £iˆóœ##2Ü=òÃU@M¯b‘N\­ÑèVòç†D=
+´Áã6M!àê'[¾¯:D¯ ¸ñåêók‘BhÎBX›ˆKPM$ͬ#ê“:K±ý© Dk-–´3:H¢žåL~½©!þc¼Ìq#9‚(zÞ¶ "÷Å(“®N0Ç1u½ŸI «³Db AͨÜâÇ_øïpd
+4Ÿ'"Ùã‹h ß0XªmêWõ3‰IPŽ<ßç*J8Ô^a+°êÌ…¹âJ ž]«‹„àƒÑÏü÷-Šq™(|N@¼%?¦6cë0홿ßÇ"”Ô
+Ÿ7E¤t½¥¥K
+†üR>8xcÒšýwï9Õ´yT›qÈËÊpÎM¨õØ·Û
+ÑbZ!²ùåf®ëº:ñ²~š€¡Æò†ã)ïŽòOü·ß
+™âfÇAŠ§žbåñužÉ@ƒw¢Pjk.F?àC.?Â-²fé¦K •í¯®Ýe0’ÅN (=&ç¹x}„•&T‚P)_ Ç&¨ãÔŒ½#¦KÑÞœs¢¼JƒƒçXï·‡U¨ò¸…UÀ ±*P\±5Yg8J*°âø©Ý*ñ1¥1zƒI„0€ðÅ…vQB
+i ¸16³ŠÌЧj³ ‹AùIqo?ÖœYN8È=yp
+£á-¸`Ü]?D¥(…¼­0™ñ
+v¨m“§R_èÑqÎÜ&ñ“†ó9>
+²X¬fœxXAr`l3ÌŠâ–z(úô"Þ»Ná7J¨¡1ÆÒn¥KæäAÛΠu¹0´ÛJäâlùÁc*¨’Y ËuûÚÏS!ÊiÃÇÆ$äÊÓ¦®1] ö(¾ 
+ “ÕÞݼ”ØÐñ=LɧoÖÁþàý&Ìæëˆ
+}ù’nDÂÜ…°û%-wHN‘]‰_×–!C±rn ŸŒ(+L²ëÏ·Võ}9Zhc,i :Xèß«ˆìÓ¤^<ŽK«®Íä¢òÁ41Ó=Ì „úô•°AQ÷uY%Ì)4F‘Ž~A¼ 4Á³¶ßÁÔa°Éñ—a†ä:{G§|£ŠoŠœ…™)VÔÅïa7ˆxNhGˆ/¬?]BãÇ: γëîÒ”]äó¦()
+ˆ‘ÄÖISc]§Áà‘c6¯©© iB©Þ/ÉSá¡à—b­ÂŠQ+ .V‚ÐQ€ÂÚNx(ô-Åk‘ÑÞÙJ^—ïè3TE7E"p
+KOE®YEE¯€zo~õ®45 8ÐÕ‹$£+Ù‚QࢋW†³”UÁ÷Q)–GÜjeºr^¯£[ªT'Ê,Úó
+•ôÇ_×2xq€Å¢e å©Mÿßk¡"8*ÛOÉ{rüп$Ï]Ÿ ™Ÿ@/‡MõPd ˜uŽy@¼Jx ‡)
+ÓKPØÐI ŒnY·Çª_º1KIÎì
+èÀg¥v¦Õ>} 6ŠØ+˃’†(xœÿX`
+Û¤™_Œ`3Å–˜ñÿ*a\>Jf]î,û -ƒ{nˆ½Å ªT¹õˆøÕјFûX%jr?Ó?TÍ„ó˜ýHÁï§è2 B\„ÿÞÈÛµzÐÀ(P´¥·wRÿ`»åpØbã×,‡á‰XEJ/ƒ .Ü
+Ô‚}/¨HÌ;tOA×;)à‘ RÐÜ~¨à[¸-ãߎÒÙÉPN"š€¨PCë)œÃ~Hª5£(Å’³«ËÖR-IÄ9úVý$ôù§;ý,RÉ´H*Qß=z‘Ó Ëpaî“~áà¿FÕJ EA¼¬Ù…Š"†'ñØaT½¼:Wƻऽµ½v½âV²2q$²º÷ˆ¥¥gjRÅÒpY±+¸.Û$ãÛIjr(..Ç(#‚Âò+Õ2ꄦÇ)ZÕÕ×J6*”–•o}òä µ·ï`‹C‰
+ ,q}ˆ†Œ‚ŸH‘\´3â…%{‘É›ì¢}fÈC–R1é2ÿòŸ•2SA«ã6Cç;L9Ï嬋—IGÿ¡ðW fö#és›`¸*FÛQû@NϺ-’Ê ØD|z¼Ò=êõEc1yóò¨J8 #jýž£~FI5‹4A%`YÌwÄjDçE‘í%÷R­S¡ù¨îCuÈuÏ£¿3PDïÿ
+ ^Â:2!x¼„ŠUÎÈzesè,ñ׸ežÊ¢›FJkÈøvÒQ¯†€ÄŠP/ïh‡0wɪÑ.®tÀ-ÉWÍÙ>;†²„´ïT:0÷°Ã ³®<NiŒÀ0×¥:¥))£>Hò„TYÒ~¶¼
+P\ò—AS4Ù©s•oPæLòEÊÖXx  ŠÇS½¶HxE˜*‰Ä-³R-Ìa2pÄ…¼“ D…Ý“€:¢A |f"yzß ‡¦ð"¥ê‘÷Ó³ö*æ ð^/#³5‚è¹}'b EA§$H‰zLOZU†§H-.ͬ†â¶´ÙÄ~<ùεç·Ûܹã¼êNÁ[uî<¾ÕØ›‡‡^ý÷ÊÐh¾Âž/>÷Ô)@ðzÿÇEm"&fP‹Ý«”ÎË¢òÉ.GÍA˜êõºŽjhòñ°Óí@h<Y¤œ*…†¦"­l â"-SÙ ÑIM6;ø>ÈÔ½õw±ƒdÚ½RáS£{_ÎQRH;ª‹%‘k¶P"ݾ÷„HðCˆY
+혆Spyþ¥Ë»t¸>:™Z¥k¼'kgAJOê'^¢÷È86D=Q8b©Ø]Êè?q( òù惺þå‚h.q«o\tÚaH:>Ë
+V¶T’n¹3©säõpâ±*¥kï…H©‡nklw}Ii¡“WHˆ-KÄCÂb¨ÍS-þëíp®T^WA!`ùaáYê|Gk_Tp¬ÇÕ „b°Pø”=³\×RðþJ,¨ y¸ô=W\•£ȼ40È“¡"kö÷5*“»ò»YwËD;r˜xq בIzB Qî}Ô/s¹²\úÀP[L zËÙãŘRQ'oÎgû¢ºož÷Ó^ÁdÛ(ιxê@º*[s¢"*#~®ÂNp*jÀLªXZ5©sô¤PÔw¿&“‰÷!\uU Úÿò²
+„„”$-Pè8»4„¸Òȸ¡mÆŠú=ÊQ9OZÃévT'Cvf[Ëf==oEÂËÙ“Qˆh‘ÃÇ1\“&¾ÊÜ7‚ôA>.MΨÖOôŸ¾\rCä„J£UcòýÊ÷@Rˆ#+;Og¶ûÊ<¹õ±«|-!á²…¢ÐUį—|êôó–rE‹I¬¼"ú_™(»yhsß$c>¨ÑÿŒ—I’$·DO ;Ô ÊÎ\·–} m«î¿Õs©Î¤*;Éúg£ƒ$àðïXDQ$\—9N¹Î‚Àι-ß.¨gA8VÛÁ%A
+=O¿â‰DÞá¼gÞëÇÑI¤Gódö>ú»Xƒ1¶Ãk¼Â•üú™•`Z=r_ãgJ‡µ.¸ÃѤ%Á±};‹š,ý^'±e@G‘ìx9ŠC0/Óép0ŒEî­uëu³-²°œW7aepSµœ×½¨i“bÃÁ›‹î1Æ[E,$%Š‡Õ6,®EI-D–ß †bC„µ„eÐnRW›„°R¡åÝFíØ׋VÆÕ`eÑel®V°ç9F±”œKÉ:J7fªCYÁý$fŒ…¦QÖ*Éâ¦N?S1 ŒÔchŽ¸ÁãØ8vë@qÀÿÊÔš5‡yAÆ]%(/ò@3 ÈÝ&ŒÐÕl.i1~¢Ò-6ù (u Ûec™£ÍAX],zo°N#ºµ7Ãñ>f c¶9Ož5‰¨•&Ðy$ø#™þšy—w˜°=ýpÞS`Û¤ur./!ƒÁ$Þ#€üÙbÈD¯¨‘9céLZ>ö‰o6Q.¬Ug‰ì”r
+]œ’æQHwáp(ºßÑ
+E@œêƒãø‡‚ªÔ1Kô*þ>)ìMÚ’CœÃ¸‰;v
+jr¹‹ÈwÜ@d–_]ï“ñ&E¯€I˜
+¾„‡‘söšÛ™zߣU¦ÁðX‹Ñò«$ÅP¹ªÀÊW—âA«UÅs#
+LF“D>><„Q"¹š1ÆcŸô O´¢TÈ F)2—É"É
+ÆRÅw‹ÞÔqD6XÓ$}¯‹LR8øRÞEÔËŽ±ßaœ5DóñëÀvóSĺ®®-€Nn¾pfq)YSO<&Ž´ñâ;¡¨="ë~»$ ¥Nþ`)]#V¢¶s›âÚ Y#5õX7ïÊý¢µŒi,,_áž>UÁêòíÔÜ6ŒOˆà ÛGý°[ÿéT ñPtŠ¯tç^„}¯<(≤•^¸(;–Û‰¨Ÿ•rd™zÂB—ÑÎÛšÄ+δµ.NNIâÕTK©Ã•(Ÿx#Ÿl@l 2dYÊ,ÑíáÐóŒN‰Ž"ÇA¤À‰?¦ì~GÍ»h NgßS2“OG-gI60/6‚]Wûh4çjúmIWô4Ž/·
+†DéƒѺî àÖØ£MäÜ>°”½w›%†P•Z¹Bi«fáEÐaë<8‘Ì*0ß²³˜ö4g›l²ÛQ\[맊‡AZà͸šŒ_à ËgNÉš'ê‰ÛÃñ¿ß¹Žüv›;tœGÝxkÎÆ·{ëð4ªÞÙ™ÿTNBÃðx¹¾P¹{/‘ÇäÖ²öËb€ÇŽÞ*'’¤ ¸õ:™tŸÆדÃAÏj|\½o2UÜEH ÆŽl¯¯dXÓ˜nÇþ>éÓ}ôw•‹’#òŒ6Ê fî “ÓüÐÎM¡¡4aíVEŒõÂë¶?
+Œò°lLÈPŠnOëå ¹!„TE‰»H®—ós‘] hœ«’Q6GóçNÕ\uó¸ò¦’@¢fº¬Öýï
+Á=Ê"ë(x¼Ìǽ…Ç "Љ ¦ùS+¬vÛëÁú4¼ÊN ¿âO€þúË)q€Þõ¯¸>+¹¾]tß½ûioÔ\ÉÀ]«kÑ"–òÉÀåüƒ §sÞ÷*’oÒ×þe¼L’¹• zÝ¡O@×ú7émõý·z ù›‰H«’Éd"ˉ)"|@¶I׆õÅ1H±)¬z’W$å™ðå¨1ˆ‘ô,k®¾¤—ö’Â<Àœ‹zï«4H•Q'ò0|ÙI¥ª§ Ï4BÙØz=&étð³ò'èL’lƯhàð7PÔÃ7Ø)¢ž«d–A(ʪóf Ž Ol;Pò¶•7O !3#¹ÄònW¬‹1„\,çý„AÖ¼×p™|ì'œ¨|q AÉgÌ,›¤Áp#¤Áu ¿gW`C`™Ì»çö°NF3 ꊬKóY'ÐZÐT¦KG»¦+ÉûtU˜µöŒ b]âå¿à^l+PÆ\%døOƒÓÛ¾A—µêz<½
+D–è&t.ƒ³o0’¼y\ Η†©YÃø¨#ƒbÕh'¬
+Y±!….—ÿ
+Qõ-7íW’lé§Í·:´_ï ¥GÊjŽhkâè îàH¾ôó ¢AÛ¢bsV‘ÐÃò¨8“rù§›ôóRÁG©=Iÿ r*†¯®|• «›ŸÊz‚é÷@7é¸è݉BÉÕ~LüÔH<pOÑ×~Ñã`fØÓxÉíßÚïTâ®Ù¢5^“U9oª¾ö«ä³3îšÐ‡uxà‘˜Ü˜=éWgáäx-˜ì:íMúÁ„ZåèÎàj?]Lfaô±°–/ãô¡ýjtŠ—1å3WûOÌYo08qH…ôü :Çøûù\c\™vî’;Õ²2L–G$lŒÞmŽ1~.6EþrEn˜5*/Þè+µ: gJ“IK|¸^ 9Àôq´V@…æÔâ·{y¶
+Áâw …¤‡r>,”ñé(1‰³¢B {…i%¬›Å¿ y€AwÃCDc;U²\D·Òzp|@#‚‰íËñ<êGªàVxhsnÊgo³¯ŸTWMýhxIî›,{™;¦A·3=•¥ãìƒc/̆Ó7 R0¸%ÈùŒ½_'L5S+a°<ë‰ãBp>8¥jÞâœÉÀhq~ÅMÄ wÔ®% Ò‚q§˜©Ñîʘeta£µd;]¢­âk
+}ã¢õJi·uâ«[4u £ìÓ0}&Qè¼æ‚T(™@6¶^¯Ô?ÁÃkþ=âò¼^]bx‚ üŽs¨è}=7Sƒ%qÏî U~ ŠÆôm>Bç¸|NTÚWÇ6$Ö¬<ÀÅŸÖ¨ÆçÏs„ `:‡ÝQ™:ëVŽ¸^ãAç%Ø&9UÐ*ݘ&)<­s¯ùqš³wœ[-x¼ÎÑÆÇ;ÃðQ©ß?VÐhRFÏ@0ÊÊÎr\­j¨|{ R°Hò™TwW•­ðÀxÊDÀDŠÉ=›Œ¼c¸ö%>64;w×oÉE˜”_„|‰Ç‡á:Ë~.5íQåãðV¡•‡Òƒ1O¥^G‘Zçf[¤)ÏLšª|µW…†Ý Ú¹Ïɹ¶Ú“Ê:]T<
+O
+Lû "±ŠàílÛ’ñ˜’´L„DRÂ%Ctv5<v1JYyp+EUx…b[¯M·tå=­äÈ ¥‡”!#^ZwE LVß‚€öVÔ(6­^$
+öEBïnË‹c'[mÝïyÍ(K|ÙD?P7c€åD¼™ýäDm‡¦rNÚR•@&#€”uð›êì9ÄòËËE©™£:zEì2¬ŸGòäÂ)Æ©:ª)ÒLç’º» Á@q%½U‡›Ò<¥N¢Áh5þܽ¸/Uãgî¹fCÊ}]®z¦_òßX½|owt:DãYs!LK$h¬†÷VßÌ–Æ0@æ…ô”[Þ¼™5\è G/sµ<ìBÊ…¯v½%ESÃÈ©‡`ÊJ0<·PŒyªòŠømȲWöÿZGôC‡O “ ¶Š‘%GÖ_•Lñ£.Œ×b7:kBÎ ÄÕú^¶ED¸[ÊkÞã´”ºv½ ªHÏAÚÄÅÔç:˜"šf±öÁêB¸AjA¨¨¼më[nµK2ˆø#kþ:LoÁ7hä10b¥8­· é“Ã0ë(†jK*¼3 ‘?AeÍ ´†ï³²Ö]Š®ZM_¤—|à®”zVB7Kü‹M² °#Ohø
+»6#rq3Œ<!9@djùheׄ<²½«8?êiç.©i!8è~®ÿQ@JSÚ†pÏ.°Öò‚4>b!e×bñx ¿¤ù>qu3cÑß’ÙÆ,àúý>Õ¸ D·>µ<Í)AуšÐ×O&l bx¥JŽár<fq”þÏÁÆ-Ñ¥¶ DϤ€äb%f‹ÀµŒ;Rþ ©¼<@ÿ1>iP{Œ-£Ã:
+¨bñL¢š=¬Ã_YEfû²Jü&Ñ}*ܘÊr by§N_æ€NÑH’³
+±üsÖL›eš±I€WÆðA·ÝÜÂ×GøG|1Þý·[Ð#"WX,ňk³¿u^µ½©Ê]ŽÚu T]>RšžR÷Ü•¼‘`Z¿‰È /'yöWXæ·Èû–±wú¦ ßa%i<M®8CÁ^Hýã‚Œ&ÂZS¶ª‰ÁÞŸ÷î[3ö*"®êp&ò‚`Gµ¦ÀÃ/ Ê)v€ðmÌt £có’
+¸âgÙx5Óž±4LçÐV¨<~êÂŒÔá@´UUPäŽ KñÎ*Ÿë4$MÝ¥Y½&žhiòexô´ ¼pEع…íèÈ+›É1´5èC¿\ê—Šb2bs3ÜF Ñ0eW•Fµ€+sÍ«÷ÉΤ öœRpn„•D"÷Õ=wÇvâ²£Q3£Ïup2z`ž$^¹GŽ}b|ÒzeÄŸ ZâE>ˆUO|fætô•EnËœ%?s¶Žs©£·9›øxao>*õû'óF)‹$¹Æàþ¹øÁÈÅSäÄà?ÆË$KŽ[‡¢+ðjyØ7ãòP»ð´´ÿ©ïÉ<ʤª<øþNAAÀëªÐU¨£œöé$UŽB‰‡`½^‡õbq¡˜´Ûˆ
+’tîÀƒi+vÉ n`"j!àŠ±ú“æãR~Ô"o•*´äÐa dнy&DÕ¼3†ã)êßAƒ¶Â‹¶ÝûQQ–ÙŸ´d±6Õ«aÙ'¶ËÕKJZÐ'4´'"§‰C׬É]‚Á%¨5à´è#GúŸ…Ä¢ð÷˜ÛÊ#a‚AŠÁX—³¡ê)sÖRÈ1JŒÃ:‰° ŠQŽv`ñR²Nšè:ê4÷;üPåéðF3g@$RÊáÿÏoº/$®Ü¼¢ûeE`‹1;ùyc‡Í!9‚Ò´š
+~çÊ…Ð)t@ÂV‚xPÃFÞ%Ên˜$ñøÒÙDè
+µ!¥µU‚OIP oÛ”@ßeùØ!VüÓN"9$H#’î}­¢$ÿ¢Ø6E5=€?âôi‡ÁM!4•ôæå0š~ ¢›U‚$f8 8•y^Þ)'…>6zPà™,^šw¤ÉL°éqÛjÜ
+ Ð`ÎÍŠ1¹Ìu‹ü›“Ù<VÒ¸ùãœÈ5¥œ#ý`“YÖëØ&;Ÿqò6©¡/0rì››1o³t¢jFðhÛîÁù Ý®­ÃÐì ÓsyâF_ûÉŸ";È0&ä5ÆHÀ¢¨îý„Ô™ó´÷¬ø.e â"åR)1r¸#!Òhñy•ã» A)ndÞ‹À¢/2™q#óZ”#%ÙÈÊ¢ˆå›hÑ‘kÎœ²"èº26…îH b;Ù†'²M˜Ž'ÿ‘\€!ÂZc¤\œ7ÿuŸƒ£xÎOä5~üËÓHJ¹ÀJÝ™)‰J1„…Q
+w(a4ØaÞ¶mã~Tà3KÕHŸ'‰I5‹hco †Å@@±&û+°,¸îÊ{Ý>“Ò”E `/!œ®XZY%Qü‘µuæîë “²™$ŠóHº?uŠ~½)Sˆ)-‹¶)jXSùÜö¥1#ÜÐõt"-¡ÓÍÓÇî_Ñ붪X¯ÓÒ¬gs¢Ì(ˆ(Ù|%ExŽâ÷t¬3]kXŸIžÃ‚pŠãïç­Í{3hùPbå“Ž¯Íh\8(>pW­5°jàf ý¨u%oĶj¦ëƒÖ¹³[­'§§œå˜íõ•&J
+Nt$Jì'xEJ2 *ãð/·è¶ˆ\™@‡;fhg3Øÿ)B
+®cßØKÇXy-û`Ÿ’(•:!ÌÕ«z<1-:i<éÆÀ´Ý;XYí'û
+|‰%RØ}éÒêćBh«$›ÑnxòáxªÏü"TSÜ›¨È`îÆŠ0K”(¶%÷¢,ÇÞ•=¬‡3<âêLÉþLæ™ÉH¾NyQ^<æõU'(Rj²÷ÕMFÂ8+Es§4’µ ²óï†|÷FÃýÉ8€t—ÑR…åeD‚5ò_å e_¸ @¬S= ¯ÓñÊ´N|Ø>ÅŒiŸA-ºìÁë4Ò‹P0’Ý ¤Ådç‘Ÿ‹P£PŠ„;!Ô'h“Å_VD‹á.Z-¦ZÜ•1UbËnãäYC‹ÍßÝvæƀߩ(WLÅC#=d!–ž‚Àf|[ÜòN9EŒ&Ñ}š Ù\Ø„ñĘŽãÎÐ-ØoVÂßÆBÊ–—è”hbiÂTå¢Ûó8ߊ£:MéQ-„1qo°½n£WñÔˆŽí6@©¶Å·÷"Ò%«BF¢r¤MëÒRúq Ævñyxš^ÿ²ãØ:Ì8ôÝJ[t½“|6ÉŠF`ûAaŠ…׶zbȇ…&x±TÑçPˆ;Ië•S™óŒ˜Rx7úÌÌPa5Àe"¼¯°™ý§„Ó]`~uÄlx F‰”†íÅÏ­²ßlá/[Vô­‘‡k¨*óW©YÀ6¯]uj¤„=‡¥l9ÒšúY-–™z–‰ÃsqU`»EúbÈU2¢‚iVR]¾Ú£ó ²ä.¢Ùì%@^Ѻѳl³¯
+š…*$³Vmq¦1;%ë¤
+N‚BVÒ놖.mƒÀr3J@Ñm?(XùB¿9í˜îNËY«¢£æC©Â`›ê–í càBì‰Udì>]4¿Wè ¢¼Ü8éú ;ăjon® V9À½_ÝóÄZLÅ4ô^»a6ÙÀtxb|;HEæ)±ë4š’ „O;v ÁÝÌ /)!qÞ})Y¿¶ïöû.Zã ‡1q_üCå=ÌëRć2g5<àZŠëjEµù“\ZÝ(‚^h?_ÎQßc­|°•'*ñ[—5|~È>݈‡¿½ˆþÄ83LÉ:D&VÚée—À+L’dnvqF`©‘ãôœÊºx¡âd³yNE½îß”hGu<3%‘ÛpOÍ”Te[ˆwjTArL23 ìé™Bé?4ÈÝw^Dö
+
+ ì…Ö£:¹;\/TÜgq©XCG¶)ˆÄ¶šÝÏ°M‰&‘zææ'@Ø0¥°¸ö+͈™d<s_¯jXf0ØS1š’±p³‰V¶5ĹVù²ìù¡‚ZÆ‘»W‘,÷Êu´0ã>èï°2þg¼\’k aº•¬àc`œíäíš# ièz]™%
+4¶%K
+A #…Ë8ÙMSÛ`ß:ìÁPd£KâeüÄ× ”,À¸€öãêh¿îè¯Ôÿ<`S6eØ1:ç ëÚÍ::FX4/Ò©ÕeˆêZ<Ââ<ʤ3©¢
+˜Möŵ₴ŽÔ¢dƒÄ€¨0¬Á|íI“©ÂqÖ€$ÖP•§«- ó*ÈYº<Ûçáõ·Ð¬°èr ¯L/ºöuê„>
+H‰Œ—M’d· „O0wè ¸‚
+ã)|6lcjÁáÒ"Ö2½Ÿ4“ÞƆ¤„Ob}ô QÓ4Z˵Š>´EóÙø¬Ÿl•9s´6uæô×H€=´÷Ï ŠÑºp—¸68uouuÒ$5œï6 ×½]{ë}b*;›NÿzinâÝl=N>Fô9¹zö®×÷>]oº—éüÈ.:æF´Ñ4sòMD{fo*)ÚŸ?þó£}ü{ígÊ_ì1´??…yúpýøµ*–JÔ5²ÍhW¬ñ ÉmÂ6¤§óEK(±‹J)^ŽÑî­„7 53ö_÷¼býñB¼ì3|ô™-D>
+‘Ÿ¨û¸ }X²[›Þ碄–Ý%ûpYä8(p Öi”eÕýôÂDŽÜxˆ™ÒlÜuå(©)0JöÕÛœÓe^Âi2ZŒ9ý\ºxft+2xªE+2$ÒçTdaáâM»&¤jy,ýïˆÍ±hP1j?®2ÍÑGs¨§bøis@z_"ψ ™Ž„ë‘gÆÚi"uÎÃinQ¨Ã[ÉÖ§®enÑ%trÕKWÓÑQohA '*“¦ûJº<e"4齃'P è©ÈÕ›,¥Ÿ<ã[ tÎ3r£ÀŸG=4£iÑ?sÓ7-+Ì°}w{ŒÆOjÅŒM ¤PN(ü¶Á­àŠ
+b»X‘ÊÕŒ'dñ ‚ZªÈ‡«æÜ;ñ¯hÒr ‹§é1Ö± <¬åÄ^};÷dóy
++ÃLoÖ 8Ý&&ª¤—5!€ÎK$‡OæÕ
+®WÛ žl~ñ¢ îÁE›Ìy«Ü ¾¬9WÕé¢Ùë /HÄP‘Agér¤ / Ó­!Cœ§Q>¶Ëuš5mEår‹Ï2ÌQÊ™Øàr/3J‰aÆ*'ך¼_C9=NFù /-Û-¿°RÏÅs_­¤Œ¢ÚËrÇCyxå€ö
+,¿Ñ~‡n“ó‰ð
+ãj’284Ž+Ë‚4Åa‚¿ùÕ°ÿ ©bøcp%æy^Æ”À13¿O\§SŽ9悘V@Ý-¯®T€+«Î«¯ þp/VBN~]úãÍ‚¾Y¿[Œoƒ°0Κœ£ê±]Ñi®&-ïAOgÂǸyÆàÖîþþ¨–ÐÔQ²\ Ai'Õ™ûhô…ñO¦J1à)å•ŽÖLMiO䲆ó*œÂÙ·“Q7¨I‹þ8 H5ŒÛš×N`á_‹¬K,î]áëoÈŠÀ»ŠÑÉH?’}w­Í1Ì7dµ
+TÈÉ[²Òê‘(vØòˆ)D9D)n¸ŸÉjëRõéÄ^Èú
+:ðNĽF™¡wd}xÈv‚Ä’~ù O':PÕ*àb£#ÊLTå ±Öʳ45=‘̪-jE%¼ãMŠ ¢øyiV®:¯©¥áãâGª¾Òë@Õ?rpSµqèœÞ«¯RT¿ÆëÙ/æb*«ó–Õ¥o‹îÓàiõÏžÎKõŠ„ÖÆÉèsVO¦5“§Gœò0§ÔÉ6*’{³-'ªÑ|.ò±”ºÀoY
+«„É˯ÃèpK¨áÕýk§\¡Œ®òíÕâ¤F¤B)€@l®…hIW«Äô«_©p‡!…ň~wÃ…/ÏëÃÕM WžrèJ"^IzÞAö [SLÖêGEæ#ˆ¡¬u¼ u¯rïNf!ö«êœÌÐÈÒÝÏ^c•X¾"þ^´€³£EhŽÃ* ðuXO¿N’p˜a’v¿dÿÊAø($¯¤†Q“l“\fº\åt:†5§QA¯‰íÛ ƒõ°s
+ð±DºêPçgIž‡Õ7ëðï×Æœä`ÈàÑy^­àD Ï&©gÃÍÚÑ$êÓ' M”WjT"ïWÝüÅ^$¿KT‰%"žK|Qýôšà82%ó"½(¿ :˜à ôd‚’
+?oXÁOݪÈØãÜË24§äÚ*ô–/$"'q‹YWŠR‚\æÆË¢
+%4k¿ùGæ¦Çý£=0 Yå亖ñ5-1«M½veMŠ+—!cÐàûõvÕ:‹ÄŠEŠÈk¹Q_ç%wÌñmP
+HÙ¡•‘zê¹T8R®ÞɃiã:ù¨-"+ßyÊQ·Ð$¦.
+>,NÉÆí*T:šLšÄWÁÔæ®úÏ ã’tJ}QFeqˆS5Ÿþ/ŒVrÇ(y,ÜÔ<š<xÝàüt+zô©¨vÃvðn4?¨‰†ñZÆúìåÅíñ·•Ü¹ñ©á¾—ß °Ñð4{?æ“ÙàÒxr÷¿hå×YÞw%º6/a¦`MÂ~=¦°Þ´¢aê¹±T²bA_^âBÀXÃ`’°Þ·d=‹.V’Â¥a åþÊÔ<‹VÄ?—‘"›½.úp'"oJˆ„(ú²“ V‘¬—E¨
+N}—ðÈ¥zŒÇ]éa€‚‡…ßE}@
+ŽÖÓižâ¦'qÀ®K®€çú¸¡%V?É¢œ%ý[K©ÀÖ(
+t
+*Ñ匭Í49oìðôÜ€6*âòÌÚÑ,“‡/[b¨à‰„Éb{1Ïw%ûK“Û©Ë=×û9@G #÷§¤t:Ea.¥N&x4n®n ¡däé [Ø°µ¦·—3¤¤TÚgȇDŽ<EVâKŸXÕ8Úüí_¾ù’W¶kÞ$B®ÒKÒ7“±îW‰€‚!Qè8Xœ½Ñ¶Ë­G–ÑO&Ë%··ÉŸùL¾ êüõp=‹Õsr©n"ã!Rñ]çPOžZã )0È4ÈvEÃ#{(À*…N “¨q0µžWaþðíßE?_ix€õ4§"h½Éž‡F0™tsÆ-b4ˆ ̃4=»¡ƒf^xL´Ga¿-â/ÿ;V\€·Àƒ«DRp‰ûc«õoÎ/Æô鸅ŒÈÀei›&¤}á° FÊpH/½ßŠ| ÝŒÜc/$ò2Ýž(”cõ…2Å
+æŸÙØbóÞ°ÒQRÁÈ.Œ  ›ú£ç@=–›¾rÇfëZÂp&沑JzÛVðVdbsÎaÉ7Ï=‹8Ô•30\îp5e'q«¬ìOO5¿¨juŒ#wNFáYžXŠxNÒpè
+=3ÛMYq ¾,õæÇŸsºz
+§æz)q¤+K2X(uÅEš$–7hþøU–“ ·qYøŠ¦¯È^Œ»<Qô™êÓÿª
+)Àía‡üV]À¬ä#Z´o]Þ÷<î›ExP=À^yTdJz`Ý=}3–…7Ê“œ %P}EÚ »œ£DÐÁ¯WÄÄ+ø¢¨g°D3*°*&';¤=lnÇØvè]ËQ<¡ NCþ ¦`ý)€= F¢ øöš=­©{Éò¬‰BÑ¢KÉߎ¼Zý×ïÌ-¾’TIyW §[—”ƒ
+Z,ÇÓw‰¼mÅ™ZÛÑ,
+=mµìAî<YvÕü39ÃeUÚ.1._÷¼u@åø?#:眓Ì9LDD |ƒÄÞ±—(’ì0£…¶L$—‘ï¦=Q$Zï2-s\_ý:Ç¡ýÖí!…1Ÿ1FX”‘±rÿ
+LŒjûM¬Ê”c釗xì Ùs5ÍdZœD¸AËI>ÖÇšDdƒÍÏ£ÑMYF9[‰¶ ÊqÅå6ÿZóX'šC3B9mÌo]VüyÜ·Š^hçó;܆¼dñ‰¹¡|½_÷ L8•—+êdQTcyµ]}—™zî!ûä%l3æWe;ŽŒK%øT:
+[«Þˆµ÷CÏð¯ ÷ dÑÞE([}ßç@áúQcrìvf@™HØC¦À.JKŽ» ò¥$ŽâRš ªåÍw2ï _×ìÛ ¬ ¤dQÂ^³HdÏÓæQ¥ˆ¦âÃF'(äÂYÑí
+nÂË@/~Tr\a’¸Á9ªñ
+e4”f¼)Ò6f¾ŽzMHÖ3åßé ‡€”Ït¶›˜‰šB»›¨Cå¸bÞ¯29•¾äÁÎ*d96àˆ-ÚœÅoÃRîˆkú }}WhÞ}ˆkT ©¨üx›²Š ˜ ’±WÁiX41¯Ñ:À8Öd%b¥Â+&}35ÖKÀ8b:T
+oþ+Ú øqÁºeŒ†7Y æ­GÇ0þ¾zÖ°úcNobo0<@”êâ,Ú€øÌŒ»Ù7~öw" t°&)œ '1§¯D‡;­ZFµâ¦©¯SK%[ÆuS±[ÆܘÀ3­sz|%}l¡(sì¯ÈPâ·ùï„ïÛ j%P?‡WmVûÒ–Eﲚ5©–ædÿŒ»|œÞ`Dƒá3†‰î×½ Ï>b¸ Žç2?ü$,Í’†p¿}†þÐIü©œÛþR—dAŽÒ¿0
+ŒŽÝèPæøDú˜7FÊïÃÚ±a]V~ÅÀÁ6gËçs>-®Úy¿²ŸŽŸêYA³57‘†ìð&·“5“$ö7Ãü­$NB¢à(Vœðæ;Æß ZrØÁ ÈRÂÒñxl»Ô"ÞdB§ñÔÙBa{$‘_ð³³ Ìv &c…y|ØK˜“"èqŸóïõN6ÿõßÿ(Aá“ÙØ™WyÀζ 7¼ ‘«ë&” ]SÆZq…ÛhHRŠòŠ†R±½“^o6®R}4„{èíÔˆ:äÛ±à[»ˆxŠN´åMY’”€&£ÁÛ
+@…X÷‘éO‹ö¢MmôÍ[P~’+‚ <¦xŒm¯‰îØ¥èç›".‡7AGJk»ŠØMô­”\öÀ¿ÜAêb[*`UèHˆÜ‚¦‡wu¬y ƒBûjÎÿÛÿý üma­+^âÙ<~ÖS|©…¦7ƒúãÀ…´±Œt‰¨½QX`C¶cô%&7žÓ<Xj¤‘‘„aj.ò2]L5ñê ç¨lŒ\e…üýãC¹'U÷;ãB *AèÁ*˱7¬ |5 BéíZ‚üàƒ‰¨hwx-‚©’¬8¼äDw)z@QWFÓE­³œ¹Ê%à0|7ýé ›o£Bã {A¢ù¥íÅx…4Fzâ>4ø-6µ"LkÇ~ýÃÓ c]Q0¬\ï_ÜY² ®Ò%±²èCx7”ãMÄãnû ñGW“-²ED.â›,IkO ¬
+È@°ç5ÞA:HTG”Xɘ”ÚéÅΊUŠ Î]͇y+¢Õ‹ƒ‡èØWýFß*’]œrd)âÁ¥¨jÜN%Oç9®Äˆ¹V4¨âýXBôd,x‚¨°íYÁñ¼
+hÁ2á04r€'³P[O–8"q£}~˜2$γÁ—7ÝÒš³šKVÕZ½ëŸ˜Å”q˜Í7ßai0¾©Ø^s9Þ®ìÑV "~Cæuå-êF@ã³iëŸð¥V°T qž-‡ñÄ\d(1I>B¯;û@3±ªà%_!X¥PT7žðŒ¡½ã8³órþ! Êb‹O/Âfæœp8}«:„Ì$e}š¼Š kÂíªåJ¤Ò©Èž^'^€øëZTC½ð=tF·â½B ûN{ «’ã‡yy dåá Krl|•ˆDrþ>º¿´·<z=ºù¶é(¸:‘wÝ
+U™án›ÿ{7Y# ¬ûØ5˜ŒÙdÊ”]§O½‰°f“dò•ec'®K‚X!Òsó6Ö}cÞ¥__ýRÏVtt¯åú=’€Ú8JÈ ÝG=* æq$:cz1€¶c’¯ˆPâl:K`
+D¼âJ®¦{VömžøäÇKàÇï£þ
+ŒOêÅq¤sˆ¥œë4”ÁWBpªÍÝ0Y(@ï¦ ¯¥oÅÆ{ÂøôGàÒÖ £¸ÔYä¿oñ'½ÅÖûê<‹:ˆÎ$B3í׆…pÑÄáÎKÚT·X+ËKà"‹k}—LM›ƒ|Ĭx59bFE¦)%41ØR²]q›~i„<Xo±È°˜
+aÙ~$ @9ìQÆfmå'ÞBøæ&/s&ÆðÄf=”&ÀØ'n06
+ŒåŠí´H¹R0L|ìBÓ96=Ãà h2P…D3]i£fU€Nù¸@;3xAœ
+v>A"^1ghÙÓ¯7±Sau¬öSf©`lÝ!*Pçì²›ÖWеäy*²ñ€ÌQëñeÐÃðÝ_™ÐÏ^r3‹N ͸çP-¾31” sîHgîŒ(ÓÓ$­’ À!¿ã 3G©Zê!ØRF\±û'dˆ’Ð>J¼QET%d¼¦‚DT£¨ÞòP@Z§Í$„1ï4IŠäšÇa.å—Àà9=V Q|c59`… ¨Å´çî ª‰þK‰ »°/(®¬CªžŠãüü #¹¿¦ùbÀ=›Að@Ü2Ð_ÕÏùªŠt_ÏÓÌìÂb8…%„É
+È¢#Yº¢#‹„`;fL§'äŸ@0#š[t%5ßê
+ÒY,˜aëXE5Wy«SRFŽþÏ†à—Œ˜<@üJ€½6¤‘[ìKÉOÑNXúÍ#Ê{¥°Öaˆ5@îÇüe'ìCÁèQˆ2ˆ[¾¿MÚjzs)ÉRfs;!WŠ]Å ®6CÎÔ™’ÛÃ!LKòN$Àñè[ã%òµ)¼zÓ'|tfw{Cî›m™¹¯uhÚ—çP;8õØ +˜8Yž³s±‚ _nëqm•ølä¼EŒK1¨Ä˜Uw „6Ô/~í !áÐRëNx`, q€ ³}­RxáM¨u0Ô É:0Í¡„…éŽAò„‹
+“&I¨¾Õ$Ï“pRm$:ËAò¿oÉ@SEµìR’©S÷î£.Ad¬‘Œ¾Çñ5>ÆÉŽÂ`´–éäLBd¥åó‚(ôðžP[DˆÒsãêæñŒ¾> ŒNŠM"=ű÷' ŒN)­qõ¸Ôfbøê¶xN†)›!2ÅŽS_šÅµ’“i‘ÊÛ¸tIpT/¹èR‘ŽÇ•S]ëȉ(ÙÍCš"LÉ'ûV"Ò- åd‚ŸKiêÇu(D r–›1t<ÎàNسŸô I è.ÝLjeQ²KN?tÙ &§}…aõu
+‹û¤'(Ζ
+¯•Û*@×a÷Ü”iåß?n': ÿQ¬Ì!Vã\AE61“¢&Ý6ãy§T¤õmâRÇ8qLP2ˆúcŠÿykÄ„í¨wi~žèg}½¿"–63&(` ¨ ?{¼›9®1«{M«á{T–Þ¦JyzL¬Wæ2#îNý^xÞ õëA„OÚGºŒƒ¬© ù´JA÷(r‘ãéù%!5VþÑ6>&É+æÔäzѸÔ^]ƒäô=H
+B¹$-³s$ø—¿àEFáœ#³,?T2:Ë!GÊð˜ÿ€Ôª£ñðuÜcŽTÁ''ã¼PH}²NbÖHEéè#AȬ Í››ÀKŽ¤CÜ,‚0Ž1R=¬©ƒÔ¦§yhókŒ<€Ç'pºI—â÷ŸµÎT…)EaóñyÚîte>דg5ò·;ïYÖœ¦›Ër™)NE+ÆÞ A"Ö§ÃÆWýÎbaE= µ÷à2(¸,a).8Èœq×_‘C6©`ß%@`£Æ¶%_…þg‘lÅ\M¨Cû"ð§l6·-.¤ÒdQ.V8@w©-¾0¤Ý³~M#@sª‡ÔwdG~ß<d^.N#¨”hÓw«h5ùu@Ä~q.‰ÌÊÕxw ]ɽ¥Ã`*Àû™§=F„S5£FšïÐWF8ñy ugÚ(ÆtMBFH‘B‚h),‡‚7úÚJù‰özwÛjà“8<2f>®Bi•ó´e¤û’¦ä»V?GÞ„Œ K’ÅÞÕÊyÑFˆÊ0«œ¾¼ˆÎ¢,ëºÖÉŕ]Ì#×QŽ’õÆ(áÃbÆ¡no§2<JÖµšWá£)í†å ¡ó*z¬j™/t?Š„-±¢m5(fGf;×à<& X¸"–ÚvR£wÑIW@9)ÄuZ.~û:uª÷q;ÍïAu-\gÇÄåGšôœt@Aè1ìÔ MXôŽò%.ÏÍó‘“ÚÈË' (w ra16¶h:¿ñ²Eí{î¹VóšŸh
+Å_õ8®£¾ÁFWyîý8H%ÔW¢ÈÚÒj69D£µS’¯I ¾Õ&ˆÉdF[&…Àtð›™}'Yp ,Â’Ï<‘x"$;§ÖM ˜±ƒLøä~eãHš Û«.Õyª¬dÒt'cÚ„4E­â:²¸vœz—¶BTÉ`ÿóõD¾éÉÍJX
+=JÉ ²¤P*FMàAù'žML9­ÃHQUªª½ Ål¡nðÌ g(ŠÄ› !sëÖeeüé<Á®IÌ€*5@ÊçNüÍé‡f~>ãÇPÓ}´aV×7jDk™ëzÆïÄ'½Á-ORôâr<´Á›”{²É7 µh!oKÚFU4Õþ$"[ä÷=¬-…?¾eH¢2°<“±·Þ(D!PR^Úwl‘)æšÉIy¤jû\°Šu':¹3õ¤u%FŠ%.2ÐÚ6öU%‰Aø8U<¶ˆ<ת`¤ŸDå¥4<? j%l€çcÇUSKCªã*ñ'DäL'€P¥9»Ž‹yQ P×®²¾€°´!Œ',6×»‚x";NQ$UrÿöÊ(×,Åýóôù„6²Ij=²ú<û0ªņ&õtZ£-Õë¡&U«‚1êá1ÖŸÒPè÷V áÒ$¦“9‰øŸéÜRk1 Úâž­9×GjÒ}¦ÓÕ„°6æ†Þ¨ÿîq}Úø[J
+s`ÈÈù(ÜÐH~1¤¿({ƒæù­WB%§ælÌ¡½ãÌç&™ÎÄ‚`w£±'%,­¡6¨% A¾“C²ù)&­íY|:±ZÊöPç>ÜHØ}}}N“ÿÉŠŠ­©‚зU=vúcmÜCn=–W„€¥vœCæ&ÑçUg¬É†Û-Ÿ‰‚ëD”‚í’ vÅ"ÊM |(˜Ì —ƒŸƒø>NfÛHÊø!ªPdKãY|.ÿ)n¸^XtCùðÓ,ò
+”¤$f2HA£{¿÷ãã´I± 7¯gˆ©qÒBÈÆ™AÜf›Ð¼·Ðö2¢ ìÒ6X€W÷P/ ˆ(;pÔÈÍöY)ÜŒ«p®QHŽcÕˆà’×xÃYQ’©‰w/¢;üâ)uz˜\ú.|’
+ºµ
+1‰hçsÏwaß™ƒ– ;Fg¨(7\ãÔoc™óòAi.‹<\ÆFé 11›™À¼€~½
+H蟀ž®+ F¶9ÚíÃï ŠÒ1(Lf¡èqÝT2 Ttøþ lúǨþºÖò;æózÿR[*B«Yü äèñM˜-Ï-ÙöÞ+èá›êþPˆJ®Õ»òæÛeŸï|‘øóY>¥Ý,ÏVŒ|Ñ»è‘*•AàîA Iþ èñºËûÞ‘O¨c-Êá«Åu‘/*'¿"x1–I+PiûEc@ŸïTÜÃ7°‹2¢‹×._õß+èRΆ9KSðÀ´ëÛ K*Šž´Uh&öÛ K¥ž¯{”my#úTÐ+ˆh„É $*°A†½vÌZ`KÉ¢v¬¡Œ¬IÆÓB“úÞz_“Ð*B—o¯#¥­ßx§£<CŽeÉ;ªÃÅ„£Bš HÓgY ^Ž ÷•X=tn\Äòº•‡›b…h±d`x2´Ü°/®2ã¤SÙRQÓŸ½´¾uvÞº¼Ùäzü˯¢$’ ØcD%PaÛ…æaÃ?)ìs„|”ôˆ2‘•ˆŒz1H×/Ñlp] ~Õä-QS¢á‹s¶„mµ3”j±a²=TååJ¤ß$g"‘5šÀ'­Ê<ËÌPaq$qœ‡@ì6D]º‡: Òˆ¹XžUÏ«ˆ¢,=™[ Ò‰I9÷ê!?ÿºc´³65¬Õ8z» 6-sQΰï°åx·VA¶ÞÝücÀB>ò>ÜHçu:2Í%&eTEMdêœÃPå–»bK9«\$¡@ÒÉ9ЧyÈÙZo¿©KèYmXÇÊ‹s”-{FèòÅ‚°t}\ÏóœÂw±Èd­Eq•GŒ%fYEpê¯bÆtÊÐÙu^Ž,¥>¶Ah-ŸCŠ¥P´ã•Z)ãª,9¢,_21¼ð(‹Ù9MdBZ‘ã*n­ð‚ÙÜÝÊÀV­B I¢õú<¤±ÑðÐ-(ÑÈžÜÔýAÿî¾–4œ™,®úyu‰‹Øjd+¥ôÄìò6èÁ
+Ásx ™ï’žh³9ÉòcÃD‚(þ¶ûü„¥É®ÒIÌ¢$‰‚ì¤=U¹w¶8rVY 1ÒÆ<óK~ÓÊ2Îfº$·ãGŒ_…èëc†f'2._‹²EIÐÔoÓV½Äà¿­]þÉžñÉUÌ$hdi« ¹&H‘:
+kÎÄ™1A:íåG©+%„¿d-‚O\f¯êò6ÒÊXÑ©5‡~9Içéd°Š¿Ñ°Ìѯ¤R’bW”°«ÊˆÏ<_C-è9ÎUæÌTIºœåzKbÁ€áj\cJRð3æ¿äðjéÓZÞÖ$Yл|…¬)Y‡AªxÇÙ‡|ß
+(ØsÞšÜ,ýA®ã&j5Tˆân5qÑá÷‹Ÿƒ
+Î`år…=Ž¶ã·S·§32µÑ7¥¯t†-B1–õS)•Fa¡ÚÉB•‘ˆ6Ã
+×4q!%ó‰S†õˆFÒ*S2&w¡ œ~Ä6ŒB«ç´MR·©øêb\ÉÜ*@ÕaŒ²ÄÒL[ÌÒ˜>¶\ør‘ãÞW>MªEŠq,]bBHGXªM²eÖ›‰¸âOçVFrõ7NÒÆ‘%aó™Ö¹cöAvÊð‡%ïjœ½„‡>¯w×!Æ ‚¨Ïë:†ÿ$?8å: ï÷”a9{I‡»
+mŠ)£çeM1éw¥³Yç™ÓÕ üà¸?<<þìÕ騹f÷U¡/|v„—Þû7Z*¡¸ºhð S±Èem•XÉUøí6™r¢®ŒØh'/]êèÃi0½³ªyšçμòp”bYÅßšÞ²3Žå0†Hà!Ñe Âî/†êŒY<ÝæemìLÉt#íÀ}þºû½Hßiè e†xî¡ù¹üSWm™õ°î^zI, /Ã?×{KS´ïǤîe¾PF$:{0_<îÒ˜ÕQÈPžFàî”´„©y˜› d |e†™âŒŽ8ѶpšãïQëxº”`ÀP.¾_xø|çRelå°ÜCÂS™«<}=ssέE;*^.uu”=ïh™X›(£–s*¯ =JjP³îóR’8†¹áŸÃ¹¾¬cÔNâÛ‚WèãêºÕz ½2ÓÝd.ìàI#*AîmiÄsÞ/7O ¾¯-SÚëû•?¯N lð¾póKÆV8”÷.—ûÏóp…Gì—ºÒ×!~I:@¿@AÑø~úYGE|w Q Yi­!ŠòŒv‚Ç>à³5ô]âR2á.µÏ'Æ
+³ñd¬G )ŠcÌJãZûžd©&•Ž©«gH+ˆ\¢$ ïD¶Z;ùà²B×¾ŠhGât=}hõǵw›I¥z•èÛÝ»™ÀÊù<Vo笸¶ê4{ÏIc'óùêñmVCš!®Á7p¶‡]=Î NÕmt‚x½’ßDÆÇñ]Ôl’_% &œÈlx|#¸%—ôu<B0í}ʼö¡½rÃF…{,ÃÙtà™íÆY…ÞµòEÌx"ÉêêÕÔM
+ yp[Ç‘¯c¦æVƒ@å«_cð=±÷õ0c£#Òá„Q™™qôxžôé«ì‚ŒØa;.^Šã&Ï©·’¸›Ý—lþVÄÁú¸3 SèÓ\Mîæa63—¢zN•ênšãâÇú"go¢Pat×¥¶ ¦¹¶rŽ"Òɘþs¼^8?ŸÍÏ3JXÅà$G¼_PƒÔ‚Æ9·2é;ˆ ßgžðÂ-–~h/pè>žÚ(Iœ †Ë°g§ëœØ[”YbN<˜nk¤vÛ°;‰$u•z²!;gT†ÚÆ*‰N³äìQìä–ïW¥ú([±EÀƧ—!¬¿­…¡¬Óu¶µNÍx‡ü÷k°ëWïf¥y+þ„#fí‡Óù+:…‚V¸[êÉ·Þ v˜Ãë\~Ê3ƒ:187×æ _¶Þ˜ ø̺úbóç4w¨÷0áãÀONf¯cuÊ
+S31Óâ¨hèÚKΚíÈ
+1ÃL%[LmXí$ œ@Ònô¸Rx˜þë (Ú"K-$4ÈIû¹Dnhâžž+¬’=Ö÷òeð~)YV4¾¹qÇ—uŽô¤$»µò®s¸ÃaL¾=ß[„ ŸFa×ûµM'q»qµ€ÝOäuu³x=¬_JòpúPÂ_+4ü^d
+9œÒž:ˆkCŽž¸»mÇfÜÔ°Þ÷öƒU﹊ç÷Px~E†I8ç›Ë Æ:½Æ6–ùŒJ0O–~ê{ª½H4×ÎŒþxù\¡†²-þºŽd½¨‘¹¯9Rw€¶ÅÊO…Ñ#ßœâ»Ù&Ûó·“ÒíGûöuíʘw}0×Xq5O¾­ŠîviÊh„;ZìaÚ<Kà Õ{h Ô6¼¸ÎÓ<Ôø*9^4!x
+Ž ðœËRœ1^oúøê îG;+ZHL1Ê‹Ç
+*áZ+Jĸ¿uÙØðR¨Ba([@r‘£°Í{™»"…¨¨÷ò„˜®†Œ]Œ^§âVÕ ÛA2, »F¨š¶Žâ,³†H¦ì\Ã’Í‡Ç Aæ¨J·¼b 4Qb|Õ>v*X!$Xj¯”¾6ÜÑÒ“ÑðÇ[ê6ÝEÄפ%@¸°ržÚ©9òÚ°…,”;¦´(VÒ½he<ƒ Ç@#«¸ ]jyq(òL‡™e.È·’ðý"K BŽûg«ÚÆ-ðä°£±ŽNƒ:n.Y{uXk‰R½€pÒPÄÙâ¡«eRuøÛ4&îå/“¬c•ÄÍŒ…u]‹Ž`’ËpÚ1bgc‘QÄŒAÉ ;±B–IâÓhgLÂdΦhÆÖ™èòßã:#^µ2•òYÖ´–]3þ—ÎgªùS7ðùËêqZx­'–T¯$KWI4$CÏ ÷ƒø;“N'ŸÈNõq}'vhUã²F½®w)TΤF>w“0?ˆ¿Ó£““ài‰²§ì%J,šÔy»ü$JH´0§’yQ
+[®ž² X)v,F£á“ù¦„-˜PÙtï
+Òáh.æ¾~|¹ 3±Ì,Vb¬ èûˆ¢b¥òÁ:JŒCãà_\JóùÄ)m]éŠóh¾AÀ^uÅÔà0y¯ÂÁW˜Æ%Zb@y›0 »@ÓA^3+šY·:è>˜ùœÝ)PÖ€ÿw?CC–Ö ’$}5ó‚ݵö0]æ³á"÷¯¢—Õ§Š‡ÙzÜ=b"ÌŒƒÊéìCpK½ÏP
+Cs¬®| KŒÇÝ5… Áè<áVU‹O'f¤h>g¹ B†ù=œ÷¦úb™]á?îÀ@žÃPËUÝtºµ xLÚÎù(^‚ÍtFLŒÚNL‡(ß”’bYÚ­qbò÷ŠÈ¢è',­\IàA„¼‡!9ön°ÙˆÃpC¬Ÿ®eí)“ši+$:@–ÿáeùÏÇWñž˜0k\
+b ŸÛ2_+Ø´€TˆóFšwT°K¥w¥A8gŽ‹ã@ª“îäe‰·’ìdè¸h ÝF¨{𖮦©‡ù¬ŠÛæá?榨‘Ë0È8†`ò75'®¹ImÝœàUè.J]§?™‹ #š<þe¨‘JŠzŒâÓ“oÌ l2åëÜ#ùLa±¿0S0eòoXBÆw ¶`@òÄI7OW€ TŽ–ëqƒŽH<§ÅÔ*Ñ ˆbkÒ±‡CÆJY–Pø»K¤°‰BÑ?'ñ$¸5¬š™¤¦æCí“ ãHšqŠ!:2ªa¿ |X¤ÍxËû¶ŠhlÉÒÀb¹^/¶²”Jà*”E6q
+7
+«Ò+‹ N(ú/€ðˆÔÿ™šÉ0p hwNƒ´­„¢WÚÇp=¨™@¤×:{ÞJ žšhXäMÔVl†ˆH<Wl…+¦‡óZ|A
+^«‰I á5”}NO¦Iÿärv BëH‹”°zqÖÉ¥+e â‘Y W›ë¤Éϲ½²Ÿ8çš² "U9“nR/ôQ. Ñëoƒ(Osʾ3ß/@;´HÎoÊoÉŒþ~¶r‹•‚:‰E+®8VA›uu¶ „@ÌåPb˜×©Ò¯*Íž7å?þXäÚ ÆVü4è,6åOµ_rZl%‡*6í'ÊË¡°clE0eÚÅ]î--EHÈÁFOÝ;³K±Ž˜Zü2†7Ÿ­ 3È‹”ò1Š”')Äñ;['[t©<銭š  T…1pò!M†ŒŽ'M2i³´­!†æq¶ºæúv•`œ&^e—…çýøÊú­âÉQ óÕøá°•Ž#ùBvs®Š¤oy`ÝýRƒšô—œãĬÒ4{Û$„)»™¬~ÞM&§à$Ü- T”ñâsž÷„‘ËV_‡Ž0h󛆕¸L%Yã]:Ž":sž•¬È~ÌÃñâ4ª‚gŸbÒÂȯR?Tºä:™¨ÇYÜÃÊŒýt::Úe²‰þšr¼ÄxÆêÈ_“##‘ü1ÆÏyÐ[æ­ãɯüŽHdü¶HÁ‚2|Jiú¼”ï°)ÉUî¼ø,•j Îeä+)7ùB'~dÚ‘Q¦hc×ë˾!ëlKMÐ\€ c Ù"üùcMº\K»GÓõ²gEQS#ZN[6ú2 ®{ eÆÑ‹ñOòdÌs‘©ÌÝäSOŽ±!Vöv •RXH²¥…2ïáTBÝ•%:´rM°±× y*Q×Í3
+ë šæd‰_ßêy¤žÖa´<Ã\ùÅ­8 ôZb¿/±Å·âù3LÀv=/ÞD7øœ¤[±ð€’vžÞ‚htÚ°„³*ò¢F¬BWÁ&ÖÓ¶z >•­9š¶Î¤xÝâN‡J³\¢M#Q>à`K”»Ç*fî'9R‰­hifa)¿F•QbhÃgÛ:8?•JY* 6™ÔÊ‚ƒAðY ‘³˜p:RO‘–ØŠ|ÅJ›–q` ÔJ!
+"B-PÚs¶ú‡áF¤²?‹óK±½+:Á½Ý¢i7"7¯N %hÙƒ IéM wã}̯;ß9‘üy­ArÅ• ‘IÈèëè× TèóA½éüzôæ-ÐÓvÏ÷{ t15•XÊ@Ì„]wCÿèb´ž‹ù
+åúÀ:}âd!eJ7ÊtÖÓ3»‘0™Î•*¡þ‘:Š÷L,œvæuåТ¾¸÷Ž#¢»Aþe¼Lrã<b(|‚ÜA'0jÖÎÒ·•sÿm¾G²©»~$†l-vM||Ã\|aà÷‰ tžÈü&¶’a›…Ó%O”¦ðy¶uð\¸ (>¬˜wÀÐÐm« ×@ 9c'Þ÷˪{•<<`–ÍÚ2D3Ö'ÑêzVaN3r“Yª^
+†a
+«¸ðLýlóRÒͼÑ5ÚâkmqŠÒÿ“dLl׺¾Ú$K€Ø|í4‰‰Ë4n‰Ãà
+¹jæ/ñôÎ[Ê/XÞT-Qyƒ?ø‹£,¾i4 wìÄ´ÇžØ.E‰xnÃR¹FIÅ5ˆd;–\iTlŽì¢\^„K"Ph`÷Û‹è5GNü7¯Vš 䳓“Å;d}~Žƒg‚-yV–¶‘ïfÓ€Aô¿ÇMÍ¢3ÅJŽ™ãâìÄÐ6‡ªuׂú·(Ù4¥ÀN¤]§tVBÒO£¾•퀊ºhÆ­È8t¶ ÷p«(µô–vh8¿ÂUòZûrÞ0 ‚?@î9q‘–ÍTDäVB;õœ¤ÛXFâøD !É(“ZDh@<g;þp;œNüÃqöÕÏ«s@Wxγñ å¼`éÆ:˸[.
+>fé–bt½±'Væ¢Ø)¥ªÜÊ¡ "®°œ%DÃÁŸ­Þ‹à‘D|å ŸÖy‰¢·’·(z-2ÊüÈ«xÉbØÑ\DDQD,"s^¹”´¬‚‹!”üuõÄS28Ù%éMÖùfÃJ¾êâχ[}+ú}µÎaùºHútŒn9é­öôxe ù–]-½JI9t•3wLkC·9ÒÅÜ ÃÏÎR)¥æeäã,Ä¢|!Õ¦ 3>%bpà­$ÜÒwý¸,Óuz<‡Ž;-9S¨ê‰ÍÎBû #ltžø/:QÞž ¨:¨K¾㬔§é<0ÇÚõuÕ†)’j8µ¬‹màaŠÌhj§¥`4§ˆÓ–aÉ­Ø€,†[J8–ãਇ—ภ÷
+Â&¢OòO,»wìÐ3Ö'K·Ãˆ¬á®›m³››WE¾ÂZpŒM'ÁIy(yóµïEDDl(ÅÛapát‰{3ZÊS—Káö¡rU>¥Ñ°Z‹¸¼/1|+bGÊo9’Жåv÷N)çÀ‡9Õ’…­¼¨<~!%]­¾UûaÔÁ½™3E!˜6²ä%XOÔŸ»¡­Ž¿ìÀé6©AüŒ-#„ˆgÂ}
+dÕ7×DaŽ@Ë$q4ä86²9ÈŠqÊ£*!«me’±²ˆPx„|í«–Ï¡÷gz±‡õ_¤á¥è÷SQYJ‚PEÜ꽄åÕEJí±Ä*=¯ŸÚªà£qìãóêIv9ˆvî¡þ'šs*ˆo­o¾3˽b ˆ8tžŽ Úœ½ÐNø;°cB±òxž
+ C
+
+£¥tI/àY/A›-FþÙK˜g$:AÍ-ì R/OÏ„)«¨ñ@h‰­ªœ¥rfRæ¤dM!c3slUÛáý4+WHšAŽ0Jh—Â#†sÇVL=’Åf‰¢¼ikN²fÍÖÁ¢iMQß±Kx·/3¤å‡¹ôÒ¦>{0T%I0Wê%–bæ û:ºøá=JÜg¯+wå´D?Q‚žÂ%ÊH’b+± k>/EïñBÇAëái(«ž"%EZ'ª´ÍXRíÜŠ¬^¢‹‹ñäàýyL"l»Z[NŒKc”ö¹ùæÆÌ(P]Ñ+Ú G…˜—¼KÇ¡Î>x(ùŠQ¡¹¬ ¾2¼Xiŵ,}¥{ 3`P+“;s¡xãE ¦ZG³9‡ŒS
+UV‡Ôœ> Fx (Áǘúe§'uØ\ï1Rð?¥ÀÀ0}X2#>ÐƧ\•-d»ØJ~Ž|µw:Ž§žŠ_«ÅN¢y ¬’¯Î+4°ÈW=~€ 
+RÍC ÁpțɀîôZÄX‚°)¿1|ÁŸKbäNÉ’M’'¿L‚ÓfÊŽE~‹1!Üt+Ù…ñR “Âû: -EÊI!]^>í}E3{â€øËvVùT(ª:Õd¾ŽwbfpuDé¨A”¨ýèa´:DË@ó¨™.”`‘è›0vâkc¢sy7AFÞð%• À'RdL0
+ ƒx[<ž ÕTŽ)Nð¤4xi‹"F”H¡Ø;ÕqÕ* òF¨=è Fes…<~]ññ¿ŠØn{8!›rêÌ¢´„œè) 6¥ÑLV&ó—AB/g¦ÙÊð_$“°\YÎÿÝÄ:¦ai"˜ËÇè¬Î#•”´ŒŠIÐd4”=ó¬Ê^ËJð CtµÝêø’"ËÂØ’åÓð6Ù£ÐZ)NEú*9‰žyÀè¥"«­j%ÈD‹7üpŸ†•ŽzÅN»”8Ÿ7FT1;IXñKáCG@ÚÃdYdd—˜Â*DÌ׆!71¶×#ᤅýW€
+H‰Œ—AŽd¹ DOPwÈõ
+ê„25¢w!4Ÿ ÒE»vŸsʹhN¡:ÔÏEÝ%¼ ’^ xÊЩfÍ÷U£îO>6¤ ?#Mk âéc¦ŒvAzS®>ÎUÑr´dµå% Oiº¯JSë¦ÉëO4*Ñ:±ñ¶¾éM[Z¡v ­;×tò¬w Á'ÃB¬Æ8Õ¬ú’ i1ý´ dÓšöéùëœF9[ã­;ËSÚ$”“Û7„šµÞ{Uì<=“¼q|ŸctD39/÷¡¡.|—A~Ŧñýò„%©üYo û&‡4ÚYÜ œs4#ù1t×ScXVÜrƒ4(¤Ýäâ׃”†µë10cö”‹¢_›a<á‘ìÍ÷9ÔN'ÕKåW â;é*ϨG y qõ²ýýð4¯H‡lÚÈ3O¶ž½ºcz˜ ¯&³±"1Æzø©$xíüÐ{o âÍé2:ñœ¢ÒxÍ ±sÕð Y片î [½ »Fðï¦?ù–ÏÌÛ›ï½+RÎ%¹çš‰Ÿ|ê­ÉNË×HúSiI9HMܾ¨ÓsðŽæÒŠf_Å—6g“âÙ³á:-sSÔä2h5û†dDBi§±vLe iÃÚÄÅM³]l¸ìSáÝ,{úì<€FÛ¼ÓÖú( ÈÌQ*àHŸ©± KZ.µȨ"sùDÎUƒ”êl„c'àÁ¨µöbÍ’^X} OÆHðbžmÜêˆ!øPR—ô¾Ñ{¢ºÈuòJ{ü FŸ†rÏä÷1¿]ö¹@E5FƒÐó6h}Ecn«œ_ž®HS•sÜÞ¤ÐJãa\Oïí¤Ð év(ÆÌ{½˜£5÷` ê2™&h©]9×|™y²ƒ:TãÓÎU½TovŠÂÉ©IÖ±Žá•­”Žm" £)‘¹ïAºÈC8o˜Î µ36™ó¶cx@«x![«ïÈ.:Çtë2º¢z4Cž«\™a“jrãb…>gsdÚR¿ *åƒ(¼ÞõT3û
+&8|lâlC1c•
+q"åÎ1 ¯@çSLÍÇo€@K’oBO8_AH£¸U‚3Û §Zx¢CÎœ¾-jŸœi턼{_Î#o ?÷U¨‚éÚõÝ9Lë¹™v P«7)ˆrvÝðu=•—ï›x´•?Ã_]º_"Åð É;ƒÑK· Ö£ûÌLø æ†|-'FŽFù]»èÕDjºÁþæ×â¸Ƚy\G]÷kšñÀj÷Íd‚¡ñ1*×¢4<¿ñ_½IGO¢®¶?á@‘ªI]Ç,â :.[’e8yi¬ùéLLŸÇûÉÒV\Çœ›ðtÝÄœlNøÉÄOâg˜âëœ$>Åì¯aœŒºGF7rõ=º„ôßüóCÿ×Çÿù€<Ï
+ƒ´¡á½jÉ@¡ÞÕ,þkƒÈ®`%—Ƥ;:“‰YR÷¹@^ºÒ‘®ß'a¬-„ÄK
+§xÑôU¸º SŒ”I§§„hGáŒo ??
+5ÀQ<´àþœ,[L–1×U§aª–1LL.ãea|é¾j>‹®AJ ¹®JÀC‘-’ôîþ”5}ÛÅ×h8ÄBÀ±Ñï_ÕäY¢€1•ÄAݤÓ*]„…`ub"—’ Mî?Ó½Üiµ3–¡4
+?
+î.DµzS»äyõ¨e‡é¯¤ëÿP9†×žÇ•$Žæ(«6Ö1P„aÜËžX¨½ÊÁÅÙÁüMÜM_ÚRUª™Eº|B¬7˜›jG}D;”é°ø6ˆÛØìZí hÙâÄ ¨Þ^› \föô¥k« ;y›ã¨gðÌ{zÛÁÎUlº K0nÏqò>ËÙ)8; Ù()[ßãÌzÁuè9‘ÊPÆwåïs—¦Õ§wgõøwA_%ùó;ºý'Jßÿ
+Nh–ÉÍ=JI
+Ju+þ¨_&Q[÷„°˜ ÇŸKäÔ¿"¦Ç‚ÃÆ䣼®LD"Uî—A·®E{D剮RÁ!r@ ùWQ9®M’ ƒ¾õ3"|©@ ZÄ˺أã~ꉂS,¨ù´>Qïº×;·b¥ù{{@bqñ)OÐ9ÊVY솤®u ¤NØzeN€¦ =„.€œGÉÀÃFxÎ~§í”%G'²p7 ö/}¤—Šî”Ž­S
+Þº>;gqAíµw…ZRW®Ì”î3eZB„,\z°~zÉwíQšr­!Øó2D "ÃÆï¶+@0ÔCÛƒ·hç¸'ÞŠ±€Ïs¶Å¼oïèóì N¬lÂÜåXI-ŠW•ÞçæYÛSXje»ÔY[Ö3b$õ›jj¶È=óª1¨V(6Î/Þù;±rs;ÊÐOÓ¤xr€åi{Ûù
+cÒþ1\_xRÞúT{±_Ÿ°;v©%X–§¥-ÑÇ‹]ˆÔîÕüƒ¸æ·ÿóÀÁÞ4vqK±®Ó8š±d º , n–ø,Í´F
+Ô’6öf÷PÞ„5ÓÃß ÆG ·ç`þ'ãÀë[ñ$Æèü• ¡D–•{÷vËŸx8«k}¿ƒLâØN±3÷a¯ƒÉ‡O˜þ @Ÿ¢3ŒÆ˜œ½ ¸¸†%hÛ)ƒâ±7 XÞIt|BÛ„Zi7ŠL¥é•§¿³ê›L³ P¡Rµ.¿õ&ˆ^™Ç¡$ÌäwÑú¤‘¡ÞO ?dí<ê‚ÑTÁD²£Ž2eK™òšèjTÍTTƒl®R#®Ø›Î¼S1¶b4kŪcÓv$­ý×@ «JÉúÀ„(Ç“ üe’5ôɆ~b€Xî²L¤‡úu'µ3ŽÜß Ž‚¡‹Rï8c† _ëôê&ã¨7×ã¸!åÙØÖkq5†b+àìkæ ÅOðß^Fø ÷ˆÍÏVi¶«`Þ¦òa)¡)bÄ(7—1#ÿå•Îì»Å¤…Çtž´Õ‡–g÷'ÁiD
+K€Ï²'ÝÕh çVQbÖì-˜vé L@Ô[„­ÁVÐô.?´üQ¿¬Ö·îÐ"ÒÉtQðÀf~HŒ'¢˜{D^,Ä'45%?‡BAÐÎÐPÏ!f¼̩€âF`XFC™N?
+îËÍ(&*ÉøuŽÁ›.Ušý.çrIBÅß·-¼ ¨Ç”Ää,„«) ²ãpšˆáTBEz¾SÎß ' 
+sÀ $ ¢Åç%Ú““}9_è&¤%võEï»ô»¼ÔàR|DäØ‚Zk+Â|Wço›ô=)Qr••‘ôFT9Š
+LÉ;ÄáL>hOzõKÏÿ\$ §+Èä怪Îtà£0]Èu­çž ™b’.r”K ALd7HmÍ$ó×)+¦~úlÀ$ jÊrþ®†™ #ÞDÑ@X\÷*Ls½X(LÛéÒVc°bØ€d^!
+öp
+ÃÐdÆ/eo:÷‡[¾%QæqEKESn&…[B û(dPì©|¦¿u{H-åŠVŒ•ø.0¶Ìi›!b
+Öª‘ÁÝôËh1óì IsËþfTŠÇ|YߥFᩧì“‚ª1Îþ•súbÁFž¯ÂSºø•%[àQEH—Ûâ74Áìû,8š¡ªúÑÓýVJ%ºŒí“7œ‚Õƒ“â61<Ñ-(u9È»g{‚vìyÜôã;}ó«c¥ä(
+™Á^\Gg‚&j/®þ
+}<›%£ô‚ªôÅE˜ã2Pß è#ñ"|
+G®!!Â5,-þ…ÛV!hvÛ
+‰ÖDç©'¡-Õ ì•'{V·'{nM
+v˜É€²ðs:MõfGA;ƒƒ©:&µ„î¨i)­K¬’m>
+1…*oT®“pj5H‹þ=ÜX`à`â¥öøÆÆoGcER¨ñºúûk†£Áênu=A–ì\׎o'Pú•ôkã­?d¬ÛWÇ^ìè˜ÄQçÂí+î&ª3‘3´8¦N5q?ýFjÄaj{U‘WŒ`¥æ²¥¤‘ÐBmíÃ[ƒ˸ák©(ÇïÀy¼îʬUKÜÆÔcžßd\ µl™Z5=ûUH‚Ø%Á3Žb™Ò™Ì}fP‘¿ÁÒOM5äó`²Ù‚РǦ
+Q²¹!ØV“©¯54AÒ"o‹Z˜7ôâ ©Rc¶só?IÇ ü)‘Ð’b· ÆÄø¹àL]l}äâÎX@ÈŠ²$TuHó(Çž#$„ML¤‰¥)u/¡¦¯/–E½Ü¼J4‡–eÿJ‡XSäíšš²¤Ê<µê‰ò ZUÑò
+7kt•ó9áã03¦šã‰jV–܉)ï‡'å£Ë=ý ´gf 4°žã°Ár«ъ´öË[ûpa5ölSn ¶ðw»8ìíŽÕçg OÐȶÂM£ÈE~™·1Û×Ó‹–,öfZó^!(2Aࢂh­aÖxÿî&·âÝÒ‚y€ìédåÊmi_ÓwàÖZ Œ$Ž38š¼Z‹í¼6µ§) Ïïq_ ªÏ¼–~p”ÿd,†¶á1ôU+›aþÞÔ™áGQÚLGKµ ©ò‹ô—½®‰ù鈰ÇóÒ 3ž“\å¾~Ap»9·  Ru¸òtnSåű¯Œo‡Ê©5 PTËy
+‹¦Ù£}4/)ypè;CñÁ¤o2ƒõ pg¹½k ÔI˜¿ª=œŽBéR̨‡5»'‚**„LÞìÅqh´f)‹ÕÂìµnŸ äb¯7ZÛÉ•_Áb–ôbý fÕÌ{)‹ƒžòúñÎýƶýó_üû?ÿóG&ð@b«‡¨k©Çùzîpá~AÙå»hœ¨ç‡CØ@Kî/ºHµeZ)F±;ĆøCèÐ|9Ä ‹„…å%N 4q'ÔCû.läJÊŒ$ÎêGUšFí!˜Œb@ <˘m7‹C$3ÖèZ™ƒè¨ú)Ie&pô}¾ø–‡0Šà”Q¯Ûà
+ñsûï± <iŠÒ˜ö`šÚ~Ü'†áfo3²ò|Míó£&õ«€µzì^Fœ¶xýØNŠ;ÄÆ\ëùðð;d?üVÀçwmxÞæÑÎû«v;ï´@4XïRäQÏ D€³
+F™/ \ž¶IåÖÅœß0YüONzQSŽ¶túÞÏ ”'‚’ª)Ú
+‚»›ŸÎ®ŽôZ°¶2´qUMˆ<ŠÛ£­ØQ©•žWÇ™‚ßî±= m¢Ú¸å%hŒ2æ;Ѹ~Ȩ‚ wðv…°cÖu‚ȱci–ŒØé;0‘×àS¡ùåÞXâÇ@rñ_ÆËäHŽ\ ¢|(AÖ
+š“JØ|™ñtº9‡GfÔë›m~ •Šóq¥²È@´bò¢¶Kؘ`#ÐÌåÕ<œ`(è´¯ážÅ‚•)ÀƒF1Jì2vxŠm²¹vÞ g2|œÃÔWå‚LòI5 ‰jæRvÞ•ÏÀT±î×徬
+ƒ˜¯/å^öR2 qLÆÊ7 Ê'™ÁÊÔ×Ô \äV+>ì³ãºJjf^>’ œP‡¢âž %9%$¨ƒÿqÐ6ßÌ$+‘w;e ¶C-Ëhç îeÀ×ÓI¡a3’ò@³8‡`j¢k÷éˆ# ÚrÄÉ!6!è/g™Åj,ecPâ,Ož”lw„Êh¯‚)ò Òo'†`‰ÑŸý
+ìy7´øŽ„b`©!¨ 1ݤÃ-£þÙÄŸr¬ŸNÙ!|guJ¹Ýd¼ÒLò(<úºÉã=ã…™
+@$‡cY8U|ÛØÖâYÜä­Iþ¥'ˆÍÁý`^yÛÃeæ‹­48…§öv|Ó|‰\Šª’Ü&*3weˆÀ6 <Ê;_Ø"ù)š›ŽMº!üC÷^Ž¹ÏËá.÷¹;¾é>¿Úœ¶àVà¿nÓϽtôÛe;ìx,]#ÑÓiý<@‡˜ñü܉.þz'ñEVÈ,25cëVyô÷”q¾ i˜Ø*gÊøR,)>‚j‡3»¬:01²X;†‚\Ÿ\€a)¾brµH¿f-»CÅç$Ë8Äœk| gŒUÇÄŒëQDÁ•ãʆÈÑ` P¦1}Š\ÐäYZk©¬ã9D$‡»ŒÔb×m”8e„åï‹rŒ®³äEr¼ªcÝ ksÐ'hë(J‚ˆ²½Þ4¢Ì*½ËDŒ$]t«ËögÅ(]™V\ªÙŽêöxúI%%<skÄó6÷~Þå_ºƒ¹Ü!Î}ÚiI"#mJGÈ›¹üõIÖЧ=ôØk²—)·Õ“Wý}Æ@_¹ð AGÓ¡ôW©‚\4ƒî‘:Œ<m#ºB­Hnþç ec’…z±š|a'ZO¬ÛÉö&éÜ×~NìQM¢¾y´²Õ?Eçûî¼[Y ÇÂÌ)q!-ÇsšR®Ò.p\¾Ú†fàGŸxCzpXüQ ³¢iur[1ñMó”1¸Õ-ÔËú«*0¦ ?äò]Ð˾Ž ¦ïÚsrR ;•'ž0šøøH¤„?cd¼º4Z*‡¬ì5²[Д˜B\Ú‹ú ÊL Ùb7a‰Ì­píıá´A
+i¢,¾ænÂdvpÞ®.ãpÛÌÞ!g2<œSaa'”É’•H†i÷‹LJ¯¦ì%.Ì•l9¸^Cˆ¯Æ\2ˆ5ÎÉÌÉÿØôsôÑÆyW@L¹$áðɆ4ëUüÉE
+ªPCã]C”Tæ‚ÚìЪw×…1áa%6+pÉâÖWf(gVl[å¬\T´þ*œùˆPï o$šû m€tclqÒh^Ú&»@ƒÙ°KŒYÔ ’»¼YZ%
+1^žeÊvR0}`8±lcZˆ9'¾„µ–Ïç<BftöGæÂ/D ³Ò¯¥©²ˆHZ·B ¹hÇw†UhsóC #Ò‡r5†ß/óÐüæTùÌ°¿¾¡WÿÙ9DªSTֲϫDŒÊ1Xgs;—Ø7¨1[ïvÂÐç¡Õ¤›ØYV9™/Ebè*%Kòý— “¦CW,©O|zqy*”ÄE—âÚ F£ø9d(4QŠÓ†ñÏÑ©º_¦ã‹( žÁ†ÊÅíæcø¥}1º¥„WÎCçwÌ—ñ2qnñg½cúÓ…`Vfõë$<{_៶!Ä2vXdé
+„WW3†ÚÂuï¡`
+çPF9B¨
+«Ä°ÈÜgE‘YÎÅŽv|ØÜç°«Xµ!;òg‹åmøÅ=Bò¦‰1ó³âSOJÌú1@­ìs†2S(øµY" ÙìÏÞã#Qµ{5Ò4þù#ÊG×x)›ÜkÓâM¦ÀvãÄÓÞÞ¡ÇMé>6L Q†•í×§Þ Ÿøâ ôÏV½ª5˜¡`Œ螃œãþ¬¼tå?žµÐttqä)•·Ä¿”|j×$S°:2Ü1Äšéï:¾µý8pœ òŒ |9|Ø;½Ä±÷r¥¿7ˆ· )Ï”ã9jÅà ÎЕm,Çn
+Èt7;!T¿Ä$ã€pq›¹5:øloZù
+!OtŨ©AÉhÉÚ:œ5í´Š…%%Ä£ð7Óôöéˆp4Ɔ'ˆ¿¢8Dʶ¥mÎ6&S‘§FœEšàRß{‚¨S2m­±Å[N $?ëã"ì*ûeÂJC\è÷Úðd›Ñƒµ™<ø ‹!-§²vX”q‘ÿ›„ø} {~ü«bÉaµ<HŒè„·m¯2Æk²!M–”¿–°@ÏTË´2–“Â;}Ä"|¸ €ƒžŸûhûÐ$ÏÎ2#:_@lMÚB„N
+Âê(~äHBX ¤€cö{ÙÁýàÚÉlüÚ_„t€w]‚²ZAÈ¥Š[&‡L`&•‘\/ãøÿîRn6=)Ñ8PJÈf@&b u<f¾²²i͆弾„²Zev¦rúP‹O.úvÝ/wÜÈr$Š®@{ÝF‚ þÍÚwVPhO2{ÿs., óñ¡h4ªTWd|îgÑØ+ˆ*¸ñ9ôï4& ðµçNTˆ<áÓJ<>üâ h Fz™Î|ƒb¥:¼° •PÊñ;å"Ø$ˆ/!þ”Ì“YéÞĦ½nñE¥2­
+óÝ/ÓôUJœ%†lÒHoƒñzØ— =ú+hm{~h›d
+ÇýÜ€¨+| ã|
+Òä 7BZôå#ÁBÐÅ ©¨$‚±È‘òÒª_ó¨"R—ô#° ”°KÌ1†%®ï$Þ®²êtwjÃ=àÍÑ'„vs“€ítRD–,s™hGHIÍí#šq“ó)Ï%b†¶²SÈ.Æ)ÈéÁëšL_ÛN­rf]µ%?H¿`™ÏæævnØü,/Ëwì1–óe›ºC°Ð‰)r'ƾˌÐSäDG@Ïæ‰ÛÄPä[±å(“z7É/$Ü^õ,·*²ÆwÁ¥~’m Ì^Äa!fR¸ˆ¿š‰dNŠg¡áâ |›îÅ~üNÁöH1ñFqR²n“zÎð‘°ƒàÏpú˜c½ÞT-eÜ©¨fTQ8É`lciC_2×A˜{™W¶íaŸöü ‘ãÖ SÏ<)å²0¯ ï/”ùcf“o•þÄ•C6ï¸HŠÁ*?ªÆ,J0_?@Vq`Tˆ%_;~úŽüM/%°3[ªÙ_^ÏûgDÊHQSÇ™€`‡ê¬£08%ˆž¸øŽ,bé[“Ó•ñ’r¦§Õé’ðóù1µ‚̇®™ÏèôTäyÓ…-îŠß#RÁ„Üýn0úbŽÝ¼G Gi~Ï(ä“":Ë3Ü7FX~l˜‚æ}àzr eó‰‘rŠÂL‰ë65—¡Í§ç;2¤!j†O)_„¤bdm<±‘ê¢,,¬Ì$BáFØ—²!ìviê‚wÁÔÊúUOCF)éÿy/æH¾h \¡Öá™8 »Ò§ZœtÞÉ™!)l溂ŒŠÀqxJuÝøe;a*æ-Y?,¹ü49)‘¦úI/T!Cé{­Öçp®ÆâB\'ƒÂp‘A{Rˆ'F”bjq—u{©3›yÇD°¸¬Û~6NO)YiÕ'}ÎF‡%Ù/gÉ—Ø7«‹ø% AÙÍ?Å>‰$G›~‰Š».îÏìó·5†«££Êu^¿À‚™ ¦bj•4Gæ’Ä‘ÜUðH ÉýBYÔýHG—ï¢8µŠqØ‘ ïÐœõ¡Äœ,°î „á¤Ý°³; (Ö*Gþ—_`ààÞToû‰Çç÷ä6œO(û¢Ô[6„
+Ê·‰
+5 : fã“-kG~Ïõów0š<öæQ£o¤Ác²ÝÁúÍ£ Hnå¡-¥cqd{qŒ•d÷«^J|‚<µÊº€
+Wö3Ê?ŸoSáKÌMì<¿ª©NÒI‹~Òµ8H!AdVõ®f
+)ôLâºiÔdĵá—ï\¦æé*§Ñ{}Ïi‚_ÊrÚƒ—âþqŸ´Ä¢‡”›a>¥P¶.`¥’Î/ÓŒ|Œ†:ŠãÝú‡zÎ: ã‚~#¦p™ŽC?¤`ü²fà{]IRA(®pJLؤ* ‹ { GµV΂È) µ='Í1Å@|e“Ü
+¢p;ñ”2†xU JF‘øyAÍÁ!²°ŸQŒI êy#8-–Šn΃šdi\Çã¯
+MçJ!¦³¢ýØؼ qȈ"Öy¬âô5Æ2žu›4ô×Ëí/4€8SS‚×íãEÙf¢ŽÓ¬¿±Yÿû×ÐqXºæ„ ô¤…UÄæ'¸ŸÎk+ì„ã?õáAJ<¥‹§$N‚¬«"X‰î1åUË7BßY‘¦èt@üš'q8îˆ~ŒÖn>ŸSTm±ßFÔ\àHlÝ¥È
+Özú¡¦2w]¾ûëã
+¹×uså·ŽF‹«Œíû9ad ’€)Ë
++°!]N·¢ ¤<v›òí> 뢂V$|Y½ˆd(WKSÑŒ_œ_iH6³GA’K®B.UìÊ(@’6,ïf†'ˆ‚•†rß’o¾Ãx³jÙvûdÀ*Bò&‚¦C}6÷Å:€aKs5® l#´'®1<,H¨Øqòغi ÈHÏVO5Pä5™u›*ë­™o3¯·Ie¿œSPô=ìÙ ¢a }¡-môtf<mUÑì×Ó¥$ö7Ú²º #ËúP”µ\—ï\~½ÍepN¯º àµ:‡I)ññÔ©_oì‹6+ÌÍŠŒM­ø¶&û¾~îç„7ÆçHZƒt¥Á9ôј>ón”†&§ÎÅsž>p¡p2/ÞÝ`¤ c¿ê¾9~„¦ÒùXê ~ΡüûAAPUÒ^GŠº6þ@uH:NÃð‚(zºùÞN$Šü2¨Ž•‰
+1^ãWªtÑ…홟‹è2ÃBÏ˘ËkƒÙ9X§ ‚ÀæxDmÝk3äûé¹|È‚
+¹‚†E¯0ˆW¦_¹n¤ YU8ÅùÃn.?â)ü6nlI6æŸc¸ˆãŽ ƒaV ÊJJö.fèË .i(Žy=ìÔxÀÁ¬D$CÎQ=ð“ÞÁ i-@d‚GPðœË¥f(C¬Üå1ÔOž‘½_Ú™ ‰.q;àç;«M “ùšžjýôùfI>
+2c”¹å„ðwŠ5I- ë(È¡eÔç| Ò™­J>ÁÐÍ0Gl˜}^1ïKñ‚2^Ÿlp€<YÙUa~4oqû]œšBKÍßdMÆ]šQàºX¯!èÄjZn%ãE$˜¥¶XÀêq5”4úQpcÓ ¾lŸ¤ )fRÇ!ƒ…PtÃwÒ“ˆÃÚhGR”®¬%Æ ¢¾ø"l¶ <Xî}`–ü21Ejœ„Ÿ /úõq
+¡è$ðñq˜É­Ì—œ¡9 hœ³`þ8/‹ZŒ ¦Øf˜¢{Nßbš*ŸE…š
+s¡Cc–$åZñ%[–éM²P%ÍOÕ‡€KÔ¬ò]›½iUl⓪öUYú]å÷¬‹À¸%ì­_‚IH‚wXã¼]üÓ·W$&±I ;‘|»²ÜœÆq˜*ïé”DY_ÃÔÝåK e.a0ÇFùræp5¨Î<ïFwâA
+èWî9Ú™”±¯û2À*`ÕFù÷ü€T”Ít˜²ÆÒsƒT7J+þ=‰l~ÛL×e¢£è`}ê²1”ô¤¬§6cË¼Í È
+ (è_ëyÝáKÑZO zYß·Á¬Ë<ɯW±MóÜæð’äŒ3´gýô¸±Í¨?îhø3®L¯Ìsø-0Þ>Bs‚¦7Î[`U ü¡ §{ÈÁ&’ÛXÞ\·Ô1ý”¥…Q0¡p£|1N`ƒIKZôƒQˆõÌ
+ŽÏ‚@hi1 ȤÇðÛΆ3öŠãFuÉ‚ÍCù‚"c¡7¼uÐÓ Ñ}@sœ^‘xEz&L)錪Ӏ\·jäcÍ[ÚÚ+ô;cÍs–8ípÃúOõ ‘Ò¨ÛÒ$,áA‹¿ë2Oö>ÈçT6~ýŸ•tmpI^ófÿ3‹µ8°†ñ‰èËìó#³L¦×‘†ÜÌ81XZc%ÛìÙC…È
+‰Ü
+2Í ÆòzTÙpÆ#¯x€Eq•¶çóò*teÆâx„¿øÀ|q¤5Qf]Ÿ‚­rˆoHð™ŠwÑÊÀ(_ã×Í…—r1´MÎ¥(hAšŒÀ\kSo«h.NÏ‹ŒÄ±c¸AzMƒlVT™ت?‰ç¥äŸù%™¦Š¨ô£'·c=謓?× ‹ =@ eëÀ²Ÿ%f}ITŒ*.7v+’H ––x$ 0—/ ‰…ìZ€öÛ"1g¥(hm „¯EѺ“_t»x
+ŠTHt¢ƒÀ`,WTTUÉ
+7U9!÷èÞ†ñÁÈZ²ñæUDÜ&ì°Ì =·æP‘g¸’Æ·Å^É˨ö—nE O/ÿ
+|¾Ü»@b<3+f&÷IU/3•0—ýkgˆ-Öép=e5ïÚ_J8£kü•Ý9]J$®ó¾sGÍí6wôÝå¸Êï JBûòWÄ)¤˜áõç,^,¹q¸‡Ö41$øîH±O–·‡ï»}ÿæFOî:¤' ÿß'c^}Ö[gDËø(Æõ5+ ^²PâiUt4 1ŠØï8KÐfÄ›YåYp ,(v“=L3WPÄëaTðx“UáP`²NÁxÀ°H^µÝÈ$G@Ęj¤—(
+a|'#ßÙŽýM±•Í­óc….à˜¢.½õZÞKrr{ùµbuøÒÀû1·!\Ç&%í“ R‹ö§.  H&:QVZã¼Ã/¬,ÁxSR•á°‰±¦óª0âÃD<‰©vºÙ‡¾ã¾Šå€»¼"Ù$*E…צ«ãz }x/¸jc™­œzL)RÒ,!@p#*:8že]r«™AŠ<ËB|ƒ­ 4%sc %hKÖë[|'G¦ù/x2›{N{,ÿÔõ£Û$ƒ&íb^i’Zåƒüß`¾OAÆÍ‹û¤2™£¨ÊѯÏEq6r(«”hb´ü¶H.ŠÈÂIqeõœ{sÛ´÷r_éÉœä ˜SW‹²Ž†kù«yùâ>kÉš{•®ídÁÛ9©ðOt„0¸YJ¾Pv"ÎìJI`R
+3¹žG)1†þÍ/Ô.3dyw°ðÄ(Dúò– `
+È5ö¦"Ðs <YòþÒ‡Ýz
+´Nyð_‰ŸùwâƤ©o·(?€P"%‰4oM­ÖRÛf¨¬Ä%M²³„ÐardÄœ¾J¬ŠÁ_k}GéÚò?ª¨°.q
+_¢©ë©EäsÕV w /‡ã\ãb©å`¥q^ÉÞT¹š(¯+;ç
+—mÅ«ü`ÿŠˆƒ¿ ú’Z#Ë_ãž`ä.½+-ižÓå)å2¹‡ÕdºyB°´^Ü 1d»„à|²âj2_1¼ |×’5O^ vêÌ=‡‘ãVX‹\í|ª´¾Áv¼Ä‚ô
+2L9Ac!”©À3Uïf@37Å5T¤Q•F6™´j¬3Nñí¹­äyŒ©,X'¸©m ‘ÅY‡ZuJ]4z²#YWÁ0œŒ¯” ¢Žs¢:'1^Cú1+®Q”êÇW B&F]‚C†Õ@±úáSò’©}Õ!¢e)\ÞfíÃÿ}$m-cßt”z¿dæ ¶SöE÷ØÐü°“ ‹/+|÷#1-:DxŒìfê&YWÝ3îœs¯çknåç½é¨a@T Žðù@Ŕ鵹?(^²ôçj» Ò
+
+2 Æ%¬`&>Ä;&­“•5 ñƒ(©S‡¼øÉë:0bŽ”_î“Ô«™U†¡ñ4’ö1šU#sΧ»èûÜÍסŠó ˜JM{f2uµ‰PŠѲ±Pø~‹2°ra!Hp6ȶkølæÈÚ#瞨†D¢Ð²\i(Gò5¯Ê:–nÿÇ…û9A˜&b϶¿Æê\C`\Zízª5ÓÞ³Á;û Oó3ži4¤àƒr{`»Säd_·ÁVYæ^ž%÷æL¦*jÊ*oç&¶ÂÁF·ºÏJ+<Â
+cƨ ~ÂÈúz§;Óñˆ€Qƒ¢uÇäHÄTc³‰aVì`5O
+W^þ‹Kh7ºˆç sq FšÖ¤áã’UZ{È~ºù"IJœé!ÝÅ%I8ƒIžm×Ú‰KŽèÄ%Wô:Ë‘dã±Bš="Ы
+Ç{ÔQ€gp¼Z¿…Ø“Üqé÷žùÁ%¤¸ ®_ø·?à’+zÅ%$¬kuˆ‡ZÉ.!ÁÁxª ,n¸¤(¡f¯+º.)!Í Æv­.æ8©?q ùbƒ«pöÏ¡ ™ÏA“¡÷âáö"½a¯ù‚ÀW\B3‰Sá‚ûW\2؃‡3`¨ ¦_qI’Îfé)ÅÇ%WtÇ%GtÇ%}rî’8ÑÅ%½œ(ðÅ‘þ>.)‚$‚š¯Ãš‹KêvJ5iŠq¼‡9®aÞqIukÒˆ”˜ùçP]Q8bv½â’ª”Gи”÷¨>.©Úµ@5…‹Kj™X»¾År²—œž:qé÷d¼³ôBîøÆ>Mµñʯb.³þëŠVÈŸðÄ\Va“\rDpH¦|tNoïºwDÊÓO²ö:aÁ3lB1u†ømÖòÀÉwZ¡ÔfÄ©)L’@[B3°Ü6s©m‚ŠÚâ
+7":”ð'5﹉Ÿ1a± Üü©IÏÉ®šçQ?£/¦‚SûC»Ù“|Í‚ôtã`\…xœ“k’$:å’˜ “FÈ!}8‰˜ßKðX#‰×4Oó‘ßSDwµ<x¥];Œ*Ph”ÀzEH ƒ€Áo®$ÃÂV˜ýåÂÚ£I¹\“áaªôáÃpájãòüŸºÑ"c+›L`<Ãèݶ%ÖŒA-2Ju_Å_ Gë;›‚Bâ@,Fçpj¤x¥í\EÖDÊ«æL>%·ýó#òŠ]0°/Ú2§ü¶ÈiÀóº·D7Sp{ë.úñÂ_`“À&Èn^Éb2¥c{ h¤tòU&¯uDË?¦Íí,Z)4c„°%Zº²RàJ¦]d†}Í›(J*‚÷9Ù'L
+ã º[»ƒ[y¿V🠋I'ãƒal ŒÖ×\Åì Lý‘<˜GdrÈX7ý
+ƒRN»o*$[‡þÃAJpeþKn ¬›³R ê1…ˆÙ6w¯rU£VùV ئ%5\E‘ û’$Ôdž´Cßa3EÂ¥ q”vð¤'5•&ÉQËÖM.ùÇS„´ $t¶ måiraWÛs‹8ÍÔTAìl%‚Ǫ“yW¹ûPÎT4coEµ$Ý2ÜÕ‚¤’Mùü6>@ÝQxÙ^<‘‡K°;3†C†v…>«Æ*‹¯À~ —~þs)p¸Ç¦ÍœWÞX«ª…ì° 8pf†‚8!ÇþÍ8îf¡RB""!êÉÀ¹mäç¹€¾L$ßðï`Ú8ÅRʧ-ÓM>6ˆØÅ+Á¿«nÁ™xj‚Èg¹y\¸œ1Õm}õmUѽÁ'§Ýɤ´F—êØ,ÖBÇÁ™ÐÈœÔ}ú2œ–Ìp f:$— °ÇUAð@FQ€îø ¯Óá9E!íGibBÓÔ». ·PmxV&;kö|wª@ƒAÒÃ#L3$pï»±¡ãÌŒ­qw†*¡À¸’ôˆšFÛ aí‡PÜJÔ±¶~ÔÝU*û%Fce™ÒæÃc}óæ¿£\C‘ÉM
+ݤÊK¤qz(°Bm+ŸQãKîÑ«¡$]²ÜÉ=èÆLòFð}Tч³“Ѩ7ò:‚”«+3‹8—¼+Z†«àʈ<ÔLªß•Ýw¹A(DgÁÉ-ã”°{“ÿÓÕŒgï 22teÚ
+Ùª¡eö"«BËs!%›“{§H}’–¡ 6þ´Ø…Á‡,Áæo·*ÿˆ°—ÍÜ‚¯ :—OŠâÿ~v„AD8êçX¨3W¥}BïKz9# ¢ä—x.6߆I:ÃÌJ+-ïg—» ižpI™¹œdB d"2ªtøVcuF§ö°&10¨2>§Ä"¾“›kw-ÌÄÐ8f6$PÃÜ
+
+¢©ä2ØWÇa@ŠÍZv
+*%ù°¯ƒ3/=*<w–x¡ * _IG™òBRÉÕjãÈJ¢²Ã5žÈ|PY.ŽƒP®.Å4ß*·¥6¦ðGà¾hà·Z*Ù…ù’>)
+I!-+SªQ¸éÇ¡¥E]™ÖÂVßv W¥rL„“,k™t%´M£&ŸoSÊP±Þ/=UåF¤Ê¤iä¶L&n¤¡m;SN—0@ä}C„>€QÉ(
+¡k¿Ä è5¶Àj¾G}4Vë ’‚‘¶ÔIyPê7ßΤü­3?ƒ^^˜‘^Fƒé € P¹ÁôvÉỆ«–¢CZ;[ý_Qy.|G ìI™e‰‰)²?¬#hÌaj€ð
+&‹äÄÿÞ1U6CŠKlõ ?3deÊ%ýU¥$äå4}õð{úcƒzÇï«~ìd*WIÉN þL.w`ñìB<̪Pb/ÿààuÉ˳B¼\.4Qíü2é„’Ykj¿êØÅÔʃe‡@*œDuAû2Çì}g„ (ÑѬËȆû1H‡VŒ!ÜÒêôî%\“þ"Ú“. A`åëYrÖÄ —¤JÜuCò@)lSÁ‹^rs”Ž¯5iQ¤Ÿ•˜«’Öšƒö…„5n¼j{€`wE^ÊÊÚêš<—äB‘Qëü'À
+H‰l—½’$¹ „Ÿ@ïÐŽ þ
+É;ó ½½¾kFŠéÞÙíéÊ"A ‘H¦3,ö¯é§Ø#—E·°—E¶ÙóÿúbË5òì¯þ῾£önódÏ™éýÖ±¶Îl}NËy¶û˜/cÇÜ Œu_ìø†¨ |µ<¬|µ÷§uzëã°N¬áÄ>Íã,BÂù°f{y®1‡=ýDÅi<í¹€ô`™hÑ»â bQB¢Y&'ìmŒ±ÏY;<ë68™ò¾ŸL:³ egÎBÍIV×°³Ö©uV_Cˆ±c]„»Ö±íõÜú ž ¾ûÌ1ëùñßûøí±Žßh" •±g­ã§»¬{=¦*ëS¯"Ø„®X{£ÈCŸ{}ïÔm™â=kZ%„pÉ+ŸPÊ ëyQ,1›Õ:k“Êb´Ó“h‰Ù|GÔN©ú"âÝ)Ëþ°ŽñE$¹#µÚ)–yBÕƒc¶? ŠvYÀ×ÏN?QÇ|ÐmvruÞOÀI‘ÒZ÷¾s:MáJï&ßJ/﹘ÿQÓ†A’Mž-·u2¯sÜņBP>ª‘4éËÍG ±‘tgæ3UØ„xÑN,ìF6d<ŠÇwãصÁÜJ*+LN«wh°–™}
+ƺP›<Õ2æî…@# q|ŠåÚˆB8«"é!àöúÞéêµI½€Œu—!šùÌ Ô»ˆDÄåbKLÔÈsÜ%6ÜÓ6Ï÷¼‘†]ïIKƨÔ”9³Ï Ø;|äH+ZïÊ©Cr·8|Ó¢î°çHo¨´ÃéÉ
+ÃÑ;zt èÄ´ƒÞÙ—ª<V[†D‰v>ÁHõ¢8Ï€£‡FAC©»þº,ÑJ‘ˆåil2ž$T3‹·áP×Û¦ñÉÄkŽ)ã„® e]Ž
+ü
+ó†©U,ybPŽ‰­uBÃÿ"BQ ÁOEHªN¢¶¹zíIš¼$ÅŒÂBQ¥
+sQ5ÙÏ¡aBIÉ,ûȱÐØù Íx,ÞûCqKò!s2«€ÔËU@l–â¿¿y±ëiIF´zý³¡ãp`0DK¤ûíõÜ^®K½µ;؃ó4(Ç‘ªkªýDýí ¹ <¸ÖñŒ†´­"ÀPy0BóH9¹zHY–¾kþTÕ>!—É©#_—£7ò¹d@p‘!ˆÆJÝ™LFŽ…k]’Ó.¹ß§Æ0sG"‡…Éoˆ¯[Øà©naP,>¬£[“R—פIRÙ‡¾?‡îµ­?Q(ÃK|ÚS%Ä÷™ìòÃùé!ÔÏë¾Fzð– Ös)@û¬¬]"šþ˜ÕEKÓ5tþf–¢"Iˆ 4äžñÂÄ6z¾,>v,Ú”é¬Ö5íw_‡å¨g“Y„6Š}×g_OÈâ4°®“bð˜¬õ%ç tw`à CÉÑCî_´aé–Ãf¾Ù3c<,c­Ç¾cŒã0®xM?eÎ'4ÑUÂqQ°KaÐÞ½!”qúŽà¸{2œíÃ:TŸ:vYe×°—O'(XEæ8Ç„¦+ýŸ,Œ¼½ä
+í( \îØ$з5þÌt5Ë›r®‰Ì–M,¹„×”«Õ=¦ çÞ)Øxd%S‰œRLÔÅ_Z¢9KèÖ
+™ë^ë I6¿´í*†î¥ä»SvêkN>7×÷æÚÿ·Ó’gÅ×~Q¡t‚º«h¥X¸¦éL_=÷ |ÖAhÜõ,ç)íP3@5~ ¹BÌ2_wQªÛÑXÝ¡¸Êcèwå’@Ð0ôJ:ÏÐ\5%¸]Òbù¸½Òuäõl2UˆjÀu¨Âå¡ÇáL$Nz©‹­f8‚/éolJ¢ÝŒ4ÜuÜKЖ[˜(̾îÍqÐKC‚+B§¬£+Ý‹q ‘ºœ6ÃV‚Ç÷XÌ,ÝGÜuW ÅIGWyü.[I-ÖWWƒ¢%%U\Þä¾~ØY¯Wü<à÷zÀY< ˜û¾Á™vŒ/—V(¦‹Pl÷ Žf6žSëø©Û6„æìÔ,‹B°Àâ”bêVÇN_vÊuK“é
+uˆš]"ºsH¦)ÅJ´—Ca¨‚bÁWR{ý>ô…*‹ÇnH²‰ÝOï¹F¬¬Mˆ(tf—k#^pÈœ8
+åBpšó½S»D¼!W¼¹Y ¦¢.³.ÚÈ™ëzø_ÖË%׶«†¢]9Å ÁÍú ”@ ¢P
+I¤èDïÃÞç"Q • ºoû¬—==&ÏWÂcÑÙ;Þ7h÷Eí½Rà jUy6*ãy Fõ#ùf¡MåA®€z_ñ:¼xw^¢&üšb°—N“ CèP9ûbýÆ˱hØ%gKÏfo–!D/Ž;ñZ±Óñm@X„
+fÖ„EAT£æ-4™?¶­ÎT""šã­Ý0—F8„s§¸+Í}2#Dou|¨<åEÔö)#bxs’Vr#,Øq÷r̸ª„e9nF”륡fFncW•e—§U°fpW4ŠŸ ÇÌBÍ%ª»¡®_‹êä9[®z!ÂóiæÖŽx[Ï+Fyîº*–v)p õôðB´˜6“‹íœÈd£çètɧ’¨O7Ћ\W÷ãÔ} '†£X4þÚÔÓrRÊÓnü
+…"¦túýÔc‚¨ xUoÕNWa|“á(ÅR"Ô†šRX«Ïè,çTA³°×»Íªò;“.?!–ÿ ö"âG~¯E¿š´ý”bÌîˆÐq9ËçNN49ŠÄbÀwc?ô6•æÔ-×¥ñ†;7Ê*#Jug\ÑzŠžQϸáTà
+-h¹ó$ÖÑãÑ$‹¦X ‚žeåNÌÝŒ!×X­”Ï£©Ç+¤ù0­6eÌpÛ¼ñkh‘Ž6[pb¼Ðü@!ù
+Ü4¢´F•1sýæ ʬ€m÷Yã8"ºsŒÆäΈˋ‹Òç™2£P4ýG+õQ (RÁ„Æ–du”~;ï‘̾Nj×HÜG_Ó®A—]úøƳ‘Ú ÔóL¸<”ÃNv8å‚!‡ºK3§Ë#
+
+Íz&eØ6ºˆ5HLkª aÿÖÃ0à ú;íèf¥·“Ru‘
+,äÍB1i?*å¤o†qsêÍz.[õ(È3-ù5ÿ5KSY‘ð3˜…wù€mI]â1/T5x‚âÍ ÝHíÁ
+3‹Hoo9âNZKx åÂ÷‘Æ›0XXTÛ´»wmtûœŸOÂÞ> ˆH4|~ˆanMáÀü0¬11e@€FPÒãDíïŒP*ßëFÉð>ºñ‘}_Yfj€FÍ×»f9U»“ëNs h1­%ïO'r¤©Iàúšž&óþ`VxQF]Ç:gÆÕ~›w~O烨«wÃ*PøGH2ä@‰µ¤+îXUwS»Ñ‘Ê!5!} ëP˜éŽJ¸„êyùK®ª­Eº¸^«¡-8‡µïD‘ˆ²3ˆ¢ÃjDA»-VÌ!~¢
+D æ$´Jr+Òzm뇙M¥èÃ!óØóLçÏŽw%
+Ã22j¤—ÃfåN’¶ì¿ó,¶ '.W³JÄÍ;•æ j‰ÌňQ9éë•‘Ùëä'5ØAô‰5©zuý¸0ècZÛ0ڤ촠
+CÑ/jëƒ]é€y¾ß„¨Hcñm¼þÖzžøùrðs2™?Çb ¢8pµÜM¡¾“£Ï ñˆšæ5¢ìa£žexIIÙÏ9¯oÎ9Q©Œ€nŒè>qD´x7@çÙht\@˜Ti¢Æãâ˜]Ue'õ5®´£x¨oF7  
+ø«)ý\­<µ&ú5dÂ6ã1ûÇÒ|2næg¦Jˆ)Q„Z6Åim/¼~Ügƒ¬ðÂŒÆl?ÚæÄ)H5BîÖ®ÐÝÒNç)^1sèñò¸¥&DÙ&¨/ºÂ[p¥4¸I‰€_*T2Ÿ’"uµ2¹AYC³ÕÕÇO—†µ ýÜW«sc£N·ÐFN&i®…ÝÛäzŽ' ¥
+UZ¥îJ=@%÷ˆÐñ±iÏg'è.TÒD‡Ux¢ÐSJ±rÌHU"]u‹6ÿ^3 
+¬†&šdªŠÈ’Z® z¡f'{fæ»I
+JÆŒŸgO³þùN@f÷è¥V)
+majßi˜\a× |RÊi—ÛjnTÛ{NõÆwÅu¼³¢žl €è}ç¡V*¢d°æµ'Âò­Š@(wD<T„M £ÀÁ±~Oº‚{¢´cGmÙ‰VE³Î#.¸vDêá¾èªŠXç)¸±.I‚ž^ïƒ Dß
+ì-Ñd`ocd©þÚrNmwÄŠñá6N:NûИ9Ù“@éW<<·×A Q?cHГ¬½«Õdt¯hàeÒ•à[ðfª!ªÒ›ˆU`G­CE\Õ•ù0µGÙÍÔ<Êt"¸ -á§Q¸0„×3ÝÕI3½ØyfVÈIál›TD$=¥Ø¹ÅþÃ’‰ZQÊ›Ž^Q#ƒ*ÊüÎÊ’Í<TÄœ¡´´Nþz76¬¹#JôŒqÿšùܼÕ-zõãt¸‚×NÅV®6oßw}=Õ&ŸÞç_i³)@l–F¾O˜âÍ
+ÓÒÓæ‘n*~§o%Ã)»ˆu–àIOÔ¨õòÎ{–ÖÑŒõ>~¸®a_<Ò
+˜—?6š¤³Íq«Õ
+r!-5 ia1C2¯÷‘©rÛë;y«-ô¿WФ…ÄJ®‹±Ú/
+
+D¶pó:
+ÕÌ8¹0Ö4zòŽ¿Áf/‰|>'EøÀ h‚éRÙ ¡HîŽZå!»UoÅEÊò…;ñ¿&™»öç¿•%ü>Râ10´õ÷jçíÙ#uÉ1Nu_Õ´±“'Ç4ª"û{µ´¦g§Aëwg%‰ò¹¯û£Â{¢HìyòÌóÁ
+ØS˜€lUý}¤cþŽÝó_y@>âÏúHXî¹C57Oô@2¨oçvÄ8‰.;÷?Íÿ²/—"R¢bWÃÂ~äòm_^ýQì5Ž
+…²&oÞd=7° îÖ]Jæåîì¬
+_¬Êc`+B#֎غ‹xߊЖ7òî“ü!: ýœ¬µ]ððõ– µE¿õ/-‰G{ÃŒ¾«šÃ-ª"àÞ"–ºÊŠ/88‡Ó»‰ç î!ΡkæK‘&ïTfPÍYš§à½Ÿ4#¢¶rŽL)¦øš&ø†›6auj<¨7Œú.f©ƒq€«üR®é¥j——2…iÙgh0"m) GÛõ§ÿ!`¶Øh”}h]5|ŒÃ³l¶¶P|+±L\.Á´öæ€çûÜT’žÀ8äªüwÿ*©a1¢¤Œ½ "Âe4,” ..üxJþ»ÎÈ=…­ÛñW­£–” íY?}¼kýë%-ËQ°²(é*X$a†Røx_i„Îp6´–[–Ìt\âáÕDQH5ƒ¢¶ç(ÁùUž›8L„IØœð)}ŸÔC™†1î“Þ ¾«9~Obër’yÉ,%j•Ë,õÊ3¹ÌD´zk"à`0­ˆ}[ƒ1ZE”Úè…§‡šø‡7"Ûf€j½ ®ž =· ÙœD+é(¦øâɘ„wlní­¡œ6lüøÎiîæ!YÓ´µK¨/dmVø)=­Ì¸ÎϬ»“®—4Q3æT«ó=ã,GÀ½¦ÂâyÜOßÛ1¢bï6raó¿¹Öõx\\D0ü%VèÈùÜ1¯ò’‰6o³±žFÂ×bÉrGpð…§7±
+Fõ‘Þ:’ø¼ˆ¿QˆR¤§¢¼$'ELÏʳ¢íU†EZ;Ï µzлJg8ðZŽÐÒ»f*{?­ì]E kRQ68“† a‰'âÚi8¬JSû>(ˆ=WE¿o°ówÎ18PF‹¨Þ¹‡:t«0sD“É€Ò‘óHq×Óqʱß‹ý/Ú£$Ci[ÀAlŸÒÝ×( dÚ²aÕ»™-/­=/ PòÕlH¾G>wŒ}™PB­qí¦…DôxiÖúç¤z““¾,Ñe#º
+ö•WÁ‘®D¼gû
+Ë%OÛvKÞ/_­ÌÚ¶í[G2ô÷3ž ßÓ+jŒIˆ½!þÞr3•æüƒ{¥ÞÑÚÎÌí%¥ÈÙ¾z ‹¬òVV9m™å<YÊ"Q¤áÐEè^DXì†@å˜Dç~ãû/’—‡‚£‚Ö^*´o°á»“¨Ï™Ó "&±Ã”â
+tf
+Ø¡¯¢­:ü,¥¨Ÿ%S"Xñ„Ð`$ ŽÄõAà=j»M…ÍÊ”Mqr›xª §ÇþGd=ú÷÷~¸GÌt¡?Ó'ë\¼ vcœâë¼?j·õ„fǦ´´Õ¢Gh3 w:æíï1 Þ™"Ô¢žJ3e¾ÂAÒ´“@e–Ð%³ §îd±Mt‚ÌLz;Y‚x»v£ÅY†+B^f¿Ç:%\=¥©ßD%‘ê)‡ÕÞÝ©Yei¦ºUs—¹–¶)O¼7µ’R SSˆÈv-—ê劽T1¢˜ÃòLûd”Ë$øØhí 3—s’´
+&Öõ Ñ l‘£¤@±¡æ‚{6¯äiá›
+Šæ™QŠ@,40Â̪µöó K¼è¸Òžroý, ¯]ñƒlE„ñ W:,ú\V”¡ ‚ðNÒ—…Æó@ýÔ!"¦phÏMáջ؀"ˆ4Q&­@ÑÌV¢öŒyú( ‘ êÙ–xNqÖœ‚Ð#¢öt•uÆc!¯ˆÂIÔ`”MHZfyÈKΣ‹i`^WB|FÄŒL«9ÇÒ?€àâ/æGÎjlc„©"
+2YÇwRxõ‚Ü’¿Â6U³Bç"1éšO\}»ìÝÌD‰½7
+zÄñgXà­¦ ¿BÁº„nѤS¦fë°)ñ5¥Ô}À\åZˆG½M9TAÐgÁñÁ.ð
+ù?q~PÒ ƒj¡ƒ³*@à~‹˜@:c€§(Pf-¬v¹·Šƒ5?³Ð˜”ÏÍ@¯œë™€›Ir  À ]d^„brµ8Âóp˜, Ù0vÈV¡Œ=â0¦~2RoYFkf4i4¿¶ ÿ{D¬DJÂ…SrýÚ<.Ý-1¶\m™”lÍ !sEÎä6Vmš!ž¨¦Y1iVÚyÏ“E_±µWZšµj˜!j1O£DŒ¹Ó iÜAxyóöǶëºL,*Æyÿ¿æ°† ÄgC¦L)/”ƒ«ŸMÊ(F·°z A¹¼‡†­Q"óí¶L,ÃRPZI°Ôx:ðjÌÅãò2&)ò²)Ìû=lð«'B
+$™^9%ø§ß•
+¼~]"½ë%bEAì4`ü1 ÚHœç
+¨bYa#Sï €‚#Euƒƒ(* ‰½¦-š$Â@¨"  3\f òîh?®¢x6ç PÍ@Vk>èð-PõHÔY®•öƒÐ$bqXšÊMRÍuç@Sù*©è^1ëª;Ë™Wb‘¾´ XHÚO·Ì,pUÞy¡¼sÔç5×ÑÌTÕ6ºŽò„" LaköuùÜY÷Jp(Æ6 YDÇ”<ˆ?$Q‘éF” ‚Ýû•iÂ}ñ~P:ìEYƒö~À. ]06´€$äϨ…t²eÓY/“$‡r
+^¥NPÁ™ükßÉçw&@U;$Exã^tG×âà 0/âìI8å°Øº7zÛ·ŸØŽP‰9Ê<Ó/“˜¿´)Í
+|w¥TÕ'‡{N”Ý"*d•øÁóñ“Fñù>ù3ß©÷
+œUD„ Ä>õT.ÿÛ‡Lêi ©BÔѳ´þx!£
+³LEv°þªZ 'xŒŸÿéŽþŸÁQ†Ciµ¢W—Ù6Ñ(˜Wx1D{BÇ *ÎÊ0>?¼”ÌÏÉA:U†Í¢NÒì:Ò'ÒA5=ZÓY{Z0Q¬(ìOOTH¨âÖÉ”Á
+KÿäF´@lÔf BÀñ¢¶\RíéÓD­Ò¼íÓ\_¯Ã¸9_A:¸áøƇֆæiÑg &WÌ ç*Õc<ΘbWš©Çy)%-ÁƇð”•Møû}Òqy 0übqäy—ïpE;ÕU¥"UQG»t\\û°£DF²€‰Îu庇æEz¨Y€yÜ)#S¯ÀÐlHé¾T'#PIPõb$0ÈEU¨
+>62"Hè3´tÚh›eEtƒ¬OÓKÿgŸ‡2‰v (èmˆ¢O®c©T;½¥`µ¼'´%üŽð;ƒz—?úÆbÕ–ÞÍ\u4QÃ-¬Å•ÍŒpÚ™²CÚï4úu1³=V w´ÄÕÛ¦¼$/ˆ[8ç´ÐNÆš_µÉ-1üx¤ðøh­¿þ\‚< žü¦äŸß4-õ¶ñh}•uq§¡{i©h ¤a±ØÓüèqȈu°<‘€óÚáËb
+H ÁîÃi=QÁ 6×—]‘h­\È#Ò\zæjVùDÄùñ Ÿ}B*ÇøDA›4„^µÃ´Ç»Mx! ƒyùêc¾È"ÿ¦¿ìúe‡\ò¡§yŸc ³E¾¢7èˆÅ´ D*9§£z¿D”‹¸>kô’F÷·àŸD“(" %cPŽ/°dŸ¦»‚¥dz?¼ã¥; Ÿ|wzG!*ÔÜ wnÄñoÇØ…‘#Öä DÇàJ\í8aÍŒ+ïˆW/¡ÜûÄL)éëà‹P vâ‘ô¤¨Ÿ¹L$·Ao¯¶Õ´¢(o'dÓ¿¹¾ß ~=‚¿uC0˜j
+(•ãyÊAÿä¸Î;®Á$oˆ,&Õhû`‹Æ]fŸ Ò‰4-çà/ϽpãÆB÷ æRy r©ãnó"f‹Y †£½ͤqÚ¶8mÈ»ñ^Tp8œðuSXÞù^šqEG°Ëú¶Qâ¦AX¼{L:ý¿>F»{~¸ìÙ·_ïǦ×mž›ùØ„*Óù€ÌmÅÅ‚=¼õ]Þ¸j­¾ ^×¼7î&¦ÏuÆúµ‰Ntø æÁ_ßSÄO@(ZÄv!A†7AOÄÔ(VZgÄd¯Ì ˆ?\b`«aŽ D]¢¡Êcõźû‘/EÛI!Øçõ±£N…“é×;’Þ©sBWäR¬°yDÅ~=xIé³3(Bן@5Í4`EÅmÊ ù¡ÁוŒ1 "¦:î.B±KıM árCÔ4a=ª!:Ç0ÑyŒ b#®òD
+Dæœ ¥
+Døk×Ø¥bžP9©î¶W©\›Î»$qËÃ}Waá‡>cÖ)È&}1!¨L-:íâYuQhqÚŸý_µØÎú‰Ò¯í0ŒM±¡¼Q»Šäc¿ (9Y
+yª¬ôr†ï¨Mà?œ`•¢ãe˜-Î0BéöŒ¥µã&‹«p“SBiÞµtΘ†UÆ-N{¹-D@q…a ÔmÀ„“kEàEz ¢Ü 07#˜@`¿Á[Äáýÿv¢0'PSÏJç
+ˆâ´—7e˜Vž¥Bd"F„³¨Ž¯AufË;!æÞiÎúrxî¡Â…W¶ö<Úà Nò9a솖Ëæ!­ž/ˆ‰9*ˆº½ö+à| {¸‘¾ªá3ãðD)Vç’kå ú
+#<¤3Øc4˜œþ‰økmfÁÖ^LÊEi²¶ãŽ Âc˜aà¬ÑÜqâ²ÌEc†ÄXÝ9{öΆªà
+:mº
+²ÿÖË®7¯£ŠÂå½L*pæûœ)W E¨Ôª"½²¢$E4Ž‚ƒ”Ïóì9v‚¹£­]¿ï¬ùÚ³÷ZkÃÆçeL­ÆK³€¶<yQµg
+•$b/wùµc§m™3HáJçƒ$ð8dÄ~cQ ÐÓ5®Ž
+'-øZµ¶Yñ—Õl+˜F®çÈÞIÇC¯hM„·àÝZÚW.ÈdË$)DZzR[N<MÏ»ñ¶}4‹V¹.‘Ö|W=?_ðtT)šºOA/‹ÐáŶÕ2k'Óœl´(²=Sh$yŠUÑ~jíA Ír&ÂÑ“Yð’?W´1„žær—ièg4ä#Ü\ƱS[6‰6–:vî„:;iNÇ"zYäut[D8ÛòvœÂAœ•×@l q—¬X‘£³À{~dÚ*ü %E`µ î¢ï䙸?‚ ¼ŽÜ…\Þ½Ê1c ÉŽ j¬C
+6ƒQLž8Á‘ª!7„súºÓ\±Âßithú¢n)å-.Lƒ²P6–D”‚^Ó‡=ã@SM¥Ì u@g ±‘À"ð–@…c ¾÷;È’f”ÖN½›iT<ëlj ¸hò+FÊóW»bWËßÐbÇɤ»åÙ“68̽ø¶¤¶T¦É€[1
+éEºMeXÎHuò¡šêgÎ[¢¤”îv:¡H¯@u$¿»„áÄ´}o;m*šU<K¿C ¿³Ÿk§²ÌÞ@ÃŒž×Áë†à~ü"“+E5yÔ_‹Šh_ùz ÆrYÄåxà¬eY%#
+‚½ÚB•}¡øçò§ã<S‘Vl^¢&–®bèšiíHO8FiRðÝ
+âé¹n õ“@¬¶©¨r¿ßH‡ê ¹›Â3oë˜Gg3e[
+!±¤åXpÝõ?„—Ù‘+7 ES™¦š;ùíPœ>hɶZe¸êyúŠ Üå6,W˜äòv‚а
+D3 %bõ)Ê»½ ŠD‰½}Á;ð3óæ±IEŽ"MÊ°VåÅ’Ð!·1%ÜÉVÚGÄæºvX.}ngÓ$¸ÂHRpQ¹ÒêlÍ»1Ä=ÉrxPÈr+^¨0Ó«ešÑlpM/E÷äÁý›Ž‘ÝóñÒh‘¼Œ€íE'®"´
+û…}
+
+ÚHE|w¢éM„<!¢Z êƒõú=‡«ÊHD© ¥
+—6_\ÐOÔ‡n׺8¶ 2¸Œ-7š»†¾ p@ÕÃBPý•w(D‡<©ðJY'Gb"ðÈT|riwó#éÌ„©úiŠá{ú´?y'ä„ú¨Ò˜¶/(KR7sH—Ab-Î ®"@”/î4_ñüÈäãã¢Ôγ¥FŒ°´d—Ãñ¤îÌØéM—?­éúÔÖ¼6€'†®†<„% æit«FA@Ëeºã,
+ÚML£Œ]ÅèC5jU­^ínµ³ðFÝ  •‘SÈk‚R›3km™þ… GèĪZÓ¿ççÿMÓ+™PW8IDÈ:$ÆZX6þíNÅÅÃ^Ò®N
+ÎñúD\eÒ»<ÐaÌ ŸëË:+H”G§9|sÖÅG¢oƒ­ë àŠ¼.Åà>cýÝ\ÿU£…ƒÄèób?ã/jmL'Œü%™˜¿†2BÑ9•ƒ*/ŸæÛ`åI0¼ #¾¿­B¶‚Åü?Ìi¡*—ê˲þò
+] Vi@ŧˆv\"Ôä÷NH–©À”DÙs¸ì‚UŽu8¥)4õÑš`%jî6D ˆG "ä(xÐ{#ƨ:L‰tBJ•Nôî@qê  Ç¸tÿ=ŠM—©³ë¬QŒ:ÙâÈ7B4£…«Gx¬¢_ƒÿyê=[Úw¾Ù.zšñ k*šT^q¿xçDo¢w2™#V‘~g°næoÆ-á
+è„ÆÔ}~ÏZiàí3dy”õ\ƒlÁ#3J”<ECBhyÖý†À?]¾‰Þäý&Ÿ(èÂêmÝ™yZh•nÅúã‘å²8¼c¢Ä¢ãq¢ø_ãÑ'â5£1ŸÛØXÖCNÑÚÇÆ—?›±ÐïÈXü—«>P¤‰C°†¶*$»/`¸C«/ ŒóŸ_ƒ7ÄmP˜"+EëÉ1Wð|Yò¦×%ïnÞ¼=Ù¸=™W]5£+îÒ@˜Tltœ¶Ý6Qäǃ#îÑ]5~51"À¥9Í72°öBPÑ"¸R(>ï¨{¬s­¹‚“õËÜç\SQàR»Çwd¯h¡ÑÍ}¬0r5î{ T]¿Ž½:"ÔäK ÍzW~MÁ
+üƒq¤µ~J¸ú®bL=
+mÚETöýÖ¢½ ‡@,»ƒH9úëa:ÍŠ•Ê‡Çm¸ŽÌÓ›dDr‡ŒËE¨E­¦ž/¯`€dùãÞùëEƒª†cÂ(3óWÑ8`9G<ŽÏI3ç༬wÕ¾?¼[_në²ñ?~…Ïk%0eèC‹«wÅHRÄ OGøÁ0_†.}ð18³r‘¶³Á ­Çë(bÌ1´¥€ò1$vtK½ðuW8Z –†ÑÊCŒ\Asˆ¸J¡PßSŒ)s}Yç‚”t˱]æ:²Gü•±i j_L2é
+lAòh’€þ^Y5ý€¾ A9÷t-Y™gQ Z[ÁôA1ê–Ñ>!>‰ßTÙ™˜ŒÌR<­öD6âÁü´$å…ùÄ@_dÚ€ŽÁ…c 3Û©6f¬ûF'
+θV¯®³¿«ù
+£€„°NÂŽSì]´„‹6À×À<^ 'ƒ ´jŠ10SO–¥«Ø§H)û@èT:lÃ’L™xOˆô Â£¼>üå¯1Aßö@K¿>š5øˆ1'ýDÈD#ý4c¯È¡¤0’L˜žT>^ç4~T¶üØÓÏÇ¡Ñä:Ø@@ ×¢D­?ˆv#õ‹`GÍŸ O¢èlõ—^¬>w¶dgxI<â>ˆh† SpÑ3N`H«ˆÁÈÝâ€H?dnN«žÑ„W3ž+*‚²Y"Óæâƒã$Aò¬+¡<ËF¬Œ®)8æbkçète0baO«Nݧ¥AN+.ÂؼÝ+œî…Ê,Fúæ<N;Ó%
+m¢f (t_”Ì+
+ÇžQÇ:ÆežWNøðbâåŽØkÓ¾¯‚&†âlø÷ ›fÄôP9<¾z%n§Ä”öò ¯ƒl‰B©f hÙ.jF,Ñ55  6š-ºÜÂm³Û
+ÄfNDÐÛõµÑalo9 „ªÔå2¬û¾V¶@tät“áûê4ˆ)Ÿ€@.úYcRc×Àj¾TòìDdhñ°8M¨uòÐZZdN<Oj§ë±¦R|øÁ7
+% újý‡EJ5‡p@ö¨2v6ÃiÔ°O²ä0l~z’ WOž(tŽêAY„U&Žu6âÉC•®±„tæ”vâXœN¦$ ®
+È5ŠÄ9j<¦âûd¯õÚgÚ¢•óTúaPÄë Úþ !bîtŸƒ’Æsì~
+‹f<N„ñÍQIØI××èŸLÆ¿{|´¯tZ“¯W /¼NÇýÚÇ¿ŸÅ求uS«ýéÇÌTëq¦Äá §nϸîœï–Ë{ž—[™8r‡ TÇŠ"æ”'ê÷{Šf¸µb{ÕØmú„̦²BÂ} “ÃJ2Ì9©Úû‚÷ "íX¹‹ž(²j=²U0¶õyI´Ó?ð¾H² €ð43%
+ÌT#Øš‘ç÷Ÿô•,Å~Ãõ@i!’…ÁYñpÐõ¦¾C¥^ T~Þ¥6öyAPÄS;‰Ûo×ÂÓåzô'Û Î>•iaòÆÍñÇ$JÉ®IÅ2Ö#»ÝY“Hq0šG\´× =j>Ö sç…™Ow†ý6Ž[4z=¬QkC 荒N0›B¤æ·­²uÓ†dÂÓÞrÑÅ.n8Üh!´õ¿b™þm¸a³IuŽ”‘t˜×®âÞÈ*Ð*3Æ~kÊ b„àšúoþcfèç|Dž.¿”Ñ×…oã<}ŒWáÎ'©ADïü'‚ž£Ñs­œÁ|‚T}ûmÏ0½ˆ"¹A²€vÃ#q´ePŒ E`dCõZÓíSqÒ!ŠB#kò
+î#2i¾H…KWµ¢„0Š"S"üCĺŽEs.]‚dÚÒi”"¨i¨È€a7ÐìvH ó“’–¡ÙZ¦#zò¨a¥Þ(º˜ìPµ}k'±¦_;U­¨ö’m<ð~]@‰®ò(:>ôÄÁù
+_2´Qà ²C“›&½vÕ…ƒæs:ãx”1XFRF±ÿ.ïW0Ãg¥"
+–ÿ†ð¾=‘2Ÿˆšs‹è7§±ßEV‹ˆK,7¹ÏéBuDø\€
+RV!oßU¼ÿ¨(£iu¥â*Ј)Õ“! wÅbÆâZ€Á\Ÿx
+¦š«›Zw¶]÷uô­EòHÛ/íÚ,ïH Õ 6÷)
+âêÎX-J
+â鶴¡ûº4e×avCéÅ ¤mš²mGb˜·‚\o*£1¡k¾.*00£`ˆar‰@e‚Ô#2S•0d¦„´1\ Ö³é¼ìßNg„âp‚"Þ\Ñ¢xsÅ`·DMMŠÆgõ8§¸ 7I±‹É#àmGŠ0.5)lÜDáW· 2>ÒøÊyßÙòxÉPf[Ï“Êxp¨ `åK•ܹú‹ÂÈ•$ÀP‹É¼ˆN´X4mBûS¦Â´hÕêµuEeYÆ[B‘ÏéRRÞÖ¸D á@ ¸£àfˆm±>ˆœØ@t=³g¾%¸»“a|Í çVJc
+Ÿêëçü¨ÖÆŠ NF`¦{ÏÏS>§¡z|1l15ÊPø.%â"œè@È’¯c³a¬DËs¹ö-; Ãd ßü‚žòܱk"àXÙw2@;Ïf– ¾}X|=SHõ:O›¹ß™0_­‡…RG¿ÙÝñ´ÿ+wþLÛÓêJLŠ ý þÎ
+‡~qˆJëW…3™HZšÂP<šY$¿ØWWK:‡ÂžD¸_T ½óæ/É…€|Šb¡' êÓsþС€RoäqÇEʦ¸gÇ9sƯ,LUJ(Z¡Õ«V«
+À8˜F´ŸD(y@âã&TD FŸÕ'`P³äM!³AÔm'‹HÄ!“Dè`¡¬‰7ÑÕ"Fy‘Iít|Xí`RƒœÄ>ñ3Z`¨ÎçµA‘h{˜2éS×Äjj>„œ²«Höa-¯§…+ ¿U¡ÂdìÒžçR;-Pˆ¹ªâßÈAtM§.ÅÌÎhóÕdö‰ŒR½jjÆíÁy³‹²%~¾JhWXþ>ˆc3€(.S·Âg$Â:‰m|\€¨Tm“„ý œaQÏ1ˆæ" EÂŒóZsâ„£q|"ˆ²2(Ó#r>.t¯ÝÅå!£Ëx<««Ê묟ꓽìµE³@Õ°À‘©Y²ïêZz¼»E@ !ãBO´¯ DЂœÃöXˆB.åjeêÅ€/ŠO=O“C—cœ¿ë1!G@ ÚÔªìEìY6(;$Ï'¬XM'+§6­›ã5ÔüZÞÅZ(ä°Y›¦P/®ã ¢ áHD%6}WQ³ƒxƒo‚Õ‰›,n…(·‡G¬ªÜK4¼›/º²š àYÅ;áÏÿ²]f¹rä0¼ŠO`h)mßs§9ÿD¤ªž? ÛÝl-™ô¸Z{2g(_”3ÿpùÕ7lkSY•ò•ž9ç­á’£p,%GN¬²–´‘A­F\òµÝKOYO‡OÜfüd
+"EM‰:vÛí>ªÓâzú ÐÙ‚z9Ÿ¸=·ÿè›í)H)‰š™nm §[ØçEA‹#u/ AÙ&¨/÷v˜Ä—C‚‡~ôJŒ`™Þç'0ÁOXÈ#é¸g·žŸ)b%ýîM»<Ù©Û.ciM¬G‘¢<|AÊŠhÏñwfÀ[áR;u!&Îë[7¯ú­- ƒtÇÙGâIût̓O¼R R…cÎAˆØ™£T œ‡Ùu¦ì»$b¿y$Öi†ÆJþ/È|œŒ> TNË6+Ý|}>ynUž(™ýíC”KµÚ­ÝkVu×D¹‘u}™-ª$ˆ€&ð¬W–%un„ãËξ;1~®BY`e ­‰bRÒ8¦©{¨’}53’ÆÿçS!"ùÂéN_#õüõ>‰ÇA5¨ñÕ
+ÚQ¸bYêÔç{~0¨ddŽd‰ŠÕu±Ä‘’ÒoÛ'qÖ³9Ø euÍF#?qPd¹õÛ| MÐaƼ/MùF…F ReGÖ%+!2BæùZ*nD¦F¤tŠ–ìÒñW¼ûN¢ô½žÊϪæ‰ÜL/>÷íflÎW·ôÉöö媿ý¥yöÒñ¸
+
+¸½ Áû#ŸäÕw§§J•/:<N™ü”†tü¶ùAN¦åçµ+Œ%¥>ÑFšÐäóžÒj{“¶1ïžü„IF˜‘Ú^ 6ji´ÏkØD=CjQüåv#f0†]wëxEïD8DÑ®¡0qtÛqrxüv*ÊQXȺWˆŠ ›¢&i`–VÉ¥ž\Rêñ’m&bûE+÷\íÝ
+/òL˜—o8öÂ
+Ü;¬`oDa±œ¡ õHRE°î Y
+KÀò~Û³˜sÉôÔ1.aðª."} ŠÂ ?õ.3Ûeb&´‹¤¥{6Îf ´ØAÎþU²QäCp…gžD 딨ž¦&‚9Áuªû%4*F\­&‚RÑÝk¯š€AžÁ
+覿Ÿ?Ë6ÑVz´ø£¤.õ’õ
+U4 ¹"Ïœ2mM’±Ÿ„y‘­Î@Á« Òá-L
+Žû: ˆßPc´+sÒà+
+áaŠ9‚Jë¹ÕTð3†°'¶þ8çRlwÀ<àÒ¼ºY’4}ç"iÜ¢•ÆGd“—lÑᯒpŠg”˜i“‘¼®("P³Ô‘­lçv½SüÃv"üüÔW¯eî±ÉÂy>ÚZíòm§•£k|'d9ÞбFÇb¹‰”•¦±¬;Dð†YŸŸÌ]/ !ÂT€à‹ø^²~.Y ìЛëpK²sñ”ä’$%+XçØŽËÙ#SÜlÏã ç!ùK\Yã·ÒÌU„çw§©»»}·Ôjпð
+nÝ›íÂÖ\IÇ¢DÊ£{Z
+,6¸ä¿YG‡×*ŒQXaâ-7W/—ÉÔïäJ]Ayܨ²u,ö¯ãêcÒ¸dðzªëø¯QQTÞ|×™ïœÙ/¶™/H²?•«nSo"Êù³ôÕàÅ([;QMß4Ân°Üy Ñ=Ê8Ú=²3Œà²w'FÐRþÙij M¯‡¬hxúù®qñå°Æ=ZlhP "h/¯„‘ï»Ä¨ì‘ù–4ÿóRôÙr¬ÌÙ¹€&ÕõLlÝ¡bdŸéN²ÄX¨œnef¤˜ÙhÖðfwr¡¢yƒUÛÇ?FÙ¥D-KÌ(`­±%Kˆ¡Œ€F"¶4Áº_ð6wƒý56_†óø’nº¿:Î(¬Û3ç!§åWûdCž¾æ‹€Ã.Šu
+eG€ò®¿07çQDûèÈÛÁÅ~C{:gþhW+¥Ë:(ÿ«¶(Nœ"°€ãS‰”<•Ô‚$çt^öa•A‚Ÿñp4K{U¡[ª=_x­^8Øc “DÓÔ+ðÂ
+NAg¬w#‹«­y£jÜs‹SY'ó,£+ÁFäc¸Ó:Žûñ|r€IW¾ËSt ‡T»>Q›v²~ð ÒBÞñðâ8NdlEws
+Û´Ø9Âð•:^Ô®ôE)µ)Ö«OXpÜàÇ¢"ìÙOøröÒ©ag„®ÀC1äH2A÷•/Utu§ÌŽ‚M'âlx6HXkÔ‚~Qk¨ ±®g[6z¶"ëÀ{Š'k°%^Q5½–âŒyå„4¦à¶û÷ÐÓmÑc^UÊÀÈt!<‚@]ïé$m™Ñ*qP“ ™Òfd ñâvï#‘OU”g½nóæÒfP(šA.«'†
+$X³ˆ'±Âãš0Ï[ø%n™õ—ôºžûÂ,
+µ_7à~1-jÒþË¢¸ªÄÄóÔó³ú5”Œ3Q2™QØÅÎ:Ã
+lŽ=rº—¼(MEªHÜ•sÞø@PBÔ»Œ»}3žé À8®Na´ û‘sÞr+ç:QŠðB•·b,÷(L;:÷Ÿ
+H‰”—MŽ\9„OPw¨u)þHËA÷²¶s‚Æ̦«—sÿù(éžÊ—ƒjÛ°¬HQ"ƒÁàcúèctïÍäý×>ôѤ[Þ‚Ÿ¼[f1D»I´™iÑ<,ìý·Õ—$£Ïž¤2\fd›ëž>ZZW=›êîÄZo*}pª·qùííßoíýwÎGiÜ¢Åй¡9¤ác¶ïmNnß›ÎìSƒ(æ3ëV@m´Ø燭ó@\!3çŒsñÞçHCà¬P-ÚìÜ>#N‚÷+qé²^—õIr4O¨áfn|ÃÚεq€˜¥O7ëæͳkצýöœ$Tš8¸:Ò„òô¾!Òç¤:]ü<œ'Xö6,W¤$É•@6¿^î6Að|rQ
+‡ÈN»nÜ‚L%yÎé·¡
+Ýa]]xœPÏ
+7U8m¬sx\‡ ÙúÊp{LjÀ»”/
+­¼~T£zÁ:TÛçã # º--Ë×[ƒ¶!f¦|Ço¿8Ì«'eQï'R篜ۘ¯—Ã⯥ÈFèPËÖÈ™oDtË:—+Ç dS…ÑœC†þ✺\:5o~nLN†$rA.†h“v"ѹƈҢ«YJ–,˜¢'7‰XŽj˜EhDâTyÖÀº5Óæ/ äÒ;уx«â¹x#FòšŒÐç PÒÍP<!Ô¦q¯«Í±ºì\U$ëÃJoVó"””›R\Iæ\¤°iµÖa:)V§hóÆðÑù§Ù– Ä’ëx¢‚ŒgP¤Ä=÷ËG"¾YÙ Ac! çÎ#~‚ Ù-Ùé¡Ch»”¦ŽþneSfÌBì@ÔJpè÷¾Å(hGÒŒ=n ‡£¤‰¾œü¾?‡T…•Y¢_7¦™œö1»ˆ>´à…;5ô¥”ä[cÈíHã'êŽ"GL0Î?Ã76Ú§¼ŠéXP[dÄFªÂ~H! 8Š¢ŒÕ£_@ˆŸp}]ºttà+ˆáˆ’/¢Ï=©(M¥°BÎPD¦0ñÒ¡…Ycš—òz“ÍŠš ¤ÊÊ#žuŸ{ÐÏÃõó;øƒaýË?ßÒÓµ4ísah¿þK;òÙÞÿ|SŠÄAþ£öÒetxp‰Æ9;&@¸QƒXðÿôq²Æ(°³eMuôî ôù;},?ò½ýòÞY­T/£Wè¨õß F½‘ÊÔ¿¾uõj “Á¦+q³Ó©¶š[¹6/-%¤½m»}¼
+Á¨1ÜN(x‹ýÄ<"ëë\kݦ,ß’7:U«€ä£lC`MâB$RŠ45|ÀŠf œh3â}®ƒ×á®^k@¬c˜Ã&IÅÃHý°ŽÁeA S05°?ó²CY]è<m¾8W`ÐI9ëĘXødj¾ Kó¬ÌŒêÍ…w(ºÎÁÊʸž>Ü+åeEÞKqeÐ’¤sΨ*á™ I]Š”Ò£Œé¸R ßËd"Øhî(0IP‹¾ešmŽŽòÖ·ºv¯^¾?¿Þ…§gé’Zœü@œ´ãX½4kA¤£@ƒ…Åû0lZŠ/_O/§ì|±fdŠµ@Œ~¥â$Û.¤ “¬º3áÆÅ}Ù k ÜÜ ¬Ké‚;ÓO(/óÊ÷Šš$ËèiÍŸ…h“<^ëe!´Œ>õ­A»X±Ö¬DÜ@v¤j¡à2=ÚcEù¹ÏÁLcÅp¯~žÍä¬D@ ÛoÂqò>øÏ_7Ýy_Ûêét Ëâ1GöÛGfýÁZ »Naƒ4)c¯!'œSi\•rRLJéâ­'Dé|S\¯B14è¤Ê6‚†Ãß’˜¸j‰ðâòc ^—r}€ª FyË Ô‚˜Jê°!J'ßCƒ¶r5~ŒâÑäÓÙm (ßl‡€ØûøfCŸO’kÌ•ç%Š~e»Ã[ðñUtÊk["i±!اŠ~µ8ÚA¢Ê¡mJ,a°šŸµÜö/Ì" ¾«å‘ÈL)5áSy¿é_ôzGå.I8íš TžØ5šísÍgûóKi1ÙÝמÖý¢õ2‹¨RÚèÿŒ²-Ôº:‡§5ÁróŽ¯Á0—ÞËò!Ï y$û*ീ¬ùŠãbÄ°÷¡íú]Ì—`Ÿß¹Ñ¾øÓQ_æQÝÛh`¤­t‡ù¸Ã|i®ÂHÉ2± <ÎÿÛ ›hÏûèÆÎB%©Œñ¿z²XO™ü‚ùüF¶WMc,0® ôc\üœ§¿nAöÀlçݾIp ªA9PÁÌšÝ "8vxÁTØb‰ÊÄ5UG„5-'‡È™Ž¯éªµµŒj@lJåÕÑ«<ïgÏeÃ*h °‚pA¦}5Üé%nÁTcŸÅ°mˆÑŒŠÆÌS²,S\Ž„ü_‘j½Â¶ˆêU2ÎF*ÓJë”=¹¡fÖ7ÄKa¢6¥²…aü±P rÁ/…1y*is–,$õ@H1ÏÄ\ŽÆ v
+¡DXxæÂÈ,WÃÈÚÙ|H}ÝÏgM¦‚¬éÅôvøÉ*ƒïˆ¬¼ŸP¬•ekpùýœSÆ}- ²N©Ñk€È´n
+·,â ÂrÅaIb†à;N«eïeó¢<HAW‚íȼ6Tô„'³[€¹"=Z,óˆ+þâ6=ÆlЈµöÜC~Öó͇VÖ•u»ý{ÔzJ»à.Þ_@è-º…Z§½‚ÀÝYÛ'š{úàDþ’v¦;»¾8‡},I }Ú_݆åŽ@“ö½¤V+4/×Nƒ5¹)ú‚Heí›v´¦v…ÎHF>æ „˜ˆ0ZØûê”Ck”bÆ‹s¼L“r—ô—fÁZ èÍ«Á‘©AB3Þ€vA±õÌ'„wú™R´%¦ªvö³Œ>uœ([bë]Á eÜÅ/“œ¹n$Ÿ@wÐ
+’ÓZ¾‰¯¬ûoý‡‚êU0ÐhtÿŠâãCŒ[ûʘcˆùïÛ±ªÁÅpê‘ë†Ü'…šö§8’±;n>o °v0­8×~P‰5¡Y^¿™*™[§Èl¡<¨â·Ç„`nØ]zT.«úŒí ´„©¼-åvƆ ­îCXvG&gй ÎDlce1DU¿Ì+›ª5>WŽ³ÒŸ¨?¸Y_ôBIÈÈ\záæYŸ’%0ÁxJ¼­Crà³ðÖ³e|5óŸj}Bð:=·ì·^t§¿P7¶¢
+UwLÒlV a…"I À˜Ç÷DK¨}i„•Kø(U¶*§ä M)5}ïXôMºœý¦ A+*³ÓÅ¡’7÷Ï~Ô]1+Îk ÂÌtQl_ XRîŒ9>¸ e'ªqm]>ý‹x0!m^…’î‘n>Ë,âz½Oòmµ7K «ê)í/%À<™%~Õ¹²âS™ËäÂ%wÅê3ÃmD¸ò¼äñ2ÅW& îD +F–NÂí_Æ«D¡¸ 2Ë1w½‹s*¥jš˜0\v òK@tàvXJà°tžÐ²PfK—u70‚ûIù=3ÈZÉiqµFåšÕ9¸
+mP¨ ÊÛL×~*å}²<þ¨X!îÞ%'¹¶“ /ZnLB‚ž2å¨ÿÓ"
+l.C¶g¬px2ÕQöÀ¨¢ÚÜû‚T¤
+Í[ë· r¦Â=¦B )*Ñ¿kåçT˜äªêxÌEºL ,®(ã¦ck©ÐÍ2VÐj&w*Ðâž•MÇËTHlèSM!ü„‡ÇT
+¥³xÒú˜#ì*O
+U‘./
+z #rBŸ0#¹`2à6㘧œ¸?«îíClU Œ£Œý)&,¥Òæ(SO°©‘)¨ xá”z¹ $*)ÀaÑù²Nªm, p!6µE J&r7êÕп7PÄG¦k±Ý÷0Œ+kvƒ@b¼%¡gö¾AÜŸ‚;cšÓeˆ`s1Ìb¾íæ™^¢ÈJ+Y=9¯>!Dtn”ÖÚ©sʪI¦5.SÕŒ3»äó©o¹.Á ´¼_Ö)¿H쥕+äÙåH;1|D´´WÕØþæ©T-ãκäŠy$¥ò~¼ê¡­X_[š-.ïäs9V5¼)=²ÍDð~,OþâDt î˜GZšŒ-7˜À{lH”h3Fòý‘)b©lúL ÅBö­”ý©N
+7–"O•FpŠÇª¿Xj/.ǽž"˨^rº²ŽN¾¸Z §œý`î°¢’/ô …»€oCckûSä f”—Ñ}éè€JÁî;žQö¦“üžƒÛŽ¹N„F j®÷’³p{¼¯÷©ƒ;Í\|ß „íâkûS’cNßÕÙŽ¸7ÝòPæ˜ëåMLP9J™hâ­"ЄäV2¼!cŒ¸iA‹@'þêþ”ÁQhÀóõ¼A gïJwsQ¸xŽeÙ¥WyÉñ¶È㌠M ñŒÌE'‹—uè9\ìr%A ÛC+Ñá<!œ—˜jšÛæ\Ÿª\c‰'Dá RLòÇ.*ž‘¸ôÀ¬E1â;dµ±ݘ8×óqó§CTþÄòs¶x.‰€HÍeR|‡ºfÖ°#\úž'„³U½oßï­|FÀDvÞg"ûF½,Ìm@ø}@~ê÷ÂoÈ#rþú᜔Ǜ'l†,Í–Æÿ9mÎ=ÚHlîä›ý_mN€ðà|c\ÊTšiØÂOÝ2W¦R¢W8Ç»©}^3’÷ê+ñVæ
+T?9zÙ¼€kè+àz‚ƒiÒ"\ØNó=˜¼œæéÄ_tÿçGüùÐøÒ%‘;²¼?
+½ø9iNÐßØ[H8c]‘|
+Ïl#”,eK_¢Fïþ^_"ˆ3cÓÃtÿš®FìÉs™Ø•VUJq<žÃ¡ §>Æ0ì‹Ï1’œý%vG
+KÐ3Ÿ‡-*
+µeH³^]^ïú±Q
+Í\æQæ28VÑÔ¶vôçè!›F…Æv®@€ËU~S³¿Šn†­1[ç;UNY*÷0c€Ë¼lT9Q†p­$À„­ÂÀû:--V÷;©ÙÌƬ#HˆGÊËa„1´L?›ÌÈ÷ö§ ÅDRÝFDòv#)Äø€[Ï`õ}*$˜‹$²ű}ÏÛÁã!R•Ãô¹Ž<¥ªcODB¦e™ë¡r¥þáß:Âb}¶`Ón« ¤¬ ØÔÓF°{"ˆ1‡k+»7ÑâØ»qúZ;Ô•8)±´”7H5( 68§…{#âÊhò¾`|€ðF7ë3]0PïB
+ûÝ‘¬ R[šYˆ¬íD˜K²=ÛéG#+?‚—Ä×X(ñ^ˆ/Ý«®UJ”ÐO«ë ?•LƒÔuB˜v¬µ˜!ÍJÎ0ø°' ¬Ÿ÷:…nô w‰äÜp_?Û0]¥µâß²f‚`Õ†±¬Fç¬CÀãªh Å¼ÍHs Ž¿R>ª(@Ê¥Yá|èón@XR±Ôd­ ü¼a L
+ÛÆÖQJï½,”±Õ´5¡¿$šø&ãt&ëÉ>D¼iÉ£y,‚!(ꊽ{³à@í÷@üT…NÅ?¯-“}yKœ±íÙ$4g$1f RY2«½Í*·Õ%òŠÀºzw‡<œ:B¶&Ÿ-×æòÿ+Ÿ±ÎIOói¨$X¦G¿BÏ$Ýq[½Þ‰Üê°BÔ"Ö}N@µÿ£¼L’äÊq z à̵z©[ôVuÿm='@YÇFUö¢¥Ÿ$àð¡Ul{¯1sÌ€5tƒ«Û¬W
+…d>Ÿ%CAÒT$N
+ÉÈ"`ßò‰+hþ’/è.èII·ðMÃ͸ gz–9¯ï¯T´ÿÉÊÌ R^ºèõ¶âINþ2SÀGáù R4NtæG Åfe”c«@›Rþqó®÷TËG9‰`€[û)‚áñ Üžk©ÔA$“†ó15Ä >J^°#õšS‘¦º?©3jžTƒ$ù#­€©]K˜¦\™Ã$)~Ô{8gÜH²Dåv°•ÕË*#5¯"VáƒAµÔjD÷Ä8œÃ\JlÌ» ~ ùd ›B]Í'§L#8€œÜèÄÂMr5~+vr)+Nª"…’‡ìl,ð@‘À5cP iH9{„\Ñ@V¸ÝÞ5ºÐÉiw:†K™&:kÝhI›ÐWJÖXÚu˜ë…Ü.õN’ õ¢uD6ÕßYLæY%<"%Cqc¥Îc)ðh×¼Z£²„½1(‚Ã\w(‚ÃPs$jôý*ÓÁxS_‡GqÐtË•ò.!¨b–À—>¦£YÞ’ôZâ(>8L ?U¾
+‘±`,ØG?jæ”û<íPv“¡ÉF ÙÀ`Ô„¦:ÕB7|(1 8‰Vp“9äöòðúÏßb¯i&Ùh:pÌÊ£þ~(^Bd^¸ulƒ)GAìÄGî&#x1ŠàÌF°Î2ð¼þÇo/R†k=ÍvÎâ£àRnu¿ŠæuƒrêP¦€„eÚ<ÀÄ!Ô9 —èðà¢Ì‘9­¸á’ ŽðÔ«ó
+Íë`ô
+L‰kë Õ(÷A¨4$ZÌû°H4~p†nâº2ix}L ‡Ð¡.z¤dLnק±žq]Ná›
+`à€v
+kØøhæ³áô½$ â²E,.ÄÅOq°û3¬Þ„ sb”@X°0óƒô&èeà`¢´Lh$JÆA2ßœq¸)–1Í":ÌOó‡¼Y"ã·zÜ¥b6ÍW‘ÕŸ˜Î%H ˆ@ópÕ Ò
+ï£`ð¼ð¥"•Á7t+õFUAsíËq¯tP±C˜m KËÙ‘%ÇÄ8ÚðÓé‘ç#1ö5‚"÷%掴dTÄ ¹pâßáˆèN"ý”ÂZ•8•s‘»ÂFL™ž2ãc´¸0@Ö8YÚ£uŠ¢`–d2,žÍü1…]¢¹qº‡
+ЬÆ#xUÜfêhv ‘ÿ›ñ2Évë†è
+²¯À‡-HŽ¡×‘‘³ÿin ?QÇöÈ_‚Ø¡P _a)!Éu9oXî(5«uƉ ¤•|9üRÀL[1i%ÖEr&™rοD€ï e¢Êr¥Çüh .øîÔ”&yâƒåÔ¦cHŠ{éVy%æ¤@é¹ÞÇ|â`³¥‡
+ÆÉPsª§ñ"[‚"0â3§“ª@n3ÇNŒ×줔Ñ?”@±(U°^[½/×B™XèÃ: z+y ¢×"ÌOâØöˆu@5܃EËDq t>å+R’ôÜýOœ?‹”V™.x-¯~çã‡ÿPòMüv½Õ£èÇÕ7sèVMÌfôÕ!ºä8—(€A4å@`)‡X=í¬í‘j(ž¢Ó™;&ŽÇ€8ò‰` Ó104 ÑŠæRŒ'‰*µ­mÑE7K:a¢À[I8¥_Åã² eئ­¸¬ „¡ïÞB:Øî,VÕœ®l†Œ
+"ůœÈÈ…a}|¥PL_Ày=NÃ6]ÓÚwe
+|<ƒŽÙÅà ö²Ö³—P¨Ø2r`F­:éŽqÉ긮â\Ê„°—‚Šyb\&þx ^º=F¤Zü³üÄD¯Š›~˜•–KVEnH(—@¼>á~hAuh=JB¢[OòMÓóßs™­ÐMò ŠçY†ùB³®í
+Í¢ùÈJéQÂÒ3.oRA•=Ð2<9
+åøŸÕÇy=™^¾oòžWRz>ñÓŒ(ÂêÀY’êJqb¤{§D/¡üRàJ7‰®ò!
+È[¿fŽ âø à”<Äóé5‹xToî%+‹tùm<ŸšŒ*}XŸJ PÒÿìeè½5‚ZZD“è>|¸Gó$¶ˆ<}UÓÁ%ùkÚ¾ðÙœ—ÑU73¬­ðf~]Š~x‘ˆ>„uâêiÛø®„²÷šu3jwhâñ8*É­/Mï™:¦²—íÒÍIàVÔ¦ì*\—º}XE Î4,Tû´£€²·m}ÏÍE诚 à`çæoE¢$Za²j{³¡ð#%/Gê§b#”Ý”$v fˆ’ÞŽ†¤ŠFxY\ÜÈ'þ/B¶{yšÉ$ûû­zï³4~ØGäÄ[ýG]†oÔ¶>‹Šs$‚NìGDjl†ø4¬@ZqNh¹tîePBþRƒ-R|ƒH1‹Úñ§þ.ÉËÉ‘C(ÁõØ BÄS-5'²bâŹm¾RŽl?bÕ%’ÈŠ<ZŒ&“Ì~®ôKÉ·¿þù+ù­‹cÉ°|µy<ëÛ,%´ñl_þýP„™ê2·ånS’aÀŸVL '„ucª=,ÃK •>%-aOdxŸQ< ªdC®[_£>áØp+cÁz/ù"qãô’IûYaÉK8_­×êøj¥È
+ñÎg«Ñ¥X’Q¢HñQÐ`2m¯ci4uöc—
+Ì•z‰ex,$j„ö:-!\À‹÷6L>TŽ¢¯]/ÑP¦¨{¼m{†IiV§ôRô0t¤ž+$Þç%žšÅþνÙ
+‰=«QD´Ârôáæ,oë@\XÛ§zIS¬DP¸Ë.A¼…ôp…gwt
+AßêGöÙ…c_N,,YN’¤’*Ã…Et¢D¨˜¶u}— èt=ÂEÉ’êÛ8ÅVø@úÇfæ}× q0˜yn_§(–0'¥¼œ ¶sÀ|EIâ]Ûþì8¸ÊJ`fçVœ˜g¯²ú çì ëzb•q)بþ©D³P4¥)ÿÜéYƒA×E¡kù:—@w±r§DÞ—iC“üNp‰p©1ø (HhrRÜÑصMe¾. s›„î(Adx1Üc±h&Á9\ç%©PTuªÉ…È©4¥±Ùàê*ŸO,dH³Ò¨CRÄÑc‹[ѵ¢›ËûN¸&ž4Ë…¢EA“Ú-ßiJe(ð -~®@wzÉs¨(:§òBµØê7“÷M!8Xv]Ä·~r,ÇæÜ‹G Áy/†…Í¡À¹K” +…‹fѸlÅ5×]2”Ry2l؃›™¿©ª}ô*¦ãÐ(2m
+2„˜!¿–ðÐ{cª¡¹!Tw+ðn<ñX(ǵ¤îtÕ-ª7Ñl
+8抭*†8¶=‰qG8˜Ëv?q–åÁ¡¦0±ø«ËÐIÈÏï”ù0yäX¤*°Mw®A»SL²Ñï°`Ø\pJ…—6R}^êE ŽljŽ“]‡
+øCÈ‘(¹ > ª$~@ ÷ûTÄv¢Sì‰"oéÊ‚ÕP< æŒ(’æž•A¾dü`áÙËY‡Ôc »³s‹eçîm\l¬cRIBÂs¼nY
+¡øøÝ e†
+.ž#ù!ÚâG˜ZX{œêH{˜&æ^&ßH¼ŒÝB‚»]åx?ù0MÜh^Ç‚uq >bD;‹¦šã-íÆ®C¼»;Å4½ãõF¬Â *Öqí`Ý"Øâ
+Q.çÀ´6»ÛÕç½ÝÃ/~»NfûÊñF©‚9Bâ­¾2ð’óÉ£h—ˆ¡r‘~­L*’Ÿ‡¯à"5ô"J Š,/OX«3©;ÊÒ w0ª}¸œß £Q¶Fb<£„ÿ¢« Ô;.óJ›°¹¼WøFb N¨¾Ä*\’y784_Š2uìw°PŒ¼ÒØÅÆPÂèw¨Ky
+5°Ð”}( ¶.áÚ{ï B¹m´/·Ã ‘L`•à¡f×;=\0uÚÙ€–÷X‡)H2y¾Œ°É^²³± ¦
+Iò°à‰q §Qðl9í„_tV õ+Àòxˆ—ÇVkÖ`åiqŸn¶xΗig/¡©µ pºôÂÔBoøi &‚³ý:ZbÄ
+•±amûV=wA`Œápgº²‚L©ò¢Ç/$”#M¶0ÿ Hø¹Ä>.A+<h±7ã—‘ÁEù/IK,”(ÐO’ßæÖ å¥ô=uí•|ln
+:Ú/g‚BBšƒ—¯æs\䶹]ÙG]i[‚ËF]é:Š ù`,WwéÑR<™þçhÛˆÅRÌs‡LoARÄ Àòãí¿oýû-½ÿë?oýï­íôü ;Ø)í!ã„i/ÄLVo0¿CÐDwD@,1ó±
+´”ˆrŒß„7örsßä~Ô× L° OHwhËb,Z¥ 0Öz7qnËhBYuv¦;+Ì;–" C¦b£† ©y‰öáì(Sa ô„À/õí;MCÁÏȘÈ;³Â× B‡ú”9‚øQŒ!@„¦¹ ¿Ã4hY}­¢AðšM^Žœsëƒþß•aò™‘;Bv c”Qz¦øÔw°ºD .#Iˆ7Á(ÂÀfÚ‹2žå`BÏwà4•P›“×—…âAT‰ þh-†|1mˆ@mmì?â•”Ž´dvåaËŠ»Ç
+£«jZùå<…™|˜DÈQ€oÐ/YmHIª®z¸
+ê,_þ]Ìóâ…‡}ôDáV=ƒþat©ÊTâP™~¾ÅiŒƒ ›ŠVBÒ/`gQµX›‰¢ÙÖ©………¹ña±¸€*ЇCFmìGÕU½­€eìÎIæG üxZ2ãØûŽÒ°5dÏ©,,BŒÜ ƒ°øL»Æ¶E‹Ðñ$$ÏDaÆÖõð§ÛL‰%sÈ:¥D¯š¤LTšx5-SÕ‚¹c`°™c…5Ž ŸzuŽºP`‡+(ó=¾ ‚[¶Ò…ˆß„ãb†d.ŸƒžkÓÙ@økË^ð“¨Â@ðæ˜K~ºkØ©'ˆÅsǃï<ÏÍí6ÑüÝ^Í1hŽ]
+>\÷m EX%|hŸ~½U?®å#½nRCR ¹Ó÷oo(©§+qÚÛŸ1ÿ˜ˆ5n‡=ƒ~}çFΘÈmÏÙ²aÁ·~hdô²£zÝAD˜¼(Ìb ´0š)%:ÁÉh;ÃY·êdþ5°8ã˱pIœ-‡§lZD,ëjkD­Å|&Ž—Åm…ßÁ5’
+ÙYúsþUyM¹©‚¬ÌCõ™1#4e´å5nyÁ£•ð;©¤ºÔ?^¦cj;åÇÜùÅ£=´´%5vøøHq Ï£u9}XÌ+<ÿ8‚i-O Ÿ š#XÐòÙLoh Ù'’®›<Ú‘¤ÃÈÄx·úXD Rym[y6¿EZäû9;DÖ£MñÛ2ȲÑ1ðy9„֢ɸy¦Ð*ر‰[±€‰O§WØrv]vŸN¬I·QîuuâSÏóyçÚd€úb,ºx–ñ#h±_áwH
+t²‰Ê<K³ÉnÄÄz”\M¯çQä‚…ewëÇ
+S‹ØhÓ) »25؈j
+íHT{åp—yÔj˜f˜%׋-“©”xþ<œ•‹‘òE X%XXI$ûgJRù±tì‚O!~EcúôWôLSoïo%ÛÜ L¯¾óÔíûmnS½ê6}÷âÜgøVâhÌ?µêçwF»•l·Ê£iöÒ\Æ ¾÷;aQqn'm¯ ¬ €Dòª—ÆQÚÜ[»¿U颿6IPP8Ät^ aÖáOüñ‡=’ÞCy$Q½!héH­*„ž%êý͉5ø+„¿ž=466Ð̾œwë2œËå
+¿¢?’‚PA¶ëó(Th“IaNĮّ™ú*—\ü©•‚ëªÜNìL&x öf‡,ÙP«ž®Bü…'¢EÉu0}jý¯o0…²l —¶+csͪ2ÔÃB7'¼æOï­ÏÑ|@èfáù¬Ë§È0#sçj?^ŒeQµ0‚½Z‘[æ ÎÊÉ è•‹çÓåäÐòÚrÌŠÞ^|‡>‘b°Qšís›Ê{¬Ã>ÈhPÕìáU´¦ñ«í»Ì´ó$Æ$}À wù‘Ùì3M•[CÊx ™J
+º$”ñê‘ %œâüsÒûéQ(ãQ(( n{Ôó-X ƒ]/Ûb0©Êá2Œó\ SÒë´¡™%ÎŒÁÆ—´qÞÅÔmDZÝ «[Øë”ëµÉÍkíÒšƒŠZ9kÜ%0Wl>Í2ªJòÕ–äõ“ŒÂgùkY˜ñh(8 ÿ³Äx1ØçÅgà L=$¼žŽóè.‚gjyÄcæ ›áLI¤²t€*(ÆÙ95‰ A@¦ ®³l:2ж¯ðš‚À Îîä&f\í_ü÷’QËÕeP¶œ
+@J§ÚLÈd*®êÊ9Ÿ9Iæ.åï¸í(4ê\™¥D¡êÙÆ£óMbŠj§Âò§•ÓA¨6WÜ?—U_DZ€OA:íÇ{²ßƒöX·7C‹pÄs,Iì8g½øÎfÀ¹ {æ‘ÛÀÎ0dgd}„™M ‰±ñÄ1p«i¨3ÃdGiÎyê’A¶!D
+Ì° 5í=XJœiAפêG=ï–ËU”·èÖŠÀJJIŠsä
+241!uÿÆ–™¹ôY½Cº‘±Rw·Ó:à˜á€ÆN_îŒ,/Å Ó˜FˆÑWz!šIßmªaµG^ŠTåSÅ¿} ‰„à—˜·‘=cmˆ Õ#„AK²ý8æ÷€^Aw¯|AØç$3Ù1ѲL0/Ù<#HÍ©x­@×ÕC•Íáâ/Ú½F¡ËžP˜úÅ(ŒEŠ´,iÖNâoÄRE§lèqª|ø¬#Ù^«sÈ‹
+¨-‘”°—½Mº7ô6•Áðy6{é-CÓ¬&Ú <%gÀiÏßá9 µ…{%ô;ø0zIâmI)ç¶cQÑÉ"|×2Cî“ [^Ý®NÁoïD‚@&A -ÚpA`ç‚YŒ÷ç×5!Mñjà`á&ð1ˆÓÄ•z
+ÍÙ‰d‹\pÓ¹rß ‘‹D«™¢A0¥È³ŒÚ.HPë(©öQ¼“šH·Càe¬ 0õ:Lí¬Í;.«Ê9zLhH’qö&)Àq+] k+f")h‡Íð}JᎡŸ麦-Å“K Òõ¨?ï³o%=ÎçÑøÐ@"IþcùëtÍkŽË7Á˜#Ð|r#)¤þ
+ú|
+’<ã¿;Ë‚éEùƶÊp+ê!…ä=š¹B“蛄dD–ì]ÖÊ‹™—f„f¶)‹©zF2¢“MÁÙ”[§DåϯH¦H9éþÕ9'ÃimöeÛ ¥¢ž7“]Eı– ®#CѼL.` ]…SaŽØužè_‰ýü ¿o“ZsŠ€’ðS'Jøk —U8|J'J
+dä&Ö°7(Uš‹‚î ÈÂ*¢E°GT¯Ãü‹X}fšfnÇUè-„bõ²SbQ °Ì¹-”Ÿ‘å‚û|zñÅ´†† ûN$ÃÂ0P«ìÁ·ð,hë@¤S~$¿Ö!?J5¶SêiCw£T»-اF…Š±e›ˆ©nm“;"¦ÂpugHž¡Š+Ó: ̨]¦‚Бý¾eQ.ƒ!mñ9tWÃPÙ6&©°$_ÆÍ“E5ðo6~íM9ˇՈ;-pĨ¤9LmŽ…e"N —t€|ØV SZYX†üaiœÂ Ô·ÕaÌ3†C¥¨Ê@ƒêtñÜâ Ùè¸ía|{Ý-‹@DDÚ
+šehóµÕ÷áþ X%ƒhPá¬Q_ÕŠ™Žƒº¯[åRÉMžàà÷ÖV“ÀX²ÜÞj f‘TËýבE˜Ä(Žc~×Çÿ{b"˜¾àÁ8ÐÐßJæ¦ØÚuƒ.([Þúê3|ÖD0¼ît†?!×ñËfՠ˦X6/Ûð úæJÙ›©gè¹{Ì{'„’Ep$Æ@äAê‚bJ‚Nú£ëã'ƒ¨;nþý‚ðöa»L@™õa ‘‹TÃßm’ŒnßT— §êcúµ©;¼‚NTóÒMX뙼`¸â¤¡ÀÆ4[§ªÁq-ysŠ,ü„ 6Kr@¨=°îû|…Ðícê ÝšÕ‘Wyk¼šÏd€¸B½ 1E&*ÿÌî.³¤%Èmx•hö¢h‰¯h}ÇMÍ=²Àœû”'u{£úÕ…R.¿©Œ+ÜPH"uæ!úr¦¦ èýTµ;n¯šN  A§Ö÷ÒêPNÂ0dŠç'b ™ ‘¢A
+¾U òwðãe’›Érá«øBÎÃúm} o»ï¿õ$SvWåµa4$ª2“ Æ œKÌ›²ƒňf¢KÂk¨;ðÊfm]"šr6¯¯zM¶ ½¤¥ÇùüQâ£`1i ˆR¾#C{؃rì‘6¼5;ḣ*¨Õó*ÅYAóÙ—Þ³#ëØ#À2e¨Š3œ<«$;•ˆzªøØ‘ÊüP¢Ní-'½ÌËjaž!XÚV=‹~}(Âî
+X%äQtÌ÷7å
+ŸÀ[džlôW‚HÕ{H.¿à‘
+Úû{´“‹L “f-™É¿T F"H«Ç1PþN
+kS©‹‚Ž„˜QùÖ.%~ÌBaa1¥ŠzýxበÐ{ïÔ*!ÅBXIY“Ÿmð]cîð:C.x”Ù4±w‘xEq* ÕÚÄtk~ûÉ
+9 þlîyUœ‚’açòõ;À%4xK8v›F'lG®¨Hš&‹(Œ£Š~¸P˜p‡Ö®¦—6%£[Yá¡ål¡µ¥vöPY€oÚÖÎvþ‰õü‘Û%0¨»ˆ1
+¯hÓô•³hL‡‡=Ô^顽Ç(6b·h.|~ÅÃUh8˱rݼ.%ÿ1`(žÀWHøÑÑ×wÀ/¼«£D>w«ïFsÁ&"û»ä‹+ô“è:#ÎÓ®G܃ ÜAU(LQCSÇU¨sÔv` ½"J-|Xú‹d\©áâUt¹T³ã]Îëo‹žøëoÖÔ·9 >»Áw£{ðD‰:ŠŒ!Ù6ߊ¯\Õ§‰Z _FÎL{¼„m·øBpó’& bf€Æ+ØÉ&‹@˜óÉSSÅÕrK˜äË>CªÈ$à¾{”3²²©š­’¢ÿ˜‹bôü,ñ£2ƒèj-·þðU$¨Kº®·²+\­¥¥xñ@ÃëxGŸÅ«9”`ÿ Ñqê×ßJþUõ*"Sá`X[ÒÛe²GØÌ1ßÞ„Ø ÉæÔѾgoú—þ‚-Å\˜Éw˜,Ï”é»^'õ(ñ£ž¿|牛Ëm^ð»<êbŒ nÎë‰÷.0¡Ušx&µ% ꟳz,e•§qWýXõß>N&bç¾]Ä“^E·,ð<íÆ?ÝH”‘•ëü"JâÁy¿EÆß·"ŒIu²ËeÈüQ‚±)²p0c÷’Š55oÇvX‰´k®!aöŠ.&&¿rª!¤J‰ c.Ì|ã$2`• Hàê’âϲ=<’,zBòqSÝJý€V' Þ.%:È¢ÌYbÀ÷ïll÷B)g„î’Flì"[§Y,…
+á7^WE¸‰i–÷]$ÝÑÄXdêŠ&¦Ãš7F³î~9»2ÍMR¯1ÇMLßO¿ˆ2E ›5XxÚtSnÚ¬ 
+¶NÜÈ÷LÁ¬R•1=½xèP6U+±Õ¡L+J¸J•þk1¬ƒz<Þº
+Zn^$íêÒ¦è[Š,!¨XgO •$Jp½}KI­M;€¯»”Ä–â:-¤´|øNÒ&k F;G±m
+ Ý<‚6PÿÛÚwÏ·\X)“³ûÆ+oJŠ¸%¾Ãïih&,'–x˜þ(A~16h,Ý°–#‰FvÞKèØ4ز
+ãåUö„rã\!Å"1/d%øÝ8[Ôù'–óGbÿŸëià[4>øH‰qår'Ž^¦íK÷Ìà.‘þ.E,#ȳyœ¿Ò¾­äØ]"Þ\`úøÚ†L€w_¿N_MGZ–Ð{‹Ú˜ÂÏü3 Kw±ðÇ;UÓo¥ƒé%Ks˜ÿ·eÉšæ3i’ÁðUD‹HH¸v Ô4ª;Ó@¾Šå>ZúGÑ/ohåYP¾ÑÓ³H%ìHvÑÉšÌ*c± Lc°&·4š”Æ\¼/»¹@6MMÀ~twÅÐ9œÒeî·µqe¿15Û…vc$q/EIÈFõ*Ê´ýÜ@ìG½‹´Kä0lK£@fˆågZ¤;’Íhþ*
+À4­Nó³È, 8Š77Mž•"—•À5¸202™­³—+
+ðzÉæ)/—¹nŠ® {è4ô¥¤±3ô.<íìšs)ÊpU©` ¸Í~’HÞ`Å,ïVsp±e÷è¾XV¯_YªÑ{ÌöÀçC¾/l§yàáfºõûw*Ge¶…Ö”"¾(šÊUf/ßäÂ>ñµx7“ç–¥nI©ŸB) l2Dñr 2°ãöï`£“œ4‘)Q`¬‰4«¿)Ñ°GÔ8驆•Ç êϾ±þeØvH£€0‚Ò뻌àWÍ)œ
+¤íJüfLŠ‡­Ä"EläEx›*ÐÝ€:pEÄ¡¹y†r1FYüÙMÚ0$BÝ¥äÎOOEßßõÖ•:È/c‹é­¨&¼HY槄¦/ÙÆÕ"ÂÈ$2SdÔÓ Ô,zçƸ£ðøI«#_Ë;›ŒŸD8㈗º¹,lËÖ 8?I&êžÄPç±Ù¿ó7„ŠÐë,긔ìQX« KYß|‡‹±×ä²r¾CÂM0kåͺlÚòË<é®sv8¾–h` ×Ýa†t:à©=}·|šCœHJ?–ÊxSâyBÑ¥}è`¦ê²²K?³Ö¯E_oŠ˜IF)ä˜|—õjì:Ï+.œÉš…GáØ7„Å–Åt‹”´HšSÙË"J‚ 0=„ÅDw*§þ
+ÞÃÜÔ}ešÅ“=¶Ð6MCòPƸϥèW‰ýú–M%tr'xHhwS˜ '" a&ôÉÕú¥†™"EðS¦™ËÙ²lÙl4£û‹¢`|¿ŸöÛšgúu¯Á+‚¢ÐUçbjU Ú6†™â&<y æñƼõ9ä*AŽ–ËW‘"@ANÀ‘Î3yà¡×îTHࣖ|ì)y´X]&ï®Þ渔ì“X¯.ÓßR»©Ä´äÉÂè£ÏÔ†9>.SxŠßn“º­G!¬`V| ÃÈ1ð$Cåg5kÀdªõê‰èM¦¡BS—Šýn~›^òSöòú™Ì+å€m0þqcö¯€(•ê%˜Dí¡9a­†j ÐåGeZ\/æsÖc*%øØp=Ü+”Gqš°•q¯†£YóMÉKJz)ºm:‡sÝÂSqƒù/Š^Àw;øà†¬çg–‚OäFIrf'VTÓ‡ñüüPÔr-zˆK*#sCDw®XW±&U´› ¨Ä|8­󒔸)šÁ55XŠè#Ŷ¬Nv¥æj‰ëÚß©`¯6ádç¿É™Mº8÷ߧFµ„iΰ¨\RQJålP&ê
+k°H8#Öa*ŸZ³ú¦¤á‘`yšG½=ʶ^Eý¬t«Ôãbå¸|^Zó~ßd–2,&}–»âm3(n‚Z¸f=ö©*/.ÅFóï S®¾:ÖÓ]À? Yß8#­_ ¼s\–ÀÀO9=q¡sF€
+a{hÎJ<uÓ% ÁÓ“À#Í~sÝ·
+¬14 ËÐ31˜ ‰&ðQº8Ê¥èëM^.3†_+âx<¬ðï%%…ξoÀ
+0
+3Ä&J˪í“ÄH¬c /áÞ Ÿ‚‘eó†î“ª¾83
+¤ó/kUß8<-„|›r`>Ùèé;l,{‡ÖŒã;ü)33å%®$²¬c[3û¯aêû:ú²´Ï)ë¿ÇDC7Ë7¥¹N±ÓY„x_ ×\lÑ0s‚äʈ5–Ã`õRôµ‹
+Qbɪƨh…<Q[}ã›eui`=æMÀ ðz`·A‡_Â.oxÒâ’ŽpMûÙãÎ>C9ýì8kÉ+µºIK•$`8µÈ;ˆ¤Æ­×}š{m°:òc´òý+?ŒëÌ
+SQÌbÖ+¿Œ°Ô]m¿G/¡›‹Šê€jœd3Zy‹òq·˜½È<Ó`û¦äÁª~ÃÑæ9°´PŒ”Èu!þÿ¼V
+],] “Ú]XA%]Êæ+’ƒø¤ ™ËµDÁ(uoÈ(e3Ý­¨ÔN¤Ísã¥æe¹±åeÏPI4Ø
+H‰”—Mr9„Oà;èó‚
+{¸™ëy•ÚKï^ç7¢×lÁa}B¨cÕ0é!}A|¢¹Ò|ïä­ KЪºÏëÒ& Xç:1J‹NyC6¤%ï«r:é'úeá`á
+Ü­{háC=@þúößoU`Rã
+ô˜fìçÏ0P+íý9Aƒ+ µÎ¦—Dw^ ý`»òR(“•§í8ÀP©PMºUN3ž—IZšæŒ×ÈÏD±´k+Í!/iA’l&$Õ5Án½DMªÇêÄD…è-iHÖœ=yëÙO§"ñUPn×›Z¤ªX›]=jc9‚ŽˆY!ä-ë*¶Ä4^ŠÔÒ
+c­ €p4qt«‚f ajÎBÝ^ißI±šõᆈf”À?iÅH]wÖ‚ÂR §¶KK?@ÖV´‰bÀªøµÕ}2P6±!L,c-*bÒ !ÒJCü É?&9<òËèòß¾:Ž"ˆšC…¹R2µ
+uغmZ˜“´«œŠÝií¨œD°ˆ$Ætè9 ÆZ ZÜò¢_•Æ)
+cƒîgºÞ¿2§ßç8ûkªŸCµ:¼t$H7¤ Õæ8?AÌ؃X‚ ¬SA=†…yg—?
+ºÂ›¼.!Æ|A”¦ô84éiàø̺9®Ã?òŸŒí™hÞ@ „ÇZŸ¤‰BQ¯H!x£ð9"4!Ì,Â;A¯çÛÈê%ÂÂ{­åÊõ“uní>æF›Ó­îì{çÁàG…ÿШ_˜•œª²§Š½iFŽüŠ¾·å~Añ"<ÁÌ–¯UŸ§‚J…™éh\ܘ”*zLHë<f‘7^q»Ì6¨Ìå›×ÁÉÜ^n^ÞNRÎt—qÊV/°³L‰õ”èÏm¿‡þdfŒ#ãÀe×ïÂ[‘ È°õë4éÏPŠOQuh*ŸÈÅ0Ò!ÅÂëR žE²0ò¦üŠ‘É&n£)oų“܋̤ îÇCK~ƒaTeAØ9ãªÉ"áxñRâ®åãsÎñ ô¡õï'¢A‡‰´ðµT›ìVtG±)DØûÒžˆQ–¨l£ÊõSÀû®20ïp
+Œ€£Øážwg¤¤dÇmv·¾’ÑŽ{aT×8ÿ+}€SŒsì¿æωÏ÷,ÆãŒyˈTG ¹QËqS¤)»hôX‡°Pwr^û,š—&+S‰ qDƒ 2ô=@ðÁpN„ Aç}‚ §ÊåÊ¡L¿¯™›qˆðÕˆMµÌOC!÷éêwȪñ­„ÏumÈÓ0ÿ„ÀÑ#3˳™Š5ŸQÐNx®­n´ÈXLÜ£Î$A]ëÜÈ´ Ìíq„'£Ck×NÿŸÈ¿‚q!¸äcBÉ’úC0>€2µ1Vü>_l !MÍΤvczÄMCšÈ”AV·>¶¥"‡$\ê[Ã÷ÑÉY{n°³èô œ0>+Pgd$Þ`Ž§D $é‹
+ÃÞb‘>EÒ0W£ZÇeÚ|uB9òlñë0–±Ž‹—#éð`2¢1Œþ éùÄ’
+d†yª²Dà U[ïů€îV÷}néŠôj—OA8lO­É¸~ˆµk[ÀjÃÈèä)Öf‰«Ô‹8¡GÓ|tãä™45CkËV·c°Mjð’©Pˆtyݽàú GXŒ[W&·]‰tª.5D[çN0Õã %zaÒJ”kŠËƒï JkY=$GO´t&OCþî{«ß ×?ÞC$‡Hlç½t G˜sUì½ùœCŠÏ¢A¡±øz
+”¡þ •«þ:éÅàj!¡úHÌ^•Ÿ
+¸É'sO‹ ÕR>nÝâ¶U_ÛÍ
+n ;½·Ž¡–®à.ÛšwºÓ˜ÂÊñëÐZ‹å‚Ⱥ$9ƒ’Ñ÷£bm4ÄG0O8üU˜m&Ñéé…q ˜Ú¼zÅpÁk-ïùÅ ŒÈ÷úFÆvØ)B*h‚œå—(„“si'È@b›ƒ?½/ 7:µQ1Ä&
+ª"1Ý8è=ã úâªÈ äÙU¾ÅA•èq"ÌŸ@˜UÄ“òIËõ°_aP— s‘”œ§’>ù66º 7/jX‘ioûaYµ¶-i:䯒ª¨&w]rsàSt‡AÛ¬ð.8<AÏ ƒväÀ“´Ð(/Ä9W¿Ã ó„Þ:oMxFA§•wt ñŒ‚úQÐè{üˆOTiwqQ槹QÐ+zDA•ðn¨XX&üi TÂû´ÔP£U„DqÈ"þŽN´ÇvÍUQ•ðÞVüŸŠ+´~ãÐå"¢»Î°¬ÑMÊt² ç+ zEWÌcˆ¬DF
+V¿Ys‡<Û âÙ2œ÷Š2³þkæÝ$h×Oðz„'ñN´GL{kkËï=¨ÕiÆmÄ€ïd(ÆË‹;l™“ a‚–©GI^4 rµÁÎNtàþL‚þØ<’à7fëŸ/ÙÉ/bMªÐ]qõeç*ºe‡’ž øÃ’}ÙÉLjŠ%3¡Ç]ª“åò±Ïò¦;Y9Gݱ®\”t íÒÒ/pÉN˜<›\=pü°NãÊ° \V½Ì¡’® ÓUYà²sy²Ãf±(Áee^Wv82;s ,S=!ð].®«{²ó|Á{™« ·î<{éÉΉ[vnô]²ãô);ñ/ÙÁÖáU¡9ÍO²s]²“0ÿ|%W^=EWva"ïŘŒ^?ÈNæ[V@ ±'WvxëVpò<c©Ù•‹ xVv²}ù$;åE3+ˆ¤Ã—ò›Ž‚] ýKßd熳#;w‘#)õUȬ®™*ß-ò4¥¼p†ä>¬yJýcd¤V*ýƒðð
+ËÄxVWx.ÀßÂã Î%<œ®_ÂÃ]kgþ‹Çø ÷± ÆjØ ’Ý0­Ø2¸§M§H%ôŽa¯|ðc„UÀ-E[£|xœ·©•L±ÿkûÐÓRºMê–’ª2%Ï×2ˆn'bˆ^|# ç
+«”؉'O¨¯.ñRhS§î,ÉåaälušÍô!um¥†2 IHßÍŠy Hƒ¶¯[xfŸß04Žv¯­4#Y¦mžva˜,|KÛàBjC (pÌåþþ€ã_ÚáúŽ8
+wLX´ì,ÅtÆCó‘Îëá'_Ü[aZbBãГsóßi^%!7T:1âeBîÈ#/_?”¨ äêT5@~L¥bmš†Û¢ïóøø $¶¯Þž9cåÔ÷ #š ›$p5Ê
+3ÎoÑ¥Å"Y¢$猿bF6ÜEC¹@Pg`m3æ™»ÇN Z´.¦d¡Àubd2b¼hàqÔ4=CîPÅ}§èwyýù –C%8Âä2ä×t qÆhCUˆ*#ú߇¢7Cc%ÐB—ß,uëˆîFêªøЬ‰;—0ù%' f ªE¬‚™Û:!k.H0`ë`Ô eàyÅM†`0¿¼"<»JDÒÑ&§n“Æ9åãøc.â!'A•- 4u/ƒ¦0)Y>QóGHJ« —ù¶h±UXÂi÷.üI­iî
+Í9[QöFðØd!$më…|xĶLDN ©ñÛy°3ã Wk[øTÁ\%<Ú–,žI^ÂÀ¬­òK{sZä ç‘`ú2¼¬KQRƒ™hó-1†Øª´ü¡Äw7æ‰g««è}¸tdjUdZ÷ˆJ‹е÷ ™£¡![®ï*äfc?1Έ çfAx’+"²54[E“_X ‰í
+rÈ/õ‹½4d:Ànë” é!O¹UOd/5š¦yÌ%£¢4ƒ`4§èç‡"Ø–¨A3mxtR ö^7•&!R^Áú¢
+×èrÙÿ1^&¹•Þ0¾ŠO`h¢†u²ô-²µï¿ÍWåÀïéÅ # ¤›–ô“Åp
+ÓöÆ=ÄVg¾Ödââ½õ" #„Z4N²Òñ~Iq.²$¯Í€šx»ês"5éSB••nË‹d˲$>¢ªsi\ÏiïlÀ8ò²8‡äfIä&ê’q
+˜!²¼ÙS†Œh†\<ô|Q[4± §{ Ô‹pÂ~‚¼y)úÜEr?Ñú]„ý†ñ“Åv)³®°»_£D¨ç {)ÙÀ
+Ô¸HY—6ðÌy–›FÂ+$Á\óq°„\R«›²è?;ǽյE% ×\BÀm˜?+6lød91.²~?¥³ø8¾Å,Î=ú…Av,áøœDˆak³§> ¼²€=—|uŠ>ð|Yuãrf#Yx»›K+ŠIô—ð¢ä‡Iý /›ßþæB,ö7„µSºÑþ—5©KAX«6ä÷"aõ“
+£Ûª…›ÌRfa—€ X°Ñ47ýR¬AÓá“ ¶s)™æRAàkÛìUg/ôs}ù©[l8“á„ŠSº‹”‚_D7ÀÎÊ·C€ Ê>e™ì?ÒÔÿåÉùme˜ŠÝ¨5¾ÅÅg%ÙÖ7‘ñ9õQuRö];ìçˆï
+pªÅM¿ ø㸋Aêcxì-Þ©ÍX5³Mw—"4`B“˜Ž.þTI—­`ÔmžeS®™G4/ac‘
+ôÃëF‘ÌÎ4A6Š©Æc¼Í$¢ ÍÌ3@4&û~±0¯a/—tm,‚h†ZåTÿ´HT&Ô‘]ÒV¿k *«tÌ\Õ(–G\`‡ºMWäcaƒaâä©-OU*=JL,Ó(×i!z£nÞܨP„õIºäÞSÖÖ’Èw«^ù‚ìµ÷”+’ ÃÀ‡’ 6T¶W±I÷éœAþ;“›Ái” ÃÌÓÌS€v°3åYœZ<˜Ð*/ "7ì>[Ôú.âßáÃœ¥ŠË•jMÂW™ÄÙ@BÍîS^ºðmdÂ]Òà¬Á¾srqd u‹Y=1ĬÐÏŸ®z³[ ßùðâª@LÑø‡kë «ñQUÛÈ– º¾‚Í\´¹÷f—’=MÈkx´b„×s #$«M>Ê+°â¹·¾‰
+—ƪyåÐ
+Ò¶ÕMnuÁ§Qj»m‹ƒP‡cÚOf—ÑÆ(á«'4‡ôĬJ$EöyŠíÏUÏEq—‚b˜í«dűWØ‘“XÙÒ%ž
+Oy〞ôÒ]*óÜä: VfÙmÄàs˜FÊóê6€2Ž #˜Œòµh&×ÿ¶«ûéKl‹E'„öî‡m2!¤„M›8$[ãlkågB2î )¢15w%Š{ºä«Ù
+M÷sj1ÝïDìP döhÙ½B3€Ê(qÏÏàNÌä!Ã1ç‡ààs~V=Ñ–‰¡Vû®àUb¥RÓŒC´ó+±µ-ÆÄBà-Ö­ßEü ÚÀXø¬R‚k¡'òÊËtM±xðዘyÉ—’;3=}¼("ßfØ™Ûߊ*ª€? *›N‹,N®ñ"6¡2N¼kÉ^Â!š7«×ÃB$¡¦¢³c¶
+>qô½Mž×r¿Zw™ ÜédÓÿ¥¼L’ãÈ• zÝ'(Ã<¬õ—} mÉûoÿó
+/ý䞤:†ô=[ŒcCèÐÔ±xÕÀßånöP°]¸y&#&¶8@òC´;®™¶ô@r5 ™ûX”ëÇÄ è[?D¬5?¯G9qŠ×{½¤!I—Ùi4qßÇý[\?ßQ` š­=DÜŠ.ø‹‹ä9ÚÜ%Ô€põò¹YìãLƒN©9<†_dH ªˆJÔøb€š¨¥áy棭%;Niϸç)B6ëáPQ!¨éGÈäDî<Wq)f¾ rb¤ z’‚0*<ƒeÝ ’ x"ö•ñ)¡ùA²‰$VHäV/Hº­xN€@˜H 4÷ Ó¬OQñœšŒfÈî9 K$i&ÚK’¯Ù¤7¡Žp Å-I’Ý© ü¥¢OI ‡Ë¶Ït‘÷S’tÆýL’'Èkz}ðK9°rÃï‚B}¨¨´L¶gè¼Ó ôùΞ®uÎü¦ ‘ïÛæã„0ýQvïË DAøþÄäVVÔ$_6¦Ge@C‰5É„¥]:”©€ˆñZ»\(ˆ<bX’¾yS’©%qÚ9EB/’Ú>±Â
+ó EÁ4ß}.:YÄ£´ïqeÄV,ÉúØäY &>§OoÐ JÄ­Ón|Z挔¶Ÿ^tK‰a\ÓÁ傦‘Ê­*Ó?JcN7'Í<ã˜T´MºððI}"tª±•‰»À 4kRiC %xF¯ïGÏiv×Ì}‚A’WÎÔ¶­(ÁÁ#51þ°c’ £âGsC¯Áá3Õ°\ŽÌY3=2#%ÏüY|z‚†< ªåÇçÊfÕb'‘Úùò»–¬—ßêgꇙÐÚ‡Ó…S¶îÍôÄ‘ÀÀÄFw‚'6WüzSEÞ÷]ª’$>ÂXó9KEúb‰»ÏÆ?2È}‰u#$vüG-®FÛrøîsëîÂ÷û—³¿ž:ê]°9UÌí¢å D4ƒ+Ú³hlѬßþVªü¸IkêôHÉSGÕ˜õ€¸ÿö2³jÑCfÅZ¸BeÍeªŸã×Í{ŠCY4|„—Ç$rÅcxúu™‘äaÓç$L WÄö' ­ 5J'ÁyW«ße9±m“
+Sa¢¸ PæÀ;Ð+e½¼K‚ZÊÙ2‰‡O±´xÛU9BdXã² ;ˆôƒ²Ô*ò­‡àý š¿%­µb«jgßÛßPBâ‰'|¨aÙÏT¿GG‹ô!Av@ˆ¶T‘Ím‰4í)ÊêMÚU=NÊ Šm.T¹Ú;})>£T [œ&§7´ ’e˜Š´ûŠ~LSi¼žý*)Sô ‡ÐQß VÅ×JD`!÷lÉŠô':pÝ=&’câ”ï}ñªùÀ&V¸²>î1 %£Eÿ+Ûtõ @cXºƺm¥1/¢L—fý„8üÈRÁ­dŸwAº g¤:d[‰“‚g½HÕ!/@ïà £2¶P¶à=æ,Ú[mk
+ìS*u,&<01"H¤KÞ—‘”íÚÌÉÝdyr¹zìÁŠ`wøžø-Ø3ÒÛý©”礼äPÕj¬}ôlŠøt`Ø zÚAë&-j »rz}Þæ˜ïUÇìÕ9'ø¨±7äO­úóκh³ÂÞ,¬•æ=i¹ÔÛy_.ŸŠAÞØñÐí^) ÊlRG®.GÌ¿Wœ$toJŒušRØ-MÒô )íýº:J¬Ôr3Ò*ÂKr™«!P,´Áß/ots^ïØ‘MIMŠ&þ9L4•DInK—)dÄB—J_C/Ö…¶ZžWÊägT"À¥%íO!äð}€[Çzÿ­•¢L†!"äкaï§0lk\’jÀ›Ö$’È_üY2èžzÿé  Æ¥—«áÒver&‰÷¼Œ>u§¤£Å,
+6y&}Óí$/àêhûéL{ ôCóô"15Ä !ÏvN`V‡f%›½‚‡é0Ú1ølyƒlV¦äp4šº{ã…É…€P¦<®ÛÈhcí1)kLÙf™å§ý*V‚¡ñZf¨=Oå4<Ñ®Ž¹Êôbç ;ˆ07J}'%æ a—>üåCê[ÕoÐúý©6ôKB|Ÿ_RÞÊ)n‹Éð#(6Å)Ë
+®Š®ß®Ž®dŠ…û)×¹ƒíš— e'U7ùRAòbM¦üZä'×.Ò^Cv¨ÅìV#Rü|]™&S5²F‘µb¯â*ðà¦Ä.ÐRí÷ÐÈŸ Ç’\úˆ;õ…LÞ–Ä>‡$W9¬XËkÐíâÐB„ÈÙCLV×”:Iß¿M/ƒ1œJ}iZ­±´Ôš­ËÑ‹^ÖŽ†}f~‘C/Nþ±Î#ÊM|Hâõц£rYIüwt )BŠ6°çá«°>C–ÛþÔ“h[V†rD1嵊O ùò@š¢Ô'v >ËÕjÆ›a½ÊL-ýÐÑ5ïso€ÈhBšRÃV¬µ)äV8s @`ƒ‘Ô·íÚ#¥ÉƒéŠTq@Å¡.!þLt±[Æ*º"Ô™£¶iise­‘;§õ4¸ÝqAZSî /ÁÄ},$žvJKxo?¶R˜P𬯎Q4ÍYñ¥¼@4a (혡ø;ÉK/û¾)Q/|Tl;=Ö£`94§ìâ ÖòP“%çc€J§z0,~Ä>& Î!üŸ€dVWɇhb§„¥’ãÞgÄ*1,E=Õ¿Ô¼S:ÝÏh]òî·–m("Y¤?$ÛäeÆÅeè˜@Þáoþ+Ôä?€Ž­ð>÷3辩îÀŸüª­ÏJT…äá³°+YÌ.”$k[‚œ÷ùòÁ…zûj¡=Ðñ>ïs?ƒÌ™<¯e$T%g N—ë7þ –TX¸œƒüü,Ñ]ÙMôÂÚ¾ŠIÓⵘ¢: ¦‰$ÄXö§ø(Þ"IP¢ƒúòX†~ÝÆÔEî5×uÙ.&×´ìYŸÂê%J®åTgý¼Æ¬§§ ÁÅàøñ*ýÃé„ü6„8FXÃbœAã6mòfŠŠ_Þ.»&ûLQËzWË¢Íë˜g¨êáIM
+Fö¬âz7ªGd`þ~é~yÏLk»nÌÈ´ÛEØX,¯Š´jûü<®Ê›d–D…“â%œ.' k¡ Ù¬bQàmœÐÅ´{lz¦Þe…Š§ ýýËy³ž Z.ˆÅ™ Þ; cÿ¼Ï½ºq‚»ZwÐâ—HÃ7õhî³dÖF¼ ’Æ/ˆ¿¡4¬!Rôa‘,ʾùœp6Ðg&fC¤¬Èä.Hcˆ¹ â<WgãC¡/=µ@=Ðd›ñRíœÂšdIÔÿ/—äZr†nÅ+¸!‰úŽ«‡½‹šÚûŸö>7úf2¨çG+%
+^‘Jà9|LRs{¸L`Å&G^Úã=
+p³`v ÃmÎL‚Cü®9ºv*>µ?t­ù\»ÞM†0³ ´û ºˆ?Åä÷wï®)ðÓ„Râ—×^Jð˸ Öë0wL—’õ©Ë´c®q.s‡žó¨;„#„Å þY€¸áb ~%Ô?‡wˆüÚŠ{ž›3²¢ÚxJ`—O.nŸº}ÿå>S.¬àZ†b,­ ^–û™ETbÖFØŒŒˆŠ³©@…>h³·¸klx8rHäa³7"ÄQIn,ð8s?Žå#ƒQ‚Äñ-2AëÙ)a°ÆØ>x…„öúç`ø£öO›”\% 1"³Ë³¤ üƒ…Ƶë‰2ÔÆæÉ“é†9Î#d¢þ9rêÄFøe"¶w›Ž3©0ÙÒìáQãÅ߇ ¼,ŽwÌ fuð×¥Y»9>%múQVK–kècEOÝ\#o3XÜKRd<ãÆÎYŽç/EúX¥;°[°ðŠ &Èêã*IÜ” rµ­ C‰ž°¤å., üR]%‘Gƒ?_±ÝAT‘ôkmgž¨Q©dcÏatË¢ÙÝG®ÄH¤úµøˆ
+(ô
+é4{ÐQ ·²IŠ¦»„€€Ob‹¬
+îÚù Ø°b+?ÉìükNÙÞø
+^™(Å5qËÜžHû@ 4û"&1zÌFnbÈö*˜iê(OçÐ㪶Y<»(szEÓeH0ÉÚ<ÝWv)C&ðᜦ¿ÃøTíÞÆ^
+$Þ^ErƒÁè—L¢wNfðñóVÌ“øÌòƒ5s‡ËŸ+ñ ¦X"y‹ÿN#ö§"Oâ½¢‹ÄS½†L šçJ<ùŸ†>Ó\$^‰qNrÚoUýÔx©EŒ6ÜÇ]èNÚdJbvèÏ°À묯H%¼…]b OyRâ‡Ä§ù¦‘¡CéùAâ@ pll
++®ÄSÂþëÚl£ûO<¨5Î?‹â&ñ·"oæpÜJ€#O-ò$Þ+úx²@”«–4_šñà .ò ÈÞ†XÚ¡ET­ÛÃÌ/,£e&þu%>L¢„F2I+rº“ȘxäéÿZä‰ü¯ê-‘_ÿá<Å &_’–°b)»¢­U[•Ð»ElÇ¡ÄF«
+%èF©Â1WA /SºlZ¡¬UpF ¹*^”URÈB" ™I3¡¨Ñé*Úh«¨üÈMpdž‚mF¨p¢!ìSX‘G®€Š¦­Ä’ˆµÑ¶{…>Ó^€ taû ˆwŠddê)"k}U`£•?y=P% „µˆ÷Y]YÛ>iK1y·Hv¡ä zO-tŠðœ¡Àm'z«„ÐQ;gZæ‘YbÑàÐ9æèF†\áeì—s@€Ì™¼m3–KŽêü<!¬Py= ¢n‹RÖê1á"¡ä’5ËA/¤eäÿœÛ¸ï·¹ÁÆ{Õ}÷æÜ!|k±‡òQýû¾ˆZaR«¼0e¹ó~3ç¼·ˆ,Þ²Í oP“°l<;ŒÎlAÔt
+3DðçÕYl‡‘ǪhÊŽZpìÒvÆÁ ”ÄʶM‚‡(!sð•Çñ_­†;ù«eÈEÃG÷ÏaÎXt ^Íê¹M6d¶ÓØyYÎÊ:á¸#þŽ'†L‚Z‚¡nÑøqÂpv¥*«£l?.¢(?PY×e`:‹‚­Æ*1‹–ØÊfò½ècòß^²30gÜyÞ8G•È¡­Š
+ýe›3ίÐ?œQßêÄ0GÚzÝ×s W ]Û"™ÎOS*6g…*Iv5l•d¦[8žˆé‹å¥d‹²F t,G÷°•¢|\Vì:—ÁÃ
+Ü¢:î*áùaö^CæeÞ/.ƒtv?¬¸»]TµŒ‹Ì>uñe4Ö[ŒvÚÇ
+ç䈮„ôåó®fIQâ?#îOýBΙƒ’½L&
+Ææ%¸­ Ò§žàñqüeSÐÝ`gÉ ì%y~ {>aMµƒ-Ü»ü¬Ïsðz¨Z`Z€Ð…Õæ•ìü¯Œ ‘fMÓ+úзo·¬/ð#9Wži ÔC¤@[½§+ŠÂ_d»±ØÛ~ú¥ƒz5>^öåÌá¾B®ãô6 `§@CÄ)»§ˆ1°™Þ%¹°ðQtb,„b:i§¶ÑÞy¤¤!µ¦í/AƒÖñ6üî>gHâÑ%H²ù…/Š
+¬SC»j8%Ÿ¼SB‚·Ö¥â¶6ÑÁ×¢ïUÄb
+²JM³$æBàsHå±S(K56ÂØ
+‘'ÕÍÍ{rMꔚԺ¹y•œ05“ÓyÆúˆ`ÀMPÝZ‘a4k˜QYZ/GWÄ_|O=ÖCÞà*ÍnLs G¼ÅQì ÕYLñË™Ãmãý²6ÿÑn]ö„5‘綺™.gâÚŒžq¼L»D›u£¬Šð¹ÐëÊš}(êJŽ
+7KðÂ](uÑ:$Åð‡¸‹ûF7…mBš9Eÿu‹@2
+V–Ä÷,JpKVšµ 0 ˆÁ|yžÊ¶yWÜ%ra­ÔUf »¼!sZG‰òƒ «çX¬vÞ8øb.” Ðç:æœ
+­ž#[è€5»BÛzölÛ"¬¬·m#î
+AIIDª&½ÉÏÉ àU;sƒ?1&TO8›Ý@ ùyÇð´©"¡ÚæÙ´Vr7Ò}§„ÉËÞÒZ n‘FˆŠ‰þ·[ã@‘+›‹_Jï…g8uùôÚ×á/k¿½g*OÎ#1 ­í‡_T
+&`äè`ÛŽ'¢Kh#.§¯cÒì˜8tl«GLÅ)
+¢ö\Ü5E1T“ͽ¸ÐG1°Ö3½y¾1ò‡·¦”‰±­,cIÃ÷Ö}M M€,É›øçNðÕ ²OÞš†/Ð¥z>u5×eÖe&GwŸ¼5) ÉLÏZß*gíÕ\Œõ½ÄA¡üi%rAT'K>ùjJXìNOÈÇÈ^µƒæ›P2‚ÈÏÅä-}8wêW¡¼°Ícâ¾Çhî9U6š+£<ËòÝŒ5%Hfnؾ±¦ˆ=Ò»‚Œ«g¬Cû`­€Ç ÏY«„‰ƒbñŽÕ½:k·èjš]Îx«èâ¬ï57g-’“A*뮳YBùÌ“ÍÅwÖ¶yœPÕóÏÎZÔ-XÏÂmNÅŸžX+>ÄËIJ‡ë¬E)]6¹Šž¦wJ•ÇG]ø‹øøΓ³¿M¹Ž ÎÎZèbM@Gòœ5%˜ÍÀ×àÏYßè8k¡¢TˆEãm¾³ÖA,èœ2ÆÙsÖ"ö$7¡¤P]òû–D—³ŽÄHÙ²€w(&KkÀ<Œ‡×Þ‹nÊŽGû¨Ä^ˆ)ÉýE/Δóç‹Ï}_$»8Ù¸QàY­“^V²"›½9Q•ÐŽ©xÜ6ä;¬­„À/ÿÐ¥ ¨>öf6<j
+Ù"¦h¹×‘àðí˜h–¹‡mZá@LÍ°ä3²3U²å”¬/AˆS‘¶¿:¹"š‰Ò¢ƒ2gªà·ÑŒ!2ÿ×ÖÕ~ZQá;&c„Ü36Ÿ™cƒCY¯â?ØbX´úh¥7øª(~Ÿ^RüeÃÄ&—&«ý8II«’)õ<!Ä`[˜NÊV‚6¦Ê} ¨}Kö%µý© AL-O=¸døIC²c2v_€£×l,“ax/Jžúï?N‘‡uŽæ2p˜Y»¿(ºíŸ÷¹7Š.œà®Öµè¸}ÐþѸéÍÁë—Õ0ZVïIrŠT2±
+iS?&h–¨Äjïg¨Ùlì9#e¨(ö窰R•hl×Óu„ ûº¨M âÙçÐb6‰eHa S+œ‘
+f®U;†vÿ% 2i(ú:÷¤Ø¦‘Âa%QÍÓ63Õ‚E„ex#šI½É%‰î
+Ê0C豚†
+d/¯±ïè° y\Ä.¦ˆ•ßA¬$éÔŒ8qï­€
+—øTß÷qŠžƒÉüÛ V¨8 Ø»èìú—Õà.DÂ`¾6—Š2K‰'Û’‹¾ƒç­
+û©
+Å)úéÉ*@YA¶ü\EØÐ&YMeߨBɈ½½*A‘zÈéè„°Áé€-V+]#¢ËáÑž?ñúËÑavü_S@ÛmnÜeÒ€h>­"¾Q³à1-»³únä¿­\E¼2†Q,¶öWKóe3›&˜ìáEÜ54¨}È¥Іar@ÜHV"'‹¿äòçS3ŽõÆì͵÷ùCj —¡Ÿ3:~W%ØZ4¨bg분²{ˆ-Jn‰l>wdÈkZ&Á+‚E›8›ha“¿×Ü°È!³(k„å;§\V4Ʊ^Ž¡!oÁ GÙŸÈl/ÆÓ§L R
+ùcY¨|¯û½xæ¡púò|q¼UÔX8û3 ·@ȶ‹ú µð^Gb·ëØP.*œs¯D·LB«G«'
+(øÑÂ¥ LO7¹ó·0WS<È;=B÷Ud™ÊzÕÐÊ3ÛYýðø-ŠqÅ…*ÌâÔ6WÐzF« ûõãeŽ#ÇDÑôÚ¦1È}1…‘I—'äõ˜º¿ÞÌ°»¢À
+~feÆòeY
+ˆE9œ7–K’§l÷2¦š2°7á°ïìª ·›Œ_aȨ¢<¦Q'ÒC4ñØ =.î9 Ÿ$ÍÒ7»5E°šqÍ ö(¦{^d"ÞâY'N ³_A.?xAño4ßÔ8 ±^j‹³¦?
+‰¥4Ú%èõâÐr ½B‡c >üìï\¨ZGŽ.ÇÇžù”và‰Q;©Ï•»¦«…Ø˱ôyÛl°€YZ«_"êbJHwoÆ€ ˆŸ¢YÛŸúà þ´y ì36âo&üZ˜8‡‰¼bÍ’cÙ%mDüëØPæÚLÙ̦W)ÕÀ ƒ‰çI›æ´àè-%ð+‡nìZ‡QäK¦nœ_Y ªÁïÙÛS ˜(V[qLØ„/ $~(ÄÀlœîžƒ¹cEù L><Òlð†¾+Iœ©G"÷DµÚ@é„BáD¹-íŒÓ¡ñß$Šài:ƒ©ý¼y ž€ì´˜QWÈñ@$R<žIƒÒìcR úÀà CßJ5°8s_yêÑ<"ˆC ‚Š¤½b uÕ˜RT¦%ZîËÑÓÝE¢Ãj,›Û°d¬–ð°6ŸÒÄÔÖM¶j¢ˆ9;}‰©À¾!ÁÛT¼s4Z-‚ð*Çe WH¶Bvk†±& ¬\œ<åSëÆØ#Š]Œ
+Q1ís¸Xª‰¿cîζPâH ˜-¹™õ©×¥ëì¨nÊ^Ÿö)f­¡ ±8 Ç±ê\YʺAYÀžb·Ì9EÌ\å~ZÃàÀ0XZ+òì²
+ü´!¶FFXþIåJph*ÊqÄ<Äà,-œC\‘qÃL„„ $nb³œ Âq&‘Æë YŸÂ¾Àã­£øéâFóˆ#YL%HÓ&:Ö«?\Ìãpîûys0Øû àV‰hT!`7ÒáXâPàSÚ¬îÃ_L ª${¯ßUͤìÆ#’g²!1
+TÚN©¥bF)j‰;oªŽ±Ê€p@žÄ‡„67A;’\yé»v·˜Y* XÚŸ–VkÞ‡^3®TÃÉ‘ÖH¦'ò(Ø£6WYF
+KÖ‡{J¡iüiÊð7Árw\3<$ÄÐͽl¡í™1lz¢”jÓÙk’Ðþ’2~’±UÖ µœœ—“³æ>ÆéLÙ#£”Óª¼`6©Uù:ÔÇ^à1q2fzw: \$Én¨¾ì:TÇ#àœ3b5’:¥‚“¦DÙ?I-!`ûÕ/ÝÎÚÊ¡šµw²SNaÖ—˜»¬°£vî'±¡œÂj¯ÅÖìR>e¸ý%ù{²‰mé Á̺ˆ¤Õv|éú½À†`ÚÑAÅ¢¹­’ÙϤ­µ7‘…à!™ßÝI˜BìDaj=ªI
+(ØÄ@´¢yN|úÙÃ6àe^½ˆy.qÓÅ9É4ªC/æ²tuœ=ijA‚RŽ¸vÌúè3ƒÁ´OÁ½EL0—q÷HÔVç@àÆБǞœF£(=z±µ$ˆõ‘‹ÙŒ¼îÜ5mƒW¥ÃEý$ÛŒ< ]¼Ÿ}\€hn“;è×
+oB’üç~˜ì®”µvS ‘2%±œùÇ&ƒÒ&ºÕ\œ‚¿lÜ®¾vahþMQ´3CÔ&Ÿb?‹#Ÿ7äE¡h³ ¿%”q¼ Òô°8t+E¹~®­`ØáMó…èñÎê(T±±á~.ßœ[}-sW
+a'§mõz ôж> Ä¥£›)Þï+RãØu…vÄ\UAûú<êô»Eæˆ(áItØgw ÚÊÆO˜.¶ðíûOçÈËDe‡Vö»h2ÇNó BÌÚDClû2Pg‡õ'[[Øôò û…±NÞ1mݳTSòƒ
+ÿ*ífiˆ±ËðËüN"PËTh Ó&4ƒÂa¥¶ßNX%t¾P¹ʟij²>{r7NAR/ÎI¡ÇH‘K7µÕ•% –¤$’Šˆ<òû‡û—_LŸ™V»N ¯õƒG!€Ìbø.Hí‚;¿d>¬]ˆ†BŠSmµÅ t§bðQØä¶Kæ #k]´ ‚׬51»íRNÐW˜¢[åòA3¶G‰©_t jâHÔRéWç =ü‡R\˜‰S½#-öÂ$ÊL 1½è>oÈkD†UPrì/v8½ zeæÇ;ô-–ÿñëîý{ûñß-Þÿ¾•†× ú{ÌÑ6 ¼$©ìÚ2š éwÙ&:Ÿ­q@?/@Ùî å(^=.@Aîê…†Ò]>©$Ç·­ø°]0‡«B¶Á¾…`®.-ž…Ÿt£uºËóòï0q ©[ l]­JªSñµ4Kbd‚…é1´B ‘pDB‚W¦yF¬I[hÌw¹8~ðó8ç¸ÊüŸñrIª,†aè
+z¬àU¾Ž3îí¼ýûÈÎí„‚*F r[–%Ù>öŽäš>ìØ5Ši¡j@ð­’¼Á3z…i¡ÉD“v^D)_­£ãl³Ä ̬/u•õg1ùüøEÇå·‹ÈÁ½>nÉž.afý#z bŽ‰­"‡nŽÇé*"ù$Hj>‡a†²Jx?ÖOÉ[a°‡÷>>¬ÅÌÏÑVÀ1ƒÔ@°ê³å ñqP\¤v ¥Ž÷ï—¼˜Âãäww€–{© ݯ~A£Œ\Ò䪮˜BÖƒñêR|ˆŽ7tŽúÕöðA'ìì)Ä«+”Aç;‡[BHzZ‘<gÓvÄ ùn%{X’Ò]Ú‡F¶ãRYïl¼Ã_beî1(ÉdÜŠÓG¹Õ $©ìdQJÞû9•PƒãßЬ&Äej”uç°€ðxÒãWþ¿
+¹uÅØ‘ù Pp†GÁšÒ²™ýö8ÇYrA˜K;%fSö¶ñ× Uœ2ämÂ^U¸J-Ž¿n ê>dî8„çI¾,²¢T-½ý'È;ç¢oiVë šè ÄÓY]áÅv}ÎQÔ3‰S Z(vuõªÈ·&d¹BâÖZo¦0õ+"lmÕ˜yZØžš"‹ò±ç˜aEiðÞGÞ`4Þ.Ór“͈%1¯çÔ8y‘]Îe>l™°9£É­H)Nç<›»×RÕŸ6ùW¹‡~Ô„DV=ÈQÞ‚M®KÂœ >ÅTT(‡^›SÐ3’aMȤ–È+šº’9¸àN*¢ÆæàTœ%®A9 TKؼ£œs\\kP
+A^ŽBã§`Ï>¢oƒªżRùüŽaèD¥uÆ/–
+H‰Œ—Anœ9…Oà;x`
+"ERÒ²‘^z;'0ºWÎrî?%ýF\¥Bìt’våY¢ÈÇÇÇh¯zÞ¢ˆ´Zš¼þÇdÜ|ô6Fáw«¯ï/gPZKXU€œSo¥¹ŒêÃT-·b…¯Ze´1!UJmÝj¸ôäçË¿/åõï—„©µøáuA[ïÏJëœÿk‚ø@GŒ^¼ÙÕâ":št›Wv7Qþh£oHh¡V[Ó Qù8¯c_e½ht¯@gê-À[ot]Õ œpŠî×õÌ@ãÇÊN@*Ö´—¢ò$G_ +׈•sµ÷8ž£7 éZG’üû(fÐû„hm$¶t>ÛÏ\òýˆ}UѪ1¬–ýô¼¨T­š§e°J:ÍLwÁH–GkëÑ÷
+…Ê:V³ˆVÞì^¯GÕÊÿ[q/âÔѳP„#"™5´§&OÿÈetågÂR$$Š[…\LÖÙqÒBè]]F'D-K¾RL7ŠYf/÷“ô=žc7Zcب@eGCü¹)DŸÉuÄ‘ìëU¥;¦F }^e·h'T¢:²³C*Ë@3Hã< -4€AŠ‹~ô²ôñG¥rGÞY/«ž qÊG´/÷Ïr>`Ð$QQo¦Ñº«i¡Ñ*]ö©}(7Ùé¥ ™$wB/Ñÿ2:V8ÐïCèã;“ê¡f>nÕ$%ÍK±ÝçœìA7¢V¿&È9¦Ò/v0Sª›w*‹<áªN ³½ú±ðå&É[1ÈÑŸˆŒ¨u/n̉öäæ!FIxE‚t4„ÎNÈì-f
+Ÿo bÏàˆ¶åŸQEaȪÇî¿J}8—Ìö5fz© #‰[œ…!Ž !² ‘Xj–m=¸=Ö"cæŃørÙwAy]K ™¶¨x}øY‹Ñé7ˆÅ[Þ©(“+õ]ÅG01 àz<sÌp-L·Øå*ÎÄ¢{îaw¢F,¨9>™1jöî*V¹€ŒšŸ0”&Sê(“ê
+™lÌ©P_ ﳚ°.£|ºïûcð*žöµ\¦ø.–À`Ô¬YÿM‡îŸ7ÏŽ¢ƒP8=¦&Ò7år‚™ªí˜àä¡P'Ð]ÁOÑ|eÍéQä;äæŽÃ‡üÞõÁû)×Äor¯Èõ*7¤`¶]¤t9‚Œš~.¿ƒÞVzRÞÂI±dÁ"Hs|ÜÛnªBà2Þ÷óñ€R9„õÖ Þl0–—­ùšeá䆻áeñËYEæÉÄĸá°ÒÚ¦ßç0Y„ Ãf’CÑÅF÷mßœùÍÚ[Ÿëm‚ø~°Ü2Ê–ÈŒa‚FnÖæ9H>S¿½_ÃŽçå^Âé E¤bˆÚ^x  ƒ¡fåRó19"w Ô ·' &‹å
+INlæþ;H¯ôk/¨4Ï@Ì_3…QØV‡•k”ý>§ÑéÜ̻蕛í^°É}¦ÇØ5éI–G½,Œu!âl1Ï¡ué²ô˜£‹õÇ¢'¯ËæiÖ\Ôº~ªPT¬íÈ{'?jÔéÖ¥ú´Š¦-ûo:÷”!¬¾çè>ÿ=mKfþºÇrkˆÂ²ÔCI"®Wr÷#ñ&ÓAfSŽîfß[ßÆ–ê)Ø–cô ‘$
+ñò†:Éñê©:%·µÏ>;î˜Hȹy%]w5¨(ÏäJX¿ž^ò
+ÿ`È'ǼàjX»ˆüx„φ&`‹ÙWåÈqZ&ê„TÍ`¿OwD®®‘¿Ïƨ2p’ºihi›èœ;Î"Ksu¼ÜæÈâWÒ^¦¬
+úsò`åm}Az-JA«l^0ѲܯÝ1õ›oÈðج`#™(T\¶UE%¯Á™.áA=zŽ=Kϸ&.
+^ç ¥-êx=pnžhpõO >Rc“ÍÑ÷U òÛö ¥O±‚h²ç­dI› .¿ŽfÁ€ÏüêHÞŒJÓ¿ôJ¦Ê塪ˆ«Lˆ1:²jxÛÓVÈ£‚ñ8³Œ¥£0õB÷|£Åé°›kàS±­Èy9OÛ’WÁ'D‰Ò=™¶¨
+3=ç"zÆ-È}J3Æ˨ô:™Ù§9/¢Œƒ3l~B)ÚYPýÙWá?Ë@‰ìíE_HÿiLÜýÉŒD§{£§n‡í§.BhœyœËPN~±‰röD ¼SV Bv1SUrú”ŽDÇPîì‹èxo29{/úO< È[øœ¦ÉO9ö
+ÄO‡>æ¯H’—à-5‘.KĹê¿Jûß/î‘Ðh‰d®óê—M"Ë…LÊ?¤š7df[AÍÏ2Æê²’ND<#®³¦‡
+WβÉø2|ž£âø šÔ½%« º¤È_ÌðW`ÌñŒùݹI
+AðtÙjoçªg®Ñ³ïã\Å¡znw Å/¡iËÚW@“@»S¹Ø8{L ¾
+Ó©²Q¢îz‚e0 lÙçHšH]3l¿ÿÙÆ^Ô3|½MdÛì<ŠµÞ"±“ÙýgÇ°bMÞšîÊ„bIJàüµ{LNß:Ég=Ü!
+Š.k§ÝY^VUªI '
+ôÂþ‰ó3)Ò°Ó>¤“"0 Rˆ®Â*p°»²¼ Ý&¬Ñ¿3¥lÈ<Æ߇´.óH¿Š&§ œ»Ï|h}¸›Ÿãx#}÷546BË 7ß“!Z)¨ÃPÌy®z!]ûZ¨äV±ætç×øa ˆ%œåãgü
+HØAï:(maŒŠ62™hr·z "¾)Ó[Ðßa`.Ф竒óû%hh\«ž­-•¤“ÞŸ@ÎYLÌTHx`Ô-Û Ú>Å¢ýì@ÆîIÍ…ˆ·ñx>‰Ï.…³~×yÆ?]¤hkô»,ñÊÇ ž@ñ>ÍOŸÖ(dBž,ãµ’<Î1Áv2úù¾F˜–)UÚµÂ/ük»›Ÿ†Ð¶6ïÈTÖ<Ôbö×j3Fïc†[QàE.²Ýìày8ÆdÝròŒB´JHµÑÏîE7ïÔ•)J#úý4¤cÒÆÜw+ƒ%Â46T»O†~hÄÈýˆÎÄMwŸš« Ôñ&MÜs%,§KØ.×I!¸ÌêcÚ9¶æbïI[šQvˆò¢]ÒØYf=0äM™ìt;˦M´h:›ÝΞ/×zõm©·¸iëc_óÖ¡FŒïÔÍÑÚçM:Á¸
+™E»¡kö‚1»P×w=¸
+6h'õ¤BPŠ{ïg£
+¸ƒ¤tëúÇi/bFæmÒ&¬“ç/3±9­ªmQ¥š¯s¤Ù©’Š€nÑãLÕBœ«›õÚ«Ä3 ª]ŒÄìÍÝ9 ù#2‹É’æºïYÀM]€Ó¢­‚´V<„3&æ r©œ2eÞÂMí<'úOýý?<X|ʼþH:¤¦9í¢b
+¡q@"9ĬO>•juXUû,íyPä±¼Ÿm¨
+â¥ò=štS.§N¿_E¯1oE×÷P)R
+ð¬ L&̉^¯yǼâÍ…ò–ûbþ·.ùØÞâÜ6ÑHªjçªg£¯`жÏY`˜VÇyÕ"MõL¦«xÈÒZ2µöƒÒ™ªÌiÙÍŠOë3å¬PGPø>*ŒÈm±Åb—ب¢9G—Ø¿øÚ¨ì¦0õlÑq"š† <âÍg¤Æ°Gbq:éÚ‚–œ8ïaàZŠI¶dL¢UiFÚ1dHŽOà L¦Ö©<ÏU€3®­5Ùbµ›Btôø @H#^ E ­|i}‰J
+Y&|ÐmeÝ_8LMŽ w(q<FÙù$MèÜâ=èKȱþq°¥åŠÀŸÙJ›°‚>À6I†h)ÖŒ:b°¥u±áçRëÆ`›ä´22]î
+ñ¶*q7éÝÒÕØN’Á±
+‘.ÿX2`È×uùªSç¡W–±LDä|¶µš;QÀŒ¬»½ôóÅÕ².×æSS[–Áo—ÑÒººZº‡úÀ,’˃«•A„3öÉÎÍ¿¸Ú›ÍüâjkWåjóÏðŠã89´ ’.äÿ—U(Ç`‘ýÒ¯1°(`íÝn05[0/cë$G;ñªøÄúî¹&B#z E9:j©YWIªt4/[t›xÙ<ľ¼dŠ´é+*|‹½ÂV=Š9ž¥§l ð„~)úõPÄùÓÀ'iê}QµÜðô¾¥‰âzè·¤FžŽ‹câ‘âxBm•ð0~õ’Ìדh¡ô›WüÓ·âîÜS¶-›ãè
+ºõ›¦ éàCÖ$A¢c\¨lÃ| kšèЕ6Õ‘%+€€µy¸WAÁ.y’‰Vì°3ü°è4«äðÀo°"}µY.Ä ¼!,†ë
+/Àå=„ìÄ£!í7[~iü«½Ɔ’âŸêÕÞSËñ¼s¨“åe&ŠÌžJ†’ÏD…ú‰>Yàcwo¥°V$í6ÇÅ
+«ÏÓeåÑé3\ÔZ[‚„·|%=ºÉ4äðNÝE
+Í>Ób05Ïð}Ö/J&– #ÌG³ßuÐ8”´òö#Ý×Q†[r­pʼn”bàǶ©r7¹Ø•`ƒà+ݶ0ªb‚,é°u4aóÚ´ ŒÎañeŠìøˆÁPÑyFîŠAe†¯¡å¼}è€ìJ•uy¿…ºMñŒ/”
+‹Þ^$GßŘxÎ}/ª1Gm¦~%Áßq©X—ÓÑ>l´ taZÌV’Ÿ‡¾È•N¹“ÿq„ÞÂ
+ˆðAÙf ŒW©4 VR{0"3÷S%Þ.M;p½Î:Áà/ܸâ3²G òÐö°r$3dÀ!ÖYUöôHÉ|hXNMqè
+u_¦`*¤Ê5£‹X˜Ø‰Ó؇ –RxËL2-˜t~ËÖKÑ­çL_Fš2–óÜ·Š´Ì€Ô×ÌY¯EÜ bÝd}ÌçXù­(ëúÌ …Æ*Àít{ëŠáE¦ ß[*8òxWêÕ(ñUe
+Å8‹se#¯äî/øRsyœ©(;+˜ÈšÀï}eæ÷ïÐ÷¯“½f£ibÊÚB¼#ög5è©!Då*¶«‡>©d’û:–³Š& ôáYð#*YºFFs ­„…yÈ,¨{¶˜¸ ùÔ'Ðbj‡j“òPÕV˜ õ”Iå÷pΈ©¾§ÐÒ½„½¡KP\rÍ…à[™Gõ¥ÈB>jûµe*“*o=ìµæÝkºÜ6ËŒ¯Ï5ªÀ¡ðþ•nìqÆÑq<T—5ð¦û™™W‹£$YÁ´…÷™ímIk ])#¬„t“KÁáÀS%®Aš™¢„q]WóVÝJPMÆ‹Kô=×"¢%ä£84÷VÞOÌN_Ö1D’ºÌâØ[¸ŠÈ´Ò/QéO?z;$§ŒÝ`qKn.Á*³äÏ1Óc<
+–"ÒÃêÏÇ£óÑ6”8üµ×¡%PTöÐb8:\ŒìÁ3è%c`‹>ؘ€V«k5”³ÉâkÑҫÚ¼í_‹¤,¸ä•«ï…çâÌU¡ œV™¨È$ïÒFV>H3qæå,¬}¸ëRô¿òúþ –AýãŸ?° œÑð%?÷çW@%ÙM?ÿýj'â’0^\Íï|‘pÄmš ¤÷LTL3»Ö½ýº RÉÃnšŠ.Û}-zÿΙ~¹#ùÛ¿~üñî‰Åô›M“ñ_eºMw|s@rSÚŃˆüH¡NZ߃ÁBü‹\U F×è~vM ”Só
+ÚŒ€¶44þ—{ãõ¹9¤ 0@½÷C‚•;s}»h¨¢#x†ì^$KŽ5ZÞsôÝÃY&µÄm›H{z Þ¹DÆ –¸:Ä©¹ûó"¬qeÌJô
+ˆ8¶å…ö:PŸU¥‚xd=ÁüĦºK“ ×ÓMY™%^Vl “hm"V?Eè’üµö
+BçÛÅÃ[
+ìñšD-¸LövoEFƒ·
+…åÀœ‡ù/ãu’£ÇDø¾ƒN`$™3×î¥oÑ@¯Ü÷ßö÷8VUþ {!CU!’ñâ Jj·ä½„- àLÉ>*ÿ£ Ž¾ë{Ef€<Wlûã·—š—Å,¼µíG<HûÇE{„
+Ò,êÖþå¶R×i,ÌKüg—šP>— d&Æð
+ çÑ<r­¸ø¨]'%Ý{Iý˧¢Éã¥$WÝÈXOÝ9†Ü½œc´p[ à\^ÀsÏlfgQ%ÄN*z¢M ÚE’ñ¯"{0‚XÄÿ÷òé)mî't]†Ä|k`!ÒIçËÆUGH!–ì9'þˆ¿¡¥ýœ=&nQà‰
+ xÁ^Qcü²ÿ-ScÛ’ŸæM®M+0éÐMäp“4înE•”«¶xû‰tØ64%›.\1ƒ!©±/À
+^P»o+y><“Që܇4ùÁ©W’Ö_£ÉŽ–_±ÝZ+g²/aÀm|9?ؼ Xë1Kb®w ï~ !I÷žW1dnßL¬:-{
+Ñ•æ¿Îê{ôÈÌq"pÖ Æ™–swÔÐÕ;ò„þÝÊJ¦íË´;0’ia¢8_ÒÔ„ú™¤p¢È2ŸsûÝ®¸™¾1TòeÙvͧ”t¯ç«J})Wù}MÚ¥&Ïë9‘—‹A®¶^lÚwÅatÖB~l(Í›Mþ+:vÿ$ôŒœ
+[Gå>ÕØIvÏð&œÜ5Á’ók³¦Ât€óŒ4ú=äÀùØðÀŒAP7H»æ!Én¥ØxíÑ<È·CðÖ&†iJhÆ· o¨èÔ:î ['Ù'¹Æ´¦ô¢oÓe1ÎùáqùÄì
+ÂÆ,ï;Vá*S`¼øŽ¼Ó…r¯aÖ žä´ví/a²—
+Q êK
+ýRñ—Pb½çM”RåÕ^ܪÜ>3…ï·ž
+>S„ðÆ]ôj~”.DïÀpõñÓŽVf¬ý*"fGÌŒÿ&(¾†Š“+B¨(#ža^õ5V(Š±»ã®çWEÅE«ÓÙs¼×1ܨax
+S2D?ÕÉÚ S~ÖUT‰çlùãžE~vúxÆ9w ¼oAÿ*9½f¯(A‡úÕ½='yNÛ† wÀ5‹k™^Žü gž¼O£+< +UË -©5ŽéØ—«8KA¬sâ!„^³¼ î6÷9¯:ÑìƒÇ‘ä20çA´½žösZ \ãëôv1SŽ*eŒÍöYwoË'ÒlF3oÂ
+qÒgôtZ®øCÆçÚ2òPvĬFŸë|1ÜìañøýWÊf47ã=Küý=©¿±— S6ßc¾Ìiü¿ ÷’PÀTžùÝ6P¦¸Úóµ$Ñ£ÉvÚ€qÿ~+?þåÛcÈó%*.ÇiÑ8™ê§÷ÿ*"ÌfÅòѲåñ:x(/_ºLòþß1”›^ŠR¢¹m«W|6BÎ^€ŽóõAѬÈ|KÉD‡F>N«‹.2_³HÛÏýŽ*ý˜˜ 3=[¤ñ¾s¿švŽ’šÙ•F®d_Òʼ
+_ô °FFƬ²ÛϧŸ#}>-Ä3Í…'Š@x³[ûï†DT8‡e@‡Ø`¤:˜g1t0WÒö{å/½sQ/€¸§N4‹y(\¸ªÉWJ,™OhÑøk]õ­ÈO·xf˜}Æ9'öàÌ|Ã,9bR™¨¦Óãíyt·N9j
+Mê]ÞG šb]xÆi ¢D@ÁÎòR2®B;;Žu¿œs†q…™‰?Qµû²´gûñô–y‡1õ WŇY/.fªÖÚˆ„ó³ –†™Õ@z87ß²†`Q,c¼Ã¼Èó}óÉŒ0’«<ÉôÆ(ûb™ã~L×ÞÇmŒ{½:K0¡çš:ƒU‚‹x!Ýß(å•'ìyD-²ò¡ÂßcÅÑÖEÿŸmþDL['&Ð!=þkbZÓl·ç8²wbÚïúnŸ2ìΗ¢”ÈAØÎUBcûüb,– N˜„Î{–lѱÓÄŽ{n´˜&N•Q„•ü#ÃÜ÷sö¼•®?G™OÞØ1Ž£Èfw/á5¬CÉnM(‡"1§y<kAÁ½tásáÔ±}`åãú9Å­f꫶9V¹ƒ²náªQ’¶XrT8án¾º08f\å7Úήµ à†xèdˆ²vöâRç1¼â‘Ðâχ’È¥3¸ø6äú­Èg™¥gê1<(ãcaŒñ÷ê°Ü,¹ ŽÄìyÞ«ˆ¦9Ùßf¹Ú)—Òà¥äŠ>s¹
+\lÀnœiv‘ªŒœýOs.*þ_ÊöÄ– ‚Ds›ÛêxŸ€øFÃÑBhè^$[ØÈ“Ë>ô‰"VžÓÊËI œª¼C{«Èkœƒú*ò(ÜÌ0SÊÔ—³|·¿ê25àU–j:îÖSQ;Zœ’h-B&Õà—!
+Pu}Fu¢`Ð5øŽ•ï§Àþ¼QØòp­ëÓ¤òøžZ¤HQëùÔí€ɬ‡9ÿ²>’ ÀŠ÷H'uÙ’rB`P&‘?—ý0§Ÿ¢‚ !±öÀ5¾-ཬŒ…¨g ˜6ú’DÔWØT)ŒÛ`åhDœ« ÊK øèñl\DgÇû÷›
+bÆ+ìT÷s„dÉ¿„' CQN(Ù‹)\ËLØ0{ùÜ•ŸWîà:&gB¿sì“Êì é(1ÜÄFóÌå’X¡O@Çxè&øXésÇ71ˆd sülviLwÕ'À”‡€5 .Ãhf')2 ¥ìc‡hQ«hëÒöuÜ.¿CÆ9³bMzKØ’­qZ‚ÇâOÌÄéìx ì»
+7UXŽ.‹ÒO3߆‚ ãràɼ™U‹!ÑîÕ#„S²j—͵ÓÉ©Ììr3ør—Bç0³œQ€:THgèHt;éçÙ©è6ø·aÌ5Ir=RA/2„`ÀÑí¸ iœ}’0k<yû¸Œú=ä â;w¼¡Hô²Æ§-|ñ >wÍ|O†ê(Ì´Äf®ý)déoVûj<}1´«l|Õa@÷ å
+ÃÓ{rH§šäêl¡°y)%xfõdìæDÎl‹!TÄ°õåORa´”‹gB$Ð b¹Ûy:›\¦¤¹s´Zj í*#f83!à^¾âGáâh<¢Ùöl”°E
+”šß8aû˜6¼_~™ÑhgWAÅ‘5œÚ%$Öáë¬x!"( ¨:2¸!Ô…&T„ºcΤƒ[Ä–—éú5Ä3 Ûhò´öp›È¢¢z×<ÍdŠà_J‘–$;PyI³~qTžJ]Ëò cÅòj¢ƒ »~M‚Q'¡îCña—šCb¶ÓŒ•‘5Xi¥pxã÷
+%‹_ (˜pZFI°ãAòôÆæK¨äªÓ®"ž—Åt 4§Hr8¥½ ÍK• Êøf›á®32(…„žª ™Øb–«\öj IJcï¯ËB@±Ì àžÁx›OG—ë¨0Jæ·Ÿ»”<x ùãÛßß(RlIm¢wÚEÏÿ³c’ú‡2kiÙ%èÏk¥ÇRd” ²ßƒP#‚ãeë1H»^åþÌõò¦ ‡´/Ðú6`釔Õ€C2¿ô™.çÄVýý Ï\ÒýVЀ3Âq²õŒèχ ˜
+L¢©øÝï!K»AD¯ü£Â/°{óa#HSLã@ËØVðF“׊»5B:“×ö¼å‹ÒØ! Ž”–ÙMgx*л€8>ú‘x”©ÜÉ>§‹-
+ˆ@º©‘ŒÄ*l1Ó‡&
+
+P?W-’èq ~)Ìèƒa¸4Ãàa}#Œ(kYázÓ{Ì[|@ËORäs§.瀓Y7\äM<)ï„%‚WÇ‹qàP(Î>©` ¿K§M`‡\)³ëo‚EäÒ§Ý ›¥Z%Åw 5 l–fÄmÐuQ
+.¾×îBâõ¢Toy!+ÉÊÔŽYú²%Y#¡T2SŒœî±¼ò£ º Pdb *DÊä}ÅÜId´*C¹CÔâY@ì”nT…‚c‚yB+Þ¬‚y°sËnÛ«µŽ *@‹`ã–¶ãû…Ñ?}¡bÈ*u
+W»)D…
+£ÎèèÏýp -P„É~U2
+(ÝZUxú›NÌNκP½5ã¼_5S4 å !*4œaÏù€óÎœ=+™(œé½JzƒO´ ª’8
+’
+%÷¹×:ýŽß¹çV
+c£)8ŠoÝu%ò¸«µ÷^Ñ/±2äÜž"çè‰` ñÖ¢B¿(ÞyÕ·LM'¬œmÙ}z–iÿ(™ð„(2o8ŽùT)ºd5f0_ðäZ¶ÂózN£/z3'!~’ZÍr¼”Ì­>'êe“^yûæVNbN÷azŸ3ñ‘hTY[-Ýu(Ý’oÕ‹Sf¶ó´×¯P»_î {ô[x­%§AÆ(qV£qÆ ×*Kä€l ¾¿J„"e+ˆT¢Dó¤ÍW±Màȹ
+ †,$¥óAÁ,qòãnk'į€º^5» OgÝkîtH¡©¤ÀYâ‚¢[hÚ,YÙKôÙã\æ€K.NG ¯½¶‚´‘CšY{`%š{Äʯwi:¡j1ƒz±þzÓ󶮭¨ˆ[Yí,žõ)Ád$,=Ç¡°ßê4yrÍDêmû¦$>¯ýñ)ÿÄ_ü5lÈnn"n<¾¯O6œl&0NÆ|-Ú“ ©4î]
+¿¬ãAòÈs¸3ý«œ\€Cp
+î½ü>ˆä6.t{vù(¹,$Àøì=V:"hôÿI?¤Òá´u¿_{FxX\†sÛsÌë™™\ηÀ1pBÿγûº’ ºØ#ßGÛýÍ:±RAb+$(qï¶!(£2K\Ù°kÙ³ÐX7öìx¶â ¸eré©ž[²B5¿^ÆZÁ–ZæÇ9ÿô—cµÑ3²ŸÓÇ[hœzNvø$ªmá»ów,E£ôæü¹ÑWÚäj—|S²™þJ¾±¨ÇËõïJþ ñÿàû¥øžÏ:ڸܜ9ä&‰+x£ø~ñ`f•¥Û¯—¢1ÜÇ2w)Ç«$¾PÔó×IJ`„ ßY…ÿC¬{§ì {ËU¤A^'LÝçXÎíX%#ñö¾I
+òGIËÜŸíYÇó iTÛé\ƒiÉ0ã“"ëtYu{ð€.èAŸ“Q†Âo×Z;qaÄb{ÿ¦DŸ'd”ïëÙêk‘}]˜®óu/Aô­ä3ˆ¾Öp5x¤·çÄN¶‡`Z¥C:j
+,r>‡ù`Òž¤pŒ&ñß­¾iLsïÇÞ¿YçþMÉÿÅÿ|s«?Šþy5Í‘Ĉ
+Ù×%XÎÚ
+Ô×hŽ”µ¸÷ð3/—@–Š>†ö—ÇY
+²«©-*Riº¢ÊÄ“"؃žM\}|iÔ¡”DÙìvT7ܻėà7p,ì.¿ ¬ŠÃ5_0Jš”F¤[Χf—d1žYNfÄZ¤µsXìÅ¿O>ìDJŒMÀg[‰ùôÒ€úêoUÑÁ
+T¢B5Ó
+MB–iäWGœcãmt¨<œ `ƒXðVËK€#÷cOÒqpMÆ´óðø7f0•wüO ç"l?«qôÜpþ› ÁcAq˜/}/Bý
+9 O¡:?Gö+ߎT3Þ-n²÷ìŸ"Á›p@G£°b¼W–eåV\™ùÂÉt ŠIXU¼;¦‰ªÒÌ‚í¼D•³U£j2`QÄýXÇ„Vønõ+bU‚,ºõœ€Ë¦_FæªÜ&%>a# ¦¼ãKÜ ýÉ2E!éb&æ ß&Ÿ¸ƒÝ…—RÄ8õ
+žbó«êS”°öôEã<›þ€÷øL¡7¨/Óâ=µõc¹"i§Ë%þ¼A ÜjKªy£QÂ2ý¥S؈ –m†P1¥XÉTJ%³¶îè‚Ãð 0{ÞüêUDǥ"Ì´Ú9p†å:|…]F`S[Z*•ÒÜ·é^‚&q>-/A $Îi–ÄkveÁ$uÈ—“åyû.ƒÅFʬ
+r¶4ö®7”èñ”þFppjMébt reô·ýø—E*ÙH‰LºXjÙ
+‘;ÇZ4ÆÏDùå pˆœW2¶ÑÆÕì½"ïÉ4þv…çøâ2•³X'lšÏ“¹ÈÀN{\Š¬„Qcjeˆç(žÉ2gºv&bž»D Ç"ls9q¬*¨1Â0ÃÈÇT³:îÍ_>ØJ)%æ3Jpè8Mw Ë”ðD¹\JüS2J­ÖÌÖŸs`ri 0
+éÇsèz™ÿy ÂÃ?H~V¾zž¡ÌHJIÒ¤³¤¯x Pòµ.oêÜ%jÙM^)…€<’`½%§%±W¨^·À0›Ü‚VæÍUdÅ!©ªê ȱCŒi»½<<ÛȈ
+/òÏ 6…gL-1›Xå|ø¦KÚé° f’èŽÕÒ°Ða¼Ç]ØOÌô’îk ~‘l‡oƒq>õRÄŸÐ;tAºÝ¦™Þ£]õÝû_' L¼Ç1"h‚o¿±¶“o±X;ŽÉXdæŠ|7/Ùµ$qv¯á™
+V›Äìu6#wŽYsŽjb>ìp>!BÇÄ}¹kíü‰»âJœÂFB>0¬(A‰Kg}"F¼î:æÛ6ÔÏ}…Œ,4›¥ÅH'Z²(yên|ÝK:¶²*{žG |n% ¾IIliDä—Ä)ˆ{ û©Ë ¥©ŸËÔ¤ 8•¹dûtÇÅ«¦è.Þõîl)¡{K+ÍýÆÙBo™êTvÜFÞXÔ«¿ÖXt±5¿©h(I3ç±^+ÜЋږ‚ÉnåÍ)ŠO“àÖê©à“[á¦v/ðÀ÷|GGò yGH+ük’¦‚†`}¥™ìÍ›Op€ë$X4MòˆáNþ¥×IÊ1bêØü|V8+Ê”*3Ÿšf¾
+±F³˜°ñÓÔy„+Ø9¼†‡A7Ë°L Û 0å²l*aŠJEÐn[—>µÉ#ô& ÷"• f@ÒeT%>Å|¹ž€‹±²°@w`²áÁ˜Uî/TQÔ¥Ç(L :¯Ls­A @G«ª³/Ñ;ŽÒ²W(+)ÓÈXX¦‹µòÍÚرM3á>iz‹g¥ÄF°À
+7¼˜Bn`Ã_‡J±'¸Öe4­V“éø°°¾šÔMá5ƒ3E(IFxŸ1£V%‡çàƒù,dÓcŸ£ÿV(c<R|¤°ÎâsãY±#_·©¼¯¶ZÉâo ’I_XÅ®C–[Ä;íSù]­“A¡8P@¡âlv·=f'ó&8B3ŠgÞcÞ ÀFb^‚WæóU½„zy„ ¤†-ò³è6ûÏE‹ !td·ÚÇ€*Rˆ½ž=xž”‘.ÒM{:¤—eY
+ž/؉ŽfÒMÎ3G—ÁúÍ(ÚÅO²¼”~Å9ˆ!f„Ø Ùªeqä×2~dË[I³.‹l®cÏs€ÏD¹€I3%¬5_F—SÌ'½Ä«êÁêbÀ´É}jš™Gu§á5dI"mi˜ÞT·ÊÚňq9~‹³N{Å`ú¬\_v"¾ôÕ.·5ß¹!¾_4Šz8Ö»âêÁDºïñ³âJ‹Sîàô+’?Ç
+ÿòÂÒvÌP]/ŽLƒ¬™Qêt+¨2øþvƒJä_ѧ¬Tóû4+a~#áÒ/Ø&:Ü¡šÂšškÁ<`¦—ßGÄG˜`<õ¼¦ôÆu 9÷übM±|äMÌ;¤•O»¬ö&Kô”oãÊ –ð˜*â ã7£ ^a–ÄM~uL—ª+Lsdß¼ÈL¡<Êdç4ý/V˜Ó’a[|*¿*ùÑß¿E'°còYÛ©™—Kr~TôXÀÓç~Pt#…ãnÝ‹œ`H,€U£u©>ø׋*‚ ^{½nõMâ?­¨-ôµÔ%ù9J<9!AÓgFô:J|ãg2è(Ê)/$ž"pFº¬Û휑TÉÚ€¶ƒ¤€ÏF €~ö
+öñó00(Ÿ²XØóχ¢Û’}ØuƶB:pVýqŸC–Ñnv¿X O5((Tý¥š­?PìŽ<ÌÊ’69Ô8­e%ümdI#º óALÈÒ¯Aò#¬Ë`“òcbîçQ
+ jûÆ'üY†ç?Ô€­•—…OuˆŠ¤(ˆ>$7Dz<´‡•ƒÑª•
+ærÓjøxo’,ÃMmÃrŒ^D+T[žql Æø$¥l(ɱ½§’oSòOÝ‹&[>³èüû9÷ÛL²‡\:Щ_5Ù¥#•í»5‡ö)mBnQ„94ëÁL,è´ã”¾øWî£~œq‡Ëá7Ô_s/]‘gsÈnÞÛÐZÈCIsó<UÜ&ô;¶Mn"¦ô÷°Ü2DlÌçéïÀ
+¸v_ÅiN,L—¼üJcE5.¢SJ
+‘ êNEŸ/ŠÒ¨ì:Ûµ«¿¨Ï¬æ±= @ÿ™VÁ5 C¡.³S{ñZIî¿ô˪µŸê¾Ú CWé¤vÝ!³+ömÇ9~+pÀ¬”ºµg\s|œB\L¸Ns^³i´ìlîø(V/2Sf핶 ÿT«RaÌõ5'¦Ìäa‘êS›çà‹ÇÕ;‰¨G½ò©DëÖ‹¨”I]Kð(*ð %\xn;§á,
+Qd¿ƒˆh0ä†h›£XŒ^a˜FP•ð
+wœ,ÈIËùŒ ™ëíP€Øl€(°§y<e¼c©#0/_ÃK›LÓ®®¶µL‘Ô}YX°¡0˼/I1š4"ñ¢>xP’L×®‘'7î½:uRRH^|žN´},Á¬ ]Ü%Éæ5rcfÐ6Fwx(úô"<(”.ÏêË8ˆ¥(Á‚ûî2%âªñ\Ì;¡w@tkléÈŠMqm[œ¥¤i "
+ÔW“á'öJÝñtˆ‘Í6±¥›ò%±gnÒ°$‘†,ñc˜·G ;;YRityqŠÌ. …#XQb(GßÝëqó!+cæÏ_$ÔÉ%悧pvøìuÁD/í*¯x;;O]knóªä›9•÷Îoÿù%ÄqÇ)úY}(ÿ¯Õ”Õd8$¼'ñ0àÏpfà R²@À×®]XÎ11 ëÃÅ®C«¬]vÜЮ`È"_¢šd.qHuÚ9< Ù?k^l ÎÄíš—à—qs<¾Å)ô¯ ×Hv†äÞ6Ä
+,0Ö1˜6‚ˆ¢!ˆJ½|áÄ^ða.yít9‰ÈÅóß6À]#Bbñó¬þ÷ÈŽà@à¸×î½| 0G‡äfƒúy"CŸ™âŒÌ G†j fæ`kCƒ•^Gï±È°–gŠñ xÐÇ­ÈV(Á€Nì¢ü~«­Ý$]ä%„ &YƒÇ³‘ìÐ’¥øù¢èÅ›± ²6ìb+N¡û•¹AU#Xó˜GÚÉB3ÄäiŠ
++2†¾‚l¼/Ÿbÿ`
+H‰”—A²6DOà;ü ŒŠ @\;KßÂU³ú¾ÿv^“Tf¢O•=I%eÉ îÆ£xk3KfñÝ|ìÕ[m~ü+r>þñó[ôxÃJ ›6.A
+ñ,^šy”yBlÌÑG¶Yf_!mô™Ãfk­îàï,f/üï\5ª[óâ}Äɇ?E­^½ŒºÎ™­¤Ç ÓˣƨV‚/|îˆÖú˜¥–s‡ŒÎI™óãû·[=êœÅ¼ËôÕG÷l=ÛàñãÿòÑCÿô˜þñù&hTêêI›}(d˜w#'^¬ˆú0wžZú Î+bò÷i”cðÅ
+Q&ÕÍØÝr~•Q%œ%wP£¤ƒ÷RæjºçèÔdºí,ɯ )®ÌZÆ æ±oÓjƼtœ;½šÛè'™Î+/˜¶qÁ“F ~8빪Á¨Çˆ~`Aûy÷¤YYwLÔœ­‡[ÇD–‡鳞ò97g+VJ7ªÂ@¶ZŒVj}â¢rGi<|ΓN:ãEs´ÕÍx¤ µü—ý<k’d¶Z«­Ë*¸îcN_!4&[„Ñ°2öìq®'H»„|ÿöïoöñ×·=pJ›ìg^pøëÓƒgY·2ƒœ1™¶ÀáY€Ò c]{g¼VùÏʸ'Ùï:|fdhºÕ‚<†šÌˆ÷g;%¾,³•¾ÎiÙ<¨ÁœqÎiô—¬Ö24øĬ—u¾<HŽ!Ià“·cˆ
+ ÞÀ çl€¾nX¼`«h܆ñM@k÷qk®øù(þÞËÂûx8Oož"ì}œõÒ£g¥M ð· užX ú‡"€$ÄX:ƒiûù€ÉÒkoB‹BzN*pè³£­Â¹Tˆ±Ì•ø hnÙ³Þò¦™(L#¾+Ýà]30tIuGWÁa:Þˆ­@‡*ÒpW±¥öd;¥¬ö¼ŠðÆ[Ö¹Ÿ´Ï¨ÆyÀÓ2
+ÄO0Ùƒg,u£E”¼jZìOƒ¶
+Uø "z}ÍÎ-(ySU¿LEˆ1H¦òG_Z€€ÚË}£Œý2Í ÒdÒ˜Båaf>Âe§ˆˆ’ó~ƒ¶ƒÊ,G?Ö9Ìà‘ôØ!H£#Á-»_¢áÕŒ¾ºþ²1½®¢î¾Yãr ŠT[Î÷xŸCNàɺh›>ÑÑ2O¾ÐÍá/3ž DL)C—Fì ¨hÉ8]îÌ<ÙŸ³ÏRñ 01Ô6Û
+ÁnP®
+÷ÄɆ\I1±U­ ‰ p ‚×Ý*ú†ý#®µÅ…J؈w‘屃ÀVôÞ =Ù‚L3JƒOŒOÌ$zÛ7m0š‰çÁD»„ìvQ¨–ÂÄÝÎ{ób¾bNžÉÀ‚œ½Ðt‡ù> b:óF°4’4,HÜǘÀYtiéÀ–!»±.C 蓬ÜÎøUý˜X¸µÀ—.4ÄFx¯3®.B°hø0<DÝÐQ2x«Ù°–‡_Qµbˆ ÜÎ[T‰d’³ôîÈ(¿d‡ÙÇæ[ħÉQÇ<¯Ny¦ýãÆÈXaü^Ô)A>ý†Ú¥Ôñè!Åæ…u~í!DvzQ55<¢c‹<ôç
+’¨¼¾C,‡,KçlYÔ.‘Ì®SÊåÔèJÝùˆ6qxSÓßPwvµŠC|êÂÅ×s:Ú"o)¨ú i0’¨kší¨A¢-è©åkUyÈñ|ÿv r™`@+ ercqSk9ÆÑp<o]%¼Å ¡XvÃ`º­úH-N•YÏ(ÿˆMÜ„à0$ÿ8‚|j±Aÿ>äзÐæCÛM Ló|Jfm IØë›V¼ø¢„Û}“E.¸ù+ºÎ¡¨ßÞUnç4Þ€ÏÄ)üצ1(( J÷É
+‘ëbíI`gŸ,kÛšÐY¬Ž| Âä0]4–R#¥?ÖËEñRúêû²— Ï]èY2o×KBQÐI PÂã°ÙXH`Äš+Dþø³äÉu‘G§ý¾kkI˜˜
+ µçIùÆ´Ð(½/Ô‡_±u[  ÎM²ËÊæûÂáXB4ßϳ1 ;Oëó\…ïV1 ’:S
+åOV¹é\çhãé
+9{ª1N©ÚUž¯êEL(SúäA-£œì÷ ï1lj}£KûúØ5~O€+Š!x¢Æà<œ½h+’-ì°A¨>.AŸo‚Š¥–Fô%}£Ý´|òm”Se ì>¦d0ÚL;‡œØ)¥J-JiÏ—S§Å ¥2™ÚÌÛ§œ­/Lös‘k_€Lç¾N5ñôŸË¡™<íÄÄŠ—`”“ RÈöÿâ'6»µÅãeâæàáÆWBGD^BŽ¿(6†y Rò&Î_µÚ 3(20û{`h É¢6ù:l¹Ú‹:ZÕA#ßÜV … ŠÍ¡×ÉE¶n®õoî¹[^oÒé(‡O”¤È:ùpÅk Ðg™NñYøïkÊ9¨n©â¯i&Nw†d-î¢1ãT
+‡|±Ômp_Íu˜wgs‰ù_mýü^›fÿ¡¼L’äFv z‚¾ƒNó°V/u mK÷ßþç`Dv“»òk!3•P ÀáË›1?]}o¹‘ÿ¤uÒiŠ8ƒŠŒmÚc?L%HJcõxiwcd%zâ¡ð¸ÐCôðÅL):òZ€-ºØa:¸leF¾r“×)E:p ÐÕCŠ¼Ýs@Ñ{Ä2ÍÝR¤[sN‘Uì:Á7 26™žS$% ˈ|Ͻ7×IQ4ª¤gn‰8¥HwçôGI0¢Iù}Ê%EjèMN•ÌïŒx>g@_x–¤@Øv`=ÅH¡Ër¤¬ÄŒ~Œ¤HÏDÿÁÂîÎ9FR’µjLµ-{v‘w´;1Ò)r†Þ_26à ÆŒYó^Ô:@dµXω!·¢û^Š¾>YÓc›ëKXPuYxȯÑZHöøc5p*îRÁh[áS‘JŒ9ðe¾³è‰Éj£µl<ôÛ—u'àqdÇ1´öŠú_!C¿hÕ
+™ýîŦ\‰À ÷¼J™-óXR
+ÿ(ë8S¸«ßu˜žø±wIºÇ_mûòË1Ú~¢ KÏÖ·`¤aƆa@1Í#ÇPŸBÒ­Ø»w/œ°J´ámê>«Ä}[®–ÛÙº³ô›y]ß»<R 
+UÔþ¢SvüõpÝ÷EêuÐs±
+î`K<­«ä4‡ÄÅNE¿GH lLXÞéðrNxa¾«,±c èc•àR#§ð¢· õÞ f‰‰á¿¼®¢|2SúX·mñG È…ÙÎA£Ø‰¤±}bA© 5n|*9Aôç_N‘ö9ÒuùµV?.¹-ŸwÕEBp÷êZd®½tl2CÖvª;Ý÷ç¨aK2ÉH–¨ã> Q~“é¾¢à¦ä…T°h#oö H‹{)1AIJ~az£èg§IL;fߪE?^R±´h˜{ŽR&á,§¢üs·VV‘“ø"  Ëà«Å>òa¢{Ò*ÊxÑøÍüiÍ͇x%±á€B§­9b!ãÂ+c k¬D b +)z2+þô}Eà‰€|ϹshÜ\eUY2›&ža}OáTòÛPÑ sÁ¬Õûªë9X«)3ÿ6¸à ¦:ôÒ*Ðtz 1¾vˆzNç´n’«à7¹k,ü L2;"×íXHa‹]Hy›JÐNþC@äSZâqË­HáYªX¶ŸyEÎÄÛ«â8ºøMÿ´èº~_¬¨9þø›J†¨J}ûøÇŠ"O•½Íž;,ù5±³Ø>¹©â$¿ºL`æ15ív+&åWÄc&u
+}viÂ\;FpãIá¯Û9RF|gby—‹'Í‚+Í®–£D/U>®SX EE·f3©¸¸X9D?›Nѯ‡"^ˆ
+#`š„¥y”À-È "e_£8(já›c.{߯ET‘“’²jû~gŽ‹ef6q˜Ù á1ÚÖèc6¯&Èb¿P½d)ÒœY|VÚO–¶S &¶íûOÉRŽ;Å=ð5{qÎÑR«ßhAjsJh´Nô‘­g¯Û9Ê IÂ…ÜY&“AÒ`QúÁu¬ë¹ìÛ\%
+4q”¾A zE4Ú««^2mØØÑmhYIë’–¶ ã’¦‡Au>K‹RÚÀ(À–¯çÆýÁÿNVÇ‹§…žºzL¢ƒàLÌÞAò8¬êÈy“Ü…¿¥ÓŸf±•Eé*Û'¬]ïˆ]‹"wc]‹
+Ÿ·„Yp×.è »ªØ÷СlÝE¸0Ïÿ¤Õ@½ay{’Ä‘±·’Ú:šgÓ#·ÂÇVãVäa•§Ÿ‰ÿcü êq"ØT˜Š|Ñ—[Q“Úi~!Y‡š<š†Åæ¯Ç‹$ù5ÌË1Rrîšßà”ü6h0ÿ†j.ïçÀaü$ò}}M‰ôCèœñ(Q‰™¶±ƒ´´‘ZÄbM¼yýéðv†lŸy$Äf°K\–JvÕ÷ë“õ9¶ŒêûקgÿX‚‘eŽ¬±ç&3» xʦm8/%>aZilžØ[§ÛšZÆ<"›ð7TS]€P‚y”>¡°kjô1å)ž­Z‰l* J
+ŠËÔˆ-#ê¬Ù‚¾þ¿Z< Ý)ú²¢ H»ÛXÏJòOX
+û~•Ørá,‹YyK®—vÔò?ÊË$9Ž‰¢'Ðr]‹4Ìòu…>­wÔ²ïßï;Te„‡1»´)QŸÀ‡?쬂Âð&Â-µïàØXR)BÝ­âÜ8º¢Óh7,’•QÌ)Z~Ý€¨™…@EÎe9Xü"%ïåRî€RÖ˜ŠýðSM¹™Ú©§‡Ó…«p_ºé·¦‚숃dŠ+Üš-
+:³0ŠF N…Ö³ƒxšŸµ¶ûÄàÉÛC%¥x”¤nG¼-CÀÎÏæ÷Sët¿ž¸ñŤGc”­SSe€ÄÔÑ=“)RêäÊ7Í|¬ÕÔBÚ5çoSxþ„‰a•rù‚YL+òšî1;\O׿m³Z¸@¯Ç„Âé¨Å¾q7ëª1✛&¬»"²lÑÊ´îÒK'cï ’º7ó bÇhk/â’±óŠEb¸a_$0aƒI!Pð­A1S,ó`Ò×»©m®Š+ck‡Nb’ö‡ýXl–•W®,
+ž"#¦c_ó–;_ç¼õóšLU×fߧLÈôó *ËVˆBX/o|˜T,(<{‘Ä5ú@n-7y ‘ø]–âæ;±3$ Ö°{¦)ecfIÇ ˆøæ $mäE6Ž‰KÈ“P®îå-A"“ˆß¹É[W7«åÉ9J™\½Üä‰+ÈÉ[èl§€ç‚tC[çä$ ÚËŽèqzQêÓF#›®7æ·ºyKÓƒ
+™X¼¦öÙ[ŒWÓ±ƒ30ÍímGAœ&«ÄO û駭Ÿ—G;ÅÊ@¯£á‹JÞZgVBR…ñ=ó@\D‘¨Dиú†¥ê,zOÛ€3eWNPq1<Aãýúw˜Bêš:™–UÄÅn
+Ëï`ì°h<’|…Gî…_œ® Á˜¡ý#îÚè(4íNCÔç‚{Ø#µªA\÷žÍZQYN@Z”¯ÏF÷2Jƒ™ß©Ù,¤
+O650j'³.¨FÙKЋ-`9êkæO6S£ÈJ!KÙžÅà´ ¢|˜ÈŸ¹ž>$>DVxqëO‡¦ueìÄ´ï4q¢`Ñ3ªrY„^³6‘Ö-ÜÕJÝ3šN˯—¹ŒŽ÷¨ë^ŠsäK‰=ÈK«>ßÙ-XЂEYx´­J£ó½ß7 Œyj’× Ø DsGÑP»q„ƒAœ „ȼÚÕQU‚µ.¨_g{úø®TUþ6æMù¨>ó¢™ß%àÃ|CÜ0è¶þâ*˜2>L¸¥!ÝÿÝõƒ +Æ9 òs9GApÕx–•ö«(°áÈ»%~c‰Íí‰×/f&Jî]Æ®FÖ"d%²UcÞÌ„5œ×:Šs¹ÏOãHÌ/ X¼síòtêý× ˆz1jʃ)Ûa]Ñ”B‡ÙÆ‘”1&ÆÌ Oç~qK„›¡0•‘¹‹˜®ýôˆ %ÌS‡ñh2LD^R—}‡³$®G4×¼\Ó1ATƒ/“Dà é9%/œ ý¥Æé0AAæke®1-è.*›¿Iµa+ŸPu”ƽ£ß¸}­ü®¼F&‰JG¶ü:‚F\ª«:
+nH“éõÃÛ+ÞY;,!KÖ÷I?,¨ÒØ!œ®?’¸{<Öy©,†öxðø§EÍüUâÀLîU&õX¯ ˆ€0”rbGŸv©"^•µ’4eºG·T1 y›É¾#¸R©‡  Üp FyÊeˆ£“ ¢‰ŠšUÈbA´6
+·wdEêˆ0J¨
+•%ê<(ÁʱH\ .³ñ`E«"‹Aäëð¿¨}ô :ªY¡‡<)·v¿Óž"X‡±…ƒàïF,¼(H–«˜¹Ž áÿbV6dM>~ù y)´ò]}à(l,ÑsXf›˜/˜#HÑVð'*A¬G$R¤ŽB…öYŸñyÜæ‚p9XŒÈ‚ïn"np'>km»óAÌ]q`˜ !T•ì;„ 2¬Š .HWoXK^Z„y‡Y糬¤„½ZyŒÁ«ŸFÍÚdmakÀ8»<ÁÒU²›Yf2(`Í$tDÐÐ×;ûµÖ§@Ugíí[ãÉÿ4 ¢Y—œ^Aέ#³ò“(?ÿ>FReŸÆ¤Æ;ìgŒd áM‚ Ì× †ã/p½z"ëW•õÂ.$Šþããö¿·&R ó°Ïêu…yl„˜*lwBjJ>¨G Ñ@Á8í‡ÞÍ
+`°e¿Ž›ÐF—áP£!{fQq ÃA|Zù©”2»ùLGÇ?‰Óij1¦Ñü¹Bd±¶4à“?œ>9¡H—!HdV©¦½J™t½Ë…z`ï] ´ÚÔ Ã@RH¾Lj(SÍ}ŸtþLAF’FŽ#Å1vƒÐ+7ƒd¼´ÎÞÆálÑõ_Ý´œ)p’šr¥¼ÛmÁ Oˆ!ÊöHPÒªså#å"ÂLGÅ;ÈËp~ür@Þ˜k˜ œ<ÙþÐeó¼ãÞ
+WZv «]¢Ø¤ÈÖ¢²Ù‘ë¥"qö}˜Ö1
+i•s²ß™EÏäûÎ ¤BoSÜm$2D£¨“n ("œ´³û¤+Fj„}g
+Ó)ˆDê›­äÃëùôõÎ`h†Âí ñ±R´ë…)ýí‚®Ó  –›æíML£hŸyÒƒ…¹ ì´–úâ—Óh”ÜYûœAô$#¦ak3C3­âJ†L³4…²õ ~Òtôºæ•ò’WHgŒƒHÂŽMeJö™›Dž=0)Ó .ȃeÑ\ˆ¢+ÞK‹±Ï¹"Æ”¼cø”,ÖUÚÀÂÌÑR_½b'•$2>ÅÃÞÒÚ”A‘R“¿€ø N­ÂŒ­mg%u\*î± õÇi k\»D-dyAgr>ß/Mâ_ÿfÿõŸ_ý÷q aã^ºkõpÃÿ´±¿o@L›µñ!ìÄ#èB_éN €ÉJÒ0Ê'£(ûÒk‡+¡RRXAÅ’ø:YËa0y%ZP;ÆAŽKA`4.ÁŠÁ™óŽ¼úr‚訨ã'h–ÇýÊ7fR'Zjîe¤im@Òyó¨ø”a”ðZuºÅ‚V¥ ÂÈÓ-±yiÕ>êêr«¸ ˆ6=üÛ r _iFÃÿ£¼L’ãÈ• zÞ'(Ã<¬ù—º…¶Ôý·ÿy PÆÊD™ÔÝfmMÑ$bðáü*fšM+«XëªKq` a’M[oº'!Œ€Ñ‡™º@ÖLô ¸XªÞÞœCpTOø–ÜOsš¾Û“NS|)Íi.þëN}±…UKÏ{"–\TäCZ…›6OŠ™ä8{ùi™ø´1!éž “{ÑF¬iqÃ2¿k_¥W1YJz!mŸòáí€Dv²‚üxs©ô4ÁÜš‡X@«•kHhQ#æS˜àŒ+Ç+ØEP1ŒG†·SQ‹@Pé±cÍiÎ䔉$™Y^^ß@^¨÷ë㺩¤UGÎ’Ç1œ|âÄu} ¼v¶3ˆ€’Ùƒ±ZQë€×ñqÁ!̤ 1Æg4ƒ¤Î¤ œö~<Ïî]¦cînÝ‚&%¹¶Ë×±Eöod;Û›‚Ȉ8DäVµü3­Ùa¿Ò0r? ~¯DùIE.üÍ1ÈˈŒÕ•Rb–«¸+,ÈeØõî†ÔbÙ¬]wСíQjeÀÐÂùL²5ênŽ²Ýðúþ‡-ýe»\#•Ä_Sròˆ„L´>x[æ;Á!ÁŽ#jÖûòè°Z•çHÅ!<+ r”à ³&òÃT Ï«ƒ €1¨XÓŠ²AL8àèÙ
+ê´ÞrÀ%*ávÈc_u¡ I0µÍtxoÔ…läÙévQ´t"­+ħ‡V"k Oçd>ä•0^«á@ø&‚ÿFƒ˜vÖw­>˜-3KÞjw*Îp{ãÅ(Þ6ÿòýúGfÍ8Ÿ²à[X¢á2ß“¶rTTÀå¥Ë‡¤Œ‹ö
+#nÅ"»ˆ3g\@¿Þ€lÙ tôoiœ@Htf õ´²X ŠÃcǶûDáÈqŒÅ…º4G­"ãOq±{’Æ ±¡Sá•å„¨Ìv’;¯>ê<»Ö§\« LC¨°GãÝ1¬6+U¸Ÿm;¡ggŒ;$Ó¼5–?ÐP° ¬ ÀV˜ïF¥)øÂÇ€1m¶ˆ°ÆD•ù @üUiŒ˜A†’(É“ …UÀFÐN7³IŠÈäÅ°ó§&±‹qk¿Xír ±LúMË4ùÄïùÝë骼<¯¨û[°¬CmmA(C—¢cÄüªŒ€0rŸnõ—¢Å“«ñÊh›ÐWfdY½Ì¨â0FÏÑ\"©æQ›ÈJ(UÔšÛJÝA(>¿eËù™ ø~ªmM$tæßSÆFŸÁ!ì%#O9°s)tI– =ˆÇúœæ§
+}ÿ‹TýBÕÊ«òîs«DãcÃê &IE;è~³Ñb+"úîÿÄø…È"Èí;è~ÝßAòßX¶§hlÁî \&V_+‡5NŸ¡¼7øi{ôˆÄ1£t–5kª8€/O›ñÛ®ªI*ÌÝOÇËV6žq\ÇpþIa ¼¥] hºÚãÑ~
+D¸nþ Ÿ<ªU™)ìÚå²ëOûmFŠ#H;v¼|î×Ç ÄÁ›Ìô¤%/qŸèWÂæ¼C"[
+“ó×êéÝ7ç@“BäÍ-ž²¨ÞÝWqø<œÀ8žÓ’íÊâŠâÝ4ñy™ "„5‡°ŽSÛ¼ ì_%x°lÓ×ÇtÀF‘Q€ŒU”sùwÐm)N×ý貨Çy¿‚ÖÒ×Ä)¶‡TÊ<„¯?G¬Œƒš äçÓ ¡òIŒDÜñv‘@ù0ƒð0n0ŸÂ5……IÍþmWÁëðBÆEì«h ö˜s–ƒô¦€N²¥mAZàKXÉŒåR¤ä( »+s²ÒIç&ŒÊ=íªò@_3ŠŠgžÛÎÉ.gKŽÙΡ|aqAx¶xº¢ZŸüÀÞQ|kÝânµÁÇÊ-ÙUù1BÆQY“X>~.t„JvNO-³˜‘MM R±Kã ´½T`0:µ‚ÀtõOö58x©¬öA.õpü•Þ@ÅF<©®0<)ÉïqüÓHüoAuR"—·|rÖÍ
+\ŽD…Þ¿ÏE£Yæ›~%‰*‰5ûàÞ ~?ͧò U]VSùè,cAu-#Ð!@õöТám*@‹ ½ÀqB }®ÄtÓÀ¼¨¸¥Žwô5LîÚMÈzM@
+Êœ´³ÌèÇÑÉÇlðn—Ò@›±¤íáÿù8ƤUéC#[\Z'0$Q'm—VsÒG1µÆàþžoÒ©N£CÐøµ¶’Q÷xiôà” ­-e£r’šUÌ%BV‘ÂMñIáóV/ë¼bÛW¬ÿ%ؽÃüõ†lðP7ˆ,ðž÷·shz„Ç7Úþ‰££3(MY†Å'¤ú¨’s8Uxò8РûS<}?Íødˆ€ø™Å`‚Û]ƒ>~çLBÜðøóŸ·?þ}‹oÜ•„Úí¨:aŸ¾%À¬¾ciþÿñ–ó€ ªÀ4rYyT½ eBN&Àûó&(G@4 $»?,÷*íWÅ ¸4qÒ
+)PÕH…V_Ä›†Ü¥ù¤Í£ä¬­xp‘SPFŠ¨¹k'À5zˆŽÊøèj™nªë¸ %>TÎœ|'*LtÍÊÑcxž}©¶J§êY·˜ç[в°€¤ZˆN¡V€(ò
+Q‡Pšvß4f=Šñû](Ð0)…ðɨà‰ß
+aâ©*Xà™(õêSþ=ã!D[‰»b™íf.ŠÎdØöiPÝ……B°|äΟä#»°Äð­
+¥ÈYu;Z‰!h‹…ð L @Gó×a’¥/5÷Ôa!Øœš”­´”L&ð1tË·ªhÀZØ…Cc +Ô\õu¨ð:fŠÅCd—ÅØÜBD> ˜é.¿˜˜«ø(è[pƒ
+#Ñ^Æœ !®uÀ3äm^3ÑJê=ÞD0RêM÷û]ƒŠzœ–cª
+–á99Þ\”¢†¨J#®K¡È3Q8ݸå±*Á
+(õP“J¯0ù­u®*,^ç£Z4+™_ªù»ùÄ·µ!õ4óQ½ë m¢ ¶Ò]ø©ü ×G+ˆtâ4l^!z+šž‹ ý„q¿ y5†&î€F‘_ž¦jq þДË$M ÖL×x}Uu hBý§»\þò£½Ö
+ Féâ
+jq‚WЂêåô„ 0`û®¯×
+\4`±sç“÷kš.pfÚ”) ÒÓ˾¦©yFmÓB€]NùPZk'q6†·Ìɵ=IMHÞ\;‘€.q(~bÉr!SQçi+¤)o¬@nÉ¥ˆ¢†Û^|+èŽRÇ4zp±ä™ÓP¦ªc…heöÁû\º!HȈ}êcÈ«•ƒ°°I–šPðq:MµÓ MltÄñV Ì
+‡¹óèœÍæÖ)FE#ïBhR=ù@–¶ó=
+ÙÞÍ2¬€âˆ«ÛÝ#ãØôgVõäÛÈÔ”5 ífÞ3ò3ä•ù&äK;œád<#B"“êñ Î¸ˆz0@´ÔÛoöCC\GXa¼Æà2òÍdÓ€ÞP!è*Œ
+êo³ŠbÝ!D·
+ÈϲHUdTLRjEÙi—&ùpDžÉPC)ÍÚ¨ä8 %j«4€(fÌÒ¦O|¹2pðÒÖæ±m•ðæf!ܪB,?IgÖ¡²ÝnÒúŒ2£5=«€bAC®f [Ne+*¾fOµÈñí48£øÛèðCˆ¶â͇=]EgúÍ:z;Ð(ΓSÔ¢O+zrð‰òf
+Û!Ðc ÖV¼ºxÜUOTˆT˜…CDD–äSªç!õ5䕘ŽAª N¦¹N|9L5w¬ì¢»ïTŸ‚1ÞÜSåëÛÀC”(ÁŒ,­Ù:+ˆÚ'öæ>‚a¡~Lë0d7E´‚”÷CÈ*
+¦º â=í¸ eS° Mìí!re‰Si^~jŠõ ›ßœm v¥g\•¨ÀV~œ¼ dÇ«a4t 5››:YMç…^` xFz÷|tf‘
+Pæ0%ê3ˆô­?æ£þͧ~2a„F‚š·:
+ãìU«º™øz¿„h« N2qjè#_×É/<£SxeM2ÐlK#„à Mt[{¿ód~ \qO5i½òdfà1ÅÓmPŽN7ms‡Tš¾‘a´À‹Bí#‚[ûV¤6Ë-¥¸^ƒp :ëh$•oöfl m½œ$ r4ªÖC`l“)‰ÄûVÈ Ìó(”šU¸%ÎzÖáΦª^Ón@y‹øð´Ï Í’7¹ÇõÄèE_B#f,Ïænx€ô…è¼ÏhäÇËh­º®³)Wà ­äç6VîÜ@`êŽÛpzjs@)Õmµ<¬3æP!Ó´Í ‹LÚÊŸnÀ?¨FµÑCk¶ÍÕÁX߈’RSu`£]ïDƒS­
+©&@j€ŽáÃ+xáb©Bï]*MZÁÿ”¼WXS×€«¤ÙžBøÑuêab+αòf• J‘“îIåú„Pqy|UØg€&T
+ˆÿrøÌ%h.Q?ÞCä¶G—ÇSÈRJñxrARw§õ 4·KÐ?ÇbQn\:|ýÆ;;dUkÊç]ÝdçW‹å2²^éÝpØfÒqЪE„}’]:ñø'Š†‚10¬@8hŒ.4ÍXG ØT3F¯¡^¸'¸?ôÍ(. Ñá _À-´bêaµáú¥¾‚!mŒÉû+áK™i¤¢W=„~äê¬UKXæÏà¤Fm~d¬q"5ŒTã7æ_ñ.>æ•?íóÂÒ¨;é£ ÷½³tÆ48!„)¦½²t~Ñüü¨‘0Èþƒ¥3WG¶×&¶hÏï,mƒlFS_Åw”¶—ØÁ‚b\ù@iãÕiDËèé 7úŽÒ„0ó˜1ëŠÒöªº³æOêí¥íµÉ¢ò]Ê¥ ! æâ³v…éÏ‹ß‚ñE–T*çÈï§iû48&•cåz+0†ª¦DªþŽ|{Ñmã+Ò“_·Í°0*‡j¿fjO8”=ºoÃ÷yË7£ 4ÃbÄã€Î³‚ÌÍl!º¤²z¸b÷eÉÛð£ÀˆÉÒÄGÔ%‡$ua8ýòkôœš\Ž¤`y·!zŒu˜ ;L@2ç ­øžr 9[eø9;|ô´ϤÇlR!sƒ‘ªztbƒÅØ$ã!¤?Iµ í/B(H‰½Ñ
+HŸ)™GÚ+]vUâu¦|
+i«®Z}Š–t-?< A ð§á)¿:_KUÃjrÛ$E¨ªÞש8Òa8’^…9œq¿8‹˜ÈI[m¡ Uø(­oü䜛8êÀž²Õ¯ÓGï.Žã&þfTosÊï«q¾ýó4å/”ZvµÎ¾§WhˆÉoÜžŠ¨c_S“9•QÀƒÉ³ŽÖˆÑ:z{¸¬×VÐÔï²ÊÑs©þµÕ{^Û( ùÞÃ2¬ h ^OÌôH‡ÕOy܉L-y¾ÙÖâsiå!ä[CÜéd¾2B#MLõëÏ_Å3ã µøV>îú£ È~ª*“LB…q‰Áfdœd+ä w0ÂÌE°+4pjØó –IF ê@-²O[=¾1…0–
+‘èbæçXÙÇm3Ë%Ö—ÂÕÉ/sjø°NÏ8„¼ú3Û¸}¶esG@, mæƒçÁWˆc*æ;Š¼®Æµ1À4ÆZ½
+7G~)'ª7Åa!ÈÇ(å„ð<}=ËCy>¸»Ñ»5x½çåÖ{+¨{­(•ùø%½0µU?!Xæ£cðZ|Oe¾ÎÈKñ”Û']lXsÛ‘BÈø’×a¦XZºóÊ<׺Gh. È©¬¢áó#g´J]S¤8쟓ˌ@S_¼êúqP%ˆiÜ¥òV‚[帜9ïœWrU7fóSC5 ö\Náhá=ÉúôUTëtl¢º—EA3©ÁZP©¾eàTÎë¬ÃÀ$&êÚ<2®L³vÈ «õªÅü02T¤tå(@Ä”KÁHN)$”LѼ“ç>—ãuŒ°ú„€­ÇP³žÇ:½öH€¾lW³é%ŠŸ}QÉâ»(žùÁÛ—B渉.¢o싸Ny!“±9 ·W
+zÔÀ:ÖÑ¿ÖŽ˜0–6Æùâ8¢„Òˆx\í~m~€Rs%¾õ\”oþˆ ”SÒ&3õƒ=5Œ¶1" †½j?!byá:Þí¹D,)³rÆ­Œ‡ãl¨ÝðŽeSôcÝŽH~¦°ëµ­t¾MsïäåG‰,¤AO·Ê `C E¥kNY;5g™‚Žª7†—Äž
+„x×å
+5 L.–ç=‚‘ui ¢ÖÓ>h˜v•ì‹dܵܟgCš¨#êÊÓM‘SåÚ>4
+â+k³â4 „m5¨ýL”ÔšQ™ÆãT)
+–¹
+ºß$£™‹çéYIˆY®sæتÊÒÓV>fà Ø¢·J”_¢êˆD€ßIJ—«\;õ™<ÔñRÁCQ\‹ã
+ƒ1DÂn¾K<!Ótà ÞEäè‰GCìð,o)Ê#( ËQ”ítœÇሦk=”À
+IY£å“nõ)Ú¸7Þž7vzÏMn&íhàakn'W*½Æ0àµó^7Å K_à 2‡<ËSŠÒ«³Éï²4ö+¶â‚ÒP‘ƒ·a
+Áä¸mѼÄv<`îÂÖup?[ßWeË©\ £J¯pÁa2Gf®²XtOïPZ•Wjõø ¼ Ðáñ|Àw.žýõzS–ô·Ó(8H ¯ä±.&‘3ùôá·ÈžFÉŽÈ [»Ç×Á#¯~0 =c¶9S¶s+è¾dYu2/¯Ám(Ä×R²"q.3<{@dp‰üÂ׶QÓ‚´ÏR$iªáCâß*ŽšÂ½L‘ú ±‹» 8‘R3òC‰x,¶Í‡?¿ýû-ÿ‡«qú°•ׄ.’œ#Ùâ?j(R Àœ¯\PxWÈBvÜ`Šúyz`_.E*áþm2~©Ÿ 
+ b]^ Š
+˜@¤Ã:½1÷lºÈå,ÃQà†{†¦tY•cX:®_Œ…“bÉ)añú u<%SG@زØ
+àï1ç ´‡íÉ
+×°Kú±’fzºèI“ë?%”¨C®d0Ožç›b®)ÁQƒ ‚©P–Ò¢S%,²ÜŸtš¹°(hî‰,åTðr­ÿZáÁ84œ§ìÏULL‹9èQÀ d1z~¡wŒsX.œdËÁÃÀp_ŒÜ9m–ìæÅFÊhSê±ZÜæM j•CØ%b? ø"@ÀvPzÑZlE¸âÊSÆkxÅ$áŽ`¿hvÅ)Ñlž ¿§_x³êIŽ'#ö…±R«“Æ_ÃìFq2~'“+C4´™!à®ûÖ·BÆPä³Õ_™æœ”6'+(?BÝz¼3]5rȳmR’SFmòºëR¤âÔÌ4Äb8)!XL@‹3´]Âô²
+ÆO%¼²8gÛbdȈzC݃ ZÃÞ­>÷:UgEo1qd¾™ºˆ¯»¤˜¼[Ö`Å*Ú\¯¸˜’Ø
+´3ÕˆT;p7ADàÐêÓ™1=•bÆèqÞÎy¡½âD râÐ`à}ì¬ÃºçR; ñÊHÅ™NÆÓUphjkÙÔ9(›ÿIÎ&¦+ÝÜK&rňˆú}nnE²(lÍc,gI^¼€d¨±a>«ì¨y§0Ãàh$&_ÕSO£ñÝÊ|$f1-Óüõ
+‘¿2WŽU4Ÿ¸M=XTÐ5ñ‡ŸÒx’d˜zÚÄ>’)Ü|“8yy”–’ߨK‚{³ã§ :î­ ?Ëoè ;Þc \\f¿ù¢ë7.¦_ŽµÈrg¡eĆ_KÏ%i…A˜¸+‹ŠË”à}þì ø9 _ýݯ‡’+¾ç*ÑþýPÄd`š3ÖÇ‚1
+ã"—ßû ôV²9&/‘ÛÛñ¨Ùgv šœ@¢±ÖŒkañµ
+,˜«
+Ö½]í¡bë !À –ÇÙ
+i…ƒ13 •³LB&þ~³@\¢ÀàX>J²¬_"³D’™“–ÂãMV„Y¤-å2.¿¯ÚÑôÙf ^ÌI´ÈbŠ`†+"Ûc8¨Þ9°n¥€.È;í„!+miŽ¨
+ ýÕgê]ÈÈÙÿ4§(ñæݾìÀ ÄÆãkuSdÕ©ýá䜃tn€¤ÕâJïqqb@¬?æŦd÷˜äÆc…O¯È€¤ÒжFSÂCG·~®STÜ¥YÀÆë:ÉwŒgêëôø*Ö<æÄ–“± ØfäW€AÖ$LÇ.!ÀqBKJÎ2Ü'ý–ƒ¨ /LbF>뢘*f¿JÙ<ÆòPx¼¼××’}’„ !‚]j{xNƒëJcý2Y†)w¿ÊÞ;1ñ.iÔƒ4µ"A°zÌòôþ‰yHB–†ì9 L'L÷©¸E¥¾u_ ùÛègØŽxð:â–õkƒ…­+*:ÔËßñ‡8‡±—yòr=H›
+»Vë¾9OÈ=5ŒÞ•€ˆ‹—iÍòz€Q>!°Ý²ˆX‰ÁÀΫî Q›\g@3è2E9+ IYÏ­s
+s‚âw¶éI˜Øb¶«‹eIkh{õØ,þš”6¤¶~·Ùù¤;J†¼ËÊ×F7É<ÿ ô#*ùãÛ_ßhÝ#wž2kpþo«Aè—° »kAÑχ"l%¤=tåK·Ìh^NãA‘v½r]òM•ÍB›ÁÝ[
+Ü’Š€‡ÌÉkµh}U!- fKçˆ=ÀÈ?´RŸŽþ™
+US.}Ó@vÊqܸˆdŒf%ð‚ÞDZ…‹Õ¯š†4®ÀÁVR*c.ü ÿÄ‹Ÿ!ËÀP0¤¼ {* ÄÑÿB¢¢ÕI6X?0Î訄jÂ?”(Š²iò;‹ùR]’¦±È{g(brs -å3‚¬)OÜ =G\ÉÂB³~ÿñ2Ò¡’!*ä‰â×ÉqQxç(ؕĦºp½M»JÄ÷ÐFì|©1'R+T¡|ô`e¨ï2šéG]XˆtöfÙ#ð÷Ò¥k_óªÃ´ÂUé+)A0yå…i8˜¿•ì£ÊÂ
+2
+ÃÉ=Ò+Ñ@‚°ÇôÑb‘xPeì“P |^Qg  sLJÕâ¿RhfJ8‹Î»B‹ÈTXØ B¤ÙÍœ^íËÊŽ]Í… ‹á& ZKN¯"ú™Å‡àýyWƒ#š![B+™áߢJdÙ"µó!%š€Ô”}<î¾O…T˜rÀnz
+95!¾Þw8Ôì±
+¬H>ÒÁÊmaI¦Í Üé0<€öBÌP» ô
+H‰”—]®[G„Wà=h#ôÉ&ŸGïÂÀ<9ûÝ<F,an€$‘JÍn²X,š[W›ÿˆë³éTSËüñóÛlúœÍ€h·n‰‘g,“!S|®x$btïÑu,ký@|ÙjsNiÍ6„oçî]—ÈÒè½E®Q‘šÕù‘ödÒµ»D_}Ó$–K£w?¾kmÆŸ ³qѶÆ+Ò¨KðDmÁ­Î9ËC‡¨¬¶„·ðŠ5¦Ûywç<f÷šÉ»ÉMçGd¤B&$„®“œù\ÒÇ$¶Mr±!-æš:»ˆ%M}!zü£Pó©“›JŒ°ÐŠ”QÉ…ºh]‡Lf•ŒË>Ç"\¦û>Øéb1ÚÚÎeÜWSÎè­¡Œ}
+µ9é3rÓe¨rí1(«Ø©e[’76>&¤Óו›aZòÐÞ׆hÁÓ‰äz9¡Væ”؇®çø¢P®s]È °¢Í¼Ì¢Üî0Ø»IÔ£ºsAƒ:w¤‹§¶¾àIÕ †·ÖyXÛì[ÏiÐ…LP¾:FH7g€òØÉT-’àVoâ#4ˆ_‘,³×C$©ª©<STÕ†ïs 6†:œ¬‚su8 Ó×Xâ’˜®ddk%×êmN¨hd©q,))ŠÆ àôÉINhh–ÃF  éh·¡‚ë5—‚ŒÖ)¿˜ýñ}Gê¡(?…^…á{¾é>~Ђbø®R}‹œÍؽcõä'ÍABJ)ȸ‰˜¶N’;‡ÂY1ªù¤Åšt4ê<œž£…BF¬ëU¤”‡1rHÕ–9mFBNnÂùlöiœ¶©ÖžÅD¨
+¢½u4"[Q4‚@SC¢:9'-»Î£ (…
+¾óê;÷Td€§lÈ22LcR‹ñALìiÉcë©ëQá!\¢lH[†8 R´p›ÃŠNh¼? 'WƒYóˆçtN@b&yË-„í !ë:ä-ú DUhj‘KiÇÒœC½2•ðV­ÉÐОTtð HÊ @v…ºZKÕÑÈs Õì¶xo&Ìk)d³ŸËð¼a´¢Îº.B‚HÒ ðïzÓb$QÉÖ.Œ¦62 ùsR#Œ:—¥U§eBÁ‘õäw0±šùœ×m™?¤¸eGW™:ÍT€E½Æ”*ª$úÒið&Ä5žáíèê:üÜó¥çËGÝ×9EYl––@›$ †´V(›BW#Û‰Mðp–öªÎ´,#nv.“ys.¢±êÙæ©afsün¨IÍèxæPYH‡ôÁ·ÑÝ»\?gfvÃå'°.‡äötŽhäªîâiI%rÕ ½f°Ìü%>£@P~õ6Sö9
+mc†ü,AJ;[ó–GÑÆOê®_T*À¹—"åË—çoÒbЉ¨Æ8†IçÄF{¡&ë@:Ÿ¬à_Ûü]­ÓŸMd‹fˆ3_œ®íK WEBÄ%àcCÖjé0ý@`9}̧dçd!Ì<@ò/ªÿßoˆ+ÄΤâæ¥Ð&©l¿¥DFò?“xƒùqùcFÿ8Á‚' IÓ~¡,¨BÚ½¶)6ž2˜SÌS }ƒœ®n‰£•Ž%øè&\<“¨L|Vÿtñ;Ð[îÂ}¤Û$ÅاÌÙ{Pš_.ÂLÇ[€t¢!ªþШs!ÛѽÁɽ!SaèL©:çð}Ò$ŸR43ɵ!ŒêžÆ ÅÛùAuPdeü…W¨´¸:g9Äuç¶*ÎèHF‹?ÆÑê„#3H
+­™¨|vÔˆ“¿-ªí
+EÆ[vZjò ˆ1ÏbísôJK
+BƒáC©ÄywMk˜…yCüÜÄH“L¯å“&©ˆôòz!Pæ´Àb2S‚¡ŠDÝ\ö’´g#íi=:x?
+‹ZŸCçOïadê9G¤ׂ3݈ÕY먢éïÌá
+‹i`O׳!ø|Šï W¥B„„ÍŸQ¡Po¼õ©BPqŒ+Ž›MªÎáX
+œfùx“î‹G2o BÁ…ÐÔ³Bq[²³»¢"ñà|@¤=-cy ¦ÑÏ£l;AŸ×!ŒKVO¶µœ¢ï
+ÍDgýļڔ««v)Ú.Ühj¸^áw ºëP& 䢻2ÍÓ÷t`Ú39‡”£GŸðØC†6ÒäÂœ%´‹Ü!èøFèQ ·ê]ÄL¤D΀mÉsvÇ}1vZnb&‘º)¯‘ÉÅz i 7Égù]JÈ0€M¡ì^Mô…­WbÝG)Ã`{1„ŠU^áˆ$
+kíïh›ÞÐÃÏζHy
+߯¢DÀR’/‘/Z¤D*2
+ðd@ÁŒÞÈyñ„®€ä2Î(24¹.÷ ¿{—ÆY‹$†~D¥£È %¾ÓÔÞ.h4ßQƽ”žz ‚jôÔÎA¸U%bÆŒ¢
+•a£ šœÂ=È%pùùæ_Üøv³íL_»”ˆd‡t2¬3É«åà!)ƒL¥ËŒRÕúd9äô% ‚$ÙÞ”ÐãA¤MPG½hJR ëw/y
+£·’—0z-â"ÙП°ª2(œÌ–EBÄ£
+<!û~»Œ,8 ¢@`ñë£0òÍ€ªJ;ýK¤ Dn-ŽRÔnÛŸ¸lBe.#Ád†Æ­ ÐËÚ1ªæΑ¨æHIØçÈcRb#’L_d·!K­géì¢}gr'Þ5Ys‘dYžêÂNLµà—…'ÚÃá'Æ(ON…rx´UgwñŠ
+Æ¿Ø»’RÄ0h;˜YÆ£qŠ&ytì
+ÎÐê‡Äå`GÓ‹R«t‚>ÿÚEàj Ök2¿),µé»JäèÆË! P8Ã"tBO»+ 0UW07Ì6€è€ùb-ÇÓT{Ø7y.è‹Ä1Ûþ£XÒ’.[˜ º+sI4ܼic”šHƒqWæqÖHÁî0/Â6¿°TŽ¼K‡ÊâK؉7A“M« ó†Ö …üEŽ“¸/?Wtí¸ã?Ý›WÐpüþ¬Ç±À(³’oJ@âÒÖ¬±úã¤ç"xP9Q)þÌ)jZqqQS0Þˆ€ú›`ÜÜÈý¸ãçPEe, [’-fiBц¿5ÿ W/ÛÝ”|Ü[b˜ìõ™܃þs–œÚkB9ˆ¨šS“óŠ¢ÿð
+£·á¸]Eu&`±uIÇ'“§¾ryIá²|gP´AB§¥ ºHÒ¢wöW™x‚žÈoiÇ=½«øQÏ+¥hðEÆjñ¿³w?YÏjƒ[·íákë'¿â¸Ñ0½)âÅ™=
+¢Íöw >n¢>@XÁJ±9Dº±+$¸
+tk¶€;K‚Öð@FâpPÌÃs¤>4
+É3ÁK‘·yEŸ
+°ØÙºýk’§À½‡ì5Ô‰@ÃæI4x@„XdýºÅGpŒ ùäøý‘Mµ}?<F)× OiZÍI©ÊîBšèš—HIéÒ®ÅQÊ­‹§¾ŽŸ) Ä”ý¾{º‚¢…+b‡<ñæ] â
+]ÂI©Ÿ“^j$ÚØÖñÆË9®c‰¢+À`Ë@Ô<˜ŠÿMºZC²@Sû×¹™U º_½
+'H´‰ª¬Äÿ¬.8¸Q¤k̦t¸4ÐNBfD“`Z/aN§)ÌÄEpËH,òÃpŠ÷˜ú×iFÀ©à¡1CîZ¡B9Hk$‚Œšºì‰—€X‚R©+FŽûEoÐɆpÎãÄÈC,#ìh >pÐ5÷õøG!0­{?>÷’3òRrpà
+|@=`DµÚ9ŠFªRwŽÅžÀ;¡›-ãI‹ø›Æ”µLèzÓ!mÈGk›=1ùŒ_½±¶°cW†l!éÇÑCòI,}(²ø.ƒ9Þ•¤¬˜û‡wõb7ì$
+[ÒÝ:Aax¯¼KðŸ]²™뢂®Ðš÷Nƒh…1“ûÚ‰KÓnA2lêOghRwÁn!8Ò¢~DK}aBC=µÉ´›—ÊeÁ+*Ф,Kº¶Â¤#Mâþº¢IÙsSWI”8ŸNlÓ
+,ô#*~«)¾áòÃc àž¡áÑ¥¯×‹_Jüâx\ç± v˜Ôð~UQ+Ú©’š‘3š‰œNÛê*ÂWð_YürF ùM%IOoJ*#44 4bmõ’€ÿ°@è°c­G·²>+蟋¸1¯"ÿ^Ö±  f«ãoSö
+:N\dW´ßJ°È(cÜv?8cîU¦½µ}r ÔÄsv;y‡F¨]aÆ­èP„G ºš½¤ñ8¸…¤·’R•f¨€á%ÞzL‹°GÙó:Âa†-k×}1p’I¬ÌÛ­Ðô=*Þ`ž¤‰ÙÁKHºh‡j¦~ÎòØfÀ¿Q£ÄÞÂÊ<k†¼¨ Ôä–Ò}M#aF_ãÎà›%'íc7 |º¸¥Aç"<Û’½3<›*’茮ÜýÃAhr¯­¸”x+L ’òŽë
+Ìâ°€ah>ÍhW @#ù:”hj KI:ß7–¿-M¡K­†ûò bÔEgq*A¹Ma}“
+RvdóP¤Þ„ôˆkomsÞ0Ó¯•½ãÉA E‹«xzfÍœ…Š2¶¶âNrªknÁ‡Àˆ‰¶uÝ芚˜¢Å •¹„qå7­jÒÚb!I%n%ë¥4Ü}áJ²æž‹~Ü%Ydò…øExUQdg¼”ˆ\‚³.rÁ’݆“¸I¢nO[{¨ÀùüÍJpo<™8÷ãy>ÙOÛ
+°PÏæe³¨–¿òûÝÖ¤‰™!OÍú²éÿû`éÆ,BT@{B†‡q|4ùR@ Ÿ§HM `y¦:OóÝô˜¤!•æ^¾=†½ ¨9²´ÀÛ¡Ö¢¾}òTð]†byèOYå3nJØ{b$åå»áã¹È†¨4̪„ëù~,zÆ"Æž+C¼DˉrÊ·tY 4%oÓ%@ôÈ‘ÛÓ¦;á‘—€cú2bD(ÅhGY94þ O`ŒAÅ
+3Ïùn11½ŸZl[ž0ŒÌ£7îoQ}ÛüRk@ùŽ˜£­ºäi’ŽbÊ­n»¥Á»ô‘l8›„¡žy­3 [&¢fogý¶PàÉdá’N!žÐ~âÐfþŽ5OÆäÌß*"Iž”Ù„ìßEBX‘¡"P~´vÉçÁ†=A
+˳*0±n|Z ø†áQÞuId_R•$-\À·
+2ë¦LŠÛ=AÐ^"¯‰fÇFÎQ`ù*?Ò- f.gíd%)“\ã&8å<FÇ{f¿‡%<B"59ðK.íŠ1$lE9¤”“íÿeEç`ª4Æ.bð;pev°Œ½
+Äô#j5YÉ %Úó‘T>—¨™DQª¦½ä›urØÆ´î„QÚë2ÏÙJt+ðN—GÚsLãCœsŸ‹N²$y¸½çEÆP(©rÂ
+H™m³Þ¹!øF3Ìds>~ÌZ>õL:L™ëy¬›·DPDÁKß>Ry'i‹Ñ"²kÄdì~Žʺ,=€Ùœ'ÃêýÄ%ec>­siùõ4èœnuàõuŽh|ãcÉC¯~~gj~l#ž•¤eäUêu½_Ç"ì(œC D%B”è;X£Ôr:úQN%4Ñ&Xœý¨^ ºg7öîóàGÕ
+‡œPRS:¤¦éšQ†½Í&“—0ü'gIýlGO5?™‰„¤›<|h{ÑþàÆsÜ,Ƀ3Qy *q‘SSæ d«ë…%U°n¢îpDU €b{á‚
+`ÂVŽ£½9‘åCÉâe\&¢H ÊÇu„,ú”Üç>M›N³Ê†PIqç°o¥ü È%|¶HGqID÷<¸¡º ˜oD†&:#«…¥65L~æKu—\ææ¦Ù\û¹¶úb85Ç8ý·RZEE­ רƒCÔ}†¯EWS†<H€ÔðÒs|»h¼Ywè5ЬèºÝ7ŠL¿àuQ{—5x¿)M’'Tc)¬¤1²PŒêjÉ ‹’‚ÞI%Xluœå•g@/ÆRs7ý½)+òþ-†åa^X°E€T˜Â±gÇ2‰ø€Í¬„†±êÇ
+Ÿ+|ãY¤äãf•‰€G¤ÞØ%ŸÓõ V‚™ä`AQ|p,zð´þÀÓGTad9b ú­bð>‰¢å8^¼ÝLÎâ͘v4°ò~¤¢ß[=¯c9‹?
+EëÈ2¥: ,?!&ßì¼¢`J ´àšadòfr^„²+`Yüè«J
+Œž©‡½ÿ>—Œ|†^F¢Ø€-…’d|î=Ñ·ýõã¶:K?bRþí `üîÇ}+èM¢Éºyi³yh›aÎΤ•–Òž–·¼DA0Uã
+]Ú^ÏX «u÷L¶!ßjû
+UðŸüÓ÷.³AžñSÛÁ‹G놽Ó.æò+/nࢼ¿ÂnŠo”ÑY¯NÄÆF“³RÔ }‚9?¨/‹®Ó
+¯}ËpŒ„©âëL¸¶12ÆX¸µÝÊ,•ñ¨…¶'C©=|&É„) À%Û0£Øã’
+¬ŠháDç]C‹ºb×¢’˜“µ§3äTš§jç\×¢Â*ƒÐ‰XÖ+ËSÜÁÍ׺2Þ)^ö±’sªo‡zé´«ƒ–ê¼
+ú%ä®3e3¡ õá;Ó@¿bTþjA€ £F–Ê<ÊO™h?|`^Ì~[¿š¶B^šípuVàÞòñÎ;fÒÔRl>„|ÁÕ_¢Z°Rkˆ<ßœ;ç›\7Õjô;¯©e>°67`B%°U´q\Û)â€tCc’i)|Pèê Ý Õ¡ƒŒJ÷¤­*‰üºÐ‹›,)°êœgƒ2Ô\j{Âw+*Ø€ÆAV
+¡ÇY{Ѧ?mâ4ßï¦ê|GdH &ɧ95|Æ.zIHP¥¯CM&= â»5
+9GUÀ§K|ê|úŽ‘x:ãoÍCÄTL)#UvHn­¬*‡ÕC
+®ž“ŽïA¶÷]›S’¿·,‚¶è©ÍììF½
+õ÷2+^-D™àñš ã¹H̉a”éNú#É·T,¨¿0Ï›ÁõxÌßKN3¥YA'BÖܵM²ìä¬Ý̤†a=0%g쉣O&Úð°‚êåL ©‡.£ ôó;óµ—KÎ+©h&Âê2¥Š‘tÝki ­tŒ ½ÅÈë ‚þ
+‚´Í¢½K:Y¼ô什Ç|~çFºxþù'¡H â0Ô$%;rÀô8™ÿö壠/(¥~i@#ƒ~1ä°£±~Ñr*ùÁCPUæ'èÙ:ÓU† å‘E‹àÆØ/ä½DèôcQgÉÍ(>!c<"‹öW¢ƒ„‡©åh~G–)<g±æÎ U&FpmÚîF¡¾T ´»Á¢ úõã´]UÅ~Ìf{?lÛ ƒfÂÈ:~Þo|·±ÛË#;Ü „e‡µ?}‡²ð„”\éóžE®ÃK´åaÌüÊ—‹-f\“Rî“h
+Dj¯Bc ‰´xµèîÖJ$TÒÛD[©‚Ò€SÜ}Z`M>ÌOúM«ã“w¼kð&ìÌy^7N!ÝÃ;þkЦ%ƒîÈ}Û•‡kåaÜ÷ó¢rßÜ]¸á¼­¦Qön5®j€AÂll¼¶ëæhפ‹ÓfçTdÆr)×l¨hYMtA¤„¨2E›`_`Kg'g£lé1.,öÖ Wx›{7¿½*ny¬ÎrÆ°±ùz¤ Ûx dGj9¨½ ‹ñ1‹Äü ™We•ÃªÎ¤²£PLŠÄÜùÒR +¥ÅÏ—€;ÐÇ\§Ô@\›±!€Ýx¸¼>ÍS‹ÂµØaAÈ©ÈÁÄCÄä(üNc*×[2rʨ0«œ³}aÒ<æy” —)Ç5…‚Ë.gµj.c"^Å:öw?Í$iuÅd?+BŠzúý>6µ¡
+p‰BŠf¥…È«óLÒŠQ„öt•ŽB¾pHÙùr<°ÑÐ)ô–—ýTˆÜœSáæ<Ãï)Åü(D²HV@ò‚×JsoAQ»‡ZGâÓCÇÝ‚öqHi‚;`¾+A Ô¬äÿÔbÊÆ›œíbBUt±‡¦éåâ¾ì'òþÐÓ)W‚Š8½áAžCv#FYcÈOÔK0J9Kqi—÷ó.8cŸ¤fBþ(!æ<‚¿Oò öÉŠŒÙÃw`ÃÙùŒÓoŒgòôNþûϸÝLÇ$‚>u#á-(,£?Ûæ0VÓ‡™½iø•5ñ(¤aÇܯô5æó;Sª¹Æ,iΚàÆ©h':ˆx Coóæ(¨Ñ  RÃì°g6þíÃCj«dž,ñŽÿ3^îHzA>ÁÞA6ÆF¿&!L¹œ@·2¹?_VW/šz@DBKîtwUVf–l
+E[gˆÑ
+Š
+¶ª–!£»4Q·›û6°™…óm!èÁÓ‘óüQ¦'Ñ\#ˆ¦ýiÊ¢\Ž®ĽØnrŒì*”ø
+ü½BŸFçˆy£Ów*‹É"Êàóɳ
+ `±øD°H^1èá ®†?—€Ï-Zô¸4é? ßþ´’ñ¨ÜÚ0–ê³MqaÚ-zBœ€sq¢HD“ì¹ô*\´ ·¶› +UMi× 2˜v²ªT?èš…‹Ñ¹Ùý;×ᔣ#ø8„9†ÜB5ª¯¤;[Ý&s 3UCT”Ú–Y]%ç/^”ëSà ìYd-VçÏàXÊ—-Ñ~9È[ÐÐ T
+‹ƒû18D9… 0r]øe¢´/°¾zÂ/Hv‘v¥°ìŒ¦´©ÄV÷QT'ç.Šàf« °¶ø…#öB³&›å§Çð³ÑDžéÌåÙmúˆ
+©(]¶™:AJ /G>L$ ú‚Ää˜Äz
+öÍØè]ÔTÚÿôŸd
+~ÉHè…ª²|E2£¹ ê ó²õu
+ %|#E÷A˜²¢Éã
+“íƒ^\¡A NÅ…¦î¨  ¸%j$잉X_NˆÄPUeÞË#Pnè
+—}lm‹
+ÉÓ«ÈTÂ~¢:59ÕÏÛu9¶§s^[î¼æ>:îWÝ&Ð)Ž7ë·{—Vý÷ÎÎ(o[/1Ÿìâ£×ú/„+!ð6È|J:‚L—½ÆŽRƒâæØ ¥‹¤'ìÅ®4Òïòçñýò
+èÐCÆÛOm;¯Y5b­Š~ïòÖ/öÛkûaãmÂ0$CåîÙxfT1T@i×S*þ
+æ“€4­þ°LÑú5<0娸šÊdè*™ ¼+µ„»]ì1‹ÂÔdçpœ=°¼;'M–µn¸±X<ü†©oÅÿ#VLa)¶Åæ¥ëŸÈD ·Ö°›Ú8»+óf¾ëe~’ ÖìfóÅ¡#£|›™G z5µºK<dá1íœv9ƹ˸·ÅÜË3§#ñ‰òæll$²,?ÿçù›*U3ÑjÖ1-6œ*R¡!%ïS–
+ÅSƒ×ÔàHhKSÑ.Å…†¨UÇìÙ9…h;fÝJ„ìcIÐ÷zAŽ•ƒ³i5)
+DGµ +” ƒÔìm> ýtYQJÜÅ\fƯVÅ¢Ð=Ⱥ‡Ùg6&.?ÃÐ%"ìÜÞDã X׌öÿ>š`ˆ\`œ(ù™F÷È¡X“²Ê»6†\“®xÂ˲r©j•JçLTƒè®•#ûá
+~'?,hBùØz¼*öÚK0…¥ +è ÷ iŠ•0’`5
+Tøƒsá×ebod^èž#êŸj„EØÙMgâ`yDcj«Ž ÂÑ á ¶º>lФ<»wN1µƒš£e¿K²™îT
+{Ú‚ ùôY¦?.ê Χ@xÅfÝ¿ƒŽûûKƈ(½¶ñÍ=?‚ìºÞR’5éq•ðaÚÆ€<˜tA:vyÈD´Í»ÔÌJUCí\§ÈéÛVÓ]܃”õ$3UE<`ûöÄŽI”ÃKR)·@¨ "Ë6Öj„­Ì¼·E²®‚m˜
+¿¯z=gà`˜/˜ƒáØÆÃÏñ¸ÚºAht‡³ˆu;Oœ]O|€&Õ®bS|g’ÛŸŽg@Ä”ë¤Âǵ#ü ¢¡Q1Ö r™¹æA^¾ùóë¹Mï–”2ö¦?MÆtlàç;kº¶¹™ 2è0ÍZú&Î.KÛeÒ©Gì:ⶠÀLÏ ‚«ÍÈÄÛ‚`ÔúÀ‘á¯6»L5+€‘åüÏ®R‹‹H£×½¨AÔŽôaV“SG§_Øâ\7k°…¨«Y2Hi$$u¢Ôd]ÅE4)ÊŒ‡s4)˜×:êL¯QvS©¾áñ«¹¶ìÿCm¨1
+ŒÙÁüõ1©fæ‚‘b¬ÔJ$²ã]k·_ a&5:0È¿U½)ÀžÎËü4ùÏbÞ¢‚H€„±¡Lþ®Má9A÷Ls
+C™à@Xõè=V·á„qѸæévêÇ~Ëþ†k4&E•ˆCpŽ>YdžZÁ³[ËÓqëû-\¾ƒ0QÔR–Hâ;4 t`~fÇ2u¤9+@¡Ž êJx†¼Aš.j†–7|Ѐæ@Ŷ=¤^Y±ƒÅËéõ&µ¬u½ƒÔúŠÏ£PPCõé‚î“È‹1_ØÄA½úÊ_™³C}Ö—³–òP±êHåZ‹ûDߥ’6 ¤J•y“ø]âœÎŸR©!€lC÷Ïéˆ;m‘X¤º!ŒNʲ£qfƒ¬àê„È„]™0£ «™íªÎ®³Ð<KV†@ûÈNµ_ËEŒd%äLÖU=âxö/iépŸ6ey2CG²"çv[v5ÞÑ{ì…üè0 }€4aìGRØŽÕ±• ­Éc‡ËJ²f4”UËsñå'BF˜;È`À BúØsÇŽ¤„í²ýQŽ
+õD"¬ë1Á–3ˆX÷Òðû“ÕÆkÖi¢æ¡Û=²£ANäY[iç0Á¦;߉ˆÓQèo!¨'sŽ¥K›+¢ù;þ̱{,‚ÖŠª³2ÄDfe¨Š‡³ž3|´““™]š
+×zÔCÂ<hk +÷ÍŸÁö3Uÿg¼Ì‘#»±(ºî¶ æÁT°Ír{Œö’fï_ç>
+%bL sãFÌxehÅ¥MÇ~­ñK¨B€öéNÕ î|d$&Áœ$ÉH¢ÚP "w‚¬ÃÍa»óÎÁ|(~¶$pyÄ£(!ÿÔ1^]¶ïöÊŠj“£âYÇü8¯ÅÏšcX¿XÎS&Q*„ôJnÄ
+…ˆ°k‹_[4¦¿EÀk›È™+tMA#£I! ¤#çë^fSmÌÚ9NÁ2£µx&²8 :Î ߌö.þ—>ÎHËÝsH0òÐvıÞåȹLФ£¥²´)/*B£$ÖÚïh úTZ“¹=a)
+7ÜÓº’¦”¹T÷2kö(Þƒåçåyï3Ë/2ó’Ç~yR2›"“´713õI“VäF© †€%TØØK!µÊèÓŽ¶Šœ¢ÔÞô«øòŠÆNtåÙ1÷w/s?9î£'Ð)Ž7ì%ö w­úzei´_aïÝLÚö.9ç}» ñ1ʦÐf.HN¼^|žË!+Ïü!|jÈr |ÅÑÜ}uÌLWºëÑ‘\µƒ
+ÕàûrÂHF8–Ø`öéHáÜædËngA®{qÓn<6š¾?õ‡å\Ž7ˈŸZ…'¡ø66ôWJrÕD›•hV?q²È“¤R2H×Ò(%œ˜Ç OZ4ÈqëÚÄNòZš=bø%¸¯@‡²c@d@Üë™BæåRë6úc‘c+qËq)èª8'¥5ò売[( LW†º-1#JL‰»c#AVÄÌQ§¼`*Gdsõì>„ Qa•Ûv•™’©oU­ízú ò6àÒGbkFS[c¶w1í*!•˜Þ<û ½Œ|¢‘FèÊOÎQ>Ój%ùÞ½L7f4iYºAì5(4[°·ËÌ,‡ ±¬EŽl»q296cN5†OO™^
+'؃*iÜ#ŸAÀ¥UŽö
+±‘§È(8ä’¬Ÿæwš»¹˜ÁÀAžõŠï× ç2(²‡óðKžZ5¾/ UÑÖN<ñ~mƒ#$ít‰åÃgTÈ&§áëš–.˜|»§¼oƒÐÀNˆæžQl â©îÊø¹0§-oËè'¡P…ز–. ³b£ÁÆbÇûuñ.ðóíºÂ^J(“P»ÞÙw#ÈC‚4ë¸"׉0wöêÊK^L´³ãòŒ£m™Eõè?¤>vNaô“²LäúÁk7_™”ÝzŸ¸ËvŠüpƒCÚÃ~€83š ã„ÝçßkFkï³1e掩‚ºÀ¡›sJÄŽ ÉÐоOë,Nô~ñ@C2JàËíø7¦„ÑlDr¨ÂâY™íP­ŸYÆô‹O ú›²06•Å¦Ѿ¥Wlœ-o®`’ðy´;ç¹^Ž£‡lùQP}©ðGôá sžùHç図£œ£ºÖÃïÛàŠÞÄóýë¿Øå¿ÿ÷ö×ÿß°nx\¾a_ÏŽt¿1§øˬBpÞ<ÌqqI‰,žÂZÏ ÝðAUyê@¡A§q!%\{Psa`ü!#Û*/Çm³I¦û]ض@”ÉÔ"Û1²—ÜY±(d¨<4ºƒøzãm.¢¤’žÓÔjÊbn"“ eg –ѹÐ؇¼!ð);ߥÜÔÜ17‘àX¤^XÌ_Âj“&Aš×7Pb’°ƒAî¶.™òyÿžô;ÈÞÎòP?Ò
+Ø ¿Æ/ÄÅ 3/‚¦³»4¡ÉEþºÕ~#&NmhÜ_’-VäQ€±>ÀšP†Üò†+©K „;ðÎXåÛ„bNq™¾få¤æ^­¯Ge
+†é¤n»<AÉ«!F}:`8•’ÎÕÝ^zYQÖì£ãoyo8±Šâ'!cWàZí ".,[™j’‰&E¯ö=‚.Ì`¤çSjC “¶ 7¶¹qpl0ÿUŠ!¨h•Rü¦Q¸°HD‰kµ¯ óH¤ÑŠ8­D¤Ò ¸ÉÜóþAn±I3Æ*ÃÜŸu„;-*—miˆU¶.Y¬B¼Ÿo‰J>Þ„™Ž°(“Öß­†¤?Ê(²-Ž¥°VˆV™jô·&µ¥\&z ë;’É:Àdá@`"[b â‚°Ü°nfã#²V2£ùÂøhÊâû€Bp¼@ê5m§8Šþ†‚`[lÒAæJyN—5FY¶^kE©çŽP2²BŒÅ-¤*‚ñ²‰¿t º:­”÷¦âÙ=§|ˆ*0ågwèáv
+-ºsÞ· âæ0ñ‡ Õîä+C“ÉÞE*ÒG¨•MèÁ2¡Œyz´®Þ010 ‰dºD1 ÌÇL=øÔqí¼CAŒ*4$¤÷r îÜ—Q¼Ë”I#2
+e»´úe,ŽmAg‰B? ‡ÚT 6$ÓêWø
+yèÔ盺ëü͉Š0\VÍï×›W“#bÅ”—›ÉEë h€Ý5¾/ @\âHHy¿vÁ<Gk@ ½Nˆñ¸òâ-—s£•¡œÌGËQÜûË0¡jŠ‹›õÉ›’¹-†s pÑ­Í㾬Ó(h?؈5*Õ9ÙôÁ?ö©?.çrHK†/—pÅaX‚,!Ì "súí‚—@A0€Ö¬mÉ^=Pæ/÷s/€¬N.fZK·iõ@ð¶·#n5¿‚ñ\}žô×+"D+[4ˆüÆ$âö)øwÉiƒ´v¹#ž­)õô¼‘‘AñÈnq“ôh¥ædCÇX±¬ë2Ðã*
+Hd}Š‰Ç…p©žSysÜ£þÈ ƒÅ -ò¨”œ ¾y þ†MÐâ¢|q¹ÈŠ“ÕäZöú8˜k½4÷é— £¤&XO65¬úÌ’‡2…wŽ
+„€ÚLN!µñ(¢UO#«ÉÄêøžÏ·+È›ÁÂFÕik|ãlÅõc/6Õø ȶ¾ Eäxt8úβõ5Š#"mô-$â$! ®OÇ­öP‚À21!bTø^±rApfdòd&=)¡œœ4Ðí ¨SÅK”¹šèÚ£È2sL&[o÷R/
+©µçƒÊpÚ˜µQXŒfßSÖX‚ÉÓpfe½Jw6âpQ5Vˆ¬yÎh@2+D6¶9øç¬2./‘Ñúœû6Q쪲'º0lqÀ­[{& ’¡ËûTû`'¹¥ä¢ƒ!˜¦ŠëhÉÎIYÈ?Œ—¹y^9 E+Pª@I€[¬ ÝŤrÿéœË%°þ‘3K†I
+‹†‚$:ôº1ÄaçŽÛ÷]2xE›˜ñE8
+= ƒéù˜ƒ&É€”‹¾[ŒÈ E„Ú|GN2%8ÅQר  3į´€–×4“f Hù8Þ¹f‡•exÌùâ;@­,ì¹å·q¼R‹k#~û;±×,Žñ(ÒÁ®ïýãA³HÄÀÉBꨪãuÊ,§¤ÐÉ ÌãøÜ@²Ê\~¾ÅE’}ÜãäKKEEâÜe †: ՔƲÍC&ø:š0H»cßØLÊæ¯iÒV;8¨¨Ú}89"L;Ò‘Dwp¼k‰Õ>Nžbô+ÀEV†–æ}ýr®ÊÞ»€mÑù„ïI²¾¸h Ƶ;ŠP[²‚j†
+96Ÿ>‹„?bT 9>•ÔÆ¥«Vü9tŠ²à:/ðçôöâ’ÉfŒ?7Œ³š4G‡'ÿ&!‚Ãð#ÝA€8
+ÀPu‚ ¿S?²ËÔ»–ã
+ˆOU=L¶K–}Ã 1«û(„G°'mÛÉ
+‚1TÎõë
+–°ó<+¯ït${ËQý”ð`®øe§dr3hºv?„Ãj×É…Ä
+H"íD’ÁÃ{ÁNmQ-$€æ&Ñ
+‹¾S*ObÁ[;®·"s’í=æÑâ,x½bí šßžxÖ´P”+˜%ƒ®ºüëå”BIAnhÉáoÅÙ"ò2Û#Mp.™„0C€àªèŽŒ…p%g곑àÛ”<üNÝ 'ç¹ ÆÒ6˜að#JºK0uŒHZçã<Ü%‘ ÈõŽ©Íp+sB„äºËáÒÄÕå*°5e9üô‰",HΤ¿ë0ä„›7±Ø!6±)äh«ö¢2oèÂ
+Ãì¬m¬ç¨Vç—6Ì;Ùî&¡/kìäNøá]u9¹°ˆ> !‡‹!¢&ûREÕ·C#á’?¦ÒJ–C3…CÇô›è¨ïUaÿxE^rMXšY6¬Ù9IÌÈÚ²¨z=%$@›aç|*ä] K¹u7–û` †=+tŽBï¡ióåWp@\îžÝ›Ìeßq1:ìŃ“Ïè0ãÈac(Ø8­éaw£’?¦tŽzA½lÇŒ÷Ÿ·Qþã&Q™Ñ£ú™¢HØ°ƒ÷¤ï½éÂϨN÷´ÆAƒÉ](jÍäpLVìuø6ëïyîËã&Ͻ ^¬ï·¾DøÖݱ´H]C@8KCŽáüF¿Ï… Õ±LÀˆ9òQàã¸GÑ×ÿÞé?
+H‰Œ—MŽ;„Oà;ô&!R)®ý–s ³jß;%¥ºR7 îê(ý1ì}Ôÿýñ¿òñÏVûeZÌÚ(%L>þÓ"®Ñ¤´hÞEåã÷ÔK¹´6uM›ö éC½zé2|Az‰êcô!â5Ä{ˆÆ°¤„5­böñkn4Ôl°o1תZ#Ú_«„·jÅ{ײÏ2"*_²Þ¬±K<ZÍ›È8@r+»êè ƨìùf^{„™zŒ{â2´T9!V»—ªÃ‡Ô}+‰p×.&íãç'¨Å¸'ó+|þxn•ãÂ-/i=>žNH§
+Ó¹z1xù^¥Û-Ü\²ñ~ÍÖVÏŽAÔ}ˇսÕ_Úê_Ï)—”1à!ÝÓõ缂¦ç8áYü²zCˆú¾‡îÎëË$4ßèÝ´Sä:nÏixÒàò<ï<x¹*á"‘â¹U^ÐPN®xõÑSw±³£W”ËSÑy8zéd'k+¨ÉcSE:ú¸Ž\>W¤¶ŒÅú‡
+<?@ñî¢~qÒìÂWÐÔg[GçÙ ­¥_F™÷š® £5S ›÷
+
+ÃÀéFÈb¤Ó%<ÍÞèõa<ƒÃbØ1îùºÙÒT×Go5úŠX\x)ôë"O²<Nò$ÝáF'ò¾<Ì©^ž÷¯­ôsvUÈr`Pqhðßû<’éýíã
+¼‚NÓÆËfG¡øËy–Læ¤Á”À —ñÓ.¤½Z½Îc“ä`W%TĪfaØòy æy3!óDÏ>CG›|”¯=LjZf;mö->;MÃ3eÝÆϬ™1rù^Áá Ü‹º!îJZšæø¦s²¢ó™Túx3j†ÖNë—Huwe4/óÍZIÓF 4DT}CÍ«e”#÷èó;…õçµ »¤ úÜ»N3L:§²™Ä
+—`àà@b{À4s-' à $Ùo ’9˜—#×LˆÐc*ú|âa+q\ÓužN73#橶`1'(C·˜^Š§"¹—;`£7\Ó§Ü7g^¬5ÇÓ#”AÊ·6ס;€xšðÎÆÈ ùÖ&÷Oü
+j5fàPß ¦ž²‚
+fßCöϹ)ÉÅÿ/_ØàJKOÙÜ{ÃíæIb¤°õ¶!¾fÆk¾—ôz!Oeúõ&V¿ëwŒ FÞ Yó>Ü ¾9H©41ÐO…`RHþ(Î.j™•B<ìÓÉ4Ãp¦èéÏúô\Bœæ.ÇËžõ‡4"MI
+‰—¹ºñZvG}hÓ‚ Ë.zŽî)bò>…’å“qž?…5•!‚
+Îtó"¶<Ô{p¹‰nf 9frÞ`G7¿×—:ýõÃzªûà 2R√^¿X€-Ý ´²u:/—u%4ÍK<kî—?'PA|.¢3(àáç*(Bèç°®2IW•| ðË9…¶J~©S_é}
+Ý á ²ÌLº{QÖT³ù¢I(“›™×YYé¥LYܺbeâÓ¦¶þÚW}1˜‹`? «›áò亡I ¹Ûø&RXØͪüèÖc^A 2\{”\|´Ôcj7ÄBf1ÛŠF¸cò6jh{m‡}!¾P“‘vî &J4‹R -$—¿Y„úM jœA4–í–þã8HA4 ì0n‚ø$éê(¤’h'á+ŸE‰7@NšrŽ’œr4?ú²¼j‚?þFËÿüçÇÿþ(“ÎG^9¥
+a—”ÐúÌ_¥° bšð²DNê
+MšZÄ°¢©"âóPëêëD£K²X5’…Ìk‚ºsqB~ÙU°wóÐüs@ ›®ü|Ÿƒò ò€ï""Œ=håÚT.]Ã)€u˜×¯¦ªæ”ص»þ½yÕÓmeË4Bs·Û÷ë'™=`}h±á¨*<% ¨OËõìÌ#a€gyX¢ùsdh
+z³çUªE£êØã…¬Z°EŠ6¸;zXnÁ¶‰Œ"º5yÄítØ•¸¿nÃOâº@wÖ
+è¶b&’ÊS‹u§%+#•®m”² ²±ìG[ÿdÙCXM–Ý·™ÑÓä®äÍeùû‚­µ*D‡ªV~éÍ$…­ídÈ?°&©_ºÖ¹O'‡æ’—È„/¼èˆP|òRSh- ªŒ{®€ÃÒ
+?ÈF„'ÑH;:¨ÝmC û
+ÐCe˜oø
+tÀÔñ£](Ò"d­-+D™å¯u·'çÁH¸$w«k^c±4 Íx¸1‚Y‰å~Lv…‚Á4ñsku‘iò&ú©­9fX_r¹l ¢*`W/ûsœ ÿÛêã;Þû›K 
+ á6­­MïeÌ?,ˆ!¦…aLÊéjA¶ÄU!ÈûìW*Y!]cTúy˜{U ‘
+›éE¦¯¡]eì«`[`€§pvBÍÕ¤±[!ü7ßÖ*+ëŠ`¬ØÈPž±}†DrFÔ6š,“õMíÂU]“è½ßIâצ6²tÄÞG®SI­6âÿ0Bƒ¸ò6µ \ ‡ @ÂNÚšEð`Þ„Œ™výe…À~E
+Ãâ7èµùb+*hÝÚ)+d¸Œ0®—Ç&©§h¡:Z¶æâµ¥‘dT‡ôI–ך†Â¾cTW}¯…wTœcÁ¹¸­ønPA4ÖÛ.~ÍåøôÍTàÙÙBPº ŸAö²Ô$"h¥²
+²…ôê¹÷‡¥iK‘- ®Å_ƒÀ¬· ÂÍð#ÌñîÜöóøΉ'øóXZÑi âÜÌhÄ¥A×."„"É CÎÇPžqŠĺH¿Ø§HÂyìÀhm³ H¦ ]u5ÉF·*Û£'&!DãÄšŸŒ"ÁÖÑÒ±¾f0Y¹EËžeRƒÑmié ?b¶Y´ì:1ÃBHs°^”º?‡T±ú0 ¦šËãÛrfÈÉ ¬• "d}‡Î©»„ûå#bIø¦&aÕ«¨~œ›d·Ê1xBÑ–âu«[ͧ]¤= øÐ`ÐÔî9
+›2V× ÊûùxƇ=
+ëê
+‹Av¨±dô <¿VÙNăvŽ’‹P°+ä]*
+›ÂÉñs—Ûf~Õ†y-ÃÕ³/åô¼_]‘ƒ:ŸSÒ¼9‡®¢GQÙÖ6f¨ÓðkÞ°;.™–m§@ž Ð
+e&°×æ¾
+ëË$U·?¹u^AŠi¥²„
+X'M*ÈZPÒóÿ²­d¾0½œÉfDÑõ±Bffhæ¾¹åÑ€½´!”¼‘NYƒ¬H6ɉŽQJèe.õ#
+ˆ@*‹FÐD§ª{ó™DÁTª¼ð²qÞðë`ðnï†AJ»H7©Cž^ä%ø±žGAÇV‘—/ž Zůï~Aœw?–/<æ± ö-Íg|ó4Óø‹•™´GtÖøy(Œ«Øª#Heç¹EÕºêñ¦¤È}¸WýóËT&yºI>©¤„äÞic8Ɔ\>Bô‚’*°ç³ìþ­E»ÌKñ~ÜŠL„‰‘cä[û¥UžElàucø—c3I/læã
+òœ]F"™Pl*ˆä@u†BªŒHgPz®4û´ÏÆ„Ûñ+<‡x3O¾mš¡=ˆ¦ùÁfÄ#ÿ&¹ a`¤!ãk˜(™pWCpØÏ•?‰/ú"V–ÜÁIõNÖel Hw ³bßÚÊV÷:˜á)LÇ™|1›H¢X¡G}îEèué)#‡Œ#)Šo6{Î*ȵ_¯›™U| ];–R<Œ|¡?j£©—
+·ø„‰T*îCúãÂC$e¡o{Ôó¸›×Ũ\C&^›¡üõ•Ý²l76•Ç,!N¹ÜAœ*“¹
+eý8 %­V'Šï Æ÷vQÓÄåªaC“ä€!!¶“]8šDA…ÍÙ#”6úô& Þ…¡QÕÓ¨[ŠÁ2–ž£œÁ6‘â.Áf¤ÈÇ0qs8Ýq¶ w‘èhwž0á4K]‰<þù« Ð¬¾‚ iÊ…¥œ¨ã°úðâ‹ao–ó8´O5°ö8uƒh\pG,q¾lølV1Øzi“Ê%²éA+^Ô‰D€å›¢L|x¬rê:ˆÈ´”r$…‚ ˜r‚,ñÑ!Sg˜«‚Å‚þp~ë·¢'%S0ùsUß3Ëåç°8sËX0‡vN…œ¨ë[÷ Ì>L»ô}6íì-/'‹´«•[t]àXÿÇ·WPÔõÁѬ/5§€¥}ô²ï_YÓŸ×GŽ!«Ä¼(®Ü¡ÅfÃdÜM´P°¬ ƒW@‚tîSLªüÇ!”nXŽ”ðó¤Ã×Ý2 6o<~
+_ûfP HÒ+ÍÞÖŽJSpKdMÁü+"°uyÄîEí˜xÜ>µÍá9ý\…Õ,¿!J„DùØeÂ2щq:„™ 
+MŠ^ýª$=•x{²|òmm4¢m—sç“™Ö„WOÆn}Q8 ë»*©ãb÷iy…¯
+yt—ö]ü425åõçáQåXÓ±¾ÛÈ–ú 6¸"ß
+¹8ü¿÷Ef…ɸðÃrF3Œs‚纫7J"%`}¦™
+ŒÓqD©*HŸUñí¼UÆáÅ-- DÌ…¥éÜÔ© uÊLÉ8&cS[Ø…7·zÈq¢ ®È7”ÊŒ°f~æ®dH¶úUøó-ê­ªòQÏL¡]0#rðâG•§'[æ0 h€ e¦q½G m
+v^Á6£NþÅô}e¥}Hˆp)RrÆ0ªX«î41ß7ˆ'³Ç‚HÄ«²U>åxŽ@a®‘Ù#Ëa~îÔ@ |3>œ%1Ç%™Z¸¸ûþ?cPF¿z´rt
+×E7åt¯"6é¦HžD3…L@sÙ5hȉ‘ù“ëªÐß•õý+ò{Òf¶ÈÆU¦)páô.EJäô5- 'ç6ˆóà.4AIòÝ@gRb¨²Êè.“ó-2p™˜b橽=ߤÝ]™NÊO„ÊÓŒÔrG`WšYþñ-Ñ*Înk‚þ­@Ðk/ƒÔf¦0nµj@Oj Ω$™²ÐfƒlM5¶Þ 51 R5SG«ÒM)š´_vun’Â}Žá`&ÕÄ×”lÇ$˜¹”(”Ñ,@V,UòþsOeÒþøŸöŸÿ~ûãß(=ÖfÄQÎDðE’/³Ãh'ÌhæuˆsvÞ$Ç_ã(CHD
+ybbV½jx¼ù¤Ð·] ·"¯Q¯î¢ŸØG®†Ñífß,<Z{!ÄDÞEý&É\˜í¯_g;aƒZ`«zx΄cðÙ,fO·Y+û«ïá°‹O L@[Ö«'LØr«UÆtÔ¯a¨¬×ÉüŒvïòþ…õ•#|oVbìZ)õÚx9hé?[b)UÃéC$Ü4o-™£IPiC,ŠË“\/µšq+(‡Y¯
+öŸ‡I)p‡ÎX¸½n|Œµ”!hù@•¨Ä–evâ@»1ãr>ÓÖyMi'|
+ï Õ¶Fé‡mGBó´ op@ÍO<a/ËÖáw6¶™Îíèc›,Ø{;d–&ùoÆ·IÌ<ljš5Ù+Èx… @Z»˜ßÓ@Ã2ª0B
+W'"LŒªrÁáUþúY–LývŒÖiòn‘D5
+Ô"©£ýÍ5F¬:¼2¼;D7¿Öù¤]ÖPt †{¯~qЋzŽ)eð´<ö¹:ZW”l4U¶¡5t­ë͸2ÊÏqÖBÉ ?ˆË0«ƒH“V$­ÎjëLŠ^rãݯ샬Àé½Ý›â’0W»ÌŠQY§Ûó:僧«2 ´wY'L~$²• ã)Ö%Ìé4 ÉQÍJR³@ž8ãè{ÂWƒ¥üðW˜'…Ê{»xŽ59ãs9aÚžßáÁ§Sêg¶t?=D:œ(å«‘³šG­Üf” ï$BÉ"s"Õ«“:]ß¹B þãW5Ê—ad\$¿Ö!bP‚*ë3 Õª ƒw°&˜ðlD-j
+×ÖXLë=©äFêŠ ®] ‹ÚᬪkFëPeæ„wG¾Òù݆db& †àÀÎd¯ ¬Ö+j ²w>L¦Ú°|þåi&• g!>‰®þâ!¬ÆI4Ç-jlEŒ@®M
+A à(€­Ã$𱽬`Òcv
+·)§³»ÑÊë¸Ü@ Ž_hµb­ªW°ƒéDÀŽÓrHÝ„¤ æêÓ
++¹\a Àºä œ|îà–H]Zvì7
+‚O¥<3?@&£‰ò&j6¯­n OEöÓ`áÑü9¯‹Ó$0_G°Võ[µÍmªå|8ñ ô™‡
+\”O„¡¹ë8 š‘E¥KÛ‹°åj:¡,C$œˆÂ¶é¯ÉKmÙÎ]ã8à2LpÊW—Š…ÔýŸufâÄæeÎGR ç4Êd\ŠŸÁJ“w튴Ùo™C2T‚ARÒ8NóCÄ-lÜzÐëFÆòS[Ìõ
+¶{}|åLŠ—éý_ÿ}ûëÜs§a7Cl (ûkÁÛè;ŠÿÿóF)H„U—Çþ4­šÑ¶é³=‹Æè3I,HD9ƒ`ÍÐÃMïm‡Ì¤ÔXŒÃ Rhž„"Èp9d© ÉnZY-¨±xW–.Ú&æ'&Ó×!=`8ñxˤ,£"`4W>L“‰F3°LvˆäG­Âb˶šHâb'é¿y
+@(Ÿmô¦.[ûÀÙ¶`Ë!µò
+íE•©hZP^µ•
+
+ì›±§Ú…JûŸúDf²¬zÐÿ€aKñHÞl¢á_ûº|7^ç²eÓ¤Ÿ×êI0ù=
+3DSùÈ ª
+#ÓÅrnĺ~%O0˜·hC‚1*3ÿÏ+¤`(Gӌùê 1S¯ =çêç0Z]ÍJN}b¦yðnŠ›àD¢Àæ}%ÑwWBÜ7aïe
+©h]Bª0€l”¼…•8“C
+0Qm+ÎÁÇR¤WHV§%Y›ñ,$,‚ææ>ŸÒièw …Ûa¢'ëX{±>qdñF ³ MmYÑé„ŽîRVzS§ø¢yDå¯\]Í܈ù‰«ªêõ6¿èŽ·`$h BïWUfȘx·câ7¢Ê†#®û‚/`3ð!yÀùÿr²Ew©±>õŠß…õ×TMø"òyÅȦcñ*ˆ©Z
+7ÖDýy÷·Xa
+t}ökž¢\È--— wWìè»ä;? IR|,æÄÞ0/+ù ›QX&ä ûÛÛ;¨ÉFáùÔ†¼|>ør*Œ$Vð™rk+‰—ž ü<K|× ×,»‘œ.gR‚4V5B
+ž¼«Þ@¬6¾_™Ö2Ù "Û7ÑëeÚ{E¬‚„Ð×¹§ICùøîn–܉žÃWüÉÎ~
+ΚlÀêæ!?9ôí ‚®TšÅüœ©€[á&Èq½C>²”opäýá& ЗYÆöú^ ¨ÜD«!æ}ýê+ä[énˆ—úß o}¼‚Jë¼'kÃãœ$Á.ôXÞ-“ˆ¦SÚåþZÌgq×b­äÂ_^ ЊL¼¯gL×ÚJóHD,±‚-Äj¦‰™\i¿c¼‡Z$ ‘#XŠ¤Ñ îrÞd5azþçV¥ÅÍÐTË…”ráU™ýæÖB¤ ‰òø¾éfåû<™äP  Gsh”^…W†LÞe)$¦¨CžaŠ^ ~“ñ<ïs\ºPP^
+yôxnSZ‘
+5ã—Lµ ¡#‰çr „,gìß”a·Á ÀªãÿÉeæ–ÌŒSFApÿ´bÄ9–ã°Á K1i¯Nò ¸ä5ÇUÕDrˆÏê:Nå“p¨~NYS&n $¬T‹eŒ¹CºþzÓÈ„ˆs.S›‚ôÅUxk(ß‘KX2ZU<2³ %’Å9ÆÔPx™
+¥<A~3_ÿuƒ¼hÊÝç½ ¾2OmGƃ©9-’!n
+‡¡1€xþ\ˆAòoJfIP*ýa¡aÀë¤u ,‡ð`wªècEЦ%Þ-¼“'³y!’(Î.— …4œä“l€JšnÆ.«TD` f%ÅǘÓPÒÕv ˜Ál"” bh É{š’Y^°;Úí®ª[ø+(ì&D^AÚÕ‡'dÉ 3ß3ÎMIôJÈ >­ßx­ŒýÞvNÂ~ÕqEè!KÎb]…ð±Ã`ÑzÁ
+lþx i2¤ÄÕ¾¤¤µíødv¹ñ°Óaš»:§8ÅCVÁ›)% CÌ6¸Á¯ôi€ÅâóØŒl©¢ýl^ná*¤½Õ#†šuâôC•„w©чxˆsÄjÑËœª a€ú‰u ¼8V>´…cEÙ§šÔ»¹=L"½—º/;Üä ´Všý&Èiª±#wš2Î0
+m<"ÉþIVõ*¤Õ”€9©ØSÑrOøÖÄH
+z
+•ä0.d²Î<ÌÉ]×DôGf‡,á­DÛàÓ|rŽ—Ûj yìAPÏÏïž-ÁKÎKBO-ßz"“a HƒË¼ûªÆ ó÷áÉ#D.å°Öz¹éM:d.Ôy]Bîô8¸à »ïåÉ'ËÑY–ô: ±«(¶¬4òG™ K„v’¸Š>#®£§CÑû‰*
+nF…˜°Òkdáµmýà·H×ÔùœÙ®g4!…w÷:udÆ(=T”ü;„ìuI]þØ£üš"g?œóä-ŒŠ¹$ÿ® °,'@÷nx[’º ~b£K+EãªÎ”v»¦ñË
+ÓøgЛØý´ ^P«ÔPÞšW±beU“øÛG¿
+¯RêÐ}
+rHç?ÈÅæYÜ×ç?”B5 „ˆ®ø‘qwºšŠOµÛ]|³ÞÀŒ!áèå?¨ù¨xç
+ã+’¦hKˆ_”ÔÄ(býD4)s óúD ksVY^†|gç@=Î
+QC ù¦qPˆö@ÖÉg„
+5)¶,‰!ì›'}³”@¤°äT‚ɱãß ~äÁ‹ Ï«í‚î'tVýä»PRRæÜŒái_¼÷@Ӏ؂"Ë9à¡›×ÂÁ˜Á&™m×êéd±šj×Ú Âᯠ1š—8d² ÀD/B ÕÔ–mžv#“ ‘`6pã V•å›k}=*Ió­øÕ…)x=SL%Y•È›t=<)1:")Â5±G|Äj!P@¸ ¼Ê—•M!í°€Ñ³JàÂ!岩5ÇÄkÙ0r­ìg †‘à¯j»yCAD¼í1QÎÞ®³®(a*·G1°;CÏ:~æH,ãWA3”ùÊ:ëýà 5zÌ?cÂÎ]m– h66RýÛ¬Á`~)¾(
+¨P1d™o=:[@æ~Ôu|®\íÝßiÒõÁíÖ!ë‰:­¥çr]¸ˆE;äŠhùˆ§ïðK
+ë¬öâ6[¡Ø)øËW1½[¡%œ×Ú°³\:´|¯ï€¨wXåÕï]Âïx.`Þ{ ëm«L;s:[À”f]O"»!xðQ*ŽÁƒÜ†|@®%ŽÂPÞ#<k
+–¿èR†PçÀ4¥XÆ ¶uuÔTXZ5ëÎÂ*÷Àöh&†«Èâ-NÚÞ™”Ò¦Åwp„¼¢iþœbù›
+å m§ã0”!+©;`ªûü„! @EÅ–\$›áÀ$kò{%Ft.d#ÁŽÙ®Á†9¯‚Ëæºj¨*¦*CÛ3Õ\tä×}RƵ!¢ ñŒBù$fcmKê0Hœ·ó¥¦^ÒÞéá'k<au P@ªt¦3)ÆŸ€:”8ª‹>M‘·ë]b¨tv^U
+q‚V–òO=\8@4k×µ{€øQUÔ½Ôóµ^|'ó¸ºR’ëhu· c½îåC I‡ˆÐÚŠÚ˜<-Sy>Ò®Óôl Æ
+ü…Öy±ÉP™Òzܲ'*læ<Ñdé`yÊ~¼ ŒÛ5²@‚ph]µh˜Â»`!a47wù]Bƒ,¡®²2˜ÌzH_O'®àåÎä0š¬ò’õ£$–IÄ0ZÔx(¼@SLK¿ÒuÝö†Î`“Oúdñd®F£¿Çñ¬DˆÔë¨)UJ2¸ŠHcŒŒÀfŽÍI7HÑj˜ƒíÿñ ìJ½ðÞH¯
+à†DW}ûH³ÌB¬#ß07̃Døaè›´E/AÔ f¥¸8o%eQv (Y
+4—$\b8×ÿ
+cØ­!Þý|BD“ò!2¿½€ˆ´T
+7¡ ^6ã$¶'iÑ¥ˆž”xu=“س?ƒ1/I;†‘HüŠ’5Àt’rr½@~ß“!—Ì®Æ $¶ÞŠ ‚bo@ ß…*)= [uä„4T/÷õ“šZ‘?g#eq×óß|H§’–x-²TdŠ¢8+"È5±2öU;8]Cד8á"C*‘h–²ÔçuÎh3L% `‹0Yv£¸®.³@ %I6PÍÝ/Ë{°×nˆ€@W%ƒ6Çy6zEc˜ÚùÎBûÓ·Fõ³ó‡4¶•µ¸í¶!Ð=w)Ð_¼‰"ñÿ.sØâ$„ƒL)vn$Ǥ
+œ¯©ÀdTPˆº(öyn£Z*6øËNb’Tó àÇ<®ÓÓ7Xjv¤le{ñî€éÂ(¯Eý±x8"\œ“ïHØmÙé5MY²ñS òâ*BŠÇ™*QÚ¶)Õ!\”?ëòÀñ–ªhÿŠ;¦›:
+L"ÀÔw½¡ìïùP´)k«Íïö§puË!Ì)gSÂ|¶ß6÷0BfqeG†c»îîÇf1#y…œw
+ÚƧ9[³!DÜAmhäi*Oæ²ùÈJB#†.ƒ’ϳ×t>MhÛŸ‘÷”»á‚Ý!(½Ò>'Û†ìðÄÿ³|æ3ä/ºë$In\ è t@FÀµú,¥ÿm?'€êR&Ód2U¥"1…‡}«Â à”%K}X'¹÷J­s«;ài
+ýצvýâ_q›Ç;ÖYâ'µò\¶JQ©Ñ>‹•ñÆ$ ©e.Ï{T3*k£G"UJNö%yO_Æyý–?æûÓ`‘$Ì.$|–,K”îeŽ¼&/¿
+¾} ÒÆ"vÀ'€ç… nPé¼#os—¿J¤U5FÆžï‚3þýÖþzÀÛLxZïÿôpdÉËrRpøµQFöÈX.ÇS̸Ñp€ªO²æƒÅ}ÞKI^œ_/Юׇu6C
+1ÐyÍL§IëÖ±¹¹²1à ʈ<r€œäË>·Ú›¹ç²ç,Ê5©'wÔ÷e´#ì-65:ŸBg’߸ڹÑ+Ïlq{Ëu“Uí½’Õ‹®?pÞö+¤(Üä“ó^©3˜"˦Q{ùùLÀöÀ5
+i|(ùÎã¿1þ2—zøÜ­ÏËÁ>Ë Suš—Nù~âæj{(º'œ|¹ ¸v³«ÄÏÀ1lËìÛê‹{7>*Ö5yvÏ9v>®.œ«Œ¢#=n™°x/cP‹Ûq”Ħ0“ZÛY+—ò¬çV÷Q²3º®¿²­“Lâ»í³×ᇮ+†,lÉ>-u-á— z ”ÒN]͘\î|?âI{ QnëX·~«„vw©wŽêE%‘ˆQí^G†oaløØõ––þ¾• ;c1JÜ’¼xJ ”Fý„²ÉKãËÿéEšíÈ$§ CäѨ“CIï§w0èõœ¹ÄƒoIYºÕy‡5›RݹÇÑ“.%]_pNM$E¦eÜÜáü…œ>èw6T ÷ã—¶È-%}¹!JWMRüZ}¯¤Þi•›jnBM’å£s
+…Ì3Ò5N‹£pÌrćvÆÑJ;¡éõšïb~q¿¸Ö'X«ÓþmhXbý$˜=MÞGâ’6¸ƒsPPÃ{„s L¶’¶e!&ëX×'ÆÙï‘óÖð{–É8Å¢öÎÓô"Kê3\×~¥«æù‘[+c'GÏì²ôûñ¡Å#ãýGmï%ŒOøúó"/ùó©ä->­9q-×qÍuš4ºE F(ôÚ”7ÝnÇ#‰*)غ$=^Ó:¾µ{´€ÕÀ}Xç»ýþPñ]?^ê¥èÏ£evf] Q;úÀÅ!­  Ç9@Á„uy“è<ZÙ=Óä}è·‘3lÛæ+^d¤*ê"wlŸÔg»„ì÷ŠåÎQ²#8.'„Ùyæb€4ÚþP2lÒßÊñ°ŒƒšÛl׸”^‡˜/fª3š9½ÎÝBÃ¥ºT …¹×±‘éaÑe™Iñ¸`r´¾ÓÂ/€5ìã0K˜ ¿Ã_yÔ˜ œ†{ÅsëÔï²ÆƒF׆M‚™ól·åL Ú¸’â
+Œß#%½¿^ŠáÄç,2ðŒÒF`Ëܳ„Qz ô$ƒt–'uV` Ñ*“²LÖ¿ÝQS @ÄH p~±s:㟈ègVµÇ!]\ÏR¶
+n[(´2YÿE^Šþ|*ª ±uêY„§a]éE:?•°ô&ªl#H¦h±.jºÏ‘Ò74¯37—9qÛ¬(²bÆ×å¹BÕ¨Åôs#Á`ÕM¼1Þ¤*ïŸsÈf|•65a¶ñ
+ö9>•D Cß2N©ò^üH
+ÑÄ—.ýê%Û{ŠʶߛÁ³Úužx{”p+WÆw|³&…ð›8ó¼¯þTd*ñj+ú°Š:Èmùï0¯§w® ã­óæ/Eä ö°
+üÇö•Ec/PÞzƒ´` -AÏ5Ž‘**Df8—\‘—™ ã^±*'Ô&Žx¨VÕŒ«§yH¸Øê6XTßxƒÕ
+Tw-‘ès¤­½qdŸWú«ä÷ÿý(?ÿ!VÕ(±d ün=˜ñ‚#çðåçÿ?9 ÔG.׈;‹¥W<æѺ#¸ö[N"Öz‰Q¤M”»n£ÄÀ8–y꬜¢
+nðê015zºg·ë^§ÝÞÝÏ2¶Š7©±0çÞ·j¥Šw¢ìѦÄÿ7Ĩrn…]5ß<×Yb YmG_çˆYñf"ÒôKñ‘PFuë]rõu̶°T·e1î´¯s4gÔ¡¹_j#ðCÕÖqï=lV%Ãíì;a&µúÞ³m½‡xeú~ÿx*zO9¶Šó@³ˆá,Àk»~ž/:°Ñ¨Ãÿj5°û´„,óÈ«+2¼íamsdÃJ„ŽÙO76£ÀÚ†EÞ¼i2HK0}—Î5Cvß?”üÒàym£iŒVt]ë|ÿ±®7”ÃËUD4ç¨Á•ÒgŹz¹½ƒ¯Q˜édŽÈžmÍÝy—{êÝÉåðL3LH€¥vˆ{Òûµ/ çQÍú²§«÷:ÖÓv 6’“’˜Ô£`‘¥Ý%Þ2i” >fÉÕB^©­c+\ñ©šeHRˈ`(Œ9ÖÁ’"Ž'Z¿œ`¼yº\^B*Y‰ËHN Ç#Ô0ª9¶râóqJ®WpD–©×‚ªc­¶%bSQ9¬¯^‹Öu‹Ç£»kïCEžž1ü*qŠ’w¿Z.…KøPOÚMò{8øW€
+H‰Œ—AŽ$¶ EOÐw¨u€$R¤Èe`/½Í Œx5^æþy”X »:±mS5¿$ŠüüüŒù\Ë]ÝsÍ°ÇßmÊsMË‘¶3×zH
+=ŽMómØ0WàôáŸýöñð?H#npÝ7I¤ÙŒñ‘‹8g'‡CÅ–ûÅI} ¶Q-ïŠ"ኹß׵ƒ<S&£s¨UR晽*ñKÎ –ñ<¶¯sLùSέ(û˜j¦YñûZID^ß^!Þ°÷Ë@væ³3ßvMYh¸UÔ¯ÞÓZFÐg¿nuG?"ZPð‘Vj§5¥¯™Lêe. ÃÝQ‡²t]NX]Á°ÒŒf!jHýŸÕµòr4°u_×ųÎC!ÜXo­í¬µ©@›fÌo¬-4ñ¨ 9;˜êaÌ0®Åí+æ P|<sUf~ƒX°hó_×Ñ—¸á™°K¾9ÅW°•Èà«FÔžjŒ3$ïBЦýûº§d¢\ÿ^»/*ë0j¬Ò-üR6tÕÞh·YÎvRÖòµ¾â¾(, Gï ‰õ*#‰–æÕ¬EF´Ü¨¿¦PÍ5¸¿{ñª°á4Œµ£ KØ“i« õéú¥;ÞêÎCJ†3Äç«+íÔv¬™¯9/0„éÀ‚zW¼ã(ö2&Š[E彘~L§ úÛ£•½Œ “Á×ÖÀRŠ»ÇAãO.ø=H«² ø½êój«XžÓÊy ÁõÖÆ u7äüããoÿüüëãoÿþ@ë™ñÕäåx6‰?o›µÕ ³?ígÖ\ØkШE ÖWh©}ÿ*áq!˜”‘ß9µ.Ⱦ+ ¥Ÿ,|†ü~®ZÕŽµQ—oΙr×£«p²yl¬= ÖÈèý…a©²jâÒþh ixƒÑùÏâKbn6SÁÏt°MÑÚñ1D\rGí³û`¸Ìïü+Ãÿ=èSÔŽ:R—T|ßü8 ©€AU¡OÊÅrDTû>ž¬™|Ö9´!EXË–Ÿj±ÆŒÖÛo ·YŽ²Zøxò¯Ç@žAaئƖ~:}<kÝ”2"ïù…SˆY¾—>7ý_þmçãW µ bŽ1ËrS”Hó†ÈØ2ãÐƳoÒ£|•ó ¨ 4>‘£2ÑZm7ƒÀç [ü-Ûù¿,Ä&zgôû‰œµ áEA˜LÛ.Èê]e’÷:ÇàÂð{¸(;ˈ –¾…Zù…”¿Ó¬1ݪe“}–茔w (Ùì0ëÁ%!OÚ!]nö+æÇMƒ¶„†æY_1¬¶¬?(`I© "ËœÀè¨}_¸;«=™BÌy2s<„BÁdØ9ªT[ ’ïçœ.jeÈð…G¼]žßBò9±«–¨e«¯ú
+Òª$J³‚]æ@jLˆý³NØ™-,¸þ±²Æ<,ï®·TS3ÃaĽÉaåfªÍ®iCÞjˆö½ Ψe[gð¼#ßÿæp‰ôh¶GmtIuìØÝÏúséNÀaem)S¶Ø´Ô¹1jïäµl^È`»É)z!P]Fä^7(Ôz3w½–ŒKv«ùHXaú"h‚Ë-%Û÷"„«¥ o_DNX ¢&z„éU¨Å€ÚoMãV¼ÇyÀûcÎM[ëMÞ¯®†®Aa—¦£l^ߟýèòÎ%±ØÀsþoD…Ëe½Þí¤Š®æУ ä‰.IÙ­˜Þ¨qçôHYºŒŽHé«>ƒ ;Æí-›X| }E”Ýz°ÍPwž~»ól?T\ç•åxr/"ô«ùP?–.ÞÒ-\>¡æP¿ÙaadüãeŽdבCÑp´eTä<˜rËí(Ú+š½ÿ>@RÍÿò‡(j¤P/3ÜI5gƒDÂåÄ#Œ"Là$I[0ÃÐWš—’;/½}¾)¿1 üõ¦HšÀ½‰²½:SBɸ+¸±Åð!` ¢Õi—Àè¹u„lmíqg÷³Ç¹±ë°Œ‡HyŒÆठ×ötÖ§ Ö#Å0k“+nÕY›n[Êki]*|›‚{f¹_?_@¬è=R¼D8JQ\ÛùVI†ûP‚¾1yIæ•ûÈ 8…÷Ž+Âñ0D5™B]‚HnÞšiŠÞqEí'%?Jx^ã&®êΠ̈ÙºÔ|ÝkD·JROÛõ…%Å¿3î¼ãÂ8–Éþó©æVåãJ+ÑÌ,ßrñpvTì²cd÷ðeÉœ+ve3©A^Ò“\»¢^‹Þ˜X¹·§­
+öçXX©ë§ÂËàÖ$3¼põb8I¹ìjššÓÖ¥$Vt1þ=ÝŠŒ±•AøEv:7&gUÑ8úHIÿ
+B)%0å^(øõ’LŠ¸¼š>fýÆÔW™l»,ë_vTB¹s¥¢œ8¶&®Éç–Öäµ×ŠGé
+° ÁËJ›¸!ÆPʹlÊBҒ厫aÞM¶ó Ëä3;çQÖ·Ðt²Éùò¢»uµð¶{´_-ÞèXô³$ûijwŒ à€&úÉž­Ch¿A›'5[~gß—ÓzÜÞãÞ?R¨Ø?%ufñ™{)¹†hûü â:HLeKÑç­¨,@«Lì–»ú¼œöZóõ7ú´{CV³K#q9³^PñË uÅL„k ?äO¸Q‰|£ü0š>böô¶ŠwºR]vþØÔX38ö³uÙY¥÷¹‹)¦)Çöd
+©&Ô¤Ûê$~C<Äìu¬ËF«DAjÄ)­˜)¢)AcëM 1Hò7¥‚?¿ÝŠ°)™/€Z` éR4\ù,&±\Yjº!bxǦTÉ4#/Å_>i—Óx¼„;ÆRœ;š Uâ¢8+¾(5þg[“v >bß9¥Ã?²a6NÞÀ<! ìh)ñÅÁþp‚¹~gˆÊ‰g$WT4nÃx÷†¹I¸VBØeLœTçòŸ¥%•v›à¨ÉSñ*0ãd¾«åï7Ä · $‰Û÷òåúR0–\teÆ»•fý¤—š/¯éZs¬¡øYA¬)ímkà–æÒðÅÐüÂPí¢3Ž)þgÛJ“ÙsjG‹øO„=é§Ã, _¿žw"JŸõs¥ú¤pØf¹çíƒKè(¨‘·¾ ó¥Ä÷†§ ¸%ª×ï4V,þH)¾ÓAÃ
+_æ؈|õ\çñHÓÈ¥OqÛѧ©ºlúƒkp¡}¬9PžYß/ {‘Ä¿~G7%¯ü›ö¯ÿ|ûã¿ß@#çÊE,z½áý‡‘9o¬±²0n@Á³È¨ E¤ìkÏr3øT,Yù¦ˆyXã5(¬ÎŽ¤¢¹H}¯ßPxõ²t]‚ÄðLMË)b³îŸIOðD\f çÚèžò9‰›®Ù•£F>™—y”ËS/S}b SI{:|¸
+&°«;åM †¬(ì Òòa—¢‹Ã¢=[»ií {é8+餰z-âÖ”ÐÈ"©@ èöŠJâtI¦oˆ³ü|º–‡ËyÙZŽZk¯ìB‡‹q¼„‹Š¡
+º¯€ÊQ#zÖ¤ ËÍÄÈAµÝEA¡Ÿ ÔŠ°Eú³qƒ‡ã&ŽC`að¤Òáè]FQ T¶Ò{±§ s·tîŽ\ Úµ®¤Ì$ÅÇè¼Sß;{5ál\ÙòõüN&×&–D.°¥ÁO¤°#bV²¥h˜Ý‘˜>á†Þ¨DGö[A 90ŽâîâûY»my1 Ôû}Z̤ÉMm¤w%ˆÞê)A)øî?¿ÝÐòRôõ¦ÓJ$騽K–§ÁìJ¼‹•6t@i›gKôbßJ| ˜À„*c¬7ß™2Ÿ»A§Áƒ¬Q²’M×€>2+€ÖKsü$^á$,Ý8úU
+]Nš¦Mæj[㙶£Œ
+{¡—vÓßt—1ìF„Q‚:½À§ŽCZϨôˆŽ%@AYÀšºöÁ*½°žßvˆÙ5&fi…´ÆÂ<o5Ô¼
+A Ù¬Šf'Ä—˜_~ ×Gä¤ý¥o͸Ä`h()µÐ~[*×ùã¤é|&¡¿Ò¦~xZI¿qµ¬–Ìid1wDt£k ¯*GˆÔ‹‰‰PâêõÊwø0YÎNÈ:
+PèÔ…Ì·›ÏpuCæX¨ûQL²z¤‹ýCÔA—¤ne sÐ ÔUê}Ü1àäJD¬­½˜çÁ^EkѬÀOâýr]£W¨ ÂÄ}ŽÝ…‰ø‡YLrFXøÊ’æ—Ç…
+¹šÀ¯w1Ó8"Tfi÷«—U’Gëàkb-¶—ßž^¿Ãˆ4MƒÞZÚ¹Mˆˆ;%ž+DÍ‘!eCìåeºP;Š-Y“Ç@c(ƒ˜ã¸¾Ã{îlÄzç87…ÛA¬¢ ‹å ¥i½±öQP´ÐêéÅ@„”Ò–D·³˜(ã÷2ç¿"Xõï™:~ÂÏESFrÈû›óßMôñ“uõ‹ÍFºŸô©eÓmŠëS¤FúZ—T~ºAM¸Bž;û§/©T,Òtæ~£QÇ‚
+"' $^ÅRà%À[T£Í;!\É]vŠ`Ë1Èf®¶LlJ5ÿ­f4Ö2 %– ¼¿Ã¢ ×Íko¡¤ÔZ =³C—
+7ê¼
+çŒÓD¤Ñ¤Ž[àÔÉÚǼÂú‘è³i÷Ãm¬í){ø5ÈiÁLJÑ'D–Ù?r¦âzÜ‚^Õïø— 5ôé‰{Զמõì×çMq*> Qi3g†2Ö|†°Fö}‡*"êBœJ­o[1—óKiŽE²ñ©w±ãäVwL ‡Á,û
+£Í3h’–6‡Ñ/êÌÄg‰•B²"ZÚ¶¢Ñ ©¾»8,ˆºØw©‡ç¦hŽÙÐuPÍÉ"föÓ
+ÈŒº®Å-éÀ0Òá¬Ô™;A6å?q[ÚŽ³¹ä>>™Å‰a®ï
+
+ù§)É"ú¼ ¡Y™ÔèçñPù@ô¼)äål…¨#б©t9†ã7G¡ t/M¬ênÿÓFC? ŒBd» ZÆ~%FR‘:’§€F3D¬ØÙI_#tV"Ñ”®º1Š€˜ñ,¤˜Óg!pD¦*%^yAXx®”Åv¾Äv è»8^]í}EAEðª¤×ígOB7¦$6ÔéÃzwåÍ`é³ôYÎà,šºÓ‡æëÔ‘‡Š ÜÄ+ÃÒ¤æËÅ Y¥d躀•»ï¼Vûr›k×8¯ºvßkr®-üš`¯É¿Ôé÷÷Ã"oöT±mø{|tôúµO7ɈSZÏǾD€ òÔŽæaô‹E(½A5ê äYDcëÂús
+?ÞCX¸5› ÅUö³*ñ(KË^ˆÛ/û ¹[‡áúä¥yän½ÜNl§vî·g»Ïh½À:,ÚÂjÚoÊ9°ÙNmõW}’MäC›¥ôDÑYoHâPn*oBå Î²Ì Ó ëþ;[ý w03=ºÂ¡&¹46ýû›ôŸ²¸!S”&ÿf_'•Âa#ïÈ/ÐmD\ïæòì_m³£J”$›àÜØ .ì.Tž—®Ån.c@yYÎá¡Š#‘Wš±Ž TJX釾J’­e>òÊ*ÖŸÂLk­Ëîñ&àša3µ¼ûS¿ˆ —ž±iHõVŸS…Ô²w$ûô¤µïü¡³…dd{ÚG}3™âRñºtXA›ØÜUX úW}À.›ßK ”òƒˆ“2O¾Ä~ã´~çæûÚ? ‚DLˆˆô—Ú÷1S‡•dWbùáÇ;øC“>,¢KÆ@"Ž ·è&«ª‘ákÀXMf÷ž¥:ËœÇ-Õ!Ç'oÕ·Q/a²¡%™L—Á¹Fv-m´C:"(1;„Ö×FâkwBÖQZ6L‰&¥Þ|ÂÃ7
+áÝx-‘sÛƒ,#…˜£­[Èÿ)/“ÜJr$ˆž ï œ‡µjY·È­tÿm?s2ùƒ%5Õ@J&éƒ XúÆ‡à™œ<±>E ¸±—ܵD
+ß*­s¸„Mwnco;s3Ñt†ýò2¤¿<Ð9í…æÈ苇QÉÿt, ÷¹€nœàn× cìRP*)´¬üê|ïkDþ5ш‘eÿ4-"Tl&OÙàlJºôöU ’WE½åiˆóÈ­Ll¨Ã=FŽÜÕ4o…³¦êó$ÞAJ[4IZx³8·jsY&“ACMÕýt_±í>x$Þ-)?Äèc= Áâí
+:9ùìRäA…P´”èËbáA‹’Ì¡6 ’“JŒ^…Ë‹°`(7íìyOÁõšÂÌ®‹v’’ˆ7`·ÙM†C‹©nõ$®tòÛ¦‚±‚T¥§cˆ¹¼ˆQêñ’6ÂÃÍÑú™¼s¦²Bëgþv(Á <û}•†ÞÓíjÞÛΉ]Œå¶MÙ«Ë¥U9!ƒàù¨žOÿþñËÁxýn–’¸+cÅùè¾|Ÿ?Ùеȕáwñ¦Êºkß“®M‹„¯Œ˜)Ií ̲Ôó¶Äü¤Á«ãĶ$O@Wñ;}Ax3@aeëF•ÆðSD—@´@ ^翘‰ vͬ¶\%o㶊z˜vðÚˆÁÌ Ï2Ù0?)wœpuyà)ü{E6¢!ðá=øaíìbÑ­‹¢…Á!#IÉ­®ù«GûC¥ Uã.%ñïÂï5€]çpßD!FNEK”¯âÝj£Ÿ4YÙO¿yåå`­
+T›z/n“n5 ÷V;çÜæ~™sîœ7yó FB)÷”at·
+ آnT
+¶–Õ¦!
+œÖ·¢oS]Rb½¹ TžŸaˆ£Ã1½£AµöKIg@pÐz&
+÷œòŽ
+wx'kåömRž3Ñš8²ÛËþÎó˜….\ÜŸºÏOϬdË"­õ©ûdu¼ÞÀH1[™ð‡/L<󇿸^õŸC¬i6íù]­ašF¤Ú ˆY ©·™BŽ6ï'¨¯ÓPè”õþÌLÖ ÂO×Ó‚ XX>ŒüN/ÚÔ–pÚª"ÿà†—Oí{c!:š\Ëåô'­l¬j_ÓiU qmã²O¢eI ‚‰ÕB`øÆp kÚ!´£ª¯hM¡<-êÒ¯O•0 ö¢í{Ú•$‹†rnæ02» C·~Àa0iž¼ôÆt4S7´ÅñÁ ³º,_ÆVïó4CΈ!õÕ(ð»©2gyRØîaϪADTX+Y† )Mª ‘î(`Ïœ A7S@=+p°™”Uˆ6`r ãÄ-ižª²Z:Y5&G¥œdï©>ÕÙ‚2ÚÃ9\rdMDzð@dgrÇLîÑ@¹ô?Zºd‡ GøNå Š×r$•aƒë>‡ÀÆ"Ô´Þ6ÌÅ•*qCʤp¥$ß ]ë0áG¶ ŽguØh£(ýü²{kP±ÉÀTK‘ºô òìmG8‰m×·È›7Œ˜)„SöÇ“ŠÃ¢ìeU9ŠÕRݦY -•vv.›èCÏÉ“ô‹”v}*Àa´ldNâÆð¼I~ÅQas<ÀYv*„ßß"3dPƒ ÞÖl(¿VåÚ¾6M€“¸ ¼áå1‘û‘P[='Õ‰RÔ6,- å¦Cñ)] ÚŸ~íTŠiÀ÷¬ôìÞHX`lUÑ/š}*˄ÈR­Vˆµ“£òšVŸ
+÷Œ¸Ÿ^lj
+‡w¾Hv~š;ÙzL8Ã%£vë,£!&­¦íšÅDP¬ÒÙ
+.Ë0ƒ|~™Õ%]V-Pþ@¢ö@Þé=kËpךD÷œ„oÄ
+ËYûÊúü€!H 2¢ÚG8¸¬·…ä$ly êòŒj’ØÑHÅý)HŸÃºøÒUD”[T½bÁ;X… 08žë­o¯Á¯Z‚÷J‹,iEÿøѶÈî#„2Z£”ª±×
+C—ó¢oþwùÐŒ›9‚÷~P䞆YŸR ÂøðÅQÎÁUYcÚ¸Gc@ùrQ Ù›æ úÅ0LØsdÇþ^C˜‘l>ⵋÃÐÒrà,¢£­ŠS¨ù‚$„„t©èÕ ‚¨Puªã>E6¤ÙKÕŒ×ó
+ÿgk¯ïE½€æe—ôÚýcCÌX4ú:½Çýʰ碓c0ïá_ V‡­5X{èo†Ô†gvmì
+vüdÍi5¸‰“²LíšÁ
+§Æ¶ƒc²Ç(%Ýk>fM=ƒŠ`ï5ªÈ 8§¹”kÐ+ï³@«Éþsź¯Â<¡Þ‰¬ÎÎØk+²EËû.uLÅb¯¢Þ¸.!VŠ…”­MÇ
+?÷ä–ˆL{”+¹,Ñ÷ŠL“49ŒÖæ•9{=äcòÙÔ–’Ôd!"Ɔ§Øó}Æ$MH%€‡õ¤D˜bŠ ÷Ì Ó‡‹PŠµõ>«4¾åø
+è”Ńu“Ì¢ûa_†dfFÚ]~]Ã(=W&
+m±AP1øH±Üòi¬4N’@µ% ôp”cb„¬LWvÖê|³°· w¡tÄÖa78.ɺYâ$«³¤ñiÀ_Õ┬A@ ­
+¸IJ߄š“–°óõ½3AíB67¯Ó¬ Càµq T1ǽ@°:Œs(˵(Ù+aÛ%<€Gš3O;l¨Ôº9EEb\h 4³àQÐ=è0Ô}erÖ€MŽy–ˆ,q ðt¹Ã¿xQ¤®ØÞ¬J{xCi­l»Ã¡ì= Î]@™œmMÃøȅ熖wwè–DMݦ‰»³{œûV€j"&Î>èbÉ„¥Q—˜Cpp&Ml²‚®=:F£êm6 CA¬6@ þ9Èÿ&AàÏçƸ3l!¸˜I#£öẢ9X‡0GÕ°’}Š¶ Ÿt(GÇߪb°ª±
+ræþœEl ù¯*¹œ¹¥§¡èr”ð9=–}êÑ~yõÉÁË°>€¨°†løP³ñpNªAö›íî‡asìÍR `Á“9Áö~ñ«
+¿Ä™ðBž÷a"èæ8ûü/IPA¦`Öî |²1BöÀf‰¼‚ÛG˜y
+¬ «‚Ô¨eŸnžÞtøwàNô’w¯ÂNÛíã øi¹èѼ
+sŸË…xxò&þé5´…LBkòR’ˆç‡º†$¿ŸÒ9W1ÅY‰0>»èĘ}mn™’œcÞ–ŽÅa:ãúÒп‚Ý°é¼Ü‘_Ehs=¹ûç€ã‚8F¨–;·‰½ËÆg G"î°èûUüß”—=n%7„Oðî x͆†nêΤÐ÷÷W$G^Íô`ŸaÀßÖrÈî®êªˆÂ|×MànRjž9æšUqŠ‚+u­}Ìs°æ|™×³lw‰1‰œxåº þNêcuŠÀDÑ-Ì&/_0¿´ýÃCà$¥=€F[ŸA1hÚû;(`Ž¹VUá×£YÛ1°ëaÉÐ#ÁÎÞ&Ê‘.omÛb=ÙpfRœ?¬\g¤îyaG=§ÃHt ¬L,•wϱéÌs+6N'X‘Aíxú5 l3ÚÈ-óεðäOa»#/`úû£t¿Èž‹E­[X”i,Ú«‡_ X)^ø¬+¥hüÐVªþþ 5Åâ4˜‚Báe‰¶s`©¨Üaƒš„€z©~%[TG3Èå_„ xTÃ(›5‡i(sT=”Âä<ÑJ R>&H½sô°PI-©k8D;DŒ3„Ñ\´®Ë£¤ƒ1Ì01ìÂCæ°_@W¢û0l9X’ë“}¬%!:ZÅÅÐL®Ä|0ì³<ÈãR&¶)L»Pv&%W›’+jÓ`N:„€žÂ\UK»‚†pb½:róFã 7@l<ûiö“RÉÆsßTÈû ÆŸf o¿9«K m¸Ó±Ç«¥õôp" ÃÎ)ùk3Â:S:‚¼ûKP3PLxlÇËúË\|óÃÙv©U)BÅ›4»Z_¼Yÿ¾<ß<>xǺþQ
+Ã#= Š™z•)†JUt½Ò ôñ G•I
+©N;ƒ½sr槇¹sa*̓-IÞû€¤¼¦ð™6èòµßc†>&#@ì6 à`°IÔÖctt"¨û¿hÂV|¤£ mBØtÈ8zˆÂnÃ|¿ÂÌ™ïóK¨~Åsè3˹Ê/Dä}C´¦æäl¾¹i«‡ Iºz¨K9õ%9=œ)tÏHÂ5 õƒ;ûQpMçQüÅkƒ.¬dÆÂ5Ì™¾€®)jÞgD6\E_Ò–ºÄ&²V}¿ —6$ÎVÌY”³~]«‹ÐÂIîÂM£¼jŽ«*ÚRqÏ)zE/±y_™Õ@¢ÅÔ6!„R46ilˆºÂ…UjûSÐ ÀjÚ‘Ä”çPüpXç$j‚­ž=ü„9—zÜA¾ éÛÃ9Óž1ùUN#ŽzØƧ@zŸ{tÒ—]'ÌR—LÈ•í…•´`QÊIâ eŠ‹ažÉ yÍÌ-“Á i_(ãê±ÿý ‘:Vccò„ý"¨H¸BÆ@œ~º/ÜFl §Ì80XUKïD‹ö»¸mᙹ Ð^ 6ñ@ŸI¯ìP†LF?›{%b íxòåç«h1ìæ=€%Álß­KzÍâ![ãÝêz_z´>t…X.ØR6®п N™°±at÷M™¥Ðn<6ͯµ„ñ`A£°ëKçòf’
+§sù¥Oo›pX&¬ÚÏîwTûsÍ y¢§FMwvåò¤âò¹3èã™;-­0bmgw!º¼xgþg°ò:ki^=ò“¡|ɽþœ †3㨆U½S9{ÕÓÈ DÑÖnŠ`ú)æÐŒ‰‹7 Àè&Y 8ï¾".¬4¸Èž¦³` F#Q"ûBPgöKËHx \m+–ÚÃðˆį(Åf'Â"ä$¬µKÁC%‹6Ùx(±‡!‘¯Z“7µ ˜\‹F¾¹kåã™þj ~üõ/üýøñÏ=áÆš®I‚åDÖÏ ê§<Ø}ãI{^‰
+2••æ³NbЕX+5ÙÍV=BÜÍ©G$žEVd /‚ fÔpìclC}ðjH£òʵ‹yDèXQj[nŽáþq*mC{‰5ø1!F†£È2´uC(gE&W&Äq{¬âDuguŒp‘Ï·6ˆÞ4ü^í³8Üš09È_LÈ|·¼«be ›s4nôÚˆ•Á¤3´•DkÛuò­E©êQ™ZµiØFµU!%­cXrŒ•ȶæðHˆHuZšOŸ:fq«`¡ÞT‚Å]ò.³Åõû²t¨-y†XE|È|.Œ»Ñâœ3Ûò»búñ̸‹ úžb‰òcÞ™5!|®3ÝŸÿau•’”lÉ Ûü`‘e¬8Rt¹F$~}45¤nm³¢¹LJR ‚N¡þq,û±…Ž&`g!/ «´QO|7ë,±òÒ³¯Ú¸ ¬iT_ý&ˆƒpAü\vK…•‰BG…êœzÔ6÷ý9–-/ZcÖæóU
+º_˜ê¶ jø’*ÌU3à¨$Á±ò>;F;K&ÖõâÍ9rFH(jÔò†pùÈ/1p¿9–j‘3A‹<²4ÒþÔo&Hƒf/µWy>
+ÓfU¬M’eòêr¥Šª›H0`ð‹.„.ÁÖ>R‹¥î/ý†–bpä,JÌKw
+Ž Ý/2 ìÓ9þ
+kgT倾 µLƒCP1Çñ¼=<3…¿ÇOÈ–&? º0ÃûÜS [ý¡?óÙE
+‘\ ´g?'cH6%ræèÙPAÐ}¼ßúÚ|‰Óñe,O¡?¸R—›‚I%QÎz7~b\3z¿?u}¸ >–¥Üò”&¶¶yeÓ­KßÒdÁo6ñFÄ6)¡õ=øç†?†ñuι.I>sÇöÇ=÷ }M„M[ÒU˜x‹µº£H‰¡#­=}3Ñ…áT·
+4kÞî„‹iÙLú†¨m…uÀSË„h¼£–òáòYÇüT,ƺ¿¸N†7ÔïØ=8¡"Í×9&ó&$”MÄØíÚñA‡i,ò‰±÷Š‡IÇîQV)*2öW½ô@TÕŠ¬Ã\g/¯ ú’’ÖV)­®g8«'ÄlÇô%@V§~âš0É{ë´DÓèvÅýì——&ûÂ[í kð_ÆË$9’[ ¢'è;Ô Ê0ëÖ²oÁ-ûþÛÿФÌÈOši!•‚H ÂÇA{æŒëš‹Q½0yæÝz»p;dq/I­æø²0Ť2‹¶á‰€Í@ ´Ñ}1A,žá³£ôAÁ|vŸ¦e(ß¾¼U!Qz½H%µ‡ØF]
+òek–÷å½}>U†B…0šVÿ†4`à™f4U/aÄŸº°ÕVVah°S´1Ò…¾X»6C &ÛY”ÂmÒ.´«íÕDB
+7& ¸Çä÷Àòô®[LØóTÚà=.†‡C,0ØñëMX}F…'ÛUàÍ‹ÙéÚŽ·
+2¸4F(ëÊpøR7¸Ë ¬ñ$‡í’ÒfK±%‡Ô¥É~ÍZÌëÝ‹è”B)%-þb-:áRÊ_RuŠ>wãk<VŽ–
+X¶‰82i†Q¸2 OÏq¹ûôÆ—vN)J`®ˆá¸oúm8%6rxE?hõáQœ€ 1Ÿ
+à7À:ÞZ«l°äIènæFišCþ,~%’¨½“3;"QY+8¶¶=,Q÷
+óí%ýC¶ªso:Vgûi‘hc}¬:ÑÈŠpcj#oEºÓÚ eªZÊÜ="²¡¨@µs)3ð­dXFv¹ŽqLþ%E”ˆµƒ=L€O¼LPñ0%‹̪Bìéʈ”tixOšª•Lmâ)Û—¾AÐmà-¢ÜÀÎûF$ÐÞiCQ]@s‹b¢…Ì!y­
+¬*ÛÊ[¦8ë¢Ef’Äxiù¬î
+Ä'×ó|?Ö‡rÛA“ÝE8îJ·Ä‚ûgþ?š²ÉŽö’;ÉöU‚uƒ[peëÒ¥d
+6` Ñ>ëÃ9"…&?Kvo3–—‡È0+³<¼
+•AKD®•ôà6Ç€¹Ëru›¾k‡½Šÿ jé^T[0€¥Ù_º^¦BlÈ]ö»ÿ¨ŠÂÀ.ëmý»6§îæÀ ¼¾¼×÷ȵB»ÈŸMó:ªKÉþÔuäÎ9Wà8·¹àÏ}ÔÆ·æx»piñ·;µ8^“€öÈ&„™rTçßLh«W[’ã×ø@—·".oŸ»}þäNNH/DÊoÐtéÛÞ9Œ€å@^×õ½"‚ÿ&’©*¡I¬Q1'bÕ0 .Ž]!¸RÅ<ͧ§&–äúµíÑ•åž;‘|c^ª
+J•(â³<07˜D9O6ÔG<˜#$ мm,*ãh2^ÄòŠúO‹<欋Z ïŽ-¯ÏE(:fŠÖ-<³‰l¡£
+£H @šÖ:ÌI
+Ð È8›,«9M'e[šŽ9Äç’äŽI@\£tf‡ ô줅LÊxÓhìl{X S–9oÖe¨éô¶E
+ª› Cûºr¸éŒKŠ=ÄS¥öM²ñBÆJØ7SШZ^ÒÜŠY’¤Î&´}Õ99u%‡´â'â»—â*z­U2íjžKu‚¬RKîœsnç5çt¢º6ò%;Þ4œrüãT}ØðQ
+(· ”ißÃut1S-7áŒqÇõ2oküø"Û M$u‰ä|1xgÉRUµ­ÑdºØÏ£‰ì-jº+ÿ˜ÍßÈ ¯!ƒjÁëHú—A „[ÑÆä<ÿº×@°/k¼gHJsF”ÀC|£úˆ.™jd|¥ Šæ
+„£ÄqòŸ¾ª 0Ò!‹ºsÄ®eKGŒ^d"°7]:IósˆqñÔg“ΧB#ˈmê­I¢Õ¬÷<EÅw 0êŒ{›$ö,ÍG2Æ4HÄ;Ù¯\«ˆ™Ž‚ –Ãù¹…ÔiñýPŸ§¡E»­FÝFŠR²f»`°±Ø
+žG±ÉÙÄóu„m𙃠z†ôt•Öèá…ŒLHˆ•Å‘—s
+ï‹Ìƒ,H‚mZ˜(Ó™â˜(9äðŠ‰D ÚØã¤ÛÖÁ<¹¥/C™£1ôÚçº)HgŠz]Œ®X*±»Aðuˆ ¦<ÇxÈw®W+Ç7¤‚Z|[ãGíž‚+ ÈÍt˜xÖ­ðÉ#µ,ƒG7Á'ȧ•"÷9d oÎA8LÆ[ “·äGÑÀf­ä6o"¢gxlÖ1ˆs73—¶º¤×iΧ"}¾ÐÀjõ`­Ÿ2åuÀOç¸oÄ»ÛY^—
+¼ B¬”œOGÏG±š31ˆÒœs«³+ãiõ|ÚUÚº
+Ž­îê‘òìÈ-DÈþθ–ÝÙ=EÆ ƒX
+©ºç §Lg€Âjv_SiB„¿¡*2§‘véòSnv¡”Ïèæø
+9ÕêãÍ=ÕþË!˜²¨*Àba¼{Ož|ÄŽá/´§:R…h8²!Gù
+H‰Œ—KŽ]¹DWP{¨q¾ 3I&9l´‡šz {ÒÒÐû÷ ’Wèz–JêÅ$óÙÊ#çÉZTÿüGõtåQRÊ©‹ø,­\>JÎm$« âÍÝKqëæ@üê=R þ£ ~äÑÌ#u«ÅçØ5zÊ­Õ\[ªÇÛØÕF¤Ô£÷–
+W/=ÊÈ­zž‘ì*–=¬+5/LMa-GM%­HütDmä>$¹gç¡Õ{=B:çZ탣kÛ‘Þ19ܸsö‘Úç·ÿ
+^Ö
+_ñM”Có‰ÑK…z¤dù
+Eo56@GBTªNHΕPEZ|@(Ž3_\£q¿ÑëÃ1dÒ*ýØkùyoi”È-ú‚tb‘Íf»LAY4¬ï@°(7¥‹¯„— W2º-É.^S£I|gWDM(ÈeC:™2-ö)¤~vl‘sZ¡ÐӪΓÝY Rß±IŽq"ú@Æ)B¹/¬Dg~NNË„„,NË&o¹[¹Ä;Çý(RTe˜èéÝIݨë¼B©(dÓ1`kxrÁB ½?@pÌ 'øûŽô†±–4ÊI£qº0=„ãã·Ž]IDG” · ADôAß»NTÃðS­N²Sfw<&ļªMc2žÇ*s–¶º“Ñ*µa—*UÑ7¬«…ßÎá rZxLfY¨¿ÝcÏ­j‚XÒES t_§‰Lþøž&bhš”‰q|™ ˆ8T®oH£É¯®EcQåæÉpK+;}V¸2êšiáJ¬¡ÑÅ^ìG! F³¬s^ ‹g: J.ø3ñ‘¬AULny‡z%Pz¢&ǾFÃr~ži¸”Šî1tÇä O!D Å
+»CÑL˨톖 E¼ÄîÕ×DÕijãâ†,I©Èê$Ê 1Gçšé;¹È”§Ûò7Eæ§RÖÕA¤YŽñs¼þú¾ô<\»¡ß÷ùY`QŠ¶ªÅbÓ´~±a 9gˆ£¼Úô,Ž§wîÙáW$Œuö扥 ¬Ýu;ä„$ktý.yÅиöÍÕ]#Ë Qœv3݉nš£ßŒ@qÅ,ry· 4»Ò›æYgc4 Ô†¤Þ'ÿPÖEs¡m$i‹Ý(˜ªã¡€[b%,ZñÇ4y…§<‹Q½FF5ò2åˆ% ý<éç d+_H}Ø*Ããáœ^Ù4‘tzùž=¼
+dDC9Fô–ŠB
+¥‘ÐÑò†—žqqÎm‡ ÷&ÛÄømP…&ý]j6Ĭ±äsŸƒfñ'çÍûŒ#Úuýœ?ÓŠ×6nÓöË!õ ¦u‹bð¼Yp_4)CǴȬH]RÃÅ-KJ¹1ô#õµŸË©‚‡!¯;Ép^å X~{ÌÚQÜÆîó¡dçc->O:õ²¥üqÔÍÐ÷'>ÀØÈâÙ3q¦¿ëCЄ×À²(}?u|Éfh¿Y ÆÒY)WßEv®)j[Çß!ªRÁÂùé_Ax -¼…]ª<œÃ°À9È+¬ý
+Ì'®‹$=†rv?Ê7ÇèAúX)´E>]æË<œÍIc[iPC†`(Õ7@/ù­|;/qý%M‹ SAþm6Æ CÅÞE1éa@°´´1t°uˆ’)kŒX
+ÈàÇMA7 JÛ¾€¶Ä|±¼T¥¤aGKÜÕ–ÉßçåÆidx cÜó>§°!꤂™ÃGæRî›Þ(É‚ T¶îJ|xû„“Çh¢á òÚ‡Þž.®*4åvÝÃïÖ^mfidE7´#k*€YBî9e^»ýÃÙk0˜K¶ÓÃÊÓ‘«÷éì)â»H´xŒñr*Á–ã¤SŠ¿VÊ´ŠÁŠåÃ'ͯÄ!ÄHœú5í?3.¬œ~=K ›;€h•Ëb§G‰‡Dd1(5£QSÁrð³–/ªH|~kÀõ’Àwñ8¦„2ˆ¿*Iüæ mAXòdý¨FD¦É¬Æ9†ååÛF†œÜP0 H€m^þ1„<üžG¥H LówݯBF U¬u»þV‘ßô~îsè #À\«ÀW06“±3'>-ӽч+/ŒÊz5E®Û>ÆL2œS½>1m¯ÀŸºN‰ñyì—€SˆÂ#Z=Ì›ÕlN¤áÊóÁ)ÍQ«‹&ʽ2Õ$# 9Ûc˜õ’”¸À`-´S0rT´—[‚ @••Â¯#x$S™ ¯¿¼
+¦êÍ"Ã4G|…ÏAJ‘"l±hoòÛ•âJ ›+|.ÿ'¹˜í@
+ƒŸl'|Š¤‘C¦gŽ}Žà?ÅL×aOFÀ¯±îM”Ís'ÓÄú4÷&ôšvaW’' 9B°£4KtìT#èžßçÀÏL‹Ÿ~i^E]®;{P`À˜«P‡›î0.–>W¿Ì¸ÌkÔ•iÈ“uöµÏH4.É ûER!ê +/%k24UÁ”FEíëÀÂ’]qŽi26€Öþk ½AØjÒ-ý륞€}ð¤Ö¥ô”°±Ì
+Æ$ä|QlZù¬ŒÙï£d#²H®'
+KJvVO»,G˜gdæl„8
+˜2ˆnA{v‰ò.ëý
+ Ë[zÍ–ÍÎÒðµeÉ¢˜ÓI&,á6RQ¤ó›š˜M’uIé$³1.³zŽéüEKn|ó¶ÿì‘‚^;%@‚ŽÓË-)‘œ
+w×;¨AM‰_htê'¢'—â%¢ªJ³‡o9`„ûÐóù tܽ,IÆ~ú–Ë #:XÖqò¹J‰ÝrB–½ÜMi6b/žGËn2¼óòÜCÀ•Ÿ Τ…mÕæÝ›
+STfÍ}Ξ8O˺7äUi•¥Éó”À"Ó“UÀqÔyipÎSì)Á塾¹âÓ4èƒ(2ï>`>`
+?¼I™<U OšÏU"¹¤GWûšh‘èm—èA
+“Ïó˜gËç*]ÄÜÔÛi5§ð³MîiÞÔ1>4¤ŠººBÙ¹
+—ÑjCä{rœghŠØîS;çÀYÛN8º®ÀïÔ¾Ä%j¦U}eºˆxÕ/æS¥­ßs´QˆTs{Q¿
+“áá,q=“’NrL¥ú)8æ.+†q¸Wѧ©PŠäÛ)bŽ@O{Tú°=C@¶uR#º¾é'ܽêAJckÒ›3ñGɹJ#cb/ç(/$¤RHñ’LfZ ƒžœ•âï“àEØõ–õ™¼>ßåE«µQÀÒfø(–ÖÈrƒizÿ:ŽŠ‰–qTø“'d´ð˜`w)éÁ7òPà<²Õ‡ož¬Å¨D
+·­Wý¦Tú€ÁÀïÔTCEcTœ¿Kؾ\£øVª÷€&Ö éHgÑ0©‚m¯~0ç÷HÏl‡u g6´ÉPç Äéô3_n²õr_
+ùžuîù1y}¡SâR,dšá›¨ÁsA0Û{cðŽryš¿gKºOÏ»®Aû
+ë4¶}QþË/yGJORAbûÛ9Å}d™íš’E!d–y¿—¹²’†ËºAŸ°åPuó¸³|ÃùœÅ)¤Lì_[a\ŒÜõGûl;9à@í¡=Šš0\Xª™CÚËìîÐ"°unäs'ËÂc™SÛT¤6–o†í’(…)¿*FæùÃ\7pu4 sw'ÎÚ*(k„\ù°ïÛ®¾È%Õ†ÚK Ý<K ¯WÑIˆ/wiÇË9D¢hÓîèK‰ÜÕ?Œ—IŽ\G DO ;èFÎÃZ^ê¼’ï¿õ ’Y°ªò ¶ÕbÿÌä|1 i_íñ(y%ÀÓû¦#¤À¯X\J‘Bä$y¶Ø¡?%®, ¼*ù~e5à†•š,É=o­þãz3T
+]ŠÑaßDNQþ‹(µþå ””bèyˆöû!YÝ8¿=‹]»8² Øþ!ým…x¼ñ EFŽ}ßè—†
+ƒZUì”HP׸"êÚǶN¹ùÚÁg >Þ9!U( ¶PÐe+˜<f‰£„U¢>Qm¡ÙÖ\nO & ifHZ»Nº!Ÿ‹^Ž”¢÷Ä—;ç}^EQ­"9mÞÉçä!Hƒ§¢¢­Y-ÂÜ’…,Ý#(š¿(µûñíó9—P"û“SiÐ2¿ó¹é?ÏúJ r Ÿ®íÞ¦1dúJ fö—ã,Ö*I>´”Œñ™HÎû^EÜu{ærÌS…÷`š¥ÄÃ{Ë÷¯üÉÆ·ˆÚ
+ÖŒEÌFy:GÖe ö*ñ•ŒºãÕ"4V…§ËÅòGT’„úÏp’× w ¸„üOJî0ÉÛþˆqº‘Çc’¹a§´YkÇäats‹ayâ6ÀÄ´5á„°{Ò0?x8µxaC\в܈P@rV€ é 
+eòßθÒi¸U¤~cÈŒ»Õþæ7`—`HÌ™(j"ÀdYë`&K„*ÌÛ… .ˆ§ÃŠ!<Á™(Í»ð=û¯\¶IR9KSTž´KAõ8Ò¢["#Ä¢‚ž8*­LÔtïräy1Ê,}œ¾péMŒ3ÞDz€%¢»£¾¨ôl—µPcÒØIOóuwù#ÆÊÐlº)Ûèu  éç‚d©‚k¾"-°ƒ&«XÝľÈ9_®‰dl‰uNãš¾IOÒ|IÕ¼Áâ³Ì{Ó"£@&f€§2p„T]òÔþ¦Ø@ü“Ę"ìÛ k4…ZK¿ÆÒÛ¯WQmŽÒÜúÞ¤I‘4äoÀ~e.)´ÒʧÕõrôNšD¨êÒþy¡!'L¸[é>AðÒZk<Æ$s=¤˜Õ#¡U’!k<VƒbØ"VKØÛ HI«–!¤xC? ¨ßg³Éh7zuƒ‡¡þ+‡0©è´z“sÜíYDÐw"«N¾ H= ÉÝ,ú)"( ¶ÇÈÔÏKØÕäŽDߌ$!ÍG­ð ‚'bí£`@g
+'‡ø³J1 äRËàØ‚ D}¹ ñ !¡˜Ckóu—)Ó¡çrº·?ŠŒpWÚ±Ìýð.G§OÑJ}¸zsPn)ýë6 Éut\Êù’´†:3)Ðjª×ünÄZ-ÞE ÷*²ܹPãѯµFùLÉ· 1ÍX$™:)±‡À’xú(BÆ€At¢ÄQ°ŒD–qÈ‘aÔ
+
+EÂgŲiògZz·t A å(ºø/Žú B
+\
+­4O­U¶Ê¶fD°ö¹mbRs{·È­+häsþH>e
+TaaAäÁ¢%H(k…´{
+á €X/Œò˜c=Óz_›çñ
+‰¼ÀPükí,ÖRR§ßx©ƒk‚vÆ 0¹šúÑÛ†QÎÌ<—ëqI#ÙSf U.¨Q¥\b§…,‡D®£ê€!Vjõ
+*l9ê·D]löÚùX½İy« H1î—>•xRÍ–ñ„,ñTòêù±«àœ
+ÑkùpNÛb|øÚ>5J×­™Ï)ç{Ù`”…]Åo"ž2 z/†#!L‰%½rJ!(Pówü,C^ 5»J [áºs4N‡i™§Öüªà²˜Ê1†a{;–«ÑË9Ö/Ú_ñŠ7\î
+s’h„Aè,ôÒp~
+uÒ´Ar>~
+cô Suöa:$wq\“£šr` ýhÅÇŠGŒŸÉl zìnþ2„ ™¡žÓOžO—”—‚F/3‘©0 “†/³é«Zb”¿"•Àåìî3Ìl2!sÁÎë¹» ·s0œ`÷½ÌEòÉRtÂ’^w ç*š-)õúÑfÒmU&ñ«˜3…A8 &¾Ÿ°¦¥˜qÛŒš¦“·ÏË¤ß Ê7ñx‚ÚѲ]–».¼ƒø-MEçûe2ï] •ØÎOˆ-?A…Š‡@(ø–5îÛ=ÇèéÐsžsØ9‡æ¨CYW3bk`Ù³qé- ¬K–kb"¾Ñ'¥7ªsœLjç¡õuÕ#¡
+èuïfzˆ:ô ,zª¯ïý͈þõí’µîêÂñ0gp¸ fmr««»¹¦¼äœ-¤™ÕÄ©¤pBÖ¤0K–Õ^>‰Ò¢Üš!m,E¼8¡„Z·8GŠC½p\ÓŠ -̱þÍCc©1
+ˆÍ Cé­™ÐwcªG¼„|^ýD ˜ÐÔM
+*º›WFbȬ¢~ælžæò­¼@pˆ¬¢”7ZcH} ?:Q{ËCËe“Žo¤.ÂEкl
+BœEít'‰Â 4ÐoÞÚx×þÒjW:5[v™O¢|Æ­;×åô]FjŠ¯%nz^Ç&'¢õÏAï%¸\÷G ü;!-/8ësAt˜Qy¶¤õ¹BàŒ¤0l
+_Â(®»ûÈiþ–at¾@þ>“¡$&a6æ‡sþ-“P¬€È33çò‚ù–.*¨—¶«p—hÒÇﯞJsÚüÁÏ{Ô=‚•}´“éÆ
+À.çWý*!
+7±„ánEµûÿH1aÄ•{·Ûâ
+!*Ð5síËž3AºÏ!_Õü=
+C)å §ˆFXgÿâ ÓŽúaKbž;wD@¤w+Š÷ÿÖâÇ1 ‹-àë™PlUèØ¢‘X³† ýü€éÈo’ÛP𦶠Ï-·¦ù‰`¼T¿áç
+²óβŸžLpVéðnqtZa‘›¬$^Ùí<v†Ãqí3Sâ·ÅªªÏ$G½xHZ~G’ÍT ¬/Ã.ˆ=CÝr  Jµdú`Å›˜·¸îô™o î \~Ëa+Ԥز%R@¦Hpž6úb)HaÉ©“°ã_ väÁ‹ Ï«í‚î'tV=òÝo”””¹&_Æð´ï=h[Pd9'<tóÚ@¸3Ø$³íZ=Ý,VSíZû@8ü$F³ñA&€
+^­cºÒ¸óWý„ ÐÁ”%™'¢çÀ™i;²‡0 @¯ôò þB¤£xèˆ7áo»¼ƒ˜îð×D ×ÊÊ0õ¸CÃú…é†@éóô€’‡¢Pf×ú§:ùòÊxbØ(]Vs¼OiÈZà ‡÷»|ö$Z¥–üQò^TœËuл+{(3™
+û†DƒÒ¼8ÁbL‡y&Áý’Э9´.$Â&Ю©^UHÞ·è©r žÊsžj2lÄR'Õ|àÇö9]B¸n¥½W!3çxFD5²Õ‰pÃ4gd,"ªÈAS1¿Æ\ËŒ{»/Ìü
+¸âh±æëByQµˆ‘çLÑŒ `r%¨—O%$š8JÎçÀDF#˜ƒqBØ lçÆ0,ä
+°G3\E‚Õh‘ikg\J›ç yEÓü9Äò›
+ä@m§ã ”A+©{ÀT÷ù„!Œ€
+‹-©H6+¡ÀDkÒ{%Ft.h#ŽÙ®Æ†9¯
+—ÌuÖPT
+DUD mÏTsá‘?w¦ŒjƒDâ-r fcmIHÐa€8·sRS/iïtó“5ž º(Bªx¦3)!Œ:v(‘ª >M–·ë]d(wv^U0
+ÒÜÄÖ쪥B£ù. Pm?¡övº`¦û¬3<:f-iEyÀØNCܳ " % b£Ðks–‚œ€•%ÿSO* ÀšµëÚ½„xª*è^êùZçdN
+Gv|Â{Ъ
+ZîL£É*/IQO%²L†Ñ¢ÆCæ˜bZú®ë–7t!˜|Ò'‹'q5ý=Š· %Z6¨^©¦X)I  *Â1B ›96&ÝBêŒVCt`ÿ?€®Ô í 5ðªÀ>0$ĸêÇ H"–YˆuÈá[̯[Ì Eÿòdð›¸FAÔ d¥¸(oJò¢ì@‘³TÐd\’âùþEÐ[ºõ©A¥Ó@M~ºø{Ð¥ïé~„=“Cn áîï‡ H4É/`"óÇCˆ@K@ó<„4æšAb²MäAHfQFN‹x¡Ü€¿Â÷“ÕkœÃò/ÀVé~¸:K7a^åD:à›¹B¤jP$³.©Àr&ß´ÐeŸÃøŸ¤qŠsäKY=€:Ù!L5*ò·p¯nA¼lF&¶'iÑ ¥°ž”xu=۳Ș—$ŠCH$~#Æ£$ ¸œ\/!ïÉJfW±ã¤d½ ÙÞ|¬$÷¤ЪC'¸¡z¹¯gjRhEú4ž •Æ]Ïÿð!rZµˆ¤ÂSÙYE@‚\)c_µØ5x= nAxHy Í’—ú½ƒ:y ´¢’ ` 3Yv£¸W—YD@%I2PÍÝ/"–÷ ¯]\– ÚçÙð=ajçœ÷A¦lê5f $æil+k7PÛm‡
+DFõ¨‹ì`Ÿç6ª¥lƒO°ä$ò!‰5ß<Íë:½ÁR³#e3ÛÃ{¸¢ A"¿õGâ¡\°p‘' Þ‘Û(²Ókš²$ã§0¤Å+P3U‚´-Sª‡pQ~֥㖪hÿŠ+¦;D±.@Í^&B¨“(ÈŠð5e`$JñÞ¤XÐsPª‡$ù>f-£e#•i5p)-Ï(0Ž
+í
+錢-Û ÌXH„Ý~K÷ „#Äár–fj“+•]ˆ®2XýÇA/é~ÿäN~õ÷³¾“‘‹§„ö­ˆ;ùÇ÷˜_טïK¦˜.KŠ3ùuԟƼçzÚOb.Rf»"€ˆ]îL~t‘W·–| úýƒZ«#ùã/"Ó'˜–PÂlÓqUÀÃj26ÃçéÄ
+¯·ù¾tä3~ !ªûâÏ_Ø
+L¢NÞDt®V¶k›èúeåX¶Öø:©
+u!w´OòÝÎ"û^a¹%‚Ãåˆ0g6FJÛ/%a“¾+Çå3\”-à˜¶ãQÌZļ1SÎhìéž…KåQU&æ.qÛƒ„.óIŠ¯!˜Œå'%ü°=.“ÄLð;øËWM
+ìžÄLZ\ZõZòbhoEÐ:üiSŽï<ÝûÅQŠˆ–^_…‰çI * Où“ÒYH^™ÔBŠUœçŠ‰r3`E·É [O?ÊLÍ#/ðç’JÙÍp4Û$E­ç¨’äÓ
+Á!‡å¨•‹è'Ù¡è/Gç€$NA·âQzºMZõø¹„€N‡N†s ?6\3u¿_‹<‘ ²Wà^%ÛÒmØ9-vh=•„2ãvAÖÐËgL™›t—®®ó"ñ Ö"¬"zÝBÈů‹?aUÎC`žEÒ¶¤¾; äøž –âMø'†+`ü®”ôÚ=!|'\0O ñ„¬ÈØ2Þ™Å(^ú€$iæ›:SÀBB«˜”tXßÜ‘¦@ÈH@áøEçtŒ¿|"D²*'à8Hû.e…àÖD ˆÁʇõŸ¤á©èó]QÅóK&u!®³`]Ò Yh¾+ÁÒ³Q¹ETQ'bmÔ´Ÿ•bnÐ<“9¸Ù챈c´S‘É3|ï$QjaúsÁ 0Mx#ú¤*žÍMù*Æ´ðgÜ`^}Æ»i¡¨ãKæ‚Á§¨r¯?$
+z<cDb¨8PAdZàX\²%/'Aʽª8¡up ‹j©:qu²
+­¶`Qæ†7(,qT@u;I¢g¤­¾p(H?OúVòñãïù矈Ue•°d ü6fø
+‚WÖåóÏÞq:€P=n!îX,f…ÇËÁî¦F[^Â*¢M(wmQÂÂp-öÉYYE¸ÁÀ
+ùLþ£ƒ²x¹Y gÔÀ•¤Ï
+ ëéÙ¼†Â'3${ËÞM+{Jß‘ËðL3Œ
+zš²û,û.Ë>3äœ9J†Ó+6þ¬'—@“Òv¦¸Ã¬—eäoÅIü sc†Ä‹8•.‚é¦|DI–ãÁ ¦ð°Ø+ˆ]Ÿå/³3¡"ßWçø
+“Pc¹-ƒA¸Òmá¿ø"ØF Éo®YSœ„±«¾”À[°¢¼[¾Š %cu¸î]lpiBÄméò×ÿ³ˆ/“¬ÛUKìÙÄŽè枧‡¨S ²œ2ƈP9Ÿé}&Q¿á<È S"Øf²ÎÅÃ:œa”¤ ¢_G<æÖ4æVÞ@¤ ­SŒSÚHŒ[ †c(®ÖbV<®¶Ø3Ÿ–üÞÇÈ7¨&Î)Õ-û?Éù*0
+¡8
+™P“ËÞ2#<î½áþC|Ç>ú2,)S5’W—÷ºvOnñ㺛ccS³‰qa™>ï”òTd%LšÜ"'üøN Bp–ÅTdÿjK”`üyLSZ< ±ÓÚö)âácP’‹>¹·˜Db;£¤ÉXAÿ{D ²À¯pC¹\Jü¨j°$Šzç;˜WK†=ºÌA`]<Å«êPÎ&ØÅ«Û¡„6(›4势®ûPÿPÊt á dy PI7ÚÎò¢áÉŽ‚–hé^¡xÈ…²MAßúƒpŠ.Åþâ+–M™³}Ĉ¶ÛËÃ\(Ë䕘JñxaÛ\ÏK8G
+^ïqT“,\¡jºè{½Q“$aûU9r1¸ƒÅ£ —íΣîíØT.þ!Û›ÇËJ2¢xF}óˆ4[Ç>6³š°Æ“ÑÀ9l#OÅL~;ÕF¶Fd gQà~:µRÛ\f¯xê”âgýR@DHâ·Y÷šaAF»&ÕÞlñ)ëê”±Œš7S};J"Ô5õ#Ä¡Ú¡_ yàxç>všÚRi¤k°´ñ`-ôy8­3î0‡jò\ã0î9Lnò¢9­"„1ËuèŽ<é"TµÃH“ú5Å1X·Á¤B†ˆ†jN]\Ë.JÁ¥vDÛ¬±©@›òÊoЖ2K¿9òŽÃ¨‡a¨eô{ŒE ø0³2“ßD0„BK‚up¢—¸AŒ8l+oVm1•”Ä"BsjÇÎ<Ap ú÷ÚG2!êŸmÆFB‡$[¥Bø‹0´inìÞ,6-¯ñú"±4 5úyN$è%…KÔUÖ Sªht\.$_£ög ^Z §az¯žäÞÔÖô'Jglå~H*ÐpL<_]Ù-·©å}ù|¡Bp¼U}Ä3ÆPú&ZEå‡*Ý+˜NIô%ÖÊ\Æ ó‚×ÔÀP
+ÝCÐð‰×£iU”á[½Ž¶äITš0•cÔ«‰¡joŠó_¿ýã#}Ñú"—þ™¾xl '¾e …~?Óç¿?˜!¾è]¤‹s7ñ1pF"‡ë?ÿø°ÛRì ¸H²•{Ð÷)¨2ÆW›Þd 5I¾o÷ôóäLß\1}þ퟿ý‡{ò2v3F: ˜¾Å R}·5qS€ÚEJyJ¤hë]9ëeHধ ‘¢®¥ô£Ñß-¶D¤âxÆÓ 2P= ´tlŸk}Ÿ¶{„ 7¡Úô ‚ÃCÇÓ ×'øyòNzýüùwB›¬ÓE©qß/yˆ™±§lOÊ,ªæ’a9A
+!w£T5eÒ%à¥jr´z”xŽ.Põô¡ŽÅ¤N“(š:•„í1(Üžtê¸m™}nøµEÇ¢ºÔPÝBùdV^z¬R5™"2ˆeìT7Ó!NSm6PLÒ·üN|Ág*©5BЋœq\ÒBÊBÄ®ÙC8­ÆWt§—تèéaÞ$x´ ξ'šÊ 3}‰íVP¼ÞB¥7â˜ÄÈÇöA‘3Z Éà~þÀ\Š•÷=æçMÌjhžø´“Í¿8.™Å õªÁŠ¢f¨wê”"éË3Ù¿P³:ŠÆ…«àp ä<‚R°Ém×û2¸på!D·e’wH½Å"Ìd@Ûí;Ñ 4hoûª`DsåÍ­*ŸRšSMP¨©D¸z·ˆÒ°¥m
+pEh_]œ–‰0E½×êQyYL=³¼}'ê¥mjz¬S7=h¸ßM½‰HQôž
+jEo2«ˆ ’Ž~²v =D‚¼ÉŠj\CÓ¦¨cD¿é§¥Å*ôem³
+ ®:¦‘Gt­[?TÄ™vÆÔèF« Œm9Bª’º‡¬‰ì,Y¢@Å “6†‡L²Y¬R‡çç¥5»àa×0KäfëèVƒT¹–‡Tù"¤ÈüÙ-¤® ±t°5G
+5U€b^[Uª½3£e
+ˆ crAHk,C›m݈çž*‰ú¢Iv7Ñ™”$ éE¹.…Ý¡(ÔJÄ”‹X1™p «.è˜:Ò?] æ/ƒ ÜݵVÀ‡ÑJ{-F¤ÐÄ*ê¯#Ac‡_œ V©rÉT]G¡_ ³ðR'ÍÇ I.[yÎÑ (éöCˆ·ºr?
++È•´Õ“ YgÙf!ÙEÙÌ‘lª€(2nï^`"+“̼ûQ'‡fN&Ú¬ÿé‰KQd¤ÕC@o* {½¤T©ÎÚ|+f:f&%8ÅVªVÇ«¯ÓMúI×nÙ[©•ómÉoBTçDƒÊ–yÞ1ˆÇ‡È ®òíÌŠ{ Æ!èçM5Ü„'ÙßùæÁ›Ñ‰
+`¦Ùz0‹è}ãìèm-¡ÀÚ: ÈÁH6C#“£ó·RìÝ@j˜av·•pmé%׬AP)|“—xÃC˜uȹ${\C3±á!sÇ:䟄N>X¼ñú`eJ…•‹‡ðÔ¾¼r,7¥ BRBFINˆqí Ü$ª|uÁ[6õ… ßiARÜ#ر H†q{_Ü›ÂQå»í&Œ^¢eÔ4Ï«PG4"°wدˆ ð€«,ïÝ<5Õñ+öÁm ?L°Î +º€Ëï° Êh[ÃzƒW‰.³èN±•€ò@495àÕ‚¢ˆ‹ì³š±“z1w_ÅÊs=õ,FÍqΓVîáJÑĸº˜f(¿V•¼—*µJÍWè”6¼Þ†‹Î
+ARÍ™ÒȬõ<è¾›z¤
+€)žö,ä0éJ3ïŒ0ëÿºMº·g| úyðÖtQCLKœS-un¡)'dgC:”’CÐýP|Ä\âZu>zÙîçÉ™üè·µîÅ$ü£Å8å²ú1w‡˜C¨PgÍIÈëã ûn·Ë=‰4l”:i¯ôÍÄüéfy$[IG–ú¼MÊ/A?^ÛsR2f[8u;êSÐé-3,
+”áSI~tzÉÙ²#
+h=:<Ô}»‡A•¡Á)0ºŸ7AL`AÇãá á™@: åš ²¸‹´ÐeÞ1iªÉ š}å8À€¤í
+Á¨GÍÝC4 8L$šBøoän#Ä„O°ŽF\C!äŸnÀƒ
+_‹WeŠÇ‚€âì})2€ÀC1ÁÕÙ-„/RNçrˆÐN]Ÿ…ì{
+RÈ_ óÝxbñ>N½†…ðÝ0ü…e#d*ºŽ§­ÎŒNVœm¯+hcð#ó<B±É¶S¹]:œÅ5FðˆŠˆêæz½¿jðïÇuB™‘g«ÏÓN›8‚”Žn[%xŽ ¿„S-Uç&£%’ÀÓRKÓ +Bˆ()ÚVâ‰Á´1ø z­Ã.YÙØ:ƒmø=\Ö²„T#£oY’£Í¡Ú:„øV¶#"irã7ë6iU¸9ëáÈ
+ɤ(‘¼ô§'º'iÚX3v‚Ë0^ÕHD½
+hBáF¿’’ŠŸò Td±
+ÖàØMRQ;¹6Ÿ“´ìäÚ|ÆV\Á?*ý#I?¦L|;3ËÊÂpMÚíOã$ M™pýŒc(£‚…ÛÓe" ÚЯ´e+¨¶t£†ƒâß÷ÝômÅ^AH¸’à*bz‡p %ŽDѨé dîJÅif¼™t×Ôbv=gyųyFF4–•0YZ0„vJ³¸à¦äU,d0 M,¾œ6é@ÉCh&_‚ ñ³aêéC´ZDÓ²â¨a†€q1x˜Æ.ÇâÙgø¦nX“GÞ€UYuƒ +UbåS_ŒÌš ð€’â \FÖ4<Jƒ6$:‡mÜ~a¤¹vY ºÍˆPjÖbÍñ!žÃzâþ²qï;èb½ûEjJ² 5}HMï ™ºp'‰yá;ˆ™¬T­Ã€^!˜VØrV¢€¼ à ¤!éâ8l×õ;ÙF¶‘á¾Ä$w›‡EÞx‡ýá¨ùE·a‰sþ¶™ed Ž¼c5˜~v•è/R=GÅ…xêºúxÕ5COq,î‡ï ‰ DÅÆöOïbê£6ñ qPÞ÷¨xUf*¢õ÷™lHQ”÷ÂVSÁTö˜#–â‚B!pØ´~úŽ–­à²ÊþR,&ù„H‘ùû¸ôÜ [ƒ[[áXh.ý¦6}”‚éC2ÔñÌsІ<@W9ß¿‚Þ¬9ù”²ëQiƒˆbžNÊo©JD¸}y'¡a¬{2ÆY‚BÏq¼þ¦î&’ŠæzÅïM-xTAsÕjšQ˜Q0 x‰}h”¬A(‚zŽÿ¤‹xeKÎ]t}†6iW@PÕÅÌâ†}¬&i—Õ¨Ðôr$ŽûõvÄβÐi•ÀF£|Ù…
+ïÄõ(ùqŸ]šÂgóÁCã¹CáñçeB[³<õx܇'á7µeËj†å;šÅa~'tJR؉oóñ“ªj¡|4æ $Hç\º£V· E2Æ "5È ?ñ+£Tón
+Ÿp+1¨»*ès&,&Ú£Š ãÃ$RûŒHH
+ªù5J,úÞ ?#ÜM©ðñ“2Ó†þ#y_¿3¾¶ÔtàÃÚqŠ/D¤²äe!ŸØäVþ*nÅþ³¬r©×LuQ±}§s4öqaÐ] °2®•2ÌÊjªS;º «Ãµ5ŽÂÏ@‹¸ó}¶ÂÖ$kfz±ï°[˜ ô³ù¤n xV0…4ü( „ìNÏ׆1œè8ƒ…*qÓÕa رÄwH¥¹Û®-ÿ 7ãÑ0µ·
+cå\qÕææa
+mÜKö¢¯È¨ 
+ršÓ ,gÚP]¯giè[•€±Œ5b¯
+›ÚÖcRŸ7 ˆž@*úü„§c´qò‚ȔⱨP Ö4ÙŒUyç $½ZÚ}ƒþ ë°Ö8–N“q&TÅm­á¨?¬4¶„)€áçy•Ä•c‹Oy
+5™2œˆÐ8îõÙ/
+‚ Ð
+æv3ø=¯øh¤JŽÎÆÐ?bë"`½„ÉE´²b Í!ê£Ìƒæ[Ž0ˆ8G©Euˆf@f˜´K‘ôëÆ\òöK} ‚à]Û#amÌ<Äeà
+îéßa"h:™åˆèS΂—)}®G¹'®¿ï†Û@kWŒ
+IAõeIÿS«½ÆÒ2MWëìâå“Þªw=–‘”9Y³¦‘Œvf c,ÇäíäÊÈ2ÿãqŸoæóF`¼‹ÈÅ°2ËÌVSöyHù©~‡N7§ÊJE#Ђ¤HðÊʯKÜ>™ŽÁNëþ>8l4„Ásb… ôhù£H4²U¼kÆZ±àJ¨bOït¢@GaJ¾¬ƒ+[IA™Â’û -”Ö›FÜÓ:Î
+ôá;/‚?Í6q;v±­«oxÉ{~zÆà0…ò=1Y>3-h­S>ú¸¹´É½^Üе|ÿc™ä¬ tÞ»É û4¥¿
+sÕ/ˆ¿l,DÞ„+˜`^0Bä%ɦ|ÙŒˆ!äR
+¬@©ÁçÂtfÕ÷»ú9P0€ DêSÊ×ä |>×Tød£&s×Õ‹.æ§H/'-4MÊ& 9E‰í†!Své·ÙÜ_Ä‘i.ÛyE AÞÀTò¿LgR
+ÔÃáÊ”Ò!˜zWC ãàIC©ˆD#Íüq7G;N™yÞ¸:Ø)ç8T 3Í 23y–iÒpHìbÞ'_âJù•iÙ§8³¦,¤®Hé¿ÍÚ{u2dIÒ¸*³¹c.÷‚x(èpÞ~Aø\Òø^ˆ«{Ÿ„ÁÄ×%Cës)eMªç:Wé3cÊ"9+Ú3´Ö#A|‡øI¯‹tùNµ%/ÀÊ÷'q‘´±\¥›ñ¯
+H‰Œ—KŽc·DWÐ{¨ <™L~rÜz<*ïúN¼….é
+(À@[ªÉüEDšYµO«%>þùå9e4‹’½Ì¬ÿ‹j|sÖècûðþX³Œšuô©¥‹QÛÌ™½Õ^{/£¯SÊ#ÇL¯5jº¯«ÆcŒž5ûp/¨Wµ­Å:g”ÚZz´Z}Cæðnµe”دéÑܽÎbíœ2yN™anuœ«ÚlÙûô°Ù6hx›}”ŒcÓÂF‹é™å@zpYc4N^ÓjŽjÒÈŠ×Ösƹ)H•ìÁ;7&FÖÉû¨s$·yw·´ !Ù lWÅPy݆þ·xF¶+® 8­Ï rªG²œôí ”îÒr”ˆó3|ÌÚÞ@ŠÕ6ëh×UßßãóÁ5æÔ2²ô¿ý ¬>rZiNÖÂU beNoÅÉÓÇ· þ -‚ŒqþœEš¥«¨YVzºîó'oÚO9KuËš›$õò®ÄÔÚ‹€7˜¿o1FÆÿ2ü1ŒÖc¢¼ŽúcÐëm/ÁýóZ;
+=ÞFé‘n?1|ÎÜñdžßßåèóÙVMìã/P÷·Ì“­ÎËÑ v²˜¶
+s²B³ôÊ´NÍ.êI<­ù0ù®kÑ2dÆÆ‹#@Œ9'à “Á|ÿ¬›`'Žà;ŽÚ ðŒ3+
+2¦2”ÐV=çh&ÅW´ÅØ«â1’{‰Ú­0½$¼ž›z[ÙnÔmcjÌN
+i²ó^‘šqHy NZøÙPÇ,D™c(õªj/S‹šç"J¤ÇdãŸòJöÒIF[çð{8Äðõ”’Fk–î;j‡ü³X¬Ä d_eP üXtÔ›sÊ4Ø”$ׯ«\,<mš²7ó‘–•äu¿ C}Ói\Œ/EI+f'Ç4 J6¤u3£7cæxBÈl•ÇчuCè
+ví§ö»„¨~õê«B‚ êÄ)ŒSZ‹¸ø¡M7æ–n~ED¯NüJŽ=üß[+0½ÝЃt]†&‘ù2ý\ôÄ2Ê/…°yâªge¿¡<fb"$ôÔ¹é™9Õ¸²ÙZ÷{þmÂøUÖúòÇCùåP>&‹Ÿ+¸5,Õá±ÑØœý0>lJ;ÊÎÕùŠYÓ-äªYn排wâ“õQO _m;5œQNË™§E?(8CÚø€Ôö*é¼HBmÏ8§øTÃZN5\,ˆBj(<=u ØtNýb,Ùn®iõØa˜L„ô‡Ÿ¯c
+Z3̦*½!Œö“Þ·6|Ðy­"ÚÖ‚ÌcÂFû*˜%›È‰Žó¹AðŽIÁxt®s°YQñ‰íøX“—ßDP´bÙ€/í²:¼dR;Iï ¤‹`ÝD…'‚¼A”=a¡HÙš‘Y‚7¨R'ÒÇÖïrº3®Ô_Ï¡´j_fkË‚IcÖ®kÖçrÇÍš¨€$}G>䔡¾çsÕ9™´ýÉ Õ‚/v3㦆øέÔÈáI F§ô~ZŒB{"År'9 c~ØΟp”U!¼¾÷XCè³Zçy1Ÿ 3ŸLÄæ‚N=¹
+ñsÎîò6–9Û¬C/’-Øá
+_ö¤xh•–Õ(´ˆŒµqìsXµš¦¥Û¶¶X4Ç ›m«@›Bwc“¾ËÇÍ1<”9àšÈÓëÔ ‹k[<+÷ÕsHHó2껆mB^ê¹ —ìüHVù¬y¬r‡xã±E¨@+XfH¡JÇÐbån¤ŒâêTBW´KHŒË„–¸ÊÉ‚@ ÚØs¤–ºéX%
+Gœô;3»!2¤ø=:ó2ˆ+þÁHƹŠFG
+>eYö)°¬°»]K™Ñøü„†Úµáð€Œ~Ö…Â|h01/—]À4jäI׺i@š|Àìã‰vo9œËó©y ¨#]EÓÇßØ—GÀPçA›@ê—by²¹cµ FÕ—rÙ1ûì ´ òFÐ @p‘ÌøçÐBÆëj«gÈgêJI°ºýÍ!¤¾ó:&É,:%ÅK›å.HÔ@RÎs)|ÀTN»ßª¸ræÖò˜}’O6ÏsC9xA¿ã£›ìå1²åÁ¸@ ´BCô}•Xƒ0ÑɆ»”(7Ú¬RãŽ0˜Ìn^’¹ I;ã±Â±M™™­¼|æK¬âµ¨è«Ëï–v+u@Lk‡8ËÇÅøOVþ;æó†,Ñœ*p¿ÝxMRo‡xDZ
+7u¬O²•_ªÊvËÎèWàÄ¥}êk?¡näÆ{\¾•—Žeït˜«ØÍʵr%åÅSIâ€d¨ØTÓ®-nä7¸Ý<•ÂéÐùl3ËXßCjaÂP9±sÕ$l…@ëé>$´p†íä­Ô8‰*„Á™À*Ïœˆ ¹fNQÄkZ¾M®ª‰Uì…oC6>o@Ÿ$ši<´\¡ãµØU4S>×e”Ž —Ò]4ñ”Að0©é½¦I’S 1};ôWSp~PCo«Iï rt“þC4ó $Ð{R1ä¯Ð¿ƒ$Ï%‹ÔÛ¤uŸo@ÞµiÈ™øŽ ‡>–Šû%ó¡4©Y?ŒBJ
+¬À´+¤?¿ýûË>þBªª¬^“ᩱö29
+ÂèšuØöã¿7 *»¢E±Íÿ3^æH–7]Aí¡l9¦‚2ÛÕ
+’Å6µ +Äÿò[UŸù¸¸Ca·ÆfRŒy¬°SZOow™^2’΄‡k‹¸¶h•  “NŠÈ<xsh¦ÅU<©Úº¬Ú9DT 2Ûœã*8…@dô#+!iÔJ÷‡ÁK%(\éîðm…7H±`ÅYN‘~ãò¿lçÀÑ‹gsû±J8%‘Òá¯2‹^°§iõ»›Ró%À<‰`5H»â–ßÔ´F Ñwãª~h,H…P"éAvT0ž^0ˆKûù,ºD }JOÅÑÕS$wÅÒâ¯üs&‰u‰êK 㫇"zX¼ëXièvµð´ø4¢-n~ä3NEYþƒM oœùf9m£Ü'¸d|›„~ˆCÖ­ä¤Â3ÀˆŽ0  I"hÿ!K~øÓŠ€È q¨aЊÒ~þfÁ ›uà3‰JÇÈTuT¡³ˆº)áó€öbî n@ÀEf|ìpíÜ·¾°Á¤Òl#9•TdW æ©I%¬)Ÿ-ÍÌV„™z„Ãß¡PìÄèq•ì=tJM
+èòZß´,ËPKÊŠÖŽäP~±zé^“3½w:cÁ"gsÞ~_Œé&Lçú çø¡!$ä£×<X´ö~SÂ…].#sž›^‹ [Ü%Ï`ÓýR¥?aw0ž£o>ª™`µ‰aÜ“5à­<^ö%FA‹Øƒl2-5™>UA B–+Ry¬ha¢¸8‡‚ë¼Ä”ŠªI5ù¯(êˆ
+˜L3ûUž
+¶x¨<Q:8dÁEË1†%‘¥YbÇ(™Âuн}¯K…- |>éì{R³y?XЂƒG_¶µ_®ÔÅúò°?oEâ^Û==ã„%Ê ÈDfÙòï;eË„õKV?+ƒt[.‘˜¨™§!>ú*¦ã£QdáÅÉüà%ø´iÇ ™$®‚‚ †b"õ +)%îêJ‚¢M3q“Üảñ±¨&£ïÓ%™ƒã°–=®bz>¡zI2_‡yC^£9¤ˆ?õ#mD ¢ƒ â±i ‹5.ÃukŠ–¶ì߈Q´Ç}ÜGFJ:ðFp ½*m èýqƒÇ¯
+ ÏGã¬MºÀt¦®bF‰%E,ò¾dýXZç$ÅEÉþÄY#·”X·ÌŸ/.Ö1ÅÁ 
+¡mŒ Í\2/°« ,Ú'¤À2ú"õ@<äc— ‡KIêó„ |ø”:}’?KU™aè1« ¦B±¨`êÓó'?‰6¼7?íB
+QGy x6Xš\Ìפmâe^‰˜õq•ck›šf4ïpiˆ!£'¥ãäÌðÄeä'Ñqj©MŠm :È!Î8«‡Rðï%t‹5„LÐ s¥Vb¬±üë Pqvµ› ,æ„ïY go‘7 ÃÊ­h ‘€ˆÄ®a#oú¨îe,Úàtäÿh‰ÚEgxk€¢€½!_Â=¼…FU:ÑQ¶g‡X€ÀJŒ"J† Nê²RÁðr‘
+;îÂD6Í
+s†gíñÿBW¯÷\¼Ïøû•á÷W´µ‰à%ÆIße à¦=.EV¤Ñ]ùáïs
+Éв?]!d¥Å(aºmœ %žNƒÛ™]má†q!`Ú]Û‰€õ(&”˜Ï(Á‚ØËSw"ƒeNE${)ñ«8VuäœSH¨d—•[Xúð¯Â\s&¡
+½sÉø*Û8—³Ý<ãî/ýåºkÜ}~6q£Š~HôæõñXª5h=ÊÄuošˆ9cA0ÔK ‹"±8oåp“(
+Ad.“M´P Û…­³’²Tf¯ƒŒ"fMʬ3®jâ¾ÍÆ+7C?€iuû #èkùÀÇ`¶09¼‰Q{‰Ub9â‚vü/æj ©\ß·¥‘‡–‘ûhI=Œ^øe÷ŠÎ_«¢ç—¼ç^—Ô*4y}F‡¸ªœij£‡‚ÏLýÄX6r“+°Q ¼Óî³Å1¢fV†ªÝoÖV%ŠFX VgÞ­­øM[ iO7>G;¼åú˜ó¥ÈJª\¡oÕü®„Éfþc]JÜÔ‹ÞSÐÊ»sÌñ1Ž§#œ°PnÁÄ|H—¼ƒ,`Òºâ&Í°QVv"È¿Zh NÕoš–QðëÄØÎ ¶LëÞž^ljÊ
+·søÇÌÈ
+S±ÐmOñOé1Š/ÂxSe±ÉL\ƒ#щqÏ0vÄ«)¡£ Rà½Æ$ Â(Æ€Ÿæ^«™™Bb)d[©ð$ÂRaîԽѩ+»“êh6/7ë0ç7h·ÔÍœþˆr¬‚„¢
+^éqñ$¹,/ð{U o€NB#*×äÐÚÝ3@‡ Ûeb²ŠË´ Í—y&81e·Þ墟”t{izß®™Vä…ÔT®Œ(-98”ÜU¬È5*æ4•<‰Fgy¤¸çÎ}K¼YŸ‡±×Š @p¶4Bgz~Y=¢óGŒ%k§qökz`J˜w'YɨǷ B‘ÝØ;ú<uz(5¦È4×_€Ž¢YÛ}
+k»@—Aµûý`×ߨwÃáêkÓ?]ö÷
+¤SÓÏÈçÕ‡Q“ìd¥ãÜ ÒE€d0éžmK»Çò/]ëDÄõ©Ç°^çÏ“r‰à„Ħ/+v3@—öe¾ñ§ Ç<+¿•Ñ‰%Gt…Û>g‚S ,=/*§¹U›Í™@ÓĆÑ/Ÿ¨Ð‡›+ ©Âþ^㇑dêÑÞ5[)+Ô^n$Ç“9Å@™À¢PP¾BÀìŽIçÁu¼@®dv•#çà8øýf!Œ­¦é×ijׄâ<Ú@àNðB CÓBÐY2û|)¬ÎCƹR®ê÷ ”Pìœfgè!ÉØ“´Çgü†#õ`6!O,çËt1)ew>…ùÇùU¬
+•PB5 ³ž dÏÃMWTÜ5’« ʤI•yà‰ä⢀ëR’°È%¡ùµ]„p8“yœ£Gð(NÓHHÂfùŽ
+v@pwI¤¥i†¯Á΄\ƒ:ƒ :š( ¹¤‘›ì€PÏù8e;Ö-}‰uªBbKôªy+Žu?S:Œ&QОÝZFýÎuâ ¥h„:
+v¦S͹)ãÂþ±Y™NÜÝÕ!¢Ì=1ïYLCÞØ(ë,Vê›;á„|äÑ
+˜Dä®Z‰N׊r|°r.V\û€GG¢ „R!§æëÌ\Š&WÙV5
+ ±á•l»'Ó¥Ùرv*ŒÓFŸÙ±7;_ÒvU±M/o€0IúèxØxw&õ óŸÕÑ:Óóçø߶xÜš ‡9­ß7 â°ßôŸjÉÀ(C%• K-ÃäKPª¾ EHoO¢GÜ Ö5æI›€Øë€4Ä=‰z¸,g€öu2S†Ä¡÷1›“PL«÷Ö­)ÓV»! Â*Þ™£¤zQöqŸØ)³-Ò|!z¿$0ëR—IqHà BKxfˆ|TÌÂ$ zOÓ„±—ŒyeÀìºhÜ1ñPyT´wBãa{O8X槡ÐkÌŒˆÿx=±@X‚RT £ƒçN^©ŽwÑʦ÷a]‹>Sn Ȭ& B« ¬O7ë\ ~œælãRgs¶ññÄäÏJýþdd¾^¶ÏCÔ”œÅ'ù\îû’h9f|ð87ö°tWãâ|üCñUÑdn¼O›U½½@ïÞ‡bˆ#xGþ1M‹Q÷ÓüÐ?pC"%bCƒ½Í\hunPJYŠ±@ÿénn; $Þ.e@–ýÁS5‘À&þœ‚¬<—}ê`9âÒè0<iA˜ö/ë}}`ˆ ÛDˆ‰®ÀÅj›t)ûóDówHÕ’©Óe»Øƒ ÛP7"Œtv^û‚$³ÆË$T_ôb~XoLœã9*ä¸Å»«¹¥ëH¸(#˜zzå²8™"Ä3æ›epW.Y!éuàyp µí¾ájS€ë¯ãf*>Žâæd!(ÿQ^6¹‘åF>îàõ,þ3¹4´ÕvNÐðNZúþþ‚?BW½|îÕ!>2322Bã{IÛ×°ÁØ ‘-cƒRq%Û‚¢¶™ØDwËúÒó@QrŒ[a’mêÿO¦f8Ç&»=â…‡÷ví÷!£
+ 8&ÛL†4Œ¡ŒE @ TLK'*r›HÅètdÊAàÇ)HŸ­÷f&v˜Lè º2æÏ ÜÊ—ÙYæŸcŒ=ìr³õAÆÂhóQÞ ÁŽWåHhxä]]}×^Ó§È[SטÀ4âÍ9†Ëb›ÂÉXÝÛ %OCÝ5¯^àR¿‚(W#Üs’ /òϯsÒ–\„"QÄ*%[x U!aÞAˆ1I81²RŸnÖ]­—–ÕfÕ2ÚÇξ
+rêSÙ™¤YîÌLÜ„%tÍAðŸ$Ù§¬ˆ’µ¢â¡õï^õ{‚Xb,î†_ªæ€|£‹ã +6vEDx;!ü‰`Z‡³ò±Qd&x6E#ÎúŒò|»ýCš&3ÅþhàbP
+t`óš~TÌYB?ú‚XàL!{A¸96‹µÏ
+ñ‰ÍNd¢5ÍF@f ©‡)òØ7¨ '»‚’ÒŒ€T;„0EE~5LEÉ0CrØéç6õ) 4òâÎå˜Ã:•8‘ÆÎ]øª‰ìÍ–*.%î)/ЪE¹Áím”\­ËM×ÒÛ™r)a.‹üß„‰Ò£NdŠè/! ³]Rà
+ÿ-“S^;@+‹Aãa'râeø Òµä½Ið™Fäl?ËôèÁ qƒë]Ko+ÛJ\$ðOJúqVrôÒÁXt\1mýÂgçJd«p2ÕÅéæ¥\Pt£â¥: A²x"ÛOÍ÷„¡¹Ha(koúL·F=4fl¡
+"ÓV½1Pƒè‚ܧ•äâ;Ñ ¯3³º»QW|¥è+U Í8»Õ¸ Ájr¢$8âÍ=9-¾!6¢YèæçSq§Öôزێ/ÀLSZpûS8k
+Œ_ÏÇ?æ†`ýcuû, h(ÉeãdžbYiANp ²ÔºsˆŠŽig0ÓÚƒQä쳜îæû…QÅGÉ0ôœCq“z1h¼­9 ¯WX¯ùëofäßÿyûë¿oEZCØöŠ¶i¯W
+ +LÎ9)*ù°IcðãM‘7`d¤zºQWŠƒÏ”åX¢ M­Èÿà¤xD™ÊVÖ‚ÍK¹»Ü<Dõ,AÈ\Pi#.Hc(P“ò/fH–€ÕÏ–®ÝAüz¦Ééà¢KÿæÌ%–…ܪÞåQøiBT¿&ʧŸSŠð ˜üã͵w†‘Ž"1hø*üV êZ–Ô
+Z\È4 Û»:ký8zœö_ Š ÏÓÓÉ4Ê•QJµÏúô–Îg¦ò¤:‡b¸Y¡4ôõ
+í5(ú ºÂC;FáÑnþÿætHÖS•UçV«k¬ë1šŽR]3äV’Ø4FáiH?ž‹ê2kqkê‚ c°zAäz9¥+§å"xrgæe2특¨ ‹Cþ“¦hI„þ2èZn>×pÿ¦F˜nA: u4’Ws××aò0úù=q©ˆ" ‰/)ÍfˆgÆ„ nâˆk`ƒ¾oÎiï þ”ÿ@4 Üÿ¸<\µíiÔPãd ÄþÐøó¹M(¯B+§µÊZÜŒ¤|ÌC[Ëï)¾°O¸@äZJ“çÞ1ƒ¡n§N¨BΤ }Bø;î mYDW'@‘ú„@CÊÍ9CjŽˆõP÷mFDq`ëL„­2OEû™nHfP:€lköÞ)$ª†tLvx ^Îì`Q/÷¡XZ,;sì¡ ZÖÌ A/ì‰\@,‹ÂÆ~:Õ‹réÖ6¥æÓWD3µyN€vk\~ü7!‹¿áíæù ²¾„U!1 J³›sY8ö„èörs™ÀW"þW3nE˜ÌJŽÄ¼˜³[œ+».%ö ­úõ
+•MGðߧkmòÅ}8ç}߀ô2¨®¬€aa=;H·R!žá›‡§AëêZm¸[VÄèžQÇ‚"„¤ëkǵõŽAV‰¶®À=§**rýb1—ì]¦âªŽÖ]]ý5'gàla2{wkî…:ø+†Ý²[aòЩ7ôÔù¯1€µ—‘×i`®WF|°¾XË}+ËóÓ+½ãopðµî§?W“å2_Vý±§>p¿Î¿ì›ÄíçÄŸ¯Ë9 Ó”ÕÝò³toCÙkfÿWF'ܽ
+²w-w¼DZQéRëȨÆí½Ü@`wˆò¿¶?õ‡ù\>I»Gšåè–bp²€äœå“® Ç)À_ÔÊrþ Ùü¼ùÜ ‰?>¥wlgœ|õ0xGB®”3J£\°1,œ¾-æÞñß²ô)øXÒó¼1D¢PeWÍ\:A¢BDj·1ìpªÕ§"0ÿ$0H$ë±é1èYõˆÍ&dÊë˸¤Y_b£ÑàZ°›sŠ)ÌÄÞœÛ0%P„¬”ƒjœJ?fÞ½^øãÍÑ»Öð J,³Ä܇rᔂrÞž\høü_vŸ~™/ (Î
+Û¯^ÜÌi¤>ƒñâQµùóÞGšÝ“‡ÚWƹJŠh±AÂÈO#Æx8ñ»õÑÓ¯ ‡¸KµYŠñ€.Sá}îÐÓ¤úŒiêñÙïøuÆ€¢ÔæùÈo@Ô²(Ï‘à ¬nîÄjã_öø]PqÕÊ‚˜L-ɨô½3DÔѨHÙõ†"LÔtîèËiV©lêÕÙ[ÝX¯Åeí ‚™ŠÌ·®ÓÿÇx¹$G’ã@ôu àŸkͲnQ[õý·óœ`äŒ"‘]jk«n+A pøGƸé/ì0¹aáY—?ûå•Ü–ña­×CÓ óPMËþ¬–µ¨Â´
+~È ¹ºR¥ëKôNÍy8ìו=Aá:n “Ør®tqîYe 5@Z‰<]4Îo-ÄË9ë!HË ß{bOÀCw°ì %Zž
+Ö>æ+“b›ÛP?™Ìþ­]Dd¥½4@DC¼°$z2̦½)Ýs^`"Ûã|Ýá[Ñ×›"ÆícwFòåcð>`ò8¶‚-zTÈ nÒ‘éHÕáKàØ1œHƒ]K³x%í@.ž!nT-ò”Ûž–Œ@c!øÏ
+Èyžb{ÀˆHÞ?P\ˆ²Õ¨H%>
+F-Z‘ø6Eª¼¹óÛGÁ\$nƒ=9Í!£ò›Ü ™£àg9^‚¥—àî¦DÍÉ»æ7õe?1oTÔUr,Ûó|-ª[þÏ*œ¶çU¡V¾"z¶†=K
+U:̈`Xö¤¶û«÷ZÄ0N(ò%zFíz9¨!­6˜¯Iî,ìŠ÷»ØPi˜ýv°†ÄÀær>ŒËOš4 pÂÁ¬ó©:4Î¥³³…€”æ¬âçðzHèœ9”½¿Êç'*kÿáƒèª ž±QõÌ£ÓèšÑ#«RZȺÃÞs Ñ«E¿ß!AFåºöТ¢,û:Þéc— \Cr–x •\:®[}‡W¤U–KB’!ì q2œêSñÊwr[ðõ7K˜`EëV™3<X) Bôuž„kGvÆ®€ &*&À\\ˆë#7áëù8žð.†Õ9žÞð]K–òáUÊ0˜mžÌ7¬Ÿ%€WÉ¿Î\ðHà†Y1Â2¸y ÿÿì[éü»
+7Æö ÚðkJ“ýç­­úËÓ–2ŽË]C«"Ôt$ŸÉ£ÎàV sðc@ê*«û)l<÷'ý,ŸÔ‹²+f1fÙ¾s
+$ä#%Ř^Îaº¸­Nˆ—_)â2+#õ]RøYÒÒ²çMˆKÓ¡ËûS5f!cèà<\Z€A(¢Û}ýÍ<‹OƒæœßÆí‚1/Qࣈst Ž%e°Î篨D6 Þ–…Ê›Áh!õÒ7®šƒ¢¯C˜¼‚Ã{qnÕß°äve•}“q€YR¹úåR±ë8Á¬ìét
+yÈ‹ˆ&íË:}e0Ä
+°ø@¯½/â¤*l•+œ|ãJoNvÀøliÉ’$BÄš¢!ÅÑÓÊî
+cm¼£JFØå
+à‚Ó,Ÿ/Ý{c|º& )Å~D¶¼Y¤«ô8žÔ­ÄAqŸxpÎ7÷Ûø{}Õ+Œï½ váÞá¿ï”<ƒàF8h¸4è›'šâëSe1WE ¾|íVóõƒý¾2àDs³2®» VREGÊè-ô¶/!¶£rShR­¢jƒê0Lk]Öw7@þŽ”t9læ=Ö[cEш}­oËÌÎ ±8ò,ÆûŠ3‘I’V:]9à›g™ã¡ 1u;þˆ½Eøvp]–íÍ9€0òŽ>‡bO¸1sxIÛë¯õÉÇ\â< ;Ï­¦AÑ-Ö~ýŠ>†¡að
+8ÃÇÉ’âà¸L:(i(¤=uà| íkòЊWÇÃ'é!v ‡ò«<˜B­t­­7%S à ν¾ôï@þ}Û¹­gâÀhÇ
+)<Š‘jâzhûò¤6*×’Q™VCå!¾Ðç çs΋b˜ªÀ/Í=G <ÀM‡Àa/ŸGpÎè%îo+ï¦.r9æé,|Äú
+‹°" <%Ð4÷­Ñ/–V†5/AmÔd½v…6{°å$ $¦ î=sº34™.ƒ•æEÈ‹ ñêœ`ÛoÌ^"·Å
+Ûn¢¹î$ÍŒ²Í"€]‚BK›d1Ê.QöDºâ¼NºŒ¢¿‘PÁ f6«tŸ˶‘÷Ø°=OŠGYƒŠ\zˇ–a‹´8{'¸H‚f?ç`ÒÁa3Lµo(‡T1?{ i)ÚqÉKr g?a¾vÎgƒ8h¢3.ƒjU’î%ˆ}k±µ«û@ÓÀ‚’³~= ‰fc¬oÎÙ¯¢±
+À+°²#l˜"Ý„Æ”Na!ÒÀTÔvÙ"¬oçüòîI ÒNa‘ÂìçÏ¢%}Ë][  ÙÎâÑî¯"önÛ –
+«Ê‰}M½P‰X¸|%Áªðr2]¼3ˆ!‚†<5éöàåáa~˽ÍxŸmbš¥Ç9ƒh©ØÀLæKGq/pšß¢
+Ò’üÏ*ÃÚÒDuùãÍù„ë(N6¹”‘ÊË ü˜^–“Ù 8kè¤$ì”)W:nŸ¸TÊ墠A´*LDhT™Él}\f¡B "Û%ŒbÙ*™Z›¥c#»BÞyžâÜ›ÏõÑPc–™=Æ>yÏ5­±ÿÔ°]¢}œƒÁ{uFêr¡Z ƒgÃT
+(¼†©'kBšÁJ+?íñ'Nq ~Áª­±Fèrg×[Œ„›"»ä†P²—ãæ5Jí•-Z—™ÉŒ‘Š—‚´¶]{Æð;1Nš{‚žâÒ× ˆ‡³;™lF ›÷iøq
+]Bàܧ\Hæ9É%§í'iR‹H+É=§?¡6}Lì]†AUD³õq÷& JmùwŽü^š>%`ÁÜòzomúxó@OmÿºÑ7Bl†ZG{wnL[bżãÉ}8# U‰GfP×ßëÇ®A½Ú¥‡›¿žºÐXþ½Lòô©ò âïÖqŽ’‚ÚRåÝÛ0¢>1eŽ”o^¥AG'‡ëUOÕ9×E%¨;bÆ n Ìñ#Àö§~ØÍi‘š, oç,XZg‰Xh ¡Û\aŒ a°à
+þø7|þÿ¼ýñßée
+ÎÝÀ¤ÉaÅ=`2T
+Ôo2,ËÃtOV©ÊR¤¯pwlÏR–‚ÎQƒÛ¯^3¢µ5V¶NºˆsaF¢EhÄ+YWöŠçÍsŒ™FeËh½ìí‹Hj–JÈx°™ìÈp úî±U¬ÃðA‚
+r
+–¿íë2ÆýYK®½˜÷&´ÁŽlœã˜f'0§lÒºãtœ–†is?¤©zÉoÎqDž Fº¼rÄËñê2R„NHcиª­o¢D:cT¾72FÉ°PÝ$L Rò
+ nâ·MJмžEî»ÄdÒÄssÁ]]¥á>ÕH«ÄhÿŒ™kÅŸŒŽG’‡ašCQ82ÿæŠ ”è
+¹o<£%3@òO3<Þæ7J_X¦Aûœ‹Ð•^"Ìëö I–jhÊx_»"'€C «8åÓæÞå2J~÷Ö‰N¡Õ87]¡íOýõ^jƒ‹²% 6†NQÃvþhЀ3²æp®ï :ä[ß 47Ódß/ù ,¦‡¶æ)ßþç^
+®8ù]ãJ)³´[ÅÌh«H|žC^-‘ŠòáÝÔ¥òÓzù6£oÈ™vÆ–‚óæRÿèØ@ïs/€žXÁ_®'Ðb˜ð08ÈüŠŽ8üµ@QnSn2yâ®r|“ŠÀùV\u' ±~Üǘv_–#¶‚Êñ¿®[òÎÇ5`¨Nµ¹çàÎDüˆ ä±”*FwM^ÌKÌŒ'J±8ã*oMòoèˆkÉ°câªW1|ÌNÑø†Kþò1¬lSR]NŸŠÖ.òiä°íÃÐEŒkDeªM’‚`)ݦœxÖÚÊ¥Pß«íêð]tfŸ¸
+”¤ºê›ŸÂjÖ…‰ü³BØŸÔ³”N™ªfÄ¥µDÍ•L$§n ô­kV bvдj):<e@«Š«RÁj6-,þ2p~|v4žM!|—Sµô¦á„èSƒ‰b©C ¦¤ÖÙ))Za—3W- ˜BŒ‘¨ºdŒ²³€½ªa?~xAïôöç!æ}×SH„3&^Bñ6ƪœ¥s H\Ñ_< Âx‘cò{ ,!ð>µŠ¬§;¢Š$H˜
+¸rÌóðø‰ˆL'd•³f•.ÁI¼ ¯âÇeÎÎquvà‘œ³{!ÿ­ÔïïÌŒÆ+ìñ‚1\¨Êt
+ÿù“JÕÅkÕ.eÀZI8ã´5zL³)(²Bš,v°+Çr÷ÅQ3
+†ÕÅîX®Š‘K5
+õJ§î§åªÃÔªMò[ýshf˜–n‡íæîTÁXø¦8,d],òʺ»§0ûâ×£²ú+ÂÈ¥î—w2œÉ:lò¨‚\ðsìÎ@”˜bFI$l!Ø
+Í\µ]vØ'€M ›â3èV÷?AåE&Éùhö±¤BÖ¢تmGÑæ¹T…Cr:2_.mÝVÔù×N2 $Z0HÒ¼`ƒÁïb&FÅÎgÈ1‹L[Ÿº#¶£•'ª«/jn¨5¾Ûýsh.LYdà/‹‹$8MC«Õ£Œ(!¬±ateŽ*“чݣEÖÚ4ê~TBË Æ´L;aHE¨Ú—|ÞPD Búõ©ûLQ*V ÚV{Íñ߇ӈ·j‘¢š ñ\ðP·*(p̧[ q(sG~Ø6ykÏ}ý¾Ñ±²"Ø6˜+©Ü
+`
+hi´‰æ±ëÚ&ÛÔ“Xê<&Õ´·*"Úꃌ¸¿#éãyòâ‚·Ôº‘²¢/aÝ
+ôtÂE¥-hÖúÔ=5A¾ZKm¼ÏÆ›¡ÂÜéòéê²Zâ^pçœ{×·¹÷žó¦£I Ù‚ÝH«±Ž1@ñVlñßWƒô±Ç rOxRÄüþ\Å,…ê³JˆÓ]Rv‚v¾vÒô—7Z2Á~†@aI?ÞmZQµ”´;E»øäÜ)ÎQ}†YÇü?‚Ø¿
+CíûØAçç¾DëE-½Õ\Ôrà±±IâÆ‹œ¡ec¢®-Ü`ƒ, áÖX kØe| ÕlHÉxeÔ©1¶DGcNu·‰Ï¿ä O‡˜÷’
+ Žìn]eBL T¬6Y;„™ë“‰ÅÆ-„­È¬¤æ½— ‰Wl£[ÃŽÃqU8~MyZY[¨v îĆWEyÓ7¿ 0ÝW6RîVeeÀ­av«.)ßXsŽK‡oAÿ<‘z@äš,ÝÁÚ<hLûF´×Iý§2H.†VŠÒâ~VèÚ)˜ÎÜ-‚®NSÎðÚM:b"8°Ýé·fï9î®B°q ‘O7;‡»¸MkX÷jõuÍ?^ûf@OQðÓÏÎXZÑpf<-£ÅÝ#þU´Ä ÊEóü€n†… RabŒ¡_ÊØ´Ê5R·ö–
+ÑQ—âçfÅBAª LyÐß ©/TŸ´F
+ #)Œ“_Û9ÂVîÃI±îáªÈê† ¤"èæ{eŒ=RÈ›¡iû=ˆ vG%3µqwrüÝ É]º|¬à¸A=¡Zy +—¸@í‘IØ$ Aoh³5Lºä¶(“{SitŠÖ™ß{ü´¿ðñölÉ謽BYò#W-$nƒ ƒKá´|ÁB86˜¿nó²:Ãöš5´ñtNo˜wnu^·éSÊCÆÒÂÐ|Æ9ip¡³ZÄúÓ^eXÕ:®Œúô„§JËêŒ81~ÛîÒ•œæ ýt&· Iq¥åŸtÈÕ¶ã YL¨ƒdKã3ÚXDÿ<m =šæ­sl/ÒPMAŽ.})§¶³”.mÄK;ì½}äÓ‚ôð:€£r•ý¾´8A\)
+åü Zùj>ShÖ««ËåW¹Š\^+É;RHžž—ÌÔ˜mg2
+žÜB¾rsŠÕé40ýÏ`{@a[ 4š¼(¹…ú²à/ Ðš›X
+rSŒ=Uw™°’)¥`Þê+¨ C’O<Q°ŒtÈ«·]ž :]K%úE"]žðBž8ƒžð‚nHK1vÐ/&®º¾ó/
+¼“rPÛAP ‡Ä4Ü{ñ{L)&†|Ÿl–0€=‚è'Â+ö¦shïYŒ[ÈÖ9m{ü®í<Ρ§cæš~ríp /H ´5¥,P}ŸLÜ(þ82þ„¿­›gÀMäæ²ö>äÚ|ˆò–Í.y
+ =ô½üËx¹å6 Ã@ðF…%êy¨Üÿ·C'N`qÕýj@ز¸ÜYÚëU×{ 4wIî‡.q‘*ÿ<6Ewîx ì®Ø)±CÝcÇÂ1͚ƎyÜ Ó/¢pWÜ¡á¸a3 ï0qã…9©Ýù©*üMð}z %fŽCbÇ<@Z)tv¼ÝŠJ*NÇhLî«j숢ˆÏA¾hW.¾aÇ<ÌaÁ£/¯»ã"~y¤Ž¸@ñ˜µ +vD;#v¢*Vêi-Ø‘+w¾Ëø¶¾žŒÅ‹•î(<ªfA}øv[¸Ž9x(é 9e|<Õ x(ò­‡1˜½”kŻǯú¼ì•V`ØE'F–X‚Sž’oüÐ<÷ËÒwâp~ê©À#Õ¼‚GE¨XǸh#ÏflÆ¿‹"Ux]cv³{iOe_Då½`¬èñ1<ŽšØtiÚ±zü €HñäÁŠ ÑŽˆoëà~ÒáBnò9ˆ£2˜,4 äâî =.2 B×PjÝ¡ÇÅ:¦ƒ™Cg‰ž(ù€UÐóm¼>èI|?ŠlŽTÄÈ>tÍ‚6ÿðéÙm[’'J+?5È܇LÏîYGåE9IòKèÅ©+7d… f—Ï'‰’$û=ÌKóF³\¶ís0†´û!7JÜðŽœq ºÙxD‘@ƒ†þ {ï* z82ÞFl…—Í$3⧠öÄ+ ωì‰ ì‰Âð êZÙ#
+z¾ÉøC65hŽ¼Á
+Gú`
+H‰Œ—A’c¹ DOÐw¨ XA‚ ¬{–}‹‰ðªêþ[¿$ùËéËSžq¨”"A ‘HÔâññ/÷þ賎1¬MþóñùË›=ø<-½ÔÖrƒ²Œ>­$ßæ‡ mÔ´^Ìz6AÆ£ÌjÅ[÷ð ¤>rÔ:=¦sÀ äï_uÏêV:GÅ›s̆÷
+ŒO4u¤Uâ±Ñ€”Gfµ1Ë´1|CF)Ñœ¿Y¯ëªò˜}”0k¥] ›Q{q¹ £…GFÑé‚ø#¬F&)òx1²Döj™ÞÎUÏ Æ9mF#µ~ýûWýøë—[<š{Î H¯cåÑÌÍÈKñ¯êµt2BFÜ€Ü?z+$ó”Ì[æh­ž¸ QJ#±DimCZ¯ØkíŠPúÌhY#º$ øͺ)„bÉ;b¶s ß*6[_jœÐ¨j=á–j1­SÇ2>~ÿºÁ8u7øV³·ê¤HÁÌ>K%¯”²Ý€>È4{1j[o@‚Ôä»ÙrŽy.#M#úœ³ä\ÂOFŠ‰ãTnÀ¸1WUm>»«)Üڹɉ­%o g‚¬ˆGõNmHçPêW²Ï||;šM³sÕ3ˆV±Î¾Î ’jQ©òw¥(@üB_lHäèFî{=Óà¾~ÓÛ¸^ýÊT«–y‡‹Èhîr’>
+£ºÖ©¶Ýˆ¼ j+Ò<}^sÀˆÂç*}½…ø®B”ž=/¢¾‚º¨ŽX tsc>Ô‹JüÕ}‘RDul.CÒh$fô­—Ùi6^ ¡ÆÕp¦ŒÖ‰â€È-]‘¹¾ Á\`®Aú±!=&- .
+•³ÑB1híðÈ­8=aþÜcÔ¯)),>–6½`ì‘RS¾'a›¤t4–¸îæ2xÌ A˜;ô_ç°Zb’³¾ÒzŠär£Ö¥I°ÜçAH¦ÚTî÷»!675ìÄÒ5 ú3„fâ †¾m|‚ì›èÓZ¥‹-Û›sÐFssZ£y8˜uëd¦š3lj†FEÁ!.¼:†èÕÏã(»‰f“‹²¹uìC+ÏM©AºbKÓ ¢):Fq3ö,š‹6° )µyú¼©˜†}¡µšmkÆÃþ¤t'J5µ Í;…(䧚Lv\f{pî´3Õ¶@?7Ö£ó…†Ø7Á¢¤ã¡ã<ùCÕ¨\%Â+5´Sʵu?Ù£{‘’^ÕF§šòB]=j‚iSoÓÒrom´áo(í@1Á榖ºñCý¶²=AŽÒZ%†näý9Œ ³HRzŵÀq¯h’ÙdT±i~½Û)ˆ/ZlQϲR$w.Z ïŒa’Ç°°uÎÄñ0™W1§z‡Ñˆo2+Ÿöå‘›ŠDeã©„[(žA˜!î2KéüW 6¨‘ue?œG‡z¼´Ë¼ÑLÒkÑ 6$0PÍ"pZg40ű{ôšÛ‰æô¿Ãõóø¿ÞÔ–Ÿà¼^Çåt ÉoxÁ4}ÝcðxÓüo5  &qá†Ç1qj¡ß”ÙÄ­VY|Äà¼_¢I2êØMakzÓÚZLˆÌ®ak8Ú…tm—U>™Æ˜!OC£H{ 1¬$Sv¶Ý@tUcÈR™Ñi²ñæ9Yn¤ÓãÎY B5/$-â ~!*d!õ‘±*Æe‹L´ü¨œÌ7þšiÂP ùòvšiÕLþBþõîåOäç ¾œóZ“-jÕÛzÚC»C9Œ<W=ó¢©Ûå¾Â¶sx!Ïhˆ:Éíjr¡HBþþ‹ÿ|[SvÑhZj8Ão¶¶¯7t¥ B>a¢#%,¥ßJK]Z¨­ÆX.Ž@§i,^ù©2²²¦ýý^yì‘\TÙ>ùES¡[!צœý²ùNΡ3£ßôrŒüϘÚA‰úD\0Cì’¿å;á­)Š¸Àú7|/L6²‰D2ìærV¾ä±Ðýècý1èEÇÖuò3lz£ŒñT1F×O7nùô`…Ó†m‘×¢ áZ˜ÁW"g<ŽÜm+÷bð_«q³(¶ôŽJÐñæ-Húˆý^  \„-ù¡„ê–F¯y„ŽÍ0šSGö´uU}`‹°à¡au†Ö^D-d?îϺj²v¤Èã„ Ã|Á¦2¨ÏUÿ¿¹Ô†Øò%l,¬iõž'ªªÝrõ ^Ѐ^{3ß?ˆÑŽ–Jƒ\íSÕ;H4N¬ÈÉ:LÂw´"ç†!á½· ¦—AΉ$QŸ5†îÚ§`a1~-q´7½± ÎÆħZê‘ÃÖQ|ªafµÏ+è†Ï…Î Š
+3ñu?qN¹Aþì‹ôw ­+8k„kŒ¶Z$ÎóÛeÊ9Ž¬Ð ÇJ"Lè“ùäã2ÅÔrq°+…@èbòU;ã;Ù+³ËKÆîJñ<™€ÀmbR”°Û #NsÛì؆7çh‘Cï0vƗȲãÖv4´ÝD–~ AÖ"í´4ïê.(ˆ‡©Ì0ñÏÄ¥ÓØLí/Beà`ˆ®FýÀÙÌaÛvE4†ù¹G;>´~CEŒÐkÍI¼"àþcÐS~þ¤M¿MdEuƒÎr‡ñ¸<Y`â ß®íkØÖ<ô“šß€!EÈW`wÛA°FÚ>E´A^0ИêxÔŒ†WžjÅ“®¢Œ‡æiaapí™[ò†
+ŽäcÇó •çÛÌÎUÏ þ‚“AìPOm¹Š†¬‚`d~×
+3Ç4çÂŽ05æ ËßWñPÈíy]ň‘Ö]QþÀ`Gÿ˜ ^ß0ð˜üûr’TµcäˆsÜ5Úצ;âF®Í1M1úìmÓ
+&¯#Øs¤T#ä 7„!7»|ѵˆÈŸó¯i1º8_³Žä×ûå³Ñ+Uv³ƒiÕ$¶†‰¸3UËð0ìæ¶@¯æEõÈF÷tŒÙ^A_Îq=“FÒÎû½¥bPeô]‹©ƒžPÇcÉ´˜
+fhÝU…v¤!Ç÷ÌvãÛq­˜˜s ÜêTëSüz ñ] {O;W½‚ºØNÇÚU ÜUƒ!WR))¬î "ãDŸâécl%OºM¾…"«-—ZÔhÁ"Ž¹Ñú.„+ ÉK9á?Œ—9v¤G„O ‹ÈàË}1çÉ¥«èWmÎýç
+/:|IA*Ý/º”Ü ê©èóM‘äq‹SèÁk2&V¥
+¸C›—Á ’eÐƵÞàâ'ø:6R¥Ê:à ÜÔr°C¯Ä*/ù»zY›ëÔ˜[Ÿ$V/Ác¥Øî—b* &ªÇiclŠ’
+0¹Š9ö±Œk"wö~Š’Y–f:¡>sœÌªx2)Dz{ª
+`vÓ‡g‹•.»Õ+Dj’ÙÎÕjçà:Ùuúœj”ðÍI€”Û‹’Ÿùߦñ°l#î5ß<Ä+ª†Öý/þ
+Ð-Žæ#£¨:¾¯Ô éýª"-ïï…ÂigOfÂ
+^ìzS1Õím»)‡®3“¯§fH—ôìc
+9”8eo¥1V?”Â#l–vÙ™Ø4ÉŠ1–Òê$ùî³
+0 ÷P®˜Án*5¬~)‰‰«Qì)4S¯çà» ⦯ùäY¸m £6”l[³>é윆
+tOø¡x²$:‰WÑêuQµ‡e^n3íÇT+Â.¾ø<„«š!js±Æ).£9ÖƒÍÄÇp¯5/&ˆ~@«,òPÓò/áúè<kLÛ0ìŸö¹¹IdX,v}[¤“òè–W.\ù°"î̧˜N?&ó;[â(£`Á¼Ó/4‡¡ E0[ž¸.tYÍ&s½™7[l“‡|H°Àº8zs—n‰µøÃÙ?̱ßLtåå_ú €Ž£CÂIfì4K¶S‹¹Ùô¡’Lk*bК”Rç¥H%Ø"ü”ƒxGIMÚ{þ¡'*,Z3Ú”w°Çâ7ˆ»CæHEÐ>ö¨âI×)‚. ƒÌ\ýsð^tØNÊoƒçï(!9àÿ\E8%p¶ÃB½5»5XxóÓîóé#4ú¥æáíI¬çÔZ.5ªàf<c…i Á³7ºGó—• ¶Ã‚^u_ÔlÉ–œ~É»#G‡VYtX˜öÀ*XB@6ôÐò.ë,ÉèoJàKäN$\óùÒSsàòt¡«i~cŸ‹¬î—<£â'è:ÞQÓ Yèˆwôç7üð"º„@÷¸„+I€ÝOJeÎøU 6–ÞsͶ.G$ä‹>®|Þ¿(à—ð™í\Ñ.JÌч}XºæòóÄæ·=•èSSxVÆ]
+…×sæ</oR­¸ œ•ï¼Ë*øÛ½±|#ºº„•ÒâKr<‚˜qŠ°þ`:÷°c`9¾•Ôå3SÒ!v’ ¶u->´m@T“U/½‘«ê|lP\6á ìù>kÃyt2UI×™ô\FÛ]uérÄ¿ÙãK¢¥‰³La«‡ä{rÖðrÑ´€,ÞÖfÂ6ð+s_Jî„ñTôù¦H«. uÅãV„)gef¾‚åø²Ì¸JH·RÑR¸ÌŽ®g®$.àà6ö2Xbóå(O˜$#2Öfú"?qúa4‰ÿªÅ‘>ÐÙÁÉ=å×
+ÿNK ×lû2ï§ð‘*Ýâ¨ÐlcÂâô=ÕkIµ°•é¯à@'›]
+Îpê!ÅçTô¬‘òÀEø­Ã2¿,ǽâ¯+ù½³Qƒ&Ä~Ù"ì8Ésm*¼éH3Â):fT aéñ)±%v/±ãÂÇÜü
+í‘oL
+œæ-Š¸jY‹æ%(³Ú"
+z I› ºpD:RŒU‘?öÂ#ºŽcXÅ©¼Àév©Tˬïy"LO'v¶·HeP­) ÍÞä´Î§~Ð+I[ù P ²»#ùƦŸ^TÙƬ}œ‡ßRŒ_g°ìG)K=”y‘7Æš-â’7• ƒ ±Boã]I(ÙòWØbO$6z[²1"Z]cEJïÊtM´\W½4´hqò+¹ëéPj—Hz‡*[†»ƒ¤»KÒ³èáˆíÒìxâ2ô6òÖq{+ ó²Aù4ñY$a7šÂ­wÕ¿$O^Š¿
+õCwT@IY
+¼¡ÛLñ,ÇVBV!ˆ4²î¼Îm+xÀ4¬ƒQyMR v´e0; n=¡ná=Ê…bWô¨‚Žla 2(/¤­¿‹ ø!dD²uiË œ?*”fÅÙt†Õ\fÏ…96‰õä€3‡±eéÀ~/A‰7™þJˆ‰£ÃsžtËmà[⽆´Ýù‰,íðggj°9‹0éþ¡¥Iþæ"² *(欕<¾‰·×ÔÛ[¤3t %ƒPRbΧ~P¬ÿÜ\ÒÊahr^ãê5´¢´–©›¸%8~l¶»Q[Pd%èÚ’Iè×`KMœŠ4$ƒbÒæ¢ì
+uŒ}xñ-ÞݵE*¡ 0ICm˱}òêŬXk‰ 4ûìv ©¢+ÓÁ†WŠæÖ0úvÜ£›SU.ãVÁÿ’RIÕ+#v0™)~Q§Bͤ ±÷ùÒ­ˆIÐÄ=ºú?üÆüÕŸXW°ø^¾lVz­sšUÞמÝCQ‚-ª†›¥R%<¨N¡/Ÿ’Åßð¿ëR¸Õž×† ǵ%É)ZÚ0ÓùPÓ>‰“×ô·Ñ³b^§µˆ;‚=9ˆ"5”s‡\F è.ð&4Ô¯ÛÀ@ÝËVAóªL2­9)8‰Eàö¥•¥]q‰£ÕÓbv‘‚JÏ5ÒÅäøƒ9úµÆx7DÐ\aIsrÙš‰ëdXÔM¤‰ÇjNºLUvŽ¸8È£!;©6z$ƒ8çì<&j`¶0ëì§}uàÜ:W$zyÑØ0ϔޟպcq`=·Ü‹Ûø‹xCg_ŸúVSÆ­èï‹"­ú|AæíãEÑ·4ä<׌
+0iBIó&ßÑ6Íf
+׋˜ÓBWÒN5,¡yÚ¸)#DjúãàšrdI¶¦EaÏE€¤uG2IŒ·ñ.öÈK0‘¸óÉkr²ü4Fí_ÆË9®#¢'À`Ó˜è}1”IW'`È"`êþzYÝ þ/QÀ0ÙKuVf íÊdJÅ6¬>ŽT’Ñÿ”Ùrß …$@ó,ië@ÔˆD—• osÎÊÿ!ÞÈöÓ•¿Û:§‹tlÖ,{£û‘f1#Ž–tSÁÔ{ÛƒhÒ2$m®¾†‰H„fBâ®8MÛÅaþ˜,Bº­Ó"å"›|ðÊ2¯_n€g2‚hT…"ß_îL}@ÚЭڬWîs<ÍadÖµŽ?j›GúÀð=<… ôô·áûdë(è:7þÑ¥­Jïú”$„:PÙõPê Q‹Ødfè>ÍBRM¡]#ÒhÏc ™”BÑ{ÆÛì ´³°…Öhåa$óŒƒè›fHA2é³…TÊɈþ¤l¤ü¼êN\Ž8tÂàïéâ§í•Mëó 2ö#(UlBÇÌ"_Á •*ŽÔ$³nJÇ;¯¹JÀÄ2æ¯ÖAcIB,Éà@¨
+›W9¬Aºæ>M2Þy—xÝ0
+Ö REƒÝÖ.jAFÁÜã™\8dÕwvï}Ë ”˜FJ$JrÃWÙ£[qÈb;Ýu)Ñ€Aþ€¿ýÄ¥Z¦x}/WÂÌñ«²°H$<î`íå€2T’ô1xäõà“ [OxÛ=º´©Oø hµ<)H4ÐÃ¥´ç 9óˆ-‰æÖòˆ„c‘¬ÿj ŒpbÇ"&O~U2PV?áªø]Þ3€ÏÔ ìaù('ª‰Ç~‘†²Vn‹Ú"|ópàBTTá“X2DƇ"ÒÙHÖA‚de£ìAy=Ù8œ¹(¬~¤à#ÐIö²× ‰5ˆDçn„#QÒ¬@´'VêR´ )eo…7"´´µßIO>À”òX[‘å…ƒ.Ýëª5ú Qø | ½Èß´éÞê
+º†&A †¸Ù=ƒ’±„H€È±ù>Ûu6š=âV‡§ŸüßJRvO®ëë5iZº‘¨·âÿ==ˆY…)¨kîl¨t‹_èªFË»©œ$ðAÅ EZJRíã¤8þ1 e(seÁ*ŠRhQë΋$ÁNl'ЗµÓ u¡!1
+§Õ=HÖùZˤ Šhºrë— æÍðÂXt5R›°Á}k÷Å»xO×ÔêñØ™ƒåì@V±à‰†¾‡9g²j•ùq†à]ðAªWVƒGNA>ëüYÒ¬BcNBaZœG*¡ÎÛ¹ÇÚÉXœåQco…lË4&bâ"ÔdI«âéÜrïtý^âuñ¢v;ëÑ+þÆJö¥\e«’—àЙ›[þ>;1 ’`K{,¢èŒt(¸˜Ô«Hª"úêpÅú¤×‹ ¢O+L÷L„˜xŠEKçÍÐÈ}PT„g«
+—šÝ= üYâRç1n—Š|”!e¤Πv)–$%òѹեÄäÓSí­n ¦Zè O±ºWÿ4<
+ AòW—’¡ ^Ñí\êZô‹mÉÌq@½W¯Ä@` Ë­»ûTÈ"ÅõÉu.¼¹Æ£ßíR?×Æë…KÿØSê¾ ‘f”a¶àzˆ›êGÚS¹U?r~ýðë¥&f¾ÆÈBÄή ÷“Ë¢ Š¦ï/½Á<ý65µâ€~x :˜‹Òüˆ? g»+èí™3iÄ ¯ýûòí?þ¿¾½ôژ⒆7'­N¤Oˆb‹q Qº ö¦!ÇDSФ\•å˜v6‘JÀTò× ¾< R(ÂfkÇÜHºü
+z{æv*K¯+?Êü² )1ùªcì8˜½(1É1–aÞ,ì€~x ¯RD
+Ó±J)Ò ÒI(”“í‚|i3#<BeD¤ã‚ gM#ØP
+DÓ‘xË|øÄ´š§Zq Z‚vÊ’à8ìÈ£ é@ lAhY£á˜}•’LÌXÄDÛGA)=:£9J³7²«ßAJÊtL¿ËïØ^ö¨Jh¼Âe×Õ‘íÄ=L$²/“3M{* NuO†À¸žtÄLGÌVã¢q‘lOè<¯.·'øÒè«ž“PM…æ[I.Äøù {–ÀŠhø93¦o«×¹ïÈi8­P€PÂäá|Sˆ-d\$d¤R ÙZm‘÷f´ i iúR°"^ŒHOµIëv?…Ü"º¶°ŠPm|˜š_iÄ=ŨQc¦É”zD¥²õlüÌHÄ”ÉÛ.¿Uzk(”P|&°"ïÏî ùPPâxœªZóßAº+ád#úÚ ¡É¸±§îÖ :ò÷ÖÍÑR[SË’*EÓË2€íëê04P]o
+á©DaëŸÛ;\Ÿ]ïÙÀËÚ8dr ?Ÿ¡Ï‡¤åö@&¢f©8Ýøî‚èF$‰«TÞŒGËJ<`Uy[\¯Æ8J{¶Jó‚&#£411ív¤¥ù•Q°)ï
+¤|?ðˆ‘wðfaÒ)”uàK´š^)a†TÕ˜‰Ú4HÖ¬4¥ ³;mUÌA åÍ]ÇF¼.Πx›¬Ê—! ÄváRq ¼öºTäoIV-Ðu¶“M­#¥Ðž£Tä®ds`Ð¥xùÑúœ·›‘÷Ù:ÇF]ˆHMp<Ä+o/SÈÌü³‘Œóh>þ%þÈ»8Áyì8§Æí#ñÛN ž·´ì°í
+‘Vãæ$ o‚ö–ò7¾ym$N0à ±MÞEÝɘ„ï6†Ô87àIC9ZR8sûN]28™Bß …ÂîSöcï—ÓQnë ”¬ÉN;“㔸)
+§dÀÔ…Ý[ý¡7? ƒ¨ÞF²IÊ$çáß=çš1k&å¸AGB‚ŠÆW?/ÆûLy[¶¦èvª¦,8·Ö‰Ì$Cî8×Éaïhƒ>€˜«’Ê¢Êgî«Hhj—Íj6[Æ#-J
+Ù~}ú dq,¡Âˆ>A¡5w8ñH\ä ç4¨QÍðnêRx&Nb”0úÜj6¦"Š˜ÒÚ*=h’‰Ýñg93 ²D,ˆZ|V@²N&xJ Na²LkuËpMÁDòC’âéñL¼Á¤€o.HN‰ü&¨ÞBµ{ÑzdERP°¡Nvíò¸kßWG`}Ú·žÄ­rjÂÝ‘°¢Ø)*v«âñÂä œ­• ]iÐÏòaAP‘Iñpvêãëò²Xÿ?ãe’IŽDÑäòg®³—u‹Üªî¿í÷t5ÚÝŠD•
+›*©éí¦}ˆ ûσâód,
+®i1Ò©ûÂɘÊì"pÈs„1Ñ<y·>·2B |‹ý¦0h=¹xDoÔ“±®Ð)J'A|&cÔ˜K(uŒÓ‘RX-X:ò-
+w±DµveüéxÍ%‚ŸEY¥´£˜"_X‚ò ØÌŽËe<œÑ4>l,RÎþ÷Ì(Sk½R`þüŠ@·Ìó‚h.”PEUò­ë2ߤÒÔº¢j‘w¢¿Ö²¿6ë‰ôòZ³]ÜÉ7j!”Ù6µ”/¡…|R`#„SåIÊ@¦<Ø€‰˜Üd4)äДúÒŠ@Ç£…BÔvrxœÓ|ùdÊzµ£OPZè|ö!ÎDÕ®ÛŒy, œŠÌºìß½ ›tL?Ž_ƒ>#À~üÖNQ‹¹XYϽ^cf,qt5”âw°v²óù醼Š7´‰W9ƒµeèkƒX(bAõöíè@ÍÝš”QüÕqÒŒR:²)Øå³÷V!í$ܦ°S X…µÇ0£•§Ê(ª¾ïÓ-nĤ"µÅÏaÒ0ù}l܉L”†Õ!•ºJŸPÝ©=
+ÒCu}7Yµ7ç`|1¿ògçÆ\W ¾émO½¢É|§ž>`HØC\|*×”âÖEÓÈú:±´aò‰-& ÷sh‚IOô‡£
+óuXˆ_„Ì"Í£µIôð­ptŸHÅç$1©Sv]þ;‚‰„Âcðölv’‚Lh^ ‘òà¯^Š[MjÚÎ,‰TM¶!×Î1ý¥$‰ƒÀcf Ì9§ÁbsͶÆÓäC"dV
+™lˆˆGµðœ®¸‡bãg:W†¢LÌY»Õ=£ü@q 98ïM¿ùGôÔmIÞƒí¼´ª©x¬ Läë@`ë™PbýŠ@°TúùÙ éPûöPÜeñïÒ¹6½Ø4Ö£«L3öPCG!ˆDýÖ½»_T‘FU£ºò
+i±N?—o#âx¨<dzP‡Qý¥q]ŽBÒªAþ~Ò«oáExWIJ®ÐFýÒ&òIúz¿ÅG¬'9¯E¤„Söèðõ8¤_= $ZÅÆœ£Õ\¨­Ü[¦9¥ªÈ·ûªT…7£rë=ü\p²k,¿¼JÃ.ž…dŽ.m©,“Àú…Î
+A 2•íôõ â“‘³^
+çÅÁïÔ®ûí`V¤¯‘i¨Wòµ ÃDèï)–‘€ëš§@}§i•à6¤ÞA‹®UÔ Ë·í¨Á mOË
+™bâùþ7)ÛÙtš'cÔÈØXÔºð¬hÕR¨ƒWD}K‡FkËÛêW â (jDÔJâMžÂï=pQHƒ”ÃxÅQ (ÿÚ3Û2ä<Õ*Æ?%I»óJÁ×Ó̪¹ðGQ) Mi;§ÐÉ•T£^õ³ÏÐØ©øfÝøv…ôäÊD-ñ.2>-߉, ½²ÄFáÌ“Á$™Ÿƒ°ë²O›ÑJlNn'3üq|EÃy³³EZ0Ÿ˜Î;èt},FfÊ„¯bîu(À¢¾¯’³î÷QœÓ¤ÔgÞ¬dÔ¦ÈðÒ>5ïã:ÜüvÚáâßÞÈïÍXN¦’YÝÒ.³Ë’ÑKè§t¿x—vmyX(¢Å€³°Ð—\â›x%|9þ<˜
+ÇÔ¤’®™å×ZTÏ>¥uÑ6'Dߢ;I‘+¼ËHdòW‘]
+R"⥾O–Ú*v€W„éQZ’`/-ÝŸ+¦;T€¦ò¿IQ¶ÚwêÀܲ ÉR#U†¥á7%“´S[Ø7fk®D'‰}ÈY[ËQç“ïàb)ÌÓû5ŸL5Q ¦ÁFÚ`1º¸“ÜJ¿²Y¡|•9JqJñÒίö¨¬‹åË6J‚ ù>~n`³:0RZ~–~™½^¹„McqøÆnÁë
+Ñ4Ç+Å«à•!éèä˜Øfnf
+J E.xXñ„ó¢
+e¼$èÝ@Å‹XÅùU ®šÑ†¾Y5¢ÙÇI[AŸ¯°ét)¼…$лüvËUùs[ͬAä
+èˆ$ˆä“É›EÿF±‰ ¬„om’!å^OülØfZ‰^2Ä°½ ­×ŠS‚–]=³]®y¥ž@”A*¶5àwˆŽ¢÷T±\³üwÿºMÃjléuã‡Û4cÆDı@s|Œ_pÖFè»KÓd{æR¶lí\àä—FùQwÐ’ "xð©òvºŽZ¡c·y|TUØ£TX±ŒÂúQÅ©bÒ)tÏNÆs dçƱS
+ÞÇ—zÇÀŸ@‚µh dº¿‚ÂTð”†a¦ÓÇï@U¥¢ŸË³èaˆ© >‚
+JŠûÛyØØE„ÂþÎòòK§~²yùíèà»ÔhÉúÍ.¶ê£¡zÈ&Û—δÉêq“zÀ|œ0ã}a¾šJ4v¿04NZŽ:0b}~¹0µøþBb¤»d¤Ãšh#´·Ïw/DFXN¤Œ#Ÿ/I\¨ 5ò
+š•î¨T$7¹Å…™†‰íPÚÔŠ\k™å$Èê lš“Œ¾ÍlÖÊ Ä.V@ó4¿ ¬bI$Ÿ ý¬1§˜Ô
+ÊåÂûl¤œ™sém‘$sÇ©øP4¥?c˜u€øQ8”Œâ›W}òÍ-è$Jºã6Ì_¡rozÔ}Ô-\6åKù;*«1Ì-@ó]öp>JÎ Œ ûŒ¢
+¶°¨òQ>žÇYpJó“pÏäQÊ;G¼û¡¡¥@–Qª­’Ü:úåë€Pa7¹v¨ÙgØqšÀðø@°RÄõ}„¦h˸ΎÊÀ)Y‰#‘Bã$urãñJ˜äþvâŠn¢„í¢á©!,“FO&k3®£þŸs.ób3FÐ8)wÊE*991©OÐØ¥eöõ$H¦ÒCZÊz²ZÉ ´“A*¼³k³ÓIØT¸K¾K_û]!M‰¹Ç`“ '<F‚
+Ý…~I-VEKq…EFQ”–/Î~ d0üB!Ã*À¸  étIKÞ0¿´Ãz"ÒfLÀÒÑðFâ9o'6ˆÔ ˆ
+ïÄôéŒL—²ûÐbc“ÊÆ]¯"70ÇÜ
+–)L¿Ú£z˜n¬|îDgŽ@5ÔÞ%êÒZÊ|€ølmQHÏ8˜þì;Ø:2A
+D§Ë€`Бú$*~ò&¦Ág³ÎWYXLJ¶Ï¨…olE”râë|¿úJa¸JÚHy»zÐ1@‰ÉªãË#>Ø
+@”\bÅýÆh3¾±ˆUclÐ •-Xåä¬D™,ìµ™¸…„qN~‹l (<éµ™6ˆnJì"$ž¼p…#îÂ[(ƒ/ÿ´–an®¨‚Þ·åó¨\‡&Â%‡ìd=ÔÞ-aÁÛüÇx¹#GvÃPtÚì`Šÿ±R¯ÃÑÌþSŸK€]R7»,G¶Œ~$Üg²Nó’Ao+ƒÂĬû4U4dã ëÒš´rÊdÓkÿŽö `F¼\Ï„m¶6‹?á`M +Ûî¸â¢ê'Þ⌲aċ |.?ˆ P®ÁiËcØâA  îðìÂÍ[ŒóÊz†ù´Fâš"?ðŠ*@[¸)oˆš¶§0‘2©²ì…§’» º|g()#ßanÌE ì!ŠIŒ£: 9”[¢¿Y¾‚ªÕº§)Í]àNÏŠ9í12e§ QÒfÈzÙô[Éç~ÜŠÚ–2S¶Á/oa¸! UWÔͯ‡a9 k¦Kô{W
+»¨S œˆIîGEã·Ò@à ‘ïÞœö³šo øó“.ífÊÄŒ •‡ÓeCÑÒŒê%5¸¿„ŠpôñÔß.%82íé‚ŠòÅǪæ”ç7&h1„“D>[z¨aø¹(PX6bFÁh”à­D¡<ÉÜæ~3Ž”€iàÌßú1ŽÏT~ ƒ‡IV6½¹T•`,Ê)}Ü0æDŒ³Ÿ¹Ãžê¼šëv¬“V¨[‰ƒ–Ì%О‡CÒJ™š&zã}h¬—"Ò‘VŒ=$C5/aŽôÅ8+—$¡ƒ`.¶ ZâK'ìêpÙP
+@QA¶{3–JÆúI½#V’fÔ€HŽ rÇ ^š`.Ïúu¶æ ä›Žÿ£QUØ<‹#ûj¬Vwã£"É+†jÌi¬!‰ük–K W8`€~”ÈKÑe^a›' >
+B¦ÝJ‚(øjØÕ¼Þ|§Íeë06‰ˆ$a.Í)‰´ÈløØ8ä—±’IFbæ8ŠV¢Z˜Ù1#>öM¡šÏ&
+v ’|XžÝ¡Ã®ZÞ¯râÌdÑÖ·wM›L7ã¤b  ½ÏK‘”˜ægÇ$Žc>ã/È¢¤tÝdb OP…á1&ãGI¦L6i V½ÍdAŸ÷‘#Æzx?².M€ùù»’¦ÛÁé&Êüü¸]ð ™ÑŽ©£«½ñkÑ«\_ŽûQÄ W²Ûü±l½IÀq’X’ÁL¼¤\ zuÖ0ɹʮYϿÁ+Ä%›G÷^‹pÕØkd
+€º”þ¦„„¦iVy{”˜)ìï9
+Ô+‘ôà¶"‹ö 5¯@4@
+ÿ:¢5l:†`H1F/EßéàZò•Vî%_ Ê»7}­q«ƒ·À”"»'ß}õÅwQå~ÎÏ
+z–í¾
+B¯úqVÀ—(
+-Rè[
+^ d^•æ¥ÄÑöá\i¶ñæ;;»Âêìʹ ¶Ž8ÅB­Ð^Èp?'A-m7‚®ÅQxóq–¹ÆwD ¤¤=›W oçG†È¸iõ
+W a a)_‹Ox›BQõW±&üIÛ’CªDGpÍù
+ó§?Šç$5
+ì½|‡q*Š²cì{÷–‹ @YSµ+ Düïe ÆZ`1 vª¡2MnÚÀtñ´É<<|¦BÕp&¨È­6²Õ£Uüª6å¥?7ø6@zX諱JCŽIÌþçã†-¿ Äëm6 éTûyzëcKpC•œ
+Šð¶«`‹Ò¸äT•$`Î2ãj9L‰#
+ßë/«JÏпÚa‚È'©kÈB£ 8-è2ýü#
+ªöß•yšq½ aºXWÌ„ĺÙB
+ÍÆ#ílÊ $Y»Ø†î媇'üjp_ °r1Ñ"0ü°«¶2›Æ¥¸€~úô@S¥ÊñÃý¸ Ü™ôõ¸>ùrùôèQÂ+ä÷FÜ vaÏËêYóÇLA`ìÙ(An¸oÊå¦û"×HìÀÚ÷¯›j«²¼£Ùv LSF¬=JÓ«((îá,ÄN&Txë/ßX2Ö.Wá2ÛäÝÌxoô fõ’-JÕº‚ÿdœ¬Ü"®È»@CàÙÐ_ÅxLÑÒÓ_ôá1]‚l³›ð/¢uË{´IE™¾†/¾çFXú‹Ò _ÎmCÚE5¹åF £o)•H&ßs# Ìx‡ïfi©ßr#N±óΚs쮺v‡PqiþcF3‰wáO/àB"x4_$ˆ^¡"ß®î ÖÊDÈL_ù€`‚yÄÛ&«1OF98³óHO€pjä iÖIO-êr™ƒ*±ŠUɭݢȂ¦áûØ2*UÿñízÍÝ1}¨Ñ_ßò÷?jòv«ÿœ~©rÔh¸$ªi6­° ¬†¼®b§Xv$'ŒÀÛ¥…!ânìTq ¢=Dí‹Ä= œL‹*ÃåzC)19k}A&¦£Û²×ï¡™ÆÆÊs1ÃU¬˜øw÷½ôð€t<PV÷«H#ë‹Ñßç«vN’?¦¿ÇU˜&"¦ÌÅŽ¯Â”atÙçlô$‡¨,f2¥Ö·ã¨ü̇aEÀq¨žXì­×k’ì&@ü(±…IÚåÅW†ªÑ7³\p@‰tȬZB"<½ 0ª¬7Ù¯—q.zbºlŒÍì~J%u+ c—Äà8<ÿè"å gî× %ÌÂúÉL0O·jmRs1sî;IYf›§”ÏIµåz{Kå‚ð‹š_ÕÛæ|9¦ã“yßQ$kîª2ý“žSÎs;c¿/Æ8®b\rÖHea²’L¹BÒM0ö!רËÄU°eó‹lvñÑeöu‰¨~Ñ&)²¯йŠé •Õì5¯Rˆ¨e…GÏý«·Ä“&aâ1rñ”înþIP
+keõ°œ×09¨ßZJE)f&¶Ç­ŽBZV%ný\•‡1C³‚â$¦ÓµîkKX‹¯r[.ŸÙ-*}®’ï$ã S ø9âäüº*¡¨LØ"®Æ8óé|4º.ÙJÆ\|ÔµY@ñ&µHý „šè“dÓœFo h ˃Lq›?8KW{°’äÂ1ðˆ#H‘M æň¡,P²œâq*2Lv5&¬oø“bÎåýÆ6ªï‘ú¸Ë11§Óß"ÝÂ’Õrb¡|+2œæhg ÌÐ*”Æ=°v—óy@E >Ø­–<)›ÅظõÏ" Öú’¶yF—Úâ¾]?È ÒFo{uC)%“•®‰©?1YÃØ0”7mFÕ|X3kq[N> ñT½nX†½˜M6
+±Û܇$¡R˜‹jÍ+P~ž¢Q˜Ç)eSbê1pr€ Ê.àÛ|
+þuWßµ#…ë©Y\µ’‚3£ï ¾y( Á8ÎëÜÄ7ã9<áâ¡î!C–€@ˆqŽãܲÌ[õˆ«Ø`•MËqkœ$\’ßÄ[&¥ÁpÕKv2½ãs ý9bj.ñ
+ÝDBD½IŸy?‡*A—[þ`Þß"ÛBà*úú×Oâ½’–ÆùnÔ†à$Þvj¨=è»´ðýò$05­ºâaî ºý544Áf²ê8
+ý°`ð ’*,O˜hÛéŒÒ VEÿ+)¹ZCæ
+…¤JyµXL@IS$¾‰&ˆiðx‘Ø˧b‚Ù¿Åøaÿr@’òÜwzͧP8åLDü‡“šÅC©¨ð¹,?¯²Á{h"T‚ÏÈÛ™/Ãzü„ç0÷¼qbq{@´íÒÂÞÞº =m²¢UÝb»äð'ÕÏû øæX™^¶£ËbD(Ù•óÝÙ´±+„§ŠÄÀODŠr†¾§Ó´&œ5Ú€^Ák!¢jŽýCèÊÕ|¯pâþôå¶#Á.“?†Lr þä|4ÑK'B`~ìÃüùÊmb¹±Ý/»ú8‡Zª«ƒ¿á•ãÁ<¾ÞÈù2ˆ®‚S¸¬Æ"ÀMzŠ;z\ÅfJn‰6ºdMÔ@Îjçà g3
+íc²{¨Â'H¦«ìlU½^†Ý¨2¦Ä ùØ´¿ŠIB
+Ž¦ÿÌð:N~én& "+ÁÒ˜uøUÌ‘,‹¿ÞÎa…ĺI3x^3%Í0Á4Dç[¹ØÏß>!XjH{jwù,ù!…-Vž†ˆG&ÂôæOáo¼C2–ÂÙvlù[Ø~d„óè€l9<‡[8_]â‡7lÿæ
+H‰¬—ÏŽgÅ …Ÿ ïp7‘
+¡Q‚FF·ç;®ÛM¤aõtO÷ïžk—íãcWÞ6ûÚ}îäÇõöOþ֛߫¥íî=»çÅó{˜>ËgËËÛºg†ïÞ[ëm]}ûc'·/¿ÜÆ=2ææyØíÛîf#–·~õq7ÏÜ6‡ó9ŽÖ9/w¿GØ–+ÇWŸã^™±s-úå}óê1Ö\fWýná]¿Ó¶­>=âêa÷Ükr6^ˆÍqæ=V#"θ|òz¬Ílâ ¯~[›D´¦sÆ«§Ý×Û‡¾úõžúwöIœsØØŽ¼»~õÕ‚³Uà‘|ЇO×A“·ÍYöèVÉìw8H'2lýO(¶ô°ÝÔ(l5þöè÷2Ççv·­\à¦Jø6_Ö•9¿c©··q¬
+4" ¤„ U¦²Ä¼ËLÏ ¦RP
+¬l~Q!†­H
+*y™¶… ÃÂzÙbvç°c­'¤Üs±xúxŠ{ÃvÛJüH\wB™ÉS¶›‚‚°„’œ%‰7›À68„ñµ‰`Á d¿£h‡Ñò4ãÞ 2µìc/δ‡ÓADÀC*
++ÈYîñ`-vòÎ1OTZ€ 7ŽÈy‘b,ú¥èæþtÇî7 ÁJ[–bñ¤ë ãî;1NÐ.®ªòŠ²4É”õvÓx¾áѤ ª­Öè–¶>ûSš™·äå4%¦B±¹`<ÙÃüØ·ø¶­«—Ö\jÑA
+ŽÐ‹:§R–š‹]mJ ykì*’¯¹ˆl3hOþ '9 ö~ïIün/%pfãŸD´Áˆ æT’F¬“|Ui–JJTôî†K“"5°êtß@9ÚªÉÉÑä¤ÎþxªùŠò7hBÊ“…k4#€[4£×93ˆðhQ'VÃðfõ\ÀG%ÛÖY E`4¾ÚÏ~’s×ÃØÊ+‘‹¢ÃAHc@@ÚQˆÇ1yì^‚¸_0í›PÄ*ê톈ésRp>7uo»Ú® sB¸Zcµ ÑâeUA-7£BÐt[§@é~P4´8‹ˆâf2i¦ÍÜZJ!DŠutꌲ±|Ì}RØ^¦
+:ã:â;ìäÂi‰QëG©­3x¤¶PÇÊA(5j‘ñ-Veª<
+Íʧ_Z*f,ÒËì8#Bý½…@Ìh75å‡j¥dl>|«ÝX2RcItµ·hÃd¦1&•â¡íÜY9F¥Y1—Õ:iFè‰m©[h" ‰Vƒ[»,ÇÒ.K¿Ãù* ‹iõ‚:\K½kñ‘á×PËLƒ$ âI7ƒ"µ×¼¥uB*:1kuÙ5Ðʺ™CÛP×ý‚$ $Ãí¨ï¤>R_[Ú%¹”Ú†nãú¦Ì°àCÌØ`äã !«•X ãÄpi¨¦6šFDAwÖ£ý¨„Ø@D-Ž#’Ät!yÏõ‡N©žq´XO˜‘LjHY«[ð-‹ˆVÒ/ÓäZzg6ÝNÄ™š”RŽŒ øÌ ÜÉIÛ³ÕB‹$÷‰ €å6×Ê3´å«Öµ#ÐÊ,zýbˆébÔ4nɱXÅ·O Õ©g>uD[d¨›Ž
+Á)éغpQIc…¥èô[Óƒd…„!¨ƒ¤‡Ý…•µ‡£¿d*5[*‚ÿòýÅ›÷¾~÷öûŸúîý¯×_ùè“ϵN†à§×ÿüðþÝOß_Ÿ|ùå›·oùñ?øNØO¯¿€üßüûì_ÿ'Cízóþûå÷_?;¿]?Ï×õ»=ýû×RGý®æe:koÑê«©Æ0h Êÿø€Ž„. ¤?@é±J¢Ùf¹Æb1ëÁ,û.%¬ç¶DIãå²7¤‚Më ͵­î3´Ý#Xèe-X]sÝL‹ü,†Ôê$[ƒ#8-(RYhÁVïlÊ<˜g/ÓuíiÚ
+E?K6µÂβÜ/D_\S…0mí R$?6¦½
+^ÞÒVÔå}càxãʨ¬^„²zÑu*A`óÕ*Óqêa¦Y=LL©"õó:WŽz½ü‚ K\ˆ
+¡{\­9Y!¸m”þ¢B1ì´«ýÆz¹$In#Aô*u‚2€ør­£ès~½ç`VË:Ó¤Yhꩤ
+|Aƒ€á¶1Tžá½qzs¥Qˆdq®­äÁOÏãAX§aÞ½[u!Ä §W‡«%(çj9É
+o‘³Ô¯ÿePk¹L¡»jOy¿ÔYQÌ ¦yD‹xL<ÕÎí®¨çû]^£ãC{›ßp½ÞFÍzÞ"eCîü
+f@²'Uvjþ øHŠËÓÚ$¢qI.C e)Cò‚ˆ
+EÇá…~B³¢wgèErZƃ˜fß¡I‚¾´œˆFÖI2lLÉr3aÀ¿·ÜGìܱ5–
+8V.k¨0š—t/ÎïŸ=Âhì –ÞDó³kì]Yǯ/?öè^úÛjñæ׿ú°t¼KÓÝÿ¯Y¬q…&@ ŒâM“ÏеyÉ!Å4ï‡ÕÃ:d%[œˆBé·5Á
+ ¼¬CyyuJ©ü¬Olð¾ ejæ_áãR/Ï}‰#Qz Œ0 ˆF²•-(£|3ˆcÞ/è^'æNœÊ}v 3‚@µv¢‰%R‚sT9¯“GÝ
+2>(ò {Öã‰æèY¸ƒ€zÒØ5_âÔnU#ˆ{]®A!^Ã
+3(
+{˜Ñ„ÎÇA­òìtj æ8€9ò­Ì”gäÛï~ ]¾ Á= µ°ïp‰ÅXóˆô…õ¤3ñ뛃sóÀ§äE^*¬B¨q&,•åzõï(ì'D ÕB$÷S{JÖ¬wq…gº 3•«¦ßظKó¬2Þ§]‰ ,F)
+ÿ¾N§ù7÷WáT|ì—,Êçx€[@4¡lŠ‹Ë:¼£6ʉo!?Ád|[oßØ < µdÜÈUŸéÎ4U¾^PDro8“
+©[âFDŸË6P{Ý>ýêÀuÛú!!T£è{´ûn§Å1ŸG|{ÙšÍë1@ÍÌEɽ\âÑð{±açÓê4ÐÆäõ}¹ýßά¶^t­{ô²ò­GTI< ÁÙ
+x»®ä’É“%æcÅr™¼ 'XBGì+|R^)sŒGAUÝ];ÊŸ…§f“…wVÁïp¥(Ay:™Ç\÷
+D»ˆÓÞ6D–¥ec÷ó‰ÒºítèŽ#Á½“l0
+èN ÿð…¨´Z+Éæ¥'_¨¡:üåV)ºßmPäwÆÆC.”“,ŽâIžPÆA†\ºhœÃ*—T<oÚ®3¼EñõØ Îé?¡œ@àoŽÜHN$#?Ķ€Cýß:'@]ö¥{x9"Ò¥âu{n¥ú—Ö§ë«ãr,†—c(¡¼˜õå& «\L#Û`”mðl¥œtÂÜqÒ‡&`0F ƒz~ ð­,¾„Ïܯ°ó…‚°8r·Þ§JEØÈØ<Rξimœ\Ì`ÙÃ"r¦ÁÌ<4Þä!‰}!Þ­í,ÐÚS‘(.AÔ4 ÕO®„Ý7ìŽ A‚kÎhhÑØ™æ—$™¼6PjšHXº±(Ì3é·–m9Ì
+üƒGBxÉ!ÍÔœ[@áPrù4 mì·¥öoDœéÐ&+‚ÊÒçÿXçAJµË´¾¦%3íÖm3àEò…ø©œŸ(%#8” >KºÑ¿òà À8‡f\Ú’ÊÇ8¢¨píÚý­ðW%@¾¢z-«Ž`R§.ìü†ë0ô–“ü£{y8 †2QS[§`‰hbÊõзj(Ê1Ù4ƒF¹¾nf}â¤'Áíú`‡†pK®ú~ð¯“Y‚ìõbkŒ¯#+8b³,FÇȉmŒÜÃfOPFL¢¯p]ÓØZäsÏÜŽ37¨~Qã‚Æ
+-z—A) '£\YDHžˆ}ã…Ðà`’->„ØÍDA²¢NÓ؉°­@ c—uM„RžhT}r õ2póý¥®£åb4Øþ½k‚ÞŠb¢R¡
+¼U׿æ—@éjÀ1iúÁ@ÍD‡m¡þ•É§Á•Ä—ˆL=Ýbs÷2è0Ëdùúî3Õ}AªûÒÚúÊÐú9òuq‹ ™r ­ØB[·TctÀ¨ïëYëÄõ`)¾¬&ÍÁ¯#,²}÷h,™ö}L¼2$·Ì\óÛL„~Y^2’Ýc9h(ÝÞýÒç:›Ñô
+Ǧ§šI·æíu×È „¸•—ÄØÉwª¾ˆšo±+/pj—¸_íá‹•„FL=ßû ­ir…ÙC‰raðb¯Y¹ãr8€[ØpP¬SçZ›-DPI‹ª¯{¾Yú4l߯7§ÑÛìA¥ZF¼‡ÇDÜíÌ»Õ~æ>QÈc Ág†ñŽŽÜ¨d ÖÚu}PþMÖ€ ÁqÓ…`Ñtú™?Pq$>é‘ö,=ƒA˜iôÒåUž®?H9ü°aÛk¦7ÜñfuH&ÑbÔŒiåæj¹>ŽÏË~à‡ÑÃ}4·ô… B*5X È“
+9 ” <q»°5ö¬ë™è™âêÒwk4çP£úÊŒcÍ4SŸShÖÐ ò¥v®zÍ(”Yý MG ^&P˜€ëìël&òä:Žö”E7¿­x€‘˜¾JƒÿûÓg£;3P]׈°­\甕ͤ@`î]‡Ü¢çEŒ¼~<Ól±´6Þ²"êÔd,
+® ˆ¦ Eò¬8›g`éjø÷û ;÷åüûçu5:‡Vº‚\æ!ˆî`… Üô.ÈzÂà{ ¨ŽÛر¿)*šB—h$ëïe3ì;ÀŽi
+FÍè„»ð%4w-ûN×'ª7n9aËÕô>¸Ñ¡ Ó!鯉TžˆàµÂå­©˜ ƒìû‰xÅ€¾ê óücô_]ˆ4ïØ1ÔÞÜ1—Ï™¥ïR’½Í<d݉aÖ»º_”{Q6b¢¸fQO¤7=¯XàǬù0-l‰Y Fa‰@³æûãŠmÂÅèQ8„\8µ5 f>xjnÁžå¨yÌ£`câKØœ{ýõ¹_‚§Ñ Px@*5ñ½˜îVú|¢ÿðèóÍG‡ÒŸ—:Ì´Í f;z½úy,º·!ŽdEg"ì÷6 q6ÃÒ;;¸£oD6­­&|½>£Þ¦Žóˆè©Óô*„,aF¸:
+WH®€>°1Íù£Sn
+rv¼Þâ=³ÿ•*IŸbáW¤O­=l~Š]̲%=ésP]Êó‡CnÁ2ê`Š"‚Eà!o¬ûNIÎ=± 'Ržg(ÌðmÆ‘¡ b[ݧo©™›c œ–àPb'âݪhBD1ãNåÇ:¤7
+ûth¥\¨»i;ÉLs[²/Õ ee.¶þº“oÄŒ…¢"³â%Û ô4 Û;©rˆ†rfžé™Q+(“—6y`^êæ!ƒ¼=0Û‰2URч#ÅëKÅDýpFYóÞ$fµB÷*b&µê(¸2S¬1Æ‹IDÙ#¢±¼»iŸm%0×Ù=_ç[t?yèäþ‰€q'EWÄóûÛy—GN n¢òPÂç×8H%c0e»i¦–ѧ½jùD£/Þ°Ñ¿X|ˆæ¼ß/}¡h¯@͹ô$] Bƒ°w°ânåq8Ó…½¬óBUä ›iö
+\¿çÏeDÝcJÏp7øC]æ£ø3® =ž°†QõDYîýV=KNŒ¨½ƒ‚UF¢£âß_ÿ¹ûaËŒU®b„‰4^¸füê”_´pM— ÝÔù~P¯XÊz&|Íèë!*ùè-0šÌœ*yn彪jF=·e^D…)ãöÁ;$Ñ™ñ7½ÃÛÊ™Ü
+ÓaT¶rOW­\ žDÐÁß2š–ó+éce%I£F° ¶_-”‡O eæX ÖõíD¶|@ÊlS
+ü÷ZO¤u2 œ¢zy­!cÅí ·½e@â}S»ªXä
+MÒãª0_ÃÂ=Ô*óa*9ééú?Z3¾³jšºÞÃDƒâbGå5«)ÁÓW£g@œ¸<T—“@Ùûºnö¿¬—K^G†ÿÊ·t"wŸ¾ÃÊNÊ@ÞY–“ ì‰ÌÉÿžç©>ß ö8Ê%»êôµê½tnˆçÁ–±j…‹€­´X•ã7E7§À.Ï.t*Z²Äë})#.œ2Éöès^—6¬:º£Äi-7íGË
+(Zumõ’¤E’Á•h¾¹|z
+q] T9”@Í"¦ˆÈŒ/ÊþâتÆIŒÀ-¬_šé“bÜ>k€}÷äpD|±ïòœ Q•
+@| —¯
+æ*›¡ ˆÎ]òÜ?pr "å™BC#{P·—*c{b@èäš½Çnʪ›Ži§òœ{cS
+²+ꑨ}¶zæŸ6MíW8ŒXe>bU 0†‡¤•Yrî¯é_3`ŒHàl‘±¦\›Aì´ç]Š`pÎóMy…ä¿`È^‰}O³p¥Pª®Ô4¼;ã˜)2ŠECFAð™q´€¹3¡¦z2=fñÆ»æÀe¥
+ß‹É6½ºGög%…¦4p
+çGhóSx¼ú•"ª+lÕˆkûA«©W«Ü,ÃÀrƒ
+s‰*¹ô )дç¦Nì¥~N‚|“) B6 c‡¾–â2^„QÆõ³Å‰ }D
+vAŒÉÝ“±Ð‘ד@ý\ÐGÙ]¡ååq–žENšØhB+6É˜Ê ˆ8¨ìW©ùª‹Ýc· Ô±ÙVODz֕èì$.°ñ^z΃.w¾±XK¬8-H_ªÕ•+fJ‚Œ‘&[84( ÁRÎ䵩:Y™d”S)™oFR— "I\7©ÛÓaŽÊ4c…3#H(ñÚyF+„H6£Ë 6 CF‘°W:îY?ÌÁPº±@ÏXÇÞ'ÊwšaãGFˆ;Š´Ø’Â=‘‘5¨{. ½±ï8ŠvN¥ HpÈh…ioÐRE-æ­"mÔFiÎÔ6vé®Ñ;
+‡XÖs”} Ô–s᪱ûöø×wÚãCœ9·±»aŒ±cfÊà9ôއѴ3@ÉoÙn äí®àÞ©Ñ&•¨ëKÄ«¹Y·¹Àúe¬ÊBÀKÜYÊàÏf¥Lª‰‰k=,‡9> À¹ùÓ(¡Æ¨bo5ìJ•äЛSLDíй°'œà™)´Å·Þm#Pý}PG̵¼xDÙR]ÕÅk"‰i‡Kø2¢‡ä@!´<)”üìw?)wAÞ'1&ÍïC®MÜàPqi±p:»ó–þá’LFg³¥ÈQÎ4‘€l)tøiÏo%“@²Ñ)“Y³;(sû%_KõÎ=ƒ : ÏÄl°Ë•š`2ÉÛK¯)8˜®¯˜¯œº²õÌÕI+‚õòˆ©èâ­ÃóRÉ7A´ºööKº¨XXy¿jòˆêj]É ÄmyªíÊ•Q²\‚v®·áĨ]ösá5‰5’q üÖ¾üø"ÖŠ+Ì/Ÿ55u˜þåö(´ú‰)ØS– œÈ®£áÉ`ô1Õ½ü ¦Þÿ² ¢ãÆ·_©-&¡-Ô¯©¬æ­¬œ|t¦ŠQKI‹À_ICT²–3Ãô!®ÅϤÝÔ刈,60¼ÏÔ¾ž²!õÝc*‘èΗ+5Êt_2ÖÔÔ‚°‰äažƒ4T®ØW¬ƒKê“j®ˆÈìÐg"ýž¯‡Ô_çW¼®
+S[7* L kQè @èƒÈJkJiO ´VÚ±`Zψ#Ò÷åç3‡eLÚ¸9ǵ$!Ó#Ôôgħ8xiÐ(BWËvî¾R§íKº½ )¼ù€Ý´ix›x"+éüÀ7§ª'Cwy‰w+õQ>ºç<¡8‘æ‹…¡ àïKE ö }ú{ß
+¿Æ‘Ê%š
+F 3ÞEÄ=q‡ø¶_ß–‚±_ Ì‹ÝYÁsÕ@Ü ýµPj,hïíúqð:Ðß­ u£fþªkab!Š_©
+]åB5…Ý9qzÉ.ävók,ò9© /ocÐÊs(®Óý5Ò ÅÏåóSC\ê*jˆQj?¢?¦jÙ€=ÿùY—ðá]ŽÛƒ…Êdd§³xúÈ55Ï»jÅü¾<ß,@™…`ÏÂV¯’†ƒ}ym6•ª.òÑÝ€ŸK~¦ã3Ê6Vš#|3ãBh]7ÓH»dÜ3~„ ꮀ¹ŒA(âxßXK(4E^󘱒QhU(;Ó¶Dœ]4qnêt½à2“óÐ2 ã™ü-œt!vârïEp¡¡½ ™·èyÎCŒ• QT¸}<R¢a¬°üQ!œ«-`¬ß³C·'ºñòmŸ‚˜±?ƒõÁ–`ëT
+hÀB
+ÿ_˜lvRv¼ùN}©*Rá§ê[Å"ЋgD– ìÄ]Æ]ýú²…D$<
+Wh-WYRЗ
+EÄÎ7 =Pîï“
+–Ñ4¤ÓåU!J¢ÈÄ°` (ïX´{ü\äeþlP©„\3ÇÎÞgDVäS­<öbÐú :SÇ]˜)Ógïí/Qû‘µ¯ïQýŒÒ]‚ÊÁÎûÂë¾ð•àªYÀDÔõÒŒ *$x‰ÞÎÃg@œÃUEö‚,¥ãÇ.KÝH+óh¯™—uÉ<}A¦(À¯&M/Ñ6Z¯‡¤ÞIbËÙ
+½`Ê
+€Pæx¡#ú£Æ@u5Æe—~¼Q¦%º;>wØÇ)lò÷Ìa/@ù£¹"¢&‚ÑbUe•I™D“—ÕD¢8iFRy¥‹}8À«š|G‚9"F62'…2aZ>"h“bD¯œeAwQpÎ’(zþ¾1 ç]Ð^}FDˆ["À…;¸jzî±i0÷í¼I/OåÚqŸ’²{Ρ6¹l¤i9ŽpW\™^TòV="hÔÌ àpæ@|FUùÓ}È"ï¥rg„1[¸3fÐ]!x˜9
+HgíÛ_‘è ˾aa_ÿ±^.½vEý+g˜ púݽaäà!# #+ œH–ƒ”ÏZUû\"® Šâħk÷³ê«õ•¼®©Ž8 Íb€NÌZ,±V¾Æ#ÂÓ^2⃌³SÕ¬s&jÔ~1@«½Ùæå7ŸßlË:oµ ãÜ*€Á¬û? 8 ½›Å¿0¸›ò2cI@À,#Ž~ªмºû¼Z`±ÌÍ­vôëõàr­f õû¼c µr؇¦»ƒÇ«²r«¨È/zúÀ:qj7Ö¿ ¢öÝ6JäŽç謸^¡«EûD7QRÑek¿Žxº…ºlá$ü¬_šg¸‚âC3¬¡¡w´ì70‘¾õUÄ¿÷“XéU…»íl®ÉŽô«hÒgŠl¥…±à2 #:ðus,œ Qø±°e¸Ú¦àº[ÈItb|÷$¼2?Žk`ÓͦyÃ|±tR%Ý¡{D= "Äsµ5ð-÷:ðj€
+1ÑÿÐ-éÆXJþCU¹
+ˆ-(£ë´8ér¡ƒ ¢IyΛ._ðÐ"Jêš@ÂÄÔq&ƾ*†˜:‚N/ѲñLúN¾ð›¹ÌUÒ¨ùxô/|ÎãGŒ29fÆ„&Ñ.îx¯" ]Ú"t ¬¶¬ª×Av6¾‘áA ƒKÃ!44ë²³@«ÁCÆ¡üì”ö~ÅEÓè]‹yp]“ÈDosi<™nèW‡¦j0¯U(·®Ú=œbù&<_·ða¹,­ÁKìû¢þÆ¿¿ú3”ÇÛïýÿŸâÿßùHzÓ£Ä?ùùÎb,¨Y<göÖ„NË»‚óññŽB°—QÔꊨ}¬õ]œbž~ZÌSOFPƒF°ë™u—…Ð0­géiDR-º(N€ø{ãY£¨L<ŠŠä$‡vOIž‹RW†¹£Eª!j¼qT…u‰þЛt‘&.x¹÷²nÖ2Js-œ eÆç$k3Í´´P>‚Š{Žª'"V·Âdµ•&«ük8¤ÅI切h¢‚›‰àáŠÅlr+ô)Ÿ¥å¾é{ޔcëÇ<ZÒ-ä¸XäÙ³‚r6Øcó"»†U÷xuånZ=”£› %(ñaDÕë±VÁ1=(i
+)Î4oÉÆÄT»”kN!öÝÌéy¢ŠFz•¾x€/ÎÛy¢†ÑÑv=ç½jqª÷ kksêbyóZ› ×€'Ÿ”óan±…d'_T"_¬OøðPj!»’ìX¨±2´A³¼Û?¶0:Õ 5òý£Ë²¨)ZW€ +ñ8±’:ûèpJñˆ\,ÜQ#íB7»ä@‡Âã ƹÇñ¼¸ö&$3æ@þúA¶ŽbØìU6]žš_©FˆØNfÏ@¹ÅõL%§çŽ‰®ˆŽni4ôöòhDèè#úçÕ„îŠÃrA_³ðÆž"Cc¯2¼pÿˆi}I}-#[%QÜ`5j´@Ýæ/F
+ê jÙYb;dAû¬œ¢œpî¡hl¤¨±rþryT†fxϯm -BPÆkdéÐê©ÿ¸+î“L)‘äRdL[­/ªŸtKù#«,:Ð3«µÍIWUÙö×K!ŠãAݲ^S2Ñ.œE©iüV”©ðÂ-Ó~Àíj i'Ñ
+oÊ@³HyÒsÈK×a1ÐestP1 .wp§lbW÷ÂœhyNÓTa)èll’´§b ¢Sót§g5DDÌÖmÄ+èyäG´Ÿu mtDo¯`È’ ÉÝ>ŒßÌé$ÏÜ8ÉéWTÕ‰¤è8°`è–3"A ÚËtÒ“ƒÑê$8¦#Eâ÷q$`î 1ô÷p¡1pqíî¹e<(ê£À÷Tn¢°®ºã+|ˆ›ÓjŽ, =!q„,©5&»˜ã²ŽŽ„t‹›vÊ^¹ë­‘¡oDëŠL•Š¦±´m…ñ¼áàÛ¬—²ÒÆT²r?»
+‘*sÆ4d‚@h*¾c˜¹›yöÌ΂È+i0s¡Ê‰[1—g'{±GÒÙÔå\Ëy—ö¬`†¦¬àm1H" ›E¯tr!­õÒÓØj0VKz_£G¸™*x@ûSD ‘—nÌæˆ(©]H‰¹ÒŠžˆà¡®s¯THo*’(
+Q¨xy*i`„¤VÕ«c»ÀsŽßä‹éY÷ev܇ÕTÕü:BW9[~Íß\ŸK¸ÏQFκ¯•«Žû|6RÖ¢ß<ç‡Gu=(¼âk™< ¯Ó[ËŽ4t—>áŒq¦aÍòéA5e¥=ïi+ÓÑX.Î:+¿ìbµa-xLŽ#É\(ÜÇÙÒ.ÚÖŠt…c¾ÌÍv¼,Å®¨Ä™¨]ÃG¢¢•ˆ¶q’´´%
+ê|çر$Q4NUÌì”R,Œòæh„©" à|!\Ù4#! _|QÔˆ;<GÜ}„?\ù¹Å)U*Ud±È˜Šªy'Ý6§ =úL¡Ûég®Š~¾J±8›z–Å7@]~µŠºÆ…ô
+ÈN²vᶷ`õ\@}·ÛÛ6-¯Å]Ì(ØʱæÀ8ƉdYà*. ÞnÌôôËxb,>èªjr:®©ûœ´ÜùAyrÅ]&νq’òŠ@Ÿ²ö©N†LÞšÇè T³ su¯»íú Hìà,wÕ\iø–ìâ´6¥´>jÈ@|$<¡“C­tK40÷ç®ÛsD`;¨ËÓÚT_§½#) „
+á÷H‚ýŠ·'m­¶iºK‡4Èã‡xóʶK?(4•/Ù!øøï*­/~”ׂîX!#¢<И2ÒEy0Àâ {*÷ÁÆù­Æ®%vuX%(3 pJéËâŒèjú“‘<áìC=ƒž&Ÿ<œ£‹'û„é×†í¤ƒè{h‡¯Vh¾`J«±
+Wõ@ß~dé—#OîÎcFÅN*ôn7» ¾•ä.
+¶F¯«»uÙ+(ˆòª6" -W{àWø9õ Âa0ŠT¡ƒpoýµ„‹º§OÏ"¶ü
+‰•_{Å…Àx¡ž AsÐÈ79šN„5Uº»AŽz#O‘ý}îõj~@“[›yèŸÝРA&´1‹8U»¼!µª‚RÁ%>;w .£dÊ¡>¿¸¦¥(’ÓUäÉ¥kˆzÍÕïH¨…,€dâ¼OŸ>&Ü_Ö€ë Œ¡ª¦Œœ
+A²^ …B8S`ò]w‡ULt¯í]PFº¡&æÿèLdÑz…ø·(q™(äìzûð.Á3ggAÓ¿:”ù|Z]#Êý}’-@Ô:˜ £ŽJÁ(P+÷Qê1WÍ
+Þþ„N‚“Žûè\É@Ód‘ÙT7Çñ›Xä!c*ºc1ž–.‘R>¡'bèiˆXv5“cÇþÛös© ³_ïÏ9I!T{D)²Œ‚Nì3UIk0›yÌHI…Ø™†šW¨‡ö÷;(~ ‚—ꯛ7
+Èá67î£[JÊÖe´ÚÃêQšeÝhÂTM7 ¥Ì‘‰€€n”àaß9Èv:œ(&£õèøxèÆÝwy…q¶- HÊÔô·ÏTÄP.1d1kC•}éÉ”ö0‰ÙaLRg߉ÄBè3½ôŒÆTY¬Wu>ÕÛ+a“æ!>-’=ΣÿpÝäWÛVõ…æK‹’,£z[¢eç*©-GáD
+]]—®Ö—¡#‰ QC ƒ ÿÞçyWïÃ`Ÿ D.çë·«ªW­õ^º<&ªA>UþEF²¶4ˆmnX}‹b›¶j'Œ¤6ZU½ø*È“­iD2!ÇNБ„ÂÌ\.ànW9â>1n´dMÒÌ„Ò^ó5%b…µŸ¸{•a*óe–¼Ë›Ó{Üh\YW§'°‹t ËT9º~àÄŽ±/¶û:ÒmBl'éôš“Sëªó´¿?*—Ç‹˜Þü€üœô ûðƒãf`”¼~Hw¯cȈA,ÈAãÎçCâeLÓpÆ»Ñ\TÈš%ùÄv›&é\µNò"‹ Ý®‘á¿Hz-.Qjcð1çãRoèÓð€LêÌ’ï ^;4åT’Ú<ÑÀm.éç#¿|oÐÒ‹_-áÅYåyì.5.ã%êR:@!ô+¨¡‰íLåö[Oe0zµÌ-›2yd“TnD¼ïÉРyu ‚õì3jÈFèþ
+êÔµƒêÑVªºùŠÂÁ]f5$áö˜’ᜅ@‡/¸–ûÙ  C©Îjk Ú]>ÀÚÍ"µ÷zõ8ðŽEÕ*[ÿÐò¸wólX‡˜]¾à²Ë ¯2*“uc÷±;~¢áZ¢ÝÊ@O*:œe~ˆP3¬3Ñ0&–Ãð'„E p)ÒK9ÙÉOr§è/æ+}ˆ@½î„‹{=;"ÍÁ‰)Ū8sè^i &À¹*VÖ#ê_Ç;$ÇCAØ¢
+ªé\ÎÓ¡äÜ»Þ$ïù¹‰]ƒ±+!pÒÆ´õ‡®±¦0bÃz›&x½ u•ö¼U )(o"£IáÈ;WIçJ».Ò8ŠÅ¢ÉDº£?C·ãYO ¥‚@ÏŸ¤Â¹ "ŠŽî£´µSݵ®R #c Tõ–;(¼S„!ÇÂW@ôÎóqcA Æ|D!Ý]÷tfH·É4)]»‚¨0€—uAcÑ¿:EaFw¡FÞf줢訷›#ÆÛTmb×ÑŒ>`’Î÷y7çêâ’·¯“ÜÔmjAãÜá®eOBÆËDÂ-ô™ncR  æ9ìb+w¼ŠHÿTN÷7­yÿýRÜ`Ô~[×»ñµîÈ1+ªz
+Ò¯§<ªfz\^¬Eâ ÔÓ¤°aë“è
+$°PBˆ’l:µè”~²«°:½
+s ØsAT^,楧 •VŠóKœclÇ©ÆcUýXl¬ÊD†´Ú¤@‰/àÓl׶h§…›ZÛ£ÌÄef€áÐБwêô˜&JæÇãÓå*È› ºjƒA¼²" z“Ë>T>¯k@±¾Ü¤±á’ÎA¬b×a²X/ò-äd‰:_|ÆCíÝ¡›7¶Ay»º[;¦òÁ¬ÉçUê¨Þ¹þᜫ¿ÆB&$–},YßɽÜåµøÿú8D5Ö)ºgL©ë¾”? Oo¡j””@ñx)•oïZöˆHºô+*Ï)÷|Â˃dyŒÇÌiÓØœƒó–Ö,RǤ¿˜OîÀ‡MáÙ/Üé³V~H!Ñ6ãAùmÄÃ>?Õ‚œîŸüýÙç?¾ûêÛoÞ}ûÃ÷_ÿøóËøé£ßëÖ ¶óã—ÏþòîÇo¿ÿ×ËG_|ñù7ßüôÝŸx÷µØ_~òüÍÿ?ùëo´Ðñòù?ø×O¿üç'õß_åŸõ׿óßíùÓß~Ž2’‡Nö³«Ø :^f<òÐÁ÷÷ B‡ P¿ù•*ÉHV©Ýlx3¿GÁ­ÞîyP©†²×T¦­I8¸†9Š¶½wÙŸº,:ÿ0Ðt16ÒÎ&Ð"ªp7Ž ?íÊŒg‚
+j"ÂÔKI£~ ·„ ÏG¹ Üxí¤ÄÃEpÒ‘¾¢R+¦ƒµåk£úsôΧ³5Ê”&Á?à4ïTg&9]¥;ƒ&›¼×rêoÌ S ¿_
+†­“ˆæ‘¦¶‰ñÃìƒÎšÄx\Šÿ9IS'D¯äÁ—OóÓѬËEί¢„Üe¦¹Œo|!ô1†Ž q„Û^þ“e@]š×ÉôŒBaJQ«©³"–];ÑÄm÷ò a$šC}¼Î[ËoM Ça_å-ä8ÒP³wŽG¸>†æš”©… E(/ÏÔ‚ùþÄ€hË1%´c_§É4LM9:AÁKŠÙF&>Í#ù’é¼)ñ¶ã-";ÁNšö·¯›íìoürš¼°{çÂÆnåw{Y>(CNÕ´s4-˜ÞÇ´¬²¢æ¨ÞۻűљuøØrK—ôÒ,Uõö¯»®_5™¶óÿzÃØŒ¹’Ⱥ‹ 
+îí–’}–õ=ëÿe½Ls$¶q0zŸ aíòÅæüó©ªíæÏ$@.ÒZ(ò[\iíL ?VÍíCOW²è1ÎMÊdtPWUÈ¢ÿC󒇈¿mÔóBƒÛcøžy׊žyg¤Cà<SÃF"x%)NhÞuS¬õ¡Jƒ1-Æù“%įÌ"Ò˜aEz³jòŒY&È,tFd±#N;¡±N
+Q2ÒO훃–\Ça!c¶Y2c
+QÔ É/‡‚r¡ß
+™!™˜ðD¨1##ŠÉ+ì½ÌÀƒB)dÐÕßÉaaÌ™YsÅC #³Ö}vzÂÅ<(=çÂŒ9â®I“ ˜ÎÀ øð)¨$`°ŒMºµj#+¢i ÙVXDq„F_pÍÚ߬ií§éá©5fÅ™û\åw4ˆ‹Aq;Ï©ý
+ÑÕ¸Ü*C¨vl½W0þ½‚ìøïï`ö¡s˜w–Ô „¥çêÁÇ(Va6åç ÀKÉÊ›Ÿ?ýró’
+Vˆ30Û^°ŠÊÇڌɈÄw°Mô<S9ÂF¤¬8[¨É6ÀÁóá',¯ B”dá8î¼×Þ²8…æCÁà…6´u}/õvýÐXÛžüwÆ^!PmPEÜÝÖ ü(</hQxÓvpðD @â’$jœ?Õ¤²{ÕF4Ï”øº´ñTÐ
+µ§äEÒšB”«Ð*56b­=ŸèÖ«ör£ å;ÂÁþ*À5Æ´1ϱS„™‘ Üf!›{¬3‰ä‘yƒ\G²äCáÏ ÑÁÀ8táo€fó+(½E°‡eà£nÏü•ó(SN§Ìu‘Op$ÍÀx†ñB)øT0×ñ‚°É.êg}pG´QŽ‚l4=ÍHQo¦ú åRË)x;ÎkÞ+fµ3¬Ì*BØà‡éŒ TŸN<ƱjÜè
+Œ!ð‰Kd"z^;Ù£QÕ´"Ɖ £ úDá5ñg_^N¼}x‘9¼x)ÿ:~x$/!m']×ç”QŒ‹é爀ÚýÕkæ6§‚Ïçµ,[!Ä>F‹V†£šá¤5ݤYV1 ƒ 'ŽEàZ)ºë€d+{ªüÅ;¶¸f!‰!뺞ý
+r„Žp¯ntÄêuĪR?´/±¾‡ëî…Ì°8‚=¯_Ð$†ë9õ³Ø.£öDžVÛíìR‰‹‰Î
+0KôY- ®*…T)û2àQ>d#ê¼Ú¡^ƒý^'ò’K¬÷`9®×®‹,ßÿÇaË«<±k\àö›/- ^ÎèÌ|¡KCüi›!ädÍ„5ç¸&)ûQD,§ÏšS}œ`ؼuÐOE埌êm¬qºðHD ‡1‚fÒ&\kQÆŒ€;Öj÷8~\aH®ºŸ3å¸d¢öæ+¶ :¨ÅM°Øó¸|a¦Æ”tŒ‡‹ˆ#Jq#á³÷FuEÊVÚšh Y^Ó¬¨”`‰‚¶¦±R¡M…3ƒæã:b¥ÔXˆYín5š«qF9o€Š=‰8–ˆ”ƒ% øƒ¼7;(gZ åKŒ)’2gïc áqèLÉzr[æY*µ­íèaÈRL»LzÇÓl–~ÄÙrŸ¶£ÅæÃKñx °œÒÎ8ÁG&VÓÜ1“¢óy8ÅŽÝ
+hÐvŽ:ÉMCÕ]B‰ˆ¾"²ÖÉ"•‹õ'ÆÉû©ì-SßåÍtIí2€3 wÕ1
+³FDÙ×õÄ9Êýu<RŽ^³:À‰¼1©Ž±Q§"I^rNNß©y6{H¶Ãeˆ›¼»ÉUÆ@ó JÙmžè dRDz(;£ìí¶ˆ°ˆ¨v
+ˆÃw}`ÿ¾ÃƒøEÍ—¬Ù¯‰Á3"í3È\ݹ¦Ä’ÎPÁˆ–OÛ+hÛŽ~Rö4¨ÖZÃo…1v8ã¤n&’†3NìÄç”YBåTôœ³¤Ä30 ƒåT—˜BA7Ö?SÜÄ¡Žý Ü)ò ÐÃ
+H‰Œ—Ind9DOwÐ:àéä:kY·h WU÷ßösjHú®L ‡ws3£jkùñ/Ïþ
+™ÑTg³ùÑz¼”¨Ûjz:‡È05‹ÿZ µ˜2ŽÙYºY“¾×áoÙæÝÄc´‘žÁÞ Â’ÍÃøÚÊ_³ÏèfÎ1/(̇4.ú± ª:,‡Ïˆ ™SÌæÔè 2¢–³µÈÞªkï#fÏ&þf*U OáŒâTªfÁmăø†&•X|ƒ¯é8[™GNv›ýœXSš4nÚVýœ4›Rí§"1C´õZfAš®<tÚZ¥½rd·žF?ÇÇﵓúÈé­£ ¿ˆf™ðÙ.q{êš„tÎÌVöšsvŠéá2§÷p¥/Ò6ÄùØMÔµŸ“¡‘!2×½íŲ:غžk‡kÞ‡¦ùZ'G>ôÑõ@ŒZN&}Aú£µ)ú®Ä€T”®§D; &°ÄÛÞª)wœBM£ÝnJêàA­ k9ÞŒƒ½\š3úå#qì¥#9wŠ»L§—6D±…€Ñ6{ÞkAüþõ¶’—ĈAñØkÁ`mʤªÁ÷óãï_­Í× Š%‰P; z•F„†PM_ó ­Ô¤‰>‚¿áUïÌy;Ðd
+%§­"ªæ5¨ÇîNæӜѤñk&LÇ Î+ã@H}uè‚8dá³=AöV
+Ñ…–Ÿÿ¾ Kh›É)U/5^0
+ƒò»
+…ªãB_Ó“SC„sšDŨ8ªè¾–éô—yay=å£'!cl¤Ñ&H:û¤äŽ?¡“ÏÞÎVr$dpÉo‡Žt4÷‰aä Y…³ UЃ‘ÖÒ‚„Ú¦Ïy¶‚:áàDyvr#Ìì`:ÊË‹&¹–1¶ï´âB#4i©o ÷À*(ßœLY ¢&fPÐ?å˙ת3¢Òÿ1¨ªÓ©f”KºAëÙž9©CƒÈžeaΡC;ç`¸bCÚ`Ù¡ØÙá:ZÒøU–°›(°3æmxž* n­1 Z{/’κEŸÖ7E€æ¥Ù¹!ÈQÒŽ£ón…³–eqÇ
+ÙÔ²Æ<;ádè,2­ý,ƒGÂí²ï97é+Ú–£mˆÝ/¿·q/e±D³Ìûì„– /'‡q{¬)‚ÀAê‡ÀÈV³¿/…—XÉSÐÄHŽëç!†ÔÐI2![¾þZ Çghq@ÉØ•j×8.á@_9Ã'VUƃÕû†pOÔK€ !-3Èð eBܼw˜ðPŸÌ~¥£Ã‹r4È(õ³úKþ
+xÅtT‚"+È>B„Ñ­Eye(
+ÑK+÷i^zÀ¥˜ö·ÔIŠÉpAe¿ L§r)Õß[!.Ä æ*æš^ßJJä›]lË zøÃ@lÛ“TAO!¢ŸÑB™pJ|ƒà¼|¯ªÂ÷˜¯}äŠYˆPÀ¶<vï¥IY»UçdoÅŠ˜OçˆaoÖùî÷@Rʶ+Xëcn(HV{ x·ÂQˆ+d/‹¸·J1>_ËÐné­’ŒÜâHÉkÑ©W6û™…~Öïÿ¦?ÉUúñ‡ò*lG.éü§G†2Œ6B±²ÕˆŸÎ:}EÚBL)OïB8qZâyÔ°HåÃÆâ´eCÈŠ(ŠTˆ^Ï‘M„ª’ðûÑEb.Q
+ab~¥=³?@öNv¤Ä³x³ÃG­%ùx)z‡ XŒÿ<çE)‚Ö%‘aoÕ0VÏžåK§U±?²µúKu”aîqÚ õ!tdyË$S“)ç%qwú Š–Uwæ鮃ØZq„ t#39Öùæ†|?oÑ$I
+š<úh ”Ÿo’¿ß€¼R:9œYà b•ž¹2Ýéo ˆaòÍäÌ_¥lò©«mâ[Y¼ øº—ô®‘5Ç•í¡‰¶&Õô ¤†Ð ”YIî'H¡F݈٥Rë5Vý@¬à_Ó *×æ’xÁagüG¢4Œ¹úBÀÂø˜9Iò L,NÇ'‰¾ƒJè84êÓÞ­£ƒçâ"qGŒª°Yrõn#rHEì¬{/&N/‡%5_­ô@[É÷ÊŒ?É
+$K¯Ê$ÆÝé'9fÌéá•GD$¥›}Æx‹oÒôû;€N3c · ²gÜyVU‘ôÜ%øÕeGãÊÝGÓÚ|+n…–Y¹6<zpB
+í­ø!‡¥€ðj&ãÊ-§FÁ{Ñ@î“ÿõ
+.J°z )¯¢+ôRlë*·MÞ dný ï²D?¶œD¹u ï
+†ñúVn¤Ö‡–Óæ ¹ Æ“ákŸ~Äc¡‰†^„h¥íÌûö529#„ßù˜ËºãC¾ÇÐI]p ¥‘çw±…IÔæžæËü$²Ì6c’o
+ØÊZfÎFxœöðŠ*HI¹Á,ýdyfñ;: þ€&T¨7ã€(Ò#…ˉ2?¼‚fôzœÅqP¬°"
+T‘±!\39_¥›cZG- ‚m1A£½œ…£Ã'5Á£„QpÀÖ:pBy¹"±ûµVß9¡ò˜]>üùóž@ SÖ# ¤îu0ž+óle§Nép¤âé¾åçù8IÚËì ULH?[ñr-yFJ<Á¸Á¦­F \Y©iÈÉ®eåÌÞzçíVUA9r24ǬzT7OVf¥¦Üç!†L÷ê›Zm`+¢J@ì×9ÿKy™$ǹã@øï>ƒçµßÒ·ðV÷_÷—¨¶þbE«á°TÎâ
+çVÅ”ïPߊ ¼hÊz@ #â‚zvŽ«¼%`Òi0툷Ò)§‰¿Ü,6Z“d#‚i†®¥åÊêzq²)‡#ò窦O [% 9ìŠZ.‹˜É$¢¢„‘öV¥!ð
+½Û¸*4)C¯ïð‚¡gOÑ{€>Þ¦‚äånUhdE
+»Ë+Zš#SèÔÞ97§©ÀÑæËŒ%³‹£«ýb’Žå,Ëÿk¸[í†q=Û|E˜ÜÏæÌæ~¡e”!ß0ô@:d³ ±Ç9ᬮÎå´ÕŽGäÂáÙç´í*¼Æàû:\¢ Ùïô…eX×´§áòDAqßÍ„ÿùŽSÿ©Ç›ý”Tð¾ÈAi—<ˆ¡¯RNÒ òé:¶ì è÷Ĩ£¹©ÄvÜ0˜öÄ”A¦0µùƒ
+Ç d%bÿèe»£R~Ó£ì·@—¼n÷-PÛ>:ÞStóñTd[H
+„š$þf¾ÎäU“¡né@¨NãÔô¸ŸÇÔRÞýÓŒkg€†xÔb+ÔN"€íi±Î»‡$¹ØÜëˆÀ‘‰¦’DçíQÓ„B™˜©ã
+‚êa—Ï5c'ð˜Q‘³]S–CòaBî…é¡&ØäÕ.?»3ØHUÅõ·ë2ŸnÊ´B9ËØ”ÚXÛ¤ìGÙä¤^Ïë;a^‰J ê±*_=†ÚTpÕêóø;Aªš2<@0è˜Hrä<å“ö ñ8 “
+¼bè
+Øqà2÷öIw«Ê½È au©ËqƒV.†ÇwR~ª24}Lªn{†»¯ƒ³>`}²ïß>d÷2—T/ß­
+ ¹df`Ã1ŽUÁë`éž-Š‘¥2Ü«Ÿ#C I»oU£óþÒºœÆá;=g게_N
+^ªHm·ªvMl¡>õË…që|'hV§w«|ÿ+"X‡N'L—r¿¯"Z€ÜàžçÅ 1Jet\ÆÉü IÖÛiÃ1°nÇœñ–$¿F[à > ]>Áå©ê)M¥c¸‚5‡ š¨ÓfkBc*¤qȳf≥KDª¹êÄpˆ'Íâ1Ž%žáeYU½²NßC)-Ùü ž‘ësJtESI|”¨áJS²ÒFlTgd
+yµ7Ûyuîx¶z™¢‘ú-õ7ë|Í£WÈ×<z‡mø#5*±Ê òªÌ c¿Ä…øQú­_‰ˆÉèåæi¾WÐTÔE×á ;!?¬øÈߪøëz«èãêž94½ßl1Áßs›%^/Œ%ΓíáÚ%~zZ*ómz?E.t'‚ÒD‚Ehkú|ÆPeÑLjí“
+Î8žÎçö¡O&ÜeHX¥‡v\Ö©H»çd1-›´;07§s¸±»×ëA|êäøðs™Gß
+aŒüaÒ;¼bÝûÏŠVUi‘©àXdŠìÙE“ í …¼$çña3>½º¸âPúÆä ³":îË ¦Lm\‚¯ –܉һ¬"ÏÕÄæºØ=
+ÎÓÜ éR;@«Òt~²B°¡5™Fg>(¾ÊîšÅk«÷vaFöxj³žšAÔÖ¡|$1²^fʸ@zqâƒ_¹ £SÏ[ó—i£çó]节›:ÕeR~]ÅåúxâåRRiâV¯²W ÅI;ï X‡*…ıƒT
+˜÷ 
+F4Yn_§cdiF.Ö1ÍVÛÖZo y X ¶Ìg+\ß`UÝ#@”zÏrI¾Žá5·rÞ»iXp‘k/c’PÈÿ0^îÈu9^÷ÀتßpJ2¸ÆÎþç;
+[šÊ—€®º~Œ˜ñp ^dÍr|<Ÿíæh ûߤàãˆmº±Lm+‘ü-à Ez!#IÛলâ(@¼š®˜}äFñÊrZb‡ÃcQˆdæ Ø3¾p,:Á»OâÂúçBm´Âq ¹Ñ*&4… d%X×îK.—DÓ‘É“ÛPÑÙ¡opãû[ºl°8r¬KÉÏ·?Þòû¿9/ðVÁî¡‹ýØ
+ÖzÑ~ŽÝï¾(âŽl;Pìqɶ
+CÏ LhBUÂ8‹ðJüú,ò*%[L »¬ˆ‰7EM’¬c¹r\™µÏÀ$Й¨rÆ«%È•ÿžÙä5áÊ‹æèF¼ÚVx PÌÏ·[Ñ%[pÞ'ÿÉJöSÄF Ô˜]o1Ïd–Bæ
+ëËËIƒE!ˆŒÁ­\£B7fEÈ¥avA„ŠÚ"aiÀ±o
+7`q
+³P{j/J~¨°Œ*q]—c_9ø‹V0Á¸ˆ”åå
+<=Â/ Ñ,8͘QÂþÂk÷y¼ÛP\’"4%AJ†L™žÐ[èÈPrh«hÌz;E/`/ÀJî^ÄJ‹#zÛ¢\•ØÚS˜ÂáMéÏ—A³
+”‹O`±J¨Ñ’¥ÂracG-ÎYüÏZ
+€Ò*²R̵Ʊ’À–F¬1«TÝ-3ÆÑ=i°’^1Nâq¼»yï‹}ó\:n2¥/ÙÃÛs}ÖžÃï%€„ºqp«õXDr†<Ê_ÅkX¬¦-ŠxÐÁ0÷#-Æɵ+ˆÜSµ?‹t?de![Nu'zƒSd´…€Ø}c5‰”¬Ç™$&óõ~ (€˜ÜÆ:
+œ”sÀ›cHÞ`i`®¶/Ë`
+¤~?–„¨ã6fY{¬j¤¸Ù¦ÓÂ,1
+çá„wø×ÄŠ1N0 EN=‚MÙÄPëÍ@Ð(ç(€Žx‚Þ–BûÚ*èeU¼‚b±ؤ
+’QÙ§Eöˆ±J0*1N–öítvøW¶ö±½
+æ÷ZE¾¼å¸1¾1NнØ
+H¢ÇÃQTB¤›œºái"@W„
+ëÀN+`ñðîZƒµe 2‡%J´C’ =B£U½»ôó.ÖZŠ™gqªcYi1ÒÝk”4yx”ƒ 7®òHû’r/nUœJÒá"ÒÉ\ñòΛ!¢ÝmÑŸd‚AiëâK ')IÖÓF(Åc!™êRl3ÎÁÒã~¤û.Á¶´‰iÙÀ¿:¼ËÚ=8ÅŸ×Ýl(Ÿ '@ÇöÆ0Àè¢s\ò/EV"SÏꬣ„_myúÃ7¬¸²×1ì0—Ú)ÄÃñý0;°W õ¤¾æUÅ_µ†`Ãd"©$‰àê†Ï½D)… ÞãRâG1ÅMæÀî®szÕ’LŒb£fÉ_7íb9»—T…9$ƒä±¯N‡Þ
+b"G§È)%1$¥«]\¼™WƒôÑ"§dé<"µ}5Èåþ²ä—0(Ç–2^h”ÛìSdb#`!w
+FÊæ6µ cVwïPEC¹‚,ÏÓírqìC¨¢Ô«UXºžô%Àzâ[ WÒ¬‹G+WŽÏ­aØ88êl^e_ˆ`©ÇGºTG&GÊî'x@#ÇP¢hf^Q¦ç1ß6l#BQûk®·É¾fÂ1ïçÛo¿ýç-½ÿë¿o¿ýï ‡ôƒ` †¢v¯i·ÅÎÈb¬÷?­Ò×./^¤æq­ÅýÆ»J†ô„ëÂ#Q‚?£‘h'ëûÎ:`äCAëá¾KÉïo*šy -Ì—Öõ; Ÿ:b &€º2˜b1F°¥•LV~˜Æ< }–¤OR<Úð\³ÅŸ ˆ>ðù‰Pè6élaÍß-Òi"KÜFˆm¿×3góŽnÝaœØPaQ5¤í¬¶qVIñ,QâJfÝÑ?îЈb 98ÊÔ…F<Ë9°ér–[mš¼7c™åVò»¡ñaý`çd:qû ˜ÁìQvOÜ!nÀ+4X6•¿Ž8‰ÜcKsœÛO^%–ŠW#ƒMA·©wT`ß‹ü*¨ŒÆb(B‡;Á5Ýp¾ ÂY»Ã ÏE—q7û½¥ßéc¿U´”ÄfÔ-kc>®»÷Pôùý`¥G›?XÍMá”WÙPgqÌ°4ßãç¢ùCßYr4úú‡ rf£¡O߯‘/‚ iDÍóaÿ\´¥,fCµEŸ/ŠÚHhTjï”ßí"f€1¼D)Ê…©qä*á»|oV¦W`ÀÌ¡0¯bP£FÞ\½Æ&y‘´²ñrâ°Ï”ŽÙn«Ñ%ò*H,‘ÔOÂu¢„‚ڥĂà¸-Zé[xûNo„M‰B;—aUøiƒÎ÷ç9¨‚ÿuƒÙÔO5põ7ãÿ)/“äÊm%Š®À{Ð
+^=0.½‹šJûŸúÜLPQ"“–ìÁø¯®@ ›Û°CÙÂAè (€þ)¼
+rriÊŠ §¼°sPÉÁÓgJ¹Œ["LÑcXBÌ“–/¿óbòű!u`B²Fsc@6¡´ÎäôšQ@Þ´ÞÙ†¨Zõ,Ëç žØXB
+ê‚ÆUŒC¥Pµ‹]‚´ƒwIRg1™g©™Î%€èSx0<f™¤3êÃ9½èÚ˜×Óm0*Œb*²5¯t Ú,&çÕ°:•ú¡”
+ÁÔ°ÆäÏVù—î˜DЀwدêÇÜ/Ã_ôÄÇž#|T“r/–;ÜçþÔµ8€(–·;æ[TâF&@ÞÅN5‡úŠð]~=å>5·«Ü§/xR4Å4rÉ!Ë[¼ Iþø~·R¿öâ%‹pA5 ïœ|JÑæÉÉÞAgÜ>w½ÿäNÆe½dã«8ÎÕYøEfŠ\‚+¢#Z‰Œ–q3Õb쪑:G#éVøÕœá*j¼œ9iL #Eì †‡ |g2Z•Ï¾šé "ƒ=mˆw}
+A`­¶; ÀaC³ÒLCÐÌ<Þaú¡[ 4…É=Dõ§´c QAI‘Ó:ø/§uz•):¬›¸ a¼Ðuë½O”ˆwñZcç‰Ös´Ó·ÂÔÂÑËïÂhŒÖr—›ºü3=ÆÐæ’¬:÷3‹¶ÙÖyÙÛ=`YÆqÉóñ9d@ÌÇ|( és)äzžs+îò¥Iþ©+Kٴ°½Ñm˜nTwQOÒf•ŒJ“x•±¿t­yU­6Ö}½EõÅ$3±yŒ…h´°KˆêÚëàœëÄ·¹N^øªëŹîAPâoöÉd±¹žÄ¨aÃ"ÕÐÖÕíT¬Sù/<@i'ã,Øg>€Ê«Â3 +”á¿76©8ëÕ-¢êFŠ¼?+»h2†m4†Å‚#ªÏ”; ¶Ž-Òóm”‹lDã­Crç~UüÌÚ«s~Mn–3''s€ðïì]aøENe
+H9ƆÀvKöŽ2tŒ}+‰W–
+BBl›¬;Œ‹BæµM5€¨Æ¡ê+…ç „ˆŠÙ³±Ÿ“–1á¬e>”ŸŠé„‰p¿21q•iÊê¡Oë8‘Œ³Åˆvع°+?E-ãk /·Ôê3èëµÇKéN8UÖÚÊë!,B)„z1«!L) yAˆp˜/šæí:h<ÒC¥g
++£‡dyl^ÆEp}&sÔðœ.u…!4ŸAïàÿ%B™Œ• )¬ppŸzRî,ŠUÌzí{HÙí¶d›[ ©=òÆ á>?‡UkHÃP*¡¬º×á¾xM¦G;3?)ã¿·Ó<]®›b«èêß_2ÛEQ#c§?ÈÝŒd²©fÒ:þ†Â4¬+rk˜û§¾ƒH³’íY,šOmUˆ*Œ* ©öµ› Í=”æ2T¿sûvq'®VŽ€é%Än 5Ÿ9.¹G„7å’o‰ºð%-'ÿ_Ä
+Ž‚ jëGûÈo«^&·A1Ð}êçØèòrã„ð†¡?)k¼Ý{ ƒŽ€1Üͼîs±±ï†)¸èe„vz]…ŒÉÂã«ýSlS†~áõ:â|ü—ÕšÜËÃnV*ªÅÄÙ–-° ­2j9“2½”Ì&í3DUBëã ¨îËXrû"ÙûKl7\!šòÚÈr2™ý|²â3rZ<%c<§Ù·òe>ý€¢9//1dÖô”úsÌmí¢ý
+)F•á9ŒkÈ:„å 6É¿tÇ`Ó¸+KÕªs¿ 2‹~×na2xSƒ1IL“­­ú—®¥DÙh?²gñRÝ}#mb£šÃ}EøW®¾Ÿr–àש Þ /=„ß¹_¶a ‘Piüˆ6è—­·™2—²£æ€©?|b Í!¿–W€ù'ÀD qûØôþ“9G :J¼òØu«o&БB£â“>bŒâÎ-ʦ’Zl‰jnªåßÐõ‰”‡tþ†åèåp3¿hi£‘2wÞ‘7åw¸Ž‘›Ås#Ëaºzˆþp/¿ˆømòJkæåõé®ïX|îŽ,­W÷R0ç§#cbsæN 11Ó»Ì
+†ˆä®å^§dœY¦ÂîZ‡éTòi³>”Èñ²¥ˆPÙlV~‹å2J«ùôkðMšWÞðæm¹cOvIÔæ£Lk¶JÐ ,–©Ú0§ %<À I\£=»I
+p«´uœ­Žœ ÝÚ(q…ü Î‚ø>ŒòKÉÞš Y«&{çhkÉl9…t¶X6žÃj‹ØDÒjÞ ³Ù§
+=â²jð½D’ HäÐßï{èà” Ñ/Ãm¸3Ô/É2…lLÁ²íwëª< „™a`‹‹=»Ú'ÙÇ¡u'"âA¡âÆÿ÷GUï©M‚^0Ž|ì¸zO‚KT4¡ã×u¾žCIÖ>ðRH阚
+‹G*ix«‘ìS½àñèߨÖ$£)§kòÝcQóDâKM~ŧ*#?þ¡‡•Fsl…êó¡¶_SfÔLç÷C7d¨HÂŒXå% $Vé*¡=ì×TÆ8k¸€Îߧ=Rr $±08Ÿd-Ââè5JcC¤`bxJ뎔Š2t=º˜êðGûK
+r¨ËîH£¬“R,-׸WyŠ8Qþ*‹­vP8#RšÅ®‹ü…|ïÏ~ˆ<†}ÊËU85²£ú¶w¶õ­„Îbµt¹Øž†3ñWIÄ¢KÏBÚYélø?ÎÅqm;ß^’ñ…®f®ç‚VbñaÒÕÁ.«,×À*¸†€&³¦0%‘Óƒ±`VJ#Ï܆WäLü~›Ûâx¯º-à½;÷5¾õØÛô?Gõ¿ï@Fi1,t•—ž9qÄ›sÜo·Bàâ|EòÇáI¦‹M3ØjE4Qq^æ’,Š™EŒé/ÉE–Ó"üJ5Î6UØ•Ÿavˆkªt,vË=Sïþ=hDz¾…`ÍÜsØø ¼ºDÛì"¿‰ðù½ñLœ¾ô¨ k¯â?×?K9@ˆN¦Ìt9JÚZµ Sñ
+˜´ÕvÚáëà$[Ã6u8°OÃ(Ž¢*‡@×È^Ñ—ÉzE°Fèܱ”!¯wñnÒ}¦Ê8^¯äŒ¦=]Æ™·¤Õè©ÉüÇ%’ötä×Æ(¶Žâ èpTÏæžÕÔQŒqvmÈ,;ÃZ€¢(\CwÏa¹ªRZ;R9—‘U”Ï(}/igc’c5rÇ„6å $C»—”Sñ§Ì´µãšR$/Ö9 †ÕÆf ÜG²cL¨„Ü̃¼Ú~Í0Êø:]*™™XÏ«ÿÙÇñ½ækRX` ãöpâʼn-*¡€WÑxEGÜÿÐÛ¾qœ_ 35E«< ¤dÞŸ±Ðûø%áÞOvd‚,F_›@DÃÎë!žðV¢/%øAyÁ(ç@QJALj'ÉbÉ
+´…xÇ`©@‘Ä%MµGÁˆƒïd19@†uÂiõ«7œÁ«¦öwõf¾4@H
+KmçÑ ™Y¼^Û¢I˜çRøíêNê¯ÿyXšÒ¤HDA‡šCU{9z•Ž8³èò⚬ÉÂÜ¢ ¡éo¥e w• »t ’Û‰P„–X|–›h·¨3ðÜ¢¨—¡ÛÃÊ™w§y ¦/O]j ê¤ó^ è
+ ¤„Ú/ø³…¿wMÇßAZ!äcHÞü~
+B¯Šë@R%´,JÄüM¢¾yîQt8¢c
+F‡ c[ôºŸ±£ÚdÇzÕÔ‘âÀùú´Ì·ãXäk †20A!ó
+5e"6.`FZÆ°ªâšWˆø`üF’†Zô°ËhxO]X!Øpí¢ž5–’žù9„Á.kR˜]Bv2‡3ôÙ–"+ RИ´—ø¥DWaŸâ·æHÜ7çðm Íž@ìþ5ÓE2k!l¾y^NÚ\L2Я͡Ä2mƒÃúµÃ·’ßç7=j0 S;D‹c##š•®X÷Û›šVF¹¦ÌÖgÜôÚš&ædþ]ap~»5¸¡¬•@lå:§¯¯ã~=剙ǧ<±wyÒÂŒ{+ÇÃe pX7ڛƽâ÷}? ‡Q%ÊÈ _öû¿=Il§žÎoÞÑ¥è¹àÏÛžDñç/ÚDÑ> u$¿k™¤L¥‹yZ÷¿´…#ät¨J%lÒµÖ›‘0zIFðK¡y¸Ý´0ø.L}Í>¯n GL
+½çɼ|(û­¸JZ»HÀû,Ž5gx½ùÌ ï„¼ñe^| J”s \C½YÎ@`™>qÀp3¾•#Yò†ó5à±6¼>¸ð’6øž˜Á|¼J¦'‘US‰›à´çºÎË1ÐÊéæJ£øšSׯ¯,§¬ö¦ä%‹ùvŽ t^ÞoEŸoŠ˜+\4²º·œ›y«€Ž3K5XHv{oyÂFaóÅ›i ƒ‡*;LâÝnj“¿§=)nD2vóøı æߎ7ÃüR²¯2NYÝboŽ!¥¦F”ŸChED…‹›pò"@† â„']K¬ÅMIÌ$¾œÎ¤˜¸ D*]~ŽåožNÖ¾€÷ú¦¢Bù>zñ³}Ï"›ò'˜xI†—àC´yV,H
+¨ ±¡ ûI`‡®½«Q‚–o[Ipä©h]«s—@¾£ ÌPOƒÍUC”ZãáÐ=ç‚þMGei6O€ œ ®ù·I¾Tì‹'`C.:Ï~9ÌàE8fÀ
+½h¯¥œÎZÍP!æ­ó’T‹—À‡Ò…¹±.Öœ+»µi”§ FŽµƒÌúÑUìHa”Ã1áˆç€„y,™I!±½f^‚ à²|Jx ;€ÐÇr†¨`cbŸñ—¢oŠ&·Yåf<E˜wd˜îg' pVÌÅ*CôhŽñ¸iÁë˜<}%“.^Ê3,| p¸Äý¢^‹î…-,"„œ¹êôsxv‚@k”ë¨þ8r¡#t0S©DBê.¶Ñ45M°+Ï1)%”ÔÒÉWúGü;ÙS…Õq2Î=è¿) 7·EQ¾‘I¨UüW.¬ O­.?9èÊzÄŒ|+á'˜~­"[Ý^‹2«MraÆ°ÖçµèŠþÉpðè²1Ö9”­ä'ê~9ž¦½8¾ýÆY™È9öâÑ7AåI#so !˜¾óô·Á?<=Cè'¸¯v=§|ÈÃ6Æñú楤žœ½„-ÌCƇ§'’6E=„uû‹Â–ˆQtkÇ,þò¿*à?+…qG¦d±PŠL°!þU/QÎÑ>€žɶ
+Y¼óýŸ{~NÄ!qÕk‹ÿ¶héÕŒ\ºùy+â'I=„ÿ3PÜ$†Ò*ÅÑžqT’=G3ð£»1DôAºR
+xYôÖ>ßÔ°X7^‰@5O›ìCP˜üÉöfv”m^’”,‰¿âÆ·1m†s>K ’
+JÎë—’}ÚÍؾÞë›s
+±Ð çÓ!LÿôÖ­Á¢Û¼;N‚Mç©ù¿-šdÅ;²6æÇu÷^Š>ÿfAø“_JÑ’péºüÏ‹$  °rÁWN¥„' nÇÌÙa(Âh«åé%ʤ%>åaÏ«–…8£>5ƒ‰%þ3—|˜Î&7K¹†‘’ù`~q… ™f†G[»„ïJ¸õœg*âh²Ž `or“÷aCäRó¹k#ÞMsF¤%+ˆ&ÁÍòÉ0t´Ê0ÒëËÉ\ KÉ¢öàT0T¤Øpk‹—cNt«óÀ)…Žó¥DJP6è È·vãæÛ<_JtU•L%µ^·]Ï©0_OW›Ô‡A2@\µ<åä‰_#ù(+dcÁ+åcÓë„ÂÚ‘ÈSáýèéòs:{>´ÜGi3i¡GÚ”G²2±¤9ñußÿ¹Ö|qWŸ·Vƒœ¾†£øñ¹â †€+C7j¿=ûUFvƒ¿vÏ}'`ÀÄ«Öo—<õê1Ê›î±w˜Þ¹$|oΙ|kuwŒ¸¯FÍsðÈ <HËâ"¤‚#ælûI‚9‚’XX܇B<–Åé” ƒoé¸}{îÜ‹æ}ÿç²»]¤F–"/d$ÇMb§!×R7 QMnÐýaòý6x¤—]t‘öbIz„xõ`µÑ.·ú1(»aA‡· {ä—’™É «ŒòÏ<ór Éj
+\Í
+>õH’§I\ì/¾‰…”‹3}°ÑZEA`ÜúpŽ8®ÐâîÛ|¶ÑÁLr¤9r:ùh0ElvŒiŒÏ6š
+ÀOp «àÈN6ZPçªS‘£9Ûè{ÑaÞè°“ Hõ»E×õ{gGåã¿)m/†¥ 
+eæÍt°‰Ð´un%†O›ýT¤Ò¼Ô›ñì*Áyñ}½ªSxWùÆÊÍÈfÂ^ò8 B+þ©ÊŒXR0­søýSp[Έ…àÂk„X­¤Ø±P G;¯vúŸ³Þùó¯C.•Õç3Diý&k ü‘D£{(z[x6¸GO]´/E*‘›…xû‚É|9'^^¥ã*YƒXÇÃFtMAðxf—¨YZ?õc
+Â’Y IrÞ¬˜¯1Ì_@*1cî­€ZÑ°Á:oBzdl@Gz*°â3(ÀÃ%_ÔÉ…Àù¢ƒ©GÂ,qÍêZr&¨KÑÇC‘¦‚Q.§"æMoðœU§ò bŽ/p5䢘JÖY0 ²Jðaß’Z¡]r/­¯Žå( »Í]ă‡å¿¨Ô+Ne·é9b²Cäç< ÅS²ºê9VháùLIL¿óp
+…€÷^·ß¨M s0u™»‰ËóŒ3•áDâeŸùdghMXŠsVRD "ðÜN ñX€£.-6ójØÁ^`MK?½ŠÈXQ”`v‡;~›LHž›;Jˆ–q®Å"‹ª{¸¢ì/ç €†CóÅÒ…Y
+X¯yÀÞrœ°èÂ:*Û4½Ç(Bm)‘B×ËñðØ!PÑÜÈ#Ñ!IÚ
+ÕÄé y*ÝqÍ“pD¸x:¤âœ„c pÅB¢éx O¨+Aõ”ü2IçëÀÂmH¯B–£jûÝ’=ÚÉCšjBˆÀ Ì äÿ!z‰ÌB¤Ê %ŸŠÏ$±ù±®zL|£‰Ãm(šÃ8¹@Ã9·"³E™>Ó°ÑWæ:ñk…PNŠÃ>& È›`܆bú¡m²@ «„ÝTeæ¶4²ŠEãA#ü>‡¢ÿŠìû;Jüa¡³¼¦° yaÜïcJðUž¿™`S ¡
+³=Ö1 ÄÙ0‚
+ìs]ÌLJrŸz.º\T',…]Dû¶EÚoUf>,½Jà›:‡üÑëe ÓgÈLêa¡‹òÉD!´ræÀ <m—4¢ Ä=XØ; Œñ\k[ôO}Ä?Ñ*âvXù–k9Ø·óz(!fï5ƒL„1PxÄ8ýPIÇ° ûS¢¹JrÄÏ£`¬w·žžxÖt8…DyÕ û3–q‰/ 6)6hßœîc
+dåìœ,Qár\jK7iò¡­¯¥´rãP¢OáðY¼…õVŽÇˆš:ŽZÝŠÊÚS1¨V’º<Ò£·F¡
+LK¦–\ÞŠä1׈V’DoSA½åÀiÛø±n\†¼!Çl^œ˜Ã]ä”ÖËqJZ 0q¨X=Ît_ˆ£®åᦦ
+gÆ°ÌC ÓWt}êÿqüñ;W¥1¨(¤š~\ ¶± +Röä8üÔ © /*iãOf(;hO¡ •ÒË<8’Ä?ž-&¶m#4ú½¡âÂrÊöoR •Á¡—«Ó¼60/.ÓB–I6/>…*† l›ÂMÙ9ðr ljZ
+îs*gª¤@£]žâsÍbõ´(PþÜ%6p@ 8&6I@¡¯ñY]ÌoØ/\
+‹îñõyåÅð,Râ÷H+ÑÓE>ø
+R‹ùÓo-Ó‘Jdµ³† âÉ—F¼ 0„œ¤áÌ~Gksµ•&Z>·áoFÛÒP
+W›àß%©Êû 9J%~°¿7ý:\ >‡¥’/èmgžrýØ=Jh&Æ=±æûy[â[Í^O(IƒØý(È"u%ÄÚ×IlÜ%ý›#•]ƒ‡vx(É%à%[cJ}ó³¿îc‹÷ŽëÕÄÄŽfëšÍ|ôØ1E£|8/°?aè4˜£ï5ÌÑeÙ¸3¼®4­_%&íÇF';.å«©r€Bèˆ(=hþò‚!!4%UI±÷’P_ÎV6m!QhëhŸõÁ
+ì/Á…žÂ&}¯æ“r dH`*Wð˜}Ø0<5¿wâ
+ÙI»î}c• óŠìl¬¨0¥+ù°_ÏUŸe÷¶D`à3¾t·!D‚÷ƒp¾£¯ùï8°aÿ
+Il‡÷7™‚-Þ°Š ¹]â;dˆäXŽ¤Y[X©T®×_ˆ
+^”£1[‡'iÎïõõ€F¢1ºž-z=%]
+4£EŽ@GA0©Vlf ¿ƒ±#=w[«§‹z0"XøU‚KÀj…—³Pûä|2V®m‹1=â Ô»½Âš¡¹ƒc¦n²îºNÅnt ¡Œ€Rƒg!,¯”’Ü
+¿ÍÍ£7BÙ/'x“<2ÝOïÀ¥Œ"“Ke¦€²s,÷mÏi2×—æ0©ó…†Õ CV¿ï™Gß¹<ºÍ 9Ñ«|vçãG‹ Ô¿°/r®É7‹‰VÑ·Ëðïû•À`èw. ?¶n$jÐxÚpW+®««äâƒ`–Æ!å¯aïÍŒFc¡|¸IžGäÅ_LâZ)Ì-Òépèw½_pgjè ¢ê½ lSz´z¢¡’)oï¶ÑjšI=û8ÐᎾC°{‰ÁŒÕŠAò¡«OpJ$(Ëé3dÃqØ}¬ Š½K„—k— Ð¸DvKÖÍ›m÷,úmð¯¨H*Ñ3â'ÉÏuÆîa„èP›GÀ,Á„ÙýéX±L‚BE5ñß87¦w™Å®‹d«Ûm†‹ñ$jÌÝdÐÆýqLiŸô0ÒO¦ 9¸ÀçãwxÉáwX>ŽÖõ™Ø8—aPd‚Fß(eÉéB!G Øír”V¹Äš&0sÆ…|áÅ„ èû;$Œêsñîü/:#žÀº¾ÅkZW-Íø¤‹ÿ]Ε?›½
+É”fãª?éJK§E7©$‰o$l–ý(îX“@¦£Œ.Ë=°=uÎ@8ÚLÙô0 ªsU ýP'â:K¦i¬E?'ÝŠ„y݇)ðo_ßA¦¹ ¯®gsŒ3r‡ƒ ¥õ¨ ‹¿B¨r»\ð¥@ÕìϵèÈÈÅ—!& š)õUæ‹|Ât'Ø0\ò™±ð2VâK€@΋æ%1CÝŠ>¾)ÂÖ@.½Ëg8C©è?
+H‰”—AŽ¤5 …OÐw¨5¥8±{‰†eo9ÁV=KîÏç$ÿ@W¥4Ð]ý*‰íg¿çîC›DÜ~mî÷Z[5V´Èʹ߇v­¢cXõ)6ºG¯
+nBz éÚêC2îaÎGEJ1»}}KÕ(Ñ:—õ¾@nµ—ο2tžÓú¨uÔÒÆ‚Œ"b¡À&DLGE5¼Ê¸½g]ÌõxŽñjuQ0ãzMç~±b± ½G“NzÛQ6xïu•™Œ*V[ÝÙ áÃ"±yŽFÕâ¦îýÊqó&ÕIDÓ­™OWñÛ®Ò;xáMÑ¥0gL•ÐÐÒ"Ƹ%"3GE©xµýàJ!DBvÜ¥’^¢u\…Riµ™{”+n!ÖJ'Ÿ¾@݆ÊI£É<§20Ô¥ÇN± ¥ö^kï behÞ]lߤÎŒpn»nÒ¬Z4çÍ Tù…×û(ó˜P‘F±)EÝ2\8£S†Å›Ñ[P· ›¢;%Ú ‘~“ÑKíiš”L
+MAR¯ãŒøDÑ/oϘ×KÎü~\Äÿ
+„ÂBþç@t”©Ó‰¾­Qd|8B“ Áå!-„¾•Ò)†§ìfÆ×EFúlŒãviƒ§”4Ae´yH
+=Ìp•í‹,Û¾`jp9/ $…ŸÓ€5ß7=ƒ> w>&røRé—ü†餹:ò£ Þ6¢ aÓ!mÍÒ¬BÞž¶•z]vãž& ™…j ®=99N¦Hú{ )åzvFɾ:§’©O‰éWdÚîËâÚpn45”˜ú`>Æòq+¦5,M´Ô}ÏÄÁƒ_6ÍçóÛHßËYQhÒ‘ú@÷ ’j–Š‚ážò}9¦“ƒÈõúx¢4oÍ‚µÕßð:‡NZèa,å„!ø^Wc{3&’qíG©ä¥¸_í]&‡š%ówàè!„5e*h ³¬îy;:Öòq;D&ƒBé‹SP1eq“‹|Ÿ7µ9#r`iMRž7>@âX‘ôÇ>=ÃÓæ˜êDU¦´ìäa²[.0Ñ^ šY`g:‹\7=Ò9JUr±Šè$W÷bdä€ x¯×=9âÚäTæF¡qußC¡±
+ß:N†N—uŒL\Ç`t¬–GPL‰@ö1Žå|€¬›ð`…ßøìŠüᘃ{åÔVõÚP(­Xb»¾š–¦âá°üç½kZC˜Ÿaä^³’ƒÂã2òÛ>L<ѪÕOFõËô³Á4wÔè¶loæ
+£Êý1íì C_ÒJÌf«O“¸ÐBÓYÖjØBPûÊ—è+[tgô>Çö•å>I˜:Iž)·ÓK©ó-_Gv+á,‰b9pàÞyB${NÁ¹w=BÖM%Ý7Ó'Ø^çØ=MS«9°z_cŒqM;9 ¦¾
+PéT]˜n-ŽÉ1–Àsè Ç Ÿ ÿ-ÔºéÃ8ᱬŠ¦ë˜çÇ`àé:ìA™ð9(K)bŒ!!4Ö¾ê19|Bâøº3‡ösŠ9y œ\4´+õ±
+õXðçSHsxÉ#÷(LÓ
+ Ÿ›XÏ}Àº€U ÌÒÿVéj:í)ì¹e¶?#œ kvaVH"–ÿ;ÞO 4ؤÂóÆüŸ §ëA?ó¦÷ùôzO9EŽ¨r‰ ƒ¦çb(r=UÇ+c•MÉ ÷#è_½SÁ\FÊÏ‚²¼Jˆ¹¾Ÿþúø™è2 ¿üñVn¿ýùöËßorûý­Ë(ÀŽcúÖ˜4TÎÀÁ4r’ ¸‡ÁÆ«³(!žÃw—ÄÝ:øŒ„º´SÞöaÛ¬ÜÒ %}ÇÆ;‚6=ˆÃ„àf DB·8´´ÅÈ:þsLˆà2œ× ¥û1mi¥[êÇ„¤9%‘[\âûŒÜSwp ÚW—?€>VzX0˜éÆê”üÊÉ”n:¾5!X\Mã¡i'$õ™˜Î,A¹ ²:¨íl‡Ò¹¹ˆÍcÅÄÔä"¶_•‘™c]LOG'´ozñZ2†6“‘õbü ~¸²Û´´ø½r¨”ÉÄ\CsàjÎæS»|[ ôQéKE·3­9B-ýã|ܤXqÚwÛ)è…¤òÁ¾ÅZËf|¸ù´ŸñE*½ãgʲ.¯~Ÿ)IÅÁ˜ñæ3¸ÁŒäAþåe’ÛÖDÑdZÀ¾gê]xjïúÏ-’Fü^ öG€$JlŠ·n£|êØd¯E7»­"C4& [éÙmÃF¸e Ó×:Ii© š3[I•)–± õØí¢x€O—Tk+I3ò/N˜ÇoÃ>uÔ$ꟶN’™f³x $0jÕ|ÿ:²§"em5íM¾•£€ƒZÆÚÖ˜Cbž‚_ÞP/òÐ<XTdS À)::·alá ôáãËÞˆïðâÊY#s žÞ8V™1¨³ÈÅ,ê
+b`p7’Wâ³Å¥èíEQ-š©H‹+¼f>€r”Ö`%‚Ã@ãç ÷¼JpÜi‹}>’ô %)MÄyð˲®0íÞÐ9<~i¤Õ›+¹±²º§DÚqlɇç/^ÉÚŠñ„þð)ù‹uòPÀ Y÷Þwâνâ^õE îŒÁ
+MÁt$rɳÜk>^Ô˜1¦7WÁ~1kÊm™
+u?‘1ÎJz™ZÆH|•4.Å¿¼w8=)öÊ6ŸÛœ`<9Q¶ûâèf²B仄°›uK&dÓÈ̱#h,ßœ’wøîëÐ
+fê_~Jq·ÚL,âÔ!0ˆ¯íUk¨•úšª m KgÃUvw¢ˆu=•pí¨–öœóé1íKâùQ_” @Hò%¦ùûÇ)’Ü ÛM–%úxQÔñæû—P=Û nˆ9þʇûb—ŸEt³•ðF’!ø£ýW9Öyœ¢5èã7B%£Å{ƒÌ
+ ^`nŽãjœ§Ëº™œe94ÌÎ)…ì½¹E—N¾y»]j>~q¢‹AìBTaŠzÒdîÎO±Ì@»úñù¢ˆ¹É9c|ô…L@—˜ÈSÒmTWz¦ž~W"0I „;Dœé)š7¡XHTuØâ„Ç,Ä#^ Ù:%‰‚Õgi7ýRV=äÖLÿ­@Û0
+£à¨³³Æ”ÅÀÃ2Úùø‡Ë9(éüÂelú‹û
+'¼[k%).9)Õ$h Ø*ÂÆ1±qؼà êB×äű)Ø1•$­M`ÔÅ.ßl«Tf8¤UÄŠYˆ’¯³uø/k(GìuFŽ< ýIcPBhÅ?zˆlÚSäg Ò$I¼ŠxÎ ?‰çµNSjJS>üÃNÉãq+Ænì’,¿_9µ¦Jxº¢ÜGÛ–zÈnÀØ Ê*°`Œâ1ËA)üˆ!åR©ï{£<` 9Ï Yôt[eTºËècßöC¡K0/.¡ù¢„ç)æe› _Ä|cH¹hŽûÚ×D›,Ø/ÛV„<n %×Xcè‹öF/m~ÄkX+å?×µP-3(Òî"¥èâÄÓbë`®*ör„VLLxÝÀ£
+¾–Wa¨Ç‚Ÿˆ‚(&Xîu:)CþˆÔºŽÜ•Ä”'ÚÒ?€D9YpÊnØÕåª&kŽTÌ
+ÅI9‚·Ñ€Ãñ¥´Í AI#òódžmhÚpˆÍÞ½<þ[
+¶½½½(ìc †{ƒ¢*CÆðC|«H‘‰bLõdåYY—W–Bï«Ãˆ
+cVAŠ¦ýôF<† -.,Œ O¡ËhîžnI·­à¿8ƒÂ¾x¨\ØŒ-(ç™ÆÉ6É:Ò¦~°W‡ñð­'§ÈÞýAö£ÞÒ‘7zL[鈾#K §Hâa¾š5
+,—£WÂp4 %êÝ¿ü¢¨<†{RJ³‡¿Ý ¨#rÄ$lÀåãlÀíꎹé )ØB2¤!ŜǞ‹ ¤™qeÕ‚4oM`«B¶)' ùo z³¡{E »LÁ#B`)Ls³<+#tV‚¯ÂðËîŸðÊt ô`¸-GXŸX½!ˆ3Ëû4&\iDãoxàÑXõÌU•—¡[Ø•UüÓoLë"oŒË"éü›áïEèf, ‘ìôæ6ø·ESw¦¡ÓÒ™Sƒ:±ÌÁÌ%nÀ¥S®ÃJð ‚
+4}c•¸Áa&ûÌfË`|¹|ªÏÓ“
+Ò(õ©V
+Wž|^û|Q¤žÓ5ÎÆ8¨$b÷5v¾ æé,ßLù}J ñEÒ}ìA,"îÀ÷X‹wÛ‰7ûÌžv È'Ebk«žŽì†úåäjX‘o
+]¸ä蔬×ì¸QV¡ÁãÕ:—¿Ÿæ†ïV7üÝ›sGñ­ÃÐÿ}¨÷ßLÌÛ L¥=i#¡Åü¾³Ü§[0KÖÁṎk£„f˜cäãé…JF-²é<éh~hPòàÅŽÔ³(‘3,t_í†÷寡A Ë‘Ç“»͇$%º+ÆÀÑ2ìC´‰yG-ábñW—\Aè¶Õ„Ú8PAºÝ|' *[§¦Žßà€vfnk+Æ!UÞ¹Ê~rp‹¾=ý‡W$¿ßã`7`³m–%F]60Çš:žcÐú¾:ÃXÎxØ ¬üBMÝ]fº¤)\´l?Š» Q‘¬æjrÁ÷N\.5y²ìå]Þ… ü6êM–(®Mº dZV˜Ü£ïAK¦NN](EÌ9PÆEŸØ0x
+
+4\[ìkÜ6rÍd×]c’Ö1ÿ{î“W8ÒÐŒÍ?§¹äýZ39²ü¹Šˆ1Ê1Úx, A0*¥˜ç¥H¾fƒã÷:£r$°SqêÄöt DœhîÔ$…¼ ¼€‰EoúÒSq+‹#ò‡8?“R †–áËœXâÇ)­¤Ðº1öXákàR Å û’ëL8#^Nä×i.Ë'1„Eæó?ÊË&¹ŽÂ'ðt‚ÿ¹Ö¶oÑ[ùþÛùd9Z¯PaÍxz¢GN±H ‘ÈŒÔB4 +‹ôPsô%ÒYšMÌFšâsé€ÌÉ Æ—b[‘Eëɯ½z‚ I$Èc $b¥’D¥fŸ¿лµ–£S¢D”ViDÕùS>'VTMRuRDh‘ð
+:^ÄvŒ†?‡¯gÿ¡x\91ÕË!¬Ui
+ܬ,fB‹£œ1Õx!¡L@•ƒ¶ôß\Ë5¦ä4 ‹åíÒ
+vÒ?`ñJv´R+%%mó ìH©ø¼Ž/×¾æ&óŠQ0oÊ v… 8^ˆAØ;ç ²9ë6­®É”†ç@34Ñ(~:/B34œ }ÚwyHûÌéœ2žLr1v*· 0@¾Wë5äÈ
+™‹ËÔ`Ô—٫f)çÂómT(û¶àÆŒäˆ+”_ÔØPP†¯œs8×O®¢Éa³<[O> ˆ‹†²Ž,[Æ…Ó¤Ï ¦ŠE­åñõ€Áâ)Íj^ì Y²èBãä%–±RŠ¹ø’bL¸“Õ‰3« Y/9í… Ñ65ãp|óðQ'¾ç% Ì‹ÐÅŸ8v©éÚÑsdls ÏQСÄÈÜvÝæ»ÙÕŠ©äÁ‚m¿úùñ¯°WWþ™Wi(-õ¥uÕ«—dg0ïIù┆¡mM’Ÿ]ãï\ŸNcÓH²œœ7PÐðÌBaGófÔï97Ìl ¿ehd·Kî7z}ýdD}’³\}r#/‚uÖ%zX1­¹ú$ »jróÔ*-BZqÿˆ"_M\Jþ¾ðsiÏÃ÷®x†RB{–,ùkÚ›=®ñ‡ kv ØY:Ì¥m.‡0²åRûã¶zÇTàf;Ùb÷P3XkýXŠª}'7½ºŸÁ5†];N¤Ö†óØŸì°Ì±d
+€/bÏç6Î!{@îÃØ'h… ˆ#*¡xæ¼@oœÝUÆÃ2Éi>§–.Çhîÿô.ì~A +662J* óÛXË«¥@öÓ K™ý„Ñ-óᣣ¦tñçÆg@˜X¶
+KAþÛ©ý¥;†šsYæ«Õ}Ìý2äºN$ãù6ÂGé'$ŒÉª†B§~ïÅDáÚ |ä ¨ÄMƒ[“´©æ¨Qßû;ïí¾òΙà&ïÜ _tç° U’[ˇ÷I0½
+÷ftø©Õ ¡@ ¦ŠµÓó7b¬òJ¨VÁ°›µ?=/R:Tjí4“)!ÝùÒnL™Ydz>ExèêJ冎ÅA“Ó¹LfûÑ=íA7>þ• ÓØ ã8zñ?©z÷}Êe£IMÔ©#B¼i…¯Dk/3…G.™¶}ñ¨Iynß+!ˆ‘^ôŠääTfÖ¦{AåÚÏ}ø»:1uÌñ†dåC¿ûaç 2¦‚¿¼¡z¶süÚŽu2P•c*mè
+`ÖÚ† Ö<«}ö6Ô»¥Qw¶Êõ¥¦ 4äPú–v>QÆÚûÖ„¼ä"~áYüT»I»=ß8„ÍÅü¢i 1Vh•ze TO•¥šÙ´¹_U”ôÌ¥#ÙþÇx™$WvãPtÞƒVÁ¾§‡¹ OåýOë\T”þÃkà§ñ‘
+†Q¡h©ø‡`)^»–ÙE˜}£1’T-N8ç29u¸{‚œª îþ¦ä›ÁúmŸoaçxÈ‘Æ—¢Ï7E M¬C
+²°«[ 4 iÀ§Q¬„í¯‚°Ôð¼Šg&–g­‹qÈÞlòQÍ>ðr ˆŸIíBŠIØÔ¯IÍG†˜š¤2æ·’³7ŠÛ€Øï0ç€Æ$™É‡*¸L—9æ¿<á° òJ€¼ø†‚v4 ¡¿½û—2à ás.~#G‡
+¤¼ímJ6ñè·{À¼°ïõMë±ñKcNo_Tôâï(×`'׺%
+ýÆže¾’R—•€|v˜ù·îþ†ÑWZ…tÕ«.,’Eɺ’ño¬¤'ç$9dȧ)ÔnuN~W’M¤° ÜÐèuaúX ìB‹Š>½dlŒ6×tÃEl€ Ñí:]‚Xê<-iä ŽÝIsÉÐê
+A§®ìÉ`Ïêm2ît.¬ zàOg&0<²s( €Áh¤öË7'ËšâCÆœá8_JΗ8[—¡¼ÖÃsØÀ‹½•Þù£È3P¼´À½Ÿ¸DG¤=ýSȲ6p¹ëÊ»NĉñGɱ¡5SÁî#¶™k€EySòÍ®ÊÕæ¿ù [GÄe-áà¼îÿ׊$yY2MØ ‚Ž03ö0—Ö\h˜ä^eá‹• j¶;ò§ïi™ë:lªçÂxhÍ‚/¯¾Ve¦hÙ€ç}’l¿¬š;3Z 8ÃÒœ’©œ$ðO?e7"ˆ‚’OŽ+òaMQ‹-AÑŸ7Elyt£…Ÿ§¯¶µzýJ
+.k1?EFehK;%RtúEDrq#—q¬àŸMŸER‰‹é¢ˆàG#_È/¸²$ú£¢—Øöù¦†¬•‘‹(i—f·Ù% É{¿”âꦕdL|Ïh«’°µîN‡ã’L®tW¸GÎ(œšWðl¯D‚’©
+`Læ%˜D¤Tˆs= ŠH=6lª<óÌÌxá?)ó ¤“NØFWΰToŠJó;hWLàéÛ€ÿ²ä+LÌã±
+rB[X%P"ÞKÈ!F*bÛc^ã4|aæj=”œéé¥è㦇³´&C8ééTD§è
+΄§BÄÌEvoûkÈäÊbxØ 6¹ô­¨éÖ€Fš9”Á±e,ém “xð—fÏï
+ȦɈ•}æ„ÈÀ¾Ö¾EY!ó
+Ú€ 0ö…ö‚rm–zOSü<DZö
+ìC·äFK;÷ä)Âð;¾W½C\Côµ=q5,kÁ`âb é7ðÌ>LCEðK(x]%òü8xÐå°‘?b*]zä-†άi±ÝŸéˈ¥q8¿i*ÞŽñ`á§Má*Teaí&Œù®v¦ÇïðÊÂéÐŽ}2ú ¨pº(U²eÑ¿b’=¤»*Íè(š>yÃRƒk
+RIlr;(ŠÌÍšrÏ$± ÑV‰Ì'ç—Üœ,¸ãþ±ï¿EÓñ܃tl"çTÿ%Ô&õy˜„ ÒK™G§v½ “,¬H—ÍŽØZ‚À“úTùuŸCÑW‰ýü‰ÌÄiБJ R(ÞkÀßJ39þ:åº<¿ƒaÀž÷]áj¥P¬ð›J:\}Ë6•mf˜Q‹”M?Q ±‚)+WÚ¡ä÷<
+&¨ÒDä¯Ü|ß[”c†çMÆJ¦@ yÄtÃE¯Òá¶s#“™‚2Vn¸"AÆ7²8ºùXîü'E×H0kALÂùõœNÕ)«¸{[$E
+‘Eæøzéd/$‚Pcľ·Ã> ìXNÈÏÓÚ©‚Õ
+$XbKÍúûVMsÔñ¼Xí¬4UóÉhý™Ex^(¢šÛš0.E‡©_{-úüÉÖÕv£
+¼ÌÌIPÝ ­A!¸G`*ŸH 0‹²ñBœ ºÎÖô°!¿çIMÿl”–™4´{²£,ES°PI¤ˆ”…/ ”ÃMu–ðë- ե%cØX\êøþëR&%ÌÄÚšq³Ñi!<
+Z[ó¡èsAgÀ cšÛéK Á$Ü€•-«¤hcy5.¥Î¬a…¥^ùŠÁ+ñÌUNëÒ]l&À´î'5¦Òù)g•ùݘ¡€i¬=
+3ÃbKwØqˆ0T¨Ó©„{
+kûÜ
+Q¬Šº®¢\„k'X ds#žÚ—bvé+Ê qS>€Ÿ°ÞõPrb§—’c‰”œÀDŽîÜôZ¤é
+,Á©ÔäH+9«š[
+l;¨¦ÖáøË´bÒÚÀïô1JÖIü_LTj;G^¾Ã <¦}—šñ$dͱ*”ìÈ9,lò„(á2Ù×E‚Adž;½Ab0®ìõXÔÄ ¡¢F^½éÓ¬±É|ÛùZª$î¯8 0,KßhqéùPôyS”ØE¶1ƒ&:|¬þU(W÷Ë~û˱0+ZÔÚI4)Sð‹þr¦&%Ûu¬¢Êo5åQØ`·c´øÉá6ÕFÓåìÖËun-Õèž"ƒA»ÄÈbqþÛàoŸDÂe *$’¸
+gìj´UQ¥%!š»sPè
+´€¤›¢ú`BâØЗ¡ÑØD#ä9!Î"{®ŽÆ¡‰¡Ü|Éh3dŸH˜ç6A—,’:yÓáåue
+?˜”lݵɦŗ(á¬]l±áfÐiÞ¯c[$wÇUa›¾³rco㷢ϟL÷™PPÄËE¼; =ÄÇ?çš¡´9Ä¢*Pˆ2-f·´IË,ª9Í’$/ƒ”ÜÒ²À4xH´ÛÔ c(|äGa{ZX‡Á°ì²”àóÇT:énéc³âÀÕ­’A8ò,íP¢£?²^¿˜¨ïßA¿q©´›ä—ü(=XX– ®zZøw‘h]£Åû¯ÿ/sÜØŽ$Š®€{ -ƒÈ)r0_&Ý^A£-Qfï¿ÏÍP½Ÿ€
+T“H@!`‘,E ;„©&ÛÉ°ï̪¤9qN›ŸiVÒè×´ÎC²´ rõ„Š ù4d ÷U_OT¡óÄ›rråĽã÷ÇÜÇKê6€÷âܦøVagÎÿÙ§ÿü`]>jL7ú"÷t?ìo/¤k(õædrŠ0L¨ÊQ×´‹Ê)#2ªŒØ ‘vM4–>ÜåÁ_©D£í*ãÞJ@Xƒ}æ.‘$(Jh»-¿
+MŒ> ÷`¶ÌW õÑ.bHR—@$Ø F¦qŒeä[|"L:¯Êè‡Ap†µïžË? D#üŸæ9E G½X­"%Õy„Ñ ±¥mP¼½lß!ht‚ÚÏö‚^úþåMG3"¶8,ÏËðµ™±Ë,éÆIp ÷)™Óvê;8înU¹ñ
+6ö›TVˆ
+'aCû=ÈQG<zH jWR÷䨤ëP=QDV§„vcd(YÒ,›t0dI˜¸×8¢®#jQnk†t´#Ë :?HIDÂÍ
+v‰ $¤d§£ôŸ€ÔÖªû‰b¯
+tf%akÍô‹è¨'æ#Œ†TÀ÷ f±:ø”¤Kö{€Ö$œœDHí"Bôë7é{á;C¾B ð(è´ Lq–íí(ê}ð`€BùÖÊ *9‚ayc
+‚x~¹!
+&ÁfV¡ì­V`=æÏòù¸?!’„ÿ¼Š…A0#nE óq”Ó$Ê×N1œd.“¶}Pp]]V‰o!¢L¶‚©áãœÎU· ô§df·-,‘uA[ [±ëñ ¼4_\X"ÓK°æ¶x:¤Ó°’¾ ˆ!ê1¶ç8>–®æïöîÐêͪh«°ž(vˆèÁñh*ø–Ab.ûx8&  ZåûÅRØUH…“%ÌxI
+''é®,ò7½t
+a›"š2ˆ1Ë¢C†/KÛÙ’£„À„.“ãy‰“¦Øh ÎÄGŒa’ÆÇõxA_;/•µ¶í+BŃoƒÖÞ¡O¡: iÜý€ì˜Öt­fyT,Z=öüA’±¬}gN‰‘÷`†olÅØ õ…1\{‡öc'öM=ÂŽ]ªµ5¯——ˆ55eLFÓ=†©©l%êÛçhž#j ºÛšŽŠTµ„çÊ €
+¡5UVŸÜoV±LµxdP²0üTœÇ0\Ò4Ý®3¥hNXŸ€ì…¬›Àfˆ½ðæà;\Úðòá«Î[˜á) {Ì©w!TAmßJ«-Gì%=øòÒ¨uÕ=‚g([ïÞk`Nd5K_JknR·nºÔFÔ*‚D¢µ}̵ÀP+K/Ý„Øwûô±î¹tû~Èubœ—\ÏÍç:¿÷²Ü—àVÛß,ÓÃαšC’úÃß9ŽÖƒ´Foç8ó˜Ñ`à¤.¼á!”~)Ã߹ɽ˜Pð±YSD†Ó¸v¸| p÷í~ÆëDy¯¸ ¦ŸÍe¾½¢\¶Ä+í=ä¥EšÉ "oÛ‘-EâÙJq³ŠS!| …ÜÜuSÌXr¤á­›Är
+lº¹]º„x çsç1—±sSºN¯Sšë8þÍ.iåþø÷·!ÑÙöÎOpùü‰ÐÃE¾‡÷¿Þ°Ð1³pü<®‚ÕšŒ)¥2«ÙDÐ’_<œmq‚> J†ÌèÂ.Šþt®»}ýäMŸ¤Þÿõß·?þGž(¨™ÍŠ¶þ$2våølòÿ¿ÞjH®Ž.WHctuEK©p¬d¤õ»AHlœ$Ê*W£Í>¤WÑ„ìêÊôGAÌ}©s¤QDòº×ý0(i¨%%¬ h€€k¸»öã K ¾~R'U?¾ÿù†þÄÙÎãðjò›E?Î¥Œn®+(ÆN"“¼ … ";Þa”i
+fˆñ3ÔtLø LCÎ?0¼ìòaºqx Ø>)ˆ%z'Û±ƒp#ŘNfgƒM衾ç1±êºD¥VH˜¦¯ò ´BôO aVaßÄVó_ÂB%ÛAƒklò^œç@’ÀœûŠÈÖN—RÖM¬6¾‡÷Ø‘„UK*46qŠcÑ+¹ð0íçÐ$¬k^À§"Æeï"(°B0±&ËX>DYÙ)–,
+4Ô…Q4±„lÉ úz’K•’ŒÀÕì&¾ H#°¦,i!é€É¬†÷
+üwÑÝy±;Ef™Dïép
+†´ú¤m…L)@¡qŠº CÑ+2 ¹ÆX!|`ÙGpê*¬ hÀZÓ¡šVF‚nÌeo+)ð ´BøšïÙv8C˜5GC@‘$Ó`RÓ}YÓ/ ¬YÍòEY¶ˆv÷yŽŠÃêa¡¬èŠaé)+!ÉþÏx™%irÛ@øºƒNðp{¶Ï¢§Ñý_ý%¶§«Y¶B3šn7$rXM¼ÐÙêQT°e]¯…ü©]Ù‹ÄlÌ(醨òáàÝüVÆ€òï*ëáÕAeY%­Àªâ_]²19zæi œÅ2Ío5¡š.„—%))åÑL z»³x_˜,•dÆŸ÷†F Ï°à÷ Hæ$/Å` Á°:¡²s—Œ”Àh¦ç¼8üÀ‘9tE¯Nü¨ÍK€"sG„‹c«Ám@gÅ‹
+b#Î^ l Ø&~§J•0š|#ÿQÇ‘¾¢¯äñ|£±Ìl¬²{¹0±âßj°HÊ›­Ã8Ì9SÅD«„uQ£nV{÷‰Éˆã˼_+tÆNñg”/E ®
+J °Ý ·ô&ãfÜ4Õ°±²Ÿ‡/§@Ì~ÁÇ¿ce—tõ®ÅÌÙÄ>"ì$’­D‡¡»æƒ'’ÞpúÃüÀ“L&›%ØNæhÈ4n‰!¿‡Ûƒjeu˜ZµŽé¬ ›†ÊBÙ¼T:$5{PɤXx"„XoÙù!Lî³)=e:l]Jb6a
+9ü2Mw ¼ ÅT;t!âG(RZkà헎褓—¨‹×YÁ®¾¤¡µKP÷†#¿ü
+nª/9Œ"-B [ÿU£ïynC¹2p»NÉ·P"ip'æÚ^²¥`;7„Ôì}Ϩ”ä™õð-Wß΄`ŒºØ`àó­Ä·B¶± Wlùe=]Ò`Ñ™(Au…HFÒ;Åï·md^Ë%°øV08ö›ØÙó)ú|(
+ â€9¯šLC€ˆÄ˜¼/ÿe8‘†š‰µ±×ÉФ3²õ“
+·6ÀA@ÃKДX~}Â\™—ªg#”D(•ž¬[ÀL‹ù•x5ˆ
+¬²ãýRBî%ÌÑò”_Jñà¥j04Ær½­ó{‚¸—àtp
+U*QÎV’JrbîíÒô]aü=
+—IqrÑt.ÅWh=£‡šu‰igTas á.Ô°ó(ñxJˆLfüø±ìÌð‘/żâÀÈ<ØtÊ]¢ÀT g”©½°M#„ È˜…ÖVt[ÑÉæÅV\O¹ñjåP(­E Qó’ŽÝ$ãÁÏö‚QŠ¦„HÚ?o@þµ‹ ‘,kbÄJ=z¨8k{3ÃîÑZqP½ð¥¬M´” Ì!‰ÆsG®Û`'ç¸:½ ù£š@'™î±i¶²D™”Wòáš,Þño‡C Ž &Yø÷Xÿ¯‰ê Hø_ƒ» ‘‹V᧑ž~îU÷\KCu(v†IÜzØ2"
+étL×Kv£Æ}°J;$ú=»Á“Ó-†(Ÿ·yd®¶N¦Ú»ûæ„tYi$)ñãÜè÷T¶Ù³)2T°Pt€¤UÔËW±Ñ“‡`¸‰¸#s–C a4«Xk^+*G«±tîˆË³èa7@Oñýô¿þÈþ›R±ÔŸ÷Q²o
+S,`  ”¿wQ⛬9T¬F%¤A
+ —"•ÐUtï
+” 6Ï»Vï]¾pãn’.â¯ÙN¢hcJñ:ØÞi =©ïe€IIz¬Ó4åx£aÓ+¡@†Üç®@kÖÌb@c§ÚÿjF®‰ gæZC‘}N§Ѹ[ªy0š{›½”hÕý¶¹ìlõ(2¥Rè
+F Ã’#çðÄr«‰X×|,¨AL˜8'“[0x,ó´Ié†ÿð{s½ÛW2˼”øVSr*›=f}Y†x;˜Ê(É°º#öç èƒÝ ØV“³JFæ àL¡›]\ø¬5¹=Î:†™«àf¶x>ÓÐ69üì%ÜÉä G{óö×_ò1­ùƒà²4ÜÓ|ˆ6¸,>lßû^§"Nòåps¬ÃÎâzo»H%0ÂqVÀ.2ƒI©™“dØ”7}kû
+f¹ú…4ù§ßÉ^J`!òj‡*[?[ýoÂ7¥ÍM@l2l
+°9H ¯žåJ¥c;–ñÍôte\ŠTÂÒâF©24ÆŠ\J$s^Je$™óÄû]ø’ƒÏõa†ñk³qŸÀJ¹ê¦Jäoë—êBq–€·J¨Wp„`* E¤g3ÇV]Öš}R:ˆèæ ‘Á „K2D´šéñLìšÜ]±_¯1ç $à.· eâõfìdÚ,ßyà*É? “óø:Òibê±èRÐä/¹Åk I¨n>ÎV"è+ËÛ'†$û2&[BL[€8ŸÂ|~ë\€*¦³•ÿ0^.9zÜ0>Aîzµko}‹
+þJv#_ÿ)ñþÁ˜f6Ω{IÓ=42cOç- AcØÉDeDp„'Ïa¦äãR{'wP†déߤ-‹EEá÷00_G÷à: 1`5~àú‡T0‡¸Cå”hvv!cZ˯‘j}YåZÑìêQ2ÿXÆ{»%qÙ&ÄÁ™Ñ¢(ÏLJôOŠ«ì&9
+ÙÖ9AÌajÅri†ËÃ
+$Šgä…ßò# {‰¹±¢ íÎØÚR(g‡«Fé=¥kruÚKuƒ§gE£V±Ö !˾å©—id;Pý ùÐýŸœ@äÍ!çDW•D¾Ž ƒ’"SƒñÕãaäx„Ö&4¼¼AÌWö0%Q‹_*[„q2m'üçnß¡8Qj#=*±pÛ¾×ûf ™¦‹)™ÔÈv˜;3Óã(âû’9cŽ{
+sÏjÁˆqÉ)²uõ)ÉÀGu5¢URü¸öRD%зA ü30]ÃÑÆܟц””Ìò
+2Êì‘Y¶›Ý ~á
+ Æ"8<û†°Kf©\w^Éž[³Uâ
+³ iW¨/i”—ÓúYšǶ œŠü/‡â0\OýÏSÐ<™©Ã>{l%šÅgQºÜy
+Ë#×#Ñ„Æô³)WBæeZ›wpCÉ|Œ‰˜ÞËb*x†È¿ì²À0g§‘Û¤R( ÚwjBÓùxM;<,( ˜\ú½´;\ˆŸ$!6èÅÕßé?D!E^‹l¬¥Uib„Îáæ‡ûê¨N†à×éxíP[ly£4¼Ö¾£é†“ŠŠ;aWæ°)3°•
+Â*)¯¸Dœ¨p^´J‹ÂÕã¨Ë<Ÿ0Bˆ«rA0Ê@°£0%‰¿ChùÃéy9¤(-3ù×® ´êU°™÷« ”Ö†ÛD/IIª`÷+Wn%XâÊœÉ.FÄi2™¤Z˜YÚ²­à ºÑø ‹ 1((A±×ÿºeÀ¯ÐçÖt„ä®Å2­\_ ýâ ºÇVAˆaxc´"!“s øœƒ0¼´íåá?+Hô€ $Q:ɲZ_¾bá`“k/V<Ÿ¤„ø¿ÅÐLübä·£øL'-±ã¬ü\0’dÖ®M þšÄ¥–æôå |±è¿ËU‡ ‚®#³Œz¼ò òxú t+áòÙˆäÖN ¬ævyID^FuäÌÀDˆ¦â¢ÄJN[R*Ƹ´·(³8ÕIòL*½†‡T‘‘w±§B§LP-}½@>„2ÚÉP¯V¨ìäíl„ò$ïÜ'ˆ]\sÉ¡¥ÄÄkþæ1–ŒUbhÍ… ¡ÃErcø¢6¬PpM‘fÕ‡¸‘K¶M2ÿLõ´ßÊÐ,‡3»ÊOOˆŸ„ÝM¤õ"ŵ—ïLþ5Y‡¸À
+‰FRZÛå¬MÉö€zÍÏuÔüÁJ¥MÜÕöËÉ'Y¿×Í`'5ïpk(žï!Çá*\–A*ÙW#x׸ k-õâ‘kŒ8ª.[òt…
+8MÄÞó™²!4½„â<17—9¦¥‡)›1#ä§A‹ô6Áäse)p3pÓÂÙ”à5S†%Wk*;›»Í'è_
+H‰Œ—In¤9…Oà;øHŠ¢Ö¹­[4ЫÌûoû£†@:¬@0
+eçû5P|ÕJÿü磅=JïÝ]¬›ÔÏÿX)0/£•ÑëX }”b:JŒ¦C~ jÞZˆôÒ­ø›í~ò‡v1jñù<j“·ÕzÐ?ÿûhݵ‡Uuíª&‘(­” þü3A2¼/ì‘ úÍko¥v)í3!fnc”¡üÂôÖ=
+ªÉ„¸ª‡ðŧRчS$ýüïÜ)j¯ªV†˜,P±Ñõ´Ü©=XRZé#¢ú‚˜«HsmMë„¥‹nväVíÁéˈ^øs³Ž÷b¬ÃV«8@Æ5ë0|&
+µq¾xÞ»9ŸõfEÅöVTK¤¦»~ü®ù¨Þ{nåânźÝõ“h<Ucž’ÊHžn˜.«tU÷17ò‡(ÿåÈ}C;Qáó|–¦w©QVïÐ(l ÂéŸÎ-Ö¼¯"]Ä¥x~·wRÏ·žÐl̲ jëkÞI’^Û‚dÏðc#êx‰oŒÝxí_7 ½è5\T’Tز‡Šø
+´€ŠÏ»1ˆÕxBJ¹ï®£rq£ávW˜Vktu§S†N ºw‚‰#IL£ž*³4¯-VÂ)PÊþMD»A*6¯z¶¢×FÈàcƒ„ëñZÍ ÿâ M$«»èP>äÞÅ'¤i3ùyzj@CJi±·ªè=|ׯR&îÎU7ƒ“ ˆÇèûâÜ—fKzè’ ôcÆ ²Å‚…ÀЪu¼YŠ„hy«ù…@!ÝìøÂbý(`•1¤¢ å蜫¨²»QÅÑß"‘Ò¹>Špš§ïꨦd¶Î7K-Dþáyì[«ÒVÂ+ûÞJŽ˜Ê^»-s¶oÕç:ÂáCyÂÞû•Y@`3G ÓÃOÜÂ5aQÏ­Ò!‚×å¶{«pŽcYA_GæÍ-jÞÜ÷:à^+Dç3HM&Sõ_7Ð… ú€Vžä—w,þ*éX£ãkºmû²Ý@h·"¶Yy”vêÁ ä<p*ŸÕIA CQlzfÛ„§°sÎì½Ï›ÍÖù”––±Ÿã;ˆ§J›miÛoÖ‰€ÛÖFÁ]ß@†…#-üÍë›­„J÷‘n,ª{²J†­o=(9DÃG¯)y0a“«¦žÁÇþ¼ÓwÌW9¸Bþ–•;äKJyw§/ •xÊ#éèð‡»É<é̓|ÿ3A†Ôy ›a/ „KhC$œ³m‚5$Ëû„àÍÉm¬–tÍzú Þ& }<B;ÒŒu¤¹NP€‡:šÁç3!î'GÄ6¤#Vè²dPš†ˆP0vÝ;5ÌÆ$-¬ˆŸ%OméÐdÜ2{™Ì¥sôŒÀIJ!Â
+¿RÖ¾ )èe®È£ÙÃ)òܪ]h(È+º4!Å[¥52\%úX*HCè¤Pß—úI½léq¶z½*Ôå4ˆ¡6Î<:ém\oõ¢ºk+7jŠ[yº
+6lmAø
+´‘eìG)3–ÔtºyRѨ '|·CFŽ”)t>Ç„ ëØ,ëL;d´1³
+>f’ù‹ÄK¼9áÀIØ÷òØÓ±©òpRúÒt“†DA6IY²åŽ€Às‚Â=7Ȳ81(jÈzPB¾¥ï#óÖL)”t¿9!ˆ¾¦Éâð“†ùÂy+‰Ó;Ø'â2g,© ­0›Y]’Ì5.ÁŠ“¯JT|? gŒÕ¦UæV%.ňô¯œÄ°¿þf9Æ"íÚŸY8þ@¾¼Å2Ü‹ò|»ÊŠ"ózŒ“ÞöV‚[RÛm¯Óøgº–¶•¸’8'’ ájë¸BÊ™ÿ©"Åß[½‚n"k š•@ºnÅ=ɼĪ1‘ßÞ\yþY[qcKÚäû¶ÏÉX…Íxæ…É_(†p;»Jf”åc¾Qä|·ò¡BîÙux¼\™”­/ÌÅዹ§Ãa<œò¿² ˜ƒ(HÝ[ŒÈ<Šg˜èËÎY¦îÆã±òï·r3ÍŠq¾¾Ú„ÇMÇ<W¯ fÉ,ä)–°j£$ƒSÎa½î™Li©<Lˆz윘 “h(ïKv =
+ýê~¤ ƒE/})œ§ï9Ò('[ð8<^¸g”É%øÑ,;¡ˆ`¦9ù\¤Q-Ú­=ñcdü' ÑÄíÍ#0š9«·÷¡
+7—‚¥CòÍ/ ò…ú¿4ËAbBÈ…š§-¡)§$š>p%õƒò(R?%Ÿô•@:’ÇT‡EÕ*ý2¬&¤@rZ™Ü`ztrxêɈyÝémúÑ‚ýâÉ­/ô^ø ;ßÖaèI‰ä¡ý8ù>¢‹ A’êS¹œwíÄ3ÑÔÞý€|Vø¤ Ü$R<yßÅ!²d¸æ­eB°íÂ@Œ“]?£?á!y5r‚ȱ¿§¼D`C$ä9Åo„Œüp•TÛ„Ô<‡˜íyOæ0—“Qô\
+³‚Gè(1j«¶sËúù:1s$ÔÄNÇyñ—äú¢ó$ÉEªL]º€^™a×Û#_!’Z~J9«˜Kãl³Ûo  %”µå$óy‡|ú®W#¾€HV#G””9kÞ‚ñˆÔÝv¤¤CÑô
+ùú7ÈËsç8MhkO$¢óÖ㲇§oÃ÷ÆÌŠåeÊG| `óø
+:ŽsAmÛÒ)ƒ@Щhíê>aöOªô(¨«´v”šN7ÑfùrV(‹}á»ýkß'{CÎIË·³tûÞ;£ñÐ;FA9gÈÃx‹}[±5\Í:¶É ;‡‰Å—hµ{ 3\äj÷›d9•»¨aL!`:/·#gÊ|-¢j 3ô “´¶Þ”Œ¸x̵W@Q•EaŽúŨâ:Y>»éseC¦q1ßBÛ(¦rP ØzØ›™ïNJ¤Dƒú÷„Þ“J;×–«Šâ!
+ ÞGd†8“CÚ8ï e3Ø=Îác&ÅÁpÕKt2Åã=ÐþÁyIW*:õm ÓñæÄÆ „aµ.#çB‡‹ÞÿöQœ"‚¢ ã¼\Ô¿ÔÀêÖAÔ.àDZìƒXaZŽ«~N™ÞÐîÇÜà6¡r¾ŸiŠ«ž\…™Aþ¥3£ûL é‹u®«Gmðï¿éÚr5‡<€qA‘·†ø\„€4ä°£¯ÐĄ̂޳¢žÌ&û”aÀ°R,M’eŒ›:îž/lÊc¶œY³ÆÐó#ª|Ù—_Wéà{H}„’ÍO‚ýð‹8QââŽsJâ  *ë© ‡½½ë&Y¡wE«º#êm~<I´áÀ¡È*Î8ψ”rð¨Ç< 92Cl‹¿>$_B£JE‡Ði-*‘”×┡ìÉ¢×ÎÖ‹˜Ç³{éÈ–«x_eœúÕ€á—|z’*žf~ q<oB;jŠd ‰qG,…ø
+³¸µc ¸C†l÷ änƒ^ÎAµï†~’[|°t‚f“e—AtÕÆPT~å[좯¥Š«…Èc
+mÚ…-àMx ;gËX`'öuô;ä é»|<ƒøÉ”n¢µ [(Ã3· —ÈÒ zõzžOÑÒæRÞA` œ Ÿ¼N•7ìaV/@T†aþ¡2?‡á²þràÕÎWsÐH=LuNy ²Ý˜1Â4yܶÁƘW°1üD’uË1á ,³ÜÞ õ)IÛf\E%ôÁ¬Ò
+—‰¹ß°ä1íhš±eˆW>Ç`%âçf¼a*Þ/¿‰a“±PM߃8smMÂó1l7–¡à ÒDû„ÔSà/6ôÛÇ ‚¨jÕlSÓ¤/íÐÙa‰i=Œ°´6þ%P7Ÿ!! /+3Ç~°kû£-äò½|s@vÒãøà}:Iii±ýD×y}½$îΡÖ*8È›eƉxt Dž«‡nNÂËøÛZ½ÝM‘7;l~‚‰À–2l|ä8épù1ë)pqm^ ±
+Osþ’‚ªÅÍUHI2*é‚÷J=»e£ ˆw2 ~øU ±¬§úæôaFZYßÓV›0’Ü€Ctz±Œc_²”_…â¤É`ãä$¦ˆ‰}èv ŠŠm¡<ùLÅלTóy1ž¢Ä!ÒT‰5†³! Xé.ÊÎPx^ˆ†‡ÎÇ £F2W«„z0d˜è°I`óE°sr'@XƒŸÐLœR|ï*b#Ê7>”wÃÄ4~l~B€ÅŒt@¼å¹?oóRa@¬%MG6{€”9³T(uæ›5CŸ{ë—­2 ‚Ýú8[_¶Aš1Ã7PǼÎÍ‹«1ô7ÒÅ(1PI$Y³^ß>~ZMd7ù&î:y
+—ÝÎé’>FÛpLÅõ1“_Uùvœ³ßo¿*3³Á[‡?ÃØo˜;z}Ô",‘<dÒë9EÑŽw³m€0D2:u²[Fîø³QýœÇÒauhGËÇÐBì½!º0þÛ9’Ç(ÐÊ–<7á)!©]‹›±#¨XBàÆ4ÚR•(0ó
+A‰m‹#šLŸÈÆ­ª¶™ðªâÂ+ Q°2¥”À³@JaÔJÔeb߀4˜µÀoÍúb$
+l¯$Àbƒ™iè­ï!™„ÑX‰Œ®â݆*v)Azg©hVÌ…Ò^JØbË)?ŸL²„
+‹òe¯>èµ~7K?ðTùó;E>£äƒXÿ£ œv›©º!q­læÖ„‘C’Ôœû—ò2IŽã¢è |Ÿ€yXËKÞB[ùþ[¿L”ÕÕ(GÛ MfaHüüÃÜ%(5"s¾:­Dá¬Ç‚\^î–ÁV#­CM(œ¢@ÍŠ˜Q@Ƨ«Ñe™E:
+ºw~€´DÚø””W  À‹ðZ!¹¹ej FÊÖNeÙR¢d}$á#³’jûZ'‰¸’Fk$´š‹3¡­¬‰•ª³2†mEM˜œó ÂhIÚPűNVšó
+š˜ÂaÙv§ñ(âÙ%¶“|ŽR-nm>¬ÃÆܨ*ô㥔2Exo”ÙûÇL— á Ö¿
+ÿK-Û’$)R ‰¡õe.*~˜îÐK¶:&ø©Âåì5J’<¤Ý7œŠpxŠA^ÛÖÑÞc* îÈDÚdl«ûyñT©WXûNœ Ô€Ëávˆ\²þ˶L˜Ê¦à©ww:Š¡"q.Ÿ­öcðPØäÄžñ’d;CoþR“£F
+:›*JÀé!Ì} ªM}¤Æ›YE>ç6ã/2㠠钦ߛÃ%8ed³mÕØ/„­ßIåEcþD h†d´1… S§ÖQ¬MI±ÑKFgçâ* þ÷–·x"ºHïÓ§oŪ
+ø×ëê ¡ÐÅWFºP@G’GOE40 H?; +di¿U\ï€î]óË<@G< ·Sm–×€Tÿ<ñÈI8ë)ÂýÈö¡2dPœýn,
+Œ!#`Ã~ '.ô! ®Í‡’ ýÄñ§ô&d
+X Ò †¾è"dA¥Ó¹cÈKÑ÷±ÉKœø6qö·mdÂ.5õ±ˆi•ÀFÙs”TÓ…¨ð©¢ö•b,Öæó¢ÃvB…‡ø×Zð¾ÝGEzOô›‡mLšìX4“DµË›@ç8¶ª˜ÝcI1Þm OËð¬¢Ù[¸6à˜Œ‰BNÁÒÖÁÌP·°K–qéSØ\%&F枸Bb’dÑØ|+øU€ë©¾N«1ªaynJÄߨp¾ŸO|n±ÌŒRía•b7æ}ß ž)Ð5ÜœŽ±1Â[>JèIX´Æj‡’Ÿ lÄÉ&F¨—é_„n Û¤Mñ4]ÏÞVI^ß$À§óÚN<.^ß³*w!˜¢‘<Dï×3äž•$xõVWIGa#.}ŒÝ>Öƒ@Á_’œJð]0;ü‡ñ\í_$Ì}cÚ¶áy¥2¦æ¤ewcýÁÈ¡^¸”‰d²ù~¦Éý&N‰×½®¨ ‡ÃGOL†)¢ZËÛÇ¢Q>3]d7…òέ­3L´@Ž¾¤|°;¶•Ò“ÎKo‹Al“¥ÌâÇõÜC•ïæE¾¿»%¶”ÏF…"ræTO5Ô^Ä_ÉØÿæ%-ÐQö>²Lòà¢5Ú,4Ú…Scñ~¨°î#uXFy‹™oøp)dYž²¶¶ïtÓœ"/-»#»ß›ä©œÄ"z(‘$Ë’ñ^®£L.~löe™¨
+ÁûËäÒ6úZ÷hîƒûñ8»uEQ¸ìˤeIhÀIÏoTí;ò#Ûé›Á#Xí,Ö´uˆnܹ*¤u¹ÒÑÒ±ŠJ£ÇÊÞê¿ý…ÙeV¼6,ÃóDSóäÒƒ"ç\6äT €ìŸ'yM_ú?ÙÜ0ÚüE/ÛýúäLvô÷µnzd
+‘S‡Ë›º_Š¾Eo–D„·­è ¬]|\tØîý~,M\Qˆ
+V¨>*:ج÷fÞŠ~}Òq=Lüó¯?À¸ W’oên’°Þ!Ä‚ÙŠz›CMZF
+ºaœû*IÄ D
+v÷‡ÑbX
+>ëÈðQEð
+ìPçÙ™¬
+AæÎÛ&ɘ¨Õ+F‡Tš$Ú¨¯(#ªE‰ýÀô_ Á‘ߥD݃ª‡L»—pkúÇôŠ)¡‘Ëpº—d™V;L¾g²…ŸGÓ±XÑþµ?p
+ÉECY¸߉WÄÌ
+ e\Á†Û"}‚Yµ®<ÐñRÛvæB2­ÁûFzW¦¶ˆºýB<1kóJÁfé>Ù”@ŒŒt4ã‘!Pw®ˆ•ÄSÅ}§Ñ”õÒEø-Õîtg«›¼Ÿ8/³,ÃÏÂVûRwî.NBOýÄï,M"Tp`¢Z~(ùÈ@ùÁ)?UÅx@á€Jb§œ~ç `Ç9Ÿç4?c¥æ¡È&|L¬Vÿ‡ñ2I’´†¡ð ¸'¨ð<¬‹eß‚VÕ÷ßò=KêèÊôÀÈJ¥-kxâÐÏ‘eËÌ5óìk·ZYò%7A¿ñ…™cïÐØ'J¥=¦H2uÕßö»òªá|Úðˆ2²61`ÛP:ïé‚øíéâ0§U9úE1
+@’Ir]T%ÈÙ¿Mw¿,†Fj)àž ð1™€ŽõŒa`M¶§3Òa¤‰FïÆ ‚ü%7Ö¶òr¸¯}–¹¨Iï\¼~HA¶ºÈ‡Í3¨R>0-%ÍQ?²c©°[Íf¹0Ôê•à¿„8èˆ+šœRç ­EÆ´·zÊð0Þd&ùX£pÙ¯5€ÈvKØÕÃ4 ÚAÌ `­¹°«¤e`ŠD·ZTG>ˆÖ8¢ p9Œˆˆ€ñ’ÈÙ!ph]³=c
+ä·±&ÚQMÓ±ù¥ 3Ö'ºÌÑ?F@ùtnC¬T8&å„ÚAeÌe1Ì*좇“?ئC¶Ãà<ŸWÊMñͶᣖL0£Ó¦‡ ü2†‚±‘ÞIéBŽÕb`8#ÉŸLê×|F¸:Rçà£ÈºäéB‹jó
+˜/NÍ×%ò]Oai¡­ø‚ï8žÃá^½çXlzÄ œÉF<Ø‚¤D§6Ùp¸a)˜2$‘GpŠ}Nù
+D—Ú´ÛÖhsŒº-X„í~€Mb·Ä›Ø“ b iÁ+1ç3g²#@Dø)¤%N“± &mËxÔêļØ-ä/ÈÛ ?¡Yˆ½Ú•Ã
+® <ÞŒ¢ŒÆç•X^‚¾ž‚ä‚6ži>X‚|FHú '„KÈÑ1µˆŸƒè:?AK­šcB(CV‘«Äö°s~ “†wÕN•ü`h&TRÜpLÞŠJó
+Jߢ­Ó>£G%ë™+öEšáÓ¿ÆS{Ü$øWñ%Ó%‘íWuýŠ‰C»
+`öEj,Ÿ¿ûì*_y!ûøß’~èírÙ^õs,„²˜Òy[ñ/ BMRØÀbÊá1¶~ýHk†,ðõºgYet³bH‘€|ÚØS³ïAL-
+~NÈR!ØîëÔ¹Œº×Ž9:Ôº¡D¸Ü@›žªXÁ7¡éÒ¥!ÑY,+µ…ýåê&X¼ú ]Œc.6p4Ê9‡¦ty)í^‰‘àgÈ?#ßýßM(mÔýp¯™Ø<ïap»‰!aJ¸9[Ëñ£8ò•<<§àI˜:Ôaj™­³{#æOpÒ­e8J#ÉÞA‚3VxKpu&;ÏF< »J¥me$’
+šÎìСu$3„s˜Âд3ãpÞO\¯ÑaK<¨‘>z€?L  Î5kF…˜É—ôøÇ’áå þùÝò@9¬æWMY±rq{£"QÀñûœàuáòÂÅ’ô-:Ì”U”ÌrŸø*§HT¤
+ V®,ú”ÈÉçyOžÄŒMrF,²~©Ú&:#-x.ß, YY3j:Îv¾]\é0N…ÎÊ=‚H¨
+=ù4Æ…uX.|õj([Þ¬.KP›¢ =D:>‰cs<×N@mîUACóç¦6ÝÆj‹è7ì#yù6žšd‘˹Òë+;üøŒÊ‚”’Ÿ'ˆe%!ÄÄ./h%ßCé]`@û b ’fp &a*p”-!â'ŠÁíÍq›ÿ¯,Wbû`ÄÞK^ ls· lk“OdgÊ9GL€£ÚºÚ"À%ÔëÒO€ÄO`>B¨!xËÜ«çv{˜
+ÝÁš$GŠ†*mê=ª`O¿
+þ`'Ð'gEo°{é !ò!H±v°þ„0o#õœá/ƒ@ÝÉF´fóCs€^y™QúAÒLI3rêÆ›Ð1Ú‚]ËQ?l Þ%Iö•gÕÙ
+ „KúÅâ!(Í*5ûÛŠSÝÚxBB"hQL/u&UU±Ð—ç"Tž*iƒ:í*Òb”‡
+I;;ˆŸ¡«x³èËqqÄ}¹µ.¾Nx³iÑÓ姴^[Q)ï ²e’Ä&v?9äOp¨.lÞn . Ää£äbºÜÔ1w# Ï¿À:" –)ùFÎQrlü²
+û|
+¼¤¼c#1´è ¾{'ß]Q_fUÑäÌr`’µŸþr…6Í9®Bã2 èÏᯂ`a#$¯ÔÐÕæ“Šø7PÅüÆÕBm“÷ ðŸUñðÔä ñRd%²ö² "ÄoJ0+4-:êz3&Yæ`Ïï¾£XÇš›žœà‡}€èËAºÑ€Lc®å*Ùòˆ it?
+뉃•â‡øé.4Ä~x ÀJÒ×>øQâ2µ¡Hî#šgÑ"haëœ.xá `.ÔiM?
+z\Êp,g;gdu÷öÞà2±Àä‚Ö=yÑÜ.Ýb'\!p~©4Sü ‘
+0ÁÓHÌâå2¨¶
+/ù°hµuýœûlÑ-G7ðêV#ÒÈ""ô–[ü–$­hËS˦›uÏÊ<±+CÏtó”2Ë  M9ɆJ[…,ÞìÐ JÎAÊtOÿŠT"™Ä¶!%•(ö,•žh ”TQpâ™à$.ZÚp‚)ô°½ÇŽ ñz~NÑɳfðïé1ì"^Xˆ hAw
+γ ‘ï*ÍÍá78e@3!¿,.8d™kž@ ¢&Lï˜Y­¢]²3!ñÓ"–Yˆ¥ˆ×–$Ò±ïp_Æ…f Œ‡ä,…½U¼`óÏAÍãS‘÷õÙ0=ïÖKw;뚈÷é¥è'ì‚©£Ñ`øçý>E¸Y¾ ‹çu‡Þ*kà¨tVijà~ˆ¹vïRÊrÈšµ“t”vL/8kU@
+\ê²ò‰j0Ø @SOÅš*ïÞv ¿2Èj] nÓ‡øcÿ*2ª•ÈÊâö*™X£$[ÔDÂ6÷{ÑËRiœŽ=xQ³òvÇÍm¡3Éô„Eã)’Á‘3‹<¬?T…Ÿd© —ΤÓBÖŽŸŽ¼Ð:d;& X÷YÑίˆƒóRº¨]ºT•Bv4
+
+Š¯£Ò³ZœEê*y%ç ©:¨BK+üŽp Gk'“™•°û¸G1ô´îQO:–½5®
+¾ˆ¦Ôá1-teX‘ÜÀ¼O·µ¹¹Ž¤S‚õŸ¨lÝGiç“Ïô v›‡Ü+Ë+˜R¾×üü¦¦ÉH`2Ö:Múb:Ó§ï)‹F£Ð"ÌÀC%¬Ÿ.Èä—wg!‰[ÃJð›(3?D1ïê—º-üQ¯ò”Ê,ßò¹a_aŸŸD*͹¡"%Õÿ·,dr`L™é6Nü&Êyl-¼1z t›QLÔίŸƒÑ0'ö+U«
+®ËW&³JóZò´±ë‰ßûN_2Y¿ô+#Í(¾Z HƒLŸäº.XtÖ†ò¯ûüo„:Ä>Ñ*ù¢zñ|¼e‘8²Ÿg± Õ”~·€ýþ‚AEµ³ðYˆ
+X àØÞ.
+ Èq4V4
+†ö÷E/wºãUF²%5¥´O ñ¯tq‘ùLÂŒyÁ–­âqˆ›ßÀ•¹Ë›"áÌ5†ý”×ìmÉC×®wˆpýK¸6®]gh“›ËÆðëð[5¸V4nV,‰1_ƒ…óå0UÐô6—;ÑSÀ 8#–§—»èÆ…G €«"Nkß(O݇6òņôr %ÜßJ€­RNÍå„æ’Li}õsð{”$äŠMVí울朔‰ŽôIÑf¹F®†Çå é'ápwæI—sêYŒÇ"å㮂¢
+Ñs„/RË=͸dÏ÷Z<(s܇p“Øû$©ó?Œ—Iv9 DOà;Ô ô8k÷Ò·ðVºÿ¶€¤^W&ªU›n[†˜$ˆA+N×ÃËs:jV]"ë¹ 6#@ÒÙN
+G´µ¼¯ŠùºF¸êô‡³qæ TxÙVÞW÷Rô¹ve¨Ä z¾5ùcªøSÅ8+Aè0¦üÛž&¾º5ƒáÒóÆ*äÎPòL§ÅZméU=.†ë¥
+A¬X DÀF@f™*:Ú¬$C~‰žOnèXGÊZ‰ú!IæÛãfÀ"Õ@…v:2€Áœøsúÿi aãiê
+Q&º Y³UÃS­7ȬØ|ctJ(ðõ$„*9w•p=ð誓öm' [B^ @ú¡@rQÌûSä]¶?*Ò\ŸªÐ¯`V¹œSB(eç4­!KÂ/îWá‘2(fŽïø£ÁÜ,‰O°Ñ¬ƒsÞ☠¥]8Y,VghÈ´,Õ Šðñ¬"Êlö˜wñ¥Ì>§öûAEµôç(ºòåñ\ WþdF¿¬¤Ëà¢øÈ­]‘ó˜AŽ5bŽ¹ˆþNÏÝåÅÓÊúÑ)LÍ §ÓG}p‹V§{NÂW’+0Qs~ÛÈÿf +ö9…¹wFëæݨ·!Ü‹¾ÄRÎiÚÞE¢%ÙcˆN |£èîÄ"œxë@¢ÑTÒE` ç¼y©ëÂI&¬&b.ÙÍ(é9æâÅ)‚h+ëÌ@â·~²B÷aP’ùäL{¶,^“¼“z*YŸ+²ø•ÿM÷œðD¸q¡ÓÓ7 à‹A¨¥ðWsù¯°q ÄÄŸWl’(®˜U¶shDƒ·;ñ1ŸdUð#„± wG;¼Ž†zAƒº!ãVsŸyàGbNhzž{ ÔJ– O*‰tnŸz.ùüy?ÿh‰Ã€ ZV¼QT[aVAÝÜ’S„|F’ ì$æëÒüˆÏÚûEÌ”ÿ@`xÎl5÷¯½S[â-‰(uJm>Ý">׉Åš?¬¤ ÀhHl›˜‡>E42CDI•…–L ›Þ[¸™X0Ÿ§"6‚—&1æ&f6K^0†u >‡-‚”÷VPit)Êe*éÓ@çgé^ÉúÒèâ4»á|qŽ…-OÃQ o” º=#Þp„àì=au5™wÓÚÕÒ¶Á›K»ˆë]ì â–ð‹ã.7êž’Š2öâV°ž 'a#.®L÷Œâ˜Y•”ìËvÂ*Á—=·ŠªÉ9ƒØ3‚(‚¬g[R ]™ DX*Úo®¡5‘=Z)P ›O ì-„ýâĪ1Y¾”º[rçï_^ÑçØst˜­†ŠæÛ5ÎâÝ?öVÑ… ü­º‰X¢‚XHƳŽf‰ÎÅ¡~½(2;1M.AóHBMêØÛ>ðUâh%Xrö $ìÄn@HQv~a(@0#NÊicˆÐÀ×ëø‰J¸®IÌJ¤høV।æÐþ0ªS²>5
+a1Xé`ˆ¬× 7—‚½£ãŒXC„HÐ(iBÃIì
+Ð/¢dXkE#LDµí»ŠXi âpöFy"”Ü5øUD "ÌŠrƒâ8ì{¬û.1H(m «[B
++§û2U4Žíè‹“Ùwv¶òŠUÃ7PEÆÓÚ#‘7Âp-ìƒ:5Xf¤Ú«#»‘(‰»ÿ|‹Ë â
+2WwY$¬”V³9%«¿Zë N–Øîç0jvŽu‚WΕu×.ûˆ 8äOE@ráˆp²Oþ“¼F 2r ¿¸îBÛç·‹£×M Ù«0Q‘chóÌÀ¿¢î"mß A#xêØ 0àœ‰ÉÔ1Á
+DG®c‡‡3¼÷(M”ÜÆŠñïQ
+׆Wt›z›Ä<%ÌÂæÔùvÑe?ßYÔµÏa²H› ¬„'
+D+ôž}Nx!èTEtDÒ°¿!a ¨úàújÞ «º´Åª.n‘CžP'úxGÿs‘á·¯(•:hdס"ø 45Y^¡ ™››A¤§HÄ4|0 w±¹Ò”9ï>?lòN‚¡ ªã°ðj&’ÿFe`G•š•K6Ïqøö†³¬îÛ°`Ï<¤Õ!Á^ílIXç”ð>Œšk (BÎÀߨ¼M¥'Šƒ¹2(ÈÑ:ú²º«´QŸ`~¬?ª=hÆPÇ®-à %ü;Ó—{¸EwÎðÇ÷ýÛZ"ƒ’¿mSQ²ÿõçÔ^¨jv{óç°™ù¬„Íoþ·éä0‹£6mI,B;Ôo–U»Ù©McLã±3íê[­p¿ÔåªuœÃàÒU°ÃYd88Ȥ¯pz˜’ªòà~©¬ÖaÝÁ™ôP
+ùhít&ͽ˜ô]ò¯-6¸VPœ¥¡) ? yå¾.=p?œDOQòÌDÏ­’oŒmºÒ w‡Äù¤•~Å&i~v³kónX+˜%„QH,Ha´óôÇdËãÝ®
+Dd œ©ý¢éY¼´´X4 à©òp}Ϭх™²©RM„yHh⊦ý8†øBqyb'"š Ä[¥ ¸£¬Ék‡Ǹ¨å&jàöµ:Û3L4Áƒ$§›‰ÛÚ¨Š[DH³æ„°„<ˆ®
+d[$¡ÚxÒÊifÔw´Ï—ûá”*ŸlÌÈùò³’©$àhéE©˜ |çü‘*.V|EUkb;E
+\rat Ô†ÿyx–ÜѬ…ßëëÙØ<N$#Ÿë"ˆ>#¬¹g×%áTÝÿÈquÍÁn2 gJèM›gÙÓøm5šM~ŠšÖ
+9>k‰ù׌ñOE*?'àÄò>D@—×âÀ?̬c
+4S°LS9 F­WâsúÀ7:ºâ‡´W·ˆ‰:¦—s°pN*Þ¦!{õ†d~
+æpZ«\ &9ªv€ Æ)ðÜú9¨!ñVÈdz -ä-­éÇý¼”
+Õ¯Â4™Ö9~­ï6çÔHM1\Æ9‰®&”:/ ‹-g]רA"L4ƒ,…³wap‚Ǫä¦ë>LÙªZ–_Log0ÉË£ðhŠðd³ŒÚvõ®ìXJ2R üÆER·üR϶kuM‹«%¬1Ì–­+«()ƒ-"pf‚‚ÌVØÊ‚ŠZç€?m­) Ï£Ù’ˆDy`ç#z\¥°r4ó–ï1 m_Åo69ìÔ×!áUlUQ̳6-¦ÛÛÅ‘‡[d
+ñ74²xd쨈~6ŸÔÈÆ h]ÄkR£F+•Æ]7è¿c£ÆŠŠòÙ*ðÇÀ˜a˜Ù)hÓ€0×mlD‚cð¯8^66†±/]Ûïª>¹ÑÒ\àèg¦ ÛbžûæÅ(<¥ÞhüYíàÆÀtÅç
+žŸöÂuqcxñQ&w÷¿÷ ƒ=µ
+®PïõçtÿæFá•ÀTÉÌòbr£§H§öËÝÎo¦©T)8àAÍÍÄFv;F³h*µú@,nðN‹}yü;5²$QÕ ‚ Q`R£%¹¨ñÔh‰®Äer£’»•E<¼hŒÑ"¾nÂ?©ñ.ä“i<êÕá—úUÓTî”æDz­™
+,ŽWqhó…sc7$óéô¸æ›¯e"°q‰ z¤ŸŒCÆ1²ÌÌȃM,ÿFïr=Fåzø¥¹êG…¤¹.°ì?Ý q}ì’£;ÍZ¿–šÅÚ•{Æ€€ %“µÑ”\ÄèŒ~K$H9¡árL µ‘ð] ™’Â*mÔF˜Eø4±ÙⵑPr!7п“t$aŸtš"yÆùBí*ör þ¼|ðBmSs¢¶DÏvÌÝl±6’ ’`4š@Åbm$ZS(—\\¯6kWÁXÓà¬Ô,ÖFÂô
+
+ã.Û©ús¾¿`»jé¤Ûc6»¥ga`= C²}¾ÇÍÈVÔ¢J5lÁ;m×ÄÌ'žð:á/6n#ÂIiHÍão¸"…(Ó»OÜ6%'n¢·MÑQ„ܘÑ&Ú€ÿ²…Ûzy‚Z½Lôkï9pÛ(æ·Õ|Ä㊎ó-L6’~ã¶Ê fp"ÜV£yNy14c´+&n#á7ÀÆHP}·q›±O*û`¦jó6a3 ¬»¯Þx[ª“%B?(6o¢¥ ÿTtð¶)zçmIð4Àƒ{²x[f)ì ÜZÛ ÷ÎÛ£õþ§¼\’"Ùa(ºV@ø+Ûã·¦°ÿé;WvP©
+ª££"mësï¬ÚfûŠ€›Ñ¤A…ÖÍ-"eÍxPfpÄÄMPAš‡q«gßáà%òÀ}gDÜRAf6˜ºOLÜRSèZ­¼äˆ¸ a±œÎÓs¬ˆ¸ƒ¼7QÉrÚ•œGà&†afº2>ÕjÜzª,›+PÀ?Ttwó GPßœ¡é•.ªtrïb[!ŠY‡ñ=ææQB[‰Þ‚F2g4S™×\%’£ °â!T.ã„„|øQu B¬–ùä3¤ZäNÎ|É[“\(éÃCô(l‘‰Üµ$"^•D¯Â=èF*`<•Õ+ é¿ XA®$¶²§gœv¿Ò(uE¨‡wï§Yȼ®4&ÄK
+L?~Æ£iS¾ê)ÅhRz’BéÞŘmŽ)ëû^\nßA@ŠëP«í„­+yªcÛìc‹²è[ÑU9LýgŠ±<(ƒ—#ݤL/É{ºftá‘´«M&‡ ¿ðo¼ «£w–¥‘/1Å, °P¿‚Øp› ƒ"-:ŒåPó‚´Ã8¼;PµA;5%ñ§=ü$ú€µ­©Ñ ˆ$‹]M…7m/*™Ö§ò1Lœ‘ak9ϺMø¦j€²JFȨ Ä“÷³ÈºÒ¸Z=/0ĺUµ?ÉQ…‘>
+çdDñh"Fòw3ˆîót“*"RbË2OÈÌž-¶ööBE]§Lx)o…’ËÕ?'ãËchiœÀœh.<Á@Y‹VÔÏ6ùpÇÏx. 펓Žp¾èAnªM ÜsÁ}/,²*q#!Z9Ì™ë:*ÅLŒ,ž#Þ›çt îƒÅHû=özÇQ*Q~â oŸ{±Á“?RKÍK£†.\´o¥D¤ ­ÅÝS=f`òUp.'‰ejÃ1Jm#ÚÜ‚b¨Ä
+¼È…wH’i&­ÍªÄÊ™Žì[]Ä𢊒Nz¶{!£ G±¢-?K¾?3â—æ‘s̱uãÊ›‘y¹blqƒvDK'a,³ÏKøøë.ˆGŽNÓ*yŽì-(Aàsø¥rÇ$
+Û¹.ó ¢ q³5‰F1D« NÁÔð£FMHF#Ytù–} ÿOŠV³CËܘtØe¿ýô¿
+H‰Œ—K’9DOPw¨ LA|®Õ˺…Ìf¥¹ÿvH†ÔUiª^H)OFp¸;lª…¼ÿÇd>rF‹¡]µÏ÷·ð|è a¢>¾òÇ”>³ÏÞlÎ÷_€æ£‰j‹é2Û¸}¼ý÷MÞÿÊ? i|™’sì‡jŠ¥‡™¹¾ÿP<DÃ9edÄ ¦=Gãtå‰ó@tôÁ ±õgôÜnsd¼©Í÷ŸëI>¬I ›\yƒ$¸kI͹Ήl}JÌ&ý¼qsé™mdËXÁ…²» K+Hrþóé3=߼ݵh:¨_‹«ÜÁE{ ÖÕòôkøßém¸h“P•9»u3^S<÷5£`S_Ç‚„ Õ¤Û祫Ñm¨Û”\õñ‡ ± †üÝ7H›wN¯Û:GS›Ñ?›TÚŒ6«¼€ð”Ná;U´ó¨gÐŒz·–Óû~e룻ÑzÓÓ¬žÖ§Nב áâ1’¢ÏC
+9tŠÕû9k:,t±K‹XÙ¼¥¯S†kŒ!”Aõ–€åñ(ßåã“4”štÉ›9Û”P3 ÒôáÔh‡òn¼Éf—§ø#eHDƒR–Ò`ï‚ÀäTh®~FÚ¨°!<íâ|Ÿc&—h¿Ÿ$ÍÍçì›Î]][ãµã®ÉÈðÞúf<ß
+Sr|õL‹ iM —o4ðš(R€Ñ=´DOŽI&›`#<nKzNÝ‘’¶eoH?pµž”›5 #i—Ë äè«aÅ>ÚÀÌ^œÃÈ›
+–=ÍO`Â0t„wÅŽ±,¹¤œ~*Œ½PÀAª™ÛËÆ?Ä Ëÿò”Ü„–”SØ:¦l΂F59ôƒò4›i¼6„² åo\ãM«‰SÐœo~¼ÝHAPª2w¶xs‡!Å8Ýá ëëY¼lZ 8úz$¤Sx .#‡G4¡DG¬SΘö¼ÞæôoKýõß­TZDíÓ)sFç•&@ ¦
++]ö -j† æ:f1z^ˆNÉÁŒ÷ioHñ°¾noÅK”"+\ÌHõTajE‹šjí·ç(UDN†ýRHÌåü2„÷°Yc„¼ž¦–@1º?WŸA7@‡/”3ÅìÛ § `=Cí½ !îv‰Ûw‚Ó XÍ÷í5Üàï^’uÕñÓÄ&â"„Û]ħ´•.ÐËà›»qßžO¹ ¤Ü{‰¸9§£Y•vÑ…8(?Ã#t­"Ï+­AOé«ý 2ááŸ%JØQ ?ÆÎ_gKÀü¢(p_”½ñ@XŒ<qø{A •TH+ ØÄu'³¶½zõöà#óGœR×£ÈÆL^Û2Ô°Ô™å£|ä¼:ÊÏ.#ºí aÌÓ×ó$²<a™Ð¹‹Ôh3C‹ºÆ¸dü„'!’ªŠÚõî ¼.ÎúóœC㆘——m©ÇâóŒj¥4E*õÖpÜ€r5&Ìj7cá(s¤œ´_unk½VÕÉ›”ÏDîâ0µQÍcˆÇ d™€
+ÐP››îØ–€Sôi·úýµ 7.ðÜɧSžù€·QcƒTÉàÞòŠ+‘ra<Ó×ãðê+?K½h82èýû˱öDhI®$c}ð›¼6èœGýe¤V>2xrj}Ô€UOËGu³&PÒáb1ó…µ[ùYýÿG1_€X…l–w¢[òŠe,t‹Ö
+Tè/@¶Z‚"…ü.Ó¿Pa”æcLYØâÅAÍÄÙð&Ñx ªe…ôi‘ž.GLÂ
+Ø£
+^Ì–s7€ÙIÆ‹ƒ n5D–<ƒ~}§½¿c‡5(–P«+šQ`§ð"‚RÎDŽ0ƒ~ƒ);fÓ V~-†˜j¯Ñ¨Y/Á ›kZ³r† ¶®YÙd% D±¯_N9 ŒJTƒ}¬s”*2ÞîeWÖrÆZµÄ¾ ¨#׿oǨØÛëÞõñ'»ê|Æ|¼À;`Q™ò÷Uk@Q+6ŠJòy¢Ö&öµ‚T²R`\Ñ6Ñ/f‚‹•Ë ÄgV¶ý½ |Zé~®Gw´Do¯ D“ÉðÆ:‡®O+•í-oZõ׆ÿ¸ì$IA¢¸DÇ'§ÚÌR1Þ´ýè³™­n‰0V½®{ÆŒ ‹Ç“äñÝ‚PáŠRÞ2Ž{SI
+\1hK¨VZ/%$Û^>Å4á#¼3˜BDP¨Š¹¢zÀ: Õxé½…À7"òŠˆ7 d¶ÜdÖžØVD¼}!!OˆýhSÏkŸƒ$üPWn©›û²ÂY"tã‡{$¾’ù‹Öð‘Ñ{ rë‡7MvÄ¢’2‰½®-^œ3k%¢Ýy)8ë†]@¥? t†«ž+ÁGÌ'ˆQº"" x_û¿‘CA¶-66b]®$PÀK×ú.̨R§¤»n
+þVtØ7cO½‹šJûŸúH¦¿‘–l—Ï©L$;Ç&qÒ Mp'B[óî‰J$c¶Š^¡Š³œÂ+¼63Ã…¬¾³2ŠL§¼¿E,M0¼È§è˽¿Y¦Eá?ŽÖNý’Æ9ÜOíG!<à…_í­ʼnfë({«µJ©•Sâar—Ò\ªrÌ)½Çx!}‹2JrÈ#™$;‰{ D4P~&Þ Ž5ç.!Ë+>-o`‚‹´þ¾ AŒQe”9//…UiìI x;ä*¯…#~’Ì«<€øZAL¥Ø|EâÑgçŒ3Pˆ\ƒ†0<vÎú¿áM‘…g
+¡yèJ ñGß+2,ဌ®¡(„ÙŠâë5l?ÐØB¢‚ÔsX'¥F^J¼òt“ApZ"YÀaý}ÛõiV}ÞÞðj6ÐXƒÎd!´v4ŽñÅmí]Nb°.OÅPÕ<%8ÈÍó¼Ú
+}R>8óp©éN!‰„¼:÷l!Ć*ð´Ã Y[eÊ w…xsy³/…®“&ˆæÑ…ô}àBòNŽqÿ1¥" Ä˃¦ÓÚœu0iá"Z¡™BE¼HðŸËÀ,‹…0óf*‡¨–ÝàÀÁx¡nÒ¸ƒœ¬Wz™ƒ:µé¯ƒn¬þ¹P_X1ÁSž%ûXáaã¤ñŽQ]ƒ€Öð}î‹Äšx¸Äò«éì6åÊJ‡Õ=ö¢‘6[]¢!$éJTÆ.Usí©I·4ømv—ªÝ˜'U+ˆ¦ˆA·QÆô¾QµBP}¸,õæQ5!]kjÚ«ÜTMJ¨Ì¯pYqe¯ pÑ&(Û¼Dý”îT‰^ñ yÌäB5ãÛwÌF·s ZM™³béð€j€›A;i ªËÒ^)MUü«ãþT'u¼N!sâ0“ÕnȪ ªÝ ï´ó6êr/!? š›cI•·k/î¾ ú’ò³ORy£¨€^“ÜþvçÜé“(Ž&ði.›çÔ
+¹6ª ‘UG}Œâ ÕÄT$Ä9ã™ü¾C5!ü‰(…ºk.V+{Í´*J¦ûXí9Ä|=ñ/cžPíÄ<˜w£:ébâ‘ê25.YqœHâµ.S«êeåéă©ÁO5LJƒN䳕7Â8Ho>T„'rX@v¸ämºAÁ“ÿ@‘éA5!C‡á-×ò€j‰+ÊÊø|¦äA5!Ðs]]¦»P}ëïfj‰‚`2CKÏg x05AüH¾eSëZ²~îMn²ã~?8¨1u¸ ÃîQª%¨pdú ø`šÑ:AW?—å 5FÞªƒÇ_ÑDŠžÂHÑbîÝ~ÃKÇ(ñ×)¥~ºAó#PÂ(œf [ˆ¨¤ItßÓ¡­&þjVJaäCV¼”Ѳx
+,
+«CÄ—Z7ÑÌvRK±.ÃZòÕ×üêL¢L¦¼s)E–Bg¢éˆÛÆtBÖFS‡0Òk\}¬Ã%Ÿ"ØÛ¸ô˜—Br>c¼ñ_n®<¸Þ˜† y“-²Âæ¸J@Ö½Ò€Î)ôPáOÇ×MÆ^ú-ÔumrHÉ^Ix¬‘ø=;öúW®°þuŒ`(bqÑç™(Æ'u½P3Dî Zô2’a'„ÐG©»1ï[ôf;¥î†<Ôù×ÿ¼ [æ»h¯E¨Yæocœº»7ûUÐà ü¢z½Ø>Uͨ`R*©9Zý² Vøa®~YÔÚè:\Z£‘£U…@ª,’Ñií'%L`Â>ú¿¥ž …sld1÷ib‹YÝ&š¶ùQ¤E¥U sÜGµÿ@‡àE%ãMjï tÕƒVÅVšõt6kâR6›@¶ôiAL= Y"#­:A
+Á`¨ƒÆ_SY'
+0§ –ëêÐd(áO"wÓæ*›AÉDëë1€•tÍÔÛ
+ÊôHº=%¡Y“F•VþÍíèº**xÊ;¾ a—„…b>½ì­î ‰´8DšÖ‘Ń˜$~’•x‡™ñ?ÈÄ"øKLŒµ¶Ê×FXFÎ8Sc"9Ú‘²€èŒö|Üw`î€QËoøƒŽ_S ™sa¨¤ Ç3¿–<ÔË1d„u¼JN+÷—̪Ƹ¡Zߢ'ƒÜ†„¯0"",îÀU ¤;ä#z@
+=[EÙóœöДïEq±ZôœµªJøZÉiÝug¥BžÀ¼š3ˆ M"y¢ÿôãÎ…fçjúP´´ gNƒÔÝ‘#~ÝêÞˆlæØví;3˜%ÕP­ÝÖÁ›Ø„Åû|uô$ØgÿéFhV£v9"RŽ{§;ˆz!š@ÊZ'r+CõX6íJYƒ½ ZH‘ ¸ób´.¯µÎ«ðÊP:Æ]ãñ”Ç£§ö-RJšÆàÖãô䇲0.²½òȤµáoi8!ïŒé[Ðßo‚dQ#/ÍC›1ÝAMsAœtžz¹)mL]—›2ƒ²žZ–á")9\Óºg1!-hÜF?ÆMEUUún‚5¡
+ž½–uw¡ƒ>¼FYฉ–Ëz@
+Å{ùþ~íB ×&Ëî¯ÁˆÃÑU, 1tŽ¦Ä@émé\LžÕšfßýºvÑ>6ÁéNµ°M‘k¢Ëý.ŒB±³7ZZÞ–à·¨zm¿.ïß´6æ冥¨™««eYº1+RÙÔoîw̧£DD?ÕQ¶Ð¹"mœyŸWè ™·eÖdÄÒ!äá`ʺ5R¦±”¡Z[1©âÎC%4×>X»
+%Å×­é¬rºË~`¼•ñˆ.ý"®Ðæà õUÜô“ê&¢a1®’·©Ñ°
+yä`ØÑÄ3]ý$åzî]†ERûûc§ªá'$kW
+»‚tùŠ-Ó "t_oÓx<ž¥Ï9V[QeÁ+ôŒ¼™ƒ:Æe Ç‚¨—I<ƒ4Q€M5Wvùß1L-U¹‰š¤Ò)GŒ§è»±àõ䩲a^¨ldŒ;œgdyö±Oã=§Ûî¿PùÏ¢˜(Ȼ̿,)«“‘ÿ’<+ˆhƒ¯Äí8ÒÌL]8 RIDSÈW;ƒ®ú
+­i°¥ VH% :8°WL(ÁH@(™î˜¿ßÄ`è`7yVü\A©éðä4+
+H©›'YxC Ü m¿àŽÐ¥(Ñ(:a‰.>åèÕ‘êÛ*«fð+^ö¼2 …±nt['ª²Ô“N‹yfê?Óý/¹Eºž ÒÖž ³tÁxŠýSq}zƒ¬’ ЄQÃf!)Q¸4ti>ð¼K’å½FªÓÀòÁÖÀÈÃSãŒ7Ú*BÅZ¢†ëfë°’xtPüÍ5©ÜAýC—A€Ð7'þ|ôÐ '®"5ˆxS$ …^Õ50ô¹nÁ#ΨbvlUÄSËø»j-Ö$H¿j·òËÜ¿[î•sǹWUßã•™CÜe:R@¤wçž0¹&£…Ì„"§©*ZMäÓ£º‚m•©r漉«1Šl(ì'Rpz¾üU¦(ë¼0£}œ«6„ÂäÃ+7½×¦D ¥…›³tÞA zF¨)”5xÞoüÛ É/̨ ÄáQˆ ô®•®X5Ñ~5‹®Q/Sö åºB2ÛW3ð¶K"jdÁ&ë1Ê¢Q€L$FÒÝnxQ€Œ¡i6[¥ãCE”÷Óïñ‰ˆOÇ$¡/Œ6jÎNÈ,G-
+eÆx³pÊÀXåX{š!˜]W,aÀ‰ ‡%œkB3$©Üs”½UC¡¨‚l•yÊ<L©‰®œlP±ñKà陦 &•N6²«A^ÍÈ£˜ÆFck^&½æ@¦VEËò‹åí@+]†ÓĶmGƒj•Yæ\×½dm lÙZ¾,ð?mT~Ûô#fBw<¤Ùp1Øv0à|YÐ?”—»’cED¿`þA6†¢ß“
+ƒeµJuw½2³4ixÆŠ_tJáµÐi›2–7Aú Tlñ0¦ˆ'}B/'™Û!éÎAL±Ô äËnÊÈgKÌéÅ9Qþ2cÑÛ1è$J„FøVY§1J±0>ß=/+‹ªÃt1*å$ åËõ¾ ‚¢lùDçÁ±ó
+h)
+%H–ÁÔœØÒdÀpÂcENy«IÛ‰ATh³Ë‚0 ÊM+N•c
+tD?{ŽYÔZ†o@g%1$ /ŸRí¾B:S/xSPX-’ƒ)ÛVóY£I)«¶7´¸¿8'¢fx”Ú£¿8Ê*RBæ/B+HWöÚQ)) Ž£A¡¨BÝè1‘9yb²cʽÇ(gŸà/CÐ1ÿ5†äÉ‘Ñû%úlžAÝf6„ËbòÙ<ƒXjL$8òXI™ƒÝµoº)¥üìÚ#Ö“)5âRÔÎn“gÇ´âò‚’³r»@xº3¶Z¬WIe¥U%[˜x¦ÜÙÍÌ#ë[íÍ~ƒ¬Æ‰6ü~;,Óé-­ÿ*ÞÆNîZôì¢7~!Úë¸<F9 ø,œ¦î$†_ï(¦„õ—?>Âí×??~ùû#Þ~ÿè¢PoÁÚܼ!ya@HÎ-ˆ àÒEK4N%Ä1¡Ee^!ƒÌaý.O—®:m¦“äê! G0U»žË Y|S’
+áÙ¢3ñåôš¶Þ¯ ¹ØVœzÇEdËî2ì\ÚPéjÏÖj¬öÜ!˜,ŸáhƒQ1‘ m-â„Çóm_]ÏEù»>Y¢¤C(+l¶’L%!2çi
++Ãô-ˆ@³æˆ­Å®þ%Kt5øÁ⾂0k% »–awë8Ä(ü -£[¡ñ>WàÑ>ä%pïÌP:%Ié˜,¬RTŠ)šSžvîť4âS NW)«DÍ =YüäëÆQ-‹w€E# ¬Ì\9:áă©S%Ŀƺ}ÚIXžOH©"=Ž–7¦þñÎuÿvºkûIÊaŽžõ®þÍL6T½, ïÖ™ |ã7ЧT?hnUk—¬Ü÷òc¼mž¶k²®˜,³ƒ—`Ï}tì®L.Ù©Ðã,)¡L)ÃÑ
+NéX›¢Gß®“ð4$³à˜ÙlmLߨÐçtQ4rI3<„›æ^õ6˜MQDºI;n“ò¿ º$|sÛ;˜ 3ï $3Ó¦š°bå t-É ôx§n«¼Ðl•ø'Èc)åU)
+›¢¼ZÍU»~úÜ‚ Hñà‹Æ
+” p ú¸†ñ>hs]¼+fJvñÅÔm@×â]o{³)Ë5o®·]krÝŸ×Í'®™ßJ:DsÑ'qJôY´‡±áÄn‹Ê4똛A c„òÉL4
+†Õ5Hò(>{MRAO’òP–ÄИHý$¹f7ðH™„#Øì–¡:’”°´‹Ç€|âà©Ée³À|LS7ŸOÑüvO | K†œûö@¤¸!’†Ù_Ä#úÇ¢²èW¯K^´çÀ_I»âÏ)»;È·*ùUv6#c¸¦±¢º¾†n©˜8¢Äì£"×2•ÊW]³3&]˳åxnû ³ŠR´Æ>[ó‹:}ƒ¬†¸VûrεgN¯ÙõÞ%ª]Ÿ²³›„SŽ:Q¿ÉŠàëàn¿,hâBÿ+ÏF™oáö×á`X»:’h‹ø áÓØ&ªŒ&û‚¦³UŠ’N…×Êô¹eìè$c£Šº¤›ëΠÇ;oZVk­´e±Yd¬E±®¿¶ØãPŒlŸúÿ_¸rΠ-‘r Œn.÷Ù1Æm&úCvq‹Á0‘™‡†ÁÅl>øX }bMýMLbÞŠü¤P¼çss×[z5±ÞÑðì­Í0hÝA”3üÐ9úÇ:¼7rqTm$èˆ äœ «aÌQª-P•DÄQg }¤À%ÃφZ–jï]–HÜ Éäåæ‘é}ÌBr#?ú²«hè;e,ÂB—Æð›à–œÎˆ÷áˆ:°àX
+ì>9ÎXÝÁ’Z7˜Ç“Ù;0“E&Þ QκE$Å‚¯b­J– Ìñ¬ZÅ$&½A Èø`1ÐÞ
+BÌÉ•ú|1-?™ºß|ÝAYÜZ$ÅÜBƒû€’®YØä’žyÙLpÍ ³éTaxZ¾GoÂÒ“ÿ.-C<é]ü¿73åK¨,U2# ˆ!Ò9µQ;§¢sd•ÈmA8„ƒÅh5ƒÐ€p{`ÐûB˜‘sæ16F9”‡ÔxPH2?,3i­$VŸ,Á6èé>¬‘ôš§AB“ý€¨Ñ‚´B£79’±®ªŒµm¹c¬…eÑdÒÑZ¨Š Qbÿ9½·‰rÑ£ŽßCâG03ô{Ëå¸éª OÐÐELÊ:‡My‡UŠOŠ;'øRVP¥æêx°’3‘Ÿ´ HKéè vÌS‚R¿•œŒ*Èù°½:±“~F”á•¢©p$ø¬ÂèVÚ¯~“úŽ!a9ƒ ÉPQ¶&;†Á"Ê•úQ5âýYlKž0Z˜ÊCeÈ[š#vúñ©t(
+Ç›ŠOì ñÜTÒ’"ÜFCùh9¿Š>Ã!7ú)øüaTh8õײ®¢ h¯øjŽí9P“|Zhl`Ó§…!ÒÂ/ób/‰|ÚÒOáb}†¾`¦E_µ!œR=ÍJ«TÑžÔÔ”†£ ³†rFÈÈ ÒP×ÆvJà[Æ#§žý¦9$@e>õõ;QÊ£”ÿ0^6IzÜ8=î tÿɵ½ô9f%ß;/A೺Š5ãp„Ý–²É"ÈLÀ©²¢l*ÄALoåli[Á§Wð/«ykñ}}·ŠàŸä®ò þ2#Ž]ʃv5˜ÈK^% A+ÈŠGD6¦gÇMÙ\ïÂ'áÉ‚ûYÁI ¤6³«5ýúõJ"
+I›e{ '£ÊŒ§(É0¤Õ¼•c~ñòÏÂLd´´î!'Õb8cs­UùÕI‘ªxeV3ó ‚iˆÐ,HýpÍá6 *à}ÀJвR¡[uåâT­½.’Äâ2Ê¥Ñó›ÄÐ U€N MŒ¼\}¢ª”PMÙÐà ©\ƒ¿ê–?B7ÏĈf|
+_›Ð1ÞAñÖqbêXg±xh¼µÙl΀ÜÃÔÿ eÊoìÒÊ{!¡Ù¿Î`N&%‚¿ d’¢£Ù5iQúõ’ÃÒt¾Õ⇠ʭYrá\¡F«‰í
+³ 뉫,@a_f1 ”¦(8oˆ÷÷UeßÔ™)ª€­Œ³“áM´[¹1V\"¾V®® Ç (’¸áýF.¡qQƒã*
+ÓmŽ.gŸüo¤ª¥v?ªñ*̬±0ùVIV¥u]keÞ&yCÉFp8côò*¤súUÈ5Ì&6|HZµ°1M dž4I}õ½S®IóЛø”ï?¤ç]Ÿ>‹éì qJ…~ Re%¦ÿkåíÊ¡ƒŠÒë_/ ú:´>Ò~õà»ãº”bë äÁ½ˆ~0AM¾¼^Ρ*äB#òñAi*“«ÈúzU‘I-±ÖÈdæ )FŒDœµHê¦é-=(ýêå°øUPR¸iZZJ9‡ÜŒÓ¡&Xî$-‹Ed¬æ¼ è ÂR¯š _o y&9sÛCu€ðÁ$z~•Èc-8‚ê@Ñ‘Šzµ·s¾o'íÄ
+° ¢m\%rã_,F§®DÒ1µnx! ¢2Óuëh¢cH‹¥d$]9Á]²‘Ê‚äEºá{JÌxݦ Ðî%:œØadþõ°2¤P+•¼W7KñØYS>ØÚW‡,²I we°––¹¯•ð –4îÏÐâ¢Í‘70Gû*…¹’ìWaI8b[maʲ¿‚…’;r UK² ¼7mX ;\ãMÅ_•´ËvÖ5ÿö2~(ÚkT‹Hst¥°-£k‹0ùoäÃ0„³.ý&ÞÄ ñÛ+mƒfòXTGMN¾‹(HƦ ×úyÊ67È (*ã›pĵ^ÎÑ&„¹@õoâ‘Y}¸òŽ@¨¾,“žŽñ"8E;ÚFª$zÈZ¤ºWö£¦ŒÇ
+#R8ì[„>ÉÒãU·£œdHë¿/g&£¼¿Ã0)¹—o1—0T8Ú]T.’Låâ¢Xf°³”ðé´+|‚¨~2jƲæ6s݈¼mænöÿçGúùçXò¥EwÌ–\ìR´©jͨ(öÏ¿ T»²#AC{ üebT—Æζ#@eop Ly@‚d|a0¾¤§)5ºRWF’oFƒy«ASÙ<8¾› „òBC2NiʤìNV+o‡¯Z’è áP†ˆ‰¦iº‹¶ ¯#ˆ ¹!¡Ì&P‰:Ä1 E#‹©1ûÉtWì-Å¿7ÉÁQUB¤C4±à’r”A  ‘Yákü*†­“Àx~ósˆ†•Ã^Ö´sD¬NŸ7DfMK¡Q­/ùej¼‹« äŠQ§È„ÍýÉ)©OÈL@0tzÅCûL2‚qô4½€èY’ìC€¸Šà„Ò8LÙA‹&HP»$Ì:Å»«2evùfÁųV¾hs1bû «nNÜ ›x@êJÜœýr†ºq´º:úQpž26CŸLGbõÌZõ«ˆö™)‘ù{uÓ¤T–í†-Ûá<Ï (7LÚ
+ê¾
+ñ„ÃD™¼‡ÔÂ~± IÈò«ÆÀœ‘:Ù¿‡ºñóE†¨ûU´H[–R?‡ñ#ÆϺ!M†
+‰'®ýC ­mÜ̧œøÌÿÂVÖ>µbSc§ø/ãe’É DÑè:ÀyXËK߀Wêûoý>#XPe1áò¢ÑÎþÅ!ñ¤‹<—Ì.]œE-IÍ©Q«· Gí’5˜pÿQÚ±Î×Yù9
+ÇÁddùßⶠ0üHál¾$×V£$R…`ÿîÞåa±“Ƀ#-K“-ØV«m†2Uö&&\)}ÅŠ±ODIæºû\ÃÕÅÐиo…-#¹I¹öL©]á2Ú¢Û[5¢%qWâëGV¸’W‡µÓÑŒ¡g¡Zȶ'¯]AFÁºÁ€¨5º¤!+¾yW Y܋糩£2\\¢ g#t]'qIlõá©Šfù°ùUA”HÂ"æ=˜¿Ìðr‹¶^*­+P.,°{´*¶T¥/dR tÙ!¨¹ÔC¯Ÿ Êÿþ8Ò3¼‚^¹¯Œzá%²ø¹+€!]šŽS)ë9ϹTGžöÕ4Fz¸a@h$Ɍ索rzXúmûŸ½òÐÌu¯çd “ɬNwŠcܵåñ;1¬³Ššb>Å ŸWÁFuˆÔ’žˆ$ß µÿ(=è ®©Š¬1`@iÁ¼”ß!l/·H2¶»sw¦íÑV°lq›š’v³Dæ
+}CøUWLê†@ ñx¸™¼cÞo#úýqAF≞ ”õ”èmôÓàûòÓ-ÙipÊ‹™*s/3i%™Zƒdi q¡‡„¦h|– ¶‹C
+œ¤ ±Ÿ“p¦Nt!³¹[¶¶HÐe.’°×Áñߢl5úÉÚ!ç7Ä{ô¹Õ¯AÄ
+Ä*9vÇGŸ)«ÍË
+¯ð/» ¶.Ã"Á±¤›u²˜ oc»Ä˜*Ú÷8È 0g|œæ)NÙVäîH$;xVjZÀ_˜µN€ó3tŒ ‹§´$}Ç8*ùx:™¼2º1–ÿÆFs¼z¨(ÒÔ´Z«Oñ,ÍÍÕÌŠR„„}UëÇó£Ï,fVž`ÚqwjÂaap¿±¢º6¥Ã¦Ñß2šJ5 {z!ôáżèÕf¾VXz†9@‚)bÚ/…sIA,ÉZ‡£0®4ßìý0TK7á9’¼´ië: r ³×©i꧶9X; |Æz¢ëR¸©¨ž’ÿt€|üË^M<…a©LmÝó›´³‡ÓüsÂÄli+„ŠÞú9c2‘fbD<Ÿ Qè.R"Ãí] ÎÄ
+‰‡å_*Š#ñ¥mŸ|¤ªS¿†vRë°Õr«Š,°m^ëàÐ&h³ŸJý’½¦Û™ü‡7þ ±øÜÅ“Ó©ö°.2Æ…Q‡@\•Ÿa,ã‚?“Ì y8¯m…¶À£¼O©Ûˆcö Nz ÛV¡Ñ#Ê }»:QfbX®¬0œÒŽ„³­ÛdcÛ ¨ZwÊ2‰”¸?l6 “aß:W ,ð(í–©pHb¥G}¤Êeó«`̃SnÊ`{áhš"ø:IûÉý[G†o`O{öudËè ž¼ÜAº|‡²Ô¾xétiä¿å/¾À²¬½ º¸ÀŸ;Ðsp:A:ÈöPû:n /ãz6®‚h]x$ɉ$&ÆœH‹/p~]\â!„øNW fyh8¹R<¯"÷˘c¿×{©Fž 'CÞí% ­qœXÏ«Èî æ.`Än$f÷Wª÷:€5"Œ6 Iý;oŒyÜKü4”“ûòËO—{Ÿ@—ò!Ïop‚¼<% œ^‘ܶ˜D,§´òh+ÒEI§D+ƒT…X’TöFÈ¢” ÆóÖ#º­˜€!ñƒáßY)%‡0¤<OSú ä‰#ý9g
+F!ÆÈžKÎÃÉù6_ ^C¥98×q"E:¸žß‰Tþ~N(ª “±¨aú"08åeeþVžºKžä OéVŠÇ F`È?¦­\œ^Æoæt\§ÑmbuÂÌô³°)®=jHÆBƒT»´ÌÞkŸÛNÕ¢a1ì‹ã=“’ƒ=U£¨.ÍTÆcÂg&)„ApW¼§œíô{Ã](® T­¾v+a²xÒÝÆu™a„ª„¶ÖAJ°[8†V7;âx†\C·KIKœ’ÀíH¹„.ipòÅ^Ð@ör­ÇK+©v;1Ù)šv  ‰£(‡Ê½Ý (,˜zÒY«C_A}9:¥ ’/Ó0RŒ¾ªSt â-)“?—/»bÒ ¦ø^½jKÍÒ-Ì%VdLoƒp»…‹gžƒ ³@H7_Ä<´K|Ĺyó"H–Õ?n÷.è©?oTiÕ2¤/fe®Ä‘òM1 ë¡)¥êb)!Ê» C¡^·{ôúx¡|ÚGŽ´ÌÞªùÿuR9ãç_xÐ/ÚWž<ÌYÜïã½:zCl¢ 'ˆÖ‡„jÖŠãsApl‰2yJD¼$U'Ð>BÀ¦=áDéM¦7b™ðj ·Ê3:ˆ¾Ðmy†jë [Ì]ŒXÜiXcb»Éi ˆš8‘Cd³èæ ,i[ ­éNa ±(Tu­33E&˜Õ˜ýV°#ø@P%âѬråÊN„¯ÌTìmi”¼ö™¢ü‰3€R«;UØR‰ÖV[$’€º¾•ìD"y…X° IC$£Ë<@l+,¹ž¡ªãf*…GÂúó87Wâ_yXò‰\»U1À”¾=‚
+%)¢_Væ']m¶^ʹæë$Ùn
+„s# $km¥*žÁûâ6’ryÜøòæ,åèÂ!Œo${Z·á"Ü|ö Ó2üˆãf
+rÁ+ܹi3b„6ä»ñ]Gév2´nûȤ½#«vÙ»!÷P$<IëàGm$²Ž‡ÅœÎ–UÃÅþH8ºM䙪°Žbu¨&5.åa™’I1H’9­ðFó
+:ͬøQöûù#2Ab²}R¥Ÿ¸ñ¹!Ü"hPܱ ¿„VÐŽ¾•jdWt¼UiêC¨¢ãl¼Ÿ›}¦4Å£ÂQÍYÈ©„¡‹Áä>˜@h «¦,±N"b@Pbz¨s#ßH^.„Ô”G„«ö
+Ðû]Ñ üï'q2d¤Ø]–í
+`ÖØCDÕHKÇ{L–%i$#Š™nÞ3åÒ*?–Ä,P53<ÂÞ¨@ƒÄUÌþ‡µÍ> T'꘷ùAÈE]bA$Ùˆ¨Ÿ|ˆ}ÆZ-•Ò8,ŒAd˜BGÙ¢C`©¯ûME“ËÚqÁ£8&óŠµEoÐ1hî+3*IóJ
+’Z5d³ç|üŽø{„‘3ÜA¨¶'»Zêè êb û´J±P¹ŽOòù%°*8ชlkŒ*¤¹×‰vUFö~Ñ5æ†àŠ‚m3vé'º€Ï&)æ•Ã|™ü@u•ÿÎ)çDºN‚K eñùƒ©;@ÖQâ}¢GmçwùŽªÞµÏü”zÿÐfRâ,Õßhj’»‚‘Ô?(DÓ‹ZÝû€ÀX|–³ì; m@º‡S…÷y2|]‡Aø•bÝ·xH¬’ß‹F?JÉ%ZÊœ^45wµ£kß‘Ø!D] ãDAðAòöÿw–3bç3ö“2tÚš‡í[‚¬F3‡õ(Òý ?s£PEæÐR_o ߭د'Ì‹¼œmßEƒþþþ´Â4AW‡ÍW­ã‡D7,–fìÏ ¨Ñgv…ç =Hlb0’ʲ(‘‹£'mûìaÂi‰´¯bGƒ1…[㈚ˆ­¦GÅÈzuò)# ‰®´ªm­&ÒÂLl2RÙ· RúºLAÀBáDc°‘ð£ðS1ɺaSˆ
+a q$Ý,kų¸•é€ö‰×TìËŠU@X Ež”Ø!D:uˆP×IÌ÷Á¢åáý $-ÆšœÊgÊÇÄ°¦†ryýÂéI‚Ï%K5lÌ
+º1Æ¢£
+®ÛÅîdBåÍwˆ«ÜŸnä}TçÚý9Û4}éÊDŒµEýsV(ÑOŠz¢iæuÞ)‚-Wd[ÌãIÁ@(¬ae(h
+ìÁ—ÄÓø­“^A²xÄO±È”=9\†íPÈPÏÍ^ßÄŽ6Κ¬
+mö£^kƒ°¦òÞ˜Ždßa^˜K;»â¼n\ŽÔ𖉓È:j†*z˜€Ïßanø7ê‚dÅ~¤§ªÅŽÔK˜é¢Zâc1©Uów“
+*Ã3ûf"Tø“5²9®ð-]k£ôÅé®zÚLnÜdú÷m8ñÁæ3í?OûM£Tªª:Ë‘'¶ÿÊ7Ìr´¨yUæ•´sÛ’‚ìä÷ ž Æ“K¡
+%£GÜas|§1¢4–Ð L-&=‰MµÓƒ²¢/«ÔM kRUd¦î–EÊ_b‚Ýh<× lHÜž*DÓGäLƒà]õ3Ó²½Á“B®ROÅÌ(îÎe4§ ·ZÂâ‹
+åuq=ggw<ˆáT«²šÊ?•_yê> {ÄTr>öi32"ÎÊ☇˱übw“Ŷ•èÔAÄêѧœ–ïâwXâ
+⛽¬Â·*%Aãs×r‘^‚¥Ä ß"¯ŠU±Á©òeØÇB„ŠJÓy'/ ­–—Èò(J’÷¢—ã(ÎÃqð~Øêv§kQYl
+]Âvn±Óõ¸¿*¢S8ç½gïV„[ë
+™¥Y óH]ìÀ/B¨yIºGI¼0¸hg®Ç4kÚ0ÁÔêSB«(
+ú î]æøð9*hZ8vX¹ª,,>˵aHÌ@ü_èžéý˜qSé8~¸)!“[ŽH?u[_¤‘U&hΞJ^“Â¥¨ø·T5öG5"ŠÑŸ‚Çð£6¶¿ÜVü¥ÂOB_OPš¸†a>vf„Ä‚£]¢Ãµ®,PŒöá5dõ
+‰/™Ó[Œó£6VŠã{]¿5¶UihÛÑ ÌŒ]½*{‹Ä7¶x]ò—³Š·›0ØOcHBЮ³ì²öx…3Ü=c¯¬„}a7Øqt8XÕÉ•ãñgvT]œåÉm]‰²Áä8¨Ùd•¼€Fõ˜°— ÊòºœK_’“ÅO@É€…ñ3 †·°G‰.‹;C1C™\,çkE1¨—Â7Ù¾kA‰Øˆ“ïåÇO—ašm‰Nç¥èëCQ–bÀÒv¾)1ì ªE£iç0¹•P V§_lr¸‚ÕÅd$¡C:]½ã¯4
+߈–RÝ|~ n›/°c]¾š6tYÄcýI–Û¨³Y p.[â@†%øWˆõï(-ò÷„–ÏÞÒò
+.<_ñJ†1mëù•-f´£Œ‚¨4;GPˆ{˜éáKŽk€Çà©žûÕ±óFfìëNy_JB„{GÉKèì‡ïðr.¯å$0üšˆ“4V¯†ôÒ¦už&­•Ã,½CO¸4?ƒB›œ\ •j¦tåÓ4»Á4áù+ ¼ÈPÀ8KI[‘Nµ ì'åÆ_V®€º,ÐŒQq,AÏ7ÓzJ°&…¨´ó,C>JôµÒ  Ÿ2l}ÈÍÓ ÒP ™†é|8\Ë9BǠӜ󨒞ÝÌ…‰ÂÄ G”øBÓæÅI0?“Ò•¨ÑÆHË5UÀ¨M‡Œë‰WÈ[—óoN˜—Nº¢¯£}ˆWï‹W/º./°Ý¿]ÌÔ7¦Lþ ˆ³C™¼@NéÇ”þ–Cðn]–,åËàcœ
+ÄÎ[†¨Ÿ
+¥²
+Ê.î'¥ï¶žuÕ0ÎÕžb…9ÜQ™M
+¨Bç&ýD —¦D Ûˆ“6U
+iF¸Dz‡¹#O€éðwH)©¢7'J*AÇ*ùšÑn%,šC É„Æ9ïE@9±Šü¶Èµþôy¢0 uOåPò_á “°¢ðªb¯k_QÒuÊ{*ÉÉ<־ǵÛ`…Ì(W+!4f¢9"|
+íll„4U0ÎÿS^îXnÞ0ÞŠW0‡O¬Ýzný·ù.*‘DLºx‘?ÜfR% ]åK÷!rXô¹ÁyÑdþ³ËdϾ—>½h óqBòA2þ9nb·p€Ã}t ¹^ZÂœ3P¨øOulw:îÎ( °Ä>²_xéØ>EìœËrŠ8¢`rŠs†øÏd.ú>‡}e Ð8 p”ðuXRJ1,΃ޤc~ŸJ‚+º2€´óò·sø\P. xø„ÏS¡#3oZâ €¸rh‰OCYVä\…0yøìeš?öU9Y‚AÔó*¼
+Ã1ým3 l®ñ(랈Dµj“$µžåËX¬ê‘1›Ã7°3äPLÈ Vbõ¥/}`%_ ŸyÓoê7ùìáÄró¾*QÄSøzx_œg“¥·Ñ>• ¹#¯"YBð¥èÎÙ0¶ÅÆ7k
+ûÆ8ñžmH£æå²o‰¸«`%HO'‚[† ;a“}{$Ÿ DöÚY üs…-YÝ2Üãwt¼øgoEMnI®@„ñ¡d@ãÈ¥ü⇹”(&¼ê)‚y ¿áoljxjš§ÌÛTºR NbÂ<ìÃQ‘ÁÀ±ç[!®%ÏLp«ø7¡\+žÜɧ=ýr§Ó¾ «+ÖZ¶‹!úË‹½"‹ù±6V]éÔݘÜbx8`&à½2?ì$ Z] Ç)Q¤©Y>É?›?Ȭð©¹ý$è†ÖÙ×|þÀÕsWÓ–r,Æ(ÍK™Ò ôûñ¿CA
+Ρ-q•¤*O¬tb†Ò
+DAoBÞKÄ@ÄLñKqÓKœÍ`é²ÒíGÑorIKɃÏñÕPþõŠñ—’Ý?Spc‹ú‡cØñ®´‚ÕˆàP+,{]Y 8ñÃlnu 0ÇpöH3ŠØU\µ¶/•·-–V5e‚›g8J‚ƒÒ
+øh²Æp4¼ãJ—eÖˆ…B6ô’Œ¾Ñç cZ«Š6bäàGØ †¼ÂA¼ƒ,°F‹§Oe2•%»Ë‚%ܳ Zw®-jãvõHÓÊ0æ¬ûÇt’‚/8*Jà欥‡"ù¯9ëæ„c´ÒE?2Y.^a_ºf"Ý­^‡@ Ì3/ùÚXÞ³h€%n2÷W5Áp[†R mðõƒ)ûs÷S°u9,×ãÞ?EF<`㋲ö‘°´Æ-WþúPÄ€V´{‘º¨çÓ ˆEZm¨ÒäW¬\äYÔº¯³¯ÊåÅ·‹n×/ÙVjKó½µàvÝ7ŠÞt-Rª»Ð)齄üÚÔ€†2ÜK´üÿŽÜº¿ò"¾oH†¶“ˆ'é†`)K­ ‰Êw~{J–gÐ&¬ºJ$•r‘Pœ{Aö´ÅU¤%VƈЩ9Áæçô¤Ž¡ÿJ‚»D oÄD¢DÞ|®u8S8Æv·÷|t~NÀOCIÂÁþhE´z
+¨Ë1
+=
+sõùáQ%áó8Åì¼)Cw깉·HLÔù3ðŽù%aiÜȹ¦
+“@ Güø¹t@4/Á0f¥½%È4»ËZä î7uPM‘ž$$´˜C@¨j]b=±±|(†£(ñP‚é“A"åx3Á•î£ñ<+®¢KF¶oÄ9l=eÌ…Eös
+H‰”—Mr$·„O ;èî
+™sYø§wt÷)aæÝüó·nú˜+7W õÏ?>6¨»…µÑ[/ÐXË­MQ=çtÞ"t¶Uf}u6Þ@\\úðµfë×UOïiiSúšcˆØçÏ?ÉcÍ5xèm 0]o²xÕŠáöù×-(„äcy_ù¦Ÿ€ôK„èb¬_=]÷õ+o:O9‹4¬p—¡ÑÏÃû£©5m­¸ÈÏ[ˆ‘o}„ê°¾A¤NÜL”uýeÐËe/‘ý
+ä¥n jÜ×…Àç°ÿ$B3 ¥ï ò úúïLg9äó÷:ûÁ»iå9gŸ;òˆ¶|i›’5¹Å8µådNÈ¢J]‡JH×&Ú=ÏŠ ‰IÔ¼Qˆa<‚™Ó)äû*Ú?\Ý8«Î>j¾fxó}NNps²ÖA4ñ!Æð˜ƒåïË\f o`^‡t1­› _Ò²Gû…í¨ÂL3<ZÓNÇ\tJÐ6¼è@Q5%±Ü} .J„cÖM|ï„ÚÂO—eßuŸ»­˜ƒ,„â7³y $w)OBØJ:m½œ«dªKkÍ[ïoÎid”úvþ‰ƒ…Û³–ó±ÈV¼*
+1†I•jç"0ô\¦kŒz0Œ1•!}k“É‹9ÂF¯fæ'‹ ÍäbCfðgÍœYSÍòÃ.uUm+Œ÷êrŸ<E7Û9†<FP£ÐQ-Íw™6“ë’Õ¦þ=Ó°!F¦D¨exÔU±i¶ºžìÑļë{Ÿ®çi‹âÒG½Îfƒo[o aDNM¼_=Aô¡ 3AëÁÎZ§HφÎfóªÓsöÐ*
+öè
+özîÊ!¦9mŒ3Ú˜ƒºŸ®JC1U—ÏjˆœJZANâ.ü"ºp"zžm ü}rŠ×[Ž@ü•
+ð¢uÕÕ`S²wù ꙯ž„ýŽ÷ôa#rØrLWÝôÌŸt¤bK{6×ç 룃ì4u ù7™ÿ€ö[ѾÂqM6)îû:SOÐ;Ð’ï“UXWLäÌÕè y¬–+q3»ÚÄhŪé (Ó¸‡/aÚÙ ”jSrFupU«0ÁXŠäUCn¨#½hèQR†Â1GÍ6Dù$Ù›«ë½‡®¬_ÖMð\Š>ÖëÅt‹EÊÓ¾Ï!n¸c§û¸gç¢Ìmd1Æc Š˜§­«z&Kªxuлêà§O;”é¼Ï:%)2E4®§>Ó$s R¯ÔÚãx Üÿ By³SÒM´
+ŠÅ¼$rl Y&ÞAö»×–Y&[æú’íÖ#]~Æs¤s_Õ¬ÔD .ÕÆ0#­Nì‚4ƒé\p9 ÆÈ
+D8¯ææ­O¬äu¥§öQ>f³jI§>üÊ9¶gŽd8Nã¢ÊH8l6V6šœ ô4iÊÒ†RP`:ÖÊDz½Á.ÄHO§Æ4€¸xô¤B‹´x{¾§Ž±K'uQ&,Ä jÄÛ«Ð6’IæWxƒõž™›¡{‘)Zcïk7D
+D2ýÐ3<v]õB+,©ƒ<Ï7œýþðOQüqÓèëÖ9ódTßiKfõ¼fû$Œû•â ‰)¥^~kgmO’Gg‰_cGwNÈ.ùñ€¸ÁK#,zò'É3 Ö¼ SÈXŽCç` X7ù+¤|Ò“tÜœÓQz„VöB iÇÊ/›Ãƒá¡(ÇTÞp²~2zsK๬œÔÀ)äV*–f"}œPOa¼Xr°{M "÷›ló¥—( |ˆ
+sK×®,Aµ0‰°-^ÂÜ)s$gÌ‚P¦¤¼‘ëÞ›m
+Ûî;f×tûäy”½‰ù%ŽÖ*…–›.³]îð^Z\Ô£ÉηÞBÒëàp¦~U´ØRБÿºŠE†.„[ÜÊ° BÆL^Tà¸hD—
+Ò‰@Öc3êK2ôf~³ ëÁ
+{-nüb 8l9Åýêœ#»€qùññç‡|þ΅†Gp0œy9 ìóŽØaþz¢qhÓ¹­W¶=]¨„Ù(÷1$%ð³"ù
+½æ°:$u»Ï0^ήƒ—iÜXap h/ìc°ªmó\?Åf_¹(uÂVçQÁ… •h1Úp]7¡ÀI÷ø˜Sw@˜\ÇF°Î}΀’-rç;n '”»Gîcä[¢öÄ?¢‘
+·9*ä=¿d\a¹=¯ ›Í"õ
+¦ BöÏw$µÁ÷¶k Åùïnéè<ÂÕNv‰rßGÉ@¬¢¶@€ÉJ›õ™ª€´* vå/Ñ) C‡œµ-Gôe{ÎO
+‰¾ª„õí’AÒ@GMG1áãCÆ Ê†ÕV”«WÀïN†uñ.xu/ÂÙ’I°INF%¸a
+/ǽ%\~‰ŠIráÎGûsD9p
+™ÌÇ™ YJwÄÆ»¢µXËçÿ¸.ºÂ²@ëi×ðX¨¸{ÄŒÕ!²“R“]¥ïóܦ,y<΃0‰ì@Ááz«»µXU¹Jœ”± >áó^ó¤sñ`Á«¤¿Ðo¸fä9”)â$Z˜‡.LÕTt•Âb8q± PþXÃÊ°(KZ‰kÝŸ”wÁ) ž£žŠX1ŒuÑø⨷Þè'~S‚1n¯z4ýÁØxGýh`*½›LšÇCk1a…E”ÐDI߉øû´Šn`æsnc¶u pý ©€ý
+4B¡ ¥¯›AÖ/ ¹.ñæñ¥,DÊuö)j²Ç"¯Ž?! çHèHwà|L) ¬ø³,IA¯€àwå5v“Íé8Oùggñµ¢‡ã®1÷ñÖÂ$Š, ¼1D·§ËS!74~#¸ûÞBÛ‘Ìz o.2¦)sè­Òm³xK˜A–™P̳ȸ7lX $‰jò2ö:`AdâéÌ°µ8I¾ bÆ+Ž×ëú‡Ùg´ÝÕTdÅ$`›¢½ß£¸™ì„Wìøý|ǺQ+bF«x}¹íŒ<tƒŒÚžgó0˜¼¨Óg/Q´R\Þ.QÏÍä–-$°)±Á™ýæ–$û4øl¬$ÙŽ‹4€&ø¿Ø¬ 5nÁ`®ã]¬cKMCn7skb¹åóéÆøÌÜrCTc9®ƒßÊÀ§¦|îüÿ«¨z%¦¡íÏ*šÑYýrŽ{z3' ë¿?}ë9Àã½bmÕ€RoŒñ@®ì¯›)J–ó#,ÅI9âÒGÈñát¼¨©Ý÷Ø%IlŸ¡C‰˜¹äOÖôÛ<ÎèWzÕ•¾ÞÞê‚@DñÆìôéÛ€1fq÷M¤ÕuBQR=_t–µƒUw M䃜Z„í8HÀ 1ï-"X䌯e·<O
+4  ¤Õ°]æiÈ~nÏg4œ!‚¥_Á2˜3ÏsÔ²Ø'ÃP¢—LÓQ–ç9Ýæ:‰:‹{EÕ`ºi)èüëå·?^Òëï¾üöÏ šü&‹‡˜+ù©Q­a¶
+þTÊöò{@KYð×û4?”ü°iBÀˆ'gï®ßÑhØ è›é–3Ã]Û–RB{¦X·ð‡xÚJFÕ¶]-ű²†Ë4ØšÃÖ°¥r=Í¿C<ZMÂ×P' ÈxeúÁK®%CqQ J–äé^$C+çßØÍóRÔß{,£¿Þ® k`4aŸ¼óº¾üAIüå”ø±0’™˜ÛEë2Ïgñ.#\}«ñ©d×-Çt.£FÈ?:)Ú‰HT¤xyÉRô 
+QÉ“ìÔ¢Mò
+’, AKÕ_^ZàñÜ‚Ži.HNO³ê ¹a Œ2„ÁÙ™^¨§ñz›Ã“æýR:¿™Âö·ª$Œ/†Ü«o2ÛvEVâïk *ž¨=`¨>-#T s®þå"ÀACsÍfš¸÷¥¢)·<¶tkØÌnEƒ¿`TºÐ4J•¤¡m‰‰,"‘ŽéÎ) €X¤~¡úkðÛض­ßùap ‰ æèl‘_‚’}'«¯†ªvJþe¼Ìq$9’(z‚ºCÊ
+¾/â G¤:'hP«yÿyß̴͢  ˆêŸî¶ü¹¤Ò Ó“‘«eµ;€Ø§”h™–MT©7çÐí¬È¹Å#!žZºiåuHåWHЀAÏb¼ƒ^<á—݇bÁsÐj[.ØL}ä®­4©wUªŒr‘ j¨ép¤Åævã  YªÈXê32‚Œrt„öd·!Zt͈X¶a|,ïr«Õi\ÛšTû‚,‰R{^"qìDÆféç~Uµeë·«drF.­—]æ äiJ|D `ÞëŒÅÅX"Òß;øþ¹oži!Þ®gŒYø†ï’ï‡òG†jƒa€3‹$ì× ¨O‹¡Â׫ÚÉüª!7¦î•]^ЖÐØiÐTƒvO¿ôĥäÖ§jàUV…y7Y5SýÄVýaðúc̶j!­ÇX¬ÓXÌHc•àÒ@ìSôcQÉ3 —ƒŸó¼þvùy:ÓÙùyû*¼7L#§ Ë[uê'¦ÙŠB;¬qyê•}êqL™kìO}Ä·ai\B®ò¼y)Ã
+w ü9ù÷…;ß=Gbg ŒØ &C~ú”ÿUÅ7¬éÖŸa/ü’ùJçs•HC-™Wâ“
+þµ½g
+ê `à…µ½°™Á2êMú›¤½­)@Ù ¢‘“¡ÁádL
+‹[„ê9‡lFHÐÒöÛHÉ$JíÄɉR“eî©ÜÔ¡Òc*«¼LÉ€:÷`'ºÁÿT8}œsà‚Ï—Ó¿ò*©²/ýT H%ᮘ£k1?|Z!ñèG%ÆQÏ|ÒÊÌžV+¦ˆWlùdª7IiÕ?EŒRÚCÿ3«ü‡LT•]ôO1&ˆ
+^© CÃÐc7[:¹#T)MÝ…ºÞys" iÝ´ý’ \éæFÙ†U@¸Øþ(¬ÑÍžM¤*K&£ª$”«Ó
+EØðFVÆ›Œ:éu¾<‡f£Êqœ6MIÒ–)\F©È,ëÁDûÒHµ®œ†®ã}*ä[úˆ/çMùLu>açHøL%Œ¡ ÃM—®'£°Ä èëÄIu Ù¬Yý2÷çg N6ÃIKÄe¹•0Dè Ô½á˜u¸ˆXĬ\T¢—:•ôù£¢
+-5§u¹`¸¼Æ H>3:ïç b#ºˆVÚ¿?õr Ïžˆá
+âŸzÑò³]{±s¶Ì*ÌàQ‡7²4A,{ÞÏ)ôöe¾\E~Ñ”$/"~Y_Î… g°ê­©Ü7§ÆÙ‘ø˜¿©Þ(YTy¾-v Òáù“Ü|&pºh òš-TññÁ°CüÍöŽ]Á<4f§{äã F`Òj2²â²2]ì¤GŸ =O_<œ‡È¬>]¦ —®
+†L² M‹Í°i ??â
+ÿcÜ÷)wÆÉ!„øÀœß1BÀaEç {Ó'‹àÝ:zdÕáåp»Uü¬À ºG¶UeàˆS’?òÛHÐ
+ÔN—ëié‘0’ñŽÓ)šúµc²{ƒL~ÕR‡ðBþˆl£>§:H.Ó™t¢—Kó¼sì0ÄdÕḓÅ3Ž´ç$Ü<÷ESó #í7Æ^‘Mæ¢l%‘LŽÒÃt°h³¢a%-bãh+0 _”1ß”wI³þåàíDžîÆXÃÀÎAuCùKE”MŠiýò%‡žˆhI窒ï )™Ø“vˆ.U¤ò©«=xË\ßåæs™uÝ2œý@œ$®M5»ÿc¬æÒP2U^#†1É:i.Üôãå)ÓÄ­‡ E&°:’Ý@JT9=þƒ¿«­ŸçKÇ”á†ñåæþ›Ú3ƒ}xrhq-K¬=„—sa¢DºL-öÂf_zËþ©ž ÍY~ü$”çý¹™ggHP1טø„„Uøî’ú>)l9ÅåÿÜÀ1ë˜ \Uîí °
+âu9¬@›Ú ¹ã½õ1‰ò‰pIBwÂsògSkXC9ð6™Jt®+nÍñ«Äã|‚ùAèSmAu)(2"‚Í kA^zõã#=õþ+a0!ä¡*,<¢++ÐÀgç¹áÓ‰Qèp’ç¯òk ±©
+³»óçd¬ñÚˆ—p5ô-dFö25^|‡¤7P‰ÜF½9-¢ßðUgÜQžVøF'¨N´4Ô¸µŠ³R Q˜ÁN(oõ€þ}AµË‚Q½†—ÝÃ-^E‡÷X“ _û¿‚Þœ‚@C
+ê°oÆòP»ÐTÞÿÔ7@R¶2Q~úçü$ˆIh
+¸(Š@-;Ž—Ï$Ý%ˆ4˜Ëbì<mú´)d–2+P„åioç-»ä”6lÄmÀsÑf+!0ð>DùÙ£Y·òF´Oå'›%à@BÛ”ÐéJè
+E©Ø9jRki~ 7{ܤ(
+ `Ú³vQ_*#Õ…ÑÅ°²‚Ç<~‰öŒÖò»‚:%+ФÝZs§
+ƒÖ‡·0„ œ8aCF|Qˆ ÀعÍû›·À—¢¯E
+Éü£å§ä¿Ìleë*»ðlÆZPRV5fœ´'*!L¤‰œqF÷6€
+²Ð‘¦˜òJ ·0 ²ÔõýÍ/ÒûÍZ€vŠ®’¢+wšÔ7Ò&_®”?"¶d=EÁƒóü£¦P¬Äµ‰O÷ì1‘I6 oG˜xŒ%@³sàx¼MDU\mÑŠü´äþÊ#°¦È4Z‰«kþ9é‰÷Ää¿-愤b¬¦ázQZº±½ÅFòûPb•‹Ô‚^;{S4]-ÓXÇ2¸7>”w NŠ¸2…¦¼J²|H†lWûps¦£ÇQ—yó‹” 7[ÊÅ…ì9ošòQNÑ×&L^žÑf¦¾ƒ@ Cª'_ËŒiÓc…Ö¥Á`•
+è×Øô8]1ˆIdË:fªG§dϺ"ʱð'%]ÎIFtÌ…sæ¾ ˜6ô³‚ÕJ !¶Hw™Ç k3{]R/JÒC­Hºävi¶uh°Uá%ƸÆd~‘&®i*Œ´Éi­’„U‚U“‚™•$ö¿›…ÄÍ;¿ÁtÑ鱟>m?±¥-ìÀU9–½éµK–„¤)5OÅ¥¸?R¥XUt
+¶CÐGæCFjàVüË1â˜\þGœW ®£LÍaì˜Ê†±Žˆ-IÀF—Ì@[“í^ÎDæ´-FÈ9¬fœòM`exG%x¯*äó9ÏßèSŒ“@’ðS„ôâY¢
+â[Ž%ƒåqM‹:¬D>‰ÿú$óîH*hn&ª÷¢KÐýzó>†ÆËÌ°/]ÆÛ»2Ñ2d'ÄÜݧ_JÖÓq,ÂÊ[î9 b4
+1!XµÍ\Gu¹ÑTìŒ'«ñÇá¤9ŽE°¹q·5Ü Aæ,ùþÔVë[|z·‹(cùè»ø8EˆmÁ`DŠ@ ¼9óäžÈû*ÁÂ#¦dOsx]o‰¬W"± +
+˜ø£Ê…uuIðIC©•£,áfŽžvŽ¬E€`zJž²¨ûÂì'7nÊ *¯Ñ¾eãrÎxFœ[Õz¶xJ~H!%IbI©0;’Ê":EÐ4Ô “åK} Jƒ·XýzB("&(D\¤=K¼ß‚òd¯žf8/¿kÓAçœëœÛ\çùóQëKWXÀß|^[ñ²>'xƒHŠsyQòÏŸ¿Aò·ôôF«ÖŒ§Œe_îÒã]¥‡±t6Cv¥‡~‰YÉ\"MWz¨päEdŽ›'=<.
+kÌÇ{FôƘJ‰ `J[Œ“®î5 ÔÂÄÂdoI¶ŽŘ!Š‹>F Œu¡ì 4ÐHUâ™×£PZD/¥vf§³H­-±‰8º(:È ÂOtJdA
+'v
+†‡Æ.OsuCŘ¯­J,gpú.KŸù—7l9bpƵŒ+b¯Û\IbðmóOÑ“
+GtTc_¥Á¥S{_‹I÷ÑøÐQ’ýjŽ¯›êºgrêÔ@ë³s'¼†ÊÁ 1UW±ìIPÅ> zš#"Ou…Q3]™a²‘§%j”—æRטù*Ëk'åRà)±o«{6`ji†¿â€ƒYfKmƒFqϹÒìÙV:l}²§k_`ºÞ”É07ÛÈUê¾–!r,¤B©ny…BY‘üð5¨ÉQe¦žl°?õƒPIÓ K©pËâ°è×1ÁP–ºØJÄá½Ëê·1û…=gí¡6ZŽ“FIl¨ÎÓÛÊS12QGžë*ˆ~Peü`Öàå$=­ò´Á¼AÑÕMA Šr¤¸xô­2W
+r’Æõscüx§Éü¥Öˆ;Bç–vÎp¨Æ࣠_„»ÃPáqÓÛ(Fš¤Ñò¼•º¾¯a€pÕMY -ù(aõ¥þS{ìæsoP^.™f#ËÆP#æI[% X}þWA6H;Èm1Gý¦-ašÚ¢SÒ ¨a†åÁQD– ¬zc¹ W]“²Î: ®Hd®n=ÞŒŠN2@‚(ã&oþÜÞ58Jö‰zú–<|)Œ[µ9mjt`{lO–¥!õè8cQ“±ÁÔ³†Y$ˆÌË£ùÜçàÑš¬)"Š ì"ÉqCŒË:Ó™(v@N‘è
+Ë÷§þ{‚4gññ?:A¶iÇš)
+"Ui
+wÛÔe5™<\"îò!ÞgØø¶!xp~Ç
+Q£–žZlÆ‘{Zr ºyz¶á\®¾‡sŒ’D– 8D‘Œ+ŽHP\‘
+F3·•þÚÓ&
+kÇÿ:ÈŽz*Nž¶2‹RMn‰¯S«>?|ÐKë» µ"À² ©=¼+wÜ|ZGÉ‘ûtüŒ|þs:áõôs Ñ|,/ZÍ̇µÈçF˃¯ü¼tsz‚ø v9G1fBG3rïÞ†`T÷ÁÛÍ«4í™g…$yw«sÝjœ›ZU&•û»ÇÒ"«1“ö—~ØÏéª  ±~8ÿlÁ:¿CßQË4´Æu<…i¼«X½qïMæn¶Ôb¸3œDë¯"˜ï[¸ò—»hóÖL"»RõŽwÛ²ý0w ?Mz†umÆoæ¿Y)S†â1´ñîJì”rF ‘£nG匘ˆ½ñÆ's£¸fQÓæÕ{¨uçNhBµ›“4€VPoNjÍOK?·WSðÇ_púŸüñÏZõŒò¼#“h7/éÝ_k¢uaòàgÝèäþôxF;ć Aˆx'²ëpH­3*Ð ìñè¯ §éTœ¶ç™è'G@82:u×É©½+4Á€‚R^KÙ:d¥çØ”óD€æ2ºNÅ>âa†á‹R|€IѯÌãƒ$M
+yb£Y Âz…ƒÂC9ðß„dž0>ìÁ!øo5]´k˜*¹Ps2V6«Of‹á2c½N
+DêF4yøÓƒd²È1e-=\)¡7EŽ¦2<"º¥in2Ð'°1ôÄÛ{7kÍ}ÿ„»“âM’BfcŸSÔØ)ƒå’ÅŒ'[Å]D!)¡VA+Š ƒ¤4t·Ÿ,GLaâ´ñ¶ ኤ8¢Z+'ÄNàìcJ œk¬Š­mq Ö…ÁÃäáaF…bc—ƒ ]3ækBhF7ê¡uĬ£ š)­æ‡ïô;´6ŸnâXÅì:þÏ«¤‘dSÚQ†[Œ0³:\VèÕ؃|ôJGy ü£²4ïË» Ug*Qÿ±ýWQõÉ$†C6·^u­ŽÝd»Ä6ÙˆScZÃ’ÀôÒœšÝ^] ë¨kÏï\™ãÜæÊ@÷UW&;Õ¹ÏíƘ«iŽ­¾äA$)îÐú’"µMAí6§5Œ;/'e$G‚iÚ%Ñmn¹?S²¾"Áiº³½‚P AaïˆÞn/Ô’5…£ÇQÄËwËj¥®2âS¸1Í¥æôÏÆ‚ L5"71ÙÚPb"%¢µVsWC®Cx¬øX ¹y»ŸªËì‚âÝZ]P5ºÃ_l¦\ ´jtbér/A¹ ²ª°yB2ԡ¹ŒÒbDšª$zjˆ9T¤<ï=‰NE©qw; jWÕh³Ÿˆ;ùÒýZÈ~‡ü;yGX5©zZqÈùwåœóþLøQ´Ož’¨TÓ~Û†Ä^ã
+ºÚé—C2Q“¶fóBŽ Šd\â¯íúœ›^ÛSsÑêIB y½<ј÷:V(Uâ!ßìŸ[–øî4¾¼>8Ž÷çœYÙø4Z7l.3|æÌp¬@²|B~V0Ymço<—2BL*d]øÅï2Ê Ä¿ZD…L[ ÏÔÀX/. 2֪кº© d‘Úƒ ÙîwÐRRœN+57PƒÈÅ0‚˜¨ï˜{&â6¤EZÅ‚“ºk† ú Ô‚ðe‹X¢áj HbëŠC±øš†E‡]¡ä‡w­túpÍÁ@0&)
+·-æçi@ÆG3º .>|’ŽËç’¨(+mª4ÇÔ€HX‘ ØÉyøG tŒ!„µ™¨a¶÷œß&q ÔÈi9IÁ’´ èùÇ Ëü}ÿdH–ã×ß@¡y&}0R¸-X°Î‰ç<WyŽ¨á‰ A¨t"TÓšw`æŠ1Ñhò âñ$Š[„ éÅpzMø˜2ˆ~$zÐG*'c1(D%Ìù%·Žç*ì[¤<„­oB˜[¦[O;ÄbLêPHÃê€XP¨VˆÄ¨Ð¬·¦e¤,
+rqô=A䑨Ьôã€Tgåh«Š-„É´a¶2³
+Þº/ò€œƒ »›¹‘ÞpØ>À*p«b‡\¬¹U3ÍÿXÅC«Qž”v(¼ñï<–}…Iy„4`B¸jÕœ9[”o’Y#EÆ~@Œ,€„õE²ÜM©·ÇÅç®0]°3M ¥_˜~ÜžZ1aTäž6ãa =–¸ZY Â"]FñPÁ5\!rÅ4㊷âðþNÚ…ÏR®â¯J³8.cI]úÃwo‰¨LÚ*¼˜Xj©ÎndÜÚYyÙb–h|V*·ÝU‚±Êoè­„õt^¢‘ÈLÜüŽú®v°6ð!Qg
+‹ti‰æ¿ ‚‘6ß*ƒ"Y™irž—AqwBÕ
+C“³‘{@$–˜ÅPBѨ©‰àF€!âÐÎòðîÀéàbyké°PY&„GYG{Ü asÓ@³°Làr6‚ˆFTdWûYù9è¶Ì㊼,i}yÆ\®¥SÔøAmö5Ál²Gü³{?‹ˆüHžûÛ.CH3Ot„M®xåý„Éœ¶C˜°bÚ’Ÿ©].Á…® “ú°¤’³åxû¨?Ðð×R^ì&8Æ».ÅàEžJfObú†i@þ")¢Ï P_ ùŒ—I¶7 EW=h:ì›±§ÞE¦öþ§¹$eÿ*(_ÉÉ 6T$‡×ø´n„¨Yô :i=®O½†]BT`¡å|†‘EòÑðº|S?÷Vê’›P8¡¤J˜Ð=²ÎY O“åæV’ TˆC®¡8%:jÀnƒ.ë¥/Uùú!yÀ*ÒüTö»å Ð <X NÃ,s?Œ¨0ž‰Æv÷l!˜ˆ¬4B(tN"{`ahÀ1ì Ix²)ϦCM·hM¬d>3t„Óì–¬c» zøÄVÓ›ïàC¯8"þ ?ÀI+<å5L¤ƒþJ™ö£
+b,VÜàU%abøÍH^ü¢Ž—Í‚·ŽUýÛñ®›c‹
+ÑjÎw®ŽWó Ô*/š½lªè3QžB oâ+§I,@¯k‹ ‡ì^ïZ‘ÿÂvž/lçƒÞÑPÕáh8q¤öy‘£NO„¦›¦wF
+Ý—“
+ÐK¢dD‹áï~1C¹Œ =‚‰×MœÐlk
+“~‹Úcï Ãá£ÃcÿÚIìC­ø©qTƒpØX8Òbµï.HEL½—ê êûÿx±txraƉ ,ÙÛ …Q´@@˜mô6HóàÎ5–·¼6ˆžðŽ^hšJ"-ÅqBV稘øÍ8È{iCáÄ Ž «6x_ŽÛu(9á“èõJ½G3§œã4p¸E¹`•B–&F Þ)º‘³oH"Ùöè<½$­B i=\ö²‚;>å˜ñµ@_½¸¦€«ågüS}3î þ&OW Ä”‡«a¶XŽÚ¸Î<â`êÞØÔlà–ùFfU·Äñ˜ vØA‘Mg¯‘9ì]<nKÓb«{”@*KA–Ý›U÷ª“UúgÏZÚMt¤¬"»^$÷kÕïE_ârÆ'54œÜ2u¥l¨¸ÕtÛ ªG‹À
+Î`:uŒ:]¦¡B 6ò
+s‘Ø„z8v?ÐßœxyK,¸(‡×o‘IòËÿüÅ&‡Rd6÷»Љ7Š$H´¸BOtÎm<rè{TXòmûJ2vìýÀ  6L)AÇÖ î°;1ËË#Ru-Ä·D*Îmzj+h}Ù€¿8¨ßV„<ri¤¶Ä7^Ì)*R†
+•öæ.ºw)úõÉ~ÚÕMÑ03œû»«ß‹0"¦© ¦¹â
+ƒ./-ü¸Èyßý¸‹âŠxlÖ4·"’"y /i(È@N»A ªé ã·-­Lƒˆ³" y`M.€Î¬5Éü‰…(Š˜Z†,~}l?>a"13å;¢8üfeÙò®èÐs•AK¢Eq×ઙ´ÓtJtº§Ýd´ 1¿ùÎÔ‡„[^¶K hØŒŸØ£ú3*H±6èò¾.”#á–ÕN~+§NÆÀŸðŠA³ª}FÍÃöã#J[%SÞ8òÎØ×IµiÍb+ïÌP¢;PQ5åæ;…¥ÇêÖ°î“ùÙЕĔÓ2êðAaò{œü'âu‘ôýå·qÊwW-bZèNÉjr‘”+î o¾úº(»¾`a0‡¦®‰#)hZ™ó~ÕÀ
+Š™f‰û(¦­
+ˆ£1ï£nÍarl#TCxøP)¤—jhÍÔ—Š…ˆû¼/Ÿq@s¹‹‡½Û“< #0½¬ Ôûpešl8&.¼©ø2¦géè5vµõ7þATÎ_ˆ>cŒo¬Ï½È¡ËYŽïùÿÛ,šˆ° Æåã¤êØâßVÄ$1¢"žàzpJÐalCœlÛq¢…„‡ÐvÓ¾(Éú %Û¥wK­Qé)‡…ôôD‰øHéø‡¼Š˜þÍ Z“HO½œø¹1.j`„‰­#®‚¾Ï“`p$ !©¸n
+Ìß}HɧÚa$5H¡òð<½—§§ö SŠØ£
+„dL 6N‚ ¥8±êž@£5Qàïæ¥dÉ+ÆýNxêöt<A/Çmò'½PL=ÆD¸ÿ=§D£”ÑPÖ¼J'ä>1Ûa&‹<`Øg\4À
+V¡t›â™ƒÙ*
+øLѬÜ!Ì5N¯¨§‰§ôÅ´÷"E¶pÀ)¨¬Ö€0Î7hWÉŒ—Kv'†W=h:@ñœgè]díšï/@‰n—#M||Ûeš†ÿITͦ`ëŸ^™…ÖŽâVl*0|:ôO¾HùTl>ripWˆçEŽ÷s*ä·?ÑŒŽ°€—Óë®|¹Ö¢·%DJ‘Í¢»gŸ!ž‘d{hr0YSS'=ˆ/t]¾
+;Jž¼ÒŠjp\í¹V°‹c-ELóut3J$ç{ó˜«Ô÷@l´G(o˜")ÙxùtUÆYqXaš-úõ›!R
+gˆo²kFr†bq¹ŸÊÍwSº½ ^#œ\Æ•OÏg±G¹ÈGLË
+ÆíŠ{ÅÈõü«wP†
+§ _¬Õté*@KY|$Žû\=}\Õ7W.t¤ƒŽÐÏó»?Þà ÛC+bîج5m]ˆÍŽÃ3r¹¦M¾EðFMÚ7´ƒâ$ù˜va â $ðÏï:Fw*ÂÙ1ä)1QoP,gÂô¥ë䎫;Á/8 ËáH÷¬Ä(Hkƒ#ˆ– _ö‹=¨Ãã®È¿.è'Ùa¸óìý(Ò ÚDÉý\FKÙG¥ê:´xtEo8?L4—~ø‡ì ë½ö¯N^û«c †©ƒÑæv®3ß;¥U¢½Z/7?$Ô$4úˆ’ˆPÙ9#|†k'0┲¼Ûg“§NÄíã[ïú §{¼æµV—lR#ð“ØÍ«[®v{uu»¡2S½´„ªñ£!$[Ú”90žCˆ_ÉH–$oFÈ*ê#¿`ÀÐPòFí±_8ù‹¨&u䌠(Ж¤Ø/DóÆMt´Üƒ‘ Ì) *«+\ô€äš„[I0JÉP¿X>‚ O$»^Š—!²¥I#Ϋ؊~Ö[i/•Fhé…C¡gæŒ3ÃÅ£–+.1
+9ãÆæ9t·_hðшeò¼´÷ÃcäÚ3À‘øÅ™#ÍÑÑ&ƒÓ
+Éã"žDÑQ+\2¬7ßké¿žŒ¨ˆQ#”bñA:9BÉô#šy‰¡ˆULM[…uÇ,@èÀ¹ÈÓ|DùM«ªÛá¼²r´.©Áƒ¤{¤«CBˆU„ΞüÓÐR3üBŒ>ÍüÓ<¹÷¼w£øîe¥öŒèUÆ-wEýUj«á:F2EšÐµ²m³’)ø1"Z yä›ùj~Ͼõý1ò‚Œ¿ÿˆÞ¹o^£2UÞ¢ý>(ñüî€Z®±p‹b±S|°LWíë­¦FXV
+*T•9Ž=Y9ÀÒC¢W8ŒÐd4?bú†ú˜Vdn)NMöÎŽwh}Ýç±›Ž_>*ÂzKpª˜j" ­nk…ô…Ô.wýÉøÑ[| ]Û eä„s'Ù¥öÛ!<‚û
+ÁîC”¸yC]MM¡•“Uœ耯
+H‰Œ—Mn$7 …O0wðÒI‰×Îrn1@VžûoóQR à.5¦Hìg©DòýPãa­Œ:lDïíãŸZÛ£yÒ¬v­¿~¸ž0Z«†7qò‘ê£Ö2¤¤>¢» µ&¥Û„ôb®Í›©Ú‚ôƒ#¤U“}UØà­é´êêÖùcã+µmÔ}LåÜÒ먭넸4mµ”1nÑ¥ªŽ6\çÈÃJ륷֊îsøÏ¢Õ=:!\3‚OꦾÕ-Ô‡I>¯~ÄtP¼ÕSš*½®aî‘÷ºK<e§|îöâUø~þ—²|Ϋ´öªTp”Uä'Ð× P¥-&«éz—Ðib´c!L(L”lØúâÒ Oè¢æMˆŒ²·^ý*rã‘ECÚ>¦8·´ZCe¶ªÇðÚ½yDì¹ jÌÝl¼èæ7Ⱥ¨Š3MÖC¬½8GöÒ¬6®7圹öÞ£N_Mè–èFHóQZ㉭ï›JYkãj¦2!\<º×˜“·ŠZÍfíNQFÚÍ;ŠÉ H£ËÊv‘áò!Ý|ðÅÞç'«C,Çmú€¥üÒàÞz_žï‚›º ù½¸x-×›$t(í"}‚7S8­"1Ï1WU€Å ñÙʆJŒU>íV¾ÈÇ‚0…B êÓ6Ä2D)Vb,?–Wƒ­s²*壟¨ûªæRêRdBx`c¨Qº½Ú Àmt}ïÉNíÂ(´8}
+[Ç00ôÒau›þ`Ê­1”¾€T…6…yäð}Õ„
+€€ÈÅb/Dñ^š2ß=ЧX‰8,F!6YS_f•ÛÉ¥)IT7e“í SyNÕd1饖N㤡T+™¶)+U*R²fø ²†"‹ÕÌ`¦ŒÓ9 èpxœÝßWÁl þ•_do¡é5el=
+Ùer¨¡ýñžÙ™“m•mn…N?›Ç¨¡L-±ö¡±½©Hµ”ë@àQ»ÔÇübèl ÂÚ ¯ Bö½+sÒˆ¶éȪ™­ïŽ_à•º^° 5…l23§ÂÄõ5pÔ4:µºÔQwPM´íS€PeÀ Ä¢]Tè“VÝ3Q`2UGš·„Þ›ù ²®âïQg¹;žÃÜÈœ*¿ä‘a0©’Þ× Sêž
+ÀœÆ~“S}>?èàžP,ÄÒÆÖ|JãÈD*&“:ÏÁ)sV3)%×U¾e¼€0s„ˆ©Ùçÿ~ÈÇ¿t ïÊ3v[»ž”ÿ÷ÄšˆÍ„¥€ìA3¯ ³”=fzÛ*%ɬ™\éK"ÍAk£Z™ BdâðX¢]Æ*^¸Ky
+̤¥T"mÉÆFRi›Â¸]>tëŸTéX$ƒ°Ùa'©D*]ëôóˆéçfÆ íÿšACy¶×¯ÄÀØ¢£ðÖ¦„p0‚ËËëöÅJc°äšåùÈ3õ‘‰u‹CDü5»€ ‚G¡Q‰]âžÞm‡·yŽ§{ ^YŽú[¿s2Êž ‡Sj"S9ÉÜ ÒI‰¾RåQæhãÛ2¥Ž?¢ uÅäF›܇ñÄ™¥ìS`EÇD¨|ßÓ!i‡8jû. ®öˆL£Ô?Ùˆü,æ’Íàp‡8΂RQ}´o Ç dÐqT¡R³ñwÐa…Ì8
+|´.W*%;v‚ïXw–‚Ô„?¹¿•N$È$ûáÏÍOØÒùÁf{º¢¤Õ8¥ñSߟC}Ž!nCN†]½h6'q“_¡>P¾Ôs›ÐÁŽt«‚šivu“Äñ‘æ0†K¾åß„PñH£)㪰#®¹;0ÖU#×
+yº¦Áíº¹~aÊžl¯YäŸÇ"¿ êéˆT€²9wPäÄÒÇx/ëô¯,¤¿²’)1q ÝÀ3V"W&ÊŠ¶ƒêî
+ChDß
+Í,
+¸ÜžBËS Õ²«×J¤Ìèy
+©1ÃOòWÄ=Ê-£äuEG3CPº%¾%Ð|QÙÙ“¡FJæ5ò$*¬OqVÁ¿ªi
+/' ™†yŠÕKŸU’ƒl6>5W2ò[ÅQ“zqp}sI}J.Œ2¦~;2Yéé/÷9bô EPæ»`ld½¶Ç§sì!¹éXfúk¿,ô© è±LDŠ7¯ßÆ… Ÿq÷­¹ÏL‚~ã·lúäŸ>øµCUú.æiaû:c˜AáÓ[FñYþCCŠàèÞA+
+P6›w\,h‹;ËäÉ"z•/·Ö âT¯Rѽ i¨Œg )&}¶2·-é8úòkŽ-õ̱úâœäG°"¹ã«cÒ›tÅû'Q^WåòF1óW”K)' Õë*´½Å©ß’@ÜÇP²4›Œ¹Ï9=lÐR‰(èç‘ ‡†—GŽŒhPû}æ~›#š]_yï~Ýèë ‚þLK -͘>¯­ÂPöËpØ’Æ 4.™ 3Å´@éN™à‡ò6(¯²\ËØ çëÞ¡š<«Yz!\ýzú¾M&É0âñèÜ¡ˆûPb!>ªFrl/¶!É¥´'_ðË?‡¾q wìóӌȎ_Û&ÞG¾v”+Cš›O£ž ë*Ö“ÜGæ¾öâþEöpæRäà§N
+½d}¤òû“ñ
+É1DÊŽJ˜SxÃ'˜ œŽ²?õÍ„.g¯±ó˜Þ§ñkŒã߬kMSKyFï·ƒ¦¸~îVCã^Ð 2()÷ÔæÑ8ËaÖÄçB…ú'hÒIÜ>’Kã‘IÅtèàbq):JrA­§Ù YŸ2:&ÉEüs ±œáÔlº4~­„Cã× ‡ÆùX ®ýÕ£ñøà:,!´>Ép',J®9›¨Xê›ID—ûE[XßœÃf0‡ªK]Ð&ñ”r@ëBã,ÓpM`_²Kã„DÌ`C¢Ó=Ó¸r¡ñkÓïá‘ì\Úy¯·‚œ¼~îVЕƿ“ Ì þýñÇ?æ=hš:'“IŒbËëi‘9`
+ŽÐpAD“É £B­0‡®›oßkQ—«á+„¬˜©„2˜½Å³–"+(¬‰yÏ­®äoiçXK]çðŸƒûňNì8è×IsŒFH[1]ŸÝ ѧâß±RPaÎ7Ç`…)„
+÷)ä%‹å™Âh
+ÒCâË>ƒ~S£2€ûÏ'æeeùúX_ŠâéÀ0oad>ÓÇ1ãǺ-æÖQµv|H@€w¥ÆCãigc¹¨É Y F𚄉ìÔ7ç¼Ö€þ•'Á9q¸µ|¤õ©×žÀ:FJµÕýð:‹•/U­]tnknîZ€ˆ ¢J¾>ï´ñAe¸õQGTië&+(ärÄ°†¿ÆtC4¡/PÃ'dŒ;À½©—zСK3¹ùX!üÖ*ã¬Ïü¡Ø›æ@†ÓüMUÿὌÇÒ# 1µzÉmšÐºúZm#ÁßÇU*î9A iL¡ïs
+®)r%¶<…€±QŠÆí¶â‡Ù`_…Þ Ïç€ÉÉCsl
+E›£…â‘ÀÔí „¤k—b(U*ëÌטòÂÙ&šcÏ Û
+óZ q¡¦àÌ@–®P)¶Æ6jìήaó…#Í©qNÓÝY¬¨IÛ)ÛDÍÞÎb­Ašsfi*眺‰ÿÅÕ_´)»!þ™Ï&–¢ŽÉa‹mÚx"àÃoö.šH"ÒŒuLåiúsK.] ìÁ¥­3¼™ÀER¬Oå|êÿË
+ÍPžÝº
+I†Ø`¼ `9A-s5‡„vŽ¢ K’õå]:‘K¸YXZÉ»bÊ‚VŸ
+(ˆ•žksÂÕ+v±>Uù&©¥¹gT„#\gºŠÔ +jÞ‹²üËÍòÍ 67&rêRÙZãDB@ ˆQJ¿tŒé–6BY}c'‚Р˶Ò5Q0Ëä<´Íx’SXÚßZ¾lZ±‚H30K Ò`ÇLæƒ×7֦ŔÅþšó™¤C×vBVcàO0×Ц7ç€Ö @a–6J³6¡!†¹”0PÞ nh4^¥´ûKT–nr(äžó4Ä2º_²¢“ê",;é“Áçò[ ׄN®î=}Q±yð›¡ÜÔ>[ÞtŸ|YkÏ6_Èë幉ÌPÌÕ+5h¯íV¾ˆà·b*Ý…8¹pÔo8($ÉMh^Á9LôˆŠLab9¸esùŽÒ#IfV‚‡nªE~TfdåÓ—ƒüš’Q·•g‚ž
+‹” \+Iô]fÖ³…hÿäì8ö#ð'Ü×nD¢i©ˆ¤uš?9lt­ØC£y±—n! ¾`Çâºu:!ëCܾË5€‚ñæD{ö,¯MÝeºKÈU ¶x0ãI–ק@\¿±Õ”Ã+T€ýd}*O4N4Ë<0—*Ù@¶±¹6;E©
+† À^Ý3åoT\‹µ$pBV’+XÆ
+šð×»-HŽ–RöÀr ‚ ušÏ%…˜ëdVîÉ#‚^¡o­žqòÇPÞYÕÀW¤ð,õ7çh³£ûÉØïÛ0ÀÊý/ãe’É­Ñè}æa­mß‚Ûâý·zŠdf”H“™ôwTˆÁýE˜[ƒö9R–ND ½9ñðv:1IëÉ¡ž‘@;(§œð^_„ÜMz\Í-ò ³?ÐEtjl§+И©Ãa°Ç
+Br§¨¢X—<J¥e>v·ó*Ä œòW
+Üáþsg{•pÅÂjŽÜÂ0!¼
+Øâö'¹ábIšŽL½€û„°¥8«yú}žÞð¡Ú@*Í…ûÈ;#÷#{}¦pÉqÚ ÆtÑž€D)#šõÜÃ.lï…Üàþä´yDM 14êü}3w÷ã~tçûÿWŠ'Þç‰égôIÎ5;Íú±‚œ¬ ¦ð‚ÂÎ6Pw¿5§_:5bKé¹n5mðß}_GµÉGÙ"(ÂÑîÚ)}æþ[!»â©6j/¹'Ðv“Åßã@ÑSžÿñ‚íJ_•¦FW–Ö¥`ˆ-È Ç
+Âùèbô}n帡¨ “PØxÚè!k0™º<WDï4V(ÉØ¡Ëã9;Ç5bUä't~·62ŽNB𺶾Ãû€ÐÕßo'[‹dBr~’3ã$ó¿Ë9êǵBiGчèj<ž˜@¬±kà Zôîä ù>‰:ˆoÙcžªŠTí.!íä $w±t­/:ð‡N~®-„Ò­Öº'œ»é!å6´—Íp‚B™á·c·þ
+ÊÏãEAÄR‹ôz÷©›µ#qŽí¡µV¹,[Û¾4ò4Ô»±U•|j¹¡×k?­Œß coNXDT°ÎÜ­\á¾6°d‡„ÀÎ|ƒ f…à\D‘Ôܺ²O
+ »§3å:îw ºàZg¤-2ŠÐ¤k[tñ-áz°!çQ0^äwl éL  È¸
+K-†R•fŠÚðiFD°e)Î4 隘÷‹piG†ÝUô¾š'iMa  Ç‹ ` Í`®šv-…à&ä˜Ç„se’š¸±4uÝ'@s$Õ­Í–ýt€NKÕ«UkÔ2HhÖ@mÁ@É¡šÕ.;„NC:鮳Ÿ.oA½k9[‰±nÐÒd&@:iGýÛŠÎÕïTä–¸˜cSÚ~vÙ9ÆyËÚüÔ9Ùàº9sB¬GI zE÷„ñâ;Së#Þê“Õ
+Êy6ÊSE.qËAdI{@ÃHO“":ƒl0kû;þ©É*Ų
+3âAIÈ.Ú¬R Ò
+
+È‘Š"p¡“ZÌ!ÐÔ6d®l×q‚.»ÉÏ>üÉ©•ä²Ð´ôtÆýci™CÁµÜ\M ¹È٥˛M!£/Q¥_W
+e ÷ņ–câXòÆÂÆ{Hã‘‚åmîÞð‚„¢ =݉¬>Ü §inP„ýò43* F.ûÚ×iX1–3YÜŽ!•±ýðk?ó3ЊƒzL͆ÝaˆèÔ\åõê~Sp1s…ðqù
+Ά"€k<
+μòÐƨæB#ÑÚdf‚àEL°87wcË:ÎÙ£’f€0”:sç¯ÓK6Ye-§ôÿBB"˜ZLÏ´øG†’‹ÿ5¤iUÕ´*ÁÝÿ2Hj_×þP³5Å5¨C„ŠÜ£é—°HR£õto$Òef—Ä ÿʲu„±œío
+G«³÷¶lð´]/ íkôÚ ÃV­,¦•Vž^Ï‚`ùlÉÝ•¿eTŠÛs–qiÔ
+°Ì"ë3ÃÀ&^S¨ÀªÅ=èF+
+YÇÔö‡-þ:q"}¡êÁ4$•3*{_ðƒ.wbpS”f°rµïŸ8;{Ý“üVÙ‰Pü¢~©® æÕœ¨-Ÿ^¡5U­ê:À’xñΡS5ÏGºë¥C´äÇë0m@æÂñ÷ß´áßխᥠ±_úþ›*|¬ ÚaP¶Àä)¤HÌ#²6ÂÑ…¯àLDÒ4ŽÉåø>–ÍWò·ó™ƒ”‚]Ò }ý“û^§áìX¥ÕfÊÐp½¨Õc_fHãÚ8†ƒz Õ%ûÛOâ[äšFŒ—8AÄg„ˆÑ¸‘Û †…Ö§Ó.s_RãVÞë»ãÛ‚LiF_qŒIjÏf”‘QÎO_ Ϥåfh;ÁÜ%¨1W ¼Z~ á¨4ß´sŽ(ÍÙû!¢MdpV.Ü„¿9Ò‚i¼IÉA-4àÐ"‹J{Ùú6Äp²ã
+>T}™h+¤“"ÌUM7ˆ?í ΨàšÌ{ZŒó.4A³Ãš† B™­z¸­—“eLF«ÓÇí•AF†wŒÚâ~Ãm§ŽÛýàš S]`y°b¦#¤_Yçc1IÚŠiWˆœ ÀF»Y£4®Ç]‚¿¹Óâ‚T
+Èkÿñ2G’d7‚è æ%¡ [`i­Rå hÔfDÞŸÏ$íW"ÒºGë*/
+BŽÌGgéWtßë=L+_ )ÀÂDrH„G›­¸Rãž/ÅhT¡ë‰PËÌ2û+6 Ê YYn²A±¡‡s¨,«õší"ü æ[(‰ $KË7S±6LuGóï«Ra5ôicà“¸ÄD²y ÏEº³©rؽEãT"2]ŠÃ…|ôè×/ät;ŒŽhWÓóO1Îü—ýôI þd}b¹ <“QÉ—£.èS-EÉ:šÝΞ‰žæWÊÒŽÐôƒv‹RKü »ò+W‘Ìà"þÌäCHA lÓPù‚ºLª Šð0BÀ0=WkêxxLæ[ ]ãcP KŸùWäGr’>Èüñâr¤.èSº¯ù¤nTwñæfçSz)þ’n¥î‚Ô­øqÎÙ7ÇcÎþs‚:ûøS‘ºÓð)I¿Ÿª©Iu™¶M Q+Ç¥ªÜ\Ù%¡†ö €NÃçuŽ(ùöM‹7fwä¡f×VFÅ‘
+¿¤~äÅx¹À´¦ŠìÌT­WA™s{ÛYŽ Z…DIO»Ö›Í¨ý(mV‹5‚ASÃ׫1ŠRW¤³ {h˜’W²¦3Ê&òž[qÏ¡wÔ|††J}ŸÃ¸«áù¼ $}þ‰yk,~CûgM^»Ú”$@ò”¸lEŽD™Åãóœ‚J# HîK†ÁÝL(€˜W'3´(bòÌT¯ÙcWkúø—¦vt@L1³&Õš†­õ@j’Ê"¼ãå=ùfMgè¨f±‹¶–•“bþªÜÊ
+}Láwec:‹-šÞæ1Hm˜–]%Ž¾|ÇßÎc[‡;ÁªèÖÇ9´ ÌŠÉ,m³J¯S]MZŠ(pf­mó‡ð$µ(CÝzŸVF\$-?TßjÆVƒU'ˆFOÒËLIü1ÈX} ˆjÓ’úç´ß@¿°Dçª ¨ ÒhÐ{8:ÿç„A˜(ò„ÜŸF[ÍÏö“ت¡iG#W&Dº§hæðhÛŤë°hÐYX„iÍ!‚ÙË‚öáiÈÖUîùô±!¡ÊýÐxuLÐbEý[Ⱥ
+ËjŒ9ì¢ÕÛ9s¼Ùd…¨zt_„CP}DU‚‚Û,ô‘ÜÜ@‘¸{;v7Ãä£Rë¦T ³ T¨ôå>7Aã€MîqB2¦ªåÆ{ÓØÝ3co†1>:[¯¼¼üë¥Zñ¬cJ¢³N7ȪӽÞÎ9÷®q^svß•×Å·äx³pËð·3õõ0zl©‚pêÌ?ðaôš –¡/XÂÙ=˜Žê"ºá»ÐÜàáYRÖúÈ£Vö8„rGïƘ^IoôŽsÎ;^sô©ÔÑíGnΑ92ìA>*åž–;–ÕWK5oôp
+B{Ë$&3D b$1ÄÙF¡
+éGßç éÞ‰cž£í‚Í”2¶ ‘{ãjÚo½¦óFdXœt‡¬« > íÒûìÇó|#œÆÿ|dÍ} #ž:•‡¨øˆ¶¡ch½ºÙ‘ä¬Y[yRÜ{Zí«ƒ
+yHˆ Á¬“PÊi6½E‰ @KÕ*)‡Ñ™m:iž{'ÄÖÙU#h žTúøî̵1-ùFD´‹&ï‹âÛ4éÊkªûÁA˜p¤ŒCœçpq²˜¼H{k]W‘¿Õ1!&–${œî\¬T…àJû"–cƒ ÐÝm,HS´‘ÁªÔ„¹†’ˆ%·º 4²-.kcÌX-Ù‚p ñ´”Û’¢€šæ<3ÞiAH¿1´ìó”Æ×ÚTÍŽ2X‡LXr!Œ5_A*TÚÚuÑB—"pad ëÁü¨·^ÿÇx™cç‘Ã@øs@ûÏ„º…Sùþé|E‚¿­nô“– 6 j™ÉÖÝ«õÚôE€†#²·+h-£Ç7ñk¢Ë_UðnëP¥™à“{¯sVì„Æ#a—
+2˜â|S]jê²Ôp÷eÂÝê°%‡"*ŒŒrß¹¯¢¤Éõ
+i§È‰6¥TòëáD†Ô—Ý*vífŽ€Yçˆbè&úزñ£ä'I­Q²¿ AóÐf•ñe]èi6H@¿°h¥ƒÍŠpêb½Cìs°Ð1^ç¿K`)2q¯¬ÏwЕ2“1=J Y¶nn‡:™¦dº‹§’–uN¨•ö—¦*«ÓDÈÙ¯@eCîæYíK N•ÇàÈÔ÷¸N‘vMö?äb%HEg}òýèÉ—±Kà(ûCr`°r”G%ù%%'>ÓlΊeîâ¬7OHof,I˜*™âXƒ£ƒiPêÍ®·s⊲­ÉÜ{Ô`¸ì±b\©V¼Ú)°
+TÄ
+Îò0‚"¬,x\16µJ(CY¢"OÏOíuÎ׸p¯Àª )´‚û–MÜX{ŒváÏ’Sô¹‹0“ñÝÜ!ïdRlgÝ{QÒH+œqFbŽ…ûåPZ@ÐíãB³4»  }¼zŒB¤ØMª‘vAH)w|€ÃöÀW—ñ0Î/%9`ˆTÒÁd(çÈhDx¹¾&רš¼ÝTˆx³‰Ç£ßò‚¢J …!áêIzþæùJƉ€dì®nÉW{ú¯Ll™°&éj;ÀÀlÂ\²åa½L%ÿ º1·Q”³°¾nA:ðòÙ*0¢ø¾ƒ]áˆkz¸Š¸°Ô…¿6ŸfÒò¥ûSð»ðPºÙT奆¯ìOe (ÔŠ§dJ¶#C€×+R 6À¯×ùt¶›E ÄÈ_…_¥¡”BqÝaï lœ
+_|ûÒµ7
+)l³²ìöæuðCqV|dwR—’ý©ëÄs®¸qnsÅŸûª+ŽµD„!q…YÝeà.øsŒ)ÛéWü=§×Ú%(Sn÷ ¶— \ÜÞ;ù€,‹›¶_½}¸E÷Ô{ÿÚ¥æó7Z™·@!¼ ?À†å­ '#dTÞ¯‹wL`Ë°r* ÿõNãÞ˽sÄÙŠ[ä„™­™äÈ_–ŒydDû$< 6Q s<ô‰;u]ZÖ¯Ô‡"^'S$BØ £-ŽïJŽl‘6óÔºÄúô9¬kÄã3œÏ ¤¤<V ä‡×)¬bG‰R¬éSŸ¸ÛÊßV{z˜ð·³ÓˆãÛ”æwä WDcKòÃïU”dôØ0‚ÜðC‘Ëd}ÐÞ©MÝ%ÐgÝêQëÑÑí¡Å<>¾qcn?ü
+ Ô 3ÃbÙm”ø
+ûšÖ!Ê+ëâLÍÆSŽkRH+»„öã/ îS‚ „^‘}‹½)Îb€®Þ)úx(‚.÷ ó±›MQ‹,î*™Ç7a°ˆF‹óI¸“ÑFˆ|B$Ú’>–%£$(3ðmœÞðÔ–§[¿Ö¦|fG(úvd´xHP_ô˜±@ø"MûSrÔ7mÆ‚À‡ÃÀ›;¾vc‡ˆ!ë¤áí™aþr–Õ=æ—Ž.:÷È«DŸÔEGΧ¸'65%«8䌛>ǘ£¨ö°ƒ²t8™]@QzTžJ’T‡,÷ë½äY³Ø—ÄöùPtâä
+³ˆl6h –¨ÜQ÷}
+W(bãÖwK0ä±çåWH>DÁFÛ ØC‰ÃÅØz!éðé2ÝÉ­0Œ‘ 0¥›ë¿žÂípÿ pYP# ö^d ÆUR }XÏ º.ËÅÈl»µ>TÞ tÄ!¾¥T”'+£PÖ1DšÁÈ «eí…ÔSˆô·»K’4FwISjÅ5û^õk$J³äÞ›:üávø§EÜKÏûAŽ[ÎëƒlÉÞ®Ï+ÄÄg–%Yios%qˆp“å‚Œõ!§˜Æf¹!RÎ<NÞa›ò€`Q›²F®ðÅ=ȇn"ÒŽ+F7äà ;ûK@§Äé)d÷ðˆ7©ØË’ÝpV%™´Ü,Xáö9Ø™zœ™…’›Á"Í>‘S(·¥³âd<æ> IQÐç'2ÅÁ9ˆœ§‡?ÚÛBÒfÒžl H4wáÔW‚ƒ€èQ´³·Xà-9¼nŸ¿Qå:ŸÆ¬rÁqua¿oYtùÄŒ½›øF¼ VÊé$ÀEU‚£ÈÖ)º[ŠøÁVOœÄ‹hlaiÚå©VtýÜŠš>ƒ@O¨‚Zé‘bq¬E\
+˜FX4²†$Øæ*oÀó *¸KZGjãˆ)Ù!IÈ4ž„ ŠP n7{îÁâD!â­ëœ £ûÖVh5Ò.”QRr’j5ôî”ìOáxˆ…žôøpNÃñ$Æ™þfÞ t_qpm
+­nÑ“¹{Œß£ísÛ©]T°°´Ÿö˧<nFŸJôàªþAEœˆ³N‰^>”Y•—Øê3à8ôqôMóIì:䨜K‰.‚êE¸Å.Lí~N÷—jDµP,þÒ^Îg«92´Ï)…dH„:ƒàà"ì–\0úï?^‘ƒv^Á¸ ¤Qïøq‘³÷Ïý¨èÂ
+þr]Š^v?£…StR•ûí׬Ž£ÊÀI¯Ëìƒ`¦¿•—•ˆoY¡jî’$Å€’Í_Ömf?
+0VÊ:c\;›’«Ü>UÞĽBŒè€¬ùxùÛ9¡D†-¹Šfk’1o{ûzw¸.Œ„=¼(¿
+3)•8¢ü{‘dèbŸ­;Ë÷¹j
+Nà°n/u m¥ûoý=Lue2­
+GØí.äOxxPûâ„P
+c%Ô3Yr•)°Pùz˜{Ì3àÖ0,ŸòN©-Ùƺä%¸õq…‚hfÀðpqæ)è–±8J}øµd•8¶VðÞ³]¿“AM/bíÐáÅüŽnÀ@—¸ •À¼Äm ×`6é§CÉÅËË?ºCZ_ñßû(Œu#Åô0Wísꯦ·*à
+ët®2xo¿èì?ÿ¹]†ž`ˆ™:>Žeß.zÚ¿_ßYRßåBš
+üãK½$§T–ÖŽÂĆ#¬s¸ûdÜF—¸K ÿ$£bbføæC%\½ªc ˆ»„à†ïf~W/@¶¢éypÏA ‡Õ8‰jøTº>òñr´¦i‘mùgxqnZÐÞâ¤Ü ¹
+DV0Z`FiÏh’B¹MÎ"ÒvÌ?òÊp“Ÿ3!H¶´Ê7<Z»ŒÎj1æµBNƒ‹³´rQb-$5sbú†ÝŠ~]‹ 6yMž"÷Úš.Ëðå«‚Y,‘¬ép[Gœ¨òD²”(÷âçp¿âÚú„c]†öW°íKaµ?ºð%]æøš®Š3Ó"1ÊZÞ|Ç©écßwìÒ"Iõ5½ÅbÂŤá³Ä˜ø3
+QHš£ÅQØSãõƒphf1!ŸñÑnµžýMîZ^oJ”uE\êa«ç"¦9qüØK<uÛßA3‡ÒÅ1'(„Á²¤µ/#{Ê hCkC±OBgrÖס+t˜Q²Þ©îïàU1žƒ¼©Ó|št¸èC>M5vã_!k°ø6dÏÓ.\úË™D|ŠØŸa•äªE=ÁÀRaü`¥576†•H4Ž¯5<JRǽuüè0”‡:a%36¥.{©x[Àz—Pþ™ÐD{<|]K¦€MDYçQ¯E ›÷ XôÔueº‚±.&ϦߣÁÇY¼{U€„Wí9ÂÀÓÉœ>´Rÿ&K£ê6Iü »ºäÇ ®›œ>‡-•“k¢4ßÃŽ@AêDûØšÜÞ|Ç—»FWøLúí–Œ<êŠ
+Ë>ôk…ÒJŽc 6A",øÇ%+ÛD=ýÚEY†@ý[á ¡.ÃMÛöÞÉ~Ó–&$ÇÀQ l +žû^<B(&ÂR>'!Ý$XøîÑcâÆ’X—è±ìIÞ”Ýc(K€å:³cÂYÒ˜ùfœ_J6rÄÖÌ@©j\¿#=„¨”ÝPì¸ ÿ̳»ömèXÂ2{2UûUŠnŒä8ŠE€Ã'çéì"KÅæ
+
+­ál,nÛ»ÞtCöœi·z#{Z÷
+6FˆBèÕ1ˆ?}PFÕ1¼Ã× G Mצ°½¾™Õÿ¹À‘øbC+Àua± Ú±ÁCãЯT§‘±J½;Ó‹>µwÕ#H!µ˜ìÏ*a¬†Ö›@¤ÞÎà€ûør†³;¡•$Å[½?•`2v¥`Ц7%ÀEA(鸣ãµ­E1öBñÁߊ^ mà;¸u*ôü¾‘™ˆ4û>-Ó² ©31&“'8À¸Ÿ§?CÀx:£=x轂äŽ}ÝùËà_m½›t‚_“ÎÛí# ‡AËyó6ƒüfɃÒHÎ÷â6 #<Ž#Çä£7 Ò·½éø:rÔ€¯03Ç1þÛ«dⶰòö'OâÖ
+¢€}û¨©*Ó6gX«.Ÿ‚ôÍìU.R ô‚ÿ¸vø»E s¸ÄñãÀâµ+Ãëù\ßh‡G1¬ôYØ*Ù””0Wˆ»—,4
+IÐK[ÞH¾/ZеA¿ù_J:ôTD"ó¾/%:©CÊ„­QË›ïà· ø¦Û| I”@7~©=짢Õ`ÉÜ]ŠÚç „´Tۥ̵‚V˜ßÑ
+”Ø:Zü°š¬AúªYbm:Ž«(cÜžþT²›üÜ—ï¼ÌË0>¶|'ÂÕÀ §c6Ï8ŸQÁËù".¿ƒù´ø ±6Ö›XYkJE~Ç”‹§È‚e³«þ~SÄ’²ÎÌ.úP ¦!B‰G–`?ìI¨èò`‹©BþÓÉšü€5ÚWWô
+¬¦MT®ÚçÚyBœPr‚º“²É³!Mš½‹qð<ì-ÐMüÙº¦À„!ÕA¡Y ؘLšN$Fé‹‹!ˆb…AF±°µðwt<®¥2ɬ‡²}j½ IféÓà¡a7—B
+ÕW@¤>Ô½W
+öp— ºŒa½­Ø⾉'[âU±]¿Õ†Í‰Á% f~±¹ö ÿm”Nò0L ph‹ýðîbldI|Â.Sußd/¾H'ŸÉ€×›îµÓ)µ£86Eå2*ÂÛ¼6Ýë {·ÏÜ9ãÜåÎ=÷MwS¤Š¡%›¡Vþ$p2Q±Ûä¿}ú³Ç®v¤*ñGº×Ü$•Ð2Ð_t*†sÜ ôùΖbïQÇ<fÚõ\çË‚ˆ[¸1ô+™{ä¼ï<îM+V%€Š;Ó.]P¨ 4 Äf& Ú»`M¯r‰­¬ŒTŽÊyB2¬WÒf@Æ曑k´ÌŠ'ßØ.µÔ˜š/çoŒ»æR
+‚uÊ;I¤a‡`N´I
+ XuY0nR)'BU|Y»Ÿéöðb ,)¡· ƒÆ-M™ˆ–M"3!¼ïé°L
+y:ƳùÎ
+k©œ€U^(‰0¼ÉÃßÕÚÊòxõz.
+¡Æ§Ûöqž®ÕòùUþ°X¨|Á“»šúTãrO æç`œw9RÂù&ÇQÏÚÎ|Vøð÷³SNN8;î|çÎç6wþ¹¯ºóøÈ Þ4Ü4î·¡ú³G¯WyIj|ï]w³¥xrÊ4ÌcäèÏyœ“~½“Tƒš¿2ÔáK [Ê0;4uÕzø514h
+å'ió&¤Ÿµ "{ÿQt˦NY$¥úí¨ePQ½ØÅø@JÑzØÛf<…¥È²4g‹åÒÚëÂ?6Ñ«Ñ— H–ñ7¤ÙŒŽþjËtA‚pŽKå¨ã¾ŒrëHc¶‚º²»B„’‹]Ïæ9ˆ‘ò>*F ñH¬ {£ãCQz[G±O1®L7F´ÙC¿©œ¢ru!u6TÃHÔ‹¨'ˆ"³X•¤ýó6·$c¾¦oÈñ¯'beÒ0SÔ¶ÙNf£4ü7]#14áSjW4$p™}Ù4•þâz©Û 2â†TQœ¶ ’,‰RÅÈ“4ý
+ WÉ \$@€ärÿuÞÁØ–èJ´“Ô4zøé#Äi}è–K×»”¶9ÈÆ“:9jfl’r¬‹Âž4äõxØMúÛ³£?y`éÂ…¸í¶/¯ž"ã~<–jÎ<ŸCËZ¦°ôûø
+–á‚Þ­ÀÁêE?¢}ÄpþwЛ×eM5’)?½ädª‘(Z
+{­m¨$.!f}ßøQFbFŠ&ÿ²f¯{84m—Ô¶9$o3m+`þáÍ*™³ãŽˆ¨µgÖ¬ýzš0ïÆXÏØ÷yÑ?¦ðÓKU0ÊbäëR®Öâë…:ZãŒÆÀ>•f-¾ï‘ú·@p›E¤¯¶3ätáG%£w`°/G;gV„.e×#/ªL‡à~_ÚßÔµÐùPS ÔvÆMšë¼
+÷ñÔg©m„ô4Ëêr<„äªòQb‚;µüp h3›yg½y‰®ÍÇø'd¥¹ô|]u~b"ï ã‚Ú%Þbz~Øǧm—èy¿
+åÁU mÎýו¯g[úG€
+H‰Œ—KŽ\;DWà=Ô:¡)’c¿áÛ…ÙûŸö¡¤ëvÝ«„ †•‘EƒÁúñQ{I)ÚÌ=øûcx{VZÕj¥âÇ·ÄD«-|Øñþª­«4÷ª ÒÂ"zw)Q'¤iÃO„Ob´QÃ{Ì‹ú«›é(œ+Z4^î2Z-µÏcDzç¿Õ{i ¡V,Z+*ÚÞ@j·Z›uiÑöMw¾¬)ñT·þñï·ÿ~+ÿ
+B:¸ÑS`™Êùçé8ØÐ&Ø¥*õ¤tG.’º3áŸCÀü•\îHˆwý:è9—,„ƒ¢ç’·˜drw§q91ëQœ )òÕƒJšüá!²“( ™ïÏæ÷4 ö; OsûP‹çøÏ’v>`4õZN IiG«0¾K¼HÒËÀáÝ<.º;š¤©ÀPM±YHøD!޲ι“ýn¯Ž»íû{gýî0Sô tÇV)|›+cˆÎ&Ä°-]Ë Íë”ÒGZòzwL•Â¸&¼ M«aˆ ºlÄÒ¢q2CoP–yU°ÑV·¶b·yý Ùmƒì"\…ÇÞŠ€…KáKdAH4'Wù‚¨Dåt_Êæ _z -¥J ߀d0xª7-R‚ŠyΈ2¶]@ ½Ð2“Bòâ
+sˆY^§&¯,»MºÂ×YÚ ÆwÄ"äM­þRóï¿5ºƒ§­ñFõЋ•|ñ@¨=ô,ZÍ ÓØõê!¦.~ŽùÛ'Dg^/~¹%–þ¦/óˆDS'rô­@c>”uZ¯]ÛUaŽƒNzIµdp‹~ÿvÑD¼²Sx­ÎÒŸ@22Ë™ðú›ÑèZÖYtÅ#lvœìˆÙɈ¯§ßI}7âYÒ¥5›ê4Wž…N'íié@_ü¹ŸBl(aKÍßó‹3éRòȬ™tÓü„œ÷k‹Gt”æÚ7¹ D‹v]N ƒ‰’"§3w¸ø§¦èqu
+Sè…uUj/»Eäj° X5ܺ†^ݽ~=\É)Á_3)4àäÅŠ'( :Ž#w—YqgU$[ù²IÌ
+Cyk;,‚pFiÆ^OЈtõÙ©™±`cj?Êß_e4wXŃ…‘ÓC*Õ¶ Š”’a"ZÞY±'¨ç>ÄS›à£—Ÿ×Ý@?¿Sz Tè•ûH
+ˆ–c39»uƒIVhä ñmvaA
+ ÉñMhv°LçÖ¯›î¹„ùº°º¥9dùJGŠFð~¬Ô ²*u¯øáœ;oÑÜèwxÔ“Å$Dz‡ „‹}[PðêH­·7ˆ?Ëôýj:f†u*ÂöÆ9Œi>Y÷ˆÝMÏt˜÷Ï랦çï1-½dÅ(£¶ ñ¯ aYuÚß8™æÁÂÈÙa7z~YxíC‰G· i!— þmTs_e¡à+mL_ 0¦,^6ùoIæX¶@O¬;öŸËçfИ¸¨‹À•äOÓß‹‹rgNGV„9Æ ¦¨É'‘èç KKŸñ¸Žžg– €yYTÉP—húæáCçÒV˶y†¯ä®¶=þxyä2Zᬈõ¥Ç0y“yNúZ>úÉŸjù ðcÖ’¤³¿±–xŒã),IÄ莻íõ†}ƒÊRabB¨~ÏFØ;e $)…[W1ÜؾV²­WÅ ãòä:'ý(òTËVrñ”·ÌÖò?ÆË·Ñ$‰Â'Ðh·!侘ƒjS1Vk̹ÿ|/#~¢I†P,P%*˜Ë[2m›&cÀN;_ƒ¨úJç˜Á¸ŸvFA
+ÑÞHCÜ¢”ñN5)éLÏWøô&ó‡DÑ!ús ±•
+>·á…ë~C˜ùö'×åϬM„UZ<âÖ¤â7L¢R]aßPÆÎèm G¸|BžÔTRóÆ#l,ôñ×¹
+F“D‘—uBA&"ØÊ9¦bÝ
+û‡î¼ÏCˆ³Ñ,D€   t³…Ð^‰ÅÆg„ÆBf ¯‚ð6`ÈŠœéÈ”˜_ A†cöÄ$ñVc+"P·}òëÙýéü=ÏßšÆ ™IM†VÆüÄÓ‹$­mzþ¸]€t¿AÁÅWsYš?%pHt¢=~£åšŽäÓÁä5à
+1±¹ òm/‰Ü5bÊWË´I&8Y£ød3Ü'j‚U§¨ÏG¶W$&S5ª1Vß|«eÁâAü<Km³røM!(I„/ú«d—^ ÉD¹ÏÙ~ˆÄcÀ
+z$¦ŽbÇPéfj‚W‚_HÇ
+4F—PðïƒÂ$=uºž-»“6êÀ:¸Èþ—ÑBàû~Þy¸/zW¤ÙyútSÒD¿óIÔ†A²S!èøSʹ9£nó‘´‹$‚“Ùc×vsÙÙž¥È-A­E\Ì­öyš |@±n=NåP÷ÍtQ è‡1L[)òÞÔÚBì*œ U"l@x-LHý‚è=æOQäg!ìµØâ”qIF€'8¸þô4ßÑeLá@ \À„}‹R~^‰à鯫¥r)!›J¸ZjÄ(ŸqÜÁÞœ†¦2™fŒãð«^ŒA•V9W-1%ý£ÃÆfäju ç94‡þì5ª ¼A9oÑ>Ý¿Þ™å¯K`ÊËIFS»O¸ûß‚è I5HvX #O#Ùç«ÚåÈ">…™NÈ€i!2>›^HÔ¦?@ͯÔšÞôê2/¥R±rÕΡ¤²m‹š×híù€ÕGñ L@× ÄzÏ)ê*wçž#^Xuæ…fó:ÑO¯ŠÇ~ÿÌ7C†<)b7‚ !É.Ióv||´/´¼Aã½ïNvþ1/ÇÓ:'(_Ū?}µ»›|T>*#Ž5B_—=huï Œ‹[f¨|ÔTFAÊ€Ùp<Ÿ²´˜)1ƒN_ÏÂGVEÒ²f3Ö=šSÉHœò:J *I ØzNÙ|]€„\™—ìá*Ò€él Ÿ÷Ù3³“×$ÿf³´„îªIXo‡:,Q›²ÑNƒTÏGgñïmr
+œ¢o2/Œî•Í:°SÖµBùŽt›w¼¡ána‡4¹™déLj”˜`•¦|R§!|¹ºÒeÌ£ e Ñt¶,?´¼åÜÂg˜ŸÙ«_%0)Û“‘èBs&êƒÔ«½Ý«aZ(¢‡íì% A@ð+X‚V÷yÝôô`VOÆ8\ŠW]úÐÛ…Ic”, j“‘”¯&ßmjKÁ“¤ñò6‘\™‡èÓå7€ÊñwkxN±hÚ `uùJ‘©
+ãÛ×®üèÀÊT¾Ø’±£OÂŽáÇ,V‡™‚®[D¨/"³‚R=·j V™
+˜‘õ]È€ÐëÖÁGH¼Òü*ôÔ$£>õÉáÂ"å8Ü¥3u
+0ÇÍ€åÿŒ—I\GDOà;ô Œœ‡µ}½’ï¿õ ’YmýʵR+'c Dæf,kd%©<¡$Ç¥À/GC
+v [u^ñ-ð%²“7:¾UÇÍ €0ú/#ó‹ÑûÃ8ò:¥Ð©
+nñd‹}”°
+ÐÎØl…3¯(¸ ¦I–Ô|52«€±îð"èúÀCaŽl¼ñÒ/È›ÅG‹Ç$‚àÓz/%À Ê‘Éqž­¾Š¸0¯Œ%SÀ´Ë.*Áõ
+V ÞIs‚$ÔEx6LI/W#ÝÚ|L­@"}
+Ö€‚Kå—!]Ì2=ûÜkbÌžñ„™0˜ ÀèBLN½ýx)Ò,‚\¤c¼é°¬;ÌÇæÖJ08ôÞÜØD9ˆ÷›üw\¬16#˜‹·¬É£Ç@€·àAŒ—ÔÜp' %;ÑîÖÊtŽ Z¢£lÄû!lÁ‘dV[ã# aZiûÈ$XuCûä¼4
+÷± ¸ I#»aоÏ*|š6º;”çóåx„ ˆÑÕ4äQ}lRSvQù¡%Ðiéäx¼±˜¡_JB…¹ŽfuzYfî,)9’ŽFÒ—švX YŠNsTˆcêÑH>;.FÆ e O­B,Ê /TXƒÎ2kça,ZÙž’ŸYà©BãÌJ¸(Ý´q ƒ6ñ”»7^<éô"ÞOx_zœ}3Ì’Ò,sL;T+³Æ·Fàìx›É
+ML‡± nI9ÅÆà±s9¶c “°dXIuä 3án_Ûx¬¨y6œ"NÂØ Ù0!2Y¶qW#õKC&ï6²LO—Ûd|OÌ”(ɶr°f¾í«H~
+?@‰™ô¦ÿ­ˆ×Ž&`ëѼŻ‡;¦Ðv¼.7‹­$ˆrë ë ’Ä”(ÊÆŠ“½dÒt•‹­Àn“Vaûþê0öG¨k L´NìÆ“Ìóª!ÑÒMÌGr§t)¨´…³1û+Õ>kž“‰cHøžÈ"ýÿ¬Ñ ož‰;1/šÝkI®à6›´Þ***‹Æ˜I»W<±w«A¨3¾$$¸V䧰H¾Op‚Œ°×PÍ}Œ*XG:¸/Á*ȼ(,C›Ž—elÑ‹m%L^’|³ô¾Ó¥ó?”$K/ë@\cºÅù^J .¾!®LGªÊ8t÷Lö(úñVÄâô&|8Ä/%X<L1VÙrЭä+\‹¦l3^Ÿ7xYç‘®% ‹Ç,À7ålf=QKãÒt/A‰
+pl#q ãJ¾£¼• ¦©ós«¯"î#‰®´+¿¬ƒÍçñxà•Þ¶RÐ#W’FÒi(Š3Ôÿ'ÿ.ò†¢ÖŒQûÙìßqÉJz!õ±gý}Ê¥õ(Ù:!Õ%0Ö!¥ïUÜë·Ä‡ø0è/ÃßÉ›­œÉâÞ²žœÈKàIÅ‘V§Y)Á‚ï’Ä»taÑÉ2gLƆ’:%^®@ÄL( œ°9çâëL£øªÅcÈãìË@Y…U™v…„(ÂrOx+‡^5Ôf¬@×Ä]I…ÉO-Äîim%Ú
+«݈Tiè¾®“‰FK÷žÏ­0Æ •ÇÓ+‹D¹—ÌoÚ¡ˆ$Yd2pR+ú «…1l.Òö?-‡g±ÁYYnYÉÈÜîf_ï(¥¨
+ÇD
+Œ–ôtnÄ÷×áGâþa¼\róÈa |ßaNèýX{;·•sÿí|EQüw«1A€Æ.K-²XUœ¢²¢ª×Ÿ¯ÂèœÐü¢
+’Íg&QÛDL…ÚÙÎËU²ÄD-çf¼¤$³q!ô÷‹‘¢ªŠ+h¿ ;‚’ñî  ehHÒÃ:ç®S©›5—•b<@ºv2kÜ=ú•‘ $xÃçÍȲ2fvíš²<"‰’ÄïÅcÒéHå­ …ÇCv¢½ùŒ rßp²ø‡Ðñ¡<”2¹x¬[éãÂ0»ÄwÛÌëÀ£b(qÔ>+kòÎPÙþÈÜÃLÅA®¨‰Ö
+œJ‡¸7Îè]ÅàiÀÇLB+»]—aÀ°èüa¼X)
+IŒI4•Ã!ŸÒ©ž¥ùô«š‚ ®Çrâ3QIP< Óhë‰*ò†˜íù-GÈ2Õ> I¾lö«î Ô\
+I ª~­¦ XñZPIX
+À„´^EO
+Y R¹¨w ­ÊêÇí„V­¬n 6ÅxzÉ+|.µ6¡üßÝT–¢†cSU#Z9ñÚ’ûTFBדU ´‘ØÙNÂþb”ŒÿKìFq©›„¡¥Û3“¶
+HÖ™%¸1 kÝI‘Ô†À$ö¸U™åî9k;,=¦ÿ3‹§Yþ³r€¶DÇ–Ö“Š¡nõÑÏYNÓQGLš#yr–89ßi_)¢Ï½¥½¥h™šÊM6ɽ8…Z>£ô’%¤¯‹®ßB¨„RÚôû-Ù‘Õ›\n×X› nöøiQ5ˆ¹¬JX¤ÆA#H֌ī|°F1n6·X¡v’r‚à¯]ÈX”p7œŽÐâ¿=ûï¹_^Åäq(F·‹ƒ˜0P8·ø%‰Ã­÷¦ÓmW„÷’ ï6…åd•ñ¹´N›§ÒåaZ¾N¢ÏÁ -K£‘ÎÎt*qøË3~·ù¢¥ê¨ÝÔzã‹Å×v¢’dlZC‰ª—}ÏŠÊdè¥JQ~2`?J½ ø±Ô˜·¬"se½{zÿb0d}¦?íäTíqÄóõ=ýN;˜¬6rq!%ùiyõsø8(ÜìöcG€Ô%™)Ú̹ð¢ÛºÅˆ ]}æW*ý+Ìð‚4(!Ϙ¥{šìºÊË.s"ºC¹h-cG`+ûU¨IP©F¯aWMYFÛ©a©0¹ók»
+ð@ÒIVöŽJ8ôØ9ÕÊ27/ýÎö3äM÷?? %”}F˜Ø¯'ÐPÚÊZ8~"pÕôrRééRDššó”ýét€ZdJäaˆI¤@Jž–Þ€,¤‘=ÄúaQZÌ`EˆÛ Ä sgŽkÛëNs,²Ù9ÑÃr0óRO›
+æ•$’:ãåBe— T€D®ŒµAfA"ÿ´@€Ù’qDwdù’Õ\p'ƒL=yH@â8@ÖU“ÒÀ/Nnóx΄¤Á~¯wlH1?…^Ñ 4Ÿ¹±åC"sî ålr.Ê…šq¸ »H
+¿
+Ž ¥ —
+Dy= Åf{¡lk“#ÒËPµ`
+z¯q`2ÈhLMÍé°X-!Uø#vQÖ½_L¾>ËNCX¹ŒôÇV£¾Xê¿oMÝ:•ùr¡s”@¦ª'õ]ù˜OÉ
+çÝÉuyô-ê¢ó‡íÈ5êôº")\õEÓâ'/Ë"üB`¾5b„¡ûàÍ€¬3zEjrL¤ör=
+nâLb¤Ö±î}€Ïˆ”&´¬â\Âæ¹Èõƒ~i•’ã”Á••W¶Ù2âa¨Ì9)*‰ã•ø0 </Í’»onéNÉ”Ø^}õ"ñmÚç òùñ‹»2Y|eß,U’ë1‹¿O [ã‘”òô\¬çwDµ×nÕì³Ôªz6 ‘¸„¦¨Ý-Åd K’’Ú=Kþ´{'}sðð{Hn1”É«k¶Cj béÀÏkJÆJaå©a‡þ7Ⱥ
+"bAÈÊÃ9Q3>Á,
+?_0Ö9ŽÚv¶ÓF‘ŸEZ Òh:Ç1s§¢ª6Ãq|Ô¯j:$å6ùðƒÓ„˜ŒÌB’mm$þ&P¡õîŠþ#<¾eåâÅ¢,3u[BZhþ4Øê¶kˆ`4HQº=ùƲ®*‘0VµFíÐx;G¥ T[€C¤]t’› ø<‚q' Ç°°Ž¤}#J’fþZÜaæ»2Ä”tt²øVf¬’€ÛYMW‰í§1¨
+«ÐêfJ$´Ý6(Ð@Wx±KuÊa}Ã.É3$Í«ÃÒ… T-«ÆÄë" ˜kÙ1€.RR¡}b) ÂkL‘3<B_¼
+HáØda²aÂgÀ ´¯õö€¸dÏè>Æu²nÈغØ1ãß‚l @Ý‹v¨f3|Ä$MÁ;5uë‘œWâ<kj€Ü8x)k‰rcš!‘mVÇÄÀÅN ¼¤¡Û%óìÜüœ „!™ïáh0èÊ\šð)\p›ëYÕf³¯ºƒhÁ…öpNïr#E¢YŸ ïÉS¼Ààe¨a“ÁרNÄA¨úÏ„DŽvæÈ›_ÿ|¸JeÉìúÉòfêï¹É¯B~ )xk=4ÝJmQ{Œ«^N¿%¿-= ¾ç¿çŠyÛΈNj^äâ‡{˜K¶8@l»•¶[•‘ùáä­Ä#v^êŽÿ1^&Ir%7=Aß'(‹yXSKÝBfZ5ï¿Õs
+A8«•úIŒßîW±,†®-^õf9Ú!XíS´$还-oIìòL;ë´:îº0è©?_|À‡?eAŸ–ßDó
+óVôŽb·Ao
+ü õÿþ•ü‹Ò̲˟0TtË/•Å‚¸1·µþøõPÄËè=ƒÖ~X ûЫ2aD=™IÖlŽéµt͵´‘/øß„‰ÉJû¨,Óâ?d¤ú°sø¼ck±¡ˆtÙ¹æ™p,à
+?‡'‹„jË—ÅQIR
+Jè¨Ô´ç!Šw¾ÁaaFÐN òãNZ(ÿÝ4™üPò ~?áÉd<Yø(ü/_0Ö ¨¿î5|
+¾š|—-¦dÈ÷×£HfÈ|–—l¡õ¯©S-’Âxø,_J ŒKX®1/(_"…Xm;çÌÃäv ƒ¸8•Á”Uè<“R˜—XåYŒ› Žºvm²/^ÄÌ@§~ •ìsÕή6Š,&·¢ÑpkÉ,ðÑ£Üëð?Lð02ñ`GF?šïâRòèŽv>˜ÏÀ,8J)ÙrC„•Þæu÷ÞJ|Ëg'"ò‚кžÃ†Ð$Žâ3[¿~õᨑŽ<Šñ.›g1Í÷Þ,È ™
+IP )ëôoa0‹}®°`Y ‡„ñ
+—Æ67\šJ$9…œsQ¸ÀOy¼ÕHdJ¿7+|VˆD
+ÿ(R’3Š?&E?1àËú2& 5FZR¶ÌÆâ`ePó¾Ùãe© 2QT
+s.´‹ÙÅXü ÷à•ŠˆŒhÒ4ÇOQÀ!$Ç  €¤õe¼2ÿ\Gžn‰‘o.ê„'ñÄÎZPù­DWHð12f|<œÒ”)¹ ÷1¯oš_²·£bc]WmÜ€ƒR–¸ˆÜ©
+
+½Oq-¯¡c»”Ç1³)¯èÒ ì~–O%4Š ë0=;ÿó¯KÑg~Åò;:ê” €Tdí!$0_n]?þ~(¢5¤LÀjZEEZPíægõ¬0ÿœeˆ—ì&%S¬¾øß~¶Š'ËŽ
+†s)âª3r½,ƒ_Õ-¡t#Žùô­ë+ÖßÎbø„è7ç&yEt`L¾™D¿ŠŠåºv=çSìU–% ¼´«iàƒYž¯êä0 ˆ&&ª×þBuÌ ÷n†â(ØÞÇm&Ñ38®ýÇÍ]øOnéß橪yR¤|íq¨ôLÝŠnŠUÀFIÈ{Ò¾¢÷ëT„#§K0ÿǽõà~ÝiårK·e¾•TÈ ñ…=’ÆF ‚nÖ!’Ñä‹ Ûå%(rŒ*Õ
+j]m¾‚-Og¾:B¿o¦èpc8÷
+ã<Ä9ëø¼•’=W>¢C½bñZQ≽è2‡ç?Çl1Iõ‡pÖçXE+èÃÖ[ì¼0pÆ Ï›·Øv̆eÇsƒ«y
+Ø… û²Yû…=øEI³(!,v³ìËPOÑÍäÖº¨¤sí£„ÛÅ"ÅnSG΄úC~÷5u
+²_÷¹Õs ýG§«È ôÏuP·Ó#Êûš%'/TÏ*¡ãÞ@£ø¾­­2‡ÂåÄŽ÷l5ŠqÐÆ}6‡_‚5-&@ý±°zؤ\Ýù61ÿ2x¿Ìèö>£¹­I@%¤uΨ©rÈ<»´~-ê×dý9=Û$Y¾XXH({¢ÏâIbo/Ù#¾ˆè)}FAêyÚż\ô©ÙMñcZpÄ_)©FH@ô
+¯i
+íÃÑLN¼h§ŽÕ:Ús¾TLÕZ¾Iåóü°ÌÃåõ`¹¯×ÜL+»úˆ5ƒv¼ˆÎѼý~9î¤bâ$—Ô5Ûg†sÕ"«ƒT@–5}˜Øum¬ÍHßÇØJ‰¹
+Ï]Ö{;íŒ,¯­p å1uyÁêEŽD¥çœVȳÜÉjPTIü[\ñ ï™;·sñA¾HË9qF0Ö:@Q3B¾’¯ožò½dg”•äϵշ¢Í¥Pë³Wy]‡'ÇÄé ú*9Œ<ÞIê[m1b†YÄ;ŸI•%Òí™ö?,oø.|ù¼±iJ.ãeó¸Ôè{Qa5MÙÁï´Öù”QßK>iã¯nõ©è÷›þŽ‚A†Éí æl §’±B÷›µÍKª©oÞKðã-Éà9y4¹Ç¸ãguhß™ùf‰ÎðTeLžW;÷¸–v<ß+¦ü¢_W!æßY}`½PŠVzI­•%ðÉ°¬_ƒÜàëb ð’ÈÕ¶þ?võÈ€çW=‘åôaŽÍ¯^¥a ‘a$ê²÷ÜÊÔ5/ ô™ëto,o¶ÿ1^&ÉuÜ@=î 80ky©[(Â+êþ[¿¬*æ':ä…öW
+@×EsÞçø²Ï1LÉ–3G*ýÃÕN²@O†…_$êühq•(™gÎ)ظáQÁ\ðp›Õ¨DÈ„¤ºÞÆäÕ×Þ0y[²¸õûí1râi3HH8n¥ ˆ‹…Éš¾OýT&{Ë {¾À­ÑS öô>`æ1Txˆ2•ŒGïW×yfš4‚Üò`ª+³¼Où0¬Y€JÇ1t‘øÐÎDÙáå«ÌÙ²b<‹FÂÃobµäÔºÞ눘ïf¶Ù¾ã¦"'i«;„ÉtAÂN
+–ƒÞÉ™i$©Ü»‡. eP-3ÎeÖ $äÚµ of¶nç(·Âô¥œ×ÀäÌQqúk¨€ ¾JÓ‚¬!™UÕ¸ÇP>ö‹Z9,]µä¬<)‚ÀÅ墛õÆG·êM‰ºLÉúhTÉ„²Í5X–gÐ;ItI£«’0®ê¬^SÉAŒ¨gŸ`X‚‚ˆ$Y(ÐÐ`a‹ÂD@˜™èqËÌ[qD”ý&cNL,•a`[=„ÿbç_@o 2“ÜÁ‚Éæ5
+äÅp1«ø(–ˆ)'E–ä_K†•2Ç|±†$ fžŒ¡tòŸpí1óòIF(H$[#×N(ÿÅ~àøÑ!½ˆéƒÌ€ß„ë/uˆHʼnx'Ü:Õ
+&ÍS`+b+6‘`‘•[ùí å!XÐ äÇ·¸«±ùtO#€ÒxÓ›ÅXæ÷÷Û0zyI«Q&mYó¯UÂ#’}k5f‡¹Æö°ZÝÔµ²X'‘ò°#ÈÀ”1*å¶O¯q¤ÙÈVÏk"êJcLì+þ
+ÿÊîñqÒ’„iè/åbCy e¿@ü¦Â¿ð!Eãá¼=-†}˾~SÁQSñÎNý²2º©°öG,è ÛR¦"¡-;‡€q@å0ÛƤ°œÅ
+Âuo J#㺙 =³çÍNþêk B_²¼c>K5,¸É£&·¾€ÒdªiÙ.ýºU°&¶ic0EAÚÜ•Q¹ ]8Ç §.ž§Ü%;Œ9®)É×÷µ‚¸†x§»'"gC«‰WÁ‚ÓØ$1fãh¹Fè0¤§q61¡<üÉ8ö-S©,ævNÙ”u„Üš³Ïd66ËÔ
+ˆX ÓZ{;ÎöU…¡qü&aR[ü Â`†f}ÓÚÏ]Ì7Qzöy'yÀHÐë\7sa…
+1»ÚÁ P$ ‘è±P+ĉ6×y+Aˆ5x¯­°rÍ @8qÛ/¥\¼Y\ÅD°çaƒO.Ï 0Æff1Íój € _rú¢«€hÑÉoYn6®š
+·L{_ñžjƒ¦Ö õs(6a^bñÖÔF³}ÓS¶-Fy#S+±
+ŠTϦgĆ7â/ï'åäÞI}z=ÏÁõgÑtÏ+ñYØ°•5í)%ËÄNf}Ì÷"¿ºd±)ÕàÊÇF %®lžäÊÊÓ—4Ë€y;B/ã£_'HÜS×8ž•…bù£Æ¹ü¬÷t…ZAê Ò3/ûàªÓv¯œ
+mïdRƒtV‰^°ñz>6þLl~…lc\|þFg§¸©oj¬}c³Ç1EŸ@oW— 9ˆ·Ù—¡:D†¦1>CÏÆ\j(£ïfð¿öâ—ÝTdá¬íå‹¥bíd4ièIsô“DE7²CÒVŠ…7(ÇÝ‘ $Óô t@ü„ó£…vŽ¾’‡¨›µĸŸÔ,aAõd8¤R¤Àl??&g.ÎO—ÅA„qÏ”8 ¿J©&#\™6曧à“îK*ÛHÈ’êTy_Rª_‘õ­»€lu’»ÂžØ²ºÈ|á$UZ›g4 ä;l,†¦ÂÖ£Æ<c9¶‡øç© Æ”¶C‚uÛ1²ï¬Ju ’þ·0bp•r€ ¼þÄÔ7s„@8
+Ÿàå“hOdKÛGì™ZŽ¬V‚ø‚J²lg4;̯“µ+q›ÌÚÑÎz:þ™%Sg¬ô@G1[²Š+ëÉÕ 8>ô­ÑÍz ŽT”,Úny@ÜKžÂ%÷ás΢BOLIÕ¶
+ D?08!hðfˆš9ÞÂ
+"§ÅÒG\ÅfÀð¨Wµ¹hÈ ë¤êçàäÂp3j³spƒJkl'»´Ãmö $4˜•Ã’2 }=œƒhjÍyr;¯ÁÒà„èËg¡úU…•¯é˜ÞÆõ;cƒÌ<j·D«X¡4ÀB üÃùQaÇÿB¶y¡Wò9†±…mi™¢ßZ‡&ûŒ¾9ˆ=•’2
+œ‡µ·º…¯Ô÷ßúý`°`e2òª%‘ÉþàœÉ^xm¼tr„¬f/$wœJ©5²B¤+ ~ÌŠ7mÇ+R€ÞFr¬ÃÎ!Ép*ã[:Dô†oÇl¬«ð°ê:¡,·ˆøEð@/·]’¤Fn³m ó3 f8SÓð´iì4x •€X–¹ß®þNÀż9°ý爛_*@”3?ȺJ”-Sæüpt¹Jæ÷RJÝej¦AÔ¼ï
+³×¼xq(!Ù¨ãÂW?›¬8.˜V¼Y<;ƒà‹‚ÙDÚåZ|±`6Uƒ0”v‘ù6y¯$Kë ”¬b²K ÌÅ`ßÆÞòËD
+³÷Þ%ÏÌU˜Ë6lEˆ˜-ÛÅŠòræªîp»(¬²‘?‰”…Ã**Äü}29È2 ¹Sªg ijŠÏ˜
+©û“¡ô~*!
+‚!ü@08§4)›ÜÄû3]8c3A(^ƒÒPÁ½ ÙŽ”¬/·Iªâ¸®2F6¹$IhÌ#ZÄx„œaÞ'Ñi¦
+Œ˜"yiAaŒ1¦éAaâ4‘r>k“œß†2Ǻ
+B¤kx€ùfQHŸ©éááLltBœ"³¶‰g2
+ͯ"¨dˆí˜0€ÀÏMvwnªmÚî)u7©:A~øÍ¿~@'ƒGÓCÒX’KRùt
+rwÐ-È1„P&~-a÷Û1ÉÁ4Lç!ÉR%(=ÕÎÇ$„ƒ>`é’Žu‚[ãOô”ä
+Î$(+Bu%×Ã.ÿDà Î"-öÓÂA—ñµ®ƒVrÇúÂt`¸àÌ´(¨-eWªD ÔèR¶Ô;±Äƒ×õWê?ŒA‡ܯûÔË!fc#>Ÿˆøý
+¢®h&´-{Ëá\ 2hj€ò)Ò”*[’²AXEªÅ´e‹‘‚0T"ĸùU5²Œzöêçà šÀTÊ(
+oëäàú¢qõ”‰N%ùMÚx\ƒåÚ'ÄlÙ1/´Ã¢È©
+çewAP’ÙÎ,ûvCümc±´ˆ8c¾ævHÅ¡šcR~ÂzbÎxÂ0v+&ô%†yúØu‘hÍŠÌ¥
+•Á6Ì̈v"@!ùÅ»M¾¡ãÕ†’" äKžiWDÞØE.wHDí3™—þ³Ø68!žÃzÚX;h(2ua³ÇÇ0D,%Ÿ›ºC¦Ø0Åf6ïÃy%¯­Èœ!NGËÆ~w
+¬3ˆ Ÿe_…þ%ù0~½¦{i ò²æ[„Úxa R §e-/[ÂצTéù<)£°öCŠÛƒõB? ÖM×…:£ÄTÑå:•äÜe:ÚIpÖM¼EZ‚cx7œ\©œÊÍ¢uFœYM™6GˆÓS!ƒ˜É•R‡ ËRð´â&@BU²b§tR"4.Gä[I¨a`E#c/Û4‰ð˜¯Ó´jg¨1ï«È§ÒE¦¯û9ÌGeÅ‚ŒµƒðÉ°Ó!²H¼ÝLá(Cð겕Œ=aÃòô›(íÀuó·–³î« DÆ…ÕlÉQ´ÄðÏš¤üJÓ~SágZË^9ˆˆ07»Ï)$ òQêaºläUäÌ<@¢61“3ßWý¿µX$¾X¦Æ>u×}Cä6B ýs5.^%å¹Ú'¶Š2ËJŽåÓ>]®ûþä›Ö§ßκjÑ2OgH!ˆÆôuÝÓI Š—4‚ý %} :\w{ßG “›Ñò1IØÓ¶dô3ÐÁaóôýë_
+H‰t—Mrœ9DOà;è£à/
+)³žçŒZJé#š÷ƒ °^Zµ6í z”Jƨ÷&¾?[”säÃûu¶Rûòq‹OgwOHk“gô5ËØæ­ Ã'ër®ªÎG„È'ãÍ9%(eSá.bøªm
+¯ZúçZ-Fèª,_ŽÕ–í‹ÀÔº†u}˜n<«xeû%/Ü¢ÛèY…2×´ÑÖ(¶!ü¹yB¬P›³÷y¯ò.îv"ÅRª*<ˆ}Ž­A‘¢Yæ&TXŠPÆ<Wír[†%û&‡¥æU¶9}ÚI,^´¹˜uÖsN-«ŸÚÏ«èÒ0ëR³ù×ñ HSüÞô‚ H[óï}÷P§‹kãÁ‹Sæ§üéÀU•1o©àÌAÿr@ëÒçý´Tö-¥™1Ò­¢®y"ß7ÄáK?S?„æù”Qëˆ1ÈÆÌpç4Bixöðæ0Š57¯¡',ôÿ5Ô¤ÇèÜÑyù}ÑZ4øyÎùÖÝ‚tx…­>žDB¹S7hÑçí§¯Zë­,›¾Î1ßKUÈ$o’°=
+ߢÃ|ñð"ozРo+ù$aGŽ^e˜ÌD[‹œ÷þòE΢ü%•¿MGƒf;ðû ¢èëÐâ(?õŒ‰NÕz&É7Ðis(Y¹ NH ”z"#ˆÐ”Pë8ˆ9gˆÚôL$Kg%ó^ÈôÅTˆ)ÔÑ“îÓ«SÐ2ì@}R"Ùi“÷ õ+ÃE|Hé%É㔧 .~Œ—à ¾¦H?ÇðjG™ƒ:„·å Æžwö¹¬Ã[Â!B[B9å%kjŸ’©›Ú¡iErŒÎ<FÉw4qAË1ÃÆž0 ¸µ †¡~   ß¡I¨èÖ"'òYÆMõBHÄçǯƒ¡Žê‰ÑzF㢗„ÿJUëš\sý G|R3ÙѶ%ÙZˬŽ„¶6RT“Ëâìb&3Vf‚(£ªY.—}¶µ•9’ù£¿iìF«HCÑ™&(öŒHŠL_< u°7ç D†ú">½&„.+ôh/9Å»ñb˜ByâM¿Péñ0§šdPÄ‘kzèˆNlõ.ÜŸe ¢-<Í«3€£x3!šl Nä¡Þ«ð
+ŠzÏ«PZEOÅ&ÒjM4gÒÂ%)`
+>ÉŽH¡¶#`FM¿²C)yÑ"YòÑ£‰L~X„GIÆѼ¼ŠÉŽëìáo (=wëô{Õ ¨ð(ô™žöxN¡w¯aÓ;H£|Ì`êo®*ˆ)&&1]R)I.Å#9QÄ
+¥¨†1„O˜UÁÔ¸³èD{úÓ0;ëÍ9_ìø3äËdüùæU_@¿ž ´‚fä2û06qÞµÝR…þãfZuœ=Ÿl­JEWII± ó¶žÔŽñ ™Ì¢#w˜ Éü>õ¬R›ë®,)3c‘ ëGqHe
+¬½"Ò*}¯§ ul<ßÛ™UMŠÀÐDgH!†.+´?& ³ƒ!4⺿Š`¢¡(GËÔQ£¥‰s8îO†B^ ÍL[ø­í|èßÇÉ@0êSzlÞÉ`‰˜ÚeßöÅÎKjû'ùÓgÜáO\ÏÄ1SDN6â$ó¹Ñ´‘WÑ‚D‡ñyº£øQÇíìs°Wˆ Ô#oâ u^jÌÝ™Oïžö S5W Ήúã)¹pàäáµØÓ£´önŒX;×Í_ÑDvrvwÉÙØ{¼jÝð38™]”ϵOäÓ)ݦã¹I{ÿ£Þ5·D†ì’g†ð%’Z¹‰Ñ˜ÛUäriLà‡Ë j" ¢))1A -éǹò ?t˜wW&- N44¹9ÛƒšF4Î|ö^7‰ûkAPø¯™s›ùN—Ï­€œÎòÄÌ®c§ùd•àpXtj±$z®£è2Ç0ÊüBh2¢ïxÏ+@xL
+‚ô(öþû;$K°î­Ûv8LýUEžÉ«æ'`žM¾Üùf~½„ÉbXÐúã’x‡AÓ¯J$1, ‡­Ï£¾É|L`e‘Î_ÅkX+˜é†…©¹ó_š×£}Z rþ=Xûø³Hóp’`*§È4ÇÈ“Ðs’§ñ)ÝÒÅc\¸C~ý9 4€`‚Cá·0QìJ6ý+mâ c P{V—¬è’õcښ憩Eîj¤´I8-ì(×Xí(ûvÐÈ?ô0µFj,îê~—ÇMR*›rHôÜqÒ/Ö탭L!/²ásÙô}¢ë’WÛ!/E"‚Ž
+´’y„ v
+GÆfáðºêµ%‹‡A¥ìaÀw©æà„ü¤¡TЄÆÁd€!K«@~ÈGtŽ Ͻ§/)Aë¾€5
+·¡”-÷äßÁ¡Š˜X”%ÌK<%÷Va|,ÙÛé,ðW¶îé‰È+VH¶‰ëM *†IÂD¼¸vîáb6÷¡Pss…
+Ï€/Ò®YƒpñzL“V‰0,¶¥éGD’d™‡—~ž…©aÕ
+ë”`dz÷+oÄW)…¾G‰h8kÛS>2ã‡×þ*lØØX
+ýéC¸”žˆT¢œS”2{(ŸÒ Ô΃ǥÄbŽ›P®?Šø%<ÃÒ?>Ͷ³{‰!+†U×ÕæPÒØÌ­\Óß</CÒ+ˆä<Æ,á6vÍãé$JÎrJjrªðÝ<þcã
+dÄ»dÇi
+ᶗ|ƒºœ/:€OÝ»ÜFþ9ÛOÈc{žµC@­Í_=•ªUà¶KÊs‰£Åkm©dÐ
+.SŒdÔ.å1:Ö…™ o¡õ\ò{ 6ªuK†õÛ@' ja
+†F;³‘'üQ2ŽÂÄ1L<bËÓcÌöî½Ùò”ÌËçPg YæÀJDÉžP œä<HLiioa@6—Ç*y ‡T´iè1"p[áHÆŽ„
+¦~Lmhl†å,'ýæ÷dJIáÈ_Þã9ÞRÂ.E¾ô¢ØK+ð+(ÓûÛÞþø÷[úö¯¿ßþøï[þöç{ ƒð…SÓâ—V „¾R‰×{ A
+2ÔTðB|Ú’£VÏWÿŽÈˆü;{W¬„› Èä(82@ŸšŒA‘ºÛ—u9{Qg_”K‹qÐl²8…~j˶—À$S;Îè–•TbÆì¨ò67üX¢£šì
+û« ×_}‡¹ªu;wã2J0iþkÞôÉ3ÅZYrõxx<1Ã¥¨'^ÙÕŒì>B\/ž ˜YE¨ø/÷§Ë¨Të¹XJøÀ”ý@Ïûõé%þôÇ>}çyJÖ.ò›[Ktho¸y1iŒô<ÕÅ/uÚž¿]ÐU¿7
+:‚՛à bÞ{k„ň®¡}Ì»,ˆ³Ð v‘hã:Œ‡’ :eXÇ=Ëõ;
+U§%°ÈHb¥ü2ôîƒàˆìî”K_ Ëi«‘µ…ì3ß‚9žk>^Ô
+¼Þ¢«² ö¶n>ˆ@Üî¸ë/%Ž v™¾ÓÅÞúõ;@ŠN ph½„U­,2kí%dÜ=±Ã#®%‡dhXjq”TB¦
+–qÔ+éñB  jŽ\°›¶š‰£ÐR¥7°Úr0<ËÉ] «qžúliɲ~xDù€æv}¼à/¸T´‹Kã©Øi–…›ž²Ÿ=”;&¦…†`[èK»­K ÷?ÆË丒¢´²@A‚ûyæØ^ôUíÿu^‚¤4ªb…þa)  $rÁd89õšû×¾×|¼r£ß~qz:q¬à!ׇ‹ß‹ÐžÚ›ÈüçV³ŠÔé·†’?SÑ+E××¾ös Ø’Ñ¿@¶·@óŽSfˆ³(e-}ÌÂcå©2ô•Íp…×}ÏuÀ!¬<:4¦÷ þ&“Å/®oUËK-‚rEè=þ*Ó‡U‚G@þ'¯s(&+`Q`ª7ÍÝÈ”#šâþ¥äƒ#¶)(W–öpS æá3®Ûdƒ@ëk^‚檆 Ü%ðØÂàvÖ§HLƒÏÀ[mÅ‹=(#Xüò
+1 Ä@'ÙIÉi7axÀjv*ú˜E\u(Äá»çÇÐm
+Q§¶5-¡žY ž' ` ˆj$¶`³~h#)ºX?òDš T`Œµù@ïE²4 A®ø@OEÅoè5æ>€ÀFç`þ*[àm–`‡"­`àu•@æÔtNɶ鯡‹(Öii e«µíí4‡›àý(œ2ñíß_È…(¯`Y`½rBÇ_/"TÉ41N£/$Mö èu­6‚βfÚúª`Æ0Z«‘(¤çS„zTEØ‚™\k:¢{):Ÿüp X×ትº-Dú¼ )&·f»·ðØîâs/ã].×0Àë¸×ü~¨©] Ý(qV‚*ˆ¶¹Ç"î€ãŽrÝåM ¦ƒË(FXo‚Ì"Žn„¢ wܳ±æA,½zúºü}fˆÞ›»K$j£‰kÕÁŠ%"«Rý ÉÄóòÁ·)ý8m#,`@r˜yq'µžÀDÙ(³;Žb­Y`€‹¶uà‡ŠŸ/R?•$y ØâÖj„žÂlSµ¨ ÊC<Tqi5"ìv‡Æ1‚pž—I)ïjF- ¤9vî%Ù]ð*RGƽ½ne¨4ß|짢
+!5©»ò—Ö·â|xæj¹ÊS®±c0RMr²_~3„J+©T­Ýƒ¤†ºãIgƒ¿êµÖME×£nç ¼øg\2ôÛ=è‘@±ÈtR’y
+6ò1möž©/æ ìq„°aY¹Va ñ•V]Ú-´)§±ôºap
+f¼ÎÖØðª´CÏm‡T½éKyxà,œáªÊuñ>VÒ+àÃ"
+ú%äô8c…¡b3<‡Þab
+ºhŽ¨Ç«“èÊôy¯êÎê7Æj¦G|¡v‡{Lå¢¼d™kî˜1]?[Ä9h¸l®È#2‡g,·¡Žù²"Q­qŽ‘Ü$eI®lVI‡–8R\Pfs»œ
+ºa3éòo”˜±dAh.¢<± Nukô¤ð$¼ËÉ”>ÝP4<[HÑB·1‹žüîÏÖ…qŸp ç7<ßg&®›Æ9èAVm;r{A^!:y²YÝsH—Ô 7õ_Í¿ôDËwa˜ÄÌÎa=’ÃZʵ ,ÄãBÙ΀gé êBZ}=ÐZÌ`f½xþXÀÈ1φ0d€r4­´o‘¯>Ñf–KA\E­7……Ť´ZxNúÙ: ƒþ,¶\eó2ðcŸIÐì2ntFñܬf0¼Ó§“‰’6~{å&”Š§Nó):I ïzBh"À¥¢\ø…dcPshrßíMôc"É×ÊAÐÃÌÀ; 6“àp°éóM±a
+mŽ~åJ}•
+:ì„pý&;Ù­\‹%ËäQ©²¯CËð±îîË ¾Ôd È-ÉšF~~î;·­ñ¹œÁö™Ù’äü¬/Îéü¢€Ó×F.g¹Â Nª€RÁ<ýS GQŠ°Ñ?¥úƒ£ýj ²ù‰P¡‚#éÏ(JâÄd
+Îf¿Zߺ9ÉãEPÞê/x\«¥…
+õÇwF³•l¶+ÒTG{+:ïãE^&ÂB$¾˜Ôýx àâüÃûÙ¾*7ÏÙBtÀ¸dðê‚Þrºçé-ðr%æôô3ÑÖ5‹_ðuTù'NOb¯\µp”#ë,h)DV÷¸.ƒ¦ƒ««ça!]ê[æ
+•Ðʬým›âç [á/‚pd=‘ÕÕí: äct·Ê._äM¬«óHJWµSüFsaÚrvypYþn¼€1þpÀäÆ¥"{Z¥vÃÈ(«§›
+.h°rú3Á´>чg£ú(ês†Eà¶E짱ヱ7ëúÍe¢$4R£ÎÿçdV×É­éA×YrƉФªº0°B"Nù±/A¿Â Áã
+,X´™š'ÂDQ`ßv”7ÝHÔšÉûÒÑb‹-Ì@Ù‹…p®@¬4™Ð‘VM›%€—ÒY+À&oŽ¤1SͲŸÃmðnJ²jØ?UK+êÎLÒ±3î‚´Ýð'Œi®ð.¸W¶VÍ[LSÞa4ÄU ß-Ÿs®5  ÷ÙúQ8S‘õŸìˆ¡Áob#,ÙÎÿx!prMŸ(:i$ËQD;X0¹Û€´€RÂ=Ƚ=^mɱ°£Ú—`Rá°DÏ1E™¡sÀVÓ~òPÆ4n¦?}&¬ÝñKðëÊ0ÊŽÚ³H?‡Ô®„úSßsŽÎ˜6GWSHZй¯°˜·ó)áZãÓºUx}£fãÓû…pn™êëlèDE1ÚUnÅ¿äBî\ïP´e¼|»PdÏÒR§Ä–QàiŒú"„f
+G¡šiA¿^ñ×I…G¢ v³(ˆ‘aVì[Ïa?…$O¯•·É~Ð-Ý™4aÓ¸3È"2!‰>¢å%µ
+‚FF™tîºH‡Ôr
+-ŠÎØ9SpÒ4TÛñm NšYo³ñœ!Ir>Ec—IW^œƒŒÒ5¹H¾E$­_,¤([߀Xf+m{%lÃœJß¼^ÅpKpsÎk¡ÔÌ*âF2NEéBx<{mVí'ïºþµäïŽÒ
+þrãªí%0‘s'Ôá0OŠ‚ÐÛ.ô |þrDQ›ÞW-Ä  X-òru‚†³q‘d((sdI¨¹’v|X{Ÿ~ÚÔ>„°ühu¬r^—}S„´¿‘i³ŸM´÷Ç1{–7º9R7c ôXJé¼Ñp°
+ ]}÷p‰P&YŒÉ2ƒ%ÂÊ*c&‹Åku£ëfîJ³/p¹…K„Íßn›$ãú#Ú4‚—j‹‚ýÆÔ²³(aßöw SèÊ”—k… 4‘­g+KìSZ"|…˜"ײh]}‡B°†`Û˜Ò‚1UKBrbgÈ$¡~.nîRÀþýGÔŠÁÿmÂôc ä¯ÊXtvôp¹Tô<¼-Dyô¦²ÏxIÜ(‚ßIf/ˆ“2SÄ¢tÑ5ä£]&‹xÇï>ꡘÿ‹ÝQÄ
+S©QË©'ñI0É0»£ƒj 5e’úÑ8
+©5xrJ‘s‘WhJFxN6›³á³ß^N 0ú9,O(³1°?\ìÃô!kÛK‘ÔD‹ŸN2Ð÷ÖÊ(»KlZ‡dŽÚ¨ÓZ ”(¯ìj?4ôt Í°ÝXwCÛß”—I’$·EOÀ;ô Ò0kjÙ·èmñþ[½ï
+Mæ=ñÆðòÉÃÜ ˜J·DF~ «#›Lß% Æ;Ì„‘x¦kk&Ž0BlÁþÁ*D4Bíà»l
+ÇÀ‡ŠC½:KËN;R°”úED×ñ0Ë’RçÄŸM®Pb8†· 8 ¸¦„±åÏØɎו"ŒŠû›k½î §Y¤Šu“+^$öè¿>`ðï\$,¤¨¿²*¶¡ÄÌŒ±}Fö‘^ƒ¡0åˆØFˆ¢Æ¼"<´! t þr7Bp„ :™6"Êÿ  WkÒÌOYjYŽ¹¦’QÎv[’X0(÷ÛnáÙœ³AzDP¸¬>¾m ÇÞ¡ü¡YCî ̵nC¾«"“ß*ô‘9â§Ð×*!¼É*°2©: Aø?+Þ›a\ÓXVåf<ŽeèKÎhÜ’Œ"cÀÐMÙé¥h<À`kãþTÓ˜ËÂö¿‘Ä“ãÎm°yØ>ªÌ=@¦ü­,ëH}ê
+¢ÎêàdãÙšueB‡ã
+k$ÞÄþÕy л zR¦€Ÿ‹Õf'áœÓ—«»€¾\/ï2. ~Hë>x^¸š¸UÃ~_ï£Ënõ±– 7øþ²ÉæuåŽÔya&ÃQeÎ%ÈǬc˜X"}3Oû˜5Gyùú
+îx;‡oÓGu C¶ßwÀüBÃάÁeG³Â71Ko±E%2çNùò±ið9 ‹#Û_¢iÜ·SNüÀ¥²hIÇB§ *$“ùçÿå%ÁÙlz³ñ@’?ì?Þ½vû˜Œ>ž³¤í³`Aœ3üÅ+lϹ`¹m1Æ Y÷¹ƒÞÔèëÉ’Ïb¦ ½H’ö«yŽíŸ…ÁxFò`û¶´•)«âùÃƹcë2ãEœAvòd¸èö™YDQ¢,›ªlÃÑðká'OØd©æZsÏ™/…L3Æ5îÛÈñ²+²kÍ P[Âr¥Ãº5àO™§BÍö&_A·*Ú¥ñ8‘bS”O1·ÜébÞb§!È(¢«{qrŒ 8Ôävc™nŽ1ý†lØ:/uªWlF»8ȉÖN&dˆP7Æ$ÆpsVΡà7àëÚvF†Ñb_ºc<Ó‡öÂa‚<÷S³î kŒùyql½$1BÔ
+¼”RA1 ÍÈõä Ñ
+~'·È¦ ¡ûƒštwG[,(ò½á=Qæ2S]1ç¡£¿B–9²„ÝsºŒY3¯ö1¬
+ÑŒy’ Ì@£#Ú±Þò&B‰^võû~õšCŽmÜ N(î9ÞAV“…ÉɽL—S³ÐϳoR"¤R¾4NÆy¯Í@IÙ`ø ³VÝß!—Fýý—zkü׃ÈÄðöÞÆ/ïÆQpr/»/¯/Í[G`‰¼k|)`coP ì °Ž¹vþâ€`ˆÊj7·›ˆ¿Z·s˜­žÍæÞ¦b¼uBY
+OÒ¨Cœü¸Ç-Ž·U2+åAËvácfOiê‡í\ɤ°5H XrÇŸ(rG¥¡QÛa‘><‰© =Ÿ¸™ŠH¢)ÖÙhþŒ{bŸ°½ÝÑÎפáTˆKÎ-ÿß„*UnØav5ìqªÈ@PqZmTï GÛkÔ¨T‘òƒ[s@Wu××:_j°a@»ž0#ñ0iWÉÅÙå/ÍI!h Ï.'ÐGX©B³›Ë+åe×¥&½…'~*/ ¡¦5köÎA²0UäƒQÒfѤׅ`Ï%E"´ÞH£JBôeéϲ œš_Bwzñ ºˆéoÑ…>!?œîÿºvÌûÚÏ-ΡÚ–™à¯P.Jaª‹‚t8ò%ÛÔ$Ð œ¯"™!˜ 2)ymwÆÛ@y­ÔšêÚ¨ŠÞ öˆu3‹­¦Æ—È2Rú˜Î9°K¡ÊHBÊ`ÝÆG—y¾@þØZ}š€:£{ÕB|{ïwY¸b¾&‘iF,ìnjߧ Ñ•îðÖa»|Q>:@õ°7eÕ˜=ƒ¾à³â2Å‘_øwAjº},îÛD’õ@` ½‚jëÊAí«ä ±ŠÜÙ,,9kÝ=&²\l€Ø•Ù6¢W¯õò_ÆË9®ˆ¢+Ð+˜ÿÐ¥”©W rF†Þ¿Ïm
+/‹3$'íP2‚Ñ£’é“ïÔ¢¦Ù¤U!;Á%€Ô¬ÀU ½€¯Eך£.£c$×Iôa V[ß±˜|ètAÆOÝoŒƒ`„TÓ‚tX±ùé}ã‚»yíZB0^èzžÓäK˜p´¡Òûu^ôØ¢Ÿø» ÏZÁÛ‚ò…¿¥S1¯(ÃÎk -š/4‚mGz²³n¾éíÆ.ÙØD\à£d ­8õFЖºÜZ÷籠=©><س¶C‰†äI¸h˜-ö>|3ÏY 5ßË®¦Ë"…ÉKäʳô 4ì=ÆõÞNŠða\‹.ŽŠ
+VÆÅnñï/=Ú]?Åá_:Š:žÖ<ÜC„FQvµáðHlr,fw:d>Cß÷Çãè?’vœ(5 P]Ž Õ#{OŒxQ&Êyþ%Ⓠ“·¸KÐKšù½ñb‚Œq‘rü~„2“ÓAN”vk;RßKß=X z—2™QŒS9©¤H¡MÙ+of@5™ ±ä%’&tºb¨VIVld å,ýê¸^‰rÏFÌZG!¶Øâè¹K”Éy0x£*´YUé,uS‡r[Ǻ²÷ŽÖk‘šß²"iÆ©9€¸2û•àîÓE^¤sˆ¨¡ŠT¢e…0)Q#RˆÅݬ2
+I4BÌg:FDÜ{Üê±ÓÎáãI‰¦€Ag„Ñûw(ÊR=à‚¿Îuˆ¨Õ¥jôoH$ŽùBi2”
+s×JÎõPôþ¤Èº<“‚l‹ ®Eº6ñ³\’—a— ï‹åoÉÊ;rÒdЪmHºø‡‚>.$ã´8ËÔ°`IJ¨¯œÍ<‰°ËöuùòsÈEnŒPÁ:¶Zó$TO—çRýø‘Fåÿ¤åq‹2J™æ¤·NÒU £UÔz5Ä0à vÏöÊ Åì}±·;’›UY_ÁYŽa$윶ú¤„å€Ýàm7ŽQ€£-*ÚÄKÍÇ“X“ FüC\P§= …ßÛa³‹<˜L娄æWó­'Õª>–X¢õ섳Ò"»;m² ŸnÅIÿ°?Tôô±º—42ö24¹='^KÚv±x«Åþ‰` —ígè7A«ÁÏ“ØPM¶…ÑÙÙ7í."¨1>³_°,rVDçÀøXNÀ[°#ëŘ(ŒŽ¾«1$·¸– ÍÄÕè
+PL3iÅ›§bAk €í#1aáÿŽìJ(È:
+¸£+¤/äd–DÚK’¢¿{³õ ä¥dÄÿ×SQQØÁTAÓŒ?§Ö\²í ržÅ~ò,.mK¥ºL±é˜láKÏOK,CÂäÒó:×¢/ÂúñŠúÊœ„€ó–|@ÀóN`‰ñ!‘Îr4E!²Œ-Ò¸†!•ão*æ%¦@rìÀñUñ²ÂB
+Z16&J‡ï}>)ÒË4é1PT0ð àH_Ö¶ûä±Ü•~ó(‰ÁaãÓÁn¬%8‹Æ¯lˆ“ó% Èæ4Èš˜{ìGÞ'}5H§±?º,á 9ãSäÐm©>ÃF}])÷Ëœ|Ί^‚a†a¤U€ÝBø%˜ÖNxšQb„ÇÓN,rˆ ƹ3X=Z9änVwåOyAŠižÓ0WôÛS§ÙYn€–¯~,z˜úÇ“¢.çƒð²â‡U„#âíƥý
+ØöVÛd•.¹yi ÖC~Àúz¸ì0³DŒÊ24\y Iô`4Ò¹FÜÖ<éâU®<yð<`Â8½‘'cäÀ*B' ÉS²uD
+>Æ8™*Èëçc¸Ñ¢£ØL_v™Ä ÚÊA‘ú/±•9_ÃTp­K¨÷u†Åõ| “6Üç#xgœ‡P‘°F9‘BT@\àl-»†¥pC4èyž`‚ÉS¹£®=,Þˆ³f{;¹¬Óó‰—ÑD½=&0ój]ê
+Jº2míÅÐËáèF,iœþñ<]
+0Ùþ\óõÎzÝmjE𠛘ÕÈm|{í•~Fh7(á¢Û¢{û}ØLóõ¾f^Y÷ì×Éú6].bIÐùé_ó£ R–£*è!ÓaVýyTÈ®ÁÜíaq™ïÜ—Iâç"½/Cè3¹ö Õš¤ºÂ±¨m#ö³æï‹š
+°K”ì^+äU!±´ã.++@ÌâŸÉf`‡†|ZSû¹1Œ†Ó€„“% Q€TºôÖÄñÎ0®þU‹CïDºSd ª.˜ªKr)áPI;4>ó‹Iý2ñ?w›E©I§tÔ…ÚàhÊuðêY#Ó<èJ¢¼zö,á5,Òe¬xÜ„ÇNá^
+‰Ebˆ8œj·šb–˜~4üK ï²€
+ó[ãœ#w®„4Ñ•àéY¢]-.`€ÕGt×ðØä0æ™®ø`3ƒ¢§p5ùÍ"¼ ¹…æà@Q à"†¼gÁ+û,
+g´¡½x,ˆ—ðB¥¡¡|”ì/6G§å𜠾É þ²–#·A‰ü-öA[-àïÏA–›×’îÕœ"U,èÌþÒ`0$1B—?"¢dñÜ♎ö® 3¸ãÈ
+z“š² çþvÑ“ÉþuIï»´ÛÀÝiñ²ÈÊ÷‹"8€t‰ˆ0ÄPY¾ÐrÚ“ÅÛHtDÀËv‰äÍ99_Šƒ\â<²ÀžˆþŠ@ê”Ý—uµ›GvôC%e(Ú®¤1}‘Ê°»Óæ Å(ô–="¤á*<‡ÐƒŸŸC0:ò…ð;,FªeWuÚ±¹å ÅMº)ILVçÏ?Q” ±ÊHcß3‹Š€L“½€)›ŒˆÉ…“LIæÂð£T<­ž%\RJn¥ç帧4L[uÖ‡‘È€«y‰§ô·á[hÖÕd~‡Û/â» dϳ°-|Ûû‹sGþt›gè¯z†àSwžüÔã¨äǬ>ßÙš¿WN)ü52Õé&?8ïûE‘ž&ÂÎxØQ"\¡Ñxƒyõ"à-Å|ôEã^]7ÇÁ)iÂö¡ê2Á7 ÅƃBÙFÿ(»aK _:·ÈÐ; {å]ègû/9 #È–tx L‹¡Æ´õq>Õ•˜0Ì,x?€Æ˜f. cžæh÷C©”}ˆ5馬zÒkO‡«Á!Œ,»bP‚µíIÌ?®-}ðêAÑÃä¿^á)±bÉïÏZä!Mcr¹gŒÔ2l C‘Q5Ña§ÅÒbÑ$>çÝì:¨iÒÆ#Üx­N0-ËüœDø!4å’îŽä‡ó Øò¡ä³Mñ.ÔÒGxNSòJÍ6¯Û R#Ò¼TÍÝ÷˪šìI"ôu š7>
+| nv¶q6.`5ø#ÓÅ)]ÜQ>d–‚úÐv'Ñêç4°[Kb.N™¬ÍnØÖ]’±Còkù*1ãåSAÆðé&Ï¢˜Ë—çš¿/jøKÂ#¾Ô ÎonÊà: ›ÈÉ?ÓN$–Ä`ˆ„ÝÏgG“â#¦N›^bæ" ]ÍÁñ(œ*íSMXÕ,Á ×åºÃ„u7¬6²ÎH»ÞøŸ;Ç'^²r‚J²h66Hˆšó䀨Èç!½Â˜¯y_gö’·bÜl—0qîÅ
+ò=Ëa/be4û'}f@ëˆ<µž“Á/˜Ã)åܦÀ]ÎBÚ½6Z7Ön£Å0¡»Tи­où†áG]laF%ø,?Xíò†0´<íO‘e$q¼¸ç¢'kuùÍ¢–ÕQåvõëE”^Y&˜áÌ0½JïßPÅ ­ÛDg7g:0 ŠqE‹ÚgUHdå@c¦püÒËSÄ‘ÀghÖæs‡1M™pJh¢HÀ®× ?WVa¼ŠéƆ°Õ¶8ZÀdJƒÏz¥˜$mÄzџ͇\„…kL¥M/°ôÖΧà0XâÚuւɃ\}îX#<þoœWU6O|Ö…ôXÁ WÌ'çTÐ -ñ¦yîÃï›ÐÜš”¢šåæ±7wî€,´‰ÚïšÐhU{¶>Y‰_U䋸ÜÄ”ôT?=Ûç늋ÞyzÍü%žtyòâk ‘a6ƒ&ª€÷˜ìû¹Y•(DdÙh#&„lSÔ‹ åÏ1Hm˜ÐÆÚ^Vùo8uõ1w ðJºK¯Ç†²×XÁ½oÚ}.â•|-t’÷´[DªÞ®!É&F…Ù|GƒR0ÆJq¨ßPÖÖ¡¬|O'¬ðli^ÂX
+Â÷Àæ²ùcÍòý!Ûþ ·!x¿±†R:æÛE2L /{þ˜§èñsE_ïlè__ä
+%
+¡ªîÇ¥)Ñuz!]a¥M¢BÒ¼tOÊ6²òÅK€fÐ|[9*ÙŸú—ò29nî‚pʸ°/g9“ÿ*çõ׀ߕh•t›Øf¦—LÜÀ]dœÒOëd s‡™)G/¼R
+*E{ºË@¢øo~Ù8ŸIÄZèK²‹áyÑvžC»u2BPÚ´7R‚ãchçt
+MAq MŽµâ£²ÍÌ© ;YÅ=ÈK“~~x §ÝùÕ«´¤¼Õÿ
+gÅ0ØÚÂ'²VÏK/í<™êÀÃVC$5 © æž Á+æÄÖ>IÓ7™.üNÞûÐùZ ò·b±b%Ÿ%{¸@XrE!9íNƒ®2Á\|]›sF|C¹¬k'j†‚Pöã€ÇJ,µíkÎS”2Òqbœ¦B¹˜ýRö +x`3yž-ºP)n—ƒ9ÉÊ&U%C²Òpðc´œvûüðASÎÎ|- ¸ƒ”r0ÿÍ•ëÈA™¥ò°ÛìS¹É#a1ò®xƒb(^ µ,VIp-]‹ÙêéYqÙ$ƒ±Ù‰dDj`{tyUœ¥è´V±WÆœÁ‘-â‚›R©SÏ®óiy gѯ}ѹUƒô \LÛ¾úd ›RÂÒ›Î#ŽIÃa“”€t™d$‰ò×f¬‘(yÂçD*@l(`ÝG"Â"¡XsÅèñµB»Ôm›|)_èM[Óyq¸Õ=©$rá
+‹¶Æ ©_ô]?zöçŽ2£<t¼G
+Y‰ ÞÅÜs‡³Ù=wü>žf wá±zú(mÖÍŒ 4¯.³)f
+ O(.'(Ê Rå3á°ã ¥‰ùZKч]n.êÁØÐ,XιØý†~£™<ÁeJ3¨4Â`ËÐþªj‘¶oäì„«˜Ká?Õ_ÌiÛjÓ,TèÞaä
+>·,IÚ6íúZ Z™‹q¾R­C£L)†µÓ÷ñ¿°p¹9¾[„Ì@r‘mc‡¥ˆ+ãÜ|6TñÉ}·¬˜‚h"[¬/Qž³zÆÛ©çÝ¿¦ áš¼¢ÆÛ]Gú׸Éiôݬ¡ˆœ ÒAP§dB:Ç.KR¸$ß³­PcQå 󤤒ÄÃÌP¶‚¢ê¸-=*ÇŽ«Ì°ÜªÛ»(W±Ó燇Q¨d´D}8«§ʲyúKŠ¢Î‰aN›%¢4Œ{ó‹’¬G¾¾ ¤êäqxûµÎµ7Ѻ×Ó?\^g
+„—+òz¿dÙ±[=ï FX- 4ÏêépÀrá²&¶^¬dVn}Ë暤+‡‚In…5‡¦u)>[ŠÎ{¤}ñ&Ù'Ã¥ü$íRÅÚˆzë¯ Žèý"žrÊØòNÚROcð=é<Qª ±†Á ÁK8ž°;ƒ
+N%gþ3‚äɲ²<ôªC‚t^7 ´cÒn”‚£iÏ’¹à­#Ès2-³ìúi „Õ¢pšbþÁPßAŽ/
+<5`?iàò6Èá tqÔžb¾èBlOquø+@M–èi¯.œ¡—æ !”¿žqÿΖ~-^¼° tEÓᘄézj8î‹ÉÈž¥ÁÂÝ3­œ³|÷Ô‚D[…øˆáp=µõ`¤+ɼ´ôá•ožZ­<cÄŸñ“æS¾yjëö¬Gé˜øT]Oín%(RKú‰«÷ö6èu
+H‰Œ—Mr\9„O ;Ô¦‚
+;<ì
+çpþµYU{(Ù¹µî‚A öTwne<2ÿHÕnnûêÑ“ñ!¼ÿ\§i‡_<èˆ 1)R*Oij¿dŒÊE‘º·z±yr·ìkÞ9Hu½ОU”Ò… ÊTFõΤ8×yÕdÝn@8ªU®6 ZŸ|C¢Ô† ÕÅÕ‘,
+$­¶q¤ áÛÒ§@²çF•ä¬O/ Ï7 åi¨ÅH‘œu•V<„î%ªhnïÜc7ªBå&](`[d¯>è,£ÇXªœV+Ù]TÖl©Fá[‹êHK3zeí„àuˆC­®:=‹(5óS¥IÌƽCV%øiÑ;§*íÍ:ÉÏPíUÝ¡¨©¡tu‹Ã³Ì%ö½K±@9h?½Šü5
+Dk‚Þ8±ÖA?œåõ–ÀóÄùÿ–‚èý WCàn[ž“M%¼:MpÇüzƒ)°¼Ó£Èf;•…$«ì‹ó up
+8U‘jtKcÚ. êxl׬?»LžîB›á› AWÖ,@±Í‡\
+¼¬ˆ}×¹ñ*Ù»­ÌØEóÉ_Ç;,Aø}l—êi7¤Tcå†ùb¬¿¾ã¾Ÿur/Í è¾ËÉ‘é8¼6‰“&]Ÿ˜fCµ³¸@<.ÅDn4é‡>Gv)J…l,‘ô³6|B ½aãPRˆŸs§”–&Å]z}³ ²WyΚJzÉ&“y­D¼”Á8Beßõ$øà¿–¾=ñº=þM\Ä™¢djðoƒ 2%#“`b61ìÆ e©âï0/'‚ʤ‘`#<aÕ•›PXÒù[›çï tTf¦áÇÖ«,à)¥Ë¤znaj®ˆ:yD¼[îíÁ«Æ΂@HsÍ¿)J'vÁ¢*[þþBÁdªÌHYž¼…Ö
+AĶéi‰N>]l=ŒÌ7ˆ¶äÁT–‚âúƒMùØ!—ud^…Nˆgv 3Æw #1ñYm;SšŒ‘
+Ûr"Nd,µZÍà[ø‰ý¨ã÷jüà^ÕÛ:wn¤7Áé”wÒÁ‘cÜ
+#â[˜H›c¯\ÕLI¤ˆ:MîNøúÌá£åJ}AÍyKÎ[£îþÒ]3$%e˜pKFíPBÒ³TC陈~A7‡‡1$†Ö¶.ßÇ|>ßlö ŠFqÁ(çœs!¥šÕ&?ò”³czÉ¿òß“t¤Pv%aó=Ù €ÚÔ×a!4¦Ï^ñ8å…(—&’TyESw·fy˜†æš`‹ìqÈןó 3“pI¡@q\‡æ¥#x1C/׈™]`šÉãT 9ò1caujÇtãyžÌ~0Úÿ•2Ov㪬¶îUsÖp¾[¯PÿUíx@”®“ÿ£ë‘y¾ô‘sê›e*ž—§C·„ÓVµcå8ºM- Hj¦üýÈŒ DrOÜ;!ά<°¶‹8È.¥µ;9¸§ 1eq?ÿw âµ%h@³â'ÈŽæßA¶Ó¹$< u GïZâzmÀÓnǼ(¹µ^@K]„ÈHÄÈTƒqÝ÷û½0ª«}¼ñ䘀t]àèúdêdâê{Òð9ØÁ2ÔX¬œb–¾fÔ«d)&Ýr^'‡½HW!@]£Ìÿë|"†ˆæLK“ê!¦ÿø8¦K†í `ÓÕ—j| ”“¶Øæ »Þð"ï{vÊÑç±%(‘irÏXbd‚0µ )´6zCÜŒ~ù—9zÈÍêRC>bºŠ¢Š9n™gì¾ÙíM)^">ªÀo2þ»ÁšóÍD}®ñ¶JjøÆ<h»œˆ ƒT¢jR dN
+çŽþª” ТìÂzù©IkÑ"7Æ}¥rn“B¨2¢µ. 2GÃÓûUI:„ä c_R\¢-ô=Íså7ŠVI.ô.¡»Å 0búæä«y†R
+»†þÊL„U"É+üƒ‹ÚK‘ëÈ’0–64F~ÁÜãK">"⶘W&£ËmòÉ((,Ëäl^`ŽŠ¢ßåï’$dÚÒ¦þpfѺљë‰1¼’eîôgq]úÀ¤s_Qô8ˆ6ûK„Ž!ˆ‘ö¾Íà¡"%þ/+Û½…uýPBnÙ!-Ø"D‘OŽƒŒ$§ŠÉç0'U}YQ€œZäƒáœ4m• Í4ÖǸésDÐp2Ê;þȧ¢^Û;¾y-ïâXÇh·½ð$¨1 ÕŽ1îæ ’’d§aá Z<œ±EiC¯£[…ZŒ7r1:%ìK|¢UÞM
+(ç´J«qlõ°\‰' "•èQ‚ÂNõ³ÈNø<‚cÝ{ÑÝÿtÆ<¤¸¸¶Ï‹n‰H_ƒ)ÙÑÄàÇcÍåFðVhò¡mÙ¶·—Ø¡%‡0’:§ôÁ_Äaü”îEn¡¡LJޘ™y‚I¹ŠºåÆ9ûUÜvy³úB³(Äp º}e([h@ ÅÀ^€Œ˜°Bã¨EÞ=ˆ«±pÃj¡¥¤3XDiÊE˜$Å2äÙëRË+b}8»²Ñ>R³z8•ëPh©ØÀ¢†@„ay1©÷"„²®jÂçCÊsŠî(Ìz´†IËgٚˤ¢Œ.nh5–ÑA*-„å ¹"—àbŒQ
+],ðÂT÷c©ç 9IJ¿–&ƒ@Ìd»£LÈ눽Ý(媤¤¡ïs €Š^£¬k=¯+“í2êBYzt_½ü’á³e-ÇÞÏË_jÖzZcÛv{È¿^‰ÊÖ@
+ûŒ`žvN…²yU;î½1ý®”‰¨> ó­d}(Øý›XÝsÀMæ6Àv†Àl•PðêÉJð*1ŽWZ
+Açœ7D±F¼”ÿc¢«}14Át+_(&ˆB«0û\%à¬ÃBX¹4\ªÈ«}ìST~ûínŒ4ZÌ;¿ŠFšH½Ìf´o C`BÛÆ!¶Œ€#:=¬þÒ
+³ÚØ4ïƒò}u#˜“5Jä”=Jh®R» ²¢©àI¡>…z+ºáœK.Ù=aÖ§õÒ~Â]âHu (­’„!%©•ÍˆåÅs¸ªN¦<Ni tYÃ1[ºs‹ ,¬d8œbƒ°UFý8Le=¸M¾ÏJ*±Dóô|Äòo‡¹ž^"vÃ]S>â͇&„Òó\ŸÂ7ù/öÒ5~êr£B™¥dß@Ú´XhùˆžãÃ9×™ßnsÇŽóª;oݹ#ùÖc¯ämV>YmX° ã/&Æ j(u)Ë弊ô4ôCW©À“wažqì È
+q7d%Ò÷¤€Ž~WyFI9áÜ\—,0$¬µÝDF‰€Ë
+ÐDÕ.ÙšóÄR1–ß”†á|(ŠÐ§ƒUI,FL‹6ð¾<œÿ‚™}Ìd’±Có <vG( %¢1¯/áU岓LÿžT€W±U˜c{§è2ù¯‡"ä(•i«}Œ]¯5;VO.(¼iöf4Ç»i-ãÃõ¦ÃaÕFA#°[  Bn[…Ý
+"9â1HÉóªjÖ‡ßè¼2{ÓaË»We*XQ,#—,Áõªš-†šþò®C*ÏfU3ŠLñÌÆ!L³ªQgÙÜožYÕ¾d¼Fà7ÑYϬ:+u7«¿/§™ÕRp;L !^Á¢&7Ë0C“fVÐM»9ÅK(6W}ÓH$Zs6iÈ;ì i"%H~õë„‘KDC
+UJ ¸L­z:d›:ã[:“Ö¢!DÞŒ?{&…6SËUj Øà$'ÚËx )>†–µa_щEŽ6‡d˜÷:Ehªuè:Þõ ««Œidýq¹‹ï°ÔJ;ø¾0öm4ÛТäþåõ¡*"èÝ <ÆôÓm[Á²úØ¢ƒªñ\LE6‹M¹ YíéÒ»ŠÖºÓÝ.ªkcà2º<l)A¯Š$xIÞ* ’—ÁeûA¡?èÍ0¹-ÒM Kç×ÓÅ­È-ëÝ÷I¤•JT‚¿ó;e ±s‘²Ïè¨^VŽåŠ,('í–ß!§ýüãœaÏÌd‡vÐ1²ÂÿºîŸwÚï˜ !ø›u-r Š
+[Áþá·=ˆzŸhc›¸¶&mt¿ƒ
+/‹ËA.–‡ï°/Z7¸·§‡Û(¾%m–öáU˜b|ž™¸9Üâ(0pxïàè–؃œZµOº€˜oÈs)P×ür.Ã\tAfÖ{“.Æ ½e1öI×Ú0qÒF$PØôò*ÈuC¸§Û© duíøí;÷¹¹Ýæ>Ϋîs¬í‡vØsXc¾¼m Äâ¯}ÔäB.­ú<–Bóbéô$àÛOmȦ†ê‚º©¿sÚ4~¿ÑbŒqFj`ØmóO…Ž&*°.N&Ñ?}b5Û&Ö$Οeõ K‰»£FØ4{z ¤s·$;Âøºž«´"³GD­ØÜï`òlàý\]„àÊ*¤}aw@N3dœyõÀóÏò.æ®ëæ,ë }¾‰hç£ígYϲè-êgøôäË: ¶/ÂUÑÑu·g=R¦Ü1T¾®«ç¹ã+e ¿¯04ƒŸŒì ;Pyv• çì »æ
+ƒ&j*?Åù¯°ƒ€Æ#ò<|è »3éwaw@NÇù4Þ“Aüîƒßs@!dü"ü »mÐõ¸ èë]›,÷I“\˜èdÈKÌ;4ÈØ&#EQFÌb$ Äø¯’ö¯pH#Ê• ÂñÈ+Àw2-…`€D$IÈ?v”< ƒ-/é©°DÐÇ™ßnŸ!‹ñ
+Jý°â‡—ׇ›nÝûéèsÊ2’Ôc÷;lDÄÊâÚ¶ö#Q™F,kSÊVñ ûÖ
+s4Ńåá;¡A°m,ÇQgGÍlÉ£C¸pàÅQb¸äÞ+7G­1Æ@áX’ƒ
+ÎŽZ6^€LsöµrZ^ñ “ÅÆ'„RßÝRï¯ *«_d¦°¬A+N/÷ÆÓ>F®
+Év9›,iRÌH!êÁ¹Ï´¬üCJ.›È8pc``aäMQ¶] 'œh<*†õå°AY‘$99 lƨ»gÕ–›ãI•©$‹ñ×4÷7$†ÌrËúê磔†"o”Æýmïfõ%Š ÉèË@­0X;&©: AägýÈmm)hÝÒ µˆIÔMR7–Ë |lr"€ðS« “W-´Ãšh ÊÐTI^žìÆ…qÆd쓺lÇÒÎø
+Bw±ÍÔ­í[ h댗=r]·„W =0VÀÂÿOèRÊÔ+P9£Bïß_
+òiàÂIRñ½ÂywÈ‘»“Ô©€ï‡û’
+#w¸Çq [ ÄlÏdîDL ­!ì~A‹h6‡ænö”`‚H—¸>›è0%œö˜_3lÛ°!E[@!Ï÷¢&”¦8ó>ê
+*Úã3ËC”¶¾SÌüÕ~ÊGc"! }³Az¢ü(Òö ¹cøùÊ×LðMjÇ
+[+koÆ0¦9­N)ÐAâN Þ8Ò©Œ»Æ†Úñ߸ßvÊħ æÃÇ`Û0ü‰-‰+üô1Ç£ÅÉdÄ¥¦|uÂõžö„Š‘Ʊ<ÏùCW”À¸í=J§•H(gê›Äøif
+G•N€lÌ„oƒ—KàØ|ü^RX^’"%d9G²HŒOa2¸ yò"ËDˆ‡gûl9žY y5JF…‰Ÿu¸¸Ï¥hdÈ3/2«œÜÈIÁOÈ,k‘yéÐ…P´ Ñ.k%ñ†¡BMúòE˜Ï'˜À1ó¬Ê¸™žÌÞ'Lؾ°mII—à¢T@+¾
+#?F«´â6ÍÑFì>Ö¾/ó€5–ûZKf0?Z<ü½]\fØñÈKX/„ò¾ŠV/CÙÅe’·øA8Ì#_%a,á_©–0WFvM{ÖàVRó‰ù‡Â CWª"^t¿ST9ÄyÎç(¼<âÒqäRn¹‰—á…a”òÜG Ïb`Æúpb s  sû74C!ˆUU×mÈ[ƒ2Ðþ²5Bf¶R*¦¹n¸‚ðA0&G„Iý|‚‘ðháâP%èhjàÃaÞKŠ{Üÿc ¢ƒÊcü÷raÍÐ'‘Ò®ãöêç+Ë÷ÃòeÄLb#uçv" ·fê˜"è—ð’íÂw˺E#IN £­[þ=0¯›†
+1Qû ‡l
+È z,y2Éôœ +‹ÿ+òí;(`•exd,ÙLa±âÎ.øŠ^$¡ùù
+¿"TF»8KWUV_ùtBL8WluA ±DDZŒ °žãæïDô97“©YBÖãvòjãgR—¥$IbuÈ´-/gE)ì;ÜÛ*›­Í[”ÈS¥Øߕ̇¯=û;DGu¼:û —ß—úõ;ˆ3(ä>öedšJJ‡!àÊÐÒ~·ŽD£«¹p@k¢Ñç@=ÄÃûYxJ<|fU‘'ì¨Úõ*üb^$Ø& á$ÆÔuèŽÿ†ªóÙÈ*qbг¶zç~‡.°„ Î?•¨¨Ñh(Ö­fbfi'åuñËô¨kíï“ø <:¿„†ï †¤sÃÁÏoµÈ|3‘øhy‘‚»Æ9ÃäÝÌ?òøㄨ8ßA6IB;Ï÷,L™‚D Q.Hßc÷Ìl©ˆjV‘g~PO
+Phê‘ ‘ÉálŽ´›Ê7pÝ ¦Öùº:þ”1™ÕìñÚPä˜.cSÛª;º@¼ytõ!ý€rVL…R«Ÿ¡ ‡ñ3Åw½ e,ä xÑa˳, ¿–ñðeQ>7,lŒg/ãÚØÔ<LÅß”§J”J¶>ù2ÏÂ(‹Â.ÏK  Ý©–"Ù0Ð}Â^]üÍÃV´)Qའ2²IUùК1‘:€‡ÕÅ“q§÷upï©ó™+1´™ ôNôáŒ'e6L‘_okàïDMrISÞ#jÅ9l'†àªþ‘Hø‰ïà›øÈ™÷I-Má÷¿Ä¿þùöýßo,%¼+yùJh‰€~A„Ã1Œ>(°CÙ¦²Ä7ƒ˜:’Û‚0¯ å€ã ‚4R69¥YD(㽇e¶Ÿv\ÇNcæØß!°%ºÉêDò¡#Sçædå¢ðX›LD3Ä bLÅ'ßë ©TGç´”½¯ôw ÿæIÖþûUÄh¬ ×,>yRWXÁ,ñã8š[ ¸jÎ…\­¸ö ÚGÝ@ÌÚhT‘ÙG]nÃâ@éÐÄ„WñÞ„¬b"Ø•E at­ *}“˜I˜ò
+¬øñ}
+J%º}º@V£®ív¾s%s›+ùœWÝI|©7—úþq ~0‚L5“ªM<”ì>Lü(K1jsw‘†Ü1COçã<4ÂH¬V:ïâG³u5ÙC #‘c“ÝÙÞÓ,EÒkqKO/:ŠB–9d…úñ]Ò
+>K·éiiX0,œ"Á‡U1‹û´£ò&2X°J³î¹ (æRdàš•š;!˜„-°g‡¤£Ìªh”I°²|ô]fAÚ”­aóuÛY‘ÑÁXHrˆ{FÂÜ4¶xg+u”È"*ØÒaM•jð|ê ƒÛ´ïp ö ¾|ÅÉ)ƒ‹Ô«eˆ±AÐìÈç@tT°B3uå·ûgvF`;²Û„ÿ¡9³„WBee÷}I%"¬á4:ßAÚ.Aö&<·F©ÚL²ÎtÍ‘°Õ¼0± !­kÞt.¾S&YRjÝ$ÀÛˆ™}ASªŠ²ÚöQˆ6eçg"ÝêD6­&Q•ÊX>Kecµï’ Ó
+X!%ü0H‘ 1Ëu.Q¥ìmÈp+1ü°£ _Š,ðZÇ\Þp-*¿êÃè ìáåyλIëpÙèó• “éåÊRÿ ç;HÄØ,ÿ0–Ñu0Î¥‚yŸ*×’M…^1™h4m‹(TÈ9î%@ÖE3ÔaÍ盓õƒíÔ@B&
+‡SêqÖÒ
+]8bÉ`æ·_²â&«¯´¾«Ì#ki¨ã—_¥aY§åõô%aöö}tHŶÀ
+– ‰ÎËß¼ºÏ sÜK GYð§ë³¦3ð
+Ò@ÚìPH
+C*¢˜ €¹: „Ï¿Q^µ|•àvÜôùÊÖÕ1h—‹ ^9cG¬@Ó7›P^mÅ cÄë@\%&vÁñÖˆƒRÃÄfäM¢™lʘöwX<,\
+L°«ÌßØEYZ+©./fÁ>²ŠŒËVŠ—t¼ÌÌ}KJ~92ZÒÊòFn/¾ƒÛçBŠNã¼;‹'1 É.Ç*R¸9·‘Õ-\º£0œ$ñ›ç;¥Èòcvà7³Ò"Ø•” %ëŠÖÁ˜k—ä–È6¨M?%Pv½Mópd<‹‚¡—w”‰¬ü™#q‰‹ž^çëEÕ>ç·)Å[òZHJs¼†‚hökŠ´Ó¸Tt][ÝçŸáþ]¤E*†‹jä!äFÐË}H=×d ƒÔ­hä0v~RC˜;p¬Kf­©
+]”0Cš©|wÙ¡‡FœVïi_†£;§µíЕu´‚‘âÃ9#møsåÒý|Q¤h€)@mN»)¢9KÖ²^@b”8ùgIcóûЫá‡~ž^åäYÖè^ÀN€Ædÿ;Aæ‚™gÃi´w‡)fñX]©„ÈÇÀÓ<+ZD[ᨾ¹"i:èàëHx&Êc££wYH
+6{9ÏÙJÄFaWGÑ 0CtˬCˆZ%o#o”Jr=+F
+_x³Iä’tF ãéÜ‹_0F>G}DO†¥ƒ"V™Ì^ ØŽ4B}€öª!`û»R#¦ŠK1`;MäùdÜÔxØNî!ãNä!*Q" ßùÞ¯®Íß$É_¨ó ¸>‹$’Â`ôÅn Ö/ÜP ‘ãð~ReÔ_ÝîÀ• „Hø¬åø WšÒ¯4êœ!̘r…
+÷[±ÎðôèËvxBz‘|
+Þ|úgšˆÃd»ûÑ]$+% ™5Yu•¸î°‡ÇªWžÁ‘¡7¯‚¢
+è‡u 2½%ÚÔô^ Î`¼ ½Xx^Þ¡zЈ8Ôâ–WÕ]ÀKD?á4ï4fx—©PÆù>¾3&0ÍC‡HUÇ3Âæ%*±âáí\˜DÙî!õ=Ga€ø yôq…1#ë;ã]I‹ÃâW**’zÂdjXBØk®8êÍcaѧlùÁ$Ê™üßÚ[te(‹ô€2±ö«‡OG¸«,;A
+<O¿·PÂMÌ1Ðy‹qÜ` Oá0€)Í÷?nm HBáôµs#“&ÆÆhQÊkØšóã9R†RÜ ˆ"L–Ì;.£ˆq ¬]9ÇÜ÷Åü&Ð|æò÷Ü;{gÝQ‹ûŸå¼oð­h/'­#Ä,èä: ¤ÐCê~&A†§Ú:h U†2Ǭ¤q[†&yg³«Á@ƨƒõ.»‹g«&ÒËÅ¿3XñI Eïl8yuåN¾ÎòV²¢{”ÁÖrø¥E^lÖq}¢ æ¯Èf¯˜Ð#qqæ™ÎepóÚNô°å  ,¨f=E$°.Ç.rß4
+GdJJ’Ánö‹ÿºØÁ˜ùºÌÇdnóè}
+à}!œ?\_!!8² …-J·¿wŽ–uñû! Çp츻/â§Ì·Ôq¾„Ú#zIÖ0Šh(óV¤©ŒP ×n8€Gœ£é%@ŽI¤në¨D&-/Œã
+/s Jhò(ëðÅœÕ$IþëÇ?QÑÓð˜fhM†˜Ñ×o=9#,ê@…  ¿Šœ*ÁšV€¶jº"''M>’Ü`PÂF`_¡ÂúŠ3*ÁÀ:Íøw¶ fÁ®w÷ ÄŒR¼„ÿQˆæ¬-(ùåÈXüarŸËzøÂÞ6€CV`{Ïm²¬ÌÈ e÷©r‘ÌrÞmˆ–?ÚíÕ0.x­EÇ®æà'S[†t ÿ˜…Œxfºè©võr!ky mâ\†wJðn ŸÄÊåáÈxCG¾™pÑ.³oÝvðã;‹*¿œßþýgdVŸág«d‹Ý)è '‡ìñÿ¶gŠ¾2
+b’ `D A1inØýãŽè]æ·&VÚ¼LŒ·â⻄n
+OÁ….gò,yÂB°z™Ó¡<Á/V1–ÜÕ`šp¢1Ÿ%8‡)c_fP¢ñ§wyˆÖkqÈ€†?µ­]¹”æ‹\·í¡¢Â°6ûPwû|^]&m^ˆŠXZ¨žä
+
+dËg¢ÙvÃmªcÊ
+›è¿€þ¾2–†=&”añ¦(ærÝ+èý;ßädõ¯ÿþøë¼S.Y/c,1ßûG¨šÃô6šÿÿóÃ2q{AVAÀGÕÕÄ\-—F/½€Òâ0 wp;W[ÖKùf:¹vø&HΖnS~VÍA_¯û&(aþ‰SžiƒŒÈ4Ó€Œd§¿ z-ÁûwêtœOFÓ
+¿¦ÈC—vˆ„_mÒ¹ZvIA3‰Ã $§0Õ"ÉÞ¢ÅãàÅÚ†hSøǯ!žÂd6ÅÿÙW%EHÈ}8 ,7ŒU°½´ù„W1%êþ{“–Ê0bcCø<ã6H_›º!³Ž•¤æcî«DRzI­+ë „Ci ËW %‹†ÖÕRlŽ}d,»CH9z‡T)õ‚nJÜ —!NE9$ZcXx¸yC:V³¦B/–Cx%¼Â™Ÿ™ˆøèûW•]d‚év½?€ÐKªORÊ»Ÿ@YLŸã“a,D¼°&‘:µb4§­órôo!¦pÁÚ/Dˆb©È!=zŸ~x¼¾Çb·g4K´Á´<”†d»!»Eyò™89IDSù/&‡¶T©ÝÔˆ;HÒ°”ç(Ç2’‚ÃÅD6\VÑ瘨$ ^–‡ @iäÑâ*"ž"¨Ú1Dø­„;t–¡Íñ°2X½_aènPäj›9Â<bK3"_SRËÐ^ºŽAQÀ›™ÒŠ-íñyNÜ„âÍ# ˆ%_…GH9º)­ y¼Ð1Ѐy‘e‚IP9(n+1•4‹á‡mû‘
+›°Å£š,ñ˜UJ7á®ÙúÏð;ˆ)dšx$þdªýQ&KUºCre~ £^‚­çœÎ`Ù† iÎ’æ–VÍÂ0Ñ•rõì ÃD0>‰­}ŽŠƒÙ]¸¼é¦TÈgS‰ñ
+W±£¬'[ƒ/dö«jÛ'ã/RFã”D¹ÖyÕbá,J{˜ÅmèËî£ K•‚n§üN«–°P f×+¡¬S(OTŠSm"8 7˜Á÷>u‹Üçt¹å•ØÏKÃÚ³Tl6ôÙÃa…—Å~6™$v K}h›ZÓæ¤ù«Ñi5škxJu¥A~9¶Jq㸠6–¸ûz&jË«‰<ù+·Ü Ca÷SàpQ$J%Ô†˜Û9ÚY’æ#×i`,£ÀüdŠ#Õ²Kb»Xƒæ¶Î«Ç
+.U°Å9ôœøY—ܸC˜åÉA¿Ý)›?ô:/­kôÒ¤®™Ýl%®4­ðêV®YÞ˜ \“[Ш(uÈ¡ÉÂîðûKÎ!2jI˜±qޤȔø"®é¤j‹?|¡VßÈ×JØ4Y"…æü
+>â¤!É»bèA¸2Ïß¾))äÕ¥_>/ ÷‹€ÄÈÌZ®"<Þ #$ªhÁ 4†áØÁ% CŸX”PÚ™b„
+:E¯)*2ØD¿j± s¯é ÔAZ|& S`n PN†m2]9øœýâó‘F…ÐX¦”e)ÉŽ.0“iJ“‡¹û@™u^më@°]”3S];5i$+Úœ‚e·™*K¿sÜ[Æðo(AúðÓ·8%¹.¢£ Xæiþ¨©á—7SÛ»©t44
+–/`ÅÏÄpÑ®‡sÐl¤«òÅ!/$Ô>'ô"|…Ê—¦uÄÇàn¨x·VK›ö ãl(À©M[Öy´ë;“”Ð2¶>®âKxc5­ð•^ÈÍÛÂ|ÖšRLò^¾
+Â!âÅ<}N_ ;†³S¨³ô įBãPÓz®‡sZíÖ”…Ž¯A•!Ù¯qÓ#ÄÀ}ÈïIůjZ†& ]>¼Ýïj.ù‰aÊɸ,°!r²GR5´2ÇIê`H *¾1®bô 4ètœžK>åùY¿
+sŠ` mÄU64MmÝ!âÄF1Ú±øN™r^çªdÌž†wÆ9øŠÂ]„ÍêÕk†ãu®¢tƒ 9zŒúWä ³æ½+[Ý@/û‰qØN ÈA;º÷ e.2g ï¼yûŠaƒåáèØ~×W].Xô6 _fð
+"vA‡e¹ñ+„-£ *äÈÙ•å'MåÓU0Co¨ rc~¾u¥³³|Ì-ž¥­¯Xü…í´qŒÿïÙ ®ú
+ªpC£DsŒ§sP„,• ¸Cꦓ¡
+!0ÀåÑO“õëðmò›8‘e;̱˜¢
+Û0×¹‰ƒ³îP\CV,“ÙÚ s1“J[O“FËrn7Ö%—}ö¼ìÃYŒB³…uŠ"ádâ6Úù"ç÷1\kQ:Úàßòêt>#tÑÀKϺÓç8ßûù²4OÊÀH×ó)"
+¤gpô†ÔFéù LÌx âgP_üÇ9§k¡ðÍ'‚ø—UÍ4y¤e èq·žâF ™Zë|˜P@
+Nšž&tà·åÞŒ¬‡Ø»v˜ÀÐv«€°]•Õ÷ïA•"Ä+™pf†`ÖáuÉWÆË© ×$ÍWÔ˜¶âyñ$¦ð)ˆÌ
+ú?Ä®?
+:ž–Æ6¿©’ŒX”®:(èÝL> .Ïsª6ƒ£J5˜
+¨·–Põip?ôâæ,IA³#ÿ˶\pFú Ýç_C!OhÓsF "Ûž”Vž*éièŸÍŠnú2Ð
+z¼Ò½ ¡¾–ÉO6Ê‘LÛ$œŸúP§Á¸oèÅÿýPÄZ°z ¤ææŽà^Ä_ø<ºÜ-ÎÈR1lBî”Až *Ôai•¶h ³Û®()ç@ä[Õ BÈ­¯}{\~œ””på‹)ùA0X˜yz…òL—QÂohŸl„—
+QÁ›J‚dЧØ!GèVHyøöæ‘4覴¹š0ãÛe>ñ°-ßGùà²À!Ä-<’ÓÝ$©5|ènM«Ú°l‹ÑÙ5~ƒ?Iñi–0$ÒhØÏäPp†&cµÑ:Ã,ÛŽW´¢kÓ¤³öFP&•a
+þŸ%†‡Ö$0W¼ˆ»Ù 0Éw.eß±ü¥¹¬Xq– ®@ôèÅë—r`Ÿdù4/¨¨r?;”õÉš†3K‚½$b5™ŠÍG±˜S¨HmÜ+ÎNè~Ê
+ž²Ð´óÄŸ0ž¥ú9 %°ñ2ÚÇœBÉ
+v¥" 釒uvC‰‰Ç×òpÎñÁ]‹è%à ¹À×9€Ùà(Æs²¢BΩ)ÁLIè‡#4¥Õþ”ÖÙx°ù÷ÍèÝÙÖ¸Ën5ÉRXà¢ã1@(¨Ý%†@òϨ¶?k v®uFe+؃·×ÕäXVr”wn
+M¼>××8q¬ûèÓâ 3Ö ŒÕõÉÒUÜ2Û_^)w /Ò§,
+q]Q§°”‡߇Ø/iˆH¥l²Lž©Âäbll­³DyS¤ºÇ¡d]…ÌgŽ‘K;©D¾‰uQ
+I»Çòi ÃÜ–UL¥iL´C¨ZTÚÕpðrtì`U„ñýreÄú#iÌõ˜˜òd~\»í!G@?âOdsoŒGÉ t$Û§¼¹íåÃ0ûí¸ƒsl8,T–’q‘Ù`iüUhFž5öwc=ùyF÷öç@.ŠŽ¦òàFõné¤qn[ïÎC‰EŠÐw‰w¡+¡Üæ±Å`ÜXšº_N·%¶pi[ý#­ðwnJqÖjÚHµ·Êù¦ò°È+žUŽ²xÎÝÛQÂÖC ´ÈsWC_ñ_,^?Tüúøçƒq|IÄY»Ž‰ÞÏhp gïÿ=µ™o­â‰
+,øýPD@1 qXýT KcÄÙ.À»}Óè*TT ÏYB* ¨<¢Vï^ò÷¼ ¦ç¢€˜oÛÚX3¼FºÌS˜-®ŸÌ1j;¤•$ÜLÖät%ë&Yµ¨üSy8#ÃÁ2};ääDŸðº
+ð&÷äaõø½§’Û»Eïý;•\¦p*¹MSE] ‘c=£‚d‡^&XØJÂU)Šç @W@H+fÌ"ÔÑš4?z"d¿i¼6²-Jå‘{&Q75áѹª¼ÒŸJþ$J_tây« v(ZãlòÌDBiïL Õ"#=†Í¦øaèª3ï2d†Á˜R»¸=`ÈyÞ
+H‰Œ—Kr„7ƒO;øÓ%Q)­³Í-R5+çþÛù ‡cw«kœEœØøõ"€uxíÅ>þÓR{Ôž#‡›µ­Ç£õ2ê„Ymµ÷QJ¿#Š×lÍR®Ö?þüã‚©Ôkä‘zËÕ?þÓÙ:ÕˆdÅJù5¨?Òˆ‘-×’£~|¾Y”^*‡²ò±ÕÒ°T›ÇBð}ýc%dpÍZ£Ö¤y·ž»Eøøø{îÔ’%wã/ÉÈGd¯ª¶µNK,ÐS n¿ 1Ú¨zA3{éžcx¡ÑæVñpÞÈbqýõÇåÇÉ"§1ÖÕyúV³sÕÎ;}üsÃø#<å^Zæ&m>tyô\·ô:úø5èi·Ï_œhž;ê#G¯¹x‰Rö~©—àÓZ=ºȆ§ä©u^oq­çÌ3ja#à•GižÄ3•O/{™/E§æ—±)ÍóSÙ§«^ŒÚ êhõ°:ø¦Ñ”eÚ#•n\gôž}Cò¹°lna~ÔÕù䡵çi:dÝL|]Å#UVaŸõ2 š{š—š7âã­ý{é]ºvÍ‹GMa£Ÿ{ÃÞ`í–3ëðäyX~Axjk£èW>!¹Ïè· hÑr
+¾²VÄ©”¯|œ¼Îuô64[¦qö‘‡ós`dB
+oOƒÂ…œ%²õ”ì¡×NÅUêNÇÕº068 äŠub•‰BpÎ7!\}cóöá:?l¯¼ˆ$ìzé?½±ôª$óì× d¼_½Â¶Ï7 
+rx‹^Óì›@¯ò®»K}·,՟װ·[ÑŽ‰Uyö^‡œ€ÁàêÛ’F™VTöi0ôlHvz¬Ä¡Žüºä³ÕèE®ïºòò=¥ÜoõZ‰'=äF”±hFå$àŠ³1O’EB8v‹=1T.'í’%]Á$àþ„ðò}/\õxùÁhéØ>] æÍ(µ‚j†²æ¬Ä© vCÇÉÄCY
+vº|Ú`¸1»¶¬9"HäÞ©@cºæ¶/¥ôå²
+N5—ÿ·äSœœ\s-8R ô2ú
+WñСM$·¼7âä‹lD ,Œs>ÆÒ_¬óæÜQÆ!‡ÜR•‹Ñ;öÂdƒ¿$œËÎNO˜gºFZÈß4&…ÏåNOš»¶BoûÂB_PhO=»AHCòêF/ìh:˜Çàž°ïÍlÃÿa:ñ®?Uo„""žGÓ- R^”èX¤§]Uö±/í½­]j_^§RäÙ4°˜)Ц›ÝÆHAšž½)öžÈø3*¿¶Ôkàβé¾~ØŸ«ä‡†\4$2Q¡!§5xB
+=òî~ÆÞ +3\¯ào#"á '^¨ãÐÒŽšø\FÚ†7+Úì²J‘ýÑ ˜n!¢G=jL-„\´è܉˜ÄµˆsœP·IG‘Ža‚q€I)¸ë®7<ËêÔ6MÖ`5JJç%ã„0øëJ E ó”H}ç*ªuãF>G ðSV´n‚y9ö@¹Û„(y178O. Ä(ªÑ±7,Œ¯9µ¡ˆ”EØ>M"`ÀÊ“;U,E\Ë3gMðÞð•/4{fM£®B`ÉL·¬ÛWê¤ù—Xx˜Ãºœ¨2蜑EIËi¾rz±ú`Vƒì'/Øeiˆä‚0XÀ“έR¿@V7½†¦0Œ/Þ¬3çWªÌïO
+æYB3i]¾@‚ç{¦Æ¯Ñ`IŒ©ï}2]ÙjÞrÕ¡rk*ªaìÚ½¤3]ªÉ«_!dæÑ‘‰Á¡÷V¯ Þœ÷—ºØr2êH+¦Ì¼D¿p'b—ÆŠríð'ÈÚŠ ã‘Ñî¼—u¨%ÜÇ\èó3¨™âfU”mq•>eŸy ëÈ›…~Èò[mû¦k]ôÛròLc“K(o@à!?ÌVOyäÅÒ>Ûž¡nü„ËÄù ìiÌ©uµÃkci3ºØqȺÚ 5²cõsõ¤³1G=ÆT:·q òÀ¹:Gƒì¡¨¸•@1Ýa2,Û¢y‰4Eræ‰+ÃÏ>­t¥D‡$øµäÍex®8s‡·2³õÈðæwXHÓçîp¢©–EiOêÈ•êµ
+D ¢6–çöF8вª
+ù1ë] ¯.|é…
+“aàkjÁGÄícÔ°3
+ôIÛ?÷RñL²”°>¿øy¹øôóo§2Ü /唑ÑýÊ
+!xÇ/Ûá–‰Wd—šß@˜B:îà Æ/ŒžéOÌM')¢¼XjHŠÖ:$jh;I‘·Š»ç4¯ï:¹©%û ÉÞ´ÊÉ|Ið³,ó½Ì•KL)OZþåzVš%œRù¥ì¸=*“”Èvɇbgd©·ñƒ^‚Œ™7ùÛº {r´À,`Ñø2Tþ½ýõŒ—I¶\E DWà=üp²oÆfÈ:™ýO¹!)üª,‡ ¶U/;)âÆÂ`ñp ùõ+m$» º×È8Dt[Fßžôú©Ä \´RKý‡ yÛýaÜgÄ;Æ%C½Q½è£+BÍ@ŠlSÄfKÁ|ºÎ#‡ˆeg\1Õ´cá.)5¤‘8Khª¼D‘“6O£<bü=7Q¤'©p¬|œ‘¿¶§®ì;…ßÓü¬ô¸Þ·r-ÛX„;ĸ­Eß‹^læŽKo^ôçüõ;¥•AÁÀ…ÙqÚ2ý¼•QÄh…îe,Ĺ$Ã(’Õ6µÔ´5‹äˆóÀF½õ÷UhåÏ2ö¨àÙZEÊVR¡ûÆüƒM§Dˆ¡ÏFåÔàà m¦ÇÙ±,‹PX™û W¶áî¥]{IÍèy—< _)«m«úeÇ‘&Ùl)±w^ \ ‚¨ ˆÐybÿßrPŒ×+ìF7s§:r–RÉ+p©WtÒkšbŒá eù2£„½¶£ˆÔXÄZë|'¯¡d¬Ã¬{¥R£È\*|þ•n!'—„ýA5€±¥K´’*À>ñ¯h‰ªû‘ ÊW
+zÄkpRÑšÌL
+7ܲ§=†±DcyÄŸ ÄÊ,î½
+_¨)æ k¢{/Ÿaa®šÞŸå”¨ë:;óþºµ7%YýÄúµœ3Ñ*ôª%üœÃœÄ)  ‘ !ÇЉ¤ø©¯cm <s—ë’K}vžkBF:¯3¶ˆ¯y%C_±è]E7l‰{Ž9&¯´t
+3}ÃÈ‚ÇЮ(é< ](l­^Â7½@/GÐ+…®{œ3q¿ràR댞·1Fè³S ÏÀ@3M9íR«¹ðôî/Å'qi¨C¸ì¹¼†ÀpÎÒ½C‡%+ ¡é¨öF•'aÙê`Kò¤3š2¶ïµ < _ø{TÔÚå8Èþ#Ø/rLÆݼ™€j¬>&‚®ò¿S‚éÎ
+p©7!&°'bE¸øyOŠˆ L¡8«Yz½)^
+‚‚:õÇÎÐ8ôõ"¯á×Ø2Ø]’·V‡÷/Åf+ßòñ!ìƒ]çˆBχ(c3‹f[°/ÛȆ@ABÜîtmW^#¼`‘ÑYþªHR‹ÓÌ/’DçÐæT®áúò¡éàq6¯E<ÿÐAZumg3z_pëlæß¡É<ó üsDß\rÞ‰¬–uŒñá;¬ˆŸ¡…Z—͈]°”¢ó<_…+„5ÎÉåL&ê—ƒ'jú.m”GŸ#—y4*!dH[£m0/>Ÿ)UùR/\¡$¸»f5ù‘2~K›ÕÕ÷ÁùŒ’Lð+Ò4
+\Ä0ÐvŸe
+¢îMÎ@?iqGsÒ2ô \½‚` ÙîïwzýJýÍb7Ž6ÇœáP¦¡;taÔB4tÕ9âò8›xD_±qµ¬$b,q¤Õ”‘p€ßÙ¦][C¶.]~/ù&÷n¯EÓ} u¢‘WxÂ{/Ôø <<ïû¡8a×
+qùZ‘ô*4CÕ(r/±Ìaì eQE¦Jn? 
+_`¢6¯,_ Ÿ-EŒó•·DÐð(e>Ô“rº‰jof@MâÿãOmÝBŒ•( à‚ \ËTˆ?ÄR9Û†‘…„‰Ô`ßÐB7Sm:ÃfVéÔ|¾C å-¯Z­.,(½Óû¥Ä—‚Å$úô|ɪI]xJ¸¾q'V¢k"øÔsÃßôç[ VÝ1Ñ¡õM“¹ ³/EÜÓ€ŽØ ¿b#²± Ù%ÐB +ZàÇFË¥Ÿ§drS˜\rŽ]%>Ða{²€$ŒŽçkqÃd¬ÄhÒ gˈ2ÑŒ^Â$2Ðzƒ³Ô”éëìµ? ÿ$À£ž§#0k1\÷-§ÑNh'¼°<êǦ–— ÊÀ! ü\à¿KbÞZý%UË› ŽÐâŽA3Ý~Ü]–0:z _J|)X‡“’Êzª¾ÃT0«Œ,|~ì]º6Òṯ/QÊ—R<%®ð±c(kð,<»Yk<t½åÓ/1©šêsd¢ÄWxû!}áîK¨›¨«‘žîúVÄ;„f(Þë49øÍë5g@‚íѵÅÕàSlŸN?D5H¦c¾;Ê%N¥ªs§ÄP :)Hü?"?ò)¡a…¶<š¼æå†)b0yt¥š3 Ìܱqw<t&f:Z¿L•á#ÌìrûmðVDœ‰
+É;6¢`VüƒÛbý~ Sp†ô‚¼:7E£H *º2ŠØ §Ð} ûAOW>~˜Y«Y ˆ Š"»ßJ|©Lûçú?çõ3|ôžM4z;“…Ð!>¯ÏÝaƬÞóŠ˜ä&'QÄn8
+'[Šï 6 Lë½½ë ”¯VgÉɈù$Èø ù3óíK1ÏȉܮÅdšÐØá°ï@cÜúPö<Áá,4Z_Õ—b µ5ÄfÇR4ÎÖ̳çKUZ¿ÒdËéh¢Ì
+—϶êÙ]0,«€qt¦‘ I:¨~;x H¸óvGN—² E¶ {¤Rû*ËÝ—±f>ãèC#/ÑeÜ?¶ÎD;ø#­\£¨a<[à0C–Ù\%ÚáNûL äÃ%1•ü2A¸:ŽZ/áÆ—&i5É`ê- 3kæø*Ñ­pËÌ×Ù2]"yç·Ý-VšDÁ;æ{…/DOÔ5mS^.ÙrÜ8]÷ðV ÃääØjšÊûŸú–_U1»Ë>ý9²Pd’"näó*¯vOE6B­?ë(!PñŒ+õØi4ÀöH¹Ö}$¼”ƒ#¨k+;ñ.4ò‡"W©`ñu"¡÷Ûû¿¸ô¨º¾þâ£BJ>¨Ú¿ ‹Iùhæ¿oj<ºãuQ$ÉÒ1Ÿ¹K8îBl˜Êr*Q>k²Ì•ål.‚K­×(šÚ ‰îû* )@+Z§:0š½¯ aÜšúƒL}•ÐDM,å
+:e›'TÁU)£ì™‚• °ÌF0Kž
+ÝÕåÝ¿ŽüÑÔó¢HQw¹Y‡Yº” QÏ|Wò]›þ¼9ÕSQ¼' ‚rS¨ÎØ‘ÔÖ{ HA§(5NÎÎEFg¢b*Ç–äá‚Qè
+.Ú艫*˜ËH (.ãòa ÆèN•ïÚ6$ƵÒ÷©p hƒÜÊ9–±A䃥™¤y¢òww|gû&”
+I{+ĈÈÆìm˜¤º8$ä(Á‘5½øÜâÇs#t‰e²m<ár–@ý"<.¢pW•¾K´³´¥|„ÉÃ"¢t€ÌZ<‰— ÂU‹-Å ŠrèDΤGIzàRè+iÁ¦Iè2![–öVLÆç\ž^1ˆpbÛA¯Šèi7bЙ(ùÄ䉯ð²WÃ{)ú}ST\0ƒæ²,áõi7nÔæMIåTc²TÏ7.®ƒ ÞI–-ÇNDcLZ?Pâ*‘òÎ¥²¼Ÿ!)i ÕÞç¥BM…Ä£ÞÁSfì
+œç­³°³ñâ5 ›<rÑH˜Y|*·=UܽÍ[ÍÐßvÉZŠe4·€)|Vvwq„q—ð#Z
+é;!ø¯O8ý'H0qåˆ ‡
+´Cç«lSúÍGÍÍdOE?oŠ˜ÄÌv‰¦zÛ¡h]žòÒ»"3i)†–×{xDän°Í‹K­d¥XñðÇE‡íŒy3Y;Ç~Tôv§í>(2×ïœ]œþÏEêhš¿íCgדœâXâ²+¹á€ê/š¸]Õë•(šÒJ`¾\ëp3ÉŸÓ6¿VÊsÕK
+n u¶ýJ"/rSEŒÇ>w¢âÒoSœ›:¨cÍâú:Ú&ªÏ©_
+Èz• ŸêqH0oUý;k+'œ›_0Ð^2[kžŠôÜ#y³ùÞï âm£ø0Ç¥N>c
+Ec
+dB³};S˜ÊºŒÕêÐià:v‡âð)ɘÄÞæô¥oìP±vzŸ¨·eõˆe+n…°ˆ( ’ûL/ŽSÒ‚áëãÁ¡,E<ðKÂN»š¤Uý´±
+óáŽ3á%ü?ÍŒ§¼K¾CÕ¯£A`ØoÆÅè¨ê똔ØàRÛv}À#ñæŠVT Ê]ºÁ$Æ©ñV1 oµµS&ÙéîÆľNSZÌürnb/®
+Á£`ùûöÞkhË,zäƒ×åô>•Óæ>n¢):pÁ|ùñþx•ÂÊF§Û¿Å›Ñ7x[·Ðá#d`ëAßy÷ÔzÏ«ó[:?1“'jö1¸pØŠ G²áÕî"E gÇj}'$¹;îˆ*^±Sƒ<Û*õÞ'%ÀaòJû:¶Îȳò¯,]G…à¢þa¼^r,¹(€®À{Ð
+Œü’̱<ô:<’÷?õ¹ÉȆëu>ØÔ‚ª£’dÄûaásÛìýF4}Z¾d«£Íƒ>ÙêCàßX/8ëgfÂÁ:é“=ãûñw"¨qýñÎÓ–ïH|¸Ú²)ùAåbý¥X;aì‡%Pº.~2¨˜ç†1Yß<‡ÄjiïÅú,šk>d Übõ«dßÊSãÖÚx‰èw–¬î³N ô‚)硱XêzjŽD (LÊÞ#q&êɳ X\2hO‰ÛëIçÀ.Tp®l’uÐz,~
+5“#¢Ï eCxli÷þLHò‚†ñÜEßNJ{ÖY¡õÛá•cš‹ë¶ÅÉ3 r&†ðˆË, ^³H«ÁT óK"“ÌV@B]'ÌÚ‘G¶gþeJtýºÔÁôÚÀ9ïÄÃ6i׺ X
+}°‚…æ%ÃsYj`C]ìÀ-Ó ¬;Ô^;YŸvŠ¹]âÓ QìЉoLÿKIѬ‹/6rm_¾Ã_[V«äŒ†ɇ tÚ“’<Þ.\~aµæ¼Y2a=ýêÇ)"’¹£-6žôW "DDd1HŸ;ª™MÒ±üg•Î…‚%›XH˜ó+õ
+ýõQƒ6îÔÔi+óÂ!ñ¬O–¼IU8¿“ $´ämJƒ¤ƒù®$ïS]“tüWÇ×ÊT¾À1¬ãý8hoD’ýþÕYÄ¡†Öí(o‚€ ?ä¬Pu ŠÜ÷‰¿qÆÐsTÀã&ü#0µµ=&ÈÉüKló¬Ùï˲=<ÿ´üûz£x/ºV"•áÈ›ç§Bö‚žb÷QPúlM}8Øn¯_FÄreâ3äðØÆ2Ù[à3þ®?%-÷ç+½ôK,PdWâꀰôYäá½–˜Ôj fÙ÷v¯ŒôÒ=ElñÝVE,tª‰HÞÜ—ÛÇônÏ«BN&ã¹ÇöªÏ¦í¾’æ§Æ%ÐÁ‚t`õ=ÚÊÐ@ûTßq«­@û |ì‹ä
+}ìú£ŸQ¥%ÑÕÓ·‡ö?´á£è¯oEKˆÀ"ΫƜ±î c/±£_JzRêy>~©8ë
+§H6ž§g¡/mÝë; 8¼»½«ï´axl†f|-Ùˆ¼ÏÜö¾Ž¢³h•h/ÕB+µÁ q{Z趉ËxV†;[…žM><¿”@€•Bâg¼†ŠÄm?ë¹'V0 £—Žœó­Þ¨‡Öñš…SÂ:Q‡XÀýxüc3PYâD:{Óþ¶åÍ"ÌÒ“¤žI´âˆÀõ[eTÐx@à¶ñÚœ” .«å‚J½£f8ûlò[‘OÈ–Æb¼~§1ø ¿­#¬ö—’Õ uìûóò"˦g¸@Ô}^þQ¤«kâÏŽlïLtA¥euᨴ³OÛ³ä'wEÐE¶å±êt‚[×x¯—gšèxÄΕéÏ“ÆQÍ—ã€|4ŠP™)7Æþâš—ÁU¼ÑÁZ¶
+2z;J]`¯£À˜wß³H{eW-Dâ¸`›GI':éÏR “‘—ç¿Â(ˆŠØfÉÊüÞ;cb…doô
+ƒ^nIS„쌫…³æòÅ--ÉÇáRbñÁ¤ÿ-<¿†)Ûx)ùóoÿúÛúÇ?¸O¢ÔÑ㋧1 §ºCwcSþý¥Èü íýºåÞ/B±ï­üEä…}ðÚvÍŠs ø+«ÜÆ€ÚiÕôpŠ(~ÀcPU´ Þo5ï½X ÈHCuÇÜ@%¦H`ôÌ£¼Üí#<F•¸»†ùö½Ž"ÃPç/¶9zV¡yCÐ|Të ‚1ÈTUl±T„ɧï
+xÊeF%Æßm•tŸÄÍ>Ö Ãybs>IµØºìõjá+DpÆ:ß%€ÒÀó~«$[Ì£t¼|¯èïE/!Ã}¨ ³bæ²Û+|o÷Öž³}IÓ³£<ðš´À*DLg‹ÑWïwö*ái¸âƒÝþÕb±÷¸+ö£ž~a& V¿Zð Z¼D» $ þRò¢A3gé0I$Þ}¬% žˆ/iÇ¿ï".Î…È ûQE€å€5jöGJì0Þ°*ýQË-êàˆä\-þ q÷ó(òf@Øàû·Ò*:}€ÉÀ\ëYE¤öŒµÐnJvöô£¥Ìž[´•åÕ®»" KKBŬhiŽÀPuБ
+†#D2ÏNÖñ£=®ÒïÐdžù擬®ùfE?ÀþH»FÞu]ßLð,a×ÙJ¬PŸ!ÌÖ÷v}+˜¬LòÞ¯£>‹â((d"œÜ%ìÑ‚{¯Gˆ½¯ø×ùn@!Íñ¯ñàîž?·Hÿ£Ÿ–ºêÕ¿5°°`RŸAR€Ýƒ¶^ƒtaÏ8Ÿ‚ÿN*`X‚XnFŽ‡žÆµ™J¡Jt¸ÐKËÎ’="ŒÇ¦i(ѹ>ßÀŠ7±Ÿ:'±“Ô†é÷*ºüŽ?bïïïä}uêÛY!.´2ÜÜÌç*%ž18‹tK9ë¤ÿ±oÿ´–K‰LÜ8çË×õdرÇBÇU"ó{‘ý9A£%[ÜL Æ¿ÉÅÇæ
+íy™9,I
+V|d„“ä`ÚòxEaƒÈÀÂÂ0Gw {9Ћ‰Þž”øFɹÎÜ …<"#¹ÆOƒU{âša,mb0¥®ñH'E’ÓˆCf
+z¦“òN¬L¡œÁ´}ÅAŸŽ;gÜ뵕q±v²Àqz¼<FkaÅy.¢ÜYýòkWú…–Âz¬…Rœ<ÞÐØga(‡À~45 +ã‚G7y[â“AÍ!¡‰?«~”ŒÈ"
+÷¤·Ì$,ŽßÒß_á.¦ÂÚÉÜx;‘IÔŸ¢aÂw€åÄÕ̤
+}Œsç Í_… æPr«Gs[-ñt‘'sÛ°#¼+béß'«T´*øV\@AÍ7
+OÈ*Î,«z:jùzs(LØ.óé;MF¬¿!
+è˜aÑAÌŒTv5b„EA‡ŸÄèOF9Øb®¸JÑ‘ÜÖÎP¬ ež\! õ_A„¯S;A̤àĈ•¶WË–Qúî'±”X€T”ÌÖ>@yteN¯LÅÄÁB¾¯ ‡Â± tp]Ä4²
+<£ì… `ª±—Å¢kh7œ¡_A¹!M¤Ä-&€+œy1öÑ ²“Ë
+k‰ ÐVôKì“2õž2R’]ùù
+Y'áÙ,Ôtõÿô¬`WŽ ‹ —‘Ícx’9ÏÓh6äõIýDZ2´:dØsʨµc}OO}ZGÝAUl9R—³xoÃsaî #><Š(c•P¼Ý¨{màzªÈùlÄëTa S,£“kŽº@ÖQ׎¾s›ÛmîÓwxÕ}ŠoÕ¹ïÂ¥ÆÜ)m¡`AŒ$ƒß³ÃIJˆ*KMñ‹­^%É Zd—±Üœ@­+µB*SÇa}“b öÿéLëT(E· ‚—° ô%JWÈw;JÜÜy‡8ûá;JSI¯WÿU•ßáa-a+%«Am.È”`³¹çñ'úÅÁ3ÖcbÔˆ$ *„¸RÜøUPÄq’¿ˆ7m¶ë4Ü
+?ÖøúhâùŠ"\›i[PKµ$ÌŒcµŽ3ê=EŸ@‚pOd?+mìiÄ@¼±G{‹ݤîÜ£z;ÐW´ 7ÑL*vf¹°ß§KÞ§æ¼dû 1ù6tØúàb,QæËÑ #š<'³S
+>áÞoörF7ÈB)$Ü1 ^(ðè 0¬m›2QûYT¥j%dXål`i‡àý˘ò!iý¡¼üͯ¯Ô‹˜+®(¡•Êðí½Æì7ÆE®¨Ùg˜U
+“™Å~îÔ;.& >©aö¤Ù6u%|WTd[ÃÁÞæ•®nžþZ㹈T/½xZº*°õ}Z€UØF’Þ´™ŠgÜ~'¨Ç䇿aJD®ü¿¹Àíu:‹ó*å¡(¬ež6w¦0à»p^Ìt²ÖŸ@—ITJ™ôµUrÜìªVGìïX{:¨ÓÇô֛Dž—1³Ã÷â2Ñ¢){ŒU\+H`½xë¦Ä ¿Üzâ) ûËDt|óÃw&£K¯8.9OñNŒ¸ŒjRCq;‰!ØÅ D¾ÌX“ìAøvT~Wàœ}Š7\æ¨Á†"Xí;ü91Dî[{ºö ßÊ‚0ÿ,.RdÁ4Éã3‚­"Œ×··3hjŒzÐçmÝO´ñg ÓS lf¾âëm0N e:B?’u«@“CîuA˜c<=‘6÷AvÐv–&ÔËKÓ±(#*e$ß¾¨’èÄ`Í‚»¨8lCfp'ÚDÖ\›Ó ’&wãg†# k.Ä‹ØÃ[hßi “ŒYîÙ-
+(Å­‚ûþŒß0È1.†çWªh³AØôEAqÜRæ²ÞUä§È¡ž˜ò dj’p‡PË?s¡Ð¦Î ãòQÃ.aªÓÂÂÈPHMG³d0&0£ÚÈ LŒðdvÄ|¦K÷ïp4þ­cÖv×¹1œ+ªámA‚'Ÿ]F¡-vh­wÌÝ‚ÁóeœF#E}ÃYL¥CHñª?Nhš…ü'”;ìÆð(ÿÁKb%Ù0¸&
+€±`Äœ1´!‰bÀáB!Py¼:Ñ+:Çà øa¾Ñr4<Þ¢t¢m(îRôYSH¢%¦iÉ “ú2ÌD?†ñ¥—³1ÒCt}·ž&‰Æ‚DHÄ †<-ª¼B¾[4Ï"‡è+xø'`­ðº°ÔA)N}È
+—$~äa6Ò'Чiýa ÞHàbZõû˜ *ô
+ZïRƒ˜gèé¤8* c*S”ÑUe>‰ƒÈÊ#ñá;pÊžùMrýCö1mÈY0 ÜÂjôâ½bÑÉ4ˆt*~’ºFßéêðGA*iC¶~VêyâWÂØEF¿;ÔÁIË~{;Ó^p„¸îb~þi%n ÃþÝNûæ§ݺbÄ,QÉ,`ûp|­+vÝêÏ#&Y½…Âi¨ã»M3æ¶yX’ÁDµ«EWJ±ô0¢%™±Ô*ËXg‰h'êÈmšŽä´ÂJ£Y:‰£ @-ã×Ò¯5üdƒÒ­Ì
+âTÊ8@t”6*f=30‘Çï*†YEÙ3÷¨•9+rÒÙ 5è$mvÏtã@!ñº ÉD¬ ¯pDTÄZv1¯¿Çj„²îƒ)¥ýUÉð.tBÀ IÉ­–îÒ-¥íü8zÜ/è;l"¹vñî*Á™a+­‚D+8l tqO4wãŸiO«ÈûÂ’>OÕÏ ?©WC§Ÿ¿smùí6÷Ñ9¼ê6×Úœ&ýRàäS£¾ac´[Áw+ŒDJ Pé‡Ïý|
+JÆW³¯PF¤©®¦¶˜çRæ,Û¥{Zè/cJ¡wæëÖžnM,jÝó¦ÚÂ0íIΞ;*»ã%ÚÍBÏü°úQXM­5¶N#æ7âks‡·Öá\‘ÇRAé· Ì®|4t¹²|©‘»:ºCXŠ‚¡#Ám#ÖTØÖÿN_©Q_=‘øé·Å6ˆWWü$5û-Èèì4é,Ùæ†<WÄŽùm:\¥‡Ã´=ðO}”êì"!xñœÕ`œ×Ž®@ŠA(ª C£œ­7½¡Æ…y·ëx!cO Šm¦ ”Ãx¾·‚ꦹҟ­]Û†3>D¥¦,Ö²Q Ax€6]È9 ¦x×ÅAk—„à™ÇýÄ!í¿Ú·Ë3µÃKIñ:©UBFþ™…³B‚€Vcx&ËÔE|»ç©a¥²î³W§j³1‘Ä"ÞéÕa0\#vV:Ø 7Q(,ª#KJ\­½fž¥aqÈ »ûxg»ö /¦°®OŸúÜ "ÉÔìƒ
+‡I™Yf1{¡®/³Œ“íˆÌíQ¾]ËòŸKÁ¶ñ»rþ ’‡xÈ~²«ñ&øhÊAgKBÇÅsÍm¿‰ç¾Ý¯·OboE £®×ÁÄay°KÙü3•|Hl“•¸Ì.ê
+¥PŒ¶!ÌU!MÒ¼¾î^÷ϯæÐq/Ê àõè°ÉÿZÑ+oöEe²”Ô´‡ƒÌBy†¶žS}›)\›·¬ŽFˆN¿ÆT¹kø öZd¬êjÌï Ô) ˆ¶ªa‘¼Ô lÒ‡\/ácÁRNÝñâÔµÑüèv îCœ0kl²× 77‡áàuìvÜAä¾
+–´`,zW«ŽÆ
+κ—¨5‡Z`”:NBj”Yü1‰ID–Óð£üa¥YS"œ¥u„<¹‘}ÔíÁòØm(Ä/ÃrʸZµ9±V9N^ÀD ‚CdhY$òì†@&•Ù¯(b¿6‚–)æŒXâÊJu…±Ù{®cQº‚6ʽaýlîfrYÖ
+nõ
+‹…!õt Eæ'H/Ë–o‘(¨3“ ] ]g™},`ßõAlÑün«í
+%Õ¡Òäki”J©ŽêªŽ2 Ò±›YhŒcU™/ƒÐ¨O-µ¿€¨2xc-cV×5¨ð¢&ꊛO Ç fH—)ëž÷¡MäÏ8/ž5º0þ¢Ax ƒÄ8—ëQâ(úÏpÖ/ç¾kÊ,‹
+R-4žOÍýpª@XÂî&C)Šêñ±±O’LZzÊOZëo/  ß&ÃÇYáUè«x±Õ­Ÿ&BžäʳÅ÷¹é®‚¬‡•)@õL°4õ£!MIoä€PK¬(ñlÚ¦~¤>áYõZä
+ö™ôàGe$UšÅ¯S®‡ü#ÈPé¸s‚éc´$ì]w´½›ClÂÿù«—“–˜D’ ¶x!ÕÚÄ^)îÌAÏ "Í°¦àHƒ÷aL &š?¬¡¨Bt¹Ch;Vµ{—0òãÒ(ñš¸ÏôCbïèð—C$.E¹'} V]°(ñ…&¹b0Øê4›ÖBÏÂ)nÊM¶É¥B!Šá Yj(…Ö;M®T…[…bb` }ÈAÇRY7ÊÉ‹öQª$#‹s,aã?éí@õ¥RùN†Òí
+Ÿ@ßûþ8bˆ~¬±… ÚºŸ%—Ëôc¬R/âX •yp÷»ÆμAúqE(¶D£³zóWÒ ýD_ìœGN,yË5LE‡o©¹ìøñ;Ìã©£A<:f” F@ps]™…¥Ï23|Íâ¯Ð~«ž"´d©5[<×^†ºËBÐCߢÂbâ)_©¿O!s.Å‚4R“þ±›Zc~¤ò]f ßÑ|iæ愉Š§Ï#H~TaŒ}Vš
+m{{°²µÉ&1++%;¸È_­x?ó‡›Zæ@òLЉ•9Cž¦ôϯè0ïH&ý.ºÅ» Ã
+ÞN{ óÄ Çåz9¿ŒùAAÀ¸k*ë~ÞçÆ@ul ®ÿ®îÁ¤†„Š®÷SÝÇ‚ìÉp'UJ>É24Gñ¶°©§
+äs3Ô÷)åÃA&1fi‹ ';@öQI·Cþ Í|ü΄ÉF®ø?ãe’GCÑøuça­^úÞÚ÷ßöû YÝ•‰²ÑCX†˜$ðñ‡qÆŃW™”°*:¸…}ìûQFjY’m4O«Í9cˆ
+¶c|öÚÚ1‰!BÉy›1F$iu•È=Ârè@rRÎç¯ÆyWZ¢¹´–oÖ\Öï÷7Vt-rûq öî}ïdö
+X)òÁHûS×æŒ5.Š Åä^‹)aUÁ2f*WwT—’õ©ëÈs®ÀqnóŠ>÷Mw W- äÎÄþ"Ï"£@éMÉË >ÏÞÁ²r#³yD°Öz¦D“yÜç nEwå¿}Ìa‹¯î#¶ˆ¨D¤šP%Í÷<ùÇ­ÁW`ßÇ”o*7¤¥2ˆ³s›(¸=*2’È Q¸Ç´…çZ
+Ø>Áà!Î7çdˆû©‚, z‘Z`%Ü âG´ÛwNQørŒ(·:Ì«éctŒ|Ëk{:ÚÆFÐ-Зíc(„EãÞÓÕÐûÓ-¾·ðvÎ}ˆ1»À­sJyEg'2Û 'Üzê
+ ž>û˜Æ5¶Ë#F'`PpzSR[ìÌd´ó©¿CY zî)?ŦqÄ9ŽJZö@Züã…©£*Ç_<TÒÈ/Ð!Ô:¶àoDE Û×€!c9Igl‚‘šlß¾9oEƒèô±ûJŽµ$Ø5 ¤€DŠMHÕ5Í&b\ÅèÃÓ :4Kø€^½C!Y-PÁú¹‹ðÇ;[.ä/¶Ú…<Ä ã èC[lG\ãÉ–Žõw‹<ÞLfˆ¹1«7ßÖô*Ê’'›ùdóc Ï" Y~r†ÍÒXj®ƒEŸ­ÚûA4dŽ×€{ƵdsöV¶sÊ8øç°^tƒâo÷m:û­v¤\À¸rU8TXxmÞnŸ¨Qž‘w§Ê`Vx$Ì…å+Ü“íD&f`%’[‚ .G[PÝŸúb·žÚÓmX!f™úMC•iÐÖ,]ùcEh:ô1ÅÕ)RIbž §ÉK1­«Kl.­Íu/3¨†·0Ô^W§ˆQ+lÌñüUX±'<„JšØÙ:[çz¶©ðNž«¤6E3"•URà>ÞYô¶£)1A‚¼·q/ùé— „º˜Ê«$ÀÏQò~7=Áíð$=J%Q¹„:vIkl?I$O+!ue>Oy!±_6„žf’ªÒaº×lÖdŒ*Ÿùî:§/æýyº)¡A:äTžë-Ђó&›X½ý±qoø6›gÐôX¸kiVRBƒfI”4aïÏ` N¼ÁÜÈÐ/ðS\ë9çÕPÂ
+Cðñ©Y¶!*p½ÂÂtI&éf(êru`„õªÇiádÄú#®½&&,Eß`æjSñ£WE8UÀ»<Ç36
+:5×(Ø
+tÀW†ª¥u¢ %±@œÈÐ8=º&Aj`àIJaÃzñ’ %eÔ”-R^‚£¤¬Å8>ì[ÅdѸä{E*Éò ü‰;Fõá.|ªÕ½7² ü#–]|p/ÂaÈÙ¢Àd¯bƒçcø‰§õéÒWFÙKyÎËï9P DE2ŽazE6†.„Î…_cà}˜÷è`âš]ô½¦@·äš¿Dñ3R dérÄáU?ÞkÐÊÊS w¬K™s“-u? Mb.4%Åh%¸lT—®¤6ý HMmb˜xÄíÿ!P)LèËláCüŽŒpi^É‚;4DK¹NÙ=Ê3MñÄÉ£r¼L´0ö…ö‚çÆNíâBNâí1p:h—Õª$:¶achçÝ“)[ûcõ8Èzó¥»Év@×H@¶­¹ÝaN¦y…Ôö¡$vŒcõhXƒ‘CFÕí]€²@™êE]%$&dUtaHè¡bÂZöË#i/h§ŸŒŽï«D6…¾ƒÍCM,šÜZÞòw)Y‹{cÿðVºsα\ÐeÊê¾ Ü€rT.˜W šäcáóòæºDS~.¸JX:$ɦEQ{ C
+=aí1»Ôvwè.¢‰s3–‰L†SôüU2à<pÝŒ;?íSp“Z¬—¤U”Q‡šÓXv†Kc`ßìi±!ØSÁn?]´Ü‘È{•ty=S×°ÔȬ_—ü¯§_JÖ@“R ÷ž)»ÇTvz‚/ô7/‘KB® ‘.ÿÓPFÒ*ô äêó?aƒWòg‹”‡ÿxÔ–ÅZ`z‘+û¾-ăíYÝ„Ÿ‡ë‘­€’-²h)n¸É+¹çðúGìÙ3Û`:aÄ2³‹ŠlÓì¤Î :6º ‚iȨå(hÕx&ÿX\;äTÇÀ°ìò]Œ¦Ì‡CÇØ`˜”/ÓÕppüwZ—
+Ú ¶ý ɉj‹e%ŠìïpÕtüœÊÙÎSÛ¢ð׌6Çv‰Þ* R ¶¾¯ Çe¦$%ØO{8ì…í(|}Aãµæç›ÓDþáaBjè2>w²ºÇÉÑå’y”ž¥’6¦ZUžoj²µ(¯˜VÛFP²ðìMÙ
+•W%ëÍü@†ñ<¬ÆŒ»Ë3è“ ØìéFdgè}v'õÕÀ?¥2’´ß\Üãð…†WQpŠÛ$\‰Þ&åò%öCô2pè4RHIGíÙ@ºëù2ŽáÂt}{g[è,xëûœ
+6y¯èD®<2s¡òÿìø;
+bf™þe¼<’#Ëa z]EAºµ¶s‹Ù¶î¿— ÙªB…jÕ¦ðéH8KqO r“uœ9Ž£üG¶ WâA½²ƒ@š†¿Û.)<o øÈ2.:ó$]èúúˆ‹~f·˜4~¯<62ÂÓ*Q‘atðë2!eÄD•Öö©0?IK†mÓ%s‡h³R9–ë³*X…dëÁ…£²hæ 0™1â¶`§îéãè4YéÐ%>¦“UŒs³74»ñå@éJò’ Œ´ý€åë€nÙÕÁ3 ØJŸ>=L `—ÀÌYƒ¤0^,ãhg#ôŽó/ùšs'Oí„Ôfõeè.þ1Ÿ^ƒïÂdµˆ",ÉCÁEeXT~ecS:ä‹gÅñ¨ÛËÛiÖçyÀ† ÆD—m_ >«r‡Z:"Á_ÉT¼‹¼*‰dvg’F`j¾wjêzõššÊð3Y@9¹-UÞLe¬;¤h OêAJøä_8¬ Ð'‹&Ð\j‘cQ¿ˆSècs¢k1ñ(NUø&,å2ÁÍ„|ƒ—`¯¸³qæKeVbÊOÄ;[ ŽÊc=[×!âSÚà¼kƧ!+‘ê
+|}ÞXòÀš³y¨L"„p­Ã’ÔežÃ]XT4éƒÀ<SÑß/„™¦3ZÙŒñ\ÄíÛ\†²˜b„ø
+¦‘Ÿ‰o
+yòʺh̆|#ò­…oäá™d”ÝTRœÕ«
+c¾í²|M
+ÄÛðI —‰]Bȹ8ýœ²ùpmUQ+¡•F´"ŽWÉLɪŒ+I–›É+,y°Ð{«ç"T´AÇ)góe°VrI9]ÎÄðð´¹V¿9Áø`²å‚gÊHáò΄Μv«Äiè±öZk¯3ÑZX’®³á‚3C!£làðžÂ)ƒ½JPòŠž~ý äJ¦”9,‡žž‹8gÀ³É¢y ˆàL8|̃¸&eR/é˜]F™e®S+™oøˆ~(ƒõ³e»ëóÜ*÷áPþO€
+H‰„—=Žm¹ „Wà=tâô€”HJŠÇûp`À™S¯ß_Q§ÛðÜÜÀ`®êHü)É8þäÙ¹Wn÷•_sù³ÓìXYU_qÆsl ±Gø×?þò׿ µf-¡ŽÏsQ€„Zkô552
+×Elüω=¹÷û9ä-y¼æ´ù5“ÄšüxæáÞ8ó!ÊΨZ D>®ô`&¯ç'â:r¸‡¸ã5:ú¾‡0Xa‹íœ±¼¸f¯µ'#~[WùQü
+ŸE”Åã܇„âX¨æ w›q¡¸Õ€Ñ!͇!Æ´¶Äž1”æ}ôw6åÞHËŸw¦{Ÿí±LguÄzH¸ü8‘c\´b‰ÀB$|b@†‹ØY}œï ñN¡°¶ˆë^Ofâ±óÙÏÌê@a–5Ã(«Ÿ1>ˆ¿PðÍÄÏá&Þ“[ÛŽJ9çAª/¡uÚ|¶ÁìÊìLÈ7¦è2•ú¸œTP-çZäíóš™á
+ÕS\¨ç@uL‰š9AüFÞЪÞÌàw\Ç
+}­ÏrIœm,yåæ•3þQGÊ¢æ\ß’ØÊŠªÒAHv„P{{_ª¦žP–pZ¨2ƒr¨7_…ÎÑ
+Mà/bÈ8å à ÐúûP”õCµßÄÑ•è?êÈÄÀû£p >»ÑLju  ·—µ¸¡§ ‚Îj³Û tè¡!ó۴ݺíIëš—¹ú:Y£”åÃ̸Z™2p¿­;!iB ÁbäÚˆh¾fwáóžÞ‡cÊnå2ÏýŠ®‚8Þ¯o³:³Ø›t`È°
+Þj„š(ˆ$Ÿ{DqÎO º›Ö’B€@|CˆYé V×aPˆ¿Z¤ìéÇr Ö³ÈoB†¦²8DZ¸dH1¹½/!ºzéØzC‹4Ò.8Üš5cžâvJàiK;r
+ÝS(³…¦P›Dd·%ΑŸˆ~Àa&ðû„ñë—{Ì0TúHa¡hw´CQ5Ú1TâuÀȄΞ9hÔ ]€|ŽXsárP~èuB)‡€Šâ
+šÇ!~?"ØQ,¥ìãœ=€da*­»òåÖ'Š<n­²T]ÌAbdñUä\:þ·nߣ¨ï1ŸÀõ‡>âKÎÚì…éã—èbÈ.mˆ&/B^~E„¶¿÷þCêþýJÔà
+B,rhÅÄvœéY»ñ(µ-Ú&µ5gßR%RÑpp‚IÜ{¥ÚZE5—´Ï¼"ŸQ͸¢ICt–FM¿{÷”˜Ý½bš„˜YÁF6©¬¸Ùh3¬°=ò#ª˜âãV+ìuÙjï$b‚icY6Jì
+¡¯¾‡úЮÆÚÙt˜¯âÁÿµÀJ¨\
+G„0ÕbÛ´;智·^ª¢îžbhð04Ã6B<߇êÎ_µøšá‚ uK¦m¿÷h .ïFÐG¬5{§<†9!4‰¿/©>Ì¡°5@x6K½„ú F‚I‰”œ<\6OØ"¡šŠ.CŠؤ
+ÊW£v JT£¯Éq>·Ù2Þçý™Q·l„€™+ÿ{=ùµ¬nÓ¶Ú¢&®™IØúêôö±¼ #¯#—R—µjÄø±ŸÊÓ$Fó>jY*®»°‚ªzH(¬t(\«u ,j.Ÿˆ0Í#ë'ÿ{8$p*Iú†"Ah; ³
+âKZ¬JZÌò_ÿa»Lp%Çq(x£‚µKçé;Ìù'‚tf¡ÒÆ
+Y¢œ“Àú²Î¥¥†bÇ;ÍÆ”ùh(ÎË#“ô¸W™žqÄ1Þü‰–ºý9Á "³CÃÔ<8r¬à“yëÒï©i’ùšFv8$äŸãUàônOáœ/ˆ¸J£wy!8¸cæ}¬ÓƒA}uIUå†òŽ6™­£¾ ¸$‰? 8ûÛ]ÿ` ¬?'¼5ôÚíÒF3‘ 9 òÝ{D/ä8¢îe¯q¦Hûò@ÄN¸xô™$Bº»^×!XÁc}ÇK7Æ~©À* TÐË‚VŶ_¶*÷¾k÷@¡)xÃŒˆ¦ ¡n==îW"ßPlªk“T5\‹¢,ézA|Nî°ázÈÎs Q‘Ðø碊!|$CR‡âxÇ‚ºè;&çm²ó¹ÈpJ,eßw
+TPg¦%Õ›ŠëÆÜä:1ã¬cŠÑ
+i„rÜÉA[•@@‡Æ
+‹¸¿;5ã"("ÇL'
+t,Ciz©Ç•
+÷QþœœKžÌÖóEsâë!B•·„n×z[Fã†ðÚ$дñµñµ´7
+U’:Jn¸¤c0<Vƒäƒ¨?
+°iÈd˱
+M‚²–)ã)yçaü¨pùqµÏGÝÌÁ¥1ñ‰€a£ŸdôDÌ¢'‚º$À  Ÿ}Œ5bèk}}Ø9^ Wc•xG À²ÁEP
+jA"`C˜”ˆr&bÁ%÷Nq<æ–:M)ñx<¸Š3¥9
+añÉGßÆ2¿mÂ.jwÅS«q%âôD2­šbåNJ;ÕØzþAU<~º÷Ü Qíƒ#Lçögœnš2þÁ+ ÚP¹¿rˆI¦\iPÖf“ㇱŒØ׳ØÜÐb7ýN¾‘óVcvwºü–³kšQ¯(?Òb9è
+n|Ds„à›¾Ÿ(hÏÄÄX¶¦W±…B
+i!lçD'°n”‹L›
+k@‡Tn±D×Ûñ†Àò&ÍÝ—1—omªhûA-’l¬Ó¤>ÏÂ$wˆ«äN\Gâõ9GîĹD ¸ç»“í/
+GÞïó”ø¹áEŠ?öh;Ùl‡<Í:\JÐ÷ýØ;΃ÃíÕ@›“žÙAªñ$H]H†M
+¼šë™SYoÍú‹ {{TXr]ŸfúE‘÷øÓ\YÌñÓ¯ç`éºH:(2L­fð_›Âr_¤ö
+FgzlÝI–B UÆüÿ"òÉ51Ž¤ùq­·ul§oú"ü©·XS¦y"
+rãØÅüm®PÈ Þa²ëÌLŒ0§)ñæ=Æ‚jÇjé’¹Z r³…ÿ¾ Ý.
+¢¬ªµÊÔUnŽu /±édÀ:‚6ðdÊ ˆÝK¼îpâ8ÆŽÏNišräy”=%ykElUƒÊ‡R‚@á}ÝÖ¤B3ØšœvyXÂb—ÓÔ³¿aݣͰX=*ÂyX. fÛfEdؤê·âòÑÏ[·À¯fhô/"IæÇò=×ÍhGg·JaqÌûåxõк"ú ß}PnÃþ@67'p`âï¯ûÄÇwc$‡|ÜL+˜–úk€ûDd4àUô‹B‡*<ÖÁn µœZ^K¯Ðv*ÌI}7ȱFómth§óóC…œôKœî3ˆ L†ÓŽóWÙ
+BçcQëÿY/—[* ÿ•=LD;u¿èèÄ3t¤: A%ƒ$N„ü{ŸgUí£t7d¢’ö÷v]V­õ^htMák„m|Ê‚EÜÏŒ÷µŒŽx/$¼VOŽ`„ÐülŒx¸oœj NÃIM9¬7€Ón´z2N”y=ü«UàÕoZ‰+kÎqö%ù«N²1øÓ¤3!œX’OÛ‡³£ä!:-,/z ½ã4‹OLL«2–~NÛyÃu <ˆŒ§ H5iH1;ëÏïõ81œDXcÖWÖX_E‰?Î’'ÜB@§‰UzMH¼Á.é ð ÛŸä•× U‘ŒPvlôUw2Œƒ§ÛAûlÝÔÌõ{µ™d(ÐXWUÞAÁîS'1 ¬3Pe²è1¡ÔÞµKq•æ[›÷†¥>OÍÇ¡[Ûv̾áþ|¬"ýƒ8ÍÀšo½ ¯ÈýD%ú8µâ5دx
+ˆ°ˆ¨ôúçf´Æ’NÊy0Ý1¨QG‰u†Fà DZs9géx
+ïÅEïãm
+¿Î0€‚¬k ’¼÷õ§{ CCl<ò°Û´h ©VÒ"·v#Ï
+n¡ t°"!(û¯Ý B­¦škÈß ˪ ˜¶bƒ;ÌÙ®Ø ÷ZeÔA=¦b‰ošzy2Ý[Ä3e¾È&TðÎ:ø‰dmhÈÚ›<¨ñP¸GMc¼E¼‘Þã^_£à+ôˆB³êñM›G'SŠµì ‰
+ï¸ýà½Cÿ ÃD!n½IŠhËd$jQØÚe8£¸Cƒ@h Ø™þa,NåH¹‰ç<G¸B·ô³¶éÚr#é?ùç7å_éñáþ÷Ïñßùw~¤—òHñÿ¿ýr[A²…ÕdKf/Ýáýþ¢²þ¡7[ 8D6M¥ð‡®ã* fxE²¯@ðgèjØ5çRË'"m ‰ëåË‹² „}Ó0Qôâ0 ^FØ,Š¨›tˆø
+wTëU8•"ºÓÈá!q)‡ò–!.åv×çG3^µSP±!¯È¬ Fœ6­`gø¢mx^’ãL› à€•\Ìú°Rµ¿<U²÷ñ¢üñDµ•ÑÝcÖƒîWð'!"`@ЊŠ^†Œ•­T2ǬŒázOeè\ŽéÛÛ‰f‚‹Î ´P"^–ÒñaËyÑ\k $R¡ d®×%ûшëGnÏmÕAÅÎÃÉ2‰ÍAeE¬(!ˆ¬òBëx›»ÁàµÙ€nZŸ7H¸cQ õ·ê¢J1ãŠ(;=È %w'nXÎY’=à0U ðÆYÄ2"<wÚÑ`¹æfëP‰ p*ÁCùšl['m}ˆtï´Ù]âÃ/ðÆd:î”é6ºhÅì¯çk³©ìT®Íöæ ÓW¢ah­° Ý {óÅÞFx¹J:ÔÂDrH/wù£‚Õyíb+W6ª6'4ËÆFæI7Rx¢BüÚ]Ësel•“»™æç B¤—* –Ÿqm”³Yü#¶ƒˆ8S jááYWÍSuh`ÕÝcànzM²¤©ƒä°¢áÀe:±V'6ÓÃü
+¢9ôO\lÃÓ™Þú¬t_s×ÆOZAWãùMŽì„ØíK˜¸v~¢Ï¨sÆÙ°N>VG;ìM›+ÇQ€W°yxvÝ¥j!ëÅas¹æH3íPxÒ^Š ” ;(‚I› J±ŽÌsP§3ß¹|ò;l|u ¾PÓ9MXêh›ç]š'a— Ö§ƒ .Ö–†égž"ÎQî¹Î@™ïÓmafÝ/|1Ny©“éŒßûñÇ«ÄhñÜDÇFäþU¦ûµùãÿq*á LRuèbÊÛTì\œ…nÆ@Š¦#Pø»ƒ²9B.8üCD\|›QÿX§ôëä
+@S8Llm¬ízŒBU9šïxÐt<(’]žc0é:QPö>(®-*¥3¹ì 8Žñ>ôáú¬5ßÑñ¡,õ~SøyybXÌ=7TU`@I«qJŸ
+Àð8ÛªSVøÁ‹:'® B²‘Ú} y
+qeÄ°GÞã9àå¦Ý²`ê‰ó¯Î2ZM—iÁoQAšŠ=-Ï:[+È,Îç»!tõ»˜V $•È¶3wäÙZX¬Õ¬“_±:<‹õ§ÑœTóÚsr'#A€8ë'#¸ò?êflüëe’#ÙnÁ«ô äã|1_fNVý…h# Ñ@eF’Á|àüÆP! ÀywGè¡ÐP8ã³rÎщ¨ „#Í,VÓ[~t­§@¯hÐé¼›Üè¦P~5hS(R[Ö¬îë8˜x†£ô¥ˆÌ$
+³¶¬Ys,q<ªñÀkN«Ê ÷#bh#<Ü®Ÿ×Þ)R‰"ƒvR›ªˆÑ…Ìò"º B„Þ³k¾œ^þK7V]DУ¯½›Pq‡'èÿæZ7
+ÃaïœS·¡m.AÊ’ŒÏ Pá UQ¤ðþ\…Žß‹¬Q”û$*¸GÔ·pN‰`HrÎyOR%û
+áûT5OÅ÷=YFAvcp©;cí0j Ü^Ý:(ªBWñ‹žd\÷ôu˜šêýh‘øé†ø)ðó€<‘x;~-iÀ(>€ÞC¥¤¿¢³|M«œ"FŸ ÔeupRU]ÉBÖŽ­Ñœ,Á@VËF8µtÒ™”ÊhèîiT‡fW‘#Vÿ*­( ¢ÂÀ¶H
+û&Äs¥êDPUQ¸)hî¹£Eu°æ¡y{ËHÝ= ðd,e%=Ð=vÚ@ÂsÌøò²ÿ-|þŸæM5,fœ…jiˆ‰ 2£ÿ©°#³bg()‘ê«w¢x3ë¨á”ûþ ®ƒXð¥tIûkC¾øSÞ
+Q³ÉŸï#x©|À¶®[®D¹Du¥dÎc‚µ¾œÃ$ú3f‘r '6èöI}6‚aü¾üIKô{Óö±DºýF%c¢V»7©¸`¡×Í…;Ìå»ßŸû¢ÂVÞ\äâ÷ƒ!¹÷ìJû!J[P
+èÚZ`½ØÏAPÒ_„ÅSG5x,ý,qv¤ ][?6j§D
+Ådÿ0x\0à|÷ìä%$¬LýF½ ÈâP? lÏ:hsË"Ve®Û_ZË~:ª½|ÝWhÁ¦¨9z_åߌ’Š´áOY]Ä8aèï]/çb»äÜfF—HÖ^Cp¹€¹'­þºÄ¤AÙ:[(aÅÄÑ>’Fã*a8ÏV«Ææï·Ìð¨2D„]Â:¯%\¬=PÝ EQ*µâ–ˆ$‚\„wtl_3vçtW×Ùz7U…ë´B4züg9±@´lŠ‰^´üPj½31tîáyRŽ$å«™QñCâm¿Ó+]Õ±{+êMãÍ7l4`’¿<ébH±ÆÍ%Æï¨5ˆÙŒŠ¼&
+,åŽDýpÿéMÌÉÞª”«ü=G„Ú3صaKîƒvÑÇï\ÓAG1
+,ü¸­Sغ£ˆv Ž2¥uAŒŸå¼ª”'¢-¾”ƒŒÈþÃRª 8uéwDf¸ÎY?1¯ ÿ3ØFöÙcæX<¥qa¶ÿ8@f'9pjœ;´+0´D9fµITšÀœ‚œ\t0
+¬¾ub)uZH:ödíæ|:!CJÚ%U~†@ùTÙf‡ü÷&]—DYÜKýÔþûÒÐïò½/iŸkOïz¦¶\<ᔓu‡ßÃ"ÓI[¹ˆ R9h¥§âÈZBâ%_
+›Ø^í±‘Ö°Zšñ]ð„òGÏOÌVYD£{Q6(Øa&ª»)D‰I÷X8ª`#À¾‹³Ilòå¦Ýox(Òn¿7±SͨYæÄ|‚<Eco0Ws¿Gªz|¤2Žˆýž3&Iºô.@X
+þ<yë¼ð:?hÒçÁñ”ZÂòÆ”I‚a`êѽý^
+÷6Á
+÷cmA¾ˆ@Ú"v}Å‘û@‡‡} ÅU˜[…(:Èv¤1˜†1¡SÓR›,Þœ“®Êa…(^Èê4G
+KߊI[E}:L#ä]®âÖÒÞU¢aƒ‹ÕQÝù"Öm‘[¶œ¬¡&¾€
+å|ù&Kæ·‚
+&›¡€Ž`Ò:w·wCD‹ÕŠ#…×úÀY­
+ð‘߈ó‡
+€q¡ßÄ­Ó0а 3ö-ã]Ç#xD8¾DϘ³š¤ƒÑ Í EÏ_öûALõV©³éÐvájP*QŽ{è."#j@ý¤wCý›VS‹=zígî+•½Fp–Jg+Gyä 6Í„Á…H^ƒ;E/¾)°aË .“R$W ¤Œ4ò;ãÝË<*Æ^Ô`LžD›ëŒ?X×ã⯅–¾þ2è´è¯£Ê¹ÝT¬,ýú{ÖñÉŠ ïŒIÞHÌöbTg·öÕšÑò_ñ²1ŒA­¬‘ÖE^ hìC¢7fÈH¿‚õø°ÄÙ(_ †¹‹æ)‡<yµow{5Iˆév£O%
+%·DöéUn$bc†U–Õ²‘†¹r˜¢%f#š³tÍf_$PSºþ«1°qVŽ‚fN3q¨®7±¸I)NifÖû€Ä;8  \¦¬ ¢
+—‰4ò/ ÅóE#ÔÜ"§[znuû–)짟nû'ÿ}ýÍ/Ÿ¾ûøç?ÿôý/¿½þÀG_üžkÈyýòõõ_>ýòñ§½¾øöÛo~øá×ÿüó§ïýòõ;"ÿÈüûÕ_ÿO ]¯oþÁÿ~ýüãWççïòçùçßù¹<ûÛoGH¿êÓÃæ……_]Ì;ýøœBù_A+
+ ýÒç Xâ«_ )§)>?³Ò¶×»ÙK©Í»>ã£Ðè[ÞZ% ÔE°KJyP>"â¢ÿ¬(f@JØVÛp2;#ùÅóŒehâ¢û‰BZ¢ð^ç²éŽˆûJ£iŠÈ¾…êû,1ËY‹1âb¼1ÂEÞ7‚X/£
+ýE‰kRԅȬÃÀT2‚Q‰`]wB+ǹÒÈH[k‡aN„ÈnÄõæÏ aØóK©Yoò6‘ÙÞQ /ÐT­ DA
+9¤Á«ÐL.чîÆ)±¡Kô¾ ÐÜp –w<«…™À}¢m !#'Ý‹l½:
+A¡Õ ªNºlÑ´xй6ËT‰V<ø}{¾†ÍÛA˜R¹,Érœ²Òö45®S{ƒ­0áîs6¦ïñù ¤m†ò6Üù:)Ôשê ïÅÎ^|@—µpÚåsR|XóoöÙ© Gù Æ+Å›KÀ‰Ã`ÅåM
+.öA]¬DÓèåòA­†Øy8\ x¯‹LO"`WZÕÜ`0øÛÒb†"BhZµ(‡Æ·fÍßþ×) Ó)Y3ˆAëq<3 0Y›ªHø‹7NÆÉÞlÅŸªf"„— ifâ#Sßéúîå©•±t“"¸eæÐÔÔ—ÌÁ´Ƭ0^&ZöÏÞ †[”F=PUo
+•Ïeðì±LƦsµmlµâô|Ðp„y×Gœe.C£[ù{ÛjyÄ@ЇŽß qYA—µ{Xžîø\·v`ÿNt+v‹¯e¾2ºž·ëAW»õïæâ÷¿8‹cBB&Õ­çÞ¦
+‹¨%p¯-ÖéÒ AhÕ¸EÚˆˆ: VpºF=vr´c§Eïš)0ÎÓm®Zr^—]±m‚ðóÅè4-;>Ôœ²ÕŽÃ´Ï0BÉ~"2ÑÎIY|°^Q¦æd›nvdŒÚôd2Úä“)U÷lp—†B}4Å¢TP î Cp…
+H¶"0È$‹Ì¿.ShÿÍ÷Ñ\§J”é
+Møù
+„&R§h¹QEè@`2Ö×N§ÇAhä
+Q|Ç Ĩà
+xç=ZšÖé3}˜(Ö&¨'*TT›=ÖáH5}ýÉmF׆uY3
+×A›Ò´Ç6A }æ/‚É‘(,+¢?mïCœ ¨¦·õpu¹ŽIµÓ^j
+õŽÝ_˜qo¢·xEÄñ ÍŠ×Ör·ãÕ¡>þÏoÔnJÞC[!9®y¸Ç‹È¢çÜ–¹Ã`ö°ÌñÝÜm±<Ûk"(ÞŽ.ØŽÐú®¥59Êq½Ö‹(‰8×h œp8¹Ã #ž¨±/Êfï‹­i+Àä„%( ¹¾Ø>{AÐx§…=)^Anô„¤p㊉Méµd¸c«yÕÈG›¡ˆÐÌÈ–¨Àiˆ«—õðÙH¤„e#qóu•º!BÊ¡B!‡«ÌT¿Af¡”8µJOŽØÒ7N–êçú>ìÞÄ[ÒfH@‚ é'ßfT<ó¤í„èô¸î–ˆ­ôÁ¶«`ƒsC­Ç+@^wª¥zŠš¬P; wâ7G"j‰ Vð ˆìYTN®‘ö‰#ÀP_;|(ø⌌7Í:£côÉ–¿jø Ê«C6ˆi}î´“ü@äUpð÷…m¹Ë¬ ºÊ-U
+ C¹£ž
+ÔÉý/zr¿yS¦QóL ê=4Nœ:¥´N£¤uZ:‚¹ôÐM&žqÜ|±Gò{ÒîΠŠJ;âÜñ¹^‘ À5ù¹¼O!ý'â±HпvõBÔ4aµ°ÌÜF$:¶AHŒyFåDŽ
+DÆžˆÚ‰)4×NA·À€$À£¦.UŽ‹EçV‚Œxúû8…ÊìNc*‚äl\s™Í¢%FŒÒƒ DÕ#\òK¿ˆ–öòã=øWÏJÖ*õÒ­íp‹M¥QÑ645<†Ø7†"¸0GÆ]é…Rþq«í®FSYÍz½9'N²8
+'y4•‘v×òÙ!6qŸ¦}¬"ÀE
+µu÷˜‡ÑíTñ"|lÄÛ“ˆÓK ðÞ lTº{<?+ñ0O f?2…‚¢Mú])) ¹r/õhéx‘ÕÚ}o£(@y&”Ü3!ûÏÍÕ‰¢q[+Ë`¨»<|ôþ1ô<aêœ<NM¤°[5'GóF`0ZYÒ=kÒÍEÙ>¾áò®Òcâ×´ÚzEø<œ©Ò149.·Û߈ŸÒnKª|.ŠWûe€ *—³cÇe=Ö¾]óHdÙvÙÙ;W’bòøú¿ËЭØD„&N•uÉ¡¬KLe Áí¥†$·ÇCI
+B)¢h´óøŒ 0WsÞy`içÑF‰Î
+g-ÆNtcˆ•ñ§ù·d8CCƒÖa®™.°Õ{ë;k¡_S—Js’¸ES…Ü`fl¯uâ1Ârç}¸B†z#Ø@·Þ°’dÜm v¢(føþiKÏN´ÂeX?jahMµª·`ŽCYéЦágI_¼/Ã'Ò´¬ßÛ·.Ã`³ÇF™a>ÕFf_ÇÖ5Ù*ç“öãpzú?ÂVyÁUÑh+2»¯ì€Âø5Q·“(¸
+ÑÒØE”³*¬@ýÌK?5 µÁ£bœÞ¨8ÑTݨ Pg〴4
+îõ1CÅÙ‡2¨Xó[Ò䬷ÝmÕËEñƒ"Ì|ECuzwL´?,øŸÝÃØßÜÌj‚áÍÚ-Î@i]AñRÃ$ Äž‚E FöÑŒ"½‡Ö©MVp‘ÉGFôUyô®sÐî~«÷¥Q£.بÕW x…óWgâÒ{Îc8ÀW ß5à«é§\ÝïRDqRe¨ë~鉰ÒÀqÁÅ8M˜Ã@,þ1Ç\ 1b,äïv^æîDr¥ÿ¨•È´;+‘Uå€û÷À&i~<Åç·ù8YO¦™Ý"åà¨5MË1FëiÖà
+
+)¦œ'RLÇB¼Pºóá¿ZÓ t åÖP¾HtiG kFß÷M 3æÐÞaC‡î«¡. ‹”¢ŸÀ¨aïÖ”Eº¥óüPn®òç—iPBv¦ÇCÆv;9ÍíòòJ'ß%£ÉùÖçÖ1ÔÞ:|Wª¿N(q£º’¨Š'¡_‹-=?g_1àÖs°*Vé=^«ŸùaÄ»+A|RÁ¹O™/‹à-A°1 x˜²íÀr¹ˆ;âŸç¶Âº+?°C °}\TÃí’ ¶©UÁk’Ú—*5O¾B
+òvìA2 9Ջ؉àíó®ƒÌ`n~Ö/óÛfP”
+¥oSBà+‹×¯Þ»ÃŒ¥µÏ«¼PПǕ,šŒiȪûïÜ´Þ°(Å1´8ÒÉ«j‚+²íNÚv7¿ã¼d’DuçŸ:Ìøz™9U+2Í6HRÜø3WÎσµ@ ð 1‚½D¨¨myÍ…æ´Î¨<‚[̳•pÏÕR°·q€þAÃ#‰ ªä Ta| LÛôÏÓ|[Ü–ž‚›ÂïÓt‰>j) 4ÌŽ»<Qêì´¾!° ‹‚ÅgÖÖ?+ý²¼ÕÉuÛy°;¦w·…ªo[–±¤Ï‚?Ï|#r¥–F¬35¢_桵BP?TÁóà ™ÐºD׺xO'ׇÅò^ò…Ç™òj´Œ("P¨ö\Nýß»\ýÛôšš¡U |;ݯZÂ.ÚPŽ†¡õç÷åÛ5›vóÌÏ yG$R+JíÕ™”ÖGD9œ6”"ý?ëeÓcÇQ…á¿ÒK;‚ëúêê*X9 BY PP„Y¬ÄAÄc™1’ÿ=Ïsªg¾Ø °cÝ~»ªºÎ9ï‡l¿ªÁ“ïöÁS4
+r¬'ßæ“øDF:gTð™¬_º½½óD¤|­¢±æ
+VÚÃ)7úŠ†§«é’@¤%-ØÚANbp‘|¥MŒBmªc ‡båPî
+2\¶m%Õò]³X;4ìï!vûŠƒ¤ó£QõP‘(tHˆšIê+8PLæȤü$éÓ>hc |_•±,§& ¸Ÿ9â-üªÅç‚G¾ýp}Km¶?ÇÛY„:ŒìTà3²Xõþ2¹)…¦ŽÄÕi®gøG`#ÌÕ-8÷yðÆírÝÙÕÃJyS²uè8>w~’ú+DÛÑ‚êûLe^%½F©ã´0,5„§„ pë”qÐ0Înir’dbæ÷®q¨·9Â9rm†²/.%rŠv¸–VñͱÜú>cph9rçRÚò0ØÍô^b
+³<ß^üñáÃÛwÙž}ùåËï¿ÿøÓ·÷¯Å>ß~ò×üáÿ_|Ç_ßýŸKÓ¿o)þ÷êÓúe{õÿèÛ³çÛ«?ýçÍòöâËûû¿mÏ^~ó‡×o>¼»ûæïw¿{ýöÝÝW÷ï?ÝÝÿx÷›Þ>üöÃýÇ÷kÓÛo|ûæý›×o~¸c‹;Ü|:AÚ^¾á?þçëß_Çß¿÷oúéüë£þÏò¿~\i<Ác£¹Ðªi‘é¡×èrZ÷Ó‰’Ž@ABi^£DÀl]D‹0âvÃR.ôX ¢Xm ‚þV(fÔ™W’ ¶ï0m}½û¾•½„O›20’ÙrFA6é ï‚™ç8µ2¦íH$LB÷ÇqZuBÛEùÅPÑÕÎs*J£²‚o,0 ˆàƒö…€@c`.©{žës
+¬¼Ï:–1ž1%¼ˆyʬ-,è\ˆ˜½ ƒŽ…à³=lœ¼‡ˆÎ®vèùÄ `I§;aÈñ7«à­.\6ë D=¾Ä+§lÿ~P%\²Â]¢I¹ñ;¦+1âÎ?,~ѲÅE“ʲœ‡ƒd±ºèMäá ˆ1.i†–\¸ÓjƒÔЄt:\|~XUØ@ªJšs˜<7”M‰ô#õ3»Œ=² ¥`'îpO¦Ÿ²§„Åâ£øé´U¢PìC]ZÊR€Â¼Ç2[@ÏìñœŒUfA.¹º€<ÇZŽ3‰¡y<íL
+ØBõHE0$¼ÖÁ“{ p$¦1ÖŸë$˜Ô8IM pŠ8’c¤â´Ä”oñã9{L/vsËpÀrëã*A ¶mCáÐ`ÂØn/š6×ï®ÊÖk9˜ŸÞѶÀ*Òä-h߃Rž.½ßB ´Å2³÷ÈçòŸƒ¨!îãcÈU8ð‹Ž„A«Eä:¬Ý‹ÉÇ”\`¬K!ñì×€ØÈ›¤yçžq4qùŸ/3—æs Ø%žû³Xœ—ñòšÌ€‡KPtçm` ³}r¬Àº6%ÝÊѶä9쉠i+
+#EõÛ|ÜÀ†”Ù±yï&^ÊÃu nÐcËÃpO`¼'œ CõôÀþ¦ì^ð±z\ÁH¿·Y!™’SáÓˆ}‰°- NÍÔpl:,F ¼FÄú$'ú•ËÃeð17ÖðÃÁչļw,ÛîQh´½Þ@ÜjÝ+vÏ‚Š,a ú´MLÌä#G
+'ïHu<±#• ˜p^ a™±ø‚ÁÛrÜóa‘dwz=Ø]VÎ&·±Œwï5Œ7=²ý#ngñ#U5»B|«=g§8æ\¬/‚à! Z
+
+ÕГë$FLĨí8Í7;ö
+ML’ãZBúôÄ°=]Ú®
+'ßEò ä<ãÀtTöS‹LGg€ö(ȳ…¾=à±ôeŸ#yav 8,{¹±NÇô¥¦±§4òæïpxs¿ v5¥VkD=ÖNר‚"‰Rã›7âbFÁ—•ÉQš5À-Stì$ „n¬»¹Ç:6
+B18÷;BíÜÙ)ê!:b³ èYd›‡8SE¥1Û>Á©Ë?1ÙŠÖeU‰hÚÏ}Ø<;]dÛ΋ÏF§¥GiƒmH…»Ò}Å*½ÛT¼2ñúߊT|‹¯/f¿¸ˆ7ö„Òe=d¿Ç2K¹«\ÆFtGMÙe¨t´T¢œ´\ìM'Ü4ÇDÊ°™Õvªçc[ÊY Q´€(Ø(¨paÿ$¼ÌŽÉu(êJYP‘ÜI{žcÿœ¤ÔÓJE¼ù˜è¨¼âwDô˜±Ì 'ðÇDÛÑü
+$žmêc8 ä¡JCõ§wÚ*èºò’ÎevŠ .|.Ñ7ëO/Ž´vz˜‰:Y‰¸:ÁâÑ1/Þ}:>®¹¡¬—eU”PkÌ<÷²&Êô`°u q‡pÒ½ŽÊíNó¦çÈ)"¶ýæ¸hé5Šœ®'Pz/PÌlº<F;PtÃÌꊳ›€c €`³@q/s­<,*ÚðûJTbûz­ãS<0]5\eh²¹¹ÂaüÕ%yòŸÅV–…§ï‹u>øÄçý
+QÁŽ`D½f‹­y"TùÒv 07¥¥|GRÕk-è¾ œã‰xuÛt@ŠÆÂtöX‡(É¥9 Ä^n…ÅQN&ñ2 왦ƒù« ‹Æ9YóŽ?òå ÕÕ›zá^VS„î2pQ Z!(‚8ÁÅÃÄÄ FUA@…&
+k¸ß;Ñv ’’(šCT¹5¤2…~¸VZ˜Ýkn>„' 2ä$”ôÞ‡9ªÎ
+»¦ :C<^¤×@EpéþÞië\k® 攀©—M3­ù=Ê~:[ÚÁ…PÔþ0c‘K¬qß„÷ËÝÌDÇ[ÐÆbà×ôRIWvbLš±ÄÎ)gõ¦ Y{~HsQ~£wõLòÑã×øÍ™~³UÃ!„p¶ÜΖ3†ä&¢¥‰¸CÈ9èd¿ÒÓÿjZ¢q‡)2ëË5pÅ0¸¼'
+ŠXòÉÆÊŠ1°L*:|åÃøNÿv‘CÕ¸Ô¤[Åj ¹äîó €·£g–*X\âwû…¾Ã^,Ãî+í«ì§ÿä<æÏI3ó`¬6¦ÌßÞ‹£³q±kÿùy¥E¬ÀŸ5} §ª«(1øúp@0u¡5YwÇÕñ>EÙü6½ä$.m'#¤(·Q1¶î*®ÛÑ-4¤º.˜Mqå‘Vvo@\¤L(‰ )çPŠõ\åÂéêš‘ü袠¼:ÎÖ¨÷@|UÀOá„Q3zâW›uí_ZR¡TY½àà(. ÙŠ[¨%Ý‚¢‰M¸Úa­Aa1FQºký2Ý+®¥³ÎüeèØ»k¿X‡­ñ1ãTÄÀ!¦ÎœßËÌSbï„Õ‘AL
+¶½_ œ"›ò0¼1£ç1­]Á­.–vΨº÷Ä¡Ù¬f¨Gа뺛éªÌ_„Êbx˜~´¿a=–7(ؾ—qÃMŒ»År㪼É ö9t`õMÈ,òö R„ñ_]Q(¦Ølá—y¾
+w÷)B€fØâIô Ås‚ES¸ðJ´{rÛš¥Á0çµÝ-½¡¨¬.œ{H›ü[õÏ$Ñd‡´ Únî̶-uzñûõ_”À4Qá{Û‡ÏG‚?©ÎÚ¬à"?¤­…—%4ó‘Ô¶;þË;X‡ŽÆ¦s¥V¿Æè6 }d1øhL‚°|u@\Ÿ$LeJ鯈oìBÄ”]Råáû8Hls–§YÇÙ³2³K_ø(+ÿœr;§¬9¤BW"_qÃT ([ÎnŒl(¢kl@Ào40zTº…?Â`•º*%¼ü>Ñ¡m¢"„
+±D–E±ð3Žâ¥à «3 lrŠ’Ä}ž1¦ˆHÞ¾‰å™i=€¸HcTò$Œ-o)c¨Ò€X$ÕM„)ü?À2>‡B²ÚÏ÷
+Zj¨Ë¥ð˜ˆåŽ›"t ™ðóïO…÷ᢱ…“cQ…7ÀI+Tz2LP,ûÓ(ÈÀÚ¡~îWkNž+W£ ŠžÜÍ9êÈÉ~TÂ>a¥ÙI±frŸ¬‰#±*Å nãQõ§Jl*î2è9ŽÆŠÒ*:«¡‡ú› CS¡w‚q|X•&0
+N °1š_S?Æ4š^ %[ô)“cvº¹Nñ^ƒ0†”gyå'…˜ƒ5ÛþÓ0¥EX"ÓTY›‚bf¶
+å£+¶W§¢'ô»®¨|@ÁíS-
+™¬)«Ø×½S_öu·ÿ¡Rn½J¥ƒó˜ÊäÔ|C‰:…öþþÄòÀˆ3á0o½¡«0'S
+¢ªEÇP¯é/øäð&¸1Ï+š"¥ZJU=¦¯…·Ë54á¤ìŒíÌ&ËqCAi\ŠÉ½fuÐÌtµÆ…µàSŒŒ|ºñàø
+Ä`©Áâ0q9Wù žxÐn™ÖÑðQB pð }£ãùÃò=Îò;ÂJ¡öèÓ3:®ãar ÃËþ†³pT€¯ßb˜þЦ2“!—Ev­* ‚e4·U†%2
+G]…¹ßs}j€{b ­ÁË£/€8k[ ê/L‰}½ðm¬ž„J £X#ìùtÃ
+º=> ˆ @1èad)¾£Ô|½&E¯íEItà¡EriË „)¯”=p÷¸é*en¡®¢0³ËP†©á"b<$„'ÛK"ô`ˆ;„
+ž¢ãtw-EòCÆñܨikSÖ@6Qµî ÀÐn¥êŸ"©U¥È˜ˆê3­áˆ° |Äâ,lÖ€¬@É–Í"¨ÄTâEÒ…³F¼,¹©˜ü²1šW~' ý•Æ "“Ûóc{E⇚ˆ%çš3Ã÷ ëak‘£¸bG©Ö¥îwܬÆK¶Ïv)øê²xA›³Þ:hãu,]Äò Eý¼,jÌbv‚Á}}ϳwAÑñSx–Á®ØÞüW€
+H‰Œ—M®\·„Wp÷p7IQ¢8v†Þ…7òÛÿ4%'ö9 w»Z?dU±ôjÝfwþË™Ÿu“—u×.#›Œù9\_ÚÒúÌ6ÚäÛÇpy¥K o2ýqyEd¶!¢Ù¤©y4“ÒdtŸ¦àÒuCXPFæ³ÛÙ¨sã03ò€ºÇèSœÅ}­ãì¥üŇŸ;ì­§š5o 3ÔÂ…c7ýüò1Z¾fÓl­3ãôý hp—¦}äçBÌÌîFåÜx¶öô}s‘è>ÂDú¹ð6lÌh~•X›!i&Þ7HiML–šûâ–ÞÍ¢÷ÁþꚯdQªÇb±wr:¢Ñ¦wÕ á÷Êñ¨`œF¦´éf]¸á€)»|ÉI’}DÛˆª°çtƒ1›5³yHR‚ÔNúê|r®0iÇ›u¨ž@&-ÎaøAjçZVÔ²—d—L›£éÜ…i TuJ®­ì5G ¨2O›Œßp:·—áºîBáYí0KšC«®qCšE•—>MV…ÆT5[Ñæd¯"€ ôaÑæÔ8O·®‚ÚÙl¤³µÖ7„oz|KéœO©²iܨå3´sŸçŠn1L¸•æ:eO( áóõãúù7„TÊ©§%؃Öÿ¿@¥ØIÊx2 1ù;òi§–œœ®¡Õ{ ÒÛ( Ì!Çy:µpŽ– ÐØ6à"M…Öí´ EOŸa%/ pw1^l-£/Q¥±´W؈fõܯ 46_v0_¥{„¥Ó|Ü1_ß`Êåø„¶cLjÓ&­ŸþÔ†¢ îT·ZÚçB‘°u EÆ=Ðs.ˆâ’è]¶'¶~[[ 'éX;%<ÊhüMѶ©ÃIl0M›Ný¦ã_ ‡rp:Áš­a›GÓ†¶ÞL§Æ!þAÑã´úQžnÍPÿ8ÄŽé®h4ʃ€tz†zXI„cL“iÕòƒB&N‚ màÂÈUQÞn½¢`I`6·ZÑ\Ô¢ìçÏFÄ¡ÉF_>0ú¢Y¾ ¡m5þs£aã jG±ã"¼7‹vø¢ûÚcBU.ÊÕŒl_û:—˯ë H&È–† c·Ñ'ë½÷ýÁ‹‡ðR±îóÑÂK=¬.‹tÏi<—mÂÔ± œ.êX^".~ÁþI)ÆÙ
+’ê2vË#¯1Æ…ÛÔ¾f­E{ìRÚ
+ÎY‚¡¸![«Ö Ü݈7”1ŠZ{ôßA¸#â£Ô‘KëOžñ{ ÜñPŠZ©æâÅäS‰mO[]Oxcè¶&:!òÐ6ËQ?P ©m²Çá—XDyÌ’&HŸý·4:CÍ,¾–ÁƒèÑDú‘µk8Kà¡›:˜+IŠ%<ã²·‚0ŒD2ûã20ÇÊ(1}>þ]Y¹mƒ¬0'–/g#2[åÃÁÿúa…38‘,ëÈoÔ®º £f[ëôbUÆÄ©M p:0ñÌG2´±HÜFZuå°Â¬W’%Æ}bdhEd²Æ±wš€uMª¾§ Ö…ñ»,ÛÛöν¥$m—»ýb€¿5Òò\<ˆÍ¤²#QòÊ,mvFFC,\~Û_П!0êHÇâ+Lãðhã³ @†.r­Ò xü3‘$Àí&³0DÇäÛÚHE‡q¹6ó ñ!^ lÍNãr8­§|¶ Ü)I„õ°KÃâ\]jâ­VÜA·ÀR !öjE¼æOA0+sˆácz0peT0žo1·c“>#À°á&‡s“A˜åY—þ'~¯’ÃFõ}§Ð»ŸÒ Ì£Æz­«£ØLZ= Þ-Ã(p²$Á©Ÿ;1,­t»åF®õ`\eôJõgŸß0ðë"*š¬èJîÁðŸZQD­N¼CQµ½é× ¤‰”ƒRH6Y Ûv¿‚¾ÿÉ™~„^ãU±‰˜Ô»]V… ã¨ÙX§§ÝB *ezÏPA0V¦9¯Zq 1°Jï ‚à‹Z:¬‚"—„WÍ—d`&¤íøoºb‰¶V© J¯¸Æf¾ÕŒCËXº^Foó˜"³ ?¤¹øÙ’ÙÄC`PyçXÅ.‘ªw×Íü_@ßHÖª¼ÿ
+Lõ--©—d¬wÓÓLµ²ZÊ7êÝò4u{°ƒ(ü1½oËX…Lªèvćòàk+I ¨&nŽ°«s\DÅÀ _Zì–’Šè„¾¼Þ/$AºÊ¹Öá2 8'—)1Ó*Æ?@l5–"‰é×V7ŽW¼¬ÈZ†7 )ªÁŽ#OFmMq²nMSP Þã¼^ $i.\+#Að°¥Ä¥Ê³—‹R"·ÝëÀ"xHÚ8ɺáÞ¢Œx³¦R*n­š£=@Þ9ÓO ¯ ¢¶XE„vœé‚Z´”˜\†¶ì”Ò01£+AÑkÛ³±!Ä9œAÎýÒ„´t’\Eä¼xŒD£]|†%nÕÓ
+Ì,®ø¸†F=†’`µë·úŠþgŠüÙ­¨x"‰ Чuª\JÀ¿N£dÙzWpÈéÕÌF$—¸nŲõx©ß]š©·¥Tþ6¿2]%ðbø6¹Š†ð„7Á)qåèdð5ψª þÁ¡qÿ/›Çüu¨P{}*ò oÍTüĘŸqºÉeð22LYÎR0„£lוÐdCT”Õ¯Kï·Ö¯Ä§üŽŒ½¶U{[ ëXò¥Ü<,!ê¾·9#°Aî÷D¸7¢é•5aÍ+ˆ ¯\úTߤðVbҌǸWg«u‰sMé§ÔX´†™“{É|·Nå[ Ñ\[wFW\k Xy'••æ¢9“
+¤)û¨¨<kRXÉ9A—xè^ÛÅd Hï‹«˜"f‚Ÿó
+‚ÃZàvHœóÜA?×ï2ƒW°6r>ŽÂc.gÏ“ô¢¦ gÇdZêGÐOifA¤ÆÛäu5ø4ë]¸üKeWŒy\©‰_3óØÐ÷TëØ×ÈrW›×¤A èÊ„¯ed–· ïœ8‰brÑ$úYÂSŠ³–©Ó0`Ë”ðWÙCÍ1"Ì4™¨'Yé2ƒÉì #µŽ¦rüYlö3³áÛ?Œ—9r½„Oðî L`_lººÅïR÷wß—4#¦QSè%>“AðìQ¤ŒeÙÞÕÆ@~–ÃíSX€‰ªð3;°µ¦âÞ˜èÊôF&UÉ6ï/í
+Ï3w‘I=Àãò¬$Gá×–¶
+_3\ûqôÓ³1+–•—èYuíF‡—m§Í3Uâ
+oôø²xwsÈ—”-\bóæñ4Çð#â‚=«ûK %Ç$õ'ÈÓ³ö a»öá
+L?#ÁT6m;q©æé2±1œŠÔ: onõËL-›XL5é–UHuI&Cš—©õ@ƒCÐg\FS³€È‹ðTd.ÈL|N¤]”14%·Ò4_i篠ÃQA{:˜€9hS"³!˜¶ÆÿT¦²Sˆ tª#eeÛrBæ­Yà i„$ÍQžq ëKFÁc )Ó "!c0z¯íá2 –ÙÏX­Î“"<«éÒ·0 à¼(²Áô»åõ omÚ_:@Ê!§B[ö9÷Ë —­‰¦0Õî“ÆKNUîƺ¿Šw«Ìx©h1âÓQÛ?^yà‰Uœœ«Û¦d}éÞnçœÛÌ8—¹Ožû¦s‚±H&Ñ'­nŸkÐÈ=¬ªÌ^z€¼õégëDJKò¦gâü·Ú 3e­è¯b1_ÑçêÑ0Ç×n˜ïOnôW×`â¦Xe¤‹ ?½˜Ìjtဎ;ñ‹5à© ªþ!FŽW¤çvl¨Ž}‚ [çÖ•àØM²\л>Ú^yY³”ç¦o2
+·S™»pê{wg›N3âtÛ9æ>3Îeî£ç>êá77âîÁ»ù}Ÿ¾®µ#„QvH:]4xs#êÖÄÙL^‘|pbº8¾uz‘ßï³ØkH•DÅÇõOÃ…˜¨P”ШÍÇ çuÇ×>Ädùv™ŠÑ‡•à±¦l`Íh±mÇÔòÖ(«ÙÒ¸6,dÍ"]_ŽÞÙã2¯±ç§™£6ÖPcr4fƒ¹Åg/2./ÐÂ5…X(†ÝíóÚÔKª£qA/sEóbžÓèSùÕ¸>Y=ùᜑS‘*ô¶…÷… ›Aªk\´'ÙCm ‰…#/+(ÇÈÜzosc!#T“rXcæ|ê¶?æ8Wéâ*ÍIJÎÅŽ§+5¼AÖ»Ùü4Õ¡ûdˆ¤ˆ#e¿’q&Áj²Ó…`¸xRA|gc?üÝ'Pk‚ª£ãÔo%Ž}r\᯻¼V>b6†FèÁ8˜›|ÈÌN 3>i`äÒ<®¥„æK)˜ñfØÙ’«ÈA¢¢^÷u=¼Gˆ?Œ4üAx5;Á<ñÃ1î¨Ú
+Xäá2üÏIòH5úo
+/È„*`ÈSñœ+ƒÒ8¼»ö ‡Að@·¥ðnssç£1=‹sˆòQáCÙÏF9áløqÎ96ÇeÎésåMñ»Cp6áFp¿íÓ×µu|†ŒC{‡§ýÿV;{ï„H¾žëƒA8@ó_s¯72º =Î&}1ê)$@1ÃkL3Íd€Fœ\1± eÌÕ ÓcN
+­7éhmV)@ )Åè0‡Ò% 0¥œD¡u£)1n.Åõwƪ‹³lÔg¶ë´xwbgîšØ‘P‘¶¿†ÁÒµ»¿| Ê”ž}C
+UšO žZFNì×d/ RÔt‚Ý_FŽF£%”]Cl"ó!{ÛÉÓÒàØ£ß ™ZŒ ¤Ó£YGqŸ cÈ£È6xŸŒ'y8§©`9”jŠY‚2ñŠ),Hå‡b°²?Eƒ¯rË×V0ƒ1°þ±àã6¨B折̊ƒc„ö%!õ*…œ¸zdsAÎiGD™Ù¬VÙ\œ§åðÑÈš(Ên†ø#Ò¶[sGKèøÜôýÉ–.ì)õ!óôÒ×¥°ú9,K¦=`ا /Lk›„HQUÜaž`¶Î-’A&‰vTÁ·Ž4£ûdëXb ïL€™?äË´+f$yIË2øu!ØÂ
+ñq <HÊíd\h`AXXšEÌÂ>X˲T’<„”Ð÷1Qâj8tŸ4D—„©ÔÒºOSa’ ôŽù¦¿ä œAÛÚUÔf&\™êz9Á7P@¨7ïé`mg“èúª1§Ö€Á‰»W¤"h#ËO,ÈÑÍ7„¾„‡"t0ÂuæðÆË$;Ž$¢'¨;ä ø|ÖÝKÝB[êþÛúG¤Ä d‰›z%ôp 6”ð– KmFåí~ŽXF1²íj€
+6Åm´ËŽÐî5ãƒfýK dw¼Z«×›R×›¡’C^¤MŽàc…œècØIT
+£^"º6wY³•Hj¾wóK'Ú«48pSÖ‚TAœa0Zê9G‘
+0×6Ø9XÁÍØyÚðþ Ø”>Ç°QE%_ìéùÔ½ˆÁÁðŸÌïœÃ2KD1€û’%ùDN·Uô©Aâ‘È>M2Ò•¦Ë¿¤è60!lt½Cî‘0Ôó¡%;«nÍ4ßÀï/0–p%G<­/(9—(3X²ƒøÅÙïép:„!ÁëÀ¬â<&¤LG<s‘¥.ïÁ*c§ƒt¥]OƒÅ€¼ÄÂâ¡Šú⸵ä+uŒŽ'ÛÁÙv3/t§€Õ¤õˆÔÕ˜ÏÐÞ‡)éÌcVüN5í7çað$Ãßžy¡ ‚ÌLXI‚h8."ûmØ,è…L‚KµO)SL©q^QŠÛk«É"êŸ\ŽÜ}}Ê-W…úQLûï%ŦÀLYŠÕüK÷"¢Ÿ‰¦Ú1ØLº¾hëö ÝáBêUƒ±gâàž$ œ’)ü£ª9×q탒v`›ýœÆR }K^Ò ÊSB[»o:úÈa-ÌùaJ¶òa/ßø¥ä=})úaqÚÒ%õú|S¸D5,v>Ëc¾h03·j²« î§d°Ã-u–¬^bÊ(‘JØ^’ù»Á——‰‡Pra‘ÑÙóx:º¶=EQÀø”” ,ƒd) î–hu÷žÃ(xcƒaÅ—~~0e­ +ax\$U»ŠÀ"­º–¦¯ŽM…¦¢ØaêSÚ8ǧÃú3Æ%j {(1Ï6tv~þUü}¾)¹`Ö€ î|×Âb~c^ƒt$º‡£ŒR·K—9‡êÄ‹¹ð‡Ëòi^žÜ†± äNŽZçá|c†) gÇf°À08©çá™…å_y»{çÏi¡+±îJð‰Q™x¼C)Ý»¤’`\eX#óÞ´ÀK–{ÈÄ!
+1éi ZEE–³=ô×Yrí-/kéG%ˆÂb=0šÉ!ÜÕî˜éá)aÁPBô£_€À£)hâ~ÿû'*"{³ Mqõ æ^dŒWX_V¡úÇ6­‘™XÖdJØÌ$Qa›¹èèŠT:]L~
+ûÖˆ„«4ý>÷¢/úúùþaAïÂÑÐ}­Mû(ÿÆDþ²"¸6¡Oä y-:W†øᶙíþØ‘k‰IRcKÕJŸV’DwS>n´ DcEx°‡ç tÀ5ï'Û›æh’ùb%¼ªñZ¸røöñéÆO‘œvà^d„Haƒa5Ì÷‹naÀ¾ŸÐWjZ}[s»6€Ç39¸´ü!ýcw)£ÜÞzȱt#‹³Â-dÚ8ìf?) Zff
+õ³féŒ4:Þ!ˆ­-×Þ„P£Xyð2æ47‚Èõü;Áà3L­ýäh5&¡zTWot-V\âL?º ¶ð¡’LaÚ[¼ÓÂZ%u*V’€´x yiöœòø¸žmp] ¶ ÷@ãå©Ç˜Vz†Oëüµ6œßmG+Mä*(¼PB¬aqtt;(9_Ây£KSº¾Âs&z,ÛÁ×[ö¹'{:´¬D)†‡g¶À×Ô¢Tµ¥Ç,FP„LRh­|m‚að1$o"À“Àf<ΕaöÛù¢D“p•3ž‘NAµ_§|)9O—å€ÿ1]‡[‚sÈ3K– ù9¹íÙxW*ÍçYñš‚=æa
+•Â3£þÕ h¸ð?vôùÓÚ8§â©ºÊG+¤'þgd±x@ÜÂ"ºt¶§û§þåW ¢t±b¤ä;»wÞŒ
+,VßOÀ¦á1éÁ4 E«ÙBêäà”ÕÒT-o(˜ÑÖ9µ=âsäeñ6ÈêêÛ÷9±QæÒh€• ’ ­
+`Í÷ûÓ>µE¶•è5,Ó½º_ƒ?€ŸÐKGwŽ*
+\.™‹ÄgYؼ®FYÁP|Vù^Luš¿0]„øHÚ‡´µî´wùNM$M|KÂÛý}QEðQSÂo2ŸÂ gÌú^×J…ȯð³Ó#á:¸á=º=.☿ÔCí~Dd˜'`‚-°±Ãc
+‘`|m“-#½N§s™ÁÅ;YÜ  3ÒØsYP‰ HÚÄטï71˜8sBÑ{X¥Þ†ò1$ß'h4áNº•…¤ˆY”Õ
+iÀ<è‰&ÊÞxá2ïxâçÛü-`ÿZ¨•?]X÷V9!°â9š­ÓB”i¶3Ý2õ1ãÿy&´d6HœlÛÜ¥9þXÆð7‡B.Õí Ë9Mø*³Ìi!2òc/ÍBX£¥Æív‰eÍ­“&›¸þÜÅ4Õd-œ<èЪ`‹17û ˆÄ²úACšINÕÆ=&ò¬ )„@='åÝ‹¹U!ÍÞ+æfß¾EYŒ‰ŸTqÝš¿Èñ²CàëÖ—j¾¸ºoÊ…1ó\¿§Ý±%‚FœªAZ«O×–d1tùE’â> FÍ!Æ©YˆŠ’ãÊ»ö­T^M—À L£h”3™apJåPV…Q²<qõM/E¥‡ƒàØfã,|\Vˆ~O
+Õ¶ÒeN×°VUÖjõ{Ð+ø’ñ9F¤ƒÝRî—µºð‚Ê@#zÇ·¹†i
+HûÓá*M²UÔ
+éŽÊ«„è(
+“¥"».H·U7_ÛF
+ïÑS43š`I§°¤“ó¯Ñ”aéØÞR´BîH}wBV]°Q8Q­o–¨ñd )àôá÷1ÉÛë’8îD™ œû¸æÅš8qU_šî8NÜ-NÈ&fbS—ÔjÒ…C¾M“§¼B.n&
+›ÙûÒ({ªBâ2sG9Oè¸
+VÞꎎãD(î®Rñø…X&
+°ømŒ¤Gg˜^~{›ý.è2xý¼ BØGéXYRæ&Sd†!¹üµs_2 `‘–£…PAü‡Ù–"€:',„hêÉO4ü³¢‘â‘÷ÏÃÖeJŸ…gA‹Äɲ–,„áˆÚò…â„ükHÙ•©ò˜y¸ët¤Ò-Y'lN™y©àV4S#(òµíI÷ ¶^¦žC
+üI”Ñ<‚'Êj)´²ü«PXù€
+Ó2'$µ­Ê³)BÈ_ƛӆ5¹Â&ϵSQoËñjÜ‹Tøó̇u§•‡H‘À¼ ŸÄd!¸òö•1@O¡aKë<:I\ýY‰·›7Ñ¢Fóne)ø&Ù‹S;7‡µ±4–?¶Ü!‰ÁU‚ÌÈÞXÃdd­æw——Í[—š`ð@3xí®#k´2E,Ã<p^Up4o¶z¨#…¼}:ãmƒGF2b;%z€K‘Æš½S°¡”æÝmFAîØ<Y@ÌfÄht/ëÒÓ‘©µhÉtb^ˆïÇ‹ÑLÖ•ja¬;]‹ÕÛC ¢<…{m±oÅ[]¤x_ûòzÂaT „i`Âørrp‡ó[.=8§$FS_i*ráÜßiJÎ1~ˆ[R¯y(PFæÊfOøm•Z!ù}ï4¤ô
+–³mŸm@ó»ÚN÷n v˜Ê$
+÷µ/¯ëâƒÂã
+´*ojÙ¼÷ï%ègõ w$snÏ
+Ìê][{]+«Ÿq|zqìó¤È hÕÑ£+J¤¼K€4R„ò|dø9ê~„•jž<rk–,¹}•ïrÆ­ÿ<'ï܆ۛ—Õ›<:Ň–õün®ÔÒä¦m!>§çlº³e > „–gùL™"æPZØ·¢J©óÆ|Å}w¶:c
+j# /KørâZw"x${G…]¥ˆëÁh
+fìö¼ñ[ÚWZ0êîÏkCRåZÚãXk3@`¿àü6"qñTÈu«dæ͈¤÷cæÃLs¬þˆtÏÂÍï>ú¦ð=~ýŸ 5¿Ðþ\¨˜NN±Ø&… 
+Q¢>Cóß4pµº\=ôÚ„`<<ÑÃ·¨U2m(LL¦Œá)V Uº„ÑEå²-ÃH†É
+''†ÑíÒ(L;ð!R´ð”†D¤C‘»§xù~£®X@±K1”G–#ÝAuÑŠ®¥hrP¸\|ì¦`r X ¡ž¦…ðG±ûyFCBž¿Øx™ÜGäÁö klÔ)š­"Ï(z4“Û ó­Ò»4Ð4ÆŽ
+•äXñ*ΡQ5
+ä€ì«_[Â4!¿ý p,Ç,XŒ”—íBãðe¯‚NÍ»‰LZm *¨ ¬§aO¾4¡LûK!Ȥ‡6§¸ùKþHb–7!"=A*©Þð‚â£ÔCÍ™Çøyt)DŽ<rJ³ ÜÒÑ::°ó5“ ]õÎ `a¯¢wÇ
+‘¯L‡Ñ«þçqAz/hÔT«»’ñ9†ÒAQémž>­ªð‚
+#AïZá"Ì9ä=¯VƒÑÜeô®YXï5œ–Š‡¹_Í‚¾ÂSi<óŒÀº<kî#¿å4ðKÈ*
+\™Q®šï9Ô íb$Úí¬ÃïcÒ°´eP9’îÃí
+·†f À}'ÿ‘§ù¶ Aœ8ƒÊÐŽÙ&‘…°Ïߢ¿*Ò«JŽR‡SYü½¼P~+¤¶tq<Πíþ§KˆO%ôaÖe`{ü¨kˆ[[ÎÖwHœ…%ša 9SÀ.¬ÕòÅ=ñÇlÎHļ?Eß@jbŽÝ‰‰)ݪî'ëÿj¢úI9½Ù4µ0𸕠ËùÔ¤¼Dvrh‡g,>*–ÿÌ'Ï?˜<žƒ¬Œ²ö!i—ßrêBTª
+bYëÀ‰BFˆÓvLèï`Éb.¾xMã
+º6Ì.sÆlaúÀÊŸKx*9
+ò+³G GWÖ®E_«ÉC °zÅ…d¾d8q.é”ñW6¡? Üf’]V‘µÃO(€ µ‡`¹{Ì¢òS¬—÷˜u¨Ïµvì®ùÝÜ·›üîÓ¼mˆ–qÂóœ4On|i"Ab(¦ýv™í³®q ¾7´ƒ„É…§
+õMg ¤ 2)>v[°g¤¨âºLF åæ;<¯kæàûaEL~1\N…IúÆÖø»¹/tÅö6þ¨~¿–m“znG8é fbˆ P• ìjN—oÂñ˜‡8 0)$(‡ðš¦ã‚'06™Ç~F2 Éø*›'_F1c[jø Ü(_Ö»0¨Mò—· {bÁÙTÄ[«.I¢
+±5] ”áeçbma‹"Ͷ8ìk„'65R ï@ƒpaµ˜¡;ÔdÅÂþQXÝ×ÐŽðøt\—Åc
+`eÞ¡‹È4:?Ç›Ó؈R≠êך¯_¼þc—2ÞLä°Îqœ¶õϱ†˜
+-:j¾é„ŠM GI ó
+$¤oŒ</"E¨«Ìwú8mk­(H–ì2¾ ûYþ«d°M(ì²QiÅ.fKâXëq-‚[™1@È_7E±7šÎÏ¡];Œ|ÕE‘;]àðÅ—™AØv$Â’ÚO¢ÄI8‹Ä <Ât1•ˆV*´Õc££ˆ´~ z\Ç YB½ý·dàBµpÆ~þÎuâ—Û\‘sxÕO½9Bý{ƒ%ßõù‹•ùØίtòŽ­ÄYž>÷ç¦(„`›•¥rT(UI<\'÷ÃP*œ$7|v?j!Nѳ¶vt?šäCÆœálZ®s?˜A,ZÃç…t4?`yà(±á,ܾ ¨ew}µ
+ L×Ùá flÙ é MÌDŽ\ƒ×AëiÑtóÃ{¦¼ª}gGhQ`»y~- ʹV2aJ@’å¼1?§¢çþu¬÷ÓÐK1µÙYÈiCöp–mH@6G@ÖÃI‰AJÝÅ£ü4®ª¥þð8ñÑE®%o5Å[wAgÊ%h
+¸ž™dmæQMLù­dá†ÕDþÁÞúø •'k‘dÐ˾ 7H w-:O`šÀ²÷X¹°D,º¾fGõÁØŒ §gvšfÉ0¯k_d*’ÌÎð‹N
+ËgÈ ´;sö4ðlf)Ád`xYܱûGÑ&ô=Š¦(›9Ï#ªçƒeQ¦’Ò§EAÉ¢¼÷G1 ¤od%+aÙÙo¢kÝ\#B.çAð°’PÒú¯z¢ï#MX³5‘ û-Vîm^k>nj2{MåðÕkmûǺ·†ž
+\'!µ¢AŸ/@O<Ô•ÙTP7·æ=½n\1úVÇ‹ürçó-¿h
+.Ø9›rª; ›O Åcƒpo>gý,r$_^«éqhш&ÄAnì/ŽA)ØÙ«Ë€9„ß'c\ ›ä]èÛa×OåþÕýKp«0 œ{e.Š§v²OVµž'H´ÐÐv.\ä€å†à[m! ¶* ö;+ˆ¡EŠ)¾Þ„þY®øÓ@%-­ò’kóë ¾N>%‘övžÅ˜ó#Íl Sâ_µôÛµ‘kÿK¥”jM—•¤Q)êk1ÙrŒ8wD»×
+„-D]*ƒVüñ~ÊÉð'ýS•ÔC£DOFãÂ.nûS¹ÉìB˱¢ Eáhüs3£ŽÈ:úpòp éÖ¼/·6¹csdÙiA„$}I@-"Ì3u&GËÄñ¶Y{
+³?]<¡ ÐtÝæÕ™Ž2Üã¼KûD¹ˆƒüS ‘reµ¤'äJƒŽº@<1ãÇ;ô¹yªEèß–)W2yàðÏt×H»˜&z6åÄŠ¤Õ€‹ÌÉ̦HH‘5&¸°4IÇû
+ƒì!ÂkŠ¬î)Gô¤5{žI7€:©ÈS$ ¥Œ„ÉKëpõ±Ï 7ÍPÆcº‘„
+‚h±Î¡bõšÇT ^x!oéS&²«9AV ¼ Æ2Iƒ@.Q9íé‚ÎñCö
+å‡,ZÝF•TìÎêžø÷yæþŽÁÎ Í rÏ¿¿dOFc¶±Û"ÚQµÁ: 0ÈÆö/yƒr™4øÑ»~I¢°Þ¢ö4 J5¯è¿ U©Äìº(CX¬©2W@”fÂ)_ÉDŸjy0œ³ú ÏÁ©P–r±Wd¡EüÚ ¯ ºAè,£¾FwP6ÓHq›¥[Ó"õd«âÏÒó±,ε‡/kXa¤y `}0ø\·ýŠ)¬óóð¦Ð 4È!é0Þ©qj ã&ç Û!d1yÆK\§ÆL WkHÕ §ìržÄŠ…¸èœçŽßnsgNðª;Ÿ‹Qý©Àä¡Q?Þ™_¾$‘ —†"§’ƒã~¾
+ g“Ìi…µÂà^gãeôaLFéÛ—ôgã?C &²`¾ð¢ÜsØ·’YrêЇk%uŠx÷zt[!ÉjΑ¦ZúПØR¢ópÐK ÿì:Hq)p®Ø9ò GÞ4I!^)ò²¡ˆ¤òâªÌVg{a±gx ÜZ¥ÉûäVêu¸†ÓUî_ÅFÇxU?…{MAæe`©%+×æJ91ÀŒñÚg’j×â5†WXr²Ø­ÄÓ¯ÑHóÈ2-©¦æŸúËpþZ’m²øöeÎCÄÛ’ 0,I9pí “: •ÿLjG9öž²)½êmISDK-É#‘]œ‚)‰ùÑÍ›ÜDc›OyŠ-I îp*™ž£
+‡-ù\¾kŠ?cEógj úɵ™/¦uקnç Ù‘‰ÛXé:¡‰‘Ûû@oF’WìíŒçú4Ѩַ/(aZ¼Œ²5^úš KÁéÄ;+rCH6veK¡ˆkÛµpQbIG]#|úäTù¹„·sî`wAnÆÎ6yÚè! j\ }&FÒ6[ïGƨ_c
+f´=mN®»¼€ô¡Ö,…ëSÿŸÊ¿–WòïÊdð× æãgBZu«›¬©›Šª~Ÿ:äîuäwZk% \áD·GöõEáÅ)D;e¿9Cè+›%ùâY:*˜ˆ«(¡E°š£¥‚a’h!T+‚Σµ8Aj„φ¥hߪ–×UÄ?´ ãRž'±À‰‹ZŠ#¦¼ò"¹‹!ãCݘX²ôäŦloƒîŽß>·Wfëʽì× ø”Ň™/™þs÷ø²†y*¢;{´{TE¹ìj:õ¶4îÝvšÊ1H «píçð
+>·ß´Y}ôh†ÓÊ™L[‚ ëôêÑX g€0ûÍøýeŒ~1O—Êo"-NïœúíAhRüÁZ­æ›âT?jœ5ê
+å ÅKAÏÔÉhÂÉi Ëe b,«<úÎÆÄ–p¬$%@R–£²0åŠRMéò@`©æ›ŠŽù¡ˆ´O,}GMr I)ô#É`X<™uÚ燛$DèÆÉ›~BùøºyšŠ‘B"þ Î+$‘µìVmù(;Àarò,i_CŠuž’ÁjqÕkDÚa×”%؉¤¾É3›t^7Çêis7óL»b…“G5uœ•˜R_•=òAÍ? h:ÂUÛ
+†+_èbÙ;R¡¹cÔóÄՙѴB“
+êªzè³
+²ûX<@Áüòì
+²A5LìÚÑ3K®hASÕvžh¿mÄp&}’»
+j!þ-³ÐBÑ ië(½ Á€òBàž4— Z˜º —ÚŒû¯AchON@…¬Z;ìVé3"µ‹³‰ÀB2c…Ng³þd¾OÓ,˜·„P#ùÀÃ[UIJñ{_ÃpF¬[ØÁîI½žÃ¼ËîIN—çÐ+ƒM&USHI%îé8c¨ƒÿ¢Û:²²
+ôm–,K•šRH%=
+Ä¢% ²0–íj…îïžï¯(*ÀÅxüP¥ª>w×i‹gƒî gWí%ý$U‰•ØPˇÅ`ñÐÜ¢„>¾ó,Q?n—}/ˆqâB>RKƒÊ[À¾>Lí*dªKl]>$AÝaQ5[®æð/±_€Mvæ—]%B”7`ýÏD'¸¶Ên
+Áa ìHni5¬t¢ê‹6†¹ˆ˜²[ˆ_5–ŠgÂ^oαiª püzÍÿÇìÖ
+²‚/°`¢rÓ*× gѧˤ“X)Ÿ ᶬé‹åÕÁF)Öoãªê$¹CNæÑ—OD›LyÏëØ× ‚R;¡#˯Á_4à¹v²än°[8¥¨2–„ãe›Ý4忤ö
+Œ/†
+ö Z²~’h?›YÇ>”G}öþ&äiJþs ºÌû]Ä&L)ˆóÝ Ë
+¾Üö­˜'L¸.×sЇáKÿ‚büøX/(0›˜¨J™ _nA}Ëð*r©¯òÒ¨ìáANò1¢öe½Ê 5c“"¤òs¸iJÂYc±p(F£ í·±³kHù§Ùì…EE0’¥Lž°ð
+A™/Þg Vf ¸.ƒö>C5=AsÛÝ™X$%I¦Z .uc XàÒ=„—²È,‘°Bšøo+ÍBbð64($ºÏUüœõ†AV
+ò‰é.–¯˜B¤¤ÜÃìÊŽ—6ˆm QlÚ_ƒž\ㇽ‡£i˜KÔù·ƒžäó$)ɪUIǾ,3H«H+‰ƒ“8ê\,D”’ÚÖȇÌùñ2Ç‘+‚è úeË(p_LAcÊÕ „ñ$sî¯Iþú3KÓåŸLæYÔvÌN+ÛÑÃõøÑLÂ`–­ÓdWƒÑ/†ÊN3Ũmƨ‹™Â1QÝã@~Zgx".LÏ»¯¸ŸSÔ}S$w¹;l£L"^$,HR{I¥SI/Ì9mÊ
+Ö¯ìTí%48=cÇ„*‚H”º“ƒßáVcXAèv$®¦ÁØA¥ÐWÕÊãÄ85ײbalRý,è6¿>1£¶Ÿ¦I÷dZŸWmÇ`íH*¼"Ókû© B¦*7˜Wô¥Ó-ÃäÄLð†Ü—(T¤Q¶†@®xHðÐ6ªÂÕ!¡{ØÉ)&Õ¬ v
+R¡V%ìaÇéR¤|L]ÄÍ -º,¡9ÝÄúŠN™’çt"ÁÜ0$à ¯/š‡V‹ÿ¤Á¶Š>™5,~f€ 
+@)_@>ÔéÛ5uQÓÉR™š7ä¿W9ùƒµmù‚ NÐ1åÎm'[üD¢‹/?ÞÂãë¿o_þ{‹Þzè|ÅP\Ï…*‘:iÿ4öpA=HàéCjö0NG”pƒcA&Žs?©Ñ4–6É襵“¡F1ʉQkÇDAÛìho1•—®pOÕ¨ë ¢‚ךæ2M?ñ¢!HÁ²AH óÐõYr ºi<Í|ÅñÃî1ã© B[O_s¤Xºì¶Ô[n+X',£c,H¶æ²©M³%ìxCül&À¹,pRVê³þ8#¦ä6zmhíòÞ}C¬7%ŽC9xú§`ª0ûÌL4†Q$¸ ÚŠ¬§ÁþfrE$õzQÂ%Ã;¼ªí›²\=ªíb215Øcsï+TSR³7pŒßz¼®dùÝQûuÓß›X­¬ßÛSkî„eiߺϣ4‚˶v?1>õ|üVœ*E{j“DlŠ–ݕĨrQæ–§!8îWs_Õ"øþƵ+d·>1Dûœ$*Šl¼ _ ·E™$ÂaÃÍ ‚æªd–_C
+ éœ%²r„02Z¸©š{ÎÐ8rWï{!˜¬@Ú¤ªÑkw …âÊ‹áB“ßî©K¡:ÃìWZ€¬0g££ó'1ørØCÛG¯%ùn—‰T,ÔxÌK¦’…ÃÈÄ­)Å|S°:Cì×
+Té5÷ {H–UûëY‹;dÕ‚øºÃ~³{kæ×ÄW44ÁÔeÓÓ°¨·•åôª†Y|Iÿî£sLyeGnÅô$öXíÎH"’D”6ucŽi—Tƒ¼±;5„‹çF•!þ}ÕßGËìj¨8sF½*9l¡HSV@»¨ ”ra㦆άÇôݱ Ô EÖUúóºè×gbºIg¯M› ãbÀ+­CG-.ð÷ï \M—FR9r/{ ¼ÂöyA¨ß€3ðoÙÌä ̺{_9ñJ…95RHK]§
+H‰”—AŽc9DOPwðæCEŠZg/ëÌ*ëþÛy”ô]¶ŒÊÝmgXÉ`0hZ¯!½5®½¶G7¿Zm¥©[7•Ç H”®½ ©ÅÚããÇð§K­Z×jm¨«ã’î@8§yü^ wo¥—î¾0.ü&¢ÔÒåñ91^‹[t± ªÝ¢‰òë#!£µêÝZ-Òö]¥ö¦¦Íl
+ ‹ØGò®‹ªC§È‚0Kª¦ò:ÝX‚ø<p6i×7(˜7æÌ-óœÙu=E\bARB <ÿšzŽÁZ,Ï?@ÖU|ƒ§×joÎi%¥ ¯Þ†½y¦ÏBÑnàmTP«†í®o²CEf6Ô79~…ü»Tû¦LÚ,Ka„‡Óc(æÚrè0sŽAQ—”EúŽù{õœ*ƒs£?s±±Ç)Å@Ô0Ò%í½KõYW=—üpÎ3q¯y&à1ªg"ó ê‡1Ew×1¯ÝPÐ^ͽ"Š¾ü»Rwë5Í€rm8­K«÷*’Ç'‘£žó+èÕ®;Øë¿¿i©†]‘+%“Ö©Ýf+•FãYØ0˜¿ Ã«<ýua;½êˆµ 5í¢OÐ麿ƒàiŠ;ìÓÑfN %+´¼v&ÀcB ›&[·áo,€ÀŸ4‚ÆãdÜÛ¶û„”TöØvË1µ°ºp’ÙmçK¤¯IŸ›ý
+ÖÔë×N€ËÈÙÝçöáWîEq 8W娦C'‡c0‰À·6žsçb™ˆìK,À(uAžê0_‹1MwÊþ8Õê™AŸ„ÔûZm\j¤{§ó.d/ ŒÊq¸gf 
+V©Q+3Ý ;2¢òFn;c—¥sÂ{$]ö‹qJMr€N­›©ú—§ÉMˆNa¼Z웈»±°7Êmkr•ÄXô¥@0²†wW‚ßœ ¼T–«Ìß@þ`èÇèÄõÆ¢ƒª§½T³ÿôÒ§ë¾zÒ„ck=ƒR_d®u®rì!e÷Ã~õ{‚’Á]¤ª˜—0z×Ó¨+…ísÈò,éׄymõó½!ø㑃\€ÎòR¡™i‰Ñl¯¨8+ȇÁ³Úæ9%9eTÜboX„ÊûÃÙm×UEs× $J~ÂÒ#³¼zYzÍÊò`ÐÏ7 :&¨ Ë÷¹@¤§³¢ÆÚ1r9 üÌw¼tÍõ ÒA’ o#’³¸P&kó‰€Ó,_8ˆ¯ìàkÓâàè—¾ÐUy.ÿ–[¢YB2g¼gÌcJŽ[ÞL©Æ›Zý¥æ_Û' ˜²’ì­kyjìE„K‡¢–86– âÓ€¸ç{Í TÜ™¤ÂB1
+&äFrÇ<`-¬¿EV Ä
+¢v>¿*8ÏÙ쯲ñMPÃûAܲå>߀øDÉ¦Ì¼Õ ;Ç›lo©ßÊîš³lÕ SÃ(tñvH¨*#1'äbF«RrÞÃe¤À(Ö:…Ód#•í¶6˜P¯­þDm™[bñ‚ NÎkÊù¨ÃŽQx3ry;ú"ò>!dª;~âkÄ[^Kµ¼ï›¼ ‰|FvoÛ7r¹âÈ=áÑ‘©àóm{÷LŽø‰™_Éi¹*›e¤ŽÓ;¥ìØ’÷»Luà´[½Ô’¬4]VX9ì»tòRºö$…ˆÖ3³Ó*‚â*mBfr[«1·Ëþò
+bÉ2 .ë鯞n{Â|~çE_nBù1Ú–D/Ø…³›
+J±´MV5¥%tsê„•0ÌyÙî&ž%ý  å¡Ê†)âÒ#Tˆ3ÿNª±Œr"2ÒÂu–<mÊ8è—Ñ!šWyt™ÂŠi‚ Š ½’î‘_i‚Úo3e" ù6× M(„z““ÓDô…@8þcÐ;M„A¯4!­k[]·2…Ñùµ
+à€r—Ò„ÒŽ[6‰
+Ì‘aWĈ¾éüc!ÿúF µ/_§åF®~*®ðƒ†6£è(¨Î¥’†ŽP § fÀCrÀQ
+ÁJúfqAO*€n.›iÀB3'Hù:îÀ
+âÍöÖ‘ã6’‘2öç²á:krXBHÛuÜAº(d~DE¯[¡ÎxE¦®F\ôÏ £v¤Œ)- |w0a„1Ñ8ÓhÝNz°@Šôsj£awîë¼[ê˜ ]7n"ÉÀ)òkRNeÁ],–ÑÓe}˜RŠ&Z6àG2ÞC¬d ÝÊn
+çB•Æ1µ$ØóÓДޘ耕5ÊBlwEjZ~ÝÙi^ºÕÔÏŒN×Q7
+Z‘Rû|¶®àîl_>„`þL¬¸®oõ‡îR#ò_55Æž‡váäˆMÓ±Ô„AgÚ«Ê alÊUÅÙä0¤ä Œ²¦©F!?œüDÐYBùî(JoðîA=ŸS¸hlÊ°œï4V’,ðn_ÜQ¥‘8¤s’‰gðAIã„€”¨¬Jw;° QW=ÀÙŠñ Ü&ýMplA…©…ŒW˜ŸœÒ[S:°ûCÓ(+`ÙÛ<!²O&¨ÅõŽJî°'?Ón°7S2\ÜxÎL@[®ÓËj8êds5&DŸMA€2Ï–-C‘ˆ7¸%ûd
+ ɧ¡!1´g§RQ²›tißé‚ðT
+Z£Çš¼'ódÈœ›|ÒÓ£ÐÙØeíaH¶AeJ ºI#™ËøK ‚~›ý VÜû9Ay€Ð*#L0´ï‘y^‹¢&©Ö™{ëbøÀŽæ×ûÆ4^CiûûH°†4 ëp†NM9IÝç!“²9“n ³ùa;‰9:ÿ$*^F^8Áþ2y3%jµ“U1}ÌiQS¦O á·[Ò=àL/Q~Ç#õž‡ò öz(¨‡» §mŽ!/Œú”Íš)KêÈKæ°ùh/º/œmÐ
+8ÆG;_z3‡FGb”œõu Aj
+FHÝBº½#ÕÝÝb6©iõ'ô<
+ZùàÒ|
+Ø#®ÔÀ©Š(ˆ^']¸D­¦P¸ ³’Ý‹»rÑÈCJ9ã>!€5£Ý×¼Žá¢ŠÒc,Õ‹b"ñ˜8ÿy7ô¥RÄM‡­±ñ£m è8´.Z|S|@cí“¢*‹÷ÌâZ£Ó`!ò:Íu]’^`< èX?*Țį|ËÏ˵“˜oµuÎX|›?Z&×hÃr.°§’ù^ºˆ÷ö¡×É#(@=o–ÕpÔäV?è/7ß÷Rè\Vƒê'—,¯RÚjuqãÁU(þÌv-zP3!ÕÓÞuT’ËKàÈçD£\üs‚(›%äóæ»/²›‰ãÔ› °¢aßH`=!ôâbzÛ2f4…?.yU%VÂôêÏÌ>]Ô…ùžUZ×ï…ËÓ3Š—ó5ú3ål!§ë\¦üœ¼p⫵@£>¡vÇ
+‚LkAÊkŒqs
+ô Å´{3!òSÕ3>Ü[Ƙ/8/©­z!Áê,¿8@—ÄÖi_8§¢¤rx¯=1µLj¬aÒŸÙ FƳ†É1„¤VÂe ´¬ˆíÊè×;«¦[š=ŸˆÁË1 é;^È\ŽúÀyhˆ³Ê ZmYUO~qÚ‰Z*¢Â³Œ¦u ¶ì*¹÷ª*tu©Ì½ ]È:œûó¯(èM’Ž©`Lí~'–Að…DyÍòvs @&óÎ^Æ”_Á©‹™?žYxšÞ#™‘uRHC—Ò¯¯£ŽiX'MV/(É7GÄ0¬c$µyÏ1Ç=MCÇ«&»]ŠoÅ4&×ÍEbà~6L²Ó°F‡³~D—¾4?1ÌPÖÉ@ùÑÁo1¿-FÊ€šZ<E²M…%r®UgKµ@ªÌµÎÀEýƒ̵#Q:ÏCcSäü~äü?ÚËu·ªäˆÂOpÞaÿA‚I8ôý’(?0HÑD&‘HÐ E‘e°!ÇöÄc’ðöùV÷Þ{÷<“‰`/wwU­ZµJ¶9§®Š\ eŠqViÅ õ•}².Žê¶ Õó¤7§vR+·†ÉÛs·2Dgg#£él³b±AWlÈLñ‹µ‡Òlðñ†¤RuG\8þ¹V«GaurÜ&²Õx6›‘lÂ,ÎöC­0-Ì]Ê—þ¼ ¢‰5ã¢%¥¹?× >IÔ80úeSÑQ‡º¡‡!tÖQ¨UøÔMŒÕdfþg_fõm³*Ãzâ}ur¶k© 'º{?…q
+7³)ŸÉsë˜Âµô0n–íç˼Êt„mú’að·>ÍJÊ3éCºÖ´ ;
+?q­ŠŽí:W‹±.ÌÍJoR‚Üõ§ãd³v…Â3sGkèà!]í~D͘…q¸s€àÈ&dˆ‹m¼»sØ´õP™E† A’^CËøå-øì$q~hq ”,/* "‹
+
+¾~Íš8ƒ¨Ö\egMãUŽG[µz{ŸžQ{™¹½4¾‡jóà¼ó=  qÊŽ…Û,í]>’ $»Ìx–jj.¡#c0{-åš½ÄaœÉvÉ›&Ξ³â¬0r“ØxŒšÆ®
+R0ÅXDŒÒHÌƵ_é4c§arSÅ$Ý9FçJµ šä—ÇðVæc¡ä /°#P$ä…e†äƒ;ë1e&V‚AG ÿãH—†§Ú@è’ðšažaò€x ~ÙvˆÌ© ýÃ`«x¶îT~·D·9¾A·²o—1/PÆ(“ßB± îMé‘‹ÎØ’,ùìK—Æ“uIsŽ9†W-(óêÆvšdï5=[šdeí4a´
+¾/-³Ô¤ö%§ë‹íH³Y#ê†Ñ&øøSQÒó姑×>feÛVja1TÔ'Z·íFw*ÞõïB{úÞ$º Œž¶žŠ8ÐȺ¥U¬õç®@ƒ§Ž®{×+ñÏ 1✠UŠÞÅAß[¼Ò%f-N£ã¯h@Æô
+÷¦ÿS
+›?ûÒs™é|ñ>ú÷dÍôbúëßÌtÂǯ_næl“ëQ¦Ýdºåù–5üæ#sýù¦õ…÷%…ÂÐ6R°dΰN±HÐÇQ®Äe-¨™Ìx¶š§°«áÉcÀá•e™Ö Ùqø€ÙO &n]ˆQÌtÖß³ºlwŸgnþ¾ùnsA´Š’Çšâí=füqA«Ù'
+ûëJ±-Êj¶Îñvv@b€v3(T/½Â;*{&kŸãÓ2iS`}Ââ'~Ùé®°µ¡Z¶–GV³©ÙñÓl³äc‘Û¨¬ æ’KÒ*2<‡Ý­ÄR•ž\Ưam"£«†APÏtUm‹Î0‰ã8r@ï‹úá F—ycH3Øe¶œaèÞØ-&űÌúPÆ‘£ÑHº£-&j¹7ž5ɦª…Ê#o(C¨(ó8ro˯[£7Á—qà á’‰ ï²u 5»Z0ã3W  …ÒŠ{wP‡éTuUçˆD=Q,ç†lÜ{FåzúFû¼'Ó+ÞÃÀ†‹í›/ Ú/Û$ÔU …­Q=;‚Ë. šùm"E4po½È0­Ì&Þg{àáWjd€¹~?eᥠD¹ùœ$'ÀôReh5«1
+º– ±½®ß#”q9ÕösRR4ô—Ô~Œ©ÜäÞ²ÄðM@¤ñF·Ÿ’Mp‘_0™²/W!ùÜæ
+ '¨;Ôš¬¥¥öº‚lÝÙïÈjiÝ&+™ôàÃ\š-¡÷>ƒx d¥åûëœðã
+Uh ~zÇ¡€›Wá
+N>úíß“.ÔŒÙÅlõ2àô!Ÿ°…&†¢7H†ÖLþ*çŸnøï¬i†ÏLÞd²ã‘»¨aIïþe¥„Ââê‚Í«öa”ÀFÐÇ9ú›Ò’lÍ9ÈL\¥×9œh›ÄæG~¶ûªÝn/(!Ã:Ký8÷6©õùœŠPDÓõyUÓ
+"ýh»3šà¸e¤¾}ΠV
+çòÆ#ÁËžVÁ£Á€éÖ1¤¥DõÛáå*”VÍwX:BÒ5Ú=âÞÑey>§|dþtß[~Í•m¢ gØ’JÓ27HÁq»ž‚>g2àc¶«†ÀîÊÐä‹@vŽ|±y€8­×ˆ´þ1óMì¹]ï©8#
+1Ó7äQFyótBÅ‚þ÷ªx÷¹•áæðijµuL/EiåLʘmõº!QS_!x ó_ÛTz¡»?óh1ë&&5ŽjoËXHÚ80ª¾zÏsL¼öرQ?oà•Ò×MÙvB7s2 ÄKoáuSóýã”h]Ǥh°Y.ý;¤D˜Õe‹IÁJÛcF!®rîÜBÐé9¿n2¿Ü—hwÀÄ`úoÝ”I;ÐfÚÜUK‘3Øû
+á]“Q›Õ»¹Úì¦;0\¯›²·œ[g>Ê20W¬?»ïÕï~Ž©å‚ê°A›WY
+燰Œ~‡\¶BâÓ­ªHvjsÞë)JÕ²]mó%,J£øöICøºY–¤Š›§éå&·{Ë"5"Óx©ò¹×>€q³íq{3äÆËŽ1ŸëÂÂÞ¿$J-Kx­¶™Ô ,=‚àyŽ P6+TÕG þU ¼ ’u4Ëñ|N½Ô´l-@+um0m3Üc Ëk\ØH/éüëª!¡¬õd›¤úV„ÄW/7
+q}ÆW_!¾ƒXj¯³ {°_9¹£ýº)¢€Ž0݈Á
+¯V!´W7Ú-Šß3ŒÝý’Æ«qn!äB_±~WVþgnÅ·¯’HmÆœ\Ú˜@Ì:e®3•±™b¶L[¹ ¿Ÿ!Wð4VÙ¯EÈ_óÕ—£aÏýZýþ!g˜ÕŽžÉïkBEkAº}ýâmî›A†—†ª|Åypœk'øc'žF^wÄ\GÄ}Ò‡Ý3á~-êë=äŸY„¦4+d¶Z'—ì<gÆÔ„hÖÉg¯Œb31c ˜4rò’5ðÙ¨îxNn*'¨‘öÉpwg#ü ÌÌë;€À&0ùo]™OÛéc<NÞ¾Ÿñ¢v}gáÑ5ø0w:C‰[ô}TEß¾/ì×4NÛCBn@·«Q“çùÕu‰kÞqø¡Éu=ÙÈ»(ôža(ýqgv«“|«V«hzƒ^3¼Á™«fÀ“$³¨¦ª)¾îÕàê½ÅÜ÷2§Ú "]”q·ˆ± ã4.¨t7}/Wéêu R@:N¢GüŒ§‡C ‰Ž(4íPG>l´B' ýýõ -^µgŠ]ý~p_71æû^n––ÇSþK ¯Nìõ] &|[]çØŽ‹vèÄc¹Š¤ ã¡s×ú(±{V|¦w~ÈÛ/5Zf*‹_?äݯHo3Œ\ûÑA
+jcÇ醌(¤|§?‹×Gwc> œÑCgìe]Àg¸ ò[¹ŸåpV‡L^ a,s"ì¬Û³Må3GlivÂÕs˜«|çj°¼ÁëQškª†}HéÊ 5?´s†ÙÜT­m¾©¯e(D:厂­âÊÈz"F©¶ý¥¹8”á„žk%GBjlWYéžÒW²÷±RÏUЛ
+¯BÞ´|òa÷M¡üÄ
+ùHý#èým3õùäÔ W_=ƒŽ2Š±"¿|pQrìa°Îz™# 1a…òø†×VŽ1%Ì3ÞC5CKmøž:ÒA®§Î­Îï #é6‚ Jð©šìYeå¥U*DZÆTƒLqÅ9‰ù¤ÝÃ0a`7fx
+Ujê–ê?‰§3Vœw3„$þÌ/Ú¬
+SÇé¢8ñvSlPÌC‚ĦŒ –ëÜáÛ>‚Ùó‘ÉàJN
+°Þ§B®qÌ;ˆtïßÊîñ—RG3w}`çöBÛ‰Q¼Ñªp½ÙlÕ ÀŒïÖ¢×@ÿÎ{K¯§e‚)ý˜¡ßSÑÍ -bH»Dìlµ·’«/îìeªó䪦Ù}ôæ•áaKƒf舑1ûÒ—:bÃá]pžÓ_esò8¯7@Ü6ºZÇSªñ Ýô´Kt½m=/Syçu‹bÑçÈ)`~Ÿg vÔáRn+9åbú*&&uV}‡‹,•å^Bà”¼÷AÑ«»týïÙÑ˱ÿ¹ýíÈ?ÃDËuìNü0ü}×NCK ë ¬þyGNhžzx×*õ~[édTú¼æ+¥ßÀÔöœ§^€®tˆtÐ(ëi˜¶
+îºL¤ÏY´:©ï÷[PjR²+Ѩ©à62¯M‡I‰lWA¿Ÿ à Aòoe¹Y”XgìÆ“-ݽ8òG/ROÔƒD”nP\Mí;1èG³èÇ3|†|¾æ*F/&­
+Œïšˆ
+÷¼½p÷ÀN4hnT©R¤
+õ‡ýΊÊ\Æ;ž~ kÛë„„š•ãq=ƒï'
+ÒÉ2ï·^‡–)û¢›áÀ IßjñžZŸ!—ÊNó*ïr°}¦o^•œQt§‰z¹XP´u®Ó•LMÏ
+dX^ûTÍÄRz{Þ +"íKƒ·ížë æÈ”ñT„ºë‘EQýÙÊg—^ÎÙ+ª¾„·µï}½vRg3ÏøóÅ`”çÖêýZFõÁÀþä¤eë™i-Ô’'5[Eȳ•»õ
+ÎΪ@E=òt»íÊ”«ÇHÙsn) áËi.áè† k6âä~,ç3
+E¨«…"‰é·œ
+lv-÷u´øè¦C–|´ÅJ„k«rŸÝGkIÃáT5çœ8‡`£Uç:¤_ëÂņ;È +…HâÁÂ62¢[Pq«C“nÒ¢A$
+Z …BÎò*XŒ T‰a¼ú¸q¢Ÿ«²wXuÏ‹õN(
+éÎéë: VGCÐ2-(p†oyý:‚mëQH:íÔœ°tj‹« ɸÊ`^–ÒÄÇí{»¤Ð»$¶Î‘8؈ãrŠ*HäÌa*Ä.ª£Ÿ©$½Ã3ˆ™hR¸Ùƒ œ‚o÷"©)½5–ïT›pª9Ym†Y’`Çšf;"@¨š…·þŽð‹.´¤‰¤ã“S”%ê¬ÃÆ3 A>˜ æ“ èÜH—;@àF5õ®°U¹ô 1&8gvR„ðÞ%y5Ö×êJÑx’¿ã*°™ò.xå¾J–Ô{Ñ~²qÀ1Ù§0] BP˜åÿMK€Tà(: ¨¡Q©••(° 5à]c"XIŠ²K³ÇK$
+4'"T$ûÇû©?iñ0<ò DYn”hò²HAØìIÐÏ'H+F§Z¼G¶Ù4m™E;%&'”É3<ü¯ìÛ²[Á½qIŽ¬úŠ1±3Ú$+Q&ÃWÀ,>è×Í(DW&m.T_3ü ¹·¥Tönálv[Çÿ5gäyDd)½B„Gxî$@d¤EhÑ%YÖ‘ðK0!`äØDù%Ý+˜0J‹¥ìrŽö‹cX7”%ðŽØ6vž‡qÕ¹EJ‚”ålÐ Pks AmÒZh”‘Õ UÖ¸hAkèç.X9ŽŒM\UƒðKÃС'ˆk¨ r|å#„OÙcÝ8M™áË.pœfº‘S]'ÏpHà=ü‹f€lfà=œ‚˜Cðóh§°‡ˆÈ–¬ªJe±-Ô#ØG HŽ¬D°Ô
+pÔ[7>WŠ½³vôiT "
+ãϋɨºç1»ª8ôñVÂPO{ Ù‡‡È¼™šÄsÚ§~Åa[ÂË<¨‹@¶Iz{æ—"´hÄö·HH ê©'¸r7Š÷m©åô
+¹¹ÉU¤êÈüŒP4Q·Àþâ9ªêŠ¡9Õ¡èÈBí¦/ Š–ègŽ
+óTï ¾éXÈ©瘒âC‡;2Ö±E=B¿£Èã1 ªiR©ïoBO2´kÌh:z„"
+t³,èç4*Ö‰é]
+‘ÊŸG¸œ¾8 y%þ
+z×tkÙ_45m %³fÈ\.݈WʇÂd¸*8€(µü1ˆ4§W 2X×b° Øû=Ñ«ßÛ{¦I°"RçÍ1ó™£9£(œ ÍуÎ
+È…+«Øk„ÈÆÿt€‚ü ñA7ÂÁ…äA5j Æþ NüdÅîV¾EȺðÓŸæè7áâŽpÀ>9ÿâDq HmAâ…Sql[#©”¦ä;è,ëPB  e¤Äi]™èU.‘<(=tDÌIš/)q…ÀØ êÔ eòeÒZTÇXÀD&iý" ¥Ñ¦­•Éuï¤Ä´‹È·R*‰[jµõE-
+zÁ}”Ì€þýM‰ -Ë(C™ýt'†B)6}X’ÃCH‘‚vßÀ·³ëù[ž!INiÐo~ñl)jO”±T„ 2ëÆ7XN‰½D´”v¢å”AMÌJó»ˆÀ¬`y“å/NBÞ™?ƒÞ¬åÂE u¢•Œî ªÄÍ+~ig ÛPÖRFTÈÖÕU·÷ü5Ï,«,èQ¡èX‡¹NZc…tiw¤|ÿ¢Wˆ ½_¤¦šeA?Ÿ Ìz Ýúùy™BàæV;铳Wꯠw ÛÏB w#ÚÁy‘†<gûÖÐ^.Ð'
+vl‰ Á“ £ø[BM½_ó
+ɲJ‚ö¡ê +Å6µûœ. ÉÞ ž™Qöû¡.è†R,ë
+jWPÒ¯‚Œ&Âa¡NœC¸·ašÚÏ ÈSZ
+GZCƒ¢'Û¢:dáGy5Pï‚XÔ†þEêt#uxš±uzJ²àúäójã{”ˆtD·~aü>×ESi9DS,gü¾b Ðå#ŒÏ?9#å_-c|0ûš
+yzúSÐs —ÝD‚|SìslÄj·®-]ƒe_4ƒ‹sÀ?è­gó°b¨@$þâÍcÈñUÏA
+‚[ŸM­‚ÔÏ^eE±xÏZü2n¦ÁÀTcÄeÚ‘
+˜ñúq¬›ÍØ`Šðæ^)Àà«4ÀcÜð–ò¶‚3‰—÷¥¢fR`8A)À†Imp5=»ºŸÚ.A’n‚‘=ˆˆ‘ð­a‡Æ¢34šõ¸ŒkÃW6rÒÍ ï¼<h1<Ìj4†`¡Û™oÒ B(ú¼ †l§­NÞ‹Ñ+‡¿JÌNïx,–ì|Îdh<SÒÆΘáb½n²ÀßMDgÝæ½8øÅ0Úû|þ{ôž‚ö|š%Y(³]ÂÇË4Ÿâœbá)?BùøôÇ‘8ó0Xd3€ÀˆÄ@ûcˆ6[)H/‚Åi@
+7Uö?¬©åÃ|3‘–âý¦£ëéQ!{>ó($  D‚§sKŒžµ$­,"–ƒMæQ] ’
+À‘•O—CÓƒÞ.ð<_&.½
+J@WN)?AùôtF¢Y¢…¬†ëÅ9L–3Å9¨’‚¦R±¶CÚ`$ÈQÛ¥ú™µžäÂúYöUP+õ£Y渨­mbª³ûÉ‚^$">X n˜™“[ßœCÝÊ
+m/]êò±Y*ÊØË á¤•¸q¢Räz0CMn³gŸØVK!¶h[q>±-ûçÄ2%FÖMÞÚ É0I0w=
+ÄÓª{£¼W’@Ôùœ.+†œ*ÃrÎF«e™èP%4†Ð,ê‡'ïéô¶ƒx;Öu²’DO îtËÁ¥ˆ!Ë,dï2S)œYÅõ{H—|àS²yÆ Ð¶f•©úißÔ¤6ìS»%°áÈ\ÒÂBˆâÕ¹ŸÁXÚ'°-sEˆ@<*kéŒV{”ÅÊlU÷«ZÞÀêA*s†,7wC
+)|O¹"c¾0cÔ|u29bI+cž#_HÔ 2ƒ’ïáï†ü£ïrr(ƒ¦-/ó(û˜"Kp,Ž¦xVòßåcq™‹7Ýá¢U!‰wZy/Ÿl#ò† tU¤ˆ|=¢Í‚–èE2@f‚#gÝõ%yº–ü¨K†0Ø!9“·ß/2«J˜—Ä1Yµ£¡ÖÆ8Gºd™V$“ŒK`Ã)û!p@AxÐæ8W* ~¡/ý½|€Øä¦_%¨ ‡Ÿ¥Ý§"Wø´å"'ž´©õý*LEÁJÌö£ê?ÿÓ©âÖ —Ã.VÌF¢Î÷”µCš6Éò2*m5wK;a`'øÂ1½Ý¯b©Aä3¥oHA£lÅ©k\àïÕÁQº0zQ7ëâ`‹uqn6AþX˜¦8o6ACCJ×=s*ÔÂ7gœKŽÎ~$BŠfµ$V¿WÄUE€hÜ”½<!äG!øcŸCÿaVÁ“BX¿ ÿ ½¤mƇȞ_Ñ×>‘ ©J°‚Á¤­ÎÛ3ç Í‚5ùÖax(CfE”™»F l1a™.Ô-®
+Ê*)ÏõPea„
+~XDÏgåš·LÙˆaÞ5Îhc„ €“E/cuí~•ˆéÑ OþÆóçØ s¼úÀmì‹–ˆæÜ©PÞ,mNû.ž6 et¿§ªVlI6÷äñ}스+[œ£áÌä¿ÆF:CÆ°@×ë1_ÿ#NcŒŒ+Jù~UÖ ÅÛ+QòjC¶Kš!†ZPUš·Ù„/˜œÿj;›Ì6ËV!ÀC`QN<ÛÞ«‡àX¹¥Ù$¸P†í.h¨.m*"©m¾tZß!þ —â-0¯Q÷›° ›ëUµ ÑîàÄmt!…ðb£ZeÄ£ä㱦¢¯@Í_Æ1ÌÖm³¾öžv¯ûM
+§(ÚV˜JëEó%ò%’ÀO0CA´].8/ZÜ]¦aÅcÖN\¹¡º_¿ßôÄDiZÎ/Nù¬þµOáñ”,¡½’J5•zÏF½ç‰¶uUŒ ô<`>nº§ºW¶¨µ1 4x‹]­xnMÉÆ»Ù)°sð¼“@.²›lyÏÊÍédÇU¡Ù(–‚îd·¢r  º©´®Zâ5$ûò³ YV
+u–‡ å©"™Ü
+zÛA4—+>^fðÝ…rð;㘲™coDœª£§›& —Rž_NÃI!¤Hò«X
+b%€‰3ò¼ˆ$‘%Ä# %Ë+ÃÉ蹂s £
+82˜–TªÜ L7Ô5»”øŠi9]v Ç+/¥Kl‹±Ž<ê!°>ª e³B>]~½|¹üqùðÃåû˺~õõõÇ/—týæçˇ?ù÷[þ~Çßøó›ò‚Þ«6N4ÒÙ©ñR‡ÔÑ# ù»‚ 
+T¹§õCÌgÅØM>\Ëh’†Ò÷ 8ãQ-‚ÎÚÄÉò!èíÿ¤ôùòËE‹œF2Œ£y.£²Qô‰Å.Ë3'h`KpL½²¢b¬"#Á¢ˆÞêÂŒ˜v-–HªÃ É„i°Ñ©7Y€%X#Ô2BØÿy<M™üë Û§4™ðø7ãå’[WÑ­dõ§Æ™f™:ûŸö)‘z€ãû:i4h›¾’Èb}ð'ÇÉ©ˆñãHk
+©§h°
+%Jœ¤ÐõTÂ*ÎÀ«¢Ø:Ô[–æ:]Q4i¹®ÄèJ ™¼±6¼$Ì@eŽú°ö O›ñ[N“ ySDëiòÖßg'É@Výd(áVSJý‘Eî„(k
+`E‰£ßž¬‰Be
+ãMɧMøÁÒX,M•içw
+,5yNž{î#†Aàf ’mñ|%
+:œAºˆ•y¨ñ$víÞJ¡à,Eæ¶-G¶¶„d…剣`
+X”‡õLøIÚ*êïÒL ˜ŠsÀö‘)´+˜"X– ç«™c݇ Ž¿b¡ Ð;N#Š†¡Ú§WžúÀìâ3Õ´c,Ì’AÿAc9nG@‚À:Üá6ÎbôõPôóM¾’#]qÉ`ŠhÍTÚ-épñ²]¡eThšxX¸aÝ„F€ëX‰Ü^ ˆ{E»üG²ô[>àšQü«â,­ñ8j³ÀPTjô,õ«`{´È|ƒ Þd…'¡£l´¸ DsÐZ¶Q©;wA†ƒ‰³¯ˆÃGÖȵïóßÔ;¯algAD\dÔ“Åc¨×ëÉ% “»l˜ë{8À´5Ó/Ôé~Ì­T_™^„%÷åØ¥Œ´áó(6ƒ«V/Cþ¿Ä¤9ÎÑ=}f2ël#®”êZB‰Šp~[ô éÍb:E‘%Ï·ïõ7DÙ›’½ùLͲî•iq(ÚQ9Ÿæ7¾±ñxàY{0 ¾ŽÌ€¡‘‡I
+W ‰eTÀ%8|Å~¨8É^#ÿÃZýÍWàoh×2²ê&Å UìBÉ›À,òeß˺Ñ!%-9´s´)ô©PNS6” ŸŠQßN I…"Ëm/€á_Ã^Ï7%H˜@íˆu÷¨/E° ÛK)ãŒï˜¶:i;}&w!3)ZÔû*~­\â¥_ßlú(oÝ·{K¸å¸Vúõ³ì?Ž{E TƒÉ„´Ãêë9àÍ“ZÍ9¡ŽŽ7Ù%y» vEŸŠ4F‚(Å/qö S BÂ(}‚ 6VE¸Øû áy¦Ù!Z È·ç=ødÀÿºMgéNJ4;%cŽddÐ×Y)i@,Eh†‚ …lǃьQ„ö]>HjË`/ ò
+(§Õ¢Ñ™·ÚüR6±K#DƒÏáI·rXmŠäb˜ˆÜhèáÿhª¬º b}D ‚£ïr5%E¿I— e7žäAŒ×0Š”EV¬ \0‰
+ö?ƒÝ+)‹"¶‰uÆb‰ÖU$y ï #ƒ$´á•Åë¡fªÙ
+»ZÛ·’MœÕ4¶ÍvâB(‘ê•Uó¾Ul]g÷‰j³Áø‰óC9·ÆáÊÊÊîu…U¼QiÉ[Ó—–Ë<G9¦œ2â?C«„n·Jä‹(Ô°s·2²×Ç¿àï'P5Aõ ¬vù5mNúw±íR¿^K®©œÍìêL6fÇá‹,‰›“g‡DsÐ(Ý7c£hm–@3òÀûxæêܼþa¿Ì‚SÔÕéÔ—Á×`DÇg//nùRÄ—dupÛý°B׬ÑpZÒ7Súy§îa+ü¹æ  H°+ÔŸ„9Icuö‹5À¨±3m£æÑd–g.sÅaI7ÝN¢KHéH ™4f¯ó…-p$ý2ëžQVÁ‚'ÌšLž˜Jœ¸
+Œ W&â÷Ø71d#_ä‹ä­
+·9•ò]{ØÚ,‚˜5PyÔô¶·–¡-KÒ˜ª³qµ$iÊû‘Qñ éÑ4E8¡¿Èzâ:„‘ ±Ž7qˆQ±Ä•©çUË[K¥5#ZAFÙù*v‡” Í¥MáÈ ”YÚº¯¢u °¶Ò9±èd¹Í†”cŒÑ‰¹®Œâó™“‘»z6¸±°Xª‰l ´6Êu;ì`“™Åb·H‡Š`ˆà™CƒXa`ÿ º_Ï—è@tÊ
+l9m^.“¥AÅ@\‰M†Rþ£¹n
+4¢;°ÿ<œSøGjmËŽ9G`üGC¸*šô“Ê[Êùñ×=ú)óNæôWÉ‚ýµG˜!{ÇŽAZ[9¥«£5÷=æƒ'É T®ãy
+H‰Œ—IŽ\G DOÐw¨ ¸rZËKÝB€Wíûoý˜ä/@Ý¿` PÛªŽÊ ~ˆìþÔÙe “½÷ã¯Þý9dŽ¾ù]Óýøü8 &m‰5ïR]Û׳ù
+×­¦o›rX›×V­¡›­âõªîÜrñÁ¶ÃVEchT«Ïz2–Ui³í- Ùmk Aå«ö£R¾±×4Í
+«ÓO¬Ü %¡þÀû] gcçjì÷8ÇcŽíybyÆÛZ˜æL"ë‰Ð7º±zO˜6ðDz¢ïÜj†hå´.éUTÌ}Šƒ¿B8þ­cUýVH¶µ‘[qíÔÓµIQÙB[ìZû‘·¸Ï;m®4 „Æ›[˜ÚL¾‡ÃªÀ;® 2žŸzPÅw@£Ñ“—ÑÔÊ—ñm  éuùo›-þ/LG®ò„ü0¨=/߆EÑë|«]gÆ©´Q¶qÓl>ÿ¤#ý¤y‹Z
+7!¬½k\íiXèŒ÷°y»ÖY)*‚]»~øŽv‡F©&£˜ÒÂÊÆÑØWÐ矜©ŽÞ¢4,C…õ¼=•Çu
+NÇÈ£¯ ß‚c^%” AÐu9çÏ\‰6²'ºIáßcXO ÿ,Â!zÌBàfþ3wMhèÐEû{2ç£æ“Í cŠiE^ öÂPÅœa
+1aÒ=…
+P8,òj­âÒâòtP>— T@°³Åð‘ŠK³¡ü`ê(âǘ‹òȯÜ
+±%Éܱ‹TJ«$>x®ÓgþŽq­ÃCÃ[<Î2©ôyÚ½
+ݹõ^Iï(",‚Òò
+&m*eW(ûºzÐfEÕ‹#´kEkxêuuº€Rì6Æm0Y‹®Ðó¶è›€È'‚LsÕypU#HFFŸ¹Ž jòWÓë4ÔÜ#°D¢×­E5íQŽ]‡v©SÅšs«ŸEŽ×•$ÃQöqš‡å:$ò©í
+AmñÚh÷B@ÄÑ}«—âÜKàM×ã¼y¸áŽc¿ãéä{$žjä;܃¾œøF;lg+¼ØG­t:φ5çœ?ÿDói ð†b˜F¿Ö
+~cO´Ðt†LÃ㜷¿”;ÇdJ 9—£-¥)ÐÜ‚™
+¬7Yb9•LØ÷ËÝ¿e öÃIi-ÈoÌw†Á1XN ‘©¿ƒ>ÿäLÇ0Tp©Å#íëdF­z!Y4¢3°%‰}ž!R9.+1¶ÌˆíZ"þBB¡Óa=œFÀÅ°q÷ÐÐïx¹¡º)ü‚xO •ë2§®Jè˜Ä­jJ{º£,Í‚ôC!­Æ9ú4ó ¼·ÊJÿ¢—GKðših*-‚LÔÜ «<D/êóÑ´1–Ó#àø(dVü'*‘ö!›®Råüì<ñ®îéŸpÝGÈ
+FЊŽo5€’E†:|`¥D0˜Ä0‡ŸÂIzlB™f¯\ˆÐ-$è„,£Ÿð6»÷Žq
+Þ[*ü?Ú„8Z2LÑ4n cynæ¬)/Ïà¨Þ -zœ÷‚OL?r¥Õ ¿O®˜É/fR4ïÑt«~)Å8ýzô°Pdï$†XM ·Ûžì#UD»7ã ícEv©q„æAxd±<4†ïkålDhè+Z•ÉÆ‹DhZˆi±ÜÀMÆ¥š/üŠˆìÑ—¬·¬žœel¡$ån2b1¤žT"2^« ThCkfy¸$¤×2´R'ðѹ~¬ðˆøYiw‡¦! f” Qâž²n1°ŒÊŸtÅ ß„7yïcáú'íw‡e£=Bá¨x'LÉLrî8–~WHÖ`CÌ_I
+l=NÓ稧ŒaÆ©ñà3AQ¨CûÚN¼”(|¯kñôlÄc¶Úì<C¨b÷zÃÞa%"‰¶0Y/#àÈ8à,)€a 1‹$+E
+ÝøŸF˜zñJ°.ž]–Mâl°sj¿:ŽPd4÷‘7‡8X¶ÁruÚ-½#c±Ú¼<0ÄËÄååD%e³NŒy-|3ØEx3tà:Nƒ°hõònè ‚¨,ÌÛûÝdr ¼ qd®¦oNÃÐ:m¡«VáË­.~‘¶/ì( òy4,êœË4˜Y"YTÓ#Œ eX+« At¤ˆ¸Ê¹%Ñ'¼áµÓþÒ':#}j¿¶ê'î1"–%ÇsŸüÇx™$Wvë@t+ZƒØŒËÃÚEM¥ýO}’
+&v+îQnE(2;Z$ýºN%$úÉÌu`õ¤Y~(©RÞ:š0¸œÊÀE²($ÄVHik—qñsdâèäó=Žîº²‰:¿ìk´÷ÐWe,]_A-ÀÛR–;T}ÌŒ¥G¼š—´É¸N(Ç!ü†,å6a4í<Fœ#ƒwô6û9ÇBÙðŒöæÛ@Ú®áVÂçè¹³{ë\õ­ˆ•ÂPÊ8ýŒ[‘–¨àSè—Ø8Ë íæ%"c˜ƒòº¨Ê¢.Y±àHÉi×H·æÇ
+þ³M±tü™ö¹Ë9RÒ…?ë©B&¾tLû˜
+Óñ–ŸŠ3‹Ž^t{z ¤í"ªŒú@@E¼6L¦ÕÍmX@
+w³멨(ŒŠ—z?ÜLšÁ×uÍ4:+ÑpœãVóþ'œ±©åíoÁ‘1²wŒ7}@Dš€êù ¤ðã¡h€•e<"xÛ%ì;£eEæ8#I$‚%¶T«93‘uÏò „/d;øIóEì[攥#^DÇÌZuê™,¹}šwvŸÇÅrÞÓK¤ÒØB^ó„ÓÃý°'/ÚFøå( CG…)鲉̇5‡0¼ˆpÉ9„‘‘ã2´ËÌ»Â×8‹É9ÌñP¯è¯oþôKü‚‘ãå;*vùQEW¥Û*†¤@xH3o2dwjì"tÑdÛî½–xTù‹)45Øf~Ép°:¯Š¹…Š7ƒcª¸
+·%º²A8©õ@Kפ" W|8#tº²¨­Ÿ›Å“º$ƒUä/âœo(Nè}Ó¾³Ð%ÿÙ¹õ䋃…._{aŒ–ÑEPÆt>|¤82òØ oQcu[4@æEò`1u /Ý'BÉ”ÍVóQ ×¼›Ñ”eŠ Œ0C4-¬:ë1”zÕÏaegB–Ãn@6ub1¦Öã*|imªG‡ÊFˆÌYÝÏÞj¦”´iý`Äw/Â7ó¯^§³† ÝØNž
+I;Ó–£À’WLÞˆ,p¹Ÿ€Ë:«íõðñ—ñ"ÀÏ“Ma ºÊ&9Nñ`Ežø˜YY³¤Ñ·’»¸›Žæñ`{„ŒŠ/£b]]3 Ø 2'–n/Ë‹S÷‚´”m
+üÖž,f6mÚÀáØ%OR@D²©®Œ HŒ-yØ`8½+È?ps¸¤¶ðí(­{P°¹‘ݱ–Í*rÞ–¦ƒùÌQÂ9ˆúà{¾vÎ(j?Ž«Þ(ô‡_ÕX38 ”×X_Á”WÖ€¡¦;6SdŸ´0
+‘“yó’­TDËÁ¶<DFl­^‚ŸàKồqpZ¢xLÀqÙÆRßjÑF¤1u¿ø1²o@—Ö]d2ãì*lo7Ú7áS
+‡[O§¨àø»:†ÓdG¶É>" *&Ðëì%Ef°ÌšdÑ,wb­6Àð‹¢(Ú5ë1­Ï"éI¡ãI` ØÈH¹Z=¿9RÖÒ
+ ýãe)¿:š“”Æ
+ƒöÝÁ0‰&ZšÆƒƒa˜’Éӕàß EÚ&·ìÑÁü~J##8L‘ri"üð"é« *œ5Ùöï}< =óìŠŹUÍó’Þ¶“k÷y„'âMã )d(ôzòöȣTA˜öXÄIdV(utW­Fn$”˜ ÄÚ†8& .˜çs'ô¼ä‡ƒ–w¸ïaµ¼çjä)CÉA!ÊIh¿äXè„jñẫCÐ%M²Aͱóm.úf3_X&öN‡~çˆmU¦a3e`bͪrnMÿXAtÃyK¨4E¶‹ ¾ŒaâyÚŽŒÊ½‡¿(Nê²Ð~Êìì Ô™gl3Ê€{^ò{9JP!¸* ž7öK›a’ï¸i&ö8•ÈçÈ/0
+>¼®å%Nî&5É^ÂÙ­„°OÏI>Gæ“rð4†®6þÅÍω`KV¢? ,+~1ȸ* Þü<V d(?"P®a·"1 z‰~>ý[ÊHùh„5¾-„ƨÇü±Í™‡ž’íÌQðp~¸ù
+`ÑòçËU‡¯WEA²d„Æ15±$ÓFšvØ`ð3Miè£n\Yü#Š”Âíוhl 5È.ßÀ€› ÑèpOy(ér“(‚Nð¸ÄÔƒ#6Hêù=ƒN1ú¦hçewA_–ÑÆ,ÏšN0—d!80€*ßf·¥Þ%Ez*{U£;Ê­ˆ,¶~ÇÄeù<z5JôÆBÀƒò«Ø`À#æ:ce‰°Ð„Bhæm—W•§PãèöO¸Ó•£þƒ5sr/n{Mið’Í9WuÖ†Óç‹¢‹D³€æähøzõ¯¹ëǽ íµ²‹Å»ÿa¼LÒìªa(¼öP+ÈçFîÆa˜]dZìÊ,ù…ÔóƒP¨|méè4XZ¸y¥ð.D‡Æ3ÙZ®ÔOÿ VŽþ8t*V WÇÊbUØ
+<hÎÏ…ù±J8@ÄKpÆ=Ýœþ^xgM¹°pùÉRÃcü¦7†¹Ø¥Õ®n”,IPvH.ÂÕá=XT@ȬÞÄ&¿ØÑ8H :_ÛPB‰þtÏDi+Vâé214fë —4_Ý©piˆ´sšø‘ý
+d‘Ø
+@}¦>þóŽ«“°*ÿ¸o—HÒj”«>”ü¶Uß}ù e¬ ÞµZøzyxHÏ–·"%“yI[L&MÇCœ8ƒEBRg—óõ
+ÔËCüY(:öôQ9Æy{’aìLŽÌƒAeÓ‘U[æ+£p=¼“Á&ÛÁ¯Ù˜^!B­3ð¯8M%E&¼?²1«‘ËŽ5æˆ7=ÌgÉ”O[=O‰uÈ(å~ƒÃ4,®
+£5|ÁĽ¤ìç(1 Æ
+®J€Cl/f…‹µ^áH~ ŒQ™@Í2æù±KH´¤DšC‹Ûa‡`P‘š—€‚z¼âSÐ?À©2-ÿT‘S% ÚT"ò·‚=ƒÄ÷§ä]Y(^Ýjœ“‘Hb¨ÍK  ‚-µWN,JŸà©¶ó)>‹Í+µŒ“ðE aõs Ö’œAµ¬¦5I';*©dbrE*!1… C W9iàýS\PB$Ž*%ÎAÙ=Hçˆt-rGZ¾^½Eÿ à¦wÓ09”¦Ú™•î³ÔØÁÑ™J©ú ˜y#p!LuØ5ã¼ð’qL`Âd`üÃ5¿ekfÅØLÆáà)
+šŽ@8QÉ€éÌþÜؾÚ,}–Ó¡‘øÄEC?ˆd6éX‰žGÙd‰©„C˜kŒ§Åʽ̜@øÝ×j[»²?þ^ó5>îŽ- µ‡çÛÔ:b½ƒ‹q#¨=žǦL”SDñš‚«¸1Ȫ¢uDß_ΪÉw€[;CçÓ` ÷$fòaq4FL˦‹í(]­Q‚‚“¨êRŸª¢d®xr¹S„î5Ôç‹kØ%Ú3|z·Á^é¾(Vz¡t-…îÇ0#úe¼Õ›CEÍZQòˆ«½MÜä
+¬¥®’Üò
+Ò\wœ—"z†÷’{pÙ£¤1‡–'ˆ‡
+¿2÷‘›—Èùaù3œü…b’ŒÚƒ ’L<CNÚŠPˆM(yÜ™Ÿ“4‡‚qMåjªêBs—vâ®QRðšòk%RE8Uø Ì÷q)Ú%  ¯1-È”Û$‰-
+¼`vú9hö’.‰#aæ†ëa>yâ "Šò/—_kòêó%exòÐ ÑY€çˆ qSÜ%8à<p€‘ Ãÿ@G½¸ùŸB£gJ\ “C#üá¬L*Y/OãL{³zWœZX=
+¼‡…?ŒöÅÕaضÍ/®)ƒ¢*««­Š²Œk;êaØ…BIpÙ!d0<#—I‘ûƒq'Üi-©Ûkj/ç (MÄèöîç0SšNæ!ª£]+² s§µï¶má+&'Ö6‰ çù+ìoÇ ¨x‡ßŽIKž˜-kíâG'àTš3Ù–'A…òMÙÝk
+)L¨åu0•EçiirÙñÆ!,øÜ3´A˜-"#¿ƾÁa”h8-
+-¼ ºŒéÀãÉü*ª"Óµ0IHqÀDp5 (JgD—»‰ûÕ³Š>‚Ì6c¬®îî›H+áÁåD–7å@ ”§IW¬³çèQã„7㇎}¶aÇ·ëØ\…ž¼[¨
+}Pòj§ÈP³”§T 7 QM¤hÅ
+Në‚üáߢˆSª–ø4‚2K¤œƒ“——[ô#Èÿ™Ô°1õMdÒþsú)‚¤ÅÁhsÕ·epúÇ™5`z†é¢rÅ – ÷ót6|ÕˆJh?LÑ•
+1^BÞßU‹ eg¢¬$?õöêÿµíwÞë&"ÒU/.}+kÛùÙöã!pPÜ€ÉXã@EÛ¯5ìã!§ð5“°@ˆgš®Ø‹Å$69Xõ„ÖòÃGÈ…°'Uø:Ô?#eŠ3øîô9F©Ê)ÖöPso EÈ „äìøzW1-â*H¨V/ýSMŽ‚Њ#]PBƈÁý~Žu¹Rž‘º¡óR—ÍÞ (á*؈”_Á&»á„V“`²2Q(66‚b†89žŽMiâð•gÒÐHÌ+YÏÓ£¦Œ±]ÆDzA}­IŠ.ýô„W…B+®¶Å8Ò¿ÊàÑ6'hÅ*hŸ˜•Ç•MÁ¦RZ“œ¤ÅKY”Ê9uúþÈ[®¿5RŸ4L²9%Mâ6l3
+6€…—tk?
+Ãl ír‰)+øVfqÌ9 ]Ï¿µ„ È0äZå|Š9¬…û–~¡¨+•ÙìÇ—ËÇòÐ.Á'*©6}ûTª1Æ'IÕØLû°ò ’Ó¡ #N²moH 3q@…Á8Ë)ûµK»1ÿž;"â8îØtê\y4ßîPI“‘;(¡"x ÌL'èVO±á /öý´e™:Lz+~õ:9$ó›w¢\ý²ÏãÁ»¨ˆ¡Æž¶C.Z²cEòHa)ãV»ü¡ï~ÄžÞéTH…2ÒÀ,Ô…`!-z’å4_l+üYë!püV{ØÀÃ&Ñ+’˜8. ÷Ÿ0Æ&–MSoPƒªÀà6öÑq˜-Háã€`vùñ±‰ÿIšÊõæ"·;YqsWHÒk„µ:[‰oÍ)x±;ì!iî°‹#Ò=H3âÃ*¥e°·Æ!›Òw¬¿ôNuYœ$Év{Ê,YǺ@ö§2ªOû<GyƤ8’BÒƒ„XÖÁÅcHxv’óÎñ¡ú’e +zÚ}Bd’ê6œü^¬—D)o)Z–!Qj?çÞï³(›@j©½hèi ö#;1T“4I^Ÿf'Â?¬O;–YFÜGD4@¦j²uDõöÄ˸Ø!ÃÉÚ0`C2ì½$ØêI'4ivS,ýå_Âjèh:ˆ$Èö餰}?jòQU¿°uI?7ƒóá ““£ÉéÓµOÌÞ¦—u¤\ U,‘ 6ñ-î³(\¦1ðdÞs:Ä ‡f‹1Â&í÷¥}u:Ë÷û¾¦µ^yRW¬Üöõ·Ÿ4Q‚ÏžÛضõ"Iâ/ÍÝûƒ Û›e9*†3Iæ}b“< ±8³¶fe‹gÙ,'¤<@®ê±Ìm“Ÿ3(Mî“"¡€32ø0p^- •÷’ê&`Ï4!Ò62Þ ­ãáLÍ-ì«jÁ¥,9¡¸ œ
+lÔiŸ«†L°ð-ds'øˆ;§PÒŠÀŠË<ïÐî¢ðýèV€~Ûîœã„$XÁ!ÓkÚU4Y´vh7ïÄ3Ž©cp‚ nxG¢?"t‡]\ê³ÃEQ§ |/ÓløŽ/k ÝÆLÏz*áIY{\7þ
+b øç/W ¤Ë¯Ê°w Eûxx•+VÉ°mÒ´8¨iÑè ¿É^b«ÂìÒîß÷’çÉrå¸2žß!À`ä±+h‚
+KAO毨§E‘üƒ)Ìñ-? #„¦@()ü7a!ÜÖMÉ ?þ¹.B6 ¼¼9ÆÀ§⫦ó¡T óÍ‘˜a‘!óƒÂßu*šÌx1È nÅg
+M –RúwˆloÛˆ
++<GVºù
+?3¢r~’¹ÄcÝŽwÅ+ˆ3LÿíßbÙ$ÅÆ°át½žÝâQ°'í:C€:ŽÔµqŽÒæ(&‡<!{AɸôøÎ5¦Q ŸIµß”¼Àáä$GNÝ¿dmŸõ»Ž}ùP/L*–‰R.Ô€rÇöL´7€É
+ãé£éÀ²¥^H›ÝW±c-y8>¦„1£H9ÏΕBÀ•œËçTÿÖhà:Ï ¾“Z.àÖG…Et²Ä¼p„|Óˆ$nI¯jLÚÀ‚‡ÇPàoGÄ£Äql'N!‡öOæᔹ8cGÞ̆U†ZNô®©íùðöFDeZTŽ ¾Ðë»L¿¡«Œnaluö’"l/®eFsàf˜¦Þx_í‚ReéýÆ?¼¯É5A‰Y6<̯)NÂyKr‘ÈœÛZƒ-å§~l”ø–
+Ò‡”Š^ý+pŸäm†=¤1\¥‹Ïè¹—`§+A+,I¨ÃûÀm„‚sPæ²Hù«„=&l()h1ü;LEÊÌ@€`žëšE ‹I¿²<õO"}÷£
+ûl8³é®d°4¢¯šci¨á*ôœ]j¾Y˜{T   ~¦özÂïAo¸HF ^v€³²=_!óÙ±ó…ÖJê‰_õŒ̲Š ¿v熄<,ľÃ+{P®ìŸà}ð‰íy(Ìž/„ïË‹žL3-:êÈñ±³r⦹Ø%„o¶’c;5‰]¹•Wdº>Å^5JdhJ&&Ð2ŸDzƒí¬‰ê×¼(úŒ¢Š“ÅúH½w¦\&vcmªÄ7'äUTPf,¡ZÖe™â:Œ
+Ô°îU~Ò6ÄêÔÏW”dšFv1&Gݘ²SÇ}T‘°-°ŸWÅ—ÉÁ†” ó°à6@òp ˜ôÌü¸YlÉ*ŸÁ Îîe{1.—z 9Xpôrð…cÅ„žús›?þbãßÅ 'Ð:¥¨õ8
+!ÄóqûEŽ¡çt8kpñÌßDo§$TçŽzƒÝ¦—ôͯ‰ë1¸~~âø+«>QÔñM–#Àh vº<ļ£O²gXµ%×ÖŠ>â›!x «í{„xA‘{©ŸCWºßÙD¾z¼5%¾¶¶°(‘ã4¹_:v`D¨"cµñEøÇÔ‘_(¶8‡3IF0AËöW*Î-¯ª ‹åPüHãG<d8UËíy("0â¾àÜýûå?Š¾Ùx•èk1ÃR~€KO‚jvKæE¾£‚ÕÙÎê"_/Ç<0A¡íÚÙ¥QÞó˜.…‚M<vì¾þ‚R±hC ¦¦ãaC>³H{B¿RQwÀ|ŽG,‚_˜ žtÉð‹’9F [
+)¸§™ß#žr»ì^¾$¿ék=„”S‚Å
+b-‘c\Þˆ²ÚYÏdÈA9¬¼õí”x,LaÎ “Ô¢ñ5K´´fÕD¶”o¹ü¯«`+‘nϽ`4¾ë§bsú·¯sÃuŽ ýŒ|·lDÊy”´ÇRmi6)ÂñïE¢¨;¥wK°8ƒÍM vM’²(ššñ ßPßž¨ç[I’†+ Øz(J'Þ™'!°E¢Æÿö¯"ùî¥p’'¯+â,;\ÙÏ"äGƳ ÄcõEØy#Yî}6»Îc›bdâ
+õj%eì[Iâ+Epó#úYTYpþgMt>s‡@¤òb×q¥°GMªœAf<_…àKT1!£G‰´›\P˜úµõè\8Îãé –Å:2Ékþt”h‹j>;Ö«âê1¤.ï­À0‰§ù*4K‰V:4~sV`®uu—f°ëÄ‘ÏšÚ}Yÿ/ë ?¢œ¤©‘¼Ã"²¶(PØ€ëK\D&:¡ðÑúúàSÞUNë˽MÑ'G ;a U–=eò6 4®Z¼|âU
+ œÐA y£—‚Žsa*Žœ§vtàNý^КØ{Ì°,RÕ º¶øŸ¸ê,Ť%;H2s!—ɼg‘p#³jÑ•É$Â+SˆŠ°µPü”'ÉáòRùÓü¢—ñÐ¥†@³=
+÷Š›kÉ•ãÙÙÓÝúýæA`d™äøäæão4é˜-2ôÌÑæ«JdµÏ(»h)ƒö+¨dV$ˆ<á¨ý–•èóÁF’%iG§@º ¶ÕF®™o3â /þh>}d‘¤˜åÈ.ý´GÄ×µ åæ'£?Vpc=œ !Læb(®ø©¤ýäFb#·}iWQOYŒ 1¸¦ ,Èéê©€1öV0û4ÖkÝèôSIY'è@cØ#å–äÛq,üZÎ~Õ_°‡Vpe&ïw¤Wáe«Êq 8JÒ‰½RRl?XúÆ|9¸\lãé+Žé´o2ëó1|/ÎÔ²:B™0
+ LÂê}+zQÔ] W¤üÉp±@èMk@û¦L‡2ntNÚÍlìYþ5 Á†b±¼Zzå¤ë¦€¹ "ýz4:&MžRã‹…³Ú^‹#ãü t82Í™&ƒÑ€õˆ’©ƒK®–Ͳˆ_¢‚´hï&Áêî옢´RV¹Ç»)ÂÂíq¬Á v£j<5(ÜL ]½ÁŽF%ò$—œÝ•}õŒ‡‡ä3qÃë.7Á}ˆB­HVÆ–.æÓ'áõjîgïj—!ÿ[c”¤êIRR d⡱ëaŸQ$«Dcæ°ÜcÎË Yà·SRDK•‹Ãœ‹Ð@h-Ÿæ@tK»‡…ƹ 3ŠX?øXi2+wÅÛ$ª Æ ¥S?J>¢„}e‘èT"^À?åó¹h­¦X$*à»BI]å´ù¡¢«ï¬¹#ºgZª• , “{è!ŽqL…ìÓØOñ'ð;ö
+TM l54ÿ›¬}>vðG@¤Dš6á€þWYId"9‘’*gL
+²êéœ0q.;ÞOã¯H ¥$΀/y ¢1o§d@ †u¾¶€ÿ'NµPÁ@Â>Çy@bÛÁœÄ0¯R`ca!¹=É)UÍ8%dYD
+8â„’s
+JÍ}+h×J>qç- (êƒü0þ-¸ÅäÖ¡{”ø„]¸FÇW»ê‡õ$O°Óù®)³Ü%Ç— ¥—h¡\kvN‚Ïé`2ª€Ë$š!zñt¾éßU
+L° „.h±[DŠ19c¬8‡Uäan¯Úä÷˜&»mUcØõ¡è#G>®Åe ùˆ‡ªÕÃÞ²b”£–XçŠcjn0AIÈ ;KP:t„êá‰-ÖWF™fx¦&‰N𜖬MÓ1=.ò-aç:€€*v`ËPBù¿jü¡_>p†[þÚîÇJIäHã~òƒ¸kr;s€¢K”íž%‡þ›ò`€s…¤h²¥‘¢#¿±Ï1Ö²ˆ`‹è²û~Í¢¿
+I\ÊHð#³›)"ÄMW¸[?Ž•‡o²Ûî÷árYPf³EhüÂ,YÆèßYpe†às‹ã
+ðµ£Äw8@ÃÇukÃ…pé=îƒ*Œ~”²¡Þ)QB)œFƒ£Ä´PIùW2n{ûîæD?-ÏîCîÉ¿ë9§aäü¢9ÅÍô‡Dhzb°³TP«ÕZ|Gú‡ürÛ9=D²Ib,
+ùEGÿ£†8’_F 0-#ñª9Z†w~¡ëûÑ?À;¡%;Z*1xjêfŒÎÒxöâ Õ“î‚] –#³8M†cÕSIɉ¨g*êr<ƒ2ˆ*PÿNàÆþ8ÿÎÞ–·Í­¬ÆZçÑ%zUøË–v™(Û¡²è9t\nl/;n„+Ъí.(1h›€“AOêÌ/ ‰çÈ‚´¿Y/
+šû¹VÞ>‡&„1Ck&§´±KC²‡@ú…w¹VÎíiðO䶺,×õ
+œ Å‹
+Z¯mõ3z¦¡ ´KzJv¸ Púr@zéAÐ:ø|åSH…t J¸“rý.ˆ¥
+ÄÜ‚Ö“Y@÷èC“£…·Yúå[Ä[D°XØ d|¤“$0Ȩú¾.! Zâ·naȧþ{ÒÊMkÒH4‹9ùfÞAH½k­Ÿwýt]w*$yä˜d­ØÉ0ÿOj”ô§|0<¡ü²MK¤|~ï—Iü´CØ(jyÓX}§%÷­˜8¦íè^sÈ$uØKm?Ï78Âx1d¦„K·m!¦EDcY~âüÐœmÁuh‹7²!ÏQ¨%Ýx:'4öëÑ`YÇ5ÈS‰QÆ õ)\b¢SÔa)À®3pè%±âMHz)£Øzñ 
+
+å£4~c^ÎPd__vjÁÀ¥YV|†–Aa˜¹í‹BÔѼºY º°”«0Ç­Ÿ“¤¯oO1lª¤ íß¡=›ÊО‘‰!Á=2Lˆ,¨Oż'˜Ï–P Œ‚c AÜ}Mue‰8Hà{Ö ?¼œŒe(’Ç‹ ·JMÙAå"ûA‘•ëf/BuI5Žnç3dŒåeº K*!
+ïU7ÄKNy22%wé—¡©`q¨‡È
+"‡Çb„ M±‚l¡®(E«Ó·Í¢×º*}Ö
+3)ür)
+6„‡ ÃÏÀ&Øñ¤¤áR—?~«“EÈ5G êLeÙ•þD•d)÷³·ÑÙ©rÁ
+Í„ ÌH©ïmAP‘sƒ ÃI‚–ÌqacèÃoÞòeÙµ©mFû±¨6ý¬T
+#í÷¥¥«/ú™ì7*™¦ÖGE"é¥Û ¾$ÿRyE®’ècÚv™òÙWåª(©ïw“dV›È®×˜N¦!Ðì¤6¥»
+@M¯s6W[¬Øµ~,?
+Ž(-ᇜ|­"{ŸX{O‚´ ".^î h×UDº­w
+ðL*à'lÍÏû<ªy8eË2‘Þh|ûÝ0JÖ èöã ‚±=7»ó«¢3èóZH>³[NÊÎWe'øýzï‹0Ø“x.Îà~¬"ì¡ÁHj±48·’¡{Á½R {›<s¬¢o ñ_ýãý0Ci¹0¢^®ë·æ·HY¿â Y†ãüygÝ ú‚^Äæëw)¹IÙŽ×6½"juYŸ¸<”@ø n—[7Mnµ¼ý˜E|›æ2j%+®Å“:ò]ÚÑΡ:FvÎ$S‡1G¦G[Eñø-#ª¶—¢¯ßy]š[m²E¤¸Í°º1ÄhËähOÄÛ𕬃Ý?ŽgѬ*]&ßÃþåCW´O%:½¾-:ñÃBúZì±%\‰—?Æq18ÉœWû¶d¿£°xîØ®ù8ˆˆ·HNÝŸ¢ÁŠ7ËPÖèdX
+'ˆc)©úm^à´?¹9€é¬pÈaäQ“eû[ !°6zìÂ&‰
+ÓÀþ P1‘Ü”ë +÷]ѯW~Yúgü¡A‡@ê·E}C å\ûõË:ýÆÊOb Ñ
+ìë¨_^¥„]<PF¶qõKwõ@6j¦/-NIƒâåýmT¿–ÌQy84ë\¯ÂY¶‚'ìû„Ÿ«í|y¬özUg
+Y½3–÷0õÍýëé•gÎÿøŽWx¾äÞÍqoâþõ;WšœqúaÁùÝ&ì}+%¼1ç1nά0ž¾ì÷"hŽ_É»Xù#%¥’l©ç¼¯EÐø¡ê<ê(Ùâ ™ „Xg‰o˜{ À17ŒK+Þ4ýø©pqÅ[âå8j÷ÙÅÁ¢èr„Ù¸ô>˜%–ìÚÛˆ­£pcéz}ç›P6˽©{èù¹ 8ÁZÜê=JJ“\fÏóyxp1uKfp’"9}‚1€.<£õš í¾Ólœ9Š8p½„²\éåÇ8JêXôæcG}4Ðn߆êã¨f0ÌcÓ8–ר–ø„ F÷ßI ñH¬³â´{N—Gfþ¤.LÌÔÒÂùÛ7¦ªôúœ©ø¨!ø™
+Áehã…žƒP˜ß^ñ½³âL?둳×I¢éVis)Š€…ãŒxKÈø'eaù¿`mYP¤Â@„±î×(’| ÈÀ¯«Ï¥¸ƒ¸÷1*à/z®éÛªH@5Ð2ð—’œDìnÁqqOäÆ›òÀFÀ)tnHïÔ
+¹SŠ2+’o;Í?¦!´ó!Ž+”…>ç£xe݉ºž/E?Þ^Š£tmÛ§@æz*j¸cJX*,29Çòœ[xj_ôÝ¢mA û˜Œ#\;)kæ Ö ˆ_} {§„q—Õ¯ðx¦pÀK ê3rÚ)Ÿ¡1˜ ïŽ
+½e§¯jÝóåúÄMïÉ 3€—»ßcCæØá÷ü¨öÀ)‰¸)’ç×ò²6_³Øô~¯’ÓŸ²d¥2éM/êøÆ0zJؼšlÁ"÷ù œèÃû}ï‹ ²…=m÷¢7K®×Èv/+WÅK<å^çg„n¡t®s~$!›O}¼½qzôãç¸9eé+´µ–a_ä¶ñ¬i±P-ºXa‹(²®bZ›sH»¡Bˆ»ž<ökôà 77ãïz«¯ Ò|ñM·¾m‘Å•ÞŠ(µ¹å0«s6ñî/ú'E¶}$œ¶&e›÷hŽj,DYÜÿ˜ðùMøÛ+„»E4Rd÷2eÎÓ=œ)">œíùRôõ;¶ îáÿõ‡å”ȦçlCNnÁQA½C»^ø/5µ¢Ž p÷ßk~¬~…`#|§€°ÚåŒ|AŠSq *]Óòß+Bgü÷>Zµ®m(HJ|)úú·¥ ÛÇü÷ÿøŸ?öÿô£qÁ:/œðXÃH&rsª;öírTƒµ)/ENFô~ž¶q~GÚ­Y¡ƒ1%Í>_Qųp+ÿ¬¤
+ˆ_ºJÝïY±^¢Ñuñ3&èÕÊ®Ë|ñý*oÂÓ”ÎLÊùU[üøöç‘<¿EÔuùuá·êÛvs5ùG=þȽ“ 
+Ùrš·±ÆôgN®ø
+ŠÂÔr;çeøªœ©|1x\ÏèÆÓ®ÛÓv]ÎÇFJk{œÞe1Á±nÇ$Hˆn4Ì …ùJè›Ûµ½?#įH5{ á¸pÌñàlïÚÖ—÷º#¢ÎãÕU9'hs9àÚI'¹½õva:é0-l£Q;÷LÇó“% –*¡¸”fÇsùzrÛ–hÿ#$‚|Ʊ¦çnÈLícñ£ê%§¶mÌÔ$„#<³i;lqv]õ9(¾âºóSA­WÁEm*ßÛL¥êUUz²Þ3©{õ¤ê¶§¹»Ïù1÷˳¥Ý?¦=³º‚‹ÈF“¥TCˆÙŠmˆóÑyÖ#¶òîÿÖS¡*G¡+¡W†i%ÿõ 9^€“Êfå7*$Žu9xã’.ý½ Ùe§­«Á$˜·_yß
+H‰Ô—MŽd¹ „OÐw¨µ~(R$—†¯úÏÆÕKßߥ,©r=ó™n ²"%Š ƒ!×ð&6§[|ëÍìš*ÝÔZö·ïñøí>S‹f!Ó^!
+üt
+ü”òöÖ®é
+«õ…ŸZdñkú¤Çê]´ÜÔ› ãu½]=j/„“>n‚,¯ Måo[ö¾ã~ÊÀ3æýN––¥÷†GÙéú ׊DѧG_‚1KÜ„òjj×èÇÄî‡gËÐj7‰yó Òtâ"üMÐ!ã3qþÒ„•q,1½:%“Û¤sSaTîaN•{IÀ-¬÷(dÕ}ÝsQžAïw*·
+<™Ýd¶8àté'.E-+;ž ü :ÕnF^Á•4Ö]ЩvÎû˜¶Q ¨|Òœ/ Cñê6ôŸ: Ng<CŽ•{~þ-Щ¼¯%9”÷ëºíòò]Á¼¨èÔvê•*ït\N ’ó³†z9`è\Ù ¬Ÿ|¦Ï ãuŒ„) ?3’øYÿ>ƒNµ{¾íæX–—Ün{®ÉAž¿®Û.¯Î«À\é8b
+æÌð4eB”ý<œöʚɀðöo@ìŠ.Lÿ>€Á‹öd€“<ëÒ%EÐ\\
+™T¤ÈqŠõqÕ¯ þ¿£ëŠÙ²GĈ,Ib\rFÖZ5ÛD–׳9ÚkÃì U€P¶IÚ4²>c_å‹YÃ)xÖÔÿPàâQÊómUsŠAl•®Õ†ÿ#žþA¢…­ðÖô±¨¯ ïÔö„Yä„”Áh¥n»íH~‹I„›ã^ŽÒ—Ó®`á2üÀ#1û´AS6‹[¯.Ý 
+µ³¼HÄ3æý„õì[,O£ª’üñA-¼æÈ+ 4ØÄS+-µ¾ö݆3f…2RŒÕJeï›|¥‚‡5\ÖCFPCô‰ì{&W¨¨eíF9¬y¬«hÖZgpÂîv<~áoÚþÃÝáXF°-yßbãš´jí›±ËÉP˜KóV0® Ð>k·$3왕^žä» hæd°iÒw+¿˜“ÑiÑšž hSÔ@@&!¶}tܯ §ÙÃøñètüCëR´‡mU—Ô 3v±\e؈À\#…¬yº‹EÙ´õ‡Ú—7ˆ¦òØ!è(h¼ áˆÅ†$„1:c #Q%bNcŒÅ_¹*«Vãaéx‡ÉXéÉýúÁ†,EÜsa¢#ߡƶX5ëÍô†±ëûàg21Ÿz>š;Æ4’¬íÖ«¼–®ä{[‚µ^†U{|Eu)é¥tñè&gq­^{RÒÑÔ´£È©.ÿGp4?zûP´‹±^½ÒyçÖ+HE¶QøëÛ+*Ù–Ϲ5(2*îB¼Á>ãQá©ýC¯˜A°m¦ù6^¬’Üšla¬…riðÃÿ­eª H+»—H§•5ý
+_ãÖM`" ‹¡_§ÚÒÍÚâ¥C‚S8³ ¿Yzâî€0êö¡‹¬ù“éBqåhÁ¨H+¬
+4ˆ‰æ݉¼ºh)j"ÆÏq%!æÊÜ®±~î‰ÐëN•¼Õì7†ñCDVñ\‡iZbd˜ÊS-‡›Ü[°Ë=
+§ad'âЂµ‰0ÑŽ^
+p „EC…“L{×>ìãN=9c^7ú¶»‹a%”LüŽ?ª’Ú‹yv^ÑWܨ”gP8¿4h™=©ò>·@áqÍž™­ÄíËæßE­;Ÿv6åR€; è´sOžþ¾o»½(,v`ñ3uº‡ÉÜÍuá$¼½ iOpít³X¹Q8U4ñ
+šä[kÅßÁb¹Ij«®Àׂ€ÿ«s¤r”¿{†(”i¶Uì™*Oƒ¥L©K½˜]7¥Ž|'Ãì Χ÷arr#ùtš‘•˜®¼pµ.“a)OzQ¬Ì;pP²e¯
+û <+OLÊEßa@¨b#ª ýáÉŒ¤®¯‰é•— —¹Õ??®K×y"·ÔìÒ—§ Ý×˸ RB
+@¯ bõÈfd&m9‡qÆ“
+\@ÁÅ/§ÿþFûâSF©k&JãÓd£Øý¶ùÅáП±MK‚*uLÄÀŸ6?o²nÝ#¦Vu;äNÕ§«ýª\‡A9 B)Evb >“Ÿ9¶E0!)WÆ·ãψ›P=ÃÇ%Ѹ‚DšZOb)‚:“¹?ˆé•Å|³Êyò·{±M¦i`Œá¤ïà¹mmP’'[Ä7pˆ­Í”æhèY…Óěͭ‹®C¥©ðÏW ö†_ç
+Wt×Ñ3KÔi&Í­ÜGá—…„ “̸H®Zé.ö'4=ºÉïra¢OsÀló==ž–Ü)¥ìÂdp¤zÍZâªÊÃ; –Ñg1j›©TJ>[ƒÜRh‰ QšÄé*®ð#cÏQ…,êí* –sN¸MÛácÇ­¡¸I¤1‹æ/"mÚ'­§1Ë·j?›/įøº‡CT‚¡/•­ÆS„£¶3=®«‚Ò–„ÎR´¬ o$WæòTÐ
+@¯ êê?S1UÇó)Dðضߴ«2J.û]À¢†˜=[Á.u.‹÷<æ,ï
+C"½à*f=<îcªåHŒ'Å0ò™"
+¼ŒvÒ
+åÃgî.ŒÌ/“¼Lbh*—Áím+ˆ–$¢í:ÆSHžÀÃxñH•Öv´€¤ÃLÕ£òu¦®i6‚º´ži®ÍRzä¤\Ưì•<dŠ˜xV£«¡›e/ ñ”oíbÂt\‡ó!g’ÈhØxwEò?ô
+ʘdzSÁj!ôbJ·X/q5{:Þ¤‡K&ä¬z~¾4¾Zeo%FB!1%_Ê«—qz…åJf‹ ÇÔ ²09þ‰Bec„ux"žÈAPe0qLNGS·%‚Í¢‹òX
+—P¦UzkJ¯_ƒ‹5<_¶A™É\ó×(ÀM´œZ+~Ì :mùôº£š×?þùà ]~˜2×ÀØèä.¶Âÿˆ)ÓþúÁÖ2Øä›B]“+<R°¡®K‰sî|†NÀìÔñ ªîàRR‘ É~pÐôúþ6z¡=þü÷?þÃÿïÿüÅù©?T<Õ!bJEMÕ˜²'¬¶?#)â \²@°ªzü/ÿê/¹‚àäl¤½6‘£ä–a9Qû=P†=æ€ÿbåj|Ü=¢EÍr6ãæõg•ñPæ•–Ðm‚çj/3“Ç—´ó‹ád¦,}8. ŠI;¥ñ•0^CÇã:æ<®DùjÁŒ­÷‡|&T~x~*Ó„JGÍH=
+fJF1-Vì'P5Ä–A)ë¸OÖ©Üï5öwØ­‚ÍÍd³Ý_üwÕû ýReJ0ÎÓøßQ¿ƒPÎF!ÑdR‹C¸;FWL“6„g»<¤ëÝ”¦¢mYX¯€Ÿa~Ǽîôjïû¯Ý äniPJž{ÈÌ7Önëù{gÐW
+¦Ò´MhgO©›˜hOT(Ž®2?%À¼vGÐ5î•e‰„ˆ°GÐåÑQ­>6‚YYKÝž>f]Þh°f(ˆ÷ÂÃKf¦„<RÔ²ôŠ‡C˜@¤pärt¶ ~ß]„ žfÛ¸Þçü¦4´L¹íë’Ú
+^SaŠy§(03w<ˆõƨ£¿s&Þ˳)ÁgŒsàFuvu×Û„ÀŠÐY‚¯ + NÛ›5üugÿ…òs±bÞÞ“Í&®I¬k²3‡ (Wªƒq´éáÒAÉ°|96Ñ=ÞôT´6‚ª¶’q9›_†ó¾"²@úÎÑÜ“ DNT „Ÿ•i°˜|"hn…÷lhM`\ÌÙLBL•`ù@ü(Ã¥;Ž?·ø;èæT'õQÞ·Á ±M}ú)tnIßj?^…ÍCß²Øê}”AP¦¤Ä/d‘´¼ŠJ?—>ë‰+%æn¥3 ¨þaÆšüô8¤ŒI३#Ln¯ ÆÑ“&GA±]ó€Ý[Œ~逸ã]8SrÁÂW¶íA*#áVÝG®O/š>ŽQaAÞ/ÿ½‚¥(¤þ—ñ2ÉÎ#7‚ð t€cXkÛ·ð–ºÿÖ_ Q”øW–HÛ¯Ûƒ
+RW™’q•ô5æ)ZÌà÷ŠA.?“BôJr!/†HÐ]ˆ¯\ϹP–P„PÖ8
+ÔðÑÕ(­G¹P FÅTkQ,Œ¯©ðŽy …Bd>ƒÈ™o×¥á«Tšêò–
+ƒ.ÜRá×úg]I«Òî˜Û©{*¼Ÿ¤Â
+†B˜¸]Åâ`ˆ9zË
+_j‚Í(
+ÒȨP[9ñš È-˜×l¨ãZVb)A4 mØ
+¬eÎÜk´ç!èõº÷„ùÓGÊV&Ñ8ˆ®ˆÈ`âχÑdhXº†CX|hP¤r&¾ôFõyÐÕ­E ¡^Isߎ9‚HÑô~šÎì©™{Ü[r æâž@5^⸄³J½ÇçÀ*4Ù,Ë{ů¡ÇŒÕÑ/>}U•´SwÄÚ?ý^Œ°ië°Üë@ ò.õ` .SKxÉùéeƒý@‘|Iü‰Öm‰Zã ÒþAóÀ³Dh Îk{Ú*ï]Îó«eYmÍ”Ji”k“Ì1Š¸K6¸v¬3øöÔ~ž$@I‹âDÃO)ÛéÔåmEs»¬pÀ`í·ÀÙÐ<(”¡}SãM|t)>‡Zë§Ä™±gèâÜÚD6ĉóÒ3Æ2Ss4¯bðX%‚ª¤çÔ&a·ôÀš†ŸSX8&±a%N…Y}ŒA±RT$2÷¿~ ×„ó‚X]£è~Ëç»H- &;ß®qe"X7ZˆŸ„ÿ»äÎéáõåŸ+ÈödÔ‡@&6i?OXu40\eog Vcâ£E>ƒƒ¿%zRõüp³ÅF JÖ.‚ÊLÎ*8#š›Z5Ü­j‘ʘ>“›^zg
+WÉìÏ—µô’7`ˆˉ²’®ÕxÆ:ï’7Ú—u–pEêUdÀ‘öDO )¡ë0dÙ
+Õ˜ÕíLµÏ'ZWžl‚]c÷·Ø  üÛ™ðjåé$1 FöËó›’¼? Ƕ¬Èrž“ ¡RcË ¨ªÀ ¹½Ï âçáM?'œ¤§§L‰k0s”|Þ¿Ó^Ÿ‚ºä¼j&蜚0Ï„ŒùrݬöýB:6¦ëÙ è¿„B4ùŒêï ñìWÉ}´…¿ãOxpžQžzwEÕÔuÖ´‹©”§´y z°ä ÕWà[
+€CÆQ‡6ü˜ …aKêáiâ%üEy€Ð¾ŸË–릤€×¯söV¶WBªT
+²5þöÚµ1˜Åéwį° Ÿ1ïßiÔŸÐÊ•
+oeÌÄ:–Ï™¼¼§¯ç½‚þ AÁ&¥©€Á÷ñÖùä®n h“T+¶+ÓOÿöRÿù'ɤ{ñÃJ3 ‘‚TÙÏ9CÖ¢Ô´ó ­èçtòL¦ËìH—´û
+í\áäs£ü¦' ©‰Jq4ëãô1¬o,*»±øõQEÚŸ˜ÉEÂûª§â0ƒ¯Âò7¶ôq*1ÉËázŠ­z‚øLxpb×{=llX¦}­› 4² Y;Ž_‘{ P“Ã;ß¿œÆXé-`ϸ'öÇi(ñàåY63!¿wꛕGI½ü6÷o|Œ¶ZÉR‹f%âá8²´›Ë&¼:{ªäë „.R½Ú BÇ4ò€¸±ˆ o1 bìúÉp1 D—©Š ‹z°Coì/ž ªo¼ ¿ s…X ÂC—kéÍ 'I*$GtJßJzOwÝ4Þj¬%Ðâv¬‡ÓÂ'Ãc%¤‚&•`EG2HUå[TßÝü0pOJïVÀ)ÇÚ»~níBØZÖìH9ÄYo|Kd
+8Ç!„Ú5LÚ¢c´ÐK|¬óÅÄ–à5˜~¨gú«&ãNb!ßD1^‹sØ ƒ°ŸL ½Ú+ÁPÖÈç²#s×B½²€{š©¤¤‹=ië4³¨—|X÷s˜è™IOªSä§L†¤<éŠx·¹^f„@²
+7)J‘T—³À€ST»¤‹£ØíÒ¶DcðåÅ+5ýh%£
+Ó²Už)™Ž9¨^<ÙDDL LÃ׸,2u –è<¸øÐY|}S>@ÞH`Þ>1^ôãîXŸ(É?Åá øN+ò@†Ð)1xskàˆ<›òØ‹ O…É;‚à½B—àÃÎ3£ÃJ0¡˜éä%&ÅNú<”Þà‰'wí‹. ˆÔbñÕcî“‚à›{Þ!’½i ¿ð7ÕT{áUY”ź3Ø»x”HFW)Âq`³\©É0©Q~Làï<ÑGôú¢àGÚæN´¿A|$ÐPEGüp?ŸÃôQ]+ô™ ‡¬ÁÄ´ìëòVW¾—å»Û^ñ9€s ‰$I~µ]øe•ñýúçƒŠ<øZüsÞÿdúaÖGxüøBí4Ê!6Qd™X£•éXº7ÉfgGf;`¾0 ÍXMr^ÎþpÙ3èç+_dô¿¾|ý›W2¾ë]}Ðzû'Sƒâè_dBþÿƒªµ.;„nO|‹f¡¢œR8ÈQ+¸ É4˜»ŠB“˜4Sò †Ùg„+ûë  3×ÓA—ë^Ák ‚ÄÛF6ȧ B/ƒžJðó•:­\3ªàL$J+Q™JV?‡ÙÎæï
+„þˆš3ÝR®±”{˜rñ6¦\Æ‘hŒc
+^]þÌA,Q!¾…’†£²ð¹ä¯1Õˆ)ºæWñ+TV)à m#ãÌ6«jà“e}ö9D%©-þ*rOÑWv{äJ­èd"RøU
+Ùνã(BæöU¨Bú0 D~etÈÚÏ€“Ü“í9ã¥…å ¸hÜ@л4¤…˜t^@O³,(ž £½ ¢Î¨–‹"4®¿‚è—ªºLˆ†ð„`9XXðØýQ6ÅCåì¦êRdHK†ŸC¤ÔèªA„B; .kµV
+kˆŠ"7ä?†>?nzÆ„‰‘ÓX2r@Ð}î„ØãâÁBü=‘òÚÝ5p ^œ%›mœÁ2¢ÌÊ|ƒøœ¾Ù=²Ý|W’y¿‚¼¨«,
+ù(;„œÃ¬Q³|t¿
+6©o?ûB1Â0.ŽR@{b¼ãY‚ åà 1eÞ¡Óä¯F ™,Ú]üš„,`þŠÂŽqc‚ »Äµ¼îI,8'¹¼Ã'+tA°„µ:QjvÜ#Ñ1™Y_ï['?¤ç´&¹"²¡£„ÑÎa•x6‚» ‚— ý‚|*I ì¤ñÍô$.g£tQ 93Îgº#¡Ší«‡ñúuµ·¤§Qì·Ü¤Õ£&­^ì„@FÈiÍ eÕ¬TM‡CXhè”Q "!ïT_þÍÈ
+#<X[LañÿÃx¹$ÉqëPtÚC¯ ‚$øËC/EÞÿÔç&À´ºŠòÓ Û’Ð$Àýi)ô´1&Åc¶³M~›rrF²7ƒa}yɨh9Ëúg ¹*øyÒŸÔã¼J…ÝŒ֦ØáJ®±tÉaé"•PÔ$sIcxÄHncJ²º„s#v5wEoè¼lä|!ô5œö¿‹´Ç4Á!üQDÇÊPN¢#ãêá¡ä-ÄKàqdŒ²¸¢H.?4=†Œá aÚ½Ç1L+ãtÇ^Ì‚ÏôV+%¡iÚ4ê¾é£kZÃùpNkd [Õ7œK:d7xÎRÀØWMbɥŇwàÂzAsÄ1$EC VN~‡îæ¥æǒ߉;< •Ÿ[ ¢L*Sn—Q’«²:ÏOâz”5Ë™<}ù¡è½ƒ‡’÷9œJ>æy(‚@l¢eóÃã¾ï–‘$¶â1y¡K€xn~ÃÇ0=,2ý¸þ^$qò6-ç‡s’$_6+O%¼4Õ%¯5n ãúªè¬ÕCQÌó–ü–ÅÐ!NôBÄr“©¼òe3.CØ
+x|Ê ·%UáA$‹ºo’š®Ëö½­BäŒÀçD {$=é{µ&^(î%iÉát67¦-öàðÏr·/)$e„|†¤!ÑXš$7´Ï©À+-ä
+—\‘qÐPçCÉ7_öóÇ©è”rÿd'/×ùõ—Jí*‰E8ènu•#•¸õîÎóPD0œ(^ÏM%%¸¡¤ j^Á2,ºKó,
+ØElF<bš‰F4Ò˜³†ÓÚÖœwZøÙâÇÀäòFð3$Ðû5=_R¢@Ð$a3Þ ÛØ»V÷M ˆÀḬŠ¶ˆlåÝå:§ ÍmÆVŒ]"çoð´æ%ôH‘”)îØ2+ÏÇ+”-²å5
+øP'~õ¹Û÷ÖÀαD†µ’Û*:Üå^á£Íh(Ff“ó “JŠ“ˆc:•ÄUÐK™§ùtÚôÑ·Š¼³SÑ&ÉìÌ›ý?s{ÌðÁªÝ*BüÃàáJ T±4°
+ʳ‚À–Ì~ð<ÊQ2À0æxj è„ $+4Ÿ¢$îà¦hà;Ä•q˜ÿAtœG¦8Ùÿw¾A§‘^jWs¾N¤…û§^ä]*Þ¶ï'4™œ&«~vè‡ÏâD“EÊEa¢å䦨%è-È;íÒ-E£®ÑG ݘãî¡DŸ
+–Žéfá%Æ-Œw I˧1/@¼}T#št(;Ç9‰3ðàp`П‰KÑ°²øºò'5aSxP
+ÿ
+ÐTf·ZÍ+ŒËK;E–.[BSÓòsˆ†žjŠN‘ìE-–‹ Ì©$eˆ :_õ½ˆ½P&\È>òëô¶«7Ø;WÌq=~[
+K%E'дHϹ¸÷›j #‡þÁ’7_ ƒ7fødV"¸°§Y¡ì_YNø[üÎßå{TUY„×Í•š(ˆÿµi±„ˆŽ…i#¿ðt›h' ‰LD$­å>Ñ" iœSHRh¸¦Ü–ìö©IRÃ`’|p³SÑUrQ~‚~<†™â9º÷b‹Si˜ïÿŠ¸,g-Øò›ñ?AÏf
+Ž´*¦‚_}%Ö«¡sŒÈtO¸%À‚øá% tgø$¯xK3†=õÆM,=•Wï"ýà‰¹ú9Ä™<”
+àÚ&« 00£„8†µ‚}gœ2¯TBOù×¾
+FEAضI3™rd’yZ~+O¤, AˆÄºð<€“À7Ý òü?Ó‚±µ0ì#Ýg?ý*ÚI¯ºö:ŠÖdeÉ  óë—©
+ÃÌ’wØ*ˆŽ¿ÉÎ œ«Eo}ú—cµ8Tí{q¦^^ªr"JºlœœäíM¸¢ª²"¾¢ì0ÒÚÞœo%q‡bí&ßðtLuü†£â¦•ëå¤Ù Üi5œuÚ“büV°Ö;‘:Ç
+F¢(×ÎqiñÛ^Ð^³7í¡âÃD~ÁØè1«]’¼ˆSâÇû¶Î˜&™YÂL?áû­"z ò6 Z{:F¤Š­w¨àe xœ`\œoè,•7Ê¢mä“‚™V¯Ø×i…ùèzYÔlê4·¾äŸ··¤“•=.(/¦}}œ£
+¥V"")L[\—äq}¹(šÜ]`qÿàí¼$ñ6VyÌ­Š,až^v9hÜ‘¿-|ôåïöUãÒuÎÞ9¦ó ã€þ甋(Ú-o~õTÂ@ð2ƒ£áÀŸ?NEo›ü·Š¤œ …ÙõóÿQ$c4àö€¤SÜgãBÚ¡ÊE|+ 2d¦à þe¼LräÈ• z‚¾C @ç̵ú&ø«êûoûYÐ=Ô™É
+Ç°ã6ýµ ¡náY™Æ¢ 2
+S èšÝ¶!Uáì4Ö}Õ‹ƒ‚Áé­>œS•Êi—Q<A°qìl¿úãM/Vü yq¶ùQ(%)3ù`ЗÊå°9€~DÑ+›1N6zCj¸Óôƒã“O÷/?`Þ x€¼·áùh' ´¶îHô>òë,‰ôá²Y ûó˜MÙ
+Ê×£}7|#ÆG-£f€S¯†ƒèm¡-Õy‹`ÅlÑïz߃x-¼­‰>1ø¥²ÜÆ;®ü†£\‘dÒ„·æÄxÁûiÆÜ|„&@‹*Ñï´£ Ò' Ü„Ìš õ쨆½Ïs9@p¾¸7n^}3Î'èMeÎ~éCŠdЊ„Z¥©cûä*åã'Ê5—AûŒøøÕ–ìôÚ²6¾±$>LfùSÌÛe?ò"8#¤È'ƒr…ïåwµÚ»ýîwL&(Nú.~še?©hé4ôŒ~ýcPaçú0± !gƒ2漉®yÀŸƒ°Ñ³UB*<ÛÃuz«ÀÏTéªå×ß ³ho¬Ín¥X½ŽÑ$pÅþy
+ë*iÛ.ÿ%ëÖ/.ÇâfRÊõ`F/w7–W?XZ¿©ò¥°
+³9ë½!$º®eY˜b+Á±oÓpò°†è‹ÿìq…õZé#d¬Â+§>ãÅGKjn6ºü.ò˜úp„‘êJ·Š½@ü&¸œCH~v)ßLFˆÚŒ£¦™|A¡­—°˜tÆWC÷U…°†{e.GȆòaD?ñs:y”r@t»°¡rœ9þ¥¦cöXƒ…Ó(7±O†ºTäÐAK’Ö%keŸ£YK”˜L‹E~0yCˆ‡9ª,åf ðqUUåRBÕœÍp9’(ì÷e\‘kÒØNÿ¨i*â\ò¢É‚ºj›Ÿ ®Q2F½vü%g®ßÃÕU®†'¢Ä¥ ØeõY ‘™îN1ŒÚÚsÞ¿¥Üx˲Ìü›ðL…ó[r Þ¢ÝÀÝÎãø½A|ü¨$¶‹ß&àt›Ü(&)®B™à9h~ù¤—Âî úL­Cx[ÉB³±½ìm¢åVâ«-.‡’by_÷„LÄÈW”#OP½†³€^‡­›^é¦Óï6“(¹û)o”E› mÞ­‘=2_§³x_H‰‹Þ”`8VÅä“ɾN<Ü)8æ [`ËæòÆç¿ þÔ¯•ŸÕöæ*Qò ¦"°µ©.˜ÄJqk©¯9µ‡QýP›AYÁl1É™9P†Ý¤³¾SÃ,žß°ARTg™ƒ… ¤¾æTuÒœTÛع”0èðŒm݆^ð½5oGàL±¦5æ­‡Üd`sösȩˆϫÔùúnf®î2Îo­Ù’gƒ³!2ÐuÛžÉ"ñ<2nb
+,Òl&uHãP¢¦jCè÷")‘p¿œ&fùi‹''²*sɶÿ8HÌD´ìåá_XXFÁ,ÚÙ–H§îÅa?Ø*JAÛ¿œû—l(ãêO®0˜ŠÅiÑOžË³aûén¬´Ò’¾ÏyGN™p‘£‚0YQ][ó‰g¼ùn8ÚÆúJ"ÐVF?Á~ zŒöùgÃìVÕº¹;¡™}Š’71½=7X‡ ›ÑÎçðÁEú¿úUp¨ˆˆfŒ¨ÍµÓ8„â;ÚfÖ 3™fi‰ˆLßmøæ$æäï¥¢Æ Ó´œx˜ýÚ°¼ãD+ÊÉGV;3ϼ/3Õ…›¶/)§©8á"¬l0<îCÅá˜Rƒ¶ù¥
+½çWä¾õvÏñÇêWÎîº088Ž ÛÀ j0ýÉù†,Qx ŒÝð€¯r:G¹_ˆm H»œ#í ¾Át¹œþQ”ª‰&g›’¨7ËîFmf‹Ö‘Í™Ÿb&¥ºö{´æd»a‹^â@hõ46^ž5Ä1š˜Ç9ÃèÐܵž0óúF»WG &F+ÄWô"¦Èîs:Þ
+/×Qå[ñ0ÈœQe¢7¨RIjA§áçðwÇQî,ÖDN§—ør2¶º9_S¦àëôyqrX›%?~9° X1ïë. O噃’†‚†îßç0ŠP<6úŽ^ŠÓØoì+»ÉÒn‰o–=ÇPå5qæ Çå‡ä`öà üŠu\¢*]EÖånWÐH&aùUÒëÁkçïR&–•A˜ÛoÊ1c{ø‚Ëz{ ʥ傧Âs²/lÂsxö<@B¡§8
+›•ÊÓ9Kk™eý£ˆ¨Y™rääLsÃZ]yÌ!ÒÞPõ‡d ¯Z »ö(.6UF‚‹sÖµPdÊR:Ôª̉<kñâ…] 4,è.u7ò­ÆÏ„hi%Zý¦ 4‚×ýŽrJ8ªê†“(E³3ÊUªßÄ¡1ì«Ŭ*Á-ÙC‘ñÍû¯âðúy
+z„@ÇÈ/ó½D÷§¿‚iÄŠ‹HÀ1? ‹ÎPVßï‚£åëîÖ ByIr12ÁªvÄÎ47ÐxpùȽLJ#ÀIŒa~ž¢3s¼ÜëG$máæ(O‚¼WÜiö›à2–>.Óã$<2%Á¥ÅE&ÅÃn$ó×L²…á—ª'vª(oÔ¸i "dOrñÝT’èH̼ÆfaV%2 TyïfC|ñ„:ÜAK&i)ðFÖ!B({•ñÖ·rHwjh°: ?«‰ù_ýÿ/ûú[&^E¡¹Óã®
+1el:•o@© òŠb·÷×쩈26Œ¥¶gHÓ/hãü1&ý'ìÌÙý1ˆé
+×þƒbÌVX@…Ô‰
+vûTDÓOßBøš$Ãí%°ão\I¼öNý(^I¢À&8!ãvÁþWÎp-CÙˆà^Í‘IÄòó„e¼(açƒÒ`ŠýÓræÊõhah^Ä ÙOW·¿DžUTeÞ%5)Å}Ô…q*æ?BËÔo‘Š‚ü9=T\à'¦ ‹)KE¬aAQÒSÞŠ8‘ë`h•«f«çŠ÷Ú?¬ÇIÍ‘ÍÞK¸"“Wjr4c8PbìôeŸ@4êë$Ø W0› 7Í1Ù˜nÇFFÒI­.¥06ËØ|Ê
+aD]2Ib æ}”iiaØT†Yx+F÷‰á³VofÔB®Ý±Œi!lnÕÂ9h ¸&öÚ^”ŒÍdkÌw›ZÌJÆÍ’óºòæëÉkð <:õ‡ÕûoÅæH² ñê~úŠ¸aÀ¨¡ðùp
+ˆ¶‘ü‚£‹Ï¡ˆõ†…з®kS AÆ£ìT?vÖdGø•Ž èö0!ŠªIîYª=¡Ë¤)‘TãEòg¼PBê#Œ…阰£&é«ÐÂèíˆ^•d$šå-ywà^rbýCQƒÌIƒÜw²ß¼MS5ys¦%„‚ $-ôz‚„ú–Xý+ä#ÐŽù–Çò£QÐ9bœ]…h ex+}©ÅœZÕ«;¹)ñ!)Q˜
+…Gn" ¼#„g’ú>ªã
+ê«üšmïØØ=ðÉÌÍöË»¼»Òà½èÊ ÚUµuwP–PŒ—pµ
+#õW“#‡3­÷Q¿lµ„[î&ÇñrÞ]’‰ìg&Ä »ÙÕ"+AʶJ2‹ÔE†‡?
+ch¼½¿Wã¿itLPÚÅï s;)ðJÀUx¸ÊF'@öÞ%{í®;uýëkyÈÁç×Q—W ½à µRêG!9ªƒ
+ïÜXµ1Ý">Y%˜K¦lûþJàòÝáçQ#8›ëñ ~à ¹ÿÚ<¢‡ä@ö³Ôî%`¦ öpK$‹ Ë5á¼O{Y~§T9) x ÅÅi C"çôËà‘µ›¥®Ëˆõ75c‹1x¥Éìgv2Q*‚hC õ¼À”ð^«r®þ”^lj­}ýÂÖû$.›ù:§9ë#,ÆÁÈgôÏhjZL+÷@v®À0ƒ{ œûë ÿsîA+ÃPºá‚{²à`_ÈþçXtpF3Wùp³ÐÞ®¹öõÎüâ×OìlŸ¦cüƒ;ÝœjˆŸœ6^ý´ƒOE÷ãnÏ{«èäg"ØBS0ï×ÜÖµ“—š¯7º=gòñ·*{ ·Wxd¥â| "½®ÁŠäM[À댙±(aÅÙû
+cDÅ®º>Ã{Õ tÅV…(™ûŒöex-ÁN1¿ŒTÝ€TjÞ'a±ÐeŽïnBÙX|¯$®ïÀ¾U–e7ê,rfØŒ‰H
+cÃVä6Ä’¯ïøÉ<QÁ(Ùå( º?4¼gä¦{éå³€•
+Î^Â'¶J„×ý(> ÄÈ<zÂ,"1¡T‰Fy~GφŒÕ[%˜]¾Ð±¼cÝ"ã9£·î'qMx3“Hsö“(1Ѓ¹ eå2³i–*ÌÏКYD"«‚þ*R–
+‘Î
+(feDw³dšbÄkÚél1{À&bº¿‰p˜¥9³é_‹Jù
+jÉ–Fÿ|Ӈȋ¿&¬/YΟ•¨çYS_‚MàÉ¿’/pÄÚ§ÖU†4ÅÛƒ“)Öûæw4†ø6}÷’ÌTM¢2!
+ßTÀÏíPâ¬,˜&´SëÃwd¯•qXó’8Ø-ˆQü±…Áqr—‡ oÖ¡5ƒÉ§Å^</ `†˜ûŽš¶oÚ–ÝÎ
+KbmŠ²ß¹ÆÑSÉ-ŽŠ7ÀÍ|côÏàÉ•( ôiîx;’)µF›ýöšÔ­UI
+}·=|ç›%?—|ÓÅ¿õ­èëh¢¹4ÙÒ°ÐX(‡hJ“Wd SûÜÚ8:Û6w*'1Æq-^XFM÷4Æ¢êSüS=À5™ô»^ÁÕØ?¸| ,P¶õþU¬ƒ®úqûL—ÅæPdŒû.E{‰*mq:™”i“vÿÀ$u+BeÍä Wgº¶™‰¶ho0¿U¾Õ;» UÔ|RebkŸ îÊ µ¤Ú“¤÷# €Ñi¿NoJ¿ÍMv§Ž,´­ &•¥Ên"y |Iy«Ë
+ðêþø´Uàù/áeŽ,E Ñp‡9!©ZKÙ`r "°àþ./¥RóÕƒñÉiIµä‚³èó;ršô°XÈTãÆTÕ»¾ïƒ©= ‡â‡ Áëtùp2›ñ?¾Š¨4‹C(výŠL׺Þ)OA;Õ¼¥¬˜Ê ç·k/­cT¼­£fԡ߬F¤!N0I/-ëqוZxkD/Ö‹C’}™¶ƒià[Ê_™.Xbˆ‰§kúp: a_S°à¶ãOüÈJ
+% 'Wâ(ˆ‘Åu~y?ª‰Ã¨FÄ´éKY¶øm{g?3¼_ÌØÎð¼o ŸÂNs!(16J0ì³y–‡¡ÅúÖsu€$ƒ ¤{’=Qu%Æ“|
+´šú?@þ™Q³¯ážld‹xì³k'ц9Ê"]èÀQͼš
+HNûÒãæöäiЮ^k@0(I¹Óæ,‹xðÈ šÈ-„‚Iv ’Uô=*‚¬†PðÿŒ-¼osÄòjE‚/ùY@ CS©œêœ¸^© ûMUÂdT9QY½y è „®ðÉ”™uWl~FEÌrd¡ZEœ7C[ ±Vc¿­Fíãðu<Ž`+Ùø&n"(&ºÆŽlª·pS£'ˆÒKšÛ~ÒG e`‘œ—L믻ˆìy@Ùw¡Ú²ñWWrçÊl@Ú÷t@õÈx(ÇFõà ¹(Ü̸VjMôoßÂî`’/¶F‘v÷’ ÂIx«[dÿÎ*{& ù,ß5fõYNžNæZ³U”`ÉW¾v˜Y„zÔ5Sfº!²cLCrˆ£XlQÒŒŽ‹›*íâÈE;hWÕk!ú0³Ï x}–
+ÜKl¢¥Ñ«ÿnÞ74M½1|oMŠ÷.Ó
+åIÍÙ\Òˆw9õdF5e†¼ˆv•€j@° ‹]{@ˆf¿
+H‰Œ—MŽc9„Owðº6D‰Åe£·µ4fVÙ˹ÿ|”ø
+SÎgt.
+¨´Ã$ÅŸ`Ð\tùãw±ù —ÕÕæc=þúˆOYâÓ»ÆI?E–-ÓÞ›û#!¿¥a¦Ç:®®³™¨Æ
+ª.k-6d=:Å‘zY–×-3´“Øž³…/uZÅÀ­-­¹ÍdÝÚÈ
+VÕ5È;rzl#_- õîÕ;©·QŽz“4“%­äI4e6‹Ÿ7µX1Y^zµ)^•¾³Lë4wŸ™ÐrÕd¶1mæ‡éjÅ3´)3©™Xù‹Ôcè#!kɤébL=ˆ¹4š…ñK;ú~Žåj½ $DE3Cöþ<Ù›Kè^:×Óš2}2v5-J3›f'–%IŽ ~2èB&]ã@l´Ù³\c·2eăb0º2#¡Î`­J²;“îÝG¹š¡t2ضC° ÑœI=ÒOõ-þ@ðE8’ ªüñ“µ#¢\1¬Ù£ `A‚Œ#ü°ö`µÆ8Ò#äãb&k½áÙ.Dhg ¡¢YFbMZ ½Q…¿Î,Dë/avUþQ&¡‡÷mgdnEÂb΂ä{=÷c×8XÂkÊ_Aö„qBtͦvïè'‘yÚF™ô’¥¸ì4HE §ÞN<#§Þ†B„ý@œð[£Ï—®zú°Î[gÒ•ˆ1̱fÆËΘá ú•O¬%»n“ÍÊ“Hey
+íÉÜÄév@“é§^ŒÃw¶»øDÒ$–.§qrf‚jZŒ™š„Íà“£‹q^ÆÁž° ³Ã\,¦È7I\… iêÉrÒQúQL¡ ©j:R葼8ga+ì¹zÕÕÚb`´ù¶³©–uÀ["Ðeៜ‡ú x`EÃ|Ó#‹b¹•«ÆÜS éF‚ô™¾¡íµ±!9²<Ùõ@ frÃœ/{ƒ`«…âºÉ•¿¯ žùœÚyÓIÎ×`H96„@ÑÀ룳G_tÖôgó½dgÁ*ó€`fVšD¾íP–•rÃúiäÁªìtj-–/•ƒÐÆ8èœáÃêZ^®Œí·§ä§Ó–ÒB’ÊNßl64Ú´"ÖIgÓ6¹
+ÔúȬ§NH;ñd½Á\„§ [y 2Ðë X¶ÕÝÞÛ¯í) èÜ a/•[;JŸÉ@+¹¼ †G ±âÚx÷¨x¦ÌA}·±o…›ä
+¯i#\—Ç}1ÿ±a—€1õ\K_­äwžÈΙ…€aL'GU¡«œ#TN†Ù8sCjêñD]¸NQyœa%U"×Xp¢4Ž\~­:
+‰x3ë¨Øòî-ÞEû>ßœ öô‘šÜñ37g'Tàÿ`¹óðÆ£×> Ï ,›”\YÉ“Gµ˜7—1Z²G¥ ÙA·#Ûæa™0즈`V¤š”šÜi^J 8=¡×«ÒoÎ8Œ»Š5h1kr˜´mÃ8‰Ê¢ÌpÊGù¢R(ç&bØŒÌmSôÆzä®$q ‡žê1EÌŒÕìŽs¹"ìö%ö¼›::54’ Ÿàc¾Ý"è8 ° ßw%Ba—[^‰TÄæ¥ÔQ².æÕ饬Àâ)Od6.°ô˜rD¦çwg ®àý[8—]s[X¦‘å½XŸþÁõ&}]ExXD°3NY#-„¤©“–ô°f)%hÇsUƒ˜>°dvr<ÝcUÈ\L·G9«; 0”ζ¦zCK¶óPºÅ$|;M‰,{ϾßÙék‘kˆXü$ ]Ø÷B‘G×¢';­öLT¸Hÿcôì´J13=ôá ÕH*q òÝO> âê‚UË(¡yÁÅM¯g61'ðì­Ô,'eÁC?Ý´€%£ÌFÆì»é…>
+® Ç’ fíCM«|%ÏÈŽ à±4­ïs’œ2!’ǘÈ*攅λDÂ_3¥h¬Zø/<÷„T?ß¼š Ï]¡¬q§= CWÀ)úÞE)‘
+ )‹›ší˲ÄNÂYØl ‹èæ¤= öj(¯d÷”Â=Œx€äb&¿ñûp½¡§‰Þ „mÕu@
+þ3phs¯Ôþà¯Ì±1ÁO,OÝ{ù” Ý’^pl­ÀnôåÓ`<Q
+š9@®q— R”ÅõyÚËqn|"êhæ]ÎHj©¢ùc¤ èÄ®jIbÎR›IéáÔVü
+[ß`ÍÅT&îù•ØãÞ6`¯57f°Àkô‹ÂɆ™¼5çÚ¯6wKV!q>ɹA§m§G\@‘Ztí š&¡Ömšñ‰ÿïBÍ‘[8;Éz2ZJŸ'áƒÏëTè&j0ïe.<ÜŸDù«6ìÙØUæ5ðPËï )QolaŒÁNQÂNASq綧"™B<¡¾.—ç«d-yoyJŽïöÁ¬ â8nrM
+9ÓÀfâ‹( Öæ”X‡5áb„Ï=GC(ÐjÞ‚9w(¼Uì>Dßl˜Ë¨HžNŽŠ¼3®q®â_ׄºxNy,jœØ „äÝCÑOÿ*ëmþÀè
+FL>#Ët¯{ˆ¦b'ô…Ý5©Èàñ$'ˆ(‘•/s4àtúJD^Éßøü|sj\ —x_¡«3_.ò–ï麗Š.„à.ÖµÈÈo%“ÛšäEƒßVDpÍô<œ`ô,Xš•¯4k_$²¹¸ßÑ©9^q§â•¬é“ÓÀ!¾ñÑ£ë1 ©
+ò”cw˜~—$Ô9²“¥8&ýóÍ)re7}ÈÀ²\ìí]˜{.
+z@Ö ã0[{-R,˜Êš|ÞºK˜BèKÕ?bÏî°sÔ]‚ÞaÁ^¯GÁFœÚº¥gh/‘+‚<eÁÎ`ÒìŽâÙñ§,Öê.90ôQÄÎ8#¯h•ÐxÞÄ]ÓJR$’À$#îG±½h:*JìGE¨äkç¾
+í@ñéESBÚÍáH„>Ê>uÅ&¡²'¤T¸Š~F#íz-š†WíeÜÀRy#ãZä=(•D>‡Wk®û÷ýÊ’þɧ¥ëQxÍó¡Þ¸²d 䡵Ï•IŒ«ŠKÕ)Z%00"ØybwBIÔÜ5ÜPñW€®#){"Ô}æ­ ÃYif¬uLÿà
+M’õ³ÉÒ Øœ] +ö¨IŒœ1›Qü7’‡š¯‰tNNÒtm;‰KÑ×M6Ãøìzó½‹Ê8,q¶9O^WXª÷]’YÀÜg9ŒX±ˆ@©£ny—@‡S’”‹uKuD`ï!EìåÿŒ—Kz7 „O;èúH‚ϵ³Ì-¼•î¿Í_$zMcdÙ‹Äv‰M…ª­å­VBæ!*Ì0ßåU³¾oú¯Ç>)cìÄÂ`õqzxaæÞ "ß=c )åhž'à“¥-Lm`†“× wzD‰G0EòßýüAùßñ\’Eb³MõÎ9ÆW´ÒÔåéÞvƈ
+"Þ Ìú8V.¤‘#別 qÀ%Ç<Æ„T䉫à¯ü×YŸ'¹MƒfþòÉæÁ9véï·ô—¥ôÝ-Õ†4L²SV¼ôÜØ%b'¢ö¸ÕøØ;7¥°Ò®åÉZUµuªKâ•Ì€?ªHCà{sùÅÒŒ I-úˆ4zC²XÉwÚ%+d}êÇ…†9‚Ÿ¦â£Oó>‘qV,Òþ¯¿bÐÓæ«Æ@Ì,›„)ø‚ò;Åáå¹£†ãtB†ÌbI·ÒûØžK’'ßøFwÈÄиµñ\‚‰Z ©ªá•ùéB/)6\wµÓ2&<ÅÇ8N=™Öd*ÞK6J€pZ`‚uS²×ø˜¯™³b—X(í›´‡ÊiÍ!Ó%ó$ž(¨…«ÑÿD¡ã•våkÌå=H3žvΡZ„ìc“TÅÕKÉ`DT‰'dZUãÖÌ Â
+Ê^‚µÊF¾¸é ü_‰Ù;ýTr †ifS “VÒ_;_Š
+¢¥Ë®hÃƃœ úüÜçQQÚ,¹\
+›ùŽø}>D–EÉËQÃSØ™GrUè5uô<¼í' -¯Ë?¤•¯UÆ“íðÈí3(Ê>€òZø/>[^¤(Z‰ô9¢ »ƒ;¿=_/1Úg¡D…-¶Íì˅ŸüÆÊ ,‰c‘jÒ£POéÅ$®r¡•£Å›ÁBF
+¦ô¯t¹«²(#"Ó|§â£S*ÃáNŒ'‚ñòÂd¡…ds}ê{žepTQˆÉûðd­ïسÒ*‰ºÆd­ïÖ·‡"t3¤YU RQÉ4^ÕPbX5ö
+̓5tiÍ<†³*asAõŠÔºÊýýKVå°qöÛàW¤jE‰zŽ)ZÃpæºEœ*À›˜ÚçöÐò-^Ü/¿åO#cÀ,£gɽ"¢*#/ì‚¿z)ÏÏ>–Õt#i`F›ËFU!ߎ&ãÞmкAö¶â&k*J=º#è²PrC ›^Ä@â¼D•èŸ“õ7$`-ªÅ‹6
+–Ééi.k»¬\+ðû6Ú´ºÚà+é3&tŽ.\
+avÇý (R)!ŒH´ºE2öñ“©9ÃÕA}’ùuÑùK:ü< 2Q¤žF
+öŒ¤Fž~˜Å][Ã=… ö82IK½¶CP¦ŽÖ]þWïÔ„ºà×ç3¢ygä½vÅAÞKÇô›½Ã"›ã.U"±û—ž†­ç@[£‘-ëiæm|Ÿ@BØ(ÍòÀ—»TÔôz8RƒH(::Ü`2¾‰Ò1]&“ñlã¿c_Єˆê/§ÚJ‰ÍçΦ‚.cÞ}ãÈ$5&­^Â^>Aœ6t l=I5>Ú°Úˆ¤åÑ*n b³”°ôÂ4vëÙzÍ`°èëK6´ÿà×9=Q¤ ­‹ E‡ò¡\S™;„… •"ò)†f’S‘š,7bl–Õäß±CV³ë>J˜ ‹ùx5Ê°á>‹‡Ù³t¯—£] ¹\×E^Jœ=ì-èBhwßÛæ¯ã®j§ÉÏV§þŒ@júÐü.]!Ÿd….VœQûê´ƒ¢ŒvûÜA™ƒsW Æé٠ü‘«ºj×Ëž jK9J“å¡;’IöAsˆþŸT†8Œ‘Ê Ö
+÷‚²¸G1aõØZ.ÈäϱìèlX2.æƒ0˜Lš#Æ”wôÓI ˆ ‰¸.sÍcFIì8êöʦC=L ´Pó€ð¯äî$Bý%"grŸÇÚ™Þé&» º_7&Q÷ óùCøÒhz{=å[¬EYf¾.c @•é×!NË ƒªAnó„s줄_ÜÐÕ—þ&^ÉÔL;‡¼²#ÃØ‚áGw¸ϸ@E“!%pžsZokRgpèî@ŠV(\–½H êUaâP¤ò"m<7<¸Ì3oÂG=Ó/(NÀô¯ŽÿïÓïŸÌ‹F+ÑBuºXKàÚCÿtÜg„QÒßQ[öµÓ ôzRjÈá²@¸$#a=ÇëªÂ„¶ƒ“ô§)kU¦¾<nÞ%ÀƒÌíÙ7…olxy3Œ×iK¨qÒ¿÷=Hú¢˜<†½¿Èú°¹dÍ[¢CXi›¡ó"¡î¡Á¬W¥Nˆ¿)¾zMÄbzÞ¡OöâÀ}ØEÔvΙæ–Ú•2Y`Ià(ä˜Ã!Ô¡§–aÿËRæS|}éüG"餂é 2ýºÎÀO &ÁÅT ähö%<\c'93ûÒJ`0nÍïÇÓ³ÑPÂ: ‚*C=•ÿOºÎ€:Å}€ØœØXØ ó ©ü?âÒä
+ãE‘ÃS¦ÂVUê™ó}> ™Ÿbé¹ÕŽEe„ó%¨úVØ«4³ò‹ØÐÏ,hÆË‘¯òVb5³@žº ÏSGiWÅ~ ýúз£¹ý¡Âl‘øöìþ5= f±íó`fS4¯ì¿µ÷V•Ûµ—¾
+œÄeX0èóxâ‹‘5’$élóKWb½d•5ö’â‡øüžë­sU;(ÉålC@†¬§æ“BØžˆ2
+úàˆ¥UƒjþN‰Œ+’¿vhʧ…‘ïžöØ
+þ?cM½‹žÊûŸöÉ"xeUáу¶^^ ™õ”Ýô.„šöè?8 ¯7øe,L¨ìœ×“MâYQº .fŒECÔÑCf)yÎa\JçÛcÍê\œÚîs˜¹P¨írIÖÃÚZ›ñ‰¸zy½äzJSÝS$­ìUM¯}MÞãºÍ‚äáE¡¹– úzq=M< –ÉÀoBž¸Ýð¿AnÇø\éù«õ'Ðýâ´‘1Ô_¦1ƒ.jGà ¦ãòbT•}™ë*€‚ÍÖÒðÍà%:5Fº:Êyãéñ›Ïµeâ™Q³¢¥`“q›0žžïR€a2ÿ÷Î~gªB"
+_òh§Lõ=2• (E¼ÁÍT ÐñRµË8d*@ÕÖ¿gs3U þd¤áPênBª ‰2×#2 üYä„S?SeÚ‚¹ÍeiÙ#R A6ඉ):D*tTæ§á"bQúe]ÜÔÀ“&7…ëùe0é eò#^ëG* <ºV–é>æ–„@°% H)kÅy‰êêT͹#SÛßϹµÛ¹Ë}jÜ7݇ϩ3ç·;ˆ{¢ú'[¾UiÈ$c
+IBÍÏãþx˜g¢2y9ί£ n¢âRŒy ½$ù¨ts
+©•Åén¢R3p
+ý‰”o¹µgž¢ð`k§<åyê zä)Ý'"õêsºyJ/c¦ö§T?*Ãïz¯ÛûüÌSê5eÕã%!O&ïyJ3Áu«vavS™ ÓlYG7Oi@óÌx9ä) :
+²…m—æï<u‘§©ª›§<Î=òÔ¿ˆ¹œ\©-2¸Ëz­™†aÅ-³Á LJð=Ì:Ì„Âù}v33òèñ¹w@” ±`V°ûýuÀ0Ë •–2‘xvŒüÞ玘ƒ¸BŒ (t‡øad©¦ñѪ]‘™ˆÈ3º+)²ÑÙåšwÍÝ:gä@Ølúºmâ˜BG ˜™º d²g÷Mbe“c()cNþ9íC_+é´Û0äBNîùÙ AÐ-ŒSaá|zíº[Ù/»Î%aSsÛ~·k¾3T³½K[ײCÁU¿ŠÎÐaºq ieýMšÇµÃ)0”O£¦sûs
+£ü„-œ "{Ê¿°VbBmãWسœö—¾›»$Ò˜193‚èéîâ`ù`·Óä}R¦BO €¢Xå
+ß1ÌéW}äñïñ¹·@7Mp¹u™¾z»Ìgo/5ƒ"êÆ óÿç
+ž o ½3'=ç!Kø2T GÍÌ—Q±èoÂv£o›ˆN¬ » ,df°pyy9k†é³SHQ’j&¬ÏWé7ҭɵ‡cþ¢Â=7†ãå¨9üÄöh§—ü>œàÅ©ãUãÇ9éZ¨\'ìpÈ‚W2f·Áäò¤ÊÜZâM:“TÉBß_Â{¶ øSöË©-uI¬^ãÝ5[¨KÛ›µICýN­ ê1)|“á’ÎñuF£äucþ-ʈъÔ‘°"¯ön*Pj¦¹W$2ØS¦w¼%’%;Ñ_‚–hv‰²L³¯s2ÇÀ^¤ÓD‰fb¼yZ® Ñd¹¶RCJò¨47béL[fô-Ðâ¥Y|™’Ê.Y¯)áÌvc‰Oé-¡6ˆCMg‰¨ê¾ksÊ°-°?¼Ó¶Z©ËáÚìK, š‰5i¶`´J@-´~€TØ? š´?ôÀ@T^E±R5új•13ìÅm9¥„.a¬ò!&X.îGÅ̽A\ŽÖÅkiª³tD¥°ìË{fMS­ÛZ}X³¤ÅH#æ! žn7ÔnÖNtO!,•yÍçËHVúW4¡üÌ6Ýl¼ d€ö zßØ—4</0¬Þ> $Oƒ{ yiÃŽåÅSØÏÙãŸè06d‰#7f{B2nØÐ× Z[fíÛ)ráªi‹±wY„7¢ ¹Úʈ3kySã5¤|u甦ÝØm¯“c0ì!kàè^0¶ÆnÌûšm+NøDÆÆ”HšùbŸ¢3U‘G;35Žò.˲I62Q“4êÖ| ImÒãSú’;äþp9t£ÂÐÉ $“dKóá1{ò¢üªçä‡Wý\–}ÁrÀEŒeYΗ(Á¾“ËHuYZ„˃—™\†+,ƒÃ'çÅ ø>$Š-žçXj¡$Wqia`+&(µ-Øa!Ýœ8’šIYµÎÁNmd)ø‚àgŸC¶E›<UV&ªÃœâ@ô)@|—xÉ<GHQqÓ½ ¢gël‘yx ¡™‹&¡òª#ƘŒÆ³[cò£WûSwÅDìXEèû/ÿ6¬–Î¥‹å𪬢K4ùÜþÔ£:éšcTƒù˯1ÍÇv'uzõbcñèùíorn·ñ&ðñ*o’Yx=ú—V:| Šè™´wÞ Õ7ûxR tI²Þ0üÈûce¥‚wËÑýö@rÚx)þÇR£í¿½ÏÝA_ïÜé÷uõÜøë Ì”Ì籩[—ï#µ¬›7Âr]ñSÝ’·Ã6™4‰fVeRÈ—Ãx† •Ò+ÐÆéå•k‡lfb}ÉTúçè±ìפƚQ¦nZ(ôè2z‚°³‚Ì~2ƒ;1×p‰‚Ÿÿ9 ·CqŒ¸x{tó•_H>wâUå5ë•}¨ÐÄPñ æÚ®]ØŒpD]¬ÎÌ"dòP湡
+)$­¢88È Z³yw*“Ù×|*»½ Ô®ƒÝ«qAH¶¤ž(V;û»ŠÐ©öÓ9<@WÆ·N» ²ÆÃDñëQíC[%×ê>å¡4„°÷A<;Î0¥HtÓ•x”ñ‚´Á‘‰JÄvùgÜ5É3Àå¹O‡nË«vLÇ×^Žd¾ƒep+Ž¯±Ñè~£æë ’•ñ6¯ÎÞ(ÓörŠ¬³ŒË#0™Ø1å ©~xDï5ÛÄHˆèñ¹w@ò8D,0+ƒ¹Y_ “7+2æÊXÈ9ˆ Ò —öáØ»qãa¬|>dZÍ
+þÏx™$Y‘+Qt¹‚gê›1'L“ýOë\Éõ #< 1«* n*$on³ЭNc)æ#î5v ÷€á€®ùÍ5`8¯º §:×€áÔø0œ^݆×óû9·É¹ßæ6÷W9“| Þ>| ÿ\«ïíƒO1?5:¼å º5"±ˆ{×Gßr¹¼qùš/þu£Í©bçƒ$)ôhê—(íåìÂÞàË™ªÈžmšÛ#ìüà!<ªLkÕ´"2Ð~Œ÷ ¡¹Ù!µf‘æ{Ùƒ¨±€è¨Xꟃ©•^Ñ«A:–Ù@ªÛÜØ»JCz°Ï`Ø"úTú~ŒD†©æße,ÎMZ¬^ôZ_Šò”|úç`ºs£…’Op',<{»!UÞTvÞ ³âW0§Ô|çªÈ›CîÃ2ãN’äéÛ 'WÝ@²ô FLP?jRûÕ—aJ'SQ³²!¬ÛOMÞ¹
+:-˜Žœê<E,úÅ—j.'Xá'³bÈ"5ƒ&‰÷ §—@$hÞ1@¹¶çÉä2ë(~®¡Ë"ÕÓž¤0— fþe3ºžD¸´÷ð4ÒCRæ{üø–˜†cG(.eXÝÑ÷!\’•xÐᦠ¡
+TDA\{ùß!4õ{ä—¸ÁCÔãAzêTÅ.!nJ³!úçTæ¦Iæñ«ÑÉ· ’à $“cuKæÞ¢ôdñ
+rëS˜‹Ü
+S£69>ŠÛè–×?&¾2$ƒÙa†²ÏÍñ…蘂֋7Bö%ü œ€úçúÈ|¸
+)cï*›Ó;˜"y˜ÈÄqDê}íä«wv*­Y‚¡Jˆõ #nÄd`SÄ&Å –·ÙD
+çA‚ñ\Ñö$4yçáˆf5 ‡ ±CRàJÚ²‡5Ej{m¨¬(–Ñ ×oRŒÄÚ™a¢FçÞ„y;ækÃË\æÆ}ÓuúœÚÜÇüRß;àÏ&ýüƪh©ÂYª0 Ž+Ó~y˜&«D­  FÍÞNŽd”ùÊáx”Š‚¡E¢NÎz2D` ‘6Tq¤÷½ x>&ûØb“  šÖLT<+â5Üq+ÌV SC¢Îé*D¡fv—,÷‹c#xJ#Låš­„ƒr“ âú+È1ÃŒÇÑ|‘ÈÁþTX˜5È€8á àHA¨ëm[ÚÚŠ¹øŽ-èKÛ?]P䤄C\Õîg;sÛ ߘÜìÍ8=kÚÔÈ }RXaéc:E.Y"ö¾Ñ•uP©VÂ0;¡ ÔMmð¡ºÑãGþ‰8lÜ‘BL~^Ów?…½C½yæÌ1Ÿ« [’†0›ŒÑe—sדbáÏXõ’ÞûËe|ñV™Qøã¦Ùú’¦e}¹Yéô8¸£† rÛ8*;‹Ìz¾ó×µ´ð“¡)®ƒÄã½iøµA9Æ•Êp:&£æö† —ä†QÃæ,7%¯¡ØÃ!æ ”¡áÿ¹¿D²(L '«N$u‹´Ï…òBš”yCع¨»Ô ÂdV IÛ—! qy*å”ö¨—J|:핹‚> ùª§s»{dÇ¢F5®Q/2I˜Zyî¾¼¼´gŒ "c³E$…å{)]²—³…!d±­€Uv¬«§yìg¡‰
+†pgÔéæmÒñYd†ÉD¥êŸÂÔBËY®«™½­ò °wM ½#îÍeɧM:ëÛ`åcÙ_’…¨SÑ’y
+vÄ_òÌ}Nc'+¬_›uJA©…lWzƒ0ìEœÐv3Ðrûô@"Iþ÷ÄbÑËñá\YT ¯â‚Éb±zO_;ƒh¯ÖY‘¿–PÌ „Ú'L–>œ>8úqm§«Clž §-s瞃£'‡!çÛœp8z’ÿ–]Ù3Jɧg7ˆÂÙ(ÉÛîO1êh4…Ÿ±¾³e ð>äSó‡³0JjÜfàb`ûÔeñ°'èbPü²z[á èÓ@¹×¡—NSÏÏG¸
+Á²§ë
+srx8¼žÃäD>Œ]§«§ M>(ÈlHá+tÃæØ»õŠnœO-ZÇ|Žã¸ —ž¡ƒ:ÏB6œ‘ô{ ±‘ bÁÐ’é²EØõ“òTà`ð œeæÝÍB&/© }‹„Cj6² `FYÆ(Ùïf«rÎ4q-Š‰ëœýýî¦
+÷éyáñå˜ ñ±ÓWñþ®œ?–ÀÂ(½j×jgÁé#0§´0-}½anŒÂ,$º8Œò ÃÓ×zdÈ)nÐõkßÀ¨ÒhSús_ír ]%VeÊšS!A,!ÄcÍ ê¹gÂVAú2‰ OrL®…ÝÇSÅÍp!øø2íÁQXh` Iû®Æ1ðkMJb¹[ÝNnmé†ù¹ (Sk³%ÿ• gkÚˆv›ÙÛ¿¶âÃiƒ ”‚Jpì¨k'<PKøjÙ|œó.ò\¶°ü<Ø@T¹¤h‹qõ.T¥5)Òôô\Å‘ÏÂh•â› •$Ö­%×DƒÈ5¢Ê¶ºT
+kÚìK ~ꤤûœ Š&Ñ­í9´Oµ©W_–ʃü9 ?þç`ÜAïò ô„'¢üÈÛ½Û羺зYWÌvî¡ÉwF‰ü.V‚vÔÊÏnfq@„…X>î2Ú-YIJ\„¾âŒùã0#õu9žH{wc$Ú¡kx=Î Š…~Ð×”– U¡4ú$¿!¼‡¿Í1̨x(ä-"£É_¦ŽxÈ=Šá…¯‘DáÜ— …¥  BySF`¹HŒÄM”=oˆl”/Úu<i·P‹ý©B+ºâY É>Řá)(ÿÝç`&hägFEI5Oaï†GzÈF±Ëðtb,Óv’®@1±&u¼%’z#è9¶Ÿ“uÊ—›ù‡Au²2KóÒ5qPjå©çS7P–áÙ˜¹nW&j~S†Y :ÄĽF±OÑm¸i/÷¸dQer[>_‚˜Yçh3ñ†có}i4ñ-Ïá.;$¯Cyʃ Öða]qè
+Uþ9¬B¦Nü“ÆYb‰|ÖPç´!UÖ¤†94ŒËÙ"Jñ|JsIJ!‡1â¹0fÞçL±zåM!9îˇôÎÚa2#b·ŒÕ¤÷šFòéB Ž àÚk·õæË\–LjrOë±±©ÖgoƒÑ;kšÉxõÿ/sIŽ$Šž îÐ2…„ï‹HÅVy‚µj‘÷çûîIf„˜Äp0ÓýÓ=Ü–¿Ìcé&ͯàŠÃ6LXl踭7×ú¤t¸Wëzm¦c±p„
+fòYáË9Ø)*‡™uÅ–¢ƒ˜¿:íkà"__«p‘PÍÊÏGQéFàUörJK]R…¸÷1¸Tø;T¾ÁJL熺¶#p mˆ²1«)äçUgÐ`›‚R]µs´’I(ƒÌ„€¢”µ{7ô$¯ß©³‹ì*~¥­OJ
+4›†[š}ŸCbòñ½ÁÔÌL”¢1ö(ôFl^÷Pˆ×
+(’G¥yìܬ=`žŒ®I”ˆ¹b¤b;•T°¦˜fL<ób˜À毋ºñY©ÙU£7õ
+Ëõï†KÛ‡2Ïâi¦ŸpCW§¤PÔ4yA‹TÉY¿(ÞROQÒqÓƒ*0Õ¶!Ë& Ó< !ƒU³ë×´‰l |Í/±-Uœ:ÛS2±AEsÔOÅð"µˆT1Ò:‰êÅ—Õ¥PT"ÏyçîhƒÑKcør
+b8EÍ}<Md¥E#Z›A¶“ƒ‡’C|¹:þ$|DVtÏÃ
+&Qz™ö1‰é®•f×èçíAçÐpãc>MZ01ƒ†˜з"ÔÌÔ0úGb$HÔ‚íˆÅœÂÀ*v1‡g0㑨rìÁ†`LŽÓ\Ù½òYâA“¢RÂvüä !¶Ý(ü=þç(Ík¤ôzù±›&¸®œàåÎ=5ÙîJéˆ(¡`ÍFµ‹,²ºIuî‚WSD™²‡ð‰Õ†jQ2\4ɼÌÄXÌx¾¼ÕÏíg3&›³98¬®c{¹œ¹eÅ„ígP—¬šÜn+cfÄdÁZ ˜>(žç0H¢uP
+eCëM„Œ‘E›û˜™CâÔS73¸NvCB}3¦=:uU‚çå¥ÄxÕ?'=4]¤¦ôækXjüŽÖ¦Ö»Giñ¹†rK~qVÂI”“ý
+_/²‹Î¸¤kŽÈí‡ÿ)yÅKÕtÿE”ÒÁeÇE—¤5”Ýÿá—jÉsÙÑqÓ¦ˆMÄ¥Ý×s.Csþgø®¯r†á€ZiyÜ,é¬B™|>·¦|ƒxiÔsñ2ÌžººµÉ¢-î€_-{ïèDÄöŠFyýô@rظ(þƒšqöOç¶3æû/úÉwÃè æ'…žº±
+GŸñìxÀõáÐú•CGt@?o@§ u]슻(E¬obÔýŽ»c¬øÔn˜ÓgŸAßï¼M%øíÏðã÷¿>~ûû÷$/Á3SÈà>¶uñ´RëôË];$.†Å¬­Ì›6: bi£‡ïp®{$!ìv´ózM„ âfÌÿ+Ê…/ˆ¨¬+e5“è±wÆqbj¤ˆOéYȇXaZ,hÖ½½ãWÝ@d^\›/_8Iê›÷¹qCÖ ÒÚœÒXÓØU|-…¡êåîœÁg)óèDT¬ 7bÂ'àÉ
+qh+Êp’î µsa\]G?;Ik”šËd´‘æÖUA`lé;b8Z|íB²v˜vžv\u>GùÄAHuöÉÔ+’ èËÜÑr]èJ¢ª™Á.‘¹ýüp0WµZŸŒ¡‘qÓoƒ¸mà–:övæ]Á3¦‰½g ÕÒÄdåIPÉϳ! {b$ˆ³3o^[¶gl/GíÑòÆ.Pö¯}UäàÄzçnWUÊÙ§BZ-ûH“}UØ°‰FJ&í s×8)ÎÎÚä­¢ùÚcÁHt­èŒ·çT½Á¬{!³M"& o ›G%Ɔf9€H‹{ÝÍ:ƒÜFD¥§"#Õn;zÂ8ÖâÿgïWš2§ìjŽÏK¢Ákó᤯µ_€`åéônTkÎAM Kp@HDH–±Æèq]!C¶œ|ò ”Ê„ñ´RnNQÈ€Ò û”.Åà£ãbÌD^ SL5¯ØEL¢É¥ û&Ò€ì£4æcûäÉ´4”}L—OâÞjÊ×UÕÁo]¤Ì Á¬éjùã±%oR\h]ÁäΫ\@º­”.†‹XÈÕsÔµ‚LB©ÝÚ0ø$jÌFšÌ²²< .ÃzÉï'¬X‹ùÚ#ÁÁÐfâöª Ãyµ9&dA m
+†\ ƒðŒN®XÀ]Â3ÆUœ°Æƒ¤¯~äíVZ‹‹Ý‚¹W 9ƒ¾ßÙšµ\?þ´`Hd?˜âmÅø
+ö²(à„²ì
+bñ¿°KËsc}À&QŽ¨—é×»>¤\‰Ü„3¹ë[åÏtÑìmFÿœöàmú¸ûrõÁ²ÃAè—½iBÏ ¶¥oiò@U:QSçÁ›¥<P,³É¼±ÖÝ.ÓþkÒ†4Åx •ˆýr(•7P½>}õDH¢†ØŸ/§„-àSŸ,Aö±
+ÂÏüL"]—äù ±«ˆ§0ÒîÆÝOŒ-ØòaÈ®_ƒÀ•øÞPï^U–eASøqò«ãLà¹Æä¥W_ïL²†>ì¡Ï°L"èE=Ú9ï—âÓÑË”Åø9¤ý]zÃbSó£$ÃIÙá²!‘ƒoÊ+ãƒ!¶(}z¹CݹZÒë$õ¦™V‚Añ á`á“g»öÞñ~šÅ©{ˆU7Ç(¿áüÒË÷?†PÕyñ@ss¼{Q§vØ”ŽÅ8§Ã¡C¹JõK|†œ[e2v½´þÛE4‚0ƒúÂ’¶Ë¯Ÿ,ö‘ÖðAœ—¼§C­ø¬»² l“=ýµ„²¬º…±|rÂûpµºt Éy»®§0Yl:›Fx™þ—”GškË님ôØM ºìWæ²TÔ·Á¤ŒQ¸ú$»¹¯HóõÎrš3Œ¼=%½G¯þ«k‡Ñ½VÕo…"_N0¢ênšIðM Ý g7½x›ÏýÕ$„©r߸3@ˆµËsÈÍ+¶ ‹!Xs~9FŒ“HÜzL€‰ÛìäÀÐ2pŒ9H&!×6ГÔ'ÊäÂಣq?K_å6š3a»Æpo`HçÍ Ê
+ÀIXܧ׸œ.30dã؆"[ŒKF ê/[‚-ÕòªA®†S×EA¿Â2il¾ðÐÌŽbOû®emR{zÞ’Åo bkqC(7¦º¦L%ø8¦ çÌdìf: ¼Æú<èÄLÖ´¤>HéÓæÉ eSzlÆëØRÒ£Æȃ0k“mdM°9`Ð_
+Sc1ƒuƒPGH"b{9
+-SÁíGÑ2ã“ä„Ž
+2UKŽÐË"Â'
+1¶šœ¸XÌoI” Ü|oÏv&Ö%ÒvH”Z"-†&÷9CZ¿÷pžþO5?—¸FBMY{¥„çäÕ_³Bx°™;ªÄ†³x‰Õ @9JTJ3œ=Éb±5cÅ5 x²¼¼oôÉ Ãâ“àFº!¯/sKr+Š® öPv΃)”ÌtµA^¶©ýë\¾ÇÌú è 4u?ƒ|ÃbGL¹Dˆ%mfºž30ì¥Hëf€xEÒ«1ÂÓQn¨¼ìI¥Z䑇…Ç;(±4\zàQÖ}‚’j¸Þú6(,+Ín³)FN7Œ”¦òÎ䋼†¸¬½m®4È/êʤ1‘Ýa°Y}K%MËWT7_€v¬“¼
+áÎ!CIq˜.SŽ©…Ú:
+ÿñ›Jçsá4.ÖÌ© ÝfJ&|ÓñÚAÚ2õ\ªÿ}êÖu§¼ÈŒ[ÂÜg£ƒ( åb€jögEʼn1¥‡‡¡ò56>JgÒ9ª€!ÿà¿»"éÃ)2G“8S‡GÒ.úòL@Bç-ÈôÒI¤ÜY ¾T~Ac°*õíþ%Ü/.…Q!Aü\‚¥Êsk>
+#KÌ—–G9 þœÏß?î㜳ÒÍîOéßvïúµw068nÕdü82÷„Šèœ=͵¨’Íøñz±iṃї=]^/WÚˆÌôiÌWÖ¯6›Ðedäɬ§Iq3#‚¥ûžãjºŒ1f}íç§$Ï'52±R$CÈû3„I·Á‹ƒ¹*hûCøq\ vùqp©L伬åõ±±ÌX!7ƒFc ðêi¤NªÌ}ÝX¨ÝIk…û±OaNi#!•auº/ª'DP†S´×8ºšüœeùd¬‚­ÄòÎD”"ùmx;—cÖèØþ”Bͧd’’çÍÎá ~…p×òAyrÆ¥”1 ÔœDV°±}ê
+¢#l§êš»_YÛIè«Û Ñ"¦ÀMÅ?Å*òN˜ÔòÓ Wiàù&,—÷§ðeE¶;æ;ÁbeœÚ0òW˜ÃZC<yE„»+ReæJ‘myp·€Ð’ROؤT™ îÅα‰ðYNAr˜€„¤øž³ôST‹"9Of€JÜŒµÉ…±Ì$>Jvo»ãиâÑù¼mÃÒ;{W”ùøo_ß GÒ¼/kûú|
+lT`9*]µs&*ØJ`J½4“»1&…ôW+Õ`bf§¶I’± ½)½9ˆV3ú îìvN²Іڣ3—z‰?àm¹z£zåLÊ:Û¤%©ð¨4÷6k&ÏçDŠfÕ)6}¢(eb›Ó±È¹ó†œ}aX §«9Ìß›z…ãÚ;žeð¦–53¾¤¦mjHšj”Gw©¢ÆŒ‘­?@ª¼û
+« Àçe<ƒ/ÀO#¾nÙsÙK_8rSÏsÚ6طЕ•O&C°{¾RÆ —èŠy3˜Ä"QÖ¿çÈ‹Qý-?ûóŸ?ä$ Dõ¾‰{|þŒ^ˆëh{+s@@–VÐœ²éï’¾$QêÑPï„A0œfV PAb˜ph¾ï0© 'èvZ
+¬-"Ê_åã7BŽEÒ¿ûÍ=µdyw†{Í” ^™˜œ¹³Œ. °õõÂy\‡®¤i±SûBKŒÈáÐ爈‚>`3†} ˆ˜wh&½6ÐaѲr‹½¿±HæoU›ŽpÒ*¥È½UŠ%ìÕ°PDc Gle'ºx&;7“÷!AA‡X?iœ½œúkÇêòô@IM¿BZÝEÆ¥°¾¨Æl"Y ·t¯ø—ú:ƒ;/B5nºó¾vÚÓŽ†HLï=¢òÈü7qήdö·åèxŒHAcqFŸ'ÀêÝËÁóm8Ô½)¹NÄB±8ÝJ Û33Ó¨cA4…$,ÚÞº.>"ï„Üʪ—ÝKÒ%ÆZ„<lpn å³, ŽÃLù ´Â*],@ñoAû¸î¨A€c ؤh\<–[2½õ°ÉlÃìâ¾Î ô"¬Ÿï¨ï‡ì)!¿&H9ØÚy銇¬´ÎKÇ£î˜Ö˜|Îv£wýØôùÎ>¾}5æ XÖÈF§p†¾á¾±X°êßGV +€Ù.ôg þŽ‘Ó…]+)‚•fÂÐ;ÕBüßvx9¥œ%¾köã/Æ Z‚Ä·ÁÂÉ(â2nÍŽA¤¬hL;†¹; a%Õ§°´,PËH2–æáªF7ˆEÉ_Äà
+0’üÏ
+!l!ÙãÄD’¬®8¤:’ÆZr=”C“7'FW ,"I»Qh-S¯Ã·)|µŸA¾&#ÔôÝN‰I¬$;-Šä®øÒ<viºÌPŒ‹l™"ó‚ªÙ
+G ÛÂ\‡ŽÒâ’õ8ê9èÏÉ\K}’ H{.2E±ÂŠ¨-Ú4øêêl}¾VçƱ‰r[A±ûá÷D™ ‹¥[úÀÃHtõ📚Á˜²`Òv\oC51nT-¿•Æv´cÚ"¸›¦šÕž”>]&‘Û‘tVÔïc»âd9ÞJ¨³ôéРV´-Ȥ–_ŽÝì£Ìèäf¨ôñ[  8ScTȾ9/!ÌÅ/ñî=—'uÊÀ‡6ÝyU*ÑA–w^Lkˆ[˜7^ªŸ\ÍÀx`h˜
+6^v£ þ”’dÕviÞx±:yAÈŽ?M¼õPá7 e–«Y'Áå¥hÞƒµ3É™ÄNaðꊃäãø½í1%·ªÍY—_ ?[ôýŸƒq{‹Ø`¦$UÔƒ¼ù»÷táw¶® Í/ö?vt&œÓ&'ºüry·2d4ë ®–ƒ¼JÝŽ{òøÅÁ\ùÅØjâd´]ê>¿
+H‰Œ—An£;„OÐwÈÆHŠ”Ö½Í-˜UÞý·óñ凶݈S–(²X,Êìþõß_½ûxh_Òš5[òõŸòh1¬ûËûüº ÖÜWW›}lHïÒbšëò±!CL¦†/½AÔMÞ%ZĈ韎‰Ö»ö0·^Á¬hj«‰ÄÌ5¢5þ?ñ:ºùò9¾~ÿº¹¸Ï9]_?õÞW³z–‡F7U¡õòcéã„Ì¡äjøŠ¾Ê¿Þ–t™ïˆzx ·X&!v{Š=æìá|¦Z'1@ â½ aƒ
+P‚Q)6in\¯²o2¾æ&^爆H×Í|Ÿ3tiŸmTÀý±b8ÇrU³2mF,áWŒ¯·‰ƒ€ ýë;Aú
+ñõÏÄÞ&tWe)5umX‹PÓÑF“†àþ5F§¼³è0—'é.¬<F¶VtÞV%éPºûþ<9ÃÚìÒ´÷Ù/znDóÅ—è¹ÝÇí1W'<³¯Òƒþ ¤¢Åêï¤g[»:GïƒÏ¬ N p¨õº!ªƒ"9y(H\²·ÚXç¦>'i #‹Ë&™(ÀÜçКϦ=6D[zØ¥í¾
+ åì9 ’œH¥"ON\JÜqRW†ådǪ©´—ÔÒG¦ ô|jõ‹ðÄT¥<x‹~xÖ
+ÏuZœŽÁ¢HKæ× k9Iœ ý\…ÞäCiñš@$ÎDŽ³ø
+úù›˜*tc{£'7n…ñŸ KúµÉ—6
+&h±ÑYÙ/Ò…X1„×F¤[Ðœx{fàâr“"؉õ<7Ñ!´:Ý/å*ƒ! IY¢,gØHSi»eF‚`³À]ƒH\–'ôÃÊv⢤[n¬Û›b¤1yq:eMqtìiFbîc,7
+ž}¼4Ê+=÷ƶõNÒÑÞŒÌUñrÜ+5¡bç"½\še¿•ß&äÏ)„ïs4»ƒ¯Q¼2ÿ$»`Õ?@pi˜G²ÊFõ¼ê¤¬(=³Y£BÆ¡ÔÑ~6£–æ›Q<­®‚±ì ø ½<MRβnz™9@¨‰‚RÊ À(÷]paDI×Úˆ´`.âÁ^³!+ñÆ ä°/ .¿[ï÷ç@t8ÎÌÐÍ­ †ågŒ+¹œ|"±En½ÉpÃR¯}•Á6ƒ ›+9䊛Ùæ–îs¨ö`î0^+ņZYgç› Á
+7 @n'—EÍ%'9ávúù
+‹¨ÌØw1ö0|DA’¨$’uºácK—XŠ=rƒJ$Ç6µ,PT®î²JŒQ:KÃB3nˆ*e9­{é~\Ž+×?WMºÂWÏøÊÂã¨ä¹
+b‚—çîA5ÓNE´¸G šŸ¥*%éÜó
+‰¼‰Œ3†ö!ì`žÅ­Y—›£‡VÁR’ZýÁ9J-»«† [GYÁ„ $K CšF -X™¯»¡*)肸E (‰|'¤ÒwÄ¡Ãü?ãeŽG’DÑà”[€Å¾ˆcP©Î h£âÜÞð¬dz4Æ~Åæî‘z‹k†»ŠRÌCö×I¨^QƒÖf5µT Om*p;jI¹_-¹2px¯aV‰Ž¯Uµ" )oJÙ6‚È7'šÄv‚À&°9,Ü8ÌÇÞI¶½b8²ú4±qÒÄ£YÇ M¹Rœa±Á….ȃìj)•ˆš1à=_§û`ï‰CÖ­rX†ñûû‰áEê8ë¾·,}½ÈËØÀÁwYÛD+TÄnpGV«õPË/Û 3'ée§tZ‡…YæuȾ‹-!C£{8„v˜O»Çs­´qõ'ÜôO©ª½ ZÉó0„Ñóa0aQ:®çä‹QµÞ‰0|Ž¤”¸Ã†”N9NÛÏ>@^@ÐH£Ï }X£÷=âÑåÈ7ØÀ zl÷î‡KÔdã-v#:˜{×é³Ê …WE¢æ±€ØfiÙe¼[Íðý©hq D—c ÖAÚÐæ¢à½Ö¥ÁCÇ«…"3GCYuCh¯&Rlb[eÍ
+Ü9F>­Gi^ßGV+vI¶D× _+!H¿&yÔ=îèK(úÜ 5”Ðr¹@¼ }ë»ï¹—hLrtåÂF1V[V1Õ¡¢N…êr‘|ZFâjFr‚xÕŽÂÃTµ}ß¹
+e[¡2™§C¥WÆ*+RÁ X‚jˆ!§/3¿DD§5èw¥<b;Aô‰ÁaNÓi4Äd”x: šNydíþáRrxëšG÷£²¦[òç;/¥º¶ºƒ°+Ê‘¢›öÃ?M7Ò@9ÜJa¡Ê›²ÝµÕãuÒb\ؘåøoœøÜj’‡Z}ØV÷’?—yôÍý0Nÿ=/åô1Šu£ìqI’7 …Ü‹$¥šòñ¥R×ì=ù]"Út‡½[Añ–07´ÐOäÑÆc»;èó;g2ÚÀ¶)Êò¾­xfâ· q+8ó A*’YŠÐ³7”»#
+h)˜-Æ£=$¡à…p°‡
+Œ"B$<xUÅ&V £=$›ÒD…lH><½NÀë ˆü<½ñò´‡ènÓÜí¡s«§“r^çîÈœ7¾û:§VO{èÔü¹Î£sž§yt w«G'ßý¡37ø§±úxM_„UöÅNþr±ºØ¹ü‰î ×Þ·s‰ãOgÚÄ‘!nLH$€ææê÷!PyH2†âj9L¼¤b,îú§·Ýôù3éèýä@Qj¡'GäOw+sŽìÕ—¹å#SÑâmn‡, Q mÎÙ¸³’ò•ä€#R¡‰D¹÷ž\Á«ÙÞ>pFéYM ¾ŸRpÉX‹¥]ûÄrs˜ý¼M©
+…—å³7ä”3siz®‡Nµ}‚ØŽ±j</¶žðáÔL›l`T̵÷é '3J—ÀNØ)ãêÌ 2bž£¹*F–l©ÊÿÚ[áŠ:…ví$þÜSÑ/¶ù –¢ÿœx=óu.0,ó|­òòË£1Hm¹¨Ã2r–µY[ØaÒ‘Õ7Öƒ÷ÚÈ×F_üÛÇ›òê0ˆ×àµê±¢GœÍXøñ¯ÿ¼ýõß7x„z‹¸)8?{cÆcFŒì(#iÐ\ŒÍ Á›9Ó Âò¤fÀº ¶Ëð)w(qCDevÎìñ{†»CþbZ °0x=ÒhÅŸ
+ƒì¹ ‰-ZÔ·lÑT”
+ ËÓ.kÊ(â® ƒ2R”v‡47¤¡ŽÖNÃÝ`(Ÿš][U0h?—–òÆ]DÓö:\&f·PMJy´J„1ŽèE}ûk«;HîoIÉÝŽLþäsÍ%†JEiBÛiLf]Øk >kPù媇Kz©Ô¯(Û±Ri"0qª`«iÄÝuO‚¨óÐ}|_ôí“ZK> g„‚~CIœ?]îxdú^ö`Q$ˆž+ÏÐ †˜6Î(/µº6š8¾ò²4] Œ-¹ W6ähÐëu  c÷ 8Þº2¥ÓMÊ¿³y¼¶ˆöú<€¾ø¢=½jM4<F3` ïÌ &›±g·a ŠzÏì Ú('ýÕç뉱𕛌aë0ËØ1xƒšïR‘‚BR03r<8„4å“[ÍÄúF"p* öi¬a¸ð¼H]D•{E`vª™që-›ÕK´,ÊIŸÌk£¤q'I^‡QZåU`úd‹¬Æâ—ô‰=pâ0ªwjõ
+5íß°ŸÃxž¨z«”^=‘ewÐ7¸ÂH4`=ésž§ìÞâ¬p3” "ŸŒ0v²µ‚¸Y‡iõ1¼ÔJÁÁ&œ™aUÌtÍýþ ;Ã{+Í"þ*¡ÙÜýAËtéY?@ÐqÊÙEI×N Rȵ GÊcŒ’ÑáKs8Ð;“€¡ÙÖNdÒ`]†É3¥§HA´ðK3I|$ŸÔË0 ½ ‡¡RÅH릪I|Î"°[7J=Zâùwë¢gf\ʈ‡%T3ò?æ[*Õ+jP’“±½&OiZÂÈ¥'HG_Í/]Á pí5ÄMj™ö2EÅH]Ž¸Ë-G¯E9Œ„K®‹›9/†¨‹ÜÇÿ/sä8Ž(ˆž
+“‚ ü1?E&«LfÍab”œ`f&nÒ ½`Œ³”;{£íÂÌ6Ï·ËÍd
+k×¹H;Y°Ü·›ŒÞìWÔÆ>™f‰»Ã:…[°8|º×>™ˆéh>£;!bJ¦ÀKVf Ï ³:÷QÔ
+^Y<ÿ[_<a&0dÅ¡PMžW£ì‹w4Oþ‘¨²Sp«MóA>%DýãšMϸ 4µhζ¾Ò¼$Œ®ŠYoX>RµB Ø4åÏÜèPiwÑ_%LÅó1 ÷eBY7ÒEÂ&è©šñ%2'>«‘¬J ö9Úà+4“ä…¨D-¬BÊé†ä/ sÄ”1¼•{düt%y p²Œ sÕ$y PA¯zóý†ä¢)ZPäå6¯>³¼z³t ¤h¯{:Š¬?f]ïƒâqT'‰æ»s¦±‡yŒÍòi¾ªi!6µ\X^3ˆKȵh6ËGQ(EÝR´YHa H=Éû;–?ƒÌ®³}|ÚwªZ_™,o€Î,±%dÌí2óujVKËÍYzûc’St9ºä§Ýœãªó¼À¥=gš÷ÃŒà)u¹£ù3È,žžƒ
+!È;u™4ÿ;þ4ÿþç/kC 8MÎ\W–§4Ö0°'¢z$û9‚»¦„fø”®¾ \@vóÁN2­Ml5TÍ*‘±‰O üš˜"µ¶xh$¾¤Š¤È­“–¡`2Ù\6Ÿ:!t,K
+s1ãKŒ¬ÊÏB·0ÉFfˆÎµuáˆÓQÜáD Ë­öMv]“r`>¢šo‚R&%ú1çꘉq ~ršà´nã±pµ±ÖYò';B­ÊÚø„Bøöx7‰©ðáì6õÂFÔ¬e¦<Ìs|m Wûµ¡¹ÌŽ:]oVØ1O\.3 «™Ê`‘ºvwÎs¿ÛœçÆ|ÕyüŒê“~*±ø¹Q?^Ù­–›«UˆÄÁdˆ¿÷ea¸7ëÍÿÏÕËÇ HöX(82ì(ƒVJ‹ÏíiBØ$4ˆëõ®éHuº=ºá´²ðIÞᑈ¹õÕ ("d¥=Ón}¿Ú–1bllÇ 6gÚŸ1Íè´‡,†ÂådñArC”e0c:ÞEÈìaR¸CNQ@49oo󤕒"ʼnAgU˜©Dïs­S)¤¸MvÓüðWrè¢~¿dÐ
+Ù¥ÕÛDù3`3rfhbªZ6û,ª‹‰n•¸o¢ä„MÃmÏe΂wôõ"4Þ7p·µÃ ºÌ9^:ö]˜ƒ€é'Û²,"¤5‡EÈxhò”ÛmÈyç¨lÇöË#–ý¡_.æPGøñ‘T'p¡†B|MP§øÝôÈogÉž1;fpZtIZŪU†dòæ;à#¹©ÎgAθ_—¤=óÎÃW© gïˆäÙx¯ãCå€'”oؾ‰`ã0‘²+
+ Õæ_…² ¡*ª´sÊU9jî|%Í}9c>†ÑrÚÞRNŽuš]¼ÊüvÉ|^]Fæ/ ÅJ0B =d´s?A­²ˆeÕWe`w²ž¿ê[ýCo= F'/cž=†'<Ù§¤¼á¼
+q¬sØ,Rp+ð!sìMsŽ-á…_¶etÒ
+ãíåó2€½DÁ¨p\kGÿ+ çõ;_ìߥ™–ÌÓ‰þd˜ÃÛç$†¸p[i]ÝM(2@‡·†˜͈u+yA’žƒ‘×ö„°‘è„kZc\D,P4lÀ¤ó%øp…X¶ƒÍ¬hH·˜ÂÍòIñv&¸Bàv
+!2Aü>- DLRRžõ!fŽO£[y)f)µd¡¥óÙpDÌË3"a»>ž-ò%}qÖ˜¿â¿DÅFL¡ûµ`~ «ßþzs:I Ÿß™à°èëF eîýŸ7
+‚ÇòÙÄÌ6ƒçŽŽ]„·,%Îc»€ÈÓD3Rh
+PShBÙr*gfž«þ5(eÏô°Î,8„d„A [¥ásˆ(O^b+N@â,A"Æl2 ÂfÁHá÷bLH€0M­ˆ;]Q¬f4‰ÈBb@ò4=yÆVX}°žä ½šb?øåÀZø+Â:¤kZz–¨õ7©
+I”å·ã¼ öÓ*k¿€>߀úä`ÌüžÉ6¢aFÚ¦9¯>Yß‚±¶ó V ÀrR¹vÕ ný´VÊÄnÃâ/Á‰[tø}Öiœkc';û¹D Â#d2¹$©ØÁÛáœÔC9Tá9b+ÄäéÔ„-•½“ü€`ûk+g»y¬õ½]„·%µóœ};DWN¶¥±ÔØ
+mF4d"cSøÓÕýÉ(¤¾Ï
+Ùuf¾Ÿ½?mª\Ç”^³.WI1°ÌÇthÖXâ$ßWÐ BŸ–C†q‚å_‚÷Áå¬ Áu
+Œ‘íãk4…xWêR*CÀz?•‡¶„x…C®½ÌDà›ñ]>R™;êÕY‡@YðOnÑ×Ü.{Ž5Vò)©›$yú’^“ D*¢{´Óäq,¨>ó]'+ý£(ÎGÚÅÙÍ„Ó¾ê4bDX5Vi¬G‚¹c+Ê#C?y«}@r\|>§ªôDú‘$kš±år… ¸Ž@2 ò1¾ˆùI24¢‚™Y(F×:ÒUöôùD?ʦõk\x@öÊoeqg J‰äºZè—šàž%iÒ
+g2]‡ç%í…\,Q€ÀÌ+Æ:è‰TÞ*ÃÂ}ÈlQ6«!‘üWăt!¢ÄÌÀµ¢wN.êè7®FsI±“
+ ¯Ã!Œ8åË.ÕJÌ÷o™t†YÞXþ pÊ”“«é#ñò!Ç¥±j¹¾KÙʨ°TîÃÉEU?Á $†“*F®Ã§Þ¬ƒßSù@>8¾îïÁÀ$*1>îZÝ„P0ÂC5J‹È’ø…”)@,I¿@ò–¯CdTB¦»úÇÐG(f([mwxq!§1¥i‰RßóÞ—ÎXpż>T5‡É£{uÞ›TÌžÛ˜>D;œ{Åc:©†5U`œ4‘•tc~7bU’?,Vy)¦¾Â±‘±|€i`’.Çß
+}†kŽìÊ¥ƒ±ü{qæ$wU“ ýã d¥øFC1@WŠ
+oPž7Æ‘Ñ$E3“Š U©âä60UPVZ_?¯F}IìàÁ
+ˆª Ÿ »Ú;O ?æz T£Ïrô
+Ïä´ÑZd;(ÃYƒ°¨r–YY9 Ê7'¤]Am™‡ÈT—ÌÈI¦<ÙÍ÷{Žh0pÙóùƒ\p*2¬³ EŠo!9ì€ÝOüÊ&§.ê
+ÝŠ K׿h»@¨6©Ÿc…â
+“‚üY† 4$ÈDîÀ±Ëf Á‚~³ õñ˜<n™;lãÝ:ƒØEtD¯ÚbÒ'Pan<ý\ß-ˆUjµÎŠê)jA±w~; …¢@îäluÜз¬P¦’µ­ÇÝAmª’4íГ­ˆÙ &ÄE÷*j«hSñc“Âè¢p:\ϲ—ƒ‘ ‡à›óù¨ ïPǪVœs#ÛíqÏUö k’¥Iݽo鵞uÈ[ÈÐ}ù#
+áË ýY¾³"TLZØ„nú¡(%•8 #S¬ÅðGíÙ‰rXVÙ~&%Ïd‚]ÅÝ«‹ÃYºæ·i@ÌjHÃœ;|]màªP¦òUåÖ×÷ÂóKÕDE°F
+Qø4ÒÄAÏ:ü3ŒL´ŽƒUé34,Îë‰k§¹Uß*Ië&»%×õöÁ´´B^ÚË™³e;šU]Æ`“ª‚û¨×0“æa¨'½Hf€phè¤@©ZKž[YÉ$VÈÚ¹¨)
+x)YG»I’3Tr¶ŸêÁüP¢ÂhÎg§oG┎8A2b N¨VziP.N‰:¦4ɬ^›X¥:*6^ùnúªŽ“ö´ßš,Í‘W@¾™Ú}O^…L
+çЩ±¢’Ÿac=ÇpëüË©|â(’¨Ì^vl…_eK!áçH
+± B%?‡ì'ëµÇ¡[I‚}'z™|µð‡näZ®+›9vÊR®Déˆ`JI”â]¾R‹n£·!;ÊÅœ´}…@BåaÒwÚ½>[½‚†ÌY_”{l…bó9È­S=át´µšœô¶w!w†h+ Alò9Šé÷^†.Œòs­þÉ+ª7˜B
+¨n}=_#¹S„ÒuˆF”ŒLúyN…p)7íC¾Îè++휶³ÆIVõLVçrضôœ7Ò . _ H–óëÿ/¢Ü?ªšò×Þahø%à8‚S5j,tÓnZ€ ©ìSD¾L( JQßôYÈÍ„ÞA±‰Ø‹íÞV. äŒ3àiu…d@ü!Ùí~,q‚€ÆžñÂ÷.ÅÛ33ö¯Âós0ö"*î 2"ɸL×J ïY}'nçÄæòR•(ãdqÇÈ
+X^¢|Å•a\øÖ6r¢y)ñ­à Lp<­ƒOk³³Y™O§‘Wʲ¸¯‹_n…ó*X±ì5…oȺ‰žO…Ì7Ô©tJ:aÿ–d³ŽqƒœÄH ö–+y½Ô›»à9óÎ&Ãæ3ƒ†åË>31f‡£«OY•VaÌÝù²:lÜ4¢)Š–0môpù­~º!P¬ñ„©àñ»®u|øu"ßI¦å÷ 7ÅàuáÛÀüº*Ç2ŠL
+áÜh6uþëã2TÇ VI i~´UiAµÜaóáì(a™<@}+eª%?Uo%¿ÿöm–acZF¯ç˜æ¢S¹þ×_§(¡¤0˜ñ€–Äwƒ²´]b `HRÜŠl1ÔPòç`Ò†³½RL’ÆYý\=açùÇÂx‘ ·L#ÙY 1©ÈÞÊáÛ؉I#¼”S‚/–2aڥķª:=m.µ<­“嘾ñ*ù¸£ \&-òö-Òî#[•õ­@ÀPs7‹
+µ¾¶b Ò>õœ‚Ø åû:%Á9zˆœÒ‡\L!/
+ˆË<t~-|±[l…SÏR…±"…L¸Abž—¯£þ2ä¼³¯Ó„ZÌ“E 'æ 6ÝŸ"^¤MÒèÈ`0‡fKÍ/¯!Ö èýšTBÆ›ŽweUÃ`&*=àîU~ÒoN'2úÓ[ÌΛ§ª]ºs*ˆU”w¼Y“hÐsŠÆô9—aÍÑx)Ú*¢½Ôc' $#S̼;ƒBÇ !£u$ÿ`Kå°`˜ùYËK¤{Î
+Wô|™xÉ-aû˜Rç.=¦BGZNo<bˆÅK8©ÈßÆ  Ãg¤0tê$R—"ÍaA°_çA…«︲÷ÆbR9Oöcž1›`¢–K÷üæ†ËZ¶·ØÀoâæ€åÆÈ2s„Iø_¦ÝiÝÄ«–ÚÿB j&“ÝÜ¢}Yê•„Ú³Îbüië%Ì7oOÎ+Ùu1  &»Í‚‹íÅ»ÿC…Œ2C¼Ý¦6ébß΢™ u0¼ª(³y)ñŒmeèK­O뼉½L*FŽY»}ŸžAÇÕâ2–Óœ#dz˜Òã)â¥qær‘»7øßp]0»—H³Á$Ô¿n>èÖ¾3KÊS}ý¡G5¾.aNÜ.äq)³¥mܶ¯ú,BhE”¸ùU¶QV ð«â*ßQd †)¢àS¤ ¡°‡¦a%º¥fç ÛæžýÙÎU“Šà­ùYgy˜¬ªîÞA bÖ²Æÿ”èð¼!Âê“NHƒ1 Œjl%k_Ä//ø&jô¢K•™ØÆ
+âX\öi:ˆßW“ºG˜¥ØýãáŠÚEä)G¢xã ä6Î:„;ÄZä|Áµˆ%ê)±†eáöµµK‰oU±û-O¥–§uÔ86¿.•›$›[æ©  Ø‚É)»·TŒ!š SÀÂ'بxûö¨C4`vß B[°¬â„Á ¦ŒÇ6êµä ~¾ÓGÜò 1þòu9Œ}‹àhú=¯ëÆ7´™wÚ´«÷Ö Â Ö‘9GàóY×ÊGl¡¶†‰S¤Æß)Ékªo%¾8ÃeÂ2ÙžÖæŒLá·“Ä66Êw¾Ê×Ä#GÅ?S®ãê²ÅÎ¥\
+8gu¦Îéó’MyÐ0Z^BH.L]Ë^2:ˆüØxjŸF“ä±™¢ŸgX‰q×[”¯Ûx›Ò颽xàÙ®4aß=Q§ýdÜ8lÌÕùfýºÓËNS>„J~@OÁ3’|™d²Àó‰$/E@…–‚Ý|†œçb!ĦyLRh⪓i(azqÉÕšcÖ`øº­›ž§nã×[à”Ç5ù³ä¼Ä'¤§Lƒ° *.š÷©Þ
+ÑÃ/]ã×- tƒá&h_Z=)äæÁD49m¨öq_ e†’ïcû5^{ÕÖÝÜNŒ!¨
+î­ˆU’…LU¶s2¯Ñ´¼HòTÂÙAÒ~]õ^ÄbÐ" Šýª÷¯Qø"55pÂAÇW±¦ðKkZÕ4½œ…ádÅŠ¯;¬Þ˜0¬g T^šòsÝ
+7²¶àøUx ¶y“ˆ`
+&•àVÎX{àäh{2s«‚H4Ív Ò
+:qÉ Aà 4Bq†Ô»ÒÞܤC Öªñ‡)Ø®'Viá¯BÙ%½aœ¡ïæÌ€§Á„(w“#¯ÀHæb¼]«”ÙŠï]įhDð1Ô0¬N¦hÁ›ùqãYcZ _‹5c™ÉW6òˆõ`æ–X¥Õ&þbT%úê0¹JèQÊ=«Q| Ñr ¨•ÄBêAio—0Nvv+åPbW18
+—üÏs@ ¾!V£‹ ÄDaÕ¦éCemɵ¹ÙÃSʱ/VŽr©2[ºÉÛÀo½ó ÁõÕ:ö¥yÉÌ{ÉÉJŠ°ÿðíÂÛØ›cb*¡zh`««&A~+±öáøö|öysÄئ~ <° j?Ò@÷‚UÅ SíVѤˆ‹Õ(¼)³óë´ÆR+yéY6ä%Ù#$îä%­*iÀÎ7±á
+(¡¯ÇYMÍoìoW±<1WY £8øi7¹J;gFƒÙd¹3þŸiÁúPòÆ‚‚hj2;Lf=}?U,ÞXøS òT—Y­.|K©Y‘ÉJ$= ¸·ôà)b
+ØFÆ´ö¤E¶¬Â\Š¥XˆÙüÖ­¢rÆÜ%kžxKaqdè,1!«D[ÉQ€í±Œ[ôU‚Éc#b5;¸Ó™øR0gÐo×OïjWu­Àw·2TÁçT­û`>ù'ñÓ'ÌüzBix@é!¯ `ƒ†ˆÛ™ È­òé%^ô¢æWad[3ÞP@B)Ƙ]N™)(søB7,Xûwã2ü—ðSUÛèÒ%5Û¾¦éëGF6L ;wõúÊt¥BjbRðìWEÅl¡à´ŠÐ:L-ô:ý½Jöxz
+ ö" kƒªœ¥Øšx3Ò¿®ªr¨››ÆžÏlp ‘¦}zÇòðÍ,›Ér‹K(ù°"ŸEà”§YŠšÃÎá}E/p~’úa×q!Ú«sÑ(¢•`Ñ
+þF~Фo„›F F€GŽæ›˜e<*6zZ‰ž HÏbl¼‡e ×ZÐ:ˆúV„pÄ_ÙzÑ_6ä¢-’ ¥H2ž?Ø8ñHÀá<°a&pø+ü]B‘1YÏ-Y‰åEÝ í¼¡KH«»å[ЮøTFÇU§,fW¨&9´_Ÿ|?gH_XR°”¯øÈR£lØhcË*Iú¾C3¶Äž2YGKZUjBãYø¾ÏÙ:‹ù3Èr°=[ Ç æd×P2÷÷ø(Â"‹ÜÌ;Q„³GRöÐr'ˬÊ7)²ùrEmî+Äùs£ÅŒ%BÔºiÊ´’#Ôg;‡ìÃЭ´E j×B£}x™eiø±„…”±
+Ãn»Ù
+Àq 0÷f¦üby2 „B<KD!Ò™î
+(ÊÂ#ÝÎÆÊ09«P©©iŸ3dÖ`+ݽ;üÛk¬I€ä²AKÞ¢ör&~ÃKÜ„qcþ3­’F\œpLu#CO”°ªÝK¢ÌRIÉ%–Ù Ážñ› Á
+)²ˆæcx%}Xg×} ¦°_%rH¡«D‰¦+…Ç ša4eéÜ\|žÃ;2 Í)tϲÄ4 éí»„ÿ™á‚?Gg+ IoS«š5b² Å‹JÁÀžà‡€åÕ1.ç˜@ZÓeŒwÉ
+{Kª»„mÊ‚v±s†Bßb9V4…IXÙñA×M÷"¶“Õftaø9ün'hÆ6I|ð‡Ýû':fuØKãä!'ž§¸Ð¯‚ý²Rà•¯ôîZñFNlBä‘£«ÚOÂÝ 20[´æ‘“YdÝ‚³Çs*w¡YD0—áwá£b6¡@ú!jòˆMò»¹Ô§Gu-
+ä*K@Ù}ѯºQMP™8g€oÄ…€òÅEB„à °-ŽV´Ë•æΣØ7¶yLúÓ¯3cãºyVÀùÕöPòFêâÿpñ?˜"1aZmË©òñõâ:; RWÌcÀœ…³Ðýäüß™(!ÚnhS™ÐOÙ*RHŠ
+éÏÿ(Y=Ö¯ÇááDnx€0ïò§åø~J$…"³½®ºU\&Á Mëv ¨ˆÍ«} Ó¤.š{Ã(ÉÒb˜Åß]”!™ê@?Ô 2Sú9GšǬ™Faì%ð@æ1ØóÂÄ”ñgÒ=Xoª/‰r§A‚SÀL² &'#¶€æ¶?$­‹†Ö3©K¨ù}TL‹îÚiNþJÙPœŠ˜ á}knF ÊS
+ªü@×ä¸5õÓoD ¿ïÛC !iT”4ð<HÈ)\‚â®ÏKõÎ3ÑA´ñ>ªPå•ÆV£I‚x«Æ-–Ç¥`;>„ÙÇ“)®’Úx
+\33Sp›ó g†¿8ÈnP£aë…&=sñðè6ª3(Ì ÂäÙœ
+[0PQ”æìwû
+vGµqS¢˜í ´5÷%®››É¹ÛK†ÒÎ?I6;Q6 ¡¹îcÆŒÕVX æÚIá4£Ï/8&·ñë%¡Œb׋&ÑNC³¤æ[
++Æ(xNsd™¤ðk2³E¢ÜhÚw’LÓšíz)Ï°óAdo+aØÔ}уZëAc…¿AÓ×wôÜÜTÉ^²>,…þˆõA‚÷à(YáÐÏ_;Ñ®7«„@ÖáßÝYk³Ü["Üo­ƒô£–lD²RBÌêÀÝÓû-ùŒ§RçIxCÇKÌ"éra\+ö縉˜W³ôyÈßy™Qö
+Ê&1Ù:ðq%™ ÎT¬š«ÜŽ&âw3Ê!©dÄ(%Ïh…Þ¡¬Îƹ‹.Vp“\,åAò7¦ìOuÈóûIãiíù˜碣cŒ<ƒÄž(ÓÏ™œÒ±/$%ƒâ̺ ×EY "ÔžMB3â0KC#¾Ì[Ï'Ú•'âªG3¤ã˜,ɘ¸: O<:o4Ê’LêÐ猩.Iç3¸MŸ ÆȉŠbÊ—â)šÌŒ8–(ªvÙM¯Ù¶,zb*iÝg<”æPüX
+¢¡ ŠE-Ü—ÆÀp͵=W‰zØ­‰¨8‘3D“?¢NÝ}LI4Zb”ЯßSLdT]O‰-¶ñ"d¨!÷ï`;>OÄ>ØjdÐêKR°Ø.€-v-ŠŒ¢á+ÅóDÐýعB[Š~HTÆ:ÆúNƒ«*³h.áø!°‚ œÕ“~p¹öÁàùs*U±
+50íL
+â"Vû•""‚·[&Ú¸NÒgÉ&Q#ðäüÒqè;Yþ
+|ɨMDsgB«ã¦öRÂ'ZvvˆE³GÐsZýE^…¼Éå/[
+j§y½”Ÿ¾`g&$ìÉQ†v ‰há­£…B·Dn´ƒ&pŠÀd7•Ï=Öº\Š‘~nH2§X5—Í §¸!ÑÇeä©mHeçY€J ñ2òÖûêBg¦FËé}%á‡Xg(Œý;¯N … å+áX[ÉÅÑ?1ÿàæ_ÔŒ
+
+S›¶óÎ> RP÷ø³ºK$ÝRߢ„QÈ!-õØ {G«Dª>LãU d¸ûJ#†ù‘&ÙpÿÅaŠ,ô½rÊ"¨Yß­¾-b&^M8aÃ;rœÂ7З"û›ZŽkS€×eU˲0X"껓¬è%S2~t›ãÍë„L>!‰y#ùgnþÀ§3Ö‡¥öK‰7šH N¾þã:L†xóXì!®èÏéÞʹ‰€ÔÊÚÅwZ˜Ë"ãµêXqqD™xÁ ç³bF«8Oȧ:É„±v^§t ùþu paHÙ&[E}’D§&Æ…¾v°_<gˆ•†Ñ³±5éÃÃCàªKHI¡jÈøÂ+2ÅV{,ð²+f·K¾å”ª»óAè<¡
+Á´Q{¸ÊŠy2 ZüCí‡Qx¶0{h¾NâUö{lÁCÂ1WÍïŠÒ`¸ç” XjÉÅX|ÑcoÕõb6§QÆ aÏ@èv!Ûa÷‡JÂa€>ÂÆN<;岉aÝé;ÒŽÍ9vbLV#ï͘uU2=ÏŠ§þKOéÃp0q—”}]KÀ!…±DÚónõ½˜Bâœ(·ØŠ¸Xvé
+üÂsVߊÿëL[^…€Ñð0ÍÛ¿$^n5OÓ^ø*8x‚¿#‰=$½ETcJù ŽÓL^ e=¥+A+õ½ÞPç—jÿ
+‹ä’ÇÎX—BPÒ,I/MŸ`=ÌN!ìc)}º$c@¸fyñ÷AËM1±V=ÞZ!i h¥lÃMEå´ VŸ;‡}òiÛt@\#j€¤_×!¥ˆ4p"%ÞæêVÔBœ‘Ð>Ž)¸iXJÓOØU gS
+Å„ =¾m!{MÉó.aÞÄÌ´ý†ô{ÉÂÿõÏ­¨%C”†2Þˆ]]?¦ãVf ÔQË…Ï
+l Ê6|æ/n^
+8°r¬ƒê¬ 7þuY§Ñ£<0•UwJ
+Fù–@´ò”+º¼#ËÐŒKI`ô;Ö¿E!J”:sÇs¼j>Œ.hŸÅ=F¥¦$q¼«üYâ­€ý^'t]z[âߌojQòðJYž,0ÉzIó%O™H%¬ÒŒx"ì=R·ƒ@U
+ˆ@«gÃFP”ë©uÞ]è6¬ô–i· ›bàpSq’®þ}ɛü÷—ÔÉÖðÒˆP‹“z¤BO·%cžð}(ÆÓ.#ud³gô‚§üÃ(Èýñ RWüÁ4(ôÿ
+H‰Œ—M’[7 „O;èQ‘ÄÁµ³Ì-R••}ÿm><‚ryôTñÂ5£q‹ F£¡Ö£­a2ö˜ÏXáÒEšõùè-âi-¦/_Óî ßþø÷`lôé€úJ˜={3‹îf&ãñcƒ´‰D̈nÔÖjmŽ©æú¸ cñ'ñ‚ÄœC½ÉXsCúï]#Ú(Ètí2ÆXÚÿìP-Ä´…òåY˜yŸm6Ïsì¹|ðã°s%’ÎÕÄƆÄð9d¶ãr…²§+é2ÝüÓ9ºzôÖÍî_eO1Ïñ
+Õ]CæèÝZ?¡FwZÍtc†(©›ÄÒØÇ´|ÒQ‘D´/NqîX6|Ã&¡F®‚®¹v }®n]B3]dA"´õ.Ë$”ÒʤÁ™"‹ÈÎ7eC&¬Q[ËV…
+~÷Æ©+ô„‚3¯­±CQ:ç2FQE+Ô”«)Çû†^8äƽçˆ^­}4—¤é.ÃÈ!}j¦ëïÉ3_íÒÜšþ6ˆü,¸¬«eß?€Ô ÖúZ1® ‘¦N%Ö¨ ‘ãé0jrÓ‚ôaK]†VEÇu™„ÅÎ!˜Ö¥÷E[¬ûƒ礀­+‰»"Qâ =?¬ $È%vE)ñäfô­PW¹H ¯¾AÓFdN®sÈ=´¶Ù®O·É³Ûf³ #¹å*±6Ä> јtÑ Õ† Š5zCÏ«õÞ™:‡ó¾Ù)’Ì!Å”ì@H:lª¾!’ÂIöf˜N’j«/½}/‘¼EOΨ` ~ÇJúãÍQš°Þý9 z½˜ÊKuvOÔÓaI¾šûi
+[–LM*Üäç‚xo’÷QÕr´  ½ °Á ·jEÿC5"5;¡¸-â­TuÈ'º¹˜ SëœIjÊË‹Ä× ÅX³½AÃV‡Ö‡+?(:I^²'x4˜>:%Û®YCaíá>
+²Þ´…ª'‹•ºôW9y _¢dÞ€ªœ4½,Îu`£Ð56oå‹g»#Ò‹ëôÊ03%‚Ûõ~“»£¥ƒ)‚X¢÷U((˸ •y§È›òϱG³I®OÚQ?q†ÁX¾\~¸ªÑ
+ÓkAEBˆz3í=H-mßk*¦8[ 7P¡x C§§¼¨“pEÖV6ËG’n§aÒ)ªÆýfÍ*„5DÂ7
+µ YŽ3·yÎÛ¬ç6 FG¶s¿µ y_´¨™ä<:–è©®Hp/˜¦0M}ŸƒÍ˜9õ°œ>XTn
+³þqg„îò÷néï4U¿ÚéjèÄÍ×xÌYгcIõ[] *-'¶^r©o$ï6»‚ø#|$wCŒzNˆ{|ÕE2ŒŒ¦»øgGÊqcиêÐtGŒ3‚-ßÇp¢s»%VŠ½Lþ« ÒÇD«@ÍOf§“8¦p.7>ï‚ ÖÊܵzTÎ_ŠÏhÔUú†6¡!0Åd:‘HBÁècÒ^Z€vqcø|ò×”iˆc¯sx0ãÉ!ýEù†€àI˜gìý‚¸"µgj(¢'åÓ1)Î|Ê;—ª+on`ü\KÓVÏn’o1dƉ„b÷ÁéGK5ç…XÛZ4¦}ƒ-°Ã BäT!éÓ7$_Íðbšˉ KJyì J˜é8N:ßÄá4…íc$oß³q«àšæƒwð¯.s•»smpëÈ+].ÝN$Á0©)s]‡Ò2…éu½1ÒFG=êr1¾-ëúñ‹Yð,û±¿B}ñžô“ð¯Î!/¨{ß Éž¿rTÞæÏqÖˆ";éãW©ø}NÈïk[Nr̲ÂØV¯J'€Œ¤FmyiÙAHÛ-ý¾ Šè,à›©Ýh÷þJr2Ï ‡ÐÒgµdáy8âPÁª0±h¡WûŽ4¥Æv?Š÷Ѥ]‡·Ÿy=†3¬é­P>4,':`'ÒÁqæ4†™é=ÈÚãN¶¨”åî½¼Ï;õsŠ‚Õ¤rPö¥~_DÔ÷îÄD@—JoÞô¾$Û%·¶ßôo¨Ûêßò¹0G²ßºØøÒäŸ8?6ˆ;çDÒZ¿€ªÓé
+Ò4² /R¼0£¹›ò¦~¯È@F®%9ýû§P¿ŒÅo^õ èû­…žiŽpÊ”‹*Öe—$¬ÕËá ’š›e·[[;³`ƒÙÆ+É-WDMµ­;OT…é 7ŽêG—*Õ9˜H„‡õ¯ë™‘K"ŽpÊ ä¸¥_§ÇÝ9hâœæè@h÷œ&¬Š5:h:vUžP~ÀS˜Ó|i¾æJÈЉÝTäÅpo8‚Râì0m¹‘jM&+ÝÓÆÝL˜i*òd¯áƒ‘ÂbOÉò—OâÁÇÙîSPª431ŽëX¹ ݲÎL@7H5o4/×ÛK.¾zBÑÊìž®zƒØË,Ê™NxCð3Á>"^>ѲòŽj o–ö„5&ã¾k»ÛàÂÑAÊi»n_Å
+ÈAg"æˆõI i0älôûnÎK­’û¤½Úk½=)Žþj &ÚÄØ<Ž2G³¿òÇ`â+é(j£"-3Ûk[7^LAöX)®ÌOcÿ@]õrîPËu š¢ŸLÃ8½Ü¦üµBqL9îW¬ÜÆÀp,¯+ S;•;v&3•[krúr&³"«åÖôéœHÇ“a,Hî\ˆû„ÂÑ 0¿WŽå2×#ÝL|Ø
+hÞiÅ0/éçú¶Uÿ/“In$Šž ï $8ëÖ²n! WY÷ßöû¤™WE8½YúÁÁhö5 ƒ%ùËG}æÅÅa¨q˜ùRMd=ˆ8z¶#w¬>NVpyæð0Ç$ÔmÄ$ÚºâÆçô(‰€>aåø‹ô_•á ôý
+„âyñÐõ,B\
+†Ôg¢³Kïj-
+Ö7P`Ÿ$³Ü/4=å]Y•j pÅ›'¿…\~ù¬6C$SiEP&¥ëÈ
+¶ô!ûû“O8žV©5>A8.——ºZGáG°&ÅõAÜóÊŠ^ÂM3z>W]x%Ói‡¡nꬮ©ú}€×{&ÙÿJÓÒ¤ý
+ÊÀ}©¯ ¢G±è0HÑY
+ÊÀà$à‚*Sž<6 ,¶áºÁ0\;OØÃåïeôž=I­8j ¸¡sCôž°3ÔìïIpˆ²`<‡ï¡r^Dš {Aªä¡¥¾‚àcz—³57…Q°;OµÔ·éKKÝh@ëõIá`Tê®.EĻȗ» )S6P«j¥¨*gæϳ'r c
+…Mò…Âuó1E*åDÒÐ q [Ôjáu4utÔ,ة؇7 “®1yÌlÜl ËÖ3mTÛ–ép;&µ*V©ó—¦†É¦DiC§ ™H«{J3I¦Ô-ØNE²‚T0úN¹Óÿ-2ÕÑ’(+!gú:ëRvšˆ¦£;X­07$6œã,ä¼qÐʸŠÕŒ¾UØo:±ìîhÜá'.šö:¡i?Ó<,äBµqB|ý‚•C_o ˆ)¥å‹$8.§-È„Sªœ£ ¡¤Ê´%Àºá
+…Úr9Á›Y#'¤ž—üÅiH›êîQõíÐÃ4ÉòÞ¬òä˜L66 êYNŒ«°#ó+JOÈ6Ã1+aŠ‹l•Õ”<E/2tå‹ø1[æbÖůŽ451C‰võ‚¯P†Ä_˜¥ ~FÍK·§‚‚‚4–ÈêEædc9ål¶An€‹ÕtA{ä*HÍ|€ž¶î|ŒŸLÜ»äNýÓ#@j¯ß},‡ îòyù¡·ævéæ¨þìÌvÂmñ ‡SV{Œp+bdxÑŸGƒTÐAnÆ]¿@ÄÔÌ$‘wÃG1Þ4à°Ý˜ëæ ·†ÝÛ^<xº5Ï¥!pÄ®PD%`aEƒì*Qèx¾pZ'|‰xê)¡Ûv¹Ó%Yž©ocD—ðê³Þk£
+² us`øRIK'«/<ÌÄP½º}ÖÅå >.7ßøšü@¦ñ<þžŽ6„q!ßrâzÎXák±ÒSJô¤†¯å{A6Ú¶Rï#åcº¿K,L öº}—†±Ñ´_Œõ2ñs¸j\óf¦è­%±uBŒ$D¼} ¢ÎyE—ç«ÙO @ŸSå‚VKˆïuü»ÆøQÄ”°TÓ¬Hr¡h¸­£«Š5a/²çôEkÉ Ä .N‡FÎ…‰è…X®Þ1º9Už¡ØV$®|F”­"êìþ´ ,€)Ì…z^)eè ;4ã£j?lÞj 0Ä,†£#í
+—On[a*ˆi¸ÅáWÿ= .Ž¦Ó
+ç,•’’σF%Q<p¾Sâù> ‡×¬»BHW¶ë«-3ŽÚò1›;;A"éÏtôÐsGo
+ô†Jð}'&˜ ¤šYHËÒRB|È^‡aââ)àPMïYôQ…y€PÊéS®ÙwÞ@oúröI7’1«Ê‘Ìb0·ÇÉ_86d&$Ü?@œßS³v°¬Ë[ã³8ÕžãA/Û}r&;úm­·(¶Ž>‡B†H ˜èÇè.Ø2Ãòº=š|ºow»ßG WO¸0ŠdÞLó9æ…AÎÏrÒ°«·=KfžèjïÏ·ä<Õ<ÃÜ+pÇÜëÿÆ3Ñðãç˜û^š^ERéßã“Ü@ù o
+s”<Q° Rø(S›­Þ‚î³r+äèû“j¯Gùëo eH1sr¯nð:MßDéy¿‹0ÐL…˜kïЂdå!åÚYz½ z9©Æà (6B´FôHƒ+è¨-Êö:LÝè8—ýWo[:ŸŒV:êî˨ Þßb@iaææi/ËK`í‰{÷æQXËé›D _B+HŠ’¤œ›¥H”7»oEŸ¡â­°Qð,ú’Ë^§·,c…k´u*F»*úäX 'aø¨µ%eRe²Zdÿ ïÐÿ/“$;n$ˆž ï ”a
+Ò
+×dØ×NHýÅ}ÆG Ã9ÚÆ0Æ´#›¹ìÏð6Ò]¶!ÑZ?Â8¿@Ò‚Él+Åø<@ì(óNéÞeªé”{ÞcàdÕ1ßì[öGA¯×’¯ I®LÆ^Q?
+ îÿ0!áýc±ÛÚõˆㄠ`ŸCþ?ÁƒŒ¯C´h
+h)‚*+‡¦¨¼.ŽjS¹ Ê‘¹9(Uk>]üHb¸”C
+ü€h0°Ê”ƒ‰oåJÄBŠ¶‹x
+ö(›•€Póĺú¨#J’/6·ÏIwŒ^ŽÇ``ÎA?î}âbëѶ|0)k¼Edfš5Kýü•ÊëØ3„¬¼!°YㇿûŒ×gÉ ;€~8ˆõAˆŠã|– P&“kÛ˜</|‚<Þ}
+é-Þµ}[¨äþïx¦ØŽtYÒ tA(?6Q,k³ÔyCÔ5,g-kæÜêø.<†E/¿eÀ ßĵ3ŽpK€µÃòAú)Ç„2"ÔàÏ“ø[¶—ˆ’¼ J`ô’Ô7ÚþŽ|
+-/­~È1 ’GZ±ä±“ó36H”û¶'±–$Ò!Tå²²”ëßÁ‚’Oi¯;Ž†1À4'Ù—ˆ1tp>JºÆžÐè&/G‹ô Ùÿ2ƒä ™‡Èg<‚G]9e»²¨o¿®R„?6«Ë´)ýmȸ,¬|‚™CX‚ê,ßב˜.ͯÙ{–¾´#xu+Ëð
+,?ÿ^¹D¶¶÷¥Ø‹ÁCóªï:¤ñÀXy³w‰¢VqøƳJ_ª5ŸAN£ùeŠ Óê·Áú9˜ŸXd¥Â)²úÄÎÄúóDñHÿÆELëÒ·ÅK9›Ã@[Èë7™¾ Rã6m–ÄJжBÉZõøº®ê´i¢§ ËƼf¹¾¹!ÊgDHÚOtÈáÙ& @ðR#5e— ö*á,¼õØß¡UYc8ÃBƒ…V.†­GÈmã¨;¨C¿E±c^VèyB%ÿ¡9‹‡¯ã«H‹$þ¢5{u«yqª{œ_¶¦ÆC”
+µôyÈ‹»WY‰¶Ÿ'ˆ÷ŠÁQÎ\"Å=¿ƒß"‘á’—ß‚#× ÉQ&29ÕÓÔ„hËÏ©ÀY¢æ²3þòŒ‡Í* WØß¡+ÊDS´¶!IÁO›×üݹb! g{©ŸvÞé¹1*Î(‹(ÖÕ ÒmŶ?¹Iª©Â`BF“H©œ·zPŽ±B
+Z…¯×?ÎäF¦Âðiç¦_ñŸ²kÚTYØæ °øs¼QåTÍ4’ÖóÞô AÐâ)«þ82–¢¤âGú†”Á݉ÀÙèNð#ÞN©®kvoX_7rrÊ´½BâG‡ÀA³.öoV/
+Û†¨3¾ùXb ýêºnž/­ªó‹SAD+Zuk9²
+J„•cE€,'ýæmõ¥W"Òqõ‰„[=*f¹G´ŽÅ›ü¶…«z  @KvŒ1,ó8ÈO‘¹oÃ/µJ²Æ\t~Á)k‡u„©hÿº$í ÂÚcï`'eU#M
+P‘¹4"Ó¿×Vg;’6/bÏÅá)_æZ%àIÁ`‘Ÿ…J\;K‰êÜøGx+,­í­Ø6«+iç&¤2HÄÄËdªÃÉä4ÛÆÈ8~‘9Yò!xW`²£Ò{䢇ˆÿd5`™4wÿ0ö¨4jC hòÍsqƒ*Œ.0ô8ÄCIì” ?ÇÝNE”>1ý“Þô}ǘ]6‚ŠAbcèyÁÀ!s
+¯ø ‚µSA•YÑÑåýš‰ÜF|ŒË\ë É¬ÏGÃÊà(¹Z%âb 0š?d;Šp:\ÅEEÑ”&¢kîkð SÁ‰Uqü?qØ[Ï_mk2Ú€$"ª½SUã><ï Lj¦×lÙb\ÌG»ùg ¡ìéÇ’v‹Èƒ‰švoõ^Ä4^{Ï·’¡‚ÿ»‡ñÑÌáŽ'ËÇþpL(›„šÚUkúZX,øב™’=.E)zÏeG22\É—¿<Âï­$àÇg¢ÈÇ>­ÃžìÜŽ½UÃû2œb·˜©¢wK2ü»ÉÁ"ÀŒÐÏô
+)¼9*·o…N·šÖ;| 8%PÔ¼ô½y‚öaMÈ™èfö›’^ùÿÙPmn€ÁÛ”ôÊZ¼Ôå¨W³~d? *Ö^í£ßì÷Æ¢Ne†—‚p>;ßEó"‹ð?8ý'GŠ/¸Å #º.¥X†S™´æ‹þáB*¦€y«‡¢uL
+ŽwúŒ¾0ä~f”ß»Hdñž“[ò"N»j¦ G´º4e¾„8yd`­“4+øöXò¢“¼~± 0¶†ÅqIËiᒻȊ1åÜk« QcdHYy©;n[H–# \c‘¯‹£>uõÓÎFμÃ3*ð X"«„0¼uâ±7‚&¢aNWÓ;øBù.6Sä ­’ZÔ¿Žs5—æ“ù,VÉÓä€8²îŸ`JðÌ
+ǯýP²]à«~œÖ‘ö«÷Íw‰OÉ?~#Ø~jŒ F,,AGHr¡ä½6‘e³¹›ƒÓh Ž/AÆp%ÆäÜàêˆkiôç¨ <A‘€@¿83DpÛØ6‡7‚ÏÞ¤_0<öÌÛÞ¡>´|–¹u#@dEŽ¬‡ƒËñ Ò­ðM¬Qe¡#’`Ð è²–X‡¿™´ŽÑZ%°cæU æê%Ÿ¾ö£ ›´õJã÷é4Xq‡yQLy¯ã­\O AW(ÂŽ­„:ùVßñÌ4?~‰f]ëÀACF7ïà†@båõöK”˜÷…±W ÆÝ“<·»³Êiâ;,âY“³d`dxÃst˜µñÅ´'„À­D §à!qô3¶ª"þ‰ÅQBÚˆ‡mܳ®"ipEb“‡rl3¸ÅŽ”[ä‡%Ûê ™pÎ=%[‡l,™6•§u¦f2ËÆ­ŠˆQj°(ìc‚>2%—ÃæKzðs0 Hê‹6ûosk2AŠ/Q2Ñ6âlíHI§òÖÔeXKt‡¡“ËÅïÕ­ÑýAÀ½ÅÅ@‹Ík9j4/^”ÁÆ,?É@6 r¨QÓ™VÞüJc‹®
+Öä-c£‘À/âÐŒD ˜N„Ó~hÿUÞŠ¾ŠðS‚Ç茣ÆP’M(Â;Ë2I—,¸4øV<Ùv<lÞÈÁ|9®W ÿ­É²xHÇÍ4aŸJøÿª¼Sêí¤¶x+üL¹|Ø>2§ÔÁ†dÞ2dánO%—%e…n䌌»æD=Øq~º&¦p;ÒĆ!±8 Ο¬x:÷iÈ&žX¹æÃ
+,¯ìUVÄ›_xQÚ î|‘D›yYîã­äϯ~Ùï¿´aâT´š=#B`
+âg®uš‹©³¹ÇiòdM|]I)Nƒ ±~Û.ÄàÒDÅgÚÞ
+ÑPJœa¥«siœ*¨‰u*-LPl³˜ ˆ5x8(s•°5£ŒoÕz™®Ø
+‡”§ÐÚ}ÛÙø.[Ù×:ñ ¹Æ:Jq•$®DŠœá¶ßJ´•Md
+k°/NÄPLã³±Jj§ÒÏEsô\H•‹±·ñ(?s7cKøé:ãÕ×:/¢ä%Kv•@,=úeÛN%oÜ[½‘Ò
+£%Æ4àUV#ïB‚³
+Ͻ‘’‡á{)ÙD‰6±WÇuÄÈCG\ʽÎëi(!èf #ÑîáV1äÌ5sTüØÃw Þ4[ãØbJ(wÑ]öðT)˜Æk?ÕÛ“Sù— ×8”`Ø-Ëü
+ó®JAI&àn$i®Q¤WS©ÐÏ„ÁwUw2ÈÑfÈ ›ÌÏÒ_€îÇ)B2 /ƒö'DæzÌ.L?Ñ'?ˆ•®ñ(¢ØÎÊ›1•?e¼€>¾S럫%·”D Í’¯æ,c?I%ðå¯ É|Y~.m!ýŠùù€Á*P|UfÅ Äïø¯Tíq'פ§ë0¶Ëï îØ. Œ°Õ™h±oƒNÇI*7Gjbù Э‡ÓþŒiÒe"™zÎ&}<€xUV/1p²´'ÞM¡`~BpûÁ¤3
+£<p¤-M?JjcìaX++»Ð$×!¨ºÞ=“5“æKYŃˆ…£ L»èßéöÌTW»2‹ÂPýâ9' ¬ L͆ÄÆÚâÆèˆïÜu¡®ßá/Œ‰¼{yuyÕN²ØlÃACí(´f%ŒÚ\heVqO¬üþŒØ´â{²Oº¨:Æ`™ ¬,ƒ'l03Hþe?è"\@
+OL–Ì.»œ]ª­{0¤¾ÄB7²"CƒáÊÅ¥±ÊÆÃxh?‰Ù+´%×fïÆÚ0³qŒ0ìMÈ­7Lf—AÍÙLr ãý¶xms¾R„¡»)7 0<)´Óþ๱1WÓ¾ÂD$4¸æ·ƒŒ_xÚÏá®…Ýä,£{¶ ±FÛÔ(HÁ•°—±rØÒW²¬²ýuÔÿ¸
+³Òì´i.¦ô€˜F:Øù_ ›!
+h6.*w|ï_`¾öñÙůŸ:¸ØPßÙˆP4ïöë ºÔÐAý•Oøºw{Þ·@“Ð>f|­ø·!w[u­ãóñZ¯Ž¼ý#dxgÈC°H±Á”
+‘t0WÉÚr)Êà‚íÊ2@2!ÊãAv ¿J¨,É ¥g8¢N²‚ iˆ¨g (ঈyæVª¸ê%¥MaË=>‰Ú\ì‹æî”D.¨C¬-VOyuHø“ý(íz©dÆ=Gõê„–(2¶¿÷6¹hÅ qQ¿)ó !…«„˜´éž9YbÂ,ýXd%в‘
+«¡yﱯÜ.§€ Bƒ|©OÖKe.¤C¦‰y€ì£° :Šþ”öðT9O´SÂë·ÅQ<¹2!
+šŒZ°ìÊŒ³>04ãj')¼@è ¿V TfzÊ7,H¤2SÞfÚw8T²hxAfo¤É«’w“_ L±l;·@¢öˆç®Éú©7ÕRƒÆMi;¥îÅ:UøEÑ,!$"jGòØ; •bN°ux8;)ÐOêÂŷ˪*Î’³ðâq}Á 2Œœ½íÊ3²Í,ÁÒÖhe¡8£uñÂE(ûÊE- ?Ù6 ü&!| Y:ÖORƒõœX 6Ù[E¯=VÏÝû—¸±†‚ú±Õ0a®»{š¿ ÄF¨¨ŠïßQöQ'q¼fZÔ=ža„îMpÑo{ðM=ãµÀrü-Ï¥LÅqÚqI<ëÉõæ¶57ª±èƒÜ`‚ê'](§mˇ{J½+]ˆë¢ð'$ÈÒ[ )îç“
+¿yєͶcųF,aYtÔÕ!‘v}ÊkGÑì!ë¾GL[›0ÍLUm{Çò~ªÉ²Û”¸"Â@7Aš‰²Æ†ð¿($ÍGßDÒòOóè|·C 9£æGµwiçxØ Q »ŸçÚõ±Þ !«6qC¸.óÝ)ôâ8 ÛF)è ƒ3Mºñ°ƒ@Di¯~¶1xo©?5ïƒ2¼@¡0öy#Èd”¯kcëBHáÐAj ²\qÀ¡´t•˜UäVÅž¤€Š# ñ‚ͦ|Ì¢&ûòIáñ˜ìÍ*A`ƒÝá÷)Pb?l5blÈ"!ÛW( zÎFŽêÁ>P(Æ°g»“ÍÆA„$Åõu°ujAD¦‚Áa”ƒqkX…x€ñÈi##Iöá;ò×¢X&¬$Ãgêäæ^Ã0Ê[.ë¤CY¦l“Ïî²Ì¼r$s Q›×ˆ9Žˆ-åì©Y ŒU)Á.‚+ÍhœD.½H‡¢ME¶©É¢›(æÎFoXÔõµ7Ó¶ÊÐH”ó‘tÆZºQDáÅoÐ ž†k+0EÐ0ÄÕŽ
+æÂÉ×þ +ôä‘˧W(¢!&ux¯
+n ò+cèø8ëÚ½ã¸ßU¼ž \—Ç˽æÓ‡ A‹ý(,_ÆH3y/ÏÑ°±ÌìZð’Ê¥Óo3BXž'ŸÖw54¾‹Yùt6Ã{}ˆøÄ…ðn¶z’”ˆÒ¢ô¶!•Çñ¢`çê
+¸z×ÃÝ׸)9­¯[ÑKÀ°K0|(mj‘À$£dð¹=}á—äØ¥(áÎønv}Ä ’ ^`ÌÃüÒ<D+1PŒ*?T$‹wñ ¹
+‹’-Ÿ‚Kã
+ìàæ´ÑÛÇ*OöŠ Â-Û–ôV$ÓÝüe‹Qñï"]e ¾¯,­0ÿ¬ÃKš(æªÁOØ‚%ÏÓ¦¾ÂsZ
+Âå÷˘-T¢HÆ™ê(™ƒ÷Ò¼‘¯êHó¸ 7ÜףŽ|RøÌ-€…Ab¿ÌëU"(!ð1M¥›0|·˜Õø(!ìuÓ¾~ ¥žW8†OŸyÓßħ±yË©]½¥ä¸z¼ÛÎ}óŠ_×ÅÄuf™Wá/í‹ ‚dz±y\Š¬Dã_ ß …F ™_™Eä™Mrà%,½c¡Éx: ÏhÑ܈kݼbȓþ¼¶S±d?´‰;JøœÌ BäKI4»Ôa!è²E,‡ªnaÖæ½å$…a‚°“ͺZN’dûiéÔ2üûº ý‡ò_SÀ‚Êí;8õ­'‘£}h=m‚ŽïKc®¹ÓvHÜKXtò•2E;ĆȒ|‰"å<J³Ã|±ædb,[ƒ¶¼ƒÏŸÂSÝ)T‰'óíÑ OÐöm
+.ƒ
+K1u q!Ž,æE¸ë1ÍÊM°iÛš!–%ÁçÚ†½猬ð,œ‹—°ÑüŒ ß_m-/Ÿ2 Öü­…‘a’~¸ê‘«P =ŽŠ|+R N£#M€gïw%Ê'U¥®K‰o¨ý$ýí;¼¸‹½‚Ùá¾¾¥>3ûŠ€%®sŽ2‡M.Œ“Š¸ ¥¦ìVÏIƒ,„÷Ūxv(Š,U)`„\Uõ}‘m‹cýyœTÐN°^|Vfê‚Rò#Ë¢ó"¢Š/„,4xâÖIK
+†[ÙÎJh[‘?âe¡‹‰¿IGÀ®„3ŠaNGeó<iÀÖÅÓ!åP×­-µé%›G˜è`\BD|ùM}ÅÂVG…îÙªÔåßGõF۪ /‘øü¦„]‘-¢Ã´æëãÏßþøHŸÿúÏÇoÿû ³!pyØz£ãX$:.7ˆEßüõ¦ˆ&±*¨vc[½„­Ë:—Ý´Ù \ ƒ#_ZIVsy¦:¥
+¬æ¾l–UYÃkøb lJ%©»»göÏðÆ!zÉž“GºD¦eœœ•ýp
+V;­žº
+ß!çæÉ.ßòP–ÜÇm
+ïi— ³•àþ¸>ôUƒ²Œ¼Ù¸¤µiüN
+¼ /Z
+êÄ“’2^Šš²üÈTcI¡íÿŒ—Kz\¹ƒW=Ô
+êÓû1öf=uö?½?$ª:®ÃÓö(‰I$<b9RAøH—˜W
+¾!)(|%Yä/¡¾÷%@4Ä–O$Ë$­¤­™{™‰R9kš)à {ì$ÒG\¾ztb“AÜâÊP2Gÿ; OC·$*ü`®ÛQ:î.+‹3/vߢ”WÕõyŽ’z’5:DǨWÉsêû;jB.´¿CqpxMþ¯gW‰‡,~~ôôš l,† °úÑx¾Í0äÀDž’S_ö¨íTüqR,s'
+Ù­Ï;›¯‚ß©éÚ̸'
+¤àžÕØÕùr@^ÇàB Äj`Òµè¨Æç5q
+“ƒf¶‚7WQ¤ÐcCXdŸÊª:;*ëðÆìÆt÷xE±Xõî2»LMç(ãþQQLšZo‹£µÅòs»¯ÄÈß²“.˜:*T#†˜þe–ùƒGˆ|¼yË\ÆôRûsÔ×Ú°â Á 'ÐÒ´“Þ
+  —$B¬ê6ê b'½5ÜûÎÛØx·¹ŒŸ÷¨Ëã˜jDp†ýár¡NZ-ûŒ‘ò÷éã°®Y™´ìü•æÆ»(O4r(·[ä+Æ!ùõ0_.¾»‘ÉÛŽ6”4•(o.PYì»bH(õææï 
+>̈ƒbŠÍɾw}þäNûêà Ί·}ŠŽPJÇï«
+t.ª_'¿âª£ÂìÇ‚ŒÅBÑÏwXÌgÙ7„äØ`9;öQš?Öx¾ý
+ó[1ocØ
+d±²¦ñ+l`!*OŠü 6Ù9øJ†ü0]Z;ï ¿•g’
+s"°%ºMqÖPgg%küÕŒ2ˆ;”{ýV}×q-p†#)¢!Ÿµf'¨Ùp°æÙp\ÜÀ§† 0ì~¿ÅÆŠx± fœuCp5!ghφä–HQxÛ‘m®Ùz8j2GÝŽ" 9àGYŸ‰š—Ê{ж“nß2o Ø•ñµ•>~y  ƒÀÓâïnüÈEíiÜxä–Ã,;=ÆÐÙ3¬ t—êN€5Z|™h'Àª
+¯VÌèËË¥óžJ)¨tž3Ý”»Yíôø%S#ñÚ¯Ž+~á¡I+¦@˜zÝ‚´uU ûJ¯sôè§a-òOø•lž/))9³ ƒ Õ(î´
+CÂ×î~: ¬šIkøs³ÝÑ€ŸT:ñ•%Â6ü¼aBIÚZÃú.j!‡¸Jƒð‘ŽTžJ¦˜#ÌŒ¬§Á$BÒÑ!y9£eê²úûe‰%—D‘zföÎ'¨t3Ö$ÑÖÑëiªºÊíÔq|ÙˆMÜ$BÜÚ¤ñ)ód˜>ŽÏ\î%têo¢¢Ó*6(¾I×ç9Š}Ógæë=¢WÖ€Ä9õÝv°§3Ž÷æé}8C¸JLŵhäk2ríè O7_Gã™o†¹˜o”
+½Âž¦˜FËF
+ØÊàû!ú2øœ~ü»–YFKÙñ›yÚPcˆBIµÛÊë€"r9aõ,Ùžl›» )¹¯P¨_aíT´š@iPq„º5c[×WœVÛ;a)ОÊ=D¢‡jDl«(ºšA±7„¸„ÂGf#;;*²÷†Z“ÿñ”Õ ["´ÉF„¢¬“´LÂvƒÈÆz¸AúZqŒ*Uç/ Ëx|þº¶UQ-Zã×_iqy¹G¯uźÖö¨Ù¥éꃾ¡¨wø…;»ŸHM)"Á¦…4,j”L3 ±˜´Ùú!ƒ$Æs‹³•PìÀ‹mI˜UË9à@þøͱîtPÓ9ê¿ù÷¿nƒ_ÇØHòx‚#¿\P”²£ë¬AÄtß ¿ÆP7ƪ2›}–¨²-DÓPq‡Þ § Á&éusò—ª€¿:¦%óòJïF/>Ò‡þ’…¯œ_NË=5X»ok=×Õ"GÍšÿæhbï6Î<¿½Êz¤¥X‰sQ Nf€c1u{ȾCxákÙ 2—Ì9Þƒ°ødVŽù9Dõ©4,žùY”
+ògëÜTÎB'~òèw9îG 7Ep¸uÁ˜¶dÉ:ú‹ÊÕ`˜Ì˱mmq0ú.N qÝ=ß
+ñmíÂÐåsÔ[q:ÄîÉߥiG}­0¨Ï 'Ø\ÝF½A줷†_¿s›ëeœñ»>ê:ÅUì™Mµ?|*`n{Öír»ƒüݨï8ÿ’Vþ»H÷ë'ÛHžÚ: ßÈWŒ·ã. ÏŸÜiKÆ ¸X1ê¨W9ßú³AE²N÷‹Å<ÂOÄùà¤Ê\çi g¢0ýhfŽ°ˆüR¾Ç‚ÌŽ®Ó·4<od †xK¸«wí£@h}Žµu×>²7¸!ë´„ ü5*åÐ6„_!º^~¼vûAÇGßGMèÓà÷ÿ/—ì:r†®À{ð
+ÞÑÿ3v蠟Éþ§}!QîóªX‰'ɉ«$<çÑ°û9ƒÛÂ{¼ñðM±Ò»žºB£‡WÍÈF soëþ9ñE¨`›AÃcxseä¦ÜQ15Aµf)Ûƒ†JË•e1õ_Ä£!®™÷âgÙ.ñÇ @Ñ3·¢ßÙXxÁ,s +ØZ”ú^)¥¢sÆ.¾AÀU¢Û–§_ç`Ý·tò‹v_U.Ýô’ċωÁ@˜)…ôs+3}ÜCK{T§å ‚ÙÄ@õ‘{|fÅ,’„Hmýs€ô!s¿b½Â­ðl _H¢Wé—Øüö*R…˜¤ŽþO@élnv2S…ˆò°}Ž¬cEW³ÕÍ×3¿3 ÂUƒÂ^µVñ
+ªúžˆq9Mgöd»øÆë‰>wPÐ>†‚¢kÞzqÁèÖ¸5VrÄ×1¨2Õ zy¨ò`
+£½uñÛ0²C$Ø~*p×x±†
+af²Hóƒ2i+‡¡IéqoÞÐ8,`¨g™\Ï©ÈW …^TWâ@®¢J]¿c<Š‘[ÂN’c£8}Ð]ä¯Gä òQÒææŠ<€iE”rL?”IùVíj«ñ@z‰#´!x¾ È6òMOs~âM#©9{äY,)T'Bäîk|áQI4È]ãEAA˜â”}'³–[N¾Æ“HgE ƒ¸û¤ñ7×s¦OšÆþ"Úüähüãi< fö žpN¿Ìií· Zyãħ@8{÷ÏA½Ð<BUïÇh\E„”ZŸDþòË_ËŠ0„9=Nàä‹ü_Ô{iüç? ;9“Òëu¤ Ý ×Eù{ ý!-Ù•¥EvTk0³¨ÙèÒ¤>8aîªBõñ
+3±3ñàÃNÆn^Ò¤Ž mh»2D
+O HÚç–Má¯@ gø¶iˆÎ4pg>9æ ²¾Äà‘F_ÊàŸÃLÁÄÐ×’íÆ°Pw&ÛH® b&5Ø»q²šÇ`;k)¸&YضZ梈ÏY‰òîoU…|(÷tZ‚š}LÔÊf¾Jw+åËéûå‰(š)g®G‘æ*žñ¿ûù£sNÌɲ®4<Ìn%Æ—¦S›±fjóÃ'±ç霷~{w¹ðÆÓ…^mª_+ì@Þ:õïOFFÓÎt!›¸l‡$øvÞo¤«£GÜ cÐ÷½t|m&šÚW¹S†ƒ6Bët¢y1Y‘¢<JîM¶é»HgÖçÿÀâàô½jýèTÕ5º~ãÞzÇ·@ DuÆYg Õ?‡7È÷–Ž¹Ëç6¼Š ª
+švªÑ”:ÉtöÉʲt§WªÑ4Ó>èÂTØ¢@‡,È@Ïö)FV^k²[ ;[Ù¦í5áÌžT#ÐtìÙ·lüy@wê•Õ€Da­˜gWüÞ ‚€cV>Ú_(•)…DƒÍJéõ )…êmC‰Á/rŽµ4ÔŒÃÅ­·nÓ…W‡ÿ4¢%«?…;(Œû•"ÄNª4∠Ôò„Ù ¼gRµsH¡ÊF²îÝÕÐZR™ôq: _Âôr
+
+mO‚J‹l}.H‘«Ô§çð_ÞøIP«ÝÎDÑ+Äóp‚bdœB­†!L"ô4á²ËÛ"çiÕ¨N;ï„'Ðu–ðpNyá=¼XµÅ×C0<‚º!DÂJÞ`Yǹm©•ŠÅj¯Â©# ˆ.å³W±žåŒ4qŸ ¡æáäÙž&Ú’äO„gYÕ;¾W‰'¢¸ÞׇzS¹_h©e¬+ù̼ÓõÆKs!JgL­á—‡/é.XV-|>5~+àZÈ44eböê»´Á[$—vú Z0R2|£æ§s¦Â§öåìvx†Ä6¬f4ŽJ³ÙÄñئ¨ÌBòÜŸ×*nTÊñW˜HöÏ\Áõ:1+¾q›"/§}ê2y, j) Sžû²qèÿ 0
+H‰Œ—A’\¹ DO ;ô\A
+_/Nçg˜Oþçã¢uðd_ºW¸Ð9[|CèRXŸÝMXiâd^ˆÛâwŒ‘·4*¹óLXZÆ.Ýà†¥[v‹µ·ÕúÿUO‚”INR’ÉôðâRÌo,,xí&HˆÎaz‚vÕZã3©í Ò[ÏŽ6*Ù¯H¾8—'#b™5ˆ7)3 ¯¤yDOv(2Q
+–_L¤ 9¨ì>#°
+zè¢âRZVyÐ2¢“O
+ºy WCÚ,ýt"#7–ü;¸.—âiåÝþ‰„zÓÝ»òž²‰PI\ñ…Ó°ÿEjÁr¢m帕)ôFð¡jCÑDÕŽ•¿A6ɪr›JÖN˜Õ½Axj³Ë Rô…0Âú‚ :ÑŸCP4KÝA™‘äE ëxÚºƒÒd©¸¼ŒWĶ·­,0 ®u:cCã5*oßÞ¤HD(Á¶Ð@ú1iÂn³ÝOÂñ ìQŽeÐ!R²ˆq
+CgÍè/LVKv›ž “„þRÇŽ ¬©¼9ÇÑaD®eÏv4M :ÏݬOEžÆˆíꢦàyméò£/·‚]CàK¯«G;¥¯=u™òôôòwÌ”ŸR"”ÿ¬ôŒ¤¡1‘®y›ü6¥Zº œéSDÎV#†n†`èÙB=*1fCš+|ArfzµØ²C!Õ4ì-úîÈUv; Ø…Ú1JèÇrïß‹‚È-ü&%Wþ˜ÅŽ«û,|@QFïeùú@ˆ‚…  !ƒh\E0<X¡ZÉøùã :—¼¦~òKäó›˜GûýùNþúÛbÛ+·¦}—kÿšƒÀh$yµóÄŸ‘¿Ök‚&„¿ÃlñÝaÙnP­ç|Z†
+,`WeF}<ËðqÏr> ›9_hq>ç ¹öüÆÑ|Ó‚,Tعý¦×”ÍÖÒÓøˆgÇ$„• Òa¯Ûrsð¿¿Óž¿>w!„¡àsr3í¥*ÿׄÇM{AÜŽ™[÷
+~ÇæcRêN0Êò« ’Òܸ“\kŽ²ž.;°¶g‰ŠQm¿êšöl4›VoÕƒu
+­PÿÔœs"³-ðøÜxÛÕX––m öúìáH©¦gÑë´$@èV˜Á—¶….íI*š Y2³Éí¥…¬dd™&ïëÚ€¨' Up÷K¾™Us{kŽb–2P ‘8,"øÄž¬òfOdsr(—hïÎÁ·îø…w·i‚¸GÎy÷*@ƒ¯(¬Ê99¹ ä ÌçÏ=ñ–âäK©v¤¨B7ÆYØ~Ôý2vÄð0ý‹½yücId.Èž³§Ü¤â0‡™½±uË°Îy “Qªz®Ô ²CÝ*þ<çÀ›ûmü{¾êÀã{vÝpOñ?uÕÚl›½ðì#·¹øÜ
+ÖÒÖ¾Yä¬4ðÎ| »Qþ„¶—ª—þ{J>ÃL€íò;ŠHQœÄ¬s(|º1Ówd,<ŸC©~ĉg3¶.€÷(áÛs°Ki…Ðß‹i\ £¿l6² d‰X=­à~7Ž¿±–´›?<As ŒÉøáðÝñ·`s*£`Lª”©ççÀ%48M>—…ûËdŠd¹®É¥d÷srãa Lãp-T KŸ†]Æ‚[.u!ê~R•žég=i.¼l˽ 8$ðÓw=yï`Zý—ñrI¯ãÖð
+¼­@Ið9öÔ»ÈTÞÿ4‘`Û:Í–•ÉMŽpÙ$P¨wösH( ÚLÆåí ?B¬9ø¾^õ5ÿ¤ÀÂ{¹‘RÝòótu¬1ݵ…ù[oÁ¼c§¹\VS
+ öI{nàN»†y €|>ä‡"Ý…LÈ%ôãtØaHk,<¢çû‡ÿE>hñ“h 5<›‘¯‡ã$åìHÖ2k`¾Û“i‰zXP˜ìÇ¢YÒxoà5»Xµ$N!Ýnlñ$Ò$ªáJr…5Èj­/ ¡°.æX8ƒ{;†„laÇÇÎâÁ‹wïC ±Kþë’'{lLÂþÒ×;õGr2ÆW[DXW6c‚Æñq®_Æe§b!CL›>ͽã¯Ù-Ç¡¨wš÷>½%Q2¦íÇnQ‡¢‚ÊPe§*NÄNC‰Ó@S‚7ÌŒ_Ú*éBtŽUÒÄã!…fÀ‹8›òçSQ`sÕì³¹ÄSÄJvpV­Ø¡ècAà˜Zx°¤CÑì3@*Hcz YÒr’óçâq•0ž=Ð[çç LjIÂ=¬öÔwÊ_È݆¯ÐO0IëCõ*ü¯s8挀 Iñ¡óPh(øpM>)´20€Î¢®ÛDõ9ŒîÃbz™Ô‰wòOÁÀ>$”éå\ö—PÒLnW¾mMÀ| $"š¥àuGà¿üóÒæÅ`¯YlWÚûË:è¡ðJëp;®ÌÈYS†×û)¡õ];}‘êa‚Ϊ—”ÙÇòçVˆ9”GFjæ!gØ.þÑfÞä~JsÌ%),-:‹…Æt‚Ģљã@ô!nùtN‚°ñÔp¯?ª1rHfšv|âÀ)òGßdÖÅà7âîúT¡É¼?·ÚÒ¥Õ@ fûHq,‹ ÆýÝh+S%ãç’¨!Lk‹m©ûK·¢ÄÕËa•uK2æøöú±œ)gx˜o(î
+p0x
+ê2ÈGeÓ‹|è*A$2ßÁ‰žJ|¼´w­Ñhçs…‰ÔO/€y¤I|Ü Lö #™</°cUî…¯_ä²r÷" Ä~Ãï
+ÆXòÐœ×gV'Û¶ïs+ú$°ßQáéR…U žXv``€¬
+Aÿ’ÒÊoj
+#6Ñòã9]žz@ìñŠ…ƒq~³Jø…ù!!F•0M3,Òÿµ/EˆDY6 ðhÆÇJ¤íƱ þeä¨X×}*êÙ †M¬`—Çgíðò[‰¿œTƒÕÁ}E;ŸÃºd/ëB÷yNêÀ¡dÜæëšç'\Ì—Ë CKÕÝÚ‚aX€=ñ[EÉoÆ1zÁßAò¯+Td0jœ¼8Ï¢1€5AÿZ¤›c8’¨€×½(!µ@”ÁûÄš<È·ä W˜¥s“ùÕMévÆ3ÑlT[ö4”îˆ|J|—ÄðOßå‰æ†Ùƒ§
+ÿçÕD^&Ç…!Å:«(¿+Y
+z/ J~ ‚–Â÷Š½¨?ð®v<%àLXd‰eõS0Øk`zš;€Ÿ†P:o‹Õ‚øøZ.­è0ÔJ™×F“f9%D–ÓAgo ¯åïØ©â%Á0rð¡i•à„‰¥ e\¸àS@ži²;³°+Ê€·¹4Þ…Áð“ù¨"É•±àæO9cYkîþ1%\ÆB“¼ÇøÊKà”r(ñ&ãiGʹÛùë9 <.™ú~xŽL":t=î›P“tÖ™þaRÄ•Kp¥°ÁˆÙkàœ {ÂXÏ‚õÈV«‹/n ¸R€=uÍDt+Ùb!!üHíç0¬>0‚Èm w…†kk›š^p‘Ö<q˜=›ŸUâÖ“nòOÔ?ƒúæ|Ûr›±d
+).2üpQ{;óöÐX¸ŽlÕþÒ×ä¾¼ºU­,lšq¾¶>Wµ‘KÅ5€$‡ë#™T—ä;1M¼xÙ§"â§l.¦m°b)¡Ü<ä8G¯;u¹ZdóØ0—wiô”°KX»iøò`°x$dØV—
+À#-Pá=_åªBó­Õ¥?±Ûð^±î¼!È×BYç°€»£‡{,ˆ)`oU0S¸…Ÿâ8”ø—b‹¨]%= 1x«Ö7Í }œ<—µ–å•• ü¾²…ê3ÝŸëu/b“ ´J ü±¯Ið1òNÖ~µtX÷þ2Ú`®t*š%ˆ$ S€Ù%HGB'0!c•” „!¬ûSŸHlOzB; ÇÄ`‹cÍ뀪ÿBÞ¼ÂdH~ä´]ÂB?¢›k
+5/az±r LÄÛ d<Ý8Cñ`ìEü'`g€Hø|bMë)kü>‘Í´øHX_÷¢:‘žÂÔÝwdf(¬Æ˜L‰0+™€°V !á¤áy¹7ŠÈ±†Žƒì…‘8Ù¹)3BÎ  @Û’Ãǃð7ÙD/1L=rä¦ö¥böˆw"ö)6ÚÒÎÇàkánYÔkïÁOו »kBHB<üÙÐB•¤‘t×rÜj^düã¡.­ÿ3^æhrÜ0¾Êœ@÷%¶CÝBéèþ©ÿG‚-wÊn%–G²àmUé6n5Ä•6Iç4ÐkW+‘ ™ûá Gþ†‡<ËW`±iÆëå AB;EY9W8ŒÝΑò
+Üe¡(£}8›n-Æ¡W\Þ») „¨Mî9—y;ßr]÷M×õszãmú¥Ã^ÉÛ¤~}‚+lpA&J\ÂHÙ9ï·S¤OG‹ù¦L–K¦„qòú¨”h-H©î:í/×&wå´lMŠh7jÛ —ñjRЉ¨Êh÷ EÖ}ã¡›-Фn“÷È?> +$¹™þ9¬3æPßÎ×ðªA€•=X%Ø šMô鶇°>ŸÌߢ%KŠh.™fkNÁç7Å©9ê>g4%Z<aµ‡t‰g&û ×‹lÒv£ŒŠl¥#sð—!ùVô6úo·÷¼!9(êù…ngç.ÁÙá äg´§óð‘•J’E‘ Óo“ﶧGÌVé/óA-ƒ¶ª£gÛÓÅ¡»Z/9lyËWÚ ˆÕMµw÷mW¬•ì@\ª'í‘p˃ÿÚ–ÂÙì$fÇJ2þ~ગ5ÿµñ@W0˜Ä|šÃÇóÜÛƃ(%À$ss7-†ª:A¸L_>ônëñ¹]ê<¤²î=×Æw¶;Êwwº ã[‘ãI¸0‘'é$´óymƧE‚tÿ§{ÝEêi6+/1ò­<^ÑÄ•±À:pñ%MfHG›>Ö/(üŒ¾R %ÂUÓí Ž¨ˆ+±ÛM €‹­ ÛE¸(tâó/û˜ÑAà·Â‘nä"‹€ã.%EôkGµK‰M–ÈX9(VÿœñCF“#jœÂç‚S‰¶Do“ØŒòËŸ¡³‹¼¢7[û½‹b`óèsÌÇûêÕEš?¬Éø$¹ÓêCL{5b¾SôPh]®˜µë}>“
+ì‹)<vGCÃÌò™”$Ñ ¿ÙŠñOº!+ª´y®â,ïŒãpTÑ"ƒzý„Šê žHwz´½€§ItÜTÜŠËŽ®_ŠümoÄXyeøº—‹<Þ®û¨èÂ
+¸nEÆ0r×Øá·=šÀÁi æÌ…;E²Jˆê3–©?R•d
+‹z>ôúØò8›OwêIyË]‚¤˜’<’´ÀV‡w/î6P'Rw°”¡¾ øýœÄrU”£”sY¬&ás—Døò‹3Ú«p­`졦׫Ȥ
+Z;ÎÓñølŽ4Ñvp­#ËGM7‰€WËmû%¬R•¹Æº¿nºÖ {„PÁív Àgšzëf9èÄ“¦hs?Še~x©fdÁOD”ãG&­h"cÀ>¯ Ý^%YiGÑ­ui˜ðz.¢Kkþå0W„
+âÖGt¼Jøæܦa<!céêq'o%ë*VŽ.åÉ¿ôäŸCW1•Ì"Öý¯¡«„ʬ¼æÓ« =EŠÒ«TÇí%8;Y”гßc§äߣ:7]kØ-D‰í 1}ùú%ÖÛ2î<ªP¥ @ò\ui™UÇÊÞ¥iW]ZLIh
+iÈx®î¨.%¶—‘{ç\çþ5ÎÞ_å,r ?ÓªlΗ<OÏyñýSÉ¿Gõ{(Ebã¡8„‰¨¿"³|Ì‚uý1’èýtŠ–׆ÓÔ¡AÆÚE—ënEߟ|ÓÏõé»O@›$ÑÛYÅ*Íòˆc}:E3*GäÀÂÍÇK+ÏuÍ$ÊevœßÃws%ÀQ+ÂQy$6Ž¾B©ŸGðICÿÑd;ƒ‰Y¸vÔJäÑåLç1ƒ£ÈGòVÀ[7~áaò‹Þ}å·S³#&:€!ÝÚ3Q!T’­¶gUŸ9vF -ÎÛÑ+çÐœxVØ£W”&¿Ûf3ë.qÅŽéN‚é5é|TÐ黤H"Y <ªSbWu%åZ´§s¢&Ç=D=ût5ô
+½íW±]À„ÕöŸ(áÝbX$ðô&ËðÀÅé|pv¤GF@³ûòÊÞªk‹«¡0÷—ƒwàþÉš¦Ó‡E¢D4Ê÷Å|Š.ßt)úþ£ Ê_«4ÿ€Y™üu"¥o2Ððào·»ß™ i
+¥ôŠ3Ï…1<­0Îã\õ¶ëé™Êê×–¿ü$ÖZñ÷gâ·Š
+9Ë‘[ó¹é¿7YKöÒ¥ 25©îÄÈy•HD&
+9mï{-Ò—Ï2h‡|ÖŠq”TZ–+N‡^á®.ÜÅMÒ
+W[‚öc
+Å\Rä¯þ{¥HÆ´Å5åñ¨nö‚6j‘tÈxSĵÿ¿“?Iåsn$˜°&íÛƒMn `<¼¦—S•õ~:ó@T0P¿8â§&º³yÈíŒFòüVH2bFrû£çù#6ÕÖ7³”Ü%yµ{ûtà•!&EåÈz0fµNX㩆˜ŒCCÈçïT;Ê’¿Càa,eÉbÅÙÑy•9{ª!¾T'RÙ¼²£døá„k’X%€YNÜŠ»Ö$J™Ï!QU˜ Þ\Û>ê”
+ 8’è½®ïä©.xùˆ2)á¼,¯¦¥%*}…`8ìcdˆ°ÇTtl
+þ’­!$aËÑtIh’ ¡‘hʼn§áÕÄž’`h‹ÁSÈ<=}‚Ì}¨$3´z.y:µªãÖT%¾gÚIB%€X7š‡ðŸÈšÄ÷WZшØuzôKД=†ºÝ{tø/&
+*E¿Á<s¸
+2$êìŠ`I¥'¶ ¼a³è„œªÄîn5ðláÚO%£Ù÷ì6SC‡³rÆÅ܉š––D䡯û‚ž öëo\ØwMnɲ‚CÉCt£6Ëľo‚žˆÆBà
+‰M+ÄÞÆ™äÜž¾ h7ƒãiä:¹ ¹úö5R[4,Pm¸Ù,­âÅ«Ý£ü›æ@cß”Æ#c,’£¢ìÐ\Ru?Bi9Ô2ûHð›6–)»ó ‰ Yqí l-ݽF&±v£¹"°åX øÑ]hæžÇϺbåc¨Pµàß‘Á÷¨e}‡Ö§™“ ÌjèSøÚê
+ál¸ÈÎ~?P8AŽïG¥@‚-YK2E©Òú^„Àì-¯O2ÕZj7!"nÖ6=ö‘¾KÐëtѽ5®ÒµÈ²ää T`hrÏÙ|Ð'… SJ0÷Q 5+_Ÿ%y[3:¥¯ŠÓŒÓj5ÓYuèÈ,UOü7êEÿü·*È4`oÈJµæZ·AŠY
+S[k+0ÆBXxE.þØ ë"W·øƒu0”2âo‹EÏØ XAü;8îÐú1wŽ_­ñ¢ ¤¸Ckä*ÛÂt úº ‚
+
+4²!Ài}Tʑϵú©æêì°Û#W4ôˆ1$ø{mh}¥ÐršƒN[Ed†Peqfb›é-›‹…`îA|—’e²¤-OÌo ($rjq(¾ø=KšEŒ`öÄwKLÐÕìΛ “¿ÿøu
+bw
+@wÖº]*SÖÀ 0'Õ­T£Æƈö„¶BRÔ©WØn[™-Ô
+Úzß)q¤+§¨å9x8£\¡ k2Þ¢MÿcÝPèôAß±gõÒB²î uBì(ÒÏ1ÿ2^&ÉqäH=îÀÈ0kÕ’·Ð6uÿm½¸'+3*V[·u‘NàþýPçX.ü|›ÝúJF–E›3HS V®BÈ`¨8ŸbLÙã„–Tý[Ñ’ ‚ª ˆ×-(Vœ¡3mÒåÆÌTÿ-n±É½Êb9¼9 »¯ ¶y*±—ÄX<C:Ãø1+hèÄù-Š&g²gY¦Æ$YµH
+»ä_ú;ˆ?¿<F¹ps—DÏíþ9Åu$„#×­Obyj@K­I!Eü{*pæØ%üŸ6øý´yfýÃÊ3b¿8𧳠z¢,³àJ‘ÿ2­Õ\&ÔVói•×8Iü'(ú9Þª®gáër*Ú
+#Xµ("+W´/_ÉnWLöÄèJÖ‚Áÿ¾,f·Ë_­¯ 8úÈ”‰6®rI _70Sk ©™l9’R§#䥈’ù“‡ÀL ùÉT$‹$N+¡ ¥:õšØœUQ{ÂÁ¤nßœ"¶
+h€‘@߾㌠ˆèØVž»—fî‰u›F©4å…MpŒA!—ÇjŸ"Ýð/::jè
+@BñTrGL/EŸ‡¢åv'Þ€HÈ‚î s*BV% <>¼ª¼->aåÍ¥JŒ
+ðë² ­{‰RÚ¢+·ì ½~r“ô‰‰)…ìœD$ÈZëm> 4ŸŸVnmPy$*Å›’Q¤Xà (ï™÷Pe¸E›"â&K¼=ºJ$‚,2ÄcÏ"N0@ˆ·ÛCŠ '¹Ø}x"ÇäÞ}±Ør~@®ðaiÏÙ| ÔÞ”:Xªf‹ðËK%:¿°§‹U3Z^’;'Ù¶]z
+
+î²&Ò¿ 0ïEÇlòþ¹KÑã;w²«Ó…¯T¢© JÍ$¾¯~(zñb»5´}W¬©ðIÐÒvü‚POTØl!·ÉÈ8hwQf˜ŒfE¢)%ߤ¼ïmÅŸF$î.µ”Ê'+s ^ áÀ>m; Ä”b@aúlûÌð
+ÊDelpêmìcÄHЉäsWt(ˆ]aíÂÜ%üÞ”|L“a¨Á(:kã_â6wS™ñ&\P z‰‹Ÿ¹ ïÁE#¦¥¤¥Ñ§lw«»dà;ŒÞºKDù8Vzˆ]YŸâ†t®±‹b%¾tõ"§}Ng è²N³ðÆ“ ^´8µ›%…\h;x~ê½ète&›ÁséNá¢eH)™í‰âkäÑlÕ¤ˆ¬ŸhlzQÛ¨ô8³“ÖIa‡ìÒ÷9Ð!ì\I`éL™x7YTÚÀï¨8à PÕæ …ƒt Ç­s|^¦É®Æ¤»*°8‘Ò³‹RŠ$ !}(ƒþ&1Þäî€(Ó´Ãi’q&dN‘q.gY?”À›Lí"£mÍ–W‡Þ•Ug?=nŠ@¬RòlÓÞÍå ökkVzG‘ ؈öpœ9Lqš¹*‰\1ôöØžæ‡äG`ò4=rÜ )n‡*ÒGh F#Ƴuº ódÁP1 £ä%çsÀ âÒø¯êÍB…€… #ÞùJè. ö$ÍÖÏþÙ âÙ°Û0m¼¯.!Ý”ôcâ°/Ã{ ûƒ¡ £qNÄO±{FÈ ŽÙ»W$ÔÑÁ‰"bß¹ìøC’ ÖvÍ$0E¹ì\ö1‹oé@ÃTÒ©Ùâ´ðÂvÆõÈÙSKÚ\Ì×ÈLF£ÄôfÊ&­
+l÷E(šÝENŽ-—fû‚ÕÁ,`nÒ0Ö'+ÕQ%ýÑ×. Ð`'MS2à@³pÛÄeÈFt DS²<°Ö08á¦Ü”@žLß;=É^ŠYè¿6òÞ¨,%CL®™IzDz‹Ã|²£°^ÐܶÙAÝ$OäÝëXwÌp+ÁŠºâ ¾ 'Y¥Ÿê12رAÉèöû¾”8$è䥊VIª˜[Æyf¾V
+â›/–W¯”;ܯb!ÙÍ„œÍ/}á‰}ìÅšÃ-£Lyª¦Sèa-‘Tl`ÊÀà¼)©k{£œ‡%Y®ÜZå_ò¡èaEÂ:—DÇÍ(A˜rDÕm‡ ÈU³QfŽ¢¥Zsy~Ï †½\ÂGå\êWq²,¦
+ÈTyébâËÛ ÈïÎu\w¦›a¾”nÀ.0Í»sèƒ8ƒû˜ÿÒþ„çÃ$êºXÊž¤œÁÞ±3OYU
+A
+à|Õ
+d¤z¹sÃ(¦’bôCÑçMQ†…aHñ⻄9‘'Äb’ž‰RË~;‰}”±ö8Á5±[‰R/Á \âï=|%çbA³á­ 3Ÿ—% dð?-®ÞÍê¯#8‚ƒ­²”ÎP/$fà€¹YC¬þ<ÙĈƒ™x8” 4­“Ìÿ*YÖWØjdI>…Y¦C9D蔓â•V…²wXÞiˆ«>ÈŸÇ‚ úƒVÒFÅ[ /Ê’WÌwÝã~)9Ã/áv™ôÕÝ&8†y”M®AO{Ûˆ™ìi9Ãü‚bhJ
+Ü“ªùlm`˜õèÂ/Ó>˜y°t½‚õÜð~ HkrFQ/µËÀ9AÙµ®4D ™1БAO!FRÚ?…ó¨ò³—ƒõ]%+6`ɆžF ä°Rè ‰æÊöÈD°ê€ÎüR„Aà•òøˆÏC“¿YÕ°Ž­ "‡Å¥nG'¦†jc§ŸâÔ¤/爮YRg,Ù{„븂›c1ijŒÅy
+q›øy÷Þ8'£Wp¸B…+èÐßèñun²€É¡yNPR…¥ë¾b˜M+`9q­¹SÍÛ‚ÐË;ÛZÏ)Ô7•Pó <†•~ËÚÁfÁ3nar!üb<ëãYî}ªLiØô”WqŸŠ‰ÅšYQ'm£€¸@1°åÅõ (q­ ª»|²Rj O6´ªéˆ¾Øò‡#šÉ(š›6,o÷/ž!Á\w~» ~9øÌzš6mÜ‘;þr3³2„í0ìöv/ƒ—|—rú ZŲÜi7>ûé9¼œ„àFÚØ_"ââ)‰»GõqÀ]²Í|)‹®NÑö©Ôëø<w–ój˜I›|L©Òö›.sÞÕÓFXCÛ«š·þªùØš¤Ž5lzÇ9–Ia çÜ€¶œTë¡!=W´ ­SZõ&ý;}*8WL<Vú&•Ý7 0ÇŒzãž¼¬äîmŽ ¿·j^$»qh´Lg[æ?§Ìå“·!ÚŸœõ9¹É«‹ w €Â¼ãÜ wÀ¦ÉÕ×^ΫXn¨vÏiìVï³Ü3»w&Þš@8]׬C
+£mrD܃Ÿh®?Î*wàfÓ~3ýpúÑ|ˆáä8-ÙŸ F7Èðiª Ý æR?ñ¾Oΰág­=3¢gö¨\Qô˜Ï-ŠZ¤´çÊ?–Èš®>kãò¡<jT>iv|/`5“™VÂúž‚—[\<ž“8F q´áØà’à
+|x)‹ˆèžQÛÌV^qÓðü°Ð:Mwñg‰0mÚ+í×"Ç3.šéAaPf"LÅ¢w¦iìÉa­Í
+…¸,ƒŽªªJˆéën€ôÆÿ‹¨¹Zå­Œ:åÀMo+ú„$Ü ß_;’ý*†“O£ÝŸž©–B^¾¾à¤}ÕKûT!³ùÀYã<åËvôÏnÁ¨SÂ:a,è•¡dFߦ‚CCoÆF·ßÄ+ã(ƒ¯k¶$¯ÉŠìÔ
+žÐÑŸ½Â¯+_„-|lQžgO/ŽàV#Çek]‡` E3 ê2ú5`ÊÆMnIQZ#öS
+°Š–Òª†#™«-h»‹@p>,„)ãZ¨®"¯ùâ†oóìv$Ü{‘ŽBêW H'.÷d|éi'.U†B|‡ ªs÷Ê;q©&kZR™Ü0üçà(AÃͫסøªÆ`°WLºA‰Í‹_Hª5 ƽ^ÅÏ:gÅ
+óÝðW}‚H¬9Ó[¤‡…âû§*Fà¤hÙGH‚X—ùj¶'„d§cnùDX¯¹è•(G‡ÀšŽäŽ7‘‡‘ׇ|1ùOódkÕEHÞÞ…7<¼¤'„¼´³‡çZÁ÷–[Ù=¢2iv-£õ@¢L„447?÷ 2sëAWãAf½HÒí ó;ž‹e¬Ö}€DRE¼–Y+ž
+^A1üÑ›ï€?9é"È*4f¼ø¥îÒ§#šÞ+¿fU`œf«"JŠYò¬Äök‘ÃQ÷×ýR”4¶-J—Ì›¼‹:,˜zí£U÷„„¡Ɇ\–D¼BèX©Š_1š…¢a¥qIrÕJKœ2O³‰ª–Fœ;Æw–ˆE‹AiïÇT¹‰ººï  k[¢ËË’X˜y™7}‘ìT
+¬oA-R<Ñ”¤À*8>mIæ/`
+-I¦ Ÿ^^¯¢{ ^bî'–è0¼˜#…ý‘<¿a¢B<±t{„Ûs&uò¼A$Ê­†µ¥µ •«Vq
+òýç 3òžXÛ–@’JpÎkæJ´Š²©b%TkMª'º?ç┈ðǵà&òãöº_ˆnÃêõ¼³ó¯Ezcû5zìö¹Dü-t‚™ x•EC¸3ZÄ1]GÂvÃÊR¢ZÔGqD2YZ_€é¢8’š D§Œá2$²%^z|@ñJ³sšÊͶ•.Š{¢ŠKԴˆþ"ä ŠKHÉÔ8ûÙ0¾²8—<HŸ´„8¹²8"™õ9#š ãHª _pœŠõSÑÿ¥q¤E)Øèh®¢A %<9²›E³hä•<öPÃ…Ç‘®C´Æµ=ð8"¨â@t¸ÇãµÐ‰6ÔDª¢ÇãžäÆãw‘ÃãW‘׋åÝ`
+‹¬ˆëà@,îì4ÇÇ/-íà¸Fîá ª¹}/¼Ããê1|ƒÏÅfüÇkj9jÐâù˜¯8ŽDì;c4öGÄïðnfël¨GÒiXGÈ.K¢>©”Æú{¢j;¶ñ³Æ¡qGsq)ˆy-jeíž7—]Ò'‰V·'Ÿƒ§+æ\©z,N1£¾«P¯˜]†ÖˆþŽšÿÿŒ—Éq¹„-´€}9ëé…®¤ÿ×ù(è‰ÝÕÒ?111"Sh –\²±¡h0\c,jOç ]I‘çPÅÅ‹ÁldE„–âƒ×tQ;¢)C8\/D>¶bæ†ëůèzqMEPÙq;ù¼êêű™‘¥bP§kÆõ.)Ýäé)ùø/"53^”ÒQy®±En%C‹dÒdf¼ ­y•S2ÖÉLî/›u’zZDÉG(ô€"óVû†D["*ݺYÍÈï
+O{.£Ž¢.*ÉzãZ®c5PQ¢AÖ«XåÔM²i“Üïà?ÜAŽkÄÏ$}•Ù;óüOŸø\År…’þº^<¢ÒLñØB¦¦ƒ¹–CFÖÓ0y/sÖOÖ¡ŸTiG¥"¢ÂöDÍt•†B&)¤øtLÖ…Q%ÈÏ ðg”@Öf
+y™1^Žy¢º9çùÔßqyH¶OÖ°ÌÅØÝ)Ð×ñKŠ,Br Dü‚aåž2É7¸–jtïñº6 éÌm^ï"f =׋©²Ã¤lSžÁmfÍPš[ ”‹%%ïq½aœIä:…d©p ¡¼ RV‚Kœïš±+fmP£3Uüg—'O…0LçH¶†#ÐØHRZÖŒ
+ w¼¡¤Õ%qÙ¶ æLÂ(‹˜WÏpJØmÆŒ\c‰é›ƒ[³
+Áe¥“i×™8ãÈ?MVÿ×þRÀ䆳\òõYÎUÔ9™¿FÎEpZ¶é*UQŽ?lˆx5+—¹õ)l4rXÔðTŸÎ-à{¼Ú|º ‚ΰð½ZžõÃìÁÑ/¦vÙ:”µN¿ÄäÏFÙ—nX°À*™+½ù—áï$’5ÏñáQ8é†apG>Ÿú^Â>†ÒÁPÓ¾t)0Ð4ÈIà6ê±/]~?ç66÷Û8ãw”3Æð/l•,ÕßÜ]¨d5ô(O÷öéçÙ:ôh¢a Bu˜ûˇ3!e.ôh\. Ÿ0.Ÿ»>_¹“F$\¦.F_7kR@-ŠVÌ“ VPs¤ú'òÜ/%q@ö†|¼w©ýµa0$nEY¿‘‰H°ê^ž"h ï[ãf Ç·|K¼eŠì]“¨>FV^m>ÅŒŒ½s¹tÜóÃã
+;s‡@„q 2õзÍu怋7aÃàÌþ´RÔ)ö,Uh£ymù|¥ÁkÞþ4±3¨Ž4%œÐåU™Fqí×Æ`™Ém²Å-žIÏ9—˜ $Â'Š¹-˜ÍªÒÚD¼Â..Oi Þé0â†'¥›ÌÎaï°‰4<¦h·áAŸk¼A¶XdÛ×ÄB-ŠdEyà ¥2/?³; ¬H˜”¨¡hŸJø
+Ü<m±Y€Zy­<vš¦•ó.+¢ŠTÒ 9÷Ä$4~CÊà«i4Xt‹ ÄüSH€vNÆ®3V-qÏ}N4V–)ŧnýµé’¹pƃÌMí­;¡Àæc{šÌ¹›VÓ:¦=v‹ Žjé³nH§¼}hŸ™sKr:YÒ¶çc¼+€dqÉ°O±l¨L‘ƒœC’ŒÝ£ß$,L6}D¨´a̵k8n˜°h&¬_¬«íŒ?‡Ì;ÿêÖR \OWÁV0fuY&hœGgí<e3È‚©Úþ᫘B(Ûˆ_ys
+IËkúqÆ û€¦éÕ=FÃ>ËÔž—l–…kát1 $Ü !ä6ºŸ%{TR›¹L½?¥ªwY­0¢4øC¦’ï¿-«Œ¼1ÆUc`¿aĞߣxÉ%b%[5ÙÉŸ?|~ZTöýpŠü"ˆWH°kEôÿù
+hù4_ª›T ;عå¡ÙÈÙ¬O5>OàÈ“ø6üsÚ»èµh¾jôo„©dÙKëõéUí]£H^üâ
+˜zD¶z€üÙ©ÿo^‚†d¬5}K_ÖPb/»×ô.×Å_?æºøÞh§¹Dr"ð!&y¢+h$#–ÑÉ}ïJ±»IÊlOÑ‚‹SÛŠ±izócm`Û¸™ö©e}-ÌYû|J`‰˜¦9Ço÷òøµüκTÇ4ÊSþQ
+@v1†a|?²^V Œm’¤×½&nI¸ÚÞ¤ðŠÑä¨ê9cëì ½#$1?Ó¹oTh™¶²mµ2ÔuKÂmÄx9¡,ÈEŠ*½2‡k\WøŠIôî+mßê’Ó¾6[‘:wÎîÆ= ¸?*Í\´3¤B$W_™HÆg¥“ϬñŠR_ûSŠP(%½µ«#S0=F(-» ýÁâ ·'Ÿ^B‘ 3N…›Ûh“dàù;d\3 +/
+–æÃÇ øj£`@?7FI:ì„Ý'Hʱ˜e?ý@[‘d»2A–±B@b7ˆdgò/ý·¬Â`À
+ ß½g>– Š{üM ØÈСp¦`ŸÃ^µHïÉ5O½ú{Ï¥Va!ÆH2áÓ³”65£D²#þÇx$׃@ôF.wÈ-²Mî¿ÍCbœ¤¬©dåú.F3‚î¦ûjM÷Ì–Mþ]š>æ¬ç mY‚ý!vÌ”Xë§$ýJ„à¼úA6E\T qڱǸ3‘dˆÕ1|l28zó#Õ3)Æ$²^Joí ]fét|)"2
+®ŠÂAØ¿?äµ–M,†Ê`€I½dYFçåKžjÉh¸S¢AkÀ?° ½”0~3ìT;íTǶÿ.á 'Is\ a¨>6,Ô€¡Çó&‘ÊÉ+@÷éç@‚Gg}XQM¤ˆ½‡;¹@p7xÅä‚ÈŽë'.4½ªÏEK"lõkXV Ï,ª}33!ji±Šÿû©›Jþ‡ž„ ãcaØ’Ž¡xqÚ2}öO.œ±^ÜEL3UǸÙÿoçuÎJŸ]Åš¿82ŠöëRÆ›·ƒßÆÑmêô·×€ÜzÎ7«ýÏüa^d›…9v½öçµHÐ<ËÎbGIJ2\Ž4g熲·“¡°g~˜=‹þAô:eAw¥¬–yá1ZØgiJD½g
+ÄÏè9g!Ә˹ºÝI”á.«.7žíWeŠHAF(×Û1õ4+QƒùM_,Ð]Ò?íP¿pîýK€
+H‰Œ—M’7…OÐw¨µ#œA ,š¥¶s‡½qk9÷Ÿ$³êbÛ¥ÔÕY/ ?W©Å†ŠJ­ooµT¹J±(&V½>~m¥\½«–â­H³Çû ÚÅ:gµ:ÆH»¢µ¦¼"æ_kÄ墣órµ 2ú°ZKáÑ‚ôˆn½yHkßß&h>:¼ö’nÞÝÌêØ爷ÆQRÛX&uÔ>z/±½Á ¨|¤È4U/W+b:F´ó9õ²æ£¦Šž½©—š–P¥·¯nU/)Vzqí½ž£S¯Æ%x·Ž1>@~ÊÕ6õ
+1Që•ÔÈãûÛŸoåñŸ„òºWó̈ŽûñŒIÇc <‚ ÓñrêÅ}ßì
+2K
+FH¬s˜ŽÐŸ¤Ü^„8ƒj{]ØuÐ ûq€LSõª’kt_N  tYV‘T¡B–ªå2fÒi}ªi{SËÈ‹sýa·)”y'xµËÎgî‚<,$¯®sÐ…9œ]iC4'2ž«.H!;6Öƒá™g÷)VN FKäúþv6•,¹â²¯>¶Ã,@ÉþM6êæ÷ Á-@DCvÆÇ\—Pȇûâ, ƒ²¡
+nPÆœ `Ò÷­¹¤ècCn!þˆð›\6»U1?@våÞ2@J‰8ŸS=I§ýàñDŒÙ­FÇÜþJ Îa-–fpˆªŒm r ƒÀråØ5ÚÀSLìr âh
+/§ 2i
+Ò¢è¨è Ôs24.ºÈ“Õ@Iõí²Qá•€5]3ò
+;ÿï Q‡”lÖŸÖuŒ kÑùu{ 0n ¡Ðv}ò‰ºcHÄÝZì%t»ó#nS='zVçnäàÂ9ø| }J³¡]FÑ/›åŸ›îÛÇVù õ Vƒséo®{÷g!€L«ÉØÏ Õy6¨ö!Š-2æw%§HšËi_îÄtô•×»’5Å6c:I}ˆ)sŸ›4[rAøQÔÚö¦ šœ>!ˆà\íòñâg!(È=vR7ßç
+[0>È‚
+ÜÏšc›Ríÿu¾G¿º2™Ñ£m•H. ÞVuöeO
+< Ê8aƒN­;‘ap/\?.^‡æ\Šæ·bhi 0z÷[IS
+~b舛I»ã—¦È×òM¿TчI ܪ@¥rY0ÐÂog«”sݧïl^|™&&PEs‚¶’t‹û*Ìœ;yäýí sìv¸ EC]rWpEèΉpŒ˜=S6ôÑ‘P:­ª^² ë>À çñ‰¯/¾Ø±
+ÏÉÑø˜Ú/¨à–Q-㌭‹A?§¬
+86솪DjËI6ƒØâQOŒ ·ñì%Pxarò%£íÒ~,„Vv[Æÿ²ä$I gÌ ˆ9ŒËR
+†i"þl…‹TvðtAÙŽJqåóœ ¶r†,ôQ¶b,ï/`––ÔÔ Ñ–+º(¹x0ÎCrè”×¥ÆßsßtÛJÀÈ´+s ȯr@÷¦‘lë¥{Á¢<¶d-‘'Ù©o
+LýÊÆ<÷’ã~N :×XõÓØ@ü“$Ïè>5 ÀYùë,Ãg„’ŒùðǬ‰uÀ¹PaÈŠóOšü'|'Ù€"çô“é¼M[g‚‰Zû&‘V>\z§¸ö{(E¢‘tæÖ®57W ד›òî½ùJðŠ5ßà; n^ñ\
+BÁtÔý‚¸OŠHw¼¿8y,zœÝ<Э}ÿf”þ’Ÿúõ_JiÁÉŠ‹#O¦ûsõ=Õ{QÛ]Iú¹®’n:ÁŽ‡Ó.‚»°°^"8ˆ»—ÃxÏX5)Í9:E] üñL.X£69ÿz|ŒJ°ÜWÓë‚…ì1º† ûid²kÑ®VÇ4››œÌ³Ó‹Ë;%rçØïÈ5”8ÓÚA„
+n„õ!^5·(h
+¦8ã|)ñ’r(nùVDIùRÔá èM%é+
+*™ŒCÁã³1ýÈXÆ…“Pa… ¥$Ù˜ÅO£¼•‰«9¬¶¨Uãnz<ߪªu¨c1¿úD݉eÂéðuÀèR0š~«ícvv|ë{Iߣ%ðÀú³ÕktZvÄÜ×Qoœéê_2fSé4¥ymàØ~®,|
+ ´Ç/µUÉíÜ[uÂë A÷|)ñ¤ë¸m ´Æ§uH2¸>tbÆV˜Dr$ˆ‰´
+šHÉ£
+%Ò4+‹À¿ 7q[øÚ‹tõiuZqx8ÑMtͨ\©‚þõ,æ”ûÏ+ý¤œ~b.)’C+ý$.žªii¬õhåJ€žÖcUR~ð…Hû‰N,3mô_wÎVþ–Ќ¹>”ü õß(@
+à¥èl,Uº 4‚µsCtþ>$ÊC[:†æ¥ÈÁ¾HŽ˜†¶¼Dn_rV·©Ô8ãRîƒ×&FE¨
+5Ǭxˆf›.QñLž5É®î@‡?É}ùúâôÌæ¥6ç^UGª¯B|! Kßվèm¦Õ¶×™¤˜
+©Sì¶/žd*שEÔ¤®¶ó“* ˜wϧDϳÔÔ؉!ÜSRO÷î¨#D×}'‘åë©ý”hXàWyÖì%(‡=@ÊOI¼ (.<·=U5tâ£8±á::Êg¢Œo/Šå?ÌNQÍHJ¼N_Ô­DÇѵ9’̼+
+ŽÅã%ýÚÁ¢ÀÜñp8FxÔáE˜ú¤d6‚x&°B€ŸTYð;"ü+ñÌ;Sü‡w$çC´ƒ)R#–ïDT駽 w]Ír-¤D
+4ë½»mA¹¦i¹X…ô“»Y!JðA’—^²Û†ª=ÅJTÃs`½¼+œF–XÒ–ÇÚx¦„]_Ý­v›Œªà
+ÔŠÉšÌжŸi¤ÜeÛ%<†=F‡·^]vËJðÒV{u¼ÀF6> À…«Ê*–qЈU‚–Æ Vê¡DG1è.Ñ#S°^ÇïP¢ÞfW“=;Ê*Ò^Þ%3„J ØG‡Å;]¯ÅïÂÿ0Ÿ]·ä=d>íï(f™fÝéܾ,n™ÇŠ üü¤kK] IYËñqºLC'x ²Õ?é&DEàéF§÷æàèYàÏó×þ©ÅüiæñHƒÊoÿp¯6*R ­â€S‰¡0k4¾¶§ïú <¥UžÐ"pÄÿà¢8y¶tȦv¯@mÄî1Œƒk¬¶á¯jY+?žd0P¬’Úm*A,(
+æôÐ?í&Öw[Z°£Cø
+–¬nþ=¢}ÊÐ(ñÙâ']§}J t}݈âÆmÀ¡Ò¹DçÓCÉ7ü‰)ÃfÊÈ­
+Ø×üÄ”‡¢‚L°ÿ­VG²ÊkÂzÍ^—_èÀJº€Æ@ž†f¬›O>æyâ²ÐA³£˜G‹œDfɽîï(B• 8äR¦`¼¥"²[x$üBÞ¬#µI±7’º¥/Ói=lÑ3– =|»‘ÑuÇhhCƒíν×ç\·°40†¨Ç×TátdVhbî8oÉûÆaŠÞÍaò¦²kpÜ¿K‰S%±’Ãxú8~G”Áý» •ïñå6ñ.¢!möôð*ù…&.SVÍ‘5!íÁ¿l×8¶˜pCú˜ü<>ŒJ.(JøY/Õeä2Sðd3œCIáG×~
+êªB‹£zvÄzaBR|=
+
+r;YèØÜ
+ñ!lc£ ½ç…tË“,¿Ÿ@$!¥#
+²ÎrCt™¸è¸aïxÓtw{Áh=a+þ
+1uöƒ×àÃac &d“I¬OuÝ–‹uÑ RN“—aggÎû;mc˜àÍS¢h¢§ºh—
+âK„dÂK݃x7$®•cø—€iCÝøtÕöÁ,ñ1‹@( P~öcãÄ¢‡­}Z2³ø6ÂObÀŒ©°ãËõ”C6c=ƒš¸WP£TE NÊ^ç:z4WBž½à[mƒª¥§ W‘Ö 9`ðoJ1Dv°×Ʋ‘az;GUZèê8!V¦aïʃædä€>É—Pž¦ƒIãÍ9Bì®HÞêê“Éèø¹§H§Ñ9AæåÂGyH PÉNVâé(µ¬¬%YÓ7ØwND‘ÚÈAgµ–â.èMÒx ÁJ!Ù\\‹UôM@)ê7îp,Ádz¥”âIãˆÁÝY6w‚ôÝ¿eG@{Š#´=-§žpM! Aº´Š‡h·Ûô#ÀP¯!,¥…Gü'/;Ÿz ‚{ ’ÉÒô期Ké%äu)½á3ä—Ä·}ΡúŠÚ„áKUТÔ_Å”½•Áäï@«õ艗 ò6s¦Js̘ßCž¬ñóÍ£ž‚¾®(ÍQ?< /,QOAŠ³R¬*I‚äW¾6SnOš2<“Õ>[-L–‹L ‚Û~„)PQZ„lÌ#¡·X¼Ë ÖÂåò:ûØS„駼ƒ‚CŽXQå\†Æê³æJK¢(w"AíEΆΎ50aE„Æ/"7[í'9[îBJB™Ùuzkvpþ¾Y5Àðrz‚CÂ4™D ¬QLC74<2ÝÇ*?à5G€êYÄâéXC–„
+¬Z°¤v]ÎÁ0ΓÀ½EÛÐ`+è !)¨u_vŠps žÂ¥†@†Q¿²Ê›²} ‚ñX‚áªíþüó2‚qˆ¬iÃ(ëú&¨ŸE¾µÇùTÑ3é¬õØõ˜IЉår»¯"äÉq @ßt5TÒClß¡Øü¡]¦q_1H§Jj’Q&-í!Ø‘MÜåÅæWði×
+V=„¬Ë Ùþ$±ª¾;x–Olݦžµ@ #jå{ÔDÜmsúöm±
++KgB¶z¹ÊÑKÝœñæ‰gFn8r‡¿4Ê®{FÜl%j©ÞÉqðuõfª]µu!äëáÍà„šBè`AK@,&Âx;&Ê:¹#³ä‘:i¬«‹Ñع–ÿ-øÏ®ð#èëÄÇ( …côòÝ€aøqïŠ"½‰à®¼ƒæêßN·x9ÎrÚFÀÛpø/Ž©É…JZŽü žA¤èoC
+5då’!<Þ®[„ö¨G0†1æ¦ÊknA/Ë…Ý™û%Ö– r‚($¾Ñj‰—/X‰bÖ…ÓÔ©YP…¤F/Ú cµÐ}+8MÏ3Ï ³ÄJl {¦‚öª[g¡ÐPVŵözòÔ¡jf=»ƒTÊûQ ÝÑÈ%Sð·U’—KMB˜¹åf«ÍN6x@¸zaÖJZ´tŽä¥È>fï›y„Q €e'ùŽ¢'l b£
+Ô‚¹¶Hßu2ŠŸÂÅ1 ¾L~Ã%vñY:Å@™µ=ú±Ùo*§)Ì}xG9À¨õÔS’½¹Š–W–«ÝâSb_."lw•;N}›Ž{„t–ÊÆ• ‹O13])ŸÑ\Ý”IpÃÖ°ìœJk‚ aûèŠ8$`·©Ò††ÜÉ`ríñ©ÿ½_Lh2»©h5Úœ´<†y’jþ‹š¸ÝÜ‚ꬫÛ\TE¢«È iÁX¡ÛY<„¯¤È÷
+ ËÚ+šöÏìý\É ¹e]Ûú‘¡)›Ù¦ÞmÛ9à'.Æ1eǧšz>ñƒ9Üpøk̆¼1•ÂÐ&Ú2C qìIò7G›ù0ceL®Ã{ÄECÛ–‡°„±x¡=»Ò¹t˜“„Qh.Œ@är¬mÊØxÎAÐ £Ã*–\ày_êËÖÅ8gSP†¬­ûj8
+a˜’}µ7†³ °­Še¨ç¯kü¯ >‡¹ÑÀx$C÷eAyiÝ¢û×y&_ì=ˆq(&EÖ)ã‘!¼™ÄÒ`ËEÕ.Mw"ùýB²®
+ !Ï$etÔbi ¥÷‘I;‡ MÖb¦"BmƒS2ÿ›r/hØqßÎÉ}Æ.G¾KÊ:F5D+·êjº`2úÚ ©vÚÎSKFq-L2­"qlñ)ö(Ñ'¹­ÝìØ€9p?Éa A:¸)J#1²
+ŒKâ÷d¥¢»Iì<½Zì=ç#L¦KSL:V];ÛƒNyuQ§0Ó‚tTFÖ²pK ˆv›W‡${Ü”GR©yl‹qV‹æ­•SŸì®¼½å«QÒ§hW3 ÍÚ™Š’Î?§ð“¬ä÷P]
+‹ïìd$
+
+Ý–döþû\¾Ç€â†”¨
+Áʨ¨ï覣QN±û«³ø"èåsç¼{»6Ž)ˆ¥;Þl×ùòx¯ì‘)Ö·ELô‹$Å0uÅAôNìh3WhrBKÉG¬b€µÍœáVHŽx ·MFñO)Âv“
+ˆöð À€ÛU¦}‰ý¨îØöFYf¾„p˜G&•!T°†øfÜUw£ ±ÔãÚÈF3éü
+ ®¬ÌX-Ef¸Å”`°îóñóŒáÓ„‚¬8ð
+ˆ"ð¹€Ñ XS;Hñ§3°­ˆsÁS0µŸE2@SÕ’„¤£œ™ãS¶Ùö’£†q‚@r3ÊÉÞÿĸ³($ÄiÇà!á«2Šß…‰£ï0BÊôO‹" <@üCU®®)íÝ1­0<uŒ§Í`…)C•R9䵺mG•ZPL‹N –)È"†g+…CÊØ Ô 7äLª#Áù£ÐÑpj§ ´ÚuÑŒµ{p_Òþpî#3sœÏiŸÚÆ2×ÿý6W©¬jÅÈšfe@ UѳLì Fº€8dFeÌ쯒Ħñ²dÇ­Ä‚HI÷©ÁH‰”ÕŽË€~û8€Ž£^WM™xãíÒÜ@§õ»}îK  %7ë
+rzÉòùƒáƒvNüé z
+]Áõý ï? D#Q‚‚gyÏœMk riµÿ ï$_ÒkUº'Èjád̃Õú›s*7DÞ™Æж#YT/ŠíÕ 9tÅNrYŽƒÛ®Mì²þß@/+öÝnÓØʘ5éí‹„‘*É/&TÊ
+xÉB(N¤a> ˆ¬¬œÄ~Ìê(~tD›땲ݵd¯ñªw3z‹Y%m ÎDUb#-®ÇF0Óãa8’b–EŠÊ…óòÅèÂ÷µ ÇsògÇ¡„Ø—Æ–6Šyg†‹mÊ„±O©Ì$L-­i
+;Þ£Yû®ß‚Zªbç@OQDÒ’»5ŒUkÊ,Õ =Ùs·áW'ÿíã
+8¯ÎÅ!€n‹|
+ /Ú_º‚ÐE^Á…cÙŸz½ ZçÁ‰³x.»=
+H¢ûì vù.µÁTºÂ±ÌÀãTa ÁèµiÕNº@üS—ŽŸÎ¹ÌÍé6—ù;>ê2Å”gRT3—Çy:övWˆ0¿¼têÛsõˆDÔÚ}Óz;»˜Ioøâ
+9JÿõSGÆøý}_<þþˆqV>™—bDzsʯ‰òçP2'ÊD…?Cn‰IÓÀº“B2•û2×2HÄËþ<öYÀÈÛÌ ƒAì’£²Q”r*9^².Y@jB¥\ŽYq¬"1Ê\ BØ-èuîOÿý+d}
+wT–Jòã7ç‚yÈNAD^Þ ÁowæÅÂâÝ@ÞAÉ/ömHšÔ±õ­ŽÁ–Îä¸å-IòR“s^ÆíVLXõ$£÷‡äø^Àã9¯mK KÅ«C3%´`8èrÆý¥×¡ÐÃñ‡Ii¤ÍÕÍÛha‹š
+DUý á“üD3ª}éOc¬‰{â¡¢FÀ F?NŽ, 퉿í(ðn+ÖŽŠ_ÂÚopØÞ0rÿnhd Âöq²ËئQâÌÂj”}õ1'¾û]P‚<”dkèVlxAÖz2»‚4z10y!¿1Íš ,3Øtäó9Œ!ó•S,ú¶ß†²ðFv¥žfþê«Ï3Ïô¢’‘c|ž¬œ<üÖ”?bn¬©OáˆÙ%ŒsJï ²|omö°úà‰c"Ï dR³z•<áÂ;è)WÑ…\ñežòí½Wˆ/FÊVÚÑãù&:Bª0œÃp¿14t®ù0^L–d™¹óW1’˜XmvÛãUøo&.´e'êפšó8Íz\ nR ~r†`‹(7‡ÎöüÒïëÕÁÐ2Ì‘f<E•CŸÄ,[ÁŒ¯¢a­Ë„FcX˜ÍELJ #ƒ'"eßÒõ[üÿˆÎS‰|ÄÌŸüSƒVÀÄ\ÝVÒö‰‘èSìf„€¸Rס>‚õ¤ü|È^(芮Ä%†yh¡–›¸`¾¿ÁàHÏ°>«€bìÔ¹á{ü:ÿg¼ÌÑ#Éu |‚¹ƒN ûbk̾E»ÒýÝùƒ
+ôGå4
+ŒµúÚàÕhKu ¡Lô°l—m )lJqj(ñ”\f»kB*kƒz%g D
+;"qH‡G†¤ˆÉ6óÙ9#ˆIqM% "dqS!ZRºïÊžV¯°É¥¶ Œ
+ÑŽùaJ-ZÞŠÄ¥lhèÓb[J0Ɉ\ÆÕß•œX[ŸâÃŒD$ûMÑõÒ_ÔñÝŠ+ b™ã,Ž}YE¼6î,Ž]b4é*„vÒ=ÜY/þ‰È‚
+b,Ü LyÉT–M/'pñp¨«µ¨ÈÕö§¾EàŸOGž¥Ø42Õê ƒr—ÿ‡‹ «¢$¨EµMÚ—¢U‚3þåÓYD¨Ñ¾ô~j¬{A ÿ­Ó®YÓˆ™b(Á¯Šàq )Åf‘E©Ä]Zݧ)¢±mõ
+%rk·|ˆ ÅÁK'óÉ£ÐçØõ¿fDøµæÏ“ll‡Äª¶ÂÀC”Æ°@^D3ùâ
+è^VI™«]£wo ;% pÔÊs”ÐÌŽÖ’8}Q€ A"]ÖIë*ðµÝâÉöŒˆš…E5‰Ÿ8{Výé ¾÷Û§‰Už%òòÅ8O4ïÐÐüðœi^“– ÍitãÔ+1haZÄ&ò4BˆÓ<€®zëìNóü64mqg$š¬ØD:lvÎRZÎ¥—Fâ= h‘¡ðP‚bîz%h9ÝŠ‚é$‰ÙH6úCщÜx(r¢D­oZmx.z›ß›XåPRô’4YÑ,¿Wó^‹¯ˆEA%“³Ù”äû'É,Yº3·\'¢¨¢¯Ë" ó|Ly]_!5ŲéSA¤ ÍîR^yö†3… kTbèºëK•f5Éå9…Vt÷¤uß‹£¸ÉŸ¡õ!{ C `-Õ=(®Ž—)Š˜6Í[Ñ-¸Xã—E¼‘bYÃÅ¡¨Êðý€Qñ•âbÒš%øè¢v`’½Ëcfw>a…6´Û÷ò¡(
+5GK …­––BJñÞ€{¥[ˆ§ž0¨[Ôb×è°m·åœ½ ›f€åêÙ“¸26Q1,9}i¾bÌèx/##tpÏ8ð{.}[Ʊw93¬wEÁÇÁÔ|xQåQd7´Õ׋_õ
+þÔt‰"X­ƒÔ|ÛÅï…gLÑ'%˜Ù¨¼:'yè¸ë”­6¬G:ÐÀºî8äQº…œÃ9ÊSÌ‚:Âߦc®„8ÝJ¸»ÆŸmÒÀ¡Uv@‹lyªK!tö
+øì4ß⟙,tœŸØØÒOT¹PÈbÇœ8»¦|2t«Dì>±¹ç¹…ØH^‚iTÔÄÖ¸YAÔjJ$K‚¡¡ðVtwÄ4C2r²[e,  ¢)é*cUÃòµHŒ
+*0Àb7Gù/`+ܬˆ¹¤Ì® _"û
+·•Ã5H‹—QEäÃM¬ëÍ™b_€ËèV¢ÀÃÙF·ŒQž²ô!K´@q/ºM\{—1]‰i´3nî%j(®!Hg0 ï§"¹ÔS3ïsó
+Éã!š4¾“9Q艹úωT²ðàYÜi_Àw½o íÉ ëÔ;ÚE€´Dm[}t‰À܈ûÉ‚‰U3G”•0‹ó~5¬øOŽ>$ðöÒ˜;á…aYÜ©×+½$,©Ä2rú3Ï„¢5ž¥ÅC`MÙî[’"äQ5Çp$ûM‰‚“î†Å§Ç|­÷}˜«m¼oºÚレ»‡¯ûõ$_êôë;£Ù
+k¶3€[F€orž÷ûADšÉ42W¯ŒÀ5l¯Â[2‚
+ôÍ–$“äØ‚<é¤
+B+¢×ü:ºñ?ºƒŠ ”žë–vA27Mh¡}ýTv•ÞKw4Y]án˜—–V7cHœ¬¬ç4N«’6YS÷ðßõt¦Yx¤,«g‰~P,xD_|Ú/Ãõ`"ùÜñ4d 2ØVš00<k©±+1mßûཕþóAd¬&G%Öq°~ÄÒb˜>VIž€óËzXí¥d€z¯eS'³öù›ýáØL׋èŸ%Â(«‚÷ä]ÎÑ€v³ÍŠ;kÙ1Ë{½s_51—¸îð1AÍñšâGnç4U…é©Ö-ÉÔehã÷³¹ ‰Ùåí4)E3Sà=Xõ!mn @RÕ¸û†+ÐôÖúo¨¨ÔТéÔ¶iük<„›}høè@f-:kù÷Á-C—ñû\šLgT4åæŽcðø¸m.÷ØX£W
+ZÝ’œU.6F'þüÏ]‘ˆÓ…·Ò¸ìï)ðfž\‡]­ëúÞ4²ø
+ÔV3L¹ÏáïD5ÊÝ óTA’Ы×òï+Òoù†‹2ê) J–•B™·©ÅgüŽÆqD†’{"‚bÏ« ( jBkÃÇ3€æ+ø|J.8ê9_aã°
+}à{/„Ž*('+8 J|Ú©ˆ…ƒ¥¦E½›K[¶Óni¶zˆGéžù¢Ù¤üý¤¡\¦?³ÙSÝmüÖéqŽ+F$¸œÄÅ
+~}g¬6Vƒ.År 8²l”¶mdžPÏܼscGJ!0ß–\nD‚Óa»ÂÝïHØüÖÄ> Q¹©}ògÎ1ôðœÁ*ëɇ˒d¹|ʸñ]ÍÌi˜,•Ã˜Ž·Ä!ÇKt££$üÓBŽ Š‹ŽHWò¦bOèˆHŸfâ]t¼ qm%$B²¢Ñqéò×j  Pæ*}z=ÑI`¬ùæ¢#’,>
+oGÇ*·Â¨¸±>Îå|EG$Ék!PŸæ¢£$adÖøøt¼DNɉQx“,…Eõ=‰‡ŽÿÐ?èX³VT†žLš#(׃ߞ墈9˜€$;¢)IºF°)¢zÐ
+ØaÝÙ¥0‘D°}Œ¬kÚ¯\å*Hù dêéÉ‹/µ£Eª½¬Ç@à­ºŒÏ'¤±zÐJœ’†Ap¡”ò
+ÝÅ~VNã0iUá'Õ¸Ž|6×ßì½_EÄ©Ey³ž´Ð€«ªh²êÉÆ »±Æê÷ß¿úøçx,=èmäkÆv»7l®±wÆ!„Vdˆ|W] M¬àϤVua6 ' ‹— À¡¬9aÔú´;÷ ppñ}‹è~Y Gœ
+†›T›df׋å기Ü|Iœe0Í 7y^u‰²L·c*1ÅõœžO¨ÃÖ‘AŸ¤xUä¤c8÷«÷³!Ö„RFŒxôk"„ü¤ŸÍOÓŠÌ Ö3Y˜=‹Ÿ‡¸$Œ'ÔKô$>l›L“ÞC6OòäL_DÿóDÚ9¬…ȇãýxÓ%¢µ…|Ç>‘'
+s*np¼Ëp>ŠÉTijɮܨ‚C­†å@~O!a˜‰UïÆFõŒ°«Î7½çFD‰U"ö®%»¹IÌ,2.p'µ+7z}~åÆKäÔ» ¯dA´Sûž$)ùŠ‰Ya!Å}œ¯šÏïŒæž`ü„‚Åtø˜觢pð{‰ ¥¢­ÒÌM &Æ%$Ñ]ëB‚­‘îÚ ÖÉL´:[ø_åª,SM&'ÍûM˜8 ÿàsôSŒcƒPŸc¤ðÙ_Ö4¶KÏŠRKÀ2nJyQ½>‹eà”Ûh‚æˆ>·ˆÕ…’õ$X3KJ|ÅzãÁ=@$æ[6†Á‚ÄÛ†þÊa:t™½>œ‹cÚèÕ-bÄxtçisI늛¨• 9UxË^5¯|Q´:a>¦|ßÏý c«Š6[!¶ÁŒqK1$ê‡ìó2ôb€NYÈPÈz"þÁ¤õ+sŸ°§áÿ1%°râ—÷rB®/Áßé$žÃÜ®z^¢ÿ3^&Éqä0=ï (8k{ÙGÑý×ý>V¨2™¶Ü GË“ð§@Üá.tO”bó<ñhÆĵ‹_çýÆË•a!zFÑO/¿*ˆ÷ø­Kó
+þ ƃ|¦pмë4šWe¡[©ÙÎ"†žBtãÆ¡)vM"_QÐ=gvΦ µ¯qßPm:¨‘ØÎêpÅËÝcßqwQ<ç~O¢H /4”·9#+²à÷Ÿ·vnìÉÌ[À·æy2Q¼PÒQÕà$lò—K^ ˜p)žßañ™fz¯KÒ¹Ïò˜(
+D–FÉî|Aqâ÷pÞe[Mf&¿Jwz´Ö¡ÁܯÂ/¨(½.[ëW†žœžE€N¢ØÈjO·\¾%´“[¥Oë_Osš·ÐKt„åàÜË×¹O^XÎÒ•ñì¾,ç,R¡á¬ßIXU¦lSR+E¢Dˆr¶ % J¤ÛÏ湬bÉÒ@£k
+PwÁÕØòa(Æ-Ó½iFßv”ÆĹ$®!4á†>î/ÝŠ²w@*ôÕÎpªìR´Cç`a,Å›ÓÞpÿRþnq.রX ¶¿º·òÌÐÝú6µ—YÄXŒZš²7«xb¨Éf±UeáKTӡ䉙ފþ;Ip&.˜‡Ã¦§"tW性û…*î0‚.‘t¥ÁÙ‚œ•”¾¢ýØ1Q3o€Ýò^c ¿^F[°ÅcJ€·Bà 4Òá9KˆK ô†;ÅŸùK&tç§sH¤
+yÐÓ¾L&!è‚ÑÙ ÛR'”œŠ_
+B)Å%¢mzCyf;$\œ»Š¬÷˜
+H‰Œ—A’\7DO ;ô¦‚ XËKßB³’ᅦOþ©Šeu8ÂaWç'A ‘Htí=G|üýMDí!îÙzºóÓøË£OÉ4]çøø¹@jçiKŠGjhL±æÄÒ‡Krx,ˆóEHälž ’üË"ƒ[uÕ|4ɘáÚÅÏç̇´èÙ½7× É·îM6„WIïæ²£ µ˜Sfýõ¾ê ”1£Fd’žÿ~“¿
+©ÆÓz­÷k{R›mê³üó$á3[4+¬þ ÍF^3l¬Ãœ ºò‘,H éÃ÷ã’«²‰
+¹÷X‘÷unèê~G>º§ÖW¾Î±¦ê¹!”ÓÆhM¢é-ªŽ|$Èu•<ÂGN3ãðó9ò˜„«.fºóh#rt²ÉÇ 2Œð%FÚ~UV G…ññýÛÄNðÞÃdz_T|¾ŒWÿ¥ÝacÌ2÷6RªcATÕ¸¾òÑzz׌bë ±“lpªéèïŽqXTxýŠÐÂ7‹©Ó¦Øl\Ó¤u^+”ªìk2ªR¼Åz5qÁ¢ ô:æ…YRÅ&ÐOº¿4z¡w™Ä» ÿ'ãÛÍxB„Q¤žvYçQrÚFæÍøP£Ó¿"+.ó42ÖÛÜI‚Û|Ö&qŒA&T€f 1hlZÝ‘Ké <mWÝ–˜¤Äî­s‚ƒ.ûœ¤&r⺠J»Á“áÑMø„a6 8S¯¤!›m²ƒéÓ+^ò*›ïÃï¬Û6w&ÿɘm|ò7³¶ú¯ž $9F´¾Ô¹ñ¨PŒs¾éŽì@±Þ‰Òæ¥ý¾‚a$:¨æ×/w÷ÁxiÅ…­«¨Ïœ)ƒVþÈkVt; øsŽƒà¹ž‡sžYq%ˆl£3!ì@®zU1)Ú»Ýäú£¥_ÕúÆCöMOLo5¦T:Ú3ü bÍ9Üø¼èß›êš8ä®è¤„hmæªÅ(–’4î?GŽ3fÿe¸óêªôEû:…'áFíEè庯€JÊÞ"FsÆÓE¡WšØŠRs}ö± ÉOàGE£ ¼¡ìŸ=ØHÍ&GÅ¢På:3„àEçâŽ\Ç$ƒ“’x±aõ)uE‘“QOzˆ¬ñÈô< ~¬ŠõjŸ˜c¾;†“èr|ŸÃ|²A£0-?…¨pQ•˜ R}‰Æ ô‹"üÜѲïظ¶E˜1Y¢6ö£ÈÃÀ˜ÀÏ£ÊUò¼®€âXb¼á9ÞäÝ9£S(@{íh¤Ú‹ µË­©߈mÈ„OCꤳí¾JF‰tò¼ç"Ë´åe}ƒ.4’ÃöèJ(wt4ÃçòÄÐïß #×çCLçÏ°/ƒNý÷rÝ—@Ošpl­gÐÖå|,òÖÝþ³A†ïϘö7ã ª“ÃÔî½à÷q
+Z ÞÙ­=#ž[ïçWúóÿ‹iÇ@
+þýs…ŠòCUÊ(§Ù¼¹Á3éLþšzàU1€RlÛ‰j¬½è”Ö
+òŠëXãÙ5.åc:ÛkB*ôn,“ô
+♬H$v:ù»jýÎÄŠ¸ù`~H9´ÅùJ©Öª5wĘªbž›¿ÉÝ¿1ú0%é¿z&'Cµót{©üiJÂDè‘L‚Ó(]}ÁåjºP‘bŒè\ÑàÈù¢ ˜Ù&—ÿC—Ì­¼eqQü£Ç½5ý*Ïdð o”ð^)“]õ/׶!ƒì£©]),É5+V»¿€^ö¦ƒl| ƒfN•µ­¾¯«”oýZKåÈR˜ý¦ “/_&¢mk…³
+¿ „oê›GçGK›ùA=*R-÷ã¢óTçÕ.…¯ õbSæy2‡¼1Ã4kÛÝ`I˃ž!wW¡æîî}¬BQáØO;Š°$95•èËA=¬eÿµíj*Ö@òf´Ã#Ê܆OÇ}G‰
+¼ýçÿû«]çÒ©@ùøš>Žœ¡*GqZÏ.õÔЃ%OdkèÊ/¾ƒëánb~äÝêøŸ†'‰Lƒ)LQ,ó«Ò3*HuöQ’õ’¡Cg9Öñ¢Ú\£Óá+¬Uêe ï¼Ù0Ä,å>G ã;ˆÕÏ;è’!¿^€x´¶‚LÙ÷ +϶åI{£ŸÞ-½æ1î âr÷Ïú-½Æ(ÁUü²>]¸ëì­›'½ÖT°RÔ^éµvf…©Ê ý6Úuµ"ŸÑ5¡lñôWÅŽOXý ÏmJøóð'sD¼a@÷S}6·iT“*&ßàËæ…X‰˜‚—BÅöz^vøòõävp¹Œ¡)"SÎ(? èO²&Xê4½¡ìxB19N̤žó§•eÉv•ÙV(5â(ýé 86>eßil*ƒÑGõê 5¹+fr«cC/?
+‹†uÈaÆzþýK¢ÀÁÖ>ír‰;ÊÓ£A¨2ìʾ 6}ÌNÌíÐ’O©˜½I ‹›÷Ao¡ö,t"€{‡zlB,žbƒÈÒ#W«_ì]“aëy±ÃXÅ”D(­Ùz@jaD ìã‡q]n]ä
+ÇËÒ¼ 9Æ $Â`A2ÕHºÏ‚ ðSƼøâ ô
+ëA Ò‡ô
+ùÙG•ÄJ“†šbAp-œEÅQ<Àƒ¸nÚ'"#}ïâpdPEOöEGÆwœ¶
+rx¹67ÐioǽºÂq·® '¬¥†•±Éæ^.~;ŸÒNb?(ü:0)%RÝXK*g…O5+×­é;)³ IãoñçYí'`i„Ødtòü,“Ï}2¬ìʜًdûrw$B}•mFÁ¸’×V„ýüu]“‘Ž"éQß {ô7!AÅbY2ý©Õ
+xÉH’Ûè¤NÚ«à‰Vc‘u76ŠB­~2 º!è,Mrv–rZQéwQ|äGyÁVôI…R=6‚™Æ.!Žr%Å \4äÁáý€ømSA¤z›¯>ÃåÙgÆÄ*¸,h­+n‚ô¾ÈăCM2|5Õ´OŠJuµ•Üvm²\&Ûoßù-öj_†çÊŸå ìa£Žiˆ“?å`æ?Ý1‡~GÒß¡w!×Åûzg;×/Ã?páµQT¬ïSºÿN<ZäÁ_'Ü´Š¯mý
+¢EÚ\_@`
+ àGÑc4Žg=y Ø©Îˬíµ„E™÷â€Æ¨ŠzêiUâ©ÄÈðÌçd$%BóßþÎT_J4†-dE'0
+ÛÄ™19Ã^ѵ/Xð¿Øôs9ëAÈã*4‘dãô4(§eÉ¿_€Z§{Üœ)_Ç‘à´%­Ñ±ì3X!ÙŽ/˜k»€D‘>Á’5HaMð…Œ{ô S¾eAyVI>˹Ja²,È"o2Æï1¥Á@#ý“‰3vª²ð}½×øÝ"Ç6ÑŸ·£(Ð}ÑÀ;rQ,C§9q Xá'Q…gÆÿ3^&ÉqÜ@=ïÀ00%†µ½ä-´¥î¿õû@¢©îB‘R8¡V¦Ì?­’®i¼‘Jm•p.`²—0pEž"*äÍÊ;˜!0Ê'd󓸗¾™ˆ)“¼* Eã„}FNJ0YeI”ï$^g’ñyÝöN…7Itð¢„Gµ¯urãRYŒ›Ê ¬ç{-™¿ãåð¤LïÞêRôä!Öi††¶Hµ\ü#O"w•4ÉxPyŠYZ 7[±·bövƒÙÅÙdu|fFQ˜Ý’½We±!3uÒš=$¶&K“n 4d^>ËSxø£K ¥$í¾J¦`sDÈo…$×ÀW{+
+Z9}Þq~â‰ûx¬qhºvn1ÁE$n~X’‚Œ 9e›Ê×üCØ<<à-S" /ñ<3
+Þ´2a){JgSyéäK‰ï„¾uÍ~}<ïe(2 •éûhšÏ—ÕOÃýàa¸¶ûVe4ü6šööV g
+U ûæŽd@‡_à ‚b^ö‹³b…ý:¹Ý”pѵ)·<¶z*zéÜ\Ê"•@tÐ/è¹'\ÌP7¿xäýËÂNHž©
+c¸·Â< À@Ìr¢H²ûц\ÝZ§(ÿ)Ív§-µðƒßªáwqÚ)™XSÁ/öÅùq(ï–ÞƒoH0P:Ôä€J¥‘?
+WÃð<YsHU Ú­.㜫IKŸsâE€óE’{Ÿçr
+$êXµ7Æ^&n&Ï¥,LlË+æCѧE9y–þ2ÏŠQA€ÙN¡“
+xsŸ‰=ãP¨¹˜§¹·±gâÏ8ùxå†ÌËEº]ÅÃbC utc|ph4+îÇyñÅ×v^í5, 3uâ@ÚÆøuÛ¸s²‡WÕ•ëĸ[:Ì’€ÑóÎJOáÑ=¢|Ï3
+@ÃC¼ÕyÏYiß­QN²¯Œ 6nôkÍÇM €¢ÃÙ¦ðz
+#™
+†¶NsÕ„#HÈêüáZ¢NP
+¼áí:¸‰Æy5›à&AK½$54,JYËÆpDëL|µøöR$_ŽÜ£Š8Â^ëïP’ð”ìïJ`&‚Õ˜Š
+Z™ƒWÏë^¸Èæ¾Oc 6)7cW‰að$xéqï¥7%¶‹×¢Wûüç°™“ó—"q˜&ãrä+{_®~R=¡HË
+ÿ?‡)Jð6 bç­'Ž_ýäFÔÃ[Ú$µ„$–Z;15ÒÍFzsåùX%0N \Ìá‘ÇZ%x¢DÌ“Îûp=š‘á‘vì¾ã‡¦òãuDì`~ßUe®!º›8¤¤Òe\#À÷~åÞ&G`éV…¦)ǯ*\ ªÁ÷¶ÏÍ÷ä\ÒAt>lâsD›:ÖCà `¡Ûå(L”Ð?ô™ÿoV}*ñ¶’/NCˆÐ3;ü¹9Íe˜_nužø¸’´Íл¶Ø¹¼£¼ÓGc¯ÿ¶èÈó6m~(9~STø“8j¯‹¾Qh¨ MnYy±èzÆŠk†¢ÒÑ€¯v@Ö)›\Þ?ð5Þ=/Ãl0QX
+pÅø¦à“
+#í(n Û«&š
+ó3‹m­;Aórç>ýÔï¿:NçK`¢#õ@T>¦4!¡È'/¾t&yëœæµ ð(©Œ¹(«•á,^pRÆßÇšjŠxF²… ANõ¼q•)—ÌÔTÝÒã¯Áo®…'šSx*aE\eC¶ÊrÐ×"t¬óÃàµÎòó¦èyç‰áS¬Õ
+ƒÓЋDQõXýÄàO¸ ù@‡Šç>Ð!}€ú£ž"ÝðØ¥õ':dÈzB
+ìˆÛ0ÜMuˆfÁP/™Ñ¿ÙpÃÁ¼D… Òèž þ•ô†Ž xˆA ½8íRÍô‚òÚÎ6SwQN¸±«ñ=cl@Z)#Ý­CA@éñ^‡ÁAã\˜A à8Gë[5™(~N8JÑŒá€ÊZF¡öó·áÁ -¢;Íà«Ý÷Á d20Ó¾S  e+ÞMB_›Ž°M¸Ü@eÆä—–£ }&ÁŸÈT¼;é€2wÝtðg`üí5ð ˜6&Ô‘ Ç6&§€GÔRÃ4ìE2Ž ÌyÊ«ÓAÌ"æôt(™„ÛÙ[)"iÆîÖIJÈîX“ü^—Bz žZw€bcú(òðæ„ûZÄótf¬¥Æÿ3^&ÉuäH=AÝ¡N@Ã<¬µå-´¥î¿­ç@€,fFŠŸ‹6k•$šb<Ï­Ç:ãðÄ  úT§CL¤y¶¿€®›æˆÄL ­s
+” 6Yo ÀÀ (²4÷}cˆ¿/Bq½c>ìjèkP¯Íh¾c¤Æ˜Š…&ÉX7¢#õDä2V»‚!ðÀSo†ÄØçBªAY÷Õh*!Ž "Íó !ÙëhÃjìÙ< WÃP–´_Áðön –)ŸOÝ@Ì‘öLV©ÅÖ¡Îrlåœcl¨Á@“¶“híÄÔù+ÍÉzö)¼§*$2‡8êIlÙÞ“ ²
+Ü€AªxHÅQm0£LÉA /MncðŒ˜Éá»Õ`äj ÂnІb_ÌíÊ/ùŒÖظ!"õdüƒç]‡? ‡×ÿ>­³>Eš B©CÒŠ
+ñ'ô±êS¶‹Æu§–˜äßý¥Ì£c ÎSyF!ú=ÆùMÞô7OàB98I­û¸^¡ip¸Èó©(“ÇU´?ŽŽt‹<•ˆ   23ç>ï˜8A¯gÐyÅÅîþ5ÞVFƆвsê§ÄŽLoŒû¡þ+r¥´šJÆLRæÁ§ƒxR¦o w$CFB¢Âø°Ðã:”Θ d1©,W¦v…Åw.¥¡Ù¹M£”fôèÝAo8ädHZþ¤qjUÍ!FKYj¡±fÚìè =HjRn­•”ò”¢HNž±ÅTK.þ2…SGiºÏ^ˆ7‰_È·èèOÅ´Ù*ä,&ŒvS­Úh^p T9zR ê‰Ò´"£8
+2 t(k°ôÊÕ!—D«q>Åè¯Ò‘œXeŸê¤m bžéD™¤¬…ÀÄOeÃqJ…¶']2SÕþÐ,¶×½¶{*G –˸Ë0—ìl¶ *Æ°G5Þ5-í-Jüù˜íj#†Y·slº½åDÕDf>yƒ>b’ØýÜæÑ°W v…J¡àMƲ¯à:ÙÒbe(yH›NÞ¾‚V
+]ï@ô‹›77þ:\”#’}Œ
+ ò‘ÜÚ yâ?2â›Ô·Ú ýbÿ©(øµ·6~Æ+’ïCók/’Y'.Í­½äV{=Ð¥öj7YK)êÅ­½œ*ð˦—›OµWGGÂ&I\ñë½@’HB
+¼Ù‡ø°ˆ="ιŽC¤–Ñ8lMçCè LãêÏõ5Q
+r^<)Æ3°¯Ô× ´BÌ¥Vƒe‹Ûv¾c>^™NbÂXÝ<íÕ)¡\Óy«ÚÇÈT+½ º˜Û»û¹W@×þøá‚è?X4‚#»·
+›¿÷§Hå\o#€Ó'Ū1÷2ÐæaÈã¡!QóR15!;ûRÏb4^ÚÓ:xþÌœz“x’Ý%®Å ß_bU:È‚ÿê®7¥ÐÕ*¢+aDÁðÔ2nf¦Da;•Ò}¤ÓÌé—nüÕ3‰^ﱃãG„|Õ˜ø´N:!úSú)GU_Ö•®ÐÞðU̘vÇT‹ÙNJ°rD¿H…ÈFŠÍö)Ü’„Á»ä´—i•
+‚gµcqä Ç[‰Õƒ\(úëä’=¬`¤:Çë o
+‚°bC!:*Ìo¬Â‡âò€õ²…ÌËX8Âm ¼B'´®X ÄÏÂ*B@˜+lâ•[Ú$ñçž–Ÿª³Î‰Àr®ÒÆù] { øž¾©Ê”'™­S5,p—lÜ­o÷"ôÈKÿ¤3ÈC¯Y aþá¯n+o›$2äª“Ï jhãY/­ê Aþª™¶òš AHÀ‘p¶[À”ˆÎ²£ž/åõiún¶í$8@’EûV‘„rÇÄq
+[‡†Šö½Nò +ÕŒ¤Ú“‘ÝÏO]A—
+
+X²SaîSÚØ»A˜b5Ø„Ê÷ó)…ÄÉ`†0O­hô…šQ.{rAEÈbqã%í…‹)±õ‡˜*jfpØí¯Ã8 „$¤4ÏŒ’ù"4hcä6ds¨øãe’$ÉCÑèq‚4Îú´Ô-´Íºÿ¶ß'Á…;¼+ÛÚÚZ)>þPׯz·HQ'!²ÆøÇÓ–552@\Ö‘p Ç‘EO‹%{³+{L%|ºá,P*
+Ýx¥©¦W8EßE<‡º<Î’“©(°ÍÏTldeà‚^íÆ!¡±-½ÍÚÍô©Å1$¹E;Fªšƒ¶!ÖŽiIVùíuñòYž0’Ýi^JìS,.›O³ÆÓ1¨2ÈŸ<ü¸°> —\Ð.#¸¶f{É/"sƒ~½¿„m‰ £ÙË!$èŒNÛò€Å
+Xñ± kq'¿‚kH>ñ?ý½ 5Ú^úŸê²&Æ%¼™…çƒ-8PeO: ÕíÕì×ä7”:Ùæ¤XÄÎsä£>4dŸ³èvžÝhK£Äf•¹ó#%pË _r¼q¨ ѹá!ý¾™X#™Ý8”`ƒ‹ WB¯î¢¨MÖA±•oµ³tM„¤¤L:À)ÐD´úYoÖ…R¢‰þ
+(üTÆÀ6Š~C.¬·IêG»hz®\Âkéý¥Ï"ŠÀÚ j³¤Ž] J™ ª}Tì.U6µÃàé¨3Öo"ánAÄÑë±ð àݹ¼<Y½y3í“4j”<ž 5â¹ÿ¨šïB~1Ø帺
+ys#f+z„ovè»}[‘ÌyWíf“:@"ϱ2gw£<)Wì'̘& už­Ã* …I„º!ÌÉ¥tVä¿ãw9©ž‘'\iÅèCvÕ¶®ŠïuÌý” â­ûÃ4?JìS©­¡VÒÓ9Æe£ÖUôè¶öÜ(¿+paýëxÈ_ZqTTöóô€] ±åå»L@;q¾ ©Ô‡’·úk›Úü5µáÂiŒŽ÷ýí9V»”¯e˜X?/rìÿýs?)ºF’o·èŽ{Jä‹b׃­Û¬,!û°º]¾B$b8EåS£¨cACJ‹
+hŸˆ‚CÚüâMYî‚$·°úÍâbæ1\s,. éoÝ*ØÙÀ… 8«
+——¨¨ÖÈ~Þ%l
+dЫæ”ا„)H‚°ŸÎÁÌDÉc~º 6yÈò÷µÉ¯R¤’.Ãnnsâ—ô[ž«ßa§äcRö¥[Q#Ñ) e|÷Ë» Æ J“½/–Õn’w#¨É¡öt¾télmÀêÊ©§ñò:L‰ÂIAÿë6Ý·I]JìS—‰{ç\ps¿Í Σn(¦}4Î4|Wyù»@»¡NÌY ù¡äcR¿Îêñê©á2ç¼p ý‘øuÉ·’¼—1®Ÿº}ÿù>›/2~ ­QL½8'ý¶"%¶ÖaèM‡k0 ·ù)ËÕ94mšx ù jb”0…Ê/8[cœw²_¡K³s_1;‰Žz%š*E(?N{V³ Ɉqt[Þt ±ð]˜Ù®@¼¥µJrÆñ¤Aý#~±ì/ §ÉÖ1ŒòtŽB@¦­þ]è`ÁMm¬ÿ¦`¢Ƕ4Ýs(ÉÊ*S׶)äÀI
+%9r¦ôz4gà«„˜Ú³,ÍÛ8˜ðK&”•)œs˜]¿@;Ñ>%7Sq¡.ÇHIUŒÊë‘ûQ„:9
+ܦ\Yöé3rú¦k `#oAíS²4¨öÖüs2ù±a±36ãÚó²4°7y¯"±aY:7NÑãÿUÒÁqr¼ÅèÂí*·;v¶¿—ëÊí÷¢;ÈH~¤ËÌ}üGL¿Äãök‘Ãí” Ó]ÇwŸÚ 5Øj ³–ñÄ튡)T0š{ò¹9Tunìq¯V:´'ó„
+’˜J˜×z:‡û3CŸÛ¯ŠÀŠuÈçU7r
+Z á`6ñ»=;Æ–¢FßÖàïEA$CsÀÛ¾Fæ±lyÁ%Ǽ?¦o/é¾G£$e
+ÚA
+­<~9‰´ÈL`%íÌ1º¡\fóBH°ËXD^¼¯]¾FÉ稽ÞJD+û¹ ¸_ Mæ±B
+~Öœ’o+Ü®ùˆzkXX¢WŸ îCºCAȧÿîŠj2 >„ßÝ%• {±ÇÈèy7î‰äcÖb–„õÓLc´ÓÞJçÓ¬>NiÞñN
+èriux8'i”ŸSAŸðò±aç.¡W“ÈìUx&å‘¡·?¥G$È W ñȃ¹¦™€e‡òx~´Y±Fq¨£œþPj…>Äÿc¼Ì±ã¼±(¼î¡b<˜‡°2íè8£Bï¿¿‹÷PTÕjÑv`Q—ø7Ü«òãíz"¹Ï ^MŸ¸vñë<ÞX„Û2OmË™œ^.V\k®õêuù±‚
+²²Œc»J$r"óÁw¡”«¼ðƒ—vž|e~‡ç#Eäìx>‡É©Ü¾ÄÖwŠìF „71¡b”»©BÁø [œîC*^gjGòaÜbÏbAgæ5õ"VóD›°ªn•Žd¬€±w †5ôb‡ÙDäFÁä}¾
+ƺ¡!“ðõ뺤Z>(“)ʈíÛ ¨ÏÊ´2 Ôõãø¹ï€Tì2q^Ø56|5í
+¢Ü¡ã
+Ñ-TåfT;¢Ò~1&Œ*#ëNlV×L­H¸Ë.­žÁßsGt¿ö-µ‰OT±˜2U ’KîŽÀGd ?]Û.sL
+úÃàäå2 Ilø£È|Ñ'Ô!Oúãí
+ßÆ–ïú±ožá¸WÏ 3ð±Ë€2w¼ºl;É*$¬ó4r9€žL– ù˜x`3²poóÇ(³c$ŽNŽìÜKA0¶‘Fïk'‹hMµî-É•‘ϨU]F6’¦àl3â4ÏVÁ´rÈ‹æTùÞIÉÚxq
+í®¿ŠXŠ³ãÜäv2èÎÜw«pÝUªÛa:‰NÖŒêzËùÔYTŸ£‚„c¸ðâãät÷
+…Öpr“Dœ\¢ø^i_º€ph;G€ð]’„±>™N¸ý› "¬Q¦Ñ)¤ÀãxàÜÚàHñ}¸sH¡‰ I¥î¦BÐïÎåvÔ«'kK˜à¦¼ðvLÀF”ý¥çcK ±wÙå´:s3²C¤þZÛä®·by‡ZǦÜe*b"¢xÐÝ3Óòâ';&9yd¸•sf¸@°, }Ä°
+Ù˜‘Wĉq­@ŸjdQÙƸ±pª•Ù«‹”
+CÏZ7D^˜}(n‚,9ˆ 9»Â([é^"J}¤Iœdç$[•B6‡ð*mA&„1¤ðjÊÈúT¦dhãŒE<Ÿ“™[éØÓœo$H¬‹XùÕ«2l‹_QùâX¼iˆsvöx®ðòЩý¥gü¡(+‹½?õxäb.>œÅ}ÔåQ@&JÒÓþÒSm`Ö*Ï9K ¤·S…ù2ìg5I¼tê âCñÔñÓ9Oss½ÍeþºL1å£xT¦aËËí¼ ¸%hŸ]C~yèÔ×êÅ ‘.-n)ÊÈ8ï¢ê¿¼h/ Q¶>ü†ø8 ä¬É†xìíãô¡gÐçŸoóaW&ÌÁ3]›œâðßÄ´ˆY°K£sžW|Ìù
+Uë’áÖ¿QÛFmyè²1w~Â|~ç]zþ_ÿ} ·ÿüóö׿ož…ìå"¯—ûu‚Èþ“’JÀŽ®»¥¸\o¬üV ã›k‡Ÿú&H¾|H–ÙUâb 9díÄ‚àܨ¸‹Î)‰#ˆ?y¤ðIR‰éZóŸö%ô ílÊ
+†np²È¥¶dAfñê­ø"aq0|”'®ÅwVoäd¯ˆõ!,é
+Pôò€Yœ;9·~G`|åY0ëÑ $ÜŠ £ƒwœúÉ0ËÖBÈÌ(z`Æþ2eòFÜÇ™žE@3*f¿¬Ê.â&¶P'T f#:á/Z<@üá nÍ„‹Ú^ƒíQLKq«WTøƒNX¨Wh3K¿H:c¿üºÎ/‡GRpªß]6âú±?C·ó8è¾»ý­¤Ñ8¯)Y’ªÔFÙ£II´ëž[ð3;í ôñÄìW¥AƒÝëzÌ£‚`î¹%¿
+î²u8DA-"ÅkÄë&æ>qMÌ÷Ƶ „oé“f”"êÇkTÑ.j—Z/€$”5å¾—¿ÿiõÃÖ9™Àó܈[ðmÛò¹-ƒÚ¹È0HÎÿâ GÏatX¿2bÜß¡#!†îUé2t¨…°c’Š"—lA‰ÚI7 ¨.}£ÛÒî°cÁØY²O9¼_‚žh”®ÛO)ê">Ù¥$®=Dº—ôºfZÐNÒ*ƒ"¸g,³m; Lôiò!ÓÍBÔ_“';÷ÊÜÀ,Ä{DÇÌ°%ÒÇj¥‚¬¶¶ý
+
+,m£W¬2¦Òæø
+ 69pZÃÍâ4ûXZ-Hm:sš Òø+Œ)C]“õóŠ"˜N”«tò’Þá¥á–ó
+ ðy¬PÉ)bÉI­TgÉÀ%ßÇJ6*í^/‰nË};íÓ@¹I=4™Ù
+h¾ÒÒ™É
+=LÏæ|¤$GÐ¥ Ї@ ôS¹ŸÅ̪Aa±T
+¦îlƒßßöqÕ¼îÌì7T6f'D{‘·Üª= 1±`R=
+Û =1UYj–v†òÔÄimꜿzjƒ¤¡úR=Ž
+!‰
+ë^xR"ú ~
+åוL›öi{â$êªSªô‘RëÎSey #pQª~‹)®*ÊE‡åòŽ*«t DÃçå UÖG“4ŠSnÁ–¢­YÑy„ÐQ ugSú6„X~÷ªî¡gGWJ‘n¡è´üöM(¦bhØú$ëç­•äŒð,ÐÙ ‰3˜¶#<šøR¢Ñ²ApJY„ð5ûˆl·I@ƒEåAøÅA¬eØkÑ0ÝΙ’Lô-ëLľ´v¢š¡ÐŒlÒçä\U1¼™ ”j|LÕè‹0jÆB®¡¬\ym2kCB–6sœš„Ö㨲®hyNq
+úâ쉼ÈòÞñ¤BݽÒò¡À­!÷`ì4cSôó³R8ó7¥îù¬„¦*¨ú³N8=ÈjAÜæHL
+‘®â§ƒà ÍV)õrEéǸ‚9-Ø,Ðνç; l öi;4Ù MûBž1W
+FÌÜÃu~a“d.Jô¾@h¬CÐÄaÐuj´=Šâˆß½2‡Ò/Üò¡ç "†á%Œ×x zNg¸.SZžÞS˜b’Jc1*ë:çR:‡dŒ8¥II—¯Ö hB®´‹£†”õ£O² ;U}©0ÔOpŸnÀÈvë³m;)“NhèZYŸ‹Wбçìe„Õþ.HÇAÑã’ÖŒŒÑà|›½ÅIÓ¾„·ŸË|ñ!…ˆÑ-ÍÇ-¾8j}(ȇ¶_ zÈ_mOÆc ì
+c%á¯#"ˆ*Ù锂Ýo cyH¡Ldn•Ï¯ï‚^™ùûúþú[½€¡†ìöÜÒX…¾vĉ×ÐüŒ
+Ú „K`ö|Ë?6¬O óXA
+|qµ€°ÏÐ&9äLjI“eð¼uI+—fd°^í¼(ˆEÄæçè;ʃÏV¦Èó€YåÕÒÄ2û¬¹ê\réÇh¹í  ÆSbx:â(a±0lÈu\‡°€²Bxh¿gݸ.mr¦|Ðw’£7âÁæÀ™L<VcïÆ„}"DVyüï¡ê† ædÛÊÔp–û0]˜Û6ÊA¢8„¤8
+Yø`
+H‰Ò÷wVÐ÷u6PprqVà*ä2P036P°04PÐ1ŠR¹Âò€âúîÁ
+éÅ@ù}·\—|®@.W_ ¦@.€
+8;Z,'4.>1P%!M&K+3#%BQUs'$E0Y0B0&\W^Q'U_e6G+lVS/qL]DoKd+#,B3l$)2#h
+WO$l_LsNPA]VJhAao?t6jF+JPF'VPY"=1*FOLRDK7:]\)gY6A5L[iQ.4=erIAU-IU
+s02KkN?e>G(g0)U(&q?aUtE*5Z-D!QD+#6GHTL.`pUUN4fK=Ftn+F*$[eHZ3&F;hY
+!_r)C8*3Y$[bn:/qKQj]YQRNaB(dqm(uHjq,<G*OT`cmS(YH%,O$nqaB[#>!.G45$
+%'@a;dFr'sBZ<,pa:tIrqEdr&@bKc"qLhFJ1O6tX<ULUcQfYj>4'I2pXB[b03BSe*
+br!K)$sl__n#RNE.Y2$#)>7//rB]kA`=X:Lq>>2RcZ:D+;L':,<@M!s+(P1<c4dQ1
+i\<goA+/V'5#9C&FOhlR;0HX(nPp,4IlZ'9k:Oe==O1"h-?Kg^)-q`XK9-*_oRVtP
+g2T8.\c/\e,mq0lHT!oAs%XNE&`72*Gth+(dSr+M$/p!mC@u0InS4`KP?'Li1++ND
+OcEcBj5b?1a.Q>):sX;&1UNHmCJj\S[00N^V?'7EOC!u3gIG=L7;>hr9;VHX4A!g2
+j.=GhQj:7r4g`[,Nh=$[9r%QLR#i3CiNKonmo:3Ak\*L&kQ_nu6aWUQj)`HO4&#el
+R?JrV$/N[I1Z[kI;#71*KnmPk6]dA2dYVKKnNPQqB=tEKNa3rOeI!hSTS":jT!T(U
+D5"k"S*iY>($I^YJ);0Br,EljcDT@8Glf;5rS;E4HL(7Pj?5!W4<\2fMr5+@]TaeL
+,=m$`H.'b\VF=-_0&o-kB//#s=:=G"-%k`\$cr&!Q4YJ!S)j/dbP`C@QZi0^pi2tH
+mgD/F>Ib=-lI[^J9BQWAol<t@PIfV86:RMo0BS,CK[,dAHb"ZaL_t,9@<*NENqW4J
+\B`(Bd45eBlQRObMaTp'lS_E)U<=.8-dfPuj`HLaD^UU#/oHd+]rN(c8QVEnf9fCN
+c!\C5HBiJj9tIU,oCn)hGCn<#prZ0<P-#NTOhBEEV%maTkPVb+r6QU_*F6P6V3!_Y
+#a2Y?f4Jr=bfV$%.99`(I_`QP%:f42gr8?fYL5e@dK81,B.#'u,4_;uZY"1.O0q*c
+J*ZJ(W1;'Zi'=Y"/@bnG56Cmo^g2<~> endstream endobj 13 0 obj <</BBox[0.0 630.0 810.0 0.0]/Group 295 0 R/Length 1678498/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R/GS1 296 0 R>>/XObject<</Fm0 297 0 R>>>>/Subtype/Form>>stream
+0.793 0.801 0.129 0.016 k
+/GS0 gs
+0 630 810 -174.639 re
+f
+0 75.361 810 -75.361 re
+f
+0 0 0 0 k
+q 1 0 0 1 758.8652 63.3223 cm
+0 0 m
+0.44 2.19 l
+1.396 2.19 l
+0.44 -1.294 l
+-0.427 -1.294 l
+-1.397 2.19 l
+-0.441 2.19 l
+h
+3.881 -1.294 m
+2.969 -1.294 l
+2.969 2.278 l
+2.072 1.94 l
+2.072 2.69 l
+3.792 3.395 l
+3.881 3.395 l
+h
+5.409 -0.823 m
+5.409 -0.688 5.453 -0.57 5.541 -0.47 c
+5.637 -0.375 5.765 -0.324 5.923 -0.324 c
+6.077 -0.324 6.206 -0.375 6.306 -0.47 c
+6.412 -0.559 6.468 -0.676 6.468 -0.823 c
+6.468 -0.981 6.412 -1.103 6.306 -1.191 c
+6.206 -1.278 6.077 -1.323 5.923 -1.323 c
+5.776 -1.323 5.651 -1.278 5.556 -1.191 c
+5.456 -1.103 5.409 -0.981 5.409 -0.823 c
+9.998 0.646 m
+9.998 0 9.881 -0.496 9.645 -0.838 c
+9.41 -1.183 9.076 -1.353 8.646 -1.353 c
+8.213 -1.353 7.881 -1.187 7.646 -0.852 c
+7.411 -0.522 7.287 -0.044 7.279 0.573 c
+7.279 1.455 l
+7.279 2.102 7.389 2.595 7.617 2.94 c
+7.852 3.281 8.191 3.454 8.631 3.454 c
+9.072 3.454 9.404 3.281 9.631 2.94 c
+9.867 2.605 9.988 2.124 9.998 1.5 c
+h
+9.088 1.587 m
+9.088 1.959 9.047 2.234 8.97 2.41 c
+8.899 2.595 8.786 2.69 8.631 2.69 c
+8.345 2.69 8.194 2.356 8.176 1.691 c
+8.176 0.515 l
+8.176 0.139 8.213 -0.14 8.294 -0.324 c
+8.371 -0.511 8.488 -0.603 8.646 -0.603 c
+8.793 -0.603 8.899 -0.522 8.97 -0.353 c
+9.036 -0.177 9.076 0.092 9.088 0.455 c
+h
+10.807 -0.823 m
+10.807 -0.688 10.851 -0.57 10.939 -0.47 c
+11.035 -0.375 11.164 -0.324 11.322 -0.324 c
+11.476 -0.324 11.605 -0.375 11.704 -0.47 c
+11.81 -0.559 11.866 -0.676 11.866 -0.823 c
+11.866 -0.981 11.81 -1.103 11.704 -1.191 c
+11.605 -1.278 11.476 -1.323 11.322 -1.323 c
+11.174 -1.323 11.05 -1.278 10.954 -1.191 c
+10.855 -1.103 10.807 -0.981 10.807 -0.823 c
+15.397 0.646 m
+15.397 0 15.279 -0.496 15.044 -0.838 c
+14.809 -1.183 14.474 -1.353 14.044 -1.353 c
+13.611 -1.353 13.28 -1.187 13.045 -0.852 c
+12.81 -0.522 12.685 -0.044 12.677 0.573 c
+12.677 1.455 l
+12.677 2.102 12.787 2.595 13.016 2.94 c
+13.251 3.281 13.589 3.454 14.03 3.454 c
+14.47 3.454 14.802 3.281 15.029 2.94 c
+15.264 2.605 15.386 2.124 15.397 1.5 c
+h
+14.485 1.587 m
+14.485 1.959 14.445 2.234 14.368 2.41 c
+14.298 2.595 14.184 2.69 14.03 2.69 c
+13.743 2.69 13.593 2.356 13.574 1.691 c
+13.574 0.515 l
+13.574 0.139 13.611 -0.14 13.692 -0.324 c
+13.769 -0.511 13.886 -0.603 14.044 -0.603 c
+14.192 -0.603 14.298 -0.522 14.368 -0.353 c
+14.434 -0.177 14.474 0.092 14.485 0.455 c
+h
+f
+Q
+q 1 0 0 1 40.6324 65.0269 cm
+0 0 m
+-0.276 -0.305 -0.632 -0.54 -1.073 -0.706 c
+-1.507 -0.87 -1.97 -0.947 -2.469 -0.941 c
+-2.911 -0.941 -3.293 -0.845 -3.616 -0.661 c
+-3.939 -0.467 -4.189 -0.187 -4.366 0.177 c
+-4.542 0.537 -4.642 0.956 -4.659 1.426 c
+-4.671 1.68 -4.656 1.945 -4.615 2.22 c
+-4.439 3.425 l
+-4.285 4.454 -3.95 5.248 -3.439 5.806 c
+-2.932 6.365 -2.263 6.633 -1.44 6.615 c
+-0.735 6.604 -0.206 6.394 0.147 5.983 c
+0.5 5.571 0.68 4.969 0.69 4.175 c
+-0.721 4.175 l
+-0.735 4.586 l
+-0.775 5.104 -1.037 5.373 -1.514 5.395 c
+-2.213 5.424 -2.668 4.961 -2.881 4.013 c
+-2.955 3.631 l
+-3.16 2.22 l
+-3.2 1.897 -3.215 1.617 -3.204 1.382 c
+-3.197 1.008 -3.113 0.736 -2.955 0.559 c
+-2.801 0.389 -2.583 0.302 -2.308 0.294 c
+-2.043 0.294 -1.749 0.383 -1.426 0.559 c
+-1.176 1.912 l
+-2.19 1.912 l
+-1.984 3.028 l
+0.47 3.028 l
+h
+2.095 -0.837 m
+0.698 -0.837 l
+1.639 4.63 l
+3.05 4.63 l
+h
+1.83 6.012 m
+1.83 6.247 1.903 6.438 2.051 6.585 c
+2.198 6.733 2.373 6.806 2.579 6.806 c
+2.793 6.814 2.977 6.747 3.123 6.6 c
+3.271 6.461 3.344 6.284 3.344 6.072 c
+3.344 5.836 3.271 5.644 3.123 5.498 c
+2.977 5.351 2.793 5.278 2.579 5.278 c
+2.363 5.266 2.183 5.328 2.036 5.469 c
+1.897 5.615 1.83 5.796 1.83 6.012 c
+5.945 5.968 m
+5.71 4.63 l
+6.416 4.63 l
+6.24 3.558 l
+5.534 3.558 l
+5.064 0.794 l
+5.049 0.632 l
+5.038 0.405 5.13 0.294 5.328 0.294 c
+5.388 0.283 5.505 0.287 5.681 0.31 c
+5.548 -0.808 l
+5.343 -0.897 5.097 -0.941 4.814 -0.941 c
+4.409 -0.929 4.108 -0.786 3.902 -0.5 c
+3.697 -0.205 3.616 0.184 3.667 0.676 c
+4.137 3.558 l
+3.52 3.558 l
+3.697 4.63 l
+4.314 4.63 l
+4.549 5.968 l
+h
+7.915 0.397 m
+10.444 0.397 l
+10.238 -0.837 l
+6.254 -0.837 l
+7.533 6.527 l
+8.974 6.527 l
+h
+13.498 -0.837 m
+13.475 -0.72 13.468 -0.58 13.468 -0.411 c
+13.152 -0.764 12.796 -0.941 12.395 -0.941 c
+11.973 -0.941 11.634 -0.789 11.381 -0.484 c
+11.135 -0.183 11.021 0.195 11.042 0.647 c
+11.072 1.235 11.296 1.691 11.719 2.014 c
+12.137 2.345 12.704 2.514 13.409 2.514 c
+13.82 2.514 l
+13.88 2.955 l
+13.895 3.175 l
+13.895 3.469 13.777 3.616 13.542 3.616 c
+13.218 3.624 13.02 3.418 12.954 2.999 c
+11.557 2.984 l
+11.586 3.502 11.8 3.925 12.204 4.248 c
+12.604 4.58 13.093 4.74 13.674 4.734 c
+14.21 4.723 14.622 4.549 14.909 4.219 c
+15.202 3.896 15.324 3.462 15.276 2.926 c
+14.82 0.148 l
+14.805 -0.132 l
+14.795 -0.367 14.82 -0.573 14.879 -0.749 c
+14.865 -0.837 l
+h
+12.792 0.177 m
+13.034 0.166 13.263 0.272 13.468 0.5 c
+13.718 1.646 l
+13.409 1.646 l
+13.145 1.636 12.928 1.548 12.762 1.382 c
+12.594 1.213 12.498 1.004 12.469 0.75 c
+12.469 0.559 l
+12.469 0.449 12.49 0.357 12.542 0.279 c
+12.601 0.21 12.681 0.177 12.792 0.177 c
+18.057 -0.941 m
+17.595 -0.918 17.249 -0.706 17.014 -0.294 c
+16.837 -0.837 l
+15.53 -0.837 l
+16.882 6.924 l
+18.279 6.924 l
+17.749 4.175 l
+18.061 4.557 18.418 4.74 18.822 4.734 c
+19.3 4.723 19.66 4.543 19.895 4.19 c
+20.13 3.844 20.233 3.341 20.204 2.675 c
+20.182 1.9 20.087 1.228 19.91 0.662 c
+19.74 0.092 19.502 -0.323 19.189 -0.588 c
+18.874 -0.841 18.499 -0.959 18.057 -0.941 c
+18.836 2.661 m
+18.844 2.974 18.807 3.194 18.719 3.323 c
+18.639 3.458 18.506 3.528 18.323 3.528 c
+18.065 3.535 17.83 3.404 17.617 3.132 c
+17.19 0.618 l
+17.286 0.383 17.477 0.254 17.764 0.235 c
+18.282 0.206 18.591 0.578 18.69 1.353 c
+18.734 1.721 l
+h
+25.672 1.721 m
+23.262 1.721 l
+23.482 2.911 l
+25.878 2.911 l
+h
+32.933 2.352 m
+30.684 2.352 l
+30.346 0.397 l
+33.007 0.397 l
+32.787 -0.837 l
+28.685 -0.837 l
+29.964 6.527 l
+34.065 6.527 l
+33.845 5.278 l
+31.199 5.278 l
+30.89 3.543 l
+33.139 3.543 l
+h
+35.424 1.206 m
+36.63 4.63 l
+38.115 4.63 l
+35.807 -0.837 l
+34.484 -0.837 l
+33.867 4.63 l
+35.293 4.63 l
+h
+39.966 -0.941 m
+39.526 -0.941 39.147 -0.833 38.835 -0.617 c
+38.53 -0.404 38.31 -0.103 38.173 0.279 c
+38.034 0.662 37.99 1.095 38.041 1.588 c
+38.085 1.956 l
+38.202 2.866 38.474 3.562 38.908 4.042 c
+39.349 4.52 39.912 4.752 40.599 4.734 c
+41.098 4.711 41.488 4.557 41.774 4.263 c
+42.058 3.969 42.223 3.55 42.274 3.014 c
+42.293 2.691 42.282 2.374 42.245 2.073 c
+42.157 1.411 l
+39.423 1.411 l
+39.401 1.272 39.397 1.135 39.409 1 c
+39.438 0.507 39.677 0.258 40.128 0.25 c
+40.548 0.239 40.955 0.401 41.348 0.736 c
+41.819 -0.132 l
+41.631 -0.389 41.371 -0.588 41.04 -0.735 c
+40.706 -0.881 40.349 -0.947 39.966 -0.941 c
+40.467 3.558 m
+40.062 3.564 39.783 3.308 39.629 2.779 c
+39.526 2.411 l
+40.907 2.411 l
+40.944 2.606 40.966 2.764 40.966 2.881 c
+40.974 3.311 40.808 3.535 40.467 3.558 c
+45.799 3.249 m
+45.358 3.308 l
+44.982 3.315 44.681 3.138 44.446 2.779 c
+43.814 -0.837 l
+42.418 -0.837 l
+43.373 4.63 l
+44.681 4.63 l
+44.564 4.028 l
+44.729 4.293 44.891 4.476 45.049 4.586 c
+45.203 4.693 45.376 4.748 45.564 4.748 c
+45.67 4.748 45.813 4.723 45.99 4.675 c
+h
+47.897 1.573 m
+49.146 4.63 l
+50.661 4.63 l
+47.853 -1.66 l
+47.647 -2.15 47.405 -2.502 47.133 -2.719 c
+46.857 -2.944 46.537 -3.057 46.177 -3.057 c
+46.037 -3.057 45.832 -3.021 45.56 -2.954 c
+45.692 -1.837 l
+45.839 -1.851 l
+46.221 -1.851 46.501 -1.679 46.677 -1.337 c
+46.912 -0.823 l
+46.339 4.63 l
+47.808 4.63 l
+h
+52.997 4.734 m
+53.556 4.711 53.986 4.52 54.291 4.16 c
+54.603 3.807 54.776 3.326 54.806 2.72 c
+54.806 2.367 l
+54.754 1.309 54.501 0.485 54.041 -0.103 c
+53.578 -0.683 52.976 -0.959 52.233 -0.941 c
+51.8 -0.929 51.443 -0.816 51.16 -0.588 c
+50.873 -0.363 50.667 -0.055 50.543 0.339 c
+50.426 0.739 50.389 1.199 50.44 1.721 c
+50.469 1.985 l
+50.565 2.845 50.84 3.521 51.292 4.013 c
+51.741 4.513 52.31 4.752 52.997 4.734 c
+51.822 1.147 m
+51.822 0.559 51.997 0.254 52.35 0.235 c
+52.839 0.206 53.159 0.578 53.306 1.353 c
+53.35 1.721 l
+53.398 2.198 53.424 2.506 53.424 2.646 c
+53.424 3.223 53.24 3.528 52.88 3.558 c
+52.604 3.564 52.38 3.44 52.204 3.175 c
+52.035 2.918 51.928 2.547 51.88 2.058 c
+51.839 1.565 51.822 1.264 51.822 1.147 c
+57.246 4.63 m
+57.142 4.087 l
+57.532 4.535 57.958 4.752 58.422 4.734 c
+58.804 4.723 59.091 4.576 59.288 4.293 c
+59.494 4.017 59.598 3.62 59.598 3.102 c
+59.568 2.646 l
+58.98 -0.837 l
+57.584 -0.837 l
+58.157 2.646 l
+58.187 2.94 l
+58.204 3.341 58.058 3.543 57.745 3.543 c
+57.599 3.543 57.47 3.502 57.363 3.425 c
+57.264 3.344 57.175 3.252 57.098 3.146 c
+56.393 -0.837 l
+54.997 -0.837 l
+55.952 4.63 l
+h
+62.141 -0.941 m
+61.699 -0.941 61.321 -0.833 61.009 -0.617 c
+60.703 -0.404 60.483 -0.103 60.347 0.279 c
+60.207 0.662 60.163 1.095 60.215 1.588 c
+60.259 1.956 l
+60.377 2.866 60.649 3.562 61.082 4.042 c
+61.522 4.52 62.085 4.752 62.773 4.734 c
+63.272 4.711 63.662 4.557 63.949 4.263 c
+64.231 3.969 64.396 3.55 64.448 3.014 c
+64.466 2.691 64.456 2.374 64.419 2.073 c
+64.331 1.411 l
+61.597 1.411 l
+61.574 1.272 61.57 1.135 61.582 1 c
+61.611 0.507 61.85 0.258 62.302 0.25 c
+62.721 0.239 63.128 0.401 63.522 0.736 c
+63.992 -0.132 l
+63.805 -0.389 63.544 -0.588 63.213 -0.735 c
+62.879 -0.881 62.522 -0.947 62.141 -0.941 c
+62.64 3.558 m
+62.236 3.564 61.956 3.308 61.802 2.779 c
+61.699 2.411 l
+63.081 2.411 l
+63.118 2.606 63.14 2.764 63.14 2.881 c
+63.147 3.311 62.982 3.535 62.64 3.558 c
+69.034 0.235 m
+69.416 0.225 69.655 0.5 69.754 1.058 c
+71.063 1.058 l
+71.004 0.449 70.776 -0.04 70.386 -0.411 c
+69.993 -0.786 69.519 -0.959 68.961 -0.941 c
+68.45 -0.929 68.042 -0.779 67.741 -0.484 c
+67.436 -0.191 67.255 0.214 67.197 0.736 c
+67.145 1.154 67.171 1.665 67.27 2.264 c
+67.365 2.87 67.554 3.373 67.829 3.778 c
+68.269 4.432 68.894 4.752 69.711 4.734 c
+70.258 4.711 70.681 4.513 70.974 4.131 c
+71.269 3.749 71.4 3.234 71.371 2.587 c
+70.048 2.587 l
+70.048 2.897 l
+70.037 3.315 69.875 3.535 69.563 3.558 c
+69.063 3.576 68.77 3.19 68.682 2.396 c
+68.578 1.485 l
+68.538 1.21 68.523 0.985 68.535 0.809 c
+68.564 0.434 68.729 0.243 69.034 0.235 c
+74.028 -0.837 m
+74.006 -0.72 73.999 -0.58 73.999 -0.411 c
+73.682 -0.764 73.326 -0.941 72.926 -0.941 c
+72.503 -0.941 72.165 -0.789 71.911 -0.484 c
+71.666 -0.183 71.552 0.195 71.573 0.647 c
+71.602 1.235 71.827 1.691 72.25 2.014 c
+72.668 2.345 73.235 2.514 73.94 2.514 c
+74.351 2.514 l
+74.411 2.955 l
+74.425 3.175 l
+74.425 3.469 74.307 3.616 74.072 3.616 c
+73.749 3.624 73.551 3.418 73.484 2.999 c
+72.088 2.984 l
+72.117 3.502 72.331 3.925 72.734 4.248 c
+73.135 4.58 73.624 4.74 74.205 4.734 c
+74.741 4.723 75.153 4.549 75.439 4.219 c
+75.733 3.896 75.855 3.462 75.807 2.926 c
+75.351 0.148 l
+75.336 -0.132 l
+75.325 -0.367 75.351 -0.573 75.41 -0.749 c
+75.396 -0.837 l
+h
+73.322 0.177 m
+73.565 0.166 73.793 0.272 73.999 0.5 c
+74.249 1.646 l
+73.94 1.646 l
+73.675 1.636 73.459 1.548 73.293 1.382 c
+73.124 1.213 73.029 1.004 72.999 0.75 c
+72.999 0.559 l
+72.999 0.449 73.021 0.357 73.073 0.279 c
+73.131 0.21 73.212 0.177 73.322 0.177 c
+78.28 4.63 m
+78.177 4.087 l
+78.567 4.535 78.993 4.752 79.456 4.734 c
+79.838 4.723 80.125 4.576 80.323 4.293 c
+80.529 4.017 80.632 3.62 80.632 3.102 c
+80.603 2.646 l
+80.015 -0.837 l
+78.618 -0.837 l
+79.191 2.646 l
+79.221 2.94 l
+79.238 3.341 79.092 3.543 78.779 3.543 c
+78.633 3.543 78.504 3.502 78.397 3.425 c
+78.298 3.344 78.21 3.252 78.133 3.146 c
+77.428 -0.837 l
+76.031 -0.837 l
+76.986 4.63 l
+h
+85.357 0.235 m
+85.74 0.225 85.979 0.5 86.078 1.058 c
+87.386 1.058 l
+87.327 0.449 87.099 -0.04 86.71 -0.411 c
+86.317 -0.786 85.842 -0.959 85.284 -0.941 c
+84.773 -0.929 84.366 -0.779 84.064 -0.484 c
+83.759 -0.191 83.579 0.214 83.52 0.736 c
+83.469 1.154 83.494 1.665 83.593 2.264 c
+83.689 2.87 83.876 3.373 84.152 3.778 c
+84.593 4.432 85.218 4.752 86.033 4.734 c
+86.581 4.711 87.003 4.513 87.298 4.131 c
+87.591 3.749 87.724 3.234 87.695 2.587 c
+86.372 2.587 l
+86.372 2.897 l
+86.361 3.315 86.199 3.535 85.887 3.558 c
+85.387 3.576 85.093 3.19 85.004 2.396 c
+84.902 1.485 l
+84.861 1.21 84.846 0.985 84.858 0.809 c
+84.887 0.434 85.052 0.243 85.357 0.235 c
+90.627 4.734 m
+91.186 4.711 91.616 4.52 91.921 4.16 c
+92.233 3.807 92.406 3.326 92.435 2.72 c
+92.435 2.367 l
+92.383 1.309 92.13 0.485 91.67 -0.103 c
+91.208 -0.683 90.605 -0.959 89.862 -0.941 c
+89.43 -0.929 89.073 -0.816 88.79 -0.588 c
+88.503 -0.363 88.297 -0.055 88.173 0.339 c
+88.055 0.739 88.018 1.199 88.069 1.721 c
+88.098 1.985 l
+88.194 2.845 88.47 3.521 88.921 4.013 c
+89.37 4.513 89.939 4.752 90.627 4.734 c
+89.451 1.147 m
+89.451 0.559 89.627 0.254 89.98 0.235 c
+90.469 0.206 90.789 0.578 90.936 1.353 c
+90.98 1.721 l
+91.028 2.198 91.053 2.506 91.053 2.646 c
+91.053 3.223 90.87 3.528 90.509 3.558 c
+90.234 3.564 90.01 3.44 89.833 3.175 c
+89.665 2.918 89.557 2.547 89.509 2.058 c
+89.469 1.565 89.451 1.264 89.451 1.147 c
+94.878 4.63 m
+94.776 4.087 l
+95.165 4.535 95.591 4.752 96.054 4.734 c
+96.437 4.723 96.723 4.576 96.922 4.293 c
+97.128 4.017 97.23 3.62 97.23 3.102 c
+97.201 2.646 l
+96.613 -0.837 l
+95.217 -0.837 l
+95.79 2.646 l
+95.819 2.94 l
+95.838 3.341 95.691 3.543 95.379 3.543 c
+95.231 3.543 95.103 3.502 94.996 3.425 c
+94.897 3.344 94.809 3.252 94.732 3.146 c
+94.026 -0.837 l
+92.63 -0.837 l
+93.585 4.63 l
+h
+100.318 5.968 m
+100.082 4.63 l
+100.788 4.63 l
+100.611 3.558 l
+99.906 3.558 l
+99.435 0.794 l
+99.421 0.632 l
+99.41 0.405 99.502 0.294 99.7 0.294 c
+99.759 0.283 99.876 0.287 100.052 0.31 c
+99.921 -0.808 l
+99.715 -0.897 99.468 -0.941 99.186 -0.941 c
+98.781 -0.929 98.48 -0.786 98.274 -0.5 c
+98.068 -0.205 97.987 0.184 98.039 0.676 c
+98.51 3.558 l
+97.892 3.558 l
+98.068 4.63 l
+98.685 4.63 l
+98.921 5.968 l
+h
+103.933 3.249 m
+103.493 3.308 l
+103.117 3.315 102.816 3.138 102.581 2.779 c
+101.949 -0.837 l
+100.553 -0.837 l
+101.508 4.63 l
+102.816 4.63 l
+102.699 4.028 l
+102.864 4.293 103.026 4.476 103.184 4.586 c
+103.338 4.693 103.51 4.748 103.698 4.748 c
+103.805 4.748 103.948 4.723 104.125 4.675 c
+h
+105.304 -0.837 m
+103.907 -0.837 l
+104.848 4.63 l
+106.259 4.63 l
+h
+105.039 6.012 m
+105.039 6.247 105.113 6.438 105.26 6.585 c
+105.407 6.733 105.583 6.806 105.789 6.806 c
+106.003 6.814 106.186 6.747 106.333 6.6 c
+106.479 6.461 106.554 6.284 106.554 6.072 c
+106.554 5.836 106.479 5.644 106.333 5.498 c
+106.186 5.351 106.003 5.278 105.789 5.278 c
+105.573 5.266 105.392 5.328 105.245 5.469 c
+105.106 5.615 105.039 5.796 105.039 6.012 c
+108.876 -0.941 m
+108.413 -0.918 108.067 -0.706 107.832 -0.294 c
+107.655 -0.837 l
+106.348 -0.837 l
+107.7 6.924 l
+109.097 6.924 l
+108.567 4.175 l
+108.879 4.557 109.236 4.74 109.64 4.734 c
+110.118 4.723 110.478 4.543 110.713 4.19 c
+110.948 3.844 111.051 3.341 111.022 2.675 c
+111 1.9 110.905 1.228 110.728 0.662 c
+110.559 0.092 110.32 -0.323 110.007 -0.588 c
+109.692 -0.841 109.317 -0.959 108.876 -0.941 c
+109.655 2.661 m
+109.662 2.974 109.625 3.194 109.537 3.323 c
+109.457 3.458 109.324 3.528 109.141 3.528 c
+108.883 3.535 108.648 3.404 108.435 3.132 c
+108.009 0.618 l
+108.104 0.383 108.295 0.254 108.582 0.235 c
+109.1 0.206 109.409 0.578 109.508 1.353 c
+109.552 1.721 l
+h
+114.003 -0.338 m
+113.656 -0.749 113.257 -0.947 112.797 -0.941 c
+112.433 -0.941 112.143 -0.823 111.929 -0.588 c
+111.713 -0.345 111.591 -0.014 111.562 0.397 c
+111.54 0.632 111.54 0.86 111.562 1.088 c
+112.164 4.63 l
+113.546 4.63 l
+112.958 1.073 l
+112.944 0.823 l
+112.933 0.655 112.958 0.518 113.018 0.412 c
+113.076 0.312 113.168 0.258 113.297 0.25 c
+113.569 0.239 113.826 0.383 114.061 0.676 c
+114.751 4.63 l
+116.148 4.63 l
+115.208 -0.837 l
+113.899 -0.837 l
+h
+118.897 5.968 m
+118.662 4.63 l
+119.368 4.63 l
+119.191 3.558 l
+118.485 3.558 l
+118.015 0.794 l
+118.001 0.632 l
+117.989 0.405 118.082 0.294 118.279 0.294 c
+118.338 0.283 118.456 0.287 118.632 0.31 c
+118.5 -0.808 l
+118.294 -0.897 118.048 -0.941 117.766 -0.941 c
+117.361 -0.929 117.06 -0.786 116.854 -0.5 c
+116.648 -0.205 116.567 0.184 116.619 0.676 c
+117.089 3.558 l
+116.472 3.558 l
+116.648 4.63 l
+117.265 4.63 l
+117.5 5.968 l
+h
+121.396 -0.941 m
+120.955 -0.941 120.576 -0.833 120.264 -0.617 c
+119.959 -0.404 119.738 -0.103 119.603 0.279 c
+119.463 0.662 119.418 1.095 119.47 1.588 c
+119.514 1.956 l
+119.632 2.866 119.904 3.562 120.337 4.042 c
+120.779 4.52 121.34 4.752 122.028 4.734 c
+122.528 4.711 122.917 4.557 123.204 4.263 c
+123.487 3.969 123.652 3.55 123.703 3.014 c
+123.722 2.691 123.711 2.374 123.674 2.073 c
+123.586 1.411 l
+120.852 1.411 l
+120.829 1.272 120.826 1.135 120.837 1 c
+120.866 0.507 121.105 0.258 121.558 0.25 c
+121.976 0.239 122.385 0.401 122.778 0.736 c
+123.248 -0.132 l
+123.061 -0.389 122.799 -0.588 122.469 -0.735 c
+122.134 -0.881 121.778 -0.947 121.396 -0.941 c
+121.895 3.558 m
+121.492 3.564 121.212 3.308 121.058 2.779 c
+120.955 2.411 l
+122.337 2.411 l
+122.373 2.606 122.395 2.764 122.395 2.881 c
+122.402 3.311 122.237 3.535 121.895 3.558 c
+135.212 4.146 m
+135.565 4.546 135.948 4.74 136.359 4.734 c
+136.76 4.723 137.065 4.572 137.271 4.278 c
+137.484 3.992 137.594 3.595 137.594 3.088 c
+137.579 2.602 l
+136.991 -0.837 l
+135.595 -0.837 l
+136.168 2.617 l
+136.197 2.911 l
+136.205 3.323 136.058 3.528 135.757 3.528 c
+135.529 3.535 135.316 3.418 135.11 3.175 c
+134.404 -0.837 l
+133.008 -0.837 l
+134.36 6.924 l
+135.757 6.924 l
+h
+140.696 5.968 m
+140.461 4.63 l
+141.166 4.63 l
+140.99 3.558 l
+140.284 3.558 l
+139.814 0.794 l
+139.799 0.632 l
+139.788 0.405 139.879 0.294 140.078 0.294 c
+140.137 0.283 140.255 0.287 140.431 0.31 c
+140.299 -0.808 l
+140.093 -0.897 139.847 -0.941 139.563 -0.941 c
+139.16 -0.929 138.858 -0.786 138.653 -0.5 c
+138.447 -0.205 138.366 0.184 138.418 0.676 c
+138.888 3.558 l
+138.27 3.558 l
+138.447 4.63 l
+139.064 4.63 l
+139.299 5.968 l
+h
+143.742 5.968 m
+143.507 4.63 l
+144.213 4.63 l
+144.036 3.558 l
+143.33 3.558 l
+142.86 0.794 l
+142.846 0.632 l
+142.834 0.405 142.927 0.294 143.125 0.294 c
+143.183 0.283 143.301 0.287 143.478 0.31 c
+143.345 -0.808 l
+143.139 -0.897 142.894 -0.941 142.61 -0.941 c
+142.206 -0.929 141.905 -0.786 141.699 -0.5 c
+141.493 -0.205 141.412 0.184 141.464 0.676 c
+141.934 3.558 l
+141.317 3.558 l
+141.493 4.63 l
+142.111 4.63 l
+142.346 5.968 l
+h
+146.491 -0.941 m
+146.069 -0.929 145.734 -0.746 145.491 -0.382 c
+145.007 -2.94 l
+143.625 -2.94 l
+144.933 4.63 l
+146.212 4.63 l
+146.123 4.131 l
+146.454 4.543 146.836 4.74 147.27 4.734 c
+147.748 4.723 148.107 4.543 148.342 4.19 c
+148.578 3.837 148.681 3.326 148.652 2.661 c
+148.629 1.867 148.534 1.195 148.357 0.647 c
+148.182 0.107 147.931 -0.301 147.608 -0.573 c
+147.292 -0.837 146.921 -0.959 146.491 -0.941 c
+147.27 2.675 m
+147.27 2.988 147.226 3.209 147.137 3.337 c
+147.056 3.462 146.931 3.532 146.755 3.543 c
+146.509 3.543 146.285 3.418 146.079 3.175 c
+145.624 0.588 l
+145.73 0.372 145.921 0.258 146.197 0.25 c
+146.704 0.221 147.023 0.622 147.152 1.455 c
+147.255 2.484 l
+h
+151.499 0.662 m
+151.536 0.897 151.356 1.106 150.956 1.294 c
+150.551 1.478 150.25 1.65 150.044 1.808 c
+149.846 1.974 149.699 2.153 149.603 2.352 c
+149.515 2.558 149.475 2.786 149.485 3.043 c
+149.515 3.532 149.721 3.94 150.103 4.263 c
+150.485 4.586 150.948 4.74 151.499 4.734 c
+152.047 4.723 152.477 4.561 152.793 4.248 c
+153.105 3.932 153.256 3.521 153.248 3.014 c
+151.852 3.014 l
+151.86 3.249 151.831 3.414 151.764 3.514 c
+151.694 3.62 151.58 3.675 151.426 3.675 c
+151.257 3.675 151.118 3.616 151 3.499 c
+150.89 3.389 150.827 3.256 150.809 3.102 c
+150.757 2.885 150.927 2.691 151.309 2.514 c
+151.698 2.345 151.977 2.205 152.146 2.088 c
+152.646 1.754 152.874 1.297 152.837 0.721 c
+152.815 0.387 152.712 0.092 152.529 -0.161 c
+152.34 -0.419 152.087 -0.613 151.764 -0.749 c
+151.448 -0.885 151.106 -0.947 150.735 -0.941 c
+150.195 -0.929 149.757 -0.76 149.427 -0.426 c
+149.092 -0.084 148.928 0.346 148.928 0.867 c
+150.264 0.853 l
+150.254 0.588 150.294 0.397 150.382 0.279 c
+150.478 0.169 150.625 0.118 150.823 0.118 c
+151 0.118 151.147 0.162 151.264 0.25 c
+151.389 0.346 151.47 0.485 151.499 0.662 c
+153.595 -0.147 m
+153.595 0.096 153.668 0.294 153.815 0.441 c
+153.969 0.595 154.167 0.676 154.403 0.676 c
+154.638 0.676 154.829 0.603 154.976 0.456 c
+155.13 0.316 155.211 0.14 155.211 -0.073 c
+155.211 -0.319 155.126 -0.521 154.961 -0.675 c
+154.803 -0.823 154.612 -0.897 154.388 -0.897 c
+154.152 -0.897 153.961 -0.83 153.815 -0.691 c
+153.668 -0.544 153.595 -0.363 153.595 -0.147 c
+154.535 3.616 m
+154.535 3.859 154.609 4.057 154.755 4.204 c
+154.91 4.358 155.108 4.439 155.343 4.439 c
+155.579 4.439 155.77 4.366 155.916 4.219 c
+156.071 4.079 156.151 3.903 156.151 3.69 c
+156.151 3.444 156.067 3.242 155.902 3.088 c
+155.744 2.94 155.553 2.866 155.328 2.866 c
+155.093 2.866 154.902 2.933 154.755 3.072 c
+154.609 3.219 154.535 3.4 154.535 3.616 c
+156.5 -1.469 m
+155.442 -1.469 l
+158.97 6.527 l
+160.028 6.527 l
+h
+158.566 -1.469 m
+157.508 -1.469 l
+161.036 6.527 l
+162.094 6.527 l
+h
+164.02 -0.837 m
+163.997 -0.72 163.99 -0.58 163.99 -0.411 c
+163.674 -0.764 163.317 -0.941 162.917 -0.941 c
+162.494 -0.941 162.156 -0.789 161.903 -0.484 c
+161.657 -0.183 161.543 0.195 161.564 0.647 c
+161.594 1.235 161.818 1.691 162.241 2.014 c
+162.659 2.345 163.226 2.514 163.931 2.514 c
+164.342 2.514 l
+164.402 2.955 l
+164.416 3.175 l
+164.416 3.469 164.298 3.616 164.063 3.616 c
+163.74 3.624 163.542 3.418 163.475 2.999 c
+162.079 2.984 l
+162.108 3.502 162.322 3.925 162.726 4.248 c
+163.126 4.58 163.615 4.74 164.196 4.734 c
+164.732 4.723 165.144 4.549 165.431 4.219 c
+165.724 3.896 165.846 3.462 165.798 2.926 c
+165.342 0.148 l
+165.327 -0.132 l
+165.316 -0.367 165.342 -0.573 165.401 -0.749 c
+165.387 -0.837 l
+h
+163.314 0.177 m
+163.556 0.166 163.785 0.272 163.99 0.5 c
+164.24 1.646 l
+163.931 1.646 l
+163.667 1.636 163.45 1.548 163.284 1.382 c
+163.116 1.213 163.02 1.004 162.991 0.75 c
+162.991 0.559 l
+162.991 0.449 163.012 0.357 163.064 0.279 c
+163.122 0.21 163.203 0.177 163.314 0.177 c
+168.58 -0.941 m
+168.117 -0.918 167.771 -0.706 167.536 -0.294 c
+167.359 -0.837 l
+166.052 -0.837 l
+167.404 6.924 l
+168.801 6.924 l
+168.271 4.175 l
+168.583 4.557 168.94 4.74 169.344 4.734 c
+169.822 4.723 170.182 4.543 170.417 4.19 c
+170.652 3.844 170.755 3.341 170.725 2.675 c
+170.704 1.9 170.608 1.228 170.432 0.662 c
+170.263 0.092 170.024 -0.323 169.711 -0.588 c
+169.395 -0.841 169.021 -0.959 168.58 -0.941 c
+169.358 2.661 m
+169.366 2.974 169.329 3.194 169.241 3.323 c
+169.16 3.458 169.028 3.528 168.844 3.528 c
+168.587 3.535 168.352 3.404 168.138 3.132 c
+167.712 0.618 l
+167.808 0.383 167.999 0.254 168.286 0.235 c
+168.803 0.206 169.113 0.578 169.212 1.353 c
+169.256 1.721 l
+h
+173.823 4.734 m
+174.382 4.711 174.812 4.52 175.117 4.16 c
+175.429 3.807 175.602 3.326 175.631 2.72 c
+175.631 2.367 l
+175.581 1.309 175.327 0.485 174.867 -0.103 c
+174.405 -0.683 173.802 -0.959 173.059 -0.941 c
+172.626 -0.929 172.269 -0.816 171.986 -0.588 c
+171.7 -0.363 171.494 -0.055 171.369 0.339 c
+171.251 0.739 171.215 1.199 171.266 1.721 c
+171.295 1.985 l
+171.39 2.845 171.666 3.521 172.119 4.013 c
+172.566 4.513 173.136 4.752 173.823 4.734 c
+172.647 1.147 m
+172.647 0.559 172.824 0.254 173.177 0.235 c
+173.665 0.206 173.985 0.578 174.133 1.353 c
+174.176 1.721 l
+174.224 2.198 174.25 2.506 174.25 2.646 c
+174.25 3.223 174.066 3.528 173.706 3.558 c
+173.43 3.564 173.206 3.44 173.03 3.175 c
+172.861 2.918 172.755 2.547 172.707 2.058 c
+172.666 1.565 172.647 1.264 172.647 1.147 c
+178.615 -0.338 m
+178.27 -0.749 177.869 -0.947 177.41 -0.941 c
+177.046 -0.941 176.756 -0.823 176.543 -0.588 c
+176.327 -0.345 176.205 -0.014 176.175 0.397 c
+176.153 0.632 176.153 0.86 176.175 1.088 c
+176.778 4.63 l
+178.16 4.63 l
+177.572 1.073 l
+177.557 0.823 l
+177.546 0.655 177.572 0.518 177.63 0.412 c
+177.69 0.312 177.781 0.258 177.91 0.25 c
+178.182 0.239 178.439 0.383 178.675 0.676 c
+179.365 4.63 l
+180.761 4.63 l
+179.82 -0.837 l
+178.513 -0.837 l
+h
+183.514 5.968 m
+183.279 4.63 l
+183.984 4.63 l
+183.808 3.558 l
+183.103 3.558 l
+182.632 0.794 l
+182.617 0.632 l
+182.606 0.405 182.698 0.294 182.897 0.294 c
+182.955 0.283 183.073 0.287 183.249 0.31 c
+183.117 -0.808 l
+182.912 -0.897 182.665 -0.941 182.382 -0.941 c
+181.978 -0.929 181.677 -0.786 181.47 -0.5 c
+181.265 -0.205 181.185 0.184 181.235 0.676 c
+181.706 3.558 l
+181.089 3.558 l
+181.265 4.63 l
+181.883 4.63 l
+182.118 5.968 l
+h
+183.999 -0.147 m
+183.999 0.096 184.073 0.294 184.219 0.441 c
+184.374 0.595 184.572 0.676 184.807 0.676 c
+185.042 0.676 185.233 0.603 185.381 0.456 c
+185.535 0.316 185.616 0.14 185.616 -0.073 c
+185.616 -0.319 185.532 -0.521 185.366 -0.675 c
+185.208 -0.823 185.017 -0.897 184.793 -0.897 c
+184.558 -0.897 184.366 -0.83 184.219 -0.691 c
+184.073 -0.544 183.999 -0.363 183.999 -0.147 c
+189.137 4.734 m
+189.614 4.711 189.967 4.513 190.195 4.131 c
+190.371 4.63 l
+191.635 4.63 l
+190.71 -0.837 l
+190.61 -1.55 190.334 -2.094 189.886 -2.469 c
+189.445 -2.84 188.886 -3.017 188.21 -2.998 c
+187.916 -2.987 187.622 -2.925 187.328 -2.807 c
+187.034 -2.697 186.792 -2.543 186.608 -2.337 c
+187.167 -1.352 l
+187.45 -1.675 187.803 -1.841 188.225 -1.851 c
+188.82 -1.881 189.187 -1.547 189.328 -0.852 c
+189.43 -0.396 l
+189.107 -0.76 188.743 -0.941 188.343 -0.941 c
+187.872 -0.941 187.512 -0.76 187.269 -0.396 c
+187.024 -0.037 186.906 0.47 186.916 1.118 c
+186.916 1.507 186.953 1.929 187.034 2.382 c
+187.111 2.841 187.226 3.227 187.373 3.543 c
+187.755 4.355 188.343 4.752 189.137 4.734 c
+188.284 1.133 m
+188.284 0.551 188.468 0.258 188.842 0.25 c
+189.085 0.25 189.316 0.357 189.534 0.574 c
+190.004 3.19 l
+189.875 3.414 189.688 3.532 189.445 3.543 c
+188.857 3.572 188.497 3.091 188.372 2.103 c
+188.313 1.632 188.284 1.309 188.284 1.133 c
+193.054 -0.837 m
+191.657 -0.837 l
+192.598 4.63 l
+194.009 4.63 l
+h
+192.789 6.012 m
+192.789 6.247 192.863 6.438 193.01 6.585 c
+193.156 6.733 193.333 6.806 193.538 6.806 c
+193.752 6.814 193.935 6.747 194.083 6.6 c
+194.23 6.461 194.303 6.284 194.303 6.072 c
+194.303 5.836 194.23 5.644 194.083 5.498 c
+193.935 5.351 193.752 5.278 193.538 5.278 c
+193.322 5.266 193.142 5.328 192.995 5.469 c
+192.855 5.615 192.789 5.796 192.789 6.012 c
+196.909 5.968 m
+196.674 4.63 l
+197.379 4.63 l
+197.202 3.558 l
+196.497 3.558 l
+196.027 0.794 l
+196.012 0.632 l
+196.001 0.405 196.092 0.294 196.291 0.294 c
+196.35 0.283 196.468 0.287 196.644 0.31 c
+196.512 -0.808 l
+196.306 -0.897 196.059 -0.941 195.776 -0.941 c
+195.373 -0.929 195.071 -0.786 194.866 -0.5 c
+194.66 -0.205 194.579 0.184 194.631 0.676 c
+195.101 3.558 l
+194.483 3.558 l
+194.66 4.63 l
+195.277 4.63 l
+195.512 5.968 l
+h
+198.614 -0.837 m
+197.218 -0.837 l
+198.555 6.924 l
+199.966 6.924 l
+h
+202.259 -0.837 m
+202.237 -0.72 202.23 -0.58 202.23 -0.411 c
+201.914 -0.764 201.557 -0.941 201.156 -0.941 c
+200.734 -0.941 200.396 -0.789 200.142 -0.484 c
+199.896 -0.183 199.782 0.195 199.805 0.647 c
+199.834 1.235 200.058 1.691 200.48 2.014 c
+200.9 2.345 201.465 2.514 202.171 2.514 c
+202.583 2.514 l
+202.641 2.955 l
+202.656 3.175 l
+202.656 3.469 202.538 3.616 202.303 3.616 c
+201.98 3.624 201.781 3.418 201.715 2.999 c
+200.318 2.984 l
+200.348 3.502 200.561 3.925 200.965 4.248 c
+201.366 4.58 201.854 4.74 202.435 4.734 c
+202.972 4.723 203.383 4.549 203.67 4.219 c
+203.965 3.896 204.085 3.462 204.038 2.926 c
+203.582 0.148 l
+203.568 -0.132 l
+203.556 -0.367 203.582 -0.573 203.641 -0.749 c
+203.626 -0.837 l
+h
+201.553 0.177 m
+201.796 0.166 202.024 0.272 202.23 0.5 c
+202.479 1.646 l
+202.171 1.646 l
+201.906 1.636 201.69 1.548 201.524 1.382 c
+201.355 1.213 201.259 1.004 201.23 0.75 c
+201.23 0.559 l
+201.23 0.449 201.252 0.357 201.303 0.279 c
+201.362 0.21 201.443 0.177 201.553 0.177 c
+206.82 -0.941 m
+206.356 -0.918 206.011 -0.706 205.775 -0.294 c
+205.6 -0.837 l
+204.291 -0.837 l
+205.644 6.924 l
+207.04 6.924 l
+206.511 4.175 l
+206.823 4.557 207.179 4.74 207.584 4.734 c
+208.061 4.723 208.422 4.543 208.657 4.19 c
+208.892 3.844 208.995 3.341 208.965 2.675 c
+208.943 1.9 208.848 1.228 208.671 0.662 c
+208.503 0.092 208.264 -0.323 207.951 -0.588 c
+207.635 -0.841 207.26 -0.959 206.82 -0.941 c
+207.599 2.661 m
+207.606 2.974 207.569 3.194 207.481 3.323 c
+207.4 3.458 207.267 3.528 207.084 3.528 c
+206.826 3.535 206.591 3.404 206.378 3.132 c
+205.952 0.618 l
+206.047 0.383 206.238 0.254 206.525 0.235 c
+207.044 0.206 207.352 0.578 207.452 1.353 c
+207.495 1.721 l
+h
+209.432 -0.147 m
+209.432 0.096 209.505 0.294 209.652 0.441 c
+209.807 0.595 210.005 0.676 210.24 0.676 c
+210.475 0.676 210.666 0.603 210.814 0.456 c
+210.968 0.316 211.049 0.14 211.049 -0.073 c
+211.049 -0.319 210.965 -0.521 210.799 -0.675 c
+210.641 -0.823 210.45 -0.897 210.226 -0.897 c
+209.991 -0.897 209.8 -0.83 209.652 -0.691 c
+209.505 -0.544 209.432 -0.363 209.432 -0.147 c
+214.217 0.235 m
+214.599 0.225 214.838 0.5 214.937 1.058 c
+216.245 1.058 l
+216.187 0.449 215.959 -0.04 215.569 -0.411 c
+215.175 -0.786 214.702 -0.959 214.143 -0.941 c
+213.632 -0.929 213.224 -0.779 212.923 -0.484 c
+212.618 -0.191 212.438 0.214 212.379 0.736 c
+212.328 1.154 212.353 1.665 212.453 2.264 c
+212.548 2.87 212.736 3.373 213.012 3.778 c
+213.452 4.432 214.077 4.752 214.893 4.734 c
+215.441 4.711 215.863 4.513 216.157 4.131 c
+216.451 3.749 216.584 3.234 216.553 2.587 c
+215.231 2.587 l
+215.231 2.897 l
+215.22 3.315 215.058 3.535 214.745 3.558 c
+214.246 3.576 213.952 3.19 213.864 2.396 c
+213.761 1.485 l
+213.721 1.21 213.706 0.985 213.717 0.809 c
+213.746 0.434 213.912 0.243 214.217 0.235 c
+219.49 4.734 m
+220.048 4.711 220.478 4.52 220.783 4.16 c
+221.095 3.807 221.268 3.326 221.298 2.72 c
+221.298 2.367 l
+221.247 1.309 220.993 0.485 220.534 -0.103 c
+220.071 -0.683 219.468 -0.959 218.726 -0.941 c
+218.292 -0.929 217.935 -0.816 217.652 -0.588 c
+217.366 -0.363 217.16 -0.055 217.035 0.339 c
+216.918 0.739 216.881 1.199 216.933 1.721 c
+216.962 1.985 l
+217.057 2.845 217.332 3.521 217.785 4.013 c
+218.233 4.513 218.803 4.752 219.49 4.734 c
+218.314 1.147 m
+218.314 0.559 218.49 0.254 218.843 0.235 c
+219.331 0.206 219.651 0.578 219.799 1.353 c
+219.842 1.721 l
+219.89 2.198 219.917 2.506 219.917 2.646 c
+219.917 3.223 219.732 3.528 219.372 3.558 c
+219.096 3.564 218.872 3.44 218.696 3.175 c
+218.527 2.918 218.421 2.547 218.373 2.058 c
+218.332 1.565 218.314 1.264 218.314 1.147 c
+223.767 4.63 m
+223.68 4.116 l
+224.062 4.535 224.491 4.74 224.973 4.734 c
+225.491 4.711 225.829 4.469 225.987 3.998 c
+226.398 4.499 226.857 4.74 227.368 4.734 c
+227.758 4.723 228.052 4.576 228.251 4.293 c
+228.457 4.017 228.559 3.62 228.559 3.102 c
+228.53 2.646 l
+227.956 -0.837 l
+226.56 -0.837 l
+227.133 2.646 l
+227.163 2.926 l
+227.192 3.337 227.052 3.543 226.751 3.543 c
+226.516 3.543 226.3 3.373 226.105 3.043 c
+226.075 2.808 l
+225.443 -0.837 l
+224.046 -0.837 l
+224.62 2.646 l
+224.649 2.926 l
+224.679 3.337 224.546 3.543 224.252 3.543 c
+224.106 3.543 223.981 3.502 223.885 3.425 c
+223.786 3.344 223.697 3.252 223.62 3.146 c
+222.93 -0.837 l
+221.533 -0.837 l
+222.474 4.63 l
+h
+229.232 -1.469 m
+228.174 -1.469 l
+231.701 6.527 l
+232.76 6.527 l
+h
+f
+Q
+q
+457.854 554.164 m
+456.424 554.164 455.223 553.183 454.899 551.849 c
+408.477 551.849 l
+408.315 551.849 408.182 551.651 408.197 551.489 c
+408.211 551.327 408.373 551.191 408.535 551.191 c
+454.8 551.191 l
+454.8 551.129 l
+454.8 549.449 456.175 548.093 457.854 548.093 c
+459.489 548.093 460.798 549.376 460.871 550.989 c
+467.03 550.126 470.499 546.631 474.067 543.063 c
+477.584 539.549 481.196 535.97 487.366 534.997 c
+487.535 533.475 488.796 532.299 490.361 532.299 c
+491.838 532.299 493.062 533.339 493.338 534.735 c
+505.038 534.735 l
+505.313 533.339 506.537 532.299 508.014 532.299 c
+509.492 532.299 510.711 533.339 510.987 534.735 c
+523.687 534.735 l
+532.026 534.735 536.266 538.947 540.381 543.063 c
+544.067 546.748 547.654 550.338 554.199 551.051 c
+554.239 549.405 555.599 548.093 557.253 548.093 c
+558.936 548.093 560.288 549.449 560.288 551.129 c
+560.288 551.191 l
+586.724 551.191 l
+586.724 551.129 l
+586.724 549.449 588.081 548.093 589.76 548.093 c
+591.399 548.093 592.733 549.386 592.795 551.011 c
+599.329 550.305 604.44 547.512 608.828 543.562 c
+613.928 538.972 618.052 532.821 622.167 526.651 c
+626.283 520.477 630.399 514.285 635.588 509.618 c
+639.369 506.212 643.723 503.643 649.023 502.49 c
+625.261 502.49 l
+624.986 503.886 623.766 504.944 622.289 504.944 c
+620.812 504.944 619.569 503.886 619.293 502.49 c
+592.754 502.49 l
+592.479 503.886 591.237 504.944 589.76 504.944 c
+588.341 504.944 587.161 503.963 586.824 502.648 c
+580.466 503.434 576.916 506.983 573.286 510.615 c
+569.655 514.249 565.914 517.964 559.351 518.783 c
+559.263 520.385 557.94 521.657 556.316 521.657 c
+554.746 521.657 553.486 520.466 553.32 518.941 c
+543.535 518.941 l
+543.369 520.466 542.091 521.657 540.522 521.657 c
+538.952 521.657 537.692 520.466 537.526 518.941 c
+529.001 518.941 l
+534.035 520.283 537.247 523.477 540.381 526.611 c
+543.913 530.142 547.36 533.607 553.397 534.515 c
+553.758 533.237 554.92 532.299 556.316 532.299 c
+557.8 532.299 559.042 533.35 559.311 534.758 c
+586.787 534.758 l
+587.055 533.35 588.275 532.299 589.76 532.299 c
+591.443 532.299 592.817 533.655 592.817 535.334 c
+592.817 537.017 591.443 538.37 589.76 538.37 c
+588.098 538.37 586.757 537.047 586.724 535.397 c
+559.369 535.397 l
+559.336 537.047 557.977 538.37 556.316 538.37 c
+554.633 538.37 553.28 537.017 553.28 535.334 c
+553.28 535.275 553.295 535.217 553.299 535.155 c
+547.07 534.207 543.436 530.602 539.901 527.07 c
+535.917 523.083 532.066 519.18 524.448 518.941 c
+510.09 518.941 l
+510.069 519.136 510.028 519.32 509.969 519.5 c
+509.918 519.673 509.852 519.841 509.771 520 c
+509.683 520.169 509.587 520.331 509.47 520.481 c
+509.381 520.599 509.279 520.694 509.172 520.801 c
+509.146 520.823 509.136 520.856 509.113 520.878 c
+509.076 520.911 509.028 520.929 508.992 520.959 c
+508.889 521.044 508.787 521.127 508.672 521.198 c
+508.521 521.293 508.359 521.374 508.195 521.437 c
+507.849 521.572 507.467 521.657 507.073 521.657 c
+506.867 521.657 506.67 521.635 506.474 521.598 c
+506.273 521.557 506.082 521.495 505.898 521.418 c
+505.729 521.345 505.549 521.26 505.398 521.158 c
+505.391 521.154 505.383 521.143 505.376 521.139 c
+505.215 521.029 505.078 520.896 504.939 520.761 c
+504.814 520.635 504.7 520.503 504.6 520.36 c
+504.531 520.264 504.476 520.165 504.421 520.059 c
+504.384 519.992 504.332 519.93 504.299 519.86 c
+504.292 519.841 504.288 519.82 504.28 519.801 c
+504.203 519.625 504.16 519.452 504.12 519.261 c
+504.101 519.18 504.089 519.103 504.079 519.022 c
+504.068 518.923 504.042 518.824 504.039 518.721 c
+497.747 517.798 494.094 514.168 490.541 510.615 c
+490.008 510.081 489.483 509.56 488.946 509.038 c
+486.308 511.853 484.577 515.282 482.835 518.761 c
+480.777 522.877 478.69 527.044 475.026 530.182 c
+471.811 532.938 467.387 534.864 460.75 535.294 c
+460.368 536.54 459.225 537.451 457.854 537.451 c
+456.524 537.451 455.392 536.588 454.98 535.397 c
+375.929 535.397 l
+375.9 535.4 375.859 535.4 375.83 535.397 c
+375.657 535.371 375.524 535.188 375.551 535.015 c
+375.572 534.845 375.756 534.714 375.929 534.735 c
+454.841 534.735 l
+454.83 534.629 454.8 534.53 454.8 534.415 c
+454.8 532.736 456.175 531.362 457.854 531.362 c
+459.537 531.362 460.889 532.736 460.889 534.415 c
+460.889 534.493 460.875 534.563 460.871 534.636 c
+467.294 534.188 471.531 532.303 474.608 529.665 c
+478.146 526.633 480.178 522.579 482.236 518.463 c
+483.975 514.984 485.735 511.46 488.446 508.56 c
+485.543 505.815 482.354 503.452 477.484 502.728 c
+477.117 503.999 475.956 504.944 474.567 504.944 c
+473.089 504.944 471.869 503.886 471.594 502.49 c
+460.831 502.49 l
+460.555 503.886 459.331 504.944 457.854 504.944 c
+456.377 504.944 455.134 503.886 454.859 502.49 c
+375.551 502.49 l
+326.151 502.49 l
+325.974 502.482 325.823 502.306 325.831 502.129 c
+325.838 501.953 325.996 501.802 326.168 501.809 c
+454.8 501.809 l
+454.845 500.167 456.2 498.855 457.854 498.855 c
+459.508 498.855 460.848 500.167 460.889 501.809 c
+471.531 501.809 l
+471.576 500.167 472.913 498.855 474.567 498.855 c
+476.22 498.855 477.562 500.167 477.602 501.809 c
+504.039 501.809 l
+504.083 500.167 505.42 498.855 507.073 498.855 c
+508.727 498.855 510.087 500.167 510.131 501.809 c
+518.377 501.809 l
+513.343 500.465 510.127 497.275 506.996 494.144 c
+503.495 490.642 500.062 487.218 494.117 486.277 c
+493.672 487.409 492.569 488.213 491.279 488.213 c
+489.898 488.213 488.755 487.28 488.384 486.015 c
+460.75 486.015 l
+460.378 487.28 459.24 488.213 457.854 488.213 c
+456.472 488.213 455.311 487.28 454.94 486.015 c
+392.002 486.015 l
+391.819 486.038 391.642 485.884 391.642 485.695 c
+391.642 485.508 391.819 485.354 392.002 485.377 c
+454.818 485.377 l
+454.815 485.306 454.8 485.248 454.8 485.178 c
+454.8 483.495 456.175 482.121 457.854 482.121 c
+459.537 482.121 460.889 483.495 460.889 485.178 c
+460.889 485.248 460.875 485.306 460.871 485.377 c
+488.266 485.377 l
+488.262 485.306 488.245 485.248 488.245 485.178 c
+488.245 483.495 489.6 482.121 491.279 482.121 c
+492.962 482.121 494.337 483.495 494.337 485.178 c
+494.337 485.346 494.323 485.497 494.296 485.655 c
+500.382 486.655 503.968 490.198 507.455 493.685 c
+511.046 497.275 514.555 500.795 520.791 501.63 c
+520.924 500.072 522.214 498.855 523.808 498.855 c
+525.462 498.855 526.8 500.167 526.844 501.809 c
+537.486 501.809 l
+537.526 500.167 538.868 498.855 540.522 498.855 c
+542.175 498.855 543.535 500.167 543.575 501.809 c
+556.595 501.809 l
+564.713 501.809 568.715 497.797 572.826 493.685 c
+576.461 490.05 580.202 486.35 586.764 485.537 c
+586.75 485.413 586.724 485.302 586.724 485.178 c
+586.724 483.495 588.081 482.121 589.76 482.121 c
+591.443 482.121 592.817 483.495 592.817 485.178 c
+592.817 485.248 592.798 485.306 592.795 485.377 c
+603.459 485.377 l
+603.451 485.306 603.437 485.248 603.437 485.178 c
+603.437 483.495 604.812 482.121 606.495 482.121 c
+608.174 482.121 609.529 483.495 609.529 485.178 c
+609.529 485.248 609.512 485.306 609.508 485.377 c
+635.984 485.377 l
+635.981 485.306 635.966 485.248 635.966 485.178 c
+635.966 483.495 637.318 482.121 639.002 482.121 c
+640.681 482.121 642.037 483.495 642.037 485.178 c
+642.037 485.317 642.015 485.442 641.996 485.578 c
+648.35 486.474 652.021 490.113 655.593 493.685 c
+659.106 497.198 662.534 500.619 668.514 501.549 c
+668.682 500.031 669.943 498.855 671.508 498.855 c
+673.162 498.855 674.518 500.167 674.562 501.809 c
+704.732 501.809 l
+712.853 501.809 716.833 497.797 720.949 493.685 c
+724.502 490.127 728.159 486.512 734.464 485.597 c
+734.446 485.454 734.424 485.325 734.424 485.178 c
+734.424 483.495 735.798 482.121 737.481 482.121 c
+739.161 482.121 740.517 483.495 740.517 485.178 c
+740.517 485.248 740.498 485.306 740.494 485.377 c
+751.177 485.377 l
+751.174 485.306 751.159 485.248 751.159 485.178 c
+751.159 483.495 752.511 482.121 754.194 482.121 c
+755.874 482.121 757.248 483.495 757.248 485.178 c
+757.248 486.857 755.874 488.213 754.194 488.213 c
+752.809 488.213 751.666 487.28 751.299 486.015 c
+740.373 486.015 l
+740.006 487.28 738.863 488.213 737.481 488.213 c
+736.17 488.213 735.052 487.378 734.626 486.214 c
+728.471 487.077 724.995 490.572 721.427 494.144 c
+718.292 497.275 715.08 500.465 710.046 501.809 c
+734.424 501.809 l
+734.468 500.167 735.827 498.855 737.481 498.855 c
+739.161 498.855 740.517 500.207 740.517 501.89 c
+740.517 503.569 739.161 504.944 737.481 504.944 c
+736.004 504.944 734.762 503.886 734.487 502.49 c
+693.571 502.49 l
+698.606 503.835 701.818 507.002 704.952 510.137 c
+708.443 513.628 711.865 517.042 717.774 518.004 c
+718.057 516.616 719.277 515.568 720.746 515.568 c
+722.312 515.568 723.59 516.762 723.763 518.284 c
+734.464 518.284 l
+734.634 516.762 735.916 515.568 737.481 515.568 c
+739.161 515.568 740.517 516.942 740.517 518.621 c
+740.517 520.304 739.161 521.657 737.481 521.657 c
+735.912 521.657 734.63 520.466 734.464 518.941 c
+723.763 518.941 l
+723.598 520.466 722.316 521.657 720.746 521.657 c
+719.081 521.657 717.733 520.323 717.711 518.662 c
+711.593 517.67 707.991 514.112 704.493 510.615 c
+700.378 506.503 696.379 502.49 688.262 502.49 c
+674.504 502.49 l
+674.228 503.886 672.985 504.944 671.508 504.944 c
+670.031 504.944 668.807 503.886 668.532 502.49 c
+658.709 502.49 l
+658.698 502.545 658.683 502.596 658.669 502.648 c
+658.632 502.794 658.584 502.931 658.529 503.066 c
+658.47 503.206 658.404 503.342 658.327 503.467 c
+658.29 503.529 658.249 503.588 658.209 503.647 c
+658.11 503.791 657.993 503.922 657.871 504.047 c
+657.75 504.169 657.628 504.286 657.489 504.386 c
+657.47 504.4 657.449 504.411 657.43 504.427 c
+657.42 504.433 657.401 504.437 657.39 504.444 c
+657.235 504.547 657.081 504.632 656.913 504.705 c
+656.549 504.859 656.152 504.944 655.733 504.944 c
+655.516 504.944 655.317 504.907 655.115 504.863 c
+654.957 504.83 654.799 504.801 654.656 504.745 c
+654.549 504.705 654.453 504.654 654.355 504.606 c
+654.292 504.573 654.233 504.54 654.174 504.506 c
+654.087 504.452 653.998 504.408 653.917 504.346 c
+653.825 504.279 653.74 504.184 653.657 504.107 c
+653.627 504.077 653.586 504.059 653.557 504.026 c
+653.422 503.889 653.304 503.746 653.197 503.588 c
+653.094 503.43 652.992 503.261 652.917 503.089 c
+652.914 503.081 652.921 503.074 652.917 503.066 c
+652.855 502.919 652.797 502.769 652.756 502.607 c
+645.888 503.176 640.57 506.006 636.024 510.096 c
+630.925 514.686 626.819 520.838 622.707 527.007 c
+618.592 533.181 614.476 539.395 609.288 544.062 c
+604.8 548.1 599.491 550.989 592.754 551.687 c
+592.494 553.106 591.252 554.164 589.76 554.164 c
+588.326 554.164 587.15 553.183 586.824 551.849 c
+560.189 551.849 l
+559.865 553.183 558.685 554.164 557.253 554.164 c
+555.776 554.164 554.533 553.124 554.257 551.728 c
+547.434 551.018 543.612 547.23 539.901 543.522 c
+535.789 539.406 531.808 535.397 523.687 535.397 c
+511.05 535.397 l
+511.017 537.047 509.676 538.37 508.014 538.37 c
+506.354 538.37 505.012 537.047 504.979 535.397 c
+493.396 535.397 l
+493.367 537.047 492.022 538.37 490.361 538.37 c
+488.796 538.37 487.535 537.194 487.366 535.676 c
+481.45 536.628 478.021 540.027 474.527 543.522 c
+470.936 547.115 467.261 550.797 460.831 551.669 c
+460.577 553.095 459.354 554.164 457.854 554.164 c
+454.462 523.674 m
+454.462 513.672 l
+457.795 508.66 l
+461.128 513.672 l
+461.128 523.674 l
+h
+668.433 523.674 m
+668.433 513.672 l
+671.766 508.66 l
+675.102 513.672 l
+675.102 523.674 l
+h
+510.09 518.284 m
+537.526 518.284 l
+537.695 516.762 538.956 515.568 540.522 515.568 c
+542.087 515.568 543.365 516.762 543.535 518.284 c
+553.32 518.284 l
+553.49 516.762 554.75 515.568 556.316 515.568 c
+557.826 515.568 559.094 516.678 559.329 518.122 c
+565.664 517.324 569.206 513.76 572.826 510.137 c
+575.961 507.002 579.176 503.835 584.21 502.49 c
+576.023 502.49 l
+575.747 503.886 574.524 504.944 573.047 504.944 c
+571.57 504.944 570.328 503.886 570.052 502.49 c
+543.517 502.49 l
+543.241 503.886 541.998 504.944 540.522 504.944 c
+539.045 504.944 537.821 503.886 537.545 502.49 c
+526.781 502.49 l
+526.505 503.886 525.286 504.944 523.808 504.944 c
+522.331 504.944 521.107 503.886 520.832 502.49 c
+510.069 502.49 l
+509.793 503.886 508.551 504.944 507.073 504.944 c
+505.645 504.944 504.465 503.941 504.141 502.607 c
+497.751 503.059 493.529 504.911 490.464 507.542 c
+490.089 507.862 489.725 508.219 489.384 508.56 c
+489.931 509.086 490.468 509.603 491 510.137 c
+494.547 513.682 498.015 517.166 504.101 518.063 c
+504.13 517.909 504.167 517.751 504.218 517.603 c
+504.23 517.578 504.23 517.549 504.241 517.523 c
+504.292 517.391 504.369 517.269 504.439 517.144 c
+504.454 517.119 504.465 517.093 504.479 517.063 c
+504.534 516.968 504.593 516.876 504.66 516.784 c
+504.744 516.67 504.839 516.568 504.939 516.464 c
+505.045 516.358 505.155 516.259 505.277 516.167 c
+505.336 516.123 505.394 516.086 505.456 516.046 c
+505.541 515.994 505.629 515.951 505.718 515.906 c
+505.809 515.862 505.898 515.803 505.997 515.766 c
+506.148 515.708 506.313 515.66 506.474 515.627 c
+506.673 515.587 506.867 515.568 507.073 515.568 c
+507.467 515.568 507.831 515.652 508.172 515.789 c
+508.349 515.855 508.514 515.932 508.672 516.028 c
+508.787 516.097 508.889 516.182 508.992 516.266 c
+509.028 516.296 509.076 516.314 509.113 516.347 c
+509.153 516.383 509.194 516.428 509.231 516.464 c
+509.452 516.689 509.624 516.946 509.771 517.225 c
+509.852 517.383 509.918 517.553 509.969 517.725 c
+510.025 517.905 510.069 518.093 510.09 518.284 c
+488.906 508.101 m
+489.266 507.737 489.644 507.38 490.041 507.043 c
+492.482 504.951 495.619 503.342 499.886 502.49 c
+479.62 502.49 l
+483.551 503.537 486.367 505.705 488.906 508.101 c
+750.717 505.565 m
+750.717 495.559 l
+754.054 490.569 l
+757.387 495.559 l
+757.387 505.565 l
+h
+561.905 501.809 m
+569.993 501.809 l
+570.033 500.167 571.393 498.855 573.047 498.855 c
+574.7 498.855 576.042 500.167 576.082 501.809 c
+586.724 501.809 l
+586.768 500.167 588.106 498.855 589.76 498.855 c
+591.414 498.855 592.773 500.167 592.817 501.809 c
+619.231 501.809 l
+619.276 500.167 620.635 498.855 622.289 498.855 c
+623.943 498.855 625.28 500.167 625.324 501.809 c
+652.679 501.809 l
+652.679 501.736 652.69 501.663 652.697 501.589 c
+652.712 501.46 652.73 501.335 652.756 501.211 c
+652.797 501.034 652.848 500.872 652.917 500.711 c
+652.955 500.623 653.009 500.538 653.057 500.454 c
+653.197 500.193 653.37 499.939 653.576 499.733 c
+653.612 499.697 653.657 499.667 653.697 499.634 c
+653.946 499.41 654.222 499.226 654.534 499.094 c
+654.542 499.091 654.549 499.097 654.557 499.094 c
+654.733 499.02 654.92 498.954 655.115 498.914 c
+655.119 498.914 655.126 498.918 655.134 498.914 c
+655.325 498.877 655.531 498.855 655.733 498.855 c
+655.942 498.855 656.133 498.873 656.331 498.914 c
+656.633 498.977 656.909 499.094 657.169 499.234 c
+657.258 499.282 657.349 499.318 657.43 499.373 c
+657.581 499.476 657.721 499.586 657.85 499.715 c
+657.867 499.733 l
+657.894 499.756 657.908 499.789 657.93 499.814 c
+658.041 499.932 658.158 500.057 658.249 500.193 c
+658.349 500.34 658.438 500.49 658.507 500.652 c
+658.518 500.67 658.522 500.693 658.529 500.711 c
+658.596 500.872 658.65 501.038 658.687 501.211 c
+658.717 501.335 658.735 501.46 658.75 501.589 c
+658.754 501.663 658.764 501.736 658.768 501.809 c
+666.496 501.809 l
+661.461 500.465 658.247 497.275 655.115 494.144 c
+651.533 490.561 648.049 487.062 641.857 486.214 c
+641.427 487.378 640.313 488.213 639.002 488.213 c
+637.616 488.213 636.473 487.28 636.105 486.015 c
+609.386 486.015 l
+609.019 487.28 607.877 488.213 606.495 488.213 c
+605.109 488.213 603.948 487.28 603.576 486.015 c
+592.673 486.015 l
+592.306 487.28 591.145 488.213 589.76 488.213 c
+588.433 488.213 587.323 487.361 586.905 486.177 c
+580.495 486.942 576.931 490.499 573.286 494.144 c
+570.155 497.275 566.939 500.465 561.905 501.809 c
+540.481 495.761 m
+537.144 490.767 l
+537.144 480.746 l
+543.814 480.746 l
+543.814 490.767 l
+h
+W n
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 g
+/GS1 gs
+0 TL/Fm0 Do
+Q
+Q
+q 1 0 0 1 175.2352 546.0975 cm
+0 0 m
+-3.391 0 l
+-3.381 -25.219 l
+10.33 -25.219 l
+10.33 -22.1 l
+0.008 -22.1 l
+h
+f
+Q
+q 1 0 0 1 198.6173 525.3062 cm
+0 0 m
+-0.845 -0.886 -2.271 -1.771 -4.196 -1.771 c
+-6.776 -1.771 -7.816 -0.5 -7.816 1.153 c
+-7.816 3.657 -6.081 4.85 -2.385 4.85 c
+-1.693 4.85 -0.577 4.773 0 4.659 c
+h
+-3.501 15.283 m
+-6.239 15.283 -8.749 14.313 -10.708 12.7 c
+-9.51 10.628 l
+-8.124 11.436 -6.43 12.244 -4.005 12.244 c
+-1.23 12.244 0 10.819 0 8.43 c
+0 7.199 l
+-0.536 7.316 -1.653 7.393 -2.348 7.393 c
+-8.279 7.393 -11.281 5.313 -11.281 0.962 c
+-11.281 -2.926 -8.893 -4.891 -5.273 -4.891 c
+-2.836 -4.891 -0.5 -3.774 0.31 -1.966 c
+0.927 -4.428 l
+3.315 -4.428 l
+3.315 8.47 l
+3.315 12.553 1.544 15.283 -3.501 15.283 c
+f
+Q
+q 1 0 0 1 212.8648 523.4172 cm
+0 0 m
+-1.272 0 -2.389 0.154 -3.233 0.54 c
+-3.233 12.208 l
+-2.08 13.17 -0.654 13.861 1.158 13.861 c
+4.428 13.861 5.7 11.553 5.7 7.817 c
+5.7 2.502 3.66 0 0 0 c
+1.426 17.172 m
+-1.602 17.172 -3.233 15.114 y
+-3.233 18.366 l
+-3.245 22.68 l
+-6.556 22.68 l
+-6.545 -1.922 l
+-4.891 -2.616 -2.616 -3.002 -0.154 -3.002 c
+6.163 -3.002 9.205 1.039 9.205 8.011 c
+9.205 13.516 6.394 17.172 1.426 17.172 c
+f
+Q
+q 1 0 0 1 138.3959 543.3637 cm
+0 0 m
+3.002 0 4.928 -1.003 6.199 -2.003 c
+7.655 0.518 l
+5.67 2.26 3.002 3.194 0.154 3.194 c
+-7.048 3.194 -12.094 -1.194 -12.094 -10.05 c
+-12.094 -19.329 -6.651 -22.948 -0.422 -22.948 c
+2.697 -22.948 5.354 -22.217 7.085 -21.487 c
+7.015 -11.572 l
+7.015 -8.452 l
+-2.227 -8.452 l
+-2.227 -11.572 l
+3.663 -11.572 l
+3.734 -19.098 l
+2.965 -19.484 1.617 -19.792 -0.191 -19.792 c
+-5.199 -19.792 -8.548 -16.643 -8.548 -10.009 c
+-8.548 -3.274 -5.082 0 0 0 c
+f
+Q
+q 1 0 0 1 162.2267 546.0975 cm
+0 0 m
+-3.311 0 l
+-3.3 -4.237 l
+-3.3 -18.866 l
+-3.3 -22.948 -1.529 -25.682 3.516 -25.682 c
+4.215 -25.682 4.895 -25.62 5.556 -25.499 c
+5.556 -22.526 l
+5.078 -22.599 4.567 -22.64 4.016 -22.64 c
+1.246 -22.64 0.011 -21.214 0.011 -18.829 c
+0.011 -8.742 l
+5.556 -8.742 l
+5.556 -5.967 l
+0.011 -5.967 l
+h
+f
+Q
+150.512 540.13 3.314 -19.252 re
+f
+150.512 546.098 3.314 -3.311 re
+f
+0 0.672 0.855 0 k
+q 1 0 0 1 111.978 528.4332 cm
+0 0 m
+-4.278 13.163 l
+-12.755 39.254 l
+-13.193 40.595 -15.092 40.595 -15.53 39.254 c
+-24.008 13.163 l
+-52.159 13.163 l
+-60.641 39.254 l
+-61.075 40.595 -62.975 40.595 -63.411 39.254 c
+-71.889 13.163 l
+-76.167 0 l
+-76.56 -1.201 -76.13 -2.514 -75.109 -3.256 c
+-38.086 -30.152 l
+-1.058 -3.256 l
+-0.037 -2.514 0.389 -1.201 0 0 c
+f
+Q
+0.031 0.844 0.875 0.004 k
+q 1 0 0 1 73.8922 498.2816 cm
+0 0 m
+14.078 43.314 l
+-14.073 43.314 l
+h
+f
+Q
+0 0.672 0.855 0 k
+q 1 0 0 1 73.8922 498.2816 cm
+0 0 m
+-14.073 43.314 l
+-33.804 43.314 l
+h
+f
+Q
+0 0.43 0.871 0 k
+q 1 0 0 1 40.0886 541.5961 cm
+0 0 m
+-4.278 -13.163 l
+-4.671 -14.364 -4.241 -15.68 -3.219 -16.419 c
+33.804 -43.314 l
+h
+f
+Q
+0.031 0.844 0.875 0.004 k
+q 1 0 0 1 40.0886 541.5961 cm
+0 0 m
+19.73 0 l
+11.248 26.091 l
+10.815 27.432 8.914 27.432 8.478 26.091 c
+h
+f
+Q
+0 0.672 0.855 0 k
+q 1 0 0 1 73.8922 498.2816 cm
+0 0 m
+14.078 43.314 l
+33.808 43.314 l
+h
+f
+Q
+0 0.43 0.871 0 k
+q 1 0 0 1 107.7005 541.5961 cm
+0 0 m
+4.278 -13.163 l
+4.667 -14.364 4.241 -15.68 3.219 -16.419 c
+-33.808 -43.314 l
+h
+f
+Q
+0.031 0.844 0.875 0.004 k
+q 1 0 0 1 107.7005 541.5961 cm
+0 0 m
+-19.73 0 l
+-11.252 26.091 l
+-10.815 27.432 -8.915 27.432 -8.478 26.091 c
+h
+f
+Q
+0 0 0 0 k
+q 1 0 0 1 142.633 472.606 cm
+0 0 m
+-0.559 -0.706 l
+-2.168 -2.579 -4.513 -3.513 -7.599 -3.513 c
+-10.356 -3.513 -12.517 -2.601 -14.082 -0.779 c
+-15.64 1.044 -16.441 3.62 -16.478 6.953 c
+-16.478 11.936 l
+-16.478 15.501 -15.769 18.172 -14.346 19.947 c
+-12.917 21.718 -10.782 22.608 -7.938 22.608 c
+-5.519 22.608 -3.627 21.931 -2.263 20.579 c
+-0.893 19.227 -0.14 17.301 0 14.803 c
+-3.19 14.803 l
+-3.319 16.378 -3.759 17.613 -4.513 18.506 c
+-5.259 19.395 -6.394 19.844 -7.923 19.844 c
+-9.746 19.844 -11.083 19.245 -11.936 18.051 c
+-12.788 16.864 -13.23 14.964 -13.259 12.347 c
+-13.259 7.159 l
+-13.259 4.601 -12.773 2.635 -11.803 1.264 c
+-10.826 -0.099 -9.419 -0.779 -7.585 -0.779 c
+-5.872 -0.779 -4.564 -0.363 -3.66 0.47 c
+-3.19 0.912 l
+-3.19 6.776 l
+-7.834 6.776 l
+-7.834 9.496 l
+0 9.496 l
+h
+8.712 -3.16 -3.189 25.415 re
+28.737 19.491 m
+22.048 19.491 l
+22.048 -3.16 l
+18.859 -3.16 l
+18.859 19.491 l
+12.185 19.491 l
+12.185 22.255 l
+28.737 22.255 l
+h
+56.088 4.91 m
+55.941 2.183 55.169 0.096 53.78 -1.352 c
+52.398 -2.792 50.436 -3.513 47.901 -3.513 c
+45.35 -3.513 43.322 -2.543 41.815 -0.602 c
+40.315 1.338 39.566 3.961 39.566 7.277 c
+39.566 11.892 l
+39.566 15.192 40.334 17.804 41.873 19.726 c
+43.421 21.645 45.526 22.608 48.194 22.608 c
+50.642 22.608 52.537 21.865 53.883 20.388 c
+55.236 18.918 55.97 16.816 56.088 14.082 c
+52.854 14.082 l
+52.714 16.158 52.281 17.639 51.546 18.521 c
+50.81 19.403 49.694 19.844 48.194 19.844 c
+46.46 19.844 45.126 19.16 44.196 17.801 c
+43.263 16.449 42.8 14.464 42.8 11.848 c
+42.8 7.188 l
+42.8 4.619 43.23 2.65 44.093 1.279 c
+44.965 -0.095 46.232 -0.779 47.901 -0.779 c
+49.565 -0.779 50.759 -0.367 51.487 0.456 c
+52.221 1.279 52.678 2.764 52.854 4.91 c
+h
+77.144 -3.16 m
+73.939 -3.16 l
+73.939 8.584 l
+63.709 8.584 l
+63.709 -3.16 l
+60.505 -3.16 l
+60.505 22.255 l
+63.709 22.255 l
+63.709 11.333 l
+73.939 11.333 l
+73.939 22.255 l
+77.144 22.255 l
+h
+95.025 8.584 m
+86.045 8.584 l
+86.045 -0.426 l
+96.51 -0.426 l
+96.51 -3.16 l
+82.84 -3.16 l
+82.84 22.255 l
+96.334 22.255 l
+96.334 19.491 l
+86.045 19.491 l
+86.045 11.333 l
+95.025 11.333 l
+h
+112.54 3.469 m
+103.955 3.469 l
+101.971 -3.16 l
+98.693 -3.16 l
+106.88 22.255 l
+109.614 22.255 l
+117.831 -3.16 l
+114.539 -3.16 l
+h
+104.793 6.232 m
+111.717 6.232 l
+108.247 17.787 l
+h
+134.007 19.491 m
+127.32 19.491 l
+127.32 -3.16 l
+124.13 -3.16 l
+124.13 19.491 l
+117.456 19.491 l
+117.456 22.255 l
+134.007 22.255 l
+h
+156.527 3.263 m
+156.527 4.528 156.181 5.498 155.498 6.174 c
+154.81 6.85 153.572 7.504 151.779 8.144 c
+149.985 8.79 148.611 9.467 147.663 10.172 c
+146.711 10.878 146.002 11.678 145.531 12.582 c
+145.061 13.483 144.826 14.512 144.826 15.67 c
+144.826 17.687 145.495 19.348 146.84 20.652 c
+148.181 21.953 149.942 22.608 152.117 22.608 c
+153.605 22.608 154.931 22.269 156.1 21.593 c
+157.265 20.924 158.162 19.998 158.79 18.815 c
+159.415 17.629 159.731 16.324 159.731 14.905 c
+156.527 14.905 l
+156.527 16.47 156.144 17.687 155.38 18.55 c
+154.623 19.41 153.535 19.844 152.117 19.844 c
+150.831 19.844 149.831 19.48 149.118 18.757 c
+148.412 18.04 148.06 17.029 148.06 15.728 c
+148.06 14.659 148.442 13.762 149.206 13.039 c
+149.978 12.311 151.165 11.664 152.764 11.098 c
+155.27 10.275 157.059 9.253 158.129 8.041 c
+159.205 6.835 159.745 5.251 159.745 3.293 c
+159.745 1.235 159.073 -0.419 157.732 -1.66 c
+156.398 -2.896 154.579 -3.513 152.278 -3.513 c
+150.798 -3.513 149.431 -3.189 148.177 -2.543 c
+146.931 -1.896 145.95 -0.992 145.238 0.177 c
+144.521 1.353 144.165 2.694 144.165 4.204 c
+147.369 4.204 l
+147.369 2.635 147.81 1.415 148.691 0.544 c
+149.574 -0.33 150.768 -0.764 152.278 -0.764 c
+153.69 -0.764 154.748 -0.407 155.453 0.309 c
+156.167 1.033 156.527 2.018 156.527 3.263 c
+180.662 -3.16 m
+177.458 -3.16 l
+177.458 8.584 l
+167.227 8.584 l
+167.227 -3.16 l
+164.023 -3.16 l
+164.023 22.255 l
+167.227 22.255 l
+167.227 11.333 l
+177.458 11.333 l
+177.458 22.255 l
+180.662 22.255 l
+h
+198.544 8.584 m
+189.563 8.584 l
+189.563 -0.426 l
+200.028 -0.426 l
+200.028 -3.16 l
+186.358 -3.16 l
+186.358 22.255 l
+199.852 22.255 l
+199.852 19.491 l
+189.563 19.491 l
+189.563 11.333 l
+198.544 11.333 l
+h
+216.38 8.584 m
+207.4 8.584 l
+207.4 -0.426 l
+217.866 -0.426 l
+217.866 -3.16 l
+204.195 -3.16 l
+204.195 22.255 l
+217.689 22.255 l
+217.689 19.491 l
+207.4 19.491 l
+207.4 11.333 l
+216.38 11.333 l
+h
+237.246 19.491 m
+230.558 19.491 l
+230.558 -3.16 l
+227.368 -3.16 l
+227.368 19.491 l
+220.695 19.491 l
+220.695 22.255 l
+237.246 22.255 l
+h
+f
+Q
+0.793 0.801 0.129 0.016 k
+535.667 442.028 238.665 -21.457 re
+f
+0 0 0 0 k
+q 1 0 0 1 655.8467 428.4505 cm
+0 0 m
+-2.573 0 l
+-3.072 -1.911 l
+-5.072 -1.911 l
+-2.147 7.453 l
+-0.426 7.453 l
+2.528 -1.911 l
+0.5 -1.911 l
+h
+-2.161 1.587 m
+-0.412 1.587 l
+-1.294 4.924 l
+h
+3.686 -0.985 m
+3.686 -0.691 3.781 -0.453 3.979 -0.264 c
+4.174 -0.081 4.428 0.014 4.744 0.014 c
+5.045 0.014 5.295 -0.081 5.494 -0.264 c
+5.699 -0.453 5.802 -0.691 5.802 -0.985 c
+5.802 -1.29 5.699 -1.536 5.494 -1.72 c
+5.295 -1.897 5.045 -1.985 4.744 -1.985 c
+4.438 -1.985 4.185 -1.893 3.979 -1.706 c
+3.781 -1.521 3.686 -1.279 3.686 -0.985 c
+17.055 -0.852 m
+16.691 -1.246 16.246 -1.544 15.717 -1.75 c
+15.187 -1.945 14.607 -2.043 13.982 -2.043 c
+12.902 -2.043 12.064 -1.713 11.469 -1.044 c
+10.869 -0.379 10.565 0.592 10.557 1.866 c
+10.557 3.557 l
+10.557 4.85 10.836 5.843 11.395 6.541 c
+11.962 7.235 12.785 7.584 13.865 7.584 c
+14.883 7.584 15.647 7.327 16.158 6.82 c
+16.676 6.321 16.974 5.534 17.055 4.469 c
+15.217 4.469 l
+15.166 5.064 15.044 5.471 14.85 5.689 c
+14.651 5.901 14.343 6.011 13.924 6.011 c
+13.413 6.011 13.041 5.824 12.806 5.453 c
+12.579 5.078 12.461 4.486 12.453 3.675 c
+12.453 1.97 l
+12.453 1.117 12.579 0.492 12.835 0.103 c
+13.089 -0.279 13.504 -0.47 14.085 -0.47 c
+14.456 -0.47 14.761 -0.397 14.996 -0.25 c
+15.158 -0.133 l
+15.158 1.587 l
+13.836 1.587 l
+13.836 3.013 l
+17.055 3.013 l
+h
+20.612 -1.911 -1.897 9.363 re
+28.192 5.88 m
+25.87 5.88 l
+25.87 -1.911 l
+23.974 -1.911 l
+23.974 5.88 l
+21.695 5.88 l
+21.695 7.453 l
+28.192 7.453 l
+h
+34.187 -1.911 -1.897 9.363 re
+42.436 -1.911 m
+40.54 -1.911 l
+37.776 4.233 l
+37.776 -1.911 l
+35.88 -1.911 l
+35.88 7.453 l
+37.776 7.453 l
+40.54 1.308 l
+40.54 7.453 l
+42.436 7.453 l
+h
+48.143 0.544 m
+48.143 0.926 48.044 1.213 47.849 1.411 c
+47.65 1.606 47.298 1.808 46.79 2.013 c
+45.85 2.373 45.173 2.793 44.762 3.263 c
+44.35 3.74 44.145 4.31 44.145 4.968 c
+44.145 5.751 44.424 6.383 44.982 6.865 c
+45.541 7.342 46.25 7.584 47.114 7.584 c
+47.691 7.584 48.205 7.459 48.657 7.217 c
+49.106 6.971 49.451 6.629 49.686 6.188 c
+49.929 5.747 50.054 5.247 50.054 4.689 c
+48.172 4.689 l
+48.172 5.13 48.076 5.46 47.893 5.689 c
+47.706 5.913 47.438 6.026 47.085 6.026 c
+46.75 6.026 46.49 5.928 46.305 5.733 c
+46.129 5.545 46.041 5.284 46.041 4.953 c
+46.041 4.696 46.144 4.461 46.349 4.247 c
+46.555 4.042 46.916 3.825 47.438 3.601 c
+48.348 3.278 49.01 2.873 49.422 2.396 c
+49.84 1.914 50.054 1.301 50.054 0.559 c
+50.054 -0.258 49.792 -0.893 49.275 -1.353 c
+48.753 -1.816 48.047 -2.043 47.158 -2.043 c
+46.548 -2.043 45.997 -1.918 45.497 -1.675 c
+45.005 -1.422 44.618 -1.066 44.336 -0.603 c
+44.049 -0.133 43.91 0.415 43.91 1.043 c
+45.806 1.043 l
+45.806 0.503 45.909 0.11 46.114 -0.133 c
+46.328 -0.379 46.677 -0.5 47.158 -0.5 c
+47.812 -0.5 48.143 -0.154 48.143 0.544 c
+57.587 5.88 m
+55.265 5.88 l
+55.265 -1.911 l
+53.368 -1.911 l
+53.368 5.88 l
+51.09 5.88 l
+51.09 7.453 l
+57.587 7.453 l
+h
+62.548 0 m
+59.976 0 l
+59.475 -1.911 l
+57.476 -1.911 l
+60.402 7.453 l
+62.122 7.453 l
+65.077 -1.911 l
+63.047 -1.911 l
+h
+60.387 1.587 m
+62.137 1.587 l
+61.254 4.924 l
+h
+68.071 -0.339 m
+71.393 -0.339 l
+71.393 -1.911 l
+66.175 -1.911 l
+66.175 7.453 l
+68.071 7.453 l
+h
+74.554 -0.339 m
+77.875 -0.339 l
+77.875 -1.911 l
+72.657 -1.911 l
+72.657 7.453 l
+74.554 7.453 l
+h
+83.74 0 m
+81.168 0 l
+80.668 -1.911 l
+78.669 -1.911 l
+81.594 7.453 l
+83.314 7.453 l
+86.269 -1.911 l
+84.24 -1.911 l
+h
+81.579 1.587 m
+83.329 1.587 l
+82.446 4.924 l
+h
+92.644 5.88 m
+90.321 5.88 l
+90.321 -1.911 l
+88.426 -1.911 l
+88.426 5.88 l
+86.147 5.88 l
+86.147 7.453 l
+92.644 7.453 l
+h
+95.915 -1.911 -1.897 9.363 re
+104.205 1.926 m
+104.205 0.669 103.904 -0.305 103.308 -1 c
+102.709 -1.698 101.886 -2.043 100.839 -2.043 c
+99.788 -2.043 98.961 -1.702 98.355 -1.014 c
+97.756 -0.32 97.451 0.646 97.444 1.881 c
+97.444 3.484 l
+97.444 4.766 97.741 5.77 98.34 6.497 c
+98.936 7.221 99.766 7.584 100.825 7.584 c
+101.86 7.584 102.68 7.224 103.279 6.512 c
+103.885 5.806 104.194 4.81 104.205 3.528 c
+h
+102.309 3.499 m
+102.309 4.34 102.184 4.968 101.941 5.38 c
+101.706 5.791 101.332 5.997 100.825 5.997 c
+100.324 5.997 99.95 5.795 99.707 5.394 c
+99.472 5.001 99.347 4.402 99.339 3.601 c
+99.339 1.926 l
+99.339 1.109 99.461 0.507 99.707 0.118 c
+99.95 -0.276 100.328 -0.47 100.839 -0.47 c
+101.328 -0.47 101.691 -0.279 101.926 0.103 c
+102.169 0.484 102.298 1.072 102.309 1.866 c
+h
+112.337 -1.911 m
+110.441 -1.911 l
+107.678 4.233 l
+107.678 -1.911 l
+105.781 -1.911 l
+105.781 7.453 l
+107.678 7.453 l
+110.441 1.308 l
+110.441 7.453 l
+112.337 7.453 l
+h
+f
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 539.3305 407.9565 cm
+0 0 m
+-2.263 0 l
+-2.263 -2.955 l
+-3.102 -2.955 l
+-3.102 3.733 l
+0.383 3.733 l
+0.383 3.013 l
+-2.263 3.013 l
+-2.263 0.72 l
+0 0.72 l
+h
+0.871 -0.235 m
+0.871 0.477 1.04 1.047 1.386 1.469 c
+1.739 1.888 2.201 2.102 2.782 2.102 c
+3.359 2.102 3.818 1.896 4.164 1.484 c
+4.517 1.08 4.696 0.521 4.708 -0.191 c
+4.708 -0.706 l
+4.708 -1.434 4.532 -2.007 4.179 -2.425 c
+3.833 -2.837 3.373 -3.043 2.797 -3.043 c
+2.216 -3.043 1.754 -2.845 1.401 -2.44 c
+1.055 -2.029 0.879 -1.478 0.871 -0.779 c
+h
+1.679 -0.706 m
+1.679 -1.216 1.775 -1.617 1.974 -1.912 c
+2.18 -2.205 2.452 -2.352 2.797 -2.352 c
+3.51 -2.352 3.877 -1.834 3.899 -0.794 c
+3.899 -0.235 l
+3.899 0.272 3.796 0.675 3.591 0.97 c
+3.392 1.263 3.124 1.411 2.782 1.411 c
+2.448 1.411 2.18 1.263 1.974 0.97 c
+1.775 0.675 1.679 0.272 1.679 -0.235 c
+h
+7.622 1.249 m
+7.504 1.267 7.379 1.278 7.254 1.278 c
+6.832 1.278 6.541 1.051 6.387 0.602 c
+6.387 -2.955 l
+5.564 -2.955 l
+5.564 2.013 l
+6.358 2.013 l
+6.373 1.514 l
+6.585 1.903 6.894 2.102 7.298 2.102 c
+7.423 2.102 7.533 2.08 7.622 2.043 c
+h
+14.93 -2.117 m
+14.784 -2.308 l
+14.361 -2.801 13.744 -3.043 12.931 -3.043 c
+12.204 -3.043 11.638 -2.804 11.227 -2.323 c
+10.815 -1.845 10.602 -1.169 10.595 -0.294 c
+10.595 1.014 l
+10.595 1.955 10.778 2.653 11.153 3.116 c
+11.524 3.586 12.087 3.821 12.844 3.821 c
+13.479 3.821 13.976 3.645 14.328 3.293 c
+14.689 2.94 14.89 2.433 14.93 1.778 c
+14.093 1.778 l
+14.053 2.19 13.935 2.514 13.74 2.749 c
+13.542 2.984 13.244 3.102 12.844 3.102 c
+12.362 3.102 12.01 2.944 11.786 2.631 c
+11.557 2.315 11.439 1.815 11.433 1.132 c
+11.433 -0.235 l
+11.433 -0.912 11.557 -1.434 11.815 -1.794 c
+12.079 -2.147 12.451 -2.323 12.931 -2.323 c
+13.38 -2.323 13.725 -2.216 13.961 -1.999 c
+14.093 -1.881 l
+14.093 -0.339 l
+12.858 -0.339 l
+12.858 0.382 l
+14.93 0.382 l
+h
+20.454 -2.955 m
+19.616 -2.955 l
+16.941 2.204 l
+16.941 -2.955 l
+16.089 -2.955 l
+16.089 3.733 l
+16.941 3.733 l
+19.616 -1.441 l
+19.616 3.733 l
+20.454 3.733 l
+h
+25.661 3.733 m
+25.661 -1.014 l
+25.661 -1.654 25.477 -2.153 25.118 -2.514 c
+24.754 -2.866 24.25 -3.043 23.603 -3.043 c
+22.946 -3.043 22.442 -2.874 22.09 -2.529 c
+21.737 -2.176 21.56 -1.673 21.56 -1.014 c
+21.56 3.733 l
+22.398 3.733 l
+22.398 -0.985 l
+22.398 -1.437 22.49 -1.775 22.677 -1.999 c
+22.872 -2.216 23.181 -2.323 23.603 -2.323 c
+24.033 -2.323 24.342 -2.216 24.529 -1.999 c
+24.725 -1.775 24.823 -1.437 24.823 -0.985 c
+24.823 3.733 l
+h
+26.878 -3.528 m
+26.186 -3.528 l
+28.524 3.733 l
+29.215 3.733 l
+h
+30.964 -2.234 m
+33.581 -2.234 l
+33.581 -2.955 l
+30.111 -2.955 l
+30.111 3.733 l
+30.964 3.733 l
+h
+35.16 -2.955 -0.808 4.968 re
+35.219 3.337 m
+35.219 3.197 35.179 3.079 35.102 2.984 c
+35.032 2.896 34.917 2.851 34.763 2.851 c
+34.605 2.851 34.488 2.896 34.41 2.984 c
+34.341 3.079 34.308 3.197 34.308 3.337 c
+34.308 3.472 34.341 3.586 34.41 3.675 c
+34.488 3.77 34.602 3.821 34.749 3.821 c
+34.903 3.821 35.021 3.77 35.102 3.675 c
+35.179 3.586 35.219 3.472 35.219 3.337 c
+37.108 2.013 m
+37.138 1.484 l
+37.45 1.896 37.851 2.102 38.343 2.102 c
+39.225 2.102 39.669 1.517 39.68 0.353 c
+39.68 -2.955 l
+38.872 -2.955 l
+38.872 0.309 l
+38.872 0.698 38.805 0.974 38.68 1.132 c
+38.552 1.297 38.358 1.381 38.092 1.381 c
+37.887 1.381 37.703 1.311 37.549 1.176 c
+37.391 1.047 37.263 0.874 37.167 0.661 c
+37.167 -2.955 l
+36.344 -2.955 l
+36.344 2.013 l
+h
+43.26 -2.514 m
+42.984 -2.866 42.587 -3.043 42.069 -3.043 c
+41.628 -3.043 41.29 -2.893 41.055 -2.587 c
+40.827 -2.275 40.71 -1.819 40.702 -1.22 c
+40.702 2.013 l
+41.51 2.013 l
+41.51 -1.162 l
+41.51 -1.937 41.745 -2.323 42.216 -2.323 c
+42.705 -2.323 43.043 -2.103 43.23 -1.661 c
+43.23 2.013 l
+44.053 2.013 l
+44.053 -2.955 l
+43.274 -2.955 l
+h
+46.53 0.205 m
+47.382 2.013 l
+48.323 2.013 l
+46.971 -0.441 l
+48.353 -2.955 l
+47.426 -2.955 l
+46.545 -1.088 l
+45.663 -2.955 l
+44.722 -2.955 l
+46.104 -0.441 l
+44.766 2.013 l
+45.693 2.013 l
+h
+51.208 -0.25 m
+51.208 0.521 51.347 1.105 51.634 1.499 c
+51.918 1.899 52.329 2.102 52.87 2.102 c
+53.34 2.102 53.707 1.911 53.971 1.529 c
+53.971 4.101 l
+54.794 4.101 l
+54.794 -2.955 l
+54.045 -2.955 l
+54.001 -2.425 l
+53.736 -2.837 53.358 -3.043 52.87 -3.043 c
+52.347 -3.043 51.943 -2.849 51.649 -2.455 c
+51.355 -2.055 51.208 -1.484 51.208 -0.75 c
+h
+52.016 -0.706 m
+52.016 -1.264 52.097 -1.676 52.267 -1.941 c
+52.432 -2.198 52.7 -2.323 53.075 -2.323 c
+53.475 -2.323 53.773 -2.124 53.971 -1.72 c
+53.971 0.793 l
+53.766 1.182 53.464 1.381 53.075 1.381 c
+52.7 1.381 52.432 1.249 52.267 0.985 c
+52.097 0.727 52.016 0.33 52.016 -0.206 c
+h
+56.731 -2.955 -0.808 4.968 re
+56.79 3.337 m
+56.79 3.197 56.749 3.079 56.672 2.984 c
+56.602 2.896 56.489 2.851 56.334 2.851 c
+56.176 2.851 56.059 2.896 55.982 2.984 c
+55.912 3.079 55.879 3.197 55.879 3.337 c
+55.879 3.472 55.912 3.586 55.982 3.675 c
+56.059 3.77 56.172 3.821 56.319 3.821 c
+56.474 3.821 56.592 3.77 56.672 3.675 c
+56.749 3.586 56.79 3.472 56.79 3.337 c
+60.34 -1.676 m
+60.34 -1.511 60.27 -1.364 60.134 -1.235 c
+60.005 -1.11 59.752 -0.963 59.37 -0.794 c
+58.936 -0.611 58.628 -0.452 58.443 -0.324 c
+58.268 -0.198 58.135 -0.055 58.046 0.103 c
+57.959 0.268 57.915 0.463 57.915 0.691 c
+57.915 1.103 58.061 1.44 58.356 1.705 c
+58.649 1.969 59.024 2.102 59.488 2.102 c
+59.976 2.102 60.369 1.959 60.664 1.675 c
+60.957 1.4 61.104 1.043 61.104 0.602 c
+60.296 0.602 l
+60.296 0.827 60.215 1.018 60.061 1.176 c
+59.914 1.33 59.723 1.411 59.488 1.411 c
+59.253 1.411 59.064 1.344 58.929 1.22 c
+58.789 1.103 58.723 0.933 58.723 0.72 c
+58.723 0.551 58.771 0.419 58.87 0.323 c
+58.966 0.224 59.208 0.091 59.59 -0.073 c
+60.197 -0.309 60.608 -0.541 60.825 -0.765 c
+61.038 -0.992 61.148 -1.276 61.148 -1.617 c
+61.148 -2.051 60.994 -2.396 60.693 -2.66 c
+60.398 -2.918 60.002 -3.043 59.502 -3.043 c
+58.991 -3.043 58.576 -2.896 58.252 -2.602 c
+57.929 -2.308 57.768 -1.933 57.768 -1.47 c
+58.591 -1.47 l
+58.598 -1.746 58.682 -1.962 58.84 -2.117 c
+58.995 -2.275 59.216 -2.352 59.502 -2.352 c
+59.774 -2.352 59.98 -2.293 60.12 -2.176 c
+60.267 -2.051 60.34 -1.881 60.34 -1.676 c
+63.096 3.219 m
+63.096 2.013 l
+63.845 2.013 l
+63.845 1.352 l
+63.096 1.352 l
+63.096 -1.72 l
+63.096 -1.918 63.126 -2.07 63.184 -2.176 c
+63.251 -2.275 63.364 -2.323 63.523 -2.323 c
+63.629 -2.323 63.735 -2.305 63.845 -2.264 c
+63.831 -2.955 l
+63.654 -3.013 63.467 -3.043 63.272 -3.043 c
+62.949 -3.043 62.703 -2.933 62.538 -2.705 c
+62.368 -2.469 62.287 -2.147 62.287 -1.735 c
+62.287 1.352 l
+61.523 1.352 l
+61.523 2.013 l
+62.287 2.013 l
+62.287 3.219 l
+h
+66.745 1.249 m
+66.627 1.267 66.503 1.278 66.378 1.278 c
+65.955 1.278 65.665 1.051 65.51 0.602 c
+65.51 -2.955 l
+64.687 -2.955 l
+64.687 2.013 l
+65.481 2.013 l
+65.495 1.514 l
+65.709 1.903 66.017 2.102 66.422 2.102 c
+66.547 2.102 66.657 2.08 66.745 2.043 c
+h
+68.321 -2.955 -0.808 4.968 re
+68.38 3.337 m
+68.38 3.197 68.34 3.079 68.263 2.984 c
+68.193 2.896 68.078 2.851 67.924 2.851 c
+67.766 2.851 67.649 2.896 67.571 2.984 c
+67.502 3.079 67.469 3.197 67.469 3.337 c
+67.469 3.472 67.502 3.586 67.571 3.675 c
+67.649 3.77 67.763 3.821 67.91 3.821 c
+68.064 3.821 68.182 3.77 68.263 3.675 c
+68.34 3.586 68.38 3.472 68.38 3.337 c
+73.102 -0.706 m
+73.102 -1.482 72.959 -2.066 72.676 -2.455 c
+72.4 -2.849 72 -3.043 71.471 -3.043 c
+70.949 -3.043 70.559 -2.818 70.295 -2.367 c
+70.251 -2.955 l
+69.516 -2.955 l
+69.516 4.101 l
+70.324 4.101 l
+70.324 1.469 l
+70.588 1.888 70.971 2.102 71.471 2.102 c
+72.007 2.102 72.415 1.911 72.691 1.529 c
+72.963 1.146 73.102 0.562 73.102 -0.221 c
+h
+72.294 -0.25 m
+72.294 0.338 72.209 0.753 72.044 0.999 c
+71.886 1.253 71.621 1.381 71.251 1.381 c
+70.839 1.381 70.53 1.153 70.324 0.706 c
+70.324 -1.661 l
+70.519 -2.103 70.831 -2.323 71.265 -2.323 c
+71.625 -2.323 71.886 -2.198 72.044 -1.941 c
+72.209 -1.687 72.294 -1.29 72.294 -0.75 c
+h
+76.508 -2.514 m
+76.233 -2.866 75.837 -3.043 75.318 -3.043 c
+74.877 -3.043 74.54 -2.893 74.304 -2.587 c
+74.076 -2.275 73.958 -1.819 73.952 -1.22 c
+73.952 2.013 l
+74.76 2.013 l
+74.76 -1.162 l
+74.76 -1.937 74.995 -2.323 75.465 -2.323 c
+75.954 -2.323 76.292 -2.103 76.479 -1.661 c
+76.479 2.013 l
+77.302 2.013 l
+77.302 -2.955 l
+76.523 -2.955 l
+h
+79.412 3.219 m
+79.412 2.013 l
+80.161 2.013 l
+80.161 1.352 l
+79.412 1.352 l
+79.412 -1.72 l
+79.412 -1.918 79.442 -2.07 79.5 -2.176 c
+79.566 -2.275 79.681 -2.323 79.838 -2.323 c
+79.945 -2.323 80.051 -2.305 80.161 -2.264 c
+80.147 -2.955 l
+79.97 -3.013 79.783 -3.043 79.589 -3.043 c
+79.265 -3.043 79.018 -2.933 78.854 -2.705 c
+78.684 -2.469 78.604 -2.147 78.604 -1.735 c
+78.604 1.352 l
+77.839 1.352 l
+77.839 2.013 l
+78.604 2.013 l
+78.604 3.219 l
+h
+81.885 -2.955 -0.808 4.968 re
+81.944 3.337 m
+81.944 3.197 81.904 3.079 81.826 2.984 c
+81.757 2.896 81.642 2.851 81.488 2.851 c
+81.33 2.851 81.212 2.896 81.135 2.984 c
+81.065 3.079 81.032 3.197 81.032 3.337 c
+81.032 3.472 81.065 3.586 81.135 3.675 c
+81.212 3.77 81.327 3.821 81.474 3.821 c
+81.628 3.821 81.746 3.77 81.826 3.675 c
+81.904 3.586 81.944 3.472 81.944 3.337 c
+82.903 -0.235 m
+82.903 0.477 83.072 1.047 83.417 1.469 c
+83.77 1.888 84.233 2.102 84.814 2.102 c
+85.391 2.102 85.85 1.896 86.195 1.484 c
+86.548 1.08 86.729 0.521 86.739 -0.191 c
+86.739 -0.706 l
+86.739 -1.434 86.563 -2.007 86.21 -2.425 c
+85.865 -2.837 85.405 -3.043 84.828 -3.043 c
+84.248 -3.043 83.785 -2.845 83.432 -2.44 c
+83.087 -2.029 82.91 -1.478 82.903 -0.779 c
+h
+83.712 -0.706 m
+83.712 -1.216 83.807 -1.617 84.005 -1.912 c
+84.211 -2.205 84.483 -2.352 84.828 -2.352 c
+85.542 -2.352 85.909 -1.834 85.931 -0.794 c
+85.931 -0.235 l
+85.931 0.272 85.828 0.675 85.622 0.97 c
+85.424 1.263 85.156 1.411 84.814 1.411 c
+84.479 1.411 84.211 1.263 84.005 0.97 c
+83.807 0.675 83.712 0.272 83.712 -0.235 c
+h
+88.364 2.013 m
+88.393 1.484 l
+88.705 1.896 89.106 2.102 89.598 2.102 c
+90.48 2.102 90.925 1.517 90.936 0.353 c
+90.936 -2.955 l
+90.128 -2.955 l
+90.128 0.309 l
+90.128 0.698 90.062 0.974 89.937 1.132 c
+89.808 1.297 89.613 1.381 89.349 1.381 c
+89.143 1.381 88.959 1.311 88.805 1.176 c
+88.647 1.047 88.518 0.874 88.422 0.661 c
+88.422 -2.955 l
+87.599 -2.955 l
+87.599 2.013 l
+h
+94.398 -1.676 m
+94.398 -1.511 94.328 -1.364 94.192 -1.235 c
+94.064 -1.11 93.81 -0.963 93.428 -0.794 c
+92.994 -0.611 92.685 -0.452 92.501 -0.324 c
+92.325 -0.198 92.192 -0.055 92.105 0.103 c
+92.017 0.268 91.972 0.463 91.972 0.691 c
+91.972 1.103 92.119 1.44 92.414 1.705 c
+92.707 1.969 93.082 2.102 93.545 2.102 c
+94.034 2.102 94.427 1.959 94.721 1.675 c
+95.015 1.4 95.162 1.043 95.162 0.602 c
+94.353 0.602 l
+94.353 0.827 94.272 1.018 94.118 1.176 c
+93.971 1.33 93.78 1.411 93.545 1.411 c
+93.31 1.411 93.123 1.344 92.986 1.22 c
+92.847 1.103 92.78 0.933 92.78 0.72 c
+92.78 0.551 92.828 0.419 92.928 0.323 c
+93.023 0.224 93.266 0.091 93.648 -0.073 c
+94.255 -0.309 94.666 -0.541 94.883 -0.765 c
+95.096 -0.992 95.206 -1.276 95.206 -1.617 c
+95.206 -2.051 95.051 -2.396 94.75 -2.66 c
+94.457 -2.918 94.06 -3.043 93.559 -3.043 c
+93.049 -3.043 92.634 -2.896 92.31 -2.602 c
+91.987 -2.308 91.826 -1.933 91.826 -1.47 c
+92.649 -1.47 l
+92.655 -1.746 92.74 -1.962 92.898 -2.117 c
+93.052 -2.275 93.273 -2.352 93.559 -2.352 c
+93.831 -2.352 94.037 -2.293 94.177 -2.176 c
+94.324 -2.051 94.398 -1.881 94.398 -1.676 c
+102.699 -2.117 m
+102.552 -2.308 l
+102.13 -2.801 101.512 -3.043 100.7 -3.043 c
+99.972 -3.043 99.406 -2.804 98.995 -2.323 c
+98.583 -1.845 98.37 -1.169 98.363 -0.294 c
+98.363 1.014 l
+98.363 1.955 98.546 2.653 98.922 3.116 c
+99.292 3.586 99.855 3.821 100.612 3.821 c
+101.247 3.821 101.744 3.645 102.097 3.293 c
+102.456 2.94 102.658 2.433 102.699 1.778 c
+101.861 1.778 l
+101.821 2.19 101.703 2.514 101.509 2.749 c
+101.31 2.984 101.012 3.102 100.612 3.102 c
+100.13 3.102 99.778 2.944 99.553 2.631 c
+99.325 2.315 99.208 1.815 99.201 1.132 c
+99.201 -0.235 l
+99.201 -0.912 99.325 -1.434 99.583 -1.794 c
+99.847 -2.147 100.219 -2.323 100.7 -2.323 c
+101.148 -2.323 101.494 -2.216 101.729 -1.999 c
+101.861 -1.881 l
+101.861 -0.339 l
+100.626 -0.339 l
+100.626 0.382 l
+102.699 0.382 l
+h
+104.617 -2.955 -0.808 4.968 re
+104.676 3.337 m
+104.676 3.197 104.636 3.079 104.558 2.984 c
+104.489 2.896 104.375 2.851 104.22 2.851 c
+104.062 2.851 103.944 2.896 103.867 2.984 c
+103.797 3.079 103.765 3.197 103.765 3.337 c
+103.765 3.472 103.797 3.586 103.867 3.675 c
+103.944 3.77 104.059 3.821 104.206 3.821 c
+104.36 3.821 104.478 3.77 104.558 3.675 c
+104.636 3.586 104.676 3.472 104.676 3.337 c
+106.874 3.219 m
+106.874 2.013 l
+107.623 2.013 l
+107.623 1.352 l
+106.874 1.352 l
+106.874 -1.72 l
+106.874 -1.918 106.903 -2.07 106.962 -2.176 c
+107.028 -2.275 107.142 -2.323 107.3 -2.323 c
+107.406 -2.323 107.512 -2.305 107.623 -2.264 c
+107.608 -2.955 l
+107.432 -3.013 107.244 -3.043 107.05 -3.043 c
+106.727 -3.043 106.48 -2.933 106.315 -2.705 c
+106.146 -2.469 106.065 -2.147 106.065 -1.735 c
+106.065 1.352 l
+105.301 1.352 l
+105.301 2.013 l
+106.065 2.013 l
+106.065 3.219 l
+h
+113.197 -1.676 m
+113.197 -1.511 113.128 -1.364 112.992 -1.235 c
+112.863 -1.11 112.609 -0.963 112.227 -0.794 c
+111.794 -0.611 111.485 -0.452 111.302 -0.324 c
+111.125 -0.198 110.993 -0.055 110.905 0.103 c
+110.816 0.268 110.772 0.463 110.772 0.691 c
+110.772 1.103 110.92 1.44 111.213 1.705 c
+111.508 1.969 111.882 2.102 112.345 2.102 c
+112.834 2.102 113.227 1.959 113.521 1.675 c
+113.815 1.4 113.962 1.043 113.962 0.602 c
+113.154 0.602 l
+113.154 0.827 113.073 1.018 112.919 1.176 c
+112.771 1.33 112.58 1.411 112.345 1.411 c
+112.11 1.411 111.923 1.344 111.786 1.22 c
+111.647 1.103 111.581 0.933 111.581 0.72 c
+111.581 0.551 111.628 0.419 111.728 0.323 c
+111.823 0.224 112.066 0.091 112.448 -0.073 c
+113.054 -0.309 113.466 -0.541 113.683 -0.765 c
+113.896 -0.992 114.006 -1.276 114.006 -1.617 c
+114.006 -2.051 113.852 -2.396 113.55 -2.66 c
+113.257 -2.918 112.86 -3.043 112.36 -3.043 c
+111.849 -3.043 111.433 -2.896 111.111 -2.602 c
+110.787 -2.308 110.625 -1.933 110.625 -1.47 c
+111.448 -1.47 l
+111.456 -1.746 111.541 -1.962 111.699 -2.117 c
+111.853 -2.275 112.073 -2.352 112.36 -2.352 c
+112.632 -2.352 112.838 -2.293 112.977 -2.176 c
+113.124 -2.051 113.197 -1.881 113.197 -1.676 c
+115.703 1.499 m
+116.005 1.899 116.399 2.102 116.879 2.102 c
+117.762 2.102 118.207 1.517 118.217 0.353 c
+118.217 -2.955 l
+117.409 -2.955 l
+117.409 0.309 l
+117.409 0.698 117.343 0.974 117.218 1.132 c
+117.089 1.297 116.894 1.381 116.63 1.381 c
+116.424 1.381 116.241 1.311 116.086 1.176 c
+115.928 1.047 115.799 0.874 115.703 0.661 c
+115.703 -2.955 l
+114.88 -2.955 l
+114.88 4.101 l
+115.703 4.101 l
+h
+119.077 -0.235 m
+119.077 0.477 119.246 1.047 119.591 1.469 c
+119.944 1.888 120.407 2.102 120.989 2.102 c
+121.565 2.102 122.024 1.896 122.37 1.484 c
+122.722 1.08 122.903 0.521 122.914 -0.191 c
+122.914 -0.706 l
+122.914 -1.434 122.737 -2.007 122.385 -2.425 c
+122.039 -2.837 121.58 -3.043 121.003 -3.043 c
+120.422 -3.043 119.959 -2.845 119.607 -2.44 c
+119.261 -2.029 119.084 -1.478 119.077 -0.779 c
+h
+119.886 -0.706 m
+119.886 -1.216 119.981 -1.617 120.179 -1.912 c
+120.385 -2.205 120.657 -2.352 121.003 -2.352 c
+121.716 -2.352 122.084 -1.834 122.105 -0.794 c
+122.105 -0.235 l
+122.105 0.272 122.003 0.675 121.797 0.97 c
+121.598 1.263 121.33 1.411 120.989 1.411 c
+120.654 1.411 120.385 1.263 120.179 0.97 c
+119.981 0.675 119.886 0.272 119.886 -0.235 c
+h
+126.317 -2.514 m
+126.041 -2.866 125.644 -3.043 125.126 -3.043 c
+124.685 -3.043 124.347 -2.893 124.112 -2.587 c
+123.884 -2.275 123.767 -1.819 123.759 -1.22 c
+123.759 2.013 l
+124.567 2.013 l
+124.567 -1.162 l
+124.567 -1.937 124.802 -2.323 125.273 -2.323 c
+125.762 -2.323 126.1 -2.103 126.287 -1.661 c
+126.287 2.013 l
+127.11 2.013 l
+127.11 -2.955 l
+126.331 -2.955 l
+h
+129.029 -2.955 -0.809 7.056 re
+130.05 -0.25 m
+130.05 0.521 130.19 1.105 130.477 1.499 c
+130.759 1.899 131.171 2.102 131.711 2.102 c
+132.181 2.102 132.549 1.911 132.814 1.529 c
+132.814 4.101 l
+133.637 4.101 l
+133.637 -2.955 l
+132.887 -2.955 l
+132.843 -2.425 l
+132.578 -2.837 132.2 -3.043 131.711 -3.043 c
+131.189 -3.043 130.785 -2.849 130.491 -2.455 c
+130.197 -2.055 130.05 -1.484 130.05 -0.75 c
+h
+130.859 -0.706 m
+130.859 -1.264 130.94 -1.676 131.108 -1.941 c
+131.274 -2.198 131.542 -2.323 131.917 -2.323 c
+132.318 -2.323 132.615 -2.124 132.814 -1.72 c
+132.814 0.793 l
+132.608 1.182 132.307 1.381 131.917 1.381 c
+131.542 1.381 131.274 1.249 131.108 0.985 c
+130.94 0.727 130.859 0.33 130.859 -0.206 c
+h
+140.6 -0.706 m
+140.6 -1.482 140.457 -2.066 140.174 -2.455 c
+139.898 -2.849 139.498 -3.043 138.969 -3.043 c
+138.447 -3.043 138.057 -2.818 137.793 -2.367 c
+137.749 -2.955 l
+137.014 -2.955 l
+137.014 4.101 l
+137.822 4.101 l
+137.822 1.469 l
+138.086 1.888 138.469 2.102 138.969 2.102 c
+139.505 2.102 139.913 1.911 140.189 1.529 c
+140.461 1.146 140.6 0.562 140.6 -0.221 c
+h
+139.792 -0.25 m
+139.792 0.338 139.707 0.753 139.542 0.999 c
+139.384 1.253 139.119 1.381 138.749 1.381 c
+138.337 1.381 138.028 1.153 137.822 0.706 c
+137.822 -1.661 l
+138.017 -2.103 138.329 -2.323 138.763 -2.323 c
+139.123 -2.323 139.384 -2.198 139.542 -1.941 c
+139.707 -1.687 139.792 -1.29 139.792 -0.75 c
+h
+143.243 -3.043 m
+142.626 -3.043 142.148 -2.863 141.816 -2.5 c
+141.494 -2.128 141.325 -1.584 141.317 -0.867 c
+141.317 -0.265 l
+141.317 0.47 141.479 1.047 141.802 1.469 c
+142.125 1.888 142.574 2.102 143.154 2.102 c
+143.731 2.102 144.161 1.914 144.448 1.543 c
+144.742 1.18 144.893 0.606 144.904 -0.177 c
+144.904 -0.706 l
+142.125 -0.706 l
+142.125 -0.823 l
+142.125 -1.364 142.221 -1.757 142.42 -1.999 c
+142.626 -2.234 142.911 -2.352 143.287 -2.352 c
+143.53 -2.352 143.742 -2.308 143.919 -2.22 c
+144.103 -2.132 144.276 -1.992 144.434 -1.794 c
+144.86 -2.308 l
+144.507 -2.801 143.966 -3.043 143.243 -3.043 c
+143.154 1.411 m
+142.82 1.411 142.57 1.294 142.404 1.058 c
+142.236 0.83 142.144 0.474 142.125 -0.015 c
+144.081 -0.015 l
+144.081 0.103 l
+144.058 0.573 143.977 0.904 143.831 1.103 c
+143.684 1.308 143.455 1.411 143.154 1.411 c
+150.562 -2.955 m
+150.511 -2.849 150.478 -2.668 150.46 -2.411 c
+150.173 -2.833 149.805 -3.043 149.357 -3.043 c
+148.905 -3.043 148.552 -2.922 148.299 -2.675 c
+148.053 -2.422 147.931 -2.066 147.931 -1.602 c
+147.931 -1.095 148.101 -0.691 148.446 -0.397 c
+148.787 -0.103 149.258 0.047 149.857 0.058 c
+150.445 0.058 l
+150.445 0.588 l
+150.445 0.882 150.375 1.091 150.239 1.22 c
+150.111 1.344 149.916 1.411 149.651 1.411 c
+149.405 1.411 149.203 1.338 149.049 1.19 c
+148.902 1.043 148.828 0.856 148.828 0.632 c
+148.005 0.632 l
+148.005 0.885 148.079 1.132 148.226 1.367 c
+148.38 1.602 148.586 1.782 148.843 1.911 c
+149.097 2.036 149.379 2.102 149.695 2.102 c
+150.202 2.102 150.592 1.973 150.857 1.72 c
+151.121 1.473 151.254 1.105 151.254 0.617 c
+151.254 -1.881 l
+151.261 -2.264 151.316 -2.598 151.415 -2.881 c
+151.415 -2.955 l
+h
+149.49 -2.308 m
+149.685 -2.308 149.872 -2.257 150.048 -2.147 c
+150.232 -2.029 150.364 -1.893 150.445 -1.735 c
+150.445 -0.544 l
+149.99 -0.544 l
+149.608 -0.555 149.302 -0.643 149.078 -0.809 c
+148.85 -0.977 148.74 -1.206 148.74 -1.5 c
+148.74 -1.786 148.791 -1.992 148.902 -2.117 c
+149.02 -2.246 149.214 -2.308 149.49 -2.308 c
+153.668 -1.72 m
+154.609 2.013 l
+155.447 2.013 l
+153.961 -2.955 l
+153.359 -2.955 l
+151.86 2.013 l
+152.698 2.013 l
+h
+158.607 -2.955 m
+158.555 -2.849 158.522 -2.668 158.504 -2.411 c
+158.217 -2.833 157.849 -3.043 157.402 -3.043 c
+156.949 -3.043 156.596 -2.922 156.343 -2.675 c
+156.097 -2.422 155.976 -2.066 155.976 -1.602 c
+155.976 -1.095 156.145 -0.691 156.49 -0.397 c
+156.832 -0.103 157.302 0.047 157.901 0.058 c
+158.489 0.058 l
+158.489 0.588 l
+158.489 0.882 158.42 1.091 158.283 1.22 c
+158.154 1.344 157.96 1.411 157.695 1.411 c
+157.449 1.411 157.247 1.338 157.093 1.19 c
+156.945 1.043 156.872 0.856 156.872 0.632 c
+156.049 0.632 l
+156.049 0.885 156.122 1.132 156.27 1.367 c
+156.424 1.602 156.629 1.782 156.887 1.911 c
+157.14 2.036 157.423 2.102 157.739 2.102 c
+158.247 2.102 158.636 1.973 158.9 1.72 c
+159.166 1.473 159.297 1.105 159.297 0.617 c
+159.297 -1.881 l
+159.305 -2.264 159.36 -2.598 159.459 -2.881 c
+159.459 -2.955 l
+h
+157.533 -2.308 m
+157.728 -2.308 157.916 -2.257 158.092 -2.147 c
+158.276 -2.029 158.408 -1.893 158.489 -1.735 c
+158.489 -0.544 l
+158.034 -0.544 l
+157.651 -0.555 157.346 -0.643 157.122 -0.809 c
+156.895 -0.977 156.784 -1.206 156.784 -1.5 c
+156.784 -1.786 156.835 -1.992 156.945 -2.117 c
+157.063 -2.246 157.258 -2.308 157.533 -2.308 c
+161.252 -2.955 -0.808 4.968 re
+161.311 3.337 m
+161.311 3.197 161.271 3.079 161.194 2.984 c
+161.124 2.896 161.01 2.851 160.856 2.851 c
+160.698 2.851 160.581 2.896 160.503 2.984 c
+160.433 3.079 160.4 3.197 160.4 3.337 c
+160.4 3.472 160.433 3.586 160.503 3.675 c
+160.581 3.77 160.694 3.821 160.841 3.821 c
+160.995 3.821 161.113 3.77 161.194 3.675 c
+161.271 3.586 161.311 3.472 161.311 3.337 c
+163.314 -2.955 -0.809 7.056 re
+167.055 -2.955 m
+167.004 -2.849 166.971 -2.668 166.952 -2.411 c
+166.665 -2.833 166.298 -3.043 165.85 -3.043 c
+165.398 -3.043 165.045 -2.922 164.791 -2.675 c
+164.545 -2.422 164.424 -2.066 164.424 -1.602 c
+164.424 -1.095 164.593 -0.691 164.938 -0.397 c
+165.28 -0.103 165.751 0.047 166.349 0.058 c
+166.937 0.058 l
+166.937 0.588 l
+166.937 0.882 166.867 1.091 166.732 1.22 c
+166.603 1.344 166.408 1.411 166.144 1.411 c
+165.898 1.411 165.695 1.338 165.541 1.19 c
+165.394 1.043 165.321 0.856 165.321 0.632 c
+164.498 0.632 l
+164.498 0.885 164.571 1.132 164.718 1.367 c
+164.872 1.602 165.078 1.782 165.335 1.911 c
+165.589 2.036 165.872 2.102 166.188 2.102 c
+166.695 2.102 167.085 1.973 167.349 1.72 c
+167.613 1.473 167.746 1.105 167.746 0.617 c
+167.746 -1.881 l
+167.754 -2.264 167.808 -2.598 167.908 -2.881 c
+167.908 -2.955 l
+h
+165.982 -2.308 m
+166.177 -2.308 166.364 -2.257 166.541 -2.147 c
+166.724 -2.029 166.856 -1.893 166.937 -1.735 c
+166.937 -0.544 l
+166.482 -0.544 l
+166.1 -0.555 165.795 -0.643 165.57 -0.809 c
+165.342 -0.977 165.232 -1.206 165.232 -1.5 c
+165.232 -1.786 165.284 -1.992 165.394 -2.117 c
+165.512 -2.246 165.707 -2.308 165.982 -2.308 c
+172.421 -0.706 m
+172.421 -1.482 172.277 -2.066 171.994 -2.455 c
+171.718 -2.849 171.318 -3.043 170.788 -3.043 c
+170.266 -3.043 169.877 -2.818 169.612 -2.367 c
+169.568 -2.955 l
+168.834 -2.955 l
+168.834 4.101 l
+169.642 4.101 l
+169.642 1.469 l
+169.907 1.888 170.289 2.102 170.788 2.102 c
+171.325 2.102 171.733 1.911 172.009 1.529 c
+172.28 1.146 172.421 0.562 172.421 -0.221 c
+h
+171.612 -0.25 m
+171.612 0.338 171.527 0.753 171.362 0.999 c
+171.204 1.253 170.939 1.381 170.568 1.381 c
+170.156 1.381 169.848 1.153 169.642 0.706 c
+169.642 -1.661 l
+169.836 -2.103 170.149 -2.323 170.582 -2.323 c
+170.943 -2.323 171.204 -2.198 171.362 -1.941 c
+171.527 -1.687 171.612 -1.29 171.612 -0.75 c
+h
+174.162 -2.955 -0.808 7.056 re
+177.124 -3.043 m
+176.506 -3.043 176.028 -2.863 175.698 -2.5 c
+175.375 -2.128 175.205 -1.584 175.199 -0.867 c
+175.199 -0.265 l
+175.199 0.47 175.36 1.047 175.683 1.469 c
+176.007 1.888 176.455 2.102 177.036 2.102 c
+177.613 2.102 178.042 1.914 178.329 1.543 c
+178.623 1.18 178.773 0.606 178.785 -0.177 c
+178.785 -0.706 l
+176.007 -0.706 l
+176.007 -0.823 l
+176.007 -1.364 176.103 -1.757 176.301 -1.999 c
+176.506 -2.234 176.793 -2.352 177.168 -2.352 c
+177.41 -2.352 177.624 -2.308 177.8 -2.22 c
+177.984 -2.132 178.156 -1.992 178.314 -1.794 c
+178.74 -2.308 l
+178.388 -2.801 177.848 -3.043 177.124 -3.043 c
+177.036 1.411 m
+176.701 1.411 176.452 1.294 176.286 1.058 c
+176.117 0.83 176.026 0.474 176.007 -0.015 c
+177.962 -0.015 l
+177.962 0.103 l
+177.94 0.573 177.859 0.904 177.712 1.103 c
+177.565 1.308 177.337 1.411 177.036 1.411 c
+182.769 -2.955 -0.809 4.968 re
+182.827 3.337 m
+182.827 3.197 182.787 3.079 182.709 2.984 c
+182.64 2.896 182.526 2.851 182.372 2.851 c
+182.214 2.851 182.096 2.896 182.019 2.984 c
+181.948 3.079 181.915 3.197 181.915 3.337 c
+181.915 3.472 181.948 3.586 182.019 3.675 c
+182.096 3.77 182.21 3.821 182.357 3.821 c
+182.511 3.821 182.629 3.77 182.709 3.675 c
+182.787 3.586 182.827 3.472 182.827 3.337 c
+184.716 2.013 m
+184.745 1.484 l
+185.058 1.896 185.458 2.102 185.95 2.102 c
+186.833 2.102 187.277 1.517 187.288 0.353 c
+187.288 -2.955 l
+186.48 -2.955 l
+186.48 0.309 l
+186.48 0.698 186.414 0.974 186.289 1.132 c
+186.16 1.297 185.965 1.381 185.701 1.381 c
+185.495 1.381 185.312 1.311 185.157 1.176 c
+184.999 1.047 184.87 0.874 184.774 0.661 c
+184.774 -2.955 l
+183.951 -2.955 l
+183.951 2.013 l
+h
+191.706 3.219 m
+191.706 2.013 l
+192.455 2.013 l
+192.455 1.352 l
+191.706 1.352 l
+191.706 -1.72 l
+191.706 -1.918 191.735 -2.07 191.793 -2.176 c
+191.86 -2.275 191.974 -2.323 192.132 -2.323 c
+192.238 -2.323 192.345 -2.305 192.455 -2.264 c
+192.44 -2.955 l
+192.264 -3.013 192.076 -3.043 191.882 -3.043 c
+191.558 -3.043 191.313 -2.933 191.147 -2.705 c
+190.978 -2.469 190.897 -2.147 190.897 -1.735 c
+190.897 1.352 l
+190.133 1.352 l
+190.133 2.013 l
+190.897 2.013 l
+190.897 3.219 l
+h
+194.12 1.499 m
+194.421 1.899 194.814 2.102 195.296 2.102 c
+196.177 2.102 196.622 1.517 196.633 0.353 c
+196.633 -2.955 l
+195.824 -2.955 l
+195.824 0.309 l
+195.824 0.698 195.758 0.974 195.633 1.132 c
+195.505 1.297 195.311 1.381 195.045 1.381 c
+194.84 1.381 194.656 1.311 194.502 1.176 c
+194.344 1.047 194.216 0.874 194.12 0.661 c
+194.12 -2.955 l
+193.297 -2.955 l
+193.297 4.101 l
+194.12 4.101 l
+h
+199.433 -3.043 m
+198.816 -3.043 198.338 -2.863 198.008 -2.5 c
+197.684 -2.128 197.515 -1.584 197.508 -0.867 c
+197.508 -0.265 l
+197.508 0.47 197.669 1.047 197.993 1.469 c
+198.316 1.888 198.764 2.102 199.346 2.102 c
+199.922 2.102 200.352 1.914 200.639 1.543 c
+200.933 1.18 201.083 0.606 201.094 -0.177 c
+201.094 -0.706 l
+198.316 -0.706 l
+198.316 -0.823 l
+198.316 -1.364 198.411 -1.757 198.61 -1.999 c
+198.816 -2.234 199.103 -2.352 199.477 -2.352 c
+199.72 -2.352 199.933 -2.308 200.109 -2.22 c
+200.293 -2.132 200.466 -1.992 200.624 -1.794 c
+201.05 -2.308 l
+200.697 -2.801 200.157 -3.043 199.433 -3.043 c
+199.346 1.411 m
+199.011 1.411 198.761 1.294 198.596 1.058 c
+198.426 0.83 198.334 0.474 198.316 -0.015 c
+200.271 -0.015 l
+200.271 0.103 l
+200.25 0.573 200.169 0.904 200.021 1.103 c
+199.874 1.308 199.647 1.411 199.346 1.411 c
+206.621 -1.676 m
+206.621 -1.511 206.552 -1.364 206.415 -1.235 c
+206.287 -1.11 206.033 -0.963 205.651 -0.794 c
+205.218 -0.611 204.909 -0.452 204.725 -0.324 c
+204.549 -0.198 204.416 -0.055 204.329 0.103 c
+204.24 0.268 204.196 0.463 204.196 0.691 c
+204.196 1.103 204.343 1.44 204.637 1.705 c
+204.931 1.969 205.306 2.102 205.769 2.102 c
+206.257 2.102 206.65 1.959 206.945 1.675 c
+207.238 1.4 207.386 1.043 207.386 0.602 c
+206.577 0.602 l
+206.577 0.827 206.496 1.018 206.342 1.176 c
+206.195 1.33 206.004 1.411 205.769 1.411 c
+205.534 1.411 205.346 1.344 205.21 1.22 c
+205.071 1.103 205.004 0.933 205.004 0.72 c
+205.004 0.551 205.052 0.419 205.151 0.323 c
+205.247 0.224 205.49 0.091 205.871 -0.073 c
+206.478 -0.309 206.889 -0.541 207.107 -0.765 c
+207.319 -0.992 207.429 -1.276 207.429 -1.617 c
+207.429 -2.051 207.275 -2.396 206.974 -2.66 c
+206.68 -2.918 206.283 -3.043 205.783 -3.043 c
+205.272 -3.043 204.857 -2.896 204.534 -2.602 c
+204.21 -2.308 204.049 -1.933 204.049 -1.47 c
+204.872 -1.47 l
+204.879 -1.746 204.964 -1.962 205.122 -2.117 c
+205.276 -2.275 205.497 -2.352 205.783 -2.352 c
+206.055 -2.352 206.261 -2.293 206.401 -2.176 c
+206.548 -2.051 206.621 -1.881 206.621 -1.676 c
+209.378 3.219 m
+209.378 2.013 l
+210.127 2.013 l
+210.127 1.352 l
+209.378 1.352 l
+209.378 -1.72 l
+209.378 -1.918 209.407 -2.07 209.465 -2.176 c
+209.532 -2.275 209.646 -2.323 209.804 -2.323 c
+209.91 -2.323 210.016 -2.305 210.127 -2.264 c
+210.112 -2.955 l
+209.935 -3.013 209.748 -3.043 209.553 -3.043 c
+209.23 -3.043 208.984 -2.933 208.819 -2.705 c
+208.649 -2.469 208.569 -2.147 208.569 -1.735 c
+208.569 1.352 l
+207.805 1.352 l
+207.805 2.013 l
+208.569 2.013 l
+208.569 3.219 l
+h
+213.526 -2.955 m
+213.474 -2.849 213.442 -2.668 213.423 -2.411 c
+213.137 -2.833 212.769 -3.043 212.321 -3.043 c
+211.869 -3.043 211.516 -2.922 211.263 -2.675 c
+211.016 -2.422 210.895 -2.066 210.895 -1.602 c
+210.895 -1.095 211.064 -0.691 211.41 -0.397 c
+211.751 -0.103 212.221 0.047 212.821 0.058 c
+213.409 0.058 l
+213.409 0.588 l
+213.409 0.882 213.339 1.091 213.203 1.22 c
+213.074 1.344 212.879 1.411 212.615 1.411 c
+212.368 1.411 212.167 1.338 212.012 1.19 c
+211.865 1.043 211.792 0.856 211.792 0.632 c
+210.968 0.632 l
+210.968 0.885 211.042 1.132 211.188 1.367 c
+211.344 1.602 211.549 1.782 211.807 1.911 c
+212.06 2.036 212.343 2.102 212.659 2.102 c
+213.166 2.102 213.555 1.973 213.82 1.72 c
+214.085 1.473 214.217 1.105 214.217 0.617 c
+214.217 -1.881 l
+214.224 -2.264 214.28 -2.598 214.378 -2.881 c
+214.378 -2.955 l
+h
+212.453 -2.308 m
+212.648 -2.308 212.835 -2.257 213.012 -2.147 c
+213.195 -2.029 213.328 -1.893 213.409 -1.735 c
+213.409 -0.544 l
+212.952 -0.544 l
+212.57 -0.555 212.266 -0.643 212.042 -0.809 c
+211.814 -0.977 211.703 -1.206 211.703 -1.5 c
+211.703 -1.786 211.755 -1.992 211.865 -2.117 c
+211.982 -2.246 212.177 -2.308 212.453 -2.308 c
+216.054 2.013 m
+216.084 1.484 l
+216.396 1.896 216.796 2.102 217.289 2.102 c
+218.171 2.102 218.616 1.517 218.627 0.353 c
+218.627 -2.955 l
+217.818 -2.955 l
+217.818 0.309 l
+217.818 0.698 217.752 0.974 217.627 1.132 c
+217.499 1.297 217.303 1.381 217.039 1.381 c
+216.833 1.381 216.649 1.311 216.495 1.176 c
+216.337 1.047 216.208 0.874 216.113 0.661 c
+216.113 -2.955 l
+215.29 -2.955 l
+215.29 2.013 l
+h
+219.505 -0.25 m
+219.505 0.521 219.645 1.105 219.931 1.499 c
+220.214 1.899 220.626 2.102 221.166 2.102 c
+221.636 2.102 222.004 1.911 222.268 1.529 c
+222.268 4.101 l
+223.092 4.101 l
+223.092 -2.955 l
+222.342 -2.955 l
+222.298 -2.425 l
+222.033 -2.837 221.654 -3.043 221.166 -3.043 c
+220.644 -3.043 220.24 -2.849 219.946 -2.455 c
+219.652 -2.055 219.505 -1.484 219.505 -0.75 c
+h
+220.314 -0.706 m
+220.314 -1.264 220.395 -1.676 220.563 -1.941 c
+220.729 -2.198 220.997 -2.323 221.372 -2.323 c
+221.772 -2.323 222.07 -2.124 222.268 -1.72 c
+222.268 0.793 l
+222.062 1.182 221.761 1.381 221.372 1.381 c
+220.997 1.381 220.729 1.249 220.563 0.985 c
+220.395 0.727 220.314 0.33 220.314 -0.206 c
+h
+226.704 -2.955 m
+226.652 -2.849 226.619 -2.668 226.601 -2.411 c
+226.315 -2.833 225.947 -3.043 225.498 -3.043 c
+225.047 -3.043 224.694 -2.922 224.44 -2.675 c
+224.194 -2.422 224.073 -2.066 224.073 -1.602 c
+224.073 -1.095 224.241 -0.691 224.587 -0.397 c
+224.929 -0.103 225.399 0.047 225.999 0.058 c
+226.587 0.058 l
+226.587 0.588 l
+226.587 0.882 226.516 1.091 226.38 1.22 c
+226.252 1.344 226.057 1.411 225.793 1.411 c
+225.546 1.411 225.344 1.338 225.19 1.19 c
+225.043 1.043 224.969 0.856 224.969 0.632 c
+224.146 0.632 l
+224.146 0.885 224.22 1.132 224.366 1.367 c
+224.521 1.602 224.727 1.782 224.984 1.911 c
+225.237 2.036 225.521 2.102 225.837 2.102 c
+226.344 2.102 226.733 1.973 226.998 1.72 c
+227.262 1.473 227.395 1.105 227.395 0.617 c
+227.395 -1.881 l
+227.402 -2.264 227.457 -2.598 227.556 -2.881 c
+227.556 -2.955 l
+h
+225.631 -2.308 m
+225.825 -2.308 226.013 -2.257 226.19 -2.147 c
+226.373 -2.029 226.506 -1.893 226.587 -1.735 c
+226.587 -0.544 l
+226.13 -0.544 l
+225.748 -0.555 225.443 -0.643 225.22 -0.809 c
+224.991 -0.977 224.881 -1.206 224.881 -1.5 c
+224.881 -1.786 224.933 -1.992 225.043 -2.117 c
+225.16 -2.246 225.355 -2.308 225.631 -2.308 c
+230.525 1.249 m
+230.408 1.267 230.283 1.278 230.159 1.278 c
+229.735 1.278 229.445 1.051 229.291 0.602 c
+229.291 -2.955 l
+228.468 -2.955 l
+228.468 2.013 l
+229.261 2.013 l
+229.276 1.514 l
+229.49 1.903 229.798 2.102 230.202 2.102 c
+230.327 2.102 230.437 2.08 230.525 2.043 c
+h
+230.97 -0.25 m
+230.97 0.521 231.11 1.105 231.396 1.499 c
+231.68 1.899 232.091 2.102 232.631 2.102 c
+233.101 2.102 233.469 1.911 233.733 1.529 c
+233.733 4.101 l
+234.556 4.101 l
+234.556 -2.955 l
+233.807 -2.955 l
+233.763 -2.425 l
+233.498 -2.837 233.12 -3.043 232.631 -3.043 c
+232.11 -3.043 231.705 -2.849 231.412 -2.455 c
+231.117 -2.055 230.97 -1.484 230.97 -0.75 c
+h
+231.778 -0.706 m
+231.778 -1.264 231.859 -1.676 232.029 -1.941 c
+232.194 -2.198 232.462 -2.323 232.837 -2.323 c
+233.238 -2.323 233.535 -2.124 233.733 -1.72 c
+233.733 0.793 l
+233.528 1.182 233.226 1.381 232.837 1.381 c
+232.462 1.381 232.194 1.249 232.029 0.985 c
+231.859 0.727 231.778 0.33 231.778 -0.206 c
+h
+f
+Q
+q 1 0 0 1 538.5375 394.9912 cm
+0 0 m
+0 0.166 -0.071 0.312 -0.206 0.441 c
+-0.335 0.566 -0.588 0.713 -0.971 0.882 c
+-1.405 1.066 -1.713 1.224 -1.896 1.353 c
+-2.073 1.478 -2.205 1.621 -2.294 1.779 c
+-2.382 1.945 -2.426 2.139 -2.426 2.367 c
+-2.426 2.779 -2.278 3.117 -1.985 3.381 c
+-1.69 3.645 -1.316 3.778 -0.853 3.778 c
+-0.364 3.778 0.029 3.635 0.323 3.352 c
+0.617 3.076 0.764 2.72 0.764 2.278 c
+-0.044 2.278 l
+-0.044 2.503 -0.125 2.694 -0.279 2.852 c
+-0.427 3.007 -0.618 3.088 -0.853 3.088 c
+-1.088 3.088 -1.276 3.021 -1.411 2.897 c
+-1.551 2.779 -1.617 2.61 -1.617 2.396 c
+-1.617 2.228 -1.569 2.095 -1.47 1.999 c
+-1.374 1.9 -1.133 1.768 -0.75 1.603 c
+-0.144 1.368 0.268 1.135 0.484 0.912 c
+0.698 0.684 0.808 0.401 0.808 0.059 c
+0.808 -0.374 0.654 -0.72 0.353 -0.984 c
+0.058 -1.242 -0.339 -1.367 -0.838 -1.367 c
+-1.349 -1.367 -1.764 -1.219 -2.087 -0.926 c
+-2.411 -0.631 -2.573 -0.257 -2.573 0.206 c
+-1.75 0.206 l
+-1.742 -0.07 -1.658 -0.286 -1.5 -0.44 c
+-1.345 -0.598 -1.125 -0.675 -0.838 -0.675 c
+-0.566 -0.675 -0.36 -0.617 -0.221 -0.5 c
+-0.074 -0.374 0 -0.205 0 0 c
+3.05 0.074 m
+3.946 3.69 l
+4.814 3.69 l
+3.182 -1.984 l
+3.064 -2.403 2.892 -2.726 2.667 -2.954 c
+2.439 -3.179 2.186 -3.293 1.903 -3.293 c
+1.793 -3.293 1.657 -3.266 1.491 -3.218 c
+1.491 -2.528 l
+1.668 -2.543 l
+1.903 -2.543 2.083 -2.484 2.212 -2.366 c
+2.348 -2.256 2.454 -2.065 2.535 -1.793 c
+2.697 -1.234 l
+1.242 3.69 l
+2.123 3.69 l
+h
+7.867 0 m
+7.867 0.166 7.798 0.312 7.661 0.441 c
+7.532 0.566 7.279 0.713 6.898 0.882 c
+6.464 1.066 6.155 1.224 5.971 1.353 c
+5.795 1.478 5.662 1.621 5.574 1.779 c
+5.486 1.945 5.442 2.139 5.442 2.367 c
+5.442 2.779 5.589 3.117 5.882 3.381 c
+6.177 3.645 6.551 3.778 7.015 3.778 c
+7.503 3.778 7.897 3.635 8.191 3.352 c
+8.485 3.076 8.631 2.72 8.631 2.278 c
+7.823 2.278 l
+7.823 2.503 7.742 2.694 7.588 2.852 c
+7.441 3.007 7.25 3.088 7.015 3.088 c
+6.78 3.088 6.592 3.021 6.456 2.897 c
+6.316 2.779 6.25 2.61 6.25 2.396 c
+6.25 2.228 6.298 2.095 6.397 1.999 c
+6.493 1.9 6.736 1.768 7.118 1.603 c
+7.723 1.368 8.136 1.135 8.352 0.912 c
+8.565 0.684 8.676 0.401 8.676 0.059 c
+8.676 -0.374 8.521 -0.72 8.22 -0.984 c
+7.926 -1.242 7.529 -1.367 7.029 -1.367 c
+6.518 -1.367 6.104 -1.219 5.78 -0.926 c
+5.456 -0.631 5.294 -0.257 5.294 0.206 c
+6.118 0.206 l
+6.125 -0.07 6.21 -0.286 6.368 -0.44 c
+6.522 -0.598 6.742 -0.675 7.029 -0.675 c
+7.301 -0.675 7.507 -0.617 7.646 -0.5 c
+7.794 -0.374 7.867 -0.205 7.867 0 c
+10.624 4.896 m
+10.624 3.69 l
+11.373 3.69 l
+11.373 3.028 l
+10.624 3.028 l
+10.624 -0.043 l
+10.624 -0.242 10.653 -0.393 10.711 -0.5 c
+10.778 -0.598 10.892 -0.646 11.05 -0.646 c
+11.156 -0.646 11.263 -0.628 11.373 -0.588 c
+11.359 -1.278 l
+11.182 -1.337 10.994 -1.367 10.8 -1.367 c
+10.476 -1.367 10.231 -1.257 10.065 -1.028 c
+9.896 -0.793 9.815 -0.47 9.815 -0.058 c
+9.815 3.028 l
+9.051 3.028 l
+9.051 3.69 l
+9.815 3.69 l
+9.815 4.896 l
+h
+13.994 -1.367 m
+13.375 -1.367 12.898 -1.186 12.567 -0.823 c
+12.244 -0.452 12.074 0.092 12.068 0.809 c
+12.068 1.411 l
+12.068 2.147 12.23 2.723 12.552 3.146 c
+12.876 3.564 13.325 3.778 13.905 3.778 c
+14.482 3.778 14.912 3.591 15.199 3.219 c
+15.492 2.856 15.643 2.282 15.654 1.5 c
+15.654 0.971 l
+12.876 0.971 l
+12.876 0.853 l
+12.876 0.312 12.972 -0.081 13.17 -0.323 c
+13.375 -0.558 13.662 -0.675 14.037 -0.675 c
+14.279 -0.675 14.493 -0.631 14.669 -0.544 c
+14.853 -0.455 15.026 -0.316 15.184 -0.118 c
+15.61 -0.631 l
+15.257 -1.124 14.717 -1.367 13.994 -1.367 c
+13.905 3.088 m
+13.57 3.088 13.321 2.97 13.155 2.735 c
+12.986 2.506 12.895 2.151 12.876 1.661 c
+14.831 1.661 l
+14.831 1.779 l
+14.809 2.249 14.728 2.58 14.581 2.779 c
+14.434 2.984 14.206 3.088 13.905 3.088 c
+17.212 3.69 m
+17.242 3.234 l
+17.543 3.595 17.94 3.778 18.432 3.778 c
+18.991 3.778 19.376 3.535 19.594 3.057 c
+19.906 3.535 20.344 3.778 20.901 3.778 c
+21.82 3.778 22.291 3.209 22.312 2.073 c
+22.312 -1.278 l
+21.504 -1.278 l
+21.504 1.999 l
+21.504 2.352 21.435 2.617 21.298 2.793 c
+21.169 2.97 20.953 3.057 20.652 3.057 c
+20.406 3.057 20.203 2.962 20.049 2.779 c
+19.902 2.591 19.814 2.352 19.785 2.058 c
+19.785 -1.278 l
+18.976 -1.278 l
+18.976 2.029 l
+18.965 2.712 18.686 3.057 18.138 3.057 c
+17.726 3.057 17.437 2.852 17.271 2.44 c
+17.271 -1.278 l
+16.463 -1.278 l
+16.463 3.69 l
+h
+28.942 2.926 m
+28.824 2.944 28.699 2.955 28.575 2.955 c
+28.152 2.955 27.862 2.727 27.708 2.278 c
+27.708 -1.278 l
+26.884 -1.278 l
+26.884 3.69 l
+27.677 3.69 l
+27.693 3.19 l
+27.906 3.58 28.215 3.778 28.618 3.778 c
+28.743 3.778 28.853 3.756 28.942 3.72 c
+h
+31.327 -1.367 m
+30.71 -1.367 30.232 -1.186 29.901 -0.823 c
+29.578 -0.452 29.408 0.092 29.401 0.809 c
+29.401 1.411 l
+29.401 2.147 29.563 2.723 29.886 3.146 c
+30.21 3.564 30.658 3.778 31.239 3.778 c
+31.816 3.778 32.246 3.591 32.533 3.219 c
+32.826 2.856 32.977 2.282 32.988 1.5 c
+32.988 0.971 l
+30.21 0.971 l
+30.21 0.853 l
+30.21 0.312 30.305 -0.081 30.503 -0.323 c
+30.71 -0.558 30.996 -0.675 31.371 -0.675 c
+31.614 -0.675 31.827 -0.631 32.003 -0.544 c
+32.186 -0.455 32.36 -0.316 32.518 -0.118 c
+32.944 -0.631 l
+32.591 -1.124 32.051 -1.367 31.327 -1.367 c
+31.239 3.088 m
+30.904 3.088 30.654 2.97 30.489 2.735 c
+30.32 2.506 30.228 2.151 30.21 1.661 c
+32.165 1.661 l
+32.165 1.779 l
+32.142 2.249 32.062 2.58 31.915 2.779 c
+31.768 2.984 31.54 3.088 31.239 3.088 c
+37.383 0.971 m
+37.383 0.184 37.239 -0.404 36.957 -0.793 c
+36.67 -1.176 36.269 -1.367 35.751 -1.367 c
+35.251 -1.367 34.869 -1.182 34.605 -0.808 c
+34.605 -3.189 l
+33.796 -3.189 l
+33.796 3.69 l
+34.532 3.69 l
+34.561 3.146 l
+34.833 3.564 35.226 3.778 35.737 3.778 c
+36.284 3.778 36.692 3.587 36.957 3.205 c
+37.229 2.83 37.372 2.268 37.383 1.515 c
+h
+36.574 1.426 m
+36.574 1.985 36.487 2.396 36.31 2.661 c
+36.14 2.926 35.869 3.057 35.487 3.057 c
+35.093 3.057 34.8 2.866 34.605 2.485 c
+34.605 -0.103 l
+34.8 -0.484 35.097 -0.675 35.502 -0.675 c
+35.862 -0.675 36.126 -0.544 36.296 -0.278 c
+36.472 -0.014 36.564 0.389 36.574 0.941 c
+h
+38.081 1.441 m
+38.081 2.153 38.25 2.723 38.596 3.146 c
+38.948 3.564 39.411 3.778 39.992 3.778 c
+40.569 3.778 41.029 3.572 41.374 3.161 c
+41.727 2.756 41.906 2.198 41.917 1.485 c
+41.917 0.971 l
+41.917 0.243 41.742 -0.33 41.389 -0.749 c
+41.043 -1.161 40.583 -1.367 40.007 -1.367 c
+39.426 -1.367 38.963 -1.168 38.611 -0.764 c
+38.265 -0.353 38.089 0.198 38.081 0.897 c
+h
+38.889 0.971 m
+38.889 0.46 38.985 0.059 39.184 -0.235 c
+39.39 -0.529 39.662 -0.675 40.007 -0.675 c
+40.72 -0.675 41.087 -0.158 41.109 0.882 c
+41.109 1.441 l
+41.109 1.948 41.006 2.352 40.801 2.646 c
+40.602 2.94 40.334 3.088 39.992 3.088 c
+39.658 3.088 39.39 2.94 39.184 2.646 c
+38.985 2.352 38.889 1.948 38.889 1.441 c
+h
+45.203 0 m
+45.203 0.166 45.133 0.312 44.997 0.441 c
+44.869 0.566 44.615 0.713 44.233 0.882 c
+43.799 1.066 43.49 1.224 43.307 1.353 c
+43.13 1.478 42.998 1.621 42.91 1.779 c
+42.822 1.945 42.777 2.139 42.777 2.367 c
+42.777 2.779 42.924 3.117 43.219 3.381 c
+43.512 3.645 43.887 3.778 44.35 3.778 c
+44.839 3.778 45.233 3.635 45.526 3.352 c
+45.821 3.076 45.967 2.72 45.967 2.278 c
+45.158 2.278 l
+45.158 2.503 45.077 2.694 44.923 2.852 c
+44.776 3.007 44.585 3.088 44.35 3.088 c
+44.115 3.088 43.928 3.021 43.791 2.897 c
+43.652 2.779 43.586 2.61 43.586 2.396 c
+43.586 2.228 43.633 2.095 43.733 1.999 c
+43.828 1.9 44.071 1.768 44.453 1.603 c
+45.06 1.368 45.471 1.135 45.688 0.912 c
+45.901 0.684 46.012 0.401 46.012 0.059 c
+46.012 -0.374 45.857 -0.72 45.555 -0.984 c
+45.262 -1.242 44.865 -1.367 44.365 -1.367 c
+43.854 -1.367 43.439 -1.219 43.116 -0.926 c
+42.792 -0.631 42.631 -0.257 42.631 0.206 c
+43.454 0.206 l
+43.461 -0.07 43.546 -0.286 43.704 -0.44 c
+43.858 -0.598 44.078 -0.675 44.365 -0.675 c
+44.637 -0.675 44.842 -0.617 44.982 -0.5 c
+45.129 -0.374 45.203 -0.205 45.203 0 c
+47.768 -1.278 -0.809 4.968 re
+47.826 5.013 m
+47.826 4.873 47.786 4.755 47.709 4.66 c
+47.639 4.572 47.525 4.528 47.371 4.528 c
+47.213 4.528 47.095 4.572 47.018 4.66 c
+46.949 4.755 46.916 4.873 46.916 5.013 c
+46.916 5.149 46.949 5.263 47.018 5.351 c
+47.095 5.446 47.209 5.498 47.356 5.498 c
+47.51 5.498 47.628 5.446 47.709 5.351 c
+47.786 5.263 47.826 5.149 47.826 5.013 c
+50.024 4.896 m
+50.024 3.69 l
+50.774 3.69 l
+50.774 3.028 l
+50.024 3.028 l
+50.024 -0.043 l
+50.024 -0.242 50.054 -0.393 50.112 -0.5 c
+50.178 -0.598 50.292 -0.646 50.45 -0.646 c
+50.557 -0.646 50.664 -0.628 50.774 -0.588 c
+50.759 -1.278 l
+50.583 -1.337 50.395 -1.367 50.201 -1.367 c
+49.877 -1.367 49.631 -1.257 49.466 -1.028 c
+49.297 -0.793 49.216 -0.47 49.216 -0.058 c
+49.216 3.028 l
+48.451 3.028 l
+48.451 3.69 l
+49.216 3.69 l
+49.216 4.896 l
+h
+51.365 1.441 m
+51.365 2.153 51.535 2.723 51.88 3.146 c
+52.233 3.564 52.695 3.778 53.276 3.778 c
+53.854 3.778 54.313 3.572 54.658 3.161 c
+55.011 2.756 55.19 2.198 55.202 1.485 c
+55.202 0.971 l
+55.202 0.243 55.026 -0.33 54.673 -0.749 c
+54.328 -1.161 53.868 -1.367 53.291 -1.367 c
+52.711 -1.367 52.248 -1.168 51.895 -0.764 c
+51.549 -0.353 51.373 0.198 51.365 0.897 c
+h
+52.173 0.971 m
+52.173 0.46 52.269 0.059 52.468 -0.235 c
+52.674 -0.529 52.946 -0.675 53.291 -0.675 c
+54.004 -0.675 54.371 -0.158 54.394 0.882 c
+54.394 1.441 l
+54.394 1.948 54.29 2.352 54.085 2.646 c
+53.887 2.94 53.618 3.088 53.276 3.088 c
+52.942 3.088 52.674 2.94 52.468 2.646 c
+52.269 2.352 52.173 1.948 52.173 1.441 c
+h
+58.116 2.926 m
+57.998 2.944 57.873 2.955 57.748 2.955 c
+57.326 2.955 57.035 2.727 56.881 2.278 c
+56.881 -1.278 l
+56.058 -1.278 l
+56.058 3.69 l
+56.852 3.69 l
+56.867 3.19 l
+57.079 3.58 57.388 3.778 57.792 3.778 c
+57.918 3.778 58.028 3.756 58.116 3.72 c
+h
+60.266 0.074 m
+61.162 3.69 l
+62.03 3.69 l
+60.398 -1.984 l
+60.281 -2.403 60.108 -2.726 59.884 -2.954 c
+59.656 -3.179 59.402 -3.293 59.119 -3.293 c
+59.009 -3.293 58.873 -3.266 58.708 -3.218 c
+58.708 -2.528 l
+58.884 -2.543 l
+59.119 -2.543 59.299 -2.484 59.427 -2.366 c
+59.564 -2.256 59.67 -2.065 59.751 -1.793 c
+59.913 -1.234 l
+58.458 3.69 l
+59.34 3.69 l
+h
+62.239 -0.837 m
+62.239 -0.69 62.284 -0.569 62.371 -0.47 c
+62.459 -0.374 62.585 -0.323 62.754 -0.323 c
+62.93 -0.323 63.062 -0.374 63.15 -0.47 c
+63.246 -0.569 63.298 -0.69 63.298 -0.837 c
+63.298 -0.977 63.246 -1.095 63.15 -1.19 c
+63.062 -1.278 62.93 -1.323 62.754 -1.323 c
+62.585 -1.323 62.459 -1.278 62.371 -1.19 c
+62.284 -1.095 62.239 -0.977 62.239 -0.837 c
+71.426 1.676 m
+69.162 1.676 l
+69.162 -1.278 l
+68.324 -1.278 l
+68.324 5.409 l
+71.809 5.409 l
+71.809 4.69 l
+69.162 4.69 l
+69.162 2.396 l
+71.426 2.396 l
+h
+72.297 1.441 m
+72.297 2.153 72.466 2.723 72.811 3.146 c
+73.164 3.564 73.627 3.778 74.207 3.778 c
+74.785 3.778 75.244 3.572 75.589 3.161 c
+75.942 2.756 76.122 2.198 76.133 1.485 c
+76.133 0.971 l
+76.133 0.243 75.957 -0.33 75.604 -0.749 c
+75.259 -1.161 74.799 -1.367 74.222 -1.367 c
+73.642 -1.367 73.179 -1.168 72.826 -0.764 c
+72.48 -0.353 72.304 0.198 72.297 0.897 c
+h
+73.105 0.971 m
+73.105 0.46 73.201 0.059 73.399 -0.235 c
+73.605 -0.529 73.877 -0.675 74.222 -0.675 c
+74.936 -0.675 75.302 -0.158 75.325 0.882 c
+75.325 1.441 l
+75.325 1.948 75.221 2.352 75.016 2.646 c
+74.818 2.94 74.55 3.088 74.207 3.088 c
+73.873 3.088 73.605 2.94 73.399 2.646 c
+73.201 2.352 73.105 1.948 73.105 1.441 c
+h
+79.051 2.926 m
+78.934 2.944 78.809 2.955 78.683 2.955 c
+78.261 2.955 77.97 2.727 77.816 2.278 c
+77.816 -1.278 l
+76.993 -1.278 l
+76.993 3.69 l
+77.787 3.69 l
+77.802 3.19 l
+78.015 3.58 78.323 3.778 78.728 3.778 c
+78.853 3.778 78.963 3.756 79.051 3.72 c
+h
+85.17 -1.367 m
+84.552 -1.367 84.075 -1.186 83.744 -0.823 c
+83.42 -0.452 83.252 0.092 83.244 0.809 c
+83.244 1.411 l
+83.244 2.147 83.406 2.723 83.729 3.146 c
+84.052 3.564 84.501 3.778 85.081 3.778 c
+85.658 3.778 86.088 3.591 86.375 3.219 c
+86.668 2.856 86.82 2.282 86.83 1.5 c
+86.83 0.971 l
+84.052 0.971 l
+84.052 0.853 l
+84.052 0.312 84.148 -0.081 84.347 -0.323 c
+84.552 -0.558 84.839 -0.675 85.214 -0.675 c
+85.456 -0.675 85.669 -0.631 85.845 -0.544 c
+86.03 -0.455 86.202 -0.316 86.36 -0.118 c
+86.786 -0.631 l
+86.433 -1.124 85.893 -1.367 85.17 -1.367 c
+85.081 3.088 m
+84.747 3.088 84.497 2.97 84.332 2.735 c
+84.162 2.506 84.071 2.151 84.052 1.661 c
+86.007 1.661 l
+86.007 1.779 l
+85.985 2.249 85.905 2.58 85.758 2.779 c
+85.61 2.984 85.382 3.088 85.081 3.088 c
+89.065 1.881 m
+89.918 3.69 l
+90.859 3.69 l
+89.506 1.235 l
+90.888 -1.278 l
+89.961 -1.278 l
+89.08 0.588 l
+88.197 -1.278 l
+87.256 -1.278 l
+88.638 1.235 l
+87.301 3.69 l
+88.227 3.69 l
+h
+94.151 -1.278 m
+94.099 -1.172 94.066 -0.992 94.048 -0.735 c
+93.761 -1.157 93.394 -1.367 92.945 -1.367 c
+92.494 -1.367 92.141 -1.246 91.887 -0.999 c
+91.641 -0.746 91.52 -0.389 91.52 0.074 c
+91.52 0.581 91.688 0.985 92.034 1.279 c
+92.376 1.573 92.846 1.723 93.445 1.735 c
+94.034 1.735 l
+94.034 2.264 l
+94.034 2.558 93.963 2.768 93.827 2.897 c
+93.699 3.021 93.504 3.088 93.24 3.088 c
+92.993 3.088 92.791 3.014 92.636 2.866 c
+92.49 2.72 92.416 2.532 92.416 2.309 c
+91.593 2.309 l
+91.593 2.562 91.667 2.808 91.813 3.043 c
+91.968 3.279 92.174 3.458 92.43 3.587 c
+92.685 3.712 92.968 3.778 93.284 3.778 c
+93.791 3.778 94.18 3.649 94.445 3.396 c
+94.709 3.15 94.842 2.782 94.842 2.294 c
+94.842 -0.205 l
+94.849 -0.588 94.904 -0.922 95.003 -1.205 c
+95.003 -1.278 l
+h
+93.078 -0.631 m
+93.272 -0.631 93.46 -0.58 93.636 -0.47 c
+93.82 -0.353 93.953 -0.216 94.034 -0.058 c
+94.034 1.133 l
+93.577 1.133 l
+93.195 1.121 92.891 1.033 92.666 0.867 c
+92.438 0.699 92.328 0.47 92.328 0.177 c
+92.328 -0.11 92.38 -0.316 92.49 -0.44 c
+92.607 -0.569 92.802 -0.631 93.078 -0.631 c
+96.679 3.69 m
+96.708 3.234 l
+97.01 3.595 97.407 3.778 97.899 3.778 c
+98.458 3.778 98.844 3.535 99.06 3.057 c
+99.372 3.535 99.81 3.778 100.368 3.778 c
+101.287 3.778 101.757 3.209 101.78 2.073 c
+101.78 -1.278 l
+100.971 -1.278 l
+100.971 1.999 l
+100.971 2.352 100.901 2.617 100.765 2.793 c
+100.637 2.97 100.42 3.057 100.118 3.057 c
+99.873 3.057 99.67 2.962 99.516 2.779 c
+99.368 2.591 99.281 2.352 99.251 2.058 c
+99.251 -1.278 l
+98.443 -1.278 l
+98.443 2.029 l
+98.431 2.712 98.152 3.057 97.605 3.057 c
+97.193 3.057 96.903 2.852 96.738 2.44 c
+96.738 -1.278 l
+95.929 -1.278 l
+95.929 3.69 l
+h
+106.306 0.971 m
+106.306 0.184 106.163 -0.404 105.88 -0.793 c
+105.594 -1.176 105.194 -1.367 104.675 -1.367 c
+104.176 -1.367 103.794 -1.182 103.528 -0.808 c
+103.528 -3.189 l
+102.72 -3.189 l
+102.72 3.69 l
+103.455 3.69 l
+103.484 3.146 l
+103.757 3.564 104.149 3.778 104.66 3.778 c
+105.208 3.778 105.616 3.587 105.88 3.205 c
+106.152 2.83 106.296 2.268 106.306 1.515 c
+h
+105.498 1.426 m
+105.498 1.985 105.41 2.396 105.234 2.661 c
+105.065 2.926 104.793 3.057 104.411 3.057 c
+104.018 3.057 103.723 2.866 103.528 2.485 c
+103.528 -0.103 l
+103.723 -0.484 104.021 -0.675 104.425 -0.675 c
+104.785 -0.675 105.05 -0.544 105.219 -0.278 c
+105.396 -0.014 105.487 0.389 105.498 0.941 c
+h
+108.049 -1.278 -0.808 7.056 re
+111.01 -1.367 m
+110.393 -1.367 109.915 -1.186 109.585 -0.823 c
+109.261 -0.452 109.092 0.092 109.085 0.809 c
+109.085 1.411 l
+109.085 2.147 109.246 2.723 109.57 3.146 c
+109.893 3.564 110.342 3.778 110.923 3.778 c
+111.499 3.778 111.929 3.591 112.216 3.219 c
+112.51 2.856 112.66 2.282 112.671 1.5 c
+112.671 0.971 l
+109.893 0.971 l
+109.893 0.853 l
+109.893 0.312 109.988 -0.081 110.187 -0.323 c
+110.393 -0.558 110.68 -0.675 111.054 -0.675 c
+111.297 -0.675 111.511 -0.631 111.686 -0.544 c
+111.87 -0.455 112.043 -0.316 112.201 -0.118 c
+112.627 -0.631 l
+112.274 -1.124 111.734 -1.367 111.01 -1.367 c
+110.923 3.088 m
+110.588 3.088 110.338 2.97 110.173 2.735 c
+110.003 2.506 109.911 2.151 109.893 1.661 c
+111.848 1.661 l
+111.848 1.779 l
+111.827 2.249 111.746 2.58 111.598 2.779 c
+111.451 2.984 111.224 3.088 110.923 3.088 c
+117.992 -1.278 -0.808 4.968 re
+118.052 5.013 m
+118.052 4.873 118.011 4.755 117.934 4.66 c
+117.864 4.572 117.75 4.528 117.595 4.528 c
+117.437 4.528 117.32 4.572 117.242 4.66 c
+117.173 4.755 117.14 4.873 117.14 5.013 c
+117.14 5.149 117.173 5.263 117.242 5.351 c
+117.32 5.446 117.434 5.498 117.581 5.498 c
+117.735 5.498 117.853 5.446 117.934 5.351 c
+118.011 5.263 118.052 5.149 118.052 5.013 c
+119.94 3.69 m
+119.97 3.161 l
+120.282 3.572 120.683 3.778 121.175 3.778 c
+122.057 3.778 122.501 3.194 122.513 2.029 c
+122.513 -1.278 l
+121.704 -1.278 l
+121.704 1.985 l
+121.704 2.374 121.638 2.65 121.513 2.808 c
+121.385 2.974 121.19 3.057 120.925 3.057 c
+120.719 3.057 120.535 2.988 120.381 2.852 c
+120.223 2.723 120.095 2.55 119.999 2.338 c
+119.999 -1.278 l
+119.176 -1.278 l
+119.176 3.69 l
+h
+127.315 -1.278 m
+127.315 5.409 l
+128.918 5.409 l
+129.689 5.409 130.292 5.164 130.725 4.675 c
+131.155 4.183 131.372 3.499 131.372 2.617 c
+131.372 1.5 l
+131.372 0.607 131.152 -0.081 130.711 -0.558 c
+130.277 -1.039 129.645 -1.278 128.815 -1.278 c
+h
+128.153 4.69 m
+128.153 -0.558 l
+128.83 -0.558 l
+129.425 -0.558 129.859 -0.393 130.123 -0.058 c
+130.395 0.283 130.538 0.786 130.549 1.455 c
+130.549 2.646 l
+130.549 3.341 130.41 3.855 130.137 4.19 c
+129.862 4.52 129.454 4.69 128.918 4.69 c
+h
+134.125 -1.367 m
+133.507 -1.367 133.03 -1.186 132.699 -0.823 c
+132.375 -0.452 132.207 0.092 132.199 0.809 c
+132.199 1.411 l
+132.199 2.147 132.361 2.723 132.685 3.146 c
+133.007 3.564 133.456 3.778 134.037 3.778 c
+134.613 3.778 135.043 3.591 135.33 3.219 c
+135.624 2.856 135.775 2.282 135.785 1.5 c
+135.785 0.971 l
+133.007 0.971 l
+133.007 0.853 l
+133.007 0.312 133.103 -0.081 133.302 -0.323 c
+133.507 -0.558 133.794 -0.675 134.169 -0.675 c
+134.411 -0.675 134.625 -0.631 134.801 -0.544 c
+134.985 -0.455 135.157 -0.316 135.315 -0.118 c
+135.742 -0.631 l
+135.388 -1.124 134.848 -1.367 134.125 -1.367 c
+134.037 3.088 m
+133.703 3.088 133.452 2.97 133.287 2.735 c
+133.117 2.506 133.026 2.151 133.007 1.661 c
+134.962 1.661 l
+134.962 1.779 l
+134.941 2.249 134.86 2.58 134.713 2.779 c
+134.566 2.984 134.338 3.088 134.037 3.088 c
+140.181 0.971 m
+140.181 0.195 140.038 -0.389 139.754 -0.779 c
+139.479 -1.172 139.078 -1.367 138.549 -1.367 c
+138.027 -1.367 137.638 -1.142 137.373 -0.69 c
+137.329 -1.278 l
+136.594 -1.278 l
+136.594 5.777 l
+137.403 5.777 l
+137.403 3.146 l
+137.667 3.564 138.05 3.778 138.549 3.778 c
+139.086 3.778 139.494 3.587 139.769 3.205 c
+140.041 2.822 140.181 2.238 140.181 1.455 c
+h
+139.372 1.426 m
+139.372 2.014 139.288 2.429 139.122 2.675 c
+138.964 2.929 138.7 3.057 138.329 3.057 c
+137.917 3.057 137.609 2.83 137.403 2.382 c
+137.403 0.015 l
+137.597 -0.426 137.91 -0.646 138.343 -0.646 c
+138.704 -0.646 138.964 -0.521 139.122 -0.264 c
+139.288 -0.01 139.372 0.387 139.372 0.927 c
+h
+141.927 -1.278 -0.809 4.968 re
+141.985 5.013 m
+141.985 4.873 141.944 4.755 141.867 4.66 c
+141.798 4.572 141.684 4.528 141.53 4.528 c
+141.372 4.528 141.254 4.572 141.177 4.66 c
+141.107 4.755 141.073 4.873 141.073 5.013 c
+141.073 5.149 141.107 5.263 141.177 5.351 c
+141.254 5.446 141.368 5.498 141.514 5.498 c
+141.669 5.498 141.786 5.446 141.867 5.351 c
+141.944 5.263 141.985 5.149 141.985 5.013 c
+145.663 -1.278 m
+145.612 -1.172 145.579 -0.992 145.561 -0.735 c
+145.274 -1.157 144.907 -1.367 144.458 -1.367 c
+144.007 -1.367 143.654 -1.246 143.4 -0.999 c
+143.153 -0.746 143.033 -0.389 143.033 0.074 c
+143.033 0.581 143.201 0.985 143.547 1.279 c
+143.889 1.573 144.359 1.723 144.958 1.735 c
+145.546 1.735 l
+145.546 2.264 l
+145.546 2.558 145.476 2.768 145.34 2.897 c
+145.212 3.021 145.017 3.088 144.753 3.088 c
+144.506 3.088 144.304 3.014 144.149 2.866 c
+144.003 2.72 143.929 2.532 143.929 2.309 c
+143.106 2.309 l
+143.106 2.562 143.18 2.808 143.326 3.043 c
+143.481 3.279 143.687 3.458 143.943 3.587 c
+144.198 3.712 144.481 3.778 144.796 3.778 c
+145.304 3.778 145.693 3.649 145.958 3.396 c
+146.222 3.15 146.355 2.782 146.355 2.294 c
+146.355 -0.205 l
+146.362 -0.588 146.417 -0.922 146.516 -1.205 c
+146.516 -1.278 l
+h
+144.591 -0.631 m
+144.785 -0.631 144.973 -0.58 145.149 -0.47 c
+145.333 -0.353 145.465 -0.216 145.546 -0.058 c
+145.546 1.133 l
+145.09 1.133 l
+144.708 1.121 144.404 1.033 144.179 0.867 c
+143.951 0.699 143.841 0.47 143.841 0.177 c
+143.841 -0.11 143.893 -0.316 144.003 -0.44 c
+144.12 -0.569 144.315 -0.631 144.591 -0.631 c
+148.192 3.69 m
+148.221 3.161 l
+148.533 3.572 148.934 3.778 149.426 3.778 c
+150.309 3.778 150.754 3.194 150.764 2.029 c
+150.764 -1.278 l
+149.956 -1.278 l
+149.956 1.985 l
+149.956 2.374 149.89 2.65 149.765 2.808 c
+149.636 2.974 149.441 3.057 149.177 3.057 c
+148.971 3.057 148.787 2.988 148.633 2.852 c
+148.475 2.723 148.346 2.55 148.25 2.338 c
+148.25 -1.278 l
+147.427 -1.278 l
+147.427 3.69 l
+h
+152.039 -1.851 m
+151.348 -1.851 l
+153.686 5.409 l
+154.376 5.409 l
+h
+159.257 5.409 m
+159.257 0.662 l
+159.257 0.023 159.072 -0.477 158.712 -0.837 c
+158.349 -1.19 157.846 -1.367 157.198 -1.367 c
+156.541 -1.367 156.038 -1.198 155.685 -0.852 c
+155.332 -0.5 155.155 0.004 155.155 0.662 c
+155.155 5.409 l
+155.993 5.409 l
+155.993 0.691 l
+155.993 0.239 156.085 -0.099 156.273 -0.323 c
+156.468 -0.54 156.776 -0.646 157.198 -0.646 c
+157.628 -0.646 157.937 -0.54 158.124 -0.323 c
+158.32 -0.099 158.419 0.239 158.419 0.691 c
+158.419 5.409 l
+h
+163.835 0.971 m
+163.835 0.195 163.691 -0.389 163.409 -0.779 c
+163.134 -1.172 162.733 -1.367 162.203 -1.367 c
+161.682 -1.367 161.293 -1.142 161.027 -0.69 c
+160.984 -1.278 l
+160.248 -1.278 l
+160.248 5.777 l
+161.057 5.777 l
+161.057 3.146 l
+161.322 3.564 161.704 3.778 162.203 3.778 c
+162.74 3.778 163.148 3.587 163.423 3.205 c
+163.695 2.822 163.835 2.238 163.835 1.455 c
+h
+163.026 1.426 m
+163.026 2.014 162.943 2.429 162.777 2.675 c
+162.619 2.929 162.355 3.057 161.983 3.057 c
+161.572 3.057 161.262 2.83 161.057 2.382 c
+161.057 0.015 l
+161.252 -0.426 161.565 -0.646 161.998 -0.646 c
+162.357 -0.646 162.619 -0.521 162.777 -0.264 c
+162.943 -0.01 163.026 0.387 163.026 0.927 c
+h
+167.242 -0.837 m
+166.966 -1.19 166.569 -1.367 166.051 -1.367 c
+165.611 -1.367 165.272 -1.216 165.037 -0.911 c
+164.809 -0.598 164.691 -0.143 164.684 0.456 c
+164.684 3.69 l
+165.492 3.69 l
+165.492 0.515 l
+165.492 -0.261 165.727 -0.646 166.198 -0.646 c
+166.687 -0.646 167.024 -0.426 167.213 0.015 c
+167.213 3.69 l
+168.036 3.69 l
+168.036 -1.278 l
+167.257 -1.278 l
+h
+169.836 3.69 m
+169.866 3.161 l
+170.178 3.572 170.579 3.778 171.071 3.778 c
+171.953 3.778 172.397 3.194 172.408 2.029 c
+172.408 -1.278 l
+171.6 -1.278 l
+171.6 1.985 l
+171.6 2.374 171.534 2.65 171.409 2.808 c
+171.28 2.974 171.086 3.057 170.821 3.057 c
+170.615 3.057 170.431 2.988 170.277 2.852 c
+170.119 2.723 169.991 2.55 169.895 2.338 c
+169.895 -1.278 l
+169.072 -1.278 l
+169.072 3.69 l
+h
+174.518 4.896 m
+174.518 3.69 l
+175.267 3.69 l
+175.267 3.028 l
+174.518 3.028 l
+174.518 -0.043 l
+174.518 -0.242 174.548 -0.393 174.606 -0.5 c
+174.672 -0.598 174.786 -0.646 174.944 -0.646 c
+175.051 -0.646 175.157 -0.628 175.267 -0.588 c
+175.253 -1.278 l
+175.076 -1.337 174.889 -1.367 174.694 -1.367 c
+174.371 -1.367 174.124 -1.257 173.959 -1.028 c
+173.79 -0.793 173.709 -0.47 173.709 -0.058 c
+173.709 3.028 l
+172.945 3.028 l
+172.945 3.69 l
+173.709 3.69 l
+173.709 4.896 l
+h
+178.652 -0.837 m
+178.376 -1.19 177.979 -1.367 177.461 -1.367 c
+177.02 -1.367 176.682 -1.216 176.447 -0.911 c
+176.219 -0.598 176.102 -0.143 176.094 0.456 c
+176.094 3.69 l
+176.902 3.69 l
+176.902 0.515 l
+176.902 -0.261 177.137 -0.646 177.608 -0.646 c
+178.097 -0.646 178.435 -0.426 178.623 0.015 c
+178.623 3.69 l
+179.446 3.69 l
+179.446 -1.278 l
+178.666 -1.278 l
+h
+187.732 0.971 m
+187.732 0.184 187.589 -0.404 187.306 -0.793 c
+187.019 -1.176 186.619 -1.367 186.101 -1.367 c
+185.601 -1.367 185.218 -1.182 184.954 -0.808 c
+184.954 -3.189 l
+184.146 -3.189 l
+184.146 3.69 l
+184.881 3.69 l
+184.91 3.146 l
+185.182 3.564 185.575 3.778 186.086 3.778 c
+186.633 3.778 187.042 3.587 187.306 3.205 c
+187.578 2.83 187.721 2.268 187.732 1.515 c
+h
+186.924 1.426 m
+186.924 1.985 186.836 2.396 186.659 2.661 c
+186.49 2.926 186.218 3.057 185.836 3.057 c
+185.443 3.057 185.149 2.866 184.954 2.485 c
+184.954 -0.103 l
+185.149 -0.484 185.446 -0.675 185.851 -0.675 c
+186.211 -0.675 186.475 -0.544 186.645 -0.278 c
+186.82 -0.014 186.913 0.389 186.924 0.941 c
+h
+189.474 -1.278 -0.809 7.056 re
+192.436 -1.367 m
+191.819 -1.367 191.341 -1.186 191.011 -0.823 c
+190.687 -0.452 190.518 0.092 190.51 0.809 c
+190.51 1.411 l
+190.51 2.147 190.672 2.723 190.995 3.146 c
+191.319 3.564 191.767 3.778 192.347 3.778 c
+192.925 3.778 193.355 3.591 193.641 3.219 c
+193.935 2.856 194.086 2.282 194.097 1.5 c
+194.097 0.971 l
+191.319 0.971 l
+191.319 0.853 l
+191.319 0.312 191.414 -0.081 191.613 -0.323 c
+191.819 -0.558 192.106 -0.675 192.48 -0.675 c
+192.723 -0.675 192.935 -0.631 193.112 -0.544 c
+193.296 -0.455 193.469 -0.316 193.627 -0.118 c
+194.053 -0.631 l
+193.7 -1.124 193.16 -1.367 192.436 -1.367 c
+192.347 3.088 m
+192.013 3.088 191.763 2.97 191.598 2.735 c
+191.429 2.506 191.337 2.151 191.319 1.661 c
+193.274 1.661 l
+193.274 1.779 l
+193.251 2.249 193.17 2.58 193.024 2.779 c
+192.877 2.984 192.649 3.088 192.347 3.088 c
+197.448 -1.278 m
+197.397 -1.172 197.363 -0.992 197.346 -0.735 c
+197.059 -1.157 196.692 -1.367 196.243 -1.367 c
+195.791 -1.367 195.439 -1.246 195.185 -0.999 c
+194.938 -0.746 194.817 -0.389 194.817 0.074 c
+194.817 0.581 194.986 0.985 195.331 1.279 c
+195.674 1.573 196.144 1.723 196.742 1.735 c
+197.33 1.735 l
+197.33 2.264 l
+197.33 2.558 197.261 2.768 197.125 2.897 c
+196.997 3.021 196.802 3.088 196.536 3.088 c
+196.291 3.088 196.089 3.014 195.934 2.866 c
+195.788 2.72 195.714 2.532 195.714 2.309 c
+194.89 2.309 l
+194.89 2.562 194.964 2.808 195.111 3.043 c
+195.266 3.279 195.472 3.458 195.728 3.587 c
+195.982 3.712 196.265 3.778 196.581 3.778 c
+197.088 3.778 197.477 3.649 197.742 3.396 c
+198.007 3.15 198.139 2.782 198.139 2.294 c
+198.139 -0.205 l
+198.146 -0.588 198.202 -0.922 198.301 -1.205 c
+198.301 -1.278 l
+h
+196.376 -0.631 m
+196.57 -0.631 196.758 -0.58 196.933 -0.47 c
+197.118 -0.353 197.25 -0.216 197.33 -0.058 c
+197.33 1.133 l
+196.875 1.133 l
+196.493 1.121 196.187 1.033 195.964 0.867 c
+195.736 0.699 195.626 0.47 195.626 0.177 c
+195.626 -0.11 195.677 -0.316 195.788 -0.44 c
+195.905 -0.569 196.1 -0.631 196.376 -0.631 c
+201.637 0 m
+201.637 0.166 201.568 0.312 201.432 0.441 c
+201.303 0.566 201.049 0.713 200.667 0.882 c
+200.234 1.066 199.925 1.224 199.742 1.353 c
+199.565 1.478 199.433 1.621 199.345 1.779 c
+199.256 1.945 199.212 2.139 199.212 2.367 c
+199.212 2.779 199.359 3.117 199.653 3.381 c
+199.948 3.645 200.322 3.778 200.785 3.778 c
+201.274 3.778 201.667 3.635 201.961 3.352 c
+202.255 3.076 202.402 2.72 202.402 2.278 c
+201.594 2.278 l
+201.594 2.503 201.513 2.694 201.359 2.852 c
+201.211 3.007 201.02 3.088 200.785 3.088 c
+200.55 3.088 200.362 3.021 200.226 2.897 c
+200.087 2.779 200.021 2.61 200.021 2.396 c
+200.021 2.228 200.068 2.095 200.168 1.999 c
+200.263 1.9 200.505 1.768 200.888 1.603 c
+201.494 1.368 201.906 1.135 202.123 0.912 c
+202.336 0.684 202.446 0.401 202.446 0.059 c
+202.446 -0.374 202.292 -0.72 201.99 -0.984 c
+201.696 -1.242 201.299 -1.367 200.8 -1.367 c
+200.289 -1.367 199.873 -1.219 199.551 -0.926 c
+199.227 -0.631 199.065 -0.257 199.065 0.206 c
+199.888 0.206 l
+199.896 -0.07 199.981 -0.286 200.139 -0.44 c
+200.293 -0.598 200.513 -0.675 200.8 -0.675 c
+201.072 -0.675 201.278 -0.617 201.417 -0.5 c
+201.564 -0.374 201.637 -0.205 201.637 0 c
+205.099 -1.367 m
+204.482 -1.367 204.004 -1.186 203.673 -0.823 c
+203.35 -0.452 203.181 0.092 203.173 0.809 c
+203.173 1.411 l
+203.173 2.147 203.335 2.723 203.659 3.146 c
+203.982 3.564 204.43 3.778 205.011 3.778 c
+205.588 3.778 206.018 3.591 206.304 3.219 c
+206.599 2.856 206.749 2.282 206.76 1.5 c
+206.76 0.971 l
+203.982 0.971 l
+203.982 0.853 l
+203.982 0.312 204.077 -0.081 204.276 -0.323 c
+204.482 -0.558 204.768 -0.675 205.143 -0.675 c
+205.386 -0.675 205.599 -0.631 205.775 -0.544 c
+205.959 -0.455 206.132 -0.316 206.29 -0.118 c
+206.716 -0.631 l
+206.363 -1.124 205.823 -1.367 205.099 -1.367 c
+205.011 3.088 m
+204.677 3.088 204.426 2.97 204.261 2.735 c
+204.092 2.506 204 2.151 203.982 1.661 c
+205.937 1.661 l
+205.937 1.779 l
+205.915 2.249 205.834 2.58 205.687 2.779 c
+205.54 2.984 205.313 3.088 205.011 3.088 c
+212.276 4.896 m
+212.276 3.69 l
+213.026 3.69 l
+213.026 3.028 l
+212.276 3.028 l
+212.276 -0.043 l
+212.276 -0.242 212.305 -0.393 212.364 -0.5 c
+212.43 -0.598 212.544 -0.646 212.702 -0.646 c
+212.808 -0.646 212.916 -0.628 213.026 -0.588 c
+213.011 -1.278 l
+212.835 -1.337 212.648 -1.367 212.452 -1.367 c
+212.129 -1.367 211.883 -1.257 211.717 -1.028 c
+211.549 -0.793 211.468 -0.47 211.468 -0.058 c
+211.468 3.028 l
+210.703 3.028 l
+210.703 3.69 l
+211.468 3.69 l
+211.468 4.896 l
+h
+215.235 0.074 m
+216.131 3.69 l
+216.998 3.69 l
+215.366 -1.984 l
+215.249 -2.403 215.077 -2.726 214.852 -2.954 c
+214.624 -3.179 214.371 -3.293 214.088 -3.293 c
+213.978 -3.293 213.841 -3.266 213.676 -3.218 c
+213.676 -2.528 l
+213.853 -2.543 l
+214.088 -2.543 214.268 -2.484 214.396 -2.366 c
+214.532 -2.256 214.639 -2.065 214.72 -1.793 c
+214.881 -1.234 l
+213.427 3.69 l
+214.308 3.69 l
+h
+221.224 0.971 m
+221.224 0.184 221.08 -0.404 220.798 -0.793 c
+220.511 -1.176 220.11 -1.367 219.592 -1.367 c
+219.093 -1.367 218.711 -1.182 218.446 -0.808 c
+218.446 -3.189 l
+217.637 -3.189 l
+217.637 3.69 l
+218.372 3.69 l
+218.402 3.146 l
+218.674 3.564 219.067 3.778 219.578 3.778 c
+220.126 3.778 220.533 3.587 220.798 3.205 c
+221.07 2.83 221.213 2.268 221.224 1.515 c
+h
+220.415 1.426 m
+220.415 1.985 220.328 2.396 220.151 2.661 c
+219.982 2.926 219.71 3.057 219.328 3.057 c
+218.935 3.057 218.641 2.866 218.446 2.485 c
+218.446 -0.103 l
+218.641 -0.484 218.938 -0.675 219.343 -0.675 c
+219.703 -0.675 219.967 -0.544 220.136 -0.278 c
+220.313 -0.014 220.405 0.389 220.415 0.941 c
+h
+223.862 -1.367 m
+223.245 -1.367 222.767 -1.186 222.437 -0.823 c
+222.113 -0.452 221.944 0.092 221.936 0.809 c
+221.936 1.411 l
+221.936 2.147 222.098 2.723 222.422 3.146 c
+222.745 3.564 223.193 3.778 223.775 3.778 c
+224.351 3.778 224.781 3.591 225.068 3.219 c
+225.362 2.856 225.512 2.282 225.523 1.5 c
+225.523 0.971 l
+222.745 0.971 l
+222.745 0.853 l
+222.745 0.312 222.84 -0.081 223.039 -0.323 c
+223.245 -0.558 223.532 -0.675 223.906 -0.675 c
+224.149 -0.675 224.363 -0.631 224.539 -0.544 c
+224.722 -0.455 224.895 -0.316 225.053 -0.118 c
+225.479 -0.631 l
+225.126 -1.124 224.586 -1.367 223.862 -1.367 c
+223.775 3.088 m
+223.44 3.088 223.19 2.97 223.025 2.735 c
+222.856 2.506 222.763 2.151 222.745 1.661 c
+224.7 1.661 l
+224.7 1.779 l
+224.679 2.249 224.598 2.58 224.45 2.779 c
+224.303 2.984 224.076 3.088 223.775 3.088 c
+230.848 -1.278 -0.808 4.968 re
+230.907 5.013 m
+230.907 4.873 230.867 4.755 230.79 4.66 c
+230.719 4.572 230.605 4.528 230.451 4.528 c
+230.293 4.528 230.175 4.572 230.098 4.66 c
+230.029 4.755 229.996 4.873 229.996 5.013 c
+229.996 5.149 230.029 5.263 230.098 5.351 c
+230.175 5.446 230.289 5.498 230.437 5.498 c
+230.591 5.498 230.709 5.446 230.79 5.351 c
+230.867 5.263 230.907 5.149 230.907 5.013 c
+232.793 3.69 m
+232.822 3.161 l
+233.134 3.572 233.535 3.778 234.027 3.778 c
+234.909 3.778 235.353 3.194 235.365 2.029 c
+235.365 -1.278 l
+234.556 -1.278 l
+234.556 1.985 l
+234.556 2.374 234.49 2.65 234.365 2.808 c
+234.237 2.974 234.042 3.057 233.777 3.057 c
+233.571 3.057 233.387 2.988 233.233 2.852 c
+233.075 2.723 232.947 2.55 232.851 2.338 c
+232.851 -1.278 l
+232.028 -1.278 l
+232.028 3.69 l
+h
+f
+Q
+q 1 0 0 1 537.1847 388.598 cm
+0 0 m
+0 -1.206 l
+0.75 -1.206 l
+0.75 -1.867 l
+0 -1.867 l
+0 -4.939 l
+0 -5.137 0.029 -5.289 0.088 -5.395 c
+0.154 -5.494 0.268 -5.542 0.426 -5.542 c
+0.532 -5.542 0.64 -5.524 0.75 -5.484 c
+0.735 -6.174 l
+0.559 -6.232 0.372 -6.263 0.177 -6.263 c
+-0.147 -6.263 -0.393 -6.152 -0.559 -5.924 c
+-0.727 -5.689 -0.808 -5.366 -0.808 -4.954 c
+-0.808 -1.867 l
+-1.573 -1.867 l
+-1.573 -1.206 l
+-0.808 -1.206 l
+-0.808 0 l
+h
+2.414 -1.721 m
+2.716 -1.32 3.109 -1.118 3.59 -1.118 c
+4.472 -1.118 4.917 -1.702 4.928 -2.866 c
+4.928 -6.174 l
+4.12 -6.174 l
+4.12 -2.911 l
+4.12 -2.521 4.054 -2.246 3.929 -2.087 c
+3.8 -1.922 3.605 -1.838 3.341 -1.838 c
+3.135 -1.838 2.951 -1.908 2.797 -2.043 c
+2.639 -2.172 2.51 -2.345 2.414 -2.558 c
+2.414 -6.174 l
+1.591 -6.174 l
+1.591 0.881 l
+2.414 0.881 l
+h
+7.724 -6.263 m
+7.107 -6.263 6.629 -6.082 6.298 -5.719 c
+5.976 -5.347 5.806 -4.803 5.799 -4.087 c
+5.799 -3.485 l
+5.799 -2.749 5.961 -2.172 6.284 -1.75 c
+6.607 -1.331 7.056 -1.118 7.636 -1.118 c
+8.214 -1.118 8.644 -1.305 8.93 -1.676 c
+9.224 -2.04 9.374 -2.613 9.386 -3.396 c
+9.386 -3.925 l
+6.607 -3.925 l
+6.607 -4.042 l
+6.607 -4.583 6.703 -4.977 6.901 -5.218 c
+7.107 -5.453 7.393 -5.571 7.769 -5.571 c
+8.011 -5.571 8.224 -5.527 8.401 -5.439 c
+8.584 -5.351 8.757 -5.212 8.915 -5.013 c
+9.342 -5.527 l
+8.989 -6.02 8.449 -6.263 7.724 -6.263 c
+7.636 -1.808 m
+7.302 -1.808 7.052 -1.926 6.886 -2.161 c
+6.718 -2.389 6.626 -2.745 6.607 -3.234 c
+8.563 -3.234 l
+8.563 -3.117 l
+8.54 -2.646 8.459 -2.315 8.312 -2.117 c
+8.166 -1.912 7.938 -1.808 7.636 -1.808 c
+13.317 0 m
+13.317 -1.206 l
+14.067 -1.206 l
+14.067 -1.867 l
+13.317 -1.867 l
+13.317 -4.939 l
+13.317 -5.137 13.347 -5.289 13.406 -5.395 c
+13.471 -5.494 13.585 -5.542 13.743 -5.542 c
+13.851 -5.542 13.957 -5.524 14.067 -5.484 c
+14.053 -6.174 l
+13.876 -6.232 13.689 -6.263 13.494 -6.263 c
+13.17 -6.263 12.924 -6.152 12.759 -5.924 c
+12.59 -5.689 12.509 -5.366 12.509 -4.954 c
+12.509 -1.867 l
+11.744 -1.867 l
+11.744 -1.206 l
+12.509 -1.206 l
+12.509 0 l
+h
+16.687 -6.263 m
+16.07 -6.263 15.592 -6.082 15.262 -5.719 c
+14.938 -5.347 14.769 -4.803 14.761 -4.087 c
+14.761 -3.485 l
+14.761 -2.749 14.923 -2.172 15.247 -1.75 c
+15.57 -1.331 16.018 -1.118 16.599 -1.118 c
+17.176 -1.118 17.606 -1.305 17.893 -1.676 c
+18.186 -2.04 18.337 -2.613 18.348 -3.396 c
+18.348 -3.925 l
+15.57 -3.925 l
+15.57 -4.042 l
+15.57 -4.583 15.665 -4.977 15.864 -5.218 c
+16.07 -5.453 16.357 -5.571 16.731 -5.571 c
+16.974 -5.571 17.187 -5.527 17.363 -5.439 c
+17.547 -5.351 17.72 -5.212 17.878 -5.013 c
+18.304 -5.527 l
+17.951 -6.02 17.411 -6.263 16.687 -6.263 c
+16.599 -1.808 m
+16.264 -1.808 16.014 -1.926 15.85 -2.161 c
+15.68 -2.389 15.588 -2.745 15.57 -3.234 c
+17.525 -3.234 l
+17.525 -3.117 l
+17.503 -2.646 17.422 -2.315 17.275 -2.117 c
+17.128 -1.912 16.9 -1.808 16.599 -1.808 c
+21.2 -1.97 m
+21.082 -1.952 20.957 -1.941 20.833 -1.941 c
+20.409 -1.941 20.12 -2.168 19.965 -2.617 c
+19.965 -6.174 l
+19.142 -6.174 l
+19.142 -1.206 l
+19.935 -1.206 l
+19.95 -1.706 l
+20.164 -1.316 20.472 -1.118 20.876 -1.118 c
+21.001 -1.118 21.111 -1.139 21.2 -1.176 c
+h
+22.655 -1.206 m
+22.684 -1.661 l
+22.986 -1.301 23.382 -1.118 23.875 -1.118 c
+24.434 -1.118 24.82 -1.36 25.036 -1.838 c
+25.348 -1.36 25.786 -1.118 26.344 -1.118 c
+27.264 -1.118 27.734 -1.687 27.756 -2.822 c
+27.756 -6.174 l
+26.948 -6.174 l
+26.948 -2.897 l
+26.948 -2.544 26.877 -2.278 26.741 -2.103 c
+26.613 -1.926 26.396 -1.838 26.094 -1.838 c
+25.849 -1.838 25.646 -1.933 25.492 -2.117 c
+25.344 -2.305 25.257 -2.544 25.227 -2.837 c
+25.227 -6.174 l
+24.419 -6.174 l
+24.419 -2.866 l
+24.407 -2.183 24.128 -1.838 23.581 -1.838 c
+23.169 -1.838 22.879 -2.043 22.714 -2.455 c
+22.714 -6.174 l
+21.905 -6.174 l
+21.905 -1.206 l
+h
+29.564 -6.174 -0.809 4.968 re
+29.622 0.118 m
+29.622 -0.023 29.582 -0.14 29.504 -0.235 c
+29.435 -0.324 29.321 -0.368 29.167 -0.368 c
+29.009 -0.368 28.891 -0.324 28.814 -0.235 c
+28.744 -0.14 28.711 -0.023 28.711 0.118 c
+28.711 0.253 28.744 0.367 28.814 0.455 c
+28.891 0.55 29.005 0.602 29.152 0.602 c
+29.306 0.602 29.424 0.55 29.504 0.455 c
+29.582 0.367 29.622 0.253 29.622 0.118 c
+31.511 -1.206 m
+31.54 -1.735 l
+31.852 -1.324 32.253 -1.118 32.746 -1.118 c
+33.628 -1.118 34.073 -1.702 34.084 -2.866 c
+34.084 -6.174 l
+33.275 -6.174 l
+33.275 -2.911 l
+33.275 -2.521 33.209 -2.246 33.084 -2.087 c
+32.955 -1.922 32.76 -1.838 32.496 -1.838 c
+32.29 -1.838 32.107 -1.908 31.952 -2.043 c
+31.794 -2.172 31.665 -2.345 31.57 -2.558 c
+31.57 -6.174 l
+30.747 -6.174 l
+30.747 -1.206 l
+h
+37.678 -6.174 m
+37.626 -6.068 37.593 -5.887 37.574 -5.63 c
+37.288 -6.053 36.92 -6.263 36.472 -6.263 c
+36.02 -6.263 35.667 -6.141 35.414 -5.895 c
+35.168 -5.642 35.046 -5.285 35.046 -4.821 c
+35.046 -4.314 35.216 -3.911 35.561 -3.616 c
+35.902 -3.323 36.373 -3.172 36.972 -3.161 c
+37.56 -3.161 l
+37.56 -2.631 l
+37.56 -2.338 37.49 -2.128 37.354 -1.999 c
+37.225 -1.875 37.03 -1.808 36.766 -1.808 c
+36.519 -1.808 36.317 -1.881 36.163 -2.029 c
+36.016 -2.176 35.943 -2.363 35.943 -2.587 c
+35.12 -2.587 l
+35.12 -2.334 35.193 -2.087 35.34 -1.852 c
+35.495 -1.617 35.7 -1.437 35.958 -1.309 c
+36.211 -1.183 36.494 -1.118 36.81 -1.118 c
+37.317 -1.118 37.707 -1.246 37.971 -1.5 c
+38.236 -1.746 38.368 -2.114 38.368 -2.602 c
+38.368 -5.101 l
+38.376 -5.484 38.431 -5.818 38.53 -6.101 c
+38.53 -6.174 l
+h
+36.604 -5.527 m
+36.799 -5.527 36.986 -5.476 37.163 -5.366 c
+37.346 -5.248 37.479 -5.112 37.56 -4.954 c
+37.56 -3.763 l
+37.104 -3.763 l
+36.722 -3.774 36.417 -3.863 36.193 -4.028 c
+35.965 -4.197 35.854 -4.425 35.854 -4.719 c
+35.854 -5.006 35.906 -5.212 36.016 -5.336 c
+36.134 -5.465 36.328 -5.527 36.604 -5.527 c
+40.323 -6.174 -0.808 7.056 re
+41.566 -5.733 m
+41.566 -5.586 41.61 -5.465 41.697 -5.366 c
+41.786 -5.27 41.911 -5.218 42.08 -5.218 c
+42.256 -5.218 42.389 -5.27 42.476 -5.366 c
+42.572 -5.465 42.624 -5.586 42.624 -5.733 c
+42.624 -5.873 42.572 -5.991 42.476 -6.086 c
+42.389 -6.174 42.256 -6.218 42.08 -6.218 c
+41.911 -6.218 41.786 -6.174 41.697 -6.086 c
+41.61 -5.991 41.566 -5.873 41.566 -5.733 c
+41.566 -1.97 m
+41.566 -1.823 41.61 -1.702 41.697 -1.603 c
+41.786 -1.507 41.911 -1.455 42.08 -1.455 c
+42.256 -1.455 42.389 -1.507 42.476 -1.603 c
+42.572 -1.702 42.624 -1.823 42.624 -1.97 c
+42.624 -2.11 42.572 -2.228 42.476 -2.323 c
+42.389 -2.411 42.256 -2.455 42.08 -2.455 c
+41.911 -2.455 41.786 -2.411 41.697 -2.323 c
+41.61 -2.228 41.566 -2.11 41.566 -1.97 c
+f
+Q
+537.111 348.557 -0.838 6.688 re
+538.735 348.557 m
+538.735 352.864 l
+538.089 352.864 l
+538.089 353.525 l
+538.735 353.525 l
+538.735 354.099 l
+538.743 354.606 538.871 355.003 539.118 355.289 c
+539.361 355.572 539.71 355.715 540.161 355.715 c
+540.315 355.715 540.477 355.686 540.647 355.628 c
+540.602 354.936 l
+540.492 354.967 540.371 354.981 540.235 354.981 c
+539.772 354.981 539.544 354.65 539.544 353.996 c
+539.544 353.525 l
+540.396 353.525 l
+540.396 352.864 l
+539.544 352.864 l
+539.544 348.557 l
+h
+544.655 349.91 m
+545.553 353.525 l
+546.419 353.525 l
+544.788 347.852 l
+544.67 347.433 544.497 347.109 544.273 346.882 c
+544.046 346.657 543.792 346.543 543.509 346.543 c
+543.398 346.543 543.263 346.57 543.097 346.617 c
+543.097 347.308 l
+543.274 347.293 l
+543.509 347.293 543.689 347.352 543.818 347.47 c
+543.953 347.58 544.061 347.771 544.141 348.043 c
+544.302 348.602 l
+542.848 353.525 l
+543.729 353.525 l
+h
+546.816 351.277 m
+546.816 351.989 546.985 352.559 547.331 352.982 c
+547.683 353.4 548.146 353.614 548.728 353.614 c
+549.304 353.614 549.763 353.408 550.109 352.997 c
+550.461 352.592 550.642 352.033 550.652 351.321 c
+550.652 350.807 l
+550.652 350.078 550.476 349.506 550.124 349.087 c
+549.778 348.675 549.318 348.469 548.742 348.469 c
+548.161 348.469 547.698 348.667 547.346 349.072 c
+547 349.483 546.824 350.034 546.816 350.733 c
+h
+547.625 350.807 m
+547.625 350.296 547.72 349.895 547.919 349.601 c
+548.125 349.307 548.396 349.16 548.742 349.16 c
+549.455 349.16 549.823 349.678 549.844 350.718 c
+549.844 351.277 l
+549.844 351.784 549.742 352.188 549.536 352.482 c
+549.337 352.776 549.069 352.923 548.728 352.923 c
+548.393 352.923 548.125 352.776 547.919 352.482 c
+547.72 352.188 547.625 351.784 547.625 351.277 c
+h
+554.052 348.999 m
+553.776 348.646 553.38 348.469 552.861 348.469 c
+552.42 348.469 552.082 348.619 551.847 348.925 c
+551.619 349.237 551.502 349.693 551.494 350.292 c
+551.494 353.525 l
+552.302 353.525 l
+552.302 350.35 l
+552.302 349.575 552.538 349.189 553.008 349.189 c
+553.497 349.189 553.835 349.41 554.022 349.851 c
+554.022 353.525 l
+554.845 353.525 l
+554.845 348.557 l
+554.066 348.557 l
+h
+561.651 349.983 m
+562.415 353.525 l
+563.209 353.525 l
+562.004 348.557 l
+561.357 348.557 l
+560.387 352.114 l
+559.431 348.557 l
+558.785 348.557 l
+557.58 353.525 l
+558.373 353.525 l
+559.153 350.071 l
+560.063 353.525 l
+560.711 353.525 l
+h
+566.381 348.557 m
+566.33 348.664 566.296 348.844 566.278 349.101 c
+565.991 348.679 565.624 348.469 565.175 348.469 c
+564.723 348.469 564.37 348.59 564.117 348.837 c
+563.871 349.09 563.749 349.446 563.749 349.91 c
+563.749 350.417 563.919 350.821 564.264 351.115 c
+564.605 351.409 565.076 351.559 565.675 351.57 c
+566.263 351.57 l
+566.263 352.1 l
+566.263 352.394 566.193 352.603 566.057 352.732 c
+565.929 352.856 565.734 352.923 565.469 352.923 c
+565.223 352.923 565.021 352.85 564.867 352.702 c
+564.72 352.555 564.646 352.368 564.646 352.144 c
+563.823 352.144 l
+563.823 352.397 563.897 352.644 564.044 352.879 c
+564.198 353.114 564.404 353.294 564.661 353.423 c
+564.915 353.548 565.197 353.614 565.513 353.614 c
+566.02 353.614 566.41 353.485 566.675 353.232 c
+566.939 352.985 567.072 352.618 567.072 352.129 c
+567.072 349.631 l
+567.079 349.248 567.134 348.914 567.233 348.631 c
+567.233 348.557 l
+h
+565.308 349.205 m
+565.503 349.205 565.69 349.255 565.866 349.365 c
+566.05 349.483 566.182 349.619 566.263 349.777 c
+566.263 350.968 l
+565.808 350.968 l
+565.426 350.957 565.12 350.869 564.896 350.703 c
+564.668 350.535 564.558 350.306 564.558 350.013 c
+564.558 349.726 564.609 349.52 564.72 349.396 c
+564.838 349.267 565.032 349.205 565.308 349.205 c
+568.909 353.525 m
+568.938 352.997 l
+569.251 353.408 569.651 353.614 570.143 353.614 c
+571.026 353.614 571.47 353.03 571.481 351.865 c
+571.481 348.557 l
+570.673 348.557 l
+570.673 351.821 l
+570.673 352.21 570.606 352.486 570.482 352.644 c
+570.353 352.809 570.159 352.893 569.894 352.893 c
+569.688 352.893 569.504 352.824 569.35 352.688 c
+569.191 352.559 569.064 352.386 568.968 352.173 c
+568.968 348.557 l
+568.144 348.557 l
+568.144 353.525 l
+h
+573.59 354.731 m
+573.59 353.525 l
+574.34 353.525 l
+574.34 352.864 l
+573.59 352.864 l
+573.59 349.792 l
+573.59 349.594 573.62 349.443 573.679 349.336 c
+573.745 349.237 573.858 349.189 574.017 349.189 c
+574.124 349.189 574.23 349.207 574.34 349.248 c
+574.326 348.557 l
+574.149 348.499 573.962 348.469 573.767 348.469 c
+573.444 348.469 573.197 348.579 573.032 348.808 c
+572.863 349.043 572.782 349.365 572.782 349.777 c
+572.782 352.864 l
+572.017 352.864 l
+572.017 353.525 l
+572.782 353.525 l
+572.782 354.731 l
+h
+577.081 351.277 m
+577.081 351.989 577.251 352.559 577.596 352.982 c
+577.949 353.4 578.412 353.614 578.992 353.614 c
+579.57 353.614 580.029 353.408 580.374 352.997 c
+580.727 352.592 580.907 352.033 580.918 351.321 c
+580.918 350.807 l
+580.918 350.078 580.742 349.506 580.389 349.087 c
+580.044 348.675 579.584 348.469 579.007 348.469 c
+578.427 348.469 577.964 348.667 577.611 349.072 c
+577.265 349.483 577.089 350.034 577.081 350.733 c
+h
+577.891 350.807 m
+577.891 350.296 577.986 349.895 578.184 349.601 c
+578.39 349.307 578.662 349.16 579.007 349.16 c
+579.72 349.16 580.087 349.678 580.11 350.718 c
+580.11 351.277 l
+580.11 351.784 580.007 352.188 579.801 352.482 c
+579.603 352.776 579.335 352.923 578.992 352.923 c
+578.658 352.923 578.39 352.776 578.184 352.482 c
+577.986 352.188 577.891 351.784 577.891 351.277 c
+h
+583.836 352.761 m
+583.718 352.779 583.593 352.791 583.468 352.791 c
+583.046 352.791 582.755 352.563 582.601 352.114 c
+582.601 348.557 l
+581.778 348.557 l
+581.778 353.525 l
+582.572 353.525 l
+582.587 353.026 l
+582.799 353.415 583.108 353.614 583.512 353.614 c
+583.637 353.614 583.748 353.592 583.836 353.555 c
+h
+587.356 353.525 m
+587.385 352.997 l
+587.698 353.408 588.098 353.614 588.591 353.614 c
+589.473 353.614 589.918 353.03 589.928 351.865 c
+589.928 348.557 l
+589.12 348.557 l
+589.12 351.821 l
+589.12 352.21 589.054 352.486 588.929 352.644 c
+588.8 352.809 588.606 352.893 588.341 352.893 c
+588.135 352.893 587.952 352.824 587.797 352.688 c
+587.639 352.559 587.51 352.386 587.415 352.173 c
+587.415 348.557 l
+586.592 348.557 l
+586.592 353.525 l
+h
+592.748 348.469 m
+592.13 348.469 591.652 348.65 591.321 349.013 c
+590.998 349.384 590.828 349.928 590.822 350.645 c
+590.822 351.247 l
+590.822 351.983 590.984 352.559 591.306 352.982 c
+591.63 353.4 592.079 353.614 592.659 353.614 c
+593.236 353.614 593.666 353.427 593.953 353.055 c
+594.246 352.692 594.397 352.118 594.408 351.335 c
+594.408 350.807 l
+591.63 350.807 l
+591.63 350.689 l
+591.63 350.148 591.726 349.755 591.924 349.513 c
+592.13 349.278 592.417 349.16 592.791 349.16 c
+593.034 349.16 593.247 349.205 593.423 349.292 c
+593.607 349.38 593.78 349.52 593.938 349.718 c
+594.364 349.205 l
+594.011 348.712 593.471 348.469 592.748 348.469 c
+592.659 352.923 m
+592.324 352.923 592.075 352.806 591.909 352.57 c
+591.74 352.342 591.649 351.986 591.63 351.497 c
+593.585 351.497 l
+593.585 351.615 l
+593.563 352.085 593.482 352.416 593.336 352.615 c
+593.188 352.82 592.96 352.923 592.659 352.923 c
+596.981 348.469 m
+596.363 348.469 595.885 348.65 595.555 349.013 c
+595.231 349.384 595.062 349.928 595.055 350.645 c
+595.055 351.247 l
+595.055 351.983 595.217 352.559 595.54 352.982 c
+595.863 353.4 596.312 353.614 596.893 353.614 c
+597.469 353.614 597.899 353.427 598.186 353.055 c
+598.479 352.692 598.63 352.118 598.641 351.335 c
+598.641 350.807 l
+595.863 350.807 l
+595.863 350.689 l
+595.863 350.148 595.959 349.755 596.158 349.513 c
+596.363 349.278 596.65 349.16 597.024 349.16 c
+597.267 349.16 597.48 349.205 597.656 349.292 c
+597.841 349.38 598.013 349.52 598.171 349.718 c
+598.597 349.205 l
+598.244 348.712 597.704 348.469 596.981 348.469 c
+596.893 352.923 m
+596.558 352.923 596.308 352.806 596.143 352.57 c
+595.973 352.342 595.882 351.986 595.863 351.497 c
+597.818 351.497 l
+597.818 351.615 l
+597.797 352.085 597.716 352.416 597.569 352.615 c
+597.421 352.82 597.193 352.923 596.893 352.923 c
+599.273 351.262 m
+599.273 352.033 599.413 352.618 599.7 353.011 c
+599.983 353.412 600.394 353.614 600.935 353.614 c
+601.405 353.614 601.772 353.423 602.037 353.041 c
+602.037 355.613 l
+602.861 355.613 l
+602.861 348.557 l
+602.111 348.557 l
+602.067 349.087 l
+601.802 348.675 601.423 348.469 600.935 348.469 c
+600.413 348.469 600.008 348.664 599.715 349.057 c
+599.42 349.458 599.273 350.028 599.273 350.762 c
+h
+600.082 350.807 m
+600.082 350.248 600.162 349.836 600.332 349.571 c
+600.497 349.315 600.766 349.189 601.14 349.189 c
+601.541 349.189 601.839 349.388 602.037 349.792 c
+602.037 352.305 l
+601.831 352.695 601.529 352.893 601.14 352.893 c
+600.766 352.893 600.497 352.761 600.332 352.497 c
+600.162 352.239 600.082 351.842 600.082 351.306 c
+h
+607.053 354.731 m
+607.053 353.525 l
+607.802 353.525 l
+607.802 352.864 l
+607.053 352.864 l
+607.053 349.792 l
+607.053 349.594 607.083 349.443 607.141 349.336 c
+607.208 349.237 607.322 349.189 607.48 349.189 c
+607.586 349.189 607.692 349.207 607.802 349.248 c
+607.788 348.557 l
+607.611 348.499 607.424 348.469 607.229 348.469 c
+606.906 348.469 606.66 348.579 606.495 348.808 c
+606.325 349.043 606.244 349.365 606.244 349.777 c
+606.244 352.864 l
+605.48 352.864 l
+605.48 353.525 l
+606.244 353.525 l
+606.244 354.731 l
+h
+608.39 351.277 m
+608.39 351.989 608.56 352.559 608.905 352.982 c
+609.258 353.4 609.72 353.614 610.302 353.614 c
+610.878 353.614 611.338 353.408 611.683 352.997 c
+612.036 352.592 612.216 352.033 612.227 351.321 c
+612.227 350.807 l
+612.227 350.078 612.051 349.506 611.698 349.087 c
+611.353 348.675 610.894 348.469 610.316 348.469 c
+609.735 348.469 609.273 348.667 608.92 349.072 c
+608.575 349.483 608.398 350.034 608.39 350.733 c
+h
+609.199 350.807 m
+609.199 350.296 609.294 349.895 609.493 349.601 c
+609.699 349.307 609.971 349.16 610.316 349.16 c
+611.029 349.16 611.397 349.678 611.418 350.718 c
+611.418 351.277 l
+611.418 351.784 611.316 352.188 611.11 352.482 c
+610.911 352.776 610.643 352.923 610.302 352.923 c
+609.967 352.923 609.699 352.776 609.493 352.482 c
+609.294 352.188 609.199 351.784 609.199 351.277 c
+h
+616.034 348.557 -0.808 4.968 re
+616.093 354.849 m
+616.093 354.709 616.053 354.591 615.975 354.496 c
+615.906 354.408 615.792 354.364 615.638 354.364 c
+615.48 354.364 615.362 354.408 615.285 354.496 c
+615.214 354.591 615.181 354.709 615.181 354.849 c
+615.181 354.984 615.214 355.098 615.285 355.187 c
+615.362 355.282 615.476 355.333 615.623 355.333 c
+615.777 355.333 615.894 355.282 615.975 355.187 c
+616.053 355.098 616.093 354.984 616.093 354.849 c
+617.978 353.525 m
+618.007 352.997 l
+618.32 353.408 618.721 353.614 619.212 353.614 c
+620.095 353.614 620.539 353.03 620.55 351.865 c
+620.55 348.557 l
+619.742 348.557 l
+619.742 351.821 l
+619.742 352.21 619.676 352.486 619.551 352.644 c
+619.422 352.809 619.228 352.893 618.963 352.893 c
+618.757 352.893 618.574 352.824 618.419 352.688 c
+618.261 352.559 618.133 352.386 618.036 352.173 c
+618.036 348.557 l
+617.213 348.557 l
+617.213 353.525 l
+h
+624.016 349.836 m
+624.016 350.001 623.946 350.148 623.81 350.277 c
+623.681 350.402 623.428 350.549 623.046 350.718 c
+622.612 350.902 622.304 351.06 622.119 351.189 c
+621.943 351.314 621.811 351.457 621.722 351.615 c
+621.635 351.78 621.591 351.975 621.591 352.203 c
+621.591 352.615 621.737 352.952 622.031 353.217 c
+622.325 353.481 622.7 353.614 623.164 353.614 c
+623.652 353.614 624.045 353.471 624.339 353.188 c
+624.633 352.912 624.78 352.555 624.78 352.114 c
+623.972 352.114 l
+623.972 352.339 623.891 352.53 623.737 352.688 c
+623.59 352.842 623.399 352.923 623.164 352.923 c
+622.928 352.923 622.74 352.856 622.605 352.732 c
+622.465 352.615 622.399 352.445 622.399 352.232 c
+622.399 352.063 622.447 351.931 622.546 351.835 c
+622.641 351.736 622.884 351.603 623.266 351.439 c
+623.872 351.204 624.284 350.971 624.5 350.747 c
+624.714 350.52 624.824 350.237 624.824 349.895 c
+624.824 349.461 624.67 349.116 624.369 348.852 c
+624.074 348.594 623.677 348.469 623.178 348.469 c
+622.667 348.469 622.252 348.617 621.928 348.91 c
+621.605 349.205 621.443 349.579 621.443 350.042 c
+622.266 350.042 l
+622.274 349.766 622.358 349.55 622.516 349.396 c
+622.671 349.237 622.891 349.16 623.178 349.16 c
+623.45 349.16 623.656 349.219 623.795 349.336 c
+623.943 349.461 624.016 349.631 624.016 349.836 c
+626.772 354.731 m
+626.772 353.525 l
+627.521 353.525 l
+627.521 352.864 l
+626.772 352.864 l
+626.772 349.792 l
+626.772 349.594 626.801 349.443 626.86 349.336 c
+626.927 349.237 627.04 349.189 627.198 349.189 c
+627.305 349.189 627.411 349.207 627.521 349.248 c
+627.507 348.557 l
+627.33 348.499 627.143 348.469 626.948 348.469 c
+626.625 348.469 626.379 348.579 626.213 348.808 c
+626.044 349.043 625.963 349.365 625.963 349.777 c
+625.963 352.864 l
+625.199 352.864 l
+625.199 353.525 l
+625.963 353.525 l
+625.963 354.731 l
+h
+630.921 348.557 m
+630.869 348.664 630.836 348.844 630.817 349.101 c
+630.531 348.679 630.164 348.469 629.715 348.469 c
+629.263 348.469 628.911 348.59 628.657 348.837 c
+628.411 349.09 628.29 349.446 628.29 349.91 c
+628.29 350.417 628.458 350.821 628.804 351.115 c
+629.146 351.409 629.616 351.559 630.215 351.57 c
+630.803 351.57 l
+630.803 352.1 l
+630.803 352.394 630.733 352.603 630.597 352.732 c
+630.468 352.856 630.274 352.923 630.009 352.923 c
+629.763 352.923 629.561 352.85 629.406 352.702 c
+629.26 352.555 629.186 352.368 629.186 352.144 c
+628.363 352.144 l
+628.363 352.397 628.436 352.644 628.583 352.879 c
+628.737 353.114 628.943 353.294 629.201 353.423 c
+629.454 353.548 629.737 353.614 630.054 353.614 c
+630.561 353.614 630.95 353.485 631.214 353.232 c
+631.479 352.985 631.611 352.618 631.611 352.129 c
+631.611 349.631 l
+631.619 349.248 631.674 348.914 631.773 348.631 c
+631.773 348.557 l
+h
+629.848 349.205 m
+630.042 349.205 630.229 349.255 630.406 349.365 c
+630.59 349.483 630.722 349.619 630.803 349.777 c
+630.803 350.968 l
+630.347 350.968 l
+629.965 350.957 629.66 350.869 629.436 350.703 c
+629.208 350.535 629.098 350.306 629.098 350.013 c
+629.098 349.726 629.15 349.52 629.26 349.396 c
+629.377 349.267 629.572 349.205 629.848 349.205 c
+633.566 348.557 -0.808 7.056 re
+635.628 348.557 -0.809 7.056 re
+643.183 349.396 m
+643.037 349.205 l
+642.613 348.712 641.996 348.469 641.184 348.469 c
+640.456 348.469 639.891 348.708 639.479 349.189 c
+639.068 349.667 638.854 350.343 638.847 351.218 c
+638.847 352.526 l
+638.847 353.467 639.031 354.165 639.405 354.628 c
+639.777 355.098 640.339 355.333 641.096 355.333 c
+641.732 355.333 642.228 355.158 642.58 354.805 c
+642.941 354.452 643.143 353.945 643.183 353.29 c
+642.345 353.29 l
+642.305 353.702 642.187 354.026 641.992 354.261 c
+641.794 354.496 641.497 354.614 641.096 354.614 c
+640.614 354.614 640.261 354.456 640.038 354.143 c
+639.81 353.827 639.692 353.327 639.685 352.644 c
+639.685 351.277 l
+639.685 350.601 639.81 350.078 640.067 349.718 c
+640.332 349.365 640.703 349.189 641.184 349.189 c
+641.632 349.189 641.978 349.296 642.214 349.513 c
+642.345 349.631 l
+642.345 351.173 l
+641.111 351.173 l
+641.111 351.894 l
+643.183 351.894 l
+h
+645.102 348.557 -0.809 4.968 re
+645.16 354.849 m
+645.16 354.709 645.119 354.591 645.042 354.496 c
+644.973 354.408 644.859 354.364 644.705 354.364 c
+644.547 354.364 644.429 354.408 644.352 354.496 c
+644.282 354.591 644.249 354.709 644.249 354.849 c
+644.249 354.984 644.282 355.098 644.352 355.187 c
+644.429 355.282 644.543 355.333 644.69 355.333 c
+644.844 355.333 644.961 355.282 645.042 355.187 c
+645.119 355.098 645.16 354.984 645.16 354.849 c
+647.358 354.731 m
+647.358 353.525 l
+648.107 353.525 l
+648.107 352.864 l
+647.358 352.864 l
+647.358 349.792 l
+647.358 349.594 647.388 349.443 647.446 349.336 c
+647.512 349.237 647.626 349.189 647.784 349.189 c
+647.891 349.189 647.997 349.207 648.107 349.248 c
+648.093 348.557 l
+647.916 348.499 647.729 348.469 647.534 348.469 c
+647.211 348.469 646.964 348.579 646.8 348.808 c
+646.63 349.043 646.549 349.365 646.549 349.777 c
+646.549 352.864 l
+645.785 352.864 l
+645.785 353.525 l
+646.549 353.525 l
+646.549 354.731 l
+h
+651.378 348.557 m
+651.378 352.864 l
+650.731 352.864 l
+650.731 353.525 l
+651.378 353.525 l
+651.378 354.099 l
+651.386 354.606 651.514 355.003 651.76 355.289 c
+652.003 355.572 652.352 355.715 652.803 355.715 c
+652.958 355.715 653.12 355.686 653.289 355.628 c
+653.245 354.936 l
+653.135 354.967 653.013 354.981 652.878 354.981 c
+652.414 354.981 652.186 354.65 652.186 353.996 c
+652.186 353.525 l
+653.039 353.525 l
+653.039 352.864 l
+652.186 352.864 l
+652.186 348.557 l
+h
+655.928 352.761 m
+655.81 352.779 655.685 352.791 655.56 352.791 c
+655.137 352.791 654.847 352.563 654.692 352.114 c
+654.692 348.557 l
+653.869 348.557 l
+653.869 353.525 l
+654.663 353.525 l
+654.678 353.026 l
+654.891 353.415 655.2 353.614 655.604 353.614 c
+655.729 353.614 655.839 353.592 655.928 353.555 c
+h
+656.368 351.277 m
+656.368 351.989 656.537 352.559 656.883 352.982 c
+657.235 353.4 657.698 353.614 658.279 353.614 c
+658.856 353.614 659.315 353.408 659.661 352.997 c
+660.013 352.592 660.194 352.033 660.205 351.321 c
+660.205 350.807 l
+660.205 350.078 660.028 349.506 659.676 349.087 c
+659.33 348.675 658.871 348.469 658.294 348.469 c
+657.713 348.469 657.25 348.667 656.898 349.072 c
+656.552 349.483 656.375 350.034 656.368 350.733 c
+h
+657.177 350.807 m
+657.177 350.296 657.272 349.895 657.47 349.601 c
+657.677 349.307 657.948 349.16 658.294 349.16 c
+659.007 349.16 659.375 349.678 659.396 350.718 c
+659.396 351.277 l
+659.396 351.784 659.294 352.188 659.088 352.482 c
+658.889 352.776 658.621 352.923 658.279 352.923 c
+657.945 352.923 657.677 352.776 657.47 352.482 c
+657.272 352.188 657.177 351.784 657.177 351.277 c
+h
+661.829 353.525 m
+661.858 353.07 l
+662.16 353.43 662.557 353.614 663.049 353.614 c
+663.608 353.614 663.994 353.371 664.21 352.893 c
+664.522 353.371 664.96 353.614 665.518 353.614 c
+666.438 353.614 666.908 353.045 666.93 351.909 c
+666.93 348.557 l
+666.122 348.557 l
+666.122 351.835 l
+666.122 352.188 666.051 352.453 665.915 352.629 c
+665.787 352.806 665.57 352.893 665.268 352.893 c
+665.023 352.893 664.82 352.798 664.666 352.615 c
+664.518 352.427 664.431 352.188 664.402 351.894 c
+664.402 348.557 l
+663.593 348.557 l
+663.593 351.865 l
+663.581 352.548 663.303 352.893 662.756 352.893 c
+662.344 352.893 662.053 352.688 661.888 352.276 c
+661.888 348.557 l
+661.079 348.557 l
+661.079 353.525 l
+h
+672.346 349.836 m
+672.346 350.001 672.277 350.148 672.14 350.277 c
+672.011 350.402 671.758 350.549 671.376 350.718 c
+670.943 350.902 670.633 351.06 670.45 351.189 c
+670.274 351.314 670.141 351.457 670.053 351.615 c
+669.965 351.78 669.921 351.975 669.921 352.203 c
+669.921 352.615 670.068 352.952 670.361 353.217 c
+670.656 353.481 671.03 353.614 671.494 353.614 c
+671.982 353.614 672.376 353.471 672.67 353.188 c
+672.964 352.912 673.11 352.555 673.11 352.114 c
+672.302 352.114 l
+672.302 352.339 672.221 352.53 672.067 352.688 c
+671.92 352.842 671.729 352.923 671.494 352.923 c
+671.259 352.923 671.071 352.856 670.935 352.732 c
+670.795 352.615 670.729 352.445 670.729 352.232 c
+670.729 352.063 670.777 351.931 670.876 351.835 c
+670.972 351.736 671.215 351.603 671.597 351.439 c
+672.202 351.204 672.615 350.971 672.831 350.747 c
+673.044 350.52 673.154 350.237 673.154 349.895 c
+673.154 349.461 673 349.116 672.699 348.852 c
+672.405 348.594 672.008 348.469 671.508 348.469 c
+670.997 348.469 670.582 348.617 670.259 348.91 c
+669.935 349.205 669.773 349.579 669.773 350.042 c
+670.597 350.042 l
+670.604 349.766 670.689 349.55 670.847 349.396 c
+671.001 349.237 671.222 349.16 671.508 349.16 c
+671.78 349.16 671.986 349.219 672.125 349.336 c
+672.273 349.461 672.346 349.631 672.346 349.836 c
+673.868 351.277 m
+673.868 351.989 674.037 352.559 674.382 352.982 c
+674.735 353.4 675.198 353.614 675.778 353.614 c
+676.356 353.614 676.815 353.408 677.16 352.997 c
+677.513 352.592 677.693 352.033 677.704 351.321 c
+677.704 350.807 l
+677.704 350.078 677.528 349.506 677.175 349.087 c
+676.829 348.675 676.37 348.469 675.793 348.469 c
+675.213 348.469 674.75 348.667 674.396 349.072 c
+674.051 349.483 673.875 350.034 673.868 350.733 c
+h
+674.676 350.807 m
+674.676 350.296 674.772 349.895 674.97 349.601 c
+675.176 349.307 675.448 349.16 675.793 349.16 c
+676.506 349.16 676.873 349.678 676.896 350.718 c
+676.896 351.277 l
+676.896 351.784 676.792 352.188 676.587 352.482 c
+676.389 352.776 676.121 352.923 675.778 352.923 c
+675.444 352.923 675.176 352.776 674.97 352.482 c
+674.772 352.188 674.676 351.784 674.676 351.277 c
+h
+681.107 348.999 m
+680.831 348.646 680.434 348.469 679.917 348.469 c
+679.475 348.469 679.138 348.619 678.902 348.925 c
+678.674 349.237 678.556 349.693 678.55 350.292 c
+678.55 353.525 l
+679.358 353.525 l
+679.358 350.35 l
+679.358 349.575 679.593 349.189 680.063 349.189 c
+680.552 349.189 680.89 349.41 681.077 349.851 c
+681.077 353.525 l
+681.901 353.525 l
+681.901 348.557 l
+681.122 348.557 l
+h
+684.995 352.761 m
+684.877 352.779 684.752 352.791 684.628 352.791 c
+684.204 352.791 683.915 352.563 683.76 352.114 c
+683.76 348.557 l
+682.937 348.557 l
+682.937 353.525 l
+683.73 353.525 l
+683.745 353.026 l
+683.959 353.415 684.267 353.614 684.671 353.614 c
+684.796 353.614 684.906 353.592 684.995 353.555 c
+h
+687.335 349.16 m
+687.6 349.16 687.809 349.241 687.967 349.41 c
+688.133 349.575 688.225 349.814 688.247 350.13 c
+689.012 350.13 l
+688.989 349.649 688.821 349.252 688.497 348.939 c
+688.181 348.623 687.795 348.469 687.335 348.469 c
+686.718 348.469 686.248 348.66 685.924 349.043 c
+685.601 349.432 685.44 350.013 685.44 350.776 c
+685.44 351.321 l
+685.44 352.074 685.601 352.644 685.924 353.026 c
+686.248 353.415 686.711 353.614 687.321 353.614 c
+687.828 353.614 688.233 353.452 688.526 353.128 c
+688.827 352.812 688.989 352.38 689.012 351.821 c
+688.247 351.821 l
+688.225 352.181 688.137 352.457 687.982 352.644 c
+687.824 352.827 687.604 352.923 687.321 352.923 c
+686.968 352.923 686.704 352.798 686.527 352.555 c
+686.351 352.32 686.255 351.931 686.248 351.395 c
+686.248 350.762 l
+686.248 350.174 686.336 349.755 686.512 349.513 c
+686.689 349.278 686.961 349.16 687.335 349.16 c
+691.558 348.469 m
+690.94 348.469 690.463 348.65 690.132 349.013 c
+689.808 349.384 689.64 349.928 689.632 350.645 c
+689.632 351.247 l
+689.632 351.983 689.794 352.559 690.117 352.982 c
+690.441 353.4 690.889 353.614 691.47 353.614 c
+692.046 353.614 692.476 353.427 692.763 353.055 c
+693.057 352.692 693.208 352.118 693.219 351.335 c
+693.219 350.807 l
+690.441 350.807 l
+690.441 350.689 l
+690.441 350.148 690.536 349.755 690.735 349.513 c
+690.94 349.278 691.227 349.16 691.602 349.16 c
+691.844 349.16 692.058 349.205 692.234 349.292 c
+692.418 349.38 692.59 349.52 692.748 349.718 c
+693.174 349.205 l
+692.822 348.712 692.282 348.469 691.558 348.469 c
+691.47 352.923 m
+691.135 352.923 690.886 352.806 690.72 352.57 c
+690.551 352.342 690.459 351.986 690.441 351.497 c
+692.395 351.497 l
+692.395 351.615 l
+692.374 352.085 692.293 352.416 692.146 352.615 c
+691.998 352.82 691.771 352.923 691.47 352.923 c
+694.028 347.22 m
+693.542 347.558 l
+693.825 347.962 693.976 348.374 693.997 348.792 c
+693.997 349.557 l
+694.821 349.557 l
+694.821 348.895 l
+694.821 348.59 694.741 348.285 694.585 347.969 c
+694.439 347.657 694.252 347.407 694.028 347.22 c
+699.227 349.91 m
+700.124 353.525 l
+700.991 353.525 l
+699.36 347.852 l
+699.242 347.433 699.069 347.109 698.845 346.882 c
+698.617 346.657 698.363 346.543 698.08 346.543 c
+697.97 346.543 697.835 346.57 697.669 346.617 c
+697.669 347.308 l
+697.845 347.293 l
+698.08 347.293 698.261 347.352 698.389 347.47 c
+698.525 347.58 698.632 347.771 698.712 348.043 c
+698.874 348.602 l
+697.419 353.525 l
+698.301 353.525 l
+h
+701.384 351.277 m
+701.384 351.989 701.554 352.559 701.899 352.982 c
+702.252 353.4 702.714 353.614 703.295 353.614 c
+703.872 353.614 704.331 353.408 704.677 352.997 c
+705.03 352.592 705.209 352.033 705.221 351.321 c
+705.221 350.807 l
+705.221 350.078 705.045 349.506 704.692 349.087 c
+704.346 348.675 703.887 348.469 703.31 348.469 c
+702.729 348.469 702.267 348.667 701.913 349.072 c
+701.568 349.483 701.392 350.034 701.384 350.733 c
+h
+702.192 350.807 m
+702.192 350.296 702.288 349.895 702.487 349.601 c
+702.693 349.307 702.965 349.16 703.31 349.16 c
+704.023 349.16 704.39 349.678 704.412 350.718 c
+704.412 351.277 l
+704.412 351.784 704.309 352.188 704.104 352.482 c
+703.905 352.776 703.637 352.923 703.295 352.923 c
+702.961 352.923 702.693 352.776 702.487 352.482 c
+702.288 352.188 702.192 351.784 702.192 351.277 c
+h
+708.623 348.999 m
+708.348 348.646 707.951 348.469 707.433 348.469 c
+706.992 348.469 706.654 348.619 706.419 348.925 c
+706.19 349.237 706.073 349.693 706.066 350.292 c
+706.066 353.525 l
+706.874 353.525 l
+706.874 350.35 l
+706.874 349.575 707.109 349.189 707.58 349.189 c
+708.068 349.189 708.407 349.41 708.594 349.851 c
+708.594 353.525 l
+709.417 353.525 l
+709.417 348.557 l
+708.638 348.557 l
+h
+714.253 349.16 m
+714.518 349.16 714.728 349.241 714.886 349.41 c
+715.05 349.575 715.143 349.814 715.164 350.13 c
+715.929 350.13 l
+715.907 349.649 715.738 349.252 715.414 348.939 c
+715.098 348.623 714.713 348.469 714.253 348.469 c
+713.635 348.469 713.165 348.66 712.842 349.043 c
+712.519 349.432 712.357 350.013 712.357 350.776 c
+712.357 351.321 l
+712.357 352.074 712.519 352.644 712.842 353.026 c
+713.165 353.415 713.629 353.614 714.238 353.614 c
+714.745 353.614 715.15 353.452 715.444 353.128 c
+715.745 352.812 715.907 352.38 715.929 351.821 c
+715.164 351.821 l
+715.143 352.181 715.054 352.457 714.9 352.644 c
+714.742 352.827 714.522 352.923 714.238 352.923 c
+713.886 352.923 713.621 352.798 713.444 352.555 c
+713.269 352.32 713.173 351.931 713.165 351.395 c
+713.165 350.762 l
+713.165 350.174 713.253 349.755 713.43 349.513 c
+713.606 349.278 713.878 349.16 714.253 349.16 c
+719.254 348.557 m
+719.203 348.664 719.17 348.844 719.152 349.101 c
+718.865 348.679 718.497 348.469 718.049 348.469 c
+717.597 348.469 717.244 348.59 716.991 348.837 c
+716.745 349.09 716.623 349.446 716.623 349.91 c
+716.623 350.417 716.793 350.821 717.138 351.115 c
+717.479 351.409 717.95 351.559 718.549 351.57 c
+719.137 351.57 l
+719.137 352.1 l
+719.137 352.394 719.067 352.603 718.931 352.732 c
+718.803 352.856 718.608 352.923 718.343 352.923 c
+718.097 352.923 717.895 352.85 717.741 352.702 c
+717.593 352.555 717.52 352.368 717.52 352.144 c
+716.697 352.144 l
+716.697 352.397 716.77 352.644 716.918 352.879 c
+717.072 353.114 717.278 353.294 717.535 353.423 c
+717.789 353.548 718.071 353.614 718.387 353.614 c
+718.894 353.614 719.284 353.485 719.549 353.232 c
+719.813 352.985 719.945 352.618 719.945 352.129 c
+719.945 349.631 l
+719.952 349.248 720.008 348.914 720.107 348.631 c
+720.107 348.557 l
+h
+718.181 349.205 m
+718.376 349.205 718.564 349.255 718.74 349.365 c
+718.924 349.483 719.056 349.619 719.137 349.777 c
+719.137 350.968 l
+718.682 350.968 l
+718.299 350.957 717.994 350.869 717.77 350.703 c
+717.542 350.535 717.432 350.306 717.432 350.013 c
+717.432 349.726 717.483 349.52 717.593 349.396 c
+717.711 349.267 717.905 349.205 718.181 349.205 c
+721.783 353.525 m
+721.812 352.997 l
+722.125 353.408 722.525 353.614 723.017 353.614 c
+723.9 353.614 724.344 353.03 724.355 351.865 c
+724.355 348.557 l
+723.547 348.557 l
+723.547 351.821 l
+723.547 352.21 723.48 352.486 723.355 352.644 c
+723.227 352.809 723.032 352.893 722.767 352.893 c
+722.562 352.893 722.378 352.824 722.223 352.688 c
+722.065 352.559 721.937 352.386 721.841 352.173 c
+721.841 348.557 l
+721.018 348.557 l
+721.018 353.525 l
+h
+727.295 351.262 m
+727.295 352.033 727.434 352.618 727.721 353.011 c
+728.004 353.412 728.415 353.614 728.956 353.614 c
+729.463 353.614 729.853 353.397 730.117 352.967 c
+730.146 353.525 l
+730.881 353.525 l
+730.881 348.513 l
+730.881 347.896 730.724 347.426 730.411 347.102 c
+730.096 346.772 729.662 346.602 729.103 346.602 c
+728.857 346.602 728.577 346.668 728.265 346.793 c
+727.96 346.911 727.736 347.058 727.588 347.235 c
+727.912 347.793 l
+728.254 347.462 728.625 347.293 729.03 347.293 c
+729.705 347.293 730.051 347.661 730.073 348.396 c
+730.073 349.043 l
+729.809 348.66 729.433 348.469 728.956 348.469 c
+728.434 348.469 728.033 348.66 727.75 349.043 c
+727.464 349.432 727.313 349.99 727.295 350.718 c
+h
+728.118 350.807 m
+728.118 350.248 728.195 349.836 728.353 349.571 c
+728.519 349.315 728.787 349.189 729.161 349.189 c
+729.562 349.189 729.867 349.396 730.073 349.807 c
+730.073 352.291 l
+729.867 352.692 729.566 352.893 729.176 352.893 c
+728.802 352.893 728.533 352.761 728.368 352.497 c
+728.199 352.239 728.118 351.842 728.118 351.306 c
+h
+733.682 348.469 m
+733.065 348.469 732.587 348.65 732.255 349.013 c
+731.933 349.384 731.763 349.928 731.756 350.645 c
+731.756 351.247 l
+731.756 351.983 731.918 352.559 732.241 352.982 c
+732.565 353.4 733.013 353.614 733.593 353.614 c
+734.171 353.614 734.601 353.427 734.887 353.055 c
+735.181 352.692 735.332 352.118 735.343 351.335 c
+735.343 350.807 l
+732.565 350.807 l
+732.565 350.689 l
+732.565 350.148 732.66 349.755 732.858 349.513 c
+733.065 349.278 733.35 349.16 733.726 349.16 c
+733.969 349.16 734.181 349.205 734.358 349.292 c
+734.541 349.38 734.715 349.52 734.873 349.718 c
+735.299 349.205 l
+734.946 348.712 734.406 348.469 733.682 348.469 c
+733.593 352.923 m
+733.259 352.923 733.009 352.806 732.843 352.57 c
+732.675 352.342 732.583 351.986 732.565 351.497 c
+734.52 351.497 l
+734.52 351.615 l
+734.497 352.085 734.416 352.416 734.27 352.615 c
+734.123 352.82 733.895 352.923 733.593 352.923 c
+737.209 354.731 m
+737.209 353.525 l
+737.959 353.525 l
+737.959 352.864 l
+737.209 352.864 l
+737.209 349.792 l
+737.209 349.594 737.239 349.443 737.298 349.336 c
+737.364 349.237 737.478 349.189 737.636 349.189 c
+737.742 349.189 737.849 349.207 737.959 349.248 c
+737.944 348.557 l
+737.768 348.499 737.581 348.469 737.386 348.469 c
+737.063 348.469 736.816 348.579 736.651 348.808 c
+736.482 349.043 736.401 349.365 736.401 349.777 c
+736.401 352.864 l
+735.636 352.864 l
+735.636 353.525 l
+736.401 353.525 l
+736.401 354.731 l
+h
+741.744 348.557 -0.808 4.968 re
+741.803 354.849 m
+741.803 354.709 741.763 354.591 741.685 354.496 c
+741.616 354.408 741.502 354.364 741.347 354.364 c
+741.189 354.364 741.072 354.408 740.994 354.496 c
+740.924 354.591 740.891 354.709 740.891 354.849 c
+740.891 354.984 740.924 355.098 740.994 355.187 c
+741.072 355.282 741.186 355.333 741.333 355.333 c
+741.487 355.333 741.605 355.282 741.685 355.187 c
+741.763 355.098 741.803 354.984 741.803 354.849 c
+744.001 354.731 m
+744.001 353.525 l
+744.75 353.525 l
+744.75 352.864 l
+744.001 352.864 l
+744.001 349.792 l
+744.001 349.594 744.03 349.443 744.089 349.336 c
+744.155 349.237 744.269 349.189 744.427 349.189 c
+744.533 349.189 744.639 349.207 744.75 349.248 c
+744.735 348.557 l
+744.559 348.499 744.371 348.469 744.177 348.469 c
+743.854 348.469 743.607 348.579 743.442 348.808 c
+743.272 349.043 743.192 349.365 743.192 349.777 c
+743.192 352.864 l
+742.428 352.864 l
+742.428 353.525 l
+743.192 353.525 l
+743.192 354.731 l
+h
+748.02 348.557 m
+748.02 352.864 l
+747.374 352.864 l
+747.374 353.525 l
+748.02 353.525 l
+748.02 354.099 l
+748.028 354.606 748.157 355.003 748.402 355.289 c
+748.645 355.572 748.994 355.715 749.447 355.715 c
+749.601 355.715 749.763 355.686 749.931 355.628 c
+749.888 354.936 l
+749.777 354.967 749.655 354.981 749.52 354.981 c
+749.057 354.981 748.829 354.65 748.829 353.996 c
+748.829 353.525 l
+749.682 353.525 l
+749.682 352.864 l
+748.829 352.864 l
+748.829 348.557 l
+h
+752.57 352.761 m
+752.452 352.779 752.327 352.791 752.203 352.791 c
+751.78 352.791 751.49 352.563 751.336 352.114 c
+751.336 348.557 l
+750.512 348.557 l
+750.512 353.525 l
+751.305 353.525 l
+751.32 353.026 l
+751.534 353.415 751.843 353.614 752.246 353.614 c
+752.371 353.614 752.481 353.592 752.57 353.555 c
+h
+753.015 351.277 m
+753.015 351.989 753.183 352.559 753.529 352.982 c
+753.882 353.4 754.345 353.614 754.925 353.614 c
+755.502 353.614 755.962 353.408 756.307 352.997 c
+756.66 352.592 756.84 352.033 756.851 351.321 c
+756.851 350.807 l
+756.851 350.078 756.674 349.506 756.321 349.087 c
+755.976 348.675 755.517 348.469 754.94 348.469 c
+754.359 348.469 753.896 348.667 753.543 349.072 c
+753.198 349.483 753.022 350.034 753.015 350.733 c
+h
+753.823 350.807 m
+753.823 350.296 753.919 349.895 754.117 349.601 c
+754.322 349.307 754.594 349.16 754.94 349.16 c
+755.654 349.16 756.02 349.678 756.043 350.718 c
+756.043 351.277 l
+756.043 351.784 755.94 352.188 755.734 352.482 c
+755.535 352.776 755.267 352.923 754.925 352.923 c
+754.591 352.923 754.322 352.776 754.117 352.482 c
+753.919 352.188 753.823 351.784 753.823 351.277 c
+h
+758.472 353.525 m
+758.501 353.07 l
+758.802 353.43 759.199 353.614 759.691 353.614 c
+760.25 353.614 760.636 353.371 760.853 352.893 c
+761.165 353.371 761.603 353.614 762.161 353.614 c
+763.08 353.614 763.55 353.045 763.572 351.909 c
+763.572 348.557 l
+762.764 348.557 l
+762.764 351.835 l
+762.764 352.188 762.694 352.453 762.558 352.629 c
+762.43 352.806 762.212 352.893 761.911 352.893 c
+761.665 352.893 761.463 352.798 761.308 352.615 c
+761.162 352.427 761.073 352.188 761.044 351.894 c
+761.044 348.557 l
+760.236 348.557 l
+760.236 351.865 l
+760.225 352.548 759.945 352.893 759.398 352.893 c
+758.986 352.893 758.696 352.688 758.53 352.276 c
+758.53 348.557 l
+757.722 348.557 l
+757.722 353.525 l
+h
+f
+q 1 0 0 1 536.9344 341.7219 cm
+0 0 m
+0.302 0.401 0.695 0.603 1.176 0.603 c
+2.058 0.603 2.503 0.019 2.514 -1.146 c
+2.514 -4.453 l
+1.706 -4.453 l
+1.706 -1.19 l
+1.706 -0.801 1.64 -0.525 1.515 -0.367 c
+1.386 -0.201 1.191 -0.118 0.927 -0.118 c
+0.721 -0.118 0.537 -0.187 0.383 -0.323 c
+0.225 -0.452 0.096 -0.625 0 -0.837 c
+0 -4.453 l
+-0.823 -4.453 l
+-0.823 2.602 l
+0 2.602 l
+h
+4.605 1.721 m
+4.605 0.515 l
+5.355 0.515 l
+5.355 -0.147 l
+4.605 -0.147 l
+4.605 -3.218 l
+4.605 -3.417 4.634 -3.568 4.693 -3.674 c
+4.759 -3.773 4.873 -3.821 5.031 -3.821 c
+5.137 -3.821 5.245 -3.803 5.355 -3.763 c
+5.34 -4.453 l
+5.164 -4.512 4.976 -4.542 4.781 -4.542 c
+4.458 -4.542 4.212 -4.432 4.046 -4.203 c
+3.877 -3.968 3.797 -3.645 3.797 -3.233 c
+3.797 -0.147 l
+3.032 -0.147 l
+3.032 0.515 l
+3.797 0.515 l
+3.797 1.721 l
+h
+7.269 1.721 m
+7.269 0.515 l
+8.019 0.515 l
+8.019 -0.147 l
+7.269 -0.147 l
+7.269 -3.218 l
+7.269 -3.417 7.298 -3.568 7.358 -3.674 c
+7.423 -3.773 7.537 -3.821 7.695 -3.821 c
+7.802 -3.821 7.909 -3.803 8.019 -3.763 c
+8.004 -4.453 l
+7.828 -4.512 7.64 -4.542 7.445 -4.542 c
+7.122 -4.542 6.876 -4.432 6.71 -4.203 c
+6.542 -3.968 6.461 -3.645 6.461 -3.233 c
+6.461 -0.147 l
+5.696 -0.147 l
+5.696 0.515 l
+6.461 0.515 l
+6.461 1.721 l
+h
+12.462 -2.204 m
+12.462 -2.991 12.318 -3.579 12.035 -3.968 c
+11.749 -4.351 11.348 -4.542 10.83 -4.542 c
+10.33 -4.542 9.948 -4.357 9.683 -3.983 c
+9.683 -6.364 l
+8.875 -6.364 l
+8.875 0.515 l
+9.61 0.515 l
+9.64 -0.029 l
+9.912 0.389 10.305 0.603 10.816 0.603 c
+11.363 0.603 11.771 0.412 12.035 0.03 c
+12.307 -0.345 12.451 -0.907 12.462 -1.66 c
+h
+11.653 -1.749 m
+11.653 -1.19 11.565 -0.779 11.389 -0.514 c
+11.219 -0.249 10.947 -0.118 10.565 -0.118 c
+10.172 -0.118 9.878 -0.309 9.683 -0.69 c
+9.683 -3.277 l
+9.878 -3.659 10.176 -3.85 10.581 -3.85 c
+10.94 -3.85 11.205 -3.719 11.374 -3.453 c
+11.55 -3.189 11.642 -2.786 11.653 -2.234 c
+h
+15.747 -3.175 m
+15.747 -3.009 15.676 -2.863 15.541 -2.734 c
+15.412 -2.609 15.159 -2.462 14.776 -2.293 c
+14.343 -2.109 14.034 -1.951 13.851 -1.822 c
+13.675 -1.697 13.542 -1.554 13.454 -1.396 c
+13.365 -1.23 13.322 -1.036 13.322 -0.808 c
+13.322 -0.396 13.469 -0.058 13.762 0.206 c
+14.057 0.47 14.431 0.603 14.894 0.603 c
+15.383 0.603 15.776 0.46 16.07 0.177 c
+16.364 -0.099 16.511 -0.455 16.511 -0.897 c
+15.703 -0.897 l
+15.703 -0.672 15.622 -0.481 15.468 -0.323 c
+15.321 -0.168 15.129 -0.087 14.894 -0.087 c
+14.659 -0.087 14.471 -0.154 14.336 -0.278 c
+14.196 -0.396 14.13 -0.565 14.13 -0.779 c
+14.13 -0.947 14.178 -1.08 14.277 -1.176 c
+14.373 -1.275 14.615 -1.407 14.997 -1.572 c
+15.603 -1.807 16.015 -2.04 16.232 -2.263 c
+16.445 -2.491 16.555 -2.774 16.555 -3.116 c
+16.555 -3.549 16.401 -3.895 16.1 -4.159 c
+15.805 -4.417 15.408 -4.542 14.909 -4.542 c
+14.398 -4.542 13.983 -4.394 13.66 -4.101 c
+13.336 -3.806 13.174 -3.432 13.174 -2.969 c
+13.997 -2.969 l
+14.005 -3.245 14.089 -3.461 14.247 -3.615 c
+14.402 -3.773 14.622 -3.85 14.909 -3.85 c
+15.181 -3.85 15.387 -3.792 15.526 -3.674 c
+15.674 -3.549 15.747 -3.38 15.747 -3.175 c
+17.492 -4.012 m
+17.492 -3.865 17.536 -3.744 17.625 -3.645 c
+17.713 -3.549 17.837 -3.498 18.007 -3.498 c
+18.184 -3.498 18.315 -3.549 18.404 -3.645 c
+18.499 -3.744 18.55 -3.865 18.55 -4.012 c
+18.55 -4.152 18.499 -4.27 18.404 -4.365 c
+18.315 -4.453 18.184 -4.498 18.007 -4.498 c
+17.837 -4.498 17.713 -4.453 17.625 -4.365 c
+17.536 -4.27 17.492 -4.152 17.492 -4.012 c
+17.492 -0.249 m
+17.492 -0.103 17.536 0.019 17.625 0.118 c
+17.713 0.214 17.837 0.265 18.007 0.265 c
+18.184 0.265 18.315 0.214 18.404 0.118 c
+18.499 0.019 18.55 -0.103 18.55 -0.249 c
+18.55 -0.389 18.499 -0.507 18.404 -0.602 c
+18.315 -0.69 18.184 -0.735 18.007 -0.735 c
+17.837 -0.735 17.713 -0.69 17.625 -0.602 c
+17.536 -0.507 17.492 -0.389 17.492 -0.249 c
+19.786 -5.026 m
+19.094 -5.026 l
+21.432 2.234 l
+22.122 2.234 l
+h
+22.148 -5.026 m
+21.457 -5.026 l
+23.794 2.234 l
+24.486 2.234 l
+h
+25.103 -1.749 m
+25.103 -0.977 25.242 -0.393 25.529 0 c
+25.812 0.401 26.223 0.603 26.764 0.603 c
+27.271 0.603 27.661 0.387 27.925 -0.043 c
+27.954 0.515 l
+28.69 0.515 l
+28.69 -4.498 l
+28.69 -5.115 28.532 -5.585 28.219 -5.909 c
+27.903 -6.239 27.47 -6.408 26.911 -6.408 c
+26.664 -6.408 26.385 -6.342 26.073 -6.217 c
+25.768 -6.1 25.544 -5.953 25.397 -5.776 c
+25.72 -5.217 l
+26.062 -5.548 26.433 -5.718 26.837 -5.718 c
+27.514 -5.718 27.859 -5.35 27.881 -4.615 c
+27.881 -3.968 l
+27.616 -4.351 27.241 -4.542 26.764 -4.542 c
+26.242 -4.542 25.841 -4.351 25.558 -3.968 c
+25.272 -3.579 25.122 -3.021 25.103 -2.293 c
+h
+25.926 -2.204 m
+25.926 -2.763 26.003 -3.175 26.161 -3.439 c
+26.327 -3.696 26.595 -3.821 26.969 -3.821 c
+27.37 -3.821 27.675 -3.615 27.881 -3.204 c
+27.881 -0.72 l
+27.675 -0.319 27.374 -0.118 26.984 -0.118 c
+26.61 -0.118 26.341 -0.249 26.176 -0.514 c
+26.007 -0.771 25.926 -1.168 25.926 -1.705 c
+h
+30.593 -4.453 -0.808 4.968 re
+30.651 1.838 m
+30.651 1.698 30.611 1.58 30.534 1.485 c
+30.464 1.397 30.35 1.353 30.196 1.353 c
+30.038 1.353 29.92 1.397 29.843 1.485 c
+29.773 1.58 29.741 1.698 29.741 1.838 c
+29.741 1.974 29.773 2.088 29.843 2.176 c
+29.92 2.271 30.034 2.323 30.181 2.323 c
+30.336 2.323 30.453 2.271 30.534 2.176 c
+30.611 2.088 30.651 1.974 30.651 1.838 c
+32.845 1.721 m
+32.845 0.515 l
+33.595 0.515 l
+33.595 -0.147 l
+32.845 -0.147 l
+32.845 -3.218 l
+32.845 -3.417 32.875 -3.568 32.933 -3.674 c
+33 -3.773 33.114 -3.821 33.272 -3.821 c
+33.378 -3.821 33.485 -3.803 33.595 -3.763 c
+33.581 -4.453 l
+33.404 -4.512 33.217 -4.542 33.022 -4.542 c
+32.698 -4.542 32.453 -4.432 32.287 -4.203 c
+32.118 -3.968 32.037 -3.645 32.037 -3.233 c
+32.037 -0.147 l
+31.273 -0.147 l
+31.273 0.515 l
+32.037 0.515 l
+32.037 1.721 l
+h
+35.95 -1.955 -1.896 0.691 re
+39.104 -3.175 m
+39.104 -3.009 39.034 -2.863 38.898 -2.734 c
+38.769 -2.609 38.516 -2.462 38.134 -2.293 c
+37.7 -2.109 37.392 -1.951 37.207 -1.822 c
+37.031 -1.697 36.899 -1.554 36.81 -1.396 c
+36.723 -1.23 36.679 -1.036 36.679 -0.808 c
+36.679 -0.396 36.825 -0.058 37.119 0.206 c
+37.413 0.47 37.788 0.603 38.251 0.603 c
+38.74 0.603 39.133 0.46 39.427 0.177 c
+39.721 -0.099 39.868 -0.455 39.868 -0.897 c
+39.06 -0.897 l
+39.06 -0.672 38.979 -0.481 38.824 -0.323 c
+38.678 -0.168 38.487 -0.087 38.251 -0.087 c
+38.016 -0.087 37.828 -0.154 37.693 -0.278 c
+37.552 -0.396 37.487 -0.565 37.487 -0.779 c
+37.487 -0.947 37.535 -1.08 37.633 -1.176 c
+37.729 -1.275 37.972 -1.407 38.354 -1.572 c
+38.96 -1.807 39.372 -2.04 39.588 -2.263 c
+39.802 -2.491 39.912 -2.774 39.912 -3.116 c
+39.912 -3.549 39.758 -3.895 39.456 -4.159 c
+39.162 -4.417 38.765 -4.542 38.266 -4.542 c
+37.755 -4.542 37.34 -4.394 37.016 -4.101 c
+36.693 -3.806 36.531 -3.432 36.531 -2.969 c
+37.354 -2.969 l
+37.362 -3.245 37.446 -3.461 37.604 -3.615 c
+37.758 -3.773 37.979 -3.85 38.266 -3.85 c
+38.537 -3.85 38.743 -3.792 38.883 -3.674 c
+39.03 -3.549 39.104 -3.38 39.104 -3.175 c
+42.521 -3.85 m
+42.786 -3.85 42.996 -3.77 43.153 -3.601 c
+43.318 -3.436 43.41 -3.197 43.432 -2.881 c
+44.197 -2.881 l
+44.174 -3.362 44.006 -3.759 43.682 -4.072 c
+43.366 -4.388 42.981 -4.542 42.521 -4.542 c
+41.903 -4.542 41.433 -4.351 41.11 -3.968 c
+40.787 -3.579 40.625 -2.998 40.625 -2.234 c
+40.625 -1.69 l
+40.625 -0.937 40.787 -0.367 41.11 0.015 c
+41.433 0.405 41.897 0.603 42.506 0.603 c
+43.013 0.603 43.418 0.441 43.711 0.118 c
+44.013 -0.198 44.174 -0.631 44.197 -1.19 c
+43.432 -1.19 l
+43.41 -0.83 43.322 -0.554 43.168 -0.367 c
+43.01 -0.183 42.79 -0.087 42.506 -0.087 c
+42.154 -0.087 41.889 -0.213 41.712 -0.455 c
+41.536 -0.69 41.441 -1.08 41.433 -1.616 c
+41.433 -2.248 l
+41.433 -2.836 41.521 -3.256 41.698 -3.498 c
+41.874 -3.733 42.146 -3.85 42.521 -3.85 c
+45.733 0.515 m
+45.762 0.059 l
+46.063 0.42 46.46 0.603 46.953 0.603 c
+47.511 0.603 47.897 0.36 48.114 -0.118 c
+48.427 0.36 48.864 0.603 49.423 0.603 c
+50.341 0.603 50.811 0.034 50.834 -1.102 c
+50.834 -4.453 l
+50.025 -4.453 l
+50.025 -1.176 l
+50.025 -0.823 49.955 -0.558 49.819 -0.382 c
+49.691 -0.205 49.474 -0.118 49.172 -0.118 c
+48.926 -0.118 48.724 -0.213 48.569 -0.396 c
+48.423 -0.584 48.334 -0.823 48.305 -1.117 c
+48.305 -4.453 l
+47.497 -4.453 l
+47.497 -1.146 l
+47.486 -0.463 47.206 -0.118 46.659 -0.118 c
+46.248 -0.118 45.957 -0.323 45.791 -0.735 c
+45.791 -4.453 l
+44.983 -4.453 l
+44.983 0.515 l
+h
+51.818 -4.012 m
+51.818 -3.865 51.862 -3.744 51.951 -3.645 c
+52.039 -3.549 52.164 -3.498 52.332 -3.498 c
+52.509 -3.498 52.641 -3.549 52.729 -3.645 c
+52.825 -3.744 52.876 -3.865 52.876 -4.012 c
+52.876 -4.152 52.825 -4.27 52.729 -4.365 c
+52.641 -4.453 52.509 -4.498 52.332 -4.498 c
+52.164 -4.498 52.039 -4.453 51.951 -4.365 c
+51.862 -4.27 51.818 -4.152 51.818 -4.012 c
+55.875 -3.85 m
+56.14 -3.85 56.349 -3.77 56.507 -3.601 c
+56.673 -3.436 56.764 -3.197 56.787 -2.881 c
+57.551 -2.881 l
+57.529 -3.362 57.36 -3.759 57.036 -4.072 c
+56.72 -4.388 56.334 -4.542 55.875 -4.542 c
+55.258 -4.542 54.788 -4.351 54.464 -3.968 c
+54.141 -3.579 53.979 -2.998 53.979 -2.234 c
+53.979 -1.69 l
+53.979 -0.937 54.141 -0.367 54.464 0.015 c
+54.788 0.405 55.251 0.603 55.86 0.603 c
+56.367 0.603 56.772 0.441 57.066 0.118 c
+57.367 -0.198 57.529 -0.631 57.551 -1.19 c
+56.787 -1.19 l
+56.764 -0.83 56.677 -0.554 56.522 -0.367 c
+56.363 -0.183 56.143 -0.087 55.86 -0.087 c
+55.507 -0.087 55.243 -0.213 55.067 -0.455 c
+54.89 -0.69 54.795 -1.08 54.788 -1.616 c
+54.788 -2.248 l
+54.788 -2.836 54.875 -3.256 55.052 -3.498 c
+55.228 -3.733 55.501 -3.85 55.875 -3.85 c
+58.157 -1.734 m
+58.157 -1.022 58.326 -0.452 58.672 -0.029 c
+59.025 0.389 59.488 0.603 60.068 0.603 c
+60.645 0.603 61.105 0.397 61.45 -0.014 c
+61.803 -0.419 61.983 -0.977 61.994 -1.69 c
+61.994 -2.204 l
+61.994 -2.932 61.817 -3.505 61.464 -3.924 c
+61.119 -4.336 60.66 -4.542 60.083 -4.542 c
+59.502 -4.542 59.039 -4.343 58.686 -3.939 c
+58.341 -3.528 58.165 -2.977 58.157 -2.277 c
+h
+58.966 -2.204 m
+58.966 -2.715 59.062 -3.116 59.26 -3.41 c
+59.465 -3.704 59.737 -3.85 60.083 -3.85 c
+60.795 -3.85 61.163 -3.333 61.185 -2.293 c
+61.185 -1.734 l
+61.185 -1.227 61.082 -0.823 60.876 -0.529 c
+60.678 -0.235 60.41 -0.087 60.068 -0.087 c
+59.734 -0.087 59.465 -0.235 59.26 -0.529 c
+59.062 -0.823 58.966 -1.227 58.966 -1.734 c
+h
+63.617 0.515 m
+63.648 0.059 l
+63.949 0.42 64.346 0.603 64.838 0.603 c
+65.396 0.603 65.782 0.36 66 -0.118 c
+66.312 0.36 66.749 0.603 67.307 0.603 c
+68.226 0.603 68.697 0.034 68.718 -1.102 c
+68.718 -4.453 l
+67.91 -4.453 l
+67.91 -1.176 l
+67.91 -0.823 67.841 -0.558 67.704 -0.382 c
+67.575 -0.205 67.359 -0.118 67.058 -0.118 c
+66.811 -0.118 66.609 -0.213 66.455 -0.396 c
+66.308 -0.584 66.22 -0.823 66.19 -1.117 c
+66.19 -4.453 l
+65.381 -4.453 l
+65.381 -1.146 l
+65.371 -0.463 65.092 -0.118 64.544 -0.118 c
+64.132 -0.118 63.842 -0.323 63.677 -0.735 c
+63.677 -4.453 l
+62.869 -4.453 l
+62.869 0.515 l
+h
+69.88 -5.026 m
+69.189 -5.026 l
+71.526 2.234 l
+72.217 2.234 l
+h
+72.834 -1.749 m
+72.834 -0.977 72.974 -0.393 73.26 0 c
+73.543 0.401 73.955 0.603 74.495 0.603 c
+74.966 0.603 75.333 0.412 75.598 0.03 c
+75.598 2.602 l
+76.421 2.602 l
+76.421 -4.453 l
+75.671 -4.453 l
+75.627 -3.924 l
+75.363 -4.336 74.984 -4.542 74.495 -4.542 c
+73.973 -4.542 73.57 -4.347 73.275 -3.954 c
+72.982 -3.553 72.834 -2.983 72.834 -2.248 c
+h
+73.643 -2.204 m
+73.643 -2.763 73.724 -3.175 73.892 -3.439 c
+74.058 -3.696 74.326 -3.821 74.701 -3.821 c
+75.101 -3.821 75.399 -3.623 75.598 -3.218 c
+75.598 -0.706 l
+75.392 -0.316 75.091 -0.118 74.701 -0.118 c
+74.326 -0.118 74.058 -0.249 73.892 -0.514 c
+73.724 -0.771 73.643 -1.168 73.643 -1.705 c
+h
+77.314 -1.734 m
+77.314 -1.022 77.483 -0.452 77.828 -0.029 c
+78.181 0.389 78.644 0.603 79.224 0.603 c
+79.802 0.603 80.261 0.397 80.606 -0.014 c
+80.959 -0.419 81.139 -0.977 81.15 -1.69 c
+81.15 -2.204 l
+81.15 -2.932 80.974 -3.505 80.621 -3.924 c
+80.275 -4.336 79.816 -4.542 79.239 -4.542 c
+78.659 -4.542 78.195 -4.343 77.843 -3.939 c
+77.497 -3.528 77.321 -2.977 77.314 -2.277 c
+h
+78.122 -2.204 m
+78.122 -2.715 78.218 -3.116 78.416 -3.41 c
+78.622 -3.704 78.894 -3.85 79.239 -3.85 c
+79.953 -3.85 80.319 -3.333 80.342 -2.293 c
+80.342 -1.734 l
+80.342 -1.227 80.239 -0.823 80.033 -0.529 c
+79.835 -0.235 79.567 -0.087 79.224 -0.087 c
+78.89 -0.087 78.622 -0.235 78.416 -0.529 c
+78.218 -0.823 78.122 -1.227 78.122 -1.734 c
+h
+85.715 -3.027 m
+86.478 0.515 l
+87.272 0.515 l
+86.067 -4.453 l
+85.42 -4.453 l
+84.45 -0.897 l
+83.494 -4.453 l
+82.848 -4.453 l
+81.643 0.515 l
+82.436 0.515 l
+83.215 -2.94 l
+84.127 0.515 l
+84.774 0.515 l
+h
+88.647 0.515 m
+88.676 -0.014 l
+88.988 0.397 89.389 0.603 89.881 0.603 c
+90.763 0.603 91.208 0.019 91.219 -1.146 c
+91.219 -4.453 l
+90.411 -4.453 l
+90.411 -1.19 l
+90.411 -0.801 90.345 -0.525 90.22 -0.367 c
+90.091 -0.201 89.896 -0.118 89.632 -0.118 c
+89.426 -0.118 89.242 -0.187 89.088 -0.323 c
+88.93 -0.452 88.801 -0.625 88.705 -0.837 c
+88.705 -4.453 l
+87.882 -4.453 l
+87.882 0.515 l
+h
+93.137 -4.453 -0.808 7.056 re
+94.159 -1.734 m
+94.159 -1.022 94.328 -0.452 94.673 -0.029 c
+95.026 0.389 95.489 0.603 96.069 0.603 c
+96.647 0.603 97.106 0.397 97.451 -0.014 c
+97.804 -0.419 97.985 -0.977 97.995 -1.69 c
+97.995 -2.204 l
+97.995 -2.932 97.819 -3.505 97.466 -3.924 c
+97.121 -4.336 96.661 -4.542 96.084 -4.542 c
+95.504 -4.542 95.041 -4.343 94.688 -3.939 c
+94.343 -3.528 94.166 -2.977 94.159 -2.277 c
+h
+94.968 -2.204 m
+94.968 -2.715 95.063 -3.116 95.261 -3.41 c
+95.467 -3.704 95.739 -3.85 96.084 -3.85 c
+96.797 -3.85 97.165 -3.333 97.187 -2.293 c
+97.187 -1.734 l
+97.187 -1.227 97.084 -0.823 96.878 -0.529 c
+96.68 -0.235 96.412 -0.087 96.069 -0.087 c
+95.735 -0.087 95.467 -0.235 95.261 -0.529 c
+95.063 -0.823 94.968 -1.227 94.968 -1.734 c
+h
+101.413 -4.453 m
+101.362 -4.347 101.328 -4.167 101.31 -3.91 c
+101.023 -4.332 100.656 -4.542 100.208 -4.542 c
+99.755 -4.542 99.402 -4.421 99.149 -4.174 c
+98.903 -3.921 98.781 -3.564 98.781 -3.101 c
+98.781 -2.594 98.951 -2.19 99.296 -1.896 c
+99.637 -1.602 100.108 -1.452 100.707 -1.44 c
+101.295 -1.44 l
+101.295 -0.911 l
+101.295 -0.617 101.225 -0.407 101.089 -0.278 c
+100.961 -0.154 100.766 -0.087 100.501 -0.087 c
+100.256 -0.087 100.053 -0.161 99.899 -0.309 c
+99.752 -0.455 99.678 -0.642 99.678 -0.866 c
+98.855 -0.866 l
+98.855 -0.613 98.929 -0.367 99.076 -0.132 c
+99.23 0.104 99.436 0.283 99.693 0.412 c
+99.947 0.537 100.229 0.603 100.545 0.603 c
+101.052 0.603 101.442 0.474 101.707 0.221 c
+101.971 -0.025 102.104 -0.393 102.104 -0.881 c
+102.104 -3.38 l
+102.111 -3.763 102.166 -4.097 102.265 -4.38 c
+102.265 -4.453 l
+h
+100.34 -3.806 m
+100.535 -3.806 100.722 -3.755 100.898 -3.645 c
+101.082 -3.528 101.214 -3.391 101.295 -3.233 c
+101.295 -2.042 l
+100.84 -2.042 l
+100.458 -2.054 100.152 -2.142 99.928 -2.308 c
+99.701 -2.476 99.59 -2.705 99.59 -2.998 c
+99.59 -3.285 99.641 -3.491 99.752 -3.615 c
+99.87 -3.744 100.065 -3.806 100.34 -3.806 c
+103.015 -1.749 m
+103.015 -0.977 103.155 -0.393 103.441 0 c
+103.724 0.401 104.136 0.603 104.676 0.603 c
+105.146 0.603 105.514 0.412 105.779 0.03 c
+105.779 2.602 l
+106.602 2.602 l
+106.602 -4.453 l
+105.852 -4.453 l
+105.808 -3.924 l
+105.543 -4.336 105.164 -4.542 104.676 -4.542 c
+104.154 -4.542 103.75 -4.347 103.456 -3.954 c
+103.162 -3.553 103.015 -2.983 103.015 -2.248 c
+h
+103.824 -2.204 m
+103.824 -2.763 103.905 -3.175 104.073 -3.439 c
+104.239 -3.696 104.507 -3.821 104.882 -3.821 c
+105.282 -3.821 105.58 -3.623 105.779 -3.218 c
+105.779 -0.706 l
+105.573 -0.316 105.272 -0.118 104.882 -0.118 c
+104.507 -0.118 104.239 -0.249 104.073 -0.514 c
+103.905 -0.771 103.824 -1.168 103.824 -1.705 c
+h
+110.082 -3.175 m
+110.082 -3.009 110.012 -2.863 109.876 -2.734 c
+109.748 -2.609 109.494 -2.462 109.112 -2.293 c
+108.678 -2.109 108.369 -1.951 108.185 -1.822 c
+108.009 -1.697 107.876 -1.554 107.789 -1.396 c
+107.701 -1.23 107.656 -1.036 107.656 -0.808 c
+107.656 -0.396 107.803 -0.058 108.098 0.206 c
+108.391 0.47 108.766 0.603 109.229 0.603 c
+109.718 0.603 110.111 0.46 110.405 0.177 c
+110.699 -0.099 110.846 -0.455 110.846 -0.897 c
+110.037 -0.897 l
+110.037 -0.672 109.956 -0.481 109.802 -0.323 c
+109.655 -0.168 109.464 -0.087 109.229 -0.087 c
+108.994 -0.087 108.807 -0.154 108.67 -0.278 c
+108.531 -0.396 108.464 -0.565 108.464 -0.779 c
+108.464 -0.947 108.512 -1.08 108.612 -1.176 c
+108.707 -1.275 108.95 -1.407 109.332 -1.572 c
+109.939 -1.807 110.35 -2.04 110.567 -2.263 c
+110.78 -2.491 110.89 -2.774 110.89 -3.116 c
+110.89 -3.549 110.735 -3.895 110.434 -4.159 c
+110.141 -4.417 109.744 -4.542 109.243 -4.542 c
+108.733 -4.542 108.318 -4.394 107.994 -4.101 c
+107.671 -3.806 107.51 -3.432 107.51 -2.969 c
+108.333 -2.969 l
+108.339 -3.245 108.424 -3.461 108.582 -3.615 c
+108.736 -3.773 108.957 -3.85 109.243 -3.85 c
+109.515 -3.85 109.721 -3.792 109.861 -3.674 c
+110.008 -3.549 110.082 -3.38 110.082 -3.175 c
+111.824 -4.012 m
+111.824 -3.865 111.867 -3.744 111.956 -3.645 c
+112.044 -3.549 112.169 -3.498 112.337 -3.498 c
+112.514 -3.498 112.647 -3.549 112.734 -3.645 c
+112.83 -3.744 112.882 -3.865 112.882 -4.012 c
+112.882 -4.152 112.83 -4.27 112.734 -4.365 c
+112.647 -4.453 112.514 -4.498 112.337 -4.498 c
+112.169 -4.498 112.044 -4.453 111.956 -4.365 c
+111.867 -4.27 111.824 -4.152 111.824 -4.012 c
+f
+Q
+q 1 0 0 1 539.3456 316.4395 cm
+0 0 m
+-2.249 0 l
+-2.778 -1.749 l
+-3.645 -1.749 l
+-1.484 4.939 l
+-0.765 4.939 l
+1.396 -1.749 l
+0.529 -1.749 l
+h
+-2.028 0.721 m
+-0.206 0.721 l
+-1.132 3.763 l
+h
+2.734 3.219 m
+2.763 2.691 l
+3.075 3.102 3.476 3.308 3.969 3.308 c
+4.85 3.308 5.295 2.723 5.307 1.559 c
+5.307 -1.749 l
+4.498 -1.749 l
+4.498 1.515 l
+4.498 1.904 4.432 2.18 4.307 2.338 c
+4.178 2.503 3.983 2.587 3.719 2.587 c
+3.513 2.587 3.329 2.517 3.175 2.382 c
+3.017 2.253 2.888 2.08 2.793 1.867 c
+2.793 -1.749 l
+1.97 -1.749 l
+1.97 3.219 l
+h
+10.911 -1.837 m
+10.293 -1.837 9.816 -1.657 9.485 -1.294 c
+9.161 -0.922 8.992 -0.378 8.985 0.339 c
+8.985 0.941 l
+8.985 1.676 9.147 2.253 9.469 2.675 c
+9.793 3.094 10.242 3.308 10.822 3.308 c
+11.399 3.308 11.829 3.12 12.116 2.749 c
+12.409 2.386 12.56 1.812 12.571 1.029 c
+12.571 0.5 l
+9.793 0.5 l
+9.793 0.383 l
+9.793 -0.158 9.889 -0.551 10.088 -0.793 c
+10.293 -1.028 10.58 -1.146 10.954 -1.146 c
+11.197 -1.146 11.41 -1.102 11.586 -1.014 c
+11.771 -0.926 11.943 -0.786 12.101 -0.588 c
+12.527 -1.102 l
+12.174 -1.595 11.634 -1.837 10.911 -1.837 c
+10.822 2.617 m
+10.487 2.617 10.238 2.5 10.073 2.264 c
+9.903 2.036 9.812 1.68 9.793 1.191 c
+11.748 1.191 l
+11.748 1.309 l
+11.726 1.779 11.645 2.11 11.499 2.309 c
+11.351 2.514 11.123 2.617 10.822 2.617 c
+14.805 1.411 m
+15.658 3.219 l
+16.598 3.219 l
+15.247 0.765 l
+16.628 -1.749 l
+15.702 -1.749 l
+14.82 0.118 l
+13.938 -1.749 l
+12.997 -1.749 l
+14.379 0.765 l
+13.042 3.219 l
+13.968 3.219 l
+h
+18.98 -1.146 m
+19.245 -1.146 19.455 -1.065 19.613 -0.897 c
+19.777 -0.731 19.869 -0.492 19.891 -0.176 c
+20.656 -0.176 l
+20.634 -0.658 20.465 -1.055 20.141 -1.367 c
+19.825 -1.683 19.439 -1.837 18.98 -1.837 c
+18.362 -1.837 17.892 -1.646 17.569 -1.263 c
+17.246 -0.874 17.084 -0.294 17.084 0.47 c
+17.084 1.015 l
+17.084 1.768 17.246 2.338 17.569 2.72 c
+17.892 3.109 18.356 3.308 18.965 3.308 c
+19.472 3.308 19.877 3.146 20.17 2.822 c
+20.472 2.506 20.634 2.073 20.656 1.515 c
+19.891 1.515 l
+19.869 1.875 19.781 2.151 19.627 2.338 c
+19.469 2.521 19.248 2.617 18.965 2.617 c
+18.613 2.617 18.348 2.492 18.171 2.249 c
+17.995 2.014 17.899 1.625 17.892 1.088 c
+17.892 0.456 l
+17.892 -0.132 17.98 -0.551 18.157 -0.793 c
+18.333 -1.028 18.605 -1.146 18.98 -1.146 c
+23.206 -1.837 m
+22.589 -1.837 22.111 -1.657 21.78 -1.294 c
+21.456 -0.922 21.288 -0.378 21.28 0.339 c
+21.28 0.941 l
+21.28 1.676 21.442 2.253 21.766 2.675 c
+22.089 3.094 22.537 3.308 23.118 3.308 c
+23.694 3.308 24.124 3.12 24.411 2.749 c
+24.706 2.386 24.856 1.812 24.867 1.029 c
+24.867 0.5 l
+22.089 0.5 l
+22.089 0.383 l
+22.089 -0.158 22.185 -0.551 22.383 -0.793 c
+22.589 -1.028 22.875 -1.146 23.25 -1.146 c
+23.493 -1.146 23.706 -1.102 23.883 -1.014 c
+24.066 -0.926 24.239 -0.786 24.397 -0.588 c
+24.823 -1.102 l
+24.471 -1.595 23.93 -1.837 23.206 -1.837 c
+23.118 2.617 m
+22.784 2.617 22.534 2.5 22.368 2.264 c
+22.2 2.036 22.107 1.68 22.089 1.191 c
+24.043 1.191 l
+24.043 1.309 l
+24.022 1.779 23.941 2.11 23.794 2.309 c
+23.647 2.514 23.419 2.617 23.118 2.617 c
+26.543 -1.749 -0.809 7.056 re
+28.608 -1.749 -0.808 7.056 re
+31.567 -1.837 m
+30.948 -1.837 30.471 -1.657 30.14 -1.294 c
+29.817 -0.922 29.648 -0.378 29.641 0.339 c
+29.641 0.941 l
+29.641 1.676 29.803 2.253 30.125 2.675 c
+30.449 3.094 30.898 3.308 31.478 3.308 c
+32.055 3.308 32.485 3.12 32.772 2.749 c
+33.065 2.386 33.216 1.812 33.227 1.029 c
+33.227 0.5 l
+30.449 0.5 l
+30.449 0.383 l
+30.449 -0.158 30.545 -0.551 30.743 -0.793 c
+30.948 -1.028 31.235 -1.146 31.61 -1.146 c
+31.852 -1.146 32.066 -1.102 32.242 -1.014 c
+32.426 -0.926 32.599 -0.786 32.757 -0.588 c
+33.183 -1.102 l
+32.83 -1.595 32.29 -1.837 31.567 -1.837 c
+31.478 2.617 m
+31.143 2.617 30.894 2.5 30.728 2.264 c
+30.559 2.036 30.468 1.68 30.449 1.191 c
+32.404 1.191 l
+32.404 1.309 l
+32.382 1.779 32.301 2.11 32.154 2.309 c
+32.007 2.514 31.779 2.617 31.478 2.617 c
+34.785 3.219 m
+34.815 2.691 l
+35.127 3.102 35.528 3.308 36.02 3.308 c
+36.901 3.308 37.346 2.723 37.358 1.559 c
+37.358 -1.749 l
+36.549 -1.749 l
+36.549 1.515 l
+36.549 1.904 36.483 2.18 36.358 2.338 c
+36.23 2.503 36.035 2.587 35.77 2.587 c
+35.565 2.587 35.38 2.517 35.226 2.382 c
+35.068 2.253 34.94 2.08 34.844 1.867 c
+34.844 -1.749 l
+34.021 -1.749 l
+34.021 3.219 l
+h
+39.471 4.425 m
+39.471 3.219 l
+40.22 3.219 l
+40.22 2.558 l
+39.471 2.558 l
+39.471 -0.514 l
+39.471 -0.712 39.5 -0.864 39.559 -0.97 c
+39.625 -1.069 39.739 -1.117 39.897 -1.117 c
+40.003 -1.117 40.11 -1.099 40.22 -1.058 c
+40.205 -1.749 l
+40.029 -1.807 39.841 -1.837 39.647 -1.837 c
+39.324 -1.837 39.077 -1.727 38.912 -1.499 c
+38.743 -1.263 38.662 -0.941 38.662 -0.529 c
+38.662 2.558 l
+37.898 2.558 l
+37.898 3.219 l
+38.662 3.219 l
+38.662 4.425 l
+h
+48.154 -0.911 m
+48.007 -1.102 l
+47.584 -1.595 46.967 -1.837 46.155 -1.837 c
+45.427 -1.837 44.861 -1.598 44.45 -1.117 c
+44.038 -0.639 43.825 0.037 43.818 0.912 c
+43.818 2.22 l
+43.818 3.161 44.001 3.859 44.377 4.322 c
+44.747 4.792 45.31 5.027 46.067 5.027 c
+46.702 5.027 47.199 4.851 47.552 4.499 c
+47.912 4.146 48.113 3.639 48.154 2.984 c
+47.316 2.984 l
+47.276 3.396 47.158 3.72 46.964 3.955 c
+46.765 4.19 46.467 4.308 46.067 4.308 c
+45.585 4.308 45.233 4.15 45.009 3.837 c
+44.78 3.521 44.663 3.021 44.656 2.338 c
+44.656 0.971 l
+44.656 0.294 44.78 -0.228 45.038 -0.588 c
+45.302 -0.941 45.674 -1.117 46.155 -1.117 c
+46.603 -1.117 46.948 -1.01 47.184 -0.793 c
+47.316 -0.675 l
+47.316 0.867 l
+46.081 0.867 l
+46.081 1.588 l
+48.154 1.588 l
+h
+50.076 -1.749 -0.808 4.968 re
+50.135 4.543 m
+50.135 4.403 50.094 4.285 50.017 4.19 c
+49.948 4.102 49.834 4.057 49.679 4.057 c
+49.521 4.057 49.404 4.102 49.327 4.19 c
+49.256 4.285 49.223 4.403 49.223 4.543 c
+49.223 4.678 49.256 4.792 49.327 4.881 c
+49.404 4.976 49.518 5.027 49.664 5.027 c
+49.819 5.027 49.936 4.976 50.017 4.881 c
+50.094 4.792 50.135 4.678 50.135 4.543 c
+52.329 4.425 m
+52.329 3.219 l
+53.078 3.219 l
+53.078 2.558 l
+52.329 2.558 l
+52.329 -0.514 l
+52.329 -0.712 52.358 -0.864 52.417 -0.97 c
+52.483 -1.069 52.597 -1.117 52.755 -1.117 c
+52.861 -1.117 52.968 -1.099 53.078 -1.058 c
+53.063 -1.749 l
+52.887 -1.807 52.699 -1.837 52.505 -1.837 c
+52.182 -1.837 51.935 -1.727 51.77 -1.499 c
+51.6 -1.263 51.521 -0.941 51.521 -0.529 c
+51.521 2.558 l
+50.756 2.558 l
+50.756 3.219 l
+51.521 3.219 l
+51.521 4.425 l
+h
+58.443 -1.146 m
+58.708 -1.146 58.918 -1.065 59.076 -0.897 c
+59.241 -0.731 59.332 -0.492 59.355 -0.176 c
+60.119 -0.176 l
+60.097 -0.658 59.928 -1.055 59.604 -1.367 c
+59.288 -1.683 58.903 -1.837 58.443 -1.837 c
+57.826 -1.837 57.356 -1.646 57.032 -1.263 c
+56.709 -0.874 56.547 -0.294 56.547 0.47 c
+56.547 1.015 l
+56.547 1.768 56.709 2.338 57.032 2.72 c
+57.356 3.109 57.819 3.308 58.428 3.308 c
+58.935 3.308 59.34 3.146 59.634 2.822 c
+59.935 2.506 60.097 2.073 60.119 1.515 c
+59.355 1.515 l
+59.332 1.875 59.244 2.151 59.09 2.338 c
+58.932 2.521 58.712 2.617 58.428 2.617 c
+58.076 2.617 57.811 2.492 57.635 2.249 c
+57.458 2.014 57.362 1.625 57.356 1.088 c
+57.356 0.456 l
+57.356 -0.132 57.443 -0.551 57.62 -0.793 c
+57.796 -1.028 58.068 -1.146 58.443 -1.146 c
+60.729 0.971 m
+60.729 1.683 60.898 2.253 61.243 2.675 c
+61.596 3.094 62.06 3.308 62.64 3.308 c
+63.217 3.308 63.676 3.102 64.022 2.691 c
+64.375 2.286 64.555 1.727 64.566 1.015 c
+64.566 0.5 l
+64.566 -0.228 64.389 -0.801 64.036 -1.219 c
+63.691 -1.631 63.232 -1.837 62.654 -1.837 c
+62.074 -1.837 61.611 -1.639 61.258 -1.234 c
+60.913 -0.823 60.736 -0.272 60.729 0.427 c
+h
+61.538 0.5 m
+61.538 -0.01 61.633 -0.411 61.831 -0.706 c
+62.037 -0.999 62.309 -1.146 62.654 -1.146 c
+63.367 -1.146 63.735 -0.628 63.757 0.412 c
+63.757 0.971 l
+63.757 1.478 63.654 1.881 63.448 2.176 c
+63.25 2.469 62.982 2.617 62.64 2.617 c
+62.305 2.617 62.037 2.469 61.831 2.176 c
+61.633 1.881 61.538 1.478 61.538 0.971 c
+h
+67.968 -1.308 m
+67.693 -1.66 67.296 -1.837 66.777 -1.837 c
+66.337 -1.837 65.998 -1.687 65.763 -1.381 c
+65.536 -1.069 65.418 -0.613 65.411 -0.014 c
+65.411 3.219 l
+66.22 3.219 l
+66.22 0.044 l
+66.22 -0.731 66.455 -1.117 66.925 -1.117 c
+67.413 -1.117 67.751 -0.897 67.939 -0.455 c
+67.939 3.219 l
+68.762 3.219 l
+68.762 -1.749 l
+67.984 -1.749 l
+h
+71.857 2.455 m
+71.739 2.473 71.614 2.484 71.489 2.484 c
+71.066 2.484 70.776 2.257 70.621 1.808 c
+70.621 -1.749 l
+69.798 -1.749 l
+69.798 3.219 l
+70.592 3.219 l
+70.607 2.72 l
+70.82 3.109 71.128 3.308 71.533 3.308 c
+71.658 3.308 71.768 3.286 71.857 3.249 c
+h
+74.976 -0.47 m
+74.976 -0.305 74.906 -0.158 74.77 -0.029 c
+74.642 0.096 74.388 0.243 74.006 0.412 c
+73.572 0.595 73.264 0.754 73.08 0.882 c
+72.904 1.008 72.771 1.151 72.683 1.309 c
+72.595 1.474 72.551 1.669 72.551 1.897 c
+72.551 2.309 72.698 2.646 72.992 2.911 c
+73.285 3.175 73.661 3.308 74.124 3.308 c
+74.612 3.308 75.005 3.165 75.3 2.882 c
+75.593 2.606 75.741 2.249 75.741 1.808 c
+74.932 1.808 l
+74.932 2.033 74.851 2.224 74.697 2.382 c
+74.55 2.536 74.359 2.617 74.124 2.617 c
+73.888 2.617 73.701 2.55 73.565 2.426 c
+73.426 2.309 73.359 2.139 73.359 1.926 c
+73.359 1.757 73.407 1.625 73.507 1.529 c
+73.602 1.43 73.844 1.297 74.226 1.133 c
+74.833 0.897 75.244 0.665 75.461 0.441 c
+75.674 0.214 75.784 -0.07 75.784 -0.411 c
+75.784 -0.845 75.63 -1.19 75.329 -1.454 c
+75.035 -1.712 74.638 -1.837 74.138 -1.837 c
+73.628 -1.837 73.212 -1.69 72.888 -1.396 c
+72.566 -1.102 72.404 -0.727 72.404 -0.264 c
+73.227 -0.264 l
+73.235 -0.54 73.318 -0.756 73.476 -0.911 c
+73.631 -1.069 73.852 -1.146 74.138 -1.146 c
+74.411 -1.146 74.616 -1.087 74.756 -0.97 c
+74.903 -0.845 74.976 -0.675 74.976 -0.47 c
+78.438 -1.837 m
+77.821 -1.837 77.343 -1.657 77.012 -1.294 c
+76.688 -0.922 76.52 -0.378 76.512 0.339 c
+76.512 0.941 l
+76.512 1.676 76.674 2.253 76.998 2.675 c
+77.32 3.094 77.769 3.308 78.349 3.308 c
+78.926 3.308 79.356 3.12 79.643 2.749 c
+79.937 2.386 80.088 1.812 80.098 1.029 c
+80.098 0.5 l
+77.32 0.5 l
+77.32 0.383 l
+77.32 -0.158 77.416 -0.551 77.615 -0.793 c
+77.821 -1.028 78.107 -1.146 78.482 -1.146 c
+78.725 -1.146 78.937 -1.102 79.114 -1.014 c
+79.298 -0.926 79.47 -0.786 79.628 -0.588 c
+80.055 -1.102 l
+79.702 -1.595 79.161 -1.837 78.438 -1.837 c
+78.349 2.617 m
+78.016 2.617 77.765 2.5 77.6 2.264 c
+77.43 2.036 77.339 1.68 77.32 1.191 c
+79.275 1.191 l
+79.275 1.309 l
+79.254 1.779 79.173 2.11 79.026 2.309 c
+78.879 2.514 78.651 2.617 78.349 2.617 c
+85.416 -1.146 m
+85.681 -1.146 85.89 -1.065 86.049 -0.897 c
+86.213 -0.731 86.305 -0.492 86.328 -0.176 c
+87.092 -0.176 l
+87.07 -0.658 86.901 -1.055 86.577 -1.367 c
+86.261 -1.683 85.875 -1.837 85.416 -1.837 c
+84.799 -1.837 84.329 -1.646 84.005 -1.263 c
+83.682 -0.874 83.52 -0.294 83.52 0.47 c
+83.52 1.015 l
+83.52 1.768 83.682 2.338 84.005 2.72 c
+84.329 3.109 84.792 3.308 85.401 3.308 c
+85.908 3.308 86.313 3.146 86.606 2.822 c
+86.908 2.506 87.07 2.073 87.092 1.515 c
+86.328 1.515 l
+86.305 1.875 86.217 2.151 86.063 2.338 c
+85.905 2.521 85.684 2.617 85.401 2.617 c
+85.048 2.617 84.784 2.492 84.607 2.249 c
+84.431 2.014 84.335 1.625 84.329 1.088 c
+84.329 0.456 l
+84.329 -0.132 84.416 -0.551 84.593 -0.793 c
+84.769 -1.028 85.041 -1.146 85.416 -1.146 c
+90.421 -1.749 m
+90.369 -1.643 90.336 -1.462 90.319 -1.205 c
+90.032 -1.627 89.664 -1.837 89.216 -1.837 c
+88.763 -1.837 88.411 -1.716 88.158 -1.469 c
+87.911 -1.216 87.79 -0.86 87.79 -0.396 c
+87.79 0.111 87.959 0.515 88.304 0.809 c
+88.646 1.103 89.116 1.253 89.715 1.264 c
+90.303 1.264 l
+90.303 1.794 l
+90.303 2.088 90.234 2.297 90.097 2.426 c
+89.969 2.55 89.775 2.617 89.509 2.617 c
+89.264 2.617 89.062 2.544 88.907 2.396 c
+88.76 2.249 88.686 2.062 88.686 1.838 c
+87.863 1.838 l
+87.863 2.091 87.937 2.338 88.084 2.573 c
+88.239 2.808 88.445 2.988 88.701 3.117 c
+88.954 3.242 89.238 3.308 89.554 3.308 c
+90.061 3.308 90.45 3.179 90.716 2.926 c
+90.98 2.679 91.112 2.311 91.112 1.823 c
+91.112 -0.675 l
+91.119 -1.058 91.175 -1.392 91.273 -1.675 c
+91.273 -1.749 l
+h
+89.348 -1.102 m
+89.543 -1.102 89.731 -1.051 89.906 -0.941 c
+90.091 -0.823 90.223 -0.687 90.303 -0.529 c
+90.303 0.662 l
+89.848 0.662 l
+89.465 0.651 89.16 0.563 88.937 0.397 c
+88.709 0.229 88.599 0 88.599 -0.294 c
+88.599 -0.58 88.65 -0.786 88.76 -0.911 c
+88.877 -1.04 89.073 -1.102 89.348 -1.102 c
+92.95 3.219 m
+92.979 2.691 l
+93.291 3.102 93.692 3.308 94.184 3.308 c
+95.066 3.308 95.51 2.723 95.522 1.559 c
+95.522 -1.749 l
+94.714 -1.749 l
+94.714 1.515 l
+94.714 1.904 94.647 2.18 94.522 2.338 c
+94.394 2.503 94.199 2.587 93.934 2.587 c
+93.729 2.587 93.544 2.517 93.39 2.382 c
+93.232 2.253 93.104 2.08 93.008 1.867 c
+93.008 -1.749 l
+92.185 -1.749 l
+92.185 3.219 l
+h
+102.949 0.5 m
+102.949 -0.276 102.805 -0.86 102.522 -1.249 c
+102.246 -1.643 101.846 -1.837 101.317 -1.837 c
+100.795 -1.837 100.405 -1.612 100.141 -1.161 c
+100.097 -1.749 l
+99.362 -1.749 l
+99.362 5.307 l
+100.17 5.307 l
+100.17 2.675 l
+100.435 3.094 100.817 3.308 101.317 3.308 c
+101.853 3.308 102.261 3.117 102.537 2.735 c
+102.809 2.352 102.949 1.768 102.949 0.985 c
+h
+102.14 0.956 m
+102.14 1.544 102.055 1.959 101.89 2.205 c
+101.733 2.459 101.467 2.587 101.097 2.587 c
+100.685 2.587 100.376 2.359 100.17 1.912 c
+100.17 -0.455 l
+100.365 -0.897 100.677 -1.117 101.111 -1.117 c
+101.471 -1.117 101.733 -0.992 101.89 -0.735 c
+102.055 -0.481 102.14 -0.084 102.14 0.456 c
+h
+105.59 -1.837 m
+104.973 -1.837 104.495 -1.657 104.164 -1.294 c
+103.842 -0.922 103.672 -0.378 103.665 0.339 c
+103.665 0.941 l
+103.665 1.676 103.827 2.253 104.15 2.675 c
+104.474 3.094 104.922 3.308 105.502 3.308 c
+106.08 3.308 106.51 3.12 106.796 2.749 c
+107.09 2.386 107.241 1.812 107.252 1.029 c
+107.252 0.5 l
+104.474 0.5 l
+104.474 0.383 l
+104.474 -0.158 104.569 -0.551 104.767 -0.793 c
+104.973 -1.028 105.26 -1.146 105.635 -1.146 c
+105.877 -1.146 106.09 -1.102 106.267 -1.014 c
+106.45 -0.926 106.623 -0.786 106.781 -0.588 c
+107.208 -1.102 l
+106.855 -1.595 106.315 -1.837 105.59 -1.837 c
+105.502 2.617 m
+105.168 2.617 104.918 2.5 104.752 2.264 c
+104.584 2.036 104.492 1.68 104.474 1.191 c
+106.429 1.191 l
+106.429 1.309 l
+106.406 1.779 106.325 2.11 106.178 2.309 c
+106.032 2.514 105.804 2.617 105.502 2.617 c
+111.202 -1.749 m
+111.202 2.558 l
+110.555 2.558 l
+110.555 3.219 l
+111.202 3.219 l
+111.202 3.793 l
+111.209 4.3 111.337 4.697 111.584 4.983 c
+111.827 5.266 112.176 5.409 112.628 5.409 c
+112.782 5.409 112.943 5.38 113.113 5.322 c
+113.068 4.63 l
+112.958 4.66 112.837 4.675 112.702 4.675 c
+112.238 4.675 112.01 4.344 112.01 3.69 c
+112.01 3.219 l
+112.863 3.219 l
+112.863 2.558 l
+112.01 2.558 l
+112.01 -1.749 l
+h
+113.532 0.971 m
+113.532 1.683 113.701 2.253 114.046 2.675 c
+114.399 3.094 114.862 3.308 115.443 3.308 c
+116.019 3.308 116.479 3.102 116.825 2.691 c
+117.177 2.286 117.357 1.727 117.369 1.015 c
+117.369 0.5 l
+117.369 -0.228 117.192 -0.801 116.839 -1.219 c
+116.494 -1.631 116.035 -1.837 115.457 -1.837 c
+114.877 -1.837 114.414 -1.639 114.061 -1.234 c
+113.716 -0.823 113.539 -0.272 113.532 0.427 c
+h
+114.34 0.5 m
+114.34 -0.01 114.435 -0.411 114.634 -0.706 c
+114.84 -0.999 115.112 -1.146 115.457 -1.146 c
+116.17 -1.146 116.538 -0.628 116.56 0.412 c
+116.56 0.971 l
+116.56 1.478 116.457 1.881 116.251 2.176 c
+116.052 2.469 115.784 2.617 115.443 2.617 c
+115.108 2.617 114.84 2.469 114.634 2.176 c
+114.435 1.881 114.34 1.478 114.34 0.971 c
+h
+120.767 -1.308 m
+120.492 -1.66 120.095 -1.837 119.576 -1.837 c
+119.136 -1.837 118.797 -1.687 118.562 -1.381 c
+118.335 -1.069 118.217 -0.613 118.21 -0.014 c
+118.21 3.219 l
+119.019 3.219 l
+119.019 0.044 l
+119.019 -0.731 119.254 -1.117 119.724 -1.117 c
+120.212 -1.117 120.55 -0.897 120.738 -0.455 c
+120.738 3.219 l
+121.561 3.219 l
+121.561 -1.749 l
+120.782 -1.749 l
+h
+123.366 3.219 m
+123.395 2.691 l
+123.707 3.102 124.108 3.308 124.6 3.308 c
+125.482 3.308 125.926 2.723 125.938 1.559 c
+125.938 -1.749 l
+125.13 -1.749 l
+125.13 1.515 l
+125.13 1.904 125.063 2.18 124.938 2.338 c
+124.81 2.503 124.615 2.587 124.351 2.587 c
+124.145 2.587 123.96 2.517 123.806 2.382 c
+123.648 2.253 123.52 2.08 123.424 1.867 c
+123.424 -1.749 l
+122.601 -1.749 l
+122.601 3.219 l
+h
+126.813 0.956 m
+126.813 1.727 126.952 2.311 127.239 2.705 c
+127.522 3.105 127.933 3.308 128.473 3.308 c
+128.943 3.308 129.311 3.117 129.576 2.735 c
+129.576 5.307 l
+130.399 5.307 l
+130.399 -1.749 l
+129.649 -1.749 l
+129.605 -1.219 l
+129.34 -1.631 128.962 -1.837 128.473 -1.837 c
+127.952 -1.837 127.547 -1.643 127.253 -1.249 c
+126.959 -0.849 126.813 -0.278 126.813 0.456 c
+h
+127.621 0.5 m
+127.621 -0.058 127.702 -0.47 127.871 -0.735 c
+128.036 -0.992 128.305 -1.117 128.679 -1.117 c
+129.08 -1.117 129.377 -0.918 129.576 -0.514 c
+129.576 1.999 l
+129.37 2.389 129.068 2.587 128.679 2.587 c
+128.305 2.587 128.036 2.455 127.871 2.191 c
+127.702 1.933 127.621 1.536 127.621 1 c
+h
+135.125 -1.749 -0.809 4.968 re
+135.183 4.543 m
+135.183 4.403 135.143 4.285 135.066 4.19 c
+134.996 4.102 134.882 4.057 134.728 4.057 c
+134.57 4.057 134.452 4.102 134.375 4.19 c
+134.306 4.285 134.272 4.403 134.272 4.543 c
+134.272 4.678 134.306 4.792 134.375 4.881 c
+134.452 4.976 134.566 5.027 134.713 5.027 c
+134.867 5.027 134.985 4.976 135.066 4.881 c
+135.143 4.792 135.183 4.678 135.183 4.543 c
+137.072 3.219 m
+137.102 2.691 l
+137.414 3.102 137.815 3.308 138.307 3.308 c
+139.189 3.308 139.634 2.723 139.644 1.559 c
+139.644 -1.749 l
+138.836 -1.749 l
+138.836 1.515 l
+138.836 1.904 138.77 2.18 138.645 2.338 c
+138.516 2.503 138.322 2.587 138.057 2.587 c
+137.851 2.587 137.668 2.517 137.513 2.382 c
+137.355 2.253 137.227 2.08 137.131 1.867 c
+137.131 -1.749 l
+136.307 -1.749 l
+136.307 3.219 l
+h
+144.547 4.425 m
+144.547 3.219 l
+145.296 3.219 l
+145.296 2.558 l
+144.547 2.558 l
+144.547 -0.514 l
+144.547 -0.712 144.577 -0.864 144.635 -0.97 c
+144.701 -1.069 144.815 -1.117 144.973 -1.117 c
+145.08 -1.117 145.186 -1.099 145.296 -1.058 c
+145.282 -1.749 l
+145.105 -1.807 144.918 -1.837 144.723 -1.837 c
+144.4 -1.837 144.153 -1.727 143.988 -1.499 c
+143.819 -1.263 143.738 -0.941 143.738 -0.529 c
+143.738 2.558 l
+142.974 2.558 l
+142.974 3.219 l
+143.738 3.219 l
+143.738 4.425 l
+h
+146.958 2.705 m
+147.259 3.105 147.652 3.308 148.134 3.308 c
+149.015 3.308 149.46 2.723 149.471 1.559 c
+149.471 -1.749 l
+148.662 -1.749 l
+148.662 1.515 l
+148.662 1.904 148.596 2.18 148.471 2.338 c
+148.342 2.503 148.148 2.587 147.883 2.587 c
+147.677 2.587 147.494 2.517 147.34 2.382 c
+147.181 2.253 147.053 2.08 146.958 1.867 c
+146.958 -1.749 l
+146.134 -1.749 l
+146.134 5.307 l
+146.958 5.307 l
+h
+152.271 -1.837 m
+151.654 -1.837 151.176 -1.657 150.846 -1.294 c
+150.522 -0.922 150.353 -0.378 150.345 0.339 c
+150.345 0.941 l
+150.345 1.676 150.507 2.253 150.831 2.675 c
+151.154 3.094 151.602 3.308 152.182 3.308 c
+152.76 3.308 153.19 3.12 153.476 2.749 c
+153.77 2.386 153.921 1.812 153.932 1.029 c
+153.932 0.5 l
+151.154 0.5 l
+151.154 0.383 l
+151.154 -0.158 151.249 -0.551 151.448 -0.793 c
+151.654 -1.028 151.941 -1.146 152.315 -1.146 c
+152.558 -1.146 152.77 -1.102 152.947 -1.014 c
+153.131 -0.926 153.304 -0.786 153.462 -0.588 c
+153.888 -1.102 l
+153.535 -1.595 152.995 -1.837 152.271 -1.837 c
+152.182 2.617 m
+151.849 2.617 151.598 2.5 151.434 2.264 c
+151.264 2.036 151.172 1.68 151.154 1.191 c
+153.109 1.191 l
+153.109 1.309 l
+153.087 1.779 153.006 2.11 152.859 2.309 c
+152.712 2.514 152.484 2.617 152.182 2.617 c
+157.354 0.956 m
+157.354 1.727 157.493 2.311 157.78 2.705 c
+158.062 3.105 158.474 3.308 159.014 3.308 c
+159.521 3.308 159.911 3.091 160.176 2.661 c
+160.205 3.219 l
+160.94 3.219 l
+160.94 -1.793 l
+160.94 -2.41 160.782 -2.881 160.469 -3.204 c
+160.153 -3.534 159.72 -3.704 159.161 -3.704 c
+158.915 -3.704 158.636 -3.638 158.324 -3.513 c
+158.019 -3.395 157.794 -3.248 157.647 -3.072 c
+157.971 -2.513 l
+158.312 -2.844 158.684 -3.013 159.087 -3.013 c
+159.764 -3.013 160.109 -2.645 160.132 -1.911 c
+160.132 -1.263 l
+159.866 -1.646 159.492 -1.837 159.014 -1.837 c
+158.492 -1.837 158.092 -1.646 157.809 -1.263 c
+157.522 -0.874 157.372 -0.316 157.354 0.412 c
+h
+158.177 0.5 m
+158.177 -0.058 158.254 -0.47 158.412 -0.735 c
+158.577 -0.992 158.845 -1.117 159.22 -1.117 c
+159.621 -1.117 159.926 -0.911 160.132 -0.5 c
+160.132 1.985 l
+159.926 2.386 159.625 2.587 159.235 2.587 c
+158.86 2.587 158.592 2.455 158.426 2.191 c
+158.257 1.933 158.177 1.536 158.177 1 c
+h
+164.019 2.455 m
+163.901 2.473 163.777 2.484 163.652 2.484 c
+163.23 2.484 162.939 2.257 162.785 1.808 c
+162.785 -1.749 l
+161.961 -1.749 l
+161.961 3.219 l
+162.755 3.219 l
+162.77 2.72 l
+162.983 3.109 163.292 3.308 163.696 3.308 c
+163.821 3.308 163.931 3.286 164.019 3.249 c
+h
+166.401 -1.837 m
+165.783 -1.837 165.306 -1.657 164.975 -1.294 c
+164.651 -0.922 164.483 -0.378 164.475 0.339 c
+164.475 0.941 l
+164.475 1.676 164.637 2.253 164.96 2.675 c
+165.283 3.094 165.732 3.308 166.312 3.308 c
+166.889 3.308 167.319 3.12 167.606 2.749 c
+167.899 2.386 168.051 1.812 168.061 1.029 c
+168.061 0.5 l
+165.283 0.5 l
+165.283 0.383 l
+165.283 -0.158 165.379 -0.551 165.578 -0.793 c
+165.783 -1.028 166.07 -1.146 166.445 -1.146 c
+166.687 -1.146 166.9 -1.102 167.076 -1.014 c
+167.261 -0.926 167.433 -0.786 167.591 -0.588 c
+168.017 -1.102 l
+167.664 -1.595 167.124 -1.837 166.401 -1.837 c
+166.312 2.617 m
+165.978 2.617 165.728 2.5 165.563 2.264 c
+165.393 2.036 165.302 1.68 165.283 1.191 c
+167.238 1.191 l
+167.238 1.309 l
+167.216 1.779 167.136 2.11 166.989 2.309 c
+166.841 2.514 166.613 2.617 166.312 2.617 c
+171.413 -1.749 m
+171.361 -1.643 171.328 -1.462 171.31 -1.205 c
+171.024 -1.627 170.656 -1.837 170.208 -1.837 c
+169.755 -1.837 169.403 -1.716 169.15 -1.469 c
+168.903 -1.216 168.782 -0.86 168.782 -0.396 c
+168.782 0.111 168.951 0.515 169.296 0.809 c
+169.638 1.103 170.108 1.253 170.708 1.264 c
+171.295 1.264 l
+171.295 1.794 l
+171.295 2.088 171.226 2.297 171.089 2.426 c
+170.961 2.55 170.766 2.617 170.501 2.617 c
+170.255 2.617 170.054 2.544 169.898 2.396 c
+169.752 2.249 169.678 2.062 169.678 1.838 c
+168.855 1.838 l
+168.855 2.091 168.929 2.338 169.075 2.573 c
+169.231 2.808 169.436 2.988 169.693 3.117 c
+169.946 3.242 170.23 3.308 170.546 3.308 c
+171.053 3.308 171.442 3.179 171.707 2.926 c
+171.972 2.679 172.104 2.311 172.104 1.823 c
+172.104 -0.675 l
+172.111 -1.058 172.167 -1.392 172.265 -1.675 c
+172.265 -1.749 l
+h
+170.34 -1.102 m
+170.534 -1.102 170.722 -1.051 170.898 -0.941 c
+171.082 -0.823 171.215 -0.687 171.295 -0.529 c
+171.295 0.662 l
+170.839 0.662 l
+170.457 0.651 170.152 0.563 169.929 0.397 c
+169.701 0.229 169.59 0 169.59 -0.294 c
+169.59 -0.58 169.642 -0.786 169.752 -0.911 c
+169.869 -1.04 170.064 -1.102 170.34 -1.102 c
+174.249 4.425 m
+174.249 3.219 l
+174.999 3.219 l
+174.999 2.558 l
+174.249 2.558 l
+174.249 -0.514 l
+174.249 -0.712 174.28 -0.864 174.338 -0.97 c
+174.405 -1.069 174.518 -1.117 174.677 -1.117 c
+174.783 -1.117 174.889 -1.099 174.999 -1.058 c
+174.985 -1.749 l
+174.808 -1.807 174.621 -1.837 174.426 -1.837 c
+174.103 -1.837 173.856 -1.727 173.692 -1.499 c
+173.522 -1.263 173.441 -0.941 173.441 -0.529 c
+173.441 2.558 l
+172.677 2.558 l
+172.677 3.219 l
+173.441 3.219 l
+173.441 4.425 l
+h
+f
+Q
+q 1 0 0 1 719.2545 317.0425 cm
+0 0 m
+0 -2.352 l
+-1.338 -2.352 l
+-1.338 4.336 l
+0.941 4.336 l
+1.595 4.336 2.12 4.131 2.514 3.719 c
+2.903 3.308 3.102 2.77 3.102 2.117 c
+3.102 1.47 2.903 0.956 2.514 0.573 c
+2.132 0.191 1.595 0 0.912 0 c
+h
+0 1.132 m
+0.941 1.132 l
+1.195 1.132 1.39 1.213 1.529 1.382 c
+1.675 1.548 1.749 1.793 1.749 2.117 c
+1.749 2.448 1.675 2.712 1.529 2.911 c
+1.382 3.105 1.191 3.204 0.956 3.204 c
+0 3.204 l
+h
+6.177 1.367 m
+5.751 1.396 l
+5.388 1.396 5.149 1.238 5.031 0.926 c
+5.031 -2.352 l
+3.723 -2.352 l
+3.723 2.616 l
+4.943 2.616 l
+4.987 2.087 l
+5.193 2.499 5.475 2.705 5.839 2.705 c
+5.986 2.705 6.104 2.683 6.192 2.646 c
+h
+6.416 0.294 m
+6.416 1.047 6.593 1.635 6.945 2.058 c
+7.298 2.488 7.786 2.705 8.415 2.705 c
+9.051 2.705 9.548 2.488 9.9 2.058 c
+10.26 1.635 10.444 1.043 10.444 0.279 c
+10.444 -0.029 l
+10.444 -0.786 10.267 -1.378 9.914 -1.808 c
+9.562 -2.23 9.066 -2.44 8.43 -2.44 c
+7.79 -2.44 7.298 -2.23 6.945 -1.808 c
+6.593 -1.378 6.416 -0.786 6.416 -0.029 c
+h
+7.724 -0.029 m
+7.724 -0.922 7.96 -1.367 8.43 -1.367 c
+8.871 -1.367 9.106 -0.996 9.135 -0.25 c
+9.151 0.294 l
+9.151 0.742 9.084 1.077 8.96 1.294 c
+8.831 1.517 8.65 1.631 8.415 1.631 c
+8.199 1.631 8.025 1.517 7.901 1.294 c
+7.784 1.077 7.724 0.742 7.724 0.294 c
+h
+18.485 -1.587 m
+18.219 -1.874 17.897 -2.088 17.514 -2.234 c
+17.139 -2.371 16.727 -2.44 16.28 -2.44 c
+15.515 -2.44 14.916 -2.205 14.486 -1.735 c
+14.063 -1.257 13.847 -0.559 13.839 0.353 c
+13.839 1.558 l
+13.839 2.477 14.038 3.183 14.442 3.674 c
+14.842 4.175 15.43 4.424 16.206 4.424 c
+16.93 4.424 17.473 4.241 17.837 3.881 c
+18.209 3.528 18.425 2.969 18.485 2.205 c
+17.176 2.205 l
+17.136 2.624 17.043 2.914 16.897 3.072 c
+16.757 3.227 16.536 3.308 16.235 3.308 c
+15.871 3.308 15.607 3.175 15.441 2.911 c
+15.283 2.646 15.199 2.219 15.192 1.631 c
+15.192 0.426 l
+15.192 -0.183 15.279 -0.628 15.456 -0.912 c
+15.64 -1.187 15.945 -1.323 16.368 -1.323 c
+16.632 -1.323 16.845 -1.272 17.014 -1.161 c
+17.132 -1.073 l
+17.132 0.147 l
+16.176 0.147 l
+16.176 1.161 l
+18.485 1.161 l
+h
+20.527 -2.352 -1.308 4.968 re
+19.16 3.91 m
+19.16 4.104 19.223 4.266 19.351 4.395 c
+19.476 4.531 19.649 4.601 19.866 4.601 c
+20.079 4.601 20.251 4.531 20.38 4.395 c
+20.505 4.266 20.571 4.104 20.571 3.91 c
+20.571 3.705 20.505 3.532 20.38 3.395 c
+20.263 3.267 20.09 3.204 19.866 3.204 c
+19.649 3.204 19.476 3.267 19.351 3.395 c
+19.223 3.532 19.16 3.705 19.16 3.91 c
+22.949 3.836 m
+22.949 2.616 l
+23.611 2.616 l
+23.611 1.646 l
+22.949 1.646 l
+22.949 -0.823 l
+22.949 -1.022 22.971 -1.157 23.023 -1.234 c
+23.081 -1.305 23.188 -1.338 23.345 -1.338 c
+23.464 -1.338 23.566 -1.33 23.655 -1.309 c
+23.64 -2.323 l
+23.412 -2.4 23.173 -2.44 22.919 -2.44 c
+22.086 -2.44 21.662 -1.962 21.656 -0.999 c
+21.656 1.646 l
+21.082 1.646 l
+21.082 2.616 l
+21.656 2.616 l
+21.656 3.836 l
+h
+f
+Q
+q 1 0 0 1 749.9827 316.94 cm
+0 0 m
+0 -0.776 -0.143 -1.36 -0.426 -1.75 c
+-0.702 -2.143 -1.103 -2.338 -1.631 -2.338 c
+-2.153 -2.338 -2.543 -2.113 -2.807 -1.661 c
+-2.851 -2.249 l
+-3.586 -2.249 l
+-3.586 4.806 l
+-2.778 4.806 l
+-2.778 2.175 l
+-2.514 2.594 -2.131 2.807 -1.631 2.807 c
+-1.095 2.807 -0.687 2.616 -0.411 2.234 c
+-0.139 1.851 0 1.267 0 0.484 c
+h
+-0.808 0.455 m
+-0.808 1.043 -0.893 1.458 -1.058 1.705 c
+-1.216 1.959 -1.481 2.087 -1.852 2.087 c
+-2.263 2.087 -2.572 1.859 -2.778 1.411 c
+-2.778 -0.956 l
+-2.583 -1.397 -2.271 -1.617 -1.837 -1.617 c
+-1.477 -1.617 -1.216 -1.492 -1.058 -1.235 c
+-0.893 -0.981 -0.808 -0.584 -0.808 -0.044 c
+h
+0.698 0.47 m
+0.698 1.182 0.867 1.753 1.213 2.175 c
+1.565 2.594 2.028 2.807 2.61 2.807 c
+3.186 2.807 3.645 2.601 3.991 2.19 c
+4.343 1.786 4.524 1.227 4.534 0.515 c
+4.534 0 l
+4.534 -0.728 4.359 -1.301 4.006 -1.72 c
+3.66 -2.132 3.2 -2.338 2.624 -2.338 c
+2.043 -2.338 1.581 -2.139 1.228 -1.735 c
+0.883 -1.324 0.706 -0.772 0.698 -0.073 c
+h
+1.507 0 m
+1.507 -0.511 1.602 -0.912 1.801 -1.206 c
+2.007 -1.5 2.279 -1.646 2.624 -1.646 c
+3.337 -1.646 3.705 -1.129 3.726 -0.088 c
+3.726 0.47 l
+3.726 0.977 3.624 1.381 3.418 1.675 c
+3.219 1.969 2.951 2.117 2.61 2.117 c
+2.275 2.117 2.007 1.969 1.801 1.675 c
+1.602 1.381 1.507 0.977 1.507 0.47 c
+h
+5.233 0.47 m
+5.233 1.182 5.402 1.753 5.748 2.175 c
+6.101 2.594 6.564 2.807 7.144 2.807 c
+7.721 2.807 8.18 2.601 8.526 2.19 c
+8.879 1.786 9.058 1.227 9.07 0.515 c
+9.07 0 l
+9.07 -0.728 8.893 -1.301 8.54 -1.72 c
+8.195 -2.132 7.736 -2.338 7.159 -2.338 c
+6.578 -2.338 6.115 -2.139 5.762 -1.735 c
+5.417 -1.324 5.24 -0.772 5.233 -0.073 c
+h
+6.041 0 m
+6.041 -0.511 6.137 -0.912 6.336 -1.206 c
+6.541 -1.5 6.813 -1.646 7.159 -1.646 c
+7.871 -1.646 8.239 -1.129 8.261 -0.088 c
+8.261 0.47 l
+8.261 0.977 8.158 1.381 7.952 1.675 c
+7.754 1.969 7.486 2.117 7.144 2.117 c
+6.809 2.117 6.541 1.969 6.336 1.675 c
+6.137 1.381 6.041 0.977 6.041 0.47 c
+h
+11.175 0.029 m
+10.749 -0.47 l
+10.749 -2.249 l
+9.941 -2.249 l
+9.941 4.806 l
+10.749 4.806 l
+10.749 0.588 l
+12.293 2.719 l
+13.263 2.719 l
+11.69 0.646 l
+13.483 -2.249 l
+12.528 -2.249 l
+h
+20.391 0 m
+20.391 -0.776 20.249 -1.36 19.965 -1.75 c
+19.69 -2.143 19.289 -2.338 18.76 -2.338 c
+18.238 -2.338 17.849 -2.113 17.584 -1.661 c
+17.54 -2.249 l
+16.805 -2.249 l
+16.805 4.806 l
+17.614 4.806 l
+17.614 2.175 l
+17.878 2.594 18.26 2.807 18.76 2.807 c
+19.297 2.807 19.704 2.616 19.979 2.234 c
+20.252 1.851 20.391 1.267 20.391 0.484 c
+h
+19.583 0.455 m
+19.583 1.043 19.499 1.458 19.333 1.705 c
+19.175 1.959 18.911 2.087 18.539 2.087 c
+18.128 2.087 17.82 1.859 17.614 1.411 c
+17.614 -0.956 l
+17.808 -1.397 18.121 -1.617 18.554 -1.617 c
+18.915 -1.617 19.175 -1.492 19.333 -1.235 c
+19.499 -0.981 19.583 -0.584 19.583 -0.044 c
+h
+22.567 -0.897 m
+23.464 2.719 l
+24.33 2.719 l
+22.699 -2.955 l
+22.582 -3.374 22.408 -3.697 22.185 -3.925 c
+21.957 -4.15 21.703 -4.263 21.421 -4.263 c
+21.31 -4.263 21.174 -4.237 21.009 -4.189 c
+21.009 -3.499 l
+21.185 -3.514 l
+21.421 -3.514 21.6 -3.454 21.729 -3.337 c
+21.865 -3.227 21.972 -3.036 22.053 -2.764 c
+22.214 -2.205 l
+20.759 2.719 l
+21.641 2.719 l
+h
+f
+Q
+q 1 0 0 1 539.1547 305.0923 cm
+0 0 m
+0 0.33 -0.096 0.588 -0.279 0.764 c
+-0.456 0.941 -0.779 1.11 -1.249 1.278 c
+-1.72 1.455 -2.084 1.635 -2.338 1.822 c
+-2.583 2.007 -2.771 2.219 -2.896 2.454 c
+-3.025 2.69 -3.087 2.958 -3.087 3.263 c
+-3.087 3.792 -2.911 4.226 -2.558 4.571 c
+-2.198 4.913 -1.731 5.086 -1.162 5.086 c
+-0.772 5.086 -0.422 4.997 -0.118 4.821 c
+0.195 4.644 0.43 4.399 0.588 4.087 c
+0.753 3.781 0.837 3.439 0.837 3.057 c
+0 3.057 l
+0 3.476 -0.104 3.8 -0.309 4.027 c
+-0.507 4.251 -0.79 4.366 -1.162 4.366 c
+-1.507 4.366 -1.771 4.266 -1.955 4.072 c
+-2.143 3.884 -2.234 3.62 -2.234 3.278 c
+-2.234 2.992 -2.132 2.756 -1.926 2.572 c
+-1.72 2.385 -1.407 2.212 -0.985 2.057 c
+-0.331 1.841 0.139 1.573 0.426 1.249 c
+0.709 0.933 0.852 0.522 0.852 0.015 c
+0.852 -0.536 0.676 -0.97 0.324 -1.294 c
+-0.029 -1.617 -0.511 -1.779 -1.118 -1.779 c
+-1.511 -1.779 -1.874 -1.694 -2.205 -1.529 c
+-2.529 -1.363 -2.786 -1.128 -2.969 -0.823 c
+-3.157 -0.511 -3.248 -0.154 -3.248 0.25 c
+-2.411 0.25 l
+-2.411 -0.162 -2.301 -0.485 -2.072 -0.721 c
+-1.837 -0.948 -1.521 -1.058 -1.118 -1.058 c
+-0.746 -1.058 -0.467 -0.966 -0.279 -0.779 c
+-0.096 -0.584 0 -0.324 0 0 c
+3.366 -1.087 m
+3.63 -1.087 3.84 -1.007 3.998 -0.838 c
+4.164 -0.673 4.255 -0.434 4.278 -0.118 c
+5.041 -0.118 l
+5.02 -0.599 4.85 -0.996 4.527 -1.309 c
+4.211 -1.625 3.825 -1.779 3.366 -1.779 c
+2.749 -1.779 2.278 -1.588 1.955 -1.205 c
+1.631 -0.816 1.469 -0.235 1.469 0.529 c
+1.469 1.073 l
+1.469 1.826 1.631 2.396 1.955 2.778 c
+2.278 3.167 2.741 3.366 3.351 3.366 c
+3.858 3.366 4.262 3.204 4.557 2.881 c
+4.858 2.564 5.02 2.132 5.041 1.573 c
+4.278 1.573 l
+4.255 1.933 4.166 2.209 4.012 2.396 c
+3.854 2.58 3.634 2.675 3.351 2.675 c
+2.998 2.675 2.734 2.55 2.558 2.308 c
+2.381 2.072 2.285 1.683 2.278 1.147 c
+2.278 0.515 l
+2.278 -0.073 2.366 -0.493 2.543 -0.735 c
+2.719 -0.97 2.991 -1.087 3.366 -1.087 c
+5.648 1.029 m
+5.648 1.741 5.817 2.311 6.163 2.734 c
+6.516 3.152 6.978 3.366 7.559 3.366 c
+8.135 3.366 8.595 3.16 8.941 2.749 c
+9.294 2.344 9.473 1.786 9.484 1.073 c
+9.484 0.559 l
+9.484 -0.169 9.308 -0.742 8.955 -1.161 c
+8.61 -1.573 8.151 -1.779 7.574 -1.779 c
+6.992 -1.779 6.53 -1.58 6.177 -1.176 c
+5.832 -0.765 5.655 -0.214 5.648 0.485 c
+h
+6.456 0.559 m
+6.456 0.048 6.552 -0.353 6.751 -0.647 c
+6.956 -0.941 7.228 -1.087 7.574 -1.087 c
+8.286 -1.087 8.654 -0.57 8.675 0.47 c
+8.675 1.029 l
+8.675 1.536 8.573 1.94 8.367 2.234 c
+8.168 2.528 7.9 2.675 7.559 2.675 c
+7.224 2.675 6.956 2.528 6.751 2.234 c
+6.552 1.94 6.456 1.536 6.456 1.029 c
+h
+11.418 4.484 m
+11.418 3.278 l
+12.167 3.278 l
+12.167 2.616 l
+11.418 2.616 l
+11.418 -0.455 l
+11.418 -0.654 11.447 -0.805 11.505 -0.912 c
+11.572 -1.01 11.686 -1.058 11.844 -1.058 c
+11.95 -1.058 12.056 -1.04 12.167 -1 c
+12.152 -1.69 l
+11.976 -1.749 11.788 -1.779 11.594 -1.779 c
+11.27 -1.779 11.024 -1.669 10.859 -1.44 c
+10.69 -1.205 10.609 -0.882 10.609 -0.47 c
+10.609 2.616 l
+9.845 2.616 l
+9.845 3.278 l
+10.609 3.278 l
+10.609 4.484 l
+h
+14.082 4.484 m
+14.082 3.278 l
+14.831 3.278 l
+14.831 2.616 l
+14.082 2.616 l
+14.082 -0.455 l
+14.082 -0.654 14.111 -0.805 14.169 -0.912 c
+14.236 -1.01 14.35 -1.058 14.508 -1.058 c
+14.614 -1.058 14.721 -1.04 14.831 -1 c
+14.817 -1.69 l
+14.64 -1.749 14.453 -1.779 14.258 -1.779 c
+13.934 -1.779 13.689 -1.669 13.523 -1.44 c
+13.354 -1.205 13.273 -0.882 13.273 -0.47 c
+13.273 2.616 l
+12.509 2.616 l
+12.509 3.278 l
+13.273 3.278 l
+13.273 4.484 l
+h
+22.416 0.426 m
+22.387 -0.291 22.184 -0.838 21.813 -1.22 c
+21.45 -1.595 20.935 -1.779 20.27 -1.779 c
+19.594 -1.779 19.057 -1.525 18.668 -1.014 c
+18.275 -0.507 18.08 0.183 18.08 1.058 c
+18.08 2.263 l
+18.08 3.135 18.278 3.821 18.682 4.322 c
+19.094 4.829 19.645 5.086 20.343 5.086 c
+20.99 5.086 21.49 4.887 21.843 4.498 c
+22.196 4.116 22.387 3.564 22.416 2.851 c
+21.578 2.851 l
+21.537 3.388 21.42 3.778 21.225 4.013 c
+21.026 4.248 20.733 4.366 20.343 4.366 c
+19.891 4.366 19.542 4.182 19.299 3.821 c
+19.054 3.469 18.932 2.947 18.932 2.263 c
+18.932 1.029 l
+18.932 0.353 19.042 -0.169 19.27 -0.53 c
+19.494 -0.882 19.829 -1.058 20.27 -1.058 c
+20.71 -1.058 21.023 -0.952 21.211 -0.735 c
+21.406 -0.522 21.527 -0.133 21.578 0.426 c
+h
+24.047 2.763 m
+24.349 3.164 24.742 3.366 25.223 3.366 c
+26.105 3.366 26.549 2.782 26.561 1.617 c
+26.561 -1.69 l
+25.753 -1.69 l
+25.753 1.573 l
+25.753 1.962 25.686 2.238 25.562 2.396 c
+25.433 2.562 25.238 2.645 24.974 2.645 c
+24.768 2.645 24.584 2.576 24.43 2.44 c
+24.272 2.311 24.143 2.138 24.047 1.926 c
+24.047 -1.69 l
+23.224 -1.69 l
+23.224 5.365 l
+24.047 5.365 l
+h
+30.14 -1.69 m
+30.089 -1.584 30.056 -1.404 30.037 -1.147 c
+29.751 -1.569 29.383 -1.779 28.935 -1.779 c
+28.483 -1.779 28.13 -1.658 27.877 -1.411 c
+27.63 -1.158 27.509 -0.802 27.509 -0.338 c
+27.509 0.169 27.678 0.573 28.024 0.867 c
+28.365 1.161 28.836 1.311 29.435 1.323 c
+30.023 1.323 l
+30.023 1.852 l
+30.023 2.146 29.953 2.356 29.817 2.484 c
+29.688 2.609 29.493 2.675 29.229 2.675 c
+28.982 2.675 28.781 2.602 28.626 2.454 c
+28.479 2.308 28.406 2.12 28.406 1.897 c
+27.582 1.897 l
+27.582 2.15 27.656 2.396 27.803 2.631 c
+27.958 2.866 28.163 3.046 28.421 3.175 c
+28.674 3.3 28.957 3.366 29.273 3.366 c
+29.78 3.366 30.169 3.237 30.434 2.984 c
+30.699 2.738 30.831 2.37 30.831 1.882 c
+30.831 -0.617 l
+30.838 -1 30.894 -1.334 30.993 -1.617 c
+30.993 -1.69 l
+h
+29.067 -1.043 m
+29.262 -1.043 29.449 -0.992 29.626 -0.882 c
+29.809 -0.765 29.942 -0.628 30.023 -0.47 c
+30.023 0.721 l
+29.566 0.721 l
+29.185 0.709 28.88 0.621 28.656 0.455 c
+28.428 0.287 28.317 0.058 28.317 -0.235 c
+28.317 -0.522 28.369 -0.728 28.479 -0.852 c
+28.596 -0.981 28.791 -1.043 29.067 -1.043 c
+33.639 -1.087 m
+33.903 -1.087 34.112 -1.007 34.27 -0.838 c
+34.436 -0.673 34.528 -0.434 34.549 -0.118 c
+35.314 -0.118 l
+35.292 -0.599 35.123 -0.996 34.8 -1.309 c
+34.484 -1.625 34.098 -1.779 33.639 -1.779 c
+33.021 -1.779 32.55 -1.588 32.228 -1.205 c
+31.904 -0.816 31.742 -0.235 31.742 0.529 c
+31.742 1.073 l
+31.742 1.826 31.904 2.396 32.228 2.778 c
+32.55 3.167 33.014 3.366 33.624 3.366 c
+34.131 3.366 34.535 3.204 34.829 2.881 c
+35.131 2.564 35.292 2.132 35.314 1.573 c
+34.549 1.573 l
+34.528 1.933 34.439 2.209 34.285 2.396 c
+34.127 2.58 33.907 2.675 33.624 2.675 c
+33.271 2.675 33.007 2.55 32.83 2.308 c
+32.654 2.072 32.558 1.683 32.55 1.147 c
+32.55 0.515 l
+32.55 -0.073 32.639 -0.493 32.816 -0.735 c
+32.992 -0.97 33.264 -1.087 33.639 -1.087 c
+35.924 1.029 m
+35.924 1.741 36.093 2.311 36.439 2.734 c
+36.791 3.152 37.254 3.366 37.836 3.366 c
+38.412 3.366 38.871 3.16 39.217 2.749 c
+39.569 2.344 39.75 1.786 39.76 1.073 c
+39.76 0.559 l
+39.76 -0.169 39.584 -0.742 39.232 -1.161 c
+38.886 -1.573 38.426 -1.779 37.85 -1.779 c
+37.269 -1.779 36.806 -1.58 36.454 -1.176 c
+36.108 -0.765 35.931 -0.214 35.924 0.485 c
+h
+36.733 0.559 m
+36.733 0.048 36.828 -0.353 37.026 -0.647 c
+37.233 -0.941 37.504 -1.087 37.85 -1.087 c
+38.563 -1.087 38.931 -0.57 38.952 0.47 c
+38.952 1.029 l
+38.952 1.536 38.85 1.94 38.644 2.234 c
+38.445 2.528 38.177 2.675 37.836 2.675 c
+37.501 2.675 37.233 2.528 37.026 2.234 c
+36.828 1.94 36.733 1.536 36.733 1.029 c
+h
+41.381 3.278 m
+41.41 2.749 l
+41.723 3.16 42.123 3.366 42.616 3.366 c
+43.498 3.366 43.943 2.782 43.953 1.617 c
+43.953 -1.69 l
+43.145 -1.69 l
+43.145 1.573 l
+43.145 1.962 43.079 2.238 42.954 2.396 c
+42.825 2.562 42.63 2.645 42.366 2.645 c
+42.16 2.645 41.977 2.576 41.822 2.44 c
+41.664 2.311 41.535 2.138 41.44 1.926 c
+41.44 -1.69 l
+40.617 -1.69 l
+40.617 3.278 l
+h
+49.988 -1.69 m
+49.936 -1.584 49.903 -1.404 49.885 -1.147 c
+49.598 -1.569 49.231 -1.779 48.782 -1.779 c
+48.33 -1.779 47.978 -1.658 47.724 -1.411 c
+47.478 -1.158 47.357 -0.802 47.357 -0.338 c
+47.357 0.169 47.525 0.573 47.871 0.867 c
+48.213 1.161 48.683 1.311 49.282 1.323 c
+49.87 1.323 l
+49.87 1.852 l
+49.87 2.146 49.8 2.356 49.664 2.484 c
+49.536 2.609 49.341 2.675 49.076 2.675 c
+48.83 2.675 48.628 2.602 48.473 2.454 c
+48.327 2.308 48.253 2.12 48.253 1.897 c
+47.43 1.897 l
+47.43 2.15 47.504 2.396 47.65 2.631 c
+47.805 2.866 48.011 3.046 48.267 3.175 c
+48.521 3.3 48.805 3.366 49.121 3.366 c
+49.628 3.366 50.017 3.237 50.282 2.984 c
+50.546 2.738 50.679 2.37 50.679 1.882 c
+50.679 -0.617 l
+50.686 -1 50.741 -1.334 50.84 -1.617 c
+50.84 -1.69 l
+h
+48.915 -1.043 m
+49.109 -1.043 49.297 -0.992 49.473 -0.882 c
+49.657 -0.765 49.789 -0.628 49.87 -0.47 c
+49.87 0.721 l
+49.414 0.721 l
+49.032 0.709 48.727 0.621 48.503 0.455 c
+48.275 0.287 48.165 0.058 48.165 -0.235 c
+48.165 -0.522 48.217 -0.728 48.327 -0.852 c
+48.444 -0.981 48.639 -1.043 48.915 -1.043 c
+52.516 3.278 m
+52.545 2.749 l
+52.857 3.16 53.258 3.366 53.751 3.366 c
+54.632 3.366 55.077 2.782 55.088 1.617 c
+55.088 -1.69 l
+54.28 -1.69 l
+54.28 1.573 l
+54.28 1.962 54.214 2.238 54.089 2.396 c
+53.96 2.562 53.765 2.645 53.501 2.645 c
+53.295 2.645 53.111 2.576 52.957 2.44 c
+52.799 2.311 52.67 2.138 52.575 1.926 c
+52.575 -1.69 l
+51.751 -1.69 l
+51.751 3.278 l
+h
+55.966 1.014 m
+55.966 1.786 56.106 2.37 56.393 2.763 c
+56.676 3.164 57.087 3.366 57.628 3.366 c
+58.098 3.366 58.465 3.175 58.729 2.793 c
+58.729 5.365 l
+59.552 5.365 l
+59.552 -1.69 l
+58.804 -1.69 l
+58.76 -1.161 l
+58.494 -1.573 58.116 -1.779 57.628 -1.779 c
+57.106 -1.779 56.701 -1.584 56.408 -1.191 c
+56.113 -0.79 55.966 -0.22 55.966 0.515 c
+h
+56.774 0.559 m
+56.774 0 56.855 -0.412 57.025 -0.676 c
+57.19 -0.933 57.458 -1.058 57.833 -1.058 c
+58.234 -1.058 58.532 -0.86 58.729 -0.455 c
+58.729 2.057 l
+58.524 2.447 58.222 2.645 57.833 2.645 c
+57.458 2.645 57.19 2.514 57.025 2.249 c
+56.855 1.992 56.774 1.595 56.774 1.058 c
+h
+63.165 -1.69 m
+63.165 4.997 l
+65.077 4.997 l
+65.682 4.997 66.138 4.843 66.443 4.542 c
+66.756 4.248 66.914 3.807 66.914 3.219 c
+66.914 2.903 66.833 2.624 66.679 2.381 c
+66.521 2.146 66.311 1.962 66.046 1.837 c
+66.347 1.738 66.59 1.547 66.766 1.264 c
+66.951 0.977 67.046 0.636 67.046 0.235 c
+67.046 -0.364 66.877 -0.834 66.546 -1.176 c
+66.212 -1.521 65.742 -1.69 65.135 -1.69 c
+h
+64.003 1.44 m
+64.003 -0.97 l
+65.15 -0.97 l
+65.473 -0.97 65.727 -0.867 65.914 -0.661 c
+66.097 -0.449 66.193 -0.147 66.193 0.235 c
+66.193 1.036 65.855 1.44 65.179 1.44 c
+h
+64.003 2.146 m
+65.091 2.146 l
+65.374 2.146 65.605 2.242 65.782 2.44 c
+65.966 2.635 66.061 2.896 66.061 3.219 c
+66.061 3.59 65.977 3.858 65.811 4.027 c
+65.653 4.193 65.407 4.278 65.077 4.278 c
+64.003 4.278 l
+h
+69.746 -1.779 m
+69.129 -1.779 68.651 -1.598 68.321 -1.235 c
+67.997 -0.864 67.828 -0.32 67.822 0.397 c
+67.822 0.999 l
+67.822 1.735 67.982 2.311 68.306 2.734 c
+68.63 3.152 69.077 3.366 69.659 3.366 c
+70.236 3.366 70.665 3.179 70.952 2.807 c
+71.246 2.444 71.396 1.87 71.408 1.087 c
+71.408 0.559 l
+68.63 0.559 l
+68.63 0.441 l
+68.63 -0.1 68.725 -0.493 68.923 -0.735 c
+69.129 -0.97 69.416 -1.087 69.791 -1.087 c
+70.033 -1.087 70.247 -1.043 70.423 -0.956 c
+70.606 -0.867 70.779 -0.728 70.937 -0.53 c
+71.363 -1.043 l
+71.011 -1.536 70.471 -1.779 69.746 -1.779 c
+69.659 2.675 m
+69.324 2.675 69.075 2.558 68.909 2.323 c
+68.74 2.094 68.648 1.738 68.63 1.249 c
+70.585 1.249 l
+70.585 1.367 l
+70.563 1.837 70.482 2.168 70.334 2.367 c
+70.188 2.572 69.96 2.675 69.659 2.675 c
+72.966 3.278 m
+72.996 2.749 l
+73.308 3.16 73.708 3.366 74.201 3.366 c
+75.082 3.366 75.527 2.782 75.539 1.617 c
+75.539 -1.69 l
+74.729 -1.69 l
+74.729 1.573 l
+74.729 1.962 74.664 2.238 74.538 2.396 c
+74.41 2.562 74.215 2.645 73.951 2.645 c
+73.745 2.645 73.561 2.576 73.407 2.44 c
+73.249 2.311 73.12 2.138 73.025 1.926 c
+73.025 -1.69 l
+72.202 -1.69 l
+72.202 3.278 l
+h
+82.057 0 m
+82.057 0.33 81.962 0.588 81.777 0.764 c
+81.602 0.941 81.278 1.11 80.808 1.278 c
+80.337 1.455 79.973 1.635 79.72 1.822 c
+79.474 2.007 79.286 2.219 79.161 2.454 c
+79.032 2.69 78.97 2.958 78.97 3.263 c
+78.97 3.792 79.147 4.226 79.5 4.571 c
+79.859 4.913 80.327 5.086 80.896 5.086 c
+81.285 5.086 81.635 4.997 81.939 4.821 c
+82.252 4.644 82.487 4.399 82.645 4.087 c
+82.81 3.781 82.895 3.439 82.895 3.057 c
+82.057 3.057 l
+82.057 3.476 81.954 3.8 81.748 4.027 c
+81.55 4.251 81.268 4.366 80.896 4.366 c
+80.551 4.366 80.286 4.266 80.102 4.072 c
+79.915 3.884 79.823 3.62 79.823 3.278 c
+79.823 2.992 79.926 2.756 80.131 2.572 c
+80.337 2.385 80.65 2.212 81.072 2.057 c
+81.727 1.841 82.197 1.573 82.483 1.249 c
+82.766 0.933 82.91 0.522 82.91 0.015 c
+82.91 -0.536 82.733 -0.97 82.38 -1.294 c
+82.028 -1.617 81.546 -1.779 80.94 -1.779 c
+80.547 -1.779 80.183 -1.694 79.853 -1.529 c
+79.529 -1.363 79.271 -1.128 79.088 -0.823 c
+78.901 -0.511 78.808 -0.154 78.808 0.25 c
+79.647 0.25 l
+79.647 -0.162 79.757 -0.485 79.984 -0.721 c
+80.22 -0.948 80.536 -1.058 80.94 -1.058 c
+81.311 -1.058 81.59 -0.966 81.777 -0.779 c
+81.962 -0.584 82.057 -0.324 82.057 0 c
+84.761 4.484 m
+84.761 3.278 l
+85.511 3.278 l
+85.511 2.616 l
+84.761 2.616 l
+84.761 -0.455 l
+84.761 -0.654 84.792 -0.805 84.85 -0.912 c
+84.916 -1.01 85.031 -1.058 85.188 -1.058 c
+85.295 -1.058 85.401 -1.04 85.511 -1 c
+85.497 -1.69 l
+85.32 -1.749 85.133 -1.779 84.938 -1.779 c
+84.615 -1.779 84.368 -1.669 84.204 -1.44 c
+84.034 -1.205 83.953 -0.882 83.953 -0.47 c
+83.953 2.616 l
+83.189 2.616 l
+83.189 3.278 l
+83.953 3.278 l
+83.953 4.484 l
+h
+88.411 2.514 m
+88.293 2.532 88.168 2.543 88.044 2.543 c
+87.62 2.543 87.331 2.315 87.176 1.866 c
+87.176 -1.69 l
+86.353 -1.69 l
+86.353 3.278 l
+87.147 3.278 l
+87.161 2.778 l
+87.375 3.167 87.683 3.366 88.088 3.366 c
+88.212 3.366 88.323 3.344 88.411 3.308 c
+h
+91.483 -1.69 m
+91.431 -1.584 91.398 -1.404 91.381 -1.147 c
+91.094 -1.569 90.726 -1.779 90.278 -1.779 c
+89.826 -1.779 89.473 -1.658 89.22 -1.411 c
+88.973 -1.158 88.852 -0.802 88.852 -0.338 c
+88.852 0.169 89.021 0.573 89.366 0.867 c
+89.708 1.161 90.178 1.311 90.778 1.323 c
+91.365 1.323 l
+91.365 1.852 l
+91.365 2.146 91.296 2.356 91.159 2.484 c
+91.031 2.609 90.836 2.675 90.572 2.675 c
+90.325 2.675 90.124 2.602 89.969 2.454 c
+89.822 2.308 89.748 2.12 89.748 1.897 c
+88.925 1.897 l
+88.925 2.15 88.999 2.396 89.145 2.631 c
+89.301 2.866 89.506 3.046 89.763 3.175 c
+90.016 3.3 90.3 3.366 90.616 3.366 c
+91.123 3.366 91.512 3.237 91.777 2.984 c
+92.042 2.738 92.174 2.37 92.174 1.882 c
+92.174 -0.617 l
+92.181 -1 92.237 -1.334 92.335 -1.617 c
+92.335 -1.69 l
+h
+90.41 -1.043 m
+90.604 -1.043 90.792 -0.992 90.969 -0.882 c
+91.152 -0.765 91.285 -0.628 91.365 -0.47 c
+91.365 0.721 l
+90.91 0.721 l
+90.527 0.709 90.222 0.621 89.999 0.455 c
+89.771 0.287 89.66 0.058 89.66 -0.235 c
+89.66 -0.522 89.712 -0.728 89.822 -0.852 c
+89.939 -0.981 90.134 -1.043 90.41 -1.043 c
+95.79 -1.249 m
+95.514 -1.602 95.117 -1.779 94.599 -1.779 c
+94.159 -1.779 93.82 -1.628 93.585 -1.323 c
+93.357 -1.01 93.239 -0.555 93.232 0.044 c
+93.232 3.278 l
+94.041 3.278 l
+94.041 0.103 l
+94.041 -0.673 94.276 -1.058 94.747 -1.058 c
+95.235 -1.058 95.573 -0.838 95.761 -0.397 c
+95.761 3.278 l
+96.584 3.278 l
+96.584 -1.69 l
+95.805 -1.69 l
+h
+101.224 0.559 m
+101.224 -0.217 101.081 -0.802 100.798 -1.191 c
+100.523 -1.584 100.122 -1.779 99.593 -1.779 c
+99.071 -1.779 98.682 -1.554 98.417 -1.103 c
+98.373 -1.69 l
+97.638 -1.69 l
+97.638 5.365 l
+98.446 5.365 l
+98.446 2.734 l
+98.711 3.152 99.094 3.366 99.593 3.366 c
+100.129 3.366 100.538 3.175 100.813 2.793 c
+101.085 2.41 101.224 1.826 101.224 1.043 c
+h
+100.416 1.014 m
+100.416 1.602 100.332 2.017 100.166 2.263 c
+100.008 2.517 99.744 2.645 99.373 2.645 c
+98.961 2.645 98.652 2.418 98.446 1.97 c
+98.446 -0.397 l
+98.641 -0.838 98.953 -1.058 99.387 -1.058 c
+99.747 -1.058 100.008 -0.933 100.166 -0.676 c
+100.332 -0.422 100.416 -0.025 100.416 0.515 c
+h
+102.144 -1.249 m
+102.144 -1.103 102.188 -0.981 102.276 -0.882 c
+102.364 -0.786 102.489 -0.735 102.658 -0.735 c
+102.834 -0.735 102.967 -0.786 103.055 -0.882 c
+103.15 -0.981 103.202 -1.103 103.202 -1.249 c
+103.202 -1.389 103.15 -1.507 103.055 -1.602 c
+102.967 -1.69 102.834 -1.735 102.658 -1.735 c
+102.489 -1.735 102.364 -1.69 102.276 -1.602 c
+102.188 -1.507 102.144 -1.389 102.144 -1.249 c
+110.757 4.278 m
+108.993 4.278 l
+108.993 -1.69 l
+108.156 -1.69 l
+108.156 4.278 l
+106.406 4.278 l
+106.406 4.997 l
+110.757 4.997 l
+h
+112.264 2.763 m
+112.565 3.164 112.958 3.366 113.44 3.366 c
+114.321 3.366 114.766 2.782 114.778 1.617 c
+114.778 -1.69 l
+113.969 -1.69 l
+113.969 1.573 l
+113.969 1.962 113.903 2.238 113.778 2.396 c
+113.649 2.562 113.454 2.645 113.19 2.645 c
+112.984 2.645 112.8 2.576 112.646 2.44 c
+112.488 2.311 112.359 2.138 112.264 1.926 c
+112.264 -1.69 l
+111.441 -1.69 l
+111.441 5.365 l
+112.264 5.365 l
+h
+117.574 -1.779 m
+116.956 -1.779 116.479 -1.598 116.148 -1.235 c
+115.825 -0.864 115.655 -0.32 115.648 0.397 c
+115.648 0.999 l
+115.648 1.735 115.81 2.311 116.133 2.734 c
+116.457 3.152 116.905 3.366 117.486 3.366 c
+118.063 3.366 118.493 3.179 118.779 2.807 c
+119.073 2.444 119.224 1.87 119.235 1.087 c
+119.235 0.559 l
+116.457 0.559 l
+116.457 0.441 l
+116.457 -0.1 116.552 -0.493 116.75 -0.735 c
+116.956 -0.97 117.243 -1.087 117.618 -1.087 c
+117.86 -1.087 118.073 -1.043 118.25 -0.956 c
+118.433 -0.867 118.607 -0.728 118.765 -0.53 c
+119.191 -1.043 l
+118.838 -1.536 118.298 -1.779 117.574 -1.779 c
+117.486 2.675 m
+117.151 2.675 116.901 2.558 116.736 2.323 c
+116.567 2.094 116.475 1.738 116.457 1.249 c
+118.412 1.249 l
+118.412 1.367 l
+118.389 1.837 118.308 2.168 118.161 2.367 c
+118.015 2.572 117.787 2.675 117.486 2.675 c
+126.069 0.559 m
+126.069 -0.217 125.926 -0.802 125.643 -1.191 c
+125.368 -1.584 124.968 -1.779 124.438 -1.779 c
+123.916 -1.779 123.527 -1.554 123.262 -1.103 c
+123.218 -1.69 l
+122.483 -1.69 l
+122.483 5.365 l
+123.291 5.365 l
+123.291 2.734 l
+123.557 3.152 123.939 3.366 124.438 3.366 c
+124.974 3.366 125.383 3.175 125.658 2.793 c
+125.93 2.41 126.069 1.826 126.069 1.043 c
+h
+125.261 1.014 m
+125.261 1.602 125.177 2.017 125.012 2.263 c
+124.854 2.517 124.589 2.645 124.218 2.645 c
+123.806 2.645 123.497 2.418 123.291 1.97 c
+123.291 -0.397 l
+123.486 -0.838 123.798 -1.058 124.232 -1.058 c
+124.592 -1.058 124.854 -0.933 125.012 -0.676 c
+125.177 -0.422 125.261 -0.025 125.261 0.515 c
+h
+126.768 1.029 m
+126.768 1.741 126.937 2.311 127.283 2.734 c
+127.636 3.152 128.099 3.366 128.679 3.366 c
+129.256 3.366 129.716 3.16 130.061 2.749 c
+130.414 2.344 130.593 1.786 130.605 1.073 c
+130.605 0.559 l
+130.605 -0.169 130.428 -0.742 130.075 -1.161 c
+129.73 -1.573 129.271 -1.779 128.694 -1.779 c
+128.113 -1.779 127.65 -1.58 127.297 -1.176 c
+126.952 -0.765 126.775 -0.214 126.768 0.485 c
+h
+127.576 0.559 m
+127.576 0.048 127.672 -0.353 127.871 -0.647 c
+128.076 -0.941 128.348 -1.087 128.694 -1.087 c
+129.406 -1.087 129.774 -0.57 129.796 0.47 c
+129.796 1.029 l
+129.796 1.536 129.693 1.94 129.487 2.234 c
+129.289 2.528 129.02 2.675 128.679 2.675 c
+128.344 2.675 128.076 2.528 127.871 2.234 c
+127.672 1.94 127.576 1.536 127.576 1.029 c
+h
+131.303 1.029 m
+131.303 1.741 131.472 2.311 131.817 2.734 c
+132.17 3.152 132.633 3.366 133.213 3.366 c
+133.791 3.366 134.25 3.16 134.595 2.749 c
+134.948 2.344 135.128 1.786 135.139 1.073 c
+135.139 0.559 l
+135.139 -0.169 134.963 -0.742 134.61 -1.161 c
+134.264 -1.573 133.805 -1.779 133.228 -1.779 c
+132.648 -1.779 132.184 -1.58 131.832 -1.176 c
+131.486 -0.765 131.31 -0.214 131.303 0.485 c
+h
+132.111 0.559 m
+132.111 0.048 132.207 -0.353 132.405 -0.647 c
+132.611 -0.941 132.883 -1.087 133.228 -1.087 c
+133.941 -1.087 134.308 -0.57 134.331 0.47 c
+134.331 1.029 l
+134.331 1.536 134.227 1.94 134.022 2.234 c
+133.824 2.528 133.556 2.675 133.213 2.675 c
+132.879 2.675 132.611 2.528 132.405 2.234 c
+132.207 1.94 132.111 1.536 132.111 1.029 c
+h
+137.244 0.588 m
+136.818 0.088 l
+136.818 -1.69 l
+136.01 -1.69 l
+136.01 5.365 l
+136.818 5.365 l
+136.818 1.147 l
+138.362 3.278 l
+139.332 3.278 l
+137.759 1.205 l
+139.553 -1.69 l
+138.597 -1.69 l
+h
+143.393 -1.69 -0.809 4.968 re
+143.451 4.601 m
+143.451 4.461 143.411 4.343 143.334 4.248 c
+143.264 4.16 143.15 4.116 142.996 4.116 c
+142.838 4.116 142.72 4.16 142.643 4.248 c
+142.573 4.343 142.54 4.461 142.54 4.601 c
+142.54 4.737 142.573 4.85 142.643 4.939 c
+142.72 5.034 142.834 5.086 142.981 5.086 c
+143.135 5.086 143.253 5.034 143.334 4.939 c
+143.411 4.85 143.451 4.737 143.451 4.601 c
+147.001 -0.412 m
+147.001 -0.246 146.931 -0.1 146.796 0.029 c
+146.667 0.154 146.414 0.301 146.031 0.47 c
+145.597 0.654 145.289 0.812 145.105 0.941 c
+144.928 1.066 144.797 1.209 144.708 1.367 c
+144.62 1.532 144.576 1.727 144.576 1.955 c
+144.576 2.367 144.723 2.705 145.017 2.969 c
+145.311 3.233 145.686 3.366 146.148 3.366 c
+146.638 3.366 147.031 3.223 147.324 2.94 c
+147.619 2.664 147.766 2.308 147.766 1.866 c
+146.958 1.866 l
+146.958 2.091 146.877 2.282 146.722 2.44 c
+146.575 2.595 146.384 2.675 146.148 2.675 c
+145.913 2.675 145.726 2.609 145.59 2.484 c
+145.451 2.367 145.385 2.198 145.385 1.984 c
+145.385 1.816 145.433 1.683 145.531 1.587 c
+145.627 1.488 145.869 1.356 146.252 1.191 c
+146.858 0.956 147.27 0.723 147.486 0.5 c
+147.7 0.272 147.81 -0.011 147.81 -0.353 c
+147.81 -0.786 147.656 -1.132 147.355 -1.396 c
+147.06 -1.654 146.663 -1.779 146.164 -1.779 c
+145.653 -1.779 145.238 -1.631 144.914 -1.338 c
+144.591 -1.043 144.429 -0.669 144.429 -0.206 c
+145.252 -0.206 l
+145.26 -0.482 145.344 -0.698 145.502 -0.852 c
+145.656 -1.01 145.877 -1.087 146.164 -1.087 c
+146.435 -1.087 146.641 -1.029 146.781 -0.912 c
+146.927 -0.786 147.001 -0.617 147.001 -0.412 c
+153.682 -1.69 m
+153.63 -1.584 153.597 -1.404 153.579 -1.147 c
+153.292 -1.569 152.925 -1.779 152.477 -1.779 c
+152.024 -1.779 151.672 -1.658 151.419 -1.411 c
+151.172 -1.158 151.051 -0.802 151.051 -0.338 c
+151.051 0.169 151.22 0.573 151.565 0.867 c
+151.907 1.161 152.377 1.311 152.976 1.323 c
+153.564 1.323 l
+153.564 1.852 l
+153.564 2.146 153.495 2.356 153.358 2.484 c
+153.23 2.609 153.036 2.675 152.77 2.675 c
+152.525 2.675 152.323 2.602 152.168 2.454 c
+152.021 2.308 151.947 2.12 151.947 1.897 c
+151.124 1.897 l
+151.124 2.15 151.197 2.396 151.345 2.631 c
+151.499 2.866 151.705 3.046 151.962 3.175 c
+152.215 3.3 152.499 3.366 152.815 3.366 c
+153.322 3.366 153.711 3.237 153.976 2.984 c
+154.241 2.738 154.372 2.37 154.372 1.882 c
+154.372 -0.617 l
+154.38 -1 154.435 -1.334 154.534 -1.617 c
+154.534 -1.69 l
+h
+152.609 -1.043 m
+152.803 -1.043 152.991 -0.992 153.167 -0.882 c
+153.351 -0.765 153.483 -0.628 153.564 -0.47 c
+153.564 0.721 l
+153.109 0.721 l
+152.726 0.709 152.421 0.621 152.197 0.455 c
+151.97 0.287 151.86 0.058 151.86 -0.235 c
+151.86 -0.522 151.911 -0.728 152.021 -0.852 c
+152.138 -0.981 152.333 -1.043 152.609 -1.043 c
+156.784 -0.455 m
+157.724 3.278 l
+158.562 3.278 l
+157.077 -1.69 l
+156.475 -1.69 l
+154.975 3.278 l
+155.814 3.278 l
+h
+161.722 -1.69 m
+161.671 -1.584 161.638 -1.404 161.62 -1.147 c
+161.333 -1.569 160.965 -1.779 160.517 -1.779 c
+160.065 -1.779 159.712 -1.658 159.459 -1.411 c
+159.213 -1.158 159.091 -0.802 159.091 -0.338 c
+159.091 0.169 159.261 0.573 159.606 0.867 c
+159.947 1.161 160.418 1.311 161.017 1.323 c
+161.605 1.323 l
+161.605 1.852 l
+161.605 2.146 161.535 2.356 161.399 2.484 c
+161.27 2.609 161.075 2.675 160.811 2.675 c
+160.564 2.675 160.363 2.602 160.209 2.454 c
+160.061 2.308 159.988 2.12 159.988 1.897 c
+159.165 1.897 l
+159.165 2.15 159.238 2.396 159.386 2.631 c
+159.54 2.866 159.745 3.046 160.003 3.175 c
+160.256 3.3 160.539 3.366 160.855 3.366 c
+161.362 3.366 161.752 3.237 162.016 2.984 c
+162.281 2.738 162.413 2.37 162.413 1.882 c
+162.413 -0.617 l
+162.42 -1 162.476 -1.334 162.575 -1.617 c
+162.575 -1.69 l
+h
+160.649 -1.043 m
+160.844 -1.043 161.032 -0.992 161.208 -0.882 c
+161.391 -0.765 161.524 -0.628 161.605 -0.47 c
+161.605 0.721 l
+161.15 0.721 l
+160.767 0.709 160.462 0.621 160.238 0.455 c
+160.01 0.287 159.899 0.058 159.899 -0.235 c
+159.899 -0.522 159.951 -0.728 160.061 -0.852 c
+160.179 -0.981 160.373 -1.043 160.649 -1.043 c
+164.368 -1.69 -0.808 4.968 re
+164.427 4.601 m
+164.427 4.461 164.387 4.343 164.31 4.248 c
+164.24 4.16 164.126 4.116 163.972 4.116 c
+163.814 4.116 163.696 4.16 163.619 4.248 c
+163.548 4.343 163.516 4.461 163.516 4.601 c
+163.516 4.737 163.548 4.85 163.619 4.939 c
+163.696 5.034 163.81 5.086 163.957 5.086 c
+164.111 5.086 164.229 5.034 164.31 4.939 c
+164.387 4.85 164.427 4.737 164.427 4.601 c
+166.434 -1.69 -0.809 7.056 re
+170.174 -1.69 m
+170.123 -1.584 170.089 -1.404 170.072 -1.147 c
+169.785 -1.569 169.418 -1.779 168.969 -1.779 c
+168.517 -1.779 168.165 -1.658 167.911 -1.411 c
+167.664 -1.158 167.543 -0.802 167.543 -0.338 c
+167.543 0.169 167.712 0.573 168.057 0.867 c
+168.4 1.161 168.87 1.311 169.469 1.323 c
+170.056 1.323 l
+170.056 1.852 l
+170.056 2.146 169.987 2.356 169.851 2.484 c
+169.723 2.609 169.528 2.675 169.263 2.675 c
+169.017 2.675 168.815 2.602 168.66 2.454 c
+168.514 2.308 168.44 2.12 168.44 1.897 c
+167.617 1.897 l
+167.617 2.15 167.69 2.396 167.837 2.631 c
+167.992 2.866 168.198 3.046 168.454 3.175 c
+168.708 3.3 168.992 3.366 169.307 3.366 c
+169.814 3.366 170.204 3.237 170.469 2.984 c
+170.733 2.738 170.865 2.37 170.865 1.882 c
+170.865 -0.617 l
+170.873 -1 170.928 -1.334 171.027 -1.617 c
+171.027 -1.69 l
+h
+169.102 -1.043 m
+169.296 -1.043 169.484 -0.992 169.659 -0.882 c
+169.844 -0.765 169.976 -0.628 170.056 -0.47 c
+170.056 0.721 l
+169.601 0.721 l
+169.219 0.709 168.913 0.621 168.69 0.455 c
+168.462 0.287 168.352 0.058 168.352 -0.235 c
+168.352 -0.522 168.403 -0.728 168.514 -0.852 c
+168.631 -0.981 168.826 -1.043 169.102 -1.043 c
+175.539 0.559 m
+175.539 -0.217 175.396 -0.802 175.113 -1.191 c
+174.837 -1.584 174.437 -1.779 173.908 -1.779 c
+173.386 -1.779 172.996 -1.554 172.732 -1.103 c
+172.688 -1.69 l
+171.953 -1.69 l
+171.953 5.365 l
+172.761 5.365 l
+172.761 2.734 l
+173.026 3.152 173.408 3.366 173.908 3.366 c
+174.444 3.366 174.852 3.175 175.128 2.793 c
+175.4 2.41 175.539 1.826 175.539 1.043 c
+h
+174.731 1.014 m
+174.731 1.602 174.646 2.017 174.481 2.263 c
+174.323 2.517 174.058 2.645 173.688 2.645 c
+173.276 2.645 172.967 2.418 172.761 1.97 c
+172.761 -0.397 l
+172.956 -0.838 173.268 -1.058 173.702 -1.058 c
+174.062 -1.058 174.323 -0.933 174.481 -0.676 c
+174.646 -0.422 174.731 -0.025 174.731 0.515 c
+h
+177.281 -1.69 -0.808 7.056 re
+180.243 -1.779 m
+179.626 -1.779 179.148 -1.598 178.818 -1.235 c
+178.494 -0.864 178.325 -0.32 178.318 0.397 c
+178.318 0.999 l
+178.318 1.735 178.479 2.311 178.803 2.734 c
+179.126 3.152 179.575 3.366 180.155 3.366 c
+180.732 3.366 181.162 3.179 181.449 2.807 c
+181.742 2.444 181.893 1.87 181.904 1.087 c
+181.904 0.559 l
+179.126 0.559 l
+179.126 0.441 l
+179.126 -0.1 179.221 -0.493 179.42 -0.735 c
+179.626 -0.97 179.913 -1.087 180.287 -1.087 c
+180.53 -1.087 180.743 -1.043 180.919 -0.956 c
+181.103 -0.867 181.276 -0.728 181.434 -0.53 c
+181.86 -1.043 l
+181.507 -1.536 180.967 -1.779 180.243 -1.779 c
+180.155 2.675 m
+179.82 2.675 179.571 2.558 179.406 2.323 c
+179.236 2.094 179.144 1.738 179.126 1.249 c
+181.081 1.249 l
+181.081 1.367 l
+181.059 1.837 180.978 2.168 180.831 2.367 c
+180.684 2.572 180.456 2.675 180.155 2.675 c
+184.973 1.029 m
+184.973 1.741 185.141 2.311 185.487 2.734 c
+185.84 3.152 186.303 3.366 186.883 3.366 c
+187.46 3.366 187.92 3.16 188.265 2.749 c
+188.618 2.344 188.798 1.786 188.809 1.073 c
+188.809 0.559 l
+188.809 -0.169 188.632 -0.742 188.279 -1.161 c
+187.934 -1.573 187.475 -1.779 186.899 -1.779 c
+186.317 -1.779 185.854 -1.58 185.502 -1.176 c
+185.156 -0.765 184.98 -0.214 184.973 0.485 c
+h
+185.781 0.559 m
+185.781 0.048 185.877 -0.353 186.075 -0.647 c
+186.28 -0.941 186.552 -1.087 186.899 -1.087 c
+187.611 -1.087 187.978 -0.57 188.001 0.47 c
+188.001 1.029 l
+188.001 1.536 187.898 1.94 187.692 2.234 c
+187.493 2.528 187.225 2.675 186.883 2.675 c
+186.549 2.675 186.28 2.528 186.075 2.234 c
+185.877 1.94 185.781 1.536 185.781 1.029 c
+h
+190.433 3.278 m
+190.463 2.749 l
+190.775 3.16 191.176 3.366 191.668 3.366 c
+192.549 3.366 192.995 2.782 193.006 1.617 c
+193.006 -1.69 l
+192.197 -1.69 l
+192.197 1.573 l
+192.197 1.962 192.131 2.238 192.006 2.396 c
+191.878 2.562 191.683 2.645 191.418 2.645 c
+191.213 2.645 191.028 2.576 190.874 2.44 c
+190.716 2.311 190.588 2.138 190.492 1.926 c
+190.492 -1.69 l
+189.669 -1.69 l
+189.669 3.278 l
+h
+194.924 -1.69 -0.808 7.056 re
+196.989 -1.69 -0.808 4.968 re
+197.048 4.601 m
+197.048 4.461 197.008 4.343 196.931 4.248 c
+196.86 4.16 196.746 4.116 196.592 4.116 c
+196.434 4.116 196.316 4.16 196.239 4.248 c
+196.169 4.343 196.137 4.461 196.137 4.601 c
+196.137 4.737 196.169 4.85 196.239 4.939 c
+196.316 5.034 196.43 5.086 196.578 5.086 c
+196.732 5.086 196.85 5.034 196.931 4.939 c
+197.008 4.85 197.048 4.737 197.048 4.601 c
+198.937 3.278 m
+198.966 2.749 l
+199.279 3.16 199.679 3.366 200.171 3.366 c
+201.054 3.366 201.498 2.782 201.509 1.617 c
+201.509 -1.69 l
+200.701 -1.69 l
+200.701 1.573 l
+200.701 1.962 200.634 2.238 200.509 2.396 c
+200.381 2.562 200.186 2.645 199.921 2.645 c
+199.716 2.645 199.532 2.576 199.377 2.44 c
+199.219 2.311 199.091 2.138 198.995 1.926 c
+198.995 -1.69 l
+198.172 -1.69 l
+198.172 3.278 l
+h
+204.324 -1.779 m
+203.707 -1.779 203.229 -1.598 202.898 -1.235 c
+202.575 -0.864 202.406 -0.32 202.398 0.397 c
+202.398 0.999 l
+202.398 1.735 202.56 2.311 202.884 2.734 c
+203.207 3.152 203.655 3.366 204.235 3.366 c
+204.813 3.366 205.243 3.179 205.529 2.807 c
+205.823 2.444 205.974 1.87 205.985 1.087 c
+205.985 0.559 l
+203.207 0.559 l
+203.207 0.441 l
+203.207 -0.1 203.302 -0.493 203.501 -0.735 c
+203.707 -0.97 203.994 -1.087 204.368 -1.087 c
+204.611 -1.087 204.823 -1.043 205 -0.956 c
+205.184 -0.867 205.357 -0.728 205.515 -0.53 c
+205.941 -1.043 l
+205.588 -1.536 205.048 -1.779 204.324 -1.779 c
+204.235 2.675 m
+203.901 2.675 203.651 2.558 203.486 2.323 c
+203.317 2.094 203.225 1.738 203.207 1.249 c
+205.162 1.249 l
+205.162 1.367 l
+205.139 1.837 205.059 2.168 204.912 2.367 c
+204.765 2.572 204.537 2.675 204.235 2.675 c
+209.586 -1.69 m
+209.586 2.616 l
+208.939 2.616 l
+208.939 3.278 l
+209.586 3.278 l
+209.586 3.851 l
+209.594 4.358 209.722 4.755 209.968 5.041 c
+210.211 5.325 210.56 5.468 211.012 5.468 c
+211.167 5.468 211.328 5.438 211.497 5.38 c
+211.453 4.689 l
+211.343 4.719 211.221 4.733 211.086 4.733 c
+210.622 4.733 210.394 4.403 210.394 3.748 c
+210.394 3.278 l
+211.247 3.278 l
+211.247 2.616 l
+210.394 2.616 l
+210.394 -1.69 l
+h
+211.912 1.029 m
+211.912 1.741 212.081 2.311 212.426 2.734 c
+212.779 3.152 213.243 3.366 213.823 3.366 c
+214.4 3.366 214.859 3.16 215.204 2.749 c
+215.558 2.344 215.738 1.786 215.749 1.073 c
+215.749 0.559 l
+215.749 -0.169 215.572 -0.742 215.219 -1.161 c
+214.874 -1.573 214.415 -1.779 213.838 -1.779 c
+213.257 -1.779 212.794 -1.58 212.441 -1.176 c
+212.096 -0.765 211.919 -0.214 211.912 0.485 c
+h
+212.721 0.559 m
+212.721 0.048 212.816 -0.353 213.014 -0.647 c
+213.22 -0.941 213.492 -1.087 213.838 -1.087 c
+214.551 -1.087 214.918 -0.57 214.94 0.47 c
+214.94 1.029 l
+214.94 1.536 214.838 1.94 214.632 2.234 c
+214.433 2.528 214.165 2.675 213.823 2.675 c
+213.489 2.675 213.22 2.528 213.014 2.234 c
+212.816 1.94 212.721 1.536 212.721 1.029 c
+h
+218.666 2.514 m
+218.549 2.532 218.424 2.543 218.299 2.543 c
+217.876 2.543 217.586 2.315 217.432 1.866 c
+217.432 -1.69 l
+216.609 -1.69 l
+216.609 3.278 l
+217.402 3.278 l
+217.417 2.778 l
+217.631 3.167 217.939 3.366 218.343 3.366 c
+218.468 3.366 218.578 3.344 218.666 3.308 c
+h
+222.165 -1.69 m
+222.165 2.616 l
+221.518 2.616 l
+221.518 3.278 l
+222.165 3.278 l
+222.165 3.851 l
+222.172 4.358 222.3 4.755 222.547 5.041 c
+222.79 5.325 223.139 5.468 223.591 5.468 c
+223.745 5.468 223.906 5.438 224.076 5.38 c
+224.031 4.689 l
+223.921 4.719 223.8 4.733 223.664 4.733 c
+223.201 4.733 222.973 4.403 222.973 3.748 c
+222.973 3.278 l
+223.826 3.278 l
+223.826 2.616 l
+222.973 2.616 l
+222.973 -1.69 l
+h
+226.714 2.514 m
+226.597 2.532 226.472 2.543 226.347 2.543 c
+225.924 2.543 225.633 2.315 225.479 1.866 c
+225.479 -1.69 l
+224.656 -1.69 l
+224.656 3.278 l
+225.45 3.278 l
+225.465 2.778 l
+225.678 3.167 225.986 3.366 226.391 3.366 c
+226.516 3.366 226.626 3.344 226.714 3.308 c
+h
+229.099 -1.779 m
+228.482 -1.779 228.004 -1.598 227.673 -1.235 c
+227.35 -0.864 227.181 -0.32 227.173 0.397 c
+227.173 0.999 l
+227.173 1.735 227.335 2.311 227.659 2.734 c
+227.982 3.152 228.43 3.366 229.011 3.366 c
+229.588 3.366 230.018 3.179 230.304 2.807 c
+230.599 2.444 230.749 1.87 230.76 1.087 c
+230.76 0.559 l
+227.982 0.559 l
+227.982 0.441 l
+227.982 -0.1 228.077 -0.493 228.276 -0.735 c
+228.482 -0.97 228.768 -1.087 229.143 -1.087 c
+229.386 -1.087 229.599 -1.043 229.776 -0.956 c
+229.959 -0.867 230.132 -0.728 230.29 -0.53 c
+230.716 -1.043 l
+230.364 -1.536 229.823 -1.779 229.099 -1.779 c
+229.011 2.675 m
+228.677 2.675 228.427 2.558 228.261 2.323 c
+228.093 2.094 228 1.738 227.982 1.249 c
+229.937 1.249 l
+229.937 1.367 l
+229.915 1.837 229.834 2.168 229.687 2.367 c
+229.54 2.572 229.313 2.675 229.011 2.675 c
+233.332 -1.779 m
+232.715 -1.779 232.237 -1.598 231.906 -1.235 c
+231.584 -0.864 231.414 -0.32 231.407 0.397 c
+231.407 0.999 l
+231.407 1.735 231.569 2.311 231.892 2.734 c
+232.216 3.152 232.664 3.366 233.244 3.366 c
+233.822 3.366 234.252 3.179 234.538 2.807 c
+234.832 2.444 234.983 1.87 234.994 1.087 c
+234.994 0.559 l
+232.216 0.559 l
+232.216 0.441 l
+232.216 -0.1 232.311 -0.493 232.509 -0.735 c
+232.715 -0.97 233.001 -1.087 233.377 -1.087 c
+233.619 -1.087 233.832 -1.043 234.009 -0.956 c
+234.192 -0.867 234.365 -0.728 234.523 -0.53 c
+234.95 -1.043 l
+234.597 -1.536 234.057 -1.779 233.332 -1.779 c
+233.244 2.675 m
+232.91 2.675 232.66 2.558 232.494 2.323 c
+232.326 2.094 232.234 1.738 232.216 1.249 c
+234.171 1.249 l
+234.171 1.367 l
+234.148 1.837 234.067 2.168 233.92 2.367 c
+233.774 2.572 233.546 2.675 233.244 2.675 c
+f
+Q
+q 1 0 0 1 538.6692 292.1129 cm
+0 0 m
+-0.052 0.106 -0.085 0.287 -0.103 0.544 c
+-0.389 0.121 -0.757 -0.088 -1.205 -0.088 c
+-1.658 -0.088 -2.01 0.033 -2.263 0.279 c
+-2.51 0.532 -2.631 0.889 -2.631 1.353 c
+-2.631 1.86 -2.462 2.263 -2.117 2.558 c
+-1.775 2.851 -1.305 3.002 -0.706 3.013 c
+-0.118 3.013 l
+-0.118 3.543 l
+-0.118 3.836 -0.187 4.046 -0.324 4.175 c
+-0.452 4.299 -0.646 4.366 -0.912 4.366 c
+-1.157 4.366 -1.359 4.293 -1.514 4.145 c
+-1.66 3.998 -1.735 3.811 -1.735 3.587 c
+-2.558 3.587 l
+-2.558 3.84 -2.484 4.087 -2.337 4.322 c
+-2.182 4.557 -1.977 4.737 -1.72 4.866 c
+-1.466 4.991 -1.183 5.056 -0.867 5.056 c
+-0.36 5.056 0.029 4.928 0.294 4.675 c
+0.559 4.428 0.691 4.06 0.691 3.572 c
+0.691 1.073 l
+0.698 0.69 0.754 0.357 0.852 0.073 c
+0.852 0 l
+h
+-1.072 0.647 m
+-0.878 0.647 -0.69 0.698 -0.515 0.808 c
+-0.33 0.926 -0.199 1.062 -0.118 1.22 c
+-0.118 2.411 l
+-0.573 2.411 l
+-0.955 2.4 -1.261 2.311 -1.484 2.146 c
+-1.712 1.977 -1.822 1.749 -1.822 1.455 c
+-1.822 1.168 -1.771 0.962 -1.66 0.838 c
+-1.543 0.709 -1.348 0.647 -1.072 0.647 c
+2.837 6.174 m
+2.837 4.968 l
+3.587 4.968 l
+3.587 4.307 l
+2.837 4.307 l
+2.837 1.235 l
+2.837 1.037 2.866 0.885 2.926 0.779 c
+2.992 0.68 3.105 0.632 3.263 0.632 c
+3.37 0.632 3.476 0.65 3.587 0.69 c
+3.572 0 l
+3.396 -0.058 3.208 -0.088 3.013 -0.088 c
+2.691 -0.088 2.444 0.022 2.278 0.25 c
+2.109 0.485 2.028 0.808 2.028 1.22 c
+2.028 4.307 l
+1.264 4.307 l
+1.264 4.968 l
+2.028 4.968 l
+2.028 6.174 l
+h
+f
+Q
+0.793 0.801 0.129 0.016 k
+q 1 0 0 1 545.9825 296.5664 cm
+0 0 m
+0.301 0.401 0.694 0.603 1.176 0.603 c
+2.057 0.603 2.502 0.019 2.513 -1.146 c
+2.513 -4.453 l
+1.705 -4.453 l
+1.705 -1.19 l
+1.705 -0.801 1.639 -0.525 1.514 -0.367 c
+1.385 -0.201 1.19 -0.118 0.926 -0.118 c
+0.72 -0.118 0.536 -0.187 0.382 -0.323 c
+0.224 -0.452 0.095 -0.625 0 -0.837 c
+0 -4.453 l
+-0.823 -4.453 l
+-0.823 2.602 l
+0 2.602 l
+h
+4.608 1.721 m
+4.608 0.515 l
+5.357 0.515 l
+5.357 -0.147 l
+4.608 -0.147 l
+4.608 -3.218 l
+4.608 -3.417 4.637 -3.568 4.696 -3.674 c
+4.762 -3.773 4.876 -3.821 5.034 -3.821 c
+5.14 -3.821 5.247 -3.803 5.357 -3.763 c
+5.342 -4.453 l
+5.167 -4.512 4.979 -4.542 4.785 -4.542 c
+4.461 -4.542 4.214 -4.432 4.049 -4.203 c
+3.881 -3.968 3.8 -3.645 3.8 -3.233 c
+3.8 -0.147 l
+3.035 -0.147 l
+3.035 0.515 l
+3.8 0.515 l
+3.8 1.721 l
+h
+7.272 1.721 m
+7.272 0.515 l
+8.022 0.515 l
+8.022 -0.147 l
+7.272 -0.147 l
+7.272 -3.218 l
+7.272 -3.417 7.301 -3.568 7.36 -3.674 c
+7.426 -3.773 7.54 -3.821 7.698 -3.821 c
+7.804 -3.821 7.912 -3.803 8.022 -3.763 c
+8.007 -4.453 l
+7.831 -4.512 7.643 -4.542 7.449 -4.542 c
+7.125 -4.542 6.879 -4.432 6.713 -4.203 c
+6.545 -3.968 6.464 -3.645 6.464 -3.233 c
+6.464 -0.147 l
+5.699 -0.147 l
+5.699 0.515 l
+6.464 0.515 l
+6.464 1.721 l
+h
+12.461 -2.204 m
+12.461 -2.991 12.317 -3.579 12.035 -3.968 c
+11.748 -4.351 11.347 -4.542 10.829 -4.542 c
+10.329 -4.542 9.947 -4.357 9.683 -3.983 c
+9.683 -6.364 l
+8.874 -6.364 l
+8.874 0.515 l
+9.609 0.515 l
+9.639 -0.029 l
+9.911 0.389 10.304 0.603 10.815 0.603 c
+11.362 0.603 11.77 0.412 12.035 0.03 c
+12.307 -0.345 12.45 -0.907 12.461 -1.66 c
+h
+11.652 -1.749 m
+11.652 -1.19 11.564 -0.779 11.388 -0.514 c
+11.218 -0.249 10.946 -0.118 10.564 -0.118 c
+10.171 -0.118 9.878 -0.309 9.683 -0.69 c
+9.683 -3.277 l
+9.878 -3.659 10.175 -3.85 10.58 -3.85 c
+10.94 -3.85 11.204 -3.719 11.373 -3.453 c
+11.549 -3.189 11.642 -2.786 11.652 -2.234 c
+h
+15.75 -3.175 m
+15.75 -3.009 15.68 -2.863 15.544 -2.734 c
+15.415 -2.609 15.162 -2.462 14.78 -2.293 c
+14.346 -2.109 14.037 -1.951 13.853 -1.822 c
+13.677 -1.697 13.545 -1.554 13.456 -1.396 c
+13.369 -1.23 13.325 -1.036 13.325 -0.808 c
+13.325 -0.396 13.471 -0.058 13.765 0.206 c
+14.059 0.47 14.434 0.603 14.898 0.603 c
+15.386 0.603 15.779 0.46 16.073 0.177 c
+16.367 -0.099 16.514 -0.455 16.514 -0.897 c
+15.706 -0.897 l
+15.706 -0.672 15.625 -0.481 15.47 -0.323 c
+15.324 -0.168 15.133 -0.087 14.898 -0.087 c
+14.662 -0.087 14.474 -0.154 14.339 -0.278 c
+14.198 -0.396 14.133 -0.565 14.133 -0.779 c
+14.133 -0.947 14.181 -1.08 14.279 -1.176 c
+14.375 -1.275 14.618 -1.407 15 -1.572 c
+15.606 -1.807 16.018 -2.04 16.234 -2.263 c
+16.448 -2.491 16.558 -2.774 16.558 -3.116 c
+16.558 -3.549 16.404 -3.895 16.103 -4.159 c
+15.808 -4.417 15.411 -4.542 14.912 -4.542 c
+14.401 -4.542 13.986 -4.394 13.662 -4.101 c
+13.339 -3.806 13.177 -3.432 13.177 -2.969 c
+14 -2.969 l
+14.008 -3.245 14.092 -3.461 14.25 -3.615 c
+14.405 -3.773 14.625 -3.85 14.912 -3.85 c
+15.183 -3.85 15.39 -3.792 15.529 -3.674 c
+15.676 -3.549 15.75 -3.38 15.75 -3.175 c
+17.491 -4.012 m
+17.491 -3.865 17.535 -3.744 17.624 -3.645 c
+17.712 -3.549 17.837 -3.498 18.006 -3.498 c
+18.183 -3.498 18.314 -3.549 18.403 -3.645 c
+18.499 -3.744 18.549 -3.865 18.549 -4.012 c
+18.549 -4.152 18.499 -4.27 18.403 -4.365 c
+18.314 -4.453 18.183 -4.498 18.006 -4.498 c
+17.837 -4.498 17.712 -4.453 17.624 -4.365 c
+17.535 -4.27 17.491 -4.152 17.491 -4.012 c
+17.491 -0.249 m
+17.491 -0.103 17.535 0.019 17.624 0.118 c
+17.712 0.214 17.837 0.265 18.006 0.265 c
+18.183 0.265 18.314 0.214 18.403 0.118 c
+18.499 0.019 18.549 -0.103 18.549 -0.249 c
+18.549 -0.389 18.499 -0.507 18.403 -0.602 c
+18.314 -0.69 18.183 -0.735 18.006 -0.735 c
+17.837 -0.735 17.712 -0.69 17.624 -0.602 c
+17.535 -0.507 17.491 -0.389 17.491 -0.249 c
+19.785 -5.026 m
+19.093 -5.026 l
+21.431 2.234 l
+22.121 2.234 l
+h
+22.148 -5.026 m
+21.456 -5.026 l
+23.794 2.234 l
+24.485 2.234 l
+h
+25.102 -1.749 m
+25.102 -0.977 25.242 -0.393 25.528 0 c
+25.811 0.401 26.223 0.603 26.763 0.603 c
+27.27 0.603 27.66 0.387 27.924 -0.043 c
+27.953 0.515 l
+28.689 0.515 l
+28.689 -4.498 l
+28.689 -5.115 28.531 -5.585 28.218 -5.909 c
+27.902 -6.239 27.469 -6.408 26.91 -6.408 c
+26.663 -6.408 26.384 -6.342 26.072 -6.217 c
+25.767 -6.1 25.543 -5.953 25.396 -5.776 c
+25.719 -5.217 l
+26.061 -5.548 26.432 -5.718 26.836 -5.718 c
+27.513 -5.718 27.858 -5.35 27.88 -4.615 c
+27.88 -3.968 l
+27.615 -4.351 27.241 -4.542 26.763 -4.542 c
+26.241 -4.542 25.84 -4.351 25.558 -3.968 c
+25.271 -3.579 25.121 -3.021 25.102 -2.293 c
+h
+25.925 -2.204 m
+25.925 -2.763 26.002 -3.175 26.16 -3.439 c
+26.326 -3.696 26.594 -3.821 26.969 -3.821 c
+27.369 -3.821 27.675 -3.615 27.88 -3.204 c
+27.88 -0.72 l
+27.675 -0.319 27.373 -0.118 26.983 -0.118 c
+26.609 -0.118 26.341 -0.249 26.175 -0.514 c
+26.006 -0.771 25.925 -1.168 25.925 -1.705 c
+h
+30.592 -4.453 -0.808 4.968 re
+30.651 1.838 m
+30.651 1.698 30.611 1.58 30.534 1.485 c
+30.463 1.397 30.349 1.353 30.195 1.353 c
+30.037 1.353 29.919 1.397 29.842 1.485 c
+29.772 1.58 29.74 1.698 29.74 1.838 c
+29.74 1.974 29.772 2.088 29.842 2.176 c
+29.919 2.271 30.033 2.323 30.181 2.323 c
+30.335 2.323 30.453 2.271 30.534 2.176 c
+30.611 2.088 30.651 1.974 30.651 1.838 c
+32.849 1.721 m
+32.849 0.515 l
+33.598 0.515 l
+33.598 -0.147 l
+32.849 -0.147 l
+32.849 -3.218 l
+32.849 -3.417 32.878 -3.568 32.936 -3.674 c
+33.003 -3.773 33.117 -3.821 33.275 -3.821 c
+33.381 -3.821 33.487 -3.803 33.598 -3.763 c
+33.583 -4.453 l
+33.407 -4.512 33.219 -4.542 33.025 -4.542 c
+32.701 -4.542 32.456 -4.432 32.29 -4.203 c
+32.121 -3.968 32.04 -3.645 32.04 -3.233 c
+32.04 -0.147 l
+31.276 -0.147 l
+31.276 0.515 l
+32.04 0.515 l
+32.04 1.721 l
+h
+35.949 -1.955 -1.896 0.691 re
+39.103 -3.175 m
+39.103 -3.009 39.033 -2.863 38.897 -2.734 c
+38.769 -2.609 38.515 -2.462 38.133 -2.293 c
+37.699 -2.109 37.391 -1.951 37.206 -1.822 c
+37.03 -1.697 36.898 -1.554 36.81 -1.396 c
+36.722 -1.23 36.677 -1.036 36.677 -0.808 c
+36.677 -0.396 36.824 -0.058 37.119 0.206 c
+37.412 0.47 37.788 0.603 38.25 0.603 c
+38.739 0.603 39.132 0.46 39.426 0.177 c
+39.72 -0.099 39.868 -0.455 39.868 -0.897 c
+39.059 -0.897 l
+39.059 -0.672 38.978 -0.481 38.823 -0.323 c
+38.677 -0.168 38.486 -0.087 38.25 -0.087 c
+38.015 -0.087 37.828 -0.154 37.692 -0.278 c
+37.552 -0.396 37.486 -0.565 37.486 -0.779 c
+37.486 -0.947 37.534 -1.08 37.632 -1.176 c
+37.728 -1.275 37.971 -1.407 38.353 -1.572 c
+38.96 -1.807 39.371 -2.04 39.588 -2.263 c
+39.801 -2.491 39.911 -2.774 39.911 -3.116 c
+39.911 -3.549 39.757 -3.895 39.456 -4.159 c
+39.162 -4.417 38.765 -4.542 38.265 -4.542 c
+37.754 -4.542 37.339 -4.394 37.015 -4.101 c
+36.692 -3.806 36.531 -3.432 36.531 -2.969 c
+37.354 -2.969 l
+37.36 -3.245 37.445 -3.461 37.603 -3.615 c
+37.758 -3.773 37.979 -3.85 38.265 -3.85 c
+38.536 -3.85 38.742 -3.792 38.883 -3.674 c
+39.029 -3.549 39.103 -3.38 39.103 -3.175 c
+42.52 -3.85 m
+42.785 -3.85 42.995 -3.77 43.153 -3.601 c
+43.317 -3.436 43.409 -3.197 43.432 -2.881 c
+44.196 -2.881 l
+44.174 -3.362 44.005 -3.759 43.681 -4.072 c
+43.365 -4.388 42.979 -4.542 42.52 -4.542 c
+41.903 -4.542 41.433 -4.351 41.109 -3.968 c
+40.786 -3.579 40.624 -2.998 40.624 -2.234 c
+40.624 -1.69 l
+40.624 -0.937 40.786 -0.367 41.109 0.015 c
+41.433 0.405 41.896 0.603 42.505 0.603 c
+43.012 0.603 43.417 0.441 43.71 0.118 c
+44.012 -0.198 44.174 -0.631 44.196 -1.19 c
+43.432 -1.19 l
+43.409 -0.83 43.321 -0.554 43.167 -0.367 c
+43.009 -0.183 42.789 -0.087 42.505 -0.087 c
+42.153 -0.087 41.888 -0.213 41.711 -0.455 c
+41.535 -0.69 41.44 -1.08 41.433 -1.616 c
+41.433 -2.248 l
+41.433 -2.836 41.52 -3.256 41.697 -3.498 c
+41.873 -3.733 42.145 -3.85 42.52 -3.85 c
+45.732 0.515 m
+45.761 0.059 l
+46.062 0.42 46.459 0.603 46.952 0.603 c
+47.51 0.603 47.897 0.36 48.113 -0.118 c
+48.425 0.36 48.863 0.603 49.422 0.603 c
+50.34 0.603 50.81 0.034 50.833 -1.102 c
+50.833 -4.453 l
+50.024 -4.453 l
+50.024 -1.176 l
+50.024 -0.823 49.954 -0.558 49.819 -0.382 c
+49.69 -0.205 49.473 -0.118 49.171 -0.118 c
+48.925 -0.118 48.724 -0.213 48.569 -0.396 c
+48.422 -0.584 48.334 -0.823 48.304 -1.117 c
+48.304 -4.453 l
+47.496 -4.453 l
+47.496 -1.146 l
+47.485 -0.463 47.205 -0.118 46.658 -0.118 c
+46.247 -0.118 45.956 -0.323 45.79 -0.735 c
+45.79 -4.453 l
+44.982 -4.453 l
+44.982 0.515 l
+h
+51.818 -4.012 m
+51.818 -3.865 51.862 -3.744 51.949 -3.645 c
+52.038 -3.549 52.163 -3.498 52.332 -3.498 c
+52.508 -3.498 52.641 -3.549 52.728 -3.645 c
+52.824 -3.744 52.876 -3.865 52.876 -4.012 c
+52.876 -4.152 52.824 -4.27 52.728 -4.365 c
+52.641 -4.453 52.508 -4.498 52.332 -4.498 c
+52.163 -4.498 52.038 -4.453 51.949 -4.365 c
+51.862 -4.27 51.818 -4.152 51.818 -4.012 c
+55.874 -3.85 m
+56.139 -3.85 56.348 -3.77 56.506 -3.601 c
+56.672 -3.436 56.763 -3.197 56.786 -2.881 c
+57.55 -2.881 l
+57.528 -3.362 57.359 -3.759 57.036 -4.072 c
+56.72 -4.388 56.333 -4.542 55.874 -4.542 c
+55.257 -4.542 54.787 -4.351 54.463 -3.968 c
+54.14 -3.579 53.979 -2.998 53.979 -2.234 c
+53.979 -1.69 l
+53.979 -0.937 54.14 -0.367 54.463 0.015 c
+54.787 0.405 55.25 0.603 55.86 0.603 c
+56.367 0.603 56.771 0.441 57.065 0.118 c
+57.366 -0.198 57.528 -0.631 57.55 -1.19 c
+56.786 -1.19 l
+56.763 -0.83 56.676 -0.554 56.521 -0.367 c
+56.363 -0.183 56.142 -0.087 55.86 -0.087 c
+55.506 -0.087 55.242 -0.213 55.066 -0.455 c
+54.889 -0.69 54.794 -1.08 54.787 -1.616 c
+54.787 -2.248 l
+54.787 -2.836 54.875 -3.256 55.051 -3.498 c
+55.228 -3.733 55.5 -3.85 55.874 -3.85 c
+58.16 -1.734 m
+58.16 -1.022 58.329 -0.452 58.675 -0.029 c
+59.028 0.389 59.49 0.603 60.071 0.603 c
+60.648 0.603 61.108 0.397 61.453 -0.014 c
+61.806 -0.419 61.985 -0.977 61.997 -1.69 c
+61.997 -2.204 l
+61.997 -2.932 61.82 -3.505 61.467 -3.924 c
+61.122 -4.336 60.663 -4.542 60.086 -4.542 c
+59.505 -4.542 59.042 -4.343 58.689 -3.939 c
+58.344 -3.528 58.168 -2.977 58.16 -2.278 c
+h
+58.968 -2.204 m
+58.968 -2.715 59.064 -3.116 59.263 -3.41 c
+59.468 -3.704 59.74 -3.85 60.086 -3.85 c
+60.799 -3.85 61.166 -3.333 61.188 -2.293 c
+61.188 -1.734 l
+61.188 -1.227 61.085 -0.823 60.879 -0.529 c
+60.68 -0.235 60.412 -0.087 60.071 -0.087 c
+59.737 -0.087 59.468 -0.235 59.263 -0.529 c
+59.064 -0.823 58.968 -1.227 58.968 -1.734 c
+h
+63.617 0.515 m
+63.647 0.059 l
+63.948 0.42 64.345 0.603 64.837 0.603 c
+65.395 0.603 65.781 0.36 65.998 -0.118 c
+66.311 0.36 66.748 0.603 67.306 0.603 c
+68.225 0.603 68.696 0.034 68.717 -1.102 c
+68.717 -4.453 l
+67.909 -4.453 l
+67.909 -1.176 l
+67.909 -0.823 67.839 -0.558 67.703 -0.382 c
+67.575 -0.205 67.358 -0.118 67.057 -0.118 c
+66.81 -0.118 66.608 -0.213 66.454 -0.396 c
+66.307 -0.584 66.219 -0.823 66.189 -1.117 c
+66.189 -4.453 l
+65.381 -4.453 l
+65.381 -1.146 l
+65.37 -0.463 65.091 -0.118 64.543 -0.118 c
+64.131 -0.118 63.841 -0.323 63.676 -0.735 c
+63.676 -4.453 l
+62.868 -4.453 l
+62.868 0.515 l
+h
+69.879 -5.026 m
+69.188 -5.026 l
+71.525 2.234 l
+72.216 2.234 l
+h
+76.596 -2.204 m
+76.596 -2.98 76.453 -3.564 76.17 -3.954 c
+75.894 -4.347 75.494 -4.542 74.965 -4.542 c
+74.443 -4.542 74.053 -4.317 73.789 -3.865 c
+73.745 -4.453 l
+73.01 -4.453 l
+73.01 2.602 l
+73.818 2.602 l
+73.818 -0.029 l
+74.083 0.389 74.465 0.603 74.965 0.603 c
+75.501 0.603 75.909 0.412 76.185 0.03 c
+76.457 -0.353 76.596 -0.937 76.596 -1.72 c
+h
+75.788 -1.749 m
+75.788 -1.161 75.703 -0.746 75.538 -0.5 c
+75.38 -0.246 75.115 -0.118 74.745 -0.118 c
+74.332 -0.118 74.024 -0.345 73.818 -0.793 c
+73.818 -3.16 l
+74.013 -3.601 74.325 -3.821 74.759 -3.821 c
+75.119 -3.821 75.38 -3.696 75.538 -3.439 c
+75.703 -3.185 75.788 -2.788 75.788 -2.248 c
+h
+77.299 -1.734 m
+77.299 -1.022 77.467 -0.452 77.812 -0.029 c
+78.165 0.389 78.629 0.603 79.209 0.603 c
+79.786 0.603 80.245 0.397 80.591 -0.014 c
+80.944 -0.419 81.124 -0.977 81.135 -1.69 c
+81.135 -2.204 l
+81.135 -2.932 80.958 -3.505 80.605 -3.924 c
+80.26 -4.336 79.801 -4.542 79.223 -4.542 c
+78.643 -4.542 78.18 -4.343 77.827 -3.939 c
+77.482 -3.528 77.305 -2.977 77.299 -2.278 c
+h
+78.107 -2.204 m
+78.107 -2.715 78.203 -3.116 78.4 -3.41 c
+78.606 -3.704 78.878 -3.85 79.223 -3.85 c
+79.936 -3.85 80.304 -3.333 80.326 -2.293 c
+80.326 -1.734 l
+80.326 -1.227 80.223 -0.823 80.017 -0.529 c
+79.819 -0.235 79.551 -0.087 79.209 -0.087 c
+78.874 -0.087 78.606 -0.235 78.4 -0.529 c
+78.203 -0.823 78.107 -1.227 78.107 -1.734 c
+h
+81.829 -1.734 m
+81.829 -1.022 81.999 -0.452 82.344 -0.029 c
+82.697 0.389 83.159 0.603 83.74 0.603 c
+84.317 0.603 84.777 0.397 85.122 -0.014 c
+85.475 -0.419 85.654 -0.977 85.666 -1.69 c
+85.666 -2.204 l
+85.666 -2.932 85.49 -3.505 85.137 -3.924 c
+84.791 -4.336 84.332 -4.542 83.755 -4.542 c
+83.174 -4.542 82.711 -4.343 82.358 -3.939 c
+82.013 -3.528 81.837 -2.977 81.829 -2.278 c
+h
+82.637 -2.204 m
+82.637 -2.715 82.733 -3.116 82.932 -3.41 c
+83.138 -3.704 83.41 -3.85 83.755 -3.85 c
+84.468 -3.85 84.835 -3.333 84.857 -2.293 c
+84.857 -1.734 l
+84.857 -1.227 84.754 -0.823 84.549 -0.529 c
+84.35 -0.235 84.082 -0.087 83.74 -0.087 c
+83.406 -0.087 83.138 -0.235 82.932 -0.529 c
+82.733 -0.823 82.637 -1.227 82.637 -1.734 c
+h
+87.775 -2.175 m
+87.349 -2.674 l
+87.349 -4.453 l
+86.54 -4.453 l
+86.54 2.602 l
+87.349 2.602 l
+87.349 -1.616 l
+88.892 0.515 l
+89.862 0.515 l
+88.289 -1.558 l
+90.082 -4.453 l
+89.128 -4.453 l
+h
+f
+Q
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 636.6425 292.5541 cm
+0 0 m
+0 0.147 0.044 0.268 0.132 0.367 c
+0.22 0.463 0.345 0.515 0.515 0.515 c
+0.691 0.515 0.823 0.463 0.911 0.367 c
+1.007 0.268 1.058 0.147 1.058 0 c
+1.058 -0.14 1.007 -0.258 0.911 -0.353 c
+0.823 -0.441 0.691 -0.485 0.515 -0.485 c
+0.345 -0.485 0.22 -0.441 0.132 -0.353 c
+0.044 -0.258 0 -0.14 0 0 c
+f
+Q
+0.113 0.082 0.09 0 k
+535.667 375.475 238.665 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 540.8555 368.6364 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.088 -0.5 c
+-0.147 -0.647 -0.242 -0.775 -0.367 -0.882 c
+-0.496 -0.992 -0.658 -1.081 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.243 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.358 -1.22 -2.543 -1.162 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.927 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.132 l
+-2.642 0.033 -2.616 -0.059 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.302 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.683 -1.992 0.691 -1.999 0.691 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.881 -2.786 0.959 -2.91 1.058 c
+-3.039 1.153 -3.141 1.278 -3.218 1.425 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.218 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.836 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.042 c
+-0.804 2.991 -0.669 2.917 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.201 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.252 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.352 c
+-1.294 1.311 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.319 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.318 2.385 -2.366 2.337 c
+-2.406 2.296 -2.436 2.248 -2.454 2.19 c
+-2.476 2.131 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.778 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.2 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.469 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.091 -0.86 0.176 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.102 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.529 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.53 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+7.975 -0.25 m
+7.975 -0.42 7.934 -0.57 7.857 -0.706 c
+7.787 -0.834 7.684 -0.948 7.548 -1.044 c
+7.42 -1.132 7.258 -1.202 7.063 -1.249 c
+6.876 -1.297 6.659 -1.323 6.417 -1.323 c
+6.189 -1.323 5.991 -1.309 5.814 -1.279 c
+5.638 -1.249 5.48 -1.202 5.343 -1.132 c
+5.204 -1.055 5.093 -0.956 5.006 -0.838 c
+4.917 -0.721 4.848 -0.574 4.8 -0.397 c
+5.608 -0.279 l
+5.627 -0.379 5.656 -0.456 5.696 -0.515 c
+5.744 -0.574 5.802 -0.617 5.873 -0.647 c
+5.939 -0.676 6.02 -0.702 6.108 -0.721 c
+6.196 -0.732 6.299 -0.735 6.417 -0.735 c
+6.512 -0.735 6.608 -0.732 6.696 -0.721 c
+6.784 -0.702 6.861 -0.676 6.931 -0.647 c
+6.997 -0.617 7.049 -0.58 7.078 -0.53 c
+7.115 -0.482 7.136 -0.42 7.136 -0.339 c
+7.136 -0.243 7.107 -0.169 7.049 -0.118 c
+6.997 -0.07 6.931 -0.029 6.843 0 c
+6.755 0.037 6.644 0.066 6.519 0.088 c
+6.402 0.118 6.269 0.147 6.122 0.176 c
+5.983 0.213 5.843 0.253 5.696 0.293 c
+5.557 0.341 5.432 0.404 5.314 0.484 c
+5.204 0.562 5.116 0.661 5.05 0.779 c
+4.979 0.897 4.946 1.047 4.946 1.234 c
+4.946 1.389 4.976 1.532 5.035 1.66 c
+5.101 1.797 5.197 1.911 5.314 1.999 c
+5.439 2.087 5.597 2.153 5.785 2.205 c
+5.968 2.252 6.182 2.278 6.417 2.278 c
+6.6 2.278 6.776 2.256 6.945 2.219 c
+7.111 2.19 7.258 2.135 7.387 2.057 c
+7.512 1.988 7.622 1.889 7.71 1.764 c
+7.798 1.646 7.857 1.502 7.886 1.338 c
+7.092 1.264 l
+7.071 1.341 7.041 1.404 7.005 1.455 c
+6.964 1.514 6.916 1.558 6.857 1.587 c
+6.806 1.624 6.743 1.65 6.666 1.66 c
+6.585 1.668 6.504 1.675 6.417 1.675 c
+6.199 1.675 6.038 1.646 5.931 1.587 c
+5.821 1.536 5.77 1.448 5.77 1.323 c
+5.77 1.242 5.788 1.18 5.829 1.132 c
+5.876 1.08 5.939 1.043 6.02 1.014 c
+6.108 0.985 6.203 0.955 6.313 0.926 c
+6.421 0.904 6.541 0.881 6.681 0.852 c
+6.835 0.823 6.993 0.783 7.151 0.735 c
+7.306 0.683 7.445 0.621 7.563 0.544 c
+7.68 0.463 7.776 0.36 7.857 0.235 c
+7.934 0.106 7.975 -0.055 7.975 -0.25 c
+9.816 2.219 m
+9.816 0.264 l
+9.816 0.125 9.823 0 9.845 -0.118 c
+9.864 -0.228 9.897 -0.32 9.948 -0.397 c
+9.995 -0.478 10.055 -0.54 10.124 -0.588 c
+10.19 -0.628 10.275 -0.647 10.375 -0.647 c
+10.462 -0.647 10.543 -0.628 10.624 -0.588 c
+10.712 -0.54 10.786 -0.47 10.845 -0.382 c
+10.903 -0.287 10.947 -0.177 10.977 -0.059 c
+11.013 0.066 11.036 0.206 11.036 0.353 c
+11.036 2.219 l
+11.932 2.219 l
+11.932 -0.485 l
+11.932 -0.721 l
+11.94 -0.802 11.947 -0.879 11.947 -0.956 c
+11.947 -1.147 l
+11.954 -1.199 11.961 -1.235 11.961 -1.264 c
+11.109 -1.264 l
+11.098 -1.235 11.088 -1.199 11.08 -1.147 c
+11.08 -0.956 l
+11.08 -0.89 11.073 -0.819 11.065 -0.75 c
+11.065 -0.574 l
+11.05 -0.574 l
+10.932 -0.838 10.778 -1.029 10.595 -1.147 c
+10.419 -1.264 10.216 -1.323 9.992 -1.323 c
+9.787 -1.323 9.613 -1.286 9.478 -1.22 c
+9.338 -1.154 9.228 -1.058 9.139 -0.941 c
+9.058 -0.823 9 -0.688 8.963 -0.53 c
+8.933 -0.364 8.919 -0.187 8.919 0 c
+8.919 2.219 l
+h
+15.173 -1.264 m
+15.163 -1.246 15.152 -1.216 15.144 -1.176 c
+15.144 -1.128 15.136 -1.081 15.129 -1.029 c
+15.129 -0.97 15.122 -0.912 15.115 -0.852 c
+15.115 -0.691 l
+14.997 -0.927 14.853 -1.095 14.689 -1.191 c
+14.519 -1.279 14.321 -1.323 14.086 -1.323 c
+13.887 -1.323 13.711 -1.279 13.557 -1.191 c
+13.399 -1.103 13.266 -0.981 13.16 -0.823 c
+13.06 -0.658 12.983 -0.467 12.925 -0.25 c
+12.873 -0.037 12.851 0.206 12.851 0.47 c
+12.851 0.735 12.873 0.974 12.925 1.19 c
+12.983 1.415 13.06 1.606 13.16 1.764 c
+13.266 1.918 13.399 2.043 13.557 2.131 c
+13.722 2.227 13.913 2.278 14.13 2.278 c
+14.225 2.278 14.321 2.263 14.409 2.234 c
+14.504 2.212 14.6 2.179 14.689 2.131 c
+14.776 2.08 14.853 2.017 14.924 1.94 c
+15.001 1.859 15.063 1.768 15.115 1.66 c
+15.115 1.749 l
+15.115 1.896 l
+15.115 2.057 l
+15.115 2.234 l
+15.115 3.513 l
+16.011 3.513 l
+16.011 -0.5 l
+16.011 -0.676 16.015 -0.834 16.026 -0.97 c
+16.033 -1.099 16.041 -1.199 16.041 -1.264 c
+h
+15.129 0.484 m
+15.129 0.72 15.104 0.912 15.056 1.058 c
+15.015 1.213 14.961 1.338 14.894 1.425 c
+14.836 1.514 14.766 1.573 14.689 1.602 c
+14.608 1.639 14.531 1.66 14.454 1.66 c
+14.354 1.66 14.263 1.635 14.174 1.587 c
+14.093 1.547 14.027 1.477 13.968 1.382 c
+13.916 1.282 13.872 1.161 13.835 1.014 c
+13.806 0.867 13.792 0.683 13.792 0.47 c
+13.792 0.077 13.843 -0.217 13.953 -0.412 c
+14.071 -0.611 14.232 -0.706 14.438 -0.706 c
+14.516 -0.706 14.593 -0.688 14.674 -0.647 c
+14.751 -0.611 14.824 -0.544 14.894 -0.456 c
+14.961 -0.368 15.015 -0.246 15.056 -0.088 c
+15.104 0.066 15.129 0.257 15.129 0.484 c
+20.263 0.484 m
+20.263 0.209 20.226 -0.04 20.16 -0.264 c
+20.09 -0.482 19.987 -0.669 19.852 -0.823 c
+19.711 -0.981 19.535 -1.103 19.322 -1.191 c
+19.106 -1.279 18.852 -1.323 18.558 -1.323 c
+18.282 -1.323 18.036 -1.279 17.823 -1.191 c
+17.617 -1.103 17.444 -0.981 17.309 -0.823 c
+17.169 -0.669 17.066 -0.482 17 -0.264 c
+16.93 -0.04 16.897 0.209 16.897 0.484 c
+16.897 0.738 16.927 0.974 16.985 1.19 c
+17.051 1.415 17.154 1.606 17.294 1.764 c
+17.43 1.929 17.606 2.057 17.823 2.146 c
+18.036 2.234 18.294 2.278 18.587 2.278 c
+18.899 2.278 19.161 2.234 19.366 2.146 c
+19.58 2.057 19.752 1.929 19.881 1.764 c
+20.017 1.606 20.116 1.415 20.175 1.19 c
+20.233 0.974 20.263 0.738 20.263 0.484 c
+19.308 0.484 m
+19.308 0.691 19.293 0.867 19.263 1.014 c
+19.241 1.161 19.204 1.282 19.146 1.382 c
+19.087 1.477 19.013 1.547 18.926 1.587 c
+18.837 1.635 18.727 1.66 18.602 1.66 c
+18.338 1.66 18.146 1.562 18.028 1.367 c
+17.911 1.18 17.852 0.885 17.852 0.484 c
+17.852 0.062 17.911 -0.243 18.028 -0.426 c
+18.146 -0.614 18.323 -0.706 18.558 -0.706 c
+18.683 -0.706 18.797 -0.688 18.896 -0.647 c
+18.992 -0.599 19.073 -0.526 19.131 -0.426 c
+19.198 -0.331 19.241 -0.206 19.263 -0.059 c
+19.293 0.088 19.308 0.268 19.308 0.484 c
+26.136 -1.323 m
+25.966 -1.323 25.816 -1.301 25.679 -1.264 c
+25.551 -1.216 25.437 -1.147 25.342 -1.058 c
+25.253 -0.97 25.184 -0.864 25.136 -0.735 c
+25.084 -0.599 25.062 -0.449 25.062 -0.279 c
+25.062 -0.073 25.095 0.095 25.165 0.235 c
+25.232 0.382 25.327 0.492 25.444 0.573 c
+25.569 0.661 25.712 0.723 25.87 0.764 c
+26.036 0.801 26.213 0.827 26.4 0.837 c
+27.121 0.852 l
+27.121 1.029 l
+27.121 1.147 27.109 1.249 27.09 1.338 c
+27.069 1.425 27.036 1.492 26.988 1.543 c
+26.948 1.602 26.899 1.639 26.841 1.66 c
+26.782 1.679 26.716 1.69 26.65 1.69 c
+26.58 1.69 26.518 1.679 26.458 1.66 c
+26.407 1.65 26.36 1.624 26.312 1.587 c
+26.271 1.558 26.238 1.506 26.209 1.44 c
+26.186 1.382 26.172 1.301 26.165 1.205 c
+25.224 1.249 l
+25.253 1.396 25.297 1.532 25.356 1.66 c
+25.423 1.785 25.518 1.896 25.635 1.984 c
+25.753 2.08 25.893 2.153 26.061 2.205 c
+26.238 2.252 26.444 2.278 26.679 2.278 c
+27.121 2.278 27.451 2.167 27.678 1.955 c
+27.914 1.749 28.031 1.44 28.031 1.029 c
+28.031 -0.235 l
+28.031 -0.456 l
+28.039 -0.515 28.054 -0.57 28.075 -0.617 c
+28.094 -0.658 28.123 -0.691 28.164 -0.721 c
+28.201 -0.742 28.252 -0.75 28.311 -0.75 c
+28.376 -0.75 28.447 -0.746 28.517 -0.735 c
+28.517 -1.22 l
+28.457 -1.231 28.403 -1.243 28.355 -1.249 c
+28.314 -1.261 28.274 -1.268 28.237 -1.279 c
+28.197 -1.286 28.153 -1.294 28.105 -1.294 c
+28.054 -1.301 27.995 -1.309 27.929 -1.309 c
+27.701 -1.309 27.535 -1.257 27.429 -1.147 c
+27.318 -1.029 27.256 -0.864 27.237 -0.647 c
+27.223 -0.647 l
+27.154 -0.757 27.083 -0.852 27.017 -0.941 c
+26.948 -1.022 26.87 -1.087 26.782 -1.147 c
+26.693 -1.205 26.595 -1.249 26.488 -1.279 c
+26.389 -1.309 26.271 -1.323 26.136 -1.323 c
+27.121 0.353 m
+26.693 0.338 l
+26.595 0.338 26.503 0.33 26.415 0.324 c
+26.334 0.312 26.267 0.286 26.209 0.249 c
+26.15 0.209 26.099 0.151 26.061 0.073 c
+26.022 0.004 26.003 -0.088 26.003 -0.206 c
+26.003 -0.375 26.036 -0.497 26.106 -0.574 c
+26.172 -0.655 26.271 -0.691 26.4 -0.691 c
+26.506 -0.691 26.606 -0.669 26.693 -0.617 c
+26.789 -0.57 26.87 -0.507 26.929 -0.426 c
+26.995 -0.349 27.046 -0.262 27.076 -0.162 c
+27.106 -0.055 27.121 0.058 27.121 0.176 c
+h
+30.107 2.219 m
+30.115 2.198 30.122 2.165 30.122 2.117 c
+30.13 2.076 30.138 2.028 30.138 1.97 c
+30.144 1.918 30.152 1.866 30.152 1.808 c
+30.152 1.646 l
+30.167 1.646 l
+30.225 1.764 30.292 1.859 30.373 1.94 c
+30.45 2.017 30.534 2.08 30.622 2.131 c
+30.71 2.19 30.799 2.227 30.886 2.248 c
+30.982 2.267 31.081 2.278 31.181 2.278 c
+31.387 2.278 31.567 2.234 31.725 2.146 c
+31.879 2.057 32.008 1.929 32.106 1.764 c
+32.214 1.606 32.291 1.415 32.342 1.19 c
+32.401 0.974 32.43 0.738 32.43 0.484 c
+32.43 0.22 32.401 -0.026 32.342 -0.25 c
+32.291 -0.467 32.214 -0.658 32.106 -0.823 c
+32.008 -0.981 31.875 -1.103 31.709 -1.191 c
+31.551 -1.279 31.364 -1.323 31.152 -1.323 c
+31.052 -1.323 30.953 -1.312 30.857 -1.294 c
+30.758 -1.272 30.666 -1.243 30.578 -1.191 c
+30.497 -1.143 30.42 -1.081 30.343 -1 c
+30.273 -0.923 30.215 -0.831 30.167 -0.721 c
+30.152 -0.721 l
+30.152 -0.809 l
+30.159 -0.85 30.167 -0.897 30.167 -0.956 c
+30.167 -1.118 l
+30.167 -1.294 l
+30.167 -2.631 l
+29.255 -2.631 l
+29.255 1.455 l
+29.255 1.62 29.248 1.768 29.24 1.896 c
+29.24 2.219 l
+h
+30.152 0.455 m
+30.152 0.228 30.17 0.037 30.211 -0.118 c
+30.258 -0.264 30.313 -0.382 30.373 -0.47 c
+30.439 -0.559 30.512 -0.625 30.593 -0.661 c
+30.67 -0.702 30.747 -0.721 30.828 -0.721 c
+30.923 -0.721 31.011 -0.698 31.092 -0.647 c
+31.181 -0.599 31.247 -0.53 31.298 -0.441 c
+31.357 -0.345 31.401 -0.221 31.431 -0.073 c
+31.468 0.081 31.489 0.268 31.489 0.484 c
+31.489 0.874 31.431 1.168 31.313 1.367 c
+31.202 1.562 31.048 1.66 30.843 1.66 c
+30.762 1.66 30.685 1.639 30.608 1.602 c
+30.527 1.562 30.453 1.5 30.387 1.411 c
+30.317 1.323 30.258 1.198 30.211 1.043 c
+30.17 0.885 30.152 0.691 30.152 0.455 c
+33.907 1.602 m
+33.363 1.602 l
+33.363 2.219 l
+33.951 2.219 l
+34.231 3.116 l
+34.804 3.116 l
+34.804 2.219 l
+36.039 2.219 l
+36.039 1.602 l
+34.804 1.602 l
+34.804 -0.103 l
+34.804 -0.324 l
+34.811 -0.393 34.834 -0.456 34.863 -0.515 c
+34.9 -0.566 34.955 -0.611 35.025 -0.647 c
+35.102 -0.676 35.216 -0.691 35.362 -0.691 c
+35.499 -0.691 35.634 -0.688 35.774 -0.676 c
+35.91 -0.658 36.043 -0.632 36.171 -0.603 c
+36.171 -1.205 l
+36.091 -1.216 36.013 -1.231 35.936 -1.249 c
+35.855 -1.261 35.778 -1.268 35.701 -1.279 c
+35.62 -1.286 35.532 -1.294 35.436 -1.294 c
+35.348 -1.301 35.249 -1.309 35.142 -1.309 c
+34.955 -1.309 34.793 -1.294 34.657 -1.264 c
+34.528 -1.228 34.414 -1.183 34.319 -1.132 c
+34.231 -1.085 34.157 -1.025 34.098 -0.956 c
+34.04 -0.879 33.995 -0.802 33.966 -0.721 c
+33.937 -0.632 33.915 -0.544 33.907 -0.456 c
+33.897 -0.36 33.893 -0.264 33.893 -0.177 c
+h
+37.953 0.837 1.867 -0.793 re
+37.953 0.044 m
+42.955 -2.66 m
+42.738 -2.66 42.547 -2.635 42.381 -2.587 c
+42.212 -2.547 42.073 -2.484 41.955 -2.396 c
+41.837 -2.315 41.739 -2.22 41.662 -2.103 c
+41.591 -1.985 41.544 -1.856 41.514 -1.72 c
+42.41 -1.617 l
+42.447 -1.754 42.518 -1.86 42.616 -1.941 c
+42.712 -2.028 42.838 -2.072 42.984 -2.072 c
+43.073 -2.072 43.153 -2.058 43.234 -2.028 c
+43.311 -1.999 43.381 -1.945 43.44 -1.867 c
+43.499 -1.797 43.543 -1.706 43.572 -1.588 c
+43.609 -1.47 43.631 -1.323 43.631 -1.147 c
+43.631 -0.956 l
+43.631 -0.89 43.634 -0.831 43.646 -0.779 c
+43.646 -0.588 l
+43.631 -0.588 l
+43.532 -0.816 43.388 -0.977 43.204 -1.073 c
+43.017 -1.172 42.811 -1.22 42.587 -1.22 c
+42.381 -1.22 42.198 -1.183 42.044 -1.103 c
+41.897 -1.014 41.768 -0.897 41.662 -0.75 c
+41.562 -0.595 41.488 -0.412 41.44 -0.206 c
+41.389 0.008 41.367 0.243 41.367 0.5 c
+41.367 0.771 41.389 1.018 41.44 1.234 c
+41.5 1.448 41.581 1.631 41.691 1.778 c
+41.797 1.932 41.93 2.05 42.088 2.131 c
+42.242 2.219 42.429 2.263 42.646 2.263 c
+42.742 2.263 42.84 2.252 42.94 2.234 c
+43.035 2.212 43.123 2.179 43.204 2.131 c
+43.293 2.08 43.37 2.017 43.44 1.94 c
+43.517 1.859 43.58 1.768 43.631 1.66 c
+43.646 1.66 l
+43.646 1.808 l
+43.653 1.866 43.661 1.918 43.661 1.97 c
+43.667 2.028 43.675 2.076 43.675 2.117 c
+43.682 2.165 43.694 2.198 43.704 2.219 c
+44.557 2.219 l
+44.546 2.138 44.535 2.028 44.527 1.881 c
+44.527 1.411 l
+44.527 -1.162 l
+44.527 -1.415 44.49 -1.636 44.424 -1.823 c
+44.355 -2.007 44.251 -2.161 44.116 -2.278 c
+43.976 -2.404 43.811 -2.499 43.616 -2.558 c
+43.418 -2.624 43.197 -2.66 42.955 -2.66 c
+43.646 0.529 m
+43.646 0.742 43.62 0.918 43.572 1.058 c
+43.532 1.205 43.476 1.323 43.41 1.411 c
+43.351 1.5 43.282 1.558 43.204 1.587 c
+43.123 1.624 43.046 1.646 42.969 1.646 c
+42.87 1.646 42.778 1.62 42.69 1.573 c
+42.609 1.532 42.543 1.462 42.485 1.367 c
+42.433 1.278 42.389 1.161 42.352 1.014 c
+42.323 0.874 42.308 0.706 42.308 0.5 c
+42.308 0.125 42.367 -0.154 42.485 -0.339 c
+42.602 -0.515 42.763 -0.603 42.969 -0.603 c
+43.035 -0.603 43.109 -0.588 43.19 -0.559 c
+43.278 -0.522 43.351 -0.463 43.41 -0.382 c
+43.476 -0.294 43.532 -0.177 43.572 -0.029 c
+43.62 0.118 43.646 0.301 43.646 0.529 c
+47.044 -1.323 m
+46.788 -1.323 46.56 -1.286 46.354 -1.22 c
+46.148 -1.143 45.972 -1.029 45.824 -0.882 c
+45.678 -0.728 45.56 -0.537 45.472 -0.309 c
+45.391 -0.085 45.354 0.18 45.354 0.484 c
+45.354 0.816 45.398 1.095 45.487 1.323 c
+45.582 1.558 45.711 1.741 45.869 1.881 c
+46.034 2.017 46.221 2.117 46.427 2.175 c
+46.633 2.242 46.842 2.278 47.06 2.278 c
+47.331 2.278 47.567 2.227 47.765 2.131 c
+47.971 2.043 48.136 1.911 48.265 1.735 c
+48.401 1.565 48.5 1.359 48.559 1.117 c
+48.625 0.881 48.662 0.617 48.662 0.324 c
+48.662 0.309 l
+46.295 0.309 l
+46.295 0.162 46.31 0.022 46.339 -0.103 c
+46.376 -0.231 46.431 -0.345 46.501 -0.441 c
+46.567 -0.53 46.651 -0.599 46.751 -0.647 c
+46.846 -0.698 46.96 -0.721 47.089 -0.721 c
+47.243 -0.721 47.383 -0.688 47.501 -0.617 c
+47.625 -0.551 47.713 -0.449 47.765 -0.309 c
+48.602 -0.382 l
+48.573 -0.482 48.519 -0.588 48.441 -0.706 c
+48.361 -0.816 48.257 -0.919 48.132 -1.014 c
+48.014 -1.103 47.86 -1.176 47.677 -1.235 c
+47.501 -1.294 47.287 -1.323 47.044 -1.323 c
+47.044 1.705 m
+46.956 1.705 46.869 1.69 46.78 1.66 c
+46.692 1.631 46.611 1.579 46.545 1.514 c
+46.475 1.444 46.416 1.356 46.368 1.249 c
+46.328 1.139 46.31 1.014 46.31 0.867 c
+47.779 0.867 l
+47.779 1.003 47.754 1.124 47.706 1.234 c
+47.665 1.341 47.611 1.429 47.544 1.5 c
+47.486 1.565 47.412 1.617 47.324 1.646 c
+47.235 1.683 47.14 1.705 47.044 1.705 c
+50.15 1.602 m
+49.606 1.602 l
+49.606 2.219 l
+50.194 2.219 l
+50.474 3.116 l
+51.046 3.116 l
+51.046 2.219 l
+52.282 2.219 l
+52.282 1.602 l
+51.046 1.602 l
+51.046 -0.103 l
+51.046 -0.324 l
+51.054 -0.393 51.076 -0.456 51.106 -0.515 c
+51.142 -0.566 51.197 -0.611 51.267 -0.647 c
+51.345 -0.676 51.458 -0.691 51.605 -0.691 c
+51.741 -0.691 51.877 -0.688 52.016 -0.676 c
+52.153 -0.658 52.285 -0.632 52.413 -0.603 c
+52.413 -1.205 l
+52.332 -1.216 52.255 -1.231 52.178 -1.249 c
+52.097 -1.261 52.02 -1.268 51.943 -1.279 c
+51.862 -1.286 51.775 -1.294 51.679 -1.294 c
+51.59 -1.301 51.491 -1.309 51.384 -1.309 c
+51.197 -1.309 51.035 -1.294 50.9 -1.264 c
+50.771 -1.228 50.657 -1.183 50.561 -1.132 c
+50.474 -1.085 50.4 -1.025 50.341 -0.956 c
+50.283 -0.879 50.238 -0.802 50.208 -0.721 c
+50.179 -0.632 50.157 -0.544 50.15 -0.456 c
+50.139 -0.36 50.135 -0.264 50.135 -0.177 c
+h
+59.774 -0.647 m
+60.906 -0.647 l
+60.906 -1.264 l
+57.599 -1.264 l
+57.599 -0.647 l
+58.863 -0.647 l
+58.863 1.602 l
+57.936 1.602 l
+57.936 2.219 l
+59.774 2.219 l
+h
+58.863 3.513 0.911 -0.676 re
+58.863 2.836 m
+63.923 -1.264 m
+63.923 0.72 l
+63.923 1.022 63.879 1.242 63.791 1.382 c
+63.71 1.529 63.574 1.602 63.379 1.602 c
+63.268 1.602 63.166 1.577 63.07 1.529 c
+62.983 1.477 62.902 1.411 62.835 1.323 c
+62.776 1.234 62.725 1.124 62.688 0.999 c
+62.659 0.881 62.644 0.75 62.644 0.602 c
+62.644 -1.264 l
+61.732 -1.264 l
+61.732 1.44 l
+61.732 1.66 l
+61.732 1.749 61.726 1.826 61.718 1.896 c
+61.718 2.087 l
+61.718 2.219 l
+62.57 2.219 l
+62.578 2.19 62.586 2.146 62.586 2.087 c
+62.586 1.896 l
+62.593 1.826 62.6 1.756 62.6 1.69 c
+62.607 1.62 62.615 1.565 62.615 1.529 c
+62.63 1.529 l
+62.747 1.793 62.898 1.984 63.085 2.102 c
+63.268 2.219 63.49 2.278 63.746 2.278 c
+63.93 2.278 64.092 2.248 64.232 2.19 c
+64.367 2.131 64.481 2.043 64.57 1.926 c
+64.658 1.808 64.72 1.664 64.76 1.5 c
+64.808 1.341 64.834 1.153 64.834 0.941 c
+64.834 -1.264 l
+h
+68.895 -0.25 m
+68.895 -0.42 68.855 -0.57 68.777 -0.706 c
+68.708 -0.834 68.604 -0.948 68.469 -1.044 c
+68.34 -1.132 68.178 -1.202 67.983 -1.249 c
+67.796 -1.297 67.579 -1.323 67.337 -1.323 c
+67.109 -1.323 66.91 -1.309 66.734 -1.279 c
+66.557 -1.249 66.399 -1.202 66.264 -1.132 c
+66.124 -1.055 66.014 -0.956 65.926 -0.838 c
+65.838 -0.721 65.768 -0.574 65.72 -0.397 c
+66.528 -0.279 l
+66.547 -0.379 66.576 -0.456 66.617 -0.515 c
+66.665 -0.574 66.723 -0.617 66.792 -0.647 c
+66.859 -0.676 66.94 -0.702 67.028 -0.721 c
+67.116 -0.732 67.219 -0.735 67.337 -0.735 c
+67.432 -0.735 67.528 -0.732 67.616 -0.721 c
+67.704 -0.702 67.781 -0.676 67.851 -0.647 c
+67.918 -0.617 67.968 -0.58 67.999 -0.53 c
+68.035 -0.482 68.057 -0.42 68.057 -0.339 c
+68.057 -0.243 68.028 -0.169 67.968 -0.118 c
+67.918 -0.07 67.851 -0.029 67.763 0 c
+67.675 0.037 67.565 0.066 67.44 0.088 c
+67.322 0.118 67.19 0.147 67.043 0.176 c
+66.904 0.213 66.763 0.253 66.617 0.293 c
+66.476 0.341 66.352 0.404 66.235 0.484 c
+66.124 0.562 66.036 0.661 65.969 0.779 c
+65.9 0.897 65.867 1.047 65.867 1.234 c
+65.867 1.389 65.896 1.532 65.955 1.66 c
+66.021 1.797 66.117 1.911 66.235 1.999 c
+66.359 2.087 66.517 2.153 66.705 2.205 c
+66.888 2.252 67.102 2.278 67.337 2.278 c
+67.521 2.278 67.697 2.256 67.866 2.219 c
+68.031 2.19 68.178 2.135 68.307 2.057 c
+68.432 1.988 68.542 1.889 68.63 1.764 c
+68.718 1.646 68.777 1.502 68.807 1.338 c
+68.013 1.264 l
+67.991 1.341 67.962 1.404 67.924 1.455 c
+67.885 1.514 67.837 1.558 67.777 1.587 c
+67.727 1.624 67.664 1.65 67.586 1.66 c
+67.506 1.668 67.425 1.675 67.337 1.675 c
+67.12 1.675 66.958 1.646 66.852 1.587 c
+66.742 1.536 66.69 1.448 66.69 1.323 c
+66.69 1.242 66.709 1.18 66.748 1.132 c
+66.796 1.08 66.859 1.043 66.94 1.014 c
+67.028 0.985 67.124 0.955 67.234 0.926 c
+67.34 0.904 67.461 0.881 67.602 0.852 c
+67.756 0.823 67.914 0.783 68.072 0.735 c
+68.226 0.683 68.365 0.621 68.483 0.544 c
+68.601 0.463 68.697 0.36 68.777 0.235 c
+68.855 0.106 68.895 -0.055 68.895 -0.25 c
+70.457 1.602 m
+69.913 1.602 l
+69.913 2.219 l
+70.501 2.219 l
+70.78 3.116 l
+71.353 3.116 l
+71.353 2.219 l
+72.588 2.219 l
+72.588 1.602 l
+71.353 1.602 l
+71.353 -0.103 l
+71.353 -0.324 l
+71.361 -0.393 71.382 -0.456 71.412 -0.515 c
+71.449 -0.566 71.504 -0.611 71.573 -0.647 c
+71.651 -0.676 71.765 -0.691 71.912 -0.691 c
+72.047 -0.691 72.184 -0.688 72.323 -0.676 c
+72.46 -0.658 72.591 -0.632 72.72 -0.603 c
+72.72 -1.205 l
+72.639 -1.216 72.562 -1.231 72.485 -1.249 c
+72.404 -1.261 72.327 -1.268 72.25 -1.279 c
+72.169 -1.286 72.08 -1.294 71.985 -1.294 c
+71.897 -1.301 71.798 -1.309 71.691 -1.309 c
+71.504 -1.309 71.342 -1.294 71.206 -1.264 c
+71.078 -1.228 70.964 -1.183 70.868 -1.132 c
+70.78 -1.085 70.707 -1.025 70.648 -0.956 c
+70.589 -0.879 70.545 -0.802 70.515 -0.721 c
+70.486 -0.632 70.464 -0.544 70.457 -0.456 c
+70.445 -0.36 70.442 -0.264 70.442 -0.177 c
+h
+74.873 -1.323 m
+74.705 -1.323 74.554 -1.301 74.418 -1.264 c
+74.289 -1.216 74.175 -1.147 74.079 -1.058 c
+73.992 -0.97 73.922 -0.864 73.874 -0.735 c
+73.823 -0.599 73.801 -0.449 73.801 -0.279 c
+73.801 -0.073 73.834 0.095 73.904 0.235 c
+73.969 0.382 74.065 0.492 74.183 0.573 c
+74.308 0.661 74.451 0.723 74.609 0.764 c
+74.775 0.801 74.951 0.827 75.138 0.837 c
+75.858 0.852 l
+75.858 1.029 l
+75.858 1.147 75.847 1.249 75.829 1.338 c
+75.807 1.425 75.774 1.492 75.726 1.543 c
+75.685 1.602 75.638 1.639 75.579 1.66 c
+75.521 1.679 75.454 1.69 75.388 1.69 c
+75.318 1.69 75.255 1.679 75.197 1.66 c
+75.145 1.65 75.098 1.624 75.05 1.587 c
+75.01 1.558 74.977 1.506 74.947 1.44 c
+74.925 1.382 74.91 1.301 74.903 1.205 c
+73.962 1.249 l
+73.992 1.396 74.036 1.532 74.094 1.66 c
+74.16 1.785 74.256 1.896 74.374 1.984 c
+74.492 2.08 74.631 2.153 74.8 2.205 c
+74.977 2.252 75.182 2.278 75.417 2.278 c
+75.858 2.278 76.19 2.167 76.417 1.955 c
+76.652 1.749 76.77 1.44 76.77 1.029 c
+76.77 -0.235 l
+76.77 -0.456 l
+76.778 -0.515 76.792 -0.57 76.814 -0.617 c
+76.832 -0.658 76.861 -0.691 76.902 -0.721 c
+76.939 -0.742 76.99 -0.75 77.049 -0.75 c
+77.115 -0.75 77.185 -0.746 77.254 -0.735 c
+77.254 -1.22 l
+77.196 -1.231 77.141 -1.243 77.094 -1.249 c
+77.053 -1.261 77.013 -1.268 76.976 -1.279 c
+76.936 -1.286 76.891 -1.294 76.843 -1.294 c
+76.792 -1.301 76.733 -1.309 76.667 -1.309 c
+76.439 -1.309 76.274 -1.257 76.167 -1.147 c
+76.057 -1.029 75.995 -0.864 75.976 -0.647 c
+75.961 -0.647 l
+75.891 -0.757 75.822 -0.852 75.756 -0.941 c
+75.685 -1.022 75.608 -1.087 75.521 -1.147 c
+75.432 -1.205 75.333 -1.249 75.226 -1.279 c
+75.127 -1.309 75.01 -1.323 74.873 -1.323 c
+75.858 0.353 m
+75.432 0.338 l
+75.333 0.338 75.241 0.33 75.153 0.324 c
+75.072 0.312 75.006 0.286 74.947 0.249 c
+74.889 0.209 74.837 0.151 74.8 0.073 c
+74.76 0.004 74.742 -0.088 74.742 -0.206 c
+74.742 -0.375 74.775 -0.497 74.844 -0.574 c
+74.91 -0.655 75.01 -0.691 75.138 -0.691 c
+75.245 -0.691 75.344 -0.669 75.432 -0.617 c
+75.528 -0.57 75.608 -0.507 75.667 -0.426 c
+75.733 -0.349 75.785 -0.262 75.814 -0.162 c
+75.843 -0.055 75.858 0.058 75.858 0.176 c
+h
+80.08 -0.647 m
+81.213 -0.647 l
+81.213 -1.264 l
+77.905 -1.264 l
+77.905 -0.647 l
+79.17 -0.647 l
+79.17 2.896 l
+78.243 2.896 l
+78.243 3.513 l
+80.08 3.513 l
+h
+84.142 -0.647 m
+85.273 -0.647 l
+85.273 -1.264 l
+81.966 -1.264 l
+81.966 -0.647 l
+83.23 -0.647 l
+83.23 2.896 l
+82.304 2.896 l
+82.304 3.513 l
+84.142 3.513 l
+h
+91.689 -2.66 m
+91.473 -2.66 91.282 -2.635 91.116 -2.587 c
+90.947 -2.547 90.808 -2.484 90.69 -2.396 c
+90.573 -2.315 90.473 -2.22 90.396 -2.103 c
+90.326 -1.985 90.278 -1.856 90.249 -1.72 c
+91.145 -1.617 l
+91.182 -1.754 91.252 -1.86 91.351 -1.941 c
+91.446 -2.028 91.572 -2.072 91.718 -2.072 c
+91.807 -2.072 91.888 -2.058 91.969 -2.028 c
+92.046 -1.999 92.115 -1.945 92.175 -1.867 c
+92.233 -1.797 92.277 -1.706 92.306 -1.588 c
+92.344 -1.47 92.366 -1.323 92.366 -1.147 c
+92.366 -0.956 l
+92.366 -0.89 92.369 -0.831 92.381 -0.779 c
+92.381 -0.588 l
+92.366 -0.588 l
+92.267 -0.816 92.123 -0.977 91.939 -1.073 c
+91.752 -1.172 91.546 -1.22 91.322 -1.22 c
+91.116 -1.22 90.933 -1.183 90.778 -1.103 c
+90.631 -1.014 90.502 -0.897 90.396 -0.75 c
+90.297 -0.595 90.224 -0.412 90.176 -0.206 c
+90.124 0.008 90.102 0.243 90.102 0.5 c
+90.102 0.771 90.124 1.018 90.176 1.234 c
+90.234 1.448 90.315 1.631 90.425 1.778 c
+90.532 1.932 90.664 2.05 90.822 2.131 c
+90.976 2.219 91.164 2.263 91.381 2.263 c
+91.477 2.263 91.575 2.252 91.675 2.234 c
+91.77 2.212 91.859 2.179 91.939 2.131 c
+92.028 2.08 92.105 2.017 92.175 1.94 c
+92.252 1.859 92.314 1.768 92.366 1.66 c
+92.381 1.66 l
+92.381 1.808 l
+92.387 1.866 92.395 1.918 92.395 1.97 c
+92.402 2.028 92.41 2.076 92.41 2.117 c
+92.417 2.165 92.428 2.198 92.439 2.219 c
+93.291 2.219 l
+93.281 2.138 93.27 2.028 93.262 1.881 c
+93.262 1.411 l
+93.262 -1.162 l
+93.262 -1.415 93.225 -1.636 93.16 -1.823 c
+93.089 -2.007 92.986 -2.161 92.851 -2.278 c
+92.711 -2.404 92.545 -2.499 92.35 -2.558 c
+92.152 -2.624 91.932 -2.66 91.689 -2.66 c
+92.381 0.529 m
+92.381 0.742 92.354 0.918 92.306 1.058 c
+92.267 1.205 92.211 1.323 92.145 1.411 c
+92.086 1.5 92.017 1.558 91.939 1.587 c
+91.859 1.624 91.781 1.646 91.704 1.646 c
+91.604 1.646 91.513 1.62 91.425 1.573 c
+91.344 1.532 91.278 1.462 91.219 1.367 c
+91.168 1.278 91.124 1.161 91.087 1.014 c
+91.057 0.874 91.043 0.706 91.043 0.5 c
+91.043 0.125 91.101 -0.154 91.219 -0.339 c
+91.336 -0.515 91.498 -0.603 91.704 -0.603 c
+91.77 -0.603 91.843 -0.588 91.924 -0.559 c
+92.013 -0.522 92.086 -0.463 92.145 -0.382 c
+92.211 -0.294 92.267 -0.177 92.306 -0.029 c
+92.354 0.118 92.381 0.301 92.381 0.529 c
+96.327 -0.647 m
+97.459 -0.647 l
+97.459 -1.264 l
+94.151 -1.264 l
+94.151 -0.647 l
+95.415 -0.647 l
+95.415 1.602 l
+94.49 1.602 l
+94.49 2.219 l
+96.327 2.219 l
+h
+95.415 3.513 0.912 -0.676 re
+95.415 2.836 m
+98.889 1.602 m
+98.344 1.602 l
+98.344 2.219 l
+98.932 2.219 l
+99.211 3.116 l
+99.785 3.116 l
+99.785 2.219 l
+101.019 2.219 l
+101.019 1.602 l
+99.785 1.602 l
+99.785 -0.103 l
+99.785 -0.324 l
+99.793 -0.393 99.814 -0.456 99.844 -0.515 c
+99.88 -0.566 99.936 -0.611 100.005 -0.647 c
+100.082 -0.676 100.196 -0.691 100.343 -0.691 c
+100.479 -0.691 100.615 -0.688 100.755 -0.676 c
+100.891 -0.658 101.023 -0.632 101.152 -0.603 c
+101.152 -1.205 l
+101.071 -1.216 100.994 -1.231 100.917 -1.249 c
+100.836 -1.261 100.759 -1.268 100.682 -1.279 c
+100.601 -1.286 100.512 -1.294 100.417 -1.294 c
+100.329 -1.301 100.229 -1.309 100.123 -1.309 c
+99.936 -1.309 99.774 -1.294 99.637 -1.264 c
+99.51 -1.228 99.396 -1.183 99.3 -1.132 c
+99.211 -1.085 99.138 -1.025 99.08 -0.956 c
+99.02 -0.879 98.976 -0.802 98.947 -0.721 c
+98.918 -0.632 98.895 -0.544 98.889 -0.456 c
+98.877 -0.36 98.874 -0.264 98.874 -0.177 c
+h
+f
+Q
+0.793 0.801 0.129 0.016 k
+35.668 201.199 238.665 -21.457 re
+f
+0 0 0 0 k
+q 1 0 0 1 164.9238 185.7106 cm
+0 0 m
+0 9.363 l
+2.896 9.363 l
+3.873 9.363 4.619 9.142 5.13 8.702 c
+5.637 8.268 5.895 7.632 5.895 6.79 c
+5.895 6.32 5.785 5.913 5.571 5.57 c
+5.365 5.225 5.075 4.976 4.704 4.821 c
+5.122 4.692 5.446 4.446 5.674 4.086 c
+5.909 3.733 6.026 3.285 6.026 2.748 c
+6.026 1.844 5.777 1.161 5.277 0.691 c
+4.777 0.228 4.05 0 3.102 0 c
+h
+1.897 4.072 m
+1.897 1.572 l
+3.102 1.572 l
+3.443 1.572 3.705 1.675 3.881 1.881 c
+4.057 2.094 4.145 2.395 4.145 2.778 c
+4.145 3.619 3.836 4.049 3.219 4.072 c
+h
+1.897 5.453 m
+2.882 5.453 l
+3.616 5.453 3.983 5.835 3.983 6.599 c
+3.983 7.018 3.896 7.324 3.719 7.511 c
+3.55 7.694 3.278 7.79 2.896 7.79 c
+1.897 7.79 l
+h
+7.655 0.926 m
+7.655 1.219 7.75 1.458 7.948 1.646 c
+8.143 1.83 8.397 1.925 8.713 1.925 c
+9.014 1.925 9.264 1.83 9.463 1.646 c
+9.668 1.458 9.771 1.219 9.771 0.926 c
+9.771 0.621 9.668 0.374 9.463 0.191 c
+9.264 0.014 9.014 -0.074 8.713 -0.074 c
+8.408 -0.074 8.154 0.018 7.948 0.205 c
+7.75 0.389 7.655 0.631 7.655 0.926 c
+16.644 0 -1.897 9.363 re
+24.702 1.058 m
+24.338 0.665 23.894 0.367 23.364 0.161 c
+22.836 -0.034 22.254 -0.133 21.629 -0.133 c
+20.55 -0.133 19.711 0.198 19.116 0.866 c
+18.518 1.532 18.212 2.502 18.205 3.777 c
+18.205 5.468 l
+18.205 6.761 18.485 7.754 19.042 8.452 c
+19.609 9.146 20.432 9.495 21.512 9.495 c
+22.53 9.495 23.295 9.238 23.805 8.731 c
+24.324 8.231 24.621 7.445 24.702 6.379 c
+22.865 6.379 l
+22.813 6.975 22.692 7.382 22.497 7.599 c
+22.298 7.812 21.99 7.922 21.571 7.922 c
+21.06 7.922 20.689 7.735 20.454 7.364 c
+20.226 6.989 20.108 6.397 20.101 5.585 c
+20.101 3.881 l
+20.101 3.027 20.226 2.403 20.484 2.013 c
+20.737 1.631 21.152 1.44 21.733 1.44 c
+22.104 1.44 22.408 1.514 22.644 1.66 c
+22.805 1.778 l
+22.805 3.498 l
+21.483 3.498 l
+21.483 4.924 l
+24.702 4.924 l
+h
+32.831 0 m
+30.934 0 l
+28.17 6.144 l
+28.17 0 l
+26.275 0 l
+26.275 9.363 l
+28.17 9.363 l
+30.934 3.218 l
+30.934 9.363 l
+32.831 9.363 l
+h
+41.183 3.836 m
+41.183 2.58 40.882 1.606 40.286 0.911 c
+39.688 0.213 38.865 -0.133 37.817 -0.133 c
+36.766 -0.133 35.939 0.209 35.333 0.897 c
+34.734 1.591 34.429 2.557 34.422 3.792 c
+34.422 5.394 l
+34.422 6.676 34.719 7.68 35.318 8.407 c
+35.914 9.132 36.744 9.495 37.803 9.495 c
+38.838 9.495 39.658 9.135 40.257 8.422 c
+40.864 7.717 41.172 6.721 41.183 5.438 c
+h
+39.287 5.409 m
+39.287 6.25 39.162 6.879 38.919 7.291 c
+38.684 7.702 38.31 7.908 37.803 7.908 c
+37.302 7.908 36.928 7.706 36.685 7.305 c
+36.45 6.912 36.325 6.312 36.318 5.512 c
+36.318 3.836 l
+36.318 3.02 36.439 2.418 36.685 2.028 c
+36.928 1.635 37.306 1.44 37.817 1.44 c
+38.306 1.44 38.67 1.631 38.905 2.013 c
+39.147 2.395 39.276 2.983 39.287 3.777 c
+h
+45.593 3.424 m
+44.652 3.424 l
+44.652 0 l
+42.771 0 l
+42.771 9.363 l
+45.784 9.363 l
+46.732 9.363 47.463 9.117 47.974 8.628 c
+48.492 8.136 48.753 7.441 48.753 6.541 c
+48.753 5.294 48.301 4.424 47.401 3.924 c
+49.032 0.087 l
+49.032 0 l
+47.004 0 l
+h
+44.652 4.997 m
+45.726 4.997 l
+46.108 4.997 46.391 5.119 46.578 5.365 c
+46.761 5.618 46.857 5.957 46.857 6.379 c
+46.857 7.32 46.493 7.79 45.769 7.79 c
+44.652 7.79 l
+h
+52.255 0 -1.897 9.363 re
+60.505 0 m
+58.609 0 l
+55.845 6.144 l
+55.845 0 l
+53.95 0 l
+53.95 9.363 l
+55.845 9.363 l
+58.609 3.218 l
+58.609 9.363 l
+60.505 9.363 l
+h
+68.622 1.058 m
+68.259 0.665 67.814 0.367 67.285 0.161 c
+66.756 -0.034 66.175 -0.133 65.551 -0.133 c
+64.47 -0.133 63.633 0.198 63.037 0.866 c
+62.438 1.532 62.133 2.502 62.125 3.777 c
+62.125 5.468 l
+62.125 6.761 62.405 7.754 62.964 8.452 c
+63.529 9.146 64.352 9.495 65.433 9.495 c
+66.451 9.495 67.215 9.238 67.726 8.731 c
+68.244 8.231 68.541 7.445 68.622 6.379 c
+66.785 6.379 l
+66.734 6.975 66.613 7.382 66.418 7.599 c
+66.22 7.812 65.911 7.922 65.491 7.922 c
+64.981 7.922 64.61 7.735 64.375 7.364 c
+64.147 6.989 64.03 6.397 64.022 5.585 c
+64.022 3.881 l
+64.022 3.027 64.147 2.403 64.404 2.013 c
+64.658 1.631 65.073 1.44 65.653 1.44 c
+66.025 1.44 66.33 1.514 66.565 1.66 c
+66.727 1.778 l
+66.727 3.498 l
+65.404 3.498 l
+65.404 4.924 l
+68.622 4.924 l
+h
+78.151 3.821 m
+75.211 3.821 l
+75.211 0 l
+73.316 0 l
+73.316 9.363 l
+78.504 9.363 l
+78.504 7.79 l
+75.211 7.79 l
+75.211 5.394 l
+78.151 5.394 l
+h
+81.756 0 -1.896 9.363 re
+85.347 1.572 m
+88.668 1.572 l
+88.668 0 l
+83.45 0 l
+83.45 9.363 l
+85.347 9.363 l
+h
+94.768 4.056 m
+91.828 4.056 l
+91.828 1.572 l
+95.312 1.572 l
+95.312 0 l
+89.933 0 l
+89.933 9.363 l
+95.298 9.363 l
+95.298 7.79 l
+91.828 7.79 l
+91.828 5.57 l
+94.768 5.57 l
+h
+100.526 2.454 m
+100.526 2.836 100.428 3.123 100.233 3.322 c
+100.034 3.516 99.682 3.719 99.175 3.924 c
+98.234 4.284 97.558 4.704 97.146 5.174 c
+96.734 5.651 96.528 6.221 96.528 6.879 c
+96.528 7.661 96.808 8.294 97.367 8.775 c
+97.925 9.252 98.635 9.495 99.498 9.495 c
+100.075 9.495 100.589 9.37 101.041 9.128 c
+101.49 8.882 101.835 8.54 102.07 8.099 c
+102.313 7.658 102.438 7.158 102.438 6.599 c
+100.557 6.599 l
+100.557 7.04 100.461 7.371 100.277 7.599 c
+100.09 7.823 99.821 7.937 99.468 7.937 c
+99.134 7.937 98.874 7.838 98.689 7.644 c
+98.513 7.455 98.425 7.195 98.425 6.864 c
+98.425 6.607 98.527 6.372 98.733 6.158 c
+98.939 5.953 99.3 5.736 99.821 5.512 c
+100.732 5.188 101.394 4.784 101.806 4.307 c
+102.225 3.825 102.438 3.212 102.438 2.469 c
+102.438 1.653 102.177 1.018 101.659 0.558 c
+101.137 0.095 100.431 -0.133 99.542 -0.133 c
+98.932 -0.133 98.381 -0.008 97.881 0.235 c
+97.389 0.488 97.002 0.845 96.72 1.308 c
+96.433 1.778 96.293 2.326 96.293 2.954 c
+98.19 2.954 l
+98.19 2.414 98.292 2.021 98.498 1.778 c
+98.712 1.532 99.061 1.411 99.542 1.411 c
+100.196 1.411 100.526 1.756 100.526 2.454 c
+f
+Q
+0.113 0.082 0.09 0 k
+35.668 173.911 238.665 -49.165 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 40.8563 167.0717 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.69 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.278 -3.219 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.042 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.319 2.385 -2.366 2.337 c
+-2.406 2.296 -2.437 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.431 -1.323 m
+6.145 -1.323 5.902 -1.282 5.696 -1.205 c
+5.49 -1.117 5.318 -0.996 5.182 -0.838 c
+5.042 -0.684 4.939 -0.496 4.873 -0.279 c
+4.803 -0.055 4.77 0.191 4.77 0.455 c
+4.77 0.75 4.803 1.007 4.873 1.235 c
+4.95 1.459 5.056 1.646 5.197 1.793 c
+5.343 1.947 5.519 2.065 5.725 2.146 c
+5.931 2.234 6.167 2.278 6.431 2.278 c
+6.656 2.278 6.857 2.249 7.034 2.19 c
+7.21 2.132 7.361 2.047 7.489 1.941 c
+7.614 1.841 7.717 1.72 7.798 1.573 c
+7.875 1.433 7.93 1.282 7.96 1.118 c
+7.048 1.073 l
+7.019 1.249 6.949 1.389 6.843 1.5 c
+6.743 1.606 6.6 1.661 6.417 1.661 c
+6.17 1.661 5.993 1.558 5.887 1.353 c
+5.777 1.154 5.725 0.867 5.725 0.485 c
+5.725 -0.309 5.961 -0.706 6.431 -0.706 c
+6.596 -0.706 6.739 -0.654 6.857 -0.544 c
+6.975 -0.437 7.048 -0.276 7.078 -0.058 c
+7.989 -0.103 l
+7.96 -0.272 7.905 -0.426 7.828 -0.573 c
+7.757 -0.721 7.655 -0.852 7.518 -0.97 c
+7.39 -1.08 7.232 -1.168 7.048 -1.234 c
+6.872 -1.294 6.666 -1.323 6.431 -1.323 c
+9.889 -1.323 m
+9.72 -1.323 9.569 -1.301 9.434 -1.264 c
+9.305 -1.216 9.191 -1.147 9.095 -1.058 c
+9.008 -0.97 8.937 -0.864 8.889 -0.735 c
+8.838 -0.599 8.816 -0.449 8.816 -0.279 c
+8.816 -0.073 8.85 0.096 8.919 0.235 c
+8.985 0.382 9.081 0.492 9.199 0.573 c
+9.323 0.661 9.467 0.724 9.625 0.765 c
+9.79 0.802 9.966 0.827 10.153 0.838 c
+10.874 0.852 l
+10.874 1.029 l
+10.874 1.147 10.863 1.249 10.845 1.338 c
+10.822 1.426 10.789 1.492 10.741 1.544 c
+10.701 1.602 10.654 1.639 10.595 1.661 c
+10.535 1.679 10.469 1.691 10.404 1.691 c
+10.334 1.691 10.271 1.679 10.213 1.661 c
+10.161 1.65 10.113 1.625 10.065 1.588 c
+10.025 1.558 9.992 1.507 9.962 1.44 c
+9.941 1.382 9.926 1.301 9.918 1.205 c
+8.977 1.249 l
+9.008 1.396 9.051 1.532 9.11 1.661 c
+9.176 1.786 9.272 1.897 9.39 1.984 c
+9.507 2.08 9.646 2.153 9.816 2.205 c
+9.992 2.253 10.198 2.278 10.433 2.278 c
+10.874 2.278 11.204 2.168 11.433 1.955 c
+11.668 1.749 11.786 1.44 11.786 1.029 c
+11.786 -0.235 l
+11.786 -0.455 l
+11.792 -0.515 11.807 -0.569 11.83 -0.617 c
+11.848 -0.658 11.877 -0.69 11.917 -0.721 c
+11.954 -0.742 12.006 -0.75 12.065 -0.75 c
+12.131 -0.75 12.2 -0.746 12.27 -0.735 c
+12.27 -1.22 l
+12.212 -1.231 12.156 -1.242 12.108 -1.249 c
+12.068 -1.261 12.027 -1.268 11.991 -1.278 c
+11.95 -1.286 11.907 -1.294 11.859 -1.294 c
+11.807 -1.301 11.749 -1.309 11.682 -1.309 c
+11.454 -1.309 11.289 -1.257 11.183 -1.147 c
+11.072 -1.029 11.009 -0.864 10.992 -0.646 c
+10.977 -0.646 l
+10.907 -0.757 10.837 -0.852 10.771 -0.941 c
+10.701 -1.022 10.624 -1.087 10.535 -1.147 c
+10.448 -1.205 10.348 -1.249 10.242 -1.278 c
+10.143 -1.309 10.025 -1.323 9.889 -1.323 c
+10.874 0.353 m
+10.448 0.338 l
+10.348 0.338 10.257 0.331 10.168 0.324 c
+10.088 0.312 10.022 0.287 9.962 0.25 c
+9.904 0.21 9.852 0.151 9.816 0.073 c
+9.775 0.004 9.756 -0.088 9.756 -0.206 c
+9.756 -0.374 9.79 -0.496 9.86 -0.573 c
+9.926 -0.654 10.025 -0.69 10.153 -0.69 c
+10.261 -0.69 10.359 -0.669 10.448 -0.617 c
+10.543 -0.569 10.624 -0.507 10.683 -0.426 c
+10.749 -0.349 10.801 -0.261 10.83 -0.162 c
+10.859 -0.055 10.874 0.059 10.874 0.177 c
+h
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.219 l
+13.644 2.219 l
+13.924 3.117 l
+14.497 3.117 l
+14.497 2.219 l
+15.732 2.219 l
+15.732 1.602 l
+14.497 1.602 l
+14.497 -0.103 l
+14.497 -0.324 l
+14.504 -0.393 14.527 -0.455 14.556 -0.515 c
+14.593 -0.566 14.648 -0.61 14.718 -0.646 c
+14.795 -0.676 14.909 -0.69 15.056 -0.69 c
+15.192 -0.69 15.327 -0.687 15.468 -0.676 c
+15.603 -0.658 15.736 -0.632 15.865 -0.603 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.231 15.629 -1.249 c
+15.549 -1.261 15.471 -1.268 15.394 -1.278 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.041 -1.301 14.942 -1.309 14.835 -1.309 c
+14.648 -1.309 14.486 -1.294 14.35 -1.264 c
+14.221 -1.228 14.107 -1.183 14.012 -1.132 c
+13.924 -1.084 13.85 -1.025 13.791 -0.956 c
+13.733 -0.879 13.689 -0.801 13.66 -0.721 c
+13.63 -0.632 13.608 -0.544 13.6 -0.455 c
+13.59 -0.36 13.586 -0.264 13.586 -0.176 c
+h
+22.178 -0.279 0.926 -0.985 re
+22.178 -1.264 m
+26.709 -2.66 m
+26.491 -2.66 26.3 -2.635 26.136 -2.587 c
+25.966 -2.547 25.826 -2.484 25.709 -2.396 c
+25.591 -2.315 25.492 -2.219 25.415 -2.102 c
+25.345 -1.984 25.297 -1.856 25.268 -1.72 c
+26.165 -1.617 l
+26.201 -1.753 26.271 -1.86 26.371 -1.94 c
+26.466 -2.028 26.591 -2.072 26.738 -2.072 c
+26.826 -2.072 26.907 -2.057 26.988 -2.028 c
+27.065 -1.999 27.135 -1.944 27.194 -1.866 c
+27.252 -1.797 27.296 -1.705 27.326 -1.587 c
+27.362 -1.469 27.385 -1.323 27.385 -1.147 c
+27.385 -0.956 l
+27.385 -0.889 27.389 -0.831 27.399 -0.779 c
+27.399 -0.588 l
+27.385 -0.588 l
+27.285 -0.816 27.142 -0.977 26.959 -1.073 c
+26.771 -1.172 26.566 -1.22 26.341 -1.22 c
+26.136 -1.22 25.951 -1.183 25.797 -1.103 c
+25.65 -1.014 25.521 -0.897 25.415 -0.75 c
+25.315 -0.595 25.242 -0.411 25.195 -0.206 c
+25.143 0.008 25.121 0.243 25.121 0.5 c
+25.121 0.771 25.143 1.018 25.195 1.235 c
+25.253 1.448 25.334 1.631 25.444 1.779 c
+25.55 1.933 25.683 2.051 25.841 2.132 c
+25.995 2.219 26.183 2.263 26.4 2.263 c
+26.495 2.263 26.595 2.253 26.693 2.234 c
+26.789 2.213 26.878 2.179 26.959 2.132 c
+27.046 2.08 27.123 2.018 27.194 1.941 c
+27.271 1.86 27.333 1.768 27.385 1.661 c
+27.399 1.661 l
+27.399 1.808 l
+27.407 1.866 27.414 1.918 27.414 1.97 c
+27.422 2.028 27.429 2.076 27.429 2.117 c
+27.436 2.165 27.447 2.198 27.458 2.219 c
+28.311 2.219 l
+28.299 2.138 28.289 2.028 28.281 1.881 c
+28.281 1.411 l
+28.281 -1.161 l
+28.281 -1.415 28.245 -1.635 28.178 -1.822 c
+28.108 -2.007 28.006 -2.161 27.869 -2.278 c
+27.73 -2.404 27.565 -2.499 27.37 -2.558 c
+27.171 -2.624 26.951 -2.66 26.709 -2.66 c
+27.399 0.53 m
+27.399 0.742 27.374 0.919 27.326 1.058 c
+27.285 1.205 27.231 1.323 27.164 1.411 c
+27.106 1.5 27.036 1.558 26.959 1.588 c
+26.878 1.625 26.801 1.646 26.724 1.646 c
+26.624 1.646 26.532 1.621 26.444 1.573 c
+26.363 1.532 26.296 1.463 26.238 1.367 c
+26.186 1.278 26.142 1.161 26.106 1.014 c
+26.076 0.875 26.061 0.706 26.061 0.5 c
+26.061 0.125 26.121 -0.154 26.238 -0.338 c
+26.356 -0.515 26.518 -0.603 26.724 -0.603 c
+26.789 -0.603 26.863 -0.588 26.944 -0.559 c
+27.032 -0.522 27.106 -0.463 27.164 -0.382 c
+27.231 -0.294 27.285 -0.176 27.326 -0.029 c
+27.374 0.118 27.399 0.301 27.399 0.53 c
+31.343 -0.646 m
+32.474 -0.646 l
+32.474 -1.264 l
+29.167 -1.264 l
+29.167 -0.646 l
+30.431 -0.646 l
+30.431 1.602 l
+29.505 1.602 l
+29.505 2.219 l
+31.343 2.219 l
+h
+30.431 3.513 0.912 -0.675 re
+30.431 2.837 m
+33.907 1.602 m
+33.363 1.602 l
+33.363 2.219 l
+33.951 2.219 l
+34.231 3.117 l
+34.804 3.117 l
+34.804 2.219 l
+36.039 2.219 l
+36.039 1.602 l
+34.804 1.602 l
+34.804 -0.103 l
+34.804 -0.324 l
+34.811 -0.393 34.834 -0.455 34.863 -0.515 c
+34.9 -0.566 34.955 -0.61 35.025 -0.646 c
+35.102 -0.676 35.216 -0.69 35.362 -0.69 c
+35.499 -0.69 35.634 -0.687 35.774 -0.676 c
+35.91 -0.658 36.043 -0.632 36.17 -0.603 c
+36.17 -1.205 l
+36.091 -1.216 36.013 -1.231 35.935 -1.249 c
+35.855 -1.261 35.778 -1.268 35.7 -1.278 c
+35.62 -1.286 35.532 -1.294 35.436 -1.294 c
+35.348 -1.301 35.249 -1.309 35.142 -1.309 c
+34.955 -1.309 34.793 -1.294 34.657 -1.264 c
+34.528 -1.228 34.414 -1.183 34.319 -1.132 c
+34.231 -1.084 34.157 -1.025 34.098 -0.956 c
+34.04 -0.879 33.995 -0.801 33.966 -0.721 c
+33.937 -0.632 33.915 -0.544 33.907 -0.455 c
+33.897 -0.36 33.893 -0.264 33.893 -0.176 c
+h
+39.467 -0.646 m
+40.599 -0.646 l
+40.599 -1.264 l
+37.292 -1.264 l
+37.292 -0.646 l
+38.556 -0.646 l
+38.556 1.602 l
+37.63 1.602 l
+37.63 2.219 l
+39.467 2.219 l
+h
+38.556 3.513 0.911 -0.675 re
+38.556 2.837 m
+42.954 -2.66 m
+42.738 -2.66 42.547 -2.635 42.381 -2.587 c
+42.212 -2.547 42.073 -2.484 41.955 -2.396 c
+41.837 -2.315 41.738 -2.219 41.661 -2.102 c
+41.591 -1.984 41.543 -1.856 41.514 -1.72 c
+42.41 -1.617 l
+42.447 -1.753 42.518 -1.86 42.616 -1.94 c
+42.712 -2.028 42.837 -2.072 42.984 -2.072 c
+43.072 -2.072 43.153 -2.057 43.234 -2.028 c
+43.311 -1.999 43.381 -1.944 43.44 -1.866 c
+43.499 -1.797 43.542 -1.705 43.572 -1.587 c
+43.609 -1.469 43.631 -1.323 43.631 -1.147 c
+43.631 -0.956 l
+43.631 -0.889 43.634 -0.831 43.646 -0.779 c
+43.646 -0.588 l
+43.631 -0.588 l
+43.532 -0.816 43.388 -0.977 43.204 -1.073 c
+43.017 -1.172 42.811 -1.22 42.587 -1.22 c
+42.381 -1.22 42.198 -1.183 42.044 -1.103 c
+41.896 -1.014 41.768 -0.897 41.661 -0.75 c
+41.562 -0.595 41.488 -0.411 41.441 -0.206 c
+41.389 0.008 41.367 0.243 41.367 0.5 c
+41.367 0.771 41.389 1.018 41.441 1.235 c
+41.5 1.448 41.58 1.631 41.691 1.779 c
+41.797 1.933 41.93 2.051 42.088 2.132 c
+42.242 2.219 42.429 2.263 42.646 2.263 c
+42.742 2.263 42.84 2.253 42.94 2.234 c
+43.035 2.213 43.123 2.179 43.204 2.132 c
+43.293 2.08 43.37 2.018 43.44 1.941 c
+43.517 1.86 43.58 1.768 43.631 1.661 c
+43.646 1.661 l
+43.646 1.808 l
+43.653 1.866 43.66 1.918 43.66 1.97 c
+43.667 2.028 43.675 2.076 43.675 2.117 c
+43.682 2.165 43.694 2.198 43.704 2.219 c
+44.557 2.219 l
+44.546 2.138 44.535 2.028 44.527 1.881 c
+44.527 1.411 l
+44.527 -1.161 l
+44.527 -1.415 44.49 -1.635 44.425 -1.822 c
+44.355 -2.007 44.251 -2.161 44.116 -2.278 c
+43.976 -2.404 43.811 -2.499 43.616 -2.558 c
+43.418 -2.624 43.197 -2.66 42.954 -2.66 c
+43.646 0.53 m
+43.646 0.742 43.619 0.919 43.572 1.058 c
+43.532 1.205 43.476 1.323 43.41 1.411 c
+43.351 1.5 43.282 1.558 43.204 1.588 c
+43.123 1.625 43.046 1.646 42.969 1.646 c
+42.87 1.646 42.778 1.621 42.69 1.573 c
+42.609 1.532 42.543 1.463 42.484 1.367 c
+42.433 1.278 42.389 1.161 42.352 1.014 c
+42.323 0.875 42.308 0.706 42.308 0.5 c
+42.308 0.125 42.366 -0.154 42.484 -0.338 c
+42.601 -0.515 42.763 -0.603 42.969 -0.603 c
+43.035 -0.603 43.109 -0.588 43.189 -0.559 c
+43.278 -0.522 43.351 -0.463 43.41 -0.382 c
+43.476 -0.294 43.532 -0.176 43.572 -0.029 c
+43.619 0.118 43.646 0.301 43.646 0.53 c
+47.677 -1.264 m
+47.677 0.721 l
+47.677 1.022 47.632 1.242 47.544 1.382 c
+47.463 1.529 47.328 1.602 47.133 1.602 c
+47.023 1.602 46.919 1.577 46.824 1.529 c
+46.736 1.477 46.655 1.411 46.589 1.323 c
+46.53 1.235 46.479 1.124 46.441 1 c
+46.412 0.882 46.398 0.75 46.398 0.603 c
+46.398 -1.264 l
+45.487 -1.264 l
+45.487 1.44 l
+45.487 1.661 l
+45.487 1.749 45.479 1.826 45.472 1.897 c
+45.472 2.088 l
+45.472 2.219 l
+46.324 2.219 l
+46.331 2.19 46.339 2.146 46.339 2.088 c
+46.339 1.897 l
+46.346 1.826 46.354 1.756 46.354 1.691 c
+46.362 1.621 46.368 1.565 46.368 1.529 c
+46.383 1.529 l
+46.501 1.793 46.651 1.984 46.838 2.102 c
+47.023 2.219 47.243 2.278 47.5 2.278 c
+47.684 2.278 47.846 2.249 47.985 2.19 c
+48.122 2.132 48.235 2.043 48.323 1.926 c
+48.411 1.808 48.474 1.665 48.515 1.5 c
+48.562 1.342 48.588 1.154 48.588 0.941 c
+48.588 -1.264 l
+h
+52.752 0.485 m
+52.752 0.21 52.714 -0.04 52.648 -0.264 c
+52.579 -0.482 52.476 -0.669 52.34 -0.823 c
+52.201 -0.981 52.024 -1.103 51.811 -1.191 c
+51.594 -1.278 51.341 -1.323 51.046 -1.323 c
+50.771 -1.323 50.524 -1.278 50.312 -1.191 c
+50.106 -1.103 49.933 -0.981 49.797 -0.823 c
+49.657 -0.669 49.554 -0.482 49.489 -0.264 c
+49.419 -0.04 49.385 0.21 49.385 0.485 c
+49.385 0.738 49.415 0.974 49.473 1.191 c
+49.539 1.415 49.643 1.606 49.782 1.764 c
+49.918 1.929 50.094 2.058 50.312 2.146 c
+50.524 2.234 50.782 2.278 51.076 2.278 c
+51.388 2.278 51.649 2.234 51.854 2.146 c
+52.068 2.058 52.241 1.929 52.369 1.764 c
+52.505 1.606 52.604 1.415 52.664 1.191 c
+52.722 0.974 52.752 0.738 52.752 0.485 c
+51.796 0.485 m
+51.796 0.691 51.781 0.867 51.752 1.014 c
+51.73 1.161 51.693 1.282 51.634 1.382 c
+51.576 1.477 51.502 1.548 51.414 1.588 c
+51.326 1.635 51.216 1.661 51.091 1.661 c
+50.826 1.661 50.635 1.562 50.517 1.367 c
+50.4 1.18 50.341 0.885 50.341 0.485 c
+50.341 0.062 50.4 -0.243 50.517 -0.426 c
+50.635 -0.613 50.811 -0.706 51.046 -0.706 c
+51.172 -0.706 51.285 -0.687 51.384 -0.646 c
+51.48 -0.599 51.561 -0.526 51.619 -0.426 c
+51.686 -0.331 51.73 -0.206 51.752 -0.058 c
+51.781 0.088 51.796 0.268 51.796 0.485 c
+56.625 1.47 m
+56.525 1.477 56.423 1.488 56.316 1.5 c
+56.205 1.517 56.084 1.529 55.949 1.529 c
+55.772 1.529 55.614 1.488 55.478 1.411 c
+55.339 1.342 55.22 1.242 55.125 1.118 c
+55.037 0.989 54.967 0.842 54.919 0.676 c
+54.879 0.507 54.861 0.331 54.861 0.147 c
+54.861 -1.264 l
+53.965 -1.264 l
+53.965 0.985 l
+53.965 1.11 53.953 1.235 53.934 1.353 c
+53.924 1.477 53.909 1.595 53.89 1.706 c
+53.88 1.823 53.865 1.918 53.847 1.999 c
+53.824 2.088 53.807 2.161 53.788 2.219 c
+54.67 2.219 l
+54.677 2.168 54.688 2.117 54.699 2.058 c
+54.717 1.999 54.732 1.933 54.743 1.866 c
+54.761 1.808 54.776 1.742 54.788 1.675 c
+54.794 1.606 54.806 1.544 54.817 1.484 c
+54.831 1.484 l
+54.869 1.602 54.919 1.708 54.979 1.808 c
+55.045 1.903 55.125 1.988 55.214 2.058 c
+55.301 2.124 55.405 2.179 55.522 2.219 c
+55.648 2.256 55.794 2.278 55.964 2.278 c
+56.088 2.278 56.205 2.271 56.316 2.263 c
+56.434 2.253 56.537 2.238 56.625 2.219 c
+h
+59.23 -1.323 m
+58.973 -1.323 58.745 -1.286 58.539 -1.22 c
+58.333 -1.143 58.157 -1.029 58.01 -0.881 c
+57.863 -0.727 57.745 -0.536 57.657 -0.309 c
+57.576 -0.085 57.539 0.18 57.539 0.485 c
+57.539 0.816 57.584 1.095 57.672 1.323 c
+57.768 1.558 57.896 1.742 58.054 1.881 c
+58.22 2.018 58.407 2.117 58.613 2.176 c
+58.819 2.242 59.028 2.278 59.245 2.278 c
+59.517 2.278 59.752 2.227 59.951 2.132 c
+60.157 2.043 60.321 1.911 60.45 1.735 c
+60.586 1.565 60.685 1.359 60.744 1.118 c
+60.81 0.882 60.847 0.617 60.847 0.324 c
+60.847 0.309 l
+58.48 0.309 l
+58.48 0.162 58.495 0.022 58.524 -0.103 c
+58.561 -0.231 58.617 -0.345 58.686 -0.441 c
+58.752 -0.529 58.837 -0.599 58.936 -0.646 c
+59.031 -0.698 59.145 -0.721 59.274 -0.721 c
+59.428 -0.721 59.569 -0.687 59.686 -0.617 c
+59.81 -0.551 59.899 -0.449 59.951 -0.309 c
+60.788 -0.382 l
+60.759 -0.482 60.704 -0.588 60.627 -0.706 c
+60.546 -0.816 60.443 -0.919 60.317 -1.014 c
+60.2 -1.103 60.046 -1.176 59.862 -1.234 c
+59.686 -1.294 59.473 -1.323 59.23 -1.323 c
+59.23 1.706 m
+59.141 1.706 59.054 1.691 58.966 1.661 c
+58.877 1.631 58.796 1.58 58.73 1.514 c
+58.661 1.444 58.601 1.356 58.553 1.249 c
+58.513 1.139 58.495 1.014 58.495 0.867 c
+59.965 0.867 l
+59.965 1.003 59.939 1.124 59.891 1.235 c
+59.851 1.342 59.796 1.43 59.729 1.5 c
+59.671 1.565 59.598 1.617 59.509 1.646 c
+59.421 1.683 59.326 1.706 59.23 1.706 c
+f
+Q
+q 1 0 0 1 40.8309 120.2041 cm
+0 0 m
+-1.411 0 l
+-1.411 -4.777 l
+-2.072 -4.777 l
+-2.072 0 l
+-3.484 0 l
+-3.484 0.573 l
+0 0.573 l
+h
+1.352 -1.206 m
+1.606 -0.882 1.926 -0.721 2.308 -0.721 c
+3.013 -0.721 3.37 -1.191 3.381 -2.132 c
+3.381 -4.777 l
+2.734 -4.777 l
+2.734 -2.161 l
+2.734 -1.849 2.679 -1.628 2.572 -1.5 c
+2.462 -1.374 2.308 -1.309 2.102 -1.309 c
+1.944 -1.309 1.797 -1.363 1.661 -1.47 c
+1.532 -1.58 1.429 -1.716 1.352 -1.881 c
+1.352 -4.777 l
+0.706 -4.777 l
+0.706 0.867 l
+1.352 0.867 l
+h
+6.379 -4.777 m
+6.339 -4.69 6.313 -4.542 6.306 -4.337 c
+6.071 -4.682 5.777 -4.851 5.424 -4.851 c
+5.06 -4.851 4.777 -4.755 4.571 -4.557 c
+4.373 -4.351 4.278 -4.065 4.278 -3.69 c
+4.278 -3.289 4.413 -2.97 4.689 -2.735 c
+4.961 -2.492 5.336 -2.367 5.806 -2.367 c
+6.291 -2.367 l
+6.291 -1.941 l
+6.291 -1.706 6.236 -1.54 6.13 -1.441 c
+6.019 -1.334 5.857 -1.279 5.644 -1.279 c
+5.446 -1.279 5.284 -1.338 5.159 -1.455 c
+5.041 -1.573 4.983 -1.72 4.983 -1.897 c
+4.336 -1.897 l
+4.336 -1.702 4.395 -1.511 4.513 -1.324 c
+4.638 -1.139 4.8 -0.992 4.997 -0.882 c
+5.203 -0.775 5.431 -0.721 5.689 -0.721 c
+6.089 -0.721 6.394 -0.823 6.6 -1.029 c
+6.813 -1.235 6.927 -1.529 6.938 -1.912 c
+6.938 -3.925 l
+6.938 -4.23 6.975 -4.495 7.056 -4.719 c
+7.056 -4.777 l
+h
+5.512 -4.263 m
+5.677 -4.263 5.828 -4.219 5.968 -4.131 c
+6.115 -4.042 6.221 -3.932 6.291 -3.793 c
+6.291 -2.852 l
+5.924 -2.852 l
+5.608 -2.852 5.365 -2.922 5.189 -3.057 c
+5.012 -3.186 4.924 -3.373 4.924 -3.616 c
+4.924 -3.844 4.968 -4.009 5.056 -4.116 c
+5.145 -4.215 5.295 -4.263 5.512 -4.263 c
+8.555 -0.794 m
+8.569 -1.235 l
+8.823 -0.893 9.147 -0.721 9.54 -0.721 c
+10.246 -0.721 10.601 -1.191 10.612 -2.132 c
+10.612 -4.777 l
+9.966 -4.777 l
+9.966 -2.161 l
+9.966 -1.849 9.911 -1.628 9.804 -1.5 c
+9.694 -1.374 9.54 -1.309 9.334 -1.309 c
+9.176 -1.309 9.029 -1.363 8.893 -1.47 c
+8.764 -1.58 8.661 -1.716 8.584 -1.881 c
+8.584 -4.777 l
+7.937 -4.777 l
+7.937 -0.794 l
+h
+12.582 -2.955 m
+12.245 -3.352 l
+12.245 -4.777 l
+11.582 -4.777 l
+11.582 0.867 l
+12.245 0.867 l
+12.245 -2.514 l
+13.479 -0.794 l
+14.258 -0.794 l
+12.993 -2.455 l
+14.42 -4.777 l
+13.67 -4.777 l
+h
+16.918 -3.763 m
+16.918 -3.616 16.864 -3.495 16.756 -3.396 c
+16.646 -3.3 16.44 -3.183 16.139 -3.043 c
+15.794 -2.896 15.551 -2.774 15.405 -2.675 c
+15.258 -2.569 15.148 -2.452 15.081 -2.323 c
+15.011 -2.198 14.978 -2.04 14.978 -1.852 c
+14.978 -1.529 15.096 -1.261 15.331 -1.044 c
+15.566 -0.831 15.867 -0.721 16.243 -0.721 c
+16.625 -0.721 16.933 -0.834 17.168 -1.058 c
+17.404 -1.286 17.521 -1.573 17.521 -1.926 c
+16.874 -1.926 l
+16.874 -1.75 16.816 -1.598 16.698 -1.47 c
+16.581 -1.345 16.426 -1.279 16.243 -1.279 c
+16.044 -1.279 15.893 -1.334 15.787 -1.441 c
+15.676 -1.54 15.625 -1.673 15.625 -1.837 c
+15.625 -1.966 15.661 -2.072 15.742 -2.161 c
+15.819 -2.242 16.01 -2.344 16.316 -2.469 c
+16.794 -2.657 17.124 -2.845 17.301 -3.028 c
+17.477 -3.205 17.565 -3.433 17.565 -3.705 c
+17.565 -4.057 17.44 -4.337 17.198 -4.542 c
+16.962 -4.748 16.646 -4.851 16.257 -4.851 c
+15.835 -4.851 15.497 -4.734 15.243 -4.499 c
+14.986 -4.256 14.861 -3.95 14.861 -3.587 c
+15.507 -3.587 l
+15.515 -3.815 15.584 -3.991 15.713 -4.116 c
+15.838 -4.233 16.022 -4.293 16.257 -4.293 c
+16.47 -4.293 16.632 -4.245 16.742 -4.146 c
+16.86 -4.05 16.918 -3.921 16.918 -3.763 c
+23.518 0.162 m
+23.518 -0.794 l
+24.122 -0.794 l
+24.122 -1.324 l
+23.518 -1.324 l
+23.518 -3.793 l
+23.518 -3.95 23.54 -4.068 23.592 -4.146 c
+23.651 -4.226 23.739 -4.263 23.856 -4.263 c
+23.945 -4.263 24.033 -4.248 24.122 -4.219 c
+24.122 -4.777 l
+23.974 -4.825 23.82 -4.851 23.665 -4.851 c
+23.408 -4.851 23.214 -4.759 23.077 -4.572 c
+22.938 -4.388 22.871 -4.127 22.871 -3.793 c
+22.871 -1.324 l
+22.269 -1.324 l
+22.269 -0.794 l
+22.871 -0.794 l
+22.871 0.162 l
+h
+24.679 -2.602 m
+24.679 -2.025 24.816 -1.569 25.091 -1.235 c
+25.375 -0.893 25.745 -0.721 26.208 -0.721 c
+26.668 -0.721 27.035 -0.89 27.311 -1.22 c
+27.594 -1.544 27.741 -1.992 27.752 -2.558 c
+27.752 -2.984 l
+27.752 -3.554 27.609 -4.009 27.326 -4.351 c
+27.05 -4.686 26.682 -4.851 26.223 -4.851 c
+25.76 -4.851 25.389 -4.69 25.106 -4.366 c
+24.83 -4.035 24.687 -3.595 24.679 -3.043 c
+h
+25.327 -2.984 m
+25.327 -3.389 25.404 -3.705 25.562 -3.94 c
+25.727 -4.175 25.947 -4.293 26.223 -4.293 c
+26.788 -4.293 27.083 -3.881 27.105 -3.057 c
+27.105 -2.602 l
+27.105 -2.201 27.021 -1.881 26.855 -1.646 c
+26.697 -1.404 26.48 -1.279 26.208 -1.279 c
+25.944 -1.279 25.727 -1.404 25.562 -1.646 c
+25.404 -1.881 25.327 -2.201 25.327 -2.602 c
+h
+33.701 0.162 m
+33.701 -0.794 l
+34.304 -0.794 l
+34.304 -1.324 l
+33.701 -1.324 l
+33.701 -3.793 l
+33.701 -3.95 33.724 -4.068 33.774 -4.146 c
+33.834 -4.226 33.922 -4.263 34.04 -4.263 c
+34.127 -4.263 34.216 -4.248 34.304 -4.219 c
+34.304 -4.777 l
+34.157 -4.825 34.002 -4.851 33.848 -4.851 c
+33.591 -4.851 33.396 -4.759 33.26 -4.572 c
+33.121 -4.388 33.055 -4.127 33.055 -3.793 c
+33.055 -1.324 l
+32.452 -1.324 l
+32.452 -0.794 l
+33.055 -0.794 l
+33.055 0.162 l
+h
+35.715 -1.206 m
+35.968 -0.882 36.288 -0.721 36.67 -0.721 c
+37.376 -0.721 37.732 -1.191 37.743 -2.132 c
+37.743 -4.777 l
+37.097 -4.777 l
+37.097 -2.161 l
+37.097 -1.849 37.042 -1.628 36.935 -1.5 c
+36.824 -1.374 36.67 -1.309 36.465 -1.309 c
+36.307 -1.309 36.159 -1.363 36.024 -1.47 c
+35.895 -1.58 35.792 -1.716 35.715 -1.881 c
+35.715 -4.777 l
+35.068 -4.777 l
+35.068 0.867 l
+35.715 0.867 l
+h
+39.405 -4.777 -0.647 3.983 re
+39.449 0.249 m
+39.449 0.139 39.419 0.048 39.361 -0.03 c
+39.301 -0.1 39.206 -0.133 39.081 -0.133 c
+38.964 -0.133 38.868 -0.1 38.802 -0.03 c
+38.743 0.048 38.713 0.139 38.713 0.249 c
+38.713 0.367 38.743 0.459 38.802 0.529 c
+38.868 0.606 38.964 0.646 39.081 0.646 c
+39.206 0.646 39.301 0.606 39.361 0.529 c
+39.419 0.448 39.449 0.357 39.449 0.249 c
+42.359 -3.763 m
+42.359 -3.616 42.304 -3.495 42.197 -3.396 c
+42.087 -3.3 41.881 -3.183 41.58 -3.043 c
+41.234 -2.896 40.992 -2.774 40.845 -2.675 c
+40.698 -2.569 40.587 -2.452 40.521 -2.323 c
+40.452 -2.198 40.419 -2.04 40.419 -1.852 c
+40.419 -1.529 40.536 -1.261 40.772 -1.044 c
+41.007 -0.831 41.308 -0.721 41.683 -0.721 c
+42.065 -0.721 42.374 -0.834 42.609 -1.058 c
+42.844 -1.286 42.962 -1.573 42.962 -1.926 c
+42.314 -1.926 l
+42.314 -1.75 42.256 -1.598 42.139 -1.47 c
+42.021 -1.345 41.867 -1.279 41.683 -1.279 c
+41.485 -1.279 41.333 -1.334 41.227 -1.441 c
+41.117 -1.54 41.065 -1.673 41.065 -1.837 c
+41.065 -1.966 41.102 -2.072 41.183 -2.161 c
+41.26 -2.242 41.451 -2.344 41.757 -2.469 c
+42.234 -2.657 42.565 -2.845 42.742 -3.028 c
+42.917 -3.205 43.006 -3.433 43.006 -3.705 c
+43.006 -4.057 42.881 -4.337 42.638 -4.542 c
+42.403 -4.748 42.087 -4.851 41.697 -4.851 c
+41.275 -4.851 40.937 -4.734 40.683 -4.499 c
+40.426 -4.256 40.301 -3.95 40.301 -3.587 c
+40.948 -3.587 l
+40.955 -3.815 41.025 -3.991 41.154 -4.116 c
+41.279 -4.233 41.462 -4.293 41.697 -4.293 c
+41.911 -4.293 42.073 -4.245 42.183 -4.146 c
+42.3 -4.05 42.359 -3.921 42.359 -3.763 c
+48.279 -4.777 m
+48.279 -1.324 l
+47.764 -1.324 l
+47.764 -0.794 l
+48.279 -0.794 l
+48.279 -0.426 l
+48.286 0.004 48.4 0.338 48.617 0.573 c
+48.841 0.816 49.154 0.941 49.558 0.941 c
+49.705 0.941 49.844 0.918 49.984 0.881 c
+50.131 0.841 50.282 0.786 50.44 0.72 c
+50.322 0.147 l
+50.087 0.272 49.844 0.338 49.601 0.338 c
+49.356 0.338 49.183 0.268 49.088 0.132 c
+48.988 0.004 48.94 -0.191 48.94 -0.456 c
+48.94 -0.794 l
+49.587 -0.794 l
+49.587 -1.324 l
+48.94 -1.324 l
+48.94 -4.777 l
+h
+50.748 -4.777 -0.646 3.983 re
+52.498 -4.777 -0.647 5.644 re
+54.937 -4.851 m
+54.438 -4.851 54.056 -4.704 53.791 -4.41 c
+53.526 -4.116 53.394 -3.682 53.394 -3.102 c
+53.394 -2.631 l
+53.394 -2.036 53.52 -1.569 53.776 -1.235 c
+54.041 -0.893 54.401 -0.721 54.864 -0.721 c
+55.324 -0.721 55.665 -0.875 55.893 -1.176 c
+56.128 -1.47 56.25 -1.933 56.261 -2.558 c
+56.261 -2.984 l
+54.041 -2.984 l
+54.041 -3.072 l
+54.041 -3.506 54.118 -3.818 54.276 -4.013 c
+54.442 -4.2 54.673 -4.293 54.967 -4.293 c
+55.162 -4.293 55.334 -4.26 55.481 -4.189 c
+55.629 -4.112 55.764 -3.994 55.893 -3.836 c
+56.231 -4.248 l
+55.945 -4.653 55.515 -4.851 54.937 -4.851 c
+54.864 -1.279 m
+54.588 -1.279 54.386 -1.374 54.262 -1.559 c
+54.133 -1.746 54.06 -2.036 54.041 -2.425 c
+55.614 -2.425 l
+55.614 -2.338 l
+55.592 -1.955 55.525 -1.687 55.408 -1.529 c
+55.29 -1.363 55.107 -1.279 54.864 -1.279 c
+64.738 -4.116 m
+64.62 -4.263 l
+64.286 -4.656 63.791 -4.851 63.136 -4.851 c
+62.555 -4.851 62.1 -4.659 61.769 -4.278 c
+61.445 -3.896 61.277 -3.352 61.269 -2.646 c
+61.269 -1.602 l
+61.269 -0.849 61.416 -0.287 61.711 0.087 c
+62.012 0.459 62.463 0.646 63.062 0.646 c
+63.57 0.646 63.967 0.503 64.253 0.22 c
+64.547 -0.067 64.709 -0.47 64.738 -1 c
+64.062 -1 l
+64.04 -0.669 63.948 -0.408 63.783 -0.221 c
+63.625 -0.026 63.39 0.073 63.078 0.073 c
+62.684 0.073 62.401 -0.055 62.224 -0.309 c
+62.048 -0.566 61.952 -0.967 61.946 -1.515 c
+61.946 -2.602 l
+61.946 -3.142 62.048 -3.558 62.254 -3.851 c
+62.459 -4.138 62.754 -4.278 63.136 -4.278 c
+63.496 -4.278 63.776 -4.189 63.974 -4.013 c
+64.062 -3.925 l
+64.062 -2.691 l
+63.092 -2.691 l
+63.092 -2.117 l
+64.738 -2.117 l
+h
+66.458 -4.777 -0.646 3.983 re
+66.502 0.249 m
+66.502 0.139 66.473 0.048 66.414 -0.03 c
+66.355 -0.1 66.26 -0.133 66.135 -0.133 c
+66.017 -0.133 65.921 -0.1 65.856 -0.03 c
+65.796 0.048 65.767 0.139 65.767 0.249 c
+65.767 0.367 65.796 0.459 65.856 0.529 c
+65.921 0.606 66.017 0.646 66.135 0.646 c
+66.26 0.646 66.355 0.606 66.414 0.529 c
+66.473 0.448 66.502 0.357 66.502 0.249 c
+68.325 0.162 m
+68.325 -0.794 l
+68.927 -0.794 l
+68.927 -1.324 l
+68.325 -1.324 l
+68.325 -3.793 l
+68.325 -3.95 68.347 -4.068 68.398 -4.146 c
+68.457 -4.226 68.545 -4.263 68.663 -4.263 c
+68.751 -4.263 68.84 -4.248 68.927 -4.219 c
+68.927 -4.777 l
+68.78 -4.825 68.626 -4.851 68.472 -4.851 c
+68.215 -4.851 68.02 -4.759 67.884 -4.572 c
+67.745 -4.388 67.678 -4.127 67.678 -3.793 c
+67.678 -1.324 l
+67.076 -1.324 l
+67.076 -0.794 l
+67.678 -0.794 l
+67.678 0.162 l
+h
+76.921 -3.631 m
+77.523 -0.794 l
+78.17 -0.794 l
+77.185 -4.777 l
+76.67 -4.777 l
+75.891 -1.926 l
+75.142 -4.777 l
+74.612 -4.777 l
+73.657 -0.794 l
+74.289 -0.794 l
+74.906 -3.558 l
+75.641 -0.794 l
+76.156 -0.794 l
+h
+79.551 -4.777 -0.646 3.983 re
+79.595 0.249 m
+79.595 0.139 79.566 0.048 79.508 -0.03 c
+79.448 -0.1 79.353 -0.133 79.228 -0.133 c
+79.111 -0.133 79.015 -0.1 78.949 -0.03 c
+78.889 0.048 78.86 0.139 78.86 0.249 c
+78.86 0.367 78.889 0.459 78.949 0.529 c
+79.015 0.606 79.111 0.646 79.228 0.646 c
+79.353 0.646 79.448 0.606 79.508 0.529 c
+79.566 0.448 79.595 0.357 79.595 0.249 c
+81.271 -4.777 -0.647 5.644 re
+82.991 -4.777 -0.647 5.644 re
+88.973 -4.777 -0.646 3.983 re
+89.017 0.249 m
+89.017 0.139 88.988 0.048 88.929 -0.03 c
+88.871 -0.1 88.775 -0.133 88.65 -0.133 c
+88.532 -0.133 88.437 -0.1 88.37 -0.03 c
+88.312 0.048 88.283 0.139 88.283 0.249 c
+88.283 0.367 88.312 0.459 88.37 0.529 c
+88.437 0.606 88.532 0.646 88.65 0.646 c
+88.775 0.646 88.871 0.606 88.929 0.529 c
+88.988 0.448 89.017 0.357 89.017 0.249 c
+89.856 -2.602 m
+89.856 -1.985 89.966 -1.521 90.193 -1.206 c
+90.417 -0.882 90.752 -0.721 91.192 -0.721 c
+91.593 -0.721 91.898 -0.897 92.104 -1.249 c
+92.148 -0.794 l
+92.736 -0.794 l
+92.736 -4.821 l
+92.736 -5.31 92.607 -5.689 92.354 -5.953 c
+92.096 -6.218 91.744 -6.35 91.296 -6.35 c
+91.097 -6.35 90.877 -6.299 90.635 -6.203 c
+90.388 -6.104 90.208 -5.983 90.091 -5.835 c
+90.355 -5.395 l
+90.62 -5.659 90.917 -5.792 91.252 -5.792 c
+91.788 -5.792 92.064 -5.498 92.075 -4.91 c
+92.075 -4.381 l
+91.869 -4.696 91.568 -4.851 91.178 -4.851 c
+90.766 -4.851 90.444 -4.7 90.208 -4.395 c
+89.98 -4.083 89.862 -3.631 89.856 -3.043 c
+h
+90.517 -2.984 m
+90.517 -3.425 90.579 -3.755 90.708 -3.969 c
+90.833 -4.175 91.049 -4.278 91.354 -4.278 c
+91.678 -4.278 91.917 -4.112 92.075 -3.778 c
+92.075 -1.794 l
+91.906 -1.47 91.667 -1.309 91.354 -1.309 c
+91.061 -1.309 90.843 -1.411 90.708 -1.617 c
+90.579 -1.823 90.517 -2.147 90.517 -2.587 c
+h
+94.309 -0.794 m
+94.324 -1.235 l
+94.577 -0.893 94.901 -0.721 95.294 -0.721 c
+96 -0.721 96.356 -1.191 96.367 -2.132 c
+96.367 -4.777 l
+95.72 -4.777 l
+95.72 -2.161 l
+95.72 -1.849 95.665 -1.628 95.558 -1.5 c
+95.448 -1.374 95.294 -1.309 95.088 -1.309 c
+94.93 -1.309 94.783 -1.363 94.647 -1.47 c
+94.519 -1.58 94.415 -1.716 94.338 -1.881 c
+94.338 -4.777 l
+93.692 -4.777 l
+93.692 -0.794 l
+h
+97.205 -2.602 m
+97.205 -2.025 97.341 -1.569 97.617 -1.235 c
+97.899 -0.893 98.271 -0.721 98.733 -0.721 c
+99.192 -0.721 99.56 -0.89 99.836 -1.22 c
+100.119 -1.544 100.266 -1.992 100.277 -2.558 c
+100.277 -2.984 l
+100.277 -3.554 100.133 -4.009 99.851 -4.351 c
+99.575 -4.686 99.208 -4.851 98.748 -4.851 c
+98.285 -4.851 97.914 -4.69 97.631 -4.366 c
+97.355 -4.035 97.212 -3.595 97.205 -3.043 c
+h
+97.852 -2.984 m
+97.852 -3.389 97.929 -3.705 98.087 -3.94 c
+98.252 -4.175 98.473 -4.293 98.748 -4.293 c
+99.314 -4.293 99.608 -3.881 99.63 -3.057 c
+99.63 -2.602 l
+99.63 -2.201 99.545 -1.881 99.381 -1.646 c
+99.223 -1.404 99.005 -1.279 98.733 -1.279 c
+98.469 -1.279 98.252 -1.404 98.087 -1.646 c
+97.929 -1.881 97.852 -2.201 97.852 -2.602 c
+h
+102.761 -1.411 m
+102.673 -1.393 102.574 -1.382 102.467 -1.382 c
+102.132 -1.382 101.897 -1.565 101.762 -1.926 c
+101.762 -4.777 l
+101.114 -4.777 l
+101.114 -0.794 l
+101.747 -0.794 l
+101.762 -1.206 l
+101.938 -0.882 102.18 -0.721 102.496 -0.721 c
+102.603 -0.721 102.691 -0.742 102.761 -0.779 c
+h
+104.76 -4.851 m
+104.26 -4.851 103.878 -4.704 103.614 -4.41 c
+103.349 -4.116 103.217 -3.682 103.217 -3.102 c
+103.217 -2.631 l
+103.217 -2.036 103.342 -1.569 103.599 -1.235 c
+103.863 -0.893 104.224 -0.721 104.686 -0.721 c
+105.145 -0.721 105.488 -0.875 105.716 -1.176 c
+105.951 -1.47 106.072 -1.933 106.083 -2.558 c
+106.083 -2.984 l
+103.863 -2.984 l
+103.863 -3.072 l
+103.863 -3.506 103.94 -3.818 104.098 -4.013 c
+104.264 -4.2 104.495 -4.293 104.79 -4.293 c
+104.985 -4.293 105.157 -4.26 105.304 -4.189 c
+105.451 -4.112 105.587 -3.994 105.716 -3.836 c
+106.053 -4.248 l
+105.767 -4.653 105.337 -4.851 104.76 -4.851 c
+104.686 -1.279 m
+104.411 -1.279 104.209 -1.374 104.084 -1.559 c
+103.955 -1.746 103.882 -2.036 103.863 -2.425 c
+105.436 -2.425 l
+105.436 -2.338 l
+105.415 -1.955 105.348 -1.687 105.23 -1.529 c
+105.113 -1.363 104.929 -1.279 104.686 -1.279 c
+113.164 -4.777 m
+113.124 -4.69 113.099 -4.542 113.091 -4.337 c
+112.856 -4.682 112.561 -4.851 112.209 -4.851 c
+111.845 -4.851 111.562 -4.755 111.356 -4.557 c
+111.158 -4.351 111.063 -4.065 111.063 -3.69 c
+111.063 -3.289 111.198 -2.97 111.474 -2.735 c
+111.746 -2.492 112.121 -2.367 112.591 -2.367 c
+113.076 -2.367 l
+113.076 -1.941 l
+113.076 -1.706 113.021 -1.54 112.914 -1.441 c
+112.804 -1.334 112.642 -1.279 112.43 -1.279 c
+112.231 -1.279 112.069 -1.338 111.944 -1.455 c
+111.827 -1.573 111.768 -1.72 111.768 -1.897 c
+111.121 -1.897 l
+111.121 -1.702 111.18 -1.511 111.298 -1.324 c
+111.422 -1.139 111.584 -0.992 111.782 -0.882 c
+111.988 -0.775 112.216 -0.721 112.474 -0.721 c
+112.874 -0.721 113.179 -0.823 113.385 -1.029 c
+113.598 -1.235 113.712 -1.529 113.723 -1.912 c
+113.723 -3.925 l
+113.723 -4.23 113.76 -4.495 113.841 -4.719 c
+113.841 -4.777 l
+h
+112.297 -4.263 m
+112.463 -4.263 112.613 -4.219 112.752 -4.131 c
+112.9 -4.042 113.006 -3.932 113.076 -3.793 c
+113.076 -2.852 l
+112.709 -2.852 l
+112.393 -2.852 112.15 -2.922 111.973 -3.057 c
+111.797 -3.186 111.709 -3.373 111.709 -3.616 c
+111.709 -3.844 111.753 -4.009 111.842 -4.116 c
+111.929 -4.215 112.081 -4.263 112.297 -4.263 c
+115.428 -4.777 -0.646 5.644 re
+117.147 -4.777 -0.646 5.644 re
+122.597 -4.777 m
+122.597 -1.324 l
+122.083 -1.324 l
+122.083 -0.794 l
+122.597 -0.794 l
+122.597 -0.426 l
+122.605 0.004 122.719 0.338 122.936 0.573 c
+123.16 0.816 123.472 0.941 123.877 0.941 c
+124.023 0.941 124.163 0.918 124.303 0.881 c
+124.449 0.841 124.6 0.786 124.758 0.72 c
+124.64 0.147 l
+124.405 0.272 124.163 0.338 123.92 0.338 c
+123.674 0.338 123.501 0.268 123.406 0.132 c
+123.306 0.004 123.258 -0.191 123.258 -0.456 c
+123.258 -0.794 l
+123.906 -0.794 l
+123.906 -1.324 l
+123.258 -1.324 l
+123.258 -4.777 l
+h
+125.067 -4.777 -0.646 3.983 re
+126.816 -4.777 -0.647 5.644 re
+129.256 -4.851 m
+128.756 -4.851 128.374 -4.704 128.11 -4.41 c
+127.845 -4.116 127.713 -3.682 127.713 -3.102 c
+127.713 -2.631 l
+127.713 -2.036 127.838 -1.569 128.095 -1.235 c
+128.359 -0.893 128.719 -0.721 129.182 -0.721 c
+129.642 -0.721 129.984 -0.875 130.212 -1.176 c
+130.447 -1.47 130.568 -1.933 130.579 -2.558 c
+130.579 -2.984 l
+128.359 -2.984 l
+128.359 -3.072 l
+128.359 -3.506 128.436 -3.818 128.594 -4.013 c
+128.76 -4.2 128.991 -4.293 129.286 -4.293 c
+129.481 -4.293 129.653 -4.26 129.799 -4.189 c
+129.947 -4.112 130.083 -3.994 130.212 -3.836 c
+130.549 -4.248 l
+130.263 -4.653 129.833 -4.851 129.256 -4.851 c
+129.182 -1.279 m
+128.907 -1.279 128.704 -1.374 128.58 -1.559 c
+128.451 -1.746 128.378 -2.036 128.359 -2.425 c
+129.932 -2.425 l
+129.932 -2.338 l
+129.91 -1.955 129.844 -1.687 129.726 -1.529 c
+129.608 -1.363 129.425 -1.279 129.182 -1.279 c
+133.298 -3.763 m
+133.298 -3.616 133.244 -3.495 133.136 -3.396 c
+133.026 -3.3 132.82 -3.183 132.519 -3.043 c
+132.174 -2.896 131.931 -2.774 131.784 -2.675 c
+131.638 -2.569 131.527 -2.452 131.461 -2.323 c
+131.391 -2.198 131.358 -2.04 131.358 -1.852 c
+131.358 -1.529 131.476 -1.261 131.711 -1.044 c
+131.946 -0.831 132.247 -0.721 132.622 -0.721 c
+133.005 -0.721 133.313 -0.834 133.548 -1.058 c
+133.783 -1.286 133.901 -1.573 133.901 -1.926 c
+133.254 -1.926 l
+133.254 -1.75 133.196 -1.598 133.078 -1.47 c
+132.96 -1.345 132.806 -1.279 132.622 -1.279 c
+132.424 -1.279 132.273 -1.334 132.166 -1.441 c
+132.056 -1.54 132.005 -1.673 132.005 -1.837 c
+132.005 -1.966 132.041 -2.072 132.122 -2.161 c
+132.199 -2.242 132.39 -2.344 132.696 -2.469 c
+133.173 -2.657 133.504 -2.845 133.681 -3.028 c
+133.857 -3.205 133.945 -3.433 133.945 -3.705 c
+133.945 -4.057 133.82 -4.337 133.577 -4.542 c
+133.342 -4.748 133.026 -4.851 132.637 -4.851 c
+132.214 -4.851 131.877 -4.734 131.623 -4.499 c
+131.366 -4.256 131.241 -3.95 131.241 -3.587 c
+131.887 -3.587 l
+131.894 -3.815 131.964 -3.991 132.093 -4.116 c
+132.218 -4.233 132.402 -4.293 132.637 -4.293 c
+132.85 -4.293 133.012 -4.245 133.122 -4.146 c
+133.24 -4.05 133.298 -3.921 133.298 -3.763 c
+139.748 -4.777 -0.647 3.983 re
+139.792 0.249 m
+139.792 0.139 139.762 0.048 139.704 -0.03 c
+139.644 -0.1 139.549 -0.133 139.424 -0.133 c
+139.307 -0.133 139.211 -0.1 139.145 -0.03 c
+139.086 0.048 139.056 0.139 139.056 0.249 c
+139.056 0.367 139.086 0.459 139.145 0.529 c
+139.211 0.606 139.307 0.646 139.424 0.646 c
+139.549 0.646 139.644 0.606 139.704 0.529 c
+139.762 0.448 139.792 0.357 139.792 0.249 c
+141.379 -0.794 m
+141.394 -1.235 l
+141.647 -0.893 141.971 -0.721 142.364 -0.721 c
+143.07 -0.721 143.426 -1.191 143.437 -2.132 c
+143.437 -4.777 l
+142.79 -4.777 l
+142.79 -2.161 l
+142.79 -1.849 142.735 -1.628 142.628 -1.5 c
+142.518 -1.374 142.364 -1.309 142.158 -1.309 c
+142 -1.309 141.853 -1.363 141.717 -1.47 c
+141.589 -1.58 141.485 -1.716 141.408 -1.881 c
+141.408 -4.777 l
+140.762 -4.777 l
+140.762 -0.794 l
+h
+f
+Q
+190.482 115.427 -1.043 5.644 re
+191.172 117.544 m
+191.172 118.15 191.312 118.624 191.599 118.969 c
+191.882 119.311 192.275 119.484 192.775 119.484 c
+193.282 119.484 193.678 119.311 193.965 118.969 c
+194.249 118.624 194.392 118.15 194.392 117.544 c
+194.392 117.278 l
+194.392 116.68 194.249 116.21 193.965 115.867 c
+193.678 115.522 193.282 115.353 192.775 115.353 c
+192.264 115.353 191.867 115.522 191.584 115.867 c
+191.309 116.21 191.172 116.684 191.172 117.293 c
+h
+192.217 117.278 m
+192.217 116.573 192.4 116.22 192.775 116.22 c
+193.128 116.22 193.319 116.515 193.348 117.102 c
+193.348 117.544 l
+193.348 117.903 193.296 118.175 193.201 118.352 c
+193.102 118.528 192.959 118.616 192.775 118.616 c
+192.598 118.616 192.459 118.528 192.363 118.352 c
+192.264 118.175 192.217 117.903 192.217 117.544 c
+h
+194.906 117.544 m
+194.906 118.19 195.024 118.675 195.259 118.998 c
+195.494 119.322 195.825 119.484 196.259 119.484 c
+196.612 119.484 196.884 119.34 197.082 119.057 c
+197.126 119.41 l
+198.067 119.41 l
+198.067 115.427 l
+198.067 114.92 197.923 114.53 197.64 114.265 c
+197.354 113.993 196.949 113.854 196.421 113.854 c
+196.192 113.854 195.957 113.898 195.715 113.986 c
+195.48 114.074 195.303 114.188 195.185 114.324 c
+195.538 115.044 l
+195.634 114.938 195.762 114.853 195.92 114.795 c
+196.074 114.728 196.222 114.691 196.361 114.691 c
+196.597 114.691 196.762 114.751 196.861 114.868 c
+196.968 114.978 197.023 115.155 197.023 115.397 c
+197.023 115.75 l
+196.824 115.485 196.567 115.353 196.244 115.353 c
+195.821 115.353 195.494 115.515 195.259 115.838 c
+195.031 116.169 194.914 116.64 194.906 117.249 c
+h
+195.95 117.278 m
+195.95 116.904 195.997 116.636 196.097 116.47 c
+196.192 116.301 196.346 116.22 196.552 116.22 c
+196.766 116.22 196.924 116.297 197.023 116.455 c
+197.023 118.352 l
+196.913 118.517 196.758 118.602 196.552 118.602 c
+196.346 118.602 196.192 118.517 196.097 118.352 c
+195.997 118.182 195.95 117.914 195.95 117.544 c
+h
+200.595 116.499 m
+200.595 116.588 200.551 116.665 200.462 116.735 c
+200.375 116.812 200.186 116.915 199.904 117.043 c
+199.471 117.22 199.172 117.4 199.008 117.587 c
+198.85 117.771 198.773 118.003 198.773 118.278 c
+198.773 118.62 198.893 118.903 199.139 119.131 c
+199.393 119.366 199.731 119.484 200.154 119.484 c
+200.583 119.484 200.932 119.37 201.198 119.146 c
+201.462 118.918 201.595 118.616 201.595 118.234 c
+200.551 118.234 l
+200.551 118.558 200.411 118.72 200.139 118.72 c
+200.028 118.72 199.941 118.683 199.874 118.616 c
+199.805 118.547 199.772 118.448 199.772 118.323 c
+199.772 118.234 199.808 118.153 199.889 118.087 c
+199.966 118.028 200.147 117.933 200.433 117.808 c
+200.863 117.65 201.161 117.473 201.329 117.278 c
+201.506 117.091 201.595 116.842 201.595 116.529 c
+201.595 116.176 201.462 115.89 201.198 115.676 c
+200.932 115.46 200.583 115.353 200.154 115.353 c
+199.86 115.353 199.598 115.408 199.375 115.515 c
+199.147 115.632 198.971 115.794 198.846 116 c
+198.728 116.206 198.669 116.426 198.669 116.661 c
+199.654 116.661 l
+199.654 116.474 199.691 116.338 199.772 116.25 c
+199.86 116.162 199.992 116.118 200.169 116.118 c
+200.452 116.118 200.595 116.243 200.595 116.499 c
+f
+q 1 0 0 1 206.4894 117.602 cm
+0 0 m
+0 0.607 0.11 1.073 0.338 1.396 c
+0.573 1.72 0.9 1.881 1.323 1.881 c
+1.705 1.881 2.003 1.723 2.219 1.411 c
+2.219 3.469 l
+2.866 3.469 l
+2.866 -2.175 l
+2.278 -2.175 l
+2.234 -1.749 l
+2.028 -2.084 1.723 -2.249 1.323 -2.249 c
+0.911 -2.249 0.588 -2.094 0.353 -1.779 c
+0.118 -1.455 0 -0.999 0 -0.411 c
+h
+0.646 -0.382 m
+0.646 -0.823 0.709 -1.153 0.837 -1.367 c
+0.974 -1.573 1.194 -1.675 1.499 -1.675 c
+1.822 -1.675 2.061 -1.514 2.219 -1.191 c
+2.219 0.823 l
+2.05 1.135 1.811 1.294 1.499 1.294 c
+1.194 1.294 0.974 1.191 0.837 0.985 c
+0.709 0.779 0.646 0.455 0.646 0.015 c
+h
+4.571 -2.175 -0.646 3.983 re
+4.615 2.851 m
+4.615 2.741 4.586 2.65 4.527 2.572 c
+4.469 2.502 4.373 2.469 4.247 2.469 c
+4.13 2.469 4.035 2.502 3.968 2.572 c
+3.91 2.65 3.881 2.741 3.881 2.851 c
+3.881 2.969 3.91 3.061 3.968 3.131 c
+4.035 3.208 4.13 3.248 4.247 3.248 c
+4.373 3.248 4.469 3.208 4.527 3.131 c
+4.586 3.05 4.615 2.959 4.615 2.851 c
+7.231 1.191 m
+7.143 1.209 7.044 1.22 6.938 1.22 c
+6.603 1.22 6.368 1.037 6.232 0.676 c
+6.232 -2.175 l
+5.585 -2.175 l
+5.585 1.808 l
+6.217 1.808 l
+6.232 1.396 l
+6.408 1.72 6.651 1.881 6.967 1.881 c
+7.073 1.881 7.162 1.86 7.231 1.823 c
+h
+9.231 -2.249 m
+8.731 -2.249 8.349 -2.102 8.084 -1.808 c
+7.819 -1.514 7.688 -1.08 7.688 -0.5 c
+7.688 -0.029 l
+7.688 0.566 7.812 1.033 8.07 1.367 c
+8.334 1.709 8.694 1.881 9.157 1.881 c
+9.616 1.881 9.959 1.727 10.186 1.426 c
+10.422 1.132 10.543 0.669 10.553 0.044 c
+10.553 -0.382 l
+8.334 -0.382 l
+8.334 -0.47 l
+8.334 -0.904 8.411 -1.216 8.569 -1.411 c
+8.735 -1.598 8.966 -1.691 9.26 -1.691 c
+9.454 -1.691 9.628 -1.658 9.774 -1.587 c
+9.922 -1.51 10.057 -1.392 10.186 -1.234 c
+10.524 -1.646 l
+10.237 -2.051 9.807 -2.249 9.231 -2.249 c
+9.157 1.323 m
+8.882 1.323 8.679 1.228 8.554 1.043 c
+8.426 0.856 8.353 0.566 8.334 0.177 c
+9.907 0.177 l
+9.907 0.264 l
+9.885 0.647 9.819 0.915 9.701 1.073 c
+9.583 1.239 9.4 1.323 9.157 1.323 c
+12.714 -1.691 m
+12.928 -1.691 13.1 -1.627 13.229 -1.5 c
+13.365 -1.363 13.438 -1.172 13.45 -0.926 c
+14.067 -0.926 l
+14.044 -1.309 13.909 -1.627 13.655 -1.881 c
+13.398 -2.128 13.086 -2.249 12.714 -2.249 c
+12.222 -2.249 11.847 -2.098 11.582 -1.793 c
+11.326 -1.481 11.2 -1.014 11.2 -0.397 c
+11.2 0.044 l
+11.2 0.64 11.326 1.095 11.582 1.411 c
+11.847 1.723 12.222 1.881 12.714 1.881 c
+13.115 1.881 13.435 1.749 13.67 1.484 c
+13.913 1.228 14.044 0.882 14.067 0.441 c
+13.45 0.441 l
+13.427 0.735 13.354 0.956 13.229 1.103 c
+13.111 1.249 12.939 1.323 12.714 1.323 c
+12.421 1.323 12.203 1.224 12.068 1.029 c
+11.928 0.842 11.854 0.533 11.847 0.103 c
+11.847 -0.411 l
+11.847 -0.881 11.914 -1.216 12.053 -1.411 c
+12.2 -1.598 12.421 -1.691 12.714 -1.691 c
+15.669 2.764 m
+15.669 1.808 l
+16.272 1.808 l
+16.272 1.278 l
+15.669 1.278 l
+15.669 -1.191 l
+15.669 -1.348 15.691 -1.466 15.742 -1.544 c
+15.802 -1.624 15.889 -1.661 16.007 -1.661 c
+16.095 -1.661 16.184 -1.646 16.272 -1.617 c
+16.272 -2.175 l
+16.124 -2.223 15.97 -2.249 15.816 -2.249 c
+15.559 -2.249 15.364 -2.157 15.228 -1.97 c
+15.089 -1.786 15.022 -1.525 15.022 -1.191 c
+15.022 1.278 l
+14.42 1.278 l
+14.42 1.808 l
+15.022 1.808 l
+15.022 2.764 l
+h
+16.83 0 m
+16.83 0.577 16.966 1.033 17.242 1.367 c
+17.525 1.709 17.896 1.881 18.359 1.881 c
+18.819 1.881 19.185 1.712 19.461 1.382 c
+19.744 1.058 19.891 0.611 19.902 0.044 c
+19.902 -0.382 l
+19.902 -0.952 19.759 -1.407 19.476 -1.749 c
+19.2 -2.084 18.833 -2.249 18.374 -2.249 c
+17.911 -2.249 17.539 -2.088 17.256 -1.764 c
+16.98 -1.433 16.837 -0.992 16.83 -0.441 c
+h
+17.477 -0.382 m
+17.477 -0.786 17.554 -1.103 17.712 -1.338 c
+17.878 -1.573 18.098 -1.691 18.374 -1.691 c
+18.939 -1.691 19.233 -1.278 19.255 -0.455 c
+19.255 0 l
+19.255 0.401 19.171 0.721 19.006 0.956 c
+18.848 1.199 18.63 1.323 18.359 1.323 c
+18.094 1.323 17.878 1.199 17.712 0.956 c
+17.554 0.721 17.477 0.401 17.477 0 c
+h
+22.387 1.191 m
+22.298 1.209 22.199 1.22 22.092 1.22 c
+21.758 1.22 21.523 1.037 21.387 0.676 c
+21.387 -2.175 l
+20.74 -2.175 l
+20.74 1.808 l
+21.372 1.808 l
+21.387 1.396 l
+21.564 1.72 21.805 1.881 22.122 1.881 c
+22.229 1.881 22.316 1.86 22.387 1.823 c
+h
+24.194 -1.087 m
+24.915 1.808 l
+25.605 1.808 l
+24.312 -2.734 l
+24.213 -3.075 24.07 -3.337 23.885 -3.513 c
+23.709 -3.69 23.507 -3.778 23.283 -3.778 c
+23.195 -3.778 23.081 -3.755 22.945 -3.719 c
+22.945 -3.175 l
+23.092 -3.19 l
+23.276 -3.19 23.423 -3.146 23.533 -3.057 c
+23.64 -2.969 23.727 -2.811 23.798 -2.587 c
+23.915 -2.146 l
+22.754 1.808 l
+23.459 1.808 l
+h
+30.482 0 m
+30.482 0.636 30.57 1.239 30.746 1.808 c
+30.923 2.374 31.166 2.87 31.482 3.293 c
+31.677 3.557 31.864 3.748 32.04 3.865 c
+32.172 3.41 l
+31.878 3.135 31.636 2.712 31.452 2.146 c
+31.265 1.577 31.162 0.945 31.143 0.25 c
+31.143 -0.044 l
+31.143 -0.908 31.261 -1.672 31.496 -2.337 c
+31.679 -2.837 31.908 -3.219 32.172 -3.484 c
+32.04 -3.91 l
+31.812 -3.752 31.588 -3.502 31.364 -3.16 c
+30.776 -2.278 30.482 -1.228 30.482 0 c
+34.289 -2.249 m
+33.789 -2.249 33.407 -2.102 33.142 -1.808 c
+32.878 -1.514 32.745 -1.08 32.745 -0.5 c
+32.745 -0.029 l
+32.745 0.566 32.87 1.033 33.128 1.367 c
+33.392 1.709 33.753 1.881 34.216 1.881 c
+34.675 1.881 35.016 1.727 35.245 1.426 c
+35.48 1.132 35.6 0.669 35.612 0.044 c
+35.612 -0.382 l
+33.392 -0.382 l
+33.392 -0.47 l
+33.392 -0.904 33.47 -1.216 33.628 -1.411 c
+33.793 -1.598 34.025 -1.691 34.318 -1.691 c
+34.513 -1.691 34.686 -1.658 34.833 -1.587 c
+34.98 -1.51 35.116 -1.392 35.245 -1.234 c
+35.583 -1.646 l
+35.296 -2.051 34.866 -2.249 34.289 -2.249 c
+34.216 1.323 m
+33.94 1.323 33.738 1.228 33.613 1.043 c
+33.484 0.856 33.41 0.566 33.392 0.177 c
+34.965 0.177 l
+34.965 0.264 l
+34.943 0.647 34.877 0.915 34.759 1.073 c
+34.642 1.239 34.458 1.323 34.216 1.323 c
+37.537 0.353 m
+38.228 1.808 l
+38.978 1.808 l
+37.89 -0.162 l
+39.008 -2.175 l
+38.258 -2.175 l
+37.552 -0.691 l
+36.847 -2.175 l
+36.097 -2.175 l
+37.2 -0.162 l
+36.126 1.808 l
+36.876 1.808 l
+h
+41.007 -1.691 m
+41.219 -1.691 41.393 -1.627 41.52 -1.5 c
+41.657 -1.363 41.73 -1.172 41.742 -0.926 c
+42.359 -0.926 l
+42.337 -1.309 42.201 -1.627 41.948 -1.881 c
+41.69 -2.128 41.377 -2.249 41.007 -2.249 c
+40.514 -2.249 40.139 -2.098 39.874 -1.793 c
+39.617 -1.481 39.492 -1.014 39.492 -0.397 c
+39.492 0.044 l
+39.492 0.64 39.617 1.095 39.874 1.411 c
+40.139 1.723 40.514 1.881 41.007 1.881 c
+41.407 1.881 41.727 1.749 41.962 1.484 c
+42.204 1.228 42.337 0.882 42.359 0.441 c
+41.742 0.441 l
+41.719 0.735 41.646 0.956 41.52 1.103 c
+41.403 1.249 41.231 1.323 41.007 1.323 c
+40.712 1.323 40.496 1.224 40.36 1.029 c
+40.22 0.842 40.146 0.533 40.139 0.103 c
+40.139 -0.411 l
+40.139 -0.881 40.205 -1.216 40.345 -1.411 c
+40.492 -1.598 40.712 -1.691 41.007 -1.691 c
+43.814 -2.175 -0.647 5.644 re
+46.856 -1.822 m
+46.64 -2.109 46.328 -2.249 45.916 -2.249 c
+45.552 -2.249 45.277 -2.128 45.092 -1.881 c
+44.917 -1.627 44.821 -1.264 44.813 -0.794 c
+44.813 1.808 l
+45.46 1.808 l
+45.46 -0.735 l
+45.46 -1.363 45.644 -1.675 46.019 -1.675 c
+46.419 -1.675 46.695 -1.5 46.842 -1.147 c
+46.842 1.808 l
+47.489 1.808 l
+47.489 -2.175 l
+46.871 -2.175 l
+h
+48.341 0 m
+48.341 0.607 48.452 1.073 48.68 1.396 c
+48.915 1.72 49.241 1.881 49.664 1.881 c
+50.046 1.881 50.344 1.723 50.561 1.411 c
+50.561 3.469 l
+51.207 3.469 l
+51.207 -2.175 l
+50.619 -2.175 l
+50.575 -1.749 l
+50.37 -2.084 50.064 -2.249 49.664 -2.249 c
+49.252 -2.249 48.929 -2.094 48.694 -1.779 c
+48.458 -1.455 48.341 -0.999 48.341 -0.411 c
+h
+48.988 -0.382 m
+48.988 -0.823 49.05 -1.153 49.179 -1.367 c
+49.315 -1.573 49.536 -1.675 49.84 -1.675 c
+50.164 -1.675 50.403 -1.514 50.561 -1.191 c
+50.561 0.823 l
+50.392 1.135 50.153 1.294 49.84 1.294 c
+49.536 1.294 49.315 1.191 49.179 0.985 c
+49.05 0.779 48.988 0.455 48.988 0.015 c
+h
+52.913 -2.175 -0.647 3.983 re
+52.957 2.851 m
+52.957 2.741 52.927 2.65 52.869 2.572 c
+52.809 2.502 52.714 2.469 52.589 2.469 c
+52.472 2.469 52.376 2.502 52.31 2.572 c
+52.251 2.65 52.221 2.741 52.221 2.851 c
+52.221 2.969 52.251 3.061 52.31 3.131 c
+52.376 3.208 52.472 3.248 52.589 3.248 c
+52.714 3.248 52.809 3.208 52.869 3.131 c
+52.927 3.05 52.957 2.959 52.957 2.851 c
+54.544 1.808 m
+54.559 1.367 l
+54.812 1.709 55.136 1.881 55.529 1.881 c
+56.235 1.881 56.591 1.411 56.602 0.47 c
+56.602 -2.175 l
+55.955 -2.175 l
+55.955 0.441 l
+55.955 0.754 55.901 0.974 55.793 1.103 c
+55.683 1.228 55.529 1.294 55.323 1.294 c
+55.165 1.294 55.018 1.239 54.883 1.132 c
+54.754 1.022 54.65 0.886 54.573 0.721 c
+54.573 -2.175 l
+53.927 -2.175 l
+53.927 1.808 l
+h
+57.44 0 m
+57.44 0.617 57.55 1.081 57.778 1.396 c
+58.002 1.72 58.336 1.881 58.777 1.881 c
+59.178 1.881 59.483 1.706 59.689 1.353 c
+59.733 1.808 l
+60.321 1.808 l
+60.321 -2.219 l
+60.321 -2.708 60.192 -3.087 59.939 -3.351 c
+59.681 -3.616 59.329 -3.748 58.881 -3.748 c
+58.682 -3.748 58.461 -3.697 58.219 -3.601 c
+57.973 -3.502 57.792 -3.381 57.675 -3.233 c
+57.94 -2.793 l
+58.204 -3.057 58.502 -3.19 58.837 -3.19 c
+59.373 -3.19 59.649 -2.896 59.66 -2.308 c
+59.66 -1.779 l
+59.454 -2.094 59.153 -2.249 58.763 -2.249 c
+58.351 -2.249 58.028 -2.098 57.792 -1.793 c
+57.565 -1.481 57.447 -1.029 57.44 -0.441 c
+h
+58.101 -0.382 m
+58.101 -0.823 58.164 -1.153 58.293 -1.367 c
+58.417 -1.573 58.634 -1.675 58.939 -1.675 c
+59.263 -1.675 59.502 -1.51 59.66 -1.176 c
+59.66 0.808 l
+59.49 1.132 59.252 1.294 58.939 1.294 c
+58.646 1.294 58.428 1.191 58.293 0.985 c
+58.164 0.779 58.101 0.455 58.101 0.015 c
+h
+f
+Q
+q 1 0 0 1 38.464 110.9585 cm
+0 0 m
+0 -0.956 l
+0.603 -0.956 l
+0.603 -1.485 l
+0 -1.485 l
+0 -3.955 l
+0 -4.112 0.023 -4.23 0.073 -4.308 c
+0.133 -4.388 0.221 -4.425 0.339 -4.425 c
+0.426 -4.425 0.515 -4.41 0.603 -4.381 c
+0.603 -4.939 l
+0.456 -4.987 0.302 -5.013 0.148 -5.013 c
+-0.11 -5.013 -0.305 -4.921 -0.44 -4.734 c
+-0.58 -4.549 -0.646 -4.289 -0.646 -3.955 c
+-0.646 -1.485 l
+-1.249 -1.485 l
+-1.249 -0.956 l
+-0.646 -0.956 l
+-0.646 0 l
+h
+2.014 -1.368 m
+2.267 -1.044 2.587 -0.882 2.97 -0.882 c
+3.675 -0.882 4.031 -1.353 4.042 -2.294 c
+4.042 -4.939 l
+3.396 -4.939 l
+3.396 -2.323 l
+3.396 -2.01 3.341 -1.79 3.234 -1.661 c
+3.124 -1.536 2.97 -1.47 2.764 -1.47 c
+2.606 -1.47 2.459 -1.525 2.323 -1.632 c
+2.194 -1.742 2.091 -1.878 2.014 -2.043 c
+2.014 -4.939 l
+1.367 -4.939 l
+1.367 0.706 l
+2.014 0.706 l
+h
+6.423 -5.013 m
+5.924 -5.013 5.542 -4.866 5.278 -4.572 c
+5.012 -4.278 4.881 -3.844 4.881 -3.263 c
+4.881 -2.793 l
+4.881 -2.198 5.006 -1.731 5.262 -1.397 c
+5.527 -1.055 5.887 -0.882 6.35 -0.882 c
+6.81 -0.882 7.152 -1.037 7.379 -1.338 c
+7.614 -1.632 7.736 -2.095 7.747 -2.72 c
+7.747 -3.146 l
+5.527 -3.146 l
+5.527 -3.234 l
+5.527 -3.668 5.604 -3.98 5.762 -4.175 c
+5.928 -4.362 6.159 -4.454 6.453 -4.454 c
+6.648 -4.454 6.82 -4.421 6.968 -4.351 c
+7.115 -4.274 7.25 -4.156 7.379 -3.998 c
+7.717 -4.41 l
+7.431 -4.815 7.001 -5.013 6.423 -5.013 c
+6.35 -1.441 m
+6.074 -1.441 5.872 -1.536 5.748 -1.721 c
+5.619 -1.908 5.546 -2.198 5.527 -2.587 c
+7.1 -2.587 l
+7.1 -2.5 l
+7.078 -2.117 7.011 -1.849 6.894 -1.691 c
+6.776 -1.525 6.593 -1.441 6.35 -1.441 c
+f
+Q
+q 1 0 0 1 50.5656 106.5483 cm
+0 0 m
+0 0.166 0.051 0.301 0.161 0.412 c
+0.268 0.518 0.415 0.573 0.602 0.573 c
+0.768 0.573 0.911 0.518 1.028 0.412 c
+1.146 0.301 1.205 0.166 1.205 0 c
+1.205 -0.169 1.146 -0.305 1.028 -0.411 c
+0.911 -0.522 0.768 -0.573 0.602 -0.573 c
+0.426 -0.573 0.278 -0.522 0.161 -0.411 c
+0.051 -0.305 0 -0.169 0 0 c
+1.969 1.588 m
+1.969 2.234 2.087 2.72 2.322 3.042 c
+2.557 3.366 2.888 3.528 3.322 3.528 c
+3.675 3.528 3.946 3.385 4.145 3.102 c
+4.189 3.454 l
+5.13 3.454 l
+5.13 -0.529 l
+5.13 -1.036 4.986 -1.426 4.704 -1.691 c
+4.417 -1.962 4.012 -2.102 3.484 -2.102 c
+3.256 -2.102 3.021 -2.057 2.778 -1.97 c
+2.543 -1.881 2.366 -1.768 2.248 -1.631 c
+2.601 -0.912 l
+2.697 -1.018 2.826 -1.103 2.983 -1.161 c
+3.138 -1.228 3.285 -1.264 3.424 -1.264 c
+3.659 -1.264 3.825 -1.205 3.924 -1.087 c
+4.031 -0.977 4.086 -0.801 4.086 -0.559 c
+4.086 -0.206 l
+3.887 -0.47 3.63 -0.603 3.307 -0.603 c
+2.884 -0.603 2.557 -0.441 2.322 -0.118 c
+2.094 0.214 1.977 0.684 1.969 1.294 c
+h
+3.013 1.323 m
+3.013 0.948 3.061 0.68 3.16 0.515 c
+3.256 0.345 3.41 0.264 3.615 0.264 c
+3.829 0.264 3.987 0.341 4.086 0.5 c
+4.086 2.396 l
+3.976 2.562 3.821 2.646 3.615 2.646 c
+3.41 2.646 3.256 2.562 3.16 2.396 c
+3.061 2.227 3.013 1.959 3.013 1.588 c
+h
+6.981 -0.529 -1.043 3.983 re
+5.894 4.484 m
+5.894 4.638 5.942 4.767 6.04 4.866 c
+6.148 4.972 6.283 5.027 6.453 5.027 c
+6.628 5.027 6.765 4.972 6.864 4.866 c
+6.971 4.767 7.025 4.638 7.025 4.484 c
+7.025 4.314 6.971 4.179 6.864 4.072 c
+6.765 3.973 6.628 3.925 6.453 3.925 c
+6.283 3.925 6.148 3.973 6.04 4.072 c
+5.942 4.179 5.894 4.314 5.894 4.484 c
+8.995 4.424 m
+8.995 3.454 l
+9.525 3.454 l
+9.525 2.66 l
+8.995 2.66 l
+8.995 0.69 l
+8.995 0.533 9.014 0.426 9.055 0.368 c
+9.102 0.309 9.186 0.279 9.304 0.279 c
+9.411 0.279 9.495 0.287 9.554 0.309 c
+9.554 -0.5 l
+9.377 -0.565 9.186 -0.603 8.98 -0.603 c
+8.305 -0.603 7.96 -0.216 7.952 0.559 c
+7.952 2.66 l
+7.496 2.66 l
+7.496 3.454 l
+7.952 3.454 l
+7.952 4.424 l
+h
+11.421 1 m
+11.141 0.69 l
+11.141 -0.529 l
+10.098 -0.529 l
+10.098 5.116 l
+11.141 5.116 l
+11.141 2.072 l
+11.259 2.263 l
+11.979 3.454 l
+13.229 3.454 l
+12.068 1.808 l
+13.331 -0.529 l
+12.141 -0.529 l
+h
+15.228 -0.603 m
+14.699 -0.603 14.279 -0.448 13.978 -0.133 c
+13.684 0.191 13.537 0.651 13.537 1.249 c
+13.537 1.558 l
+13.537 2.183 13.674 2.668 13.949 3.013 c
+14.221 3.356 14.614 3.528 15.125 3.528 c
+15.625 3.528 15.996 3.366 16.242 3.042 c
+16.496 2.72 16.628 2.242 16.639 1.617 c
+16.639 1.118 l
+14.566 1.118 l
+14.585 0.823 14.647 0.607 14.757 0.47 c
+14.875 0.331 15.056 0.264 15.301 0.264 c
+15.643 0.264 15.933 0.382 16.168 0.617 c
+16.581 -0.015 l
+16.452 -0.191 16.264 -0.334 16.022 -0.441 c
+15.775 -0.548 15.511 -0.603 15.228 -0.603 c
+14.581 1.837 m
+15.61 1.837 l
+15.61 1.941 l
+15.61 2.176 15.569 2.352 15.492 2.469 c
+15.422 2.595 15.294 2.66 15.11 2.66 c
+14.934 2.66 14.802 2.591 14.713 2.454 c
+14.632 2.326 14.588 2.12 14.581 1.837 c
+18.829 -0.603 m
+18.3 -0.603 17.881 -0.448 17.58 -0.133 c
+17.286 0.191 17.138 0.651 17.138 1.249 c
+17.138 1.558 l
+17.138 2.183 17.275 2.668 17.55 3.013 c
+17.822 3.356 18.216 3.528 18.726 3.528 c
+19.226 3.528 19.597 3.366 19.843 3.042 c
+20.097 2.72 20.23 2.242 20.24 1.617 c
+20.24 1.118 l
+18.168 1.118 l
+18.186 0.823 18.248 0.607 18.359 0.47 c
+18.476 0.331 18.657 0.264 18.902 0.264 c
+19.245 0.264 19.534 0.382 19.77 0.617 c
+20.182 -0.015 l
+20.053 -0.191 19.866 -0.334 19.623 -0.441 c
+19.376 -0.548 19.112 -0.603 18.829 -0.603 c
+18.183 1.837 m
+19.211 1.837 l
+19.211 1.941 l
+19.211 2.176 19.17 2.352 19.093 2.469 c
+19.024 2.595 18.896 2.66 18.711 2.66 c
+18.535 2.66 18.403 2.591 18.314 2.454 c
+18.233 2.326 18.19 2.12 18.183 1.837 c
+23.93 1.338 m
+23.93 0.709 23.82 0.228 23.606 -0.103 c
+23.39 -0.437 23.07 -0.603 22.651 -0.603 c
+22.328 -0.603 22.067 -0.47 21.872 -0.206 c
+21.872 -2.057 l
+20.828 -2.057 l
+20.828 3.454 l
+21.784 3.454 l
+21.828 3.087 l
+22.023 3.381 22.291 3.528 22.636 3.528 c
+23.055 3.528 23.375 3.37 23.592 3.057 c
+23.804 2.753 23.918 2.282 23.93 1.646 c
+h
+22.886 1.602 m
+22.886 1.984 22.842 2.253 22.754 2.411 c
+22.673 2.565 22.534 2.646 22.328 2.646 c
+22.121 2.646 21.967 2.558 21.872 2.381 c
+21.872 0.515 l
+21.96 0.345 22.114 0.264 22.343 0.264 c
+22.548 0.264 22.688 0.345 22.769 0.515 c
+22.846 0.69 22.886 0.963 22.886 1.338 c
+h
+f
+Q
+q 1 0 0 1 78.9929 106.0196 cm
+0 0 m
+0 3.453 l
+-0.515 3.453 l
+-0.515 3.983 l
+0 3.983 l
+0 4.351 l
+0.008 4.781 0.121 5.115 0.339 5.35 c
+0.563 5.593 0.875 5.718 1.279 5.718 c
+1.426 5.718 1.565 5.695 1.706 5.659 c
+1.852 5.618 2.003 5.564 2.161 5.497 c
+2.043 4.924 l
+1.808 5.049 1.565 5.115 1.324 5.115 c
+1.077 5.115 0.904 5.045 0.809 4.909 c
+0.709 4.781 0.661 4.586 0.661 4.321 c
+0.661 3.983 l
+1.309 3.983 l
+1.309 3.453 l
+0.661 3.453 l
+0.661 0 l
+h
+2.469 0 -0.646 3.983 re
+4.219 0 -0.647 5.644 re
+6.659 -0.074 m
+6.159 -0.074 5.777 0.073 5.513 0.367 c
+5.247 0.661 5.116 1.095 5.116 1.675 c
+5.116 2.146 l
+5.116 2.741 5.241 3.208 5.498 3.542 c
+5.762 3.884 6.122 4.056 6.585 4.056 c
+7.045 4.056 7.387 3.902 7.614 3.601 c
+7.85 3.307 7.971 2.844 7.982 2.219 c
+7.982 1.793 l
+5.762 1.793 l
+5.762 1.705 l
+5.762 1.271 5.839 0.959 5.997 0.764 c
+6.163 0.577 6.394 0.484 6.689 0.484 c
+6.883 0.484 7.056 0.517 7.203 0.588 c
+7.35 0.665 7.485 0.783 7.614 0.941 c
+7.952 0.529 l
+7.666 0.124 7.236 -0.074 6.659 -0.074 c
+6.585 3.498 m
+6.31 3.498 6.108 3.403 5.983 3.218 c
+5.854 3.031 5.781 2.741 5.762 2.352 c
+7.335 2.352 l
+7.335 2.439 l
+7.313 2.822 7.247 3.09 7.129 3.248 c
+7.011 3.414 6.828 3.498 6.585 3.498 c
+10.157 2.131 m
+10.157 1.043 9.912 0.077 9.422 -0.765 c
+9.158 -1.213 8.882 -1.536 8.599 -1.735 c
+8.482 -1.309 l
+8.783 -1.015 9.029 -0.563 9.216 0.043 c
+9.411 0.65 9.511 1.315 9.511 2.042 c
+9.511 2.175 l
+9.511 3.104 9.357 3.939 9.055 4.674 c
+8.886 5.074 8.695 5.394 8.482 5.629 c
+8.599 6.04 l
+8.871 5.853 9.136 5.556 9.393 5.144 c
+9.9 4.292 10.157 3.285 10.157 2.131 c
+11.171 -1.073 m
+10.774 -0.809 l
+11.009 -0.485 11.131 -0.151 11.142 0.191 c
+11.142 0.808 l
+11.803 0.808 l
+11.803 0.278 l
+11.803 0.022 11.738 -0.225 11.612 -0.47 c
+11.495 -0.713 11.348 -0.915 11.171 -1.073 c
+19.198 1.146 m
+19.8 3.983 l
+20.447 3.983 l
+19.462 0 l
+18.947 0 l
+18.169 2.851 l
+17.419 0 l
+16.889 0 l
+15.934 3.983 l
+16.566 3.983 l
+17.184 1.219 l
+17.918 3.983 l
+18.433 3.983 l
+h
+21.77 3.571 m
+22.023 3.895 22.343 4.056 22.725 4.056 c
+23.431 4.056 23.788 3.586 23.798 2.645 c
+23.798 0 l
+23.152 0 l
+23.152 2.616 l
+23.152 2.929 23.096 3.149 22.99 3.278 c
+22.88 3.403 22.725 3.469 22.519 3.469 c
+22.361 3.469 22.215 3.414 22.078 3.307 c
+21.949 3.197 21.847 3.061 21.77 2.896 c
+21.77 0 l
+21.122 0 l
+21.122 5.644 l
+21.77 5.644 l
+h
+24.621 2.175 m
+24.621 2.752 24.757 3.208 25.033 3.542 c
+25.315 3.884 25.687 4.056 26.15 4.056 c
+26.61 4.056 26.977 3.887 27.252 3.557 c
+27.535 3.233 27.682 2.786 27.693 2.219 c
+27.693 1.793 l
+27.693 1.223 27.551 0.768 27.267 0.426 c
+26.992 0.091 26.624 -0.074 26.165 -0.074 c
+25.702 -0.074 25.33 0.087 25.047 0.411 c
+24.772 0.742 24.629 1.183 24.621 1.734 c
+h
+25.268 1.793 m
+25.268 1.389 25.345 1.072 25.503 0.837 c
+25.669 0.602 25.889 0.484 26.165 0.484 c
+26.73 0.484 27.025 0.897 27.046 1.72 c
+27.046 2.175 l
+27.046 2.576 26.962 2.896 26.797 3.131 c
+26.639 3.373 26.422 3.498 26.15 3.498 c
+25.885 3.498 25.669 3.373 25.503 3.131 c
+25.345 2.896 25.268 2.576 25.268 2.175 c
+h
+29.236 0 -0.646 5.644 re
+31.677 -0.074 m
+31.177 -0.074 30.795 0.073 30.53 0.367 c
+30.265 0.661 30.134 1.095 30.134 1.675 c
+30.134 2.146 l
+30.134 2.741 30.258 3.208 30.516 3.542 c
+30.78 3.884 31.14 4.056 31.603 4.056 c
+32.062 4.056 32.405 3.902 32.632 3.601 c
+32.868 3.307 32.989 2.844 32.999 2.219 c
+32.999 1.793 l
+30.78 1.793 l
+30.78 1.705 l
+30.78 1.271 30.857 0.959 31.015 0.764 c
+31.181 0.577 31.412 0.484 31.706 0.484 c
+31.9 0.484 32.074 0.517 32.22 0.588 c
+32.368 0.665 32.503 0.783 32.632 0.941 c
+32.97 0.529 l
+32.684 0.124 32.254 -0.074 31.677 -0.074 c
+31.603 3.498 m
+31.328 3.498 31.125 3.403 31 3.218 c
+30.872 3.031 30.799 2.741 30.78 2.352 c
+32.353 2.352 l
+32.353 2.439 l
+32.331 2.822 32.265 3.09 32.147 3.248 c
+32.029 3.414 31.846 3.498 31.603 3.498 c
+f
+Q
+q 1 0 0 1 117.4607 110.9726 cm
+0 0 m
+0 -0.97 l
+0.529 -0.97 l
+0.529 -1.764 l
+0 -1.764 l
+0 -3.734 l
+0 -3.891 0.018 -3.998 0.058 -4.056 c
+0.106 -4.116 0.191 -4.145 0.309 -4.145 c
+0.415 -4.145 0.5 -4.137 0.559 -4.116 c
+0.559 -4.924 l
+0.382 -4.99 0.191 -5.027 -0.015 -5.027 c
+-0.691 -5.027 -1.037 -4.641 -1.043 -3.865 c
+-1.043 -1.764 l
+-1.5 -1.764 l
+-1.5 -0.97 l
+-1.043 -0.97 l
+-1.043 0 l
+h
+2.072 -0.97 m
+2.102 -1.338 l
+2.337 -1.043 2.645 -0.897 3.028 -0.897 c
+3.429 -0.897 3.707 -1.08 3.866 -1.44 c
+4.101 -1.08 4.428 -0.897 4.85 -0.897 c
+5.546 -0.897 5.897 -1.382 5.909 -2.352 c
+5.909 -4.953 l
+4.88 -4.953 l
+4.88 -2.41 l
+4.88 -2.186 4.843 -2.024 4.777 -1.926 c
+4.719 -1.83 4.608 -1.778 4.453 -1.778 c
+4.255 -1.778 4.116 -1.896 4.027 -2.131 c
+4.027 -4.953 l
+2.984 -4.953 l
+2.984 -2.425 l
+2.984 -2.19 2.955 -2.024 2.896 -1.926 c
+2.837 -1.83 2.726 -1.778 2.572 -1.778 c
+2.396 -1.778 2.253 -1.874 2.146 -2.057 c
+2.146 -4.953 l
+1.103 -4.953 l
+1.103 -0.97 l
+h
+9.789 -3.087 m
+9.789 -3.715 9.679 -4.197 9.466 -4.527 c
+9.249 -4.862 8.93 -5.027 8.511 -5.027 c
+8.187 -5.027 7.927 -4.895 7.732 -4.63 c
+7.732 -6.482 l
+6.688 -6.482 l
+6.688 -0.97 l
+7.644 -0.97 l
+7.688 -1.338 l
+7.882 -1.043 8.151 -0.897 8.496 -0.897 c
+8.915 -0.897 9.234 -1.055 9.452 -1.367 c
+9.664 -1.672 9.779 -2.142 9.789 -2.778 c
+h
+8.746 -2.822 m
+8.746 -2.44 8.702 -2.171 8.613 -2.013 c
+8.533 -1.859 8.393 -1.778 8.187 -1.778 c
+7.981 -1.778 7.827 -1.866 7.732 -2.043 c
+7.732 -3.91 l
+7.819 -4.079 7.975 -4.16 8.202 -4.16 c
+8.407 -4.16 8.548 -4.079 8.628 -3.91 c
+8.706 -3.734 8.746 -3.461 8.746 -3.087 c
+h
+f
+Q
+q 1 0 0 1 131.4391 108.1946 cm
+0 0 m
+0 0.607 0.111 1.073 0.339 1.396 c
+0.574 1.72 0.9 1.881 1.324 1.881 c
+1.706 1.881 2.003 1.723 2.22 1.411 c
+2.22 3.469 l
+2.866 3.469 l
+2.866 -2.175 l
+2.278 -2.175 l
+2.234 -1.749 l
+2.029 -2.084 1.723 -2.249 1.324 -2.249 c
+0.912 -2.249 0.588 -2.094 0.353 -1.779 c
+0.118 -1.455 0 -0.999 0 -0.411 c
+h
+0.647 -0.382 m
+0.647 -0.823 0.709 -1.153 0.838 -1.367 c
+0.975 -1.573 1.195 -1.675 1.5 -1.675 c
+1.823 -1.675 2.062 -1.514 2.22 -1.191 c
+2.22 0.823 l
+2.051 1.135 1.812 1.294 1.5 1.294 c
+1.195 1.294 0.975 1.191 0.838 0.985 c
+0.709 0.779 0.647 0.455 0.647 0.015 c
+h
+4.572 -2.175 -0.647 3.983 re
+4.616 2.851 m
+4.616 2.741 4.586 2.65 4.528 2.572 c
+4.469 2.502 4.374 2.469 4.248 2.469 c
+4.131 2.469 4.035 2.502 3.969 2.572 c
+3.911 2.65 3.881 2.741 3.881 2.851 c
+3.881 2.969 3.911 3.061 3.969 3.131 c
+4.035 3.208 4.131 3.248 4.248 3.248 c
+4.374 3.248 4.469 3.208 4.528 3.131 c
+4.586 3.05 4.616 2.959 4.616 2.851 c
+7.232 1.191 m
+7.144 1.209 7.045 1.22 6.938 1.22 c
+6.604 1.22 6.369 1.037 6.232 0.676 c
+6.232 -2.175 l
+5.586 -2.175 l
+5.586 1.808 l
+6.218 1.808 l
+6.232 1.396 l
+6.409 1.72 6.652 1.881 6.968 1.881 c
+7.074 1.881 7.163 1.86 7.232 1.823 c
+h
+9.231 -2.249 m
+8.732 -2.249 8.349 -2.102 8.085 -1.808 c
+7.82 -1.514 7.688 -1.08 7.688 -0.5 c
+7.688 -0.029 l
+7.688 0.566 7.813 1.033 8.07 1.367 c
+8.335 1.709 8.695 1.881 9.158 1.881 c
+9.617 1.881 9.959 1.727 10.186 1.426 c
+10.422 1.132 10.543 0.669 10.554 0.044 c
+10.554 -0.382 l
+8.335 -0.382 l
+8.335 -0.47 l
+8.335 -0.904 8.412 -1.216 8.57 -1.411 c
+8.736 -1.598 8.967 -1.691 9.261 -1.691 c
+9.455 -1.691 9.628 -1.658 9.775 -1.587 c
+9.922 -1.51 10.058 -1.392 10.186 -1.234 c
+10.525 -1.646 l
+10.238 -2.051 9.808 -2.249 9.231 -2.249 c
+9.158 1.323 m
+8.882 1.323 8.68 1.228 8.555 1.043 c
+8.426 0.856 8.353 0.566 8.335 0.177 c
+9.908 0.177 l
+9.908 0.264 l
+9.885 0.647 9.819 0.915 9.702 1.073 c
+9.584 1.239 9.401 1.323 9.158 1.323 c
+12.715 -1.691 m
+12.929 -1.691 13.101 -1.627 13.23 -1.5 c
+13.365 -1.363 13.439 -1.172 13.45 -0.926 c
+14.067 -0.926 l
+14.045 -1.309 13.91 -1.627 13.656 -1.881 c
+13.399 -2.128 13.086 -2.249 12.715 -2.249 c
+12.223 -2.249 11.848 -2.098 11.583 -1.793 c
+11.326 -1.481 11.201 -1.014 11.201 -0.397 c
+11.201 0.044 l
+11.201 0.64 11.326 1.095 11.583 1.411 c
+11.848 1.723 12.223 1.881 12.715 1.881 c
+13.116 1.881 13.436 1.749 13.671 1.484 c
+13.913 1.228 14.045 0.882 14.067 0.441 c
+13.45 0.441 l
+13.428 0.735 13.355 0.956 13.23 1.103 c
+13.112 1.249 12.939 1.323 12.715 1.323 c
+12.421 1.323 12.204 1.224 12.068 1.029 c
+11.929 0.842 11.855 0.533 11.848 0.103 c
+11.848 -0.411 l
+11.848 -0.881 11.914 -1.216 12.054 -1.411 c
+12.2 -1.598 12.421 -1.691 12.715 -1.691 c
+15.67 2.764 m
+15.67 1.808 l
+16.272 1.808 l
+16.272 1.278 l
+15.67 1.278 l
+15.67 -1.191 l
+15.67 -1.348 15.692 -1.466 15.743 -1.544 c
+15.802 -1.624 15.89 -1.661 16.008 -1.661 c
+16.096 -1.661 16.184 -1.646 16.272 -1.617 c
+16.272 -2.175 l
+16.125 -2.223 15.971 -2.249 15.817 -2.249 c
+15.559 -2.249 15.364 -2.157 15.229 -1.97 c
+15.089 -1.786 15.023 -1.525 15.023 -1.191 c
+15.023 1.278 l
+14.42 1.278 l
+14.42 1.808 l
+15.023 1.808 l
+15.023 2.764 l
+h
+16.831 0 m
+16.831 0.577 16.967 1.033 17.242 1.367 c
+17.525 1.709 17.897 1.881 18.359 1.881 c
+18.819 1.881 19.186 1.712 19.462 1.382 c
+19.745 1.058 19.892 0.611 19.903 0.044 c
+19.903 -0.382 l
+19.903 -0.952 19.759 -1.407 19.476 -1.749 c
+19.201 -2.084 18.834 -2.249 18.375 -2.249 c
+17.911 -2.249 17.54 -2.087 17.257 -1.764 c
+16.981 -1.433 16.838 -0.992 16.831 -0.441 c
+h
+17.477 -0.382 m
+17.477 -0.786 17.554 -1.103 17.712 -1.338 c
+17.878 -1.573 18.099 -1.691 18.375 -1.691 c
+18.94 -1.691 19.234 -1.278 19.256 -0.455 c
+19.256 0 l
+19.256 0.401 19.171 0.721 19.006 0.956 c
+18.849 1.199 18.631 1.323 18.359 1.323 c
+18.095 1.323 17.878 1.199 17.712 0.956 c
+17.554 0.721 17.477 0.401 17.477 0 c
+h
+22.387 1.191 m
+22.298 1.209 22.2 1.22 22.093 1.22 c
+21.758 1.22 21.523 1.037 21.388 0.676 c
+21.388 -2.175 l
+20.74 -2.175 l
+20.74 1.808 l
+21.373 1.808 l
+21.388 1.396 l
+21.564 1.72 21.806 1.881 22.122 1.881 c
+22.229 1.881 22.317 1.86 22.387 1.823 c
+h
+24.195 -1.087 m
+24.915 1.808 l
+25.606 1.808 l
+24.312 -2.734 l
+24.214 -3.075 24.07 -3.337 23.886 -3.513 c
+23.709 -3.69 23.508 -3.778 23.283 -3.778 c
+23.196 -3.778 23.082 -3.755 22.946 -3.719 c
+22.946 -3.175 l
+23.092 -3.19 l
+23.277 -3.19 23.423 -3.146 23.534 -3.057 c
+23.64 -2.969 23.728 -2.811 23.798 -2.587 c
+23.915 -2.146 l
+22.755 1.808 l
+23.46 1.808 l
+h
+31.871 -2.175 m
+31.831 -2.087 31.805 -1.94 31.798 -1.735 c
+31.563 -2.08 31.269 -2.249 30.916 -2.249 c
+30.552 -2.249 30.269 -2.153 30.063 -1.955 c
+29.865 -1.749 29.77 -1.463 29.77 -1.087 c
+29.77 -0.687 29.905 -0.368 30.181 -0.133 c
+30.453 0.11 30.828 0.235 31.298 0.235 c
+31.784 0.235 l
+31.784 0.661 l
+31.784 0.897 31.728 1.062 31.622 1.161 c
+31.511 1.268 31.35 1.323 31.137 1.323 c
+30.938 1.323 30.776 1.264 30.651 1.147 c
+30.534 1.029 30.475 0.882 30.475 0.706 c
+29.828 0.706 l
+29.828 0.9 29.887 1.091 30.005 1.278 c
+30.13 1.463 30.292 1.61 30.489 1.72 c
+30.695 1.827 30.923 1.881 31.181 1.881 c
+31.582 1.881 31.886 1.779 32.092 1.573 c
+32.305 1.367 32.419 1.073 32.43 0.691 c
+32.43 -1.323 l
+32.43 -1.627 32.467 -1.893 32.548 -2.117 c
+32.548 -2.175 l
+h
+31.004 -1.661 m
+31.17 -1.661 31.32 -1.617 31.46 -1.529 c
+31.607 -1.44 31.713 -1.33 31.784 -1.191 c
+31.784 -0.25 l
+31.416 -0.25 l
+31.1 -0.25 30.857 -0.32 30.681 -0.455 c
+30.504 -0.584 30.416 -0.771 30.416 -1.014 c
+30.416 -1.242 30.46 -1.407 30.549 -1.514 c
+30.637 -1.613 30.788 -1.661 31.004 -1.661 c
+34.047 1.808 m
+34.061 1.367 l
+34.315 1.709 34.639 1.881 35.032 1.881 c
+35.738 1.881 36.094 1.411 36.105 0.47 c
+36.105 -2.175 l
+35.458 -2.175 l
+35.458 0.441 l
+35.458 0.754 35.403 0.974 35.297 1.103 c
+35.186 1.228 35.032 1.294 34.826 1.294 c
+34.668 1.294 34.521 1.239 34.385 1.132 c
+34.256 1.022 34.154 0.886 34.076 0.721 c
+34.076 -2.175 l
+33.43 -2.175 l
+33.43 1.808 l
+h
+36.943 0 m
+36.943 0.607 37.053 1.073 37.281 1.396 c
+37.516 1.72 37.843 1.881 38.266 1.881 c
+38.647 1.881 38.946 1.723 39.162 1.411 c
+39.162 3.469 l
+39.809 3.469 l
+39.809 -2.175 l
+39.221 -2.175 l
+39.177 -1.749 l
+38.971 -2.084 38.666 -2.249 38.266 -2.249 c
+37.854 -2.249 37.531 -2.094 37.296 -1.779 c
+37.06 -1.455 36.943 -0.999 36.943 -0.411 c
+h
+37.589 -0.382 m
+37.589 -0.823 37.652 -1.153 37.78 -1.367 c
+37.917 -1.573 38.137 -1.675 38.442 -1.675 c
+38.765 -1.675 39.004 -1.514 39.162 -1.191 c
+39.162 0.823 l
+38.994 1.135 38.755 1.294 38.442 1.294 c
+38.137 1.294 37.917 1.191 37.78 0.985 c
+37.652 0.779 37.589 0.455 37.589 0.015 c
+h
+46.439 -2.175 m
+46.398 -2.087 46.372 -1.94 46.365 -1.735 c
+46.13 -2.08 45.836 -2.249 45.483 -2.249 c
+45.119 -2.249 44.836 -2.153 44.631 -1.955 c
+44.432 -1.749 44.336 -1.463 44.336 -1.087 c
+44.336 -0.687 44.473 -0.368 44.748 -0.133 c
+45.02 0.11 45.394 0.235 45.865 0.235 c
+46.35 0.235 l
+46.35 0.661 l
+46.35 0.897 46.295 1.062 46.188 1.161 c
+46.078 1.268 45.917 1.323 45.703 1.323 c
+45.505 1.323 45.344 1.264 45.219 1.147 c
+45.101 1.029 45.042 0.882 45.042 0.706 c
+44.395 0.706 l
+44.395 0.9 44.454 1.091 44.571 1.278 c
+44.696 1.463 44.858 1.61 45.057 1.72 c
+45.263 1.827 45.49 1.881 45.747 1.881 c
+46.148 1.881 46.453 1.779 46.659 1.573 c
+46.872 1.367 46.986 1.073 46.997 0.691 c
+46.997 -1.323 l
+46.997 -1.627 47.033 -1.893 47.114 -2.117 c
+47.114 -2.175 l
+h
+45.571 -1.661 m
+45.737 -1.661 45.887 -1.617 46.027 -1.529 c
+46.173 -1.44 46.281 -1.33 46.35 -1.191 c
+46.35 -0.25 l
+45.982 -0.25 l
+45.666 -0.25 45.425 -0.32 45.248 -0.455 c
+45.071 -0.584 44.983 -0.771 44.983 -1.014 c
+44.983 -1.242 45.028 -1.407 45.115 -1.514 c
+45.203 -1.613 45.354 -1.661 45.571 -1.661 c
+48.702 -2.175 -0.647 5.644 re
+50.422 -2.175 -0.647 5.644 re
+55.199 -2.175 m
+55.199 1.278 l
+54.684 1.278 l
+54.684 1.808 l
+55.199 1.808 l
+55.199 2.176 l
+55.206 2.606 55.32 2.94 55.538 3.175 c
+55.761 3.418 56.074 3.543 56.478 3.543 c
+56.625 3.543 56.764 3.52 56.904 3.484 c
+57.051 3.443 57.202 3.389 57.36 3.322 c
+57.242 2.749 l
+57.007 2.874 56.764 2.94 56.521 2.94 c
+56.276 2.94 56.103 2.87 56.008 2.734 c
+55.908 2.606 55.86 2.411 55.86 2.146 c
+55.86 1.808 l
+56.507 1.808 l
+56.507 1.278 l
+55.86 1.278 l
+55.86 -2.175 l
+h
+57.668 -2.175 -0.646 3.983 re
+59.417 -2.175 -0.646 5.644 re
+61.857 -2.249 m
+61.358 -2.249 60.976 -2.102 60.712 -1.808 c
+60.446 -1.514 60.315 -1.08 60.315 -0.5 c
+60.315 -0.029 l
+60.315 0.566 60.439 1.033 60.697 1.367 c
+60.961 1.709 61.321 1.881 61.784 1.881 c
+62.243 1.881 62.586 1.727 62.813 1.426 c
+63.048 1.132 63.17 0.669 63.18 0.044 c
+63.18 -0.382 l
+60.961 -0.382 l
+60.961 -0.47 l
+60.961 -0.904 61.038 -1.216 61.196 -1.411 c
+61.362 -1.598 61.593 -1.691 61.887 -1.691 c
+62.082 -1.691 62.254 -1.658 62.401 -1.587 c
+62.549 -1.51 62.684 -1.392 62.813 -1.234 c
+63.151 -1.646 l
+62.865 -2.051 62.435 -2.249 61.857 -2.249 c
+61.784 1.323 m
+61.508 1.323 61.306 1.228 61.182 1.043 c
+61.053 0.856 60.98 0.566 60.961 0.177 c
+62.534 0.177 l
+62.534 0.264 l
+62.512 0.647 62.445 0.915 62.328 1.073 c
+62.21 1.239 62.027 1.323 61.784 1.323 c
+65.9 -1.161 m
+65.9 -1.014 65.845 -0.893 65.738 -0.794 c
+65.628 -0.698 65.422 -0.58 65.121 -0.441 c
+64.776 -0.294 64.533 -0.172 64.386 -0.073 c
+64.239 0.033 64.128 0.151 64.062 0.279 c
+63.993 0.405 63.96 0.563 63.96 0.75 c
+63.96 1.073 64.078 1.341 64.313 1.558 c
+64.548 1.771 64.849 1.881 65.223 1.881 c
+65.606 1.881 65.915 1.768 66.15 1.544 c
+66.385 1.316 66.503 1.029 66.503 0.676 c
+65.856 0.676 l
+65.856 0.852 65.797 1.004 65.68 1.132 c
+65.562 1.257 65.408 1.323 65.223 1.323 c
+65.025 1.323 64.874 1.268 64.768 1.161 c
+64.658 1.062 64.606 0.929 64.606 0.765 c
+64.606 0.636 64.643 0.53 64.724 0.441 c
+64.801 0.36 64.992 0.258 65.297 0.133 c
+65.775 -0.055 66.106 -0.243 66.282 -0.426 c
+66.459 -0.603 66.547 -0.831 66.547 -1.103 c
+66.547 -1.455 66.422 -1.735 66.179 -1.94 c
+65.944 -2.146 65.628 -2.249 65.238 -2.249 c
+64.816 -2.249 64.477 -2.132 64.224 -1.897 c
+63.967 -1.654 63.842 -1.348 63.842 -0.985 c
+64.489 -0.985 l
+64.496 -1.213 64.566 -1.389 64.695 -1.514 c
+64.82 -1.631 65.003 -1.691 65.238 -1.691 c
+65.452 -1.691 65.613 -1.643 65.724 -1.544 c
+65.841 -1.448 65.9 -1.319 65.9 -1.161 c
+f
+Q
+q 1 0 0 1 203.1893 109.5615 cm
+0 0 m
+-1.161 0.324 l
+-0.941 0.985 l
+0.191 0.53 l
+0.132 1.808 l
+0.852 1.808 l
+0.779 0.5 l
+1.897 0.956 l
+2.102 0.279 l
+0.926 -0.044 l
+1.705 -1.029 l
+1.117 -1.44 l
+0.441 -0.367 l
+-0.22 -1.411 l
+-0.809 -0.999 l
+h
+2.631 -3.013 m
+2.631 -2.848 2.682 -2.712 2.793 -2.601 c
+2.899 -2.495 3.046 -2.44 3.233 -2.44 c
+3.399 -2.44 3.543 -2.495 3.659 -2.601 c
+3.778 -2.712 3.836 -2.848 3.836 -3.013 c
+3.836 -3.183 3.778 -3.318 3.659 -3.424 c
+3.543 -3.535 3.399 -3.586 3.233 -3.586 c
+3.057 -3.586 2.911 -3.535 2.793 -3.424 c
+2.682 -3.318 2.631 -3.183 2.631 -3.013 c
+6.497 -2.469 m
+6.497 -2.381 6.453 -2.304 6.365 -2.234 c
+6.277 -2.157 6.089 -2.054 5.806 -1.926 c
+5.373 -1.749 5.074 -1.569 4.91 -1.382 c
+4.752 -1.198 4.675 -0.966 4.675 -0.691 c
+4.675 -0.349 4.796 -0.066 5.041 0.162 c
+5.295 0.397 5.633 0.515 6.056 0.515 c
+6.485 0.515 6.835 0.401 7.1 0.177 c
+7.364 -0.051 7.497 -0.353 7.497 -0.735 c
+6.453 -0.735 l
+6.453 -0.411 6.313 -0.249 6.041 -0.249 c
+5.931 -0.249 5.843 -0.286 5.776 -0.353 c
+5.707 -0.422 5.674 -0.521 5.674 -0.646 c
+5.674 -0.735 5.71 -0.816 5.791 -0.881 c
+5.868 -0.941 6.049 -1.036 6.335 -1.161 c
+6.765 -1.319 7.063 -1.496 7.231 -1.691 c
+7.408 -1.878 7.497 -2.127 7.497 -2.44 c
+7.497 -2.793 7.364 -3.079 7.1 -3.293 c
+6.835 -3.509 6.485 -3.616 6.056 -3.616 c
+5.762 -3.616 5.501 -3.561 5.277 -3.454 c
+5.049 -3.337 4.873 -3.175 4.748 -2.969 c
+4.63 -2.763 4.571 -2.543 4.571 -2.308 c
+5.556 -2.308 l
+5.556 -2.495 5.593 -2.631 5.674 -2.719 c
+5.762 -2.807 5.895 -2.851 6.071 -2.851 c
+6.354 -2.851 6.497 -2.726 6.497 -2.469 c
+11.054 -1.793 m
+11.406 0.441 l
+12.406 0.441 l
+11.582 -3.542 l
+10.715 -3.542 l
+10.157 -1.234 l
+9.598 -3.542 l
+8.731 -3.542 l
+7.908 0.441 l
+8.908 0.441 l
+9.261 -1.793 l
+9.789 0.441 l
+10.524 0.441 l
+h
+16.022 -1.675 m
+16.022 -2.304 15.912 -2.786 15.698 -3.116 c
+15.482 -3.451 15.162 -3.616 14.743 -3.616 c
+14.42 -3.616 14.159 -3.484 13.964 -3.219 c
+13.964 -5.071 l
+12.92 -5.071 l
+12.92 0.441 l
+13.876 0.441 l
+13.92 0.073 l
+14.115 0.368 14.383 0.515 14.728 0.515 c
+15.147 0.515 15.467 0.357 15.684 0.044 c
+15.897 -0.261 16.01 -0.731 16.022 -1.367 c
+h
+14.978 -1.411 m
+14.978 -1.029 14.934 -0.76 14.846 -0.602 c
+14.765 -0.448 14.626 -0.367 14.42 -0.367 c
+14.214 -0.367 14.059 -0.455 13.964 -0.632 c
+13.964 -2.499 l
+14.052 -2.668 14.206 -2.749 14.435 -2.749 c
+14.64 -2.749 14.78 -2.668 14.861 -2.499 c
+14.938 -2.323 14.978 -2.05 14.978 -1.675 c
+h
+f
+Q
+q 1 0 0 1 219.99 106.3724 cm
+0 0 m
+0 0.118 0.033 0.213 0.103 0.294 c
+0.169 0.371 0.272 0.411 0.412 0.411 c
+0.559 0.411 0.665 0.371 0.735 0.294 c
+0.813 0.213 0.853 0.118 0.853 0 c
+0.853 -0.111 0.813 -0.202 0.735 -0.279 c
+0.665 -0.357 0.559 -0.397 0.412 -0.397 c
+0.272 -0.397 0.169 -0.357 0.103 -0.279 c
+0.033 -0.202 0 -0.111 0 0 c
+5.619 -0.353 m
+5.619 4.997 l
+6.897 4.997 l
+7.522 4.997 8.008 4.799 8.353 4.409 c
+8.694 4.016 8.867 3.469 8.867 2.763 c
+8.867 1.866 l
+8.867 1.161 8.691 0.61 8.339 0.22 c
+7.993 -0.162 7.489 -0.353 6.824 -0.353 c
+h
+6.295 4.424 m
+6.295 0.22 l
+6.839 0.22 l
+7.31 0.22 7.651 0.357 7.868 0.631 c
+8.092 0.904 8.206 1.308 8.206 1.837 c
+8.206 2.778 l
+8.206 3.343 8.096 3.763 7.882 4.027 c
+7.666 4.292 7.339 4.424 6.897 4.424 c
+h
+11.248 -0.427 m
+10.749 -0.427 10.367 -0.279 10.103 0.014 c
+9.837 0.309 9.706 0.742 9.706 1.323 c
+9.706 1.793 l
+9.706 2.389 9.83 2.855 10.088 3.189 c
+10.352 3.532 10.712 3.704 11.175 3.704 c
+11.634 3.704 11.977 3.549 12.204 3.248 c
+12.439 2.954 12.561 2.491 12.572 1.866 c
+12.572 1.44 l
+10.352 1.44 l
+10.352 1.352 l
+10.352 0.918 10.429 0.606 10.587 0.411 c
+10.753 0.224 10.984 0.132 11.279 0.132 c
+11.473 0.132 11.645 0.165 11.792 0.235 c
+11.94 0.312 12.075 0.43 12.204 0.588 c
+12.542 0.176 l
+12.256 -0.229 11.826 -0.427 11.248 -0.427 c
+11.175 3.145 m
+10.899 3.145 10.697 3.05 10.573 2.865 c
+10.444 2.678 10.371 2.389 10.352 1.999 c
+11.925 1.999 l
+11.925 2.087 l
+11.903 2.469 11.836 2.738 11.719 2.896 c
+11.601 3.061 11.418 3.145 11.175 3.145 c
+15.291 0.661 m
+15.291 0.808 15.236 0.929 15.129 1.028 c
+15.019 1.124 14.813 1.242 14.512 1.381 c
+14.167 1.529 13.924 1.65 13.777 1.749 c
+13.63 1.855 13.519 1.973 13.454 2.102 c
+13.384 2.227 13.351 2.385 13.351 2.572 c
+13.351 2.896 13.469 3.164 13.704 3.38 c
+13.939 3.594 14.24 3.704 14.614 3.704 c
+14.997 3.704 15.306 3.59 15.541 3.366 c
+15.776 3.138 15.894 2.851 15.894 2.499 c
+15.247 2.499 l
+15.247 2.675 15.188 2.826 15.071 2.954 c
+14.953 3.079 14.799 3.145 14.614 3.145 c
+14.416 3.145 14.265 3.09 14.159 2.983 c
+14.049 2.884 13.997 2.752 13.997 2.587 c
+13.997 2.458 14.034 2.352 14.115 2.263 c
+14.192 2.183 14.383 2.08 14.689 1.955 c
+15.166 1.768 15.497 1.579 15.673 1.396 c
+15.85 1.219 15.938 0.992 15.938 0.72 c
+15.938 0.367 15.813 0.087 15.57 -0.118 c
+15.335 -0.324 15.019 -0.427 14.629 -0.427 c
+14.207 -0.427 13.868 -0.31 13.615 -0.074 c
+13.358 0.168 13.233 0.474 13.233 0.837 c
+13.88 0.837 l
+13.887 0.61 13.957 0.434 14.086 0.309 c
+14.211 0.191 14.394 0.132 14.629 0.132 c
+14.843 0.132 15.004 0.18 15.115 0.278 c
+15.232 0.374 15.291 0.503 15.291 0.661 c
+18.157 0.132 m
+18.371 0.132 18.543 0.195 18.672 0.323 c
+18.807 0.459 18.882 0.65 18.892 0.897 c
+19.51 0.897 l
+19.487 0.514 19.352 0.195 19.098 -0.059 c
+18.841 -0.306 18.529 -0.427 18.157 -0.427 c
+17.665 -0.427 17.29 -0.276 17.025 0.029 c
+16.768 0.341 16.644 0.808 16.644 1.425 c
+16.644 1.866 l
+16.644 2.462 16.768 2.917 17.025 3.233 c
+17.29 3.546 17.665 3.704 18.157 3.704 c
+18.558 3.704 18.878 3.571 19.113 3.307 c
+19.355 3.05 19.487 2.705 19.51 2.263 c
+18.892 2.263 l
+18.87 2.557 18.797 2.778 18.672 2.925 c
+18.554 3.072 18.381 3.145 18.157 3.145 c
+17.864 3.145 17.646 3.046 17.511 2.851 c
+17.371 2.664 17.297 2.356 17.29 1.925 c
+17.29 1.411 l
+17.29 0.941 17.356 0.606 17.496 0.411 c
+17.643 0.224 17.864 0.132 18.157 0.132 c
+21.905 3.013 m
+21.818 3.031 21.718 3.042 21.612 3.042 c
+21.277 3.042 21.042 2.859 20.906 2.499 c
+20.906 -0.353 l
+20.259 -0.353 l
+20.259 3.63 l
+20.891 3.63 l
+20.906 3.218 l
+21.082 3.542 21.325 3.704 21.641 3.704 c
+21.747 3.704 21.835 3.682 21.905 3.645 c
+h
+23.258 -0.353 -0.647 3.983 re
+23.302 4.674 m
+23.302 4.564 23.273 4.472 23.214 4.394 c
+23.155 4.325 23.059 4.292 22.934 4.292 c
+22.817 4.292 22.722 4.325 22.655 4.394 c
+22.597 4.472 22.567 4.564 22.567 4.674 c
+22.567 4.791 22.597 4.883 22.655 4.953 c
+22.722 5.03 22.817 5.071 22.934 5.071 c
+23.059 5.071 23.155 5.03 23.214 4.953 c
+23.273 4.872 23.302 4.781 23.302 4.674 c
+27.154 1.44 m
+27.154 0.823 27.039 0.357 26.815 0.043 c
+26.598 -0.272 26.275 -0.427 25.845 -0.427 c
+25.423 -0.427 25.11 -0.246 24.904 0.118 c
+24.875 -0.353 l
+24.272 -0.353 l
+24.272 5.292 l
+24.919 5.292 l
+24.919 3.189 l
+25.132 3.532 25.44 3.704 25.845 3.704 c
+26.275 3.704 26.598 3.546 26.815 3.233 c
+27.039 2.929 27.154 2.462 27.154 1.837 c
+h
+26.506 1.822 m
+26.506 2.293 26.437 2.624 26.3 2.822 c
+26.172 3.017 25.963 3.116 25.668 3.116 c
+25.334 3.116 25.084 2.932 24.919 2.572 c
+24.919 0.691 l
+25.084 0.326 25.338 0.147 25.683 0.147 c
+25.978 0.147 26.186 0.249 26.315 0.455 c
+26.44 0.661 26.506 0.977 26.506 1.411 c
+h
+29.417 -0.427 m
+28.917 -0.427 28.535 -0.279 28.27 0.014 c
+28.006 0.309 27.873 0.742 27.873 1.323 c
+27.873 1.793 l
+27.873 2.389 27.998 2.855 28.255 3.189 c
+28.52 3.532 28.88 3.704 29.344 3.704 c
+29.803 3.704 30.144 3.549 30.372 3.248 c
+30.607 2.954 30.728 2.491 30.74 1.866 c
+30.74 1.44 l
+28.52 1.44 l
+28.52 1.352 l
+28.52 0.918 28.598 0.606 28.756 0.411 c
+28.92 0.224 29.153 0.132 29.446 0.132 c
+29.641 0.132 29.814 0.165 29.961 0.235 c
+30.107 0.312 30.244 0.43 30.372 0.588 c
+30.71 0.176 l
+30.424 -0.229 29.994 -0.427 29.417 -0.427 c
+29.344 3.145 m
+29.068 3.145 28.866 3.05 28.741 2.865 c
+28.612 2.678 28.538 2.389 28.52 1.999 c
+30.093 1.999 l
+30.093 2.087 l
+30.071 2.469 30.005 2.738 29.887 2.896 c
+29.77 3.061 29.585 3.145 29.344 3.145 c
+31.387 1.822 m
+31.387 2.429 31.497 2.896 31.725 3.218 c
+31.96 3.542 32.287 3.704 32.709 3.704 c
+33.091 3.704 33.389 3.546 33.606 3.233 c
+33.606 5.292 l
+34.252 5.292 l
+34.252 -0.353 l
+33.664 -0.353 l
+33.621 0.073 l
+33.415 -0.262 33.11 -0.427 32.709 -0.427 c
+32.297 -0.427 31.975 -0.272 31.74 0.043 c
+31.504 0.367 31.387 0.823 31.387 1.411 c
+h
+32.033 1.44 m
+32.033 0.999 32.095 0.669 32.224 0.455 c
+32.36 0.249 32.581 0.147 32.885 0.147 c
+33.209 0.147 33.448 0.309 33.606 0.631 c
+33.606 2.645 l
+33.437 2.958 33.198 3.116 32.885 3.116 c
+32.581 3.116 32.36 3.013 32.224 2.807 c
+32.095 2.601 32.033 2.278 32.033 1.837 c
+h
+39.015 -0.353 m
+39.015 3.101 l
+38.501 3.101 l
+38.501 3.63 l
+39.015 3.63 l
+39.015 3.998 l
+39.023 4.428 39.137 4.762 39.353 4.997 c
+39.578 5.24 39.89 5.365 40.294 5.365 c
+40.441 5.365 40.581 5.342 40.72 5.306 c
+40.868 5.265 41.018 5.211 41.176 5.144 c
+41.059 4.571 l
+40.823 4.696 40.581 4.762 40.338 4.762 c
+40.091 4.762 39.919 4.692 39.823 4.556 c
+39.725 4.428 39.677 4.233 39.677 3.968 c
+39.677 3.63 l
+40.324 3.63 l
+40.324 3.101 l
+39.677 3.101 l
+39.677 -0.353 l
+h
+41.485 -0.353 -0.647 3.983 re
+43.234 -0.353 -0.646 5.644 re
+45.674 -0.427 m
+45.174 -0.427 44.792 -0.279 44.527 0.014 c
+44.263 0.309 44.13 0.742 44.13 1.323 c
+44.13 1.793 l
+44.13 2.389 44.255 2.855 44.513 3.189 c
+44.777 3.532 45.138 3.704 45.6 3.704 c
+46.06 3.704 46.401 3.549 46.63 3.248 c
+46.865 2.954 46.986 2.491 46.997 1.866 c
+46.997 1.44 l
+44.777 1.44 l
+44.777 1.352 l
+44.777 0.918 44.854 0.606 45.012 0.411 c
+45.178 0.224 45.409 0.132 45.703 0.132 c
+45.898 0.132 46.071 0.165 46.218 0.235 c
+46.364 0.312 46.501 0.43 46.63 0.588 c
+46.967 0.176 l
+46.68 -0.229 46.251 -0.427 45.674 -0.427 c
+45.6 3.145 m
+45.325 3.145 45.123 3.05 44.997 2.865 c
+44.869 2.678 44.795 2.389 44.777 1.999 c
+46.35 1.999 l
+46.35 2.087 l
+46.328 2.469 46.262 2.738 46.144 2.896 c
+46.027 3.061 45.843 3.145 45.6 3.145 c
+f
+Q
+38.317 96.612 -0.646 3.983 re
+38.361 101.639 m
+38.361 101.529 38.332 101.437 38.273 101.359 c
+38.215 101.29 38.119 101.257 37.994 101.257 c
+37.876 101.257 37.781 101.29 37.714 101.359 c
+37.656 101.437 37.627 101.529 37.627 101.639 c
+37.627 101.756 37.656 101.848 37.714 101.918 c
+37.781 101.995 37.876 102.036 37.994 102.036 c
+38.119 102.036 38.215 101.995 38.273 101.918 c
+38.332 101.837 38.361 101.746 38.361 101.639 c
+39.2 98.787 m
+39.2 99.404 39.31 99.868 39.537 100.183 c
+39.761 100.507 40.096 100.669 40.536 100.669 c
+40.937 100.669 41.242 100.493 41.448 100.14 c
+41.492 100.595 l
+42.08 100.595 l
+42.08 96.568 l
+42.08 96.079 41.951 95.701 41.698 95.436 c
+41.44 95.171 41.088 95.039 40.64 95.039 c
+40.441 95.039 40.221 95.09 39.979 95.186 c
+39.732 95.285 39.552 95.406 39.435 95.554 c
+39.699 95.994 l
+39.964 95.73 40.261 95.597 40.596 95.597 c
+41.132 95.597 41.408 95.892 41.419 96.48 c
+41.419 97.008 l
+41.213 96.693 40.912 96.538 40.522 96.538 c
+40.11 96.538 39.788 96.689 39.552 96.994 c
+39.324 97.307 39.206 97.758 39.2 98.346 c
+h
+39.861 98.405 m
+39.861 97.964 39.923 97.634 40.052 97.42 c
+40.177 97.214 40.393 97.112 40.698 97.112 c
+41.022 97.112 41.261 97.277 41.419 97.611 c
+41.419 99.595 l
+41.249 99.919 41.011 100.081 40.698 100.081 c
+40.405 100.081 40.187 99.978 40.052 99.772 c
+39.923 99.566 39.861 99.243 39.861 98.802 c
+h
+43.653 100.595 m
+43.668 100.154 l
+43.921 100.497 44.245 100.669 44.638 100.669 c
+45.344 100.669 45.7 100.198 45.71 99.258 c
+45.71 96.612 l
+45.064 96.612 l
+45.064 99.228 l
+45.064 99.541 45.009 99.761 44.902 99.89 c
+44.792 100.015 44.638 100.081 44.432 100.081 c
+44.274 100.081 44.127 100.026 43.991 99.919 c
+43.863 99.809 43.759 99.673 43.682 99.508 c
+43.682 96.612 l
+43.036 96.612 l
+43.036 100.595 l
+h
+46.549 98.787 m
+46.549 99.364 46.685 99.82 46.961 100.154 c
+47.243 100.497 47.615 100.669 48.077 100.669 c
+48.536 100.669 48.904 100.499 49.18 100.169 c
+49.463 99.846 49.61 99.398 49.621 98.831 c
+49.621 98.405 l
+49.621 97.835 49.477 97.38 49.195 97.038 c
+48.919 96.703 48.552 96.538 48.092 96.538 c
+47.629 96.538 47.258 96.7 46.975 97.023 c
+46.699 97.354 46.556 97.795 46.549 98.346 c
+h
+47.196 98.405 m
+47.196 98.001 47.273 97.685 47.431 97.45 c
+47.596 97.214 47.817 97.097 48.092 97.097 c
+48.658 97.097 48.952 97.509 48.974 98.332 c
+48.974 98.787 l
+48.974 99.188 48.889 99.508 48.725 99.743 c
+48.567 99.986 48.349 100.11 48.077 100.11 c
+47.813 100.11 47.596 99.986 47.431 99.743 c
+47.273 99.508 47.196 99.188 47.196 98.787 c
+h
+52.105 99.978 m
+52.017 99.996 51.917 100.007 51.811 100.007 c
+51.476 100.007 51.241 99.824 51.106 99.464 c
+51.106 96.612 l
+50.458 96.612 l
+50.458 100.595 l
+51.091 100.595 l
+51.106 100.183 l
+51.282 100.507 51.524 100.669 51.84 100.669 c
+51.947 100.669 52.035 100.647 52.105 100.61 c
+h
+53.457 96.612 -0.647 3.983 re
+53.502 101.639 m
+53.502 101.529 53.472 101.437 53.413 101.359 c
+53.354 101.29 53.259 101.257 53.134 101.257 c
+53.016 101.257 52.921 101.29 52.854 101.359 c
+52.796 101.437 52.766 101.529 52.766 101.639 c
+52.766 101.756 52.796 101.848 52.854 101.918 c
+52.921 101.995 53.016 102.036 53.134 102.036 c
+53.259 102.036 53.354 101.995 53.413 101.918 c
+53.472 101.837 53.502 101.746 53.502 101.639 c
+55.089 100.595 m
+55.104 100.154 l
+55.357 100.497 55.68 100.669 56.074 100.669 c
+56.779 100.669 57.136 100.198 57.147 99.258 c
+57.147 96.612 l
+56.5 96.612 l
+56.5 99.228 l
+56.5 99.541 56.445 99.761 56.338 99.89 c
+56.228 100.015 56.074 100.081 55.868 100.081 c
+55.71 100.081 55.563 100.026 55.427 99.919 c
+55.298 99.809 55.195 99.673 55.118 99.508 c
+55.118 96.612 l
+54.472 96.612 l
+54.472 100.595 l
+h
+57.984 98.787 m
+57.984 99.404 58.095 99.868 58.323 100.183 c
+58.547 100.507 58.881 100.669 59.322 100.669 c
+59.723 100.669 60.028 100.493 60.234 100.14 c
+60.278 100.595 l
+60.866 100.595 l
+60.866 96.568 l
+60.866 96.079 60.737 95.701 60.484 95.436 c
+60.226 95.171 59.873 95.039 59.426 95.039 c
+59.227 95.039 59.006 95.09 58.763 95.186 c
+58.518 95.285 58.337 95.406 58.219 95.554 c
+58.485 95.994 l
+58.749 95.73 59.046 95.597 59.381 95.597 c
+59.918 95.597 60.193 95.892 60.204 96.48 c
+60.204 97.008 l
+59.998 96.693 59.697 96.538 59.308 96.538 c
+58.896 96.538 58.572 96.689 58.337 96.994 c
+58.109 97.307 57.992 97.758 57.984 98.346 c
+h
+58.646 98.405 m
+58.646 97.964 58.709 97.634 58.838 97.42 c
+58.962 97.214 59.179 97.112 59.484 97.112 c
+59.807 97.112 60.046 97.277 60.204 97.611 c
+60.204 99.595 l
+60.035 99.919 59.796 100.081 59.484 100.081 c
+59.19 100.081 58.973 99.978 58.838 99.772 c
+58.709 99.566 58.646 99.243 58.646 98.802 c
+h
+66.734 97.758 m
+67.337 100.595 l
+67.983 100.595 l
+66.998 96.612 l
+66.484 96.612 l
+65.705 99.464 l
+64.955 96.612 l
+64.426 96.612 l
+63.471 100.595 l
+64.103 100.595 l
+64.72 97.831 l
+65.456 100.595 l
+65.97 100.595 l
+h
+69.365 96.612 -0.647 3.983 re
+69.41 101.639 m
+69.41 101.529 69.38 101.437 69.321 101.359 c
+69.263 101.29 69.167 101.257 69.042 101.257 c
+68.924 101.257 68.829 101.29 68.762 101.359 c
+68.704 101.437 68.675 101.529 68.675 101.639 c
+68.675 101.756 68.704 101.848 68.762 101.918 c
+68.829 101.995 68.924 102.036 69.042 102.036 c
+69.167 102.036 69.263 101.995 69.321 101.918 c
+69.38 101.837 69.41 101.746 69.41 101.639 c
+71.085 96.612 -0.646 5.644 re
+72.805 96.612 -0.646 5.644 re
+78.732 97.758 m
+79.335 100.595 l
+79.982 100.595 l
+78.997 96.612 l
+78.482 96.612 l
+77.703 99.464 l
+76.953 96.612 l
+76.425 96.612 l
+75.469 100.595 l
+76.101 100.595 l
+76.718 97.831 l
+77.454 100.595 l
+77.967 100.595 l
+h
+80.525 98.787 m
+80.525 99.364 80.662 99.82 80.937 100.154 c
+81.221 100.497 81.591 100.669 82.054 100.669 c
+82.514 100.669 82.881 100.499 83.157 100.169 c
+83.44 99.846 83.587 99.398 83.598 98.831 c
+83.598 98.405 l
+83.598 97.835 83.455 97.38 83.172 97.038 c
+82.896 96.703 82.528 96.538 82.069 96.538 c
+81.606 96.538 81.235 96.7 80.952 97.023 c
+80.676 97.354 80.533 97.795 80.525 98.346 c
+h
+81.173 98.405 m
+81.173 98.001 81.25 97.685 81.408 97.45 c
+81.573 97.214 81.793 97.097 82.069 97.097 c
+82.635 97.097 82.929 97.509 82.951 98.332 c
+82.951 98.787 l
+82.951 99.188 82.867 99.508 82.701 99.743 c
+82.543 99.986 82.326 100.11 82.054 100.11 c
+81.79 100.11 81.573 99.986 81.408 99.743 c
+81.25 99.508 81.173 99.188 81.173 98.787 c
+h
+86.082 99.978 m
+85.994 99.996 85.894 100.007 85.788 100.007 c
+85.454 100.007 85.219 99.824 85.082 99.464 c
+85.082 96.612 l
+84.436 96.612 l
+84.436 100.595 l
+85.067 100.595 l
+85.082 100.183 l
+85.258 100.507 85.501 100.669 85.817 100.669 c
+85.924 100.669 86.012 100.647 86.082 100.61 c
+h
+87.729 98.434 m
+87.39 98.037 l
+87.39 96.612 l
+86.729 96.612 l
+86.729 102.257 l
+87.39 102.257 l
+87.39 98.876 l
+88.625 100.595 l
+89.404 100.595 l
+88.14 98.934 l
+89.566 96.612 l
+88.816 96.612 l
+h
+92.366 96.612 m
+92.366 100.066 l
+91.837 100.066 l
+91.837 100.595 l
+92.366 100.595 l
+92.366 101.051 l
+92.366 101.451 92.461 101.764 92.66 101.991 c
+92.865 102.216 93.144 102.33 93.497 102.33 c
+93.634 102.33 93.765 102.307 93.894 102.271 c
+93.865 101.727 l
+93.765 101.746 93.667 101.756 93.571 101.756 c
+93.196 101.756 93.013 101.492 93.013 100.963 c
+93.013 100.595 l
+93.688 100.595 l
+93.688 100.066 l
+93.013 100.066 l
+93.013 96.612 l
+h
+94.32 98.787 m
+94.32 99.364 94.457 99.82 94.732 100.154 c
+95.016 100.497 95.386 100.669 95.849 100.669 c
+96.309 100.669 96.676 100.499 96.952 100.169 c
+97.235 99.846 97.382 99.398 97.393 98.831 c
+97.393 98.405 l
+97.393 97.835 97.25 97.38 96.967 97.038 c
+96.691 96.703 96.323 96.538 95.864 96.538 c
+95.401 96.538 95.03 96.7 94.747 97.023 c
+94.471 97.354 94.328 97.795 94.32 98.346 c
+h
+94.968 98.405 m
+94.968 98.001 95.045 97.685 95.203 97.45 c
+95.368 97.214 95.588 97.097 95.864 97.097 c
+96.43 97.097 96.724 97.509 96.746 98.332 c
+96.746 98.787 l
+96.746 99.188 96.662 99.508 96.496 99.743 c
+96.338 99.986 96.121 100.11 95.849 100.11 c
+95.585 100.11 95.368 99.986 95.203 99.743 c
+95.045 99.508 94.968 99.188 94.968 98.787 c
+h
+99.877 99.978 m
+99.789 99.996 99.689 100.007 99.583 100.007 c
+99.249 100.007 99.014 99.824 98.877 99.464 c
+98.877 96.612 l
+98.231 96.612 l
+98.231 100.595 l
+98.862 100.595 l
+98.877 100.183 l
+99.054 100.507 99.296 100.669 99.612 100.669 c
+99.719 100.669 99.807 100.647 99.877 100.61 c
+h
+103.32 101.551 m
+103.32 100.595 l
+103.922 100.595 l
+103.922 100.066 l
+103.32 100.066 l
+103.32 97.596 l
+103.32 97.439 103.342 97.322 103.394 97.243 c
+103.452 97.164 103.541 97.126 103.658 97.126 c
+103.747 97.126 103.835 97.141 103.922 97.17 c
+103.922 96.612 l
+103.776 96.564 103.621 96.538 103.467 96.538 c
+103.21 96.538 103.016 96.63 102.879 96.817 c
+102.74 97.002 102.673 97.262 102.673 97.596 c
+102.673 100.066 l
+102.071 100.066 l
+102.071 100.595 l
+102.673 100.595 l
+102.673 101.551 l
+h
+105.334 100.183 m
+105.588 100.507 105.907 100.669 106.289 100.669 c
+106.995 100.669 107.351 100.198 107.363 99.258 c
+107.363 96.612 l
+106.716 96.612 l
+106.716 99.228 l
+106.716 99.541 106.66 99.761 106.554 99.89 c
+106.444 100.015 106.289 100.081 106.083 100.081 c
+105.925 100.081 105.779 100.026 105.642 99.919 c
+105.514 99.809 105.411 99.673 105.334 99.508 c
+105.334 96.612 l
+104.687 96.612 l
+104.687 102.257 l
+105.334 102.257 l
+h
+109.744 96.538 m
+109.244 96.538 108.861 96.686 108.597 96.979 c
+108.333 97.274 108.2 97.707 108.2 98.288 c
+108.2 98.758 l
+108.2 99.354 108.325 99.82 108.582 100.154 c
+108.847 100.497 109.208 100.669 109.67 100.669 c
+110.129 100.669 110.471 100.514 110.699 100.213 c
+110.934 99.919 111.055 99.456 111.066 98.831 c
+111.066 98.405 l
+108.847 98.405 l
+108.847 98.317 l
+108.847 97.883 108.924 97.571 109.082 97.376 c
+109.247 97.189 109.479 97.097 109.773 97.097 c
+109.968 97.097 110.141 97.13 110.288 97.2 c
+110.434 97.277 110.571 97.395 110.699 97.553 c
+111.037 97.141 l
+110.75 96.736 110.32 96.538 109.744 96.538 c
+109.67 100.11 m
+109.395 100.11 109.193 100.015 109.067 99.831 c
+108.939 99.643 108.865 99.354 108.847 98.964 c
+110.42 98.964 l
+110.42 99.052 l
+110.398 99.434 110.332 99.703 110.214 99.861 c
+110.097 100.026 109.913 100.11 109.67 100.11 c
+113.657 98.787 m
+113.657 99.394 113.767 99.861 113.995 100.183 c
+114.23 100.507 114.558 100.669 114.98 100.669 c
+115.362 100.669 115.66 100.511 115.876 100.198 c
+115.876 102.257 l
+116.524 102.257 l
+116.524 96.612 l
+115.936 96.612 l
+115.892 97.038 l
+115.685 96.703 115.381 96.538 114.98 96.538 c
+114.569 96.538 114.245 96.693 114.01 97.008 c
+113.775 97.332 113.657 97.788 113.657 98.376 c
+h
+114.304 98.405 m
+114.304 97.964 114.367 97.634 114.495 97.42 c
+114.631 97.214 114.852 97.112 115.157 97.112 c
+115.48 97.112 115.718 97.274 115.876 97.596 c
+115.876 99.61 l
+115.708 99.923 115.469 100.081 115.157 100.081 c
+114.852 100.081 114.631 99.978 114.495 99.772 c
+114.367 99.566 114.304 99.243 114.304 98.802 c
+h
+118.228 96.612 -0.646 3.983 re
+118.273 101.639 m
+118.273 101.529 118.243 101.437 118.184 101.359 c
+118.126 101.29 118.03 101.257 117.906 101.257 c
+117.788 101.257 117.692 101.29 117.626 101.359 c
+117.567 101.437 117.538 101.529 117.538 101.639 c
+117.538 101.756 117.567 101.848 117.626 101.918 c
+117.692 101.995 117.788 102.036 117.906 102.036 c
+118.03 102.036 118.126 101.995 118.184 101.918 c
+118.243 101.837 118.273 101.746 118.273 101.639 c
+120.89 99.978 m
+120.801 99.996 120.702 100.007 120.595 100.007 c
+120.261 100.007 120.026 99.824 119.89 99.464 c
+119.89 96.612 l
+119.243 96.612 l
+119.243 100.595 l
+119.875 100.595 l
+119.89 100.183 l
+120.066 100.507 120.308 100.669 120.624 100.669 c
+120.732 100.669 120.819 100.647 120.89 100.61 c
+h
+122.888 96.538 m
+122.388 96.538 122.006 96.686 121.742 96.979 c
+121.477 97.274 121.345 97.707 121.345 98.288 c
+121.345 98.758 l
+121.345 99.354 121.47 99.82 121.727 100.154 c
+121.991 100.497 122.352 100.669 122.814 100.669 c
+123.274 100.669 123.616 100.514 123.844 100.213 c
+124.079 99.919 124.2 99.456 124.211 98.831 c
+124.211 98.405 l
+121.991 98.405 l
+121.991 98.317 l
+121.991 97.883 122.068 97.571 122.226 97.376 c
+122.392 97.189 122.623 97.097 122.918 97.097 c
+123.113 97.097 123.285 97.13 123.432 97.2 c
+123.579 97.277 123.715 97.395 123.844 97.553 c
+124.182 97.141 l
+123.895 96.736 123.465 96.538 122.888 96.538 c
+122.814 100.11 m
+122.539 100.11 122.337 100.015 122.212 99.831 c
+122.083 99.643 122.01 99.354 121.991 98.964 c
+123.564 98.964 l
+123.564 99.052 l
+123.543 99.434 123.477 99.703 123.358 99.861 c
+123.242 100.026 123.057 100.11 122.814 100.11 c
+126.372 97.097 m
+126.585 97.097 126.758 97.16 126.886 97.288 c
+127.022 97.424 127.096 97.615 127.107 97.862 c
+127.724 97.862 l
+127.702 97.479 127.566 97.16 127.313 96.906 c
+127.055 96.659 126.743 96.538 126.372 96.538 c
+125.879 96.538 125.505 96.689 125.24 96.994 c
+124.983 97.307 124.858 97.773 124.858 98.39 c
+124.858 98.831 l
+124.858 99.427 124.983 99.882 125.24 100.198 c
+125.505 100.511 125.879 100.669 126.372 100.669 c
+126.772 100.669 127.092 100.536 127.327 100.272 c
+127.57 100.015 127.702 99.67 127.724 99.228 c
+127.107 99.228 l
+127.084 99.522 127.011 99.743 126.886 99.89 c
+126.769 100.037 126.596 100.11 126.372 100.11 c
+126.078 100.11 125.861 100.011 125.725 99.816 c
+125.586 99.629 125.512 99.321 125.505 98.89 c
+125.505 98.376 l
+125.505 97.906 125.571 97.571 125.71 97.376 c
+125.858 97.189 126.078 97.097 126.372 97.097 c
+129.326 101.551 m
+129.326 100.595 l
+129.929 100.595 l
+129.929 100.066 l
+129.326 100.066 l
+129.326 97.596 l
+129.326 97.439 129.349 97.322 129.4 97.243 c
+129.459 97.164 129.547 97.126 129.665 97.126 c
+129.752 97.126 129.841 97.141 129.929 97.17 c
+129.929 96.612 l
+129.782 96.564 129.628 96.538 129.473 96.538 c
+129.216 96.538 129.021 96.63 128.886 96.817 c
+128.746 97.002 128.68 97.262 128.68 97.596 c
+128.68 100.066 l
+128.077 100.066 l
+128.077 100.595 l
+128.68 100.595 l
+128.68 101.551 l
+h
+130.488 98.787 m
+130.488 99.364 130.623 99.82 130.899 100.154 c
+131.182 100.497 131.553 100.669 132.017 100.669 c
+132.476 100.669 132.844 100.499 133.119 100.169 c
+133.402 99.846 133.549 99.398 133.56 98.831 c
+133.56 98.405 l
+133.56 97.835 133.417 97.38 133.133 97.038 c
+132.858 96.703 132.491 96.538 132.031 96.538 c
+131.568 96.538 131.197 96.7 130.914 97.023 c
+130.639 97.354 130.495 97.795 130.488 98.346 c
+h
+131.134 98.405 m
+131.134 98.001 131.211 97.685 131.369 97.45 c
+131.535 97.214 131.755 97.097 132.031 97.097 c
+132.597 97.097 132.891 97.509 132.913 98.332 c
+132.913 98.787 l
+132.913 99.188 132.829 99.508 132.663 99.743 c
+132.505 99.986 132.289 100.11 132.017 100.11 c
+131.751 100.11 131.535 99.986 131.369 99.743 c
+131.211 99.508 131.134 99.188 131.134 98.787 c
+h
+136.044 99.978 m
+135.956 99.996 135.857 100.007 135.75 100.007 c
+135.416 100.007 135.18 99.824 135.044 99.464 c
+135.044 96.612 l
+134.398 96.612 l
+134.398 100.595 l
+135.03 100.595 l
+135.044 100.183 l
+135.221 100.507 135.464 100.669 135.78 100.669 c
+135.886 100.669 135.974 100.647 136.044 100.61 c
+h
+137.852 97.7 m
+138.572 100.595 l
+139.263 100.595 l
+137.97 96.053 l
+137.87 95.712 137.727 95.45 137.544 95.275 c
+137.367 95.098 137.164 95.009 136.941 95.009 c
+136.852 95.009 136.738 95.032 136.603 95.068 c
+136.603 95.612 l
+136.75 95.597 l
+136.933 95.597 137.08 95.641 137.191 95.73 c
+137.297 95.818 137.386 95.976 137.455 96.2 c
+137.573 96.641 l
+136.412 100.595 l
+137.117 100.595 l
+h
+141.824 98.787 m
+141.824 99.423 141.912 100.026 142.089 100.595 c
+142.265 101.162 142.508 101.657 142.824 102.08 c
+143.019 102.344 143.206 102.535 143.383 102.653 c
+143.514 102.197 l
+143.221 101.922 142.978 101.499 142.795 100.933 c
+142.607 100.364 142.504 99.732 142.486 99.037 c
+142.486 98.743 l
+142.486 97.879 142.604 97.116 142.839 96.45 c
+143.022 95.95 143.25 95.568 143.514 95.304 c
+143.383 94.878 l
+143.154 95.036 142.93 95.285 142.706 95.627 c
+142.118 96.509 141.824 97.56 141.824 98.787 c
+146.249 96.612 m
+146.209 96.7 146.182 96.847 146.175 97.053 c
+145.94 96.707 145.646 96.538 145.293 96.538 c
+144.929 96.538 144.646 96.634 144.441 96.832 c
+144.243 97.038 144.147 97.324 144.147 97.7 c
+144.147 98.1 144.283 98.419 144.559 98.655 c
+144.831 98.897 145.205 99.022 145.675 99.022 c
+146.161 99.022 l
+146.161 99.449 l
+146.161 99.684 146.105 99.849 145.999 99.948 c
+145.889 100.055 145.727 100.11 145.514 100.11 c
+145.315 100.11 145.153 100.052 145.029 99.934 c
+144.911 99.816 144.852 99.67 144.852 99.493 c
+144.206 99.493 l
+144.206 99.688 144.264 99.878 144.382 100.066 c
+144.507 100.25 144.669 100.397 144.867 100.507 c
+145.073 100.614 145.301 100.669 145.558 100.669 c
+145.958 100.669 146.263 100.566 146.469 100.36 c
+146.682 100.154 146.797 99.861 146.807 99.478 c
+146.807 97.465 l
+146.807 97.16 146.844 96.894 146.925 96.671 c
+146.925 96.612 l
+h
+145.382 97.126 m
+145.546 97.126 145.698 97.17 145.837 97.259 c
+145.984 97.347 146.091 97.457 146.161 97.596 c
+146.161 98.537 l
+145.793 98.537 l
+145.477 98.537 145.234 98.467 145.058 98.332 c
+144.881 98.203 144.794 98.016 144.794 97.773 c
+144.794 97.545 144.838 97.38 144.926 97.274 c
+145.014 97.174 145.165 97.126 145.382 97.126 c
+148.424 100.595 m
+148.439 100.154 l
+148.692 100.497 149.016 100.669 149.409 100.669 c
+150.115 100.669 150.471 100.198 150.482 99.258 c
+150.482 96.612 l
+149.835 96.612 l
+149.835 99.228 l
+149.835 99.541 149.78 99.761 149.673 99.89 c
+149.563 100.015 149.409 100.081 149.203 100.081 c
+149.045 100.081 148.898 100.026 148.762 99.919 c
+148.634 99.809 148.53 99.673 148.453 99.508 c
+148.453 96.612 l
+147.807 96.612 l
+147.807 100.595 l
+h
+151.32 98.787 m
+151.32 99.394 151.43 99.861 151.658 100.183 c
+151.894 100.507 152.22 100.669 152.642 100.669 c
+153.025 100.669 153.323 100.511 153.54 100.198 c
+153.54 102.257 l
+154.186 102.257 l
+154.186 96.612 l
+153.598 96.612 l
+153.554 97.038 l
+153.348 96.703 153.043 96.538 152.642 96.538 c
+152.231 96.538 151.908 96.693 151.673 97.008 c
+151.437 97.332 151.32 97.788 151.32 98.376 c
+h
+151.967 98.405 m
+151.967 97.964 152.029 97.634 152.158 97.42 c
+152.293 97.214 152.514 97.112 152.819 97.112 c
+153.143 97.112 153.382 97.274 153.54 97.596 c
+153.54 99.61 l
+153.371 99.923 153.132 100.081 152.819 100.081 c
+152.514 100.081 152.293 99.978 152.158 99.772 c
+152.029 99.566 151.967 99.243 151.967 98.802 c
+h
+158.512 97.097 m
+158.724 97.097 158.897 97.16 159.026 97.288 c
+159.162 97.424 159.235 97.615 159.246 97.862 c
+159.864 97.862 l
+159.842 97.479 159.706 97.16 159.452 96.906 c
+159.195 96.659 158.882 96.538 158.512 96.538 c
+158.019 96.538 157.644 96.689 157.38 96.994 c
+157.122 97.307 156.997 97.773 156.997 98.39 c
+156.997 98.831 l
+156.997 99.427 157.122 99.882 157.38 100.198 c
+157.644 100.511 158.019 100.669 158.512 100.669 c
+158.912 100.669 159.231 100.536 159.467 100.272 c
+159.709 100.015 159.842 99.67 159.864 99.228 c
+159.246 99.228 l
+159.225 99.522 159.15 99.743 159.026 99.89 c
+158.909 100.037 158.736 100.11 158.512 100.11 c
+158.217 100.11 158.001 100.011 157.864 99.816 c
+157.725 99.629 157.652 99.321 157.644 98.89 c
+157.644 98.376 l
+157.644 97.906 157.71 97.571 157.85 97.376 c
+157.997 97.189 158.217 97.097 158.512 97.097 c
+161.261 100.183 m
+161.514 100.507 161.833 100.669 162.215 100.669 c
+162.921 100.669 163.277 100.198 163.289 99.258 c
+163.289 96.612 l
+162.642 96.612 l
+162.642 99.228 l
+162.642 99.541 162.587 99.761 162.48 99.89 c
+162.37 100.015 162.215 100.081 162.009 100.081 c
+161.851 100.081 161.705 100.026 161.569 99.919 c
+161.44 99.809 161.338 99.673 161.261 99.508 c
+161.261 96.612 l
+160.613 96.612 l
+160.613 102.257 l
+161.261 102.257 l
+h
+164.949 96.612 -0.646 3.983 re
+164.993 101.639 m
+164.993 101.529 164.964 101.437 164.906 101.359 c
+164.847 101.29 164.751 101.257 164.627 101.257 c
+164.509 101.257 164.413 101.29 164.347 101.359 c
+164.288 101.437 164.259 101.529 164.259 101.639 c
+164.259 101.756 164.288 101.848 164.347 101.918 c
+164.413 101.995 164.509 102.036 164.627 102.036 c
+164.751 102.036 164.847 101.995 164.906 101.918 c
+164.964 101.837 164.993 101.746 164.993 101.639 c
+166.67 96.612 -0.647 5.644 re
+167.551 98.787 m
+167.551 99.394 167.661 99.861 167.889 100.183 c
+168.124 100.507 168.452 100.669 168.874 100.669 c
+169.257 100.669 169.554 100.511 169.77 100.198 c
+169.77 102.257 l
+170.418 102.257 l
+170.418 96.612 l
+169.83 96.612 l
+169.786 97.038 l
+169.58 96.703 169.275 96.538 168.874 96.538 c
+168.463 96.538 168.139 96.693 167.904 97.008 c
+167.669 97.332 167.551 97.788 167.551 98.376 c
+h
+168.199 98.405 m
+168.199 97.964 168.261 97.634 168.389 97.42 c
+168.525 97.214 168.746 97.112 169.051 97.112 c
+169.374 97.112 169.612 97.274 169.77 97.596 c
+169.77 99.61 l
+169.602 99.923 169.363 100.081 169.051 100.081 c
+168.746 100.081 168.525 99.978 168.389 99.772 c
+168.261 99.566 168.199 99.243 168.199 98.802 c
+h
+173.063 99.978 m
+172.976 99.996 172.876 100.007 172.77 100.007 c
+172.435 100.007 172.199 99.824 172.064 99.464 c
+172.064 96.612 l
+171.417 96.612 l
+171.417 100.595 l
+172.049 100.595 l
+172.064 100.183 l
+172.24 100.507 172.483 100.669 172.799 100.669 c
+172.905 100.669 172.993 100.647 173.063 100.61 c
+h
+175.062 96.538 m
+174.563 96.538 174.181 96.686 173.916 96.979 c
+173.651 97.274 173.519 97.707 173.519 98.288 c
+173.519 98.758 l
+173.519 99.354 173.644 99.82 173.901 100.154 c
+174.166 100.497 174.526 100.669 174.989 100.669 c
+175.449 100.669 175.79 100.514 176.018 100.213 c
+176.253 99.919 176.374 99.456 176.386 98.831 c
+176.386 98.405 l
+174.166 98.405 l
+174.166 98.317 l
+174.166 97.883 174.243 97.571 174.401 97.376 c
+174.566 97.189 174.798 97.097 175.092 97.097 c
+175.287 97.097 175.459 97.13 175.607 97.2 c
+175.754 97.277 175.889 97.395 176.018 97.553 c
+176.356 97.141 l
+176.07 96.736 175.64 96.538 175.062 96.538 c
+174.989 100.11 m
+174.713 100.11 174.512 100.015 174.387 99.831 c
+174.258 99.643 174.184 99.354 174.166 98.964 c
+175.739 98.964 l
+175.739 99.052 l
+175.717 99.434 175.65 99.703 175.533 99.861 c
+175.415 100.026 175.231 100.11 174.989 100.11 c
+177.782 100.595 m
+177.797 100.154 l
+178.05 100.497 178.374 100.669 178.767 100.669 c
+179.472 100.669 179.829 100.198 179.84 99.258 c
+179.84 96.612 l
+179.193 96.612 l
+179.193 99.228 l
+179.193 99.541 179.137 99.761 179.031 99.89 c
+178.921 100.015 178.767 100.081 178.561 100.081 c
+178.403 100.081 178.256 100.026 178.12 99.919 c
+177.992 99.809 177.888 99.673 177.811 99.508 c
+177.811 96.612 l
+177.165 96.612 l
+177.165 100.595 l
+h
+182.622 98.787 m
+182.622 99.394 182.732 99.861 182.96 100.183 c
+183.195 100.507 183.522 100.669 183.945 100.669 c
+184.327 100.669 184.625 100.511 184.841 100.198 c
+184.841 102.257 l
+185.487 102.257 l
+185.487 96.612 l
+184.899 96.612 l
+184.856 97.038 l
+184.65 96.703 184.345 96.538 183.945 96.538 c
+183.533 96.538 183.21 96.693 182.975 97.008 c
+182.74 97.332 182.622 97.788 182.622 98.376 c
+h
+183.268 98.405 m
+183.268 97.964 183.33 97.634 183.459 97.42 c
+183.596 97.214 183.816 97.112 184.121 97.112 c
+184.444 97.112 184.683 97.274 184.841 97.596 c
+184.841 99.61 l
+184.672 99.923 184.433 100.081 184.121 100.081 c
+183.816 100.081 183.596 99.978 183.459 99.772 c
+183.33 99.566 183.268 99.243 183.268 98.802 c
+h
+187.193 96.612 -0.647 3.983 re
+187.237 101.639 m
+187.237 101.529 187.208 101.437 187.149 101.359 c
+187.09 101.29 186.994 101.257 186.869 101.257 c
+186.752 101.257 186.657 101.29 186.59 101.359 c
+186.532 101.437 186.502 101.529 186.502 101.639 c
+186.502 101.756 186.532 101.848 186.59 101.918 c
+186.657 101.995 186.752 102.036 186.869 102.036 c
+186.994 102.036 187.09 101.995 187.149 101.918 c
+187.208 101.837 187.237 101.746 187.237 101.639 c
+189.853 99.978 m
+189.765 99.996 189.666 100.007 189.56 100.007 c
+189.225 100.007 188.99 99.824 188.854 99.464 c
+188.854 96.612 l
+188.207 96.612 l
+188.207 100.595 l
+188.839 100.595 l
+188.854 100.183 l
+189.03 100.507 189.273 100.669 189.589 100.669 c
+189.695 100.669 189.784 100.647 189.853 100.61 c
+h
+191.852 96.538 m
+191.353 96.538 190.971 96.686 190.706 96.979 c
+190.441 97.274 190.309 97.707 190.309 98.288 c
+190.309 98.758 l
+190.309 99.354 190.434 99.82 190.692 100.154 c
+190.956 100.497 191.316 100.669 191.779 100.669 c
+192.238 100.669 192.581 100.514 192.808 100.213 c
+193.043 99.919 193.165 99.456 193.175 98.831 c
+193.175 98.405 l
+190.956 98.405 l
+190.956 98.317 l
+190.956 97.883 191.033 97.571 191.191 97.376 c
+191.357 97.189 191.588 97.097 191.882 97.097 c
+192.076 97.097 192.249 97.13 192.396 97.2 c
+192.543 97.277 192.679 97.395 192.808 97.553 c
+193.146 97.141 l
+192.859 96.736 192.429 96.538 191.852 96.538 c
+191.779 100.11 m
+191.503 100.11 191.301 100.015 191.176 99.831 c
+191.048 99.643 190.975 99.354 190.956 98.964 c
+192.529 98.964 l
+192.529 99.052 l
+192.506 99.434 192.44 99.703 192.323 99.861 c
+192.205 100.026 192.022 100.11 191.779 100.11 c
+195.336 97.097 m
+195.55 97.097 195.722 97.16 195.851 97.288 c
+195.987 97.424 196.06 97.615 196.071 97.862 c
+196.689 97.862 l
+196.666 97.479 196.531 97.16 196.277 96.906 c
+196.02 96.659 195.708 96.538 195.336 96.538 c
+194.844 96.538 194.469 96.689 194.204 96.994 c
+193.947 97.307 193.822 97.773 193.822 98.39 c
+193.822 98.831 l
+193.822 99.427 193.947 99.882 194.204 100.198 c
+194.469 100.511 194.844 100.669 195.336 100.669 c
+195.737 100.669 196.057 100.536 196.292 100.272 c
+196.535 100.015 196.666 99.67 196.689 99.228 c
+196.071 99.228 l
+196.049 99.522 195.976 99.743 195.851 99.89 c
+195.733 100.037 195.56 100.11 195.336 100.11 c
+195.042 100.11 194.825 100.011 194.69 99.816 c
+194.55 99.629 194.476 99.321 194.469 98.89 c
+194.469 98.376 l
+194.469 97.906 194.535 97.571 194.675 97.376 c
+194.821 97.189 195.042 97.097 195.336 97.097 c
+198.291 101.551 m
+198.291 100.595 l
+198.893 100.595 l
+198.893 100.066 l
+198.291 100.066 l
+198.291 97.596 l
+198.291 97.439 198.313 97.322 198.364 97.243 c
+198.423 97.164 198.511 97.126 198.629 97.126 c
+198.717 97.126 198.805 97.141 198.893 97.17 c
+198.893 96.612 l
+198.746 96.564 198.592 96.538 198.438 96.538 c
+198.181 96.538 197.986 96.63 197.85 96.817 c
+197.71 97.002 197.644 97.262 197.644 97.596 c
+197.644 100.066 l
+197.042 100.066 l
+197.042 100.595 l
+197.644 100.595 l
+197.644 101.551 l
+h
+199.452 98.787 m
+199.452 99.364 199.588 99.82 199.864 100.154 c
+200.147 100.497 200.518 100.669 200.98 100.669 c
+201.44 100.669 201.807 100.499 202.083 100.169 c
+202.366 99.846 202.513 99.398 202.524 98.831 c
+202.524 98.405 l
+202.524 97.835 202.38 97.38 202.098 97.038 c
+201.822 96.703 201.455 96.538 200.995 96.538 c
+200.533 96.538 200.161 96.7 199.878 97.023 c
+199.602 97.354 199.459 97.795 199.452 98.346 c
+h
+200.099 98.405 m
+200.099 98.001 200.176 97.685 200.334 97.45 c
+200.499 97.214 200.72 97.097 200.995 97.097 c
+201.561 97.097 201.855 97.509 201.877 98.332 c
+201.877 98.787 l
+201.877 99.188 201.793 99.508 201.628 99.743 c
+201.47 99.986 201.252 100.11 200.98 100.11 c
+200.716 100.11 200.499 99.986 200.334 99.743 c
+200.176 99.508 200.099 99.188 200.099 98.787 c
+h
+205.008 99.978 m
+204.92 99.996 204.821 100.007 204.714 100.007 c
+204.38 100.007 204.145 99.824 204.009 99.464 c
+204.009 96.612 l
+203.361 96.612 l
+203.361 100.595 l
+203.994 100.595 l
+204.009 100.183 l
+204.185 100.507 204.427 100.669 204.743 100.669 c
+204.851 100.669 204.938 100.647 205.008 100.61 c
+h
+206.361 96.612 -0.647 3.983 re
+206.405 101.639 m
+206.405 101.529 206.376 101.437 206.316 101.359 c
+206.258 101.29 206.162 101.257 206.037 101.257 c
+205.919 101.257 205.824 101.29 205.758 101.359 c
+205.699 101.437 205.67 101.529 205.67 101.639 c
+205.67 101.756 205.699 101.848 205.758 101.918 c
+205.824 101.995 205.919 102.036 206.037 102.036 c
+206.162 102.036 206.258 101.995 206.316 101.918 c
+206.376 101.837 206.405 101.746 206.405 101.639 c
+208.801 96.538 m
+208.3 96.538 207.918 96.686 207.654 96.979 c
+207.39 97.274 207.257 97.707 207.257 98.288 c
+207.257 98.758 l
+207.257 99.354 207.382 99.82 207.639 100.154 c
+207.904 100.497 208.264 100.669 208.727 100.669 c
+209.187 100.669 209.528 100.514 209.756 100.213 c
+209.991 99.919 210.112 99.456 210.123 98.831 c
+210.123 98.405 l
+207.904 98.405 l
+207.904 98.317 l
+207.904 97.883 207.981 97.571 208.139 97.376 c
+208.304 97.189 208.536 97.097 208.83 97.097 c
+209.025 97.097 209.198 97.13 209.345 97.2 c
+209.491 97.277 209.628 97.395 209.756 97.553 c
+210.094 97.141 l
+209.807 96.736 209.377 96.538 208.801 96.538 c
+208.727 100.11 m
+208.452 100.11 208.25 100.015 208.124 99.831 c
+207.996 99.643 207.922 99.354 207.904 98.964 c
+209.476 98.964 l
+209.476 99.052 l
+209.455 99.434 209.389 99.703 209.271 99.861 c
+209.154 100.026 208.969 100.11 208.727 100.11 c
+212.843 97.626 m
+212.843 97.773 212.788 97.894 212.681 97.993 c
+212.571 98.089 212.365 98.207 212.063 98.346 c
+211.718 98.494 211.475 98.615 211.329 98.714 c
+211.182 98.82 211.072 98.938 211.005 99.067 c
+210.935 99.192 210.902 99.35 210.902 99.537 c
+210.902 99.861 211.02 100.129 211.255 100.345 c
+211.49 100.559 211.791 100.669 212.167 100.669 c
+212.549 100.669 212.857 100.555 213.092 100.331 c
+213.328 100.103 213.445 99.816 213.445 99.464 c
+212.799 99.464 l
+212.799 99.64 212.74 99.791 212.622 99.919 c
+212.505 100.044 212.35 100.11 212.167 100.11 c
+211.968 100.11 211.818 100.055 211.711 99.948 c
+211.6 99.849 211.55 99.717 211.55 99.552 c
+211.55 99.423 211.586 99.317 211.667 99.228 c
+211.744 99.148 211.935 99.045 212.24 98.92 c
+212.718 98.733 213.048 98.545 213.225 98.361 c
+213.401 98.184 213.489 97.957 213.489 97.685 c
+213.489 97.332 213.364 97.053 213.122 96.847 c
+212.886 96.641 212.571 96.538 212.181 96.538 c
+211.758 96.538 211.421 96.656 211.167 96.891 c
+210.91 97.133 210.785 97.439 210.785 97.802 c
+211.432 97.802 l
+211.439 97.575 211.509 97.399 211.637 97.274 c
+211.762 97.156 211.946 97.097 212.181 97.097 c
+212.394 97.097 212.556 97.145 212.666 97.243 c
+212.784 97.339 212.843 97.468 212.843 97.626 c
+215.724 98.743 m
+215.724 97.656 215.477 96.689 214.989 95.847 c
+214.725 95.4 214.449 95.076 214.166 94.878 c
+214.048 95.304 l
+214.349 95.597 214.596 96.05 214.783 96.656 c
+214.978 97.262 215.077 97.927 215.077 98.655 c
+215.077 98.787 l
+215.077 99.717 214.923 100.551 214.621 101.286 c
+214.453 101.687 214.261 102.006 214.048 102.242 c
+214.166 102.653 l
+214.438 102.466 214.702 102.168 214.96 101.756 c
+215.467 100.904 215.724 99.897 215.724 98.743 c
+221.636 97.758 m
+222.239 100.595 l
+222.886 100.595 l
+221.901 96.612 l
+221.387 96.612 l
+220.608 99.464 l
+219.858 96.612 l
+219.329 96.612 l
+218.373 100.595 l
+219.005 100.595 l
+219.623 97.831 l
+220.358 100.595 l
+220.872 100.595 l
+h
+224.209 100.183 m
+224.462 100.507 224.782 100.669 225.164 100.669 c
+225.87 100.669 226.226 100.198 226.237 99.258 c
+226.237 96.612 l
+225.59 96.612 l
+225.59 99.228 l
+225.59 99.541 225.536 99.761 225.428 99.89 c
+225.318 100.015 225.164 100.081 224.958 100.081 c
+224.801 100.081 224.653 100.026 224.518 99.919 c
+224.389 99.809 224.286 99.673 224.209 99.508 c
+224.209 96.612 l
+223.562 96.612 l
+223.562 102.257 l
+224.209 102.257 l
+h
+228.618 96.538 m
+228.119 96.538 227.737 96.686 227.472 96.979 c
+227.207 97.274 227.075 97.707 227.075 98.288 c
+227.075 98.758 l
+227.075 99.354 227.2 99.82 227.458 100.154 c
+227.722 100.497 228.082 100.669 228.545 100.669 c
+229.004 100.669 229.347 100.514 229.574 100.213 c
+229.809 99.919 229.931 99.456 229.941 98.831 c
+229.941 98.405 l
+227.722 98.405 l
+227.722 98.317 l
+227.722 97.883 227.799 97.571 227.957 97.376 c
+228.123 97.189 228.354 97.097 228.648 97.097 c
+228.842 97.097 229.015 97.13 229.162 97.2 c
+229.31 97.277 229.445 97.395 229.574 97.553 c
+229.912 97.141 l
+229.625 96.736 229.195 96.538 228.618 96.538 c
+228.545 100.11 m
+228.269 100.11 228.067 100.015 227.942 99.831 c
+227.814 99.643 227.741 99.354 227.722 98.964 c
+229.295 98.964 l
+229.295 99.052 l
+229.272 99.434 229.206 99.703 229.089 99.861 c
+228.971 100.026 228.788 100.11 228.545 100.11 c
+232.367 99.978 m
+232.279 99.996 232.179 100.007 232.073 100.007 c
+231.739 100.007 231.504 99.824 231.367 99.464 c
+231.367 96.612 l
+230.721 96.612 l
+230.721 100.595 l
+231.352 100.595 l
+231.367 100.183 l
+231.543 100.507 231.786 100.669 232.102 100.669 c
+232.209 100.669 232.297 100.647 232.367 100.61 c
+h
+234.365 96.538 m
+233.866 96.538 233.484 96.686 233.22 96.979 c
+232.954 97.274 232.823 97.707 232.823 98.288 c
+232.823 98.758 l
+232.823 99.354 232.948 99.82 233.205 100.154 c
+233.469 100.497 233.829 100.669 234.292 100.669 c
+234.752 100.669 235.094 100.514 235.321 100.213 c
+235.556 99.919 235.678 99.456 235.689 98.831 c
+235.689 98.405 l
+233.469 98.405 l
+233.469 98.317 l
+233.469 97.883 233.546 97.571 233.704 97.376 c
+233.87 97.189 234.101 97.097 234.396 97.097 c
+234.59 97.097 234.762 97.13 234.91 97.2 c
+235.057 97.277 235.192 97.395 235.321 97.553 c
+235.66 97.141 l
+235.373 96.736 234.943 96.538 234.365 96.538 c
+234.292 100.11 m
+234.016 100.11 233.815 100.015 233.69 99.831 c
+233.561 99.643 233.488 99.354 233.469 98.964 c
+235.042 98.964 l
+235.042 99.052 l
+235.02 99.434 234.954 99.703 234.836 99.861 c
+234.719 100.026 234.535 100.11 234.292 100.11 c
+f
+q 1 0 0 1 238.3974 97.1409 cm
+0 0 m
+0 0.166 0.051 0.301 0.162 0.412 c
+0.268 0.518 0.415 0.573 0.602 0.573 c
+0.768 0.573 0.911 0.518 1.028 0.412 c
+1.146 0.301 1.205 0.166 1.205 0 c
+1.205 -0.169 1.146 -0.305 1.028 -0.411 c
+0.911 -0.522 0.768 -0.573 0.602 -0.573 c
+0.426 -0.573 0.279 -0.522 0.162 -0.411 c
+0.051 -0.305 0 -0.169 0 0 c
+1.969 1.588 m
+1.969 2.234 2.087 2.72 2.322 3.042 c
+2.557 3.366 2.888 3.528 3.322 3.528 c
+3.675 3.528 3.946 3.385 4.145 3.102 c
+4.189 3.454 l
+5.13 3.454 l
+5.13 -0.529 l
+5.13 -1.036 4.986 -1.426 4.704 -1.691 c
+4.417 -1.962 4.012 -2.102 3.484 -2.102 c
+3.256 -2.102 3.021 -2.057 2.778 -1.97 c
+2.543 -1.881 2.366 -1.768 2.248 -1.631 c
+2.601 -0.912 l
+2.697 -1.018 2.826 -1.103 2.984 -1.161 c
+3.138 -1.228 3.285 -1.264 3.424 -1.264 c
+3.659 -1.264 3.825 -1.205 3.925 -1.087 c
+4.031 -0.977 4.086 -0.801 4.086 -0.559 c
+4.086 -0.206 l
+3.887 -0.47 3.63 -0.603 3.307 -0.603 c
+2.884 -0.603 2.557 -0.441 2.322 -0.118 c
+2.094 0.214 1.977 0.684 1.969 1.294 c
+h
+3.013 1.323 m
+3.013 0.948 3.061 0.68 3.16 0.515 c
+3.256 0.345 3.41 0.264 3.615 0.264 c
+3.829 0.264 3.987 0.341 4.086 0.5 c
+4.086 2.396 l
+3.976 2.562 3.821 2.646 3.615 2.646 c
+3.41 2.646 3.256 2.562 3.16 2.396 c
+3.061 2.227 3.013 1.959 3.013 1.588 c
+h
+6.982 -0.529 -1.044 3.983 re
+5.894 4.484 m
+5.894 4.638 5.942 4.767 6.041 4.866 c
+6.148 4.972 6.283 5.027 6.453 5.027 c
+6.629 5.027 6.765 4.972 6.865 4.866 c
+6.971 4.767 7.025 4.638 7.025 4.484 c
+7.025 4.314 6.971 4.179 6.865 4.072 c
+6.765 3.973 6.629 3.925 6.453 3.925 c
+6.283 3.925 6.148 3.973 6.041 4.072 c
+5.942 4.179 5.894 4.314 5.894 4.484 c
+8.995 4.424 m
+8.995 3.454 l
+9.525 3.454 l
+9.525 2.66 l
+8.995 2.66 l
+8.995 0.69 l
+8.995 0.533 9.014 0.426 9.055 0.368 c
+9.102 0.309 9.186 0.279 9.304 0.279 c
+9.411 0.279 9.495 0.287 9.554 0.309 c
+9.554 -0.5 l
+9.377 -0.565 9.186 -0.603 8.981 -0.603 c
+8.305 -0.603 7.96 -0.216 7.952 0.559 c
+7.952 2.66 l
+7.496 2.66 l
+7.496 3.454 l
+7.952 3.454 l
+7.952 4.424 l
+h
+11.185 -0.529 -1.043 3.983 re
+10.098 4.484 m
+10.098 4.638 10.146 4.767 10.245 4.866 c
+10.352 4.972 10.487 5.027 10.657 5.027 c
+10.833 5.027 10.969 4.972 11.068 4.866 c
+11.175 4.767 11.23 4.638 11.23 4.484 c
+11.23 4.314 11.175 4.179 11.068 4.072 c
+10.969 3.973 10.833 3.925 10.657 3.925 c
+10.487 3.925 10.352 3.973 10.245 4.072 c
+10.146 4.179 10.098 4.314 10.098 4.484 c
+11.862 1.588 m
+11.862 2.234 11.979 2.72 12.215 3.042 c
+12.45 3.366 12.781 3.528 13.215 3.528 c
+13.567 3.528 13.839 3.385 14.038 3.102 c
+14.081 3.454 l
+15.022 3.454 l
+15.022 -0.529 l
+15.022 -1.036 14.879 -1.426 14.596 -1.691 c
+14.31 -1.962 13.905 -2.102 13.375 -2.102 c
+13.148 -2.102 12.913 -2.057 12.67 -1.97 c
+12.435 -1.881 12.259 -1.768 12.141 -1.631 c
+12.494 -0.912 l
+12.589 -1.018 12.718 -1.103 12.876 -1.161 c
+13.03 -1.228 13.177 -1.264 13.317 -1.264 c
+13.552 -1.264 13.718 -1.205 13.817 -1.087 c
+13.923 -0.977 13.978 -0.801 13.978 -0.559 c
+13.978 -0.206 l
+13.78 -0.47 13.523 -0.603 13.2 -0.603 c
+12.777 -0.603 12.45 -0.441 12.215 -0.118 c
+11.987 0.214 11.869 0.684 11.862 1.294 c
+h
+12.905 1.323 m
+12.905 0.948 12.953 0.68 13.053 0.515 c
+13.148 0.345 13.302 0.264 13.508 0.264 c
+13.722 0.264 13.88 0.341 13.978 0.5 c
+13.978 2.396 l
+13.868 2.562 13.714 2.646 13.508 2.646 c
+13.302 2.646 13.148 2.562 13.053 2.396 c
+12.953 2.227 12.905 1.959 12.905 1.588 c
+h
+16.742 3.454 m
+16.771 3.057 l
+17.007 3.37 17.308 3.528 17.683 3.528 c
+18.366 3.528 18.719 3.046 18.741 2.087 c
+18.741 -0.529 l
+17.697 -0.529 l
+17.697 2.014 l
+17.697 2.238 17.661 2.4 17.595 2.499 c
+17.525 2.595 17.407 2.646 17.242 2.646 c
+17.055 2.646 16.907 2.55 16.801 2.367 c
+16.801 -0.529 l
+15.757 -0.529 l
+15.757 3.454 l
+h
+19.373 1.588 m
+19.373 2.194 19.513 2.668 19.8 3.013 c
+20.082 3.356 20.475 3.528 20.976 3.528 c
+21.483 3.528 21.879 3.356 22.166 3.013 c
+22.449 2.668 22.592 2.194 22.592 1.588 c
+22.592 1.323 l
+22.592 0.724 22.449 0.254 22.166 -0.088 c
+21.879 -0.434 21.483 -0.603 20.976 -0.603 c
+20.465 -0.603 20.068 -0.434 19.785 -0.088 c
+19.509 0.254 19.373 0.728 19.373 1.338 c
+h
+20.417 1.323 m
+20.417 0.617 20.6 0.264 20.976 0.264 c
+21.328 0.264 21.519 0.559 21.549 1.147 c
+21.549 1.588 l
+21.549 1.947 21.497 2.219 21.402 2.396 c
+21.302 2.572 21.159 2.66 20.976 2.66 c
+20.799 2.66 20.66 2.572 20.564 2.396 c
+20.465 2.219 20.417 1.947 20.417 1.588 c
+h
+25.194 2.44 m
+24.856 2.469 l
+24.569 2.469 24.378 2.344 24.282 2.102 c
+24.282 -0.529 l
+23.239 -0.529 l
+23.239 3.454 l
+24.209 3.454 l
+24.238 3.013 l
+24.404 3.356 24.635 3.528 24.93 3.528 c
+25.047 3.528 25.138 3.506 25.209 3.469 c
+h
+27.266 -0.603 m
+26.738 -0.603 26.318 -0.448 26.017 -0.133 c
+25.723 0.191 25.576 0.651 25.576 1.249 c
+25.576 1.558 l
+25.576 2.183 25.712 2.668 25.988 3.013 c
+26.26 3.356 26.653 3.528 27.164 3.528 c
+27.663 3.528 28.034 3.366 28.281 3.042 c
+28.535 2.72 28.666 2.242 28.678 1.617 c
+28.678 1.118 l
+26.605 1.118 l
+26.623 0.823 26.686 0.607 26.796 0.47 c
+26.914 0.331 27.093 0.264 27.34 0.264 c
+27.681 0.264 27.972 0.382 28.207 0.617 c
+28.619 -0.015 l
+28.49 -0.191 28.303 -0.334 28.06 -0.441 c
+27.814 -0.548 27.55 -0.603 27.266 -0.603 c
+26.62 1.837 m
+27.648 1.837 l
+27.648 1.941 l
+27.648 2.176 27.608 2.352 27.531 2.469 c
+27.461 2.595 27.332 2.66 27.149 2.66 c
+26.973 2.66 26.84 2.591 26.752 2.454 c
+26.671 2.326 26.627 2.12 26.62 1.837 c
+f
+Q
+q 1 0 0 1 37.7885 87.2048 cm
+0 0 m
+0 3.453 l
+-0.515 3.453 l
+-0.515 3.983 l
+0 3.983 l
+0 4.351 l
+0.007 4.781 0.12 5.115 0.338 5.35 c
+0.562 5.593 0.874 5.718 1.278 5.718 c
+1.425 5.718 1.565 5.695 1.705 5.659 c
+1.851 5.618 2.002 5.564 2.16 5.497 c
+2.042 4.924 l
+1.807 5.049 1.565 5.115 1.323 5.115 c
+1.076 5.115 0.903 5.045 0.808 4.909 c
+0.708 4.781 0.661 4.586 0.661 4.321 c
+0.661 3.983 l
+1.308 3.983 l
+1.308 3.453 l
+0.661 3.453 l
+0.661 0 l
+h
+2.469 0 -0.647 3.983 re
+4.218 0 -0.647 5.644 re
+6.659 -0.074 m
+6.158 -0.074 5.776 0.073 5.512 0.367 c
+5.247 0.661 5.115 1.095 5.115 1.675 c
+5.115 2.146 l
+5.115 2.741 5.24 3.208 5.497 3.542 c
+5.762 3.884 6.121 4.056 6.585 4.056 c
+7.044 4.056 7.386 3.902 7.613 3.601 c
+7.849 3.307 7.97 2.844 7.981 2.219 c
+7.981 1.793 l
+5.762 1.793 l
+5.762 1.705 l
+5.762 1.271 5.839 0.959 5.997 0.764 c
+6.162 0.577 6.393 0.484 6.688 0.484 c
+6.882 0.484 7.056 0.517 7.202 0.588 c
+7.349 0.665 7.485 0.783 7.613 0.941 c
+7.952 0.529 l
+7.665 0.124 7.235 -0.074 6.659 -0.074 c
+6.585 3.498 m
+6.31 3.498 6.107 3.403 5.982 3.218 c
+5.853 3.031 5.78 2.741 5.762 2.352 c
+7.334 2.352 l
+7.334 2.439 l
+7.312 2.822 7.247 3.09 7.129 3.248 c
+7.011 3.414 6.827 3.498 6.585 3.498 c
+11.185 0 -0.646 3.983 re
+11.23 5.026 m
+11.23 4.916 11.2 4.825 11.141 4.747 c
+11.083 4.677 10.987 4.644 10.862 4.644 c
+10.744 4.644 10.649 4.677 10.583 4.747 c
+10.524 4.825 10.495 4.916 10.495 5.026 c
+10.495 5.144 10.524 5.236 10.583 5.306 c
+10.649 5.383 10.744 5.423 10.862 5.423 c
+10.987 5.423 11.083 5.383 11.141 5.306 c
+11.2 5.225 11.23 5.134 11.23 5.026 c
+14.14 1.014 m
+14.14 1.161 14.085 1.282 13.978 1.381 c
+13.868 1.477 13.662 1.595 13.361 1.734 c
+13.016 1.881 12.773 2.003 12.626 2.102 c
+12.479 2.208 12.369 2.326 12.303 2.454 c
+12.232 2.58 12.2 2.738 12.2 2.925 c
+12.2 3.248 12.317 3.516 12.552 3.733 c
+12.787 3.946 13.089 4.056 13.464 4.056 c
+13.846 4.056 14.154 3.943 14.39 3.719 c
+14.625 3.491 14.742 3.204 14.742 2.851 c
+14.096 2.851 l
+14.096 3.027 14.037 3.179 13.919 3.307 c
+13.802 3.432 13.647 3.498 13.464 3.498 c
+13.265 3.498 13.115 3.443 13.009 3.336 c
+12.898 3.237 12.847 3.104 12.847 2.94 c
+12.847 2.811 12.883 2.705 12.964 2.616 c
+13.041 2.535 13.232 2.433 13.537 2.308 c
+14.015 2.12 14.346 1.932 14.522 1.749 c
+14.699 1.572 14.787 1.344 14.787 1.072 c
+14.787 0.72 14.662 0.44 14.42 0.235 c
+14.184 0.029 13.868 -0.074 13.479 -0.074 c
+13.056 -0.074 12.718 0.043 12.465 0.278 c
+12.207 0.521 12.082 0.827 12.082 1.19 c
+12.729 1.19 l
+12.737 0.962 12.806 0.786 12.935 0.661 c
+13.059 0.544 13.244 0.484 13.479 0.484 c
+13.692 0.484 13.853 0.532 13.963 0.631 c
+14.081 0.727 14.14 0.856 14.14 1.014 c
+20.226 1.793 m
+20.226 1.165 20.108 0.694 19.873 0.382 c
+19.645 0.077 19.328 -0.074 18.917 -0.074 c
+18.513 -0.074 18.204 0.077 17.992 0.382 c
+17.992 -1.529 l
+17.344 -1.529 l
+17.344 3.983 l
+17.932 3.983 l
+17.977 3.542 l
+18.19 3.884 18.499 4.056 18.902 4.056 c
+19.343 4.056 19.671 3.902 19.887 3.601 c
+20.101 3.296 20.215 2.84 20.226 2.234 c
+h
+19.579 2.175 m
+19.579 2.616 19.509 2.94 19.373 3.145 c
+19.233 3.358 19.012 3.469 18.711 3.469 c
+18.395 3.469 18.156 3.314 17.992 3.013 c
+17.992 0.941 l
+18.156 0.635 18.395 0.484 18.711 0.484 c
+19.006 0.484 19.218 0.588 19.359 0.793 c
+19.494 1.007 19.567 1.337 19.579 1.778 c
+h
+21.769 0 -0.646 5.644 re
+24.826 0 m
+24.786 0.087 24.76 0.235 24.753 0.44 c
+24.518 0.095 24.224 -0.074 23.871 -0.074 c
+23.507 -0.074 23.224 0.022 23.018 0.22 c
+22.82 0.426 22.724 0.712 22.724 1.087 c
+22.724 1.488 22.86 1.807 23.136 2.042 c
+23.407 2.285 23.783 2.41 24.253 2.41 c
+24.738 2.41 l
+24.738 2.836 l
+24.738 3.072 24.683 3.237 24.577 3.336 c
+24.466 3.443 24.305 3.498 24.091 3.498 c
+23.893 3.498 23.731 3.439 23.606 3.322 c
+23.488 3.204 23.43 3.057 23.43 2.881 c
+22.783 2.881 l
+22.783 3.075 22.842 3.266 22.96 3.453 c
+23.085 3.638 23.246 3.785 23.444 3.895 c
+23.65 4.002 23.878 4.056 24.136 4.056 c
+24.536 4.056 24.841 3.954 25.047 3.748 c
+25.26 3.542 25.374 3.248 25.385 2.865 c
+25.385 0.852 l
+25.385 0.548 25.422 0.282 25.503 0.058 c
+25.503 0 l
+h
+23.959 0.514 m
+24.124 0.514 24.275 0.558 24.415 0.646 c
+24.562 0.735 24.668 0.845 24.738 0.984 c
+24.738 1.925 l
+24.371 1.925 l
+24.055 1.925 23.812 1.855 23.636 1.72 c
+23.459 1.591 23.371 1.404 23.371 1.161 c
+23.371 0.933 23.415 0.768 23.503 0.661 c
+23.592 0.562 23.742 0.514 23.959 0.514 c
+27.766 0.484 m
+27.979 0.484 28.152 0.548 28.281 0.675 c
+28.417 0.812 28.49 1.003 28.501 1.249 c
+29.119 1.249 l
+29.096 0.866 28.961 0.548 28.707 0.294 c
+28.45 0.047 28.138 -0.074 27.766 -0.074 c
+27.274 -0.074 26.899 0.077 26.634 0.382 c
+26.377 0.694 26.252 1.161 26.252 1.778 c
+26.252 2.219 l
+26.252 2.815 26.377 3.27 26.634 3.586 c
+26.899 3.898 27.274 4.056 27.766 4.056 c
+28.167 4.056 28.487 3.924 28.722 3.659 c
+28.964 3.403 29.096 3.057 29.119 2.616 c
+28.501 2.616 l
+28.479 2.91 28.406 3.131 28.281 3.278 c
+28.163 3.424 27.99 3.498 27.766 3.498 c
+27.472 3.498 27.255 3.399 27.12 3.204 c
+26.979 3.017 26.906 2.708 26.899 2.278 c
+26.899 1.764 l
+26.899 1.294 26.965 0.959 27.105 0.764 c
+27.251 0.577 27.472 0.484 27.766 0.484 c
+31.294 -0.074 m
+30.794 -0.074 30.412 0.073 30.147 0.367 c
+29.883 0.661 29.751 1.095 29.751 1.675 c
+29.751 2.146 l
+29.751 2.741 29.875 3.208 30.133 3.542 c
+30.397 3.884 30.757 4.056 31.22 4.056 c
+31.679 4.056 32.022 3.902 32.249 3.601 c
+32.485 3.307 32.606 2.844 32.616 2.219 c
+32.616 1.793 l
+30.397 1.793 l
+30.397 1.705 l
+30.397 1.271 30.474 0.959 30.632 0.764 c
+30.798 0.577 31.029 0.484 31.323 0.484 c
+31.518 0.484 31.691 0.517 31.837 0.588 c
+31.985 0.665 32.121 0.783 32.249 0.941 c
+32.587 0.529 l
+32.301 0.124 31.87 -0.074 31.294 -0.074 c
+31.22 3.498 m
+30.945 3.498 30.742 3.403 30.617 3.218 c
+30.489 3.031 30.416 2.741 30.397 2.352 c
+31.97 2.352 l
+31.97 2.439 l
+31.948 2.822 31.882 3.09 31.764 3.248 c
+31.646 3.414 31.463 3.498 31.22 3.498 c
+33.264 2.175 m
+33.264 2.782 33.374 3.248 33.601 3.571 c
+33.837 3.895 34.164 4.056 34.586 4.056 c
+34.968 4.056 35.266 3.898 35.483 3.586 c
+35.483 5.644 l
+36.13 5.644 l
+36.13 0 l
+35.542 0 l
+35.498 0.426 l
+35.292 0.091 34.987 -0.074 34.586 -0.074 c
+34.175 -0.074 33.852 0.081 33.616 0.396 c
+33.381 0.72 33.264 1.176 33.264 1.764 c
+h
+33.91 1.793 m
+33.91 1.352 33.973 1.022 34.102 0.808 c
+34.237 0.602 34.457 0.5 34.763 0.5 c
+35.086 0.5 35.325 0.661 35.483 0.984 c
+35.483 2.998 l
+35.314 3.31 35.075 3.469 34.763 3.469 c
+34.457 3.469 34.237 3.366 34.102 3.16 c
+33.973 2.954 33.91 2.63 33.91 2.19 c
+h
+37.173 0.353 m
+37.173 0.47 37.206 0.565 37.277 0.646 c
+37.343 0.723 37.445 0.764 37.585 0.764 c
+37.732 0.764 37.838 0.723 37.908 0.646 c
+37.985 0.565 38.026 0.47 38.026 0.353 c
+38.026 0.242 37.985 0.151 37.908 0.073 c
+37.838 -0.004 37.732 -0.044 37.585 -0.044 c
+37.445 -0.044 37.343 -0.004 37.277 0.073 c
+37.206 0.151 37.173 0.242 37.173 0.353 c
+f
+Q
+q 1 0 0 1 37.6521 155.6032 cm
+0 0 m
+2.646 4.835 l
+3.204 4.835 l
+0.588 0 l
+h
+6.059 0.515 m
+7.279 0.515 l
+7.279 0.058 l
+4.119 0.058 l
+4.119 0.515 l
+5.486 0.515 l
+5.486 4.38 l
+4.546 4.38 l
+4.546 4.835 l
+6.059 4.835 l
+h
+11.281 1.808 m
+11.281 1.502 11.241 1.234 11.164 0.999 c
+11.094 0.771 10.992 0.588 10.855 0.44 c
+10.726 0.294 10.565 0.18 10.37 0.103 c
+10.172 0.037 9.951 0 9.708 0 c
+9.473 0 9.261 0.037 9.076 0.103 c
+8.889 0.18 8.727 0.294 8.592 0.44 c
+8.452 0.588 8.345 0.771 8.268 0.999 c
+8.199 1.223 8.166 1.492 8.166 1.808 c
+8.166 2.403 8.301 2.851 8.577 3.145 c
+8.849 3.447 9.238 3.601 9.739 3.601 c
+10.256 3.601 10.643 3.447 10.899 3.145 c
+11.152 2.851 11.281 2.403 11.281 1.808 c
+10.679 1.808 m
+10.679 2.072 10.653 2.293 10.605 2.469 c
+10.554 2.645 10.487 2.782 10.4 2.881 c
+10.319 2.987 10.223 3.061 10.105 3.102 c
+9.995 3.149 9.874 3.175 9.739 3.175 c
+9.598 3.175 9.473 3.149 9.356 3.102 c
+9.238 3.061 9.136 2.987 9.047 2.881 c
+8.966 2.77 8.904 2.631 8.856 2.454 c
+8.804 2.278 8.783 2.061 8.783 1.808 c
+8.783 1.532 8.804 1.308 8.856 1.132 c
+8.904 0.955 8.966 0.812 9.047 0.706 c
+9.136 0.595 9.231 0.521 9.342 0.484 c
+9.459 0.444 9.58 0.426 9.708 0.426 c
+9.845 0.426 9.974 0.444 10.091 0.484 c
+10.209 0.521 10.311 0.595 10.4 0.706 c
+10.487 0.812 10.554 0.955 10.605 1.132 c
+10.653 1.308 10.679 1.532 10.679 1.808 c
+13.799 -1.309 m
+13.6 -1.309 13.431 -1.283 13.284 -1.235 c
+13.137 -1.195 13.009 -1.135 12.902 -1.058 c
+12.792 -0.989 12.704 -0.9 12.638 -0.794 c
+12.579 -0.684 12.534 -0.566 12.505 -0.441 c
+13.093 -0.368 l
+13.13 -0.522 13.211 -0.647 13.328 -0.736 c
+13.454 -0.823 13.615 -0.867 13.814 -0.867 c
+13.931 -0.867 14.038 -0.846 14.136 -0.809 c
+14.232 -0.779 14.317 -0.721 14.387 -0.632 c
+14.453 -0.551 14.508 -0.449 14.549 -0.324 c
+14.585 -0.195 14.607 -0.037 14.607 0.147 c
+14.607 0.764 l
+14.566 0.683 14.512 0.602 14.445 0.515 c
+14.387 0.434 14.306 0.359 14.21 0.294 c
+14.122 0.235 14.019 0.183 13.901 0.147 c
+13.784 0.118 13.652 0.103 13.504 0.103 c
+13.277 0.103 13.086 0.135 12.931 0.205 c
+12.785 0.272 12.66 0.374 12.564 0.515 c
+12.465 0.661 12.391 0.841 12.343 1.058 c
+12.292 1.282 12.27 1.535 12.27 1.822 c
+12.27 2.105 12.292 2.356 12.343 2.572 c
+12.391 2.786 12.465 2.969 12.564 3.116 c
+12.66 3.27 12.792 3.388 12.961 3.469 c
+13.126 3.546 13.328 3.586 13.564 3.586 c
+13.806 3.586 14.019 3.528 14.196 3.41 c
+14.372 3.299 14.508 3.145 14.607 2.94 c
+14.622 2.94 l
+14.622 3.116 l
+14.622 3.307 l
+14.629 3.366 14.637 3.414 14.637 3.454 c
+14.644 3.501 14.651 3.532 14.651 3.542 c
+15.21 3.542 l
+15.199 3.52 15.195 3.487 15.195 3.439 c
+15.195 3.388 15.188 3.329 15.181 3.262 c
+15.181 3.057 l
+15.181 2.822 l
+15.181 0.162 l
+15.181 -0.327 15.067 -0.695 14.842 -0.941 c
+14.614 -1.183 14.269 -1.309 13.799 -1.309 c
+14.607 1.837 m
+14.607 2.072 14.581 2.271 14.533 2.439 c
+14.483 2.616 14.416 2.752 14.328 2.851 c
+14.24 2.958 14.14 3.035 14.034 3.087 c
+13.924 3.135 13.818 3.16 13.71 3.16 c
+13.564 3.16 13.435 3.135 13.328 3.087 c
+13.23 3.035 13.145 2.958 13.078 2.851 c
+13.009 2.752 12.954 2.616 12.917 2.439 c
+12.887 2.271 12.873 2.072 12.873 1.837 c
+12.873 1.58 12.887 1.371 12.917 1.205 c
+12.954 1.036 13.005 0.9 13.064 0.793 c
+13.13 0.694 13.218 0.625 13.328 0.588 c
+13.435 0.548 13.556 0.529 13.696 0.529 c
+13.814 0.529 13.924 0.548 14.034 0.588 c
+14.14 0.635 14.232 0.709 14.313 0.808 c
+14.402 0.914 14.468 1.051 14.519 1.22 c
+14.578 1.385 14.607 1.591 14.607 1.837 c
+19.289 1.058 m
+19.289 0.889 19.252 0.738 19.186 0.602 c
+19.127 0.474 19.032 0.367 18.907 0.279 c
+18.789 0.191 18.642 0.121 18.466 0.073 c
+18.296 0.025 18.102 0 17.878 0 c
+17.672 0 17.485 0.014 17.319 0.044 c
+17.161 0.073 17.018 0.118 16.893 0.176 c
+16.775 0.242 16.673 0.33 16.584 0.44 c
+16.503 0.558 16.452 0.694 16.422 0.852 c
+16.922 0.955 l
+16.952 0.837 16.995 0.742 17.055 0.675 c
+17.113 0.606 17.18 0.551 17.261 0.515 c
+17.338 0.474 17.425 0.448 17.525 0.44 c
+17.631 0.43 17.749 0.426 17.878 0.426 c
+18.003 0.426 18.117 0.434 18.216 0.455 c
+18.323 0.474 18.414 0.503 18.495 0.544 c
+18.572 0.592 18.631 0.65 18.672 0.72 c
+18.719 0.786 18.745 0.87 18.745 0.97 c
+18.745 1.076 18.716 1.165 18.657 1.234 c
+18.605 1.3 18.532 1.356 18.437 1.396 c
+18.348 1.444 18.234 1.484 18.098 1.514 c
+17.97 1.543 17.834 1.58 17.687 1.631 c
+17.547 1.66 17.411 1.693 17.275 1.734 c
+17.136 1.782 17.014 1.841 16.908 1.911 c
+16.797 1.977 16.709 2.065 16.643 2.175 c
+16.584 2.281 16.555 2.418 16.555 2.587 c
+16.555 2.899 16.665 3.145 16.893 3.322 c
+17.117 3.498 17.444 3.586 17.878 3.586 c
+18.054 3.586 18.216 3.572 18.363 3.542 c
+18.51 3.513 18.635 3.461 18.745 3.395 c
+18.863 3.326 18.958 3.237 19.039 3.131 c
+19.116 3.031 19.171 2.91 19.2 2.763 c
+18.686 2.69 l
+18.664 2.786 18.631 2.866 18.583 2.925 c
+18.532 2.984 18.473 3.027 18.407 3.057 c
+18.337 3.094 18.252 3.119 18.157 3.131 c
+18.069 3.149 17.973 3.16 17.878 3.16 c
+17.356 3.16 17.099 2.998 17.099 2.675 c
+17.099 2.576 17.117 2.499 17.157 2.439 c
+17.205 2.381 17.267 2.326 17.348 2.278 c
+17.437 2.238 17.54 2.204 17.658 2.175 c
+17.775 2.146 17.899 2.117 18.04 2.087 c
+18.175 2.046 18.319 2.003 18.466 1.955 c
+18.613 1.914 18.745 1.855 18.863 1.778 c
+18.988 1.708 19.09 1.616 19.171 1.499 c
+19.248 1.381 19.289 1.234 19.289 1.058 c
+20.307 0 m
+22.952 4.835 l
+23.511 4.835 l
+20.895 0 l
+h
+26.161 3.881 m
+27.013 4.203 l
+27.145 3.792 l
+26.249 3.557 l
+26.836 2.749 l
+26.455 2.514 l
+25.969 3.351 l
+25.47 2.528 l
+25.088 2.749 l
+25.705 3.557 l
+24.793 3.792 l
+24.941 4.218 l
+25.808 3.865 l
+25.764 4.821 l
+26.204 4.821 l
+h
+f
+Q
+q 1 0 0 1 39.5044 148.4743 cm
+0 0 m
+-0.485 0 l
+-0.559 3.057 l
+0.073 3.057 l
+h
+-0.559 -0.632 0.617 -0.647 re
+-0.559 -1.279 m
+4.207 -0.823 m
+5.427 -0.823 l
+5.427 -1.279 l
+2.267 -1.279 l
+2.267 -0.823 l
+3.634 -0.823 l
+3.634 3.042 l
+2.693 3.042 l
+2.693 3.498 l
+4.207 3.498 l
+h
+9.429 0.47 m
+9.429 0.165 9.389 -0.103 9.311 -0.339 c
+9.242 -0.566 9.139 -0.75 9.003 -0.897 c
+8.874 -1.044 8.713 -1.158 8.517 -1.235 c
+8.32 -1.301 8.099 -1.338 7.856 -1.338 c
+7.621 -1.338 7.408 -1.301 7.224 -1.235 c
+7.037 -1.158 6.875 -1.044 6.739 -0.897 c
+6.599 -0.75 6.493 -0.566 6.416 -0.339 c
+6.346 -0.115 6.313 0.154 6.313 0.47 c
+6.313 1.065 6.449 1.514 6.724 1.807 c
+6.996 2.109 7.386 2.263 7.886 2.263 c
+8.404 2.263 8.79 2.109 9.047 1.807 c
+9.3 1.514 9.429 1.065 9.429 0.47 c
+8.827 0.47 m
+8.827 0.735 8.801 0.955 8.753 1.132 c
+8.702 1.308 8.635 1.444 8.548 1.543 c
+8.467 1.649 8.371 1.723 8.253 1.764 c
+8.143 1.811 8.022 1.837 7.886 1.837 c
+7.746 1.837 7.621 1.811 7.503 1.764 c
+7.386 1.723 7.283 1.649 7.195 1.543 c
+7.114 1.433 7.052 1.294 7.004 1.117 c
+6.952 0.941 6.93 0.723 6.93 0.47 c
+6.93 0.195 6.952 -0.03 7.004 -0.206 c
+7.052 -0.383 7.114 -0.526 7.195 -0.632 c
+7.283 -0.743 7.379 -0.817 7.489 -0.853 c
+7.607 -0.894 7.728 -0.912 7.856 -0.912 c
+7.993 -0.912 8.121 -0.894 8.239 -0.853 c
+8.357 -0.817 8.459 -0.743 8.548 -0.632 c
+8.635 -0.526 8.702 -0.383 8.753 -0.206 c
+8.801 -0.03 8.827 0.195 8.827 0.47 c
+11.946 -2.646 m
+11.748 -2.646 11.579 -2.621 11.432 -2.573 c
+11.285 -2.532 11.156 -2.473 11.05 -2.396 c
+10.94 -2.326 10.851 -2.238 10.786 -2.132 c
+10.726 -2.022 10.682 -1.904 10.653 -1.779 c
+11.241 -1.706 l
+11.278 -1.86 11.358 -1.985 11.476 -2.073 c
+11.601 -2.161 11.763 -2.205 11.962 -2.205 c
+12.079 -2.205 12.185 -2.183 12.284 -2.147 c
+12.38 -2.117 12.465 -2.058 12.534 -1.97 c
+12.6 -1.889 12.656 -1.786 12.696 -1.661 c
+12.733 -1.532 12.755 -1.374 12.755 -1.191 c
+12.755 -0.574 l
+12.714 -0.655 12.66 -0.736 12.593 -0.823 c
+12.534 -0.904 12.454 -0.978 12.358 -1.044 c
+12.27 -1.103 12.167 -1.154 12.049 -1.191 c
+11.931 -1.22 11.8 -1.235 11.652 -1.235 c
+11.424 -1.235 11.233 -1.202 11.079 -1.133 c
+10.932 -1.066 10.807 -0.963 10.711 -0.823 c
+10.612 -0.676 10.539 -0.497 10.491 -0.279 c
+10.439 -0.055 10.418 0.198 10.418 0.484 c
+10.418 0.768 10.439 1.018 10.491 1.234 c
+10.539 1.448 10.612 1.631 10.711 1.778 c
+10.807 1.932 10.94 2.05 11.108 2.131 c
+11.274 2.208 11.476 2.248 11.711 2.248 c
+11.954 2.248 12.167 2.19 12.343 2.072 c
+12.519 1.961 12.656 1.807 12.755 1.602 c
+12.77 1.602 l
+12.77 1.778 l
+12.77 1.969 l
+12.777 2.028 12.785 2.076 12.785 2.117 c
+12.791 2.164 12.799 2.194 12.799 2.204 c
+13.358 2.204 l
+13.346 2.183 13.343 2.15 13.343 2.102 c
+13.343 2.05 13.336 1.992 13.328 1.925 c
+13.328 1.72 l
+13.328 1.484 l
+13.328 -1.176 l
+13.328 -1.665 13.215 -2.033 12.99 -2.278 c
+12.762 -2.521 12.417 -2.646 11.946 -2.646 c
+12.755 0.5 m
+12.755 0.735 12.729 0.933 12.681 1.102 c
+12.63 1.278 12.564 1.414 12.476 1.514 c
+12.388 1.62 12.288 1.697 12.182 1.749 c
+12.072 1.797 11.965 1.822 11.858 1.822 c
+11.711 1.822 11.582 1.797 11.476 1.749 c
+11.377 1.697 11.293 1.62 11.226 1.514 c
+11.156 1.414 11.102 1.278 11.065 1.102 c
+11.035 0.933 11.021 0.735 11.021 0.5 c
+11.021 0.242 11.035 0.033 11.065 -0.133 c
+11.102 -0.302 11.152 -0.437 11.212 -0.545 c
+11.278 -0.643 11.366 -0.713 11.476 -0.75 c
+11.582 -0.79 11.704 -0.809 11.844 -0.809 c
+11.962 -0.809 12.072 -0.79 12.182 -0.75 c
+12.288 -0.703 12.38 -0.628 12.461 -0.53 c
+12.549 -0.423 12.615 -0.287 12.667 -0.118 c
+12.725 0.047 12.755 0.253 12.755 0.5 c
+17.437 -0.279 m
+17.437 -0.449 17.4 -0.599 17.334 -0.736 c
+17.275 -0.864 17.18 -0.971 17.055 -1.058 c
+16.937 -1.147 16.789 -1.216 16.613 -1.264 c
+16.444 -1.312 16.249 -1.338 16.025 -1.338 c
+15.819 -1.338 15.632 -1.324 15.467 -1.294 c
+15.309 -1.264 15.166 -1.22 15.041 -1.162 c
+14.923 -1.096 14.82 -1.008 14.732 -0.897 c
+14.651 -0.78 14.599 -0.643 14.57 -0.485 c
+15.07 -0.383 l
+15.1 -0.5 15.143 -0.595 15.202 -0.662 c
+15.261 -0.732 15.327 -0.786 15.408 -0.823 c
+15.486 -0.864 15.573 -0.89 15.673 -0.897 c
+15.779 -0.908 15.897 -0.912 16.025 -0.912 c
+16.151 -0.912 16.264 -0.904 16.363 -0.882 c
+16.47 -0.864 16.562 -0.834 16.643 -0.794 c
+16.72 -0.746 16.779 -0.688 16.819 -0.618 c
+16.867 -0.551 16.893 -0.468 16.893 -0.368 c
+16.893 -0.262 16.864 -0.173 16.804 -0.103 c
+16.753 -0.038 16.679 0.018 16.584 0.058 c
+16.496 0.106 16.382 0.147 16.246 0.176 c
+16.118 0.205 15.981 0.242 15.835 0.294 c
+15.694 0.323 15.559 0.356 15.422 0.396 c
+15.283 0.444 15.162 0.503 15.056 0.573 c
+14.945 0.639 14.857 0.727 14.79 0.837 c
+14.732 0.944 14.703 1.08 14.703 1.249 c
+14.703 1.562 14.813 1.807 15.041 1.984 c
+15.264 2.16 15.592 2.248 16.025 2.248 c
+16.201 2.248 16.363 2.234 16.511 2.204 c
+16.658 2.175 16.783 2.123 16.893 2.057 c
+17.01 1.988 17.105 1.899 17.186 1.793 c
+17.264 1.693 17.319 1.572 17.348 1.425 c
+16.834 1.352 l
+16.812 1.448 16.779 1.529 16.731 1.587 c
+16.679 1.646 16.621 1.69 16.554 1.72 c
+16.485 1.756 16.4 1.782 16.305 1.793 c
+16.216 1.811 16.121 1.822 16.025 1.822 c
+15.503 1.822 15.247 1.66 15.247 1.337 c
+15.247 1.238 15.264 1.161 15.305 1.102 c
+15.353 1.043 15.415 0.988 15.496 0.941 c
+15.584 0.9 15.688 0.866 15.805 0.837 c
+15.923 0.808 16.047 0.779 16.187 0.749 c
+16.323 0.708 16.467 0.665 16.613 0.617 c
+16.76 0.577 16.893 0.517 17.01 0.44 c
+17.136 0.371 17.238 0.278 17.319 0.161 c
+17.396 0.043 17.437 -0.103 17.437 -0.279 c
+18.454 -1.338 m
+21.1 3.498 l
+21.659 3.498 l
+19.042 -1.338 l
+h
+23.75 -0.324 0.75 -0.956 re
+23.75 -1.279 m
+28.193 -2.646 m
+27.995 -2.646 27.825 -2.621 27.678 -2.573 c
+27.531 -2.532 27.403 -2.473 27.296 -2.396 c
+27.186 -2.326 27.097 -2.238 27.031 -2.132 c
+26.973 -2.022 26.929 -1.904 26.9 -1.779 c
+27.487 -1.706 l
+27.524 -1.86 27.605 -1.985 27.723 -2.073 c
+27.847 -2.161 28.009 -2.205 28.207 -2.205 c
+28.325 -2.205 28.431 -2.183 28.531 -2.147 c
+28.626 -2.117 28.71 -2.058 28.781 -1.97 c
+28.847 -1.889 28.901 -1.786 28.942 -1.661 c
+28.979 -1.532 29.001 -1.374 29.001 -1.191 c
+29.001 -0.574 l
+28.961 -0.655 28.905 -0.736 28.839 -0.823 c
+28.781 -0.904 28.7 -0.978 28.604 -1.044 c
+28.516 -1.103 28.413 -1.154 28.296 -1.191 c
+28.178 -1.22 28.045 -1.235 27.899 -1.235 c
+27.671 -1.235 27.48 -1.202 27.326 -1.133 c
+27.178 -1.066 27.054 -0.963 26.958 -0.823 c
+26.859 -0.676 26.785 -0.497 26.738 -0.279 c
+26.686 -0.055 26.664 0.198 26.664 0.484 c
+26.664 0.768 26.686 1.018 26.738 1.234 c
+26.785 1.448 26.859 1.631 26.958 1.778 c
+27.054 1.932 27.186 2.05 27.355 2.131 c
+27.52 2.208 27.723 2.248 27.958 2.248 c
+28.2 2.248 28.413 2.19 28.589 2.072 c
+28.766 1.961 28.901 1.807 29.001 1.602 c
+29.016 1.602 l
+29.016 1.778 l
+29.016 1.969 l
+29.023 2.028 29.03 2.076 29.03 2.117 c
+29.038 2.164 29.045 2.194 29.045 2.204 c
+29.604 2.204 l
+29.593 2.183 29.589 2.15 29.589 2.102 c
+29.589 2.05 29.582 1.992 29.574 1.925 c
+29.574 1.72 l
+29.574 1.484 l
+29.574 -1.176 l
+29.574 -1.665 29.46 -2.033 29.236 -2.278 c
+29.009 -2.521 28.663 -2.646 28.193 -2.646 c
+29.001 0.5 m
+29.001 0.735 28.976 0.933 28.928 1.102 c
+28.876 1.278 28.81 1.414 28.722 1.514 c
+28.633 1.62 28.535 1.697 28.428 1.749 c
+28.317 1.797 28.211 1.822 28.105 1.822 c
+27.958 1.822 27.829 1.797 27.723 1.749 c
+27.623 1.697 27.538 1.62 27.472 1.514 c
+27.403 1.414 27.347 1.278 27.311 1.102 c
+27.281 0.933 27.266 0.735 27.266 0.5 c
+27.266 0.242 27.281 0.033 27.311 -0.133 c
+27.347 -0.302 27.399 -0.437 27.457 -0.545 c
+27.524 -0.643 27.612 -0.713 27.723 -0.75 c
+27.829 -0.79 27.95 -0.809 28.09 -0.809 c
+28.207 -0.809 28.317 -0.79 28.428 -0.75 c
+28.535 -0.703 28.626 -0.628 28.707 -0.53 c
+28.795 -0.423 28.861 -0.287 28.913 -0.118 c
+28.972 0.047 29.001 0.253 29.001 0.5 c
+32.664 -0.823 m
+33.885 -0.823 l
+33.885 -1.279 l
+30.725 -1.279 l
+30.725 -0.823 l
+32.091 -0.823 l
+32.091 1.749 l
+31.062 1.749 l
+31.062 2.204 l
+32.664 2.204 l
+h
+32.018 3.498 0.646 -0.617 re
+32.018 2.881 m
+34.95 1.749 m
+34.95 2.204 l
+35.494 2.204 l
+35.671 3.101 l
+36.068 3.101 l
+36.068 2.204 l
+37.449 2.204 l
+37.449 1.749 l
+36.068 1.749 l
+36.068 -0.353 l
+36.068 -0.522 36.111 -0.647 36.2 -0.736 c
+36.288 -0.817 36.439 -0.853 36.656 -0.853 c
+36.733 -0.853 36.817 -0.849 36.905 -0.838 c
+37.001 -0.831 37.09 -0.82 37.171 -0.809 c
+37.258 -0.801 37.335 -0.79 37.406 -0.78 c
+37.483 -0.772 37.545 -0.757 37.597 -0.736 c
+37.597 -1.176 l
+37.556 -1.199 37.497 -1.216 37.42 -1.235 c
+37.339 -1.246 37.25 -1.261 37.155 -1.279 c
+37.067 -1.287 36.968 -1.297 36.861 -1.309 c
+36.751 -1.327 36.641 -1.338 36.523 -1.338 c
+36.178 -1.338 35.92 -1.264 35.744 -1.118 c
+35.567 -0.971 35.48 -0.736 35.48 -0.412 c
+35.48 1.749 l
+h
+41.333 -1.279 m
+40.157 0.323 l
+39.731 0.014 l
+39.731 -1.279 l
+39.158 -1.279 l
+39.158 3.498 l
+39.731 3.498 l
+39.731 0.514 l
+41.26 2.204 l
+41.936 2.204 l
+40.525 0.706 l
+42.01 -1.279 l
+h
+43.483 0.338 m
+43.483 0.151 43.502 -0.023 43.542 -0.177 c
+43.59 -0.324 43.652 -0.452 43.733 -0.559 c
+43.81 -0.669 43.91 -0.757 44.028 -0.823 c
+44.152 -0.882 44.296 -0.912 44.454 -0.912 c
+44.571 -0.912 44.678 -0.897 44.776 -0.867 c
+44.884 -0.838 44.975 -0.805 45.056 -0.765 c
+45.133 -0.717 45.196 -0.659 45.247 -0.588 c
+45.306 -0.522 45.343 -0.452 45.364 -0.383 c
+45.879 -0.515 l
+45.838 -0.614 45.784 -0.713 45.717 -0.809 c
+45.648 -0.908 45.556 -0.996 45.439 -1.073 c
+45.328 -1.154 45.192 -1.216 45.027 -1.264 c
+44.869 -1.312 44.678 -1.338 44.454 -1.338 c
+44.207 -1.338 43.987 -1.301 43.792 -1.235 c
+43.594 -1.158 43.428 -1.044 43.292 -0.897 c
+43.164 -0.743 43.06 -0.551 42.983 -0.324 c
+42.914 -0.088 42.881 0.18 42.881 0.484 c
+42.881 0.816 42.917 1.095 42.998 1.323 c
+43.087 1.547 43.204 1.726 43.351 1.866 c
+43.498 2.013 43.663 2.117 43.851 2.175 c
+44.034 2.234 44.233 2.263 44.439 2.263 c
+44.722 2.263 44.957 2.219 45.144 2.131 c
+45.339 2.042 45.497 1.914 45.615 1.749 c
+45.74 1.591 45.828 1.396 45.879 1.161 c
+45.938 0.933 45.967 0.683 45.967 0.411 c
+45.967 0.338 l
+h
+44.439 1.837 m
+44.34 1.837 44.236 1.822 44.13 1.793 c
+44.02 1.764 43.917 1.705 43.822 1.616 c
+43.733 1.535 43.66 1.429 43.6 1.294 c
+43.542 1.165 43.505 0.992 43.498 0.779 c
+45.379 0.779 l
+45.358 0.984 45.321 1.15 45.262 1.278 c
+45.21 1.414 45.144 1.521 45.056 1.602 c
+44.975 1.69 44.884 1.749 44.776 1.778 c
+44.666 1.815 44.556 1.837 44.439 1.837 c
+47.544 0.338 m
+47.544 0.151 47.562 -0.023 47.602 -0.177 c
+47.65 -0.324 47.713 -0.452 47.793 -0.559 c
+47.87 -0.669 47.97 -0.757 48.088 -0.823 c
+48.213 -0.882 48.356 -0.912 48.514 -0.912 c
+48.632 -0.912 48.738 -0.897 48.838 -0.867 c
+48.944 -0.838 49.036 -0.805 49.117 -0.765 c
+49.194 -0.717 49.256 -0.659 49.308 -0.588 c
+49.366 -0.522 49.403 -0.452 49.426 -0.383 c
+49.94 -0.515 l
+49.9 -0.614 49.844 -0.713 49.778 -0.809 c
+49.709 -0.908 49.616 -0.996 49.499 -1.073 c
+49.389 -1.154 49.252 -1.216 49.087 -1.264 c
+48.93 -1.312 48.738 -1.338 48.514 -1.338 c
+48.267 -1.338 48.047 -1.301 47.853 -1.235 c
+47.654 -1.158 47.489 -1.044 47.353 -0.897 c
+47.224 -0.743 47.122 -0.551 47.044 -0.324 c
+46.974 -0.088 46.941 0.18 46.941 0.484 c
+46.941 0.816 46.978 1.095 47.059 1.323 c
+47.147 1.547 47.265 1.726 47.411 1.866 c
+47.558 2.013 47.724 2.117 47.911 2.175 c
+48.095 2.234 48.294 2.263 48.499 2.263 c
+48.782 2.263 49.017 2.219 49.204 2.131 c
+49.4 2.042 49.557 1.914 49.675 1.749 c
+49.8 1.591 49.888 1.396 49.94 1.161 c
+49.998 0.933 50.028 0.683 50.028 0.411 c
+50.028 0.338 l
+h
+48.499 1.837 m
+48.4 1.837 48.298 1.822 48.19 1.793 c
+48.08 1.764 47.978 1.705 47.882 1.616 c
+47.793 1.535 47.72 1.429 47.662 1.294 c
+47.602 1.165 47.566 0.992 47.558 0.779 c
+49.44 0.779 l
+49.418 0.984 49.381 1.15 49.322 1.278 c
+49.271 1.414 49.204 1.521 49.117 1.602 c
+49.036 1.69 48.944 1.749 48.838 1.778 c
+48.727 1.815 48.616 1.837 48.499 1.837 c
+54.074 0.47 m
+54.074 0.213 54.052 -0.026 54.015 -0.25 c
+53.975 -0.478 53.905 -0.673 53.809 -0.838 c
+53.711 -0.996 53.578 -1.118 53.412 -1.206 c
+53.254 -1.294 53.06 -1.338 52.824 -1.338 c
+52.707 -1.338 52.593 -1.327 52.487 -1.309 c
+52.377 -1.287 52.273 -1.257 52.178 -1.206 c
+52.09 -1.158 52.005 -1.099 51.928 -1.029 c
+51.858 -0.952 51.799 -0.861 51.752 -0.75 c
+51.737 -0.75 l
+51.737 -0.809 l
+51.744 -0.838 51.752 -0.879 51.752 -0.927 c
+51.752 -1.103 l
+51.752 -1.279 l
+51.752 -2.646 l
+51.163 -2.646 l
+51.163 1.484 l
+51.163 1.72 l
+51.163 1.94 l
+51.163 2.006 51.156 2.061 51.149 2.102 c
+51.149 2.204 l
+51.708 2.204 l
+51.714 2.194 51.722 2.167 51.722 2.131 c
+51.722 1.984 l
+51.729 1.932 51.737 1.874 51.737 1.807 c
+51.744 1.738 51.752 1.679 51.752 1.631 c
+51.766 1.631 l
+51.814 1.738 51.872 1.83 51.943 1.911 c
+52.009 1.999 52.082 2.065 52.163 2.117 c
+52.251 2.164 52.347 2.204 52.458 2.234 c
+52.564 2.263 52.685 2.278 52.824 2.278 c
+53.06 2.278 53.254 2.234 53.412 2.146 c
+53.578 2.057 53.711 1.932 53.809 1.778 c
+53.905 1.62 53.975 1.429 54.015 1.205 c
+54.052 0.988 54.074 0.742 54.074 0.47 c
+53.486 0.47 m
+53.486 0.683 53.472 0.874 53.442 1.043 c
+53.42 1.209 53.376 1.352 53.31 1.469 c
+53.251 1.587 53.166 1.675 53.06 1.734 c
+52.95 1.793 52.817 1.822 52.663 1.822 c
+52.545 1.822 52.427 1.801 52.31 1.764 c
+52.2 1.723 52.104 1.649 52.016 1.543 c
+51.935 1.444 51.872 1.3 51.825 1.117 c
+51.774 0.929 51.752 0.694 51.752 0.411 c
+51.752 0.154 51.77 -0.055 51.81 -0.221 c
+51.847 -0.39 51.906 -0.526 51.987 -0.632 c
+52.064 -0.732 52.156 -0.805 52.266 -0.853 c
+52.383 -0.894 52.516 -0.912 52.663 -0.912 c
+52.817 -0.912 52.946 -0.882 53.045 -0.823 c
+53.152 -0.765 53.236 -0.676 53.295 -0.559 c
+53.361 -0.441 53.412 -0.294 53.442 -0.118 c
+53.472 0.058 53.486 0.253 53.486 0.47 c
+f
+Q
+q 1 0 0 1 37.6521 138.6699 cm
+0 0 m
+2.646 4.835 l
+3.204 4.835 l
+0.588 0 l
+h
+4.31 3.087 m
+4.31 3.542 l
+4.854 3.542 l
+5.031 4.438 l
+5.428 4.438 l
+5.428 3.542 l
+6.809 3.542 l
+6.809 3.087 l
+5.428 3.087 l
+5.428 0.985 l
+5.428 0.816 5.471 0.691 5.56 0.602 c
+5.648 0.521 5.799 0.484 6.016 0.484 c
+6.093 0.484 6.177 0.488 6.265 0.5 c
+6.361 0.507 6.449 0.517 6.53 0.529 c
+6.618 0.536 6.695 0.548 6.765 0.558 c
+6.842 0.565 6.905 0.58 6.957 0.602 c
+6.957 0.162 l
+6.916 0.139 6.857 0.121 6.78 0.103 c
+6.699 0.091 6.611 0.077 6.516 0.058 c
+6.427 0.051 6.328 0.04 6.221 0.029 c
+6.111 0.01 6.001 0 5.883 0 c
+5.538 0 5.28 0.073 5.104 0.22 c
+4.928 0.367 4.84 0.602 4.84 0.926 c
+4.84 3.087 l
+h
+9.459 0.058 m
+9.459 2.263 l
+9.459 2.429 9.452 2.572 9.444 2.69 c
+9.433 2.807 9.415 2.899 9.386 2.969 c
+9.356 3.035 9.315 3.087 9.268 3.116 c
+9.216 3.145 9.157 3.16 9.091 3.16 c
+9.022 3.16 8.959 3.131 8.9 3.072 c
+8.849 3.021 8.801 2.944 8.754 2.836 c
+8.713 2.738 8.684 2.62 8.665 2.484 c
+8.644 2.344 8.636 2.19 8.636 2.013 c
+8.636 0.058 l
+8.092 0.058 l
+8.092 2.792 l
+8.092 3.027 l
+8.092 3.104 8.085 3.179 8.077 3.248 c
+8.077 3.439 l
+8.077 3.542 l
+8.548 3.542 l
+8.548 3.454 l
+8.555 3.414 8.563 3.366 8.563 3.307 c
+8.563 3.131 l
+8.569 3.072 8.577 3.017 8.577 2.969 c
+8.606 3.057 8.64 3.135 8.68 3.204 c
+8.717 3.281 8.761 3.351 8.812 3.41 c
+8.871 3.469 8.933 3.513 9.003 3.542 c
+9.08 3.579 9.168 3.601 9.268 3.601 c
+9.463 3.601 9.606 3.546 9.694 3.439 c
+9.789 3.34 9.86 3.182 9.899 2.969 c
+9.937 3.064 9.977 3.152 10.017 3.233 c
+10.065 3.31 10.12 3.373 10.179 3.424 c
+10.246 3.484 10.315 3.528 10.385 3.557 c
+10.462 3.586 10.554 3.601 10.664 3.601 c
+10.789 3.601 10.899 3.575 10.988 3.528 c
+11.075 3.476 11.15 3.403 11.208 3.307 c
+11.267 3.208 11.304 3.079 11.326 2.925 c
+11.355 2.778 11.37 2.594 11.37 2.381 c
+11.37 0.058 l
+10.826 0.058 l
+10.826 2.263 l
+10.826 2.429 10.819 2.572 10.811 2.69 c
+10.801 2.807 10.782 2.899 10.753 2.969 c
+10.723 3.035 10.682 3.087 10.635 3.116 c
+10.583 3.145 10.525 3.16 10.458 3.16 c
+10.319 3.16 10.209 3.064 10.12 2.881 c
+10.04 2.705 10.003 2.433 10.003 2.072 c
+10.003 0.058 l
+h
+15.312 1.808 m
+15.312 1.55 15.291 1.311 15.254 1.087 c
+15.214 0.86 15.144 0.665 15.048 0.5 c
+14.949 0.341 14.817 0.22 14.651 0.132 c
+14.493 0.044 14.298 0 14.063 0 c
+13.946 0 13.832 0.01 13.725 0.029 c
+13.615 0.051 13.512 0.081 13.417 0.132 c
+13.328 0.18 13.244 0.239 13.167 0.309 c
+13.097 0.386 13.038 0.477 12.991 0.588 c
+12.976 0.588 l
+12.976 0.529 l
+12.983 0.5 12.991 0.459 12.991 0.411 c
+12.991 0.235 l
+12.991 0.058 l
+12.991 -1.309 l
+12.403 -1.309 l
+12.403 2.822 l
+12.403 3.057 l
+12.403 3.278 l
+12.403 3.343 12.395 3.399 12.388 3.439 c
+12.388 3.542 l
+12.946 3.542 l
+12.954 3.532 12.961 3.505 12.961 3.469 c
+12.961 3.322 l
+12.968 3.27 12.976 3.212 12.976 3.145 c
+12.983 3.075 12.991 3.017 12.991 2.969 c
+13.005 2.969 l
+13.053 3.075 13.112 3.167 13.182 3.248 c
+13.247 3.337 13.321 3.403 13.402 3.454 c
+13.49 3.501 13.585 3.542 13.696 3.572 c
+13.803 3.601 13.924 3.615 14.063 3.615 c
+14.298 3.615 14.493 3.572 14.651 3.484 c
+14.817 3.395 14.949 3.27 15.048 3.116 c
+15.144 2.958 15.214 2.767 15.254 2.543 c
+15.291 2.326 15.312 2.08 15.312 1.808 c
+14.724 1.808 m
+14.724 2.021 14.71 2.212 14.68 2.381 c
+14.659 2.547 14.614 2.69 14.549 2.807 c
+14.489 2.925 14.406 3.013 14.298 3.072 c
+14.188 3.131 14.056 3.16 13.901 3.16 c
+13.784 3.16 13.666 3.138 13.549 3.102 c
+13.438 3.061 13.343 2.987 13.255 2.881 c
+13.174 2.782 13.112 2.638 13.064 2.454 c
+13.012 2.267 12.991 2.032 12.991 1.749 c
+12.991 1.492 13.009 1.282 13.049 1.117 c
+13.086 0.947 13.145 0.812 13.226 0.706 c
+13.303 0.606 13.394 0.532 13.504 0.484 c
+13.623 0.444 13.755 0.426 13.901 0.426 c
+14.056 0.426 14.184 0.455 14.284 0.515 c
+14.39 0.573 14.475 0.661 14.533 0.779 c
+14.6 0.897 14.651 1.043 14.68 1.22 c
+14.71 1.396 14.724 1.591 14.724 1.808 c
+f
+Q
+q 1 0 0 1 39.4451 134.0838 cm
+0 0 m
+0.853 0.323 l
+0.985 -0.088 l
+0.088 -0.324 l
+0.676 -1.132 l
+0.294 -1.367 l
+-0.191 -0.53 l
+-0.69 -1.353 l
+-1.072 -1.132 l
+-0.455 -0.324 l
+-1.367 -0.088 l
+-1.22 0.338 l
+-0.353 -0.015 l
+-0.397 0.941 l
+0.044 0.941 l
+h
+3.502 -2.866 0.75 -0.956 re
+3.502 -3.822 m
+9.371 -2.822 m
+9.371 -2.992 9.334 -3.142 9.268 -3.278 c
+9.209 -3.406 9.114 -3.514 8.989 -3.601 c
+8.871 -3.69 8.724 -3.759 8.548 -3.807 c
+8.379 -3.855 8.184 -3.881 7.96 -3.881 c
+7.754 -3.881 7.566 -3.866 7.401 -3.836 c
+7.243 -3.807 7.1 -3.763 6.975 -3.705 c
+6.857 -3.639 6.755 -3.55 6.666 -3.44 c
+6.585 -3.323 6.534 -3.186 6.504 -3.028 c
+7.005 -2.926 l
+7.034 -3.043 7.078 -3.138 7.136 -3.205 c
+7.196 -3.275 7.262 -3.329 7.342 -3.366 c
+7.42 -3.406 7.508 -3.433 7.607 -3.44 c
+7.713 -3.451 7.832 -3.454 7.96 -3.454 c
+8.085 -3.454 8.199 -3.447 8.298 -3.425 c
+8.405 -3.406 8.497 -3.377 8.577 -3.337 c
+8.654 -3.289 8.713 -3.23 8.754 -3.161 c
+8.802 -3.094 8.827 -3.01 8.827 -2.911 c
+8.827 -2.804 8.798 -2.716 8.739 -2.646 c
+8.688 -2.58 8.614 -2.525 8.518 -2.484 c
+8.43 -2.437 8.316 -2.396 8.181 -2.367 c
+8.052 -2.338 7.915 -2.301 7.769 -2.249 c
+7.629 -2.22 7.493 -2.187 7.358 -2.147 c
+7.217 -2.099 7.096 -2.04 6.99 -1.97 c
+6.88 -1.904 6.791 -1.816 6.725 -1.706 c
+6.666 -1.599 6.637 -1.463 6.637 -1.294 c
+6.637 -0.981 6.747 -0.736 6.975 -0.559 c
+7.199 -0.383 7.526 -0.294 7.96 -0.294 c
+8.136 -0.294 8.298 -0.309 8.445 -0.339 c
+8.592 -0.368 8.717 -0.42 8.827 -0.485 c
+8.945 -0.555 9.041 -0.643 9.121 -0.75 c
+9.199 -0.849 9.253 -0.971 9.282 -1.118 c
+8.769 -1.191 l
+8.746 -1.095 8.713 -1.014 8.665 -0.956 c
+8.614 -0.897 8.555 -0.853 8.489 -0.823 c
+8.419 -0.786 8.335 -0.761 8.239 -0.75 c
+8.151 -0.732 8.056 -0.721 7.96 -0.721 c
+7.438 -0.721 7.181 -0.882 7.181 -1.206 c
+7.181 -1.305 7.199 -1.382 7.24 -1.441 c
+7.287 -1.5 7.35 -1.555 7.431 -1.602 c
+7.518 -1.643 7.622 -1.676 7.739 -1.706 c
+7.857 -1.735 7.982 -1.764 8.121 -1.794 c
+8.258 -1.834 8.401 -1.878 8.548 -1.926 c
+8.694 -1.966 8.827 -2.025 8.945 -2.103 c
+9.07 -2.172 9.172 -2.264 9.253 -2.382 c
+9.33 -2.5 9.371 -2.646 9.371 -2.822 c
+13.299 -3.822 m
+12.638 -3.822 l
+12.182 -2.308 l
+12.16 -2.249 12.142 -2.187 12.123 -2.117 c
+12.102 -2.04 12.083 -1.966 12.065 -1.897 c
+12.035 -1.819 12.009 -1.742 11.991 -1.661 c
+11.969 -1.742 11.95 -1.819 11.932 -1.897 c
+11.91 -1.966 11.892 -2.04 11.873 -2.117 c
+11.851 -2.187 11.83 -2.257 11.8 -2.323 c
+11.329 -3.822 l
+10.683 -3.822 l
+10.095 -0.339 l
+10.668 -0.339 l
+10.962 -2.294 l
+10.969 -2.345 10.98 -2.419 10.992 -2.514 c
+10.999 -2.602 11.009 -2.701 11.021 -2.808 c
+11.028 -2.907 11.04 -3.007 11.05 -3.102 c
+11.057 -3.201 11.065 -3.278 11.065 -3.337 c
+11.094 -3.248 11.117 -3.161 11.138 -3.072 c
+11.157 -2.995 11.175 -2.918 11.198 -2.837 c
+11.215 -2.76 11.234 -2.701 11.256 -2.66 c
+11.682 -1.294 l
+12.314 -1.294 l
+12.726 -2.66 l
+12.733 -2.701 12.748 -2.76 12.771 -2.837 c
+12.788 -2.918 12.807 -2.992 12.829 -3.057 c
+12.858 -3.146 12.881 -3.242 12.902 -3.337 c
+12.902 -3.278 12.906 -3.201 12.917 -3.102 c
+12.925 -3.007 12.935 -2.907 12.946 -2.808 c
+12.954 -2.701 12.965 -2.602 12.976 -2.514 c
+12.994 -2.425 13.009 -2.352 13.02 -2.294 c
+13.343 -0.339 l
+13.902 -0.339 l
+h
+17.584 -2.072 m
+17.584 -2.33 17.562 -2.569 17.525 -2.793 c
+17.485 -3.021 17.415 -3.215 17.319 -3.381 c
+17.22 -3.539 17.088 -3.66 16.923 -3.749 c
+16.765 -3.836 16.57 -3.881 16.335 -3.881 c
+16.217 -3.881 16.103 -3.87 15.996 -3.851 c
+15.886 -3.83 15.784 -3.8 15.688 -3.749 c
+15.599 -3.701 15.515 -3.642 15.438 -3.572 c
+15.368 -3.495 15.31 -3.404 15.262 -3.293 c
+15.247 -3.293 l
+15.247 -3.352 l
+15.254 -3.381 15.262 -3.421 15.262 -3.469 c
+15.262 -3.645 l
+15.262 -3.822 l
+15.262 -5.189 l
+14.674 -5.189 l
+14.674 -1.058 l
+14.674 -0.823 l
+14.674 -0.603 l
+14.674 -0.537 14.666 -0.482 14.659 -0.441 c
+14.659 -0.339 l
+15.217 -0.339 l
+15.225 -0.349 15.232 -0.375 15.232 -0.412 c
+15.232 -0.559 l
+15.239 -0.611 15.247 -0.669 15.247 -0.736 c
+15.254 -0.805 15.262 -0.864 15.262 -0.912 c
+15.277 -0.912 l
+15.324 -0.805 15.383 -0.713 15.453 -0.632 c
+15.518 -0.544 15.593 -0.478 15.673 -0.426 c
+15.761 -0.379 15.857 -0.339 15.967 -0.309 c
+16.073 -0.279 16.195 -0.265 16.335 -0.265 c
+16.57 -0.265 16.765 -0.309 16.923 -0.397 c
+17.088 -0.485 17.22 -0.611 17.319 -0.765 c
+17.415 -0.923 17.485 -1.114 17.525 -1.338 c
+17.562 -1.555 17.584 -1.801 17.584 -2.072 c
+16.996 -2.072 m
+16.996 -1.86 16.981 -1.669 16.952 -1.5 c
+16.93 -1.334 16.885 -1.191 16.819 -1.073 c
+16.761 -0.956 16.676 -0.867 16.57 -0.809 c
+16.459 -0.75 16.327 -0.721 16.173 -0.721 c
+16.056 -0.721 15.938 -0.742 15.82 -0.779 c
+15.709 -0.819 15.614 -0.894 15.526 -1 c
+15.445 -1.099 15.383 -1.243 15.335 -1.426 c
+15.283 -1.613 15.262 -1.849 15.262 -2.132 c
+15.262 -2.389 15.279 -2.598 15.32 -2.764 c
+15.358 -2.933 15.416 -3.069 15.497 -3.175 c
+15.574 -3.275 15.666 -3.348 15.776 -3.396 c
+15.894 -3.437 16.025 -3.454 16.173 -3.454 c
+16.327 -3.454 16.455 -3.425 16.555 -3.366 c
+16.661 -3.308 16.746 -3.219 16.805 -3.102 c
+16.871 -2.984 16.923 -2.837 16.952 -2.66 c
+16.981 -2.484 16.996 -2.29 16.996 -2.072 c
+f
+Q
+0.793 0.801 0.129 0.016 k
+35.668 442.028 238.665 -21.457 re
+f
+0 0 0 0 k
+q 1 0 0 1 146.2115 426.5399 cm
+0 0 m
+-1.822 0 l
+-1.822 7.158 l
+-3.601 6.468 l
+-3.601 7.981 l
+-0.191 9.377 l
+0 9.377 l
+h
+3.047 0.926 m
+3.047 1.219 3.142 1.458 3.341 1.646 c
+3.535 1.83 3.789 1.925 4.105 1.925 c
+4.406 1.925 4.657 1.83 4.855 1.646 c
+5.06 1.458 5.164 1.219 5.164 0.926 c
+5.164 0.621 5.06 0.374 4.855 0.191 c
+4.657 0.014 4.406 -0.074 4.105 -0.074 c
+3.801 -0.074 3.547 0.018 3.341 0.205 c
+3.142 0.389 3.047 0.631 3.047 0.926 c
+16.416 1.058 m
+16.052 0.665 15.607 0.367 15.078 0.161 c
+14.549 -0.034 13.968 -0.133 13.343 -0.133 c
+12.263 -0.133 11.425 0.198 10.83 0.866 c
+10.231 1.532 9.926 2.502 9.918 3.777 c
+9.918 5.468 l
+9.918 6.761 10.198 7.754 10.756 8.452 c
+11.323 9.146 12.146 9.495 13.226 9.495 c
+14.244 9.495 15.009 9.238 15.519 8.731 c
+16.037 8.231 16.335 7.445 16.416 6.379 c
+14.579 6.379 l
+14.527 6.975 14.406 7.382 14.211 7.599 c
+14.012 7.812 13.704 7.922 13.285 7.922 c
+12.774 7.922 12.403 7.735 12.168 7.364 c
+11.94 6.989 11.822 6.397 11.815 5.585 c
+11.815 3.881 l
+11.815 3.027 11.94 2.403 12.197 2.013 c
+12.451 1.631 12.866 1.44 13.446 1.44 c
+13.818 1.44 14.122 1.514 14.358 1.66 c
+14.519 1.778 l
+14.519 3.498 l
+13.197 3.498 l
+13.197 4.924 l
+16.416 4.924 l
+h
+19.973 0 -1.897 9.363 re
+27.554 7.79 m
+25.232 7.79 l
+25.232 0 l
+23.335 0 l
+23.335 7.79 l
+21.057 7.79 l
+21.057 9.363 l
+27.554 9.363 l
+h
+37.913 3.116 m
+37.862 2.046 37.56 1.238 37.002 0.691 c
+36.451 0.139 35.678 -0.133 34.679 -0.133 c
+33.61 -0.133 32.79 0.213 32.224 0.911 c
+31.666 1.606 31.387 2.601 31.387 3.895 c
+31.387 5.468 l
+31.387 6.761 31.673 7.754 32.254 8.452 c
+32.842 9.146 33.654 9.495 34.694 9.495 c
+35.711 9.495 36.488 9.205 37.016 8.628 c
+37.546 8.058 37.847 7.239 37.928 6.173 c
+36.031 6.173 l
+36.01 6.838 35.906 7.294 35.723 7.54 c
+35.535 7.794 35.194 7.922 34.694 7.922 c
+34.194 7.922 33.834 7.746 33.621 7.393 c
+33.415 7.04 33.301 6.456 33.282 5.644 c
+33.282 3.881 l
+33.282 2.946 33.386 2.308 33.591 1.955 c
+33.805 1.609 34.169 1.44 34.679 1.44 c
+35.168 1.44 35.506 1.558 35.694 1.793 c
+35.888 2.036 35.995 2.476 36.017 3.116 c
+h
+45.887 3.836 m
+45.887 2.579 45.585 1.606 44.991 0.911 c
+44.392 0.213 43.568 -0.133 42.521 -0.133 c
+41.471 -0.133 40.644 0.209 40.037 0.897 c
+39.438 1.591 39.133 2.557 39.125 3.792 c
+39.125 5.394 l
+39.125 6.676 39.424 7.68 40.022 8.407 c
+40.617 9.132 41.448 9.495 42.506 9.495 c
+43.543 9.495 44.362 9.135 44.961 8.422 c
+45.568 7.717 45.876 6.721 45.887 5.438 c
+h
+43.991 5.409 m
+43.991 6.25 43.866 6.879 43.624 7.291 c
+43.389 7.702 43.013 7.908 42.506 7.908 c
+42.007 7.908 41.631 7.706 41.39 7.305 c
+41.155 6.912 41.029 6.312 41.022 5.512 c
+41.022 3.836 l
+41.022 3.02 41.143 2.418 41.39 2.028 c
+41.631 1.635 42.011 1.44 42.521 1.44 c
+43.01 1.44 43.374 1.631 43.609 2.013 c
+43.852 2.395 43.98 2.983 43.991 3.777 c
+h
+54.019 0 m
+52.124 0 l
+49.36 6.144 l
+49.36 0 l
+47.464 0 l
+47.464 9.363 l
+49.36 9.363 l
+52.124 3.218 l
+52.124 9.363 l
+54.019 9.363 l
+h
+60.608 3.821 m
+57.668 3.821 l
+57.668 0 l
+55.773 0 l
+55.773 9.363 l
+60.961 9.363 l
+60.961 7.79 l
+57.668 7.79 l
+57.668 5.394 l
+60.608 5.394 l
+h
+64.213 0 -1.896 9.363 re
+72.272 1.058 m
+71.908 0.665 71.463 0.367 70.935 0.161 c
+70.405 -0.034 69.825 -0.133 69.2 -0.133 c
+68.12 -0.133 67.282 0.198 66.686 0.866 c
+66.087 1.532 65.782 2.502 65.775 3.777 c
+65.775 5.468 l
+65.775 6.761 66.054 7.754 66.613 8.452 c
+67.179 9.146 68.002 9.495 69.082 9.495 c
+70.1 9.495 70.865 9.238 71.376 8.731 c
+71.893 8.231 72.191 7.445 72.272 6.379 c
+70.435 6.379 l
+70.383 6.975 70.262 7.382 70.067 7.599 c
+69.869 7.812 69.56 7.922 69.142 7.922 c
+68.631 7.922 68.259 7.735 68.024 7.364 c
+67.796 6.989 67.679 6.397 67.671 5.585 c
+67.671 3.881 l
+67.671 3.027 67.796 2.403 68.053 2.013 c
+68.307 1.631 68.722 1.44 69.302 1.44 c
+69.674 1.44 69.979 1.514 70.214 1.66 c
+70.376 1.778 l
+70.376 3.498 l
+69.053 3.498 l
+69.053 4.924 l
+72.272 4.924 l
+h
+79.945 9.363 m
+79.945 2.881 l
+79.934 1.911 79.666 1.165 79.137 0.646 c
+78.607 0.124 77.846 -0.133 76.858 -0.133 c
+75.858 -0.133 75.095 0.124 74.565 0.646 c
+74.036 1.176 73.771 1.932 73.771 2.925 c
+73.771 9.363 l
+75.667 9.363 l
+75.667 2.925 l
+75.667 2.385 75.748 2.002 75.918 1.778 c
+76.094 1.55 76.406 1.44 76.858 1.44 c
+77.306 1.44 77.615 1.55 77.784 1.778 c
+77.95 2.002 78.038 2.37 78.048 2.881 c
+78.048 9.363 l
+h
+84.431 3.424 m
+83.491 3.424 l
+83.491 0 l
+81.609 0 l
+81.609 9.363 l
+84.623 9.363 l
+85.571 9.363 86.302 9.117 86.813 8.628 c
+87.332 8.136 87.592 7.441 87.592 6.541 c
+87.592 5.294 87.14 4.424 86.239 3.924 c
+87.872 0.087 l
+87.872 0 l
+85.842 0 l
+h
+83.491 4.997 m
+84.564 4.997 l
+84.946 4.997 85.229 5.119 85.416 5.365 c
+85.601 5.618 85.696 5.957 85.696 6.379 c
+85.696 7.32 85.332 7.79 84.608 7.79 c
+83.491 7.79 l
+h
+93.578 1.911 m
+91.006 1.911 l
+90.506 0 l
+88.508 0 l
+91.432 9.363 l
+93.152 9.363 l
+96.107 0 l
+94.078 0 l
+h
+91.417 3.498 m
+93.167 3.498 l
+92.285 6.834 l
+h
+102.482 7.79 m
+100.16 7.79 l
+100.16 0 l
+98.264 0 l
+98.264 7.79 l
+95.986 7.79 l
+95.986 9.363 l
+102.482 9.363 l
+h
+105.753 0 -1.897 9.363 re
+114.047 3.836 m
+114.047 2.579 113.746 1.606 113.15 0.911 c
+112.551 0.213 111.728 -0.133 110.681 -0.133 c
+109.63 -0.133 108.803 0.209 108.196 0.897 c
+107.597 1.591 107.292 2.557 107.285 3.792 c
+107.285 5.394 l
+107.285 6.676 107.583 7.68 108.182 8.407 c
+108.777 9.132 109.607 9.495 110.666 9.495 c
+111.702 9.495 112.522 9.135 113.121 8.422 c
+113.727 7.717 114.036 6.721 114.047 5.438 c
+h
+112.15 5.409 m
+112.15 6.25 112.026 6.879 111.783 7.291 c
+111.548 7.702 111.173 7.908 110.666 7.908 c
+110.166 7.908 109.791 7.706 109.549 7.305 c
+109.314 6.912 109.189 6.312 109.181 5.512 c
+109.181 3.836 l
+109.181 3.02 109.303 2.418 109.549 2.028 c
+109.791 1.635 110.17 1.44 110.681 1.44 c
+111.169 1.44 111.533 1.631 111.768 2.013 c
+112.011 2.395 112.14 2.983 112.15 3.777 c
+h
+122.176 0 m
+120.279 0 l
+117.515 6.144 l
+117.515 0 l
+115.62 0 l
+115.62 9.363 l
+117.515 9.363 l
+120.279 3.218 l
+120.279 9.363 l
+122.176 9.363 l
+h
+f
+Q
+0.113 0.082 0.09 0 k
+35.668 411.726 238.665 -12.895 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 40.8563 404.8916 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.647 -0.243 -0.775 -0.367 -0.882 c
+-0.496 -0.992 -0.658 -1.081 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.162 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.927 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.132 l
+-2.642 0.033 -2.616 -0.059 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.683 -1.992 0.69 -1.999 0.69 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.881 -2.786 0.959 -2.91 1.058 c
+-3.039 1.153 -3.142 1.278 -3.219 1.425 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.836 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.119 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.119 -1.128 3.09 -0.97 3.042 c
+-0.804 2.992 -0.669 2.917 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.252 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.352 c
+-1.294 1.311 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.319 2.385 -2.366 2.337 c
+-2.406 2.296 -2.437 2.248 -2.454 2.19 c
+-2.477 2.131 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.778 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.469 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.091 -0.86 0.176 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.529 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.53 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.485 5.402 -2.396 c
+5.284 -2.315 5.185 -2.22 5.108 -2.103 c
+5.039 -1.985 4.991 -1.856 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.86 6.064 -1.941 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.058 6.681 -2.028 c
+6.758 -1.999 6.828 -1.945 6.887 -1.867 c
+6.945 -1.797 6.99 -1.706 7.019 -1.588 c
+7.056 -1.47 7.078 -1.323 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.073 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.412 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.234 c
+4.946 1.448 5.027 1.631 5.137 1.778 c
+5.245 1.933 5.376 2.051 5.534 2.131 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.252 6.387 2.234 c
+6.483 2.212 6.571 2.179 6.652 2.131 c
+6.739 2.08 6.817 2.017 6.887 1.94 c
+6.964 1.859 7.026 1.768 7.078 1.66 c
+7.092 1.66 l
+7.092 1.808 l
+7.1 1.866 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.152 2.219 c
+8.004 2.219 l
+7.993 2.138 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.162 l
+7.975 -1.415 7.938 -1.635 7.871 -1.823 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.529 m
+7.092 0.742 7.067 0.918 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.587 c
+6.571 1.624 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.62 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.339 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.177 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.529 c
+11.036 -0.647 m
+12.168 -0.647 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.647 l
+10.124 -0.647 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.676 re
+10.124 2.836 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.219 l
+13.644 2.219 l
+13.924 3.116 l
+14.497 3.116 l
+14.497 2.219 l
+15.732 2.219 l
+15.732 1.602 l
+14.497 1.602 l
+14.497 -0.103 l
+14.497 -0.324 l
+14.504 -0.393 14.527 -0.456 14.556 -0.515 c
+14.593 -0.566 14.648 -0.611 14.718 -0.647 c
+14.795 -0.676 14.909 -0.691 15.056 -0.691 c
+15.192 -0.691 15.327 -0.688 15.468 -0.676 c
+15.603 -0.658 15.736 -0.632 15.865 -0.603 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.231 15.629 -1.249 c
+15.549 -1.261 15.471 -1.268 15.394 -1.279 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.041 -1.301 14.942 -1.309 14.835 -1.309 c
+14.648 -1.309 14.486 -1.294 14.35 -1.264 c
+14.221 -1.228 14.107 -1.183 14.012 -1.132 c
+13.924 -1.085 13.85 -1.025 13.791 -0.956 c
+13.733 -0.879 13.689 -0.802 13.66 -0.721 c
+13.63 -0.632 13.608 -0.544 13.6 -0.456 c
+13.59 -0.36 13.586 -0.264 13.586 -0.177 c
+h
+22.677 -1.323 m
+22.391 -1.323 22.148 -1.282 21.943 -1.205 c
+21.737 -1.118 21.564 -0.996 21.428 -0.838 c
+21.288 -0.684 21.185 -0.497 21.119 -0.279 c
+21.049 -0.056 21.016 0.191 21.016 0.455 c
+21.016 0.75 21.049 1.007 21.119 1.234 c
+21.197 1.459 21.303 1.646 21.442 1.793 c
+21.589 1.947 21.766 2.065 21.972 2.146 c
+22.178 2.234 22.413 2.278 22.677 2.278 c
+22.901 2.278 23.104 2.248 23.28 2.19 c
+23.456 2.131 23.607 2.047 23.736 1.94 c
+23.861 1.841 23.963 1.72 24.044 1.573 c
+24.122 1.433 24.176 1.282 24.206 1.117 c
+23.295 1.072 l
+23.265 1.249 23.196 1.389 23.089 1.5 c
+22.99 1.606 22.846 1.66 22.662 1.66 c
+22.416 1.66 22.24 1.558 22.134 1.352 c
+22.023 1.153 21.972 0.867 21.972 0.484 c
+21.972 -0.309 22.207 -0.706 22.677 -0.706 c
+22.843 -0.706 22.986 -0.654 23.104 -0.544 c
+23.221 -0.437 23.295 -0.276 23.324 -0.059 c
+24.235 -0.103 l
+24.206 -0.272 24.151 -0.426 24.074 -0.574 c
+24.004 -0.721 23.901 -0.852 23.765 -0.97 c
+23.636 -1.081 23.478 -1.168 23.295 -1.235 c
+23.119 -1.294 22.913 -1.323 22.677 -1.323 c
+28.384 0.484 m
+28.384 0.209 28.347 -0.04 28.281 -0.264 c
+28.212 -0.482 28.108 -0.669 27.973 -0.823 c
+27.833 -0.981 27.657 -1.103 27.443 -1.191 c
+27.227 -1.279 26.973 -1.323 26.679 -1.323 c
+26.404 -1.323 26.157 -1.279 25.944 -1.191 c
+25.739 -1.103 25.566 -0.981 25.43 -0.823 c
+25.29 -0.669 25.187 -0.482 25.121 -0.264 c
+25.051 -0.04 25.018 0.209 25.018 0.484 c
+25.018 0.738 25.047 0.974 25.106 1.19 c
+25.172 1.415 25.275 1.606 25.415 1.764 c
+25.55 1.929 25.727 2.057 25.944 2.146 c
+26.157 2.234 26.414 2.278 26.709 2.278 c
+27.021 2.278 27.281 2.234 27.487 2.146 c
+27.701 2.057 27.873 1.929 28.002 1.764 c
+28.138 1.606 28.237 1.415 28.296 1.19 c
+28.355 0.974 28.384 0.738 28.384 0.484 c
+27.429 0.484 m
+27.429 0.69 27.414 0.867 27.385 1.014 c
+27.362 1.161 27.326 1.282 27.267 1.382 c
+27.208 1.477 27.135 1.547 27.046 1.587 c
+26.959 1.635 26.848 1.66 26.724 1.66 c
+26.458 1.66 26.267 1.562 26.15 1.367 c
+26.032 1.18 25.974 0.885 25.974 0.484 c
+25.974 0.062 26.032 -0.243 26.15 -0.426 c
+26.267 -0.614 26.444 -0.706 26.679 -0.706 c
+26.804 -0.706 26.918 -0.688 27.017 -0.647 c
+27.113 -0.599 27.194 -0.526 27.252 -0.426 c
+27.318 -0.331 27.362 -0.206 27.385 -0.059 c
+27.414 0.088 27.429 0.268 27.429 0.484 c
+31.43 -1.264 m
+31.43 0.72 l
+31.43 1.022 31.387 1.242 31.298 1.382 c
+31.217 1.529 31.081 1.602 30.886 1.602 c
+30.776 1.602 30.674 1.577 30.578 1.529 c
+30.489 1.477 30.409 1.411 30.343 1.323 c
+30.284 1.234 30.233 1.124 30.196 0.999 c
+30.167 0.881 30.152 0.75 30.152 0.602 c
+30.152 -1.264 l
+29.24 -1.264 l
+29.24 1.44 l
+29.24 1.66 l
+29.24 1.749 29.233 1.826 29.226 1.896 c
+29.226 2.087 l
+29.226 2.219 l
+30.078 2.219 l
+30.086 2.19 30.093 2.146 30.093 2.087 c
+30.093 1.896 l
+30.1 1.826 30.107 1.756 30.107 1.69 c
+30.115 1.62 30.122 1.565 30.122 1.529 c
+30.137 1.529 l
+30.254 1.793 30.406 1.984 30.593 2.102 c
+30.776 2.219 30.996 2.278 31.254 2.278 c
+31.438 2.278 31.599 2.248 31.74 2.19 c
+31.875 2.131 31.989 2.043 32.077 1.926 c
+32.166 1.808 32.228 1.664 32.268 1.5 c
+32.316 1.341 32.342 1.153 32.342 0.941 c
+32.342 -1.264 l
+h
+34.951 1.602 m
+34.951 -1.264 l
+34.054 -1.264 l
+34.054 1.602 l
+33.232 1.602 l
+33.232 2.219 l
+34.054 2.219 l
+34.054 2.484 l
+34.054 2.609 34.069 2.741 34.098 2.881 c
+34.135 3.017 34.205 3.135 34.304 3.233 c
+34.41 3.341 34.554 3.428 34.73 3.499 c
+34.907 3.564 35.131 3.601 35.407 3.601 c
+35.62 3.601 35.819 3.59 35.995 3.572 c
+36.17 3.549 36.322 3.532 36.45 3.513 c
+36.45 2.925 l
+36.322 2.944 36.178 2.958 36.024 2.969 c
+35.866 2.977 35.715 2.984 35.568 2.984 c
+35.44 2.984 35.337 2.969 35.26 2.94 c
+35.179 2.911 35.116 2.87 35.069 2.822 c
+35.017 2.77 34.984 2.708 34.965 2.631 c
+34.955 2.561 34.951 2.484 34.951 2.396 c
+34.951 2.219 l
+36.377 2.219 l
+36.377 1.602 l
+h
+39.467 -0.647 m
+40.599 -0.647 l
+40.599 -1.264 l
+37.292 -1.264 l
+37.292 -0.647 l
+38.556 -0.647 l
+38.556 1.602 l
+37.63 1.602 l
+37.63 2.219 l
+39.467 2.219 l
+h
+38.556 3.513 0.911 -0.676 re
+38.556 2.836 m
+42.954 -2.66 m
+42.738 -2.66 42.547 -2.635 42.381 -2.587 c
+42.212 -2.547 42.073 -2.485 41.955 -2.396 c
+41.837 -2.315 41.738 -2.22 41.661 -2.103 c
+41.591 -1.985 41.543 -1.856 41.514 -1.72 c
+42.41 -1.617 l
+42.447 -1.753 42.518 -1.86 42.616 -1.941 c
+42.712 -2.028 42.837 -2.072 42.984 -2.072 c
+43.072 -2.072 43.153 -2.058 43.234 -2.028 c
+43.311 -1.999 43.381 -1.945 43.44 -1.867 c
+43.499 -1.797 43.542 -1.706 43.572 -1.588 c
+43.609 -1.47 43.631 -1.323 43.631 -1.147 c
+43.631 -0.956 l
+43.631 -0.889 43.634 -0.831 43.646 -0.779 c
+43.646 -0.588 l
+43.631 -0.588 l
+43.532 -0.816 43.388 -0.977 43.204 -1.073 c
+43.017 -1.172 42.811 -1.22 42.587 -1.22 c
+42.381 -1.22 42.198 -1.183 42.044 -1.103 c
+41.896 -1.014 41.768 -0.897 41.661 -0.75 c
+41.562 -0.595 41.488 -0.412 41.441 -0.206 c
+41.389 0.008 41.367 0.243 41.367 0.5 c
+41.367 0.771 41.389 1.018 41.441 1.234 c
+41.5 1.448 41.58 1.631 41.691 1.778 c
+41.797 1.933 41.93 2.051 42.088 2.131 c
+42.242 2.219 42.429 2.263 42.646 2.263 c
+42.742 2.263 42.84 2.252 42.94 2.234 c
+43.035 2.212 43.123 2.179 43.204 2.131 c
+43.293 2.08 43.37 2.017 43.44 1.94 c
+43.517 1.859 43.58 1.768 43.631 1.66 c
+43.646 1.66 l
+43.646 1.808 l
+43.653 1.866 43.66 1.918 43.66 1.97 c
+43.667 2.028 43.675 2.076 43.675 2.117 c
+43.682 2.165 43.694 2.198 43.704 2.219 c
+44.557 2.219 l
+44.546 2.138 44.535 2.028 44.527 1.881 c
+44.527 1.411 l
+44.527 -1.162 l
+44.527 -1.415 44.49 -1.635 44.425 -1.823 c
+44.355 -2.007 44.251 -2.161 44.116 -2.278 c
+43.976 -2.404 43.811 -2.499 43.616 -2.558 c
+43.418 -2.624 43.197 -2.66 42.954 -2.66 c
+43.646 0.529 m
+43.646 0.742 43.619 0.918 43.572 1.058 c
+43.532 1.205 43.476 1.323 43.41 1.411 c
+43.351 1.5 43.282 1.558 43.204 1.587 c
+43.123 1.624 43.046 1.646 42.969 1.646 c
+42.87 1.646 42.778 1.62 42.69 1.573 c
+42.609 1.532 42.543 1.463 42.484 1.367 c
+42.433 1.278 42.389 1.161 42.352 1.014 c
+42.323 0.875 42.308 0.706 42.308 0.5 c
+42.308 0.125 42.366 -0.154 42.484 -0.339 c
+42.601 -0.515 42.763 -0.603 42.969 -0.603 c
+43.035 -0.603 43.109 -0.588 43.189 -0.559 c
+43.278 -0.522 43.351 -0.463 43.41 -0.382 c
+43.476 -0.294 43.532 -0.177 43.572 -0.029 c
+43.619 0.118 43.646 0.301 43.646 0.529 c
+50.135 0.837 1.867 -0.793 re
+50.135 0.044 m
+54.2 0.837 1.866 -0.793 re
+54.2 0.044 m
+59.201 -2.66 m
+58.983 -2.66 58.792 -2.635 58.628 -2.587 c
+58.458 -2.547 58.318 -2.485 58.201 -2.396 c
+58.083 -2.315 57.984 -2.22 57.907 -2.103 c
+57.838 -1.985 57.79 -1.856 57.76 -1.72 c
+58.657 -1.617 l
+58.694 -1.753 58.763 -1.86 58.863 -1.941 c
+58.958 -2.028 59.083 -2.072 59.23 -2.072 c
+59.318 -2.072 59.399 -2.058 59.48 -2.028 c
+59.557 -1.999 59.627 -1.945 59.686 -1.867 c
+59.744 -1.797 59.789 -1.706 59.818 -1.588 c
+59.855 -1.47 59.877 -1.323 59.877 -1.147 c
+59.877 -0.956 l
+59.877 -0.889 59.881 -0.831 59.891 -0.779 c
+59.891 -0.588 l
+59.877 -0.588 l
+59.777 -0.816 59.634 -0.977 59.451 -1.073 c
+59.263 -1.172 59.058 -1.22 58.833 -1.22 c
+58.628 -1.22 58.443 -1.183 58.289 -1.103 c
+58.142 -1.014 58.014 -0.897 57.907 -0.75 c
+57.807 -0.595 57.734 -0.412 57.687 -0.206 c
+57.635 0.008 57.613 0.243 57.613 0.5 c
+57.613 0.771 57.635 1.018 57.687 1.234 c
+57.745 1.448 57.826 1.631 57.936 1.778 c
+58.043 1.933 58.175 2.051 58.333 2.131 c
+58.488 2.219 58.675 2.263 58.892 2.263 c
+58.987 2.263 59.087 2.252 59.186 2.234 c
+59.282 2.212 59.37 2.179 59.451 2.131 c
+59.538 2.08 59.616 2.017 59.686 1.94 c
+59.763 1.859 59.825 1.768 59.877 1.66 c
+59.891 1.66 l
+59.891 1.808 l
+59.899 1.866 59.906 1.918 59.906 1.97 c
+59.914 2.028 59.921 2.076 59.921 2.117 c
+59.928 2.165 59.939 2.198 59.951 2.219 c
+60.803 2.219 l
+60.792 2.138 60.781 2.028 60.774 1.881 c
+60.774 1.411 l
+60.774 -1.162 l
+60.774 -1.415 60.737 -1.635 60.67 -1.823 c
+60.601 -2.007 60.498 -2.161 60.362 -2.278 c
+60.222 -2.404 60.057 -2.499 59.862 -2.558 c
+59.664 -2.624 59.443 -2.66 59.201 -2.66 c
+59.891 0.529 m
+59.891 0.742 59.866 0.918 59.818 1.058 c
+59.777 1.205 59.723 1.323 59.656 1.411 c
+59.598 1.5 59.528 1.558 59.451 1.587 c
+59.37 1.624 59.293 1.646 59.216 1.646 c
+59.116 1.646 59.024 1.62 58.936 1.573 c
+58.855 1.532 58.789 1.463 58.73 1.367 c
+58.679 1.278 58.634 1.161 58.598 1.014 c
+58.569 0.875 58.553 0.706 58.553 0.5 c
+58.553 0.125 58.613 -0.154 58.73 -0.339 c
+58.848 -0.515 59.01 -0.603 59.216 -0.603 c
+59.282 -0.603 59.355 -0.588 59.436 -0.559 c
+59.524 -0.522 59.598 -0.463 59.656 -0.382 c
+59.723 -0.294 59.777 -0.177 59.818 -0.029 c
+59.866 0.118 59.891 0.301 59.891 0.529 c
+63.835 -0.647 m
+64.967 -0.647 l
+64.967 -1.264 l
+61.659 -1.264 l
+61.659 -0.647 l
+62.923 -0.647 l
+62.923 2.896 l
+61.998 2.896 l
+61.998 3.513 l
+63.835 3.513 l
+h
+68.998 0.484 m
+68.998 0.209 68.961 -0.04 68.895 -0.264 c
+68.824 -0.482 68.722 -0.669 68.586 -0.823 c
+68.446 -0.981 68.27 -1.103 68.057 -1.191 c
+67.84 -1.279 67.586 -1.323 67.293 -1.323 c
+67.017 -1.323 66.771 -1.279 66.557 -1.191 c
+66.352 -1.103 66.179 -0.981 66.043 -0.823 c
+65.903 -0.669 65.801 -0.482 65.734 -0.264 c
+65.665 -0.04 65.632 0.209 65.632 0.484 c
+65.632 0.738 65.661 0.974 65.72 1.19 c
+65.786 1.415 65.888 1.606 66.029 1.764 c
+66.164 1.929 66.341 2.057 66.557 2.146 c
+66.771 2.234 67.028 2.278 67.322 2.278 c
+67.634 2.278 67.895 2.234 68.101 2.146 c
+68.314 2.057 68.487 1.929 68.616 1.764 c
+68.751 1.606 68.851 1.415 68.909 1.19 c
+68.968 0.974 68.998 0.738 68.998 0.484 c
+68.042 0.484 m
+68.042 0.69 68.028 0.867 67.999 1.014 c
+67.976 1.161 67.939 1.282 67.881 1.382 c
+67.822 1.477 67.748 1.547 67.66 1.587 c
+67.571 1.635 67.461 1.66 67.336 1.66 c
+67.072 1.66 66.881 1.562 66.763 1.367 c
+66.646 1.18 66.587 0.885 66.587 0.484 c
+66.587 0.062 66.646 -0.243 66.763 -0.426 c
+66.881 -0.614 67.058 -0.706 67.293 -0.706 c
+67.417 -0.706 67.531 -0.688 67.631 -0.647 c
+67.726 -0.599 67.807 -0.526 67.866 -0.426 c
+67.932 -0.331 67.976 -0.206 67.999 -0.059 c
+68.028 0.088 68.042 0.268 68.042 0.484 c
+69.854 -1.264 m
+69.854 -0.97 l
+69.861 -0.834 69.869 -0.676 69.869 -0.5 c
+69.869 3.513 l
+70.78 3.513 l
+70.78 2.234 l
+70.78 2.072 l
+70.78 1.896 l
+70.78 1.845 70.773 1.801 70.765 1.764 c
+70.765 1.675 l
+70.78 1.675 l
+70.827 1.782 70.89 1.874 70.971 1.955 c
+71.048 2.032 71.133 2.094 71.221 2.146 c
+71.309 2.194 71.401 2.227 71.5 2.248 c
+71.596 2.267 71.695 2.278 71.794 2.278 c
+72.007 2.278 72.194 2.234 72.352 2.146 c
+72.507 2.057 72.635 1.929 72.735 1.764 c
+72.841 1.606 72.919 1.415 72.97 1.19 c
+73.017 0.974 73.044 0.735 73.044 0.47 c
+73.044 0.213 73.015 -0.026 72.955 -0.25 c
+72.897 -0.467 72.812 -0.658 72.705 -0.823 c
+72.595 -0.981 72.463 -1.103 72.309 -1.191 c
+72.151 -1.279 71.97 -1.323 71.764 -1.323 c
+71.666 -1.323 71.567 -1.312 71.471 -1.294 c
+71.382 -1.272 71.294 -1.242 71.206 -1.191 c
+71.118 -1.132 71.037 -1.066 70.971 -0.985 c
+70.901 -0.908 70.839 -0.809 70.78 -0.691 c
+70.765 -0.691 l
+70.765 -0.852 l
+70.765 -0.912 70.758 -0.97 70.75 -1.029 c
+70.75 -1.081 70.743 -1.128 70.736 -1.176 c
+70.736 -1.216 70.729 -1.246 70.721 -1.264 c
+h
+70.765 0.5 m
+70.765 0.264 70.783 0.066 70.824 -0.088 c
+70.872 -0.246 70.931 -0.368 71 -0.456 c
+71.066 -0.544 71.14 -0.611 71.221 -0.647 c
+71.298 -0.688 71.375 -0.706 71.456 -0.706 c
+71.662 -0.706 71.816 -0.611 71.926 -0.412 c
+72.044 -0.217 72.103 0.077 72.103 0.47 c
+72.103 0.683 72.08 0.867 72.044 1.014 c
+72.015 1.168 71.97 1.294 71.912 1.382 c
+71.86 1.477 71.794 1.55 71.706 1.602 c
+71.625 1.65 71.537 1.675 71.442 1.675 c
+71.361 1.675 71.284 1.654 71.206 1.617 c
+71.126 1.577 71.052 1.514 70.985 1.425 c
+70.927 1.338 70.872 1.213 70.824 1.058 c
+70.783 0.912 70.765 0.723 70.765 0.5 c
+74.873 -1.323 m
+74.704 -1.323 74.554 -1.301 74.418 -1.264 c
+74.289 -1.216 74.175 -1.147 74.079 -1.058 c
+73.992 -0.97 73.921 -0.864 73.874 -0.735 c
+73.823 -0.599 73.8 -0.449 73.8 -0.279 c
+73.8 -0.073 73.834 0.095 73.904 0.235 c
+73.969 0.382 74.065 0.492 74.183 0.573 c
+74.308 0.661 74.451 0.723 74.609 0.764 c
+74.775 0.801 74.951 0.827 75.138 0.837 c
+75.858 0.852 l
+75.858 1.029 l
+75.858 1.147 75.847 1.249 75.829 1.338 c
+75.807 1.425 75.774 1.492 75.726 1.543 c
+75.685 1.602 75.638 1.639 75.579 1.66 c
+75.521 1.679 75.454 1.69 75.388 1.69 c
+75.318 1.69 75.255 1.679 75.197 1.66 c
+75.145 1.65 75.097 1.624 75.05 1.587 c
+75.01 1.558 74.976 1.506 74.947 1.44 c
+74.925 1.382 74.91 1.301 74.903 1.205 c
+73.962 1.249 l
+73.992 1.396 74.035 1.532 74.095 1.66 c
+74.16 1.785 74.256 1.896 74.374 1.984 c
+74.492 2.08 74.631 2.153 74.8 2.205 c
+74.976 2.252 75.182 2.278 75.417 2.278 c
+75.858 2.278 76.19 2.168 76.417 1.955 c
+76.652 1.749 76.77 1.44 76.77 1.029 c
+76.77 -0.235 l
+76.77 -0.456 l
+76.777 -0.515 76.792 -0.57 76.814 -0.617 c
+76.832 -0.658 76.861 -0.691 76.902 -0.721 c
+76.938 -0.742 76.99 -0.75 77.049 -0.75 c
+77.115 -0.75 77.185 -0.746 77.254 -0.735 c
+77.254 -1.22 l
+77.196 -1.231 77.141 -1.242 77.093 -1.249 c
+77.053 -1.261 77.013 -1.268 76.976 -1.279 c
+76.936 -1.286 76.891 -1.294 76.843 -1.294 c
+76.792 -1.301 76.733 -1.309 76.666 -1.309 c
+76.439 -1.309 76.273 -1.257 76.167 -1.147 c
+76.057 -1.029 75.995 -0.864 75.976 -0.647 c
+75.961 -0.647 l
+75.891 -0.757 75.822 -0.852 75.756 -0.941 c
+75.685 -1.022 75.608 -1.087 75.521 -1.147 c
+75.432 -1.205 75.333 -1.249 75.226 -1.279 c
+75.127 -1.309 75.01 -1.323 74.873 -1.323 c
+75.858 0.353 m
+75.432 0.338 l
+75.333 0.338 75.241 0.33 75.153 0.324 c
+75.072 0.312 75.006 0.287 74.947 0.249 c
+74.889 0.209 74.837 0.151 74.8 0.073 c
+74.76 0.004 74.741 -0.088 74.741 -0.206 c
+74.741 -0.375 74.775 -0.497 74.844 -0.574 c
+74.91 -0.654 75.01 -0.691 75.138 -0.691 c
+75.245 -0.691 75.344 -0.669 75.432 -0.617 c
+75.527 -0.57 75.608 -0.507 75.667 -0.426 c
+75.733 -0.349 75.785 -0.262 75.814 -0.162 c
+75.843 -0.056 75.858 0.058 75.858 0.176 c
+h
+80.08 -0.647 m
+81.212 -0.647 l
+81.212 -1.264 l
+77.905 -1.264 l
+77.905 -0.647 l
+79.17 -0.647 l
+79.17 2.896 l
+78.243 2.896 l
+78.243 3.513 l
+80.08 3.513 l
+h
+86.982 2.219 m
+86.982 0.264 l
+86.982 0.125 86.989 0 87.011 -0.118 c
+87.03 -0.228 87.063 -0.32 87.114 -0.397 c
+87.162 -0.478 87.221 -0.54 87.29 -0.588 c
+87.357 -0.628 87.441 -0.647 87.54 -0.647 c
+87.629 -0.647 87.71 -0.628 87.791 -0.588 c
+87.878 -0.54 87.952 -0.47 88.011 -0.382 c
+88.069 -0.287 88.113 -0.177 88.144 -0.059 c
+88.18 0.066 88.202 0.206 88.202 0.353 c
+88.202 2.219 l
+89.098 2.219 l
+89.098 -0.485 l
+89.098 -0.721 l
+89.106 -0.802 89.113 -0.879 89.113 -0.956 c
+89.113 -1.147 l
+89.121 -1.199 89.128 -1.235 89.128 -1.264 c
+88.275 -1.264 l
+88.265 -1.235 88.254 -1.199 88.246 -1.147 c
+88.246 -0.956 l
+88.246 -0.889 88.239 -0.819 88.231 -0.75 c
+88.231 -0.574 l
+88.217 -0.574 l
+88.099 -0.838 87.945 -1.029 87.761 -1.147 c
+87.585 -1.264 87.382 -1.323 87.159 -1.323 c
+86.953 -1.323 86.779 -1.286 86.644 -1.22 c
+86.504 -1.154 86.394 -1.058 86.305 -0.941 c
+86.225 -0.823 86.166 -0.688 86.129 -0.53 c
+86.1 -0.364 86.085 -0.187 86.085 0 c
+86.085 2.219 l
+h
+93.262 -0.25 m
+93.262 -0.419 93.222 -0.57 93.144 -0.706 c
+93.075 -0.834 92.971 -0.948 92.836 -1.044 c
+92.707 -1.132 92.545 -1.202 92.351 -1.249 c
+92.163 -1.297 91.947 -1.323 91.704 -1.323 c
+91.477 -1.323 91.278 -1.309 91.101 -1.279 c
+90.925 -1.249 90.767 -1.202 90.631 -1.132 c
+90.492 -1.055 90.382 -0.956 90.293 -0.838 c
+90.205 -0.721 90.135 -0.574 90.087 -0.397 c
+90.895 -0.279 l
+90.914 -0.379 90.943 -0.456 90.984 -0.515 c
+91.032 -0.574 91.09 -0.617 91.16 -0.647 c
+91.226 -0.676 91.307 -0.702 91.396 -0.721 c
+91.483 -0.732 91.587 -0.735 91.704 -0.735 c
+91.799 -0.735 91.895 -0.732 91.984 -0.721 c
+92.071 -0.702 92.148 -0.676 92.219 -0.647 c
+92.285 -0.617 92.336 -0.58 92.366 -0.53 c
+92.402 -0.482 92.424 -0.419 92.424 -0.339 c
+92.424 -0.243 92.395 -0.169 92.336 -0.118 c
+92.285 -0.07 92.219 -0.029 92.13 0 c
+92.042 0.037 91.932 0.066 91.807 0.088 c
+91.689 0.118 91.557 0.147 91.41 0.176 c
+91.271 0.213 91.13 0.253 90.984 0.293 c
+90.844 0.341 90.719 0.405 90.602 0.484 c
+90.492 0.562 90.403 0.661 90.337 0.779 c
+90.267 0.897 90.234 1.047 90.234 1.234 c
+90.234 1.389 90.263 1.532 90.322 1.66 c
+90.388 1.797 90.484 1.911 90.602 1.999 c
+90.727 2.087 90.885 2.153 91.072 2.205 c
+91.255 2.252 91.469 2.278 91.704 2.278 c
+91.888 2.278 92.065 2.256 92.233 2.219 c
+92.398 2.19 92.545 2.135 92.674 2.057 c
+92.799 1.988 92.909 1.889 92.998 1.764 c
+93.085 1.646 93.144 1.502 93.174 1.338 c
+92.38 1.264 l
+92.358 1.341 92.329 1.404 92.292 1.455 c
+92.252 1.514 92.204 1.558 92.144 1.587 c
+92.094 1.624 92.031 1.65 91.954 1.66 c
+91.873 1.668 91.793 1.675 91.704 1.675 c
+91.487 1.675 91.325 1.646 91.219 1.587 c
+91.109 1.536 91.057 1.448 91.057 1.323 c
+91.057 1.242 91.076 1.18 91.116 1.132 c
+91.164 1.08 91.226 1.043 91.307 1.014 c
+91.396 0.985 91.491 0.955 91.601 0.926 c
+91.708 0.904 91.829 0.881 91.969 0.852 c
+92.123 0.823 92.281 0.783 92.439 0.735 c
+92.593 0.683 92.733 0.621 92.85 0.544 c
+92.969 0.463 93.064 0.36 93.144 0.235 c
+93.222 0.106 93.262 -0.056 93.262 -0.25 c
+95.783 -1.323 m
+95.525 -1.323 95.298 -1.286 95.092 -1.22 c
+94.887 -1.143 94.71 -1.029 94.563 -0.882 c
+94.416 -0.728 94.299 -0.536 94.21 -0.309 c
+94.129 -0.085 94.093 0.18 94.093 0.484 c
+94.093 0.816 94.137 1.095 94.224 1.323 c
+94.32 1.558 94.449 1.741 94.607 1.881 c
+94.772 2.017 94.96 2.117 95.165 2.175 c
+95.371 2.242 95.581 2.278 95.797 2.278 c
+96.069 2.278 96.304 2.227 96.503 2.131 c
+96.709 2.043 96.875 1.911 97.003 1.735 c
+97.139 1.565 97.239 1.359 97.297 1.117 c
+97.363 0.881 97.399 0.617 97.399 0.324 c
+97.399 0.309 l
+95.033 0.309 l
+95.033 0.162 95.048 0.022 95.078 -0.103 c
+95.114 -0.231 95.169 -0.345 95.24 -0.441 c
+95.305 -0.53 95.39 -0.599 95.489 -0.647 c
+95.585 -0.698 95.699 -0.721 95.827 -0.721 c
+95.982 -0.721 96.121 -0.688 96.239 -0.617 c
+96.364 -0.551 96.452 -0.449 96.503 -0.309 c
+97.341 -0.382 l
+97.312 -0.482 97.256 -0.588 97.179 -0.706 c
+97.098 -0.816 96.996 -0.919 96.871 -1.014 c
+96.753 -1.103 96.599 -1.176 96.415 -1.235 c
+96.239 -1.294 96.026 -1.323 95.783 -1.323 c
+95.783 1.705 m
+95.695 1.705 95.606 1.69 95.518 1.66 c
+95.43 1.631 95.35 1.58 95.283 1.514 c
+95.213 1.444 95.155 1.356 95.107 1.249 c
+95.066 1.139 95.048 1.014 95.048 0.867 c
+96.518 0.867 l
+96.518 1.003 96.493 1.124 96.445 1.234 c
+96.404 1.341 96.349 1.429 96.283 1.5 c
+96.224 1.565 96.15 1.617 96.063 1.646 c
+95.974 1.683 95.878 1.705 95.783 1.705 c
+101.299 1.469 m
+101.2 1.477 101.097 1.488 100.99 1.5 c
+100.88 1.517 100.759 1.529 100.622 1.529 c
+100.446 1.529 100.288 1.488 100.152 1.411 c
+100.013 1.341 99.895 1.242 99.799 1.117 c
+99.711 0.989 99.641 0.841 99.593 0.676 c
+99.554 0.507 99.535 0.33 99.535 0.147 c
+99.535 -1.264 l
+98.638 -1.264 l
+98.638 0.985 l
+98.638 1.11 98.627 1.234 98.609 1.352 c
+98.598 1.477 98.583 1.595 98.565 1.705 c
+98.554 1.822 98.539 1.918 98.521 1.999 c
+98.498 2.087 98.48 2.161 98.462 2.219 c
+99.344 2.219 l
+99.351 2.168 99.362 2.117 99.373 2.057 c
+99.392 1.999 99.406 1.933 99.417 1.866 c
+99.435 1.808 99.45 1.741 99.462 1.675 c
+99.469 1.606 99.479 1.543 99.491 1.484 c
+99.506 1.484 l
+99.542 1.602 99.593 1.708 99.653 1.808 c
+99.718 1.903 99.799 1.988 99.888 2.057 c
+99.976 2.124 100.079 2.179 100.196 2.219 c
+100.321 2.256 100.468 2.278 100.637 2.278 c
+100.763 2.278 100.88 2.271 100.99 2.263 c
+101.108 2.252 101.21 2.238 101.299 2.219 c
+h
+103.404 -0.279 0.927 -0.985 re
+103.404 -1.264 m
+108.597 -1.264 m
+108.597 0.72 l
+108.597 1.022 108.553 1.242 108.464 1.382 c
+108.384 1.529 108.248 1.602 108.053 1.602 c
+107.942 1.602 107.84 1.577 107.745 1.529 c
+107.656 1.477 107.575 1.411 107.51 1.323 c
+107.45 1.234 107.399 1.124 107.362 0.999 c
+107.333 0.881 107.318 0.75 107.318 0.602 c
+107.318 -1.264 l
+106.407 -1.264 l
+106.407 1.44 l
+106.407 1.66 l
+106.407 1.749 106.399 1.826 106.392 1.896 c
+106.392 2.087 l
+106.392 2.219 l
+107.244 2.219 l
+107.252 2.19 107.259 2.146 107.259 2.087 c
+107.259 1.896 l
+107.267 1.826 107.274 1.756 107.274 1.69 c
+107.281 1.62 107.288 1.565 107.288 1.529 c
+107.304 1.529 l
+107.421 1.793 107.572 1.984 107.759 2.102 c
+107.942 2.219 108.163 2.278 108.42 2.278 c
+108.605 2.278 108.765 2.248 108.906 2.19 c
+109.041 2.131 109.156 2.043 109.243 1.926 c
+109.332 1.808 109.394 1.664 109.434 1.5 c
+109.482 1.341 109.509 1.153 109.509 0.941 c
+109.509 -1.264 l
+h
+111.423 -1.323 m
+111.254 -1.323 111.103 -1.301 110.967 -1.264 c
+110.839 -1.216 110.724 -1.147 110.629 -1.058 c
+110.541 -0.97 110.471 -0.864 110.423 -0.735 c
+110.372 -0.599 110.35 -0.449 110.35 -0.279 c
+110.35 -0.073 110.383 0.095 110.452 0.235 c
+110.519 0.382 110.614 0.492 110.732 0.573 c
+110.857 0.661 111 0.723 111.158 0.764 c
+111.323 0.801 111.5 0.827 111.687 0.837 c
+112.408 0.852 l
+112.408 1.029 l
+112.408 1.147 112.397 1.249 112.378 1.338 c
+112.356 1.425 112.323 1.492 112.275 1.543 c
+112.235 1.602 112.187 1.639 112.129 1.66 c
+112.069 1.679 112.003 1.69 111.938 1.69 c
+111.867 1.69 111.805 1.679 111.746 1.66 c
+111.695 1.65 111.647 1.624 111.599 1.587 c
+111.559 1.558 111.526 1.506 111.496 1.44 c
+111.474 1.382 111.46 1.301 111.452 1.205 c
+110.511 1.249 l
+110.541 1.396 110.585 1.532 110.644 1.66 c
+110.71 1.785 110.805 1.896 110.923 1.984 c
+111.04 2.08 111.18 2.153 111.35 2.205 c
+111.526 2.252 111.732 2.278 111.967 2.278 c
+112.408 2.278 112.738 2.168 112.966 1.955 c
+113.201 1.749 113.319 1.44 113.319 1.029 c
+113.319 -0.235 l
+113.319 -0.456 l
+113.326 -0.515 113.341 -0.57 113.363 -0.617 c
+113.382 -0.658 113.411 -0.691 113.451 -0.721 c
+113.488 -0.742 113.54 -0.75 113.598 -0.75 c
+113.665 -0.75 113.734 -0.746 113.804 -0.735 c
+113.804 -1.22 l
+113.745 -1.231 113.69 -1.242 113.642 -1.249 c
+113.602 -1.261 113.561 -1.268 113.525 -1.279 c
+113.484 -1.286 113.44 -1.294 113.392 -1.294 c
+113.341 -1.301 113.282 -1.309 113.216 -1.309 c
+112.988 -1.309 112.823 -1.257 112.717 -1.147 c
+112.606 -1.029 112.543 -0.864 112.526 -0.647 c
+112.511 -0.647 l
+112.441 -0.757 112.37 -0.852 112.305 -0.941 c
+112.235 -1.022 112.158 -1.087 112.069 -1.147 c
+111.981 -1.205 111.882 -1.249 111.776 -1.279 c
+111.676 -1.309 111.559 -1.323 111.423 -1.323 c
+112.408 0.353 m
+111.981 0.338 l
+111.882 0.338 111.79 0.33 111.702 0.324 c
+111.622 0.312 111.555 0.287 111.496 0.249 c
+111.437 0.209 111.386 0.151 111.35 0.073 c
+111.309 0.004 111.29 -0.088 111.29 -0.206 c
+111.29 -0.375 111.323 -0.497 111.393 -0.574 c
+111.46 -0.654 111.559 -0.691 111.687 -0.691 c
+111.794 -0.691 111.893 -0.669 111.981 -0.617 c
+112.077 -0.57 112.158 -0.507 112.216 -0.426 c
+112.283 -0.349 112.334 -0.262 112.364 -0.162 c
+112.393 -0.056 112.408 0.058 112.408 0.176 c
+h
+115.693 -1.264 m
+115.693 0.852 l
+115.693 1.018 115.686 1.153 115.678 1.264 c
+115.667 1.371 115.649 1.455 115.62 1.514 c
+115.597 1.58 115.568 1.631 115.531 1.66 c
+115.502 1.69 115.462 1.705 115.414 1.705 c
+115.354 1.705 115.3 1.675 115.252 1.617 c
+115.211 1.565 115.178 1.492 115.149 1.396 c
+115.119 1.308 115.094 1.194 115.076 1.058 c
+115.065 0.918 115.061 0.768 115.061 0.602 c
+115.061 -1.264 l
+114.311 -1.264 l
+114.311 1.469 l
+114.311 1.705 l
+114.311 1.926 l
+114.311 2.003 114.304 2.065 114.296 2.117 c
+114.296 2.219 l
+114.972 2.219 l
+114.972 2.131 l
+114.972 1.984 l
+114.98 1.926 114.988 1.866 114.988 1.808 c
+114.988 1.646 l
+115.002 1.646 l
+115.02 1.735 115.05 1.812 115.09 1.881 c
+115.127 1.959 115.171 2.028 115.223 2.087 c
+115.281 2.146 115.348 2.19 115.428 2.219 c
+115.506 2.256 115.593 2.278 115.693 2.278 c
+115.877 2.278 116.017 2.223 116.104 2.117 c
+116.2 2.017 116.27 1.859 116.31 1.646 c
+116.325 1.646 l
+116.362 1.741 116.402 1.83 116.443 1.911 c
+116.49 1.988 116.545 2.051 116.604 2.102 c
+116.663 2.161 116.729 2.205 116.81 2.234 c
+116.887 2.263 116.975 2.278 117.074 2.278 c
+117.21 2.278 117.324 2.252 117.413 2.205 c
+117.501 2.153 117.567 2.08 117.619 1.984 c
+117.677 1.885 117.714 1.756 117.736 1.602 c
+117.766 1.455 117.78 1.271 117.78 1.058 c
+117.78 -1.264 l
+117.06 -1.264 l
+117.06 0.852 l
+117.06 1.018 117.052 1.153 117.045 1.264 c
+117.035 1.371 117.016 1.455 116.987 1.514 c
+116.964 1.58 116.935 1.631 116.898 1.66 c
+116.869 1.69 116.829 1.705 116.781 1.705 c
+116.663 1.705 116.567 1.617 116.501 1.44 c
+116.443 1.271 116.413 1.014 116.413 0.661 c
+116.413 -1.264 l
+h
+120.15 -1.323 m
+119.893 -1.323 119.665 -1.286 119.46 -1.22 c
+119.254 -1.143 119.077 -1.029 118.93 -0.882 c
+118.783 -0.728 118.666 -0.536 118.577 -0.309 c
+118.496 -0.085 118.46 0.18 118.46 0.484 c
+118.46 0.816 118.504 1.095 118.592 1.323 c
+118.687 1.558 118.816 1.741 118.974 1.881 c
+119.14 2.017 119.327 2.117 119.533 2.175 c
+119.739 2.242 119.948 2.278 120.165 2.278 c
+120.437 2.278 120.672 2.227 120.871 2.131 c
+121.076 2.043 121.242 1.911 121.37 1.735 c
+121.506 1.565 121.606 1.359 121.664 1.117 c
+121.731 0.881 121.767 0.617 121.767 0.324 c
+121.767 0.309 l
+119.401 0.309 l
+119.401 0.162 119.416 0.022 119.445 -0.103 c
+119.481 -0.231 119.537 -0.345 119.607 -0.441 c
+119.672 -0.53 119.757 -0.599 119.857 -0.647 c
+119.952 -0.698 120.066 -0.721 120.195 -0.721 c
+120.349 -0.721 120.488 -0.688 120.606 -0.617 c
+120.731 -0.551 120.819 -0.449 120.871 -0.309 c
+121.708 -0.382 l
+121.679 -0.482 121.623 -0.588 121.546 -0.706 c
+121.465 -0.816 121.363 -0.919 121.238 -1.014 c
+121.12 -1.103 120.966 -1.176 120.782 -1.235 c
+120.606 -1.294 120.393 -1.323 120.15 -1.323 c
+120.15 1.705 m
+120.062 1.705 119.974 1.69 119.886 1.66 c
+119.798 1.631 119.717 1.58 119.651 1.514 c
+119.581 1.444 119.522 1.356 119.474 1.249 c
+119.433 1.139 119.416 1.014 119.416 0.867 c
+120.885 0.867 l
+120.885 1.003 120.86 1.124 120.812 1.234 c
+120.771 1.341 120.717 1.429 120.65 1.5 c
+120.591 1.565 120.518 1.617 120.43 1.646 c
+120.341 1.683 120.246 1.705 120.15 1.705 c
+129.286 1.455 m
+128.654 1.455 l
+128.521 3.513 l
+129.418 3.513 l
+h
+127.815 1.455 m
+127.184 1.455 l
+127.067 3.513 l
+127.933 3.513 l
+h
+132.758 0.529 m
+132.758 -1.264 l
+131.817 -1.264 l
+131.817 0.529 l
+130.333 3.072 l
+131.318 3.072 l
+132.288 1.249 l
+133.259 3.072 l
+134.258 3.072 l
+h
+138.043 0.484 m
+138.043 0.209 138.006 -0.04 137.94 -0.264 c
+137.87 -0.482 137.768 -0.669 137.631 -0.823 c
+137.492 -0.981 137.315 -1.103 137.102 -1.191 c
+136.885 -1.279 136.632 -1.323 136.338 -1.323 c
+136.062 -1.323 135.815 -1.279 135.603 -1.191 c
+135.397 -1.103 135.224 -0.981 135.088 -0.823 c
+134.948 -0.669 134.846 -0.482 134.78 -0.264 c
+134.71 -0.04 134.676 0.209 134.676 0.484 c
+134.676 0.738 134.706 0.974 134.765 1.19 c
+134.831 1.415 134.934 1.606 135.073 1.764 c
+135.21 1.929 135.386 2.057 135.603 2.146 c
+135.815 2.234 136.073 2.278 136.367 2.278 c
+136.679 2.278 136.941 2.234 137.146 2.146 c
+137.359 2.057 137.532 1.929 137.66 1.764 c
+137.797 1.606 137.895 1.415 137.955 1.19 c
+138.013 0.974 138.043 0.738 138.043 0.484 c
+137.087 0.484 m
+137.087 0.69 137.072 0.867 137.043 1.014 c
+137.022 1.161 136.985 1.282 136.926 1.382 c
+136.867 1.477 136.793 1.547 136.705 1.587 c
+136.617 1.635 136.507 1.66 136.382 1.66 c
+136.117 1.66 135.926 1.562 135.809 1.367 c
+135.691 1.18 135.632 0.885 135.632 0.484 c
+135.632 0.062 135.691 -0.243 135.809 -0.426 c
+135.926 -0.614 136.102 -0.706 136.338 -0.706 c
+136.463 -0.706 136.577 -0.688 136.675 -0.647 c
+136.771 -0.599 136.852 -0.526 136.91 -0.426 c
+136.977 -0.331 137.022 -0.206 137.043 -0.059 c
+137.072 0.088 137.087 0.268 137.087 0.484 c
+139.781 2.219 m
+139.781 0.264 l
+139.781 0.125 139.788 0 139.81 -0.118 c
+139.829 -0.228 139.862 -0.32 139.913 -0.397 c
+139.961 -0.478 140.02 -0.54 140.089 -0.588 c
+140.156 -0.628 140.241 -0.647 140.339 -0.647 c
+140.428 -0.647 140.509 -0.628 140.59 -0.588 c
+140.677 -0.54 140.751 -0.47 140.81 -0.382 c
+140.868 -0.287 140.912 -0.177 140.943 -0.059 c
+140.979 0.066 141.001 0.206 141.001 0.353 c
+141.001 2.219 l
+141.897 2.219 l
+141.897 -0.485 l
+141.897 -0.721 l
+141.905 -0.802 141.912 -0.879 141.912 -0.956 c
+141.912 -1.147 l
+141.92 -1.199 141.927 -1.235 141.927 -1.264 c
+141.074 -1.264 l
+141.063 -1.235 141.053 -1.199 141.045 -1.147 c
+141.045 -0.956 l
+141.045 -0.889 141.038 -0.819 141.03 -0.75 c
+141.03 -0.574 l
+141.016 -0.574 l
+140.898 -0.838 140.744 -1.029 140.56 -1.147 c
+140.384 -1.264 140.181 -1.323 139.958 -1.323 c
+139.752 -1.323 139.578 -1.286 139.443 -1.22 c
+139.303 -1.154 139.193 -1.058 139.104 -0.941 c
+139.024 -0.823 138.965 -0.688 138.928 -0.53 c
+138.899 -0.364 138.884 -0.187 138.884 0 c
+138.884 2.219 l
+h
+145.973 1.469 m
+145.874 1.477 145.77 1.488 145.664 1.5 c
+145.554 1.517 145.433 1.529 145.296 1.529 c
+145.12 1.529 144.962 1.488 144.826 1.411 c
+144.687 1.341 144.569 1.242 144.474 1.117 c
+144.386 0.989 144.316 0.841 144.268 0.676 c
+144.228 0.507 144.209 0.33 144.209 0.147 c
+144.209 -1.264 l
+143.312 -1.264 l
+143.312 0.985 l
+143.312 1.11 143.301 1.234 143.283 1.352 c
+143.272 1.477 143.258 1.595 143.239 1.705 c
+143.228 1.822 143.213 1.918 143.195 1.999 c
+143.173 2.087 143.154 2.161 143.136 2.219 c
+144.018 2.219 l
+144.025 2.168 144.037 2.117 144.047 2.057 c
+144.066 1.999 144.081 1.933 144.091 1.866 c
+144.11 1.808 144.124 1.741 144.135 1.675 c
+144.143 1.606 144.154 1.543 144.165 1.484 c
+144.18 1.484 l
+144.216 1.602 144.268 1.708 144.326 1.808 c
+144.393 1.903 144.474 1.988 144.562 2.057 c
+144.65 2.124 144.753 2.179 144.87 2.219 c
+144.995 2.256 145.142 2.278 145.311 2.278 c
+145.436 2.278 145.554 2.271 145.664 2.263 c
+145.782 2.252 145.885 2.238 145.973 2.219 c
+h
+153.036 -1.264 m
+151.801 1.984 l
+151.808 1.826 151.823 1.679 151.845 1.543 c
+151.845 1.352 l
+151.852 1.294 151.86 1.228 151.86 1.161 c
+151.867 1.103 151.875 1.043 151.875 0.985 c
+151.881 0.933 151.889 0.889 151.889 0.852 c
+151.889 -1.264 l
+151.066 -1.264 l
+151.066 3.072 l
+152.139 3.072 l
+153.404 -0.264 l
+153.381 -0.118 153.367 0.022 153.359 0.162 c
+153.348 0.287 153.337 0.415 153.33 0.544 c
+153.319 0.679 153.315 0.801 153.315 0.912 c
+153.315 3.072 l
+154.138 3.072 l
+154.138 -1.264 l
+h
+156.101 -1.323 m
+155.931 -1.323 155.781 -1.301 155.644 -1.264 c
+155.516 -1.216 155.403 -1.147 155.307 -1.058 c
+155.218 -0.97 155.149 -0.864 155.101 -0.735 c
+155.05 -0.599 155.027 -0.449 155.027 -0.279 c
+155.027 -0.073 155.06 0.095 155.131 0.235 c
+155.197 0.382 155.293 0.492 155.409 0.573 c
+155.534 0.661 155.678 0.723 155.836 0.764 c
+156.001 0.801 156.178 0.827 156.365 0.837 c
+157.086 0.852 l
+157.086 1.029 l
+157.086 1.147 157.074 1.249 157.055 1.338 c
+157.034 1.425 157.001 1.492 156.953 1.543 c
+156.913 1.602 156.865 1.639 156.806 1.66 c
+156.747 1.679 156.681 1.69 156.615 1.69 c
+156.546 1.69 156.483 1.679 156.424 1.66 c
+156.373 1.65 156.325 1.624 156.277 1.587 c
+156.236 1.558 156.203 1.506 156.174 1.44 c
+156.152 1.382 156.137 1.301 156.13 1.205 c
+155.189 1.249 l
+155.218 1.396 155.262 1.532 155.322 1.66 c
+155.388 1.785 155.484 1.896 155.601 1.984 c
+155.719 2.08 155.858 2.153 156.027 2.205 c
+156.203 2.252 156.409 2.278 156.644 2.278 c
+157.086 2.278 157.416 2.168 157.644 1.955 c
+157.88 1.749 157.996 1.44 157.996 1.029 c
+157.996 -0.235 l
+157.996 -0.456 l
+158.004 -0.515 158.019 -0.57 158.04 -0.617 c
+158.059 -0.658 158.088 -0.691 158.129 -0.721 c
+158.166 -0.742 158.217 -0.75 158.276 -0.75 c
+158.342 -0.75 158.412 -0.746 158.482 -0.735 c
+158.482 -1.22 l
+158.423 -1.231 158.368 -1.242 158.32 -1.249 c
+158.279 -1.261 158.239 -1.268 158.202 -1.279 c
+158.162 -1.286 158.118 -1.294 158.071 -1.294 c
+158.019 -1.301 157.96 -1.309 157.894 -1.309 c
+157.666 -1.309 157.5 -1.257 157.394 -1.147 c
+157.284 -1.029 157.221 -0.864 157.203 -0.647 c
+157.188 -0.647 l
+157.119 -0.757 157.049 -0.852 156.982 -0.941 c
+156.913 -1.022 156.835 -1.087 156.747 -1.147 c
+156.659 -1.205 156.56 -1.249 156.453 -1.279 c
+156.354 -1.309 156.236 -1.323 156.101 -1.323 c
+157.086 0.353 m
+156.659 0.338 l
+156.56 0.338 156.468 0.33 156.38 0.324 c
+156.299 0.312 156.233 0.287 156.174 0.249 c
+156.115 0.209 156.064 0.151 156.027 0.073 c
+155.987 0.004 155.968 -0.088 155.968 -0.206 c
+155.968 -0.375 156.001 -0.497 156.071 -0.574 c
+156.137 -0.654 156.236 -0.691 156.365 -0.691 c
+156.471 -0.691 156.571 -0.669 156.659 -0.617 c
+156.754 -0.57 156.835 -0.507 156.895 -0.426 c
+156.96 -0.349 157.012 -0.262 157.041 -0.162 c
+157.071 -0.056 157.086 0.058 157.086 0.176 c
+h
+160.367 -1.264 m
+160.367 0.852 l
+160.367 1.018 160.359 1.153 160.352 1.264 c
+160.341 1.371 160.323 1.455 160.294 1.514 c
+160.271 1.58 160.242 1.631 160.205 1.66 c
+160.176 1.69 160.135 1.705 160.087 1.705 c
+160.029 1.705 159.974 1.675 159.926 1.617 c
+159.885 1.565 159.852 1.492 159.823 1.396 c
+159.794 1.308 159.768 1.194 159.75 1.058 c
+159.738 0.918 159.735 0.768 159.735 0.602 c
+159.735 -1.264 l
+158.985 -1.264 l
+158.985 1.469 l
+158.985 1.705 l
+158.985 1.926 l
+158.985 2.003 158.977 2.065 158.971 2.117 c
+158.971 2.219 l
+159.646 2.219 l
+159.646 2.131 l
+159.646 1.984 l
+159.654 1.926 159.661 1.866 159.661 1.808 c
+159.661 1.646 l
+159.676 1.646 l
+159.694 1.735 159.723 1.812 159.764 1.881 c
+159.801 1.959 159.845 2.028 159.897 2.087 c
+159.956 2.146 160.022 2.19 160.103 2.219 c
+160.18 2.256 160.268 2.278 160.367 2.278 c
+160.55 2.278 160.691 2.223 160.779 2.117 c
+160.874 2.017 160.944 1.859 160.984 1.646 c
+160.999 1.646 l
+161.036 1.741 161.076 1.83 161.117 1.911 c
+161.165 1.988 161.219 2.051 161.278 2.102 c
+161.337 2.161 161.404 2.205 161.484 2.234 c
+161.562 2.263 161.649 2.278 161.749 2.278 c
+161.884 2.278 161.998 2.252 162.087 2.205 c
+162.175 2.153 162.241 2.08 162.293 1.984 c
+162.351 1.885 162.388 1.756 162.41 1.602 c
+162.439 1.455 162.454 1.271 162.454 1.058 c
+162.454 -1.264 l
+161.734 -1.264 l
+161.734 0.852 l
+161.734 1.018 161.726 1.153 161.72 1.264 c
+161.708 1.371 161.69 1.455 161.66 1.514 c
+161.639 1.58 161.609 1.631 161.572 1.66 c
+161.543 1.69 161.502 1.705 161.454 1.705 c
+161.337 1.705 161.242 1.617 161.175 1.44 c
+161.117 1.271 161.088 1.014 161.088 0.661 c
+161.088 -1.264 l
+h
+164.824 -1.323 m
+164.567 -1.323 164.34 -1.286 164.134 -1.22 c
+163.928 -1.143 163.752 -1.029 163.604 -0.882 c
+163.457 -0.728 163.34 -0.536 163.251 -0.309 c
+163.17 -0.085 163.134 0.18 163.134 0.484 c
+163.134 0.816 163.178 1.095 163.266 1.323 c
+163.362 1.558 163.49 1.741 163.648 1.881 c
+163.814 2.017 164.001 2.117 164.207 2.175 c
+164.413 2.242 164.622 2.278 164.839 2.278 c
+165.111 2.278 165.346 2.227 165.545 2.131 c
+165.751 2.043 165.915 1.911 166.044 1.735 c
+166.181 1.565 166.279 1.359 166.339 1.117 c
+166.405 0.881 166.441 0.617 166.441 0.324 c
+166.441 0.309 l
+164.074 0.309 l
+164.074 0.162 164.089 0.022 164.119 -0.103 c
+164.155 -0.231 164.211 -0.345 164.28 -0.441 c
+164.346 -0.53 164.431 -0.599 164.531 -0.647 c
+164.626 -0.698 164.739 -0.721 164.868 -0.721 c
+165.023 -0.721 165.163 -0.688 165.28 -0.617 c
+165.406 -0.551 165.493 -0.449 165.545 -0.309 c
+166.383 -0.382 l
+166.353 -0.482 166.298 -0.588 166.221 -0.706 c
+166.14 -0.816 166.037 -0.919 165.913 -1.014 c
+165.795 -1.103 165.641 -1.176 165.456 -1.235 c
+165.28 -1.294 165.067 -1.323 164.824 -1.323 c
+164.824 1.705 m
+164.737 1.705 164.648 1.69 164.56 1.66 c
+164.471 1.631 164.39 1.58 164.325 1.514 c
+164.255 1.444 164.196 1.356 164.149 1.249 c
+164.108 1.139 164.089 1.014 164.089 0.867 c
+165.56 0.867 l
+165.56 1.003 165.533 1.124 165.485 1.234 c
+165.445 1.341 165.39 1.429 165.325 1.5 c
+165.265 1.565 165.192 1.617 165.104 1.646 c
+165.015 1.683 164.92 1.705 164.824 1.705 c
+169.899 1.455 m
+169.267 1.455 l
+169.135 3.513 l
+170.031 3.513 l
+h
+168.429 1.455 m
+167.797 1.455 l
+167.679 3.513 l
+168.547 3.513 l
+h
+f
+Q
+q 1 0 0 1 91.976 390.0891 cm
+0 0 m
+0 0.265 -0.073 0.464 -0.22 0.603 c
+-0.36 0.75 -0.617 0.89 -0.999 1.029 c
+-1.374 1.166 -1.66 1.309 -1.866 1.455 c
+-2.065 1.603 -2.212 1.768 -2.308 1.956 c
+-2.406 2.151 -2.454 2.371 -2.454 2.617 c
+-2.454 3.036 -2.315 3.385 -2.028 3.66 c
+-1.745 3.932 -1.378 4.072 -0.926 4.072 c
+-0.613 4.072 -0.334 3.998 -0.088 3.851 c
+0.154 3.712 0.341 3.517 0.47 3.263 c
+0.607 3.017 0.676 2.749 0.676 2.455 c
+0 2.455 l
+0 2.786 -0.081 3.043 -0.235 3.219 c
+-0.393 3.404 -0.625 3.499 -0.926 3.499 c
+-1.19 3.499 -1.404 3.418 -1.558 3.263 c
+-1.705 3.117 -1.779 2.903 -1.779 2.631 c
+-1.779 2.404 -1.701 2.213 -1.544 2.058 c
+-1.378 1.912 -1.124 1.771 -0.779 1.646 c
+-0.261 1.478 0.11 1.268 0.338 1.015 c
+0.573 0.757 0.691 0.427 0.691 0.015 c
+0.691 -0.426 0.548 -0.779 0.264 -1.043 c
+-0.022 -1.3 -0.405 -1.425 -0.881 -1.425 c
+-1.198 -1.425 -1.484 -1.356 -1.749 -1.219 c
+-2.014 -1.084 -2.227 -0.893 -2.381 -0.646 c
+-2.528 -0.404 -2.601 -0.118 -2.601 0.206 c
+-1.926 0.206 l
+-1.926 -0.128 -1.834 -0.389 -1.646 -0.573 c
+-1.463 -0.76 -1.205 -0.852 -0.881 -0.852 c
+-0.588 -0.852 -0.368 -0.779 -0.22 -0.631 c
+-0.073 -0.477 0 -0.264 0 0 c
+2.896 -1.425 m
+2.396 -1.425 2.014 -1.278 1.749 -0.984 c
+1.484 -0.69 1.353 -0.257 1.353 0.324 c
+1.353 0.794 l
+1.353 1.389 1.477 1.856 1.735 2.191 c
+1.999 2.532 2.359 2.705 2.822 2.705 c
+3.281 2.705 3.624 2.55 3.851 2.249 c
+4.087 1.956 4.208 1.492 4.219 0.867 c
+4.219 0.441 l
+1.999 0.441 l
+1.999 0.353 l
+1.999 -0.08 2.076 -0.393 2.234 -0.588 c
+2.4 -0.775 2.631 -0.866 2.925 -0.866 c
+3.12 -0.866 3.293 -0.833 3.439 -0.764 c
+3.587 -0.687 3.723 -0.569 3.851 -0.411 c
+4.189 -0.823 l
+3.903 -1.227 3.473 -1.425 2.896 -1.425 c
+2.822 2.147 m
+2.547 2.147 2.344 2.051 2.219 1.867 c
+2.091 1.68 2.018 1.389 1.999 1 c
+3.572 1 l
+3.572 1.088 l
+3.55 1.47 3.484 1.738 3.366 1.897 c
+3.248 2.062 3.065 2.147 2.822 2.147 c
+5.85 3.587 m
+5.85 2.631 l
+6.453 2.631 l
+6.453 2.103 l
+5.85 2.103 l
+5.85 -0.367 l
+5.85 -0.525 5.872 -0.643 5.924 -0.72 c
+5.982 -0.801 6.071 -0.837 6.188 -0.837 c
+6.277 -0.837 6.365 -0.823 6.453 -0.793 c
+6.453 -1.352 l
+6.306 -1.4 6.151 -1.425 5.997 -1.425 c
+5.74 -1.425 5.546 -1.334 5.409 -1.146 c
+5.27 -0.962 5.203 -0.702 5.203 -0.367 c
+5.203 2.103 l
+4.601 2.103 l
+4.601 2.631 l
+5.203 2.631 l
+5.203 3.587 l
+h
+9.789 3.587 m
+9.789 2.631 l
+10.392 2.631 l
+10.392 2.103 l
+9.789 2.103 l
+9.789 -0.367 l
+9.789 -0.525 9.812 -0.643 9.864 -0.72 c
+9.922 -0.801 10.01 -0.837 10.128 -0.837 c
+10.215 -0.837 10.304 -0.823 10.392 -0.793 c
+10.392 -1.352 l
+10.246 -1.4 10.091 -1.425 9.937 -1.425 c
+9.679 -1.425 9.485 -1.334 9.349 -1.146 c
+9.209 -0.962 9.143 -0.702 9.143 -0.367 c
+9.143 2.103 l
+8.54 2.103 l
+8.54 2.631 l
+9.143 2.631 l
+9.143 3.587 l
+h
+11.803 2.22 m
+12.057 2.544 12.376 2.705 12.759 2.705 c
+13.465 2.705 13.821 2.234 13.832 1.294 c
+13.832 -1.352 l
+13.185 -1.352 l
+13.185 1.264 l
+13.185 1.577 13.13 1.798 13.024 1.926 c
+12.914 2.051 12.759 2.117 12.553 2.117 c
+12.395 2.117 12.248 2.062 12.112 1.956 c
+11.983 1.845 11.881 1.709 11.803 1.544 c
+11.803 -1.352 l
+11.156 -1.352 l
+11.156 4.293 l
+11.803 4.293 l
+h
+16.214 -1.425 m
+15.713 -1.425 15.331 -1.278 15.067 -0.984 c
+14.803 -0.69 14.67 -0.257 14.67 0.324 c
+14.67 0.794 l
+14.67 1.389 14.795 1.856 15.052 2.191 c
+15.316 2.532 15.676 2.705 16.139 2.705 c
+16.599 2.705 16.941 2.55 17.168 2.249 c
+17.404 1.956 17.525 1.492 17.536 0.867 c
+17.536 0.441 l
+15.316 0.441 l
+15.316 0.353 l
+15.316 -0.08 15.393 -0.393 15.551 -0.588 c
+15.717 -0.775 15.948 -0.866 16.243 -0.866 c
+16.438 -0.866 16.61 -0.833 16.757 -0.764 c
+16.904 -0.687 17.04 -0.569 17.168 -0.411 c
+17.506 -0.823 l
+17.22 -1.227 16.79 -1.425 16.214 -1.425 c
+16.139 2.147 m
+15.864 2.147 15.662 2.051 15.537 1.867 c
+15.408 1.68 15.335 1.389 15.316 1 c
+16.889 1 l
+16.889 1.088 l
+16.867 1.47 16.801 1.738 16.684 1.897 c
+16.565 2.062 16.382 2.147 16.139 2.147 c
+20.652 2.631 m
+20.667 2.191 l
+20.92 2.532 21.244 2.705 21.637 2.705 c
+22.343 2.705 22.699 2.234 22.71 1.294 c
+22.71 -1.352 l
+22.063 -1.352 l
+22.063 1.264 l
+22.063 1.577 22.009 1.798 21.901 1.926 c
+21.791 2.051 21.637 2.117 21.431 2.117 c
+21.273 2.117 21.126 2.062 20.991 1.956 c
+20.862 1.845 20.759 1.709 20.682 1.544 c
+20.682 -1.352 l
+20.035 -1.352 l
+20.035 2.631 l
+h
+25.724 -1.352 m
+25.683 -1.263 25.658 -1.117 25.65 -0.911 c
+25.415 -1.256 25.121 -1.425 24.768 -1.425 c
+24.405 -1.425 24.121 -1.33 23.915 -1.132 c
+23.717 -0.926 23.621 -0.639 23.621 -0.264 c
+23.621 0.136 23.757 0.456 24.033 0.691 c
+24.305 0.934 24.68 1.058 25.151 1.058 c
+25.635 1.058 l
+25.635 1.485 l
+25.635 1.721 25.581 1.885 25.473 1.985 c
+25.363 2.091 25.201 2.147 24.989 2.147 c
+24.79 2.147 24.629 2.087 24.503 1.97 c
+24.386 1.852 24.327 1.706 24.327 1.529 c
+23.68 1.529 l
+23.68 1.723 23.74 1.915 23.856 2.103 c
+23.981 2.286 24.143 2.433 24.342 2.544 c
+24.548 2.65 24.775 2.705 25.032 2.705 c
+25.433 2.705 25.738 2.602 25.944 2.396 c
+26.157 2.191 26.271 1.897 26.282 1.515 c
+26.282 -0.5 l
+26.282 -0.804 26.319 -1.069 26.4 -1.294 c
+26.4 -1.352 l
+h
+24.856 -0.837 m
+25.022 -0.837 25.172 -0.793 25.312 -0.706 c
+25.459 -0.617 25.566 -0.507 25.635 -0.367 c
+25.635 0.574 l
+25.267 0.574 l
+24.952 0.574 24.709 0.504 24.533 0.368 c
+24.357 0.239 24.268 0.052 24.268 -0.191 c
+24.268 -0.419 24.312 -0.584 24.401 -0.69 c
+24.488 -0.789 24.64 -0.837 24.856 -0.837 c
+27.899 2.631 m
+27.914 2.264 l
+28.156 2.558 28.476 2.705 28.869 2.705 c
+29.31 2.705 29.619 2.507 29.795 2.117 c
+30.049 2.507 30.398 2.705 30.838 2.705 c
+31.574 2.705 31.948 2.242 31.971 1.324 c
+31.971 -1.352 l
+31.324 -1.352 l
+31.324 1.264 l
+31.324 1.559 31.268 1.771 31.162 1.912 c
+31.063 2.047 30.89 2.117 30.647 2.117 c
+30.449 2.117 30.287 2.037 30.163 1.881 c
+30.045 1.735 29.975 1.544 29.957 1.309 c
+29.957 -1.352 l
+29.296 -1.352 l
+29.296 1.294 l
+29.296 1.841 29.074 2.117 28.634 2.117 c
+28.299 2.117 28.064 1.956 27.929 1.632 c
+27.929 -1.352 l
+27.281 -1.352 l
+27.281 2.631 l
+h
+34.366 -1.425 m
+33.867 -1.425 33.485 -1.278 33.22 -0.984 c
+32.955 -0.69 32.823 -0.257 32.823 0.324 c
+32.823 0.794 l
+32.823 1.389 32.948 1.856 33.205 2.191 c
+33.47 2.532 33.83 2.705 34.293 2.705 c
+34.753 2.705 35.094 2.55 35.322 2.249 c
+35.557 1.956 35.678 1.492 35.69 0.867 c
+35.69 0.441 l
+33.47 0.441 l
+33.47 0.353 l
+33.47 -0.08 33.547 -0.393 33.705 -0.588 c
+33.87 -0.775 34.102 -0.866 34.396 -0.866 c
+34.591 -0.866 34.763 -0.833 34.91 -0.764 c
+35.058 -0.687 35.193 -0.569 35.322 -0.411 c
+35.66 -0.823 l
+35.374 -1.227 34.944 -1.425 34.366 -1.425 c
+34.293 2.147 m
+34.017 2.147 33.815 2.051 33.691 1.867 c
+33.562 1.68 33.488 1.389 33.47 1 c
+35.043 1 l
+35.043 1.088 l
+35.021 1.47 34.954 1.738 34.837 1.897 c
+34.719 2.062 34.535 2.147 34.293 2.147 c
+39.041 3.587 m
+39.041 2.631 l
+39.644 2.631 l
+39.644 2.103 l
+39.041 2.103 l
+39.041 -0.367 l
+39.041 -0.525 39.063 -0.643 39.114 -0.72 c
+39.173 -0.801 39.262 -0.837 39.378 -0.837 c
+39.467 -0.837 39.555 -0.823 39.644 -0.793 c
+39.644 -1.352 l
+39.497 -1.4 39.342 -1.425 39.187 -1.425 c
+38.931 -1.425 38.736 -1.334 38.599 -1.146 c
+38.46 -0.962 38.394 -0.702 38.394 -0.367 c
+38.394 2.103 l
+37.791 2.103 l
+37.791 2.631 l
+38.394 2.631 l
+38.394 3.587 l
+h
+41.055 2.22 m
+41.308 2.544 41.628 2.705 42.01 2.705 c
+42.715 2.705 43.072 2.234 43.083 1.294 c
+43.083 -1.352 l
+42.436 -1.352 l
+42.436 1.264 l
+42.436 1.577 42.381 1.798 42.275 1.926 c
+42.164 2.051 42.01 2.117 41.805 2.117 c
+41.647 2.117 41.499 2.062 41.363 1.956 c
+41.234 1.845 41.132 1.709 41.055 1.544 c
+41.055 -1.352 l
+40.408 -1.352 l
+40.408 4.293 l
+41.055 4.293 l
+h
+46.082 -1.352 m
+46.042 -1.263 46.015 -1.117 46.008 -0.911 c
+45.773 -1.256 45.479 -1.425 45.126 -1.425 c
+44.762 -1.425 44.479 -1.33 44.274 -1.132 c
+44.076 -0.926 43.98 -0.639 43.98 -0.264 c
+43.98 0.136 44.116 0.456 44.392 0.691 c
+44.663 0.934 45.038 1.058 45.508 1.058 c
+45.994 1.058 l
+45.994 1.485 l
+45.994 1.721 45.938 1.885 45.832 1.985 c
+45.722 2.091 45.56 2.147 45.346 2.147 c
+45.148 2.147 44.986 2.087 44.862 1.97 c
+44.744 1.852 44.685 1.706 44.685 1.529 c
+44.039 1.529 l
+44.039 1.723 44.097 1.915 44.215 2.103 c
+44.34 2.286 44.502 2.433 44.7 2.544 c
+44.906 2.65 45.134 2.705 45.391 2.705 c
+45.791 2.705 46.096 2.602 46.302 2.396 c
+46.515 2.191 46.63 1.897 46.64 1.515 c
+46.64 -0.5 l
+46.64 -0.804 46.677 -1.069 46.758 -1.294 c
+46.758 -1.352 l
+h
+45.215 -0.837 m
+45.379 -0.837 45.531 -0.793 45.67 -0.706 c
+45.817 -0.617 45.924 -0.507 45.994 -0.367 c
+45.994 0.574 l
+45.626 0.574 l
+45.31 0.574 45.067 0.504 44.891 0.368 c
+44.714 0.239 44.627 0.052 44.627 -0.191 c
+44.627 -0.419 44.671 -0.584 44.758 -0.69 c
+44.847 -0.789 44.997 -0.837 45.215 -0.837 c
+48.492 3.587 m
+48.492 2.631 l
+49.095 2.631 l
+49.095 2.103 l
+48.492 2.103 l
+48.492 -0.367 l
+48.492 -0.525 48.514 -0.643 48.566 -0.72 c
+48.625 -0.801 48.712 -0.837 48.83 -0.837 c
+48.918 -0.837 49.007 -0.823 49.095 -0.793 c
+49.095 -1.352 l
+48.948 -1.4 48.793 -1.425 48.639 -1.425 c
+48.382 -1.425 48.187 -1.334 48.051 -1.146 c
+47.912 -0.962 47.845 -0.702 47.845 -0.367 c
+47.845 2.103 l
+47.243 2.103 l
+47.243 2.631 l
+47.845 2.631 l
+47.845 3.587 l
+h
+54.549 -0.205 m
+55.151 2.631 l
+55.798 2.631 l
+54.813 -1.352 l
+54.299 -1.352 l
+53.52 1.5 l
+52.77 -1.352 l
+52.24 -1.352 l
+51.285 2.631 l
+51.918 2.631 l
+52.535 -0.132 l
+53.269 2.631 l
+53.784 2.631 l
+h
+57.179 -1.352 -0.646 3.983 re
+57.223 3.675 m
+57.223 3.565 57.194 3.473 57.136 3.396 c
+57.077 3.326 56.981 3.293 56.856 3.293 c
+56.739 3.293 56.643 3.326 56.577 3.396 c
+56.518 3.473 56.489 3.565 56.489 3.675 c
+56.489 3.793 56.518 3.884 56.577 3.955 c
+56.643 4.032 56.739 4.072 56.856 4.072 c
+56.981 4.072 57.077 4.032 57.136 3.955 c
+57.194 3.874 57.223 3.782 57.223 3.675 c
+58.899 -1.352 -0.646 5.644 re
+60.619 -1.352 -0.647 5.644 re
+66.234 0.441 m
+66.234 -0.176 66.12 -0.643 65.896 -0.955 c
+65.68 -1.271 65.356 -1.425 64.926 -1.425 c
+64.504 -1.425 64.191 -1.246 63.985 -0.881 c
+63.956 -1.352 l
+63.353 -1.352 l
+63.353 4.293 l
+63.999 4.293 l
+63.999 2.191 l
+64.213 2.532 64.522 2.705 64.926 2.705 c
+65.356 2.705 65.68 2.547 65.896 2.234 c
+66.12 1.929 66.234 1.463 66.234 0.838 c
+h
+65.587 0.823 m
+65.587 1.294 65.518 1.625 65.381 1.823 c
+65.252 2.018 65.044 2.117 64.749 2.117 c
+64.415 2.117 64.165 1.933 63.999 1.573 c
+63.999 -0.309 l
+64.165 -0.672 64.419 -0.852 64.764 -0.852 c
+65.058 -0.852 65.268 -0.749 65.396 -0.544 c
+65.522 -0.338 65.587 -0.022 65.587 0.412 c
+h
+68.498 -1.425 m
+67.998 -1.425 67.616 -1.278 67.351 -0.984 c
+67.087 -0.69 66.954 -0.257 66.954 0.324 c
+66.954 0.794 l
+66.954 1.389 67.079 1.856 67.336 2.191 c
+67.601 2.532 67.961 2.705 68.425 2.705 c
+68.884 2.705 69.225 2.55 69.453 2.249 c
+69.688 1.956 69.809 1.492 69.821 0.867 c
+69.821 0.441 l
+67.601 0.441 l
+67.601 0.353 l
+67.601 -0.08 67.679 -0.393 67.836 -0.588 c
+68.001 -0.775 68.233 -0.866 68.527 -0.866 c
+68.722 -0.866 68.895 -0.833 69.042 -0.764 c
+69.189 -0.687 69.325 -0.569 69.453 -0.411 c
+69.792 -0.823 l
+69.505 -1.227 69.075 -1.425 68.498 -1.425 c
+68.425 2.147 m
+68.149 2.147 67.947 2.051 67.822 1.867 c
+67.693 1.68 67.619 1.389 67.601 1 c
+69.173 1 l
+69.173 1.088 l
+69.152 1.47 69.086 1.738 68.968 1.897 c
+68.851 2.062 68.666 2.147 68.425 2.147 c
+74.363 -1.352 m
+74.322 -1.263 74.297 -1.117 74.289 -0.911 c
+74.054 -1.256 73.76 -1.425 73.407 -1.425 c
+73.044 -1.425 72.761 -1.33 72.555 -1.132 c
+72.356 -0.926 72.261 -0.639 72.261 -0.264 c
+72.261 0.136 72.396 0.456 72.672 0.691 c
+72.944 0.934 73.319 1.058 73.79 1.058 c
+74.274 1.058 l
+74.274 1.485 l
+74.274 1.721 74.22 1.885 74.112 1.985 c
+74.002 2.091 73.841 2.147 73.628 2.147 c
+73.429 2.147 73.268 2.087 73.142 1.97 c
+73.025 1.852 72.967 1.706 72.967 1.529 c
+72.319 1.529 l
+72.319 1.723 72.379 1.915 72.496 2.103 c
+72.62 2.286 72.782 2.433 72.981 2.544 c
+73.187 2.65 73.414 2.705 73.672 2.705 c
+74.072 2.705 74.378 2.602 74.583 2.396 c
+74.796 2.191 74.91 1.897 74.921 1.515 c
+74.921 -0.5 l
+74.921 -0.804 74.958 -1.069 75.039 -1.294 c
+75.039 -1.352 l
+h
+73.495 -0.837 m
+73.661 -0.837 73.811 -0.793 73.951 -0.706 c
+74.098 -0.617 74.205 -0.507 74.274 -0.367 c
+74.274 0.574 l
+73.907 0.574 l
+73.591 0.574 73.348 0.504 73.172 0.368 c
+72.996 0.239 72.907 0.052 72.907 -0.191 c
+72.907 -0.419 72.952 -0.584 73.04 -0.69 c
+73.128 -0.789 73.279 -0.837 73.495 -0.837 c
+76.773 3.587 m
+76.773 2.631 l
+77.376 2.631 l
+77.376 2.103 l
+76.773 2.103 l
+76.773 -0.367 l
+76.773 -0.525 76.795 -0.643 76.847 -0.72 c
+76.905 -0.801 76.994 -0.837 77.111 -0.837 c
+77.2 -0.837 77.287 -0.823 77.376 -0.793 c
+77.376 -1.352 l
+77.229 -1.4 77.075 -1.425 76.92 -1.425 c
+76.663 -1.425 76.468 -1.334 76.333 -1.146 c
+76.192 -0.962 76.126 -0.702 76.126 -0.367 c
+76.126 2.103 l
+75.523 2.103 l
+75.523 2.631 l
+76.126 2.631 l
+76.126 3.587 l
+h
+78.993 3.587 m
+78.993 2.631 l
+79.595 2.631 l
+79.595 2.103 l
+78.993 2.103 l
+78.993 -0.367 l
+78.993 -0.525 79.015 -0.643 79.066 -0.72 c
+79.125 -0.801 79.213 -0.837 79.331 -0.837 c
+79.419 -0.837 79.508 -0.823 79.595 -0.793 c
+79.595 -1.352 l
+79.448 -1.4 79.294 -1.425 79.14 -1.425 c
+78.883 -1.425 78.688 -1.334 78.552 -1.146 c
+78.412 -0.962 78.346 -0.702 78.346 -0.367 c
+78.346 2.103 l
+77.744 2.103 l
+77.744 2.631 l
+78.346 2.631 l
+78.346 3.587 l
+h
+82.403 -1.352 m
+82.363 -1.263 82.337 -1.117 82.33 -0.911 c
+82.095 -1.256 81.8 -1.425 81.447 -1.425 c
+81.084 -1.425 80.801 -1.33 80.595 -1.132 c
+80.397 -0.926 80.301 -0.639 80.301 -0.264 c
+80.301 0.136 80.437 0.456 80.713 0.691 c
+80.984 0.934 81.36 1.058 81.83 1.058 c
+82.315 1.058 l
+82.315 1.485 l
+82.315 1.721 82.26 1.885 82.153 1.985 c
+82.043 2.091 81.881 2.147 81.668 2.147 c
+81.47 2.147 81.308 2.087 81.183 1.97 c
+81.065 1.852 81.006 1.706 81.006 1.529 c
+80.36 1.529 l
+80.36 1.723 80.419 1.915 80.536 2.103 c
+80.661 2.286 80.823 2.433 81.021 2.544 c
+81.227 2.65 81.455 2.705 81.712 2.705 c
+82.112 2.705 82.417 2.602 82.623 2.396 c
+82.837 2.191 82.951 1.897 82.962 1.515 c
+82.962 -0.5 l
+82.962 -0.804 82.999 -1.069 83.08 -1.294 c
+83.08 -1.352 l
+h
+81.536 -0.837 m
+81.701 -0.837 81.852 -0.793 81.991 -0.706 c
+82.139 -0.617 82.245 -0.507 82.315 -0.367 c
+82.315 0.574 l
+81.947 0.574 l
+81.632 0.574 81.389 0.504 81.212 0.368 c
+81.036 0.239 80.948 0.052 80.948 -0.191 c
+80.948 -0.419 80.992 -0.584 81.08 -0.69 c
+81.168 -0.789 81.319 -0.837 81.536 -0.837 c
+85.343 -0.866 m
+85.556 -0.866 85.729 -0.804 85.857 -0.675 c
+85.993 -0.54 86.066 -0.349 86.078 -0.103 c
+86.695 -0.103 l
+86.673 -0.484 86.537 -0.804 86.284 -1.058 c
+86.026 -1.304 85.714 -1.425 85.343 -1.425 c
+84.85 -1.425 84.476 -1.275 84.211 -0.97 c
+83.953 -0.658 83.828 -0.191 83.828 0.427 c
+83.828 0.867 l
+83.828 1.463 83.953 1.919 84.211 2.234 c
+84.476 2.547 84.85 2.705 85.343 2.705 c
+85.744 2.705 86.064 2.573 86.299 2.309 c
+86.54 2.051 86.673 1.706 86.695 1.264 c
+86.078 1.264 l
+86.056 1.559 85.983 1.779 85.857 1.926 c
+85.74 2.073 85.567 2.147 85.343 2.147 c
+85.048 2.147 84.832 2.047 84.696 1.852 c
+84.556 1.665 84.483 1.357 84.476 0.927 c
+84.476 0.412 l
+84.476 -0.058 84.541 -0.393 84.682 -0.588 c
+84.828 -0.775 85.048 -0.866 85.343 -0.866 c
+88.092 2.22 m
+88.345 2.544 88.665 2.705 89.047 2.705 c
+89.752 2.705 90.109 2.234 90.12 1.294 c
+90.12 -1.352 l
+89.473 -1.352 l
+89.473 1.264 l
+89.473 1.577 89.418 1.798 89.312 1.926 c
+89.201 2.051 89.047 2.117 88.842 2.117 c
+88.684 2.117 88.536 2.062 88.4 1.956 c
+88.271 1.845 88.169 1.709 88.092 1.544 c
+88.092 -1.352 l
+87.445 -1.352 l
+87.445 4.293 l
+88.092 4.293 l
+h
+92.501 -1.425 m
+92.001 -1.425 91.62 -1.278 91.354 -0.984 c
+91.09 -0.69 90.958 -0.257 90.958 0.324 c
+90.958 0.794 l
+90.958 1.389 91.082 1.856 91.34 2.191 c
+91.604 2.532 91.965 2.705 92.428 2.705 c
+92.887 2.705 93.229 2.55 93.457 2.249 c
+93.692 1.956 93.813 1.492 93.825 0.867 c
+93.825 0.441 l
+91.604 0.441 l
+91.604 0.353 l
+91.604 -0.08 91.682 -0.393 91.84 -0.588 c
+92.005 -0.775 92.237 -0.866 92.53 -0.866 c
+92.726 -0.866 92.898 -0.833 93.045 -0.764 c
+93.192 -0.687 93.328 -0.569 93.457 -0.411 c
+93.795 -0.823 l
+93.509 -1.227 93.079 -1.425 92.501 -1.425 c
+92.428 2.147 m
+92.152 2.147 91.95 2.051 91.825 1.867 c
+91.697 1.68 91.623 1.389 91.604 1 c
+93.177 1 l
+93.177 1.088 l
+93.156 1.47 93.089 1.738 92.971 1.897 c
+92.854 2.062 92.67 2.147 92.428 2.147 c
+94.471 0.823 m
+94.471 1.43 94.581 1.897 94.809 2.22 c
+95.044 2.544 95.371 2.705 95.794 2.705 c
+96.176 2.705 96.474 2.547 96.69 2.234 c
+96.69 4.293 l
+97.337 4.293 l
+97.337 -1.352 l
+96.749 -1.352 l
+96.705 -0.926 l
+96.499 -1.26 96.194 -1.425 95.794 -1.425 c
+95.382 -1.425 95.059 -1.271 94.824 -0.955 c
+94.589 -0.631 94.471 -0.176 94.471 0.412 c
+h
+95.117 0.441 m
+95.117 0 95.18 -0.33 95.309 -0.544 c
+95.445 -0.749 95.666 -0.852 95.97 -0.852 c
+96.293 -0.852 96.532 -0.69 96.69 -0.367 c
+96.69 1.646 l
+96.522 1.959 96.283 2.117 95.97 2.117 c
+95.666 2.117 95.445 2.014 95.309 1.808 c
+95.18 1.603 95.117 1.279 95.117 0.838 c
+h
+100.909 3.587 m
+100.909 2.631 l
+101.511 2.631 l
+101.511 2.103 l
+100.909 2.103 l
+100.909 -0.367 l
+100.909 -0.525 100.931 -0.643 100.983 -0.72 c
+101.041 -0.801 101.129 -0.837 101.247 -0.837 c
+101.335 -0.837 101.424 -0.823 101.511 -0.793 c
+101.511 -1.352 l
+101.365 -1.4 101.21 -1.425 101.056 -1.425 c
+100.799 -1.425 100.605 -1.334 100.468 -1.146 c
+100.329 -0.962 100.262 -0.702 100.262 -0.367 c
+100.262 2.103 l
+99.66 2.103 l
+99.66 2.631 l
+100.262 2.631 l
+100.262 3.587 l
+h
+102.07 0.823 m
+102.07 1.401 102.207 1.856 102.482 2.191 c
+102.764 2.532 103.136 2.705 103.599 2.705 c
+104.058 2.705 104.426 2.536 104.701 2.205 c
+104.985 1.881 105.131 1.434 105.143 0.867 c
+105.143 0.441 l
+105.143 -0.128 104.999 -0.584 104.717 -0.926 c
+104.441 -1.26 104.073 -1.425 103.614 -1.425 c
+103.151 -1.425 102.78 -1.263 102.496 -0.941 c
+102.221 -0.61 102.078 -0.168 102.07 0.383 c
+h
+102.717 0.441 m
+102.717 0.038 102.795 -0.278 102.953 -0.514 c
+103.117 -0.749 103.338 -0.866 103.614 -0.866 c
+104.179 -0.866 104.474 -0.455 104.495 0.368 c
+104.495 0.823 l
+104.495 1.224 104.411 1.544 104.246 1.779 c
+104.088 2.022 103.871 2.147 103.599 2.147 c
+103.335 2.147 103.117 2.022 102.953 1.779 c
+102.795 1.544 102.717 1.224 102.717 0.823 c
+h
+108.788 -0.264 m
+109.508 2.631 l
+110.199 2.631 l
+108.906 -1.911 l
+108.806 -2.252 108.663 -2.513 108.479 -2.69 c
+108.303 -2.865 108.1 -2.954 107.876 -2.954 c
+107.788 -2.954 107.674 -2.932 107.539 -2.896 c
+107.539 -2.352 l
+107.685 -2.366 l
+107.869 -2.366 108.016 -2.322 108.127 -2.234 c
+108.233 -2.146 108.321 -1.988 108.391 -1.764 c
+108.509 -1.323 l
+107.347 2.631 l
+108.052 2.631 l
+h
+110.639 0.823 m
+110.639 1.401 110.776 1.856 111.051 2.191 c
+111.335 2.532 111.705 2.705 112.169 2.705 c
+112.628 2.705 112.995 2.536 113.271 2.205 c
+113.554 1.881 113.701 1.434 113.712 0.867 c
+113.712 0.441 l
+113.712 -0.128 113.569 -0.584 113.286 -0.926 c
+113.01 -1.26 112.642 -1.425 112.183 -1.425 c
+111.72 -1.425 111.349 -1.263 111.067 -0.941 c
+110.791 -0.61 110.647 -0.168 110.639 0.383 c
+h
+111.287 0.441 m
+111.287 0.038 111.364 -0.278 111.522 -0.514 c
+111.687 -0.749 111.908 -0.866 112.183 -0.866 c
+112.749 -0.866 113.043 -0.455 113.066 0.368 c
+113.066 0.823 l
+113.066 1.224 112.981 1.544 112.815 1.779 c
+112.657 2.022 112.441 2.147 112.169 2.147 c
+111.904 2.147 111.687 2.022 111.522 1.779 c
+111.364 1.544 111.287 1.224 111.287 0.823 c
+h
+116.578 -0.999 m
+116.362 -1.286 116.049 -1.425 115.638 -1.425 c
+115.273 -1.425 114.998 -1.304 114.814 -1.058 c
+114.638 -0.804 114.543 -0.44 114.535 0.03 c
+114.535 2.631 l
+115.182 2.631 l
+115.182 0.088 l
+115.182 -0.54 115.366 -0.852 115.74 -0.852 c
+116.141 -0.852 116.416 -0.675 116.563 -0.323 c
+116.563 2.631 l
+117.21 2.631 l
+117.21 -1.352 l
+116.593 -1.352 l
+h
+119.842 2.014 m
+119.753 2.033 119.655 2.043 119.547 2.043 c
+119.213 2.043 118.978 1.86 118.842 1.5 c
+118.842 -1.352 l
+118.195 -1.352 l
+118.195 2.631 l
+118.828 2.631 l
+118.842 2.22 l
+119.019 2.544 119.261 2.705 119.576 2.705 c
+119.684 2.705 119.772 2.683 119.842 2.646 c
+h
+123.59 -0.866 m
+123.803 -0.866 123.975 -0.804 124.104 -0.675 c
+124.241 -0.54 124.314 -0.349 124.324 -0.103 c
+124.942 -0.103 l
+124.92 -0.484 124.784 -0.804 124.53 -1.058 c
+124.274 -1.304 123.961 -1.425 123.59 -1.425 c
+123.098 -1.425 122.722 -1.275 122.458 -0.97 c
+122.201 -0.658 122.076 -0.191 122.076 0.427 c
+122.076 0.867 l
+122.076 1.463 122.201 1.919 122.458 2.234 c
+122.722 2.547 123.098 2.705 123.59 2.705 c
+123.99 2.705 124.31 2.573 124.545 2.309 c
+124.788 2.051 124.92 1.706 124.942 1.264 c
+124.324 1.264 l
+124.303 1.559 124.229 1.779 124.104 1.926 c
+123.987 2.073 123.814 2.147 123.59 2.147 c
+123.296 2.147 123.079 2.047 122.943 1.852 c
+122.803 1.665 122.73 1.357 122.722 0.927 c
+122.722 0.412 l
+122.722 -0.058 122.789 -0.393 122.928 -0.588 c
+123.075 -0.775 123.296 -0.866 123.59 -0.866 c
+125.56 0.823 m
+125.56 1.401 125.695 1.856 125.971 2.191 c
+126.254 2.532 126.625 2.705 127.088 2.705 c
+127.547 2.705 127.915 2.536 128.191 2.205 c
+128.474 1.881 128.621 1.434 128.632 0.867 c
+128.632 0.441 l
+128.632 -0.128 128.488 -0.584 128.205 -0.926 c
+127.929 -1.26 127.562 -1.425 127.102 -1.425 c
+126.64 -1.425 126.269 -1.263 125.986 -0.941 c
+125.71 -0.61 125.567 -0.168 125.56 0.383 c
+h
+126.206 0.441 m
+126.206 0.038 126.283 -0.278 126.441 -0.514 c
+126.607 -0.749 126.828 -0.866 127.102 -0.866 c
+127.669 -0.866 127.963 -0.455 127.985 0.368 c
+127.985 0.823 l
+127.985 1.224 127.9 1.544 127.735 1.779 c
+127.576 2.022 127.36 2.147 127.088 2.147 c
+126.824 2.147 126.607 2.022 126.441 1.779 c
+126.283 1.544 126.206 1.224 126.206 0.823 c
+h
+130.086 2.631 m
+130.101 2.264 l
+130.344 2.558 130.664 2.705 131.057 2.705 c
+131.497 2.705 131.806 2.507 131.983 2.117 c
+132.237 2.507 132.586 2.705 133.026 2.705 c
+133.762 2.705 134.136 2.242 134.158 1.324 c
+134.158 -1.352 l
+133.512 -1.352 l
+133.512 1.264 l
+133.512 1.559 133.456 1.771 133.35 1.912 c
+133.251 2.047 133.078 2.117 132.835 2.117 c
+132.637 2.117 132.475 2.037 132.351 1.881 c
+132.233 1.735 132.163 1.544 132.145 1.309 c
+132.145 -1.352 l
+131.483 -1.352 l
+131.483 1.294 l
+131.483 1.841 131.262 2.117 130.822 2.117 c
+130.487 2.117 130.252 1.956 130.116 1.632 c
+130.116 -1.352 l
+129.469 -1.352 l
+129.469 2.631 l
+h
+135.746 2.631 m
+135.761 2.264 l
+136.003 2.558 136.323 2.705 136.716 2.705 c
+137.157 2.705 137.466 2.507 137.642 2.117 c
+137.895 2.507 138.244 2.705 138.686 2.705 c
+139.42 2.705 139.796 2.242 139.817 1.324 c
+139.817 -1.352 l
+139.171 -1.352 l
+139.171 1.264 l
+139.171 1.559 139.116 1.771 139.009 1.912 c
+138.91 2.047 138.737 2.117 138.495 2.117 c
+138.296 2.117 138.134 2.037 138.009 1.881 c
+137.892 1.735 137.822 1.544 137.804 1.309 c
+137.804 -1.352 l
+137.142 -1.352 l
+137.142 1.294 l
+137.142 1.841 136.922 2.117 136.481 2.117 c
+136.147 2.117 135.911 1.956 135.775 1.632 c
+135.775 -1.352 l
+135.129 -1.352 l
+135.129 2.631 l
+h
+141.493 -1.352 -0.646 3.983 re
+141.537 3.675 m
+141.537 3.565 141.508 3.473 141.449 3.396 c
+141.39 3.326 141.294 3.293 141.17 3.293 c
+141.053 3.293 140.957 3.326 140.891 3.396 c
+140.831 3.473 140.802 3.565 140.802 3.675 c
+140.802 3.793 140.831 3.884 140.891 3.955 c
+140.957 4.032 141.053 4.072 141.17 4.072 c
+141.294 4.072 141.39 4.032 141.449 3.955 c
+141.508 3.874 141.537 3.782 141.537 3.675 c
+143.36 3.587 m
+143.36 2.631 l
+143.962 2.631 l
+143.962 2.103 l
+143.36 2.103 l
+143.36 -0.367 l
+143.36 -0.525 143.382 -0.643 143.434 -0.72 c
+143.492 -0.801 143.58 -0.837 143.698 -0.837 c
+143.786 -0.837 143.875 -0.823 143.962 -0.793 c
+143.962 -1.352 l
+143.816 -1.4 143.661 -1.425 143.507 -1.425 c
+143.25 -1.425 143.055 -1.334 142.919 -1.146 c
+142.78 -0.962 142.713 -0.702 142.713 -0.367 c
+142.713 2.103 l
+142.111 2.103 l
+142.111 2.631 l
+142.713 2.631 l
+142.713 3.587 l
+h
+146.667 -0.338 m
+146.667 -0.191 146.612 -0.07 146.506 0.03 c
+146.395 0.125 146.19 0.243 145.888 0.383 c
+145.543 0.53 145.3 0.651 145.153 0.75 c
+145.006 0.857 144.896 0.975 144.83 1.103 c
+144.76 1.228 144.727 1.386 144.727 1.573 c
+144.727 1.897 144.845 2.165 145.08 2.382 c
+145.315 2.595 145.616 2.705 145.991 2.705 c
+146.373 2.705 146.682 2.591 146.917 2.367 c
+147.152 2.139 147.27 1.852 147.27 1.5 c
+146.623 1.5 l
+146.623 1.676 146.564 1.827 146.447 1.956 c
+146.329 2.08 146.175 2.147 145.991 2.147 c
+145.793 2.147 145.642 2.091 145.535 1.985 c
+145.425 1.885 145.373 1.754 145.373 1.588 c
+145.373 1.459 145.41 1.353 145.491 1.264 c
+145.568 1.183 145.76 1.081 146.065 0.956 c
+146.543 0.769 146.873 0.581 147.05 0.397 c
+147.226 0.221 147.314 -0.007 147.314 -0.278 c
+147.314 -0.631 147.189 -0.911 146.946 -1.117 c
+146.711 -1.323 146.395 -1.425 146.006 -1.425 c
+145.583 -1.425 145.245 -1.308 144.991 -1.072 c
+144.735 -0.83 144.609 -0.525 144.609 -0.161 c
+145.256 -0.161 l
+145.263 -0.389 145.333 -0.565 145.462 -0.69 c
+145.587 -0.808 145.77 -0.866 146.006 -0.866 c
+146.219 -0.866 146.381 -0.819 146.491 -0.72 c
+146.609 -0.625 146.667 -0.496 146.667 -0.338 c
+151.915 -1.352 m
+151.875 -1.263 151.848 -1.117 151.841 -0.911 c
+151.606 -1.256 151.312 -1.425 150.959 -1.425 c
+150.595 -1.425 150.312 -1.33 150.107 -1.132 c
+149.909 -0.926 149.813 -0.639 149.813 -0.264 c
+149.813 0.136 149.949 0.456 150.225 0.691 c
+150.497 0.934 150.871 1.058 151.341 1.058 c
+151.827 1.058 l
+151.827 1.485 l
+151.827 1.721 151.771 1.885 151.665 1.985 c
+151.555 2.091 151.393 2.147 151.18 2.147 c
+150.981 2.147 150.819 2.087 150.695 1.97 c
+150.578 1.852 150.518 1.706 150.518 1.529 c
+149.872 1.529 l
+149.872 1.723 149.93 1.915 150.048 2.103 c
+150.173 2.286 150.335 2.433 150.533 2.544 c
+150.739 2.65 150.967 2.705 151.224 2.705 c
+151.625 2.705 151.929 2.602 152.135 2.396 c
+152.348 2.191 152.463 1.897 152.473 1.515 c
+152.473 -0.5 l
+152.473 -0.804 152.51 -1.069 152.591 -1.294 c
+152.591 -1.352 l
+h
+151.048 -0.837 m
+151.213 -0.837 151.364 -0.793 151.503 -0.706 c
+151.65 -0.617 151.757 -0.507 151.827 -0.367 c
+151.827 0.574 l
+151.459 0.574 l
+151.143 0.574 150.9 0.504 150.724 0.368 c
+150.547 0.239 150.46 0.052 150.46 -0.191 c
+150.46 -0.419 150.504 -0.584 150.592 -0.69 c
+150.68 -0.789 150.831 -0.837 151.048 -0.837 c
+154.09 2.631 m
+154.105 2.191 l
+154.358 2.532 154.682 2.705 155.075 2.705 c
+155.781 2.705 156.137 2.234 156.149 1.294 c
+156.149 -1.352 l
+155.501 -1.352 l
+155.501 1.264 l
+155.501 1.577 155.446 1.798 155.34 1.926 c
+155.23 2.051 155.075 2.117 154.869 2.117 c
+154.711 2.117 154.564 2.062 154.428 1.956 c
+154.3 1.845 154.197 1.709 154.119 1.544 c
+154.119 -1.352 l
+153.473 -1.352 l
+153.473 2.631 l
+h
+156.986 0.823 m
+156.986 1.43 157.096 1.897 157.325 2.22 c
+157.56 2.544 157.886 2.705 158.309 2.705 c
+158.691 2.705 158.989 2.547 159.206 2.234 c
+159.206 4.293 l
+159.852 4.293 l
+159.852 -1.352 l
+159.264 -1.352 l
+159.22 -0.926 l
+159.014 -1.26 158.709 -1.425 158.309 -1.425 c
+157.897 -1.425 157.574 -1.271 157.339 -0.955 c
+157.103 -0.631 156.986 -0.176 156.986 0.412 c
+h
+157.633 0.441 m
+157.633 0 157.695 -0.33 157.824 -0.544 c
+157.96 -0.749 158.181 -0.852 158.485 -0.852 c
+158.809 -0.852 159.048 -0.69 159.206 -0.367 c
+159.206 1.646 l
+159.037 1.959 158.798 2.117 158.485 2.117 c
+158.181 2.117 157.96 2.014 157.824 1.808 c
+157.695 1.603 157.633 1.279 157.633 0.838 c
+h
+163.424 3.587 m
+163.424 2.631 l
+164.026 2.631 l
+164.026 2.103 l
+163.424 2.103 l
+163.424 -0.367 l
+163.424 -0.525 163.446 -0.643 163.498 -0.72 c
+163.556 -0.801 163.644 -0.837 163.762 -0.837 c
+163.85 -0.837 163.939 -0.823 164.026 -0.793 c
+164.026 -1.352 l
+163.88 -1.4 163.725 -1.425 163.571 -1.425 c
+163.314 -1.425 163.119 -1.334 162.983 -1.146 c
+162.844 -0.962 162.777 -0.702 162.777 -0.367 c
+162.777 2.103 l
+162.175 2.103 l
+162.175 2.631 l
+162.777 2.631 l
+162.777 3.587 l
+h
+166.834 -1.352 m
+166.794 -1.263 166.769 -1.117 166.761 -0.911 c
+166.526 -1.256 166.231 -1.425 165.879 -1.425 c
+165.516 -1.425 165.232 -1.33 165.026 -1.132 c
+164.828 -0.926 164.732 -0.639 164.732 -0.264 c
+164.732 0.136 164.868 0.456 165.144 0.691 c
+165.416 0.934 165.791 1.058 166.262 1.058 c
+166.746 1.058 l
+166.746 1.485 l
+166.746 1.721 166.691 1.885 166.584 1.985 c
+166.474 2.091 166.312 2.147 166.1 2.147 c
+165.901 2.147 165.739 2.087 165.614 1.97 c
+165.497 1.852 165.437 1.706 165.437 1.529 c
+164.791 1.529 l
+164.791 1.723 164.85 1.915 164.967 2.103 c
+165.092 2.286 165.254 2.433 165.453 2.544 c
+165.659 2.65 165.886 2.705 166.143 2.705 c
+166.544 2.705 166.849 2.602 167.055 2.396 c
+167.268 2.191 167.382 1.897 167.393 1.515 c
+167.393 -0.5 l
+167.393 -0.804 167.43 -1.069 167.511 -1.294 c
+167.511 -1.352 l
+h
+165.967 -0.837 m
+166.133 -0.837 166.283 -0.793 166.422 -0.706 c
+166.57 -0.617 166.676 -0.507 166.746 -0.367 c
+166.746 0.574 l
+166.378 0.574 l
+166.063 0.574 165.82 0.504 165.643 0.368 c
+165.468 0.239 165.379 0.052 165.379 -0.191 c
+165.379 -0.419 165.423 -0.584 165.512 -0.69 c
+165.599 -0.789 165.751 -0.837 165.967 -0.837 c
+168.26 0.823 m
+168.26 1.441 168.371 1.904 168.598 2.22 c
+168.822 2.544 169.157 2.705 169.597 2.705 c
+169.998 2.705 170.303 2.529 170.509 2.176 c
+170.553 2.631 l
+171.141 2.631 l
+171.141 -1.396 l
+171.141 -1.884 171.012 -2.263 170.759 -2.528 c
+170.501 -2.792 170.149 -2.925 169.701 -2.925 c
+169.502 -2.925 169.281 -2.873 169.04 -2.778 c
+168.793 -2.678 168.613 -2.557 168.495 -2.41 c
+168.76 -1.969 l
+169.025 -2.234 169.322 -2.366 169.657 -2.366 c
+170.193 -2.366 170.469 -2.072 170.48 -1.484 c
+170.48 -0.955 l
+170.274 -1.271 169.973 -1.425 169.583 -1.425 c
+169.171 -1.425 168.849 -1.275 168.613 -0.97 c
+168.385 -0.658 168.267 -0.205 168.26 0.383 c
+h
+168.922 0.441 m
+168.922 0 168.984 -0.33 169.113 -0.544 c
+169.238 -0.749 169.454 -0.852 169.759 -0.852 c
+170.083 -0.852 170.322 -0.687 170.48 -0.353 c
+170.48 1.632 l
+170.311 1.956 170.072 2.117 169.759 2.117 c
+169.466 2.117 169.248 2.014 169.113 1.808 c
+168.984 1.603 168.922 1.279 168.922 0.838 c
+h
+174.037 -0.338 m
+174.037 -0.191 173.982 -0.07 173.875 0.03 c
+173.765 0.125 173.559 0.243 173.258 0.383 c
+172.913 0.53 172.67 0.651 172.523 0.75 c
+172.376 0.857 172.265 0.975 172.2 1.103 c
+172.13 1.228 172.097 1.386 172.097 1.573 c
+172.097 1.897 172.215 2.165 172.45 2.382 c
+172.685 2.595 172.986 2.705 173.36 2.705 c
+173.743 2.705 174.052 2.591 174.287 2.367 c
+174.522 2.139 174.64 1.852 174.64 1.5 c
+173.993 1.5 l
+173.993 1.676 173.934 1.827 173.817 1.956 c
+173.699 2.08 173.545 2.147 173.36 2.147 c
+173.162 2.147 173.011 2.091 172.905 1.985 c
+172.795 1.885 172.743 1.754 172.743 1.588 c
+172.743 1.459 172.78 1.353 172.861 1.264 c
+172.938 1.183 173.129 1.081 173.434 0.956 c
+173.912 0.769 174.243 0.581 174.419 0.397 c
+174.596 0.221 174.684 -0.007 174.684 -0.278 c
+174.684 -0.631 174.559 -0.911 174.316 -1.117 c
+174.081 -1.323 173.765 -1.425 173.375 -1.425 c
+172.953 -1.425 172.614 -1.308 172.361 -1.072 c
+172.104 -0.83 171.979 -0.525 171.979 -0.161 c
+172.626 -0.161 l
+172.633 -0.389 172.703 -0.565 172.832 -0.69 c
+172.957 -0.808 173.14 -0.866 173.375 -0.866 c
+173.589 -0.866 173.75 -0.819 173.861 -0.72 c
+173.978 -0.625 174.037 -0.496 174.037 -0.338 c
+175.565 -0.999 m
+175.565 -0.881 175.598 -0.786 175.669 -0.706 c
+175.735 -0.628 175.837 -0.588 175.978 -0.588 c
+176.124 -0.588 176.231 -0.628 176.3 -0.706 c
+176.377 -0.786 176.418 -0.881 176.418 -0.999 c
+176.418 -1.109 176.377 -1.201 176.3 -1.278 c
+176.231 -1.356 176.124 -1.396 175.978 -1.396 c
+175.837 -1.396 175.735 -1.356 175.669 -1.278 c
+175.598 -1.201 175.565 -1.109 175.565 -0.999 c
+f
+Q
+0.113 0.082 0.09 0 k
+35.668 383.129 238.665 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 40.8563 376.2903 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.146 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.807 l
+-1.896 -1.807 l
+-1.896 -1.263 l
+-2.142 -1.256 -2.359 -1.219 -2.543 -1.161 c
+-2.719 -1.102 -2.873 -1.024 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.69 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.034 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.477 -2.234 -0.514 c
+-2.138 -0.554 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.662 l
+-1.907 0.662 -1.926 0.666 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.772 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.279 -3.219 1.426 c
+-3.289 1.573 -3.322 1.757 -3.322 1.985 c
+-3.322 2.18 -3.289 2.345 -3.219 2.485 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.933 -2.645 3.003 -2.469 3.043 c
+-2.293 3.091 -2.102 3.12 -1.896 3.132 c
+-1.896 3.558 l
+-1.543 3.558 l
+-1.543 3.132 l
+-1.319 3.12 -1.128 3.091 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.735 -0.349 2.621 -0.279 2.485 c
+-0.202 2.345 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.459 -1.543 2.5 c
+-1.543 1.368 l
+-1.514 1.368 l
+-1.506 1.368 -1.492 1.36 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.206 c
+-0.756 1.147 -0.595 1.066 -0.455 0.971 c
+-0.32 0.871 -0.213 0.743 -0.132 0.588 c
+-0.044 0.431 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.503 -2.113 2.485 -2.19 2.455 c
+-2.26 2.426 -2.319 2.386 -2.366 2.338 c
+-2.406 2.297 -2.437 2.249 -2.454 2.191 c
+-2.477 2.132 -2.484 2.066 -2.484 1.999 c
+-2.484 1.912 -2.469 1.838 -2.439 1.779 c
+-2.41 1.721 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.201 1.559 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.441 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.302 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.44 c
+-0.904 -0.345 -0.837 -0.201 -0.837 -0.014 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.634 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.395 c
+5.284 -2.314 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.616 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.146 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.83 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.219 6.034 -1.219 c
+5.829 -1.219 5.644 -1.182 5.49 -1.102 c
+5.343 -1.014 5.215 -0.897 5.108 -0.749 c
+5.009 -0.595 4.935 -0.411 4.888 -0.205 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.772 4.836 1.019 4.888 1.235 c
+4.946 1.449 5.027 1.632 5.137 1.779 c
+5.245 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.264 6.093 2.264 c
+6.188 2.264 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.919 7.107 1.97 c
+7.115 2.029 7.122 2.077 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.152 2.22 c
+8.004 2.22 l
+7.993 2.139 7.982 2.029 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.414 7.938 -1.635 7.871 -1.822 c
+7.802 -2.006 7.699 -2.16 7.563 -2.278 c
+7.423 -2.403 7.258 -2.499 7.063 -2.557 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.743 7.067 0.919 7.019 1.058 c
+6.978 1.206 6.924 1.324 6.857 1.411 c
+6.799 1.5 6.729 1.559 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.368 c
+5.88 1.279 5.835 1.162 5.799 1.015 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.514 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.558 c
+6.725 -0.521 6.799 -0.463 6.857 -0.382 c
+6.924 -0.293 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.302 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.263 l
+8.86 -1.263 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.603 l
+9.199 1.603 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.6 1.603 m
+13.057 1.603 l
+13.057 2.22 l
+13.644 2.22 l
+13.924 3.117 l
+14.497 3.117 l
+14.497 2.22 l
+15.732 2.22 l
+15.732 1.603 l
+14.497 1.603 l
+14.497 -0.103 l
+14.497 -0.323 l
+14.504 -0.392 14.527 -0.455 14.556 -0.514 c
+14.593 -0.565 14.648 -0.61 14.718 -0.646 c
+14.795 -0.675 14.909 -0.69 15.056 -0.69 c
+15.192 -0.69 15.327 -0.687 15.468 -0.675 c
+15.603 -0.658 15.736 -0.631 15.865 -0.602 c
+15.865 -1.205 l
+15.784 -1.215 15.707 -1.23 15.629 -1.249 c
+15.549 -1.26 15.471 -1.267 15.394 -1.278 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.041 -1.3 14.942 -1.308 14.835 -1.308 c
+14.648 -1.308 14.486 -1.294 14.35 -1.263 c
+14.221 -1.227 14.107 -1.182 14.012 -1.132 c
+13.924 -1.084 13.85 -1.024 13.791 -0.955 c
+13.733 -0.878 13.689 -0.801 13.66 -0.72 c
+13.63 -0.631 13.608 -0.544 13.6 -0.455 c
+13.59 -0.359 13.586 -0.264 13.586 -0.176 c
+h
+22.677 -1.323 m
+22.391 -1.323 22.148 -1.282 21.943 -1.205 c
+21.737 -1.117 21.564 -0.995 21.428 -0.837 c
+21.288 -0.683 21.185 -0.496 21.119 -0.278 c
+21.049 -0.055 21.016 0.192 21.016 0.456 c
+21.016 0.75 21.049 1.008 21.119 1.235 c
+21.197 1.459 21.303 1.646 21.442 1.794 c
+21.589 1.948 21.766 2.066 21.972 2.147 c
+22.178 2.234 22.413 2.278 22.677 2.278 c
+22.901 2.278 23.104 2.249 23.28 2.191 c
+23.456 2.132 23.607 2.047 23.736 1.941 c
+23.861 1.842 23.963 1.721 24.044 1.573 c
+24.122 1.434 24.176 1.283 24.206 1.118 c
+23.295 1.073 l
+23.265 1.25 23.196 1.389 23.089 1.5 c
+22.99 1.607 22.846 1.661 22.662 1.661 c
+22.416 1.661 22.24 1.559 22.134 1.353 c
+22.023 1.154 21.972 0.867 21.972 0.485 c
+21.972 -0.309 22.207 -0.706 22.677 -0.706 c
+22.843 -0.706 22.986 -0.654 23.104 -0.544 c
+23.221 -0.436 23.295 -0.275 23.324 -0.058 c
+24.235 -0.103 l
+24.206 -0.272 24.151 -0.426 24.074 -0.573 c
+24.004 -0.72 23.901 -0.852 23.765 -0.97 c
+23.636 -1.08 23.478 -1.168 23.295 -1.234 c
+23.119 -1.294 22.913 -1.323 22.677 -1.323 c
+28.384 0.485 m
+28.384 0.21 28.347 -0.039 28.281 -0.264 c
+28.212 -0.481 28.108 -0.668 27.973 -0.823 c
+27.833 -0.98 27.657 -1.102 27.443 -1.19 c
+27.227 -1.278 26.973 -1.323 26.679 -1.323 c
+26.404 -1.323 26.157 -1.278 25.944 -1.19 c
+25.739 -1.102 25.566 -0.98 25.43 -0.823 c
+25.29 -0.668 25.187 -0.481 25.121 -0.264 c
+25.051 -0.039 25.018 0.21 25.018 0.485 c
+25.018 0.739 25.047 0.975 25.106 1.191 c
+25.172 1.415 25.275 1.607 25.415 1.764 c
+25.55 1.929 25.727 2.058 25.944 2.147 c
+26.157 2.234 26.414 2.278 26.709 2.278 c
+27.021 2.278 27.281 2.234 27.487 2.147 c
+27.701 2.058 27.873 1.929 28.002 1.764 c
+28.138 1.607 28.237 1.415 28.296 1.191 c
+28.355 0.975 28.384 0.739 28.384 0.485 c
+27.429 0.485 m
+27.429 0.691 27.414 0.867 27.385 1.015 c
+27.362 1.162 27.326 1.283 27.267 1.382 c
+27.208 1.478 27.135 1.548 27.046 1.588 c
+26.959 1.636 26.848 1.661 26.724 1.661 c
+26.458 1.661 26.267 1.563 26.15 1.368 c
+26.032 1.18 25.974 0.886 25.974 0.485 c
+25.974 0.063 26.032 -0.242 26.15 -0.426 c
+26.267 -0.613 26.444 -0.706 26.679 -0.706 c
+26.804 -0.706 26.918 -0.687 27.017 -0.646 c
+27.113 -0.598 27.194 -0.525 27.252 -0.426 c
+27.318 -0.33 27.362 -0.205 27.385 -0.058 c
+27.414 0.088 27.429 0.269 27.429 0.485 c
+31.43 -1.263 m
+31.43 0.721 l
+31.43 1.022 31.387 1.243 31.298 1.382 c
+31.217 1.529 31.081 1.603 30.886 1.603 c
+30.776 1.603 30.674 1.577 30.578 1.529 c
+30.489 1.478 30.409 1.411 30.343 1.324 c
+30.284 1.235 30.233 1.125 30.196 1 c
+30.167 0.882 30.152 0.75 30.152 0.603 c
+30.152 -1.263 l
+29.24 -1.263 l
+29.24 1.441 l
+29.24 1.661 l
+29.24 1.75 29.233 1.827 29.226 1.897 c
+29.226 2.087 l
+29.226 2.22 l
+30.078 2.22 l
+30.086 2.191 30.093 2.147 30.093 2.087 c
+30.093 1.897 l
+30.1 1.827 30.107 1.757 30.107 1.691 c
+30.115 1.621 30.122 1.566 30.122 1.529 c
+30.137 1.529 l
+30.254 1.794 30.406 1.985 30.593 2.103 c
+30.776 2.22 30.996 2.278 31.254 2.278 c
+31.438 2.278 31.599 2.249 31.74 2.191 c
+31.875 2.132 31.989 2.043 32.077 1.926 c
+32.166 1.808 32.228 1.665 32.268 1.5 c
+32.316 1.341 32.342 1.154 32.342 0.941 c
+32.342 -1.263 l
+h
+34.951 1.603 m
+34.951 -1.263 l
+34.054 -1.263 l
+34.054 1.603 l
+33.232 1.603 l
+33.232 2.22 l
+34.054 2.22 l
+34.054 2.485 l
+34.054 2.61 34.069 2.742 34.098 2.882 c
+34.135 3.018 34.205 3.135 34.304 3.234 c
+34.41 3.341 34.554 3.429 34.73 3.499 c
+34.907 3.565 35.131 3.602 35.407 3.602 c
+35.62 3.602 35.819 3.591 35.995 3.572 c
+36.17 3.55 36.322 3.532 36.45 3.514 c
+36.45 2.926 l
+36.322 2.944 36.178 2.959 36.024 2.97 c
+35.866 2.977 35.715 2.984 35.568 2.984 c
+35.44 2.984 35.337 2.97 35.26 2.94 c
+35.179 2.911 35.116 2.87 35.069 2.822 c
+35.017 2.771 34.984 2.708 34.965 2.631 c
+34.955 2.562 34.951 2.485 34.951 2.396 c
+34.951 2.22 l
+36.377 2.22 l
+36.377 1.603 l
+h
+39.467 -0.646 m
+40.599 -0.646 l
+40.599 -1.263 l
+37.292 -1.263 l
+37.292 -0.646 l
+38.556 -0.646 l
+38.556 1.603 l
+37.63 1.603 l
+37.63 2.22 l
+39.467 2.22 l
+h
+38.556 3.514 0.911 -0.676 re
+38.556 2.837 m
+42.954 -2.66 m
+42.738 -2.66 42.547 -2.634 42.381 -2.587 c
+42.212 -2.547 42.073 -2.484 41.955 -2.395 c
+41.837 -2.314 41.738 -2.219 41.661 -2.102 c
+41.591 -1.984 41.543 -1.855 41.514 -1.72 c
+42.41 -1.616 l
+42.447 -1.753 42.518 -1.859 42.616 -1.94 c
+42.712 -2.028 42.837 -2.072 42.984 -2.072 c
+43.072 -2.072 43.153 -2.057 43.234 -2.028 c
+43.311 -1.999 43.381 -1.944 43.44 -1.866 c
+43.499 -1.797 43.542 -1.705 43.572 -1.587 c
+43.609 -1.469 43.631 -1.323 43.631 -1.146 c
+43.631 -0.955 l
+43.631 -0.889 43.634 -0.83 43.646 -0.779 c
+43.646 -0.588 l
+43.631 -0.588 l
+43.532 -0.816 43.388 -0.977 43.204 -1.072 c
+43.017 -1.172 42.811 -1.219 42.587 -1.219 c
+42.381 -1.219 42.198 -1.182 42.044 -1.102 c
+41.896 -1.014 41.768 -0.897 41.661 -0.749 c
+41.562 -0.595 41.488 -0.411 41.441 -0.205 c
+41.389 0.008 41.367 0.243 41.367 0.5 c
+41.367 0.772 41.389 1.019 41.441 1.235 c
+41.5 1.449 41.58 1.632 41.691 1.779 c
+41.797 1.933 41.93 2.051 42.088 2.132 c
+42.242 2.22 42.429 2.264 42.646 2.264 c
+42.742 2.264 42.84 2.253 42.94 2.234 c
+43.035 2.213 43.123 2.18 43.204 2.132 c
+43.293 2.08 43.37 2.018 43.44 1.941 c
+43.517 1.86 43.58 1.768 43.631 1.661 c
+43.646 1.661 l
+43.646 1.808 l
+43.653 1.867 43.66 1.919 43.66 1.97 c
+43.667 2.029 43.675 2.077 43.675 2.117 c
+43.682 2.165 43.694 2.198 43.704 2.22 c
+44.557 2.22 l
+44.546 2.139 44.535 2.029 44.527 1.881 c
+44.527 1.411 l
+44.527 -1.161 l
+44.527 -1.414 44.49 -1.635 44.425 -1.822 c
+44.355 -2.006 44.251 -2.16 44.116 -2.278 c
+43.976 -2.403 43.811 -2.499 43.616 -2.557 c
+43.418 -2.624 43.197 -2.66 42.954 -2.66 c
+43.646 0.53 m
+43.646 0.743 43.619 0.919 43.572 1.058 c
+43.532 1.206 43.476 1.324 43.41 1.411 c
+43.351 1.5 43.282 1.559 43.204 1.588 c
+43.123 1.625 43.046 1.646 42.969 1.646 c
+42.87 1.646 42.778 1.621 42.69 1.573 c
+42.609 1.532 42.543 1.463 42.484 1.368 c
+42.433 1.279 42.389 1.162 42.352 1.015 c
+42.323 0.875 42.308 0.706 42.308 0.5 c
+42.308 0.125 42.366 -0.154 42.484 -0.338 c
+42.601 -0.514 42.763 -0.602 42.969 -0.602 c
+43.035 -0.602 43.109 -0.588 43.189 -0.558 c
+43.278 -0.521 43.351 -0.463 43.41 -0.382 c
+43.476 -0.293 43.532 -0.176 43.572 -0.029 c
+43.619 0.118 43.646 0.302 43.646 0.53 c
+50.135 0.838 1.867 -0.794 re
+50.135 0.044 m
+54.2 0.838 1.866 -0.794 re
+54.2 0.044 m
+59.201 -2.66 m
+58.983 -2.66 58.792 -2.634 58.628 -2.587 c
+58.458 -2.547 58.318 -2.484 58.201 -2.395 c
+58.083 -2.314 57.984 -2.219 57.907 -2.102 c
+57.838 -1.984 57.79 -1.855 57.76 -1.72 c
+58.657 -1.616 l
+58.694 -1.753 58.763 -1.859 58.863 -1.94 c
+58.958 -2.028 59.083 -2.072 59.23 -2.072 c
+59.318 -2.072 59.399 -2.057 59.48 -2.028 c
+59.557 -1.999 59.627 -1.944 59.686 -1.866 c
+59.744 -1.797 59.789 -1.705 59.818 -1.587 c
+59.855 -1.469 59.877 -1.323 59.877 -1.146 c
+59.877 -0.955 l
+59.877 -0.889 59.881 -0.83 59.891 -0.779 c
+59.891 -0.588 l
+59.877 -0.588 l
+59.777 -0.816 59.634 -0.977 59.451 -1.072 c
+59.263 -1.172 59.058 -1.219 58.833 -1.219 c
+58.628 -1.219 58.443 -1.182 58.289 -1.102 c
+58.142 -1.014 58.014 -0.897 57.907 -0.749 c
+57.807 -0.595 57.734 -0.411 57.687 -0.205 c
+57.635 0.008 57.613 0.243 57.613 0.5 c
+57.613 0.772 57.635 1.019 57.687 1.235 c
+57.745 1.449 57.826 1.632 57.936 1.779 c
+58.043 1.933 58.175 2.051 58.333 2.132 c
+58.488 2.22 58.675 2.264 58.892 2.264 c
+58.987 2.264 59.087 2.253 59.186 2.234 c
+59.282 2.213 59.37 2.18 59.451 2.132 c
+59.538 2.08 59.616 2.018 59.686 1.941 c
+59.763 1.86 59.825 1.768 59.877 1.661 c
+59.891 1.661 l
+59.891 1.808 l
+59.899 1.867 59.906 1.919 59.906 1.97 c
+59.914 2.029 59.921 2.077 59.921 2.117 c
+59.928 2.165 59.939 2.198 59.951 2.22 c
+60.803 2.22 l
+60.792 2.139 60.781 2.029 60.774 1.881 c
+60.774 1.411 l
+60.774 -1.161 l
+60.774 -1.414 60.737 -1.635 60.67 -1.822 c
+60.601 -2.006 60.498 -2.16 60.362 -2.278 c
+60.222 -2.403 60.057 -2.499 59.862 -2.557 c
+59.664 -2.624 59.443 -2.66 59.201 -2.66 c
+59.891 0.53 m
+59.891 0.743 59.866 0.919 59.818 1.058 c
+59.777 1.206 59.723 1.324 59.656 1.411 c
+59.598 1.5 59.528 1.559 59.451 1.588 c
+59.37 1.625 59.293 1.646 59.216 1.646 c
+59.116 1.646 59.024 1.621 58.936 1.573 c
+58.855 1.532 58.789 1.463 58.73 1.368 c
+58.679 1.279 58.634 1.162 58.598 1.015 c
+58.569 0.875 58.553 0.706 58.553 0.5 c
+58.553 0.125 58.613 -0.154 58.73 -0.338 c
+58.848 -0.514 59.01 -0.602 59.216 -0.602 c
+59.282 -0.602 59.355 -0.588 59.436 -0.558 c
+59.524 -0.521 59.598 -0.463 59.656 -0.382 c
+59.723 -0.293 59.777 -0.176 59.818 -0.029 c
+59.866 0.118 59.891 0.302 59.891 0.53 c
+63.835 -0.646 m
+64.967 -0.646 l
+64.967 -1.263 l
+61.659 -1.263 l
+61.659 -0.646 l
+62.923 -0.646 l
+62.923 2.897 l
+61.998 2.897 l
+61.998 3.514 l
+63.835 3.514 l
+h
+68.998 0.485 m
+68.998 0.21 68.961 -0.039 68.895 -0.264 c
+68.824 -0.481 68.722 -0.668 68.586 -0.823 c
+68.446 -0.98 68.27 -1.102 68.057 -1.19 c
+67.84 -1.278 67.586 -1.323 67.293 -1.323 c
+67.017 -1.323 66.771 -1.278 66.557 -1.19 c
+66.352 -1.102 66.179 -0.98 66.043 -0.823 c
+65.903 -0.668 65.801 -0.481 65.734 -0.264 c
+65.665 -0.039 65.632 0.21 65.632 0.485 c
+65.632 0.739 65.661 0.975 65.72 1.191 c
+65.786 1.415 65.888 1.607 66.029 1.764 c
+66.164 1.929 66.341 2.058 66.557 2.147 c
+66.771 2.234 67.028 2.278 67.322 2.278 c
+67.634 2.278 67.895 2.234 68.101 2.147 c
+68.314 2.058 68.487 1.929 68.616 1.764 c
+68.751 1.607 68.851 1.415 68.909 1.191 c
+68.968 0.975 68.998 0.739 68.998 0.485 c
+68.042 0.485 m
+68.042 0.691 68.028 0.867 67.999 1.015 c
+67.976 1.162 67.939 1.283 67.881 1.382 c
+67.822 1.478 67.748 1.548 67.66 1.588 c
+67.571 1.636 67.461 1.661 67.336 1.661 c
+67.072 1.661 66.881 1.563 66.763 1.368 c
+66.646 1.18 66.587 0.886 66.587 0.485 c
+66.587 0.063 66.646 -0.242 66.763 -0.426 c
+66.881 -0.613 67.058 -0.706 67.293 -0.706 c
+67.417 -0.706 67.531 -0.687 67.631 -0.646 c
+67.726 -0.598 67.807 -0.525 67.866 -0.426 c
+67.932 -0.33 67.976 -0.205 67.999 -0.058 c
+68.028 0.088 68.042 0.269 68.042 0.485 c
+69.854 -1.263 m
+69.854 -0.97 l
+69.861 -0.833 69.869 -0.675 69.869 -0.5 c
+69.869 3.514 l
+70.78 3.514 l
+70.78 2.234 l
+70.78 2.073 l
+70.78 1.897 l
+70.78 1.845 70.773 1.802 70.765 1.764 c
+70.765 1.676 l
+70.78 1.676 l
+70.827 1.783 70.89 1.875 70.971 1.956 c
+71.048 2.033 71.133 2.095 71.221 2.147 c
+71.309 2.195 71.401 2.228 71.5 2.249 c
+71.596 2.268 71.695 2.278 71.794 2.278 c
+72.007 2.278 72.194 2.234 72.352 2.147 c
+72.507 2.058 72.635 1.929 72.735 1.764 c
+72.841 1.607 72.919 1.415 72.97 1.191 c
+73.017 0.975 73.044 0.736 73.044 0.47 c
+73.044 0.214 73.015 -0.025 72.955 -0.249 c
+72.897 -0.467 72.812 -0.658 72.705 -0.823 c
+72.595 -0.98 72.463 -1.102 72.309 -1.19 c
+72.151 -1.278 71.97 -1.323 71.764 -1.323 c
+71.666 -1.323 71.567 -1.311 71.471 -1.294 c
+71.382 -1.271 71.294 -1.242 71.206 -1.19 c
+71.118 -1.132 71.037 -1.065 70.971 -0.984 c
+70.901 -0.907 70.839 -0.808 70.78 -0.69 c
+70.765 -0.69 l
+70.765 -0.852 l
+70.765 -0.911 70.758 -0.97 70.75 -1.028 c
+70.75 -1.08 70.743 -1.128 70.736 -1.176 c
+70.736 -1.215 70.729 -1.246 70.721 -1.263 c
+h
+70.765 0.5 m
+70.765 0.265 70.783 0.067 70.824 -0.087 c
+70.872 -0.246 70.931 -0.367 71 -0.455 c
+71.066 -0.544 71.14 -0.61 71.221 -0.646 c
+71.298 -0.687 71.375 -0.706 71.456 -0.706 c
+71.662 -0.706 71.816 -0.61 71.926 -0.411 c
+72.044 -0.216 72.103 0.078 72.103 0.47 c
+72.103 0.684 72.08 0.867 72.044 1.015 c
+72.015 1.169 71.97 1.294 71.912 1.382 c
+71.86 1.478 71.794 1.551 71.706 1.603 c
+71.625 1.65 71.537 1.676 71.442 1.676 c
+71.361 1.676 71.284 1.654 71.206 1.617 c
+71.126 1.577 71.052 1.515 70.985 1.426 c
+70.927 1.338 70.872 1.214 70.824 1.058 c
+70.783 0.912 70.765 0.724 70.765 0.5 c
+74.873 -1.323 m
+74.704 -1.323 74.554 -1.3 74.418 -1.263 c
+74.289 -1.215 74.175 -1.146 74.079 -1.058 c
+73.992 -0.97 73.921 -0.863 73.874 -0.735 c
+73.823 -0.598 73.8 -0.448 73.8 -0.278 c
+73.8 -0.073 73.834 0.096 73.904 0.235 c
+73.969 0.383 74.065 0.493 74.183 0.574 c
+74.308 0.662 74.451 0.724 74.609 0.765 c
+74.775 0.802 74.951 0.827 75.138 0.838 c
+75.858 0.853 l
+75.858 1.029 l
+75.858 1.147 75.847 1.25 75.829 1.338 c
+75.807 1.426 75.774 1.492 75.726 1.544 c
+75.685 1.603 75.638 1.64 75.579 1.661 c
+75.521 1.68 75.454 1.691 75.388 1.691 c
+75.318 1.691 75.255 1.68 75.197 1.661 c
+75.145 1.65 75.097 1.625 75.05 1.588 c
+75.01 1.559 74.976 1.507 74.947 1.441 c
+74.925 1.382 74.91 1.301 74.903 1.206 c
+73.962 1.25 l
+73.992 1.397 74.035 1.532 74.095 1.661 c
+74.16 1.786 74.256 1.897 74.374 1.985 c
+74.492 2.08 74.631 2.154 74.8 2.205 c
+74.976 2.253 75.182 2.278 75.417 2.278 c
+75.858 2.278 76.19 2.168 76.417 1.956 c
+76.652 1.75 76.77 1.441 76.77 1.029 c
+76.77 -0.235 l
+76.77 -0.455 l
+76.777 -0.514 76.792 -0.569 76.814 -0.617 c
+76.832 -0.658 76.861 -0.69 76.902 -0.72 c
+76.938 -0.742 76.99 -0.749 77.049 -0.749 c
+77.115 -0.749 77.185 -0.745 77.254 -0.735 c
+77.254 -1.219 l
+77.196 -1.23 77.141 -1.242 77.093 -1.249 c
+77.053 -1.26 77.013 -1.267 76.976 -1.278 c
+76.936 -1.286 76.891 -1.294 76.843 -1.294 c
+76.792 -1.3 76.733 -1.308 76.666 -1.308 c
+76.439 -1.308 76.273 -1.256 76.167 -1.146 c
+76.057 -1.028 75.995 -0.863 75.976 -0.646 c
+75.961 -0.646 l
+75.891 -0.756 75.822 -0.852 75.756 -0.941 c
+75.685 -1.021 75.608 -1.087 75.521 -1.146 c
+75.432 -1.205 75.333 -1.249 75.226 -1.278 c
+75.127 -1.308 75.01 -1.323 74.873 -1.323 c
+75.858 0.353 m
+75.432 0.339 l
+75.333 0.339 75.241 0.331 75.153 0.324 c
+75.072 0.313 75.006 0.287 74.947 0.25 c
+74.889 0.21 74.837 0.151 74.8 0.074 c
+74.76 0.004 74.741 -0.087 74.741 -0.205 c
+74.741 -0.374 74.775 -0.496 74.844 -0.573 c
+74.91 -0.654 75.01 -0.69 75.138 -0.69 c
+75.245 -0.69 75.344 -0.668 75.432 -0.617 c
+75.527 -0.569 75.608 -0.507 75.667 -0.426 c
+75.733 -0.349 75.785 -0.261 75.814 -0.161 c
+75.843 -0.055 75.858 0.059 75.858 0.177 c
+h
+80.08 -0.646 m
+81.212 -0.646 l
+81.212 -1.263 l
+77.905 -1.263 l
+77.905 -0.646 l
+79.17 -0.646 l
+79.17 2.897 l
+78.243 2.897 l
+78.243 3.514 l
+80.08 3.514 l
+h
+86.982 2.22 m
+86.982 0.265 l
+86.982 0.125 86.989 0 87.011 -0.118 c
+87.03 -0.228 87.063 -0.319 87.114 -0.396 c
+87.162 -0.477 87.221 -0.54 87.29 -0.588 c
+87.357 -0.627 87.441 -0.646 87.54 -0.646 c
+87.629 -0.646 87.71 -0.627 87.791 -0.588 c
+87.878 -0.54 87.952 -0.47 88.011 -0.382 c
+88.069 -0.286 88.113 -0.176 88.144 -0.058 c
+88.18 0.067 88.202 0.206 88.202 0.353 c
+88.202 2.22 l
+89.098 2.22 l
+89.098 -0.484 l
+89.098 -0.72 l
+89.106 -0.801 89.113 -0.878 89.113 -0.955 c
+89.113 -1.146 l
+89.121 -1.198 89.128 -1.234 89.128 -1.263 c
+88.275 -1.263 l
+88.265 -1.234 88.254 -1.198 88.246 -1.146 c
+88.246 -0.955 l
+88.246 -0.889 88.239 -0.819 88.231 -0.749 c
+88.231 -0.573 l
+88.217 -0.573 l
+88.099 -0.837 87.945 -1.028 87.761 -1.146 c
+87.585 -1.263 87.382 -1.323 87.159 -1.323 c
+86.953 -1.323 86.779 -1.286 86.644 -1.219 c
+86.504 -1.153 86.394 -1.058 86.305 -0.941 c
+86.225 -0.823 86.166 -0.687 86.129 -0.529 c
+86.1 -0.363 86.085 -0.187 86.085 0 c
+86.085 2.22 l
+h
+93.262 -0.249 m
+93.262 -0.419 93.222 -0.569 93.144 -0.706 c
+93.075 -0.833 92.971 -0.947 92.836 -1.043 c
+92.707 -1.132 92.545 -1.201 92.351 -1.249 c
+92.163 -1.296 91.947 -1.323 91.704 -1.323 c
+91.477 -1.323 91.278 -1.308 91.101 -1.278 c
+90.925 -1.249 90.767 -1.201 90.631 -1.132 c
+90.492 -1.055 90.382 -0.955 90.293 -0.837 c
+90.205 -0.72 90.135 -0.573 90.087 -0.396 c
+90.895 -0.278 l
+90.914 -0.378 90.943 -0.455 90.984 -0.514 c
+91.032 -0.573 91.09 -0.617 91.16 -0.646 c
+91.226 -0.675 91.307 -0.702 91.396 -0.72 c
+91.483 -0.731 91.587 -0.735 91.704 -0.735 c
+91.799 -0.735 91.895 -0.731 91.984 -0.72 c
+92.071 -0.702 92.148 -0.675 92.219 -0.646 c
+92.285 -0.617 92.336 -0.58 92.366 -0.529 c
+92.402 -0.481 92.424 -0.419 92.424 -0.338 c
+92.424 -0.242 92.395 -0.168 92.336 -0.118 c
+92.285 -0.07 92.219 -0.029 92.13 0 c
+92.042 0.038 91.932 0.067 91.807 0.088 c
+91.689 0.118 91.557 0.148 91.41 0.177 c
+91.271 0.214 91.13 0.254 90.984 0.294 c
+90.844 0.342 90.719 0.405 90.602 0.485 c
+90.492 0.563 90.403 0.662 90.337 0.78 c
+90.267 0.897 90.234 1.048 90.234 1.235 c
+90.234 1.389 90.263 1.532 90.322 1.661 c
+90.388 1.798 90.484 1.912 90.602 1.999 c
+90.727 2.087 90.885 2.154 91.072 2.205 c
+91.255 2.253 91.469 2.278 91.704 2.278 c
+91.888 2.278 92.065 2.257 92.233 2.22 c
+92.398 2.191 92.545 2.135 92.674 2.058 c
+92.799 1.989 92.909 1.889 92.998 1.764 c
+93.085 1.646 93.144 1.503 93.174 1.338 c
+92.38 1.264 l
+92.358 1.341 92.329 1.405 92.292 1.455 c
+92.252 1.515 92.204 1.559 92.144 1.588 c
+92.094 1.625 92.031 1.65 91.954 1.661 c
+91.873 1.669 91.793 1.676 91.704 1.676 c
+91.487 1.676 91.325 1.646 91.219 1.588 c
+91.109 1.536 91.057 1.449 91.057 1.324 c
+91.057 1.243 91.076 1.18 91.116 1.133 c
+91.164 1.081 91.226 1.044 91.307 1.015 c
+91.396 0.985 91.491 0.956 91.601 0.927 c
+91.708 0.904 91.829 0.882 91.969 0.853 c
+92.123 0.823 92.281 0.784 92.439 0.736 c
+92.593 0.684 92.733 0.622 92.85 0.545 c
+92.969 0.464 93.064 0.36 93.144 0.235 c
+93.222 0.107 93.262 -0.055 93.262 -0.249 c
+95.783 -1.323 m
+95.525 -1.323 95.298 -1.286 95.092 -1.219 c
+94.887 -1.142 94.71 -1.028 94.563 -0.881 c
+94.416 -0.727 94.299 -0.536 94.21 -0.309 c
+94.129 -0.084 94.093 0.181 94.093 0.485 c
+94.093 0.817 94.137 1.096 94.224 1.324 c
+94.32 1.559 94.449 1.742 94.607 1.881 c
+94.772 2.018 94.96 2.117 95.165 2.176 c
+95.371 2.242 95.581 2.278 95.797 2.278 c
+96.069 2.278 96.304 2.228 96.503 2.132 c
+96.709 2.043 96.875 1.912 97.003 1.735 c
+97.139 1.566 97.239 1.36 97.297 1.118 c
+97.363 0.882 97.399 0.618 97.399 0.324 c
+97.399 0.31 l
+95.033 0.31 l
+95.033 0.162 95.048 0.023 95.078 -0.103 c
+95.114 -0.231 95.169 -0.345 95.24 -0.44 c
+95.305 -0.529 95.39 -0.598 95.489 -0.646 c
+95.585 -0.698 95.699 -0.72 95.827 -0.72 c
+95.982 -0.72 96.121 -0.687 96.239 -0.617 c
+96.364 -0.55 96.452 -0.448 96.503 -0.309 c
+97.341 -0.382 l
+97.312 -0.481 97.256 -0.588 97.179 -0.706 c
+97.098 -0.816 96.996 -0.918 96.871 -1.014 c
+96.753 -1.102 96.599 -1.176 96.415 -1.234 c
+96.239 -1.294 96.026 -1.323 95.783 -1.323 c
+95.783 1.706 m
+95.695 1.706 95.606 1.691 95.518 1.661 c
+95.43 1.632 95.35 1.58 95.283 1.515 c
+95.213 1.445 95.155 1.357 95.107 1.25 c
+95.066 1.139 95.048 1.015 95.048 0.867 c
+96.518 0.867 l
+96.518 1.004 96.493 1.125 96.445 1.235 c
+96.404 1.341 96.349 1.43 96.283 1.5 c
+96.224 1.566 96.15 1.617 96.063 1.646 c
+95.974 1.684 95.878 1.706 95.783 1.706 c
+101.299 1.47 m
+101.2 1.478 101.097 1.489 100.99 1.5 c
+100.88 1.518 100.759 1.529 100.622 1.529 c
+100.446 1.529 100.288 1.489 100.152 1.411 c
+100.013 1.341 99.895 1.243 99.799 1.118 c
+99.711 0.989 99.641 0.842 99.593 0.676 c
+99.554 0.508 99.535 0.331 99.535 0.148 c
+99.535 -1.263 l
+98.638 -1.263 l
+98.638 0.985 l
+98.638 1.11 98.627 1.235 98.609 1.353 c
+98.598 1.478 98.583 1.596 98.565 1.706 c
+98.554 1.823 98.539 1.919 98.521 1.999 c
+98.498 2.087 98.48 2.161 98.462 2.22 c
+99.344 2.22 l
+99.351 2.168 99.362 2.117 99.373 2.058 c
+99.392 1.999 99.406 1.933 99.417 1.867 c
+99.435 1.808 99.45 1.742 99.462 1.676 c
+99.469 1.607 99.479 1.544 99.491 1.485 c
+99.506 1.485 l
+99.542 1.603 99.593 1.709 99.653 1.808 c
+99.718 1.904 99.799 1.989 99.888 2.058 c
+99.976 2.124 100.079 2.18 100.196 2.22 c
+100.321 2.257 100.468 2.278 100.637 2.278 c
+100.763 2.278 100.88 2.272 100.99 2.264 c
+101.108 2.253 101.21 2.238 101.299 2.22 c
+h
+103.404 -0.278 0.927 -0.985 re
+103.404 -1.263 m
+107.965 -1.323 m
+107.707 -1.323 107.479 -1.286 107.274 -1.219 c
+107.068 -1.142 106.892 -1.028 106.745 -0.881 c
+106.598 -0.727 106.48 -0.536 106.392 -0.309 c
+106.311 -0.084 106.274 0.181 106.274 0.485 c
+106.274 0.817 106.319 1.096 106.407 1.324 c
+106.502 1.559 106.631 1.742 106.789 1.881 c
+106.955 2.018 107.142 2.117 107.348 2.176 c
+107.553 2.242 107.763 2.278 107.98 2.278 c
+108.252 2.278 108.487 2.228 108.686 2.132 c
+108.891 2.043 109.056 1.912 109.185 1.735 c
+109.32 1.566 109.42 1.36 109.479 1.118 c
+109.545 0.882 109.582 0.618 109.582 0.324 c
+109.582 0.31 l
+107.215 0.31 l
+107.215 0.162 107.23 0.023 107.259 -0.103 c
+107.296 -0.231 107.352 -0.345 107.421 -0.44 c
+107.487 -0.529 107.572 -0.598 107.67 -0.646 c
+107.766 -0.698 107.88 -0.72 108.009 -0.72 c
+108.163 -0.72 108.303 -0.687 108.42 -0.617 c
+108.545 -0.55 108.634 -0.448 108.686 -0.309 c
+109.523 -0.382 l
+109.494 -0.481 109.438 -0.588 109.361 -0.706 c
+109.28 -0.816 109.178 -0.918 109.052 -1.014 c
+108.935 -1.102 108.781 -1.176 108.597 -1.234 c
+108.42 -1.294 108.208 -1.323 107.965 -1.323 c
+107.965 1.706 m
+107.876 1.706 107.788 1.691 107.701 1.661 c
+107.612 1.632 107.531 1.58 107.465 1.515 c
+107.395 1.445 107.336 1.357 107.288 1.25 c
+107.248 1.139 107.23 1.015 107.23 0.867 c
+108.7 0.867 l
+108.7 1.004 108.674 1.125 108.626 1.235 c
+108.586 1.341 108.53 1.43 108.464 1.5 c
+108.406 1.566 108.333 1.617 108.244 1.646 c
+108.156 1.684 108.06 1.706 107.965 1.706 c
+111.628 -1.263 m
+111.628 0.853 l
+111.628 1.019 111.622 1.154 111.614 1.264 c
+111.603 1.372 111.585 1.455 111.555 1.515 c
+111.533 1.58 111.504 1.632 111.467 1.661 c
+111.437 1.691 111.397 1.706 111.35 1.706 c
+111.29 1.706 111.235 1.676 111.188 1.617 c
+111.147 1.566 111.114 1.492 111.084 1.397 c
+111.055 1.309 111.03 1.195 111.011 1.058 c
+111 0.919 110.997 0.769 110.997 0.603 c
+110.997 -1.263 l
+110.247 -1.263 l
+110.247 1.47 l
+110.247 1.706 l
+110.247 1.926 l
+110.247 2.003 110.24 2.066 110.232 2.117 c
+110.232 2.22 l
+110.908 2.22 l
+110.908 2.132 l
+110.908 1.985 l
+110.916 1.926 110.923 1.867 110.923 1.808 c
+110.923 1.646 l
+110.938 1.646 l
+110.956 1.735 110.986 1.812 111.026 1.881 c
+111.063 1.96 111.107 2.029 111.158 2.087 c
+111.217 2.147 111.283 2.191 111.364 2.22 c
+111.441 2.257 111.529 2.278 111.628 2.278 c
+111.813 2.278 111.952 2.224 112.04 2.117 c
+112.135 2.018 112.206 1.86 112.246 1.646 c
+112.26 1.646 l
+112.297 1.742 112.337 1.831 112.378 1.912 c
+112.426 1.989 112.481 2.051 112.54 2.103 c
+112.599 2.161 112.665 2.205 112.746 2.234 c
+112.823 2.264 112.911 2.278 113.01 2.278 c
+113.146 2.278 113.26 2.253 113.349 2.205 c
+113.436 2.154 113.503 2.08 113.554 1.985 c
+113.613 1.885 113.65 1.757 113.671 1.603 c
+113.702 1.455 113.716 1.272 113.716 1.058 c
+113.716 -1.263 l
+112.996 -1.263 l
+112.996 0.853 l
+112.996 1.019 112.988 1.154 112.981 1.264 c
+112.97 1.372 112.952 1.455 112.922 1.515 c
+112.9 1.58 112.871 1.632 112.834 1.661 c
+112.804 1.691 112.764 1.706 112.717 1.706 c
+112.599 1.706 112.503 1.617 112.437 1.441 c
+112.378 1.272 112.349 1.015 112.349 0.662 c
+112.349 -1.263 l
+h
+115.487 -1.323 m
+115.318 -1.323 115.167 -1.3 115.032 -1.263 c
+114.903 -1.215 114.789 -1.146 114.693 -1.058 c
+114.606 -0.97 114.535 -0.863 114.487 -0.735 c
+114.436 -0.598 114.414 -0.448 114.414 -0.278 c
+114.414 -0.073 114.448 0.096 114.517 0.235 c
+114.583 0.383 114.679 0.493 114.797 0.574 c
+114.921 0.662 115.065 0.724 115.223 0.765 c
+115.388 0.802 115.564 0.827 115.751 0.838 c
+116.472 0.853 l
+116.472 1.029 l
+116.472 1.147 116.461 1.25 116.443 1.338 c
+116.42 1.426 116.387 1.492 116.339 1.544 c
+116.299 1.603 116.252 1.64 116.193 1.661 c
+116.133 1.68 116.067 1.691 116.002 1.691 c
+115.932 1.691 115.869 1.68 115.811 1.661 c
+115.759 1.65 115.711 1.625 115.663 1.588 c
+115.623 1.559 115.59 1.507 115.56 1.441 c
+115.539 1.382 115.524 1.301 115.516 1.206 c
+114.575 1.25 l
+114.606 1.397 114.649 1.532 114.708 1.661 c
+114.774 1.786 114.87 1.897 114.988 1.985 c
+115.105 2.08 115.244 2.154 115.414 2.205 c
+115.59 2.253 115.796 2.278 116.031 2.278 c
+116.472 2.278 116.802 2.168 117.031 1.956 c
+117.266 1.75 117.384 1.441 117.384 1.029 c
+117.384 -0.235 l
+117.384 -0.455 l
+117.39 -0.514 117.405 -0.569 117.428 -0.617 c
+117.446 -0.658 117.475 -0.69 117.515 -0.72 c
+117.552 -0.742 117.604 -0.749 117.663 -0.749 c
+117.729 -0.749 117.798 -0.745 117.868 -0.735 c
+117.868 -1.219 l
+117.81 -1.23 117.754 -1.242 117.706 -1.249 c
+117.666 -1.26 117.625 -1.267 117.589 -1.278 c
+117.548 -1.286 117.505 -1.294 117.457 -1.294 c
+117.405 -1.3 117.347 -1.308 117.28 -1.308 c
+117.052 -1.308 116.887 -1.256 116.781 -1.146 c
+116.67 -1.028 116.607 -0.863 116.59 -0.646 c
+116.575 -0.646 l
+116.505 -0.756 116.435 -0.852 116.369 -0.941 c
+116.299 -1.021 116.222 -1.087 116.133 -1.146 c
+116.046 -1.205 115.946 -1.249 115.84 -1.278 c
+115.741 -1.308 115.623 -1.323 115.487 -1.323 c
+116.472 0.353 m
+116.046 0.339 l
+115.946 0.339 115.855 0.331 115.766 0.324 c
+115.686 0.313 115.62 0.287 115.56 0.25 c
+115.502 0.21 115.45 0.151 115.414 0.074 c
+115.373 0.004 115.354 -0.087 115.354 -0.205 c
+115.354 -0.374 115.388 -0.496 115.458 -0.573 c
+115.524 -0.654 115.623 -0.69 115.751 -0.69 c
+115.859 -0.69 115.957 -0.668 116.046 -0.617 c
+116.141 -0.569 116.222 -0.507 116.281 -0.426 c
+116.347 -0.349 116.399 -0.261 116.428 -0.161 c
+116.457 -0.055 116.472 0.059 116.472 0.177 c
+h
+120.694 -0.646 m
+121.826 -0.646 l
+121.826 -1.263 l
+118.519 -1.263 l
+118.519 -0.646 l
+119.782 -0.646 l
+119.782 1.603 l
+118.857 1.603 l
+118.857 2.22 l
+120.694 2.22 l
+h
+119.782 3.514 0.912 -0.676 re
+119.782 2.837 m
+124.755 -0.646 m
+125.887 -0.646 l
+125.887 -1.263 l
+122.579 -1.263 l
+122.579 -0.646 l
+123.844 -0.646 l
+123.844 2.897 l
+122.917 2.897 l
+122.917 3.514 l
+124.755 3.514 l
+h
+133.346 1.455 m
+132.715 1.455 l
+132.582 3.514 l
+133.479 3.514 l
+h
+131.877 1.455 m
+131.244 1.455 l
+131.127 3.514 l
+131.994 3.514 l
+h
+136.764 -1.44 m
+136.683 -1.646 136.602 -1.822 136.514 -1.969 c
+136.434 -2.123 136.341 -2.248 136.235 -2.337 c
+136.124 -2.432 136.007 -2.506 135.882 -2.557 c
+135.753 -2.605 135.603 -2.63 135.426 -2.63 c
+135.327 -2.63 135.224 -2.624 135.117 -2.616 c
+135.019 -2.616 134.926 -2.605 134.838 -2.587 c
+134.838 -1.94 l
+134.857 -1.947 134.882 -1.955 134.911 -1.955 c
+135 -1.955 l
+135.037 -1.961 135.067 -1.969 135.088 -1.969 c
+135.177 -1.969 l
+135.264 -1.969 135.341 -1.959 135.412 -1.94 c
+135.478 -1.918 135.537 -1.884 135.588 -1.837 c
+135.647 -1.797 135.698 -1.738 135.75 -1.66 c
+135.798 -1.591 135.842 -1.499 135.882 -1.381 c
+135.941 -1.234 l
+134.5 2.22 l
+135.456 2.22 l
+136.073 0.515 l
+136.081 0.493 136.091 0.456 136.102 0.397 c
+136.121 0.346 136.139 0.283 136.162 0.206 c
+136.191 0.136 136.212 0.063 136.235 -0.014 c
+136.264 -0.095 136.286 -0.172 136.308 -0.249 c
+136.326 -0.319 136.341 -0.382 136.353 -0.44 c
+136.371 -0.492 136.386 -0.529 136.397 -0.558 c
+136.397 -0.529 136.4 -0.492 136.411 -0.44 c
+136.43 -0.382 136.448 -0.319 136.47 -0.249 c
+136.488 -0.183 136.507 -0.11 136.529 -0.029 c
+136.558 0.048 136.577 0.121 136.588 0.192 c
+136.606 0.258 136.625 0.324 136.646 0.383 c
+136.665 0.441 136.679 0.485 136.69 0.515 c
+137.263 2.22 l
+138.204 2.22 l
+h
+142.103 0.485 m
+142.103 0.21 142.067 -0.039 142.001 -0.264 c
+141.93 -0.481 141.828 -0.668 141.691 -0.823 c
+141.552 -0.98 141.376 -1.102 141.163 -1.19 c
+140.946 -1.278 140.692 -1.323 140.398 -1.323 c
+140.122 -1.323 139.877 -1.278 139.663 -1.19 c
+139.457 -1.102 139.285 -0.98 139.149 -0.823 c
+139.009 -0.668 138.907 -0.481 138.84 -0.264 c
+138.77 -0.039 138.737 0.21 138.737 0.485 c
+138.737 0.739 138.767 0.975 138.826 1.191 c
+138.892 1.415 138.994 1.607 139.134 1.764 c
+139.27 1.929 139.447 2.058 139.663 2.147 c
+139.877 2.234 140.133 2.278 140.428 2.278 c
+140.74 2.278 141.001 2.234 141.207 2.147 c
+141.419 2.058 141.593 1.929 141.721 1.764 c
+141.857 1.607 141.957 1.415 142.015 1.191 c
+142.074 0.975 142.103 0.739 142.103 0.485 c
+141.148 0.485 m
+141.148 0.691 141.133 0.867 141.103 1.015 c
+141.082 1.162 141.045 1.283 140.986 1.382 c
+140.927 1.478 140.854 1.548 140.766 1.588 c
+140.677 1.636 140.567 1.661 140.442 1.661 c
+140.178 1.661 139.987 1.563 139.869 1.368 c
+139.752 1.18 139.692 0.886 139.692 0.485 c
+139.692 0.063 139.752 -0.242 139.869 -0.426 c
+139.987 -0.613 140.163 -0.706 140.398 -0.706 c
+140.523 -0.706 140.637 -0.687 140.736 -0.646 c
+140.831 -0.598 140.912 -0.525 140.972 -0.426 c
+141.038 -0.33 141.082 -0.205 141.103 -0.058 c
+141.133 0.088 141.148 0.269 141.148 0.485 c
+143.842 2.22 m
+143.842 0.265 l
+143.842 0.125 143.848 0 143.871 -0.118 c
+143.889 -0.228 143.923 -0.319 143.974 -0.396 c
+144.022 -0.477 144.081 -0.54 144.15 -0.588 c
+144.216 -0.627 144.301 -0.646 144.4 -0.646 c
+144.488 -0.646 144.569 -0.627 144.65 -0.588 c
+144.738 -0.54 144.812 -0.47 144.87 -0.382 c
+144.929 -0.286 144.974 -0.176 145.003 -0.058 c
+145.039 0.067 145.061 0.206 145.061 0.353 c
+145.061 2.22 l
+145.959 2.22 l
+145.959 -0.484 l
+145.959 -0.72 l
+145.965 -0.801 145.973 -0.878 145.973 -0.955 c
+145.973 -1.146 l
+145.98 -1.198 145.988 -1.234 145.988 -1.263 c
+145.135 -1.263 l
+145.124 -1.234 145.113 -1.198 145.105 -1.146 c
+145.105 -0.955 l
+145.105 -0.889 145.099 -0.819 145.091 -0.749 c
+145.091 -0.573 l
+145.076 -0.573 l
+144.959 -0.837 144.804 -1.028 144.621 -1.146 c
+144.444 -1.263 144.242 -1.323 144.018 -1.323 c
+143.812 -1.323 143.64 -1.286 143.503 -1.219 c
+143.364 -1.153 143.254 -1.058 143.165 -0.941 c
+143.085 -0.823 143.025 -0.687 142.989 -0.529 c
+142.959 -0.363 142.944 -0.187 142.944 0 c
+142.944 2.22 l
+h
+150.387 1.162 m
+150.387 0.857 150.36 0.574 150.313 0.31 c
+150.273 0.052 150.21 -0.168 150.121 -0.353 c
+150.04 -0.529 149.938 -0.672 149.813 -0.779 c
+149.695 -0.878 149.556 -0.926 149.402 -0.926 c
+149.342 -0.926 149.284 -0.922 149.225 -0.911 c
+149.166 -0.893 149.115 -0.863 149.078 -0.823 c
+149.038 -0.786 149.005 -0.735 148.975 -0.675 c
+148.953 -0.61 148.945 -0.525 148.945 -0.426 c
+148.945 -0.396 l
+148.945 -0.353 l
+148.945 -0.309 l
+148.953 -0.29 148.96 -0.275 148.96 -0.264 c
+148.931 -0.264 l
+148.902 -0.353 148.862 -0.436 148.814 -0.514 c
+148.762 -0.595 148.704 -0.668 148.637 -0.735 c
+148.578 -0.793 148.509 -0.845 148.432 -0.881 c
+148.351 -0.911 148.27 -0.926 148.181 -0.926 c
+148.041 -0.926 147.924 -0.893 147.829 -0.823 c
+147.74 -0.756 147.667 -0.668 147.609 -0.558 c
+147.557 -0.44 147.52 -0.309 147.491 -0.161 c
+147.468 -0.007 147.461 0.151 147.461 0.31 c
+147.461 0.474 147.468 0.636 147.491 0.794 c
+147.52 0.948 147.553 1.103 147.594 1.25 c
+147.642 1.397 147.7 1.532 147.769 1.661 c
+147.836 1.786 147.917 1.897 148.005 1.985 c
+148.093 2.073 148.189 2.139 148.299 2.191 c
+148.405 2.249 148.519 2.278 148.637 2.278 c
+148.714 2.278 148.785 2.264 148.843 2.234 c
+148.902 2.205 148.949 2.165 148.99 2.117 c
+149.038 2.066 149.07 2.007 149.093 1.941 c
+149.122 1.871 149.144 1.798 149.166 1.721 c
+149.181 1.721 l
+149.284 2.205 l
+149.725 2.205 l
+149.402 0.574 l
+149.379 0.485 149.361 0.397 149.342 0.31 c
+149.332 0.221 149.321 0.136 149.313 0.059 c
+149.302 -0.022 149.292 -0.095 149.284 -0.161 c
+149.273 -0.22 149.269 -0.275 149.269 -0.323 c
+149.269 -0.374 149.273 -0.411 149.284 -0.44 c
+149.292 -0.47 149.302 -0.496 149.313 -0.514 c
+149.332 -0.525 149.35 -0.536 149.372 -0.544 c
+149.431 -0.544 l
+149.508 -0.544 149.581 -0.507 149.651 -0.426 c
+149.718 -0.338 149.772 -0.22 149.813 -0.073 c
+149.861 0.074 149.894 0.25 149.916 0.456 c
+149.945 0.669 149.96 0.904 149.96 1.162 c
+149.96 1.426 149.93 1.676 149.872 1.912 c
+149.82 2.154 149.743 2.367 149.637 2.544 c
+149.537 2.72 149.409 2.856 149.255 2.955 c
+149.097 3.051 148.92 3.102 148.725 3.102 c
+148.549 3.102 148.388 3.065 148.24 2.999 c
+148.101 2.94 147.975 2.852 147.858 2.735 c
+147.74 2.617 147.638 2.473 147.549 2.309 c
+147.461 2.139 147.388 1.956 147.329 1.75 c
+147.27 1.551 147.218 1.338 147.181 1.103 c
+147.152 0.875 147.138 0.636 147.138 0.383 c
+147.138 0.067 147.167 -0.22 147.226 -0.484 c
+147.293 -0.749 147.388 -0.98 147.505 -1.176 c
+147.623 -1.359 147.763 -1.502 147.931 -1.602 c
+148.097 -1.708 148.288 -1.764 148.505 -1.764 c
+148.629 -1.764 148.747 -1.749 148.858 -1.72 c
+148.964 -1.69 149.067 -1.649 149.166 -1.602 c
+149.261 -1.562 149.357 -1.514 149.446 -1.454 c
+149.533 -1.396 149.614 -1.326 149.695 -1.249 c
+149.916 -1.572 l
+149.828 -1.649 149.728 -1.723 149.622 -1.793 c
+149.523 -1.87 149.409 -1.932 149.284 -1.984 c
+149.166 -2.042 149.038 -2.087 148.902 -2.117 c
+148.773 -2.153 148.629 -2.175 148.475 -2.175 c
+148.199 -2.175 147.954 -2.109 147.74 -1.984 c
+147.524 -1.866 147.336 -1.693 147.181 -1.469 c
+147.023 -1.256 146.906 -0.992 146.829 -0.675 c
+146.748 -0.353 146.711 0 146.711 0.383 c
+146.711 0.831 146.755 1.25 146.844 1.632 c
+146.932 2.014 147.057 2.342 147.226 2.617 c
+147.403 2.9 147.611 3.12 147.858 3.279 c
+148.112 3.433 148.402 3.514 148.725 3.514 c
+149.008 3.514 149.255 3.448 149.46 3.323 c
+149.666 3.194 149.835 3.021 149.975 2.808 c
+150.111 2.591 150.214 2.342 150.283 2.058 c
+150.35 1.771 150.387 1.474 150.387 1.162 c
+148.99 1.264 m
+148.99 1.478 148.96 1.636 148.902 1.735 c
+148.843 1.831 148.754 1.881 148.637 1.881 c
+148.527 1.881 148.432 1.831 148.343 1.735 c
+148.262 1.636 148.197 1.515 148.137 1.368 c
+148.079 1.22 148.035 1.052 148.005 0.867 c
+147.975 0.68 147.961 0.493 147.961 0.31 c
+147.961 0 l
+147.968 -0.099 147.983 -0.187 148.005 -0.264 c
+148.035 -0.345 148.068 -0.407 148.108 -0.455 c
+148.145 -0.507 148.197 -0.529 148.255 -0.529 c
+148.332 -0.529 148.405 -0.507 148.475 -0.455 c
+148.542 -0.396 148.608 -0.319 148.667 -0.22 c
+148.725 -0.114 148.773 0.015 148.814 0.162 c
+148.862 0.31 148.895 0.47 148.916 0.647 c
+148.924 0.684 148.935 0.736 148.945 0.794 c
+148.953 0.853 148.96 0.912 148.96 0.971 c
+148.968 1.029 148.975 1.081 148.975 1.133 c
+148.982 1.18 148.99 1.224 148.99 1.264 c
+152.639 -1.323 m
+152.382 -1.323 152.154 -1.286 151.948 -1.219 c
+151.742 -1.142 151.566 -1.028 151.419 -0.881 c
+151.272 -0.727 151.154 -0.536 151.066 -0.309 c
+150.985 -0.084 150.948 0.181 150.948 0.485 c
+150.948 0.817 150.992 1.096 151.081 1.324 c
+151.176 1.559 151.305 1.742 151.463 1.881 c
+151.628 2.018 151.816 2.117 152.022 2.176 c
+152.228 2.242 152.436 2.278 152.654 2.278 c
+152.926 2.278 153.161 2.228 153.359 2.132 c
+153.565 2.043 153.73 1.912 153.859 1.735 c
+153.995 1.566 154.094 1.36 154.153 1.118 c
+154.219 0.882 154.256 0.618 154.256 0.324 c
+154.256 0.31 l
+151.889 0.31 l
+151.889 0.162 151.904 0.023 151.933 -0.103 c
+151.97 -0.231 152.025 -0.345 152.095 -0.44 c
+152.161 -0.529 152.245 -0.598 152.345 -0.646 c
+152.44 -0.698 152.554 -0.72 152.683 -0.72 c
+152.837 -0.72 152.977 -0.687 153.095 -0.617 c
+153.219 -0.55 153.308 -0.448 153.359 -0.309 c
+154.197 -0.382 l
+154.167 -0.481 154.113 -0.588 154.036 -0.706 c
+153.955 -0.816 153.851 -0.918 153.726 -1.014 c
+153.609 -1.102 153.454 -1.176 153.271 -1.234 c
+153.095 -1.294 152.881 -1.323 152.639 -1.323 c
+152.639 1.706 m
+152.55 1.706 152.463 1.691 152.374 1.661 c
+152.286 1.632 152.205 1.58 152.139 1.515 c
+152.07 1.445 152.01 1.357 151.962 1.25 c
+151.922 1.139 151.904 1.015 151.904 0.867 c
+153.373 0.867 l
+153.373 1.004 153.348 1.125 153.3 1.235 c
+153.26 1.341 153.205 1.43 153.138 1.5 c
+153.08 1.566 153.007 1.617 152.918 1.646 c
+152.83 1.684 152.735 1.706 152.639 1.706 c
+157.497 -1.263 m
+156.659 0 l
+155.806 -1.263 l
+154.851 -1.263 l
+156.159 0.53 l
+154.91 2.22 l
+155.88 2.22 l
+156.659 1.073 l
+157.423 2.22 l
+158.408 2.22 l
+157.159 0.545 l
+158.482 -1.263 l
+h
+160.161 -1.323 m
+159.992 -1.323 159.841 -1.3 159.706 -1.263 c
+159.577 -1.215 159.463 -1.146 159.368 -1.058 c
+159.279 -0.97 159.21 -0.863 159.162 -0.735 c
+159.11 -0.598 159.088 -0.448 159.088 -0.278 c
+159.088 -0.073 159.121 0.096 159.191 0.235 c
+159.257 0.383 159.353 0.493 159.47 0.574 c
+159.595 0.662 159.738 0.724 159.897 0.765 c
+160.062 0.802 160.238 0.827 160.426 0.838 c
+161.146 0.853 l
+161.146 1.029 l
+161.146 1.147 161.135 1.25 161.117 1.338 c
+161.094 1.426 161.061 1.492 161.014 1.544 c
+160.974 1.603 160.926 1.64 160.866 1.661 c
+160.808 1.68 160.741 1.691 160.675 1.691 c
+160.606 1.691 160.544 1.68 160.484 1.661 c
+160.433 1.65 160.386 1.625 160.338 1.588 c
+160.297 1.559 160.264 1.507 160.234 1.441 c
+160.213 1.382 160.198 1.301 160.191 1.206 c
+159.25 1.25 l
+159.279 1.397 159.324 1.532 159.382 1.661 c
+159.448 1.786 159.544 1.897 159.661 1.985 c
+159.779 2.08 159.918 2.154 160.087 2.205 c
+160.264 2.253 160.469 2.278 160.705 2.278 c
+161.146 2.278 161.477 2.168 161.705 1.956 c
+161.94 1.75 162.057 1.441 162.057 1.029 c
+162.057 -0.235 l
+162.057 -0.455 l
+162.065 -0.514 162.079 -0.569 162.102 -0.617 c
+162.119 -0.658 162.15 -0.69 162.19 -0.72 c
+162.227 -0.742 162.278 -0.749 162.337 -0.749 c
+162.403 -0.749 162.472 -0.745 162.543 -0.735 c
+162.543 -1.219 l
+162.484 -1.23 162.428 -1.242 162.381 -1.249 c
+162.341 -1.26 162.3 -1.267 162.263 -1.278 c
+162.223 -1.286 162.179 -1.294 162.131 -1.294 c
+162.079 -1.3 162.021 -1.308 161.955 -1.308 c
+161.726 -1.308 161.562 -1.256 161.454 -1.146 c
+161.344 -1.028 161.282 -0.863 161.263 -0.646 c
+161.249 -0.646 l
+161.179 -0.756 161.109 -0.852 161.043 -0.941 c
+160.974 -1.021 160.897 -1.087 160.808 -1.146 c
+160.72 -1.205 160.621 -1.249 160.514 -1.278 c
+160.415 -1.308 160.297 -1.323 160.161 -1.323 c
+161.146 0.353 m
+160.72 0.339 l
+160.621 0.339 160.529 0.331 160.44 0.324 c
+160.359 0.313 160.294 0.287 160.234 0.25 c
+160.176 0.21 160.124 0.151 160.087 0.074 c
+160.047 0.004 160.029 -0.087 160.029 -0.205 c
+160.029 -0.374 160.062 -0.496 160.132 -0.573 c
+160.198 -0.654 160.297 -0.69 160.426 -0.69 c
+160.532 -0.69 160.631 -0.668 160.72 -0.617 c
+160.816 -0.569 160.897 -0.507 160.955 -0.426 c
+161.021 -0.349 161.072 -0.261 161.102 -0.161 c
+161.132 -0.055 161.146 0.059 161.146 0.177 c
+h
+164.427 -1.263 m
+164.427 0.853 l
+164.427 1.019 164.421 1.154 164.413 1.264 c
+164.402 1.372 164.384 1.455 164.354 1.515 c
+164.332 1.58 164.303 1.632 164.266 1.661 c
+164.236 1.691 164.196 1.706 164.149 1.706 c
+164.089 1.706 164.034 1.676 163.987 1.617 c
+163.946 1.566 163.913 1.492 163.883 1.397 c
+163.854 1.309 163.829 1.195 163.81 1.058 c
+163.799 0.919 163.796 0.769 163.796 0.603 c
+163.796 -1.263 l
+163.046 -1.263 l
+163.046 1.47 l
+163.046 1.706 l
+163.046 1.926 l
+163.046 2.003 163.039 2.066 163.031 2.117 c
+163.031 2.22 l
+163.707 2.22 l
+163.707 2.132 l
+163.707 1.985 l
+163.715 1.926 163.722 1.867 163.722 1.808 c
+163.722 1.646 l
+163.737 1.646 l
+163.755 1.735 163.785 1.812 163.825 1.881 c
+163.862 1.96 163.906 2.029 163.957 2.087 c
+164.016 2.147 164.082 2.191 164.163 2.22 c
+164.24 2.257 164.328 2.278 164.427 2.278 c
+164.612 2.278 164.751 2.224 164.839 2.117 c
+164.935 2.018 165.005 1.86 165.045 1.646 c
+165.059 1.646 l
+165.096 1.742 165.136 1.831 165.177 1.912 c
+165.225 1.989 165.28 2.051 165.339 2.103 c
+165.398 2.161 165.464 2.205 165.545 2.234 c
+165.622 2.264 165.71 2.278 165.809 2.278 c
+165.945 2.278 166.059 2.253 166.148 2.205 c
+166.235 2.154 166.302 2.08 166.353 1.985 c
+166.412 1.885 166.449 1.757 166.47 1.603 c
+166.501 1.455 166.515 1.272 166.515 1.058 c
+166.515 -1.263 l
+165.795 -1.263 l
+165.795 0.853 l
+165.795 1.019 165.787 1.154 165.78 1.264 c
+165.769 1.372 165.751 1.455 165.721 1.515 c
+165.699 1.58 165.67 1.632 165.633 1.661 c
+165.603 1.691 165.563 1.706 165.516 1.706 c
+165.398 1.706 165.302 1.617 165.236 1.441 c
+165.177 1.272 165.148 1.015 165.148 0.662 c
+165.148 -1.263 l
+h
+168.194 2.22 m
+168.201 2.198 168.209 2.165 168.209 2.117 c
+168.216 2.077 168.224 2.029 168.224 1.97 c
+168.231 1.919 168.238 1.867 168.238 1.808 c
+168.238 1.646 l
+168.253 1.646 l
+168.311 1.764 168.378 1.86 168.459 1.941 c
+168.536 2.018 168.62 2.08 168.708 2.132 c
+168.797 2.191 168.885 2.228 168.973 2.249 c
+169.069 2.268 169.168 2.278 169.267 2.278 c
+169.473 2.278 169.653 2.234 169.811 2.147 c
+169.965 2.058 170.094 1.929 170.193 1.764 c
+170.3 1.607 170.377 1.415 170.428 1.191 c
+170.487 0.975 170.517 0.739 170.517 0.485 c
+170.517 0.221 170.487 -0.025 170.428 -0.249 c
+170.377 -0.467 170.3 -0.658 170.193 -0.823 c
+170.094 -0.98 169.962 -1.102 169.796 -1.19 c
+169.639 -1.278 169.451 -1.323 169.238 -1.323 c
+169.138 -1.323 169.04 -1.311 168.944 -1.294 c
+168.845 -1.271 168.753 -1.242 168.664 -1.19 c
+168.583 -1.142 168.506 -1.08 168.429 -0.999 c
+168.359 -0.922 168.301 -0.83 168.253 -0.72 c
+168.238 -0.72 l
+168.238 -0.808 l
+168.246 -0.849 168.253 -0.897 168.253 -0.955 c
+168.253 -1.117 l
+168.253 -1.294 l
+168.253 -2.63 l
+167.342 -2.63 l
+167.342 1.455 l
+167.342 1.621 167.334 1.768 167.326 1.897 c
+167.326 2.22 l
+h
+168.238 0.456 m
+168.238 0.229 168.257 0.038 168.297 -0.118 c
+168.344 -0.264 168.4 -0.382 168.459 -0.47 c
+168.525 -0.558 168.598 -0.625 168.679 -0.661 c
+168.756 -0.702 168.834 -0.72 168.914 -0.72 c
+169.01 -0.72 169.098 -0.698 169.179 -0.646 c
+169.267 -0.598 169.333 -0.529 169.385 -0.44 c
+169.443 -0.345 169.487 -0.22 169.517 -0.073 c
+169.554 0.081 169.576 0.269 169.576 0.485 c
+169.576 0.875 169.517 1.169 169.4 1.368 c
+169.289 1.563 169.135 1.661 168.93 1.661 c
+168.849 1.661 168.771 1.64 168.694 1.603 c
+168.613 1.563 168.54 1.5 168.473 1.411 c
+168.404 1.324 168.344 1.199 168.297 1.044 c
+168.257 0.886 168.238 0.691 168.238 0.456 c
+173.489 -0.646 m
+174.621 -0.646 l
+174.621 -1.263 l
+171.314 -1.263 l
+171.314 -0.646 l
+172.578 -0.646 l
+172.578 2.897 l
+171.652 2.897 l
+171.652 3.514 l
+173.489 3.514 l
+h
+177.01 -1.323 m
+176.753 -1.323 176.525 -1.286 176.319 -1.219 c
+176.113 -1.142 175.937 -1.028 175.79 -0.881 c
+175.643 -0.727 175.525 -0.536 175.438 -0.309 c
+175.357 -0.084 175.32 0.181 175.32 0.485 c
+175.32 0.817 175.363 1.096 175.452 1.324 c
+175.548 1.559 175.676 1.742 175.834 1.881 c
+175.999 2.018 176.186 2.117 176.392 2.176 c
+176.598 2.242 176.808 2.278 177.025 2.278 c
+177.296 2.278 177.532 2.228 177.73 2.132 c
+177.936 2.043 178.102 1.912 178.23 1.735 c
+178.366 1.566 178.465 1.36 178.524 1.118 c
+178.59 0.882 178.627 0.618 178.627 0.324 c
+178.627 0.31 l
+176.261 0.31 l
+176.261 0.162 176.275 0.023 176.304 -0.103 c
+176.341 -0.231 176.396 -0.345 176.466 -0.44 c
+176.533 -0.529 176.616 -0.598 176.716 -0.646 c
+176.811 -0.698 176.926 -0.72 177.054 -0.72 c
+177.208 -0.72 177.348 -0.687 177.466 -0.617 c
+177.591 -0.55 177.678 -0.448 177.73 -0.309 c
+178.568 -0.382 l
+178.538 -0.481 178.484 -0.588 178.407 -0.706 c
+178.326 -0.816 178.222 -0.918 178.098 -1.014 c
+177.98 -1.102 177.826 -1.176 177.642 -1.234 c
+177.466 -1.294 177.252 -1.323 177.01 -1.323 c
+177.01 1.706 m
+176.922 1.706 176.834 1.691 176.745 1.661 c
+176.657 1.632 176.576 1.58 176.51 1.515 c
+176.44 1.445 176.381 1.357 176.334 1.25 c
+176.294 1.139 176.275 1.015 176.275 0.867 c
+177.745 0.867 l
+177.745 1.004 177.719 1.125 177.672 1.235 c
+177.631 1.341 177.576 1.43 177.51 1.5 c
+177.451 1.566 177.377 1.617 177.289 1.646 c
+177.201 1.684 177.105 1.706 177.01 1.706 c
+180.571 -0.278 0.926 -0.985 re
+180.571 -1.263 m
+185.131 -1.323 m
+184.845 -1.323 184.602 -1.282 184.396 -1.205 c
+184.19 -1.117 184.018 -0.995 183.882 -0.837 c
+183.742 -0.683 183.639 -0.496 183.573 -0.278 c
+183.503 -0.055 183.471 0.192 183.471 0.456 c
+183.471 0.75 183.503 1.008 183.573 1.235 c
+183.65 1.459 183.757 1.646 183.897 1.794 c
+184.043 1.948 184.22 2.066 184.425 2.147 c
+184.631 2.234 184.867 2.278 185.131 2.278 c
+185.356 2.278 185.557 2.249 185.734 2.191 c
+185.91 2.132 186.061 2.047 186.189 1.941 c
+186.314 1.842 186.417 1.721 186.498 1.573 c
+186.575 1.434 186.63 1.283 186.66 1.118 c
+185.748 1.073 l
+185.719 1.25 185.649 1.389 185.543 1.5 c
+185.443 1.607 185.3 1.661 185.117 1.661 c
+184.87 1.661 184.693 1.559 184.587 1.353 c
+184.477 1.154 184.425 0.867 184.425 0.485 c
+184.425 -0.309 184.661 -0.706 185.131 -0.706 c
+185.296 -0.706 185.439 -0.654 185.557 -0.544 c
+185.675 -0.436 185.748 -0.275 185.778 -0.058 c
+186.689 -0.103 l
+186.66 -0.272 186.605 -0.426 186.528 -0.573 c
+186.457 -0.72 186.355 -0.852 186.218 -0.97 c
+186.09 -1.08 185.932 -1.168 185.748 -1.234 c
+185.572 -1.294 185.366 -1.323 185.131 -1.323 c
+190.838 0.485 m
+190.838 0.21 190.802 -0.039 190.735 -0.264 c
+190.665 -0.481 190.563 -0.668 190.426 -0.823 c
+190.287 -0.98 190.11 -1.102 189.898 -1.19 c
+189.68 -1.278 189.427 -1.323 189.133 -1.323 c
+188.857 -1.323 188.611 -1.278 188.398 -1.19 c
+188.192 -1.102 188.02 -0.98 187.884 -0.823 c
+187.744 -0.668 187.641 -0.481 187.575 -0.264 c
+187.505 -0.039 187.472 0.21 187.472 0.485 c
+187.472 0.739 187.502 0.975 187.56 1.191 c
+187.627 1.415 187.729 1.607 187.868 1.764 c
+188.005 1.929 188.181 2.058 188.398 2.147 c
+188.611 2.234 188.868 2.278 189.162 2.278 c
+189.474 2.278 189.736 2.234 189.942 2.147 c
+190.154 2.058 190.328 1.929 190.455 1.764 c
+190.592 1.607 190.691 1.415 190.75 1.191 c
+190.808 0.975 190.838 0.739 190.838 0.485 c
+189.883 0.485 m
+189.883 0.691 189.868 0.867 189.838 1.015 c
+189.817 1.162 189.78 1.283 189.721 1.382 c
+189.662 1.478 189.589 1.548 189.501 1.588 c
+189.412 1.636 189.302 1.661 189.177 1.661 c
+188.913 1.661 188.722 1.563 188.604 1.368 c
+188.487 1.18 188.427 0.886 188.427 0.485 c
+188.427 0.063 188.487 -0.242 188.604 -0.426 c
+188.722 -0.613 188.898 -0.706 189.133 -0.706 c
+189.258 -0.706 189.372 -0.687 189.471 -0.646 c
+189.567 -0.598 189.647 -0.525 189.707 -0.426 c
+189.773 -0.33 189.817 -0.205 189.838 -0.058 c
+189.868 0.088 189.883 0.269 189.883 0.485 c
+192.855 -1.263 m
+192.855 0.853 l
+192.855 1.019 192.848 1.154 192.841 1.264 c
+192.83 1.372 192.811 1.455 192.782 1.515 c
+192.76 1.58 192.73 1.632 192.694 1.661 c
+192.664 1.691 192.624 1.706 192.576 1.706 c
+192.518 1.706 192.462 1.676 192.414 1.617 c
+192.374 1.566 192.341 1.492 192.312 1.397 c
+192.282 1.309 192.256 1.195 192.238 1.058 c
+192.227 0.919 192.223 0.769 192.223 0.603 c
+192.223 -1.263 l
+191.473 -1.263 l
+191.473 1.47 l
+191.473 1.706 l
+191.473 1.926 l
+191.473 2.003 191.467 2.066 191.459 2.117 c
+191.459 2.22 l
+192.136 2.22 l
+192.136 2.132 l
+192.136 1.985 l
+192.142 1.926 192.15 1.867 192.15 1.808 c
+192.15 1.646 l
+192.165 1.646 l
+192.183 1.735 192.213 1.812 192.253 1.881 c
+192.29 1.96 192.333 2.029 192.385 2.087 c
+192.444 2.147 192.51 2.191 192.591 2.22 c
+192.668 2.257 192.757 2.278 192.855 2.278 c
+193.039 2.278 193.179 2.224 193.267 2.117 c
+193.362 2.018 193.432 1.86 193.472 1.646 c
+193.488 1.646 l
+193.524 1.742 193.565 1.831 193.605 1.912 c
+193.653 1.989 193.708 2.051 193.767 2.103 c
+193.825 2.161 193.892 2.205 193.973 2.234 c
+194.05 2.264 194.138 2.278 194.237 2.278 c
+194.373 2.278 194.488 2.253 194.575 2.205 c
+194.663 2.154 194.729 2.08 194.781 1.985 c
+194.84 1.885 194.877 1.757 194.899 1.603 c
+194.928 1.455 194.943 1.272 194.943 1.058 c
+194.943 -1.263 l
+194.222 -1.263 l
+194.222 0.853 l
+194.222 1.019 194.215 1.154 194.208 1.264 c
+194.197 1.372 194.178 1.455 194.149 1.515 c
+194.127 1.58 194.098 1.632 194.06 1.661 c
+194.031 1.691 193.991 1.706 193.943 1.706 c
+193.825 1.706 193.73 1.617 193.664 1.441 c
+193.605 1.272 193.576 1.015 193.576 0.662 c
+193.576 -1.263 l
+h
+198.331 1.455 m
+197.699 1.455 l
+197.567 3.514 l
+198.463 3.514 l
+h
+196.861 1.455 m
+196.229 1.455 l
+196.111 3.514 l
+196.979 3.514 l
+h
+f
+Q
+q 1 0 0 1 64.9298 361.4887 cm
+0 0 m
+0 0.264 -0.073 0.463 -0.22 0.603 c
+-0.36 0.75 -0.617 0.889 -0.999 1.029 c
+-1.374 1.165 -1.66 1.309 -1.866 1.455 c
+-2.065 1.602 -2.212 1.768 -2.308 1.955 c
+-2.406 2.15 -2.454 2.371 -2.454 2.616 c
+-2.454 3.036 -2.315 3.385 -2.028 3.66 c
+-1.745 3.932 -1.378 4.072 -0.926 4.072 c
+-0.613 4.072 -0.334 3.998 -0.088 3.851 c
+0.154 3.711 0.341 3.516 0.47 3.263 c
+0.607 3.017 0.676 2.749 0.676 2.454 c
+0 2.454 l
+0 2.786 -0.081 3.042 -0.235 3.219 c
+-0.393 3.403 -0.625 3.499 -0.926 3.499 c
+-1.19 3.499 -1.404 3.418 -1.558 3.263 c
+-1.705 3.117 -1.779 2.903 -1.779 2.631 c
+-1.779 2.404 -1.701 2.213 -1.544 2.058 c
+-1.378 1.911 -1.124 1.771 -0.779 1.646 c
+-0.261 1.477 0.11 1.268 0.338 1.014 c
+0.573 0.757 0.691 0.426 0.691 0.015 c
+0.691 -0.426 0.548 -0.779 0.264 -1.043 c
+-0.022 -1.301 -0.405 -1.426 -0.881 -1.426 c
+-1.198 -1.426 -1.484 -1.356 -1.749 -1.22 c
+-2.014 -1.084 -2.227 -0.893 -2.381 -0.646 c
+-2.528 -0.405 -2.601 -0.118 -2.601 0.206 c
+-1.926 0.206 l
+-1.926 -0.129 -1.833 -0.389 -1.646 -0.573 c
+-1.463 -0.76 -1.205 -0.852 -0.881 -0.852 c
+-0.588 -0.852 -0.368 -0.779 -0.22 -0.632 c
+-0.073 -0.478 0 -0.264 0 0 c
+2.896 -1.426 m
+2.396 -1.426 2.014 -1.278 1.749 -0.985 c
+1.484 -0.691 1.353 -0.257 1.353 0.324 c
+1.353 0.794 l
+1.353 1.389 1.477 1.856 1.735 2.19 c
+1.999 2.532 2.359 2.705 2.822 2.705 c
+3.281 2.705 3.624 2.55 3.851 2.249 c
+4.087 1.955 4.208 1.492 4.219 0.867 c
+4.219 0.441 l
+1.999 0.441 l
+1.999 0.353 l
+1.999 -0.081 2.076 -0.393 2.234 -0.588 c
+2.4 -0.775 2.631 -0.867 2.925 -0.867 c
+3.12 -0.867 3.293 -0.834 3.439 -0.764 c
+3.587 -0.687 3.723 -0.569 3.851 -0.411 c
+4.189 -0.823 l
+3.903 -1.228 3.473 -1.426 2.896 -1.426 c
+2.822 2.146 m
+2.547 2.146 2.344 2.051 2.219 1.866 c
+2.091 1.679 2.018 1.389 1.999 1 c
+3.572 1 l
+3.572 1.087 l
+3.55 1.47 3.484 1.738 3.366 1.897 c
+3.248 2.062 3.065 2.146 2.822 2.146 c
+5.85 3.587 m
+5.85 2.631 l
+6.453 2.631 l
+6.453 2.102 l
+5.85 2.102 l
+5.85 -0.368 l
+5.85 -0.525 5.872 -0.643 5.924 -0.721 c
+5.982 -0.801 6.071 -0.838 6.188 -0.838 c
+6.277 -0.838 6.365 -0.823 6.453 -0.794 c
+6.453 -1.352 l
+6.306 -1.4 6.151 -1.426 5.997 -1.426 c
+5.74 -1.426 5.546 -1.334 5.409 -1.147 c
+5.27 -0.962 5.203 -0.702 5.203 -0.368 c
+5.203 2.102 l
+4.601 2.102 l
+4.601 2.631 l
+5.203 2.631 l
+5.203 3.587 l
+h
+9.789 3.587 m
+9.789 2.631 l
+10.392 2.631 l
+10.392 2.102 l
+9.789 2.102 l
+9.789 -0.368 l
+9.789 -0.525 9.812 -0.643 9.864 -0.721 c
+9.922 -0.801 10.01 -0.838 10.128 -0.838 c
+10.215 -0.838 10.304 -0.823 10.392 -0.794 c
+10.392 -1.352 l
+10.246 -1.4 10.091 -1.426 9.937 -1.426 c
+9.679 -1.426 9.485 -1.334 9.349 -1.147 c
+9.209 -0.962 9.143 -0.702 9.143 -0.368 c
+9.143 2.102 l
+8.54 2.102 l
+8.54 2.631 l
+9.143 2.631 l
+9.143 3.587 l
+h
+11.803 2.219 m
+12.057 2.543 12.376 2.705 12.759 2.705 c
+13.465 2.705 13.821 2.234 13.832 1.294 c
+13.832 -1.352 l
+13.185 -1.352 l
+13.185 1.264 l
+13.185 1.577 13.13 1.797 13.024 1.926 c
+12.914 2.051 12.759 2.117 12.553 2.117 c
+12.395 2.117 12.248 2.062 12.112 1.955 c
+11.983 1.845 11.881 1.709 11.803 1.544 c
+11.803 -1.352 l
+11.156 -1.352 l
+11.156 4.293 l
+11.803 4.293 l
+h
+16.214 -1.426 m
+15.713 -1.426 15.331 -1.278 15.067 -0.985 c
+14.803 -0.691 14.67 -0.257 14.67 0.324 c
+14.67 0.794 l
+14.67 1.389 14.795 1.856 15.052 2.19 c
+15.316 2.532 15.676 2.705 16.139 2.705 c
+16.599 2.705 16.941 2.55 17.169 2.249 c
+17.404 1.955 17.525 1.492 17.536 0.867 c
+17.536 0.441 l
+15.316 0.441 l
+15.316 0.353 l
+15.316 -0.081 15.393 -0.393 15.551 -0.588 c
+15.717 -0.775 15.948 -0.867 16.243 -0.867 c
+16.438 -0.867 16.61 -0.834 16.757 -0.764 c
+16.904 -0.687 17.04 -0.569 17.169 -0.411 c
+17.506 -0.823 l
+17.22 -1.228 16.79 -1.426 16.214 -1.426 c
+16.139 2.146 m
+15.864 2.146 15.662 2.051 15.537 1.866 c
+15.408 1.679 15.335 1.389 15.316 1 c
+16.889 1 l
+16.889 1.087 l
+16.867 1.47 16.801 1.738 16.684 1.897 c
+16.565 2.062 16.382 2.146 16.139 2.146 c
+21.461 -1.426 m
+20.961 -1.426 20.579 -1.278 20.314 -0.985 c
+20.05 -0.691 19.917 -0.257 19.917 0.324 c
+19.917 0.794 l
+19.917 1.389 20.042 1.856 20.299 2.19 c
+20.564 2.532 20.924 2.705 21.388 2.705 c
+21.847 2.705 22.188 2.55 22.416 2.249 c
+22.651 1.955 22.772 1.492 22.784 0.867 c
+22.784 0.441 l
+20.564 0.441 l
+20.564 0.353 l
+20.564 -0.081 20.642 -0.393 20.799 -0.588 c
+20.964 -0.775 21.196 -0.867 21.49 -0.867 c
+21.685 -0.867 21.858 -0.834 22.005 -0.764 c
+22.152 -0.687 22.288 -0.569 22.416 -0.411 c
+22.755 -0.823 l
+22.468 -1.228 22.038 -1.426 21.461 -1.426 c
+21.388 2.146 m
+21.112 2.146 20.91 2.051 20.785 1.866 c
+20.656 1.679 20.582 1.389 20.564 1 c
+22.137 1 l
+22.137 1.087 l
+22.115 1.47 22.049 1.738 21.931 1.897 c
+21.814 2.062 21.629 2.146 21.388 2.146 c
+24.768 0.647 -1.514 0.558 re
+26.047 2.631 m
+26.061 2.263 l
+26.304 2.558 26.624 2.705 27.017 2.705 c
+27.458 2.705 27.767 2.506 27.943 2.117 c
+28.197 2.506 28.546 2.705 28.987 2.705 c
+29.722 2.705 30.096 2.242 30.119 1.323 c
+30.119 -1.352 l
+29.471 -1.352 l
+29.471 1.264 l
+29.471 1.558 29.417 1.771 29.31 1.911 c
+29.211 2.047 29.038 2.117 28.795 2.117 c
+28.598 2.117 28.436 2.036 28.311 1.881 c
+28.193 1.735 28.123 1.544 28.105 1.309 c
+28.105 -1.352 l
+27.443 -1.352 l
+27.443 1.294 l
+27.443 1.841 27.223 2.117 26.782 2.117 c
+26.447 2.117 26.212 1.955 26.076 1.631 c
+26.076 -1.352 l
+25.429 -1.352 l
+25.429 2.631 l
+h
+33.132 -1.352 m
+33.091 -1.264 33.066 -1.117 33.059 -0.912 c
+32.823 -1.257 32.529 -1.426 32.176 -1.426 c
+31.813 -1.426 31.53 -1.33 31.324 -1.132 c
+31.125 -0.926 31.03 -0.64 31.03 -0.264 c
+31.03 0.136 31.166 0.455 31.441 0.69 c
+31.713 0.933 32.088 1.058 32.558 1.058 c
+33.043 1.058 l
+33.043 1.484 l
+33.043 1.72 32.989 1.885 32.882 1.984 c
+32.772 2.091 32.61 2.146 32.397 2.146 c
+32.199 2.146 32.037 2.087 31.912 1.97 c
+31.794 1.852 31.736 1.706 31.736 1.529 c
+31.089 1.529 l
+31.089 1.723 31.147 1.914 31.265 2.102 c
+31.39 2.286 31.551 2.433 31.75 2.543 c
+31.956 2.65 32.184 2.705 32.441 2.705 c
+32.841 2.705 33.147 2.602 33.352 2.396 c
+33.566 2.19 33.679 1.897 33.691 1.514 c
+33.691 -0.5 l
+33.691 -0.804 33.727 -1.07 33.808 -1.294 c
+33.808 -1.352 l
+h
+32.265 -0.838 m
+32.43 -0.838 32.581 -0.794 32.72 -0.706 c
+32.868 -0.617 32.974 -0.507 33.043 -0.368 c
+33.043 0.573 l
+32.677 0.573 l
+32.36 0.573 32.118 0.503 31.941 0.368 c
+31.765 0.239 31.677 0.052 31.677 -0.191 c
+31.677 -0.419 31.721 -0.584 31.809 -0.691 c
+31.897 -0.79 32.048 -0.838 32.265 -0.838 c
+35.395 -1.352 -0.646 3.983 re
+35.44 3.674 m
+35.44 3.564 35.41 3.473 35.351 3.395 c
+35.293 3.326 35.197 3.293 35.072 3.293 c
+34.954 3.293 34.859 3.326 34.793 3.395 c
+34.734 3.473 34.705 3.564 34.705 3.674 c
+34.705 3.792 34.734 3.884 34.793 3.954 c
+34.859 4.031 34.954 4.072 35.072 4.072 c
+35.197 4.072 35.293 4.031 35.351 3.954 c
+35.41 3.873 35.44 3.782 35.44 3.674 c
+37.115 -1.352 -0.646 5.644 re
+41.892 -1.352 m
+41.852 -1.264 41.826 -1.117 41.819 -0.912 c
+41.583 -1.257 41.29 -1.426 40.937 -1.426 c
+40.573 -1.426 40.29 -1.33 40.084 -1.132 c
+39.886 -0.926 39.79 -0.64 39.79 -0.264 c
+39.79 0.136 39.927 0.455 40.202 0.69 c
+40.474 0.933 40.849 1.058 41.319 1.058 c
+41.805 1.058 l
+41.805 1.484 l
+41.805 1.72 41.749 1.885 41.643 1.984 c
+41.533 2.091 41.371 2.146 41.157 2.146 c
+40.959 2.146 40.797 2.087 40.673 1.97 c
+40.554 1.852 40.496 1.706 40.496 1.529 c
+39.849 1.529 l
+39.849 1.723 39.908 1.914 40.026 2.102 c
+40.151 2.286 40.313 2.433 40.511 2.543 c
+40.716 2.65 40.945 2.705 41.202 2.705 c
+41.602 2.705 41.907 2.602 42.113 2.396 c
+42.326 2.19 42.44 1.897 42.451 1.514 c
+42.451 -0.5 l
+42.451 -0.804 42.488 -1.07 42.568 -1.294 c
+42.568 -1.352 l
+h
+41.025 -0.838 m
+41.19 -0.838 41.341 -0.794 41.481 -0.706 c
+41.628 -0.617 41.734 -0.507 41.805 -0.368 c
+41.805 0.573 l
+41.437 0.573 l
+41.121 0.573 40.878 0.503 40.702 0.368 c
+40.525 0.239 40.438 0.052 40.438 -0.191 c
+40.438 -0.419 40.481 -0.584 40.569 -0.691 c
+40.658 -0.79 40.808 -0.838 41.025 -0.838 c
+43.318 0.823 m
+43.318 1.43 43.428 1.897 43.656 2.219 c
+43.891 2.543 44.219 2.705 44.641 2.705 c
+45.023 2.705 45.321 2.547 45.537 2.234 c
+45.537 4.293 l
+46.185 4.293 l
+46.185 -1.352 l
+45.597 -1.352 l
+45.552 -0.926 l
+45.346 -1.261 45.042 -1.426 44.641 -1.426 c
+44.23 -1.426 43.906 -1.271 43.671 -0.956 c
+43.436 -0.632 43.318 -0.176 43.318 0.412 c
+h
+43.965 0.441 m
+43.965 0 44.028 -0.33 44.156 -0.544 c
+44.292 -0.75 44.513 -0.852 44.818 -0.852 c
+45.141 -0.852 45.379 -0.691 45.537 -0.368 c
+45.537 1.646 l
+45.369 1.959 45.13 2.117 44.818 2.117 c
+44.513 2.117 44.292 2.014 44.156 1.808 c
+44.028 1.602 43.965 1.278 43.965 0.838 c
+h
+47.052 0.823 m
+47.052 1.43 47.162 1.897 47.39 2.219 c
+47.625 2.543 47.952 2.705 48.375 2.705 c
+48.757 2.705 49.055 2.547 49.271 2.234 c
+49.271 4.293 l
+49.918 4.293 l
+49.918 -1.352 l
+49.33 -1.352 l
+49.286 -0.926 l
+49.08 -1.261 48.775 -1.426 48.375 -1.426 c
+47.964 -1.426 47.64 -1.271 47.405 -0.956 c
+47.17 -0.632 47.052 -0.176 47.052 0.412 c
+h
+47.698 0.441 m
+47.698 0 47.761 -0.33 47.889 -0.544 c
+48.026 -0.75 48.246 -0.852 48.551 -0.852 c
+48.874 -0.852 49.113 -0.691 49.271 -0.368 c
+49.271 1.646 l
+49.102 1.959 48.864 2.117 48.551 2.117 c
+48.246 2.117 48.026 2.014 47.889 1.808 c
+47.761 1.602 47.698 1.278 47.698 0.838 c
+h
+52.564 2.014 m
+52.475 2.032 52.377 2.043 52.27 2.043 c
+51.935 2.043 51.7 1.86 51.565 1.5 c
+51.565 -1.352 l
+50.918 -1.352 l
+50.918 2.631 l
+51.55 2.631 l
+51.565 2.219 l
+51.741 2.543 51.983 2.705 52.299 2.705 c
+52.406 2.705 52.494 2.683 52.564 2.646 c
+h
+54.563 -1.426 m
+54.063 -1.426 53.681 -1.278 53.416 -0.985 c
+53.152 -0.691 53.019 -0.257 53.019 0.324 c
+53.019 0.794 l
+53.019 1.389 53.144 1.856 53.402 2.19 c
+53.666 2.532 54.027 2.705 54.49 2.705 c
+54.949 2.705 55.291 2.55 55.519 2.249 c
+55.754 1.955 55.875 1.492 55.886 0.867 c
+55.886 0.441 l
+53.666 0.441 l
+53.666 0.353 l
+53.666 -0.081 53.743 -0.393 53.902 -0.588 c
+54.067 -0.775 54.299 -0.867 54.592 -0.867 c
+54.787 -0.867 54.96 -0.834 55.107 -0.764 c
+55.254 -0.687 55.39 -0.569 55.519 -0.411 c
+55.856 -0.823 l
+55.569 -1.228 55.14 -1.426 54.563 -1.426 c
+54.49 2.146 m
+54.214 2.146 54.012 2.051 53.886 1.866 c
+53.759 1.679 53.685 1.389 53.666 1 c
+55.239 1 l
+55.239 1.087 l
+55.217 1.47 55.151 1.738 55.033 1.897 c
+54.916 2.062 54.732 2.146 54.49 2.146 c
+58.605 -0.338 m
+58.605 -0.191 58.55 -0.07 58.443 0.029 c
+58.333 0.125 58.127 0.243 57.826 0.382 c
+57.481 0.53 57.238 0.651 57.092 0.75 c
+56.944 0.856 56.834 0.974 56.768 1.103 c
+56.698 1.228 56.665 1.386 56.665 1.573 c
+56.665 1.897 56.782 2.165 57.017 2.381 c
+57.252 2.595 57.554 2.705 57.929 2.705 c
+58.312 2.705 58.62 2.591 58.855 2.367 c
+59.091 2.139 59.208 1.852 59.208 1.5 c
+58.561 1.5 l
+58.561 1.675 58.503 1.827 58.385 1.955 c
+58.268 2.08 58.113 2.146 57.929 2.146 c
+57.73 2.146 57.58 2.091 57.474 1.984 c
+57.363 1.885 57.312 1.753 57.312 1.588 c
+57.312 1.459 57.348 1.353 57.429 1.264 c
+57.506 1.183 57.697 1.081 58.002 0.956 c
+58.48 0.769 58.811 0.58 58.987 0.397 c
+59.164 0.22 59.252 -0.008 59.252 -0.279 c
+59.252 -0.632 59.127 -0.912 58.885 -1.117 c
+58.649 -1.323 58.333 -1.426 57.944 -1.426 c
+57.522 -1.426 57.183 -1.309 56.93 -1.073 c
+56.672 -0.831 56.547 -0.525 56.547 -0.162 c
+57.194 -0.162 l
+57.202 -0.389 57.271 -0.565 57.4 -0.691 c
+57.525 -0.808 57.709 -0.867 57.944 -0.867 c
+58.157 -0.867 58.318 -0.819 58.428 -0.721 c
+58.547 -0.625 58.605 -0.496 58.605 -0.338 c
+62.03 -0.338 m
+62.03 -0.191 61.975 -0.07 61.869 0.029 c
+61.759 0.125 61.553 0.243 61.251 0.382 c
+60.905 0.53 60.664 0.651 60.516 0.75 c
+60.369 0.856 60.259 0.974 60.193 1.103 c
+60.123 1.228 60.09 1.386 60.09 1.573 c
+60.09 1.897 60.207 2.165 60.443 2.381 c
+60.678 2.595 60.979 2.705 61.354 2.705 c
+61.736 2.705 62.045 2.591 62.28 2.367 c
+62.515 2.139 62.633 1.852 62.633 1.5 c
+61.986 1.5 l
+61.986 1.675 61.927 1.827 61.809 1.955 c
+61.692 2.08 61.538 2.146 61.354 2.146 c
+61.156 2.146 61.005 2.091 60.899 1.984 c
+60.788 1.885 60.737 1.753 60.737 1.588 c
+60.737 1.459 60.774 1.353 60.855 1.264 c
+60.932 1.183 61.123 1.081 61.427 0.956 c
+61.905 0.769 62.236 0.58 62.412 0.397 c
+62.588 0.22 62.677 -0.008 62.677 -0.279 c
+62.677 -0.632 62.552 -0.912 62.31 -1.117 c
+62.075 -1.323 61.759 -1.426 61.369 -1.426 c
+60.946 -1.426 60.608 -1.309 60.354 -1.073 c
+60.097 -0.831 59.972 -0.525 59.972 -0.162 c
+60.619 -0.162 l
+60.626 -0.389 60.697 -0.565 60.824 -0.691 c
+60.95 -0.808 61.134 -0.867 61.369 -0.867 c
+61.582 -0.867 61.744 -0.819 61.854 -0.721 c
+61.971 -0.625 62.03 -0.496 62.03 -0.338 c
+66.087 3.587 m
+66.087 2.631 l
+66.69 2.631 l
+66.69 2.102 l
+66.087 2.102 l
+66.087 -0.368 l
+66.087 -0.525 66.11 -0.643 66.16 -0.721 c
+66.22 -0.801 66.308 -0.838 66.425 -0.838 c
+66.513 -0.838 66.602 -0.823 66.69 -0.794 c
+66.69 -1.352 l
+66.543 -1.4 66.388 -1.426 66.234 -1.426 c
+65.977 -1.426 65.782 -1.334 65.646 -1.147 c
+65.507 -0.962 65.441 -0.702 65.441 -0.368 c
+65.441 2.102 l
+64.838 2.102 l
+64.838 2.631 l
+65.441 2.631 l
+65.441 3.587 l
+h
+68.101 2.219 m
+68.354 2.543 68.674 2.705 69.056 2.705 c
+69.761 2.705 70.118 2.234 70.129 1.294 c
+70.129 -1.352 l
+69.482 -1.352 l
+69.482 1.264 l
+69.482 1.577 69.428 1.797 69.321 1.926 c
+69.21 2.051 69.056 2.117 68.851 2.117 c
+68.693 2.117 68.545 2.062 68.41 1.955 c
+68.281 1.845 68.178 1.709 68.101 1.544 c
+68.101 -1.352 l
+67.454 -1.352 l
+67.454 4.293 l
+68.101 4.293 l
+h
+73.128 -1.352 m
+73.088 -1.264 73.062 -1.117 73.054 -0.912 c
+72.819 -1.257 72.525 -1.426 72.173 -1.426 c
+71.809 -1.426 71.525 -1.33 71.32 -1.132 c
+71.122 -0.926 71.026 -0.64 71.026 -0.264 c
+71.026 0.136 71.162 0.455 71.438 0.69 c
+71.71 0.933 72.084 1.058 72.555 1.058 c
+73.04 1.058 l
+73.04 1.484 l
+73.04 1.72 72.984 1.885 72.878 1.984 c
+72.768 2.091 72.606 2.146 72.393 2.146 c
+72.194 2.146 72.032 2.087 71.908 1.97 c
+71.791 1.852 71.731 1.706 71.731 1.529 c
+71.085 1.529 l
+71.085 1.723 71.143 1.914 71.261 2.102 c
+71.386 2.286 71.548 2.433 71.746 2.543 c
+71.952 2.65 72.18 2.705 72.437 2.705 c
+72.838 2.705 73.142 2.602 73.349 2.396 c
+73.561 2.19 73.676 1.897 73.686 1.514 c
+73.686 -0.5 l
+73.686 -0.804 73.723 -1.07 73.804 -1.294 c
+73.804 -1.352 l
+h
+72.261 -0.838 m
+72.426 -0.838 72.577 -0.794 72.716 -0.706 c
+72.863 -0.617 72.97 -0.507 73.04 -0.368 c
+73.04 0.573 l
+72.672 0.573 l
+72.356 0.573 72.113 0.503 71.937 0.368 c
+71.761 0.239 71.673 0.052 71.673 -0.191 c
+71.673 -0.419 71.717 -0.584 71.805 -0.691 c
+71.893 -0.79 72.044 -0.838 72.261 -0.838 c
+75.539 3.587 m
+75.539 2.631 l
+76.142 2.631 l
+76.142 2.102 l
+75.539 2.102 l
+75.539 -0.368 l
+75.539 -0.525 75.56 -0.643 75.612 -0.721 c
+75.671 -0.801 75.759 -0.838 75.876 -0.838 c
+75.965 -0.838 76.053 -0.823 76.142 -0.794 c
+76.142 -1.352 l
+75.994 -1.4 75.84 -1.426 75.685 -1.426 c
+75.428 -1.426 75.234 -1.334 75.097 -1.147 c
+74.958 -0.962 74.891 -0.702 74.891 -0.368 c
+74.891 2.102 l
+74.289 2.102 l
+74.289 2.631 l
+74.891 2.631 l
+74.891 3.587 l
+h
+81.595 -0.206 m
+82.197 2.631 l
+82.844 2.631 l
+81.859 -1.352 l
+81.345 -1.352 l
+80.566 1.5 l
+79.816 -1.352 l
+79.286 -1.352 l
+78.332 2.631 l
+78.964 2.631 l
+79.581 -0.133 l
+80.316 2.631 l
+80.83 2.631 l
+h
+84.225 -1.352 -0.646 3.983 re
+84.27 3.674 m
+84.27 3.564 84.24 3.473 84.182 3.395 c
+84.123 3.326 84.027 3.293 83.903 3.293 c
+83.785 3.293 83.689 3.326 83.623 3.395 c
+83.564 3.473 83.535 3.564 83.535 3.674 c
+83.535 3.792 83.564 3.884 83.623 3.954 c
+83.689 4.031 83.785 4.072 83.903 4.072 c
+84.027 4.072 84.123 4.031 84.182 3.954 c
+84.24 3.873 84.27 3.782 84.27 3.674 c
+85.945 -1.352 -0.646 5.644 re
+87.666 -1.352 -0.647 5.644 re
+93.28 0.441 m
+93.28 -0.176 93.166 -0.643 92.942 -0.956 c
+92.726 -1.271 92.402 -1.426 91.972 -1.426 c
+91.55 -1.426 91.238 -1.246 91.032 -0.881 c
+91.002 -1.352 l
+90.399 -1.352 l
+90.399 4.293 l
+91.046 4.293 l
+91.046 2.19 l
+91.259 2.532 91.568 2.705 91.972 2.705 c
+92.402 2.705 92.726 2.547 92.942 2.234 c
+93.166 1.929 93.28 1.463 93.28 0.838 c
+h
+92.634 0.823 m
+92.634 1.294 92.564 1.625 92.428 1.823 c
+92.299 2.018 92.09 2.117 91.795 2.117 c
+91.462 2.117 91.211 1.933 91.046 1.573 c
+91.046 -0.309 l
+91.211 -0.673 91.465 -0.852 91.811 -0.852 c
+92.104 -0.852 92.314 -0.75 92.443 -0.544 c
+92.568 -0.338 92.634 -0.022 92.634 0.412 c
+h
+95.544 -1.426 m
+95.044 -1.426 94.662 -1.278 94.398 -0.985 c
+94.133 -0.691 94.001 -0.257 94.001 0.324 c
+94.001 0.794 l
+94.001 1.389 94.126 1.856 94.383 2.19 c
+94.647 2.532 95.007 2.705 95.471 2.705 c
+95.93 2.705 96.271 2.55 96.499 2.249 c
+96.734 1.955 96.856 1.492 96.867 0.867 c
+96.867 0.441 l
+94.647 0.441 l
+94.647 0.353 l
+94.647 -0.081 94.725 -0.393 94.882 -0.588 c
+95.048 -0.775 95.279 -0.867 95.573 -0.867 c
+95.768 -0.867 95.941 -0.834 96.088 -0.764 c
+96.235 -0.687 96.371 -0.569 96.499 -0.411 c
+96.838 -0.823 l
+96.551 -1.228 96.121 -1.426 95.544 -1.426 c
+95.471 2.146 m
+95.195 2.146 94.993 2.051 94.868 1.866 c
+94.739 1.679 94.666 1.389 94.647 1 c
+96.22 1 l
+96.22 1.087 l
+96.198 1.47 96.132 1.738 96.015 1.897 c
+95.897 2.062 95.713 2.146 95.471 2.146 c
+101.409 -1.352 m
+101.368 -1.264 101.343 -1.117 101.335 -0.912 c
+101.1 -1.257 100.806 -1.426 100.453 -1.426 c
+100.09 -1.426 99.807 -1.33 99.601 -1.132 c
+99.402 -0.926 99.307 -0.64 99.307 -0.264 c
+99.307 0.136 99.443 0.455 99.718 0.69 c
+99.99 0.933 100.366 1.058 100.836 1.058 c
+101.32 1.058 l
+101.32 1.484 l
+101.32 1.72 101.266 1.885 101.159 1.984 c
+101.049 2.091 100.887 2.146 100.674 2.146 c
+100.476 2.146 100.314 2.087 100.189 1.97 c
+100.071 1.852 100.013 1.706 100.013 1.529 c
+99.366 1.529 l
+99.366 1.723 99.425 1.914 99.542 2.102 c
+99.667 2.286 99.828 2.433 100.027 2.543 c
+100.233 2.65 100.461 2.705 100.718 2.705 c
+101.118 2.705 101.424 2.602 101.629 2.396 c
+101.843 2.19 101.956 1.897 101.968 1.514 c
+101.968 -0.5 l
+101.968 -0.804 102.004 -1.07 102.085 -1.294 c
+102.085 -1.352 l
+h
+100.542 -0.838 m
+100.707 -0.838 100.858 -0.794 100.997 -0.706 c
+101.145 -0.617 101.251 -0.507 101.32 -0.368 c
+101.32 0.573 l
+100.954 0.573 l
+100.637 0.573 100.395 0.503 100.218 0.368 c
+100.042 0.239 99.954 0.052 99.954 -0.191 c
+99.954 -0.419 99.998 -0.584 100.086 -0.691 c
+100.175 -0.79 100.325 -0.838 100.542 -0.838 c
+103.819 3.587 m
+103.819 2.631 l
+104.422 2.631 l
+104.422 2.102 l
+103.819 2.102 l
+103.819 -0.368 l
+103.819 -0.525 103.842 -0.643 103.893 -0.721 c
+103.952 -0.801 104.04 -0.838 104.158 -0.838 c
+104.246 -0.838 104.334 -0.823 104.422 -0.794 c
+104.422 -1.352 l
+104.275 -1.4 104.121 -1.426 103.967 -1.426 c
+103.709 -1.426 103.514 -1.334 103.379 -1.147 c
+103.239 -0.962 103.173 -0.702 103.173 -0.368 c
+103.173 2.102 l
+102.57 2.102 l
+102.57 2.631 l
+103.173 2.631 l
+103.173 3.587 l
+h
+106.039 3.587 m
+106.039 2.631 l
+106.641 2.631 l
+106.641 2.102 l
+106.039 2.102 l
+106.039 -0.368 l
+106.039 -0.525 106.061 -0.643 106.113 -0.721 c
+106.171 -0.801 106.259 -0.838 106.377 -0.838 c
+106.465 -0.838 106.554 -0.823 106.641 -0.794 c
+106.641 -1.352 l
+106.495 -1.4 106.34 -1.426 106.186 -1.426 c
+105.929 -1.426 105.734 -1.334 105.598 -1.147 c
+105.459 -0.962 105.392 -0.702 105.392 -0.368 c
+105.392 2.102 l
+104.79 2.102 l
+104.79 2.631 l
+105.392 2.631 l
+105.392 3.587 l
+h
+109.449 -1.352 m
+109.409 -1.264 109.384 -1.117 109.376 -0.912 c
+109.141 -1.257 108.846 -1.426 108.494 -1.426 c
+108.13 -1.426 107.847 -1.33 107.641 -1.132 c
+107.443 -0.926 107.347 -0.64 107.347 -0.264 c
+107.347 0.136 107.483 0.455 107.759 0.69 c
+108.031 0.933 108.406 1.058 108.876 1.058 c
+109.361 1.058 l
+109.361 1.484 l
+109.361 1.72 109.306 1.885 109.199 1.984 c
+109.089 2.091 108.927 2.146 108.715 2.146 c
+108.516 2.146 108.354 2.087 108.229 1.97 c
+108.112 1.852 108.052 1.706 108.052 1.529 c
+107.406 1.529 l
+107.406 1.723 107.465 1.914 107.582 2.102 c
+107.707 2.286 107.869 2.433 108.067 2.543 c
+108.273 2.65 108.501 2.705 108.758 2.705 c
+109.159 2.705 109.463 2.602 109.67 2.396 c
+109.883 2.19 109.997 1.897 110.008 1.514 c
+110.008 -0.5 l
+110.008 -0.804 110.045 -1.07 110.126 -1.294 c
+110.126 -1.352 l
+h
+108.582 -0.838 m
+108.748 -0.838 108.898 -0.794 109.037 -0.706 c
+109.185 -0.617 109.291 -0.507 109.361 -0.368 c
+109.361 0.573 l
+108.993 0.573 l
+108.678 0.573 108.435 0.503 108.258 0.368 c
+108.082 0.239 107.994 0.052 107.994 -0.191 c
+107.994 -0.419 108.038 -0.584 108.127 -0.691 c
+108.214 -0.79 108.366 -0.838 108.582 -0.838 c
+112.389 -0.867 m
+112.602 -0.867 112.775 -0.804 112.904 -0.676 c
+113.039 -0.54 113.113 -0.349 113.124 -0.103 c
+113.741 -0.103 l
+113.719 -0.485 113.583 -0.804 113.33 -1.058 c
+113.072 -1.305 112.76 -1.426 112.389 -1.426 c
+111.896 -1.426 111.522 -1.275 111.257 -0.97 c
+111 -0.658 110.875 -0.191 110.875 0.426 c
+110.875 0.867 l
+110.875 1.463 111 1.918 111.257 2.234 c
+111.522 2.547 111.896 2.705 112.389 2.705 c
+112.79 2.705 113.11 2.572 113.345 2.308 c
+113.587 2.051 113.719 1.706 113.741 1.264 c
+113.124 1.264 l
+113.102 1.558 113.029 1.779 112.904 1.926 c
+112.786 2.072 112.613 2.146 112.389 2.146 c
+112.095 2.146 111.878 2.047 111.742 1.852 c
+111.603 1.665 111.529 1.357 111.522 0.926 c
+111.522 0.412 l
+111.522 -0.058 111.588 -0.393 111.728 -0.588 c
+111.875 -0.775 112.095 -0.867 112.389 -0.867 c
+115.138 2.219 m
+115.391 2.543 115.711 2.705 116.093 2.705 c
+116.798 2.705 117.155 2.234 117.166 1.294 c
+117.166 -1.352 l
+116.519 -1.352 l
+116.519 1.264 l
+116.519 1.577 116.464 1.797 116.358 1.926 c
+116.247 2.051 116.093 2.117 115.888 2.117 c
+115.73 2.117 115.582 2.062 115.447 1.955 c
+115.318 1.845 115.215 1.709 115.138 1.544 c
+115.138 -1.352 l
+114.491 -1.352 l
+114.491 4.293 l
+115.138 4.293 l
+h
+119.547 -1.426 m
+119.048 -1.426 118.666 -1.278 118.401 -0.985 c
+118.136 -0.691 118.004 -0.257 118.004 0.324 c
+118.004 0.794 l
+118.004 1.389 118.129 1.856 118.386 2.19 c
+118.651 2.532 119.011 2.705 119.474 2.705 c
+119.933 2.705 120.275 2.55 120.503 2.249 c
+120.738 1.955 120.86 1.492 120.871 0.867 c
+120.871 0.441 l
+118.651 0.441 l
+118.651 0.353 l
+118.651 -0.081 118.728 -0.393 118.886 -0.588 c
+119.051 -0.775 119.283 -0.867 119.576 -0.867 c
+119.772 -0.867 119.944 -0.834 120.091 -0.764 c
+120.239 -0.687 120.374 -0.569 120.503 -0.411 c
+120.841 -0.823 l
+120.555 -1.228 120.125 -1.426 119.547 -1.426 c
+119.474 2.146 m
+119.198 2.146 118.996 2.051 118.871 1.866 c
+118.743 1.679 118.67 1.389 118.651 1 c
+120.224 1 l
+120.224 1.087 l
+120.202 1.47 120.135 1.738 120.018 1.897 c
+119.9 2.062 119.717 2.146 119.474 2.146 c
+121.517 0.823 m
+121.517 1.43 121.627 1.897 121.855 2.219 c
+122.09 2.543 122.417 2.705 122.84 2.705 c
+123.223 2.705 123.52 2.547 123.736 2.234 c
+123.736 4.293 l
+124.384 4.293 l
+124.384 -1.352 l
+123.796 -1.352 l
+123.751 -0.926 l
+123.545 -1.261 123.241 -1.426 122.84 -1.426 c
+122.429 -1.426 122.105 -1.271 121.87 -0.956 c
+121.635 -0.632 121.517 -0.176 121.517 0.412 c
+h
+122.163 0.441 m
+122.163 0 122.227 -0.33 122.355 -0.544 c
+122.491 -0.75 122.712 -0.852 123.017 -0.852 c
+123.339 -0.852 123.578 -0.691 123.736 -0.368 c
+123.736 1.646 l
+123.568 1.959 123.329 2.117 123.017 2.117 c
+122.712 2.117 122.491 2.014 122.355 1.808 c
+122.227 1.602 122.163 1.278 122.163 0.838 c
+h
+127.956 3.587 m
+127.956 2.631 l
+128.558 2.631 l
+128.558 2.102 l
+127.956 2.102 l
+127.956 -0.368 l
+127.956 -0.525 127.977 -0.643 128.029 -0.721 c
+128.087 -0.801 128.176 -0.838 128.293 -0.838 c
+128.382 -0.838 128.47 -0.823 128.558 -0.794 c
+128.558 -1.352 l
+128.411 -1.4 128.257 -1.426 128.102 -1.426 c
+127.846 -1.426 127.651 -1.334 127.514 -1.147 c
+127.375 -0.962 127.308 -0.702 127.308 -0.368 c
+127.308 2.102 l
+126.706 2.102 l
+126.706 2.631 l
+127.308 2.631 l
+127.308 3.587 l
+h
+129.116 0.823 m
+129.116 1.4 129.253 1.856 129.529 2.19 c
+129.811 2.532 130.182 2.705 130.645 2.705 c
+131.104 2.705 131.472 2.535 131.748 2.205 c
+132.031 1.881 132.178 1.434 132.189 0.867 c
+132.189 0.441 l
+132.189 -0.129 132.045 -0.584 131.763 -0.926 c
+131.487 -1.261 131.119 -1.426 130.66 -1.426 c
+130.197 -1.426 129.826 -1.264 129.543 -0.941 c
+129.267 -0.61 129.124 -0.169 129.116 0.382 c
+h
+129.764 0.441 m
+129.764 0.037 129.841 -0.279 129.999 -0.515 c
+130.164 -0.75 130.385 -0.867 130.66 -0.867 c
+131.226 -0.867 131.52 -0.455 131.542 0.368 c
+131.542 0.823 l
+131.542 1.224 131.457 1.544 131.292 1.779 c
+131.134 2.022 130.917 2.146 130.645 2.146 c
+130.381 2.146 130.164 2.022 129.999 1.779 c
+129.841 1.544 129.764 1.224 129.764 0.823 c
+h
+135.834 -0.264 m
+136.554 2.631 l
+137.245 2.631 l
+135.952 -1.911 l
+135.852 -2.252 135.709 -2.514 135.526 -2.69 c
+135.349 -2.866 135.147 -2.955 134.923 -2.955 c
+134.834 -2.955 134.72 -2.932 134.585 -2.896 c
+134.585 -2.352 l
+134.732 -2.367 l
+134.915 -2.367 135.062 -2.323 135.173 -2.234 c
+135.279 -2.146 135.368 -1.988 135.437 -1.764 c
+135.555 -1.323 l
+134.393 2.631 l
+135.099 2.631 l
+h
+137.686 0.823 m
+137.686 1.4 137.822 1.856 138.098 2.19 c
+138.381 2.532 138.752 2.705 139.215 2.705 c
+139.674 2.705 140.041 2.535 140.317 2.205 c
+140.6 1.881 140.747 1.434 140.758 0.867 c
+140.758 0.441 l
+140.758 -0.129 140.615 -0.584 140.332 -0.926 c
+140.056 -1.261 139.689 -1.426 139.229 -1.426 c
+138.767 -1.426 138.395 -1.264 138.113 -0.941 c
+137.837 -0.61 137.693 -0.169 137.686 0.382 c
+h
+138.333 0.441 m
+138.333 0.037 138.41 -0.279 138.568 -0.515 c
+138.734 -0.75 138.954 -0.867 139.229 -0.867 c
+139.796 -0.867 140.089 -0.455 140.112 0.368 c
+140.112 0.823 l
+140.112 1.224 140.027 1.544 139.862 1.779 c
+139.704 2.022 139.487 2.146 139.215 2.146 c
+138.95 2.146 138.734 2.022 138.568 1.779 c
+138.41 1.544 138.333 1.224 138.333 0.823 c
+h
+143.625 -0.999 m
+143.408 -1.286 143.095 -1.426 142.684 -1.426 c
+142.32 -1.426 142.044 -1.305 141.861 -1.058 c
+141.684 -0.804 141.589 -0.441 141.581 0.029 c
+141.581 2.631 l
+142.229 2.631 l
+142.229 0.088 l
+142.229 -0.54 142.412 -0.852 142.786 -0.852 c
+143.187 -0.852 143.463 -0.676 143.609 -0.324 c
+143.609 2.631 l
+144.257 2.631 l
+144.257 -1.352 l
+143.64 -1.352 l
+h
+146.888 2.014 m
+146.8 2.032 146.701 2.043 146.594 2.043 c
+146.26 2.043 146.024 1.86 145.888 1.5 c
+145.888 -1.352 l
+145.242 -1.352 l
+145.242 2.631 l
+145.874 2.631 l
+145.888 2.219 l
+146.065 2.543 146.308 2.705 146.623 2.705 c
+146.73 2.705 146.818 2.683 146.888 2.646 c
+h
+150.636 -0.867 m
+150.849 -0.867 151.022 -0.804 151.15 -0.676 c
+151.287 -0.54 151.36 -0.349 151.371 -0.103 c
+151.989 -0.103 l
+151.966 -0.485 151.831 -0.804 151.577 -1.058 c
+151.32 -1.305 151.007 -1.426 150.636 -1.426 c
+150.144 -1.426 149.769 -1.275 149.504 -0.97 c
+149.247 -0.658 149.122 -0.191 149.122 0.426 c
+149.122 0.867 l
+149.122 1.463 149.247 1.918 149.504 2.234 c
+149.769 2.547 150.144 2.705 150.636 2.705 c
+151.037 2.705 151.356 2.572 151.592 2.308 c
+151.834 2.051 151.966 1.706 151.989 1.264 c
+151.371 1.264 l
+151.349 1.558 151.276 1.779 151.15 1.926 c
+151.033 2.072 150.86 2.146 150.636 2.146 c
+150.342 2.146 150.125 2.047 149.99 1.852 c
+149.849 1.665 149.776 1.357 149.769 0.926 c
+149.769 0.412 l
+149.769 -0.058 149.835 -0.393 149.975 -0.588 c
+150.121 -0.775 150.342 -0.867 150.636 -0.867 c
+152.606 0.823 m
+152.606 1.4 152.741 1.856 153.017 2.19 c
+153.3 2.532 153.672 2.705 154.134 2.705 c
+154.594 2.705 154.961 2.535 155.237 2.205 c
+155.52 1.881 155.667 1.434 155.678 0.867 c
+155.678 0.441 l
+155.678 -0.129 155.534 -0.584 155.251 -0.926 c
+154.976 -1.261 154.609 -1.426 154.149 -1.426 c
+153.686 -1.426 153.315 -1.264 153.032 -0.941 c
+152.756 -0.61 152.613 -0.169 152.606 0.382 c
+h
+153.252 0.441 m
+153.252 0.037 153.329 -0.279 153.487 -0.515 c
+153.653 -0.75 153.874 -0.867 154.149 -0.867 c
+154.715 -0.867 155.009 -0.455 155.031 0.368 c
+155.031 0.823 l
+155.031 1.224 154.946 1.544 154.781 1.779 c
+154.623 2.022 154.406 2.146 154.134 2.146 c
+153.87 2.146 153.653 2.022 153.487 1.779 c
+153.329 1.544 153.252 1.224 153.252 0.823 c
+h
+157.133 2.631 m
+157.148 2.263 l
+157.39 2.558 157.71 2.705 158.103 2.705 c
+158.544 2.705 158.852 2.506 159.029 2.117 c
+159.283 2.506 159.632 2.705 160.072 2.705 c
+160.808 2.705 161.183 2.242 161.204 1.323 c
+161.204 -1.352 l
+160.558 -1.352 l
+160.558 1.264 l
+160.558 1.558 160.502 1.771 160.396 1.911 c
+160.297 2.047 160.124 2.117 159.881 2.117 c
+159.683 2.117 159.521 2.036 159.397 1.881 c
+159.279 1.735 159.209 1.544 159.191 1.309 c
+159.191 -1.352 l
+158.53 -1.352 l
+158.53 1.294 l
+158.53 1.841 158.309 2.117 157.868 2.117 c
+157.533 2.117 157.298 1.955 157.163 1.631 c
+157.163 -1.352 l
+156.516 -1.352 l
+156.516 2.631 l
+h
+162.792 2.631 m
+162.807 2.263 l
+163.049 2.558 163.369 2.705 163.762 2.705 c
+164.203 2.705 164.512 2.506 164.689 2.117 c
+164.942 2.506 165.291 2.705 165.732 2.705 c
+166.467 2.705 166.842 2.242 166.864 1.323 c
+166.864 -1.352 l
+166.217 -1.352 l
+166.217 1.264 l
+166.217 1.558 166.162 1.771 166.056 1.911 c
+165.956 2.047 165.784 2.117 165.541 2.117 c
+165.342 2.117 165.181 2.036 165.056 1.881 c
+164.938 1.735 164.868 1.544 164.85 1.309 c
+164.85 -1.352 l
+164.188 -1.352 l
+164.188 1.294 l
+164.188 1.841 163.968 2.117 163.527 2.117 c
+163.193 2.117 162.958 1.955 162.821 1.631 c
+162.821 -1.352 l
+162.175 -1.352 l
+162.175 2.631 l
+h
+168.539 -1.352 -0.646 3.983 re
+168.583 3.674 m
+168.583 3.564 168.554 3.473 168.495 3.395 c
+168.437 3.326 168.341 3.293 168.216 3.293 c
+168.099 3.293 168.003 3.326 167.937 3.395 c
+167.878 3.473 167.849 3.564 167.849 3.674 c
+167.849 3.792 167.878 3.884 167.937 3.954 c
+168.003 4.031 168.099 4.072 168.216 4.072 c
+168.341 4.072 168.437 4.031 168.495 3.954 c
+168.554 3.873 168.583 3.782 168.583 3.674 c
+170.406 3.587 m
+170.406 2.631 l
+171.009 2.631 l
+171.009 2.102 l
+170.406 2.102 l
+170.406 -0.368 l
+170.406 -0.525 170.428 -0.643 170.48 -0.721 c
+170.538 -0.801 170.627 -0.838 170.744 -0.838 c
+170.833 -0.838 170.921 -0.823 171.009 -0.794 c
+171.009 -1.352 l
+170.862 -1.4 170.708 -1.426 170.553 -1.426 c
+170.296 -1.426 170.102 -1.334 169.965 -1.147 c
+169.826 -0.962 169.759 -0.702 169.759 -0.368 c
+169.759 2.102 l
+169.157 2.102 l
+169.157 2.631 l
+169.759 2.631 l
+169.759 3.587 l
+h
+173.713 -0.338 m
+173.713 -0.191 173.659 -0.07 173.552 0.029 c
+173.441 0.125 173.236 0.243 172.934 0.382 c
+172.589 0.53 172.346 0.651 172.2 0.75 c
+172.053 0.856 171.943 0.974 171.876 1.103 c
+171.806 1.228 171.773 1.386 171.773 1.573 c
+171.773 1.897 171.891 2.165 172.126 2.381 c
+172.361 2.595 172.662 2.705 173.038 2.705 c
+173.42 2.705 173.728 2.591 173.963 2.367 c
+174.199 2.139 174.316 1.852 174.316 1.5 c
+173.669 1.5 l
+173.669 1.675 173.611 1.827 173.493 1.955 c
+173.375 2.08 173.221 2.146 173.038 2.146 c
+172.839 2.146 172.689 2.091 172.581 1.984 c
+172.471 1.885 172.42 1.753 172.42 1.588 c
+172.42 1.459 172.456 1.353 172.537 1.264 c
+172.614 1.183 172.806 1.081 173.111 0.956 c
+173.589 0.769 173.919 0.58 174.096 0.397 c
+174.272 0.22 174.36 -0.008 174.36 -0.279 c
+174.36 -0.632 174.235 -0.912 173.993 -1.117 c
+173.757 -1.323 173.441 -1.426 173.052 -1.426 c
+172.629 -1.426 172.292 -1.309 172.038 -1.073 c
+171.781 -0.831 171.656 -0.525 171.656 -0.162 c
+172.302 -0.162 l
+172.31 -0.389 172.379 -0.565 172.508 -0.691 c
+172.633 -0.808 172.817 -0.867 173.052 -0.867 c
+173.265 -0.867 173.427 -0.819 173.537 -0.721 c
+173.655 -0.625 173.713 -0.496 173.713 -0.338 c
+178.962 -1.352 m
+178.921 -1.264 178.895 -1.117 178.887 -0.912 c
+178.652 -1.257 178.359 -1.426 178.006 -1.426 c
+177.642 -1.426 177.359 -1.33 177.153 -1.132 c
+176.955 -0.926 176.859 -0.64 176.859 -0.264 c
+176.859 0.136 176.995 0.455 177.271 0.69 c
+177.543 0.933 177.917 1.058 178.388 1.058 c
+178.873 1.058 l
+178.873 1.484 l
+178.873 1.72 178.818 1.885 178.711 1.984 c
+178.601 2.091 178.439 2.146 178.226 2.146 c
+178.027 2.146 177.866 2.087 177.741 1.97 c
+177.624 1.852 177.565 1.706 177.565 1.529 c
+176.918 1.529 l
+176.918 1.723 176.977 1.914 177.094 2.102 c
+177.219 2.286 177.381 2.433 177.58 2.543 c
+177.786 2.65 178.013 2.705 178.27 2.705 c
+178.671 2.705 178.976 2.602 179.182 2.396 c
+179.394 2.19 179.509 1.897 179.519 1.514 c
+179.519 -0.5 l
+179.519 -0.804 179.556 -1.07 179.637 -1.294 c
+179.637 -1.352 l
+h
+178.094 -0.838 m
+178.259 -0.838 178.41 -0.794 178.55 -0.706 c
+178.696 -0.617 178.804 -0.507 178.873 -0.368 c
+178.873 0.573 l
+178.505 0.573 l
+178.189 0.573 177.946 0.503 177.771 0.368 c
+177.594 0.239 177.506 0.052 177.506 -0.191 c
+177.506 -0.419 177.55 -0.584 177.638 -0.691 c
+177.726 -0.79 177.877 -0.838 178.094 -0.838 c
+181.137 2.631 m
+181.152 2.19 l
+181.405 2.532 181.728 2.705 182.121 2.705 c
+182.827 2.705 183.184 2.234 183.195 1.294 c
+183.195 -1.352 l
+182.548 -1.352 l
+182.548 1.264 l
+182.548 1.577 182.492 1.797 182.386 1.926 c
+182.276 2.051 182.121 2.117 181.915 2.117 c
+181.757 2.117 181.611 2.062 181.474 1.955 c
+181.346 1.845 181.243 1.709 181.166 1.544 c
+181.166 -1.352 l
+180.519 -1.352 l
+180.519 2.631 l
+h
+184.032 0.823 m
+184.032 1.43 184.142 1.897 184.371 2.219 c
+184.606 2.543 184.932 2.705 185.355 2.705 c
+185.738 2.705 186.035 2.547 186.252 2.234 c
+186.252 4.293 l
+186.899 4.293 l
+186.899 -1.352 l
+186.311 -1.352 l
+186.266 -0.926 l
+186.06 -1.261 185.756 -1.426 185.355 -1.426 c
+184.944 -1.426 184.62 -1.271 184.385 -0.956 c
+184.15 -0.632 184.032 -0.176 184.032 0.412 c
+h
+184.679 0.441 m
+184.679 0 184.741 -0.33 184.87 -0.544 c
+185.006 -0.75 185.227 -0.852 185.532 -0.852 c
+185.855 -0.852 186.094 -0.691 186.252 -0.368 c
+186.252 1.646 l
+186.083 1.959 185.844 2.117 185.532 2.117 c
+185.227 2.117 185.006 2.014 184.87 1.808 c
+184.741 1.602 184.679 1.278 184.679 0.838 c
+h
+190.471 3.587 m
+190.471 2.631 l
+191.073 2.631 l
+191.073 2.102 l
+190.471 2.102 l
+190.471 -0.368 l
+190.471 -0.525 190.492 -0.643 190.544 -0.721 c
+190.602 -0.801 190.691 -0.838 190.808 -0.838 c
+190.897 -0.838 190.985 -0.823 191.073 -0.794 c
+191.073 -1.352 l
+190.926 -1.4 190.772 -1.426 190.617 -1.426 c
+190.36 -1.426 190.166 -1.334 190.029 -1.147 c
+189.89 -0.962 189.823 -0.702 189.823 -0.368 c
+189.823 2.102 l
+189.221 2.102 l
+189.221 2.631 l
+189.823 2.631 l
+189.823 3.587 l
+h
+193.881 -1.352 m
+193.84 -1.264 193.815 -1.117 193.807 -0.912 c
+193.572 -1.257 193.278 -1.426 192.925 -1.426 c
+192.562 -1.426 192.279 -1.33 192.073 -1.132 c
+191.874 -0.926 191.778 -0.64 191.778 -0.264 c
+191.778 0.136 191.915 0.455 192.19 0.69 c
+192.462 0.933 192.837 1.058 193.308 1.058 c
+193.792 1.058 l
+193.792 1.484 l
+193.792 1.72 193.738 1.885 193.63 1.984 c
+193.52 2.091 193.359 2.146 193.146 2.146 c
+192.948 2.146 192.786 2.087 192.661 1.97 c
+192.543 1.852 192.484 1.706 192.484 1.529 c
+191.837 1.529 l
+191.837 1.723 191.897 1.914 192.013 2.102 c
+192.138 2.286 192.3 2.433 192.499 2.543 c
+192.705 2.65 192.932 2.705 193.189 2.705 c
+193.59 2.705 193.895 2.602 194.101 2.396 c
+194.314 2.19 194.428 1.897 194.44 1.514 c
+194.44 -0.5 l
+194.44 -0.804 194.476 -1.07 194.557 -1.294 c
+194.557 -1.352 l
+h
+193.013 -0.838 m
+193.179 -0.838 193.329 -0.794 193.469 -0.706 c
+193.616 -0.617 193.723 -0.507 193.792 -0.368 c
+193.792 0.573 l
+193.424 0.573 l
+193.109 0.573 192.867 0.503 192.69 0.368 c
+192.514 0.239 192.425 0.052 192.425 -0.191 c
+192.425 -0.419 192.47 -0.584 192.558 -0.691 c
+192.646 -0.79 192.797 -0.838 193.013 -0.838 c
+195.306 0.823 m
+195.306 1.44 195.417 1.904 195.645 2.219 c
+195.869 2.543 196.203 2.705 196.644 2.705 c
+197.044 2.705 197.349 2.529 197.555 2.176 c
+197.599 2.631 l
+198.187 2.631 l
+198.187 -1.396 l
+198.187 -1.885 198.059 -2.263 197.806 -2.528 c
+197.548 -2.793 197.195 -2.925 196.747 -2.925 c
+196.549 -2.925 196.328 -2.874 196.086 -2.778 c
+195.839 -2.679 195.66 -2.558 195.541 -2.41 c
+195.806 -1.97 l
+196.071 -2.234 196.368 -2.367 196.703 -2.367 c
+197.239 -2.367 197.515 -2.072 197.526 -1.484 c
+197.526 -0.956 l
+197.32 -1.271 197.019 -1.426 196.63 -1.426 c
+196.218 -1.426 195.895 -1.275 195.66 -0.97 c
+195.431 -0.658 195.313 -0.206 195.306 0.382 c
+h
+195.968 0.441 m
+195.968 0 196.03 -0.33 196.159 -0.544 c
+196.284 -0.75 196.501 -0.852 196.806 -0.852 c
+197.129 -0.852 197.368 -0.687 197.526 -0.353 c
+197.526 1.631 l
+197.357 1.955 197.118 2.117 196.806 2.117 c
+196.512 2.117 196.295 2.014 196.159 1.808 c
+196.03 1.602 195.968 1.278 195.968 0.838 c
+h
+201.083 -0.338 m
+201.083 -0.191 201.028 -0.07 200.921 0.029 c
+200.811 0.125 200.605 0.243 200.304 0.382 c
+199.959 0.53 199.716 0.651 199.569 0.75 c
+199.423 0.856 199.312 0.974 199.246 1.103 c
+199.176 1.228 199.143 1.386 199.143 1.573 c
+199.143 1.897 199.261 2.165 199.496 2.381 c
+199.731 2.595 200.032 2.705 200.407 2.705 c
+200.79 2.705 201.098 2.591 201.333 2.367 c
+201.568 2.139 201.686 1.852 201.686 1.5 c
+201.039 1.5 l
+201.039 1.675 200.98 1.827 200.863 1.955 c
+200.745 2.08 200.591 2.146 200.407 2.146 c
+200.208 2.146 200.058 2.091 199.951 1.984 c
+199.841 1.885 199.79 1.753 199.79 1.588 c
+199.79 1.459 199.826 1.353 199.907 1.264 c
+199.984 1.183 200.175 1.081 200.48 0.956 c
+200.958 0.769 201.289 0.58 201.465 0.397 c
+201.642 0.22 201.73 -0.008 201.73 -0.279 c
+201.73 -0.632 201.605 -0.912 201.362 -1.117 c
+201.127 -1.323 200.811 -1.426 200.422 -1.426 c
+199.999 -1.426 199.661 -1.309 199.408 -1.073 c
+199.15 -0.831 199.026 -0.525 199.026 -0.162 c
+199.672 -0.162 l
+199.679 -0.389 199.749 -0.565 199.878 -0.691 c
+200.003 -0.808 200.187 -0.867 200.422 -0.867 c
+200.635 -0.867 200.796 -0.819 200.907 -0.721 c
+201.025 -0.625 201.083 -0.496 201.083 -0.338 c
+202.612 -0.999 m
+202.612 -0.881 202.645 -0.786 202.715 -0.706 c
+202.781 -0.628 202.884 -0.588 203.024 -0.588 c
+203.171 -0.588 203.277 -0.628 203.346 -0.706 c
+203.424 -0.786 203.464 -0.881 203.464 -0.999 c
+203.464 -1.11 203.424 -1.201 203.346 -1.278 c
+203.277 -1.356 203.171 -1.396 203.024 -1.396 c
+202.884 -1.396 202.781 -1.356 202.715 -1.278 c
+202.645 -1.201 202.612 -1.11 202.612 -0.999 c
+f
+Q
+0.113 0.082 0.09 0 k
+35.668 354.533 238.665 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 40.8563 347.6937 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.69 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.69 -1.999 0.69 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.278 -3.219 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.119 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.119 -1.128 3.09 -0.97 3.042 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.182 -0.103 1.999 c
+-0.941 1.882 l
+-1.01 2.253 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.319 2.385 -2.366 2.337 c
+-2.406 2.296 -2.437 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.856 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.86 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.073 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.411 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.631 5.137 1.779 c
+5.245 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.179 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.866 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.152 2.219 c
+8.004 2.219 l
+7.993 2.138 7.982 2.028 7.975 1.882 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.871 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.675 re
+10.124 2.837 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.219 l
+13.644 2.219 l
+13.924 3.117 l
+14.497 3.117 l
+14.497 2.219 l
+15.732 2.219 l
+15.732 1.602 l
+14.497 1.602 l
+14.497 -0.103 l
+14.497 -0.324 l
+14.504 -0.393 14.527 -0.455 14.556 -0.515 c
+14.593 -0.566 14.648 -0.61 14.718 -0.646 c
+14.795 -0.676 14.909 -0.69 15.056 -0.69 c
+15.192 -0.69 15.327 -0.687 15.468 -0.676 c
+15.603 -0.658 15.736 -0.632 15.865 -0.603 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.231 15.629 -1.249 c
+15.549 -1.261 15.471 -1.268 15.394 -1.278 c
+15.313 -1.286 15.225 -1.293 15.129 -1.293 c
+15.041 -1.301 14.942 -1.309 14.835 -1.309 c
+14.648 -1.309 14.486 -1.293 14.35 -1.264 c
+14.221 -1.228 14.107 -1.183 14.012 -1.132 c
+13.924 -1.084 13.85 -1.025 13.791 -0.956 c
+13.733 -0.879 13.689 -0.802 13.66 -0.721 c
+13.63 -0.632 13.608 -0.544 13.6 -0.455 c
+13.59 -0.36 13.586 -0.264 13.586 -0.176 c
+h
+22.677 -1.323 m
+22.391 -1.323 22.148 -1.282 21.943 -1.205 c
+21.737 -1.117 21.564 -0.996 21.428 -0.838 c
+21.288 -0.684 21.185 -0.496 21.119 -0.279 c
+21.049 -0.056 21.016 0.191 21.016 0.455 c
+21.016 0.75 21.049 1.007 21.119 1.235 c
+21.197 1.459 21.303 1.646 21.442 1.793 c
+21.589 1.947 21.766 2.065 21.972 2.146 c
+22.178 2.234 22.413 2.278 22.677 2.278 c
+22.901 2.278 23.104 2.249 23.28 2.19 c
+23.456 2.132 23.607 2.047 23.736 1.941 c
+23.861 1.841 23.963 1.72 24.044 1.573 c
+24.122 1.433 24.176 1.282 24.206 1.118 c
+23.295 1.073 l
+23.265 1.249 23.196 1.389 23.089 1.5 c
+22.99 1.606 22.846 1.661 22.662 1.661 c
+22.416 1.661 22.24 1.558 22.134 1.353 c
+22.023 1.154 21.972 0.867 21.972 0.485 c
+21.972 -0.309 22.207 -0.706 22.677 -0.706 c
+22.843 -0.706 22.986 -0.654 23.104 -0.544 c
+23.221 -0.437 23.295 -0.276 23.324 -0.058 c
+24.235 -0.103 l
+24.206 -0.272 24.151 -0.426 24.074 -0.573 c
+24.004 -0.721 23.901 -0.852 23.765 -0.97 c
+23.636 -1.08 23.478 -1.168 23.295 -1.234 c
+23.119 -1.293 22.913 -1.323 22.677 -1.323 c
+28.384 0.485 m
+28.384 0.21 28.347 -0.04 28.281 -0.264 c
+28.212 -0.482 28.108 -0.669 27.973 -0.823 c
+27.833 -0.981 27.657 -1.103 27.443 -1.191 c
+27.227 -1.278 26.973 -1.323 26.679 -1.323 c
+26.404 -1.323 26.157 -1.278 25.944 -1.191 c
+25.739 -1.103 25.566 -0.981 25.43 -0.823 c
+25.29 -0.669 25.187 -0.482 25.121 -0.264 c
+25.051 -0.04 25.018 0.21 25.018 0.485 c
+25.018 0.738 25.047 0.974 25.106 1.191 c
+25.172 1.415 25.275 1.606 25.415 1.764 c
+25.55 1.929 25.727 2.058 25.944 2.146 c
+26.157 2.234 26.414 2.278 26.709 2.278 c
+27.021 2.278 27.281 2.234 27.487 2.146 c
+27.701 2.058 27.873 1.929 28.002 1.764 c
+28.138 1.606 28.237 1.415 28.296 1.191 c
+28.355 0.974 28.384 0.738 28.384 0.485 c
+27.429 0.485 m
+27.429 0.69 27.414 0.867 27.385 1.014 c
+27.362 1.161 27.326 1.282 27.267 1.382 c
+27.208 1.477 27.135 1.548 27.046 1.588 c
+26.959 1.635 26.848 1.661 26.724 1.661 c
+26.458 1.661 26.267 1.562 26.15 1.367 c
+26.032 1.18 25.974 0.885 25.974 0.485 c
+25.974 0.062 26.032 -0.243 26.15 -0.426 c
+26.267 -0.613 26.444 -0.706 26.679 -0.706 c
+26.804 -0.706 26.918 -0.687 27.017 -0.646 c
+27.113 -0.599 27.194 -0.526 27.252 -0.426 c
+27.318 -0.331 27.362 -0.206 27.385 -0.058 c
+27.414 0.088 27.429 0.268 27.429 0.485 c
+31.43 -1.264 m
+31.43 0.721 l
+31.43 1.022 31.387 1.242 31.298 1.382 c
+31.217 1.529 31.081 1.602 30.886 1.602 c
+30.776 1.602 30.674 1.577 30.578 1.529 c
+30.489 1.477 30.409 1.411 30.343 1.323 c
+30.284 1.235 30.233 1.124 30.196 1 c
+30.167 0.882 30.152 0.75 30.152 0.603 c
+30.152 -1.264 l
+29.24 -1.264 l
+29.24 1.44 l
+29.24 1.661 l
+29.24 1.749 29.233 1.826 29.226 1.897 c
+29.226 2.087 l
+29.226 2.219 l
+30.078 2.219 l
+30.086 2.19 30.093 2.146 30.093 2.087 c
+30.093 1.897 l
+30.1 1.826 30.107 1.756 30.107 1.691 c
+30.115 1.621 30.122 1.565 30.122 1.529 c
+30.137 1.529 l
+30.254 1.793 30.406 1.984 30.593 2.102 c
+30.776 2.219 30.996 2.278 31.254 2.278 c
+31.438 2.278 31.599 2.249 31.74 2.19 c
+31.875 2.132 31.989 2.043 32.077 1.926 c
+32.166 1.808 32.228 1.665 32.268 1.5 c
+32.316 1.341 32.342 1.154 32.342 0.941 c
+32.342 -1.264 l
+h
+34.951 1.602 m
+34.951 -1.264 l
+34.054 -1.264 l
+34.054 1.602 l
+33.232 1.602 l
+33.232 2.219 l
+34.054 2.219 l
+34.054 2.484 l
+34.054 2.609 34.069 2.741 34.098 2.882 c
+34.135 3.017 34.205 3.135 34.304 3.234 c
+34.41 3.341 34.554 3.429 34.73 3.499 c
+34.907 3.564 35.131 3.601 35.407 3.601 c
+35.62 3.601 35.819 3.59 35.995 3.572 c
+36.17 3.549 36.322 3.532 36.45 3.513 c
+36.45 2.925 l
+36.322 2.944 36.178 2.959 36.024 2.969 c
+35.866 2.977 35.715 2.984 35.568 2.984 c
+35.44 2.984 35.337 2.969 35.26 2.94 c
+35.179 2.911 35.116 2.87 35.069 2.822 c
+35.017 2.77 34.984 2.708 34.965 2.631 c
+34.955 2.562 34.951 2.484 34.951 2.396 c
+34.951 2.219 l
+36.377 2.219 l
+36.377 1.602 l
+h
+39.467 -0.646 m
+40.599 -0.646 l
+40.599 -1.264 l
+37.292 -1.264 l
+37.292 -0.646 l
+38.556 -0.646 l
+38.556 1.602 l
+37.63 1.602 l
+37.63 2.219 l
+39.467 2.219 l
+h
+38.556 3.513 0.911 -0.675 re
+38.556 2.837 m
+42.954 -2.66 m
+42.738 -2.66 42.547 -2.635 42.381 -2.587 c
+42.212 -2.547 42.073 -2.484 41.955 -2.396 c
+41.837 -2.315 41.738 -2.219 41.661 -2.102 c
+41.591 -1.984 41.543 -1.856 41.514 -1.72 c
+42.41 -1.617 l
+42.447 -1.753 42.518 -1.86 42.616 -1.94 c
+42.712 -2.028 42.837 -2.072 42.984 -2.072 c
+43.072 -2.072 43.153 -2.057 43.234 -2.028 c
+43.311 -1.999 43.381 -1.944 43.44 -1.866 c
+43.499 -1.797 43.542 -1.705 43.572 -1.587 c
+43.609 -1.469 43.631 -1.323 43.631 -1.147 c
+43.631 -0.956 l
+43.631 -0.889 43.634 -0.831 43.646 -0.779 c
+43.646 -0.588 l
+43.631 -0.588 l
+43.532 -0.816 43.388 -0.977 43.204 -1.073 c
+43.017 -1.172 42.811 -1.22 42.587 -1.22 c
+42.381 -1.22 42.198 -1.183 42.044 -1.103 c
+41.896 -1.014 41.768 -0.897 41.661 -0.75 c
+41.562 -0.595 41.488 -0.411 41.441 -0.206 c
+41.389 0.008 41.367 0.243 41.367 0.5 c
+41.367 0.771 41.389 1.018 41.441 1.235 c
+41.5 1.448 41.58 1.631 41.691 1.779 c
+41.797 1.933 41.93 2.051 42.088 2.132 c
+42.242 2.219 42.429 2.263 42.646 2.263 c
+42.742 2.263 42.84 2.253 42.94 2.234 c
+43.035 2.213 43.123 2.179 43.204 2.132 c
+43.293 2.08 43.37 2.018 43.44 1.941 c
+43.517 1.86 43.58 1.768 43.631 1.661 c
+43.646 1.661 l
+43.646 1.808 l
+43.653 1.866 43.66 1.918 43.66 1.97 c
+43.667 2.028 43.675 2.076 43.675 2.117 c
+43.682 2.165 43.694 2.198 43.704 2.219 c
+44.557 2.219 l
+44.546 2.138 44.535 2.028 44.527 1.882 c
+44.527 1.411 l
+44.527 -1.161 l
+44.527 -1.415 44.49 -1.635 44.425 -1.822 c
+44.355 -2.007 44.251 -2.161 44.116 -2.278 c
+43.976 -2.404 43.811 -2.499 43.616 -2.558 c
+43.418 -2.624 43.197 -2.66 42.954 -2.66 c
+43.646 0.53 m
+43.646 0.742 43.619 0.919 43.572 1.058 c
+43.532 1.205 43.476 1.323 43.41 1.411 c
+43.351 1.5 43.282 1.558 43.204 1.588 c
+43.123 1.625 43.046 1.646 42.969 1.646 c
+42.87 1.646 42.778 1.621 42.69 1.573 c
+42.609 1.532 42.543 1.463 42.484 1.367 c
+42.433 1.278 42.389 1.161 42.352 1.014 c
+42.323 0.875 42.308 0.706 42.308 0.5 c
+42.308 0.125 42.366 -0.154 42.484 -0.338 c
+42.601 -0.515 42.763 -0.603 42.969 -0.603 c
+43.035 -0.603 43.109 -0.588 43.189 -0.559 c
+43.278 -0.522 43.351 -0.463 43.41 -0.382 c
+43.476 -0.294 43.532 -0.176 43.572 -0.029 c
+43.619 0.118 43.646 0.301 43.646 0.53 c
+50.135 0.838 1.867 -0.794 re
+50.135 0.044 m
+54.2 0.838 1.866 -0.794 re
+54.2 0.044 m
+59.201 -2.66 m
+58.983 -2.66 58.792 -2.635 58.628 -2.587 c
+58.458 -2.547 58.318 -2.484 58.201 -2.396 c
+58.083 -2.315 57.984 -2.219 57.907 -2.102 c
+57.838 -1.984 57.79 -1.856 57.76 -1.72 c
+58.657 -1.617 l
+58.694 -1.753 58.763 -1.86 58.863 -1.94 c
+58.958 -2.028 59.083 -2.072 59.23 -2.072 c
+59.318 -2.072 59.399 -2.057 59.48 -2.028 c
+59.557 -1.999 59.627 -1.944 59.686 -1.866 c
+59.744 -1.797 59.789 -1.705 59.818 -1.587 c
+59.855 -1.469 59.877 -1.323 59.877 -1.147 c
+59.877 -0.956 l
+59.877 -0.889 59.881 -0.831 59.891 -0.779 c
+59.891 -0.588 l
+59.877 -0.588 l
+59.777 -0.816 59.634 -0.977 59.451 -1.073 c
+59.263 -1.172 59.058 -1.22 58.833 -1.22 c
+58.628 -1.22 58.443 -1.183 58.289 -1.103 c
+58.142 -1.014 58.014 -0.897 57.907 -0.75 c
+57.807 -0.595 57.734 -0.411 57.687 -0.206 c
+57.635 0.008 57.613 0.243 57.613 0.5 c
+57.613 0.771 57.635 1.018 57.687 1.235 c
+57.745 1.448 57.826 1.631 57.936 1.779 c
+58.043 1.933 58.175 2.051 58.333 2.132 c
+58.488 2.219 58.675 2.263 58.892 2.263 c
+58.987 2.263 59.087 2.253 59.186 2.234 c
+59.282 2.213 59.37 2.179 59.451 2.132 c
+59.538 2.08 59.616 2.018 59.686 1.941 c
+59.763 1.86 59.825 1.768 59.877 1.661 c
+59.891 1.661 l
+59.891 1.808 l
+59.899 1.866 59.906 1.918 59.906 1.97 c
+59.914 2.028 59.921 2.076 59.921 2.117 c
+59.928 2.165 59.939 2.198 59.951 2.219 c
+60.803 2.219 l
+60.792 2.138 60.781 2.028 60.774 1.882 c
+60.774 1.411 l
+60.774 -1.161 l
+60.774 -1.415 60.737 -1.635 60.67 -1.822 c
+60.601 -2.007 60.498 -2.161 60.362 -2.278 c
+60.222 -2.404 60.057 -2.499 59.862 -2.558 c
+59.664 -2.624 59.443 -2.66 59.201 -2.66 c
+59.891 0.53 m
+59.891 0.742 59.866 0.919 59.818 1.058 c
+59.777 1.205 59.723 1.323 59.656 1.411 c
+59.598 1.5 59.528 1.558 59.451 1.588 c
+59.37 1.625 59.293 1.646 59.216 1.646 c
+59.116 1.646 59.024 1.621 58.936 1.573 c
+58.855 1.532 58.789 1.463 58.73 1.367 c
+58.679 1.278 58.634 1.161 58.598 1.014 c
+58.569 0.875 58.553 0.706 58.553 0.5 c
+58.553 0.125 58.613 -0.154 58.73 -0.338 c
+58.848 -0.515 59.01 -0.603 59.216 -0.603 c
+59.282 -0.603 59.355 -0.588 59.436 -0.559 c
+59.524 -0.522 59.598 -0.463 59.656 -0.382 c
+59.723 -0.294 59.777 -0.176 59.818 -0.029 c
+59.866 0.118 59.891 0.301 59.891 0.53 c
+63.835 -0.646 m
+64.967 -0.646 l
+64.967 -1.264 l
+61.659 -1.264 l
+61.659 -0.646 l
+62.923 -0.646 l
+62.923 2.896 l
+61.998 2.896 l
+61.998 3.513 l
+63.835 3.513 l
+h
+68.998 0.485 m
+68.998 0.21 68.961 -0.04 68.895 -0.264 c
+68.824 -0.482 68.722 -0.669 68.586 -0.823 c
+68.446 -0.981 68.27 -1.103 68.057 -1.191 c
+67.84 -1.278 67.586 -1.323 67.293 -1.323 c
+67.017 -1.323 66.771 -1.278 66.557 -1.191 c
+66.352 -1.103 66.179 -0.981 66.043 -0.823 c
+65.903 -0.669 65.801 -0.482 65.734 -0.264 c
+65.665 -0.04 65.632 0.21 65.632 0.485 c
+65.632 0.738 65.661 0.974 65.72 1.191 c
+65.786 1.415 65.888 1.606 66.029 1.764 c
+66.164 1.929 66.341 2.058 66.557 2.146 c
+66.771 2.234 67.028 2.278 67.322 2.278 c
+67.634 2.278 67.895 2.234 68.101 2.146 c
+68.314 2.058 68.487 1.929 68.616 1.764 c
+68.751 1.606 68.851 1.415 68.909 1.191 c
+68.968 0.974 68.998 0.738 68.998 0.485 c
+68.042 0.485 m
+68.042 0.69 68.028 0.867 67.999 1.014 c
+67.976 1.161 67.939 1.282 67.881 1.382 c
+67.822 1.477 67.748 1.548 67.66 1.588 c
+67.571 1.635 67.461 1.661 67.336 1.661 c
+67.072 1.661 66.881 1.562 66.763 1.367 c
+66.646 1.18 66.587 0.885 66.587 0.485 c
+66.587 0.062 66.646 -0.243 66.763 -0.426 c
+66.881 -0.613 67.058 -0.706 67.293 -0.706 c
+67.417 -0.706 67.531 -0.687 67.631 -0.646 c
+67.726 -0.599 67.807 -0.526 67.866 -0.426 c
+67.932 -0.331 67.976 -0.206 67.999 -0.058 c
+68.028 0.088 68.042 0.268 68.042 0.485 c
+69.854 -1.264 m
+69.854 -0.97 l
+69.861 -0.834 69.869 -0.676 69.869 -0.5 c
+69.869 3.513 l
+70.78 3.513 l
+70.78 2.234 l
+70.78 2.072 l
+70.78 1.897 l
+70.78 1.845 70.773 1.801 70.765 1.764 c
+70.765 1.675 l
+70.78 1.675 l
+70.827 1.783 70.89 1.874 70.971 1.955 c
+71.048 2.032 71.133 2.095 71.221 2.146 c
+71.309 2.194 71.401 2.227 71.5 2.249 c
+71.596 2.267 71.695 2.278 71.794 2.278 c
+72.007 2.278 72.194 2.234 72.352 2.146 c
+72.507 2.058 72.635 1.929 72.735 1.764 c
+72.841 1.606 72.919 1.415 72.97 1.191 c
+73.017 0.974 73.044 0.735 73.044 0.47 c
+73.044 0.214 73.015 -0.025 72.955 -0.25 c
+72.897 -0.467 72.812 -0.658 72.705 -0.823 c
+72.595 -0.981 72.463 -1.103 72.309 -1.191 c
+72.151 -1.278 71.97 -1.323 71.764 -1.323 c
+71.666 -1.323 71.567 -1.311 71.471 -1.293 c
+71.382 -1.272 71.294 -1.242 71.206 -1.191 c
+71.118 -1.132 71.037 -1.066 70.971 -0.985 c
+70.901 -0.908 70.839 -0.808 70.78 -0.69 c
+70.765 -0.69 l
+70.765 -0.852 l
+70.765 -0.912 70.758 -0.97 70.75 -1.029 c
+70.75 -1.08 70.743 -1.128 70.736 -1.176 c
+70.736 -1.216 70.729 -1.246 70.721 -1.264 c
+h
+70.765 0.5 m
+70.765 0.264 70.783 0.066 70.824 -0.088 c
+70.872 -0.246 70.931 -0.368 71 -0.455 c
+71.066 -0.544 71.14 -0.61 71.221 -0.646 c
+71.298 -0.687 71.375 -0.706 71.456 -0.706 c
+71.662 -0.706 71.816 -0.61 71.926 -0.411 c
+72.044 -0.216 72.103 0.077 72.103 0.47 c
+72.103 0.684 72.08 0.867 72.044 1.014 c
+72.015 1.168 71.97 1.294 71.912 1.382 c
+71.86 1.477 71.794 1.55 71.706 1.602 c
+71.625 1.65 71.537 1.675 71.442 1.675 c
+71.361 1.675 71.284 1.654 71.206 1.617 c
+71.126 1.577 71.052 1.514 70.985 1.426 c
+70.927 1.338 70.872 1.213 70.824 1.058 c
+70.783 0.912 70.765 0.724 70.765 0.5 c
+74.873 -1.323 m
+74.704 -1.323 74.554 -1.301 74.418 -1.264 c
+74.289 -1.216 74.175 -1.147 74.079 -1.058 c
+73.992 -0.97 73.921 -0.864 73.874 -0.735 c
+73.823 -0.599 73.8 -0.449 73.8 -0.279 c
+73.8 -0.073 73.834 0.096 73.904 0.235 c
+73.969 0.382 74.065 0.492 74.183 0.573 c
+74.308 0.661 74.451 0.724 74.609 0.765 c
+74.775 0.802 74.951 0.827 75.138 0.838 c
+75.858 0.852 l
+75.858 1.029 l
+75.858 1.147 75.847 1.249 75.829 1.338 c
+75.807 1.426 75.774 1.492 75.726 1.544 c
+75.685 1.602 75.638 1.639 75.579 1.661 c
+75.521 1.679 75.454 1.691 75.388 1.691 c
+75.318 1.691 75.255 1.679 75.197 1.661 c
+75.145 1.65 75.097 1.625 75.05 1.588 c
+75.01 1.558 74.976 1.507 74.947 1.44 c
+74.925 1.382 74.91 1.301 74.903 1.205 c
+73.962 1.249 l
+73.992 1.396 74.035 1.532 74.095 1.661 c
+74.16 1.786 74.256 1.897 74.374 1.984 c
+74.492 2.08 74.631 2.153 74.8 2.205 c
+74.976 2.253 75.182 2.278 75.417 2.278 c
+75.858 2.278 76.19 2.168 76.417 1.955 c
+76.652 1.749 76.77 1.44 76.77 1.029 c
+76.77 -0.235 l
+76.77 -0.455 l
+76.777 -0.515 76.792 -0.569 76.814 -0.617 c
+76.832 -0.658 76.861 -0.69 76.902 -0.721 c
+76.938 -0.742 76.99 -0.75 77.049 -0.75 c
+77.115 -0.75 77.185 -0.746 77.254 -0.735 c
+77.254 -1.22 l
+77.196 -1.231 77.141 -1.242 77.093 -1.249 c
+77.053 -1.261 77.013 -1.268 76.976 -1.278 c
+76.936 -1.286 76.891 -1.293 76.843 -1.293 c
+76.792 -1.301 76.733 -1.309 76.666 -1.309 c
+76.439 -1.309 76.273 -1.257 76.167 -1.147 c
+76.057 -1.029 75.995 -0.864 75.976 -0.646 c
+75.961 -0.646 l
+75.891 -0.757 75.822 -0.852 75.756 -0.941 c
+75.685 -1.022 75.608 -1.087 75.521 -1.147 c
+75.432 -1.205 75.333 -1.249 75.226 -1.278 c
+75.127 -1.309 75.01 -1.323 74.873 -1.323 c
+75.858 0.353 m
+75.432 0.338 l
+75.333 0.338 75.241 0.331 75.153 0.324 c
+75.072 0.312 75.006 0.287 74.947 0.25 c
+74.889 0.21 74.837 0.151 74.8 0.073 c
+74.76 0.004 74.741 -0.088 74.741 -0.206 c
+74.741 -0.374 74.775 -0.496 74.844 -0.573 c
+74.91 -0.654 75.01 -0.69 75.138 -0.69 c
+75.245 -0.69 75.344 -0.669 75.432 -0.617 c
+75.527 -0.569 75.608 -0.507 75.667 -0.426 c
+75.733 -0.349 75.785 -0.261 75.814 -0.162 c
+75.843 -0.056 75.858 0.059 75.858 0.177 c
+h
+80.08 -0.646 m
+81.212 -0.646 l
+81.212 -1.264 l
+77.905 -1.264 l
+77.905 -0.646 l
+79.17 -0.646 l
+79.17 2.896 l
+78.243 2.896 l
+78.243 3.513 l
+80.08 3.513 l
+h
+87.658 -1.323 m
+87.371 -1.323 87.128 -1.282 86.923 -1.205 c
+86.717 -1.117 86.544 -0.996 86.409 -0.838 c
+86.269 -0.684 86.166 -0.496 86.1 -0.279 c
+86.03 -0.056 85.997 0.191 85.997 0.455 c
+85.997 0.75 86.03 1.007 86.1 1.235 c
+86.177 1.459 86.284 1.646 86.423 1.793 c
+86.571 1.947 86.747 2.065 86.953 2.146 c
+87.159 2.234 87.394 2.278 87.658 2.278 c
+87.882 2.278 88.084 2.249 88.261 2.19 c
+88.437 2.132 88.588 2.047 88.716 1.941 c
+88.842 1.841 88.944 1.72 89.025 1.573 c
+89.102 1.433 89.158 1.282 89.187 1.118 c
+88.275 1.073 l
+88.246 1.249 88.176 1.389 88.069 1.5 c
+87.97 1.606 87.827 1.661 87.643 1.661 c
+87.398 1.661 87.221 1.558 87.114 1.353 c
+87.004 1.154 86.953 0.867 86.953 0.485 c
+86.953 -0.309 87.188 -0.706 87.658 -0.706 c
+87.824 -0.706 87.967 -0.654 88.084 -0.544 c
+88.202 -0.437 88.275 -0.276 88.304 -0.058 c
+89.216 -0.103 l
+89.187 -0.272 89.131 -0.426 89.054 -0.573 c
+88.985 -0.721 88.882 -0.852 88.746 -0.97 c
+88.617 -1.08 88.46 -1.168 88.275 -1.234 c
+88.099 -1.293 87.893 -1.323 87.658 -1.323 c
+93.365 0.485 m
+93.365 0.21 93.328 -0.04 93.262 -0.264 c
+93.192 -0.482 93.089 -0.669 92.954 -0.823 c
+92.813 -0.981 92.637 -1.103 92.424 -1.191 c
+92.208 -1.278 91.954 -1.323 91.66 -1.323 c
+91.384 -1.323 91.138 -1.278 90.925 -1.191 c
+90.719 -1.103 90.546 -0.981 90.411 -0.823 c
+90.271 -0.669 90.168 -0.482 90.102 -0.264 c
+90.032 -0.04 89.999 0.21 89.999 0.485 c
+89.999 0.738 90.028 0.974 90.087 1.191 c
+90.153 1.415 90.256 1.606 90.396 1.764 c
+90.532 1.929 90.708 2.058 90.925 2.146 c
+91.138 2.234 91.396 2.278 91.689 2.278 c
+92.001 2.278 92.263 2.234 92.468 2.146 c
+92.682 2.058 92.854 1.929 92.983 1.764 c
+93.119 1.606 93.218 1.415 93.277 1.191 c
+93.335 0.974 93.365 0.738 93.365 0.485 c
+92.41 0.485 m
+92.41 0.69 92.395 0.867 92.366 1.014 c
+92.343 1.161 92.306 1.282 92.248 1.382 c
+92.189 1.477 92.115 1.548 92.028 1.588 c
+91.939 1.635 91.829 1.661 91.704 1.661 c
+91.439 1.661 91.248 1.562 91.13 1.367 c
+91.013 1.18 90.954 0.885 90.954 0.485 c
+90.954 0.062 91.013 -0.243 91.13 -0.426 c
+91.248 -0.613 91.425 -0.706 91.66 -0.706 c
+91.785 -0.706 91.899 -0.687 91.998 -0.646 c
+92.094 -0.599 92.175 -0.526 92.233 -0.426 c
+92.3 -0.331 92.343 -0.206 92.366 -0.058 c
+92.395 0.088 92.41 0.268 92.41 0.485 c
+96.327 -0.646 m
+97.459 -0.646 l
+97.459 -1.264 l
+94.151 -1.264 l
+94.151 -0.646 l
+95.415 -0.646 l
+95.415 2.896 l
+94.49 2.896 l
+94.49 3.513 l
+96.327 3.513 l
+h
+101.49 0.485 m
+101.49 0.21 101.453 -0.04 101.387 -0.264 c
+101.317 -0.482 101.214 -0.669 101.079 -0.823 c
+100.939 -0.981 100.763 -1.103 100.549 -1.191 c
+100.333 -1.278 100.079 -1.323 99.785 -1.323 c
+99.51 -1.323 99.263 -1.278 99.049 -1.191 c
+98.844 -1.103 98.671 -0.981 98.535 -0.823 c
+98.396 -0.669 98.293 -0.482 98.226 -0.264 c
+98.157 -0.04 98.124 0.21 98.124 0.485 c
+98.124 0.738 98.153 0.974 98.212 1.191 c
+98.278 1.415 98.381 1.606 98.521 1.764 c
+98.656 1.929 98.833 2.058 99.049 2.146 c
+99.263 2.234 99.52 2.278 99.814 2.278 c
+100.127 2.278 100.387 2.234 100.593 2.146 c
+100.807 2.058 100.979 1.929 101.108 1.764 c
+101.243 1.606 101.343 1.415 101.401 1.191 c
+101.461 0.974 101.49 0.738 101.49 0.485 c
+100.534 0.485 m
+100.534 0.69 100.52 0.867 100.491 1.014 c
+100.468 1.161 100.431 1.282 100.373 1.382 c
+100.314 1.477 100.24 1.548 100.152 1.588 c
+100.064 1.635 99.954 1.661 99.828 1.661 c
+99.564 1.661 99.373 1.562 99.256 1.367 c
+99.138 1.18 99.08 0.885 99.08 0.485 c
+99.08 0.062 99.138 -0.243 99.256 -0.426 c
+99.373 -0.613 99.55 -0.706 99.785 -0.706 c
+99.909 -0.706 100.024 -0.687 100.123 -0.646 c
+100.219 -0.599 100.299 -0.526 100.358 -0.426 c
+100.424 -0.331 100.468 -0.206 100.491 -0.058 c
+100.52 0.088 100.534 0.268 100.534 0.485 c
+105.359 1.47 m
+105.26 1.477 105.158 1.488 105.05 1.5 c
+104.94 1.517 104.819 1.529 104.684 1.529 c
+104.507 1.529 104.349 1.488 104.213 1.411 c
+104.073 1.341 103.955 1.242 103.86 1.118 c
+103.772 0.989 103.702 0.842 103.654 0.676 c
+103.614 0.507 103.595 0.331 103.595 0.147 c
+103.595 -1.264 l
+102.699 -1.264 l
+102.699 0.985 l
+102.699 1.11 102.688 1.235 102.669 1.353 c
+102.658 1.477 102.644 1.595 102.625 1.706 c
+102.614 1.823 102.6 1.918 102.581 1.999 c
+102.559 2.087 102.541 2.161 102.523 2.219 c
+103.404 2.219 l
+103.412 2.168 103.423 2.117 103.433 2.058 c
+103.452 1.999 103.467 1.933 103.478 1.866 c
+103.496 1.808 103.511 1.742 103.522 1.675 c
+103.529 1.606 103.541 1.544 103.552 1.484 c
+103.566 1.484 l
+103.603 1.602 103.654 1.708 103.713 1.808 c
+103.78 1.903 103.86 1.988 103.948 2.058 c
+104.036 2.124 104.139 2.179 104.257 2.219 c
+104.382 2.256 104.529 2.278 104.698 2.278 c
+104.823 2.278 104.94 2.271 105.05 2.263 c
+105.168 2.253 105.272 2.238 105.359 2.219 c
+h
+107.465 -0.279 0.926 -0.985 re
+107.465 -1.264 m
+111.35 2.219 m
+111.35 0.264 l
+111.35 0.125 111.356 0 111.379 -0.118 c
+111.397 -0.228 111.43 -0.32 111.481 -0.397 c
+111.529 -0.478 111.588 -0.54 111.658 -0.588 c
+111.724 -0.628 111.809 -0.646 111.908 -0.646 c
+111.996 -0.646 112.077 -0.628 112.158 -0.588 c
+112.246 -0.54 112.32 -0.47 112.378 -0.382 c
+112.437 -0.287 112.481 -0.176 112.511 -0.058 c
+112.547 0.066 112.569 0.206 112.569 0.353 c
+112.569 2.219 l
+113.466 2.219 l
+113.466 -0.485 l
+113.466 -0.721 l
+113.473 -0.802 113.48 -0.879 113.48 -0.956 c
+113.48 -1.147 l
+113.488 -1.198 113.495 -1.234 113.495 -1.264 c
+112.643 -1.264 l
+112.632 -1.234 112.621 -1.198 112.613 -1.147 c
+112.613 -0.956 l
+112.613 -0.889 112.606 -0.819 112.599 -0.75 c
+112.599 -0.573 l
+112.584 -0.573 l
+112.466 -0.838 112.312 -1.029 112.129 -1.147 c
+111.952 -1.264 111.749 -1.323 111.526 -1.323 c
+111.32 -1.323 111.147 -1.286 111.011 -1.22 c
+110.872 -1.154 110.762 -1.058 110.673 -0.941 c
+110.592 -0.823 110.533 -0.687 110.496 -0.529 c
+110.467 -0.364 110.452 -0.187 110.452 0 c
+110.452 2.219 l
+h
+116.634 -0.646 m
+117.766 -0.646 l
+117.766 -1.264 l
+114.458 -1.264 l
+114.458 -0.646 l
+115.722 -0.646 l
+115.722 1.602 l
+114.797 1.602 l
+114.797 2.219 l
+116.634 2.219 l
+h
+115.722 3.513 0.912 -0.675 re
+115.722 2.837 m
+123.608 -1.323 m
+123.439 -1.323 123.289 -1.301 123.152 -1.264 c
+123.024 -1.216 122.91 -1.147 122.814 -1.058 c
+122.726 -0.97 122.656 -0.864 122.608 -0.735 c
+122.558 -0.599 122.535 -0.449 122.535 -0.279 c
+122.535 -0.073 122.568 0.096 122.639 0.235 c
+122.704 0.382 122.799 0.492 122.917 0.573 c
+123.042 0.661 123.186 0.724 123.344 0.765 c
+123.509 0.802 123.686 0.827 123.873 0.838 c
+124.593 0.852 l
+124.593 1.029 l
+124.593 1.147 124.582 1.249 124.563 1.338 c
+124.542 1.426 124.509 1.492 124.461 1.544 c
+124.42 1.602 124.372 1.639 124.314 1.661 c
+124.255 1.679 124.189 1.691 124.123 1.691 c
+124.052 1.691 123.99 1.679 123.932 1.661 c
+123.88 1.65 123.832 1.625 123.784 1.588 c
+123.744 1.558 123.711 1.507 123.682 1.44 c
+123.659 1.382 123.645 1.301 123.638 1.205 c
+122.697 1.249 l
+122.726 1.396 122.77 1.532 122.829 1.661 c
+122.895 1.786 122.991 1.897 123.109 1.984 c
+123.227 2.08 123.366 2.153 123.535 2.205 c
+123.711 2.253 123.917 2.278 124.152 2.278 c
+124.593 2.278 124.924 2.168 125.151 1.955 c
+125.386 1.749 125.504 1.44 125.504 1.029 c
+125.504 -0.235 l
+125.504 -0.455 l
+125.512 -0.515 125.527 -0.569 125.548 -0.617 c
+125.567 -0.658 125.596 -0.69 125.637 -0.721 c
+125.673 -0.742 125.725 -0.75 125.783 -0.75 c
+125.85 -0.75 125.92 -0.746 125.989 -0.735 c
+125.989 -1.22 l
+125.931 -1.231 125.876 -1.242 125.828 -1.249 c
+125.787 -1.261 125.747 -1.268 125.71 -1.278 c
+125.67 -1.286 125.625 -1.293 125.578 -1.293 c
+125.527 -1.301 125.467 -1.309 125.401 -1.309 c
+125.174 -1.309 125.008 -1.257 124.902 -1.147 c
+124.792 -1.029 124.729 -0.864 124.711 -0.646 c
+124.696 -0.646 l
+124.626 -0.757 124.557 -0.852 124.49 -0.941 c
+124.42 -1.022 124.343 -1.087 124.255 -1.147 c
+124.167 -1.205 124.068 -1.249 123.961 -1.278 c
+123.861 -1.309 123.744 -1.323 123.608 -1.323 c
+124.593 0.353 m
+124.167 0.338 l
+124.068 0.338 123.975 0.331 123.888 0.324 c
+123.807 0.312 123.74 0.287 123.682 0.25 c
+123.623 0.21 123.572 0.151 123.535 0.073 c
+123.495 0.004 123.476 -0.088 123.476 -0.206 c
+123.476 -0.374 123.509 -0.496 123.579 -0.573 c
+123.645 -0.654 123.744 -0.69 123.873 -0.69 c
+123.979 -0.69 124.079 -0.669 124.167 -0.617 c
+124.262 -0.569 124.343 -0.507 124.402 -0.426 c
+124.468 -0.349 124.52 -0.261 124.549 -0.162 c
+124.578 -0.056 124.593 0.059 124.593 0.177 c
+h
+127.595 2.219 m
+127.595 0.264 l
+127.595 0.125 127.603 0 127.624 -0.118 c
+127.643 -0.228 127.676 -0.32 127.728 -0.397 c
+127.776 -0.478 127.834 -0.54 127.904 -0.588 c
+127.971 -0.628 128.054 -0.646 128.154 -0.646 c
+128.243 -0.646 128.323 -0.628 128.403 -0.588 c
+128.492 -0.54 128.565 -0.47 128.624 -0.382 c
+128.683 -0.287 128.727 -0.176 128.756 -0.058 c
+128.794 0.066 128.815 0.206 128.815 0.353 c
+128.815 2.219 l
+129.712 2.219 l
+129.712 -0.485 l
+129.712 -0.721 l
+129.719 -0.802 129.727 -0.879 129.727 -0.956 c
+129.727 -1.147 l
+129.735 -1.198 129.741 -1.234 129.741 -1.264 c
+128.889 -1.264 l
+128.878 -1.234 128.867 -1.198 128.86 -1.147 c
+128.86 -0.956 l
+128.86 -0.889 128.852 -0.819 128.845 -0.75 c
+128.845 -0.573 l
+128.83 -0.573 l
+128.713 -0.838 128.559 -1.029 128.374 -1.147 c
+128.198 -1.264 127.996 -1.323 127.772 -1.323 c
+127.566 -1.323 127.393 -1.286 127.258 -1.22 c
+127.117 -1.154 127.007 -1.058 126.919 -0.941 c
+126.838 -0.823 126.78 -0.687 126.743 -0.529 c
+126.714 -0.364 126.699 -0.187 126.699 0 c
+126.699 2.219 l
+h
+131.377 1.602 m
+130.833 1.602 l
+130.833 2.219 l
+131.42 2.219 l
+131.7 3.117 l
+132.274 3.117 l
+132.274 2.219 l
+133.508 2.219 l
+133.508 1.602 l
+132.274 1.602 l
+132.274 -0.103 l
+132.274 -0.324 l
+132.281 -0.393 132.303 -0.455 132.332 -0.515 c
+132.369 -0.566 132.424 -0.61 132.494 -0.646 c
+132.571 -0.676 132.685 -0.69 132.831 -0.69 c
+132.968 -0.69 133.104 -0.687 133.243 -0.676 c
+133.38 -0.658 133.512 -0.632 133.64 -0.603 c
+133.64 -1.205 l
+133.56 -1.216 133.482 -1.231 133.405 -1.249 c
+133.324 -1.261 133.247 -1.268 133.17 -1.278 c
+133.089 -1.286 133.001 -1.293 132.906 -1.293 c
+132.817 -1.301 132.718 -1.309 132.611 -1.309 c
+132.424 -1.309 132.262 -1.293 132.126 -1.264 c
+131.998 -1.228 131.884 -1.183 131.788 -1.132 c
+131.7 -1.084 131.626 -1.025 131.568 -0.956 c
+131.509 -0.879 131.465 -0.802 131.435 -0.721 c
+131.406 -0.632 131.384 -0.544 131.377 -0.455 c
+131.366 -0.36 131.362 -0.264 131.362 -0.176 c
+h
+138.043 0.485 m
+138.043 0.21 138.006 -0.04 137.94 -0.264 c
+137.87 -0.482 137.768 -0.669 137.631 -0.823 c
+137.492 -0.981 137.315 -1.103 137.102 -1.191 c
+136.885 -1.278 136.632 -1.323 136.338 -1.323 c
+136.062 -1.323 135.815 -1.278 135.603 -1.191 c
+135.397 -1.103 135.224 -0.981 135.088 -0.823 c
+134.948 -0.669 134.846 -0.482 134.78 -0.264 c
+134.71 -0.04 134.676 0.21 134.676 0.485 c
+134.676 0.738 134.706 0.974 134.765 1.191 c
+134.831 1.415 134.934 1.606 135.073 1.764 c
+135.21 1.929 135.386 2.058 135.603 2.146 c
+135.815 2.234 136.073 2.278 136.367 2.278 c
+136.679 2.278 136.941 2.234 137.146 2.146 c
+137.359 2.058 137.532 1.929 137.66 1.764 c
+137.797 1.606 137.895 1.415 137.955 1.191 c
+138.013 0.974 138.043 0.738 138.043 0.485 c
+137.087 0.485 m
+137.087 0.69 137.072 0.867 137.043 1.014 c
+137.022 1.161 136.985 1.282 136.926 1.382 c
+136.867 1.477 136.793 1.548 136.705 1.588 c
+136.617 1.635 136.507 1.661 136.382 1.661 c
+136.117 1.661 135.926 1.562 135.809 1.367 c
+135.691 1.18 135.632 0.885 135.632 0.485 c
+135.632 0.062 135.691 -0.243 135.809 -0.426 c
+135.926 -0.613 136.102 -0.706 136.338 -0.706 c
+136.463 -0.706 136.577 -0.687 136.675 -0.646 c
+136.771 -0.599 136.852 -0.526 136.91 -0.426 c
+136.977 -0.331 137.022 -0.206 137.043 -0.058 c
+137.072 0.088 137.087 0.268 137.087 0.485 c
+f
+Q
+q 1 0 0 1 156.4026 334.0088 cm
+0 0 m
+-1.897 0 l
+-1.897 -1.896 l
+0.309 -1.896 l
+0.309 -2.469 l
+-2.573 -2.469 l
+-2.573 2.881 l
+0.278 2.881 l
+0.278 2.308 l
+-1.897 2.308 l
+-1.897 0.588 l
+0 0.588 l
+h
+1.69 1.515 m
+1.705 1.073 l
+1.959 1.415 2.281 1.588 2.675 1.588 c
+3.38 1.588 3.737 1.118 3.748 0.177 c
+3.748 -2.469 l
+3.101 -2.469 l
+3.101 0.147 l
+3.101 0.459 3.046 0.68 2.939 0.809 c
+2.829 0.933 2.675 1 2.468 1 c
+2.311 1 2.164 0.944 2.028 0.838 c
+1.899 0.728 1.797 0.592 1.72 0.426 c
+1.72 -2.469 l
+1.072 -2.469 l
+1.072 1.515 l
+h
+6.761 -2.469 m
+6.721 -2.381 6.695 -2.234 6.688 -2.028 c
+6.453 -2.374 6.158 -2.543 5.805 -2.543 c
+5.442 -2.543 5.159 -2.447 4.953 -2.248 c
+4.755 -2.043 4.659 -1.756 4.659 -1.382 c
+4.659 -0.981 4.795 -0.661 5.071 -0.426 c
+5.342 -0.183 5.718 -0.058 6.188 -0.058 c
+6.673 -0.058 l
+6.673 0.368 l
+6.673 0.603 6.618 0.769 6.511 0.867 c
+6.401 0.974 6.239 1.029 6.026 1.029 c
+5.828 1.029 5.666 0.97 5.541 0.852 c
+5.423 0.735 5.365 0.588 5.365 0.412 c
+4.718 0.412 l
+4.718 0.607 4.777 0.798 4.895 0.985 c
+5.019 1.168 5.181 1.316 5.379 1.426 c
+5.585 1.532 5.813 1.588 6.071 1.588 c
+6.47 1.588 6.776 1.484 6.981 1.279 c
+7.195 1.073 7.309 0.779 7.32 0.397 c
+7.32 -1.617 l
+7.32 -1.922 7.357 -2.186 7.437 -2.41 c
+7.437 -2.469 l
+h
+5.894 -1.955 m
+6.059 -1.955 6.21 -1.911 6.35 -1.822 c
+6.497 -1.735 6.603 -1.624 6.673 -1.484 c
+6.673 -0.544 l
+6.306 -0.544 l
+5.99 -0.544 5.747 -0.613 5.57 -0.75 c
+5.394 -0.878 5.306 -1.066 5.306 -1.308 c
+5.306 -1.536 5.35 -1.701 5.438 -1.808 c
+5.526 -1.907 5.677 -1.955 5.894 -1.955 c
+11.2 -0.676 m
+11.2 -1.294 11.087 -1.76 10.862 -2.072 c
+10.645 -2.389 10.322 -2.543 9.892 -2.543 c
+9.469 -2.543 9.157 -2.363 8.951 -1.999 c
+8.922 -2.469 l
+8.319 -2.469 l
+8.319 3.175 l
+8.966 3.175 l
+8.966 1.073 l
+9.179 1.415 9.487 1.588 9.892 1.588 c
+10.322 1.588 10.645 1.43 10.862 1.118 c
+11.087 0.812 11.2 0.345 11.2 -0.279 c
+h
+10.553 -0.294 m
+10.553 0.177 10.484 0.507 10.348 0.706 c
+10.219 0.9 10.009 1 9.716 1 c
+9.381 1 9.132 0.816 8.966 0.456 c
+8.966 -1.425 l
+9.132 -1.789 9.385 -1.97 9.73 -1.97 c
+10.025 -1.97 10.233 -1.866 10.362 -1.66 c
+10.487 -1.455 10.553 -1.139 10.553 -0.706 c
+h
+12.743 -2.469 -0.646 5.644 re
+15.184 -2.543 m
+14.684 -2.543 14.302 -2.396 14.037 -2.102 c
+13.772 -1.808 13.641 -1.374 13.641 -0.794 c
+13.641 -0.324 l
+13.641 0.272 13.765 0.738 14.023 1.073 c
+14.287 1.415 14.647 1.588 15.11 1.588 c
+15.569 1.588 15.912 1.434 16.139 1.132 c
+16.374 0.838 16.496 0.375 16.506 -0.249 c
+16.506 -0.676 l
+14.287 -0.676 l
+14.287 -0.764 l
+14.287 -1.198 14.364 -1.51 14.522 -1.705 c
+14.688 -1.893 14.919 -1.984 15.213 -1.984 c
+15.407 -1.984 15.581 -1.951 15.727 -1.882 c
+15.874 -1.804 16.01 -1.687 16.139 -1.529 c
+16.477 -1.94 l
+16.19 -2.344 15.76 -2.543 15.184 -2.543 c
+15.11 1.029 m
+14.835 1.029 14.632 0.933 14.507 0.75 c
+14.379 0.563 14.306 0.272 14.287 -0.118 c
+15.86 -0.118 l
+15.86 -0.029 l
+15.837 0.353 15.771 0.621 15.654 0.779 c
+15.536 0.944 15.353 1.029 15.11 1.029 c
+20.946 -1.455 m
+20.946 -1.308 20.891 -1.187 20.784 -1.088 c
+20.674 -0.993 20.468 -0.875 20.167 -0.735 c
+19.821 -0.588 19.579 -0.467 19.432 -0.367 c
+19.285 -0.261 19.174 -0.143 19.108 -0.014 c
+19.039 0.11 19.006 0.268 19.006 0.456 c
+19.006 0.779 19.123 1.047 19.359 1.264 c
+19.594 1.477 19.895 1.588 20.269 1.588 c
+20.652 1.588 20.961 1.474 21.196 1.249 c
+21.431 1.022 21.549 0.735 21.549 0.382 c
+20.901 0.382 l
+20.901 0.559 20.843 0.709 20.725 0.838 c
+20.608 0.963 20.454 1.029 20.269 1.029 c
+20.071 1.029 19.92 0.974 19.814 0.867 c
+19.704 0.769 19.652 0.636 19.652 0.47 c
+19.652 0.341 19.689 0.235 19.77 0.147 c
+19.847 0.066 20.038 -0.037 20.343 -0.162 c
+20.82 -0.349 21.152 -0.536 21.327 -0.72 c
+21.504 -0.897 21.593 -1.124 21.593 -1.396 c
+21.593 -1.749 21.468 -2.028 21.225 -2.234 c
+20.99 -2.44 20.674 -2.543 20.284 -2.543 c
+19.862 -2.543 19.523 -2.425 19.27 -2.19 c
+19.012 -1.947 18.888 -1.643 18.888 -1.278 c
+19.534 -1.278 l
+19.542 -1.506 19.612 -1.683 19.74 -1.808 c
+19.866 -1.926 20.049 -1.984 20.284 -1.984 c
+20.498 -1.984 20.659 -1.936 20.77 -1.837 c
+20.887 -1.741 20.946 -1.613 20.946 -1.455 c
+22.298 -0.294 m
+22.298 0.283 22.434 0.738 22.709 1.073 c
+22.993 1.415 23.363 1.588 23.827 1.588 c
+24.286 1.588 24.654 1.419 24.93 1.087 c
+25.212 0.765 25.36 0.316 25.37 -0.249 c
+25.37 -0.676 l
+25.37 -1.246 25.227 -1.701 24.944 -2.043 c
+24.668 -2.377 24.301 -2.543 23.841 -2.543 c
+23.378 -2.543 23.008 -2.381 22.724 -2.057 c
+22.449 -1.727 22.305 -1.286 22.298 -0.735 c
+h
+22.945 -0.676 m
+22.945 -1.08 23.022 -1.396 23.18 -1.631 c
+23.345 -1.866 23.566 -1.984 23.841 -1.984 c
+24.407 -1.984 24.701 -1.573 24.724 -0.75 c
+24.724 -0.294 l
+24.724 0.106 24.639 0.426 24.473 0.661 c
+24.315 0.904 24.099 1.029 23.827 1.029 c
+23.562 1.029 23.345 0.904 23.18 0.661 c
+23.022 0.426 22.945 0.106 22.945 -0.294 c
+h
+26.825 1.515 m
+26.84 1.147 l
+27.083 1.44 27.402 1.588 27.795 1.588 c
+28.236 1.588 28.545 1.389 28.722 1 c
+28.975 1.389 29.324 1.588 29.765 1.588 c
+30.5 1.588 30.875 1.124 30.897 0.206 c
+30.897 -2.469 l
+30.25 -2.469 l
+30.25 0.147 l
+30.25 0.441 30.195 0.654 30.089 0.794 c
+29.989 0.929 29.817 1 29.574 1 c
+29.376 1 29.214 0.919 29.089 0.765 c
+28.971 0.617 28.901 0.426 28.884 0.191 c
+28.884 -2.469 l
+28.222 -2.469 l
+28.222 0.177 l
+28.222 0.724 28.001 1 27.56 1 c
+27.226 1 26.991 0.838 26.854 0.515 c
+26.854 -2.469 l
+26.208 -2.469 l
+26.208 1.515 l
+h
+33.293 -2.543 m
+32.793 -2.543 32.411 -2.396 32.146 -2.102 c
+31.882 -1.808 31.75 -1.374 31.75 -0.794 c
+31.75 -0.324 l
+31.75 0.272 31.874 0.738 32.132 1.073 c
+32.396 1.415 32.757 1.588 33.219 1.588 c
+33.678 1.588 34.021 1.434 34.249 1.132 c
+34.484 0.838 34.605 0.375 34.615 -0.249 c
+34.615 -0.676 l
+32.396 -0.676 l
+32.396 -0.764 l
+32.396 -1.198 32.473 -1.51 32.631 -1.705 c
+32.797 -1.893 33.028 -1.984 33.322 -1.984 c
+33.517 -1.984 33.69 -1.951 33.837 -1.882 c
+33.983 -1.804 34.12 -1.687 34.249 -1.529 c
+34.586 -1.94 l
+34.299 -2.344 33.869 -2.543 33.293 -2.543 c
+33.219 1.029 m
+32.944 1.029 32.742 0.933 32.616 0.75 c
+32.488 0.563 32.415 0.272 32.396 -0.118 c
+33.969 -0.118 l
+33.969 -0.029 l
+33.947 0.353 33.881 0.621 33.763 0.779 c
+33.646 0.944 33.462 1.029 33.219 1.029 c
+38.496 -1.984 m
+38.71 -1.984 38.883 -1.922 39.011 -1.793 c
+39.147 -1.658 39.22 -1.466 39.232 -1.22 c
+39.849 -1.22 l
+39.826 -1.602 39.691 -1.922 39.437 -2.175 c
+39.18 -2.421 38.868 -2.543 38.496 -2.543 c
+38.004 -2.543 37.63 -2.392 37.364 -2.088 c
+37.107 -1.775 36.982 -1.308 36.982 -0.691 c
+36.982 -0.249 l
+36.982 0.345 37.107 0.801 37.364 1.118 c
+37.63 1.43 38.004 1.588 38.496 1.588 c
+38.897 1.588 39.217 1.455 39.452 1.191 c
+39.694 0.933 39.826 0.588 39.849 0.147 c
+39.232 0.147 l
+39.209 0.441 39.136 0.661 39.011 0.809 c
+38.893 0.956 38.721 1.029 38.496 1.029 c
+38.202 1.029 37.985 0.929 37.85 0.735 c
+37.71 0.547 37.636 0.239 37.63 -0.191 c
+37.63 -0.706 l
+37.63 -1.176 37.695 -1.51 37.835 -1.705 c
+37.981 -1.893 38.202 -1.984 38.496 -1.984 c
+40.466 -0.294 m
+40.466 0.283 40.602 0.738 40.878 1.073 c
+41.16 1.415 41.532 1.588 41.995 1.588 c
+42.454 1.588 42.822 1.419 43.097 1.087 c
+43.38 0.765 43.527 0.316 43.538 -0.249 c
+43.538 -0.676 l
+43.538 -1.246 43.394 -1.701 43.112 -2.043 c
+42.837 -2.377 42.469 -2.543 42.01 -2.543 c
+41.547 -2.543 41.175 -2.381 40.892 -2.057 c
+40.616 -1.727 40.473 -1.286 40.466 -0.735 c
+h
+41.113 -0.676 m
+41.113 -1.08 41.19 -1.396 41.348 -1.631 c
+41.513 -1.866 41.734 -1.984 42.01 -1.984 c
+42.575 -1.984 42.869 -1.573 42.891 -0.75 c
+42.891 -0.294 l
+42.891 0.106 42.806 0.426 42.642 0.661 c
+42.484 0.904 42.266 1.029 41.995 1.029 c
+41.73 1.029 41.513 0.904 41.348 0.661 c
+41.19 0.426 41.113 0.106 41.113 -0.294 c
+h
+45.081 -2.469 -0.646 5.644 re
+45.964 -0.294 m
+45.964 0.283 46.099 0.738 46.375 1.073 c
+46.658 1.415 47.029 1.588 47.492 1.588 c
+47.951 1.588 48.319 1.419 48.595 1.087 c
+48.878 0.765 49.025 0.316 49.035 -0.249 c
+49.035 -0.676 l
+49.035 -1.246 48.892 -1.701 48.609 -2.043 c
+48.333 -2.377 47.966 -2.543 47.507 -2.543 c
+47.044 -2.543 46.673 -2.381 46.39 -2.057 c
+46.114 -1.727 45.971 -1.286 45.964 -0.735 c
+h
+46.61 -0.676 m
+46.61 -1.08 46.687 -1.396 46.845 -1.631 c
+47.011 -1.866 47.232 -1.984 47.507 -1.984 c
+48.073 -1.984 48.367 -1.573 48.389 -0.75 c
+48.389 -0.294 l
+48.389 0.106 48.304 0.426 48.139 0.661 c
+47.981 0.904 47.764 1.029 47.492 1.029 c
+47.228 1.029 47.011 0.904 46.845 0.661 c
+46.687 0.426 46.61 0.106 46.61 -0.294 c
+h
+51.52 0.896 m
+51.431 0.915 51.332 0.927 51.226 0.927 c
+50.891 0.927 50.656 0.742 50.521 0.382 c
+50.521 -2.469 l
+49.873 -2.469 l
+49.873 1.515 l
+50.505 1.515 l
+50.521 1.103 l
+50.696 1.426 50.939 1.588 51.255 1.588 c
+51.362 1.588 51.45 1.565 51.52 1.529 c
+h
+52.872 -2.469 -0.647 3.984 re
+52.917 2.558 m
+52.917 2.448 52.886 2.356 52.828 2.278 c
+52.769 2.209 52.674 2.176 52.549 2.176 c
+52.431 2.176 52.335 2.209 52.269 2.278 c
+52.211 2.356 52.181 2.448 52.181 2.558 c
+52.181 2.675 52.211 2.768 52.269 2.837 c
+52.335 2.914 52.431 2.955 52.549 2.955 c
+52.674 2.955 52.769 2.914 52.828 2.837 c
+52.886 2.756 52.917 2.664 52.917 2.558 c
+54.489 -1.911 m
+56.414 -1.911 l
+56.414 -2.469 l
+53.754 -2.469 l
+53.754 -1.97 l
+55.577 0.941 l
+53.769 0.941 l
+53.769 1.515 l
+56.341 1.515 l
+56.341 1.029 l
+h
+59.236 -2.469 m
+59.196 -2.381 59.171 -2.234 59.163 -2.028 c
+58.928 -2.374 58.634 -2.543 58.282 -2.543 c
+57.918 -2.543 57.634 -2.447 57.428 -2.248 c
+57.23 -2.043 57.135 -1.756 57.135 -1.382 c
+57.135 -0.981 57.27 -0.661 57.546 -0.426 c
+57.818 -0.183 58.193 -0.058 58.664 -0.058 c
+59.148 -0.058 l
+59.148 0.368 l
+59.148 0.603 59.093 0.769 58.987 0.867 c
+58.876 0.974 58.715 1.029 58.502 1.029 c
+58.303 1.029 58.141 0.97 58.016 0.852 c
+57.899 0.735 57.84 0.588 57.84 0.412 c
+57.193 0.412 l
+57.193 0.607 57.252 0.798 57.37 0.985 c
+57.495 1.168 57.657 1.316 57.855 1.426 c
+58.061 1.532 58.288 1.588 58.546 1.588 c
+58.947 1.588 59.252 1.484 59.458 1.279 c
+59.67 1.073 59.784 0.779 59.795 0.397 c
+59.795 -1.617 l
+59.795 -1.922 59.832 -2.186 59.913 -2.41 c
+59.913 -2.469 l
+h
+58.369 -1.955 m
+58.535 -1.955 58.685 -1.911 58.825 -1.822 c
+58.972 -1.735 59.078 -1.624 59.148 -1.484 c
+59.148 -0.544 l
+58.781 -0.544 l
+58.465 -0.544 58.222 -0.613 58.046 -0.75 c
+57.87 -0.878 57.781 -1.066 57.781 -1.308 c
+57.781 -1.536 57.825 -1.701 57.914 -1.808 c
+58.002 -1.907 58.153 -1.955 58.369 -1.955 c
+61.648 2.469 m
+61.648 1.515 l
+62.25 1.515 l
+62.25 0.985 l
+61.648 0.985 l
+61.648 -1.484 l
+61.648 -1.643 61.669 -1.76 61.721 -1.837 c
+61.779 -1.918 61.868 -1.955 61.985 -1.955 c
+62.074 -1.955 62.162 -1.94 62.25 -1.911 c
+62.25 -2.469 l
+62.103 -2.517 61.949 -2.543 61.794 -2.543 c
+61.538 -2.543 61.343 -2.451 61.206 -2.263 c
+61.067 -2.08 61 -1.818 61 -1.484 c
+61 0.985 l
+60.398 0.985 l
+60.398 1.515 l
+61 1.515 l
+61 2.469 l
+h
+63.72 -2.469 -0.647 3.984 re
+63.764 2.558 m
+63.764 2.448 63.735 2.356 63.676 2.278 c
+63.617 2.209 63.522 2.176 63.396 2.176 c
+63.279 2.176 63.184 2.209 63.117 2.278 c
+63.059 2.356 63.03 2.448 63.03 2.558 c
+63.03 2.675 63.059 2.768 63.117 2.837 c
+63.184 2.914 63.279 2.955 63.396 2.955 c
+63.522 2.955 63.617 2.914 63.676 2.837 c
+63.735 2.756 63.764 2.664 63.764 2.558 c
+64.602 -0.294 m
+64.602 0.283 64.738 0.738 65.014 1.073 c
+65.297 1.415 65.667 1.588 66.13 1.588 c
+66.59 1.588 66.957 1.419 67.233 1.087 c
+67.516 0.765 67.663 0.316 67.674 -0.249 c
+67.674 -0.676 l
+67.674 -1.246 67.531 -1.701 67.248 -2.043 c
+66.972 -2.377 66.604 -2.543 66.145 -2.543 c
+65.682 -2.543 65.311 -2.381 65.028 -2.057 c
+64.753 -1.727 64.609 -1.286 64.602 -0.735 c
+h
+65.249 -0.676 m
+65.249 -1.08 65.326 -1.396 65.484 -1.631 c
+65.65 -1.866 65.87 -1.984 66.145 -1.984 c
+66.712 -1.984 67.005 -1.573 67.028 -0.75 c
+67.028 -0.294 l
+67.028 0.106 66.943 0.426 66.777 0.661 c
+66.619 0.904 66.402 1.029 66.13 1.029 c
+65.866 1.029 65.65 0.904 65.484 0.661 c
+65.326 0.426 65.249 0.106 65.249 -0.294 c
+h
+69.129 1.515 m
+69.144 1.073 l
+69.397 1.415 69.721 1.588 70.114 1.588 c
+70.82 1.588 71.176 1.118 71.187 0.177 c
+71.187 -2.469 l
+70.54 -2.469 l
+70.54 0.147 l
+70.54 0.459 70.485 0.68 70.379 0.809 c
+70.269 0.933 70.114 1 69.908 1 c
+69.75 1 69.603 0.944 69.467 0.838 c
+69.339 0.728 69.236 0.592 69.158 0.426 c
+69.158 -2.469 l
+68.512 -2.469 l
+68.512 1.515 l
+h
+73.745 -0.294 m
+73.745 0.283 73.881 0.738 74.157 1.073 c
+74.439 1.415 74.81 1.588 75.273 1.588 c
+75.732 1.588 76.1 1.419 76.376 1.087 c
+76.659 0.765 76.806 0.316 76.817 -0.249 c
+76.817 -0.676 l
+76.817 -1.246 76.673 -1.701 76.391 -2.043 c
+76.115 -2.377 75.747 -2.543 75.288 -2.543 c
+74.825 -2.543 74.454 -2.381 74.171 -2.057 c
+73.895 -1.727 73.752 -1.286 73.745 -0.735 c
+h
+74.392 -0.676 m
+74.392 -1.08 74.469 -1.396 74.627 -1.631 c
+74.792 -1.866 75.013 -1.984 75.288 -1.984 c
+75.854 -1.984 76.148 -1.573 76.17 -0.75 c
+76.17 -0.294 l
+76.17 0.106 76.085 0.426 75.92 0.661 c
+75.762 0.904 75.545 1.029 75.273 1.029 c
+75.009 1.029 74.792 0.904 74.627 0.661 c
+74.469 0.426 74.392 0.106 74.392 -0.294 c
+h
+77.949 -2.469 m
+77.949 0.985 l
+77.419 0.985 l
+77.419 1.515 l
+77.949 1.515 l
+77.949 1.97 l
+77.949 2.371 78.044 2.683 78.242 2.911 c
+78.448 3.134 78.728 3.248 79.08 3.248 c
+79.217 3.248 79.349 3.227 79.477 3.19 c
+79.448 2.646 l
+79.349 2.664 79.25 2.675 79.154 2.675 c
+78.779 2.675 78.595 2.411 78.595 1.881 c
+78.595 1.515 l
+79.271 1.515 l
+79.271 0.985 l
+78.595 0.985 l
+78.595 -2.469 l
+h
+85.195 -1.808 m
+85.078 -1.955 l
+84.744 -2.348 84.247 -2.543 83.593 -2.543 c
+83.013 -2.543 82.556 -2.352 82.226 -1.97 c
+81.903 -1.587 81.733 -1.043 81.726 -0.338 c
+81.726 0.706 l
+81.726 1.459 81.873 2.022 82.167 2.396 c
+82.469 2.768 82.921 2.955 83.52 2.955 c
+84.027 2.955 84.424 2.811 84.71 2.529 c
+85.004 2.242 85.166 1.837 85.195 1.309 c
+84.519 1.309 l
+84.497 1.639 84.405 1.9 84.239 2.087 c
+84.081 2.282 83.846 2.381 83.534 2.381 c
+83.141 2.381 82.858 2.253 82.682 1.999 c
+82.506 1.742 82.41 1.341 82.402 0.794 c
+82.402 -0.294 l
+82.402 -0.834 82.506 -1.249 82.711 -1.543 c
+82.917 -1.83 83.211 -1.97 83.593 -1.97 c
+83.953 -1.97 84.233 -1.882 84.431 -1.705 c
+84.519 -1.617 l
+84.519 -0.382 l
+83.549 -0.382 l
+83.549 0.191 l
+85.195 0.191 l
+h
+86.915 -2.469 -0.646 3.984 re
+86.959 2.558 m
+86.959 2.448 86.93 2.356 86.871 2.278 c
+86.812 2.209 86.716 2.176 86.591 2.176 c
+86.474 2.176 86.379 2.209 86.313 2.278 c
+86.254 2.356 86.224 2.448 86.224 2.558 c
+86.224 2.675 86.254 2.768 86.313 2.837 c
+86.379 2.914 86.474 2.955 86.591 2.955 c
+86.716 2.955 86.812 2.914 86.871 2.837 c
+86.93 2.756 86.959 2.664 86.959 2.558 c
+88.781 2.469 m
+88.781 1.515 l
+89.384 1.515 l
+89.384 0.985 l
+88.781 0.985 l
+88.781 -1.484 l
+88.781 -1.643 88.804 -1.76 88.856 -1.837 c
+88.914 -1.918 89.002 -1.955 89.12 -1.955 c
+89.208 -1.955 89.296 -1.94 89.384 -1.911 c
+89.384 -2.469 l
+89.238 -2.517 89.083 -2.543 88.929 -2.543 c
+88.671 -2.543 88.477 -2.451 88.341 -2.263 c
+88.201 -2.08 88.135 -1.818 88.135 -1.484 c
+88.135 0.985 l
+87.532 0.985 l
+87.532 1.515 l
+88.135 1.515 l
+88.135 2.469 l
+h
+91.736 -0.294 m
+91.736 0.283 91.873 0.738 92.148 1.073 c
+92.43 1.415 92.802 1.588 93.265 1.588 c
+93.724 1.588 94.092 1.419 94.367 1.087 c
+94.651 0.765 94.797 0.316 94.809 -0.249 c
+94.809 -0.676 l
+94.809 -1.246 94.665 -1.701 94.382 -2.043 c
+94.107 -2.377 93.739 -2.543 93.28 -2.543 c
+92.817 -2.543 92.446 -2.381 92.162 -2.057 c
+91.887 -1.727 91.744 -1.286 91.736 -0.735 c
+h
+92.383 -0.676 m
+92.383 -1.08 92.461 -1.396 92.619 -1.631 c
+92.783 -1.866 93.004 -1.984 93.28 -1.984 c
+93.845 -1.984 94.14 -1.573 94.161 -0.75 c
+94.161 -0.294 l
+94.161 0.106 94.077 0.426 93.912 0.661 c
+93.754 0.904 93.537 1.029 93.265 1.029 c
+93.001 1.029 92.783 0.904 92.619 0.661 c
+92.461 0.426 92.383 0.106 92.383 -0.294 c
+h
+97.675 -2.117 m
+97.458 -2.404 97.145 -2.543 96.734 -2.543 c
+96.37 -2.543 96.095 -2.421 95.911 -2.175 c
+95.734 -1.922 95.639 -1.558 95.632 -1.088 c
+95.632 1.515 l
+96.278 1.515 l
+96.278 -1.029 l
+96.278 -1.658 96.462 -1.97 96.837 -1.97 c
+97.238 -1.97 97.513 -1.793 97.66 -1.44 c
+97.66 1.515 l
+98.307 1.515 l
+98.307 -2.469 l
+97.689 -2.469 l
+h
+100.145 2.469 m
+100.145 1.515 l
+100.747 1.515 l
+100.747 0.985 l
+100.145 0.985 l
+100.145 -1.484 l
+100.145 -1.643 100.166 -1.76 100.218 -1.837 c
+100.276 -1.918 100.365 -1.955 100.482 -1.955 c
+100.571 -1.955 100.659 -1.94 100.747 -1.911 c
+100.747 -2.469 l
+100.6 -2.517 100.446 -2.543 100.291 -2.543 c
+100.034 -2.543 99.839 -2.451 99.703 -2.263 c
+99.563 -2.08 99.497 -1.818 99.497 -1.484 c
+99.497 0.985 l
+98.894 0.985 l
+98.894 1.515 l
+99.497 1.515 l
+99.497 2.469 l
+h
+104.392 -0.676 m
+104.392 -1.305 104.274 -1.775 104.039 -2.088 c
+103.812 -2.392 103.495 -2.543 103.084 -2.543 c
+102.68 -2.543 102.371 -2.392 102.158 -2.088 c
+102.158 -3.998 l
+101.511 -3.998 l
+101.511 1.515 l
+102.099 1.515 l
+102.144 1.073 l
+102.356 1.415 102.665 1.588 103.069 1.588 c
+103.51 1.588 103.837 1.434 104.054 1.132 c
+104.267 0.827 104.382 0.372 104.392 -0.235 c
+h
+103.746 -0.294 m
+103.746 0.147 103.676 0.47 103.54 0.676 c
+103.4 0.889 103.179 1 102.878 1 c
+102.562 1 102.323 0.846 102.158 0.544 c
+102.158 -1.529 l
+102.323 -1.834 102.562 -1.984 102.878 -1.984 c
+103.172 -1.984 103.385 -1.882 103.525 -1.675 c
+103.661 -1.463 103.734 -1.132 103.746 -0.691 c
+h
+107.258 -2.117 m
+107.042 -2.404 106.73 -2.543 106.318 -2.543 c
+105.954 -2.543 105.678 -2.421 105.495 -2.175 c
+105.319 -1.922 105.223 -1.558 105.215 -1.088 c
+105.215 1.515 l
+105.862 1.515 l
+105.862 -1.029 l
+105.862 -1.658 106.046 -1.97 106.42 -1.97 c
+106.821 -1.97 107.097 -1.793 107.244 -1.44 c
+107.244 1.515 l
+107.891 1.515 l
+107.891 -2.469 l
+107.273 -2.469 l
+h
+109.728 2.469 m
+109.728 1.515 l
+110.331 1.515 l
+110.331 0.985 l
+109.728 0.985 l
+109.728 -1.484 l
+109.728 -1.643 109.75 -1.76 109.801 -1.837 c
+109.86 -1.918 109.948 -1.955 110.066 -1.955 c
+110.154 -1.955 110.242 -1.94 110.331 -1.911 c
+110.331 -2.469 l
+110.183 -2.517 110.029 -2.543 109.875 -2.543 c
+109.618 -2.543 109.423 -2.451 109.287 -2.263 c
+109.147 -2.08 109.082 -1.818 109.082 -1.484 c
+109.082 0.985 l
+108.479 0.985 l
+108.479 1.515 l
+109.082 1.515 l
+109.082 2.469 l
+h
+111.139 -2.117 m
+111.139 -1.999 111.172 -1.903 111.242 -1.822 c
+111.308 -1.745 111.411 -1.705 111.551 -1.705 c
+111.698 -1.705 111.804 -1.745 111.874 -1.822 c
+111.951 -1.903 111.991 -1.999 111.991 -2.117 c
+111.991 -2.227 111.951 -2.319 111.874 -2.396 c
+111.804 -2.473 111.698 -2.514 111.551 -2.514 c
+111.411 -2.514 111.308 -2.473 111.242 -2.396 c
+111.172 -2.319 111.139 -2.227 111.139 -2.117 c
+f
+Q
+0.793 0.801 0.129 0.016 k
+35.668 318.604 238.665 -21.457 re
+f
+0 0 0 0 k
+q 1 0 0 1 140.2002 303.1149 cm
+0 0 m
+-5.513 0 l
+-5.513 1.294 l
+-2.984 4.513 l
+-2.66 4.954 -2.425 5.34 -2.278 5.675 c
+-2.124 6.016 -2.043 6.34 -2.043 6.644 c
+-2.043 7.063 -2.117 7.394 -2.263 7.629 c
+-2.404 7.865 -2.61 7.982 -2.881 7.982 c
+-3.175 7.982 -3.41 7.842 -3.587 7.57 c
+-3.763 7.294 -3.851 6.909 -3.851 6.409 c
+-5.674 6.409 l
+-5.674 6.986 -5.556 7.512 -5.321 7.982 c
+-5.079 8.46 -4.74 8.835 -4.307 9.099 c
+-3.877 9.363 -3.392 9.496 -2.851 9.496 c
+-2.022 9.496 -1.374 9.264 -0.912 8.805 c
+-0.441 8.342 -0.206 7.688 -0.206 6.835 c
+-0.206 6.306 -0.339 5.77 -0.603 5.233 c
+-0.86 4.693 -1.32 4.028 -1.985 3.234 c
+-3.19 1.515 l
+0 1.515 l
+h
+1.532 0.927 m
+1.532 1.22 1.627 1.459 1.826 1.646 c
+2.021 1.831 2.275 1.926 2.591 1.926 c
+2.892 1.926 3.142 1.831 3.341 1.646 c
+3.546 1.459 3.649 1.22 3.649 0.927 c
+3.649 0.621 3.546 0.375 3.341 0.191 c
+3.142 0.015 2.892 -0.073 2.591 -0.073 c
+2.286 -0.073 2.032 0.019 1.826 0.206 c
+1.627 0.389 1.532 0.632 1.532 0.927 c
+12.49 2.455 m
+12.49 2.837 12.391 3.124 12.197 3.323 c
+11.998 3.517 11.645 3.719 11.138 3.925 c
+10.198 4.285 9.521 4.704 9.109 5.174 c
+8.698 5.652 8.492 6.222 8.492 6.88 c
+8.492 7.662 8.771 8.295 9.33 8.775 c
+9.889 9.253 10.597 9.496 11.461 9.496 c
+12.039 9.496 12.553 9.371 13.005 9.128 c
+13.454 8.882 13.799 8.54 14.034 8.1 c
+14.277 7.659 14.401 7.159 14.401 6.6 c
+12.519 6.6 l
+12.519 7.041 12.424 7.372 12.241 7.599 c
+12.053 7.824 11.785 7.938 11.432 7.938 c
+11.098 7.938 10.836 7.838 10.653 7.644 c
+10.477 7.456 10.389 7.196 10.389 6.865 c
+10.389 6.608 10.491 6.373 10.697 6.159 c
+10.903 5.953 11.263 5.737 11.785 5.513 c
+12.696 5.189 13.358 4.785 13.77 4.307 c
+14.188 3.826 14.401 3.212 14.401 2.469 c
+14.401 1.654 14.14 1.018 13.622 0.559 c
+13.101 0.096 12.395 -0.132 11.505 -0.132 c
+10.896 -0.132 10.344 -0.007 9.845 0.235 c
+9.352 0.489 8.966 0.846 8.683 1.309 c
+8.397 1.779 8.257 2.326 8.257 2.955 c
+10.153 2.955 l
+10.153 2.415 10.256 2.022 10.462 1.779 c
+10.675 1.532 11.025 1.411 11.505 1.411 c
+12.16 1.411 12.49 1.757 12.49 2.455 c
+21.938 7.791 m
+19.615 7.791 l
+19.615 0 l
+17.72 0 l
+17.72 7.791 l
+15.441 7.791 l
+15.441 9.363 l
+21.938 9.363 l
+h
+26.896 1.912 m
+24.323 1.912 l
+23.823 0 l
+21.824 0 l
+24.749 9.363 l
+26.47 9.363 l
+29.424 0 l
+27.395 0 l
+h
+24.735 3.499 m
+26.484 3.499 l
+25.602 6.835 l
+h
+33.363 3.425 m
+32.423 3.425 l
+32.423 0 l
+30.541 0 l
+30.541 9.363 l
+33.554 9.363 l
+34.503 9.363 35.234 9.118 35.744 8.628 c
+36.263 8.136 36.523 7.441 36.523 6.541 c
+36.523 5.295 36.072 4.424 35.171 3.925 c
+36.803 0.088 l
+36.803 0 l
+34.774 0 l
+h
+32.423 4.998 m
+33.495 4.998 l
+33.878 4.998 34.16 5.12 34.348 5.365 c
+34.532 5.619 34.627 5.957 34.627 6.38 c
+34.627 7.321 34.264 7.791 33.539 7.791 c
+32.423 7.791 l
+h
+43.792 7.791 m
+41.47 7.791 l
+41.47 0 l
+39.573 0 l
+39.573 7.791 l
+37.295 7.791 l
+37.295 9.363 l
+43.792 9.363 l
+h
+47.062 0 -1.896 9.363 re
+55.309 0 m
+53.412 0 l
+50.649 6.145 l
+50.649 0 l
+48.753 0 l
+48.753 9.363 l
+50.649 9.363 l
+53.412 3.219 l
+53.412 9.363 l
+55.309 9.363 l
+h
+63.427 1.058 m
+63.062 0.665 62.617 0.368 62.089 0.162 c
+61.559 -0.033 60.979 -0.132 60.354 -0.132 c
+59.274 -0.132 58.436 0.198 57.84 0.867 c
+57.241 1.532 56.936 2.502 56.929 3.778 c
+56.929 5.469 l
+56.929 6.762 57.208 7.755 57.767 8.453 c
+58.333 9.147 59.157 9.496 60.236 9.496 c
+61.254 9.496 62.019 9.239 62.53 8.732 c
+63.047 8.231 63.346 7.445 63.427 6.38 c
+61.589 6.38 l
+61.538 6.975 61.416 7.383 61.221 7.599 c
+61.023 7.813 60.714 7.923 60.296 7.923 c
+59.785 7.923 59.413 7.736 59.178 7.364 c
+58.951 6.99 58.833 6.398 58.825 5.586 c
+58.825 3.881 l
+58.825 3.028 58.951 2.404 59.207 2.014 c
+59.461 1.632 59.876 1.441 60.457 1.441 c
+60.828 1.441 61.133 1.515 61.368 1.661 c
+61.53 1.779 l
+61.53 3.499 l
+60.207 3.499 l
+60.207 4.925 l
+63.427 4.925 l
+h
+72.591 1.912 m
+70.019 1.912 l
+69.519 0 l
+67.52 0 l
+70.445 9.363 l
+72.165 9.363 l
+75.119 0 l
+73.091 0 l
+h
+70.43 3.499 m
+72.179 3.499 l
+71.298 6.835 l
+h
+81.238 3.293 m
+81.238 0 l
+79.342 0 l
+79.342 9.363 l
+82.531 9.363 l
+83.461 9.363 84.2 9.073 84.751 8.497 c
+85.299 7.927 85.574 7.181 85.574 6.263 c
+85.574 5.351 85.299 4.623 84.751 4.087 c
+84.21 3.558 83.461 3.293 82.502 3.293 c
+h
+81.238 4.866 m
+82.531 4.866 l
+82.891 4.866 83.171 4.983 83.369 5.218 c
+83.564 5.453 83.663 5.795 83.663 6.247 c
+83.663 6.718 83.56 7.088 83.354 7.364 c
+83.156 7.637 82.891 7.78 82.561 7.791 c
+81.238 7.791 l
+h
+89.877 3.425 m
+88.937 3.425 l
+88.937 0 l
+87.055 0 l
+87.055 9.363 l
+90.068 9.363 l
+91.017 9.363 91.747 9.118 92.258 8.628 c
+92.777 8.136 93.037 7.441 93.037 6.541 c
+93.037 5.295 92.586 4.424 91.685 3.925 c
+93.317 0.088 l
+93.317 0 l
+91.288 0 l
+h
+88.937 4.998 m
+90.01 4.998 l
+90.392 4.998 90.675 5.12 90.862 5.365 c
+91.046 5.619 91.142 5.957 91.142 6.38 c
+91.142 7.321 90.778 7.791 90.053 7.791 c
+88.937 7.791 l
+h
+101.155 3.836 m
+101.155 2.58 100.854 1.606 100.258 0.912 c
+99.659 0.214 98.836 -0.132 97.789 -0.132 c
+96.738 -0.132 95.911 0.21 95.304 0.897 c
+94.706 1.592 94.4 2.558 94.394 3.793 c
+94.394 5.395 l
+94.394 6.677 94.691 7.68 95.29 8.408 c
+95.886 9.132 96.716 9.496 97.774 9.496 c
+98.811 9.496 99.63 9.136 100.229 8.422 c
+100.835 7.717 101.144 6.722 101.155 5.439 c
+h
+99.259 5.409 m
+99.259 6.251 99.134 6.88 98.891 7.291 c
+98.656 7.703 98.282 7.909 97.774 7.909 c
+97.274 7.909 96.9 7.707 96.657 7.306 c
+96.422 6.913 96.297 6.313 96.289 5.513 c
+96.289 3.836 l
+96.289 3.021 96.411 2.419 96.657 2.029 c
+96.9 1.636 97.278 1.441 97.789 1.441 c
+98.278 1.441 98.641 1.632 98.876 2.014 c
+99.119 2.396 99.248 2.984 99.259 3.778 c
+h
+105.814 9.363 m
+107.696 9.363 l
+107.696 2.882 l
+107.696 1.97 107.439 1.239 106.932 0.691 c
+106.432 0.14 105.785 -0.132 104.991 -0.132 c
+104.128 -0.132 103.456 0.121 102.978 0.632 c
+102.508 1.139 102.272 1.852 102.272 2.764 c
+104.168 2.764 l
+104.168 1.881 104.44 1.441 104.991 1.441 c
+105.539 1.441 105.814 1.948 105.814 2.97 c
+h
+114.208 4.057 m
+111.268 4.057 l
+111.268 1.573 l
+114.751 1.573 l
+114.751 0 l
+109.372 0 l
+109.372 9.363 l
+114.737 9.363 l
+114.737 7.791 l
+111.268 7.791 l
+111.268 5.571 l
+114.208 5.571 l
+h
+122.362 3.117 m
+122.31 2.047 122.009 1.239 121.45 0.691 c
+120.899 0.14 120.128 -0.132 119.129 -0.132 c
+118.059 -0.132 117.24 0.214 116.673 0.912 c
+116.115 1.606 115.836 2.602 115.836 3.896 c
+115.836 5.469 l
+115.836 6.762 116.122 7.755 116.703 8.453 c
+117.291 9.147 118.103 9.496 119.143 9.496 c
+120.161 9.496 120.937 9.205 121.465 8.628 c
+121.995 8.059 122.296 7.24 122.377 6.174 c
+120.481 6.174 l
+120.459 6.839 120.355 7.294 120.172 7.541 c
+119.985 7.794 119.643 7.923 119.143 7.923 c
+118.643 7.923 118.283 7.747 118.07 7.394 c
+117.864 7.041 117.75 6.457 117.732 5.644 c
+117.732 3.881 l
+117.732 2.947 117.835 2.308 118.04 1.955 c
+118.254 1.61 118.618 1.441 119.129 1.441 c
+119.617 1.441 119.956 1.559 120.143 1.794 c
+120.338 2.036 120.444 2.477 120.466 3.117 c
+h
+129.624 7.791 m
+127.301 7.791 l
+127.301 0 l
+125.405 0 l
+125.405 7.791 l
+123.127 7.791 l
+123.127 9.363 l
+129.624 9.363 l
+h
+f
+Q
+0.113 0.082 0.09 0 k
+35.668 288.302 238.665 -12.895 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 40.8563 281.4638 cm
+0 0 m
+0 -0.188 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.647 -0.243 -0.776 -0.367 -0.882 c
+-0.496 -0.992 -0.658 -1.081 -0.852 -1.147 c
+-1.051 -1.206 -1.278 -1.243 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.162 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.927 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.132 l
+-2.642 0.033 -2.616 -0.059 -2.587 -0.148 c
+-2.55 -0.228 -2.506 -0.302 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.675 c
+-1.977 0.683 -1.992 0.69 -1.999 0.69 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.881 -2.786 0.959 -2.91 1.058 c
+-3.039 1.153 -3.142 1.278 -3.219 1.425 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.836 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.042 c
+-0.804 2.991 -0.669 2.917 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.252 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.352 c
+-1.294 1.311 -1.117 1.263 -0.941 1.205 c
+-0.756 1.146 -0.595 1.066 -0.455 0.97 c
+-0.32 0.87 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.319 2.385 -2.366 2.337 c
+-2.406 2.296 -2.437 2.248 -2.454 2.19 c
+-2.477 2.131 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.778 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.201 1.558 -2.131 1.529 c
+-2.065 1.499 -1.984 1.469 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.091 -0.86 0.176 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.529 -1.448 0.558 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.53 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.22 5.108 -2.103 c
+5.039 -1.985 4.991 -1.856 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.754 5.964 -1.86 6.064 -1.941 c
+6.159 -2.029 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.058 6.681 -2.029 c
+6.758 -1.999 6.828 -1.945 6.887 -1.867 c
+6.945 -1.797 6.99 -1.706 7.019 -1.588 c
+7.056 -1.47 7.078 -1.324 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.89 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.073 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.412 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.234 c
+4.946 1.448 5.027 1.631 5.137 1.778 c
+5.245 1.932 5.376 2.05 5.534 2.131 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.252 6.387 2.234 c
+6.483 2.212 6.571 2.179 6.652 2.131 c
+6.739 2.08 6.817 2.017 6.887 1.94 c
+6.964 1.859 7.026 1.768 7.078 1.66 c
+7.092 1.66 l
+7.092 1.808 l
+7.1 1.866 7.107 1.918 7.107 1.969 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.164 7.14 2.198 7.152 2.219 c
+8.004 2.219 l
+7.993 2.138 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.162 l
+7.975 -1.415 7.938 -1.636 7.871 -1.823 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.5 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.529 m
+7.092 0.742 7.067 0.918 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.499 6.729 1.558 6.652 1.587 c
+6.571 1.624 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.62 6.137 1.573 c
+6.056 1.532 5.99 1.462 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.874 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.339 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.383 c
+6.924 -0.294 6.978 -0.177 7.019 -0.03 c
+7.067 0.118 7.092 0.301 7.092 0.529 c
+11.036 -0.647 m
+12.168 -0.647 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.647 l
+10.124 -0.647 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.676 re
+10.124 2.836 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.219 l
+13.644 2.219 l
+13.924 3.116 l
+14.497 3.116 l
+14.497 2.219 l
+15.732 2.219 l
+15.732 1.602 l
+14.497 1.602 l
+14.497 -0.104 l
+14.497 -0.324 l
+14.504 -0.393 14.527 -0.456 14.556 -0.515 c
+14.593 -0.566 14.648 -0.611 14.718 -0.647 c
+14.795 -0.676 14.909 -0.691 15.056 -0.691 c
+15.192 -0.691 15.327 -0.688 15.468 -0.676 c
+15.603 -0.659 15.736 -0.632 15.865 -0.603 c
+15.865 -1.206 l
+15.784 -1.216 15.707 -1.231 15.629 -1.249 c
+15.549 -1.261 15.471 -1.268 15.394 -1.279 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.041 -1.301 14.942 -1.309 14.835 -1.309 c
+14.648 -1.309 14.486 -1.294 14.35 -1.264 c
+14.221 -1.228 14.107 -1.183 14.012 -1.132 c
+13.924 -1.085 13.85 -1.025 13.791 -0.956 c
+13.733 -0.879 13.689 -0.802 13.66 -0.721 c
+13.63 -0.632 13.608 -0.544 13.6 -0.456 c
+13.59 -0.36 13.586 -0.265 13.586 -0.177 c
+h
+23.221 -0.647 m
+24.353 -0.647 l
+24.353 -1.264 l
+21.045 -1.264 l
+21.045 -0.647 l
+22.31 -0.647 l
+22.31 1.602 l
+21.384 1.602 l
+21.384 2.219 l
+23.221 2.219 l
+h
+22.31 3.513 0.912 -0.676 re
+22.31 2.836 m
+27.37 -1.264 m
+27.37 0.72 l
+27.37 1.022 27.326 1.242 27.237 1.381 c
+27.156 1.529 27.021 1.602 26.826 1.602 c
+26.716 1.602 26.613 1.576 26.518 1.529 c
+26.429 1.477 26.348 1.411 26.282 1.323 c
+26.223 1.234 26.172 1.124 26.136 0.999 c
+26.106 0.881 26.091 0.75 26.091 0.602 c
+26.091 -1.264 l
+25.18 -1.264 l
+25.18 1.44 l
+25.18 1.66 l
+25.18 1.749 25.172 1.826 25.165 1.896 c
+25.165 2.087 l
+25.165 2.219 l
+26.018 2.219 l
+26.025 2.19 26.032 2.146 26.032 2.087 c
+26.032 1.896 l
+26.04 1.826 26.047 1.756 26.047 1.69 c
+26.055 1.62 26.061 1.565 26.061 1.529 c
+26.076 1.529 l
+26.194 1.793 26.344 1.984 26.532 2.102 c
+26.716 2.219 26.936 2.278 27.194 2.278 c
+27.377 2.278 27.539 2.248 27.678 2.19 c
+27.815 2.131 27.929 2.043 28.017 1.926 c
+28.105 1.808 28.168 1.664 28.208 1.499 c
+28.255 1.341 28.281 1.153 28.281 0.941 c
+28.281 -1.264 l
+h
+31.343 -0.647 m
+32.474 -0.647 l
+32.474 -1.264 l
+29.167 -1.264 l
+29.167 -0.647 l
+30.431 -0.647 l
+30.431 1.602 l
+29.505 1.602 l
+29.505 2.219 l
+31.343 2.219 l
+h
+30.431 3.513 0.912 -0.676 re
+30.431 2.836 m
+33.907 1.602 m
+33.363 1.602 l
+33.363 2.219 l
+33.951 2.219 l
+34.231 3.116 l
+34.804 3.116 l
+34.804 2.219 l
+36.039 2.219 l
+36.039 1.602 l
+34.804 1.602 l
+34.804 -0.104 l
+34.804 -0.324 l
+34.811 -0.393 34.834 -0.456 34.863 -0.515 c
+34.9 -0.566 34.955 -0.611 35.025 -0.647 c
+35.102 -0.676 35.216 -0.691 35.362 -0.691 c
+35.499 -0.691 35.634 -0.688 35.774 -0.676 c
+35.91 -0.659 36.043 -0.632 36.17 -0.603 c
+36.17 -1.206 l
+36.091 -1.216 36.013 -1.231 35.935 -1.249 c
+35.855 -1.261 35.778 -1.268 35.7 -1.279 c
+35.62 -1.286 35.532 -1.294 35.436 -1.294 c
+35.348 -1.301 35.249 -1.309 35.142 -1.309 c
+34.955 -1.309 34.793 -1.294 34.657 -1.264 c
+34.528 -1.228 34.414 -1.183 34.319 -1.132 c
+34.231 -1.085 34.157 -1.025 34.098 -0.956 c
+34.04 -0.879 33.995 -0.802 33.966 -0.721 c
+33.937 -0.632 33.915 -0.544 33.907 -0.456 c
+33.897 -0.36 33.893 -0.265 33.893 -0.177 c
+h
+42.175 -2.631 m
+42.175 3.513 l
+44.101 3.513 l
+44.101 2.896 l
+43.028 2.896 l
+43.028 -2.014 l
+44.101 -2.014 l
+44.101 -2.631 l
+h
+46.354 2.219 m
+46.362 2.198 46.368 2.164 46.368 2.117 c
+46.376 2.076 46.383 2.028 46.383 1.969 c
+46.391 1.918 46.398 1.866 46.398 1.808 c
+46.398 1.646 l
+46.412 1.646 l
+46.472 1.764 46.537 1.859 46.618 1.94 c
+46.695 2.017 46.78 2.08 46.869 2.131 c
+46.956 2.19 47.044 2.227 47.133 2.248 c
+47.228 2.267 47.328 2.278 47.426 2.278 c
+47.632 2.278 47.813 2.234 47.97 2.146 c
+48.125 2.057 48.253 1.928 48.353 1.764 c
+48.459 1.606 48.536 1.415 48.588 1.19 c
+48.647 0.974 48.676 0.738 48.676 0.484 c
+48.676 0.22 48.647 -0.026 48.588 -0.25 c
+48.536 -0.467 48.459 -0.659 48.353 -0.823 c
+48.253 -0.981 48.122 -1.103 47.956 -1.191 c
+47.798 -1.279 47.611 -1.324 47.397 -1.324 c
+47.298 -1.324 47.199 -1.312 47.104 -1.294 c
+47.004 -1.272 46.912 -1.243 46.824 -1.191 c
+46.743 -1.143 46.666 -1.081 46.589 -1 c
+46.519 -0.923 46.46 -0.831 46.412 -0.721 c
+46.398 -0.721 l
+46.398 -0.809 l
+46.405 -0.85 46.412 -0.897 46.412 -0.956 c
+46.412 -1.118 l
+46.412 -1.294 l
+46.412 -2.631 l
+45.501 -2.631 l
+45.501 1.455 l
+45.501 1.62 45.494 1.768 45.487 1.896 c
+45.487 2.219 l
+h
+46.398 0.455 m
+46.398 0.228 46.416 0.037 46.457 -0.118 c
+46.505 -0.265 46.559 -0.383 46.618 -0.47 c
+46.684 -0.559 46.758 -0.625 46.838 -0.661 c
+46.916 -0.702 46.993 -0.721 47.074 -0.721 c
+47.17 -0.721 47.258 -0.698 47.339 -0.647 c
+47.426 -0.599 47.493 -0.53 47.544 -0.441 c
+47.603 -0.345 47.648 -0.221 47.677 -0.073 c
+47.713 0.081 47.735 0.268 47.735 0.484 c
+47.735 0.874 47.677 1.168 47.559 1.367 c
+47.449 1.562 47.295 1.66 47.089 1.66 c
+47.008 1.66 46.931 1.639 46.854 1.602 c
+46.773 1.562 46.699 1.499 46.633 1.411 c
+46.563 1.323 46.505 1.198 46.457 1.043 c
+46.416 0.885 46.398 0.69 46.398 0.455 c
+52.56 1.469 m
+52.461 1.477 52.359 1.488 52.251 1.499 c
+52.141 1.517 52.02 1.529 51.885 1.529 c
+51.708 1.529 51.55 1.488 51.414 1.411 c
+51.274 1.341 51.156 1.242 51.061 1.117 c
+50.973 0.988 50.903 0.841 50.855 0.675 c
+50.815 0.507 50.796 0.33 50.796 0.147 c
+50.796 -1.264 l
+49.9 -1.264 l
+49.9 0.985 l
+49.9 1.109 49.889 1.234 49.87 1.352 c
+49.859 1.477 49.845 1.595 49.826 1.705 c
+49.815 1.822 49.801 1.918 49.782 1.999 c
+49.76 2.087 49.742 2.161 49.724 2.219 c
+50.605 2.219 l
+50.613 2.167 50.624 2.117 50.635 2.057 c
+50.653 1.999 50.668 1.932 50.679 1.866 c
+50.697 1.808 50.712 1.741 50.723 1.675 c
+50.73 1.606 50.742 1.543 50.752 1.484 c
+50.767 1.484 l
+50.804 1.602 50.855 1.708 50.914 1.808 c
+50.981 1.903 51.061 1.988 51.149 2.057 c
+51.237 2.124 51.341 2.179 51.458 2.219 c
+51.583 2.256 51.73 2.278 51.899 2.278 c
+52.024 2.278 52.141 2.271 52.251 2.263 c
+52.369 2.252 52.473 2.238 52.56 2.219 c
+h
+56.816 0.484 m
+56.816 0.209 56.779 -0.04 56.712 -0.265 c
+56.643 -0.482 56.54 -0.669 56.404 -0.823 c
+56.265 -0.981 56.088 -1.103 55.875 -1.191 c
+55.658 -1.279 55.405 -1.324 55.11 -1.324 c
+54.835 -1.324 54.589 -1.279 54.376 -1.191 c
+54.17 -1.103 53.997 -0.981 53.861 -0.823 c
+53.722 -0.669 53.618 -0.482 53.553 -0.265 c
+53.483 -0.04 53.45 0.209 53.45 0.484 c
+53.45 0.738 53.479 0.974 53.537 1.19 c
+53.604 1.415 53.707 1.606 53.847 1.764 c
+53.982 1.928 54.159 2.057 54.376 2.146 c
+54.589 2.234 54.846 2.278 55.14 2.278 c
+55.453 2.278 55.713 2.234 55.919 2.146 c
+56.132 2.057 56.305 1.928 56.434 1.764 c
+56.569 1.606 56.669 1.415 56.728 1.19 c
+56.787 0.974 56.816 0.738 56.816 0.484 c
+55.86 0.484 m
+55.86 0.69 55.846 0.867 55.816 1.014 c
+55.794 1.161 55.758 1.282 55.698 1.381 c
+55.64 1.477 55.567 1.547 55.478 1.587 c
+55.39 1.635 55.28 1.66 55.155 1.66 c
+54.89 1.66 54.699 1.562 54.582 1.367 c
+54.464 1.18 54.405 0.885 54.405 0.484 c
+54.405 0.062 54.464 -0.243 54.582 -0.426 c
+54.699 -0.614 54.875 -0.706 55.11 -0.706 c
+55.236 -0.706 55.349 -0.688 55.449 -0.647 c
+55.544 -0.599 55.625 -0.526 55.684 -0.426 c
+55.75 -0.331 55.794 -0.206 55.816 -0.059 c
+55.846 0.087 55.86 0.268 55.86 0.484 c
+59.995 -1.309 m
+59.995 -1.544 59.951 -1.742 59.862 -1.912 c
+59.781 -2.076 59.675 -2.213 59.538 -2.323 c
+59.399 -2.429 59.245 -2.506 59.068 -2.558 c
+58.892 -2.606 58.709 -2.631 58.524 -2.631 c
+58.436 -2.631 58.348 -2.624 58.26 -2.617 c
+58.172 -2.606 58.083 -2.595 57.996 -2.587 c
+57.915 -2.577 57.841 -2.562 57.775 -2.543 c
+57.705 -2.533 57.647 -2.517 57.599 -2.5 c
+57.599 -1.823 l
+57.687 -1.841 57.805 -1.86 57.951 -1.882 c
+58.098 -1.912 58.26 -1.926 58.436 -1.926 c
+58.532 -1.926 58.62 -1.914 58.701 -1.897 c
+58.778 -1.874 58.848 -1.841 58.906 -1.794 c
+58.966 -1.742 59.01 -1.669 59.039 -1.573 c
+59.068 -1.484 59.083 -1.371 59.083 -1.235 c
+59.083 1.602 l
+57.951 1.602 l
+57.951 2.219 l
+59.995 2.219 l
+h
+59.098 3.513 0.897 -0.676 re
+59.098 2.836 m
+63.291 -1.324 m
+63.033 -1.324 62.806 -1.286 62.6 -1.22 c
+62.395 -1.143 62.218 -1.029 62.071 -0.882 c
+61.924 -0.728 61.806 -0.537 61.718 -0.309 c
+61.637 -0.085 61.601 0.18 61.601 0.484 c
+61.601 0.816 61.645 1.095 61.732 1.323 c
+61.828 1.558 61.957 1.741 62.115 1.881 c
+62.28 2.017 62.468 2.117 62.673 2.175 c
+62.879 2.242 63.089 2.278 63.305 2.278 c
+63.577 2.278 63.812 2.227 64.011 2.131 c
+64.217 2.043 64.382 1.911 64.511 1.734 c
+64.647 1.565 64.746 1.359 64.805 1.117 c
+64.871 0.881 64.907 0.617 64.907 0.323 c
+64.907 0.309 l
+62.541 0.309 l
+62.541 0.162 62.555 0.022 62.586 -0.104 c
+62.622 -0.231 62.677 -0.345 62.746 -0.441 c
+62.813 -0.53 62.898 -0.599 62.997 -0.647 c
+63.093 -0.698 63.206 -0.721 63.335 -0.721 c
+63.49 -0.721 63.629 -0.688 63.746 -0.618 c
+63.872 -0.551 63.96 -0.449 64.011 -0.309 c
+64.849 -0.383 l
+64.82 -0.482 64.764 -0.588 64.687 -0.706 c
+64.606 -0.816 64.504 -0.919 64.379 -1.014 c
+64.261 -1.103 64.107 -1.176 63.922 -1.235 c
+63.746 -1.294 63.533 -1.324 63.291 -1.324 c
+63.291 1.705 m
+63.203 1.705 63.114 1.69 63.026 1.66 c
+62.938 1.631 62.857 1.579 62.791 1.514 c
+62.721 1.444 62.663 1.356 62.615 1.249 c
+62.574 1.139 62.555 1.014 62.555 0.867 c
+64.026 0.867 l
+64.026 1.003 64 1.124 63.952 1.234 c
+63.912 1.341 63.856 1.429 63.791 1.499 c
+63.731 1.565 63.658 1.616 63.57 1.646 c
+63.482 1.683 63.386 1.705 63.291 1.705 c
+67.351 -1.324 m
+67.064 -1.324 66.823 -1.283 66.617 -1.206 c
+66.411 -1.118 66.237 -0.996 66.102 -0.838 c
+65.962 -0.684 65.859 -0.497 65.793 -0.279 c
+65.724 -0.056 65.69 0.191 65.69 0.455 c
+65.69 0.75 65.724 1.007 65.793 1.234 c
+65.871 1.458 65.977 1.646 66.117 1.793 c
+66.264 1.947 66.44 2.065 66.646 2.146 c
+66.852 2.234 67.087 2.278 67.351 2.278 c
+67.575 2.278 67.777 2.248 67.954 2.19 c
+68.13 2.131 68.281 2.046 68.41 1.94 c
+68.535 1.841 68.637 1.72 68.718 1.573 c
+68.795 1.433 68.851 1.282 68.88 1.117 c
+67.968 1.072 l
+67.939 1.249 67.87 1.389 67.763 1.499 c
+67.664 1.606 67.521 1.66 67.336 1.66 c
+67.091 1.66 66.914 1.558 66.808 1.352 c
+66.697 1.153 66.646 0.867 66.646 0.484 c
+66.646 -0.309 66.881 -0.706 67.351 -0.706 c
+67.517 -0.706 67.66 -0.655 67.777 -0.544 c
+67.895 -0.437 67.968 -0.276 67.999 -0.059 c
+68.909 -0.104 l
+68.88 -0.272 68.824 -0.426 68.747 -0.574 c
+68.678 -0.721 68.575 -0.853 68.439 -0.971 c
+68.311 -1.081 68.153 -1.168 67.968 -1.235 c
+67.792 -1.294 67.586 -1.324 67.351 -1.324 c
+70.457 1.602 m
+69.913 1.602 l
+69.913 2.219 l
+70.501 2.219 l
+70.78 3.116 l
+71.353 3.116 l
+71.353 2.219 l
+72.587 2.219 l
+72.587 1.602 l
+71.353 1.602 l
+71.353 -0.104 l
+71.353 -0.324 l
+71.361 -0.393 71.382 -0.456 71.412 -0.515 c
+71.448 -0.566 71.504 -0.611 71.573 -0.647 c
+71.65 -0.676 71.764 -0.691 71.912 -0.691 c
+72.047 -0.691 72.184 -0.688 72.323 -0.676 c
+72.46 -0.659 72.591 -0.632 72.72 -0.603 c
+72.72 -1.206 l
+72.639 -1.216 72.562 -1.231 72.485 -1.249 c
+72.404 -1.261 72.327 -1.268 72.25 -1.279 c
+72.169 -1.286 72.08 -1.294 71.985 -1.294 c
+71.897 -1.301 71.798 -1.309 71.691 -1.309 c
+71.504 -1.309 71.342 -1.294 71.206 -1.264 c
+71.078 -1.228 70.964 -1.183 70.868 -1.132 c
+70.78 -1.085 70.706 -1.025 70.648 -0.956 c
+70.588 -0.879 70.545 -0.802 70.515 -0.721 c
+70.486 -0.632 70.464 -0.544 70.457 -0.456 c
+70.445 -0.36 70.442 -0.265 70.442 -0.177 c
+h
+80.169 -1.264 m
+80.169 0.72 l
+80.169 1.022 80.125 1.242 80.036 1.381 c
+79.955 1.529 79.82 1.602 79.625 1.602 c
+79.515 1.602 79.412 1.576 79.317 1.529 c
+79.228 1.477 79.147 1.411 79.081 1.323 c
+79.022 1.234 78.971 1.124 78.935 0.999 c
+78.905 0.881 78.89 0.75 78.89 0.602 c
+78.89 -1.264 l
+77.979 -1.264 l
+77.979 1.44 l
+77.979 1.66 l
+77.979 1.749 77.971 1.826 77.964 1.896 c
+77.964 2.087 l
+77.964 2.219 l
+78.817 2.219 l
+78.824 2.19 78.831 2.146 78.831 2.087 c
+78.831 1.896 l
+78.839 1.826 78.846 1.756 78.846 1.69 c
+78.854 1.62 78.86 1.565 78.86 1.529 c
+78.875 1.529 l
+78.993 1.793 79.143 1.984 79.331 2.102 c
+79.515 2.219 79.735 2.278 79.993 2.278 c
+80.176 2.278 80.338 2.248 80.477 2.19 c
+80.614 2.131 80.728 2.043 80.816 1.926 c
+80.904 1.808 80.967 1.664 81.007 1.499 c
+81.054 1.341 81.08 1.153 81.08 0.941 c
+81.08 -1.264 l
+h
+82.995 -1.324 m
+82.826 -1.324 82.675 -1.301 82.54 -1.264 c
+82.411 -1.216 82.297 -1.147 82.201 -1.058 c
+82.112 -0.971 82.043 -0.864 81.995 -0.736 c
+81.944 -0.599 81.921 -0.449 81.921 -0.279 c
+81.921 -0.073 81.954 0.095 82.025 0.235 c
+82.091 0.382 82.187 0.492 82.304 0.573 c
+82.429 0.661 82.572 0.723 82.73 0.764 c
+82.895 0.801 83.072 0.827 83.259 0.837 c
+83.98 0.852 l
+83.98 1.028 l
+83.98 1.146 83.969 1.249 83.951 1.338 c
+83.928 1.425 83.895 1.492 83.847 1.543 c
+83.807 1.602 83.759 1.639 83.7 1.66 c
+83.641 1.679 83.575 1.69 83.509 1.69 c
+83.44 1.69 83.377 1.679 83.318 1.66 c
+83.267 1.65 83.219 1.624 83.171 1.587 c
+83.13 1.558 83.097 1.506 83.068 1.44 c
+83.047 1.381 83.032 1.301 83.024 1.205 c
+82.083 1.249 l
+82.112 1.396 82.157 1.532 82.216 1.66 c
+82.282 1.786 82.378 1.896 82.495 1.984 c
+82.613 2.08 82.752 2.153 82.921 2.204 c
+83.097 2.252 83.303 2.278 83.539 2.278 c
+83.98 2.278 84.31 2.167 84.539 1.955 c
+84.774 1.749 84.891 1.44 84.891 1.028 c
+84.891 -0.235 l
+84.891 -0.456 l
+84.898 -0.515 84.913 -0.57 84.935 -0.618 c
+84.953 -0.659 84.983 -0.691 85.023 -0.721 c
+85.06 -0.742 85.112 -0.75 85.17 -0.75 c
+85.237 -0.75 85.306 -0.746 85.376 -0.736 c
+85.376 -1.22 l
+85.318 -1.231 85.262 -1.243 85.214 -1.249 c
+85.174 -1.261 85.133 -1.268 85.096 -1.279 c
+85.056 -1.286 85.012 -1.294 84.965 -1.294 c
+84.913 -1.301 84.854 -1.309 84.788 -1.309 c
+84.56 -1.309 84.395 -1.257 84.288 -1.147 c
+84.178 -1.029 84.115 -0.864 84.097 -0.647 c
+84.082 -0.647 l
+84.013 -0.757 83.943 -0.853 83.876 -0.941 c
+83.807 -1.022 83.73 -1.088 83.641 -1.147 c
+83.554 -1.206 83.454 -1.249 83.348 -1.279 c
+83.248 -1.309 83.13 -1.324 82.995 -1.324 c
+83.98 0.353 m
+83.554 0.338 l
+83.454 0.338 83.363 0.33 83.274 0.323 c
+83.193 0.312 83.127 0.286 83.068 0.249 c
+83.01 0.209 82.958 0.151 82.921 0.073 c
+82.881 0.004 82.862 -0.088 82.862 -0.206 c
+82.862 -0.375 82.895 -0.497 82.966 -0.574 c
+83.032 -0.655 83.13 -0.691 83.259 -0.691 c
+83.366 -0.691 83.465 -0.669 83.554 -0.618 c
+83.649 -0.57 83.73 -0.507 83.789 -0.426 c
+83.855 -0.349 83.906 -0.262 83.936 -0.162 c
+83.965 -0.056 83.98 0.058 83.98 0.176 c
+h
+87.261 -1.264 m
+87.261 0.852 l
+87.261 1.018 87.254 1.153 87.246 1.263 c
+87.236 1.371 87.217 1.455 87.188 1.514 c
+87.166 1.579 87.136 1.631 87.099 1.66 c
+87.07 1.69 87.03 1.705 86.982 1.705 c
+86.923 1.705 86.868 1.675 86.82 1.616 c
+86.779 1.565 86.747 1.492 86.717 1.396 c
+86.688 1.308 86.662 1.194 86.644 1.058 c
+86.633 0.918 86.629 0.768 86.629 0.602 c
+86.629 -1.264 l
+85.879 -1.264 l
+85.879 1.469 l
+85.879 1.705 l
+85.879 1.926 l
+85.879 2.003 85.873 2.065 85.865 2.117 c
+85.865 2.219 l
+86.54 2.219 l
+86.54 2.131 l
+86.54 1.984 l
+86.548 1.926 86.556 1.866 86.556 1.808 c
+86.556 1.646 l
+86.571 1.646 l
+86.588 1.734 86.619 1.811 86.658 1.881 c
+86.696 1.959 86.739 2.028 86.791 2.087 c
+86.85 2.146 86.916 2.19 86.997 2.219 c
+87.074 2.256 87.162 2.278 87.261 2.278 c
+87.445 2.278 87.585 2.223 87.673 2.117 c
+87.768 2.017 87.838 1.859 87.878 1.646 c
+87.893 1.646 l
+87.93 1.741 87.97 1.83 88.011 1.911 c
+88.059 1.988 88.113 2.05 88.173 2.102 c
+88.231 2.161 88.298 2.204 88.379 2.234 c
+88.456 2.263 88.543 2.278 88.643 2.278 c
+88.779 2.278 88.892 2.252 88.981 2.204 c
+89.069 2.153 89.135 2.08 89.187 1.984 c
+89.245 1.885 89.283 1.756 89.304 1.602 c
+89.334 1.455 89.349 1.271 89.349 1.058 c
+89.349 -1.264 l
+88.628 -1.264 l
+88.628 0.852 l
+88.628 1.018 88.62 1.153 88.614 1.263 c
+88.603 1.371 88.584 1.455 88.555 1.514 c
+88.533 1.579 88.503 1.631 88.466 1.66 c
+88.437 1.69 88.397 1.705 88.349 1.705 c
+88.231 1.705 88.136 1.616 88.069 1.44 c
+88.011 1.271 87.982 1.014 87.982 0.661 c
+87.982 -1.264 l
+h
+91.718 -1.324 m
+91.462 -1.324 91.234 -1.286 91.028 -1.22 c
+90.822 -1.143 90.646 -1.029 90.498 -0.882 c
+90.351 -0.728 90.234 -0.537 90.146 -0.309 c
+90.065 -0.085 90.028 0.18 90.028 0.484 c
+90.028 0.816 90.072 1.095 90.16 1.323 c
+90.256 1.558 90.384 1.741 90.542 1.881 c
+90.708 2.017 90.895 2.117 91.101 2.175 c
+91.307 2.242 91.517 2.278 91.733 2.278 c
+92.005 2.278 92.24 2.227 92.439 2.131 c
+92.645 2.043 92.811 1.911 92.938 1.734 c
+93.075 1.565 93.174 1.359 93.233 1.117 c
+93.299 0.881 93.335 0.617 93.335 0.323 c
+93.335 0.309 l
+90.969 0.309 l
+90.969 0.162 90.984 0.022 91.013 -0.104 c
+91.049 -0.231 91.105 -0.345 91.175 -0.441 c
+91.241 -0.53 91.325 -0.599 91.425 -0.647 c
+91.52 -0.698 91.635 -0.721 91.763 -0.721 c
+91.917 -0.721 92.057 -0.688 92.175 -0.618 c
+92.3 -0.551 92.387 -0.449 92.439 -0.309 c
+93.277 -0.383 l
+93.247 -0.482 93.192 -0.588 93.115 -0.706 c
+93.034 -0.816 92.931 -0.919 92.807 -1.014 c
+92.689 -1.103 92.535 -1.176 92.351 -1.235 c
+92.175 -1.294 91.961 -1.324 91.718 -1.324 c
+91.718 1.705 m
+91.631 1.705 91.542 1.69 91.454 1.66 c
+91.366 1.631 91.285 1.579 91.219 1.514 c
+91.149 1.444 91.09 1.356 91.043 1.249 c
+91.002 1.139 90.984 1.014 90.984 0.867 c
+92.454 0.867 l
+92.454 1.003 92.428 1.124 92.38 1.234 c
+92.34 1.341 92.285 1.429 92.219 1.499 c
+92.16 1.565 92.086 1.616 91.998 1.646 c
+91.909 1.683 91.814 1.705 91.718 1.705 c
+94.592 -2.631 m
+94.592 -2.014 l
+95.666 -2.014 l
+95.666 2.896 l
+94.592 2.896 l
+94.592 3.513 l
+96.518 3.513 l
+96.518 -2.631 l
+h
+f
+Q
+q 1 0 0 1 59.3004 267.0178 cm
+0 0 m
+-0.029 -0.58 -0.191 -1.022 -0.485 -1.323 c
+-0.779 -1.627 -1.199 -1.778 -1.735 -1.778 c
+-2.264 -1.778 -2.691 -1.579 -3.013 -1.176 c
+-3.329 -0.764 -3.484 -0.206 -3.484 0.5 c
+-3.484 1.47 l
+-3.484 2.165 -3.322 2.712 -2.999 3.117 c
+-2.675 3.517 -2.23 3.719 -1.661 3.719 c
+-1.154 3.719 -0.757 3.561 -0.47 3.248 c
+-0.187 2.944 -0.029 2.502 0 1.926 c
+-0.691 1.926 l
+-0.721 2.367 -0.816 2.679 -0.97 2.866 c
+-1.118 3.05 -1.349 3.146 -1.661 3.146 c
+-2.036 3.146 -2.319 2.999 -2.514 2.705 c
+-2.712 2.419 -2.808 2.003 -2.808 1.455 c
+-2.808 0.47 l
+-2.808 -0.07 -2.716 -0.484 -2.529 -0.779 c
+-2.344 -1.066 -2.08 -1.205 -1.735 -1.205 c
+-1.382 -1.205 -1.128 -1.117 -0.97 -0.941 c
+-0.816 -0.764 -0.721 -0.452 -0.691 0 c
+h
+2.454 1.661 m
+2.366 1.679 2.267 1.691 2.161 1.691 c
+1.826 1.691 1.591 1.507 1.455 1.147 c
+1.455 -1.705 l
+0.808 -1.705 l
+0.808 2.278 l
+1.44 2.278 l
+1.455 1.867 l
+1.631 2.19 1.874 2.352 2.19 2.352 c
+2.296 2.352 2.385 2.33 2.454 2.294 c
+h
+4.453 -1.778 m
+3.954 -1.778 3.572 -1.631 3.307 -1.338 c
+3.042 -1.043 2.91 -0.61 2.91 -0.029 c
+2.91 0.441 l
+2.91 1.037 3.035 1.503 3.293 1.837 c
+3.557 2.18 3.917 2.352 4.38 2.352 c
+4.839 2.352 5.182 2.198 5.409 1.897 c
+5.644 1.602 5.766 1.139 5.776 0.515 c
+5.776 0.088 l
+3.557 0.088 l
+3.557 0 l
+3.557 -0.434 3.634 -0.746 3.792 -0.941 c
+3.958 -1.128 4.189 -1.22 4.483 -1.22 c
+4.677 -1.22 4.85 -1.186 4.997 -1.117 c
+5.145 -1.039 5.28 -0.922 5.409 -0.764 c
+5.747 -1.176 l
+5.46 -1.579 5.03 -1.778 4.453 -1.778 c
+4.38 1.793 m
+4.104 1.793 3.902 1.698 3.777 1.515 c
+3.649 1.326 3.576 1.037 3.557 0.647 c
+5.13 0.647 l
+5.13 0.735 l
+5.107 1.118 5.041 1.386 4.924 1.544 c
+4.806 1.709 4.623 1.793 4.38 1.793 c
+8.598 -1.705 m
+8.558 -1.617 8.533 -1.469 8.525 -1.264 c
+8.29 -1.61 7.996 -1.778 7.644 -1.778 c
+7.279 -1.778 6.996 -1.683 6.791 -1.484 c
+6.593 -1.278 6.497 -0.992 6.497 -0.617 c
+6.497 -0.216 6.633 0.103 6.908 0.339 c
+7.181 0.58 7.555 0.706 8.025 0.706 c
+8.511 0.706 l
+8.511 1.132 l
+8.511 1.367 8.455 1.532 8.349 1.632 c
+8.239 1.738 8.077 1.793 7.864 1.793 c
+7.665 1.793 7.503 1.735 7.378 1.617 c
+7.262 1.5 7.202 1.353 7.202 1.176 c
+6.556 1.176 l
+6.556 1.371 6.614 1.562 6.732 1.75 c
+6.857 1.933 7.019 2.08 7.217 2.19 c
+7.422 2.297 7.651 2.352 7.908 2.352 c
+8.309 2.352 8.613 2.249 8.819 2.043 c
+9.032 1.837 9.146 1.544 9.157 1.162 c
+9.157 -0.852 l
+9.157 -1.157 9.194 -1.421 9.275 -1.646 c
+9.275 -1.705 l
+h
+7.732 -1.19 m
+7.897 -1.19 8.047 -1.147 8.187 -1.058 c
+8.334 -0.97 8.44 -0.86 8.511 -0.72 c
+8.511 0.221 l
+8.143 0.221 l
+7.827 0.221 7.584 0.151 7.408 0.015 c
+7.231 -0.114 7.143 -0.301 7.143 -0.544 c
+7.143 -0.771 7.187 -0.937 7.276 -1.043 c
+7.364 -1.143 7.515 -1.19 7.732 -1.19 c
+11.009 3.234 m
+11.009 2.278 l
+11.612 2.278 l
+11.612 1.75 l
+11.009 1.75 l
+11.009 -0.72 l
+11.009 -0.878 11.031 -0.995 11.083 -1.072 c
+11.141 -1.153 11.23 -1.19 11.347 -1.19 c
+11.436 -1.19 11.524 -1.176 11.612 -1.147 c
+11.612 -1.705 l
+11.465 -1.753 11.311 -1.778 11.156 -1.778 c
+10.899 -1.778 10.705 -1.687 10.568 -1.5 c
+10.429 -1.315 10.362 -1.055 10.362 -0.72 c
+10.362 1.75 l
+9.76 1.75 l
+9.76 2.278 l
+10.362 2.278 l
+10.362 3.234 l
+h
+13.803 -1.778 m
+13.302 -1.778 12.92 -1.631 12.656 -1.338 c
+12.391 -1.043 12.259 -0.61 12.259 -0.029 c
+12.259 0.441 l
+12.259 1.037 12.384 1.503 12.641 1.837 c
+12.906 2.18 13.265 2.352 13.728 2.352 c
+14.188 2.352 14.53 2.198 14.757 1.897 c
+14.993 1.602 15.114 1.139 15.125 0.515 c
+15.125 0.088 l
+12.906 0.088 l
+12.906 0 l
+12.906 -0.434 12.983 -0.746 13.141 -0.941 c
+13.306 -1.128 13.537 -1.22 13.832 -1.22 c
+14.026 -1.22 14.199 -1.186 14.346 -1.117 c
+14.493 -1.039 14.629 -0.922 14.757 -0.764 c
+15.096 -1.176 l
+14.809 -1.579 14.379 -1.778 13.803 -1.778 c
+13.728 1.793 m
+13.454 1.793 13.251 1.698 13.126 1.515 c
+12.997 1.326 12.924 1.037 12.906 0.647 c
+14.478 0.647 l
+14.478 0.735 l
+14.456 1.118 14.39 1.386 14.273 1.544 c
+14.155 1.709 13.971 1.793 13.728 1.793 c
+18.241 2.278 m
+18.256 1.837 l
+18.51 2.18 18.833 2.352 19.226 2.352 c
+19.931 2.352 20.288 1.882 20.299 0.941 c
+20.299 -1.705 l
+19.652 -1.705 l
+19.652 0.912 l
+19.652 1.224 19.597 1.444 19.491 1.573 c
+19.38 1.698 19.226 1.764 19.021 1.764 c
+18.863 1.764 18.715 1.709 18.58 1.602 c
+18.451 1.492 18.348 1.357 18.271 1.191 c
+18.271 -1.705 l
+17.624 -1.705 l
+17.624 2.278 l
+h
+22.695 -1.778 m
+22.195 -1.778 21.813 -1.631 21.549 -1.338 c
+21.284 -1.043 21.152 -0.61 21.152 -0.029 c
+21.152 0.441 l
+21.152 1.037 21.277 1.503 21.534 1.837 c
+21.799 2.18 22.158 2.352 22.622 2.352 c
+23.081 2.352 23.423 2.198 23.65 1.897 c
+23.885 1.602 24.007 1.139 24.018 0.515 c
+24.018 0.088 l
+21.799 0.088 l
+21.799 0 l
+21.799 -0.434 21.876 -0.746 22.034 -0.941 c
+22.199 -1.128 22.43 -1.22 22.725 -1.22 c
+22.919 -1.22 23.092 -1.186 23.239 -1.117 c
+23.386 -1.039 23.522 -0.922 23.65 -0.764 c
+23.989 -1.176 l
+23.702 -1.579 23.272 -1.778 22.695 -1.778 c
+22.622 1.793 m
+22.346 1.793 22.144 1.698 22.019 1.515 c
+21.89 1.326 21.817 1.037 21.799 0.647 c
+23.371 0.647 l
+23.371 0.735 l
+23.349 1.118 23.283 1.386 23.166 1.544 c
+23.048 1.709 22.864 1.793 22.622 1.793 c
+27.766 -0.559 m
+28.369 2.278 l
+29.015 2.278 l
+28.031 -1.705 l
+27.517 -1.705 l
+26.738 1.147 l
+25.988 -1.705 l
+25.458 -1.705 l
+24.503 2.278 l
+25.136 2.278 l
+25.753 -0.484 l
+26.487 2.278 l
+27.002 2.278 l
+h
+32.117 -1.705 -0.646 5.644 re
+32.999 0.47 m
+32.999 1.048 33.135 1.503 33.41 1.837 c
+33.694 2.18 34.065 2.352 34.528 2.352 c
+34.987 2.352 35.355 2.183 35.631 1.852 c
+35.914 1.529 36.06 1.081 36.071 0.515 c
+36.071 0.088 l
+36.071 -0.481 35.928 -0.937 35.645 -1.278 c
+35.369 -1.613 35.002 -1.778 34.543 -1.778 c
+34.079 -1.778 33.709 -1.617 33.425 -1.294 c
+33.15 -0.962 33.007 -0.521 32.999 0.029 c
+h
+33.646 0.088 m
+33.646 -0.316 33.723 -0.632 33.881 -0.867 c
+34.046 -1.103 34.267 -1.22 34.543 -1.22 c
+35.108 -1.22 35.403 -0.808 35.424 0.015 c
+35.424 0.47 l
+35.424 0.871 35.34 1.191 35.174 1.426 c
+35.016 1.669 34.8 1.793 34.528 1.793 c
+34.264 1.793 34.046 1.669 33.881 1.426 c
+33.723 1.191 33.646 0.871 33.646 0.47 c
+h
+38.291 -1.22 m
+38.504 -1.22 38.677 -1.157 38.805 -1.029 c
+38.941 -0.893 39.014 -0.702 39.026 -0.455 c
+39.643 -0.455 l
+39.621 -0.837 39.485 -1.157 39.232 -1.411 c
+38.974 -1.657 38.662 -1.778 38.291 -1.778 c
+37.798 -1.778 37.424 -1.627 37.159 -1.323 c
+36.901 -1.01 36.776 -0.544 36.776 0.073 c
+36.776 0.515 l
+36.776 1.11 36.901 1.565 37.159 1.882 c
+37.424 2.194 37.798 2.352 38.291 2.352 c
+38.692 2.352 39.012 2.22 39.247 1.955 c
+39.488 1.698 39.621 1.353 39.643 0.912 c
+39.026 0.912 l
+39.004 1.205 38.931 1.426 38.805 1.573 c
+38.688 1.72 38.515 1.793 38.291 1.793 c
+37.996 1.793 37.78 1.694 37.644 1.5 c
+37.504 1.312 37.431 1.004 37.424 0.574 c
+37.424 0.059 l
+37.424 -0.411 37.489 -0.746 37.63 -0.941 c
+37.776 -1.128 37.996 -1.22 38.291 -1.22 c
+42.436 -1.705 m
+42.395 -1.617 42.37 -1.469 42.362 -1.264 c
+42.127 -1.61 41.834 -1.778 41.48 -1.778 c
+41.117 -1.778 40.834 -1.683 40.628 -1.484 c
+40.429 -1.278 40.334 -0.992 40.334 -0.617 c
+40.334 -0.216 40.47 0.103 40.745 0.339 c
+41.017 0.58 41.393 0.706 41.863 0.706 c
+42.347 0.706 l
+42.347 1.132 l
+42.347 1.367 42.293 1.532 42.186 1.632 c
+42.076 1.738 41.914 1.793 41.701 1.793 c
+41.503 1.793 41.341 1.735 41.216 1.617 c
+41.098 1.5 41.04 1.353 41.04 1.176 c
+40.393 1.176 l
+40.393 1.371 40.452 1.562 40.569 1.75 c
+40.695 1.933 40.855 2.08 41.054 2.19 c
+41.26 2.297 41.488 2.352 41.745 2.352 c
+42.146 2.352 42.451 2.249 42.656 2.043 c
+42.869 1.837 42.983 1.544 42.995 1.162 c
+42.995 -0.852 l
+42.995 -1.157 43.031 -1.421 43.112 -1.646 c
+43.112 -1.705 l
+h
+41.568 -1.19 m
+41.734 -1.19 41.885 -1.147 42.025 -1.058 c
+42.171 -0.97 42.278 -0.86 42.347 -0.72 c
+42.347 0.221 l
+41.98 0.221 l
+41.664 0.221 41.422 0.151 41.245 0.015 c
+41.069 -0.114 40.98 -0.301 40.98 -0.544 c
+40.98 -0.771 41.025 -0.937 41.113 -1.043 c
+41.202 -1.143 41.352 -1.19 41.568 -1.19 c
+44.699 -1.705 -0.646 5.644 re
+49.08 1.661 m
+48.992 1.679 48.892 1.691 48.786 1.691 c
+48.452 1.691 48.217 1.507 48.08 1.147 c
+48.08 -1.705 l
+47.434 -1.705 l
+47.434 2.278 l
+48.065 2.278 l
+48.08 1.867 l
+48.257 2.19 48.499 2.352 48.815 2.352 c
+48.922 2.352 49.01 2.33 49.08 2.294 c
+h
+51.079 -1.778 m
+50.579 -1.778 50.197 -1.631 49.933 -1.338 c
+49.668 -1.043 49.536 -0.61 49.536 -0.029 c
+49.536 0.441 l
+49.536 1.037 49.661 1.503 49.918 1.837 c
+50.182 2.18 50.542 2.352 51.006 2.352 c
+51.465 2.352 51.807 2.198 52.034 1.897 c
+52.269 1.602 52.391 1.139 52.402 0.515 c
+52.402 0.088 l
+50.182 0.088 l
+50.182 0 l
+50.182 -0.434 50.26 -0.746 50.417 -0.941 c
+50.583 -1.128 50.814 -1.22 51.108 -1.22 c
+51.303 -1.22 51.476 -1.186 51.623 -1.117 c
+51.77 -1.039 51.906 -0.922 52.034 -0.764 c
+52.373 -1.176 l
+52.086 -1.579 51.656 -1.778 51.079 -1.778 c
+51.006 1.793 m
+50.73 1.793 50.528 1.698 50.403 1.515 c
+50.274 1.326 50.201 1.037 50.182 0.647 c
+51.755 0.647 l
+51.755 0.735 l
+51.733 1.118 51.667 1.386 51.55 1.544 c
+51.432 1.709 51.248 1.793 51.006 1.793 c
+56.061 0.088 m
+56.061 -0.54 55.945 -1.01 55.71 -1.323 c
+55.481 -1.627 55.165 -1.778 54.754 -1.778 c
+54.349 -1.778 54.041 -1.627 53.828 -1.323 c
+53.828 -3.233 l
+53.181 -3.233 l
+53.181 2.278 l
+53.769 2.278 l
+53.813 1.837 l
+54.026 2.18 54.335 2.352 54.739 2.352 c
+55.18 2.352 55.507 2.198 55.724 1.897 c
+55.937 1.592 56.051 1.135 56.061 0.53 c
+h
+55.415 0.47 m
+55.415 0.912 55.346 1.235 55.209 1.44 c
+55.07 1.654 54.849 1.764 54.548 1.764 c
+54.232 1.764 53.993 1.61 53.828 1.309 c
+53.828 -0.764 l
+53.993 -1.069 54.232 -1.22 54.548 -1.22 c
+54.842 -1.22 55.055 -1.117 55.195 -0.912 c
+55.331 -0.698 55.404 -0.367 55.415 0.073 c
+h
+56.767 0.47 m
+56.767 1.048 56.903 1.503 57.179 1.837 c
+57.462 2.18 57.833 2.352 58.297 2.352 c
+58.756 2.352 59.123 2.183 59.398 1.852 c
+59.681 1.529 59.828 1.081 59.839 0.515 c
+59.839 0.088 l
+59.839 -0.481 59.697 -0.937 59.413 -1.278 c
+59.138 -1.613 58.77 -1.778 58.311 -1.778 c
+57.848 -1.778 57.476 -1.617 57.194 -1.294 c
+56.918 -0.962 56.775 -0.521 56.767 0.029 c
+h
+57.414 0.088 m
+57.414 -0.316 57.491 -0.632 57.649 -0.867 c
+57.815 -1.103 58.035 -1.22 58.311 -1.22 c
+58.877 -1.22 59.171 -0.808 59.193 0.015 c
+59.193 0.47 l
+59.193 0.871 59.109 1.191 58.943 1.426 c
+58.785 1.669 58.569 1.793 58.297 1.793 c
+58.031 1.793 57.815 1.669 57.649 1.426 c
+57.491 1.191 57.414 0.871 57.414 0.47 c
+h
+62.617 -0.69 m
+62.617 -0.544 62.563 -0.422 62.456 -0.324 c
+62.346 -0.228 62.14 -0.11 61.839 0.029 c
+61.493 0.177 61.251 0.298 61.104 0.397 c
+60.957 0.503 60.846 0.621 60.78 0.75 c
+60.711 0.875 60.678 1.033 60.678 1.22 c
+60.678 1.544 60.795 1.812 61.03 2.028 c
+61.266 2.242 61.567 2.352 61.941 2.352 c
+62.324 2.352 62.633 2.238 62.868 2.014 c
+63.103 1.786 63.221 1.5 63.221 1.147 c
+62.573 1.147 l
+62.573 1.323 62.515 1.474 62.397 1.602 c
+62.28 1.727 62.125 1.793 61.941 1.793 c
+61.744 1.793 61.592 1.738 61.486 1.632 c
+61.376 1.532 61.324 1.401 61.324 1.235 c
+61.324 1.106 61.361 1 61.442 0.912 c
+61.519 0.831 61.71 0.728 62.015 0.603 c
+62.492 0.416 62.824 0.228 63 0.044 c
+63.176 -0.132 63.265 -0.36 63.265 -0.632 c
+63.265 -0.985 63.14 -1.264 62.897 -1.469 c
+62.662 -1.675 62.346 -1.778 61.956 -1.778 c
+61.534 -1.778 61.196 -1.66 60.942 -1.425 c
+60.685 -1.183 60.56 -0.878 60.56 -0.515 c
+61.206 -0.515 l
+61.214 -0.742 61.284 -0.918 61.412 -1.043 c
+61.538 -1.161 61.721 -1.22 61.956 -1.22 c
+62.17 -1.22 62.331 -1.172 62.442 -1.072 c
+62.559 -0.977 62.617 -0.849 62.617 -0.69 c
+64.808 -1.705 -0.646 3.983 re
+64.852 3.322 m
+64.852 3.212 64.823 3.12 64.763 3.043 c
+64.705 2.973 64.609 2.94 64.485 2.94 c
+64.367 2.94 64.271 2.973 64.205 3.043 c
+64.146 3.12 64.117 3.212 64.117 3.322 c
+64.117 3.439 64.146 3.532 64.205 3.601 c
+64.271 3.678 64.367 3.719 64.485 3.719 c
+64.609 3.719 64.705 3.678 64.763 3.601 c
+64.823 3.52 64.852 3.429 64.852 3.322 c
+66.675 3.234 m
+66.675 2.278 l
+67.277 2.278 l
+67.277 1.75 l
+66.675 1.75 l
+66.675 -0.72 l
+66.675 -0.878 66.697 -0.995 66.748 -1.072 c
+66.807 -1.153 66.895 -1.19 67.013 -1.19 c
+67.101 -1.19 67.189 -1.176 67.277 -1.147 c
+67.277 -1.705 l
+67.13 -1.753 66.976 -1.778 66.822 -1.778 c
+66.565 -1.778 66.37 -1.687 66.234 -1.5 c
+66.094 -1.315 66.028 -1.055 66.028 -0.72 c
+66.028 1.75 l
+65.426 1.75 l
+65.426 2.278 l
+66.028 2.278 l
+66.028 3.234 l
+h
+67.836 0.47 m
+67.836 1.048 67.972 1.503 68.248 1.837 c
+68.53 2.18 68.902 2.352 69.364 2.352 c
+69.824 2.352 70.191 2.183 70.467 1.852 c
+70.75 1.529 70.897 1.081 70.908 0.515 c
+70.908 0.088 l
+70.908 -0.481 70.764 -0.937 70.482 -1.278 c
+70.206 -1.613 69.839 -1.778 69.38 -1.778 c
+68.917 -1.778 68.545 -1.617 68.262 -1.294 c
+67.986 -0.962 67.843 -0.521 67.836 0.029 c
+h
+68.483 0.088 m
+68.483 -0.316 68.56 -0.632 68.718 -0.867 c
+68.883 -1.103 69.104 -1.22 69.38 -1.22 c
+69.945 -1.22 70.239 -0.808 70.261 0.015 c
+70.261 0.47 l
+70.261 0.871 70.176 1.191 70.012 1.426 c
+69.854 1.669 69.636 1.793 69.364 1.793 c
+69.1 1.793 68.883 1.669 68.718 1.426 c
+68.56 1.191 68.483 0.871 68.483 0.47 c
+h
+73.392 1.661 m
+73.304 1.679 73.205 1.691 73.098 1.691 c
+72.763 1.691 72.528 1.507 72.393 1.147 c
+72.393 -1.705 l
+71.745 -1.705 l
+71.745 2.278 l
+72.378 2.278 l
+72.393 1.867 l
+72.569 2.19 72.811 2.352 73.127 2.352 c
+73.234 2.352 73.322 2.33 73.392 2.294 c
+h
+75.2 -0.617 m
+75.92 2.278 l
+76.611 2.278 l
+75.317 -2.263 l
+75.219 -2.605 75.075 -2.866 74.891 -3.042 c
+74.715 -3.219 74.513 -3.307 74.289 -3.307 c
+74.201 -3.307 74.087 -3.285 73.951 -3.248 c
+73.951 -2.705 l
+74.097 -2.719 l
+74.282 -2.719 74.428 -2.675 74.539 -2.587 c
+74.645 -2.499 74.733 -2.341 74.803 -2.117 c
+74.92 -1.675 l
+73.76 2.278 l
+74.465 2.278 l
+h
+76.89 -1.352 m
+76.89 -1.234 76.923 -1.139 76.993 -1.058 c
+77.06 -0.981 77.162 -0.941 77.302 -0.941 c
+77.449 -0.941 77.555 -0.981 77.625 -1.058 c
+77.702 -1.139 77.743 -1.234 77.743 -1.352 c
+77.743 -1.462 77.702 -1.554 77.625 -1.631 c
+77.555 -1.708 77.449 -1.749 77.302 -1.749 c
+77.162 -1.749 77.06 -1.708 76.993 -1.631 c
+76.923 -1.554 76.89 -1.462 76.89 -1.352 c
+81.345 -1.705 -0.676 5.35 re
+82.726 -1.705 m
+82.726 1.75 l
+82.197 1.75 l
+82.197 2.278 l
+82.726 2.278 l
+82.726 2.734 l
+82.726 3.135 82.822 3.447 83.02 3.675 c
+83.226 3.899 83.505 4.013 83.857 4.013 c
+83.994 4.013 84.127 3.991 84.255 3.954 c
+84.225 3.41 l
+84.127 3.429 84.027 3.439 83.932 3.439 c
+83.556 3.439 83.373 3.175 83.373 2.646 c
+83.373 2.278 l
+84.048 2.278 l
+84.048 1.75 l
+83.373 1.75 l
+83.373 -1.705 l
+h
+f
+Q
+q 1 0 0 1 147.1862 270.7224 cm
+0 0 m
+-0.383 0 l
+-0.383 -5.835 l
+0 -5.835 l
+0 -6.659 l
+-1.426 -6.659 l
+-1.426 0.823 l
+0 0.823 l
+h
+3.63 -3.543 m
+3.63 -4.171 3.52 -4.653 3.307 -4.983 c
+3.09 -5.318 2.77 -5.483 2.352 -5.483 c
+2.028 -5.483 1.768 -5.351 1.572 -5.087 c
+1.572 -6.938 l
+0.529 -6.938 l
+0.529 -1.426 l
+1.484 -1.426 l
+1.529 -1.794 l
+1.723 -1.5 1.992 -1.353 2.337 -1.353 c
+2.755 -1.353 3.075 -1.511 3.293 -1.823 c
+3.505 -2.128 3.619 -2.598 3.63 -3.234 c
+h
+2.587 -3.278 m
+2.587 -2.896 2.543 -2.628 2.454 -2.469 c
+2.373 -2.315 2.234 -2.234 2.028 -2.234 c
+1.822 -2.234 1.668 -2.323 1.572 -2.5 c
+1.572 -4.366 l
+1.66 -4.535 1.815 -4.616 2.042 -4.616 c
+2.248 -4.616 2.389 -4.535 2.469 -4.366 c
+2.547 -4.189 2.587 -3.917 2.587 -3.543 c
+h
+6.217 -2.44 m
+5.88 -2.411 l
+5.593 -2.411 5.402 -2.536 5.306 -2.778 c
+5.306 -5.409 l
+4.262 -5.409 l
+4.262 -1.426 l
+5.232 -1.426 l
+5.262 -1.867 l
+5.427 -1.525 5.659 -1.353 5.953 -1.353 c
+6.071 -1.353 6.162 -1.374 6.232 -1.411 c
+h
+6.511 -3.293 m
+6.511 -2.687 6.651 -2.213 6.938 -1.867 c
+7.22 -1.525 7.613 -1.353 8.114 -1.353 c
+8.621 -1.353 9.018 -1.525 9.304 -1.867 c
+9.587 -2.213 9.73 -2.687 9.73 -3.293 c
+9.73 -3.558 l
+9.73 -4.156 9.587 -4.627 9.304 -4.969 c
+9.018 -5.314 8.621 -5.483 8.114 -5.483 c
+7.603 -5.483 7.206 -5.314 6.923 -4.969 c
+6.647 -4.627 6.511 -4.152 6.511 -3.543 c
+h
+7.555 -3.558 m
+7.555 -4.263 7.739 -4.616 8.114 -4.616 c
+8.467 -4.616 8.658 -4.322 8.687 -3.734 c
+8.687 -3.293 l
+8.687 -2.932 8.635 -2.66 8.54 -2.484 c
+8.44 -2.308 8.297 -2.22 8.114 -2.22 c
+7.937 -2.22 7.798 -2.308 7.702 -2.484 c
+7.603 -2.66 7.555 -2.932 7.555 -3.293 c
+h
+11.465 -1.426 m
+11.465 -5.63 l
+11.465 -6.078 11.362 -6.423 11.156 -6.659 c
+10.95 -6.894 10.657 -7.011 10.274 -7.011 c
+10.105 -7.011 9.951 -6.99 9.803 -6.953 c
+9.789 -6.101 l
+9.907 -6.13 9.999 -6.145 10.069 -6.145 c
+10.304 -6.145 10.421 -5.983 10.421 -5.659 c
+10.421 -1.426 l
+h
+10.362 -0.397 m
+10.362 -0.243 10.41 -0.114 10.509 -0.015 c
+10.616 0.091 10.752 0.147 10.921 0.147 c
+11.098 0.147 11.233 0.091 11.333 -0.015 c
+11.439 -0.114 11.494 -0.243 11.494 -0.397 c
+11.494 -0.566 11.439 -0.702 11.333 -0.809 c
+11.233 -0.908 11.098 -0.956 10.921 -0.956 c
+10.744 -0.956 10.605 -0.908 10.509 -0.809 c
+10.41 -0.702 10.362 -0.566 10.362 -0.397 c
+13.832 -5.483 m
+13.302 -5.483 12.883 -5.328 12.582 -5.012 c
+12.288 -4.69 12.141 -4.23 12.141 -3.631 c
+12.141 -3.323 l
+12.141 -2.697 12.277 -2.213 12.552 -1.867 c
+12.824 -1.525 13.217 -1.353 13.728 -1.353 c
+14.229 -1.353 14.599 -1.515 14.846 -1.837 c
+15.099 -2.161 15.232 -2.639 15.243 -3.263 c
+15.243 -3.763 l
+13.17 -3.763 l
+13.188 -4.057 13.251 -4.274 13.361 -4.41 c
+13.479 -4.549 13.659 -4.616 13.905 -4.616 c
+14.247 -4.616 14.537 -4.499 14.772 -4.263 c
+15.184 -4.895 l
+15.056 -5.072 14.867 -5.215 14.626 -5.322 c
+14.379 -5.428 14.115 -5.483 13.832 -5.483 c
+13.184 -3.043 m
+14.214 -3.043 l
+14.214 -2.94 l
+14.214 -2.705 14.173 -2.529 14.096 -2.411 c
+14.026 -2.286 13.898 -2.22 13.714 -2.22 c
+13.537 -2.22 13.406 -2.29 13.317 -2.425 c
+13.236 -2.554 13.192 -2.76 13.184 -3.043 c
+17.271 -4.616 m
+17.565 -4.616 17.716 -4.421 17.726 -4.028 c
+18.697 -4.028 l
+18.697 -4.461 18.565 -4.814 18.3 -5.087 c
+18.035 -5.351 17.697 -5.483 17.286 -5.483 c
+16.775 -5.483 16.382 -5.328 16.11 -5.012 c
+15.845 -4.69 15.706 -4.219 15.698 -3.601 c
+15.698 -3.278 l
+15.698 -2.654 15.831 -2.176 16.095 -1.852 c
+16.367 -1.521 16.764 -1.353 17.286 -1.353 c
+17.716 -1.353 18.057 -1.492 18.314 -1.764 c
+18.568 -2.04 18.697 -2.421 18.697 -2.911 c
+17.726 -2.911 l
+17.726 -2.697 17.686 -2.529 17.609 -2.411 c
+17.539 -2.286 17.422 -2.22 17.256 -2.22 c
+17.08 -2.22 16.951 -2.286 16.874 -2.411 c
+16.793 -2.539 16.749 -2.789 16.742 -3.161 c
+16.742 -3.572 l
+16.742 -3.896 16.756 -4.123 16.786 -4.248 c
+16.822 -4.377 16.878 -4.469 16.947 -4.528 c
+17.025 -4.586 17.132 -4.616 17.271 -4.616 c
+20.505 -0.456 m
+20.505 -1.426 l
+21.034 -1.426 l
+21.034 -2.22 l
+20.505 -2.22 l
+20.505 -4.189 l
+20.505 -4.347 20.523 -4.454 20.564 -4.513 c
+20.612 -4.572 20.696 -4.601 20.814 -4.601 c
+20.92 -4.601 21.005 -4.594 21.063 -4.572 c
+21.063 -5.38 l
+20.887 -5.446 20.696 -5.483 20.49 -5.483 c
+19.814 -5.483 19.469 -5.097 19.461 -4.322 c
+19.461 -2.22 l
+19.006 -2.22 l
+19.006 -1.426 l
+19.461 -1.426 l
+19.461 -0.456 l
+h
+24.297 -1.426 m
+24.327 -1.823 l
+24.562 -1.511 24.863 -1.353 25.238 -1.353 c
+25.921 -1.353 26.274 -1.833 26.296 -2.793 c
+26.296 -5.409 l
+25.252 -5.409 l
+25.252 -2.866 l
+25.252 -2.643 25.216 -2.481 25.15 -2.382 c
+25.08 -2.286 24.963 -2.234 24.797 -2.234 c
+24.61 -2.234 24.463 -2.33 24.356 -2.514 c
+24.356 -5.409 l
+23.312 -5.409 l
+23.312 -1.426 l
+h
+28.928 -5.409 m
+28.898 -5.351 28.868 -5.247 28.839 -5.101 c
+28.652 -5.358 28.402 -5.483 28.09 -5.483 c
+27.756 -5.483 27.476 -5.376 27.251 -5.16 c
+27.035 -4.935 26.929 -4.645 26.929 -4.293 c
+26.929 -3.881 27.06 -3.564 27.326 -3.337 c
+27.59 -3.102 27.972 -2.984 28.471 -2.984 c
+28.795 -2.984 l
+28.795 -2.66 l
+28.795 -2.484 28.758 -2.363 28.693 -2.294 c
+28.633 -2.216 28.545 -2.176 28.427 -2.176 c
+28.17 -2.176 28.045 -2.33 28.045 -2.631 c
+27.002 -2.631 l
+27.002 -2.261 27.137 -1.955 27.413 -1.72 c
+27.685 -1.478 28.034 -1.353 28.457 -1.353 c
+28.898 -1.353 29.236 -1.47 29.471 -1.706 c
+29.714 -1.933 29.838 -2.257 29.838 -2.675 c
+29.838 -4.542 l
+29.838 -4.888 29.886 -5.156 29.986 -5.351 c
+29.986 -5.409 l
+h
+28.325 -4.659 m
+28.431 -4.659 28.523 -4.642 28.604 -4.601 c
+28.693 -4.553 28.755 -4.495 28.795 -4.424 c
+28.795 -3.601 l
+28.545 -3.601 l
+28.369 -3.601 28.226 -3.66 28.119 -3.778 c
+28.02 -3.888 27.972 -4.035 27.972 -4.219 c
+27.972 -4.513 28.09 -4.659 28.325 -4.659 c
+31.559 -1.426 m
+31.588 -1.794 l
+31.823 -1.5 32.132 -1.353 32.514 -1.353 c
+32.915 -1.353 33.194 -1.536 33.352 -1.897 c
+33.587 -1.536 33.914 -1.353 34.337 -1.353 c
+35.031 -1.353 35.384 -1.837 35.395 -2.808 c
+35.395 -5.409 l
+34.366 -5.409 l
+34.366 -2.866 l
+34.366 -2.643 34.329 -2.481 34.263 -2.382 c
+34.204 -2.286 34.094 -2.234 33.94 -2.234 c
+33.741 -2.234 33.601 -2.352 33.514 -2.587 c
+33.514 -5.409 l
+32.47 -5.409 l
+32.47 -2.882 l
+32.47 -2.646 32.44 -2.481 32.381 -2.382 c
+32.323 -2.286 32.213 -2.234 32.059 -2.234 c
+31.882 -2.234 31.739 -2.33 31.632 -2.514 c
+31.632 -5.409 l
+30.588 -5.409 l
+30.588 -1.426 l
+h
+37.776 -5.483 m
+37.247 -5.483 36.828 -5.328 36.527 -5.012 c
+36.233 -4.69 36.086 -4.23 36.086 -3.631 c
+36.086 -3.323 l
+36.086 -2.697 36.222 -2.213 36.498 -1.867 c
+36.77 -1.525 37.163 -1.353 37.674 -1.353 c
+38.173 -1.353 38.544 -1.515 38.79 -1.837 c
+39.044 -2.161 39.176 -2.639 39.187 -3.263 c
+39.187 -3.763 l
+37.115 -3.763 l
+37.133 -4.057 37.196 -4.274 37.306 -4.41 c
+37.424 -4.549 37.603 -4.616 37.85 -4.616 c
+38.191 -4.616 38.482 -4.499 38.717 -4.263 c
+39.128 -4.895 l
+39 -5.072 38.812 -5.215 38.57 -5.322 c
+38.324 -5.428 38.059 -5.483 37.776 -5.483 c
+37.129 -3.043 m
+38.158 -3.043 l
+38.158 -2.94 l
+38.158 -2.705 38.118 -2.529 38.041 -2.411 c
+37.971 -2.286 37.842 -2.22 37.659 -2.22 c
+37.482 -2.22 37.35 -2.29 37.262 -2.425 c
+37.181 -2.554 37.137 -2.76 37.129 -3.043 c
+39.525 0.823 m
+40.951 0.823 l
+40.951 -6.659 l
+39.525 -6.659 l
+39.525 -5.835 l
+39.907 -5.835 l
+39.907 0 l
+39.525 0 l
+h
+f
+Q
+191.474 265.313 -0.647 3.983 re
+191.518 270.34 m
+191.518 270.229 191.488 270.138 191.43 270.061 c
+191.371 269.991 191.276 269.958 191.151 269.958 c
+191.033 269.958 190.937 269.991 190.871 270.061 c
+190.813 270.138 190.783 270.229 190.783 270.34 c
+190.783 270.457 190.813 270.549 190.871 270.619 c
+190.937 270.696 191.033 270.737 191.151 270.737 c
+191.276 270.737 191.371 270.696 191.43 270.619 c
+191.488 270.538 191.518 270.447 191.518 270.34 c
+194.428 266.327 m
+194.428 266.474 194.374 266.595 194.267 266.694 c
+194.156 266.79 193.951 266.908 193.649 267.047 c
+193.304 267.195 193.061 267.316 192.915 267.415 c
+192.768 267.521 192.658 267.639 192.591 267.768 c
+192.521 267.893 192.488 268.051 192.488 268.238 c
+192.488 268.562 192.606 268.83 192.841 269.046 c
+193.076 269.26 193.377 269.37 193.753 269.37 c
+194.135 269.37 194.443 269.256 194.678 269.032 c
+194.914 268.804 195.031 268.517 195.031 268.165 c
+194.384 268.165 l
+194.384 268.34 194.326 268.492 194.208 268.62 c
+194.09 268.745 193.936 268.811 193.753 268.811 c
+193.554 268.811 193.404 268.756 193.296 268.65 c
+193.186 268.55 193.135 268.419 193.135 268.253 c
+193.135 268.124 193.171 268.018 193.252 267.929 c
+193.329 267.848 193.521 267.746 193.826 267.621 c
+194.304 267.434 194.634 267.245 194.811 267.062 c
+194.987 266.886 195.075 266.657 195.075 266.386 c
+195.075 266.033 194.95 265.753 194.708 265.548 c
+194.472 265.342 194.156 265.24 193.767 265.24 c
+193.344 265.24 193.007 265.357 192.753 265.593 c
+192.496 265.834 192.371 266.14 192.371 266.503 c
+193.017 266.503 l
+193.025 266.276 193.094 266.1 193.223 265.974 c
+193.348 265.857 193.532 265.798 193.767 265.798 c
+193.98 265.798 194.142 265.846 194.252 265.945 c
+194.37 266.04 194.428 266.169 194.428 266.327 c
+200.514 267.106 m
+200.514 266.478 200.396 266.007 200.161 265.695 c
+199.933 265.39 199.617 265.24 199.206 265.24 c
+198.802 265.24 198.493 265.39 198.28 265.695 c
+198.28 263.784 l
+197.633 263.784 l
+197.633 269.296 l
+198.221 269.296 l
+198.265 268.855 l
+198.478 269.197 198.787 269.37 199.191 269.37 c
+199.632 269.37 199.959 269.215 200.176 268.914 c
+200.389 268.609 200.503 268.153 200.514 267.547 c
+h
+199.868 267.488 m
+199.868 267.929 199.797 268.253 199.662 268.458 c
+199.521 268.672 199.301 268.782 199 268.782 c
+198.684 268.782 198.445 268.627 198.28 268.326 c
+198.28 266.254 l
+198.445 265.949 198.684 265.798 199 265.798 c
+199.294 265.798 199.507 265.901 199.646 266.106 c
+199.783 266.32 199.856 266.651 199.868 267.091 c
+h
+202.998 268.679 m
+202.91 268.697 202.811 268.708 202.704 268.708 c
+202.37 268.708 202.135 268.525 201.998 268.165 c
+201.998 265.313 l
+201.352 265.313 l
+201.352 269.296 l
+201.984 269.296 l
+201.998 268.885 l
+202.175 269.208 202.418 269.37 202.734 269.37 c
+202.84 269.37 202.929 269.348 202.998 269.311 c
+h
+203.44 267.488 m
+203.44 268.066 203.575 268.521 203.851 268.855 c
+204.134 269.197 204.504 269.37 204.967 269.37 c
+205.427 269.37 205.794 269.201 206.07 268.87 c
+206.353 268.546 206.5 268.099 206.511 267.532 c
+206.511 267.106 l
+206.511 266.537 206.368 266.081 206.085 265.739 c
+205.809 265.404 205.441 265.24 204.982 265.24 c
+204.52 265.24 204.148 265.401 203.866 265.724 c
+203.59 266.055 203.446 266.497 203.44 267.047 c
+h
+204.086 267.106 m
+204.086 266.702 204.163 266.386 204.321 266.15 c
+204.487 265.915 204.707 265.798 204.982 265.798 c
+205.549 265.798 205.842 266.21 205.865 267.033 c
+205.865 267.488 l
+205.865 267.889 205.78 268.209 205.615 268.444 c
+205.456 268.687 205.24 268.811 204.967 268.811 c
+204.703 268.811 204.487 268.687 204.321 268.444 c
+204.163 268.209 204.086 267.889 204.086 267.488 c
+h
+208.422 266.298 m
+209.171 269.296 l
+209.833 269.296 l
+208.657 265.313 l
+208.172 265.313 l
+206.981 269.296 l
+207.643 269.296 l
+h
+211.215 265.313 -0.646 3.983 re
+211.259 270.34 m
+211.259 270.229 211.23 270.138 211.171 270.061 c
+211.112 269.991 211.016 269.958 210.891 269.958 c
+210.774 269.958 210.679 269.991 210.612 270.061 c
+210.553 270.138 210.524 270.229 210.524 270.34 c
+210.524 270.457 210.553 270.549 210.612 270.619 c
+210.679 270.696 210.774 270.737 210.891 270.737 c
+211.016 270.737 211.112 270.696 211.171 270.619 c
+211.23 270.538 211.259 270.447 211.259 270.34 c
+212.097 267.488 m
+212.097 268.095 212.207 268.562 212.435 268.885 c
+212.67 269.208 212.997 269.37 213.42 269.37 c
+213.802 269.37 214.1 269.212 214.316 268.899 c
+214.316 270.958 l
+214.964 270.958 l
+214.964 265.313 l
+214.375 265.313 l
+214.331 265.739 l
+214.125 265.404 213.821 265.24 213.42 265.24 c
+213.008 265.24 212.685 265.394 212.45 265.71 c
+212.215 266.033 212.097 266.489 212.097 267.077 c
+h
+212.743 267.106 m
+212.743 266.665 212.806 266.335 212.934 266.121 c
+213.071 265.915 213.291 265.813 213.596 265.813 c
+213.919 265.813 214.158 265.974 214.316 266.298 c
+214.316 268.311 l
+214.147 268.624 213.908 268.782 213.596 268.782 c
+213.291 268.782 213.071 268.679 212.934 268.473 c
+212.806 268.267 212.743 267.944 212.743 267.503 c
+h
+217.389 265.24 m
+216.888 265.24 216.506 265.387 216.242 265.68 c
+215.978 265.974 215.845 266.408 215.845 266.989 c
+215.845 267.459 l
+215.845 268.054 215.97 268.521 216.227 268.855 c
+216.491 269.197 216.852 269.37 217.315 269.37 c
+217.775 269.37 218.116 269.215 218.344 268.914 c
+218.579 268.62 218.7 268.157 218.712 267.532 c
+218.712 267.106 l
+216.491 267.106 l
+216.491 267.018 l
+216.491 266.584 216.569 266.272 216.727 266.077 c
+216.892 265.89 217.124 265.798 217.418 265.798 c
+217.613 265.798 217.786 265.832 217.933 265.901 c
+218.079 265.978 218.216 266.096 218.344 266.254 c
+218.682 265.842 l
+218.395 265.438 217.965 265.24 217.389 265.24 c
+217.315 268.811 m
+217.04 268.811 216.838 268.716 216.712 268.532 c
+216.584 268.344 216.51 268.054 216.491 267.665 c
+218.064 267.665 l
+218.064 267.753 l
+218.043 268.135 217.977 268.403 217.859 268.562 c
+217.742 268.727 217.557 268.811 217.315 268.811 c
+219.358 267.488 m
+219.358 268.095 219.469 268.562 219.696 268.885 c
+219.932 269.208 220.258 269.37 220.681 269.37 c
+221.063 269.37 221.361 269.212 221.578 268.899 c
+221.578 270.958 l
+222.224 270.958 l
+222.224 265.313 l
+221.636 265.313 l
+221.592 265.739 l
+221.387 265.404 221.081 265.24 220.681 265.24 c
+220.269 265.24 219.946 265.394 219.711 265.71 c
+219.475 266.033 219.358 266.489 219.358 267.077 c
+h
+220.005 267.106 m
+220.005 266.665 220.067 266.335 220.196 266.121 c
+220.332 265.915 220.553 265.813 220.857 265.813 c
+221.181 265.813 221.42 265.974 221.578 266.298 c
+221.578 268.311 l
+221.409 268.624 221.17 268.782 220.857 268.782 c
+220.553 268.782 220.332 268.679 220.196 268.473 c
+220.067 268.267 220.005 267.944 220.005 267.503 c
+h
+223.238 264.24 m
+222.841 264.504 l
+223.077 264.828 223.198 265.163 223.209 265.504 c
+223.209 266.121 l
+223.871 266.121 l
+223.871 265.593 l
+223.871 265.335 223.805 265.088 223.68 264.843 c
+223.562 264.6 223.415 264.398 223.238 264.24 c
+229.868 265.974 m
+229.75 265.828 l
+229.416 265.435 228.919 265.24 228.266 265.24 c
+227.685 265.24 227.23 265.431 226.899 265.813 c
+226.575 266.195 226.407 266.738 226.399 267.444 c
+226.399 268.488 l
+226.399 269.242 226.546 269.803 226.839 270.179 c
+227.141 270.549 227.593 270.737 228.192 270.737 c
+228.699 270.737 229.096 270.594 229.383 270.31 c
+229.677 270.024 229.839 269.62 229.868 269.09 c
+229.191 269.09 l
+229.17 269.421 229.077 269.682 228.913 269.869 c
+228.755 270.065 228.52 270.164 228.207 270.164 c
+227.814 270.164 227.531 270.035 227.354 269.782 c
+227.178 269.524 227.082 269.124 227.075 268.576 c
+227.075 267.488 l
+227.075 266.948 227.178 266.533 227.384 266.239 c
+227.589 265.952 227.884 265.813 228.266 265.813 c
+228.626 265.813 228.905 265.901 229.104 266.077 c
+229.191 266.165 l
+229.191 267.4 l
+228.221 267.4 l
+228.221 267.974 l
+229.868 267.974 l
+h
+231.587 265.313 -0.646 3.983 re
+231.632 270.34 m
+231.632 270.229 231.602 270.138 231.543 270.061 c
+231.485 269.991 231.389 269.958 231.265 269.958 c
+231.147 269.958 231.051 269.991 230.985 270.061 c
+230.926 270.138 230.897 270.229 230.897 270.34 c
+230.897 270.457 230.926 270.549 230.985 270.619 c
+231.051 270.696 231.147 270.737 231.265 270.737 c
+231.389 270.737 231.485 270.696 231.543 270.619 c
+231.602 270.538 231.632 270.447 231.632 270.34 c
+233.455 270.252 m
+233.455 269.296 l
+234.057 269.296 l
+234.057 268.768 l
+233.455 268.768 l
+233.455 266.298 l
+233.455 266.14 233.476 266.022 233.528 265.945 c
+233.586 265.864 233.675 265.828 233.792 265.828 c
+233.881 265.828 233.969 265.842 234.057 265.871 c
+234.057 265.313 l
+233.91 265.265 233.756 265.24 233.602 265.24 c
+233.345 265.24 233.15 265.331 233.014 265.518 c
+232.874 265.703 232.808 265.963 232.808 266.298 c
+232.808 268.768 l
+232.205 268.768 l
+232.205 269.296 l
+232.808 269.296 l
+232.808 270.252 l
+h
+239.51 266.459 m
+240.113 269.296 l
+240.76 269.296 l
+239.775 265.313 l
+239.261 265.313 l
+238.482 268.165 l
+237.732 265.313 l
+237.203 265.313 l
+236.247 269.296 l
+236.879 269.296 l
+237.497 266.533 l
+238.232 269.296 l
+238.746 269.296 l
+h
+242.142 265.313 -0.646 3.983 re
+242.186 270.34 m
+242.186 270.229 242.157 270.138 242.097 270.061 c
+242.039 269.991 241.943 269.958 241.818 269.958 c
+241.7 269.958 241.605 269.991 241.539 270.061 c
+241.48 270.138 241.451 270.229 241.451 270.34 c
+241.451 270.457 241.48 270.549 241.539 270.619 c
+241.605 270.696 241.7 270.737 241.818 270.737 c
+241.943 270.737 242.039 270.696 242.097 270.619 c
+242.157 270.538 242.186 270.447 242.186 270.34 c
+243.861 265.313 -0.646 5.644 re
+245.581 265.313 -0.646 5.644 re
+249.697 265.798 m
+249.91 265.798 250.083 265.861 250.211 265.989 c
+250.348 266.125 250.421 266.316 250.432 266.562 c
+251.049 266.562 l
+251.027 266.181 250.891 265.861 250.637 265.607 c
+250.381 265.361 250.068 265.24 249.697 265.24 c
+249.205 265.24 248.83 265.39 248.565 265.695 c
+248.308 266.007 248.183 266.474 248.183 267.091 c
+248.183 267.532 l
+248.183 268.128 248.308 268.583 248.565 268.899 c
+248.83 269.212 249.205 269.37 249.697 269.37 c
+250.097 269.37 250.417 269.238 250.652 268.973 c
+250.895 268.716 251.027 268.371 251.049 267.929 c
+250.432 267.929 l
+250.41 268.223 250.336 268.444 250.211 268.591 c
+250.094 268.737 249.921 268.811 249.697 268.811 c
+249.403 268.811 249.186 268.712 249.05 268.517 c
+248.91 268.33 248.837 268.022 248.83 267.592 c
+248.83 267.077 l
+248.83 266.607 248.896 266.272 249.035 266.077 c
+249.182 265.89 249.403 265.798 249.697 265.798 c
+253.445 268.679 m
+253.357 268.697 253.258 268.708 253.151 268.708 c
+252.817 268.708 252.582 268.525 252.445 268.165 c
+252.445 265.313 l
+251.799 265.313 l
+251.799 269.296 l
+252.431 269.296 l
+252.445 268.885 l
+252.622 269.208 252.865 269.37 253.18 269.37 c
+253.287 269.37 253.376 269.348 253.445 269.311 c
+h
+255.445 265.24 m
+254.945 265.24 254.562 265.387 254.298 265.68 c
+254.033 265.974 253.901 266.408 253.901 266.989 c
+253.901 267.459 l
+253.901 268.054 254.026 268.521 254.283 268.855 c
+254.548 269.197 254.907 269.37 255.371 269.37 c
+255.83 269.37 256.172 269.215 256.399 268.914 c
+256.635 268.62 256.756 268.157 256.767 267.532 c
+256.767 267.106 l
+254.548 267.106 l
+254.548 267.018 l
+254.548 266.584 254.625 266.272 254.783 266.077 c
+254.948 265.89 255.18 265.798 255.474 265.798 c
+255.668 265.798 255.842 265.832 255.988 265.901 c
+256.135 265.978 256.271 266.096 256.399 266.254 c
+256.738 265.842 l
+256.451 265.438 256.021 265.24 255.445 265.24 c
+255.371 268.811 m
+255.096 268.811 254.893 268.716 254.768 268.532 c
+254.639 268.344 254.566 268.054 254.548 267.665 c
+256.121 267.665 l
+256.121 267.753 l
+256.098 268.135 256.033 268.403 255.915 268.562 c
+255.797 268.727 255.613 268.811 255.371 268.811 c
+259.589 265.313 m
+259.549 265.401 259.524 265.548 259.516 265.753 c
+259.281 265.408 258.986 265.24 258.634 265.24 c
+258.271 265.24 257.987 265.335 257.781 265.533 c
+257.583 265.739 257.488 266.026 257.488 266.401 c
+257.488 266.801 257.623 267.121 257.899 267.356 c
+258.171 267.598 258.546 267.723 259.017 267.723 c
+259.501 267.723 l
+259.501 268.149 l
+259.501 268.385 259.446 268.55 259.339 268.65 c
+259.229 268.756 259.067 268.811 258.855 268.811 c
+258.656 268.811 258.494 268.753 258.369 268.635 c
+258.252 268.517 258.193 268.371 258.193 268.194 c
+257.546 268.194 l
+257.546 268.388 257.605 268.579 257.723 268.768 c
+257.847 268.951 258.009 269.098 258.208 269.208 c
+258.414 269.315 258.641 269.37 258.899 269.37 c
+259.299 269.37 259.604 269.267 259.81 269.061 c
+260.023 268.855 260.137 268.562 260.148 268.18 c
+260.148 266.165 l
+260.148 265.861 260.185 265.596 260.266 265.371 c
+260.266 265.313 l
+h
+258.722 265.828 m
+258.888 265.828 259.038 265.871 259.178 265.959 c
+259.325 266.048 259.431 266.158 259.501 266.298 c
+259.501 267.239 l
+259.134 267.239 l
+258.818 267.239 258.575 267.168 258.398 267.033 c
+258.223 266.904 258.134 266.717 258.134 266.474 c
+258.134 266.246 258.178 266.081 258.267 265.974 c
+258.354 265.875 258.506 265.828 258.722 265.828 c
+262.001 270.252 m
+262.001 269.296 l
+262.603 269.296 l
+262.603 268.768 l
+262.001 268.768 l
+262.001 266.298 l
+262.001 266.14 262.022 266.022 262.074 265.945 c
+262.132 265.864 262.221 265.828 262.338 265.828 c
+262.427 265.828 262.514 265.842 262.603 265.871 c
+262.603 265.313 l
+262.456 265.265 262.302 265.24 262.147 265.24 c
+261.89 265.24 261.695 265.331 261.559 265.518 c
+261.419 265.703 261.353 265.963 261.353 266.298 c
+261.353 268.768 l
+260.75 268.768 l
+260.75 269.296 l
+261.353 269.296 l
+261.353 270.252 l
+h
+264.793 265.24 m
+264.293 265.24 263.911 265.387 263.647 265.68 c
+263.382 265.974 263.25 266.408 263.25 266.989 c
+263.25 267.459 l
+263.25 268.054 263.374 268.521 263.632 268.855 c
+263.896 269.197 264.256 269.37 264.719 269.37 c
+265.178 269.37 265.521 269.215 265.748 268.914 c
+265.984 268.62 266.105 268.157 266.115 267.532 c
+266.115 267.106 l
+263.896 267.106 l
+263.896 267.018 l
+263.896 266.584 263.973 266.272 264.131 266.077 c
+264.297 265.89 264.528 265.798 264.823 265.798 c
+265.018 265.798 265.19 265.832 265.336 265.901 c
+265.484 265.978 265.62 266.096 265.748 266.254 c
+266.086 265.842 l
+265.8 265.438 265.37 265.24 264.793 265.24 c
+264.719 268.811 m
+264.444 268.811 264.241 268.716 264.117 268.532 c
+263.988 268.344 263.915 268.054 263.896 267.665 c
+265.469 267.665 l
+265.469 267.753 l
+265.447 268.135 265.381 268.403 265.263 268.562 c
+265.145 268.727 264.962 268.811 264.719 268.811 c
+f
+q 1 0 0 1 41.8817 255.9058 cm
+0 0 m
+-0.04 0.087 -0.066 0.235 -0.073 0.44 c
+-0.309 0.095 -0.603 -0.073 -0.955 -0.073 c
+-1.319 -0.073 -1.602 0.022 -1.808 0.22 c
+-2.007 0.426 -2.102 0.713 -2.102 1.087 c
+-2.102 1.488 -1.966 1.808 -1.691 2.043 c
+-1.419 2.285 -1.043 2.41 -0.573 2.41 c
+-0.088 2.41 l
+-0.088 2.836 l
+-0.088 3.072 -0.143 3.237 -0.249 3.337 c
+-0.36 3.443 -0.522 3.498 -0.735 3.498 c
+-0.933 3.498 -1.095 3.439 -1.22 3.322 c
+-1.338 3.204 -1.396 3.057 -1.396 2.881 c
+-2.043 2.881 l
+-2.043 3.075 -1.984 3.266 -1.866 3.454 c
+-1.741 3.638 -1.58 3.785 -1.382 3.895 c
+-1.176 4.002 -0.948 4.056 -0.691 4.056 c
+-0.29 4.056 0.015 3.954 0.221 3.748 c
+0.434 3.542 0.548 3.248 0.559 2.866 c
+0.559 0.852 l
+0.559 0.548 0.595 0.283 0.676 0.058 c
+0.676 0 l
+h
+-0.867 0.515 m
+-0.702 0.515 -0.551 0.558 -0.411 0.646 c
+-0.264 0.735 -0.158 0.845 -0.088 0.985 c
+-0.088 1.926 l
+-0.455 1.926 l
+-0.771 1.926 -1.014 1.855 -1.19 1.72 c
+-1.367 1.591 -1.455 1.404 -1.455 1.161 c
+-1.455 0.933 -1.411 0.768 -1.323 0.661 c
+-1.234 0.562 -1.084 0.515 -0.867 0.515 c
+3.896 3.983 m
+3.91 3.542 l
+4.164 3.884 4.487 4.056 4.881 4.056 c
+5.586 4.056 5.943 3.586 5.953 2.645 c
+5.953 0 l
+5.307 0 l
+5.307 2.616 l
+5.307 2.929 5.251 3.149 5.145 3.278 c
+5.035 3.403 4.881 3.469 4.675 3.469 c
+4.516 3.469 4.37 3.414 4.233 3.307 c
+4.104 3.197 4.002 3.061 3.925 2.896 c
+3.925 0 l
+3.278 0 l
+3.278 3.983 l
+h
+8.349 -0.073 m
+7.85 -0.073 7.468 0.073 7.202 0.367 c
+6.938 0.661 6.806 1.095 6.806 1.675 c
+6.806 2.146 l
+6.806 2.741 6.93 3.208 7.188 3.542 c
+7.453 3.884 7.813 4.056 8.276 4.056 c
+8.735 4.056 9.077 3.902 9.305 3.601 c
+9.54 3.307 9.661 2.844 9.672 2.219 c
+9.672 1.793 l
+7.453 1.793 l
+7.453 1.705 l
+7.453 1.271 7.53 0.959 7.688 0.764 c
+7.853 0.577 8.085 0.484 8.378 0.484 c
+8.573 0.484 8.746 0.518 8.893 0.588 c
+9.04 0.665 9.176 0.783 9.305 0.941 c
+9.643 0.529 l
+9.356 0.125 8.926 -0.073 8.349 -0.073 c
+8.276 3.498 m
+8 3.498 7.798 3.403 7.673 3.219 c
+7.545 3.031 7.471 2.741 7.453 2.352 c
+9.025 2.352 l
+9.025 2.439 l
+9.003 2.822 8.937 3.09 8.819 3.248 c
+8.702 3.414 8.518 3.498 8.276 3.498 c
+13.421 1.146 m
+14.023 3.983 l
+14.67 3.983 l
+13.685 0 l
+13.17 0 l
+12.391 2.851 l
+11.642 0 l
+11.113 0 l
+10.157 3.983 l
+10.789 3.983 l
+11.406 1.22 l
+12.141 3.983 l
+12.656 3.983 l
+h
+16.933 2.175 m
+16.933 2.782 17.043 3.248 17.271 3.572 c
+17.506 3.895 17.834 4.056 18.256 4.056 c
+18.639 4.056 18.936 3.898 19.153 3.586 c
+19.153 5.644 l
+19.8 5.644 l
+19.8 0 l
+19.212 0 l
+19.168 0.426 l
+18.962 0.091 18.657 -0.073 18.256 -0.073 c
+17.845 -0.073 17.521 0.081 17.286 0.397 c
+17.051 0.72 16.933 1.176 16.933 1.764 c
+h
+17.581 1.793 m
+17.581 1.352 17.643 1.022 17.771 0.808 c
+17.907 0.602 18.128 0.5 18.433 0.5 c
+18.756 0.5 18.995 0.661 19.153 0.985 c
+19.153 2.998 l
+18.984 3.31 18.745 3.469 18.433 3.469 c
+18.128 3.469 17.907 3.366 17.771 3.16 c
+17.643 2.954 17.581 2.631 17.581 2.19 c
+h
+21.504 0 -0.646 3.983 re
+21.549 5.026 m
+21.549 4.916 21.519 4.825 21.461 4.748 c
+21.402 4.677 21.307 4.644 21.182 4.644 c
+21.064 4.644 20.968 4.677 20.902 4.748 c
+20.843 4.825 20.814 4.916 20.814 5.026 c
+20.814 5.144 20.843 5.236 20.902 5.306 c
+20.968 5.383 21.064 5.423 21.182 5.423 c
+21.307 5.423 21.402 5.383 21.461 5.306 c
+21.519 5.225 21.549 5.134 21.549 5.026 c
+24.166 3.366 m
+24.077 3.384 23.978 3.395 23.871 3.395 c
+23.537 3.395 23.302 3.212 23.166 2.851 c
+23.166 0 l
+22.519 0 l
+22.519 3.983 l
+23.151 3.983 l
+23.166 3.572 l
+23.343 3.895 23.584 4.056 23.9 4.056 c
+24.008 4.056 24.095 4.035 24.166 3.998 c
+h
+26.165 -0.073 m
+25.664 -0.073 25.282 0.073 25.018 0.367 c
+24.754 0.661 24.621 1.095 24.621 1.675 c
+24.621 2.146 l
+24.621 2.741 24.746 3.208 25.003 3.542 c
+25.267 3.884 25.628 4.056 26.091 4.056 c
+26.55 4.056 26.892 3.902 27.12 3.601 c
+27.355 3.307 27.476 2.844 27.487 2.219 c
+27.487 1.793 l
+25.267 1.793 l
+25.267 1.705 l
+25.267 1.271 25.345 0.959 25.503 0.764 c
+25.668 0.577 25.899 0.484 26.194 0.484 c
+26.389 0.484 26.562 0.518 26.709 0.588 c
+26.855 0.665 26.992 0.783 27.12 0.941 c
+27.458 0.529 l
+27.171 0.125 26.741 -0.073 26.165 -0.073 c
+26.091 3.498 m
+25.816 3.498 25.614 3.403 25.488 3.219 c
+25.36 3.031 25.286 2.741 25.267 2.352 c
+26.84 2.352 l
+26.84 2.439 l
+26.819 2.822 26.753 3.09 26.635 3.248 c
+26.518 3.414 26.333 3.498 26.091 3.498 c
+29.648 0.484 m
+29.861 0.484 30.034 0.548 30.163 0.675 c
+30.298 0.812 30.372 1.003 30.383 1.249 c
+31 1.249 l
+30.979 0.867 30.842 0.548 30.589 0.294 c
+30.331 0.048 30.019 -0.073 29.648 -0.073 c
+29.155 -0.073 28.781 0.077 28.517 0.382 c
+28.259 0.694 28.134 1.161 28.134 1.778 c
+28.134 2.219 l
+28.134 2.815 28.259 3.27 28.517 3.586 c
+28.781 3.898 29.155 4.056 29.648 4.056 c
+30.049 4.056 30.368 3.925 30.603 3.659 c
+30.846 3.403 30.979 3.057 31 2.616 c
+30.383 2.616 l
+30.361 2.91 30.287 3.131 30.163 3.278 c
+30.045 3.424 29.872 3.498 29.648 3.498 c
+29.354 3.498 29.138 3.399 29.001 3.204 c
+28.862 3.017 28.788 2.708 28.781 2.278 c
+28.781 1.764 l
+28.781 1.294 28.847 0.959 28.987 0.764 c
+29.134 0.577 29.354 0.484 29.648 0.484 c
+32.602 4.939 m
+32.602 3.983 l
+33.205 3.983 l
+33.205 3.454 l
+32.602 3.454 l
+32.602 0.985 l
+32.602 0.827 32.625 0.709 32.677 0.632 c
+32.735 0.551 32.823 0.515 32.941 0.515 c
+33.028 0.515 33.117 0.529 33.205 0.558 c
+33.205 0 l
+33.059 -0.048 32.904 -0.073 32.75 -0.073 c
+32.492 -0.073 32.297 0.018 32.162 0.205 c
+32.022 0.389 31.956 0.65 31.956 0.985 c
+31.956 3.454 l
+31.353 3.454 l
+31.353 3.983 l
+31.956 3.983 l
+31.956 4.939 l
+h
+33.764 2.175 m
+33.764 2.753 33.9 3.208 34.175 3.542 c
+34.458 3.884 34.83 4.056 35.293 4.056 c
+35.752 4.056 36.12 3.888 36.395 3.557 c
+36.678 3.233 36.825 2.786 36.836 2.219 c
+36.836 1.793 l
+36.836 1.224 36.693 0.768 36.409 0.426 c
+36.134 0.091 35.767 -0.073 35.307 -0.073 c
+34.844 -0.073 34.473 0.087 34.19 0.411 c
+33.915 0.742 33.772 1.183 33.764 1.734 c
+h
+34.41 1.793 m
+34.41 1.389 34.488 1.072 34.646 0.837 c
+34.811 0.602 35.031 0.484 35.307 0.484 c
+35.873 0.484 36.167 0.897 36.189 1.72 c
+36.189 2.175 l
+36.189 2.576 36.105 2.896 35.939 3.131 c
+35.781 3.374 35.565 3.498 35.293 3.498 c
+35.028 3.498 34.811 3.374 34.646 3.131 c
+34.488 2.896 34.41 2.576 34.41 2.175 c
+h
+39.32 3.366 m
+39.232 3.384 39.133 3.395 39.027 3.395 c
+38.692 3.395 38.456 3.212 38.321 2.851 c
+38.321 0 l
+37.674 0 l
+37.674 3.983 l
+38.306 3.983 l
+38.321 3.572 l
+38.497 3.895 38.74 4.056 39.056 4.056 c
+39.162 4.056 39.25 4.035 39.32 3.998 c
+h
+41.128 1.087 m
+41.849 3.983 l
+42.539 3.983 l
+41.246 -0.559 l
+41.146 -0.9 41.003 -1.162 40.82 -1.338 c
+40.643 -1.515 40.441 -1.602 40.217 -1.602 c
+40.128 -1.602 40.014 -1.58 39.879 -1.544 c
+39.879 -1 l
+40.026 -1.014 l
+40.209 -1.014 40.357 -0.971 40.467 -0.882 c
+40.573 -0.794 40.662 -0.636 40.731 -0.412 c
+40.849 0.029 l
+39.688 3.983 l
+40.393 3.983 l
+h
+45.508 3.983 m
+45.523 3.542 l
+45.776 3.884 46.1 4.056 46.493 4.056 c
+47.199 4.056 47.555 3.586 47.567 2.645 c
+47.567 0 l
+46.919 0 l
+46.919 2.616 l
+46.919 2.929 46.865 3.149 46.758 3.278 c
+46.648 3.403 46.493 3.469 46.287 3.469 c
+46.129 3.469 45.982 3.414 45.847 3.307 c
+45.718 3.197 45.615 3.061 45.537 2.896 c
+45.537 0 l
+44.891 0 l
+44.891 3.983 l
+h
+50.58 0 m
+50.539 0.087 50.513 0.235 50.506 0.44 c
+50.271 0.095 49.977 -0.073 49.624 -0.073 c
+49.26 -0.073 48.978 0.022 48.772 0.22 c
+48.573 0.426 48.477 0.713 48.477 1.087 c
+48.477 1.488 48.614 1.808 48.889 2.043 c
+49.161 2.285 49.536 2.41 50.006 2.41 c
+50.491 2.41 l
+50.491 2.836 l
+50.491 3.072 50.436 3.237 50.33 3.337 c
+50.219 3.443 50.058 3.498 49.845 3.498 c
+49.647 3.498 49.485 3.439 49.36 3.322 c
+49.242 3.204 49.183 3.057 49.183 2.881 c
+48.536 2.881 l
+48.536 3.075 48.595 3.266 48.712 3.454 c
+48.838 3.638 48.999 3.785 49.198 3.895 c
+49.404 4.002 49.632 4.056 49.888 4.056 c
+50.289 4.056 50.594 3.954 50.8 3.748 c
+51.013 3.542 51.127 3.248 51.138 2.866 c
+51.138 0.852 l
+51.138 0.548 51.175 0.283 51.256 0.058 c
+51.256 0 l
+h
+49.712 0.515 m
+49.878 0.515 50.029 0.558 50.168 0.646 c
+50.315 0.735 50.422 0.845 50.491 0.985 c
+50.491 1.926 l
+50.124 1.926 l
+49.807 1.926 49.566 1.855 49.389 1.72 c
+49.213 1.591 49.124 1.404 49.124 1.161 c
+49.124 0.933 49.169 0.768 49.256 0.661 c
+49.345 0.562 49.495 0.515 49.712 0.515 c
+52.755 3.983 m
+52.77 3.615 l
+53.013 3.91 53.332 4.056 53.725 4.056 c
+54.166 4.056 54.474 3.858 54.651 3.469 c
+54.904 3.858 55.254 4.056 55.695 4.056 c
+56.43 4.056 56.805 3.594 56.826 2.675 c
+56.826 0 l
+56.18 0 l
+56.18 2.616 l
+56.18 2.91 56.125 3.123 56.018 3.262 c
+55.919 3.399 55.746 3.469 55.504 3.469 c
+55.305 3.469 55.143 3.388 55.019 3.233 c
+54.901 3.087 54.831 2.896 54.813 2.66 c
+54.813 0 l
+54.152 0 l
+54.152 2.645 l
+54.152 3.193 53.931 3.469 53.49 3.469 c
+53.156 3.469 52.92 3.307 52.784 2.984 c
+52.784 0 l
+52.138 0 l
+52.138 3.983 l
+h
+59.222 -0.073 m
+58.723 -0.073 58.341 0.073 58.077 0.367 c
+57.811 0.661 57.68 1.095 57.68 1.675 c
+57.68 2.146 l
+57.68 2.741 57.804 3.208 58.061 3.542 c
+58.326 3.884 58.686 4.056 59.149 4.056 c
+59.608 4.056 59.951 3.902 60.178 3.601 c
+60.413 3.307 60.535 2.844 60.545 2.219 c
+60.545 1.793 l
+58.326 1.793 l
+58.326 1.705 l
+58.326 1.271 58.403 0.959 58.561 0.764 c
+58.727 0.577 58.958 0.484 59.252 0.484 c
+59.447 0.484 59.619 0.518 59.766 0.588 c
+59.914 0.665 60.049 0.783 60.178 0.941 c
+60.516 0.529 l
+60.23 0.125 59.8 -0.073 59.222 -0.073 c
+59.149 3.498 m
+58.873 3.498 58.671 3.403 58.547 3.219 c
+58.418 3.031 58.345 2.741 58.326 2.352 c
+59.899 2.352 l
+59.899 2.439 l
+59.877 2.822 59.81 3.09 59.693 3.248 c
+59.575 3.414 59.392 3.498 59.149 3.498 c
+61.192 2.175 m
+61.192 2.782 61.302 3.248 61.53 3.572 c
+61.765 3.895 62.093 4.056 62.515 4.056 c
+62.897 4.056 63.195 3.898 63.411 3.586 c
+63.411 5.644 l
+64.059 5.644 l
+64.059 0 l
+63.471 0 l
+63.427 0.426 l
+63.221 0.091 62.916 -0.073 62.515 -0.073 c
+62.104 -0.073 61.78 0.081 61.545 0.397 c
+61.31 0.72 61.192 1.176 61.192 1.764 c
+h
+61.84 1.793 m
+61.84 1.352 61.902 1.022 62.03 0.808 c
+62.166 0.602 62.387 0.5 62.692 0.5 c
+63.015 0.5 63.253 0.661 63.411 0.985 c
+63.411 2.998 l
+63.243 3.31 63.004 3.469 62.692 3.469 c
+62.387 3.469 62.166 3.366 62.03 3.16 c
+61.902 2.954 61.84 2.631 61.84 2.19 c
+h
+f
+Q
+q 1 0 0 1 110.0119 261.315 cm
+0 0 m
+-0.382 0 l
+-0.382 -5.835 l
+0 -5.835 l
+0 -6.659 l
+-1.426 -6.659 l
+-1.426 0.823 l
+0 0.823 l
+h
+3.63 -3.543 m
+3.63 -4.171 3.52 -4.653 3.308 -4.983 c
+3.09 -5.318 2.77 -5.483 2.352 -5.483 c
+2.028 -5.483 1.768 -5.351 1.573 -5.087 c
+1.573 -6.938 l
+0.53 -6.938 l
+0.53 -1.426 l
+1.484 -1.426 l
+1.529 -1.794 l
+1.723 -1.5 1.992 -1.353 2.337 -1.353 c
+2.756 -1.353 3.076 -1.511 3.293 -1.823 c
+3.506 -2.128 3.62 -2.598 3.63 -3.234 c
+h
+2.587 -3.278 m
+2.587 -2.896 2.543 -2.627 2.454 -2.469 c
+2.373 -2.315 2.234 -2.234 2.028 -2.234 c
+1.822 -2.234 1.668 -2.323 1.573 -2.5 c
+1.573 -4.366 l
+1.661 -4.535 1.816 -4.616 2.043 -4.616 c
+2.249 -4.616 2.389 -4.535 2.469 -4.366 c
+2.547 -4.189 2.587 -3.917 2.587 -3.543 c
+h
+6.217 -2.44 m
+5.88 -2.411 l
+5.593 -2.411 5.402 -2.536 5.307 -2.778 c
+5.307 -5.409 l
+4.262 -5.409 l
+4.262 -1.426 l
+5.233 -1.426 l
+5.263 -1.867 l
+5.428 -1.525 5.66 -1.353 5.953 -1.353 c
+6.071 -1.353 6.163 -1.374 6.232 -1.411 c
+h
+6.512 -3.293 m
+6.512 -2.687 6.651 -2.213 6.938 -1.867 c
+7.221 -1.525 7.614 -1.353 8.114 -1.353 c
+8.621 -1.353 9.018 -1.525 9.305 -1.867 c
+9.587 -2.213 9.731 -2.687 9.731 -3.293 c
+9.731 -3.558 l
+9.731 -4.156 9.587 -4.627 9.305 -4.969 c
+9.018 -5.314 8.621 -5.483 8.114 -5.483 c
+7.603 -5.483 7.206 -5.314 6.923 -4.969 c
+6.647 -4.627 6.512 -4.152 6.512 -3.543 c
+h
+7.555 -3.558 m
+7.555 -4.263 7.739 -4.616 8.114 -4.616 c
+8.467 -4.616 8.658 -4.322 8.687 -3.734 c
+8.687 -3.293 l
+8.687 -2.932 8.636 -2.66 8.54 -2.484 c
+8.441 -2.308 8.297 -2.22 8.114 -2.22 c
+7.937 -2.22 7.798 -2.308 7.702 -2.484 c
+7.603 -2.66 7.555 -2.932 7.555 -3.293 c
+h
+11.465 -1.426 m
+11.465 -5.63 l
+11.465 -6.078 11.362 -6.423 11.156 -6.659 c
+10.951 -6.894 10.657 -7.011 10.275 -7.011 c
+10.105 -7.011 9.951 -6.99 9.804 -6.953 c
+9.789 -6.101 l
+9.907 -6.13 9.999 -6.145 10.069 -6.145 c
+10.304 -6.145 10.422 -5.983 10.422 -5.659 c
+10.422 -1.426 l
+h
+10.363 -0.397 m
+10.363 -0.243 10.41 -0.114 10.51 -0.015 c
+10.616 0.091 10.753 0.147 10.921 0.147 c
+11.098 0.147 11.233 0.091 11.333 -0.015 c
+11.439 -0.114 11.495 -0.243 11.495 -0.397 c
+11.495 -0.566 11.439 -0.702 11.333 -0.809 c
+11.233 -0.908 11.098 -0.956 10.921 -0.956 c
+10.745 -0.956 10.605 -0.908 10.51 -0.809 c
+10.41 -0.702 10.363 -0.566 10.363 -0.397 c
+13.832 -5.483 m
+13.303 -5.483 12.883 -5.328 12.582 -5.012 c
+12.289 -4.69 12.141 -4.23 12.141 -3.631 c
+12.141 -3.323 l
+12.141 -2.697 12.278 -2.213 12.553 -1.867 c
+12.825 -1.525 13.218 -1.353 13.729 -1.353 c
+14.229 -1.353 14.6 -1.515 14.846 -1.837 c
+15.1 -2.161 15.232 -2.639 15.243 -3.263 c
+15.243 -3.763 l
+13.17 -3.763 l
+13.189 -4.057 13.251 -4.274 13.361 -4.41 c
+13.479 -4.549 13.66 -4.616 13.905 -4.616 c
+14.247 -4.616 14.537 -4.499 14.772 -4.263 c
+15.184 -4.895 l
+15.056 -5.072 14.868 -5.215 14.626 -5.322 c
+14.379 -5.428 14.115 -5.483 13.832 -5.483 c
+13.185 -3.043 m
+14.214 -3.043 l
+14.214 -2.94 l
+14.214 -2.705 14.173 -2.529 14.096 -2.411 c
+14.026 -2.286 13.898 -2.22 13.714 -2.22 c
+13.538 -2.22 13.406 -2.29 13.317 -2.425 c
+13.236 -2.554 13.192 -2.76 13.185 -3.043 c
+17.271 -4.616 m
+17.565 -4.616 17.716 -4.421 17.727 -4.028 c
+18.697 -4.028 l
+18.697 -4.461 18.565 -4.814 18.3 -5.087 c
+18.036 -5.351 17.698 -5.483 17.286 -5.483 c
+16.775 -5.483 16.382 -5.328 16.11 -5.012 c
+15.846 -4.69 15.706 -4.219 15.698 -3.601 c
+15.698 -3.278 l
+15.698 -2.654 15.831 -2.176 16.095 -1.852 c
+16.367 -1.521 16.764 -1.353 17.286 -1.353 c
+17.716 -1.353 18.057 -1.492 18.315 -1.764 c
+18.568 -2.04 18.697 -2.421 18.697 -2.911 c
+17.727 -2.911 l
+17.727 -2.697 17.687 -2.529 17.61 -2.411 c
+17.54 -2.286 17.423 -2.22 17.257 -2.22 c
+17.08 -2.22 16.952 -2.286 16.874 -2.411 c
+16.794 -2.539 16.75 -2.789 16.742 -3.161 c
+16.742 -3.572 l
+16.742 -3.896 16.757 -4.123 16.787 -4.248 c
+16.823 -4.377 16.878 -4.469 16.948 -4.528 c
+17.026 -4.586 17.132 -4.616 17.271 -4.616 c
+20.505 -0.456 m
+20.505 -1.426 l
+21.034 -1.426 l
+21.034 -2.22 l
+20.505 -2.22 l
+20.505 -4.189 l
+20.505 -4.347 20.523 -4.454 20.564 -4.513 c
+20.612 -4.572 20.696 -4.601 20.814 -4.601 c
+20.92 -4.601 21.005 -4.594 21.064 -4.572 c
+21.064 -5.38 l
+20.887 -5.446 20.696 -5.483 20.49 -5.483 c
+19.815 -5.483 19.469 -5.097 19.461 -4.322 c
+19.461 -2.22 l
+19.006 -2.22 l
+19.006 -1.426 l
+19.461 -1.426 l
+19.461 -0.456 l
+h
+24.297 -1.426 m
+24.327 -1.823 l
+24.562 -1.511 24.864 -1.353 25.238 -1.353 c
+25.922 -1.353 26.275 -1.833 26.296 -2.793 c
+26.296 -5.409 l
+25.253 -5.409 l
+25.253 -2.866 l
+25.253 -2.643 25.217 -2.481 25.15 -2.382 c
+25.08 -2.286 24.963 -2.234 24.797 -2.234 c
+24.61 -2.234 24.463 -2.33 24.357 -2.514 c
+24.357 -5.409 l
+23.312 -5.409 l
+23.312 -1.426 l
+h
+28.928 -5.409 m
+28.899 -5.351 28.868 -5.247 28.839 -5.101 c
+28.652 -5.358 28.402 -5.483 28.09 -5.483 c
+27.756 -5.483 27.476 -5.376 27.252 -5.16 c
+27.035 -4.935 26.929 -4.645 26.929 -4.293 c
+26.929 -3.881 27.061 -3.564 27.326 -3.337 c
+27.59 -3.102 27.972 -2.984 28.472 -2.984 c
+28.795 -2.984 l
+28.795 -2.66 l
+28.795 -2.484 28.758 -2.363 28.693 -2.294 c
+28.633 -2.216 28.546 -2.176 28.428 -2.176 c
+28.17 -2.176 28.046 -2.33 28.046 -2.631 c
+27.002 -2.631 l
+27.002 -2.261 27.138 -1.955 27.414 -1.72 c
+27.686 -1.478 28.035 -1.353 28.457 -1.353 c
+28.899 -1.353 29.236 -1.47 29.471 -1.706 c
+29.714 -1.933 29.839 -2.257 29.839 -2.675 c
+29.839 -4.542 l
+29.839 -4.888 29.887 -5.156 29.986 -5.351 c
+29.986 -5.409 l
+h
+28.325 -4.659 m
+28.432 -4.659 28.523 -4.642 28.604 -4.601 c
+28.693 -4.553 28.755 -4.495 28.795 -4.424 c
+28.795 -3.601 l
+28.546 -3.601 l
+28.369 -3.601 28.226 -3.66 28.12 -3.778 c
+28.02 -3.888 27.972 -4.035 27.972 -4.219 c
+27.972 -4.513 28.09 -4.659 28.325 -4.659 c
+31.559 -1.426 m
+31.588 -1.794 l
+31.823 -1.5 32.132 -1.353 32.515 -1.353 c
+32.915 -1.353 33.194 -1.536 33.352 -1.897 c
+33.587 -1.536 33.915 -1.353 34.337 -1.353 c
+35.031 -1.353 35.384 -1.837 35.395 -2.808 c
+35.395 -5.409 l
+34.366 -5.409 l
+34.366 -2.866 l
+34.366 -2.643 34.329 -2.481 34.264 -2.382 c
+34.204 -2.286 34.094 -2.234 33.94 -2.234 c
+33.742 -2.234 33.602 -2.352 33.514 -2.587 c
+33.514 -5.409 l
+32.471 -5.409 l
+32.471 -2.881 l
+32.471 -2.646 32.44 -2.481 32.382 -2.382 c
+32.323 -2.286 32.213 -2.234 32.059 -2.234 c
+31.883 -2.234 31.739 -2.33 31.632 -2.514 c
+31.632 -5.409 l
+30.589 -5.409 l
+30.589 -1.426 l
+h
+37.776 -5.483 m
+37.248 -5.483 36.828 -5.328 36.527 -5.012 c
+36.234 -4.69 36.086 -4.23 36.086 -3.631 c
+36.086 -3.323 l
+36.086 -2.697 36.222 -2.213 36.498 -1.867 c
+36.77 -1.525 37.163 -1.353 37.674 -1.353 c
+38.173 -1.353 38.545 -1.515 38.79 -1.837 c
+39.044 -2.161 39.177 -2.639 39.187 -3.263 c
+39.187 -3.763 l
+37.115 -3.763 l
+37.134 -4.057 37.196 -4.274 37.306 -4.41 c
+37.424 -4.549 37.604 -4.616 37.85 -4.616 c
+38.192 -4.616 38.482 -4.499 38.717 -4.263 c
+39.129 -4.895 l
+39 -5.072 38.813 -5.215 38.57 -5.322 c
+38.324 -5.428 38.059 -5.483 37.776 -5.483 c
+37.13 -3.043 m
+38.159 -3.043 l
+38.159 -2.94 l
+38.159 -2.705 38.119 -2.529 38.041 -2.411 c
+37.971 -2.286 37.843 -2.22 37.659 -2.22 c
+37.483 -2.22 37.35 -2.29 37.262 -2.425 c
+37.181 -2.554 37.138 -2.76 37.13 -3.043 c
+39.526 0.823 m
+40.951 0.823 l
+40.951 -6.659 l
+39.526 -6.659 l
+39.526 -5.835 l
+39.908 -5.835 l
+39.908 0 l
+39.526 0 l
+h
+f
+Q
+q 1 0 0 1 155.6378 255.9058 cm
+0 0 m
+-0.04 0.087 -0.066 0.235 -0.073 0.44 c
+-0.309 0.095 -0.603 -0.073 -0.956 -0.073 c
+-1.319 -0.073 -1.602 0.022 -1.808 0.22 c
+-2.007 0.426 -2.102 0.713 -2.102 1.087 c
+-2.102 1.488 -1.966 1.808 -1.691 2.043 c
+-1.419 2.285 -1.043 2.41 -0.573 2.41 c
+-0.088 2.41 l
+-0.088 2.836 l
+-0.088 3.072 -0.143 3.237 -0.25 3.337 c
+-0.36 3.443 -0.522 3.498 -0.735 3.498 c
+-0.933 3.498 -1.095 3.439 -1.22 3.322 c
+-1.338 3.204 -1.396 3.057 -1.396 2.881 c
+-2.043 2.881 l
+-2.043 3.075 -1.984 3.266 -1.866 3.454 c
+-1.742 3.638 -1.58 3.785 -1.382 3.895 c
+-1.176 4.002 -0.948 4.056 -0.691 4.056 c
+-0.291 4.056 0.015 3.954 0.22 3.748 c
+0.434 3.542 0.548 3.248 0.559 2.866 c
+0.559 0.852 l
+0.559 0.548 0.595 0.283 0.676 0.058 c
+0.676 0 l
+h
+-0.867 0.515 m
+-0.702 0.515 -0.551 0.558 -0.411 0.646 c
+-0.264 0.735 -0.158 0.845 -0.088 0.985 c
+-0.088 1.926 l
+-0.455 1.926 l
+-0.771 1.926 -1.014 1.855 -1.191 1.72 c
+-1.367 1.591 -1.455 1.404 -1.455 1.161 c
+-1.455 0.933 -1.411 0.768 -1.323 0.661 c
+-1.235 0.562 -1.084 0.515 -0.867 0.515 c
+2.176 3.983 m
+2.19 3.542 l
+2.444 3.884 2.767 4.056 3.16 4.056 c
+3.865 4.056 4.222 3.586 4.233 2.645 c
+4.233 0 l
+3.587 0 l
+3.587 2.616 l
+3.587 2.929 3.532 3.149 3.425 3.278 c
+3.314 3.403 3.16 3.469 2.955 3.469 c
+2.797 3.469 2.649 3.414 2.514 3.307 c
+2.385 3.197 2.282 3.061 2.205 2.896 c
+2.205 0 l
+1.558 0 l
+1.558 3.983 l
+h
+5.072 2.175 m
+5.072 2.782 5.182 3.248 5.409 3.572 c
+5.644 3.895 5.972 4.056 6.394 4.056 c
+6.776 4.056 7.074 3.898 7.291 3.586 c
+7.291 5.644 l
+7.937 5.644 l
+7.937 0 l
+7.35 0 l
+7.306 0.426 l
+7.1 0.091 6.795 -0.073 6.394 -0.073 c
+5.982 -0.073 5.659 0.081 5.424 0.397 c
+5.189 0.72 5.072 1.176 5.072 1.764 c
+h
+5.718 1.793 m
+5.718 1.352 5.781 1.022 5.909 0.808 c
+6.045 0.602 6.265 0.5 6.57 0.5 c
+6.894 0.5 7.133 0.661 7.291 0.985 c
+7.291 2.998 l
+7.121 3.31 6.882 3.469 6.57 3.469 c
+6.265 3.469 6.045 3.366 5.909 3.16 c
+5.781 2.954 5.718 2.631 5.718 2.19 c
+h
+13.626 1.146 m
+14.229 3.983 l
+14.876 3.983 l
+13.891 0 l
+13.376 0 l
+12.597 2.851 l
+11.848 0 l
+11.318 0 l
+10.363 3.983 l
+10.994 3.983 l
+11.612 1.22 l
+12.347 3.983 l
+12.862 3.983 l
+h
+16.257 0 -0.646 3.983 re
+16.301 5.026 m
+16.301 4.916 16.272 4.825 16.213 4.748 c
+16.154 4.677 16.058 4.644 15.933 4.644 c
+15.817 4.644 15.721 4.677 15.655 4.748 c
+15.596 4.825 15.566 4.916 15.566 5.026 c
+15.566 5.144 15.596 5.236 15.655 5.306 c
+15.721 5.383 15.817 5.423 15.933 5.423 c
+16.058 5.423 16.154 5.383 16.213 5.306 c
+16.272 5.225 16.301 5.134 16.301 5.026 c
+17.977 0 -0.646 5.644 re
+19.696 0 -0.646 5.644 re
+23.137 0 -0.647 3.983 re
+23.181 5.026 m
+23.181 4.916 23.151 4.825 23.092 4.748 c
+23.033 4.677 22.938 4.644 22.813 4.644 c
+22.695 4.644 22.599 4.677 22.534 4.748 c
+22.475 4.825 22.445 4.916 22.445 5.026 c
+22.445 5.144 22.475 5.236 22.534 5.306 c
+22.599 5.383 22.695 5.423 22.813 5.423 c
+22.938 5.423 23.033 5.383 23.092 5.306 c
+23.151 5.225 23.181 5.134 23.181 5.026 c
+24.768 3.983 m
+24.783 3.542 l
+25.036 3.884 25.359 4.056 25.753 4.056 c
+26.458 4.056 26.815 3.586 26.826 2.645 c
+26.826 0 l
+26.179 0 l
+26.179 2.616 l
+26.179 2.929 26.124 3.149 26.017 3.278 c
+25.907 3.403 25.753 3.469 25.547 3.469 c
+25.389 3.469 25.242 3.414 25.105 3.307 c
+24.978 3.197 24.874 3.061 24.797 2.896 c
+24.797 0 l
+24.151 0 l
+24.151 3.983 l
+h
+28.502 0 -0.647 3.983 re
+28.546 5.026 m
+28.546 4.916 28.517 4.825 28.457 4.748 c
+28.398 4.677 28.303 4.644 28.178 4.644 c
+28.06 4.644 27.965 4.677 27.899 4.748 c
+27.84 4.825 27.811 4.916 27.811 5.026 c
+27.811 5.144 27.84 5.236 27.899 5.306 c
+27.965 5.383 28.06 5.423 28.178 5.423 c
+28.303 5.423 28.398 5.383 28.457 5.306 c
+28.517 5.225 28.546 5.134 28.546 5.026 c
+30.368 4.939 m
+30.368 3.983 l
+30.971 3.983 l
+30.971 3.454 l
+30.368 3.454 l
+30.368 0.985 l
+30.368 0.827 30.391 0.709 30.441 0.632 c
+30.501 0.551 30.589 0.515 30.707 0.515 c
+30.794 0.515 30.883 0.529 30.971 0.558 c
+30.971 0 l
+30.824 -0.048 30.67 -0.073 30.515 -0.073 c
+30.258 -0.073 30.063 0.018 29.928 0.205 c
+29.788 0.389 29.722 0.65 29.722 0.985 c
+29.722 3.454 l
+29.119 3.454 l
+29.119 3.983 l
+29.722 3.983 l
+29.722 4.939 l
+h
+32.44 0 -0.646 3.983 re
+32.485 5.026 m
+32.485 4.916 32.456 4.825 32.396 4.748 c
+32.338 4.677 32.242 4.644 32.118 4.644 c
+32 4.644 31.904 4.677 31.838 4.748 c
+31.779 4.825 31.75 4.916 31.75 5.026 c
+31.75 5.144 31.779 5.236 31.838 5.306 c
+31.904 5.383 32 5.423 32.118 5.423 c
+32.242 5.423 32.338 5.383 32.396 5.306 c
+32.456 5.225 32.485 5.134 32.485 5.026 c
+35.498 0 m
+35.457 0.087 35.432 0.235 35.424 0.44 c
+35.189 0.095 34.896 -0.073 34.543 -0.073 c
+34.179 -0.073 33.896 0.022 33.691 0.22 c
+33.492 0.426 33.396 0.713 33.396 1.087 c
+33.396 1.488 33.533 1.808 33.807 2.043 c
+34.08 2.285 34.455 2.41 34.925 2.41 c
+35.41 2.41 l
+35.41 2.836 l
+35.41 3.072 35.355 3.237 35.249 3.337 c
+35.138 3.443 34.977 3.498 34.763 3.498 c
+34.565 3.498 34.403 3.439 34.278 3.322 c
+34.161 3.204 34.102 3.057 34.102 2.881 c
+33.456 2.881 l
+33.456 3.075 33.514 3.266 33.631 3.454 c
+33.757 3.638 33.918 3.785 34.117 3.895 c
+34.322 4.002 34.551 4.056 34.807 4.056 c
+35.208 4.056 35.513 3.954 35.719 3.748 c
+35.932 3.542 36.045 3.248 36.057 2.866 c
+36.057 0.852 l
+36.057 0.548 36.093 0.283 36.174 0.058 c
+36.174 0 l
+h
+34.631 0.515 m
+34.796 0.515 34.947 0.558 35.087 0.646 c
+35.234 0.735 35.34 0.845 35.41 0.985 c
+35.41 1.926 l
+35.043 1.926 l
+34.726 1.926 34.484 1.855 34.308 1.72 c
+34.131 1.591 34.043 1.404 34.043 1.161 c
+34.043 0.933 34.087 0.768 34.175 0.661 c
+34.264 0.562 34.414 0.515 34.631 0.515 c
+37.762 0 -0.647 5.644 re
+39.482 0 -0.647 3.983 re
+39.526 5.026 m
+39.526 4.916 39.496 4.825 39.438 4.748 c
+39.378 4.677 39.283 4.644 39.158 4.644 c
+39.041 4.644 38.945 4.677 38.879 4.748 c
+38.821 4.825 38.79 4.916 38.79 5.026 c
+38.79 5.144 38.821 5.236 38.879 5.306 c
+38.945 5.383 39.041 5.423 39.158 5.423 c
+39.283 5.423 39.378 5.383 39.438 5.306 c
+39.496 5.225 39.526 5.134 39.526 5.026 c
+41.098 0.558 m
+43.024 0.558 l
+43.024 0 l
+40.363 0 l
+40.363 0.5 l
+42.187 3.41 l
+40.378 3.41 l
+40.378 3.983 l
+42.95 3.983 l
+42.95 3.498 l
+h
+45.171 -0.073 m
+44.67 -0.073 44.288 0.073 44.024 0.367 c
+43.759 0.661 43.627 1.095 43.627 1.675 c
+43.627 2.146 l
+43.627 2.741 43.752 3.208 44.009 3.542 c
+44.274 3.884 44.633 4.056 45.096 4.056 c
+45.556 4.056 45.898 3.902 46.125 3.601 c
+46.361 3.307 46.482 2.844 46.493 2.219 c
+46.493 1.793 l
+44.274 1.793 l
+44.274 1.705 l
+44.274 1.271 44.351 0.959 44.509 0.764 c
+44.674 0.577 44.905 0.484 45.2 0.484 c
+45.394 0.484 45.567 0.518 45.714 0.588 c
+45.861 0.665 45.997 0.783 46.125 0.941 c
+46.464 0.529 l
+46.177 0.125 45.747 -0.073 45.171 -0.073 c
+45.096 3.498 m
+44.822 3.498 44.619 3.403 44.494 3.219 c
+44.365 3.031 44.292 2.741 44.274 2.352 c
+45.846 2.352 l
+45.846 2.439 l
+45.824 2.822 45.758 3.09 45.641 3.248 c
+45.523 3.414 45.339 3.498 45.096 3.498 c
+51.035 0 m
+50.995 0.087 50.969 0.235 50.962 0.44 c
+50.727 0.095 50.432 -0.073 50.079 -0.073 c
+49.716 -0.073 49.433 0.022 49.227 0.22 c
+49.029 0.426 48.934 0.713 48.934 1.087 c
+48.934 1.488 49.069 1.808 49.345 2.043 c
+49.616 2.285 49.992 2.41 50.462 2.41 c
+50.947 2.41 l
+50.947 2.836 l
+50.947 3.072 50.892 3.237 50.785 3.337 c
+50.675 3.443 50.513 3.498 50.3 3.498 c
+50.102 3.498 49.94 3.439 49.815 3.322 c
+49.697 3.204 49.639 3.057 49.639 2.881 c
+48.992 2.881 l
+48.992 3.075 49.051 3.266 49.169 3.454 c
+49.293 3.638 49.455 3.785 49.653 3.895 c
+49.859 4.002 50.087 4.056 50.345 4.056 c
+50.744 4.056 51.05 3.954 51.255 3.748 c
+51.469 3.542 51.583 3.248 51.594 2.866 c
+51.594 0.852 l
+51.594 0.548 51.631 0.283 51.711 0.058 c
+51.711 0 l
+h
+50.168 0.515 m
+50.333 0.515 50.484 0.558 50.624 0.646 c
+50.771 0.735 50.877 0.845 50.947 0.985 c
+50.947 1.926 l
+50.58 1.926 l
+50.264 1.926 50.021 1.855 49.844 1.72 c
+49.668 1.591 49.58 1.404 49.58 1.161 c
+49.58 0.933 49.624 0.768 49.712 0.661 c
+49.8 0.562 49.951 0.515 50.168 0.515 c
+55.959 3.366 m
+55.871 3.384 55.772 3.395 55.665 3.395 c
+55.331 3.395 55.095 3.212 54.96 2.851 c
+54.96 0 l
+54.313 0 l
+54.313 3.983 l
+54.945 3.983 l
+54.96 3.572 l
+55.136 3.895 55.378 4.056 55.695 4.056 c
+55.801 4.056 55.889 4.035 55.959 3.998 c
+h
+57.958 -0.073 m
+57.458 -0.073 57.077 0.073 56.812 0.367 c
+56.547 0.661 56.415 1.095 56.415 1.675 c
+56.415 2.146 l
+56.415 2.741 56.54 3.208 56.797 3.542 c
+57.061 3.884 57.422 4.056 57.885 4.056 c
+58.345 4.056 58.686 3.902 58.914 3.601 c
+59.149 3.307 59.27 2.844 59.282 2.219 c
+59.282 1.793 l
+57.061 1.793 l
+57.061 1.705 l
+57.061 1.271 57.139 0.959 57.297 0.764 c
+57.462 0.577 57.694 0.484 57.988 0.484 c
+58.183 0.484 58.355 0.518 58.502 0.588 c
+58.649 0.665 58.785 0.783 58.914 0.941 c
+59.252 0.529 l
+58.966 0.125 58.536 -0.073 57.958 -0.073 c
+57.885 3.498 m
+57.609 3.498 57.407 3.403 57.283 3.219 c
+57.154 3.031 57.08 2.741 57.061 2.352 c
+58.634 2.352 l
+58.634 2.439 l
+58.613 2.822 58.546 3.09 58.428 3.248 c
+58.311 3.414 58.127 3.498 57.885 3.498 c
+62.941 1.793 m
+62.941 1.165 62.824 0.694 62.588 0.382 c
+62.361 0.077 62.045 -0.073 61.633 -0.073 c
+61.229 -0.073 60.92 0.077 60.707 0.382 c
+60.707 -1.529 l
+60.061 -1.529 l
+60.061 3.983 l
+60.649 3.983 l
+60.693 3.542 l
+60.905 3.884 61.214 4.056 61.618 4.056 c
+62.06 4.056 62.386 3.902 62.603 3.601 c
+62.816 3.296 62.931 2.84 62.941 2.234 c
+h
+62.295 2.175 m
+62.295 2.616 62.225 2.94 62.089 3.145 c
+61.95 3.358 61.728 3.469 61.427 3.469 c
+61.111 3.469 60.872 3.314 60.707 3.013 c
+60.707 0.941 l
+60.872 0.636 61.111 0.484 61.427 0.484 c
+61.721 0.484 61.935 0.588 62.074 0.793 c
+62.21 1.007 62.284 1.338 62.295 1.778 c
+h
+63.647 2.175 m
+63.647 2.753 63.783 3.208 64.059 3.542 c
+64.342 3.884 64.713 4.056 65.175 4.056 c
+65.635 4.056 66.002 3.888 66.278 3.557 c
+66.561 3.233 66.708 2.786 66.719 2.219 c
+66.719 1.793 l
+66.719 1.224 66.576 0.768 66.293 0.426 c
+66.017 0.091 65.649 -0.073 65.19 -0.073 c
+64.728 -0.073 64.356 0.087 64.073 0.411 c
+63.797 0.742 63.654 1.183 63.647 1.734 c
+h
+64.294 1.793 m
+64.294 1.389 64.371 1.072 64.529 0.837 c
+64.695 0.602 64.915 0.484 65.19 0.484 c
+65.756 0.484 66.05 0.897 66.072 1.72 c
+66.072 2.175 l
+66.072 2.576 65.988 2.896 65.823 3.131 c
+65.665 3.374 65.447 3.498 65.175 3.498 c
+64.911 3.498 64.695 3.374 64.529 3.131 c
+64.371 2.896 64.294 2.576 64.294 2.175 c
+h
+69.497 1.014 m
+69.497 1.161 69.442 1.282 69.335 1.381 c
+69.225 1.477 69.019 1.595 68.718 1.734 c
+68.373 1.881 68.13 2.003 67.983 2.102 c
+67.836 2.208 67.726 2.326 67.66 2.454 c
+67.59 2.579 67.557 2.738 67.557 2.925 c
+67.557 3.248 67.674 3.516 67.909 3.733 c
+68.144 3.946 68.446 4.056 68.821 4.056 c
+69.204 4.056 69.512 3.943 69.747 3.719 c
+69.983 3.491 70.1 3.204 70.1 2.851 c
+69.453 2.851 l
+69.453 3.027 69.395 3.179 69.277 3.307 c
+69.159 3.432 69.005 3.498 68.821 3.498 c
+68.622 3.498 68.472 3.443 68.365 3.337 c
+68.255 3.237 68.204 3.105 68.204 2.94 c
+68.204 2.811 68.24 2.705 68.321 2.616 c
+68.398 2.535 68.589 2.433 68.894 2.308 c
+69.372 2.12 69.703 1.932 69.879 1.749 c
+70.056 1.573 70.144 1.344 70.144 1.072 c
+70.144 0.72 70.019 0.44 69.777 0.235 c
+69.541 0.029 69.225 -0.073 68.836 -0.073 c
+68.413 -0.073 68.075 0.044 67.822 0.279 c
+67.564 0.521 67.439 0.827 67.439 1.19 c
+68.086 1.19 l
+68.094 0.962 68.163 0.786 68.292 0.661 c
+68.417 0.544 68.601 0.484 68.836 0.484 c
+69.048 0.484 69.21 0.532 69.32 0.632 c
+69.439 0.727 69.497 0.856 69.497 1.014 c
+71.687 0 -0.646 3.983 re
+71.731 5.026 m
+71.731 4.916 71.702 4.825 71.643 4.748 c
+71.585 4.677 71.489 4.644 71.364 4.644 c
+71.246 4.644 71.151 4.677 71.085 4.748 c
+71.026 4.825 70.997 4.916 70.997 5.026 c
+70.997 5.144 71.026 5.236 71.085 5.306 c
+71.151 5.383 71.246 5.423 71.364 5.423 c
+71.489 5.423 71.585 5.383 71.643 5.306 c
+71.702 5.225 71.731 5.134 71.731 5.026 c
+73.554 4.939 m
+73.554 3.983 l
+74.157 3.983 l
+74.157 3.454 l
+73.554 3.454 l
+73.554 0.985 l
+73.554 0.827 73.576 0.709 73.628 0.632 c
+73.686 0.551 73.775 0.515 73.892 0.515 c
+73.981 0.515 74.068 0.529 74.157 0.558 c
+74.157 0 l
+74.01 -0.048 73.856 -0.073 73.701 -0.073 c
+73.444 -0.073 73.249 0.018 73.113 0.205 c
+72.973 0.389 72.907 0.65 72.907 0.985 c
+72.907 3.454 l
+72.304 3.454 l
+72.304 3.983 l
+72.907 3.983 l
+72.907 4.939 l
+h
+74.715 2.175 m
+74.715 2.753 74.851 3.208 75.126 3.542 c
+75.41 3.884 75.781 4.056 76.244 4.056 c
+76.703 4.056 77.071 3.888 77.347 3.557 c
+77.63 3.233 77.777 2.786 77.787 2.219 c
+77.787 1.793 l
+77.787 1.224 77.644 0.768 77.361 0.426 c
+77.085 0.091 76.718 -0.073 76.259 -0.073 c
+75.795 -0.073 75.425 0.087 75.142 0.411 c
+74.866 0.742 74.723 1.183 74.715 1.734 c
+h
+75.362 1.793 m
+75.362 1.389 75.439 1.072 75.597 0.837 c
+75.762 0.602 75.984 0.484 76.259 0.484 c
+76.825 0.484 77.119 0.897 77.141 1.72 c
+77.141 2.175 l
+77.141 2.576 77.056 2.896 76.89 3.131 c
+76.732 3.374 76.516 3.498 76.244 3.498 c
+75.98 3.498 75.762 3.374 75.597 3.131 c
+75.439 2.896 75.362 2.576 75.362 2.175 c
+h
+80.271 3.366 m
+80.183 3.384 80.084 3.395 79.978 3.395 c
+79.643 3.395 79.408 3.212 79.272 2.851 c
+79.272 0 l
+78.625 0 l
+78.625 3.983 l
+79.257 3.983 l
+79.272 3.572 l
+79.448 3.895 79.691 4.056 80.007 4.056 c
+80.113 4.056 80.202 4.035 80.271 3.998 c
+h
+82.079 1.087 m
+82.8 3.983 l
+83.491 3.983 l
+82.197 -0.559 l
+82.098 -0.9 81.954 -1.162 81.771 -1.338 c
+81.594 -1.515 81.393 -1.602 81.168 -1.602 c
+81.079 -1.602 80.966 -1.58 80.83 -1.544 c
+80.83 -1 l
+80.977 -1.014 l
+81.16 -1.014 81.308 -0.971 81.418 -0.882 c
+81.524 -0.794 81.613 -0.636 81.683 -0.412 c
+81.8 0.029 l
+80.639 3.983 l
+81.345 3.983 l
+h
+86.548 0 -0.646 3.983 re
+86.592 5.026 m
+86.592 4.916 86.563 4.825 86.504 4.748 c
+86.445 4.677 86.35 4.644 86.224 4.644 c
+86.107 4.644 86.012 4.677 85.945 4.748 c
+85.887 4.825 85.858 4.916 85.858 5.026 c
+85.858 5.144 85.887 5.236 85.945 5.306 c
+86.012 5.383 86.107 5.423 86.224 5.423 c
+86.35 5.423 86.445 5.383 86.504 5.306 c
+86.563 5.225 86.592 5.134 86.592 5.026 c
+88.179 3.983 m
+88.194 3.542 l
+88.448 3.884 88.771 4.056 89.164 4.056 c
+89.87 4.056 90.226 3.586 90.238 2.645 c
+90.238 0 l
+89.59 0 l
+89.59 2.616 l
+89.59 2.929 89.536 3.149 89.43 3.278 c
+89.318 3.403 89.164 3.469 88.959 3.469 c
+88.801 3.469 88.653 3.414 88.518 3.307 c
+88.389 3.197 88.287 3.061 88.209 2.896 c
+88.209 0 l
+87.562 0 l
+87.562 3.983 l
+h
+93.148 1.014 m
+93.148 1.161 93.093 1.282 92.986 1.381 c
+92.876 1.477 92.67 1.595 92.368 1.734 c
+92.023 1.881 91.781 2.003 91.634 2.102 c
+91.487 2.208 91.377 2.326 91.311 2.454 c
+91.24 2.579 91.208 2.738 91.208 2.925 c
+91.208 3.248 91.325 3.516 91.56 3.733 c
+91.795 3.946 92.096 4.056 92.472 4.056 c
+92.854 4.056 93.162 3.943 93.398 3.719 c
+93.633 3.491 93.75 3.204 93.75 2.851 c
+93.104 2.851 l
+93.104 3.027 93.045 3.179 92.927 3.307 c
+92.81 3.432 92.655 3.498 92.472 3.498 c
+92.273 3.498 92.123 3.443 92.017 3.337 c
+91.906 3.237 91.855 3.105 91.855 2.94 c
+91.855 2.811 91.891 2.705 91.972 2.616 c
+92.049 2.535 92.24 2.433 92.545 2.308 c
+93.023 2.12 93.353 1.932 93.53 1.749 c
+93.706 1.573 93.795 1.344 93.795 1.072 c
+93.795 0.72 93.669 0.44 93.428 0.235 c
+93.192 0.029 92.876 -0.073 92.487 -0.073 c
+92.064 -0.073 91.726 0.044 91.472 0.279 c
+91.215 0.521 91.09 0.827 91.09 1.19 c
+91.737 1.19 l
+91.744 0.962 91.814 0.786 91.942 0.661 c
+92.067 0.544 92.252 0.484 92.487 0.484 c
+92.7 0.484 92.861 0.532 92.971 0.632 c
+93.089 0.727 93.148 0.856 93.148 1.014 c
+95.338 0 -0.647 3.983 re
+95.382 5.026 m
+95.382 4.916 95.352 4.825 95.294 4.748 c
+95.235 4.677 95.14 4.644 95.015 4.644 c
+94.897 4.644 94.801 4.677 94.735 4.748 c
+94.677 4.825 94.647 4.916 94.647 5.026 c
+94.647 5.144 94.677 5.236 94.735 5.306 c
+94.801 5.383 94.897 5.423 95.015 5.423 c
+95.14 5.423 95.235 5.383 95.294 5.306 c
+95.352 5.225 95.382 5.134 95.382 5.026 c
+96.22 2.175 m
+96.22 2.782 96.33 3.248 96.558 3.572 c
+96.794 3.895 97.12 4.056 97.542 4.056 c
+97.925 4.056 98.223 3.898 98.44 3.586 c
+98.44 5.644 l
+99.086 5.644 l
+99.086 0 l
+98.498 0 l
+98.454 0.426 l
+98.248 0.091 97.943 -0.073 97.542 -0.073 c
+97.131 -0.073 96.808 0.081 96.573 0.397 c
+96.337 0.72 96.22 1.176 96.22 1.764 c
+h
+96.867 1.793 m
+96.867 1.352 96.929 1.022 97.058 0.808 c
+97.193 0.602 97.414 0.5 97.719 0.5 c
+98.043 0.5 98.282 0.661 98.44 0.985 c
+98.44 2.998 l
+98.271 3.31 98.032 3.469 97.719 3.469 c
+97.414 3.469 97.193 3.366 97.058 3.16 c
+96.929 2.954 96.867 2.631 96.867 2.19 c
+h
+101.511 -0.073 m
+101.012 -0.073 100.63 0.073 100.365 0.367 c
+100.1 0.661 99.969 1.095 99.969 1.675 c
+99.969 2.146 l
+99.969 2.741 100.093 3.208 100.351 3.542 c
+100.615 3.884 100.975 4.056 101.438 4.056 c
+101.897 4.056 102.24 3.902 102.467 3.601 c
+102.702 3.307 102.824 2.844 102.835 2.219 c
+102.835 1.793 l
+100.615 1.793 l
+100.615 1.705 l
+100.615 1.271 100.692 0.959 100.85 0.764 c
+101.016 0.577 101.247 0.484 101.541 0.484 c
+101.736 0.484 101.908 0.518 102.055 0.588 c
+102.203 0.665 102.338 0.783 102.467 0.941 c
+102.805 0.529 l
+102.519 0.125 102.089 -0.073 101.511 -0.073 c
+101.438 3.498 m
+101.162 3.498 100.96 3.403 100.835 3.219 c
+100.707 3.031 100.634 2.741 100.615 2.352 c
+102.188 2.352 l
+102.188 2.439 l
+102.166 2.822 102.099 3.09 101.982 3.248 c
+101.864 3.414 101.681 3.498 101.438 3.498 c
+106.039 0 -0.647 3.983 re
+106.083 5.026 m
+106.083 4.916 106.053 4.825 105.995 4.748 c
+105.936 4.677 105.841 4.644 105.716 4.644 c
+105.598 4.644 105.502 4.677 105.436 4.748 c
+105.378 4.825 105.348 4.916 105.348 5.026 c
+105.348 5.144 105.378 5.236 105.436 5.306 c
+105.502 5.383 105.598 5.423 105.716 5.423 c
+105.841 5.423 105.936 5.383 105.995 5.306 c
+106.053 5.225 106.083 5.134 106.083 5.026 c
+107.906 4.939 m
+107.906 3.983 l
+108.509 3.983 l
+108.509 3.454 l
+107.906 3.454 l
+107.906 0.985 l
+107.906 0.827 107.928 0.709 107.979 0.632 c
+108.038 0.551 108.126 0.515 108.244 0.515 c
+108.332 0.515 108.42 0.529 108.509 0.558 c
+108.509 0 l
+108.361 -0.048 108.207 -0.073 108.052 -0.073 c
+107.796 -0.073 107.601 0.018 107.464 0.205 c
+107.325 0.389 107.259 0.65 107.259 0.985 c
+107.259 3.454 l
+106.656 3.454 l
+106.656 3.983 l
+107.259 3.983 l
+107.259 4.939 l
+h
+109.317 0.353 m
+109.317 0.47 109.35 0.565 109.42 0.646 c
+109.486 0.723 109.589 0.764 109.729 0.764 c
+109.876 0.764 109.982 0.723 110.051 0.646 c
+110.129 0.565 110.169 0.47 110.169 0.353 c
+110.169 0.243 110.129 0.151 110.051 0.073 c
+109.982 -0.004 109.876 -0.044 109.729 -0.044 c
+109.589 -0.044 109.486 -0.004 109.42 0.073 c
+109.35 0.151 109.317 0.243 109.317 0.353 c
+f
+Q
+39.089 246.498 -0.675 5.35 re
+40.471 246.498 m
+40.471 249.953 l
+39.942 249.953 l
+39.942 250.481 l
+40.471 250.481 l
+40.471 250.937 l
+40.471 251.338 40.567 251.65 40.765 251.878 c
+40.97 252.102 41.249 252.216 41.602 252.216 c
+41.739 252.216 41.87 252.194 41.999 252.157 c
+41.97 251.613 l
+41.87 251.632 41.772 251.642 41.676 251.642 c
+41.301 251.642 41.118 251.378 41.118 250.849 c
+41.118 250.481 l
+41.793 250.481 l
+41.793 249.953 l
+41.118 249.953 l
+41.118 246.498 l
+h
+f
+q 1 0 0 1 45.6305 251.9076 cm
+0 0 m
+-0.383 0 l
+-0.383 -5.835 l
+0 -5.835 l
+0 -6.659 l
+-1.426 -6.659 l
+-1.426 0.823 l
+0 0.823 l
+h
+3.63 -3.543 m
+3.63 -4.171 3.52 -4.653 3.307 -4.983 c
+3.09 -5.318 2.77 -5.483 2.352 -5.483 c
+2.028 -5.483 1.767 -5.351 1.572 -5.087 c
+1.572 -6.938 l
+0.529 -6.938 l
+0.529 -1.426 l
+1.484 -1.426 l
+1.528 -1.794 l
+1.723 -1.5 1.992 -1.353 2.337 -1.353 c
+2.755 -1.353 3.075 -1.511 3.293 -1.823 c
+3.505 -2.128 3.619 -2.598 3.63 -3.234 c
+h
+2.587 -3.278 m
+2.587 -2.896 2.543 -2.627 2.454 -2.469 c
+2.373 -2.315 2.233 -2.234 2.028 -2.234 c
+1.822 -2.234 1.668 -2.323 1.572 -2.5 c
+1.572 -4.366 l
+1.66 -4.535 1.815 -4.616 2.042 -4.616 c
+2.248 -4.616 2.389 -4.535 2.469 -4.366 c
+2.547 -4.189 2.587 -3.917 2.587 -3.543 c
+h
+6.217 -2.44 m
+5.88 -2.411 l
+5.593 -2.411 5.402 -2.536 5.306 -2.778 c
+5.306 -5.409 l
+4.262 -5.409 l
+4.262 -1.426 l
+5.232 -1.426 l
+5.262 -1.867 l
+5.427 -1.525 5.659 -1.353 5.953 -1.353 c
+6.071 -1.353 6.162 -1.374 6.231 -1.411 c
+h
+6.511 -3.293 m
+6.511 -2.687 6.651 -2.213 6.937 -1.867 c
+7.22 -1.525 7.613 -1.353 8.113 -1.353 c
+8.621 -1.353 9.017 -1.525 9.304 -1.867 c
+9.587 -2.213 9.73 -2.687 9.73 -3.293 c
+9.73 -3.558 l
+9.73 -4.156 9.587 -4.627 9.304 -4.969 c
+9.017 -5.314 8.621 -5.483 8.113 -5.483 c
+7.603 -5.483 7.206 -5.314 6.923 -4.969 c
+6.647 -4.627 6.511 -4.152 6.511 -3.543 c
+h
+7.555 -3.558 m
+7.555 -4.263 7.739 -4.616 8.113 -4.616 c
+8.467 -4.616 8.658 -4.322 8.687 -3.734 c
+8.687 -3.293 l
+8.687 -2.932 8.635 -2.66 8.54 -2.484 c
+8.44 -2.308 8.297 -2.22 8.113 -2.22 c
+7.937 -2.22 7.798 -2.308 7.702 -2.484 c
+7.603 -2.66 7.555 -2.932 7.555 -3.293 c
+h
+11.465 -1.426 m
+11.465 -5.63 l
+11.465 -6.078 11.362 -6.423 11.156 -6.659 c
+10.95 -6.894 10.657 -7.011 10.274 -7.011 c
+10.105 -7.011 9.951 -6.99 9.803 -6.953 c
+9.789 -6.101 l
+9.907 -6.13 9.998 -6.145 10.069 -6.145 c
+10.304 -6.145 10.422 -5.983 10.422 -5.66 c
+10.422 -1.426 l
+h
+10.362 -0.397 m
+10.362 -0.243 10.41 -0.114 10.509 -0.015 c
+10.616 0.091 10.752 0.147 10.921 0.147 c
+11.097 0.147 11.233 0.091 11.332 -0.015 c
+11.439 -0.114 11.494 -0.243 11.494 -0.397 c
+11.494 -0.566 11.439 -0.702 11.332 -0.809 c
+11.233 -0.908 11.097 -0.956 10.921 -0.956 c
+10.744 -0.956 10.605 -0.908 10.509 -0.809 c
+10.41 -0.702 10.362 -0.566 10.362 -0.397 c
+13.832 -5.483 m
+13.302 -5.483 12.883 -5.328 12.581 -5.012 c
+12.288 -4.69 12.141 -4.23 12.141 -3.631 c
+12.141 -3.323 l
+12.141 -2.697 12.277 -2.213 12.552 -1.867 c
+12.824 -1.525 13.217 -1.353 13.728 -1.353 c
+14.228 -1.353 14.599 -1.515 14.846 -1.837 c
+15.099 -2.161 15.232 -2.639 15.243 -3.263 c
+15.243 -3.763 l
+13.17 -3.763 l
+13.188 -4.057 13.25 -4.274 13.361 -4.41 c
+13.479 -4.549 13.659 -4.616 13.905 -4.616 c
+14.247 -4.616 14.537 -4.499 14.772 -4.263 c
+15.184 -4.895 l
+15.055 -5.072 14.867 -5.215 14.625 -5.322 c
+14.379 -5.428 14.114 -5.483 13.832 -5.483 c
+13.184 -3.043 m
+14.214 -3.043 l
+14.214 -2.94 l
+14.214 -2.705 14.173 -2.529 14.096 -2.411 c
+14.026 -2.286 13.898 -2.22 13.714 -2.22 c
+13.537 -2.22 13.406 -2.29 13.317 -2.425 c
+13.236 -2.554 13.192 -2.76 13.184 -3.043 c
+17.271 -4.616 m
+17.565 -4.616 17.716 -4.421 17.726 -4.028 c
+18.696 -4.028 l
+18.696 -4.461 18.565 -4.814 18.3 -5.087 c
+18.035 -5.351 17.697 -5.483 17.285 -5.483 c
+16.775 -5.483 16.382 -5.328 16.109 -5.012 c
+15.845 -4.69 15.706 -4.219 15.698 -3.601 c
+15.698 -3.278 l
+15.698 -2.654 15.831 -2.176 16.095 -1.852 c
+16.367 -1.521 16.764 -1.353 17.285 -1.353 c
+17.716 -1.353 18.057 -1.492 18.314 -1.764 c
+18.568 -2.04 18.696 -2.421 18.696 -2.911 c
+17.726 -2.911 l
+17.726 -2.697 17.686 -2.529 17.609 -2.411 c
+17.539 -2.286 17.422 -2.22 17.256 -2.22 c
+17.08 -2.22 16.951 -2.286 16.874 -2.411 c
+16.793 -2.539 16.749 -2.789 16.741 -3.161 c
+16.741 -3.572 l
+16.741 -3.896 16.756 -4.123 16.786 -4.248 c
+16.822 -4.377 16.878 -4.469 16.947 -4.528 c
+17.025 -4.586 17.131 -4.616 17.271 -4.616 c
+20.504 -0.456 m
+20.504 -1.426 l
+21.034 -1.426 l
+21.034 -2.22 l
+20.504 -2.22 l
+20.504 -4.189 l
+20.504 -4.347 20.523 -4.454 20.564 -4.513 c
+20.612 -4.572 20.696 -4.601 20.813 -4.601 c
+20.92 -4.601 21.005 -4.594 21.063 -4.572 c
+21.063 -5.38 l
+20.887 -5.446 20.696 -5.483 20.49 -5.483 c
+19.814 -5.483 19.469 -5.097 19.461 -4.322 c
+19.461 -2.22 l
+19.006 -2.22 l
+19.006 -1.426 l
+19.461 -1.426 l
+19.461 -0.456 l
+h
+24.297 -1.426 m
+24.327 -1.823 l
+24.562 -1.511 24.863 -1.353 25.238 -1.353 c
+25.921 -1.353 26.274 -1.834 26.296 -2.793 c
+26.296 -5.409 l
+25.252 -5.409 l
+25.252 -2.866 l
+25.252 -2.643 25.216 -2.481 25.15 -2.382 c
+25.08 -2.286 24.963 -2.234 24.797 -2.234 c
+24.61 -2.234 24.462 -2.33 24.356 -2.514 c
+24.356 -5.409 l
+23.312 -5.409 l
+23.312 -1.426 l
+h
+28.928 -5.409 m
+28.898 -5.351 28.868 -5.247 28.839 -5.101 c
+28.652 -5.358 28.402 -5.483 28.09 -5.483 c
+27.755 -5.483 27.476 -5.376 27.251 -5.16 c
+27.035 -4.935 26.928 -4.645 26.928 -4.293 c
+26.928 -3.881 27.06 -3.564 27.325 -3.337 c
+27.59 -3.102 27.972 -2.984 28.471 -2.984 c
+28.795 -2.984 l
+28.795 -2.66 l
+28.795 -2.484 28.758 -2.363 28.693 -2.294 c
+28.633 -2.216 28.545 -2.176 28.427 -2.176 c
+28.17 -2.176 28.045 -2.33 28.045 -2.631 c
+27.002 -2.631 l
+27.002 -2.261 27.138 -1.955 27.413 -1.72 c
+27.685 -1.478 28.034 -1.353 28.457 -1.353 c
+28.898 -1.353 29.236 -1.47 29.471 -1.706 c
+29.713 -1.933 29.838 -2.257 29.838 -2.675 c
+29.838 -4.542 l
+29.838 -4.888 29.886 -5.156 29.985 -5.351 c
+29.985 -5.409 l
+h
+28.325 -4.659 m
+28.431 -4.659 28.523 -4.642 28.604 -4.601 c
+28.693 -4.553 28.755 -4.495 28.795 -4.424 c
+28.795 -3.601 l
+28.545 -3.601 l
+28.369 -3.601 28.225 -3.66 28.119 -3.778 c
+28.02 -3.888 27.972 -4.035 27.972 -4.219 c
+27.972 -4.513 28.09 -4.659 28.325 -4.659 c
+31.558 -1.426 m
+31.588 -1.794 l
+31.823 -1.5 32.132 -1.353 32.514 -1.353 c
+32.915 -1.353 33.194 -1.536 33.352 -1.897 c
+33.587 -1.536 33.914 -1.353 34.337 -1.353 c
+35.031 -1.353 35.384 -1.837 35.394 -2.808 c
+35.394 -5.409 l
+34.366 -5.409 l
+34.366 -2.866 l
+34.366 -2.643 34.329 -2.481 34.263 -2.382 c
+34.204 -2.286 34.094 -2.234 33.94 -2.234 c
+33.742 -2.234 33.601 -2.352 33.513 -2.587 c
+33.513 -5.409 l
+32.47 -5.409 l
+32.47 -2.881 l
+32.47 -2.646 32.44 -2.481 32.381 -2.382 c
+32.323 -2.286 32.213 -2.234 32.059 -2.234 c
+31.882 -2.234 31.739 -2.33 31.631 -2.514 c
+31.631 -5.409 l
+30.588 -5.409 l
+30.588 -1.426 l
+h
+37.776 -5.483 m
+37.247 -5.483 36.828 -5.328 36.527 -5.012 c
+36.233 -4.69 36.086 -4.23 36.086 -3.631 c
+36.086 -3.323 l
+36.086 -2.697 36.221 -2.213 36.497 -1.867 c
+36.769 -1.525 37.162 -1.353 37.673 -1.353 c
+38.173 -1.353 38.544 -1.515 38.79 -1.837 c
+39.044 -2.161 39.176 -2.639 39.187 -3.263 c
+39.187 -3.763 l
+37.115 -3.763 l
+37.133 -4.057 37.196 -4.274 37.306 -4.41 c
+37.424 -4.549 37.603 -4.616 37.85 -4.616 c
+38.191 -4.616 38.482 -4.499 38.717 -4.263 c
+39.128 -4.895 l
+39 -5.072 38.812 -5.215 38.57 -5.322 c
+38.324 -5.428 38.059 -5.483 37.776 -5.483 c
+37.129 -3.043 m
+38.158 -3.043 l
+38.158 -2.94 l
+38.158 -2.705 38.118 -2.529 38.041 -2.411 c
+37.971 -2.286 37.842 -2.22 37.659 -2.22 c
+37.482 -2.22 37.35 -2.29 37.262 -2.425 c
+37.181 -2.554 37.137 -2.76 37.129 -3.043 c
+39.525 0.823 m
+40.951 0.823 l
+40.951 -6.659 l
+39.525 -6.659 l
+39.525 -5.835 l
+39.907 -5.835 l
+39.907 0 l
+39.525 0 l
+h
+f
+Q
+89.919 246.498 -0.647 3.983 re
+89.962 251.525 m
+89.962 251.415 89.933 251.323 89.874 251.246 c
+89.815 251.176 89.72 251.143 89.595 251.143 c
+89.477 251.143 89.381 251.176 89.316 251.246 c
+89.256 251.323 89.227 251.415 89.227 251.525 c
+89.227 251.642 89.256 251.735 89.316 251.804 c
+89.381 251.881 89.477 251.922 89.595 251.922 c
+89.72 251.922 89.815 251.881 89.874 251.804 c
+89.933 251.723 89.962 251.632 89.962 251.525 c
+92.873 247.512 m
+92.873 247.659 92.818 247.781 92.711 247.879 c
+92.601 247.975 92.395 248.093 92.094 248.232 c
+91.748 248.38 91.506 248.501 91.359 248.6 c
+91.212 248.706 91.101 248.824 91.035 248.953 c
+90.966 249.078 90.933 249.236 90.933 249.423 c
+90.933 249.747 91.05 250.015 91.286 250.231 c
+91.521 250.445 91.822 250.555 92.197 250.555 c
+92.579 250.555 92.888 250.441 93.123 250.217 c
+93.358 249.989 93.476 249.703 93.476 249.35 c
+92.828 249.35 l
+92.828 249.526 92.77 249.677 92.652 249.805 c
+92.535 249.93 92.381 249.996 92.197 249.996 c
+91.999 249.996 91.847 249.941 91.741 249.835 c
+91.631 249.735 91.579 249.604 91.579 249.438 c
+91.579 249.309 91.616 249.203 91.697 249.115 c
+91.774 249.034 91.965 248.931 92.27 248.806 c
+92.747 248.619 93.079 248.431 93.255 248.247 c
+93.431 248.071 93.52 247.843 93.52 247.571 c
+93.52 247.218 93.395 246.939 93.152 246.734 c
+92.917 246.528 92.601 246.425 92.211 246.425 c
+91.789 246.425 91.451 246.543 91.197 246.778 c
+90.94 247.02 90.815 247.325 90.815 247.688 c
+91.461 247.688 l
+91.469 247.461 91.539 247.285 91.667 247.16 c
+91.793 247.042 91.976 246.983 92.211 246.983 c
+92.425 246.983 92.587 247.031 92.697 247.131 c
+92.814 247.226 92.873 247.354 92.873 247.512 c
+96.695 250.481 m
+96.709 250.04 l
+96.963 250.383 97.287 250.555 97.68 250.555 c
+98.385 250.555 98.742 250.084 98.752 249.144 c
+98.752 246.498 l
+98.106 246.498 l
+98.106 249.115 l
+98.106 249.427 98.05 249.647 97.944 249.776 c
+97.834 249.901 97.68 249.967 97.474 249.967 c
+97.316 249.967 97.169 249.912 97.033 249.805 c
+96.904 249.695 96.801 249.56 96.724 249.394 c
+96.724 246.498 l
+96.077 246.498 l
+96.077 250.481 l
+h
+99.59 248.673 m
+99.59 249.251 99.726 249.706 100.001 250.04 c
+100.285 250.383 100.656 250.555 101.119 250.555 c
+101.578 250.555 101.946 250.386 102.222 250.055 c
+102.505 249.732 102.652 249.284 102.662 248.718 c
+102.662 248.291 l
+102.662 247.722 102.519 247.266 102.236 246.925 c
+101.96 246.59 101.593 246.425 101.134 246.425 c
+100.67 246.425 100.3 246.586 100.017 246.909 c
+99.741 247.241 99.598 247.682 99.59 248.232 c
+h
+100.237 248.291 m
+100.237 247.887 100.314 247.571 100.472 247.336 c
+100.637 247.1 100.858 246.983 101.134 246.983 c
+101.7 246.983 101.994 247.395 102.016 248.218 c
+102.016 248.673 l
+102.016 249.074 101.931 249.394 101.765 249.629 c
+101.607 249.872 101.391 249.996 101.119 249.996 c
+100.855 249.996 100.637 249.872 100.472 249.629 c
+100.314 249.394 100.237 249.074 100.237 248.673 c
+h
+104.352 251.437 m
+104.352 250.481 l
+104.955 250.481 l
+104.955 249.953 l
+104.352 249.953 l
+104.352 247.483 l
+104.352 247.325 104.375 247.208 104.427 247.131 c
+104.485 247.05 104.573 247.013 104.691 247.013 c
+104.779 247.013 104.867 247.027 104.955 247.056 c
+104.955 246.498 l
+104.809 246.45 104.654 246.425 104.5 246.425 c
+104.242 246.425 104.048 246.516 103.912 246.703 c
+103.772 246.888 103.706 247.148 103.706 247.483 c
+103.706 249.953 l
+103.103 249.953 l
+103.103 250.481 l
+103.706 250.481 l
+103.706 251.437 l
+h
+110.32 248.291 m
+110.32 247.663 110.203 247.193 109.968 246.88 c
+109.74 246.576 109.424 246.425 109.012 246.425 c
+108.608 246.425 108.3 246.576 108.086 246.88 c
+108.086 244.97 l
+107.44 244.97 l
+107.44 250.481 l
+108.028 250.481 l
+108.071 250.04 l
+108.285 250.383 108.593 250.555 108.998 250.555 c
+109.439 250.555 109.765 250.401 109.983 250.1 c
+110.195 249.795 110.309 249.338 110.32 248.733 c
+h
+109.674 248.673 m
+109.674 249.115 109.604 249.438 109.468 249.643 c
+109.328 249.857 109.108 249.967 108.807 249.967 c
+108.491 249.967 108.252 249.813 108.086 249.512 c
+108.086 247.439 l
+108.252 247.134 108.491 246.983 108.807 246.983 c
+109.1 246.983 109.314 247.086 109.453 247.291 c
+109.59 247.505 109.663 247.836 109.674 248.276 c
+h
+112.805 249.864 m
+112.717 249.882 112.618 249.893 112.51 249.893 c
+112.177 249.893 111.941 249.71 111.805 249.35 c
+111.805 246.498 l
+111.159 246.498 l
+111.159 250.481 l
+111.791 250.481 l
+111.805 250.07 l
+111.982 250.393 112.225 250.555 112.54 250.555 c
+112.647 250.555 112.735 250.533 112.805 250.497 c
+h
+113.245 248.673 m
+113.245 249.251 113.382 249.706 113.657 250.04 c
+113.94 250.383 114.311 250.555 114.775 250.555 c
+115.234 250.555 115.601 250.386 115.876 250.055 c
+116.16 249.732 116.306 249.284 116.318 248.718 c
+116.318 248.291 l
+116.318 247.722 116.175 247.266 115.892 246.925 c
+115.616 246.59 115.248 246.425 114.789 246.425 c
+114.326 246.425 113.955 246.586 113.672 246.909 c
+113.397 247.241 113.253 247.682 113.245 248.232 c
+h
+113.892 248.291 m
+113.892 247.887 113.97 247.571 114.128 247.336 c
+114.293 247.1 114.513 246.983 114.789 246.983 c
+115.355 246.983 115.649 247.395 115.671 248.218 c
+115.671 248.673 l
+115.671 249.074 115.587 249.394 115.421 249.629 c
+115.263 249.872 115.047 249.996 114.775 249.996 c
+114.51 249.996 114.293 249.872 114.128 249.629 c
+113.97 249.394 113.892 249.074 113.892 248.673 c
+h
+118.228 247.483 m
+118.978 250.481 l
+119.639 250.481 l
+118.464 246.498 l
+117.979 246.498 l
+116.788 250.481 l
+117.449 250.481 l
+h
+121.021 246.498 -0.646 3.983 re
+121.066 251.525 m
+121.066 251.415 121.036 251.323 120.977 251.246 c
+120.919 251.176 120.823 251.143 120.698 251.143 c
+120.58 251.143 120.485 251.176 120.419 251.246 c
+120.36 251.323 120.331 251.415 120.331 251.525 c
+120.331 251.642 120.36 251.735 120.419 251.804 c
+120.485 251.881 120.58 251.922 120.698 251.922 c
+120.823 251.922 120.919 251.881 120.977 251.804 c
+121.036 251.723 121.066 251.632 121.066 251.525 c
+121.904 248.673 m
+121.904 249.28 122.014 249.747 122.242 250.07 c
+122.477 250.393 122.804 250.555 123.226 250.555 c
+123.608 250.555 123.907 250.397 124.123 250.084 c
+124.123 252.143 l
+124.769 252.143 l
+124.769 246.498 l
+124.182 246.498 l
+124.138 246.925 l
+123.932 246.59 123.627 246.425 123.226 246.425 c
+122.814 246.425 122.492 246.579 122.257 246.895 c
+122.021 247.218 121.904 247.674 121.904 248.262 c
+h
+122.55 248.291 m
+122.55 247.85 122.613 247.52 122.741 247.306 c
+122.877 247.1 123.098 246.998 123.402 246.998 c
+123.726 246.998 123.965 247.16 124.123 247.483 c
+124.123 249.497 l
+123.954 249.809 123.715 249.967 123.402 249.967 c
+123.098 249.967 122.877 249.864 122.741 249.658 c
+122.613 249.452 122.55 249.13 122.55 248.688 c
+h
+127.195 246.425 m
+126.695 246.425 126.313 246.572 126.049 246.865 c
+125.784 247.16 125.652 247.593 125.652 248.174 c
+125.652 248.644 l
+125.652 249.24 125.777 249.706 126.034 250.04 c
+126.299 250.383 126.658 250.555 127.121 250.555 c
+127.581 250.555 127.923 250.401 128.15 250.1 c
+128.385 249.805 128.507 249.342 128.518 248.718 c
+128.518 248.291 l
+126.299 248.291 l
+126.299 248.203 l
+126.299 247.769 126.376 247.457 126.534 247.262 c
+126.699 247.075 126.93 246.983 127.225 246.983 c
+127.419 246.983 127.591 247.017 127.739 247.086 c
+127.886 247.163 128.022 247.281 128.15 247.439 c
+128.489 247.027 l
+128.202 246.623 127.772 246.425 127.195 246.425 c
+127.121 249.996 m
+126.846 249.996 126.644 249.901 126.519 249.718 c
+126.39 249.529 126.317 249.24 126.299 248.85 c
+127.871 248.85 l
+127.871 248.938 l
+127.849 249.321 127.783 249.589 127.666 249.747 c
+127.548 249.912 127.364 249.996 127.121 249.996 c
+129.164 248.673 m
+129.164 249.28 129.275 249.747 129.503 250.07 c
+129.738 250.393 130.065 250.555 130.488 250.555 c
+130.87 250.555 131.167 250.397 131.385 250.084 c
+131.385 252.143 l
+132.031 252.143 l
+132.031 246.498 l
+131.443 246.498 l
+131.399 246.925 l
+131.194 246.59 130.888 246.425 130.488 246.425 c
+130.076 246.425 129.752 246.579 129.517 246.895 c
+129.282 247.218 129.164 247.674 129.164 248.262 c
+h
+129.812 248.291 m
+129.812 247.85 129.874 247.52 130.003 247.306 c
+130.139 247.1 130.359 246.998 130.664 246.998 c
+130.988 246.998 131.227 247.16 131.385 247.483 c
+131.385 249.497 l
+131.215 249.809 130.976 249.967 130.664 249.967 c
+130.359 249.967 130.139 249.864 130.003 249.658 c
+129.874 249.452 129.812 249.13 129.812 248.688 c
+h
+133.045 245.425 m
+132.649 245.689 l
+132.884 246.013 133.005 246.348 133.016 246.689 c
+133.016 247.306 l
+133.677 247.306 l
+133.677 246.778 l
+133.677 246.52 133.611 246.274 133.486 246.028 c
+133.369 245.785 133.222 245.583 133.045 245.425 c
+137.087 251.437 m
+137.087 250.481 l
+137.69 250.481 l
+137.69 249.953 l
+137.087 249.953 l
+137.087 247.483 l
+137.087 247.325 137.11 247.208 137.161 247.131 c
+137.22 247.05 137.308 247.013 137.426 247.013 c
+137.513 247.013 137.602 247.027 137.69 247.056 c
+137.69 246.498 l
+137.544 246.45 137.389 246.425 137.234 246.425 c
+136.977 246.425 136.783 246.516 136.647 246.703 c
+136.507 246.888 136.441 247.148 136.441 247.483 c
+136.441 249.953 l
+135.838 249.953 l
+135.838 250.481 l
+136.441 250.481 l
+136.441 251.437 l
+h
+139.101 250.07 m
+139.354 250.393 139.674 250.555 140.056 250.555 c
+140.762 250.555 141.118 250.084 141.13 249.144 c
+141.13 246.498 l
+140.483 246.498 l
+140.483 249.115 l
+140.483 249.427 140.428 249.647 140.322 249.776 c
+140.212 249.901 140.056 249.967 139.851 249.967 c
+139.693 249.967 139.546 249.912 139.41 249.805 c
+139.281 249.695 139.179 249.56 139.101 249.394 c
+139.101 246.498 l
+138.454 246.498 l
+138.454 252.143 l
+139.101 252.143 l
+h
+143.511 246.425 m
+143.011 246.425 142.629 246.572 142.365 246.865 c
+142.1 247.16 141.968 247.593 141.968 248.174 c
+141.968 248.644 l
+141.968 249.24 142.093 249.706 142.35 250.04 c
+142.614 250.383 142.974 250.555 143.437 250.555 c
+143.897 250.555 144.239 250.401 144.466 250.1 c
+144.702 249.805 144.823 249.342 144.834 248.718 c
+144.834 248.291 l
+142.614 248.291 l
+142.614 248.203 l
+142.614 247.769 142.691 247.457 142.849 247.262 c
+143.015 247.075 143.246 246.983 143.541 246.983 c
+143.736 246.983 143.908 247.017 144.054 247.086 c
+144.202 247.163 144.338 247.281 144.466 247.439 c
+144.804 247.027 l
+144.518 246.623 144.088 246.425 143.511 246.425 c
+143.437 249.996 m
+143.162 249.996 142.959 249.901 142.835 249.718 c
+142.706 249.529 142.633 249.24 142.614 248.85 c
+144.187 248.85 l
+144.187 248.938 l
+144.165 249.321 144.099 249.589 143.981 249.747 c
+143.863 249.912 143.68 249.996 143.437 249.996 c
+146.23 250.481 m
+146.245 250.04 l
+146.498 250.383 146.822 250.555 147.215 250.555 c
+147.921 250.555 148.277 250.084 148.288 249.144 c
+148.288 246.498 l
+147.641 246.498 l
+147.641 249.115 l
+147.641 249.427 147.586 249.647 147.48 249.776 c
+147.37 249.901 147.215 249.967 147.009 249.967 c
+146.851 249.967 146.704 249.912 146.568 249.805 c
+146.44 249.695 146.337 249.56 146.26 249.394 c
+146.26 246.498 l
+145.613 246.498 l
+145.613 250.481 l
+h
+153.022 246.498 m
+152.981 246.586 152.955 246.734 152.948 246.939 c
+152.713 246.593 152.419 246.425 152.066 246.425 c
+151.702 246.425 151.419 246.52 151.213 246.718 c
+151.015 246.925 150.919 247.211 150.919 247.586 c
+150.919 247.987 151.055 248.306 151.331 248.542 c
+151.603 248.783 151.977 248.909 152.448 248.909 c
+152.933 248.909 l
+152.933 249.335 l
+152.933 249.57 152.878 249.735 152.771 249.835 c
+152.661 249.941 152.499 249.996 152.286 249.996 c
+152.088 249.996 151.927 249.938 151.801 249.82 c
+151.684 249.703 151.625 249.556 151.625 249.379 c
+150.978 249.379 l
+150.978 249.574 151.037 249.765 151.154 249.953 c
+151.279 250.136 151.441 250.283 151.64 250.393 c
+151.846 250.5 152.073 250.555 152.33 250.555 c
+152.731 250.555 153.036 250.452 153.242 250.246 c
+153.455 250.04 153.569 249.747 153.58 249.365 c
+153.58 247.351 l
+153.58 247.046 153.617 246.782 153.697 246.557 c
+153.697 246.498 l
+h
+152.154 247.013 m
+152.32 247.013 152.47 247.056 152.61 247.145 c
+152.756 247.233 152.864 247.343 152.933 247.483 c
+152.933 248.424 l
+152.565 248.424 l
+152.249 248.424 152.007 248.354 151.831 248.218 c
+151.655 248.089 151.566 247.902 151.566 247.659 c
+151.566 247.432 151.61 247.266 151.699 247.16 c
+151.786 247.06 151.937 247.013 152.154 247.013 c
+156.916 250.481 m
+156.931 250.04 l
+157.185 250.383 157.508 250.555 157.901 250.555 c
+158.607 250.555 158.963 250.084 158.975 249.144 c
+158.975 246.498 l
+158.327 246.498 l
+158.327 249.115 l
+158.327 249.427 158.273 249.647 158.166 249.776 c
+158.055 249.901 157.901 249.967 157.695 249.967 c
+157.538 249.967 157.39 249.912 157.255 249.805 c
+157.126 249.695 157.023 249.56 156.946 249.394 c
+156.946 246.498 l
+156.299 246.498 l
+156.299 250.481 l
+h
+161.371 246.425 m
+160.871 246.425 160.488 246.572 160.224 246.865 c
+159.96 247.16 159.827 247.593 159.827 248.174 c
+159.827 248.644 l
+159.827 249.24 159.952 249.706 160.209 250.04 c
+160.474 250.383 160.833 250.555 161.297 250.555 c
+161.756 250.555 162.098 250.401 162.325 250.1 c
+162.561 249.805 162.682 249.342 162.693 248.718 c
+162.693 248.291 l
+160.474 248.291 l
+160.474 248.203 l
+160.474 247.769 160.551 247.457 160.709 247.262 c
+160.874 247.075 161.106 246.983 161.4 246.983 c
+161.595 246.983 161.768 247.017 161.914 247.086 c
+162.061 247.163 162.198 247.281 162.325 247.439 c
+162.664 247.027 l
+162.377 246.623 161.947 246.425 161.371 246.425 c
+161.297 249.996 m
+161.022 249.996 160.819 249.901 160.694 249.718 c
+160.565 249.529 160.492 249.24 160.474 248.85 c
+162.047 248.85 l
+162.047 248.938 l
+162.024 249.321 161.959 249.589 161.841 249.747 c
+161.723 249.912 161.539 249.996 161.297 249.996 c
+166.441 247.644 m
+167.044 250.481 l
+167.691 250.481 l
+166.706 246.498 l
+166.192 246.498 l
+165.413 249.35 l
+164.663 246.498 l
+164.134 246.498 l
+163.179 250.481 l
+163.81 250.481 l
+164.428 247.719 l
+165.163 250.481 l
+165.677 250.481 l
+h
+171.733 249.864 m
+171.645 249.882 171.546 249.893 171.439 249.893 c
+171.104 249.893 170.869 249.71 170.734 249.35 c
+170.734 246.498 l
+170.087 246.498 l
+170.087 250.481 l
+170.719 250.481 l
+170.734 250.07 l
+170.91 250.393 171.152 250.555 171.469 250.555 c
+171.575 250.555 171.663 250.533 171.733 250.497 c
+h
+173.732 246.425 m
+173.232 246.425 172.85 246.572 172.586 246.865 c
+172.321 247.16 172.189 247.593 172.189 248.174 c
+172.189 248.644 l
+172.189 249.24 172.314 249.706 172.571 250.04 c
+172.835 250.383 173.196 250.555 173.659 250.555 c
+174.119 250.555 174.46 250.401 174.688 250.1 c
+174.923 249.805 175.044 249.342 175.056 248.718 c
+175.056 248.291 l
+172.835 248.291 l
+172.835 248.203 l
+172.835 247.769 172.913 247.457 173.071 247.262 c
+173.236 247.075 173.468 246.983 173.762 246.983 c
+173.957 246.983 174.129 247.017 174.277 247.086 c
+174.423 247.163 174.559 247.281 174.688 247.439 c
+175.025 247.027 l
+174.739 246.623 174.31 246.425 173.732 246.425 c
+173.659 249.996 m
+173.383 249.996 173.181 249.901 173.056 249.718 c
+172.928 249.529 172.854 249.24 172.835 248.85 c
+174.408 248.85 l
+174.408 248.938 l
+174.387 249.321 174.32 249.589 174.202 249.747 c
+174.085 249.912 173.901 249.996 173.659 249.996 c
+178.715 248.291 m
+178.715 247.663 178.597 247.193 178.362 246.88 c
+178.135 246.576 177.819 246.425 177.407 246.425 c
+177.003 246.425 176.694 246.576 176.481 246.88 c
+176.481 244.97 l
+175.834 244.97 l
+175.834 250.481 l
+176.422 250.481 l
+176.467 250.04 l
+176.679 250.383 176.988 250.555 177.392 250.555 c
+177.834 250.555 178.16 250.401 178.377 250.1 c
+178.59 249.795 178.705 249.338 178.715 248.733 c
+h
+178.069 248.673 m
+178.069 249.115 177.999 249.438 177.863 249.643 c
+177.723 249.857 177.502 249.967 177.201 249.967 c
+176.885 249.967 176.646 249.813 176.481 249.512 c
+176.481 247.439 l
+176.646 247.134 176.885 246.983 177.201 246.983 c
+177.495 246.983 177.708 247.086 177.848 247.291 c
+177.984 247.505 178.057 247.836 178.069 248.276 c
+h
+179.421 248.673 m
+179.421 249.251 179.557 249.706 179.833 250.04 c
+180.116 250.383 180.486 250.555 180.949 250.555 c
+181.409 250.555 181.776 250.386 182.052 250.055 c
+182.335 249.732 182.482 249.284 182.493 248.718 c
+182.493 248.291 l
+182.493 247.722 182.35 247.266 182.067 246.925 c
+181.791 246.59 181.423 246.425 180.964 246.425 c
+180.501 246.425 180.13 246.586 179.847 246.909 c
+179.571 247.241 179.428 247.682 179.421 248.232 c
+h
+180.068 248.291 m
+180.068 247.887 180.145 247.571 180.303 247.336 c
+180.469 247.1 180.689 246.983 180.964 246.983 c
+181.53 246.983 181.824 247.395 181.846 248.218 c
+181.846 248.673 l
+181.846 249.074 181.762 249.394 181.597 249.629 c
+181.438 249.872 181.221 249.996 180.949 249.996 c
+180.685 249.996 180.469 249.872 180.303 249.629 c
+180.145 249.394 180.068 249.074 180.068 248.673 c
+h
+185.271 247.512 m
+185.271 247.659 185.216 247.781 185.109 247.879 c
+184.999 247.975 184.793 248.093 184.492 248.232 c
+184.147 248.38 183.904 248.501 183.757 248.6 c
+183.61 248.706 183.5 248.824 183.434 248.953 c
+183.364 249.078 183.33 249.236 183.33 249.423 c
+183.33 249.747 183.449 250.015 183.684 250.231 c
+183.919 250.445 184.22 250.555 184.595 250.555 c
+184.977 250.555 185.286 250.441 185.521 250.217 c
+185.756 249.989 185.874 249.703 185.874 249.35 c
+185.227 249.35 l
+185.227 249.526 185.169 249.677 185.051 249.805 c
+184.933 249.93 184.779 249.996 184.595 249.996 c
+184.396 249.996 184.246 249.941 184.139 249.835 c
+184.029 249.735 183.978 249.604 183.978 249.438 c
+183.978 249.309 184.014 249.203 184.095 249.115 c
+184.172 249.034 184.363 248.931 184.668 248.806 c
+185.146 248.619 185.477 248.431 185.653 248.247 c
+185.83 248.071 185.917 247.843 185.917 247.571 c
+185.917 247.218 185.793 246.939 185.55 246.734 c
+185.315 246.528 184.999 246.425 184.61 246.425 c
+184.187 246.425 183.849 246.543 183.596 246.778 c
+183.338 247.02 183.214 247.325 183.214 247.688 c
+183.86 247.688 l
+183.867 247.461 183.937 247.285 184.066 247.16 c
+184.191 247.042 184.375 246.983 184.61 246.983 c
+184.822 246.983 184.984 247.031 185.095 247.131 c
+185.212 247.226 185.271 247.354 185.271 247.512 c
+187.461 246.498 -0.646 3.983 re
+187.505 251.525 m
+187.505 251.415 187.476 251.323 187.417 251.246 c
+187.359 251.176 187.263 251.143 187.137 251.143 c
+187.02 251.143 186.925 251.176 186.858 251.246 c
+186.8 251.323 186.771 251.415 186.771 251.525 c
+186.771 251.642 186.8 251.735 186.858 251.804 c
+186.925 251.881 187.02 251.922 187.137 251.922 c
+187.263 251.922 187.359 251.881 187.417 251.804 c
+187.476 251.723 187.505 251.632 187.505 251.525 c
+189.328 251.437 m
+189.328 250.481 l
+189.931 250.481 l
+189.931 249.953 l
+189.328 249.953 l
+189.328 247.483 l
+189.328 247.325 189.35 247.208 189.402 247.131 c
+189.46 247.05 189.549 247.013 189.666 247.013 c
+189.755 247.013 189.842 247.027 189.931 247.056 c
+189.931 246.498 l
+189.784 246.45 189.629 246.425 189.475 246.425 c
+189.217 246.425 189.023 246.516 188.887 246.703 c
+188.747 246.888 188.681 247.148 188.681 247.483 c
+188.681 249.953 l
+188.078 249.953 l
+188.078 250.481 l
+188.681 250.481 l
+188.681 251.437 l
+h
+190.489 248.673 m
+190.489 249.251 190.625 249.706 190.9 250.04 c
+191.184 250.383 191.555 250.555 192.018 250.555 c
+192.477 250.555 192.845 250.386 193.121 250.055 c
+193.404 249.732 193.55 249.284 193.562 248.718 c
+193.562 248.291 l
+193.562 247.722 193.418 247.266 193.135 246.925 c
+192.859 246.59 192.492 246.425 192.032 246.425 c
+191.569 246.425 191.199 246.586 190.915 246.909 c
+190.64 247.241 190.497 247.682 190.489 248.232 c
+h
+191.136 248.291 m
+191.136 247.887 191.213 247.571 191.371 247.336 c
+191.536 247.1 191.757 246.983 192.032 246.983 c
+192.598 246.983 192.893 247.395 192.915 248.218 c
+192.915 248.673 l
+192.915 249.074 192.83 249.394 192.664 249.629 c
+192.506 249.872 192.29 249.996 192.018 249.996 c
+191.754 249.996 191.536 249.872 191.371 249.629 c
+191.213 249.394 191.136 249.074 191.136 248.673 c
+h
+196.045 249.864 m
+195.957 249.882 195.858 249.893 195.752 249.893 c
+195.417 249.893 195.182 249.71 195.046 249.35 c
+195.046 246.498 l
+194.399 246.498 l
+194.399 250.481 l
+195.031 250.481 l
+195.046 250.07 l
+195.222 250.393 195.465 250.555 195.781 250.555 c
+195.887 250.555 195.976 250.533 196.045 250.497 c
+h
+197.853 247.586 m
+198.574 250.481 l
+199.265 250.481 l
+197.971 245.94 l
+197.872 245.598 197.728 245.337 197.545 245.161 c
+197.368 244.984 197.167 244.896 196.942 244.896 c
+196.854 244.896 196.74 244.918 196.604 244.955 c
+196.604 245.498 l
+196.751 245.484 l
+196.934 245.484 197.082 245.528 197.192 245.616 c
+197.298 245.704 197.387 245.862 197.456 246.086 c
+197.574 246.528 l
+196.413 250.481 l
+197.119 250.481 l
+h
+202.322 246.498 -0.647 3.983 re
+202.366 251.525 m
+202.366 251.415 202.337 251.323 202.278 251.246 c
+202.219 251.176 202.123 251.143 201.998 251.143 c
+201.881 251.143 201.786 251.176 201.719 251.246 c
+201.661 251.323 201.631 251.415 201.631 251.525 c
+201.631 251.642 201.661 251.735 201.719 251.804 c
+201.786 251.881 201.881 251.922 201.998 251.922 c
+202.123 251.922 202.219 251.881 202.278 251.804 c
+202.337 251.723 202.366 251.632 202.366 251.525 c
+205.277 247.512 m
+205.277 247.659 205.221 247.781 205.115 247.879 c
+205.005 247.975 204.799 248.093 204.497 248.232 c
+204.152 248.38 203.91 248.501 203.762 248.6 c
+203.615 248.706 203.505 248.824 203.44 248.953 c
+203.369 249.078 203.336 249.236 203.336 249.423 c
+203.336 249.747 203.454 250.015 203.689 250.231 c
+203.924 250.445 204.225 250.555 204.6 250.555 c
+204.982 250.555 205.291 250.441 205.526 250.217 c
+205.761 249.989 205.879 249.703 205.879 249.35 c
+205.233 249.35 l
+205.233 249.526 205.173 249.677 205.056 249.805 c
+204.938 249.93 204.784 249.996 204.6 249.996 c
+204.402 249.996 204.251 249.941 204.145 249.835 c
+204.034 249.735 203.983 249.604 203.983 249.438 c
+203.983 249.309 204.02 249.203 204.101 249.115 c
+204.178 249.034 204.369 248.931 204.674 248.806 c
+205.152 248.619 205.482 248.431 205.659 248.247 c
+205.835 248.071 205.923 247.843 205.923 247.571 c
+205.923 247.218 205.798 246.939 205.556 246.734 c
+205.321 246.528 205.005 246.425 204.615 246.425 c
+204.192 246.425 203.854 246.543 203.6 246.778 c
+203.344 247.02 203.218 247.325 203.218 247.688 c
+203.866 247.688 l
+203.872 247.461 203.943 247.285 204.071 247.16 c
+204.196 247.042 204.38 246.983 204.615 246.983 c
+204.828 246.983 204.99 247.031 205.1 247.131 c
+205.218 247.226 205.277 247.354 205.277 247.512 c
+209.187 246.498 -0.647 3.983 re
+209.231 251.525 m
+209.231 251.415 209.201 251.323 209.142 251.246 c
+209.084 251.176 208.988 251.143 208.863 251.143 c
+208.745 251.143 208.65 251.176 208.584 251.246 c
+208.525 251.323 208.495 251.415 208.495 251.525 c
+208.495 251.642 208.525 251.735 208.584 251.804 c
+208.65 251.881 208.745 251.922 208.863 251.922 c
+208.988 251.922 209.084 251.881 209.142 251.804 c
+209.201 251.723 209.231 251.632 209.231 251.525 c
+210.818 250.481 m
+210.833 250.04 l
+211.086 250.383 211.409 250.555 211.803 250.555 c
+212.508 250.555 212.865 250.084 212.876 249.144 c
+212.876 246.498 l
+212.229 246.498 l
+212.229 249.115 l
+212.229 249.427 212.174 249.647 212.067 249.776 c
+211.957 249.901 211.803 249.967 211.597 249.967 c
+211.439 249.967 211.292 249.912 211.156 249.805 c
+211.028 249.695 210.925 249.56 210.847 249.394 c
+210.847 246.498 l
+210.201 246.498 l
+210.201 250.481 l
+h
+214.552 246.498 -0.647 3.983 re
+214.596 251.525 m
+214.596 251.415 214.567 251.323 214.507 251.246 c
+214.449 251.176 214.353 251.143 214.228 251.143 c
+214.11 251.143 214.015 251.176 213.949 251.246 c
+213.89 251.323 213.861 251.415 213.861 251.525 c
+213.861 251.642 213.89 251.735 213.949 251.804 c
+214.015 251.881 214.11 251.922 214.228 251.922 c
+214.353 251.922 214.449 251.881 214.507 251.804 c
+214.567 251.723 214.596 251.632 214.596 251.525 c
+216.418 251.437 m
+216.418 250.481 l
+217.021 250.481 l
+217.021 249.953 l
+216.418 249.953 l
+216.418 247.483 l
+216.418 247.325 216.441 247.208 216.491 247.131 c
+216.551 247.05 216.639 247.013 216.757 247.013 c
+216.845 247.013 216.933 247.027 217.021 247.056 c
+217.021 246.498 l
+216.874 246.45 216.72 246.425 216.566 246.425 c
+216.308 246.425 216.113 246.516 215.978 246.703 c
+215.838 246.888 215.772 247.148 215.772 247.483 c
+215.772 249.953 l
+215.169 249.953 l
+215.169 250.481 l
+215.772 250.481 l
+215.772 251.437 l
+h
+218.491 246.498 -0.647 3.983 re
+218.535 251.525 m
+218.535 251.415 218.505 251.323 218.447 251.246 c
+218.388 251.176 218.293 251.143 218.168 251.143 c
+218.05 251.143 217.954 251.176 217.888 251.246 c
+217.829 251.323 217.8 251.415 217.8 251.525 c
+217.8 251.642 217.829 251.735 217.888 251.804 c
+217.954 251.881 218.05 251.922 218.168 251.922 c
+218.293 251.922 218.388 251.881 218.447 251.804 c
+218.505 251.723 218.535 251.632 218.535 251.525 c
+221.549 246.498 m
+221.508 246.586 221.482 246.734 221.474 246.939 c
+221.239 246.593 220.946 246.425 220.593 246.425 c
+220.229 246.425 219.946 246.52 219.741 246.718 c
+219.542 246.925 219.446 247.211 219.446 247.586 c
+219.446 247.987 219.583 248.306 219.858 248.542 c
+220.13 248.783 220.505 248.909 220.975 248.909 c
+221.46 248.909 l
+221.46 249.335 l
+221.46 249.57 221.405 249.735 221.299 249.835 c
+221.188 249.941 221.027 249.996 220.813 249.996 c
+220.615 249.996 220.453 249.938 220.329 249.82 c
+220.211 249.703 220.152 249.556 220.152 249.379 c
+219.505 249.379 l
+219.505 249.574 219.564 249.765 219.681 249.953 c
+219.807 250.136 219.968 250.283 220.167 250.393 c
+220.373 250.5 220.6 250.555 220.857 250.555 c
+221.258 250.555 221.563 250.452 221.769 250.246 c
+221.982 250.04 222.096 249.747 222.107 249.365 c
+222.107 247.351 l
+222.107 247.046 222.143 246.782 222.224 246.557 c
+222.224 246.498 l
+h
+220.681 247.013 m
+220.846 247.013 220.997 247.056 221.137 247.145 c
+221.283 247.233 221.391 247.343 221.46 247.483 c
+221.46 248.424 l
+221.093 248.424 l
+220.776 248.424 220.534 248.354 220.358 248.218 c
+220.181 248.089 220.093 247.902 220.093 247.659 c
+220.093 247.432 220.138 247.266 220.225 247.16 c
+220.314 247.06 220.464 247.013 220.681 247.013 c
+223.812 246.498 -0.647 5.644 re
+225.532 246.498 -0.647 3.983 re
+225.576 251.525 m
+225.576 251.415 225.547 251.323 225.488 251.246 c
+225.428 251.176 225.333 251.143 225.208 251.143 c
+225.091 251.143 224.996 251.176 224.929 251.246 c
+224.871 251.323 224.841 251.415 224.841 251.525 c
+224.841 251.642 224.871 251.735 224.929 251.804 c
+224.996 251.881 225.091 251.922 225.208 251.922 c
+225.333 251.922 225.428 251.881 225.488 251.804 c
+225.547 251.723 225.576 251.632 225.576 251.525 c
+227.149 247.056 m
+229.075 247.056 l
+229.075 246.498 l
+226.413 246.498 l
+226.413 246.998 l
+228.236 249.909 l
+226.428 249.909 l
+226.428 250.481 l
+229 250.481 l
+229 249.996 l
+h
+231.221 246.425 m
+230.721 246.425 230.338 246.572 230.074 246.865 c
+229.809 247.16 229.677 247.593 229.677 248.174 c
+229.677 248.644 l
+229.677 249.24 229.802 249.706 230.059 250.04 c
+230.324 250.383 230.683 250.555 231.147 250.555 c
+231.606 250.555 231.948 250.401 232.175 250.1 c
+232.411 249.805 232.532 249.342 232.543 248.718 c
+232.543 248.291 l
+230.324 248.291 l
+230.324 248.203 l
+230.324 247.769 230.401 247.457 230.559 247.262 c
+230.724 247.075 230.956 246.983 231.25 246.983 c
+231.444 246.983 231.618 247.017 231.764 247.086 c
+231.911 247.163 232.047 247.281 232.175 247.439 c
+232.514 247.027 l
+232.227 246.623 231.797 246.425 231.221 246.425 c
+231.147 249.996 m
+230.872 249.996 230.669 249.901 230.544 249.718 c
+230.415 249.529 230.342 249.24 230.324 248.85 c
+231.897 248.85 l
+231.897 248.938 l
+231.874 249.321 231.808 249.589 231.691 249.747 c
+231.573 249.912 231.389 249.996 231.147 249.996 c
+233.189 248.673 m
+233.189 249.28 233.3 249.747 233.528 250.07 c
+233.763 250.393 234.091 250.555 234.513 250.555 c
+234.895 250.555 235.192 250.397 235.41 250.084 c
+235.41 252.143 l
+236.056 252.143 l
+236.056 246.498 l
+235.468 246.498 l
+235.425 246.925 l
+235.219 246.59 234.914 246.425 234.513 246.425 c
+234.101 246.425 233.778 246.579 233.543 246.895 c
+233.308 247.218 233.189 247.674 233.189 248.262 c
+h
+233.837 248.291 m
+233.837 247.85 233.899 247.52 234.028 247.306 c
+234.164 247.1 234.384 246.998 234.689 246.998 c
+235.013 246.998 235.252 247.16 235.41 247.483 c
+235.41 249.497 l
+235.24 249.809 235.001 249.967 234.689 249.967 c
+234.384 249.967 234.164 249.864 234.028 249.658 c
+233.899 249.452 233.837 249.13 233.837 248.688 c
+h
+239.481 246.498 -0.647 3.983 re
+239.525 251.525 m
+239.525 251.415 239.496 251.323 239.437 251.246 c
+239.379 251.176 239.283 251.143 239.158 251.143 c
+239.04 251.143 238.945 251.176 238.878 251.246 c
+238.82 251.323 238.791 251.415 238.791 251.525 c
+238.791 251.642 238.82 251.735 238.878 251.804 c
+238.945 251.881 239.04 251.922 239.158 251.922 c
+239.283 251.922 239.379 251.881 239.437 251.804 c
+239.496 251.723 239.525 251.632 239.525 251.525 c
+241.112 250.481 m
+241.127 250.04 l
+241.381 250.383 241.704 250.555 242.097 250.555 c
+242.803 250.555 243.159 250.084 243.171 249.144 c
+243.171 246.498 l
+242.523 246.498 l
+242.523 249.115 l
+242.523 249.427 242.469 249.647 242.362 249.776 c
+242.252 249.901 242.097 249.967 241.891 249.967 c
+241.734 249.967 241.587 249.912 241.451 249.805 c
+241.322 249.695 241.22 249.56 241.143 249.394 c
+241.143 246.498 l
+240.495 246.498 l
+240.495 250.481 l
+h
+247.242 246.983 m
+247.456 246.983 247.628 247.046 247.757 247.174 c
+247.892 247.31 247.967 247.501 247.977 247.748 c
+248.595 247.748 l
+248.572 247.366 248.437 247.046 248.183 246.792 c
+247.926 246.546 247.614 246.425 247.242 246.425 c
+246.75 246.425 246.375 246.576 246.111 246.88 c
+245.853 247.193 245.729 247.659 245.729 248.276 c
+245.729 248.718 l
+245.729 249.313 245.853 249.768 246.111 250.084 c
+246.375 250.397 246.75 250.555 247.242 250.555 c
+247.643 250.555 247.963 250.423 248.198 250.158 c
+248.44 249.901 248.572 249.556 248.595 249.115 c
+247.977 249.115 l
+247.955 249.408 247.882 249.629 247.757 249.776 c
+247.639 249.923 247.466 249.996 247.242 249.996 c
+246.949 249.996 246.731 249.897 246.595 249.703 c
+246.456 249.515 246.382 249.207 246.375 248.777 c
+246.375 248.262 l
+246.375 247.792 246.441 247.457 246.581 247.262 c
+246.728 247.075 246.949 246.983 247.242 246.983 c
+251.373 246.851 m
+251.156 246.564 250.843 246.425 250.432 246.425 c
+250.068 246.425 249.793 246.546 249.609 246.792 c
+249.432 247.046 249.337 247.409 249.33 247.879 c
+249.33 250.481 l
+249.976 250.481 l
+249.976 247.939 l
+249.976 247.31 250.16 246.998 250.535 246.998 c
+250.936 246.998 251.211 247.174 251.358 247.527 c
+251.358 250.481 l
+252.004 250.481 l
+252.004 246.498 l
+251.387 246.498 l
+h
+254.636 249.864 m
+254.548 249.882 254.448 249.893 254.342 249.893 c
+254.007 249.893 253.772 249.71 253.636 249.35 c
+253.636 246.498 l
+252.989 246.498 l
+252.989 250.481 l
+253.621 250.481 l
+253.636 250.07 l
+253.812 250.393 254.055 250.555 254.371 250.555 c
+254.477 250.555 254.566 250.533 254.636 250.497 c
+h
+256.929 249.864 m
+256.841 249.882 256.742 249.893 256.635 249.893 c
+256.301 249.893 256.065 249.71 255.929 249.35 c
+255.929 246.498 l
+255.283 246.498 l
+255.283 250.481 l
+255.915 250.481 l
+255.929 250.07 l
+256.106 250.393 256.349 250.555 256.665 250.555 c
+256.771 250.555 256.859 250.533 256.929 250.497 c
+h
+258.928 246.425 m
+258.429 246.425 258.046 246.572 257.781 246.865 c
+257.517 247.16 257.384 247.593 257.384 248.174 c
+257.384 248.644 l
+257.384 249.24 257.509 249.706 257.767 250.04 c
+258.032 250.383 258.392 250.555 258.855 250.555 c
+259.314 250.555 259.655 250.401 259.884 250.1 c
+260.119 249.805 260.24 249.342 260.251 248.718 c
+260.251 248.291 l
+258.032 248.291 l
+258.032 248.203 l
+258.032 247.769 258.109 247.457 258.267 247.262 c
+258.432 247.075 258.664 246.983 258.957 246.983 c
+259.152 246.983 259.325 247.017 259.472 247.086 c
+259.619 247.163 259.755 247.281 259.884 247.439 c
+260.222 247.027 l
+259.935 246.623 259.505 246.425 258.928 246.425 c
+258.855 249.996 m
+258.579 249.996 258.377 249.901 258.252 249.718 c
+258.123 249.529 258.049 249.24 258.032 248.85 c
+259.604 248.85 l
+259.604 248.938 l
+259.582 249.321 259.516 249.589 259.398 249.747 c
+259.281 249.912 259.097 249.996 258.855 249.996 c
+261.647 250.481 m
+261.662 250.04 l
+261.916 250.383 262.239 250.555 262.632 250.555 c
+263.337 250.555 263.694 250.084 263.705 249.144 c
+263.705 246.498 l
+263.058 246.498 l
+263.058 249.115 l
+263.058 249.427 263.003 249.647 262.897 249.776 c
+262.786 249.901 262.632 249.967 262.427 249.967 c
+262.269 249.967 262.121 249.912 261.986 249.805 c
+261.857 249.695 261.754 249.56 261.677 249.394 c
+261.677 246.498 l
+261.03 246.498 l
+261.03 250.481 l
+h
+265.528 251.437 m
+265.528 250.481 l
+266.13 250.481 l
+266.13 249.953 l
+265.528 249.953 l
+265.528 247.483 l
+265.528 247.325 265.55 247.208 265.602 247.131 c
+265.66 247.05 265.748 247.013 265.866 247.013 c
+265.954 247.013 266.042 247.027 266.13 247.056 c
+266.13 246.498 l
+265.984 246.45 265.829 246.425 265.675 246.425 c
+265.417 246.425 265.223 246.516 265.087 246.703 c
+264.947 246.888 264.881 247.148 264.881 247.483 c
+264.881 249.953 l
+264.278 249.953 l
+264.278 250.481 l
+264.881 250.481 l
+264.881 251.437 l
+h
+f
+q 1 0 0 1 239.0691 239.266 cm
+0 0 m
+0 0.607 0.111 1.073 0.339 1.397 c
+0.574 1.72 0.901 1.881 1.324 1.881 c
+1.706 1.881 2.003 1.723 2.22 1.411 c
+2.22 3.469 l
+2.866 3.469 l
+2.866 -2.175 l
+2.278 -2.175 l
+2.235 -1.749 l
+2.029 -2.084 1.724 -2.248 1.324 -2.248 c
+0.912 -2.248 0.589 -2.094 0.354 -1.778 c
+0.119 -1.455 0 -0.999 0 -0.411 c
+h
+0.647 -0.382 m
+0.647 -0.823 0.709 -1.153 0.838 -1.367 c
+0.975 -1.573 1.195 -1.675 1.5 -1.675 c
+1.823 -1.675 2.062 -1.514 2.22 -1.19 c
+2.22 0.823 l
+2.051 1.135 1.812 1.294 1.5 1.294 c
+1.195 1.294 0.975 1.191 0.838 0.985 c
+0.709 0.779 0.647 0.456 0.647 0.015 c
+h
+4.572 -2.175 -0.647 3.983 re
+4.616 2.851 m
+4.616 2.741 4.587 2.65 4.528 2.573 c
+4.469 2.502 4.374 2.469 4.248 2.469 c
+4.131 2.469 4.036 2.502 3.969 2.573 c
+3.911 2.65 3.882 2.741 3.882 2.851 c
+3.882 2.969 3.911 3.061 3.969 3.131 c
+4.036 3.208 4.131 3.248 4.248 3.248 c
+4.374 3.248 4.469 3.208 4.528 3.131 c
+4.587 3.05 4.616 2.959 4.616 2.851 c
+7.232 1.191 m
+7.144 1.209 7.045 1.22 6.939 1.22 c
+6.604 1.22 6.369 1.037 6.233 0.676 c
+6.233 -2.175 l
+5.586 -2.175 l
+5.586 1.808 l
+6.218 1.808 l
+6.233 1.397 l
+6.409 1.72 6.652 1.881 6.968 1.881 c
+7.074 1.881 7.163 1.86 7.232 1.823 c
+h
+9.231 -2.248 m
+8.732 -2.248 8.35 -2.102 8.085 -1.808 c
+7.82 -1.514 7.688 -1.08 7.688 -0.5 c
+7.688 -0.029 l
+7.688 0.566 7.813 1.033 8.071 1.367 c
+8.335 1.709 8.695 1.881 9.158 1.881 c
+9.617 1.881 9.959 1.727 10.187 1.426 c
+10.422 1.132 10.544 0.669 10.554 0.044 c
+10.554 -0.382 l
+8.335 -0.382 l
+8.335 -0.47 l
+8.335 -0.904 8.412 -1.216 8.57 -1.411 c
+8.736 -1.598 8.967 -1.691 9.261 -1.691 c
+9.455 -1.691 9.628 -1.657 9.775 -1.587 c
+9.922 -1.51 10.058 -1.392 10.187 -1.234 c
+10.525 -1.646 l
+10.238 -2.05 9.808 -2.248 9.231 -2.248 c
+9.158 1.323 m
+8.882 1.323 8.68 1.228 8.555 1.044 c
+8.427 0.856 8.353 0.566 8.335 0.177 c
+9.908 0.177 l
+9.908 0.264 l
+9.885 0.647 9.819 0.915 9.702 1.073 c
+9.584 1.239 9.401 1.323 9.158 1.323 c
+12.715 -1.691 m
+12.929 -1.691 13.101 -1.627 13.23 -1.5 c
+13.366 -1.363 13.439 -1.172 13.45 -0.926 c
+14.068 -0.926 l
+14.045 -1.308 13.91 -1.627 13.656 -1.881 c
+13.399 -2.127 13.087 -2.248 12.715 -2.248 c
+12.223 -2.248 11.848 -2.098 11.583 -1.793 c
+11.327 -1.481 11.201 -1.014 11.201 -0.397 c
+11.201 0.044 l
+11.201 0.64 11.327 1.095 11.583 1.411 c
+11.848 1.723 12.223 1.881 12.715 1.881 c
+13.116 1.881 13.436 1.75 13.671 1.484 c
+13.914 1.228 14.045 0.882 14.068 0.441 c
+13.45 0.441 l
+13.428 0.735 13.355 0.956 13.23 1.103 c
+13.112 1.249 12.939 1.323 12.715 1.323 c
+12.422 1.323 12.204 1.224 12.069 1.029 c
+11.929 0.842 11.855 0.533 11.848 0.103 c
+11.848 -0.411 l
+11.848 -0.881 11.914 -1.216 12.054 -1.411 c
+12.2 -1.598 12.422 -1.691 12.715 -1.691 c
+15.67 2.764 m
+15.67 1.808 l
+16.272 1.808 l
+16.272 1.279 l
+15.67 1.279 l
+15.67 -1.19 l
+15.67 -1.348 15.692 -1.466 15.743 -1.543 c
+15.802 -1.624 15.89 -1.66 16.008 -1.66 c
+16.096 -1.66 16.184 -1.646 16.272 -1.617 c
+16.272 -2.175 l
+16.125 -2.223 15.971 -2.248 15.817 -2.248 c
+15.56 -2.248 15.365 -2.157 15.229 -1.97 c
+15.089 -1.786 15.023 -1.525 15.023 -1.19 c
+15.023 1.279 l
+14.421 1.279 l
+14.421 1.808 l
+15.023 1.808 l
+15.023 2.764 l
+h
+16.831 0 m
+16.831 0.578 16.967 1.033 17.243 1.367 c
+17.525 1.709 17.897 1.881 18.359 1.881 c
+18.819 1.881 19.186 1.713 19.462 1.382 c
+19.745 1.058 19.892 0.611 19.903 0.044 c
+19.903 -0.382 l
+19.903 -0.951 19.759 -1.407 19.477 -1.749 c
+19.201 -2.084 18.834 -2.248 18.375 -2.248 c
+17.912 -2.248 17.54 -2.087 17.257 -1.764 c
+16.981 -1.433 16.838 -0.992 16.831 -0.441 c
+h
+17.478 -0.382 m
+17.478 -0.786 17.555 -1.103 17.713 -1.338 c
+17.878 -1.573 18.099 -1.691 18.375 -1.691 c
+18.94 -1.691 19.234 -1.278 19.256 -0.455 c
+19.256 0 l
+19.256 0.401 19.171 0.721 19.007 0.956 c
+18.849 1.199 18.631 1.323 18.359 1.323 c
+18.095 1.323 17.878 1.199 17.713 0.956 c
+17.555 0.721 17.478 0.401 17.478 0 c
+h
+22.387 1.191 m
+22.299 1.209 22.2 1.22 22.093 1.22 c
+21.758 1.22 21.523 1.037 21.388 0.676 c
+21.388 -2.175 l
+20.741 -2.175 l
+20.741 1.808 l
+21.373 1.808 l
+21.388 1.397 l
+21.564 1.72 21.806 1.881 22.122 1.881 c
+22.229 1.881 22.317 1.86 22.387 1.823 c
+h
+24.195 -1.087 m
+24.915 1.808 l
+25.606 1.808 l
+24.312 -2.734 l
+24.214 -3.075 24.07 -3.337 23.886 -3.513 c
+23.71 -3.69 23.508 -3.777 23.283 -3.777 c
+23.196 -3.777 23.082 -3.755 22.946 -3.719 c
+22.946 -3.175 l
+23.092 -3.189 l
+23.277 -3.189 23.423 -3.146 23.534 -3.057 c
+23.64 -2.969 23.728 -2.811 23.798 -2.587 c
+23.915 -2.146 l
+22.755 1.808 l
+23.46 1.808 l
+h
+25.885 -1.822 m
+25.885 -1.705 25.918 -1.61 25.989 -1.529 c
+26.055 -1.452 26.157 -1.411 26.297 -1.411 c
+26.444 -1.411 26.551 -1.452 26.62 -1.529 c
+26.697 -1.61 26.738 -1.705 26.738 -1.822 c
+26.738 -1.932 26.697 -2.024 26.62 -2.102 c
+26.551 -2.179 26.444 -2.219 26.297 -2.219 c
+26.157 -2.219 26.055 -2.179 25.989 -2.102 c
+25.918 -2.024 25.885 -1.932 25.885 -1.822 c
+f
+Q
+0.113 0.082 0.09 0 k
+35.668 231.104 238.665 -12.895 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 40.8563 224.2696 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.647 -0.243 -0.775 -0.367 -0.882 c
+-0.496 -0.992 -0.658 -1.081 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.162 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.927 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.132 l
+-2.642 0.033 -2.616 -0.059 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.683 -1.992 0.69 -1.999 0.69 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.881 -2.786 0.959 -2.91 1.058 c
+-3.039 1.153 -3.142 1.278 -3.219 1.425 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.836 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.119 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.119 -1.128 3.09 -0.97 3.042 c
+-0.804 2.992 -0.669 2.917 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.252 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.352 c
+-1.294 1.311 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.319 2.385 -2.366 2.337 c
+-2.406 2.296 -2.437 2.248 -2.454 2.19 c
+-2.477 2.131 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.778 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.469 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.091 -0.86 0.176 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.529 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.53 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.22 5.108 -2.103 c
+5.039 -1.985 4.991 -1.856 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.86 6.064 -1.941 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.058 6.681 -2.028 c
+6.758 -1.999 6.828 -1.945 6.887 -1.867 c
+6.945 -1.797 6.99 -1.706 7.019 -1.588 c
+7.056 -1.47 7.078 -1.323 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.073 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.412 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.234 c
+4.946 1.448 5.027 1.631 5.137 1.778 c
+5.245 1.933 5.376 2.051 5.534 2.131 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.252 6.387 2.234 c
+6.483 2.212 6.571 2.179 6.652 2.131 c
+6.739 2.08 6.817 2.017 6.887 1.94 c
+6.964 1.859 7.026 1.768 7.078 1.66 c
+7.092 1.66 l
+7.092 1.808 l
+7.1 1.866 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.152 2.219 c
+8.004 2.219 l
+7.993 2.138 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.162 l
+7.975 -1.415 7.938 -1.635 7.871 -1.823 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.529 m
+7.092 0.742 7.067 0.918 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.587 c
+6.571 1.624 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.62 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.339 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.177 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.529 c
+11.036 -0.647 m
+12.168 -0.647 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.647 l
+10.124 -0.647 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.676 re
+10.124 2.836 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.219 l
+13.644 2.219 l
+13.924 3.116 l
+14.497 3.116 l
+14.497 2.219 l
+15.732 2.219 l
+15.732 1.602 l
+14.497 1.602 l
+14.497 -0.103 l
+14.497 -0.324 l
+14.504 -0.393 14.527 -0.456 14.556 -0.515 c
+14.593 -0.566 14.648 -0.611 14.718 -0.647 c
+14.795 -0.676 14.909 -0.691 15.056 -0.691 c
+15.192 -0.691 15.327 -0.688 15.468 -0.676 c
+15.603 -0.658 15.736 -0.632 15.865 -0.603 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.231 15.629 -1.249 c
+15.549 -1.261 15.471 -1.268 15.394 -1.279 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.041 -1.301 14.942 -1.309 14.835 -1.309 c
+14.648 -1.309 14.486 -1.294 14.35 -1.264 c
+14.221 -1.228 14.107 -1.183 14.012 -1.132 c
+13.924 -1.085 13.85 -1.025 13.791 -0.956 c
+13.733 -0.879 13.689 -0.802 13.66 -0.721 c
+13.63 -0.632 13.608 -0.544 13.6 -0.456 c
+13.59 -0.36 13.586 -0.264 13.586 -0.177 c
+h
+22.677 -1.323 m
+22.391 -1.323 22.148 -1.282 21.943 -1.205 c
+21.737 -1.118 21.564 -0.996 21.428 -0.838 c
+21.288 -0.684 21.185 -0.497 21.119 -0.279 c
+21.049 -0.056 21.016 0.191 21.016 0.455 c
+21.016 0.75 21.049 1.007 21.119 1.234 c
+21.197 1.459 21.303 1.646 21.442 1.793 c
+21.589 1.947 21.766 2.065 21.972 2.146 c
+22.178 2.234 22.413 2.278 22.677 2.278 c
+22.901 2.278 23.104 2.248 23.28 2.19 c
+23.456 2.131 23.607 2.047 23.736 1.94 c
+23.861 1.841 23.963 1.72 24.044 1.573 c
+24.122 1.433 24.176 1.282 24.206 1.117 c
+23.295 1.072 l
+23.265 1.249 23.196 1.389 23.089 1.5 c
+22.99 1.606 22.846 1.66 22.662 1.66 c
+22.416 1.66 22.24 1.558 22.134 1.352 c
+22.023 1.153 21.972 0.867 21.972 0.484 c
+21.972 -0.309 22.207 -0.706 22.677 -0.706 c
+22.843 -0.706 22.986 -0.654 23.104 -0.544 c
+23.221 -0.437 23.295 -0.276 23.324 -0.059 c
+24.235 -0.103 l
+24.206 -0.272 24.151 -0.426 24.074 -0.574 c
+24.004 -0.721 23.901 -0.852 23.765 -0.97 c
+23.636 -1.081 23.478 -1.168 23.295 -1.235 c
+23.119 -1.294 22.913 -1.323 22.677 -1.323 c
+27.281 -0.647 m
+28.413 -0.647 l
+28.413 -1.264 l
+25.106 -1.264 l
+25.106 -0.647 l
+26.371 -0.647 l
+26.371 2.896 l
+25.444 2.896 l
+25.444 3.513 l
+27.281 3.513 l
+h
+32.445 0.484 m
+32.445 0.209 32.408 -0.04 32.342 -0.264 c
+32.272 -0.482 32.17 -0.669 32.033 -0.823 c
+31.894 -0.981 31.717 -1.103 31.504 -1.191 c
+31.287 -1.279 31.034 -1.323 30.74 -1.323 c
+30.464 -1.323 30.217 -1.279 30.005 -1.191 c
+29.799 -1.103 29.626 -0.981 29.49 -0.823 c
+29.35 -0.669 29.248 -0.482 29.182 -0.264 c
+29.112 -0.04 29.078 0.209 29.078 0.484 c
+29.078 0.738 29.108 0.974 29.167 1.19 c
+29.233 1.415 29.336 1.606 29.475 1.764 c
+29.612 1.929 29.788 2.057 30.005 2.146 c
+30.217 2.234 30.475 2.278 30.769 2.278 c
+31.081 2.278 31.343 2.234 31.548 2.146 c
+31.761 2.057 31.934 1.929 32.062 1.764 c
+32.199 1.606 32.297 1.415 32.357 1.19 c
+32.415 0.974 32.445 0.738 32.445 0.484 c
+31.489 0.484 m
+31.489 0.69 31.474 0.867 31.445 1.014 c
+31.424 1.161 31.387 1.282 31.328 1.382 c
+31.269 1.477 31.195 1.547 31.107 1.587 c
+31.019 1.635 30.909 1.66 30.784 1.66 c
+30.519 1.66 30.328 1.562 30.211 1.367 c
+30.093 1.18 30.034 0.885 30.034 0.484 c
+30.034 0.062 30.093 -0.243 30.211 -0.426 c
+30.328 -0.614 30.504 -0.706 30.74 -0.706 c
+30.865 -0.706 30.979 -0.688 31.077 -0.647 c
+31.173 -0.599 31.254 -0.526 31.313 -0.426 c
+31.379 -0.331 31.424 -0.206 31.445 -0.059 c
+31.474 0.088 31.489 0.268 31.489 0.484 c
+35.495 -1.264 m
+35.495 0.72 l
+35.495 1.022 35.451 1.242 35.362 1.382 c
+35.281 1.529 35.146 1.602 34.951 1.602 c
+34.84 1.602 34.738 1.577 34.643 1.529 c
+34.554 1.477 34.473 1.411 34.408 1.323 c
+34.348 1.234 34.297 1.124 34.26 0.999 c
+34.231 0.881 34.216 0.75 34.216 0.602 c
+34.216 -1.264 l
+33.305 -1.264 l
+33.305 1.44 l
+33.305 1.66 l
+33.305 1.749 33.297 1.826 33.29 1.896 c
+33.29 2.087 l
+33.29 2.219 l
+34.142 2.219 l
+34.15 2.19 34.157 2.146 34.157 2.087 c
+34.157 1.896 l
+34.165 1.826 34.172 1.756 34.172 1.691 c
+34.179 1.62 34.186 1.565 34.186 1.529 c
+34.202 1.529 l
+34.319 1.793 34.47 1.984 34.657 2.102 c
+34.84 2.219 35.061 2.278 35.318 2.278 c
+35.503 2.278 35.663 2.248 35.804 2.19 c
+35.939 2.131 36.054 2.043 36.141 1.926 c
+36.23 1.808 36.292 1.664 36.332 1.5 c
+36.38 1.341 36.406 1.153 36.406 0.941 c
+36.406 -1.264 l
+h
+38.923 -1.323 m
+38.666 -1.323 38.439 -1.286 38.233 -1.22 c
+38.027 -1.143 37.851 -1.029 37.703 -0.882 c
+37.556 -0.728 37.439 -0.536 37.35 -0.309 c
+37.269 -0.085 37.233 0.18 37.233 0.484 c
+37.233 0.816 37.277 1.095 37.365 1.323 c
+37.461 1.558 37.589 1.741 37.747 1.881 c
+37.913 2.017 38.1 2.117 38.306 2.175 c
+38.512 2.242 38.721 2.278 38.938 2.278 c
+39.21 2.278 39.445 2.227 39.644 2.131 c
+39.85 2.043 40.014 1.911 40.143 1.735 c
+40.28 1.565 40.378 1.359 40.438 1.117 c
+40.504 0.881 40.54 0.617 40.54 0.324 c
+40.54 0.309 l
+38.173 0.309 l
+38.173 0.162 38.188 0.022 38.218 -0.103 c
+38.254 -0.231 38.31 -0.345 38.379 -0.441 c
+38.445 -0.53 38.53 -0.599 38.63 -0.647 c
+38.725 -0.698 38.838 -0.721 38.967 -0.721 c
+39.122 -0.721 39.262 -0.688 39.379 -0.617 c
+39.504 -0.551 39.592 -0.449 39.644 -0.309 c
+40.482 -0.382 l
+40.452 -0.482 40.397 -0.588 40.32 -0.706 c
+40.239 -0.816 40.136 -0.919 40.012 -1.014 c
+39.894 -1.103 39.739 -1.176 39.555 -1.235 c
+39.379 -1.294 39.166 -1.323 38.923 -1.323 c
+38.923 1.705 m
+38.836 1.705 38.747 1.691 38.659 1.66 c
+38.57 1.631 38.489 1.58 38.424 1.514 c
+38.354 1.444 38.295 1.356 38.248 1.249 c
+38.207 1.139 38.188 1.014 38.188 0.867 c
+39.659 0.867 l
+39.659 1.003 39.632 1.124 39.584 1.234 c
+39.544 1.341 39.489 1.429 39.424 1.5 c
+39.364 1.565 39.291 1.617 39.202 1.646 c
+39.114 1.683 39.019 1.705 38.923 1.705 c
+46.236 -2.631 m
+46.236 3.513 l
+48.162 3.513 l
+48.162 2.896 l
+47.089 2.896 l
+47.089 -2.014 l
+48.162 -2.014 l
+48.162 -2.631 l
+h
+50.414 2.219 m
+50.422 2.198 50.429 2.165 50.429 2.117 c
+50.437 2.076 50.443 2.028 50.443 1.97 c
+50.451 1.918 50.458 1.866 50.458 1.808 c
+50.458 1.646 l
+50.473 1.646 l
+50.532 1.764 50.598 1.859 50.679 1.94 c
+50.756 2.017 50.84 2.08 50.929 2.131 c
+51.017 2.19 51.106 2.227 51.193 2.248 c
+51.289 2.267 51.388 2.278 51.488 2.278 c
+51.693 2.278 51.873 2.234 52.031 2.146 c
+52.186 2.057 52.315 1.929 52.413 1.764 c
+52.52 1.606 52.597 1.415 52.648 1.19 c
+52.708 0.974 52.737 0.738 52.737 0.484 c
+52.737 0.22 52.708 -0.026 52.648 -0.25 c
+52.597 -0.467 52.52 -0.658 52.413 -0.823 c
+52.315 -0.981 52.182 -1.103 52.016 -1.191 c
+51.858 -1.279 51.671 -1.323 51.458 -1.323 c
+51.359 -1.323 51.26 -1.312 51.164 -1.294 c
+51.065 -1.272 50.973 -1.242 50.885 -1.191 c
+50.804 -1.143 50.727 -1.081 50.649 -1 c
+50.58 -0.923 50.521 -0.831 50.473 -0.721 c
+50.458 -0.721 l
+50.458 -0.809 l
+50.466 -0.849 50.473 -0.897 50.473 -0.956 c
+50.473 -1.118 l
+50.473 -1.294 l
+50.473 -2.631 l
+49.562 -2.631 l
+49.562 1.455 l
+49.562 1.62 49.554 1.768 49.547 1.896 c
+49.547 2.219 l
+h
+50.458 0.455 m
+50.458 0.228 50.477 0.037 50.517 -0.118 c
+50.565 -0.264 50.62 -0.382 50.679 -0.47 c
+50.745 -0.559 50.819 -0.625 50.9 -0.661 c
+50.977 -0.702 51.054 -0.721 51.135 -0.721 c
+51.23 -0.721 51.318 -0.698 51.399 -0.647 c
+51.488 -0.599 51.553 -0.53 51.605 -0.441 c
+51.664 -0.345 51.708 -0.221 51.737 -0.073 c
+51.774 0.081 51.796 0.268 51.796 0.484 c
+51.796 0.875 51.737 1.168 51.619 1.367 c
+51.509 1.562 51.355 1.66 51.149 1.66 c
+51.068 1.66 50.991 1.639 50.914 1.602 c
+50.833 1.562 50.759 1.5 50.694 1.411 c
+50.624 1.323 50.565 1.198 50.517 1.043 c
+50.477 0.885 50.458 0.69 50.458 0.455 c
+56.625 1.469 m
+56.525 1.477 56.423 1.488 56.316 1.5 c
+56.205 1.517 56.084 1.529 55.949 1.529 c
+55.772 1.529 55.614 1.488 55.478 1.411 c
+55.339 1.341 55.22 1.242 55.125 1.117 c
+55.037 0.989 54.967 0.841 54.919 0.676 c
+54.879 0.507 54.861 0.33 54.861 0.147 c
+54.861 -1.264 l
+53.965 -1.264 l
+53.965 0.985 l
+53.965 1.11 53.953 1.234 53.934 1.352 c
+53.924 1.477 53.909 1.595 53.89 1.705 c
+53.88 1.822 53.865 1.918 53.847 1.999 c
+53.824 2.087 53.807 2.161 53.788 2.219 c
+54.67 2.219 l
+54.677 2.168 54.688 2.117 54.699 2.057 c
+54.717 1.999 54.732 1.933 54.743 1.866 c
+54.761 1.808 54.776 1.741 54.788 1.675 c
+54.794 1.606 54.806 1.543 54.817 1.484 c
+54.831 1.484 l
+54.869 1.602 54.919 1.708 54.979 1.808 c
+55.045 1.903 55.125 1.988 55.214 2.057 c
+55.301 2.124 55.405 2.179 55.522 2.219 c
+55.648 2.256 55.794 2.278 55.964 2.278 c
+56.088 2.278 56.205 2.271 56.316 2.263 c
+56.434 2.252 56.537 2.238 56.625 2.219 c
+h
+60.876 0.484 m
+60.876 0.209 60.839 -0.04 60.774 -0.264 c
+60.704 -0.482 60.601 -0.669 60.465 -0.823 c
+60.325 -0.981 60.149 -1.103 59.935 -1.191 c
+59.719 -1.279 59.465 -1.323 59.172 -1.323 c
+58.896 -1.323 58.649 -1.279 58.436 -1.191 c
+58.231 -1.103 58.058 -0.981 57.922 -0.823 c
+57.782 -0.669 57.68 -0.482 57.613 -0.264 c
+57.543 -0.04 57.51 0.209 57.51 0.484 c
+57.51 0.738 57.539 0.974 57.599 1.19 c
+57.665 1.415 57.768 1.606 57.907 1.764 c
+58.043 1.929 58.22 2.057 58.436 2.146 c
+58.649 2.234 58.906 2.278 59.201 2.278 c
+59.513 2.278 59.774 2.234 59.98 2.146 c
+60.193 2.057 60.365 1.929 60.494 1.764 c
+60.63 1.606 60.729 1.415 60.788 1.19 c
+60.847 0.974 60.876 0.738 60.876 0.484 c
+59.921 0.484 m
+59.921 0.69 59.906 0.867 59.877 1.014 c
+59.855 1.161 59.818 1.282 59.76 1.382 c
+59.7 1.477 59.627 1.547 59.538 1.587 c
+59.451 1.635 59.34 1.66 59.216 1.66 c
+58.95 1.66 58.76 1.562 58.642 1.367 c
+58.524 1.18 58.466 0.885 58.466 0.484 c
+58.466 0.062 58.524 -0.243 58.642 -0.426 c
+58.76 -0.614 58.936 -0.706 59.172 -0.706 c
+59.297 -0.706 59.411 -0.688 59.509 -0.647 c
+59.605 -0.599 59.686 -0.526 59.744 -0.426 c
+59.81 -0.331 59.855 -0.206 59.877 -0.059 c
+59.906 0.088 59.921 0.268 59.921 0.484 c
+64.055 -1.309 m
+64.055 -1.544 64.011 -1.742 63.922 -1.911 c
+63.842 -2.076 63.735 -2.213 63.6 -2.323 c
+63.459 -2.429 63.305 -2.506 63.129 -2.558 c
+62.952 -2.606 62.769 -2.631 62.586 -2.631 c
+62.497 -2.631 62.409 -2.624 62.32 -2.616 c
+62.233 -2.606 62.144 -2.595 62.056 -2.587 c
+61.975 -2.576 61.902 -2.562 61.836 -2.543 c
+61.766 -2.532 61.707 -2.517 61.659 -2.499 c
+61.659 -1.823 l
+61.747 -1.841 61.865 -1.86 62.012 -1.881 c
+62.159 -1.911 62.32 -1.926 62.497 -1.926 c
+62.592 -1.926 62.681 -1.914 62.761 -1.897 c
+62.839 -1.874 62.908 -1.841 62.967 -1.793 c
+63.026 -1.742 63.07 -1.669 63.1 -1.573 c
+63.129 -1.484 63.143 -1.371 63.143 -1.235 c
+63.143 1.602 l
+62.012 1.602 l
+62.012 2.219 l
+64.055 2.219 l
+h
+63.158 3.513 0.897 -0.676 re
+63.158 2.836 m
+67.351 -1.323 m
+67.094 -1.323 66.866 -1.286 66.661 -1.22 c
+66.455 -1.143 66.278 -1.029 66.131 -0.882 c
+65.984 -0.728 65.867 -0.536 65.778 -0.309 c
+65.697 -0.085 65.661 0.18 65.661 0.484 c
+65.661 0.816 65.705 1.095 65.793 1.323 c
+65.888 1.558 66.017 1.741 66.175 1.881 c
+66.341 2.017 66.528 2.117 66.734 2.175 c
+66.94 2.242 67.149 2.278 67.366 2.278 c
+67.638 2.278 67.873 2.227 68.072 2.131 c
+68.277 2.043 68.443 1.911 68.571 1.735 c
+68.707 1.565 68.807 1.359 68.865 1.117 c
+68.932 0.881 68.968 0.617 68.968 0.324 c
+68.968 0.309 l
+66.602 0.309 l
+66.602 0.162 66.617 0.022 66.646 -0.103 c
+66.682 -0.231 66.738 -0.345 66.808 -0.441 c
+66.873 -0.53 66.958 -0.599 67.058 -0.647 c
+67.153 -0.698 67.267 -0.721 67.396 -0.721 c
+67.55 -0.721 67.689 -0.688 67.807 -0.617 c
+67.932 -0.551 68.02 -0.449 68.072 -0.309 c
+68.909 -0.382 l
+68.88 -0.482 68.824 -0.588 68.747 -0.706 c
+68.666 -0.816 68.564 -0.919 68.439 -1.014 c
+68.321 -1.103 68.167 -1.176 67.983 -1.235 c
+67.807 -1.294 67.594 -1.323 67.351 -1.323 c
+67.351 1.705 m
+67.263 1.705 67.175 1.691 67.087 1.66 c
+66.999 1.631 66.918 1.58 66.852 1.514 c
+66.782 1.444 66.723 1.356 66.675 1.249 c
+66.634 1.139 66.617 1.014 66.617 0.867 c
+68.086 0.867 l
+68.086 1.003 68.061 1.124 68.013 1.234 c
+67.972 1.341 67.918 1.429 67.851 1.5 c
+67.792 1.565 67.719 1.617 67.631 1.646 c
+67.542 1.683 67.447 1.705 67.351 1.705 c
+71.412 -1.323 m
+71.126 -1.323 70.883 -1.282 70.677 -1.205 c
+70.471 -1.118 70.299 -0.996 70.162 -0.838 c
+70.023 -0.684 69.92 -0.497 69.854 -0.279 c
+69.784 -0.056 69.751 0.191 69.751 0.455 c
+69.751 0.75 69.784 1.007 69.854 1.234 c
+69.931 1.459 70.037 1.646 70.177 1.793 c
+70.324 1.947 70.501 2.065 70.706 2.146 c
+70.912 2.234 71.147 2.278 71.412 2.278 c
+71.636 2.278 71.839 2.248 72.015 2.19 c
+72.191 2.131 72.342 2.047 72.47 1.94 c
+72.595 1.841 72.698 1.72 72.779 1.573 c
+72.856 1.433 72.911 1.282 72.94 1.117 c
+72.03 1.072 l
+71.999 1.249 71.93 1.389 71.824 1.5 c
+71.724 1.606 71.581 1.66 71.397 1.66 c
+71.151 1.66 70.975 1.558 70.868 1.352 c
+70.758 1.153 70.706 0.867 70.706 0.484 c
+70.706 -0.309 70.941 -0.706 71.412 -0.706 c
+71.577 -0.706 71.721 -0.654 71.839 -0.544 c
+71.956 -0.437 72.03 -0.276 72.059 -0.059 c
+72.97 -0.103 l
+72.94 -0.272 72.886 -0.426 72.809 -0.574 c
+72.739 -0.721 72.635 -0.852 72.5 -0.97 c
+72.371 -1.081 72.213 -1.168 72.03 -1.235 c
+71.853 -1.294 71.647 -1.323 71.412 -1.323 c
+74.521 1.602 m
+73.977 1.602 l
+73.977 2.219 l
+74.565 2.219 l
+74.844 3.116 l
+75.417 3.116 l
+75.417 2.219 l
+76.652 2.219 l
+76.652 1.602 l
+75.417 1.602 l
+75.417 -0.103 l
+75.417 -0.324 l
+75.425 -0.393 75.446 -0.456 75.476 -0.515 c
+75.513 -0.566 75.568 -0.611 75.638 -0.647 c
+75.715 -0.676 75.829 -0.691 75.976 -0.691 c
+76.112 -0.691 76.248 -0.688 76.387 -0.676 c
+76.523 -0.658 76.656 -0.632 76.784 -0.603 c
+76.784 -1.205 l
+76.703 -1.216 76.626 -1.231 76.549 -1.249 c
+76.468 -1.261 76.391 -1.268 76.314 -1.279 c
+76.233 -1.286 76.145 -1.294 76.049 -1.294 c
+75.961 -1.301 75.862 -1.309 75.756 -1.309 c
+75.568 -1.309 75.407 -1.294 75.27 -1.264 c
+75.142 -1.228 75.028 -1.183 74.933 -1.132 c
+74.844 -1.085 74.771 -1.025 74.712 -0.956 c
+74.653 -0.879 74.609 -0.802 74.58 -0.721 c
+74.55 -0.632 74.528 -0.544 74.521 -0.456 c
+74.509 -0.36 74.506 -0.264 74.506 -0.177 c
+h
+82.921 2.219 m
+82.921 0.264 l
+82.921 0.125 82.929 0 82.951 -0.118 c
+82.969 -0.228 83.002 -0.32 83.053 -0.397 c
+83.101 -0.478 83.16 -0.54 83.23 -0.588 c
+83.296 -0.628 83.381 -0.647 83.48 -0.647 c
+83.568 -0.647 83.649 -0.628 83.73 -0.588 c
+83.818 -0.54 83.891 -0.47 83.951 -0.382 c
+84.009 -0.287 84.053 -0.177 84.082 -0.059 c
+84.119 0.066 84.142 0.206 84.142 0.353 c
+84.142 2.219 l
+85.038 2.219 l
+85.038 -0.485 l
+85.038 -0.721 l
+85.046 -0.802 85.052 -0.879 85.052 -0.956 c
+85.052 -1.147 l
+85.06 -1.199 85.067 -1.235 85.067 -1.264 c
+84.215 -1.264 l
+84.204 -1.235 84.192 -1.199 84.186 -1.147 c
+84.186 -0.956 l
+84.186 -0.889 84.178 -0.819 84.171 -0.75 c
+84.171 -0.574 l
+84.156 -0.574 l
+84.038 -0.838 83.884 -1.029 83.7 -1.147 c
+83.524 -1.264 83.322 -1.323 83.097 -1.323 c
+82.892 -1.323 82.719 -1.286 82.583 -1.22 c
+82.444 -1.154 82.334 -1.058 82.245 -0.941 c
+82.164 -0.823 82.106 -0.688 82.069 -0.53 c
+82.039 -0.364 82.025 -0.187 82.025 0 c
+82.025 2.219 l
+h
+89.113 1.469 m
+89.014 1.477 88.911 1.488 88.805 1.5 c
+88.695 1.517 88.573 1.529 88.437 1.529 c
+88.261 1.529 88.103 1.488 87.967 1.411 c
+87.827 1.341 87.71 1.242 87.614 1.117 c
+87.525 0.989 87.456 0.841 87.408 0.676 c
+87.367 0.507 87.35 0.33 87.35 0.147 c
+87.35 -1.264 l
+86.453 -1.264 l
+86.453 0.985 l
+86.453 1.11 86.442 1.234 86.423 1.352 c
+86.413 1.477 86.398 1.595 86.38 1.705 c
+86.368 1.822 86.353 1.918 86.335 1.999 c
+86.313 2.087 86.295 2.161 86.276 2.219 c
+87.159 2.219 l
+87.166 2.168 87.176 2.117 87.188 2.057 c
+87.206 1.999 87.221 1.933 87.232 1.866 c
+87.25 1.808 87.265 1.741 87.276 1.675 c
+87.284 1.606 87.294 1.543 87.305 1.484 c
+87.32 1.484 l
+87.357 1.602 87.408 1.708 87.467 1.808 c
+87.533 1.903 87.614 1.988 87.702 2.057 c
+87.791 2.124 87.893 2.179 88.011 2.219 c
+88.136 2.256 88.283 2.278 88.452 2.278 c
+88.577 2.278 88.695 2.271 88.805 2.263 c
+88.922 2.252 89.025 2.238 89.113 2.219 c
+h
+92.263 -0.647 m
+93.395 -0.647 l
+93.395 -1.264 l
+90.087 -1.264 l
+90.087 -0.647 l
+91.351 -0.647 l
+91.351 2.896 l
+90.425 2.896 l
+90.425 3.513 l
+92.263 3.513 l
+h
+94.592 -2.631 m
+94.592 -2.014 l
+95.666 -2.014 l
+95.666 2.896 l
+94.592 2.896 l
+94.592 3.513 l
+96.518 3.513 l
+96.518 -2.631 l
+h
+f
+Q
+q 1 0 0 1 65.7934 208.1152 cm
+0 0 m
+0 5.35 l
+1.278 5.35 l
+1.904 5.35 2.389 5.152 2.734 4.762 c
+3.076 4.369 3.248 3.821 3.248 3.116 c
+3.248 2.219 l
+3.248 1.514 3.072 0.962 2.72 0.573 c
+2.374 0.191 1.87 0 1.205 0 c
+h
+0.676 4.777 m
+0.676 0.573 l
+1.22 0.573 l
+1.691 0.573 2.032 0.709 2.249 0.985 c
+2.473 1.257 2.587 1.661 2.587 2.19 c
+2.587 3.131 l
+2.587 3.697 2.477 4.116 2.263 4.38 c
+2.047 4.644 1.72 4.777 1.278 4.777 c
+h
+4.072 2.175 m
+4.072 2.753 4.208 3.208 4.484 3.543 c
+4.767 3.884 5.137 4.056 5.6 4.056 c
+6.059 4.056 6.427 3.888 6.703 3.557 c
+6.986 3.233 7.133 2.786 7.144 2.219 c
+7.144 1.793 l
+7.144 1.224 7 0.768 6.718 0.426 c
+6.442 0.092 6.074 -0.073 5.615 -0.073 c
+5.152 -0.073 4.781 0.088 4.498 0.411 c
+4.222 0.742 4.079 1.183 4.072 1.735 c
+h
+4.719 1.793 m
+4.719 1.389 4.796 1.073 4.954 0.838 c
+5.119 0.603 5.34 0.485 5.615 0.485 c
+6.181 0.485 6.475 0.897 6.497 1.72 c
+6.497 2.175 l
+6.497 2.576 6.413 2.896 6.247 3.131 c
+6.089 3.373 5.872 3.499 5.6 3.499 c
+5.336 3.499 5.119 3.373 4.954 3.131 c
+4.796 2.896 4.719 2.576 4.719 2.175 c
+h
+10.951 1.147 m
+11.553 3.983 l
+12.2 3.983 l
+11.215 0 l
+10.701 0 l
+9.922 2.851 l
+9.172 0 l
+8.644 0 l
+7.688 3.983 l
+8.32 3.983 l
+8.937 1.22 l
+9.672 3.983 l
+10.186 3.983 l
+h
+13.494 3.983 m
+13.508 3.543 l
+13.762 3.884 14.086 4.056 14.479 4.056 c
+15.184 4.056 15.541 3.586 15.551 2.645 c
+15.551 0 l
+14.905 0 l
+14.905 2.616 l
+14.905 2.929 14.85 3.15 14.743 3.278 c
+14.633 3.403 14.479 3.469 14.273 3.469 c
+14.115 3.469 13.968 3.414 13.832 3.308 c
+13.704 3.197 13.6 3.061 13.523 2.896 c
+13.523 0 l
+12.877 0 l
+12.877 3.983 l
+h
+17.228 0 -0.647 5.644 re
+18.109 2.175 m
+18.109 2.753 18.246 3.208 18.521 3.543 c
+18.803 3.884 19.175 4.056 19.638 4.056 c
+20.097 4.056 20.465 3.888 20.74 3.557 c
+21.024 3.233 21.17 2.786 21.182 2.219 c
+21.182 1.793 l
+21.182 1.224 21.038 0.768 20.756 0.426 c
+20.48 0.092 20.112 -0.073 19.653 -0.073 c
+19.19 -0.073 18.819 0.088 18.535 0.411 c
+18.26 0.742 18.117 1.183 18.109 1.735 c
+h
+18.756 1.793 m
+18.756 1.389 18.834 1.073 18.992 0.838 c
+19.156 0.603 19.377 0.485 19.653 0.485 c
+20.218 0.485 20.513 0.897 20.534 1.72 c
+20.534 2.175 l
+20.534 2.576 20.45 2.896 20.285 3.131 c
+20.127 3.373 19.91 3.499 19.638 3.499 c
+19.374 3.499 19.156 3.373 18.992 3.131 c
+18.834 2.896 18.756 2.576 18.756 2.175 c
+h
+24.062 0 m
+24.022 0.088 23.996 0.235 23.989 0.441 c
+23.754 0.096 23.46 -0.073 23.107 -0.073 c
+22.743 -0.073 22.46 0.022 22.254 0.22 c
+22.056 0.426 21.961 0.713 21.961 1.088 c
+21.961 1.488 22.096 1.808 22.372 2.043 c
+22.644 2.286 23.019 2.41 23.489 2.41 c
+23.974 2.41 l
+23.974 2.837 l
+23.974 3.072 23.919 3.237 23.813 3.337 c
+23.702 3.443 23.541 3.499 23.328 3.499 c
+23.129 3.499 22.967 3.439 22.842 3.322 c
+22.725 3.204 22.666 3.057 22.666 2.881 c
+22.019 2.881 l
+22.019 3.075 22.078 3.267 22.196 3.454 c
+22.321 3.638 22.483 3.785 22.68 3.896 c
+22.886 4.002 23.114 4.056 23.372 4.056 c
+23.772 4.056 24.077 3.954 24.283 3.748 c
+24.496 3.543 24.61 3.248 24.621 2.866 c
+24.621 0.852 l
+24.621 0.548 24.658 0.283 24.739 0.058 c
+24.739 0 l
+h
+23.195 0.515 m
+23.36 0.515 23.511 0.559 23.651 0.646 c
+23.798 0.735 23.904 0.845 23.974 0.985 c
+23.974 1.926 l
+23.607 1.926 l
+23.291 1.926 23.048 1.856 22.872 1.72 c
+22.695 1.591 22.607 1.404 22.607 1.161 c
+22.607 0.933 22.651 0.768 22.74 0.661 c
+22.828 0.563 22.979 0.515 23.195 0.515 c
+25.488 2.175 m
+25.488 2.782 25.598 3.248 25.826 3.572 c
+26.061 3.896 26.389 4.056 26.811 4.056 c
+27.193 4.056 27.491 3.898 27.708 3.586 c
+27.708 5.644 l
+28.355 5.644 l
+28.355 0 l
+27.767 0 l
+27.723 0.426 l
+27.517 0.092 27.212 -0.073 26.811 -0.073 c
+26.4 -0.073 26.076 0.081 25.841 0.397 c
+25.606 0.721 25.488 1.176 25.488 1.764 c
+h
+26.135 1.793 m
+26.135 1.352 26.198 1.022 26.326 0.808 c
+26.462 0.603 26.682 0.5 26.988 0.5 c
+27.311 0.5 27.55 0.661 27.708 0.985 c
+27.708 2.998 l
+27.539 3.31 27.3 3.469 26.988 3.469 c
+26.682 3.469 26.462 3.366 26.326 3.16 c
+26.198 2.955 26.135 2.631 26.135 2.19 c
+h
+31.295 1.014 m
+31.295 1.161 31.239 1.282 31.133 1.382 c
+31.023 1.477 30.817 1.595 30.516 1.735 c
+30.17 1.881 29.928 2.003 29.78 2.102 c
+29.633 2.209 29.523 2.326 29.457 2.454 c
+29.387 2.58 29.354 2.738 29.354 2.925 c
+29.354 3.248 29.471 3.516 29.707 3.734 c
+29.942 3.946 30.244 4.056 30.618 4.056 c
+31 4.056 31.309 3.943 31.544 3.719 c
+31.779 3.491 31.897 3.204 31.897 2.851 c
+31.25 2.851 l
+31.25 3.028 31.191 3.179 31.074 3.308 c
+30.956 3.432 30.802 3.499 30.618 3.499 c
+30.42 3.499 30.269 3.443 30.163 3.337 c
+30.052 3.237 30.001 3.105 30.001 2.94 c
+30.001 2.811 30.038 2.705 30.119 2.616 c
+30.196 2.535 30.387 2.433 30.692 2.308 c
+31.17 2.12 31.5 1.933 31.677 1.749 c
+31.852 1.573 31.941 1.345 31.941 1.073 c
+31.941 0.721 31.816 0.441 31.574 0.235 c
+31.339 0.029 31.023 -0.073 30.633 -0.073 c
+30.21 -0.073 29.872 0.044 29.618 0.279 c
+29.361 0.522 29.236 0.827 29.236 1.191 c
+29.884 1.191 l
+29.891 0.962 29.961 0.786 30.089 0.661 c
+30.214 0.544 30.398 0.485 30.633 0.485 c
+30.846 0.485 31.008 0.532 31.118 0.632 c
+31.235 0.727 31.295 0.856 31.295 1.014 c
+36.542 0 m
+36.502 0.088 36.476 0.235 36.469 0.441 c
+36.234 0.096 35.939 -0.073 35.586 -0.073 c
+35.222 -0.073 34.94 0.022 34.734 0.22 c
+34.535 0.426 34.44 0.713 34.44 1.088 c
+34.44 1.488 34.576 1.808 34.852 2.043 c
+35.123 2.286 35.498 2.41 35.968 2.41 c
+36.454 2.41 l
+36.454 2.837 l
+36.454 3.072 36.398 3.237 36.292 3.337 c
+36.182 3.443 36.02 3.499 35.807 3.499 c
+35.609 3.499 35.447 3.439 35.322 3.322 c
+35.204 3.204 35.145 3.057 35.145 2.881 c
+34.499 2.881 l
+34.499 3.075 34.557 3.267 34.675 3.454 c
+34.8 3.638 34.962 3.785 35.16 3.896 c
+35.366 4.002 35.594 4.056 35.851 4.056 c
+36.251 4.056 36.556 3.954 36.762 3.748 c
+36.976 3.543 37.09 3.248 37.101 2.866 c
+37.101 0.852 l
+37.101 0.548 37.138 0.283 37.218 0.058 c
+37.218 0 l
+h
+35.675 0.515 m
+35.84 0.515 35.991 0.559 36.13 0.646 c
+36.278 0.735 36.384 0.845 36.454 0.985 c
+36.454 1.926 l
+36.086 1.926 l
+35.771 1.926 35.528 1.856 35.351 1.72 c
+35.175 1.591 35.087 1.404 35.087 1.161 c
+35.087 0.933 35.131 0.768 35.219 0.661 c
+35.307 0.563 35.457 0.515 35.675 0.515 c
+42.701 1.793 m
+42.701 1.165 42.584 0.694 42.348 0.382 c
+42.121 0.077 41.805 -0.073 41.393 -0.073 c
+40.988 -0.073 40.679 0.077 40.467 0.382 c
+40.467 -1.529 l
+39.82 -1.529 l
+39.82 3.983 l
+40.408 3.983 l
+40.452 3.543 l
+40.665 3.884 40.974 4.056 41.377 4.056 c
+41.819 4.056 42.146 3.902 42.362 3.601 c
+42.576 3.296 42.69 2.84 42.701 2.234 c
+h
+42.054 2.175 m
+42.054 2.616 41.984 2.94 41.848 3.146 c
+41.709 3.358 41.488 3.469 41.187 3.469 c
+40.87 3.469 40.631 3.314 40.467 3.013 c
+40.467 0.941 l
+40.631 0.636 40.87 0.485 41.187 0.485 c
+41.481 0.485 41.694 0.588 41.834 0.794 c
+41.969 1.007 42.043 1.338 42.054 1.779 c
+h
+45.185 3.366 m
+45.097 3.385 44.997 3.395 44.891 3.395 c
+44.556 3.395 44.321 3.212 44.186 2.851 c
+44.186 0 l
+43.538 0 l
+43.538 3.983 l
+44.171 3.983 l
+44.186 3.572 l
+44.362 3.896 44.604 4.056 44.92 4.056 c
+45.027 4.056 45.115 4.035 45.185 3.998 c
+h
+45.626 2.175 m
+45.626 2.753 45.762 3.208 46.038 3.543 c
+46.32 3.884 46.692 4.056 47.155 4.056 c
+47.614 4.056 47.981 3.888 48.257 3.557 c
+48.54 3.233 48.687 2.786 48.698 2.219 c
+48.698 1.793 l
+48.698 1.224 48.554 0.768 48.272 0.426 c
+47.997 0.092 47.629 -0.073 47.17 -0.073 c
+46.707 -0.073 46.335 0.088 46.052 0.411 c
+45.776 0.742 45.633 1.183 45.626 1.735 c
+h
+46.273 1.793 m
+46.273 1.389 46.35 1.073 46.508 0.838 c
+46.673 0.603 46.894 0.485 47.17 0.485 c
+47.735 0.485 48.029 0.897 48.051 1.72 c
+48.051 2.175 l
+48.051 2.576 47.966 2.896 47.802 3.131 c
+47.644 3.373 47.426 3.499 47.155 3.499 c
+46.89 3.499 46.673 3.373 46.508 3.131 c
+46.35 2.896 46.273 2.576 46.273 2.175 c
+h
+50.197 3.983 m
+50.197 -0.5 l
+50.197 -1.235 49.907 -1.602 49.33 -1.602 c
+49.19 -1.602 49.069 -1.58 48.963 -1.544 c
+48.963 -1 l
+49.032 -1.018 49.117 -1.029 49.227 -1.029 c
+49.333 -1.029 49.411 -0.985 49.462 -0.897 c
+49.521 -0.816 49.551 -0.676 49.551 -0.47 c
+49.551 3.983 l
+h
+50.227 5.027 m
+50.227 4.917 50.197 4.825 50.139 4.748 c
+50.079 4.678 49.984 4.644 49.859 4.644 c
+49.742 4.644 49.647 4.678 49.58 4.748 c
+49.521 4.825 49.491 4.917 49.491 5.027 c
+49.491 5.145 49.521 5.236 49.58 5.307 c
+49.647 5.384 49.742 5.424 49.859 5.424 c
+49.984 5.424 50.079 5.384 50.139 5.307 c
+50.197 5.226 50.227 5.134 50.227 5.027 c
+52.652 -0.073 m
+52.153 -0.073 51.77 0.073 51.505 0.368 c
+51.241 0.661 51.108 1.095 51.108 1.675 c
+51.108 2.146 l
+51.108 2.741 51.234 3.208 51.49 3.543 c
+51.756 3.884 52.116 4.056 52.579 4.056 c
+53.038 4.056 53.379 3.902 53.607 3.601 c
+53.842 3.308 53.964 2.844 53.975 2.219 c
+53.975 1.793 l
+51.756 1.793 l
+51.756 1.705 l
+51.756 1.272 51.833 0.959 51.991 0.764 c
+52.156 0.577 52.388 0.485 52.681 0.485 c
+52.876 0.485 53.049 0.518 53.196 0.588 c
+53.343 0.665 53.479 0.783 53.607 0.941 c
+53.946 0.529 l
+53.659 0.125 53.229 -0.073 52.652 -0.073 c
+52.579 3.499 m
+52.303 3.499 52.101 3.403 51.976 3.219 c
+51.847 3.032 51.774 2.741 51.756 2.352 c
+53.329 2.352 l
+53.329 2.44 l
+53.306 2.822 53.24 3.09 53.123 3.248 c
+53.005 3.414 52.822 3.499 52.579 3.499 c
+56.136 0.485 m
+56.349 0.485 56.521 0.548 56.65 0.676 c
+56.786 0.812 56.859 1.003 56.871 1.249 c
+57.488 1.249 l
+57.466 0.867 57.33 0.548 57.077 0.294 c
+56.82 0.048 56.507 -0.073 56.136 -0.073 c
+55.644 -0.073 55.268 0.077 55.004 0.382 c
+54.746 0.694 54.622 1.161 54.622 1.779 c
+54.622 2.219 l
+54.622 2.815 54.746 3.271 55.004 3.586 c
+55.268 3.898 55.644 4.056 56.136 4.056 c
+56.537 4.056 56.856 3.925 57.092 3.66 c
+57.333 3.403 57.466 3.057 57.488 2.616 c
+56.871 2.616 l
+56.849 2.911 56.775 3.131 56.65 3.278 c
+56.533 3.425 56.36 3.499 56.136 3.499 c
+55.841 3.499 55.625 3.399 55.489 3.204 c
+55.349 3.017 55.276 2.708 55.268 2.278 c
+55.268 1.764 l
+55.268 1.294 55.334 0.959 55.474 0.764 c
+55.621 0.577 55.841 0.485 56.136 0.485 c
+59.091 4.939 m
+59.091 3.983 l
+59.693 3.983 l
+59.693 3.454 l
+59.091 3.454 l
+59.091 0.985 l
+59.091 0.827 59.112 0.709 59.164 0.632 c
+59.222 0.551 59.311 0.515 59.428 0.515 c
+59.517 0.515 59.604 0.529 59.693 0.559 c
+59.693 0 l
+59.546 -0.048 59.392 -0.073 59.237 -0.073 c
+58.98 -0.073 58.785 0.018 58.649 0.206 c
+58.509 0.389 58.443 0.65 58.443 0.985 c
+58.443 3.454 l
+57.84 3.454 l
+57.84 3.983 l
+58.443 3.983 l
+58.443 4.939 l
+h
+65.146 1.147 m
+65.749 3.983 l
+66.396 3.983 l
+65.411 0 l
+64.896 0 l
+64.117 2.851 l
+63.367 0 l
+62.839 0 l
+61.883 3.983 l
+62.515 3.983 l
+63.132 1.22 l
+63.868 3.983 l
+64.382 3.983 l
+h
+67.777 0 -0.647 3.983 re
+67.822 5.027 m
+67.822 4.917 67.792 4.825 67.733 4.748 c
+67.675 4.678 67.579 4.644 67.454 4.644 c
+67.336 4.644 67.241 4.678 67.174 4.748 c
+67.116 4.825 67.087 4.917 67.087 5.027 c
+67.087 5.145 67.116 5.236 67.174 5.307 c
+67.241 5.384 67.336 5.424 67.454 5.424 c
+67.579 5.424 67.675 5.384 67.733 5.307 c
+67.792 5.226 67.822 5.134 67.822 5.027 c
+69.644 4.939 m
+69.644 3.983 l
+70.247 3.983 l
+70.247 3.454 l
+69.644 3.454 l
+69.644 0.985 l
+69.644 0.827 69.666 0.709 69.717 0.632 c
+69.777 0.551 69.865 0.515 69.983 0.515 c
+70.07 0.515 70.158 0.529 70.247 0.559 c
+70.247 0 l
+70.1 -0.048 69.946 -0.073 69.792 -0.073 c
+69.534 -0.073 69.339 0.018 69.204 0.206 c
+69.063 0.389 68.998 0.65 68.998 0.985 c
+68.998 3.454 l
+68.395 3.454 l
+68.395 3.983 l
+68.998 3.983 l
+68.998 4.939 l
+h
+71.658 3.572 m
+71.911 3.896 72.231 4.056 72.614 4.056 c
+73.319 4.056 73.676 3.586 73.686 2.645 c
+73.686 0 l
+73.04 0 l
+73.04 2.616 l
+73.04 2.929 72.984 3.15 72.878 3.278 c
+72.768 3.403 72.614 3.469 72.408 3.469 c
+72.25 3.469 72.103 3.414 71.967 3.308 c
+71.838 3.197 71.735 3.061 71.658 2.896 c
+71.658 0 l
+71.011 0 l
+71.011 5.644 l
+71.658 5.644 l
+h
+77.788 -0.073 m
+77.287 -0.073 76.905 0.073 76.641 0.368 c
+76.377 0.661 76.244 1.095 76.244 1.675 c
+76.244 2.146 l
+76.244 2.741 76.369 3.208 76.626 3.543 c
+76.89 3.884 77.251 4.056 77.714 4.056 c
+78.174 4.056 78.515 3.902 78.743 3.601 c
+78.978 3.308 79.099 2.844 79.111 2.219 c
+79.111 1.793 l
+76.89 1.793 l
+76.89 1.705 l
+76.89 1.272 76.968 0.959 77.126 0.764 c
+77.291 0.577 77.523 0.485 77.817 0.485 c
+78.012 0.485 78.184 0.518 78.332 0.588 c
+78.478 0.665 78.615 0.783 78.743 0.941 c
+79.081 0.529 l
+78.794 0.125 78.365 -0.073 77.788 -0.073 c
+77.714 3.499 m
+77.439 3.499 77.237 3.403 77.111 3.219 c
+76.983 3.032 76.909 2.741 76.89 2.352 c
+78.463 2.352 l
+78.463 2.44 l
+78.442 2.822 78.376 3.09 78.258 3.248 c
+78.141 3.414 77.956 3.499 77.714 3.499 c
+80.507 3.983 m
+80.522 3.543 l
+80.775 3.884 81.098 4.056 81.492 4.056 c
+82.197 4.056 82.554 3.586 82.565 2.645 c
+82.565 0 l
+81.918 0 l
+81.918 2.616 l
+81.918 2.929 81.863 3.15 81.756 3.278 c
+81.646 3.403 81.492 3.469 81.286 3.469 c
+81.127 3.469 80.981 3.414 80.845 3.308 c
+80.716 3.197 80.613 3.061 80.536 2.896 c
+80.536 0 l
+79.889 0 l
+79.889 3.983 l
+h
+84.387 4.939 m
+84.387 3.983 l
+84.99 3.983 l
+84.99 3.454 l
+84.387 3.454 l
+84.387 0.985 l
+84.387 0.827 84.41 0.709 84.461 0.632 c
+84.52 0.551 84.608 0.515 84.726 0.515 c
+84.813 0.515 84.902 0.529 84.99 0.559 c
+84.99 0 l
+84.843 -0.048 84.689 -0.073 84.534 -0.073 c
+84.277 -0.073 84.082 0.018 83.946 0.206 c
+83.807 0.389 83.741 0.65 83.741 0.985 c
+83.741 3.454 l
+83.138 3.454 l
+83.138 3.983 l
+83.741 3.983 l
+83.741 4.939 l
+h
+86.46 0 -0.646 3.983 re
+86.504 5.027 m
+86.504 4.917 86.475 4.825 86.415 4.748 c
+86.357 4.678 86.261 4.644 86.137 4.644 c
+86.019 4.644 85.923 4.678 85.858 4.748 c
+85.798 4.825 85.769 4.917 85.769 5.027 c
+85.769 5.145 85.798 5.236 85.858 5.307 c
+85.923 5.384 86.019 5.424 86.137 5.424 c
+86.261 5.424 86.357 5.384 86.415 5.307 c
+86.475 5.226 86.504 5.134 86.504 5.027 c
+89.12 3.366 m
+89.033 3.385 88.933 3.395 88.826 3.395 c
+88.493 3.395 88.257 3.212 88.121 2.851 c
+88.121 0 l
+87.474 0 l
+87.474 3.983 l
+88.106 3.983 l
+88.121 3.572 l
+88.297 3.896 88.54 4.056 88.856 4.056 c
+88.963 4.056 89.05 4.035 89.12 3.998 c
+h
+91.119 -0.073 m
+90.62 -0.073 90.238 0.073 89.973 0.368 c
+89.708 0.661 89.576 1.095 89.576 1.675 c
+89.576 2.146 l
+89.576 2.741 89.701 3.208 89.958 3.543 c
+90.223 3.884 90.583 4.056 91.046 4.056 c
+91.506 4.056 91.847 3.902 92.075 3.601 c
+92.31 3.308 92.431 2.844 92.443 2.219 c
+92.443 1.793 l
+90.223 1.793 l
+90.223 1.705 l
+90.223 1.272 90.3 0.959 90.458 0.764 c
+90.623 0.577 90.855 0.485 91.149 0.485 c
+91.344 0.485 91.516 0.518 91.664 0.588 c
+91.811 0.665 91.946 0.783 92.075 0.941 c
+92.413 0.529 l
+92.127 0.125 91.697 -0.073 91.119 -0.073 c
+91.046 3.499 m
+90.77 3.499 90.569 3.403 90.444 3.219 c
+90.315 3.032 90.241 2.741 90.223 2.352 c
+91.795 2.352 l
+91.795 2.44 l
+91.774 2.822 91.707 3.09 91.589 3.248 c
+91.472 3.414 91.288 3.499 91.046 3.499 c
+95.588 3.572 m
+95.842 3.896 96.161 4.056 96.543 4.056 c
+97.249 4.056 97.605 3.586 97.617 2.645 c
+97.617 0 l
+96.97 0 l
+96.97 2.616 l
+96.97 2.929 96.915 3.15 96.808 3.278 c
+96.698 3.403 96.543 3.469 96.337 3.469 c
+96.179 3.469 96.033 3.414 95.897 3.308 c
+95.768 3.197 95.665 3.061 95.588 2.896 c
+95.588 0 l
+94.941 0 l
+94.941 5.644 l
+95.588 5.644 l
+h
+99.277 0 -0.646 3.983 re
+99.321 5.027 m
+99.321 4.917 99.292 4.825 99.233 4.748 c
+99.175 4.678 99.079 4.644 98.954 4.644 c
+98.837 4.644 98.741 4.678 98.675 4.748 c
+98.616 4.825 98.587 4.917 98.587 5.027 c
+98.587 5.145 98.616 5.236 98.675 5.307 c
+98.741 5.384 98.837 5.424 98.954 5.424 c
+99.079 5.424 99.175 5.384 99.233 5.307 c
+99.292 5.226 99.321 5.134 99.321 5.027 c
+102.232 1.014 m
+102.232 1.161 102.177 1.282 102.07 1.382 c
+101.96 1.477 101.754 1.595 101.453 1.735 c
+101.108 1.881 100.865 2.003 100.718 2.102 c
+100.571 2.209 100.461 2.326 100.395 2.454 c
+100.325 2.58 100.291 2.738 100.291 2.925 c
+100.291 3.248 100.409 3.516 100.644 3.734 c
+100.879 3.946 101.181 4.056 101.556 4.056 c
+101.938 4.056 102.247 3.943 102.482 3.719 c
+102.717 3.491 102.835 3.204 102.835 2.851 c
+102.188 2.851 l
+102.188 3.028 102.129 3.179 102.012 3.308 c
+101.894 3.432 101.74 3.499 101.556 3.499 c
+101.357 3.499 101.207 3.443 101.1 3.337 c
+100.99 3.237 100.939 3.105 100.939 2.94 c
+100.939 2.811 100.975 2.705 101.056 2.616 c
+101.133 2.535 101.324 2.433 101.629 2.308 c
+102.107 2.12 102.438 1.933 102.614 1.749 c
+102.791 1.573 102.878 1.345 102.878 1.073 c
+102.878 0.721 102.754 0.441 102.511 0.235 c
+102.276 0.029 101.96 -0.073 101.571 -0.073 c
+101.148 -0.073 100.81 0.044 100.557 0.279 c
+100.299 0.522 100.174 0.827 100.174 1.191 c
+100.821 1.191 l
+100.828 0.962 100.898 0.786 101.027 0.661 c
+101.152 0.544 101.335 0.485 101.571 0.485 c
+101.783 0.485 101.945 0.532 102.055 0.632 c
+102.173 0.727 102.232 0.856 102.232 1.014 c
+104.569 4.939 m
+104.569 3.983 l
+105.172 3.983 l
+105.172 3.454 l
+104.569 3.454 l
+104.569 0.985 l
+104.569 0.827 104.591 0.709 104.642 0.632 c
+104.701 0.551 104.79 0.515 104.907 0.515 c
+104.995 0.515 105.083 0.529 105.172 0.559 c
+105.172 0 l
+105.025 -0.048 104.871 -0.073 104.717 -0.073 c
+104.459 -0.073 104.264 0.018 104.129 0.206 c
+103.988 0.389 103.923 0.65 103.923 0.985 c
+103.923 3.454 l
+103.32 3.454 l
+103.32 3.983 l
+103.923 3.983 l
+103.923 4.939 l
+h
+105.731 2.175 m
+105.731 2.753 105.866 3.208 106.142 3.543 c
+106.425 3.884 106.796 4.056 107.259 4.056 c
+107.718 4.056 108.086 3.888 108.362 3.557 c
+108.644 3.233 108.792 2.786 108.802 2.219 c
+108.802 1.793 l
+108.802 1.224 108.659 0.768 108.376 0.426 c
+108.1 0.092 107.733 -0.073 107.273 -0.073 c
+106.811 -0.073 106.44 0.088 106.157 0.411 c
+105.881 0.742 105.738 1.183 105.731 1.735 c
+h
+106.377 1.793 m
+106.377 1.389 106.454 1.073 106.612 0.838 c
+106.778 0.603 106.998 0.485 107.273 0.485 c
+107.84 0.485 108.133 0.897 108.156 1.72 c
+108.156 2.175 l
+108.156 2.576 108.071 2.896 107.906 3.131 c
+107.748 3.373 107.531 3.499 107.259 3.499 c
+106.994 3.499 106.778 3.373 106.612 3.131 c
+106.454 2.896 106.377 2.576 106.377 2.175 c
+h
+111.287 3.366 m
+111.198 3.385 111.099 3.395 110.992 3.395 c
+110.658 3.395 110.423 3.212 110.287 2.851 c
+110.287 0 l
+109.64 0 l
+109.64 3.983 l
+110.273 3.983 l
+110.287 3.572 l
+110.463 3.896 110.706 4.056 111.022 4.056 c
+111.129 4.056 111.217 4.035 111.287 3.998 c
+h
+113.095 1.088 m
+113.814 3.983 l
+114.506 3.983 l
+113.212 -0.559 l
+113.113 -0.9 112.97 -1.161 112.786 -1.338 c
+112.609 -1.514 112.407 -1.602 112.183 -1.602 c
+112.095 -1.602 111.981 -1.58 111.845 -1.544 c
+111.845 -1 l
+111.992 -1.014 l
+112.176 -1.014 112.323 -0.97 112.433 -0.882 c
+112.54 -0.794 112.628 -0.636 112.698 -0.412 c
+112.815 0.029 l
+111.654 3.983 l
+112.36 3.983 l
+h
+117.151 0 m
+117.151 3.454 l
+116.623 3.454 l
+116.623 3.983 l
+117.151 3.983 l
+117.151 4.439 l
+117.151 4.839 117.247 5.152 117.446 5.38 c
+117.652 5.604 117.93 5.718 118.283 5.718 c
+118.419 5.718 118.552 5.696 118.68 5.66 c
+118.651 5.115 l
+118.552 5.134 118.452 5.145 118.357 5.145 c
+117.982 5.145 117.798 4.88 117.798 4.351 c
+117.798 3.983 l
+118.475 3.983 l
+118.475 3.454 l
+117.798 3.454 l
+117.798 0 l
+h
+120.885 3.366 m
+120.797 3.385 120.698 3.395 120.592 3.395 c
+120.257 3.395 120.021 3.212 119.886 2.851 c
+119.886 0 l
+119.239 0 l
+119.239 3.983 l
+119.871 3.983 l
+119.886 3.572 l
+120.062 3.896 120.305 4.056 120.621 4.056 c
+120.727 4.056 120.815 4.035 120.885 3.998 c
+h
+121.326 2.175 m
+121.326 2.753 121.462 3.208 121.737 3.543 c
+122.02 3.884 122.392 4.056 122.855 4.056 c
+123.314 4.056 123.682 3.888 123.957 3.557 c
+124.241 3.233 124.387 2.786 124.398 2.219 c
+124.398 1.793 l
+124.398 1.224 124.255 0.768 123.972 0.426 c
+123.696 0.092 123.329 -0.073 122.869 -0.073 c
+122.406 -0.073 122.036 0.088 121.752 0.411 c
+121.477 0.742 121.334 1.183 121.326 1.735 c
+h
+121.972 1.793 m
+121.972 1.389 122.05 1.073 122.208 0.838 c
+122.373 0.603 122.594 0.485 122.869 0.485 c
+123.435 0.485 123.73 0.897 123.751 1.72 c
+123.751 2.175 l
+123.751 2.576 123.667 2.896 123.501 3.131 c
+123.343 3.373 123.127 3.499 122.855 3.499 c
+122.591 3.499 122.373 3.373 122.208 3.131 c
+122.05 2.896 121.972 2.576 121.972 2.175 c
+h
+125.853 3.983 m
+125.868 3.616 l
+126.111 3.91 126.431 4.056 126.824 4.056 c
+127.264 4.056 127.573 3.859 127.75 3.469 c
+128.004 3.859 128.353 4.056 128.793 4.056 c
+129.529 4.056 129.903 3.594 129.925 2.675 c
+129.925 0 l
+129.278 0 l
+129.278 2.616 l
+129.278 2.911 129.223 3.123 129.116 3.263 c
+129.018 3.399 128.845 3.469 128.602 3.469 c
+128.403 3.469 128.242 3.389 128.117 3.233 c
+128 3.087 127.929 2.896 127.911 2.66 c
+127.911 0 l
+127.25 0 l
+127.25 2.645 l
+127.25 3.193 127.029 3.469 126.589 3.469 c
+126.254 3.469 126.019 3.308 125.883 2.984 c
+125.883 0 l
+125.236 0 l
+125.236 3.983 l
+h
+133.467 4.939 m
+133.467 3.983 l
+134.07 3.983 l
+134.07 3.454 l
+133.467 3.454 l
+133.467 0.985 l
+133.467 0.827 133.49 0.709 133.541 0.632 c
+133.6 0.551 133.688 0.515 133.805 0.515 c
+133.894 0.515 133.982 0.529 134.07 0.559 c
+134.07 0 l
+133.923 -0.048 133.768 -0.073 133.614 -0.073 c
+133.357 -0.073 133.163 0.018 133.026 0.206 c
+132.887 0.389 132.821 0.65 132.821 0.985 c
+132.821 3.454 l
+132.218 3.454 l
+132.218 3.983 l
+132.821 3.983 l
+132.821 4.939 l
+h
+135.482 3.572 m
+135.735 3.896 136.054 4.056 136.436 4.056 c
+137.142 4.056 137.498 3.586 137.51 2.645 c
+137.51 0 l
+136.863 0 l
+136.863 2.616 l
+136.863 2.929 136.808 3.15 136.702 3.278 c
+136.591 3.403 136.436 3.469 136.231 3.469 c
+136.073 3.469 135.926 3.414 135.79 3.308 c
+135.661 3.197 135.559 3.061 135.482 2.896 c
+135.482 0 l
+134.834 0 l
+134.834 5.644 l
+135.482 5.644 l
+h
+139.891 -0.073 m
+139.391 -0.073 139.009 0.073 138.744 0.368 c
+138.48 0.661 138.348 1.095 138.348 1.675 c
+138.348 2.146 l
+138.348 2.741 138.472 3.208 138.73 3.543 c
+138.994 3.884 139.355 4.056 139.817 4.056 c
+140.276 4.056 140.619 3.902 140.847 3.601 c
+141.082 3.308 141.203 2.844 141.213 2.219 c
+141.213 1.793 l
+138.994 1.793 l
+138.994 1.705 l
+138.994 1.272 139.071 0.959 139.229 0.764 c
+139.395 0.577 139.626 0.485 139.92 0.485 c
+140.115 0.485 140.288 0.518 140.435 0.588 c
+140.582 0.665 140.718 0.783 140.847 0.941 c
+141.184 0.529 l
+140.898 0.125 140.468 -0.073 139.891 -0.073 c
+139.817 3.499 m
+139.542 3.499 139.339 3.403 139.214 3.219 c
+139.086 3.032 139.013 2.741 138.994 2.352 c
+140.567 2.352 l
+140.567 2.44 l
+140.546 2.822 140.479 3.09 140.361 3.248 c
+140.244 3.414 140.06 3.499 139.817 3.499 c
+145.359 3.366 m
+145.271 3.385 145.172 3.395 145.065 3.395 c
+144.731 3.395 144.496 3.212 144.359 2.851 c
+144.359 0 l
+143.713 0 l
+143.713 3.983 l
+144.345 3.983 l
+144.359 3.572 l
+144.536 3.896 144.779 4.056 145.094 4.056 c
+145.201 4.056 145.289 4.035 145.359 3.998 c
+h
+147.358 -0.073 m
+146.858 -0.073 146.476 0.073 146.212 0.368 c
+145.947 0.661 145.815 1.095 145.815 1.675 c
+145.815 2.146 l
+145.815 2.741 145.94 3.208 146.197 3.543 c
+146.462 3.884 146.821 4.056 147.285 4.056 c
+147.744 4.056 148.086 3.902 148.313 3.601 c
+148.548 3.308 148.67 2.844 148.681 2.219 c
+148.681 1.793 l
+146.462 1.793 l
+146.462 1.705 l
+146.462 1.272 146.539 0.959 146.697 0.764 c
+146.862 0.577 147.093 0.485 147.388 0.485 c
+147.582 0.485 147.755 0.518 147.902 0.588 c
+148.049 0.665 148.185 0.783 148.313 0.941 c
+148.652 0.529 l
+148.365 0.125 147.935 -0.073 147.358 -0.073 c
+147.285 3.499 m
+147.009 3.499 146.807 3.403 146.682 3.219 c
+146.553 3.032 146.48 2.741 146.462 2.352 c
+148.034 2.352 l
+148.034 2.44 l
+148.012 2.822 147.946 3.09 147.829 3.248 c
+147.711 3.414 147.527 3.499 147.285 3.499 c
+150.077 3.983 m
+150.092 3.616 l
+150.335 3.91 150.655 4.056 151.048 4.056 c
+151.488 4.056 151.797 3.859 151.974 3.469 c
+152.228 3.859 152.577 4.056 153.017 4.056 c
+153.753 4.056 154.127 3.594 154.149 2.675 c
+154.149 0 l
+153.502 0 l
+153.502 2.616 l
+153.502 2.911 153.447 3.123 153.341 3.263 c
+153.242 3.399 153.069 3.469 152.826 3.469 c
+152.627 3.469 152.466 3.389 152.341 3.233 c
+152.224 3.087 152.153 2.896 152.135 2.66 c
+152.135 0 l
+151.474 0 l
+151.474 2.645 l
+151.474 3.193 151.253 3.469 150.813 3.469 c
+150.478 3.469 150.243 3.308 150.107 2.984 c
+150.107 0 l
+149.46 0 l
+149.46 3.983 l
+h
+154.987 2.175 m
+154.987 2.753 155.123 3.208 155.399 3.543 c
+155.681 3.884 156.053 4.056 156.516 4.056 c
+156.975 4.056 157.342 3.888 157.618 3.557 c
+157.901 3.233 158.048 2.786 158.059 2.219 c
+158.059 1.793 l
+158.059 1.224 157.915 0.768 157.633 0.426 c
+157.357 0.092 156.99 -0.073 156.531 -0.073 c
+156.068 -0.073 155.696 0.088 155.413 0.411 c
+155.137 0.742 154.994 1.183 154.987 1.735 c
+h
+155.634 1.793 m
+155.634 1.389 155.711 1.073 155.869 0.838 c
+156.034 0.603 156.255 0.485 156.531 0.485 c
+157.096 0.485 157.39 0.897 157.412 1.72 c
+157.412 2.175 l
+157.412 2.576 157.327 2.896 157.163 3.131 c
+157.005 3.373 156.787 3.499 156.516 3.499 c
+156.251 3.499 156.034 3.373 155.869 3.131 c
+155.711 2.896 155.634 2.576 155.634 2.175 c
+h
+159.75 4.939 m
+159.75 3.983 l
+160.352 3.983 l
+160.352 3.454 l
+159.75 3.454 l
+159.75 0.985 l
+159.75 0.827 159.771 0.709 159.823 0.632 c
+159.881 0.551 159.97 0.515 160.087 0.515 c
+160.176 0.515 160.263 0.529 160.352 0.559 c
+160.352 0 l
+160.205 -0.048 160.051 -0.073 159.897 -0.073 c
+159.639 -0.073 159.444 0.018 159.309 0.206 c
+159.168 0.389 159.103 0.65 159.103 0.985 c
+159.103 3.454 l
+158.5 3.454 l
+158.5 3.983 l
+159.103 3.983 l
+159.103 4.939 l
+h
+162.542 -0.073 m
+162.042 -0.073 161.66 0.073 161.396 0.368 c
+161.131 0.661 160.999 1.095 160.999 1.675 c
+160.999 2.146 l
+160.999 2.741 161.124 3.208 161.381 3.543 c
+161.645 3.884 162.006 4.056 162.469 4.056 c
+162.928 4.056 163.27 3.902 163.498 3.601 c
+163.733 3.308 163.854 2.844 163.866 2.219 c
+163.866 1.793 l
+161.645 1.793 l
+161.645 1.705 l
+161.645 1.272 161.723 0.959 161.881 0.764 c
+162.046 0.577 162.278 0.485 162.572 0.485 c
+162.767 0.485 162.939 0.518 163.086 0.588 c
+163.233 0.665 163.369 0.783 163.498 0.941 c
+163.835 0.529 l
+163.549 0.125 163.12 -0.073 162.542 -0.073 c
+162.469 3.499 m
+162.193 3.499 161.991 3.403 161.866 3.219 c
+161.738 3.032 161.664 2.741 161.645 2.352 c
+163.218 2.352 l
+163.218 2.44 l
+163.197 2.822 163.13 3.09 163.012 3.248 c
+162.895 3.414 162.711 3.499 162.469 3.499 c
+168.01 3.366 m
+167.922 3.385 167.823 3.395 167.716 3.395 c
+167.382 3.395 167.147 3.212 167.01 2.851 c
+167.01 0 l
+166.364 0 l
+166.364 3.983 l
+166.996 3.983 l
+167.01 3.572 l
+167.187 3.896 167.43 4.056 167.746 4.056 c
+167.852 4.056 167.941 4.035 168.01 3.998 c
+h
+170.009 -0.073 m
+169.51 -0.073 169.127 0.073 168.863 0.368 c
+168.598 0.661 168.466 1.095 168.466 1.675 c
+168.466 2.146 l
+168.466 2.741 168.591 3.208 168.848 3.543 c
+169.113 3.884 169.473 4.056 169.936 4.056 c
+170.395 4.056 170.737 3.902 170.964 3.601 c
+171.2 3.308 171.321 2.844 171.332 2.219 c
+171.332 1.793 l
+169.113 1.793 l
+169.113 1.705 l
+169.113 1.272 169.19 0.959 169.348 0.764 c
+169.513 0.577 169.745 0.485 170.039 0.485 c
+170.233 0.485 170.406 0.518 170.553 0.588 c
+170.7 0.665 170.836 0.783 170.964 0.941 c
+171.303 0.529 l
+171.016 0.125 170.586 -0.073 170.009 -0.073 c
+169.936 3.499 m
+169.66 3.499 169.458 3.403 169.333 3.219 c
+169.204 3.032 169.131 2.741 169.113 2.352 c
+170.686 2.352 l
+170.686 2.44 l
+170.663 2.822 170.597 3.09 170.48 3.248 c
+170.362 3.414 170.179 3.499 169.936 3.499 c
+174.993 1.793 m
+174.993 1.165 174.875 0.694 174.64 0.382 c
+174.412 0.077 174.096 -0.073 173.684 -0.073 c
+173.279 -0.073 172.971 0.077 172.758 0.382 c
+172.758 -1.529 l
+172.111 -1.529 l
+172.111 3.983 l
+172.699 3.983 l
+172.743 3.543 l
+172.957 3.884 173.265 4.056 173.669 4.056 c
+174.11 4.056 174.438 3.902 174.654 3.601 c
+174.867 3.296 174.981 2.84 174.993 2.234 c
+h
+174.345 2.175 m
+174.345 2.616 174.276 2.94 174.139 3.146 c
+174 3.358 173.78 3.469 173.478 3.469 c
+173.162 3.469 172.924 3.314 172.758 3.013 c
+172.758 0.941 l
+172.924 0.636 173.162 0.485 173.478 0.485 c
+173.772 0.485 173.985 0.588 174.125 0.794 c
+174.261 1.007 174.335 1.338 174.345 1.779 c
+h
+175.698 2.175 m
+175.698 2.753 175.834 3.208 176.109 3.543 c
+176.392 3.884 176.764 4.056 177.227 4.056 c
+177.686 4.056 178.054 3.888 178.329 3.557 c
+178.612 3.233 178.759 2.786 178.77 2.219 c
+178.77 1.793 l
+178.77 1.224 178.627 0.768 178.343 0.426 c
+178.068 0.092 177.701 -0.073 177.241 -0.073 c
+176.778 -0.073 176.407 0.088 176.124 0.411 c
+175.849 0.742 175.706 1.183 175.698 1.735 c
+h
+176.344 1.793 m
+176.344 1.389 176.422 1.073 176.58 0.838 c
+176.745 0.603 176.965 0.485 177.241 0.485 c
+177.807 0.485 178.101 0.897 178.123 1.72 c
+178.123 2.175 l
+178.123 2.576 178.039 2.896 177.873 3.131 c
+177.715 3.373 177.499 3.499 177.227 3.499 c
+176.962 3.499 176.745 3.373 176.58 3.131 c
+176.422 2.896 176.344 2.576 176.344 2.175 c
+h
+181.548 1.014 m
+181.548 1.161 181.493 1.282 181.387 1.382 c
+181.276 1.477 181.071 1.595 180.769 1.735 c
+180.423 1.881 180.181 2.003 180.034 2.102 c
+179.887 2.209 179.777 2.326 179.71 2.454 c
+179.641 2.58 179.608 2.738 179.608 2.925 c
+179.608 3.248 179.725 3.516 179.961 3.734 c
+180.196 3.946 180.497 4.056 180.872 4.056 c
+181.254 4.056 181.563 3.943 181.798 3.719 c
+182.033 3.491 182.151 3.204 182.151 2.851 c
+181.504 2.851 l
+181.504 3.028 181.445 3.179 181.328 3.308 c
+181.21 3.432 181.056 3.499 180.872 3.499 c
+180.674 3.499 180.523 3.443 180.416 3.337 c
+180.306 3.237 180.254 3.105 180.254 2.94 c
+180.254 2.811 180.292 2.705 180.372 2.616 c
+180.45 2.535 180.641 2.433 180.946 2.308 c
+181.423 2.12 181.754 1.933 181.931 1.749 c
+182.106 1.573 182.195 1.345 182.195 1.073 c
+182.195 0.721 182.07 0.441 181.827 0.235 c
+181.592 0.029 181.276 -0.073 180.886 -0.073 c
+180.464 -0.073 180.126 0.044 179.872 0.279 c
+179.615 0.522 179.49 0.827 179.49 1.191 c
+180.137 1.191 l
+180.144 0.962 180.215 0.786 180.343 0.661 c
+180.468 0.544 180.651 0.485 180.886 0.485 c
+181.1 0.485 181.262 0.532 181.372 0.632 c
+181.489 0.727 181.548 0.856 181.548 1.014 c
+183.739 0 -0.647 3.983 re
+183.782 5.027 m
+183.782 4.917 183.753 4.825 183.694 4.748 c
+183.635 4.678 183.54 4.644 183.415 4.644 c
+183.297 4.644 183.201 4.678 183.136 4.748 c
+183.076 4.825 183.047 4.917 183.047 5.027 c
+183.047 5.145 183.076 5.236 183.136 5.307 c
+183.201 5.384 183.297 5.424 183.415 5.424 c
+183.54 5.424 183.635 5.384 183.694 5.307 c
+183.753 5.226 183.782 5.134 183.782 5.027 c
+185.605 4.939 m
+185.605 3.983 l
+186.208 3.983 l
+186.208 3.454 l
+185.605 3.454 l
+185.605 0.985 l
+185.605 0.827 185.627 0.709 185.678 0.632 c
+185.738 0.551 185.825 0.515 185.943 0.515 c
+186.031 0.515 186.12 0.529 186.208 0.559 c
+186.208 0 l
+186.06 -0.048 185.906 -0.073 185.752 -0.073 c
+185.495 -0.073 185.3 0.018 185.164 0.206 c
+185.025 0.389 184.958 0.65 184.958 0.985 c
+184.958 3.454 l
+184.356 3.454 l
+184.356 3.983 l
+184.958 3.983 l
+184.958 4.939 l
+h
+186.766 2.175 m
+186.766 2.753 186.902 3.208 187.178 3.543 c
+187.461 3.884 187.832 4.056 188.295 4.056 c
+188.755 4.056 189.122 3.888 189.397 3.557 c
+189.68 3.233 189.827 2.786 189.838 2.219 c
+189.838 1.793 l
+189.838 1.224 189.695 0.768 189.412 0.426 c
+189.137 0.092 188.769 -0.073 188.31 -0.073 c
+187.847 -0.073 187.475 0.088 187.192 0.411 c
+186.916 0.742 186.773 1.183 186.766 1.735 c
+h
+187.413 1.793 m
+187.413 1.389 187.49 1.073 187.648 0.838 c
+187.814 0.603 188.034 0.485 188.31 0.485 c
+188.876 0.485 189.17 0.897 189.191 1.72 c
+189.191 2.175 l
+189.191 2.576 189.107 2.896 188.942 3.131 c
+188.784 3.373 188.567 3.499 188.295 3.499 c
+188.03 3.499 187.814 3.373 187.648 3.131 c
+187.49 2.896 187.413 2.576 187.413 2.175 c
+h
+192.323 3.366 m
+192.234 3.385 192.135 3.395 192.028 3.395 c
+191.694 3.395 191.459 3.212 191.323 2.851 c
+191.323 0 l
+190.677 0 l
+190.677 3.983 l
+191.308 3.983 l
+191.323 3.572 l
+191.5 3.896 191.742 4.056 192.058 4.056 c
+192.165 4.056 192.252 4.035 192.323 3.998 c
+h
+194.13 1.088 m
+194.851 3.983 l
+195.541 3.983 l
+194.248 -0.559 l
+194.149 -0.9 194.006 -1.161 193.821 -1.338 c
+193.646 -1.514 193.443 -1.602 193.219 -1.602 c
+193.131 -1.602 193.017 -1.58 192.881 -1.544 c
+192.881 -1 l
+193.028 -1.014 l
+193.212 -1.014 193.359 -0.97 193.469 -0.882 c
+193.576 -0.794 193.663 -0.636 193.734 -0.412 c
+193.852 0.029 l
+192.69 3.983 l
+193.395 3.983 l
+h
+195.821 0.353 m
+195.821 0.47 195.853 0.566 195.924 0.646 c
+195.99 0.723 196.092 0.764 196.233 0.764 c
+196.379 0.764 196.486 0.723 196.556 0.646 c
+196.633 0.566 196.674 0.47 196.674 0.353 c
+196.674 0.243 196.633 0.151 196.556 0.073 c
+196.486 -0.004 196.379 -0.044 196.233 -0.044 c
+196.092 -0.044 195.99 -0.004 195.924 0.073 c
+195.853 0.151 195.821 0.243 195.821 0.353 c
+f
+Q
+0.793 0.801 0.129 0.016 k
+287.665 442.028 234.667 -21.457 re
+f
+0 0 0 0 k
+q 1 0 0 1 400.8622 432.0517 cm
+0 0 m
+0.882 0 l
+1.213 0 1.459 0.118 1.617 0.353 c
+1.771 0.588 1.852 0.897 1.852 1.278 c
+1.852 1.661 1.768 1.955 1.602 2.161 c
+1.444 2.367 1.228 2.469 0.955 2.469 c
+0.709 2.469 0.503 2.37 0.338 2.175 c
+0.18 1.976 0.103 1.727 0.103 1.426 c
+-1.72 1.426 l
+-1.72 1.914 -1.61 2.352 -1.382 2.734 c
+-1.158 3.123 -0.846 3.428 -0.441 3.645 c
+-0.029 3.869 0.419 3.983 0.912 3.983 c
+1.771 3.983 2.447 3.74 2.94 3.263 c
+3.428 2.793 3.675 2.138 3.675 1.309 c
+3.675 0.885 3.561 0.492 3.337 0.133 c
+3.12 -0.231 2.83 -0.511 2.469 -0.706 c
+2.911 -0.893 3.237 -1.176 3.454 -1.558 c
+3.667 -1.933 3.777 -2.374 3.777 -2.882 c
+3.777 -3.715 3.513 -4.388 2.984 -4.895 c
+2.454 -5.394 1.756 -5.644 0.897 -5.644 c
+0.092 -5.644 -0.559 -5.402 -1.058 -4.91 c
+-1.558 -4.41 -1.808 -3.755 -1.808 -2.94 c
+0.014 -2.94 l
+0.014 -3.285 0.103 -3.568 0.279 -3.792 c
+0.455 -4.021 0.68 -4.131 0.955 -4.131 c
+1.268 -4.131 1.514 -4.021 1.691 -3.792 c
+1.874 -3.557 1.97 -3.245 1.97 -2.851 c
+1.97 -1.933 1.61 -1.47 0.897 -1.47 c
+0 -1.47 l
+h
+5.427 -4.586 m
+5.427 -4.293 5.523 -4.054 5.722 -3.866 c
+5.916 -3.682 6.169 -3.587 6.485 -3.587 c
+6.787 -3.587 7.037 -3.682 7.235 -3.866 c
+7.441 -4.054 7.544 -4.293 7.544 -4.586 c
+7.544 -4.891 7.441 -5.137 7.235 -5.321 c
+7.037 -5.498 6.787 -5.586 6.485 -5.586 c
+6.181 -5.586 5.928 -5.494 5.722 -5.307 c
+5.523 -5.122 5.427 -4.881 5.427 -4.586 c
+12.432 -5.512 m
+12.432 3.851 l
+14.915 3.851 l
+16.004 3.851 16.87 3.502 17.518 2.807 c
+18.171 2.109 18.506 1.161 18.517 -0.044 c
+18.517 -1.558 l
+18.517 -2.793 18.194 -3.763 17.547 -4.469 c
+16.9 -5.167 16.004 -5.512 14.857 -5.512 c
+h
+14.327 2.278 m
+14.327 -3.94 l
+14.886 -3.94 l
+15.522 -3.94 15.967 -3.774 16.224 -3.439 c
+16.477 -3.109 16.61 -2.535 16.621 -1.72 c
+16.621 -0.103 l
+16.621 0.779 16.496 1.389 16.253 1.735 c
+16.018 2.076 15.607 2.256 15.019 2.278 c
+h
+24.415 -3.601 m
+21.843 -3.601 l
+21.343 -5.512 l
+19.344 -5.512 l
+22.269 3.851 l
+23.989 3.851 l
+26.944 -5.512 l
+24.915 -5.512 l
+h
+22.254 -2.014 m
+24.003 -2.014 l
+23.121 1.323 l
+h
+29.886 -0.353 m
+31.297 3.851 l
+33.356 3.851 l
+30.842 -2.117 l
+30.842 -5.512 l
+28.932 -5.512 l
+28.932 -2.117 l
+26.418 3.851 l
+28.475 3.851 l
+h
+36.604 -2.263 -3.146 1.529 re
+44.406 2.278 m
+42.083 2.278 l
+42.083 -5.512 l
+40.187 -5.512 l
+40.187 2.278 l
+37.909 2.278 l
+37.909 3.851 l
+44.406 3.851 l
+h
+52.105 -1.675 m
+52.105 -2.932 51.803 -3.906 51.207 -4.601 c
+50.609 -5.299 49.786 -5.644 48.738 -5.644 c
+47.687 -5.644 46.86 -5.303 46.254 -4.615 c
+45.655 -3.921 45.35 -2.955 45.343 -1.72 c
+45.343 -0.118 l
+45.343 1.165 45.64 2.168 46.239 2.896 c
+46.835 3.62 47.665 3.983 48.724 3.983 c
+49.759 3.983 50.579 3.623 51.178 2.911 c
+51.785 2.205 52.093 1.209 52.105 -0.073 c
+h
+50.208 -0.103 m
+50.208 0.738 50.083 1.367 49.84 1.779 c
+49.605 2.19 49.231 2.396 48.724 2.396 c
+48.224 2.396 47.849 2.194 47.606 1.793 c
+47.371 1.4 47.247 0.801 47.239 0 c
+47.239 -1.675 l
+47.239 -2.492 47.361 -3.094 47.606 -3.484 c
+47.849 -3.877 48.227 -4.072 48.738 -4.072 c
+49.227 -4.072 49.591 -3.881 49.826 -3.499 c
+50.069 -3.117 50.197 -2.529 50.208 -1.735 c
+h
+56.871 -2.263 -3.146 1.529 re
+58.601 -5.512 m
+58.601 3.851 l
+61.085 3.851 l
+62.173 3.851 63.041 3.502 63.687 2.807 c
+64.341 2.109 64.676 1.161 64.687 -0.044 c
+64.687 -1.558 l
+64.687 -2.793 64.364 -3.763 63.716 -4.469 c
+63.07 -5.167 62.173 -5.512 61.027 -5.512 c
+h
+60.497 2.278 m
+60.497 -3.94 l
+61.056 -3.94 l
+61.692 -3.94 62.137 -3.774 62.394 -3.439 c
+62.648 -3.109 62.779 -2.535 62.791 -1.72 c
+62.791 -0.103 l
+62.791 0.779 62.665 1.389 62.423 1.735 c
+62.188 2.076 61.776 2.256 61.189 2.278 c
+h
+70.585 -3.601 m
+68.013 -3.601 l
+67.512 -5.512 l
+65.514 -5.512 l
+68.439 3.851 l
+70.158 3.851 l
+73.113 -5.512 l
+71.084 -5.512 l
+h
+68.424 -2.014 m
+70.174 -2.014 l
+69.291 1.323 l
+h
+76.057 -0.353 m
+77.468 3.851 l
+79.525 3.851 l
+77.012 -2.117 l
+77.012 -5.512 l
+75.101 -5.512 l
+75.101 -2.117 l
+72.587 3.851 l
+74.646 3.851 l
+h
+89.796 -2.028 m
+90.679 3.851 l
+92.56 3.851 l
+90.884 -5.512 l
+88.988 -5.512 l
+87.9 0 l
+86.827 -5.512 l
+84.916 -5.512 l
+83.24 3.851 l
+85.122 3.851 l
+86.004 -2.028 l
+87.107 3.851 l
+88.694 3.851 l
+h
+100.472 -1.675 m
+100.472 -2.932 100.17 -3.906 99.575 -4.601 c
+98.976 -5.299 98.153 -5.644 97.106 -5.644 c
+96.054 -5.644 95.227 -5.303 94.621 -4.615 c
+94.022 -3.921 93.717 -2.955 93.71 -1.72 c
+93.71 -0.118 l
+93.71 1.165 94.008 2.168 94.606 2.896 c
+95.202 3.62 96.033 3.983 97.091 3.983 c
+98.127 3.983 98.947 3.623 99.545 2.911 c
+100.152 2.205 100.461 1.209 100.472 -0.073 c
+h
+98.575 -0.103 m
+98.575 0.738 98.45 1.367 98.208 1.779 c
+97.972 2.19 97.598 2.396 97.091 2.396 c
+96.591 2.396 96.216 2.194 95.973 1.793 c
+95.738 1.4 95.614 0.801 95.606 0 c
+95.606 -1.675 l
+95.606 -2.492 95.728 -3.094 95.973 -3.484 c
+96.216 -3.877 96.595 -4.072 97.106 -4.072 c
+97.594 -4.072 97.958 -3.881 98.193 -3.499 c
+98.436 -3.117 98.564 -2.529 98.575 -1.735 c
+h
+104.885 -2.087 m
+103.944 -2.087 l
+103.944 -5.512 l
+102.063 -5.512 l
+102.063 3.851 l
+105.076 3.851 l
+106.024 3.851 106.755 3.605 107.266 3.116 c
+107.784 2.624 108.045 1.929 108.045 1.029 c
+108.045 -0.217 107.593 -1.088 106.693 -1.588 c
+108.324 -5.424 l
+108.324 -5.512 l
+106.296 -5.512 l
+h
+103.944 -0.515 m
+105.018 -0.515 l
+105.4 -0.515 105.683 -0.393 105.87 -0.147 c
+106.053 0.106 106.149 0.445 106.149 0.867 c
+106.149 1.808 105.785 2.278 105.062 2.278 c
+103.944 2.278 l
+h
+112.205 -1.897 m
+111.455 -2.837 l
+111.455 -5.512 l
+109.559 -5.512 l
+109.559 3.851 l
+111.455 3.851 l
+111.455 -0.235 l
+112.058 0.779 l
+113.793 3.851 l
+116.115 3.851 l
+113.425 -0.264 l
+116.159 -5.512 l
+113.91 -5.512 l
+h
+f
+Q
+0.113 0.082 0.09 0 k
+287.665 411.726 234.667 -12.895 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 404.8916 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.647 -0.243 -0.775 -0.367 -0.882 c
+-0.496 -0.992 -0.658 -1.081 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.162 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.927 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.132 l
+-2.642 0.033 -2.616 -0.059 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.683 -1.992 0.69 -1.999 0.69 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.881 -2.786 0.959 -2.91 1.058 c
+-3.039 1.153 -3.142 1.278 -3.219 1.425 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.836 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.119 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.119 -1.128 3.09 -0.97 3.042 c
+-0.804 2.992 -0.669 2.917 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.252 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.352 c
+-1.294 1.311 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.319 2.385 -2.366 2.337 c
+-2.406 2.296 -2.436 2.248 -2.454 2.19 c
+-2.477 2.131 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.778 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.469 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.091 -0.86 0.176 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.529 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.53 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.66 m
+6.184 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.485 5.402 -2.396 c
+5.284 -2.315 5.185 -2.22 5.108 -2.103 c
+5.039 -1.985 4.991 -1.856 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.86 6.064 -1.941 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.058 6.681 -2.028 c
+6.758 -1.999 6.828 -1.945 6.887 -1.867 c
+6.945 -1.797 6.99 -1.706 7.019 -1.588 c
+7.056 -1.47 7.078 -1.323 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.073 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.412 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.234 c
+4.946 1.448 5.027 1.631 5.137 1.778 c
+5.244 1.933 5.376 2.051 5.534 2.131 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.252 6.387 2.234 c
+6.483 2.212 6.571 2.179 6.652 2.131 c
+6.739 2.08 6.817 2.017 6.887 1.94 c
+6.964 1.859 7.026 1.768 7.078 1.66 c
+7.092 1.66 l
+7.092 1.808 l
+7.1 1.866 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.151 2.219 c
+8.004 2.219 l
+7.993 2.138 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.162 l
+7.975 -1.415 7.938 -1.635 7.871 -1.823 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.529 m
+7.092 0.742 7.067 0.918 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.587 c
+6.571 1.624 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.62 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.339 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.177 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.529 c
+11.036 -0.647 m
+12.168 -0.647 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.647 l
+10.124 -0.647 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.676 re
+10.124 2.836 m
+13.597 1.602 m
+13.053 1.602 l
+13.053 2.219 l
+13.641 2.219 l
+13.92 3.116 l
+14.494 3.116 l
+14.494 2.219 l
+15.728 2.219 l
+15.728 1.602 l
+14.494 1.602 l
+14.494 -0.103 l
+14.494 -0.324 l
+14.501 -0.393 14.523 -0.456 14.552 -0.515 c
+14.589 -0.566 14.645 -0.611 14.714 -0.647 c
+14.791 -0.676 14.905 -0.691 15.052 -0.691 c
+15.188 -0.691 15.324 -0.688 15.464 -0.676 c
+15.599 -0.658 15.732 -0.632 15.861 -0.603 c
+15.861 -1.205 l
+15.78 -1.216 15.703 -1.231 15.626 -1.249 c
+15.545 -1.261 15.468 -1.268 15.391 -1.279 c
+15.31 -1.286 15.221 -1.294 15.125 -1.294 c
+15.038 -1.301 14.938 -1.309 14.832 -1.309 c
+14.645 -1.309 14.483 -1.294 14.346 -1.264 c
+14.218 -1.228 14.104 -1.183 14.009 -1.132 c
+13.92 -1.085 13.847 -1.025 13.788 -0.956 c
+13.729 -0.879 13.685 -0.802 13.656 -0.721 c
+13.627 -0.632 13.604 -0.544 13.597 -0.456 c
+13.586 -0.36 13.582 -0.264 13.582 -0.177 c
+h
+24.22 -0.25 m
+24.22 -0.419 24.18 -0.57 24.103 -0.706 c
+24.033 -0.834 23.931 -0.948 23.794 -1.044 c
+23.666 -1.132 23.504 -1.202 23.31 -1.249 c
+23.121 -1.297 22.905 -1.323 22.662 -1.323 c
+22.435 -1.323 22.236 -1.309 22.06 -1.279 c
+21.883 -1.249 21.725 -1.202 21.59 -1.132 c
+21.45 -1.055 21.34 -0.956 21.251 -0.838 c
+21.163 -0.721 21.093 -0.574 21.045 -0.397 c
+21.854 -0.279 l
+21.872 -0.379 21.902 -0.456 21.942 -0.515 c
+21.99 -0.574 22.049 -0.617 22.119 -0.647 c
+22.185 -0.676 22.265 -0.702 22.354 -0.721 c
+22.442 -0.732 22.545 -0.735 22.662 -0.735 c
+22.758 -0.735 22.853 -0.732 22.942 -0.721 c
+23.03 -0.702 23.107 -0.676 23.177 -0.647 c
+23.243 -0.617 23.295 -0.58 23.324 -0.53 c
+23.36 -0.482 23.383 -0.419 23.383 -0.339 c
+23.383 -0.243 23.353 -0.169 23.295 -0.118 c
+23.243 -0.07 23.177 -0.029 23.089 0 c
+23.001 0.037 22.89 0.066 22.766 0.088 c
+22.647 0.118 22.516 0.147 22.369 0.176 c
+22.229 0.213 22.09 0.253 21.942 0.293 c
+21.803 0.341 21.677 0.405 21.56 0.484 c
+21.45 0.562 21.361 0.661 21.296 0.779 c
+21.226 0.897 21.193 1.047 21.193 1.234 c
+21.193 1.389 21.222 1.532 21.28 1.66 c
+21.347 1.797 21.442 1.911 21.56 1.999 c
+21.685 2.087 21.843 2.153 22.03 2.205 c
+22.215 2.252 22.427 2.278 22.662 2.278 c
+22.846 2.278 23.023 2.256 23.192 2.219 c
+23.357 2.19 23.504 2.135 23.632 2.057 c
+23.757 1.988 23.868 1.889 23.956 1.764 c
+24.044 1.646 24.103 1.502 24.133 1.338 c
+23.339 1.264 l
+23.316 1.341 23.287 1.404 23.25 1.455 c
+23.21 1.514 23.162 1.558 23.104 1.587 c
+23.052 1.624 22.99 1.65 22.913 1.66 c
+22.832 1.668 22.751 1.675 22.662 1.675 c
+22.446 1.675 22.284 1.646 22.177 1.587 c
+22.067 1.536 22.016 1.448 22.016 1.323 c
+22.016 1.242 22.034 1.18 22.074 1.132 c
+22.122 1.08 22.185 1.043 22.265 1.014 c
+22.354 0.985 22.45 0.955 22.56 0.926 c
+22.666 0.904 22.788 0.881 22.927 0.852 c
+23.081 0.823 23.239 0.783 23.397 0.735 c
+23.551 0.683 23.692 0.621 23.809 0.544 c
+23.927 0.463 24.022 0.36 24.103 0.235 c
+24.18 0.106 24.22 -0.056 24.22 -0.25 c
+25.783 1.602 m
+25.238 1.602 l
+25.238 2.219 l
+25.826 2.219 l
+26.106 3.116 l
+26.679 3.116 l
+26.679 2.219 l
+27.914 2.219 l
+27.914 1.602 l
+26.679 1.602 l
+26.679 -0.103 l
+26.679 -0.324 l
+26.686 -0.393 26.709 -0.456 26.738 -0.515 c
+26.774 -0.566 26.83 -0.611 26.9 -0.647 c
+26.977 -0.676 27.09 -0.691 27.237 -0.691 c
+27.374 -0.691 27.509 -0.688 27.649 -0.676 c
+27.785 -0.658 27.917 -0.632 28.046 -0.603 c
+28.046 -1.205 l
+27.965 -1.216 27.888 -1.231 27.811 -1.249 c
+27.73 -1.261 27.653 -1.268 27.576 -1.279 c
+27.495 -1.286 27.407 -1.294 27.312 -1.294 c
+27.223 -1.301 27.123 -1.309 27.017 -1.309 c
+26.83 -1.309 26.668 -1.294 26.532 -1.264 c
+26.404 -1.228 26.29 -1.183 26.194 -1.132 c
+26.106 -1.085 26.032 -1.025 25.974 -0.956 c
+25.915 -0.879 25.87 -0.802 25.841 -0.721 c
+25.812 -0.632 25.789 -0.544 25.783 -0.456 c
+25.772 -0.36 25.768 -0.264 25.768 -0.177 c
+h
+30.196 -1.323 m
+30.027 -1.323 29.876 -1.301 29.741 -1.264 c
+29.612 -1.216 29.498 -1.147 29.402 -1.058 c
+29.313 -0.97 29.244 -0.864 29.196 -0.735 c
+29.145 -0.599 29.122 -0.449 29.122 -0.279 c
+29.122 -0.073 29.155 0.095 29.226 0.235 c
+29.292 0.382 29.388 0.492 29.505 0.573 c
+29.63 0.661 29.773 0.723 29.931 0.764 c
+30.096 0.801 30.273 0.827 30.46 0.837 c
+31.181 0.852 l
+31.181 1.029 l
+31.181 1.147 31.17 1.249 31.152 1.338 c
+31.129 1.425 31.096 1.492 31.048 1.543 c
+31.008 1.602 30.96 1.639 30.901 1.66 c
+30.842 1.679 30.776 1.69 30.71 1.69 c
+30.641 1.69 30.578 1.679 30.519 1.66 c
+30.468 1.65 30.42 1.624 30.372 1.587 c
+30.331 1.558 30.298 1.506 30.269 1.44 c
+30.248 1.382 30.233 1.301 30.225 1.205 c
+29.284 1.249 l
+29.313 1.396 29.358 1.532 29.417 1.66 c
+29.483 1.785 29.579 1.896 29.696 1.984 c
+29.814 2.08 29.953 2.153 30.122 2.205 c
+30.298 2.252 30.504 2.278 30.74 2.278 c
+31.181 2.278 31.511 2.168 31.74 1.955 c
+31.975 1.749 32.092 1.44 32.092 1.029 c
+32.092 -0.235 l
+32.092 -0.456 l
+32.099 -0.515 32.114 -0.57 32.136 -0.617 c
+32.154 -0.658 32.184 -0.691 32.224 -0.721 c
+32.261 -0.742 32.313 -0.75 32.371 -0.75 c
+32.438 -0.75 32.507 -0.746 32.577 -0.735 c
+32.577 -1.22 l
+32.519 -1.231 32.463 -1.242 32.415 -1.249 c
+32.375 -1.261 32.334 -1.268 32.297 -1.279 c
+32.257 -1.286 32.213 -1.294 32.166 -1.294 c
+32.114 -1.301 32.055 -1.309 31.989 -1.309 c
+31.761 -1.309 31.596 -1.257 31.489 -1.147 c
+31.379 -1.029 31.316 -0.864 31.298 -0.647 c
+31.283 -0.647 l
+31.214 -0.757 31.144 -0.852 31.077 -0.941 c
+31.008 -1.022 30.931 -1.087 30.842 -1.147 c
+30.755 -1.205 30.655 -1.249 30.549 -1.279 c
+30.449 -1.309 30.331 -1.323 30.196 -1.323 c
+31.181 0.353 m
+30.755 0.338 l
+30.655 0.338 30.564 0.33 30.475 0.324 c
+30.394 0.312 30.328 0.287 30.269 0.249 c
+30.211 0.209 30.159 0.151 30.122 0.073 c
+30.082 0.004 30.063 -0.088 30.063 -0.206 c
+30.063 -0.375 30.096 -0.497 30.167 -0.574 c
+30.233 -0.654 30.331 -0.691 30.46 -0.691 c
+30.567 -0.691 30.666 -0.669 30.755 -0.617 c
+30.85 -0.57 30.931 -0.507 30.99 -0.426 c
+31.056 -0.349 31.107 -0.262 31.137 -0.162 c
+31.166 -0.056 31.181 0.058 31.181 0.176 c
+h
+33.903 1.602 m
+33.36 1.602 l
+33.36 2.219 l
+33.948 2.219 l
+34.227 3.116 l
+34.8 3.116 l
+34.8 2.219 l
+36.035 2.219 l
+36.035 1.602 l
+34.8 1.602 l
+34.8 -0.103 l
+34.8 -0.324 l
+34.807 -0.393 34.83 -0.456 34.859 -0.515 c
+34.896 -0.566 34.951 -0.611 35.021 -0.647 c
+35.098 -0.676 35.212 -0.691 35.359 -0.691 c
+35.495 -0.691 35.631 -0.688 35.771 -0.676 c
+35.906 -0.658 36.039 -0.632 36.168 -0.603 c
+36.168 -1.205 l
+36.087 -1.216 36.01 -1.231 35.932 -1.249 c
+35.852 -1.261 35.774 -1.268 35.697 -1.279 c
+35.616 -1.286 35.528 -1.294 35.432 -1.294 c
+35.345 -1.301 35.245 -1.309 35.138 -1.309 c
+34.951 -1.309 34.789 -1.294 34.653 -1.264 c
+34.525 -1.228 34.41 -1.183 34.315 -1.132 c
+34.227 -1.085 34.154 -1.025 34.094 -0.956 c
+34.036 -0.879 33.992 -0.802 33.963 -0.721 c
+33.933 -0.632 33.911 -0.544 33.903 -0.456 c
+33.893 -0.36 33.889 -0.264 33.889 -0.177 c
+h
+38.248 2.219 m
+38.248 0.264 l
+38.248 0.125 38.254 0 38.277 -0.118 c
+38.295 -0.228 38.328 -0.32 38.379 -0.397 c
+38.427 -0.478 38.486 -0.54 38.556 -0.588 c
+38.622 -0.628 38.707 -0.647 38.806 -0.647 c
+38.894 -0.647 38.975 -0.628 39.056 -0.588 c
+39.144 -0.54 39.218 -0.47 39.276 -0.382 c
+39.335 -0.287 39.379 -0.177 39.409 -0.059 c
+39.445 0.066 39.467 0.206 39.467 0.353 c
+39.467 2.219 l
+40.364 2.219 l
+40.364 -0.485 l
+40.364 -0.721 l
+40.371 -0.802 40.378 -0.879 40.378 -0.956 c
+40.378 -1.147 l
+40.386 -1.199 40.393 -1.235 40.393 -1.264 c
+39.541 -1.264 l
+39.53 -1.235 39.519 -1.199 39.511 -1.147 c
+39.511 -0.956 l
+39.511 -0.889 39.504 -0.819 39.497 -0.75 c
+39.497 -0.574 l
+39.482 -0.574 l
+39.364 -0.838 39.21 -1.029 39.027 -1.147 c
+38.85 -1.264 38.647 -1.323 38.424 -1.323 c
+38.218 -1.323 38.045 -1.286 37.909 -1.22 c
+37.77 -1.154 37.66 -1.058 37.571 -0.941 c
+37.49 -0.823 37.431 -0.688 37.394 -0.53 c
+37.365 -0.364 37.35 -0.187 37.35 0 c
+37.35 2.219 l
+h
+44.527 -0.25 m
+44.527 -0.419 44.487 -0.57 44.409 -0.706 c
+44.34 -0.834 44.237 -0.948 44.101 -1.044 c
+43.972 -1.132 43.811 -1.202 43.616 -1.249 c
+43.428 -1.297 43.212 -1.323 42.969 -1.323 c
+42.742 -1.323 42.543 -1.309 42.366 -1.279 c
+42.19 -1.249 42.032 -1.202 41.896 -1.132 c
+41.757 -1.055 41.647 -0.956 41.558 -0.838 c
+41.47 -0.721 41.4 -0.574 41.352 -0.397 c
+42.161 -0.279 l
+42.179 -0.379 42.208 -0.456 42.249 -0.515 c
+42.297 -0.574 42.356 -0.617 42.425 -0.647 c
+42.491 -0.676 42.572 -0.702 42.661 -0.721 c
+42.749 -0.732 42.852 -0.735 42.969 -0.735 c
+43.065 -0.735 43.16 -0.732 43.249 -0.721 c
+43.337 -0.702 43.414 -0.676 43.484 -0.647 c
+43.55 -0.617 43.601 -0.58 43.631 -0.53 c
+43.667 -0.482 43.69 -0.419 43.69 -0.339 c
+43.69 -0.243 43.66 -0.169 43.601 -0.118 c
+43.55 -0.07 43.484 -0.029 43.395 0 c
+43.307 0.037 43.197 0.066 43.072 0.088 c
+42.954 0.118 42.822 0.147 42.676 0.176 c
+42.536 0.213 42.396 0.253 42.249 0.293 c
+42.109 0.341 41.984 0.405 41.867 0.484 c
+41.757 0.562 41.668 0.661 41.602 0.779 c
+41.533 0.897 41.5 1.047 41.5 1.234 c
+41.5 1.389 41.529 1.532 41.587 1.66 c
+41.654 1.797 41.749 1.911 41.867 1.999 c
+41.992 2.087 42.15 2.153 42.337 2.205 c
+42.521 2.252 42.734 2.278 42.969 2.278 c
+43.153 2.278 43.33 2.256 43.499 2.219 c
+43.663 2.19 43.811 2.135 43.939 2.057 c
+44.064 1.988 44.174 1.889 44.263 1.764 c
+44.351 1.646 44.409 1.502 44.44 1.338 c
+43.646 1.264 l
+43.623 1.341 43.594 1.404 43.557 1.455 c
+43.517 1.514 43.469 1.558 43.41 1.587 c
+43.359 1.624 43.297 1.65 43.219 1.66 c
+43.139 1.668 43.058 1.675 42.969 1.675 c
+42.753 1.675 42.591 1.646 42.484 1.587 c
+42.374 1.536 42.323 1.448 42.323 1.323 c
+42.323 1.242 42.341 1.18 42.381 1.132 c
+42.429 1.08 42.491 1.043 42.572 1.014 c
+42.661 0.985 42.757 0.955 42.867 0.926 c
+42.973 0.904 43.094 0.881 43.234 0.852 c
+43.388 0.823 43.546 0.783 43.704 0.735 c
+43.858 0.683 43.998 0.621 44.116 0.544 c
+44.234 0.463 44.329 0.36 44.409 0.235 c
+44.487 0.106 44.527 -0.056 44.527 -0.25 c
+f
+Q
+q 1 0 0 1 310.8155 390.0891 cm
+0 0 m
+0 0.265 -0.073 0.464 -0.22 0.603 c
+-0.36 0.75 -0.617 0.89 -0.999 1.029 c
+-1.374 1.166 -1.661 1.309 -1.866 1.455 c
+-2.065 1.603 -2.212 1.768 -2.308 1.956 c
+-2.406 2.151 -2.454 2.371 -2.454 2.617 c
+-2.454 3.036 -2.315 3.385 -2.028 3.66 c
+-1.745 3.932 -1.378 4.072 -0.926 4.072 c
+-0.613 4.072 -0.334 3.998 -0.088 3.851 c
+0.154 3.712 0.341 3.517 0.47 3.263 c
+0.607 3.017 0.676 2.749 0.676 2.455 c
+0 2.455 l
+0 2.786 -0.081 3.043 -0.235 3.219 c
+-0.393 3.404 -0.625 3.499 -0.926 3.499 c
+-1.191 3.499 -1.404 3.418 -1.558 3.263 c
+-1.705 3.117 -1.778 2.903 -1.778 2.631 c
+-1.778 2.404 -1.701 2.213 -1.543 2.058 c
+-1.378 1.912 -1.124 1.771 -0.779 1.646 c
+-0.261 1.478 0.11 1.268 0.339 1.015 c
+0.574 0.757 0.691 0.427 0.691 0.015 c
+0.691 -0.426 0.548 -0.779 0.264 -1.043 c
+-0.022 -1.3 -0.405 -1.425 -0.881 -1.425 c
+-1.198 -1.425 -1.484 -1.356 -1.749 -1.219 c
+-2.013 -1.084 -2.227 -0.893 -2.381 -0.646 c
+-2.528 -0.404 -2.602 -0.118 -2.602 0.206 c
+-1.926 0.206 l
+-1.926 -0.128 -1.833 -0.389 -1.646 -0.573 c
+-1.463 -0.76 -1.205 -0.852 -0.881 -0.852 c
+-0.588 -0.852 -0.367 -0.779 -0.22 -0.631 c
+-0.073 -0.477 0 -0.264 0 0 c
+2.896 -1.425 m
+2.396 -1.425 2.014 -1.278 1.75 -0.984 c
+1.484 -0.69 1.353 -0.257 1.353 0.324 c
+1.353 0.794 l
+1.353 1.389 1.477 1.856 1.735 2.191 c
+1.999 2.532 2.359 2.705 2.822 2.705 c
+3.281 2.705 3.624 2.55 3.851 2.249 c
+4.087 1.956 4.208 1.492 4.218 0.867 c
+4.218 0.441 l
+1.999 0.441 l
+1.999 0.353 l
+1.999 -0.08 2.076 -0.393 2.234 -0.588 c
+2.4 -0.775 2.631 -0.866 2.926 -0.866 c
+3.12 -0.866 3.293 -0.833 3.439 -0.764 c
+3.587 -0.687 3.723 -0.569 3.851 -0.411 c
+4.189 -0.823 l
+3.903 -1.227 3.473 -1.425 2.896 -1.425 c
+2.822 2.147 m
+2.547 2.147 2.344 2.051 2.22 1.867 c
+2.091 1.68 2.018 1.389 1.999 1 c
+3.572 1 l
+3.572 1.088 l
+3.55 1.47 3.484 1.738 3.366 1.897 c
+3.248 2.062 3.065 2.147 2.822 2.147 c
+6.423 -1.425 m
+5.924 -1.425 5.542 -1.278 5.278 -0.984 c
+5.012 -0.69 4.881 -0.257 4.881 0.324 c
+4.881 0.794 l
+4.881 1.389 5.005 1.856 5.263 2.191 c
+5.527 2.532 5.887 2.705 6.35 2.705 c
+6.809 2.705 7.151 2.55 7.379 2.249 c
+7.614 1.956 7.736 1.492 7.746 0.867 c
+7.746 0.441 l
+5.527 0.441 l
+5.527 0.353 l
+5.527 -0.08 5.604 -0.393 5.762 -0.588 c
+5.928 -0.775 6.159 -0.866 6.453 -0.866 c
+6.648 -0.866 6.82 -0.833 6.967 -0.764 c
+7.115 -0.687 7.25 -0.569 7.379 -0.411 c
+7.717 -0.823 l
+7.431 -1.227 7.001 -1.425 6.423 -1.425 c
+6.35 2.147 m
+6.074 2.147 5.872 2.051 5.748 1.867 c
+5.619 1.68 5.546 1.389 5.527 1 c
+7.1 1 l
+7.1 1.088 l
+7.078 1.47 7.011 1.738 6.894 1.897 c
+6.776 2.062 6.593 2.147 6.35 2.147 c
+11.098 3.587 m
+11.098 2.631 l
+11.701 2.631 l
+11.701 2.103 l
+11.098 2.103 l
+11.098 -0.367 l
+11.098 -0.525 11.12 -0.643 11.171 -0.72 c
+11.231 -0.801 11.318 -0.837 11.436 -0.837 c
+11.524 -0.837 11.612 -0.823 11.701 -0.793 c
+11.701 -1.352 l
+11.553 -1.4 11.399 -1.425 11.245 -1.425 c
+10.988 -1.425 10.793 -1.334 10.657 -1.146 c
+10.517 -0.962 10.452 -0.702 10.452 -0.367 c
+10.452 2.103 l
+9.849 2.103 l
+9.849 2.631 l
+10.452 2.631 l
+10.452 3.587 l
+h
+13.112 2.22 m
+13.365 2.544 13.685 2.705 14.067 2.705 c
+14.772 2.705 15.129 2.234 15.14 1.294 c
+15.14 -1.352 l
+14.493 -1.352 l
+14.493 1.264 l
+14.493 1.577 14.438 1.798 14.331 1.926 c
+14.221 2.051 14.067 2.117 13.861 2.117 c
+13.704 2.117 13.556 2.062 13.421 1.956 c
+13.292 1.845 13.189 1.709 13.112 1.544 c
+13.112 -1.352 l
+12.465 -1.352 l
+12.465 4.293 l
+13.112 4.293 l
+h
+17.521 -1.425 m
+17.022 -1.425 16.64 -1.278 16.375 -0.984 c
+16.11 -0.69 15.978 -0.257 15.978 0.324 c
+15.978 0.794 l
+15.978 1.389 16.103 1.856 16.36 2.191 c
+16.625 2.532 16.985 2.705 17.448 2.705 c
+17.907 2.705 18.249 2.55 18.477 2.249 c
+18.712 1.956 18.834 1.492 18.844 0.867 c
+18.844 0.441 l
+16.625 0.441 l
+16.625 0.353 l
+16.625 -0.08 16.702 -0.393 16.86 -0.588 c
+17.026 -0.775 17.257 -0.866 17.55 -0.866 c
+17.745 -0.866 17.918 -0.833 18.065 -0.764 c
+18.213 -0.687 18.348 -0.569 18.477 -0.411 c
+18.815 -0.823 l
+18.528 -1.227 18.098 -1.425 17.521 -1.425 c
+17.448 2.147 m
+17.172 2.147 16.97 2.051 16.845 1.867 c
+16.717 1.68 16.644 1.389 16.625 1 c
+18.198 1 l
+18.198 1.088 l
+18.175 1.47 18.109 1.738 17.992 1.897 c
+17.874 2.062 17.691 2.147 17.448 2.147 c
+23.283 -0.338 m
+23.283 -0.191 23.229 -0.07 23.122 0.03 c
+23.011 0.125 22.805 0.243 22.504 0.383 c
+22.159 0.53 21.916 0.651 21.77 0.75 c
+21.622 0.857 21.512 0.975 21.446 1.103 c
+21.376 1.228 21.344 1.386 21.344 1.573 c
+21.344 1.897 21.461 2.165 21.696 2.382 c
+21.931 2.595 22.233 2.705 22.607 2.705 c
+22.99 2.705 23.298 2.591 23.534 2.367 c
+23.769 2.139 23.886 1.852 23.886 1.5 c
+23.239 1.5 l
+23.239 1.676 23.181 1.827 23.063 1.956 c
+22.946 2.08 22.791 2.147 22.607 2.147 c
+22.408 2.147 22.258 2.091 22.152 1.985 c
+22.042 1.885 21.99 1.754 21.99 1.588 c
+21.99 1.459 22.026 1.353 22.107 1.264 c
+22.185 1.183 22.375 1.081 22.681 0.956 c
+23.158 0.769 23.489 0.581 23.665 0.397 c
+23.842 0.221 23.931 -0.007 23.931 -0.278 c
+23.931 -0.631 23.805 -0.911 23.563 -1.117 c
+23.328 -1.323 23.011 -1.425 22.622 -1.425 c
+22.2 -1.425 21.861 -1.308 21.608 -1.072 c
+21.35 -0.83 21.226 -0.525 21.226 -0.161 c
+21.872 -0.161 l
+21.88 -0.389 21.949 -0.565 22.078 -0.69 c
+22.203 -0.808 22.387 -0.866 22.622 -0.866 c
+22.836 -0.866 22.996 -0.819 23.107 -0.72 c
+23.225 -0.625 23.283 -0.496 23.283 -0.338 c
+25.62 3.587 m
+25.62 2.631 l
+26.223 2.631 l
+26.223 2.103 l
+25.62 2.103 l
+25.62 -0.367 l
+25.62 -0.525 25.643 -0.643 25.694 -0.72 c
+25.753 -0.801 25.841 -0.837 25.959 -0.837 c
+26.047 -0.837 26.135 -0.823 26.223 -0.793 c
+26.223 -1.352 l
+26.076 -1.4 25.922 -1.425 25.768 -1.425 c
+25.51 -1.425 25.315 -1.334 25.18 -1.146 c
+25.04 -0.962 24.974 -0.702 24.974 -0.367 c
+24.974 2.103 l
+24.371 2.103 l
+24.371 2.631 l
+24.974 2.631 l
+24.974 3.587 l
+h
+29.031 -1.352 m
+28.991 -1.263 28.964 -1.117 28.957 -0.911 c
+28.722 -1.256 28.428 -1.425 28.075 -1.425 c
+27.711 -1.425 27.428 -1.33 27.223 -1.132 c
+27.025 -0.926 26.929 -0.639 26.929 -0.264 c
+26.929 0.136 27.065 0.456 27.341 0.691 c
+27.613 0.934 27.987 1.058 28.457 1.058 c
+28.943 1.058 l
+28.943 1.485 l
+28.943 1.721 28.887 1.885 28.781 1.985 c
+28.671 2.091 28.509 2.147 28.296 2.147 c
+28.097 2.147 27.935 2.087 27.811 1.97 c
+27.693 1.852 27.634 1.706 27.634 1.529 c
+26.988 1.529 l
+26.988 1.723 27.046 1.915 27.164 2.103 c
+27.289 2.286 27.451 2.433 27.649 2.544 c
+27.855 2.65 28.083 2.705 28.34 2.705 c
+28.741 2.705 29.045 2.602 29.251 2.396 c
+29.464 2.191 29.579 1.897 29.589 1.515 c
+29.589 -0.5 l
+29.589 -0.804 29.626 -1.069 29.707 -1.294 c
+29.707 -1.352 l
+h
+28.164 -0.837 m
+28.328 -0.837 28.48 -0.793 28.619 -0.706 c
+28.766 -0.617 28.873 -0.507 28.943 -0.367 c
+28.943 0.574 l
+28.575 0.574 l
+28.259 0.574 28.016 0.504 27.84 0.368 c
+27.663 0.239 27.576 0.052 27.576 -0.191 c
+27.576 -0.419 27.62 -0.584 27.708 -0.69 c
+27.796 -0.789 27.947 -0.837 28.164 -0.837 c
+31.441 3.587 m
+31.441 2.631 l
+32.044 2.631 l
+32.044 2.103 l
+31.441 2.103 l
+31.441 -0.367 l
+31.441 -0.525 31.463 -0.643 31.515 -0.72 c
+31.574 -0.801 31.662 -0.837 31.779 -0.837 c
+31.868 -0.837 31.956 -0.823 32.044 -0.793 c
+32.044 -1.352 l
+31.897 -1.4 31.742 -1.425 31.588 -1.425 c
+31.331 -1.425 31.137 -1.334 31 -1.146 c
+30.861 -0.962 30.794 -0.702 30.794 -0.367 c
+30.794 2.103 l
+30.192 2.103 l
+30.192 2.631 l
+30.794 2.631 l
+30.794 3.587 l
+h
+34.837 -0.999 m
+34.62 -1.286 34.308 -1.425 33.896 -1.425 c
+33.533 -1.425 33.257 -1.304 33.073 -1.058 c
+32.897 -0.804 32.801 -0.44 32.794 0.03 c
+32.794 2.631 l
+33.44 2.631 l
+33.44 0.088 l
+33.44 -0.54 33.624 -0.852 33.999 -0.852 c
+34.4 -0.852 34.676 -0.675 34.822 -0.323 c
+34.822 2.631 l
+35.469 2.631 l
+35.469 -1.352 l
+34.852 -1.352 l
+h
+38.394 -0.338 m
+38.394 -0.191 38.339 -0.07 38.233 0.03 c
+38.123 0.125 37.917 0.243 37.615 0.383 c
+37.269 0.53 37.027 0.651 36.88 0.75 c
+36.733 0.857 36.623 0.975 36.557 1.103 c
+36.487 1.228 36.454 1.386 36.454 1.573 c
+36.454 1.897 36.571 2.165 36.806 2.382 c
+37.042 2.595 37.343 2.705 37.718 2.705 c
+38.1 2.705 38.409 2.591 38.644 2.367 c
+38.879 2.139 38.996 1.852 38.996 1.5 c
+38.35 1.5 l
+38.35 1.676 38.291 1.827 38.173 1.956 c
+38.056 2.08 37.901 2.147 37.718 2.147 c
+37.52 2.147 37.369 2.091 37.263 1.985 c
+37.152 1.885 37.101 1.754 37.101 1.588 c
+37.101 1.459 37.138 1.353 37.218 1.264 c
+37.296 1.183 37.487 1.081 37.791 0.956 c
+38.269 0.769 38.599 0.581 38.776 0.397 c
+38.952 0.221 39.041 -0.007 39.041 -0.278 c
+39.041 -0.631 38.916 -0.911 38.674 -1.117 c
+38.439 -1.323 38.123 -1.425 37.733 -1.425 c
+37.31 -1.425 36.972 -1.308 36.718 -1.072 c
+36.461 -0.83 36.336 -0.525 36.336 -0.161 c
+36.983 -0.161 l
+36.99 -0.389 37.06 -0.565 37.188 -0.69 c
+37.314 -0.808 37.498 -0.866 37.733 -0.866 c
+37.946 -0.866 38.107 -0.819 38.218 -0.72 c
+38.335 -0.625 38.394 -0.496 38.394 -0.338 c
+41.466 0.823 m
+41.466 1.401 41.602 1.856 41.878 2.191 c
+42.161 2.532 42.532 2.705 42.995 2.705 c
+43.455 2.705 43.822 2.536 44.097 2.205 c
+44.38 1.881 44.527 1.434 44.538 0.867 c
+44.538 0.441 l
+44.538 -0.128 44.395 -0.584 44.112 -0.926 c
+43.837 -1.26 43.469 -1.425 43.01 -1.425 c
+42.547 -1.425 42.175 -1.263 41.892 -0.941 c
+41.616 -0.61 41.473 -0.168 41.466 0.383 c
+h
+42.113 0.441 m
+42.113 0.038 42.19 -0.278 42.348 -0.514 c
+42.514 -0.749 42.734 -0.866 43.01 -0.866 c
+43.575 -0.866 43.87 -0.455 43.891 0.368 c
+43.891 0.823 l
+43.891 1.224 43.807 1.544 43.642 1.779 c
+43.484 2.022 43.267 2.147 42.995 2.147 c
+42.73 2.147 42.514 2.022 42.348 1.779 c
+42.19 1.544 42.113 1.224 42.113 0.823 c
+h
+45.67 -1.352 m
+45.67 2.103 l
+45.14 2.103 l
+45.14 2.631 l
+45.67 2.631 l
+45.67 3.088 l
+45.67 3.487 45.766 3.801 45.965 4.028 c
+46.17 4.252 46.449 4.366 46.802 4.366 c
+46.938 4.366 47.07 4.344 47.199 4.308 c
+47.17 3.763 l
+47.07 3.782 46.971 3.793 46.875 3.793 c
+46.501 3.793 46.316 3.528 46.316 2.999 c
+46.316 2.631 l
+46.993 2.631 l
+46.993 2.103 l
+46.316 2.103 l
+46.316 -1.352 l
+h
+50.565 -0.264 m
+51.285 2.631 l
+51.976 2.631 l
+50.682 -1.911 l
+50.584 -2.252 50.44 -2.513 50.256 -2.69 c
+50.079 -2.865 49.878 -2.954 49.653 -2.954 c
+49.566 -2.954 49.452 -2.932 49.315 -2.896 c
+49.315 -2.352 l
+49.462 -2.366 l
+49.647 -2.366 49.793 -2.322 49.903 -2.234 c
+50.01 -2.146 50.098 -1.988 50.168 -1.764 c
+50.285 -1.323 l
+49.124 2.631 l
+49.83 2.631 l
+h
+52.417 0.823 m
+52.417 1.401 52.553 1.856 52.828 2.191 c
+53.111 2.532 53.483 2.705 53.946 2.705 c
+54.405 2.705 54.773 2.536 55.048 2.205 c
+55.331 1.881 55.478 1.434 55.489 0.867 c
+55.489 0.441 l
+55.489 -0.128 55.346 -0.584 55.062 -0.926 c
+54.787 -1.26 54.42 -1.425 53.961 -1.425 c
+53.497 -1.425 53.126 -1.263 52.843 -0.941 c
+52.568 -0.61 52.425 -0.168 52.417 0.383 c
+h
+53.063 0.441 m
+53.063 0.038 53.141 -0.278 53.299 -0.514 c
+53.464 -0.749 53.685 -0.866 53.961 -0.866 c
+54.526 -0.866 54.821 -0.455 54.842 0.368 c
+54.842 0.823 l
+54.842 1.224 54.758 1.544 54.592 1.779 c
+54.434 2.022 54.218 2.147 53.946 2.147 c
+53.681 2.147 53.464 2.022 53.299 1.779 c
+53.141 1.544 53.063 1.224 53.063 0.823 c
+h
+58.355 -0.999 m
+58.139 -1.286 57.826 -1.425 57.414 -1.425 c
+57.051 -1.425 56.776 -1.304 56.591 -1.058 c
+56.415 -0.804 56.319 -0.44 56.313 0.03 c
+56.313 2.631 l
+56.959 2.631 l
+56.959 0.088 l
+56.959 -0.54 57.142 -0.852 57.518 -0.852 c
+57.918 -0.852 58.194 -0.675 58.341 -0.323 c
+58.341 2.631 l
+58.987 2.631 l
+58.987 -1.352 l
+58.37 -1.352 l
+h
+61.618 2.014 m
+61.53 2.033 61.431 2.043 61.325 2.043 c
+60.99 2.043 60.755 1.86 60.619 1.5 c
+60.619 -1.352 l
+59.972 -1.352 l
+59.972 2.631 l
+60.604 2.631 l
+60.619 2.22 l
+60.795 2.544 61.038 2.705 61.354 2.705 c
+61.46 2.705 61.549 2.683 61.618 2.646 c
+h
+66.954 -0.205 m
+67.557 2.631 l
+68.204 2.631 l
+67.219 -1.352 l
+66.704 -1.352 l
+65.925 1.5 l
+65.175 -1.352 l
+64.647 -1.352 l
+63.691 2.631 l
+64.323 2.631 l
+64.94 -0.132 l
+65.676 2.631 l
+66.19 2.631 l
+h
+68.747 0.823 m
+68.747 1.401 68.884 1.856 69.159 2.191 c
+69.443 2.532 69.813 2.705 70.276 2.705 c
+70.736 2.705 71.103 2.536 71.379 2.205 c
+71.662 1.881 71.809 1.434 71.82 0.867 c
+71.82 0.441 l
+71.82 -0.128 71.677 -0.584 71.394 -0.926 c
+71.118 -1.26 70.75 -1.425 70.291 -1.425 c
+69.828 -1.425 69.457 -1.263 69.174 -0.941 c
+68.898 -0.61 68.755 -0.168 68.747 0.383 c
+h
+69.395 0.441 m
+69.395 0.038 69.472 -0.278 69.63 -0.514 c
+69.795 -0.749 70.015 -0.866 70.291 -0.866 c
+70.857 -0.866 71.151 -0.455 71.173 0.368 c
+71.173 0.823 l
+71.173 1.224 71.089 1.544 70.923 1.779 c
+70.765 2.022 70.548 2.147 70.276 2.147 c
+70.012 2.147 69.795 2.022 69.63 1.779 c
+69.472 1.544 69.395 1.224 69.395 0.823 c
+h
+74.303 2.014 m
+74.216 2.033 74.116 2.043 74.01 2.043 c
+73.676 2.043 73.441 1.86 73.304 1.5 c
+73.304 -1.352 l
+72.657 -1.352 l
+72.657 2.631 l
+73.289 2.631 l
+73.304 2.22 l
+73.481 2.544 73.723 2.705 74.039 2.705 c
+74.146 2.705 74.234 2.683 74.303 2.646 c
+h
+75.95 0.47 m
+75.612 0.074 l
+75.612 -1.352 l
+74.951 -1.352 l
+74.951 4.293 l
+75.612 4.293 l
+75.612 0.912 l
+76.847 2.631 l
+77.626 2.631 l
+76.362 0.971 l
+77.788 -1.352 l
+77.038 -1.352 l
+h
+78.39 -0.999 m
+78.39 -0.881 78.423 -0.786 78.493 -0.706 c
+78.559 -0.628 78.662 -0.588 78.802 -0.588 c
+78.949 -0.588 79.055 -0.628 79.126 -0.706 c
+79.203 -0.786 79.242 -0.881 79.242 -0.999 c
+79.242 -1.109 79.203 -1.201 79.126 -1.278 c
+79.055 -1.356 78.949 -1.396 78.802 -1.396 c
+78.662 -1.396 78.559 -1.356 78.493 -1.278 c
+78.423 -1.201 78.39 -1.109 78.39 -0.999 c
+85.636 -1.352 m
+84.961 -1.352 l
+82.814 2.779 l
+82.814 -1.352 l
+82.139 -1.352 l
+82.139 3.998 l
+82.814 3.998 l
+84.975 -0.147 l
+84.975 3.998 l
+85.636 3.998 l
+h
+88.136 -1.425 m
+87.636 -1.425 87.254 -1.278 86.989 -0.984 c
+86.725 -0.69 86.592 -0.257 86.592 0.324 c
+86.592 0.794 l
+86.592 1.389 86.717 1.856 86.974 2.191 c
+87.239 2.532 87.599 2.705 88.063 2.705 c
+88.522 2.705 88.863 2.55 89.091 2.249 c
+89.326 1.956 89.447 1.492 89.459 0.867 c
+89.459 0.441 l
+87.239 0.441 l
+87.239 0.353 l
+87.239 -0.08 87.317 -0.393 87.474 -0.588 c
+87.639 -0.775 87.871 -0.866 88.165 -0.866 c
+88.36 -0.866 88.533 -0.833 88.68 -0.764 c
+88.827 -0.687 88.963 -0.569 89.091 -0.411 c
+89.43 -0.823 l
+89.143 -1.227 88.713 -1.425 88.136 -1.425 c
+88.063 2.147 m
+87.787 2.147 87.585 2.051 87.46 1.867 c
+87.331 1.68 87.257 1.389 87.239 1 c
+88.811 1 l
+88.811 1.088 l
+88.79 1.47 88.724 1.738 88.606 1.897 c
+88.489 2.062 88.304 2.147 88.063 2.147 c
+93.207 -0.205 m
+93.81 2.631 l
+94.456 2.631 l
+93.472 -1.352 l
+92.957 -1.352 l
+92.177 1.5 l
+91.429 -1.352 l
+90.899 -1.352 l
+89.944 2.631 l
+90.575 2.631 l
+91.193 -0.132 l
+91.928 2.631 l
+92.443 2.631 l
+h
+94.691 -2.425 m
+94.294 -2.16 l
+94.529 -1.837 94.651 -1.502 94.662 -1.161 c
+94.662 -0.544 l
+95.323 -0.544 l
+95.323 -1.072 l
+95.323 -1.33 95.257 -1.576 95.132 -1.822 c
+95.015 -2.065 94.868 -2.267 94.691 -2.425 c
+99.822 -0.338 m
+99.822 -0.191 99.766 -0.07 99.66 0.03 c
+99.549 0.125 99.344 0.243 99.042 0.383 c
+98.697 0.53 98.454 0.651 98.307 0.75 c
+98.161 0.857 98.05 0.975 97.984 1.103 c
+97.914 1.228 97.881 1.386 97.881 1.573 c
+97.881 1.897 97.999 2.165 98.234 2.382 c
+98.469 2.595 98.77 2.705 99.145 2.705 c
+99.527 2.705 99.836 2.591 100.071 2.367 c
+100.306 2.139 100.424 1.852 100.424 1.5 c
+99.778 1.5 l
+99.778 1.676 99.718 1.827 99.601 1.956 c
+99.483 2.08 99.329 2.147 99.145 2.147 c
+98.947 2.147 98.796 2.091 98.689 1.985 c
+98.579 1.885 98.527 1.754 98.527 1.588 c
+98.527 1.459 98.565 1.353 98.646 1.264 c
+98.723 1.183 98.914 1.081 99.219 0.956 c
+99.697 0.769 100.027 0.581 100.204 0.397 c
+100.38 0.221 100.468 -0.007 100.468 -0.278 c
+100.468 -0.631 100.343 -0.911 100.1 -1.117 c
+99.865 -1.323 99.549 -1.425 99.16 -1.425 c
+98.737 -1.425 98.399 -1.308 98.145 -1.072 c
+97.889 -0.83 97.764 -0.525 97.764 -0.161 c
+98.411 -0.161 l
+98.417 -0.389 98.488 -0.565 98.616 -0.69 c
+98.741 -0.808 98.924 -0.866 99.16 -0.866 c
+99.373 -0.866 99.535 -0.819 99.645 -0.72 c
+99.763 -0.625 99.822 -0.496 99.822 -0.338 c
+102.159 3.587 m
+102.159 2.631 l
+102.761 2.631 l
+102.761 2.103 l
+102.159 2.103 l
+102.159 -0.367 l
+102.159 -0.525 102.18 -0.643 102.232 -0.72 c
+102.29 -0.801 102.379 -0.837 102.496 -0.837 c
+102.585 -0.837 102.673 -0.823 102.761 -0.793 c
+102.761 -1.352 l
+102.614 -1.4 102.46 -1.425 102.305 -1.425 c
+102.049 -1.425 101.854 -1.334 101.717 -1.146 c
+101.578 -0.962 101.511 -0.702 101.511 -0.367 c
+101.511 2.103 l
+100.909 2.103 l
+100.909 2.631 l
+101.511 2.631 l
+101.511 3.587 l
+h
+105.569 -1.352 m
+105.528 -1.263 105.503 -1.117 105.495 -0.911 c
+105.26 -1.256 104.966 -1.425 104.613 -1.425 c
+104.25 -1.425 103.967 -1.33 103.761 -1.132 c
+103.562 -0.926 103.466 -0.639 103.466 -0.264 c
+103.466 0.136 103.603 0.456 103.878 0.691 c
+104.15 0.934 104.526 1.058 104.996 1.058 c
+105.48 1.058 l
+105.48 1.485 l
+105.48 1.721 105.426 1.885 105.319 1.985 c
+105.209 2.091 105.047 2.147 104.834 2.147 c
+104.636 2.147 104.474 2.087 104.349 1.97 c
+104.231 1.852 104.172 1.706 104.172 1.529 c
+103.526 1.529 l
+103.526 1.723 103.585 1.915 103.701 2.103 c
+103.827 2.286 103.988 2.433 104.187 2.544 c
+104.393 2.65 104.621 2.705 104.877 2.705 c
+105.278 2.705 105.583 2.602 105.789 2.396 c
+106.003 2.191 106.116 1.897 106.128 1.515 c
+106.128 -0.5 l
+106.128 -0.804 106.164 -1.069 106.245 -1.294 c
+106.245 -1.352 l
+h
+104.701 -0.837 m
+104.867 -0.837 105.018 -0.793 105.157 -0.706 c
+105.304 -0.617 105.411 -0.507 105.48 -0.367 c
+105.48 0.574 l
+105.113 0.574 l
+104.797 0.574 104.555 0.504 104.378 0.368 c
+104.202 0.239 104.114 0.052 104.114 -0.191 c
+104.114 -0.419 104.158 -0.584 104.246 -0.69 c
+104.334 -0.789 104.485 -0.837 104.701 -0.837 c
+106.994 0.823 m
+106.994 1.441 107.105 1.904 107.333 2.22 c
+107.557 2.544 107.892 2.705 108.332 2.705 c
+108.733 2.705 109.037 2.529 109.243 2.176 c
+109.288 2.631 l
+109.876 2.631 l
+109.876 -1.396 l
+109.876 -1.884 109.747 -2.263 109.494 -2.528 c
+109.236 -2.792 108.883 -2.925 108.435 -2.925 c
+108.237 -2.925 108.016 -2.873 107.774 -2.778 c
+107.527 -2.678 107.348 -2.557 107.229 -2.41 c
+107.495 -1.969 l
+107.759 -2.234 108.056 -2.366 108.391 -2.366 c
+108.927 -2.366 109.203 -2.072 109.214 -1.484 c
+109.214 -0.955 l
+109.008 -1.271 108.707 -1.425 108.318 -1.425 c
+107.906 -1.425 107.583 -1.275 107.348 -0.97 c
+107.119 -0.658 107.002 -0.205 106.994 0.383 c
+h
+107.656 0.441 m
+107.656 0 107.718 -0.33 107.847 -0.544 c
+107.972 -0.749 108.189 -0.852 108.494 -0.852 c
+108.817 -0.852 109.056 -0.687 109.214 -0.353 c
+109.214 1.632 l
+109.045 1.956 108.806 2.117 108.494 2.117 c
+108.2 2.117 107.983 2.014 107.847 1.808 c
+107.718 1.603 107.656 1.279 107.656 0.838 c
+h
+112.257 -1.425 m
+111.757 -1.425 111.375 -1.278 111.111 -0.984 c
+110.845 -0.69 110.714 -0.257 110.714 0.324 c
+110.714 0.794 l
+110.714 1.389 110.838 1.856 111.096 2.191 c
+111.36 2.532 111.72 2.705 112.183 2.705 c
+112.642 2.705 112.985 2.55 113.212 2.249 c
+113.448 1.956 113.569 1.492 113.579 0.867 c
+113.579 0.441 l
+111.36 0.441 l
+111.36 0.353 l
+111.36 -0.08 111.437 -0.393 111.595 -0.588 c
+111.761 -0.775 111.992 -0.866 112.287 -0.866 c
+112.481 -0.866 112.654 -0.833 112.8 -0.764 c
+112.948 -0.687 113.083 -0.569 113.212 -0.411 c
+113.55 -0.823 l
+113.264 -1.227 112.834 -1.425 112.257 -1.425 c
+112.183 2.147 m
+111.908 2.147 111.705 2.051 111.581 1.867 c
+111.452 1.68 111.379 1.389 111.36 1 c
+112.933 1 l
+112.933 1.088 l
+112.911 1.47 112.845 1.738 112.727 1.897 c
+112.609 2.062 112.426 2.147 112.183 2.147 c
+114.226 0.823 m
+114.226 1.43 114.337 1.897 114.564 2.22 c
+114.799 2.544 115.127 2.705 115.549 2.705 c
+115.931 2.705 116.229 2.547 116.446 2.234 c
+116.446 4.293 l
+117.093 4.293 l
+117.093 -1.352 l
+116.505 -1.352 l
+116.461 -0.926 l
+116.255 -1.26 115.95 -1.425 115.549 -1.425 c
+115.138 -1.425 114.814 -1.271 114.579 -0.955 c
+114.344 -0.631 114.226 -0.176 114.226 0.412 c
+h
+114.874 0.441 m
+114.874 0 114.936 -0.33 115.065 -0.544 c
+115.2 -0.749 115.421 -0.852 115.726 -0.852 c
+116.05 -0.852 116.288 -0.69 116.446 -0.367 c
+116.446 1.646 l
+116.277 1.959 116.038 2.117 115.726 2.117 c
+115.421 2.117 115.2 2.014 115.065 1.808 c
+114.936 1.603 114.874 1.279 114.874 0.838 c
+h
+118.107 -2.425 m
+117.71 -2.16 l
+117.945 -1.837 118.067 -1.502 118.078 -1.161 c
+118.078 -0.544 l
+118.739 -0.544 l
+118.739 -1.072 l
+118.739 -1.33 118.673 -1.576 118.548 -1.822 c
+118.431 -2.065 118.283 -2.267 118.107 -2.425 c
+121.914 2.631 m
+121.929 2.264 l
+122.171 2.558 122.491 2.705 122.884 2.705 c
+123.325 2.705 123.634 2.507 123.811 2.117 c
+124.064 2.507 124.413 2.705 124.854 2.705 c
+125.589 2.705 125.964 2.242 125.986 1.324 c
+125.986 -1.352 l
+125.339 -1.352 l
+125.339 1.264 l
+125.339 1.559 125.284 1.771 125.178 1.912 c
+125.078 2.047 124.906 2.117 124.663 2.117 c
+124.465 2.117 124.303 2.037 124.178 1.881 c
+124.06 1.735 123.99 1.544 123.972 1.309 c
+123.972 -1.352 l
+123.31 -1.352 l
+123.31 1.294 l
+123.31 1.841 123.09 2.117 122.649 2.117 c
+122.315 2.117 122.08 1.956 121.943 1.632 c
+121.943 -1.352 l
+121.297 -1.352 l
+121.297 2.631 l
+h
+126.824 0.823 m
+126.824 1.401 126.959 1.856 127.235 2.191 c
+127.518 2.532 127.889 2.705 128.353 2.705 c
+128.812 2.705 129.18 2.536 129.455 2.205 c
+129.737 1.881 129.885 1.434 129.895 0.867 c
+129.895 0.441 l
+129.895 -0.128 129.752 -0.584 129.469 -0.926 c
+129.194 -1.26 128.827 -1.425 128.367 -1.425 c
+127.904 -1.425 127.533 -1.263 127.25 -0.941 c
+126.974 -0.61 126.831 -0.168 126.824 0.383 c
+h
+127.47 0.441 m
+127.47 0.038 127.547 -0.278 127.705 -0.514 c
+127.871 -0.749 128.091 -0.866 128.367 -0.866 c
+128.933 -0.866 129.227 -0.455 129.249 0.368 c
+129.249 0.823 l
+129.249 1.224 129.164 1.544 128.999 1.779 c
+128.841 2.022 128.624 2.147 128.353 2.147 c
+128.087 2.147 127.871 2.022 127.705 1.779 c
+127.547 1.544 127.47 1.224 127.47 0.823 c
+h
+130.601 0.823 m
+130.601 1.43 130.711 1.897 130.94 2.22 c
+131.175 2.544 131.501 2.705 131.924 2.705 c
+132.307 2.705 132.604 2.547 132.821 2.234 c
+132.821 4.293 l
+133.467 4.293 l
+133.467 -1.352 l
+132.879 -1.352 l
+132.835 -0.926 l
+132.629 -1.26 132.324 -1.425 131.924 -1.425 c
+131.513 -1.425 131.189 -1.271 130.954 -0.955 c
+130.719 -0.631 130.601 -0.176 130.601 0.412 c
+h
+131.248 0.441 m
+131.248 0 131.31 -0.33 131.439 -0.544 c
+131.575 -0.749 131.796 -0.852 132.101 -0.852 c
+132.424 -0.852 132.663 -0.69 132.821 -0.367 c
+132.821 1.646 l
+132.652 1.959 132.413 2.117 132.101 2.117 c
+131.796 2.117 131.575 2.014 131.439 1.808 c
+131.31 1.603 131.248 1.279 131.248 0.838 c
+h
+135.173 -1.352 -0.647 3.983 re
+135.216 3.675 m
+135.216 3.565 135.187 3.473 135.129 3.396 c
+135.069 3.326 134.974 3.293 134.849 3.293 c
+134.732 3.293 134.636 3.326 134.57 3.396 c
+134.511 3.473 134.482 3.565 134.482 3.675 c
+134.482 3.793 134.511 3.884 134.57 3.955 c
+134.636 4.032 134.732 4.072 134.849 4.072 c
+134.974 4.072 135.069 4.032 135.129 3.955 c
+135.187 3.874 135.216 3.782 135.216 3.675 c
+136.363 -1.352 m
+136.363 2.103 l
+135.848 2.103 l
+135.848 2.631 l
+136.363 2.631 l
+136.363 2.999 l
+136.371 3.429 136.484 3.763 136.702 3.998 c
+136.926 4.241 137.238 4.366 137.642 4.366 c
+137.789 4.366 137.928 4.344 138.069 4.308 c
+138.215 4.267 138.366 4.212 138.524 4.146 c
+138.406 3.572 l
+138.171 3.697 137.928 3.763 137.687 3.763 c
+137.44 3.763 137.267 3.693 137.172 3.558 c
+137.072 3.429 137.024 3.234 137.024 2.97 c
+137.024 2.631 l
+137.672 2.631 l
+137.672 2.103 l
+137.024 2.103 l
+137.024 -1.352 l
+h
+138.832 -1.352 -0.646 3.983 re
+141.302 -1.425 m
+140.802 -1.425 140.42 -1.278 140.155 -0.984 c
+139.891 -0.69 139.759 -0.257 139.759 0.324 c
+139.759 0.794 l
+139.759 1.389 139.883 1.856 140.141 2.191 c
+140.405 2.532 140.766 2.705 141.229 2.705 c
+141.688 2.705 142.03 2.55 142.258 2.249 c
+142.493 1.956 142.614 1.492 142.625 0.867 c
+142.625 0.441 l
+140.405 0.441 l
+140.405 0.353 l
+140.405 -0.08 140.483 -0.393 140.641 -0.588 c
+140.806 -0.775 141.038 -0.866 141.331 -0.866 c
+141.527 -0.866 141.699 -0.833 141.846 -0.764 c
+141.993 -0.687 142.129 -0.569 142.258 -0.411 c
+142.595 -0.823 l
+142.309 -1.227 141.879 -1.425 141.302 -1.425 c
+141.229 2.147 m
+140.953 2.147 140.751 2.051 140.626 1.867 c
+140.498 1.68 140.424 1.389 140.405 1 c
+141.978 1 l
+141.978 1.088 l
+141.957 1.47 141.89 1.738 141.772 1.897 c
+141.655 2.062 141.471 2.147 141.229 2.147 c
+143.272 0.823 m
+143.272 1.43 143.382 1.897 143.61 2.22 c
+143.845 2.544 144.172 2.705 144.594 2.705 c
+144.977 2.705 145.275 2.547 145.491 2.234 c
+145.491 4.293 l
+146.138 4.293 l
+146.138 -1.352 l
+145.55 -1.352 l
+145.506 -0.926 l
+145.3 -1.26 144.995 -1.425 144.594 -1.425 c
+144.183 -1.425 143.86 -1.271 143.625 -0.955 c
+143.389 -0.631 143.272 -0.176 143.272 0.412 c
+h
+143.918 0.441 m
+143.918 0 143.981 -0.33 144.11 -0.544 c
+144.245 -0.749 144.467 -0.852 144.771 -0.852 c
+145.094 -0.852 145.333 -0.69 145.491 -0.367 c
+145.491 1.646 l
+145.323 1.959 145.084 2.117 144.771 2.117 c
+144.467 2.117 144.245 2.014 144.11 1.808 c
+143.981 1.603 143.918 1.279 143.918 0.838 c
+h
+149.034 -1.352 m
+149.034 2.103 l
+148.519 2.103 l
+148.519 2.631 l
+149.034 2.631 l
+149.034 2.999 l
+149.041 3.429 149.155 3.763 149.372 3.998 c
+149.596 4.241 149.909 4.366 150.312 4.366 c
+150.46 4.366 150.599 4.344 150.738 4.308 c
+150.886 4.267 151.037 4.212 151.195 4.146 c
+151.077 3.572 l
+150.842 3.697 150.599 3.763 150.357 3.763 c
+150.111 3.763 149.938 3.693 149.842 3.558 c
+149.743 3.429 149.695 3.234 149.695 2.97 c
+149.695 2.631 l
+150.342 2.631 l
+150.342 2.103 l
+149.695 2.103 l
+149.695 -1.352 l
+h
+151.503 -1.352 -0.646 3.983 re
+153.252 -1.352 -0.646 5.644 re
+155.692 -1.425 m
+155.193 -1.425 154.811 -1.278 154.546 -0.984 c
+154.281 -0.69 154.15 -0.257 154.15 0.324 c
+154.15 0.794 l
+154.15 1.389 154.274 1.856 154.531 2.191 c
+154.796 2.532 155.156 2.705 155.619 2.705 c
+156.078 2.705 156.421 2.55 156.648 2.249 c
+156.883 1.956 157.005 1.492 157.015 0.867 c
+157.015 0.441 l
+154.796 0.441 l
+154.796 0.353 l
+154.796 -0.08 154.873 -0.393 155.031 -0.588 c
+155.197 -0.775 155.428 -0.866 155.722 -0.866 c
+155.916 -0.866 156.089 -0.833 156.236 -0.764 c
+156.383 -0.687 156.519 -0.569 156.648 -0.411 c
+156.986 -0.823 l
+156.699 -1.227 156.269 -1.425 155.692 -1.425 c
+155.619 2.147 m
+155.343 2.147 155.141 2.051 155.016 1.867 c
+154.888 1.68 154.815 1.389 154.796 1 c
+156.369 1 l
+156.369 1.088 l
+156.346 1.47 156.28 1.738 156.163 1.897 c
+156.045 2.062 155.862 2.147 155.619 2.147 c
+159.735 -0.338 m
+159.735 -0.191 159.679 -0.07 159.573 0.03 c
+159.463 0.125 159.257 0.243 158.956 0.383 c
+158.611 0.53 158.368 0.651 158.221 0.75 c
+158.073 0.857 157.963 0.975 157.897 1.103 c
+157.828 1.228 157.794 1.386 157.794 1.573 c
+157.794 1.897 157.913 2.165 158.148 2.382 c
+158.383 2.595 158.684 2.705 159.058 2.705 c
+159.44 2.705 159.75 2.591 159.985 2.367 c
+160.22 2.139 160.338 1.852 160.338 1.5 c
+159.691 1.5 l
+159.691 1.676 159.632 1.827 159.515 1.956 c
+159.397 2.08 159.243 2.147 159.058 2.147 c
+158.86 2.147 158.709 2.091 158.603 1.985 c
+158.493 1.885 158.441 1.754 158.441 1.588 c
+158.441 1.459 158.478 1.353 158.559 1.264 c
+158.636 1.183 158.827 1.081 159.132 0.956 c
+159.61 0.769 159.941 0.581 160.117 0.397 c
+160.294 0.221 160.381 -0.007 160.381 -0.278 c
+160.381 -0.631 160.257 -0.911 160.014 -1.117 c
+159.779 -1.323 159.463 -1.425 159.073 -1.425 c
+158.651 -1.425 158.312 -1.308 158.059 -1.072 c
+157.802 -0.83 157.677 -0.525 157.677 -0.161 c
+158.324 -0.161 l
+158.331 -0.389 158.401 -0.565 158.53 -0.69 c
+158.655 -0.808 158.838 -0.866 159.073 -0.866 c
+159.286 -0.866 159.448 -0.819 159.559 -0.72 c
+159.675 -0.625 159.735 -0.496 159.735 -0.338 c
+161.263 -0.999 m
+161.263 -0.881 161.296 -0.786 161.366 -0.706 c
+161.433 -0.628 161.535 -0.588 161.675 -0.588 c
+161.822 -0.588 161.929 -0.628 161.998 -0.706 c
+162.075 -0.786 162.116 -0.881 162.116 -0.999 c
+162.116 -1.109 162.075 -1.201 161.998 -1.278 c
+161.929 -1.356 161.822 -1.396 161.675 -1.396 c
+161.535 -1.396 161.433 -1.356 161.366 -1.278 c
+161.296 -1.201 161.263 -1.109 161.263 -0.999 c
+168.377 0.353 m
+168.348 -0.228 168.186 -0.668 167.893 -0.97 c
+167.598 -1.275 167.18 -1.425 166.644 -1.425 c
+166.114 -1.425 165.688 -1.227 165.364 -0.823 c
+165.048 -0.411 164.894 0.148 164.894 0.853 c
+164.894 1.823 l
+164.894 2.517 165.056 3.065 165.379 3.469 c
+165.703 3.87 166.147 4.072 166.717 4.072 c
+167.224 4.072 167.621 3.914 167.907 3.602 c
+168.19 3.296 168.348 2.856 168.377 2.278 c
+167.687 2.278 l
+167.658 2.72 167.562 3.032 167.407 3.219 c
+167.261 3.404 167.029 3.499 166.717 3.499 c
+166.342 3.499 166.059 3.352 165.865 3.057 c
+165.666 2.771 165.57 2.356 165.57 1.808 c
+165.57 0.823 l
+165.57 0.283 165.662 -0.132 165.85 -0.426 c
+166.033 -0.712 166.298 -0.852 166.644 -0.852 c
+166.996 -0.852 167.249 -0.764 167.407 -0.588 c
+167.562 -0.411 167.658 -0.099 167.687 0.353 c
+h
+171.215 -0.999 m
+170.998 -1.286 170.686 -1.425 170.274 -1.425 c
+169.91 -1.425 169.634 -1.304 169.451 -1.058 c
+169.275 -0.804 169.179 -0.44 169.171 0.03 c
+169.171 2.631 l
+169.819 2.631 l
+169.819 0.088 l
+169.819 -0.54 170.002 -0.852 170.377 -0.852 c
+170.777 -0.852 171.053 -0.675 171.2 -0.323 c
+171.2 2.631 l
+171.847 2.631 l
+171.847 -1.352 l
+171.23 -1.352 l
+h
+174.478 2.014 m
+174.39 2.033 174.291 2.043 174.184 2.043 c
+173.85 2.043 173.614 1.86 173.478 1.5 c
+173.478 -1.352 l
+172.832 -1.352 l
+172.832 2.631 l
+173.464 2.631 l
+173.478 2.22 l
+173.655 2.544 173.898 2.705 174.214 2.705 c
+174.32 2.705 174.408 2.683 174.478 2.646 c
+h
+176.771 2.014 m
+176.683 2.033 176.583 2.043 176.477 2.043 c
+176.142 2.043 175.907 1.86 175.772 1.5 c
+175.772 -1.352 l
+175.124 -1.352 l
+175.124 2.631 l
+175.756 2.631 l
+175.772 2.22 l
+175.947 2.544 176.19 2.705 176.506 2.705 c
+176.613 2.705 176.701 2.683 176.771 2.646 c
+h
+178.77 -1.425 m
+178.27 -1.425 177.888 -1.278 177.624 -0.984 c
+177.359 -0.69 177.227 -0.257 177.227 0.324 c
+177.227 0.794 l
+177.227 1.389 177.352 1.856 177.609 2.191 c
+177.873 2.532 178.233 2.705 178.696 2.705 c
+179.156 2.705 179.498 2.55 179.725 2.249 c
+179.961 1.956 180.082 1.492 180.093 0.867 c
+180.093 0.441 l
+177.873 0.441 l
+177.873 0.353 l
+177.873 -0.08 177.95 -0.393 178.108 -0.588 c
+178.274 -0.775 178.505 -0.866 178.8 -0.866 c
+178.994 -0.866 179.167 -0.833 179.314 -0.764 c
+179.461 -0.687 179.597 -0.569 179.725 -0.411 c
+180.063 -0.823 l
+179.777 -1.227 179.347 -1.425 178.77 -1.425 c
+178.696 2.147 m
+178.421 2.147 178.218 2.051 178.094 1.867 c
+177.965 1.68 177.892 1.389 177.873 1 c
+179.446 1 l
+179.446 1.088 l
+179.424 1.47 179.358 1.738 179.24 1.897 c
+179.122 2.062 178.939 2.147 178.696 2.147 c
+181.489 2.631 m
+181.504 2.191 l
+181.757 2.532 182.081 2.705 182.474 2.705 c
+183.18 2.705 183.536 2.234 183.548 1.294 c
+183.548 -1.352 l
+182.9 -1.352 l
+182.9 1.264 l
+182.9 1.577 182.845 1.798 182.739 1.926 c
+182.629 2.051 182.474 2.117 182.268 2.117 c
+182.11 2.117 181.964 2.062 181.827 1.956 c
+181.699 1.845 181.596 1.709 181.518 1.544 c
+181.518 -1.352 l
+180.872 -1.352 l
+180.872 2.631 l
+h
+185.37 3.587 m
+185.37 2.631 l
+185.973 2.631 l
+185.973 2.103 l
+185.37 2.103 l
+185.37 -0.367 l
+185.37 -0.525 185.392 -0.643 185.443 -0.72 c
+185.503 -0.801 185.59 -0.837 185.708 -0.837 c
+185.796 -0.837 185.884 -0.823 185.973 -0.793 c
+185.973 -1.352 l
+185.825 -1.4 185.671 -1.425 185.517 -1.425 c
+185.26 -1.425 185.065 -1.334 184.929 -1.146 c
+184.789 -0.962 184.724 -0.702 184.724 -0.367 c
+184.724 2.103 l
+184.121 2.103 l
+184.121 2.631 l
+184.724 2.631 l
+184.724 3.587 l
+h
+191.338 0.441 m
+191.338 -0.176 191.224 -0.643 190.999 -0.955 c
+190.783 -1.271 190.459 -1.425 190.029 -1.425 c
+189.607 -1.425 189.295 -1.246 189.089 -0.881 c
+189.059 -1.352 l
+188.456 -1.352 l
+188.456 4.293 l
+189.104 4.293 l
+189.104 2.191 l
+189.316 2.532 189.625 2.705 190.029 2.705 c
+190.459 2.705 190.783 2.547 190.999 2.234 c
+191.224 1.929 191.338 1.463 191.338 0.838 c
+h
+190.691 0.823 m
+190.691 1.294 190.621 1.625 190.485 1.823 c
+190.357 2.018 190.147 2.117 189.853 2.117 c
+189.519 2.117 189.269 1.933 189.104 1.573 c
+189.104 -0.309 l
+189.269 -0.672 189.522 -0.852 189.868 -0.852 c
+190.162 -0.852 190.371 -0.749 190.5 -0.544 c
+190.625 -0.338 190.691 -0.022 190.691 0.412 c
+h
+193.822 2.014 m
+193.734 2.033 193.634 2.043 193.528 2.043 c
+193.193 2.043 192.958 1.86 192.822 1.5 c
+192.822 -1.352 l
+192.175 -1.352 l
+192.175 2.631 l
+192.807 2.631 l
+192.822 2.22 l
+192.998 2.544 193.241 2.705 193.557 2.705 c
+193.663 2.705 193.752 2.683 193.822 2.646 c
+h
+196.364 -1.352 m
+196.325 -1.263 196.298 -1.117 196.291 -0.911 c
+196.056 -1.256 195.762 -1.425 195.409 -1.425 c
+195.045 -1.425 194.762 -1.33 194.557 -1.132 c
+194.359 -0.926 194.263 -0.639 194.263 -0.264 c
+194.263 0.136 194.399 0.456 194.675 0.691 c
+194.947 0.934 195.321 1.058 195.791 1.058 c
+196.277 1.058 l
+196.277 1.485 l
+196.277 1.721 196.221 1.885 196.115 1.985 c
+196.005 2.091 195.843 2.147 195.63 2.147 c
+195.431 2.147 195.269 2.087 195.145 1.97 c
+195.027 1.852 194.968 1.706 194.968 1.529 c
+194.322 1.529 l
+194.322 1.723 194.38 1.915 194.498 2.103 c
+194.623 2.286 194.785 2.433 194.983 2.544 c
+195.188 2.65 195.417 2.705 195.674 2.705 c
+196.075 2.705 196.379 2.602 196.585 2.396 c
+196.798 2.191 196.913 1.897 196.923 1.515 c
+196.923 -0.5 l
+196.923 -0.804 196.96 -1.069 197.041 -1.294 c
+197.041 -1.352 l
+h
+195.498 -0.837 m
+195.662 -0.837 195.814 -0.793 195.953 -0.706 c
+196.1 -0.617 196.207 -0.507 196.277 -0.367 c
+196.277 0.574 l
+195.909 0.574 l
+195.593 0.574 195.35 0.504 195.174 0.368 c
+194.997 0.239 194.91 0.052 194.91 -0.191 c
+194.91 -0.419 194.953 -0.584 195.042 -0.69 c
+195.13 -0.789 195.281 -0.837 195.498 -0.837 c
+198.54 2.631 m
+198.555 2.191 l
+198.808 2.532 199.132 2.705 199.525 2.705 c
+200.231 2.705 200.587 2.234 200.598 1.294 c
+200.598 -1.352 l
+199.951 -1.352 l
+199.951 1.264 l
+199.951 1.577 199.896 1.798 199.79 1.926 c
+199.679 2.051 199.525 2.117 199.319 2.117 c
+199.161 2.117 199.014 2.062 198.878 1.956 c
+198.75 1.845 198.647 1.709 198.569 1.544 c
+198.569 -1.352 l
+197.923 -1.352 l
+197.923 2.631 l
+h
+202.949 -0.866 m
+203.163 -0.866 203.336 -0.804 203.464 -0.675 c
+203.6 -0.54 203.674 -0.349 203.685 -0.103 c
+204.302 -0.103 l
+204.281 -0.484 204.144 -0.804 203.89 -1.058 c
+203.633 -1.304 203.321 -1.425 202.949 -1.425 c
+202.457 -1.425 202.083 -1.275 201.818 -0.97 c
+201.561 -0.658 201.436 -0.191 201.436 0.427 c
+201.436 0.867 l
+201.436 1.463 201.561 1.919 201.818 2.234 c
+202.083 2.547 202.457 2.705 202.949 2.705 c
+203.35 2.705 203.67 2.573 203.905 2.309 c
+204.148 2.051 204.281 1.706 204.302 1.264 c
+203.685 1.264 l
+203.663 1.559 203.589 1.779 203.464 1.926 c
+203.346 2.073 203.174 2.147 202.949 2.147 c
+202.656 2.147 202.44 2.047 202.303 1.852 c
+202.164 1.665 202.09 1.357 202.083 0.927 c
+202.083 0.412 l
+202.083 -0.058 202.149 -0.393 202.288 -0.588 c
+202.436 -0.775 202.656 -0.866 202.949 -0.866 c
+205.698 2.22 m
+205.952 2.544 206.272 2.705 206.654 2.705 c
+207.36 2.705 207.716 2.234 207.728 1.294 c
+207.728 -1.352 l
+207.08 -1.352 l
+207.08 1.264 l
+207.08 1.577 207.026 1.798 206.918 1.926 c
+206.808 2.051 206.654 2.117 206.448 2.117 c
+206.29 2.117 206.143 2.062 206.007 1.956 c
+205.879 1.845 205.775 1.709 205.698 1.544 c
+205.698 -1.352 l
+205.052 -1.352 l
+205.052 4.293 l
+205.698 4.293 l
+h
+208.727 -0.999 m
+208.727 -0.881 208.759 -0.786 208.829 -0.706 c
+208.896 -0.628 208.998 -0.588 209.139 -0.588 c
+209.285 -0.588 209.392 -0.628 209.461 -0.706 c
+209.538 -0.786 209.579 -0.881 209.579 -0.999 c
+209.579 -1.109 209.538 -1.201 209.461 -1.278 c
+209.392 -1.356 209.285 -1.396 209.139 -1.396 c
+208.998 -1.396 208.896 -1.356 208.829 -1.278 c
+208.759 -1.201 208.727 -1.109 208.727 -0.999 c
+f
+Q
+0.113 0.082 0.09 0 k
+287.665 383.129 234.667 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 376.2903 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.146 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.807 l
+-1.896 -1.807 l
+-1.896 -1.263 l
+-2.142 -1.256 -2.359 -1.219 -2.543 -1.161 c
+-2.719 -1.102 -2.873 -1.024 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.69 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.034 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.477 -2.234 -0.514 c
+-2.138 -0.554 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.662 l
+-1.907 0.662 -1.926 0.666 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.772 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.279 -3.219 1.426 c
+-3.289 1.573 -3.322 1.757 -3.322 1.985 c
+-3.322 2.18 -3.289 2.345 -3.219 2.485 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.933 -2.645 3.003 -2.469 3.043 c
+-2.293 3.091 -2.102 3.12 -1.896 3.132 c
+-1.896 3.558 l
+-1.543 3.558 l
+-1.543 3.132 l
+-1.319 3.12 -1.128 3.091 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.735 -0.349 2.621 -0.279 2.485 c
+-0.202 2.345 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.459 -1.543 2.5 c
+-1.543 1.368 l
+-1.514 1.368 l
+-1.506 1.368 -1.492 1.36 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.206 c
+-0.756 1.147 -0.595 1.066 -0.455 0.971 c
+-0.32 0.871 -0.213 0.743 -0.132 0.588 c
+-0.044 0.431 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.503 -2.113 2.485 -2.19 2.455 c
+-2.26 2.426 -2.319 2.386 -2.366 2.338 c
+-2.406 2.297 -2.436 2.249 -2.454 2.191 c
+-2.477 2.132 -2.484 2.066 -2.484 1.999 c
+-2.484 1.912 -2.469 1.838 -2.439 1.779 c
+-2.41 1.721 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.201 1.559 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.441 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.302 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.44 c
+-0.904 -0.345 -0.837 -0.201 -0.837 -0.014 c
+6.402 -2.66 m
+6.184 -2.66 5.993 -2.634 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.395 c
+5.284 -2.314 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.616 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.146 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.83 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.219 6.034 -1.219 c
+5.829 -1.219 5.644 -1.182 5.49 -1.102 c
+5.343 -1.014 5.215 -0.897 5.108 -0.749 c
+5.009 -0.595 4.935 -0.411 4.888 -0.205 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.772 4.836 1.019 4.888 1.235 c
+4.946 1.449 5.027 1.632 5.137 1.779 c
+5.244 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.264 6.093 2.264 c
+6.188 2.264 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.919 7.107 1.97 c
+7.115 2.029 7.122 2.077 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.151 2.22 c
+8.004 2.22 l
+7.993 2.139 7.982 2.029 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.414 7.938 -1.635 7.871 -1.822 c
+7.802 -2.006 7.699 -2.16 7.563 -2.278 c
+7.423 -2.403 7.258 -2.499 7.063 -2.557 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.743 7.067 0.919 7.019 1.058 c
+6.978 1.206 6.924 1.324 6.857 1.411 c
+6.799 1.5 6.729 1.559 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.368 c
+5.88 1.279 5.835 1.162 5.799 1.015 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.514 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.558 c
+6.725 -0.521 6.799 -0.463 6.857 -0.382 c
+6.924 -0.293 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.302 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.263 l
+8.86 -1.263 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.603 l
+9.199 1.603 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.597 1.603 m
+13.053 1.603 l
+13.053 2.22 l
+13.641 2.22 l
+13.92 3.117 l
+14.494 3.117 l
+14.494 2.22 l
+15.728 2.22 l
+15.728 1.603 l
+14.494 1.603 l
+14.494 -0.103 l
+14.494 -0.323 l
+14.501 -0.392 14.523 -0.455 14.552 -0.514 c
+14.589 -0.565 14.645 -0.61 14.714 -0.646 c
+14.791 -0.675 14.905 -0.69 15.052 -0.69 c
+15.188 -0.69 15.324 -0.687 15.464 -0.675 c
+15.599 -0.658 15.732 -0.631 15.861 -0.602 c
+15.861 -1.205 l
+15.78 -1.215 15.703 -1.23 15.626 -1.249 c
+15.545 -1.26 15.468 -1.267 15.391 -1.278 c
+15.31 -1.286 15.221 -1.294 15.125 -1.294 c
+15.038 -1.3 14.938 -1.308 14.832 -1.308 c
+14.645 -1.308 14.483 -1.294 14.346 -1.263 c
+14.218 -1.227 14.104 -1.182 14.009 -1.132 c
+13.92 -1.084 13.847 -1.024 13.788 -0.955 c
+13.729 -0.878 13.685 -0.801 13.656 -0.72 c
+13.627 -0.631 13.604 -0.544 13.597 -0.455 c
+13.586 -0.359 13.582 -0.264 13.582 -0.176 c
+h
+23.295 -1.263 m
+23.283 -1.246 23.273 -1.215 23.265 -1.176 c
+23.265 -1.128 23.258 -1.08 23.25 -1.028 c
+23.25 -0.97 23.243 -0.911 23.236 -0.852 c
+23.236 -0.69 l
+23.118 -0.926 22.975 -1.095 22.809 -1.19 c
+22.641 -1.278 22.442 -1.323 22.207 -1.323 c
+22.009 -1.323 21.832 -1.278 21.677 -1.19 c
+21.519 -1.102 21.388 -0.98 21.28 -0.823 c
+21.182 -0.658 21.105 -0.467 21.045 -0.249 c
+20.994 -0.037 20.972 0.206 20.972 0.47 c
+20.972 0.736 20.994 0.975 21.045 1.191 c
+21.105 1.415 21.182 1.607 21.28 1.764 c
+21.388 1.919 21.519 2.043 21.677 2.132 c
+21.843 2.228 22.034 2.278 22.251 2.278 c
+22.346 2.278 22.442 2.264 22.531 2.234 c
+22.626 2.213 22.722 2.18 22.809 2.132 c
+22.898 2.08 22.975 2.018 23.044 1.941 c
+23.121 1.86 23.185 1.768 23.236 1.661 c
+23.236 1.75 l
+23.236 1.897 l
+23.236 2.058 l
+23.236 2.234 l
+23.236 3.514 l
+24.133 3.514 l
+24.133 -0.5 l
+24.133 -0.675 24.137 -0.833 24.147 -0.97 c
+24.154 -1.098 24.162 -1.198 24.162 -1.263 c
+h
+23.25 0.485 m
+23.25 0.721 23.225 0.912 23.177 1.058 c
+23.137 1.214 23.081 1.338 23.015 1.426 c
+22.957 1.515 22.886 1.573 22.809 1.603 c
+22.728 1.64 22.651 1.661 22.574 1.661 c
+22.475 1.661 22.383 1.636 22.296 1.588 c
+22.215 1.548 22.148 1.478 22.09 1.382 c
+22.038 1.283 21.994 1.162 21.957 1.015 c
+21.928 0.867 21.913 0.684 21.913 0.47 c
+21.913 0.078 21.964 -0.216 22.074 -0.411 c
+22.192 -0.61 22.354 -0.706 22.56 -0.706 c
+22.637 -0.706 22.714 -0.687 22.795 -0.646 c
+22.872 -0.61 22.946 -0.544 23.015 -0.455 c
+23.081 -0.367 23.137 -0.246 23.177 -0.087 c
+23.225 0.067 23.25 0.258 23.25 0.485 c
+27.281 -0.646 m
+28.413 -0.646 l
+28.413 -1.263 l
+25.106 -1.263 l
+25.106 -0.646 l
+26.371 -0.646 l
+26.371 1.603 l
+25.444 1.603 l
+25.444 2.22 l
+27.281 2.22 l
+h
+26.371 3.514 0.911 -0.676 re
+26.371 2.837 m
+30.886 1.603 m
+30.886 -1.263 l
+29.99 -1.263 l
+29.99 1.603 l
+29.167 1.603 l
+29.167 2.22 l
+29.99 2.22 l
+29.99 2.485 l
+29.99 2.61 30.005 2.742 30.034 2.882 c
+30.071 3.018 30.14 3.135 30.24 3.234 c
+30.346 3.341 30.489 3.429 30.666 3.499 c
+30.842 3.565 31.067 3.602 31.343 3.602 c
+31.555 3.602 31.754 3.591 31.931 3.572 c
+32.107 3.55 32.257 3.532 32.386 3.514 c
+32.386 2.926 l
+32.257 2.944 32.114 2.959 31.96 2.97 c
+31.802 2.977 31.651 2.984 31.504 2.984 c
+31.376 2.984 31.272 2.97 31.195 2.94 c
+31.114 2.911 31.052 2.87 31.004 2.822 c
+30.953 2.771 30.919 2.708 30.901 2.631 c
+30.89 2.562 30.886 2.485 30.886 2.396 c
+30.886 2.22 l
+32.313 2.22 l
+32.313 1.603 l
+h
+34.948 1.603 m
+34.948 -1.263 l
+34.051 -1.263 l
+34.051 1.603 l
+33.228 1.603 l
+33.228 2.22 l
+34.051 2.22 l
+34.051 2.485 l
+34.051 2.61 34.065 2.742 34.094 2.882 c
+34.132 3.018 34.202 3.135 34.3 3.234 c
+34.407 3.341 34.551 3.429 34.726 3.499 c
+34.903 3.565 35.127 3.602 35.403 3.602 c
+35.616 3.602 35.815 3.591 35.991 3.572 c
+36.168 3.55 36.318 3.532 36.446 3.514 c
+36.446 2.926 l
+36.318 2.944 36.174 2.959 36.02 2.97 c
+35.862 2.977 35.711 2.984 35.565 2.984 c
+35.436 2.984 35.333 2.97 35.256 2.94 c
+35.175 2.911 35.112 2.87 35.065 2.822 c
+35.013 2.771 34.98 2.708 34.962 2.631 c
+34.951 2.562 34.948 2.485 34.948 2.396 c
+34.948 2.22 l
+36.373 2.22 l
+36.373 1.603 l
+h
+42.175 -2.63 m
+42.175 3.514 l
+44.101 3.514 l
+44.101 2.897 l
+43.028 2.897 l
+43.028 -2.013 l
+44.101 -2.013 l
+44.101 -2.63 l
+h
+47.133 1.603 m
+47.133 -1.263 l
+46.236 -1.263 l
+46.236 1.603 l
+45.413 1.603 l
+45.413 2.22 l
+46.236 2.22 l
+46.236 2.485 l
+46.236 2.61 46.251 2.742 46.281 2.882 c
+46.317 3.018 46.387 3.135 46.486 3.234 c
+46.593 3.341 46.736 3.429 46.912 3.499 c
+47.089 3.565 47.313 3.602 47.588 3.602 c
+47.802 3.602 48 3.591 48.176 3.572 c
+48.353 3.55 48.504 3.532 48.632 3.514 c
+48.632 2.926 l
+48.504 2.944 48.361 2.959 48.205 2.97 c
+48.047 2.977 47.897 2.984 47.75 2.984 c
+47.621 2.984 47.519 2.97 47.441 2.94 c
+47.361 2.911 47.298 2.87 47.251 2.822 c
+47.199 2.771 47.166 2.708 47.147 2.631 c
+47.137 2.562 47.133 2.485 47.133 2.396 c
+47.133 2.22 l
+48.558 2.22 l
+48.558 1.603 l
+h
+51.649 -0.646 m
+52.781 -0.646 l
+52.781 -1.263 l
+49.473 -1.263 l
+49.473 -0.646 l
+50.738 -0.646 l
+50.738 1.603 l
+49.812 1.603 l
+49.812 2.22 l
+51.649 2.22 l
+h
+50.738 3.514 0.912 -0.676 re
+50.738 2.837 m
+55.71 -0.646 m
+56.841 -0.646 l
+56.841 -1.263 l
+53.535 -1.263 l
+53.535 -0.646 l
+54.798 -0.646 l
+54.798 2.897 l
+53.872 2.897 l
+53.872 3.514 l
+55.71 3.514 l
+h
+59.23 -1.323 m
+58.973 -1.323 58.745 -1.286 58.539 -1.219 c
+58.333 -1.142 58.157 -1.028 58.01 -0.881 c
+57.863 -0.727 57.745 -0.536 57.657 -0.309 c
+57.576 -0.084 57.539 0.181 57.539 0.485 c
+57.539 0.817 57.584 1.096 57.672 1.324 c
+57.768 1.559 57.896 1.742 58.054 1.881 c
+58.22 2.018 58.407 2.117 58.613 2.176 c
+58.819 2.242 59.028 2.278 59.245 2.278 c
+59.517 2.278 59.752 2.228 59.951 2.132 c
+60.157 2.043 60.321 1.912 60.45 1.735 c
+60.586 1.566 60.685 1.36 60.744 1.118 c
+60.81 0.882 60.847 0.618 60.847 0.324 c
+60.847 0.31 l
+58.48 0.31 l
+58.48 0.162 58.495 0.023 58.524 -0.103 c
+58.561 -0.231 58.617 -0.345 58.686 -0.44 c
+58.752 -0.529 58.837 -0.598 58.936 -0.646 c
+59.031 -0.698 59.145 -0.72 59.274 -0.72 c
+59.428 -0.72 59.569 -0.687 59.686 -0.617 c
+59.81 -0.55 59.899 -0.448 59.951 -0.309 c
+60.788 -0.382 l
+60.759 -0.481 60.704 -0.588 60.627 -0.706 c
+60.546 -0.816 60.443 -0.918 60.317 -1.014 c
+60.2 -1.102 60.046 -1.176 59.862 -1.234 c
+59.686 -1.294 59.473 -1.323 59.23 -1.323 c
+59.23 1.706 m
+59.141 1.706 59.054 1.691 58.966 1.661 c
+58.877 1.632 58.796 1.58 58.73 1.515 c
+58.661 1.445 58.602 1.357 58.554 1.25 c
+58.514 1.139 58.495 1.015 58.495 0.867 c
+59.965 0.867 l
+59.965 1.004 59.939 1.125 59.891 1.235 c
+59.851 1.341 59.796 1.43 59.729 1.5 c
+59.671 1.566 59.598 1.617 59.509 1.646 c
+59.421 1.684 59.326 1.706 59.23 1.706 c
+62.1 -2.63 m
+62.1 -2.013 l
+63.173 -2.013 l
+63.173 2.897 l
+62.1 2.897 l
+62.1 3.514 l
+64.026 3.514 l
+64.026 -2.63 l
+h
+f
+Q
+q 1 0 0 1 346.0048 361.4887 cm
+0 0 m
+0 0.264 -0.073 0.463 -0.22 0.603 c
+-0.359 0.75 -0.617 0.889 -0.999 1.029 c
+-1.374 1.165 -1.66 1.309 -1.866 1.455 c
+-2.065 1.602 -2.212 1.768 -2.308 1.955 c
+-2.406 2.15 -2.454 2.371 -2.454 2.616 c
+-2.454 3.036 -2.315 3.385 -2.028 3.66 c
+-1.745 3.932 -1.377 4.072 -0.926 4.072 c
+-0.613 4.072 -0.334 3.998 -0.087 3.851 c
+0.154 3.711 0.342 3.516 0.47 3.263 c
+0.607 3.017 0.676 2.749 0.676 2.454 c
+0 2.454 l
+0 2.786 -0.081 3.042 -0.235 3.219 c
+-0.393 3.403 -0.625 3.499 -0.926 3.499 c
+-1.19 3.499 -1.404 3.418 -1.558 3.263 c
+-1.705 3.117 -1.778 2.903 -1.778 2.631 c
+-1.778 2.404 -1.701 2.213 -1.543 2.058 c
+-1.377 1.911 -1.124 1.771 -0.779 1.646 c
+-0.261 1.477 0.111 1.268 0.339 1.014 c
+0.574 0.757 0.691 0.426 0.691 0.015 c
+0.691 -0.426 0.548 -0.779 0.265 -1.043 c
+-0.022 -1.301 -0.404 -1.426 -0.881 -1.426 c
+-1.198 -1.426 -1.484 -1.356 -1.749 -1.22 c
+-2.013 -1.084 -2.227 -0.893 -2.381 -0.646 c
+-2.528 -0.405 -2.601 -0.118 -2.601 0.206 c
+-1.925 0.206 l
+-1.925 -0.129 -1.833 -0.389 -1.646 -0.573 c
+-1.462 -0.76 -1.205 -0.852 -0.881 -0.852 c
+-0.588 -0.852 -0.367 -0.779 -0.22 -0.632 c
+-0.073 -0.478 0 -0.264 0 0 c
+2.117 2.219 m
+2.371 2.543 2.691 2.705 3.072 2.705 c
+3.778 2.705 4.135 2.234 4.146 1.294 c
+4.146 -1.352 l
+3.499 -1.352 l
+3.499 1.264 l
+3.499 1.577 3.444 1.797 3.337 1.926 c
+3.227 2.051 3.072 2.117 2.866 2.117 c
+2.708 2.117 2.562 2.062 2.425 1.955 c
+2.297 1.845 2.194 1.709 2.117 1.544 c
+2.117 -1.352 l
+1.47 -1.352 l
+1.47 4.293 l
+2.117 4.293 l
+h
+4.969 0.823 m
+4.969 1.4 5.104 1.856 5.38 2.19 c
+5.663 2.532 6.034 2.705 6.498 2.705 c
+6.957 2.705 7.325 2.535 7.599 2.205 c
+7.882 1.881 8.03 1.434 8.04 0.867 c
+8.04 0.441 l
+8.04 -0.129 7.898 -0.584 7.614 -0.926 c
+7.339 -1.261 6.972 -1.426 6.512 -1.426 c
+6.049 -1.426 5.678 -1.264 5.395 -0.941 c
+5.12 -0.61 4.976 -0.169 4.969 0.382 c
+h
+5.615 0.441 m
+5.615 0.037 5.692 -0.279 5.85 -0.515 c
+6.016 -0.75 6.236 -0.867 6.512 -0.867 c
+7.078 -0.867 7.372 -0.455 7.394 0.368 c
+7.394 0.823 l
+7.394 1.224 7.31 1.544 7.144 1.779 c
+6.986 2.022 6.77 2.146 6.498 2.146 c
+6.232 2.146 6.016 2.022 5.85 1.779 c
+5.692 1.544 5.615 1.224 5.615 0.823 c
+h
+11.848 -0.206 m
+12.451 2.631 l
+13.097 2.631 l
+12.112 -1.352 l
+11.597 -1.352 l
+10.819 1.5 l
+10.07 -1.352 l
+9.54 -1.352 l
+8.584 2.631 l
+9.216 2.631 l
+9.834 -0.133 l
+10.569 2.631 l
+11.084 2.631 l
+h
+16.875 -0.867 m
+17.088 -0.867 17.261 -0.804 17.39 -0.676 c
+17.525 -0.54 17.598 -0.349 17.61 -0.103 c
+18.227 -0.103 l
+18.205 -0.485 18.069 -0.804 17.816 -1.058 c
+17.558 -1.305 17.246 -1.426 16.875 -1.426 c
+16.382 -1.426 16.008 -1.275 15.743 -0.97 c
+15.486 -0.658 15.36 -0.191 15.36 0.426 c
+15.36 0.867 l
+15.36 1.463 15.486 1.918 15.743 2.234 c
+16.008 2.547 16.382 2.705 16.875 2.705 c
+17.276 2.705 17.596 2.572 17.831 2.308 c
+18.073 2.051 18.205 1.706 18.227 1.264 c
+17.61 1.264 l
+17.588 1.558 17.515 1.779 17.39 1.926 c
+17.272 2.072 17.099 2.146 16.875 2.146 c
+16.581 2.146 16.364 2.047 16.228 1.852 c
+16.089 1.665 16.015 1.357 16.008 0.926 c
+16.008 0.412 l
+16.008 -0.058 16.073 -0.393 16.214 -0.588 c
+16.36 -0.775 16.581 -0.867 16.875 -0.867 c
+19.624 2.219 m
+19.877 2.543 20.197 2.705 20.579 2.705 c
+21.284 2.705 21.641 2.234 21.652 1.294 c
+21.652 -1.352 l
+21.005 -1.352 l
+21.005 1.264 l
+21.005 1.577 20.95 1.797 20.844 1.926 c
+20.733 2.051 20.579 2.117 20.374 2.117 c
+20.216 2.117 20.068 2.062 19.932 1.955 c
+19.804 1.845 19.701 1.709 19.624 1.544 c
+19.624 -1.352 l
+18.977 -1.352 l
+18.977 4.293 l
+19.624 4.293 l
+h
+24.651 -1.352 m
+24.611 -1.264 24.584 -1.117 24.577 -0.912 c
+24.342 -1.257 24.048 -1.426 23.695 -1.426 c
+23.331 -1.426 23.048 -1.33 22.843 -1.132 c
+22.645 -0.926 22.549 -0.64 22.549 -0.264 c
+22.549 0.136 22.685 0.455 22.961 0.69 c
+23.232 0.933 23.607 1.058 24.077 1.058 c
+24.563 1.058 l
+24.563 1.484 l
+24.563 1.72 24.507 1.885 24.401 1.984 c
+24.291 2.091 24.129 2.146 23.915 2.146 c
+23.717 2.146 23.555 2.087 23.431 1.97 c
+23.313 1.852 23.254 1.706 23.254 1.529 c
+22.608 1.529 l
+22.608 1.723 22.666 1.914 22.784 2.102 c
+22.909 2.286 23.071 2.433 23.269 2.543 c
+23.475 2.65 23.703 2.705 23.96 2.705 c
+24.36 2.705 24.665 2.602 24.871 2.396 c
+25.084 2.19 25.199 1.897 25.209 1.514 c
+25.209 -0.5 l
+25.209 -0.804 25.246 -1.07 25.327 -1.294 c
+25.327 -1.352 l
+h
+23.784 -0.838 m
+23.948 -0.838 24.1 -0.794 24.239 -0.706 c
+24.386 -0.617 24.493 -0.507 24.563 -0.368 c
+24.563 0.573 l
+24.195 0.573 l
+23.879 0.573 23.636 0.503 23.46 0.368 c
+23.283 0.239 23.196 0.052 23.196 -0.191 c
+23.196 -0.419 23.24 -0.584 23.328 -0.691 c
+23.416 -0.79 23.566 -0.838 23.784 -0.838 c
+26.826 2.631 m
+26.841 2.19 l
+27.094 2.532 27.418 2.705 27.811 2.705 c
+28.517 2.705 28.873 2.234 28.884 1.294 c
+28.884 -1.352 l
+28.237 -1.352 l
+28.237 1.264 l
+28.237 1.577 28.182 1.797 28.075 1.926 c
+27.965 2.051 27.811 2.117 27.605 2.117 c
+27.447 2.117 27.3 2.062 27.164 1.955 c
+27.036 1.845 26.932 1.709 26.855 1.544 c
+26.855 -1.352 l
+26.209 -1.352 l
+26.209 2.631 l
+h
+29.722 0.823 m
+29.722 1.44 29.832 1.904 30.06 2.219 c
+30.284 2.543 30.618 2.705 31.059 2.705 c
+31.46 2.705 31.765 2.529 31.971 2.176 c
+32.015 2.631 l
+32.603 2.631 l
+32.603 -1.396 l
+32.603 -1.885 32.474 -2.263 32.22 -2.528 c
+31.964 -2.793 31.611 -2.925 31.162 -2.925 c
+30.964 -2.925 30.743 -2.874 30.501 -2.778 c
+30.255 -2.679 30.074 -2.558 29.957 -2.41 c
+30.221 -1.97 l
+30.487 -2.234 30.784 -2.367 31.118 -2.367 c
+31.655 -2.367 31.931 -2.072 31.942 -1.484 c
+31.942 -0.956 l
+31.736 -1.271 31.434 -1.426 31.044 -1.426 c
+30.633 -1.426 30.31 -1.275 30.074 -0.97 c
+29.847 -0.658 29.729 -0.206 29.722 0.382 c
+h
+30.383 0.441 m
+30.383 0 30.446 -0.33 30.574 -0.544 c
+30.699 -0.75 30.916 -0.852 31.221 -0.852 c
+31.545 -0.852 31.784 -0.687 31.942 -0.353 c
+31.942 1.631 l
+31.773 1.955 31.534 2.117 31.221 2.117 c
+30.927 2.117 30.71 2.014 30.574 1.808 c
+30.446 1.602 30.383 1.278 30.383 0.838 c
+h
+34.984 -1.426 m
+34.485 -1.426 34.102 -1.278 33.837 -0.985 c
+33.573 -0.691 33.44 -0.257 33.44 0.324 c
+33.44 0.794 l
+33.44 1.389 33.566 1.856 33.823 2.19 c
+34.088 2.532 34.448 2.705 34.911 2.705 c
+35.37 2.705 35.711 2.55 35.94 2.249 c
+36.175 1.955 36.296 1.492 36.307 0.867 c
+36.307 0.441 l
+34.088 0.441 l
+34.088 0.353 l
+34.088 -0.081 34.165 -0.393 34.323 -0.588 c
+34.488 -0.775 34.72 -0.867 35.013 -0.867 c
+35.208 -0.867 35.381 -0.834 35.528 -0.764 c
+35.675 -0.687 35.811 -0.569 35.94 -0.411 c
+36.278 -0.823 l
+35.991 -1.228 35.561 -1.426 34.984 -1.426 c
+34.911 2.146 m
+34.635 2.146 34.433 2.051 34.308 1.866 c
+34.179 1.679 34.106 1.389 34.088 1 c
+35.661 1 l
+35.661 1.087 l
+35.638 1.47 35.572 1.738 35.455 1.897 c
+35.337 2.062 35.154 2.146 34.911 2.146 c
+39.027 -0.338 m
+39.027 -0.191 38.971 -0.07 38.865 0.029 c
+38.755 0.125 38.549 0.243 38.248 0.382 c
+37.901 0.53 37.66 0.651 37.512 0.75 c
+37.365 0.856 37.255 0.974 37.189 1.103 c
+37.119 1.228 37.086 1.386 37.086 1.573 c
+37.086 1.897 37.203 2.165 37.439 2.381 c
+37.674 2.595 37.976 2.705 38.35 2.705 c
+38.732 2.705 39.041 2.591 39.276 2.367 c
+39.511 2.139 39.629 1.852 39.629 1.5 c
+38.982 1.5 l
+38.982 1.675 38.923 1.827 38.806 1.955 c
+38.688 2.08 38.534 2.146 38.35 2.146 c
+38.152 2.146 38.001 2.091 37.895 1.984 c
+37.784 1.885 37.733 1.753 37.733 1.588 c
+37.733 1.459 37.77 1.353 37.851 1.264 c
+37.928 1.183 38.119 1.081 38.424 0.956 c
+38.901 0.769 39.233 0.58 39.409 0.397 c
+39.584 0.22 39.673 -0.008 39.673 -0.279 c
+39.673 -0.632 39.548 -0.912 39.306 -1.117 c
+39.071 -1.323 38.755 -1.426 38.365 -1.426 c
+37.942 -1.426 37.604 -1.309 37.351 -1.073 c
+37.093 -0.831 36.968 -0.525 36.968 -0.162 c
+37.615 -0.162 l
+37.623 -0.389 37.693 -0.565 37.821 -0.691 c
+37.946 -0.808 38.13 -0.867 38.365 -0.867 c
+38.578 -0.867 38.74 -0.819 38.85 -0.721 c
+38.967 -0.625 39.027 -0.496 39.027 -0.338 c
+45.112 0.441 m
+45.112 -0.176 44.997 -0.643 44.774 -0.956 c
+44.557 -1.271 44.234 -1.426 43.804 -1.426 c
+43.381 -1.426 43.069 -1.246 42.863 -0.881 c
+42.834 -1.352 l
+42.231 -1.352 l
+42.231 4.293 l
+42.877 4.293 l
+42.877 2.19 l
+43.091 2.532 43.399 2.705 43.804 2.705 c
+44.234 2.705 44.557 2.547 44.774 2.234 c
+44.997 1.929 45.112 1.463 45.112 0.838 c
+h
+44.465 0.823 m
+44.465 1.294 44.395 1.625 44.259 1.823 c
+44.131 2.018 43.921 2.117 43.627 2.117 c
+43.293 2.117 43.043 1.933 42.877 1.573 c
+42.877 -0.309 l
+43.043 -0.673 43.297 -0.852 43.642 -0.852 c
+43.936 -0.852 44.145 -0.75 44.274 -0.544 c
+44.399 -0.338 44.465 -0.022 44.465 0.412 c
+h
+47.376 -1.426 m
+46.875 -1.426 46.493 -1.278 46.229 -0.985 c
+45.965 -0.691 45.832 -0.257 45.832 0.324 c
+45.832 0.794 l
+45.832 1.389 45.957 1.856 46.214 2.19 c
+46.479 2.532 46.839 2.705 47.302 2.705 c
+47.761 2.705 48.103 2.55 48.331 2.249 c
+48.566 1.955 48.687 1.492 48.698 0.867 c
+48.698 0.441 l
+46.479 0.441 l
+46.479 0.353 l
+46.479 -0.081 46.556 -0.393 46.714 -0.588 c
+46.879 -0.775 47.11 -0.867 47.405 -0.867 c
+47.6 -0.867 47.773 -0.834 47.919 -0.764 c
+48.066 -0.687 48.203 -0.569 48.331 -0.411 c
+48.669 -0.823 l
+48.382 -1.228 47.952 -1.426 47.376 -1.426 c
+47.302 2.146 m
+47.027 2.146 46.824 2.051 46.699 1.866 c
+46.57 1.679 46.497 1.389 46.479 1 c
+48.051 1 l
+48.051 1.087 l
+48.029 1.47 47.964 1.738 47.846 1.897 c
+47.728 2.062 47.544 2.146 47.302 2.146 c
+50.33 3.587 m
+50.33 2.631 l
+50.933 2.631 l
+50.933 2.102 l
+50.33 2.102 l
+50.33 -0.368 l
+50.33 -0.525 50.352 -0.643 50.403 -0.721 c
+50.462 -0.801 50.551 -0.838 50.668 -0.838 c
+50.757 -0.838 50.844 -0.823 50.933 -0.794 c
+50.933 -1.352 l
+50.786 -1.4 50.632 -1.426 50.477 -1.426 c
+50.22 -1.426 50.025 -1.334 49.889 -1.147 c
+49.749 -0.962 49.683 -0.702 49.683 -0.368 c
+49.683 2.102 l
+49.08 2.102 l
+49.08 2.631 l
+49.683 2.631 l
+49.683 3.587 l
+h
+54.666 -0.206 m
+55.268 2.631 l
+55.916 2.631 l
+54.931 -1.352 l
+54.416 -1.352 l
+53.637 1.5 l
+52.887 -1.352 l
+52.359 -1.352 l
+51.403 2.631 l
+52.035 2.631 l
+52.652 -0.133 l
+53.387 2.631 l
+53.902 2.631 l
+h
+58.017 -1.426 m
+57.518 -1.426 57.136 -1.278 56.871 -0.985 c
+56.606 -0.691 56.474 -0.257 56.474 0.324 c
+56.474 0.794 l
+56.474 1.389 56.599 1.856 56.856 2.19 c
+57.121 2.532 57.481 2.705 57.944 2.705 c
+58.403 2.705 58.745 2.55 58.973 2.249 c
+59.208 1.955 59.33 1.492 59.34 0.867 c
+59.34 0.441 l
+57.121 0.441 l
+57.121 0.353 l
+57.121 -0.081 57.198 -0.393 57.356 -0.588 c
+57.522 -0.775 57.753 -0.867 58.047 -0.867 c
+58.242 -0.867 58.414 -0.834 58.561 -0.764 c
+58.709 -0.687 58.844 -0.569 58.973 -0.411 c
+59.311 -0.823 l
+59.025 -1.228 58.595 -1.426 58.017 -1.426 c
+57.944 2.146 m
+57.668 2.146 57.466 2.051 57.342 1.866 c
+57.213 1.679 57.14 1.389 57.121 1 c
+58.694 1 l
+58.694 1.087 l
+58.672 1.47 58.605 1.738 58.488 1.897 c
+58.37 2.062 58.187 2.146 57.944 2.146 c
+61.545 -1.426 m
+61.046 -1.426 60.664 -1.278 60.399 -0.985 c
+60.134 -0.691 60.002 -0.257 60.002 0.324 c
+60.002 0.794 l
+60.002 1.389 60.126 1.856 60.384 2.19 c
+60.649 2.532 61.009 2.705 61.472 2.705 c
+61.931 2.705 62.273 2.55 62.501 2.249 c
+62.736 1.955 62.857 1.492 62.868 0.867 c
+62.868 0.441 l
+60.649 0.441 l
+60.649 0.353 l
+60.649 -0.081 60.726 -0.393 60.884 -0.588 c
+61.049 -0.775 61.281 -0.867 61.575 -0.867 c
+61.77 -0.867 61.942 -0.834 62.089 -0.764 c
+62.236 -0.687 62.372 -0.569 62.501 -0.411 c
+62.839 -0.823 l
+62.553 -1.228 62.123 -1.426 61.545 -1.426 c
+61.472 2.146 m
+61.196 2.146 60.994 2.051 60.87 1.866 c
+60.741 1.679 60.667 1.389 60.649 1 c
+62.221 1 l
+62.221 1.087 l
+62.2 1.47 62.133 1.738 62.015 1.897 c
+61.898 2.062 61.714 2.146 61.472 2.146 c
+64.265 2.631 m
+64.279 2.19 l
+64.533 2.532 64.856 2.705 65.25 2.705 c
+65.955 2.705 66.312 2.234 66.322 1.294 c
+66.322 -1.352 l
+65.676 -1.352 l
+65.676 1.264 l
+65.676 1.577 65.62 1.797 65.514 1.926 c
+65.404 2.051 65.25 2.117 65.044 2.117 c
+64.886 2.117 64.739 2.062 64.602 1.955 c
+64.475 1.845 64.371 1.709 64.294 1.544 c
+64.294 -1.352 l
+63.648 -1.352 l
+63.648 2.631 l
+h
+f
+Q
+q 1 0 0 1 417.8096 361.8857 cm
+0 0 m
+0.354 2.234 l
+1.353 2.234 l
+0.53 -1.749 l
+-0.338 -1.749 l
+-0.897 0.559 l
+-1.454 -1.749 l
+-2.322 -1.749 l
+-3.145 2.234 l
+-2.146 2.234 l
+-1.793 0 l
+-1.263 2.234 l
+-0.529 2.234 l
+h
+1.75 0.368 m
+1.75 0.974 1.889 1.448 2.176 1.793 c
+2.459 2.135 2.852 2.308 3.352 2.308 c
+3.859 2.308 4.256 2.135 4.543 1.793 c
+4.825 1.448 4.969 0.974 4.969 0.368 c
+4.969 0.103 l
+4.969 -0.496 4.825 -0.966 4.543 -1.309 c
+4.256 -1.654 3.859 -1.823 3.352 -1.823 c
+2.841 -1.823 2.444 -1.654 2.161 -1.309 c
+1.885 -0.966 1.75 -0.492 1.75 0.118 c
+h
+2.793 0.103 m
+2.793 -0.603 2.977 -0.956 3.352 -0.956 c
+3.705 -0.956 3.896 -0.661 3.925 -0.073 c
+3.925 0.368 l
+3.925 0.727 3.874 0.999 3.778 1.176 c
+3.679 1.352 3.535 1.44 3.352 1.44 c
+3.176 1.44 3.036 1.352 2.941 1.176 c
+2.841 0.999 2.793 0.727 2.793 0.368 c
+h
+7.57 1.22 m
+7.232 1.249 l
+6.945 1.249 6.754 1.124 6.659 0.881 c
+6.659 -1.749 l
+5.615 -1.749 l
+5.615 2.234 l
+6.585 2.234 l
+6.615 1.793 l
+6.781 2.135 7.012 2.308 7.306 2.308 c
+7.423 2.308 7.516 2.286 7.585 2.249 c
+h
+9.437 -0.22 m
+9.158 -0.53 l
+9.158 -1.749 l
+8.115 -1.749 l
+8.115 3.896 l
+9.158 3.896 l
+9.158 0.852 l
+9.276 1.043 l
+9.996 2.234 l
+11.246 2.234 l
+10.084 0.588 l
+11.348 -1.749 l
+10.157 -1.749 l
+h
+12.803 -1.749 -1.044 3.983 re
+11.716 3.263 m
+11.716 3.418 11.763 3.547 11.863 3.645 c
+11.969 3.752 12.105 3.807 12.274 3.807 c
+12.451 3.807 12.586 3.752 12.686 3.645 c
+12.792 3.547 12.848 3.418 12.848 3.263 c
+12.848 3.094 12.792 2.959 12.686 2.851 c
+12.586 2.753 12.451 2.705 12.274 2.705 c
+12.105 2.705 11.969 2.753 11.863 2.851 c
+11.763 2.959 11.716 3.094 11.716 3.263 c
+14.567 2.234 m
+14.596 1.837 l
+14.832 2.15 15.133 2.308 15.508 2.308 c
+16.191 2.308 16.544 1.826 16.566 0.867 c
+16.566 -1.749 l
+15.522 -1.749 l
+15.522 0.794 l
+15.522 1.018 15.486 1.18 15.42 1.278 c
+15.35 1.374 15.232 1.426 15.067 1.426 c
+14.88 1.426 14.733 1.33 14.626 1.147 c
+14.626 -1.749 l
+13.582 -1.749 l
+13.582 2.234 l
+h
+17.184 0.368 m
+17.184 1.014 17.301 1.5 17.536 1.822 c
+17.771 2.146 18.103 2.308 18.536 2.308 c
+18.889 2.308 19.161 2.165 19.359 1.881 c
+19.404 2.234 l
+20.344 2.234 l
+20.344 -1.749 l
+20.344 -2.256 20.2 -2.646 19.917 -2.911 c
+19.631 -3.183 19.227 -3.322 18.698 -3.322 c
+18.47 -3.322 18.234 -3.278 17.993 -3.19 c
+17.757 -3.102 17.581 -2.988 17.463 -2.851 c
+17.816 -2.132 l
+17.912 -2.238 18.04 -2.323 18.198 -2.381 c
+18.352 -2.448 18.5 -2.485 18.639 -2.485 c
+18.874 -2.485 19.04 -2.425 19.138 -2.308 c
+19.246 -2.198 19.3 -2.021 19.3 -1.779 c
+19.3 -1.426 l
+19.102 -1.691 18.845 -1.823 18.521 -1.823 c
+18.099 -1.823 17.771 -1.661 17.536 -1.338 c
+17.309 -1.007 17.191 -0.536 17.184 0.073 c
+h
+18.228 0.103 m
+18.228 -0.272 18.275 -0.54 18.375 -0.706 c
+18.47 -0.875 18.624 -0.956 18.83 -0.956 c
+19.043 -0.956 19.201 -0.879 19.3 -0.721 c
+19.3 1.176 l
+19.19 1.341 19.036 1.426 18.83 1.426 c
+18.624 1.426 18.47 1.341 18.375 1.176 c
+18.275 1.007 18.228 0.738 18.228 0.368 c
+h
+22.696 0.368 m
+22.696 1.014 22.803 1.5 23.019 1.822 c
+23.244 2.146 23.566 2.308 23.989 2.308 c
+24.302 2.308 24.555 2.175 24.754 1.911 c
+24.754 3.896 l
+25.812 3.896 l
+25.812 -1.749 l
+24.856 -1.749 l
+24.813 -1.338 l
+24.596 -1.661 24.32 -1.823 23.989 -1.823 c
+23.578 -1.823 23.258 -1.668 23.034 -1.353 c
+22.817 -1.029 22.703 -0.559 22.696 0.058 c
+h
+23.74 0.103 m
+23.74 -0.291 23.776 -0.566 23.857 -0.721 c
+23.946 -0.879 24.092 -0.956 24.298 -0.956 c
+24.503 -0.956 24.655 -0.864 24.754 -0.676 c
+24.754 1.132 l
+24.655 1.326 24.503 1.426 24.298 1.426 c
+24.1 1.426 23.96 1.345 23.872 1.191 c
+23.784 1.043 23.74 0.771 23.74 0.382 c
+h
+27.664 -1.749 -1.044 3.983 re
+26.576 3.263 m
+26.576 3.418 26.624 3.547 26.724 3.645 c
+26.83 3.752 26.966 3.807 27.135 3.807 c
+27.312 3.807 27.447 3.752 27.547 3.645 c
+27.653 3.547 27.708 3.418 27.708 3.263 c
+27.708 3.094 27.653 2.959 27.547 2.851 c
+27.447 2.753 27.312 2.705 27.135 2.705 c
+26.966 2.705 26.83 2.753 26.724 2.851 c
+26.624 2.959 26.576 3.094 26.576 3.263 c
+30.427 1.22 m
+30.09 1.249 l
+29.803 1.249 29.612 1.124 29.517 0.881 c
+29.517 -1.749 l
+28.472 -1.749 l
+28.472 2.234 l
+29.442 2.234 l
+29.472 1.793 l
+29.637 2.135 29.868 2.308 30.163 2.308 c
+30.28 2.308 30.373 2.286 30.442 2.249 c
+h
+32.5 -1.823 m
+31.971 -1.823 31.552 -1.668 31.25 -1.353 c
+30.957 -1.029 30.809 -0.569 30.809 0.029 c
+30.809 0.338 l
+30.809 0.962 30.946 1.448 31.221 1.793 c
+31.493 2.135 31.886 2.308 32.397 2.308 c
+32.897 2.308 33.268 2.146 33.515 1.822 c
+33.768 1.5 33.9 1.022 33.911 0.397 c
+33.911 -0.103 l
+31.838 -0.103 l
+31.857 -0.397 31.919 -0.613 32.029 -0.75 c
+32.147 -0.889 32.328 -0.956 32.574 -0.956 c
+32.915 -0.956 33.205 -0.838 33.44 -0.603 c
+33.852 -1.235 l
+33.724 -1.411 33.536 -1.554 33.294 -1.661 c
+33.047 -1.768 32.783 -1.823 32.5 -1.823 c
+31.853 0.617 m
+32.883 0.617 l
+32.883 0.721 l
+32.883 0.956 32.842 1.132 32.765 1.249 c
+32.694 1.374 32.566 1.44 32.382 1.44 c
+32.206 1.44 32.074 1.371 31.985 1.234 c
+31.905 1.106 31.861 0.9 31.853 0.617 c
+35.94 -0.956 m
+36.233 -0.956 36.384 -0.761 36.395 -0.368 c
+37.365 -0.368 l
+37.365 -0.802 37.233 -1.154 36.968 -1.426 c
+36.704 -1.691 36.366 -1.823 35.954 -1.823 c
+35.443 -1.823 35.05 -1.668 34.778 -1.353 c
+34.514 -1.029 34.375 -0.559 34.367 0.058 c
+34.367 0.382 l
+34.367 1.007 34.499 1.484 34.764 1.808 c
+35.036 2.138 35.433 2.308 35.954 2.308 c
+36.384 2.308 36.726 2.168 36.983 1.897 c
+37.237 1.621 37.365 1.238 37.365 0.75 c
+36.395 0.75 l
+36.395 0.962 36.355 1.132 36.278 1.249 c
+36.208 1.374 36.091 1.44 35.925 1.44 c
+35.748 1.44 35.62 1.374 35.543 1.249 c
+35.462 1.12 35.418 0.871 35.41 0.5 c
+35.41 0.088 l
+35.41 -0.235 35.425 -0.463 35.455 -0.588 c
+35.491 -0.717 35.547 -0.808 35.616 -0.867 c
+35.694 -0.926 35.8 -0.956 35.94 -0.956 c
+39.173 3.204 m
+39.173 2.234 l
+39.703 2.234 l
+39.703 1.44 l
+39.173 1.44 l
+39.173 -0.53 l
+39.173 -0.687 39.192 -0.794 39.233 -0.852 c
+39.28 -0.912 39.364 -0.941 39.482 -0.941 c
+39.589 -0.941 39.673 -0.933 39.732 -0.912 c
+39.732 -1.72 l
+39.555 -1.786 39.364 -1.823 39.159 -1.823 c
+38.483 -1.823 38.138 -1.437 38.13 -0.661 c
+38.13 1.44 l
+37.674 1.44 l
+37.674 2.234 l
+38.13 2.234 l
+38.13 3.204 l
+h
+40.056 0.368 m
+40.056 0.974 40.195 1.448 40.482 1.793 c
+40.765 2.135 41.157 2.308 41.658 2.308 c
+42.165 2.308 42.562 2.135 42.848 1.793 c
+43.131 1.448 43.274 0.974 43.274 0.368 c
+43.274 0.103 l
+43.274 -0.496 43.131 -0.966 42.848 -1.309 c
+42.562 -1.654 42.165 -1.823 41.658 -1.823 c
+41.147 -1.823 40.75 -1.654 40.467 -1.309 c
+40.191 -0.966 40.056 -0.492 40.056 0.118 c
+h
+41.099 0.103 m
+41.099 -0.603 41.282 -0.956 41.658 -0.956 c
+42.011 -0.956 42.202 -0.661 42.231 -0.073 c
+42.231 0.368 l
+42.231 0.727 42.179 0.999 42.084 1.176 c
+41.984 1.352 41.841 1.44 41.658 1.44 c
+41.481 1.44 41.342 1.352 41.246 1.176 c
+41.147 0.999 41.099 0.727 41.099 0.368 c
+h
+45.876 1.22 m
+45.538 1.249 l
+45.251 1.249 45.06 1.124 44.965 0.881 c
+44.965 -1.749 l
+43.921 -1.749 l
+43.921 2.234 l
+44.891 2.234 l
+44.92 1.793 l
+45.086 2.135 45.317 2.308 45.612 2.308 c
+45.729 2.308 45.822 2.286 45.891 2.249 c
+h
+47.773 -0.015 m
+48.301 2.234 l
+49.404 2.234 l
+48.096 -2.352 l
+47.898 -3.017 47.53 -3.352 46.994 -3.352 c
+46.865 -3.352 46.722 -3.329 46.567 -3.293 c
+46.567 -2.469 l
+46.685 -2.485 l
+46.85 -2.485 46.971 -2.448 47.052 -2.381 c
+47.129 -2.323 47.192 -2.213 47.243 -2.058 c
+47.316 -1.793 l
+46.171 2.234 l
+47.287 2.234 l
+h
+f
+Q
+q 1 0 0 1 471.5352 360.1369 cm
+0 0 m
+-0.04 0.087 -0.066 0.235 -0.073 0.44 c
+-0.309 0.095 -0.603 -0.074 -0.956 -0.074 c
+-1.319 -0.074 -1.602 0.022 -1.808 0.22 c
+-2.007 0.426 -2.102 0.712 -2.102 1.087 c
+-2.102 1.488 -1.966 1.807 -1.691 2.042 c
+-1.419 2.285 -1.044 2.41 -0.574 2.41 c
+-0.088 2.41 l
+-0.088 2.836 l
+-0.088 3.071 -0.143 3.237 -0.25 3.336 c
+-0.36 3.443 -0.522 3.498 -0.735 3.498 c
+-0.933 3.498 -1.095 3.439 -1.22 3.322 c
+-1.338 3.204 -1.396 3.057 -1.396 2.881 c
+-2.043 2.881 l
+-2.043 3.075 -1.985 3.266 -1.866 3.453 c
+-1.742 3.638 -1.58 3.785 -1.382 3.895 c
+-1.176 4.002 -0.948 4.056 -0.691 4.056 c
+-0.291 4.056 0.015 3.954 0.22 3.748 c
+0.434 3.542 0.547 3.248 0.559 2.865 c
+0.559 0.852 l
+0.559 0.547 0.595 0.282 0.676 0.058 c
+0.676 0 l
+h
+-0.867 0.514 m
+-0.702 0.514 -0.551 0.558 -0.412 0.646 c
+-0.264 0.735 -0.158 0.845 -0.088 0.984 c
+-0.088 1.925 l
+-0.455 1.925 l
+-0.771 1.925 -1.014 1.855 -1.191 1.72 c
+-1.367 1.591 -1.455 1.404 -1.455 1.161 c
+-1.455 0.933 -1.411 0.768 -1.323 0.661 c
+-1.235 0.562 -1.084 0.514 -0.867 0.514 c
+2.175 3.983 m
+2.19 3.542 l
+2.444 3.884 2.767 4.056 3.16 4.056 c
+3.865 4.056 4.222 3.586 4.233 2.645 c
+4.233 0 l
+3.586 0 l
+3.586 2.616 l
+3.586 2.929 3.532 3.149 3.424 3.278 c
+3.314 3.403 3.16 3.469 2.954 3.469 c
+2.797 3.469 2.649 3.414 2.514 3.307 c
+2.385 3.197 2.282 3.061 2.205 2.896 c
+2.205 0 l
+1.558 0 l
+1.558 3.983 l
+h
+5.071 2.175 m
+5.071 2.782 5.182 3.248 5.409 3.571 c
+5.644 3.895 5.972 4.056 6.394 4.056 c
+6.776 4.056 7.073 3.898 7.291 3.586 c
+7.291 5.644 l
+7.937 5.644 l
+7.937 0 l
+7.349 0 l
+7.306 0.426 l
+7.1 0.091 6.795 -0.074 6.394 -0.074 c
+5.982 -0.074 5.659 0.081 5.424 0.396 c
+5.189 0.72 5.071 1.176 5.071 1.764 c
+h
+5.718 1.793 m
+5.718 1.352 5.78 1.022 5.909 0.808 c
+6.045 0.602 6.265 0.5 6.57 0.5 c
+6.894 0.5 7.133 0.661 7.291 0.984 c
+7.291 2.998 l
+7.121 3.31 6.882 3.469 6.57 3.469 c
+6.265 3.469 6.045 3.366 5.909 3.16 c
+5.78 2.954 5.718 2.63 5.718 2.19 c
+h
+f
+Q
+q 1 0 0 1 483.8532 361.2093 cm
+0 0 m
+0 0.088 -0.044 0.166 -0.133 0.235 c
+-0.221 0.312 -0.408 0.416 -0.691 0.544 c
+-1.125 0.721 -1.422 0.9 -1.588 1.087 c
+-1.746 1.272 -1.823 1.503 -1.823 1.779 c
+-1.823 2.12 -1.702 2.404 -1.455 2.631 c
+-1.202 2.866 -0.864 2.984 -0.441 2.984 c
+-0.011 2.984 0.338 2.87 0.602 2.646 c
+0.867 2.419 0.999 2.117 0.999 1.735 c
+-0.044 1.735 l
+-0.044 2.058 -0.184 2.22 -0.456 2.22 c
+-0.566 2.22 -0.655 2.183 -0.721 2.117 c
+-0.79 2.047 -0.823 1.948 -0.823 1.823 c
+-0.823 1.735 -0.786 1.654 -0.706 1.588 c
+-0.628 1.529 -0.449 1.434 -0.162 1.309 c
+0.268 1.151 0.565 0.974 0.735 0.779 c
+0.911 0.592 0.999 0.342 0.999 0.029 c
+0.999 -0.324 0.867 -0.61 0.602 -0.823 c
+0.338 -1.039 -0.011 -1.147 -0.441 -1.147 c
+-0.736 -1.147 -0.996 -1.091 -1.22 -0.985 c
+-1.448 -0.867 -1.625 -0.706 -1.75 -0.5 c
+-1.867 -0.293 -1.926 -0.073 -1.926 0.162 c
+-0.941 0.162 l
+-0.941 -0.025 -0.904 -0.162 -0.823 -0.249 c
+-0.736 -0.338 -0.603 -0.382 -0.427 -0.382 c
+-0.144 -0.382 0 -0.257 0 0 c
+2.866 3.881 m
+2.866 2.911 l
+3.395 2.911 l
+3.395 2.117 l
+2.866 2.117 l
+2.866 0.147 l
+2.866 -0.01 2.884 -0.118 2.925 -0.176 c
+2.973 -0.235 3.057 -0.264 3.175 -0.264 c
+3.281 -0.264 3.366 -0.257 3.424 -0.235 c
+3.424 -1.043 l
+3.248 -1.109 3.057 -1.147 2.851 -1.147 c
+2.175 -1.147 1.83 -0.76 1.822 0.015 c
+1.822 2.117 l
+1.367 2.117 l
+1.367 2.911 l
+1.822 2.911 l
+1.822 3.881 l
+h
+5.85 -1.072 m
+5.82 -1.014 5.791 -0.912 5.762 -0.764 c
+5.574 -1.022 5.325 -1.147 5.012 -1.147 c
+4.677 -1.147 4.398 -1.039 4.174 -0.823 c
+3.958 -0.598 3.85 -0.309 3.85 0.044 c
+3.85 0.456 3.983 0.772 4.247 1 c
+4.512 1.235 4.895 1.353 5.394 1.353 c
+5.718 1.353 l
+5.718 1.675 l
+5.718 1.852 5.681 1.974 5.614 2.043 c
+5.556 2.12 5.468 2.161 5.35 2.161 c
+5.093 2.161 4.968 2.007 4.968 1.706 c
+3.925 1.706 l
+3.925 2.076 4.06 2.381 4.336 2.616 c
+4.608 2.859 4.957 2.984 5.379 2.984 c
+5.82 2.984 6.158 2.866 6.393 2.631 c
+6.636 2.404 6.761 2.08 6.761 1.661 c
+6.761 -0.206 l
+6.761 -0.551 6.809 -0.819 6.908 -1.014 c
+6.908 -1.072 l
+h
+5.247 -0.324 m
+5.354 -0.324 5.446 -0.305 5.527 -0.264 c
+5.614 -0.216 5.677 -0.158 5.718 -0.088 c
+5.718 0.735 l
+5.468 0.735 l
+5.292 0.735 5.148 0.676 5.041 0.559 c
+4.943 0.449 4.895 0.302 4.895 0.118 c
+4.895 -0.176 5.012 -0.324 5.247 -0.324 c
+7.378 1.044 m
+7.378 1.691 7.496 2.176 7.731 2.499 c
+7.966 2.822 8.297 2.984 8.731 2.984 c
+9.084 2.984 9.356 2.841 9.554 2.558 c
+9.598 2.911 l
+10.539 2.911 l
+10.539 -1.072 l
+10.539 -1.579 10.395 -1.97 10.113 -2.234 c
+9.826 -2.506 9.422 -2.645 8.893 -2.645 c
+8.665 -2.645 8.43 -2.601 8.187 -2.514 c
+7.952 -2.425 7.775 -2.311 7.658 -2.175 c
+8.01 -1.455 l
+8.106 -1.562 8.235 -1.646 8.393 -1.705 c
+8.548 -1.771 8.694 -1.808 8.834 -1.808 c
+9.069 -1.808 9.234 -1.749 9.334 -1.631 c
+9.44 -1.521 9.495 -1.344 9.495 -1.103 c
+9.495 -0.75 l
+9.296 -1.014 9.04 -1.147 8.716 -1.147 c
+8.294 -1.147 7.966 -0.985 7.731 -0.661 c
+7.503 -0.33 7.386 0.14 7.378 0.75 c
+h
+8.422 0.779 m
+8.422 0.405 8.47 0.136 8.569 -0.029 c
+8.665 -0.198 8.819 -0.279 9.025 -0.279 c
+9.238 -0.279 9.396 -0.202 9.495 -0.044 c
+9.495 1.852 l
+9.385 2.018 9.231 2.103 9.025 2.103 c
+8.819 2.103 8.665 2.018 8.569 1.852 c
+8.47 1.683 8.422 1.415 8.422 1.044 c
+h
+12.391 -1.072 -1.044 3.983 re
+11.303 3.94 m
+11.303 4.094 11.351 4.223 11.451 4.322 c
+11.557 4.428 11.692 4.484 11.862 4.484 c
+12.038 4.484 12.174 4.428 12.273 4.322 c
+12.38 4.223 12.435 4.094 12.435 3.94 c
+12.435 3.771 12.38 3.635 12.273 3.528 c
+12.174 3.429 12.038 3.381 11.862 3.381 c
+11.692 3.381 11.557 3.429 11.451 3.528 c
+11.351 3.635 11.303 3.771 11.303 3.94 c
+14.154 2.911 m
+14.184 2.514 l
+14.42 2.826 14.721 2.984 15.095 2.984 c
+15.779 2.984 16.132 2.502 16.154 1.544 c
+16.154 -1.072 l
+15.11 -1.072 l
+15.11 1.47 l
+15.11 1.694 15.073 1.856 15.008 1.955 c
+14.938 2.051 14.82 2.103 14.655 2.103 c
+14.468 2.103 14.32 2.007 14.214 1.823 c
+14.214 -1.072 l
+13.17 -1.072 l
+13.17 2.911 l
+h
+16.772 1.044 m
+16.772 1.691 16.889 2.176 17.124 2.499 c
+17.359 2.822 17.69 2.984 18.123 2.984 c
+18.476 2.984 18.748 2.841 18.947 2.558 c
+18.991 2.911 l
+19.931 2.911 l
+19.931 -1.072 l
+19.931 -1.579 19.788 -1.97 19.505 -2.234 c
+19.218 -2.506 18.815 -2.645 18.285 -2.645 c
+18.057 -2.645 17.822 -2.601 17.58 -2.514 c
+17.344 -2.425 17.168 -2.311 17.051 -2.175 c
+17.404 -1.455 l
+17.499 -1.562 17.628 -1.646 17.786 -1.705 c
+17.94 -1.771 18.087 -1.808 18.227 -1.808 c
+18.462 -1.808 18.627 -1.749 18.726 -1.631 c
+18.833 -1.521 18.888 -1.344 18.888 -1.103 c
+18.888 -0.75 l
+18.69 -1.014 18.432 -1.147 18.109 -1.147 c
+17.686 -1.147 17.359 -0.985 17.124 -0.661 c
+16.897 -0.33 16.779 0.14 16.772 0.75 c
+h
+17.815 0.779 m
+17.815 0.405 17.863 0.136 17.962 -0.029 c
+18.057 -0.198 18.212 -0.279 18.418 -0.279 c
+18.63 -0.279 18.788 -0.202 18.888 -0.044 c
+18.888 1.852 l
+18.778 2.018 18.623 2.103 18.418 2.103 c
+18.212 2.103 18.057 2.018 17.962 1.852 c
+17.863 1.683 17.815 1.415 17.815 1.044 c
+h
+24.312 -1.072 m
+24.282 -1.014 24.253 -0.912 24.224 -0.764 c
+24.036 -1.022 23.787 -1.147 23.474 -1.147 c
+23.139 -1.147 22.86 -1.039 22.636 -0.823 c
+22.42 -0.598 22.312 -0.309 22.312 0.044 c
+22.312 0.456 22.445 0.772 22.709 1 c
+22.975 1.235 23.357 1.353 23.856 1.353 c
+24.18 1.353 l
+24.18 1.675 l
+24.18 1.852 24.143 1.974 24.076 2.043 c
+24.018 2.12 23.93 2.161 23.812 2.161 c
+23.555 2.161 23.43 2.007 23.43 1.706 c
+22.386 1.706 l
+22.386 2.076 22.522 2.381 22.798 2.616 c
+23.07 2.859 23.419 2.984 23.841 2.984 c
+24.282 2.984 24.621 2.866 24.856 2.631 c
+25.098 2.404 25.223 2.08 25.223 1.661 c
+25.223 -0.206 l
+25.223 -0.551 25.271 -0.819 25.37 -1.014 c
+25.37 -1.072 l
+h
+23.709 -0.324 m
+23.816 -0.324 23.908 -0.305 23.989 -0.264 c
+24.076 -0.216 24.139 -0.158 24.18 -0.088 c
+24.18 0.735 l
+23.93 0.735 l
+23.754 0.735 23.61 0.676 23.503 0.559 c
+23.405 0.449 23.357 0.302 23.357 0.118 c
+23.357 -0.176 23.474 -0.324 23.709 -0.324 c
+27.928 1.897 m
+27.59 1.926 l
+27.303 1.926 27.112 1.801 27.016 1.558 c
+27.016 -1.072 l
+25.973 -1.072 l
+25.973 2.911 l
+26.943 2.911 l
+26.973 2.469 l
+27.137 2.812 27.369 2.984 27.663 2.984 c
+27.781 2.984 27.873 2.962 27.943 2.926 c
+h
+30 -1.147 m
+29.471 -1.147 29.052 -0.992 28.751 -0.676 c
+28.457 -0.353 28.31 0.107 28.31 0.706 c
+28.31 1.014 l
+28.31 1.639 28.446 2.124 28.722 2.469 c
+28.994 2.812 29.387 2.984 29.898 2.984 c
+30.397 2.984 30.769 2.822 31.014 2.499 c
+31.268 2.176 31.401 1.698 31.411 1.073 c
+31.411 0.574 l
+29.339 0.574 l
+29.358 0.279 29.42 0.063 29.53 -0.073 c
+29.647 -0.213 29.828 -0.279 30.074 -0.279 c
+30.416 -0.279 30.706 -0.162 30.941 0.073 c
+31.353 -0.559 l
+31.224 -0.735 31.037 -0.878 30.794 -0.985 c
+30.548 -1.091 30.283 -1.147 30 -1.147 c
+29.354 1.294 m
+30.382 1.294 l
+30.382 1.397 l
+30.382 1.632 30.343 1.808 30.265 1.926 c
+30.195 2.051 30.067 2.117 29.883 2.117 c
+29.707 2.117 29.574 2.047 29.486 1.911 c
+29.405 1.783 29.361 1.577 29.354 1.294 c
+33.881 -1.072 m
+33.852 -1.014 33.822 -0.912 33.793 -0.764 c
+33.605 -1.022 33.356 -1.147 33.043 -1.147 c
+32.709 -1.147 32.429 -1.039 32.205 -0.823 c
+31.989 -0.598 31.882 -0.309 31.882 0.044 c
+31.882 0.456 32.014 0.772 32.279 1 c
+32.543 1.235 32.926 1.353 33.425 1.353 c
+33.749 1.353 l
+33.749 1.675 l
+33.749 1.852 33.712 1.974 33.646 2.043 c
+33.587 2.12 33.499 2.161 33.381 2.161 c
+33.124 2.161 32.999 2.007 32.999 1.706 c
+31.955 1.706 l
+31.955 2.076 32.091 2.381 32.367 2.616 c
+32.639 2.859 32.988 2.984 33.41 2.984 c
+33.852 2.984 34.189 2.866 34.424 2.631 c
+34.667 2.404 34.792 2.08 34.792 1.661 c
+34.792 -0.206 l
+34.792 -0.551 34.84 -0.819 34.939 -1.014 c
+34.939 -1.072 l
+h
+33.279 -0.324 m
+33.385 -0.324 33.477 -0.305 33.558 -0.264 c
+33.646 -0.216 33.709 -0.158 33.749 -0.088 c
+33.749 0.735 l
+33.499 0.735 l
+33.323 0.735 33.179 0.676 33.073 0.559 c
+32.973 0.449 32.926 0.302 32.926 0.118 c
+32.926 -0.176 33.043 -0.324 33.279 -0.324 c
+f
+Q
+q 1 0 0 1 519.5421 360.4896 cm
+0 0 m
+0 0.118 0.033 0.213 0.103 0.294 c
+0.169 0.371 0.272 0.411 0.412 0.411 c
+0.559 0.411 0.665 0.371 0.735 0.294 c
+0.812 0.213 0.852 0.118 0.852 0 c
+0.852 -0.111 0.812 -0.202 0.735 -0.279 c
+0.665 -0.357 0.559 -0.397 0.412 -0.397 c
+0.272 -0.397 0.169 -0.357 0.103 -0.279 c
+0.033 -0.202 0 -0.111 0 0 c
+f
+Q
+0.113 0.082 0.09 0 k
+287.665 356.035 234.667 -12.895 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 349.197 cm
+0 0 m
+0 -0.188 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.647 -0.243 -0.776 -0.367 -0.882 c
+-0.496 -0.992 -0.658 -1.081 -0.852 -1.147 c
+-1.051 -1.206 -1.278 -1.243 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.162 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.927 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.132 l
+-2.642 0.033 -2.616 -0.059 -2.587 -0.148 c
+-2.55 -0.228 -2.506 -0.302 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.675 c
+-1.977 0.683 -1.992 0.691 -1.999 0.691 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.881 -2.786 0.959 -2.91 1.058 c
+-3.039 1.153 -3.142 1.278 -3.219 1.425 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.836 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.042 c
+-0.804 2.991 -0.669 2.917 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.882 l
+-1.01 2.252 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.352 c
+-1.294 1.311 -1.117 1.263 -0.941 1.205 c
+-0.756 1.146 -0.595 1.066 -0.455 0.97 c
+-0.32 0.87 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.319 2.385 -2.366 2.337 c
+-2.406 2.296 -2.436 2.248 -2.454 2.19 c
+-2.477 2.131 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.778 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.201 1.558 -2.131 1.529 c
+-2.065 1.499 -1.984 1.469 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.091 -0.86 0.176 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.529 -1.448 0.558 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.53 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.66 m
+6.184 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.22 5.108 -2.103 c
+5.039 -1.985 4.991 -1.856 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.754 5.964 -1.86 6.064 -1.941 c
+6.159 -2.029 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.058 6.681 -2.029 c
+6.758 -1.999 6.828 -1.945 6.887 -1.867 c
+6.945 -1.797 6.99 -1.706 7.019 -1.588 c
+7.056 -1.47 7.078 -1.324 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.89 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.073 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.412 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.234 c
+4.946 1.448 5.027 1.631 5.137 1.778 c
+5.244 1.932 5.376 2.05 5.534 2.131 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.252 6.387 2.234 c
+6.483 2.212 6.571 2.179 6.652 2.131 c
+6.739 2.08 6.817 2.017 6.887 1.94 c
+6.964 1.859 7.026 1.768 7.078 1.66 c
+7.092 1.66 l
+7.092 1.808 l
+7.1 1.866 7.107 1.918 7.107 1.969 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.164 7.14 2.198 7.151 2.219 c
+8.004 2.219 l
+7.993 2.138 7.982 2.028 7.975 1.882 c
+7.975 1.411 l
+7.975 -1.162 l
+7.975 -1.415 7.938 -1.636 7.871 -1.823 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.5 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.529 m
+7.092 0.742 7.067 0.918 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.499 6.729 1.558 6.652 1.587 c
+6.571 1.624 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.62 6.137 1.573 c
+6.056 1.532 5.99 1.462 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.874 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.339 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.383 c
+6.924 -0.294 6.978 -0.177 7.019 -0.03 c
+7.067 0.118 7.092 0.301 7.092 0.529 c
+11.036 -0.647 m
+12.168 -0.647 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.647 l
+10.124 -0.647 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.676 re
+10.124 2.836 m
+13.597 1.602 m
+13.053 1.602 l
+13.053 2.219 l
+13.641 2.219 l
+13.92 3.116 l
+14.494 3.116 l
+14.494 2.219 l
+15.728 2.219 l
+15.728 1.602 l
+14.494 1.602 l
+14.494 -0.103 l
+14.494 -0.324 l
+14.501 -0.393 14.523 -0.456 14.552 -0.515 c
+14.589 -0.566 14.645 -0.611 14.714 -0.647 c
+14.791 -0.676 14.905 -0.691 15.052 -0.691 c
+15.188 -0.691 15.324 -0.688 15.464 -0.676 c
+15.599 -0.659 15.732 -0.632 15.861 -0.603 c
+15.861 -1.206 l
+15.78 -1.216 15.703 -1.231 15.626 -1.249 c
+15.545 -1.261 15.468 -1.268 15.391 -1.279 c
+15.31 -1.286 15.221 -1.294 15.125 -1.294 c
+15.038 -1.301 14.938 -1.309 14.832 -1.309 c
+14.645 -1.309 14.483 -1.294 14.346 -1.264 c
+14.218 -1.228 14.104 -1.183 14.009 -1.132 c
+13.92 -1.085 13.847 -1.025 13.788 -0.956 c
+13.729 -0.879 13.685 -0.801 13.656 -0.721 c
+13.627 -0.632 13.604 -0.544 13.597 -0.456 c
+13.586 -0.36 13.582 -0.265 13.582 -0.177 c
+h
+23.295 -1.264 m
+23.283 -1.246 23.273 -1.216 23.265 -1.176 c
+23.265 -1.129 23.258 -1.081 23.25 -1.029 c
+23.25 -0.971 23.243 -0.912 23.236 -0.853 c
+23.236 -0.691 l
+23.118 -0.927 22.975 -1.095 22.809 -1.191 c
+22.641 -1.279 22.442 -1.324 22.207 -1.324 c
+22.009 -1.324 21.832 -1.279 21.677 -1.191 c
+21.519 -1.103 21.388 -0.981 21.28 -0.823 c
+21.182 -0.659 21.105 -0.467 21.045 -0.25 c
+20.994 -0.037 20.972 0.205 20.972 0.47 c
+20.972 0.735 20.994 0.974 21.045 1.19 c
+21.105 1.415 21.182 1.606 21.28 1.764 c
+21.388 1.918 21.519 2.043 21.677 2.131 c
+21.843 2.227 22.034 2.278 22.251 2.278 c
+22.346 2.278 22.442 2.263 22.531 2.234 c
+22.626 2.212 22.722 2.179 22.809 2.131 c
+22.898 2.08 22.975 2.017 23.044 1.94 c
+23.121 1.859 23.185 1.768 23.236 1.66 c
+23.236 1.749 l
+23.236 1.896 l
+23.236 2.057 l
+23.236 2.234 l
+23.236 3.513 l
+24.133 3.513 l
+24.133 -0.5 l
+24.133 -0.676 24.137 -0.834 24.147 -0.971 c
+24.154 -1.099 24.162 -1.199 24.162 -1.264 c
+h
+23.25 0.484 m
+23.25 0.72 23.225 0.911 23.177 1.058 c
+23.137 1.213 23.081 1.338 23.015 1.425 c
+22.957 1.514 22.886 1.573 22.809 1.602 c
+22.728 1.639 22.651 1.66 22.574 1.66 c
+22.475 1.66 22.383 1.635 22.296 1.587 c
+22.215 1.547 22.148 1.477 22.09 1.381 c
+22.038 1.282 21.994 1.161 21.957 1.014 c
+21.928 0.867 21.913 0.683 21.913 0.47 c
+21.913 0.077 21.964 -0.217 22.074 -0.412 c
+22.192 -0.611 22.354 -0.706 22.56 -0.706 c
+22.637 -0.706 22.714 -0.688 22.795 -0.647 c
+22.872 -0.611 22.946 -0.544 23.015 -0.456 c
+23.081 -0.368 23.137 -0.246 23.177 -0.088 c
+23.225 0.066 23.25 0.257 23.25 0.484 c
+27.281 -0.647 m
+28.413 -0.647 l
+28.413 -1.264 l
+25.106 -1.264 l
+25.106 -0.647 l
+26.371 -0.647 l
+26.371 1.602 l
+25.444 1.602 l
+25.444 2.219 l
+27.281 2.219 l
+h
+26.371 3.513 0.911 -0.676 re
+26.371 2.836 m
+30.886 1.602 m
+30.886 -1.264 l
+29.99 -1.264 l
+29.99 1.602 l
+29.167 1.602 l
+29.167 2.219 l
+29.99 2.219 l
+29.99 2.484 l
+29.99 2.609 30.005 2.741 30.034 2.881 c
+30.071 3.017 30.14 3.135 30.24 3.233 c
+30.346 3.34 30.489 3.428 30.666 3.498 c
+30.842 3.564 31.067 3.601 31.343 3.601 c
+31.555 3.601 31.754 3.59 31.931 3.572 c
+32.107 3.549 32.257 3.532 32.386 3.513 c
+32.386 2.925 l
+32.257 2.944 32.114 2.958 31.96 2.969 c
+31.802 2.977 31.651 2.984 31.504 2.984 c
+31.376 2.984 31.272 2.969 31.195 2.94 c
+31.114 2.91 31.052 2.869 31.004 2.822 c
+30.953 2.771 30.919 2.708 30.901 2.631 c
+30.89 2.561 30.886 2.484 30.886 2.396 c
+30.886 2.219 l
+32.313 2.219 l
+32.313 1.602 l
+h
+34.948 1.602 m
+34.948 -1.264 l
+34.051 -1.264 l
+34.051 1.602 l
+33.228 1.602 l
+33.228 2.219 l
+34.051 2.219 l
+34.051 2.484 l
+34.051 2.609 34.065 2.741 34.094 2.881 c
+34.132 3.017 34.202 3.135 34.3 3.233 c
+34.407 3.34 34.551 3.428 34.726 3.498 c
+34.903 3.564 35.127 3.601 35.403 3.601 c
+35.616 3.601 35.815 3.59 35.991 3.572 c
+36.168 3.549 36.318 3.532 36.446 3.513 c
+36.446 2.925 l
+36.318 2.944 36.174 2.958 36.02 2.969 c
+35.862 2.977 35.711 2.984 35.565 2.984 c
+35.436 2.984 35.333 2.969 35.256 2.94 c
+35.175 2.91 35.112 2.869 35.065 2.822 c
+35.013 2.771 34.98 2.708 34.962 2.631 c
+34.951 2.561 34.948 2.484 34.948 2.396 c
+34.948 2.219 l
+36.373 2.219 l
+36.373 1.602 l
+h
+42.013 0.837 1.867 -0.793 re
+42.013 0.044 m
+46.075 0.837 1.866 -0.793 re
+46.075 0.044 m
+52.648 -0.25 m
+52.648 -0.42 52.608 -0.57 52.531 -0.706 c
+52.461 -0.834 52.359 -0.948 52.222 -1.044 c
+52.093 -1.132 51.932 -1.202 51.737 -1.249 c
+51.55 -1.297 51.333 -1.324 51.091 -1.324 c
+50.863 -1.324 50.664 -1.309 50.488 -1.279 c
+50.312 -1.249 50.154 -1.202 50.017 -1.132 c
+49.878 -1.055 49.768 -0.956 49.68 -0.838 c
+49.591 -0.721 49.521 -0.574 49.473 -0.397 c
+50.283 -0.279 l
+50.3 -0.379 50.33 -0.456 50.37 -0.515 c
+50.418 -0.574 50.477 -0.618 50.547 -0.647 c
+50.613 -0.676 50.694 -0.702 50.782 -0.721 c
+50.87 -0.732 50.973 -0.736 51.091 -0.736 c
+51.186 -0.736 51.282 -0.732 51.37 -0.721 c
+51.458 -0.702 51.536 -0.676 51.605 -0.647 c
+51.671 -0.618 51.723 -0.58 51.752 -0.53 c
+51.789 -0.482 51.81 -0.42 51.81 -0.339 c
+51.81 -0.243 51.781 -0.169 51.723 -0.118 c
+51.671 -0.071 51.605 -0.03 51.517 0 c
+51.428 0.037 51.318 0.066 51.193 0.087 c
+51.076 0.118 50.944 0.147 50.796 0.176 c
+50.657 0.213 50.518 0.253 50.37 0.294 c
+50.231 0.341 50.106 0.404 49.988 0.484 c
+49.878 0.562 49.79 0.661 49.724 0.779 c
+49.654 0.897 49.62 1.047 49.62 1.234 c
+49.62 1.389 49.65 1.532 49.709 1.66 c
+49.775 1.797 49.87 1.911 49.988 1.999 c
+50.113 2.087 50.271 2.153 50.458 2.204 c
+50.642 2.252 50.855 2.278 51.091 2.278 c
+51.274 2.278 51.451 2.256 51.619 2.219 c
+51.785 2.19 51.932 2.135 52.061 2.057 c
+52.186 1.988 52.296 1.889 52.384 1.764 c
+52.473 1.646 52.531 1.502 52.56 1.338 c
+51.767 1.263 l
+51.744 1.341 51.715 1.404 51.679 1.455 c
+51.638 1.514 51.59 1.558 51.532 1.587 c
+51.48 1.624 51.418 1.65 51.34 1.66 c
+51.26 1.668 51.179 1.675 51.091 1.675 c
+50.873 1.675 50.712 1.646 50.605 1.587 c
+50.495 1.536 50.443 1.448 50.443 1.323 c
+50.443 1.242 50.462 1.18 50.503 1.132 c
+50.551 1.08 50.613 1.043 50.694 1.014 c
+50.782 0.985 50.877 0.955 50.988 0.926 c
+51.094 0.904 51.216 0.881 51.355 0.852 c
+51.509 0.823 51.667 0.783 51.825 0.735 c
+51.98 0.683 52.12 0.621 52.237 0.544 c
+52.355 0.463 52.45 0.36 52.531 0.235 c
+52.608 0.106 52.648 -0.055 52.648 -0.25 c
+54.21 1.602 m
+53.666 1.602 l
+53.666 2.219 l
+54.254 2.219 l
+54.534 3.116 l
+55.107 3.116 l
+55.107 2.219 l
+56.342 2.219 l
+56.342 1.602 l
+55.107 1.602 l
+55.107 -0.103 l
+55.107 -0.324 l
+55.114 -0.393 55.137 -0.456 55.166 -0.515 c
+55.203 -0.566 55.258 -0.611 55.328 -0.647 c
+55.405 -0.676 55.519 -0.691 55.665 -0.691 c
+55.802 -0.691 55.937 -0.688 56.077 -0.676 c
+56.213 -0.659 56.346 -0.632 56.474 -0.603 c
+56.474 -1.206 l
+56.394 -1.216 56.316 -1.231 56.239 -1.249 c
+56.158 -1.261 56.081 -1.268 56.004 -1.279 c
+55.923 -1.286 55.835 -1.294 55.739 -1.294 c
+55.651 -1.301 55.552 -1.309 55.445 -1.309 c
+55.258 -1.309 55.096 -1.294 54.96 -1.264 c
+54.831 -1.228 54.717 -1.183 54.622 -1.132 c
+54.534 -1.085 54.46 -1.025 54.401 -0.956 c
+54.343 -0.879 54.299 -0.801 54.269 -0.721 c
+54.24 -0.632 54.218 -0.544 54.21 -0.456 c
+54.2 -0.36 54.196 -0.265 54.196 -0.177 c
+h
+58.628 -1.324 m
+58.458 -1.324 58.308 -1.301 58.172 -1.264 c
+58.044 -1.216 57.929 -1.147 57.834 -1.058 c
+57.745 -0.971 57.676 -0.864 57.628 -0.736 c
+57.576 -0.599 57.554 -0.449 57.554 -0.279 c
+57.554 -0.073 57.587 0.095 57.657 0.235 c
+57.724 0.382 57.819 0.492 57.936 0.573 c
+58.061 0.661 58.204 0.723 58.363 0.764 c
+58.528 0.801 58.705 0.827 58.892 0.837 c
+59.612 0.852 l
+59.612 1.028 l
+59.612 1.146 59.601 1.249 59.583 1.338 c
+59.561 1.425 59.528 1.492 59.48 1.543 c
+59.44 1.602 59.392 1.639 59.333 1.66 c
+59.274 1.679 59.208 1.691 59.141 1.691 c
+59.072 1.691 59.01 1.679 58.951 1.66 c
+58.9 1.65 58.852 1.624 58.804 1.587 c
+58.763 1.558 58.73 1.506 58.701 1.44 c
+58.679 1.381 58.664 1.301 58.657 1.205 c
+57.716 1.249 l
+57.745 1.396 57.79 1.532 57.848 1.66 c
+57.915 1.786 58.01 1.896 58.127 1.984 c
+58.245 2.08 58.385 2.153 58.554 2.204 c
+58.73 2.252 58.936 2.278 59.172 2.278 c
+59.612 2.278 59.943 2.167 60.171 1.955 c
+60.406 1.749 60.523 1.44 60.523 1.028 c
+60.523 -0.235 l
+60.523 -0.456 l
+60.531 -0.515 60.546 -0.57 60.568 -0.618 c
+60.586 -0.659 60.616 -0.691 60.656 -0.721 c
+60.693 -0.742 60.744 -0.75 60.803 -0.75 c
+60.869 -0.75 60.939 -0.746 61.009 -0.736 c
+61.009 -1.22 l
+60.95 -1.231 60.895 -1.243 60.847 -1.249 c
+60.807 -1.261 60.766 -1.268 60.729 -1.279 c
+60.689 -1.286 60.645 -1.294 60.597 -1.294 c
+60.546 -1.301 60.487 -1.309 60.421 -1.309 c
+60.193 -1.309 60.028 -1.257 59.921 -1.147 c
+59.81 -1.029 59.748 -0.864 59.729 -0.647 c
+59.715 -0.647 l
+59.646 -0.757 59.575 -0.853 59.509 -0.941 c
+59.44 -1.022 59.363 -1.088 59.274 -1.147 c
+59.186 -1.206 59.087 -1.249 58.981 -1.279 c
+58.881 -1.309 58.763 -1.324 58.628 -1.324 c
+59.612 0.353 m
+59.186 0.338 l
+59.087 0.338 58.995 0.33 58.906 0.323 c
+58.826 0.312 58.76 0.286 58.701 0.249 c
+58.642 0.209 58.591 0.151 58.554 0.073 c
+58.514 0.004 58.495 -0.088 58.495 -0.206 c
+58.495 -0.375 58.528 -0.497 58.598 -0.574 c
+58.664 -0.655 58.763 -0.691 58.892 -0.691 c
+58.998 -0.691 59.098 -0.669 59.186 -0.618 c
+59.282 -0.57 59.363 -0.507 59.421 -0.426 c
+59.488 -0.349 59.538 -0.262 59.569 -0.162 c
+59.598 -0.055 59.612 0.058 59.612 0.176 c
+h
+63.261 -2.66 m
+63.045 -2.66 62.854 -2.635 62.688 -2.587 c
+62.519 -2.547 62.379 -2.484 62.262 -2.396 c
+62.144 -2.315 62.045 -2.22 61.967 -2.103 c
+61.898 -1.985 61.85 -1.856 61.821 -1.72 c
+62.717 -1.617 l
+62.754 -1.754 62.824 -1.86 62.923 -1.941 c
+63.019 -2.029 63.143 -2.072 63.291 -2.072 c
+63.379 -2.072 63.459 -2.058 63.54 -2.029 c
+63.618 -1.999 63.688 -1.945 63.746 -1.867 c
+63.805 -1.797 63.849 -1.706 63.879 -1.588 c
+63.916 -1.47 63.937 -1.324 63.937 -1.147 c
+63.937 -0.956 l
+63.937 -0.89 63.941 -0.831 63.952 -0.779 c
+63.952 -0.588 l
+63.937 -0.588 l
+63.839 -0.816 63.695 -0.977 63.511 -1.073 c
+63.324 -1.172 63.118 -1.22 62.894 -1.22 c
+62.688 -1.22 62.505 -1.183 62.35 -1.103 c
+62.203 -1.014 62.075 -0.897 61.967 -0.75 c
+61.869 -0.595 61.795 -0.412 61.747 -0.206 c
+61.696 0.008 61.674 0.243 61.674 0.5 c
+61.674 0.771 61.696 1.018 61.747 1.234 c
+61.807 1.448 61.887 1.631 61.998 1.778 c
+62.104 1.932 62.236 2.05 62.394 2.131 c
+62.549 2.219 62.736 2.263 62.952 2.263 c
+63.048 2.263 63.147 2.252 63.247 2.234 c
+63.342 2.212 63.43 2.179 63.511 2.131 c
+63.6 2.08 63.677 2.017 63.746 1.94 c
+63.824 1.859 63.886 1.768 63.937 1.66 c
+63.952 1.66 l
+63.952 1.808 l
+63.96 1.866 63.967 1.918 63.967 1.969 c
+63.974 2.028 63.982 2.076 63.982 2.117 c
+63.989 2.164 64 2.198 64.011 2.219 c
+64.864 2.219 l
+64.853 2.138 64.841 2.028 64.834 1.882 c
+64.834 1.411 l
+64.834 -1.162 l
+64.834 -1.415 64.797 -1.636 64.731 -1.823 c
+64.662 -2.007 64.558 -2.161 64.423 -2.278 c
+64.283 -2.404 64.118 -2.5 63.923 -2.558 c
+63.725 -2.624 63.504 -2.66 63.261 -2.66 c
+63.952 0.529 m
+63.952 0.742 63.926 0.918 63.879 1.058 c
+63.839 1.205 63.783 1.323 63.717 1.411 c
+63.658 1.499 63.588 1.558 63.511 1.587 c
+63.43 1.624 63.353 1.646 63.276 1.646 c
+63.177 1.646 63.085 1.62 62.997 1.573 c
+62.916 1.532 62.85 1.462 62.791 1.367 c
+62.74 1.278 62.696 1.161 62.659 1.014 c
+62.629 0.874 62.615 0.706 62.615 0.5 c
+62.615 0.125 62.673 -0.154 62.791 -0.339 c
+62.908 -0.515 63.07 -0.603 63.276 -0.603 c
+63.342 -0.603 63.415 -0.588 63.496 -0.559 c
+63.585 -0.522 63.658 -0.463 63.717 -0.383 c
+63.783 -0.294 63.839 -0.177 63.879 -0.03 c
+63.926 0.118 63.952 0.301 63.952 0.529 c
+67.351 -1.324 m
+67.094 -1.324 66.866 -1.286 66.661 -1.22 c
+66.455 -1.143 66.278 -1.029 66.131 -0.882 c
+65.984 -0.728 65.867 -0.537 65.778 -0.309 c
+65.697 -0.085 65.661 0.18 65.661 0.484 c
+65.661 0.816 65.705 1.095 65.793 1.323 c
+65.888 1.558 66.017 1.741 66.175 1.882 c
+66.341 2.017 66.528 2.117 66.734 2.175 c
+66.94 2.242 67.149 2.278 67.366 2.278 c
+67.638 2.278 67.873 2.227 68.072 2.131 c
+68.277 2.043 68.443 1.911 68.571 1.734 c
+68.707 1.565 68.807 1.359 68.865 1.117 c
+68.932 0.881 68.968 0.617 68.968 0.323 c
+68.968 0.309 l
+66.602 0.309 l
+66.602 0.162 66.617 0.022 66.646 -0.103 c
+66.682 -0.231 66.738 -0.345 66.808 -0.441 c
+66.873 -0.53 66.958 -0.599 67.058 -0.647 c
+67.153 -0.698 67.267 -0.721 67.396 -0.721 c
+67.55 -0.721 67.689 -0.688 67.807 -0.618 c
+67.932 -0.551 68.02 -0.449 68.072 -0.309 c
+68.909 -0.383 l
+68.88 -0.482 68.824 -0.588 68.747 -0.706 c
+68.666 -0.816 68.564 -0.919 68.439 -1.014 c
+68.321 -1.103 68.167 -1.176 67.983 -1.235 c
+67.807 -1.294 67.594 -1.324 67.351 -1.324 c
+67.351 1.705 m
+67.263 1.705 67.175 1.691 67.087 1.66 c
+66.999 1.631 66.918 1.579 66.852 1.514 c
+66.782 1.444 66.723 1.356 66.675 1.249 c
+66.634 1.139 66.617 1.014 66.617 0.867 c
+68.086 0.867 l
+68.086 1.003 68.061 1.124 68.013 1.234 c
+67.972 1.341 67.918 1.429 67.851 1.499 c
+67.793 1.565 67.719 1.616 67.631 1.646 c
+67.542 1.683 67.447 1.705 67.351 1.705 c
+72.03 -1.264 m
+72.018 -1.246 72.007 -1.216 72 -1.176 c
+72 -1.129 71.993 -1.081 71.985 -1.029 c
+71.985 -0.971 71.978 -0.912 71.97 -0.853 c
+71.97 -0.691 l
+71.853 -0.927 71.71 -1.095 71.544 -1.191 c
+71.375 -1.279 71.176 -1.324 70.941 -1.324 c
+70.744 -1.324 70.567 -1.279 70.412 -1.191 c
+70.254 -1.103 70.122 -0.981 70.015 -0.823 c
+69.917 -0.659 69.84 -0.467 69.78 -0.25 c
+69.729 -0.037 69.707 0.205 69.707 0.47 c
+69.707 0.735 69.729 0.974 69.78 1.19 c
+69.84 1.415 69.917 1.606 70.015 1.764 c
+70.122 1.918 70.254 2.043 70.412 2.131 c
+70.578 2.227 70.769 2.278 70.985 2.278 c
+71.081 2.278 71.176 2.263 71.265 2.234 c
+71.361 2.212 71.456 2.179 71.544 2.131 c
+71.633 2.08 71.71 2.017 71.779 1.94 c
+71.857 1.859 71.92 1.768 71.97 1.66 c
+71.97 1.749 l
+71.97 1.896 l
+71.97 2.057 l
+71.97 2.234 l
+71.97 3.513 l
+72.867 3.513 l
+72.867 -0.5 l
+72.867 -0.676 72.871 -0.834 72.882 -0.971 c
+72.889 -1.099 72.897 -1.199 72.897 -1.264 c
+h
+71.985 0.484 m
+71.985 0.72 71.959 0.911 71.912 1.058 c
+71.872 1.213 71.816 1.338 71.75 1.425 c
+71.691 1.514 71.621 1.573 71.544 1.602 c
+71.463 1.639 71.386 1.66 71.309 1.66 c
+71.21 1.66 71.118 1.635 71.03 1.587 c
+70.949 1.547 70.883 1.477 70.824 1.381 c
+70.773 1.282 70.729 1.161 70.692 1.014 c
+70.663 0.867 70.648 0.683 70.648 0.47 c
+70.648 0.077 70.699 -0.217 70.809 -0.412 c
+70.927 -0.611 71.089 -0.706 71.294 -0.706 c
+71.371 -0.706 71.449 -0.688 71.529 -0.647 c
+71.606 -0.611 71.681 -0.544 71.75 -0.456 c
+71.816 -0.368 71.872 -0.246 71.912 -0.088 c
+71.959 0.066 71.985 0.257 71.985 0.484 c
+78.729 -2.631 m
+78.729 3.513 l
+80.654 3.513 l
+80.654 2.896 l
+79.581 2.896 l
+79.581 -2.014 l
+80.654 -2.014 l
+80.654 -2.631 l
+h
+83.685 1.602 m
+83.685 -1.264 l
+82.789 -1.264 l
+82.789 1.602 l
+81.966 1.602 l
+81.966 2.219 l
+82.789 2.219 l
+82.789 2.484 l
+82.789 2.609 82.804 2.741 82.833 2.881 c
+82.87 3.017 82.939 3.135 83.039 3.233 c
+83.145 3.34 83.288 3.428 83.465 3.498 c
+83.641 3.564 83.866 3.601 84.142 3.601 c
+84.354 3.601 84.553 3.59 84.73 3.572 c
+84.905 3.549 85.056 3.532 85.185 3.513 c
+85.185 2.925 l
+85.056 2.944 84.913 2.958 84.759 2.969 c
+84.601 2.977 84.45 2.984 84.303 2.984 c
+84.175 2.984 84.071 2.969 83.994 2.94 c
+83.914 2.91 83.851 2.869 83.803 2.822 c
+83.752 2.771 83.718 2.708 83.7 2.631 c
+83.689 2.561 83.685 2.484 83.685 2.396 c
+83.685 2.219 l
+85.112 2.219 l
+85.112 1.602 l
+h
+88.202 -0.647 m
+89.334 -0.647 l
+89.334 -1.264 l
+86.027 -1.264 l
+86.027 -0.647 l
+87.29 -0.647 l
+87.29 1.602 l
+86.365 1.602 l
+86.365 2.219 l
+88.202 2.219 l
+h
+87.29 3.513 0.912 -0.676 re
+87.29 2.836 m
+92.262 -0.647 m
+93.395 -0.647 l
+93.395 -1.264 l
+90.087 -1.264 l
+90.087 -0.647 l
+91.351 -0.647 l
+91.351 2.896 l
+90.425 2.896 l
+90.425 3.513 l
+92.262 3.513 l
+h
+95.78 -1.324 m
+95.522 -1.324 95.294 -1.286 95.088 -1.22 c
+94.883 -1.143 94.706 -1.029 94.559 -0.882 c
+94.413 -0.728 94.295 -0.537 94.207 -0.309 c
+94.126 -0.085 94.089 0.18 94.089 0.484 c
+94.089 0.816 94.133 1.095 94.222 1.323 c
+94.317 1.558 94.446 1.741 94.604 1.882 c
+94.769 2.017 94.956 2.117 95.162 2.175 c
+95.367 2.242 95.577 2.278 95.794 2.278 c
+96.065 2.278 96.301 2.227 96.499 2.131 c
+96.705 2.043 96.871 1.911 97 1.734 c
+97.135 1.565 97.235 1.359 97.293 1.117 c
+97.359 0.881 97.397 0.617 97.397 0.323 c
+97.397 0.309 l
+95.03 0.309 l
+95.03 0.162 95.045 0.022 95.074 -0.103 c
+95.111 -0.231 95.165 -0.345 95.236 -0.441 c
+95.302 -0.53 95.386 -0.599 95.485 -0.647 c
+95.581 -0.698 95.695 -0.721 95.824 -0.721 c
+95.978 -0.721 96.117 -0.688 96.235 -0.618 c
+96.36 -0.551 96.448 -0.449 96.499 -0.309 c
+97.337 -0.383 l
+97.308 -0.482 97.253 -0.588 97.176 -0.706 c
+97.095 -0.816 96.992 -0.919 96.867 -1.014 c
+96.749 -1.103 96.595 -1.176 96.412 -1.235 c
+96.235 -1.294 96.022 -1.324 95.78 -1.324 c
+95.78 1.705 m
+95.691 1.705 95.603 1.691 95.515 1.66 c
+95.427 1.631 95.346 1.579 95.28 1.514 c
+95.209 1.444 95.151 1.356 95.103 1.249 c
+95.063 1.139 95.045 1.014 95.045 0.867 c
+96.514 0.867 l
+96.514 1.003 96.489 1.124 96.441 1.234 c
+96.4 1.341 96.345 1.429 96.279 1.499 c
+96.221 1.565 96.146 1.616 96.059 1.646 c
+95.97 1.683 95.875 1.705 95.78 1.705 c
+98.653 -2.631 m
+98.653 -2.014 l
+99.726 -2.014 l
+99.726 2.896 l
+98.653 2.896 l
+98.653 3.513 l
+100.578 3.513 l
+100.578 -2.631 l
+h
+f
+Q
+q 1 0 0 1 294.3676 334.3982 cm
+0 0 m
+0 0.264 -0.073 0.463 -0.221 0.603 c
+-0.36 0.75 -0.617 0.89 -1 1.029 c
+-1.374 1.166 -1.661 1.309 -1.867 1.455 c
+-2.066 1.602 -2.213 1.768 -2.308 1.955 c
+-2.407 2.15 -2.455 2.371 -2.455 2.616 c
+-2.455 3.036 -2.315 3.385 -2.028 3.66 c
+-1.746 3.932 -1.378 4.072 -0.927 4.072 c
+-0.614 4.072 -0.335 3.998 -0.088 3.851 c
+0.154 3.712 0.341 3.517 0.47 3.263 c
+0.606 3.017 0.675 2.749 0.675 2.455 c
+0 2.455 l
+0 2.786 -0.081 3.043 -0.235 3.219 c
+-0.393 3.403 -0.625 3.499 -0.927 3.499 c
+-1.191 3.499 -1.404 3.418 -1.558 3.263 c
+-1.706 3.117 -1.779 2.903 -1.779 2.631 c
+-1.779 2.404 -1.702 2.213 -1.544 2.058 c
+-1.378 1.911 -1.125 1.771 -0.779 1.646 c
+-0.262 1.478 0.11 1.268 0.338 1.014 c
+0.573 0.757 0.69 0.426 0.69 0.015 c
+0.69 -0.426 0.548 -0.779 0.264 -1.043 c
+-0.023 -1.301 -0.405 -1.425 -0.882 -1.425 c
+-1.198 -1.425 -1.484 -1.356 -1.75 -1.22 c
+-2.014 -1.084 -2.227 -0.893 -2.382 -0.646 c
+-2.529 -0.404 -2.602 -0.118 -2.602 0.206 c
+-1.926 0.206 l
+-1.926 -0.128 -1.834 -0.389 -1.646 -0.573 c
+-1.463 -0.76 -1.206 -0.852 -0.882 -0.852 c
+-0.588 -0.852 -0.368 -0.779 -0.221 -0.632 c
+-0.073 -0.478 0 -0.264 0 0 c
+2.117 2.22 m
+2.37 2.543 2.69 2.705 3.072 2.705 c
+3.777 2.705 4.134 2.234 4.145 1.294 c
+4.145 -1.352 l
+3.498 -1.352 l
+3.498 1.264 l
+3.498 1.577 3.443 1.797 3.337 1.926 c
+3.226 2.051 3.072 2.117 2.866 2.117 c
+2.708 2.117 2.561 2.062 2.425 1.955 c
+2.296 1.845 2.194 1.709 2.117 1.544 c
+2.117 -1.352 l
+1.469 -1.352 l
+1.469 4.293 l
+2.117 4.293 l
+h
+4.968 0.823 m
+4.968 1.401 5.104 1.856 5.379 2.19 c
+5.662 2.532 6.034 2.705 6.497 2.705 c
+6.956 2.705 7.324 2.536 7.599 2.205 c
+7.882 1.881 8.029 1.434 8.04 0.867 c
+8.04 0.441 l
+8.04 -0.128 7.897 -0.584 7.614 -0.926 c
+7.339 -1.261 6.971 -1.425 6.512 -1.425 c
+6.048 -1.425 5.677 -1.264 5.394 -0.941 c
+5.119 -0.61 4.976 -0.168 4.968 0.382 c
+h
+5.614 0.441 m
+5.614 0.037 5.692 -0.279 5.85 -0.515 c
+6.015 -0.75 6.236 -0.867 6.512 -0.867 c
+7.077 -0.867 7.372 -0.455 7.393 0.368 c
+7.393 0.823 l
+7.393 1.224 7.309 1.544 7.144 1.779 c
+6.986 2.022 6.769 2.146 6.497 2.146 c
+6.232 2.146 6.015 2.022 5.85 1.779 c
+5.692 1.544 5.614 1.224 5.614 0.823 c
+h
+11.848 -0.206 m
+12.45 2.631 l
+13.097 2.631 l
+12.112 -1.352 l
+11.597 -1.352 l
+10.818 1.5 l
+10.069 -1.352 l
+9.539 -1.352 l
+8.584 2.631 l
+9.216 2.631 l
+9.834 -0.132 l
+10.568 2.631 l
+11.083 2.631 l
+h
+16.874 -0.867 m
+17.088 -0.867 17.26 -0.804 17.389 -0.676 c
+17.525 -0.54 17.598 -0.349 17.609 -0.103 c
+18.227 -0.103 l
+18.204 -0.484 18.069 -0.804 17.815 -1.058 c
+17.558 -1.304 17.246 -1.425 16.874 -1.425 c
+16.382 -1.425 16.007 -1.275 15.742 -0.97 c
+15.486 -0.658 15.36 -0.191 15.36 0.426 c
+15.36 0.867 l
+15.36 1.463 15.486 1.918 15.742 2.234 c
+16.007 2.547 16.382 2.705 16.874 2.705 c
+17.275 2.705 17.595 2.573 17.83 2.308 c
+18.073 2.051 18.204 1.706 18.227 1.264 c
+17.609 1.264 l
+17.587 1.558 17.514 1.779 17.389 1.926 c
+17.271 2.072 17.099 2.146 16.874 2.146 c
+16.581 2.146 16.363 2.047 16.228 1.852 c
+16.088 1.665 16.014 1.357 16.007 0.927 c
+16.007 0.412 l
+16.007 -0.058 16.073 -0.393 16.213 -0.588 c
+16.359 -0.775 16.581 -0.867 16.874 -0.867 c
+19.623 2.22 m
+19.877 2.543 20.196 2.705 20.579 2.705 c
+21.284 2.705 21.641 2.234 21.651 1.294 c
+21.651 -1.352 l
+21.005 -1.352 l
+21.005 1.264 l
+21.005 1.577 20.949 1.797 20.843 1.926 c
+20.733 2.051 20.579 2.117 20.373 2.117 c
+20.215 2.117 20.068 2.062 19.931 1.955 c
+19.803 1.845 19.7 1.709 19.623 1.544 c
+19.623 -1.352 l
+18.977 -1.352 l
+18.977 4.293 l
+19.623 4.293 l
+h
+24.65 -1.352 m
+24.61 -1.264 24.584 -1.117 24.577 -0.912 c
+24.342 -1.257 24.047 -1.425 23.694 -1.425 c
+23.331 -1.425 23.048 -1.33 22.842 -1.132 c
+22.644 -0.926 22.548 -0.639 22.548 -0.264 c
+22.548 0.136 22.684 0.456 22.96 0.691 c
+23.232 0.933 23.607 1.058 24.077 1.058 c
+24.562 1.058 l
+24.562 1.484 l
+24.562 1.72 24.507 1.885 24.4 1.985 c
+24.29 2.091 24.128 2.146 23.915 2.146 c
+23.717 2.146 23.555 2.088 23.43 1.97 c
+23.312 1.852 23.253 1.706 23.253 1.529 c
+22.607 1.529 l
+22.607 1.723 22.666 1.914 22.783 2.103 c
+22.908 2.286 23.07 2.433 23.268 2.543 c
+23.474 2.65 23.702 2.705 23.959 2.705 c
+24.359 2.705 24.664 2.602 24.87 2.396 c
+25.084 2.19 25.198 1.897 25.209 1.515 c
+25.209 -0.5 l
+25.209 -0.804 25.246 -1.069 25.327 -1.294 c
+25.327 -1.352 l
+h
+23.783 -0.837 m
+23.948 -0.837 24.099 -0.794 24.238 -0.706 c
+24.386 -0.617 24.492 -0.507 24.562 -0.367 c
+24.562 0.574 l
+24.194 0.574 l
+23.879 0.574 23.636 0.503 23.459 0.368 c
+23.283 0.239 23.195 0.052 23.195 -0.191 c
+23.195 -0.419 23.239 -0.584 23.328 -0.69 c
+23.415 -0.79 23.566 -0.837 23.783 -0.837 c
+26.825 2.631 m
+26.84 2.19 l
+27.094 2.532 27.417 2.705 27.81 2.705 c
+28.516 2.705 28.872 2.234 28.884 1.294 c
+28.884 -1.352 l
+28.236 -1.352 l
+28.236 1.264 l
+28.236 1.577 28.182 1.797 28.075 1.926 c
+27.964 2.051 27.81 2.117 27.605 2.117 c
+27.447 2.117 27.299 2.062 27.164 1.955 c
+27.035 1.845 26.932 1.709 26.855 1.544 c
+26.855 -1.352 l
+26.208 -1.352 l
+26.208 2.631 l
+h
+29.722 0.823 m
+29.722 1.44 29.832 1.904 30.059 2.22 c
+30.283 2.543 30.618 2.705 31.059 2.705 c
+31.459 2.705 31.764 2.529 31.97 2.176 c
+32.014 2.631 l
+32.602 2.631 l
+32.602 -1.396 l
+32.602 -1.885 32.473 -2.263 32.22 -2.528 c
+31.963 -2.793 31.61 -2.925 31.162 -2.925 c
+30.964 -2.925 30.742 -2.873 30.501 -2.778 c
+30.254 -2.678 30.074 -2.558 29.957 -2.41 c
+30.221 -1.97 l
+30.486 -2.234 30.783 -2.366 31.118 -2.366 c
+31.654 -2.366 31.93 -2.072 31.941 -1.484 c
+31.941 -0.955 l
+31.735 -1.271 31.434 -1.425 31.044 -1.425 c
+30.632 -1.425 30.309 -1.275 30.074 -0.97 c
+29.846 -0.658 29.728 -0.206 29.722 0.382 c
+h
+30.383 0.441 m
+30.383 0 30.445 -0.33 30.574 -0.544 c
+30.699 -0.75 30.916 -0.852 31.22 -0.852 c
+31.544 -0.852 31.783 -0.687 31.941 -0.353 c
+31.941 1.632 l
+31.772 1.955 31.533 2.117 31.22 2.117 c
+30.927 2.117 30.71 2.014 30.574 1.808 c
+30.445 1.602 30.383 1.279 30.383 0.838 c
+h
+34.983 -1.425 m
+34.484 -1.425 34.102 -1.278 33.837 -0.985 c
+33.572 -0.69 33.44 -0.257 33.44 0.324 c
+33.44 0.794 l
+33.44 1.389 33.565 1.856 33.822 2.19 c
+34.087 2.532 34.447 2.705 34.91 2.705 c
+35.369 2.705 35.711 2.55 35.939 2.249 c
+36.174 1.955 36.296 1.492 36.307 0.867 c
+36.307 0.441 l
+34.087 0.441 l
+34.087 0.353 l
+34.087 -0.081 34.164 -0.393 34.322 -0.588 c
+34.487 -0.775 34.719 -0.867 35.012 -0.867 c
+35.208 -0.867 35.38 -0.833 35.527 -0.764 c
+35.675 -0.687 35.81 -0.569 35.939 -0.411 c
+36.277 -0.823 l
+35.991 -1.227 35.561 -1.425 34.983 -1.425 c
+34.91 2.146 m
+34.634 2.146 34.432 2.051 34.307 1.867 c
+34.179 1.679 34.106 1.389 34.087 1 c
+35.66 1 l
+35.66 1.087 l
+35.638 1.47 35.571 1.738 35.454 1.897 c
+35.336 2.062 35.153 2.146 34.91 2.146 c
+39.026 -0.338 m
+39.026 -0.191 38.971 -0.07 38.864 0.029 c
+38.754 0.125 38.548 0.243 38.247 0.382 c
+37.901 0.53 37.659 0.651 37.512 0.75 c
+37.364 0.856 37.254 0.974 37.188 1.103 c
+37.119 1.228 37.086 1.386 37.086 1.573 c
+37.086 1.897 37.203 2.165 37.439 2.381 c
+37.674 2.595 37.975 2.705 38.349 2.705 c
+38.732 2.705 39.041 2.591 39.276 2.367 c
+39.511 2.139 39.629 1.852 39.629 1.5 c
+38.981 1.5 l
+38.981 1.675 38.923 1.827 38.805 1.955 c
+38.688 2.08 38.534 2.146 38.349 2.146 c
+38.151 2.146 38 2.091 37.894 1.985 c
+37.784 1.885 37.732 1.754 37.732 1.588 c
+37.732 1.459 37.769 1.353 37.85 1.264 c
+37.927 1.183 38.118 1.081 38.424 0.956 c
+38.901 0.769 39.232 0.58 39.408 0.397 c
+39.584 0.221 39.673 -0.008 39.673 -0.279 c
+39.673 -0.632 39.548 -0.912 39.305 -1.117 c
+39.07 -1.323 38.754 -1.425 38.364 -1.425 c
+37.942 -1.425 37.603 -1.308 37.35 -1.072 c
+37.092 -0.831 36.968 -0.525 36.968 -0.162 c
+37.615 -0.162 l
+37.622 -0.389 37.692 -0.565 37.821 -0.69 c
+37.946 -0.808 38.129 -0.867 38.364 -0.867 c
+38.578 -0.867 38.739 -0.819 38.85 -0.72 c
+38.967 -0.625 39.026 -0.496 39.026 -0.338 c
+45.111 0.441 m
+45.111 -0.176 44.997 -0.643 44.774 -0.955 c
+44.556 -1.271 44.233 -1.425 43.803 -1.425 c
+43.38 -1.425 43.068 -1.246 42.862 -0.881 c
+42.833 -1.352 l
+42.23 -1.352 l
+42.23 4.293 l
+42.877 4.293 l
+42.877 2.19 l
+43.09 2.532 43.399 2.705 43.803 2.705 c
+44.233 2.705 44.556 2.547 44.774 2.234 c
+44.997 1.929 45.111 1.463 45.111 0.838 c
+h
+44.464 0.823 m
+44.464 1.294 44.394 1.625 44.259 1.823 c
+44.13 2.018 43.92 2.117 43.627 2.117 c
+43.292 2.117 43.043 1.933 42.877 1.573 c
+42.877 -0.309 l
+43.043 -0.673 43.296 -0.852 43.641 -0.852 c
+43.935 -0.852 44.145 -0.75 44.273 -0.544 c
+44.398 -0.338 44.464 -0.022 44.464 0.412 c
+h
+47.375 -1.425 m
+46.875 -1.425 46.493 -1.278 46.228 -0.985 c
+45.964 -0.69 45.831 -0.257 45.831 0.324 c
+45.831 0.794 l
+45.831 1.389 45.956 1.856 46.214 2.19 c
+46.478 2.532 46.838 2.705 47.301 2.705 c
+47.76 2.705 48.103 2.55 48.33 2.249 c
+48.566 1.955 48.687 1.492 48.697 0.867 c
+48.697 0.441 l
+46.478 0.441 l
+46.478 0.353 l
+46.478 -0.081 46.555 -0.393 46.713 -0.588 c
+46.879 -0.775 47.11 -0.867 47.404 -0.867 c
+47.599 -0.867 47.772 -0.833 47.918 -0.764 c
+48.066 -0.687 48.202 -0.569 48.33 -0.411 c
+48.668 -0.823 l
+48.381 -1.227 47.951 -1.425 47.375 -1.425 c
+47.301 2.146 m
+47.026 2.146 46.823 2.051 46.698 1.867 c
+46.57 1.679 46.497 1.389 46.478 1 c
+48.051 1 l
+48.051 1.087 l
+48.029 1.47 47.963 1.738 47.845 1.897 c
+47.727 2.062 47.544 2.146 47.301 2.146 c
+50.33 3.587 m
+50.33 2.631 l
+50.932 2.631 l
+50.932 2.103 l
+50.33 2.103 l
+50.33 -0.367 l
+50.33 -0.525 50.351 -0.643 50.403 -0.72 c
+50.461 -0.801 50.55 -0.837 50.667 -0.837 c
+50.756 -0.837 50.844 -0.823 50.932 -0.794 c
+50.932 -1.352 l
+50.785 -1.4 50.631 -1.425 50.476 -1.425 c
+50.219 -1.425 50.025 -1.334 49.888 -1.147 c
+49.749 -0.962 49.682 -0.702 49.682 -0.367 c
+49.682 2.103 l
+49.08 2.103 l
+49.08 2.631 l
+49.682 2.631 l
+49.682 3.587 l
+h
+54.665 -0.206 m
+55.268 2.631 l
+55.915 2.631 l
+54.93 -1.352 l
+54.416 -1.352 l
+53.636 1.5 l
+52.887 -1.352 l
+52.358 -1.352 l
+51.402 2.631 l
+52.034 2.631 l
+52.651 -0.132 l
+53.387 2.631 l
+53.902 2.631 l
+h
+58.017 -1.425 m
+57.517 -1.425 57.135 -1.278 56.871 -0.985 c
+56.606 -0.69 56.474 -0.257 56.474 0.324 c
+56.474 0.794 l
+56.474 1.389 56.599 1.856 56.855 2.19 c
+57.12 2.532 57.48 2.705 57.944 2.705 c
+58.403 2.705 58.744 2.55 58.972 2.249 c
+59.207 1.955 59.329 1.492 59.34 0.867 c
+59.34 0.441 l
+57.12 0.441 l
+57.12 0.353 l
+57.12 -0.081 57.198 -0.393 57.355 -0.588 c
+57.521 -0.775 57.752 -0.867 58.046 -0.867 c
+58.241 -0.867 58.414 -0.833 58.561 -0.764 c
+58.708 -0.687 58.844 -0.569 58.972 -0.411 c
+59.311 -0.823 l
+59.024 -1.227 58.594 -1.425 58.017 -1.425 c
+57.944 2.146 m
+57.668 2.146 57.466 2.051 57.341 1.867 c
+57.212 1.679 57.139 1.389 57.12 1 c
+58.693 1 l
+58.693 1.087 l
+58.671 1.47 58.605 1.738 58.488 1.897 c
+58.37 2.062 58.186 2.146 57.944 2.146 c
+61.545 -1.425 m
+61.045 -1.425 60.663 -1.278 60.398 -0.985 c
+60.134 -0.69 60.001 -0.257 60.001 0.324 c
+60.001 0.794 l
+60.001 1.389 60.126 1.856 60.383 2.19 c
+60.648 2.532 61.008 2.705 61.472 2.705 c
+61.931 2.705 62.272 2.55 62.5 2.249 c
+62.735 1.955 62.856 1.492 62.868 0.867 c
+62.868 0.441 l
+60.648 0.441 l
+60.648 0.353 l
+60.648 -0.081 60.726 -0.393 60.883 -0.588 c
+61.048 -0.775 61.28 -0.867 61.574 -0.867 c
+61.769 -0.867 61.942 -0.833 62.089 -0.764 c
+62.236 -0.687 62.372 -0.569 62.5 -0.411 c
+62.839 -0.823 l
+62.552 -1.227 62.122 -1.425 61.545 -1.425 c
+61.472 2.146 m
+61.196 2.146 60.994 2.051 60.869 1.867 c
+60.74 1.679 60.666 1.389 60.648 1 c
+62.221 1 l
+62.221 1.087 l
+62.199 1.47 62.133 1.738 62.015 1.897 c
+61.898 2.062 61.713 2.146 61.472 2.146 c
+64.264 2.631 m
+64.279 2.19 l
+64.532 2.532 64.855 2.705 65.249 2.705 c
+65.954 2.705 66.311 2.234 66.322 1.294 c
+66.322 -1.352 l
+65.675 -1.352 l
+65.675 1.264 l
+65.675 1.577 65.62 1.797 65.513 1.926 c
+65.403 2.051 65.249 2.117 65.043 2.117 c
+64.885 2.117 64.738 2.062 64.602 1.955 c
+64.474 1.845 64.371 1.709 64.294 1.544 c
+64.294 -1.352 l
+63.647 -1.352 l
+63.647 2.631 l
+h
+f
+Q
+q 1 0 0 1 365.0407 334.1188 cm
+0 0 m
+0 0.088 -0.044 0.166 -0.133 0.235 c
+-0.221 0.312 -0.408 0.416 -0.691 0.544 c
+-1.125 0.721 -1.422 0.9 -1.588 1.088 c
+-1.746 1.272 -1.823 1.503 -1.823 1.779 c
+-1.823 2.12 -1.702 2.404 -1.455 2.631 c
+-1.202 2.866 -0.864 2.984 -0.441 2.984 c
+-0.011 2.984 0.338 2.87 0.602 2.646 c
+0.867 2.419 0.999 2.117 0.999 1.735 c
+-0.044 1.735 l
+-0.044 2.058 -0.184 2.22 -0.456 2.22 c
+-0.566 2.22 -0.655 2.183 -0.721 2.117 c
+-0.79 2.047 -0.823 1.948 -0.823 1.823 c
+-0.823 1.735 -0.786 1.654 -0.706 1.588 c
+-0.628 1.529 -0.449 1.434 -0.162 1.309 c
+0.268 1.151 0.565 0.975 0.735 0.779 c
+0.912 0.592 0.999 0.342 0.999 0.03 c
+0.999 -0.323 0.867 -0.61 0.602 -0.823 c
+0.338 -1.039 -0.011 -1.146 -0.441 -1.146 c
+-0.735 -1.146 -0.996 -1.091 -1.22 -0.985 c
+-1.448 -0.867 -1.625 -0.706 -1.75 -0.499 c
+-1.867 -0.293 -1.926 -0.073 -1.926 0.162 c
+-0.941 0.162 l
+-0.941 -0.025 -0.904 -0.162 -0.823 -0.249 c
+-0.735 -0.338 -0.603 -0.382 -0.426 -0.382 c
+-0.144 -0.382 0 -0.257 0 0 c
+2.866 3.881 m
+2.866 2.911 l
+3.395 2.911 l
+3.395 2.117 l
+2.866 2.117 l
+2.866 0.148 l
+2.866 -0.01 2.884 -0.118 2.925 -0.176 c
+2.973 -0.235 3.057 -0.264 3.175 -0.264 c
+3.281 -0.264 3.366 -0.257 3.424 -0.235 c
+3.424 -1.043 l
+3.248 -1.109 3.057 -1.146 2.851 -1.146 c
+2.175 -1.146 1.83 -0.76 1.822 0.015 c
+1.822 2.117 l
+1.367 2.117 l
+1.367 2.911 l
+1.822 2.911 l
+1.822 3.881 l
+h
+5.85 -1.072 m
+5.82 -1.014 5.791 -0.911 5.762 -0.764 c
+5.575 -1.022 5.325 -1.146 5.012 -1.146 c
+4.677 -1.146 4.399 -1.039 4.174 -0.823 c
+3.958 -0.598 3.85 -0.309 3.85 0.044 c
+3.85 0.456 3.983 0.772 4.247 1 c
+4.513 1.235 4.895 1.353 5.394 1.353 c
+5.718 1.353 l
+5.718 1.676 l
+5.718 1.852 5.681 1.974 5.615 2.043 c
+5.556 2.12 5.468 2.161 5.35 2.161 c
+5.093 2.161 4.968 2.007 4.968 1.706 c
+3.925 1.706 l
+3.925 2.076 4.06 2.382 4.336 2.617 c
+4.608 2.859 4.957 2.984 5.38 2.984 c
+5.82 2.984 6.159 2.866 6.394 2.631 c
+6.636 2.404 6.761 2.08 6.761 1.661 c
+6.761 -0.205 l
+6.761 -0.551 6.809 -0.819 6.908 -1.014 c
+6.908 -1.072 l
+h
+5.247 -0.323 m
+5.354 -0.323 5.446 -0.305 5.527 -0.264 c
+5.615 -0.216 5.677 -0.158 5.718 -0.087 c
+5.718 0.736 l
+5.468 0.736 l
+5.292 0.736 5.148 0.676 5.041 0.559 c
+4.943 0.449 4.895 0.302 4.895 0.118 c
+4.895 -0.176 5.012 -0.323 5.247 -0.323 c
+7.378 1.044 m
+7.378 1.691 7.497 2.176 7.732 2.5 c
+7.967 2.822 8.297 2.984 8.731 2.984 c
+9.084 2.984 9.356 2.841 9.554 2.558 c
+9.598 2.911 l
+10.539 2.911 l
+10.539 -1.072 l
+10.539 -1.579 10.396 -1.969 10.113 -2.234 c
+9.826 -2.506 9.422 -2.645 8.893 -2.645 c
+8.665 -2.645 8.43 -2.601 8.187 -2.514 c
+7.952 -2.425 7.775 -2.311 7.658 -2.175 c
+8.01 -1.455 l
+8.106 -1.562 8.235 -1.646 8.393 -1.705 c
+8.548 -1.77 8.694 -1.808 8.834 -1.808 c
+9.069 -1.808 9.234 -1.749 9.334 -1.631 c
+9.44 -1.521 9.495 -1.344 9.495 -1.103 c
+9.495 -0.75 l
+9.297 -1.014 9.04 -1.146 8.716 -1.146 c
+8.294 -1.146 7.967 -0.985 7.732 -0.661 c
+7.503 -0.33 7.386 0.14 7.378 0.75 c
+h
+8.422 0.779 m
+8.422 0.405 8.47 0.136 8.569 -0.029 c
+8.665 -0.198 8.819 -0.279 9.025 -0.279 c
+9.238 -0.279 9.396 -0.201 9.495 -0.044 c
+9.495 1.852 l
+9.385 2.018 9.231 2.103 9.025 2.103 c
+8.819 2.103 8.665 2.018 8.569 1.852 c
+8.47 1.683 8.422 1.415 8.422 1.044 c
+h
+12.391 -1.072 -1.044 3.983 re
+11.303 3.94 m
+11.303 4.094 11.351 4.223 11.451 4.322 c
+11.557 4.428 11.692 4.484 11.862 4.484 c
+12.039 4.484 12.174 4.428 12.274 4.322 c
+12.38 4.223 12.436 4.094 12.436 3.94 c
+12.436 3.771 12.38 3.635 12.274 3.528 c
+12.174 3.429 12.039 3.381 11.862 3.381 c
+11.692 3.381 11.557 3.429 11.451 3.528 c
+11.351 3.635 11.303 3.771 11.303 3.94 c
+14.155 2.911 m
+14.184 2.514 l
+14.42 2.826 14.721 2.984 15.096 2.984 c
+15.779 2.984 16.132 2.503 16.154 1.544 c
+16.154 -1.072 l
+15.11 -1.072 l
+15.11 1.47 l
+15.11 1.694 15.073 1.856 15.008 1.955 c
+14.938 2.051 14.82 2.103 14.655 2.103 c
+14.468 2.103 14.32 2.007 14.214 1.823 c
+14.214 -1.072 l
+13.17 -1.072 l
+13.17 2.911 l
+h
+16.772 1.044 m
+16.772 1.691 16.889 2.176 17.124 2.5 c
+17.359 2.822 17.69 2.984 18.123 2.984 c
+18.476 2.984 18.748 2.841 18.947 2.558 c
+18.991 2.911 l
+19.931 2.911 l
+19.931 -1.072 l
+19.931 -1.579 19.788 -1.969 19.505 -2.234 c
+19.218 -2.506 18.815 -2.645 18.285 -2.645 c
+18.057 -2.645 17.822 -2.601 17.58 -2.514 c
+17.344 -2.425 17.168 -2.311 17.051 -2.175 c
+17.404 -1.455 l
+17.499 -1.562 17.628 -1.646 17.786 -1.705 c
+17.94 -1.77 18.087 -1.808 18.227 -1.808 c
+18.462 -1.808 18.628 -1.749 18.726 -1.631 c
+18.833 -1.521 18.888 -1.344 18.888 -1.103 c
+18.888 -0.75 l
+18.69 -1.014 18.432 -1.146 18.109 -1.146 c
+17.687 -1.146 17.359 -0.985 17.124 -0.661 c
+16.897 -0.33 16.779 0.14 16.772 0.75 c
+h
+17.815 0.779 m
+17.815 0.405 17.863 0.136 17.962 -0.029 c
+18.057 -0.198 18.212 -0.279 18.418 -0.279 c
+18.63 -0.279 18.788 -0.201 18.888 -0.044 c
+18.888 1.852 l
+18.778 2.018 18.624 2.103 18.418 2.103 c
+18.212 2.103 18.057 2.018 17.962 1.852 c
+17.863 1.683 17.815 1.415 17.815 1.044 c
+h
+24.312 -1.072 m
+24.282 -1.014 24.253 -0.911 24.224 -0.764 c
+24.037 -1.022 23.787 -1.146 23.474 -1.146 c
+23.139 -1.146 22.861 -1.039 22.636 -0.823 c
+22.42 -0.598 22.313 -0.309 22.313 0.044 c
+22.313 0.456 22.445 0.772 22.709 1 c
+22.975 1.235 23.357 1.353 23.856 1.353 c
+24.18 1.353 l
+24.18 1.676 l
+24.18 1.852 24.143 1.974 24.076 2.043 c
+24.018 2.12 23.93 2.161 23.812 2.161 c
+23.555 2.161 23.43 2.007 23.43 1.706 c
+22.387 1.706 l
+22.387 2.076 22.522 2.382 22.798 2.617 c
+23.07 2.859 23.419 2.984 23.841 2.984 c
+24.282 2.984 24.621 2.866 24.856 2.631 c
+25.098 2.404 25.223 2.08 25.223 1.661 c
+25.223 -0.205 l
+25.223 -0.551 25.271 -0.819 25.371 -1.014 c
+25.371 -1.072 l
+h
+23.709 -0.323 m
+23.816 -0.323 23.908 -0.305 23.989 -0.264 c
+24.076 -0.216 24.139 -0.158 24.18 -0.087 c
+24.18 0.736 l
+23.93 0.736 l
+23.754 0.736 23.61 0.676 23.503 0.559 c
+23.405 0.449 23.357 0.302 23.357 0.118 c
+23.357 -0.176 23.474 -0.323 23.709 -0.323 c
+27.928 1.897 m
+27.59 1.926 l
+27.303 1.926 27.112 1.801 27.017 1.559 c
+27.017 -1.072 l
+25.973 -1.072 l
+25.973 2.911 l
+26.943 2.911 l
+26.973 2.469 l
+27.138 2.812 27.369 2.984 27.663 2.984 c
+27.781 2.984 27.873 2.962 27.943 2.926 c
+h
+30 -1.146 m
+29.471 -1.146 29.053 -0.992 28.751 -0.675 c
+28.457 -0.353 28.31 0.107 28.31 0.706 c
+28.31 1.014 l
+28.31 1.64 28.446 2.124 28.722 2.469 c
+28.994 2.812 29.387 2.984 29.898 2.984 c
+30.397 2.984 30.769 2.822 31.015 2.5 c
+31.268 2.176 31.401 1.698 31.411 1.073 c
+31.411 0.574 l
+29.339 0.574 l
+29.358 0.279 29.42 0.063 29.53 -0.073 c
+29.647 -0.213 29.828 -0.279 30.074 -0.279 c
+30.416 -0.279 30.706 -0.162 30.941 0.073 c
+31.353 -0.558 l
+31.224 -0.735 31.037 -0.878 30.794 -0.985 c
+30.548 -1.091 30.283 -1.146 30 -1.146 c
+29.354 1.294 m
+30.383 1.294 l
+30.383 1.397 l
+30.383 1.632 30.343 1.808 30.265 1.926 c
+30.195 2.051 30.067 2.117 29.883 2.117 c
+29.707 2.117 29.574 2.047 29.486 1.912 c
+29.406 1.783 29.361 1.577 29.354 1.294 c
+33.881 -1.072 m
+33.852 -1.014 33.822 -0.911 33.793 -0.764 c
+33.605 -1.022 33.356 -1.146 33.043 -1.146 c
+32.709 -1.146 32.429 -1.039 32.205 -0.823 c
+31.989 -0.598 31.882 -0.309 31.882 0.044 c
+31.882 0.456 32.014 0.772 32.279 1 c
+32.543 1.235 32.926 1.353 33.425 1.353 c
+33.749 1.353 l
+33.749 1.676 l
+33.749 1.852 33.712 1.974 33.646 2.043 c
+33.587 2.12 33.499 2.161 33.381 2.161 c
+33.124 2.161 32.999 2.007 32.999 1.706 c
+31.956 1.706 l
+31.956 2.076 32.091 2.382 32.367 2.617 c
+32.639 2.859 32.988 2.984 33.41 2.984 c
+33.852 2.984 34.189 2.866 34.424 2.631 c
+34.667 2.404 34.792 2.08 34.792 1.661 c
+34.792 -0.205 l
+34.792 -0.551 34.84 -0.819 34.939 -1.014 c
+34.939 -1.072 l
+h
+33.279 -0.323 m
+33.385 -0.323 33.477 -0.305 33.558 -0.264 c
+33.646 -0.216 33.709 -0.158 33.749 -0.087 c
+33.749 0.736 l
+33.499 0.736 l
+33.323 0.736 33.179 0.676 33.073 0.559 c
+32.974 0.449 32.926 0.302 32.926 0.118 c
+32.926 -0.176 33.043 -0.323 33.279 -0.323 c
+f
+Q
+q 1 0 0 1 404.4483 333.0464 cm
+0 0 m
+-0.04 0.087 -0.066 0.235 -0.073 0.44 c
+-0.309 0.095 -0.602 -0.073 -0.955 -0.073 c
+-1.319 -0.073 -1.602 0.022 -1.807 0.22 c
+-2.006 0.426 -2.102 0.713 -2.102 1.087 c
+-2.102 1.488 -1.965 1.808 -1.691 2.043 c
+-1.418 2.285 -1.043 2.41 -0.573 2.41 c
+-0.088 2.41 l
+-0.088 2.836 l
+-0.088 3.072 -0.143 3.237 -0.249 3.337 c
+-0.359 3.443 -0.521 3.498 -0.735 3.498 c
+-0.933 3.498 -1.095 3.439 -1.22 3.322 c
+-1.337 3.204 -1.396 3.057 -1.396 2.881 c
+-2.042 2.881 l
+-2.042 3.075 -1.984 3.266 -1.866 3.454 c
+-1.741 3.638 -1.58 3.785 -1.381 3.895 c
+-1.176 4.002 -0.947 4.056 -0.691 4.056 c
+-0.29 4.056 0.015 3.954 0.221 3.748 c
+0.434 3.542 0.548 3.248 0.559 2.866 c
+0.559 0.852 l
+0.559 0.548 0.595 0.283 0.676 0.058 c
+0.676 0 l
+h
+-0.866 0.515 m
+-0.702 0.515 -0.551 0.558 -0.411 0.646 c
+-0.264 0.735 -0.158 0.845 -0.088 0.985 c
+-0.088 1.926 l
+-0.455 1.926 l
+-0.771 1.926 -1.014 1.855 -1.19 1.72 c
+-1.367 1.591 -1.455 1.404 -1.455 1.161 c
+-1.455 0.933 -1.411 0.768 -1.323 0.661 c
+-1.234 0.562 -1.084 0.515 -0.866 0.515 c
+2.176 3.983 m
+2.191 3.542 l
+2.444 3.884 2.768 4.056 3.161 4.056 c
+3.866 4.056 4.223 3.586 4.233 2.645 c
+4.233 0 l
+3.587 0 l
+3.587 2.616 l
+3.587 2.929 3.532 3.149 3.425 3.278 c
+3.315 3.403 3.161 3.469 2.955 3.469 c
+2.797 3.469 2.65 3.414 2.514 3.307 c
+2.386 3.197 2.282 3.061 2.205 2.896 c
+2.205 0 l
+1.559 0 l
+1.559 3.983 l
+h
+5.072 2.175 m
+5.072 2.782 5.182 3.248 5.409 3.572 c
+5.644 3.895 5.972 4.056 6.394 4.056 c
+6.776 4.056 7.074 3.898 7.291 3.586 c
+7.291 5.644 l
+7.938 5.644 l
+7.938 0 l
+7.35 0 l
+7.306 0.426 l
+7.1 0.091 6.795 -0.073 6.394 -0.073 c
+5.983 -0.073 5.659 0.081 5.424 0.397 c
+5.189 0.72 5.072 1.176 5.072 1.764 c
+h
+5.719 1.793 m
+5.719 1.352 5.781 1.022 5.91 0.808 c
+6.045 0.602 6.266 0.5 6.571 0.5 c
+6.895 0.5 7.133 0.661 7.291 0.985 c
+7.291 2.998 l
+7.122 3.31 6.883 3.469 6.571 3.469 c
+6.266 3.469 6.045 3.366 5.91 3.16 c
+5.781 2.954 5.719 2.631 5.719 2.19 c
+h
+f
+Q
+416.09 333.046 -1.043 3.983 re
+415.002 338.059 m
+415.002 338.213 415.05 338.342 415.149 338.441 c
+415.256 338.547 415.392 338.602 415.561 338.602 c
+415.737 338.602 415.874 338.547 415.972 338.441 c
+416.08 338.342 416.134 338.213 416.134 338.059 c
+416.134 337.889 416.08 337.754 415.972 337.647 c
+415.874 337.548 415.737 337.5 415.561 337.5 c
+415.392 337.5 415.256 337.548 415.149 337.647 c
+415.05 337.754 415.002 337.889 415.002 338.059 c
+417.854 337.029 m
+417.884 336.632 l
+418.119 336.945 418.42 337.103 418.795 337.103 c
+419.478 337.103 419.831 336.622 419.853 335.663 c
+419.853 333.046 l
+418.81 333.046 l
+418.81 335.589 l
+418.81 335.813 418.773 335.975 418.707 336.074 c
+418.637 336.17 418.519 336.221 418.354 336.221 c
+418.166 336.221 418.019 336.125 417.913 335.942 c
+417.913 333.046 l
+416.869 333.046 l
+416.869 337.029 l
+h
+420.456 335.163 m
+420.456 335.809 420.562 336.295 420.779 336.618 c
+421.003 336.941 421.327 337.103 421.749 337.103 c
+422.062 337.103 422.316 336.971 422.513 336.706 c
+422.513 338.691 l
+423.573 338.691 l
+423.573 333.046 l
+422.617 333.046 l
+422.573 333.457 l
+422.356 333.134 422.081 332.973 421.749 332.973 c
+421.337 332.973 421.018 333.127 420.794 333.443 c
+420.577 333.766 420.463 334.236 420.456 334.854 c
+h
+421.499 334.898 m
+421.499 334.505 421.536 334.23 421.617 334.075 c
+421.705 333.918 421.852 333.839 422.058 333.839 c
+422.264 333.839 422.414 333.932 422.513 334.119 c
+422.513 335.927 l
+422.414 336.122 422.264 336.221 422.058 336.221 c
+421.859 336.221 421.72 336.14 421.632 335.986 c
+421.543 335.839 421.499 335.567 421.499 335.177 c
+h
+425.939 332.973 m
+425.41 332.973 424.99 333.127 424.689 333.443 c
+424.395 333.766 424.248 334.226 424.248 334.824 c
+424.248 335.133 l
+424.248 335.759 424.384 336.243 424.66 336.588 c
+424.932 336.931 425.325 337.103 425.836 337.103 c
+426.336 337.103 426.707 336.941 426.953 336.618 c
+427.207 336.295 427.338 335.817 427.35 335.192 c
+427.35 334.693 l
+425.277 334.693 l
+425.296 334.398 425.358 334.182 425.468 334.045 c
+425.586 333.906 425.766 333.839 426.012 333.839 c
+426.354 333.839 426.644 333.957 426.879 334.192 c
+427.291 333.561 l
+427.162 333.384 426.975 333.241 426.732 333.134 c
+426.486 333.028 426.222 332.973 425.939 332.973 c
+425.292 335.412 m
+426.32 335.412 l
+426.32 335.516 l
+426.32 335.751 426.28 335.927 426.203 336.044 c
+426.133 336.17 426.004 336.235 425.821 336.235 c
+425.645 336.235 425.512 336.166 425.424 336.03 c
+425.343 335.902 425.299 335.696 425.292 335.412 c
+429.26 335.839 m
+429.731 337.029 l
+430.833 337.029 l
+429.923 335.075 l
+430.863 333.046 l
+429.761 333.046 l
+429.275 334.296 l
+428.79 333.046 l
+427.673 333.046 l
+428.614 335.075 l
+427.717 337.029 l
+428.82 337.029 l
+h
+f
+q 1 0 0 1 433.1559 335.2214 cm
+0 0 m
+0 0.636 0.088 1.239 0.264 1.808 c
+0.441 2.374 0.684 2.87 1 3.293 c
+1.195 3.557 1.382 3.749 1.558 3.866 c
+1.691 3.41 l
+1.396 3.135 1.154 2.712 0.97 2.146 c
+0.783 1.577 0.68 0.945 0.661 0.25 c
+0.661 -0.044 l
+0.661 -0.908 0.779 -1.672 1.014 -2.337 c
+1.198 -2.836 1.426 -3.219 1.691 -3.484 c
+1.558 -3.91 l
+1.33 -3.752 1.106 -3.501 0.882 -3.16 c
+0.294 -2.278 0 -1.227 0 0 c
+4.027 1.191 m
+3.939 1.209 3.84 1.22 3.734 1.22 c
+3.399 1.22 3.164 1.037 3.028 0.676 c
+3.028 -2.175 l
+2.381 -2.175 l
+2.381 1.808 l
+3.013 1.808 l
+3.028 1.397 l
+3.204 1.72 3.447 1.881 3.763 1.881 c
+3.869 1.881 3.958 1.86 4.027 1.823 c
+h
+6.026 -2.248 m
+5.527 -2.248 5.145 -2.102 4.88 -1.808 c
+4.615 -1.514 4.484 -1.08 4.484 -0.5 c
+4.484 -0.029 l
+4.484 0.566 4.608 1.033 4.866 1.367 c
+5.13 1.709 5.49 1.881 5.953 1.881 c
+6.412 1.881 6.755 1.727 6.982 1.426 c
+7.217 1.132 7.339 0.669 7.35 0.044 c
+7.35 -0.382 l
+5.13 -0.382 l
+5.13 -0.47 l
+5.13 -0.904 5.207 -1.216 5.365 -1.411 c
+5.531 -1.598 5.762 -1.691 6.056 -1.691 c
+6.251 -1.691 6.423 -1.657 6.57 -1.587 c
+6.718 -1.51 6.853 -1.392 6.982 -1.234 c
+7.32 -1.646 l
+7.034 -2.05 6.604 -2.248 6.026 -2.248 c
+5.953 1.323 m
+5.677 1.323 5.475 1.228 5.35 1.044 c
+5.222 0.856 5.149 0.566 5.13 0.177 c
+6.703 0.177 l
+6.703 0.264 l
+6.681 0.647 6.614 0.915 6.497 1.073 c
+6.379 1.239 6.196 1.323 5.953 1.323 c
+11.009 -0.382 m
+11.009 -1.01 10.892 -1.481 10.657 -1.793 c
+10.429 -2.098 10.113 -2.248 9.702 -2.248 c
+9.297 -2.248 8.989 -2.098 8.775 -1.793 c
+8.775 -3.704 l
+8.129 -3.704 l
+8.129 1.808 l
+8.717 1.808 l
+8.761 1.367 l
+8.974 1.709 9.282 1.881 9.687 1.881 c
+10.128 1.881 10.454 1.727 10.672 1.426 c
+10.884 1.121 10.998 0.665 11.009 0.059 c
+h
+10.363 0 m
+10.363 0.441 10.293 0.765 10.157 0.97 c
+10.017 1.183 9.797 1.294 9.496 1.294 c
+9.18 1.294 8.941 1.139 8.775 0.838 c
+8.775 -1.234 l
+8.941 -1.539 9.18 -1.691 9.496 -1.691 c
+9.789 -1.691 10.003 -1.587 10.142 -1.382 c
+10.279 -1.168 10.352 -0.837 10.363 -0.397 c
+h
+11.715 0 m
+11.715 0.578 11.851 1.033 12.127 1.367 c
+12.409 1.709 12.781 1.881 13.244 1.881 c
+13.703 1.881 14.071 1.713 14.346 1.382 c
+14.629 1.058 14.776 0.611 14.787 0.044 c
+14.787 -0.382 l
+14.787 -0.951 14.644 -1.407 14.361 -1.749 c
+14.086 -2.084 13.718 -2.248 13.259 -2.248 c
+12.796 -2.248 12.424 -2.087 12.141 -1.764 c
+11.866 -1.433 11.723 -0.992 11.715 -0.441 c
+h
+12.362 -0.382 m
+12.362 -0.786 12.439 -1.103 12.597 -1.338 c
+12.762 -1.573 12.983 -1.691 13.259 -1.691 c
+13.824 -1.691 14.119 -1.278 14.14 -0.455 c
+14.14 0 l
+14.14 0.401 14.056 0.721 13.891 0.956 c
+13.733 1.199 13.516 1.323 13.244 1.323 c
+12.979 1.323 12.762 1.199 12.597 0.956 c
+12.439 0.721 12.362 0.401 12.362 0 c
+h
+17.565 -1.161 m
+17.565 -1.014 17.51 -0.893 17.404 -0.794 c
+17.294 -0.698 17.088 -0.58 16.787 -0.441 c
+16.441 -0.294 16.199 -0.172 16.052 -0.073 c
+15.904 0.033 15.794 0.151 15.728 0.279 c
+15.659 0.405 15.625 0.563 15.625 0.75 c
+15.625 1.073 15.742 1.341 15.978 1.558 c
+16.213 1.771 16.515 1.881 16.889 1.881 c
+17.271 1.881 17.58 1.768 17.815 1.544 c
+18.05 1.316 18.168 1.029 18.168 0.676 c
+17.521 0.676 l
+17.521 0.852 17.463 1.004 17.344 1.132 c
+17.228 1.257 17.073 1.323 16.889 1.323 c
+16.691 1.323 16.54 1.268 16.434 1.162 c
+16.324 1.062 16.272 0.93 16.272 0.765 c
+16.272 0.636 16.309 0.53 16.39 0.441 c
+16.467 0.36 16.658 0.258 16.962 0.133 c
+17.44 -0.055 17.772 -0.243 17.947 -0.426 c
+18.124 -0.602 18.212 -0.831 18.212 -1.103 c
+18.212 -1.455 18.088 -1.735 17.845 -1.94 c
+17.61 -2.146 17.294 -2.248 16.904 -2.248 c
+16.482 -2.248 16.143 -2.131 15.89 -1.896 c
+15.632 -1.654 15.507 -1.348 15.507 -0.985 c
+16.154 -0.985 l
+16.162 -1.213 16.232 -1.389 16.36 -1.514 c
+16.485 -1.631 16.669 -1.691 16.904 -1.691 c
+17.117 -1.691 17.279 -1.643 17.389 -1.543 c
+17.506 -1.448 17.565 -1.319 17.565 -1.161 c
+19.756 -2.175 -0.646 3.983 re
+19.8 2.851 m
+19.8 2.741 19.771 2.65 19.711 2.573 c
+19.653 2.502 19.557 2.469 19.432 2.469 c
+19.314 2.469 19.219 2.502 19.153 2.573 c
+19.094 2.65 19.065 2.741 19.065 2.851 c
+19.065 2.969 19.094 3.061 19.153 3.131 c
+19.219 3.208 19.314 3.248 19.432 3.248 c
+19.557 3.248 19.653 3.208 19.711 3.131 c
+19.771 3.05 19.8 2.959 19.8 2.851 c
+21.622 2.764 m
+21.622 1.808 l
+22.225 1.808 l
+22.225 1.279 l
+21.622 1.279 l
+21.622 -1.19 l
+21.622 -1.348 21.645 -1.466 21.696 -1.543 c
+21.755 -1.624 21.843 -1.66 21.961 -1.66 c
+22.048 -1.66 22.137 -1.646 22.225 -1.617 c
+22.225 -2.175 l
+22.078 -2.223 21.924 -2.248 21.77 -2.248 c
+21.512 -2.248 21.317 -2.157 21.182 -1.97 c
+21.042 -1.786 20.976 -1.525 20.976 -1.19 c
+20.976 1.279 l
+20.373 1.279 l
+20.373 1.808 l
+20.976 1.808 l
+20.976 2.764 l
+h
+22.784 0 m
+22.784 0.578 22.919 1.033 23.195 1.367 c
+23.478 1.709 23.85 1.881 24.312 1.881 c
+24.772 1.881 25.139 1.713 25.415 1.382 c
+25.697 1.058 25.845 0.611 25.855 0.044 c
+25.855 -0.382 l
+25.855 -0.951 25.712 -1.407 25.429 -1.749 c
+25.154 -2.084 24.787 -2.248 24.327 -2.248 c
+23.864 -2.248 23.493 -2.087 23.21 -1.764 c
+22.934 -1.433 22.791 -0.992 22.784 -0.441 c
+h
+23.43 -0.382 m
+23.43 -0.786 23.507 -1.103 23.665 -1.338 c
+23.831 -1.573 24.051 -1.691 24.327 -1.691 c
+24.893 -1.691 25.186 -1.278 25.209 -0.455 c
+25.209 0 l
+25.209 0.401 25.124 0.721 24.959 0.956 c
+24.801 1.199 24.584 1.323 24.312 1.323 c
+24.048 1.323 23.831 1.199 23.665 0.956 c
+23.507 0.721 23.43 0.401 23.43 0 c
+h
+28.34 1.191 m
+28.251 1.209 28.153 1.22 28.046 1.22 c
+27.711 1.22 27.476 1.037 27.341 0.676 c
+27.341 -2.175 l
+26.693 -2.175 l
+26.693 1.808 l
+27.326 1.808 l
+27.341 1.397 l
+27.517 1.72 27.759 1.881 28.075 1.881 c
+28.182 1.881 28.27 1.86 28.34 1.823 c
+h
+30.148 -1.087 m
+30.868 1.808 l
+31.559 1.808 l
+30.265 -2.734 l
+30.166 -3.075 30.023 -3.337 29.839 -3.513 c
+29.662 -3.69 29.46 -3.777 29.236 -3.777 c
+29.148 -3.777 29.034 -3.755 28.899 -3.719 c
+28.899 -3.175 l
+29.045 -3.189 l
+29.229 -3.189 29.376 -3.146 29.487 -3.057 c
+29.593 -2.969 29.681 -2.811 29.751 -2.587 c
+29.868 -2.146 l
+28.708 1.808 l
+29.413 1.808 l
+h
+35.293 -1.691 m
+35.505 -1.691 35.678 -1.627 35.807 -1.5 c
+35.943 -1.363 36.016 -1.172 36.027 -0.926 c
+36.645 -0.926 l
+36.623 -1.308 36.487 -1.627 36.234 -1.882 c
+35.976 -2.127 35.663 -2.248 35.293 -2.248 c
+34.8 -2.248 34.425 -2.098 34.161 -1.793 c
+33.903 -1.481 33.778 -1.014 33.778 -0.397 c
+33.778 0.044 l
+33.778 0.64 33.903 1.095 34.161 1.411 c
+34.425 1.723 34.8 1.881 35.293 1.881 c
+35.693 1.881 36.012 1.75 36.248 1.484 c
+36.49 1.228 36.623 0.882 36.645 0.441 c
+36.027 0.441 l
+36.005 0.735 35.932 0.956 35.807 1.103 c
+35.689 1.249 35.517 1.323 35.293 1.323 c
+34.998 1.323 34.782 1.224 34.646 1.029 c
+34.506 0.842 34.433 0.533 34.425 0.103 c
+34.425 -0.411 l
+34.425 -0.881 34.491 -1.216 34.631 -1.411 c
+34.778 -1.598 34.998 -1.691 35.293 -1.691 c
+37.262 0 m
+37.262 0.578 37.398 1.033 37.674 1.367 c
+37.957 1.709 38.328 1.881 38.79 1.881 c
+39.25 1.881 39.617 1.713 39.893 1.382 c
+40.176 1.058 40.323 0.611 40.334 0.044 c
+40.334 -0.382 l
+40.334 -0.951 40.191 -1.407 39.908 -1.749 c
+39.632 -2.084 39.265 -2.248 38.806 -2.248 c
+38.343 -2.248 37.971 -2.087 37.689 -1.764 c
+37.413 -1.433 37.269 -0.992 37.262 -0.441 c
+h
+37.909 -0.382 m
+37.909 -0.786 37.986 -1.103 38.144 -1.338 c
+38.31 -1.573 38.53 -1.691 38.806 -1.691 c
+39.372 -1.691 39.665 -1.278 39.687 -0.455 c
+39.687 0 l
+39.687 0.401 39.603 0.721 39.438 0.956 c
+39.28 1.199 39.062 1.323 38.79 1.323 c
+38.526 1.323 38.31 1.199 38.144 0.956 c
+37.986 0.721 37.909 0.401 37.909 0 c
+h
+41.79 1.808 m
+41.804 1.44 l
+42.046 1.735 42.366 1.881 42.759 1.881 c
+43.201 1.881 43.509 1.683 43.685 1.294 c
+43.939 1.683 44.288 1.881 44.729 1.881 c
+45.464 1.881 45.839 1.419 45.861 0.5 c
+45.861 -2.175 l
+45.215 -2.175 l
+45.215 0.441 l
+45.215 0.735 45.159 0.948 45.053 1.087 c
+44.953 1.224 44.781 1.294 44.538 1.294 c
+44.34 1.294 44.178 1.213 44.053 1.058 c
+43.935 0.912 43.866 0.721 43.847 0.485 c
+43.847 -2.175 l
+43.186 -2.175 l
+43.186 0.47 l
+43.186 1.018 42.965 1.294 42.524 1.294 c
+42.19 1.294 41.955 1.132 41.819 0.809 c
+41.819 -2.175 l
+41.172 -2.175 l
+41.172 1.808 l
+h
+47.448 1.808 m
+47.463 1.44 l
+47.706 1.735 48.026 1.881 48.419 1.881 c
+48.859 1.881 49.169 1.683 49.345 1.294 c
+49.599 1.683 49.948 1.881 50.389 1.881 c
+51.124 1.881 51.498 1.419 51.521 0.5 c
+51.521 -2.175 l
+50.873 -2.175 l
+50.873 0.441 l
+50.873 0.735 50.819 0.948 50.712 1.087 c
+50.613 1.224 50.44 1.294 50.197 1.294 c
+49.998 1.294 49.838 1.213 49.712 1.058 c
+49.595 0.912 49.525 0.721 49.506 0.485 c
+49.506 -2.175 l
+48.845 -2.175 l
+48.845 0.47 l
+48.845 1.018 48.624 1.294 48.184 1.294 c
+47.849 1.294 47.614 1.132 47.478 0.809 c
+47.478 -2.175 l
+46.831 -2.175 l
+46.831 1.808 l
+h
+53.196 -2.175 -0.647 3.983 re
+53.24 2.851 m
+53.24 2.741 53.211 2.65 53.152 2.573 c
+53.093 2.502 52.997 2.469 52.872 2.469 c
+52.755 2.469 52.66 2.502 52.593 2.573 c
+52.535 2.65 52.505 2.741 52.505 2.851 c
+52.505 2.969 52.535 3.061 52.593 3.131 c
+52.66 3.208 52.755 3.248 52.872 3.248 c
+52.997 3.248 53.093 3.208 53.152 3.131 c
+53.211 3.05 53.24 2.959 53.24 2.851 c
+55.062 2.764 m
+55.062 1.808 l
+55.665 1.808 l
+55.665 1.279 l
+55.062 1.279 l
+55.062 -1.19 l
+55.062 -1.348 55.085 -1.466 55.136 -1.543 c
+55.195 -1.624 55.283 -1.66 55.401 -1.66 c
+55.489 -1.66 55.577 -1.646 55.665 -1.617 c
+55.665 -2.175 l
+55.519 -2.223 55.364 -2.248 55.209 -2.248 c
+54.952 -2.248 54.758 -2.157 54.622 -1.97 c
+54.482 -1.786 54.416 -1.525 54.416 -1.19 c
+54.416 1.279 l
+53.813 1.279 l
+53.813 1.808 l
+54.416 1.808 l
+54.416 2.764 l
+h
+57.855 -2.248 m
+57.356 -2.248 56.974 -2.102 56.709 -1.808 c
+56.444 -1.514 56.312 -1.08 56.312 -0.5 c
+56.312 -0.029 l
+56.312 0.566 56.437 1.033 56.695 1.367 c
+56.959 1.709 57.319 1.881 57.782 1.881 c
+58.241 1.881 58.583 1.727 58.811 1.426 c
+59.046 1.132 59.168 0.669 59.178 0.044 c
+59.178 -0.382 l
+56.959 -0.382 l
+56.959 -0.47 l
+56.959 -0.904 57.036 -1.216 57.194 -1.411 c
+57.36 -1.598 57.591 -1.691 57.885 -1.691 c
+58.079 -1.691 58.252 -1.657 58.399 -1.587 c
+58.546 -1.51 58.682 -1.392 58.811 -1.234 c
+59.149 -1.646 l
+58.862 -2.05 58.432 -2.248 57.855 -2.248 c
+57.782 1.323 m
+57.507 1.323 57.304 1.228 57.179 1.044 c
+57.051 0.856 56.977 0.566 56.959 0.177 c
+58.532 0.177 l
+58.532 0.264 l
+58.509 0.647 58.443 0.915 58.326 1.073 c
+58.208 1.239 58.025 1.323 57.782 1.323 c
+59.825 0 m
+59.825 0.607 59.935 1.073 60.163 1.397 c
+60.398 1.72 60.726 1.881 61.148 1.881 c
+61.53 1.881 61.828 1.723 62.045 1.411 c
+62.045 3.469 l
+62.692 3.469 l
+62.692 -2.175 l
+62.104 -2.175 l
+62.06 -1.749 l
+61.854 -2.084 61.549 -2.248 61.148 -2.248 c
+60.737 -2.248 60.413 -2.094 60.178 -1.778 c
+59.943 -1.455 59.825 -0.999 59.825 -0.411 c
+h
+60.472 -0.382 m
+60.472 -0.823 60.535 -1.153 60.663 -1.367 c
+60.799 -1.573 61.019 -1.675 61.324 -1.675 c
+61.648 -1.675 61.887 -1.514 62.045 -1.19 c
+62.045 0.823 l
+61.875 1.135 61.637 1.294 61.324 1.294 c
+61.019 1.294 60.799 1.191 60.663 0.985 c
+60.535 0.779 60.472 0.456 60.472 0.015 c
+h
+67.351 -1.161 m
+67.351 -1.014 67.296 -0.893 67.189 -0.794 c
+67.079 -0.698 66.873 -0.58 66.572 -0.441 c
+66.226 -0.294 65.984 -0.172 65.837 -0.073 c
+65.69 0.033 65.58 0.151 65.514 0.279 c
+65.443 0.405 65.411 0.563 65.411 0.75 c
+65.411 1.073 65.528 1.341 65.763 1.558 c
+65.999 1.771 66.3 1.881 66.675 1.881 c
+67.057 1.881 67.365 1.768 67.601 1.544 c
+67.836 1.316 67.953 1.029 67.953 0.676 c
+67.307 0.676 l
+67.307 0.852 67.248 1.004 67.13 1.132 c
+67.013 1.257 66.858 1.323 66.675 1.323 c
+66.476 1.323 66.326 1.268 66.22 1.162 c
+66.109 1.062 66.058 0.93 66.058 0.765 c
+66.058 0.636 66.094 0.53 66.175 0.441 c
+66.253 0.36 66.444 0.258 66.748 0.133 c
+67.226 -0.055 67.557 -0.243 67.733 -0.426 c
+67.909 -0.602 67.998 -0.831 67.998 -1.103 c
+67.998 -1.455 67.872 -1.735 67.631 -1.94 c
+67.396 -2.146 67.079 -2.248 66.69 -2.248 c
+66.267 -2.248 65.929 -2.131 65.676 -1.896 c
+65.418 -1.654 65.293 -1.348 65.293 -0.985 c
+65.94 -0.985 l
+65.948 -1.213 66.017 -1.389 66.146 -1.514 c
+66.27 -1.631 66.455 -1.691 66.69 -1.691 c
+66.903 -1.691 67.064 -1.643 67.174 -1.543 c
+67.292 -1.448 67.351 -1.319 67.351 -1.161 c
+69.688 2.764 m
+69.688 1.808 l
+70.291 1.808 l
+70.291 1.279 l
+69.688 1.279 l
+69.688 -1.19 l
+69.688 -1.348 69.711 -1.466 69.761 -1.543 c
+69.821 -1.624 69.909 -1.66 70.026 -1.66 c
+70.114 -1.66 70.203 -1.646 70.291 -1.617 c
+70.291 -2.175 l
+70.144 -2.223 69.989 -2.248 69.835 -2.248 c
+69.578 -2.248 69.383 -2.157 69.247 -1.97 c
+69.108 -1.786 69.042 -1.525 69.042 -1.19 c
+69.042 1.279 l
+68.439 1.279 l
+68.439 1.808 l
+69.042 1.808 l
+69.042 2.764 l
+h
+73.098 -2.175 m
+73.058 -2.087 73.032 -1.94 73.025 -1.735 c
+72.79 -2.08 72.496 -2.248 72.142 -2.248 c
+71.779 -2.248 71.496 -2.153 71.29 -1.955 c
+71.092 -1.749 70.997 -1.462 70.997 -1.087 c
+70.997 -0.687 71.132 -0.367 71.408 -0.132 c
+71.68 0.11 72.055 0.235 72.525 0.235 c
+73.01 0.235 l
+73.01 0.661 l
+73.01 0.897 72.955 1.062 72.848 1.162 c
+72.738 1.268 72.576 1.323 72.364 1.323 c
+72.165 1.323 72.003 1.264 71.878 1.147 c
+71.761 1.029 71.702 0.882 71.702 0.706 c
+71.055 0.706 l
+71.055 0.9 71.114 1.091 71.232 1.279 c
+71.357 1.463 71.518 1.61 71.716 1.72 c
+71.922 1.827 72.15 1.881 72.408 1.881 c
+72.809 1.881 73.113 1.779 73.318 1.573 c
+73.532 1.367 73.646 1.073 73.657 0.691 c
+73.657 -1.323 l
+73.657 -1.627 73.694 -1.892 73.775 -2.117 c
+73.775 -2.175 l
+h
+72.231 -1.66 m
+72.396 -1.66 72.547 -1.617 72.687 -1.529 c
+72.834 -1.44 72.94 -1.33 73.01 -1.19 c
+73.01 -0.249 l
+72.643 -0.249 l
+72.327 -0.249 72.084 -0.32 71.907 -0.455 c
+71.731 -0.584 71.643 -0.771 71.643 -1.014 c
+71.643 -1.242 71.687 -1.407 71.776 -1.514 c
+71.864 -1.613 72.015 -1.66 72.231 -1.66 c
+75.509 2.764 m
+75.509 1.808 l
+76.111 1.808 l
+76.111 1.279 l
+75.509 1.279 l
+75.509 -1.19 l
+75.509 -1.348 75.531 -1.466 75.583 -1.543 c
+75.641 -1.624 75.73 -1.66 75.847 -1.66 c
+75.936 -1.66 76.024 -1.646 76.111 -1.617 c
+76.111 -2.175 l
+75.965 -2.223 75.81 -2.248 75.656 -2.248 c
+75.398 -2.248 75.204 -2.157 75.068 -1.97 c
+74.928 -1.786 74.862 -1.525 74.862 -1.19 c
+74.862 1.279 l
+74.259 1.279 l
+74.259 1.808 l
+74.862 1.808 l
+74.862 2.764 l
+h
+78.905 -1.822 m
+78.688 -2.109 78.376 -2.248 77.964 -2.248 c
+77.6 -2.248 77.324 -2.127 77.141 -1.882 c
+76.965 -1.627 76.869 -1.264 76.861 -0.794 c
+76.861 1.808 l
+77.508 1.808 l
+77.508 -0.735 l
+77.508 -1.363 77.692 -1.675 78.066 -1.675 c
+78.467 -1.675 78.743 -1.5 78.889 -1.147 c
+78.889 1.808 l
+79.537 1.808 l
+79.537 -2.175 l
+78.92 -2.175 l
+h
+82.461 -1.161 m
+82.461 -1.014 82.407 -0.893 82.3 -0.794 c
+82.19 -0.698 81.984 -0.58 81.683 -0.441 c
+81.337 -0.294 81.095 -0.172 80.948 -0.073 c
+80.801 0.033 80.69 0.151 80.624 0.279 c
+80.555 0.405 80.522 0.563 80.522 0.75 c
+80.522 1.073 80.639 1.341 80.874 1.558 c
+81.11 1.771 81.411 1.881 81.785 1.881 c
+82.168 1.881 82.477 1.768 82.712 1.544 c
+82.947 1.316 83.064 1.029 83.064 0.676 c
+82.417 0.676 l
+82.417 0.852 82.359 1.004 82.241 1.132 c
+82.124 1.257 81.969 1.323 81.785 1.323 c
+81.587 1.323 81.436 1.268 81.33 1.162 c
+81.22 1.062 81.168 0.93 81.168 0.765 c
+81.168 0.636 81.205 0.53 81.286 0.441 c
+81.363 0.36 81.554 0.258 81.859 0.133 c
+82.336 -0.055 82.668 -0.243 82.844 -0.426 c
+83.02 -0.602 83.109 -0.831 83.109 -1.103 c
+83.109 -1.455 82.984 -1.735 82.741 -1.94 c
+82.506 -2.146 82.19 -2.248 81.8 -2.248 c
+81.378 -2.248 81.04 -2.131 80.786 -1.896 c
+80.529 -1.654 80.404 -1.348 80.404 -0.985 c
+81.05 -0.985 l
+81.058 -1.213 81.127 -1.389 81.256 -1.514 c
+81.382 -1.631 81.565 -1.691 81.8 -1.691 c
+82.014 -1.691 82.175 -1.643 82.286 -1.543 c
+82.403 -1.448 82.461 -1.319 82.461 -1.161 c
+85.343 -0.044 m
+85.343 -1.132 85.096 -2.098 84.607 -2.94 c
+84.343 -3.388 84.067 -3.711 83.785 -3.91 c
+83.667 -3.484 l
+83.969 -3.189 84.215 -2.738 84.402 -2.131 c
+84.597 -1.525 84.696 -0.86 84.696 -0.132 c
+84.696 0 l
+84.696 0.93 84.541 1.764 84.24 2.499 c
+84.071 2.899 83.88 3.219 83.667 3.454 c
+83.785 3.866 l
+84.057 3.678 84.321 3.381 84.578 2.969 c
+85.085 2.117 85.343 1.11 85.343 -0.044 c
+86.386 -1.822 m
+86.386 -1.705 86.419 -1.61 86.489 -1.529 c
+86.556 -1.452 86.658 -1.411 86.798 -1.411 c
+86.945 -1.411 87.051 -1.452 87.121 -1.529 c
+87.198 -1.61 87.239 -1.705 87.239 -1.822 c
+87.239 -1.932 87.198 -2.024 87.121 -2.102 c
+87.051 -2.179 86.945 -2.219 86.798 -2.219 c
+86.658 -2.219 86.556 -2.179 86.489 -2.102 c
+86.419 -2.024 86.386 -1.932 86.386 -1.822 c
+f
+Q
+0.113 0.082 0.09 0 k
+287.665 327.439 234.667 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 320.5995 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.146 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.263 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.69 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.772 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.279 -3.219 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.985 c
+-3.322 2.18 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.003 -2.469 3.043 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.558 l
+-1.543 3.558 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.735 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.459 -1.543 2.5 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.36 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.206 c
+-0.756 1.147 -0.595 1.066 -0.455 0.971 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.455 c
+-2.26 2.425 -2.319 2.385 -2.366 2.338 c
+-2.406 2.297 -2.436 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.066 -2.484 1.999 c
+-2.484 1.912 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.201 1.559 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.441 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.302 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.44 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.014 c
+6.402 -2.66 m
+6.184 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.616 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.146 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.411 4.888 -0.205 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.772 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.632 5.137 1.779 c
+5.244 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.264 6.093 2.264 c
+6.188 2.264 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.918 7.107 1.97 c
+7.115 2.029 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.151 2.22 c
+8.004 2.22 l
+7.993 2.139 7.982 2.029 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.871 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.403 7.258 -2.499 7.063 -2.557 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.206 6.924 1.324 6.857 1.411 c
+6.799 1.5 6.729 1.559 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.279 5.835 1.162 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.558 c
+6.725 -0.521 6.799 -0.463 6.857 -0.382 c
+6.924 -0.293 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.302 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.263 l
+8.86 -1.263 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.597 1.602 m
+13.053 1.602 l
+13.053 2.22 l
+13.641 2.22 l
+13.92 3.117 l
+14.494 3.117 l
+14.494 2.22 l
+15.728 2.22 l
+15.728 1.602 l
+14.494 1.602 l
+14.494 -0.103 l
+14.494 -0.323 l
+14.501 -0.393 14.523 -0.455 14.552 -0.515 c
+14.589 -0.565 14.645 -0.61 14.714 -0.646 c
+14.791 -0.675 14.905 -0.69 15.052 -0.69 c
+15.188 -0.69 15.324 -0.687 15.464 -0.675 c
+15.599 -0.658 15.732 -0.632 15.861 -0.602 c
+15.861 -1.205 l
+15.78 -1.216 15.703 -1.23 15.626 -1.249 c
+15.545 -1.261 15.468 -1.267 15.391 -1.278 c
+15.31 -1.286 15.221 -1.294 15.125 -1.294 c
+15.038 -1.301 14.938 -1.308 14.832 -1.308 c
+14.645 -1.308 14.483 -1.294 14.346 -1.263 c
+14.218 -1.227 14.104 -1.183 14.009 -1.132 c
+13.92 -1.084 13.847 -1.025 13.788 -0.955 c
+13.729 -0.878 13.685 -0.801 13.656 -0.72 c
+13.627 -0.632 13.604 -0.544 13.597 -0.455 c
+13.586 -0.36 13.582 -0.264 13.582 -0.176 c
+h
+22.677 -1.323 m
+22.391 -1.323 22.148 -1.282 21.942 -1.205 c
+21.737 -1.117 21.564 -0.995 21.428 -0.837 c
+21.288 -0.683 21.185 -0.496 21.12 -0.279 c
+21.049 -0.055 21.016 0.191 21.016 0.456 c
+21.016 0.75 21.049 1.008 21.12 1.235 c
+21.197 1.459 21.303 1.646 21.442 1.794 c
+21.59 1.948 21.766 2.066 21.972 2.147 c
+22.177 2.234 22.412 2.279 22.677 2.279 c
+22.901 2.279 23.104 2.249 23.28 2.19 c
+23.456 2.132 23.607 2.047 23.736 1.941 c
+23.861 1.841 23.963 1.72 24.044 1.573 c
+24.121 1.434 24.177 1.283 24.206 1.118 c
+23.295 1.073 l
+23.265 1.249 23.196 1.389 23.089 1.5 c
+22.99 1.606 22.846 1.661 22.662 1.661 c
+22.416 1.661 22.24 1.559 22.134 1.353 c
+22.023 1.154 21.972 0.867 21.972 0.485 c
+21.972 -0.309 22.207 -0.706 22.677 -0.706 c
+22.843 -0.706 22.986 -0.654 23.104 -0.544 c
+23.221 -0.437 23.295 -0.276 23.324 -0.058 c
+24.235 -0.103 l
+24.206 -0.272 24.151 -0.426 24.074 -0.573 c
+24.004 -0.72 23.901 -0.852 23.765 -0.97 c
+23.636 -1.08 23.478 -1.168 23.295 -1.234 c
+23.118 -1.294 22.913 -1.323 22.677 -1.323 c
+26.076 1.515 m
+26.194 1.786 26.344 1.985 26.532 2.103 c
+26.716 2.22 26.936 2.279 27.194 2.279 c
+27.399 2.279 27.568 2.242 27.708 2.176 c
+27.855 2.106 27.965 2.014 28.046 1.897 c
+28.135 1.779 28.193 1.636 28.222 1.47 c
+28.259 1.301 28.281 1.125 28.281 0.941 c
+28.281 -1.263 l
+27.37 -1.263 l
+27.37 0.736 l
+27.37 0.871 27.359 0.992 27.341 1.103 c
+27.329 1.209 27.304 1.297 27.267 1.367 c
+27.227 1.444 27.168 1.503 27.09 1.544 c
+27.021 1.58 26.929 1.602 26.811 1.602 c
+26.701 1.602 26.606 1.577 26.518 1.529 c
+26.429 1.478 26.348 1.411 26.282 1.324 c
+26.223 1.235 26.172 1.125 26.136 1 c
+26.106 0.882 26.091 0.75 26.091 0.603 c
+26.091 -1.263 l
+25.18 -1.263 l
+25.18 3.514 l
+26.091 3.514 l
+26.091 2.205 l
+26.091 2.135 26.084 2.066 26.076 1.999 c
+26.076 1.794 l
+26.076 1.735 26.069 1.679 26.061 1.632 c
+26.061 1.515 l
+h
+30.799 -1.323 m
+30.541 -1.323 30.313 -1.286 30.107 -1.22 c
+29.901 -1.143 29.725 -1.028 29.579 -0.881 c
+29.431 -0.727 29.313 -0.536 29.226 -0.309 c
+29.145 -0.085 29.108 0.181 29.108 0.485 c
+29.108 0.816 29.153 1.095 29.24 1.324 c
+29.336 1.559 29.465 1.742 29.623 1.881 c
+29.788 2.018 29.976 2.117 30.181 2.176 c
+30.387 2.242 30.597 2.279 30.813 2.279 c
+31.085 2.279 31.32 2.227 31.519 2.132 c
+31.725 2.043 31.89 1.912 32.018 1.735 c
+32.154 1.565 32.253 1.36 32.313 1.118 c
+32.378 0.882 32.415 0.618 32.415 0.324 c
+32.415 0.309 l
+30.049 0.309 l
+30.049 0.162 30.063 0.023 30.093 -0.103 c
+30.13 -0.231 30.185 -0.345 30.254 -0.44 c
+30.321 -0.529 30.406 -0.598 30.504 -0.646 c
+30.6 -0.698 30.714 -0.72 30.842 -0.72 c
+30.997 -0.72 31.137 -0.687 31.254 -0.617 c
+31.379 -0.551 31.468 -0.448 31.519 -0.309 c
+32.357 -0.382 l
+32.328 -0.481 32.272 -0.588 32.195 -0.706 c
+32.114 -0.816 32.011 -0.918 31.886 -1.014 c
+31.769 -1.103 31.614 -1.176 31.43 -1.234 c
+31.254 -1.294 31.041 -1.323 30.799 -1.323 c
+30.799 1.706 m
+30.71 1.706 30.622 1.691 30.534 1.661 c
+30.446 1.632 30.365 1.58 30.298 1.515 c
+30.229 1.444 30.17 1.357 30.122 1.249 c
+30.082 1.139 30.063 1.014 30.063 0.867 c
+31.534 0.867 l
+31.534 1.004 31.507 1.125 31.46 1.235 c
+31.42 1.342 31.364 1.43 31.298 1.5 c
+31.239 1.565 31.166 1.617 31.077 1.646 c
+30.99 1.683 30.894 1.706 30.799 1.706 c
+34.859 -1.323 m
+34.572 -1.323 34.329 -1.282 34.124 -1.205 c
+33.918 -1.117 33.745 -0.995 33.61 -0.837 c
+33.47 -0.683 33.367 -0.496 33.301 -0.279 c
+33.231 -0.055 33.198 0.191 33.198 0.456 c
+33.198 0.75 33.231 1.008 33.301 1.235 c
+33.378 1.459 33.485 1.646 33.624 1.794 c
+33.772 1.948 33.948 2.066 34.154 2.147 c
+34.36 2.234 34.595 2.279 34.859 2.279 c
+35.083 2.279 35.285 2.249 35.462 2.19 c
+35.638 2.132 35.789 2.047 35.917 1.941 c
+36.043 1.841 36.145 1.72 36.226 1.573 c
+36.303 1.434 36.359 1.283 36.388 1.118 c
+35.476 1.073 l
+35.447 1.249 35.377 1.389 35.27 1.5 c
+35.171 1.606 35.028 1.661 34.844 1.661 c
+34.599 1.661 34.422 1.559 34.315 1.353 c
+34.205 1.154 34.154 0.867 34.154 0.485 c
+34.154 -0.309 34.389 -0.706 34.859 -0.706 c
+35.025 -0.706 35.168 -0.654 35.285 -0.544 c
+35.403 -0.437 35.476 -0.276 35.505 -0.058 c
+36.417 -0.103 l
+36.388 -0.272 36.332 -0.426 36.255 -0.573 c
+36.186 -0.72 36.083 -0.852 35.947 -0.97 c
+35.818 -1.08 35.661 -1.168 35.476 -1.234 c
+35.3 -1.294 35.094 -1.323 34.859 -1.323 c
+39.688 -1.263 m
+38.761 0.309 l
+38.365 0.044 l
+38.365 -1.263 l
+37.468 -1.263 l
+37.468 3.514 l
+38.365 3.514 l
+38.365 0.779 l
+39.615 2.22 l
+40.584 2.22 l
+39.364 0.853 l
+40.673 -1.263 l
+h
+44.631 0.485 m
+44.631 0.21 44.594 -0.04 44.527 -0.264 c
+44.457 -0.481 44.355 -0.669 44.219 -0.823 c
+44.079 -0.981 43.902 -1.103 43.69 -1.19 c
+43.473 -1.278 43.219 -1.323 42.925 -1.323 c
+42.649 -1.323 42.403 -1.278 42.19 -1.19 c
+41.984 -1.103 41.812 -0.981 41.676 -0.823 c
+41.536 -0.669 41.433 -0.481 41.367 -0.264 c
+41.298 -0.04 41.265 0.21 41.265 0.485 c
+41.265 0.738 41.294 0.974 41.352 1.191 c
+41.419 1.415 41.521 1.606 41.661 1.764 c
+41.797 1.929 41.973 2.058 42.19 2.147 c
+42.403 2.234 42.661 2.279 42.954 2.279 c
+43.267 2.279 43.528 2.234 43.734 2.147 c
+43.947 2.058 44.12 1.929 44.248 1.764 c
+44.384 1.606 44.483 1.415 44.542 1.191 c
+44.6 0.974 44.631 0.738 44.631 0.485 c
+43.675 0.485 m
+43.675 0.691 43.66 0.867 43.631 1.014 c
+43.609 1.162 43.572 1.283 43.513 1.382 c
+43.455 1.478 43.381 1.548 43.293 1.588 c
+43.204 1.636 43.094 1.661 42.969 1.661 c
+42.705 1.661 42.514 1.562 42.396 1.367 c
+42.279 1.18 42.219 0.886 42.219 0.485 c
+42.219 0.063 42.279 -0.243 42.396 -0.426 c
+42.514 -0.613 42.69 -0.706 42.925 -0.706 c
+43.05 -0.706 43.164 -0.687 43.264 -0.646 c
+43.359 -0.598 43.44 -0.525 43.499 -0.426 c
+43.565 -0.33 43.609 -0.205 43.631 -0.058 c
+43.66 0.088 43.675 0.268 43.675 0.485 c
+46.368 2.22 m
+46.368 0.265 l
+46.368 0.125 46.376 0 46.398 -0.118 c
+46.416 -0.228 46.449 -0.32 46.501 -0.397 c
+46.549 -0.478 46.607 -0.54 46.677 -0.588 c
+46.743 -0.628 46.828 -0.646 46.927 -0.646 c
+47.015 -0.646 47.096 -0.628 47.177 -0.588 c
+47.265 -0.54 47.339 -0.47 47.397 -0.382 c
+47.457 -0.286 47.5 -0.176 47.53 -0.058 c
+47.567 0.067 47.588 0.206 47.588 0.353 c
+47.588 2.22 l
+48.485 2.22 l
+48.485 -0.484 l
+48.485 -0.72 l
+48.492 -0.801 48.5 -0.878 48.5 -0.955 c
+48.5 -1.146 l
+48.507 -1.198 48.515 -1.234 48.515 -1.263 c
+47.662 -1.263 l
+47.651 -1.234 47.64 -1.198 47.632 -1.146 c
+47.632 -0.955 l
+47.632 -0.889 47.625 -0.819 47.617 -0.75 c
+47.617 -0.573 l
+47.603 -0.573 l
+47.486 -0.837 47.331 -1.028 47.147 -1.146 c
+46.971 -1.263 46.769 -1.323 46.545 -1.323 c
+46.339 -1.323 46.166 -1.286 46.03 -1.22 c
+45.891 -1.153 45.78 -1.058 45.693 -0.941 c
+45.612 -0.823 45.552 -0.687 45.516 -0.529 c
+45.487 -0.363 45.472 -0.187 45.472 0 c
+45.472 2.22 l
+h
+50.15 1.602 m
+49.606 1.602 l
+49.606 2.22 l
+50.194 2.22 l
+50.473 3.117 l
+51.046 3.117 l
+51.046 2.22 l
+52.281 2.22 l
+52.281 1.602 l
+51.046 1.602 l
+51.046 -0.103 l
+51.046 -0.323 l
+51.054 -0.393 51.076 -0.455 51.105 -0.515 c
+51.142 -0.565 51.197 -0.61 51.267 -0.646 c
+51.344 -0.675 51.458 -0.69 51.605 -0.69 c
+51.741 -0.69 51.877 -0.687 52.016 -0.675 c
+52.153 -0.658 52.284 -0.632 52.413 -0.602 c
+52.413 -1.205 l
+52.332 -1.216 52.255 -1.23 52.178 -1.249 c
+52.097 -1.261 52.02 -1.267 51.943 -1.278 c
+51.862 -1.286 51.774 -1.294 51.679 -1.294 c
+51.59 -1.301 51.491 -1.308 51.384 -1.308 c
+51.197 -1.308 51.035 -1.294 50.9 -1.263 c
+50.771 -1.227 50.657 -1.183 50.561 -1.132 c
+50.473 -1.084 50.399 -1.025 50.341 -0.955 c
+50.283 -0.878 50.238 -0.801 50.208 -0.72 c
+50.179 -0.632 50.157 -0.544 50.15 -0.455 c
+50.139 -0.36 50.135 -0.264 50.135 -0.176 c
+h
+58.26 0.838 1.866 -0.794 re
+58.26 0.044 m
+62.32 0.838 1.867 -0.794 re
+62.32 0.044 m
+70.603 -2.631 m
+70.603 3.514 l
+72.529 3.514 l
+72.529 2.896 l
+71.456 2.896 l
+71.456 -2.013 l
+72.529 -2.013 l
+72.529 -2.631 l
+h
+75.561 1.602 m
+75.561 -1.263 l
+74.664 -1.263 l
+74.664 1.602 l
+73.841 1.602 l
+73.841 2.22 l
+74.664 2.22 l
+74.664 2.484 l
+74.664 2.61 74.679 2.741 74.708 2.882 c
+74.745 3.017 74.815 3.135 74.914 3.234 c
+75.02 3.341 75.164 3.429 75.34 3.499 c
+75.517 3.564 75.741 3.601 76.016 3.601 c
+76.23 3.601 76.428 3.591 76.604 3.572 c
+76.78 3.55 76.932 3.532 77.06 3.514 c
+77.06 2.926 l
+76.932 2.944 76.788 2.959 76.634 2.97 c
+76.476 2.977 76.325 2.984 76.178 2.984 c
+76.049 2.984 75.947 2.97 75.87 2.94 c
+75.789 2.911 75.726 2.87 75.679 2.822 c
+75.627 2.771 75.594 2.708 75.575 2.631 c
+75.564 2.562 75.561 2.484 75.561 2.396 c
+75.561 2.22 l
+76.986 2.22 l
+76.986 1.602 l
+h
+80.08 -0.646 m
+81.212 -0.646 l
+81.212 -1.263 l
+77.905 -1.263 l
+77.905 -0.646 l
+79.17 -0.646 l
+79.17 1.602 l
+78.243 1.602 l
+78.243 2.22 l
+80.08 2.22 l
+h
+79.17 3.514 0.911 -0.676 re
+79.17 2.837 m
+84.142 -0.646 m
+85.273 -0.646 l
+85.273 -1.263 l
+81.966 -1.263 l
+81.966 -0.646 l
+83.23 -0.646 l
+83.23 2.896 l
+82.304 2.896 l
+82.304 3.514 l
+84.142 3.514 l
+h
+87.658 -1.323 m
+87.401 -1.323 87.173 -1.286 86.968 -1.22 c
+86.762 -1.143 86.585 -1.028 86.438 -0.881 c
+86.291 -0.727 86.174 -0.536 86.085 -0.309 c
+86.004 -0.085 85.968 0.181 85.968 0.485 c
+85.968 0.816 86.012 1.095 86.1 1.324 c
+86.195 1.559 86.324 1.742 86.482 1.881 c
+86.648 2.018 86.835 2.117 87.041 2.176 c
+87.246 2.242 87.456 2.279 87.673 2.279 c
+87.945 2.279 88.18 2.227 88.379 2.132 c
+88.584 2.043 88.749 1.912 88.878 1.735 c
+89.014 1.565 89.113 1.36 89.172 1.118 c
+89.239 0.882 89.275 0.618 89.275 0.324 c
+89.275 0.309 l
+86.908 0.309 l
+86.908 0.162 86.923 0.023 86.953 -0.103 c
+86.989 -0.231 87.045 -0.345 87.114 -0.44 c
+87.18 -0.529 87.265 -0.598 87.364 -0.646 c
+87.46 -0.698 87.573 -0.72 87.702 -0.72 c
+87.857 -0.72 87.996 -0.687 88.113 -0.617 c
+88.239 -0.551 88.327 -0.448 88.379 -0.309 c
+89.216 -0.382 l
+89.187 -0.481 89.131 -0.588 89.054 -0.706 c
+88.973 -0.816 88.871 -0.918 88.746 -1.014 c
+88.628 -1.103 88.474 -1.176 88.29 -1.234 c
+88.113 -1.294 87.901 -1.323 87.658 -1.323 c
+87.658 1.706 m
+87.57 1.706 87.481 1.691 87.394 1.661 c
+87.305 1.632 87.224 1.58 87.159 1.515 c
+87.088 1.444 87.03 1.357 86.982 1.249 c
+86.941 1.139 86.923 1.014 86.923 0.867 c
+88.393 0.867 l
+88.393 1.004 88.367 1.125 88.319 1.235 c
+88.279 1.342 88.224 1.43 88.158 1.5 c
+88.099 1.565 88.026 1.617 87.938 1.646 c
+87.849 1.683 87.754 1.706 87.658 1.706 c
+90.528 -2.631 m
+90.528 -2.013 l
+91.601 -2.013 l
+91.601 2.896 l
+90.528 2.896 l
+90.528 3.514 l
+92.454 3.514 l
+92.454 -2.631 l
+h
+f
+Q
+q 1 0 0 1 311.4185 304.4451 cm
+0 0 m
+0 5.351 l
+1.278 5.351 l
+1.903 5.351 2.389 5.152 2.734 4.763 c
+3.075 4.37 3.248 3.822 3.248 3.117 c
+3.248 2.22 l
+3.248 1.515 3.072 0.963 2.719 0.574 c
+2.373 0.192 1.87 0 1.205 0 c
+h
+0.676 4.778 m
+0.676 0.574 l
+1.22 0.574 l
+1.69 0.574 2.032 0.709 2.248 0.985 c
+2.473 1.257 2.587 1.661 2.587 2.191 c
+2.587 3.132 l
+2.587 3.697 2.477 4.116 2.263 4.381 c
+2.047 4.645 1.72 4.778 1.278 4.778 c
+h
+4.91 0 -0.647 3.984 re
+4.953 5.027 m
+4.953 4.917 4.924 4.825 4.865 4.748 c
+4.806 4.678 4.711 4.645 4.586 4.645 c
+4.469 4.645 4.373 4.678 4.307 4.748 c
+4.247 4.825 4.218 4.917 4.218 5.027 c
+4.218 5.145 4.247 5.237 4.307 5.307 c
+4.373 5.384 4.469 5.424 4.586 5.424 c
+4.711 5.424 4.806 5.384 4.865 5.307 c
+4.924 5.226 4.953 5.134 4.953 5.027 c
+7.864 1.015 m
+7.864 1.162 7.809 1.283 7.702 1.382 c
+7.592 1.478 7.386 1.596 7.085 1.735 c
+6.739 1.882 6.497 2.003 6.35 2.103 c
+6.202 2.209 6.092 2.326 6.026 2.455 c
+5.957 2.58 5.924 2.739 5.924 2.926 c
+5.924 3.249 6.041 3.517 6.277 3.734 c
+6.512 3.947 6.813 4.057 7.187 4.057 c
+7.57 4.057 7.879 3.944 8.114 3.72 c
+8.349 3.491 8.467 3.205 8.467 2.852 c
+7.819 2.852 l
+7.819 3.028 7.761 3.179 7.643 3.308 c
+7.526 3.433 7.372 3.499 7.187 3.499 c
+6.989 3.499 6.838 3.444 6.732 3.337 c
+6.622 3.238 6.57 3.105 6.57 2.94 c
+6.57 2.812 6.607 2.705 6.688 2.617 c
+6.765 2.536 6.956 2.433 7.262 2.309 c
+7.739 2.12 8.07 1.933 8.246 1.75 c
+8.422 1.573 8.511 1.345 8.511 1.073 c
+8.511 0.721 8.386 0.441 8.143 0.235 c
+7.908 0.03 7.592 -0.073 7.202 -0.073 c
+6.78 -0.073 6.441 0.044 6.188 0.279 c
+5.93 0.522 5.806 0.827 5.806 1.191 c
+6.453 1.191 l
+6.46 0.963 6.53 0.786 6.659 0.662 c
+6.784 0.545 6.967 0.485 7.202 0.485 c
+7.416 0.485 7.577 0.533 7.688 0.632 c
+7.805 0.728 7.864 0.857 7.864 1.015 c
+10.73 0.485 m
+10.944 0.485 11.116 0.548 11.245 0.676 c
+11.38 0.813 11.454 1.004 11.465 1.25 c
+12.082 1.25 l
+12.06 0.867 11.925 0.548 11.671 0.294 c
+11.414 0.048 11.102 -0.073 10.73 -0.073 c
+10.238 -0.073 9.863 0.077 9.598 0.383 c
+9.341 0.695 9.216 1.162 9.216 1.779 c
+9.216 2.22 l
+9.216 2.816 9.341 3.271 9.598 3.587 c
+9.863 3.899 10.238 4.057 10.73 4.057 c
+11.131 4.057 11.451 3.925 11.686 3.66 c
+11.928 3.404 12.06 3.057 12.082 2.617 c
+11.465 2.617 l
+11.443 2.911 11.37 3.132 11.245 3.279 c
+11.127 3.425 10.954 3.499 10.73 3.499 c
+10.436 3.499 10.219 3.4 10.084 3.205 c
+9.944 3.017 9.87 2.708 9.863 2.278 c
+9.863 1.764 l
+9.863 1.294 9.929 0.96 10.069 0.765 c
+10.215 0.578 10.436 0.485 10.73 0.485 c
+14.875 0 m
+14.835 0.088 14.809 0.235 14.802 0.441 c
+14.566 0.096 14.273 -0.073 13.92 -0.073 c
+13.556 -0.073 13.273 0.023 13.067 0.221 c
+12.868 0.427 12.773 0.713 12.773 1.088 c
+12.773 1.488 12.909 1.808 13.184 2.043 c
+13.456 2.286 13.832 2.411 14.302 2.411 c
+14.787 2.411 l
+14.787 2.837 l
+14.787 3.072 14.732 3.238 14.626 3.337 c
+14.515 3.444 14.354 3.499 14.14 3.499 c
+13.942 3.499 13.78 3.44 13.655 3.323 c
+13.537 3.205 13.479 3.057 13.479 2.882 c
+12.832 2.882 l
+12.832 3.076 12.891 3.267 13.009 3.454 c
+13.134 3.639 13.295 3.786 13.493 3.896 c
+13.699 4.002 13.927 4.057 14.184 4.057 c
+14.585 4.057 14.89 3.955 15.096 3.749 c
+15.309 3.543 15.422 3.249 15.434 2.866 c
+15.434 0.853 l
+15.434 0.548 15.47 0.283 15.551 0.059 c
+15.551 0 l
+h
+14.008 0.515 m
+14.173 0.515 14.324 0.559 14.464 0.647 c
+14.611 0.736 14.717 0.846 14.787 0.985 c
+14.787 1.926 l
+14.42 1.926 l
+14.104 1.926 13.861 1.856 13.685 1.721 c
+13.508 1.592 13.42 1.405 13.42 1.162 c
+13.42 0.934 13.464 0.769 13.552 0.662 c
+13.641 0.563 13.791 0.515 14.008 0.515 c
+18.08 3.367 m
+17.992 3.385 17.892 3.396 17.786 3.396 c
+17.452 3.396 17.216 3.212 17.08 2.852 c
+17.08 0 l
+16.434 0 l
+16.434 3.984 l
+17.065 3.984 l
+17.08 3.572 l
+17.256 3.896 17.499 4.057 17.815 4.057 c
+17.922 4.057 18.01 4.035 18.08 3.998 c
+h
+18.52 2.176 m
+18.52 2.782 18.63 3.249 18.859 3.572 c
+19.094 3.896 19.421 4.057 19.843 4.057 c
+20.226 4.057 20.523 3.899 20.74 3.587 c
+20.74 5.644 l
+21.387 5.644 l
+21.387 0 l
+20.799 0 l
+20.755 0.427 l
+20.549 0.092 20.244 -0.073 19.843 -0.073 c
+19.432 -0.073 19.108 0.081 18.873 0.397 c
+18.638 0.721 18.52 1.176 18.52 1.764 c
+h
+19.168 1.794 m
+19.168 1.353 19.23 1.022 19.359 0.809 c
+19.494 0.603 19.715 0.5 20.02 0.5 c
+20.343 0.5 20.582 0.662 20.74 0.985 c
+20.74 2.999 l
+20.571 3.311 20.332 3.469 20.02 3.469 c
+19.715 3.469 19.494 3.367 19.359 3.161 c
+19.23 2.955 19.168 2.631 19.168 2.191 c
+h
+25.487 0.485 m
+25.701 0.485 25.874 0.548 26.002 0.676 c
+26.138 0.813 26.212 1.004 26.223 1.25 c
+26.84 1.25 l
+26.819 0.867 26.682 0.548 26.428 0.294 c
+26.171 0.048 25.859 -0.073 25.487 -0.073 c
+24.995 -0.073 24.621 0.077 24.356 0.383 c
+24.099 0.695 23.974 1.162 23.974 1.779 c
+23.974 2.22 l
+23.974 2.816 24.099 3.271 24.356 3.587 c
+24.621 3.899 24.995 4.057 25.487 4.057 c
+25.888 4.057 26.208 3.925 26.443 3.66 c
+26.686 3.404 26.819 3.057 26.84 2.617 c
+26.223 2.617 l
+26.201 2.911 26.127 3.132 26.002 3.279 c
+25.884 3.425 25.712 3.499 25.487 3.499 c
+25.194 3.499 24.978 3.4 24.841 3.205 c
+24.702 3.017 24.628 2.708 24.621 2.278 c
+24.621 1.764 l
+24.621 1.294 24.687 0.96 24.826 0.765 c
+24.974 0.578 25.194 0.485 25.487 0.485 c
+28.236 3.572 m
+28.49 3.896 28.81 4.057 29.192 4.057 c
+29.898 4.057 30.254 3.587 30.265 2.646 c
+30.265 0 l
+29.618 0 l
+29.618 2.617 l
+29.618 2.929 29.564 3.15 29.456 3.279 c
+29.346 3.404 29.192 3.469 28.986 3.469 c
+28.828 3.469 28.681 3.414 28.545 3.308 c
+28.417 3.198 28.313 3.061 28.236 2.897 c
+28.236 0 l
+27.59 0 l
+27.59 5.644 l
+28.236 5.644 l
+h
+33.264 0 m
+33.223 0.088 33.198 0.235 33.19 0.441 c
+32.955 0.096 32.662 -0.073 32.308 -0.073 c
+31.945 -0.073 31.662 0.023 31.456 0.221 c
+31.257 0.427 31.162 0.713 31.162 1.088 c
+31.162 1.488 31.297 1.808 31.573 2.043 c
+31.845 2.286 32.22 2.411 32.691 2.411 c
+33.175 2.411 l
+33.175 2.837 l
+33.175 3.072 33.121 3.238 33.013 3.337 c
+32.903 3.444 32.741 3.499 32.529 3.499 c
+32.33 3.499 32.169 3.44 32.043 3.323 c
+31.926 3.205 31.868 3.057 31.868 2.882 c
+31.22 2.882 l
+31.22 3.076 31.28 3.267 31.397 3.454 c
+31.522 3.639 31.683 3.786 31.882 3.896 c
+32.088 4.002 32.315 4.057 32.573 4.057 c
+32.974 4.057 33.279 3.955 33.484 3.749 c
+33.697 3.543 33.811 3.249 33.822 2.866 c
+33.822 0.853 l
+33.822 0.548 33.859 0.283 33.94 0.059 c
+33.94 0 l
+h
+32.396 0.515 m
+32.562 0.515 32.712 0.559 32.852 0.647 c
+32.999 0.736 33.106 0.846 33.175 0.985 c
+33.175 1.926 l
+32.808 1.926 l
+32.492 1.926 32.249 1.856 32.073 1.721 c
+31.897 1.592 31.808 1.405 31.808 1.162 c
+31.808 0.934 31.852 0.769 31.941 0.662 c
+32.029 0.563 32.18 0.515 32.396 0.515 c
+35.44 3.984 m
+35.454 3.543 l
+35.708 3.884 36.031 4.057 36.424 4.057 c
+37.13 4.057 37.486 3.587 37.497 2.646 c
+37.497 0 l
+36.851 0 l
+36.851 2.617 l
+36.851 2.929 36.795 3.15 36.689 3.279 c
+36.579 3.404 36.424 3.469 36.218 3.469 c
+36.06 3.469 35.914 3.414 35.777 3.308 c
+35.648 3.198 35.546 3.061 35.469 2.897 c
+35.469 0 l
+34.821 0 l
+34.821 3.984 l
+h
+38.335 2.176 m
+38.335 2.793 38.445 3.256 38.673 3.572 c
+38.897 3.896 39.232 4.057 39.673 4.057 c
+40.073 4.057 40.378 3.881 40.583 3.528 c
+40.628 3.984 l
+41.216 3.984 l
+41.216 -0.043 l
+41.216 -0.532 41.088 -0.911 40.834 -1.176 c
+40.577 -1.44 40.224 -1.572 39.775 -1.572 c
+39.577 -1.572 39.357 -1.521 39.114 -1.425 c
+38.868 -1.326 38.688 -1.205 38.57 -1.058 c
+38.835 -0.617 l
+39.099 -0.881 39.397 -1.014 39.731 -1.014 c
+40.267 -1.014 40.543 -0.72 40.554 -0.132 c
+40.554 0.397 l
+40.348 0.081 40.047 -0.073 39.658 -0.073 c
+39.247 -0.073 38.923 0.077 38.688 0.383 c
+38.46 0.695 38.343 1.147 38.335 1.735 c
+h
+38.996 1.794 m
+38.996 1.353 39.059 1.022 39.187 0.809 c
+39.313 0.603 39.529 0.5 39.834 0.5 c
+40.157 0.5 40.396 0.665 40.554 1 c
+40.554 2.984 l
+40.385 3.308 40.147 3.469 39.834 3.469 c
+39.54 3.469 39.324 3.367 39.187 3.161 c
+39.059 2.955 38.996 2.631 38.996 2.191 c
+h
+43.597 -0.073 m
+43.097 -0.073 42.715 0.074 42.451 0.368 c
+42.186 0.662 42.054 1.095 42.054 1.676 c
+42.054 2.147 l
+42.054 2.741 42.179 3.209 42.436 3.543 c
+42.7 3.884 43.06 4.057 43.523 4.057 c
+43.983 4.057 44.325 3.903 44.552 3.602 c
+44.788 3.308 44.909 2.845 44.92 2.22 c
+44.92 1.794 l
+42.7 1.794 l
+42.7 1.706 l
+42.7 1.272 42.777 0.96 42.935 0.765 c
+43.101 0.578 43.332 0.485 43.627 0.485 c
+43.822 0.485 43.994 0.518 44.141 0.588 c
+44.288 0.665 44.424 0.783 44.552 0.941 c
+44.891 0.53 l
+44.604 0.125 44.174 -0.073 43.597 -0.073 c
+43.523 3.499 m
+43.248 3.499 43.046 3.404 42.921 3.219 c
+42.792 3.032 42.719 2.741 42.7 2.352 c
+44.273 2.352 l
+44.273 2.44 l
+44.251 2.822 44.186 3.091 44.067 3.249 c
+43.95 3.414 43.766 3.499 43.523 3.499 c
+47.639 1.015 m
+47.639 1.162 47.584 1.283 47.478 1.382 c
+47.367 1.478 47.162 1.596 46.86 1.735 c
+46.515 1.882 46.272 2.003 46.125 2.103 c
+45.979 2.209 45.869 2.326 45.802 2.455 c
+45.732 2.58 45.699 2.739 45.699 2.926 c
+45.699 3.249 45.817 3.517 46.052 3.734 c
+46.287 3.947 46.588 4.057 46.964 4.057 c
+47.346 4.057 47.654 3.944 47.889 3.72 c
+48.124 3.491 48.242 3.205 48.242 2.852 c
+47.595 2.852 l
+47.595 3.028 47.536 3.179 47.419 3.308 c
+47.301 3.433 47.147 3.499 46.964 3.499 c
+46.765 3.499 46.615 3.444 46.507 3.337 c
+46.397 3.238 46.346 3.105 46.346 2.94 c
+46.346 2.812 46.382 2.705 46.463 2.617 c
+46.54 2.536 46.732 2.433 47.037 2.309 c
+47.515 2.12 47.845 1.933 48.022 1.75 c
+48.198 1.573 48.286 1.345 48.286 1.073 c
+48.286 0.721 48.161 0.441 47.918 0.235 c
+47.683 0.03 47.367 -0.073 46.978 -0.073 c
+46.555 -0.073 46.218 0.044 45.964 0.279 c
+45.707 0.522 45.582 0.827 45.582 1.191 c
+46.228 1.191 l
+46.235 0.963 46.305 0.786 46.434 0.662 c
+46.559 0.545 46.743 0.485 46.978 0.485 c
+47.191 0.485 47.353 0.533 47.463 0.632 c
+47.581 0.728 47.639 0.857 47.639 1.015 c
+51.55 0 -0.647 3.984 re
+51.593 5.027 m
+51.593 4.917 51.564 4.825 51.505 4.748 c
+51.446 4.678 51.351 4.645 51.226 4.645 c
+51.108 4.645 51.013 4.678 50.947 4.748 c
+50.887 4.825 50.858 4.917 50.858 5.027 c
+50.858 5.145 50.887 5.237 50.947 5.307 c
+51.013 5.384 51.108 5.424 51.226 5.424 c
+51.351 5.424 51.446 5.384 51.505 5.307 c
+51.564 5.226 51.593 5.134 51.593 5.027 c
+53.181 3.984 m
+53.196 3.543 l
+53.449 3.884 53.773 4.057 54.166 4.057 c
+54.871 4.057 55.228 3.587 55.239 2.646 c
+55.239 0 l
+54.592 0 l
+54.592 2.617 l
+54.592 2.929 54.537 3.15 54.43 3.279 c
+54.32 3.404 54.166 3.469 53.96 3.469 c
+53.802 3.469 53.655 3.414 53.519 3.308 c
+53.391 3.198 53.287 3.061 53.21 2.897 c
+53.21 0 l
+52.564 0 l
+52.564 3.984 l
+h
+f
+Q
+q 1 0 0 1 372.1404 306.1949 cm
+0 0 m
+0.353 2.234 l
+1.352 2.234 l
+0.529 -1.75 l
+-0.339 -1.75 l
+-0.897 0.559 l
+-1.455 -1.75 l
+-2.323 -1.75 l
+-3.146 2.234 l
+-2.147 2.234 l
+-1.794 0 l
+-1.264 2.234 l
+-0.53 2.234 l
+h
+1.749 0.367 m
+1.749 0.974 1.888 1.448 2.175 1.793 c
+2.458 2.135 2.851 2.308 3.351 2.308 c
+3.858 2.308 4.255 2.135 4.542 1.793 c
+4.825 1.448 4.968 0.974 4.968 0.367 c
+4.968 0.103 l
+4.968 -0.497 4.825 -0.967 4.542 -1.309 c
+4.255 -1.654 3.858 -1.823 3.351 -1.823 c
+2.84 -1.823 2.443 -1.654 2.16 -1.309 c
+1.885 -0.967 1.749 -0.493 1.749 0.118 c
+h
+2.792 0.103 m
+2.792 -0.603 2.977 -0.956 3.351 -0.956 c
+3.704 -0.956 3.895 -0.661 3.925 -0.073 c
+3.925 0.367 l
+3.925 0.727 3.873 0.999 3.777 1.176 c
+3.678 1.352 3.534 1.44 3.351 1.44 c
+3.175 1.44 3.035 1.352 2.94 1.176 c
+2.84 0.999 2.792 0.727 2.792 0.367 c
+h
+7.569 1.22 m
+7.231 1.249 l
+6.945 1.249 6.754 1.124 6.659 0.881 c
+6.659 -1.75 l
+5.614 -1.75 l
+5.614 2.234 l
+6.585 2.234 l
+6.614 1.793 l
+6.78 2.135 7.011 2.308 7.305 2.308 c
+7.422 2.308 7.515 2.285 7.584 2.248 c
+h
+9.437 -0.221 m
+9.157 -0.53 l
+9.157 -1.75 l
+8.114 -1.75 l
+8.114 3.895 l
+9.157 3.895 l
+9.157 0.852 l
+9.275 1.043 l
+9.995 2.234 l
+11.245 2.234 l
+10.083 0.588 l
+11.347 -1.75 l
+10.156 -1.75 l
+h
+12.803 -1.75 -1.043 3.984 re
+11.715 3.263 m
+11.715 3.418 11.763 3.546 11.862 3.645 c
+11.968 3.752 12.104 3.807 12.273 3.807 c
+12.45 3.807 12.586 3.752 12.685 3.645 c
+12.791 3.546 12.847 3.418 12.847 3.263 c
+12.847 3.094 12.791 2.958 12.685 2.851 c
+12.586 2.753 12.45 2.705 12.273 2.705 c
+12.104 2.705 11.968 2.753 11.862 2.851 c
+11.763 2.958 11.715 3.094 11.715 3.263 c
+14.566 2.234 m
+14.596 1.837 l
+14.831 2.15 15.133 2.308 15.507 2.308 c
+16.191 2.308 16.544 1.826 16.565 0.867 c
+16.565 -1.75 l
+15.522 -1.75 l
+15.522 0.794 l
+15.522 1.018 15.486 1.18 15.419 1.278 c
+15.349 1.374 15.232 1.425 15.066 1.425 c
+14.879 1.425 14.732 1.33 14.625 1.147 c
+14.625 -1.75 l
+13.581 -1.75 l
+13.581 2.234 l
+h
+17.183 0.367 m
+17.183 1.014 17.3 1.5 17.535 1.822 c
+17.771 2.146 18.102 2.308 18.535 2.308 c
+18.888 2.308 19.16 2.165 19.359 1.882 c
+19.403 2.234 l
+20.343 2.234 l
+20.343 -1.75 l
+20.343 -2.257 20.2 -2.646 19.917 -2.911 c
+19.63 -3.182 19.226 -3.322 18.697 -3.322 c
+18.469 -3.322 18.233 -3.278 17.992 -3.19 c
+17.756 -3.102 17.58 -2.988 17.462 -2.851 c
+17.815 -2.132 l
+17.911 -2.238 18.039 -2.323 18.197 -2.381 c
+18.351 -2.448 18.499 -2.484 18.638 -2.484 c
+18.873 -2.484 19.039 -2.425 19.137 -2.308 c
+19.245 -2.198 19.299 -2.022 19.299 -1.779 c
+19.299 -1.426 l
+19.101 -1.69 18.844 -1.823 18.52 -1.823 c
+18.098 -1.823 17.771 -1.661 17.535 -1.338 c
+17.308 -1.008 17.19 -0.537 17.183 0.073 c
+h
+18.227 0.103 m
+18.227 -0.272 18.274 -0.54 18.374 -0.706 c
+18.469 -0.875 18.623 -0.956 18.829 -0.956 c
+19.042 -0.956 19.201 -0.879 19.299 -0.721 c
+19.299 1.176 l
+19.189 1.341 19.035 1.425 18.829 1.425 c
+18.623 1.425 18.469 1.341 18.374 1.176 c
+18.274 1.007 18.227 0.738 18.227 0.367 c
+h
+22.695 0.367 m
+22.695 1.014 22.802 1.5 23.018 1.822 c
+23.243 2.146 23.566 2.308 23.989 2.308 c
+24.301 2.308 24.554 2.175 24.753 1.911 c
+24.753 3.895 l
+25.811 3.895 l
+25.811 -1.75 l
+24.856 -1.75 l
+24.812 -1.338 l
+24.595 -1.661 24.319 -1.823 23.989 -1.823 c
+23.577 -1.823 23.257 -1.669 23.033 -1.353 c
+22.817 -1.029 22.702 -0.559 22.695 0.058 c
+h
+23.739 0.103 m
+23.739 -0.291 23.775 -0.566 23.856 -0.721 c
+23.945 -0.879 24.091 -0.956 24.297 -0.956 c
+24.503 -0.956 24.654 -0.864 24.753 -0.676 c
+24.753 1.132 l
+24.654 1.326 24.503 1.425 24.297 1.425 c
+24.099 1.425 23.959 1.344 23.871 1.19 c
+23.783 1.043 23.739 0.771 23.739 0.382 c
+h
+27.663 -1.75 -1.044 3.984 re
+26.576 3.263 m
+26.576 3.418 26.623 3.546 26.723 3.645 c
+26.829 3.752 26.965 3.807 27.134 3.807 c
+27.311 3.807 27.446 3.752 27.546 3.645 c
+27.652 3.546 27.708 3.418 27.708 3.263 c
+27.708 3.094 27.652 2.958 27.546 2.851 c
+27.446 2.753 27.311 2.705 27.134 2.705 c
+26.965 2.705 26.829 2.753 26.723 2.851 c
+26.623 2.958 26.576 3.094 26.576 3.263 c
+30.426 1.22 m
+30.089 1.249 l
+29.802 1.249 29.611 1.124 29.516 0.881 c
+29.516 -1.75 l
+28.471 -1.75 l
+28.471 2.234 l
+29.441 2.234 l
+29.471 1.793 l
+29.637 2.135 29.868 2.308 30.162 2.308 c
+30.28 2.308 30.372 2.285 30.441 2.248 c
+h
+32.499 -1.823 m
+31.97 -1.823 31.551 -1.669 31.249 -1.353 c
+30.956 -1.029 30.809 -0.57 30.809 0.029 c
+30.809 0.338 l
+30.809 0.962 30.945 1.448 31.22 1.793 c
+31.492 2.135 31.885 2.308 32.396 2.308 c
+32.896 2.308 33.267 2.146 33.514 1.822 c
+33.767 1.5 33.9 1.022 33.91 0.397 c
+33.91 -0.103 l
+31.837 -0.103 l
+31.856 -0.397 31.918 -0.614 32.028 -0.75 c
+32.147 -0.89 32.327 -0.956 32.573 -0.956 c
+32.915 -0.956 33.204 -0.838 33.44 -0.603 c
+33.852 -1.235 l
+33.723 -1.411 33.535 -1.555 33.293 -1.661 c
+33.047 -1.768 32.782 -1.823 32.499 -1.823 c
+31.853 0.617 m
+32.882 0.617 l
+32.882 0.72 l
+32.882 0.955 32.841 1.132 32.764 1.249 c
+32.694 1.374 32.566 1.44 32.382 1.44 c
+32.205 1.44 32.073 1.371 31.985 1.234 c
+31.904 1.106 31.86 0.9 31.853 0.617 c
+35.939 -0.956 m
+36.233 -0.956 36.383 -0.761 36.394 -0.368 c
+37.364 -0.368 l
+37.364 -0.802 37.233 -1.154 36.967 -1.426 c
+36.703 -1.69 36.365 -1.823 35.953 -1.823 c
+35.442 -1.823 35.049 -1.669 34.777 -1.353 c
+34.513 -1.029 34.374 -0.559 34.366 0.058 c
+34.366 0.382 l
+34.366 1.007 34.499 1.484 34.763 1.808 c
+35.035 2.138 35.432 2.308 35.953 2.308 c
+36.383 2.308 36.726 2.167 36.982 1.896 c
+37.236 1.62 37.364 1.238 37.364 0.75 c
+36.394 0.75 l
+36.394 0.962 36.354 1.132 36.277 1.249 c
+36.207 1.374 36.09 1.44 35.924 1.44 c
+35.748 1.44 35.619 1.374 35.542 1.249 c
+35.461 1.12 35.417 0.871 35.409 0.5 c
+35.409 0.088 l
+35.409 -0.235 35.424 -0.463 35.454 -0.588 c
+35.49 -0.717 35.546 -0.809 35.615 -0.867 c
+35.693 -0.927 35.799 -0.956 35.939 -0.956 c
+39.172 3.204 m
+39.172 2.234 l
+39.702 2.234 l
+39.702 1.44 l
+39.172 1.44 l
+39.172 -0.53 l
+39.172 -0.688 39.191 -0.794 39.232 -0.852 c
+39.28 -0.912 39.363 -0.941 39.481 -0.941 c
+39.588 -0.941 39.673 -0.933 39.731 -0.912 c
+39.731 -1.72 l
+39.554 -1.786 39.363 -1.823 39.158 -1.823 c
+38.482 -1.823 38.137 -1.437 38.129 -0.661 c
+38.129 1.44 l
+37.673 1.44 l
+37.673 2.234 l
+38.129 2.234 l
+38.129 3.204 l
+h
+40.055 0.367 m
+40.055 0.974 40.194 1.448 40.481 1.793 c
+40.764 2.135 41.157 2.308 41.657 2.308 c
+42.164 2.308 42.561 2.135 42.847 1.793 c
+43.13 1.448 43.274 0.974 43.274 0.367 c
+43.274 0.103 l
+43.274 -0.497 43.13 -0.967 42.847 -1.309 c
+42.561 -1.654 42.164 -1.823 41.657 -1.823 c
+41.146 -1.823 40.749 -1.654 40.466 -1.309 c
+40.19 -0.967 40.055 -0.493 40.055 0.118 c
+h
+41.098 0.103 m
+41.098 -0.603 41.282 -0.956 41.657 -0.956 c
+42.01 -0.956 42.201 -0.661 42.23 -0.073 c
+42.23 0.367 l
+42.23 0.727 42.179 0.999 42.083 1.176 c
+41.984 1.352 41.84 1.44 41.657 1.44 c
+41.48 1.44 41.341 1.352 41.245 1.176 c
+41.146 0.999 41.098 0.727 41.098 0.367 c
+h
+45.875 1.22 m
+45.537 1.249 l
+45.251 1.249 45.06 1.124 44.964 0.881 c
+44.964 -1.75 l
+43.92 -1.75 l
+43.92 2.234 l
+44.89 2.234 l
+44.92 1.793 l
+45.085 2.135 45.317 2.308 45.611 2.308 c
+45.728 2.308 45.821 2.285 45.89 2.248 c
+h
+47.772 -0.015 m
+48.3 2.234 l
+49.403 2.234 l
+48.095 -2.352 l
+47.897 -3.017 47.529 -3.352 46.993 -3.352 c
+46.864 -3.352 46.721 -3.329 46.567 -3.293 c
+46.567 -2.469 l
+46.684 -2.484 l
+46.849 -2.484 46.97 -2.448 47.051 -2.381 c
+47.128 -2.323 47.191 -2.213 47.242 -2.058 c
+47.315 -1.793 l
+46.17 2.234 l
+47.286 2.234 l
+h
+f
+Q
+q 1 0 0 1 422.1464 304.7979 cm
+0 0 m
+0 0.118 0.033 0.214 0.103 0.294 c
+0.169 0.372 0.272 0.412 0.411 0.412 c
+0.559 0.412 0.665 0.372 0.735 0.294 c
+0.812 0.214 0.852 0.118 0.852 0 c
+0.852 -0.11 0.812 -0.201 0.735 -0.278 c
+0.665 -0.357 0.559 -0.396 0.411 -0.396 c
+0.272 -0.396 0.169 -0.357 0.103 -0.278 c
+0.033 -0.201 0 -0.11 0 0 c
+6.732 4.425 m
+5.321 4.425 l
+5.321 -0.353 l
+4.659 -0.353 l
+4.659 4.425 l
+3.248 4.425 l
+3.248 4.998 l
+6.732 4.998 l
+h
+8.085 3.219 m
+8.338 3.543 8.658 3.705 9.04 3.705 c
+9.745 3.705 10.102 3.234 10.113 2.294 c
+10.113 -0.353 l
+9.466 -0.353 l
+9.466 2.264 l
+9.466 2.577 9.411 2.797 9.304 2.926 c
+9.194 3.051 9.04 3.117 8.834 3.117 c
+8.676 3.117 8.529 3.061 8.393 2.955 c
+8.264 2.845 8.162 2.708 8.085 2.544 c
+8.085 -0.353 l
+7.437 -0.353 l
+7.437 5.292 l
+8.085 5.292 l
+h
+11.774 -0.353 -0.647 3.984 re
+11.818 4.675 m
+11.818 4.564 11.788 4.472 11.73 4.395 c
+11.671 4.326 11.576 4.293 11.451 4.293 c
+11.333 4.293 11.237 4.326 11.171 4.395 c
+11.112 4.472 11.083 4.564 11.083 4.675 c
+11.083 4.792 11.112 4.884 11.171 4.954 c
+11.237 5.031 11.333 5.072 11.451 5.072 c
+11.576 5.072 11.671 5.031 11.73 4.954 c
+11.788 4.873 11.818 4.781 11.818 4.675 c
+14.728 0.662 m
+14.728 0.809 14.674 0.93 14.566 1.029 c
+14.456 1.125 14.25 1.243 13.949 1.382 c
+13.604 1.529 13.361 1.65 13.215 1.75 c
+13.067 1.856 12.957 1.974 12.891 2.103 c
+12.821 2.228 12.788 2.386 12.788 2.573 c
+12.788 2.897 12.906 3.165 13.141 3.381 c
+13.376 3.595 13.677 3.705 14.052 3.705 c
+14.435 3.705 14.743 3.591 14.978 3.367 c
+15.214 3.138 15.331 2.852 15.331 2.5 c
+14.684 2.5 l
+14.684 2.675 14.626 2.826 14.508 2.955 c
+14.39 3.08 14.236 3.146 14.052 3.146 c
+13.853 3.146 13.703 3.091 13.596 2.984 c
+13.486 2.885 13.435 2.753 13.435 2.587 c
+13.435 2.459 13.471 2.352 13.552 2.264 c
+13.629 2.183 13.82 2.08 14.126 1.956 c
+14.603 1.768 14.934 1.58 15.11 1.397 c
+15.287 1.22 15.375 0.992 15.375 0.721 c
+15.375 0.368 15.25 0.088 15.008 -0.118 c
+14.772 -0.323 14.456 -0.426 14.067 -0.426 c
+13.644 -0.426 13.306 -0.309 13.053 -0.073 c
+12.795 0.169 12.671 0.474 12.671 0.838 c
+13.317 0.838 l
+13.325 0.611 13.394 0.434 13.523 0.31 c
+13.648 0.192 13.832 0.133 14.067 0.133 c
+14.28 0.133 14.441 0.181 14.552 0.279 c
+14.67 0.375 14.728 0.504 14.728 0.662 c
+17.801 1.823 m
+17.801 2.4 17.936 2.856 18.212 3.19 c
+18.495 3.532 18.867 3.705 19.329 3.705 c
+19.788 3.705 20.156 3.535 20.432 3.205 c
+20.714 2.882 20.862 2.433 20.872 1.867 c
+20.872 1.441 l
+20.872 0.871 20.729 0.416 20.446 0.074 c
+20.17 -0.261 19.803 -0.426 19.343 -0.426 c
+18.881 -0.426 18.51 -0.264 18.227 0.059 c
+17.951 0.389 17.808 0.831 17.801 1.382 c
+h
+18.447 1.441 m
+18.447 1.037 18.524 0.721 18.682 0.485 c
+18.848 0.25 19.068 0.133 19.343 0.133 c
+19.91 0.133 20.203 0.545 20.226 1.368 c
+20.226 1.823 l
+20.226 2.224 20.141 2.544 19.976 2.779 c
+19.818 3.021 19.601 3.146 19.329 3.146 c
+19.065 3.146 18.848 3.021 18.682 2.779 c
+18.524 2.544 18.447 2.224 18.447 1.823 c
+h
+24.591 1.441 m
+24.591 0.813 24.474 0.342 24.239 0.03 c
+24.01 -0.276 23.694 -0.426 23.283 -0.426 c
+22.879 -0.426 22.57 -0.276 22.358 0.03 c
+22.358 -1.881 l
+21.71 -1.881 l
+21.71 3.631 l
+22.298 3.631 l
+22.343 3.19 l
+22.555 3.532 22.865 3.705 23.268 3.705 c
+23.709 3.705 24.037 3.55 24.253 3.249 c
+24.467 2.944 24.581 2.488 24.591 1.881 c
+h
+23.945 1.823 m
+23.945 2.264 23.875 2.587 23.739 2.793 c
+23.599 3.007 23.378 3.117 23.077 3.117 c
+22.761 3.117 22.522 2.962 22.358 2.661 c
+22.358 0.588 l
+22.522 0.283 22.761 0.133 23.077 0.133 c
+23.372 0.133 23.584 0.235 23.724 0.441 c
+23.86 0.655 23.933 0.985 23.945 1.426 c
+h
+26.855 -0.426 m
+26.356 -0.426 25.973 -0.278 25.709 0.015 c
+25.444 0.31 25.312 0.742 25.312 1.324 c
+25.312 1.794 l
+25.312 2.389 25.437 2.856 25.693 3.19 c
+25.959 3.532 26.318 3.705 26.782 3.705 c
+27.241 3.705 27.582 3.55 27.81 3.249 c
+28.045 2.955 28.167 2.492 28.178 1.867 c
+28.178 1.441 l
+25.959 1.441 l
+25.959 1.353 l
+25.959 0.919 26.036 0.607 26.194 0.412 c
+26.359 0.225 26.591 0.133 26.884 0.133 c
+27.079 0.133 27.252 0.166 27.399 0.235 c
+27.546 0.312 27.682 0.43 27.81 0.588 c
+28.149 0.177 l
+27.862 -0.228 27.432 -0.426 26.855 -0.426 c
+26.782 3.146 m
+26.506 3.146 26.304 3.051 26.179 2.866 c
+26.05 2.679 25.977 2.389 25.959 1.999 c
+27.532 1.999 l
+27.532 2.088 l
+27.509 2.469 27.443 2.738 27.326 2.897 c
+27.208 3.061 27.024 3.146 26.782 3.146 c
+30.603 3.014 m
+30.515 3.032 30.416 3.043 30.31 3.043 c
+29.975 3.043 29.74 2.859 29.604 2.5 c
+29.604 -0.353 l
+28.957 -0.353 l
+28.957 3.631 l
+29.589 3.631 l
+29.604 3.219 l
+29.78 3.543 30.023 3.705 30.339 3.705 c
+30.445 3.705 30.534 3.682 30.603 3.645 c
+h
+33.146 -0.353 m
+33.106 -0.264 33.08 -0.118 33.073 0.088 c
+32.837 -0.257 32.544 -0.426 32.191 -0.426 c
+31.827 -0.426 31.544 -0.33 31.338 -0.132 c
+31.139 0.074 31.044 0.36 31.044 0.736 c
+31.044 1.135 31.18 1.455 31.456 1.691 c
+31.727 1.933 32.103 2.058 32.573 2.058 c
+33.058 2.058 l
+33.058 2.485 l
+33.058 2.72 33.003 2.885 32.897 2.984 c
+32.786 3.091 32.625 3.146 32.411 3.146 c
+32.213 3.146 32.051 3.088 31.926 2.97 c
+31.808 2.852 31.75 2.705 31.75 2.529 c
+31.103 2.529 l
+31.103 2.723 31.162 2.914 31.28 3.102 c
+31.405 3.286 31.566 3.433 31.765 3.543 c
+31.97 3.649 32.198 3.705 32.456 3.705 c
+32.856 3.705 33.161 3.602 33.367 3.396 c
+33.58 3.19 33.694 2.897 33.705 2.514 c
+33.705 0.5 l
+33.705 0.195 33.741 -0.07 33.822 -0.293 c
+33.822 -0.353 l
+h
+32.279 0.162 m
+32.444 0.162 32.595 0.206 32.735 0.294 c
+32.882 0.383 32.988 0.493 33.058 0.632 c
+33.058 1.573 l
+32.691 1.573 l
+32.375 1.573 32.132 1.503 31.956 1.368 c
+31.779 1.239 31.691 1.052 31.691 0.809 c
+31.691 0.581 31.735 0.416 31.823 0.31 c
+31.912 0.21 32.062 0.162 32.279 0.162 c
+35.557 4.586 m
+35.557 3.631 l
+36.159 3.631 l
+36.159 3.102 l
+35.557 3.102 l
+35.557 0.632 l
+35.557 0.474 35.579 0.357 35.63 0.279 c
+35.689 0.198 35.777 0.162 35.895 0.162 c
+35.983 0.162 36.072 0.177 36.159 0.206 c
+36.159 -0.353 l
+36.012 -0.4 35.858 -0.426 35.704 -0.426 c
+35.447 -0.426 35.252 -0.334 35.116 -0.147 c
+34.977 0.037 34.91 0.298 34.91 0.632 c
+34.91 3.102 l
+34.308 3.102 l
+34.308 3.631 l
+34.91 3.631 l
+34.91 4.586 l
+h
+37.63 -0.353 -0.647 3.984 re
+37.674 4.675 m
+37.674 4.564 37.645 4.472 37.585 4.395 c
+37.526 4.326 37.431 4.293 37.306 4.293 c
+37.188 4.293 37.093 4.326 37.027 4.395 c
+36.968 4.472 36.939 4.564 36.939 4.675 c
+36.939 4.792 36.968 4.884 37.027 4.954 c
+37.093 5.031 37.188 5.072 37.306 5.072 c
+37.431 5.072 37.526 5.031 37.585 4.954 c
+37.645 4.873 37.674 4.781 37.674 4.675 c
+38.511 1.823 m
+38.511 2.4 38.647 2.856 38.923 3.19 c
+39.206 3.532 39.577 3.705 40.04 3.705 c
+40.5 3.705 40.867 3.535 41.142 3.205 c
+41.425 2.882 41.572 2.433 41.583 1.867 c
+41.583 1.441 l
+41.583 0.871 41.44 0.416 41.157 0.074 c
+40.882 -0.261 40.514 -0.426 40.055 -0.426 c
+39.592 -0.426 39.22 -0.264 38.937 0.059 c
+38.663 0.389 38.519 0.831 38.511 1.382 c
+h
+39.158 1.441 m
+39.158 1.037 39.235 0.721 39.393 0.485 c
+39.559 0.25 39.779 0.133 40.055 0.133 c
+40.621 0.133 40.915 0.545 40.937 1.368 c
+40.937 1.823 l
+40.937 2.224 40.853 2.544 40.687 2.779 c
+40.529 3.021 40.312 3.146 40.04 3.146 c
+39.775 3.146 39.559 3.021 39.393 2.779 c
+39.235 2.544 39.158 2.224 39.158 1.823 c
+h
+43.039 3.631 m
+43.054 3.19 l
+43.307 3.532 43.631 3.705 44.024 3.705 c
+44.729 3.705 45.086 3.234 45.096 2.294 c
+45.096 -0.353 l
+44.45 -0.353 l
+44.45 2.264 l
+44.45 2.577 44.394 2.797 44.288 2.926 c
+44.178 3.051 44.024 3.117 43.818 3.117 c
+43.66 3.117 43.513 3.061 43.377 2.955 c
+43.249 2.845 43.145 2.708 43.068 2.544 c
+43.068 -0.353 l
+42.422 -0.353 l
+42.422 3.631 l
+h
+f
+Q
+470.639 304.445 -0.647 3.984 re
+470.683 309.472 m
+470.683 309.362 470.653 309.27 470.594 309.193 c
+470.535 309.123 470.44 309.09 470.315 309.09 c
+470.197 309.09 470.102 309.123 470.036 309.193 c
+469.977 309.27 469.947 309.362 469.947 309.472 c
+469.947 309.59 469.977 309.682 470.036 309.752 c
+470.102 309.829 470.197 309.869 470.315 309.869 c
+470.44 309.869 470.535 309.829 470.594 309.752 c
+470.653 309.671 470.683 309.579 470.683 309.472 c
+473.593 305.46 m
+473.593 305.607 473.538 305.728 473.432 305.827 c
+473.321 305.923 473.116 306.041 472.814 306.18 c
+472.468 306.327 472.226 306.448 472.079 306.548 c
+471.932 306.654 471.822 306.772 471.755 306.9 c
+471.686 307.026 471.653 307.184 471.653 307.371 c
+471.653 307.694 471.77 307.963 472.006 308.179 c
+472.241 308.392 472.542 308.503 472.917 308.503 c
+473.299 308.503 473.608 308.389 473.843 308.165 c
+474.078 307.936 474.196 307.65 474.196 307.297 c
+473.548 307.297 l
+473.548 307.473 473.49 307.624 473.372 307.753 c
+473.255 307.878 473.101 307.944 472.917 307.944 c
+472.719 307.944 472.568 307.889 472.461 307.782 c
+472.351 307.683 472.299 307.55 472.299 307.385 c
+472.299 307.257 472.336 307.15 472.417 307.062 c
+472.494 306.981 472.686 306.878 472.991 306.754 c
+473.468 306.565 473.799 306.378 473.975 306.195 c
+474.151 306.018 474.24 305.79 474.24 305.518 c
+474.24 305.166 474.115 304.886 473.872 304.68 c
+473.637 304.475 473.321 304.372 472.931 304.372 c
+472.509 304.372 472.171 304.489 471.917 304.724 c
+471.66 304.967 471.535 305.272 471.535 305.636 c
+472.182 305.636 l
+472.189 305.408 472.259 305.232 472.388 305.107 c
+472.513 304.99 472.696 304.931 472.931 304.931 c
+473.145 304.931 473.307 304.978 473.417 305.077 c
+473.534 305.173 473.593 305.302 473.593 305.46 c
+f
+q 1 0 0 1 478.6491 304.8129 cm
+0 0 m
+-0.216 -0.294 -0.507 -0.441 -0.867 -0.441 c
+-1.23 -0.441 -1.51 -0.32 -1.705 -0.073 c
+-1.892 0.18 -1.984 0.548 -1.984 1.029 c
+-1.984 3.616 l
+-0.941 3.616 l
+-0.941 1.014 l
+-0.941 0.621 -0.816 0.426 -0.558 0.426 c
+-0.323 0.426 -0.154 0.53 -0.043 0.735 c
+-0.043 3.616 l
+1 3.616 l
+1 -0.368 l
+0.03 -0.368 l
+h
+2.705 3.616 m
+2.735 3.219 l
+2.97 3.532 3.271 3.69 3.645 3.69 c
+4.329 3.69 4.682 3.208 4.704 2.249 c
+4.704 -0.368 l
+3.66 -0.368 l
+3.66 2.176 l
+3.66 2.4 3.624 2.562 3.558 2.66 c
+3.487 2.756 3.37 2.807 3.205 2.807 c
+3.017 2.807 2.87 2.712 2.764 2.529 c
+2.764 -0.368 l
+1.72 -0.368 l
+1.72 3.616 l
+h
+7.408 2.602 m
+7.071 2.631 l
+6.784 2.631 6.593 2.506 6.498 2.263 c
+6.498 -0.368 l
+5.453 -0.368 l
+5.453 3.616 l
+6.423 3.616 l
+6.453 3.175 l
+6.619 3.516 6.85 3.69 7.144 3.69 c
+7.262 3.69 7.354 3.667 7.423 3.63 c
+h
+9.481 -0.441 m
+8.952 -0.441 8.533 -0.287 8.231 0.029 c
+7.938 0.353 7.791 0.812 7.791 1.411 c
+7.791 1.72 l
+7.791 2.344 7.927 2.83 8.202 3.175 c
+8.474 3.516 8.867 3.69 9.378 3.69 c
+9.878 3.69 10.249 3.528 10.496 3.204 c
+10.749 2.881 10.882 2.404 10.892 1.779 c
+10.892 1.278 l
+8.819 1.278 l
+8.838 0.985 8.9 0.768 9.01 0.632 c
+9.129 0.492 9.309 0.426 9.555 0.426 c
+9.897 0.426 10.186 0.544 10.422 0.779 c
+10.834 0.147 l
+10.705 -0.029 10.517 -0.173 10.275 -0.279 c
+10.029 -0.386 9.764 -0.441 9.481 -0.441 c
+8.834 1.999 m
+9.864 1.999 l
+9.864 2.102 l
+9.864 2.337 9.823 2.514 9.746 2.631 c
+9.676 2.756 9.548 2.822 9.364 2.822 c
+9.187 2.822 9.055 2.753 8.967 2.616 c
+8.886 2.488 8.842 2.282 8.834 1.999 c
+12.921 0.426 m
+13.215 0.426 13.365 0.621 13.376 1.014 c
+14.346 1.014 l
+14.346 0.58 14.215 0.228 13.949 -0.044 c
+13.685 -0.309 13.347 -0.441 12.935 -0.441 c
+12.424 -0.441 12.031 -0.287 11.759 0.029 c
+11.495 0.353 11.356 0.823 11.348 1.44 c
+11.348 1.764 l
+11.348 2.389 11.481 2.866 11.745 3.19 c
+12.017 3.52 12.414 3.69 12.935 3.69 c
+13.365 3.69 13.708 3.549 13.964 3.278 c
+14.218 3.002 14.346 2.62 14.346 2.132 c
+13.376 2.132 l
+13.376 2.344 13.336 2.514 13.259 2.631 c
+13.189 2.756 13.072 2.822 12.906 2.822 c
+12.73 2.822 12.601 2.756 12.524 2.631 c
+12.443 2.502 12.399 2.253 12.391 1.881 c
+12.391 1.47 l
+12.391 1.147 12.406 0.919 12.436 0.794 c
+12.472 0.665 12.528 0.573 12.597 0.515 c
+12.675 0.455 12.781 0.426 12.921 0.426 c
+14.832 1.749 m
+14.832 2.356 14.971 2.83 15.258 3.175 c
+15.541 3.516 15.934 3.69 16.434 3.69 c
+16.941 3.69 17.338 3.516 17.625 3.175 c
+17.908 2.83 18.051 2.356 18.051 1.749 c
+18.051 1.484 l
+18.051 0.885 17.908 0.415 17.625 0.073 c
+17.338 -0.272 16.941 -0.441 16.434 -0.441 c
+15.923 -0.441 15.526 -0.272 15.244 0.073 c
+14.968 0.415 14.832 0.889 14.832 1.5 c
+h
+15.875 1.484 m
+15.875 0.779 16.059 0.426 16.434 0.426 c
+16.787 0.426 16.978 0.721 17.007 1.309 c
+17.007 1.749 l
+17.007 2.109 16.956 2.381 16.86 2.558 c
+16.761 2.734 16.617 2.822 16.434 2.822 c
+16.258 2.822 16.118 2.734 16.023 2.558 c
+15.923 2.381 15.875 2.109 15.875 1.749 c
+h
+19.947 1.103 m
+20.447 3.616 l
+21.534 3.616 l
+20.432 -0.368 l
+19.447 -0.368 l
+18.344 3.616 l
+19.433 3.616 l
+h
+23.578 -0.441 m
+23.048 -0.441 22.629 -0.287 22.328 0.029 c
+22.034 0.353 21.887 0.812 21.887 1.411 c
+21.887 1.72 l
+21.887 2.344 22.024 2.83 22.299 3.175 c
+22.571 3.516 22.964 3.69 23.475 3.69 c
+23.975 3.69 24.345 3.528 24.592 3.204 c
+24.846 2.881 24.978 2.404 24.989 1.779 c
+24.989 1.278 l
+22.916 1.278 l
+22.934 0.985 22.997 0.768 23.107 0.632 c
+23.225 0.492 23.405 0.426 23.651 0.426 c
+23.993 0.426 24.283 0.544 24.518 0.779 c
+24.93 0.147 l
+24.802 -0.029 24.614 -0.173 24.372 -0.279 c
+24.125 -0.386 23.861 -0.441 23.578 -0.441 c
+22.931 1.999 m
+23.96 1.999 l
+23.96 2.102 l
+23.96 2.337 23.919 2.514 23.842 2.631 c
+23.773 2.756 23.644 2.822 23.46 2.822 c
+23.283 2.822 23.152 2.753 23.063 2.616 c
+22.982 2.488 22.938 2.282 22.931 1.999 c
+27.532 2.602 m
+27.194 2.631 l
+26.907 2.631 26.716 2.506 26.62 2.263 c
+26.62 -0.368 l
+25.577 -0.368 l
+25.577 3.616 l
+26.547 3.616 l
+26.576 3.175 l
+26.741 3.516 26.973 3.69 27.267 3.69 c
+27.385 3.69 27.476 3.667 27.547 3.63 c
+h
+29.854 -0.368 m
+29.825 -0.309 29.795 -0.206 29.766 -0.058 c
+29.579 -0.316 29.328 -0.441 29.016 -0.441 c
+28.682 -0.441 28.403 -0.334 28.179 -0.118 c
+27.962 0.106 27.855 0.397 27.855 0.75 c
+27.855 1.161 27.987 1.477 28.252 1.706 c
+28.517 1.941 28.899 2.058 29.398 2.058 c
+29.722 2.058 l
+29.722 2.381 l
+29.722 2.558 29.685 2.679 29.619 2.749 c
+29.56 2.826 29.471 2.866 29.355 2.866 c
+29.097 2.866 28.972 2.712 28.972 2.411 c
+27.929 2.411 l
+27.929 2.782 28.064 3.087 28.34 3.322 c
+28.612 3.564 28.962 3.69 29.384 3.69 c
+29.825 3.69 30.163 3.572 30.398 3.337 c
+30.641 3.109 30.766 2.786 30.766 2.367 c
+30.766 0.5 l
+30.766 0.154 30.813 -0.114 30.913 -0.309 c
+30.913 -0.368 l
+h
+29.251 0.382 m
+29.358 0.382 29.45 0.401 29.531 0.441 c
+29.619 0.489 29.681 0.548 29.722 0.617 c
+29.722 1.44 l
+29.471 1.44 l
+29.296 1.44 29.153 1.382 29.045 1.264 c
+28.947 1.154 28.899 1.007 28.899 0.823 c
+28.899 0.53 29.016 0.382 29.251 0.382 c
+34.616 1.5 m
+34.616 0.852 34.514 0.368 34.308 0.044 c
+34.102 -0.279 33.779 -0.441 33.338 -0.441 c
+32.993 -0.441 32.713 -0.287 32.5 0.029 c
+32.471 -0.368 l
+31.515 -0.368 l
+31.515 5.277 l
+32.559 5.277 l
+32.559 3.293 l
+32.754 3.557 33.007 3.69 33.323 3.69 c
+33.764 3.69 34.088 3.528 34.294 3.204 c
+34.499 2.881 34.606 2.411 34.616 1.793 c
+h
+33.573 1.749 m
+33.573 2.168 33.533 2.448 33.456 2.587 c
+33.375 2.734 33.234 2.807 33.029 2.807 c
+32.812 2.807 32.654 2.708 32.559 2.514 c
+32.559 0.706 l
+32.647 0.518 32.808 0.426 33.043 0.426 c
+33.238 0.426 33.375 0.489 33.456 0.617 c
+33.533 0.742 33.573 1 33.573 1.382 c
+h
+36.336 -0.368 -1.043 5.644 re
+38.747 -0.441 m
+38.218 -0.441 37.799 -0.287 37.498 0.029 c
+37.203 0.353 37.057 0.812 37.057 1.411 c
+37.057 1.72 l
+37.057 2.344 37.193 2.83 37.468 3.175 c
+37.741 3.516 38.134 3.69 38.644 3.69 c
+39.144 3.69 39.515 3.528 39.761 3.204 c
+40.015 2.881 40.147 2.404 40.158 1.779 c
+40.158 1.278 l
+38.086 1.278 l
+38.104 0.985 38.167 0.768 38.277 0.632 c
+38.394 0.492 38.574 0.426 38.821 0.426 c
+39.162 0.426 39.453 0.544 39.688 0.779 c
+40.099 0.147 l
+39.971 -0.029 39.783 -0.173 39.541 -0.279 c
+39.295 -0.386 39.03 -0.441 38.747 -0.441 c
+38.1 1.999 m
+39.129 1.999 l
+39.129 2.102 l
+39.129 2.337 39.089 2.514 39.012 2.631 c
+38.942 2.756 38.813 2.822 38.63 2.822 c
+38.453 2.822 38.321 2.753 38.233 2.616 c
+38.152 2.488 38.107 2.282 38.1 1.999 c
+f
+Q
+q 1 0 0 1 519.5421 304.7979 cm
+0 0 m
+0 0.118 0.033 0.214 0.103 0.294 c
+0.169 0.372 0.272 0.412 0.412 0.412 c
+0.559 0.412 0.665 0.372 0.735 0.294 c
+0.812 0.214 0.852 0.118 0.852 0 c
+0.852 -0.11 0.812 -0.201 0.735 -0.278 c
+0.665 -0.357 0.559 -0.396 0.412 -0.396 c
+0.272 -0.396 0.169 -0.357 0.103 -0.278 c
+0.033 -0.201 0 -0.11 0 0 c
+f
+Q
+0.113 0.082 0.09 0 k
+287.665 298.837 234.667 -12.895 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 292.0029 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.647 -0.243 -0.775 -0.367 -0.882 c
+-0.496 -0.992 -0.658 -1.081 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.162 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.927 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.132 l
+-2.642 0.033 -2.616 -0.059 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.683 -1.992 0.69 -1.999 0.69 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.881 -2.786 0.959 -2.91 1.058 c
+-3.039 1.153 -3.142 1.278 -3.219 1.425 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.836 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.119 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.119 -1.128 3.09 -0.97 3.042 c
+-0.804 2.992 -0.669 2.917 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.252 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.352 c
+-1.294 1.311 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.319 2.385 -2.366 2.337 c
+-2.406 2.296 -2.436 2.248 -2.454 2.19 c
+-2.477 2.131 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.778 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.469 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.091 -0.86 0.176 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.529 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.53 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.66 m
+6.184 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.22 5.108 -2.103 c
+5.039 -1.985 4.991 -1.856 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.86 6.064 -1.941 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.058 6.681 -2.028 c
+6.758 -1.999 6.828 -1.945 6.887 -1.867 c
+6.945 -1.797 6.99 -1.706 7.019 -1.588 c
+7.056 -1.47 7.078 -1.323 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.073 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.412 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.234 c
+4.946 1.448 5.027 1.631 5.137 1.778 c
+5.244 1.933 5.376 2.051 5.534 2.131 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.252 6.387 2.234 c
+6.483 2.212 6.571 2.179 6.652 2.131 c
+6.739 2.08 6.817 2.017 6.887 1.94 c
+6.964 1.859 7.026 1.768 7.078 1.66 c
+7.092 1.66 l
+7.092 1.808 l
+7.1 1.866 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.151 2.219 c
+8.004 2.219 l
+7.993 2.138 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.162 l
+7.975 -1.415 7.938 -1.635 7.871 -1.823 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.529 m
+7.092 0.742 7.067 0.918 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.587 c
+6.571 1.624 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.62 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.339 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.177 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.529 c
+11.036 -0.647 m
+12.168 -0.647 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.647 l
+10.124 -0.647 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.676 re
+10.124 2.836 m
+13.597 1.602 m
+13.053 1.602 l
+13.053 2.219 l
+13.641 2.219 l
+13.92 3.116 l
+14.494 3.116 l
+14.494 2.219 l
+15.728 2.219 l
+15.728 1.602 l
+14.494 1.602 l
+14.494 -0.103 l
+14.494 -0.324 l
+14.501 -0.393 14.523 -0.456 14.552 -0.515 c
+14.589 -0.566 14.645 -0.611 14.714 -0.647 c
+14.791 -0.676 14.905 -0.691 15.052 -0.691 c
+15.188 -0.691 15.324 -0.688 15.464 -0.676 c
+15.599 -0.658 15.732 -0.632 15.861 -0.603 c
+15.861 -1.205 l
+15.78 -1.216 15.703 -1.231 15.626 -1.249 c
+15.545 -1.261 15.468 -1.268 15.391 -1.279 c
+15.31 -1.286 15.221 -1.294 15.125 -1.294 c
+15.038 -1.301 14.938 -1.309 14.832 -1.309 c
+14.645 -1.309 14.483 -1.294 14.346 -1.264 c
+14.218 -1.228 14.104 -1.183 14.009 -1.132 c
+13.92 -1.085 13.847 -1.025 13.788 -0.956 c
+13.729 -0.879 13.685 -0.802 13.656 -0.721 c
+13.627 -0.632 13.604 -0.544 13.597 -0.456 c
+13.586 -0.36 13.582 -0.264 13.582 -0.177 c
+h
+22.074 -1.323 m
+21.905 -1.323 21.755 -1.301 21.619 -1.264 c
+21.49 -1.216 21.376 -1.147 21.28 -1.058 c
+21.193 -0.97 21.122 -0.864 21.075 -0.735 c
+21.024 -0.599 21.001 -0.449 21.001 -0.279 c
+21.001 -0.073 21.035 0.095 21.105 0.235 c
+21.17 0.382 21.266 0.492 21.384 0.573 c
+21.509 0.661 21.652 0.723 21.81 0.764 c
+21.976 0.801 22.152 0.827 22.339 0.837 c
+23.059 0.852 l
+23.059 1.029 l
+23.059 1.147 23.048 1.249 23.03 1.338 c
+23.008 1.425 22.975 1.492 22.927 1.543 c
+22.886 1.602 22.839 1.639 22.78 1.66 c
+22.722 1.679 22.655 1.691 22.589 1.691 c
+22.519 1.691 22.456 1.679 22.398 1.66 c
+22.346 1.65 22.298 1.624 22.251 1.587 c
+22.211 1.558 22.177 1.506 22.148 1.44 c
+22.126 1.382 22.111 1.301 22.104 1.205 c
+21.163 1.249 l
+21.193 1.396 21.236 1.532 21.296 1.66 c
+21.361 1.786 21.457 1.896 21.575 1.984 c
+21.693 2.08 21.832 2.153 22.001 2.205 c
+22.177 2.252 22.383 2.278 22.618 2.278 c
+23.059 2.278 23.391 2.168 23.618 1.955 c
+23.853 1.749 23.971 1.44 23.971 1.029 c
+23.971 -0.235 l
+23.971 -0.456 l
+23.979 -0.515 23.993 -0.57 24.015 -0.617 c
+24.033 -0.658 24.062 -0.691 24.103 -0.721 c
+24.139 -0.742 24.191 -0.75 24.25 -0.75 c
+24.316 -0.75 24.386 -0.746 24.455 -0.735 c
+24.455 -1.22 l
+24.397 -1.231 24.342 -1.242 24.294 -1.249 c
+24.254 -1.261 24.214 -1.268 24.177 -1.279 c
+24.137 -1.286 24.092 -1.294 24.044 -1.294 c
+23.993 -1.301 23.934 -1.309 23.868 -1.309 c
+23.64 -1.309 23.474 -1.257 23.368 -1.147 c
+23.258 -1.029 23.196 -0.864 23.177 -0.647 c
+23.162 -0.647 l
+23.092 -0.757 23.023 -0.852 22.957 -0.941 c
+22.886 -1.022 22.809 -1.087 22.722 -1.147 c
+22.633 -1.205 22.534 -1.249 22.427 -1.279 c
+22.328 -1.309 22.211 -1.323 22.074 -1.323 c
+23.059 0.353 m
+22.633 0.338 l
+22.534 0.338 22.442 0.33 22.354 0.324 c
+22.273 0.312 22.207 0.287 22.148 0.249 c
+22.09 0.209 22.038 0.151 22.001 0.073 c
+21.961 0.004 21.942 -0.088 21.942 -0.206 c
+21.942 -0.375 21.976 -0.497 22.045 -0.574 c
+22.111 -0.654 22.211 -0.691 22.339 -0.691 c
+22.446 -0.691 22.545 -0.669 22.633 -0.617 c
+22.728 -0.57 22.809 -0.507 22.868 -0.426 c
+22.934 -0.349 22.986 -0.262 23.015 -0.162 c
+23.044 -0.056 23.059 0.058 23.059 0.176 c
+h
+27.355 -1.264 m
+27.344 -1.246 27.333 -1.216 27.326 -1.176 c
+27.326 -1.128 27.318 -1.081 27.312 -1.029 c
+27.312 -0.97 27.304 -0.912 27.297 -0.852 c
+27.297 -0.691 l
+27.179 -0.927 27.036 -1.095 26.87 -1.191 c
+26.701 -1.279 26.503 -1.323 26.267 -1.323 c
+26.069 -1.323 25.893 -1.279 25.739 -1.191 c
+25.581 -1.103 25.448 -0.981 25.342 -0.823 c
+25.242 -0.658 25.165 -0.467 25.106 -0.25 c
+25.055 -0.037 25.033 0.206 25.033 0.47 c
+25.033 0.735 25.055 0.974 25.106 1.19 c
+25.165 1.415 25.242 1.606 25.342 1.764 c
+25.448 1.918 25.581 2.043 25.739 2.131 c
+25.903 2.227 26.095 2.278 26.312 2.278 c
+26.408 2.278 26.503 2.263 26.591 2.234 c
+26.686 2.212 26.782 2.179 26.87 2.131 c
+26.959 2.08 27.036 2.017 27.106 1.94 c
+27.183 1.859 27.245 1.768 27.297 1.66 c
+27.297 1.749 l
+27.297 1.896 l
+27.297 2.057 l
+27.297 2.234 l
+27.297 3.513 l
+28.193 3.513 l
+28.193 -0.5 l
+28.193 -0.676 28.197 -0.834 28.208 -0.97 c
+28.215 -1.099 28.222 -1.199 28.222 -1.264 c
+h
+27.312 0.484 m
+27.312 0.72 27.285 0.912 27.237 1.058 c
+27.197 1.213 27.142 1.338 27.076 1.425 c
+27.017 1.514 26.947 1.573 26.87 1.602 c
+26.789 1.639 26.712 1.66 26.635 1.66 c
+26.535 1.66 26.444 1.635 26.356 1.587 c
+26.275 1.547 26.209 1.477 26.15 1.382 c
+26.098 1.282 26.055 1.161 26.018 1.014 c
+25.988 0.867 25.974 0.683 25.974 0.47 c
+25.974 0.077 26.025 -0.217 26.136 -0.412 c
+26.253 -0.611 26.414 -0.706 26.62 -0.706 c
+26.697 -0.706 26.774 -0.688 26.855 -0.647 c
+26.932 -0.611 27.006 -0.544 27.076 -0.456 c
+27.142 -0.368 27.197 -0.246 27.237 -0.088 c
+27.285 0.066 27.312 0.257 27.312 0.484 c
+31.416 -1.264 m
+31.405 -1.246 31.393 -1.216 31.387 -1.176 c
+31.387 -1.128 31.379 -1.081 31.372 -1.029 c
+31.372 -0.97 31.364 -0.912 31.357 -0.852 c
+31.357 -0.691 l
+31.239 -0.927 31.096 -1.095 30.931 -1.191 c
+30.762 -1.279 30.564 -1.323 30.328 -1.323 c
+30.13 -1.323 29.953 -1.279 29.799 -1.191 c
+29.641 -1.103 29.508 -0.981 29.402 -0.823 c
+29.303 -0.658 29.226 -0.467 29.167 -0.25 c
+29.116 -0.037 29.093 0.206 29.093 0.47 c
+29.093 0.735 29.116 0.974 29.167 1.19 c
+29.226 1.415 29.303 1.606 29.402 1.764 c
+29.508 1.918 29.641 2.043 29.799 2.131 c
+29.964 2.227 30.155 2.278 30.372 2.278 c
+30.468 2.278 30.564 2.263 30.651 2.234 c
+30.747 2.212 30.842 2.179 30.931 2.131 c
+31.019 2.08 31.096 2.017 31.166 1.94 c
+31.243 1.859 31.306 1.768 31.357 1.66 c
+31.357 1.749 l
+31.357 1.896 l
+31.357 2.057 l
+31.357 2.234 l
+31.357 3.513 l
+32.253 3.513 l
+32.253 -0.5 l
+32.253 -0.676 32.257 -0.834 32.268 -0.97 c
+32.276 -1.099 32.283 -1.199 32.283 -1.264 c
+h
+31.372 0.484 m
+31.372 0.72 31.346 0.912 31.298 1.058 c
+31.258 1.213 31.202 1.338 31.137 1.425 c
+31.077 1.514 31.008 1.573 30.931 1.602 c
+30.85 1.639 30.773 1.66 30.695 1.66 c
+30.597 1.66 30.504 1.635 30.416 1.587 c
+30.335 1.547 30.269 1.477 30.211 1.382 c
+30.159 1.282 30.115 1.161 30.078 1.014 c
+30.049 0.867 30.034 0.683 30.034 0.47 c
+30.034 0.077 30.086 -0.217 30.196 -0.412 c
+30.313 -0.611 30.475 -0.706 30.681 -0.706 c
+30.758 -0.706 30.836 -0.688 30.916 -0.647 c
+30.994 -0.611 31.067 -0.544 31.137 -0.456 c
+31.202 -0.368 31.258 -0.246 31.298 -0.088 c
+31.346 0.066 31.372 0.257 31.372 0.484 c
+38.115 -2.631 m
+38.115 3.513 l
+40.041 3.513 l
+40.041 2.896 l
+38.967 2.896 l
+38.967 -2.014 l
+40.041 -2.014 l
+40.041 -2.631 l
+h
+43.072 1.602 m
+43.072 -1.264 l
+42.175 -1.264 l
+42.175 1.602 l
+41.352 1.602 l
+41.352 2.219 l
+42.175 2.219 l
+42.175 2.484 l
+42.175 2.609 42.19 2.741 42.219 2.881 c
+42.256 3.017 42.326 3.135 42.425 3.233 c
+42.532 3.341 42.676 3.428 42.852 3.499 c
+43.028 3.564 43.252 3.601 43.528 3.601 c
+43.741 3.601 43.939 3.59 44.116 3.572 c
+44.292 3.549 44.442 3.532 44.571 3.513 c
+44.571 2.925 l
+44.442 2.944 44.299 2.958 44.145 2.969 c
+43.987 2.977 43.837 2.984 43.69 2.984 c
+43.561 2.984 43.458 2.969 43.381 2.94 c
+43.3 2.911 43.237 2.87 43.189 2.822 c
+43.139 2.77 43.106 2.708 43.087 2.631 c
+43.076 2.561 43.072 2.484 43.072 2.396 c
+43.072 2.219 l
+44.498 2.219 l
+44.498 1.602 l
+h
+47.588 -0.647 m
+48.72 -0.647 l
+48.72 -1.264 l
+45.413 -1.264 l
+45.413 -0.647 l
+46.677 -0.647 l
+46.677 1.602 l
+45.751 1.602 l
+45.751 2.219 l
+47.588 2.219 l
+h
+46.677 3.513 0.912 -0.676 re
+46.677 2.836 m
+51.649 -0.647 m
+52.781 -0.647 l
+52.781 -1.264 l
+49.473 -1.264 l
+49.473 -0.647 l
+50.738 -0.647 l
+50.738 2.896 l
+49.812 2.896 l
+49.812 3.513 l
+51.649 3.513 l
+h
+55.166 -1.323 m
+54.908 -1.323 54.68 -1.286 54.475 -1.22 c
+54.269 -1.143 54.093 -1.029 53.946 -0.882 c
+53.799 -0.728 53.681 -0.536 53.593 -0.309 c
+53.512 -0.085 53.475 0.18 53.475 0.484 c
+53.475 0.816 53.52 1.095 53.608 1.323 c
+53.703 1.558 53.832 1.741 53.99 1.881 c
+54.156 2.017 54.343 2.117 54.549 2.175 c
+54.754 2.242 54.964 2.278 55.181 2.278 c
+55.453 2.278 55.688 2.227 55.887 2.131 c
+56.092 2.043 56.257 1.911 56.386 1.735 c
+56.522 1.565 56.621 1.359 56.68 1.117 c
+56.746 0.881 56.783 0.617 56.783 0.324 c
+56.783 0.309 l
+54.416 0.309 l
+54.416 0.162 54.431 0.022 54.46 -0.103 c
+54.497 -0.231 54.553 -0.345 54.622 -0.441 c
+54.688 -0.53 54.773 -0.599 54.871 -0.647 c
+54.967 -0.698 55.081 -0.721 55.21 -0.721 c
+55.364 -0.721 55.504 -0.688 55.621 -0.617 c
+55.746 -0.551 55.835 -0.449 55.887 -0.309 c
+56.724 -0.382 l
+56.695 -0.482 56.639 -0.588 56.562 -0.706 c
+56.481 -0.816 56.379 -0.919 56.253 -1.014 c
+56.136 -1.103 55.982 -1.176 55.798 -1.235 c
+55.621 -1.294 55.409 -1.323 55.166 -1.323 c
+55.166 1.705 m
+55.077 1.705 54.989 1.691 54.902 1.66 c
+54.813 1.631 54.732 1.58 54.666 1.514 c
+54.596 1.444 54.537 1.356 54.49 1.249 c
+54.449 1.139 54.431 1.014 54.431 0.867 c
+55.901 0.867 l
+55.901 1.003 55.875 1.124 55.827 1.234 c
+55.787 1.341 55.731 1.429 55.665 1.5 c
+55.607 1.565 55.534 1.617 55.445 1.646 c
+55.357 1.683 55.261 1.705 55.166 1.705 c
+58.04 -2.631 m
+58.04 -2.014 l
+59.112 -2.014 l
+59.112 2.896 l
+58.04 2.896 l
+58.04 3.513 l
+59.965 3.513 l
+59.965 -2.631 l
+h
+f
+Q
+q 1 0 0 1 316.4525 277.2445 cm
+0 0 m
+-1.808 0 l
+-2.219 -1.396 l
+-2.91 -1.396 l
+-1.19 3.954 l
+-0.617 3.954 l
+1.118 -1.396 l
+0.426 -1.396 l
+h
+-1.631 0.588 m
+-0.176 0.588 l
+-0.897 3.013 l
+h
+1.617 0.779 m
+1.617 1.386 1.727 1.852 1.955 2.176 c
+2.19 2.5 2.517 2.66 2.94 2.66 c
+3.323 2.66 3.62 2.502 3.836 2.19 c
+3.836 4.248 l
+4.484 4.248 l
+4.484 -1.396 l
+3.896 -1.396 l
+3.851 -0.97 l
+3.645 -1.304 3.341 -1.469 2.94 -1.469 c
+2.529 -1.469 2.205 -1.315 1.97 -0.999 c
+1.735 -0.675 1.617 -0.22 1.617 0.368 c
+h
+2.264 0.397 m
+2.264 -0.044 2.326 -0.374 2.455 -0.588 c
+2.591 -0.793 2.812 -0.897 3.117 -0.897 c
+3.44 -0.897 3.678 -0.735 3.836 -0.411 c
+3.836 1.602 l
+3.668 1.914 3.429 2.072 3.117 2.072 c
+2.812 2.072 2.591 1.97 2.455 1.764 c
+2.326 1.559 2.264 1.235 2.264 0.794 c
+h
+5.351 0.779 m
+5.351 1.386 5.461 1.852 5.689 2.176 c
+5.924 2.5 6.251 2.66 6.674 2.66 c
+7.056 2.66 7.354 2.502 7.57 2.19 c
+7.57 4.248 l
+8.217 4.248 l
+8.217 -1.396 l
+7.629 -1.396 l
+7.585 -0.97 l
+7.379 -1.304 7.074 -1.469 6.674 -1.469 c
+6.262 -1.469 5.939 -1.315 5.704 -0.999 c
+5.469 -0.675 5.351 -0.22 5.351 0.368 c
+h
+5.997 0.397 m
+5.997 -0.044 6.06 -0.374 6.188 -0.588 c
+6.325 -0.793 6.545 -0.897 6.85 -0.897 c
+7.173 -0.897 7.412 -0.735 7.57 -0.411 c
+7.57 1.602 l
+7.402 1.914 7.163 2.072 6.85 2.072 c
+6.545 2.072 6.325 1.97 6.188 1.764 c
+6.06 1.559 5.997 1.235 5.997 0.794 c
+h
+12.979 -1.396 m
+12.939 -1.308 12.914 -1.161 12.906 -0.955 c
+12.671 -1.3 12.377 -1.469 12.025 -1.469 c
+11.66 -1.469 11.377 -1.374 11.171 -1.176 c
+10.973 -0.97 10.878 -0.683 10.878 -0.309 c
+10.878 0.092 11.013 0.412 11.289 0.647 c
+11.561 0.89 11.936 1.014 12.406 1.014 c
+12.891 1.014 l
+12.891 1.441 l
+12.891 1.676 12.836 1.841 12.73 1.941 c
+12.619 2.047 12.457 2.103 12.245 2.103 c
+12.046 2.103 11.884 2.043 11.759 1.926 c
+11.642 1.808 11.583 1.661 11.583 1.484 c
+10.936 1.484 l
+10.936 1.679 10.995 1.871 11.113 2.058 c
+11.238 2.242 11.4 2.389 11.597 2.5 c
+11.803 2.606 12.031 2.66 12.289 2.66 c
+12.69 2.66 12.994 2.558 13.2 2.352 c
+13.413 2.147 13.527 1.852 13.538 1.47 c
+13.538 -0.544 l
+13.538 -0.849 13.575 -1.113 13.656 -1.338 c
+13.656 -1.396 l
+h
+12.112 -0.881 m
+12.278 -0.881 12.428 -0.837 12.568 -0.75 c
+12.715 -0.661 12.821 -0.551 12.891 -0.411 c
+12.891 0.53 l
+12.524 0.53 l
+12.208 0.53 11.965 0.46 11.789 0.324 c
+11.612 0.195 11.524 0.008 11.524 -0.235 c
+11.524 -0.463 11.568 -0.628 11.657 -0.735 c
+11.745 -0.833 11.896 -0.881 12.112 -0.881 c
+16.434 -1.396 m
+16.434 2.058 l
+15.919 2.058 l
+15.919 2.587 l
+16.434 2.587 l
+16.434 2.955 l
+16.441 3.385 16.555 3.719 16.771 3.954 c
+16.996 4.197 17.309 4.322 17.712 4.322 c
+17.86 4.322 17.999 4.3 18.139 4.263 c
+18.286 4.223 18.437 4.168 18.595 4.102 c
+18.477 3.528 l
+18.242 3.653 17.999 3.719 17.756 3.719 c
+17.511 3.719 17.338 3.649 17.242 3.514 c
+17.143 3.385 17.095 3.19 17.095 2.926 c
+17.095 2.587 l
+17.742 2.587 l
+17.742 2.058 l
+17.095 2.058 l
+17.095 -1.396 l
+h
+18.903 -1.396 -0.646 3.983 re
+20.652 -1.396 -0.646 5.644 re
+23.092 -1.469 m
+22.593 -1.469 22.211 -1.323 21.946 -1.028 c
+21.681 -0.735 21.549 -0.301 21.549 0.279 c
+21.549 0.75 l
+21.549 1.345 21.674 1.812 21.931 2.147 c
+22.196 2.488 22.556 2.66 23.019 2.66 c
+23.478 2.66 23.82 2.506 24.048 2.205 c
+24.283 1.912 24.405 1.448 24.415 0.823 c
+24.415 0.397 l
+22.196 0.397 l
+22.196 0.309 l
+22.196 -0.124 22.273 -0.437 22.431 -0.632 c
+22.597 -0.819 22.828 -0.911 23.121 -0.911 c
+23.316 -0.911 23.489 -0.878 23.636 -0.808 c
+23.784 -0.731 23.919 -0.613 24.048 -0.455 c
+24.386 -0.867 l
+24.1 -1.271 23.669 -1.469 23.092 -1.469 c
+23.019 2.103 m
+22.743 2.103 22.541 2.007 22.416 1.823 c
+22.288 1.636 22.215 1.345 22.196 0.956 c
+23.769 0.956 l
+23.769 1.044 l
+23.746 1.426 23.68 1.694 23.563 1.852 c
+23.445 2.018 23.262 2.103 23.019 2.103 c
+27.767 3.543 m
+27.767 2.587 l
+28.37 2.587 l
+28.37 2.058 l
+27.767 2.058 l
+27.767 -0.411 l
+27.767 -0.569 27.788 -0.687 27.84 -0.764 c
+27.899 -0.845 27.987 -0.881 28.105 -0.881 c
+28.193 -0.881 28.281 -0.867 28.37 -0.837 c
+28.37 -1.396 l
+28.222 -1.444 28.068 -1.469 27.914 -1.469 c
+27.657 -1.469 27.462 -1.378 27.326 -1.19 c
+27.186 -1.007 27.12 -0.746 27.12 -0.411 c
+27.12 2.058 l
+26.518 2.058 l
+26.518 2.587 l
+27.12 2.587 l
+27.12 3.543 l
+h
+28.928 0.779 m
+28.928 1.357 29.064 1.812 29.34 2.147 c
+29.623 2.488 29.994 2.66 30.456 2.66 c
+30.916 2.66 31.283 2.492 31.559 2.161 c
+31.842 1.837 31.989 1.389 32 0.823 c
+32 0.397 l
+32 -0.172 31.857 -0.628 31.574 -0.97 c
+31.298 -1.304 30.931 -1.469 30.471 -1.469 c
+30.009 -1.469 29.637 -1.308 29.354 -0.985 c
+29.078 -0.654 28.935 -0.213 28.928 0.339 c
+h
+29.575 0.397 m
+29.575 -0.007 29.652 -0.323 29.81 -0.558 c
+29.976 -0.793 30.196 -0.911 30.471 -0.911 c
+31.037 -0.911 31.331 -0.5 31.353 0.324 c
+31.353 0.779 l
+31.353 1.18 31.269 1.5 31.104 1.735 c
+30.946 1.977 30.728 2.103 30.456 2.103 c
+30.192 2.103 29.976 1.977 29.81 1.735 c
+29.652 1.5 29.575 1.18 29.575 0.779 c
+h
+35.41 3.543 m
+35.41 2.587 l
+36.013 2.587 l
+36.013 2.058 l
+35.41 2.058 l
+35.41 -0.411 l
+35.41 -0.569 35.432 -0.687 35.484 -0.764 c
+35.543 -0.845 35.63 -0.881 35.748 -0.881 c
+35.837 -0.881 35.925 -0.867 36.013 -0.837 c
+36.013 -1.396 l
+35.866 -1.444 35.711 -1.469 35.557 -1.469 c
+35.3 -1.469 35.106 -1.378 34.969 -1.19 c
+34.83 -1.007 34.763 -0.746 34.763 -0.411 c
+34.763 2.058 l
+34.161 2.058 l
+34.161 2.587 l
+34.763 2.587 l
+34.763 3.543 l
+h
+37.424 2.176 m
+37.678 2.5 37.997 2.66 38.379 2.66 c
+39.085 2.66 39.441 2.19 39.453 1.249 c
+39.453 -1.396 l
+38.805 -1.396 l
+38.805 1.22 l
+38.805 1.532 38.751 1.754 38.644 1.881 c
+38.534 2.007 38.379 2.072 38.173 2.072 c
+38.015 2.072 37.868 2.018 37.733 1.912 c
+37.604 1.801 37.502 1.665 37.424 1.5 c
+37.424 -1.396 l
+36.777 -1.396 l
+36.777 4.248 l
+37.424 4.248 l
+h
+41.834 -1.469 m
+41.334 -1.469 40.952 -1.323 40.687 -1.028 c
+40.423 -0.735 40.29 -0.301 40.29 0.279 c
+40.29 0.75 l
+40.29 1.345 40.415 1.812 40.673 2.147 c
+40.937 2.488 41.297 2.66 41.76 2.66 c
+42.219 2.66 42.561 2.506 42.79 2.205 c
+43.025 1.912 43.146 1.448 43.156 0.823 c
+43.156 0.397 l
+40.937 0.397 l
+40.937 0.309 l
+40.937 -0.124 41.014 -0.437 41.172 -0.632 c
+41.338 -0.819 41.569 -0.911 41.863 -0.911 c
+42.058 -0.911 42.231 -0.878 42.377 -0.808 c
+42.524 -0.731 42.661 -0.613 42.79 -0.455 c
+43.127 -0.867 l
+42.84 -1.271 42.41 -1.469 41.834 -1.469 c
+41.76 2.103 m
+41.485 2.103 41.282 2.007 41.157 1.823 c
+41.029 1.636 40.955 1.345 40.937 0.956 c
+42.51 0.956 l
+42.51 1.044 l
+42.488 1.426 42.422 1.694 42.304 1.852 c
+42.186 2.018 42.003 2.103 41.76 2.103 c
+f
+Q
+q 1 0 0 1 363.7688 276.9219 cm
+0 0 m
+0 0.087 -0.044 0.165 -0.132 0.235 c
+-0.22 0.312 -0.407 0.415 -0.69 0.544 c
+-1.124 0.72 -1.422 0.9 -1.587 1.087 c
+-1.745 1.271 -1.822 1.502 -1.822 1.778 c
+-1.822 2.119 -1.701 2.403 -1.455 2.63 c
+-1.201 2.865 -0.864 2.983 -0.441 2.983 c
+-0.011 2.983 0.339 2.869 0.603 2.645 c
+0.867 2.418 1 2.117 1 1.734 c
+-0.044 1.734 l
+-0.044 2.057 -0.183 2.219 -0.455 2.219 c
+-0.565 2.219 -0.654 2.183 -0.72 2.117 c
+-0.79 2.046 -0.823 1.947 -0.823 1.822 c
+-0.823 1.734 -0.786 1.653 -0.706 1.587 c
+-0.628 1.529 -0.448 1.433 -0.162 1.308 c
+0.268 1.15 0.566 0.974 0.735 0.779 c
+0.912 0.591 1 0.341 1 0.029 c
+1 -0.324 0.867 -0.611 0.603 -0.823 c
+0.339 -1.04 -0.011 -1.147 -0.441 -1.147 c
+-0.735 -1.147 -0.995 -1.092 -1.22 -0.985 c
+-1.448 -0.867 -1.624 -0.706 -1.749 -0.5 c
+-1.866 -0.294 -1.926 -0.074 -1.926 0.161 c
+-0.941 0.161 l
+-0.941 -0.026 -0.904 -0.162 -0.823 -0.25 c
+-0.735 -0.339 -0.602 -0.383 -0.426 -0.383 c
+-0.143 -0.383 0 -0.258 0 0 c
+2.866 3.881 m
+2.866 2.91 l
+3.396 2.91 l
+3.396 2.117 l
+2.866 2.117 l
+2.866 0.147 l
+2.866 -0.011 2.885 -0.118 2.926 -0.177 c
+2.973 -0.235 3.057 -0.265 3.175 -0.265 c
+3.281 -0.265 3.366 -0.258 3.425 -0.235 c
+3.425 -1.044 l
+3.248 -1.11 3.057 -1.147 2.851 -1.147 c
+2.176 -1.147 1.83 -0.761 1.823 0.014 c
+1.823 2.117 l
+1.367 2.117 l
+1.367 2.91 l
+1.823 2.91 l
+1.823 3.881 l
+h
+5.85 -1.073 m
+5.821 -1.015 5.791 -0.912 5.762 -0.765 c
+5.575 -1.022 5.325 -1.147 5.012 -1.147 c
+4.678 -1.147 4.399 -1.04 4.175 -0.823 c
+3.958 -0.599 3.851 -0.31 3.851 0.043 c
+3.851 0.455 3.984 0.771 4.248 0.999 c
+4.513 1.234 4.895 1.352 5.395 1.352 c
+5.718 1.352 l
+5.718 1.675 l
+5.718 1.851 5.681 1.973 5.615 2.042 c
+5.556 2.119 5.469 2.16 5.351 2.16 c
+5.093 2.16 4.968 2.006 4.968 1.705 c
+3.925 1.705 l
+3.925 2.076 4.061 2.381 4.337 2.616 c
+4.609 2.859 4.958 2.983 5.38 2.983 c
+5.821 2.983 6.159 2.865 6.394 2.63 c
+6.637 2.403 6.762 2.08 6.762 1.66 c
+6.762 -0.206 l
+6.762 -0.551 6.809 -0.82 6.909 -1.015 c
+6.909 -1.073 l
+h
+5.247 -0.324 m
+5.355 -0.324 5.446 -0.306 5.527 -0.265 c
+5.615 -0.217 5.677 -0.158 5.718 -0.088 c
+5.718 0.735 l
+5.469 0.735 l
+5.292 0.735 5.149 0.675 5.042 0.558 c
+4.943 0.448 4.895 0.301 4.895 0.118 c
+4.895 -0.177 5.012 -0.324 5.247 -0.324 c
+7.379 1.043 m
+7.379 1.69 7.497 2.175 7.732 2.499 c
+7.967 2.822 8.298 2.983 8.731 2.983 c
+9.084 2.983 9.356 2.84 9.554 2.557 c
+9.598 2.91 l
+10.539 2.91 l
+10.539 -1.073 l
+10.539 -1.58 10.396 -1.97 10.113 -2.234 c
+9.826 -2.506 9.422 -2.646 8.893 -2.646 c
+8.665 -2.646 8.43 -2.602 8.187 -2.514 c
+7.952 -2.426 7.776 -2.311 7.659 -2.176 c
+8.011 -1.455 l
+8.106 -1.563 8.235 -1.646 8.393 -1.706 c
+8.548 -1.771 8.694 -1.808 8.835 -1.808 c
+9.07 -1.808 9.235 -1.75 9.334 -1.632 c
+9.44 -1.522 9.496 -1.345 9.496 -1.103 c
+9.496 -0.75 l
+9.297 -1.015 9.04 -1.147 8.717 -1.147 c
+8.294 -1.147 7.967 -0.985 7.732 -0.662 c
+7.504 -0.331 7.387 0.139 7.379 0.749 c
+h
+8.422 0.779 m
+8.422 0.404 8.47 0.135 8.57 -0.03 c
+8.665 -0.198 8.819 -0.279 9.025 -0.279 c
+9.239 -0.279 9.396 -0.202 9.496 -0.044 c
+9.496 1.851 l
+9.386 2.017 9.231 2.102 9.025 2.102 c
+8.819 2.102 8.665 2.017 8.57 1.851 c
+8.47 1.683 8.422 1.414 8.422 1.043 c
+h
+12.391 -1.073 -1.043 3.983 re
+11.304 3.939 m
+11.304 4.093 11.352 4.222 11.451 4.321 c
+11.557 4.428 11.693 4.483 11.863 4.483 c
+12.039 4.483 12.175 4.428 12.274 4.321 c
+12.38 4.222 12.436 4.093 12.436 3.939 c
+12.436 3.77 12.38 3.634 12.274 3.528 c
+12.175 3.428 12.039 3.38 11.863 3.38 c
+11.693 3.38 11.557 3.428 11.451 3.528 c
+11.352 3.634 11.304 3.77 11.304 3.939 c
+14.155 2.91 m
+14.184 2.513 l
+14.42 2.825 14.722 2.983 15.096 2.983 c
+15.78 2.983 16.133 2.502 16.154 1.543 c
+16.154 -1.073 l
+15.111 -1.073 l
+15.111 1.469 l
+15.111 1.693 15.074 1.855 15.008 1.955 c
+14.938 2.05 14.82 2.102 14.655 2.102 c
+14.468 2.102 14.321 2.006 14.215 1.822 c
+14.215 -1.073 l
+13.17 -1.073 l
+13.17 2.91 l
+h
+16.772 1.043 m
+16.772 1.69 16.889 2.175 17.124 2.499 c
+17.359 2.822 17.691 2.983 18.124 2.983 c
+18.477 2.983 18.749 2.84 18.947 2.557 c
+18.992 2.91 l
+19.932 2.91 l
+19.932 -1.073 l
+19.932 -1.58 19.788 -1.97 19.506 -2.234 c
+19.219 -2.506 18.815 -2.646 18.286 -2.646 c
+18.058 -2.646 17.822 -2.602 17.581 -2.514 c
+17.345 -2.426 17.169 -2.311 17.051 -2.176 c
+17.404 -1.455 l
+17.5 -1.563 17.628 -1.646 17.786 -1.706 c
+17.941 -1.771 18.088 -1.808 18.227 -1.808 c
+18.462 -1.808 18.628 -1.75 18.726 -1.632 c
+18.834 -1.522 18.888 -1.345 18.888 -1.103 c
+18.888 -0.75 l
+18.69 -1.015 18.433 -1.147 18.109 -1.147 c
+17.687 -1.147 17.359 -0.985 17.124 -0.662 c
+16.897 -0.331 16.779 0.139 16.772 0.749 c
+h
+17.816 0.779 m
+17.816 0.404 17.863 0.135 17.962 -0.03 c
+18.058 -0.198 18.213 -0.279 18.418 -0.279 c
+18.631 -0.279 18.789 -0.202 18.888 -0.044 c
+18.888 1.851 l
+18.778 2.017 18.624 2.102 18.418 2.102 c
+18.213 2.102 18.058 2.017 17.962 1.851 c
+17.863 1.683 17.816 1.414 17.816 1.043 c
+h
+f
+Q
+q 1 0 0 1 388.3315 275.8485 cm
+0 0 m
+-0.04 0.088 -0.067 0.235 -0.074 0.441 c
+-0.309 0.096 -0.603 -0.073 -0.956 -0.073 c
+-1.32 -0.073 -1.603 0.022 -1.808 0.22 c
+-2.007 0.426 -2.103 0.713 -2.103 1.087 c
+-2.103 1.488 -1.966 1.808 -1.691 2.043 c
+-1.419 2.286 -1.044 2.41 -0.574 2.41 c
+-0.088 2.41 l
+-0.088 2.837 l
+-0.088 3.072 -0.144 3.237 -0.25 3.337 c
+-0.36 3.443 -0.522 3.499 -0.736 3.499 c
+-0.934 3.499 -1.096 3.439 -1.22 3.322 c
+-1.338 3.204 -1.397 3.057 -1.397 2.881 c
+-2.043 2.881 l
+-2.043 3.075 -1.985 3.267 -1.867 3.454 c
+-1.742 3.638 -1.58 3.785 -1.382 3.896 c
+-1.176 4.002 -0.948 4.056 -0.691 4.056 c
+-0.291 4.056 0.014 3.954 0.22 3.748 c
+0.434 3.543 0.548 3.248 0.558 2.866 c
+0.558 0.852 l
+0.558 0.548 0.595 0.283 0.675 0.058 c
+0.675 0 l
+h
+-0.867 0.515 m
+-0.703 0.515 -0.551 0.559 -0.412 0.646 c
+-0.265 0.735 -0.158 0.845 -0.088 0.985 c
+-0.088 1.926 l
+-0.456 1.926 l
+-0.772 1.926 -1.015 1.856 -1.191 1.72 c
+-1.368 1.591 -1.455 1.404 -1.455 1.161 c
+-1.455 0.933 -1.411 0.768 -1.324 0.661 c
+-1.235 0.563 -1.085 0.515 -0.867 0.515 c
+3.204 3.366 m
+3.116 3.385 3.017 3.395 2.91 3.395 c
+2.576 3.395 2.341 3.212 2.204 2.851 c
+2.204 0 l
+1.558 0 l
+1.558 3.983 l
+2.19 3.983 l
+2.204 3.572 l
+2.381 3.896 2.624 4.056 2.94 4.056 c
+3.046 4.056 3.135 4.035 3.204 3.998 c
+h
+5.203 -0.073 m
+4.704 -0.073 4.321 0.073 4.056 0.368 c
+3.792 0.661 3.659 1.095 3.659 1.675 c
+3.659 2.146 l
+3.659 2.741 3.785 3.208 4.041 3.543 c
+4.307 3.884 4.667 4.056 5.13 4.056 c
+5.589 4.056 5.93 3.902 6.158 3.601 c
+6.393 3.308 6.515 2.844 6.526 2.219 c
+6.526 1.793 l
+4.307 1.793 l
+4.307 1.705 l
+4.307 1.272 4.384 0.959 4.542 0.764 c
+4.707 0.577 4.939 0.485 5.232 0.485 c
+5.427 0.485 5.6 0.518 5.747 0.588 c
+5.894 0.665 6.03 0.783 6.158 0.941 c
+6.497 0.529 l
+6.21 0.125 5.78 -0.073 5.203 -0.073 c
+5.13 3.499 m
+4.854 3.499 4.652 3.403 4.527 3.219 c
+4.398 3.032 4.325 2.741 4.307 2.352 c
+5.88 2.352 l
+5.88 2.44 l
+5.857 2.822 5.791 3.09 5.674 3.248 c
+5.556 3.414 5.373 3.499 5.13 3.499 c
+9.348 0 m
+9.308 0.088 9.282 0.235 9.275 0.441 c
+9.04 0.096 8.745 -0.073 8.392 -0.073 c
+8.029 -0.073 7.746 0.022 7.54 0.22 c
+7.342 0.426 7.247 0.713 7.247 1.087 c
+7.247 1.488 7.382 1.808 7.658 2.043 c
+7.93 2.286 8.305 2.41 8.775 2.41 c
+9.26 2.41 l
+9.26 2.837 l
+9.26 3.072 9.205 3.237 9.098 3.337 c
+8.988 3.443 8.826 3.499 8.613 3.499 c
+8.415 3.499 8.253 3.439 8.128 3.322 c
+8.01 3.204 7.952 3.057 7.952 2.881 c
+7.305 2.881 l
+7.305 3.075 7.364 3.267 7.482 3.454 c
+7.606 3.638 7.768 3.785 7.966 3.896 c
+8.172 4.002 8.4 4.056 8.658 4.056 c
+9.057 4.056 9.363 3.954 9.568 3.748 c
+9.782 3.543 9.896 3.248 9.907 2.866 c
+9.907 0.852 l
+9.907 0.548 9.944 0.283 10.025 0.058 c
+10.025 0 l
+h
+8.481 0.515 m
+8.646 0.515 8.797 0.559 8.937 0.646 c
+9.084 0.735 9.19 0.845 9.26 0.985 c
+9.26 1.926 l
+8.893 1.926 l
+8.577 1.926 8.334 1.856 8.157 1.72 c
+7.981 1.591 7.893 1.404 7.893 1.161 c
+7.893 0.933 7.937 0.768 8.025 0.661 c
+8.114 0.563 8.264 0.515 8.481 0.515 c
+10.95 0.353 m
+10.95 0.47 10.983 0.566 11.054 0.646 c
+11.12 0.723 11.222 0.764 11.362 0.764 c
+11.509 0.764 11.615 0.723 11.685 0.646 c
+11.762 0.566 11.803 0.47 11.803 0.353 c
+11.803 0.243 11.762 0.151 11.685 0.073 c
+11.615 -0.004 11.509 -0.044 11.362 -0.044 c
+11.222 -0.044 11.12 -0.004 11.054 0.073 c
+10.983 0.151 10.95 0.243 10.95 0.353 c
+17.888 5.35 m
+17.888 1.544 l
+17.888 1.043 17.741 0.646 17.447 0.353 c
+17.161 0.066 16.76 -0.073 16.242 -0.073 c
+15.713 -0.073 15.305 0.062 15.022 0.338 c
+14.746 0.621 14.611 1.022 14.611 1.544 c
+14.611 5.35 l
+15.272 5.35 l
+15.272 1.573 l
+15.272 1.209 15.345 0.941 15.492 0.764 c
+15.646 0.588 15.897 0.5 16.242 0.5 c
+16.583 0.5 16.83 0.588 16.977 0.764 c
+17.132 0.941 17.212 1.209 17.212 1.573 c
+17.212 5.35 l
+h
+20.784 1.014 m
+20.784 1.161 20.729 1.282 20.622 1.382 c
+20.512 1.477 20.306 1.595 20.005 1.735 c
+19.66 1.882 19.417 2.003 19.27 2.102 c
+19.123 2.209 19.013 2.326 18.947 2.454 c
+18.877 2.58 18.844 2.738 18.844 2.925 c
+18.844 3.248 18.962 3.516 19.197 3.734 c
+19.432 3.946 19.733 4.056 20.108 4.056 c
+20.49 4.056 20.799 3.943 21.034 3.719 c
+21.269 3.491 21.387 3.204 21.387 2.851 c
+20.74 2.851 l
+20.74 3.028 20.681 3.179 20.564 3.308 c
+20.446 3.432 20.292 3.499 20.108 3.499 c
+19.91 3.499 19.758 3.443 19.652 3.337 c
+19.542 3.237 19.49 3.105 19.49 2.94 c
+19.49 2.811 19.527 2.705 19.608 2.616 c
+19.685 2.535 19.876 2.433 20.182 2.308 c
+20.66 2.12 20.99 1.933 21.167 1.749 c
+21.343 1.573 21.431 1.345 21.431 1.073 c
+21.431 0.721 21.306 0.441 21.063 0.235 c
+20.828 0.029 20.512 -0.073 20.122 -0.073 c
+19.7 -0.073 19.362 0.044 19.108 0.279 c
+18.851 0.522 18.726 0.827 18.726 1.191 c
+19.373 1.191 l
+19.38 0.962 19.45 0.786 19.579 0.661 c
+19.704 0.544 19.887 0.485 20.122 0.485 c
+20.336 0.485 20.498 0.532 20.608 0.632 c
+20.725 0.727 20.784 0.856 20.784 1.014 c
+23.694 -0.073 m
+23.195 -0.073 22.813 0.073 22.548 0.368 c
+22.283 0.661 22.151 1.095 22.151 1.675 c
+22.151 2.146 l
+22.151 2.741 22.276 3.208 22.534 3.543 c
+22.798 3.884 23.158 4.056 23.621 4.056 c
+24.08 4.056 24.423 3.902 24.65 3.601 c
+24.885 3.308 25.007 2.844 25.017 2.219 c
+25.017 1.793 l
+22.798 1.793 l
+22.798 1.705 l
+22.798 1.272 22.875 0.959 23.033 0.764 c
+23.199 0.577 23.43 0.485 23.724 0.485 c
+23.918 0.485 24.091 0.518 24.238 0.588 c
+24.385 0.665 24.521 0.783 24.65 0.941 c
+24.988 0.529 l
+24.701 0.125 24.271 -0.073 23.694 -0.073 c
+23.621 3.499 m
+23.345 3.499 23.143 3.403 23.018 3.219 c
+22.89 3.032 22.816 2.741 22.798 2.352 c
+24.371 2.352 l
+24.371 2.44 l
+24.348 2.822 24.282 3.09 24.165 3.248 c
+24.047 3.414 23.864 3.499 23.621 3.499 c
+f
+Q
+q 1 0 0 1 415.8331 276.3772 cm
+0 0 m
+0 0.166 0.052 0.302 0.162 0.412 c
+0.268 0.518 0.415 0.574 0.603 0.574 c
+0.768 0.574 0.912 0.518 1.029 0.412 c
+1.147 0.302 1.205 0.166 1.205 0 c
+1.205 -0.168 1.147 -0.305 1.029 -0.411 c
+0.912 -0.521 0.768 -0.573 0.603 -0.573 c
+0.426 -0.573 0.279 -0.521 0.162 -0.411 c
+0.052 -0.305 0 -0.168 0 0 c
+f
+Q
+420.463 275.848 -0.647 3.983 re
+420.508 280.876 m
+420.508 280.766 420.478 280.674 420.419 280.596 c
+420.36 280.527 420.265 280.493 420.14 280.493 c
+420.022 280.493 419.926 280.527 419.86 280.596 c
+419.802 280.674 419.772 280.766 419.772 280.876 c
+419.772 280.993 419.802 281.085 419.86 281.155 c
+419.926 281.232 420.022 281.273 420.14 281.273 c
+420.265 281.273 420.36 281.232 420.419 281.155 c
+420.478 281.074 420.508 280.982 420.508 280.876 c
+422.095 279.832 m
+422.11 279.391 l
+422.363 279.733 422.686 279.905 423.08 279.905 c
+423.785 279.905 424.142 279.435 424.153 278.494 c
+424.153 275.848 l
+423.506 275.848 l
+423.506 278.465 l
+423.506 278.777 423.451 278.998 423.344 279.126 c
+423.234 279.251 423.08 279.317 422.874 279.317 c
+422.716 279.317 422.569 279.262 422.433 279.156 c
+422.304 279.045 422.201 278.91 422.124 278.744 c
+422.124 275.848 l
+421.478 275.848 l
+421.478 279.832 l
+h
+427.063 276.863 m
+427.063 277.009 427.008 277.131 426.902 277.23 c
+426.791 277.325 426.586 277.443 426.284 277.583 c
+425.939 277.73 425.696 277.851 425.549 277.95 c
+425.402 278.057 425.292 278.175 425.225 278.303 c
+425.156 278.428 425.123 278.586 425.123 278.773 c
+425.123 279.097 425.24 279.365 425.476 279.582 c
+425.711 279.795 426.012 279.905 426.387 279.905 c
+426.769 279.905 427.078 279.791 427.313 279.567 c
+427.548 279.34 427.666 279.053 427.666 278.7 c
+427.019 278.7 l
+427.019 278.877 426.96 279.027 426.843 279.156 c
+426.725 279.28 426.571 279.347 426.387 279.347 c
+426.189 279.347 426.038 279.292 425.931 279.185 c
+425.821 279.086 425.769 278.954 425.769 278.788 c
+425.769 278.659 425.806 278.553 425.887 278.465 c
+425.964 278.384 426.156 278.281 426.461 278.156 c
+426.939 277.969 427.269 277.782 427.446 277.597 c
+427.621 277.421 427.71 277.194 427.71 276.922 c
+427.71 276.569 427.585 276.29 427.342 276.084 c
+427.107 275.878 426.791 275.775 426.401 275.775 c
+425.979 275.775 425.641 275.893 425.387 276.128 c
+425.13 276.371 425.005 276.675 425.005 277.039 c
+425.652 277.039 l
+425.659 276.811 425.729 276.635 425.858 276.51 c
+425.983 276.392 426.166 276.334 426.401 276.334 c
+426.615 276.334 426.777 276.381 426.887 276.481 c
+427.004 276.576 427.063 276.705 427.063 276.863 c
+429.4 280.787 m
+429.4 279.832 l
+430.003 279.832 l
+430.003 279.303 l
+429.4 279.303 l
+429.4 276.833 l
+429.4 276.675 429.422 276.558 429.474 276.481 c
+429.532 276.4 429.621 276.363 429.738 276.363 c
+429.827 276.363 429.915 276.377 430.003 276.407 c
+430.003 275.848 l
+429.856 275.801 429.701 275.775 429.547 275.775 c
+429.29 275.775 429.096 275.866 428.959 276.055 c
+428.82 276.238 428.753 276.499 428.753 276.833 c
+428.753 279.303 l
+428.151 279.303 l
+428.151 279.832 l
+428.753 279.832 l
+428.753 280.787 l
+h
+432.193 275.775 m
+431.693 275.775 431.311 275.922 431.047 276.216 c
+430.782 276.51 430.65 276.944 430.65 277.524 c
+430.65 277.994 l
+430.65 278.59 430.775 279.056 431.032 279.391 c
+431.296 279.733 431.656 279.905 432.119 279.905 c
+432.579 279.905 432.921 279.751 433.148 279.45 c
+433.384 279.156 433.505 278.692 433.516 278.068 c
+433.516 277.642 l
+431.296 277.642 l
+431.296 277.553 l
+431.296 277.12 431.373 276.807 431.531 276.612 c
+431.697 276.425 431.928 276.334 432.223 276.334 c
+432.417 276.334 432.59 276.367 432.737 276.436 c
+432.884 276.514 433.019 276.631 433.148 276.789 c
+433.487 276.377 l
+433.2 275.974 432.77 275.775 432.193 275.775 c
+432.119 279.347 m
+431.844 279.347 431.642 279.251 431.517 279.068 c
+431.388 278.88 431.315 278.59 431.296 278.2 c
+432.869 278.2 l
+432.869 278.289 l
+432.847 278.671 432.781 278.939 432.664 279.097 c
+432.546 279.262 432.362 279.347 432.119 279.347 c
+436.338 275.848 m
+436.298 275.937 436.273 276.084 436.265 276.29 c
+436.03 275.944 435.735 275.775 435.383 275.775 c
+435.019 275.775 434.736 275.87 434.53 276.069 c
+434.332 276.275 434.236 276.562 434.236 276.936 c
+434.236 277.337 434.372 277.657 434.648 277.892 c
+434.92 278.134 435.294 278.259 435.765 278.259 c
+436.25 278.259 l
+436.25 278.686 l
+436.25 278.921 436.194 279.086 436.088 279.185 c
+435.978 279.292 435.816 279.347 435.604 279.347 c
+435.405 279.347 435.243 279.288 435.118 279.17 c
+435.001 279.053 434.941 278.906 434.941 278.729 c
+434.295 278.729 l
+434.295 278.924 434.353 279.116 434.471 279.303 c
+434.596 279.486 434.758 279.633 434.956 279.744 c
+435.162 279.85 435.39 279.905 435.647 279.905 c
+436.048 279.905 436.353 279.802 436.559 279.596 c
+436.772 279.391 436.886 279.097 436.897 278.715 c
+436.897 276.701 l
+436.897 276.396 436.934 276.132 437.015 275.907 c
+437.015 275.848 l
+h
+435.471 276.363 m
+435.637 276.363 435.787 276.407 435.926 276.495 c
+436.074 276.583 436.18 276.693 436.25 276.833 c
+436.25 277.774 l
+435.882 277.774 l
+435.567 277.774 435.324 277.705 435.147 277.568 c
+434.971 277.439 434.883 277.252 434.883 277.009 c
+434.883 276.782 434.927 276.616 435.016 276.51 c
+435.103 276.411 435.254 276.363 435.471 276.363 c
+437.764 278.023 m
+437.764 278.63 437.875 279.097 438.102 279.42 c
+438.337 279.744 438.664 279.905 439.087 279.905 c
+439.469 279.905 439.766 279.747 439.984 279.435 c
+439.984 281.493 l
+440.63 281.493 l
+440.63 275.848 l
+440.042 275.848 l
+439.998 276.275 l
+439.793 275.941 439.487 275.775 439.087 275.775 c
+438.675 275.775 438.352 275.929 438.116 276.245 c
+437.881 276.569 437.764 277.024 437.764 277.612 c
+h
+438.411 277.642 m
+438.411 277.2 438.473 276.87 438.602 276.657 c
+438.738 276.452 438.958 276.348 439.263 276.348 c
+439.587 276.348 439.826 276.51 439.984 276.833 c
+439.984 278.847 l
+439.814 279.159 439.575 279.317 439.263 279.317 c
+438.958 279.317 438.738 279.214 438.602 279.008 c
+438.473 278.803 438.411 278.48 438.411 278.039 c
+h
+443.217 278.023 m
+443.217 278.601 443.353 279.056 443.629 279.391 c
+443.912 279.733 444.283 279.905 444.746 279.905 c
+445.206 279.905 445.573 279.737 445.848 279.405 c
+446.131 279.082 446.278 278.634 446.29 278.068 c
+446.29 277.642 l
+446.29 277.072 446.147 276.616 445.863 276.275 c
+445.588 275.941 445.22 275.775 444.761 275.775 c
+444.298 275.775 443.926 275.937 443.643 276.26 c
+443.368 276.591 443.225 277.032 443.217 277.583 c
+h
+443.864 277.642 m
+443.864 277.238 443.941 276.922 444.099 276.687 c
+444.265 276.452 444.485 276.334 444.761 276.334 c
+445.326 276.334 445.621 276.745 445.642 277.568 c
+445.642 278.023 l
+445.642 278.424 445.559 278.744 445.393 278.979 c
+445.235 279.222 445.018 279.347 444.746 279.347 c
+444.481 279.347 444.265 279.222 444.099 278.979 c
+443.941 278.744 443.864 278.424 443.864 278.023 c
+h
+447.421 275.848 m
+447.421 279.303 l
+446.893 279.303 l
+446.893 279.832 l
+447.421 279.832 l
+447.421 280.288 l
+447.421 280.688 447.517 281.001 447.716 281.229 c
+447.921 281.452 448.2 281.566 448.553 281.566 c
+448.689 281.566 448.821 281.545 448.95 281.508 c
+448.921 280.963 l
+448.821 280.982 448.722 280.993 448.626 280.993 c
+448.252 280.993 448.068 280.728 448.068 280.199 c
+448.068 279.832 l
+448.744 279.832 l
+448.744 279.303 l
+448.068 279.303 l
+448.068 275.848 l
+h
+451.522 275.848 m
+451.522 279.303 l
+450.993 279.303 l
+450.993 279.832 l
+451.522 279.832 l
+451.522 280.288 l
+451.522 280.688 451.618 281.001 451.816 281.229 c
+452.022 281.452 452.302 281.566 452.655 281.566 c
+452.79 281.566 452.923 281.545 453.051 281.508 c
+453.021 280.963 l
+452.923 280.982 452.823 280.993 452.728 280.993 c
+452.353 280.993 452.169 280.728 452.169 280.199 c
+452.169 279.832 l
+452.846 279.832 l
+452.846 279.303 l
+452.169 279.303 l
+452.169 275.848 l
+h
+455.638 276.201 m
+455.421 275.914 455.109 275.775 454.697 275.775 c
+454.334 275.775 454.058 275.896 453.874 276.142 c
+453.698 276.396 453.602 276.76 453.595 277.23 c
+453.595 279.832 l
+454.242 279.832 l
+454.242 277.289 l
+454.242 276.66 454.425 276.348 454.8 276.348 c
+455.201 276.348 455.477 276.525 455.624 276.878 c
+455.624 279.832 l
+456.27 279.832 l
+456.27 275.848 l
+455.653 275.848 l
+h
+457.96 275.848 -0.646 5.644 re
+459.68 275.848 -0.646 5.644 re
+462.591 275.848 m
+462.591 279.303 l
+462.076 279.303 l
+462.076 279.832 l
+462.591 279.832 l
+462.591 280.199 l
+462.598 280.629 462.712 280.963 462.928 281.198 c
+463.153 281.441 463.466 281.566 463.869 281.566 c
+464.017 281.566 464.156 281.545 464.296 281.508 c
+464.443 281.468 464.594 281.412 464.752 281.346 c
+464.634 280.772 l
+464.399 280.897 464.156 280.963 463.913 280.963 c
+463.668 280.963 463.495 280.894 463.399 280.758 c
+463.3 280.629 463.252 280.435 463.252 280.17 c
+463.252 279.832 l
+463.899 279.832 l
+463.899 279.303 l
+463.252 279.303 l
+463.252 275.848 l
+h
+465.06 275.848 -0.646 3.983 re
+466.809 275.848 -0.646 5.644 re
+469.249 275.775 m
+468.75 275.775 468.368 275.922 468.102 276.216 c
+467.838 276.51 467.706 276.944 467.706 277.524 c
+467.706 277.994 l
+467.706 278.59 467.831 279.056 468.088 279.391 c
+468.353 279.733 468.713 279.905 469.176 279.905 c
+469.635 279.905 469.977 279.751 470.205 279.45 c
+470.44 279.156 470.562 278.692 470.572 278.068 c
+470.572 277.642 l
+468.353 277.642 l
+468.353 277.553 l
+468.353 277.12 468.43 276.807 468.588 276.612 c
+468.753 276.425 468.985 276.334 469.278 276.334 c
+469.473 276.334 469.646 276.367 469.793 276.436 c
+469.941 276.514 470.076 276.631 470.205 276.789 c
+470.543 276.377 l
+470.256 275.974 469.826 275.775 469.249 275.775 c
+469.176 279.347 m
+468.9 279.347 468.698 279.251 468.573 279.068 c
+468.445 278.88 468.371 278.59 468.353 278.2 c
+469.926 278.2 l
+469.926 278.289 l
+469.904 278.671 469.837 278.939 469.72 279.097 c
+469.602 279.262 469.419 279.347 469.176 279.347 c
+475.952 277.642 m
+475.952 277.013 475.834 276.543 475.599 276.23 c
+475.372 275.926 475.055 275.775 474.644 275.775 c
+474.24 275.775 473.931 275.926 473.718 276.23 c
+473.718 274.32 l
+473.071 274.32 l
+473.071 279.832 l
+473.659 279.832 l
+473.704 279.391 l
+473.916 279.733 474.225 279.905 474.629 279.905 c
+475.07 279.905 475.397 279.751 475.614 279.45 c
+475.827 279.145 475.941 278.689 475.952 278.083 c
+h
+475.306 278.023 m
+475.306 278.465 475.235 278.788 475.1 278.994 c
+474.96 279.207 474.739 279.317 474.438 279.317 c
+474.122 279.317 473.883 279.163 473.718 278.862 c
+473.718 276.789 l
+473.883 276.484 474.122 276.334 474.438 276.334 c
+474.732 276.334 474.945 276.436 475.085 276.642 c
+475.221 276.855 475.294 277.186 475.306 277.627 c
+h
+478.833 275.848 m
+478.793 275.937 478.767 276.084 478.76 276.29 c
+478.525 275.944 478.23 275.775 477.878 275.775 c
+477.514 275.775 477.231 275.87 477.025 276.069 c
+476.827 276.275 476.731 276.562 476.731 276.936 c
+476.731 277.337 476.867 277.657 477.143 277.892 c
+477.415 278.134 477.789 278.259 478.26 278.259 c
+478.745 278.259 l
+478.745 278.686 l
+478.745 278.921 478.69 279.086 478.583 279.185 c
+478.473 279.292 478.311 279.347 478.098 279.347 c
+477.9 279.347 477.738 279.288 477.613 279.17 c
+477.496 279.053 477.436 278.906 477.436 278.729 c
+476.79 278.729 l
+476.79 278.924 476.849 279.116 476.966 279.303 c
+477.091 279.486 477.253 279.633 477.452 279.744 c
+477.658 279.85 477.885 279.905 478.142 279.905 c
+478.543 279.905 478.848 279.802 479.054 279.596 c
+479.267 279.391 479.381 279.097 479.391 278.715 c
+479.391 276.701 l
+479.391 276.396 479.428 276.132 479.509 275.907 c
+479.509 275.848 l
+h
+477.966 276.363 m
+478.132 276.363 478.282 276.407 478.421 276.495 c
+478.568 276.583 478.675 276.693 478.745 276.833 c
+478.745 277.774 l
+478.377 277.774 l
+478.061 277.774 477.819 277.705 477.642 277.568 c
+477.467 277.439 477.378 277.252 477.378 277.009 c
+477.378 276.782 477.422 276.616 477.51 276.51 c
+477.598 276.411 477.749 276.363 477.966 276.363 c
+481.244 280.787 m
+481.244 279.832 l
+481.847 279.832 l
+481.847 279.303 l
+481.244 279.303 l
+481.244 276.833 l
+481.244 276.675 481.266 276.558 481.317 276.481 c
+481.376 276.4 481.465 276.363 481.582 276.363 c
+481.67 276.363 481.758 276.377 481.847 276.407 c
+481.847 275.848 l
+481.7 275.801 481.545 275.775 481.39 275.775 c
+481.134 275.775 480.939 275.866 480.802 276.055 c
+480.663 276.238 480.597 276.499 480.597 276.833 c
+480.597 279.303 l
+479.994 279.303 l
+479.994 279.832 l
+480.597 279.832 l
+480.597 280.787 l
+h
+483.258 279.42 m
+483.511 279.744 483.831 279.905 484.213 279.905 c
+484.918 279.905 485.275 279.435 485.286 278.494 c
+485.286 275.848 l
+484.64 275.848 l
+484.64 278.465 l
+484.64 278.777 484.584 278.998 484.478 279.126 c
+484.367 279.251 484.213 279.317 484.008 279.317 c
+483.849 279.317 483.702 279.262 483.566 279.156 c
+483.437 279.045 483.335 278.91 483.258 278.744 c
+483.258 275.848 l
+482.611 275.848 l
+482.611 281.493 l
+483.258 281.493 l
+h
+486.256 274.775 m
+485.859 275.04 l
+486.094 275.363 486.215 275.698 486.227 276.039 c
+486.227 276.657 l
+486.888 276.657 l
+486.888 276.128 l
+486.888 275.87 486.822 275.625 486.697 275.378 c
+486.579 275.135 486.433 274.933 486.256 274.775 c
+490.298 280.787 m
+490.298 279.832 l
+490.901 279.832 l
+490.901 279.303 l
+490.298 279.303 l
+490.298 276.833 l
+490.298 276.675 490.321 276.558 490.372 276.481 c
+490.431 276.4 490.519 276.363 490.637 276.363 c
+490.724 276.363 490.813 276.377 490.901 276.407 c
+490.901 275.848 l
+490.755 275.801 490.6 275.775 490.445 275.775 c
+490.188 275.775 489.993 275.866 489.857 276.055 c
+489.718 276.238 489.652 276.499 489.652 276.833 c
+489.652 279.303 l
+489.049 279.303 l
+489.049 279.832 l
+489.652 279.832 l
+489.652 280.787 l
+h
+491.46 278.023 m
+491.46 278.601 491.596 279.056 491.871 279.391 c
+492.154 279.733 492.525 279.905 492.989 279.905 c
+493.448 279.905 493.815 279.737 494.09 279.405 c
+494.374 279.082 494.52 278.634 494.532 278.068 c
+494.532 277.642 l
+494.532 277.072 494.389 276.616 494.105 276.275 c
+493.83 275.941 493.462 275.775 493.003 275.775 c
+492.54 275.775 492.168 275.937 491.886 276.26 c
+491.611 276.591 491.467 277.032 491.46 277.583 c
+h
+492.106 277.642 m
+492.106 277.238 492.183 276.922 492.342 276.687 c
+492.507 276.452 492.727 276.334 493.003 276.334 c
+493.569 276.334 493.863 276.745 493.885 277.568 c
+493.885 278.023 l
+493.885 278.424 493.801 278.744 493.635 278.979 c
+493.477 279.222 493.261 279.347 492.989 279.347 c
+492.723 279.347 492.507 279.222 492.342 278.979 c
+492.183 278.744 492.106 278.424 492.106 278.023 c
+h
+499.133 275.848 m
+499.092 275.937 499.067 276.084 499.059 276.29 c
+498.824 275.944 498.53 275.775 498.177 275.775 c
+497.813 275.775 497.531 275.87 497.325 276.069 c
+497.126 276.275 497.03 276.562 497.03 276.936 c
+497.03 277.337 497.167 277.657 497.442 277.892 c
+497.714 278.134 498.089 278.259 498.559 278.259 c
+499.044 278.259 l
+499.044 278.686 l
+499.044 278.921 498.989 279.086 498.883 279.185 c
+498.772 279.292 498.611 279.347 498.398 279.347 c
+498.2 279.347 498.038 279.288 497.913 279.17 c
+497.795 279.053 497.736 278.906 497.736 278.729 c
+497.089 278.729 l
+497.089 278.924 497.148 279.116 497.265 279.303 c
+497.391 279.486 497.552 279.633 497.751 279.744 c
+497.957 279.85 498.184 279.905 498.441 279.905 c
+498.842 279.905 499.147 279.802 499.353 279.596 c
+499.566 279.391 499.68 279.097 499.692 278.715 c
+499.692 276.701 l
+499.692 276.396 499.728 276.132 499.809 275.907 c
+499.809 275.848 l
+h
+498.265 276.363 m
+498.431 276.363 498.581 276.407 498.721 276.495 c
+498.868 276.583 498.975 276.693 499.044 276.833 c
+499.044 277.774 l
+498.676 277.774 l
+498.361 277.774 498.119 277.705 497.942 277.568 c
+497.766 277.439 497.677 277.252 497.677 277.009 c
+497.677 276.782 497.722 276.616 497.81 276.51 c
+497.898 276.411 498.048 276.363 498.265 276.363 c
+500.558 278.023 m
+500.558 278.63 500.669 279.097 500.897 279.42 c
+501.132 279.744 501.458 279.905 501.882 279.905 c
+502.264 279.905 502.561 279.747 502.778 279.435 c
+502.778 281.493 l
+503.424 281.493 l
+503.424 275.848 l
+502.836 275.848 l
+502.792 276.275 l
+502.587 275.941 502.281 275.775 501.882 275.775 c
+501.47 275.775 501.146 275.929 500.911 276.245 c
+500.676 276.569 500.558 277.024 500.558 277.612 c
+h
+501.205 277.642 m
+501.205 277.2 501.267 276.87 501.396 276.657 c
+501.533 276.452 501.753 276.348 502.057 276.348 c
+502.381 276.348 502.62 276.51 502.778 276.833 c
+502.778 278.847 l
+502.609 279.159 502.37 279.317 502.057 279.317 c
+501.753 279.317 501.533 279.214 501.396 279.008 c
+501.267 278.803 501.205 278.48 501.205 278.039 c
+h
+504.292 278.023 m
+504.292 278.63 504.402 279.097 504.63 279.42 c
+504.866 279.744 505.192 279.905 505.614 279.905 c
+505.997 279.905 506.295 279.747 506.512 279.435 c
+506.512 281.493 l
+507.158 281.493 l
+507.158 275.848 l
+506.57 275.848 l
+506.526 276.275 l
+506.32 275.941 506.015 275.775 505.614 275.775 c
+505.203 275.775 504.88 275.929 504.645 276.245 c
+504.409 276.569 504.292 277.024 504.292 277.612 c
+h
+504.939 277.642 m
+504.939 277.2 505.001 276.87 505.13 276.657 c
+505.265 276.452 505.487 276.348 505.791 276.348 c
+506.115 276.348 506.354 276.51 506.512 276.833 c
+506.512 278.847 l
+506.343 279.159 506.104 279.317 505.791 279.317 c
+505.487 279.317 505.265 279.214 505.13 279.008 c
+505.001 278.803 504.939 278.48 504.939 278.039 c
+h
+511.921 275.848 m
+511.881 275.937 511.854 276.084 511.847 276.29 c
+511.612 275.944 511.318 275.775 510.965 275.775 c
+510.601 275.775 510.318 275.87 510.113 276.069 c
+509.915 276.275 509.819 276.562 509.819 276.936 c
+509.819 277.337 509.955 277.657 510.231 277.892 c
+510.503 278.134 510.877 278.259 511.347 278.259 c
+511.833 278.259 l
+511.833 278.686 l
+511.833 278.921 511.777 279.086 511.671 279.185 c
+511.561 279.292 511.399 279.347 511.185 279.347 c
+510.987 279.347 510.826 279.288 510.701 279.17 c
+510.583 279.053 510.524 278.906 510.524 278.729 c
+509.878 278.729 l
+509.878 278.924 509.936 279.116 510.054 279.303 c
+510.179 279.486 510.341 279.633 510.539 279.744 c
+510.745 279.85 510.973 279.905 511.23 279.905 c
+511.63 279.905 511.935 279.802 512.141 279.596 c
+512.354 279.391 512.469 279.097 512.479 278.715 c
+512.479 276.701 l
+512.479 276.396 512.516 276.132 512.597 275.907 c
+512.597 275.848 l
+h
+511.054 276.363 m
+511.218 276.363 511.37 276.407 511.509 276.495 c
+511.656 276.583 511.763 276.693 511.833 276.833 c
+511.833 277.774 l
+511.465 277.774 l
+511.149 277.774 510.906 277.705 510.73 277.568 c
+510.553 277.439 510.466 277.252 510.466 277.009 c
+510.466 276.782 510.51 276.616 510.598 276.51 c
+510.686 276.411 510.836 276.363 511.054 276.363 c
+514.185 275.848 -0.647 5.644 re
+515.904 275.848 -0.647 5.644 re
+f
+q 1 0 0 1 339.0603 266.9265 cm
+0 0 m
+0.213 0 0.386 0.062 0.514 0.191 c
+0.65 0.326 0.723 0.517 0.735 0.764 c
+1.352 0.764 l
+1.33 0.382 1.194 0.062 0.941 -0.192 c
+0.683 -0.437 0.371 -0.559 0 -0.559 c
+-0.493 -0.559 -0.867 -0.408 -1.133 -0.103 c
+-1.389 0.209 -1.515 0.675 -1.515 1.294 c
+-1.515 1.734 l
+-1.515 2.329 -1.389 2.786 -1.133 3.101 c
+-0.867 3.413 -0.493 3.571 0 3.571 c
+0.4 3.571 0.72 3.439 0.955 3.175 c
+1.198 2.917 1.33 2.572 1.352 2.131 c
+0.735 2.131 l
+0.712 2.425 0.639 2.645 0.514 2.792 c
+0.396 2.94 0.224 3.013 0 3.013 c
+-0.294 3.013 -0.511 2.913 -0.647 2.719 c
+-0.786 2.532 -0.86 2.223 -0.867 1.793 c
+-0.867 1.278 l
+-0.867 0.808 -0.801 0.473 -0.662 0.278 c
+-0.515 0.091 -0.294 0 0 0 c
+2.748 3.087 m
+3.002 3.41 3.322 3.571 3.704 3.571 c
+4.409 3.571 4.766 3.101 4.777 2.16 c
+4.777 -0.485 l
+4.13 -0.485 l
+4.13 2.131 l
+4.13 2.443 4.075 2.664 3.968 2.792 c
+3.858 2.917 3.704 2.983 3.498 2.983 c
+3.34 2.983 3.193 2.929 3.057 2.822 c
+2.929 2.711 2.825 2.576 2.748 2.41 c
+2.748 -0.485 l
+2.102 -0.485 l
+2.102 5.159 l
+2.748 5.159 l
+h
+7.775 -0.485 m
+7.735 -0.397 7.709 -0.25 7.702 -0.044 c
+7.467 -0.389 7.173 -0.559 6.82 -0.559 c
+6.456 -0.559 6.173 -0.464 5.967 -0.265 c
+5.769 -0.059 5.674 0.228 5.674 0.602 c
+5.674 1.003 5.809 1.323 6.085 1.558 c
+6.357 1.801 6.732 1.925 7.202 1.925 c
+7.687 1.925 l
+7.687 2.352 l
+7.687 2.587 7.632 2.752 7.526 2.851 c
+7.415 2.958 7.253 3.013 7.04 3.013 c
+6.842 3.013 6.68 2.954 6.555 2.836 c
+6.437 2.719 6.379 2.572 6.379 2.395 c
+5.732 2.395 l
+5.732 2.59 5.791 2.782 5.909 2.969 c
+6.034 3.152 6.196 3.299 6.393 3.41 c
+6.599 3.517 6.827 3.571 7.085 3.571 c
+7.485 3.571 7.79 3.469 7.996 3.262 c
+8.209 3.057 8.323 2.763 8.334 2.381 c
+8.334 0.367 l
+8.334 0.062 8.371 -0.202 8.452 -0.427 c
+8.452 -0.485 l
+h
+6.908 0.029 m
+7.073 0.029 7.224 0.073 7.364 0.161 c
+7.511 0.249 7.617 0.359 7.687 0.5 c
+7.687 1.44 l
+7.32 1.44 l
+7.004 1.44 6.761 1.371 6.585 1.234 c
+6.408 1.105 6.32 0.918 6.32 0.675 c
+6.32 0.448 6.364 0.282 6.453 0.176 c
+6.541 0.077 6.691 0.029 6.908 0.029 c
+9.951 3.498 m
+9.965 3.057 l
+10.219 3.399 10.543 3.571 10.936 3.571 c
+11.642 3.571 11.997 3.101 12.009 2.16 c
+12.009 -0.485 l
+11.362 -0.485 l
+11.362 2.131 l
+11.362 2.443 11.307 2.664 11.2 2.792 c
+11.09 2.917 10.936 2.983 10.73 2.983 c
+10.572 2.983 10.425 2.929 10.289 2.822 c
+10.16 2.711 10.057 2.576 9.98 2.41 c
+9.98 -0.485 l
+9.333 -0.485 l
+9.333 3.498 l
+h
+12.847 1.69 m
+12.847 2.308 12.957 2.77 13.184 3.087 c
+13.408 3.41 13.743 3.571 14.184 3.571 c
+14.584 3.571 14.89 3.395 15.095 3.042 c
+15.139 3.498 l
+15.727 3.498 l
+15.727 -0.53 l
+15.727 -1.018 15.599 -1.397 15.345 -1.661 c
+15.089 -1.926 14.736 -2.058 14.287 -2.058 c
+14.089 -2.058 13.868 -2.007 13.626 -1.912 c
+13.379 -1.812 13.2 -1.69 13.082 -1.544 c
+13.346 -1.103 l
+13.611 -1.368 13.909 -1.5 14.243 -1.5 c
+14.779 -1.5 15.055 -1.206 15.066 -0.618 c
+15.066 -0.088 l
+14.86 -0.405 14.559 -0.559 14.169 -0.559 c
+13.758 -0.559 13.435 -0.408 13.2 -0.103 c
+12.972 0.209 12.854 0.661 12.847 1.249 c
+h
+13.508 1.308 m
+13.508 0.866 13.57 0.536 13.699 0.323 c
+13.824 0.118 14.041 0.014 14.346 0.014 c
+14.669 0.014 14.908 0.18 15.066 0.514 c
+15.066 2.499 l
+14.898 2.822 14.659 2.983 14.346 2.983 c
+14.052 2.983 13.835 2.881 13.699 2.675 c
+13.57 2.469 13.508 2.146 13.508 1.705 c
+h
+18.109 -0.559 m
+17.609 -0.559 17.227 -0.412 16.962 -0.118 c
+16.698 0.176 16.565 0.61 16.565 1.19 c
+16.565 1.66 l
+16.565 2.256 16.691 2.723 16.947 3.057 c
+17.212 3.399 17.572 3.571 18.035 3.571 c
+18.495 3.571 18.836 3.417 19.064 3.116 c
+19.299 2.822 19.421 2.358 19.432 1.734 c
+19.432 1.308 l
+17.212 1.308 l
+17.212 1.219 l
+17.212 0.786 17.289 0.473 17.447 0.278 c
+17.613 0.091 17.844 0 18.138 0 c
+18.333 0 18.505 0.033 18.653 0.103 c
+18.8 0.18 18.935 0.297 19.064 0.455 c
+19.403 0.043 l
+19.116 -0.36 18.686 -0.559 18.109 -0.559 c
+18.035 3.013 m
+17.759 3.013 17.558 2.917 17.433 2.734 c
+17.304 2.547 17.231 2.256 17.212 1.866 c
+18.785 1.866 l
+18.785 1.955 l
+18.763 2.337 18.697 2.605 18.58 2.763 c
+18.462 2.929 18.278 3.013 18.035 3.013 c
+22.151 0.529 m
+22.151 0.675 22.096 0.797 21.99 0.897 c
+21.879 0.992 21.674 1.109 21.372 1.249 c
+21.026 1.396 20.784 1.517 20.637 1.616 c
+20.49 1.723 20.38 1.841 20.313 1.969 c
+20.244 2.094 20.211 2.252 20.211 2.439 c
+20.211 2.763 20.328 3.031 20.564 3.248 c
+20.799 3.461 21.1 3.571 21.475 3.571 c
+21.857 3.571 22.166 3.457 22.401 3.233 c
+22.636 3.006 22.754 2.719 22.754 2.366 c
+22.107 2.366 l
+22.107 2.543 22.048 2.693 21.931 2.822 c
+21.813 2.946 21.659 3.013 21.475 3.013 c
+21.277 3.013 21.126 2.958 21.019 2.851 c
+20.909 2.752 20.857 2.62 20.857 2.454 c
+20.857 2.326 20.894 2.219 20.975 2.131 c
+21.052 2.05 21.244 1.947 21.549 1.822 c
+22.026 1.635 22.357 1.448 22.534 1.263 c
+22.709 1.087 22.798 0.86 22.798 0.588 c
+22.798 0.235 22.673 -0.044 22.43 -0.25 c
+22.195 -0.456 21.879 -0.559 21.489 -0.559 c
+21.067 -0.559 20.729 -0.441 20.475 -0.206 c
+20.218 0.037 20.093 0.341 20.093 0.706 c
+20.74 0.706 l
+20.747 0.477 20.817 0.301 20.946 0.176 c
+21.071 0.058 21.254 0 21.489 0 c
+21.703 0 21.865 0.047 21.975 0.147 c
+22.092 0.242 22.151 0.371 22.151 0.529 c
+25.532 -0.485 m
+25.532 2.969 l
+25.017 2.969 l
+25.017 3.498 l
+25.532 3.498 l
+25.532 3.866 l
+25.539 4.295 25.653 4.629 25.87 4.865 c
+26.094 5.107 26.407 5.232 26.811 5.232 c
+26.958 5.232 27.097 5.211 27.237 5.174 c
+27.384 5.134 27.535 5.078 27.693 5.012 c
+27.575 4.438 l
+27.34 4.564 27.097 4.629 26.854 4.629 c
+26.609 4.629 26.436 4.56 26.341 4.424 c
+26.241 4.295 26.193 4.101 26.193 3.836 c
+26.193 3.498 l
+26.84 3.498 l
+26.84 2.969 l
+26.193 2.969 l
+26.193 -0.485 l
+h
+28.001 -0.485 -0.646 3.983 re
+29.751 -0.485 -0.647 5.644 re
+32.19 -0.559 m
+31.691 -0.559 31.309 -0.412 31.044 -0.118 c
+30.779 0.176 30.647 0.61 30.647 1.19 c
+30.647 1.66 l
+30.647 2.256 30.772 2.723 31.029 3.057 c
+31.294 3.399 31.654 3.571 32.117 3.571 c
+32.576 3.571 32.918 3.417 33.146 3.116 c
+33.381 2.822 33.503 2.358 33.514 1.734 c
+33.514 1.308 l
+31.294 1.308 l
+31.294 1.219 l
+31.294 0.786 31.371 0.473 31.529 0.278 c
+31.694 0.091 31.926 0 32.22 0 c
+32.415 0 32.587 0.033 32.734 0.103 c
+32.882 0.18 33.017 0.297 33.146 0.455 c
+33.484 0.043 l
+33.198 -0.36 32.768 -0.559 32.19 -0.559 c
+32.117 3.013 m
+31.841 3.013 31.639 2.917 31.515 2.734 c
+31.386 2.547 31.313 2.256 31.294 1.866 c
+32.867 1.866 l
+32.867 1.955 l
+32.845 2.337 32.778 2.605 32.661 2.763 c
+32.543 2.929 32.36 3.013 32.117 3.013 c
+36.233 0.529 m
+36.233 0.675 36.178 0.797 36.071 0.897 c
+35.961 0.992 35.755 1.109 35.454 1.249 c
+35.108 1.396 34.866 1.517 34.719 1.616 c
+34.572 1.723 34.461 1.841 34.395 1.969 c
+34.326 2.094 34.293 2.252 34.293 2.439 c
+34.293 2.763 34.41 3.031 34.646 3.248 c
+34.881 3.461 35.182 3.571 35.556 3.571 c
+35.939 3.571 36.248 3.457 36.483 3.233 c
+36.718 3.006 36.836 2.719 36.836 2.366 c
+36.188 2.366 l
+36.188 2.543 36.13 2.693 36.012 2.822 c
+35.895 2.946 35.741 3.013 35.556 3.013 c
+35.359 3.013 35.207 2.958 35.101 2.851 c
+34.991 2.752 34.939 2.62 34.939 2.454 c
+34.939 2.326 34.976 2.219 35.057 2.131 c
+35.134 2.05 35.325 1.947 35.631 1.822 c
+36.107 1.635 36.439 1.448 36.615 1.263 c
+36.791 1.087 36.88 0.86 36.88 0.588 c
+36.88 0.235 36.755 -0.044 36.512 -0.25 c
+36.277 -0.456 35.961 -0.559 35.571 -0.559 c
+35.149 -0.559 34.81 -0.441 34.557 -0.206 c
+34.299 0.037 34.175 0.341 34.175 0.706 c
+34.822 0.706 l
+34.829 0.477 34.899 0.301 35.027 0.176 c
+35.153 0.058 35.336 0 35.571 0 c
+35.785 0 35.946 0.047 36.057 0.147 c
+36.174 0.242 36.233 0.371 36.233 0.529 c
+39.731 -0.485 m
+39.731 2.969 l
+39.202 2.969 l
+39.202 3.498 l
+39.731 3.498 l
+39.731 3.954 l
+39.731 4.354 39.827 4.667 40.025 4.895 c
+40.231 5.119 40.51 5.232 40.863 5.232 c
+40.999 5.232 41.131 5.211 41.26 5.174 c
+41.231 4.629 l
+41.131 4.648 41.032 4.659 40.936 4.659 c
+40.562 4.659 40.378 4.394 40.378 3.866 c
+40.378 3.498 l
+41.054 3.498 l
+41.054 2.969 l
+40.378 2.969 l
+40.378 -0.485 l
+h
+43.465 2.881 m
+43.377 2.899 43.277 2.91 43.171 2.91 c
+42.837 2.91 42.601 2.726 42.465 2.366 c
+42.465 -0.485 l
+41.819 -0.485 l
+41.819 3.498 l
+42.451 3.498 l
+42.465 3.087 l
+42.642 3.41 42.885 3.571 43.2 3.571 c
+43.307 3.571 43.394 3.549 43.465 3.513 c
+h
+43.905 1.69 m
+43.905 2.267 44.042 2.723 44.317 3.057 c
+44.6 3.399 44.971 3.571 45.434 3.571 c
+45.894 3.571 46.261 3.403 46.537 3.072 c
+46.82 2.748 46.966 2.3 46.978 1.734 c
+46.978 1.308 l
+46.978 0.738 46.835 0.282 46.552 -0.059 c
+46.276 -0.393 45.908 -0.559 45.449 -0.559 c
+44.986 -0.559 44.615 -0.397 44.332 -0.074 c
+44.057 0.257 43.913 0.698 43.905 1.249 c
+h
+44.552 1.308 m
+44.552 0.904 44.63 0.588 44.788 0.353 c
+44.953 0.118 45.173 0 45.449 0 c
+46.015 0 46.309 0.411 46.331 1.234 c
+46.331 1.69 l
+46.331 2.09 46.247 2.41 46.081 2.645 c
+45.923 2.888 45.707 3.013 45.434 3.013 c
+45.17 3.013 44.953 2.888 44.788 2.645 c
+44.63 2.41 44.552 2.09 44.552 1.69 c
+h
+48.433 3.498 m
+48.448 3.131 l
+48.69 3.424 49.01 3.571 49.403 3.571 c
+49.844 3.571 50.153 3.374 50.33 2.983 c
+50.583 3.374 50.932 3.571 51.373 3.571 c
+52.108 3.571 52.483 3.108 52.505 2.19 c
+52.505 -0.485 l
+51.858 -0.485 l
+51.858 2.131 l
+51.858 2.425 51.803 2.638 51.696 2.778 c
+51.597 2.913 51.425 2.983 51.182 2.983 c
+50.983 2.983 50.822 2.903 50.696 2.748 c
+50.579 2.601 50.509 2.41 50.49 2.175 c
+50.49 -0.485 l
+49.829 -0.485 l
+49.829 2.16 l
+49.829 2.707 49.609 2.983 49.168 2.983 c
+48.834 2.983 48.599 2.822 48.462 2.499 c
+48.462 -0.485 l
+47.816 -0.485 l
+47.816 3.498 l
+h
+56.576 0 m
+56.79 0 56.962 0.062 57.091 0.191 c
+57.227 0.326 57.3 0.517 57.311 0.764 c
+57.929 0.764 l
+57.906 0.382 57.771 0.062 57.517 -0.192 c
+57.26 -0.437 56.948 -0.559 56.576 -0.559 c
+56.084 -0.559 55.709 -0.408 55.444 -0.103 c
+55.188 0.209 55.062 0.675 55.062 1.294 c
+55.062 1.734 l
+55.062 2.329 55.188 2.786 55.444 3.101 c
+55.709 3.413 56.084 3.571 56.576 3.571 c
+56.977 3.571 57.297 3.439 57.532 3.175 c
+57.775 2.917 57.906 2.572 57.929 2.131 c
+57.311 2.131 l
+57.289 2.425 57.216 2.645 57.091 2.792 c
+56.973 2.94 56.8 3.013 56.576 3.013 c
+56.283 3.013 56.065 2.913 55.93 2.719 c
+55.79 2.532 55.716 2.223 55.709 1.793 c
+55.709 1.278 l
+55.709 0.808 55.776 0.473 55.915 0.278 c
+56.061 0.091 56.283 0 56.576 0 c
+60.707 -0.133 m
+60.49 -0.42 60.177 -0.559 59.766 -0.559 c
+59.402 -0.559 59.126 -0.437 58.943 -0.192 c
+58.766 0.062 58.671 0.426 58.664 0.897 c
+58.664 3.498 l
+59.31 3.498 l
+59.31 0.955 l
+59.31 0.326 59.494 0.014 59.869 0.014 c
+60.269 0.014 60.545 0.191 60.692 0.544 c
+60.692 3.498 l
+61.339 3.498 l
+61.339 -0.485 l
+60.721 -0.485 l
+h
+63.97 2.881 m
+63.882 2.899 63.782 2.91 63.676 2.91 c
+63.342 2.91 63.107 2.726 62.97 2.366 c
+62.97 -0.485 l
+62.324 -0.485 l
+62.324 3.498 l
+62.955 3.498 l
+62.97 3.087 l
+63.147 3.41 63.389 3.571 63.705 3.571 c
+63.812 3.571 63.9 3.549 63.97 3.513 c
+h
+66.263 2.881 m
+66.174 2.899 66.076 2.91 65.969 2.91 c
+65.634 2.91 65.399 2.726 65.264 2.366 c
+65.264 -0.485 l
+64.617 -0.485 l
+64.617 3.498 l
+65.249 3.498 l
+65.264 3.087 l
+65.44 3.41 65.682 3.571 65.999 3.571 c
+66.105 3.571 66.193 3.549 66.263 3.513 c
+h
+68.262 -0.559 m
+67.762 -0.559 67.38 -0.412 67.115 -0.118 c
+66.851 0.176 66.718 0.61 66.718 1.19 c
+66.718 1.66 l
+66.718 2.256 66.843 2.723 67.101 3.057 c
+67.365 3.399 67.726 3.571 68.189 3.571 c
+68.648 3.571 68.99 3.417 69.218 3.116 c
+69.453 2.822 69.574 2.358 69.585 1.734 c
+69.585 1.308 l
+67.365 1.308 l
+67.365 1.219 l
+67.365 0.786 67.443 0.473 67.601 0.278 c
+67.766 0.091 67.998 0 68.291 0 c
+68.486 0 68.659 0.033 68.806 0.103 c
+68.952 0.18 69.089 0.297 69.218 0.455 c
+69.555 0.043 l
+69.269 -0.36 68.839 -0.559 68.262 -0.559 c
+68.189 3.013 m
+67.913 3.013 67.711 2.917 67.586 2.734 c
+67.458 2.547 67.383 2.256 67.365 1.866 c
+68.938 1.866 l
+68.938 1.955 l
+68.916 2.337 68.85 2.605 68.732 2.763 c
+68.615 2.929 68.431 3.013 68.189 3.013 c
+70.982 3.498 m
+70.996 3.057 l
+71.25 3.399 71.573 3.571 71.967 3.571 c
+72.672 3.571 73.028 3.101 73.039 2.16 c
+73.039 -0.485 l
+72.393 -0.485 l
+72.393 2.131 l
+72.393 2.443 72.337 2.664 72.231 2.792 c
+72.121 2.917 71.967 2.983 71.761 2.983 c
+71.603 2.983 71.456 2.929 71.319 2.822 c
+71.19 2.711 71.088 2.576 71.011 2.41 c
+71.011 -0.485 l
+70.364 -0.485 l
+70.364 3.498 l
+h
+74.862 4.453 m
+74.862 3.498 l
+75.464 3.498 l
+75.464 2.969 l
+74.862 2.969 l
+74.862 0.5 l
+74.862 0.341 74.884 0.224 74.936 0.147 c
+74.994 0.066 75.082 0.029 75.2 0.029 c
+75.288 0.029 75.377 0.043 75.464 0.073 c
+75.464 -0.485 l
+75.318 -0.533 75.163 -0.559 75.009 -0.559 c
+74.751 -0.559 74.556 -0.468 74.421 -0.279 c
+74.281 -0.096 74.215 0.165 74.215 0.5 c
+74.215 2.969 l
+73.613 2.969 l
+73.613 3.498 l
+74.215 3.498 l
+74.215 4.453 l
+h
+77.816 1.69 m
+77.816 2.296 77.927 2.763 78.155 3.087 c
+78.39 3.41 78.716 3.571 79.14 3.571 c
+79.522 3.571 79.819 3.413 80.036 3.101 c
+80.036 5.159 l
+80.683 5.159 l
+80.683 -0.485 l
+80.095 -0.485 l
+80.05 -0.059 l
+79.845 -0.393 79.54 -0.559 79.14 -0.559 c
+78.728 -0.559 78.404 -0.405 78.169 -0.088 c
+77.934 0.235 77.816 0.69 77.816 1.278 c
+h
+78.463 1.308 m
+78.463 0.866 78.525 0.536 78.654 0.323 c
+78.79 0.118 79.011 0.014 79.316 0.014 c
+79.639 0.014 79.878 0.176 80.036 0.5 c
+80.036 2.513 l
+79.867 2.825 79.628 2.983 79.316 2.983 c
+79.011 2.983 78.79 2.881 78.654 2.675 c
+78.525 2.469 78.463 2.146 78.463 1.705 c
+h
+82.388 -0.485 -0.647 3.983 re
+82.432 4.542 m
+82.432 4.432 82.402 4.34 82.344 4.263 c
+82.285 4.193 82.19 4.159 82.064 4.159 c
+81.947 4.159 81.851 4.193 81.785 4.263 c
+81.727 4.34 81.697 4.432 81.697 4.542 c
+81.697 4.659 81.727 4.751 81.785 4.821 c
+81.851 4.898 81.947 4.939 82.064 4.939 c
+82.19 4.939 82.285 4.898 82.344 4.821 c
+82.402 4.74 82.432 4.648 82.432 4.542 c
+85.048 2.881 m
+84.96 2.899 84.861 2.91 84.754 2.91 c
+84.42 2.91 84.185 2.726 84.048 2.366 c
+84.048 -0.485 l
+83.402 -0.485 l
+83.402 3.498 l
+84.034 3.498 l
+84.048 3.087 l
+84.225 3.41 84.468 3.571 84.784 3.571 c
+84.89 3.571 84.979 3.549 85.048 3.513 c
+h
+87.048 -0.559 m
+86.548 -0.559 86.165 -0.412 85.901 -0.118 c
+85.636 0.176 85.504 0.61 85.504 1.19 c
+85.504 1.66 l
+85.504 2.256 85.629 2.723 85.886 3.057 c
+86.151 3.399 86.51 3.571 86.974 3.571 c
+87.433 3.571 87.775 3.417 88.002 3.116 c
+88.238 2.822 88.359 2.358 88.37 1.734 c
+88.37 1.308 l
+86.151 1.308 l
+86.151 1.219 l
+86.151 0.786 86.228 0.473 86.386 0.278 c
+86.551 0.091 86.783 0 87.077 0 c
+87.271 0 87.445 0.033 87.591 0.103 c
+87.738 0.18 87.874 0.297 88.002 0.455 c
+88.341 0.043 l
+88.054 -0.36 87.624 -0.559 87.048 -0.559 c
+86.974 3.013 m
+86.699 3.013 86.496 2.917 86.371 2.734 c
+86.242 2.547 86.169 2.256 86.151 1.866 c
+87.724 1.866 l
+87.724 1.955 l
+87.701 2.337 87.636 2.605 87.518 2.763 c
+87.4 2.929 87.216 3.013 86.974 3.013 c
+90.531 0 m
+90.744 0 90.917 0.062 91.046 0.191 c
+91.181 0.326 91.255 0.517 91.266 0.764 c
+91.883 0.764 l
+91.861 0.382 91.725 0.062 91.472 -0.192 c
+91.214 -0.437 90.902 -0.559 90.531 -0.559 c
+90.038 -0.559 89.664 -0.408 89.399 -0.103 c
+89.142 0.209 89.017 0.675 89.017 1.294 c
+89.017 1.734 l
+89.017 2.329 89.142 2.786 89.399 3.101 c
+89.664 3.413 90.038 3.571 90.531 3.571 c
+90.932 3.571 91.252 3.439 91.487 3.175 c
+91.729 2.917 91.861 2.572 91.883 2.131 c
+91.266 2.131 l
+91.244 2.425 91.171 2.645 91.046 2.792 c
+90.928 2.94 90.755 3.013 90.531 3.013 c
+90.237 3.013 90.02 2.913 89.884 2.719 c
+89.745 2.532 89.671 2.223 89.664 1.793 c
+89.664 1.278 l
+89.664 0.808 89.73 0.473 89.87 0.278 c
+90.017 0.091 90.237 0 90.531 0 c
+93.486 4.453 m
+93.486 3.498 l
+94.088 3.498 l
+94.088 2.969 l
+93.486 2.969 l
+93.486 0.5 l
+93.486 0.341 93.508 0.224 93.559 0.147 c
+93.618 0.066 93.706 0.029 93.824 0.029 c
+93.912 0.029 94 0.043 94.088 0.073 c
+94.088 -0.485 l
+93.941 -0.533 93.787 -0.559 93.633 -0.559 c
+93.375 -0.559 93.18 -0.468 93.045 -0.279 c
+92.905 -0.096 92.839 0.165 92.839 0.5 c
+92.839 2.969 l
+92.236 2.969 l
+92.236 3.498 l
+92.839 3.498 l
+92.839 4.453 l
+h
+94.647 1.69 m
+94.647 2.267 94.782 2.723 95.058 3.057 c
+95.341 3.399 95.713 3.571 96.176 3.571 c
+96.635 3.571 97.002 3.403 97.278 3.072 c
+97.561 2.748 97.708 2.3 97.719 1.734 c
+97.719 1.308 l
+97.719 0.738 97.575 0.282 97.292 -0.059 c
+97.017 -0.393 96.65 -0.559 96.191 -0.559 c
+95.727 -0.559 95.356 -0.397 95.073 -0.074 c
+94.797 0.257 94.654 0.698 94.647 1.249 c
+h
+95.293 1.308 m
+95.293 0.904 95.37 0.588 95.528 0.353 c
+95.694 0.118 95.915 0 96.191 0 c
+96.756 0 97.05 0.411 97.072 1.234 c
+97.072 1.69 l
+97.072 2.09 96.987 2.41 96.822 2.645 c
+96.664 2.888 96.447 3.013 96.176 3.013 c
+95.911 3.013 95.694 2.888 95.528 2.645 c
+95.37 2.41 95.293 2.09 95.293 1.69 c
+h
+100.203 2.881 m
+100.114 2.899 100.016 2.91 99.909 2.91 c
+99.574 2.91 99.339 2.726 99.204 2.366 c
+99.204 -0.485 l
+98.557 -0.485 l
+98.557 3.498 l
+99.189 3.498 l
+99.204 3.087 l
+99.38 3.41 99.622 3.571 99.939 3.571 c
+100.045 3.571 100.133 3.549 100.203 3.513 c
+h
+102.011 0.602 m
+102.732 3.498 l
+103.422 3.498 l
+102.129 -1.044 l
+102.03 -1.386 101.886 -1.646 101.702 -1.823 c
+101.526 -1.999 101.324 -2.087 101.099 -2.087 c
+101.012 -2.087 100.897 -2.066 100.762 -2.029 c
+100.762 -1.485 l
+100.908 -1.5 l
+101.092 -1.5 101.24 -1.455 101.35 -1.368 c
+101.456 -1.279 101.544 -1.121 101.614 -0.897 c
+101.732 -0.456 l
+100.571 3.498 l
+101.276 3.498 l
+h
+105.641 1.69 m
+105.641 2.296 105.752 2.763 105.98 3.087 c
+106.215 3.41 106.542 3.571 106.965 3.571 c
+107.347 3.571 107.644 3.413 107.861 3.101 c
+107.861 5.159 l
+108.508 5.159 l
+108.508 -0.485 l
+107.92 -0.485 l
+107.876 -0.059 l
+107.67 -0.393 107.365 -0.559 106.965 -0.559 c
+106.553 -0.559 106.229 -0.405 105.994 -0.088 c
+105.759 0.235 105.641 0.69 105.641 1.278 c
+h
+106.289 1.308 m
+106.289 0.866 106.351 0.536 106.479 0.323 c
+106.616 0.118 106.836 0.014 107.141 0.014 c
+107.464 0.014 107.703 0.176 107.861 0.5 c
+107.861 2.513 l
+107.692 2.825 107.453 2.983 107.141 2.983 c
+106.836 2.983 106.616 2.881 106.479 2.675 c
+106.351 2.469 106.289 2.146 106.289 1.705 c
+h
+109.375 1.69 m
+109.375 2.267 109.511 2.723 109.787 3.057 c
+110.069 3.399 110.441 3.571 110.904 3.571 c
+111.363 3.571 111.731 3.403 112.006 3.072 c
+112.289 2.748 112.436 2.3 112.448 1.734 c
+112.448 1.308 l
+112.448 0.738 112.304 0.282 112.021 -0.059 c
+111.746 -0.393 111.378 -0.559 110.919 -0.559 c
+110.456 -0.559 110.084 -0.397 109.801 -0.074 c
+109.526 0.257 109.383 0.698 109.375 1.249 c
+h
+110.022 1.308 m
+110.022 0.904 110.099 0.588 110.257 0.353 c
+110.422 0.118 110.643 0 110.919 0 c
+111.484 0 111.779 0.411 111.8 1.234 c
+111.8 1.69 l
+111.8 2.09 111.716 2.41 111.551 2.645 c
+111.393 2.888 111.176 3.013 110.904 3.013 c
+110.639 3.013 110.422 2.888 110.257 2.645 c
+110.099 2.41 110.022 2.09 110.022 1.69 c
+h
+116.255 0.661 m
+116.857 3.498 l
+117.504 3.498 l
+116.519 -0.485 l
+116.004 -0.485 l
+115.226 2.366 l
+114.476 -0.485 l
+113.947 -0.485 l
+112.991 3.498 l
+113.623 3.498 l
+114.241 0.735 l
+114.975 3.498 l
+115.49 3.498 l
+h
+118.798 3.498 m
+118.812 3.057 l
+119.066 3.399 119.389 3.571 119.782 3.571 c
+120.488 3.571 120.845 3.101 120.855 2.16 c
+120.855 -0.485 l
+120.209 -0.485 l
+120.209 2.131 l
+120.209 2.443 120.153 2.664 120.047 2.792 c
+119.937 2.917 119.782 2.983 119.576 2.983 c
+119.418 2.983 119.272 2.929 119.135 2.822 c
+119.006 2.711 118.904 2.576 118.827 2.41 c
+118.827 -0.485 l
+118.18 -0.485 l
+118.18 3.498 l
+h
+124.251 -0.485 -0.647 3.983 re
+124.295 4.542 m
+124.295 4.432 124.265 4.34 124.207 4.263 c
+124.148 4.193 124.052 4.159 123.927 4.159 c
+123.81 4.159 123.714 4.193 123.648 4.263 c
+123.59 4.34 123.56 4.432 123.56 4.542 c
+123.56 4.659 123.59 4.751 123.648 4.821 c
+123.714 4.898 123.81 4.939 123.927 4.939 c
+124.052 4.939 124.148 4.898 124.207 4.821 c
+124.265 4.74 124.295 4.648 124.295 4.542 c
+125.882 3.498 m
+125.897 3.057 l
+126.15 3.399 126.474 3.571 126.867 3.571 c
+127.573 3.571 127.929 3.101 127.941 2.16 c
+127.941 -0.485 l
+127.293 -0.485 l
+127.293 2.131 l
+127.293 2.443 127.238 2.664 127.132 2.792 c
+127.021 2.917 126.867 2.983 126.661 2.983 c
+126.503 2.983 126.356 2.929 126.22 2.822 c
+126.092 2.711 125.989 2.576 125.911 2.41 c
+125.911 -0.485 l
+125.265 -0.485 l
+125.265 3.498 l
+h
+129.763 4.453 m
+129.763 3.498 l
+130.366 3.498 l
+130.366 2.969 l
+129.763 2.969 l
+129.763 0.5 l
+129.763 0.341 129.784 0.224 129.836 0.147 c
+129.895 0.066 129.983 0.029 130.101 0.029 c
+130.189 0.029 130.277 0.043 130.366 0.073 c
+130.366 -0.485 l
+130.218 -0.533 130.064 -0.559 129.91 -0.559 c
+129.653 -0.559 129.458 -0.468 129.322 -0.279 c
+129.182 -0.096 129.116 0.165 129.116 0.5 c
+129.116 2.969 l
+128.513 2.969 l
+128.513 3.498 l
+129.116 3.498 l
+129.116 4.453 l
+h
+130.924 1.69 m
+130.924 2.267 131.06 2.723 131.336 3.057 c
+131.619 3.399 131.99 3.571 132.452 3.571 c
+132.912 3.571 133.279 3.403 133.555 3.072 c
+133.838 2.748 133.985 2.3 133.996 1.734 c
+133.996 1.308 l
+133.996 0.738 133.853 0.282 133.57 -0.059 c
+133.294 -0.393 132.926 -0.559 132.467 -0.559 c
+132.005 -0.559 131.633 -0.397 131.351 -0.074 c
+131.075 0.257 130.931 0.698 130.924 1.249 c
+h
+131.571 1.308 m
+131.571 0.904 131.648 0.588 131.806 0.353 c
+131.972 0.118 132.192 0 132.467 0 c
+133.034 0 133.327 0.411 133.35 1.234 c
+133.35 1.69 l
+133.35 2.09 133.265 2.41 133.1 2.645 c
+132.942 2.888 132.725 3.013 132.452 3.013 c
+132.188 3.013 131.972 2.888 131.806 2.645 c
+131.648 2.41 131.571 2.09 131.571 1.69 c
+h
+136.421 1.69 m
+136.421 2.296 136.531 2.763 136.76 3.087 c
+136.995 3.41 137.322 3.571 137.744 3.571 c
+138.127 3.571 138.424 3.413 138.641 3.101 c
+138.641 5.159 l
+139.288 5.159 l
+139.288 -0.485 l
+138.7 -0.485 l
+138.656 -0.059 l
+138.45 -0.393 138.145 -0.559 137.744 -0.559 c
+137.333 -0.559 137.009 -0.405 136.774 -0.088 c
+136.539 0.235 136.421 0.69 136.421 1.278 c
+h
+137.069 1.308 m
+137.069 0.866 137.131 0.536 137.26 0.323 c
+137.395 0.118 137.616 0.014 137.921 0.014 c
+138.244 0.014 138.483 0.176 138.641 0.5 c
+138.641 2.513 l
+138.472 2.825 138.233 2.983 137.921 2.983 c
+137.616 2.983 137.395 2.881 137.26 2.675 c
+137.131 2.469 137.069 2.146 137.069 1.705 c
+h
+140.993 -0.485 -0.647 3.983 re
+141.037 4.542 m
+141.037 4.432 141.007 4.34 140.949 4.263 c
+140.89 4.193 140.795 4.159 140.67 4.159 c
+140.552 4.159 140.456 4.193 140.39 4.263 c
+140.331 4.34 140.302 4.432 140.302 4.542 c
+140.302 4.659 140.331 4.751 140.39 4.821 c
+140.456 4.898 140.552 4.939 140.67 4.939 c
+140.795 4.939 140.89 4.898 140.949 4.821 c
+141.007 4.74 141.037 4.648 141.037 4.542 c
+143.654 2.881 m
+143.565 2.899 143.466 2.91 143.359 2.91 c
+143.025 2.91 142.79 2.726 142.654 2.366 c
+142.654 -0.485 l
+142.007 -0.485 l
+142.007 3.498 l
+142.64 3.498 l
+142.654 3.087 l
+142.831 3.41 143.073 3.571 143.388 3.571 c
+143.496 3.571 143.583 3.549 143.654 3.513 c
+h
+145.653 -0.559 m
+145.152 -0.559 144.77 -0.412 144.506 -0.118 c
+144.242 0.176 144.109 0.61 144.109 1.19 c
+144.109 1.66 l
+144.109 2.256 144.234 2.723 144.491 3.057 c
+144.756 3.399 145.116 3.571 145.579 3.571 c
+146.039 3.571 146.38 3.417 146.608 3.116 c
+146.843 2.822 146.964 2.358 146.975 1.734 c
+146.975 1.308 l
+144.756 1.308 l
+144.756 1.219 l
+144.756 0.786 144.833 0.473 144.991 0.278 c
+145.156 0.091 145.388 0 145.682 0 c
+145.877 0 146.05 0.033 146.197 0.103 c
+146.343 0.18 146.48 0.297 146.608 0.455 c
+146.946 0.043 l
+146.659 -0.36 146.229 -0.559 145.653 -0.559 c
+145.579 3.013 m
+145.304 3.013 145.102 2.917 144.976 2.734 c
+144.848 2.547 144.774 2.256 144.756 1.866 c
+146.328 1.866 l
+146.328 1.955 l
+146.307 2.337 146.241 2.605 146.123 2.763 c
+146.006 2.929 145.821 3.013 145.579 3.013 c
+149.136 0 m
+149.349 0 149.522 0.062 149.651 0.191 c
+149.786 0.326 149.86 0.517 149.871 0.764 c
+150.488 0.764 l
+150.467 0.382 150.33 0.062 150.077 -0.192 c
+149.819 -0.437 149.507 -0.559 149.136 -0.559 c
+148.643 -0.559 148.269 -0.408 148.005 -0.103 c
+147.747 0.209 147.622 0.675 147.622 1.294 c
+147.622 1.734 l
+147.622 2.329 147.747 2.786 148.005 3.101 c
+148.269 3.413 148.643 3.571 149.136 3.571 c
+149.537 3.571 149.856 3.439 150.091 3.175 c
+150.334 2.917 150.467 2.572 150.488 2.131 c
+149.871 2.131 l
+149.849 2.425 149.775 2.645 149.651 2.792 c
+149.533 2.94 149.36 3.013 149.136 3.013 c
+148.842 3.013 148.626 2.913 148.489 2.719 c
+148.35 2.532 148.277 2.223 148.269 1.793 c
+148.269 1.278 l
+148.269 0.808 148.335 0.473 148.475 0.278 c
+148.622 0.091 148.842 0 149.136 0 c
+152.09 4.453 m
+152.09 3.498 l
+152.693 3.498 l
+152.693 2.969 l
+152.09 2.969 l
+152.09 0.5 l
+152.09 0.341 152.113 0.224 152.165 0.147 c
+152.223 0.066 152.311 0.029 152.429 0.029 c
+152.517 0.029 152.605 0.043 152.693 0.073 c
+152.693 -0.485 l
+152.547 -0.533 152.392 -0.559 152.238 -0.559 c
+151.98 -0.559 151.785 -0.468 151.65 -0.279 c
+151.51 -0.096 151.444 0.165 151.444 0.5 c
+151.444 2.969 l
+150.841 2.969 l
+150.841 3.498 l
+151.444 3.498 l
+151.444 4.453 l
+h
+153.252 1.69 m
+153.252 2.267 153.388 2.723 153.663 3.057 c
+153.946 3.399 154.318 3.571 154.781 3.571 c
+155.24 3.571 155.608 3.403 155.883 3.072 c
+156.166 2.748 156.313 2.3 156.324 1.734 c
+156.324 1.308 l
+156.324 0.738 156.181 0.282 155.897 -0.059 c
+155.622 -0.393 155.255 -0.559 154.795 -0.559 c
+154.332 -0.559 153.961 -0.397 153.678 -0.074 c
+153.403 0.257 153.26 0.698 153.252 1.249 c
+h
+153.898 1.308 m
+153.898 0.904 153.976 0.588 154.134 0.353 c
+154.299 0.118 154.519 0 154.795 0 c
+155.361 0 155.655 0.411 155.677 1.234 c
+155.677 1.69 l
+155.677 2.09 155.593 2.41 155.427 2.645 c
+155.269 2.888 155.053 3.013 154.781 3.013 c
+154.516 3.013 154.299 2.888 154.134 2.645 c
+153.976 2.41 153.898 2.09 153.898 1.69 c
+h
+158.808 2.881 m
+158.72 2.899 158.621 2.91 158.515 2.91 c
+158.18 2.91 157.944 2.726 157.809 2.366 c
+157.809 -0.485 l
+157.162 -0.485 l
+157.162 3.498 l
+157.794 3.498 l
+157.809 3.087 l
+157.985 3.41 158.228 3.571 158.544 3.571 c
+158.65 3.571 158.739 3.549 158.808 3.513 c
+h
+160.616 0.602 m
+161.337 3.498 l
+162.027 3.498 l
+160.734 -1.044 l
+160.634 -1.386 160.491 -1.646 160.308 -1.823 c
+160.131 -1.999 159.929 -2.087 159.705 -2.087 c
+159.616 -2.087 159.502 -2.066 159.367 -2.029 c
+159.367 -1.485 l
+159.514 -1.5 l
+159.697 -1.5 159.845 -1.455 159.955 -1.368 c
+160.061 -1.279 160.15 -1.121 160.219 -0.897 c
+160.337 -0.456 l
+159.176 3.498 l
+159.882 3.498 l
+h
+165.231 4.453 m
+165.231 3.498 l
+165.835 3.498 l
+165.835 2.969 l
+165.231 2.969 l
+165.231 0.5 l
+165.231 0.341 165.254 0.224 165.305 0.147 c
+165.364 0.066 165.453 0.029 165.57 0.029 c
+165.658 0.029 165.746 0.043 165.835 0.073 c
+165.835 -0.485 l
+165.688 -0.533 165.533 -0.559 165.378 -0.559 c
+165.121 -0.559 164.927 -0.468 164.79 -0.279 c
+164.651 -0.096 164.585 0.165 164.585 0.5 c
+164.585 2.969 l
+163.982 2.969 l
+163.982 3.498 l
+164.585 3.498 l
+164.585 4.453 l
+h
+168.245 2.881 m
+168.157 2.899 168.057 2.91 167.951 2.91 c
+167.616 2.91 167.381 2.726 167.246 2.366 c
+167.246 -0.485 l
+166.598 -0.485 l
+166.598 3.498 l
+167.231 3.498 l
+167.246 3.087 l
+167.422 3.41 167.664 3.571 167.98 3.571 c
+168.087 3.571 168.175 3.549 168.245 3.513 c
+h
+170.244 -0.559 m
+169.744 -0.559 169.362 -0.412 169.098 -0.118 c
+168.833 0.176 168.701 0.61 168.701 1.19 c
+168.701 1.66 l
+168.701 2.256 168.825 2.723 169.083 3.057 c
+169.347 3.399 169.708 3.571 170.17 3.571 c
+170.629 3.571 170.972 3.417 171.2 3.116 c
+171.435 2.822 171.556 2.358 171.567 1.734 c
+171.567 1.308 l
+169.347 1.308 l
+169.347 1.219 l
+169.347 0.786 169.424 0.473 169.582 0.278 c
+169.748 0.091 169.979 0 170.274 0 c
+170.469 0 170.641 0.033 170.788 0.103 c
+170.935 0.18 171.071 0.297 171.2 0.455 c
+171.537 0.043 l
+171.251 -0.36 170.821 -0.559 170.244 -0.559 c
+170.17 3.013 m
+169.895 3.013 169.692 2.917 169.568 2.734 c
+169.439 2.547 169.366 2.256 169.347 1.866 c
+170.92 1.866 l
+170.92 1.955 l
+170.898 2.337 170.832 2.605 170.714 2.763 c
+170.597 2.929 170.413 3.013 170.17 3.013 c
+173.772 -0.559 m
+173.272 -0.559 172.89 -0.412 172.626 -0.118 c
+172.36 0.176 172.229 0.61 172.229 1.19 c
+172.229 1.66 l
+172.229 2.256 172.353 2.723 172.611 3.057 c
+172.875 3.399 173.235 3.571 173.698 3.571 c
+174.157 3.571 174.5 3.417 174.727 3.116 c
+174.962 2.822 175.084 2.358 175.095 1.734 c
+175.095 1.308 l
+172.875 1.308 l
+172.875 1.219 l
+172.875 0.786 172.952 0.473 173.11 0.278 c
+173.276 0.091 173.507 0 173.802 0 c
+173.996 0 174.168 0.033 174.315 0.103 c
+174.463 0.18 174.598 0.297 174.727 0.455 c
+175.065 0.043 l
+174.779 -0.36 174.349 -0.559 173.772 -0.559 c
+173.698 3.013 m
+173.422 3.013 173.22 2.917 173.096 2.734 c
+172.967 2.547 172.894 2.256 172.875 1.866 c
+174.448 1.866 l
+174.448 1.955 l
+174.426 2.337 174.359 2.605 174.242 2.763 c
+174.124 2.929 173.941 3.013 173.698 3.013 c
+175.918 -0.133 m
+175.918 -0.015 175.951 0.081 176.021 0.161 c
+176.087 0.238 176.19 0.278 176.329 0.278 c
+176.476 0.278 176.583 0.238 176.653 0.161 c
+176.73 0.081 176.771 -0.015 176.771 -0.133 c
+176.771 -0.243 176.73 -0.335 176.653 -0.412 c
+176.583 -0.489 176.476 -0.53 176.329 -0.53 c
+176.19 -0.53 176.087 -0.489 176.021 -0.412 c
+175.951 -0.335 175.918 -0.243 175.918 -0.133 c
+f
+Q
+0.113 0.082 0.09 0 k
+287.665 261.208 234.667 -12.895 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 254.3733 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.647 -0.243 -0.775 -0.367 -0.882 c
+-0.496 -0.992 -0.658 -1.081 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.162 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.927 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.132 l
+-2.642 0.033 -2.616 -0.059 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.683 -1.992 0.69 -1.999 0.69 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.881 -2.786 0.959 -2.91 1.058 c
+-3.039 1.153 -3.142 1.278 -3.219 1.425 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.836 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.119 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.119 -1.128 3.09 -0.97 3.042 c
+-0.804 2.992 -0.669 2.917 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.252 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.352 c
+-1.294 1.311 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.319 2.385 -2.366 2.337 c
+-2.406 2.296 -2.436 2.248 -2.454 2.19 c
+-2.477 2.131 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.778 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.469 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.091 -0.86 0.176 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.529 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.53 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.66 m
+6.184 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.485 5.402 -2.396 c
+5.284 -2.315 5.185 -2.22 5.108 -2.103 c
+5.039 -1.985 4.991 -1.856 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.86 6.064 -1.941 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.058 6.681 -2.028 c
+6.758 -1.999 6.828 -1.945 6.887 -1.867 c
+6.945 -1.797 6.99 -1.706 7.019 -1.588 c
+7.056 -1.47 7.078 -1.323 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.073 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.596 4.935 -0.412 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.234 c
+4.946 1.448 5.027 1.631 5.137 1.778 c
+5.244 1.933 5.376 2.051 5.534 2.131 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.252 6.387 2.234 c
+6.483 2.212 6.571 2.179 6.652 2.131 c
+6.739 2.08 6.817 2.017 6.887 1.94 c
+6.964 1.859 7.026 1.768 7.078 1.66 c
+7.092 1.66 l
+7.092 1.808 l
+7.1 1.866 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.151 2.219 c
+8.004 2.219 l
+7.993 2.138 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.162 l
+7.975 -1.415 7.938 -1.635 7.871 -1.823 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.529 m
+7.092 0.742 7.067 0.918 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.587 c
+6.571 1.624 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.62 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.339 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.177 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.529 c
+11.036 -0.647 m
+12.168 -0.647 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.647 l
+10.124 -0.647 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.676 re
+10.124 2.836 m
+13.597 1.602 m
+13.053 1.602 l
+13.053 2.219 l
+13.641 2.219 l
+13.92 3.116 l
+14.494 3.116 l
+14.494 2.219 l
+15.728 2.219 l
+15.728 1.602 l
+14.494 1.602 l
+14.494 -0.103 l
+14.494 -0.324 l
+14.501 -0.393 14.523 -0.456 14.552 -0.515 c
+14.589 -0.566 14.645 -0.611 14.714 -0.647 c
+14.791 -0.676 14.905 -0.691 15.052 -0.691 c
+15.188 -0.691 15.324 -0.688 15.464 -0.676 c
+15.599 -0.658 15.732 -0.632 15.861 -0.603 c
+15.861 -1.205 l
+15.78 -1.216 15.703 -1.231 15.626 -1.249 c
+15.545 -1.261 15.468 -1.268 15.391 -1.279 c
+15.31 -1.286 15.221 -1.294 15.125 -1.294 c
+15.038 -1.301 14.938 -1.309 14.832 -1.309 c
+14.645 -1.309 14.483 -1.294 14.346 -1.264 c
+14.218 -1.228 14.104 -1.183 14.009 -1.132 c
+13.92 -1.085 13.847 -1.025 13.788 -0.956 c
+13.729 -0.879 13.685 -0.802 13.656 -0.721 c
+13.627 -0.632 13.604 -0.544 13.597 -0.456 c
+13.586 -0.36 13.582 -0.264 13.582 -0.177 c
+h
+24.133 1.469 m
+24.033 1.477 23.931 1.488 23.823 1.5 c
+23.713 1.517 23.592 1.529 23.456 1.529 c
+23.28 1.529 23.121 1.488 22.986 1.411 c
+22.846 1.341 22.728 1.242 22.633 1.117 c
+22.545 0.989 22.475 0.841 22.427 0.676 c
+22.387 0.507 22.369 0.33 22.369 0.147 c
+22.369 -1.264 l
+21.471 -1.264 l
+21.471 0.985 l
+21.471 1.11 21.461 1.234 21.442 1.352 c
+21.432 1.477 21.417 1.595 21.398 1.705 c
+21.388 1.822 21.373 1.918 21.355 1.999 c
+21.332 2.087 21.314 2.161 21.296 2.219 c
+22.177 2.219 l
+22.185 2.168 22.196 2.117 22.207 2.057 c
+22.225 1.999 22.24 1.933 22.251 1.866 c
+22.269 1.808 22.284 1.741 22.296 1.675 c
+22.302 1.606 22.313 1.543 22.325 1.484 c
+22.339 1.484 l
+22.375 1.602 22.427 1.708 22.486 1.808 c
+22.552 1.903 22.633 1.988 22.722 2.057 c
+22.809 2.124 22.913 2.179 23.03 2.219 c
+23.155 2.256 23.302 2.278 23.471 2.278 c
+23.596 2.278 23.713 2.271 23.823 2.263 c
+23.942 2.252 24.044 2.238 24.133 2.219 c
+h
+26.738 -1.323 m
+26.481 -1.323 26.253 -1.286 26.047 -1.22 c
+25.841 -1.143 25.665 -1.029 25.518 -0.882 c
+25.371 -0.728 25.253 -0.536 25.165 -0.309 c
+25.084 -0.085 25.047 0.18 25.047 0.484 c
+25.047 0.816 25.091 1.095 25.18 1.323 c
+25.275 1.558 25.404 1.741 25.562 1.881 c
+25.727 2.017 25.915 2.117 26.121 2.175 c
+26.327 2.242 26.535 2.278 26.753 2.278 c
+27.025 2.278 27.26 2.227 27.458 2.131 c
+27.664 2.043 27.829 1.911 27.958 1.735 c
+28.094 1.565 28.193 1.359 28.252 1.117 c
+28.318 0.881 28.355 0.617 28.355 0.324 c
+28.355 0.309 l
+25.988 0.309 l
+25.988 0.162 26.003 0.022 26.032 -0.103 c
+26.069 -0.231 26.124 -0.345 26.194 -0.441 c
+26.26 -0.53 26.344 -0.599 26.444 -0.647 c
+26.539 -0.698 26.653 -0.721 26.782 -0.721 c
+26.936 -0.721 27.076 -0.688 27.194 -0.617 c
+27.318 -0.551 27.407 -0.449 27.458 -0.309 c
+28.296 -0.382 l
+28.266 -0.482 28.212 -0.588 28.135 -0.706 c
+28.054 -0.816 27.95 -0.919 27.825 -1.014 c
+27.708 -1.103 27.553 -1.176 27.37 -1.235 c
+27.194 -1.294 26.98 -1.323 26.738 -1.323 c
+26.738 1.705 m
+26.649 1.705 26.562 1.691 26.473 1.66 c
+26.385 1.631 26.304 1.58 26.238 1.514 c
+26.169 1.444 26.109 1.356 26.061 1.249 c
+26.021 1.139 26.003 1.014 26.003 0.867 c
+27.472 0.867 l
+27.472 1.003 27.447 1.124 27.399 1.234 c
+27.359 1.341 27.304 1.429 27.237 1.5 c
+27.179 1.565 27.106 1.617 27.017 1.646 c
+26.929 1.683 26.834 1.705 26.738 1.705 c
+32.342 -0.25 m
+32.342 -0.419 32.301 -0.57 32.224 -0.706 c
+32.154 -0.834 32.052 -0.948 31.916 -1.044 c
+31.787 -1.132 31.625 -1.202 31.43 -1.249 c
+31.243 -1.297 31.027 -1.323 30.784 -1.323 c
+30.556 -1.323 30.358 -1.309 30.181 -1.279 c
+30.005 -1.249 29.847 -1.202 29.71 -1.132 c
+29.571 -1.055 29.461 -0.956 29.373 -0.838 c
+29.284 -0.721 29.215 -0.574 29.167 -0.397 c
+29.976 -0.279 l
+29.994 -0.379 30.023 -0.456 30.063 -0.515 c
+30.111 -0.574 30.17 -0.617 30.24 -0.647 c
+30.306 -0.676 30.387 -0.702 30.475 -0.721 c
+30.564 -0.732 30.666 -0.735 30.784 -0.735 c
+30.879 -0.735 30.975 -0.732 31.063 -0.721 c
+31.152 -0.702 31.229 -0.676 31.298 -0.647 c
+31.364 -0.617 31.416 -0.58 31.445 -0.53 c
+31.482 -0.482 31.504 -0.419 31.504 -0.339 c
+31.504 -0.243 31.474 -0.169 31.416 -0.118 c
+31.364 -0.07 31.298 -0.029 31.21 0 c
+31.122 0.037 31.011 0.066 30.886 0.088 c
+30.769 0.118 30.637 0.147 30.489 0.176 c
+30.35 0.213 30.211 0.253 30.063 0.294 c
+29.924 0.341 29.799 0.405 29.681 0.484 c
+29.571 0.562 29.483 0.661 29.417 0.779 c
+29.347 0.896 29.313 1.047 29.313 1.234 c
+29.313 1.389 29.344 1.532 29.402 1.66 c
+29.468 1.797 29.564 1.911 29.681 1.999 c
+29.806 2.087 29.964 2.153 30.152 2.205 c
+30.335 2.252 30.549 2.278 30.784 2.278 c
+30.967 2.278 31.144 2.256 31.313 2.219 c
+31.478 2.19 31.625 2.135 31.754 2.057 c
+31.879 1.988 31.989 1.889 32.077 1.764 c
+32.166 1.646 32.224 1.502 32.253 1.338 c
+31.46 1.264 l
+31.438 1.341 31.408 1.404 31.372 1.455 c
+31.331 1.514 31.283 1.558 31.225 1.587 c
+31.173 1.624 31.111 1.65 31.034 1.66 c
+30.953 1.668 30.872 1.675 30.784 1.675 c
+30.567 1.675 30.406 1.646 30.298 1.587 c
+30.188 1.536 30.137 1.448 30.137 1.323 c
+30.137 1.242 30.155 1.18 30.196 1.132 c
+30.244 1.08 30.306 1.043 30.387 1.014 c
+30.475 0.985 30.57 0.955 30.681 0.926 c
+30.788 0.904 30.909 0.881 31.048 0.852 c
+31.202 0.823 31.361 0.783 31.519 0.735 c
+31.673 0.683 31.813 0.621 31.931 0.544 c
+32.048 0.463 32.143 0.36 32.224 0.235 c
+32.301 0.106 32.342 -0.056 32.342 -0.25 c
+34.859 -1.323 m
+34.602 -1.323 34.374 -1.286 34.169 -1.22 c
+33.963 -1.143 33.786 -1.029 33.639 -0.882 c
+33.492 -0.728 33.375 -0.536 33.286 -0.309 c
+33.205 -0.085 33.169 0.18 33.169 0.484 c
+33.169 0.816 33.213 1.095 33.301 1.323 c
+33.396 1.558 33.525 1.741 33.683 1.881 c
+33.849 2.017 34.036 2.117 34.242 2.175 c
+34.447 2.242 34.657 2.278 34.874 2.278 c
+35.146 2.278 35.381 2.227 35.58 2.131 c
+35.785 2.043 35.95 1.911 36.079 1.735 c
+36.215 1.565 36.314 1.359 36.373 1.117 c
+36.44 0.881 36.476 0.617 36.476 0.324 c
+36.476 0.309 l
+34.109 0.309 l
+34.109 0.162 34.124 0.022 34.154 -0.103 c
+34.19 -0.231 34.246 -0.345 34.315 -0.441 c
+34.381 -0.53 34.466 -0.599 34.565 -0.647 c
+34.661 -0.698 34.774 -0.721 34.903 -0.721 c
+35.058 -0.721 35.197 -0.688 35.314 -0.617 c
+35.44 -0.551 35.528 -0.449 35.58 -0.309 c
+36.417 -0.382 l
+36.388 -0.482 36.332 -0.588 36.255 -0.706 c
+36.174 -0.816 36.072 -0.919 35.947 -1.014 c
+35.829 -1.103 35.675 -1.176 35.491 -1.235 c
+35.314 -1.294 35.102 -1.323 34.859 -1.323 c
+34.859 1.705 m
+34.771 1.705 34.682 1.691 34.595 1.66 c
+34.506 1.631 34.425 1.58 34.36 1.514 c
+34.29 1.444 34.231 1.356 34.183 1.249 c
+34.142 1.139 34.124 1.014 34.124 0.867 c
+35.594 0.867 l
+35.594 1.003 35.568 1.124 35.52 1.234 c
+35.48 1.341 35.425 1.429 35.359 1.5 c
+35.3 1.565 35.227 1.617 35.138 1.646 c
+35.05 1.683 34.955 1.705 34.859 1.705 c
+37.968 1.602 m
+37.424 1.602 l
+37.424 2.219 l
+38.012 2.219 l
+38.291 3.116 l
+38.865 3.116 l
+38.865 2.219 l
+40.099 2.219 l
+40.099 1.602 l
+38.865 1.602 l
+38.865 -0.103 l
+38.865 -0.324 l
+38.872 -0.393 38.894 -0.456 38.923 -0.515 c
+38.96 -0.566 39.015 -0.611 39.085 -0.647 c
+39.162 -0.676 39.276 -0.691 39.424 -0.691 c
+39.559 -0.691 39.695 -0.688 39.835 -0.676 c
+39.971 -0.658 40.103 -0.632 40.232 -0.603 c
+40.232 -1.205 l
+40.151 -1.216 40.074 -1.231 39.996 -1.249 c
+39.916 -1.261 39.838 -1.268 39.761 -1.279 c
+39.68 -1.286 39.592 -1.294 39.497 -1.294 c
+39.409 -1.301 39.309 -1.309 39.202 -1.309 c
+39.015 -1.309 38.853 -1.294 38.718 -1.264 c
+38.589 -1.228 38.475 -1.183 38.379 -1.132 c
+38.291 -1.085 38.218 -1.025 38.159 -0.956 c
+38.1 -0.879 38.056 -0.802 38.027 -0.721 c
+37.997 -0.632 37.975 -0.544 37.968 -0.456 c
+37.957 -0.36 37.953 -0.264 37.953 -0.177 c
+h
+46.236 -2.631 m
+46.236 3.513 l
+48.162 3.513 l
+48.162 2.896 l
+47.089 2.896 l
+47.089 -2.014 l
+48.162 -2.014 l
+48.162 -2.631 l
+h
+51.193 1.602 m
+51.193 -1.264 l
+50.297 -1.264 l
+50.297 1.602 l
+49.473 1.602 l
+49.473 2.219 l
+50.297 2.219 l
+50.297 2.484 l
+50.297 2.609 50.312 2.741 50.341 2.881 c
+50.378 3.017 50.447 3.135 50.547 3.233 c
+50.653 3.341 50.796 3.428 50.973 3.499 c
+51.149 3.564 51.374 3.601 51.649 3.601 c
+51.862 3.601 52.061 3.59 52.237 3.572 c
+52.413 3.549 52.564 3.532 52.693 3.513 c
+52.693 2.925 l
+52.564 2.944 52.421 2.958 52.267 2.969 c
+52.108 2.976 51.958 2.984 51.81 2.984 c
+51.682 2.984 51.579 2.969 51.502 2.94 c
+51.421 2.911 51.359 2.87 51.311 2.822 c
+51.26 2.77 51.226 2.708 51.208 2.631 c
+51.197 2.561 51.193 2.484 51.193 2.396 c
+51.193 2.219 l
+52.619 2.219 l
+52.619 1.602 l
+h
+55.71 -0.647 m
+56.841 -0.647 l
+56.841 -1.264 l
+53.535 -1.264 l
+53.535 -0.647 l
+54.798 -0.647 l
+54.798 1.602 l
+53.872 1.602 l
+53.872 2.219 l
+55.71 2.219 l
+h
+54.798 3.513 0.912 -0.676 re
+54.798 2.836 m
+59.774 -0.647 m
+60.905 -0.647 l
+60.905 -1.264 l
+57.599 -1.264 l
+57.599 -0.647 l
+58.863 -0.647 l
+58.863 2.896 l
+57.936 2.896 l
+57.936 3.513 l
+59.774 3.513 l
+h
+63.291 -1.323 m
+63.033 -1.323 62.806 -1.286 62.6 -1.22 c
+62.394 -1.143 62.218 -1.029 62.071 -0.882 c
+61.923 -0.728 61.807 -0.536 61.718 -0.309 c
+61.637 -0.085 61.601 0.18 61.601 0.484 c
+61.601 0.816 61.645 1.095 61.732 1.323 c
+61.828 1.558 61.957 1.741 62.115 1.881 c
+62.28 2.017 62.468 2.117 62.673 2.175 c
+62.879 2.242 63.089 2.278 63.305 2.278 c
+63.577 2.278 63.812 2.227 64.011 2.131 c
+64.217 2.043 64.382 1.911 64.51 1.735 c
+64.647 1.565 64.745 1.359 64.805 1.117 c
+64.871 0.881 64.907 0.617 64.907 0.324 c
+64.907 0.309 l
+62.541 0.309 l
+62.541 0.162 62.555 0.022 62.586 -0.103 c
+62.622 -0.231 62.677 -0.345 62.747 -0.441 c
+62.813 -0.53 62.898 -0.599 62.997 -0.647 c
+63.093 -0.698 63.206 -0.721 63.334 -0.721 c
+63.49 -0.721 63.629 -0.688 63.746 -0.617 c
+63.871 -0.551 63.96 -0.449 64.011 -0.309 c
+64.849 -0.382 l
+64.82 -0.482 64.764 -0.588 64.687 -0.706 c
+64.606 -0.816 64.504 -0.919 64.379 -1.014 c
+64.261 -1.103 64.107 -1.176 63.923 -1.235 c
+63.746 -1.294 63.533 -1.323 63.291 -1.323 c
+63.291 1.705 m
+63.203 1.705 63.114 1.691 63.026 1.66 c
+62.938 1.631 62.857 1.58 62.791 1.514 c
+62.721 1.444 62.663 1.356 62.615 1.249 c
+62.574 1.139 62.555 1.014 62.555 0.867 c
+64.026 0.867 l
+64.026 1.003 64 1.124 63.952 1.234 c
+63.912 1.341 63.856 1.429 63.791 1.5 c
+63.731 1.565 63.658 1.617 63.57 1.646 c
+63.482 1.683 63.386 1.705 63.291 1.705 c
+66.16 -2.631 m
+66.16 -2.014 l
+67.234 -2.014 l
+67.234 2.896 l
+66.16 2.896 l
+66.16 3.513 l
+68.086 3.513 l
+68.086 -2.631 l
+h
+f
+Q
+q 1 0 0 1 371.3314 238.8802 cm
+0 0 m
+-0.118 -0.147 l
+-0.452 -0.54 -0.948 -0.735 -1.602 -0.735 c
+-2.183 -0.735 -2.638 -0.544 -2.969 -0.162 c
+-3.293 0.22 -3.461 0.765 -3.469 1.47 c
+-3.469 2.514 l
+-3.469 3.267 -3.322 3.829 -3.027 4.204 c
+-2.726 4.575 -2.275 4.763 -1.675 4.763 c
+-1.168 4.763 -0.771 4.619 -0.484 4.336 c
+-0.191 4.05 -0.029 3.645 0 3.117 c
+-0.675 3.117 l
+-0.698 3.447 -0.79 3.707 -0.955 3.896 c
+-1.113 4.09 -1.348 4.189 -1.66 4.189 c
+-2.054 4.189 -2.337 4.06 -2.514 3.807 c
+-2.69 3.55 -2.786 3.15 -2.792 2.602 c
+-2.792 1.514 l
+-2.792 0.974 -2.69 0.559 -2.484 0.264 c
+-2.278 -0.022 -1.984 -0.162 -1.602 -0.162 c
+-1.242 -0.162 -0.962 -0.073 -0.764 0.103 c
+-0.675 0.191 l
+-0.675 1.426 l
+-1.646 1.426 l
+-1.646 1.999 l
+0 1.999 l
+h
+2.44 -0.735 m
+1.941 -0.735 1.558 -0.588 1.294 -0.294 c
+1.029 0 0.897 0.434 0.897 1.014 c
+0.897 1.484 l
+0.897 2.08 1.022 2.547 1.279 2.882 c
+1.544 3.223 1.904 3.395 2.367 3.395 c
+2.826 3.395 3.167 3.241 3.396 2.94 c
+3.631 2.646 3.753 2.183 3.763 1.558 c
+3.763 1.132 l
+1.544 1.132 l
+1.544 1.043 l
+1.544 0.611 1.621 0.297 1.779 0.103 c
+1.944 -0.085 2.176 -0.176 2.469 -0.176 c
+2.664 -0.176 2.837 -0.143 2.984 -0.073 c
+3.131 0.004 3.267 0.121 3.396 0.279 c
+3.734 -0.133 l
+3.447 -0.536 3.017 -0.735 2.44 -0.735 c
+2.367 2.837 m
+2.091 2.837 1.889 2.741 1.764 2.558 c
+1.636 2.371 1.562 2.08 1.544 1.691 c
+3.117 1.691 l
+3.117 1.779 l
+3.094 2.161 3.028 2.429 2.911 2.587 c
+2.793 2.753 2.61 2.837 2.367 2.837 c
+5.395 4.278 m
+5.395 3.322 l
+5.997 3.322 l
+5.997 2.793 l
+5.395 2.793 l
+5.395 0.324 l
+5.395 0.166 5.417 0.048 5.469 -0.029 c
+5.527 -0.11 5.615 -0.147 5.733 -0.147 c
+5.821 -0.147 5.91 -0.133 5.997 -0.103 c
+5.997 -0.661 l
+5.85 -0.709 5.696 -0.735 5.542 -0.735 c
+5.284 -0.735 5.089 -0.643 4.954 -0.455 c
+4.814 -0.272 4.748 -0.011 4.748 0.324 c
+4.748 2.793 l
+4.145 2.793 l
+4.145 3.322 l
+4.748 3.322 l
+4.748 4.278 l
+h
+8.658 -0.661 m
+8.658 2.793 l
+8.143 2.793 l
+8.143 3.322 l
+8.658 3.322 l
+8.658 3.69 l
+8.665 4.12 8.779 4.453 8.996 4.689 c
+9.22 4.931 9.533 5.056 9.937 5.056 c
+10.084 5.056 10.223 5.035 10.363 4.998 c
+10.51 4.958 10.66 4.902 10.819 4.836 c
+10.701 4.262 l
+10.466 4.388 10.223 4.453 9.981 4.453 c
+9.735 4.453 9.562 4.384 9.467 4.248 c
+9.367 4.12 9.319 3.925 9.319 3.66 c
+9.319 3.322 l
+9.966 3.322 l
+9.966 2.793 l
+9.319 2.793 l
+9.319 -0.661 l
+h
+11.127 -0.661 -0.646 3.983 re
+12.877 -0.661 -0.647 5.644 re
+15.317 -0.735 m
+14.817 -0.735 14.435 -0.588 14.17 -0.294 c
+13.906 0 13.773 0.434 13.773 1.014 c
+13.773 1.484 l
+13.773 2.08 13.898 2.547 14.155 2.882 c
+14.42 3.223 14.78 3.395 15.243 3.395 c
+15.703 3.395 16.044 3.241 16.272 2.94 c
+16.507 2.646 16.629 2.183 16.64 1.558 c
+16.64 1.132 l
+14.42 1.132 l
+14.42 1.043 l
+14.42 0.611 14.497 0.297 14.655 0.103 c
+14.82 -0.085 15.052 -0.176 15.346 -0.176 c
+15.541 -0.176 15.713 -0.143 15.861 -0.073 c
+16.008 0.004 16.143 0.121 16.272 0.279 c
+16.61 -0.133 l
+16.324 -0.536 15.894 -0.735 15.317 -0.735 c
+15.243 2.837 m
+14.967 2.837 14.766 2.741 14.641 2.558 c
+14.512 2.371 14.438 2.08 14.42 1.691 c
+15.993 1.691 l
+15.993 1.779 l
+15.971 2.161 15.904 2.429 15.787 2.587 c
+15.669 2.753 15.486 2.837 15.243 2.837 c
+22.019 1.132 m
+22.019 0.515 21.905 0.048 21.681 -0.264 c
+21.465 -0.58 21.141 -0.735 20.711 -0.735 c
+20.289 -0.735 19.977 -0.555 19.771 -0.191 c
+19.741 -0.661 l
+19.138 -0.661 l
+19.138 4.983 l
+19.786 4.983 l
+19.786 2.882 l
+19.998 3.223 20.307 3.395 20.711 3.395 c
+21.141 3.395 21.465 3.237 21.681 2.925 c
+21.905 2.62 22.019 2.153 22.019 1.529 c
+h
+21.373 1.514 m
+21.373 1.984 21.303 2.315 21.167 2.514 c
+21.039 2.708 20.829 2.807 20.534 2.807 c
+20.201 2.807 19.95 2.624 19.786 2.263 c
+19.786 0.382 l
+19.95 0.019 20.204 -0.162 20.549 -0.162 c
+20.843 -0.162 21.053 -0.058 21.182 0.147 c
+21.307 0.353 21.373 0.669 21.373 1.103 c
+h
+24.9 -0.661 m
+24.86 -0.573 24.835 -0.426 24.827 -0.22 c
+24.592 -0.565 24.297 -0.735 23.945 -0.735 c
+23.582 -0.735 23.298 -0.64 23.092 -0.441 c
+22.894 -0.235 22.799 0.052 22.799 0.426 c
+22.799 0.827 22.934 1.147 23.21 1.382 c
+23.482 1.625 23.857 1.749 24.328 1.749 c
+24.812 1.749 l
+24.812 2.176 l
+24.812 2.411 24.757 2.576 24.65 2.675 c
+24.54 2.782 24.378 2.837 24.166 2.837 c
+23.967 2.837 23.805 2.778 23.68 2.66 c
+23.563 2.543 23.504 2.396 23.504 2.219 c
+22.857 2.219 l
+22.857 2.414 22.916 2.606 23.034 2.793 c
+23.158 2.977 23.32 3.123 23.518 3.234 c
+23.724 3.341 23.952 3.395 24.21 3.395 c
+24.61 3.395 24.915 3.293 25.121 3.087 c
+25.334 2.882 25.448 2.587 25.459 2.205 c
+25.459 0.191 l
+25.459 -0.114 25.496 -0.378 25.577 -0.603 c
+25.577 -0.661 l
+h
+24.033 -0.147 m
+24.199 -0.147 24.349 -0.103 24.489 -0.015 c
+24.636 0.073 24.742 0.183 24.812 0.324 c
+24.812 1.264 l
+24.445 1.264 l
+24.129 1.264 23.886 1.195 23.709 1.058 c
+23.534 0.929 23.445 0.742 23.445 0.5 c
+23.445 0.272 23.489 0.106 23.578 0 c
+23.665 -0.099 23.817 -0.147 24.033 -0.147 c
+27.84 -0.176 m
+28.054 -0.176 28.226 -0.114 28.355 0.015 c
+28.49 0.151 28.565 0.342 28.575 0.588 c
+29.193 0.588 l
+29.17 0.206 29.035 -0.114 28.781 -0.368 c
+28.524 -0.613 28.212 -0.735 27.84 -0.735 c
+27.348 -0.735 26.973 -0.584 26.709 -0.279 c
+26.451 0.033 26.327 0.5 26.327 1.118 c
+26.327 1.558 l
+26.327 2.153 26.451 2.61 26.709 2.925 c
+26.973 3.237 27.348 3.395 27.84 3.395 c
+28.241 3.395 28.561 3.263 28.796 2.999 c
+29.038 2.741 29.17 2.396 29.193 1.955 c
+28.575 1.955 l
+28.553 2.249 28.48 2.469 28.355 2.616 c
+28.237 2.764 28.064 2.837 27.84 2.837 c
+27.547 2.837 27.329 2.738 27.193 2.543 c
+27.054 2.356 26.98 2.047 26.973 1.617 c
+26.973 1.103 l
+26.973 0.632 27.039 0.297 27.179 0.103 c
+27.326 -0.085 27.547 -0.176 27.84 -0.176 c
+30.942 1.161 m
+30.604 0.765 l
+30.604 -0.661 l
+29.942 -0.661 l
+29.942 4.983 l
+30.604 4.983 l
+30.604 1.602 l
+31.838 3.322 l
+32.617 3.322 l
+31.353 1.661 l
+32.779 -0.661 l
+32.029 -0.661 l
+h
+35.351 -0.661 m
+35.351 2.793 l
+34.822 2.793 l
+34.822 3.322 l
+35.351 3.322 l
+35.351 3.778 l
+35.351 4.178 35.447 4.491 35.646 4.719 c
+35.852 4.943 36.13 5.056 36.484 5.056 c
+36.619 5.056 36.752 5.035 36.88 4.998 c
+36.851 4.453 l
+36.752 4.472 36.652 4.484 36.557 4.484 c
+36.182 4.484 35.998 4.218 35.998 3.69 c
+35.998 3.322 l
+36.675 3.322 l
+36.675 2.793 l
+35.998 2.793 l
+35.998 -0.661 l
+h
+39.085 2.705 m
+38.996 2.723 38.898 2.734 38.791 2.734 c
+38.456 2.734 38.221 2.55 38.086 2.19 c
+38.086 -0.661 l
+37.439 -0.661 l
+37.439 3.322 l
+38.071 3.322 l
+38.086 2.911 l
+38.262 3.234 38.504 3.395 38.821 3.395 c
+38.927 3.395 39.015 3.373 39.085 3.337 c
+h
+39.526 1.514 m
+39.526 2.091 39.662 2.547 39.937 2.882 c
+40.22 3.223 40.592 3.395 41.055 3.395 c
+41.514 3.395 41.882 3.227 42.157 2.896 c
+42.44 2.572 42.587 2.124 42.599 1.558 c
+42.599 1.132 l
+42.599 0.563 42.455 0.106 42.171 -0.235 c
+41.896 -0.569 41.529 -0.735 41.069 -0.735 c
+40.606 -0.735 40.235 -0.573 39.952 -0.25 c
+39.677 0.081 39.534 0.522 39.526 1.073 c
+h
+40.172 1.132 m
+40.172 0.728 40.25 0.412 40.408 0.177 c
+40.573 -0.058 40.794 -0.176 41.069 -0.176 c
+41.635 -0.176 41.93 0.235 41.951 1.058 c
+41.951 1.514 l
+41.951 1.914 41.867 2.234 41.701 2.469 c
+41.543 2.712 41.327 2.837 41.055 2.837 c
+40.79 2.837 40.573 2.712 40.408 2.469 c
+40.25 2.234 40.172 1.914 40.172 1.514 c
+h
+44.053 3.322 m
+44.068 2.955 l
+44.311 3.248 44.631 3.395 45.024 3.395 c
+45.464 3.395 45.773 3.198 45.949 2.807 c
+46.203 3.198 46.552 3.395 46.993 3.395 c
+47.728 3.395 48.103 2.932 48.124 2.014 c
+48.124 -0.661 l
+47.478 -0.661 l
+47.478 1.955 l
+47.478 2.249 47.423 2.462 47.316 2.602 c
+47.218 2.738 47.044 2.807 46.802 2.807 c
+46.603 2.807 46.441 2.727 46.317 2.572 c
+46.2 2.425 46.129 2.234 46.111 1.999 c
+46.111 -0.661 l
+45.45 -0.661 l
+45.45 1.984 l
+45.45 2.532 45.229 2.807 44.789 2.807 c
+44.454 2.807 44.219 2.646 44.083 2.323 c
+44.083 -0.661 l
+43.436 -0.661 l
+43.436 3.322 l
+h
+f
+Q
+q 1 0 0 1 423.8077 239.2923 cm
+0 0 m
+0 0.087 -0.044 0.165 -0.133 0.235 c
+-0.221 0.312 -0.408 0.415 -0.691 0.544 c
+-1.125 0.72 -1.422 0.9 -1.588 1.088 c
+-1.746 1.271 -1.823 1.502 -1.823 1.778 c
+-1.823 2.119 -1.702 2.403 -1.455 2.63 c
+-1.202 2.865 -0.864 2.983 -0.441 2.983 c
+-0.011 2.983 0.338 2.869 0.602 2.645 c
+0.866 2.418 0.999 2.117 0.999 1.734 c
+-0.044 1.734 l
+-0.044 2.057 -0.184 2.219 -0.456 2.219 c
+-0.566 2.219 -0.655 2.183 -0.721 2.117 c
+-0.79 2.046 -0.824 1.947 -0.824 1.822 c
+-0.824 1.734 -0.786 1.653 -0.706 1.587 c
+-0.628 1.529 -0.449 1.433 -0.162 1.308 c
+0.268 1.15 0.565 0.974 0.735 0.779 c
+0.911 0.591 0.999 0.341 0.999 0.029 c
+0.999 -0.324 0.866 -0.611 0.602 -0.823 c
+0.338 -1.04 -0.011 -1.147 -0.441 -1.147 c
+-0.736 -1.147 -0.996 -1.092 -1.22 -0.985 c
+-1.449 -0.867 -1.625 -0.706 -1.75 -0.5 c
+-1.867 -0.294 -1.926 -0.074 -1.926 0.161 c
+-0.941 0.161 l
+-0.941 -0.026 -0.904 -0.162 -0.824 -0.25 c
+-0.736 -0.339 -0.603 -0.383 -0.427 -0.383 c
+-0.144 -0.383 0 -0.258 0 0 c
+2.866 3.881 m
+2.866 2.91 l
+3.395 2.91 l
+3.395 2.117 l
+2.866 2.117 l
+2.866 0.147 l
+2.866 -0.011 2.884 -0.118 2.925 -0.177 c
+2.973 -0.235 3.057 -0.265 3.174 -0.265 c
+3.281 -0.265 3.366 -0.258 3.424 -0.235 c
+3.424 -1.044 l
+3.248 -1.11 3.057 -1.147 2.851 -1.147 c
+2.175 -1.147 1.83 -0.761 1.822 0.014 c
+1.822 2.117 l
+1.367 2.117 l
+1.367 2.91 l
+1.822 2.91 l
+1.822 3.881 l
+h
+5.85 -1.073 m
+5.82 -1.015 5.791 -0.912 5.761 -0.765 c
+5.574 -1.022 5.325 -1.147 5.012 -1.147 c
+4.677 -1.147 4.398 -1.04 4.174 -0.823 c
+3.958 -0.599 3.85 -0.309 3.85 0.043 c
+3.85 0.455 3.983 0.771 4.247 0.999 c
+4.512 1.234 4.895 1.352 5.394 1.352 c
+5.718 1.352 l
+5.718 1.675 l
+5.718 1.851 5.681 1.973 5.614 2.042 c
+5.556 2.119 5.468 2.16 5.35 2.16 c
+5.093 2.16 4.968 2.006 4.968 1.705 c
+3.924 1.705 l
+3.924 2.076 4.06 2.381 4.336 2.616 c
+4.608 2.859 4.957 2.983 5.379 2.983 c
+5.82 2.983 6.158 2.865 6.393 2.63 c
+6.636 2.403 6.761 2.08 6.761 1.66 c
+6.761 -0.206 l
+6.761 -0.551 6.809 -0.82 6.908 -1.015 c
+6.908 -1.073 l
+h
+5.247 -0.324 m
+5.354 -0.324 5.446 -0.306 5.526 -0.265 c
+5.614 -0.217 5.677 -0.158 5.718 -0.088 c
+5.718 0.735 l
+5.468 0.735 l
+5.291 0.735 5.148 0.675 5.041 0.558 c
+4.942 0.448 4.895 0.301 4.895 0.118 c
+4.895 -0.177 5.012 -0.324 5.247 -0.324 c
+7.378 1.043 m
+7.378 1.69 7.496 2.175 7.731 2.499 c
+7.966 2.822 8.297 2.983 8.731 2.983 c
+9.084 2.983 9.356 2.84 9.554 2.557 c
+9.598 2.91 l
+10.539 2.91 l
+10.539 -1.073 l
+10.539 -1.58 10.395 -1.97 10.113 -2.234 c
+9.826 -2.506 9.422 -2.646 8.893 -2.646 c
+8.664 -2.646 8.429 -2.602 8.187 -2.514 c
+7.952 -2.426 7.775 -2.311 7.658 -2.176 c
+8.01 -1.455 l
+8.106 -1.563 8.234 -1.646 8.392 -1.706 c
+8.547 -1.771 8.694 -1.808 8.834 -1.808 c
+9.069 -1.808 9.234 -1.75 9.333 -1.632 c
+9.44 -1.522 9.495 -1.345 9.495 -1.103 c
+9.495 -0.75 l
+9.296 -1.015 9.04 -1.147 8.716 -1.147 c
+8.294 -1.147 7.966 -0.985 7.731 -0.662 c
+7.503 -0.331 7.386 0.139 7.378 0.749 c
+h
+8.422 0.779 m
+8.422 0.404 8.469 0.135 8.569 -0.03 c
+8.664 -0.198 8.819 -0.279 9.025 -0.279 c
+9.238 -0.279 9.396 -0.202 9.495 -0.044 c
+9.495 1.851 l
+9.385 2.017 9.231 2.102 9.025 2.102 c
+8.819 2.102 8.664 2.017 8.569 1.851 c
+8.469 1.683 8.422 1.414 8.422 1.043 c
+h
+12.39 -1.073 -1.043 3.983 re
+11.303 3.939 m
+11.303 4.093 11.351 4.222 11.45 4.321 c
+11.557 4.428 11.692 4.483 11.862 4.483 c
+12.038 4.483 12.174 4.428 12.273 4.321 c
+12.38 4.222 12.435 4.093 12.435 3.939 c
+12.435 3.77 12.38 3.634 12.273 3.528 c
+12.174 3.428 12.038 3.38 11.862 3.38 c
+11.692 3.38 11.557 3.428 11.45 3.528 c
+11.351 3.634 11.303 3.77 11.303 3.939 c
+14.154 2.91 m
+14.184 2.513 l
+14.42 2.825 14.721 2.983 15.095 2.983 c
+15.779 2.983 16.132 2.502 16.153 1.543 c
+16.153 -1.073 l
+15.11 -1.073 l
+15.11 1.469 l
+15.11 1.693 15.073 1.855 15.008 1.955 c
+14.937 2.05 14.819 2.102 14.655 2.102 c
+14.467 2.102 14.32 2.006 14.214 1.822 c
+14.214 -1.073 l
+13.17 -1.073 l
+13.17 2.91 l
+h
+16.771 1.043 m
+16.771 1.69 16.889 2.175 17.124 2.499 c
+17.359 2.822 17.69 2.983 18.123 2.983 c
+18.476 2.983 18.748 2.84 18.947 2.557 c
+18.991 2.91 l
+19.931 2.91 l
+19.931 -1.073 l
+19.931 -1.58 19.788 -1.97 19.505 -2.234 c
+19.218 -2.506 18.815 -2.646 18.285 -2.646 c
+18.057 -2.646 17.822 -2.602 17.58 -2.514 c
+17.344 -2.426 17.168 -2.311 17.05 -2.176 c
+17.404 -1.455 l
+17.499 -1.563 17.628 -1.646 17.786 -1.706 c
+17.94 -1.771 18.087 -1.808 18.226 -1.808 c
+18.461 -1.808 18.627 -1.75 18.726 -1.632 c
+18.833 -1.522 18.888 -1.345 18.888 -1.103 c
+18.888 -0.75 l
+18.69 -1.015 18.432 -1.147 18.109 -1.147 c
+17.686 -1.147 17.359 -0.985 17.124 -0.662 c
+16.896 -0.331 16.778 0.139 16.771 0.749 c
+h
+17.815 0.779 m
+17.815 0.404 17.863 0.135 17.962 -0.03 c
+18.057 -0.198 18.212 -0.279 18.418 -0.279 c
+18.63 -0.279 18.788 -0.202 18.888 -0.044 c
+18.888 1.851 l
+18.777 2.017 18.623 2.102 18.418 2.102 c
+18.212 2.102 18.057 2.017 17.962 1.851 c
+17.863 1.683 17.815 1.414 17.815 1.043 c
+h
+f
+Q
+q 1 0 0 1 448.3695 238.2189 cm
+0 0 m
+-0.04 0.088 -0.066 0.235 -0.073 0.441 c
+-0.309 0.096 -0.603 -0.073 -0.956 -0.073 c
+-1.319 -0.073 -1.602 0.022 -1.808 0.22 c
+-2.007 0.426 -2.103 0.713 -2.103 1.087 c
+-2.103 1.488 -1.966 1.808 -1.691 2.043 c
+-1.419 2.286 -1.043 2.41 -0.573 2.41 c
+-0.088 2.41 l
+-0.088 2.837 l
+-0.088 3.072 -0.143 3.237 -0.25 3.337 c
+-0.36 3.443 -0.522 3.499 -0.735 3.499 c
+-0.933 3.499 -1.095 3.439 -1.22 3.322 c
+-1.338 3.204 -1.397 3.057 -1.397 2.881 c
+-2.043 2.881 l
+-2.043 3.075 -1.984 3.267 -1.867 3.454 c
+-1.742 3.638 -1.58 3.785 -1.382 3.896 c
+-1.176 4.002 -0.948 4.056 -0.691 4.056 c
+-0.291 4.056 0.014 3.954 0.22 3.748 c
+0.434 3.543 0.548 3.248 0.559 2.866 c
+0.559 0.852 l
+0.559 0.548 0.595 0.283 0.676 0.058 c
+0.676 0 l
+h
+-0.867 0.515 m
+-0.702 0.515 -0.551 0.559 -0.412 0.646 c
+-0.264 0.735 -0.158 0.845 -0.088 0.985 c
+-0.088 1.926 l
+-0.456 1.926 l
+-0.771 1.926 -1.014 1.856 -1.191 1.72 c
+-1.367 1.591 -1.455 1.404 -1.455 1.161 c
+-1.455 0.933 -1.411 0.768 -1.323 0.661 c
+-1.235 0.563 -1.084 0.515 -0.867 0.515 c
+3.204 3.366 m
+3.116 3.385 3.017 3.395 2.911 3.395 c
+2.576 3.395 2.341 3.212 2.205 2.851 c
+2.205 0 l
+1.558 0 l
+1.558 3.983 l
+2.19 3.983 l
+2.205 3.572 l
+2.381 3.896 2.624 4.056 2.94 4.056 c
+3.046 4.056 3.135 4.035 3.204 3.998 c
+h
+5.203 -0.073 m
+4.704 -0.073 4.322 0.073 4.056 0.368 c
+3.792 0.661 3.66 1.095 3.66 1.675 c
+3.66 2.146 l
+3.66 2.741 3.785 3.208 4.042 3.543 c
+4.307 3.884 4.667 4.056 5.13 4.056 c
+5.589 4.056 5.931 3.902 6.159 3.601 c
+6.394 3.308 6.516 2.844 6.526 2.219 c
+6.526 1.793 l
+4.307 1.793 l
+4.307 1.705 l
+4.307 1.272 4.384 0.959 4.542 0.764 c
+4.707 0.577 4.939 0.485 5.232 0.485 c
+5.427 0.485 5.6 0.518 5.747 0.588 c
+5.894 0.665 6.03 0.783 6.159 0.941 c
+6.497 0.529 l
+6.21 0.125 5.78 -0.073 5.203 -0.073 c
+5.13 3.499 m
+4.854 3.499 4.652 3.403 4.527 3.219 c
+4.399 3.032 4.326 2.741 4.307 2.352 c
+5.88 2.352 l
+5.88 2.44 l
+5.857 2.822 5.791 3.09 5.674 3.248 c
+5.556 3.414 5.373 3.499 5.13 3.499 c
+9.348 0 m
+9.308 0.088 9.282 0.235 9.275 0.441 c
+9.04 0.096 8.746 -0.073 8.393 -0.073 c
+8.029 -0.073 7.746 0.022 7.54 0.22 c
+7.342 0.426 7.247 0.713 7.247 1.087 c
+7.247 1.488 7.383 1.808 7.659 2.043 c
+7.93 2.286 8.305 2.41 8.775 2.41 c
+9.261 2.41 l
+9.261 2.837 l
+9.261 3.072 9.205 3.237 9.099 3.337 c
+8.989 3.443 8.827 3.499 8.613 3.499 c
+8.415 3.499 8.253 3.439 8.129 3.322 c
+8.01 3.204 7.952 3.057 7.952 2.881 c
+7.305 2.881 l
+7.305 3.075 7.364 3.267 7.482 3.454 c
+7.607 3.638 7.769 3.785 7.967 3.896 c
+8.172 4.002 8.401 4.056 8.658 4.056 c
+9.058 4.056 9.363 3.954 9.569 3.748 c
+9.782 3.543 9.896 3.248 9.907 2.866 c
+9.907 0.852 l
+9.907 0.548 9.944 0.283 10.025 0.058 c
+10.025 0 l
+h
+8.481 0.515 m
+8.646 0.515 8.797 0.559 8.937 0.646 c
+9.084 0.735 9.19 0.845 9.261 0.985 c
+9.261 1.926 l
+8.893 1.926 l
+8.577 1.926 8.334 1.856 8.158 1.72 c
+7.981 1.591 7.894 1.404 7.894 1.161 c
+7.894 0.933 7.937 0.768 8.025 0.661 c
+8.114 0.563 8.264 0.515 8.481 0.515 c
+13.479 4.939 m
+13.479 3.983 l
+14.082 3.983 l
+14.082 3.454 l
+13.479 3.454 l
+13.479 0.985 l
+13.479 0.827 13.501 0.709 13.552 0.632 c
+13.612 0.551 13.699 0.515 13.817 0.515 c
+13.905 0.515 13.993 0.529 14.082 0.559 c
+14.082 0 l
+13.934 -0.048 13.78 -0.073 13.626 -0.073 c
+13.369 -0.073 13.174 0.018 13.038 0.206 c
+12.898 0.389 12.833 0.65 12.833 0.985 c
+12.833 3.454 l
+12.23 3.454 l
+12.23 3.983 l
+12.833 3.983 l
+12.833 4.939 l
+h
+14.64 2.175 m
+14.64 2.753 14.776 3.208 15.052 3.543 c
+15.335 3.884 15.706 4.056 16.168 4.056 c
+16.629 4.056 16.995 3.888 17.271 3.557 c
+17.554 3.233 17.701 2.786 17.712 2.219 c
+17.712 1.793 l
+17.712 1.224 17.569 0.768 17.286 0.426 c
+17.01 0.092 16.643 -0.073 16.184 -0.073 c
+15.721 -0.073 15.349 0.088 15.066 0.411 c
+14.791 0.742 14.647 1.183 14.64 1.735 c
+h
+15.287 1.793 m
+15.287 1.389 15.364 1.073 15.522 0.838 c
+15.688 0.603 15.908 0.485 16.184 0.485 c
+16.75 0.485 17.043 0.897 17.066 1.72 c
+17.066 2.175 l
+17.066 2.576 16.981 2.896 16.816 3.131 c
+16.658 3.373 16.44 3.499 16.168 3.499 c
+15.904 3.499 15.688 3.373 15.522 3.131 c
+15.364 2.896 15.287 2.576 15.287 2.175 c
+h
+23.239 1.147 m
+23.842 3.983 l
+24.488 3.983 l
+23.503 0 l
+22.989 0 l
+22.21 2.851 l
+21.46 0 l
+20.931 0 l
+19.976 3.983 l
+20.608 3.983 l
+21.225 1.22 l
+21.961 3.983 l
+22.475 3.983 l
+h
+25.032 2.175 m
+25.032 2.753 25.169 3.208 25.444 3.543 c
+25.727 3.884 26.098 4.056 26.561 4.056 c
+27.021 4.056 27.388 3.888 27.663 3.557 c
+27.947 3.233 28.093 2.786 28.105 2.219 c
+28.105 1.793 l
+28.105 1.224 27.962 0.768 27.678 0.426 c
+27.403 0.092 27.035 -0.073 26.576 -0.073 c
+26.113 -0.073 25.741 0.088 25.458 0.411 c
+25.183 0.742 25.04 1.183 25.032 1.735 c
+h
+25.679 1.793 m
+25.679 1.389 25.757 1.073 25.915 0.838 c
+26.08 0.603 26.3 0.485 26.576 0.485 c
+27.141 0.485 27.436 0.897 27.457 1.72 c
+27.457 2.175 l
+27.457 2.576 27.374 2.896 27.208 3.131 c
+27.05 3.373 26.833 3.499 26.561 3.499 c
+26.296 3.499 26.08 3.373 25.915 3.131 c
+25.757 2.896 25.679 2.576 25.679 2.175 c
+h
+30.588 3.366 m
+30.501 3.385 30.401 3.395 30.295 3.395 c
+29.961 3.395 29.725 3.212 29.589 2.851 c
+29.589 0 l
+28.942 0 l
+28.942 3.983 l
+29.574 3.983 l
+29.589 3.572 l
+29.766 3.896 30.008 4.056 30.324 4.056 c
+30.431 4.056 30.519 4.035 30.588 3.998 c
+h
+32.234 1.822 m
+31.897 1.426 l
+31.897 0 l
+31.235 0 l
+31.235 5.644 l
+31.897 5.644 l
+31.897 2.263 l
+33.132 3.983 l
+33.911 3.983 l
+32.646 2.323 l
+34.073 0 l
+33.323 0 l
+h
+35.336 0 -0.646 3.983 re
+35.38 5.027 m
+35.38 4.917 35.351 4.825 35.292 4.748 c
+35.233 4.678 35.138 4.644 35.013 4.644 c
+34.896 4.644 34.8 4.678 34.734 4.748 c
+34.675 4.825 34.646 4.917 34.646 5.027 c
+34.646 5.145 34.675 5.236 34.734 5.307 c
+34.8 5.384 34.896 5.424 35.013 5.424 c
+35.138 5.424 35.233 5.384 35.292 5.307 c
+35.351 5.226 35.38 5.134 35.38 5.027 c
+36.968 3.983 m
+36.982 3.543 l
+37.236 3.884 37.56 4.056 37.953 4.056 c
+38.659 4.056 39.015 3.586 39.026 2.645 c
+39.026 0 l
+38.379 0 l
+38.379 2.616 l
+38.379 2.929 38.324 3.15 38.218 3.278 c
+38.107 3.403 37.953 3.469 37.747 3.469 c
+37.589 3.469 37.442 3.414 37.306 3.308 c
+37.177 3.197 37.075 3.061 36.997 2.896 c
+36.997 0 l
+36.351 0 l
+36.351 3.983 l
+h
+39.864 2.175 m
+39.864 2.793 39.974 3.256 40.202 3.572 c
+40.426 3.896 40.76 4.056 41.202 4.056 c
+41.602 4.056 41.907 3.881 42.112 3.528 c
+42.156 3.983 l
+42.744 3.983 l
+42.744 -0.044 l
+42.744 -0.532 42.616 -0.912 42.362 -1.176 c
+42.106 -1.44 41.753 -1.573 41.304 -1.573 c
+41.106 -1.573 40.885 -1.521 40.643 -1.426 c
+40.396 -1.326 40.217 -1.205 40.099 -1.058 c
+40.363 -0.617 l
+40.628 -0.882 40.926 -1.014 41.26 -1.014 c
+41.797 -1.014 42.073 -0.721 42.083 -0.133 c
+42.083 0.397 l
+41.877 0.081 41.576 -0.073 41.186 -0.073 c
+40.775 -0.073 40.452 0.077 40.217 0.382 c
+39.989 0.694 39.871 1.147 39.864 1.735 c
+h
+40.525 1.793 m
+40.525 1.352 40.587 1.022 40.716 0.808 c
+40.841 0.603 41.058 0.5 41.363 0.5 c
+41.686 0.5 41.925 0.665 42.083 0.999 c
+42.083 2.984 l
+41.915 3.308 41.676 3.469 41.363 3.469 c
+41.069 3.469 40.853 3.366 40.716 3.16 c
+40.587 2.955 40.525 2.631 40.525 2.19 c
+h
+45.288 2.175 m
+45.288 2.782 45.398 3.248 45.626 3.572 c
+45.861 3.896 46.188 4.056 46.611 4.056 c
+46.993 4.056 47.29 3.898 47.507 3.586 c
+47.507 5.644 l
+48.154 5.644 l
+48.154 0 l
+47.566 0 l
+47.521 0.426 l
+47.316 0.092 47.012 -0.073 46.611 -0.073 c
+46.199 -0.073 45.875 0.081 45.64 0.397 c
+45.405 0.721 45.288 1.176 45.288 1.764 c
+h
+45.934 1.793 m
+45.934 1.352 45.996 1.022 46.125 0.808 c
+46.262 0.603 46.482 0.5 46.787 0.5 c
+47.11 0.5 47.349 0.661 47.507 0.985 c
+47.507 2.998 l
+47.338 3.31 47.099 3.469 46.787 3.469 c
+46.482 3.469 46.262 3.366 46.125 3.16 c
+45.996 2.955 45.934 2.631 45.934 2.19 c
+h
+49.859 0 -0.647 3.983 re
+49.903 5.027 m
+49.903 4.917 49.873 4.825 49.815 4.748 c
+49.757 4.678 49.661 4.644 49.536 4.644 c
+49.418 4.644 49.323 4.678 49.256 4.748 c
+49.198 4.825 49.168 4.917 49.168 5.027 c
+49.168 5.145 49.198 5.236 49.256 5.307 c
+49.323 5.384 49.418 5.424 49.536 5.424 c
+49.661 5.424 49.757 5.384 49.815 5.307 c
+49.873 5.226 49.903 5.134 49.903 5.027 c
+52.52 3.366 m
+52.431 3.385 52.332 3.395 52.225 3.395 c
+51.891 3.395 51.656 3.212 51.52 2.851 c
+51.52 0 l
+50.873 0 l
+50.873 3.983 l
+51.505 3.983 l
+51.52 3.572 l
+51.696 3.896 51.939 4.056 52.255 4.056 c
+52.362 4.056 52.45 4.035 52.52 3.998 c
+h
+54.519 -0.073 m
+54.019 -0.073 53.636 0.073 53.372 0.368 c
+53.108 0.661 52.975 1.095 52.975 1.675 c
+52.975 2.146 l
+52.975 2.741 53.1 3.208 53.358 3.543 c
+53.622 3.884 53.982 4.056 54.445 4.056 c
+54.904 4.056 55.246 3.902 55.474 3.601 c
+55.71 3.308 55.831 2.844 55.841 2.219 c
+55.841 1.793 l
+53.622 1.793 l
+53.622 1.705 l
+53.622 1.272 53.699 0.959 53.857 0.764 c
+54.023 0.577 54.254 0.485 54.548 0.485 c
+54.743 0.485 54.916 0.518 55.062 0.588 c
+55.209 0.665 55.346 0.783 55.474 0.941 c
+55.812 0.529 l
+55.525 0.125 55.095 -0.073 54.519 -0.073 c
+54.445 3.499 m
+54.17 3.499 53.967 3.403 53.842 3.219 c
+53.714 3.032 53.64 2.741 53.622 2.352 c
+55.195 2.352 l
+55.195 2.44 l
+55.172 2.822 55.107 3.09 54.989 3.248 c
+54.871 3.414 54.688 3.499 54.445 3.499 c
+58.002 0.485 m
+58.216 0.485 58.388 0.548 58.517 0.676 c
+58.653 0.812 58.727 1.003 58.737 1.249 c
+59.355 1.249 l
+59.332 0.867 59.197 0.548 58.943 0.294 c
+58.686 0.048 58.374 -0.073 58.002 -0.073 c
+57.51 -0.073 57.135 0.077 56.871 0.382 c
+56.614 0.694 56.489 1.161 56.489 1.779 c
+56.489 2.219 l
+56.489 2.815 56.614 3.271 56.871 3.586 c
+57.135 3.898 57.51 4.056 58.002 4.056 c
+58.403 4.056 58.723 3.925 58.958 3.66 c
+59.201 3.403 59.332 3.057 59.355 2.616 c
+58.737 2.616 l
+58.715 2.911 58.642 3.131 58.517 3.278 c
+58.399 3.425 58.226 3.499 58.002 3.499 c
+57.709 3.499 57.491 3.399 57.356 3.204 c
+57.216 3.017 57.142 2.708 57.135 2.278 c
+57.135 1.764 l
+57.135 1.294 57.202 0.959 57.341 0.764 c
+57.488 0.577 57.709 0.485 58.002 0.485 c
+60.957 4.939 m
+60.957 3.983 l
+61.559 3.983 l
+61.559 3.454 l
+60.957 3.454 l
+60.957 0.985 l
+60.957 0.827 60.979 0.709 61.03 0.632 c
+61.089 0.551 61.177 0.515 61.295 0.515 c
+61.383 0.515 61.472 0.529 61.559 0.559 c
+61.559 0 l
+61.412 -0.048 61.258 -0.073 61.104 -0.073 c
+60.847 -0.073 60.652 0.018 60.516 0.206 c
+60.377 0.389 60.31 0.65 60.31 0.985 c
+60.31 3.454 l
+59.708 3.454 l
+59.708 3.983 l
+60.31 3.983 l
+60.31 4.939 l
+h
+62.118 2.175 m
+62.118 2.753 62.254 3.208 62.53 3.543 c
+62.812 3.884 63.184 4.056 63.647 4.056 c
+64.106 4.056 64.474 3.888 64.749 3.557 c
+65.032 3.233 65.179 2.786 65.19 2.219 c
+65.19 1.793 l
+65.19 1.224 65.046 0.768 64.764 0.426 c
+64.489 0.092 64.121 -0.073 63.662 -0.073 c
+63.199 -0.073 62.827 0.088 62.544 0.411 c
+62.268 0.742 62.125 1.183 62.118 1.735 c
+h
+62.765 1.793 m
+62.765 1.389 62.842 1.073 63 0.838 c
+63.165 0.603 63.386 0.485 63.662 0.485 c
+64.227 0.485 64.522 0.897 64.543 1.72 c
+64.543 2.175 l
+64.543 2.576 64.458 2.896 64.294 3.131 c
+64.136 3.373 63.919 3.499 63.647 3.499 c
+63.382 3.499 63.165 3.373 63 3.131 c
+62.842 2.896 62.765 2.576 62.765 2.175 c
+h
+67.674 3.366 m
+67.586 3.385 67.487 3.395 67.38 3.395 c
+67.046 3.395 66.81 3.212 66.675 2.851 c
+66.675 0 l
+66.028 0 l
+66.028 3.983 l
+66.66 3.983 l
+66.675 3.572 l
+66.851 3.896 67.094 4.056 67.41 4.056 c
+67.516 4.056 67.604 4.035 67.674 3.998 c
+h
+69.482 1.087 m
+70.203 3.983 l
+70.893 3.983 l
+69.6 -0.559 l
+69.501 -0.9 69.357 -1.161 69.174 -1.338 c
+68.998 -1.514 68.795 -1.602 68.571 -1.602 c
+68.483 -1.602 68.369 -1.58 68.233 -1.544 c
+68.233 -1 l
+68.38 -1.014 l
+68.564 -1.014 68.711 -0.97 68.821 -0.882 c
+68.927 -0.794 69.015 -0.636 69.085 -0.412 c
+69.203 0.029 l
+68.042 3.983 l
+68.747 3.983 l
+h
+71.173 0.353 m
+71.173 0.47 71.205 0.566 71.275 0.646 c
+71.342 0.723 71.444 0.764 71.585 0.764 c
+71.731 0.764 71.838 0.723 71.907 0.646 c
+71.984 0.566 72.025 0.47 72.025 0.353 c
+72.025 0.243 71.984 0.151 71.907 0.073 c
+71.838 -0.004 71.731 -0.044 71.585 -0.044 c
+71.444 -0.044 71.342 -0.004 71.275 0.073 c
+71.205 0.151 71.173 0.243 71.173 0.353 c
+f
+Q
+0.113 0.082 0.09 0 k
+287.665 232.611 234.667 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 225.772 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.146 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.807 l
+-1.896 -1.807 l
+-1.896 -1.263 l
+-2.142 -1.256 -2.359 -1.219 -2.543 -1.161 c
+-2.719 -1.102 -2.873 -1.024 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.034 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.477 -2.234 -0.514 c
+-2.138 -0.554 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.662 l
+-1.907 0.662 -1.926 0.666 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.772 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.279 -3.219 1.426 c
+-3.289 1.573 -3.322 1.757 -3.322 1.985 c
+-3.322 2.18 -3.289 2.345 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.933 -2.645 3.003 -2.469 3.043 c
+-2.293 3.091 -2.102 3.12 -1.896 3.132 c
+-1.896 3.558 l
+-1.543 3.558 l
+-1.543 3.132 l
+-1.319 3.12 -1.128 3.091 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.735 -0.349 2.621 -0.279 2.484 c
+-0.202 2.345 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.459 -1.543 2.5 c
+-1.543 1.368 l
+-1.514 1.368 l
+-1.506 1.368 -1.492 1.36 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.206 c
+-0.756 1.147 -0.595 1.066 -0.455 0.971 c
+-0.32 0.871 -0.213 0.743 -0.132 0.588 c
+-0.044 0.431 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.503 -2.113 2.484 -2.19 2.455 c
+-2.26 2.426 -2.319 2.386 -2.366 2.338 c
+-2.406 2.297 -2.436 2.249 -2.454 2.191 c
+-2.477 2.132 -2.484 2.066 -2.484 1.999 c
+-2.484 1.912 -2.469 1.838 -2.439 1.779 c
+-2.41 1.721 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.201 1.559 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.441 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.302 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.44 c
+-0.904 -0.345 -0.837 -0.201 -0.837 -0.014 c
+6.402 -2.66 m
+6.184 -2.66 5.993 -2.634 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.395 c
+5.284 -2.314 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.616 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.146 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.83 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.219 6.034 -1.219 c
+5.829 -1.219 5.644 -1.183 5.49 -1.102 c
+5.343 -1.014 5.215 -0.897 5.108 -0.749 c
+5.009 -0.595 4.935 -0.411 4.888 -0.205 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.772 4.836 1.019 4.888 1.235 c
+4.946 1.449 5.027 1.632 5.137 1.779 c
+5.244 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.264 6.093 2.264 c
+6.188 2.264 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.919 7.107 1.97 c
+7.115 2.029 7.122 2.077 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.151 2.22 c
+8.004 2.22 l
+7.993 2.139 7.982 2.029 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.414 7.938 -1.635 7.871 -1.822 c
+7.802 -2.006 7.699 -2.16 7.563 -2.278 c
+7.423 -2.403 7.258 -2.499 7.063 -2.557 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.743 7.067 0.919 7.019 1.058 c
+6.978 1.206 6.924 1.324 6.857 1.411 c
+6.799 1.5 6.729 1.559 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.368 c
+5.88 1.279 5.835 1.162 5.799 1.015 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.514 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.558 c
+6.725 -0.521 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.302 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.263 l
+8.86 -1.263 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.603 l
+9.199 1.603 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.597 1.603 m
+13.053 1.603 l
+13.053 2.22 l
+13.641 2.22 l
+13.92 3.117 l
+14.494 3.117 l
+14.494 2.22 l
+15.728 2.22 l
+15.728 1.603 l
+14.494 1.603 l
+14.494 -0.103 l
+14.494 -0.323 l
+14.501 -0.392 14.523 -0.455 14.552 -0.514 c
+14.589 -0.565 14.645 -0.61 14.714 -0.646 c
+14.791 -0.675 14.905 -0.691 15.052 -0.691 c
+15.188 -0.691 15.324 -0.687 15.464 -0.675 c
+15.599 -0.658 15.732 -0.631 15.861 -0.602 c
+15.861 -1.205 l
+15.78 -1.215 15.703 -1.23 15.626 -1.249 c
+15.545 -1.26 15.468 -1.267 15.391 -1.278 c
+15.31 -1.286 15.221 -1.294 15.125 -1.294 c
+15.038 -1.3 14.938 -1.308 14.832 -1.308 c
+14.645 -1.308 14.483 -1.294 14.346 -1.263 c
+14.218 -1.227 14.104 -1.183 14.009 -1.132 c
+13.92 -1.084 13.847 -1.024 13.788 -0.955 c
+13.729 -0.878 13.685 -0.801 13.656 -0.72 c
+13.627 -0.631 13.604 -0.544 13.597 -0.455 c
+13.586 -0.359 13.582 -0.264 13.582 -0.176 c
+h
+22.677 -1.323 m
+22.391 -1.323 22.148 -1.282 21.942 -1.205 c
+21.737 -1.117 21.564 -0.995 21.428 -0.837 c
+21.288 -0.683 21.185 -0.496 21.12 -0.278 c
+21.049 -0.055 21.016 0.192 21.016 0.456 c
+21.016 0.75 21.049 1.008 21.12 1.235 c
+21.197 1.459 21.303 1.646 21.442 1.794 c
+21.59 1.948 21.766 2.066 21.972 2.147 c
+22.177 2.234 22.412 2.278 22.677 2.278 c
+22.901 2.278 23.104 2.249 23.28 2.191 c
+23.456 2.132 23.607 2.047 23.736 1.941 c
+23.861 1.842 23.963 1.721 24.044 1.573 c
+24.121 1.434 24.177 1.283 24.206 1.118 c
+23.295 1.073 l
+23.265 1.25 23.196 1.389 23.089 1.5 c
+22.99 1.607 22.846 1.661 22.662 1.661 c
+22.416 1.661 22.24 1.559 22.134 1.353 c
+22.023 1.154 21.972 0.867 21.972 0.485 c
+21.972 -0.309 22.207 -0.706 22.677 -0.706 c
+22.843 -0.706 22.986 -0.654 23.104 -0.544 c
+23.221 -0.437 23.295 -0.275 23.324 -0.058 c
+24.235 -0.103 l
+24.206 -0.272 24.151 -0.426 24.074 -0.573 c
+24.004 -0.72 23.901 -0.852 23.765 -0.97 c
+23.636 -1.08 23.478 -1.168 23.295 -1.234 c
+23.118 -1.294 22.913 -1.323 22.677 -1.323 c
+28.384 0.485 m
+28.384 0.21 28.347 -0.04 28.281 -0.264 c
+28.212 -0.481 28.108 -0.668 27.973 -0.823 c
+27.833 -0.98 27.657 -1.102 27.443 -1.19 c
+27.227 -1.278 26.973 -1.323 26.679 -1.323 c
+26.404 -1.323 26.157 -1.278 25.944 -1.19 c
+25.739 -1.102 25.566 -0.98 25.43 -0.823 c
+25.29 -0.668 25.187 -0.481 25.121 -0.264 c
+25.051 -0.04 25.018 0.21 25.018 0.485 c
+25.018 0.739 25.047 0.975 25.106 1.191 c
+25.172 1.415 25.275 1.607 25.415 1.764 c
+25.551 1.929 25.727 2.058 25.944 2.147 c
+26.157 2.234 26.414 2.278 26.709 2.278 c
+27.021 2.278 27.281 2.234 27.487 2.147 c
+27.701 2.058 27.873 1.929 28.002 1.764 c
+28.138 1.607 28.237 1.415 28.296 1.191 c
+28.355 0.975 28.384 0.739 28.384 0.485 c
+27.429 0.485 m
+27.429 0.691 27.414 0.867 27.385 1.015 c
+27.362 1.162 27.326 1.283 27.267 1.382 c
+27.208 1.478 27.135 1.548 27.046 1.588 c
+26.959 1.636 26.848 1.661 26.724 1.661 c
+26.458 1.661 26.267 1.563 26.15 1.368 c
+26.032 1.18 25.974 0.886 25.974 0.485 c
+25.974 0.063 26.032 -0.242 26.15 -0.426 c
+26.267 -0.613 26.444 -0.706 26.679 -0.706 c
+26.804 -0.706 26.918 -0.687 27.017 -0.646 c
+27.113 -0.598 27.194 -0.525 27.252 -0.426 c
+27.318 -0.33 27.362 -0.205 27.385 -0.058 c
+27.414 0.088 27.429 0.269 27.429 0.485 c
+30.402 -1.263 m
+30.402 0.853 l
+30.402 1.019 30.394 1.154 30.387 1.264 c
+30.376 1.372 30.358 1.455 30.328 1.515 c
+30.306 1.58 30.277 1.632 30.24 1.661 c
+30.211 1.691 30.17 1.706 30.122 1.706 c
+30.063 1.706 30.009 1.676 29.961 1.617 c
+29.92 1.566 29.887 1.492 29.858 1.397 c
+29.828 1.309 29.803 1.195 29.784 1.058 c
+29.773 0.919 29.77 0.769 29.77 0.603 c
+29.77 -1.263 l
+29.02 -1.263 l
+29.02 1.47 l
+29.02 1.706 l
+29.02 1.926 l
+29.02 2.003 29.012 2.066 29.005 2.117 c
+29.005 2.22 l
+29.681 2.22 l
+29.681 2.132 l
+29.681 1.985 l
+29.689 1.926 29.696 1.867 29.696 1.808 c
+29.696 1.646 l
+29.71 1.646 l
+29.729 1.735 29.758 1.812 29.799 1.881 c
+29.836 1.96 29.88 2.029 29.931 2.087 c
+29.99 2.147 30.057 2.191 30.137 2.22 c
+30.214 2.257 30.302 2.278 30.402 2.278 c
+30.585 2.278 30.725 2.224 30.813 2.117 c
+30.909 2.018 30.979 1.86 31.019 1.646 c
+31.034 1.646 l
+31.071 1.742 31.111 1.831 31.152 1.912 c
+31.199 1.989 31.254 2.051 31.313 2.103 c
+31.372 2.161 31.438 2.205 31.519 2.234 c
+31.596 2.264 31.684 2.278 31.783 2.278 c
+31.919 2.278 32.033 2.253 32.122 2.205 c
+32.21 2.154 32.276 2.08 32.328 1.985 c
+32.386 1.885 32.423 1.757 32.445 1.603 c
+32.474 1.455 32.488 1.272 32.488 1.058 c
+32.488 -1.263 l
+31.769 -1.263 l
+31.769 0.853 l
+31.769 1.019 31.761 1.154 31.754 1.264 c
+31.742 1.372 31.725 1.455 31.695 1.515 c
+31.673 1.58 31.644 1.632 31.607 1.661 c
+31.578 1.691 31.537 1.706 31.489 1.706 c
+31.372 1.706 31.276 1.617 31.21 1.441 c
+31.152 1.272 31.122 1.015 31.122 0.662 c
+31.122 -1.263 l
+h
+34.462 -1.263 m
+34.462 0.853 l
+34.462 1.019 34.455 1.154 34.447 1.264 c
+34.437 1.372 34.418 1.455 34.389 1.515 c
+34.367 1.58 34.337 1.632 34.3 1.661 c
+34.271 1.691 34.231 1.706 34.183 1.706 c
+34.124 1.706 34.069 1.676 34.021 1.617 c
+33.98 1.566 33.948 1.492 33.918 1.397 c
+33.889 1.309 33.863 1.195 33.845 1.058 c
+33.834 0.919 33.83 0.769 33.83 0.603 c
+33.83 -1.263 l
+33.08 -1.263 l
+33.08 1.47 l
+33.08 1.706 l
+33.08 1.926 l
+33.08 2.003 33.074 2.066 33.066 2.117 c
+33.066 2.22 l
+33.742 2.22 l
+33.742 2.132 l
+33.742 1.985 l
+33.749 1.926 33.757 1.867 33.757 1.808 c
+33.757 1.646 l
+33.772 1.646 l
+33.789 1.735 33.82 1.812 33.859 1.881 c
+33.897 1.96 33.94 2.029 33.992 2.087 c
+34.051 2.147 34.117 2.191 34.198 2.22 c
+34.275 2.257 34.363 2.278 34.462 2.278 c
+34.646 2.278 34.786 2.224 34.874 2.117 c
+34.969 2.018 35.039 1.86 35.079 1.646 c
+35.094 1.646 l
+35.131 1.742 35.171 1.831 35.212 1.912 c
+35.26 1.989 35.314 2.051 35.374 2.103 c
+35.432 2.161 35.499 2.205 35.58 2.234 c
+35.657 2.264 35.744 2.278 35.844 2.278 c
+35.98 2.278 36.093 2.253 36.182 2.205 c
+36.27 2.154 36.336 2.08 36.388 1.985 c
+36.446 1.885 36.484 1.757 36.505 1.603 c
+36.535 1.455 36.55 1.272 36.55 1.058 c
+36.55 -1.263 l
+35.829 -1.263 l
+35.829 0.853 l
+35.829 1.019 35.821 1.154 35.815 1.264 c
+35.804 1.372 35.785 1.455 35.756 1.515 c
+35.734 1.58 35.704 1.632 35.667 1.661 c
+35.638 1.691 35.598 1.706 35.55 1.706 c
+35.432 1.706 35.337 1.617 35.27 1.441 c
+35.212 1.272 35.183 1.015 35.183 0.662 c
+35.183 -1.263 l
+h
+39.467 -0.646 m
+40.599 -0.646 l
+40.599 -1.263 l
+37.292 -1.263 l
+37.292 -0.646 l
+38.556 -0.646 l
+38.556 1.603 l
+37.63 1.603 l
+37.63 2.22 l
+39.467 2.22 l
+h
+38.556 3.514 0.911 -0.676 re
+38.556 2.837 m
+42.028 1.603 m
+41.485 1.603 l
+41.485 2.22 l
+42.073 2.22 l
+42.352 3.117 l
+42.925 3.117 l
+42.925 2.22 l
+44.16 2.22 l
+44.16 1.603 l
+42.925 1.603 l
+42.925 -0.103 l
+42.925 -0.323 l
+42.933 -0.392 42.954 -0.455 42.984 -0.514 c
+43.021 -0.565 43.076 -0.61 43.146 -0.646 c
+43.223 -0.675 43.337 -0.691 43.484 -0.691 c
+43.619 -0.691 43.756 -0.687 43.895 -0.675 c
+44.031 -0.658 44.164 -0.631 44.292 -0.602 c
+44.292 -1.205 l
+44.211 -1.215 44.134 -1.23 44.057 -1.249 c
+43.976 -1.26 43.899 -1.267 43.822 -1.278 c
+43.741 -1.286 43.653 -1.294 43.557 -1.294 c
+43.469 -1.3 43.37 -1.308 43.264 -1.308 c
+43.076 -1.308 42.914 -1.294 42.778 -1.263 c
+42.649 -1.227 42.536 -1.183 42.441 -1.132 c
+42.352 -1.084 42.279 -1.024 42.219 -0.955 c
+42.161 -0.878 42.117 -0.801 42.088 -0.72 c
+42.058 -0.631 42.036 -0.544 42.028 -0.455 c
+42.017 -0.359 42.013 -0.264 42.013 -0.176 c
+h
+f
+Q
+q 1 0 0 1 299.9491 211.3232 cm
+0 0 m
+-0.029 -0.58 -0.191 -1.022 -0.484 -1.323 c
+-0.779 -1.627 -1.198 -1.779 -1.734 -1.779 c
+-2.263 -1.779 -2.69 -1.58 -3.013 -1.176 c
+-3.329 -0.764 -3.484 -0.206 -3.484 0.5 c
+-3.484 1.47 l
+-3.484 2.165 -3.322 2.712 -2.998 3.117 c
+-2.675 3.516 -2.23 3.719 -1.66 3.719 c
+-1.153 3.719 -0.756 3.561 -0.47 3.248 c
+-0.187 2.944 -0.029 2.502 0 1.926 c
+-0.691 1.926 l
+-0.72 2.367 -0.816 2.679 -0.97 2.866 c
+-1.117 3.05 -1.348 3.146 -1.66 3.146 c
+-2.036 3.146 -2.319 2.999 -2.514 2.705 c
+-2.711 2.418 -2.807 2.003 -2.807 1.455 c
+-2.807 0.47 l
+-2.807 -0.07 -2.715 -0.485 -2.528 -0.779 c
+-2.344 -1.066 -2.08 -1.205 -1.734 -1.205 c
+-1.381 -1.205 -1.128 -1.117 -0.97 -0.941 c
+-0.816 -0.764 -0.72 -0.452 -0.691 0 c
+h
+2.455 1.661 m
+2.367 1.679 2.268 1.691 2.161 1.691 c
+1.827 1.691 1.592 1.507 1.455 1.147 c
+1.455 -1.705 l
+0.809 -1.705 l
+0.809 2.278 l
+1.441 2.278 l
+1.455 1.866 l
+1.632 2.19 1.875 2.352 2.19 2.352 c
+2.297 2.352 2.385 2.33 2.455 2.294 c
+h
+4.454 -1.779 m
+3.954 -1.779 3.572 -1.631 3.308 -1.338 c
+3.043 -1.043 2.911 -0.61 2.911 -0.029 c
+2.911 0.441 l
+2.911 1.037 3.036 1.503 3.293 1.837 c
+3.558 2.18 3.917 2.352 4.381 2.352 c
+4.84 2.352 5.182 2.198 5.409 1.897 c
+5.644 1.602 5.766 1.139 5.777 0.515 c
+5.777 0.088 l
+3.558 0.088 l
+3.558 0 l
+3.558 -0.434 3.635 -0.746 3.793 -0.941 c
+3.958 -1.128 4.189 -1.22 4.484 -1.22 c
+4.678 -1.22 4.851 -1.187 4.998 -1.117 c
+5.145 -1.04 5.281 -0.922 5.409 -0.764 c
+5.748 -1.176 l
+5.461 -1.58 5.031 -1.779 4.454 -1.779 c
+4.381 1.793 m
+4.105 1.793 3.903 1.698 3.778 1.514 c
+3.649 1.326 3.576 1.037 3.558 0.647 c
+5.13 0.647 l
+5.13 0.735 l
+5.108 1.118 5.042 1.386 4.925 1.544 c
+4.807 1.709 4.623 1.793 4.381 1.793 c
+8.599 -1.705 m
+8.559 -1.617 8.533 -1.469 8.526 -1.264 c
+8.291 -1.61 7.996 -1.779 7.643 -1.779 c
+7.28 -1.779 6.997 -1.683 6.791 -1.484 c
+6.593 -1.278 6.498 -0.992 6.498 -0.617 c
+6.498 -0.216 6.633 0.103 6.909 0.338 c
+7.181 0.58 7.556 0.706 8.026 0.706 c
+8.511 0.706 l
+8.511 1.132 l
+8.511 1.367 8.456 1.532 8.349 1.631 c
+8.239 1.738 8.077 1.793 7.865 1.793 c
+7.666 1.793 7.504 1.735 7.379 1.617 c
+7.262 1.5 7.203 1.353 7.203 1.176 c
+6.556 1.176 l
+6.556 1.371 6.615 1.562 6.733 1.749 c
+6.857 1.933 7.019 2.08 7.217 2.19 c
+7.423 2.297 7.651 2.352 7.909 2.352 c
+8.309 2.352 8.614 2.249 8.819 2.043 c
+9.033 1.837 9.147 1.544 9.158 1.161 c
+9.158 -0.852 l
+9.158 -1.157 9.195 -1.422 9.276 -1.646 c
+9.276 -1.705 l
+h
+7.732 -1.191 m
+7.897 -1.191 8.048 -1.147 8.187 -1.058 c
+8.335 -0.97 8.441 -0.86 8.511 -0.721 c
+8.511 0.22 l
+8.144 0.22 l
+7.828 0.22 7.585 0.151 7.408 0.015 c
+7.232 -0.114 7.144 -0.301 7.144 -0.544 c
+7.144 -0.771 7.188 -0.937 7.277 -1.043 c
+7.364 -1.143 7.516 -1.191 7.732 -1.191 c
+11.009 3.234 m
+11.009 2.278 l
+11.612 2.278 l
+11.612 1.749 l
+11.009 1.749 l
+11.009 -0.721 l
+11.009 -0.878 11.032 -0.995 11.084 -1.073 c
+11.142 -1.153 11.231 -1.191 11.348 -1.191 c
+11.437 -1.191 11.524 -1.176 11.612 -1.147 c
+11.612 -1.705 l
+11.466 -1.753 11.311 -1.779 11.157 -1.779 c
+10.899 -1.779 10.705 -1.687 10.569 -1.5 c
+10.429 -1.315 10.363 -1.055 10.363 -0.721 c
+10.363 1.749 l
+9.76 1.749 l
+9.76 2.278 l
+10.363 2.278 l
+10.363 3.234 l
+h
+13.803 -1.779 m
+13.303 -1.779 12.921 -1.631 12.656 -1.338 c
+12.391 -1.043 12.26 -0.61 12.26 -0.029 c
+12.26 0.441 l
+12.26 1.037 12.384 1.503 12.642 1.837 c
+12.906 2.18 13.266 2.352 13.729 2.352 c
+14.188 2.352 14.531 2.198 14.758 1.897 c
+14.993 1.602 15.115 1.139 15.125 0.515 c
+15.125 0.088 l
+12.906 0.088 l
+12.906 0 l
+12.906 -0.434 12.983 -0.746 13.141 -0.941 c
+13.307 -1.128 13.538 -1.22 13.832 -1.22 c
+14.027 -1.22 14.199 -1.187 14.346 -1.117 c
+14.494 -1.04 14.629 -0.922 14.758 -0.764 c
+15.096 -1.176 l
+14.81 -1.58 14.379 -1.779 13.803 -1.779 c
+13.729 1.793 m
+13.453 1.793 13.251 1.698 13.126 1.514 c
+12.998 1.326 12.925 1.037 12.906 0.647 c
+14.479 0.647 l
+14.479 0.735 l
+14.457 1.118 14.39 1.386 14.273 1.544 c
+14.155 1.709 13.972 1.793 13.729 1.793 c
+18.242 2.278 m
+18.257 1.837 l
+18.51 2.18 18.834 2.352 19.227 2.352 c
+19.932 2.352 20.289 1.881 20.299 0.941 c
+20.299 -1.705 l
+19.653 -1.705 l
+19.653 0.912 l
+19.653 1.224 19.597 1.444 19.491 1.573 c
+19.381 1.698 19.227 1.764 19.021 1.764 c
+18.863 1.764 18.716 1.709 18.58 1.602 c
+18.452 1.492 18.348 1.357 18.271 1.191 c
+18.271 -1.705 l
+17.625 -1.705 l
+17.625 2.278 l
+h
+22.695 -1.779 m
+22.196 -1.779 21.814 -1.631 21.549 -1.338 c
+21.284 -1.043 21.152 -0.61 21.152 -0.029 c
+21.152 0.441 l
+21.152 1.037 21.278 1.503 21.534 1.837 c
+21.799 2.18 22.159 2.352 22.622 2.352 c
+23.081 2.352 23.423 2.198 23.651 1.897 c
+23.886 1.602 24.008 1.139 24.019 0.515 c
+24.019 0.088 l
+21.799 0.088 l
+21.799 0 l
+21.799 -0.434 21.876 -0.746 22.034 -0.941 c
+22.2 -1.128 22.431 -1.22 22.725 -1.22 c
+22.92 -1.22 23.092 -1.187 23.239 -1.117 c
+23.387 -1.04 23.522 -0.922 23.651 -0.764 c
+23.989 -1.176 l
+23.703 -1.58 23.273 -1.779 22.695 -1.779 c
+22.622 1.793 m
+22.346 1.793 22.144 1.698 22.02 1.514 c
+21.891 1.326 21.818 1.037 21.799 0.647 c
+23.372 0.647 l
+23.372 0.735 l
+23.35 1.118 23.283 1.386 23.166 1.544 c
+23.048 1.709 22.865 1.793 22.622 1.793 c
+27.767 -0.559 m
+28.37 2.278 l
+29.016 2.278 l
+28.031 -1.705 l
+27.517 -1.705 l
+26.738 1.147 l
+25.988 -1.705 l
+25.459 -1.705 l
+24.503 2.278 l
+25.136 2.278 l
+25.753 -0.485 l
+26.488 2.278 l
+27.002 2.278 l
+h
+32.794 -1.22 m
+33.007 -1.22 33.18 -1.157 33.309 -1.029 c
+33.444 -0.893 33.518 -0.702 33.529 -0.455 c
+34.146 -0.455 l
+34.124 -0.838 33.988 -1.157 33.735 -1.411 c
+33.477 -1.658 33.165 -1.779 32.794 -1.779 c
+32.301 -1.779 31.927 -1.627 31.662 -1.323 c
+31.405 -1.01 31.28 -0.544 31.28 0.073 c
+31.28 0.515 l
+31.28 1.11 31.405 1.565 31.662 1.881 c
+31.927 2.194 32.301 2.352 32.794 2.352 c
+33.194 2.352 33.514 2.219 33.749 1.955 c
+33.992 1.698 34.124 1.353 34.146 0.912 c
+33.529 0.912 l
+33.507 1.205 33.433 1.426 33.309 1.573 c
+33.191 1.72 33.018 1.793 32.794 1.793 c
+32.5 1.793 32.283 1.694 32.147 1.5 c
+32.008 1.312 31.934 1.004 31.927 0.573 c
+31.927 0.059 l
+31.927 -0.411 31.993 -0.746 32.133 -0.941 c
+32.28 -1.128 32.5 -1.22 32.794 -1.22 c
+34.763 0.47 m
+34.763 1.047 34.9 1.503 35.175 1.837 c
+35.458 2.18 35.829 2.352 36.292 2.352 c
+36.752 2.352 37.119 2.183 37.394 1.852 c
+37.678 1.529 37.824 1.081 37.836 0.515 c
+37.836 0.088 l
+37.836 -0.482 37.693 -0.937 37.409 -1.278 c
+37.134 -1.613 36.766 -1.779 36.307 -1.779 c
+35.844 -1.779 35.472 -1.617 35.19 -1.294 c
+34.915 -0.962 34.771 -0.522 34.763 0.029 c
+h
+35.41 0.088 m
+35.41 -0.316 35.487 -0.632 35.646 -0.867 c
+35.811 -1.103 36.031 -1.22 36.307 -1.22 c
+36.873 -1.22 37.167 -0.808 37.189 0.015 c
+37.189 0.47 l
+37.189 0.871 37.105 1.191 36.939 1.426 c
+36.781 1.669 36.565 1.793 36.292 1.793 c
+36.027 1.793 35.811 1.669 35.646 1.426 c
+35.487 1.191 35.41 0.871 35.41 0.47 c
+h
+39.291 2.278 m
+39.306 1.911 l
+39.548 2.205 39.868 2.352 40.261 2.352 c
+40.702 2.352 41.011 2.153 41.187 1.764 c
+41.44 2.153 41.79 2.352 42.231 2.352 c
+42.965 2.352 43.341 1.889 43.362 0.97 c
+43.362 -1.705 l
+42.716 -1.705 l
+42.716 0.912 l
+42.716 1.205 42.661 1.419 42.554 1.558 c
+42.455 1.694 42.282 1.764 42.04 1.764 c
+41.841 1.764 41.679 1.683 41.554 1.529 c
+41.437 1.382 41.367 1.191 41.348 0.956 c
+41.348 -1.705 l
+40.687 -1.705 l
+40.687 0.941 l
+40.687 1.488 40.467 1.764 40.026 1.764 c
+39.692 1.764 39.456 1.602 39.32 1.278 c
+39.32 -1.705 l
+38.674 -1.705 l
+38.674 2.278 l
+h
+44.95 2.278 m
+44.965 1.911 l
+45.207 2.205 45.527 2.352 45.92 2.352 c
+46.361 2.352 46.67 2.153 46.846 1.764 c
+47.1 2.153 47.449 2.352 47.89 2.352 c
+48.625 2.352 48.999 1.889 49.022 0.97 c
+49.022 -1.705 l
+48.375 -1.705 l
+48.375 0.912 l
+48.375 1.205 48.32 1.419 48.213 1.558 c
+48.114 1.694 47.941 1.764 47.698 1.764 c
+47.501 1.764 47.339 1.683 47.214 1.529 c
+47.096 1.382 47.027 1.191 47.008 0.956 c
+47.008 -1.705 l
+46.346 -1.705 l
+46.346 0.941 l
+46.346 1.488 46.126 1.764 45.685 1.764 c
+45.35 1.764 45.115 1.602 44.98 1.278 c
+44.98 -1.705 l
+44.332 -1.705 l
+44.332 2.278 l
+h
+50.697 -1.705 -0.647 3.983 re
+50.742 3.322 m
+50.742 3.212 50.712 3.12 50.653 3.042 c
+50.595 2.973 50.499 2.94 50.374 2.94 c
+50.256 2.94 50.161 2.973 50.094 3.042 c
+50.036 3.12 50.007 3.212 50.007 3.322 c
+50.007 3.439 50.036 3.532 50.094 3.601 c
+50.161 3.678 50.256 3.719 50.374 3.719 c
+50.499 3.719 50.595 3.678 50.653 3.601 c
+50.712 3.52 50.742 3.429 50.742 3.322 c
+52.564 3.234 m
+52.564 2.278 l
+53.167 2.278 l
+53.167 1.749 l
+52.564 1.749 l
+52.564 -0.721 l
+52.564 -0.878 52.586 -0.995 52.637 -1.073 c
+52.696 -1.153 52.785 -1.191 52.902 -1.191 c
+52.99 -1.191 53.078 -1.176 53.167 -1.147 c
+53.167 -1.705 l
+53.02 -1.753 52.866 -1.779 52.711 -1.779 c
+52.454 -1.779 52.259 -1.687 52.124 -1.5 c
+51.983 -1.315 51.918 -1.055 51.918 -0.721 c
+51.918 1.749 l
+51.315 1.749 l
+51.315 2.278 l
+51.918 2.278 l
+51.918 3.234 l
+h
+55.945 -1.705 m
+55.945 1.749 l
+55.416 1.749 l
+55.416 2.278 l
+55.945 2.278 l
+55.945 2.734 l
+55.945 3.135 56.041 3.447 56.239 3.675 c
+56.444 3.899 56.724 4.013 57.077 4.013 c
+57.213 4.013 57.345 3.991 57.474 3.954 c
+57.444 3.41 l
+57.345 3.429 57.246 3.439 57.15 3.439 c
+56.775 3.439 56.592 3.175 56.592 2.646 c
+56.592 2.278 l
+57.267 2.278 l
+57.267 1.749 l
+56.592 1.749 l
+56.592 -1.705 l
+h
+59.679 1.661 m
+59.59 1.679 59.491 1.691 59.384 1.691 c
+59.05 1.691 58.815 1.507 58.679 1.147 c
+58.679 -1.705 l
+58.032 -1.705 l
+58.032 2.278 l
+58.664 2.278 l
+58.679 1.866 l
+58.855 2.19 59.098 2.352 59.414 2.352 c
+59.521 2.352 59.609 2.33 59.679 2.294 c
+h
+60.12 0.47 m
+60.12 1.047 60.255 1.503 60.531 1.837 c
+60.814 2.18 61.185 2.352 61.648 2.352 c
+62.108 2.352 62.475 2.183 62.75 1.852 c
+63.033 1.529 63.181 1.081 63.191 0.515 c
+63.191 0.088 l
+63.191 -0.482 63.048 -0.937 62.765 -1.278 c
+62.49 -1.613 62.122 -1.779 61.663 -1.779 c
+61.2 -1.779 60.829 -1.617 60.546 -1.294 c
+60.27 -0.962 60.126 -0.522 60.12 0.029 c
+h
+60.766 0.088 m
+60.766 -0.316 60.843 -0.632 61.001 -0.867 c
+61.167 -1.103 61.387 -1.22 61.663 -1.22 c
+62.229 -1.22 62.522 -0.808 62.545 0.015 c
+62.545 0.47 l
+62.545 0.871 62.46 1.191 62.295 1.426 c
+62.137 1.669 61.92 1.793 61.648 1.793 c
+61.383 1.793 61.167 1.669 61.001 1.426 c
+60.843 1.191 60.766 0.871 60.766 0.47 c
+h
+64.647 2.278 m
+64.662 1.911 l
+64.904 2.205 65.223 2.352 65.617 2.352 c
+66.058 2.352 66.366 2.153 66.543 1.764 c
+66.796 2.153 67.145 2.352 67.586 2.352 c
+68.321 2.352 68.697 1.889 68.718 0.97 c
+68.718 -1.705 l
+68.072 -1.705 l
+68.072 0.912 l
+68.072 1.205 68.016 1.419 67.91 1.558 c
+67.81 1.694 67.638 1.764 67.395 1.764 c
+67.197 1.764 67.035 1.683 66.91 1.529 c
+66.792 1.382 66.723 1.191 66.705 0.956 c
+66.705 -1.705 l
+66.043 -1.705 l
+66.043 0.941 l
+66.043 1.488 65.823 1.764 65.381 1.764 c
+65.047 1.764 64.812 1.602 64.676 1.278 c
+64.676 -1.705 l
+64.03 -1.705 l
+64.03 2.278 l
+h
+72.79 -1.22 m
+73.003 -1.22 73.175 -1.157 73.304 -1.029 c
+73.441 -0.893 73.514 -0.702 73.525 -0.455 c
+74.142 -0.455 l
+74.12 -0.838 73.984 -1.157 73.73 -1.411 c
+73.474 -1.658 73.161 -1.779 72.79 -1.779 c
+72.298 -1.779 71.922 -1.627 71.658 -1.323 c
+71.401 -1.01 71.276 -0.544 71.276 0.073 c
+71.276 0.515 l
+71.276 1.11 71.401 1.565 71.658 1.881 c
+71.922 2.194 72.298 2.352 72.79 2.352 c
+73.19 2.352 73.51 2.219 73.745 1.955 c
+73.988 1.698 74.12 1.353 74.142 0.912 c
+73.525 0.912 l
+73.503 1.205 73.429 1.426 73.304 1.573 c
+73.187 1.72 73.015 1.793 72.79 1.793 c
+72.496 1.793 72.279 1.694 72.143 1.5 c
+72.003 1.312 71.93 1.004 71.922 0.573 c
+71.922 0.059 l
+71.922 -0.411 71.989 -0.746 72.128 -0.941 c
+72.275 -1.128 72.496 -1.22 72.79 -1.22 c
+75.539 1.866 m
+75.793 2.19 76.112 2.352 76.494 2.352 c
+77.2 2.352 77.556 1.881 77.567 0.941 c
+77.567 -1.705 l
+76.92 -1.705 l
+76.92 0.912 l
+76.92 1.224 76.865 1.444 76.759 1.573 c
+76.649 1.698 76.494 1.764 76.288 1.764 c
+76.13 1.764 75.983 1.709 75.847 1.602 c
+75.719 1.492 75.616 1.357 75.539 1.191 c
+75.539 -1.705 l
+74.892 -1.705 l
+74.892 3.94 l
+75.539 3.94 l
+h
+80.566 -1.705 m
+80.525 -1.617 80.5 -1.469 80.492 -1.264 c
+80.257 -1.61 79.963 -1.779 79.61 -1.779 c
+79.247 -1.779 78.964 -1.683 78.758 -1.484 c
+78.559 -1.278 78.464 -0.992 78.464 -0.617 c
+78.464 -0.216 78.6 0.103 78.875 0.338 c
+79.147 0.58 79.523 0.706 79.993 0.706 c
+80.477 0.706 l
+80.477 1.132 l
+80.477 1.367 80.423 1.532 80.316 1.631 c
+80.206 1.738 80.044 1.793 79.831 1.793 c
+79.633 1.793 79.471 1.735 79.346 1.617 c
+79.228 1.5 79.17 1.353 79.17 1.176 c
+78.523 1.176 l
+78.523 1.371 78.582 1.562 78.699 1.749 c
+78.824 1.933 78.985 2.08 79.184 2.19 c
+79.39 2.297 79.618 2.352 79.875 2.352 c
+80.275 2.352 80.581 2.249 80.786 2.043 c
+81 1.837 81.113 1.544 81.125 1.161 c
+81.125 -0.852 l
+81.125 -1.157 81.161 -1.422 81.242 -1.646 c
+81.242 -1.705 l
+h
+79.698 -1.191 m
+79.864 -1.191 80.015 -1.147 80.154 -1.058 c
+80.301 -0.97 80.408 -0.86 80.477 -0.721 c
+80.477 0.22 l
+80.111 0.22 l
+79.794 0.22 79.552 0.151 79.375 0.015 c
+79.199 -0.114 79.111 -0.301 79.111 -0.544 c
+79.111 -0.771 79.155 -0.937 79.243 -1.043 c
+79.331 -1.143 79.482 -1.191 79.698 -1.191 c
+82.741 2.278 m
+82.756 1.837 l
+83.01 2.18 83.333 2.352 83.726 2.352 c
+84.431 2.352 84.788 1.881 84.799 0.941 c
+84.799 -1.705 l
+84.152 -1.705 l
+84.152 0.912 l
+84.152 1.224 84.097 1.444 83.991 1.573 c
+83.88 1.698 83.726 1.764 83.521 1.764 c
+83.363 1.764 83.215 1.709 83.079 1.602 c
+82.951 1.492 82.848 1.357 82.771 1.191 c
+82.771 -1.705 l
+82.124 -1.705 l
+82.124 2.278 l
+h
+85.637 0.47 m
+85.637 1.087 85.747 1.551 85.975 1.866 c
+86.199 2.19 86.534 2.352 86.974 2.352 c
+87.375 2.352 87.68 2.176 87.886 1.823 c
+87.93 2.278 l
+88.518 2.278 l
+88.518 -1.749 l
+88.518 -2.238 88.389 -2.616 88.136 -2.881 c
+87.878 -3.146 87.525 -3.278 87.078 -3.278 c
+86.879 -3.278 86.659 -3.227 86.416 -3.131 c
+86.17 -3.032 85.99 -2.911 85.873 -2.763 c
+86.137 -2.323 l
+86.401 -2.587 86.699 -2.72 87.033 -2.72 c
+87.57 -2.72 87.845 -2.425 87.857 -1.837 c
+87.857 -1.309 l
+87.651 -1.624 87.35 -1.779 86.96 -1.779 c
+86.548 -1.779 86.225 -1.627 85.99 -1.323 c
+85.762 -1.01 85.644 -0.559 85.637 0.029 c
+h
+86.299 0.088 m
+86.299 -0.353 86.361 -0.683 86.49 -0.897 c
+86.615 -1.103 86.831 -1.205 87.136 -1.205 c
+87.46 -1.205 87.699 -1.04 87.857 -0.706 c
+87.857 1.278 l
+87.687 1.602 87.448 1.764 87.136 1.764 c
+86.842 1.764 86.625 1.661 86.49 1.455 c
+86.361 1.249 86.299 0.926 86.299 0.485 c
+h
+90.899 -1.779 m
+90.399 -1.779 90.017 -1.631 89.753 -1.338 c
+89.488 -1.043 89.356 -0.61 89.356 -0.029 c
+89.356 0.441 l
+89.356 1.037 89.481 1.503 89.738 1.837 c
+90.002 2.18 90.363 2.352 90.826 2.352 c
+91.285 2.352 91.627 2.198 91.855 1.897 c
+92.09 1.602 92.211 1.139 92.223 0.515 c
+92.223 0.088 l
+90.002 0.088 l
+90.002 0 l
+90.002 -0.434 90.08 -0.746 90.238 -0.941 c
+90.403 -1.128 90.635 -1.22 90.929 -1.22 c
+91.124 -1.22 91.296 -1.187 91.443 -1.117 c
+91.59 -1.04 91.726 -0.922 91.855 -0.764 c
+92.192 -1.176 l
+91.906 -1.58 91.477 -1.779 90.899 -1.779 c
+90.826 1.793 m
+90.55 1.793 90.348 1.698 90.223 1.514 c
+90.095 1.326 90.021 1.037 90.002 0.647 c
+91.575 0.647 l
+91.575 0.735 l
+91.554 1.118 91.487 1.386 91.369 1.544 c
+91.252 1.709 91.068 1.793 90.826 1.793 c
+94.941 -0.691 m
+94.941 -0.544 94.887 -0.422 94.779 -0.324 c
+94.669 -0.228 94.463 -0.11 94.162 0.029 c
+93.817 0.177 93.574 0.298 93.428 0.397 c
+93.281 0.503 93.17 0.621 93.104 0.75 c
+93.034 0.875 93.001 1.033 93.001 1.22 c
+93.001 1.544 93.119 1.812 93.354 2.028 c
+93.589 2.242 93.89 2.352 94.265 2.352 c
+94.648 2.352 94.956 2.238 95.192 2.014 c
+95.427 1.786 95.544 1.5 95.544 1.147 c
+94.897 1.147 l
+94.897 1.323 94.839 1.474 94.721 1.602 c
+94.604 1.727 94.449 1.793 94.265 1.793 c
+94.067 1.793 93.916 1.738 93.81 1.631 c
+93.699 1.532 93.648 1.4 93.648 1.235 c
+93.648 1.106 93.684 1 93.765 0.912 c
+93.842 0.831 94.033 0.728 94.339 0.603 c
+94.816 0.416 95.147 0.228 95.323 0.044 c
+95.5 -0.133 95.589 -0.36 95.589 -0.632 c
+95.589 -0.985 95.463 -1.264 95.221 -1.469 c
+94.986 -1.675 94.669 -1.779 94.28 -1.779 c
+93.858 -1.779 93.52 -1.661 93.266 -1.426 c
+93.009 -1.183 92.884 -0.878 92.884 -0.515 c
+93.53 -0.515 l
+93.538 -0.742 93.607 -0.918 93.736 -1.043 c
+93.861 -1.161 94.045 -1.22 94.28 -1.22 c
+94.493 -1.22 94.655 -1.172 94.765 -1.073 c
+94.883 -0.977 94.941 -0.849 94.941 -0.691 c
+100.189 -1.705 m
+100.148 -1.617 100.123 -1.469 100.115 -1.264 c
+99.88 -1.61 99.587 -1.779 99.234 -1.779 c
+98.87 -1.779 98.587 -1.683 98.381 -1.484 c
+98.183 -1.278 98.087 -0.992 98.087 -0.617 c
+98.087 -0.216 98.224 0.103 98.498 0.338 c
+98.771 0.58 99.145 0.706 99.616 0.706 c
+100.101 0.706 l
+100.101 1.132 l
+100.101 1.367 100.046 1.532 99.939 1.631 c
+99.829 1.738 99.668 1.793 99.454 1.793 c
+99.256 1.793 99.094 1.735 98.969 1.617 c
+98.851 1.5 98.793 1.353 98.793 1.176 c
+98.145 1.176 l
+98.145 1.371 98.205 1.562 98.322 1.749 c
+98.447 1.933 98.609 2.08 98.808 2.19 c
+99.013 2.297 99.241 2.352 99.498 2.352 c
+99.899 2.352 100.204 2.249 100.41 2.043 c
+100.622 1.837 100.736 1.544 100.748 1.161 c
+100.748 -0.852 l
+100.748 -1.157 100.784 -1.422 100.865 -1.646 c
+100.865 -1.705 l
+h
+99.321 -1.191 m
+99.487 -1.191 99.637 -1.147 99.778 -1.058 c
+99.924 -0.97 100.031 -0.86 100.101 -0.721 c
+100.101 0.22 l
+99.733 0.22 l
+99.417 0.22 99.175 0.151 98.999 0.015 c
+98.822 -0.114 98.733 -0.301 98.733 -0.544 c
+98.733 -0.771 98.778 -0.937 98.866 -1.043 c
+98.954 -1.143 99.105 -1.191 99.321 -1.191 c
+101.615 0.47 m
+101.615 1.077 101.725 1.544 101.953 1.866 c
+102.188 2.19 102.515 2.352 102.938 2.352 c
+103.32 2.352 103.618 2.194 103.834 1.881 c
+103.834 3.94 l
+104.481 3.94 l
+104.481 -1.705 l
+103.893 -1.705 l
+103.849 -1.278 l
+103.643 -1.613 103.338 -1.779 102.938 -1.779 c
+102.526 -1.779 102.203 -1.624 101.968 -1.309 c
+101.732 -0.985 101.615 -0.529 101.615 0.059 c
+h
+102.261 0.088 m
+102.261 -0.353 102.324 -0.683 102.453 -0.897 c
+102.589 -1.103 102.809 -1.205 103.114 -1.205 c
+103.437 -1.205 103.676 -1.043 103.834 -0.721 c
+103.834 1.294 l
+103.666 1.606 103.427 1.764 103.114 1.764 c
+102.809 1.764 102.589 1.661 102.453 1.455 c
+102.324 1.249 102.261 0.926 102.261 0.485 c
+h
+105.349 0.47 m
+105.349 1.077 105.459 1.544 105.686 1.866 c
+105.922 2.19 106.249 2.352 106.671 2.352 c
+107.053 2.352 107.352 2.194 107.568 1.881 c
+107.568 3.94 l
+108.215 3.94 l
+108.215 -1.705 l
+107.627 -1.705 l
+107.583 -1.278 l
+107.377 -1.613 107.072 -1.779 106.671 -1.779 c
+106.259 -1.779 105.937 -1.624 105.701 -1.309 c
+105.466 -0.985 105.349 -0.529 105.349 0.059 c
+h
+105.995 0.088 m
+105.995 -0.353 106.058 -0.683 106.186 -0.897 c
+106.322 -1.103 106.542 -1.205 106.847 -1.205 c
+107.171 -1.205 107.41 -1.043 107.568 -0.721 c
+107.568 1.294 l
+107.399 1.606 107.161 1.764 106.847 1.764 c
+106.542 1.764 106.322 1.661 106.186 1.455 c
+106.058 1.249 105.995 0.926 105.995 0.485 c
+h
+110.64 -1.779 m
+110.14 -1.779 109.758 -1.631 109.494 -1.338 c
+109.229 -1.043 109.097 -0.61 109.097 -0.029 c
+109.097 0.441 l
+109.097 1.037 109.222 1.503 109.479 1.837 c
+109.744 2.18 110.103 2.352 110.567 2.352 c
+111.026 2.352 111.368 2.198 111.595 1.897 c
+111.83 1.602 111.952 1.139 111.963 0.515 c
+111.963 0.088 l
+109.744 0.088 l
+109.744 0 l
+109.744 -0.434 109.821 -0.746 109.979 -0.941 c
+110.144 -1.128 110.375 -1.22 110.669 -1.22 c
+110.864 -1.22 111.037 -1.187 111.184 -1.117 c
+111.331 -1.04 111.467 -0.922 111.595 -0.764 c
+111.934 -1.176 l
+111.647 -1.58 111.217 -1.779 110.64 -1.779 c
+110.567 1.793 m
+110.291 1.793 110.089 1.698 109.964 1.514 c
+109.835 1.326 109.762 1.037 109.744 0.647 c
+111.316 0.647 l
+111.316 0.735 l
+111.294 1.118 111.228 1.386 111.111 1.544 c
+110.993 1.709 110.809 1.793 110.567 1.793 c
+112.609 0.47 m
+112.609 1.077 112.72 1.544 112.948 1.866 c
+113.183 2.19 113.511 2.352 113.933 2.352 c
+114.315 2.352 114.612 2.194 114.829 1.881 c
+114.829 3.94 l
+115.476 3.94 l
+115.476 -1.705 l
+114.888 -1.705 l
+114.844 -1.278 l
+114.638 -1.613 114.333 -1.779 113.933 -1.779 c
+113.521 -1.779 113.197 -1.624 112.962 -1.309 c
+112.727 -0.985 112.609 -0.529 112.609 0.059 c
+h
+113.257 0.088 m
+113.257 -0.353 113.319 -0.683 113.448 -0.897 c
+113.584 -1.103 113.804 -1.205 114.109 -1.205 c
+114.432 -1.205 114.671 -1.043 114.829 -0.721 c
+114.829 1.294 l
+114.66 1.606 114.421 1.764 114.109 1.764 c
+113.804 1.764 113.584 1.661 113.448 1.455 c
+113.319 1.249 113.257 0.926 113.257 0.485 c
+h
+119.048 3.234 m
+119.048 2.278 l
+119.651 2.278 l
+119.651 1.749 l
+119.048 1.749 l
+119.048 -0.721 l
+119.048 -0.878 119.07 -0.995 119.121 -1.073 c
+119.18 -1.153 119.269 -1.191 119.386 -1.191 c
+119.474 -1.191 119.562 -1.176 119.651 -1.147 c
+119.651 -1.705 l
+119.504 -1.753 119.35 -1.779 119.194 -1.779 c
+118.938 -1.779 118.743 -1.687 118.607 -1.5 c
+118.467 -1.315 118.401 -1.055 118.401 -0.721 c
+118.401 1.749 l
+117.798 1.749 l
+117.798 2.278 l
+118.401 2.278 l
+118.401 3.234 l
+h
+120.21 0.47 m
+120.21 1.047 120.345 1.503 120.621 1.837 c
+120.904 2.18 121.274 2.352 121.738 2.352 c
+122.197 2.352 122.564 2.183 122.84 1.852 c
+123.123 1.529 123.27 1.081 123.281 0.515 c
+123.281 0.088 l
+123.281 -0.482 123.138 -0.937 122.855 -1.278 c
+122.579 -1.613 122.212 -1.779 121.752 -1.779 c
+121.29 -1.779 120.918 -1.617 120.636 -1.294 c
+120.36 -0.962 120.216 -0.522 120.21 0.029 c
+h
+120.856 0.088 m
+120.856 -0.316 120.933 -0.632 121.091 -0.867 c
+121.257 -1.103 121.477 -1.22 121.752 -1.22 c
+122.319 -1.22 122.612 -0.808 122.635 0.015 c
+122.635 0.47 l
+122.635 0.871 122.55 1.191 122.385 1.426 c
+122.227 1.669 122.01 1.793 121.738 1.793 c
+121.473 1.793 121.257 1.669 121.091 1.426 c
+120.933 1.191 120.856 0.871 120.856 0.47 c
+h
+126.691 3.234 m
+126.691 2.278 l
+127.294 2.278 l
+127.294 1.749 l
+126.691 1.749 l
+126.691 -0.721 l
+126.691 -0.878 126.714 -0.995 126.765 -1.073 c
+126.824 -1.153 126.912 -1.191 127.03 -1.191 c
+127.117 -1.191 127.206 -1.176 127.294 -1.147 c
+127.294 -1.705 l
+127.147 -1.753 126.993 -1.779 126.838 -1.779 c
+126.581 -1.779 126.386 -1.687 126.25 -1.5 c
+126.111 -1.315 126.045 -1.055 126.045 -0.721 c
+126.045 1.749 l
+125.442 1.749 l
+125.442 2.278 l
+126.045 2.278 l
+126.045 3.234 l
+h
+128.705 1.866 m
+128.958 2.19 129.278 2.352 129.66 2.352 c
+130.366 2.352 130.722 1.881 130.734 0.941 c
+130.734 -1.705 l
+130.087 -1.705 l
+130.087 0.912 l
+130.087 1.224 130.032 1.444 129.926 1.573 c
+129.815 1.698 129.66 1.764 129.455 1.764 c
+129.297 1.764 129.149 1.709 129.014 1.602 c
+128.885 1.492 128.783 1.357 128.705 1.191 c
+128.705 -1.705 l
+128.058 -1.705 l
+128.058 3.94 l
+128.705 3.94 l
+h
+133.115 -1.779 m
+132.615 -1.779 132.233 -1.631 131.969 -1.338 c
+131.703 -1.043 131.572 -0.61 131.572 -0.029 c
+131.572 0.441 l
+131.572 1.037 131.697 1.503 131.954 1.837 c
+132.218 2.18 132.578 2.352 133.041 2.352 c
+133.501 2.352 133.843 2.198 134.07 1.897 c
+134.306 1.602 134.427 1.139 134.438 0.515 c
+134.438 0.088 l
+132.218 0.088 l
+132.218 0 l
+132.218 -0.434 132.295 -0.746 132.453 -0.941 c
+132.619 -1.128 132.85 -1.22 133.145 -1.22 c
+133.339 -1.22 133.512 -1.187 133.658 -1.117 c
+133.806 -1.04 133.942 -0.922 134.07 -0.764 c
+134.408 -1.176 l
+134.122 -1.58 133.692 -1.779 133.115 -1.779 c
+133.041 1.793 m
+132.766 1.793 132.563 1.698 132.439 1.514 c
+132.31 1.326 132.237 1.037 132.218 0.647 c
+133.791 0.647 l
+133.791 0.735 l
+133.769 1.118 133.703 1.386 133.585 1.544 c
+133.467 1.709 133.284 1.793 133.041 1.793 c
+138.877 -0.691 m
+138.877 -0.544 138.822 -0.422 138.715 -0.324 c
+138.605 -0.228 138.4 -0.11 138.098 0.029 c
+137.752 0.177 137.51 0.298 137.363 0.397 c
+137.216 0.503 137.106 0.621 137.039 0.75 c
+136.97 0.875 136.937 1.033 136.937 1.22 c
+136.937 1.544 137.054 1.812 137.29 2.028 c
+137.525 2.242 137.826 2.352 138.201 2.352 c
+138.583 2.352 138.892 2.238 139.127 2.014 c
+139.362 1.786 139.48 1.5 139.48 1.147 c
+138.832 1.147 l
+138.832 1.323 138.774 1.474 138.656 1.602 c
+138.539 1.727 138.385 1.793 138.201 1.793 c
+138.003 1.793 137.851 1.738 137.745 1.631 c
+137.635 1.532 137.583 1.4 137.583 1.235 c
+137.583 1.106 137.62 1 137.701 0.912 c
+137.778 0.831 137.97 0.728 138.275 0.603 c
+138.752 0.416 139.083 0.228 139.259 0.044 c
+139.435 -0.133 139.524 -0.36 139.524 -0.632 c
+139.524 -0.985 139.399 -1.264 139.156 -1.469 c
+138.921 -1.675 138.605 -1.779 138.215 -1.779 c
+137.793 -1.779 137.455 -1.661 137.201 -1.426 c
+136.944 -1.183 136.819 -0.878 136.819 -0.515 c
+137.466 -0.515 l
+137.473 -0.742 137.543 -0.918 137.672 -1.043 c
+137.797 -1.161 137.98 -1.22 138.215 -1.22 c
+138.429 -1.22 138.591 -1.172 138.701 -1.073 c
+138.818 -0.977 138.877 -0.849 138.877 -0.691 c
+141.214 3.234 m
+141.214 2.278 l
+141.816 2.278 l
+141.816 1.749 l
+141.214 1.749 l
+141.214 -0.721 l
+141.214 -0.878 141.236 -0.995 141.288 -1.073 c
+141.346 -1.153 141.435 -1.191 141.552 -1.191 c
+141.641 -1.191 141.729 -1.176 141.816 -1.147 c
+141.816 -1.705 l
+141.67 -1.753 141.515 -1.779 141.361 -1.779 c
+141.104 -1.779 140.909 -1.687 140.773 -1.5 c
+140.634 -1.315 140.567 -1.055 140.567 -0.721 c
+140.567 1.749 l
+139.965 1.749 l
+139.965 2.278 l
+140.567 2.278 l
+140.567 3.234 l
+h
+144.625 -1.705 m
+144.584 -1.617 144.558 -1.469 144.551 -1.264 c
+144.316 -1.61 144.022 -1.779 143.669 -1.779 c
+143.305 -1.779 143.022 -1.683 142.816 -1.484 c
+142.618 -1.278 142.522 -0.992 142.522 -0.617 c
+142.522 -0.216 142.658 0.103 142.934 0.338 c
+143.206 0.58 143.58 0.706 144.051 0.706 c
+144.536 0.706 l
+144.536 1.132 l
+144.536 1.367 144.481 1.532 144.374 1.631 c
+144.264 1.738 144.102 1.793 143.889 1.793 c
+143.691 1.793 143.53 1.735 143.404 1.617 c
+143.287 1.5 143.228 1.353 143.228 1.176 c
+142.581 1.176 l
+142.581 1.371 142.64 1.562 142.757 1.749 c
+142.882 1.933 143.044 2.08 143.243 2.19 c
+143.449 2.297 143.676 2.352 143.933 2.352 c
+144.334 2.352 144.639 2.249 144.845 2.043 c
+145.058 1.837 145.172 1.544 145.182 1.161 c
+145.182 -0.852 l
+145.182 -1.157 145.22 -1.422 145.3 -1.646 c
+145.3 -1.705 l
+h
+143.757 -1.191 m
+143.923 -1.191 144.073 -1.147 144.213 -1.058 c
+144.359 -0.97 144.466 -0.86 144.536 -0.721 c
+144.536 0.22 l
+144.168 0.22 l
+143.852 0.22 143.61 0.151 143.434 0.015 c
+143.258 -0.114 143.169 -0.301 143.169 -0.544 c
+143.169 -0.771 143.213 -0.937 143.301 -1.043 c
+143.389 -1.143 143.54 -1.191 143.757 -1.191 c
+146.05 0.47 m
+146.05 1.087 146.161 1.551 146.388 1.866 c
+146.612 2.19 146.946 2.352 147.388 2.352 c
+147.788 2.352 148.093 2.176 148.299 1.823 c
+148.343 2.278 l
+148.931 2.278 l
+148.931 -1.749 l
+148.931 -2.238 148.802 -2.616 148.549 -2.881 c
+148.292 -3.146 147.939 -3.278 147.491 -3.278 c
+147.292 -3.278 147.071 -3.227 146.829 -3.131 c
+146.583 -3.032 146.403 -2.911 146.285 -2.763 c
+146.55 -2.323 l
+146.815 -2.587 147.112 -2.72 147.447 -2.72 c
+147.983 -2.72 148.259 -2.425 148.27 -1.837 c
+148.27 -1.309 l
+148.064 -1.624 147.763 -1.779 147.373 -1.779 c
+146.961 -1.779 146.638 -1.627 146.403 -1.323 c
+146.175 -1.01 146.057 -0.559 146.05 0.029 c
+h
+146.711 0.088 m
+146.711 -0.353 146.774 -0.683 146.903 -0.897 c
+147.027 -1.103 147.245 -1.205 147.549 -1.205 c
+147.873 -1.205 148.112 -1.04 148.27 -0.706 c
+148.27 1.278 l
+148.101 1.602 147.862 1.764 147.549 1.764 c
+147.256 1.764 147.038 1.661 146.903 1.455 c
+146.774 1.249 146.711 0.926 146.711 0.485 c
+h
+150.592 -1.705 -0.646 3.983 re
+150.636 3.322 m
+150.636 3.212 150.607 3.12 150.548 3.042 c
+150.489 2.973 150.394 2.94 150.269 2.94 c
+150.151 2.94 150.055 2.973 149.99 3.042 c
+149.93 3.12 149.901 3.212 149.901 3.322 c
+149.901 3.439 149.93 3.532 149.99 3.601 c
+150.055 3.678 150.151 3.719 150.269 3.719 c
+150.394 3.719 150.489 3.678 150.548 3.601 c
+150.607 3.52 150.636 3.429 150.636 3.322 c
+152.224 2.278 m
+152.238 1.837 l
+152.492 2.18 152.816 2.352 153.209 2.352 c
+153.914 2.352 154.271 1.881 154.281 0.941 c
+154.281 -1.705 l
+153.635 -1.705 l
+153.635 0.912 l
+153.635 1.224 153.579 1.444 153.473 1.573 c
+153.363 1.698 153.209 1.764 153.003 1.764 c
+152.845 1.764 152.698 1.709 152.562 1.602 c
+152.433 1.492 152.33 1.357 152.253 1.191 c
+152.253 -1.705 l
+151.607 -1.705 l
+151.607 2.278 l
+h
+155.119 0.47 m
+155.119 1.087 155.23 1.551 155.457 1.866 c
+155.682 2.19 156.016 2.352 156.457 2.352 c
+156.858 2.352 157.163 2.176 157.369 1.823 c
+157.412 2.278 l
+158 2.278 l
+158 -1.749 l
+158 -2.238 157.872 -2.616 157.618 -2.881 c
+157.361 -3.146 157.008 -3.278 156.56 -3.278 c
+156.361 -3.278 156.141 -3.227 155.898 -3.131 c
+155.652 -3.032 155.472 -2.911 155.355 -2.763 c
+155.619 -2.323 l
+155.883 -2.587 156.182 -2.72 156.516 -2.72 c
+157.053 -2.72 157.328 -2.425 157.339 -1.837 c
+157.339 -1.309 l
+157.134 -1.624 156.832 -1.779 156.442 -1.779 c
+156.031 -1.779 155.707 -1.627 155.472 -1.323 c
+155.245 -1.01 155.127 -0.559 155.119 0.029 c
+h
+155.781 0.088 m
+155.781 -0.353 155.844 -0.683 155.972 -0.897 c
+156.097 -1.103 156.314 -1.205 156.619 -1.205 c
+156.942 -1.205 157.181 -1.04 157.339 -0.706 c
+157.339 1.278 l
+157.17 1.602 156.931 1.764 156.619 1.764 c
+156.325 1.764 156.108 1.661 155.972 1.455 c
+155.844 1.249 155.781 0.926 155.781 0.485 c
+h
+162.719 -1.705 m
+162.678 -1.617 162.653 -1.469 162.645 -1.264 c
+162.41 -1.61 162.116 -1.779 161.763 -1.779 c
+161.4 -1.779 161.117 -1.683 160.911 -1.484 c
+160.712 -1.278 160.617 -0.992 160.617 -0.617 c
+160.617 -0.216 160.753 0.103 161.028 0.338 c
+161.3 0.58 161.675 0.706 162.146 0.706 c
+162.63 0.706 l
+162.63 1.132 l
+162.63 1.367 162.576 1.532 162.469 1.631 c
+162.358 1.738 162.197 1.793 161.984 1.793 c
+161.786 1.793 161.624 1.735 161.499 1.617 c
+161.381 1.5 161.323 1.353 161.323 1.176 c
+160.675 1.176 l
+160.675 1.371 160.735 1.562 160.852 1.749 c
+160.977 1.933 161.138 2.08 161.337 2.19 c
+161.543 2.297 161.77 2.352 162.028 2.352 c
+162.429 2.352 162.734 2.249 162.939 2.043 c
+163.152 1.837 163.266 1.544 163.278 1.161 c
+163.278 -0.852 l
+163.278 -1.157 163.314 -1.422 163.395 -1.646 c
+163.395 -1.705 l
+h
+161.851 -1.191 m
+162.017 -1.191 162.167 -1.147 162.308 -1.058 c
+162.454 -0.97 162.561 -0.86 162.63 -0.721 c
+162.63 0.22 l
+162.263 0.22 l
+161.947 0.22 161.705 0.151 161.528 0.015 c
+161.352 -0.114 161.263 -0.301 161.263 -0.544 c
+161.263 -0.771 161.308 -0.937 161.396 -1.043 c
+161.484 -1.143 161.635 -1.191 161.851 -1.191 c
+165.923 1.661 m
+165.835 1.679 165.736 1.691 165.629 1.691 c
+165.294 1.691 165.059 1.507 164.924 1.147 c
+164.924 -1.705 l
+164.277 -1.705 l
+164.277 2.278 l
+164.909 2.278 l
+164.924 1.866 l
+165.1 2.19 165.342 2.352 165.659 2.352 c
+165.765 2.352 165.853 2.33 165.923 2.294 c
+h
+167.922 -1.779 m
+167.422 -1.779 167.04 -1.631 166.776 -1.338 c
+166.511 -1.043 166.379 -0.61 166.379 -0.029 c
+166.379 0.441 l
+166.379 1.037 166.504 1.503 166.761 1.837 c
+167.025 2.18 167.386 2.352 167.849 2.352 c
+168.309 2.352 168.65 2.198 168.878 1.897 c
+169.113 1.602 169.234 1.139 169.246 0.515 c
+169.246 0.088 l
+167.025 0.088 l
+167.025 0 l
+167.025 -0.434 167.103 -0.746 167.261 -0.941 c
+167.426 -1.128 167.658 -1.22 167.952 -1.22 c
+168.147 -1.22 168.319 -1.187 168.466 -1.117 c
+168.613 -1.04 168.749 -0.922 168.878 -0.764 c
+169.215 -1.176 l
+168.929 -1.58 168.5 -1.779 167.922 -1.779 c
+167.849 1.793 m
+167.573 1.793 167.371 1.698 167.246 1.514 c
+167.118 1.326 167.044 1.037 167.025 0.647 c
+168.598 0.647 l
+168.598 0.735 l
+168.577 1.118 168.51 1.386 168.392 1.544 c
+168.275 1.709 168.091 1.793 167.849 1.793 c
+172.068 -1.705 m
+172.027 -1.617 172.001 -1.469 171.993 -1.264 c
+171.758 -1.61 171.465 -1.779 171.112 -1.779 c
+170.748 -1.779 170.465 -1.683 170.26 -1.484 c
+170.061 -1.278 169.965 -0.992 169.965 -0.617 c
+169.965 -0.216 170.102 0.103 170.377 0.338 c
+170.649 0.58 171.024 0.706 171.494 0.706 c
+171.979 0.706 l
+171.979 1.132 l
+171.979 1.367 171.924 1.532 171.818 1.631 c
+171.707 1.738 171.546 1.793 171.332 1.793 c
+171.134 1.793 170.973 1.735 170.848 1.617 c
+170.73 1.5 170.671 1.353 170.671 1.176 c
+170.025 1.176 l
+170.025 1.371 170.083 1.562 170.2 1.749 c
+170.326 1.933 170.487 2.08 170.686 2.19 c
+170.892 2.297 171.12 2.352 171.376 2.352 c
+171.777 2.352 172.082 2.249 172.288 2.043 c
+172.501 1.837 172.615 1.544 172.626 1.161 c
+172.626 -0.852 l
+172.626 -1.157 172.662 -1.422 172.743 -1.646 c
+172.743 -1.705 l
+h
+171.2 -1.191 m
+171.366 -1.191 171.517 -1.147 171.656 -1.058 c
+171.803 -0.97 171.91 -0.86 171.979 -0.721 c
+171.979 0.22 l
+171.612 0.22 l
+171.295 0.22 171.053 0.151 170.877 0.015 c
+170.7 -0.114 170.612 -0.301 170.612 -0.544 c
+170.612 -0.771 170.657 -0.937 170.744 -1.043 c
+170.833 -1.143 170.983 -1.191 171.2 -1.191 c
+173.67 -1.352 m
+173.67 -1.234 173.703 -1.139 173.772 -1.058 c
+173.838 -0.981 173.942 -0.941 174.081 -0.941 c
+174.228 -0.941 174.335 -0.981 174.405 -1.058 c
+174.482 -1.139 174.522 -1.234 174.522 -1.352 c
+174.522 -1.463 174.482 -1.554 174.405 -1.631 c
+174.335 -1.708 174.228 -1.749 174.081 -1.749 c
+173.942 -1.749 173.838 -1.708 173.772 -1.631 c
+173.703 -1.554 173.67 -1.463 173.67 -1.352 c
+180.784 0 m
+180.755 -0.58 180.593 -1.022 180.299 -1.323 c
+180.005 -1.627 179.586 -1.779 179.049 -1.779 c
+178.52 -1.779 178.094 -1.58 177.771 -1.176 c
+177.454 -0.764 177.3 -0.206 177.3 0.5 c
+177.3 1.47 l
+177.3 2.165 177.462 2.712 177.786 3.117 c
+178.108 3.516 178.553 3.719 179.123 3.719 c
+179.63 3.719 180.027 3.561 180.313 3.248 c
+180.597 2.944 180.755 2.502 180.784 1.926 c
+180.093 1.926 l
+180.064 2.367 179.968 2.679 179.814 2.866 c
+179.667 3.05 179.436 3.146 179.123 3.146 c
+178.748 3.146 178.465 2.999 178.27 2.705 c
+178.072 2.418 177.977 2.003 177.977 1.455 c
+177.977 0.47 l
+177.977 -0.07 178.068 -0.485 178.256 -0.779 c
+178.439 -1.066 178.704 -1.205 179.049 -1.205 c
+179.402 -1.205 179.656 -1.117 179.814 -0.941 c
+179.968 -0.764 180.064 -0.452 180.093 0 c
+h
+181.46 0.47 m
+181.46 1.047 181.596 1.503 181.871 1.837 c
+182.154 2.18 182.526 2.352 182.989 2.352 c
+183.448 2.352 183.816 2.183 184.091 1.852 c
+184.375 1.529 184.521 1.081 184.533 0.515 c
+184.533 0.088 l
+184.533 -0.482 184.389 -0.937 184.105 -1.278 c
+183.831 -1.613 183.463 -1.779 183.004 -1.779 c
+182.54 -1.779 182.169 -1.617 181.886 -1.294 c
+181.611 -0.962 181.468 -0.522 181.46 0.029 c
+h
+182.106 0.088 m
+182.106 -0.316 182.185 -0.632 182.342 -0.867 c
+182.507 -1.103 182.728 -1.22 183.004 -1.22 c
+183.569 -1.22 183.864 -0.808 183.885 0.015 c
+183.885 0.47 l
+183.885 0.871 183.801 1.191 183.635 1.426 c
+183.477 1.669 183.261 1.793 182.989 1.793 c
+182.724 1.793 182.507 1.669 182.342 1.426 c
+182.185 1.191 182.106 0.871 182.106 0.47 c
+h
+185.987 2.278 m
+186.002 1.911 l
+186.245 2.205 186.565 2.352 186.958 2.352 c
+187.398 2.352 187.708 2.153 187.884 1.764 c
+188.138 2.153 188.487 2.352 188.927 2.352 c
+189.662 2.352 190.037 1.889 190.059 0.97 c
+190.059 -1.705 l
+189.412 -1.705 l
+189.412 0.912 l
+189.412 1.205 189.357 1.419 189.25 1.558 c
+189.152 1.694 188.979 1.764 188.736 1.764 c
+188.537 1.764 188.376 1.683 188.251 1.529 c
+188.134 1.382 188.064 1.191 188.045 0.956 c
+188.045 -1.705 l
+187.384 -1.705 l
+187.384 0.941 l
+187.384 1.488 187.163 1.764 186.723 1.764 c
+186.388 1.764 186.153 1.602 186.017 1.278 c
+186.017 -1.705 l
+185.37 -1.705 l
+185.37 2.278 l
+h
+191.646 2.278 m
+191.662 1.911 l
+191.904 2.205 192.223 2.352 192.616 2.352 c
+193.058 2.352 193.366 2.153 193.543 1.764 c
+193.796 2.153 194.145 2.352 194.586 2.352 c
+195.321 2.352 195.696 1.889 195.718 0.97 c
+195.718 -1.705 l
+195.072 -1.705 l
+195.072 0.912 l
+195.072 1.205 195.016 1.419 194.91 1.558 c
+194.81 1.694 194.638 1.764 194.395 1.764 c
+194.197 1.764 194.035 1.683 193.91 1.529 c
+193.792 1.382 193.723 1.191 193.705 0.956 c
+193.705 -1.705 l
+193.043 -1.705 l
+193.043 0.941 l
+193.043 1.488 192.822 1.764 192.381 1.764 c
+192.047 1.764 191.812 1.602 191.676 1.278 c
+191.676 -1.705 l
+191.029 -1.705 l
+191.029 2.278 l
+h
+197.393 -1.705 -0.646 3.983 re
+197.438 3.322 m
+197.438 3.212 197.408 3.12 197.35 3.042 c
+197.291 2.973 197.196 2.94 197.071 2.94 c
+196.953 2.94 196.857 2.973 196.791 3.042 c
+196.732 3.12 196.703 3.212 196.703 3.322 c
+196.703 3.439 196.732 3.532 196.791 3.601 c
+196.857 3.678 196.953 3.719 197.071 3.719 c
+197.196 3.719 197.291 3.678 197.35 3.601 c
+197.408 3.52 197.438 3.429 197.438 3.322 c
+199.261 3.234 m
+199.261 2.278 l
+199.863 2.278 l
+199.863 1.749 l
+199.261 1.749 l
+199.261 -0.721 l
+199.261 -0.878 199.282 -0.995 199.334 -1.073 c
+199.392 -1.153 199.481 -1.191 199.599 -1.191 c
+199.687 -1.191 199.775 -1.176 199.863 -1.147 c
+199.863 -1.705 l
+199.716 -1.753 199.562 -1.779 199.408 -1.779 c
+199.151 -1.779 198.956 -1.687 198.82 -1.5 c
+198.68 -1.315 198.614 -1.055 198.614 -0.721 c
+198.614 1.749 l
+198.012 1.749 l
+198.012 2.278 l
+198.614 2.278 l
+198.614 3.234 l
+h
+f
+Q
+q 1 0 0 1 503.1638 213.6016 cm
+0 0 m
+0.029 -0.368 l
+0.264 -0.073 0.573 0.073 0.956 0.073 c
+1.356 0.073 1.635 -0.11 1.793 -0.47 c
+2.028 -0.11 2.356 0.073 2.778 0.073 c
+3.472 0.073 3.825 -0.412 3.836 -1.382 c
+3.836 -3.983 l
+2.807 -3.983 l
+2.807 -1.44 l
+2.807 -1.216 2.77 -1.055 2.705 -0.956 c
+2.645 -0.86 2.535 -0.808 2.381 -0.808 c
+2.182 -0.808 2.043 -0.926 1.955 -1.161 c
+1.955 -3.983 l
+0.912 -3.983 l
+0.912 -1.455 l
+0.912 -1.22 0.881 -1.055 0.823 -0.956 c
+0.764 -0.86 0.654 -0.808 0.499 -0.808 c
+0.324 -0.808 0.18 -0.904 0.073 -1.087 c
+0.073 -3.983 l
+-0.97 -3.983 l
+-0.97 0 l
+h
+6.57 -3.616 m
+6.354 -3.91 6.063 -4.057 5.703 -4.057 c
+5.34 -4.057 5.06 -3.936 4.866 -3.69 c
+4.678 -3.436 4.586 -3.069 4.586 -2.587 c
+4.586 0 l
+5.629 0 l
+5.629 -2.602 l
+5.629 -2.995 5.754 -3.19 6.012 -3.19 c
+6.247 -3.19 6.416 -3.087 6.526 -2.881 c
+6.526 0 l
+7.57 0 l
+7.57 -3.983 l
+6.6 -3.983 l
+h
+10.084 -2.911 m
+10.084 -2.822 10.04 -2.745 9.951 -2.675 c
+9.863 -2.598 9.675 -2.495 9.392 -2.367 c
+8.959 -2.19 8.661 -2.01 8.496 -1.823 c
+8.338 -1.639 8.261 -1.407 8.261 -1.132 c
+8.261 -0.79 8.382 -0.507 8.628 -0.279 c
+8.882 -0.044 9.22 0.073 9.643 0.073 c
+10.073 0.073 10.421 -0.04 10.686 -0.264 c
+10.951 -0.492 11.083 -0.794 11.083 -1.176 c
+10.04 -1.176 l
+10.04 -0.852 9.899 -0.69 9.628 -0.69 c
+9.517 -0.69 9.429 -0.727 9.363 -0.794 c
+9.294 -0.864 9.261 -0.962 9.261 -1.087 c
+9.261 -1.176 9.297 -1.257 9.378 -1.323 c
+9.455 -1.382 9.635 -1.477 9.922 -1.602 c
+10.352 -1.76 10.649 -1.937 10.819 -2.132 c
+10.994 -2.319 11.083 -2.568 11.083 -2.881 c
+11.083 -3.234 10.951 -3.52 10.686 -3.734 c
+10.421 -3.95 10.073 -4.057 9.643 -4.057 c
+9.348 -4.057 9.088 -4.002 8.864 -3.896 c
+8.636 -3.778 8.459 -3.616 8.334 -3.41 c
+8.216 -3.204 8.158 -2.984 8.158 -2.749 c
+9.143 -2.749 l
+9.143 -2.936 9.18 -3.072 9.261 -3.16 c
+9.348 -3.248 9.481 -3.293 9.658 -3.293 c
+9.94 -3.293 10.084 -3.167 10.084 -2.911 c
+12.95 0.97 m
+12.95 0 l
+13.479 0 l
+13.479 -0.794 l
+12.95 -0.794 l
+12.95 -2.764 l
+12.95 -2.921 12.968 -3.028 13.008 -3.087 c
+13.057 -3.146 13.141 -3.175 13.259 -3.175 c
+13.365 -3.175 13.45 -3.167 13.508 -3.146 c
+13.508 -3.954 l
+13.332 -4.02 13.141 -4.057 12.935 -4.057 c
+12.259 -4.057 11.913 -3.671 11.906 -2.896 c
+11.906 -0.794 l
+11.451 -0.794 l
+11.451 0 l
+11.906 0 l
+11.906 0.97 l
+h
+f
+Q
+q 1 0 0 1 468.3414 203.8415 cm
+0 0 m
+0.225 0.283 0.5 0.426 0.823 0.426 c
+1.183 0.426 1.459 0.297 1.646 0.044 c
+1.841 -0.214 1.941 -0.595 1.941 -1.103 c
+1.941 -3.63 l
+0.897 -3.63 l
+0.897 -1.118 l
+0.897 -0.882 0.857 -0.717 0.779 -0.617 c
+0.709 -0.511 0.595 -0.455 0.441 -0.455 c
+0.254 -0.455 0.107 -0.54 0 -0.706 c
+0 -3.63 l
+-1.043 -3.63 l
+-1.043 2.014 l
+0 2.014 l
+h
+4.572 -3.63 m
+4.542 -3.572 4.513 -3.469 4.484 -3.322 c
+4.296 -3.58 4.046 -3.705 3.734 -3.705 c
+3.4 -3.705 3.12 -3.597 2.896 -3.381 c
+2.679 -3.156 2.573 -2.866 2.573 -2.514 c
+2.573 -2.102 2.705 -1.786 2.97 -1.558 c
+3.234 -1.323 3.616 -1.205 4.116 -1.205 c
+4.439 -1.205 l
+4.439 -0.882 l
+4.439 -0.706 4.403 -0.584 4.337 -0.515 c
+4.278 -0.437 4.189 -0.397 4.072 -0.397 c
+3.815 -0.397 3.69 -0.551 3.69 -0.852 c
+2.646 -0.852 l
+2.646 -0.482 2.782 -0.177 3.057 0.058 c
+3.329 0.301 3.679 0.426 4.102 0.426 c
+4.542 0.426 4.881 0.309 5.116 0.073 c
+5.358 -0.154 5.483 -0.478 5.483 -0.897 c
+5.483 -2.764 l
+5.483 -3.109 5.531 -3.377 5.63 -3.572 c
+5.63 -3.63 l
+h
+3.969 -2.881 m
+4.075 -2.881 4.167 -2.863 4.248 -2.822 c
+4.337 -2.774 4.399 -2.716 4.439 -2.646 c
+4.439 -1.823 l
+4.189 -1.823 l
+4.013 -1.823 3.87 -1.881 3.763 -1.999 c
+3.664 -2.109 3.616 -2.256 3.616 -2.44 c
+3.616 -2.734 3.734 -2.881 3.969 -2.881 c
+7.482 -2.161 m
+7.982 0.353 l
+9.07 0.353 l
+7.967 -3.63 l
+6.982 -3.63 l
+5.88 0.353 l
+6.968 0.353 l
+h
+11.113 -3.705 m
+10.583 -3.705 10.165 -3.549 9.864 -3.234 c
+9.569 -2.911 9.422 -2.451 9.422 -1.852 c
+9.422 -1.544 l
+9.422 -0.919 9.559 -0.434 9.834 -0.088 c
+10.106 0.254 10.5 0.426 11.009 0.426 c
+11.51 0.426 11.881 0.264 12.127 -0.059 c
+12.381 -0.382 12.513 -0.86 12.524 -1.484 c
+12.524 -1.984 l
+10.452 -1.984 l
+10.469 -2.278 10.533 -2.495 10.643 -2.631 c
+10.76 -2.77 10.94 -2.837 11.186 -2.837 c
+11.528 -2.837 11.819 -2.72 12.054 -2.484 c
+12.465 -3.117 l
+12.337 -3.293 12.149 -3.436 11.907 -3.543 c
+11.66 -3.649 11.396 -3.705 11.113 -3.705 c
+10.466 -1.264 m
+11.495 -1.264 l
+11.495 -1.161 l
+11.495 -0.926 11.454 -0.75 11.377 -0.632 c
+11.308 -0.507 11.179 -0.441 10.995 -0.441 c
+10.819 -0.441 10.687 -0.511 10.598 -0.647 c
+10.517 -0.775 10.473 -0.981 10.466 -1.264 c
+f
+Q
+q 1 0 0 1 485.3189 200.2112 cm
+0 0 m
+-0.04 0.087 -0.066 0.235 -0.073 0.44 c
+-0.309 0.095 -0.602 -0.074 -0.955 -0.074 c
+-1.319 -0.074 -1.602 0.022 -1.808 0.22 c
+-2.007 0.426 -2.102 0.712 -2.102 1.087 c
+-2.102 1.488 -1.966 1.807 -1.691 2.042 c
+-1.419 2.285 -1.043 2.41 -0.573 2.41 c
+-0.088 2.41 l
+-0.088 2.836 l
+-0.088 3.072 -0.143 3.237 -0.249 3.336 c
+-0.36 3.443 -0.521 3.498 -0.735 3.498 c
+-0.933 3.498 -1.095 3.439 -1.22 3.322 c
+-1.338 3.204 -1.396 3.057 -1.396 2.881 c
+-2.043 2.881 l
+-2.043 3.075 -1.984 3.266 -1.866 3.453 c
+-1.741 3.638 -1.58 3.785 -1.382 3.895 c
+-1.176 4.002 -0.948 4.056 -0.691 4.056 c
+-0.29 4.056 0.015 3.954 0.221 3.748 c
+0.434 3.542 0.547 3.248 0.559 2.865 c
+0.559 0.852 l
+0.559 0.548 0.595 0.282 0.676 0.058 c
+0.676 0 l
+h
+-0.867 0.514 m
+-0.702 0.514 -0.551 0.558 -0.411 0.646 c
+-0.264 0.735 -0.158 0.845 -0.088 0.984 c
+-0.088 1.925 l
+-0.455 1.925 l
+-0.771 1.925 -1.014 1.855 -1.19 1.72 c
+-1.367 1.591 -1.455 1.404 -1.455 1.161 c
+-1.455 0.933 -1.411 0.768 -1.323 0.661 c
+-1.234 0.562 -1.084 0.514 -0.867 0.514 c
+3.896 3.983 m
+3.91 3.615 l
+4.152 3.91 4.472 4.056 4.865 4.056 c
+5.307 4.056 5.615 3.858 5.791 3.469 c
+6.045 3.858 6.394 4.056 6.835 4.056 c
+7.57 4.056 7.945 3.594 7.967 2.675 c
+7.967 0 l
+7.32 0 l
+7.32 2.616 l
+7.32 2.91 7.265 3.123 7.159 3.262 c
+7.059 3.399 6.887 3.469 6.644 3.469 c
+6.446 3.469 6.284 3.388 6.159 3.233 c
+6.041 3.087 5.972 2.896 5.953 2.66 c
+5.953 0 l
+5.292 0 l
+5.292 2.645 l
+5.292 3.193 5.072 3.469 4.63 3.469 c
+4.296 3.469 4.061 3.307 3.925 2.983 c
+3.925 0 l
+3.278 0 l
+3.278 3.983 l
+h
+10.363 -0.074 m
+9.864 -0.074 9.481 0.073 9.216 0.367 c
+8.952 0.661 8.819 1.095 8.819 1.675 c
+8.819 2.146 l
+8.819 2.741 8.944 3.208 9.201 3.542 c
+9.467 3.884 9.827 4.056 10.29 4.056 c
+10.749 4.056 11.09 3.902 11.318 3.601 c
+11.553 3.307 11.675 2.844 11.686 2.219 c
+11.686 1.793 l
+9.467 1.793 l
+9.467 1.705 l
+9.467 1.271 9.544 0.959 9.702 0.764 c
+9.866 0.577 10.099 0.484 10.392 0.484 c
+10.587 0.484 10.76 0.517 10.907 0.588 c
+11.054 0.665 11.19 0.783 11.318 0.941 c
+11.657 0.529 l
+11.37 0.124 10.94 -0.074 10.363 -0.074 c
+10.29 3.498 m
+10.014 3.498 9.812 3.403 9.687 3.218 c
+9.558 3.031 9.485 2.741 9.467 2.352 c
+11.04 2.352 l
+11.04 2.439 l
+11.017 2.822 10.951 3.09 10.834 3.248 c
+10.716 3.414 10.533 3.498 10.29 3.498 c
+14.406 1.014 m
+14.406 1.161 14.35 1.282 14.244 1.381 c
+14.134 1.477 13.928 1.595 13.627 1.734 c
+13.28 1.881 13.039 2.003 12.891 2.102 c
+12.744 2.208 12.634 2.326 12.568 2.454 c
+12.498 2.58 12.465 2.738 12.465 2.925 c
+12.465 3.248 12.582 3.516 12.818 3.733 c
+13.053 3.946 13.355 4.056 13.729 4.056 c
+14.111 4.056 14.42 3.943 14.655 3.719 c
+14.89 3.491 15.008 3.204 15.008 2.851 c
+14.361 2.851 l
+14.361 3.027 14.302 3.179 14.184 3.307 c
+14.067 3.432 13.913 3.498 13.729 3.498 c
+13.531 3.498 13.38 3.443 13.274 3.336 c
+13.163 3.237 13.112 3.104 13.112 2.94 c
+13.112 2.811 13.149 2.705 13.23 2.616 c
+13.307 2.535 13.498 2.433 13.802 2.308 c
+14.28 2.12 14.611 1.932 14.788 1.749 c
+14.963 1.572 15.052 1.344 15.052 1.072 c
+15.052 0.72 14.927 0.44 14.685 0.235 c
+14.45 0.029 14.134 -0.074 13.744 -0.074 c
+13.321 -0.074 12.983 0.043 12.729 0.278 c
+12.472 0.521 12.347 0.827 12.347 1.19 c
+12.994 1.19 l
+13.002 0.962 13.072 0.786 13.199 0.661 c
+13.325 0.544 13.509 0.484 13.744 0.484 c
+13.957 0.484 14.119 0.532 14.229 0.631 c
+14.346 0.727 14.406 0.856 14.406 1.014 c
+17.83 1.014 m
+17.83 1.161 17.775 1.282 17.668 1.381 c
+17.558 1.477 17.353 1.595 17.051 1.734 c
+16.706 1.881 16.463 2.003 16.316 2.102 c
+16.169 2.208 16.059 2.326 15.993 2.454 c
+15.923 2.58 15.89 2.738 15.89 2.925 c
+15.89 3.248 16.008 3.516 16.243 3.733 c
+16.478 3.946 16.779 4.056 17.154 4.056 c
+17.536 4.056 17.845 3.943 18.08 3.719 c
+18.315 3.491 18.433 3.204 18.433 2.851 c
+17.786 2.851 l
+17.786 3.027 17.727 3.179 17.61 3.307 c
+17.492 3.432 17.338 3.498 17.154 3.498 c
+16.956 3.498 16.805 3.443 16.698 3.336 c
+16.588 3.237 16.536 3.104 16.536 2.94 c
+16.536 2.811 16.573 2.705 16.654 2.616 c
+16.731 2.535 16.922 2.433 17.228 2.308 c
+17.706 2.12 18.036 1.932 18.213 1.749 c
+18.389 1.572 18.477 1.344 18.477 1.072 c
+18.477 0.72 18.352 0.44 18.109 0.235 c
+17.874 0.029 17.558 -0.074 17.168 -0.074 c
+16.746 -0.074 16.408 0.043 16.154 0.278 c
+15.898 0.521 15.772 0.827 15.772 1.19 c
+16.419 1.19 l
+16.426 0.962 16.496 0.786 16.625 0.661 c
+16.75 0.544 16.933 0.484 17.168 0.484 c
+17.382 0.484 17.544 0.532 17.654 0.631 c
+17.772 0.727 17.83 0.856 17.83 1.014 c
+21.358 0 m
+21.317 0.087 21.292 0.235 21.284 0.44 c
+21.049 0.095 20.756 -0.074 20.403 -0.074 c
+20.039 -0.074 19.755 0.022 19.549 0.22 c
+19.352 0.426 19.256 0.712 19.256 1.087 c
+19.256 1.488 19.392 1.807 19.667 2.042 c
+19.94 2.285 20.314 2.41 20.785 2.41 c
+21.27 2.41 l
+21.27 2.836 l
+21.27 3.072 21.215 3.237 21.108 3.336 c
+20.998 3.443 20.836 3.498 20.623 3.498 c
+20.424 3.498 20.263 3.439 20.137 3.322 c
+20.02 3.204 19.962 3.057 19.962 2.881 c
+19.314 2.881 l
+19.314 3.075 19.374 3.266 19.491 3.453 c
+19.616 3.638 19.778 3.785 19.977 3.895 c
+20.182 4.002 20.41 4.056 20.667 4.056 c
+21.068 4.056 21.373 3.954 21.579 3.748 c
+21.791 3.542 21.905 3.248 21.916 2.865 c
+21.916 0.852 l
+21.916 0.548 21.953 0.282 22.034 0.058 c
+22.034 0 l
+h
+20.49 0.514 m
+20.656 0.514 20.806 0.558 20.947 0.646 c
+21.093 0.735 21.2 0.845 21.27 0.984 c
+21.27 1.925 l
+20.902 1.925 l
+20.586 1.925 20.343 1.855 20.168 1.72 c
+19.991 1.591 19.902 1.404 19.902 1.161 c
+19.902 0.933 19.946 0.768 20.035 0.661 c
+20.123 0.562 20.274 0.514 20.49 0.514 c
+22.784 2.175 m
+22.784 2.792 22.894 3.256 23.121 3.571 c
+23.346 3.895 23.68 4.056 24.121 4.056 c
+24.522 4.056 24.827 3.881 25.033 3.528 c
+25.076 3.983 l
+25.664 3.983 l
+25.664 -0.044 l
+25.664 -0.533 25.536 -0.912 25.282 -1.176 c
+25.026 -1.441 24.673 -1.573 24.224 -1.573 c
+24.026 -1.573 23.805 -1.522 23.563 -1.426 c
+23.316 -1.327 23.137 -1.206 23.019 -1.058 c
+23.283 -0.618 l
+23.548 -0.882 23.846 -1.015 24.18 -1.015 c
+24.717 -1.015 24.993 -0.721 25.003 -0.133 c
+25.003 0.396 l
+24.798 0.081 24.496 -0.074 24.106 -0.074 c
+23.695 -0.074 23.372 0.077 23.137 0.382 c
+22.909 0.694 22.791 1.146 22.784 1.734 c
+h
+23.445 1.793 m
+23.445 1.352 23.507 1.022 23.636 0.808 c
+23.761 0.602 23.978 0.5 24.283 0.5 c
+24.606 0.5 24.845 0.665 25.003 0.999 c
+25.003 2.983 l
+24.835 3.307 24.596 3.469 24.283 3.469 c
+23.989 3.469 23.772 3.366 23.636 3.16 c
+23.507 2.954 23.445 2.63 23.445 2.19 c
+h
+28.046 -0.074 m
+27.546 -0.074 27.164 0.073 26.9 0.367 c
+26.635 0.661 26.502 1.095 26.502 1.675 c
+26.502 2.146 l
+26.502 2.741 26.628 3.208 26.884 3.542 c
+27.15 3.884 27.509 4.056 27.973 4.056 c
+28.432 4.056 28.773 3.902 29.001 3.601 c
+29.236 3.307 29.358 2.844 29.369 2.219 c
+29.369 1.793 l
+27.15 1.793 l
+27.15 1.705 l
+27.15 1.271 27.227 0.959 27.385 0.764 c
+27.55 0.577 27.781 0.484 28.075 0.484 c
+28.27 0.484 28.443 0.517 28.59 0.588 c
+28.737 0.665 28.873 0.783 29.001 0.941 c
+29.34 0.529 l
+29.053 0.124 28.623 -0.074 28.046 -0.074 c
+27.973 3.498 m
+27.697 3.498 27.495 3.403 27.37 3.218 c
+27.241 3.031 27.168 2.741 27.15 2.352 c
+28.722 2.352 l
+28.722 2.439 l
+28.7 2.822 28.634 3.09 28.517 3.248 c
+28.399 3.414 28.215 3.498 27.973 3.498 c
+30.883 1.514 m
+30.295 1.514 l
+30.25 5.35 l
+30.942 5.35 l
+h
+30.603 0.735 m
+30.728 0.735 30.824 0.694 30.883 0.617 c
+30.949 0.548 30.986 0.455 30.986 0.338 c
+30.986 0.228 30.949 0.135 30.883 0.058 c
+30.824 -0.008 30.728 -0.044 30.603 -0.044 c
+30.486 -0.044 30.391 -0.008 30.325 0.058 c
+30.265 0.135 30.236 0.228 30.236 0.338 c
+30.236 0.455 30.265 0.548 30.325 0.617 c
+30.391 0.694 30.486 0.735 30.603 0.735 c
+f
+Q
+0.113 0.082 0.09 0 k
+287.665 170.897 234.667 -12.895 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 164.0623 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.647 -0.243 -0.775 -0.367 -0.882 c
+-0.496 -0.992 -0.658 -1.081 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.162 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.927 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.132 l
+-2.642 0.033 -2.616 -0.059 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.683 -1.992 0.691 -1.999 0.691 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.881 -2.786 0.959 -2.91 1.058 c
+-3.039 1.153 -3.142 1.278 -3.219 1.425 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.836 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.119 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.119 -1.128 3.09 -0.97 3.042 c
+-0.804 2.992 -0.669 2.917 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.252 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.352 c
+-1.294 1.311 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.319 2.385 -2.366 2.337 c
+-2.406 2.296 -2.436 2.248 -2.454 2.19 c
+-2.477 2.131 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.778 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.469 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.091 -0.86 0.176 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.529 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.53 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.66 m
+6.184 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.22 5.108 -2.103 c
+5.039 -1.985 4.991 -1.856 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.86 6.064 -1.941 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.058 6.681 -2.028 c
+6.758 -1.999 6.828 -1.945 6.887 -1.867 c
+6.945 -1.797 6.99 -1.706 7.019 -1.588 c
+7.056 -1.47 7.078 -1.323 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.073 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.412 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.234 c
+4.946 1.448 5.027 1.631 5.137 1.778 c
+5.244 1.933 5.376 2.051 5.534 2.131 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.252 6.387 2.234 c
+6.483 2.212 6.571 2.179 6.652 2.131 c
+6.739 2.08 6.817 2.017 6.887 1.94 c
+6.964 1.859 7.026 1.768 7.078 1.66 c
+7.092 1.66 l
+7.092 1.808 l
+7.1 1.866 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.151 2.219 c
+8.004 2.219 l
+7.993 2.138 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.162 l
+7.975 -1.415 7.938 -1.635 7.871 -1.823 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.529 m
+7.092 0.742 7.067 0.918 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.587 c
+6.571 1.624 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.62 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.339 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.177 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.529 c
+11.036 -0.647 m
+12.168 -0.647 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.647 l
+10.124 -0.647 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.676 re
+10.124 2.836 m
+13.597 1.602 m
+13.053 1.602 l
+13.053 2.219 l
+13.641 2.219 l
+13.92 3.116 l
+14.494 3.116 l
+14.494 2.219 l
+15.728 2.219 l
+15.728 1.602 l
+14.494 1.602 l
+14.494 -0.103 l
+14.494 -0.324 l
+14.501 -0.393 14.523 -0.456 14.552 -0.515 c
+14.589 -0.566 14.645 -0.611 14.714 -0.647 c
+14.791 -0.676 14.905 -0.691 15.052 -0.691 c
+15.188 -0.691 15.324 -0.688 15.464 -0.676 c
+15.599 -0.658 15.732 -0.632 15.861 -0.603 c
+15.861 -1.205 l
+15.78 -1.216 15.703 -1.231 15.626 -1.249 c
+15.545 -1.261 15.468 -1.268 15.391 -1.279 c
+15.31 -1.286 15.221 -1.294 15.125 -1.294 c
+15.038 -1.301 14.938 -1.309 14.832 -1.309 c
+14.645 -1.309 14.483 -1.294 14.346 -1.264 c
+14.218 -1.228 14.104 -1.183 14.009 -1.132 c
+13.92 -1.085 13.847 -1.025 13.788 -0.956 c
+13.729 -0.879 13.685 -0.802 13.656 -0.721 c
+13.627 -0.632 13.604 -0.544 13.597 -0.456 c
+13.586 -0.36 13.582 -0.264 13.582 -0.177 c
+h
+24.22 -0.25 m
+24.22 -0.419 24.18 -0.57 24.103 -0.706 c
+24.033 -0.834 23.931 -0.948 23.794 -1.044 c
+23.666 -1.132 23.504 -1.202 23.31 -1.249 c
+23.121 -1.297 22.905 -1.323 22.662 -1.323 c
+22.435 -1.323 22.236 -1.309 22.06 -1.279 c
+21.883 -1.249 21.725 -1.202 21.59 -1.132 c
+21.45 -1.055 21.34 -0.956 21.251 -0.838 c
+21.163 -0.721 21.093 -0.574 21.045 -0.397 c
+21.854 -0.279 l
+21.872 -0.379 21.902 -0.456 21.942 -0.515 c
+21.99 -0.574 22.049 -0.617 22.119 -0.647 c
+22.185 -0.676 22.265 -0.702 22.354 -0.721 c
+22.442 -0.732 22.545 -0.735 22.662 -0.735 c
+22.758 -0.735 22.853 -0.732 22.942 -0.721 c
+23.03 -0.702 23.107 -0.676 23.177 -0.647 c
+23.243 -0.617 23.295 -0.58 23.324 -0.53 c
+23.36 -0.482 23.383 -0.419 23.383 -0.339 c
+23.383 -0.243 23.353 -0.169 23.295 -0.118 c
+23.243 -0.07 23.177 -0.029 23.089 0 c
+23.001 0.037 22.89 0.066 22.766 0.088 c
+22.647 0.118 22.516 0.147 22.369 0.176 c
+22.229 0.213 22.09 0.253 21.942 0.294 c
+21.803 0.341 21.677 0.405 21.56 0.484 c
+21.45 0.562 21.361 0.661 21.296 0.779 c
+21.226 0.897 21.193 1.047 21.193 1.234 c
+21.193 1.389 21.222 1.532 21.28 1.66 c
+21.347 1.797 21.442 1.911 21.56 1.999 c
+21.685 2.087 21.843 2.153 22.03 2.205 c
+22.215 2.252 22.427 2.278 22.662 2.278 c
+22.846 2.278 23.023 2.256 23.192 2.219 c
+23.357 2.19 23.504 2.135 23.632 2.057 c
+23.757 1.988 23.868 1.889 23.956 1.764 c
+24.044 1.646 24.103 1.502 24.133 1.338 c
+23.339 1.264 l
+23.316 1.341 23.287 1.404 23.25 1.455 c
+23.21 1.514 23.162 1.558 23.104 1.587 c
+23.052 1.624 22.99 1.65 22.913 1.66 c
+22.832 1.668 22.751 1.675 22.662 1.675 c
+22.446 1.675 22.284 1.646 22.177 1.587 c
+22.067 1.536 22.016 1.448 22.016 1.323 c
+22.016 1.242 22.034 1.18 22.074 1.132 c
+22.122 1.08 22.185 1.043 22.265 1.014 c
+22.354 0.985 22.45 0.955 22.56 0.926 c
+22.666 0.904 22.788 0.881 22.927 0.852 c
+23.081 0.823 23.239 0.783 23.397 0.735 c
+23.551 0.683 23.692 0.621 23.809 0.544 c
+23.927 0.463 24.022 0.36 24.103 0.235 c
+24.18 0.106 24.22 -0.056 24.22 -0.25 c
+25.783 1.602 m
+25.238 1.602 l
+25.238 2.219 l
+25.826 2.219 l
+26.106 3.116 l
+26.679 3.116 l
+26.679 2.219 l
+27.914 2.219 l
+27.914 1.602 l
+26.679 1.602 l
+26.679 -0.103 l
+26.679 -0.324 l
+26.686 -0.393 26.709 -0.456 26.738 -0.515 c
+26.774 -0.566 26.83 -0.611 26.9 -0.647 c
+26.977 -0.676 27.09 -0.691 27.237 -0.691 c
+27.374 -0.691 27.509 -0.688 27.649 -0.676 c
+27.785 -0.658 27.917 -0.632 28.046 -0.603 c
+28.046 -1.205 l
+27.965 -1.216 27.888 -1.231 27.811 -1.249 c
+27.73 -1.261 27.653 -1.268 27.576 -1.279 c
+27.495 -1.286 27.407 -1.294 27.312 -1.294 c
+27.223 -1.301 27.123 -1.309 27.017 -1.309 c
+26.83 -1.309 26.668 -1.294 26.532 -1.264 c
+26.404 -1.228 26.29 -1.183 26.194 -1.132 c
+26.106 -1.085 26.032 -1.025 25.974 -0.956 c
+25.915 -0.879 25.87 -0.802 25.841 -0.721 c
+25.812 -0.632 25.789 -0.544 25.783 -0.456 c
+25.772 -0.36 25.768 -0.264 25.768 -0.177 c
+h
+30.196 -1.323 m
+30.027 -1.323 29.876 -1.301 29.741 -1.264 c
+29.612 -1.216 29.498 -1.147 29.402 -1.058 c
+29.313 -0.97 29.244 -0.864 29.196 -0.735 c
+29.145 -0.599 29.122 -0.449 29.122 -0.279 c
+29.122 -0.073 29.155 0.095 29.226 0.235 c
+29.292 0.382 29.388 0.492 29.505 0.573 c
+29.63 0.661 29.773 0.723 29.931 0.764 c
+30.096 0.801 30.273 0.827 30.46 0.837 c
+31.181 0.852 l
+31.181 1.029 l
+31.181 1.147 31.17 1.249 31.152 1.338 c
+31.129 1.425 31.096 1.492 31.048 1.543 c
+31.008 1.602 30.96 1.639 30.901 1.66 c
+30.842 1.679 30.776 1.691 30.71 1.691 c
+30.641 1.691 30.578 1.679 30.519 1.66 c
+30.468 1.65 30.42 1.624 30.372 1.587 c
+30.331 1.558 30.298 1.506 30.269 1.44 c
+30.248 1.382 30.233 1.301 30.225 1.205 c
+29.284 1.249 l
+29.313 1.396 29.358 1.532 29.417 1.66 c
+29.483 1.786 29.579 1.896 29.696 1.984 c
+29.814 2.08 29.953 2.153 30.122 2.205 c
+30.298 2.252 30.504 2.278 30.74 2.278 c
+31.181 2.278 31.511 2.168 31.74 1.955 c
+31.975 1.749 32.092 1.44 32.092 1.029 c
+32.092 -0.235 l
+32.092 -0.456 l
+32.099 -0.515 32.114 -0.57 32.136 -0.617 c
+32.154 -0.658 32.184 -0.691 32.224 -0.721 c
+32.261 -0.742 32.313 -0.75 32.371 -0.75 c
+32.438 -0.75 32.507 -0.746 32.577 -0.735 c
+32.577 -1.22 l
+32.519 -1.231 32.463 -1.242 32.415 -1.249 c
+32.375 -1.261 32.334 -1.268 32.297 -1.279 c
+32.257 -1.286 32.213 -1.294 32.166 -1.294 c
+32.114 -1.301 32.055 -1.309 31.989 -1.309 c
+31.761 -1.309 31.596 -1.257 31.489 -1.147 c
+31.379 -1.029 31.316 -0.864 31.298 -0.647 c
+31.283 -0.647 l
+31.214 -0.757 31.144 -0.852 31.077 -0.941 c
+31.008 -1.022 30.931 -1.087 30.842 -1.147 c
+30.755 -1.205 30.655 -1.249 30.549 -1.279 c
+30.449 -1.309 30.331 -1.323 30.196 -1.323 c
+31.181 0.353 m
+30.755 0.338 l
+30.655 0.338 30.564 0.33 30.475 0.324 c
+30.394 0.312 30.328 0.287 30.269 0.249 c
+30.211 0.209 30.159 0.151 30.122 0.073 c
+30.082 0.004 30.063 -0.088 30.063 -0.206 c
+30.063 -0.375 30.096 -0.497 30.167 -0.574 c
+30.233 -0.654 30.331 -0.691 30.46 -0.691 c
+30.567 -0.691 30.666 -0.669 30.755 -0.617 c
+30.85 -0.57 30.931 -0.507 30.99 -0.426 c
+31.056 -0.349 31.107 -0.262 31.137 -0.162 c
+31.166 -0.056 31.181 0.058 31.181 0.176 c
+h
+36.403 -0.25 m
+36.403 -0.419 36.362 -0.57 36.285 -0.706 c
+36.215 -0.834 36.112 -0.948 35.976 -1.044 c
+35.848 -1.132 35.686 -1.202 35.491 -1.249 c
+35.304 -1.297 35.087 -1.323 34.844 -1.323 c
+34.616 -1.323 34.418 -1.309 34.242 -1.279 c
+34.065 -1.249 33.907 -1.202 33.772 -1.132 c
+33.631 -1.055 33.521 -0.956 33.433 -0.838 c
+33.345 -0.721 33.275 -0.574 33.228 -0.397 c
+34.036 -0.279 l
+34.055 -0.379 34.084 -0.456 34.124 -0.515 c
+34.171 -0.574 34.231 -0.617 34.3 -0.647 c
+34.367 -0.676 34.447 -0.702 34.535 -0.721 c
+34.624 -0.732 34.726 -0.735 34.844 -0.735 c
+34.94 -0.735 35.035 -0.732 35.123 -0.721 c
+35.212 -0.702 35.289 -0.676 35.359 -0.647 c
+35.425 -0.617 35.476 -0.58 35.505 -0.53 c
+35.543 -0.482 35.565 -0.419 35.565 -0.339 c
+35.565 -0.243 35.535 -0.169 35.476 -0.118 c
+35.425 -0.07 35.359 -0.029 35.27 0 c
+35.183 0.037 35.073 0.066 34.948 0.088 c
+34.83 0.118 34.697 0.147 34.551 0.176 c
+34.41 0.213 34.271 0.253 34.124 0.294 c
+33.984 0.341 33.859 0.405 33.742 0.484 c
+33.631 0.562 33.544 0.661 33.477 0.779 c
+33.408 0.897 33.375 1.047 33.375 1.234 c
+33.375 1.389 33.404 1.532 33.463 1.66 c
+33.529 1.797 33.624 1.911 33.742 1.999 c
+33.867 2.087 34.025 2.153 34.212 2.205 c
+34.396 2.252 34.609 2.278 34.844 2.278 c
+35.028 2.278 35.204 2.256 35.374 2.219 c
+35.539 2.19 35.686 2.135 35.815 2.057 c
+35.939 1.988 36.05 1.889 36.138 1.764 c
+36.226 1.646 36.285 1.502 36.314 1.338 c
+35.52 1.264 l
+35.499 1.341 35.469 1.404 35.432 1.455 c
+35.392 1.514 35.345 1.558 35.285 1.587 c
+35.234 1.624 35.171 1.65 35.094 1.66 c
+35.013 1.668 34.932 1.675 34.844 1.675 c
+34.628 1.675 34.466 1.646 34.36 1.587 c
+34.249 1.536 34.198 1.448 34.198 1.323 c
+34.198 1.242 34.216 1.18 34.256 1.132 c
+34.304 1.08 34.367 1.043 34.447 1.014 c
+34.535 0.985 34.631 0.955 34.742 0.926 c
+34.848 0.904 34.969 0.881 35.109 0.852 c
+35.264 0.823 35.422 0.783 35.58 0.735 c
+35.734 0.683 35.873 0.621 35.991 0.544 c
+36.108 0.463 36.204 0.36 36.285 0.235 c
+36.362 0.106 36.403 -0.056 36.403 -0.25 c
+38.262 1.514 m
+38.379 1.786 38.53 1.984 38.718 2.102 c
+38.901 2.219 39.122 2.278 39.379 2.278 c
+39.584 2.278 39.754 2.242 39.894 2.175 c
+40.041 2.105 40.151 2.013 40.232 1.896 c
+40.32 1.778 40.378 1.635 40.408 1.469 c
+40.444 1.301 40.467 1.124 40.467 0.941 c
+40.467 -1.264 l
+39.555 -1.264 l
+39.555 0.735 l
+39.555 0.871 39.544 0.992 39.526 1.103 c
+39.515 1.209 39.489 1.297 39.453 1.367 c
+39.412 1.444 39.353 1.502 39.276 1.543 c
+39.206 1.58 39.114 1.602 38.996 1.602 c
+38.886 1.602 38.791 1.577 38.703 1.529 c
+38.615 1.477 38.534 1.411 38.468 1.323 c
+38.409 1.234 38.358 1.124 38.321 0.999 c
+38.291 0.881 38.277 0.75 38.277 0.602 c
+38.277 -1.264 l
+37.365 -1.264 l
+37.365 3.513 l
+38.277 3.513 l
+38.277 2.205 l
+38.277 2.135 38.269 2.065 38.262 1.999 c
+38.262 1.793 l
+38.262 1.735 38.254 1.679 38.248 1.631 c
+38.248 1.514 l
+h
+f
+Q
+q 1 0 0 1 414.8848 150.0096 cm
+0 0 m
+0 -2.102 l
+-0.676 -2.102 l
+-0.676 3.248 l
+1.029 3.248 l
+1.529 3.248 1.918 3.094 2.205 2.793 c
+2.488 2.5 2.631 2.106 2.631 1.617 c
+2.631 1.095 2.492 0.699 2.219 0.426 c
+1.955 0.151 1.577 0.008 1.087 0 c
+h
+0 0.574 m
+1.029 0.574 l
+1.33 0.574 1.562 0.661 1.72 0.838 c
+1.874 1.014 1.955 1.268 1.955 1.602 c
+1.955 1.926 1.87 2.183 1.706 2.382 c
+1.548 2.577 1.326 2.675 1.043 2.675 c
+0 2.675 l
+h
+5.438 -1.749 m
+5.222 -2.036 4.91 -2.175 4.498 -2.175 c
+4.135 -2.175 3.859 -2.054 3.675 -1.808 c
+3.499 -1.554 3.403 -1.19 3.395 -0.72 c
+3.395 1.881 l
+4.042 1.881 l
+4.042 -0.661 l
+4.042 -1.29 4.226 -1.602 4.601 -1.602 c
+5.002 -1.602 5.277 -1.425 5.424 -1.072 c
+5.424 1.881 l
+6.071 1.881 l
+6.071 -2.102 l
+5.453 -2.102 l
+h
+7.908 2.837 m
+7.908 1.881 l
+8.511 1.881 l
+8.511 1.353 l
+7.908 1.353 l
+7.908 -1.117 l
+7.908 -1.275 7.93 -1.392 7.982 -1.469 c
+8.04 -1.55 8.129 -1.587 8.247 -1.587 c
+8.334 -1.587 8.422 -1.573 8.511 -1.543 c
+8.511 -2.102 l
+8.364 -2.15 8.21 -2.175 8.056 -2.175 c
+7.798 -2.175 7.603 -2.084 7.468 -1.896 c
+7.327 -1.712 7.262 -1.452 7.262 -1.117 c
+7.262 1.353 l
+6.659 1.353 l
+6.659 1.881 l
+7.262 1.881 l
+7.262 2.837 l
+h
+12.083 -1.014 m
+12.803 1.881 l
+13.494 1.881 l
+12.2 -2.66 l
+12.101 -3.002 11.958 -3.262 11.774 -3.439 c
+11.597 -3.615 11.395 -3.704 11.171 -3.704 c
+11.083 -3.704 10.969 -3.682 10.834 -3.645 c
+10.834 -3.102 l
+10.98 -3.116 l
+11.164 -3.116 11.311 -3.072 11.422 -2.984 c
+11.528 -2.896 11.616 -2.738 11.686 -2.514 c
+11.803 -2.072 l
+10.643 1.881 l
+11.348 1.881 l
+h
+13.935 0.073 m
+13.935 0.651 14.071 1.106 14.346 1.441 c
+14.629 1.783 15 1.955 15.464 1.955 c
+15.923 1.955 16.291 1.786 16.565 1.455 c
+16.849 1.132 16.996 0.684 17.007 0.118 c
+17.007 -0.309 l
+17.007 -0.878 16.864 -1.334 16.581 -1.675 c
+16.305 -2.009 15.938 -2.175 15.478 -2.175 c
+15.015 -2.175 14.644 -2.013 14.361 -1.691 c
+14.086 -1.359 13.942 -0.918 13.935 -0.367 c
+h
+14.581 -0.309 m
+14.581 -0.712 14.659 -1.028 14.817 -1.263 c
+14.982 -1.499 15.202 -1.616 15.478 -1.616 c
+16.044 -1.616 16.338 -1.205 16.36 -0.382 c
+16.36 0.073 l
+16.36 0.474 16.276 0.794 16.11 1.029 c
+15.952 1.272 15.736 1.397 15.464 1.397 c
+15.199 1.397 14.982 1.272 14.817 1.029 c
+14.659 0.794 14.581 0.474 14.581 0.073 c
+h
+19.873 -1.749 m
+19.657 -2.036 19.344 -2.175 18.932 -2.175 c
+18.568 -2.175 18.293 -2.054 18.109 -1.808 c
+17.933 -1.554 17.837 -1.19 17.83 -0.72 c
+17.83 1.881 l
+18.477 1.881 l
+18.477 -0.661 l
+18.477 -1.29 18.66 -1.602 19.036 -1.602 c
+19.436 -1.602 19.711 -1.425 19.858 -1.072 c
+19.858 1.881 l
+20.505 1.881 l
+20.505 -2.102 l
+19.888 -2.102 l
+h
+23.137 1.264 m
+23.048 1.283 22.949 1.294 22.842 1.294 c
+22.508 1.294 22.273 1.11 22.137 0.75 c
+22.137 -2.102 l
+21.49 -2.102 l
+21.49 1.881 l
+22.122 1.881 l
+22.137 1.47 l
+22.313 1.794 22.556 1.955 22.872 1.955 c
+22.978 1.955 23.067 1.933 23.137 1.897 c
+h
+26.884 -1.616 m
+27.098 -1.616 27.27 -1.554 27.399 -1.425 c
+27.535 -1.29 27.609 -1.099 27.619 -0.852 c
+28.237 -0.852 l
+28.215 -1.234 28.079 -1.554 27.825 -1.808 c
+27.568 -2.054 27.256 -2.175 26.884 -2.175 c
+26.392 -2.175 26.017 -2.024 25.753 -1.72 c
+25.496 -1.407 25.371 -0.941 25.371 -0.323 c
+25.371 0.118 l
+25.371 0.713 25.496 1.169 25.753 1.484 c
+26.017 1.797 26.392 1.955 26.884 1.955 c
+27.285 1.955 27.605 1.823 27.84 1.559 c
+28.083 1.301 28.215 0.956 28.237 0.515 c
+27.619 0.515 l
+27.598 0.809 27.524 1.029 27.399 1.176 c
+27.281 1.324 27.109 1.397 26.884 1.397 c
+26.591 1.397 26.374 1.297 26.238 1.103 c
+26.098 0.915 26.025 0.607 26.017 0.177 c
+26.017 -0.338 l
+26.017 -0.808 26.084 -1.143 26.223 -1.338 c
+26.37 -1.525 26.591 -1.616 26.884 -1.616 c
+31.015 -1.749 m
+30.798 -2.036 30.486 -2.175 30.074 -2.175 c
+29.71 -2.175 29.435 -2.054 29.251 -1.808 c
+29.074 -1.554 28.979 -1.19 28.972 -0.72 c
+28.972 1.881 l
+29.619 1.881 l
+29.619 -0.661 l
+29.619 -1.29 29.803 -1.602 30.177 -1.602 c
+30.578 -1.602 30.853 -1.425 31 -1.072 c
+31 1.881 l
+31.647 1.881 l
+31.647 -2.102 l
+31.03 -2.102 l
+h
+34.279 1.264 m
+34.19 1.283 34.091 1.294 33.984 1.294 c
+33.65 1.294 33.415 1.11 33.279 0.75 c
+33.279 -2.102 l
+32.632 -2.102 l
+32.632 1.881 l
+33.264 1.881 l
+33.279 1.47 l
+33.456 1.794 33.697 1.955 34.013 1.955 c
+34.121 1.955 34.208 1.933 34.279 1.897 c
+h
+36.571 1.264 m
+36.483 1.283 36.384 1.294 36.278 1.294 c
+35.943 1.294 35.708 1.11 35.572 0.75 c
+35.572 -2.102 l
+34.925 -2.102 l
+34.925 1.881 l
+35.557 1.881 l
+35.572 1.47 l
+35.748 1.794 35.991 1.955 36.307 1.955 c
+36.413 1.955 36.502 1.933 36.571 1.897 c
+h
+38.57 -2.175 m
+38.071 -2.175 37.689 -2.028 37.424 -1.734 c
+37.159 -1.44 37.027 -1.007 37.027 -0.426 c
+37.027 0.044 l
+37.027 0.64 37.152 1.106 37.409 1.441 c
+37.674 1.783 38.034 1.955 38.497 1.955 c
+38.956 1.955 39.298 1.801 39.526 1.5 c
+39.761 1.206 39.883 0.742 39.893 0.118 c
+39.893 -0.309 l
+37.674 -0.309 l
+37.674 -0.397 l
+37.674 -0.83 37.751 -1.143 37.909 -1.338 c
+38.075 -1.525 38.306 -1.616 38.599 -1.616 c
+38.794 -1.616 38.967 -1.583 39.114 -1.514 c
+39.262 -1.437 39.397 -1.319 39.526 -1.161 c
+39.864 -1.573 l
+39.577 -1.977 39.147 -2.175 38.57 -2.175 c
+38.497 1.397 m
+38.221 1.397 38.019 1.301 37.894 1.118 c
+37.766 0.93 37.693 0.64 37.674 0.25 c
+39.247 0.25 l
+39.247 0.339 l
+39.224 0.721 39.158 0.989 39.041 1.147 c
+38.923 1.312 38.74 1.397 38.497 1.397 c
+41.29 1.881 m
+41.304 1.441 l
+41.558 1.783 41.882 1.955 42.275 1.955 c
+42.98 1.955 43.337 1.484 43.347 0.544 c
+43.347 -2.102 l
+42.701 -2.102 l
+42.701 0.515 l
+42.701 0.827 42.646 1.048 42.539 1.176 c
+42.429 1.301 42.275 1.367 42.069 1.367 c
+41.911 1.367 41.764 1.312 41.628 1.206 c
+41.499 1.095 41.396 0.96 41.319 0.794 c
+41.319 -2.102 l
+40.673 -2.102 l
+40.673 1.881 l
+h
+45.171 2.837 m
+45.171 1.881 l
+45.773 1.881 l
+45.773 1.353 l
+45.171 1.353 l
+45.171 -1.117 l
+45.171 -1.275 45.192 -1.392 45.244 -1.469 c
+45.302 -1.55 45.391 -1.587 45.508 -1.587 c
+45.597 -1.587 45.685 -1.573 45.773 -1.543 c
+45.773 -2.102 l
+45.626 -2.15 45.472 -2.175 45.317 -2.175 c
+45.06 -2.175 44.866 -2.084 44.729 -1.896 c
+44.59 -1.712 44.523 -1.452 44.523 -1.117 c
+44.523 1.353 l
+43.921 1.353 l
+43.921 1.881 l
+44.523 1.881 l
+44.523 2.837 l
+h
+49.639 -1.616 m
+49.852 -1.616 50.025 -1.554 50.154 -1.425 c
+50.289 -1.29 50.362 -1.099 50.374 -0.852 c
+50.991 -0.852 l
+50.969 -1.234 50.833 -1.554 50.58 -1.808 c
+50.322 -2.054 50.01 -2.175 49.639 -2.175 c
+49.146 -2.175 48.772 -2.024 48.507 -1.72 c
+48.25 -1.407 48.124 -0.941 48.124 -0.323 c
+48.124 0.118 l
+48.124 0.713 48.25 1.169 48.507 1.484 c
+48.772 1.797 49.146 1.955 49.639 1.955 c
+50.04 1.955 50.359 1.823 50.594 1.559 c
+50.837 1.301 50.969 0.956 50.991 0.515 c
+50.374 0.515 l
+50.352 0.809 50.278 1.029 50.154 1.176 c
+50.036 1.324 49.863 1.397 49.639 1.397 c
+49.345 1.397 49.128 1.297 48.992 1.103 c
+48.853 0.915 48.779 0.607 48.772 0.177 c
+48.772 -0.338 l
+48.772 -0.808 48.838 -1.143 48.978 -1.338 c
+49.124 -1.525 49.345 -1.616 49.639 -1.616 c
+52.388 1.47 m
+52.641 1.794 52.961 1.955 53.343 1.955 c
+54.048 1.955 54.405 1.484 54.416 0.544 c
+54.416 -2.102 l
+53.769 -2.102 l
+53.769 0.515 l
+53.769 0.827 53.714 1.048 53.608 1.176 c
+53.497 1.301 53.343 1.367 53.138 1.367 c
+52.98 1.367 52.832 1.312 52.696 1.206 c
+52.568 1.095 52.465 0.96 52.388 0.794 c
+52.388 -2.102 l
+51.741 -2.102 l
+51.741 3.543 l
+52.388 3.543 l
+h
+57.414 -2.102 m
+57.374 -2.013 57.348 -1.866 57.341 -1.66 c
+57.106 -2.006 56.812 -2.175 56.459 -2.175 c
+56.095 -2.175 55.812 -2.08 55.606 -1.881 c
+55.409 -1.675 55.313 -1.389 55.313 -1.014 c
+55.313 -0.613 55.449 -0.294 55.725 -0.058 c
+55.997 0.184 56.371 0.309 56.841 0.309 c
+57.327 0.309 l
+57.327 0.736 l
+57.327 0.971 57.271 1.135 57.165 1.235 c
+57.055 1.341 56.893 1.397 56.68 1.397 c
+56.481 1.397 56.319 1.338 56.195 1.22 c
+56.077 1.103 56.018 0.956 56.018 0.779 c
+55.371 0.779 l
+55.371 0.974 55.43 1.166 55.548 1.353 c
+55.673 1.536 55.835 1.683 56.033 1.794 c
+56.238 1.9 56.467 1.955 56.724 1.955 c
+57.125 1.955 57.429 1.852 57.635 1.646 c
+57.848 1.441 57.962 1.147 57.973 0.765 c
+57.973 -1.249 l
+57.973 -1.554 58.01 -1.818 58.091 -2.043 c
+58.091 -2.102 l
+h
+56.547 -1.587 m
+56.712 -1.587 56.863 -1.543 57.003 -1.455 c
+57.15 -1.367 57.256 -1.257 57.327 -1.117 c
+57.327 -0.176 l
+56.959 -0.176 l
+56.643 -0.176 56.4 -0.246 56.224 -0.382 c
+56.047 -0.511 55.96 -0.698 55.96 -0.941 c
+55.96 -1.168 56.003 -1.334 56.092 -1.44 c
+56.18 -1.539 56.331 -1.587 56.547 -1.587 c
+59.59 1.881 m
+59.604 1.441 l
+59.858 1.783 60.182 1.955 60.575 1.955 c
+61.281 1.955 61.637 1.484 61.648 0.544 c
+61.648 -2.102 l
+61.001 -2.102 l
+61.001 0.515 l
+61.001 0.827 60.946 1.048 60.84 1.176 c
+60.729 1.301 60.575 1.367 60.369 1.367 c
+60.211 1.367 60.064 1.312 59.928 1.206 c
+59.8 1.095 59.697 0.96 59.619 0.794 c
+59.619 -2.102 l
+58.973 -2.102 l
+58.973 1.881 l
+h
+62.486 0.073 m
+62.486 0.691 62.596 1.154 62.824 1.47 c
+63.048 1.794 63.382 1.955 63.824 1.955 c
+64.224 1.955 64.529 1.779 64.735 1.426 c
+64.778 1.881 l
+65.367 1.881 l
+65.367 -2.146 l
+65.367 -2.634 65.238 -3.013 64.984 -3.278 c
+64.728 -3.542 64.375 -3.675 63.926 -3.675 c
+63.728 -3.675 63.507 -3.623 63.265 -3.528 c
+63.018 -3.428 62.839 -3.307 62.721 -3.16 c
+62.985 -2.719 l
+63.251 -2.984 63.548 -3.116 63.882 -3.116 c
+64.419 -3.116 64.695 -2.822 64.705 -2.234 c
+64.705 -1.705 l
+64.5 -2.021 64.198 -2.175 63.808 -2.175 c
+63.397 -2.175 63.074 -2.024 62.839 -1.72 c
+62.611 -1.407 62.493 -0.955 62.486 -0.367 c
+h
+63.147 -0.309 m
+63.147 -0.75 63.21 -1.08 63.338 -1.294 c
+63.463 -1.499 63.681 -1.602 63.985 -1.602 c
+64.308 -1.602 64.547 -1.437 64.705 -1.103 c
+64.705 0.882 l
+64.537 1.206 64.298 1.367 63.985 1.367 c
+63.691 1.367 63.474 1.264 63.338 1.058 c
+63.21 0.853 63.147 0.53 63.147 0.088 c
+h
+67.748 -2.175 m
+67.249 -2.175 66.866 -2.028 66.602 -1.734 c
+66.337 -1.44 66.205 -1.007 66.205 -0.426 c
+66.205 0.044 l
+66.205 0.64 66.33 1.106 66.586 1.441 c
+66.852 1.783 67.211 1.955 67.675 1.955 c
+68.134 1.955 68.475 1.801 68.703 1.5 c
+68.938 1.206 69.06 0.742 69.071 0.118 c
+69.071 -0.309 l
+66.852 -0.309 l
+66.852 -0.397 l
+66.852 -0.83 66.929 -1.143 67.087 -1.338 c
+67.252 -1.525 67.484 -1.616 67.777 -1.616 c
+67.972 -1.616 68.145 -1.583 68.292 -1.514 c
+68.439 -1.437 68.575 -1.319 68.703 -1.161 c
+69.042 -1.573 l
+68.755 -1.977 68.325 -2.175 67.748 -2.175 c
+67.675 1.397 m
+67.399 1.397 67.197 1.301 67.072 1.118 c
+66.943 0.93 66.87 0.64 66.852 0.25 c
+68.425 0.25 l
+68.425 0.339 l
+68.402 0.721 68.336 0.989 68.219 1.147 c
+68.101 1.312 67.917 1.397 67.675 1.397 c
+71.791 -1.087 m
+71.791 -0.941 71.735 -0.819 71.629 -0.72 c
+71.519 -0.625 71.313 -0.507 71.012 -0.367 c
+70.666 -0.22 70.423 -0.099 70.276 0 c
+70.129 0.107 70.019 0.225 69.952 0.353 c
+69.883 0.478 69.85 0.636 69.85 0.823 c
+69.85 1.147 69.967 1.415 70.203 1.632 c
+70.438 1.845 70.739 1.955 71.114 1.955 c
+71.496 1.955 71.805 1.841 72.04 1.617 c
+72.275 1.389 72.393 1.103 72.393 0.75 c
+71.746 0.75 l
+71.746 0.927 71.687 1.077 71.57 1.206 c
+71.452 1.33 71.298 1.397 71.114 1.397 c
+70.916 1.397 70.765 1.341 70.658 1.235 c
+70.548 1.135 70.497 1.004 70.497 0.838 c
+70.497 0.709 70.534 0.603 70.615 0.515 c
+70.692 0.434 70.883 0.331 71.188 0.206 c
+71.666 0.019 71.996 -0.168 72.173 -0.353 c
+72.349 -0.529 72.437 -0.756 72.437 -1.028 c
+72.437 -1.381 72.312 -1.66 72.069 -1.866 c
+71.834 -2.072 71.519 -2.175 71.128 -2.175 c
+70.706 -2.175 70.368 -2.057 70.114 -1.822 c
+69.857 -1.579 69.732 -1.275 69.732 -0.911 c
+70.38 -0.911 l
+70.386 -1.139 70.457 -1.315 70.585 -1.44 c
+70.71 -1.558 70.893 -1.616 71.128 -1.616 c
+71.342 -1.616 71.504 -1.569 71.614 -1.469 c
+71.731 -1.374 71.791 -1.246 71.791 -1.087 c
+75.7 -2.102 -0.647 3.983 re
+75.745 2.926 m
+75.745 2.816 75.715 2.723 75.656 2.646 c
+75.597 2.577 75.502 2.543 75.377 2.543 c
+75.259 2.543 75.164 2.577 75.097 2.646 c
+75.039 2.723 75.01 2.816 75.01 2.926 c
+75.01 3.043 75.039 3.135 75.097 3.205 c
+75.164 3.282 75.259 3.323 75.377 3.323 c
+75.502 3.323 75.597 3.282 75.656 3.205 c
+75.715 3.124 75.745 3.032 75.745 2.926 c
+77.332 1.881 m
+77.347 1.441 l
+77.6 1.783 77.923 1.955 78.317 1.955 c
+79.022 1.955 79.379 1.484 79.39 0.544 c
+79.39 -2.102 l
+78.743 -2.102 l
+78.743 0.515 l
+78.743 0.827 78.688 1.048 78.581 1.176 c
+78.471 1.301 78.317 1.367 78.111 1.367 c
+77.952 1.367 77.806 1.312 77.67 1.206 c
+77.541 1.095 77.439 0.96 77.362 0.794 c
+77.362 -2.102 l
+76.714 -2.102 l
+76.714 1.881 l
+h
+81.212 2.837 m
+81.212 1.881 l
+81.815 1.881 l
+81.815 1.353 l
+81.212 1.353 l
+81.212 -1.117 l
+81.212 -1.275 81.235 -1.392 81.286 -1.469 c
+81.345 -1.55 81.433 -1.587 81.551 -1.587 c
+81.638 -1.587 81.727 -1.573 81.815 -1.543 c
+81.815 -2.102 l
+81.668 -2.15 81.514 -2.175 81.36 -2.175 c
+81.102 -2.175 80.907 -2.084 80.771 -1.896 c
+80.632 -1.712 80.566 -1.452 80.566 -1.117 c
+80.566 1.353 l
+79.963 1.353 l
+79.963 1.881 l
+80.566 1.881 l
+80.566 2.837 l
+h
+82.374 0.073 m
+82.374 0.651 82.509 1.106 82.785 1.441 c
+83.068 1.783 83.439 1.955 83.903 1.955 c
+84.362 1.955 84.73 1.786 85.004 1.455 c
+85.287 1.132 85.435 0.684 85.445 0.118 c
+85.445 -0.309 l
+85.445 -0.878 85.303 -1.334 85.019 -1.675 c
+84.744 -2.009 84.377 -2.175 83.917 -2.175 c
+83.454 -2.175 83.083 -2.013 82.8 -1.691 c
+82.525 -1.359 82.381 -0.918 82.374 -0.367 c
+h
+83.02 -0.309 m
+83.02 -0.712 83.097 -1.028 83.255 -1.263 c
+83.421 -1.499 83.641 -1.616 83.917 -1.616 c
+84.483 -1.616 84.777 -1.205 84.799 -0.382 c
+84.799 0.073 l
+84.799 0.474 84.715 0.794 84.549 1.029 c
+84.391 1.272 84.175 1.397 83.903 1.397 c
+83.637 1.397 83.421 1.272 83.255 1.029 c
+83.097 0.794 83.02 0.474 83.02 0.073 c
+h
+f
+Q
+q 1 0 0 1 504.5495 148.9813 cm
+0 0 m
+0 0.087 -0.044 0.165 -0.133 0.235 c
+-0.221 0.312 -0.408 0.415 -0.691 0.544 c
+-1.125 0.72 -1.422 0.9 -1.588 1.087 c
+-1.746 1.271 -1.823 1.502 -1.823 1.778 c
+-1.823 2.119 -1.702 2.403 -1.455 2.63 c
+-1.202 2.865 -0.864 2.983 -0.441 2.983 c
+-0.011 2.983 0.338 2.869 0.602 2.645 c
+0.867 2.418 0.999 2.117 0.999 1.734 c
+-0.044 1.734 l
+-0.044 2.057 -0.184 2.219 -0.456 2.219 c
+-0.566 2.219 -0.655 2.183 -0.721 2.117 c
+-0.79 2.046 -0.823 1.947 -0.823 1.822 c
+-0.823 1.734 -0.786 1.653 -0.706 1.587 c
+-0.628 1.529 -0.449 1.433 -0.162 1.308 c
+0.268 1.15 0.565 0.974 0.735 0.779 c
+0.911 0.591 0.999 0.341 0.999 0.029 c
+0.999 -0.324 0.867 -0.611 0.602 -0.823 c
+0.338 -1.04 -0.011 -1.147 -0.441 -1.147 c
+-0.736 -1.147 -0.996 -1.092 -1.22 -0.985 c
+-1.448 -0.867 -1.625 -0.706 -1.75 -0.5 c
+-1.867 -0.294 -1.926 -0.074 -1.926 0.161 c
+-0.941 0.161 l
+-0.941 -0.026 -0.904 -0.162 -0.823 -0.25 c
+-0.736 -0.339 -0.603 -0.383 -0.427 -0.383 c
+-0.144 -0.383 0 -0.258 0 0 c
+2.866 3.881 m
+2.866 2.91 l
+3.395 2.91 l
+3.395 2.117 l
+2.866 2.117 l
+2.866 0.147 l
+2.866 -0.011 2.884 -0.118 2.925 -0.177 c
+2.973 -0.235 3.057 -0.265 3.175 -0.265 c
+3.281 -0.265 3.366 -0.258 3.424 -0.235 c
+3.424 -1.044 l
+3.248 -1.11 3.057 -1.147 2.851 -1.147 c
+2.175 -1.147 1.83 -0.761 1.822 0.014 c
+1.822 2.117 l
+1.367 2.117 l
+1.367 2.91 l
+1.822 2.91 l
+1.822 3.881 l
+h
+5.85 -1.073 m
+5.82 -1.015 5.791 -0.912 5.762 -0.765 c
+5.574 -1.022 5.325 -1.147 5.012 -1.147 c
+4.677 -1.147 4.398 -1.04 4.174 -0.823 c
+3.958 -0.599 3.85 -0.31 3.85 0.043 c
+3.85 0.455 3.983 0.771 4.247 0.999 c
+4.512 1.234 4.895 1.352 5.394 1.352 c
+5.718 1.352 l
+5.718 1.675 l
+5.718 1.851 5.681 1.973 5.614 2.042 c
+5.556 2.119 5.468 2.16 5.35 2.16 c
+5.093 2.16 4.968 2.006 4.968 1.705 c
+3.925 1.705 l
+3.925 2.076 4.06 2.381 4.336 2.616 c
+4.608 2.859 4.957 2.983 5.379 2.983 c
+5.82 2.983 6.158 2.865 6.393 2.63 c
+6.636 2.403 6.761 2.08 6.761 1.66 c
+6.761 -0.206 l
+6.761 -0.551 6.809 -0.82 6.908 -1.015 c
+6.908 -1.073 l
+h
+5.247 -0.324 m
+5.354 -0.324 5.446 -0.306 5.527 -0.265 c
+5.614 -0.217 5.677 -0.158 5.718 -0.088 c
+5.718 0.735 l
+5.468 0.735 l
+5.292 0.735 5.148 0.675 5.041 0.558 c
+4.943 0.448 4.895 0.301 4.895 0.118 c
+4.895 -0.177 5.012 -0.324 5.247 -0.324 c
+9.275 0 m
+9.275 0.087 9.231 0.165 9.142 0.235 c
+9.055 0.312 8.866 0.415 8.584 0.544 c
+8.151 0.72 7.852 0.9 7.688 1.087 c
+7.53 1.271 7.453 1.502 7.453 1.778 c
+7.453 2.119 7.573 2.403 7.819 2.63 c
+8.073 2.865 8.411 2.983 8.834 2.983 c
+9.263 2.983 9.612 2.869 9.878 2.645 c
+10.142 2.418 10.275 2.117 10.275 1.734 c
+9.231 1.734 l
+9.231 2.057 9.091 2.219 8.819 2.219 c
+8.708 2.219 8.621 2.183 8.554 2.117 c
+8.484 2.046 8.452 1.947 8.452 1.822 c
+8.452 1.734 8.488 1.653 8.569 1.587 c
+8.646 1.529 8.826 1.433 9.113 1.308 c
+9.543 1.15 9.841 0.974 10.009 0.779 c
+10.186 0.591 10.275 0.341 10.275 0.029 c
+10.275 -0.324 10.142 -0.611 9.878 -0.823 c
+9.612 -1.04 9.263 -1.147 8.834 -1.147 c
+8.54 -1.147 8.279 -1.092 8.055 -0.985 c
+7.827 -0.867 7.65 -0.706 7.526 -0.5 c
+7.408 -0.294 7.349 -0.074 7.349 0.161 c
+8.334 0.161 l
+8.334 -0.026 8.371 -0.162 8.452 -0.25 c
+8.54 -0.339 8.672 -0.383 8.849 -0.383 c
+9.132 -0.383 9.275 -0.258 9.275 0 c
+11.95 2.557 m
+12.174 2.84 12.45 2.983 12.773 2.983 c
+13.134 2.983 13.409 2.855 13.596 2.601 c
+13.791 2.344 13.89 1.962 13.89 1.454 c
+13.89 -1.073 l
+12.847 -1.073 l
+12.847 1.44 l
+12.847 1.675 12.806 1.841 12.729 1.94 c
+12.66 2.046 12.546 2.102 12.391 2.102 c
+12.203 2.102 12.057 2.017 11.95 1.851 c
+11.95 -1.073 l
+10.906 -1.073 l
+10.906 4.571 l
+11.95 4.571 l
+h
+14.728 -0.545 m
+14.728 -0.379 14.78 -0.243 14.89 -0.133 c
+14.996 -0.026 15.143 0.029 15.33 0.029 c
+15.496 0.029 15.64 -0.026 15.757 -0.133 c
+15.875 -0.243 15.933 -0.379 15.933 -0.545 c
+15.933 -0.713 15.875 -0.849 15.757 -0.956 c
+15.64 -1.066 15.496 -1.118 15.33 -1.118 c
+15.154 -1.118 15.008 -1.066 14.89 -0.956 c
+14.78 -0.849 14.728 -0.713 14.728 -0.545 c
+f
+Q
+0.113 0.082 0.09 0 k
+287.665 142.3 234.667 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 135.461 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.146 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.807 l
+-1.896 -1.807 l
+-1.896 -1.263 l
+-2.142 -1.256 -2.359 -1.219 -2.543 -1.161 c
+-2.719 -1.102 -2.873 -1.024 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.034 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.477 -2.234 -0.514 c
+-2.138 -0.554 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.662 l
+-1.907 0.662 -1.926 0.666 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.772 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.279 -3.219 1.426 c
+-3.289 1.573 -3.322 1.757 -3.322 1.985 c
+-3.322 2.18 -3.289 2.345 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.933 -2.645 3.003 -2.469 3.043 c
+-2.293 3.091 -2.102 3.12 -1.896 3.132 c
+-1.896 3.558 l
+-1.543 3.558 l
+-1.543 3.132 l
+-1.319 3.12 -1.128 3.091 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.735 -0.349 2.621 -0.279 2.484 c
+-0.202 2.345 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.459 -1.543 2.5 c
+-1.543 1.368 l
+-1.514 1.368 l
+-1.506 1.368 -1.492 1.36 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.206 c
+-0.756 1.147 -0.595 1.066 -0.455 0.971 c
+-0.32 0.871 -0.213 0.743 -0.132 0.588 c
+-0.044 0.431 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.503 -2.113 2.484 -2.19 2.455 c
+-2.26 2.426 -2.319 2.386 -2.366 2.338 c
+-2.406 2.297 -2.436 2.249 -2.454 2.191 c
+-2.477 2.132 -2.484 2.066 -2.484 1.999 c
+-2.484 1.912 -2.469 1.838 -2.439 1.779 c
+-2.41 1.721 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.201 1.559 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.441 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.302 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.44 c
+-0.904 -0.345 -0.837 -0.201 -0.837 -0.014 c
+6.402 -2.66 m
+6.184 -2.66 5.993 -2.634 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.395 c
+5.284 -2.314 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.616 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.146 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.83 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.219 6.034 -1.219 c
+5.829 -1.219 5.644 -1.183 5.49 -1.102 c
+5.343 -1.014 5.215 -0.897 5.108 -0.749 c
+5.009 -0.595 4.935 -0.411 4.888 -0.205 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.772 4.836 1.019 4.888 1.235 c
+4.946 1.449 5.027 1.632 5.137 1.779 c
+5.244 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.264 6.093 2.264 c
+6.188 2.264 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.919 7.107 1.97 c
+7.115 2.029 7.122 2.077 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.151 2.22 c
+8.004 2.22 l
+7.993 2.139 7.982 2.029 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.414 7.938 -1.635 7.871 -1.822 c
+7.802 -2.006 7.699 -2.16 7.563 -2.278 c
+7.423 -2.403 7.258 -2.499 7.063 -2.557 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.743 7.067 0.919 7.019 1.058 c
+6.978 1.206 6.924 1.324 6.857 1.411 c
+6.799 1.5 6.729 1.559 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.368 c
+5.88 1.279 5.835 1.162 5.799 1.015 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.514 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.558 c
+6.725 -0.521 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.302 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.263 l
+8.86 -1.263 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.603 l
+9.199 1.603 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.597 1.603 m
+13.053 1.603 l
+13.053 2.22 l
+13.641 2.22 l
+13.92 3.117 l
+14.494 3.117 l
+14.494 2.22 l
+15.728 2.22 l
+15.728 1.603 l
+14.494 1.603 l
+14.494 -0.103 l
+14.494 -0.323 l
+14.501 -0.392 14.523 -0.455 14.552 -0.514 c
+14.589 -0.565 14.645 -0.61 14.714 -0.646 c
+14.791 -0.675 14.905 -0.691 15.052 -0.691 c
+15.188 -0.691 15.324 -0.687 15.464 -0.675 c
+15.599 -0.658 15.732 -0.631 15.861 -0.602 c
+15.861 -1.205 l
+15.78 -1.215 15.703 -1.23 15.626 -1.249 c
+15.545 -1.26 15.468 -1.267 15.391 -1.278 c
+15.31 -1.286 15.221 -1.294 15.125 -1.294 c
+15.038 -1.3 14.938 -1.308 14.832 -1.308 c
+14.645 -1.308 14.483 -1.294 14.346 -1.263 c
+14.218 -1.227 14.104 -1.183 14.009 -1.132 c
+13.92 -1.084 13.847 -1.024 13.788 -0.955 c
+13.729 -0.878 13.685 -0.801 13.656 -0.72 c
+13.627 -0.631 13.604 -0.544 13.597 -0.455 c
+13.586 -0.359 13.582 -0.264 13.582 -0.176 c
+h
+24.22 -0.249 m
+24.22 -0.419 24.18 -0.569 24.103 -0.706 c
+24.033 -0.833 23.931 -0.947 23.794 -1.043 c
+23.666 -1.132 23.504 -1.201 23.31 -1.249 c
+23.121 -1.296 22.905 -1.323 22.662 -1.323 c
+22.435 -1.323 22.236 -1.308 22.06 -1.278 c
+21.883 -1.249 21.725 -1.201 21.59 -1.132 c
+21.45 -1.055 21.34 -0.955 21.251 -0.837 c
+21.163 -0.72 21.093 -0.573 21.045 -0.396 c
+21.854 -0.278 l
+21.872 -0.378 21.902 -0.455 21.942 -0.514 c
+21.99 -0.573 22.049 -0.617 22.119 -0.646 c
+22.185 -0.675 22.265 -0.702 22.354 -0.72 c
+22.442 -0.731 22.545 -0.735 22.662 -0.735 c
+22.758 -0.735 22.853 -0.731 22.942 -0.72 c
+23.03 -0.702 23.107 -0.675 23.177 -0.646 c
+23.243 -0.617 23.295 -0.58 23.324 -0.529 c
+23.36 -0.481 23.383 -0.419 23.383 -0.338 c
+23.383 -0.242 23.353 -0.168 23.295 -0.118 c
+23.243 -0.07 23.177 -0.029 23.089 0 c
+23.001 0.038 22.89 0.067 22.766 0.088 c
+22.647 0.118 22.516 0.148 22.369 0.177 c
+22.229 0.214 22.09 0.254 21.942 0.294 c
+21.803 0.342 21.677 0.405 21.56 0.485 c
+21.45 0.563 21.361 0.662 21.296 0.78 c
+21.226 0.897 21.193 1.048 21.193 1.235 c
+21.193 1.389 21.222 1.532 21.28 1.661 c
+21.347 1.798 21.442 1.912 21.56 1.999 c
+21.685 2.088 21.843 2.154 22.03 2.205 c
+22.215 2.253 22.427 2.278 22.662 2.278 c
+22.846 2.278 23.023 2.257 23.192 2.22 c
+23.357 2.191 23.504 2.135 23.632 2.058 c
+23.757 1.989 23.868 1.889 23.956 1.764 c
+24.044 1.646 24.103 1.503 24.133 1.338 c
+23.339 1.264 l
+23.316 1.341 23.287 1.405 23.25 1.455 c
+23.21 1.515 23.162 1.559 23.104 1.588 c
+23.052 1.625 22.99 1.65 22.913 1.661 c
+22.832 1.669 22.751 1.676 22.662 1.676 c
+22.446 1.676 22.284 1.646 22.177 1.588 c
+22.067 1.536 22.016 1.449 22.016 1.324 c
+22.016 1.243 22.034 1.18 22.074 1.133 c
+22.122 1.081 22.185 1.044 22.265 1.015 c
+22.354 0.985 22.45 0.956 22.56 0.927 c
+22.666 0.904 22.788 0.882 22.927 0.853 c
+23.081 0.823 23.239 0.784 23.397 0.736 c
+23.551 0.684 23.692 0.622 23.809 0.545 c
+23.927 0.464 24.022 0.36 24.103 0.235 c
+24.18 0.107 24.22 -0.055 24.22 -0.249 c
+25.783 1.603 m
+25.238 1.603 l
+25.238 2.22 l
+25.826 2.22 l
+26.106 3.117 l
+26.679 3.117 l
+26.679 2.22 l
+27.914 2.22 l
+27.914 1.603 l
+26.679 1.603 l
+26.679 -0.103 l
+26.679 -0.323 l
+26.686 -0.392 26.709 -0.455 26.738 -0.514 c
+26.774 -0.565 26.83 -0.61 26.9 -0.646 c
+26.977 -0.675 27.09 -0.691 27.237 -0.691 c
+27.374 -0.691 27.509 -0.687 27.649 -0.675 c
+27.785 -0.658 27.917 -0.631 28.046 -0.602 c
+28.046 -1.205 l
+27.965 -1.215 27.888 -1.23 27.811 -1.249 c
+27.73 -1.26 27.653 -1.267 27.576 -1.278 c
+27.495 -1.286 27.407 -1.294 27.312 -1.294 c
+27.223 -1.3 27.123 -1.308 27.017 -1.308 c
+26.83 -1.308 26.668 -1.294 26.532 -1.263 c
+26.404 -1.227 26.29 -1.183 26.194 -1.132 c
+26.106 -1.084 26.032 -1.024 25.974 -0.955 c
+25.915 -0.878 25.87 -0.801 25.841 -0.72 c
+25.812 -0.631 25.789 -0.544 25.783 -0.455 c
+25.772 -0.359 25.768 -0.264 25.768 -0.176 c
+h
+30.196 -1.323 m
+30.027 -1.323 29.876 -1.3 29.741 -1.263 c
+29.612 -1.215 29.498 -1.146 29.402 -1.058 c
+29.313 -0.97 29.244 -0.863 29.196 -0.735 c
+29.145 -0.598 29.122 -0.448 29.122 -0.278 c
+29.122 -0.073 29.155 0.096 29.226 0.235 c
+29.292 0.383 29.388 0.493 29.505 0.574 c
+29.63 0.662 29.773 0.724 29.931 0.765 c
+30.096 0.802 30.273 0.827 30.46 0.838 c
+31.181 0.853 l
+31.181 1.029 l
+31.181 1.147 31.17 1.25 31.152 1.338 c
+31.129 1.426 31.096 1.492 31.048 1.544 c
+31.008 1.603 30.96 1.64 30.901 1.661 c
+30.842 1.68 30.776 1.691 30.71 1.691 c
+30.641 1.691 30.578 1.68 30.519 1.661 c
+30.468 1.65 30.42 1.625 30.372 1.588 c
+30.331 1.559 30.298 1.507 30.269 1.441 c
+30.248 1.382 30.233 1.301 30.225 1.206 c
+29.284 1.25 l
+29.313 1.397 29.358 1.532 29.417 1.661 c
+29.483 1.786 29.579 1.897 29.696 1.985 c
+29.814 2.08 29.953 2.154 30.122 2.205 c
+30.298 2.253 30.504 2.278 30.74 2.278 c
+31.181 2.278 31.511 2.168 31.74 1.956 c
+31.975 1.75 32.092 1.441 32.092 1.029 c
+32.092 -0.235 l
+32.092 -0.455 l
+32.099 -0.514 32.114 -0.569 32.136 -0.617 c
+32.154 -0.658 32.184 -0.691 32.224 -0.72 c
+32.261 -0.742 32.313 -0.749 32.371 -0.749 c
+32.438 -0.749 32.507 -0.745 32.577 -0.735 c
+32.577 -1.219 l
+32.519 -1.23 32.463 -1.242 32.415 -1.249 c
+32.375 -1.26 32.334 -1.267 32.297 -1.278 c
+32.257 -1.286 32.213 -1.294 32.166 -1.294 c
+32.114 -1.3 32.055 -1.308 31.989 -1.308 c
+31.761 -1.308 31.596 -1.256 31.489 -1.146 c
+31.379 -1.028 31.316 -0.863 31.298 -0.646 c
+31.283 -0.646 l
+31.214 -0.756 31.144 -0.852 31.077 -0.941 c
+31.008 -1.021 30.931 -1.087 30.842 -1.146 c
+30.755 -1.205 30.655 -1.249 30.549 -1.278 c
+30.449 -1.308 30.331 -1.323 30.196 -1.323 c
+31.181 0.353 m
+30.755 0.339 l
+30.655 0.339 30.564 0.331 30.475 0.324 c
+30.394 0.313 30.328 0.287 30.269 0.25 c
+30.211 0.21 30.159 0.151 30.122 0.074 c
+30.082 0.004 30.063 -0.087 30.063 -0.205 c
+30.063 -0.374 30.096 -0.496 30.167 -0.573 c
+30.233 -0.654 30.331 -0.691 30.46 -0.691 c
+30.567 -0.691 30.666 -0.668 30.755 -0.617 c
+30.85 -0.569 30.931 -0.507 30.99 -0.426 c
+31.056 -0.349 31.107 -0.261 31.137 -0.161 c
+31.166 -0.055 31.181 0.059 31.181 0.177 c
+h
+36.403 -0.249 m
+36.403 -0.419 36.362 -0.569 36.285 -0.706 c
+36.215 -0.833 36.112 -0.947 35.976 -1.043 c
+35.848 -1.132 35.686 -1.201 35.491 -1.249 c
+35.304 -1.296 35.087 -1.323 34.844 -1.323 c
+34.616 -1.323 34.418 -1.308 34.242 -1.278 c
+34.065 -1.249 33.907 -1.201 33.772 -1.132 c
+33.631 -1.055 33.521 -0.955 33.433 -0.837 c
+33.345 -0.72 33.275 -0.573 33.228 -0.396 c
+34.036 -0.278 l
+34.055 -0.378 34.084 -0.455 34.124 -0.514 c
+34.171 -0.573 34.231 -0.617 34.3 -0.646 c
+34.367 -0.675 34.447 -0.702 34.535 -0.72 c
+34.624 -0.731 34.726 -0.735 34.844 -0.735 c
+34.94 -0.735 35.035 -0.731 35.123 -0.72 c
+35.212 -0.702 35.289 -0.675 35.359 -0.646 c
+35.425 -0.617 35.476 -0.58 35.505 -0.529 c
+35.543 -0.481 35.565 -0.419 35.565 -0.338 c
+35.565 -0.242 35.535 -0.168 35.476 -0.118 c
+35.425 -0.07 35.359 -0.029 35.27 0 c
+35.183 0.038 35.073 0.067 34.948 0.088 c
+34.83 0.118 34.697 0.148 34.551 0.177 c
+34.41 0.214 34.271 0.254 34.124 0.294 c
+33.984 0.342 33.859 0.405 33.742 0.485 c
+33.631 0.563 33.544 0.662 33.477 0.78 c
+33.408 0.897 33.375 1.048 33.375 1.235 c
+33.375 1.389 33.404 1.532 33.463 1.661 c
+33.529 1.798 33.624 1.912 33.742 1.999 c
+33.867 2.088 34.025 2.154 34.212 2.205 c
+34.396 2.253 34.609 2.278 34.844 2.278 c
+35.028 2.278 35.204 2.257 35.374 2.22 c
+35.539 2.191 35.686 2.135 35.815 2.058 c
+35.939 1.989 36.05 1.889 36.138 1.764 c
+36.226 1.646 36.285 1.503 36.314 1.338 c
+35.52 1.264 l
+35.499 1.341 35.469 1.405 35.432 1.455 c
+35.392 1.515 35.345 1.559 35.285 1.588 c
+35.234 1.625 35.171 1.65 35.094 1.661 c
+35.013 1.669 34.932 1.676 34.844 1.676 c
+34.628 1.676 34.466 1.646 34.36 1.588 c
+34.249 1.536 34.198 1.449 34.198 1.324 c
+34.198 1.243 34.216 1.18 34.256 1.133 c
+34.304 1.081 34.367 1.044 34.447 1.015 c
+34.535 0.985 34.631 0.956 34.742 0.927 c
+34.848 0.904 34.969 0.882 35.109 0.853 c
+35.264 0.823 35.422 0.784 35.58 0.736 c
+35.734 0.684 35.873 0.622 35.991 0.545 c
+36.108 0.464 36.204 0.36 36.285 0.235 c
+36.362 0.107 36.403 -0.055 36.403 -0.249 c
+38.262 1.515 m
+38.379 1.786 38.53 1.985 38.718 2.103 c
+38.901 2.22 39.122 2.278 39.379 2.278 c
+39.584 2.278 39.754 2.242 39.894 2.176 c
+40.041 2.106 40.151 2.014 40.232 1.897 c
+40.32 1.779 40.378 1.636 40.408 1.47 c
+40.444 1.301 40.467 1.125 40.467 0.941 c
+40.467 -1.263 l
+39.555 -1.263 l
+39.555 0.736 l
+39.555 0.871 39.544 0.992 39.526 1.103 c
+39.515 1.21 39.489 1.297 39.453 1.368 c
+39.412 1.445 39.353 1.503 39.276 1.544 c
+39.206 1.58 39.114 1.603 38.996 1.603 c
+38.886 1.603 38.791 1.577 38.703 1.529 c
+38.615 1.478 38.534 1.411 38.468 1.324 c
+38.409 1.235 38.358 1.125 38.321 1 c
+38.291 0.882 38.277 0.75 38.277 0.603 c
+38.277 -1.263 l
+37.365 -1.263 l
+37.365 3.514 l
+38.277 3.514 l
+38.277 2.205 l
+38.277 2.135 38.269 2.066 38.262 1.999 c
+38.262 1.794 l
+38.262 1.735 38.254 1.68 38.248 1.632 c
+38.248 1.515 l
+h
+46.354 2.22 m
+46.362 2.198 46.368 2.165 46.368 2.117 c
+46.376 2.077 46.383 2.029 46.383 1.97 c
+46.391 1.919 46.398 1.867 46.398 1.808 c
+46.398 1.646 l
+46.412 1.646 l
+46.472 1.764 46.537 1.86 46.618 1.941 c
+46.695 2.018 46.78 2.08 46.869 2.132 c
+46.956 2.191 47.044 2.228 47.133 2.249 c
+47.228 2.268 47.328 2.278 47.426 2.278 c
+47.632 2.278 47.812 2.234 47.97 2.147 c
+48.125 2.058 48.253 1.929 48.353 1.764 c
+48.459 1.607 48.536 1.415 48.588 1.191 c
+48.647 0.975 48.676 0.739 48.676 0.485 c
+48.676 0.221 48.647 -0.025 48.588 -0.249 c
+48.536 -0.467 48.459 -0.658 48.353 -0.823 c
+48.253 -0.98 48.122 -1.102 47.956 -1.19 c
+47.798 -1.278 47.611 -1.323 47.397 -1.323 c
+47.298 -1.323 47.199 -1.311 47.104 -1.294 c
+47.004 -1.271 46.912 -1.242 46.824 -1.19 c
+46.743 -1.142 46.666 -1.08 46.589 -0.999 c
+46.52 -0.922 46.46 -0.83 46.412 -0.72 c
+46.398 -0.72 l
+46.398 -0.808 l
+46.405 -0.849 46.412 -0.897 46.412 -0.955 c
+46.412 -1.117 l
+46.412 -1.294 l
+46.412 -2.63 l
+45.501 -2.63 l
+45.501 1.455 l
+45.501 1.621 45.494 1.768 45.487 1.897 c
+45.487 2.22 l
+h
+46.398 0.456 m
+46.398 0.229 46.416 0.038 46.457 -0.118 c
+46.505 -0.264 46.559 -0.382 46.618 -0.47 c
+46.684 -0.558 46.758 -0.625 46.838 -0.661 c
+46.916 -0.702 46.993 -0.72 47.074 -0.72 c
+47.17 -0.72 47.258 -0.698 47.339 -0.646 c
+47.426 -0.598 47.493 -0.529 47.544 -0.44 c
+47.603 -0.345 47.647 -0.22 47.677 -0.073 c
+47.713 0.081 47.735 0.269 47.735 0.485 c
+47.735 0.875 47.677 1.169 47.559 1.368 c
+47.449 1.563 47.295 1.661 47.089 1.661 c
+47.008 1.661 46.931 1.64 46.854 1.603 c
+46.773 1.563 46.699 1.5 46.633 1.411 c
+46.563 1.324 46.505 1.199 46.457 1.044 c
+46.416 0.886 46.398 0.691 46.398 0.456 c
+52.751 0.485 m
+52.751 0.21 52.714 -0.04 52.648 -0.264 c
+52.579 -0.481 52.476 -0.668 52.34 -0.823 c
+52.201 -0.98 52.024 -1.102 51.81 -1.19 c
+51.594 -1.278 51.34 -1.323 51.046 -1.323 c
+50.771 -1.323 50.524 -1.278 50.312 -1.19 c
+50.106 -1.102 49.933 -0.98 49.797 -0.823 c
+49.657 -0.668 49.554 -0.481 49.489 -0.264 c
+49.419 -0.04 49.385 0.21 49.385 0.485 c
+49.385 0.739 49.415 0.975 49.473 1.191 c
+49.539 1.415 49.643 1.607 49.782 1.764 c
+49.918 1.929 50.094 2.058 50.312 2.147 c
+50.524 2.234 50.782 2.278 51.076 2.278 c
+51.388 2.278 51.649 2.234 51.854 2.147 c
+52.068 2.058 52.241 1.929 52.369 1.764 c
+52.505 1.607 52.604 1.415 52.664 1.191 c
+52.722 0.975 52.751 0.739 52.751 0.485 c
+51.796 0.485 m
+51.796 0.691 51.781 0.867 51.752 1.015 c
+51.73 1.162 51.694 1.283 51.634 1.382 c
+51.575 1.478 51.502 1.548 51.414 1.588 c
+51.326 1.636 51.216 1.661 51.091 1.661 c
+50.826 1.661 50.634 1.563 50.518 1.368 c
+50.399 1.18 50.341 0.886 50.341 0.485 c
+50.341 0.063 50.399 -0.242 50.518 -0.426 c
+50.634 -0.613 50.811 -0.706 51.046 -0.706 c
+51.172 -0.706 51.285 -0.687 51.384 -0.646 c
+51.48 -0.598 51.561 -0.525 51.619 -0.426 c
+51.686 -0.33 51.73 -0.205 51.752 -0.058 c
+51.781 0.088 51.796 0.269 51.796 0.485 c
+54.475 2.22 m
+54.482 2.198 54.49 2.165 54.49 2.117 c
+54.497 2.077 54.505 2.029 54.505 1.97 c
+54.512 1.919 54.519 1.867 54.519 1.808 c
+54.519 1.646 l
+54.534 1.646 l
+54.593 1.764 54.659 1.86 54.74 1.941 c
+54.817 2.018 54.902 2.08 54.989 2.132 c
+55.077 2.191 55.166 2.228 55.254 2.249 c
+55.349 2.268 55.449 2.278 55.548 2.278 c
+55.754 2.278 55.934 2.234 56.092 2.147 c
+56.246 2.058 56.375 1.929 56.474 1.764 c
+56.581 1.607 56.658 1.415 56.71 1.191 c
+56.768 0.975 56.797 0.739 56.797 0.485 c
+56.797 0.221 56.768 -0.025 56.71 -0.249 c
+56.658 -0.467 56.581 -0.658 56.474 -0.823 c
+56.375 -0.98 56.242 -1.102 56.077 -1.19 c
+55.919 -1.278 55.731 -1.323 55.519 -1.323 c
+55.419 -1.323 55.32 -1.311 55.224 -1.294 c
+55.125 -1.271 55.033 -1.242 54.946 -1.19 c
+54.865 -1.142 54.788 -1.08 54.711 -0.999 c
+54.64 -0.922 54.582 -0.83 54.534 -0.72 c
+54.519 -0.72 l
+54.519 -0.808 l
+54.526 -0.849 54.534 -0.897 54.534 -0.955 c
+54.534 -1.117 l
+54.534 -1.294 l
+54.534 -2.63 l
+53.622 -2.63 l
+53.622 1.455 l
+53.622 1.621 53.615 1.768 53.608 1.897 c
+53.608 2.22 l
+h
+54.519 0.456 m
+54.519 0.229 54.537 0.038 54.578 -0.118 c
+54.626 -0.264 54.68 -0.382 54.74 -0.47 c
+54.806 -0.558 54.879 -0.625 54.96 -0.661 c
+55.037 -0.702 55.114 -0.72 55.195 -0.72 c
+55.291 -0.72 55.379 -0.698 55.459 -0.646 c
+55.548 -0.598 55.614 -0.529 55.665 -0.44 c
+55.725 -0.345 55.769 -0.22 55.798 -0.073 c
+55.835 0.081 55.856 0.269 55.856 0.485 c
+55.856 0.875 55.798 1.169 55.68 1.368 c
+55.57 1.563 55.416 1.661 55.21 1.661 c
+55.129 1.661 55.052 1.64 54.975 1.603 c
+54.894 1.563 54.821 1.5 54.754 1.411 c
+54.684 1.324 54.626 1.199 54.578 1.044 c
+54.537 0.886 54.519 0.691 54.519 0.456 c
+f
+Q
+q 1 0 0 1 326.4111 120.7036 cm
+0 0 m
+-1.808 0 l
+-2.219 -1.396 l
+-2.911 -1.396 l
+-1.19 3.954 l
+-0.617 3.954 l
+1.118 -1.396 l
+0.426 -1.396 l
+h
+-1.631 0.588 m
+-0.176 0.588 l
+-0.897 3.013 l
+h
+4.63 0.397 m
+4.63 -0.231 4.513 -0.702 4.278 -1.014 c
+4.05 -1.319 3.734 -1.47 3.323 -1.47 c
+2.918 -1.47 2.61 -1.319 2.396 -1.014 c
+2.396 -2.925 l
+1.75 -2.925 l
+1.75 2.587 l
+2.338 2.587 l
+2.382 2.146 l
+2.595 2.488 2.903 2.66 3.308 2.66 c
+3.749 2.66 4.075 2.506 4.293 2.205 c
+4.505 1.9 4.619 1.444 4.63 0.838 c
+h
+3.984 0.779 m
+3.984 1.22 3.913 1.544 3.778 1.749 c
+3.638 1.962 3.418 2.072 3.117 2.072 c
+2.801 2.072 2.562 1.918 2.396 1.617 c
+2.396 -0.455 l
+2.562 -0.761 2.801 -0.912 3.117 -0.912 c
+3.41 -0.912 3.624 -0.808 3.763 -0.603 c
+3.899 -0.389 3.973 -0.059 3.984 0.382 c
+h
+8.349 0.397 m
+8.349 -0.231 8.231 -0.702 7.996 -1.014 c
+7.769 -1.319 7.453 -1.47 7.041 -1.47 c
+6.637 -1.47 6.328 -1.319 6.115 -1.014 c
+6.115 -2.925 l
+5.469 -2.925 l
+5.469 2.587 l
+6.056 2.587 l
+6.101 2.146 l
+6.313 2.488 6.622 2.66 7.026 2.66 c
+7.468 2.66 7.794 2.506 8.011 2.205 c
+8.224 1.9 8.339 1.444 8.349 0.838 c
+h
+7.703 0.779 m
+7.703 1.22 7.633 1.544 7.497 1.749 c
+7.358 1.962 7.136 2.072 6.835 2.072 c
+6.519 2.072 6.28 1.918 6.115 1.617 c
+6.115 -0.455 l
+6.28 -0.761 6.519 -0.912 6.835 -0.912 c
+7.129 -0.912 7.342 -0.808 7.482 -0.603 c
+7.618 -0.389 7.691 -0.059 7.703 0.382 c
+h
+9.893 -1.396 -0.647 5.644 re
+11.994 -0.309 m
+12.715 2.587 l
+13.406 2.587 l
+12.112 -1.955 l
+12.013 -2.296 11.869 -2.558 11.686 -2.734 c
+11.51 -2.911 11.308 -2.999 11.084 -2.999 c
+10.995 -2.999 10.882 -2.977 10.745 -2.94 c
+10.745 -2.396 l
+10.892 -2.411 l
+11.076 -2.411 11.223 -2.367 11.333 -2.278 c
+11.439 -2.19 11.528 -2.032 11.597 -1.808 c
+11.715 -1.367 l
+10.554 2.587 l
+11.26 2.587 l
+h
+17.698 -0.382 m
+17.698 -0.235 17.643 -0.114 17.536 -0.015 c
+17.426 0.081 17.22 0.198 16.919 0.338 c
+16.573 0.485 16.331 0.607 16.184 0.706 c
+16.037 0.812 15.927 0.929 15.861 1.058 c
+15.79 1.183 15.757 1.341 15.757 1.529 c
+15.757 1.852 15.875 2.12 16.11 2.337 c
+16.345 2.55 16.647 2.66 17.022 2.66 c
+17.404 2.66 17.712 2.547 17.947 2.323 c
+18.183 2.095 18.3 1.808 18.3 1.455 c
+17.654 1.455 l
+17.654 1.631 17.595 1.783 17.477 1.911 c
+17.359 2.036 17.205 2.102 17.022 2.102 c
+16.823 2.102 16.673 2.047 16.566 1.94 c
+16.455 1.841 16.405 1.708 16.405 1.544 c
+16.405 1.415 16.441 1.309 16.522 1.22 c
+16.599 1.139 16.79 1.037 17.095 0.912 c
+17.573 0.724 17.904 0.536 18.08 0.353 c
+18.256 0.176 18.344 -0.052 18.344 -0.324 c
+18.344 -0.676 18.219 -0.956 17.978 -1.161 c
+17.742 -1.367 17.426 -1.47 17.037 -1.47 c
+16.613 -1.47 16.276 -1.353 16.023 -1.118 c
+15.765 -0.875 15.64 -0.569 15.64 -0.206 c
+16.287 -0.206 l
+16.295 -0.434 16.364 -0.61 16.493 -0.735 c
+16.617 -0.852 16.802 -0.912 17.037 -0.912 c
+17.249 -0.912 17.411 -0.864 17.521 -0.765 c
+17.639 -0.669 17.698 -0.54 17.698 -0.382 c
+20.035 3.543 m
+20.035 2.587 l
+20.638 2.587 l
+20.638 2.057 l
+20.035 2.057 l
+20.035 -0.412 l
+20.035 -0.569 20.057 -0.687 20.108 -0.765 c
+20.168 -0.845 20.256 -0.882 20.373 -0.882 c
+20.461 -0.882 20.55 -0.867 20.638 -0.838 c
+20.638 -1.396 l
+20.491 -1.444 20.336 -1.47 20.182 -1.47 c
+19.925 -1.47 19.73 -1.378 19.594 -1.191 c
+19.454 -1.007 19.389 -0.746 19.389 -0.412 c
+19.389 2.057 l
+18.786 2.057 l
+18.786 2.587 l
+19.389 2.587 l
+19.389 3.543 l
+h
+21.197 0.779 m
+21.197 1.356 21.332 1.812 21.608 2.146 c
+21.891 2.488 22.262 2.66 22.725 2.66 c
+23.185 2.66 23.551 2.491 23.827 2.161 c
+24.11 1.837 24.257 1.389 24.268 0.823 c
+24.268 0.397 l
+24.268 -0.173 24.125 -0.628 23.842 -0.97 c
+23.566 -1.305 23.199 -1.47 22.74 -1.47 c
+22.277 -1.47 21.905 -1.309 21.623 -0.985 c
+21.347 -0.654 21.203 -0.214 21.197 0.338 c
+h
+21.843 0.397 m
+21.843 -0.008 21.92 -0.324 22.078 -0.559 c
+22.244 -0.794 22.464 -0.912 22.74 -0.912 c
+23.306 -0.912 23.599 -0.5 23.622 0.324 c
+23.622 0.779 l
+23.622 1.18 23.537 1.5 23.372 1.735 c
+23.214 1.977 22.997 2.102 22.725 2.102 c
+22.46 2.102 22.244 1.977 22.078 1.735 c
+21.92 1.5 21.843 1.18 21.843 0.779 c
+h
+26.753 1.97 m
+26.664 1.988 26.566 1.999 26.458 1.999 c
+26.124 1.999 25.889 1.816 25.753 1.455 c
+25.753 -1.396 l
+25.106 -1.396 l
+25.106 2.587 l
+25.739 2.587 l
+25.753 2.175 l
+25.93 2.499 26.172 2.66 26.487 2.66 c
+26.595 2.66 26.683 2.639 26.753 2.602 c
+h
+28.752 -1.47 m
+28.252 -1.47 27.869 -1.323 27.605 -1.029 c
+27.341 -0.735 27.208 -0.301 27.208 0.279 c
+27.208 0.75 l
+27.208 1.345 27.333 1.812 27.59 2.146 c
+27.855 2.488 28.215 2.66 28.678 2.66 c
+29.138 2.66 29.479 2.506 29.707 2.205 c
+29.942 1.911 30.063 1.448 30.074 0.823 c
+30.074 0.397 l
+27.855 0.397 l
+27.855 0.309 l
+27.855 -0.125 27.932 -0.437 28.09 -0.632 c
+28.255 -0.819 28.487 -0.912 28.781 -0.912 c
+28.976 -0.912 29.149 -0.879 29.296 -0.808 c
+29.442 -0.731 29.579 -0.613 29.707 -0.455 c
+30.045 -0.867 l
+29.758 -1.272 29.328 -1.47 28.752 -1.47 c
+28.678 2.102 m
+28.403 2.102 28.201 2.007 28.075 1.822 c
+27.947 1.635 27.873 1.345 27.855 0.956 c
+29.428 0.956 l
+29.428 1.043 l
+29.406 1.426 29.34 1.694 29.222 1.852 c
+29.105 2.018 28.92 2.102 28.678 2.102 c
+30.721 0.779 m
+30.721 1.386 30.832 1.852 31.059 2.175 c
+31.295 2.499 31.622 2.66 32.044 2.66 c
+32.426 2.66 32.724 2.502 32.941 2.19 c
+32.941 4.248 l
+33.587 4.248 l
+33.587 -1.396 l
+32.999 -1.396 l
+32.956 -0.97 l
+32.75 -1.305 32.445 -1.47 32.044 -1.47 c
+31.632 -1.47 31.31 -1.315 31.074 -1 c
+30.839 -0.676 30.721 -0.22 30.721 0.368 c
+h
+31.368 0.397 m
+31.368 -0.044 31.43 -0.374 31.559 -0.588 c
+31.695 -0.794 31.916 -0.897 32.22 -0.897 c
+32.544 -0.897 32.783 -0.735 32.941 -0.412 c
+32.941 1.602 l
+32.772 1.914 32.533 2.072 32.22 2.072 c
+31.916 2.072 31.695 1.97 31.559 1.764 c
+31.43 1.558 31.368 1.234 31.368 0.794 c
+h
+f
+Q
+q 1 0 0 1 364.3793 120.38 cm
+0 0 m
+0 0.088 -0.044 0.166 -0.133 0.235 c
+-0.221 0.312 -0.408 0.416 -0.691 0.544 c
+-1.125 0.721 -1.422 0.9 -1.588 1.087 c
+-1.746 1.272 -1.823 1.503 -1.823 1.779 c
+-1.823 2.12 -1.702 2.404 -1.455 2.631 c
+-1.202 2.866 -0.864 2.984 -0.441 2.984 c
+-0.011 2.984 0.338 2.87 0.602 2.646 c
+0.867 2.419 0.999 2.117 0.999 1.735 c
+-0.044 1.735 l
+-0.044 2.058 -0.184 2.22 -0.456 2.22 c
+-0.566 2.22 -0.655 2.183 -0.721 2.117 c
+-0.79 2.047 -0.823 1.948 -0.823 1.823 c
+-0.823 1.735 -0.786 1.654 -0.706 1.588 c
+-0.628 1.529 -0.449 1.434 -0.162 1.309 c
+0.268 1.151 0.565 0.974 0.735 0.779 c
+0.911 0.592 0.999 0.342 0.999 0.029 c
+0.999 -0.324 0.867 -0.61 0.602 -0.823 c
+0.338 -1.04 -0.011 -1.147 -0.441 -1.147 c
+-0.736 -1.147 -0.996 -1.091 -1.22 -0.985 c
+-1.448 -0.867 -1.625 -0.706 -1.75 -0.5 c
+-1.867 -0.294 -1.926 -0.073 -1.926 0.162 c
+-0.941 0.162 l
+-0.941 -0.025 -0.904 -0.162 -0.823 -0.249 c
+-0.736 -0.338 -0.603 -0.382 -0.427 -0.382 c
+-0.144 -0.382 0 -0.257 0 0 c
+2.866 3.881 m
+2.866 2.911 l
+3.395 2.911 l
+3.395 2.117 l
+2.866 2.117 l
+2.866 0.147 l
+2.866 -0.01 2.884 -0.118 2.925 -0.176 c
+2.973 -0.235 3.057 -0.264 3.175 -0.264 c
+3.281 -0.264 3.366 -0.257 3.424 -0.235 c
+3.424 -1.043 l
+3.248 -1.109 3.057 -1.147 2.851 -1.147 c
+2.175 -1.147 1.83 -0.76 1.822 0.015 c
+1.822 2.117 l
+1.367 2.117 l
+1.367 2.911 l
+1.822 2.911 l
+1.822 3.881 l
+h
+5.85 -1.072 m
+5.82 -1.014 5.791 -0.912 5.762 -0.764 c
+5.574 -1.022 5.325 -1.147 5.012 -1.147 c
+4.677 -1.147 4.398 -1.04 4.174 -0.823 c
+3.958 -0.598 3.85 -0.309 3.85 0.044 c
+3.85 0.456 3.983 0.772 4.247 1 c
+4.512 1.235 4.895 1.353 5.394 1.353 c
+5.718 1.353 l
+5.718 1.675 l
+5.718 1.852 5.681 1.974 5.614 2.043 c
+5.556 2.12 5.468 2.161 5.35 2.161 c
+5.093 2.161 4.968 2.007 4.968 1.706 c
+3.925 1.706 l
+3.925 2.076 4.06 2.381 4.336 2.616 c
+4.608 2.859 4.957 2.984 5.379 2.984 c
+5.82 2.984 6.158 2.866 6.393 2.631 c
+6.636 2.404 6.761 2.08 6.761 1.661 c
+6.761 -0.206 l
+6.761 -0.551 6.809 -0.819 6.908 -1.014 c
+6.908 -1.072 l
+h
+5.247 -0.324 m
+5.354 -0.324 5.446 -0.305 5.527 -0.264 c
+5.614 -0.216 5.677 -0.158 5.718 -0.088 c
+5.718 0.735 l
+5.468 0.735 l
+5.292 0.735 5.148 0.676 5.041 0.559 c
+4.943 0.449 4.895 0.302 4.895 0.118 c
+4.895 -0.176 5.012 -0.324 5.247 -0.324 c
+9.275 0 m
+9.275 0.088 9.231 0.166 9.142 0.235 c
+9.055 0.312 8.866 0.416 8.584 0.544 c
+8.151 0.721 7.852 0.9 7.688 1.087 c
+7.53 1.272 7.453 1.503 7.453 1.779 c
+7.453 2.12 7.573 2.404 7.819 2.631 c
+8.073 2.866 8.411 2.984 8.834 2.984 c
+9.263 2.984 9.612 2.87 9.878 2.646 c
+10.142 2.419 10.275 2.117 10.275 1.735 c
+9.231 1.735 l
+9.231 2.058 9.091 2.22 8.819 2.22 c
+8.708 2.22 8.621 2.183 8.554 2.117 c
+8.485 2.047 8.452 1.948 8.452 1.823 c
+8.452 1.735 8.488 1.654 8.569 1.588 c
+8.646 1.529 8.826 1.434 9.113 1.309 c
+9.543 1.151 9.841 0.974 10.009 0.779 c
+10.186 0.592 10.275 0.342 10.275 0.029 c
+10.275 -0.324 10.142 -0.61 9.878 -0.823 c
+9.612 -1.04 9.263 -1.147 8.834 -1.147 c
+8.54 -1.147 8.279 -1.091 8.055 -0.985 c
+7.827 -0.867 7.65 -0.706 7.526 -0.5 c
+7.408 -0.294 7.349 -0.073 7.349 0.162 c
+8.334 0.162 l
+8.334 -0.025 8.371 -0.162 8.452 -0.249 c
+8.54 -0.338 8.672 -0.382 8.849 -0.382 c
+9.132 -0.382 9.275 -0.257 9.275 0 c
+11.95 2.558 m
+12.174 2.841 12.45 2.984 12.773 2.984 c
+13.134 2.984 13.409 2.855 13.597 2.602 c
+13.791 2.344 13.89 1.962 13.89 1.455 c
+13.89 -1.072 l
+12.847 -1.072 l
+12.847 1.44 l
+12.847 1.675 12.806 1.841 12.729 1.941 c
+12.66 2.047 12.546 2.103 12.391 2.103 c
+12.203 2.103 12.057 2.018 11.95 1.852 c
+11.95 -1.072 l
+10.906 -1.072 l
+10.906 4.572 l
+11.95 4.572 l
+h
+f
+Q
+q 1 0 0 1 382.2233 119.7921 cm
+0 0 m
+0.214 0 0.387 0.063 0.515 0.191 c
+0.651 0.327 0.724 0.518 0.736 0.765 c
+1.353 0.765 l
+1.33 0.382 1.195 0.063 0.941 -0.191 c
+0.684 -0.437 0.372 -0.559 0 -0.559 c
+-0.492 -0.559 -0.867 -0.407 -1.132 -0.103 c
+-1.389 0.21 -1.514 0.676 -1.514 1.294 c
+-1.514 1.735 l
+-1.514 2.33 -1.389 2.786 -1.132 3.102 c
+-0.867 3.414 -0.492 3.572 0 3.572 c
+0.401 3.572 0.721 3.439 0.956 3.175 c
+1.198 2.918 1.33 2.573 1.353 2.132 c
+0.736 2.132 l
+0.713 2.425 0.64 2.646 0.515 2.793 c
+0.397 2.94 0.225 3.013 0 3.013 c
+-0.294 3.013 -0.511 2.914 -0.646 2.72 c
+-0.786 2.532 -0.86 2.224 -0.867 1.793 c
+-0.867 1.279 l
+-0.867 0.809 -0.801 0.474 -0.661 0.279 c
+-0.514 0.092 -0.294 0 0 0 c
+1.97 1.691 m
+1.97 2.267 2.106 2.723 2.382 3.057 c
+2.664 3.4 3.036 3.572 3.499 3.572 c
+3.958 3.572 4.326 3.403 4.601 3.072 c
+4.884 2.749 5.031 2.301 5.042 1.735 c
+5.042 1.309 l
+5.042 0.738 4.898 0.283 4.616 -0.058 c
+4.341 -0.393 3.973 -0.559 3.514 -0.559 c
+3.051 -0.559 2.679 -0.397 2.396 -0.073 c
+2.12 0.258 1.977 0.698 1.97 1.249 c
+h
+2.617 1.309 m
+2.617 0.904 2.694 0.588 2.852 0.353 c
+3.017 0.118 3.238 0 3.514 0 c
+4.079 0 4.373 0.412 4.395 1.235 c
+4.395 1.691 l
+4.395 2.091 4.31 2.411 4.146 2.646 c
+3.988 2.889 3.77 3.013 3.499 3.013 c
+3.234 3.013 3.017 2.889 2.852 2.646 c
+2.694 2.411 2.617 2.091 2.617 1.691 c
+h
+6.498 3.499 m
+6.512 3.057 l
+6.766 3.4 7.089 3.572 7.483 3.572 c
+8.188 3.572 8.544 3.102 8.555 2.161 c
+8.555 -0.484 l
+7.909 -0.484 l
+7.909 2.132 l
+7.909 2.444 7.853 2.664 7.747 2.793 c
+7.637 2.918 7.483 2.984 7.277 2.984 c
+7.119 2.984 6.972 2.929 6.835 2.822 c
+6.707 2.712 6.604 2.577 6.527 2.411 c
+6.527 -0.484 l
+5.88 -0.484 l
+5.88 3.499 l
+h
+10.378 4.454 m
+10.378 3.499 l
+10.98 3.499 l
+10.98 2.969 l
+10.378 2.969 l
+10.378 0.5 l
+10.378 0.342 10.4 0.225 10.452 0.147 c
+10.51 0.067 10.598 0.029 10.716 0.029 c
+10.804 0.029 10.892 0.044 10.98 0.073 c
+10.98 -0.484 l
+10.834 -0.532 10.679 -0.559 10.525 -0.559 c
+10.267 -0.559 10.073 -0.467 9.937 -0.279 c
+9.797 -0.095 9.731 0.166 9.731 0.5 c
+9.731 2.969 l
+9.129 2.969 l
+9.129 3.499 l
+9.731 3.499 l
+9.731 4.454 l
+h
+13.17 -0.559 m
+12.671 -0.559 12.289 -0.411 12.025 -0.118 c
+11.759 0.177 11.628 0.611 11.628 1.191 c
+11.628 1.661 l
+11.628 2.257 11.753 2.723 12.009 3.057 c
+12.274 3.4 12.634 3.572 13.097 3.572 c
+13.557 3.572 13.898 3.418 14.126 3.117 c
+14.361 2.822 14.483 2.359 14.494 1.735 c
+14.494 1.309 l
+12.274 1.309 l
+12.274 1.22 l
+12.274 0.786 12.351 0.474 12.509 0.279 c
+12.675 0.092 12.906 0 13.2 0 c
+13.395 0 13.567 0.033 13.714 0.103 c
+13.862 0.181 13.997 0.298 14.126 0.456 c
+14.464 0.044 l
+14.178 -0.36 13.748 -0.559 13.17 -0.559 c
+13.097 3.013 m
+12.821 3.013 12.619 2.918 12.495 2.734 c
+12.366 2.547 12.293 2.257 12.274 1.867 c
+13.847 1.867 l
+13.847 1.955 l
+13.825 2.338 13.758 2.606 13.641 2.764 c
+13.523 2.929 13.34 3.013 13.097 3.013 c
+15.89 3.499 m
+15.905 3.057 l
+16.158 3.4 16.482 3.572 16.875 3.572 c
+17.581 3.572 17.937 3.102 17.947 2.161 c
+17.947 -0.484 l
+17.301 -0.484 l
+17.301 2.132 l
+17.301 2.444 17.246 2.664 17.139 2.793 c
+17.029 2.918 16.875 2.984 16.669 2.984 c
+16.511 2.984 16.364 2.929 16.228 2.822 c
+16.1 2.712 15.996 2.577 15.919 2.411 c
+15.919 -0.484 l
+15.273 -0.484 l
+15.273 3.499 l
+h
+19.771 4.454 m
+19.771 3.499 l
+20.374 3.499 l
+20.374 2.969 l
+19.771 2.969 l
+19.771 0.5 l
+19.771 0.342 19.792 0.225 19.844 0.147 c
+19.903 0.067 19.991 0.029 20.108 0.029 c
+20.197 0.029 20.285 0.044 20.374 0.073 c
+20.374 -0.484 l
+20.226 -0.532 20.072 -0.559 19.917 -0.559 c
+19.66 -0.559 19.466 -0.467 19.329 -0.279 c
+19.19 -0.095 19.123 0.166 19.123 0.5 c
+19.123 2.969 l
+18.521 2.969 l
+18.521 3.499 l
+19.123 3.499 l
+19.123 4.454 l
+h
+23.563 -0.484 -0.646 3.983 re
+23.607 4.542 m
+23.607 4.432 23.578 4.341 23.518 4.262 c
+23.46 4.193 23.364 4.16 23.24 4.16 c
+23.121 4.16 23.026 4.193 22.961 4.262 c
+22.901 4.341 22.872 4.432 22.872 4.542 c
+22.872 4.659 22.901 4.752 22.961 4.821 c
+23.026 4.898 23.121 4.939 23.24 4.939 c
+23.364 4.939 23.46 4.898 23.518 4.821 c
+23.578 4.74 23.607 4.649 23.607 4.542 c
+25.195 3.499 m
+25.209 3.057 l
+25.463 3.4 25.787 3.572 26.179 3.572 c
+26.884 3.572 27.241 3.102 27.252 2.161 c
+27.252 -0.484 l
+26.606 -0.484 l
+26.606 2.132 l
+26.606 2.444 26.55 2.664 26.444 2.793 c
+26.334 2.918 26.179 2.984 25.974 2.984 c
+25.816 2.984 25.669 2.929 25.533 2.822 c
+25.404 2.712 25.301 2.577 25.224 2.411 c
+25.224 -0.484 l
+24.577 -0.484 l
+24.577 3.499 l
+h
+29.075 4.454 m
+29.075 3.499 l
+29.678 3.499 l
+29.678 2.969 l
+29.075 2.969 l
+29.075 0.5 l
+29.075 0.342 29.097 0.225 29.149 0.147 c
+29.207 0.067 29.296 0.029 29.413 0.029 c
+29.502 0.029 29.59 0.044 29.678 0.073 c
+29.678 -0.484 l
+29.531 -0.532 29.376 -0.559 29.222 -0.559 c
+28.964 -0.559 28.77 -0.467 28.634 -0.279 c
+28.494 -0.095 28.428 0.166 28.428 0.5 c
+28.428 2.969 l
+27.825 2.969 l
+27.825 3.499 l
+28.428 3.499 l
+28.428 4.454 l
+h
+30.236 1.691 m
+30.236 2.267 30.373 2.723 30.647 3.057 c
+30.931 3.4 31.302 3.572 31.765 3.572 c
+32.224 3.572 32.592 3.403 32.868 3.072 c
+33.151 2.749 33.297 2.301 33.309 1.735 c
+33.309 1.309 l
+33.309 0.738 33.165 0.283 32.883 -0.058 c
+32.607 -0.393 32.239 -0.559 31.78 -0.559 c
+31.316 -0.559 30.946 -0.397 30.662 -0.073 c
+30.387 0.258 30.244 0.698 30.236 1.249 c
+h
+30.883 1.309 m
+30.883 0.904 30.961 0.588 31.118 0.353 c
+31.283 0.118 31.504 0 31.78 0 c
+32.345 0 32.64 0.412 32.662 1.235 c
+32.662 1.691 l
+32.662 2.091 32.577 2.411 32.412 2.646 c
+32.254 2.889 32.037 3.013 31.765 3.013 c
+31.501 3.013 31.283 2.889 31.118 2.646 c
+30.961 2.411 30.883 2.091 30.883 1.691 c
+h
+f
+Q
+q 1 0 0 1 420.882 121.0564 cm
+0 0 m
+0.353 2.234 l
+1.353 2.234 l
+0.53 -1.749 l
+-0.338 -1.749 l
+-0.897 0.559 l
+-1.455 -1.749 l
+-2.323 -1.749 l
+-3.146 2.234 l
+-2.146 2.234 l
+-1.793 0 l
+-1.264 2.234 l
+-0.529 2.234 l
+h
+1.75 0.368 m
+1.75 0.974 1.889 1.448 2.176 1.793 c
+2.458 2.135 2.851 2.308 3.352 2.308 c
+3.859 2.308 4.256 2.135 4.542 1.793 c
+4.825 1.448 4.968 0.974 4.968 0.368 c
+4.968 0.103 l
+4.968 -0.496 4.825 -0.966 4.542 -1.309 c
+4.256 -1.654 3.859 -1.823 3.352 -1.823 c
+2.841 -1.823 2.444 -1.654 2.161 -1.309 c
+1.885 -0.966 1.75 -0.492 1.75 0.118 c
+h
+2.793 0.103 m
+2.793 -0.603 2.977 -0.956 3.352 -0.956 c
+3.705 -0.956 3.896 -0.661 3.925 -0.073 c
+3.925 0.368 l
+3.925 0.727 3.873 0.999 3.778 1.176 c
+3.678 1.352 3.535 1.44 3.352 1.44 c
+3.175 1.44 3.036 1.352 2.94 1.176 c
+2.841 0.999 2.793 0.727 2.793 0.368 c
+h
+7.57 1.22 m
+7.232 1.249 l
+6.945 1.249 6.754 1.124 6.659 0.881 c
+6.659 -1.749 l
+5.615 -1.749 l
+5.615 2.234 l
+6.585 2.234 l
+6.614 1.793 l
+6.78 2.135 7.011 2.308 7.306 2.308 c
+7.423 2.308 7.515 2.286 7.585 2.249 c
+h
+9.437 -0.22 m
+9.157 -0.53 l
+9.157 -1.749 l
+8.114 -1.749 l
+8.114 3.896 l
+9.157 3.896 l
+9.157 0.852 l
+9.276 1.043 l
+9.995 2.234 l
+11.245 2.234 l
+10.084 0.588 l
+11.348 -1.749 l
+10.157 -1.749 l
+h
+12.803 -1.749 -1.044 3.983 re
+11.715 3.263 m
+11.715 3.418 11.763 3.547 11.863 3.645 c
+11.969 3.752 12.104 3.807 12.274 3.807 c
+12.45 3.807 12.586 3.752 12.685 3.645 c
+12.792 3.547 12.847 3.418 12.847 3.263 c
+12.847 3.094 12.792 2.959 12.685 2.851 c
+12.586 2.753 12.45 2.705 12.274 2.705 c
+12.104 2.705 11.969 2.753 11.863 2.851 c
+11.763 2.959 11.715 3.094 11.715 3.263 c
+14.566 2.234 m
+14.596 1.837 l
+14.832 2.15 15.133 2.308 15.507 2.308 c
+16.191 2.308 16.544 1.826 16.566 0.867 c
+16.566 -1.749 l
+15.522 -1.749 l
+15.522 0.794 l
+15.522 1.018 15.486 1.18 15.42 1.278 c
+15.35 1.374 15.232 1.426 15.067 1.426 c
+14.88 1.426 14.732 1.33 14.626 1.147 c
+14.626 -1.749 l
+13.582 -1.749 l
+13.582 2.234 l
+h
+17.184 0.368 m
+17.184 1.014 17.301 1.5 17.536 1.822 c
+17.771 2.146 18.102 2.308 18.535 2.308 c
+18.888 2.308 19.16 2.165 19.359 1.881 c
+19.403 2.234 l
+20.343 2.234 l
+20.343 -1.749 l
+20.343 -2.256 20.2 -2.646 19.917 -2.911 c
+19.63 -3.183 19.227 -3.322 18.697 -3.322 c
+18.47 -3.322 18.234 -3.278 17.992 -3.19 c
+17.756 -3.102 17.581 -2.988 17.463 -2.851 c
+17.816 -2.132 l
+17.911 -2.238 18.04 -2.323 18.198 -2.381 c
+18.352 -2.448 18.499 -2.485 18.639 -2.485 c
+18.874 -2.485 19.039 -2.425 19.138 -2.308 c
+19.245 -2.198 19.3 -2.021 19.3 -1.779 c
+19.3 -1.426 l
+19.102 -1.691 18.844 -1.823 18.521 -1.823 c
+18.098 -1.823 17.771 -1.661 17.536 -1.338 c
+17.309 -1.007 17.191 -0.536 17.184 0.073 c
+h
+18.227 0.103 m
+18.227 -0.272 18.275 -0.54 18.374 -0.706 c
+18.47 -0.875 18.624 -0.956 18.83 -0.956 c
+19.042 -0.956 19.2 -0.879 19.3 -0.721 c
+19.3 1.176 l
+19.19 1.341 19.035 1.426 18.83 1.426 c
+18.624 1.426 18.47 1.341 18.374 1.176 c
+18.275 1.007 18.227 0.738 18.227 0.368 c
+h
+22.695 0.368 m
+22.695 1.014 22.802 1.5 23.019 1.822 c
+23.243 2.146 23.566 2.308 23.989 2.308 c
+24.301 2.308 24.555 2.175 24.754 1.911 c
+24.754 3.896 l
+25.812 3.896 l
+25.812 -1.749 l
+24.856 -1.749 l
+24.812 -1.338 l
+24.596 -1.661 24.32 -1.823 23.989 -1.823 c
+23.578 -1.823 23.258 -1.668 23.033 -1.353 c
+22.817 -1.029 22.703 -0.559 22.695 0.058 c
+h
+23.739 0.103 m
+23.739 -0.291 23.776 -0.566 23.857 -0.721 c
+23.945 -0.879 24.092 -0.956 24.297 -0.956 c
+24.503 -0.956 24.654 -0.864 24.754 -0.676 c
+24.754 1.132 l
+24.654 1.326 24.503 1.426 24.297 1.426 c
+24.099 1.426 23.96 1.345 23.871 1.191 c
+23.783 1.043 23.739 0.771 23.739 0.382 c
+h
+27.663 -1.749 -1.043 3.983 re
+26.576 3.263 m
+26.576 3.418 26.624 3.547 26.723 3.645 c
+26.83 3.752 26.965 3.807 27.135 3.807 c
+27.311 3.807 27.447 3.752 27.546 3.645 c
+27.653 3.547 27.708 3.418 27.708 3.263 c
+27.708 3.094 27.653 2.959 27.546 2.851 c
+27.447 2.753 27.311 2.705 27.135 2.705 c
+26.965 2.705 26.83 2.753 26.723 2.851 c
+26.624 2.959 26.576 3.094 26.576 3.263 c
+30.427 1.22 m
+30.089 1.249 l
+29.803 1.249 29.612 1.124 29.516 0.881 c
+29.516 -1.749 l
+28.472 -1.749 l
+28.472 2.234 l
+29.442 2.234 l
+29.471 1.793 l
+29.637 2.135 29.868 2.308 30.163 2.308 c
+30.28 2.308 30.372 2.286 30.442 2.249 c
+h
+32.5 -1.823 m
+31.97 -1.823 31.551 -1.668 31.25 -1.353 c
+30.956 -1.029 30.809 -0.569 30.809 0.029 c
+30.809 0.338 l
+30.809 0.962 30.946 1.448 31.221 1.793 c
+31.493 2.135 31.886 2.308 32.397 2.308 c
+32.897 2.308 33.267 2.146 33.514 1.822 c
+33.768 1.5 33.9 1.022 33.911 0.397 c
+33.911 -0.103 l
+31.838 -0.103 l
+31.856 -0.397 31.919 -0.613 32.029 -0.75 c
+32.147 -0.889 32.327 -0.956 32.573 -0.956 c
+32.915 -0.956 33.205 -0.838 33.44 -0.603 c
+33.852 -1.235 l
+33.724 -1.411 33.536 -1.554 33.294 -1.661 c
+33.047 -1.768 32.783 -1.823 32.5 -1.823 c
+31.853 0.617 m
+32.882 0.617 l
+32.882 0.721 l
+32.882 0.956 32.841 1.132 32.764 1.249 c
+32.694 1.374 32.566 1.44 32.382 1.44 c
+32.205 1.44 32.074 1.371 31.985 1.234 c
+31.904 1.106 31.86 0.9 31.853 0.617 c
+35.939 -0.956 m
+36.233 -0.956 36.384 -0.761 36.395 -0.368 c
+37.365 -0.368 l
+37.365 -0.802 37.233 -1.154 36.968 -1.426 c
+36.704 -1.691 36.365 -1.823 35.954 -1.823 c
+35.443 -1.823 35.05 -1.668 34.778 -1.353 c
+34.514 -1.029 34.374 -0.559 34.366 0.058 c
+34.366 0.382 l
+34.366 1.007 34.499 1.484 34.763 1.808 c
+35.035 2.138 35.432 2.308 35.954 2.308 c
+36.384 2.308 36.726 2.168 36.983 1.897 c
+37.236 1.621 37.365 1.238 37.365 0.75 c
+36.395 0.75 l
+36.395 0.962 36.355 1.132 36.278 1.249 c
+36.207 1.374 36.09 1.44 35.925 1.44 c
+35.748 1.44 35.619 1.374 35.542 1.249 c
+35.461 1.12 35.418 0.871 35.41 0.5 c
+35.41 0.088 l
+35.41 -0.235 35.424 -0.463 35.455 -0.588 c
+35.491 -0.717 35.546 -0.808 35.616 -0.867 c
+35.694 -0.926 35.8 -0.956 35.939 -0.956 c
+39.173 3.204 m
+39.173 2.234 l
+39.702 2.234 l
+39.702 1.44 l
+39.173 1.44 l
+39.173 -0.53 l
+39.173 -0.687 39.191 -0.794 39.232 -0.852 c
+39.28 -0.912 39.364 -0.941 39.482 -0.941 c
+39.588 -0.941 39.673 -0.933 39.731 -0.912 c
+39.731 -1.72 l
+39.555 -1.786 39.364 -1.823 39.158 -1.823 c
+38.482 -1.823 38.137 -1.437 38.129 -0.661 c
+38.129 1.44 l
+37.674 1.44 l
+37.674 2.234 l
+38.129 2.234 l
+38.129 3.204 l
+h
+40.055 0.368 m
+40.055 0.974 40.195 1.448 40.481 1.793 c
+40.764 2.135 41.157 2.308 41.657 2.308 c
+42.164 2.308 42.561 2.135 42.848 1.793 c
+43.131 1.448 43.274 0.974 43.274 0.368 c
+43.274 0.103 l
+43.274 -0.496 43.131 -0.966 42.848 -1.309 c
+42.561 -1.654 42.164 -1.823 41.657 -1.823 c
+41.146 -1.823 40.75 -1.654 40.467 -1.309 c
+40.191 -0.966 40.055 -0.492 40.055 0.118 c
+h
+41.099 0.103 m
+41.099 -0.603 41.282 -0.956 41.657 -0.956 c
+42.01 -0.956 42.202 -0.661 42.231 -0.073 c
+42.231 0.368 l
+42.231 0.727 42.179 0.999 42.083 1.176 c
+41.984 1.352 41.841 1.44 41.657 1.44 c
+41.481 1.44 41.341 1.352 41.246 1.176 c
+41.146 0.999 41.099 0.727 41.099 0.368 c
+h
+45.876 1.22 m
+45.537 1.249 l
+45.251 1.249 45.06 1.124 44.965 0.881 c
+44.965 -1.749 l
+43.921 -1.749 l
+43.921 2.234 l
+44.891 2.234 l
+44.92 1.793 l
+45.086 2.135 45.317 2.308 45.611 2.308 c
+45.729 2.308 45.821 2.286 45.89 2.249 c
+h
+47.772 -0.015 m
+48.301 2.234 l
+49.404 2.234 l
+48.095 -2.352 l
+47.897 -3.017 47.53 -3.352 46.993 -3.352 c
+46.865 -3.352 46.721 -3.329 46.567 -3.293 c
+46.567 -2.469 l
+46.684 -2.485 l
+46.85 -2.485 46.971 -2.448 47.052 -2.381 c
+47.129 -2.323 47.191 -2.213 47.243 -2.058 c
+47.316 -1.793 l
+46.17 2.234 l
+47.287 2.234 l
+h
+f
+Q
+q 1 0 0 1 470.8588 118.2342 cm
+0 0 m
+-0.397 0.264 l
+-0.162 0.588 -0.04 0.922 -0.029 1.264 c
+-0.029 1.881 l
+0.632 1.881 l
+0.632 1.352 l
+0.632 1.095 0.566 0.849 0.441 0.603 c
+0.324 0.36 0.177 0.158 0 0 c
+5.233 1.073 m
+5.193 1.161 5.167 1.309 5.16 1.514 c
+4.925 1.168 4.63 0.999 4.278 0.999 c
+3.913 0.999 3.63 1.095 3.425 1.294 c
+3.227 1.5 3.131 1.786 3.131 2.161 c
+3.131 2.562 3.267 2.881 3.543 3.116 c
+3.815 3.358 4.189 3.484 4.659 3.484 c
+5.145 3.484 l
+5.145 3.91 l
+5.145 4.145 5.089 4.31 4.983 4.409 c
+4.873 4.516 4.711 4.571 4.498 4.571 c
+4.299 4.571 4.138 4.513 4.013 4.395 c
+3.896 4.278 3.836 4.131 3.836 3.954 c
+3.19 3.954 l
+3.19 4.149 3.248 4.34 3.366 4.527 c
+3.491 4.711 3.653 4.858 3.851 4.968 c
+4.057 5.075 4.285 5.13 4.542 5.13 c
+4.943 5.13 5.247 5.027 5.453 4.821 c
+5.667 4.615 5.781 4.322 5.791 3.939 c
+5.791 1.926 l
+5.791 1.621 5.828 1.356 5.909 1.132 c
+5.909 1.073 l
+h
+4.366 1.587 m
+4.532 1.587 4.682 1.631 4.821 1.72 c
+4.968 1.808 5.075 1.918 5.145 2.057 c
+5.145 2.998 l
+4.777 2.998 l
+4.461 2.998 4.219 2.929 4.042 2.793 c
+3.866 2.664 3.778 2.477 3.778 2.234 c
+3.778 2.007 3.822 1.841 3.91 1.735 c
+3.998 1.635 4.149 1.587 4.366 1.587 c
+7.408 5.056 m
+7.423 4.615 l
+7.676 4.958 8 5.13 8.393 5.13 c
+9.099 5.13 9.455 4.659 9.467 3.719 c
+9.467 1.073 l
+8.819 1.073 l
+8.819 3.69 l
+8.819 4.002 8.765 4.222 8.658 4.351 c
+8.548 4.476 8.393 4.542 8.187 4.542 c
+8.029 4.542 7.882 4.487 7.747 4.38 c
+7.618 4.27 7.515 4.135 7.437 3.969 c
+7.437 1.073 l
+6.791 1.073 l
+6.791 5.056 l
+h
+10.304 3.248 m
+10.304 3.855 10.414 4.322 10.643 4.644 c
+10.878 4.968 11.204 5.13 11.627 5.13 c
+12.009 5.13 12.307 4.972 12.524 4.659 c
+12.524 6.718 l
+13.17 6.718 l
+13.17 1.073 l
+12.582 1.073 l
+12.538 1.5 l
+12.332 1.165 12.027 0.999 11.627 0.999 c
+11.215 0.999 10.892 1.154 10.657 1.469 c
+10.422 1.793 10.304 2.249 10.304 2.837 c
+h
+10.951 2.866 m
+10.951 2.425 11.013 2.095 11.142 1.881 c
+11.278 1.675 11.499 1.573 11.803 1.573 c
+12.127 1.573 12.366 1.735 12.524 2.057 c
+12.524 4.072 l
+12.355 4.384 12.116 4.542 11.803 4.542 c
+11.499 4.542 11.278 4.439 11.142 4.233 c
+11.013 4.027 10.951 3.704 10.951 3.263 c
+h
+17.271 1.558 m
+17.485 1.558 17.658 1.621 17.786 1.749 c
+17.922 1.885 17.995 2.076 18.007 2.323 c
+18.624 2.323 l
+18.602 1.94 18.466 1.621 18.212 1.367 c
+17.955 1.12 17.643 0.999 17.271 0.999 c
+16.779 0.999 16.405 1.151 16.139 1.455 c
+15.882 1.768 15.757 2.234 15.757 2.851 c
+15.757 3.293 l
+15.757 3.888 15.882 4.343 16.139 4.659 c
+16.405 4.972 16.779 5.13 17.271 5.13 c
+17.672 5.13 17.992 4.997 18.227 4.733 c
+18.47 4.476 18.602 4.131 18.624 3.69 c
+18.007 3.69 l
+17.984 3.983 17.911 4.204 17.786 4.351 c
+17.668 4.498 17.496 4.571 17.271 4.571 c
+16.978 4.571 16.761 4.472 16.625 4.278 c
+16.486 4.09 16.411 3.782 16.405 3.351 c
+16.405 2.837 l
+16.405 2.367 16.47 2.032 16.61 1.837 c
+16.757 1.65 16.978 1.558 17.271 1.558 c
+20.079 1.073 -0.647 5.644 re
+22.519 0.999 m
+22.019 0.999 21.637 1.147 21.373 1.44 c
+21.108 1.735 20.976 2.168 20.976 2.749 c
+20.976 3.219 l
+20.976 3.815 21.101 4.281 21.358 4.615 c
+21.623 4.958 21.982 5.13 22.445 5.13 c
+22.905 5.13 23.247 4.976 23.474 4.675 c
+23.709 4.38 23.831 3.917 23.842 3.293 c
+23.842 2.866 l
+21.623 2.866 l
+21.623 2.778 l
+21.623 2.344 21.7 2.032 21.858 1.837 c
+22.023 1.65 22.254 1.558 22.549 1.558 c
+22.743 1.558 22.915 1.591 23.063 1.661 c
+23.21 1.738 23.346 1.856 23.474 2.014 c
+23.813 1.602 l
+23.526 1.198 23.096 0.999 22.519 0.999 c
+22.445 4.571 m
+22.17 4.571 21.968 4.476 21.843 4.292 c
+21.714 4.104 21.641 3.815 21.623 3.425 c
+23.195 3.425 l
+23.195 3.513 l
+23.173 3.896 23.107 4.164 22.99 4.322 c
+22.872 4.487 22.688 4.571 22.445 4.571 c
+26.664 1.073 m
+26.624 1.161 26.598 1.309 26.591 1.514 c
+26.356 1.168 26.061 0.999 25.709 0.999 c
+25.345 0.999 25.062 1.095 24.856 1.294 c
+24.658 1.5 24.562 1.786 24.562 2.161 c
+24.562 2.562 24.698 2.881 24.974 3.116 c
+25.246 3.358 25.621 3.484 26.091 3.484 c
+26.576 3.484 l
+26.576 3.91 l
+26.576 4.145 26.521 4.31 26.414 4.409 c
+26.304 4.516 26.142 4.571 25.93 4.571 c
+25.731 4.571 25.569 4.513 25.444 4.395 c
+25.327 4.278 25.267 4.131 25.267 3.954 c
+24.621 3.954 l
+24.621 4.149 24.68 4.34 24.797 4.527 c
+24.922 4.711 25.084 4.858 25.282 4.968 c
+25.488 5.075 25.716 5.13 25.973 5.13 c
+26.374 5.13 26.678 5.027 26.884 4.821 c
+27.098 4.615 27.212 4.322 27.223 3.939 c
+27.223 1.926 l
+27.223 1.621 27.26 1.356 27.341 1.132 c
+27.341 1.073 l
+h
+25.797 1.587 m
+25.963 1.587 26.113 1.631 26.252 1.72 c
+26.4 1.808 26.506 1.918 26.576 2.057 c
+26.576 2.998 l
+26.208 2.998 l
+25.893 2.998 25.65 2.929 25.473 2.793 c
+25.297 2.664 25.209 2.477 25.209 2.234 c
+25.209 2.007 25.253 1.841 25.342 1.735 c
+25.429 1.635 25.581 1.587 25.797 1.587 c
+29.868 4.439 m
+29.78 4.457 29.681 4.469 29.575 4.469 c
+29.24 4.469 29.005 4.285 28.869 3.925 c
+28.869 1.073 l
+28.222 1.073 l
+28.222 5.056 l
+28.854 5.056 l
+28.869 4.644 l
+29.045 4.968 29.288 5.13 29.604 5.13 c
+29.71 5.13 29.799 5.108 29.868 5.072 c
+h
+f
+Q
+q 1 0 0 1 504.7546 120.38 cm
+0 0 m
+0 0.088 -0.043 0.166 -0.132 0.235 c
+-0.22 0.312 -0.407 0.416 -0.691 0.544 c
+-1.124 0.721 -1.421 0.9 -1.587 1.087 c
+-1.745 1.272 -1.822 1.503 -1.822 1.779 c
+-1.822 2.12 -1.701 2.404 -1.454 2.631 c
+-1.201 2.866 -0.864 2.984 -0.44 2.984 c
+-0.01 2.984 0.339 2.87 0.603 2.646 c
+0.867 2.419 1 2.117 1 1.735 c
+-0.043 1.735 l
+-0.043 2.058 -0.183 2.22 -0.455 2.22 c
+-0.565 2.22 -0.654 2.183 -0.72 2.117 c
+-0.789 2.047 -0.823 1.948 -0.823 1.823 c
+-0.823 1.735 -0.786 1.654 -0.706 1.588 c
+-0.628 1.529 -0.448 1.434 -0.162 1.309 c
+0.269 1.151 0.566 0.974 0.736 0.779 c
+0.912 0.592 1 0.342 1 0.029 c
+1 -0.324 0.867 -0.61 0.603 -0.823 c
+0.339 -1.04 -0.01 -1.147 -0.44 -1.147 c
+-0.735 -1.147 -0.995 -1.091 -1.219 -0.985 c
+-1.448 -0.867 -1.624 -0.706 -1.749 -0.5 c
+-1.866 -0.294 -1.925 -0.073 -1.925 0.162 c
+-0.941 0.162 l
+-0.941 -0.025 -0.904 -0.162 -0.823 -0.249 c
+-0.735 -0.338 -0.602 -0.382 -0.426 -0.382 c
+-0.143 -0.382 0 -0.257 0 0 c
+2.866 3.881 m
+2.866 2.911 l
+3.396 2.911 l
+3.396 2.117 l
+2.866 2.117 l
+2.866 0.147 l
+2.866 -0.01 2.885 -0.118 2.926 -0.176 c
+2.974 -0.235 3.057 -0.264 3.175 -0.264 c
+3.282 -0.264 3.366 -0.257 3.425 -0.235 c
+3.425 -1.043 l
+3.249 -1.109 3.057 -1.147 2.852 -1.147 c
+2.176 -1.147 1.831 -0.76 1.823 0.015 c
+1.823 2.117 l
+1.368 2.117 l
+1.368 2.911 l
+1.823 2.911 l
+1.823 3.881 l
+h
+5.85 -1.072 m
+5.821 -1.014 5.792 -0.912 5.762 -0.764 c
+5.575 -1.022 5.326 -1.147 5.012 -1.147 c
+4.678 -1.147 4.399 -1.04 4.175 -0.823 c
+3.958 -0.598 3.851 -0.309 3.851 0.044 c
+3.851 0.456 3.984 0.772 4.248 1 c
+4.513 1.235 4.896 1.353 5.395 1.353 c
+5.718 1.353 l
+5.718 1.675 l
+5.718 1.852 5.681 1.974 5.615 2.043 c
+5.557 2.12 5.469 2.161 5.351 2.161 c
+5.093 2.161 4.969 2.007 4.969 1.706 c
+3.925 1.706 l
+3.925 2.076 4.061 2.381 4.337 2.616 c
+4.609 2.859 4.958 2.984 5.38 2.984 c
+5.821 2.984 6.159 2.866 6.394 2.631 c
+6.637 2.404 6.762 2.08 6.762 1.661 c
+6.762 -0.206 l
+6.762 -0.551 6.81 -0.819 6.909 -1.014 c
+6.909 -1.072 l
+h
+5.247 -0.324 m
+5.355 -0.324 5.446 -0.305 5.527 -0.264 c
+5.615 -0.216 5.678 -0.158 5.718 -0.088 c
+5.718 0.735 l
+5.469 0.735 l
+5.292 0.735 5.149 0.676 5.042 0.559 c
+4.943 0.449 4.896 0.302 4.896 0.118 c
+4.896 -0.176 5.012 -0.324 5.247 -0.324 c
+9.276 0 m
+9.276 0.088 9.231 0.166 9.143 0.235 c
+9.055 0.312 8.867 0.416 8.584 0.544 c
+8.151 0.721 7.853 0.9 7.688 1.087 c
+7.53 1.272 7.453 1.503 7.453 1.779 c
+7.453 2.12 7.574 2.404 7.82 2.631 c
+8.073 2.866 8.412 2.984 8.834 2.984 c
+9.264 2.984 9.613 2.87 9.878 2.646 c
+10.143 2.419 10.275 2.117 10.275 1.735 c
+9.231 1.735 l
+9.231 2.058 9.091 2.22 8.819 2.22 c
+8.709 2.22 8.621 2.183 8.555 2.117 c
+8.486 2.047 8.453 1.948 8.453 1.823 c
+8.453 1.735 8.489 1.654 8.57 1.588 c
+8.647 1.529 8.827 1.434 9.114 1.309 c
+9.544 1.151 9.841 0.974 10.01 0.779 c
+10.186 0.592 10.275 0.342 10.275 0.029 c
+10.275 -0.324 10.143 -0.61 9.878 -0.823 c
+9.613 -1.04 9.264 -1.147 8.834 -1.147 c
+8.54 -1.147 8.279 -1.091 8.056 -0.985 c
+7.828 -0.867 7.651 -0.706 7.526 -0.5 c
+7.408 -0.294 7.35 -0.073 7.35 0.162 c
+8.335 0.162 l
+8.335 -0.025 8.372 -0.162 8.453 -0.249 c
+8.54 -0.338 8.673 -0.382 8.85 -0.382 c
+9.132 -0.382 9.276 -0.257 9.276 0 c
+11.951 2.558 m
+12.175 2.841 12.451 2.984 12.773 2.984 c
+13.134 2.984 13.409 2.855 13.597 2.602 c
+13.792 2.344 13.891 1.962 13.891 1.455 c
+13.891 -1.072 l
+12.848 -1.072 l
+12.848 1.44 l
+12.848 1.675 12.807 1.841 12.73 1.941 c
+12.66 2.047 12.546 2.103 12.391 2.103 c
+12.204 2.103 12.057 2.018 11.951 1.852 c
+11.951 -1.072 l
+10.907 -1.072 l
+10.907 4.572 l
+11.951 4.572 l
+h
+f
+Q
+q 1 0 0 1 519.5421 119.6604 cm
+0 0 m
+0 0.118 0.033 0.213 0.103 0.294 c
+0.169 0.371 0.272 0.411 0.412 0.411 c
+0.559 0.411 0.665 0.371 0.735 0.294 c
+0.812 0.213 0.852 0.118 0.852 0 c
+0.852 -0.111 0.812 -0.202 0.735 -0.279 c
+0.665 -0.357 0.559 -0.397 0.412 -0.397 c
+0.272 -0.397 0.169 -0.357 0.103 -0.279 c
+0.033 -0.202 0 -0.111 0 0 c
+f
+Q
+0.113 0.082 0.09 0 k
+287.665 113.704 234.667 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 106.8644 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.69 -1.999 0.69 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.278 -3.219 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.119 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.119 -1.128 3.09 -0.97 3.042 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.319 2.385 -2.366 2.337 c
+-2.406 2.296 -2.436 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.66 m
+6.184 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.856 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.86 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.073 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.411 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.631 5.137 1.779 c
+5.244 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.179 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.866 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.151 2.219 c
+8.004 2.219 l
+7.993 2.138 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.871 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.675 re
+10.124 2.837 m
+13.597 1.602 m
+13.053 1.602 l
+13.053 2.219 l
+13.641 2.219 l
+13.92 3.117 l
+14.494 3.117 l
+14.494 2.219 l
+15.728 2.219 l
+15.728 1.602 l
+14.494 1.602 l
+14.494 -0.103 l
+14.494 -0.324 l
+14.501 -0.393 14.523 -0.455 14.552 -0.515 c
+14.589 -0.566 14.645 -0.61 14.714 -0.646 c
+14.791 -0.676 14.905 -0.691 15.052 -0.691 c
+15.188 -0.691 15.324 -0.687 15.464 -0.676 c
+15.599 -0.658 15.732 -0.632 15.861 -0.603 c
+15.861 -1.205 l
+15.78 -1.216 15.703 -1.231 15.626 -1.249 c
+15.545 -1.261 15.468 -1.268 15.391 -1.278 c
+15.31 -1.286 15.221 -1.294 15.125 -1.294 c
+15.038 -1.301 14.938 -1.309 14.832 -1.309 c
+14.645 -1.309 14.483 -1.294 14.346 -1.264 c
+14.218 -1.228 14.104 -1.183 14.009 -1.132 c
+13.92 -1.084 13.847 -1.025 13.788 -0.956 c
+13.729 -0.879 13.685 -0.802 13.656 -0.721 c
+13.627 -0.632 13.604 -0.544 13.597 -0.455 c
+13.586 -0.36 13.582 -0.264 13.582 -0.176 c
+h
+24.22 -0.25 m
+24.22 -0.419 24.18 -0.569 24.103 -0.706 c
+24.033 -0.834 23.931 -0.948 23.794 -1.043 c
+23.666 -1.132 23.504 -1.201 23.31 -1.249 c
+23.121 -1.297 22.905 -1.323 22.662 -1.323 c
+22.435 -1.323 22.236 -1.309 22.06 -1.278 c
+21.883 -1.249 21.725 -1.201 21.59 -1.132 c
+21.45 -1.055 21.34 -0.956 21.251 -0.838 c
+21.163 -0.721 21.093 -0.573 21.045 -0.397 c
+21.854 -0.279 l
+21.872 -0.378 21.902 -0.455 21.942 -0.515 c
+21.99 -0.573 22.049 -0.617 22.119 -0.646 c
+22.185 -0.676 22.265 -0.702 22.354 -0.721 c
+22.442 -0.731 22.545 -0.735 22.662 -0.735 c
+22.758 -0.735 22.853 -0.731 22.942 -0.721 c
+23.03 -0.702 23.107 -0.676 23.177 -0.646 c
+23.243 -0.617 23.295 -0.58 23.324 -0.529 c
+23.36 -0.482 23.383 -0.419 23.383 -0.338 c
+23.383 -0.243 23.353 -0.169 23.295 -0.118 c
+23.243 -0.07 23.177 -0.029 23.089 0 c
+23.001 0.037 22.89 0.066 22.766 0.088 c
+22.647 0.118 22.516 0.147 22.369 0.177 c
+22.229 0.214 22.09 0.254 21.942 0.294 c
+21.803 0.341 21.677 0.405 21.56 0.485 c
+21.45 0.563 21.361 0.661 21.296 0.779 c
+21.226 0.897 21.193 1.047 21.193 1.235 c
+21.193 1.389 21.222 1.532 21.28 1.661 c
+21.347 1.797 21.442 1.911 21.56 1.999 c
+21.685 2.087 21.843 2.153 22.03 2.205 c
+22.215 2.253 22.427 2.278 22.662 2.278 c
+22.846 2.278 23.023 2.256 23.192 2.219 c
+23.357 2.19 23.504 2.135 23.632 2.058 c
+23.757 1.988 23.868 1.889 23.956 1.764 c
+24.044 1.646 24.103 1.503 24.133 1.338 c
+23.339 1.264 l
+23.316 1.341 23.287 1.404 23.25 1.455 c
+23.21 1.514 23.162 1.558 23.104 1.588 c
+23.052 1.625 22.99 1.65 22.913 1.661 c
+22.832 1.668 22.751 1.675 22.662 1.675 c
+22.446 1.675 22.284 1.646 22.177 1.588 c
+22.067 1.536 22.016 1.448 22.016 1.323 c
+22.016 1.242 22.034 1.18 22.074 1.132 c
+22.122 1.08 22.185 1.043 22.265 1.014 c
+22.354 0.985 22.45 0.956 22.56 0.926 c
+22.666 0.904 22.788 0.882 22.927 0.852 c
+23.081 0.823 23.239 0.783 23.397 0.735 c
+23.551 0.684 23.692 0.621 23.809 0.544 c
+23.927 0.463 24.022 0.36 24.103 0.235 c
+24.18 0.106 24.22 -0.056 24.22 -0.25 c
+25.783 1.602 m
+25.238 1.602 l
+25.238 2.219 l
+25.826 2.219 l
+26.106 3.117 l
+26.679 3.117 l
+26.679 2.219 l
+27.914 2.219 l
+27.914 1.602 l
+26.679 1.602 l
+26.679 -0.103 l
+26.679 -0.324 l
+26.686 -0.393 26.709 -0.455 26.738 -0.515 c
+26.774 -0.566 26.83 -0.61 26.9 -0.646 c
+26.977 -0.676 27.09 -0.691 27.237 -0.691 c
+27.374 -0.691 27.509 -0.687 27.649 -0.676 c
+27.785 -0.658 27.917 -0.632 28.046 -0.603 c
+28.046 -1.205 l
+27.965 -1.216 27.888 -1.231 27.811 -1.249 c
+27.73 -1.261 27.653 -1.268 27.576 -1.278 c
+27.495 -1.286 27.407 -1.294 27.312 -1.294 c
+27.223 -1.301 27.123 -1.309 27.017 -1.309 c
+26.83 -1.309 26.668 -1.294 26.532 -1.264 c
+26.404 -1.228 26.29 -1.183 26.194 -1.132 c
+26.106 -1.084 26.032 -1.025 25.974 -0.956 c
+25.915 -0.879 25.87 -0.802 25.841 -0.721 c
+25.812 -0.632 25.789 -0.544 25.783 -0.455 c
+25.772 -0.36 25.768 -0.264 25.768 -0.176 c
+h
+30.196 -1.323 m
+30.027 -1.323 29.876 -1.301 29.741 -1.264 c
+29.612 -1.216 29.498 -1.147 29.402 -1.058 c
+29.313 -0.97 29.244 -0.864 29.196 -0.735 c
+29.145 -0.599 29.122 -0.449 29.122 -0.279 c
+29.122 -0.073 29.155 0.096 29.226 0.235 c
+29.292 0.382 29.388 0.492 29.505 0.573 c
+29.63 0.661 29.773 0.724 29.931 0.765 c
+30.096 0.802 30.273 0.827 30.46 0.838 c
+31.181 0.852 l
+31.181 1.029 l
+31.181 1.147 31.17 1.249 31.152 1.338 c
+31.129 1.426 31.096 1.492 31.048 1.544 c
+31.008 1.602 30.96 1.639 30.901 1.661 c
+30.842 1.679 30.776 1.691 30.71 1.691 c
+30.641 1.691 30.578 1.679 30.519 1.661 c
+30.468 1.65 30.42 1.625 30.372 1.588 c
+30.331 1.558 30.298 1.507 30.269 1.44 c
+30.248 1.382 30.233 1.301 30.225 1.205 c
+29.284 1.249 l
+29.313 1.396 29.358 1.532 29.417 1.661 c
+29.483 1.786 29.579 1.897 29.696 1.984 c
+29.814 2.08 29.953 2.153 30.122 2.205 c
+30.298 2.253 30.504 2.278 30.74 2.278 c
+31.181 2.278 31.511 2.168 31.74 1.955 c
+31.975 1.749 32.092 1.44 32.092 1.029 c
+32.092 -0.235 l
+32.092 -0.455 l
+32.099 -0.515 32.114 -0.569 32.136 -0.617 c
+32.154 -0.658 32.184 -0.691 32.224 -0.721 c
+32.261 -0.742 32.313 -0.75 32.371 -0.75 c
+32.438 -0.75 32.507 -0.746 32.577 -0.735 c
+32.577 -1.22 l
+32.519 -1.231 32.463 -1.242 32.415 -1.249 c
+32.375 -1.261 32.334 -1.268 32.297 -1.278 c
+32.257 -1.286 32.213 -1.294 32.166 -1.294 c
+32.114 -1.301 32.055 -1.309 31.989 -1.309 c
+31.761 -1.309 31.596 -1.257 31.489 -1.147 c
+31.379 -1.029 31.316 -0.864 31.298 -0.646 c
+31.283 -0.646 l
+31.214 -0.757 31.144 -0.852 31.077 -0.941 c
+31.008 -1.022 30.931 -1.087 30.842 -1.147 c
+30.755 -1.205 30.655 -1.249 30.549 -1.278 c
+30.449 -1.309 30.331 -1.323 30.196 -1.323 c
+31.181 0.353 m
+30.755 0.338 l
+30.655 0.338 30.564 0.331 30.475 0.324 c
+30.394 0.312 30.328 0.287 30.269 0.25 c
+30.211 0.21 30.159 0.151 30.122 0.073 c
+30.082 0.004 30.063 -0.088 30.063 -0.206 c
+30.063 -0.374 30.096 -0.496 30.167 -0.573 c
+30.233 -0.654 30.331 -0.691 30.46 -0.691 c
+30.567 -0.691 30.666 -0.669 30.755 -0.617 c
+30.85 -0.569 30.931 -0.507 30.99 -0.426 c
+31.056 -0.349 31.107 -0.261 31.137 -0.162 c
+31.166 -0.056 31.181 0.059 31.181 0.177 c
+h
+33.903 1.602 m
+33.36 1.602 l
+33.36 2.219 l
+33.948 2.219 l
+34.227 3.117 l
+34.8 3.117 l
+34.8 2.219 l
+36.035 2.219 l
+36.035 1.602 l
+34.8 1.602 l
+34.8 -0.103 l
+34.8 -0.324 l
+34.807 -0.393 34.83 -0.455 34.859 -0.515 c
+34.896 -0.566 34.951 -0.61 35.021 -0.646 c
+35.098 -0.676 35.212 -0.691 35.359 -0.691 c
+35.495 -0.691 35.631 -0.687 35.771 -0.676 c
+35.906 -0.658 36.039 -0.632 36.168 -0.603 c
+36.168 -1.205 l
+36.087 -1.216 36.01 -1.231 35.932 -1.249 c
+35.852 -1.261 35.774 -1.268 35.697 -1.278 c
+35.616 -1.286 35.528 -1.294 35.432 -1.294 c
+35.345 -1.301 35.245 -1.309 35.138 -1.309 c
+34.951 -1.309 34.789 -1.294 34.653 -1.264 c
+34.525 -1.228 34.41 -1.183 34.315 -1.132 c
+34.227 -1.084 34.154 -1.025 34.094 -0.956 c
+34.036 -0.879 33.992 -0.802 33.963 -0.721 c
+33.933 -0.632 33.911 -0.544 33.903 -0.455 c
+33.893 -0.36 33.889 -0.264 33.889 -0.176 c
+h
+38.248 2.219 m
+38.248 0.264 l
+38.248 0.125 38.254 0 38.277 -0.118 c
+38.295 -0.228 38.328 -0.32 38.379 -0.397 c
+38.427 -0.478 38.486 -0.54 38.556 -0.588 c
+38.622 -0.628 38.707 -0.646 38.806 -0.646 c
+38.894 -0.646 38.975 -0.628 39.056 -0.588 c
+39.144 -0.54 39.218 -0.47 39.276 -0.382 c
+39.335 -0.287 39.379 -0.176 39.409 -0.058 c
+39.445 0.066 39.467 0.206 39.467 0.353 c
+39.467 2.219 l
+40.364 2.219 l
+40.364 -0.485 l
+40.364 -0.721 l
+40.371 -0.802 40.378 -0.879 40.378 -0.956 c
+40.378 -1.147 l
+40.386 -1.198 40.393 -1.234 40.393 -1.264 c
+39.541 -1.264 l
+39.53 -1.234 39.519 -1.198 39.511 -1.147 c
+39.511 -0.956 l
+39.511 -0.889 39.504 -0.819 39.497 -0.75 c
+39.497 -0.573 l
+39.482 -0.573 l
+39.364 -0.838 39.21 -1.029 39.027 -1.147 c
+38.85 -1.264 38.647 -1.323 38.424 -1.323 c
+38.218 -1.323 38.045 -1.286 37.909 -1.22 c
+37.77 -1.154 37.66 -1.058 37.571 -0.941 c
+37.49 -0.823 37.431 -0.687 37.394 -0.529 c
+37.365 -0.364 37.35 -0.187 37.35 0 c
+37.35 2.219 l
+h
+44.527 -0.25 m
+44.527 -0.419 44.487 -0.569 44.409 -0.706 c
+44.34 -0.834 44.237 -0.948 44.101 -1.043 c
+43.972 -1.132 43.811 -1.201 43.616 -1.249 c
+43.428 -1.297 43.212 -1.323 42.969 -1.323 c
+42.742 -1.323 42.543 -1.309 42.366 -1.278 c
+42.19 -1.249 42.032 -1.201 41.896 -1.132 c
+41.757 -1.055 41.647 -0.956 41.558 -0.838 c
+41.47 -0.721 41.4 -0.573 41.352 -0.397 c
+42.161 -0.279 l
+42.179 -0.378 42.208 -0.455 42.249 -0.515 c
+42.297 -0.573 42.356 -0.617 42.425 -0.646 c
+42.491 -0.676 42.572 -0.702 42.661 -0.721 c
+42.749 -0.731 42.852 -0.735 42.969 -0.735 c
+43.065 -0.735 43.16 -0.731 43.249 -0.721 c
+43.337 -0.702 43.414 -0.676 43.484 -0.646 c
+43.55 -0.617 43.601 -0.58 43.631 -0.529 c
+43.667 -0.482 43.69 -0.419 43.69 -0.338 c
+43.69 -0.243 43.66 -0.169 43.601 -0.118 c
+43.55 -0.07 43.484 -0.029 43.395 0 c
+43.307 0.037 43.197 0.066 43.072 0.088 c
+42.954 0.118 42.822 0.147 42.676 0.177 c
+42.536 0.214 42.396 0.254 42.249 0.294 c
+42.109 0.341 41.984 0.405 41.867 0.485 c
+41.757 0.563 41.668 0.661 41.602 0.779 c
+41.533 0.897 41.5 1.047 41.5 1.235 c
+41.5 1.389 41.529 1.532 41.587 1.661 c
+41.654 1.797 41.749 1.911 41.867 1.999 c
+41.992 2.087 42.15 2.153 42.337 2.205 c
+42.521 2.253 42.734 2.278 42.969 2.278 c
+43.153 2.278 43.33 2.256 43.499 2.219 c
+43.663 2.19 43.811 2.135 43.939 2.058 c
+44.064 1.988 44.174 1.889 44.263 1.764 c
+44.351 1.646 44.409 1.503 44.44 1.338 c
+43.646 1.264 l
+43.623 1.341 43.594 1.404 43.557 1.455 c
+43.517 1.514 43.469 1.558 43.41 1.588 c
+43.359 1.625 43.297 1.65 43.219 1.661 c
+43.139 1.668 43.058 1.675 42.969 1.675 c
+42.753 1.675 42.591 1.646 42.484 1.588 c
+42.374 1.536 42.323 1.448 42.323 1.323 c
+42.323 1.242 42.341 1.18 42.381 1.132 c
+42.429 1.08 42.491 1.043 42.572 1.014 c
+42.661 0.985 42.757 0.956 42.867 0.926 c
+42.973 0.904 43.094 0.882 43.234 0.852 c
+43.388 0.823 43.546 0.783 43.704 0.735 c
+43.858 0.684 43.998 0.621 44.116 0.544 c
+44.234 0.463 44.329 0.36 44.409 0.235 c
+44.487 0.106 44.527 -0.056 44.527 -0.25 c
+f
+Q
+q 1 0 0 1 365.7754 92.4156 cm
+0 0 m
+-0.029 -0.581 -0.191 -1.022 -0.485 -1.324 c
+-0.779 -1.628 -1.198 -1.779 -1.735 -1.779 c
+-2.263 -1.779 -2.69 -1.58 -3.013 -1.176 c
+-3.329 -0.765 -3.484 -0.206 -3.484 0.5 c
+-3.484 1.469 l
+-3.484 2.164 -3.322 2.711 -2.999 3.116 c
+-2.675 3.516 -2.23 3.719 -1.661 3.719 c
+-1.154 3.719 -0.757 3.561 -0.47 3.248 c
+-0.187 2.944 -0.029 2.502 0 1.926 c
+-0.69 1.926 l
+-0.721 2.366 -0.816 2.678 -0.97 2.866 c
+-1.118 3.05 -1.349 3.145 -1.661 3.145 c
+-2.036 3.145 -2.319 2.998 -2.514 2.705 c
+-2.712 2.418 -2.807 2.003 -2.807 1.455 c
+-2.807 0.47 l
+-2.807 -0.071 -2.716 -0.485 -2.529 -0.779 c
+-2.344 -1.066 -2.08 -1.206 -1.735 -1.206 c
+-1.382 -1.206 -1.128 -1.118 -0.97 -0.941 c
+-0.816 -0.765 -0.721 -0.452 -0.69 0 c
+h
+1.514 -1.706 -0.646 5.644 re
+3.954 -1.779 m
+3.454 -1.779 3.072 -1.632 2.807 -1.338 c
+2.543 -1.044 2.41 -0.611 2.41 -0.03 c
+2.41 0.44 l
+2.41 1.036 2.535 1.502 2.793 1.837 c
+3.057 2.179 3.418 2.352 3.881 2.352 c
+4.34 2.352 4.682 2.198 4.91 1.896 c
+5.145 1.602 5.266 1.139 5.277 0.515 c
+5.277 0.087 l
+3.057 0.087 l
+3.057 0 l
+3.057 -0.434 3.135 -0.746 3.293 -0.941 c
+3.458 -1.129 3.69 -1.22 3.983 -1.22 c
+4.178 -1.22 4.351 -1.187 4.498 -1.118 c
+4.645 -1.04 4.781 -0.923 4.91 -0.765 c
+5.247 -1.176 l
+4.961 -1.58 4.531 -1.779 3.954 -1.779 c
+3.881 1.793 m
+3.605 1.793 3.403 1.697 3.278 1.514 c
+3.15 1.326 3.076 1.036 3.057 0.646 c
+4.63 0.646 l
+4.63 0.735 l
+4.608 1.117 4.542 1.385 4.424 1.543 c
+4.307 1.708 4.123 1.793 3.881 1.793 c
+8.099 -1.706 m
+8.058 -1.617 8.033 -1.47 8.025 -1.264 c
+7.79 -1.61 7.497 -1.779 7.144 -1.779 c
+6.78 -1.779 6.497 -1.683 6.292 -1.484 c
+6.093 -1.279 5.997 -0.992 5.997 -0.618 c
+5.997 -0.217 6.134 0.103 6.408 0.338 c
+6.681 0.58 7.056 0.706 7.526 0.706 c
+8.011 0.706 l
+8.011 1.132 l
+8.011 1.367 7.956 1.532 7.85 1.631 c
+7.739 1.738 7.578 1.793 7.364 1.793 c
+7.166 1.793 7.004 1.734 6.879 1.616 c
+6.762 1.499 6.703 1.352 6.703 1.176 c
+6.056 1.176 l
+6.056 1.371 6.115 1.562 6.232 1.749 c
+6.358 1.932 6.519 2.08 6.718 2.19 c
+6.923 2.296 7.152 2.352 7.408 2.352 c
+7.809 2.352 8.114 2.248 8.32 2.043 c
+8.533 1.837 8.646 1.543 8.658 1.161 c
+8.658 -0.853 l
+8.658 -1.158 8.694 -1.422 8.775 -1.646 c
+8.775 -1.706 l
+h
+7.232 -1.191 m
+7.397 -1.191 7.548 -1.147 7.688 -1.058 c
+7.835 -0.971 7.941 -0.86 8.011 -0.721 c
+8.011 0.22 l
+7.644 0.22 l
+7.327 0.22 7.085 0.151 6.909 0.014 c
+6.732 -0.114 6.644 -0.302 6.644 -0.544 c
+6.644 -0.772 6.688 -0.937 6.776 -1.044 c
+6.865 -1.143 7.015 -1.191 7.232 -1.191 c
+11.304 1.66 m
+11.216 1.679 11.116 1.691 11.009 1.691 c
+10.676 1.691 10.44 1.506 10.304 1.146 c
+10.304 -1.706 l
+9.658 -1.706 l
+9.658 2.278 l
+10.29 2.278 l
+10.304 1.866 l
+10.481 2.19 10.723 2.352 11.039 2.352 c
+11.146 2.352 11.233 2.329 11.304 2.293 c
+h
+f
+Q
+q 1 0 0 1 381.1066 91.7834 cm
+0 0 m
+0 0.088 -0.044 0.166 -0.133 0.235 c
+-0.221 0.312 -0.408 0.415 -0.691 0.544 c
+-1.124 0.72 -1.422 0.9 -1.588 1.087 c
+-1.746 1.271 -1.823 1.502 -1.823 1.778 c
+-1.823 2.12 -1.702 2.403 -1.455 2.631 c
+-1.201 2.866 -0.864 2.984 -0.441 2.984 c
+-0.011 2.984 0.338 2.87 0.603 2.645 c
+0.867 2.418 0.999 2.117 0.999 1.735 c
+-0.044 1.735 l
+-0.044 2.057 -0.183 2.219 -0.456 2.219 c
+-0.566 2.219 -0.654 2.183 -0.721 2.117 c
+-0.79 2.047 -0.823 1.947 -0.823 1.822 c
+-0.823 1.735 -0.786 1.654 -0.706 1.587 c
+-0.628 1.529 -0.449 1.433 -0.162 1.308 c
+0.268 1.15 0.565 0.974 0.735 0.779 c
+0.912 0.592 0.999 0.341 0.999 0.029 c
+0.999 -0.324 0.867 -0.611 0.603 -0.823 c
+0.338 -1.04 -0.011 -1.147 -0.441 -1.147 c
+-0.735 -1.147 -0.996 -1.091 -1.22 -0.985 c
+-1.448 -0.867 -1.625 -0.706 -1.749 -0.5 c
+-1.867 -0.294 -1.926 -0.073 -1.926 0.162 c
+-0.941 0.162 l
+-0.941 -0.026 -0.904 -0.162 -0.823 -0.25 c
+-0.735 -0.339 -0.603 -0.382 -0.426 -0.382 c
+-0.143 -0.382 0 -0.258 0 0 c
+2.866 3.881 m
+2.866 2.911 l
+3.395 2.911 l
+3.395 2.117 l
+2.866 2.117 l
+2.866 0.147 l
+2.866 -0.011 2.884 -0.118 2.925 -0.177 c
+2.973 -0.235 3.057 -0.264 3.175 -0.264 c
+3.281 -0.264 3.366 -0.258 3.425 -0.235 c
+3.425 -1.044 l
+3.248 -1.11 3.057 -1.147 2.851 -1.147 c
+2.175 -1.147 1.83 -0.761 1.822 0.014 c
+1.822 2.117 l
+1.367 2.117 l
+1.367 2.911 l
+1.822 2.911 l
+1.822 3.881 l
+h
+5.85 -1.073 m
+5.82 -1.014 5.791 -0.912 5.762 -0.765 c
+5.575 -1.022 5.325 -1.147 5.012 -1.147 c
+4.678 -1.147 4.399 -1.04 4.174 -0.823 c
+3.958 -0.599 3.851 -0.309 3.851 0.044 c
+3.851 0.455 3.983 0.771 4.247 0.999 c
+4.513 1.234 4.895 1.352 5.394 1.352 c
+5.718 1.352 l
+5.718 1.675 l
+5.718 1.852 5.681 1.973 5.615 2.043 c
+5.556 2.12 5.468 2.161 5.35 2.161 c
+5.093 2.161 4.968 2.007 4.968 1.705 c
+3.925 1.705 l
+3.925 2.076 4.06 2.381 4.336 2.616 c
+4.608 2.859 4.957 2.984 5.38 2.984 c
+5.82 2.984 6.159 2.866 6.394 2.631 c
+6.637 2.403 6.761 2.08 6.761 1.66 c
+6.761 -0.206 l
+6.761 -0.551 6.809 -0.819 6.909 -1.014 c
+6.909 -1.073 l
+h
+5.247 -0.324 m
+5.354 -0.324 5.446 -0.305 5.527 -0.264 c
+5.615 -0.217 5.677 -0.158 5.718 -0.088 c
+5.718 0.735 l
+5.468 0.735 l
+5.292 0.735 5.149 0.676 5.041 0.559 c
+4.943 0.448 4.895 0.301 4.895 0.118 c
+4.895 -0.177 5.012 -0.324 5.247 -0.324 c
+9.275 0 m
+9.275 0.088 9.231 0.166 9.143 0.235 c
+9.055 0.312 8.867 0.415 8.584 0.544 c
+8.151 0.72 7.853 0.9 7.688 1.087 c
+7.53 1.271 7.453 1.502 7.453 1.778 c
+7.453 2.12 7.574 2.403 7.819 2.631 c
+8.073 2.866 8.411 2.984 8.834 2.984 c
+9.264 2.984 9.613 2.87 9.878 2.645 c
+10.142 2.418 10.275 2.117 10.275 1.735 c
+9.231 1.735 l
+9.231 2.057 9.091 2.219 8.819 2.219 c
+8.709 2.219 8.621 2.183 8.555 2.117 c
+8.485 2.047 8.452 1.947 8.452 1.822 c
+8.452 1.735 8.488 1.654 8.569 1.587 c
+8.646 1.529 8.827 1.433 9.113 1.308 c
+9.543 1.15 9.841 0.974 10.01 0.779 c
+10.186 0.592 10.275 0.341 10.275 0.029 c
+10.275 -0.324 10.142 -0.611 9.878 -0.823 c
+9.613 -1.04 9.264 -1.147 8.834 -1.147 c
+8.54 -1.147 8.279 -1.091 8.055 -0.985 c
+7.827 -0.867 7.651 -0.706 7.526 -0.5 c
+7.408 -0.294 7.349 -0.073 7.349 0.162 c
+8.334 0.162 l
+8.334 -0.026 8.371 -0.162 8.452 -0.25 c
+8.54 -0.339 8.673 -0.382 8.849 -0.382 c
+9.132 -0.382 9.275 -0.258 9.275 0 c
+11.95 2.558 m
+12.174 2.84 12.45 2.984 12.773 2.984 c
+13.134 2.984 13.409 2.855 13.597 2.601 c
+13.791 2.344 13.89 1.962 13.89 1.455 c
+13.89 -1.073 l
+12.847 -1.073 l
+12.847 1.44 l
+12.847 1.675 12.806 1.841 12.729 1.94 c
+12.66 2.047 12.546 2.102 12.391 2.102 c
+12.204 2.102 12.057 2.017 11.95 1.852 c
+11.95 -1.073 l
+10.907 -1.073 l
+10.907 4.571 l
+11.95 4.571 l
+h
+f
+Q
+q 1 0 0 1 400.5385 91.8568 cm
+0 0 m
+0.603 2.837 l
+1.249 2.837 l
+0.264 -1.147 l
+-0.249 -1.147 l
+-1.029 1.705 l
+-1.779 -1.147 l
+-2.308 -1.147 l
+-3.263 2.837 l
+-2.631 2.837 l
+-2.014 0.073 l
+-1.278 2.837 l
+-0.764 2.837 l
+h
+2.631 -1.147 -0.647 3.984 re
+2.675 3.881 m
+2.675 3.77 2.646 3.678 2.587 3.601 c
+2.529 3.532 2.433 3.499 2.308 3.499 c
+2.19 3.499 2.095 3.532 2.028 3.601 c
+1.97 3.678 1.941 3.77 1.941 3.881 c
+1.941 3.998 1.97 4.09 2.028 4.16 c
+2.095 4.237 2.19 4.278 2.308 4.278 c
+2.433 4.278 2.529 4.237 2.587 4.16 c
+2.646 4.079 2.675 3.987 2.675 3.881 c
+4.498 3.792 m
+4.498 2.837 l
+5.101 2.837 l
+5.101 2.308 l
+4.498 2.308 l
+4.498 -0.162 l
+4.498 -0.32 4.52 -0.437 4.571 -0.515 c
+4.63 -0.595 4.719 -0.632 4.836 -0.632 c
+4.925 -0.632 5.012 -0.617 5.101 -0.588 c
+5.101 -1.147 l
+4.954 -1.195 4.8 -1.22 4.645 -1.22 c
+4.388 -1.22 4.193 -1.128 4.057 -0.941 c
+3.917 -0.757 3.851 -0.496 3.851 -0.162 c
+3.851 2.308 l
+3.248 2.308 l
+3.248 2.837 l
+3.851 2.837 l
+3.851 3.792 l
+h
+6.512 2.425 m
+6.766 2.749 7.085 2.911 7.468 2.911 c
+8.173 2.911 8.53 2.44 8.54 1.5 c
+8.54 -1.147 l
+7.894 -1.147 l
+7.894 1.469 l
+7.894 1.782 7.838 2.003 7.732 2.132 c
+7.622 2.256 7.468 2.323 7.262 2.323 c
+7.104 2.323 6.957 2.267 6.82 2.161 c
+6.691 2.051 6.589 1.914 6.512 1.749 c
+6.512 -1.147 l
+5.866 -1.147 l
+5.866 4.498 l
+6.512 4.498 l
+h
+9.363 1.029 m
+9.363 1.606 9.5 2.061 9.775 2.396 c
+10.058 2.738 10.429 2.911 10.892 2.911 c
+11.352 2.911 11.719 2.741 11.994 2.41 c
+12.278 2.087 12.424 1.639 12.436 1.073 c
+12.436 0.646 l
+12.436 0.077 12.293 -0.378 12.009 -0.721 c
+11.734 -1.055 11.366 -1.22 10.907 -1.22 c
+10.444 -1.22 10.073 -1.058 9.789 -0.735 c
+9.514 -0.405 9.371 0.037 9.363 0.588 c
+h
+10.01 0.646 m
+10.01 0.243 10.088 -0.073 10.246 -0.309 c
+10.411 -0.544 10.631 -0.661 10.907 -0.661 c
+11.472 -0.661 11.767 -0.25 11.788 0.573 c
+11.788 1.029 l
+11.788 1.429 11.705 1.749 11.539 1.984 c
+11.381 2.227 11.164 2.352 10.892 2.352 c
+10.628 2.352 10.411 2.227 10.246 1.984 c
+10.088 1.749 10.01 1.429 10.01 1.029 c
+h
+15.302 -0.794 m
+15.085 -1.081 14.772 -1.22 14.361 -1.22 c
+13.997 -1.22 13.722 -1.099 13.538 -0.852 c
+13.361 -0.599 13.266 -0.235 13.259 0.235 c
+13.259 2.837 l
+13.905 2.837 l
+13.905 0.294 l
+13.905 -0.335 14.089 -0.647 14.464 -0.647 c
+14.865 -0.647 15.14 -0.47 15.287 -0.118 c
+15.287 2.837 l
+15.934 2.837 l
+15.934 -1.147 l
+15.316 -1.147 l
+h
+17.772 3.792 m
+17.772 2.837 l
+18.374 2.837 l
+18.374 2.308 l
+17.772 2.308 l
+17.772 -0.162 l
+17.772 -0.32 17.793 -0.437 17.845 -0.515 c
+17.903 -0.595 17.992 -0.632 18.109 -0.632 c
+18.198 -0.632 18.286 -0.617 18.374 -0.588 c
+18.374 -1.147 l
+18.227 -1.195 18.073 -1.22 17.918 -1.22 c
+17.661 -1.22 17.467 -1.128 17.33 -0.941 c
+17.191 -0.757 17.124 -0.496 17.124 -0.162 c
+17.124 2.308 l
+16.522 2.308 l
+16.522 2.837 l
+17.124 2.837 l
+17.124 3.792 l
+h
+22.901 -1.147 m
+22.861 -1.058 22.836 -0.912 22.828 -0.706 c
+22.593 -1.051 22.298 -1.22 21.946 -1.22 c
+21.582 -1.22 21.299 -1.124 21.093 -0.926 c
+20.895 -0.721 20.799 -0.434 20.799 -0.059 c
+20.799 0.341 20.935 0.661 21.211 0.897 c
+21.483 1.139 21.858 1.264 22.328 1.264 c
+22.813 1.264 l
+22.813 1.691 l
+22.813 1.926 22.758 2.091 22.651 2.19 c
+22.541 2.296 22.379 2.352 22.167 2.352 c
+21.968 2.352 21.806 2.293 21.681 2.175 c
+21.564 2.057 21.504 1.911 21.504 1.735 c
+20.858 1.735 l
+20.858 1.929 20.917 2.12 21.034 2.308 c
+21.159 2.491 21.321 2.639 21.519 2.749 c
+21.725 2.855 21.953 2.911 22.21 2.911 c
+22.611 2.911 22.915 2.807 23.121 2.602 c
+23.335 2.396 23.449 2.102 23.46 1.72 c
+23.46 -0.294 l
+23.46 -0.599 23.497 -0.864 23.578 -1.087 c
+23.578 -1.147 l
+h
+22.034 -0.632 m
+22.2 -0.632 22.35 -0.588 22.489 -0.5 c
+22.637 -0.412 22.743 -0.301 22.813 -0.162 c
+22.813 0.779 l
+22.445 0.779 l
+22.13 0.779 21.887 0.709 21.71 0.573 c
+21.534 0.445 21.446 0.257 21.446 0.015 c
+21.446 -0.214 21.49 -0.378 21.579 -0.485 c
+21.666 -0.584 21.818 -0.632 22.034 -0.632 c
+27.341 0.646 m
+27.341 0.018 27.223 -0.452 26.988 -0.765 c
+26.759 -1.07 26.443 -1.22 26.032 -1.22 c
+25.628 -1.22 25.319 -1.07 25.106 -0.765 c
+25.106 -2.675 l
+24.459 -2.675 l
+24.459 2.837 l
+25.047 2.837 l
+25.091 2.396 l
+25.305 2.738 25.613 2.911 26.017 2.911 c
+26.458 2.911 26.786 2.756 27.002 2.454 c
+27.216 2.15 27.329 1.694 27.341 1.087 c
+h
+26.693 1.029 m
+26.693 1.469 26.624 1.793 26.487 1.999 c
+26.348 2.212 26.128 2.323 25.826 2.323 c
+25.51 2.323 25.271 2.168 25.106 1.866 c
+25.106 -0.206 l
+25.271 -0.511 25.51 -0.661 25.826 -0.661 c
+26.121 -0.661 26.333 -0.559 26.473 -0.353 c
+26.609 -0.14 26.682 0.191 26.693 0.632 c
+h
+31.059 0.646 m
+31.059 0.018 30.942 -0.452 30.707 -0.765 c
+30.479 -1.07 30.163 -1.22 29.751 -1.22 c
+29.346 -1.22 29.038 -1.07 28.825 -0.765 c
+28.825 -2.675 l
+28.178 -2.675 l
+28.178 2.837 l
+28.766 2.837 l
+28.81 2.396 l
+29.024 2.738 29.332 2.911 29.736 2.911 c
+30.177 2.911 30.504 2.756 30.721 2.454 c
+30.934 2.15 31.048 1.694 31.059 1.087 c
+h
+30.412 1.029 m
+30.412 1.469 30.343 1.793 30.206 1.999 c
+30.067 2.212 29.847 2.323 29.545 2.323 c
+29.229 2.323 28.991 2.168 28.825 1.866 c
+28.825 -0.206 l
+28.991 -0.511 29.229 -0.661 29.545 -0.661 c
+29.839 -0.661 30.052 -0.559 30.192 -0.353 c
+30.328 -0.14 30.402 0.191 30.412 0.632 c
+h
+32.602 -1.147 -0.646 5.644 re
+34.705 -0.059 m
+35.424 2.837 l
+36.116 2.837 l
+34.822 -1.706 l
+34.723 -2.047 34.58 -2.308 34.396 -2.484 c
+34.219 -2.66 34.017 -2.749 33.793 -2.749 c
+33.705 -2.749 33.591 -2.727 33.456 -2.69 c
+33.456 -2.146 l
+33.602 -2.161 l
+33.786 -2.161 33.932 -2.117 34.043 -2.028 c
+34.15 -1.941 34.238 -1.783 34.308 -1.558 c
+34.425 -1.118 l
+33.264 2.837 l
+33.969 2.837 l
+h
+37.454 -1.147 -0.647 3.984 re
+37.497 3.881 m
+37.497 3.77 37.468 3.678 37.409 3.601 c
+37.35 3.532 37.255 3.499 37.13 3.499 c
+37.012 3.499 36.917 3.532 36.851 3.601 c
+36.791 3.678 36.762 3.77 36.762 3.881 c
+36.762 3.998 36.791 4.09 36.851 4.16 c
+36.917 4.237 37.012 4.278 37.13 4.278 c
+37.255 4.278 37.35 4.237 37.409 4.16 c
+37.468 4.079 37.497 3.987 37.497 3.881 c
+39.085 2.837 m
+39.1 2.396 l
+39.353 2.738 39.677 2.911 40.07 2.911 c
+40.775 2.911 41.132 2.44 41.143 1.5 c
+41.143 -1.147 l
+40.496 -1.147 l
+40.496 1.469 l
+40.496 1.782 40.441 2.003 40.334 2.132 c
+40.224 2.256 40.07 2.323 39.864 2.323 c
+39.706 2.323 39.559 2.267 39.423 2.161 c
+39.295 2.051 39.191 1.914 39.114 1.749 c
+39.114 -1.147 l
+38.468 -1.147 l
+38.468 2.837 l
+h
+41.98 1.029 m
+41.98 1.646 42.091 2.109 42.319 2.425 c
+42.543 2.749 42.877 2.911 43.318 2.911 c
+43.719 2.911 44.024 2.734 44.23 2.381 c
+44.274 2.837 l
+44.862 2.837 l
+44.862 -1.191 l
+44.862 -1.679 44.733 -2.058 44.479 -2.323 c
+44.222 -2.587 43.87 -2.72 43.421 -2.72 c
+43.222 -2.72 43.002 -2.668 42.759 -2.572 c
+42.514 -2.473 42.333 -2.352 42.216 -2.205 c
+42.48 -1.764 l
+42.745 -2.028 43.043 -2.161 43.377 -2.161 c
+43.914 -2.161 44.189 -1.866 44.201 -1.278 c
+44.201 -0.75 l
+43.995 -1.066 43.693 -1.22 43.303 -1.22 c
+42.892 -1.22 42.568 -1.07 42.333 -0.765 c
+42.106 -0.452 41.988 0 41.98 0.588 c
+h
+42.642 0.646 m
+42.642 0.206 42.705 -0.125 42.833 -0.338 c
+42.958 -0.544 43.175 -0.647 43.48 -0.647 c
+43.804 -0.647 44.043 -0.482 44.201 -0.147 c
+44.201 1.837 l
+44.031 2.161 43.792 2.323 43.48 2.323 c
+43.186 2.323 42.969 2.219 42.833 2.014 c
+42.705 1.808 42.642 1.484 42.642 1.043 c
+h
+48.242 -1.147 -0.646 3.984 re
+48.286 3.881 m
+48.286 3.77 48.257 3.678 48.199 3.601 c
+48.14 3.532 48.044 3.499 47.919 3.499 c
+47.802 3.499 47.706 3.532 47.64 3.601 c
+47.581 3.678 47.552 3.77 47.552 3.881 c
+47.552 3.998 47.581 4.09 47.64 4.16 c
+47.706 4.237 47.802 4.278 47.919 4.278 c
+48.044 4.278 48.14 4.237 48.199 4.16 c
+48.257 4.079 48.286 3.987 48.286 3.881 c
+50.109 3.792 m
+50.109 2.837 l
+50.712 2.837 l
+50.712 2.308 l
+50.109 2.308 l
+50.109 -0.162 l
+50.109 -0.32 50.131 -0.437 50.183 -0.515 c
+50.241 -0.595 50.33 -0.632 50.447 -0.632 c
+50.536 -0.632 50.624 -0.617 50.712 -0.588 c
+50.712 -1.147 l
+50.565 -1.195 50.41 -1.22 50.256 -1.22 c
+49.999 -1.22 49.805 -1.128 49.668 -0.941 c
+49.529 -0.757 49.462 -0.496 49.462 -0.162 c
+49.462 2.308 l
+48.86 2.308 l
+48.86 2.837 l
+49.462 2.837 l
+49.462 3.792 l
+h
+53.902 -1.147 -0.647 3.984 re
+53.946 3.881 m
+53.946 3.77 53.917 3.678 53.857 3.601 c
+53.799 3.532 53.703 3.499 53.578 3.499 c
+53.46 3.499 53.365 3.532 53.299 3.601 c
+53.24 3.678 53.211 3.77 53.211 3.881 c
+53.211 3.998 53.24 4.09 53.299 4.16 c
+53.365 4.237 53.46 4.278 53.578 4.278 c
+53.703 4.278 53.799 4.237 53.857 4.16 c
+53.917 4.079 53.946 3.987 53.946 3.881 c
+55.533 2.837 m
+55.548 2.396 l
+55.802 2.738 56.125 2.911 56.518 2.911 c
+57.223 2.911 57.58 2.44 57.591 1.5 c
+57.591 -1.147 l
+56.944 -1.147 l
+56.944 1.469 l
+56.944 1.782 56.889 2.003 56.782 2.132 c
+56.672 2.256 56.518 2.323 56.312 2.323 c
+56.155 2.323 56.007 2.267 55.871 2.161 c
+55.743 2.051 55.64 1.914 55.563 1.749 c
+55.563 -1.147 l
+54.916 -1.147 l
+54.916 2.837 l
+h
+59.413 3.792 m
+59.413 2.837 l
+60.016 2.837 l
+60.016 2.308 l
+59.413 2.308 l
+59.413 -0.162 l
+59.413 -0.32 59.436 -0.437 59.488 -0.515 c
+59.546 -0.595 59.634 -0.632 59.752 -0.632 c
+59.84 -0.632 59.928 -0.617 60.016 -0.588 c
+60.016 -1.147 l
+59.87 -1.195 59.715 -1.22 59.561 -1.22 c
+59.303 -1.22 59.109 -1.128 58.973 -0.941 c
+58.833 -0.757 58.767 -0.496 58.767 -0.162 c
+58.767 2.308 l
+58.164 2.308 l
+58.164 2.837 l
+58.767 2.837 l
+58.767 3.792 l
+h
+60.575 1.029 m
+60.575 1.606 60.711 2.061 60.986 2.396 c
+61.269 2.738 61.641 2.911 62.104 2.911 c
+62.563 2.911 62.931 2.741 63.206 2.41 c
+63.489 2.087 63.636 1.639 63.647 1.073 c
+63.647 0.646 l
+63.647 0.077 63.504 -0.378 63.221 -0.721 c
+62.945 -1.055 62.578 -1.22 62.118 -1.22 c
+61.655 -1.22 61.284 -1.058 61.001 -0.735 c
+60.726 -0.405 60.583 0.037 60.575 0.588 c
+h
+61.221 0.646 m
+61.221 0.243 61.299 -0.073 61.457 -0.309 c
+61.622 -0.544 61.842 -0.661 62.118 -0.661 c
+62.684 -0.661 62.978 -0.25 63 0.573 c
+63 1.029 l
+63 1.429 62.916 1.749 62.75 1.984 c
+62.592 2.227 62.376 2.352 62.104 2.352 c
+61.84 2.352 61.622 2.227 61.457 1.984 c
+61.299 1.749 61.221 1.429 61.221 1.029 c
+h
+f
+Q
+q 1 0 0 1 469.5361 92.4598 cm
+0 0 m
+0.353 2.234 l
+1.352 2.234 l
+0.529 -1.75 l
+-0.338 -1.75 l
+-0.897 0.558 l
+-1.455 -1.75 l
+-2.323 -1.75 l
+-3.146 2.234 l
+-2.146 2.234 l
+-1.793 0 l
+-1.264 2.234 l
+-0.53 2.234 l
+h
+1.749 0.367 m
+1.749 0.974 1.889 1.448 2.175 1.793 c
+2.458 2.135 2.851 2.308 3.351 2.308 c
+3.858 2.308 4.255 2.135 4.542 1.793 c
+4.825 1.448 4.968 0.974 4.968 0.367 c
+4.968 0.103 l
+4.968 -0.497 4.825 -0.967 4.542 -1.309 c
+4.255 -1.654 3.858 -1.823 3.351 -1.823 c
+2.84 -1.823 2.444 -1.654 2.161 -1.309 c
+1.885 -0.967 1.749 -0.493 1.749 0.118 c
+h
+2.793 0.103 m
+2.793 -0.603 2.977 -0.956 3.351 -0.956 c
+3.704 -0.956 3.896 -0.662 3.925 -0.074 c
+3.925 0.367 l
+3.925 0.727 3.873 0.999 3.777 1.176 c
+3.678 1.352 3.535 1.44 3.351 1.44 c
+3.175 1.44 3.035 1.352 2.94 1.176 c
+2.84 0.999 2.793 0.727 2.793 0.367 c
+h
+7.57 1.219 m
+7.231 1.249 l
+6.945 1.249 6.755 1.124 6.659 0.881 c
+6.659 -1.75 l
+5.615 -1.75 l
+5.615 2.234 l
+6.585 2.234 l
+6.614 1.793 l
+6.78 2.135 7.011 2.308 7.305 2.308 c
+7.423 2.308 7.515 2.285 7.584 2.248 c
+h
+9.437 -0.221 m
+9.157 -0.53 l
+9.157 -1.75 l
+8.114 -1.75 l
+8.114 3.895 l
+9.157 3.895 l
+9.157 0.852 l
+9.275 1.043 l
+9.995 2.234 l
+11.245 2.234 l
+10.084 0.588 l
+11.347 -1.75 l
+10.157 -1.75 l
+h
+12.803 -1.75 -1.043 3.984 re
+11.715 3.262 m
+11.715 3.417 11.763 3.546 11.862 3.645 c
+11.969 3.752 12.104 3.806 12.274 3.806 c
+12.45 3.806 12.586 3.752 12.685 3.645 c
+12.792 3.546 12.847 3.417 12.847 3.262 c
+12.847 3.094 12.792 2.958 12.685 2.851 c
+12.586 2.752 12.45 2.705 12.274 2.705 c
+12.104 2.705 11.969 2.752 11.862 2.851 c
+11.763 2.958 11.715 3.094 11.715 3.262 c
+14.566 2.234 m
+14.596 1.837 l
+14.831 2.15 15.133 2.308 15.507 2.308 c
+16.191 2.308 16.544 1.826 16.565 0.866 c
+16.565 -1.75 l
+15.522 -1.75 l
+15.522 0.793 l
+15.522 1.018 15.486 1.179 15.42 1.278 c
+15.349 1.373 15.232 1.425 15.066 1.425 c
+14.879 1.425 14.732 1.33 14.626 1.146 c
+14.626 -1.75 l
+13.581 -1.75 l
+13.581 2.234 l
+h
+17.183 0.367 m
+17.183 1.014 17.301 1.499 17.536 1.822 c
+17.771 2.146 18.102 2.308 18.535 2.308 c
+18.888 2.308 19.16 2.164 19.359 1.881 c
+19.403 2.234 l
+20.343 2.234 l
+20.343 -1.75 l
+20.343 -2.257 20.201 -2.646 19.917 -2.911 c
+19.63 -3.183 19.226 -3.323 18.697 -3.323 c
+18.47 -3.323 18.234 -3.278 17.992 -3.19 c
+17.756 -3.102 17.58 -2.988 17.462 -2.852 c
+17.815 -2.132 l
+17.911 -2.238 18.04 -2.323 18.198 -2.382 c
+18.352 -2.448 18.499 -2.484 18.638 -2.484 c
+18.873 -2.484 19.039 -2.426 19.138 -2.309 c
+19.245 -2.198 19.299 -2.022 19.299 -1.779 c
+19.299 -1.426 l
+19.102 -1.691 18.844 -1.823 18.52 -1.823 c
+18.098 -1.823 17.771 -1.661 17.536 -1.338 c
+17.308 -1.008 17.19 -0.537 17.183 0.073 c
+h
+18.227 0.103 m
+18.227 -0.273 18.275 -0.541 18.374 -0.706 c
+18.47 -0.875 18.624 -0.956 18.829 -0.956 c
+19.042 -0.956 19.201 -0.879 19.299 -0.721 c
+19.299 1.176 l
+19.189 1.341 19.035 1.425 18.829 1.425 c
+18.624 1.425 18.47 1.341 18.374 1.176 c
+18.275 1.007 18.227 0.738 18.227 0.367 c
+h
+22.695 0.367 m
+22.695 1.014 22.802 1.499 23.019 1.822 c
+23.243 2.146 23.566 2.308 23.989 2.308 c
+24.301 2.308 24.554 2.175 24.753 1.911 c
+24.753 3.895 l
+25.811 3.895 l
+25.811 -1.75 l
+24.856 -1.75 l
+24.812 -1.338 l
+24.595 -1.661 24.319 -1.823 23.989 -1.823 c
+23.577 -1.823 23.258 -1.669 23.033 -1.353 c
+22.817 -1.029 22.703 -0.559 22.695 0.058 c
+h
+23.739 0.103 m
+23.739 -0.291 23.775 -0.566 23.856 -0.721 c
+23.945 -0.879 24.091 -0.956 24.297 -0.956 c
+24.503 -0.956 24.654 -0.864 24.753 -0.676 c
+24.753 1.132 l
+24.654 1.326 24.503 1.425 24.297 1.425 c
+24.099 1.425 23.96 1.344 23.871 1.19 c
+23.783 1.043 23.739 0.771 23.739 0.382 c
+h
+27.663 -1.75 -1.043 3.984 re
+26.576 3.262 m
+26.576 3.417 26.624 3.546 26.723 3.645 c
+26.829 3.752 26.965 3.806 27.135 3.806 c
+27.311 3.806 27.447 3.752 27.546 3.645 c
+27.652 3.546 27.708 3.417 27.708 3.262 c
+27.708 3.094 27.652 2.958 27.546 2.851 c
+27.447 2.752 27.311 2.705 27.135 2.705 c
+26.965 2.705 26.829 2.752 26.723 2.851 c
+26.624 2.958 26.576 3.094 26.576 3.262 c
+30.427 1.219 m
+30.089 1.249 l
+29.803 1.249 29.611 1.124 29.516 0.881 c
+29.516 -1.75 l
+28.471 -1.75 l
+28.471 2.234 l
+29.442 2.234 l
+29.471 1.793 l
+29.637 2.135 29.868 2.308 30.162 2.308 c
+30.28 2.308 30.372 2.285 30.441 2.248 c
+h
+32.5 -1.823 m
+31.97 -1.823 31.551 -1.669 31.25 -1.353 c
+30.956 -1.029 30.809 -0.57 30.809 0.029 c
+30.809 0.338 l
+30.809 0.962 30.945 1.448 31.22 1.793 c
+31.492 2.135 31.885 2.308 32.396 2.308 c
+32.897 2.308 33.267 2.146 33.514 1.822 c
+33.767 1.499 33.9 1.021 33.911 0.396 c
+33.911 -0.103 l
+31.838 -0.103 l
+31.856 -0.397 31.919 -0.614 32.029 -0.75 c
+32.147 -0.89 32.327 -0.956 32.573 -0.956 c
+32.915 -0.956 33.205 -0.838 33.44 -0.603 c
+33.852 -1.235 l
+33.724 -1.411 33.535 -1.555 33.294 -1.661 c
+33.047 -1.768 32.783 -1.823 32.5 -1.823 c
+31.853 0.617 m
+32.882 0.617 l
+32.882 0.72 l
+32.882 0.955 32.841 1.132 32.764 1.249 c
+32.694 1.373 32.566 1.44 32.382 1.44 c
+32.205 1.44 32.074 1.371 31.985 1.234 c
+31.904 1.105 31.86 0.9 31.853 0.617 c
+35.939 -0.956 m
+36.233 -0.956 36.384 -0.761 36.394 -0.368 c
+37.365 -0.368 l
+37.365 -0.802 37.233 -1.154 36.968 -1.426 c
+36.703 -1.691 36.365 -1.823 35.954 -1.823 c
+35.443 -1.823 35.05 -1.669 34.778 -1.353 c
+34.513 -1.029 34.374 -0.559 34.366 0.058 c
+34.366 0.382 l
+34.366 1.007 34.499 1.484 34.763 1.807 c
+35.035 2.138 35.432 2.308 35.954 2.308 c
+36.384 2.308 36.726 2.167 36.982 1.896 c
+37.236 1.62 37.365 1.238 37.365 0.749 c
+36.394 0.749 l
+36.394 0.962 36.354 1.132 36.277 1.249 c
+36.207 1.373 36.09 1.44 35.924 1.44 c
+35.748 1.44 35.619 1.373 35.542 1.249 c
+35.461 1.12 35.417 0.87 35.41 0.5 c
+35.41 0.087 l
+35.41 -0.235 35.424 -0.464 35.454 -0.588 c
+35.49 -0.717 35.546 -0.809 35.615 -0.867 c
+35.693 -0.927 35.8 -0.956 35.939 -0.956 c
+39.173 3.204 m
+39.173 2.234 l
+39.702 2.234 l
+39.702 1.44 l
+39.173 1.44 l
+39.173 -0.53 l
+39.173 -0.688 39.191 -0.794 39.232 -0.853 c
+39.28 -0.912 39.364 -0.941 39.482 -0.941 c
+39.588 -0.941 39.673 -0.934 39.731 -0.912 c
+39.731 -1.721 l
+39.555 -1.786 39.364 -1.823 39.158 -1.823 c
+38.482 -1.823 38.137 -1.437 38.129 -0.662 c
+38.129 1.44 l
+37.674 1.44 l
+37.674 2.234 l
+38.129 2.234 l
+38.129 3.204 l
+h
+40.055 0.367 m
+40.055 0.974 40.194 1.448 40.481 1.793 c
+40.764 2.135 41.157 2.308 41.657 2.308 c
+42.164 2.308 42.561 2.135 42.848 1.793 c
+43.131 1.448 43.274 0.974 43.274 0.367 c
+43.274 0.103 l
+43.274 -0.497 43.131 -0.967 42.848 -1.309 c
+42.561 -1.654 42.164 -1.823 41.657 -1.823 c
+41.146 -1.823 40.749 -1.654 40.466 -1.309 c
+40.191 -0.967 40.055 -0.493 40.055 0.118 c
+h
+41.098 0.103 m
+41.098 -0.603 41.282 -0.956 41.657 -0.956 c
+42.01 -0.956 42.201 -0.662 42.231 -0.074 c
+42.231 0.367 l
+42.231 0.727 42.179 0.999 42.083 1.176 c
+41.984 1.352 41.84 1.44 41.657 1.44 c
+41.481 1.44 41.341 1.352 41.246 1.176 c
+41.146 0.999 41.098 0.727 41.098 0.367 c
+h
+45.875 1.219 m
+45.537 1.249 l
+45.25 1.249 45.06 1.124 44.965 0.881 c
+44.965 -1.75 l
+43.92 -1.75 l
+43.92 2.234 l
+44.891 2.234 l
+44.92 1.793 l
+45.086 2.135 45.317 2.308 45.611 2.308 c
+45.728 2.308 45.821 2.285 45.89 2.248 c
+h
+47.772 -0.015 m
+48.301 2.234 l
+49.403 2.234 l
+48.095 -2.352 l
+47.897 -3.017 47.529 -3.352 46.993 -3.352 c
+46.864 -3.352 46.721 -3.33 46.567 -3.293 c
+46.567 -2.469 l
+46.684 -2.484 l
+46.85 -2.484 46.971 -2.448 47.051 -2.382 c
+47.129 -2.323 47.191 -2.213 47.243 -2.058 c
+47.316 -1.794 l
+46.17 2.234 l
+47.286 2.234 l
+h
+f
+Q
+q 1 0 0 1 519.5421 91.0628 cm
+0 0 m
+0 0.118 0.033 0.214 0.103 0.294 c
+0.169 0.372 0.272 0.412 0.412 0.412 c
+0.559 0.412 0.665 0.372 0.735 0.294 c
+0.812 0.214 0.852 0.118 0.852 0 c
+0.852 -0.11 0.812 -0.202 0.735 -0.279 c
+0.665 -0.357 0.559 -0.397 0.412 -0.397 c
+0.272 -0.397 0.169 -0.357 0.103 -0.279 c
+0.033 -0.202 0 -0.11 0 0 c
+f
+Q
+0.113 0.082 0.09 0 k
+287.665 113.704 234.667 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 106.8644 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.646 -0.243 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.69 -1.999 0.69 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.142 1.278 -3.219 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.119 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.119 -1.128 3.09 -0.97 3.042 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.32 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.319 2.385 -2.366 2.337 c
+-2.406 2.296 -2.436 2.249 -2.454 2.19 c
+-2.477 2.132 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.201 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.66 m
+6.184 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.856 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.86 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.073 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.411 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.631 5.137 1.779 c
+5.244 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.179 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.866 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.165 7.14 2.198 7.151 2.219 c
+8.004 2.219 l
+7.993 2.138 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.871 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.621 6.137 1.573 c
+6.056 1.532 5.99 1.463 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.675 re
+10.124 2.837 m
+13.597 1.602 m
+13.053 1.602 l
+13.053 2.219 l
+13.641 2.219 l
+13.92 3.117 l
+14.494 3.117 l
+14.494 2.219 l
+15.728 2.219 l
+15.728 1.602 l
+14.494 1.602 l
+14.494 -0.103 l
+14.494 -0.324 l
+14.501 -0.393 14.523 -0.455 14.552 -0.515 c
+14.589 -0.566 14.645 -0.61 14.714 -0.646 c
+14.791 -0.676 14.905 -0.691 15.052 -0.691 c
+15.188 -0.691 15.324 -0.687 15.464 -0.676 c
+15.599 -0.658 15.732 -0.632 15.861 -0.603 c
+15.861 -1.205 l
+15.78 -1.216 15.703 -1.231 15.626 -1.249 c
+15.545 -1.261 15.468 -1.268 15.391 -1.278 c
+15.31 -1.286 15.221 -1.294 15.125 -1.294 c
+15.038 -1.301 14.938 -1.309 14.832 -1.309 c
+14.645 -1.309 14.483 -1.294 14.346 -1.264 c
+14.218 -1.228 14.104 -1.183 14.009 -1.132 c
+13.92 -1.084 13.847 -1.025 13.788 -0.956 c
+13.729 -0.879 13.685 -0.802 13.656 -0.721 c
+13.627 -0.632 13.604 -0.544 13.597 -0.455 c
+13.586 -0.36 13.582 -0.264 13.582 -0.176 c
+h
+24.22 -0.25 m
+24.22 -0.419 24.18 -0.569 24.103 -0.706 c
+24.033 -0.834 23.931 -0.948 23.794 -1.043 c
+23.666 -1.132 23.504 -1.201 23.31 -1.249 c
+23.121 -1.297 22.905 -1.323 22.662 -1.323 c
+22.435 -1.323 22.236 -1.309 22.06 -1.278 c
+21.883 -1.249 21.725 -1.201 21.59 -1.132 c
+21.45 -1.055 21.34 -0.956 21.251 -0.838 c
+21.163 -0.721 21.093 -0.573 21.045 -0.397 c
+21.854 -0.279 l
+21.872 -0.378 21.902 -0.455 21.942 -0.515 c
+21.99 -0.573 22.049 -0.617 22.119 -0.646 c
+22.185 -0.676 22.265 -0.702 22.354 -0.721 c
+22.442 -0.731 22.545 -0.735 22.662 -0.735 c
+22.758 -0.735 22.853 -0.731 22.942 -0.721 c
+23.03 -0.702 23.107 -0.676 23.177 -0.646 c
+23.243 -0.617 23.295 -0.58 23.324 -0.529 c
+23.36 -0.482 23.383 -0.419 23.383 -0.338 c
+23.383 -0.243 23.353 -0.169 23.295 -0.118 c
+23.243 -0.07 23.177 -0.029 23.089 0 c
+23.001 0.037 22.89 0.066 22.766 0.088 c
+22.647 0.118 22.516 0.147 22.369 0.177 c
+22.229 0.214 22.09 0.254 21.942 0.294 c
+21.803 0.341 21.677 0.405 21.56 0.485 c
+21.45 0.563 21.361 0.661 21.296 0.779 c
+21.226 0.897 21.193 1.047 21.193 1.235 c
+21.193 1.389 21.222 1.532 21.28 1.661 c
+21.347 1.797 21.442 1.911 21.56 1.999 c
+21.685 2.087 21.843 2.153 22.03 2.205 c
+22.215 2.253 22.427 2.278 22.662 2.278 c
+22.846 2.278 23.023 2.256 23.192 2.219 c
+23.357 2.19 23.504 2.135 23.632 2.058 c
+23.757 1.988 23.868 1.889 23.956 1.764 c
+24.044 1.646 24.103 1.503 24.133 1.338 c
+23.339 1.264 l
+23.316 1.341 23.287 1.404 23.25 1.455 c
+23.21 1.514 23.162 1.558 23.104 1.588 c
+23.052 1.625 22.99 1.65 22.913 1.661 c
+22.832 1.668 22.751 1.675 22.662 1.675 c
+22.446 1.675 22.284 1.646 22.177 1.588 c
+22.067 1.536 22.016 1.448 22.016 1.323 c
+22.016 1.242 22.034 1.18 22.074 1.132 c
+22.122 1.08 22.185 1.043 22.265 1.014 c
+22.354 0.985 22.45 0.956 22.56 0.926 c
+22.666 0.904 22.788 0.882 22.927 0.852 c
+23.081 0.823 23.239 0.783 23.397 0.735 c
+23.551 0.684 23.692 0.621 23.809 0.544 c
+23.927 0.463 24.022 0.36 24.103 0.235 c
+24.18 0.106 24.22 -0.056 24.22 -0.25 c
+25.783 1.602 m
+25.238 1.602 l
+25.238 2.219 l
+25.826 2.219 l
+26.106 3.117 l
+26.679 3.117 l
+26.679 2.219 l
+27.914 2.219 l
+27.914 1.602 l
+26.679 1.602 l
+26.679 -0.103 l
+26.679 -0.324 l
+26.686 -0.393 26.709 -0.455 26.738 -0.515 c
+26.774 -0.566 26.83 -0.61 26.9 -0.646 c
+26.977 -0.676 27.09 -0.691 27.237 -0.691 c
+27.374 -0.691 27.509 -0.687 27.649 -0.676 c
+27.785 -0.658 27.917 -0.632 28.046 -0.603 c
+28.046 -1.205 l
+27.965 -1.216 27.888 -1.231 27.811 -1.249 c
+27.73 -1.261 27.653 -1.268 27.576 -1.278 c
+27.495 -1.286 27.407 -1.294 27.312 -1.294 c
+27.223 -1.301 27.123 -1.309 27.017 -1.309 c
+26.83 -1.309 26.668 -1.294 26.532 -1.264 c
+26.404 -1.228 26.29 -1.183 26.194 -1.132 c
+26.106 -1.084 26.032 -1.025 25.974 -0.956 c
+25.915 -0.879 25.87 -0.802 25.841 -0.721 c
+25.812 -0.632 25.789 -0.544 25.783 -0.455 c
+25.772 -0.36 25.768 -0.264 25.768 -0.176 c
+h
+30.196 -1.323 m
+30.027 -1.323 29.876 -1.301 29.741 -1.264 c
+29.612 -1.216 29.498 -1.147 29.402 -1.058 c
+29.313 -0.97 29.244 -0.864 29.196 -0.735 c
+29.145 -0.599 29.122 -0.449 29.122 -0.279 c
+29.122 -0.073 29.155 0.096 29.226 0.235 c
+29.292 0.382 29.388 0.492 29.505 0.573 c
+29.63 0.661 29.773 0.724 29.931 0.765 c
+30.096 0.802 30.273 0.827 30.46 0.838 c
+31.181 0.852 l
+31.181 1.029 l
+31.181 1.147 31.17 1.249 31.152 1.338 c
+31.129 1.426 31.096 1.492 31.048 1.544 c
+31.008 1.602 30.96 1.639 30.901 1.661 c
+30.842 1.679 30.776 1.691 30.71 1.691 c
+30.641 1.691 30.578 1.679 30.519 1.661 c
+30.468 1.65 30.42 1.625 30.372 1.588 c
+30.331 1.558 30.298 1.507 30.269 1.44 c
+30.248 1.382 30.233 1.301 30.225 1.205 c
+29.284 1.249 l
+29.313 1.396 29.358 1.532 29.417 1.661 c
+29.483 1.786 29.579 1.897 29.696 1.984 c
+29.814 2.08 29.953 2.153 30.122 2.205 c
+30.298 2.253 30.504 2.278 30.74 2.278 c
+31.181 2.278 31.511 2.168 31.74 1.955 c
+31.975 1.749 32.092 1.44 32.092 1.029 c
+32.092 -0.235 l
+32.092 -0.455 l
+32.099 -0.515 32.114 -0.569 32.136 -0.617 c
+32.154 -0.658 32.184 -0.691 32.224 -0.721 c
+32.261 -0.742 32.313 -0.75 32.371 -0.75 c
+32.438 -0.75 32.507 -0.746 32.577 -0.735 c
+32.577 -1.22 l
+32.519 -1.231 32.463 -1.242 32.415 -1.249 c
+32.375 -1.261 32.334 -1.268 32.297 -1.278 c
+32.257 -1.286 32.213 -1.294 32.166 -1.294 c
+32.114 -1.301 32.055 -1.309 31.989 -1.309 c
+31.761 -1.309 31.596 -1.257 31.489 -1.147 c
+31.379 -1.029 31.316 -0.864 31.298 -0.646 c
+31.283 -0.646 l
+31.214 -0.757 31.144 -0.852 31.077 -0.941 c
+31.008 -1.022 30.931 -1.087 30.842 -1.147 c
+30.755 -1.205 30.655 -1.249 30.549 -1.278 c
+30.449 -1.309 30.331 -1.323 30.196 -1.323 c
+31.181 0.353 m
+30.755 0.338 l
+30.655 0.338 30.564 0.331 30.475 0.324 c
+30.394 0.312 30.328 0.287 30.269 0.25 c
+30.211 0.21 30.159 0.151 30.122 0.073 c
+30.082 0.004 30.063 -0.088 30.063 -0.206 c
+30.063 -0.374 30.096 -0.496 30.167 -0.573 c
+30.233 -0.654 30.331 -0.691 30.46 -0.691 c
+30.567 -0.691 30.666 -0.669 30.755 -0.617 c
+30.85 -0.569 30.931 -0.507 30.99 -0.426 c
+31.056 -0.349 31.107 -0.261 31.137 -0.162 c
+31.166 -0.056 31.181 0.059 31.181 0.177 c
+h
+36.403 -0.25 m
+36.403 -0.419 36.362 -0.569 36.285 -0.706 c
+36.215 -0.834 36.112 -0.948 35.976 -1.043 c
+35.848 -1.132 35.686 -1.201 35.491 -1.249 c
+35.304 -1.297 35.087 -1.323 34.844 -1.323 c
+34.616 -1.323 34.418 -1.309 34.242 -1.278 c
+34.065 -1.249 33.907 -1.201 33.772 -1.132 c
+33.631 -1.055 33.521 -0.956 33.433 -0.838 c
+33.345 -0.721 33.275 -0.573 33.228 -0.397 c
+34.036 -0.279 l
+34.055 -0.378 34.084 -0.455 34.124 -0.515 c
+34.171 -0.573 34.231 -0.617 34.3 -0.646 c
+34.367 -0.676 34.447 -0.702 34.535 -0.721 c
+34.624 -0.731 34.726 -0.735 34.844 -0.735 c
+34.94 -0.735 35.035 -0.731 35.123 -0.721 c
+35.212 -0.702 35.289 -0.676 35.359 -0.646 c
+35.425 -0.617 35.476 -0.58 35.505 -0.529 c
+35.543 -0.482 35.565 -0.419 35.565 -0.338 c
+35.565 -0.243 35.535 -0.169 35.476 -0.118 c
+35.425 -0.07 35.359 -0.029 35.27 0 c
+35.183 0.037 35.073 0.066 34.948 0.088 c
+34.83 0.118 34.697 0.147 34.551 0.177 c
+34.41 0.214 34.271 0.254 34.124 0.294 c
+33.984 0.341 33.859 0.405 33.742 0.485 c
+33.631 0.563 33.544 0.661 33.477 0.779 c
+33.408 0.897 33.375 1.047 33.375 1.235 c
+33.375 1.389 33.404 1.532 33.463 1.661 c
+33.529 1.797 33.624 1.911 33.742 1.999 c
+33.867 2.087 34.025 2.153 34.212 2.205 c
+34.396 2.253 34.609 2.278 34.844 2.278 c
+35.028 2.278 35.204 2.256 35.374 2.219 c
+35.539 2.19 35.686 2.135 35.815 2.058 c
+35.939 1.988 36.05 1.889 36.138 1.764 c
+36.226 1.646 36.285 1.503 36.314 1.338 c
+35.52 1.264 l
+35.499 1.341 35.469 1.404 35.432 1.455 c
+35.392 1.514 35.345 1.558 35.285 1.588 c
+35.234 1.625 35.171 1.65 35.094 1.661 c
+35.013 1.668 34.932 1.675 34.844 1.675 c
+34.628 1.675 34.466 1.646 34.36 1.588 c
+34.249 1.536 34.198 1.448 34.198 1.323 c
+34.198 1.242 34.216 1.18 34.256 1.132 c
+34.304 1.08 34.367 1.043 34.447 1.014 c
+34.535 0.985 34.631 0.956 34.742 0.926 c
+34.848 0.904 34.969 0.882 35.109 0.852 c
+35.264 0.823 35.422 0.783 35.58 0.735 c
+35.734 0.684 35.873 0.621 35.991 0.544 c
+36.108 0.463 36.204 0.36 36.285 0.235 c
+36.362 0.106 36.403 -0.056 36.403 -0.25 c
+38.262 1.514 m
+38.379 1.786 38.53 1.984 38.718 2.102 c
+38.901 2.219 39.122 2.278 39.379 2.278 c
+39.584 2.278 39.754 2.242 39.894 2.176 c
+40.041 2.105 40.151 2.014 40.232 1.897 c
+40.32 1.779 40.378 1.635 40.408 1.47 c
+40.444 1.301 40.467 1.124 40.467 0.941 c
+40.467 -1.264 l
+39.555 -1.264 l
+39.555 0.735 l
+39.555 0.871 39.544 0.992 39.526 1.103 c
+39.515 1.209 39.489 1.297 39.453 1.367 c
+39.412 1.444 39.353 1.503 39.276 1.544 c
+39.206 1.58 39.114 1.602 38.996 1.602 c
+38.886 1.602 38.791 1.577 38.703 1.529 c
+38.615 1.477 38.534 1.411 38.468 1.323 c
+38.409 1.235 38.358 1.124 38.321 1 c
+38.291 0.882 38.277 0.75 38.277 0.603 c
+38.277 -1.264 l
+37.365 -1.264 l
+37.365 3.513 l
+38.277 3.513 l
+38.277 2.205 l
+38.277 2.135 38.269 2.065 38.262 1.999 c
+38.262 1.793 l
+38.262 1.735 38.254 1.679 38.248 1.631 c
+38.248 1.514 l
+h
+47.662 -1.264 m
+47.651 -1.246 47.64 -1.216 47.632 -1.176 c
+47.632 -1.128 47.625 -1.08 47.617 -1.029 c
+47.617 -0.97 47.611 -0.912 47.603 -0.852 c
+47.603 -0.691 l
+47.486 -0.926 47.342 -1.095 47.177 -1.191 c
+47.008 -1.278 46.809 -1.323 46.574 -1.323 c
+46.376 -1.323 46.2 -1.278 46.045 -1.191 c
+45.887 -1.103 45.755 -0.981 45.648 -0.823 c
+45.549 -0.658 45.472 -0.467 45.413 -0.25 c
+45.362 -0.037 45.34 0.206 45.34 0.47 c
+45.34 0.735 45.362 0.974 45.413 1.191 c
+45.472 1.415 45.549 1.606 45.648 1.764 c
+45.755 1.918 45.887 2.043 46.045 2.132 c
+46.21 2.227 46.401 2.278 46.618 2.278 c
+46.714 2.278 46.809 2.263 46.898 2.234 c
+46.993 2.213 47.089 2.179 47.177 2.132 c
+47.265 2.08 47.342 2.018 47.412 1.941 c
+47.489 1.86 47.552 1.768 47.603 1.661 c
+47.603 1.749 l
+47.603 1.897 l
+47.603 2.058 l
+47.603 2.234 l
+47.603 3.513 l
+48.5 3.513 l
+48.5 -0.5 l
+48.5 -0.676 48.504 -0.834 48.515 -0.97 c
+48.521 -1.099 48.529 -1.198 48.529 -1.264 c
+h
+47.617 0.485 m
+47.617 0.721 47.592 0.912 47.544 1.058 c
+47.504 1.213 47.449 1.338 47.382 1.426 c
+47.324 1.514 47.254 1.573 47.177 1.602 c
+47.096 1.639 47.019 1.661 46.942 1.661 c
+46.842 1.661 46.751 1.635 46.663 1.588 c
+46.582 1.548 46.516 1.477 46.457 1.382 c
+46.405 1.282 46.362 1.161 46.324 1.014 c
+46.295 0.867 46.281 0.684 46.281 0.47 c
+46.281 0.077 46.331 -0.216 46.441 -0.411 c
+46.559 -0.61 46.721 -0.706 46.927 -0.706 c
+47.004 -0.706 47.081 -0.687 47.162 -0.646 c
+47.239 -0.61 47.313 -0.544 47.382 -0.455 c
+47.449 -0.368 47.504 -0.246 47.544 -0.088 c
+47.592 0.066 47.617 0.257 47.617 0.485 c
+52.56 1.47 m
+52.461 1.477 52.359 1.488 52.251 1.5 c
+52.141 1.517 52.02 1.529 51.885 1.529 c
+51.708 1.529 51.55 1.488 51.414 1.411 c
+51.274 1.341 51.156 1.242 51.061 1.118 c
+50.973 0.989 50.903 0.842 50.855 0.676 c
+50.815 0.507 50.796 0.331 50.796 0.147 c
+50.796 -1.264 l
+49.9 -1.264 l
+49.9 0.985 l
+49.9 1.11 49.889 1.235 49.87 1.353 c
+49.859 1.477 49.845 1.595 49.826 1.706 c
+49.815 1.823 49.801 1.918 49.782 1.999 c
+49.76 2.087 49.742 2.161 49.724 2.219 c
+50.605 2.219 l
+50.613 2.168 50.624 2.117 50.634 2.058 c
+50.653 1.999 50.668 1.933 50.679 1.866 c
+50.697 1.808 50.712 1.742 50.723 1.675 c
+50.73 1.606 50.742 1.544 50.753 1.484 c
+50.767 1.484 l
+50.804 1.602 50.855 1.708 50.914 1.808 c
+50.981 1.903 51.061 1.988 51.149 2.058 c
+51.237 2.124 51.34 2.179 51.458 2.219 c
+51.583 2.256 51.73 2.278 51.899 2.278 c
+52.024 2.278 52.141 2.271 52.251 2.263 c
+52.369 2.253 52.473 2.238 52.56 2.219 c
+h
+56.812 0.485 m
+56.812 0.21 56.776 -0.04 56.71 -0.264 c
+56.639 -0.482 56.537 -0.669 56.4 -0.823 c
+56.261 -0.981 56.084 -1.103 55.871 -1.191 c
+55.654 -1.278 55.401 -1.323 55.107 -1.323 c
+54.831 -1.323 54.585 -1.278 54.372 -1.191 c
+54.166 -1.103 53.994 -0.981 53.857 -0.823 c
+53.718 -0.669 53.615 -0.482 53.549 -0.264 c
+53.479 -0.04 53.446 0.21 53.446 0.485 c
+53.446 0.738 53.475 0.974 53.535 1.191 c
+53.6 1.415 53.703 1.606 53.843 1.764 c
+53.979 1.929 54.156 2.058 54.372 2.146 c
+54.585 2.234 54.842 2.278 55.137 2.278 c
+55.449 2.278 55.71 2.234 55.916 2.146 c
+56.128 2.058 56.301 1.929 56.43 1.764 c
+56.566 1.606 56.665 1.415 56.724 1.191 c
+56.783 0.974 56.812 0.738 56.812 0.485 c
+55.856 0.485 m
+55.856 0.69 55.842 0.867 55.812 1.014 c
+55.791 1.161 55.754 1.282 55.695 1.382 c
+55.636 1.477 55.563 1.548 55.474 1.588 c
+55.386 1.635 55.276 1.661 55.151 1.661 c
+54.887 1.661 54.696 1.562 54.578 1.367 c
+54.46 1.18 54.401 0.885 54.401 0.485 c
+54.401 0.062 54.46 -0.243 54.578 -0.426 c
+54.696 -0.613 54.871 -0.706 55.107 -0.706 c
+55.232 -0.706 55.346 -0.687 55.445 -0.646 c
+55.54 -0.599 55.621 -0.526 55.68 -0.426 c
+55.746 -0.331 55.791 -0.206 55.812 -0.058 c
+55.842 0.088 55.856 0.268 55.856 0.485 c
+58.539 2.219 m
+58.547 2.198 58.554 2.165 58.554 2.117 c
+58.561 2.076 58.569 2.028 58.569 1.97 c
+58.576 1.918 58.584 1.866 58.584 1.808 c
+58.584 1.646 l
+58.598 1.646 l
+58.657 1.764 58.723 1.86 58.804 1.941 c
+58.881 2.018 58.966 2.08 59.054 2.132 c
+59.141 2.19 59.23 2.227 59.318 2.249 c
+59.414 2.267 59.513 2.278 59.612 2.278 c
+59.818 2.278 59.998 2.234 60.157 2.146 c
+60.311 2.058 60.439 1.929 60.538 1.764 c
+60.645 1.606 60.722 1.415 60.774 1.191 c
+60.832 0.974 60.862 0.738 60.862 0.485 c
+60.862 0.22 60.832 -0.025 60.774 -0.25 c
+60.722 -0.467 60.645 -0.658 60.538 -0.823 c
+60.439 -0.981 60.307 -1.103 60.141 -1.191 c
+59.983 -1.278 59.796 -1.323 59.583 -1.323 c
+59.484 -1.323 59.384 -1.311 59.289 -1.294 c
+59.189 -1.272 59.098 -1.242 59.01 -1.191 c
+58.929 -1.143 58.852 -1.08 58.775 -0.999 c
+58.705 -0.922 58.646 -0.831 58.598 -0.721 c
+58.584 -0.721 l
+58.584 -0.808 l
+58.591 -0.849 58.598 -0.897 58.598 -0.956 c
+58.598 -1.117 l
+58.598 -1.294 l
+58.598 -2.631 l
+57.687 -2.631 l
+57.687 1.455 l
+57.687 1.621 57.68 1.768 57.672 1.897 c
+57.672 2.219 l
+h
+58.584 0.455 m
+58.584 0.228 58.602 0.037 58.642 -0.118 c
+58.69 -0.264 58.745 -0.382 58.804 -0.47 c
+58.87 -0.559 58.944 -0.625 59.024 -0.661 c
+59.101 -0.702 59.179 -0.721 59.259 -0.721 c
+59.355 -0.721 59.443 -0.698 59.524 -0.646 c
+59.612 -0.599 59.679 -0.529 59.729 -0.441 c
+59.789 -0.345 59.833 -0.22 59.862 -0.073 c
+59.899 0.081 59.921 0.268 59.921 0.485 c
+59.921 0.875 59.862 1.168 59.744 1.367 c
+59.634 1.562 59.48 1.661 59.274 1.661 c
+59.193 1.661 59.116 1.639 59.039 1.602 c
+58.958 1.562 58.885 1.5 58.819 1.411 c
+58.749 1.323 58.69 1.198 58.642 1.043 c
+58.602 0.885 58.584 0.69 58.584 0.455 c
+f
+Q
+0.113 0.082 0.09 0 k
+287.665 197.991 234.667 -12.895 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 292.8568 191.1528 cm
+0 0 m
+0 -0.188 -0.029 -0.353 -0.087 -0.5 c
+-0.147 -0.647 -0.243 -0.776 -0.367 -0.882 c
+-0.496 -0.992 -0.658 -1.081 -0.852 -1.147 c
+-1.051 -1.206 -1.278 -1.243 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.359 -1.22 -2.543 -1.162 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.927 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.132 l
+-2.642 0.033 -2.616 -0.059 -2.587 -0.148 c
+-2.55 -0.228 -2.506 -0.302 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.675 c
+-1.977 0.683 -1.992 0.691 -1.999 0.691 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.881 -2.786 0.959 -2.91 1.058 c
+-3.039 1.153 -3.142 1.278 -3.219 1.425 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.219 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.836 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.119 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.119 -1.128 3.09 -0.97 3.042 c
+-0.804 2.991 -0.669 2.917 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.202 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.252 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.352 c
+-1.294 1.311 -1.117 1.263 -0.941 1.205 c
+-0.756 1.146 -0.595 1.066 -0.455 0.97 c
+-0.32 0.87 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.319 2.385 -2.366 2.337 c
+-2.406 2.296 -2.436 2.248 -2.454 2.19 c
+-2.477 2.131 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.778 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.201 1.558 -2.131 1.529 c
+-2.065 1.499 -1.984 1.469 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.091 -0.86 0.176 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.103 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.529 -1.448 0.558 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.53 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.66 m
+6.184 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.519 -2.484 5.402 -2.396 c
+5.284 -2.315 5.185 -2.22 5.108 -2.103 c
+5.039 -1.985 4.991 -1.856 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.754 5.964 -1.86 6.064 -1.941 c
+6.159 -2.029 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.058 6.681 -2.029 c
+6.758 -1.999 6.828 -1.945 6.887 -1.867 c
+6.945 -1.797 6.99 -1.706 7.019 -1.588 c
+7.056 -1.47 7.078 -1.324 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.89 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.073 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.215 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.412 4.888 -0.206 c
+4.836 0.008 4.814 0.243 4.814 0.5 c
+4.814 0.771 4.836 1.018 4.888 1.234 c
+4.946 1.448 5.027 1.631 5.137 1.778 c
+5.244 1.932 5.376 2.05 5.534 2.131 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.188 2.263 6.288 2.252 6.387 2.234 c
+6.483 2.212 6.571 2.179 6.652 2.131 c
+6.739 2.08 6.817 2.017 6.887 1.94 c
+6.964 1.859 7.026 1.768 7.078 1.66 c
+7.092 1.66 l
+7.092 1.808 l
+7.1 1.866 7.107 1.918 7.107 1.969 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.129 2.164 7.14 2.198 7.151 2.219 c
+8.004 2.219 l
+7.993 2.138 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.162 l
+7.975 -1.415 7.938 -1.636 7.871 -1.823 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.5 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.529 m
+7.092 0.742 7.067 0.918 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.499 6.729 1.558 6.652 1.587 c
+6.571 1.624 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.225 1.62 6.137 1.573 c
+6.056 1.532 5.99 1.462 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.874 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.339 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.383 c
+6.924 -0.294 6.978 -0.177 7.019 -0.03 c
+7.067 0.118 7.092 0.301 7.092 0.529 c
+11.036 -0.647 m
+12.168 -0.647 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.647 l
+10.124 -0.647 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.676 re
+10.124 2.836 m
+13.597 1.602 m
+13.053 1.602 l
+13.053 2.219 l
+13.641 2.219 l
+13.92 3.116 l
+14.494 3.116 l
+14.494 2.219 l
+15.728 2.219 l
+15.728 1.602 l
+14.494 1.602 l
+14.494 -0.103 l
+14.494 -0.324 l
+14.501 -0.393 14.523 -0.456 14.552 -0.515 c
+14.589 -0.566 14.645 -0.611 14.714 -0.647 c
+14.791 -0.676 14.905 -0.691 15.052 -0.691 c
+15.188 -0.691 15.324 -0.688 15.464 -0.676 c
+15.599 -0.659 15.732 -0.632 15.861 -0.603 c
+15.861 -1.206 l
+15.78 -1.216 15.703 -1.231 15.626 -1.249 c
+15.545 -1.261 15.468 -1.268 15.391 -1.279 c
+15.31 -1.286 15.221 -1.294 15.125 -1.294 c
+15.038 -1.301 14.938 -1.309 14.832 -1.309 c
+14.645 -1.309 14.483 -1.294 14.346 -1.264 c
+14.218 -1.228 14.104 -1.183 14.009 -1.132 c
+13.92 -1.085 13.847 -1.025 13.788 -0.956 c
+13.729 -0.879 13.685 -0.802 13.656 -0.721 c
+13.627 -0.632 13.604 -0.544 13.597 -0.456 c
+13.586 -0.36 13.582 -0.265 13.582 -0.177 c
+h
+24.133 1.469 m
+24.033 1.477 23.931 1.488 23.823 1.499 c
+23.713 1.517 23.592 1.529 23.456 1.529 c
+23.28 1.529 23.121 1.488 22.986 1.411 c
+22.846 1.341 22.728 1.242 22.633 1.117 c
+22.545 0.988 22.475 0.841 22.427 0.675 c
+22.387 0.507 22.369 0.33 22.369 0.147 c
+22.369 -1.264 l
+21.471 -1.264 l
+21.471 0.985 l
+21.471 1.109 21.461 1.234 21.442 1.352 c
+21.432 1.477 21.417 1.595 21.398 1.705 c
+21.388 1.822 21.373 1.918 21.355 1.999 c
+21.332 2.087 21.314 2.161 21.296 2.219 c
+22.177 2.219 l
+22.185 2.167 22.196 2.117 22.207 2.057 c
+22.225 1.999 22.24 1.932 22.251 1.866 c
+22.269 1.808 22.284 1.741 22.296 1.675 c
+22.302 1.606 22.313 1.543 22.325 1.484 c
+22.339 1.484 l
+22.375 1.602 22.427 1.708 22.486 1.808 c
+22.552 1.903 22.633 1.988 22.722 2.057 c
+22.809 2.124 22.913 2.179 23.03 2.219 c
+23.155 2.256 23.302 2.278 23.471 2.278 c
+23.596 2.278 23.713 2.271 23.823 2.263 c
+23.942 2.252 24.044 2.238 24.133 2.219 c
+h
+26.341 -1.264 m
+26.341 0.852 l
+26.341 1.018 26.333 1.153 26.327 1.263 c
+26.315 1.371 26.297 1.455 26.267 1.514 c
+26.246 1.579 26.216 1.631 26.179 1.66 c
+26.15 1.691 26.109 1.705 26.061 1.705 c
+26.003 1.705 25.947 1.675 25.9 1.616 c
+25.86 1.565 25.826 1.492 25.797 1.396 c
+25.768 1.308 25.742 1.194 25.724 1.058 c
+25.712 0.918 25.709 0.768 25.709 0.602 c
+25.709 -1.264 l
+24.96 -1.264 l
+24.96 1.469 l
+24.96 1.705 l
+24.96 1.926 l
+24.96 2.003 24.952 2.065 24.945 2.117 c
+24.945 2.219 l
+25.621 2.219 l
+25.621 2.131 l
+25.621 1.984 l
+25.628 1.926 25.635 1.866 25.635 1.808 c
+25.635 1.646 l
+25.65 1.646 l
+25.668 1.734 25.698 1.811 25.739 1.881 c
+25.775 1.959 25.82 2.028 25.87 2.087 c
+25.93 2.146 25.995 2.19 26.076 2.219 c
+26.154 2.256 26.242 2.278 26.341 2.278 c
+26.525 2.278 26.664 2.223 26.753 2.117 c
+26.848 2.017 26.918 1.859 26.959 1.646 c
+26.973 1.646 l
+27.01 1.741 27.05 1.83 27.09 1.911 c
+27.138 1.988 27.194 2.05 27.252 2.102 c
+27.312 2.161 27.377 2.204 27.458 2.234 c
+27.535 2.263 27.624 2.278 27.723 2.278 c
+27.859 2.278 27.973 2.252 28.06 2.204 c
+28.149 2.153 28.215 2.08 28.266 1.984 c
+28.326 1.885 28.362 1.756 28.384 1.602 c
+28.413 1.455 28.428 1.271 28.428 1.058 c
+28.428 -1.264 l
+27.708 -1.264 l
+27.708 0.852 l
+27.708 1.018 27.701 1.153 27.693 1.263 c
+27.682 1.371 27.664 1.455 27.634 1.514 c
+27.613 1.579 27.583 1.631 27.547 1.66 c
+27.517 1.691 27.476 1.705 27.429 1.705 c
+27.312 1.705 27.216 1.616 27.15 1.44 c
+27.09 1.271 27.061 1.014 27.061 0.661 c
+27.061 -1.264 l
+h
+34.051 -2.631 m
+34.051 3.513 l
+35.976 3.513 l
+35.976 2.896 l
+34.903 2.896 l
+34.903 -2.014 l
+35.976 -2.014 l
+35.976 -2.631 l
+h
+39.012 1.602 m
+39.012 -1.264 l
+38.115 -1.264 l
+38.115 1.602 l
+37.292 1.602 l
+37.292 2.219 l
+38.115 2.219 l
+38.115 2.484 l
+38.115 2.609 38.13 2.741 38.159 2.881 c
+38.196 3.017 38.266 3.135 38.365 3.233 c
+38.472 3.34 38.615 3.428 38.791 3.498 c
+38.967 3.564 39.191 3.601 39.467 3.601 c
+39.68 3.601 39.879 3.59 40.055 3.572 c
+40.232 3.549 40.382 3.532 40.511 3.513 c
+40.511 2.925 l
+40.382 2.944 40.239 2.958 40.085 2.969 c
+39.927 2.977 39.776 2.984 39.629 2.984 c
+39.501 2.984 39.397 2.969 39.32 2.94 c
+39.239 2.91 39.177 2.869 39.129 2.822 c
+39.077 2.77 39.044 2.708 39.027 2.631 c
+39.015 2.561 39.012 2.484 39.012 2.396 c
+39.012 2.219 l
+40.438 2.219 l
+40.438 1.602 l
+h
+43.528 -0.647 m
+44.66 -0.647 l
+44.66 -1.264 l
+41.352 -1.264 l
+41.352 -0.647 l
+42.616 -0.647 l
+42.616 1.602 l
+41.691 1.602 l
+41.691 2.219 l
+43.528 2.219 l
+h
+42.616 3.513 0.912 -0.676 re
+42.616 2.836 m
+47.588 -0.647 m
+48.72 -0.647 l
+48.72 -1.264 l
+45.413 -1.264 l
+45.413 -0.647 l
+46.677 -0.647 l
+46.677 2.896 l
+45.751 2.896 l
+45.751 3.513 l
+47.588 3.513 l
+h
+51.105 -1.324 m
+50.848 -1.324 50.62 -1.286 50.414 -1.22 c
+50.208 -1.143 50.032 -1.029 49.886 -0.882 c
+49.738 -0.728 49.62 -0.537 49.533 -0.309 c
+49.452 -0.085 49.415 0.18 49.415 0.484 c
+49.415 0.816 49.458 1.095 49.547 1.323 c
+49.643 1.558 49.772 1.741 49.929 1.881 c
+50.094 2.017 50.283 2.117 50.488 2.175 c
+50.694 2.242 50.903 2.278 51.12 2.278 c
+51.392 2.278 51.627 2.227 51.825 2.131 c
+52.031 2.043 52.197 1.911 52.325 1.734 c
+52.461 1.565 52.56 1.359 52.619 1.117 c
+52.685 0.881 52.722 0.617 52.722 0.323 c
+52.722 0.309 l
+50.356 0.309 l
+50.356 0.162 50.37 0.022 50.399 -0.103 c
+50.437 -0.231 50.491 -0.345 50.561 -0.441 c
+50.628 -0.53 50.712 -0.599 50.811 -0.647 c
+50.907 -0.698 51.021 -0.721 51.149 -0.721 c
+51.303 -0.721 51.443 -0.688 51.561 -0.618 c
+51.686 -0.551 51.774 -0.449 51.825 -0.309 c
+52.664 -0.383 l
+52.634 -0.482 52.579 -0.588 52.502 -0.706 c
+52.421 -0.816 52.318 -0.919 52.193 -1.014 c
+52.076 -1.103 51.921 -1.176 51.737 -1.235 c
+51.561 -1.294 51.347 -1.324 51.105 -1.324 c
+51.105 1.705 m
+51.017 1.705 50.929 1.691 50.84 1.66 c
+50.753 1.631 50.672 1.579 50.605 1.514 c
+50.536 1.444 50.477 1.356 50.429 1.249 c
+50.389 1.139 50.37 1.014 50.37 0.867 c
+51.84 0.867 l
+51.84 1.003 51.814 1.124 51.767 1.234 c
+51.727 1.341 51.671 1.429 51.605 1.499 c
+51.546 1.565 51.473 1.616 51.384 1.646 c
+51.297 1.683 51.201 1.705 51.105 1.705 c
+53.975 -2.631 m
+53.975 -2.014 l
+55.048 -2.014 l
+55.048 2.896 l
+53.975 2.896 l
+53.975 3.513 l
+55.901 3.513 l
+55.901 -2.631 l
+h
+f
+Q
+q 1 0 0 1 318.9586 177.1631 cm
+0 0 m
+-0.941 0 l
+-0.941 -2.161 l
+-1.616 -2.161 l
+-1.616 3.189 l
+-0.118 3.189 l
+0.412 3.189 0.809 3.05 1.073 2.778 c
+1.345 2.502 1.484 2.105 1.484 1.587 c
+1.484 1.253 1.411 0.962 1.264 0.72 c
+1.118 0.474 0.912 0.286 0.647 0.161 c
+1.676 -2.117 l
+1.676 -2.161 l
+0.956 -2.161 l
+h
+-0.941 0.588 m
+-0.118 0.588 l
+0.166 0.588 0.389 0.675 0.559 0.852 c
+0.724 1.036 0.809 1.282 0.809 1.587 c
+0.809 2.271 0.493 2.616 -0.132 2.616 c
+-0.941 2.616 l
+h
+3.72 -2.234 m
+3.219 -2.234 2.837 -2.087 2.573 -1.794 c
+2.309 -1.5 2.176 -1.066 2.176 -0.485 c
+2.176 -0.015 l
+2.176 0.58 2.301 1.047 2.558 1.381 c
+2.822 1.723 3.182 1.896 3.645 1.896 c
+4.105 1.896 4.447 1.741 4.675 1.44 c
+4.91 1.146 5.031 0.683 5.042 0.058 c
+5.042 -0.368 l
+2.822 -0.368 l
+2.822 -0.456 l
+2.822 -0.89 2.899 -1.202 3.057 -1.397 c
+3.223 -1.584 3.454 -1.676 3.749 -1.676 c
+3.944 -1.676 4.116 -1.643 4.263 -1.573 c
+4.41 -1.496 4.546 -1.378 4.675 -1.22 c
+5.012 -1.632 l
+4.726 -2.036 4.296 -2.234 3.72 -2.234 c
+3.645 1.337 m
+3.37 1.337 3.168 1.242 3.043 1.058 c
+2.914 0.87 2.841 0.58 2.822 0.191 c
+4.395 0.191 l
+4.395 0.278 l
+4.373 0.661 4.307 0.929 4.19 1.087 c
+4.072 1.253 3.888 1.337 3.645 1.337 c
+6.438 1.822 m
+6.453 1.454 l
+6.696 1.749 7.015 1.896 7.408 1.896 c
+7.85 1.896 8.158 1.697 8.335 1.308 c
+8.588 1.697 8.937 1.896 9.378 1.896 c
+10.113 1.896 10.488 1.433 10.51 0.514 c
+10.51 -2.161 l
+9.864 -2.161 l
+9.864 0.455 l
+9.864 0.749 9.808 0.962 9.702 1.102 c
+9.602 1.238 9.43 1.308 9.187 1.308 c
+8.989 1.308 8.827 1.227 8.702 1.072 c
+8.584 0.926 8.515 0.735 8.497 0.5 c
+8.497 -2.161 l
+7.834 -2.161 l
+7.834 0.484 l
+7.834 1.032 7.614 1.308 7.173 1.308 c
+6.839 1.308 6.604 1.146 6.468 0.823 c
+6.468 -2.161 l
+5.821 -2.161 l
+5.821 1.822 l
+h
+11.348 0.014 m
+11.348 0.592 11.484 1.047 11.759 1.381 c
+12.042 1.723 12.414 1.896 12.877 1.896 c
+13.336 1.896 13.704 1.727 13.979 1.396 c
+14.263 1.072 14.409 0.625 14.42 0.058 c
+14.42 -0.368 l
+14.42 -0.937 14.277 -1.393 13.993 -1.735 c
+13.718 -2.07 13.351 -2.234 12.892 -2.234 c
+12.428 -2.234 12.057 -2.073 11.774 -1.75 c
+11.499 -1.419 11.356 -0.977 11.348 -0.427 c
+h
+11.994 -0.368 m
+11.994 -0.772 12.072 -1.088 12.23 -1.324 c
+12.395 -1.559 12.616 -1.676 12.892 -1.676 c
+13.457 -1.676 13.752 -1.264 13.773 -0.441 c
+13.773 0.014 l
+13.773 0.415 13.689 0.735 13.523 0.97 c
+13.365 1.213 13.149 1.337 12.877 1.337 c
+12.612 1.337 12.395 1.213 12.23 0.97 c
+12.072 0.735 11.994 0.415 11.994 0.014 c
+h
+16.331 -1.176 m
+17.081 1.822 l
+17.742 1.822 l
+16.566 -2.161 l
+16.081 -2.161 l
+14.89 1.822 l
+15.552 1.822 l
+h
+19.8 -2.234 m
+19.3 -2.234 18.918 -2.087 18.653 -1.794 c
+18.389 -1.5 18.257 -1.066 18.257 -0.485 c
+18.257 -0.015 l
+18.257 0.58 18.381 1.047 18.639 1.381 c
+18.903 1.723 19.263 1.896 19.726 1.896 c
+20.185 1.896 20.528 1.741 20.756 1.44 c
+20.991 1.146 21.112 0.683 21.123 0.058 c
+21.123 -0.368 l
+18.903 -0.368 l
+18.903 -0.456 l
+18.903 -0.89 18.98 -1.202 19.138 -1.397 c
+19.304 -1.584 19.535 -1.676 19.829 -1.676 c
+20.025 -1.676 20.197 -1.643 20.343 -1.573 c
+20.491 -1.496 20.627 -1.378 20.756 -1.22 c
+21.093 -1.632 l
+20.807 -2.036 20.377 -2.234 19.8 -2.234 c
+19.726 1.337 m
+19.451 1.337 19.248 1.242 19.123 1.058 c
+18.995 0.87 18.922 0.58 18.903 0.191 c
+20.476 0.191 l
+20.476 0.278 l
+20.454 0.661 20.388 0.929 20.27 1.087 c
+20.152 1.253 19.969 1.337 19.726 1.337 c
+23.798 -2.161 m
+23.798 1.294 l
+23.283 1.294 l
+23.283 1.822 l
+23.798 1.822 l
+23.798 2.19 l
+23.805 2.62 23.919 2.954 24.137 3.189 c
+24.36 3.432 24.673 3.557 25.077 3.557 c
+25.224 3.557 25.363 3.534 25.503 3.498 c
+25.65 3.457 25.801 3.403 25.959 3.336 c
+25.841 2.763 l
+25.606 2.888 25.363 2.954 25.121 2.954 c
+24.875 2.954 24.702 2.884 24.607 2.748 c
+24.507 2.62 24.459 2.425 24.459 2.16 c
+24.459 1.822 l
+25.106 1.822 l
+25.106 1.294 l
+24.459 1.294 l
+24.459 -2.161 l
+h
+26.267 -2.161 -0.646 3.983 re
+28.017 -2.161 -0.647 5.644 re
+30.456 -2.234 m
+29.957 -2.234 29.575 -2.087 29.311 -1.794 c
+29.045 -1.5 28.914 -1.066 28.914 -0.485 c
+28.914 -0.015 l
+28.914 0.58 29.039 1.047 29.296 1.381 c
+29.56 1.723 29.92 1.896 30.383 1.896 c
+30.843 1.896 31.185 1.741 31.412 1.44 c
+31.647 1.146 31.769 0.683 31.78 0.058 c
+31.78 -0.368 l
+29.56 -0.368 l
+29.56 -0.456 l
+29.56 -0.89 29.637 -1.202 29.795 -1.397 c
+29.961 -1.584 30.192 -1.676 30.487 -1.676 c
+30.681 -1.676 30.853 -1.643 31.001 -1.573 c
+31.148 -1.496 31.283 -1.378 31.412 -1.22 c
+31.75 -1.632 l
+31.464 -2.036 31.034 -2.234 30.456 -2.234 c
+30.383 1.337 m
+30.107 1.337 29.905 1.242 29.781 1.058 c
+29.652 0.87 29.579 0.58 29.56 0.191 c
+31.133 0.191 l
+31.133 0.278 l
+31.111 0.661 31.044 0.929 30.927 1.087 c
+30.809 1.253 30.626 1.337 30.383 1.337 c
+34.572 -2.161 m
+34.572 1.294 l
+34.043 1.294 l
+34.043 1.822 l
+34.572 1.822 l
+34.572 2.278 l
+34.572 2.678 34.668 2.991 34.867 3.218 c
+35.073 3.443 35.351 3.557 35.705 3.557 c
+35.84 3.557 35.973 3.534 36.101 3.498 c
+36.072 2.954 l
+35.973 2.973 35.873 2.983 35.778 2.983 c
+35.403 2.983 35.219 2.719 35.219 2.19 c
+35.219 1.822 l
+35.896 1.822 l
+35.896 1.294 l
+35.219 1.294 l
+35.219 -2.161 l
+h
+38.306 1.205 m
+38.218 1.223 38.119 1.234 38.012 1.234 c
+37.678 1.234 37.442 1.051 37.307 0.69 c
+37.307 -2.161 l
+36.66 -2.161 l
+36.66 1.822 l
+37.292 1.822 l
+37.307 1.411 l
+37.483 1.734 37.726 1.896 38.042 1.896 c
+38.148 1.896 38.236 1.874 38.306 1.837 c
+h
+38.747 0.014 m
+38.747 0.592 38.883 1.047 39.158 1.381 c
+39.441 1.723 39.813 1.896 40.276 1.896 c
+40.735 1.896 41.103 1.727 41.378 1.396 c
+41.662 1.072 41.808 0.625 41.82 0.058 c
+41.82 -0.368 l
+41.82 -0.937 41.676 -1.393 41.393 -1.735 c
+41.117 -2.07 40.75 -2.234 40.29 -2.234 c
+39.827 -2.234 39.456 -2.073 39.173 -1.75 c
+38.898 -1.419 38.755 -0.977 38.747 -0.427 c
+h
+39.393 -0.368 m
+39.393 -0.772 39.471 -1.088 39.629 -1.324 c
+39.794 -1.559 40.015 -1.676 40.29 -1.676 c
+40.856 -1.676 41.151 -1.264 41.172 -0.441 c
+41.172 0.014 l
+41.172 0.415 41.088 0.735 40.922 0.97 c
+40.764 1.213 40.548 1.337 40.276 1.337 c
+40.012 1.337 39.794 1.213 39.629 0.97 c
+39.471 0.735 39.393 0.415 39.393 0.014 c
+h
+43.274 1.822 m
+43.289 1.454 l
+43.532 1.749 43.852 1.896 44.245 1.896 c
+44.685 1.896 44.994 1.697 45.171 1.308 c
+45.424 1.697 45.774 1.896 46.214 1.896 c
+46.949 1.896 47.324 1.433 47.346 0.514 c
+47.346 -2.161 l
+46.699 -2.161 l
+46.699 0.455 l
+46.699 0.749 46.644 0.962 46.537 1.102 c
+46.439 1.238 46.266 1.308 46.023 1.308 c
+45.824 1.308 45.663 1.227 45.538 1.072 c
+45.421 0.926 45.35 0.735 45.332 0.5 c
+45.332 -2.161 l
+44.671 -2.161 l
+44.671 0.484 l
+44.671 1.032 44.45 1.308 44.01 1.308 c
+43.675 1.308 43.44 1.146 43.304 0.823 c
+43.304 -2.161 l
+42.657 -2.161 l
+42.657 1.822 l
+h
+f
+Q
+q 1 0 0 1 371.7877 176.751 cm
+0 0 m
+0.353 2.234 l
+1.352 2.234 l
+0.529 -1.749 l
+-0.339 -1.749 l
+-0.897 0.559 l
+-1.455 -1.749 l
+-2.323 -1.749 l
+-3.146 2.234 l
+-2.147 2.234 l
+-1.794 0 l
+-1.264 2.234 l
+-0.53 2.234 l
+h
+1.749 0.368 m
+1.749 0.974 1.888 1.448 2.175 1.793 c
+2.458 2.135 2.851 2.308 3.351 2.308 c
+3.858 2.308 4.255 2.135 4.542 1.793 c
+4.825 1.448 4.968 0.974 4.968 0.368 c
+4.968 0.103 l
+4.968 -0.496 4.825 -0.966 4.542 -1.309 c
+4.255 -1.654 3.858 -1.822 3.351 -1.822 c
+2.84 -1.822 2.443 -1.654 2.161 -1.309 c
+1.885 -0.966 1.749 -0.492 1.749 0.118 c
+h
+2.792 0.103 m
+2.792 -0.603 2.977 -0.956 3.351 -0.956 c
+3.704 -0.956 3.895 -0.661 3.924 -0.073 c
+3.924 0.368 l
+3.924 0.728 3.873 1 3.777 1.176 c
+3.678 1.353 3.534 1.44 3.351 1.44 c
+3.175 1.44 3.035 1.353 2.94 1.176 c
+2.84 1 2.792 0.728 2.792 0.368 c
+h
+7.57 1.22 m
+7.231 1.249 l
+6.945 1.249 6.754 1.124 6.659 0.882 c
+6.659 -1.749 l
+5.614 -1.749 l
+5.614 2.234 l
+6.585 2.234 l
+6.614 1.793 l
+6.78 2.135 7.011 2.308 7.305 2.308 c
+7.422 2.308 7.515 2.286 7.584 2.249 c
+h
+9.437 -0.22 m
+9.157 -0.529 l
+9.157 -1.749 l
+8.114 -1.749 l
+8.114 3.896 l
+9.157 3.896 l
+9.157 0.852 l
+9.275 1.043 l
+9.995 2.234 l
+11.245 2.234 l
+10.083 0.588 l
+11.347 -1.749 l
+10.157 -1.749 l
+h
+12.803 -1.749 -1.043 3.983 re
+11.715 3.263 m
+11.715 3.418 11.763 3.547 11.862 3.645 c
+11.968 3.752 12.104 3.807 12.274 3.807 c
+12.45 3.807 12.586 3.752 12.685 3.645 c
+12.791 3.547 12.847 3.418 12.847 3.263 c
+12.847 3.094 12.791 2.959 12.685 2.851 c
+12.586 2.753 12.45 2.705 12.274 2.705 c
+12.104 2.705 11.968 2.753 11.862 2.851 c
+11.763 2.959 11.715 3.094 11.715 3.263 c
+14.566 2.234 m
+14.596 1.837 l
+14.831 2.15 15.133 2.308 15.507 2.308 c
+16.191 2.308 16.544 1.827 16.565 0.867 c
+16.565 -1.749 l
+15.522 -1.749 l
+15.522 0.794 l
+15.522 1.018 15.486 1.18 15.419 1.278 c
+15.349 1.374 15.232 1.426 15.066 1.426 c
+14.879 1.426 14.732 1.33 14.626 1.147 c
+14.626 -1.749 l
+13.581 -1.749 l
+13.581 2.234 l
+h
+17.183 0.368 m
+17.183 1.014 17.3 1.5 17.535 1.823 c
+17.771 2.146 18.102 2.308 18.535 2.308 c
+18.888 2.308 19.16 2.165 19.359 1.881 c
+19.403 2.234 l
+20.344 2.234 l
+20.344 -1.749 l
+20.344 -2.256 20.2 -2.645 19.916 -2.911 c
+19.63 -3.183 19.226 -3.322 18.697 -3.322 c
+18.469 -3.322 18.233 -3.278 17.992 -3.19 c
+17.756 -3.102 17.58 -2.988 17.462 -2.851 c
+17.815 -2.132 l
+17.911 -2.238 18.039 -2.323 18.197 -2.381 c
+18.351 -2.447 18.499 -2.484 18.638 -2.484 c
+18.873 -2.484 19.039 -2.425 19.137 -2.308 c
+19.245 -2.198 19.299 -2.021 19.299 -1.779 c
+19.299 -1.426 l
+19.101 -1.691 18.844 -1.822 18.52 -1.822 c
+18.098 -1.822 17.771 -1.661 17.535 -1.338 c
+17.308 -1.007 17.19 -0.536 17.183 0.073 c
+h
+18.227 0.103 m
+18.227 -0.272 18.274 -0.54 18.374 -0.706 c
+18.469 -0.875 18.624 -0.956 18.829 -0.956 c
+19.042 -0.956 19.201 -0.878 19.299 -0.721 c
+19.299 1.176 l
+19.189 1.341 19.035 1.426 18.829 1.426 c
+18.624 1.426 18.469 1.341 18.374 1.176 c
+18.274 1.007 18.227 0.738 18.227 0.368 c
+h
+22.695 0.368 m
+22.695 1.014 22.802 1.5 23.018 1.823 c
+23.243 2.146 23.566 2.308 23.989 2.308 c
+24.301 2.308 24.554 2.176 24.753 1.911 c
+24.753 3.896 l
+25.811 3.896 l
+25.811 -1.749 l
+24.855 -1.749 l
+24.812 -1.338 l
+24.595 -1.661 24.319 -1.822 23.989 -1.822 c
+23.577 -1.822 23.257 -1.668 23.033 -1.352 c
+22.817 -1.029 22.702 -0.559 22.695 0.059 c
+h
+23.739 0.103 m
+23.739 -0.29 23.775 -0.565 23.856 -0.721 c
+23.945 -0.878 24.091 -0.956 24.297 -0.956 c
+24.503 -0.956 24.654 -0.864 24.753 -0.676 c
+24.753 1.132 l
+24.654 1.326 24.503 1.426 24.297 1.426 c
+24.099 1.426 23.959 1.345 23.871 1.191 c
+23.783 1.043 23.739 0.771 23.739 0.382 c
+h
+27.663 -1.749 -1.043 3.983 re
+26.576 3.263 m
+26.576 3.418 26.623 3.547 26.723 3.645 c
+26.829 3.752 26.965 3.807 27.134 3.807 c
+27.311 3.807 27.446 3.752 27.546 3.645 c
+27.652 3.547 27.708 3.418 27.708 3.263 c
+27.708 3.094 27.652 2.959 27.546 2.851 c
+27.446 2.753 27.311 2.705 27.134 2.705 c
+26.965 2.705 26.829 2.753 26.723 2.851 c
+26.623 2.959 26.576 3.094 26.576 3.263 c
+30.426 1.22 m
+30.089 1.249 l
+29.802 1.249 29.611 1.124 29.516 0.882 c
+29.516 -1.749 l
+28.471 -1.749 l
+28.471 2.234 l
+29.442 2.234 l
+29.471 1.793 l
+29.637 2.135 29.868 2.308 30.162 2.308 c
+30.28 2.308 30.372 2.286 30.441 2.249 c
+h
+32.5 -1.822 m
+31.97 -1.822 31.551 -1.668 31.25 -1.352 c
+30.956 -1.029 30.809 -0.569 30.809 0.029 c
+30.809 0.338 l
+30.809 0.963 30.945 1.448 31.22 1.793 c
+31.492 2.135 31.885 2.308 32.396 2.308 c
+32.896 2.308 33.267 2.146 33.514 1.823 c
+33.767 1.5 33.9 1.022 33.911 0.397 c
+33.911 -0.103 l
+31.837 -0.103 l
+31.856 -0.397 31.918 -0.613 32.029 -0.75 c
+32.146 -0.889 32.327 -0.956 32.573 -0.956 c
+32.915 -0.956 33.205 -0.838 33.44 -0.603 c
+33.852 -1.234 l
+33.723 -1.411 33.535 -1.554 33.293 -1.661 c
+33.047 -1.768 32.782 -1.822 32.5 -1.822 c
+31.853 0.617 m
+32.882 0.617 l
+32.882 0.721 l
+32.882 0.956 32.841 1.132 32.764 1.249 c
+32.694 1.374 32.566 1.44 32.381 1.44 c
+32.205 1.44 32.073 1.371 31.985 1.235 c
+31.904 1.106 31.86 0.9 31.853 0.617 c
+35.939 -0.956 m
+36.233 -0.956 36.383 -0.76 36.394 -0.368 c
+37.364 -0.368 l
+37.364 -0.801 37.233 -1.153 36.968 -1.426 c
+36.703 -1.691 36.365 -1.822 35.953 -1.822 c
+35.442 -1.822 35.049 -1.668 34.777 -1.352 c
+34.513 -1.029 34.374 -0.559 34.366 0.059 c
+34.366 0.382 l
+34.366 1.007 34.498 1.484 34.763 1.808 c
+35.035 2.139 35.432 2.308 35.953 2.308 c
+36.383 2.308 36.726 2.168 36.982 1.897 c
+37.236 1.621 37.364 1.239 37.364 0.75 c
+36.394 0.75 l
+36.394 0.963 36.354 1.132 36.277 1.249 c
+36.207 1.374 36.09 1.44 35.924 1.44 c
+35.748 1.44 35.619 1.374 35.542 1.249 c
+35.461 1.121 35.417 0.871 35.409 0.5 c
+35.409 0.088 l
+35.409 -0.235 35.424 -0.463 35.454 -0.588 c
+35.49 -0.717 35.546 -0.808 35.615 -0.867 c
+35.693 -0.926 35.799 -0.956 35.939 -0.956 c
+39.172 3.204 m
+39.172 2.234 l
+39.702 2.234 l
+39.702 1.44 l
+39.172 1.44 l
+39.172 -0.529 l
+39.172 -0.687 39.191 -0.794 39.232 -0.852 c
+39.28 -0.912 39.363 -0.941 39.481 -0.941 c
+39.588 -0.941 39.672 -0.933 39.731 -0.912 c
+39.731 -1.72 l
+39.555 -1.786 39.363 -1.822 39.158 -1.822 c
+38.482 -1.822 38.137 -1.437 38.129 -0.661 c
+38.129 1.44 l
+37.674 1.44 l
+37.674 2.234 l
+38.129 2.234 l
+38.129 3.204 l
+h
+40.055 0.368 m
+40.055 0.974 40.194 1.448 40.481 1.793 c
+40.764 2.135 41.157 2.308 41.657 2.308 c
+42.164 2.308 42.561 2.135 42.848 1.793 c
+43.13 1.448 43.274 0.974 43.274 0.368 c
+43.274 0.103 l
+43.274 -0.496 43.13 -0.966 42.848 -1.309 c
+42.561 -1.654 42.164 -1.822 41.657 -1.822 c
+41.146 -1.822 40.749 -1.654 40.466 -1.309 c
+40.19 -0.966 40.055 -0.492 40.055 0.118 c
+h
+41.098 0.103 m
+41.098 -0.603 41.282 -0.956 41.657 -0.956 c
+42.01 -0.956 42.201 -0.661 42.23 -0.073 c
+42.23 0.368 l
+42.23 0.728 42.179 1 42.083 1.176 c
+41.984 1.353 41.84 1.44 41.657 1.44 c
+41.48 1.44 41.341 1.353 41.245 1.176 c
+41.146 1 41.098 0.728 41.098 0.368 c
+h
+45.875 1.22 m
+45.537 1.249 l
+45.251 1.249 45.06 1.124 44.965 0.882 c
+44.965 -1.749 l
+43.92 -1.749 l
+43.92 2.234 l
+44.89 2.234 l
+44.92 1.793 l
+45.085 2.135 45.316 2.308 45.611 2.308 c
+45.728 2.308 45.821 2.286 45.89 2.249 c
+h
+47.772 -0.015 m
+48.3 2.234 l
+49.403 2.234 l
+48.095 -2.352 l
+47.897 -3.017 47.529 -3.351 46.993 -3.351 c
+46.864 -3.351 46.721 -3.329 46.567 -3.293 c
+46.567 -2.469 l
+46.684 -2.484 l
+46.849 -2.484 46.97 -2.447 47.051 -2.381 c
+47.128 -2.323 47.191 -2.212 47.242 -2.057 c
+47.316 -1.793 l
+46.17 2.234 l
+47.286 2.234 l
+h
+f
+Q
+q 1 0 0 1 425.5124 175.0022 cm
+0 0 m
+-0.04 0.087 -0.066 0.235 -0.073 0.44 c
+-0.309 0.095 -0.603 -0.073 -0.956 -0.073 c
+-1.319 -0.073 -1.602 0.022 -1.808 0.22 c
+-2.007 0.426 -2.102 0.713 -2.102 1.087 c
+-2.102 1.488 -1.966 1.808 -1.691 2.043 c
+-1.419 2.285 -1.043 2.41 -0.573 2.41 c
+-0.088 2.41 l
+-0.088 2.836 l
+-0.088 3.072 -0.143 3.237 -0.25 3.337 c
+-0.36 3.443 -0.522 3.498 -0.735 3.498 c
+-0.933 3.498 -1.095 3.439 -1.22 3.322 c
+-1.338 3.204 -1.396 3.057 -1.396 2.881 c
+-2.043 2.881 l
+-2.043 3.075 -1.984 3.266 -1.866 3.454 c
+-1.742 3.638 -1.58 3.785 -1.382 3.895 c
+-1.176 4.002 -0.948 4.056 -0.691 4.056 c
+-0.291 4.056 0.015 3.954 0.22 3.748 c
+0.434 3.542 0.548 3.248 0.559 2.866 c
+0.559 0.852 l
+0.559 0.548 0.595 0.283 0.676 0.058 c
+0.676 0 l
+h
+-0.867 0.515 m
+-0.702 0.515 -0.551 0.558 -0.412 0.646 c
+-0.264 0.735 -0.158 0.845 -0.088 0.985 c
+-0.088 1.926 l
+-0.455 1.926 l
+-0.771 1.926 -1.014 1.855 -1.191 1.72 c
+-1.367 1.591 -1.455 1.404 -1.455 1.161 c
+-1.455 0.933 -1.411 0.768 -1.323 0.661 c
+-1.234 0.562 -1.084 0.515 -0.867 0.515 c
+2.175 3.983 m
+2.19 3.542 l
+2.444 3.884 2.767 4.056 3.16 4.056 c
+3.866 4.056 4.222 3.586 4.233 2.645 c
+4.233 0 l
+3.586 0 l
+3.586 2.616 l
+3.586 2.929 3.532 3.149 3.425 3.278 c
+3.314 3.403 3.16 3.468 2.955 3.468 c
+2.797 3.468 2.649 3.414 2.514 3.307 c
+2.385 3.197 2.282 3.061 2.205 2.896 c
+2.205 0 l
+1.558 0 l
+1.558 3.983 l
+h
+5.072 2.175 m
+5.072 2.782 5.182 3.248 5.409 3.572 c
+5.644 3.895 5.972 4.056 6.394 4.056 c
+6.776 4.056 7.074 3.898 7.291 3.586 c
+7.291 5.644 l
+7.938 5.644 l
+7.938 0 l
+7.349 0 l
+7.306 0.426 l
+7.1 0.091 6.795 -0.073 6.394 -0.073 c
+5.982 -0.073 5.659 0.081 5.424 0.397 c
+5.189 0.72 5.072 1.176 5.072 1.764 c
+h
+5.718 1.793 m
+5.718 1.352 5.781 1.022 5.909 0.808 c
+6.045 0.602 6.265 0.5 6.57 0.5 c
+6.894 0.5 7.133 0.661 7.291 0.985 c
+7.291 2.998 l
+7.121 3.31 6.882 3.468 6.57 3.468 c
+6.265 3.468 6.045 3.366 5.909 3.16 c
+5.781 2.954 5.718 2.631 5.718 2.19 c
+h
+12.7 0 m
+12.66 0.087 12.634 0.235 12.627 0.44 c
+12.391 0.095 12.097 -0.073 11.744 -0.073 c
+11.381 -0.073 11.098 0.022 10.892 0.22 c
+10.693 0.426 10.598 0.713 10.598 1.087 c
+10.598 1.488 10.734 1.808 11.009 2.043 c
+11.281 2.285 11.657 2.41 12.127 2.41 c
+12.612 2.41 l
+12.612 2.836 l
+12.612 3.072 12.557 3.237 12.45 3.337 c
+12.34 3.443 12.178 3.498 11.965 3.498 c
+11.767 3.498 11.605 3.439 11.48 3.322 c
+11.362 3.204 11.304 3.057 11.304 2.881 c
+10.657 2.881 l
+10.657 3.075 10.716 3.266 10.834 3.454 c
+10.958 3.638 11.12 3.785 11.318 3.895 c
+11.524 4.002 11.752 4.056 12.009 4.056 c
+12.409 4.056 12.715 3.954 12.92 3.748 c
+13.134 3.542 13.247 3.248 13.259 2.866 c
+13.259 0.852 l
+13.259 0.548 13.295 0.283 13.376 0.058 c
+13.376 0 l
+h
+11.833 0.515 m
+11.998 0.515 12.149 0.558 12.288 0.646 c
+12.436 0.735 12.542 0.845 12.612 0.985 c
+12.612 1.926 l
+12.245 1.926 l
+11.929 1.926 11.686 1.855 11.509 1.72 c
+11.333 1.591 11.245 1.404 11.245 1.161 c
+11.245 0.933 11.289 0.768 11.377 0.661 c
+11.466 0.562 11.616 0.515 11.833 0.515 c
+14.126 2.175 m
+14.126 2.782 14.236 3.248 14.464 3.572 c
+14.699 3.895 15.026 4.056 15.449 4.056 c
+15.831 4.056 16.129 3.898 16.345 3.586 c
+16.345 5.644 l
+16.992 5.644 l
+16.992 0 l
+16.405 0 l
+16.36 0.426 l
+16.154 0.091 15.85 -0.073 15.449 -0.073 c
+15.037 -0.073 14.714 0.081 14.479 0.397 c
+14.244 0.72 14.126 1.176 14.126 1.764 c
+h
+14.772 1.793 m
+14.772 1.352 14.835 1.022 14.963 0.808 c
+15.1 0.602 15.32 0.5 15.625 0.5 c
+15.948 0.5 16.187 0.661 16.345 0.985 c
+16.345 2.998 l
+16.176 3.31 15.937 3.468 15.625 3.468 c
+15.32 3.468 15.1 3.366 14.963 3.16 c
+14.835 2.954 14.772 2.631 14.772 2.19 c
+h
+17.859 2.175 m
+17.859 2.782 17.97 3.248 18.198 3.572 c
+18.433 3.895 18.759 4.056 19.183 4.056 c
+19.565 4.056 19.862 3.898 20.079 3.586 c
+20.079 5.644 l
+20.725 5.644 l
+20.725 0 l
+20.137 0 l
+20.093 0.426 l
+19.888 0.091 19.582 -0.073 19.183 -0.073 c
+18.771 -0.073 18.447 0.081 18.212 0.397 c
+17.977 0.72 17.859 1.176 17.859 1.764 c
+h
+18.506 1.793 m
+18.506 1.352 18.568 1.022 18.697 0.808 c
+18.834 0.602 19.054 0.5 19.359 0.5 c
+19.682 0.5 19.921 0.661 20.079 0.985 c
+20.079 2.998 l
+19.91 3.31 19.671 3.468 19.359 3.468 c
+19.054 3.468 18.834 3.366 18.697 3.16 c
+18.568 2.954 18.506 2.631 18.506 2.19 c
+h
+23.312 2.175 m
+23.312 2.782 23.423 3.248 23.651 3.572 c
+23.886 3.895 24.213 4.056 24.636 4.056 c
+25.018 4.056 25.315 3.898 25.533 3.586 c
+25.533 5.644 l
+26.179 5.644 l
+26.179 0 l
+25.591 0 l
+25.547 0.426 l
+25.342 0.091 25.036 -0.073 24.636 -0.073 c
+24.224 -0.073 23.9 0.081 23.665 0.397 c
+23.43 0.72 23.312 1.176 23.312 1.764 c
+h
+23.96 1.793 m
+23.96 1.352 24.022 1.022 24.151 0.808 c
+24.286 0.602 24.507 0.5 24.812 0.5 c
+25.136 0.5 25.375 0.661 25.533 0.985 c
+25.533 2.998 l
+25.363 3.31 25.124 3.468 24.812 3.468 c
+24.507 3.468 24.286 3.366 24.151 3.16 c
+24.022 2.954 23.96 2.631 23.96 2.19 c
+h
+28.604 -0.073 m
+28.105 -0.073 27.723 0.073 27.458 0.367 c
+27.193 0.661 27.061 1.095 27.061 1.675 c
+27.061 2.146 l
+27.061 2.741 27.185 3.208 27.443 3.542 c
+27.708 3.884 28.068 4.056 28.531 4.056 c
+28.99 4.056 29.332 3.902 29.56 3.601 c
+29.795 3.307 29.916 2.844 29.927 2.219 c
+29.927 1.793 l
+27.708 1.793 l
+27.708 1.705 l
+27.708 1.271 27.785 0.959 27.943 0.764 c
+28.108 0.577 28.34 0.484 28.634 0.484 c
+28.829 0.484 29.001 0.518 29.148 0.588 c
+29.296 0.665 29.431 0.783 29.56 0.941 c
+29.898 0.529 l
+29.612 0.125 29.182 -0.073 28.604 -0.073 c
+28.531 3.498 m
+28.255 3.498 28.053 3.403 27.929 3.219 c
+27.8 3.031 27.726 2.741 27.708 2.352 c
+29.281 2.352 l
+29.281 2.439 l
+29.259 2.822 29.192 3.09 29.074 3.248 c
+28.957 3.414 28.773 3.498 28.531 3.498 c
+31.412 0 -0.647 5.644 re
+33.852 -0.073 m
+33.352 -0.073 32.97 0.073 32.706 0.367 c
+32.44 0.661 32.309 1.095 32.309 1.675 c
+32.309 2.146 l
+32.309 2.741 32.434 3.208 32.691 3.542 c
+32.955 3.884 33.315 4.056 33.778 4.056 c
+34.238 4.056 34.58 3.902 34.807 3.601 c
+35.043 3.307 35.164 2.844 35.175 2.219 c
+35.175 1.793 l
+32.955 1.793 l
+32.955 1.705 l
+32.955 1.271 33.032 0.959 33.19 0.764 c
+33.356 0.577 33.587 0.484 33.882 0.484 c
+34.076 0.484 34.249 0.518 34.395 0.588 c
+34.543 0.665 34.678 0.783 34.807 0.941 c
+35.145 0.529 l
+34.859 0.125 34.429 -0.073 33.852 -0.073 c
+33.778 3.498 m
+33.503 3.498 33.3 3.403 33.176 3.219 c
+33.047 3.031 32.974 2.741 32.955 2.352 c
+34.528 2.352 l
+34.528 2.439 l
+34.506 2.822 34.44 3.09 34.322 3.248 c
+34.204 3.414 34.021 3.498 33.778 3.498 c
+36.806 4.939 m
+36.806 3.983 l
+37.409 3.983 l
+37.409 3.454 l
+36.806 3.454 l
+36.806 0.985 l
+36.806 0.827 36.828 0.709 36.88 0.632 c
+36.939 0.551 37.027 0.515 37.144 0.515 c
+37.233 0.515 37.321 0.529 37.409 0.558 c
+37.409 0 l
+37.262 -0.048 37.107 -0.073 36.953 -0.073 c
+36.696 -0.073 36.502 0.018 36.365 0.205 c
+36.226 0.389 36.16 0.65 36.16 0.985 c
+36.16 3.454 l
+35.557 3.454 l
+35.557 3.983 l
+36.16 3.983 l
+36.16 4.939 l
+h
+38.879 0 -0.646 3.983 re
+38.923 5.026 m
+38.923 4.916 38.894 4.825 38.835 4.748 c
+38.776 4.677 38.68 4.644 38.555 4.644 c
+38.438 4.644 38.343 4.677 38.277 4.748 c
+38.218 4.825 38.188 4.916 38.188 5.026 c
+38.188 5.144 38.218 5.236 38.277 5.306 c
+38.343 5.383 38.438 5.423 38.555 5.423 c
+38.68 5.423 38.776 5.383 38.835 5.306 c
+38.894 5.225 38.923 5.134 38.923 5.026 c
+39.761 2.175 m
+39.761 2.753 39.897 3.208 40.172 3.542 c
+40.456 3.884 40.826 4.056 41.29 4.056 c
+41.749 4.056 42.117 3.888 42.392 3.557 c
+42.675 3.233 42.822 2.786 42.833 2.219 c
+42.833 1.793 l
+42.833 1.224 42.69 0.768 42.407 0.426 c
+42.131 0.091 41.764 -0.073 41.304 -0.073 c
+40.841 -0.073 40.471 0.087 40.187 0.411 c
+39.912 0.742 39.768 1.183 39.761 1.734 c
+h
+40.408 1.793 m
+40.408 1.389 40.485 1.072 40.643 0.837 c
+40.808 0.602 41.028 0.484 41.304 0.484 c
+41.87 0.484 42.164 0.897 42.186 1.72 c
+42.186 2.175 l
+42.186 2.576 42.102 2.896 41.936 3.131 c
+41.778 3.373 41.562 3.498 41.29 3.498 c
+41.025 3.498 40.808 3.373 40.643 3.131 c
+40.485 2.896 40.408 2.576 40.408 2.175 c
+h
+44.288 3.983 m
+44.303 3.542 l
+44.556 3.884 44.88 4.056 45.273 4.056 c
+45.979 4.056 46.335 3.586 46.346 2.645 c
+46.346 0 l
+45.699 0 l
+45.699 2.616 l
+45.699 2.929 45.645 3.149 45.537 3.278 c
+45.427 3.403 45.273 3.468 45.067 3.468 c
+44.909 3.468 44.762 3.414 44.627 3.307 c
+44.498 3.197 44.394 3.061 44.317 2.896 c
+44.317 0 l
+43.671 0 l
+43.671 3.983 l
+h
+49.888 4.939 m
+49.888 3.983 l
+50.491 3.983 l
+50.491 3.454 l
+49.888 3.454 l
+49.888 0.985 l
+49.888 0.827 49.911 0.709 49.962 0.632 c
+50.021 0.551 50.109 0.515 50.227 0.515 c
+50.315 0.515 50.403 0.529 50.491 0.558 c
+50.491 0 l
+50.345 -0.048 50.19 -0.073 50.036 -0.073 c
+49.778 -0.073 49.584 0.018 49.447 0.205 c
+49.308 0.389 49.242 0.65 49.242 0.985 c
+49.242 3.454 l
+48.639 3.454 l
+48.639 3.983 l
+49.242 3.983 l
+49.242 4.939 l
+h
+51.05 2.175 m
+51.05 2.753 51.186 3.208 51.461 3.542 c
+51.744 3.884 52.115 4.056 52.579 4.056 c
+53.038 4.056 53.406 3.888 53.68 3.557 c
+53.964 3.233 54.111 2.786 54.122 2.219 c
+54.122 1.793 l
+54.122 1.224 53.979 0.768 53.696 0.426 c
+53.42 0.091 53.053 -0.073 52.593 -0.073 c
+52.13 -0.073 51.759 0.087 51.476 0.411 c
+51.201 0.742 51.057 1.183 51.05 1.734 c
+h
+51.696 1.793 m
+51.696 1.389 51.774 1.072 51.932 0.837 c
+52.097 0.602 52.317 0.484 52.593 0.484 c
+53.159 0.484 53.453 0.897 53.475 1.72 c
+53.475 2.175 l
+53.475 2.576 53.391 2.896 53.225 3.131 c
+53.067 3.373 52.851 3.498 52.579 3.498 c
+52.314 3.498 52.097 3.373 51.932 3.131 c
+51.774 2.896 51.696 2.576 51.696 2.175 c
+h
+f
+Q
+q 1 0 0 1 483.8532 176.0746 cm
+0 0 m
+0 0.088 -0.044 0.166 -0.133 0.235 c
+-0.221 0.312 -0.408 0.416 -0.691 0.544 c
+-1.125 0.721 -1.422 0.9 -1.588 1.088 c
+-1.746 1.272 -1.823 1.503 -1.823 1.779 c
+-1.823 2.12 -1.702 2.404 -1.455 2.631 c
+-1.202 2.866 -0.864 2.984 -0.441 2.984 c
+-0.011 2.984 0.338 2.87 0.602 2.646 c
+0.867 2.419 0.999 2.117 0.999 1.735 c
+-0.044 1.735 l
+-0.044 2.058 -0.184 2.22 -0.456 2.22 c
+-0.566 2.22 -0.655 2.183 -0.721 2.117 c
+-0.79 2.047 -0.823 1.948 -0.823 1.823 c
+-0.823 1.735 -0.786 1.654 -0.706 1.588 c
+-0.628 1.529 -0.449 1.434 -0.162 1.309 c
+0.268 1.151 0.565 0.975 0.735 0.779 c
+0.911 0.592 0.999 0.342 0.999 0.03 c
+0.999 -0.323 0.867 -0.61 0.602 -0.823 c
+0.338 -1.04 -0.011 -1.146 -0.441 -1.146 c
+-0.736 -1.146 -0.996 -1.091 -1.22 -0.985 c
+-1.448 -0.867 -1.625 -0.706 -1.75 -0.5 c
+-1.867 -0.294 -1.926 -0.073 -1.926 0.162 c
+-0.941 0.162 l
+-0.941 -0.025 -0.904 -0.162 -0.823 -0.249 c
+-0.736 -0.338 -0.603 -0.382 -0.427 -0.382 c
+-0.144 -0.382 0 -0.257 0 0 c
+2.866 3.881 m
+2.866 2.911 l
+3.395 2.911 l
+3.395 2.117 l
+2.866 2.117 l
+2.866 0.148 l
+2.866 -0.01 2.884 -0.118 2.925 -0.176 c
+2.973 -0.235 3.057 -0.264 3.175 -0.264 c
+3.281 -0.264 3.366 -0.257 3.424 -0.235 c
+3.424 -1.043 l
+3.248 -1.109 3.057 -1.146 2.851 -1.146 c
+2.175 -1.146 1.83 -0.76 1.822 0.015 c
+1.822 2.117 l
+1.367 2.117 l
+1.367 2.911 l
+1.822 2.911 l
+1.822 3.881 l
+h
+5.85 -1.072 m
+5.82 -1.014 5.791 -0.911 5.762 -0.764 c
+5.574 -1.022 5.325 -1.146 5.012 -1.146 c
+4.677 -1.146 4.398 -1.04 4.174 -0.823 c
+3.958 -0.598 3.85 -0.309 3.85 0.044 c
+3.85 0.456 3.983 0.772 4.247 1 c
+4.512 1.235 4.895 1.353 5.394 1.353 c
+5.718 1.353 l
+5.718 1.676 l
+5.718 1.852 5.681 1.974 5.614 2.043 c
+5.556 2.12 5.468 2.161 5.35 2.161 c
+5.093 2.161 4.968 2.007 4.968 1.706 c
+3.925 1.706 l
+3.925 2.076 4.06 2.382 4.336 2.617 c
+4.608 2.859 4.957 2.984 5.379 2.984 c
+5.82 2.984 6.158 2.866 6.393 2.631 c
+6.636 2.404 6.761 2.08 6.761 1.661 c
+6.761 -0.205 l
+6.761 -0.551 6.809 -0.819 6.908 -1.014 c
+6.908 -1.072 l
+h
+5.247 -0.323 m
+5.354 -0.323 5.446 -0.305 5.527 -0.264 c
+5.614 -0.216 5.677 -0.158 5.718 -0.087 c
+5.718 0.736 l
+5.468 0.736 l
+5.292 0.736 5.148 0.676 5.041 0.559 c
+4.943 0.449 4.895 0.302 4.895 0.118 c
+4.895 -0.176 5.012 -0.323 5.247 -0.323 c
+7.378 1.044 m
+7.378 1.691 7.496 2.176 7.731 2.5 c
+7.966 2.822 8.297 2.984 8.731 2.984 c
+9.084 2.984 9.356 2.841 9.554 2.558 c
+9.598 2.911 l
+10.539 2.911 l
+10.539 -1.072 l
+10.539 -1.579 10.395 -1.969 10.113 -2.234 c
+9.826 -2.506 9.422 -2.645 8.893 -2.645 c
+8.665 -2.645 8.43 -2.601 8.187 -2.514 c
+7.952 -2.425 7.775 -2.311 7.658 -2.175 c
+8.01 -1.455 l
+8.106 -1.562 8.235 -1.646 8.393 -1.705 c
+8.548 -1.77 8.694 -1.808 8.834 -1.808 c
+9.069 -1.808 9.234 -1.749 9.334 -1.631 c
+9.44 -1.521 9.495 -1.344 9.495 -1.103 c
+9.495 -0.75 l
+9.296 -1.014 9.04 -1.146 8.716 -1.146 c
+8.294 -1.146 7.966 -0.985 7.731 -0.661 c
+7.503 -0.33 7.386 0.14 7.378 0.75 c
+h
+8.422 0.779 m
+8.422 0.405 8.47 0.136 8.569 -0.029 c
+8.665 -0.198 8.819 -0.279 9.025 -0.279 c
+9.238 -0.279 9.396 -0.201 9.495 -0.044 c
+9.495 1.852 l
+9.385 2.018 9.231 2.103 9.025 2.103 c
+8.819 2.103 8.665 2.018 8.569 1.852 c
+8.47 1.683 8.422 1.415 8.422 1.044 c
+h
+12.391 -1.072 -1.044 3.983 re
+11.303 3.94 m
+11.303 4.094 11.351 4.223 11.451 4.322 c
+11.557 4.428 11.692 4.484 11.862 4.484 c
+12.038 4.484 12.174 4.428 12.273 4.322 c
+12.38 4.223 12.435 4.094 12.435 3.94 c
+12.435 3.77 12.38 3.635 12.273 3.528 c
+12.174 3.429 12.038 3.381 11.862 3.381 c
+11.692 3.381 11.557 3.429 11.451 3.528 c
+11.351 3.635 11.303 3.77 11.303 3.94 c
+14.154 2.911 m
+14.184 2.514 l
+14.42 2.826 14.721 2.984 15.095 2.984 c
+15.779 2.984 16.132 2.503 16.154 1.544 c
+16.154 -1.072 l
+15.11 -1.072 l
+15.11 1.47 l
+15.11 1.694 15.073 1.856 15.008 1.955 c
+14.938 2.051 14.82 2.103 14.655 2.103 c
+14.468 2.103 14.32 2.007 14.214 1.823 c
+14.214 -1.072 l
+13.17 -1.072 l
+13.17 2.911 l
+h
+16.772 1.044 m
+16.772 1.691 16.889 2.176 17.124 2.5 c
+17.359 2.822 17.69 2.984 18.123 2.984 c
+18.476 2.984 18.748 2.841 18.947 2.558 c
+18.991 2.911 l
+19.931 2.911 l
+19.931 -1.072 l
+19.931 -1.579 19.788 -1.969 19.505 -2.234 c
+19.218 -2.506 18.815 -2.645 18.285 -2.645 c
+18.057 -2.645 17.822 -2.601 17.58 -2.514 c
+17.344 -2.425 17.168 -2.311 17.051 -2.175 c
+17.404 -1.455 l
+17.499 -1.562 17.628 -1.646 17.786 -1.705 c
+17.94 -1.77 18.087 -1.808 18.227 -1.808 c
+18.462 -1.808 18.627 -1.749 18.726 -1.631 c
+18.833 -1.521 18.888 -1.344 18.888 -1.103 c
+18.888 -0.75 l
+18.69 -1.014 18.432 -1.146 18.109 -1.146 c
+17.686 -1.146 17.359 -0.985 17.124 -0.661 c
+16.897 -0.33 16.779 0.14 16.772 0.75 c
+h
+17.815 0.779 m
+17.815 0.405 17.863 0.136 17.962 -0.029 c
+18.057 -0.198 18.212 -0.279 18.418 -0.279 c
+18.63 -0.279 18.788 -0.201 18.888 -0.044 c
+18.888 1.852 l
+18.778 2.018 18.623 2.103 18.418 2.103 c
+18.212 2.103 18.057 2.018 17.962 1.852 c
+17.863 1.683 17.815 1.415 17.815 1.044 c
+h
+24.312 -1.072 m
+24.282 -1.014 24.253 -0.911 24.224 -0.764 c
+24.036 -1.022 23.787 -1.146 23.474 -1.146 c
+23.139 -1.146 22.86 -1.04 22.636 -0.823 c
+22.42 -0.598 22.312 -0.309 22.312 0.044 c
+22.312 0.456 22.445 0.772 22.709 1 c
+22.975 1.235 23.357 1.353 23.856 1.353 c
+24.18 1.353 l
+24.18 1.676 l
+24.18 1.852 24.143 1.974 24.076 2.043 c
+24.018 2.12 23.93 2.161 23.812 2.161 c
+23.555 2.161 23.43 2.007 23.43 1.706 c
+22.386 1.706 l
+22.386 2.076 22.522 2.382 22.798 2.617 c
+23.07 2.859 23.419 2.984 23.841 2.984 c
+24.282 2.984 24.621 2.866 24.856 2.631 c
+25.098 2.404 25.223 2.08 25.223 1.661 c
+25.223 -0.205 l
+25.223 -0.551 25.271 -0.819 25.37 -1.014 c
+25.37 -1.072 l
+h
+23.709 -0.323 m
+23.816 -0.323 23.908 -0.305 23.989 -0.264 c
+24.076 -0.216 24.139 -0.158 24.18 -0.087 c
+24.18 0.736 l
+23.93 0.736 l
+23.754 0.736 23.61 0.676 23.503 0.559 c
+23.405 0.449 23.357 0.302 23.357 0.118 c
+23.357 -0.176 23.474 -0.323 23.709 -0.323 c
+27.928 1.897 m
+27.59 1.926 l
+27.303 1.926 27.112 1.801 27.016 1.559 c
+27.016 -1.072 l
+25.973 -1.072 l
+25.973 2.911 l
+26.943 2.911 l
+26.973 2.469 l
+27.137 2.812 27.369 2.984 27.663 2.984 c
+27.781 2.984 27.873 2.962 27.943 2.926 c
+h
+30 -1.146 m
+29.471 -1.146 29.052 -0.992 28.751 -0.675 c
+28.457 -0.353 28.31 0.107 28.31 0.706 c
+28.31 1.014 l
+28.31 1.64 28.446 2.124 28.722 2.469 c
+28.994 2.812 29.387 2.984 29.898 2.984 c
+30.397 2.984 30.769 2.822 31.014 2.5 c
+31.268 2.176 31.401 1.698 31.411 1.073 c
+31.411 0.574 l
+29.339 0.574 l
+29.358 0.279 29.42 0.063 29.53 -0.073 c
+29.647 -0.213 29.828 -0.279 30.074 -0.279 c
+30.416 -0.279 30.706 -0.162 30.941 0.073 c
+31.353 -0.558 l
+31.224 -0.735 31.037 -0.878 30.794 -0.985 c
+30.548 -1.091 30.283 -1.146 30 -1.146 c
+29.354 1.294 m
+30.382 1.294 l
+30.382 1.397 l
+30.382 1.632 30.343 1.808 30.265 1.926 c
+30.195 2.051 30.067 2.117 29.883 2.117 c
+29.707 2.117 29.574 2.047 29.486 1.912 c
+29.405 1.783 29.361 1.577 29.354 1.294 c
+33.881 -1.072 m
+33.852 -1.014 33.822 -0.911 33.793 -0.764 c
+33.605 -1.022 33.356 -1.146 33.043 -1.146 c
+32.709 -1.146 32.429 -1.04 32.205 -0.823 c
+31.989 -0.598 31.882 -0.309 31.882 0.044 c
+31.882 0.456 32.014 0.772 32.279 1 c
+32.543 1.235 32.926 1.353 33.425 1.353 c
+33.749 1.353 l
+33.749 1.676 l
+33.749 1.852 33.712 1.974 33.646 2.043 c
+33.587 2.12 33.499 2.161 33.381 2.161 c
+33.124 2.161 32.999 2.007 32.999 1.706 c
+31.955 1.706 l
+31.955 2.076 32.091 2.382 32.367 2.617 c
+32.639 2.859 32.988 2.984 33.41 2.984 c
+33.852 2.984 34.189 2.866 34.424 2.631 c
+34.667 2.404 34.792 2.08 34.792 1.661 c
+34.792 -0.205 l
+34.792 -0.551 34.84 -0.819 34.939 -1.014 c
+34.939 -1.072 l
+h
+33.279 -0.323 m
+33.385 -0.323 33.477 -0.305 33.558 -0.264 c
+33.646 -0.216 33.709 -0.158 33.749 -0.087 c
+33.749 0.736 l
+33.499 0.736 l
+33.323 0.736 33.179 0.676 33.073 0.559 c
+32.973 0.449 32.926 0.302 32.926 0.118 c
+32.926 -0.176 33.043 -0.323 33.279 -0.323 c
+f
+Q
+q 1 0 0 1 519.5421 175.3549 cm
+0 0 m
+0 0.118 0.033 0.213 0.103 0.294 c
+0.169 0.371 0.272 0.411 0.412 0.411 c
+0.559 0.411 0.665 0.371 0.735 0.294 c
+0.812 0.213 0.852 0.118 0.852 0 c
+0.852 -0.11 0.812 -0.202 0.735 -0.279 c
+0.665 -0.357 0.559 -0.397 0.412 -0.397 c
+0.272 -0.397 0.169 -0.357 0.103 -0.279 c
+0.033 -0.202 0 -0.11 0 0 c
+f
+Q
+0.793 0.801 0.129 0.016 k
+535.667 282.996 238.665 -21.457 re
+f
+0 0 0 0 k
+q 1 0 0 1 629.4581 271.0489 cm
+0 0 m
+0.794 0 l
+0.794 -1.514 l
+0 -1.514 l
+0 -3.542 l
+-1.823 -3.542 l
+-1.823 -1.514 l
+-4.924 -1.514 l
+-4.998 -0.338 l
+-1.823 5.821 l
+0 5.821 l
+h
+-3.234 0 m
+-1.823 0 l
+-1.823 3.132 l
+-1.852 3.057 l
+h
+2.253 -2.616 m
+2.253 -2.322 2.348 -2.083 2.547 -1.896 c
+2.741 -1.712 2.995 -1.616 3.31 -1.616 c
+3.612 -1.616 3.862 -1.712 4.06 -1.896 c
+4.266 -2.083 4.37 -2.322 4.37 -2.616 c
+4.37 -2.921 4.266 -3.167 4.06 -3.351 c
+3.862 -3.528 3.612 -3.615 3.31 -3.615 c
+3.006 -3.615 2.753 -3.524 2.547 -3.336 c
+2.348 -3.152 2.253 -2.91 2.253 -2.616 c
+15.621 -2.484 m
+15.258 -2.877 14.813 -3.175 14.284 -3.38 c
+13.755 -3.575 13.174 -3.675 12.549 -3.675 c
+11.469 -3.675 10.631 -3.343 10.036 -2.675 c
+9.437 -2.009 9.132 -1.04 9.124 0.235 c
+9.124 1.926 l
+9.124 3.219 9.404 4.212 9.962 4.91 c
+10.528 5.604 11.351 5.954 12.432 5.954 c
+13.45 5.954 14.214 5.696 14.724 5.189 c
+15.243 4.69 15.54 3.903 15.621 2.837 c
+13.784 2.837 l
+13.733 3.433 13.612 3.84 13.417 4.057 c
+13.218 4.27 12.91 4.381 12.49 4.381 c
+11.979 4.381 11.609 4.193 11.374 3.822 c
+11.146 3.447 11.028 2.856 11.021 2.043 c
+11.021 0.339 l
+11.021 -0.514 11.146 -1.139 11.403 -1.529 c
+11.657 -1.911 12.072 -2.102 12.652 -2.102 c
+13.024 -2.102 13.328 -2.028 13.564 -1.882 c
+13.725 -1.764 l
+13.725 -0.043 l
+12.403 -0.043 l
+12.403 1.382 l
+15.621 1.382 l
+h
+19.179 -3.542 -1.896 9.363 re
+26.759 4.248 m
+24.438 4.248 l
+24.438 -3.542 l
+22.541 -3.542 l
+22.541 4.248 l
+20.263 4.248 l
+20.263 5.821 l
+26.759 5.821 l
+h
+30.769 -3.542 m
+30.769 5.821 l
+33.664 5.821 l
+34.642 5.821 35.388 5.601 35.899 5.16 c
+36.406 4.726 36.663 4.09 36.663 3.249 c
+36.663 2.779 36.552 2.371 36.34 2.029 c
+36.134 1.683 35.844 1.434 35.472 1.279 c
+35.891 1.151 36.215 0.904 36.442 0.545 c
+36.678 0.192 36.795 -0.257 36.795 -0.793 c
+36.795 -1.697 36.546 -2.381 36.045 -2.851 c
+35.546 -3.314 34.819 -3.542 33.87 -3.542 c
+h
+32.665 0.53 m
+32.665 -1.969 l
+33.87 -1.969 l
+34.212 -1.969 34.473 -1.866 34.649 -1.66 c
+34.825 -1.448 34.914 -1.146 34.914 -0.764 c
+34.914 0.077 34.605 0.507 33.988 0.53 c
+h
+32.665 1.912 m
+33.649 1.912 l
+34.385 1.912 34.752 2.293 34.752 3.057 c
+34.752 3.477 34.664 3.782 34.487 3.969 c
+34.318 4.152 34.046 4.248 33.664 4.248 c
+32.665 4.248 l
+h
+41.198 -0.118 m
+40.257 -0.118 l
+40.257 -3.542 l
+38.376 -3.542 l
+38.376 5.821 l
+41.389 5.821 l
+42.337 5.821 43.068 5.575 43.579 5.087 c
+44.097 4.594 44.358 3.899 44.358 2.999 c
+44.358 1.754 43.906 0.882 43.006 0.383 c
+44.637 -3.453 l
+44.637 -3.542 l
+42.609 -3.542 l
+h
+40.257 1.455 m
+41.33 1.455 l
+41.712 1.455 41.996 1.577 42.183 1.823 c
+42.366 2.076 42.462 2.415 42.462 2.837 c
+42.462 3.778 42.098 4.248 41.374 4.248 c
+40.257 4.248 l
+h
+50.345 -1.631 m
+47.772 -1.631 l
+47.272 -3.542 l
+45.273 -3.542 l
+48.198 5.821 l
+49.917 5.821 l
+52.872 -3.542 l
+50.844 -3.542 l
+h
+48.184 -0.043 m
+49.933 -0.043 l
+49.051 3.293 l
+h
+60.527 -3.542 m
+58.631 -3.542 l
+55.868 2.602 l
+55.868 -3.542 l
+53.971 -3.542 l
+53.971 5.821 l
+55.868 5.821 l
+58.631 -0.323 l
+58.631 5.821 l
+60.527 5.821 l
+h
+68.63 -0.426 m
+68.578 -1.495 68.277 -2.304 67.718 -2.851 c
+67.167 -3.403 66.395 -3.675 65.396 -3.675 c
+64.327 -3.675 63.507 -3.329 62.941 -2.63 c
+62.382 -1.936 62.104 -0.941 62.104 0.353 c
+62.104 1.926 l
+62.104 3.219 62.39 4.212 62.97 4.91 c
+63.558 5.604 64.371 5.954 65.411 5.954 c
+66.428 5.954 67.204 5.663 67.733 5.087 c
+68.262 4.516 68.564 3.697 68.645 2.631 c
+66.748 2.631 l
+66.727 3.296 66.623 3.753 66.44 3.998 c
+66.253 4.252 65.91 4.381 65.411 4.381 c
+64.911 4.381 64.551 4.204 64.338 3.851 c
+64.132 3.499 64.018 2.914 63.999 2.103 c
+63.999 0.339 l
+63.999 -0.595 64.103 -1.234 64.308 -1.587 c
+64.522 -1.932 64.886 -2.102 65.396 -2.102 c
+65.885 -2.102 66.223 -1.984 66.411 -1.749 c
+66.605 -1.506 66.712 -1.065 66.733 -0.426 c
+h
+76.578 -3.542 m
+74.697 -3.542 l
+74.697 0.47 l
+71.904 0.47 l
+71.904 -3.542 l
+70.008 -3.542 l
+70.008 5.821 l
+71.904 5.821 l
+71.904 2.029 l
+74.697 2.029 l
+74.697 5.821 l
+76.578 5.821 l
+h
+80.297 -3.542 -1.896 9.363 re
+88.547 -3.542 m
+86.651 -3.542 l
+83.888 2.602 l
+83.888 -3.542 l
+81.991 -3.542 l
+81.991 5.821 l
+83.888 5.821 l
+86.651 -0.323 l
+86.651 5.821 l
+88.547 5.821 l
+h
+96.665 -2.484 m
+96.301 -2.877 95.857 -3.175 95.327 -3.38 c
+94.797 -3.575 94.217 -3.675 93.592 -3.675 c
+92.512 -3.675 91.674 -3.343 91.079 -2.675 c
+90.48 -2.009 90.175 -1.04 90.168 0.235 c
+90.168 1.926 l
+90.168 3.219 90.447 4.212 91.005 4.91 c
+91.572 5.604 92.395 5.954 93.475 5.954 c
+94.493 5.954 95.257 5.696 95.768 5.189 c
+96.287 4.69 96.584 3.903 96.665 2.837 c
+94.827 2.837 l
+94.776 3.433 94.654 3.84 94.46 4.057 c
+94.261 4.27 93.953 4.381 93.534 4.381 c
+93.023 4.381 92.652 4.193 92.416 3.822 c
+92.189 3.447 92.071 2.856 92.064 2.043 c
+92.064 0.339 l
+92.064 -0.514 92.189 -1.139 92.445 -1.529 c
+92.699 -1.911 93.114 -2.102 93.696 -2.102 c
+94.066 -2.102 94.371 -2.028 94.606 -1.882 c
+94.768 -1.764 l
+94.768 -0.043 l
+93.445 -0.043 l
+93.445 1.382 l
+96.665 1.382 l
+h
+103.83 5.821 m
+105.609 -0.955 l
+107.358 5.821 l
+109.828 5.821 l
+109.828 -3.542 l
+107.931 -3.542 l
+107.931 -1.014 l
+108.108 2.897 l
+106.241 -3.542 l
+104.948 -3.542 l
+103.081 2.897 l
+103.257 -1.014 l
+103.257 -3.542 l
+101.361 -3.542 l
+101.361 5.821 l
+h
+118.225 0.294 m
+118.225 -0.962 117.924 -1.936 117.328 -2.63 c
+116.729 -3.329 115.906 -3.675 114.859 -3.675 c
+113.808 -3.675 112.981 -3.333 112.374 -2.645 c
+111.775 -1.951 111.47 -0.984 111.463 0.25 c
+111.463 1.852 l
+111.463 3.135 111.761 4.138 112.359 4.865 c
+112.955 5.59 113.785 5.954 114.844 5.954 c
+115.88 5.954 116.7 5.594 117.298 4.881 c
+117.905 4.175 118.213 3.179 118.225 1.897 c
+h
+116.328 1.867 m
+116.328 2.708 116.203 3.337 115.961 3.749 c
+115.726 4.16 115.351 4.366 114.844 4.366 c
+114.344 4.366 113.969 4.164 113.727 3.763 c
+113.492 3.37 113.367 2.771 113.359 1.97 c
+113.359 0.294 l
+113.359 -0.521 113.48 -1.124 113.727 -1.514 c
+113.969 -1.907 114.348 -2.102 114.859 -2.102 c
+115.347 -2.102 115.711 -1.911 115.946 -1.529 c
+116.189 -1.146 116.318 -0.558 116.328 0.235 c
+h
+119.801 -3.542 m
+119.801 5.821 l
+122.285 5.821 l
+123.373 5.821 124.24 5.472 124.887 4.778 c
+125.541 4.079 125.876 3.132 125.886 1.926 c
+125.886 0.412 l
+125.886 -0.823 125.563 -1.793 124.916 -2.499 c
+124.27 -3.197 123.373 -3.542 122.227 -3.542 c
+h
+121.697 4.248 m
+121.697 -1.969 l
+122.256 -1.969 l
+122.892 -1.969 123.336 -1.804 123.593 -1.469 c
+123.846 -1.139 123.979 -0.565 123.99 0.25 c
+123.99 1.867 l
+123.99 2.749 123.865 3.359 123.623 3.705 c
+123.387 4.046 122.976 4.227 122.388 4.248 c
+h
+132.284 0.515 m
+129.344 0.515 l
+129.344 -1.969 l
+132.828 -1.969 l
+132.828 -3.542 l
+127.449 -3.542 l
+127.449 5.821 l
+132.814 5.821 l
+132.814 4.248 l
+129.344 4.248 l
+129.344 2.029 l
+132.284 2.029 l
+h
+135.985 -1.969 m
+139.307 -1.969 l
+139.307 -3.542 l
+134.088 -3.542 l
+134.088 5.821 l
+135.985 5.821 l
+h
+f
+Q
+0.113 0.082 0.09 0 k
+535.667 252.694 238.665 -12.895 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 540.8555 245.8587 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.088 -0.5 c
+-0.147 -0.646 -0.242 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.147 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.358 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.69 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.141 1.278 -3.218 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.218 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.042 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.201 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.205 c
+-0.756 1.147 -0.595 1.066 -0.455 0.97 c
+-0.319 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.318 2.385 -2.366 2.337 c
+-2.406 2.296 -2.436 2.249 -2.454 2.19 c
+-2.476 2.132 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.2 1.558 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.102 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.52 -2.484 5.403 -2.396 c
+5.285 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.856 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.753 5.964 -1.86 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.073 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.214 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.411 4.888 -0.206 c
+4.836 0.008 4.815 0.243 4.815 0.5 c
+4.815 0.771 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.631 5.137 1.779 c
+5.245 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.189 2.263 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.179 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.866 7.107 1.918 7.107 1.97 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.13 2.165 7.14 2.198 7.151 2.219 c
+8.004 2.219 l
+7.992 2.138 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.872 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.499 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.5 6.729 1.558 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.226 1.621 6.137 1.573 c
+6.056 1.532 5.991 1.463 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.301 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.675 re
+10.124 2.837 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.219 l
+13.644 2.219 l
+13.924 3.117 l
+14.498 3.117 l
+14.498 2.219 l
+15.732 2.219 l
+15.732 1.602 l
+14.498 1.602 l
+14.498 -0.103 l
+14.498 -0.324 l
+14.504 -0.393 14.527 -0.455 14.556 -0.515 c
+14.593 -0.566 14.648 -0.61 14.718 -0.646 c
+14.795 -0.676 14.909 -0.69 15.056 -0.69 c
+15.192 -0.69 15.327 -0.687 15.468 -0.676 c
+15.603 -0.658 15.736 -0.632 15.865 -0.603 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.231 15.629 -1.249 c
+15.549 -1.261 15.471 -1.268 15.394 -1.278 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.042 -1.301 14.942 -1.309 14.836 -1.309 c
+14.648 -1.309 14.486 -1.294 14.35 -1.264 c
+14.222 -1.228 14.107 -1.183 14.012 -1.132 c
+13.924 -1.084 13.85 -1.025 13.792 -0.956 c
+13.733 -0.879 13.689 -0.801 13.66 -0.721 c
+13.63 -0.632 13.608 -0.544 13.6 -0.455 c
+13.59 -0.36 13.586 -0.264 13.586 -0.176 c
+h
+21.12 -1.264 m
+21.12 -0.97 l
+21.126 -0.834 21.134 -0.676 21.134 -0.5 c
+21.134 3.513 l
+22.045 3.513 l
+22.045 2.234 l
+22.045 2.072 l
+22.045 1.897 l
+22.045 1.845 22.038 1.801 22.03 1.764 c
+22.03 1.675 l
+22.045 1.675 l
+22.093 1.783 22.155 1.874 22.236 1.955 c
+22.313 2.032 22.398 2.095 22.487 2.146 c
+22.574 2.194 22.666 2.227 22.766 2.249 c
+22.861 2.267 22.961 2.278 23.059 2.278 c
+23.273 2.278 23.46 2.234 23.618 2.146 c
+23.773 2.058 23.901 1.929 24 1.764 c
+24.106 1.606 24.184 1.415 24.235 1.191 c
+24.283 0.974 24.309 0.735 24.309 0.47 c
+24.309 0.214 24.28 -0.025 24.22 -0.25 c
+24.162 -0.467 24.077 -0.658 23.971 -0.823 c
+23.861 -0.981 23.728 -1.103 23.574 -1.191 c
+23.416 -1.278 23.236 -1.323 23.03 -1.323 c
+22.931 -1.323 22.832 -1.311 22.736 -1.294 c
+22.648 -1.272 22.56 -1.242 22.471 -1.191 c
+22.383 -1.132 22.302 -1.066 22.236 -0.985 c
+22.167 -0.908 22.104 -0.808 22.045 -0.69 c
+22.03 -0.69 l
+22.03 -0.852 l
+22.03 -0.912 22.024 -0.97 22.016 -1.029 c
+22.016 -1.08 22.009 -1.128 22.001 -1.176 c
+22.001 -1.216 21.994 -1.246 21.986 -1.264 c
+h
+22.03 0.5 m
+22.03 0.264 22.049 0.066 22.09 -0.088 c
+22.137 -0.246 22.196 -0.368 22.265 -0.455 c
+22.332 -0.544 22.406 -0.61 22.487 -0.646 c
+22.564 -0.687 22.641 -0.706 22.722 -0.706 c
+22.927 -0.706 23.082 -0.61 23.192 -0.411 c
+23.31 -0.216 23.368 0.077 23.368 0.47 c
+23.368 0.684 23.346 0.867 23.31 1.014 c
+23.28 1.168 23.236 1.294 23.177 1.382 c
+23.125 1.477 23.059 1.55 22.971 1.602 c
+22.89 1.65 22.803 1.675 22.707 1.675 c
+22.626 1.675 22.549 1.654 22.471 1.617 c
+22.391 1.577 22.317 1.514 22.251 1.426 c
+22.192 1.338 22.137 1.213 22.09 1.058 c
+22.049 0.912 22.03 0.724 22.03 0.5 c
+28.193 1.47 m
+28.094 1.477 27.991 1.488 27.884 1.5 c
+27.774 1.517 27.653 1.529 27.517 1.529 c
+27.341 1.529 27.183 1.488 27.046 1.411 c
+26.907 1.342 26.789 1.242 26.693 1.118 c
+26.606 0.989 26.535 0.842 26.488 0.676 c
+26.448 0.507 26.429 0.331 26.429 0.147 c
+26.429 -1.264 l
+25.533 -1.264 l
+25.533 0.985 l
+25.533 1.11 25.521 1.235 25.503 1.353 c
+25.492 1.477 25.477 1.595 25.459 1.706 c
+25.448 1.823 25.434 1.918 25.415 1.999 c
+25.393 2.088 25.375 2.161 25.356 2.219 c
+26.238 2.219 l
+26.246 2.168 26.257 2.117 26.267 2.058 c
+26.286 1.999 26.3 1.933 26.312 1.866 c
+26.33 1.808 26.344 1.742 26.356 1.675 c
+26.363 1.606 26.375 1.544 26.385 1.484 c
+26.4 1.484 l
+26.437 1.602 26.488 1.708 26.547 1.808 c
+26.613 1.903 26.693 1.988 26.782 2.058 c
+26.87 2.124 26.973 2.179 27.09 2.219 c
+27.216 2.256 27.362 2.278 27.532 2.278 c
+27.657 2.278 27.774 2.271 27.884 2.263 c
+28.002 2.253 28.105 2.238 28.193 2.219 c
+h
+30.196 -1.323 m
+30.026 -1.323 29.876 -1.301 29.741 -1.264 c
+29.612 -1.216 29.498 -1.147 29.402 -1.058 c
+29.314 -0.97 29.244 -0.864 29.197 -0.735 c
+29.145 -0.599 29.122 -0.449 29.122 -0.279 c
+29.122 -0.073 29.156 0.096 29.226 0.235 c
+29.292 0.382 29.388 0.492 29.505 0.573 c
+29.63 0.661 29.773 0.724 29.932 0.765 c
+30.097 0.802 30.273 0.827 30.46 0.838 c
+31.181 0.852 l
+31.181 1.029 l
+31.181 1.147 31.169 1.249 31.152 1.338 c
+31.129 1.426 31.096 1.492 31.048 1.544 c
+31.008 1.602 30.961 1.639 30.901 1.661 c
+30.843 1.679 30.776 1.691 30.71 1.691 c
+30.641 1.691 30.578 1.679 30.519 1.661 c
+30.468 1.65 30.42 1.625 30.373 1.588 c
+30.332 1.558 30.298 1.507 30.269 1.44 c
+30.248 1.382 30.233 1.301 30.225 1.205 c
+29.284 1.249 l
+29.314 1.396 29.358 1.532 29.417 1.661 c
+29.483 1.786 29.579 1.897 29.696 1.984 c
+29.814 2.08 29.953 2.153 30.122 2.205 c
+30.298 2.253 30.504 2.278 30.74 2.278 c
+31.181 2.278 31.511 2.168 31.74 1.955 c
+31.975 1.749 32.092 1.44 32.092 1.029 c
+32.092 -0.235 l
+32.092 -0.455 l
+32.099 -0.515 32.114 -0.569 32.137 -0.617 c
+32.154 -0.658 32.184 -0.69 32.224 -0.721 c
+32.261 -0.742 32.313 -0.75 32.372 -0.75 c
+32.438 -0.75 32.507 -0.746 32.577 -0.735 c
+32.577 -1.22 l
+32.519 -1.231 32.463 -1.242 32.415 -1.249 c
+32.375 -1.261 32.334 -1.268 32.297 -1.278 c
+32.257 -1.286 32.214 -1.294 32.166 -1.294 c
+32.114 -1.301 32.056 -1.309 31.989 -1.309 c
+31.761 -1.309 31.596 -1.257 31.489 -1.147 c
+31.379 -1.029 31.316 -0.864 31.298 -0.646 c
+31.283 -0.646 l
+31.214 -0.757 31.144 -0.852 31.078 -0.941 c
+31.008 -1.022 30.931 -1.087 30.843 -1.147 c
+30.755 -1.205 30.655 -1.249 30.549 -1.278 c
+30.45 -1.309 30.332 -1.323 30.196 -1.323 c
+31.181 0.353 m
+30.755 0.338 l
+30.655 0.338 30.564 0.331 30.475 0.324 c
+30.394 0.312 30.328 0.287 30.269 0.25 c
+30.211 0.21 30.159 0.151 30.122 0.073 c
+30.082 0.004 30.063 -0.088 30.063 -0.206 c
+30.063 -0.374 30.097 -0.496 30.167 -0.573 c
+30.233 -0.654 30.332 -0.69 30.46 -0.69 c
+30.567 -0.69 30.666 -0.669 30.755 -0.617 c
+30.85 -0.569 30.931 -0.507 30.99 -0.426 c
+31.056 -0.349 31.107 -0.261 31.137 -0.162 c
+31.166 -0.055 31.181 0.059 31.181 0.177 c
+h
+35.495 -1.264 m
+35.495 0.721 l
+35.495 1.022 35.451 1.242 35.362 1.382 c
+35.281 1.529 35.146 1.602 34.951 1.602 c
+34.841 1.602 34.738 1.577 34.643 1.529 c
+34.554 1.477 34.473 1.411 34.408 1.323 c
+34.348 1.235 34.297 1.124 34.26 1 c
+34.231 0.882 34.216 0.75 34.216 0.603 c
+34.216 -1.264 l
+33.305 -1.264 l
+33.305 1.44 l
+33.305 1.661 l
+33.305 1.749 33.297 1.826 33.29 1.897 c
+33.29 2.088 l
+33.29 2.219 l
+34.142 2.219 l
+34.15 2.19 34.157 2.146 34.157 2.088 c
+34.157 1.897 l
+34.165 1.826 34.172 1.756 34.172 1.691 c
+34.179 1.621 34.186 1.565 34.186 1.529 c
+34.202 1.529 l
+34.319 1.793 34.47 1.984 34.657 2.102 c
+34.841 2.219 35.061 2.278 35.318 2.278 c
+35.503 2.278 35.664 2.249 35.804 2.19 c
+35.939 2.132 36.054 2.043 36.141 1.926 c
+36.23 1.808 36.293 1.665 36.332 1.5 c
+36.38 1.342 36.407 1.154 36.407 0.941 c
+36.407 -1.264 l
+h
+38.923 -1.323 m
+38.637 -1.323 38.394 -1.282 38.188 -1.205 c
+37.982 -1.117 37.81 -0.996 37.674 -0.838 c
+37.535 -0.684 37.431 -0.496 37.365 -0.279 c
+37.296 -0.055 37.263 0.191 37.263 0.455 c
+37.263 0.75 37.296 1.007 37.365 1.235 c
+37.442 1.459 37.549 1.646 37.689 1.793 c
+37.836 1.947 38.012 2.065 38.218 2.146 c
+38.424 2.234 38.659 2.278 38.923 2.278 c
+39.148 2.278 39.35 2.249 39.526 2.19 c
+39.702 2.132 39.854 2.047 39.981 1.941 c
+40.107 1.841 40.21 1.72 40.291 1.573 c
+40.368 1.433 40.423 1.282 40.452 1.118 c
+39.541 1.073 l
+39.511 1.249 39.441 1.389 39.335 1.5 c
+39.235 1.606 39.092 1.661 38.909 1.661 c
+38.662 1.661 38.487 1.558 38.379 1.353 c
+38.269 1.154 38.218 0.867 38.218 0.485 c
+38.218 -0.309 38.453 -0.706 38.923 -0.706 c
+39.089 -0.706 39.232 -0.654 39.35 -0.544 c
+39.467 -0.437 39.541 -0.276 39.57 -0.058 c
+40.482 -0.103 l
+40.452 -0.272 40.397 -0.426 40.32 -0.573 c
+40.25 -0.721 40.147 -0.852 40.012 -0.97 c
+39.883 -1.08 39.725 -1.168 39.541 -1.234 c
+39.364 -1.294 39.158 -1.323 38.923 -1.323 c
+42.323 1.514 m
+42.441 1.786 42.591 1.984 42.778 2.102 c
+42.962 2.219 43.183 2.278 43.44 2.278 c
+43.646 2.278 43.815 2.242 43.954 2.176 c
+44.101 2.105 44.211 2.014 44.292 1.897 c
+44.38 1.779 44.44 1.635 44.469 1.47 c
+44.505 1.301 44.527 1.124 44.527 0.941 c
+44.527 -1.264 l
+43.616 -1.264 l
+43.616 0.735 l
+43.616 0.871 43.605 0.992 43.586 1.103 c
+43.576 1.209 43.55 1.297 43.513 1.367 c
+43.473 1.444 43.414 1.503 43.337 1.544 c
+43.267 1.58 43.175 1.602 43.058 1.602 c
+42.948 1.602 42.852 1.577 42.763 1.529 c
+42.676 1.477 42.595 1.411 42.528 1.323 c
+42.47 1.235 42.418 1.124 42.381 1 c
+42.352 0.882 42.337 0.75 42.337 0.603 c
+42.337 -1.264 l
+41.426 -1.264 l
+41.426 3.513 l
+42.337 3.513 l
+42.337 2.205 l
+42.337 2.135 42.329 2.065 42.323 1.999 c
+42.323 1.793 l
+42.323 1.735 42.315 1.679 42.308 1.631 c
+42.308 1.514 l
+h
+50.297 -2.631 m
+50.297 3.513 l
+52.222 3.513 l
+52.222 2.896 l
+51.149 2.896 l
+51.149 -2.014 l
+52.222 -2.014 l
+52.222 -2.631 l
+h
+54.2 0.838 1.866 -0.794 re
+54.2 0.044 m
+58.628 -1.323 m
+58.458 -1.323 58.308 -1.301 58.172 -1.264 c
+58.044 -1.216 57.93 -1.147 57.834 -1.058 c
+57.745 -0.97 57.676 -0.864 57.628 -0.735 c
+57.576 -0.599 57.554 -0.449 57.554 -0.279 c
+57.554 -0.073 57.587 0.096 57.657 0.235 c
+57.724 0.382 57.819 0.492 57.936 0.573 c
+58.062 0.661 58.204 0.724 58.363 0.765 c
+58.528 0.802 58.705 0.827 58.892 0.838 c
+59.613 0.852 l
+59.613 1.029 l
+59.613 1.147 59.602 1.249 59.583 1.338 c
+59.561 1.426 59.528 1.492 59.48 1.544 c
+59.44 1.602 59.392 1.639 59.333 1.661 c
+59.274 1.679 59.208 1.691 59.142 1.691 c
+59.072 1.691 59.01 1.679 58.951 1.661 c
+58.9 1.65 58.852 1.625 58.804 1.588 c
+58.763 1.558 58.73 1.507 58.701 1.44 c
+58.679 1.382 58.664 1.301 58.657 1.205 c
+57.716 1.249 l
+57.745 1.396 57.79 1.532 57.849 1.661 c
+57.915 1.786 58.01 1.897 58.127 1.984 c
+58.245 2.08 58.385 2.153 58.554 2.205 c
+58.73 2.253 58.936 2.278 59.172 2.278 c
+59.613 2.278 59.943 2.168 60.171 1.955 c
+60.406 1.749 60.523 1.44 60.523 1.029 c
+60.523 -0.235 l
+60.523 -0.455 l
+60.531 -0.515 60.546 -0.569 60.568 -0.617 c
+60.586 -0.658 60.616 -0.69 60.656 -0.721 c
+60.693 -0.742 60.744 -0.75 60.803 -0.75 c
+60.869 -0.75 60.939 -0.746 61.009 -0.735 c
+61.009 -1.22 l
+60.95 -1.231 60.895 -1.242 60.847 -1.249 c
+60.807 -1.261 60.766 -1.268 60.729 -1.278 c
+60.689 -1.286 60.645 -1.294 60.597 -1.294 c
+60.546 -1.301 60.487 -1.309 60.421 -1.309 c
+60.193 -1.309 60.028 -1.257 59.921 -1.147 c
+59.811 -1.029 59.748 -0.864 59.73 -0.646 c
+59.715 -0.646 l
+59.646 -0.757 59.576 -0.852 59.509 -0.941 c
+59.44 -1.022 59.363 -1.087 59.274 -1.147 c
+59.186 -1.205 59.087 -1.249 58.981 -1.278 c
+58.881 -1.309 58.763 -1.323 58.628 -1.323 c
+59.613 0.353 m
+59.186 0.338 l
+59.087 0.338 58.995 0.331 58.907 0.324 c
+58.826 0.312 58.76 0.287 58.701 0.25 c
+58.642 0.21 58.591 0.151 58.554 0.073 c
+58.514 0.004 58.495 -0.088 58.495 -0.206 c
+58.495 -0.374 58.528 -0.496 58.598 -0.573 c
+58.664 -0.654 58.763 -0.69 58.892 -0.69 c
+58.998 -0.69 59.098 -0.669 59.186 -0.617 c
+59.282 -0.569 59.363 -0.507 59.421 -0.426 c
+59.488 -0.349 59.538 -0.261 59.569 -0.162 c
+59.598 -0.055 59.613 0.059 59.613 0.177 c
+h
+62.1 -2.631 m
+62.1 -2.014 l
+63.174 -2.014 l
+63.174 2.896 l
+62.1 2.896 l
+62.1 3.513 l
+64.026 3.513 l
+64.026 -2.631 l
+h
+f
+Q
+q 1 0 0 1 541.9542 230.2781 cm
+0 0 m
+2.103 0 l
+2.103 -0.574 l
+-0.675 -0.574 l
+-0.675 4.777 l
+0 4.777 l
+h
+3.514 -0.574 -0.647 3.984 re
+3.558 4.453 m
+3.558 4.343 3.528 4.251 3.469 4.174 c
+3.41 4.104 3.315 4.072 3.19 4.072 c
+3.073 4.072 2.977 4.104 2.911 4.174 c
+2.852 4.251 2.822 4.343 2.822 4.453 c
+2.822 4.571 2.852 4.663 2.911 4.733 c
+2.977 4.81 3.073 4.85 3.19 4.85 c
+3.315 4.85 3.41 4.81 3.469 4.733 c
+3.528 4.652 3.558 4.56 3.558 4.453 c
+6.468 0.44 m
+6.468 0.588 6.413 0.708 6.306 0.808 c
+6.196 0.903 5.991 1.021 5.689 1.161 c
+5.343 1.308 5.101 1.429 4.954 1.529 c
+4.807 1.635 4.697 1.753 4.63 1.881 c
+4.561 2.006 4.528 2.164 4.528 2.352 c
+4.528 2.675 4.645 2.943 4.881 3.16 c
+5.116 3.373 5.417 3.484 5.792 3.484 c
+6.174 3.484 6.483 3.37 6.718 3.145 c
+6.953 2.917 7.071 2.63 7.071 2.278 c
+6.423 2.278 l
+6.423 2.454 6.365 2.605 6.247 2.734 c
+6.13 2.859 5.976 2.925 5.792 2.925 c
+5.594 2.925 5.442 2.869 5.336 2.763 c
+5.226 2.664 5.174 2.532 5.174 2.366 c
+5.174 2.237 5.211 2.131 5.292 2.042 c
+5.369 1.961 5.561 1.859 5.866 1.734 c
+6.343 1.547 6.674 1.359 6.851 1.176 c
+7.026 0.999 7.115 0.771 7.115 0.5 c
+7.115 0.147 6.99 -0.133 6.747 -0.339 c
+6.512 -0.545 6.196 -0.647 5.806 -0.647 c
+5.384 -0.647 5.046 -0.53 4.792 -0.294 c
+4.535 -0.052 4.41 0.253 4.41 0.617 c
+5.056 0.617 l
+5.064 0.389 5.134 0.213 5.263 0.087 c
+5.388 -0.03 5.571 -0.088 5.806 -0.088 c
+6.02 -0.088 6.182 -0.04 6.292 0.058 c
+6.409 0.154 6.468 0.282 6.468 0.44 c
+8.805 4.365 m
+8.805 3.41 l
+9.407 3.41 l
+9.407 2.881 l
+8.805 2.881 l
+8.805 0.411 l
+8.805 0.253 8.827 0.135 8.879 0.058 c
+8.937 -0.023 9.025 -0.059 9.143 -0.059 c
+9.232 -0.059 9.32 -0.044 9.407 -0.015 c
+9.407 -0.574 l
+9.261 -0.622 9.106 -0.647 8.952 -0.647 c
+8.695 -0.647 8.5 -0.555 8.364 -0.368 c
+8.225 -0.184 8.158 0.077 8.158 0.411 c
+8.158 2.881 l
+7.556 2.881 l
+7.556 3.41 l
+8.158 3.41 l
+8.158 4.365 l
+h
+13.935 -0.574 m
+13.895 -0.485 13.869 -0.339 13.862 -0.133 c
+13.627 -0.478 13.332 -0.647 12.979 -0.647 c
+12.616 -0.647 12.333 -0.551 12.127 -0.353 c
+11.929 -0.148 11.833 0.139 11.833 0.514 c
+11.833 0.914 11.969 1.234 12.245 1.469 c
+12.517 1.712 12.891 1.837 13.361 1.837 c
+13.847 1.837 l
+13.847 2.263 l
+13.847 2.499 13.792 2.664 13.685 2.763 c
+13.575 2.869 13.413 2.925 13.201 2.925 c
+13.002 2.925 12.84 2.865 12.715 2.748 c
+12.597 2.63 12.538 2.484 12.538 2.308 c
+11.892 2.308 l
+11.892 2.502 11.95 2.693 12.068 2.881 c
+12.193 3.064 12.355 3.212 12.553 3.322 c
+12.759 3.428 12.987 3.484 13.244 3.484 c
+13.645 3.484 13.949 3.38 14.155 3.175 c
+14.369 2.969 14.483 2.675 14.494 2.293 c
+14.494 0.278 l
+14.494 -0.026 14.531 -0.291 14.612 -0.515 c
+14.612 -0.574 l
+h
+13.068 -0.059 m
+13.233 -0.059 13.384 -0.015 13.523 0.073 c
+13.671 0.161 13.777 0.272 13.847 0.411 c
+13.847 1.352 l
+13.479 1.352 l
+13.164 1.352 12.921 1.282 12.744 1.146 c
+12.568 1.018 12.48 0.83 12.48 0.588 c
+12.48 0.359 12.524 0.195 12.613 0.087 c
+12.7 -0.011 12.851 -0.059 13.068 -0.059 c
+16.199 -0.574 -0.646 5.644 re
+17.918 -0.574 -0.646 5.644 re
+21.358 -0.574 -0.646 5.644 re
+22.24 1.602 m
+22.24 2.179 22.376 2.634 22.651 2.969 c
+22.934 3.31 23.306 3.484 23.769 3.484 c
+24.228 3.484 24.596 3.314 24.871 2.983 c
+25.154 2.66 25.301 2.212 25.312 1.646 c
+25.312 1.219 l
+25.312 0.65 25.169 0.195 24.885 -0.148 c
+24.611 -0.482 24.243 -0.647 23.784 -0.647 c
+23.32 -0.647 22.949 -0.485 22.666 -0.162 c
+22.391 0.168 22.248 0.61 22.24 1.161 c
+h
+22.886 1.219 m
+22.886 0.816 22.964 0.5 23.122 0.264 c
+23.287 0.029 23.508 -0.088 23.784 -0.088 c
+24.349 -0.088 24.644 0.323 24.665 1.146 c
+24.665 1.602 l
+24.665 2.002 24.581 2.322 24.415 2.557 c
+24.257 2.8 24.041 2.925 23.769 2.925 c
+23.504 2.925 23.287 2.8 23.122 2.557 c
+22.964 2.322 22.886 2.002 22.886 1.602 c
+h
+27.532 -0.088 m
+27.745 -0.088 27.917 -0.026 28.046 0.103 c
+28.182 0.238 28.255 0.43 28.266 0.675 c
+28.884 0.675 l
+28.862 0.294 28.726 -0.026 28.472 -0.279 c
+28.216 -0.526 27.903 -0.647 27.532 -0.647 c
+27.04 -0.647 26.664 -0.497 26.4 -0.192 c
+26.142 0.12 26.018 0.588 26.018 1.205 c
+26.018 1.646 l
+26.018 2.241 26.142 2.697 26.4 3.013 c
+26.664 3.326 27.04 3.484 27.532 3.484 c
+27.932 3.484 28.252 3.351 28.487 3.087 c
+28.729 2.829 28.862 2.484 28.884 2.042 c
+28.266 2.042 l
+28.245 2.337 28.171 2.557 28.046 2.705 c
+27.929 2.851 27.756 2.925 27.532 2.925 c
+27.237 2.925 27.021 2.825 26.884 2.63 c
+26.745 2.443 26.672 2.135 26.664 1.705 c
+26.664 1.19 l
+26.664 0.72 26.73 0.386 26.87 0.191 c
+27.017 0.003 27.237 -0.088 27.532 -0.088 c
+31.677 -0.574 m
+31.636 -0.485 31.611 -0.339 31.603 -0.133 c
+31.368 -0.478 31.075 -0.647 30.722 -0.647 c
+30.358 -0.647 30.075 -0.551 29.868 -0.353 c
+29.67 -0.148 29.575 0.139 29.575 0.514 c
+29.575 0.914 29.71 1.234 29.986 1.469 c
+30.258 1.712 30.633 1.837 31.104 1.837 c
+31.588 1.837 l
+31.588 2.263 l
+31.588 2.499 31.534 2.664 31.427 2.763 c
+31.316 2.869 31.155 2.925 30.942 2.925 c
+30.743 2.925 30.582 2.865 30.456 2.748 c
+30.339 2.63 30.281 2.484 30.281 2.308 c
+29.633 2.308 l
+29.633 2.502 29.693 2.693 29.81 2.881 c
+29.935 3.064 30.097 3.212 30.295 3.322 c
+30.501 3.428 30.728 3.484 30.986 3.484 c
+31.387 3.484 31.692 3.38 31.898 3.175 c
+32.11 2.969 32.224 2.675 32.235 2.293 c
+32.235 0.278 l
+32.235 -0.026 32.272 -0.291 32.353 -0.515 c
+32.353 -0.574 l
+h
+30.809 -0.059 m
+30.975 -0.059 31.125 -0.015 31.266 0.073 c
+31.412 0.161 31.519 0.272 31.588 0.411 c
+31.588 1.352 l
+31.221 1.352 l
+30.905 1.352 30.662 1.282 30.487 1.146 c
+30.31 1.018 30.221 0.83 30.221 0.588 c
+30.221 0.359 30.265 0.195 30.354 0.087 c
+30.442 -0.011 30.593 -0.059 30.809 -0.059 c
+33.94 -0.574 -0.646 5.644 re
+39.555 1.219 m
+39.555 0.602 39.441 0.135 39.218 -0.177 c
+39 -0.493 38.678 -0.647 38.248 -0.647 c
+37.824 -0.647 37.512 -0.468 37.307 -0.103 c
+37.277 -0.574 l
+36.675 -0.574 l
+36.675 5.071 l
+37.321 5.071 l
+37.321 2.969 l
+37.535 3.31 37.843 3.484 38.248 3.484 c
+38.678 3.484 39 3.326 39.218 3.013 c
+39.441 2.707 39.555 2.241 39.555 1.616 c
+h
+38.909 1.602 m
+38.909 2.072 38.838 2.403 38.703 2.601 c
+38.574 2.796 38.365 2.896 38.071 2.896 c
+37.737 2.896 37.487 2.711 37.321 2.352 c
+37.321 0.47 l
+37.487 0.106 37.741 -0.074 38.086 -0.074 c
+38.379 -0.074 38.589 0.029 38.718 0.235 c
+38.842 0.44 38.909 0.756 38.909 1.19 c
+h
+42.04 2.792 m
+41.951 2.811 41.853 2.822 41.745 2.822 c
+41.411 2.822 41.176 2.638 41.04 2.278 c
+41.04 -0.574 l
+40.393 -0.574 l
+40.393 3.41 l
+41.026 3.41 l
+41.04 2.998 l
+41.217 3.322 41.459 3.484 41.775 3.484 c
+41.882 3.484 41.97 3.461 42.04 3.424 c
+h
+44.583 -0.574 m
+44.542 -0.485 44.517 -0.339 44.509 -0.133 c
+44.274 -0.478 43.98 -0.647 43.627 -0.647 c
+43.264 -0.647 42.981 -0.551 42.774 -0.353 c
+42.576 -0.148 42.481 0.139 42.481 0.514 c
+42.481 0.914 42.616 1.234 42.892 1.469 c
+43.164 1.712 43.539 1.837 44.01 1.837 c
+44.494 1.837 l
+44.494 2.263 l
+44.494 2.499 44.44 2.664 44.332 2.763 c
+44.222 2.869 44.06 2.925 43.848 2.925 c
+43.649 2.925 43.488 2.865 43.362 2.748 c
+43.245 2.63 43.187 2.484 43.187 2.308 c
+42.539 2.308 l
+42.539 2.502 42.599 2.693 42.716 2.881 c
+42.84 3.064 43.002 3.212 43.201 3.322 c
+43.407 3.428 43.634 3.484 43.892 3.484 c
+44.292 3.484 44.598 3.38 44.803 3.175 c
+45.016 2.969 45.13 2.675 45.141 2.293 c
+45.141 0.278 l
+45.141 -0.026 45.178 -0.291 45.259 -0.515 c
+45.259 -0.574 l
+h
+43.715 -0.059 m
+43.881 -0.059 44.031 -0.015 44.171 0.073 c
+44.318 0.161 44.425 0.272 44.494 0.411 c
+44.494 1.352 l
+44.127 1.352 l
+43.811 1.352 43.569 1.282 43.392 1.146 c
+43.216 1.018 43.127 0.83 43.127 0.588 c
+43.127 0.359 43.172 0.195 43.26 0.087 c
+43.347 -0.011 43.499 -0.059 43.715 -0.059 c
+46.758 3.41 m
+46.773 2.969 l
+47.027 3.31 47.349 3.484 47.743 3.484 c
+48.448 3.484 48.805 3.013 48.816 2.072 c
+48.816 -0.574 l
+48.169 -0.574 l
+48.169 2.042 l
+48.169 2.355 48.114 2.576 48.008 2.705 c
+47.897 2.829 47.743 2.896 47.537 2.896 c
+47.379 2.896 47.232 2.84 47.096 2.734 c
+46.967 2.624 46.865 2.487 46.788 2.322 c
+46.788 -0.574 l
+46.14 -0.574 l
+46.14 3.41 l
+h
+51.168 -0.088 m
+51.381 -0.088 51.553 -0.026 51.682 0.103 c
+51.818 0.238 51.892 0.43 51.902 0.675 c
+52.52 0.675 l
+52.498 0.294 52.362 -0.026 52.109 -0.279 c
+51.852 -0.526 51.538 -0.647 51.168 -0.647 c
+50.676 -0.647 50.3 -0.497 50.036 -0.192 c
+49.778 0.12 49.654 0.588 49.654 1.205 c
+49.654 1.646 l
+49.654 2.241 49.778 2.697 50.036 3.013 c
+50.3 3.326 50.676 3.484 51.168 3.484 c
+51.569 3.484 51.888 3.351 52.124 3.087 c
+52.365 2.829 52.498 2.484 52.52 2.042 c
+51.902 2.042 l
+51.881 2.337 51.807 2.557 51.682 2.705 c
+51.565 2.851 51.392 2.925 51.168 2.925 c
+50.873 2.925 50.657 2.825 50.521 2.63 c
+50.381 2.443 50.308 2.135 50.3 1.705 c
+50.3 1.19 l
+50.3 0.72 50.366 0.386 50.506 0.191 c
+50.653 0.003 50.873 -0.088 51.168 -0.088 c
+53.917 2.998 m
+54.17 3.322 54.49 3.484 54.871 3.484 c
+55.577 3.484 55.934 3.013 55.945 2.072 c
+55.945 -0.574 l
+55.299 -0.574 l
+55.299 2.042 l
+55.299 2.355 55.243 2.576 55.137 2.705 c
+55.027 2.829 54.871 2.896 54.666 2.896 c
+54.508 2.896 54.361 2.84 54.225 2.734 c
+54.096 2.624 53.994 2.487 53.917 2.322 c
+53.917 -0.574 l
+53.269 -0.574 l
+53.269 5.071 l
+53.917 5.071 l
+h
+58.326 -0.647 m
+57.826 -0.647 57.444 -0.5 57.18 -0.206 c
+56.915 0.087 56.783 0.521 56.783 1.102 c
+56.783 1.572 l
+56.783 2.167 56.908 2.634 57.165 2.969 c
+57.429 3.31 57.79 3.484 58.252 3.484 c
+58.713 3.484 59.054 3.329 59.282 3.027 c
+59.517 2.734 59.638 2.271 59.65 1.646 c
+59.65 1.219 l
+57.429 1.219 l
+57.429 1.132 l
+57.429 0.698 57.506 0.386 57.664 0.191 c
+57.83 0.003 58.062 -0.088 58.356 -0.088 c
+58.551 -0.088 58.723 -0.056 58.87 0.014 c
+59.017 0.091 59.153 0.209 59.282 0.367 c
+59.619 -0.044 l
+59.333 -0.449 58.904 -0.647 58.326 -0.647 c
+58.252 2.925 m
+57.977 2.925 57.775 2.829 57.65 2.645 c
+57.522 2.458 57.448 2.167 57.429 1.778 c
+59.002 1.778 l
+59.002 1.866 l
+58.981 2.248 58.914 2.516 58.796 2.675 c
+58.679 2.84 58.495 2.925 58.252 2.925 c
+62.368 0.44 m
+62.368 0.588 62.314 0.708 62.206 0.808 c
+62.096 0.903 61.89 1.021 61.589 1.161 c
+61.244 1.308 61.001 1.429 60.855 1.529 c
+60.708 1.635 60.597 1.753 60.531 1.881 c
+60.461 2.006 60.428 2.164 60.428 2.352 c
+60.428 2.675 60.546 2.943 60.781 3.16 c
+61.016 3.373 61.317 3.484 61.692 3.484 c
+62.075 3.484 62.383 3.37 62.618 3.145 c
+62.854 2.917 62.971 2.63 62.971 2.278 c
+62.324 2.278 l
+62.324 2.454 62.266 2.605 62.148 2.734 c
+62.031 2.859 61.876 2.925 61.692 2.925 c
+61.494 2.925 61.343 2.869 61.237 2.763 c
+61.126 2.664 61.075 2.532 61.075 2.366 c
+61.075 2.237 61.111 2.131 61.192 2.042 c
+61.269 1.961 61.46 1.859 61.766 1.734 c
+62.243 1.547 62.574 1.359 62.75 1.176 c
+62.927 0.999 63.016 0.771 63.016 0.5 c
+63.016 0.147 62.89 -0.133 62.648 -0.339 c
+62.412 -0.545 62.096 -0.647 61.707 -0.647 c
+61.284 -0.647 60.946 -0.53 60.693 -0.294 c
+60.436 -0.052 60.311 0.253 60.311 0.617 c
+60.957 0.617 l
+60.965 0.389 61.034 0.213 61.163 0.087 c
+61.288 -0.03 61.472 -0.088 61.707 -0.088 c
+61.92 -0.088 62.082 -0.04 62.192 0.058 c
+62.31 0.154 62.368 0.282 62.368 0.44 c
+66.278 -0.574 -0.646 3.984 re
+66.322 4.453 m
+66.322 4.343 66.293 4.251 66.235 4.174 c
+66.175 4.104 66.08 4.072 65.955 4.072 c
+65.838 4.072 65.742 4.104 65.676 4.174 c
+65.617 4.251 65.587 4.343 65.587 4.453 c
+65.587 4.571 65.617 4.663 65.676 4.733 c
+65.742 4.81 65.838 4.85 65.955 4.85 c
+66.08 4.85 66.175 4.81 66.235 4.733 c
+66.293 4.652 66.322 4.56 66.322 4.453 c
+67.91 3.41 m
+67.924 2.969 l
+68.178 3.31 68.502 3.484 68.895 3.484 c
+69.601 3.484 69.957 3.013 69.967 2.072 c
+69.967 -0.574 l
+69.321 -0.574 l
+69.321 2.042 l
+69.321 2.355 69.266 2.576 69.159 2.705 c
+69.049 2.829 68.895 2.896 68.689 2.896 c
+68.531 2.896 68.384 2.84 68.248 2.734 c
+68.12 2.624 68.016 2.487 67.939 2.322 c
+67.939 -0.574 l
+67.293 -0.574 l
+67.293 3.41 l
+h
+74.304 2.792 m
+74.216 2.811 74.116 2.822 74.01 2.822 c
+73.676 2.822 73.441 2.638 73.304 2.278 c
+73.304 -0.574 l
+72.658 -0.574 l
+72.658 3.41 l
+73.29 3.41 l
+73.304 2.998 l
+73.481 3.322 73.724 3.484 74.039 3.484 c
+74.146 3.484 74.235 3.461 74.304 3.424 c
+h
+76.303 -0.647 m
+75.803 -0.647 75.421 -0.5 75.157 -0.206 c
+74.892 0.087 74.76 0.521 74.76 1.102 c
+74.76 1.572 l
+74.76 2.167 74.885 2.634 75.142 2.969 c
+75.407 3.31 75.766 3.484 76.23 3.484 c
+76.689 3.484 77.031 3.329 77.258 3.027 c
+77.493 2.734 77.615 2.271 77.626 1.646 c
+77.626 1.219 l
+75.407 1.219 l
+75.407 1.132 l
+75.407 0.698 75.484 0.386 75.642 0.191 c
+75.807 0.003 76.038 -0.088 76.333 -0.088 c
+76.527 -0.088 76.7 -0.056 76.847 0.014 c
+76.994 0.091 77.13 0.209 77.258 0.367 c
+77.597 -0.044 l
+77.31 -0.449 76.88 -0.647 76.303 -0.647 c
+76.23 2.925 m
+75.954 2.925 75.752 2.829 75.627 2.645 c
+75.498 2.458 75.425 2.167 75.407 1.778 c
+76.979 1.778 l
+76.979 1.866 l
+76.957 2.248 76.891 2.516 76.774 2.675 c
+76.656 2.84 76.472 2.925 76.23 2.925 c
+81.286 1.219 m
+81.286 0.591 81.169 0.12 80.934 -0.192 c
+80.705 -0.497 80.389 -0.647 79.978 -0.647 c
+79.573 -0.647 79.265 -0.497 79.052 -0.192 c
+79.052 -2.103 l
+78.405 -2.103 l
+78.405 3.41 l
+78.993 3.41 l
+79.037 2.969 l
+79.251 3.31 79.559 3.484 79.963 3.484 c
+80.404 3.484 80.731 3.329 80.948 3.027 c
+81.161 2.722 81.275 2.267 81.286 1.66 c
+h
+80.639 1.602 m
+80.639 2.042 80.57 2.366 80.433 2.572 c
+80.294 2.785 80.074 2.896 79.772 2.896 c
+79.456 2.896 79.217 2.741 79.052 2.439 c
+79.052 0.367 l
+79.217 0.062 79.456 -0.088 79.772 -0.088 c
+80.066 -0.088 80.279 0.014 80.419 0.22 c
+80.555 0.433 80.628 0.764 80.639 1.205 c
+h
+81.992 1.602 m
+81.992 2.179 82.128 2.634 82.403 2.969 c
+82.686 3.31 83.057 3.484 83.521 3.484 c
+83.98 3.484 84.348 3.314 84.622 2.983 c
+84.906 2.66 85.053 2.212 85.064 1.646 c
+85.064 1.219 l
+85.064 0.65 84.921 0.195 84.637 -0.148 c
+84.362 -0.482 83.994 -0.647 83.535 -0.647 c
+83.072 -0.647 82.701 -0.485 82.418 -0.162 c
+82.143 0.168 81.999 0.61 81.992 1.161 c
+h
+82.638 1.219 m
+82.638 0.816 82.715 0.5 82.873 0.264 c
+83.039 0.029 83.259 -0.088 83.535 -0.088 c
+84.101 -0.088 84.395 0.323 84.417 1.146 c
+84.417 1.602 l
+84.417 2.002 84.333 2.322 84.167 2.557 c
+84.009 2.8 83.793 2.925 83.521 2.925 c
+83.255 2.925 83.039 2.8 82.873 2.557 c
+82.715 2.322 82.638 2.002 82.638 1.602 c
+h
+87.842 0.44 m
+87.842 0.588 87.787 0.708 87.68 0.808 c
+87.57 0.903 87.365 1.021 87.063 1.161 c
+86.717 1.308 86.475 1.429 86.328 1.529 c
+86.181 1.635 86.071 1.753 86.004 1.881 c
+85.935 2.006 85.902 2.164 85.902 2.352 c
+85.902 2.675 86.019 2.943 86.255 3.16 c
+86.49 3.373 86.791 3.484 87.166 3.484 c
+87.548 3.484 87.857 3.37 88.092 3.145 c
+88.327 2.917 88.445 2.63 88.445 2.278 c
+87.797 2.278 l
+87.797 2.454 87.739 2.605 87.621 2.734 c
+87.504 2.859 87.35 2.925 87.166 2.925 c
+86.968 2.925 86.816 2.869 86.71 2.763 c
+86.6 2.664 86.548 2.532 86.548 2.366 c
+86.548 2.237 86.585 2.131 86.666 2.042 c
+86.743 1.961 86.935 1.859 87.24 1.734 c
+87.717 1.547 88.048 1.359 88.224 1.176 c
+88.4 0.999 88.489 0.771 88.489 0.5 c
+88.489 0.147 88.364 -0.133 88.121 -0.339 c
+87.886 -0.545 87.57 -0.647 87.18 -0.647 c
+86.758 -0.647 86.42 -0.53 86.166 -0.294 c
+85.909 -0.052 85.784 0.253 85.784 0.617 c
+86.43 0.617 l
+86.438 0.389 86.508 0.213 86.636 0.087 c
+86.762 -0.03 86.945 -0.088 87.18 -0.088 c
+87.394 -0.088 87.556 -0.04 87.666 0.058 c
+87.783 0.154 87.842 0.282 87.842 0.44 c
+90.032 -0.574 -0.646 3.984 re
+90.076 4.453 m
+90.076 4.343 90.047 4.251 89.988 4.174 c
+89.929 4.104 89.834 4.072 89.709 4.072 c
+89.591 4.072 89.495 4.104 89.43 4.174 c
+89.37 4.251 89.341 4.343 89.341 4.453 c
+89.341 4.571 89.37 4.663 89.43 4.733 c
+89.495 4.81 89.591 4.85 89.709 4.85 c
+89.834 4.85 89.929 4.81 89.988 4.733 c
+90.047 4.652 90.076 4.56 90.076 4.453 c
+91.899 4.365 m
+91.899 3.41 l
+92.501 3.41 l
+92.501 2.881 l
+91.899 2.881 l
+91.899 0.411 l
+91.899 0.253 91.921 0.135 91.972 0.058 c
+92.031 -0.023 92.119 -0.059 92.237 -0.059 c
+92.325 -0.059 92.414 -0.044 92.501 -0.015 c
+92.501 -0.574 l
+92.354 -0.622 92.2 -0.647 92.046 -0.647 c
+91.789 -0.647 91.594 -0.555 91.458 -0.368 c
+91.319 -0.184 91.252 0.077 91.252 0.411 c
+91.252 2.881 l
+90.65 2.881 l
+90.65 3.41 l
+91.252 3.41 l
+91.252 4.365 l
+h
+93.06 1.602 m
+93.06 2.179 93.196 2.634 93.472 2.969 c
+93.755 3.31 94.126 3.484 94.589 3.484 c
+95.048 3.484 95.415 3.314 95.691 2.983 c
+95.974 2.66 96.121 2.212 96.132 1.646 c
+96.132 1.219 l
+96.132 0.65 95.988 0.195 95.706 -0.148 c
+95.43 -0.482 95.063 -0.647 94.604 -0.647 c
+94.141 -0.647 93.769 -0.485 93.486 -0.162 c
+93.21 0.168 93.067 0.61 93.06 1.161 c
+h
+93.707 1.219 m
+93.707 0.816 93.784 0.5 93.942 0.264 c
+94.107 0.029 94.328 -0.088 94.604 -0.088 c
+95.169 -0.088 95.463 0.323 95.485 1.146 c
+95.485 1.602 l
+95.485 2.002 95.401 2.322 95.236 2.557 c
+95.078 2.8 94.86 2.925 94.589 2.925 c
+94.324 2.925 94.107 2.8 93.942 2.557 c
+93.784 2.322 93.707 2.002 93.707 1.602 c
+h
+98.616 2.792 m
+98.528 2.811 98.429 2.822 98.322 2.822 c
+97.988 2.822 97.753 2.638 97.617 2.278 c
+97.617 -0.574 l
+96.97 -0.574 l
+96.97 3.41 l
+97.602 3.41 l
+97.617 2.998 l
+97.793 3.322 98.035 3.484 98.352 3.484 c
+98.459 3.484 98.546 3.461 98.616 3.424 c
+h
+100.424 0.514 m
+101.145 3.41 l
+101.835 3.41 l
+100.542 -1.133 l
+100.443 -1.474 100.3 -1.735 100.115 -1.912 c
+99.94 -2.087 99.737 -2.176 99.513 -2.176 c
+99.425 -2.176 99.311 -2.154 99.175 -2.117 c
+99.175 -1.573 l
+99.321 -1.588 l
+99.506 -1.588 99.653 -1.544 99.763 -1.455 c
+99.87 -1.368 99.957 -1.21 100.027 -0.985 c
+100.145 -0.545 l
+98.984 3.41 l
+99.689 3.41 l
+h
+102.114 -0.221 m
+102.114 -0.103 102.147 -0.008 102.218 0.073 c
+102.284 0.151 102.386 0.191 102.527 0.191 c
+102.673 0.191 102.78 0.151 102.849 0.073 c
+102.927 -0.008 102.967 -0.103 102.967 -0.221 c
+102.967 -0.331 102.927 -0.423 102.849 -0.5 c
+102.78 -0.578 102.673 -0.618 102.527 -0.618 c
+102.386 -0.618 102.284 -0.578 102.218 -0.5 c
+102.147 -0.423 102.114 -0.331 102.114 -0.221 c
+106.892 1.117 m
+106.965 0.514 l
+107.068 1.043 l
+107.921 4.777 l
+108.48 4.777 l
+109.317 1.043 l
+109.42 0.5 l
+109.494 1.117 l
+110.155 4.777 l
+110.831 4.777 l
+109.758 -0.574 l
+109.156 -0.574 l
+108.258 3.322 l
+108.2 3.645 l
+108.156 3.322 l
+107.23 -0.574 l
+106.612 -0.574 l
+105.554 4.777 l
+106.23 4.777 l
+h
+112.213 -0.574 -0.647 3.984 re
+112.257 4.453 m
+112.257 4.343 112.227 4.251 112.169 4.174 c
+112.11 4.104 112.015 4.072 111.89 4.072 c
+111.772 4.072 111.676 4.104 111.61 4.174 c
+111.551 4.251 111.522 4.343 111.522 4.453 c
+111.522 4.571 111.551 4.663 111.61 4.733 c
+111.676 4.81 111.772 4.85 111.89 4.85 c
+112.015 4.85 112.11 4.81 112.169 4.733 c
+112.227 4.652 112.257 4.56 112.257 4.453 c
+114.08 4.365 m
+114.08 3.41 l
+114.683 3.41 l
+114.683 2.881 l
+114.08 2.881 l
+114.08 0.411 l
+114.08 0.253 114.101 0.135 114.153 0.058 c
+114.212 -0.023 114.3 -0.059 114.417 -0.059 c
+114.506 -0.059 114.594 -0.044 114.683 -0.015 c
+114.683 -0.574 l
+114.535 -0.622 114.381 -0.647 114.226 -0.647 c
+113.97 -0.647 113.775 -0.555 113.638 -0.368 c
+113.499 -0.184 113.432 0.077 113.432 0.411 c
+113.432 2.881 l
+112.83 2.881 l
+112.83 3.41 l
+113.432 3.41 l
+113.432 4.365 l
+h
+116.094 2.998 m
+116.347 3.322 116.667 3.484 117.049 3.484 c
+117.754 3.484 118.111 3.013 118.122 2.072 c
+118.122 -0.574 l
+117.475 -0.574 l
+117.475 2.042 l
+117.475 2.355 117.42 2.576 117.313 2.705 c
+117.203 2.829 117.049 2.896 116.843 2.896 c
+116.685 2.896 116.538 2.84 116.402 2.734 c
+116.274 2.624 116.171 2.487 116.094 2.322 c
+116.094 -0.574 l
+115.447 -0.574 l
+115.447 5.071 l
+116.094 5.071 l
+h
+f
+Q
+664.516 231.572 -1.794 0.866 re
+667.264 229.704 m
+667.234 229.764 667.205 229.866 667.176 230.013 c
+666.989 229.756 666.739 229.631 666.426 229.631 c
+666.091 229.631 665.813 229.737 665.588 229.955 c
+665.372 230.178 665.264 230.469 665.264 230.822 c
+665.264 231.233 665.397 231.549 665.661 231.777 c
+665.927 232.012 666.309 232.13 666.808 232.13 c
+667.132 232.13 l
+667.132 232.453 l
+667.132 232.63 667.095 232.75 667.028 232.821 c
+666.97 232.898 666.882 232.939 666.764 232.939 c
+666.507 232.939 666.382 232.784 666.382 232.482 c
+665.339 232.482 l
+665.339 232.854 665.474 233.159 665.75 233.394 c
+666.022 233.637 666.371 233.762 666.793 233.762 c
+667.234 233.762 667.573 233.644 667.808 233.409 c
+668.05 233.18 668.175 232.858 668.175 232.438 c
+668.175 230.572 l
+668.175 230.226 668.223 229.958 668.322 229.764 c
+668.322 229.704 l
+h
+666.661 230.454 m
+666.768 230.454 666.86 230.473 666.941 230.513 c
+667.028 230.56 667.091 230.62 667.132 230.689 c
+667.132 231.512 l
+666.882 231.512 l
+666.706 231.512 666.562 231.454 666.455 231.336 c
+666.357 231.225 666.309 231.079 666.309 230.895 c
+666.309 230.601 666.426 230.454 666.661 230.454 c
+f
+q 1 0 0 1 669.0717 230.0571 cm
+0 0 m
+0 0.118 0.034 0.214 0.104 0.294 c
+0.169 0.372 0.272 0.412 0.412 0.412 c
+0.559 0.412 0.665 0.372 0.736 0.294 c
+0.813 0.214 0.853 0.118 0.853 0 c
+0.853 -0.11 0.813 -0.202 0.736 -0.279 c
+0.665 -0.357 0.559 -0.397 0.412 -0.397 c
+0.272 -0.397 0.169 -0.357 0.104 -0.279 c
+0.034 -0.202 0 -0.11 0 0 c
+0 2.822 m
+0 2.94 0.034 3.036 0.104 3.117 c
+0.169 3.194 0.272 3.234 0.412 3.234 c
+0.559 3.234 0.665 3.194 0.736 3.117 c
+0.813 3.036 0.853 2.94 0.853 2.822 c
+0.853 2.712 0.813 2.62 0.736 2.543 c
+0.665 2.462 0.559 2.425 0.412 2.425 c
+0.272 2.425 0.169 2.462 0.104 2.543 c
+0.034 2.62 0 2.712 0 2.822 c
+5.38 0.661 m
+5.38 0.809 5.325 0.929 5.218 1.029 c
+5.108 1.124 4.902 1.242 4.601 1.382 c
+4.256 1.529 4.013 1.65 3.866 1.75 c
+3.719 1.856 3.609 1.974 3.543 2.103 c
+3.473 2.227 3.44 2.385 3.44 2.573 c
+3.44 2.896 3.558 3.164 3.793 3.381 c
+4.028 3.594 4.329 3.705 4.704 3.705 c
+5.087 3.705 5.395 3.591 5.63 3.366 c
+5.866 3.138 5.983 2.851 5.983 2.499 c
+5.336 2.499 l
+5.336 2.675 5.278 2.826 5.16 2.955 c
+5.042 3.08 4.888 3.146 4.704 3.146 c
+4.505 3.146 4.355 3.09 4.248 2.984 c
+4.138 2.885 4.087 2.753 4.087 2.587 c
+4.087 2.458 4.123 2.352 4.204 2.263 c
+4.281 2.183 4.472 2.08 4.777 1.955 c
+5.255 1.768 5.586 1.58 5.762 1.397 c
+5.939 1.22 6.027 0.992 6.027 0.721 c
+6.027 0.368 5.902 0.088 5.66 -0.118 c
+5.424 -0.324 5.108 -0.426 4.719 -0.426 c
+4.296 -0.426 3.958 -0.309 3.705 -0.073 c
+3.447 0.169 3.323 0.474 3.323 0.838 c
+3.969 0.838 l
+3.977 0.611 4.046 0.434 4.175 0.309 c
+4.3 0.191 4.484 0.133 4.719 0.133 c
+4.932 0.133 5.093 0.181 5.204 0.279 c
+5.322 0.375 5.38 0.503 5.38 0.661 c
+7.512 3.219 m
+7.765 3.543 8.085 3.705 8.467 3.705 c
+9.172 3.705 9.529 3.234 9.54 2.294 c
+9.54 -0.353 l
+8.893 -0.353 l
+8.893 2.263 l
+8.893 2.576 8.838 2.797 8.732 2.926 c
+8.621 3.05 8.467 3.117 8.262 3.117 c
+8.104 3.117 7.956 3.061 7.82 2.955 c
+7.691 2.845 7.589 2.708 7.512 2.543 c
+7.512 -0.353 l
+6.865 -0.353 l
+6.865 5.292 l
+7.512 5.292 l
+h
+10.363 1.823 m
+10.363 2.4 10.499 2.855 10.774 3.19 c
+11.057 3.532 11.429 3.705 11.892 3.705 c
+12.351 3.705 12.719 3.535 12.994 3.204 c
+13.278 2.881 13.424 2.433 13.436 1.867 c
+13.436 1.44 l
+13.436 0.871 13.292 0.416 13.009 0.073 c
+12.734 -0.261 12.366 -0.426 11.907 -0.426 c
+11.443 -0.426 11.073 -0.264 10.789 0.059 c
+10.514 0.389 10.371 0.831 10.363 1.382 c
+h
+11.009 1.44 m
+11.009 1.037 11.088 0.721 11.245 0.485 c
+11.41 0.25 11.631 0.133 11.907 0.133 c
+12.472 0.133 12.767 0.544 12.788 1.367 c
+12.788 1.823 l
+12.788 2.223 12.704 2.543 12.538 2.778 c
+12.38 3.021 12.164 3.146 11.892 3.146 c
+11.628 3.146 11.41 3.021 11.245 2.778 c
+11.088 2.543 11.009 2.223 11.009 1.823 c
+h
+17.242 0.794 m
+17.845 3.631 l
+18.492 3.631 l
+17.507 -0.353 l
+16.993 -0.353 l
+16.214 2.499 l
+15.464 -0.353 l
+14.934 -0.353 l
+13.979 3.631 l
+14.612 3.631 l
+15.229 0.867 l
+15.963 3.631 l
+16.478 3.631 l
+h
+22.93 -0.353 m
+22.89 -0.264 22.865 -0.118 22.857 0.088 c
+22.622 -0.257 22.328 -0.426 21.976 -0.426 c
+21.612 -0.426 21.328 -0.33 21.122 -0.132 c
+20.925 0.073 20.829 0.36 20.829 0.735 c
+20.829 1.135 20.965 1.455 21.24 1.691 c
+21.513 1.933 21.887 2.058 22.358 2.058 c
+22.843 2.058 l
+22.843 2.484 l
+22.843 2.72 22.788 2.885 22.681 2.984 c
+22.571 3.09 22.409 3.146 22.196 3.146 c
+21.997 3.146 21.836 3.087 21.71 2.969 c
+21.593 2.851 21.534 2.705 21.534 2.529 c
+20.887 2.529 l
+20.887 2.723 20.947 2.914 21.064 3.102 c
+21.189 3.285 21.351 3.433 21.55 3.543 c
+21.755 3.649 21.983 3.705 22.24 3.705 c
+22.641 3.705 22.946 3.601 23.152 3.396 c
+23.364 3.19 23.478 2.896 23.489 2.514 c
+23.489 0.5 l
+23.489 0.195 23.526 -0.07 23.607 -0.294 c
+23.607 -0.353 l
+h
+22.063 0.162 m
+22.229 0.162 22.379 0.206 22.519 0.294 c
+22.666 0.382 22.772 0.493 22.843 0.632 c
+22.843 1.573 l
+22.475 1.573 l
+22.159 1.573 21.916 1.503 21.741 1.367 c
+21.564 1.239 21.475 1.051 21.475 0.809 c
+21.475 0.58 21.519 0.416 21.608 0.309 c
+21.696 0.21 21.847 0.162 22.063 0.162 c
+25.195 -0.353 -0.647 5.644 re
+26.915 -0.353 -0.647 5.644 re
+32.529 1.44 m
+32.529 0.823 32.415 0.357 32.191 0.044 c
+31.975 -0.272 31.651 -0.426 31.221 -0.426 c
+30.799 -0.426 30.487 -0.246 30.281 0.118 c
+30.251 -0.353 l
+29.648 -0.353 l
+29.648 5.292 l
+30.295 5.292 l
+30.295 3.19 l
+30.508 3.532 30.817 3.705 31.221 3.705 c
+31.651 3.705 31.975 3.547 32.191 3.234 c
+32.415 2.929 32.529 2.462 32.529 1.837 c
+h
+31.883 1.823 m
+31.883 2.294 31.813 2.624 31.677 2.822 c
+31.549 3.017 31.339 3.117 31.044 3.117 c
+30.71 3.117 30.46 2.932 30.295 2.573 c
+30.295 0.691 l
+30.46 0.327 30.714 0.147 31.06 0.147 c
+31.353 0.147 31.563 0.25 31.692 0.456 c
+31.817 0.661 31.883 0.977 31.883 1.411 c
+h
+35.013 3.013 m
+34.925 3.032 34.826 3.043 34.72 3.043 c
+34.385 3.043 34.15 2.859 34.014 2.499 c
+34.014 -0.353 l
+33.367 -0.353 l
+33.367 3.631 l
+33.999 3.631 l
+34.014 3.219 l
+34.19 3.543 34.433 3.705 34.749 3.705 c
+34.855 3.705 34.944 3.682 35.013 3.645 c
+h
+37.556 -0.353 m
+37.516 -0.264 37.49 -0.118 37.483 0.088 c
+37.248 -0.257 36.954 -0.426 36.601 -0.426 c
+36.237 -0.426 35.954 -0.33 35.748 -0.132 c
+35.55 0.073 35.455 0.36 35.455 0.735 c
+35.455 1.135 35.59 1.455 35.866 1.691 c
+36.138 1.933 36.513 2.058 36.983 2.058 c
+37.468 2.058 l
+37.468 2.484 l
+37.468 2.72 37.413 2.885 37.307 2.984 c
+37.196 3.09 37.035 3.146 36.822 3.146 c
+36.623 3.146 36.461 3.087 36.336 2.969 c
+36.218 2.851 36.16 2.705 36.16 2.529 c
+35.513 2.529 l
+35.513 2.723 35.572 2.914 35.69 3.102 c
+35.815 3.285 35.977 3.433 36.174 3.543 c
+36.38 3.649 36.608 3.705 36.866 3.705 c
+37.266 3.705 37.571 3.601 37.777 3.396 c
+37.99 3.19 38.104 2.896 38.115 2.514 c
+38.115 0.5 l
+38.115 0.195 38.152 -0.07 38.233 -0.294 c
+38.233 -0.353 l
+h
+36.689 0.162 m
+36.854 0.162 37.005 0.206 37.145 0.294 c
+37.292 0.382 37.398 0.493 37.468 0.632 c
+37.468 1.573 l
+37.101 1.573 l
+36.785 1.573 36.542 1.503 36.366 1.367 c
+36.189 1.239 36.101 1.051 36.101 0.809 c
+36.101 0.58 36.145 0.416 36.234 0.309 c
+36.322 0.21 36.472 0.162 36.689 0.162 c
+39.732 3.631 m
+39.746 3.19 l
+40 3.532 40.324 3.705 40.717 3.705 c
+41.423 3.705 41.778 3.234 41.789 2.294 c
+41.789 -0.353 l
+41.143 -0.353 l
+41.143 2.263 l
+41.143 2.576 41.088 2.797 40.981 2.926 c
+40.871 3.05 40.717 3.117 40.511 3.117 c
+40.353 3.117 40.206 3.061 40.07 2.955 c
+39.941 2.845 39.838 2.708 39.761 2.543 c
+39.761 -0.353 l
+39.114 -0.353 l
+39.114 3.631 l
+h
+44.141 0.133 m
+44.355 0.133 44.527 0.195 44.656 0.324 c
+44.792 0.459 44.866 0.651 44.876 0.897 c
+45.494 0.897 l
+45.472 0.515 45.336 0.195 45.082 -0.058 c
+44.825 -0.305 44.513 -0.426 44.141 -0.426 c
+43.649 -0.426 43.274 -0.276 43.01 0.029 c
+42.753 0.341 42.628 0.809 42.628 1.426 c
+42.628 1.867 l
+42.628 2.462 42.753 2.918 43.01 3.234 c
+43.274 3.547 43.649 3.705 44.141 3.705 c
+44.542 3.705 44.862 3.572 45.097 3.308 c
+45.34 3.05 45.472 2.705 45.494 2.263 c
+44.876 2.263 l
+44.854 2.558 44.781 2.778 44.656 2.926 c
+44.538 3.072 44.365 3.146 44.141 3.146 c
+43.848 3.146 43.631 3.046 43.495 2.851 c
+43.355 2.664 43.281 2.356 43.274 1.926 c
+43.274 1.411 l
+43.274 0.941 43.341 0.607 43.48 0.412 c
+43.627 0.224 43.848 0.133 44.141 0.133 c
+46.89 3.219 m
+47.144 3.543 47.463 3.705 47.846 3.705 c
+48.552 3.705 48.908 3.234 48.918 2.294 c
+48.918 -0.353 l
+48.272 -0.353 l
+48.272 2.263 l
+48.272 2.576 48.217 2.797 48.11 2.926 c
+48 3.05 47.846 3.117 47.64 3.117 c
+47.482 3.117 47.335 3.061 47.199 2.955 c
+47.071 2.845 46.967 2.708 46.89 2.543 c
+46.89 -0.353 l
+46.244 -0.353 l
+46.244 5.292 l
+46.89 5.292 l
+h
+51.3 -0.426 m
+50.8 -0.426 50.418 -0.279 50.154 0.015 c
+49.889 0.309 49.757 0.742 49.757 1.323 c
+49.757 1.793 l
+49.757 2.389 49.882 2.855 50.139 3.19 c
+50.403 3.532 50.763 3.705 51.226 3.705 c
+51.686 3.705 52.028 3.55 52.255 3.248 c
+52.49 2.955 52.612 2.492 52.623 1.867 c
+52.623 1.44 l
+50.403 1.44 l
+50.403 1.353 l
+50.403 0.919 50.48 0.607 50.638 0.412 c
+50.804 0.224 51.035 0.133 51.33 0.133 c
+51.524 0.133 51.696 0.166 51.844 0.235 c
+51.991 0.312 52.126 0.43 52.255 0.588 c
+52.594 0.177 l
+52.307 -0.228 51.877 -0.426 51.3 -0.426 c
+51.226 3.146 m
+50.95 3.146 50.749 3.05 50.624 2.866 c
+50.495 2.679 50.422 2.389 50.403 1.999 c
+51.976 1.999 l
+51.976 2.087 l
+51.954 2.469 51.888 2.738 51.771 2.896 c
+51.653 3.061 51.469 3.146 51.226 3.146 c
+55.342 0.661 m
+55.342 0.809 55.287 0.929 55.181 1.029 c
+55.07 1.124 54.865 1.242 54.563 1.382 c
+54.218 1.529 53.975 1.65 53.828 1.75 c
+53.681 1.856 53.571 1.974 53.505 2.103 c
+53.435 2.227 53.402 2.385 53.402 2.573 c
+53.402 2.896 53.52 3.164 53.755 3.381 c
+53.99 3.594 54.291 3.705 54.666 3.705 c
+55.048 3.705 55.357 3.591 55.592 3.366 c
+55.827 3.138 55.945 2.851 55.945 2.499 c
+55.299 2.499 l
+55.299 2.675 55.239 2.826 55.122 2.955 c
+55.004 3.08 54.85 3.146 54.666 3.146 c
+54.468 3.146 54.317 3.09 54.21 2.984 c
+54.1 2.885 54.048 2.753 54.048 2.587 c
+54.048 2.458 54.086 2.352 54.166 2.263 c
+54.243 2.183 54.435 2.08 54.74 1.955 c
+55.218 1.768 55.548 1.58 55.725 1.397 c
+55.901 1.22 55.989 0.992 55.989 0.721 c
+55.989 0.368 55.864 0.088 55.621 -0.118 c
+55.386 -0.324 55.07 -0.426 54.68 -0.426 c
+54.258 -0.426 53.92 -0.309 53.666 -0.073 c
+53.41 0.169 53.284 0.474 53.284 0.838 c
+53.931 0.838 l
+53.938 0.611 54.008 0.434 54.137 0.309 c
+54.262 0.191 54.445 0.133 54.68 0.133 c
+54.894 0.133 55.056 0.181 55.166 0.279 c
+55.284 0.375 55.342 0.503 55.342 0.661 c
+58.532 1.823 m
+58.532 2.458 58.62 3.061 58.796 3.631 c
+58.973 4.197 59.216 4.692 59.532 5.116 c
+59.727 5.38 59.914 5.571 60.09 5.689 c
+60.222 5.233 l
+59.928 4.958 59.686 4.534 59.502 3.969 c
+59.315 3.399 59.212 2.768 59.193 2.072 c
+59.193 1.779 l
+59.193 0.915 59.311 0.151 59.546 -0.515 c
+59.73 -1.014 59.958 -1.396 60.222 -1.66 c
+60.09 -2.088 l
+59.862 -1.929 59.638 -1.679 59.414 -1.338 c
+58.826 -0.455 58.532 0.595 58.532 1.823 c
+63.883 0.794 m
+64.485 3.631 l
+65.132 3.631 l
+64.147 -0.353 l
+63.633 -0.353 l
+62.854 2.499 l
+62.104 -0.353 l
+61.574 -0.353 l
+60.619 3.631 l
+61.252 3.631 l
+61.869 0.867 l
+62.603 3.631 l
+63.118 3.631 l
+h
+66.513 -0.353 -0.646 3.984 re
+66.557 4.675 m
+66.557 4.564 66.528 4.472 66.47 4.395 c
+66.411 4.326 66.316 4.293 66.19 4.293 c
+66.073 4.293 65.977 4.326 65.911 4.395 c
+65.852 4.472 65.823 4.564 65.823 4.675 c
+65.823 4.792 65.852 4.884 65.911 4.954 c
+65.977 5.031 66.073 5.072 66.19 5.072 c
+66.316 5.072 66.411 5.031 66.47 4.954 c
+66.528 4.873 66.557 4.781 66.557 4.675 c
+68.38 4.586 m
+68.38 3.631 l
+68.983 3.631 l
+68.983 3.102 l
+68.38 3.102 l
+68.38 0.632 l
+68.38 0.474 68.402 0.357 68.454 0.279 c
+68.512 0.198 68.601 0.162 68.718 0.162 c
+68.807 0.162 68.895 0.177 68.983 0.206 c
+68.983 -0.353 l
+68.836 -0.401 68.681 -0.426 68.527 -0.426 c
+68.27 -0.426 68.076 -0.334 67.939 -0.147 c
+67.8 0.037 67.733 0.298 67.733 0.632 c
+67.733 3.102 l
+67.131 3.102 l
+67.131 3.631 l
+67.733 3.631 l
+67.733 4.586 l
+h
+70.394 3.219 m
+70.648 3.543 70.968 3.705 71.349 3.705 c
+72.055 3.705 72.412 3.234 72.423 2.294 c
+72.423 -0.353 l
+71.776 -0.353 l
+71.776 2.263 l
+71.776 2.576 71.721 2.797 71.614 2.926 c
+71.504 3.05 71.349 3.117 71.143 3.117 c
+70.985 3.117 70.839 3.061 70.703 2.955 c
+70.574 2.845 70.471 2.708 70.394 2.543 c
+70.394 -0.353 l
+69.747 -0.353 l
+69.747 5.292 l
+70.394 5.292 l
+h
+76.744 3.013 m
+76.656 3.032 76.556 3.043 76.45 3.043 c
+76.115 3.043 75.88 2.859 75.745 2.499 c
+75.745 -0.353 l
+75.097 -0.353 l
+75.097 3.631 l
+75.729 3.631 l
+75.745 3.219 l
+75.92 3.543 76.163 3.705 76.479 3.705 c
+76.586 3.705 76.674 3.682 76.744 3.645 c
+h
+78.743 -0.426 m
+78.243 -0.426 77.861 -0.279 77.597 0.015 c
+77.332 0.309 77.2 0.742 77.2 1.323 c
+77.2 1.793 l
+77.2 2.389 77.325 2.855 77.582 3.19 c
+77.846 3.532 78.206 3.705 78.669 3.705 c
+79.129 3.705 79.471 3.55 79.698 3.248 c
+79.934 2.955 80.055 2.492 80.066 1.867 c
+80.066 1.44 l
+77.846 1.44 l
+77.846 1.353 l
+77.846 0.919 77.923 0.607 78.081 0.412 c
+78.247 0.224 78.478 0.133 78.773 0.133 c
+78.968 0.133 79.14 0.166 79.287 0.235 c
+79.434 0.312 79.57 0.43 79.698 0.588 c
+80.036 0.177 l
+79.75 -0.228 79.32 -0.426 78.743 -0.426 c
+78.669 3.146 m
+78.394 3.146 78.192 3.05 78.067 2.866 c
+77.938 2.679 77.865 2.389 77.846 1.999 c
+79.419 1.999 l
+79.419 2.087 l
+79.397 2.469 79.331 2.738 79.213 2.896 c
+79.095 3.061 78.912 3.146 78.669 3.146 c
+81.462 3.631 m
+81.477 3.263 l
+81.72 3.557 82.039 3.705 82.432 3.705 c
+82.873 3.705 83.182 3.506 83.359 3.117 c
+83.612 3.506 83.961 3.705 84.402 3.705 c
+85.137 3.705 85.512 3.241 85.534 2.323 c
+85.534 -0.353 l
+84.888 -0.353 l
+84.888 2.263 l
+84.888 2.558 84.832 2.77 84.726 2.911 c
+84.626 3.046 84.454 3.117 84.211 3.117 c
+84.013 3.117 83.851 3.036 83.726 2.881 c
+83.608 2.734 83.539 2.543 83.521 2.308 c
+83.521 -0.353 l
+82.858 -0.353 l
+82.858 2.294 l
+82.858 2.841 82.638 3.117 82.197 3.117 c
+81.863 3.117 81.628 2.955 81.492 2.631 c
+81.492 -0.353 l
+80.845 -0.353 l
+80.845 3.631 l
+h
+86.372 1.823 m
+86.372 2.4 86.508 2.855 86.783 3.19 c
+87.066 3.532 87.438 3.705 87.901 3.705 c
+88.36 3.705 88.728 3.535 89.003 3.204 c
+89.286 2.881 89.433 2.433 89.444 1.867 c
+89.444 1.44 l
+89.444 0.871 89.301 0.416 89.017 0.073 c
+88.742 -0.261 88.375 -0.426 87.915 -0.426 c
+87.452 -0.426 87.081 -0.264 86.798 0.059 c
+86.523 0.389 86.38 0.831 86.372 1.382 c
+h
+87.018 1.44 m
+87.018 1.037 87.096 0.721 87.254 0.485 c
+87.419 0.25 87.639 0.133 87.915 0.133 c
+88.481 0.133 88.776 0.544 88.797 1.367 c
+88.797 1.823 l
+88.797 2.223 88.713 2.543 88.547 2.778 c
+88.389 3.021 88.173 3.146 87.901 3.146 c
+87.636 3.146 87.419 3.021 87.254 2.778 c
+87.096 2.543 87.018 2.223 87.018 1.823 c
+h
+91.134 4.586 m
+91.134 3.631 l
+91.737 3.631 l
+91.737 3.102 l
+91.134 3.102 l
+91.134 0.632 l
+91.134 0.474 91.157 0.357 91.208 0.279 c
+91.267 0.198 91.355 0.162 91.473 0.162 c
+91.56 0.162 91.649 0.177 91.737 0.206 c
+91.737 -0.353 l
+91.59 -0.401 91.436 -0.426 91.282 -0.426 c
+91.024 -0.426 90.829 -0.334 90.694 -0.147 c
+90.554 0.037 90.488 0.298 90.488 0.632 c
+90.488 3.102 l
+89.885 3.102 l
+89.885 3.631 l
+90.488 3.631 l
+90.488 4.586 l
+h
+93.927 -0.426 m
+93.428 -0.426 93.046 -0.279 92.78 0.015 c
+92.516 0.309 92.383 0.742 92.383 1.323 c
+92.383 1.793 l
+92.383 2.389 92.509 2.855 92.766 3.19 c
+93.031 3.532 93.391 3.705 93.854 3.705 c
+94.313 3.705 94.655 3.55 94.883 3.248 c
+95.118 2.955 95.24 2.492 95.25 1.867 c
+95.25 1.44 l
+93.031 1.44 l
+93.031 1.353 l
+93.031 0.919 93.108 0.607 93.266 0.412 c
+93.431 0.224 93.663 0.133 93.956 0.133 c
+94.151 0.133 94.324 0.166 94.471 0.235 c
+94.618 0.312 94.754 0.43 94.883 0.588 c
+95.221 0.177 l
+94.934 -0.228 94.504 -0.426 93.927 -0.426 c
+93.854 3.146 m
+93.578 3.146 93.376 3.05 93.251 2.866 c
+93.123 2.679 93.049 2.389 93.031 1.999 c
+94.604 1.999 l
+94.604 2.087 l
+94.581 2.469 94.515 2.738 94.398 2.896 c
+94.28 3.061 94.097 3.146 93.854 3.146 c
+97.426 1.779 m
+97.426 0.691 97.179 -0.276 96.691 -1.117 c
+96.426 -1.565 96.15 -1.889 95.868 -2.088 c
+95.75 -1.66 l
+96.051 -1.367 96.298 -0.914 96.485 -0.309 c
+96.68 0.298 96.779 0.963 96.779 1.691 c
+96.779 1.823 l
+96.779 2.753 96.624 3.587 96.323 4.322 c
+96.154 4.723 95.963 5.042 95.75 5.278 c
+95.868 5.689 l
+96.14 5.501 96.404 5.203 96.661 4.792 c
+97.168 3.94 97.426 2.932 97.426 1.779 c
+98.469 0 m
+98.469 0.118 98.502 0.214 98.573 0.294 c
+98.638 0.372 98.741 0.412 98.881 0.412 c
+99.028 0.412 99.134 0.372 99.204 0.294 c
+99.282 0.214 99.321 0.118 99.321 0 c
+99.321 -0.11 99.282 -0.202 99.204 -0.279 c
+99.134 -0.357 99.028 -0.397 98.881 -0.397 c
+98.741 -0.397 98.638 -0.357 98.573 -0.279 c
+98.502 -0.202 98.469 -0.11 98.469 0 c
+f
+Q
+0.113 0.082 0.09 0 k
+535.667 224.097 238.665 -12.895 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 540.8555 217.2583 cm
+0 0 m
+0 -0.188 -0.029 -0.353 -0.088 -0.5 c
+-0.147 -0.647 -0.242 -0.776 -0.367 -0.882 c
+-0.496 -0.992 -0.658 -1.081 -0.852 -1.147 c
+-1.051 -1.206 -1.278 -1.243 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.264 l
+-2.142 -1.257 -2.358 -1.22 -2.543 -1.162 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.927 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.214 -3.484 -0.015 c
+-2.66 0.132 l
+-2.642 0.033 -2.616 -0.059 -2.587 -0.148 c
+-2.55 -0.228 -2.506 -0.302 -2.454 -0.368 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.675 c
+-1.977 0.683 -1.992 0.691 -1.999 0.691 c
+-2.167 0.727 -2.329 0.771 -2.484 0.823 c
+-2.642 0.881 -2.786 0.959 -2.91 1.058 c
+-3.039 1.153 -3.141 1.278 -3.218 1.425 c
+-3.289 1.573 -3.322 1.756 -3.322 1.984 c
+-3.322 2.179 -3.289 2.344 -3.218 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.836 c
+-2.8 2.932 -2.645 3.002 -2.469 3.042 c
+-2.293 3.09 -2.102 3.119 -1.896 3.131 c
+-1.896 3.557 l
+-1.543 3.557 l
+-1.543 3.131 l
+-1.319 3.119 -1.128 3.09 -0.97 3.042 c
+-0.804 2.991 -0.669 2.917 -0.558 2.822 c
+-0.44 2.734 -0.349 2.62 -0.279 2.484 c
+-0.201 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.252 -1.213 2.458 -1.543 2.499 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.359 -1.469 1.352 c
+-1.294 1.311 -1.117 1.263 -0.941 1.205 c
+-0.756 1.146 -0.595 1.066 -0.455 0.97 c
+-0.319 0.87 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.454 c
+-2.26 2.425 -2.318 2.385 -2.366 2.337 c
+-2.406 2.296 -2.436 2.248 -2.454 2.19 c
+-2.476 2.131 -2.484 2.065 -2.484 1.999 c
+-2.484 1.911 -2.469 1.837 -2.439 1.778 c
+-2.41 1.72 -2.373 1.668 -2.322 1.631 c
+-2.263 1.591 -2.2 1.558 -2.131 1.529 c
+-2.065 1.499 -1.984 1.469 -1.896 1.44 c
+h
+-0.837 -0.015 m
+-0.837 0.091 -0.86 0.176 -0.897 0.235 c
+-0.926 0.301 -0.977 0.357 -1.043 0.397 c
+-1.102 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.529 -1.448 0.558 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.53 -1.028 -0.441 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.015 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.52 -2.484 5.403 -2.396 c
+5.285 -2.315 5.185 -2.22 5.108 -2.103 c
+5.039 -1.985 4.991 -1.856 4.961 -1.72 c
+5.858 -1.617 l
+5.895 -1.754 5.964 -1.86 6.064 -1.941 c
+6.159 -2.029 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.058 6.681 -2.029 c
+6.758 -1.999 6.828 -1.945 6.887 -1.867 c
+6.945 -1.797 6.99 -1.706 7.019 -1.588 c
+7.056 -1.47 7.078 -1.324 7.078 -1.147 c
+7.078 -0.956 l
+7.078 -0.89 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.073 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.214 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.412 4.888 -0.206 c
+4.836 0.008 4.815 0.243 4.815 0.5 c
+4.815 0.771 4.836 1.018 4.888 1.234 c
+4.946 1.448 5.027 1.631 5.137 1.778 c
+5.245 1.932 5.376 2.05 5.534 2.131 c
+5.689 2.219 5.876 2.263 6.093 2.263 c
+6.189 2.263 6.288 2.252 6.387 2.234 c
+6.483 2.212 6.571 2.179 6.652 2.131 c
+6.739 2.08 6.817 2.017 6.887 1.94 c
+6.964 1.859 7.026 1.768 7.078 1.66 c
+7.092 1.66 l
+7.092 1.808 l
+7.1 1.866 7.107 1.918 7.107 1.969 c
+7.115 2.028 7.122 2.076 7.122 2.117 c
+7.13 2.164 7.14 2.198 7.151 2.219 c
+8.004 2.219 l
+7.992 2.138 7.982 2.028 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.162 l
+7.975 -1.415 7.938 -1.636 7.872 -1.823 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.404 7.258 -2.5 7.063 -2.558 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.529 m
+7.092 0.742 7.067 0.918 7.019 1.058 c
+6.978 1.205 6.924 1.323 6.857 1.411 c
+6.799 1.499 6.729 1.558 6.652 1.587 c
+6.571 1.624 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.226 1.62 6.137 1.573 c
+6.056 1.532 5.991 1.462 5.931 1.367 c
+5.88 1.278 5.835 1.161 5.799 1.014 c
+5.77 0.874 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.339 c
+6.049 -0.515 6.211 -0.603 6.417 -0.603 c
+6.483 -0.603 6.556 -0.588 6.637 -0.559 c
+6.725 -0.522 6.799 -0.463 6.857 -0.383 c
+6.924 -0.294 6.978 -0.177 7.019 -0.03 c
+7.067 0.118 7.092 0.301 7.092 0.529 c
+11.036 -0.647 m
+12.168 -0.647 l
+12.168 -1.264 l
+8.86 -1.264 l
+8.86 -0.647 l
+10.124 -0.647 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.219 l
+11.036 2.219 l
+h
+10.124 3.513 0.912 -0.676 re
+10.124 2.836 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.219 l
+13.644 2.219 l
+13.924 3.116 l
+14.498 3.116 l
+14.498 2.219 l
+15.732 2.219 l
+15.732 1.602 l
+14.498 1.602 l
+14.498 -0.103 l
+14.498 -0.324 l
+14.504 -0.393 14.527 -0.456 14.556 -0.515 c
+14.593 -0.566 14.648 -0.611 14.718 -0.647 c
+14.795 -0.676 14.909 -0.691 15.056 -0.691 c
+15.192 -0.691 15.327 -0.688 15.468 -0.676 c
+15.603 -0.659 15.736 -0.632 15.865 -0.603 c
+15.865 -1.206 l
+15.784 -1.216 15.707 -1.231 15.629 -1.249 c
+15.549 -1.261 15.471 -1.268 15.394 -1.279 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.042 -1.301 14.942 -1.309 14.836 -1.309 c
+14.648 -1.309 14.486 -1.294 14.35 -1.264 c
+14.222 -1.228 14.107 -1.183 14.012 -1.132 c
+13.924 -1.085 13.85 -1.025 13.792 -0.956 c
+13.733 -0.879 13.689 -0.802 13.66 -0.721 c
+13.63 -0.632 13.608 -0.544 13.6 -0.456 c
+13.59 -0.36 13.586 -0.265 13.586 -0.177 c
+h
+21.12 -1.264 m
+21.12 -0.971 l
+21.126 -0.834 21.134 -0.676 21.134 -0.5 c
+21.134 3.513 l
+22.045 3.513 l
+22.045 2.234 l
+22.045 2.072 l
+22.045 1.896 l
+22.045 1.845 22.038 1.801 22.03 1.764 c
+22.03 1.675 l
+22.045 1.675 l
+22.093 1.782 22.155 1.874 22.236 1.955 c
+22.313 2.032 22.398 2.094 22.487 2.146 c
+22.574 2.194 22.666 2.227 22.766 2.248 c
+22.861 2.267 22.961 2.278 23.059 2.278 c
+23.273 2.278 23.46 2.234 23.618 2.146 c
+23.773 2.057 23.901 1.929 24 1.764 c
+24.106 1.606 24.184 1.415 24.235 1.19 c
+24.283 0.974 24.309 0.735 24.309 0.47 c
+24.309 0.213 24.28 -0.026 24.22 -0.25 c
+24.162 -0.467 24.077 -0.659 23.971 -0.823 c
+23.861 -0.981 23.728 -1.103 23.574 -1.191 c
+23.416 -1.279 23.236 -1.324 23.03 -1.324 c
+22.931 -1.324 22.832 -1.312 22.736 -1.294 c
+22.648 -1.272 22.56 -1.243 22.471 -1.191 c
+22.383 -1.132 22.302 -1.066 22.236 -0.985 c
+22.167 -0.908 22.104 -0.809 22.045 -0.691 c
+22.03 -0.691 l
+22.03 -0.853 l
+22.03 -0.912 22.024 -0.971 22.016 -1.029 c
+22.016 -1.081 22.009 -1.129 22.001 -1.176 c
+22.001 -1.216 21.994 -1.246 21.986 -1.264 c
+h
+22.03 0.5 m
+22.03 0.264 22.049 0.066 22.09 -0.088 c
+22.137 -0.246 22.196 -0.368 22.265 -0.456 c
+22.332 -0.544 22.406 -0.611 22.487 -0.647 c
+22.564 -0.688 22.641 -0.706 22.722 -0.706 c
+22.927 -0.706 23.082 -0.611 23.192 -0.412 c
+23.31 -0.217 23.368 0.077 23.368 0.47 c
+23.368 0.683 23.346 0.867 23.31 1.014 c
+23.28 1.168 23.236 1.294 23.177 1.381 c
+23.125 1.477 23.059 1.55 22.971 1.602 c
+22.89 1.65 22.803 1.675 22.707 1.675 c
+22.626 1.675 22.549 1.654 22.471 1.616 c
+22.391 1.576 22.317 1.514 22.251 1.425 c
+22.192 1.338 22.137 1.213 22.09 1.058 c
+22.049 0.911 22.03 0.723 22.03 0.5 c
+28.193 1.469 m
+28.094 1.477 27.991 1.488 27.884 1.499 c
+27.774 1.517 27.653 1.529 27.517 1.529 c
+27.341 1.529 27.183 1.488 27.046 1.411 c
+26.907 1.341 26.789 1.242 26.693 1.117 c
+26.606 0.988 26.535 0.841 26.488 0.675 c
+26.448 0.507 26.429 0.33 26.429 0.147 c
+26.429 -1.264 l
+25.533 -1.264 l
+25.533 0.985 l
+25.533 1.109 25.521 1.234 25.503 1.352 c
+25.492 1.477 25.477 1.595 25.459 1.705 c
+25.448 1.822 25.434 1.918 25.415 1.999 c
+25.393 2.087 25.375 2.161 25.356 2.219 c
+26.238 2.219 l
+26.246 2.167 26.257 2.117 26.267 2.057 c
+26.286 1.999 26.3 1.932 26.312 1.866 c
+26.33 1.808 26.344 1.741 26.356 1.675 c
+26.363 1.606 26.375 1.543 26.385 1.484 c
+26.4 1.484 l
+26.437 1.602 26.488 1.708 26.547 1.808 c
+26.613 1.903 26.693 1.988 26.782 2.057 c
+26.87 2.124 26.973 2.179 27.09 2.219 c
+27.216 2.256 27.362 2.278 27.532 2.278 c
+27.657 2.278 27.774 2.271 27.884 2.263 c
+28.002 2.252 28.105 2.238 28.193 2.219 c
+h
+30.196 -1.324 m
+30.026 -1.324 29.876 -1.301 29.741 -1.264 c
+29.612 -1.216 29.498 -1.147 29.402 -1.058 c
+29.314 -0.971 29.244 -0.864 29.197 -0.736 c
+29.145 -0.599 29.122 -0.449 29.122 -0.279 c
+29.122 -0.073 29.156 0.095 29.226 0.235 c
+29.292 0.382 29.388 0.492 29.505 0.573 c
+29.63 0.661 29.773 0.723 29.932 0.764 c
+30.097 0.801 30.273 0.827 30.46 0.837 c
+31.181 0.852 l
+31.181 1.028 l
+31.181 1.146 31.169 1.249 31.152 1.338 c
+31.129 1.425 31.096 1.492 31.048 1.543 c
+31.008 1.602 30.961 1.639 30.901 1.66 c
+30.843 1.679 30.776 1.691 30.71 1.691 c
+30.641 1.691 30.578 1.679 30.519 1.66 c
+30.468 1.65 30.42 1.624 30.373 1.587 c
+30.332 1.558 30.298 1.506 30.269 1.44 c
+30.248 1.381 30.233 1.301 30.225 1.205 c
+29.284 1.249 l
+29.314 1.396 29.358 1.532 29.417 1.66 c
+29.483 1.786 29.579 1.896 29.696 1.984 c
+29.814 2.08 29.953 2.153 30.122 2.204 c
+30.298 2.252 30.504 2.278 30.74 2.278 c
+31.181 2.278 31.511 2.167 31.74 1.955 c
+31.975 1.749 32.092 1.44 32.092 1.028 c
+32.092 -0.235 l
+32.092 -0.456 l
+32.099 -0.515 32.114 -0.57 32.137 -0.618 c
+32.154 -0.659 32.184 -0.691 32.224 -0.721 c
+32.261 -0.742 32.313 -0.75 32.372 -0.75 c
+32.438 -0.75 32.507 -0.746 32.577 -0.736 c
+32.577 -1.22 l
+32.519 -1.231 32.463 -1.243 32.415 -1.249 c
+32.375 -1.261 32.334 -1.268 32.297 -1.279 c
+32.257 -1.286 32.214 -1.294 32.166 -1.294 c
+32.114 -1.301 32.056 -1.309 31.989 -1.309 c
+31.761 -1.309 31.596 -1.257 31.489 -1.147 c
+31.379 -1.029 31.316 -0.864 31.298 -0.647 c
+31.283 -0.647 l
+31.214 -0.757 31.144 -0.853 31.078 -0.941 c
+31.008 -1.022 30.931 -1.088 30.843 -1.147 c
+30.755 -1.206 30.655 -1.249 30.549 -1.279 c
+30.45 -1.309 30.332 -1.324 30.196 -1.324 c
+31.181 0.353 m
+30.755 0.338 l
+30.655 0.338 30.564 0.33 30.475 0.323 c
+30.394 0.312 30.328 0.286 30.269 0.249 c
+30.211 0.209 30.159 0.151 30.122 0.073 c
+30.082 0.004 30.063 -0.088 30.063 -0.206 c
+30.063 -0.375 30.097 -0.497 30.167 -0.574 c
+30.233 -0.655 30.332 -0.691 30.46 -0.691 c
+30.567 -0.691 30.666 -0.669 30.755 -0.618 c
+30.85 -0.57 30.931 -0.507 30.99 -0.426 c
+31.056 -0.349 31.107 -0.262 31.137 -0.162 c
+31.166 -0.055 31.181 0.058 31.181 0.176 c
+h
+35.495 -1.264 m
+35.495 0.72 l
+35.495 1.022 35.451 1.242 35.362 1.381 c
+35.281 1.529 35.146 1.602 34.951 1.602 c
+34.841 1.602 34.738 1.576 34.643 1.529 c
+34.554 1.477 34.473 1.411 34.408 1.323 c
+34.348 1.234 34.297 1.124 34.26 0.999 c
+34.231 0.881 34.216 0.75 34.216 0.602 c
+34.216 -1.264 l
+33.305 -1.264 l
+33.305 1.44 l
+33.305 1.66 l
+33.305 1.749 33.297 1.826 33.29 1.896 c
+33.29 2.087 l
+33.29 2.219 l
+34.142 2.219 l
+34.15 2.19 34.157 2.146 34.157 2.087 c
+34.157 1.896 l
+34.165 1.826 34.172 1.756 34.172 1.691 c
+34.179 1.62 34.186 1.565 34.186 1.529 c
+34.202 1.529 l
+34.319 1.793 34.47 1.984 34.657 2.102 c
+34.841 2.219 35.061 2.278 35.318 2.278 c
+35.503 2.278 35.664 2.248 35.804 2.19 c
+35.939 2.131 36.054 2.043 36.141 1.926 c
+36.23 1.808 36.293 1.664 36.332 1.499 c
+36.38 1.341 36.407 1.153 36.407 0.941 c
+36.407 -1.264 l
+h
+38.923 -1.324 m
+38.637 -1.324 38.394 -1.283 38.188 -1.206 c
+37.982 -1.118 37.81 -0.996 37.674 -0.838 c
+37.535 -0.684 37.431 -0.497 37.365 -0.279 c
+37.296 -0.055 37.263 0.191 37.263 0.455 c
+37.263 0.75 37.296 1.007 37.365 1.234 c
+37.442 1.458 37.549 1.646 37.689 1.793 c
+37.836 1.947 38.012 2.065 38.218 2.146 c
+38.424 2.234 38.659 2.278 38.923 2.278 c
+39.148 2.278 39.35 2.248 39.526 2.19 c
+39.702 2.131 39.854 2.046 39.981 1.94 c
+40.107 1.841 40.21 1.72 40.291 1.573 c
+40.368 1.433 40.423 1.282 40.452 1.117 c
+39.541 1.072 l
+39.511 1.249 39.441 1.389 39.335 1.499 c
+39.235 1.606 39.092 1.66 38.909 1.66 c
+38.662 1.66 38.487 1.558 38.379 1.352 c
+38.269 1.153 38.218 0.867 38.218 0.484 c
+38.218 -0.309 38.453 -0.706 38.923 -0.706 c
+39.089 -0.706 39.232 -0.655 39.35 -0.544 c
+39.467 -0.437 39.541 -0.276 39.57 -0.059 c
+40.482 -0.103 l
+40.452 -0.272 40.397 -0.426 40.32 -0.574 c
+40.25 -0.721 40.147 -0.853 40.012 -0.971 c
+39.883 -1.081 39.725 -1.168 39.541 -1.235 c
+39.364 -1.294 39.158 -1.324 38.923 -1.324 c
+42.323 1.514 m
+42.441 1.786 42.591 1.984 42.778 2.102 c
+42.962 2.219 43.183 2.278 43.44 2.278 c
+43.646 2.278 43.815 2.242 43.954 2.175 c
+44.101 2.105 44.211 2.013 44.292 1.896 c
+44.38 1.778 44.44 1.635 44.469 1.469 c
+44.505 1.301 44.527 1.124 44.527 0.941 c
+44.527 -1.264 l
+43.616 -1.264 l
+43.616 0.735 l
+43.616 0.87 43.605 0.992 43.586 1.103 c
+43.576 1.209 43.55 1.297 43.513 1.367 c
+43.473 1.444 43.414 1.502 43.337 1.543 c
+43.267 1.58 43.175 1.602 43.058 1.602 c
+42.948 1.602 42.852 1.576 42.763 1.529 c
+42.676 1.477 42.595 1.411 42.528 1.323 c
+42.47 1.234 42.418 1.124 42.381 0.999 c
+42.352 0.881 42.337 0.75 42.337 0.602 c
+42.337 -1.264 l
+41.426 -1.264 l
+41.426 3.513 l
+42.337 3.513 l
+42.337 2.204 l
+42.337 2.135 42.329 2.065 42.323 1.999 c
+42.323 1.793 l
+42.323 1.734 42.315 1.679 42.308 1.631 c
+42.308 1.514 l
+h
+50.297 -2.631 m
+50.297 3.513 l
+52.222 3.513 l
+52.222 2.896 l
+51.149 2.896 l
+51.149 -2.014 l
+52.222 -2.014 l
+52.222 -2.631 l
+h
+55.802 -1.264 m
+55.802 0.72 l
+55.802 1.022 55.758 1.242 55.669 1.381 c
+55.588 1.529 55.453 1.602 55.258 1.602 c
+55.147 1.602 55.044 1.576 54.95 1.529 c
+54.861 1.477 54.78 1.411 54.714 1.323 c
+54.655 1.234 54.603 1.124 54.567 0.999 c
+54.537 0.881 54.522 0.75 54.522 0.602 c
+54.522 -1.264 l
+53.612 -1.264 l
+53.612 1.44 l
+53.612 1.66 l
+53.612 1.749 53.604 1.826 53.597 1.896 c
+53.597 2.087 l
+53.597 2.219 l
+54.449 2.219 l
+54.457 2.19 54.464 2.146 54.464 2.087 c
+54.464 1.896 l
+54.472 1.826 54.479 1.756 54.479 1.691 c
+54.486 1.62 54.493 1.565 54.493 1.529 c
+54.508 1.529 l
+54.626 1.793 54.776 1.984 54.964 2.102 c
+55.147 2.219 55.368 2.278 55.625 2.278 c
+55.809 2.278 55.97 2.248 56.11 2.19 c
+56.246 2.131 56.361 2.043 56.448 1.926 c
+56.536 1.808 56.599 1.664 56.639 1.499 c
+56.687 1.341 56.713 1.153 56.713 0.941 c
+56.713 -1.264 l
+h
+58.628 -1.324 m
+58.458 -1.324 58.308 -1.301 58.172 -1.264 c
+58.044 -1.216 57.93 -1.147 57.834 -1.058 c
+57.745 -0.971 57.676 -0.864 57.628 -0.736 c
+57.576 -0.599 57.554 -0.449 57.554 -0.279 c
+57.554 -0.073 57.587 0.095 57.657 0.235 c
+57.724 0.382 57.819 0.492 57.936 0.573 c
+58.062 0.661 58.204 0.723 58.363 0.764 c
+58.528 0.801 58.705 0.827 58.892 0.837 c
+59.613 0.852 l
+59.613 1.028 l
+59.613 1.146 59.602 1.249 59.583 1.338 c
+59.561 1.425 59.528 1.492 59.48 1.543 c
+59.44 1.602 59.392 1.639 59.333 1.66 c
+59.274 1.679 59.208 1.691 59.142 1.691 c
+59.072 1.691 59.01 1.679 58.951 1.66 c
+58.9 1.65 58.852 1.624 58.804 1.587 c
+58.763 1.558 58.73 1.506 58.701 1.44 c
+58.679 1.381 58.664 1.301 58.657 1.205 c
+57.716 1.249 l
+57.745 1.396 57.79 1.532 57.849 1.66 c
+57.915 1.786 58.01 1.896 58.127 1.984 c
+58.245 2.08 58.385 2.153 58.554 2.204 c
+58.73 2.252 58.936 2.278 59.172 2.278 c
+59.613 2.278 59.943 2.167 60.171 1.955 c
+60.406 1.749 60.523 1.44 60.523 1.028 c
+60.523 -0.235 l
+60.523 -0.456 l
+60.531 -0.515 60.546 -0.57 60.568 -0.618 c
+60.586 -0.659 60.616 -0.691 60.656 -0.721 c
+60.693 -0.742 60.744 -0.75 60.803 -0.75 c
+60.869 -0.75 60.939 -0.746 61.009 -0.736 c
+61.009 -1.22 l
+60.95 -1.231 60.895 -1.243 60.847 -1.249 c
+60.807 -1.261 60.766 -1.268 60.729 -1.279 c
+60.689 -1.286 60.645 -1.294 60.597 -1.294 c
+60.546 -1.301 60.487 -1.309 60.421 -1.309 c
+60.193 -1.309 60.028 -1.257 59.921 -1.147 c
+59.811 -1.029 59.748 -0.864 59.73 -0.647 c
+59.715 -0.647 l
+59.646 -0.757 59.576 -0.853 59.509 -0.941 c
+59.44 -1.022 59.363 -1.088 59.274 -1.147 c
+59.186 -1.206 59.087 -1.249 58.981 -1.279 c
+58.881 -1.309 58.763 -1.324 58.628 -1.324 c
+59.613 0.353 m
+59.186 0.338 l
+59.087 0.338 58.995 0.33 58.907 0.323 c
+58.826 0.312 58.76 0.286 58.701 0.249 c
+58.642 0.209 58.591 0.151 58.554 0.073 c
+58.514 0.004 58.495 -0.088 58.495 -0.206 c
+58.495 -0.375 58.528 -0.497 58.598 -0.574 c
+58.664 -0.655 58.763 -0.691 58.892 -0.691 c
+58.998 -0.691 59.098 -0.669 59.186 -0.618 c
+59.282 -0.57 59.363 -0.507 59.421 -0.426 c
+59.488 -0.349 59.538 -0.262 59.569 -0.162 c
+59.598 -0.055 59.613 0.058 59.613 0.176 c
+h
+62.894 -1.264 m
+62.894 0.852 l
+62.894 1.018 62.887 1.153 62.879 1.263 c
+62.869 1.371 62.85 1.455 62.821 1.514 c
+62.798 1.58 62.769 1.631 62.732 1.66 c
+62.703 1.691 62.663 1.705 62.615 1.705 c
+62.555 1.705 62.501 1.675 62.453 1.616 c
+62.412 1.565 62.38 1.492 62.35 1.396 c
+62.32 1.308 62.295 1.194 62.277 1.058 c
+62.266 0.918 62.262 0.768 62.262 0.602 c
+62.262 -1.264 l
+61.512 -1.264 l
+61.512 1.469 l
+61.512 1.705 l
+61.512 1.926 l
+61.512 2.003 61.505 2.065 61.497 2.117 c
+61.497 2.219 l
+62.173 2.219 l
+62.173 2.131 l
+62.173 1.984 l
+62.181 1.926 62.189 1.866 62.189 1.808 c
+62.189 1.646 l
+62.203 1.646 l
+62.221 1.734 62.251 1.811 62.291 1.881 c
+62.328 1.959 62.372 2.028 62.424 2.087 c
+62.482 2.146 62.549 2.19 62.63 2.219 c
+62.707 2.256 62.794 2.278 62.894 2.278 c
+63.078 2.278 63.218 2.223 63.305 2.117 c
+63.401 2.017 63.471 1.859 63.511 1.646 c
+63.526 1.646 l
+63.563 1.741 63.603 1.83 63.644 1.911 c
+63.691 1.988 63.746 2.05 63.806 2.102 c
+63.864 2.161 63.93 2.204 64.011 2.234 c
+64.088 2.263 64.176 2.278 64.276 2.278 c
+64.411 2.278 64.525 2.252 64.614 2.204 c
+64.702 2.153 64.768 2.08 64.82 1.984 c
+64.878 1.885 64.915 1.756 64.937 1.602 c
+64.967 1.455 64.982 1.271 64.982 1.058 c
+64.982 -1.264 l
+64.261 -1.264 l
+64.261 0.852 l
+64.261 1.018 64.253 1.153 64.246 1.263 c
+64.236 1.371 64.217 1.455 64.188 1.514 c
+64.165 1.58 64.136 1.631 64.099 1.66 c
+64.07 1.691 64.03 1.705 63.982 1.705 c
+63.864 1.705 63.769 1.616 63.702 1.44 c
+63.644 1.271 63.614 1.014 63.614 0.661 c
+63.614 -1.264 l
+h
+67.351 -1.324 m
+67.094 -1.324 66.867 -1.286 66.661 -1.22 c
+66.455 -1.143 66.278 -1.029 66.131 -0.882 c
+65.984 -0.728 65.867 -0.537 65.778 -0.309 c
+65.698 -0.085 65.661 0.18 65.661 0.484 c
+65.661 0.816 65.705 1.095 65.793 1.323 c
+65.888 1.558 66.017 1.741 66.175 1.881 c
+66.341 2.017 66.528 2.117 66.734 2.175 c
+66.94 2.242 67.149 2.278 67.366 2.278 c
+67.638 2.278 67.873 2.227 68.072 2.131 c
+68.278 2.043 68.443 1.911 68.571 1.734 c
+68.708 1.565 68.807 1.359 68.865 1.117 c
+68.932 0.881 68.968 0.617 68.968 0.323 c
+68.968 0.309 l
+66.602 0.309 l
+66.602 0.162 66.617 0.022 66.646 -0.103 c
+66.682 -0.231 66.738 -0.345 66.808 -0.441 c
+66.873 -0.53 66.958 -0.599 67.058 -0.647 c
+67.153 -0.698 67.267 -0.721 67.396 -0.721 c
+67.55 -0.721 67.689 -0.688 67.808 -0.618 c
+67.932 -0.551 68.02 -0.449 68.072 -0.309 c
+68.909 -0.383 l
+68.88 -0.482 68.825 -0.588 68.748 -0.706 c
+68.667 -0.816 68.564 -0.919 68.439 -1.014 c
+68.321 -1.103 68.167 -1.176 67.983 -1.235 c
+67.808 -1.294 67.594 -1.324 67.351 -1.324 c
+67.351 1.705 m
+67.263 1.705 67.175 1.691 67.087 1.66 c
+66.999 1.631 66.918 1.58 66.852 1.514 c
+66.782 1.444 66.723 1.356 66.675 1.249 c
+66.634 1.139 66.617 1.014 66.617 0.867 c
+68.086 0.867 l
+68.086 1.003 68.061 1.124 68.013 1.234 c
+67.972 1.341 67.918 1.429 67.851 1.499 c
+67.792 1.565 67.719 1.616 67.631 1.646 c
+67.542 1.683 67.447 1.705 67.351 1.705 c
+70.221 -2.631 m
+70.221 -2.014 l
+71.295 -2.014 l
+71.295 2.896 l
+70.221 2.896 l
+70.221 3.513 l
+72.147 3.513 l
+72.147 -2.631 l
+h
+f
+Q
+q 1 0 0 1 626.5183 202.8085 cm
+0 0 m
+-0.029 -0.58 -0.191 -1.022 -0.485 -1.323 c
+-0.779 -1.627 -1.198 -1.778 -1.735 -1.778 c
+-2.263 -1.778 -2.69 -1.579 -3.013 -1.176 c
+-3.329 -0.764 -3.484 -0.205 -3.484 0.5 c
+-3.484 1.47 l
+-3.484 2.165 -3.322 2.712 -2.999 3.117 c
+-2.676 3.517 -2.231 3.719 -1.661 3.719 c
+-1.154 3.719 -0.757 3.561 -0.47 3.248 c
+-0.187 2.944 -0.029 2.502 0 1.926 c
+-0.691 1.926 l
+-0.721 2.367 -0.816 2.679 -0.97 2.866 c
+-1.118 3.051 -1.349 3.146 -1.661 3.146 c
+-2.036 3.146 -2.319 2.999 -2.514 2.705 c
+-2.712 2.419 -2.807 2.003 -2.807 1.455 c
+-2.807 0.47 l
+-2.807 -0.07 -2.716 -0.484 -2.529 -0.779 c
+-2.344 -1.065 -2.08 -1.205 -1.735 -1.205 c
+-1.382 -1.205 -1.128 -1.117 -0.97 -0.941 c
+-0.816 -0.764 -0.721 -0.452 -0.691 0 c
+h
+2.454 1.661 m
+2.367 1.679 2.267 1.691 2.161 1.691 c
+1.826 1.691 1.591 1.507 1.455 1.147 c
+1.455 -1.705 l
+0.808 -1.705 l
+0.808 2.278 l
+1.44 2.278 l
+1.455 1.867 l
+1.631 2.19 1.874 2.352 2.19 2.352 c
+2.296 2.352 2.385 2.33 2.454 2.294 c
+h
+4.453 -1.778 m
+3.954 -1.778 3.572 -1.631 3.308 -1.338 c
+3.042 -1.043 2.911 -0.61 2.911 -0.029 c
+2.911 0.441 l
+2.911 1.037 3.036 1.503 3.293 1.837 c
+3.557 2.18 3.917 2.352 4.38 2.352 c
+4.839 2.352 5.182 2.198 5.409 1.897 c
+5.644 1.602 5.766 1.139 5.777 0.515 c
+5.777 0.088 l
+3.557 0.088 l
+3.557 0 l
+3.557 -0.434 3.634 -0.746 3.792 -0.941 c
+3.958 -1.128 4.189 -1.22 4.484 -1.22 c
+4.678 -1.22 4.85 -1.186 4.997 -1.117 c
+5.145 -1.04 5.28 -0.922 5.409 -0.764 c
+5.747 -1.176 l
+5.461 -1.579 5.031 -1.778 4.453 -1.778 c
+4.38 1.794 m
+4.104 1.794 3.902 1.698 3.778 1.515 c
+3.649 1.326 3.576 1.037 3.557 0.647 c
+5.13 0.647 l
+5.13 0.736 l
+5.108 1.118 5.041 1.386 4.924 1.544 c
+4.806 1.709 4.623 1.794 4.38 1.794 c
+8.599 -1.705 m
+8.559 -1.616 8.532 -1.469 8.525 -1.263 c
+8.29 -1.61 7.996 -1.778 7.643 -1.778 c
+7.279 -1.778 6.996 -1.683 6.791 -1.484 c
+6.593 -1.278 6.497 -0.992 6.497 -0.617 c
+6.497 -0.216 6.633 0.103 6.909 0.339 c
+7.181 0.581 7.555 0.706 8.025 0.706 c
+8.511 0.706 l
+8.511 1.132 l
+8.511 1.367 8.455 1.532 8.349 1.632 c
+8.239 1.738 8.077 1.794 7.864 1.794 c
+7.665 1.794 7.504 1.735 7.379 1.617 c
+7.262 1.5 7.202 1.353 7.202 1.176 c
+6.556 1.176 l
+6.556 1.371 6.614 1.562 6.732 1.75 c
+6.857 1.933 7.019 2.08 7.217 2.19 c
+7.423 2.297 7.651 2.352 7.908 2.352 c
+8.309 2.352 8.613 2.249 8.819 2.043 c
+9.033 1.837 9.147 1.544 9.157 1.162 c
+9.157 -0.852 l
+9.157 -1.157 9.194 -1.421 9.275 -1.646 c
+9.275 -1.705 l
+h
+7.732 -1.19 m
+7.897 -1.19 8.048 -1.146 8.187 -1.058 c
+8.334 -0.97 8.441 -0.86 8.511 -0.72 c
+8.511 0.221 l
+8.143 0.221 l
+7.827 0.221 7.584 0.151 7.408 0.015 c
+7.231 -0.114 7.144 -0.301 7.144 -0.544 c
+7.144 -0.771 7.188 -0.937 7.276 -1.043 c
+7.364 -1.143 7.515 -1.19 7.732 -1.19 c
+11.009 3.234 m
+11.009 2.278 l
+11.612 2.278 l
+11.612 1.75 l
+11.009 1.75 l
+11.009 -0.72 l
+11.009 -0.878 11.032 -0.995 11.083 -1.072 c
+11.142 -1.153 11.23 -1.19 11.347 -1.19 c
+11.436 -1.19 11.524 -1.176 11.612 -1.146 c
+11.612 -1.705 l
+11.465 -1.753 11.31 -1.778 11.156 -1.778 c
+10.899 -1.778 10.705 -1.687 10.568 -1.499 c
+10.429 -1.315 10.363 -1.055 10.363 -0.72 c
+10.363 1.75 l
+9.76 1.75 l
+9.76 2.278 l
+10.363 2.278 l
+10.363 3.234 l
+h
+13.802 -1.778 m
+13.303 -1.778 12.92 -1.631 12.656 -1.338 c
+12.391 -1.043 12.259 -0.61 12.259 -0.029 c
+12.259 0.441 l
+12.259 1.037 12.384 1.503 12.641 1.837 c
+12.906 2.18 13.266 2.352 13.729 2.352 c
+14.188 2.352 14.53 2.198 14.757 1.897 c
+14.992 1.602 15.114 1.139 15.125 0.515 c
+15.125 0.088 l
+12.906 0.088 l
+12.906 0 l
+12.906 -0.434 12.983 -0.746 13.141 -0.941 c
+13.306 -1.128 13.538 -1.22 13.832 -1.22 c
+14.026 -1.22 14.199 -1.186 14.346 -1.117 c
+14.493 -1.04 14.629 -0.922 14.757 -0.764 c
+15.096 -1.176 l
+14.809 -1.579 14.379 -1.778 13.802 -1.778 c
+13.729 1.794 m
+13.453 1.794 13.251 1.698 13.126 1.515 c
+12.997 1.326 12.924 1.037 12.906 0.647 c
+14.479 0.647 l
+14.479 0.736 l
+14.456 1.118 14.39 1.386 14.273 1.544 c
+14.155 1.709 13.972 1.794 13.729 1.794 c
+18.242 2.278 m
+18.256 1.837 l
+18.51 2.18 18.834 2.352 19.226 2.352 c
+19.931 2.352 20.288 1.881 20.299 0.941 c
+20.299 -1.705 l
+19.653 -1.705 l
+19.653 0.912 l
+19.653 1.224 19.597 1.444 19.491 1.573 c
+19.381 1.698 19.226 1.764 19.021 1.764 c
+18.863 1.764 18.715 1.709 18.58 1.602 c
+18.451 1.492 18.348 1.357 18.271 1.191 c
+18.271 -1.705 l
+17.624 -1.705 l
+17.624 2.278 l
+h
+22.695 -1.778 m
+22.196 -1.778 21.813 -1.631 21.549 -1.338 c
+21.284 -1.043 21.151 -0.61 21.151 -0.029 c
+21.151 0.441 l
+21.151 1.037 21.277 1.503 21.534 1.837 c
+21.799 2.18 22.159 2.352 22.622 2.352 c
+23.081 2.352 23.422 2.198 23.651 1.897 c
+23.886 1.602 24.008 1.139 24.018 0.515 c
+24.018 0.088 l
+21.799 0.088 l
+21.799 0 l
+21.799 -0.434 21.876 -0.746 22.034 -0.941 c
+22.2 -1.128 22.431 -1.22 22.724 -1.22 c
+22.919 -1.22 23.092 -1.186 23.239 -1.117 c
+23.386 -1.04 23.522 -0.922 23.651 -0.764 c
+23.989 -1.176 l
+23.702 -1.579 23.272 -1.778 22.695 -1.778 c
+22.622 1.794 m
+22.346 1.794 22.144 1.698 22.019 1.515 c
+21.891 1.326 21.817 1.037 21.799 0.647 c
+23.372 0.647 l
+23.372 0.736 l
+23.349 1.118 23.283 1.386 23.166 1.544 c
+23.048 1.709 22.865 1.794 22.622 1.794 c
+27.767 -0.558 m
+28.369 2.278 l
+29.016 2.278 l
+28.031 -1.705 l
+27.517 -1.705 l
+26.738 1.147 l
+25.988 -1.705 l
+25.458 -1.705 l
+24.503 2.278 l
+25.136 2.278 l
+25.753 -0.484 l
+26.487 2.278 l
+27.002 2.278 l
+h
+34.293 0.088 m
+34.293 -0.529 34.179 -0.995 33.955 -1.308 c
+33.738 -1.624 33.415 -1.778 32.984 -1.778 c
+32.562 -1.778 32.249 -1.598 32.043 -1.234 c
+32.014 -1.705 l
+31.412 -1.705 l
+31.412 3.94 l
+32.058 3.94 l
+32.058 1.837 l
+32.272 2.18 32.581 2.352 32.984 2.352 c
+33.415 2.352 33.738 2.194 33.955 1.881 c
+34.179 1.577 34.293 1.11 34.293 0.485 c
+h
+33.646 0.47 m
+33.646 0.941 33.576 1.272 33.44 1.47 c
+33.312 1.665 33.102 1.764 32.808 1.764 c
+32.474 1.764 32.224 1.58 32.058 1.22 c
+32.058 -0.661 l
+32.224 -1.025 32.477 -1.205 32.823 -1.205 c
+33.117 -1.205 33.327 -1.103 33.455 -0.897 c
+33.58 -0.691 33.646 -0.374 33.646 0.059 c
+h
+36.777 1.661 m
+36.689 1.679 36.589 1.691 36.483 1.691 c
+36.149 1.691 35.914 1.507 35.777 1.147 c
+35.777 -1.705 l
+35.131 -1.705 l
+35.131 2.278 l
+35.763 2.278 l
+35.777 1.867 l
+35.954 2.19 36.197 2.352 36.512 2.352 c
+36.619 2.352 36.708 2.33 36.777 2.294 c
+h
+39.32 -1.705 m
+39.28 -1.616 39.254 -1.469 39.247 -1.263 c
+39.011 -1.61 38.717 -1.778 38.364 -1.778 c
+38 -1.778 37.718 -1.683 37.512 -1.484 c
+37.313 -1.278 37.217 -0.992 37.217 -0.617 c
+37.217 -0.216 37.354 0.103 37.63 0.339 c
+37.901 0.581 38.276 0.706 38.746 0.706 c
+39.232 0.706 l
+39.232 1.132 l
+39.232 1.367 39.176 1.532 39.07 1.632 c
+38.96 1.738 38.798 1.794 38.585 1.794 c
+38.387 1.794 38.225 1.735 38.1 1.617 c
+37.982 1.5 37.923 1.353 37.923 1.176 c
+37.277 1.176 l
+37.277 1.371 37.335 1.562 37.453 1.75 c
+37.578 1.933 37.74 2.08 37.938 2.19 c
+38.144 2.297 38.372 2.352 38.629 2.352 c
+39.029 2.352 39.334 2.249 39.54 2.043 c
+39.754 1.837 39.868 1.544 39.879 1.162 c
+39.879 -0.852 l
+39.879 -1.157 39.916 -1.421 39.996 -1.646 c
+39.996 -1.705 l
+h
+38.453 -1.19 m
+38.618 -1.19 38.769 -1.146 38.908 -1.058 c
+39.056 -0.97 39.162 -0.86 39.232 -0.72 c
+39.232 0.221 l
+38.864 0.221 l
+38.549 0.221 38.306 0.151 38.129 0.015 c
+37.953 -0.114 37.865 -0.301 37.865 -0.544 c
+37.865 -0.771 37.909 -0.937 37.997 -1.043 c
+38.085 -1.143 38.235 -1.19 38.453 -1.19 c
+41.495 2.278 m
+41.51 1.837 l
+41.763 2.18 42.087 2.352 42.48 2.352 c
+43.185 2.352 43.542 1.881 43.553 0.941 c
+43.553 -1.705 l
+42.906 -1.705 l
+42.906 0.912 l
+42.906 1.224 42.852 1.444 42.744 1.573 c
+42.634 1.698 42.48 1.764 42.274 1.764 c
+42.117 1.764 41.969 1.709 41.834 1.602 c
+41.705 1.492 41.602 1.357 41.525 1.191 c
+41.525 -1.705 l
+40.878 -1.705 l
+40.878 2.278 l
+h
+45.905 -1.22 m
+46.118 -1.22 46.291 -1.157 46.42 -1.028 c
+46.555 -0.893 46.629 -0.702 46.64 -0.455 c
+47.257 -0.455 l
+47.235 -0.837 47.099 -1.157 46.846 -1.411 c
+46.588 -1.657 46.276 -1.778 45.905 -1.778 c
+45.412 -1.778 45.038 -1.627 44.773 -1.323 c
+44.516 -1.01 44.391 -0.544 44.391 0.073 c
+44.391 0.515 l
+44.391 1.11 44.516 1.565 44.773 1.881 c
+45.038 2.194 45.412 2.352 45.905 2.352 c
+46.306 2.352 46.625 2.22 46.86 1.955 c
+47.103 1.698 47.235 1.353 47.257 0.912 c
+46.64 0.912 l
+46.618 1.206 46.545 1.426 46.42 1.573 c
+46.302 1.72 46.129 1.794 45.905 1.794 c
+45.611 1.794 45.394 1.694 45.258 1.5 c
+45.119 1.312 45.045 1.004 45.038 0.574 c
+45.038 0.059 l
+45.038 -0.411 45.104 -0.746 45.244 -0.941 c
+45.391 -1.128 45.611 -1.22 45.905 -1.22 c
+48.654 1.867 m
+48.907 2.19 49.227 2.352 49.609 2.352 c
+50.314 2.352 50.671 1.881 50.682 0.941 c
+50.682 -1.705 l
+50.035 -1.705 l
+50.035 0.912 l
+50.035 1.224 49.98 1.444 49.874 1.573 c
+49.763 1.698 49.609 1.764 49.404 1.764 c
+49.246 1.764 49.098 1.709 48.963 1.602 c
+48.834 1.492 48.731 1.357 48.654 1.191 c
+48.654 -1.705 l
+48.007 -1.705 l
+48.007 3.94 l
+48.654 3.94 l
+h
+51.652 -2.778 m
+51.255 -2.514 l
+51.49 -2.19 51.612 -1.855 51.623 -1.514 c
+51.623 -0.897 l
+52.284 -0.897 l
+52.284 -1.425 l
+52.284 -1.683 52.219 -1.929 52.093 -2.175 c
+51.976 -2.418 51.829 -2.62 51.652 -2.778 c
+56.489 1.661 m
+56.4 1.679 56.301 1.691 56.194 1.691 c
+55.86 1.691 55.625 1.507 55.488 1.147 c
+55.488 -1.705 l
+54.842 -1.705 l
+54.842 2.278 l
+55.474 2.278 l
+55.488 1.867 l
+55.665 2.19 55.908 2.352 56.224 2.352 c
+56.33 2.352 56.419 2.33 56.489 2.294 c
+h
+58.488 -1.778 m
+57.988 -1.778 57.605 -1.631 57.341 -1.338 c
+57.077 -1.043 56.944 -0.61 56.944 -0.029 c
+56.944 0.441 l
+56.944 1.037 57.069 1.503 57.326 1.837 c
+57.591 2.18 57.951 2.352 58.414 2.352 c
+58.873 2.352 59.215 2.198 59.442 1.897 c
+59.678 1.602 59.799 1.139 59.81 0.515 c
+59.81 0.088 l
+57.591 0.088 l
+57.591 0 l
+57.591 -0.434 57.668 -0.746 57.826 -0.941 c
+57.991 -1.128 58.223 -1.22 58.517 -1.22 c
+58.711 -1.22 58.885 -1.186 59.031 -1.117 c
+59.178 -1.04 59.315 -0.922 59.442 -0.764 c
+59.781 -1.176 l
+59.494 -1.579 59.064 -1.778 58.488 -1.778 c
+58.414 1.794 m
+58.139 1.794 57.936 1.698 57.811 1.515 c
+57.682 1.326 57.609 1.037 57.591 0.647 c
+59.164 0.647 l
+59.164 0.736 l
+59.141 1.118 59.076 1.386 58.958 1.544 c
+58.84 1.709 58.657 1.794 58.414 1.794 c
+60.884 -1.705 m
+60.884 1.75 l
+60.354 1.75 l
+60.354 2.278 l
+60.884 2.278 l
+60.884 2.735 l
+60.884 3.135 60.979 3.447 61.177 3.675 c
+61.383 3.899 61.663 4.013 62.015 4.013 c
+62.151 4.013 62.283 3.992 62.412 3.954 c
+62.382 3.41 l
+62.283 3.429 62.185 3.44 62.089 3.44 c
+61.714 3.44 61.53 3.175 61.53 2.646 c
+61.53 2.278 l
+62.206 2.278 l
+62.206 1.75 l
+61.53 1.75 l
+61.53 -1.705 l
+h
+64.308 -1.778 m
+63.808 -1.778 63.427 -1.631 63.162 -1.338 c
+62.897 -1.043 62.765 -0.61 62.765 -0.029 c
+62.765 0.441 l
+62.765 1.037 62.89 1.503 63.147 1.837 c
+63.411 2.18 63.772 2.352 64.235 2.352 c
+64.695 2.352 65.036 2.198 65.264 1.897 c
+65.499 1.602 65.62 1.139 65.632 0.515 c
+65.632 0.088 l
+63.411 0.088 l
+63.411 0 l
+63.411 -0.434 63.489 -0.746 63.647 -0.941 c
+63.812 -1.128 64.044 -1.22 64.338 -1.22 c
+64.533 -1.22 64.705 -1.186 64.852 -1.117 c
+64.999 -1.04 65.135 -0.922 65.264 -0.764 c
+65.601 -1.176 l
+65.315 -1.579 64.886 -1.778 64.308 -1.778 c
+64.235 1.794 m
+63.959 1.794 63.757 1.698 63.633 1.515 c
+63.504 1.326 63.43 1.037 63.411 0.647 c
+64.984 0.647 l
+64.984 0.736 l
+64.963 1.118 64.896 1.386 64.778 1.544 c
+64.661 1.709 64.477 1.794 64.235 1.794 c
+68.057 1.661 m
+67.968 1.679 67.869 1.691 67.762 1.691 c
+67.428 1.691 67.193 1.507 67.057 1.147 c
+67.057 -1.705 l
+66.411 -1.705 l
+66.411 2.278 l
+67.043 2.278 l
+67.057 1.867 l
+67.234 2.19 67.476 2.352 67.792 2.352 c
+67.899 2.352 67.987 2.33 68.057 2.294 c
+h
+70.056 -1.778 m
+69.555 -1.778 69.173 -1.631 68.909 -1.338 c
+68.645 -1.043 68.512 -0.61 68.512 -0.029 c
+68.512 0.441 l
+68.512 1.037 68.637 1.503 68.894 1.837 c
+69.159 2.18 69.519 2.352 69.982 2.352 c
+70.442 2.352 70.783 2.198 71.011 1.897 c
+71.246 1.602 71.367 1.139 71.379 0.515 c
+71.379 0.088 l
+69.159 0.088 l
+69.159 0 l
+69.159 -0.434 69.236 -0.746 69.395 -0.941 c
+69.559 -1.128 69.791 -1.22 70.085 -1.22 c
+70.28 -1.22 70.453 -1.186 70.6 -1.117 c
+70.746 -1.04 70.883 -0.922 71.011 -0.764 c
+71.349 -1.176 l
+71.062 -1.579 70.633 -1.778 70.056 -1.778 c
+69.982 1.794 m
+69.707 1.794 69.505 1.698 69.38 1.515 c
+69.251 1.326 69.177 1.037 69.159 0.647 c
+70.731 0.647 l
+70.731 0.736 l
+70.71 1.118 70.644 1.386 70.526 1.544 c
+70.409 1.709 70.224 1.794 69.982 1.794 c
+72.775 2.278 m
+72.79 1.837 l
+73.043 2.18 73.366 2.352 73.76 2.352 c
+74.465 2.352 74.822 1.881 74.833 0.941 c
+74.833 -1.705 l
+74.186 -1.705 l
+74.186 0.912 l
+74.186 1.224 74.131 1.444 74.024 1.573 c
+73.914 1.698 73.76 1.764 73.554 1.764 c
+73.396 1.764 73.249 1.709 73.113 1.602 c
+72.984 1.492 72.882 1.357 72.805 1.191 c
+72.805 -1.705 l
+72.157 -1.705 l
+72.157 2.278 l
+h
+77.185 -1.22 m
+77.397 -1.22 77.57 -1.157 77.699 -1.028 c
+77.835 -0.893 77.908 -0.702 77.919 -0.455 c
+78.537 -0.455 l
+78.515 -0.837 78.379 -1.157 78.126 -1.411 c
+77.868 -1.657 77.555 -1.778 77.185 -1.778 c
+76.692 -1.778 76.317 -1.627 76.053 -1.323 c
+75.795 -1.01 75.67 -0.544 75.67 0.073 c
+75.67 0.515 l
+75.67 1.11 75.795 1.565 76.053 1.881 c
+76.317 2.194 76.692 2.352 77.185 2.352 c
+77.586 2.352 77.904 2.22 78.14 1.955 c
+78.382 1.698 78.515 1.353 78.537 0.912 c
+77.919 0.912 l
+77.898 1.206 77.825 1.426 77.699 1.573 c
+77.582 1.72 77.409 1.794 77.185 1.794 c
+76.89 1.794 76.674 1.694 76.538 1.5 c
+76.398 1.312 76.325 1.004 76.317 0.574 c
+76.317 0.059 l
+76.317 -0.411 76.383 -0.746 76.523 -0.941 c
+76.67 -1.128 76.89 -1.22 77.185 -1.22 c
+79.992 -1.705 -0.646 3.983 re
+80.036 3.323 m
+80.036 3.212 80.007 3.12 79.948 3.043 c
+79.889 2.973 79.793 2.94 79.668 2.94 c
+79.551 2.94 79.456 2.973 79.39 3.043 c
+79.331 3.12 79.301 3.212 79.301 3.323 c
+79.301 3.44 79.331 3.532 79.39 3.601 c
+79.456 3.678 79.551 3.719 79.668 3.719 c
+79.793 3.719 79.889 3.678 79.948 3.601 c
+80.007 3.521 80.036 3.429 80.036 3.323 c
+81.624 2.278 m
+81.638 1.837 l
+81.892 2.18 82.215 2.352 82.608 2.352 c
+83.314 2.352 83.67 1.881 83.682 0.941 c
+83.682 -1.705 l
+83.035 -1.705 l
+83.035 0.912 l
+83.035 1.224 82.98 1.444 82.873 1.573 c
+82.763 1.698 82.608 1.764 82.403 1.764 c
+82.245 1.764 82.098 1.709 81.962 1.602 c
+81.833 1.492 81.73 1.357 81.653 1.191 c
+81.653 -1.705 l
+81.006 -1.705 l
+81.006 2.278 l
+h
+84.52 0.47 m
+84.52 1.088 84.63 1.551 84.857 1.867 c
+85.081 2.19 85.416 2.352 85.857 2.352 c
+86.257 2.352 86.563 2.176 86.768 1.823 c
+86.812 2.278 l
+87.4 2.278 l
+87.4 -1.749 l
+87.4 -2.238 87.272 -2.616 87.018 -2.881 c
+86.762 -3.145 86.409 -3.278 85.96 -3.278 c
+85.761 -3.278 85.541 -3.226 85.299 -3.131 c
+85.052 -3.031 84.873 -2.91 84.755 -2.763 c
+85.019 -2.322 l
+85.284 -2.587 85.582 -2.719 85.916 -2.719 c
+86.452 -2.719 86.728 -2.425 86.739 -1.837 c
+86.739 -1.308 l
+86.533 -1.624 86.232 -1.778 85.842 -1.778 c
+85.43 -1.778 85.108 -1.627 84.873 -1.323 c
+84.645 -1.01 84.527 -0.558 84.52 0.03 c
+h
+85.181 0.088 m
+85.181 -0.353 85.243 -0.683 85.372 -0.897 c
+85.497 -1.103 85.714 -1.205 86.018 -1.205 c
+86.342 -1.205 86.581 -1.04 86.739 -0.706 c
+86.739 1.279 l
+86.57 1.602 86.332 1.764 86.018 1.764 c
+85.725 1.764 85.508 1.661 85.372 1.455 c
+85.243 1.249 85.181 0.927 85.181 0.485 c
+h
+90.928 3.234 m
+90.928 2.278 l
+91.531 2.278 l
+91.531 1.75 l
+90.928 1.75 l
+90.928 -0.72 l
+90.928 -0.878 90.951 -0.995 91.001 -1.072 c
+91.061 -1.153 91.149 -1.19 91.267 -1.19 c
+91.354 -1.19 91.443 -1.176 91.531 -1.146 c
+91.531 -1.705 l
+91.384 -1.753 91.23 -1.778 91.075 -1.778 c
+90.818 -1.778 90.623 -1.687 90.487 -1.499 c
+90.348 -1.315 90.282 -1.055 90.282 -0.72 c
+90.282 1.75 l
+89.679 1.75 l
+89.679 2.278 l
+90.282 2.278 l
+90.282 3.234 l
+h
+92.942 1.867 m
+93.195 2.19 93.515 2.352 93.897 2.352 c
+94.603 2.352 94.959 1.881 94.97 0.941 c
+94.97 -1.705 l
+94.324 -1.705 l
+94.324 0.912 l
+94.324 1.224 94.269 1.444 94.162 1.573 c
+94.052 1.698 93.897 1.764 93.692 1.764 c
+93.534 1.764 93.387 1.709 93.251 1.602 c
+93.122 1.492 93.019 1.357 92.942 1.191 c
+92.942 -1.705 l
+92.295 -1.705 l
+92.295 3.94 l
+92.942 3.94 l
+h
+97.351 -1.778 m
+96.852 -1.778 96.47 -1.631 96.206 -1.338 c
+95.94 -1.043 95.809 -0.61 95.809 -0.029 c
+95.809 0.441 l
+95.809 1.037 95.934 1.503 96.191 1.837 c
+96.455 2.18 96.815 2.352 97.278 2.352 c
+97.737 2.352 98.08 2.198 98.307 1.897 c
+98.542 1.602 98.664 1.139 98.675 0.515 c
+98.675 0.088 l
+96.455 0.088 l
+96.455 0 l
+96.455 -0.434 96.532 -0.746 96.69 -0.941 c
+96.856 -1.128 97.087 -1.22 97.382 -1.22 c
+97.576 -1.22 97.748 -1.186 97.895 -1.117 c
+98.043 -1.04 98.178 -0.922 98.307 -0.764 c
+98.645 -1.176 l
+98.359 -1.579 97.929 -1.778 97.351 -1.778 c
+97.278 1.794 m
+97.002 1.794 96.8 1.698 96.676 1.515 c
+96.547 1.326 96.474 1.037 96.455 0.647 c
+98.028 0.647 l
+98.028 0.736 l
+98.006 1.118 97.939 1.386 97.822 1.544 c
+97.704 1.709 97.521 1.794 97.278 1.794 c
+102.556 -1.22 m
+102.768 -1.22 102.941 -1.157 103.069 -1.028 c
+103.206 -0.893 103.279 -0.702 103.29 -0.455 c
+103.907 -0.455 l
+103.886 -0.837 103.749 -1.157 103.496 -1.411 c
+103.239 -1.657 102.926 -1.778 102.556 -1.778 c
+102.063 -1.778 101.688 -1.627 101.423 -1.323 c
+101.166 -1.01 101.041 -0.544 101.041 0.073 c
+101.041 0.515 l
+101.041 1.11 101.166 1.565 101.423 1.881 c
+101.688 2.194 102.063 2.352 102.556 2.352 c
+102.955 2.352 103.275 2.22 103.51 1.955 c
+103.753 1.698 103.886 1.353 103.907 0.912 c
+103.29 0.912 l
+103.268 1.206 103.194 1.426 103.069 1.573 c
+102.952 1.72 102.779 1.794 102.556 1.794 c
+102.261 1.794 102.045 1.694 101.908 1.5 c
+101.769 1.312 101.696 1.004 101.688 0.574 c
+101.688 0.059 l
+101.688 -0.411 101.754 -0.746 101.893 -0.941 c
+102.041 -1.128 102.261 -1.22 102.556 -1.22 c
+106.685 -1.352 m
+106.469 -1.639 106.157 -1.778 105.745 -1.778 c
+105.382 -1.778 105.106 -1.657 104.922 -1.411 c
+104.746 -1.157 104.65 -0.793 104.642 -0.323 c
+104.642 2.278 l
+105.289 2.278 l
+105.289 -0.264 l
+105.289 -0.893 105.473 -1.205 105.848 -1.205 c
+106.248 -1.205 106.524 -1.028 106.671 -0.675 c
+106.671 2.278 l
+107.318 2.278 l
+107.318 -1.705 l
+106.701 -1.705 l
+h
+109.949 1.661 m
+109.86 1.679 109.762 1.691 109.654 1.691 c
+109.32 1.691 109.085 1.507 108.949 1.147 c
+108.949 -1.705 l
+108.303 -1.705 l
+108.303 2.278 l
+108.935 2.278 l
+108.949 1.867 l
+109.126 2.19 109.368 2.352 109.685 2.352 c
+109.791 2.352 109.879 2.33 109.949 2.294 c
+h
+112.241 1.661 m
+112.154 1.679 112.054 1.691 111.948 1.691 c
+111.613 1.691 111.378 1.507 111.242 1.147 c
+111.242 -1.705 l
+110.595 -1.705 l
+110.595 2.278 l
+111.227 2.278 l
+111.242 1.867 l
+111.418 2.19 111.661 2.352 111.977 2.352 c
+112.083 2.352 112.172 2.33 112.241 2.294 c
+h
+114.24 -1.778 m
+113.741 -1.778 113.359 -1.631 113.095 -1.338 c
+112.829 -1.043 112.698 -0.61 112.698 -0.029 c
+112.698 0.441 l
+112.698 1.037 112.823 1.503 113.08 1.837 c
+113.344 2.18 113.704 2.352 114.167 2.352 c
+114.627 2.352 114.969 2.198 115.196 1.897 c
+115.431 1.602 115.553 1.139 115.564 0.515 c
+115.564 0.088 l
+113.344 0.088 l
+113.344 0 l
+113.344 -0.434 113.421 -0.746 113.579 -0.941 c
+113.745 -1.128 113.976 -1.22 114.271 -1.22 c
+114.465 -1.22 114.638 -1.186 114.785 -1.117 c
+114.932 -1.04 115.067 -0.922 115.196 -0.764 c
+115.534 -1.176 l
+115.248 -1.579 114.818 -1.778 114.24 -1.778 c
+114.167 1.794 m
+113.891 1.794 113.69 1.698 113.565 1.515 c
+113.436 1.326 113.363 1.037 113.344 0.647 c
+114.917 0.647 l
+114.917 0.736 l
+114.895 1.118 114.828 1.386 114.711 1.544 c
+114.593 1.709 114.41 1.794 114.167 1.794 c
+116.96 2.278 m
+116.975 1.837 l
+117.228 2.18 117.552 2.352 117.945 2.352 c
+118.651 2.352 119.007 1.881 119.019 0.941 c
+119.019 -1.705 l
+118.371 -1.705 l
+118.371 0.912 l
+118.371 1.224 118.317 1.444 118.209 1.573 c
+118.099 1.698 117.945 1.764 117.739 1.764 c
+117.581 1.764 117.434 1.709 117.298 1.602 c
+117.17 1.492 117.067 1.357 116.989 1.191 c
+116.989 -1.705 l
+116.343 -1.705 l
+116.343 2.278 l
+h
+120.841 3.234 m
+120.841 2.278 l
+121.444 2.278 l
+121.444 1.75 l
+120.841 1.75 l
+120.841 -0.72 l
+120.841 -0.878 120.863 -0.995 120.914 -1.072 c
+120.973 -1.153 121.061 -1.19 121.178 -1.19 c
+121.267 -1.19 121.355 -1.176 121.444 -1.146 c
+121.444 -1.705 l
+121.296 -1.753 121.142 -1.778 120.987 -1.778 c
+120.731 -1.778 120.536 -1.687 120.4 -1.499 c
+120.26 -1.315 120.194 -1.055 120.194 -0.72 c
+120.194 1.75 l
+119.591 1.75 l
+119.591 2.278 l
+120.194 2.278 l
+120.194 3.234 l
+h
+f
+Q
+q 1 0 0 1 754.1503 201.1039 cm
+0 0 m
+-1.088 0 l
+-1.088 2.293 l
+-2.676 2.293 l
+-2.676 0 l
+-3.763 0 l
+-3.763 5.35 l
+-2.676 5.35 l
+-2.676 3.189 l
+-1.088 3.189 l
+-1.088 5.35 l
+0 5.35 l
+h
+3.616 2.323 m
+1.94 2.323 l
+1.94 0.897 l
+3.925 0.897 l
+3.925 0 l
+0.852 0 l
+0.852 5.35 l
+3.925 5.35 l
+3.925 4.453 l
+1.94 4.453 l
+1.94 3.189 l
+3.616 3.189 l
+h
+7.1 1.103 m
+5.629 1.103 l
+5.336 0 l
+4.204 0 l
+5.865 5.35 l
+6.865 5.35 l
+8.54 0 l
+7.393 0 l
+h
+5.865 1.999 m
+6.865 1.999 l
+6.364 3.91 l
+h
+9.039 0 m
+9.039 5.35 l
+10.466 5.35 l
+11.083 5.35 11.576 5.148 11.95 4.748 c
+12.322 4.355 12.513 3.815 12.523 3.131 c
+12.523 2.263 l
+12.523 1.558 12.336 1.003 11.965 0.602 c
+11.59 0.199 11.083 0 10.437 0 c
+h
+10.127 4.453 m
+10.127 0.897 l
+10.451 0.897 l
+10.811 0.897 11.068 0.989 11.216 1.176 c
+11.362 1.371 11.436 1.698 11.436 2.161 c
+11.436 3.102 l
+11.436 3.601 11.366 3.946 11.23 4.145 c
+11.09 4.34 10.855 4.442 10.524 4.453 c
+h
+f
+Q
+q 1 0 0 1 767.5407 201.4567 cm
+0 0 m
+0 0.118 0.033 0.213 0.104 0.294 c
+0.169 0.371 0.272 0.411 0.412 0.411 c
+0.559 0.411 0.665 0.371 0.735 0.294 c
+0.813 0.213 0.852 0.118 0.852 0 c
+0.852 -0.11 0.813 -0.202 0.735 -0.279 c
+0.665 -0.357 0.559 -0.397 0.412 -0.397 c
+0.272 -0.397 0.169 -0.357 0.104 -0.279 c
+0.033 -0.202 0 -0.11 0 0 c
+f
+Q
+0.113 0.082 0.09 0 k
+535.667 195.5 238.665 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 540.8555 188.6608 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.088 -0.5 c
+-0.147 -0.646 -0.242 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.146 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.263 l
+-2.142 -1.257 -2.358 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.772 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.141 1.279 -3.218 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.985 c
+-3.322 2.18 -3.289 2.344 -3.218 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.003 -2.469 3.043 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.558 l
+-1.543 3.558 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.735 -0.349 2.62 -0.279 2.484 c
+-0.201 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.459 -1.543 2.5 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.36 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.206 c
+-0.756 1.147 -0.595 1.066 -0.455 0.971 c
+-0.319 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.455 c
+-2.26 2.425 -2.318 2.385 -2.366 2.338 c
+-2.406 2.297 -2.436 2.249 -2.454 2.19 c
+-2.476 2.132 -2.484 2.066 -2.484 1.999 c
+-2.484 1.912 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.2 1.559 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.441 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.302 -0.977 0.357 -1.043 0.397 c
+-1.102 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.44 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.014 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.52 -2.484 5.403 -2.396 c
+5.285 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.616 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.146 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.214 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.411 4.888 -0.205 c
+4.836 0.008 4.815 0.243 4.815 0.5 c
+4.815 0.772 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.632 5.137 1.779 c
+5.245 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.264 6.093 2.264 c
+6.189 2.264 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.918 7.107 1.97 c
+7.115 2.029 7.122 2.076 7.122 2.117 c
+7.13 2.165 7.14 2.198 7.151 2.22 c
+8.004 2.22 l
+7.992 2.139 7.982 2.029 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.872 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.403 7.258 -2.499 7.063 -2.557 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.206 6.924 1.324 6.857 1.411 c
+6.799 1.5 6.729 1.559 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.226 1.621 6.137 1.573 c
+6.056 1.532 5.991 1.463 5.931 1.367 c
+5.88 1.279 5.835 1.162 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.558 c
+6.725 -0.521 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.302 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.263 l
+8.86 -1.263 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.22 l
+13.644 2.22 l
+13.924 3.117 l
+14.498 3.117 l
+14.498 2.22 l
+15.732 2.22 l
+15.732 1.602 l
+14.498 1.602 l
+14.498 -0.103 l
+14.498 -0.323 l
+14.504 -0.393 14.527 -0.455 14.556 -0.515 c
+14.593 -0.565 14.648 -0.61 14.718 -0.646 c
+14.795 -0.675 14.909 -0.691 15.056 -0.691 c
+15.192 -0.691 15.327 -0.687 15.468 -0.675 c
+15.603 -0.658 15.736 -0.632 15.865 -0.602 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.23 15.629 -1.249 c
+15.549 -1.261 15.471 -1.267 15.394 -1.278 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.042 -1.301 14.942 -1.308 14.836 -1.308 c
+14.648 -1.308 14.486 -1.294 14.35 -1.263 c
+14.222 -1.227 14.107 -1.183 14.012 -1.132 c
+13.924 -1.084 13.85 -1.025 13.792 -0.955 c
+13.733 -0.878 13.689 -0.801 13.66 -0.72 c
+13.63 -0.632 13.608 -0.544 13.6 -0.455 c
+13.59 -0.36 13.586 -0.264 13.586 -0.176 c
+h
+22.677 -1.323 m
+22.391 -1.323 22.148 -1.282 21.943 -1.205 c
+21.737 -1.117 21.564 -0.995 21.428 -0.837 c
+21.288 -0.683 21.185 -0.496 21.12 -0.279 c
+21.049 -0.055 21.016 0.191 21.016 0.456 c
+21.016 0.75 21.049 1.008 21.12 1.235 c
+21.197 1.459 21.303 1.646 21.442 1.794 c
+21.59 1.948 21.766 2.066 21.972 2.147 c
+22.178 2.234 22.413 2.278 22.677 2.278 c
+22.901 2.278 23.104 2.249 23.28 2.19 c
+23.456 2.132 23.607 2.047 23.736 1.941 c
+23.861 1.841 23.963 1.72 24.044 1.573 c
+24.122 1.434 24.177 1.283 24.206 1.118 c
+23.295 1.073 l
+23.265 1.249 23.196 1.389 23.089 1.5 c
+22.99 1.606 22.847 1.661 22.662 1.661 c
+22.417 1.661 22.24 1.559 22.134 1.353 c
+22.024 1.154 21.972 0.867 21.972 0.485 c
+21.972 -0.309 22.207 -0.706 22.677 -0.706 c
+22.843 -0.706 22.986 -0.654 23.104 -0.544 c
+23.221 -0.437 23.295 -0.276 23.324 -0.058 c
+24.235 -0.103 l
+24.206 -0.272 24.151 -0.426 24.073 -0.573 c
+24.004 -0.72 23.901 -0.852 23.765 -0.97 c
+23.636 -1.08 23.478 -1.168 23.295 -1.234 c
+23.119 -1.294 22.913 -1.323 22.677 -1.323 c
+26.076 1.515 m
+26.194 1.786 26.344 1.985 26.532 2.103 c
+26.716 2.22 26.936 2.278 27.194 2.278 c
+27.399 2.278 27.568 2.242 27.708 2.176 c
+27.855 2.106 27.965 2.014 28.046 1.897 c
+28.135 1.779 28.193 1.636 28.222 1.47 c
+28.259 1.301 28.281 1.125 28.281 0.941 c
+28.281 -1.263 l
+27.37 -1.263 l
+27.37 0.736 l
+27.37 0.871 27.359 0.992 27.341 1.103 c
+27.329 1.209 27.304 1.297 27.267 1.367 c
+27.227 1.444 27.168 1.503 27.09 1.544 c
+27.021 1.58 26.929 1.602 26.811 1.602 c
+26.701 1.602 26.606 1.577 26.518 1.529 c
+26.429 1.478 26.348 1.411 26.282 1.324 c
+26.223 1.235 26.172 1.125 26.136 1 c
+26.106 0.882 26.091 0.75 26.091 0.603 c
+26.091 -1.263 l
+25.18 -1.263 l
+25.18 3.514 l
+26.091 3.514 l
+26.091 2.205 l
+26.091 2.135 26.084 2.066 26.076 1.999 c
+26.076 1.794 l
+26.076 1.735 26.069 1.679 26.061 1.632 c
+26.061 1.515 l
+h
+30.799 -1.323 m
+30.541 -1.323 30.313 -1.286 30.107 -1.22 c
+29.902 -1.143 29.725 -1.028 29.579 -0.881 c
+29.432 -0.727 29.314 -0.536 29.226 -0.309 c
+29.145 -0.085 29.108 0.181 29.108 0.485 c
+29.108 0.816 29.153 1.095 29.24 1.324 c
+29.336 1.559 29.465 1.742 29.623 1.881 c
+29.788 2.018 29.976 2.117 30.181 2.176 c
+30.387 2.242 30.597 2.278 30.813 2.278 c
+31.085 2.278 31.32 2.227 31.518 2.132 c
+31.725 2.043 31.89 1.912 32.019 1.735 c
+32.154 1.565 32.254 1.36 32.313 1.118 c
+32.378 0.882 32.415 0.618 32.415 0.324 c
+32.415 0.309 l
+30.049 0.309 l
+30.049 0.162 30.063 0.023 30.093 -0.103 c
+30.13 -0.231 30.185 -0.345 30.255 -0.44 c
+30.321 -0.529 30.406 -0.598 30.504 -0.646 c
+30.6 -0.698 30.714 -0.72 30.843 -0.72 c
+30.997 -0.72 31.137 -0.687 31.254 -0.617 c
+31.379 -0.551 31.468 -0.448 31.518 -0.309 c
+32.357 -0.382 l
+32.328 -0.481 32.272 -0.588 32.195 -0.706 c
+32.114 -0.816 32.011 -0.918 31.886 -1.014 c
+31.769 -1.103 31.615 -1.176 31.431 -1.234 c
+31.254 -1.294 31.041 -1.323 30.799 -1.323 c
+30.799 1.706 m
+30.71 1.706 30.622 1.691 30.534 1.661 c
+30.446 1.632 30.365 1.58 30.298 1.515 c
+30.229 1.444 30.17 1.357 30.122 1.249 c
+30.082 1.139 30.063 1.014 30.063 0.867 c
+31.534 0.867 l
+31.534 1.004 31.508 1.125 31.46 1.235 c
+31.42 1.341 31.364 1.43 31.298 1.5 c
+31.239 1.565 31.166 1.617 31.078 1.646 c
+30.99 1.683 30.894 1.706 30.799 1.706 c
+34.863 -1.323 m
+34.576 -1.323 34.333 -1.282 34.128 -1.205 c
+33.922 -1.117 33.749 -0.995 33.614 -0.837 c
+33.473 -0.683 33.371 -0.496 33.305 -0.279 c
+33.235 -0.055 33.201 0.191 33.201 0.456 c
+33.201 0.75 33.235 1.008 33.305 1.235 c
+33.382 1.459 33.488 1.646 33.628 1.794 c
+33.775 1.948 33.951 2.066 34.157 2.147 c
+34.363 2.234 34.599 2.278 34.863 2.278 c
+35.087 2.278 35.289 2.249 35.466 2.19 c
+35.642 2.132 35.792 2.047 35.921 1.941 c
+36.046 1.841 36.149 1.72 36.23 1.573 c
+36.307 1.434 36.362 1.283 36.392 1.118 c
+35.48 1.073 l
+35.451 1.249 35.381 1.389 35.274 1.5 c
+35.175 1.606 35.032 1.661 34.848 1.661 c
+34.602 1.661 34.425 1.559 34.319 1.353 c
+34.209 1.154 34.157 0.867 34.157 0.485 c
+34.157 -0.309 34.393 -0.706 34.863 -0.706 c
+35.028 -0.706 35.171 -0.654 35.289 -0.544 c
+35.407 -0.437 35.48 -0.276 35.509 -0.058 c
+36.421 -0.103 l
+36.392 -0.272 36.336 -0.426 36.259 -0.573 c
+36.189 -0.72 36.087 -0.852 35.95 -0.97 c
+35.822 -1.08 35.664 -1.168 35.48 -1.234 c
+35.304 -1.294 35.098 -1.323 34.863 -1.323 c
+39.688 -1.263 m
+38.761 0.309 l
+38.365 0.044 l
+38.365 -1.263 l
+37.469 -1.263 l
+37.469 3.514 l
+38.365 3.514 l
+38.365 0.779 l
+39.615 2.22 l
+40.584 2.22 l
+39.364 0.853 l
+40.673 -1.263 l
+h
+44.631 0.485 m
+44.631 0.21 44.594 -0.04 44.527 -0.264 c
+44.457 -0.481 44.355 -0.669 44.219 -0.823 c
+44.079 -0.981 43.902 -1.103 43.69 -1.19 c
+43.473 -1.278 43.219 -1.323 42.925 -1.323 c
+42.649 -1.323 42.404 -1.278 42.19 -1.19 c
+41.984 -1.103 41.812 -0.981 41.676 -0.823 c
+41.536 -0.669 41.433 -0.481 41.367 -0.264 c
+41.297 -0.04 41.265 0.21 41.265 0.485 c
+41.265 0.738 41.294 0.974 41.352 1.191 c
+41.419 1.415 41.521 1.606 41.662 1.764 c
+41.797 1.929 41.974 2.058 42.19 2.147 c
+42.404 2.234 42.661 2.278 42.955 2.278 c
+43.267 2.278 43.528 2.234 43.734 2.147 c
+43.947 2.058 44.12 1.929 44.249 1.764 c
+44.384 1.606 44.484 1.415 44.542 1.191 c
+44.601 0.974 44.631 0.738 44.631 0.485 c
+43.675 0.485 m
+43.675 0.691 43.661 0.867 43.631 1.014 c
+43.609 1.162 43.572 1.283 43.513 1.382 c
+43.455 1.478 43.381 1.548 43.293 1.588 c
+43.204 1.636 43.094 1.661 42.969 1.661 c
+42.705 1.661 42.514 1.562 42.396 1.367 c
+42.279 1.18 42.219 0.886 42.219 0.485 c
+42.219 0.063 42.279 -0.243 42.396 -0.426 c
+42.514 -0.613 42.69 -0.706 42.925 -0.706 c
+43.05 -0.706 43.164 -0.687 43.264 -0.646 c
+43.359 -0.598 43.44 -0.525 43.499 -0.426 c
+43.565 -0.33 43.609 -0.205 43.631 -0.058 c
+43.661 0.088 43.675 0.268 43.675 0.485 c
+46.368 2.22 m
+46.368 0.265 l
+46.368 0.125 46.376 0 46.398 -0.118 c
+46.416 -0.228 46.449 -0.32 46.501 -0.397 c
+46.549 -0.478 46.607 -0.54 46.678 -0.588 c
+46.743 -0.628 46.828 -0.646 46.927 -0.646 c
+47.015 -0.646 47.096 -0.628 47.177 -0.588 c
+47.266 -0.54 47.339 -0.47 47.397 -0.382 c
+47.457 -0.286 47.501 -0.176 47.53 -0.058 c
+47.567 0.067 47.588 0.206 47.588 0.353 c
+47.588 2.22 l
+48.485 2.22 l
+48.485 -0.484 l
+48.485 -0.72 l
+48.492 -0.801 48.5 -0.878 48.5 -0.955 c
+48.5 -1.146 l
+48.507 -1.198 48.515 -1.234 48.515 -1.263 c
+47.662 -1.263 l
+47.651 -1.234 47.64 -1.198 47.632 -1.146 c
+47.632 -0.955 l
+47.632 -0.889 47.625 -0.819 47.618 -0.75 c
+47.618 -0.573 l
+47.603 -0.573 l
+47.486 -0.837 47.331 -1.028 47.148 -1.146 c
+46.971 -1.263 46.769 -1.323 46.545 -1.323 c
+46.339 -1.323 46.167 -1.286 46.03 -1.22 c
+45.891 -1.153 45.78 -1.058 45.693 -0.941 c
+45.612 -0.823 45.552 -0.687 45.516 -0.529 c
+45.487 -0.363 45.472 -0.187 45.472 0 c
+45.472 2.22 l
+h
+50.15 1.602 m
+49.606 1.602 l
+49.606 2.22 l
+50.194 2.22 l
+50.474 3.117 l
+51.046 3.117 l
+51.046 2.22 l
+52.282 2.22 l
+52.282 1.602 l
+51.046 1.602 l
+51.046 -0.103 l
+51.046 -0.323 l
+51.054 -0.393 51.076 -0.455 51.106 -0.515 c
+51.142 -0.565 51.197 -0.61 51.267 -0.646 c
+51.345 -0.675 51.458 -0.691 51.605 -0.691 c
+51.741 -0.691 51.877 -0.687 52.016 -0.675 c
+52.153 -0.658 52.285 -0.632 52.413 -0.602 c
+52.413 -1.205 l
+52.332 -1.216 52.255 -1.23 52.178 -1.249 c
+52.097 -1.261 52.02 -1.267 51.943 -1.278 c
+51.862 -1.286 51.775 -1.294 51.679 -1.294 c
+51.59 -1.301 51.491 -1.308 51.384 -1.308 c
+51.197 -1.308 51.035 -1.294 50.9 -1.263 c
+50.771 -1.227 50.657 -1.183 50.561 -1.132 c
+50.474 -1.084 50.4 -1.025 50.341 -0.955 c
+50.283 -0.878 50.238 -0.801 50.208 -0.72 c
+50.179 -0.632 50.157 -0.544 50.15 -0.455 c
+50.139 -0.36 50.135 -0.264 50.135 -0.176 c
+h
+58.422 -2.631 m
+58.422 3.514 l
+60.347 3.514 l
+60.347 2.896 l
+59.274 2.896 l
+59.274 -2.013 l
+60.347 -2.013 l
+60.347 -2.631 l
+h
+62.32 0.838 1.867 -0.794 re
+62.32 0.044 m
+65.793 -1.263 m
+65.793 -0.97 l
+65.801 -0.833 65.808 -0.675 65.808 -0.5 c
+65.808 3.514 l
+66.719 3.514 l
+66.719 2.234 l
+66.719 2.072 l
+66.719 1.897 l
+66.719 1.845 66.712 1.801 66.705 1.764 c
+66.705 1.676 l
+66.719 1.676 l
+66.767 1.783 66.829 1.874 66.91 1.955 c
+66.987 2.032 67.072 2.095 67.16 2.147 c
+67.249 2.194 67.34 2.227 67.44 2.249 c
+67.535 2.267 67.634 2.278 67.733 2.278 c
+67.947 2.278 68.134 2.234 68.292 2.147 c
+68.446 2.058 68.575 1.929 68.674 1.764 c
+68.781 1.606 68.858 1.415 68.909 1.191 c
+68.957 0.974 68.983 0.736 68.983 0.47 c
+68.983 0.214 68.953 -0.025 68.895 -0.249 c
+68.836 -0.467 68.751 -0.658 68.645 -0.823 c
+68.535 -0.981 68.402 -1.103 68.248 -1.19 c
+68.09 -1.278 67.91 -1.323 67.704 -1.323 c
+67.605 -1.323 67.506 -1.311 67.411 -1.294 c
+67.322 -1.271 67.234 -1.242 67.145 -1.19 c
+67.058 -1.132 66.977 -1.066 66.91 -0.985 c
+66.84 -0.908 66.778 -0.808 66.719 -0.691 c
+66.705 -0.691 l
+66.705 -0.852 l
+66.705 -0.911 66.697 -0.97 66.69 -1.028 c
+66.69 -1.08 66.682 -1.128 66.675 -1.176 c
+66.675 -1.216 66.668 -1.246 66.661 -1.263 c
+h
+66.705 0.5 m
+66.705 0.265 66.723 0.067 66.763 -0.087 c
+66.811 -0.246 66.87 -0.367 66.94 -0.455 c
+67.006 -0.544 67.079 -0.61 67.16 -0.646 c
+67.237 -0.687 67.315 -0.706 67.396 -0.706 c
+67.602 -0.706 67.756 -0.61 67.866 -0.411 c
+67.983 -0.216 68.043 0.077 68.043 0.47 c
+68.043 0.684 68.02 0.867 67.983 1.014 c
+67.954 1.168 67.91 1.294 67.851 1.382 c
+67.8 1.478 67.733 1.551 67.646 1.602 c
+67.565 1.65 67.476 1.676 67.38 1.676 c
+67.3 1.676 67.222 1.654 67.145 1.617 c
+67.064 1.577 66.991 1.515 66.925 1.426 c
+66.867 1.338 66.811 1.213 66.763 1.058 c
+66.723 0.912 66.705 0.724 66.705 0.5 c
+70.221 -2.631 m
+70.221 -2.013 l
+71.295 -2.013 l
+71.295 2.896 l
+70.221 2.896 l
+70.221 3.514 l
+72.147 3.514 l
+72.147 -2.631 l
+h
+78.729 -2.631 m
+78.729 3.514 l
+80.654 3.514 l
+80.654 2.896 l
+79.581 2.896 l
+79.581 -2.013 l
+80.654 -2.013 l
+80.654 -2.631 l
+h
+84.23 -1.263 m
+84.23 0.721 l
+84.23 1.022 84.186 1.243 84.097 1.382 c
+84.017 1.529 83.88 1.602 83.685 1.602 c
+83.575 1.602 83.473 1.577 83.377 1.529 c
+83.289 1.478 83.208 1.411 83.142 1.324 c
+83.083 1.235 83.031 1.125 82.995 1 c
+82.966 0.882 82.951 0.75 82.951 0.603 c
+82.951 -1.263 l
+82.039 -1.263 l
+82.039 1.441 l
+82.039 1.661 l
+82.039 1.75 82.032 1.827 82.025 1.897 c
+82.025 2.087 l
+82.025 2.22 l
+82.877 2.22 l
+82.885 2.19 82.892 2.147 82.892 2.087 c
+82.892 1.897 l
+82.899 1.827 82.906 1.756 82.906 1.691 c
+82.914 1.621 82.922 1.565 82.922 1.529 c
+82.937 1.529 l
+83.054 1.794 83.205 1.985 83.392 2.103 c
+83.575 2.22 83.796 2.278 84.053 2.278 c
+84.237 2.278 84.398 2.249 84.539 2.19 c
+84.674 2.132 84.788 2.043 84.876 1.926 c
+84.965 1.808 85.027 1.665 85.067 1.5 c
+85.115 1.341 85.141 1.154 85.141 0.941 c
+85.141 -1.263 l
+h
+87.055 -1.323 m
+86.887 -1.323 86.736 -1.301 86.6 -1.263 c
+86.471 -1.216 86.357 -1.146 86.262 -1.058 c
+86.174 -0.97 86.104 -0.864 86.056 -0.735 c
+86.004 -0.598 85.983 -0.448 85.983 -0.279 c
+85.983 -0.073 86.016 0.096 86.085 0.235 c
+86.152 0.383 86.247 0.493 86.365 0.574 c
+86.49 0.661 86.633 0.724 86.791 0.765 c
+86.956 0.802 87.132 0.827 87.32 0.838 c
+88.04 0.853 l
+88.04 1.029 l
+88.04 1.147 88.03 1.249 88.011 1.338 c
+87.989 1.426 87.955 1.492 87.908 1.544 c
+87.868 1.602 87.82 1.639 87.761 1.661 c
+87.702 1.679 87.636 1.691 87.57 1.691 c
+87.5 1.691 87.438 1.679 87.379 1.661 c
+87.328 1.65 87.28 1.625 87.232 1.588 c
+87.192 1.559 87.159 1.507 87.129 1.441 c
+87.107 1.382 87.093 1.301 87.085 1.206 c
+86.144 1.249 l
+86.174 1.397 86.218 1.532 86.276 1.661 c
+86.343 1.786 86.438 1.897 86.556 1.985 c
+86.673 2.08 86.813 2.153 86.982 2.205 c
+87.159 2.253 87.365 2.278 87.6 2.278 c
+88.04 2.278 88.371 2.168 88.599 1.955 c
+88.834 1.75 88.952 1.441 88.952 1.029 c
+88.952 -0.235 l
+88.952 -0.455 l
+88.959 -0.515 88.974 -0.569 88.996 -0.617 c
+89.014 -0.658 89.044 -0.691 89.084 -0.72 c
+89.121 -0.742 89.172 -0.75 89.231 -0.75 c
+89.297 -0.75 89.366 -0.746 89.437 -0.735 c
+89.437 -1.22 l
+89.378 -1.23 89.323 -1.242 89.275 -1.249 c
+89.235 -1.261 89.194 -1.267 89.158 -1.278 c
+89.117 -1.286 89.073 -1.294 89.025 -1.294 c
+88.974 -1.301 88.915 -1.308 88.849 -1.308 c
+88.62 -1.308 88.456 -1.257 88.349 -1.146 c
+88.239 -1.028 88.176 -0.864 88.158 -0.646 c
+88.143 -0.646 l
+88.073 -0.756 88.003 -0.852 87.938 -0.941 c
+87.868 -1.022 87.791 -1.087 87.702 -1.146 c
+87.614 -1.205 87.515 -1.249 87.408 -1.278 c
+87.309 -1.308 87.192 -1.323 87.055 -1.323 c
+88.04 0.353 m
+87.614 0.339 l
+87.515 0.339 87.423 0.331 87.334 0.324 c
+87.254 0.312 87.188 0.287 87.129 0.25 c
+87.07 0.21 87.018 0.151 86.982 0.073 c
+86.941 0.004 86.923 -0.087 86.923 -0.205 c
+86.923 -0.374 86.956 -0.496 87.026 -0.573 c
+87.093 -0.654 87.192 -0.691 87.32 -0.691 c
+87.427 -0.691 87.525 -0.669 87.614 -0.617 c
+87.71 -0.569 87.791 -0.507 87.849 -0.426 c
+87.915 -0.349 87.967 -0.261 87.996 -0.162 c
+88.026 -0.055 88.04 0.059 88.04 0.177 c
+h
+91.322 -1.263 m
+91.322 0.853 l
+91.322 1.018 91.315 1.154 91.307 1.264 c
+91.296 1.371 91.278 1.455 91.248 1.515 c
+91.226 1.58 91.197 1.632 91.16 1.661 c
+91.13 1.691 91.091 1.706 91.043 1.706 c
+90.984 1.706 90.929 1.676 90.881 1.617 c
+90.841 1.565 90.808 1.492 90.778 1.397 c
+90.748 1.309 90.723 1.195 90.704 1.058 c
+90.694 0.919 90.69 0.769 90.69 0.603 c
+90.69 -1.263 l
+89.94 -1.263 l
+89.94 1.47 l
+89.94 1.706 l
+89.94 1.926 l
+89.94 2.003 89.933 2.066 89.925 2.117 c
+89.925 2.22 l
+90.602 2.22 l
+90.602 2.132 l
+90.602 1.985 l
+90.609 1.926 90.617 1.867 90.617 1.808 c
+90.617 1.646 l
+90.631 1.646 l
+90.65 1.735 90.679 1.812 90.719 1.881 c
+90.756 1.959 90.8 2.029 90.852 2.087 c
+90.91 2.147 90.976 2.19 91.057 2.22 c
+91.134 2.257 91.223 2.278 91.322 2.278 c
+91.506 2.278 91.645 2.224 91.733 2.117 c
+91.829 2.018 91.899 1.86 91.939 1.646 c
+91.953 1.646 l
+91.991 1.742 92.032 1.831 92.071 1.912 c
+92.119 1.989 92.175 2.051 92.233 2.103 c
+92.292 2.161 92.358 2.205 92.439 2.234 c
+92.516 2.264 92.604 2.278 92.703 2.278 c
+92.84 2.278 92.954 2.253 93.042 2.205 c
+93.129 2.153 93.196 2.08 93.247 1.985 c
+93.306 1.885 93.343 1.756 93.365 1.602 c
+93.395 1.455 93.409 1.272 93.409 1.058 c
+93.409 -1.263 l
+92.689 -1.263 l
+92.689 0.853 l
+92.689 1.018 92.682 1.154 92.674 1.264 c
+92.663 1.371 92.645 1.455 92.616 1.515 c
+92.593 1.58 92.564 1.632 92.527 1.661 c
+92.498 1.691 92.458 1.706 92.41 1.706 c
+92.292 1.706 92.196 1.617 92.13 1.441 c
+92.071 1.272 92.042 1.014 92.042 0.661 c
+92.042 -1.263 l
+h
+95.783 -1.323 m
+95.525 -1.323 95.298 -1.286 95.092 -1.22 c
+94.887 -1.143 94.71 -1.028 94.563 -0.881 c
+94.416 -0.727 94.299 -0.536 94.21 -0.309 c
+94.129 -0.085 94.093 0.181 94.093 0.485 c
+94.093 0.816 94.137 1.095 94.225 1.324 c
+94.32 1.559 94.449 1.742 94.607 1.881 c
+94.773 2.018 94.96 2.117 95.166 2.176 c
+95.371 2.242 95.581 2.278 95.797 2.278 c
+96.069 2.278 96.304 2.227 96.503 2.132 c
+96.709 2.043 96.875 1.912 97.003 1.735 c
+97.139 1.565 97.239 1.36 97.297 1.118 c
+97.363 0.882 97.4 0.618 97.4 0.324 c
+97.4 0.309 l
+95.034 0.309 l
+95.034 0.162 95.049 0.023 95.078 -0.103 c
+95.114 -0.231 95.169 -0.345 95.24 -0.44 c
+95.305 -0.529 95.39 -0.598 95.489 -0.646 c
+95.585 -0.698 95.699 -0.72 95.828 -0.72 c
+95.982 -0.72 96.121 -0.687 96.239 -0.617 c
+96.364 -0.551 96.452 -0.448 96.503 -0.309 c
+97.341 -0.382 l
+97.312 -0.481 97.256 -0.588 97.179 -0.706 c
+97.098 -0.816 96.996 -0.918 96.871 -1.014 c
+96.753 -1.103 96.599 -1.176 96.415 -1.234 c
+96.239 -1.294 96.026 -1.323 95.783 -1.323 c
+95.783 1.706 m
+95.695 1.706 95.606 1.691 95.519 1.661 c
+95.43 1.632 95.35 1.58 95.284 1.515 c
+95.213 1.444 95.155 1.357 95.107 1.249 c
+95.066 1.139 95.049 1.014 95.049 0.867 c
+96.518 0.867 l
+96.518 1.004 96.493 1.125 96.445 1.235 c
+96.404 1.341 96.349 1.43 96.283 1.5 c
+96.224 1.565 96.15 1.617 96.063 1.646 c
+95.974 1.683 95.878 1.706 95.783 1.706 c
+98.653 -2.631 m
+98.653 -2.013 l
+99.726 -2.013 l
+99.726 2.896 l
+98.653 2.896 l
+98.653 3.514 l
+100.578 3.514 l
+100.578 -2.631 l
+h
+f
+Q
+q 1 0 0 1 545.9966 173.8592 cm
+0 0 m
+0 0.264 -0.073 0.463 -0.22 0.603 c
+-0.36 0.75 -0.617 0.889 -0.999 1.029 c
+-1.374 1.165 -1.66 1.309 -1.866 1.455 c
+-2.065 1.602 -2.212 1.768 -2.308 1.955 c
+-2.406 2.15 -2.454 2.37 -2.454 2.616 c
+-2.454 3.035 -2.315 3.385 -2.028 3.66 c
+-1.745 3.932 -1.378 4.072 -0.926 4.072 c
+-0.613 4.072 -0.334 3.998 -0.088 3.851 c
+0.154 3.711 0.342 3.516 0.47 3.263 c
+0.607 3.017 0.676 2.749 0.676 2.454 c
+0 2.454 l
+0 2.786 -0.081 3.042 -0.235 3.219 c
+-0.393 3.403 -0.625 3.499 -0.926 3.499 c
+-1.19 3.499 -1.404 3.418 -1.558 3.263 c
+-1.705 3.116 -1.778 2.903 -1.778 2.631 c
+-1.778 2.404 -1.701 2.212 -1.543 2.057 c
+-1.378 1.911 -1.124 1.771 -0.779 1.646 c
+-0.261 1.477 0.11 1.268 0.339 1.014 c
+0.574 0.757 0.691 0.426 0.691 0.015 c
+0.691 -0.426 0.548 -0.779 0.264 -1.043 c
+-0.022 -1.301 -0.404 -1.426 -0.881 -1.426 c
+-1.198 -1.426 -1.484 -1.357 -1.749 -1.22 c
+-2.013 -1.084 -2.227 -0.893 -2.381 -0.647 c
+-2.528 -0.405 -2.601 -0.118 -2.601 0.206 c
+-1.926 0.206 l
+-1.926 -0.129 -1.833 -0.389 -1.646 -0.573 c
+-1.462 -0.761 -1.205 -0.852 -0.881 -0.852 c
+-0.588 -0.852 -0.367 -0.779 -0.22 -0.632 c
+-0.073 -0.478 0 -0.264 0 0 c
+4.439 -0.206 m
+5.042 2.631 l
+5.689 2.631 l
+4.704 -1.353 l
+4.189 -1.353 l
+3.41 1.5 l
+2.66 -1.353 l
+2.132 -1.353 l
+1.176 2.631 l
+1.808 2.631 l
+2.425 -0.133 l
+3.161 2.631 l
+3.675 2.631 l
+h
+7.071 -1.353 -0.647 3.984 re
+7.115 3.675 m
+7.115 3.564 7.085 3.472 7.026 3.395 c
+6.967 3.326 6.872 3.293 6.747 3.293 c
+6.629 3.293 6.534 3.326 6.468 3.395 c
+6.409 3.472 6.379 3.564 6.379 3.675 c
+6.379 3.792 6.409 3.884 6.468 3.954 c
+6.534 4.031 6.629 4.072 6.747 4.072 c
+6.872 4.072 6.967 4.031 7.026 3.954 c
+7.085 3.873 7.115 3.781 7.115 3.675 c
+8.937 3.586 m
+8.937 2.631 l
+9.54 2.631 l
+9.54 2.102 l
+8.937 2.102 l
+8.937 -0.368 l
+8.937 -0.526 8.96 -0.643 9.01 -0.721 c
+9.07 -0.801 9.158 -0.838 9.276 -0.838 c
+9.363 -0.838 9.452 -0.823 9.54 -0.794 c
+9.54 -1.353 l
+9.393 -1.4 9.239 -1.426 9.084 -1.426 c
+8.827 -1.426 8.632 -1.334 8.496 -1.147 c
+8.357 -0.963 8.291 -0.702 8.291 -0.368 c
+8.291 2.102 l
+7.688 2.102 l
+7.688 2.631 l
+8.291 2.631 l
+8.291 3.586 l
+h
+11.686 -0.867 m
+11.899 -0.867 12.072 -0.805 12.201 -0.676 c
+12.337 -0.54 12.41 -0.349 12.421 -0.103 c
+13.039 -0.103 l
+13.016 -0.485 12.881 -0.805 12.627 -1.058 c
+12.37 -1.305 12.057 -1.426 11.686 -1.426 c
+11.194 -1.426 10.818 -1.276 10.554 -0.97 c
+10.297 -0.658 10.172 -0.191 10.172 0.426 c
+10.172 0.867 l
+10.172 1.463 10.297 1.918 10.554 2.234 c
+10.818 2.547 11.194 2.705 11.686 2.705 c
+12.087 2.705 12.406 2.572 12.642 2.308 c
+12.884 2.051 13.016 1.705 13.039 1.264 c
+12.421 1.264 l
+12.399 1.558 12.326 1.779 12.201 1.926 c
+12.083 2.072 11.91 2.146 11.686 2.146 c
+11.392 2.146 11.175 2.047 11.04 1.852 c
+10.899 1.664 10.826 1.356 10.818 0.926 c
+10.818 0.411 l
+10.818 -0.059 10.885 -0.393 11.025 -0.588 c
+11.171 -0.775 11.392 -0.867 11.686 -0.867 c
+14.435 2.219 m
+14.689 2.543 15.008 2.705 15.391 2.705 c
+16.096 2.705 16.452 2.234 16.463 1.294 c
+16.463 -1.353 l
+15.817 -1.353 l
+15.817 1.264 l
+15.817 1.577 15.761 1.797 15.655 1.926 c
+15.545 2.051 15.391 2.117 15.185 2.117 c
+15.026 2.117 14.88 2.061 14.743 1.955 c
+14.614 1.845 14.512 1.708 14.435 1.544 c
+14.435 -1.353 l
+13.787 -1.353 l
+13.787 4.292 l
+14.435 4.292 l
+h
+f
+Q
+q 1 0 0 1 567.9281 174.2562 cm
+0 0 m
+0.353 2.234 l
+1.352 2.234 l
+0.529 -1.75 l
+-0.339 -1.75 l
+-0.897 0.559 l
+-1.455 -1.75 l
+-2.323 -1.75 l
+-3.146 2.234 l
+-2.147 2.234 l
+-1.794 0 l
+-1.264 2.234 l
+-0.53 2.234 l
+h
+1.749 0.367 m
+1.749 0.974 1.889 1.448 2.175 1.793 c
+2.458 2.135 2.851 2.308 3.351 2.308 c
+3.858 2.308 4.255 2.135 4.542 1.793 c
+4.825 1.448 4.968 0.974 4.968 0.367 c
+4.968 0.103 l
+4.968 -0.497 4.825 -0.967 4.542 -1.309 c
+4.255 -1.654 3.858 -1.823 3.351 -1.823 c
+2.84 -1.823 2.443 -1.654 2.161 -1.309 c
+1.885 -0.967 1.749 -0.493 1.749 0.118 c
+h
+2.792 0.103 m
+2.792 -0.603 2.977 -0.956 3.351 -0.956 c
+3.704 -0.956 3.895 -0.661 3.925 -0.073 c
+3.925 0.367 l
+3.925 0.727 3.873 0.999 3.777 1.176 c
+3.678 1.352 3.535 1.44 3.351 1.44 c
+3.175 1.44 3.035 1.352 2.94 1.176 c
+2.84 0.999 2.792 0.727 2.792 0.367 c
+h
+7.57 1.22 m
+7.231 1.249 l
+6.945 1.249 6.754 1.124 6.659 0.881 c
+6.659 -1.75 l
+5.614 -1.75 l
+5.614 2.234 l
+6.585 2.234 l
+6.614 1.793 l
+6.78 2.135 7.011 2.308 7.305 2.308 c
+7.422 2.308 7.515 2.285 7.584 2.248 c
+h
+9.437 -0.221 m
+9.157 -0.53 l
+9.157 -1.75 l
+8.114 -1.75 l
+8.114 3.895 l
+9.157 3.895 l
+9.157 0.852 l
+9.275 1.043 l
+9.995 2.234 l
+11.245 2.234 l
+10.083 0.588 l
+11.347 -1.75 l
+10.157 -1.75 l
+h
+12.802 -1.75 -1.043 3.984 re
+11.715 3.263 m
+11.715 3.418 11.763 3.546 11.862 3.645 c
+11.968 3.752 12.104 3.807 12.274 3.807 c
+12.45 3.807 12.586 3.752 12.685 3.645 c
+12.791 3.546 12.847 3.418 12.847 3.263 c
+12.847 3.094 12.791 2.958 12.685 2.851 c
+12.586 2.753 12.45 2.705 12.274 2.705 c
+12.104 2.705 11.968 2.753 11.862 2.851 c
+11.763 2.958 11.715 3.094 11.715 3.263 c
+14.566 2.234 m
+14.596 1.837 l
+14.831 2.15 15.133 2.308 15.507 2.308 c
+16.191 2.308 16.544 1.826 16.565 0.867 c
+16.565 -1.75 l
+15.522 -1.75 l
+15.522 0.794 l
+15.522 1.018 15.485 1.18 15.419 1.278 c
+15.349 1.374 15.232 1.425 15.066 1.425 c
+14.879 1.425 14.732 1.33 14.626 1.147 c
+14.626 -1.75 l
+13.581 -1.75 l
+13.581 2.234 l
+h
+17.183 0.367 m
+17.183 1.014 17.3 1.5 17.535 1.822 c
+17.771 2.146 18.102 2.308 18.535 2.308 c
+18.888 2.308 19.16 2.165 19.359 1.881 c
+19.403 2.234 l
+20.344 2.234 l
+20.344 -1.75 l
+20.344 -2.257 20.2 -2.646 19.917 -2.911 c
+19.63 -3.183 19.226 -3.322 18.697 -3.322 c
+18.47 -3.322 18.234 -3.278 17.992 -3.19 c
+17.756 -3.102 17.58 -2.988 17.462 -2.851 c
+17.815 -2.132 l
+17.911 -2.238 18.039 -2.323 18.197 -2.381 c
+18.352 -2.448 18.499 -2.484 18.638 -2.484 c
+18.873 -2.484 19.039 -2.425 19.137 -2.308 c
+19.245 -2.198 19.299 -2.022 19.299 -1.779 c
+19.299 -1.426 l
+19.101 -1.691 18.844 -1.823 18.52 -1.823 c
+18.098 -1.823 17.771 -1.661 17.535 -1.338 c
+17.308 -1.008 17.19 -0.537 17.183 0.073 c
+h
+18.227 0.103 m
+18.227 -0.272 18.274 -0.54 18.374 -0.706 c
+18.47 -0.875 18.624 -0.956 18.829 -0.956 c
+19.042 -0.956 19.2 -0.879 19.299 -0.721 c
+19.299 1.176 l
+19.189 1.341 19.035 1.425 18.829 1.425 c
+18.624 1.425 18.47 1.341 18.374 1.176 c
+18.274 1.007 18.227 0.738 18.227 0.367 c
+h
+22.695 0.367 m
+22.695 1.014 22.802 1.5 23.018 1.822 c
+23.243 2.146 23.566 2.308 23.989 2.308 c
+24.301 2.308 24.554 2.175 24.753 1.911 c
+24.753 3.895 l
+25.811 3.895 l
+25.811 -1.75 l
+24.856 -1.75 l
+24.812 -1.338 l
+24.595 -1.661 24.319 -1.823 23.989 -1.823 c
+23.577 -1.823 23.257 -1.669 23.033 -1.353 c
+22.817 -1.029 22.703 -0.559 22.695 0.058 c
+h
+23.739 0.103 m
+23.739 -0.291 23.775 -0.566 23.856 -0.721 c
+23.945 -0.879 24.091 -0.956 24.297 -0.956 c
+24.503 -0.956 24.654 -0.864 24.753 -0.676 c
+24.753 1.132 l
+24.654 1.326 24.503 1.425 24.297 1.425 c
+24.099 1.425 23.959 1.344 23.871 1.19 c
+23.783 1.043 23.739 0.771 23.739 0.382 c
+h
+27.663 -1.75 -1.043 3.984 re
+26.576 3.263 m
+26.576 3.418 26.624 3.546 26.723 3.645 c
+26.829 3.752 26.965 3.807 27.134 3.807 c
+27.311 3.807 27.446 3.752 27.546 3.645 c
+27.652 3.546 27.708 3.418 27.708 3.263 c
+27.708 3.094 27.652 2.958 27.546 2.851 c
+27.446 2.753 27.311 2.705 27.134 2.705 c
+26.965 2.705 26.829 2.753 26.723 2.851 c
+26.624 2.958 26.576 3.094 26.576 3.263 c
+30.426 1.22 m
+30.089 1.249 l
+29.802 1.249 29.611 1.124 29.516 0.881 c
+29.516 -1.75 l
+28.471 -1.75 l
+28.471 2.234 l
+29.442 2.234 l
+29.471 1.793 l
+29.637 2.135 29.868 2.308 30.162 2.308 c
+30.28 2.308 30.372 2.285 30.441 2.248 c
+h
+32.5 -1.823 m
+31.97 -1.823 31.551 -1.669 31.249 -1.353 c
+30.956 -1.029 30.809 -0.57 30.809 0.029 c
+30.809 0.338 l
+30.809 0.962 30.945 1.448 31.22 1.793 c
+31.492 2.135 31.885 2.308 32.396 2.308 c
+32.896 2.308 33.267 2.146 33.514 1.822 c
+33.767 1.5 33.9 1.022 33.911 0.397 c
+33.911 -0.103 l
+31.837 -0.103 l
+31.856 -0.397 31.918 -0.614 32.029 -0.75 c
+32.147 -0.89 32.327 -0.956 32.573 -0.956 c
+32.915 -0.956 33.205 -0.838 33.44 -0.603 c
+33.852 -1.235 l
+33.723 -1.411 33.535 -1.555 33.293 -1.661 c
+33.047 -1.768 32.782 -1.823 32.5 -1.823 c
+31.852 0.617 m
+32.882 0.617 l
+32.882 0.72 l
+32.882 0.955 32.841 1.132 32.764 1.249 c
+32.694 1.374 32.566 1.44 32.382 1.44 c
+32.205 1.44 32.073 1.371 31.985 1.234 c
+31.904 1.106 31.86 0.9 31.852 0.617 c
+35.939 -0.956 m
+36.233 -0.956 36.383 -0.761 36.394 -0.368 c
+37.364 -0.368 l
+37.364 -0.802 37.233 -1.154 36.968 -1.426 c
+36.703 -1.691 36.365 -1.823 35.953 -1.823 c
+35.442 -1.823 35.05 -1.669 34.777 -1.353 c
+34.513 -1.029 34.374 -0.559 34.366 0.058 c
+34.366 0.382 l
+34.366 1.007 34.499 1.484 34.763 1.808 c
+35.035 2.138 35.432 2.308 35.953 2.308 c
+36.383 2.308 36.726 2.167 36.982 1.896 c
+37.236 1.62 37.364 1.238 37.364 0.75 c
+36.394 0.75 l
+36.394 0.962 36.354 1.132 36.277 1.249 c
+36.207 1.374 36.09 1.44 35.924 1.44 c
+35.748 1.44 35.619 1.374 35.542 1.249 c
+35.461 1.12 35.417 0.871 35.409 0.5 c
+35.409 0.088 l
+35.409 -0.235 35.424 -0.463 35.454 -0.588 c
+35.49 -0.717 35.546 -0.809 35.615 -0.867 c
+35.693 -0.927 35.799 -0.956 35.939 -0.956 c
+39.172 3.204 m
+39.172 2.234 l
+39.702 2.234 l
+39.702 1.44 l
+39.172 1.44 l
+39.172 -0.53 l
+39.172 -0.688 39.191 -0.794 39.232 -0.852 c
+39.28 -0.912 39.363 -0.941 39.481 -0.941 c
+39.588 -0.941 39.673 -0.933 39.731 -0.912 c
+39.731 -1.72 l
+39.555 -1.786 39.363 -1.823 39.158 -1.823 c
+38.482 -1.823 38.137 -1.437 38.129 -0.661 c
+38.129 1.44 l
+37.674 1.44 l
+37.674 2.234 l
+38.129 2.234 l
+38.129 3.204 l
+h
+40.055 0.367 m
+40.055 0.974 40.194 1.448 40.481 1.793 c
+40.764 2.135 41.157 2.308 41.657 2.308 c
+42.164 2.308 42.561 2.135 42.848 1.793 c
+43.13 1.448 43.274 0.974 43.274 0.367 c
+43.274 0.103 l
+43.274 -0.497 43.13 -0.967 42.848 -1.309 c
+42.561 -1.654 42.164 -1.823 41.657 -1.823 c
+41.146 -1.823 40.749 -1.654 40.466 -1.309 c
+40.19 -0.967 40.055 -0.493 40.055 0.118 c
+h
+41.098 0.103 m
+41.098 -0.603 41.282 -0.956 41.657 -0.956 c
+42.01 -0.956 42.201 -0.661 42.23 -0.073 c
+42.23 0.367 l
+42.23 0.727 42.179 0.999 42.083 1.176 c
+41.984 1.352 41.84 1.44 41.657 1.44 c
+41.48 1.44 41.341 1.352 41.245 1.176 c
+41.146 0.999 41.098 0.727 41.098 0.367 c
+h
+45.875 1.22 m
+45.537 1.249 l
+45.25 1.249 45.059 1.124 44.964 0.881 c
+44.964 -1.75 l
+43.92 -1.75 l
+43.92 2.234 l
+44.89 2.234 l
+44.92 1.793 l
+45.085 2.135 45.317 2.308 45.611 2.308 c
+45.728 2.308 45.821 2.285 45.89 2.248 c
+h
+47.772 -0.015 m
+48.3 2.234 l
+49.403 2.234 l
+48.095 -2.352 l
+47.897 -3.017 47.529 -3.352 46.993 -3.352 c
+46.864 -3.352 46.721 -3.329 46.567 -3.293 c
+46.567 -2.469 l
+46.684 -2.484 l
+46.85 -2.484 46.97 -2.448 47.051 -2.381 c
+47.128 -2.323 47.191 -2.213 47.242 -2.058 c
+47.316 -1.793 l
+46.17 2.234 l
+47.286 2.234 l
+h
+f
+Q
+q 1 0 0 1 620.4617 177.4453 cm
+0 0 m
+0 -0.955 l
+0.603 -0.955 l
+0.603 -1.484 l
+0 -1.484 l
+0 -3.954 l
+0 -4.112 0.023 -4.23 0.074 -4.307 c
+0.133 -4.388 0.221 -4.424 0.339 -4.424 c
+0.427 -4.424 0.515 -4.409 0.603 -4.38 c
+0.603 -4.939 l
+0.456 -4.986 0.302 -5.012 0.148 -5.012 c
+-0.11 -5.012 -0.305 -4.92 -0.44 -4.733 c
+-0.58 -4.549 -0.646 -4.288 -0.646 -3.954 c
+-0.646 -1.484 l
+-1.249 -1.484 l
+-1.249 -0.955 l
+-0.646 -0.955 l
+-0.646 0 l
+h
+1.162 -2.763 m
+1.162 -2.186 1.297 -1.73 1.573 -1.396 c
+1.856 -1.055 2.228 -0.881 2.691 -0.881 c
+3.15 -0.881 3.517 -1.051 3.793 -1.381 c
+4.075 -1.705 4.223 -2.153 4.233 -2.719 c
+4.233 -3.145 l
+4.233 -3.715 4.09 -4.17 3.807 -4.512 c
+3.532 -4.847 3.165 -5.012 2.705 -5.012 c
+2.242 -5.012 1.871 -4.85 1.588 -4.527 c
+1.312 -4.197 1.169 -3.755 1.162 -3.204 c
+h
+1.808 -3.145 m
+1.808 -3.549 1.885 -3.866 2.043 -4.101 c
+2.209 -4.336 2.429 -4.453 2.705 -4.453 c
+3.271 -4.453 3.565 -4.041 3.587 -3.218 c
+3.587 -2.763 l
+3.587 -2.362 3.502 -2.042 3.337 -1.807 c
+3.179 -1.565 2.962 -1.44 2.691 -1.44 c
+2.426 -1.44 2.209 -1.565 2.043 -1.807 c
+1.885 -2.042 1.808 -2.362 1.808 -2.763 c
+h
+7.644 0 m
+7.644 -0.955 l
+8.247 -0.955 l
+8.247 -1.484 l
+7.644 -1.484 l
+7.644 -3.954 l
+7.644 -4.112 7.666 -4.23 7.718 -4.307 c
+7.776 -4.388 7.865 -4.424 7.982 -4.424 c
+8.071 -4.424 8.158 -4.409 8.247 -4.38 c
+8.247 -4.939 l
+8.1 -4.986 7.946 -5.012 7.791 -5.012 c
+7.533 -5.012 7.339 -4.92 7.203 -4.733 c
+7.063 -4.549 6.997 -4.288 6.997 -3.954 c
+6.997 -1.484 l
+6.394 -1.484 l
+6.394 -0.955 l
+6.997 -0.955 l
+6.997 0 l
+h
+9.658 -1.367 m
+9.912 -1.043 10.231 -0.881 10.613 -0.881 c
+11.319 -0.881 11.676 -1.352 11.686 -2.293 c
+11.686 -4.939 l
+11.04 -4.939 l
+11.04 -2.322 l
+11.04 -2.009 10.984 -1.789 10.878 -1.66 c
+10.768 -1.535 10.613 -1.469 10.407 -1.469 c
+10.249 -1.469 10.103 -1.525 9.966 -1.631 c
+9.838 -1.741 9.735 -1.878 9.658 -2.042 c
+9.658 -4.939 l
+9.011 -4.939 l
+9.011 0.706 l
+9.658 0.706 l
+h
+14.068 -5.012 m
+13.567 -5.012 13.185 -4.865 12.921 -4.571 c
+12.657 -4.277 12.524 -3.844 12.524 -3.262 c
+12.524 -2.792 l
+12.524 -2.198 12.649 -1.73 12.906 -1.396 c
+13.17 -1.055 13.531 -0.881 13.994 -0.881 c
+14.454 -0.881 14.795 -1.036 15.023 -1.337 c
+15.258 -1.631 15.379 -2.094 15.391 -2.719 c
+15.391 -3.145 l
+13.17 -3.145 l
+13.17 -3.233 l
+13.17 -3.667 13.248 -3.979 13.406 -4.174 c
+13.571 -4.361 13.803 -4.453 14.097 -4.453 c
+14.292 -4.453 14.464 -4.421 14.612 -4.351 c
+14.758 -4.274 14.894 -4.156 15.023 -3.998 c
+15.361 -4.409 l
+15.074 -4.814 14.645 -5.012 14.068 -5.012 c
+13.994 -1.44 m
+13.718 -1.44 13.517 -1.535 13.391 -1.72 c
+13.263 -1.907 13.189 -2.198 13.17 -2.587 c
+14.743 -2.587 l
+14.743 -2.499 l
+14.722 -2.117 14.656 -1.848 14.538 -1.69 c
+14.421 -1.525 14.236 -1.44 13.994 -1.44 c
+19.83 -3.924 m
+19.83 -3.777 19.774 -3.656 19.668 -3.557 c
+19.558 -3.461 19.352 -3.343 19.05 -3.204 c
+18.705 -3.057 18.462 -2.936 18.315 -2.836 c
+18.169 -2.73 18.058 -2.612 17.992 -2.484 c
+17.922 -2.358 17.889 -2.2 17.889 -2.013 c
+17.889 -1.69 18.007 -1.421 18.242 -1.205 c
+18.477 -0.992 18.778 -0.881 19.154 -0.881 c
+19.535 -0.881 19.844 -0.995 20.079 -1.219 c
+20.314 -1.448 20.432 -1.734 20.432 -2.087 c
+19.786 -2.087 l
+19.786 -1.911 19.726 -1.76 19.609 -1.631 c
+19.491 -1.506 19.337 -1.44 19.154 -1.44 c
+18.955 -1.44 18.805 -1.495 18.697 -1.602 c
+18.587 -1.701 18.536 -1.834 18.536 -1.999 c
+18.536 -2.127 18.573 -2.234 18.654 -2.322 c
+18.731 -2.403 18.922 -2.506 19.227 -2.63 c
+19.705 -2.818 20.035 -3.006 20.212 -3.189 c
+20.388 -3.366 20.476 -3.594 20.476 -3.866 c
+20.476 -4.218 20.351 -4.498 20.108 -4.704 c
+19.873 -4.909 19.558 -5.012 19.168 -5.012 c
+18.745 -5.012 18.407 -4.895 18.153 -4.659 c
+17.897 -4.417 17.772 -4.112 17.772 -3.748 c
+18.419 -3.748 l
+18.425 -3.976 18.496 -4.152 18.624 -4.277 c
+18.749 -4.394 18.932 -4.453 19.168 -4.453 c
+19.381 -4.453 19.543 -4.405 19.653 -4.307 c
+19.771 -4.211 19.83 -4.082 19.83 -3.924 c
+24.195 -3.145 m
+24.195 -3.773 24.077 -4.244 23.842 -4.556 c
+23.614 -4.862 23.298 -5.012 22.887 -5.012 c
+22.483 -5.012 22.174 -4.862 21.961 -4.556 c
+21.961 -6.468 l
+21.314 -6.468 l
+21.314 -0.955 l
+21.902 -0.955 l
+21.947 -1.396 l
+22.159 -1.055 22.468 -0.881 22.872 -0.881 c
+23.313 -0.881 23.64 -1.036 23.857 -1.337 c
+24.07 -1.643 24.185 -2.098 24.195 -2.705 c
+h
+23.549 -2.763 m
+23.549 -2.322 23.479 -1.999 23.343 -1.793 c
+23.203 -1.58 22.982 -1.469 22.681 -1.469 c
+22.365 -1.469 22.126 -1.624 21.961 -1.925 c
+21.961 -3.998 l
+22.126 -4.303 22.365 -4.453 22.681 -4.453 c
+22.975 -4.453 23.188 -4.351 23.328 -4.145 c
+23.464 -3.931 23.537 -3.601 23.549 -3.16 c
+h
+26.458 -5.012 m
+25.959 -5.012 25.577 -4.865 25.313 -4.571 c
+25.047 -4.277 24.916 -3.844 24.916 -3.262 c
+24.916 -2.792 l
+24.916 -2.198 25.041 -1.73 25.297 -1.396 c
+25.562 -1.055 25.922 -0.881 26.385 -0.881 c
+26.845 -0.881 27.187 -1.036 27.414 -1.337 c
+27.649 -1.631 27.771 -2.094 27.782 -2.719 c
+27.782 -3.145 l
+25.562 -3.145 l
+25.562 -3.233 l
+25.562 -3.667 25.639 -3.979 25.797 -4.174 c
+25.963 -4.361 26.194 -4.453 26.488 -4.453 c
+26.683 -4.453 26.855 -4.421 27.003 -4.351 c
+27.15 -4.274 27.285 -4.156 27.414 -3.998 c
+27.752 -4.409 l
+27.466 -4.814 27.036 -5.012 26.458 -5.012 c
+26.385 -1.44 m
+26.109 -1.44 25.908 -1.535 25.783 -1.72 c
+25.654 -1.907 25.581 -2.198 25.562 -2.587 c
+27.135 -2.587 l
+27.135 -2.499 l
+27.113 -2.117 27.046 -1.848 26.929 -1.69 c
+26.811 -1.525 26.628 -1.44 26.385 -1.44 c
+29.943 -4.453 m
+30.155 -4.453 30.329 -4.391 30.456 -4.262 c
+30.593 -4.126 30.666 -3.935 30.678 -3.689 c
+31.295 -3.689 l
+31.273 -4.072 31.137 -4.391 30.884 -4.644 c
+30.626 -4.891 30.313 -5.012 29.943 -5.012 c
+29.45 -5.012 29.076 -4.862 28.81 -4.556 c
+28.553 -4.244 28.428 -3.777 28.428 -3.16 c
+28.428 -2.719 l
+28.428 -2.123 28.553 -1.668 28.81 -1.352 c
+29.076 -1.04 29.45 -0.881 29.943 -0.881 c
+30.343 -0.881 30.662 -1.014 30.898 -1.278 c
+31.14 -1.535 31.273 -1.881 31.295 -2.322 c
+30.678 -2.322 l
+30.655 -2.028 30.582 -1.807 30.456 -1.66 c
+30.339 -1.514 30.167 -1.44 29.943 -1.44 c
+29.648 -1.44 29.432 -1.539 29.296 -1.734 c
+29.156 -1.922 29.083 -2.23 29.076 -2.66 c
+29.076 -3.175 l
+29.076 -3.645 29.141 -3.979 29.281 -4.174 c
+29.428 -4.361 29.648 -4.453 29.943 -4.453 c
+32.75 -4.939 -0.647 3.984 re
+32.794 0.088 m
+32.794 -0.022 32.765 -0.114 32.706 -0.191 c
+32.647 -0.261 32.551 -0.294 32.426 -0.294 c
+32.309 -0.294 32.214 -0.261 32.147 -0.191 c
+32.089 -0.114 32.06 -0.022 32.06 0.088 c
+32.06 0.206 32.089 0.298 32.147 0.368 c
+32.214 0.445 32.309 0.485 32.426 0.485 c
+32.551 0.485 32.647 0.445 32.706 0.368 c
+32.765 0.287 32.794 0.195 32.794 0.088 c
+33.941 -4.939 m
+33.941 -1.484 l
+33.426 -1.484 l
+33.426 -0.955 l
+33.941 -0.955 l
+33.941 -0.588 l
+33.948 -0.158 34.062 0.177 34.279 0.412 c
+34.503 0.655 34.815 0.78 35.219 0.78 c
+35.366 0.78 35.506 0.757 35.646 0.721 c
+35.792 0.68 35.944 0.625 36.101 0.559 c
+35.983 -0.014 l
+35.748 0.111 35.506 0.177 35.264 0.177 c
+35.017 0.177 34.845 0.107 34.749 -0.029 c
+34.649 -0.158 34.602 -0.353 34.602 -0.617 c
+34.602 -0.955 l
+35.249 -0.955 l
+35.249 -1.484 l
+34.602 -1.484 l
+34.602 -4.939 l
+h
+36.41 -4.939 -0.647 3.984 re
+38.88 -5.012 m
+38.379 -5.012 37.997 -4.865 37.733 -4.571 c
+37.469 -4.277 37.336 -3.844 37.336 -3.262 c
+37.336 -2.792 l
+37.336 -2.198 37.461 -1.73 37.718 -1.396 c
+37.982 -1.055 38.343 -0.881 38.806 -0.881 c
+39.266 -0.881 39.607 -1.036 39.835 -1.337 c
+40.07 -1.631 40.191 -2.094 40.203 -2.719 c
+40.203 -3.145 l
+37.982 -3.145 l
+37.982 -3.233 l
+37.982 -3.667 38.06 -3.979 38.218 -4.174 c
+38.383 -4.361 38.615 -4.453 38.909 -4.453 c
+39.104 -4.453 39.276 -4.421 39.424 -4.351 c
+39.57 -4.274 39.707 -4.156 39.835 -3.998 c
+40.173 -4.409 l
+39.886 -4.814 39.457 -5.012 38.88 -5.012 c
+38.806 -1.44 m
+38.531 -1.44 38.329 -1.535 38.203 -1.72 c
+38.075 -1.907 38.001 -2.198 37.982 -2.587 c
+39.555 -2.587 l
+39.555 -2.499 l
+39.534 -2.117 39.468 -1.848 39.35 -1.69 c
+39.233 -1.525 39.048 -1.44 38.806 -1.44 c
+40.849 -2.763 m
+40.849 -2.157 40.96 -1.69 41.188 -1.367 c
+41.423 -1.043 41.749 -0.881 42.172 -0.881 c
+42.554 -0.881 42.852 -1.04 43.069 -1.352 c
+43.069 0.706 l
+43.715 0.706 l
+43.715 -4.939 l
+43.127 -4.939 l
+43.083 -4.512 l
+42.878 -4.847 42.572 -5.012 42.172 -5.012 c
+41.76 -5.012 41.437 -4.858 41.202 -4.542 c
+40.966 -4.218 40.849 -3.763 40.849 -3.175 c
+h
+41.496 -3.145 m
+41.496 -3.586 41.558 -3.917 41.687 -4.13 c
+41.823 -4.336 42.044 -4.438 42.348 -4.438 c
+42.672 -4.438 42.911 -4.277 43.069 -3.954 c
+43.069 -1.94 l
+42.9 -1.628 42.661 -1.469 42.348 -1.469 c
+42.044 -1.469 41.823 -1.572 41.687 -1.778 c
+41.558 -1.984 41.496 -2.308 41.496 -2.748 c
+h
+49.315 -3.145 m
+49.315 -3.763 49.202 -4.23 48.978 -4.542 c
+48.76 -4.858 48.438 -5.012 48.008 -5.012 c
+47.585 -5.012 47.272 -4.832 47.067 -4.469 c
+47.037 -4.939 l
+46.435 -4.939 l
+46.435 0.706 l
+47.081 0.706 l
+47.081 -1.396 l
+47.295 -1.055 47.603 -0.881 48.008 -0.881 c
+48.438 -0.881 48.76 -1.04 48.978 -1.352 c
+49.202 -1.657 49.315 -2.123 49.315 -2.748 c
+h
+48.669 -2.763 m
+48.669 -2.293 48.6 -1.962 48.463 -1.764 c
+48.334 -1.569 48.125 -1.469 47.831 -1.469 c
+47.497 -1.469 47.247 -1.653 47.081 -2.013 c
+47.081 -3.895 l
+47.247 -4.259 47.501 -4.438 47.846 -4.438 c
+48.14 -4.438 48.349 -4.336 48.478 -4.13 c
+48.603 -3.924 48.669 -3.609 48.669 -3.175 c
+h
+51.8 -1.572 m
+51.712 -1.554 51.613 -1.543 51.505 -1.543 c
+51.172 -1.543 50.936 -1.727 50.8 -2.087 c
+50.8 -4.939 l
+50.154 -4.939 l
+50.154 -0.955 l
+50.786 -0.955 l
+50.8 -1.367 l
+50.977 -1.043 51.22 -0.881 51.536 -0.881 c
+51.642 -0.881 51.73 -0.904 51.8 -0.941 c
+h
+54.343 -4.939 m
+54.302 -4.85 54.277 -4.704 54.269 -4.498 c
+54.034 -4.843 53.74 -5.012 53.387 -5.012 c
+53.024 -5.012 52.741 -4.916 52.535 -4.718 c
+52.336 -4.512 52.241 -4.226 52.241 -3.85 c
+52.241 -3.451 52.377 -3.131 52.652 -2.896 c
+52.924 -2.653 53.3 -2.528 53.77 -2.528 c
+54.254 -2.528 l
+54.254 -2.102 l
+54.254 -1.866 54.2 -1.701 54.093 -1.602 c
+53.982 -1.495 53.821 -1.44 53.608 -1.44 c
+53.41 -1.44 53.248 -1.499 53.123 -1.616 c
+53.005 -1.734 52.947 -1.881 52.947 -2.057 c
+52.299 -2.057 l
+52.299 -1.863 52.359 -1.672 52.476 -1.484 c
+52.602 -1.3 52.762 -1.153 52.961 -1.043 c
+53.167 -0.937 53.395 -0.881 53.652 -0.881 c
+54.053 -0.881 54.358 -0.984 54.563 -1.19 c
+54.776 -1.396 54.89 -1.69 54.902 -2.072 c
+54.902 -4.086 l
+54.902 -4.391 54.938 -4.656 55.019 -4.88 c
+55.019 -4.939 l
+h
+53.475 -4.424 m
+53.641 -4.424 53.792 -4.38 53.932 -4.292 c
+54.078 -4.203 54.185 -4.093 54.254 -3.954 c
+54.254 -3.013 l
+53.888 -3.013 l
+53.571 -3.013 53.329 -3.083 53.152 -3.218 c
+52.976 -3.347 52.887 -3.534 52.887 -3.777 c
+52.887 -4.005 52.932 -4.17 53.02 -4.277 c
+53.109 -4.376 53.259 -4.424 53.475 -4.424 c
+56.519 -0.955 m
+56.533 -1.396 l
+56.787 -1.055 57.11 -0.881 57.503 -0.881 c
+58.208 -0.881 58.565 -1.352 58.576 -2.293 c
+58.576 -4.939 l
+57.93 -4.939 l
+57.93 -2.322 l
+57.93 -2.009 57.874 -1.789 57.768 -1.66 c
+57.658 -1.535 57.503 -1.469 57.298 -1.469 c
+57.14 -1.469 56.992 -1.525 56.857 -1.631 c
+56.728 -1.741 56.625 -1.878 56.548 -2.042 c
+56.548 -4.939 l
+55.901 -4.939 l
+55.901 -0.955 l
+h
+60.928 -4.453 m
+61.142 -4.453 61.314 -4.391 61.443 -4.262 c
+61.579 -4.126 61.652 -3.935 61.663 -3.689 c
+62.281 -3.689 l
+62.258 -4.072 62.123 -4.391 61.869 -4.644 c
+61.612 -4.891 61.3 -5.012 60.928 -5.012 c
+60.436 -5.012 60.061 -4.862 59.796 -4.556 c
+59.539 -4.244 59.414 -3.777 59.414 -3.16 c
+59.414 -2.719 l
+59.414 -2.123 59.539 -1.668 59.796 -1.352 c
+60.061 -1.04 60.436 -0.881 60.928 -0.881 c
+61.329 -0.881 61.649 -1.014 61.884 -1.278 c
+62.126 -1.535 62.258 -1.881 62.281 -2.322 c
+61.663 -2.322 l
+61.641 -2.028 61.568 -1.807 61.443 -1.66 c
+61.325 -1.514 61.152 -1.44 60.928 -1.44 c
+60.634 -1.44 60.417 -1.539 60.282 -1.734 c
+60.141 -1.922 60.068 -2.23 60.061 -2.66 c
+60.061 -3.175 l
+60.061 -3.645 60.127 -3.979 60.267 -4.174 c
+60.413 -4.361 60.634 -4.453 60.928 -4.453 c
+63.677 -1.367 m
+63.931 -1.043 64.25 -0.881 64.633 -0.881 c
+65.338 -0.881 65.694 -1.352 65.705 -2.293 c
+65.705 -4.939 l
+65.059 -4.939 l
+65.059 -2.322 l
+65.059 -2.009 65.003 -1.789 64.897 -1.66 c
+64.787 -1.535 64.633 -1.469 64.427 -1.469 c
+64.269 -1.469 64.122 -1.525 63.985 -1.631 c
+63.857 -1.741 63.754 -1.878 63.677 -2.042 c
+63.677 -4.939 l
+63.03 -4.939 l
+63.03 0.706 l
+63.677 0.706 l
+h
+66.705 -4.586 m
+66.705 -4.469 66.738 -4.373 66.808 -4.292 c
+66.873 -4.215 66.977 -4.174 67.116 -4.174 c
+67.263 -4.174 67.37 -4.215 67.44 -4.292 c
+67.517 -4.373 67.557 -4.469 67.557 -4.586 c
+67.557 -4.696 67.517 -4.787 67.44 -4.865 c
+67.37 -4.943 67.263 -4.982 67.116 -4.982 c
+66.977 -4.982 66.873 -4.943 66.808 -4.865 c
+66.738 -4.787 66.705 -4.696 66.705 -4.586 c
+71.482 -3.248 m
+71.556 -3.85 l
+71.658 -3.322 l
+72.511 0.412 l
+73.069 0.412 l
+73.907 -3.322 l
+74.01 -3.866 l
+74.083 -3.248 l
+74.746 0.412 l
+75.421 0.412 l
+74.349 -4.939 l
+73.746 -4.939 l
+72.849 -1.043 l
+72.79 -0.72 l
+72.747 -1.043 l
+71.82 -4.939 l
+71.203 -4.939 l
+70.144 0.412 l
+70.821 0.412 l
+h
+76.803 -4.939 -0.646 3.984 re
+76.847 0.088 m
+76.847 -0.022 76.818 -0.114 76.759 -0.191 c
+76.7 -0.261 76.604 -0.294 76.479 -0.294 c
+76.362 -0.294 76.267 -0.261 76.2 -0.191 c
+76.142 -0.114 76.112 -0.022 76.112 0.088 c
+76.112 0.206 76.142 0.298 76.2 0.368 c
+76.267 0.445 76.362 0.485 76.479 0.485 c
+76.604 0.485 76.7 0.445 76.759 0.368 c
+76.818 0.287 76.847 0.195 76.847 0.088 c
+78.669 0 m
+78.669 -0.955 l
+79.272 -0.955 l
+79.272 -1.484 l
+78.669 -1.484 l
+78.669 -3.954 l
+78.669 -4.112 78.692 -4.23 78.744 -4.307 c
+78.802 -4.388 78.891 -4.424 79.008 -4.424 c
+79.096 -4.424 79.184 -4.409 79.272 -4.38 c
+79.272 -4.939 l
+79.126 -4.986 78.971 -5.012 78.817 -5.012 c
+78.559 -5.012 78.365 -4.92 78.229 -4.733 c
+78.089 -4.549 78.023 -4.288 78.023 -3.954 c
+78.023 -1.484 l
+77.42 -1.484 l
+77.42 -0.955 l
+78.023 -0.955 l
+78.023 0 l
+h
+80.683 -1.367 m
+80.938 -1.043 81.256 -0.881 81.639 -0.881 c
+82.345 -0.881 82.701 -1.352 82.712 -2.293 c
+82.712 -4.939 l
+82.065 -4.939 l
+82.065 -2.322 l
+82.065 -2.009 82.01 -1.789 81.904 -1.66 c
+81.794 -1.535 81.639 -1.469 81.433 -1.469 c
+81.275 -1.469 81.128 -1.525 80.992 -1.631 c
+80.864 -1.741 80.761 -1.878 80.683 -2.042 c
+80.683 -4.939 l
+80.037 -4.939 l
+80.037 0.706 l
+80.683 0.706 l
+h
+f
+Q
+707.613 174.374 -1.793 0.867 re
+711.582 174.374 m
+711.582 173.727 711.478 173.242 711.273 172.918 c
+711.067 172.595 710.744 172.433 710.302 172.433 c
+709.957 172.433 709.678 172.587 709.465 172.903 c
+709.436 172.506 l
+708.48 172.506 l
+708.48 178.151 l
+709.523 178.151 l
+709.523 176.167 l
+709.718 176.431 709.972 176.564 710.288 176.564 c
+710.729 176.564 711.052 176.402 711.258 176.078 c
+711.464 175.756 711.57 175.285 711.582 174.667 c
+h
+710.538 174.623 m
+710.538 175.043 710.498 175.322 710.42 175.461 c
+710.34 175.608 710.2 175.681 709.994 175.681 c
+709.777 175.681 709.619 175.583 709.523 175.388 c
+709.523 173.58 l
+709.612 173.393 709.774 173.3 710.009 173.3 c
+710.204 173.3 710.34 173.363 710.42 173.491 c
+710.498 173.616 710.538 173.874 710.538 174.256 c
+h
+f
+q 1 0 0 1 712.3608 172.8592 cm
+0 0 m
+0 0.118 0.033 0.214 0.102 0.294 c
+0.169 0.372 0.272 0.412 0.411 0.412 c
+0.559 0.412 0.665 0.372 0.735 0.294 c
+0.812 0.214 0.852 0.118 0.852 0 c
+0.852 -0.11 0.812 -0.201 0.735 -0.278 c
+0.665 -0.357 0.559 -0.396 0.411 -0.396 c
+0.272 -0.396 0.169 -0.357 0.102 -0.278 c
+0.033 -0.201 0 -0.11 0 0 c
+0 2.822 m
+0 2.94 0.033 3.036 0.102 3.117 c
+0.169 3.194 0.272 3.234 0.411 3.234 c
+0.559 3.234 0.665 3.194 0.735 3.117 c
+0.812 3.036 0.852 2.94 0.852 2.822 c
+0.852 2.712 0.812 2.621 0.735 2.544 c
+0.665 2.463 0.559 2.426 0.411 2.426 c
+0.272 2.426 0.169 2.463 0.102 2.544 c
+0.033 2.621 0 2.712 0 2.822 c
+6.879 0.309 m
+6.761 0.162 l
+6.427 -0.231 5.931 -0.426 5.277 -0.426 c
+4.696 -0.426 4.241 -0.235 3.91 0.148 c
+3.586 0.53 3.418 1.073 3.41 1.779 c
+3.41 2.822 l
+3.41 3.576 3.557 4.138 3.851 4.513 c
+4.152 4.884 4.604 5.072 5.203 5.072 c
+5.71 5.072 6.107 4.929 6.394 4.645 c
+6.688 4.358 6.849 3.955 6.879 3.425 c
+6.203 3.425 l
+6.181 3.756 6.089 4.017 5.924 4.204 c
+5.766 4.399 5.531 4.499 5.218 4.499 c
+4.825 4.499 4.542 4.37 4.366 4.116 c
+4.189 3.859 4.094 3.458 4.087 2.911 c
+4.087 1.823 l
+4.087 1.283 4.189 0.867 4.395 0.574 c
+4.601 0.287 4.895 0.148 5.277 0.148 c
+5.637 0.148 5.916 0.235 6.115 0.412 c
+6.203 0.5 l
+6.203 1.735 l
+5.232 1.735 l
+5.232 2.309 l
+6.879 2.309 l
+h
+8.599 -0.353 -0.647 3.984 re
+8.643 4.675 m
+8.643 4.564 8.613 4.472 8.555 4.395 c
+8.496 4.326 8.401 4.293 8.276 4.293 c
+8.158 4.293 8.062 4.326 7.996 4.395 c
+7.937 4.472 7.908 4.564 7.908 4.675 c
+7.908 4.792 7.937 4.884 7.996 4.954 c
+8.062 5.031 8.158 5.072 8.276 5.072 c
+8.401 5.072 8.496 5.031 8.555 4.954 c
+8.613 4.873 8.643 4.781 8.643 4.675 c
+10.466 4.586 m
+10.466 3.631 l
+11.069 3.631 l
+11.069 3.102 l
+10.466 3.102 l
+10.466 0.632 l
+10.466 0.474 10.487 0.357 10.539 0.279 c
+10.598 0.198 10.686 0.162 10.803 0.162 c
+10.892 0.162 10.98 0.177 11.069 0.206 c
+11.069 -0.353 l
+10.921 -0.4 10.767 -0.426 10.612 -0.426 c
+10.356 -0.426 10.161 -0.334 10.024 -0.147 c
+9.885 0.037 9.818 0.298 9.818 0.632 c
+9.818 3.102 l
+9.216 3.102 l
+9.216 3.631 l
+9.818 3.631 l
+9.818 4.586 l
+h
+16.521 0.794 m
+17.124 3.631 l
+17.771 3.631 l
+16.786 -0.353 l
+16.272 -0.353 l
+15.493 2.5 l
+14.743 -0.353 l
+14.214 -0.353 l
+13.259 3.631 l
+13.891 3.631 l
+14.508 0.867 l
+15.243 3.631 l
+15.757 3.631 l
+h
+19.152 -0.353 -0.646 3.984 re
+19.197 4.675 m
+19.197 4.564 19.168 4.472 19.108 4.395 c
+19.05 4.326 18.954 4.293 18.83 4.293 c
+18.712 4.293 18.616 4.326 18.55 4.395 c
+18.491 4.472 18.462 4.564 18.462 4.675 c
+18.462 4.792 18.491 4.884 18.55 4.954 c
+18.616 5.031 18.712 5.072 18.83 5.072 c
+18.954 5.072 19.05 5.031 19.108 4.954 c
+19.168 4.873 19.197 4.781 19.197 4.675 c
+20.872 -0.353 -0.646 5.644 re
+22.593 -0.353 -0.647 5.644 re
+26.708 0.133 m
+26.921 0.133 27.094 0.195 27.222 0.324 c
+27.359 0.46 27.432 0.651 27.443 0.897 c
+28.06 0.897 l
+28.039 0.515 27.902 0.195 27.649 -0.058 c
+27.391 -0.305 27.079 -0.426 26.708 -0.426 c
+26.216 -0.426 25.841 -0.276 25.576 0.03 c
+25.319 0.342 25.194 0.809 25.194 1.426 c
+25.194 1.867 l
+25.194 2.463 25.319 2.918 25.576 3.234 c
+25.841 3.547 26.216 3.705 26.708 3.705 c
+27.108 3.705 27.428 3.572 27.663 3.308 c
+27.906 3.051 28.039 2.705 28.06 2.264 c
+27.443 2.264 l
+27.421 2.558 27.347 2.779 27.222 2.926 c
+27.104 3.072 26.932 3.146 26.708 3.146 c
+26.414 3.146 26.198 3.047 26.061 2.852 c
+25.922 2.664 25.849 2.356 25.841 1.926 c
+25.841 1.411 l
+25.841 0.941 25.907 0.607 26.046 0.412 c
+26.194 0.225 26.414 0.133 26.708 0.133 c
+30.456 3.014 m
+30.368 3.032 30.269 3.043 30.162 3.043 c
+29.828 3.043 29.593 2.859 29.456 2.5 c
+29.456 -0.353 l
+28.81 -0.353 l
+28.81 3.631 l
+29.442 3.631 l
+29.456 3.219 l
+29.633 3.543 29.876 3.705 30.192 3.705 c
+30.298 3.705 30.387 3.682 30.456 3.645 c
+h
+32.456 -0.426 m
+31.956 -0.426 31.573 -0.278 31.309 0.015 c
+31.044 0.309 30.912 0.742 30.912 1.324 c
+30.912 1.794 l
+30.912 2.389 31.037 2.856 31.295 3.19 c
+31.559 3.532 31.919 3.705 32.382 3.705 c
+32.841 3.705 33.183 3.55 33.411 3.249 c
+33.646 2.955 33.767 2.492 33.778 1.867 c
+33.778 1.441 l
+31.559 1.441 l
+31.559 1.353 l
+31.559 0.919 31.636 0.607 31.794 0.412 c
+31.96 0.225 32.191 0.133 32.485 0.133 c
+32.679 0.133 32.852 0.166 32.999 0.235 c
+33.146 0.312 33.282 0.43 33.411 0.588 c
+33.749 0.177 l
+33.462 -0.228 33.032 -0.426 32.456 -0.426 c
+32.382 3.146 m
+32.106 3.146 31.904 3.051 31.779 2.866 c
+31.65 2.679 31.577 2.389 31.559 1.999 c
+33.132 1.999 l
+33.132 2.087 l
+33.109 2.469 33.043 2.738 32.926 2.897 c
+32.808 3.061 32.625 3.146 32.382 3.146 c
+36.6 -0.353 m
+36.56 -0.264 36.535 -0.118 36.527 0.088 c
+36.292 -0.257 35.998 -0.426 35.646 -0.426 c
+35.281 -0.426 34.998 -0.33 34.792 -0.132 c
+34.594 0.074 34.499 0.36 34.499 0.736 c
+34.499 1.135 34.634 1.455 34.91 1.691 c
+35.182 1.933 35.557 2.058 36.027 2.058 c
+36.512 2.058 l
+36.512 2.484 l
+36.512 2.72 36.457 2.885 36.351 2.984 c
+36.24 3.091 36.079 3.146 35.866 3.146 c
+35.667 3.146 35.505 3.087 35.38 2.97 c
+35.263 2.852 35.204 2.705 35.204 2.529 c
+34.557 2.529 l
+34.557 2.723 34.616 2.914 34.734 3.102 c
+34.859 3.286 35.021 3.433 35.218 3.543 c
+35.424 3.649 35.652 3.705 35.91 3.705 c
+36.311 3.705 36.615 3.602 36.821 3.396 c
+37.034 3.19 37.148 2.897 37.159 2.514 c
+37.159 0.5 l
+37.159 0.195 37.196 -0.07 37.277 -0.294 c
+37.277 -0.353 l
+h
+35.733 0.162 m
+35.899 0.162 36.049 0.206 36.189 0.294 c
+36.336 0.383 36.442 0.493 36.512 0.632 c
+36.512 1.573 l
+36.145 1.573 l
+35.829 1.573 35.586 1.503 35.41 1.368 c
+35.233 1.239 35.145 1.052 35.145 0.809 c
+35.145 0.581 35.189 0.416 35.278 0.309 c
+35.366 0.21 35.517 0.162 35.733 0.162 c
+39.011 4.586 m
+39.011 3.631 l
+39.614 3.631 l
+39.614 3.102 l
+39.011 3.102 l
+39.011 0.632 l
+39.011 0.474 39.033 0.357 39.085 0.279 c
+39.143 0.198 39.232 0.162 39.349 0.162 c
+39.438 0.162 39.526 0.177 39.614 0.206 c
+39.614 -0.353 l
+39.467 -0.4 39.313 -0.426 39.158 -0.426 c
+38.901 -0.426 38.706 -0.334 38.57 -0.147 c
+38.431 0.037 38.364 0.298 38.364 0.632 c
+38.364 3.102 l
+37.762 3.102 l
+37.762 3.631 l
+38.364 3.631 l
+38.364 4.586 l
+h
+41.804 -0.426 m
+41.304 -0.426 40.922 -0.278 40.658 0.015 c
+40.392 0.309 40.261 0.742 40.261 1.324 c
+40.261 1.794 l
+40.261 2.389 40.386 2.856 40.643 3.19 c
+40.907 3.532 41.267 3.705 41.73 3.705 c
+42.19 3.705 42.532 3.55 42.759 3.249 c
+42.995 2.955 43.116 2.492 43.127 1.867 c
+43.127 1.441 l
+40.907 1.441 l
+40.907 1.353 l
+40.907 0.919 40.984 0.607 41.142 0.412 c
+41.308 0.225 41.539 0.133 41.834 0.133 c
+42.028 0.133 42.201 0.166 42.348 0.235 c
+42.495 0.312 42.63 0.43 42.759 0.588 c
+43.097 0.177 l
+42.811 -0.228 42.381 -0.426 41.804 -0.426 c
+41.73 3.146 m
+41.455 3.146 41.253 3.051 41.128 2.866 c
+40.999 2.679 40.926 2.389 40.907 1.999 c
+42.48 1.999 l
+42.48 2.087 l
+42.458 2.469 42.392 2.738 42.274 2.897 c
+42.156 3.061 41.973 3.146 41.73 3.146 c
+46.478 4.586 m
+46.478 3.631 l
+47.081 3.631 l
+47.081 3.102 l
+46.478 3.102 l
+46.478 0.632 l
+46.478 0.474 46.501 0.357 46.551 0.279 c
+46.611 0.198 46.699 0.162 46.817 0.162 c
+46.904 0.162 46.993 0.177 47.081 0.206 c
+47.081 -0.353 l
+46.934 -0.4 46.78 -0.426 46.625 -0.426 c
+46.368 -0.426 46.173 -0.334 46.037 -0.147 c
+45.898 0.037 45.832 0.298 45.832 0.632 c
+45.832 3.102 l
+45.229 3.102 l
+45.229 3.631 l
+45.832 3.631 l
+45.832 4.586 l
+h
+48.492 3.219 m
+48.745 3.543 49.065 3.705 49.447 3.705 c
+50.153 3.705 50.509 3.234 50.52 2.294 c
+50.52 -0.353 l
+49.874 -0.353 l
+49.874 2.264 l
+49.874 2.577 49.819 2.797 49.712 2.926 c
+49.602 3.051 49.447 3.117 49.242 3.117 c
+49.084 3.117 48.937 3.061 48.801 2.955 c
+48.672 2.845 48.569 2.708 48.492 2.544 c
+48.492 -0.353 l
+47.845 -0.353 l
+47.845 5.292 l
+48.492 5.292 l
+h
+52.901 -0.426 m
+52.402 -0.426 52.02 -0.278 51.756 0.015 c
+51.49 0.309 51.359 0.742 51.359 1.324 c
+51.359 1.794 l
+51.359 2.389 51.484 2.856 51.741 3.19 c
+52.005 3.532 52.365 3.705 52.828 3.705 c
+53.287 3.705 53.63 3.55 53.857 3.249 c
+54.092 2.955 54.214 2.492 54.225 1.867 c
+54.225 1.441 l
+52.005 1.441 l
+52.005 1.353 l
+52.005 0.919 52.082 0.607 52.24 0.412 c
+52.406 0.225 52.637 0.133 52.932 0.133 c
+53.126 0.133 53.298 0.166 53.445 0.235 c
+53.593 0.312 53.728 0.43 53.857 0.588 c
+54.195 0.177 l
+53.909 -0.228 53.479 -0.426 52.901 -0.426 c
+52.828 3.146 m
+52.552 3.146 52.35 3.051 52.226 2.866 c
+52.097 2.679 52.024 2.389 52.005 1.999 c
+53.578 1.999 l
+53.578 2.087 l
+53.556 2.469 53.489 2.738 53.372 2.897 c
+53.254 3.061 53.071 3.146 52.828 3.146 c
+f
+Q
+q 1 0 0 1 663.6041 164.1141 cm
+0 0 m
+0 0.147 -0.056 0.268 -0.162 0.367 c
+-0.272 0.463 -0.478 0.58 -0.779 0.72 c
+-1.124 0.866 -1.367 0.988 -1.515 1.087 c
+-1.661 1.194 -1.771 1.311 -1.837 1.44 c
+-1.908 1.565 -1.941 1.723 -1.941 1.911 c
+-1.941 2.234 -1.823 2.502 -1.588 2.719 c
+-1.353 2.932 -1.051 3.042 -0.676 3.042 c
+-0.294 3.042 0.014 2.929 0.249 2.705 c
+0.484 2.476 0.602 2.19 0.602 1.837 c
+-0.044 1.837 l
+-0.044 2.013 -0.104 2.164 -0.221 2.293 c
+-0.339 2.418 -0.493 2.484 -0.676 2.484 c
+-0.875 2.484 -1.025 2.429 -1.132 2.322 c
+-1.242 2.223 -1.294 2.09 -1.294 1.925 c
+-1.294 1.797 -1.257 1.69 -1.176 1.602 c
+-1.099 1.521 -0.908 1.418 -0.603 1.294 c
+-0.125 1.105 0.206 0.918 0.382 0.735 c
+0.559 0.558 0.646 0.33 0.646 0.058 c
+0.646 -0.294 0.522 -0.574 0.279 -0.78 c
+0.044 -0.985 -0.272 -1.088 -0.661 -1.088 c
+-1.084 -1.088 -1.422 -0.971 -1.675 -0.736 c
+-1.933 -0.493 -2.058 -0.188 -2.058 0.176 c
+-1.411 0.176 l
+-1.404 -0.052 -1.334 -0.229 -1.205 -0.353 c
+-1.081 -0.47 -0.897 -0.53 -0.661 -0.53 c
+-0.449 -0.53 -0.287 -0.482 -0.177 -0.383 c
+-0.059 -0.287 0 -0.158 0 0 c
+4.365 0.779 m
+4.365 0.151 4.247 -0.32 4.012 -0.632 c
+3.785 -0.938 3.468 -1.088 3.057 -1.088 c
+2.653 -1.088 2.344 -0.938 2.131 -0.632 c
+2.131 -2.544 l
+1.484 -2.544 l
+1.484 2.969 l
+2.072 2.969 l
+2.117 2.528 l
+2.329 2.869 2.639 3.042 3.042 3.042 c
+3.484 3.042 3.811 2.888 4.027 2.587 c
+4.241 2.281 4.355 1.826 4.365 1.219 c
+h
+3.719 1.161 m
+3.719 1.602 3.649 1.925 3.513 2.131 c
+3.373 2.344 3.152 2.454 2.851 2.454 c
+2.535 2.454 2.296 2.3 2.131 1.999 c
+2.131 -0.074 l
+2.296 -0.379 2.535 -0.53 2.851 -0.53 c
+3.146 -0.53 3.358 -0.427 3.499 -0.221 c
+3.634 -0.008 3.707 0.323 3.719 0.764 c
+h
+6.629 -1.088 m
+6.129 -1.088 5.747 -0.941 5.483 -0.647 c
+5.218 -0.353 5.086 0.08 5.086 0.661 c
+5.086 1.132 l
+5.086 1.726 5.211 2.194 5.468 2.528 c
+5.733 2.869 6.092 3.042 6.556 3.042 c
+7.015 3.042 7.357 2.888 7.584 2.587 c
+7.819 2.293 7.941 1.83 7.952 1.205 c
+7.952 0.779 l
+5.733 0.779 l
+5.733 0.69 l
+5.733 0.257 5.81 -0.056 5.968 -0.25 c
+6.133 -0.437 6.364 -0.53 6.659 -0.53 c
+6.853 -0.53 7.026 -0.497 7.173 -0.427 c
+7.32 -0.35 7.456 -0.232 7.584 -0.074 c
+7.923 -0.485 l
+7.636 -0.89 7.206 -1.088 6.629 -1.088 c
+6.556 2.484 m
+6.28 2.484 6.078 2.389 5.953 2.204 c
+5.824 2.017 5.751 1.726 5.733 1.337 c
+7.305 1.337 l
+7.305 1.425 l
+7.283 1.807 7.217 2.076 7.1 2.234 c
+6.982 2.399 6.798 2.484 6.556 2.484 c
+10.113 -0.53 m
+10.326 -0.53 10.499 -0.468 10.628 -0.339 c
+10.763 -0.202 10.836 -0.011 10.848 0.235 c
+11.465 0.235 l
+11.443 -0.148 11.307 -0.468 11.054 -0.721 c
+10.796 -0.967 10.484 -1.088 10.113 -1.088 c
+9.62 -1.088 9.246 -0.938 8.981 -0.632 c
+8.723 -0.32 8.598 0.147 8.598 0.764 c
+8.598 1.205 l
+8.598 1.801 8.723 2.256 8.981 2.572 c
+9.246 2.884 9.62 3.042 10.113 3.042 c
+10.514 3.042 10.833 2.91 11.068 2.645 c
+11.31 2.389 11.443 2.042 11.465 1.602 c
+10.848 1.602 l
+10.826 1.896 10.753 2.117 10.628 2.263 c
+10.51 2.41 10.337 2.484 10.113 2.484 c
+9.818 2.484 9.602 2.385 9.466 2.19 c
+9.326 2.002 9.253 1.693 9.246 1.263 c
+9.246 0.749 l
+9.246 0.278 9.311 -0.056 9.452 -0.25 c
+9.598 -0.437 9.818 -0.53 10.113 -0.53 c
+12.92 -1.015 -0.646 3.984 re
+12.964 4.012 m
+12.964 3.902 12.935 3.81 12.876 3.733 c
+12.818 3.663 12.722 3.63 12.596 3.63 c
+12.479 3.63 12.384 3.663 12.318 3.733 c
+12.259 3.81 12.23 3.902 12.23 4.012 c
+12.23 4.13 12.259 4.222 12.318 4.292 c
+12.384 4.369 12.479 4.409 12.596 4.409 c
+12.722 4.409 12.818 4.369 12.876 4.292 c
+12.935 4.211 12.964 4.119 12.964 4.012 c
+14.111 -1.015 m
+14.111 2.439 l
+13.596 2.439 l
+13.596 2.969 l
+14.111 2.969 l
+14.111 3.336 l
+14.119 3.766 14.232 4.101 14.449 4.336 c
+14.674 4.579 14.986 4.704 15.389 4.704 c
+15.536 4.704 15.676 4.681 15.816 4.644 c
+15.963 4.604 16.114 4.548 16.272 4.483 c
+16.154 3.91 l
+15.919 4.035 15.676 4.101 15.434 4.101 c
+15.187 4.101 15.015 4.031 14.919 3.895 c
+14.82 3.766 14.772 3.571 14.772 3.307 c
+14.772 2.969 l
+15.419 2.969 l
+15.419 2.439 l
+14.772 2.439 l
+14.772 -1.015 l
+h
+16.581 -1.015 -0.647 3.984 re
+19.05 -1.088 m
+18.55 -1.088 18.167 -0.941 17.903 -0.647 c
+17.639 -0.353 17.506 0.08 17.506 0.661 c
+17.506 1.132 l
+17.506 1.726 17.631 2.194 17.888 2.528 c
+18.153 2.869 18.514 3.042 18.977 3.042 c
+19.436 3.042 19.777 2.888 20.005 2.587 c
+20.24 2.293 20.361 1.83 20.373 1.205 c
+20.373 0.779 l
+18.153 0.779 l
+18.153 0.69 l
+18.153 0.257 18.231 -0.056 18.389 -0.25 c
+18.553 -0.437 18.786 -0.53 19.079 -0.53 c
+19.274 -0.53 19.447 -0.497 19.594 -0.427 c
+19.74 -0.35 19.877 -0.232 20.005 -0.074 c
+20.343 -0.485 l
+20.057 -0.89 19.627 -1.088 19.05 -1.088 c
+18.977 2.484 m
+18.701 2.484 18.499 2.389 18.374 2.204 c
+18.245 2.017 18.171 1.726 18.153 1.337 c
+19.726 1.337 l
+19.726 1.425 l
+19.704 1.807 19.638 2.076 19.52 2.234 c
+19.403 2.399 19.219 2.484 18.977 2.484 c
+21.02 1.161 m
+21.02 1.767 21.13 2.234 21.358 2.557 c
+21.593 2.881 21.92 3.042 22.343 3.042 c
+22.724 3.042 23.022 2.884 23.239 2.572 c
+23.239 4.629 l
+23.885 4.629 l
+23.885 -1.015 l
+23.297 -1.015 l
+23.254 -0.588 l
+23.048 -0.923 22.743 -1.088 22.343 -1.088 c
+21.93 -1.088 21.608 -0.934 21.373 -0.618 c
+21.137 -0.294 21.02 0.161 21.02 0.749 c
+h
+21.666 0.779 m
+21.666 0.338 21.729 0.007 21.857 -0.206 c
+21.993 -0.412 22.214 -0.515 22.518 -0.515 c
+22.842 -0.515 23.081 -0.353 23.239 -0.03 c
+23.239 1.984 l
+23.07 2.296 22.831 2.454 22.518 2.454 c
+22.214 2.454 21.993 2.352 21.857 2.146 c
+21.729 1.94 21.666 1.616 21.666 1.176 c
+h
+29.487 0.779 m
+29.487 0.161 29.372 -0.306 29.148 -0.618 c
+28.931 -0.934 28.608 -1.088 28.178 -1.088 c
+27.756 -1.088 27.443 -0.908 27.237 -0.545 c
+27.208 -1.015 l
+26.605 -1.015 l
+26.605 4.629 l
+27.252 4.629 l
+27.252 2.528 l
+27.465 2.869 27.773 3.042 28.178 3.042 c
+28.608 3.042 28.931 2.884 29.148 2.572 c
+29.372 2.267 29.487 1.801 29.487 1.176 c
+h
+28.839 1.161 m
+28.839 1.631 28.77 1.961 28.633 2.16 c
+28.505 2.355 28.296 2.454 28.001 2.454 c
+27.667 2.454 27.417 2.271 27.252 1.911 c
+27.252 0.029 l
+27.417 -0.335 27.671 -0.515 28.016 -0.515 c
+28.311 -0.515 28.519 -0.412 28.648 -0.206 c
+28.773 0 28.839 0.315 28.839 0.749 c
+h
+31.97 2.352 m
+31.882 2.37 31.783 2.381 31.677 2.381 c
+31.342 2.381 31.106 2.197 30.971 1.837 c
+30.971 -1.015 l
+30.324 -1.015 l
+30.324 2.969 l
+30.956 2.969 l
+30.971 2.557 l
+31.147 2.881 31.39 3.042 31.706 3.042 c
+31.812 3.042 31.9 3.02 31.97 2.983 c
+h
+34.513 -1.015 m
+34.472 -0.927 34.447 -0.78 34.439 -0.574 c
+34.204 -0.919 33.911 -1.088 33.558 -1.088 c
+33.194 -1.088 32.911 -0.992 32.705 -0.794 c
+32.507 -0.588 32.411 -0.302 32.411 0.073 c
+32.411 0.473 32.548 0.793 32.822 1.028 c
+33.095 1.271 33.47 1.396 33.94 1.396 c
+34.425 1.396 l
+34.425 1.822 l
+34.425 2.057 34.37 2.223 34.264 2.322 c
+34.154 2.429 33.992 2.484 33.778 2.484 c
+33.58 2.484 33.418 2.425 33.293 2.308 c
+33.175 2.19 33.117 2.042 33.117 1.866 c
+32.47 1.866 l
+32.47 2.061 32.529 2.252 32.646 2.439 c
+32.772 2.624 32.933 2.77 33.132 2.881 c
+33.337 2.987 33.566 3.042 33.822 3.042 c
+34.223 3.042 34.528 2.94 34.734 2.734 c
+34.947 2.528 35.06 2.234 35.072 1.851 c
+35.072 -0.162 l
+35.072 -0.468 35.108 -0.732 35.189 -0.956 c
+35.189 -1.015 l
+h
+33.646 -0.5 m
+33.811 -0.5 33.962 -0.456 34.102 -0.368 c
+34.248 -0.279 34.355 -0.169 34.425 -0.03 c
+34.425 0.911 l
+34.058 0.911 l
+33.741 0.911 33.499 0.841 33.323 0.706 c
+33.146 0.577 33.057 0.389 33.057 0.147 c
+33.057 -0.081 33.102 -0.246 33.19 -0.353 c
+33.279 -0.452 33.429 -0.5 33.646 -0.5 c
+36.689 2.969 m
+36.703 2.528 l
+36.957 2.869 37.281 3.042 37.674 3.042 c
+38.379 3.042 38.736 2.572 38.746 1.631 c
+38.746 -1.015 l
+38.1 -1.015 l
+38.1 1.602 l
+38.1 1.914 38.044 2.135 37.938 2.263 c
+37.828 2.389 37.674 2.454 37.468 2.454 c
+37.31 2.454 37.163 2.399 37.026 2.293 c
+36.898 2.183 36.795 2.046 36.718 1.881 c
+36.718 -1.015 l
+36.072 -1.015 l
+36.072 2.969 l
+h
+41.098 -0.53 m
+41.312 -0.53 41.485 -0.468 41.613 -0.339 c
+41.749 -0.202 41.822 -0.011 41.834 0.235 c
+42.451 0.235 l
+42.428 -0.148 42.293 -0.468 42.039 -0.721 c
+41.782 -0.967 41.47 -1.088 41.098 -1.088 c
+40.606 -1.088 40.231 -0.938 39.966 -0.632 c
+39.71 -0.32 39.584 0.147 39.584 0.764 c
+39.584 1.205 l
+39.584 1.801 39.71 2.256 39.966 2.572 c
+40.231 2.884 40.606 3.042 41.098 3.042 c
+41.499 3.042 41.819 2.91 42.054 2.645 c
+42.297 2.389 42.428 2.042 42.451 1.602 c
+41.834 1.602 l
+41.811 1.896 41.738 2.117 41.613 2.263 c
+41.495 2.41 41.323 2.484 41.098 2.484 c
+40.805 2.484 40.587 2.385 40.452 2.19 c
+40.312 2.002 40.238 1.693 40.231 1.263 c
+40.231 0.749 l
+40.231 0.278 40.297 -0.056 40.437 -0.25 c
+40.583 -0.437 40.805 -0.53 41.098 -0.53 c
+43.847 2.557 m
+44.101 2.881 44.421 3.042 44.803 3.042 c
+45.508 3.042 45.865 2.572 45.875 1.631 c
+45.875 -1.015 l
+45.229 -1.015 l
+45.229 1.602 l
+45.229 1.914 45.173 2.135 45.067 2.263 c
+44.957 2.389 44.803 2.454 44.597 2.454 c
+44.439 2.454 44.292 2.399 44.155 2.293 c
+44.027 2.183 43.924 2.046 43.847 1.881 c
+43.847 -1.015 l
+43.201 -1.015 l
+43.201 4.629 l
+43.847 4.629 l
+h
+49.256 -1.015 -0.646 3.984 re
+49.3 4.012 m
+49.3 3.902 49.271 3.81 49.212 3.733 c
+49.154 3.663 49.058 3.63 48.932 3.63 c
+48.815 3.63 48.72 3.663 48.654 3.733 c
+48.595 3.81 48.566 3.902 48.566 4.012 c
+48.566 4.13 48.595 4.222 48.654 4.292 c
+48.72 4.369 48.815 4.409 48.932 4.409 c
+49.058 4.409 49.154 4.369 49.212 4.292 c
+49.271 4.211 49.3 4.119 49.3 4.012 c
+50.565 -1.015 m
+50.565 2.439 l
+50.035 2.439 l
+50.035 2.969 l
+50.565 2.969 l
+50.565 3.424 l
+50.565 3.825 50.66 4.137 50.858 4.365 c
+51.064 4.589 51.344 4.704 51.696 4.704 c
+51.833 4.704 51.965 4.681 52.093 4.644 c
+52.064 4.101 l
+51.965 4.119 51.866 4.13 51.77 4.13 c
+51.395 4.13 51.211 3.865 51.211 3.336 c
+51.211 2.969 l
+51.887 2.969 l
+51.887 2.439 l
+51.211 2.439 l
+51.211 -1.015 l
+h
+55.077 -1.015 -0.647 3.984 re
+55.122 4.012 m
+55.122 3.902 55.091 3.81 55.033 3.733 c
+54.974 3.663 54.879 3.63 54.754 3.63 c
+54.636 3.63 54.54 3.663 54.474 3.733 c
+54.416 3.81 54.386 3.902 54.386 4.012 c
+54.386 4.13 54.416 4.222 54.474 4.292 c
+54.54 4.369 54.636 4.409 54.754 4.409 c
+54.879 4.409 54.974 4.369 55.033 4.292 c
+55.091 4.211 55.122 4.119 55.122 4.012 c
+56.944 3.924 m
+56.944 2.969 l
+57.547 2.969 l
+57.547 2.439 l
+56.944 2.439 l
+56.944 -0.03 l
+56.944 -0.188 56.966 -0.306 57.017 -0.383 c
+57.077 -0.464 57.164 -0.5 57.282 -0.5 c
+57.37 -0.5 57.458 -0.485 57.547 -0.456 c
+57.547 -1.015 l
+57.399 -1.062 57.245 -1.088 57.091 -1.088 c
+56.834 -1.088 56.639 -0.996 56.503 -0.809 c
+56.363 -0.626 56.298 -0.364 56.298 -0.03 c
+56.298 2.439 l
+55.695 2.439 l
+55.695 2.969 l
+56.298 2.969 l
+56.298 3.924 l
+h
+59.899 1.161 m
+59.899 1.767 60.009 2.234 60.236 2.557 c
+60.472 2.881 60.799 3.042 61.221 3.042 c
+61.603 3.042 61.902 2.884 62.118 2.572 c
+62.118 4.629 l
+62.765 4.629 l
+62.765 -1.015 l
+62.177 -1.015 l
+62.133 -0.588 l
+61.927 -0.923 61.622 -1.088 61.221 -1.088 c
+60.809 -1.088 60.487 -0.934 60.252 -0.618 c
+60.016 -0.294 59.899 0.161 59.899 0.749 c
+h
+60.545 0.779 m
+60.545 0.338 60.608 0.007 60.736 -0.206 c
+60.872 -0.412 61.093 -0.515 61.397 -0.515 c
+61.721 -0.515 61.96 -0.353 62.118 -0.03 c
+62.118 1.984 l
+61.949 2.296 61.711 2.454 61.397 2.454 c
+61.093 2.454 60.872 2.352 60.736 2.146 c
+60.608 1.94 60.545 1.616 60.545 1.176 c
+h
+63.632 1.161 m
+63.632 1.738 63.768 2.194 64.044 2.528 c
+64.327 2.869 64.697 3.042 65.16 3.042 c
+65.62 3.042 65.987 2.873 66.263 2.543 c
+66.546 2.219 66.693 1.77 66.704 1.205 c
+66.704 0.779 l
+66.704 0.209 66.561 -0.246 66.278 -0.588 c
+66.002 -0.923 65.634 -1.088 65.175 -1.088 c
+64.713 -1.088 64.341 -0.927 64.059 -0.603 c
+63.783 -0.273 63.639 0.168 63.632 0.72 c
+h
+64.279 0.779 m
+64.279 0.374 64.356 0.058 64.514 -0.177 c
+64.68 -0.412 64.9 -0.53 65.175 -0.53 c
+65.742 -0.53 66.035 -0.118 66.058 0.706 c
+66.058 1.161 l
+66.058 1.562 65.973 1.881 65.808 2.117 c
+65.649 2.358 65.433 2.484 65.16 2.484 c
+64.896 2.484 64.68 2.358 64.514 2.117 c
+64.356 1.881 64.279 1.562 64.279 1.161 c
+h
+68.967 -1.088 m
+68.468 -1.088 68.086 -0.941 67.822 -0.647 c
+67.556 -0.353 67.425 0.08 67.425 0.661 c
+67.425 1.132 l
+67.425 1.726 67.55 2.194 67.807 2.528 c
+68.071 2.869 68.431 3.042 68.894 3.042 c
+69.353 3.042 69.696 2.888 69.923 2.587 c
+70.158 2.293 70.28 1.83 70.291 1.205 c
+70.291 0.779 l
+68.071 0.779 l
+68.071 0.69 l
+68.071 0.257 68.148 -0.056 68.306 -0.25 c
+68.472 -0.437 68.703 -0.53 68.998 -0.53 c
+69.192 -0.53 69.364 -0.497 69.511 -0.427 c
+69.659 -0.35 69.794 -0.232 69.923 -0.074 c
+70.261 -0.485 l
+69.975 -0.89 69.545 -1.088 68.967 -1.088 c
+68.894 2.484 m
+68.618 2.484 68.416 2.389 68.292 2.204 c
+68.163 2.017 68.09 1.726 68.071 1.337 c
+69.644 1.337 l
+69.644 1.425 l
+69.622 1.807 69.555 2.076 69.438 2.234 c
+69.32 2.399 69.137 2.484 68.894 2.484 c
+73.01 0 m
+73.01 0.147 72.955 0.268 72.848 0.367 c
+72.738 0.463 72.532 0.58 72.231 0.72 c
+71.886 0.866 71.643 0.988 71.496 1.087 c
+71.349 1.194 71.238 1.311 71.172 1.44 c
+71.103 1.565 71.07 1.723 71.07 1.911 c
+71.07 2.234 71.188 2.502 71.423 2.719 c
+71.658 2.932 71.959 3.042 72.333 3.042 c
+72.716 3.042 73.025 2.929 73.26 2.705 c
+73.495 2.476 73.613 2.19 73.613 1.837 c
+72.966 1.837 l
+72.966 2.013 72.907 2.164 72.79 2.293 c
+72.672 2.418 72.518 2.484 72.333 2.484 c
+72.136 2.484 71.984 2.429 71.878 2.322 c
+71.768 2.223 71.716 2.09 71.716 1.925 c
+71.716 1.797 71.753 1.69 71.834 1.602 c
+71.911 1.521 72.102 1.418 72.408 1.294 c
+72.885 1.105 73.216 0.918 73.392 0.735 c
+73.569 0.558 73.657 0.33 73.657 0.058 c
+73.657 -0.294 73.532 -0.574 73.289 -0.78 c
+73.054 -0.985 72.738 -1.088 72.348 -1.088 c
+71.926 -1.088 71.588 -0.971 71.334 -0.736 c
+71.078 -0.493 70.952 -0.188 70.952 0.176 c
+71.599 0.176 l
+71.606 -0.052 71.676 -0.229 71.805 -0.353 c
+71.93 -0.47 72.113 -0.53 72.348 -0.53 c
+72.562 -0.53 72.724 -0.482 72.834 -0.383 c
+72.951 -0.287 73.01 -0.158 73.01 0 c
+76.832 2.969 m
+76.846 2.528 l
+77.1 2.869 77.424 3.042 77.817 3.042 c
+78.523 3.042 78.879 2.572 78.889 1.631 c
+78.889 -1.015 l
+78.243 -1.015 l
+78.243 1.602 l
+78.243 1.914 78.188 2.135 78.081 2.263 c
+77.971 2.389 77.817 2.454 77.611 2.454 c
+77.453 2.454 77.306 2.399 77.17 2.293 c
+77.041 2.183 76.938 2.046 76.861 1.881 c
+76.861 -1.015 l
+76.214 -1.015 l
+76.214 2.969 l
+h
+79.728 1.161 m
+79.728 1.738 79.863 2.194 80.139 2.528 c
+80.422 2.869 80.794 3.042 81.256 3.042 c
+81.715 3.042 82.083 2.873 82.359 2.543 c
+82.642 2.219 82.789 1.77 82.799 1.205 c
+82.799 0.779 l
+82.799 0.209 82.656 -0.246 82.373 -0.588 c
+82.097 -0.923 81.73 -1.088 81.27 -1.088 c
+80.808 -1.088 80.437 -0.927 80.154 -0.603 c
+79.878 -0.273 79.735 0.168 79.728 0.72 c
+h
+80.374 0.779 m
+80.374 0.374 80.451 0.058 80.609 -0.177 c
+80.775 -0.412 80.996 -0.53 81.27 -0.53 c
+81.837 -0.53 82.131 -0.118 82.153 0.706 c
+82.153 1.161 l
+82.153 1.562 82.068 1.881 81.903 2.117 c
+81.745 2.358 81.528 2.484 81.256 2.484 c
+80.992 2.484 80.775 2.358 80.609 2.117 c
+80.451 1.881 80.374 1.562 80.374 1.161 c
+h
+84.49 3.924 m
+84.49 2.969 l
+85.093 2.969 l
+85.093 2.439 l
+84.49 2.439 l
+84.49 -0.03 l
+84.49 -0.188 84.512 -0.306 84.563 -0.383 c
+84.622 -0.464 84.711 -0.5 84.828 -0.5 c
+84.916 -0.5 85.004 -0.485 85.093 -0.456 c
+85.093 -1.015 l
+84.946 -1.062 84.792 -1.088 84.637 -1.088 c
+84.38 -1.088 84.185 -0.996 84.049 -0.809 c
+83.909 -0.626 83.843 -0.364 83.843 -0.03 c
+83.843 2.439 l
+83.24 2.439 l
+83.24 2.969 l
+83.843 2.969 l
+83.843 3.924 l
+h
+89.002 -1.088 m
+88.503 -1.088 88.121 -0.941 87.856 -0.647 c
+87.591 -0.353 87.46 0.08 87.46 0.661 c
+87.46 1.132 l
+87.46 1.726 87.584 2.194 87.841 2.528 c
+88.106 2.869 88.466 3.042 88.929 3.042 c
+89.388 3.042 89.731 2.888 89.958 2.587 c
+90.193 2.293 90.315 1.83 90.325 1.205 c
+90.325 0.779 l
+88.106 0.779 l
+88.106 0.69 l
+88.106 0.257 88.183 -0.056 88.341 -0.25 c
+88.507 -0.437 88.738 -0.53 89.031 -0.53 c
+89.227 -0.53 89.399 -0.497 89.546 -0.427 c
+89.694 -0.35 89.829 -0.232 89.958 -0.074 c
+90.296 -0.485 l
+90.01 -0.89 89.579 -1.088 89.002 -1.088 c
+88.929 2.484 m
+88.653 2.484 88.451 2.389 88.326 2.204 c
+88.198 2.017 88.125 1.726 88.106 1.337 c
+89.679 1.337 l
+89.679 1.425 l
+89.657 1.807 89.59 2.076 89.473 2.234 c
+89.355 2.399 89.172 2.484 88.929 2.484 c
+92.251 1.514 m
+92.942 2.969 l
+93.692 2.969 l
+92.604 0.999 l
+93.721 -1.015 l
+92.971 -1.015 l
+92.266 0.47 l
+91.56 -1.015 l
+90.81 -1.015 l
+91.913 0.999 l
+90.84 2.969 l
+91.589 2.969 l
+h
+95.117 -1.015 -0.646 3.984 re
+95.161 4.012 m
+95.161 3.902 95.132 3.81 95.073 3.733 c
+95.015 3.663 94.919 3.63 94.794 3.63 c
+94.676 3.63 94.581 3.663 94.515 3.733 c
+94.456 3.81 94.427 3.902 94.427 4.012 c
+94.427 4.13 94.456 4.222 94.515 4.292 c
+94.581 4.369 94.676 4.409 94.794 4.409 c
+94.919 4.409 95.015 4.369 95.073 4.292 c
+95.132 4.211 95.161 4.119 95.161 4.012 c
+98.072 0 m
+98.072 0.147 98.017 0.268 97.91 0.367 c
+97.8 0.463 97.594 0.58 97.293 0.72 c
+96.948 0.866 96.705 0.988 96.557 1.087 c
+96.411 1.194 96.301 1.311 96.235 1.44 c
+96.164 1.565 96.131 1.723 96.131 1.911 c
+96.131 2.234 96.249 2.502 96.484 2.719 c
+96.719 2.932 97.021 3.042 97.396 3.042 c
+97.778 3.042 98.086 2.929 98.321 2.705 c
+98.557 2.476 98.674 2.19 98.674 1.837 c
+98.028 1.837 l
+98.028 2.013 97.969 2.164 97.851 2.293 c
+97.733 2.418 97.579 2.484 97.396 2.484 c
+97.197 2.484 97.047 2.429 96.94 2.322 c
+96.83 2.223 96.779 2.09 96.779 1.925 c
+96.779 1.797 96.815 1.69 96.896 1.602 c
+96.973 1.521 97.164 1.418 97.469 1.294 c
+97.947 1.105 98.278 0.918 98.454 0.735 c
+98.631 0.558 98.718 0.33 98.718 0.058 c
+98.718 -0.294 98.594 -0.574 98.351 -0.78 c
+98.116 -0.985 97.8 -1.088 97.411 -1.088 c
+96.988 -1.088 96.65 -0.971 96.397 -0.736 c
+96.139 -0.493 96.014 -0.188 96.014 0.176 c
+96.661 0.176 l
+96.668 -0.052 96.738 -0.229 96.867 -0.353 c
+96.991 -0.47 97.176 -0.53 97.411 -0.53 c
+97.623 -0.53 97.785 -0.482 97.895 -0.383 c
+98.013 -0.287 98.072 -0.158 98.072 0 c
+100.409 3.924 m
+100.409 2.969 l
+101.012 2.969 l
+101.012 2.439 l
+100.409 2.439 l
+100.409 -0.03 l
+100.409 -0.188 100.431 -0.306 100.482 -0.383 c
+100.542 -0.464 100.63 -0.5 100.747 -0.5 c
+100.835 -0.5 100.923 -0.485 101.012 -0.456 c
+101.012 -1.015 l
+100.865 -1.062 100.711 -1.088 100.556 -1.088 c
+100.299 -1.088 100.104 -0.996 99.968 -0.809 c
+99.828 -0.626 99.763 -0.364 99.763 -0.03 c
+99.763 2.439 l
+99.159 2.439 l
+99.159 2.969 l
+99.763 2.969 l
+99.763 3.924 l
+h
+101.82 -0.662 m
+101.82 -0.545 101.853 -0.449 101.923 -0.368 c
+101.989 -0.291 102.092 -0.25 102.232 -0.25 c
+102.379 -0.25 102.485 -0.291 102.555 -0.368 c
+102.633 -0.449 102.672 -0.545 102.672 -0.662 c
+102.672 -0.772 102.633 -0.864 102.555 -0.941 c
+102.485 -1.019 102.379 -1.058 102.232 -1.058 c
+102.092 -1.058 101.989 -1.019 101.923 -0.941 c
+101.853 -0.864 101.82 -0.772 101.82 -0.662 c
+f
+Q
+0.113 0.082 0.09 0 k
+535.667 157.87 238.665 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 540.8555 151.0312 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.088 -0.5 c
+-0.147 -0.646 -0.242 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.146 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.263 l
+-2.142 -1.257 -2.358 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.772 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.141 1.279 -3.218 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.985 c
+-3.322 2.18 -3.289 2.344 -3.218 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.003 -2.469 3.043 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.558 l
+-1.543 3.558 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.735 -0.349 2.62 -0.279 2.484 c
+-0.201 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.459 -1.543 2.5 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.36 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.206 c
+-0.756 1.147 -0.595 1.066 -0.455 0.971 c
+-0.319 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.455 c
+-2.26 2.425 -2.318 2.385 -2.366 2.338 c
+-2.406 2.297 -2.436 2.249 -2.454 2.19 c
+-2.476 2.132 -2.484 2.066 -2.484 1.999 c
+-2.484 1.912 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.2 1.559 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.441 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.302 -0.977 0.357 -1.043 0.397 c
+-1.102 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.44 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.014 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.52 -2.484 5.403 -2.396 c
+5.285 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.616 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.146 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.214 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.411 4.888 -0.205 c
+4.836 0.008 4.815 0.243 4.815 0.5 c
+4.815 0.772 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.632 5.137 1.779 c
+5.245 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.264 6.093 2.264 c
+6.189 2.264 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.918 7.107 1.97 c
+7.115 2.029 7.122 2.076 7.122 2.117 c
+7.13 2.165 7.14 2.198 7.151 2.22 c
+8.004 2.22 l
+7.992 2.139 7.982 2.029 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.872 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.403 7.258 -2.499 7.063 -2.557 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.206 6.924 1.324 6.857 1.411 c
+6.799 1.5 6.729 1.559 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.226 1.621 6.137 1.573 c
+6.056 1.532 5.991 1.463 5.931 1.367 c
+5.88 1.279 5.835 1.162 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.558 c
+6.725 -0.521 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.302 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.263 l
+8.86 -1.263 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.22 l
+13.644 2.22 l
+13.924 3.117 l
+14.498 3.117 l
+14.498 2.22 l
+15.732 2.22 l
+15.732 1.602 l
+14.498 1.602 l
+14.498 -0.103 l
+14.498 -0.323 l
+14.504 -0.393 14.527 -0.455 14.556 -0.515 c
+14.593 -0.565 14.648 -0.61 14.718 -0.646 c
+14.795 -0.675 14.909 -0.691 15.056 -0.691 c
+15.192 -0.691 15.327 -0.687 15.468 -0.675 c
+15.603 -0.658 15.736 -0.632 15.865 -0.602 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.23 15.629 -1.249 c
+15.549 -1.261 15.471 -1.267 15.394 -1.278 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.042 -1.301 14.942 -1.308 14.836 -1.308 c
+14.648 -1.308 14.486 -1.294 14.35 -1.263 c
+14.222 -1.227 14.107 -1.183 14.012 -1.132 c
+13.924 -1.084 13.85 -1.025 13.792 -0.955 c
+13.733 -0.878 13.689 -0.801 13.66 -0.72 c
+13.63 -0.632 13.608 -0.544 13.6 -0.455 c
+13.59 -0.36 13.586 -0.264 13.586 -0.176 c
+h
+22.281 -1.263 m
+22.281 0.853 l
+22.281 1.018 22.273 1.154 22.265 1.264 c
+22.255 1.371 22.236 1.455 22.207 1.515 c
+22.185 1.58 22.155 1.632 22.119 1.661 c
+22.09 1.691 22.049 1.706 22.001 1.706 c
+21.943 1.706 21.887 1.676 21.839 1.617 c
+21.799 1.565 21.766 1.492 21.737 1.397 c
+21.708 1.309 21.681 1.195 21.663 1.058 c
+21.652 0.919 21.648 0.769 21.648 0.603 c
+21.648 -1.263 l
+20.898 -1.263 l
+20.898 1.47 l
+20.898 1.706 l
+20.898 1.926 l
+20.898 2.003 20.891 2.066 20.884 2.117 c
+20.884 2.22 l
+21.56 2.22 l
+21.56 2.132 l
+21.56 1.985 l
+21.567 1.926 21.575 1.867 21.575 1.808 c
+21.575 1.646 l
+21.59 1.646 l
+21.608 1.735 21.637 1.812 21.677 1.881 c
+21.714 1.959 21.758 2.029 21.81 2.088 c
+21.868 2.147 21.935 2.19 22.016 2.22 c
+22.093 2.257 22.182 2.278 22.281 2.278 c
+22.464 2.278 22.604 2.224 22.692 2.117 c
+22.787 2.018 22.857 1.86 22.898 1.646 c
+22.913 1.646 l
+22.949 1.742 22.99 1.831 23.03 1.912 c
+23.078 1.989 23.133 2.051 23.192 2.103 c
+23.25 2.161 23.317 2.205 23.397 2.234 c
+23.474 2.264 23.563 2.278 23.662 2.278 c
+23.798 2.278 23.912 2.253 24 2.205 c
+24.089 2.153 24.154 2.08 24.206 1.985 c
+24.264 1.885 24.301 1.756 24.324 1.602 c
+24.353 1.455 24.368 1.272 24.368 1.058 c
+24.368 -1.263 l
+23.647 -1.263 l
+23.647 0.853 l
+23.647 1.018 23.64 1.154 23.632 1.264 c
+23.622 1.371 23.603 1.455 23.574 1.515 c
+23.552 1.58 23.522 1.632 23.486 1.661 c
+23.456 1.691 23.416 1.706 23.368 1.706 c
+23.25 1.706 23.155 1.617 23.089 1.441 c
+23.03 1.272 23.001 1.014 23.001 0.661 c
+23.001 -1.263 l
+h
+26.738 -1.323 m
+26.481 -1.323 26.253 -1.286 26.047 -1.22 c
+25.841 -1.143 25.665 -1.028 25.518 -0.881 c
+25.371 -0.727 25.253 -0.536 25.165 -0.309 c
+25.084 -0.085 25.047 0.181 25.047 0.485 c
+25.047 0.816 25.091 1.095 25.18 1.324 c
+25.276 1.559 25.404 1.742 25.562 1.881 c
+25.727 2.018 25.915 2.117 26.121 2.176 c
+26.327 2.242 26.535 2.278 26.753 2.278 c
+27.025 2.278 27.26 2.227 27.458 2.132 c
+27.664 2.043 27.829 1.912 27.958 1.735 c
+28.094 1.565 28.193 1.36 28.252 1.118 c
+28.318 0.882 28.355 0.618 28.355 0.324 c
+28.355 0.309 l
+25.988 0.309 l
+25.988 0.162 26.003 0.023 26.032 -0.103 c
+26.069 -0.231 26.124 -0.345 26.194 -0.44 c
+26.26 -0.529 26.344 -0.598 26.444 -0.646 c
+26.539 -0.698 26.653 -0.72 26.782 -0.72 c
+26.936 -0.72 27.076 -0.687 27.194 -0.617 c
+27.318 -0.551 27.407 -0.448 27.458 -0.309 c
+28.297 -0.382 l
+28.266 -0.481 28.212 -0.588 28.135 -0.706 c
+28.054 -0.816 27.95 -0.918 27.826 -1.014 c
+27.708 -1.103 27.553 -1.176 27.37 -1.234 c
+27.194 -1.294 26.98 -1.323 26.738 -1.323 c
+26.738 1.706 m
+26.65 1.706 26.562 1.691 26.473 1.661 c
+26.385 1.632 26.304 1.58 26.238 1.515 c
+26.169 1.444 26.109 1.357 26.061 1.249 c
+26.022 1.139 26.003 1.014 26.003 0.867 c
+27.472 0.867 l
+27.472 1.004 27.447 1.125 27.399 1.235 c
+27.359 1.341 27.304 1.43 27.237 1.5 c
+27.179 1.565 27.106 1.617 27.017 1.646 c
+26.929 1.683 26.834 1.706 26.738 1.706 c
+32.254 1.47 m
+32.154 1.478 32.052 1.488 31.945 1.5 c
+31.835 1.518 31.713 1.529 31.578 1.529 c
+31.401 1.529 31.243 1.488 31.107 1.411 c
+30.967 1.341 30.85 1.243 30.755 1.118 c
+30.666 0.989 30.597 0.842 30.549 0.676 c
+30.508 0.507 30.49 0.331 30.49 0.148 c
+30.49 -1.263 l
+29.593 -1.263 l
+29.593 0.985 l
+29.593 1.11 29.582 1.235 29.564 1.353 c
+29.552 1.478 29.538 1.596 29.519 1.706 c
+29.509 1.823 29.494 1.918 29.475 1.999 c
+29.454 2.088 29.435 2.161 29.417 2.22 c
+30.298 2.22 l
+30.306 2.168 30.317 2.117 30.328 2.058 c
+30.346 1.999 30.361 1.933 30.373 1.867 c
+30.391 1.808 30.406 1.742 30.416 1.676 c
+30.423 1.606 30.435 1.544 30.446 1.484 c
+30.46 1.484 l
+30.497 1.602 30.549 1.709 30.608 1.808 c
+30.674 1.904 30.755 1.989 30.843 2.058 c
+30.931 2.124 31.034 2.18 31.152 2.22 c
+31.276 2.257 31.424 2.278 31.592 2.278 c
+31.717 2.278 31.835 2.271 31.945 2.264 c
+32.062 2.253 32.166 2.238 32.254 2.22 c
+h
+34.834 -2.66 m
+34.616 -2.66 34.425 -2.635 34.26 -2.587 c
+34.091 -2.547 33.951 -2.484 33.834 -2.396 c
+33.716 -2.315 33.617 -2.219 33.54 -2.102 c
+33.471 -1.984 33.423 -1.855 33.392 -1.72 c
+34.29 -1.616 l
+34.327 -1.753 34.396 -1.859 34.495 -1.94 c
+34.591 -2.028 34.716 -2.072 34.863 -2.072 c
+34.951 -2.072 35.032 -2.057 35.113 -2.028 c
+35.19 -1.999 35.26 -1.944 35.318 -1.866 c
+35.377 -1.797 35.422 -1.705 35.451 -1.587 c
+35.487 -1.469 35.509 -1.323 35.509 -1.146 c
+35.509 -0.955 l
+35.509 -0.889 35.513 -0.831 35.524 -0.779 c
+35.524 -0.588 l
+35.509 -0.588 l
+35.41 -0.816 35.267 -0.977 35.083 -1.072 c
+34.896 -1.172 34.69 -1.22 34.466 -1.22 c
+34.26 -1.22 34.076 -1.183 33.922 -1.103 c
+33.775 -1.014 33.646 -0.897 33.54 -0.75 c
+33.44 -0.595 33.367 -0.411 33.319 -0.205 c
+33.268 0.008 33.246 0.243 33.246 0.5 c
+33.246 0.772 33.268 1.018 33.319 1.235 c
+33.378 1.448 33.459 1.632 33.569 1.779 c
+33.676 1.933 33.808 2.051 33.966 2.132 c
+34.121 2.22 34.308 2.264 34.525 2.264 c
+34.62 2.264 34.72 2.253 34.819 2.234 c
+34.915 2.213 35.002 2.18 35.083 2.132 c
+35.171 2.08 35.249 2.018 35.318 1.941 c
+35.395 1.86 35.458 1.768 35.509 1.661 c
+35.524 1.661 l
+35.524 1.808 l
+35.532 1.867 35.539 1.918 35.539 1.97 c
+35.547 2.029 35.553 2.076 35.553 2.117 c
+35.561 2.165 35.572 2.198 35.583 2.22 c
+36.436 2.22 l
+36.424 2.139 36.413 2.029 36.407 1.881 c
+36.407 1.411 l
+36.407 -1.161 l
+36.407 -1.415 36.37 -1.635 36.303 -1.822 c
+36.234 -2.007 36.131 -2.161 35.995 -2.278 c
+35.855 -2.403 35.69 -2.499 35.495 -2.557 c
+35.297 -2.624 35.076 -2.66 34.834 -2.66 c
+35.524 0.53 m
+35.524 0.742 35.499 0.919 35.451 1.058 c
+35.41 1.206 35.355 1.324 35.289 1.411 c
+35.231 1.5 35.16 1.559 35.083 1.588 c
+35.002 1.625 34.925 1.646 34.848 1.646 c
+34.749 1.646 34.657 1.621 34.568 1.573 c
+34.488 1.532 34.422 1.463 34.363 1.367 c
+34.312 1.279 34.267 1.162 34.231 1.014 c
+34.202 0.875 34.186 0.706 34.186 0.5 c
+34.186 0.125 34.246 -0.154 34.363 -0.338 c
+34.481 -0.515 34.643 -0.602 34.848 -0.602 c
+34.915 -0.602 34.988 -0.588 35.069 -0.558 c
+35.156 -0.521 35.231 -0.463 35.289 -0.382 c
+35.355 -0.294 35.41 -0.176 35.451 -0.029 c
+35.499 0.118 35.524 0.302 35.524 0.53 c
+38.923 -1.323 m
+38.666 -1.323 38.439 -1.286 38.233 -1.22 c
+38.027 -1.143 37.851 -1.028 37.704 -0.881 c
+37.556 -0.727 37.439 -0.536 37.35 -0.309 c
+37.27 -0.085 37.234 0.181 37.234 0.485 c
+37.234 0.816 37.277 1.095 37.365 1.324 c
+37.461 1.559 37.589 1.742 37.747 1.881 c
+37.913 2.018 38.1 2.117 38.306 2.176 c
+38.512 2.242 38.722 2.278 38.938 2.278 c
+39.21 2.278 39.445 2.227 39.644 2.132 c
+39.85 2.043 40.015 1.912 40.143 1.735 c
+40.28 1.565 40.378 1.36 40.438 1.118 c
+40.504 0.882 40.54 0.618 40.54 0.324 c
+40.54 0.309 l
+38.174 0.309 l
+38.174 0.162 38.188 0.023 38.218 -0.103 c
+38.254 -0.231 38.31 -0.345 38.379 -0.44 c
+38.446 -0.529 38.53 -0.598 38.63 -0.646 c
+38.725 -0.698 38.839 -0.72 38.967 -0.72 c
+39.122 -0.72 39.262 -0.687 39.379 -0.617 c
+39.504 -0.551 39.592 -0.448 39.644 -0.309 c
+40.482 -0.382 l
+40.452 -0.481 40.397 -0.588 40.32 -0.706 c
+40.239 -0.816 40.136 -0.918 40.012 -1.014 c
+39.894 -1.103 39.74 -1.176 39.555 -1.234 c
+39.379 -1.294 39.166 -1.323 38.923 -1.323 c
+38.923 1.706 m
+38.836 1.706 38.747 1.691 38.659 1.661 c
+38.57 1.632 38.489 1.58 38.424 1.515 c
+38.354 1.444 38.295 1.357 38.248 1.249 c
+38.207 1.139 38.188 1.014 38.188 0.867 c
+39.659 0.867 l
+39.659 1.004 39.632 1.125 39.585 1.235 c
+39.545 1.341 39.489 1.43 39.424 1.5 c
+39.364 1.565 39.291 1.617 39.203 1.646 c
+39.115 1.683 39.019 1.706 38.923 1.706 c
+46.236 -2.631 m
+46.236 3.514 l
+48.162 3.514 l
+48.162 2.896 l
+47.089 2.896 l
+47.089 -2.013 l
+48.162 -2.013 l
+48.162 -2.631 l
+h
+51.193 1.602 m
+51.193 -1.263 l
+50.297 -1.263 l
+50.297 1.602 l
+49.473 1.602 l
+49.473 2.22 l
+50.297 2.22 l
+50.297 2.484 l
+50.297 2.61 50.312 2.741 50.341 2.881 c
+50.378 3.017 50.447 3.135 50.547 3.234 c
+50.653 3.341 50.796 3.429 50.973 3.499 c
+51.149 3.564 51.374 3.601 51.649 3.601 c
+51.862 3.601 52.06 3.591 52.237 3.572 c
+52.413 3.55 52.564 3.532 52.693 3.514 c
+52.693 2.926 l
+52.564 2.944 52.421 2.959 52.267 2.97 c
+52.109 2.977 51.958 2.984 51.811 2.984 c
+51.682 2.984 51.58 2.97 51.502 2.94 c
+51.422 2.911 51.359 2.87 51.311 2.822 c
+51.26 2.771 51.226 2.708 51.208 2.631 c
+51.197 2.562 51.193 2.484 51.193 2.396 c
+51.193 2.22 l
+52.619 2.22 l
+52.619 1.602 l
+h
+56.625 1.47 m
+56.525 1.478 56.423 1.488 56.316 1.5 c
+56.205 1.518 56.085 1.529 55.949 1.529 c
+55.773 1.529 55.615 1.488 55.478 1.411 c
+55.339 1.341 55.221 1.243 55.125 1.118 c
+55.037 0.989 54.967 0.842 54.919 0.676 c
+54.879 0.507 54.861 0.331 54.861 0.148 c
+54.861 -1.263 l
+53.965 -1.263 l
+53.965 0.985 l
+53.965 1.11 53.953 1.235 53.934 1.353 c
+53.924 1.478 53.909 1.596 53.891 1.706 c
+53.88 1.823 53.865 1.918 53.847 1.999 c
+53.824 2.088 53.807 2.161 53.788 2.22 c
+54.67 2.22 l
+54.677 2.168 54.688 2.117 54.699 2.058 c
+54.717 1.999 54.732 1.933 54.744 1.867 c
+54.761 1.808 54.776 1.742 54.788 1.676 c
+54.794 1.606 54.806 1.544 54.817 1.484 c
+54.832 1.484 l
+54.869 1.602 54.919 1.709 54.979 1.808 c
+55.044 1.904 55.125 1.989 55.214 2.058 c
+55.302 2.124 55.405 2.18 55.522 2.22 c
+55.648 2.257 55.794 2.278 55.964 2.278 c
+56.088 2.278 56.205 2.271 56.316 2.264 c
+56.434 2.253 56.536 2.238 56.625 2.22 c
+h
+60.876 0.485 m
+60.876 0.21 60.839 -0.04 60.774 -0.264 c
+60.704 -0.481 60.601 -0.669 60.465 -0.823 c
+60.325 -0.981 60.149 -1.103 59.935 -1.19 c
+59.719 -1.278 59.465 -1.323 59.172 -1.323 c
+58.896 -1.323 58.649 -1.278 58.437 -1.19 c
+58.231 -1.103 58.058 -0.981 57.922 -0.823 c
+57.782 -0.669 57.68 -0.481 57.614 -0.264 c
+57.543 -0.04 57.51 0.21 57.51 0.485 c
+57.51 0.738 57.539 0.974 57.599 1.191 c
+57.664 1.415 57.768 1.606 57.907 1.764 c
+58.044 1.929 58.219 2.058 58.437 2.147 c
+58.649 2.234 58.907 2.278 59.201 2.278 c
+59.513 2.278 59.774 2.234 59.98 2.147 c
+60.193 2.058 60.365 1.929 60.494 1.764 c
+60.631 1.606 60.729 1.415 60.789 1.191 c
+60.847 0.974 60.876 0.738 60.876 0.485 c
+59.921 0.485 m
+59.921 0.691 59.906 0.867 59.877 1.014 c
+59.855 1.162 59.818 1.283 59.76 1.382 c
+59.7 1.478 59.627 1.548 59.538 1.588 c
+59.451 1.636 59.341 1.661 59.216 1.661 c
+58.951 1.661 58.76 1.562 58.642 1.367 c
+58.524 1.18 58.466 0.886 58.466 0.485 c
+58.466 0.063 58.524 -0.243 58.642 -0.426 c
+58.76 -0.613 58.936 -0.706 59.172 -0.706 c
+59.297 -0.706 59.411 -0.687 59.509 -0.646 c
+59.605 -0.598 59.686 -0.525 59.745 -0.426 c
+59.811 -0.33 59.855 -0.205 59.877 -0.058 c
+59.906 0.088 59.921 0.268 59.921 0.485 c
+62.894 -1.263 m
+62.894 0.853 l
+62.894 1.018 62.887 1.154 62.879 1.264 c
+62.869 1.371 62.85 1.455 62.821 1.515 c
+62.798 1.58 62.769 1.632 62.732 1.661 c
+62.703 1.691 62.663 1.706 62.615 1.706 c
+62.555 1.706 62.501 1.676 62.453 1.617 c
+62.412 1.565 62.38 1.492 62.35 1.397 c
+62.32 1.309 62.295 1.195 62.277 1.058 c
+62.266 0.919 62.262 0.769 62.262 0.603 c
+62.262 -1.263 l
+61.512 -1.263 l
+61.512 1.47 l
+61.512 1.706 l
+61.512 1.926 l
+61.512 2.003 61.505 2.066 61.497 2.117 c
+61.497 2.22 l
+62.173 2.22 l
+62.173 2.132 l
+62.173 1.985 l
+62.181 1.926 62.189 1.867 62.189 1.808 c
+62.189 1.646 l
+62.203 1.646 l
+62.221 1.735 62.251 1.812 62.291 1.881 c
+62.328 1.959 62.372 2.029 62.424 2.088 c
+62.482 2.147 62.549 2.19 62.63 2.22 c
+62.707 2.257 62.794 2.278 62.894 2.278 c
+63.078 2.278 63.218 2.224 63.305 2.117 c
+63.401 2.018 63.471 1.86 63.511 1.646 c
+63.526 1.646 l
+63.563 1.742 63.603 1.831 63.644 1.912 c
+63.691 1.989 63.746 2.051 63.806 2.103 c
+63.864 2.161 63.93 2.205 64.011 2.234 c
+64.088 2.264 64.176 2.278 64.276 2.278 c
+64.411 2.278 64.525 2.253 64.614 2.205 c
+64.702 2.153 64.768 2.08 64.82 1.985 c
+64.878 1.885 64.915 1.756 64.937 1.602 c
+64.967 1.455 64.982 1.272 64.982 1.058 c
+64.982 -1.263 l
+64.261 -1.263 l
+64.261 0.853 l
+64.261 1.018 64.253 1.154 64.246 1.264 c
+64.236 1.371 64.217 1.455 64.188 1.515 c
+64.165 1.58 64.136 1.632 64.099 1.661 c
+64.07 1.691 64.03 1.706 63.982 1.706 c
+63.864 1.706 63.769 1.617 63.702 1.441 c
+63.644 1.272 63.614 1.014 63.614 0.661 c
+63.614 -1.263 l
+h
+72.044 -1.263 m
+72.044 0.721 l
+72.044 1.022 72 1.243 71.912 1.382 c
+71.831 1.529 71.695 1.602 71.5 1.602 c
+71.39 1.602 71.287 1.577 71.191 1.529 c
+71.103 1.478 71.022 1.411 70.956 1.324 c
+70.898 1.235 70.846 1.125 70.81 1 c
+70.78 0.882 70.765 0.75 70.765 0.603 c
+70.765 -1.263 l
+69.854 -1.263 l
+69.854 1.441 l
+69.854 1.661 l
+69.854 1.75 69.846 1.827 69.84 1.897 c
+69.84 2.088 l
+69.84 2.22 l
+70.692 2.22 l
+70.699 2.19 70.707 2.147 70.707 2.088 c
+70.707 1.897 l
+70.714 1.827 70.721 1.756 70.721 1.691 c
+70.729 1.621 70.736 1.565 70.736 1.529 c
+70.75 1.529 l
+70.868 1.794 71.019 1.985 71.206 2.103 c
+71.39 2.22 71.61 2.278 71.868 2.278 c
+72.051 2.278 72.213 2.249 72.353 2.19 c
+72.489 2.132 72.602 2.043 72.691 1.926 c
+72.779 1.808 72.841 1.665 72.882 1.5 c
+72.93 1.341 72.955 1.154 72.955 0.941 c
+72.955 -1.263 l
+h
+74.873 -1.323 m
+74.705 -1.323 74.554 -1.301 74.418 -1.263 c
+74.289 -1.216 74.175 -1.146 74.079 -1.058 c
+73.992 -0.97 73.922 -0.864 73.874 -0.735 c
+73.823 -0.598 73.801 -0.448 73.801 -0.279 c
+73.801 -0.073 73.834 0.096 73.904 0.235 c
+73.969 0.383 74.065 0.493 74.183 0.574 c
+74.308 0.661 74.451 0.724 74.609 0.765 c
+74.775 0.802 74.951 0.827 75.138 0.838 c
+75.858 0.853 l
+75.858 1.029 l
+75.858 1.147 75.847 1.249 75.829 1.338 c
+75.807 1.426 75.774 1.492 75.726 1.544 c
+75.685 1.602 75.638 1.639 75.579 1.661 c
+75.521 1.679 75.454 1.691 75.388 1.691 c
+75.318 1.691 75.255 1.679 75.197 1.661 c
+75.145 1.65 75.098 1.625 75.05 1.588 c
+75.01 1.559 74.977 1.507 74.947 1.441 c
+74.925 1.382 74.91 1.301 74.903 1.206 c
+73.962 1.249 l
+73.992 1.397 74.036 1.532 74.094 1.661 c
+74.16 1.786 74.256 1.897 74.374 1.985 c
+74.492 2.08 74.631 2.153 74.8 2.205 c
+74.977 2.253 75.182 2.278 75.417 2.278 c
+75.858 2.278 76.19 2.168 76.417 1.955 c
+76.652 1.75 76.77 1.441 76.77 1.029 c
+76.77 -0.235 l
+76.77 -0.455 l
+76.778 -0.515 76.792 -0.569 76.814 -0.617 c
+76.832 -0.658 76.861 -0.691 76.902 -0.72 c
+76.939 -0.742 76.99 -0.75 77.049 -0.75 c
+77.115 -0.75 77.185 -0.746 77.254 -0.735 c
+77.254 -1.22 l
+77.196 -1.23 77.141 -1.242 77.094 -1.249 c
+77.053 -1.261 77.013 -1.267 76.976 -1.278 c
+76.936 -1.286 76.891 -1.294 76.843 -1.294 c
+76.792 -1.301 76.733 -1.308 76.667 -1.308 c
+76.439 -1.308 76.274 -1.257 76.167 -1.146 c
+76.057 -1.028 75.995 -0.864 75.976 -0.646 c
+75.961 -0.646 l
+75.891 -0.756 75.822 -0.852 75.756 -0.941 c
+75.685 -1.022 75.608 -1.087 75.521 -1.146 c
+75.432 -1.205 75.333 -1.249 75.226 -1.278 c
+75.127 -1.308 75.01 -1.323 74.873 -1.323 c
+75.858 0.353 m
+75.432 0.339 l
+75.333 0.339 75.241 0.331 75.153 0.324 c
+75.072 0.312 75.006 0.287 74.947 0.25 c
+74.889 0.21 74.837 0.151 74.8 0.073 c
+74.76 0.004 74.742 -0.087 74.742 -0.205 c
+74.742 -0.374 74.775 -0.496 74.844 -0.573 c
+74.91 -0.654 75.01 -0.691 75.138 -0.691 c
+75.245 -0.691 75.344 -0.669 75.432 -0.617 c
+75.528 -0.569 75.608 -0.507 75.667 -0.426 c
+75.733 -0.349 75.785 -0.261 75.814 -0.162 c
+75.843 -0.055 75.858 0.059 75.858 0.177 c
+h
+79.14 -1.263 m
+79.14 0.853 l
+79.14 1.018 79.133 1.154 79.126 1.264 c
+79.114 1.371 79.096 1.455 79.066 1.515 c
+79.045 1.58 79.016 1.632 78.978 1.661 c
+78.949 1.691 78.908 1.706 78.861 1.706 c
+78.802 1.706 78.746 1.676 78.699 1.617 c
+78.659 1.565 78.626 1.492 78.596 1.397 c
+78.567 1.309 78.541 1.195 78.523 1.058 c
+78.511 0.919 78.508 0.769 78.508 0.603 c
+78.508 -1.263 l
+77.759 -1.263 l
+77.759 1.47 l
+77.759 1.706 l
+77.759 1.926 l
+77.759 2.003 77.751 2.066 77.744 2.117 c
+77.744 2.22 l
+78.42 2.22 l
+78.42 2.132 l
+78.42 1.985 l
+78.428 1.926 78.434 1.867 78.434 1.808 c
+78.434 1.646 l
+78.449 1.646 l
+78.468 1.735 78.497 1.812 78.538 1.881 c
+78.574 1.959 78.619 2.029 78.669 2.088 c
+78.729 2.147 78.794 2.19 78.875 2.22 c
+78.952 2.257 79.041 2.278 79.14 2.278 c
+79.324 2.278 79.463 2.224 79.552 2.117 c
+79.647 2.018 79.717 1.86 79.758 1.646 c
+79.772 1.646 l
+79.809 1.742 79.849 1.831 79.889 1.912 c
+79.937 1.989 79.993 2.051 80.051 2.103 c
+80.111 2.161 80.176 2.205 80.257 2.234 c
+80.334 2.264 80.423 2.278 80.522 2.278 c
+80.658 2.278 80.772 2.253 80.859 2.205 c
+80.948 2.153 81.015 2.08 81.065 1.985 c
+81.125 1.885 81.161 1.756 81.183 1.602 c
+81.213 1.455 81.227 1.272 81.227 1.058 c
+81.227 -1.263 l
+80.508 -1.263 l
+80.508 0.853 l
+80.508 1.018 80.5 1.154 80.492 1.264 c
+80.481 1.371 80.463 1.455 80.433 1.515 c
+80.412 1.58 80.382 1.632 80.346 1.661 c
+80.316 1.691 80.275 1.706 80.228 1.706 c
+80.111 1.706 80.015 1.617 79.949 1.441 c
+79.889 1.272 79.86 1.014 79.86 0.661 c
+79.86 -1.263 l
+h
+83.598 -1.323 m
+83.34 -1.323 83.112 -1.286 82.906 -1.22 c
+82.701 -1.143 82.524 -1.028 82.378 -0.881 c
+82.231 -0.727 82.113 -0.536 82.025 -0.309 c
+81.944 -0.085 81.907 0.181 81.907 0.485 c
+81.907 0.816 81.952 1.095 82.039 1.324 c
+82.135 1.559 82.264 1.742 82.422 1.881 c
+82.587 2.018 82.775 2.117 82.98 2.176 c
+83.186 2.242 83.396 2.278 83.612 2.278 c
+83.884 2.278 84.119 2.227 84.318 2.132 c
+84.523 2.043 84.689 1.912 84.818 1.735 c
+84.953 1.565 85.053 1.36 85.112 1.118 c
+85.177 0.882 85.214 0.618 85.214 0.324 c
+85.214 0.309 l
+82.848 0.309 l
+82.848 0.162 82.862 0.023 82.892 -0.103 c
+82.929 -0.231 82.984 -0.345 83.054 -0.44 c
+83.12 -0.529 83.205 -0.598 83.303 -0.646 c
+83.399 -0.698 83.513 -0.72 83.642 -0.72 c
+83.796 -0.72 83.936 -0.687 84.053 -0.617 c
+84.178 -0.551 84.267 -0.448 84.318 -0.309 c
+85.156 -0.382 l
+85.127 -0.481 85.071 -0.588 84.994 -0.706 c
+84.913 -0.816 84.81 -0.918 84.685 -1.014 c
+84.568 -1.103 84.414 -1.176 84.23 -1.234 c
+84.053 -1.294 83.84 -1.323 83.598 -1.323 c
+83.598 1.706 m
+83.509 1.706 83.421 1.691 83.333 1.661 c
+83.245 1.632 83.164 1.58 83.097 1.515 c
+83.028 1.444 82.969 1.357 82.922 1.249 c
+82.881 1.139 82.862 1.014 82.862 0.867 c
+84.333 0.867 l
+84.333 1.004 84.307 1.125 84.259 1.235 c
+84.219 1.341 84.163 1.43 84.097 1.5 c
+84.038 1.565 83.965 1.617 83.877 1.646 c
+83.789 1.683 83.693 1.706 83.598 1.706 c
+86.467 -2.631 m
+86.467 -2.013 l
+87.541 -2.013 l
+87.541 2.896 l
+86.467 2.896 l
+86.467 3.514 l
+88.393 3.514 l
+88.393 -2.631 l
+h
+f
+Q
+q 1 0 0 1 546.3644 140.2277 cm
+0 0 m
+0.676 0 l
+0.676 -3.792 l
+0.676 -4.303 0.544 -4.704 0.279 -4.998 c
+0.022 -5.284 -0.324 -5.424 -0.765 -5.424 c
+-1.228 -5.424 -1.584 -5.288 -1.837 -5.012 c
+-2.084 -4.74 -2.205 -4.358 -2.205 -3.865 c
+-1.529 -3.865 l
+-1.529 -4.182 -1.467 -4.424 -1.338 -4.601 c
+-1.201 -4.77 -1.01 -4.85 -0.765 -4.85 c
+-0.54 -4.85 -0.36 -4.759 -0.221 -4.571 c
+-0.073 -4.388 0 -4.123 0 -3.778 c
+h
+1.573 -3.175 m
+1.573 -2.598 1.708 -2.142 1.984 -1.808 c
+2.267 -1.467 2.639 -1.294 3.102 -1.294 c
+3.561 -1.294 3.929 -1.463 4.204 -1.793 c
+4.486 -2.117 4.634 -2.565 4.644 -3.131 c
+4.644 -3.557 l
+4.644 -4.127 4.501 -4.582 4.218 -4.924 c
+3.943 -5.259 3.576 -5.424 3.116 -5.424 c
+2.653 -5.424 2.282 -5.262 1.999 -4.939 c
+1.723 -4.609 1.58 -4.167 1.573 -3.616 c
+h
+2.219 -3.557 m
+2.219 -3.961 2.296 -4.278 2.454 -4.513 c
+2.62 -4.748 2.84 -4.865 3.116 -4.865 c
+3.682 -4.865 3.976 -4.453 3.998 -3.63 c
+3.998 -3.175 l
+3.998 -2.774 3.913 -2.454 3.748 -2.219 c
+3.59 -1.977 3.374 -1.852 3.102 -1.852 c
+2.836 -1.852 2.62 -1.977 2.454 -2.219 c
+2.296 -2.454 2.219 -2.774 2.219 -3.175 c
+h
+6.188 -5.351 -0.647 3.984 re
+6.232 -0.324 m
+6.232 -0.434 6.203 -0.526 6.144 -0.603 c
+6.086 -0.673 5.99 -0.706 5.865 -0.706 c
+5.747 -0.706 5.652 -0.673 5.585 -0.603 c
+5.527 -0.526 5.498 -0.434 5.498 -0.324 c
+5.498 -0.206 5.527 -0.114 5.585 -0.044 c
+5.652 0.033 5.747 0.073 5.865 0.073 c
+5.99 0.073 6.086 0.033 6.144 -0.044 c
+6.203 -0.125 6.232 -0.217 6.232 -0.324 c
+7.819 -1.367 m
+7.835 -1.808 l
+8.088 -1.467 8.411 -1.294 8.804 -1.294 c
+9.51 -1.294 9.866 -1.764 9.878 -2.705 c
+9.878 -5.351 l
+9.231 -5.351 l
+9.231 -2.734 l
+9.231 -2.421 9.176 -2.201 9.069 -2.072 c
+8.959 -1.947 8.804 -1.881 8.598 -1.881 c
+8.441 -1.881 8.294 -1.937 8.158 -2.043 c
+8.029 -2.153 7.927 -2.29 7.85 -2.454 c
+7.85 -5.351 l
+7.202 -5.351 l
+7.202 -1.367 l
+h
+14.508 -4.336 m
+14.508 -4.189 14.453 -4.068 14.346 -3.969 c
+14.236 -3.873 14.03 -3.755 13.729 -3.616 c
+13.383 -3.469 13.141 -3.348 12.993 -3.248 c
+12.847 -3.142 12.737 -3.024 12.671 -2.896 c
+12.6 -2.77 12.567 -2.612 12.567 -2.425 c
+12.567 -2.102 12.685 -1.833 12.92 -1.617 c
+13.155 -1.404 13.457 -1.294 13.832 -1.294 c
+14.214 -1.294 14.522 -1.407 14.757 -1.631 c
+14.993 -1.86 15.11 -2.146 15.11 -2.499 c
+14.464 -2.499 l
+14.464 -2.323 14.405 -2.172 14.287 -2.043 c
+14.169 -1.918 14.015 -1.852 13.832 -1.852 c
+13.633 -1.852 13.483 -1.907 13.376 -2.014 c
+13.265 -2.113 13.215 -2.246 13.215 -2.411 c
+13.215 -2.539 13.251 -2.646 13.332 -2.734 c
+13.409 -2.815 13.6 -2.918 13.905 -3.042 c
+14.383 -3.23 14.713 -3.418 14.89 -3.601 c
+15.066 -3.778 15.154 -4.006 15.154 -4.278 c
+15.154 -4.63 15.029 -4.91 14.787 -5.116 c
+14.552 -5.321 14.236 -5.424 13.847 -5.424 c
+13.423 -5.424 13.086 -5.307 12.832 -5.072 c
+12.575 -4.829 12.45 -4.524 12.45 -4.16 c
+13.097 -4.16 l
+13.104 -4.388 13.174 -4.564 13.302 -4.689 c
+13.427 -4.806 13.612 -4.865 13.847 -4.865 c
+14.059 -4.865 14.221 -4.818 14.331 -4.719 c
+14.449 -4.623 14.508 -4.494 14.508 -4.336 c
+18.873 -3.557 m
+18.873 -4.185 18.755 -4.656 18.52 -4.968 c
+18.293 -5.274 17.977 -5.424 17.565 -5.424 c
+17.161 -5.424 16.852 -5.274 16.639 -4.968 c
+16.639 -6.88 l
+15.993 -6.88 l
+15.993 -1.367 l
+16.581 -1.367 l
+16.625 -1.808 l
+16.837 -1.467 17.146 -1.294 17.55 -1.294 c
+17.992 -1.294 18.319 -1.448 18.535 -1.749 c
+18.749 -2.055 18.863 -2.51 18.873 -3.117 c
+h
+18.227 -3.175 m
+18.227 -2.734 18.157 -2.411 18.021 -2.205 c
+17.882 -1.992 17.66 -1.881 17.359 -1.881 c
+17.043 -1.881 16.804 -2.036 16.639 -2.337 c
+16.639 -4.41 l
+16.804 -4.715 17.043 -4.865 17.359 -4.865 c
+17.653 -4.865 17.867 -4.763 18.006 -4.557 c
+18.142 -4.343 18.216 -4.013 18.227 -3.572 c
+h
+21.138 -5.424 m
+20.637 -5.424 20.255 -5.277 19.991 -4.983 c
+19.726 -4.689 19.594 -4.256 19.594 -3.675 c
+19.594 -3.204 l
+19.594 -2.61 19.719 -2.142 19.976 -1.808 c
+20.24 -1.467 20.6 -1.294 21.063 -1.294 c
+21.523 -1.294 21.865 -1.448 22.092 -1.749 c
+22.327 -2.043 22.449 -2.506 22.46 -3.131 c
+22.46 -3.557 l
+20.24 -3.557 l
+20.24 -3.645 l
+20.24 -4.079 20.317 -4.391 20.475 -4.586 c
+20.641 -4.773 20.872 -4.865 21.167 -4.865 c
+21.361 -4.865 21.534 -4.833 21.681 -4.763 c
+21.828 -4.686 21.963 -4.568 22.092 -4.41 c
+22.431 -4.821 l
+22.144 -5.226 21.714 -5.424 21.138 -5.424 c
+21.063 -1.852 m
+20.788 -1.852 20.586 -1.947 20.461 -2.132 c
+20.332 -2.319 20.259 -2.61 20.24 -2.999 c
+21.813 -2.999 l
+21.813 -2.911 l
+21.791 -2.529 21.725 -2.26 21.608 -2.102 c
+21.49 -1.937 21.306 -1.852 21.063 -1.852 c
+24.621 -4.865 m
+24.834 -4.865 25.007 -4.803 25.136 -4.675 c
+25.271 -4.538 25.344 -4.347 25.356 -4.101 c
+25.973 -4.101 l
+25.951 -4.484 25.815 -4.803 25.562 -5.056 c
+25.304 -5.303 24.992 -5.424 24.621 -5.424 c
+24.128 -5.424 23.754 -5.274 23.489 -4.968 c
+23.232 -4.656 23.106 -4.189 23.106 -3.572 c
+23.106 -3.131 l
+23.106 -2.535 23.232 -2.08 23.489 -1.764 c
+23.754 -1.452 24.128 -1.294 24.621 -1.294 c
+25.021 -1.294 25.341 -1.426 25.576 -1.691 c
+25.819 -1.947 25.951 -2.294 25.973 -2.734 c
+25.356 -2.734 l
+25.334 -2.44 25.26 -2.219 25.136 -2.072 c
+25.018 -1.926 24.845 -1.852 24.621 -1.852 c
+24.327 -1.852 24.11 -1.951 23.974 -2.146 c
+23.835 -2.334 23.761 -2.643 23.754 -3.072 c
+23.754 -3.587 l
+23.754 -4.057 23.82 -4.391 23.96 -4.586 c
+24.106 -4.773 24.327 -4.865 24.621 -4.865 c
+27.428 -5.351 -0.646 3.984 re
+27.472 -0.324 m
+27.472 -0.434 27.443 -0.526 27.384 -0.603 c
+27.326 -0.673 27.23 -0.706 27.105 -0.706 c
+26.987 -0.706 26.892 -0.673 26.825 -0.603 c
+26.767 -0.526 26.738 -0.434 26.738 -0.324 c
+26.738 -0.206 26.767 -0.114 26.825 -0.044 c
+26.892 0.033 26.987 0.073 27.105 0.073 c
+27.23 0.073 27.326 0.033 27.384 -0.044 c
+27.443 -0.125 27.472 -0.217 27.472 -0.324 c
+28.619 -5.351 m
+28.619 -1.897 l
+28.105 -1.897 l
+28.105 -1.367 l
+28.619 -1.367 l
+28.619 -1 l
+28.627 -0.57 28.741 -0.235 28.957 0 c
+29.181 0.243 29.493 0.368 29.898 0.368 c
+30.044 0.368 30.185 0.345 30.324 0.309 c
+30.471 0.268 30.622 0.213 30.78 0.147 c
+30.662 -0.426 l
+30.427 -0.301 30.185 -0.235 29.942 -0.235 c
+29.695 -0.235 29.523 -0.305 29.427 -0.441 c
+29.328 -0.57 29.281 -0.765 29.281 -1.029 c
+29.281 -1.367 l
+29.927 -1.367 l
+29.927 -1.897 l
+29.281 -1.897 l
+29.281 -5.351 l
+h
+31.089 -5.351 -0.647 3.984 re
+33.558 -5.424 m
+33.058 -5.424 32.676 -5.277 32.411 -4.983 c
+32.147 -4.689 32.014 -4.256 32.014 -3.675 c
+32.014 -3.204 l
+32.014 -2.61 32.139 -2.142 32.396 -1.808 c
+32.662 -1.467 33.021 -1.294 33.485 -1.294 c
+33.944 -1.294 34.285 -1.448 34.513 -1.749 c
+34.748 -2.043 34.869 -2.506 34.881 -3.131 c
+34.881 -3.557 l
+32.662 -3.557 l
+32.662 -3.645 l
+32.662 -4.079 32.739 -4.391 32.897 -4.586 c
+33.061 -4.773 33.293 -4.865 33.587 -4.865 c
+33.782 -4.865 33.955 -4.833 34.102 -4.763 c
+34.249 -4.686 34.385 -4.568 34.513 -4.41 c
+34.852 -4.821 l
+34.565 -5.226 34.135 -5.424 33.558 -5.424 c
+33.485 -1.852 m
+33.209 -1.852 33.007 -1.947 32.882 -2.132 c
+32.753 -2.319 32.679 -2.61 32.662 -2.999 c
+34.233 -2.999 l
+34.233 -2.911 l
+34.212 -2.529 34.146 -2.26 34.028 -2.102 c
+33.911 -1.937 33.726 -1.852 33.485 -1.852 c
+35.527 -3.175 m
+35.527 -2.569 35.638 -2.102 35.866 -1.779 c
+36.101 -1.455 36.428 -1.294 36.851 -1.294 c
+37.233 -1.294 37.53 -1.452 37.747 -1.764 c
+37.747 0.294 l
+38.393 0.294 l
+38.393 -5.351 l
+37.805 -5.351 l
+37.761 -4.924 l
+37.556 -5.259 37.25 -5.424 36.851 -5.424 c
+36.439 -5.424 36.115 -5.27 35.88 -4.954 c
+35.645 -4.63 35.527 -4.175 35.527 -3.587 c
+h
+36.174 -3.557 m
+36.174 -3.998 36.236 -4.329 36.365 -4.542 c
+36.502 -4.748 36.722 -4.85 37.027 -4.85 c
+37.35 -4.85 37.589 -4.689 37.747 -4.366 c
+37.747 -2.352 l
+37.578 -2.04 37.339 -1.881 37.027 -1.881 c
+36.722 -1.881 36.502 -1.984 36.365 -2.19 c
+36.236 -2.396 36.174 -2.72 36.174 -3.16 c
+h
+f
+Q
+q 1 0 0 1 588.8294 140.2861 cm
+0 0 m
+-0.382 0 l
+-0.382 -5.835 l
+0 -5.835 l
+0 -6.659 l
+-1.425 -6.659 l
+-1.425 0.823 l
+0 0.823 l
+h
+0.765 -5.409 m
+0.765 -2.219 l
+0.279 -2.219 l
+0.279 -1.425 l
+0.765 -1.425 l
+0.765 -1.072 l
+0.765 -0.631 0.875 -0.294 1.103 -0.058 c
+1.338 0.184 1.654 0.31 2.058 0.31 c
+2.183 0.31 2.341 0.283 2.529 0.235 c
+2.529 -0.588 l
+2.459 -0.569 2.374 -0.558 2.278 -0.558 c
+1.962 -0.558 1.808 -0.742 1.808 -1.102 c
+1.808 -1.425 l
+2.426 -1.425 l
+2.426 -2.219 l
+1.808 -2.219 l
+1.808 -5.409 l
+h
+4.954 -2.439 m
+4.616 -2.41 l
+4.329 -2.41 4.138 -2.535 4.042 -2.778 c
+4.042 -5.409 l
+2.999 -5.409 l
+2.999 -1.425 l
+3.969 -1.425 l
+3.998 -1.866 l
+4.164 -1.525 4.395 -1.352 4.69 -1.352 c
+4.807 -1.352 4.898 -1.374 4.969 -1.411 c
+h
+5.248 -3.293 m
+5.248 -2.686 5.388 -2.212 5.675 -1.866 c
+5.958 -1.525 6.35 -1.352 6.85 -1.352 c
+7.358 -1.352 7.755 -1.525 8.04 -1.866 c
+8.324 -2.212 8.467 -2.686 8.467 -3.293 c
+8.467 -3.557 l
+8.467 -4.156 8.324 -4.627 8.04 -4.968 c
+7.755 -5.313 7.358 -5.483 6.85 -5.483 c
+6.34 -5.483 5.943 -5.313 5.659 -4.968 c
+5.384 -4.627 5.248 -4.152 5.248 -3.542 c
+h
+6.292 -3.557 m
+6.292 -4.262 6.475 -4.615 6.85 -4.615 c
+7.203 -4.615 7.394 -4.321 7.423 -3.733 c
+7.423 -3.293 l
+7.423 -2.932 7.372 -2.66 7.277 -2.484 c
+7.177 -2.308 7.034 -2.219 6.85 -2.219 c
+6.674 -2.219 6.534 -2.308 6.438 -2.484 c
+6.34 -2.66 6.292 -2.932 6.292 -3.293 c
+h
+10.084 -1.425 m
+10.113 -1.793 l
+10.348 -1.499 10.658 -1.352 11.04 -1.352 c
+11.44 -1.352 11.719 -1.535 11.877 -1.896 c
+12.112 -1.535 12.439 -1.352 12.862 -1.352 c
+13.557 -1.352 13.91 -1.837 13.92 -2.807 c
+13.92 -5.409 l
+12.892 -5.409 l
+12.892 -2.865 l
+12.892 -2.642 12.855 -2.48 12.788 -2.381 c
+12.73 -2.285 12.62 -2.234 12.465 -2.234 c
+12.267 -2.234 12.127 -2.352 12.039 -2.587 c
+12.039 -5.409 l
+10.995 -5.409 l
+10.995 -2.881 l
+10.995 -2.645 10.966 -2.48 10.907 -2.381 c
+10.849 -2.285 10.739 -2.234 10.583 -2.234 c
+10.407 -2.234 10.264 -2.329 10.157 -2.513 c
+10.157 -5.409 l
+9.114 -5.409 l
+9.114 -1.425 l
+h
+17.39 -1.425 m
+17.419 -1.822 l
+17.654 -1.51 17.955 -1.352 18.33 -1.352 c
+19.013 -1.352 19.366 -1.833 19.389 -2.792 c
+19.389 -5.409 l
+18.344 -5.409 l
+18.344 -2.865 l
+18.344 -2.642 18.308 -2.48 18.242 -2.381 c
+18.172 -2.285 18.055 -2.234 17.889 -2.234 c
+17.702 -2.234 17.555 -2.329 17.448 -2.513 c
+17.448 -5.409 l
+16.405 -5.409 l
+16.405 -1.425 l
+h
+22.02 -5.409 m
+21.99 -5.35 21.961 -5.247 21.932 -5.1 c
+21.744 -5.357 21.494 -5.483 21.182 -5.483 c
+20.848 -5.483 20.568 -5.375 20.344 -5.159 c
+20.127 -4.935 20.021 -4.644 20.021 -4.292 c
+20.021 -3.881 20.153 -3.564 20.418 -3.336 c
+20.682 -3.101 21.064 -2.983 21.564 -2.983 c
+21.887 -2.983 l
+21.887 -2.66 l
+21.887 -2.484 21.851 -2.362 21.785 -2.293 c
+21.725 -2.215 21.637 -2.175 21.519 -2.175 c
+21.263 -2.175 21.137 -2.329 21.137 -2.63 c
+20.094 -2.63 l
+20.094 -2.26 20.23 -1.955 20.505 -1.72 c
+20.777 -1.477 21.126 -1.352 21.55 -1.352 c
+21.99 -1.352 22.328 -1.469 22.564 -1.705 c
+22.806 -1.932 22.93 -2.256 22.93 -2.675 c
+22.93 -4.542 l
+22.93 -4.887 22.979 -5.155 23.078 -5.35 c
+23.078 -5.409 l
+h
+21.417 -4.659 m
+21.523 -4.659 21.615 -4.641 21.696 -4.6 c
+21.785 -4.552 21.847 -4.494 21.887 -4.424 c
+21.887 -3.601 l
+21.637 -3.601 l
+21.461 -3.601 21.318 -3.659 21.211 -3.777 c
+21.112 -3.887 21.064 -4.035 21.064 -4.218 c
+21.064 -4.512 21.182 -4.659 21.417 -4.659 c
+24.651 -1.425 m
+24.68 -1.793 l
+24.916 -1.499 25.224 -1.352 25.606 -1.352 c
+26.007 -1.352 26.286 -1.535 26.444 -1.896 c
+26.679 -1.535 27.006 -1.352 27.429 -1.352 c
+28.123 -1.352 28.476 -1.837 28.487 -2.807 c
+28.487 -5.409 l
+27.458 -5.409 l
+27.458 -2.865 l
+27.458 -2.642 27.422 -2.48 27.356 -2.381 c
+27.296 -2.285 27.186 -2.234 27.032 -2.234 c
+26.834 -2.234 26.693 -2.352 26.606 -2.587 c
+26.606 -5.409 l
+25.562 -5.409 l
+25.562 -2.881 l
+25.562 -2.645 25.533 -2.48 25.474 -2.381 c
+25.415 -2.285 25.305 -2.234 25.151 -2.234 c
+24.974 -2.234 24.831 -2.329 24.725 -2.513 c
+24.725 -5.409 l
+23.68 -5.409 l
+23.68 -1.425 l
+h
+30.869 -5.483 m
+30.339 -5.483 29.92 -5.328 29.619 -5.012 c
+29.325 -4.689 29.178 -4.23 29.178 -3.63 c
+29.178 -3.322 l
+29.178 -2.697 29.314 -2.212 29.59 -1.866 c
+29.862 -1.525 30.255 -1.352 30.766 -1.352 c
+31.266 -1.352 31.636 -1.514 31.883 -1.837 c
+32.137 -2.16 32.268 -2.638 32.28 -3.262 c
+32.28 -3.763 l
+30.207 -3.763 l
+30.225 -4.056 30.288 -4.274 30.398 -4.409 c
+30.516 -4.549 30.695 -4.615 30.942 -4.615 c
+31.283 -4.615 31.574 -4.498 31.809 -4.262 c
+32.22 -4.895 l
+32.092 -5.071 31.905 -5.215 31.662 -5.321 c
+31.416 -5.427 31.152 -5.483 30.869 -5.483 c
+30.221 -3.042 m
+31.25 -3.042 l
+31.25 -2.94 l
+31.25 -2.705 31.21 -2.528 31.133 -2.41 c
+31.063 -2.285 30.934 -2.219 30.751 -2.219 c
+30.574 -2.219 30.442 -2.289 30.354 -2.425 c
+30.273 -2.553 30.229 -2.759 30.221 -3.042 c
+32.617 0.823 m
+34.044 0.823 l
+34.044 -6.659 l
+32.617 -6.659 l
+32.617 -5.835 l
+33 -5.835 l
+33 0 l
+32.617 0 l
+h
+f
+Q
+q 1 0 0 1 628.3846 136.6708 cm
+0 0 m
+0 -0.618 -0.114 -1.085 -0.338 -1.397 c
+-0.555 -1.713 -0.878 -1.867 -1.308 -1.867 c
+-1.731 -1.867 -2.043 -1.687 -2.248 -1.324 c
+-2.278 -1.794 l
+-2.88 -1.794 l
+-2.88 3.85 l
+-2.234 3.85 l
+-2.234 1.749 l
+-2.021 2.09 -1.712 2.263 -1.308 2.263 c
+-0.878 2.263 -0.555 2.105 -0.338 1.793 c
+-0.114 1.488 0 1.022 0 0.397 c
+h
+-0.646 0.382 m
+-0.646 0.852 -0.716 1.183 -0.852 1.381 c
+-0.981 1.576 -1.19 1.675 -1.484 1.675 c
+-1.818 1.675 -2.069 1.492 -2.234 1.132 c
+-2.234 -0.75 l
+-2.069 -1.114 -1.815 -1.294 -1.469 -1.294 c
+-1.176 -1.294 -0.966 -1.191 -0.837 -0.985 c
+-0.712 -0.779 -0.646 -0.464 -0.646 -0.03 c
+h
+2.485 1.573 m
+2.396 1.591 2.297 1.602 2.19 1.602 c
+1.856 1.602 1.621 1.418 1.484 1.058 c
+1.484 -1.794 l
+0.838 -1.794 l
+0.838 2.19 l
+1.47 2.19 l
+1.484 1.778 l
+1.661 2.102 1.904 2.263 2.22 2.263 c
+2.326 2.263 2.415 2.241 2.485 2.204 c
+h
+5.027 -1.794 m
+4.987 -1.706 4.962 -1.559 4.954 -1.353 c
+4.719 -1.698 4.424 -1.867 4.072 -1.867 c
+3.708 -1.867 3.425 -1.771 3.219 -1.573 c
+3.021 -1.367 2.926 -1.081 2.926 -0.706 c
+2.926 -0.306 3.061 0.014 3.337 0.249 c
+3.609 0.492 3.984 0.617 4.454 0.617 c
+4.939 0.617 l
+4.939 1.043 l
+4.939 1.278 4.884 1.444 4.777 1.543 c
+4.667 1.65 4.505 1.705 4.293 1.705 c
+4.094 1.705 3.932 1.646 3.807 1.529 c
+3.69 1.411 3.631 1.263 3.631 1.087 c
+2.984 1.087 l
+2.984 1.282 3.043 1.473 3.161 1.66 c
+3.286 1.845 3.447 1.992 3.645 2.102 c
+3.851 2.208 4.079 2.263 4.337 2.263 c
+4.738 2.263 5.042 2.161 5.247 1.955 c
+5.461 1.749 5.575 1.455 5.586 1.072 c
+5.586 -0.941 l
+5.586 -1.246 5.623 -1.511 5.704 -1.735 c
+5.704 -1.794 l
+h
+4.16 -1.279 m
+4.326 -1.279 4.476 -1.235 4.616 -1.147 c
+4.763 -1.058 4.869 -0.948 4.939 -0.809 c
+4.939 0.132 l
+4.572 0.132 l
+4.256 0.132 4.013 0.062 3.836 -0.073 c
+3.66 -0.202 3.572 -0.389 3.572 -0.632 c
+3.572 -0.86 3.616 -1.025 3.705 -1.132 c
+3.793 -1.231 3.944 -1.279 4.16 -1.279 c
+7.203 2.19 m
+7.217 1.749 l
+7.471 2.09 7.795 2.263 8.187 2.263 c
+8.893 2.263 9.249 1.793 9.261 0.852 c
+9.261 -1.794 l
+8.614 -1.794 l
+8.614 0.823 l
+8.614 1.135 8.559 1.356 8.453 1.484 c
+8.343 1.61 8.187 1.675 7.982 1.675 c
+7.824 1.675 7.676 1.62 7.541 1.514 c
+7.412 1.404 7.31 1.267 7.232 1.103 c
+7.232 -1.794 l
+6.585 -1.794 l
+6.585 2.19 l
+h
+11.612 -1.309 m
+11.826 -1.309 11.998 -1.246 12.127 -1.118 c
+12.263 -0.981 12.337 -0.79 12.347 -0.544 c
+12.965 -0.544 l
+12.943 -0.927 12.807 -1.246 12.553 -1.5 c
+12.296 -1.746 11.984 -1.867 11.612 -1.867 c
+11.121 -1.867 10.745 -1.717 10.481 -1.411 c
+10.224 -1.099 10.099 -0.632 10.099 -0.015 c
+10.099 0.426 l
+10.099 1.022 10.224 1.477 10.481 1.793 c
+10.745 2.105 11.121 2.263 11.612 2.263 c
+12.013 2.263 12.333 2.131 12.568 1.866 c
+12.811 1.61 12.943 1.263 12.965 0.823 c
+12.347 0.823 l
+12.326 1.117 12.252 1.338 12.127 1.484 c
+12.01 1.631 11.836 1.705 11.612 1.705 c
+11.319 1.705 11.102 1.606 10.966 1.411 c
+10.826 1.223 10.753 0.914 10.745 0.484 c
+10.745 -0.03 l
+10.745 -0.5 10.812 -0.834 10.951 -1.029 c
+11.098 -1.216 11.319 -1.309 11.612 -1.309 c
+14.361 1.778 m
+14.615 2.102 14.934 2.263 15.317 2.263 c
+16.023 2.263 16.378 1.793 16.39 0.852 c
+16.39 -1.794 l
+15.743 -1.794 l
+15.743 0.823 l
+15.743 1.135 15.688 1.356 15.582 1.484 c
+15.471 1.61 15.317 1.675 15.111 1.675 c
+14.953 1.675 14.806 1.62 14.67 1.514 c
+14.541 1.404 14.438 1.267 14.361 1.103 c
+14.361 -1.794 l
+13.714 -1.794 l
+13.714 3.85 l
+14.361 3.85 l
+h
+19.771 -1.794 -0.647 3.984 re
+19.815 3.233 m
+19.815 3.123 19.786 3.031 19.726 2.954 c
+19.668 2.884 19.572 2.851 19.447 2.851 c
+19.329 2.851 19.234 2.884 19.168 2.954 c
+19.109 3.031 19.08 3.123 19.08 3.233 c
+19.08 3.351 19.109 3.443 19.168 3.513 c
+19.234 3.59 19.329 3.63 19.447 3.63 c
+19.572 3.63 19.668 3.59 19.726 3.513 c
+19.786 3.432 19.815 3.34 19.815 3.233 c
+21.402 2.19 m
+21.417 1.749 l
+21.671 2.09 21.994 2.263 22.387 2.263 c
+23.092 2.263 23.449 1.793 23.46 0.852 c
+23.46 -1.794 l
+22.813 -1.794 l
+22.813 0.823 l
+22.813 1.135 22.758 1.356 22.651 1.484 c
+22.541 1.61 22.387 1.675 22.181 1.675 c
+22.023 1.675 21.876 1.62 21.741 1.514 c
+21.612 1.404 21.509 1.267 21.432 1.103 c
+21.432 -1.794 l
+20.785 -1.794 l
+20.785 2.19 l
+h
+25.282 3.145 m
+25.282 2.19 l
+25.885 2.19 l
+25.885 1.66 l
+25.282 1.66 l
+25.282 -0.809 l
+25.282 -0.967 25.305 -1.085 25.356 -1.162 c
+25.415 -1.243 25.503 -1.279 25.621 -1.279 c
+25.709 -1.279 25.797 -1.264 25.885 -1.235 c
+25.885 -1.794 l
+25.739 -1.841 25.584 -1.867 25.43 -1.867 c
+25.172 -1.867 24.978 -1.775 24.842 -1.588 c
+24.702 -1.405 24.636 -1.143 24.636 -0.809 c
+24.636 1.66 l
+24.033 1.66 l
+24.033 2.19 l
+24.636 2.19 l
+24.636 3.145 l
+h
+26.444 0.382 m
+26.444 0.959 26.58 1.415 26.855 1.749 c
+27.138 2.09 27.51 2.263 27.973 2.263 c
+28.432 2.263 28.8 2.094 29.076 1.764 c
+29.358 1.44 29.505 0.992 29.516 0.426 c
+29.516 0 l
+29.516 -0.57 29.373 -1.025 29.09 -1.367 c
+28.814 -1.702 28.447 -1.867 27.987 -1.867 c
+27.524 -1.867 27.154 -1.706 26.87 -1.382 c
+26.595 -1.052 26.452 -0.611 26.444 -0.059 c
+h
+27.091 0 m
+27.091 -0.405 27.168 -0.721 27.326 -0.956 c
+27.491 -1.191 27.711 -1.309 27.987 -1.309 c
+28.553 -1.309 28.847 -0.897 28.869 -0.073 c
+28.869 0.382 l
+28.869 0.783 28.785 1.103 28.619 1.338 c
+28.461 1.579 28.245 1.705 27.973 1.705 c
+27.708 1.705 27.491 1.579 27.326 1.338 c
+27.168 1.103 27.091 0.783 27.091 0.382 c
+h
+33.161 -0.706 m
+33.882 2.19 l
+34.572 2.19 l
+33.279 -2.352 l
+33.18 -2.694 33.037 -2.955 32.853 -3.131 c
+32.677 -3.308 32.474 -3.396 32.25 -3.396 c
+32.162 -3.396 32.048 -3.373 31.912 -3.337 c
+31.912 -2.793 l
+32.059 -2.808 l
+32.243 -2.808 32.39 -2.764 32.5 -2.675 c
+32.606 -2.587 32.695 -2.429 32.764 -2.205 c
+32.882 -1.764 l
+31.721 2.19 l
+32.426 2.19 l
+h
+35.013 0.382 m
+35.013 0.959 35.15 1.415 35.425 1.749 c
+35.708 2.09 36.079 2.263 36.542 2.263 c
+37.001 2.263 37.369 2.094 37.645 1.764 c
+37.928 1.44 38.075 0.992 38.086 0.426 c
+38.086 0 l
+38.086 -0.57 37.942 -1.025 37.66 -1.367 c
+37.384 -1.702 37.016 -1.867 36.557 -1.867 c
+36.094 -1.867 35.723 -1.706 35.44 -1.382 c
+35.164 -1.052 35.021 -0.611 35.013 -0.059 c
+h
+35.661 0 m
+35.661 -0.405 35.738 -0.721 35.896 -0.956 c
+36.06 -1.191 36.282 -1.309 36.557 -1.309 c
+37.123 -1.309 37.417 -0.897 37.439 -0.073 c
+37.439 0.382 l
+37.439 0.783 37.354 1.103 37.189 1.338 c
+37.031 1.579 36.814 1.705 36.542 1.705 c
+36.278 1.705 36.06 1.579 35.896 1.338 c
+35.738 1.103 35.661 0.783 35.661 0.382 c
+h
+40.952 -1.441 m
+40.735 -1.727 40.423 -1.867 40.012 -1.867 c
+39.648 -1.867 39.372 -1.746 39.188 -1.5 c
+39.012 -1.246 38.917 -0.882 38.909 -0.412 c
+38.909 2.19 l
+39.555 2.19 l
+39.555 -0.353 l
+39.555 -0.981 39.74 -1.294 40.114 -1.294 c
+40.515 -1.294 40.791 -1.118 40.937 -0.765 c
+40.937 2.19 l
+41.583 2.19 l
+41.583 -1.794 l
+40.966 -1.794 l
+h
+44.215 1.573 m
+44.127 1.591 44.028 1.602 43.921 1.602 c
+43.586 1.602 43.351 1.418 43.216 1.058 c
+43.216 -1.794 l
+42.568 -1.794 l
+42.568 2.19 l
+43.201 2.19 l
+43.216 1.778 l
+43.392 2.102 43.634 2.263 43.95 2.263 c
+44.057 2.263 44.145 2.241 44.215 2.204 c
+h
+47.964 -1.309 m
+48.176 -1.309 48.349 -1.246 48.478 -1.118 c
+48.614 -0.981 48.687 -0.79 48.698 -0.544 c
+49.315 -0.544 l
+49.294 -0.927 49.157 -1.246 48.904 -1.5 c
+48.647 -1.746 48.334 -1.867 47.964 -1.867 c
+47.471 -1.867 47.096 -1.717 46.832 -1.411 c
+46.574 -1.099 46.449 -0.632 46.449 -0.015 c
+46.449 0.426 l
+46.449 1.022 46.574 1.477 46.832 1.793 c
+47.096 2.105 47.471 2.263 47.964 2.263 c
+48.363 2.263 48.683 2.131 48.918 1.866 c
+49.161 1.61 49.294 1.263 49.315 0.823 c
+48.698 0.823 l
+48.677 1.117 48.602 1.338 48.478 1.484 c
+48.361 1.631 48.188 1.705 47.964 1.705 c
+47.669 1.705 47.453 1.606 47.316 1.411 c
+47.177 1.223 47.104 0.914 47.096 0.484 c
+47.096 -0.03 l
+47.096 -0.5 47.162 -0.834 47.302 -1.029 c
+47.449 -1.216 47.669 -1.309 47.964 -1.309 c
+52.093 -1.441 m
+51.877 -1.727 51.565 -1.867 51.153 -1.867 c
+50.79 -1.867 50.514 -1.746 50.33 -1.5 c
+50.154 -1.246 50.058 -0.882 50.05 -0.412 c
+50.05 2.19 l
+50.697 2.19 l
+50.697 -0.353 l
+50.697 -0.981 50.881 -1.294 51.256 -1.294 c
+51.656 -1.294 51.932 -1.118 52.079 -0.765 c
+52.079 2.19 l
+52.726 2.19 l
+52.726 -1.794 l
+52.109 -1.794 l
+h
+55.357 1.573 m
+55.268 1.591 55.17 1.602 55.063 1.602 c
+54.729 1.602 54.493 1.418 54.358 1.058 c
+54.358 -1.794 l
+53.711 -1.794 l
+53.711 2.19 l
+54.343 2.19 l
+54.358 1.778 l
+54.534 2.102 54.776 2.263 55.093 2.263 c
+55.199 2.263 55.287 2.241 55.357 2.204 c
+h
+57.65 1.573 m
+57.562 1.591 57.462 1.602 57.356 1.602 c
+57.022 1.602 56.787 1.418 56.65 1.058 c
+56.65 -1.794 l
+56.004 -1.794 l
+56.004 2.19 l
+56.635 2.19 l
+56.65 1.778 l
+56.827 2.102 57.069 2.263 57.385 2.263 c
+57.492 2.263 57.58 2.241 57.65 2.204 c
+h
+59.65 -1.867 m
+59.149 -1.867 58.767 -1.72 58.503 -1.426 c
+58.238 -1.132 58.106 -0.699 58.106 -0.118 c
+58.106 0.353 l
+58.106 0.947 58.231 1.415 58.488 1.749 c
+58.752 2.09 59.112 2.263 59.575 2.263 c
+60.035 2.263 60.377 2.109 60.604 1.808 c
+60.84 1.514 60.961 1.051 60.972 0.426 c
+60.972 0 l
+58.752 0 l
+58.752 -0.088 l
+58.752 -0.522 58.83 -0.834 58.987 -1.029 c
+59.153 -1.216 59.384 -1.309 59.679 -1.309 c
+59.873 -1.309 60.046 -1.276 60.193 -1.206 c
+60.34 -1.129 60.476 -1.011 60.604 -0.853 c
+60.943 -1.264 l
+60.656 -1.669 60.226 -1.867 59.65 -1.867 c
+59.575 1.705 m
+59.3 1.705 59.098 1.61 58.973 1.425 c
+58.844 1.238 58.771 0.947 58.752 0.558 c
+60.325 0.558 l
+60.325 0.646 l
+60.303 1.028 60.237 1.297 60.12 1.455 c
+60.002 1.62 59.818 1.705 59.575 1.705 c
+62.368 2.19 m
+62.383 1.749 l
+62.636 2.09 62.96 2.263 63.353 2.263 c
+64.059 2.263 64.415 1.793 64.427 0.852 c
+64.427 -1.794 l
+63.779 -1.794 l
+63.779 0.823 l
+63.779 1.135 63.725 1.356 63.617 1.484 c
+63.507 1.61 63.353 1.675 63.147 1.675 c
+62.989 1.675 62.842 1.62 62.707 1.514 c
+62.578 1.404 62.475 1.267 62.397 1.103 c
+62.397 -1.794 l
+61.751 -1.794 l
+61.751 2.19 l
+h
+66.249 3.145 m
+66.249 2.19 l
+66.852 2.19 l
+66.852 1.66 l
+66.249 1.66 l
+66.249 -0.809 l
+66.249 -0.967 66.271 -1.085 66.322 -1.162 c
+66.381 -1.243 66.47 -1.279 66.587 -1.279 c
+66.675 -1.279 66.763 -1.264 66.852 -1.235 c
+66.852 -1.794 l
+66.705 -1.841 66.551 -1.867 66.396 -1.867 c
+66.139 -1.867 65.944 -1.775 65.808 -1.588 c
+65.668 -1.405 65.603 -1.143 65.603 -0.809 c
+65.603 1.66 l
+64.999 1.66 l
+64.999 2.19 l
+65.603 2.19 l
+65.603 3.145 l
+h
+72.217 0 m
+72.217 -0.618 72.103 -1.085 71.879 -1.397 c
+71.662 -1.713 71.338 -1.867 70.908 -1.867 c
+70.486 -1.867 70.174 -1.687 69.968 -1.324 c
+69.938 -1.794 l
+69.335 -1.794 l
+69.335 3.85 l
+69.983 3.85 l
+69.983 1.749 l
+70.196 2.09 70.505 2.263 70.908 2.263 c
+71.338 2.263 71.662 2.105 71.879 1.793 c
+72.103 1.488 72.217 1.022 72.217 0.397 c
+h
+71.57 0.382 m
+71.57 0.852 71.5 1.183 71.365 1.381 c
+71.236 1.576 71.026 1.675 70.732 1.675 c
+70.397 1.675 70.148 1.492 69.983 1.132 c
+69.983 -0.75 l
+70.148 -1.114 70.401 -1.294 70.746 -1.294 c
+71.041 -1.294 71.251 -1.191 71.379 -0.985 c
+71.504 -0.779 71.57 -0.464 71.57 -0.03 c
+h
+74.701 1.573 m
+74.613 1.591 74.513 1.602 74.407 1.602 c
+74.073 1.602 73.838 1.418 73.701 1.058 c
+73.701 -1.794 l
+73.055 -1.794 l
+73.055 2.19 l
+73.686 2.19 l
+73.701 1.778 l
+73.878 2.102 74.12 2.263 74.436 2.263 c
+74.543 2.263 74.631 2.241 74.701 2.204 c
+h
+77.244 -1.794 m
+77.204 -1.706 77.177 -1.559 77.171 -1.353 c
+76.936 -1.698 76.641 -1.867 76.288 -1.867 c
+75.924 -1.867 75.642 -1.771 75.436 -1.573 c
+75.238 -1.367 75.142 -1.081 75.142 -0.706 c
+75.142 -0.306 75.278 0.014 75.554 0.249 c
+75.826 0.492 76.2 0.617 76.67 0.617 c
+77.156 0.617 l
+77.156 1.043 l
+77.156 1.278 77.1 1.444 76.994 1.543 c
+76.884 1.65 76.722 1.705 76.508 1.705 c
+76.311 1.705 76.149 1.646 76.024 1.529 c
+75.906 1.411 75.847 1.263 75.847 1.087 c
+75.201 1.087 l
+75.201 1.282 75.259 1.473 75.377 1.66 c
+75.502 1.845 75.664 1.992 75.862 2.102 c
+76.068 2.208 76.296 2.263 76.553 2.263 c
+76.953 2.263 77.258 2.161 77.464 1.955 c
+77.678 1.749 77.792 1.455 77.802 1.072 c
+77.802 -0.941 l
+77.802 -1.246 77.84 -1.511 77.92 -1.735 c
+77.92 -1.794 l
+h
+76.377 -1.279 m
+76.542 -1.279 76.693 -1.235 76.832 -1.147 c
+76.979 -1.058 77.086 -0.948 77.156 -0.809 c
+77.156 0.132 l
+76.788 0.132 l
+76.472 0.132 76.23 0.062 76.053 -0.073 c
+75.877 -0.202 75.789 -0.389 75.789 -0.632 c
+75.789 -0.86 75.833 -1.025 75.921 -1.132 c
+76.009 -1.231 76.159 -1.279 76.377 -1.279 c
+79.419 2.19 m
+79.434 1.749 l
+79.687 2.09 80.011 2.263 80.404 2.263 c
+81.11 2.263 81.466 1.793 81.477 0.852 c
+81.477 -1.794 l
+80.83 -1.794 l
+80.83 0.823 l
+80.83 1.135 80.776 1.356 80.668 1.484 c
+80.558 1.61 80.404 1.675 80.198 1.675 c
+80.04 1.675 79.893 1.62 79.758 1.514 c
+79.629 1.404 79.526 1.267 79.448 1.103 c
+79.448 -1.794 l
+78.802 -1.794 l
+78.802 2.19 l
+h
+83.829 -1.309 m
+84.042 -1.309 84.215 -1.246 84.344 -1.118 c
+84.479 -0.981 84.553 -0.79 84.564 -0.544 c
+85.181 -0.544 l
+85.16 -0.927 85.023 -1.246 84.77 -1.5 c
+84.512 -1.746 84.2 -1.867 83.829 -1.867 c
+83.336 -1.867 82.962 -1.717 82.698 -1.411 c
+82.44 -1.099 82.315 -0.632 82.315 -0.015 c
+82.315 0.426 l
+82.315 1.022 82.44 1.477 82.698 1.793 c
+82.962 2.105 83.336 2.263 83.829 2.263 c
+84.23 2.263 84.549 2.131 84.784 1.866 c
+85.027 1.61 85.16 1.263 85.181 0.823 c
+84.564 0.823 l
+84.542 1.117 84.468 1.338 84.344 1.484 c
+84.226 1.631 84.053 1.705 83.829 1.705 c
+83.535 1.705 83.318 1.606 83.182 1.411 c
+83.043 1.223 82.969 0.914 82.962 0.484 c
+82.962 -0.03 l
+82.962 -0.5 83.028 -0.834 83.168 -1.029 c
+83.315 -1.216 83.535 -1.309 83.829 -1.309 c
+86.578 1.778 m
+86.831 2.102 87.151 2.263 87.533 2.263 c
+88.239 2.263 88.595 1.793 88.606 0.852 c
+88.606 -1.794 l
+87.959 -1.794 l
+87.959 0.823 l
+87.959 1.135 87.905 1.356 87.797 1.484 c
+87.687 1.61 87.533 1.675 87.327 1.675 c
+87.169 1.675 87.022 1.62 86.887 1.514 c
+86.758 1.404 86.655 1.267 86.578 1.103 c
+86.578 -1.794 l
+85.931 -1.794 l
+85.931 3.85 l
+86.578 3.85 l
+h
+91.267 0.382 m
+91.267 1.018 91.355 1.62 91.531 2.19 c
+91.708 2.755 91.951 3.252 92.266 3.675 c
+92.462 3.939 92.649 4.13 92.825 4.247 c
+92.957 3.792 l
+92.663 3.516 92.421 3.094 92.237 2.528 c
+92.049 1.959 91.947 1.326 91.928 0.632 c
+91.928 0.338 l
+91.928 -0.526 92.046 -1.29 92.281 -1.955 c
+92.464 -2.455 92.693 -2.837 92.957 -3.102 c
+92.825 -3.528 l
+92.597 -3.37 92.373 -3.12 92.148 -2.778 c
+91.56 -1.897 91.267 -0.846 91.267 0.382 c
+94.5 3.145 m
+94.5 2.19 l
+95.103 2.19 l
+95.103 1.66 l
+94.5 1.66 l
+94.5 -0.809 l
+94.5 -0.967 94.523 -1.085 94.574 -1.162 c
+94.633 -1.243 94.721 -1.279 94.839 -1.279 c
+94.927 -1.279 95.015 -1.264 95.103 -1.235 c
+95.103 -1.794 l
+94.956 -1.841 94.802 -1.867 94.648 -1.867 c
+94.39 -1.867 94.195 -1.775 94.06 -1.588 c
+93.92 -1.405 93.854 -1.143 93.854 -0.809 c
+93.854 1.66 l
+93.251 1.66 l
+93.251 2.19 l
+93.854 2.19 l
+93.854 3.145 l
+h
+96.514 1.778 m
+96.768 2.102 97.087 2.263 97.47 2.263 c
+98.176 2.263 98.532 1.793 98.542 0.852 c
+98.542 -1.794 l
+97.896 -1.794 l
+97.896 0.823 l
+97.896 1.135 97.841 1.356 97.734 1.484 c
+97.624 1.61 97.47 1.675 97.264 1.675 c
+97.106 1.675 96.959 1.62 96.823 1.514 c
+96.695 1.404 96.591 1.267 96.514 1.103 c
+96.514 -1.794 l
+95.868 -1.794 l
+95.868 3.85 l
+96.514 3.85 l
+h
+100.924 -1.867 m
+100.424 -1.867 100.042 -1.72 99.778 -1.426 c
+99.513 -1.132 99.381 -0.699 99.381 -0.118 c
+99.381 0.353 l
+99.381 0.947 99.506 1.415 99.763 1.749 c
+100.027 2.09 100.387 2.263 100.85 2.263 c
+101.31 2.263 101.652 2.109 101.879 1.808 c
+102.114 1.514 102.236 1.051 102.247 0.426 c
+102.247 0 l
+100.027 0 l
+100.027 -0.088 l
+100.027 -0.522 100.104 -0.834 100.262 -1.029 c
+100.428 -1.216 100.659 -1.309 100.954 -1.309 c
+101.148 -1.309 101.32 -1.276 101.468 -1.206 c
+101.615 -1.129 101.75 -1.011 101.879 -0.853 c
+102.218 -1.264 l
+101.931 -1.669 101.501 -1.867 100.924 -1.867 c
+100.85 1.705 m
+100.575 1.705 100.373 1.61 100.248 1.425 c
+100.119 1.238 100.046 0.947 100.027 0.558 c
+101.6 0.558 l
+101.6 0.646 l
+101.578 1.028 101.512 1.297 101.395 1.455 c
+101.277 1.62 101.093 1.705 100.85 1.705 c
+104.613 0.382 m
+104.613 0.959 104.75 1.415 105.025 1.749 c
+105.308 2.09 105.679 2.263 106.142 2.263 c
+106.602 2.263 106.969 2.094 107.244 1.764 c
+107.527 1.44 107.674 0.992 107.685 0.426 c
+107.685 0 l
+107.685 -0.57 107.543 -1.025 107.259 -1.367 c
+106.984 -1.702 106.616 -1.867 106.157 -1.867 c
+105.694 -1.867 105.322 -1.706 105.04 -1.382 c
+104.765 -1.052 104.621 -0.611 104.613 -0.059 c
+h
+105.26 0 m
+105.26 -0.405 105.337 -0.721 105.496 -0.956 c
+105.661 -1.191 105.881 -1.309 106.157 -1.309 c
+106.723 -1.309 107.017 -0.897 107.039 -0.073 c
+107.039 0.382 l
+107.039 0.783 106.955 1.103 106.789 1.338 c
+106.631 1.579 106.415 1.705 106.142 1.705 c
+105.877 1.705 105.661 1.579 105.496 1.338 c
+105.337 1.103 105.26 0.783 105.26 0.382 c
+h
+109.141 2.19 m
+109.156 1.749 l
+109.409 2.09 109.733 2.263 110.126 2.263 c
+110.831 2.263 111.188 1.793 111.198 0.852 c
+111.198 -1.794 l
+110.552 -1.794 l
+110.552 0.823 l
+110.552 1.135 110.496 1.356 110.39 1.484 c
+110.28 1.61 110.126 1.675 109.92 1.675 c
+109.762 1.675 109.615 1.62 109.479 1.514 c
+109.351 1.404 109.247 1.267 109.17 1.103 c
+109.17 -1.794 l
+108.524 -1.794 l
+108.524 2.19 l
+h
+113.594 -1.867 m
+113.095 -1.867 112.713 -1.72 112.448 -1.426 c
+112.183 -1.132 112.052 -0.699 112.052 -0.118 c
+112.052 0.353 l
+112.052 0.947 112.177 1.415 112.433 1.749 c
+112.698 2.09 113.058 2.263 113.521 2.263 c
+113.98 2.263 114.322 2.109 114.55 1.808 c
+114.785 1.514 114.907 1.051 114.918 0.426 c
+114.918 0 l
+112.698 0 l
+112.698 -0.088 l
+112.698 -0.522 112.775 -0.834 112.933 -1.029 c
+113.099 -1.216 113.33 -1.309 113.624 -1.309 c
+113.819 -1.309 113.991 -1.276 114.138 -1.206 c
+114.286 -1.129 114.421 -1.011 114.55 -0.853 c
+114.888 -1.264 l
+114.602 -1.669 114.172 -1.867 113.594 -1.867 c
+113.521 1.705 m
+113.245 1.705 113.043 1.61 112.919 1.425 c
+112.79 1.238 112.717 0.947 112.698 0.558 c
+114.271 0.558 l
+114.271 0.646 l
+114.249 1.028 114.182 1.297 114.065 1.455 c
+113.947 1.62 113.764 1.705 113.521 1.705 c
+118.504 -0.706 m
+119.225 2.19 l
+119.915 2.19 l
+118.622 -2.352 l
+118.523 -2.694 118.379 -2.955 118.195 -3.131 c
+118.019 -3.308 117.817 -3.396 117.592 -3.396 c
+117.505 -3.396 117.391 -3.373 117.255 -3.337 c
+117.255 -2.793 l
+117.401 -2.808 l
+117.586 -2.808 117.733 -2.764 117.843 -2.675 c
+117.949 -2.587 118.037 -2.429 118.107 -2.205 c
+118.225 -1.764 l
+117.064 2.19 l
+117.769 2.19 l
+h
+120.356 0.382 m
+120.356 0.959 120.492 1.415 120.767 1.749 c
+121.051 2.09 121.422 2.263 121.885 2.263 c
+122.344 2.263 122.712 2.094 122.988 1.764 c
+123.271 1.44 123.418 0.992 123.428 0.426 c
+123.428 0 l
+123.428 -0.57 123.285 -1.025 123.002 -1.367 c
+122.726 -1.702 122.359 -1.867 121.899 -1.867 c
+121.436 -1.867 121.066 -1.706 120.783 -1.382 c
+120.507 -1.052 120.364 -0.611 120.356 -0.059 c
+h
+121.003 0 m
+121.003 -0.405 121.08 -0.721 121.238 -0.956 c
+121.403 -1.191 121.624 -1.309 121.899 -1.309 c
+122.465 -1.309 122.76 -0.897 122.782 -0.073 c
+122.782 0.382 l
+122.782 0.783 122.697 1.103 122.531 1.338 c
+122.373 1.579 122.157 1.705 121.885 1.705 c
+121.621 1.705 121.403 1.579 121.238 1.338 c
+121.08 1.103 121.003 0.783 121.003 0.382 c
+h
+126.294 -1.441 m
+126.078 -1.727 125.766 -1.867 125.354 -1.867 c
+124.99 -1.867 124.715 -1.746 124.53 -1.5 c
+124.354 -1.246 124.259 -0.882 124.251 -0.412 c
+124.251 2.19 l
+124.898 2.19 l
+124.898 -0.353 l
+124.898 -0.981 125.082 -1.294 125.457 -1.294 c
+125.858 -1.294 126.132 -1.118 126.28 -0.765 c
+126.28 2.19 l
+126.926 2.19 l
+126.926 -1.794 l
+126.309 -1.794 l
+h
+131.674 -1.794 m
+131.634 -1.706 131.609 -1.559 131.601 -1.353 c
+131.366 -1.698 131.071 -1.867 130.719 -1.867 c
+130.355 -1.867 130.072 -1.771 129.866 -1.573 c
+129.668 -1.367 129.573 -1.081 129.573 -0.706 c
+129.573 -0.306 129.708 0.014 129.984 0.249 c
+130.256 0.492 130.631 0.617 131.102 0.617 c
+131.586 0.617 l
+131.586 1.043 l
+131.586 1.278 131.531 1.444 131.424 1.543 c
+131.314 1.65 131.152 1.705 130.94 1.705 c
+130.741 1.705 130.579 1.646 130.454 1.529 c
+130.337 1.411 130.278 1.263 130.278 1.087 c
+129.631 1.087 l
+129.631 1.282 129.69 1.473 129.808 1.66 c
+129.933 1.845 130.094 1.992 130.292 2.102 c
+130.498 2.208 130.726 2.263 130.984 2.263 c
+131.384 2.263 131.689 2.161 131.895 1.955 c
+132.108 1.749 132.222 1.455 132.233 1.072 c
+132.233 -0.941 l
+132.233 -1.246 132.27 -1.511 132.351 -1.735 c
+132.351 -1.794 l
+h
+130.807 -1.279 m
+130.973 -1.279 131.123 -1.235 131.263 -1.147 c
+131.41 -1.058 131.516 -0.948 131.586 -0.809 c
+131.586 0.132 l
+131.219 0.132 l
+130.903 0.132 130.66 0.062 130.483 -0.073 c
+130.307 -0.202 130.219 -0.389 130.219 -0.632 c
+130.219 -0.86 130.263 -1.025 130.352 -1.132 c
+130.44 -1.231 130.591 -1.279 130.807 -1.279 c
+134.879 1.573 m
+134.791 1.591 134.691 1.602 134.585 1.602 c
+134.25 1.602 134.015 1.418 133.88 1.058 c
+133.88 -1.794 l
+133.232 -1.794 l
+133.232 2.19 l
+133.864 2.19 l
+133.88 1.778 l
+134.055 2.102 134.298 2.263 134.614 2.263 c
+134.721 2.263 134.809 2.241 134.879 2.204 c
+h
+136.878 -1.867 m
+136.378 -1.867 135.996 -1.72 135.732 -1.426 c
+135.466 -1.132 135.335 -0.699 135.335 -0.118 c
+135.335 0.353 l
+135.335 0.947 135.46 1.415 135.717 1.749 c
+135.981 2.09 136.341 2.263 136.804 2.263 c
+137.263 2.263 137.606 2.109 137.833 1.808 c
+138.069 1.514 138.19 1.051 138.201 0.426 c
+138.201 0 l
+135.981 0 l
+135.981 -0.088 l
+135.981 -0.522 136.058 -0.834 136.216 -1.029 c
+136.382 -1.216 136.613 -1.309 136.908 -1.309 c
+137.102 -1.309 137.275 -1.276 137.421 -1.206 c
+137.569 -1.129 137.705 -1.011 137.833 -0.853 c
+138.171 -1.264 l
+137.885 -1.669 137.455 -1.867 136.878 -1.867 c
+136.804 1.705 m
+136.529 1.705 136.326 1.61 136.202 1.425 c
+136.073 1.238 136 0.947 135.981 0.558 c
+137.554 0.558 l
+137.554 0.646 l
+137.532 1.028 137.466 1.297 137.348 1.455 c
+137.23 1.62 137.047 1.705 136.804 1.705 c
+f
+Q
+q 1 0 0 1 727.8236 127.6454 cm
+0 0 m
+0 0.577 0.136 1.033 0.412 1.367 c
+0.695 1.708 1.066 1.881 1.529 1.881 c
+1.989 1.881 2.356 1.712 2.631 1.382 c
+2.914 1.058 3.061 0.61 3.072 0.044 c
+3.072 -0.382 l
+3.072 -0.952 2.93 -1.407 2.646 -1.749 c
+2.371 -2.084 2.003 -2.249 1.544 -2.249 c
+1.081 -2.249 0.709 -2.087 0.427 -1.764 c
+0.151 -1.434 0.008 -0.992 0 -0.441 c
+h
+0.647 -0.382 m
+0.647 -0.786 0.724 -1.103 0.883 -1.338 c
+1.048 -1.573 1.268 -1.691 1.544 -1.691 c
+2.11 -1.691 2.404 -1.278 2.426 -0.455 c
+2.426 0 l
+2.426 0.401 2.342 0.721 2.176 0.956 c
+2.018 1.198 1.802 1.323 1.529 1.323 c
+1.264 1.323 1.048 1.198 0.883 0.956 c
+0.724 0.721 0.647 0.401 0.647 0 c
+h
+4.528 1.808 m
+4.543 1.367 l
+4.796 1.708 5.12 1.881 5.513 1.881 c
+6.218 1.881 6.575 1.411 6.585 0.47 c
+6.585 -2.176 l
+5.939 -2.176 l
+5.939 0.441 l
+5.939 0.754 5.883 0.974 5.777 1.103 c
+5.667 1.228 5.513 1.294 5.307 1.294 c
+5.149 1.294 5.002 1.238 4.866 1.132 c
+4.738 1.022 4.634 0.885 4.557 0.721 c
+4.557 -2.176 l
+3.911 -2.176 l
+3.911 1.808 l
+h
+10.658 -1.691 m
+10.87 -1.691 11.043 -1.628 11.171 -1.5 c
+11.308 -1.363 11.381 -1.172 11.392 -0.926 c
+12.01 -0.926 l
+11.988 -1.309 11.852 -1.628 11.598 -1.881 c
+11.341 -2.128 11.028 -2.249 10.658 -2.249 c
+10.165 -2.249 9.79 -2.099 9.525 -1.793 c
+9.268 -1.481 9.143 -1.014 9.143 -0.397 c
+9.143 0.044 l
+9.143 0.64 9.268 1.095 9.525 1.411 c
+9.79 1.723 10.165 1.881 10.658 1.881 c
+11.057 1.881 11.377 1.749 11.612 1.484 c
+11.855 1.228 11.988 0.881 12.01 0.441 c
+11.392 0.441 l
+11.37 0.735 11.296 0.956 11.171 1.103 c
+11.054 1.249 10.882 1.323 10.658 1.323 c
+10.363 1.323 10.147 1.224 10.01 1.029 c
+9.871 0.841 9.798 0.532 9.79 0.103 c
+9.79 -0.412 l
+9.79 -0.882 9.856 -1.216 9.995 -1.411 c
+10.143 -1.598 10.363 -1.691 10.658 -1.691 c
+14.787 -1.823 m
+14.571 -2.109 14.259 -2.249 13.847 -2.249 c
+13.484 -2.249 13.208 -2.128 13.024 -1.881 c
+12.848 -1.628 12.752 -1.264 12.744 -0.794 c
+12.744 1.808 l
+13.391 1.808 l
+13.391 -0.735 l
+13.391 -1.363 13.575 -1.675 13.95 -1.675 c
+14.35 -1.675 14.626 -1.5 14.773 -1.147 c
+14.773 1.808 l
+15.42 1.808 l
+15.42 -2.176 l
+14.803 -2.176 l
+h
+18.051 1.191 m
+17.963 1.209 17.864 1.22 17.756 1.22 c
+17.423 1.22 17.187 1.036 17.051 0.676 c
+17.051 -2.176 l
+16.405 -2.176 l
+16.405 1.808 l
+17.037 1.808 l
+17.051 1.396 l
+17.228 1.72 17.471 1.881 17.787 1.881 c
+17.893 1.881 17.981 1.859 18.051 1.822 c
+h
+20.344 1.191 m
+20.256 1.209 20.156 1.22 20.05 1.22 c
+19.715 1.22 19.48 1.036 19.344 0.676 c
+19.344 -2.176 l
+18.697 -2.176 l
+18.697 1.808 l
+19.329 1.808 l
+19.344 1.396 l
+19.52 1.72 19.763 1.881 20.079 1.881 c
+20.185 1.881 20.274 1.859 20.344 1.822 c
+h
+22.343 -2.249 m
+21.843 -2.249 21.461 -2.102 21.197 -1.808 c
+20.931 -1.514 20.8 -1.081 20.8 -0.5 c
+20.8 -0.029 l
+20.8 0.565 20.925 1.033 21.182 1.367 c
+21.446 1.708 21.806 1.881 22.269 1.881 c
+22.729 1.881 23.071 1.727 23.298 1.426 c
+23.534 1.132 23.655 0.669 23.666 0.044 c
+23.666 -0.382 l
+21.446 -0.382 l
+21.446 -0.47 l
+21.446 -0.904 21.523 -1.216 21.681 -1.411 c
+21.847 -1.598 22.078 -1.691 22.373 -1.691 c
+22.567 -1.691 22.74 -1.658 22.887 -1.588 c
+23.034 -1.511 23.17 -1.393 23.298 -1.235 c
+23.636 -1.646 l
+23.35 -2.051 22.92 -2.249 22.343 -2.249 c
+22.269 1.323 m
+21.994 1.323 21.792 1.228 21.667 1.043 c
+21.538 0.856 21.465 0.565 21.446 0.176 c
+23.019 0.176 l
+23.019 0.264 l
+22.997 0.646 22.931 0.915 22.813 1.073 c
+22.695 1.238 22.512 1.323 22.269 1.323 c
+25.062 1.808 m
+25.077 1.367 l
+25.33 1.708 25.654 1.881 26.047 1.881 c
+26.753 1.881 27.109 1.411 27.121 0.47 c
+27.121 -2.176 l
+26.473 -2.176 l
+26.473 0.441 l
+26.473 0.754 26.419 0.974 26.312 1.103 c
+26.201 1.228 26.047 1.294 25.841 1.294 c
+25.683 1.294 25.536 1.238 25.4 1.132 c
+25.272 1.022 25.169 0.885 25.091 0.721 c
+25.091 -2.176 l
+24.445 -2.176 l
+24.445 1.808 l
+h
+28.796 -2.176 -0.647 5.644 re
+30.662 2.763 m
+30.662 1.808 l
+31.266 1.808 l
+31.266 1.278 l
+30.662 1.278 l
+30.662 -1.191 l
+30.662 -1.349 30.685 -1.467 30.736 -1.544 c
+30.795 -1.625 30.884 -1.661 31.001 -1.661 c
+31.089 -1.661 31.177 -1.646 31.266 -1.617 c
+31.266 -2.176 l
+31.119 -2.223 30.964 -2.249 30.809 -2.249 c
+30.552 -2.249 30.358 -2.157 30.221 -1.97 c
+30.082 -1.786 30.016 -1.525 30.016 -1.191 c
+30.016 1.278 l
+29.413 1.278 l
+29.413 1.808 l
+30.016 1.808 l
+30.016 2.763 l
+h
+33.118 -1.087 m
+33.837 1.808 l
+34.529 1.808 l
+33.235 -2.734 l
+33.136 -3.076 32.993 -3.337 32.808 -3.513 c
+32.632 -3.69 32.43 -3.778 32.206 -3.778 c
+32.118 -3.778 32.004 -3.755 31.868 -3.719 c
+31.868 -3.175 l
+32.015 -3.19 l
+32.199 -3.19 32.345 -3.146 32.456 -3.057 c
+32.563 -2.969 32.65 -2.811 32.721 -2.587 c
+32.838 -2.146 l
+31.677 1.808 l
+32.382 1.808 l
+h
+36.557 -0.044 m
+36.557 -1.132 36.311 -2.099 35.823 -2.94 c
+35.557 -3.389 35.282 -3.711 34.999 -3.91 c
+34.882 -3.484 l
+35.183 -3.19 35.429 -2.738 35.616 -2.132 c
+35.811 -1.525 35.91 -0.86 35.91 -0.133 c
+35.91 0 l
+35.91 0.929 35.756 1.764 35.455 2.499 c
+35.285 2.899 35.094 3.219 34.882 3.454 c
+34.999 3.865 l
+35.271 3.678 35.536 3.381 35.792 2.969 c
+36.299 2.117 36.557 1.11 36.557 -0.044 c
+37.6 -1.823 m
+37.6 -1.706 37.633 -1.61 37.704 -1.529 c
+37.77 -1.452 37.872 -1.411 38.013 -1.411 c
+38.159 -1.411 38.266 -1.452 38.335 -1.529 c
+38.413 -1.61 38.453 -1.706 38.453 -1.823 c
+38.453 -1.933 38.413 -2.024 38.335 -2.102 c
+38.266 -2.18 38.159 -2.219 38.013 -2.219 c
+37.872 -2.219 37.77 -2.18 37.704 -2.102 c
+37.633 -2.024 37.6 -1.933 37.6 -1.823 c
+f
+Q
+0.113 0.082 0.09 0 k
+535.667 120.241 238.665 -12.898 re
+f
+0.906 0.785 0.617 0.969 k
+q 1 0 0 1 540.8555 113.4016 cm
+0 0 m
+0 -0.187 -0.029 -0.353 -0.088 -0.5 c
+-0.147 -0.646 -0.242 -0.775 -0.367 -0.881 c
+-0.496 -0.992 -0.658 -1.08 -0.852 -1.146 c
+-1.051 -1.205 -1.278 -1.242 -1.543 -1.249 c
+-1.543 -1.808 l
+-1.896 -1.808 l
+-1.896 -1.263 l
+-2.142 -1.257 -2.358 -1.22 -2.543 -1.161 c
+-2.719 -1.103 -2.873 -1.025 -2.998 -0.926 c
+-3.127 -0.819 -3.23 -0.691 -3.307 -0.544 c
+-3.388 -0.389 -3.447 -0.213 -3.484 -0.014 c
+-2.66 0.133 l
+-2.642 0.033 -2.616 -0.058 -2.587 -0.147 c
+-2.55 -0.228 -2.506 -0.301 -2.454 -0.367 c
+-2.396 -0.426 -2.322 -0.478 -2.234 -0.515 c
+-2.138 -0.555 -2.024 -0.58 -1.896 -0.588 c
+-1.896 0.661 l
+-1.907 0.661 -1.926 0.665 -1.955 0.676 c
+-1.977 0.684 -1.992 0.691 -1.999 0.691 c
+-2.167 0.728 -2.329 0.772 -2.484 0.823 c
+-2.642 0.882 -2.786 0.96 -2.91 1.058 c
+-3.039 1.154 -3.141 1.279 -3.218 1.426 c
+-3.289 1.573 -3.322 1.756 -3.322 1.985 c
+-3.322 2.18 -3.289 2.344 -3.218 2.484 c
+-3.152 2.631 -3.054 2.749 -2.925 2.837 c
+-2.8 2.932 -2.645 3.003 -2.469 3.043 c
+-2.293 3.09 -2.102 3.12 -1.896 3.131 c
+-1.896 3.558 l
+-1.543 3.558 l
+-1.543 3.131 l
+-1.319 3.12 -1.128 3.09 -0.97 3.043 c
+-0.804 2.992 -0.669 2.918 -0.558 2.822 c
+-0.44 2.735 -0.349 2.62 -0.279 2.484 c
+-0.201 2.344 -0.143 2.183 -0.103 1.999 c
+-0.941 1.881 l
+-1.01 2.253 -1.213 2.459 -1.543 2.5 c
+-1.543 1.367 l
+-1.514 1.367 l
+-1.506 1.367 -1.492 1.36 -1.469 1.353 c
+-1.294 1.312 -1.117 1.264 -0.941 1.206 c
+-0.756 1.147 -0.595 1.066 -0.455 0.971 c
+-0.319 0.871 -0.213 0.742 -0.132 0.588 c
+-0.044 0.43 0 0.235 0 0 c
+-1.896 2.514 m
+-2.013 2.502 -2.113 2.484 -2.19 2.455 c
+-2.26 2.425 -2.318 2.385 -2.366 2.338 c
+-2.406 2.297 -2.436 2.249 -2.454 2.19 c
+-2.476 2.132 -2.484 2.066 -2.484 1.999 c
+-2.484 1.912 -2.469 1.837 -2.439 1.779 c
+-2.41 1.72 -2.373 1.669 -2.322 1.632 c
+-2.263 1.592 -2.2 1.559 -2.131 1.529 c
+-2.065 1.5 -1.984 1.47 -1.896 1.441 c
+h
+-0.837 -0.014 m
+-0.837 0.092 -0.86 0.177 -0.897 0.235 c
+-0.926 0.302 -0.977 0.357 -1.043 0.397 c
+-1.102 0.434 -1.176 0.47 -1.263 0.5 c
+-1.352 0.53 -1.448 0.559 -1.543 0.588 c
+-1.543 -0.588 l
+-1.319 -0.58 -1.146 -0.529 -1.028 -0.44 c
+-0.904 -0.345 -0.837 -0.202 -0.837 -0.014 c
+6.402 -2.66 m
+6.185 -2.66 5.993 -2.635 5.829 -2.587 c
+5.659 -2.547 5.52 -2.484 5.403 -2.396 c
+5.285 -2.315 5.185 -2.219 5.108 -2.102 c
+5.039 -1.984 4.991 -1.855 4.961 -1.72 c
+5.858 -1.616 l
+5.895 -1.753 5.964 -1.859 6.064 -1.94 c
+6.159 -2.028 6.284 -2.072 6.431 -2.072 c
+6.519 -2.072 6.6 -2.057 6.681 -2.028 c
+6.758 -1.999 6.828 -1.944 6.887 -1.866 c
+6.945 -1.797 6.99 -1.705 7.019 -1.587 c
+7.056 -1.469 7.078 -1.323 7.078 -1.146 c
+7.078 -0.955 l
+7.078 -0.889 7.082 -0.831 7.092 -0.779 c
+7.092 -0.588 l
+7.078 -0.588 l
+6.978 -0.816 6.835 -0.977 6.652 -1.072 c
+6.464 -1.172 6.259 -1.22 6.034 -1.22 c
+5.829 -1.22 5.644 -1.183 5.49 -1.103 c
+5.343 -1.014 5.214 -0.897 5.108 -0.75 c
+5.009 -0.595 4.935 -0.411 4.888 -0.205 c
+4.836 0.008 4.815 0.243 4.815 0.5 c
+4.815 0.772 4.836 1.018 4.888 1.235 c
+4.946 1.448 5.027 1.632 5.137 1.779 c
+5.245 1.933 5.376 2.051 5.534 2.132 c
+5.689 2.22 5.876 2.264 6.093 2.264 c
+6.189 2.264 6.288 2.253 6.387 2.234 c
+6.483 2.213 6.571 2.18 6.652 2.132 c
+6.739 2.08 6.817 2.018 6.887 1.941 c
+6.964 1.86 7.026 1.768 7.078 1.661 c
+7.092 1.661 l
+7.092 1.808 l
+7.1 1.867 7.107 1.918 7.107 1.97 c
+7.115 2.029 7.122 2.076 7.122 2.117 c
+7.13 2.165 7.14 2.198 7.151 2.22 c
+8.004 2.22 l
+7.992 2.139 7.982 2.029 7.975 1.881 c
+7.975 1.411 l
+7.975 -1.161 l
+7.975 -1.415 7.938 -1.635 7.872 -1.822 c
+7.802 -2.007 7.699 -2.161 7.563 -2.278 c
+7.423 -2.403 7.258 -2.499 7.063 -2.557 c
+6.865 -2.624 6.644 -2.66 6.402 -2.66 c
+7.092 0.53 m
+7.092 0.742 7.067 0.919 7.019 1.058 c
+6.978 1.206 6.924 1.324 6.857 1.411 c
+6.799 1.5 6.729 1.559 6.652 1.588 c
+6.571 1.625 6.494 1.646 6.417 1.646 c
+6.317 1.646 6.226 1.621 6.137 1.573 c
+6.056 1.532 5.991 1.463 5.931 1.367 c
+5.88 1.279 5.835 1.162 5.799 1.014 c
+5.77 0.875 5.755 0.706 5.755 0.5 c
+5.755 0.125 5.814 -0.154 5.931 -0.338 c
+6.049 -0.515 6.211 -0.602 6.417 -0.602 c
+6.483 -0.602 6.556 -0.588 6.637 -0.558 c
+6.725 -0.521 6.799 -0.463 6.857 -0.382 c
+6.924 -0.294 6.978 -0.176 7.019 -0.029 c
+7.067 0.118 7.092 0.302 7.092 0.53 c
+11.036 -0.646 m
+12.168 -0.646 l
+12.168 -1.263 l
+8.86 -1.263 l
+8.86 -0.646 l
+10.124 -0.646 l
+10.124 1.602 l
+9.199 1.602 l
+9.199 2.22 l
+11.036 2.22 l
+h
+10.124 3.514 0.912 -0.676 re
+10.124 2.837 m
+13.6 1.602 m
+13.057 1.602 l
+13.057 2.22 l
+13.644 2.22 l
+13.924 3.117 l
+14.498 3.117 l
+14.498 2.22 l
+15.732 2.22 l
+15.732 1.602 l
+14.498 1.602 l
+14.498 -0.103 l
+14.498 -0.323 l
+14.504 -0.393 14.527 -0.455 14.556 -0.515 c
+14.593 -0.565 14.648 -0.61 14.718 -0.646 c
+14.795 -0.675 14.909 -0.691 15.056 -0.691 c
+15.192 -0.691 15.327 -0.687 15.468 -0.675 c
+15.603 -0.658 15.736 -0.632 15.865 -0.602 c
+15.865 -1.205 l
+15.784 -1.216 15.707 -1.23 15.629 -1.249 c
+15.549 -1.261 15.471 -1.267 15.394 -1.278 c
+15.313 -1.286 15.225 -1.294 15.129 -1.294 c
+15.042 -1.301 14.942 -1.308 14.836 -1.308 c
+14.648 -1.308 14.486 -1.294 14.35 -1.263 c
+14.222 -1.227 14.107 -1.183 14.012 -1.132 c
+13.924 -1.084 13.85 -1.025 13.792 -0.955 c
+13.733 -0.878 13.689 -0.801 13.66 -0.72 c
+13.63 -0.632 13.608 -0.544 13.6 -0.455 c
+13.59 -0.36 13.586 -0.264 13.586 -0.176 c
+h
+21.12 -1.263 m
+21.12 -0.97 l
+21.126 -0.833 21.134 -0.675 21.134 -0.5 c
+21.134 3.514 l
+22.045 3.514 l
+22.045 2.234 l
+22.045 2.072 l
+22.045 1.897 l
+22.045 1.845 22.038 1.801 22.03 1.764 c
+22.03 1.676 l
+22.045 1.676 l
+22.093 1.783 22.155 1.874 22.236 1.955 c
+22.313 2.032 22.398 2.095 22.487 2.147 c
+22.574 2.194 22.666 2.227 22.766 2.249 c
+22.861 2.267 22.961 2.278 23.059 2.278 c
+23.273 2.278 23.46 2.234 23.618 2.147 c
+23.773 2.058 23.901 1.929 24 1.764 c
+24.106 1.606 24.184 1.415 24.235 1.191 c
+24.283 0.974 24.309 0.736 24.309 0.47 c
+24.309 0.214 24.28 -0.025 24.22 -0.249 c
+24.162 -0.467 24.077 -0.658 23.971 -0.823 c
+23.861 -0.981 23.728 -1.103 23.574 -1.19 c
+23.416 -1.278 23.236 -1.323 23.03 -1.323 c
+22.931 -1.323 22.832 -1.311 22.736 -1.294 c
+22.648 -1.271 22.56 -1.242 22.471 -1.19 c
+22.383 -1.132 22.302 -1.066 22.236 -0.985 c
+22.167 -0.908 22.104 -0.808 22.045 -0.691 c
+22.03 -0.691 l
+22.03 -0.852 l
+22.03 -0.911 22.024 -0.97 22.016 -1.028 c
+22.016 -1.08 22.009 -1.128 22.001 -1.176 c
+22.001 -1.216 21.994 -1.246 21.986 -1.263 c
+h
+22.03 0.5 m
+22.03 0.265 22.049 0.067 22.09 -0.087 c
+22.137 -0.246 22.196 -0.367 22.265 -0.455 c
+22.332 -0.544 22.406 -0.61 22.487 -0.646 c
+22.564 -0.687 22.641 -0.706 22.722 -0.706 c
+22.927 -0.706 23.082 -0.61 23.192 -0.411 c
+23.31 -0.216 23.368 0.077 23.368 0.47 c
+23.368 0.684 23.346 0.867 23.31 1.014 c
+23.28 1.168 23.236 1.294 23.177 1.382 c
+23.125 1.478 23.059 1.551 22.971 1.602 c
+22.89 1.65 22.803 1.676 22.707 1.676 c
+22.626 1.676 22.549 1.654 22.471 1.617 c
+22.391 1.577 22.317 1.515 22.251 1.426 c
+22.192 1.338 22.137 1.213 22.09 1.058 c
+22.049 0.912 22.03 0.724 22.03 0.5 c
+28.193 1.47 m
+28.094 1.478 27.991 1.488 27.884 1.5 c
+27.774 1.518 27.653 1.529 27.517 1.529 c
+27.341 1.529 27.183 1.488 27.046 1.411 c
+26.907 1.341 26.789 1.243 26.693 1.118 c
+26.606 0.989 26.535 0.842 26.488 0.676 c
+26.448 0.507 26.429 0.331 26.429 0.148 c
+26.429 -1.263 l
+25.533 -1.263 l
+25.533 0.985 l
+25.533 1.11 25.521 1.235 25.503 1.353 c
+25.492 1.478 25.477 1.595 25.459 1.706 c
+25.448 1.823 25.434 1.918 25.415 1.999 c
+25.393 2.087 25.375 2.161 25.356 2.22 c
+26.238 2.22 l
+26.246 2.168 26.257 2.117 26.267 2.058 c
+26.286 1.999 26.3 1.933 26.312 1.867 c
+26.33 1.808 26.344 1.742 26.356 1.676 c
+26.363 1.606 26.375 1.544 26.385 1.484 c
+26.4 1.484 l
+26.437 1.602 26.488 1.709 26.547 1.808 c
+26.613 1.904 26.693 1.989 26.782 2.058 c
+26.87 2.124 26.973 2.18 27.09 2.22 c
+27.216 2.257 27.362 2.278 27.532 2.278 c
+27.657 2.278 27.774 2.271 27.884 2.264 c
+28.002 2.253 28.105 2.238 28.193 2.22 c
+h
+30.196 -1.323 m
+30.026 -1.323 29.876 -1.301 29.741 -1.263 c
+29.612 -1.216 29.498 -1.146 29.402 -1.058 c
+29.314 -0.97 29.244 -0.864 29.197 -0.735 c
+29.145 -0.598 29.122 -0.448 29.122 -0.279 c
+29.122 -0.073 29.156 0.096 29.226 0.235 c
+29.292 0.383 29.388 0.493 29.505 0.574 c
+29.63 0.661 29.773 0.724 29.932 0.765 c
+30.097 0.801 30.273 0.827 30.46 0.838 c
+31.181 0.853 l
+31.181 1.029 l
+31.181 1.147 31.169 1.249 31.152 1.338 c
+31.129 1.426 31.096 1.492 31.048 1.544 c
+31.008 1.602 30.961 1.639 30.901 1.661 c
+30.843 1.679 30.776 1.691 30.71 1.691 c
+30.641 1.691 30.578 1.679 30.519 1.661 c
+30.468 1.65 30.42 1.625 30.373 1.588 c
+30.332 1.559 30.298 1.507 30.269 1.441 c
+30.248 1.382 30.233 1.301 30.225 1.206 c
+29.284 1.249 l
+29.314 1.397 29.358 1.532 29.417 1.661 c
+29.483 1.786 29.579 1.897 29.696 1.985 c
+29.814 2.08 29.953 2.153 30.122 2.205 c
+30.298 2.253 30.504 2.278 30.74 2.278 c
+31.181 2.278 31.511 2.168 31.74 1.955 c
+31.975 1.75 32.092 1.441 32.092 1.029 c
+32.092 -0.235 l
+32.092 -0.455 l
+32.099 -0.515 32.114 -0.569 32.137 -0.617 c
+32.154 -0.658 32.184 -0.691 32.224 -0.72 c
+32.261 -0.742 32.313 -0.75 32.372 -0.75 c
+32.438 -0.75 32.507 -0.746 32.577 -0.735 c
+32.577 -1.22 l
+32.519 -1.23 32.463 -1.242 32.415 -1.249 c
+32.375 -1.261 32.334 -1.267 32.297 -1.278 c
+32.257 -1.286 32.214 -1.294 32.166 -1.294 c
+32.114 -1.301 32.056 -1.308 31.989 -1.308 c
+31.761 -1.308 31.596 -1.257 31.489 -1.146 c
+31.379 -1.028 31.316 -0.864 31.298 -0.646 c
+31.283 -0.646 l
+31.214 -0.756 31.144 -0.852 31.078 -0.941 c
+31.008 -1.022 30.931 -1.087 30.843 -1.146 c
+30.755 -1.205 30.655 -1.249 30.549 -1.278 c
+30.45 -1.308 30.332 -1.323 30.196 -1.323 c
+31.181 0.353 m
+30.755 0.339 l
+30.655 0.339 30.564 0.331 30.475 0.324 c
+30.394 0.312 30.328 0.287 30.269 0.25 c
+30.211 0.21 30.159 0.151 30.122 0.073 c
+30.082 0.004 30.063 -0.087 30.063 -0.205 c
+30.063 -0.374 30.097 -0.496 30.167 -0.573 c
+30.233 -0.654 30.332 -0.691 30.46 -0.691 c
+30.567 -0.691 30.666 -0.669 30.755 -0.617 c
+30.85 -0.569 30.931 -0.507 30.99 -0.426 c
+31.056 -0.349 31.107 -0.261 31.137 -0.162 c
+31.166 -0.055 31.181 0.059 31.181 0.177 c
+h
+35.495 -1.263 m
+35.495 0.721 l
+35.495 1.022 35.451 1.243 35.362 1.382 c
+35.281 1.529 35.146 1.602 34.951 1.602 c
+34.841 1.602 34.738 1.577 34.643 1.529 c
+34.554 1.478 34.473 1.411 34.408 1.324 c
+34.348 1.235 34.297 1.125 34.26 1 c
+34.231 0.882 34.216 0.75 34.216 0.603 c
+34.216 -1.263 l
+33.305 -1.263 l
+33.305 1.441 l
+33.305 1.661 l
+33.305 1.75 33.297 1.827 33.29 1.897 c
+33.29 2.087 l
+33.29 2.22 l
+34.142 2.22 l
+34.15 2.19 34.157 2.147 34.157 2.087 c
+34.157 1.897 l
+34.165 1.827 34.172 1.756 34.172 1.691 c
+34.179 1.621 34.186 1.565 34.186 1.529 c
+34.202 1.529 l
+34.319 1.794 34.47 1.985 34.657 2.103 c
+34.841 2.22 35.061 2.278 35.318 2.278 c
+35.503 2.278 35.664 2.249 35.804 2.19 c
+35.939 2.132 36.054 2.043 36.141 1.926 c
+36.23 1.808 36.293 1.665 36.332 1.5 c
+36.38 1.341 36.407 1.154 36.407 0.941 c
+36.407 -1.263 l
+h
+38.923 -1.323 m
+38.637 -1.323 38.394 -1.282 38.188 -1.205 c
+37.982 -1.117 37.81 -0.995 37.674 -0.837 c
+37.535 -0.683 37.431 -0.496 37.365 -0.279 c
+37.296 -0.055 37.263 0.191 37.263 0.456 c
+37.263 0.75 37.296 1.008 37.365 1.235 c
+37.442 1.459 37.549 1.646 37.689 1.794 c
+37.836 1.948 38.012 2.066 38.218 2.147 c
+38.424 2.234 38.659 2.278 38.923 2.278 c
+39.148 2.278 39.35 2.249 39.526 2.19 c
+39.702 2.132 39.854 2.047 39.981 1.941 c
+40.107 1.841 40.21 1.72 40.291 1.573 c
+40.368 1.434 40.423 1.283 40.452 1.118 c
+39.541 1.073 l
+39.511 1.249 39.441 1.389 39.335 1.5 c
+39.235 1.606 39.092 1.661 38.909 1.661 c
+38.662 1.661 38.487 1.559 38.379 1.353 c
+38.269 1.154 38.218 0.867 38.218 0.485 c
+38.218 -0.309 38.453 -0.706 38.923 -0.706 c
+39.089 -0.706 39.232 -0.654 39.35 -0.544 c
+39.467 -0.437 39.541 -0.276 39.57 -0.058 c
+40.482 -0.103 l
+40.452 -0.272 40.397 -0.426 40.32 -0.573 c
+40.25 -0.72 40.147 -0.852 40.012 -0.97 c
+39.883 -1.08 39.725 -1.168 39.541 -1.234 c
+39.364 -1.294 39.158 -1.323 38.923 -1.323 c
+42.323 1.515 m
+42.441 1.786 42.591 1.985 42.778 2.103 c
+42.962 2.22 43.183 2.278 43.44 2.278 c
+43.646 2.278 43.815 2.242 43.954 2.176 c
+44.101 2.106 44.211 2.014 44.292 1.897 c
+44.38 1.779 44.44 1.636 44.469 1.47 c
+44.505 1.301 44.527 1.125 44.527 0.941 c
+44.527 -1.263 l
+43.616 -1.263 l
+43.616 0.736 l
+43.616 0.871 43.605 0.992 43.586 1.103 c
+43.576 1.209 43.55 1.297 43.513 1.367 c
+43.473 1.444 43.414 1.503 43.337 1.544 c
+43.267 1.58 43.175 1.602 43.058 1.602 c
+42.948 1.602 42.852 1.577 42.763 1.529 c
+42.676 1.478 42.595 1.411 42.528 1.324 c
+42.47 1.235 42.418 1.125 42.381 1 c
+42.352 0.882 42.337 0.75 42.337 0.603 c
+42.337 -1.263 l
+41.426 -1.263 l
+41.426 3.514 l
+42.337 3.514 l
+42.337 2.205 l
+42.337 2.135 42.329 2.066 42.323 1.999 c
+42.323 1.794 l
+42.323 1.735 42.315 1.679 42.308 1.632 c
+42.308 1.515 l
+h
+50.135 0.838 1.867 -0.794 re
+50.135 0.044 m
+55.787 -1.263 m
+55.776 -1.246 55.765 -1.216 55.758 -1.176 c
+55.758 -1.128 55.75 -1.08 55.743 -1.028 c
+55.743 -0.97 55.735 -0.911 55.728 -0.852 c
+55.728 -0.691 l
+55.611 -0.926 55.467 -1.095 55.302 -1.19 c
+55.133 -1.278 54.935 -1.323 54.699 -1.323 c
+54.501 -1.323 54.324 -1.278 54.17 -1.19 c
+54.012 -1.103 53.88 -0.981 53.774 -0.823 c
+53.674 -0.658 53.597 -0.467 53.538 -0.249 c
+53.487 -0.037 53.464 0.206 53.464 0.47 c
+53.464 0.736 53.487 0.974 53.538 1.191 c
+53.597 1.415 53.674 1.606 53.774 1.764 c
+53.88 1.918 54.012 2.043 54.17 2.132 c
+54.335 2.227 54.526 2.278 54.744 2.278 c
+54.839 2.278 54.935 2.264 55.023 2.234 c
+55.118 2.213 55.214 2.18 55.302 2.132 c
+55.39 2.08 55.467 2.018 55.538 1.941 c
+55.615 1.86 55.677 1.768 55.728 1.661 c
+55.728 1.75 l
+55.728 1.897 l
+55.728 2.058 l
+55.728 2.234 l
+55.728 3.514 l
+56.625 3.514 l
+56.625 -0.5 l
+56.625 -0.675 56.629 -0.833 56.639 -0.97 c
+56.647 -1.099 56.654 -1.198 56.654 -1.263 c
+h
+55.743 0.485 m
+55.743 0.721 55.717 0.912 55.669 1.058 c
+55.629 1.213 55.574 1.338 55.507 1.426 c
+55.449 1.515 55.379 1.573 55.302 1.602 c
+55.221 1.639 55.144 1.661 55.067 1.661 c
+54.967 1.661 54.875 1.636 54.788 1.588 c
+54.707 1.548 54.64 1.478 54.582 1.382 c
+54.53 1.283 54.486 1.162 54.449 1.014 c
+54.42 0.867 54.405 0.684 54.405 0.47 c
+54.405 0.077 54.457 -0.216 54.567 -0.411 c
+54.684 -0.61 54.846 -0.706 55.052 -0.706 c
+55.129 -0.706 55.206 -0.687 55.287 -0.646 c
+55.364 -0.61 55.438 -0.544 55.507 -0.455 c
+55.574 -0.367 55.629 -0.246 55.669 -0.087 c
+55.717 0.067 55.743 0.258 55.743 0.485 c
+62.482 -2.631 m
+62.482 3.514 l
+64.408 3.514 l
+64.408 2.896 l
+63.335 2.896 l
+63.335 -2.013 l
+64.408 -2.013 l
+64.408 -2.631 l
+h
+67.983 -1.263 m
+67.983 0.721 l
+67.983 1.022 67.939 1.243 67.851 1.382 c
+67.77 1.529 67.634 1.602 67.44 1.602 c
+67.33 1.602 67.226 1.577 67.131 1.529 c
+67.043 1.478 66.962 1.411 66.896 1.324 c
+66.837 1.235 66.786 1.125 66.748 1 c
+66.719 0.882 66.705 0.75 66.705 0.603 c
+66.705 -1.263 l
+65.793 -1.263 l
+65.793 1.441 l
+65.793 1.661 l
+65.793 1.75 65.786 1.827 65.778 1.897 c
+65.778 2.087 l
+65.778 2.22 l
+66.632 2.22 l
+66.638 2.19 66.646 2.147 66.646 2.087 c
+66.646 1.897 l
+66.653 1.827 66.661 1.756 66.661 1.691 c
+66.668 1.621 66.675 1.565 66.675 1.529 c
+66.69 1.529 l
+66.808 1.794 66.958 1.985 67.145 2.103 c
+67.33 2.22 67.55 2.278 67.808 2.278 c
+67.991 2.278 68.153 2.249 68.292 2.19 c
+68.428 2.132 68.542 2.043 68.63 1.926 c
+68.718 1.808 68.781 1.665 68.822 1.5 c
+68.869 1.341 68.895 1.154 68.895 0.941 c
+68.895 -1.263 l
+h
+70.81 -1.323 m
+70.64 -1.323 70.49 -1.301 70.354 -1.263 c
+70.225 -1.216 70.111 -1.146 70.015 -1.058 c
+69.927 -0.97 69.857 -0.864 69.809 -0.735 c
+69.759 -0.598 69.736 -0.448 69.736 -0.279 c
+69.736 -0.073 69.769 0.096 69.84 0.235 c
+69.905 0.383 70.001 0.493 70.119 0.574 c
+70.243 0.661 70.387 0.724 70.545 0.765 c
+70.71 0.801 70.887 0.827 71.074 0.838 c
+71.794 0.853 l
+71.794 1.029 l
+71.794 1.147 71.783 1.249 71.765 1.338 c
+71.743 1.426 71.71 1.492 71.662 1.544 c
+71.621 1.602 71.573 1.639 71.515 1.661 c
+71.456 1.679 71.39 1.691 71.324 1.691 c
+71.254 1.691 71.191 1.679 71.133 1.661 c
+71.081 1.65 71.033 1.625 70.985 1.588 c
+70.945 1.559 70.912 1.507 70.883 1.441 c
+70.861 1.382 70.846 1.301 70.839 1.206 c
+69.898 1.249 l
+69.927 1.397 69.971 1.532 70.031 1.661 c
+70.096 1.786 70.192 1.897 70.31 1.985 c
+70.428 2.08 70.567 2.153 70.736 2.205 c
+70.912 2.253 71.118 2.278 71.353 2.278 c
+71.794 2.278 72.125 2.168 72.353 1.955 c
+72.588 1.75 72.706 1.441 72.706 1.029 c
+72.706 -0.235 l
+72.706 -0.455 l
+72.713 -0.515 72.728 -0.569 72.749 -0.617 c
+72.768 -0.658 72.797 -0.691 72.838 -0.72 c
+72.874 -0.742 72.926 -0.75 72.984 -0.75 c
+73.051 -0.75 73.121 -0.746 73.19 -0.735 c
+73.19 -1.22 l
+73.132 -1.23 73.077 -1.242 73.029 -1.249 c
+72.988 -1.261 72.948 -1.267 72.911 -1.278 c
+72.871 -1.286 72.826 -1.294 72.779 -1.294 c
+72.728 -1.301 72.668 -1.308 72.602 -1.308 c
+72.375 -1.308 72.209 -1.257 72.103 -1.146 c
+71.993 -1.028 71.93 -0.864 71.912 -0.646 c
+71.897 -0.646 l
+71.827 -0.756 71.758 -0.852 71.691 -0.941 c
+71.621 -1.022 71.544 -1.087 71.456 -1.146 c
+71.368 -1.205 71.269 -1.249 71.162 -1.278 c
+71.063 -1.308 70.945 -1.323 70.81 -1.323 c
+71.794 0.353 m
+71.368 0.339 l
+71.269 0.339 71.177 0.331 71.089 0.324 c
+71.008 0.312 70.942 0.287 70.883 0.25 c
+70.825 0.21 70.773 0.151 70.736 0.073 c
+70.696 0.004 70.677 -0.087 70.677 -0.205 c
+70.677 -0.374 70.71 -0.496 70.78 -0.573 c
+70.846 -0.654 70.945 -0.691 71.074 -0.691 c
+71.18 -0.691 71.28 -0.669 71.368 -0.617 c
+71.463 -0.569 71.544 -0.507 71.603 -0.426 c
+71.669 -0.349 71.721 -0.261 71.75 -0.162 c
+71.779 -0.055 71.794 0.059 71.794 0.177 c
+h
+75.079 -1.263 m
+75.079 0.853 l
+75.079 1.018 75.072 1.154 75.064 1.264 c
+75.054 1.371 75.035 1.455 75.006 1.515 c
+74.984 1.58 74.954 1.632 74.918 1.661 c
+74.889 1.691 74.848 1.706 74.8 1.706 c
+74.742 1.706 74.686 1.676 74.638 1.617 c
+74.598 1.565 74.565 1.492 74.536 1.397 c
+74.507 1.309 74.48 1.195 74.462 1.058 c
+74.451 0.919 74.447 0.769 74.447 0.603 c
+74.447 -1.263 l
+73.698 -1.263 l
+73.698 1.47 l
+73.698 1.706 l
+73.698 1.926 l
+73.698 2.003 73.69 2.066 73.683 2.117 c
+73.683 2.22 l
+74.359 2.22 l
+74.359 2.132 l
+74.359 1.985 l
+74.366 1.926 74.374 1.867 74.374 1.808 c
+74.374 1.646 l
+74.389 1.646 l
+74.407 1.735 74.436 1.812 74.476 1.881 c
+74.513 1.959 74.557 2.029 74.609 2.087 c
+74.667 2.147 74.734 2.19 74.815 2.22 c
+74.892 2.257 74.98 2.278 75.079 2.278 c
+75.263 2.278 75.403 2.224 75.491 2.117 c
+75.586 2.018 75.656 1.86 75.697 1.646 c
+75.712 1.646 l
+75.748 1.742 75.789 1.831 75.829 1.912 c
+75.877 1.989 75.932 2.051 75.991 2.103 c
+76.049 2.161 76.116 2.205 76.196 2.234 c
+76.274 2.264 76.362 2.278 76.461 2.278 c
+76.597 2.278 76.711 2.253 76.799 2.205 c
+76.888 2.153 76.953 2.08 77.005 1.985 c
+77.063 1.885 77.1 1.756 77.123 1.602 c
+77.152 1.455 77.167 1.272 77.167 1.058 c
+77.167 -1.263 l
+76.446 -1.263 l
+76.446 0.853 l
+76.446 1.018 76.439 1.154 76.431 1.264 c
+76.421 1.371 76.402 1.455 76.373 1.515 c
+76.351 1.58 76.321 1.632 76.285 1.661 c
+76.255 1.691 76.215 1.706 76.167 1.706 c
+76.049 1.706 75.954 1.617 75.888 1.441 c
+75.829 1.272 75.8 1.014 75.8 0.661 c
+75.8 -1.263 l
+h
+79.537 -1.323 m
+79.28 -1.323 79.052 -1.286 78.846 -1.22 c
+78.64 -1.143 78.464 -1.028 78.317 -0.881 c
+78.17 -0.727 78.052 -0.536 77.964 -0.309 c
+77.883 -0.085 77.846 0.181 77.846 0.485 c
+77.846 0.816 77.89 1.095 77.979 1.324 c
+78.075 1.559 78.203 1.742 78.361 1.881 c
+78.526 2.018 78.714 2.117 78.92 2.176 c
+79.126 2.242 79.334 2.278 79.552 2.278 c
+79.824 2.278 80.059 2.227 80.257 2.132 c
+80.463 2.043 80.628 1.912 80.757 1.735 c
+80.893 1.565 80.992 1.36 81.051 1.118 c
+81.117 0.882 81.154 0.618 81.154 0.324 c
+81.154 0.309 l
+78.787 0.309 l
+78.787 0.162 78.802 0.023 78.831 -0.103 c
+78.868 -0.231 78.923 -0.345 78.993 -0.44 c
+79.059 -0.529 79.143 -0.598 79.243 -0.646 c
+79.338 -0.698 79.452 -0.72 79.581 -0.72 c
+79.735 -0.72 79.875 -0.687 79.993 -0.617 c
+80.117 -0.551 80.206 -0.448 80.257 -0.309 c
+81.095 -0.382 l
+81.065 -0.481 81.011 -0.588 80.934 -0.706 c
+80.853 -0.816 80.749 -0.918 80.624 -1.014 c
+80.508 -1.103 80.352 -1.176 80.169 -1.234 c
+79.993 -1.294 79.779 -1.323 79.537 -1.323 c
+79.537 1.706 m
+79.448 1.706 79.361 1.691 79.272 1.661 c
+79.184 1.632 79.103 1.58 79.037 1.515 c
+78.968 1.444 78.908 1.357 78.861 1.249 c
+78.821 1.139 78.802 1.014 78.802 0.867 c
+80.272 0.867 l
+80.272 1.004 80.246 1.125 80.198 1.235 c
+80.158 1.341 80.103 1.43 80.037 1.5 c
+79.978 1.565 79.905 1.617 79.816 1.646 c
+79.728 1.683 79.633 1.706 79.537 1.706 c
+82.407 -2.631 m
+82.407 -2.013 l
+83.48 -2.013 l
+83.48 2.896 l
+82.407 2.896 l
+82.407 3.514 l
+84.333 3.514 l
+84.333 -2.631 l
+h
+f
+Q
+q 1 0 0 1 545.482 99.4081 cm
+0 0 m
+-0.941 0 l
+-0.941 -2.161 l
+-1.616 -2.161 l
+-1.616 3.19 l
+-0.118 3.19 l
+0.412 3.19 0.809 3.05 1.073 2.778 c
+1.345 2.502 1.484 2.106 1.484 1.588 c
+1.484 1.253 1.411 0.963 1.264 0.721 c
+1.118 0.474 0.912 0.287 0.647 0.162 c
+1.676 -2.117 l
+1.676 -2.161 l
+0.956 -2.161 l
+h
+-0.941 0.588 m
+-0.118 0.588 l
+0.166 0.588 0.389 0.676 0.559 0.853 c
+0.724 1.037 0.809 1.283 0.809 1.588 c
+0.809 2.271 0.493 2.617 -0.132 2.617 c
+-0.941 2.617 l
+h
+3.719 -2.234 m
+3.219 -2.234 2.837 -2.087 2.573 -1.793 c
+2.308 -1.499 2.176 -1.066 2.176 -0.484 c
+2.176 -0.014 l
+2.176 0.58 2.301 1.048 2.558 1.382 c
+2.822 1.723 3.183 1.897 3.645 1.897 c
+4.105 1.897 4.447 1.742 4.675 1.441 c
+4.91 1.147 5.031 0.684 5.042 0.059 c
+5.042 -0.367 l
+2.822 -0.367 l
+2.822 -0.455 l
+2.822 -0.889 2.899 -1.201 3.057 -1.396 c
+3.223 -1.583 3.454 -1.675 3.749 -1.675 c
+3.944 -1.675 4.116 -1.643 4.263 -1.573 c
+4.41 -1.496 4.546 -1.378 4.675 -1.22 c
+5.012 -1.631 l
+4.726 -2.036 4.296 -2.234 3.719 -2.234 c
+3.645 1.338 m
+3.37 1.338 3.168 1.243 3.043 1.058 c
+2.914 0.871 2.841 0.58 2.822 0.191 c
+4.395 0.191 l
+4.395 0.279 l
+4.374 0.661 4.307 0.93 4.189 1.088 c
+4.072 1.253 3.888 1.338 3.645 1.338 c
+6.438 1.823 m
+6.454 1.455 l
+6.696 1.75 7.015 1.897 7.408 1.897 c
+7.85 1.897 8.158 1.698 8.335 1.309 c
+8.588 1.698 8.937 1.897 9.378 1.897 c
+10.113 1.897 10.488 1.434 10.51 0.515 c
+10.51 -2.161 l
+9.864 -2.161 l
+9.864 0.456 l
+9.864 0.75 9.808 0.963 9.702 1.103 c
+9.602 1.239 9.43 1.309 9.187 1.309 c
+8.989 1.309 8.827 1.228 8.702 1.073 c
+8.584 0.927 8.515 0.736 8.497 0.5 c
+8.497 -2.161 l
+7.834 -2.161 l
+7.834 0.485 l
+7.834 1.033 7.614 1.309 7.173 1.309 c
+6.839 1.309 6.604 1.147 6.468 0.823 c
+6.468 -2.161 l
+5.821 -2.161 l
+5.821 1.823 l
+h
+11.348 0.015 m
+11.348 0.592 11.484 1.048 11.759 1.382 c
+12.042 1.723 12.414 1.897 12.877 1.897 c
+13.336 1.897 13.704 1.727 13.979 1.397 c
+14.263 1.073 14.409 0.625 14.42 0.059 c
+14.42 -0.367 l
+14.42 -0.937 14.277 -1.392 13.994 -1.734 c
+13.718 -2.069 13.351 -2.234 12.891 -2.234 c
+12.428 -2.234 12.057 -2.072 11.774 -1.749 c
+11.499 -1.419 11.356 -0.977 11.348 -0.426 c
+h
+11.994 -0.367 m
+11.994 -0.771 12.072 -1.087 12.23 -1.323 c
+12.395 -1.558 12.616 -1.675 12.891 -1.675 c
+13.457 -1.675 13.752 -1.263 13.773 -0.44 c
+13.773 0.015 l
+13.773 0.416 13.689 0.736 13.523 0.971 c
+13.365 1.213 13.149 1.338 12.877 1.338 c
+12.613 1.338 12.395 1.213 12.23 0.971 c
+12.072 0.736 11.994 0.416 11.994 0.015 c
+h
+16.331 -1.176 m
+17.081 1.823 l
+17.742 1.823 l
+16.566 -2.161 l
+16.081 -2.161 l
+14.89 1.823 l
+15.552 1.823 l
+h
+19.8 -2.234 m
+19.3 -2.234 18.918 -2.087 18.653 -1.793 c
+18.389 -1.499 18.257 -1.066 18.257 -0.484 c
+18.257 -0.014 l
+18.257 0.58 18.381 1.048 18.639 1.382 c
+18.903 1.723 19.264 1.897 19.726 1.897 c
+20.185 1.897 20.528 1.742 20.756 1.441 c
+20.991 1.147 21.112 0.684 21.122 0.059 c
+21.122 -0.367 l
+18.903 -0.367 l
+18.903 -0.455 l
+18.903 -0.889 18.98 -1.201 19.138 -1.396 c
+19.304 -1.583 19.535 -1.675 19.829 -1.675 c
+20.024 -1.675 20.197 -1.643 20.344 -1.573 c
+20.491 -1.496 20.627 -1.378 20.756 -1.22 c
+21.093 -1.631 l
+20.807 -2.036 20.377 -2.234 19.8 -2.234 c
+19.726 1.338 m
+19.451 1.338 19.248 1.243 19.123 1.058 c
+18.995 0.871 18.922 0.58 18.903 0.191 c
+20.476 0.191 l
+20.476 0.279 l
+20.455 0.661 20.388 0.93 20.27 1.088 c
+20.153 1.253 19.969 1.338 19.726 1.338 c
+25.562 -1.146 m
+25.562 -0.999 25.507 -0.878 25.4 -0.779 c
+25.29 -0.683 25.084 -0.565 24.783 -0.426 c
+24.438 -0.279 24.195 -0.158 24.048 -0.058 c
+23.901 0.048 23.79 0.166 23.724 0.294 c
+23.655 0.42 23.622 0.578 23.622 0.765 c
+23.622 1.088 23.74 1.357 23.975 1.573 c
+24.21 1.786 24.511 1.897 24.885 1.897 c
+25.268 1.897 25.577 1.783 25.812 1.559 c
+26.047 1.33 26.165 1.044 26.165 0.691 c
+25.518 0.691 l
+25.518 0.867 25.459 1.018 25.342 1.147 c
+25.224 1.272 25.07 1.338 24.885 1.338 c
+24.688 1.338 24.536 1.283 24.43 1.176 c
+24.32 1.077 24.268 0.945 24.268 0.779 c
+24.268 0.651 24.305 0.544 24.386 0.456 c
+24.463 0.375 24.654 0.272 24.96 0.148 c
+25.437 -0.04 25.768 -0.228 25.944 -0.411 c
+26.121 -0.588 26.209 -0.816 26.209 -1.087 c
+26.209 -1.44 26.084 -1.72 25.841 -1.926 c
+25.606 -2.131 25.29 -2.234 24.9 -2.234 c
+24.478 -2.234 24.14 -2.117 23.886 -1.881 c
+23.63 -1.639 23.504 -1.334 23.504 -0.97 c
+24.151 -0.97 l
+24.158 -1.198 24.228 -1.374 24.357 -1.499 c
+24.482 -1.616 24.665 -1.675 24.9 -1.675 c
+25.114 -1.675 25.276 -1.627 25.386 -1.529 c
+25.503 -1.433 25.562 -1.304 25.562 -1.146 c
+28.472 -2.234 m
+27.973 -2.234 27.59 -2.087 27.326 -1.793 c
+27.061 -1.499 26.929 -1.066 26.929 -0.484 c
+26.929 -0.014 l
+26.929 0.58 27.054 1.048 27.312 1.382 c
+27.576 1.723 27.936 1.897 28.399 1.897 c
+28.858 1.897 29.2 1.742 29.428 1.441 c
+29.663 1.147 29.785 0.684 29.795 0.059 c
+29.795 -0.367 l
+27.576 -0.367 l
+27.576 -0.455 l
+27.576 -0.889 27.653 -1.201 27.811 -1.396 c
+27.977 -1.583 28.208 -1.675 28.502 -1.675 c
+28.696 -1.675 28.869 -1.643 29.016 -1.573 c
+29.163 -1.496 29.299 -1.378 29.428 -1.22 c
+29.766 -1.631 l
+29.479 -2.036 29.049 -2.234 28.472 -2.234 c
+28.399 1.338 m
+28.123 1.338 27.921 1.243 27.796 1.058 c
+27.668 0.871 27.594 0.58 27.576 0.191 c
+29.149 0.191 l
+29.149 0.279 l
+29.126 0.661 29.06 0.93 28.943 1.088 c
+28.825 1.253 28.642 1.338 28.399 1.338 c
+31.28 -2.161 -0.646 5.644 re
+33.72 -2.234 m
+33.22 -2.234 32.838 -2.087 32.573 -1.793 c
+32.309 -1.499 32.176 -1.066 32.176 -0.484 c
+32.176 -0.014 l
+32.176 0.58 32.301 1.048 32.559 1.382 c
+32.823 1.723 33.184 1.897 33.647 1.897 c
+34.106 1.897 34.448 1.742 34.676 1.441 c
+34.911 1.147 35.032 0.684 35.043 0.059 c
+35.043 -0.367 l
+32.823 -0.367 l
+32.823 -0.455 l
+32.823 -0.889 32.901 -1.201 33.059 -1.396 c
+33.224 -1.583 33.456 -1.675 33.749 -1.675 c
+33.944 -1.675 34.117 -1.643 34.264 -1.573 c
+34.41 -1.496 34.547 -1.378 34.676 -1.22 c
+35.013 -1.631 l
+34.726 -2.036 34.297 -2.234 33.72 -2.234 c
+33.647 1.338 m
+33.371 1.338 33.169 1.243 33.043 1.058 c
+32.916 0.871 32.842 0.58 32.823 0.191 c
+34.396 0.191 l
+34.396 0.279 l
+34.374 0.661 34.308 0.93 34.19 1.088 c
+34.073 1.253 33.889 1.338 33.647 1.338 c
+37.203 -1.675 m
+37.417 -1.675 37.589 -1.613 37.718 -1.484 c
+37.854 -1.348 37.928 -1.157 37.938 -0.911 c
+38.556 -0.911 l
+38.534 -1.294 38.398 -1.613 38.144 -1.866 c
+37.887 -2.113 37.575 -2.234 37.203 -2.234 c
+36.711 -2.234 36.336 -2.084 36.072 -1.778 c
+35.815 -1.466 35.69 -0.999 35.69 -0.382 c
+35.69 0.059 l
+35.69 0.655 35.815 1.11 36.072 1.426 c
+36.336 1.738 36.711 1.897 37.203 1.897 c
+37.604 1.897 37.924 1.764 38.159 1.5 c
+38.402 1.243 38.534 0.897 38.556 0.456 c
+37.938 0.456 l
+37.917 0.75 37.843 0.971 37.718 1.118 c
+37.6 1.264 37.427 1.338 37.203 1.338 c
+36.91 1.338 36.693 1.239 36.557 1.044 c
+36.417 0.856 36.344 0.548 36.336 0.118 c
+36.336 -0.397 l
+36.336 -0.867 36.403 -1.201 36.542 -1.396 c
+36.689 -1.583 36.91 -1.675 37.203 -1.675 c
+40.158 2.778 m
+40.158 1.823 l
+40.76 1.823 l
+40.76 1.294 l
+40.158 1.294 l
+40.158 -1.176 l
+40.158 -1.334 40.18 -1.452 40.232 -1.529 c
+40.29 -1.61 40.378 -1.646 40.496 -1.646 c
+40.584 -1.646 40.673 -1.631 40.76 -1.602 c
+40.76 -2.161 l
+40.614 -2.208 40.459 -2.234 40.305 -2.234 c
+40.048 -2.234 39.854 -2.142 39.717 -1.955 c
+39.578 -1.771 39.511 -1.51 39.511 -1.176 c
+39.511 1.294 l
+38.909 1.294 l
+38.909 1.823 l
+39.511 1.823 l
+39.511 2.778 l
+h
+42.951 -2.234 m
+42.451 -2.234 42.069 -2.087 41.805 -1.793 c
+41.54 -1.499 41.408 -1.066 41.408 -0.484 c
+41.408 -0.014 l
+41.408 0.58 41.533 1.048 41.79 1.382 c
+42.054 1.723 42.414 1.897 42.877 1.897 c
+43.337 1.897 43.679 1.742 43.906 1.441 c
+44.141 1.147 44.263 0.684 44.274 0.059 c
+44.274 -0.367 l
+42.054 -0.367 l
+42.054 -0.455 l
+42.054 -0.889 42.131 -1.201 42.289 -1.396 c
+42.455 -1.583 42.686 -1.675 42.981 -1.675 c
+43.175 -1.675 43.347 -1.643 43.495 -1.573 c
+43.642 -1.496 43.777 -1.378 43.906 -1.22 c
+44.245 -1.631 l
+43.958 -2.036 43.528 -2.234 42.951 -2.234 c
+42.877 1.338 m
+42.601 1.338 42.4 1.243 42.275 1.058 c
+42.146 0.871 42.073 0.58 42.054 0.191 c
+43.627 0.191 l
+43.627 0.279 l
+43.605 0.661 43.539 0.93 43.422 1.088 c
+43.304 1.253 43.12 1.338 42.877 1.338 c
+44.92 0.015 m
+44.92 0.621 45.031 1.088 45.259 1.411 c
+45.494 1.735 45.821 1.897 46.244 1.897 c
+46.626 1.897 46.923 1.738 47.141 1.426 c
+47.141 3.484 l
+47.787 3.484 l
+47.787 -2.161 l
+47.199 -2.161 l
+47.155 -1.734 l
+46.95 -2.069 46.644 -2.234 46.244 -2.234 c
+45.832 -2.234 45.508 -2.08 45.273 -1.764 c
+45.038 -1.44 44.92 -0.985 44.92 -0.397 c
+h
+45.568 -0.367 m
+45.568 -0.808 45.63 -1.139 45.759 -1.352 c
+45.894 -1.558 46.115 -1.66 46.42 -1.66 c
+46.744 -1.66 46.982 -1.499 47.141 -1.176 c
+47.141 0.838 l
+46.971 1.151 46.732 1.309 46.42 1.309 c
+46.115 1.309 45.894 1.206 45.759 1 c
+45.63 0.794 45.568 0.47 45.568 0.03 c
+h
+53.387 -0.367 m
+53.387 -0.985 53.273 -1.452 53.049 -1.764 c
+52.833 -2.08 52.509 -2.234 52.079 -2.234 c
+51.657 -2.234 51.344 -2.054 51.139 -1.691 c
+51.109 -2.161 l
+50.506 -2.161 l
+50.506 3.484 l
+51.153 3.484 l
+51.153 1.382 l
+51.366 1.723 51.675 1.897 52.079 1.897 c
+52.509 1.897 52.833 1.738 53.049 1.426 c
+53.273 1.121 53.387 0.655 53.387 0.03 c
+h
+52.741 0.015 m
+52.741 0.485 52.671 0.816 52.535 1.014 c
+52.406 1.209 52.197 1.309 51.902 1.309 c
+51.569 1.309 51.318 1.125 51.153 0.765 c
+51.153 -1.117 l
+51.318 -1.481 51.572 -1.66 51.918 -1.66 c
+52.211 -1.66 52.421 -1.558 52.55 -1.352 c
+52.675 -1.146 52.741 -0.831 52.741 -0.397 c
+h
+55.872 1.206 m
+55.783 1.224 55.684 1.235 55.577 1.235 c
+55.243 1.235 55.008 1.051 54.871 0.691 c
+54.871 -2.161 l
+54.225 -2.161 l
+54.225 1.823 l
+54.857 1.823 l
+54.871 1.411 l
+55.048 1.735 55.291 1.897 55.607 1.897 c
+55.713 1.897 55.802 1.874 55.872 1.837 c
+h
+58.414 -2.161 m
+58.374 -2.072 58.348 -1.926 58.341 -1.72 c
+58.106 -2.065 57.811 -2.234 57.458 -2.234 c
+57.095 -2.234 56.812 -2.138 56.606 -1.94 c
+56.408 -1.734 56.313 -1.448 56.313 -1.072 c
+56.313 -0.673 56.448 -0.353 56.724 -0.118 c
+56.996 0.125 57.371 0.25 57.841 0.25 c
+58.326 0.25 l
+58.326 0.676 l
+58.326 0.912 58.271 1.077 58.164 1.176 c
+58.054 1.283 57.892 1.338 57.68 1.338 c
+57.481 1.338 57.319 1.279 57.194 1.162 c
+57.077 1.044 57.018 0.897 57.018 0.721 c
+56.371 0.721 l
+56.371 0.915 56.43 1.106 56.548 1.294 c
+56.673 1.478 56.834 1.625 57.032 1.735 c
+57.238 1.841 57.466 1.897 57.724 1.897 c
+58.124 1.897 58.429 1.794 58.634 1.588 c
+58.848 1.382 58.962 1.088 58.973 0.706 c
+58.973 -1.308 l
+58.973 -1.613 59.01 -1.878 59.091 -2.102 c
+59.091 -2.161 l
+h
+57.547 -1.646 m
+57.713 -1.646 57.863 -1.602 58.003 -1.514 c
+58.15 -1.425 58.256 -1.315 58.326 -1.176 c
+58.326 -0.235 l
+57.959 -0.235 l
+57.643 -0.235 57.4 -0.305 57.223 -0.44 c
+57.047 -0.569 56.959 -0.756 56.959 -0.999 c
+56.959 -1.227 57.003 -1.392 57.092 -1.499 c
+57.18 -1.598 57.331 -1.646 57.547 -1.646 c
+60.59 1.823 m
+60.604 1.382 l
+60.858 1.723 61.181 1.897 61.574 1.897 c
+62.28 1.897 62.636 1.426 62.648 0.485 c
+62.648 -2.161 l
+62.001 -2.161 l
+62.001 0.456 l
+62.001 0.769 61.946 0.989 61.84 1.118 c
+61.729 1.243 61.574 1.309 61.369 1.309 c
+61.211 1.309 61.064 1.253 60.928 1.147 c
+60.799 1.037 60.697 0.9 60.619 0.736 c
+60.619 -2.161 l
+59.972 -2.161 l
+59.972 1.823 l
+h
+64.999 -1.675 m
+65.213 -1.675 65.385 -1.613 65.514 -1.484 c
+65.65 -1.348 65.724 -1.157 65.734 -0.911 c
+66.352 -0.911 l
+66.33 -1.294 66.194 -1.613 65.94 -1.866 c
+65.683 -2.113 65.371 -2.234 64.999 -2.234 c
+64.508 -2.234 64.132 -2.084 63.868 -1.778 c
+63.611 -1.466 63.486 -0.999 63.486 -0.382 c
+63.486 0.059 l
+63.486 0.655 63.611 1.11 63.868 1.426 c
+64.132 1.738 64.508 1.897 64.999 1.897 c
+65.4 1.897 65.72 1.764 65.955 1.5 c
+66.198 1.243 66.33 0.897 66.352 0.456 c
+65.734 0.456 l
+65.713 0.75 65.639 0.971 65.514 1.118 c
+65.396 1.264 65.223 1.338 64.999 1.338 c
+64.706 1.338 64.489 1.239 64.353 1.044 c
+64.213 0.856 64.14 0.548 64.132 0.118 c
+64.132 -0.397 l
+64.132 -0.867 64.199 -1.201 64.338 -1.396 c
+64.485 -1.583 64.706 -1.675 64.999 -1.675 c
+67.748 1.411 m
+68.001 1.735 68.321 1.897 68.704 1.897 c
+69.41 1.897 69.766 1.426 69.777 0.485 c
+69.777 -2.161 l
+69.13 -2.161 l
+69.13 0.456 l
+69.13 0.769 69.075 0.989 68.969 1.118 c
+68.858 1.243 68.704 1.309 68.498 1.309 c
+68.34 1.309 68.193 1.253 68.057 1.147 c
+67.928 1.037 67.825 0.9 67.748 0.736 c
+67.748 -2.161 l
+67.101 -2.161 l
+67.101 3.484 l
+67.748 3.484 l
+h
+70.746 -3.233 m
+70.35 -2.969 l
+70.586 -2.645 70.707 -2.311 70.717 -1.969 c
+70.717 -1.352 l
+71.379 -1.352 l
+71.379 -1.881 l
+71.379 -2.138 71.313 -2.385 71.188 -2.631 c
+71.07 -2.873 70.923 -3.075 70.746 -3.233 c
+74.642 -2.161 -0.646 3.984 re
+74.686 2.866 m
+74.686 2.756 74.657 2.664 74.598 2.587 c
+74.54 2.517 74.444 2.484 74.318 2.484 c
+74.201 2.484 74.106 2.517 74.039 2.587 c
+73.981 2.664 73.952 2.756 73.952 2.866 c
+73.952 2.984 73.981 3.076 74.039 3.146 c
+74.106 3.223 74.201 3.263 74.318 3.263 c
+74.444 3.263 74.54 3.223 74.598 3.146 c
+74.657 3.065 74.686 2.973 74.686 2.866 c
+75.951 -2.161 m
+75.951 1.294 l
+75.421 1.294 l
+75.421 1.823 l
+75.951 1.823 l
+75.951 2.278 l
+75.951 2.679 76.046 2.992 76.244 3.219 c
+76.45 3.443 76.73 3.558 77.082 3.558 c
+77.218 3.558 77.35 3.535 77.479 3.499 c
+77.449 2.955 l
+77.35 2.973 77.252 2.984 77.156 2.984 c
+76.781 2.984 76.597 2.72 76.597 2.19 c
+76.597 1.823 l
+77.273 1.823 l
+77.273 1.294 l
+76.597 1.294 l
+76.597 -2.161 l
+h
+80.463 -2.161 -0.647 3.984 re
+80.507 2.866 m
+80.507 2.756 80.477 2.664 80.419 2.587 c
+80.36 2.517 80.265 2.484 80.14 2.484 c
+80.022 2.484 79.926 2.517 79.86 2.587 c
+79.801 2.664 79.772 2.756 79.772 2.866 c
+79.772 2.984 79.801 3.076 79.86 3.146 c
+79.926 3.223 80.022 3.263 80.14 3.263 c
+80.265 3.263 80.36 3.223 80.419 3.146 c
+80.477 3.065 80.507 2.973 80.507 2.866 c
+82.33 2.778 m
+82.33 1.823 l
+82.933 1.823 l
+82.933 1.294 l
+82.33 1.294 l
+82.33 -1.176 l
+82.33 -1.334 82.351 -1.452 82.403 -1.529 c
+82.462 -1.61 82.55 -1.646 82.667 -1.646 c
+82.756 -1.646 82.844 -1.631 82.933 -1.602 c
+82.933 -2.161 l
+82.785 -2.208 82.631 -2.234 82.477 -2.234 c
+82.22 -2.234 82.025 -2.142 81.889 -1.955 c
+81.749 -1.771 81.683 -1.51 81.683 -1.176 c
+81.683 1.294 l
+81.081 1.294 l
+81.081 1.823 l
+81.683 1.823 l
+81.683 2.778 l
+h
+86.122 -2.161 -0.646 3.984 re
+86.166 2.866 m
+86.166 2.756 86.137 2.664 86.078 2.587 c
+86.019 2.517 85.923 2.484 85.798 2.484 c
+85.681 2.484 85.586 2.517 85.52 2.587 c
+85.461 2.664 85.431 2.756 85.431 2.866 c
+85.431 2.984 85.461 3.076 85.52 3.146 c
+85.586 3.223 85.681 3.263 85.798 3.263 c
+85.923 3.263 86.019 3.223 86.078 3.146 c
+86.137 3.065 86.166 2.973 86.166 2.866 c
+89.077 -1.146 m
+89.077 -0.999 89.021 -0.878 88.915 -0.779 c
+88.805 -0.683 88.599 -0.565 88.298 -0.426 c
+87.953 -0.279 87.71 -0.158 87.562 -0.058 c
+87.415 0.048 87.305 0.166 87.24 0.294 c
+87.17 0.42 87.136 0.578 87.136 0.765 c
+87.136 1.088 87.254 1.357 87.489 1.573 c
+87.724 1.786 88.026 1.897 88.4 1.897 c
+88.782 1.897 89.091 1.783 89.326 1.559 c
+89.561 1.33 89.679 1.044 89.679 0.691 c
+89.033 0.691 l
+89.033 0.867 88.973 1.018 88.856 1.147 c
+88.738 1.272 88.584 1.338 88.4 1.338 c
+88.202 1.338 88.051 1.283 87.945 1.176 c
+87.835 1.077 87.783 0.945 87.783 0.779 c
+87.783 0.651 87.82 0.544 87.901 0.456 c
+87.978 0.375 88.169 0.272 88.474 0.148 c
+88.952 -0.04 89.283 -0.228 89.459 -0.411 c
+89.636 -0.588 89.723 -0.816 89.723 -1.087 c
+89.723 -1.44 89.599 -1.72 89.356 -1.926 c
+89.121 -2.131 88.805 -2.234 88.415 -2.234 c
+87.992 -2.234 87.654 -2.117 87.401 -1.881 c
+87.143 -1.639 87.018 -1.334 87.018 -0.97 c
+87.666 -0.97 l
+87.673 -1.198 87.743 -1.374 87.872 -1.499 c
+87.996 -1.616 88.18 -1.675 88.415 -1.675 c
+88.628 -1.675 88.79 -1.627 88.9 -1.529 c
+89.017 -1.433 89.077 -1.304 89.077 -1.146 c
+94.324 -2.161 m
+94.284 -2.072 94.258 -1.926 94.251 -1.72 c
+94.016 -2.065 93.721 -2.234 93.368 -2.234 c
+93.005 -2.234 92.722 -2.138 92.516 -1.94 c
+92.318 -1.734 92.223 -1.448 92.223 -1.072 c
+92.223 -0.673 92.358 -0.353 92.634 -0.118 c
+92.906 0.125 93.281 0.25 93.751 0.25 c
+94.236 0.25 l
+94.236 0.676 l
+94.236 0.912 94.181 1.077 94.074 1.176 c
+93.964 1.283 93.802 1.338 93.59 1.338 c
+93.391 1.338 93.229 1.279 93.104 1.162 c
+92.986 1.044 92.928 0.897 92.928 0.721 c
+92.281 0.721 l
+92.281 0.915 92.34 1.106 92.458 1.294 c
+92.582 1.478 92.744 1.625 92.942 1.735 c
+93.148 1.841 93.376 1.897 93.634 1.897 c
+94.034 1.897 94.339 1.794 94.544 1.588 c
+94.758 1.382 94.872 1.088 94.883 0.706 c
+94.883 -1.308 l
+94.883 -1.613 94.92 -1.878 95.001 -2.102 c
+95.001 -2.161 l
+h
+93.457 -1.646 m
+93.622 -1.646 93.773 -1.602 93.912 -1.514 c
+94.06 -1.425 94.166 -1.315 94.236 -1.176 c
+94.236 -0.235 l
+93.869 -0.235 l
+93.553 -0.235 93.31 -0.305 93.133 -0.44 c
+92.957 -0.569 92.869 -0.756 92.869 -0.999 c
+92.869 -1.227 92.913 -1.392 93.002 -1.499 c
+93.089 -1.598 93.24 -1.646 93.457 -1.646 c
+96.588 -2.161 -0.646 5.644 re
+99.248 1.206 m
+99.161 1.224 99.061 1.235 98.955 1.235 c
+98.62 1.235 98.384 1.051 98.249 0.691 c
+98.249 -2.161 l
+97.602 -2.161 l
+97.602 1.823 l
+98.234 1.823 l
+98.249 1.411 l
+98.425 1.735 98.668 1.897 98.984 1.897 c
+99.09 1.897 99.178 1.874 99.248 1.837 c
+h
+101.247 -2.234 m
+100.748 -2.234 100.366 -2.087 100.101 -1.793 c
+99.836 -1.499 99.704 -1.066 99.704 -0.484 c
+99.704 -0.014 l
+99.704 0.58 99.829 1.048 100.086 1.382 c
+100.351 1.723 100.711 1.897 101.174 1.897 c
+101.633 1.897 101.975 1.742 102.203 1.441 c
+102.438 1.147 102.559 0.684 102.571 0.059 c
+102.571 -0.367 l
+100.351 -0.367 l
+100.351 -0.455 l
+100.351 -0.889 100.428 -1.201 100.586 -1.396 c
+100.751 -1.583 100.983 -1.675 101.277 -1.675 c
+101.472 -1.675 101.644 -1.643 101.791 -1.573 c
+101.939 -1.496 102.074 -1.378 102.203 -1.22 c
+102.541 -1.631 l
+102.255 -2.036 101.825 -2.234 101.247 -2.234 c
+101.174 1.338 m
+100.898 1.338 100.696 1.243 100.572 1.058 c
+100.443 0.871 100.369 0.58 100.351 0.191 c
+101.923 0.191 l
+101.923 0.279 l
+101.902 0.661 101.835 0.93 101.717 1.088 c
+101.6 1.253 101.416 1.338 101.174 1.338 c
+105.393 -2.161 m
+105.352 -2.072 105.326 -1.926 105.319 -1.72 c
+105.083 -2.065 104.79 -2.234 104.437 -2.234 c
+104.073 -2.234 103.79 -2.138 103.585 -1.94 c
+103.386 -1.734 103.29 -1.448 103.29 -1.072 c
+103.29 -0.673 103.427 -0.353 103.702 -0.118 c
+103.974 0.125 104.349 0.25 104.819 0.25 c
+105.305 0.25 l
+105.305 0.676 l
+105.305 0.912 105.249 1.077 105.143 1.176 c
+105.033 1.283 104.871 1.338 104.657 1.338 c
+104.459 1.338 104.298 1.279 104.173 1.162 c
+104.055 1.044 103.996 0.897 103.996 0.721 c
+103.35 0.721 l
+103.35 0.915 103.408 1.106 103.526 1.294 c
+103.651 1.478 103.813 1.625 104.011 1.735 c
+104.217 1.841 104.445 1.897 104.701 1.897 c
+105.102 1.897 105.407 1.794 105.613 1.588 c
+105.827 1.382 105.94 1.088 105.951 0.706 c
+105.951 -1.308 l
+105.951 -1.613 105.987 -1.878 106.068 -2.102 c
+106.068 -2.161 l
+h
+104.526 -1.646 m
+104.69 -1.646 104.842 -1.602 104.981 -1.514 c
+105.128 -1.425 105.235 -1.315 105.305 -1.176 c
+105.305 -0.235 l
+104.937 -0.235 l
+104.621 -0.235 104.378 -0.305 104.202 -0.44 c
+104.025 -0.569 103.938 -0.756 103.938 -0.999 c
+103.938 -1.227 103.982 -1.392 104.069 -1.499 c
+104.158 -1.598 104.308 -1.646 104.526 -1.646 c
+106.818 0.015 m
+106.818 0.621 106.928 1.088 107.157 1.411 c
+107.392 1.735 107.718 1.897 108.141 1.897 c
+108.524 1.897 108.821 1.738 109.038 1.426 c
+109.038 3.484 l
+109.685 3.484 l
+109.685 -2.161 l
+109.097 -2.161 l
+109.052 -1.734 l
+108.846 -2.069 108.542 -2.234 108.141 -2.234 c
+107.73 -2.234 107.406 -2.08 107.171 -1.764 c
+106.936 -1.44 106.818 -0.985 106.818 -0.397 c
+h
+107.465 -0.367 m
+107.465 -0.808 107.527 -1.139 107.656 -1.352 c
+107.792 -1.558 108.013 -1.66 108.318 -1.66 c
+108.641 -1.66 108.88 -1.499 109.038 -1.176 c
+109.038 0.838 l
+108.869 1.151 108.63 1.309 108.318 1.309 c
+108.013 1.309 107.792 1.206 107.656 1 c
+107.527 0.794 107.465 0.47 107.465 0.03 c
+h
+111.772 -1.072 m
+112.492 1.823 l
+113.183 1.823 l
+111.89 -2.719 l
+111.79 -3.061 111.647 -3.322 111.464 -3.498 c
+111.287 -3.675 111.084 -3.763 110.86 -3.763 c
+110.772 -3.763 110.658 -3.74 110.523 -3.704 c
+110.523 -3.16 l
+110.67 -3.175 l
+110.853 -3.175 111.001 -3.131 111.111 -3.042 c
+111.217 -2.954 111.305 -2.796 111.375 -2.572 c
+111.493 -2.131 l
+110.332 1.823 l
+111.037 1.823 l
+h
+116.152 1.823 m
+116.167 1.455 l
+116.41 1.75 116.729 1.897 117.122 1.897 c
+117.563 1.897 117.872 1.698 118.049 1.309 c
+118.302 1.698 118.651 1.897 119.092 1.897 c
+119.827 1.897 120.202 1.434 120.224 0.515 c
+120.224 -2.161 l
+119.577 -2.161 l
+119.577 0.456 l
+119.577 0.75 119.522 0.963 119.416 1.103 c
+119.316 1.239 119.144 1.309 118.901 1.309 c
+118.703 1.309 118.541 1.228 118.416 1.073 c
+118.298 0.927 118.228 0.736 118.211 0.5 c
+118.211 -2.161 l
+117.548 -2.161 l
+117.548 0.485 l
+117.548 1.033 117.328 1.309 116.887 1.309 c
+116.553 1.309 116.318 1.147 116.181 0.823 c
+116.181 -2.161 l
+115.535 -2.161 l
+115.535 1.823 l
+h
+122.62 -2.234 m
+122.12 -2.234 121.738 -2.087 121.473 -1.793 c
+121.209 -1.499 121.076 -1.066 121.076 -0.484 c
+121.076 -0.014 l
+121.076 0.58 121.201 1.048 121.459 1.382 c
+121.723 1.723 122.084 1.897 122.546 1.897 c
+123.005 1.897 123.348 1.742 123.576 1.441 c
+123.811 1.147 123.932 0.684 123.942 0.059 c
+123.942 -0.367 l
+121.723 -0.367 l
+121.723 -0.455 l
+121.723 -0.889 121.8 -1.201 121.958 -1.396 c
+122.124 -1.583 122.355 -1.675 122.649 -1.675 c
+122.844 -1.675 123.017 -1.643 123.164 -1.573 c
+123.31 -1.496 123.447 -1.378 123.576 -1.22 c
+123.913 -1.631 l
+123.626 -2.036 123.196 -2.234 122.62 -2.234 c
+122.546 1.338 m
+122.271 1.338 122.068 1.243 121.943 1.058 c
+121.815 0.871 121.742 0.58 121.723 0.191 c
+123.296 0.191 l
+123.296 0.279 l
+123.274 0.661 123.208 0.93 123.09 1.088 c
+122.973 1.253 122.789 1.338 122.546 1.338 c
+126.368 1.206 m
+126.28 1.224 126.18 1.235 126.074 1.235 c
+125.74 1.235 125.505 1.051 125.369 0.691 c
+125.369 -2.161 l
+124.721 -2.161 l
+124.721 1.823 l
+125.354 1.823 l
+125.369 1.411 l
+125.544 1.735 125.787 1.897 126.103 1.897 c
+126.211 1.897 126.298 1.874 126.368 1.837 c
+h
+126.809 0.015 m
+126.809 0.632 126.919 1.095 127.148 1.411 c
+127.371 1.735 127.705 1.897 128.147 1.897 c
+128.547 1.897 128.852 1.72 129.058 1.367 c
+129.102 1.823 l
+129.69 1.823 l
+129.69 -2.204 l
+129.69 -2.693 129.561 -3.072 129.307 -3.337 c
+129.051 -3.601 128.698 -3.733 128.249 -3.733 c
+128.052 -3.733 127.831 -3.682 127.588 -3.586 c
+127.342 -3.487 127.162 -3.366 127.044 -3.219 c
+127.308 -2.778 l
+127.574 -3.042 127.871 -3.175 128.206 -3.175 c
+128.742 -3.175 129.018 -2.881 129.029 -2.293 c
+129.029 -1.764 l
+128.823 -2.08 128.522 -2.234 128.132 -2.234 c
+127.72 -2.234 127.397 -2.084 127.162 -1.778 c
+126.934 -1.466 126.816 -1.014 126.809 -0.426 c
+h
+127.47 -0.367 m
+127.47 -0.808 127.533 -1.139 127.661 -1.352 c
+127.786 -1.558 128.004 -1.66 128.308 -1.66 c
+128.632 -1.66 128.871 -1.496 129.029 -1.161 c
+129.029 0.823 l
+128.86 1.147 128.621 1.309 128.308 1.309 c
+128.014 1.309 127.798 1.206 127.661 1 c
+127.533 0.794 127.47 0.47 127.47 0.03 c
+h
+132.071 -2.234 m
+131.572 -2.234 131.189 -2.087 130.925 -1.793 c
+130.66 -1.499 130.528 -1.066 130.528 -0.484 c
+130.528 -0.014 l
+130.528 0.58 130.653 1.048 130.911 1.382 c
+131.175 1.723 131.535 1.897 131.998 1.897 c
+132.457 1.897 132.799 1.742 133.027 1.441 c
+133.262 1.147 133.383 0.684 133.394 0.059 c
+133.394 -0.367 l
+131.175 -0.367 l
+131.175 -0.455 l
+131.175 -0.889 131.252 -1.201 131.41 -1.396 c
+131.576 -1.583 131.807 -1.675 132.101 -1.675 c
+132.295 -1.675 132.468 -1.643 132.615 -1.573 c
+132.762 -1.496 132.898 -1.378 133.027 -1.22 c
+133.365 -1.631 l
+133.078 -2.036 132.648 -2.234 132.071 -2.234 c
+131.998 1.338 m
+131.722 1.338 131.52 1.243 131.395 1.058 c
+131.266 0.871 131.193 0.58 131.175 0.191 c
+132.748 0.191 l
+132.748 0.279 l
+132.725 0.661 132.659 0.93 132.542 1.088 c
+132.424 1.253 132.241 1.338 131.998 1.338 c
+134.041 0.015 m
+134.041 0.621 134.151 1.088 134.379 1.411 c
+134.614 1.735 134.942 1.897 135.364 1.897 c
+135.746 1.897 136.044 1.738 136.26 1.426 c
+136.26 3.484 l
+136.908 3.484 l
+136.908 -2.161 l
+136.32 -2.161 l
+136.276 -1.734 l
+136.07 -2.069 135.765 -2.234 135.364 -2.234 c
+134.952 -2.234 134.629 -2.08 134.394 -1.764 c
+134.159 -1.44 134.041 -0.985 134.041 -0.397 c
+h
+134.688 -0.367 m
+134.688 -0.808 134.751 -1.139 134.879 -1.352 c
+135.015 -1.558 135.235 -1.66 135.54 -1.66 c
+135.863 -1.66 136.102 -1.499 136.26 -1.176 c
+136.26 0.838 l
+136.091 1.151 135.853 1.309 135.54 1.309 c
+135.235 1.309 135.015 1.206 134.879 1 c
+134.751 0.794 134.688 0.47 134.688 0.03 c
+h
+140.332 -2.161 -0.646 3.984 re
+140.376 2.866 m
+140.376 2.756 140.347 2.664 140.288 2.587 c
+140.229 2.517 140.133 2.484 140.008 2.484 c
+139.891 2.484 139.796 2.517 139.73 2.587 c
+139.671 2.664 139.642 2.756 139.642 2.866 c
+139.642 2.984 139.671 3.076 139.73 3.146 c
+139.796 3.223 139.891 3.263 140.008 3.263 c
+140.133 3.263 140.229 3.223 140.288 3.146 c
+140.347 3.065 140.376 2.973 140.376 2.866 c
+141.964 1.823 m
+141.978 1.382 l
+142.232 1.723 142.555 1.897 142.948 1.897 c
+143.654 1.897 144.01 1.426 144.022 0.485 c
+144.022 -2.161 l
+143.375 -2.161 l
+143.375 0.456 l
+143.375 0.769 143.32 0.989 143.214 1.118 c
+143.103 1.243 142.948 1.309 142.743 1.309 c
+142.585 1.309 142.438 1.253 142.302 1.147 c
+142.173 1.037 142.07 0.9 141.993 0.736 c
+141.993 -2.161 l
+141.346 -2.161 l
+141.346 1.823 l
+h
+145.845 2.778 m
+145.845 1.823 l
+146.447 1.823 l
+146.447 1.294 l
+145.845 1.294 l
+145.845 -1.176 l
+145.845 -1.334 145.866 -1.452 145.918 -1.529 c
+145.976 -1.61 146.065 -1.646 146.182 -1.646 c
+146.271 -1.646 146.358 -1.631 146.447 -1.602 c
+146.447 -2.161 l
+146.3 -2.208 146.146 -2.234 145.992 -2.234 c
+145.734 -2.234 145.539 -2.142 145.404 -1.955 c
+145.263 -1.771 145.198 -1.51 145.198 -1.176 c
+145.198 1.294 l
+144.594 1.294 l
+144.594 1.823 l
+145.198 1.823 l
+145.198 2.778 l
+h
+147.006 0.015 m
+147.006 0.592 147.142 1.048 147.417 1.382 c
+147.7 1.723 148.071 1.897 148.534 1.897 c
+148.993 1.897 149.361 1.727 149.637 1.397 c
+149.92 1.073 150.067 0.625 150.078 0.059 c
+150.078 -0.367 l
+150.078 -0.937 149.934 -1.392 149.651 -1.734 c
+149.375 -2.069 149.008 -2.234 148.549 -2.234 c
+148.086 -2.234 147.715 -2.072 147.432 -1.749 c
+147.156 -1.419 147.013 -0.977 147.006 -0.426 c
+h
+147.652 -0.367 m
+147.652 -0.771 147.729 -1.087 147.887 -1.323 c
+148.053 -1.558 148.274 -1.675 148.549 -1.675 c
+149.115 -1.675 149.409 -1.263 149.431 -0.44 c
+149.431 0.015 l
+149.431 0.416 149.346 0.736 149.181 0.971 c
+149.023 1.213 148.806 1.338 148.534 1.338 c
+148.27 1.338 148.053 1.213 147.887 0.971 c
+147.729 0.736 147.652 0.416 147.652 0.015 c
+h
+154.678 -2.161 m
+154.638 -2.072 154.612 -1.926 154.605 -1.72 c
+154.37 -2.065 154.076 -2.234 153.723 -2.234 c
+153.359 -2.234 153.076 -2.138 152.87 -1.94 c
+152.672 -1.734 152.577 -1.448 152.577 -1.072 c
+152.577 -0.673 152.712 -0.353 152.988 -0.118 c
+153.26 0.125 153.635 0.25 154.105 0.25 c
+154.59 0.25 l
+154.59 0.676 l
+154.59 0.912 154.535 1.077 154.429 1.176 c
+154.318 1.283 154.157 1.338 153.944 1.338 c
+153.745 1.338 153.583 1.279 153.458 1.162 c
+153.341 1.044 153.282 0.897 153.282 0.721 c
+152.635 0.721 l
+152.635 0.915 152.694 1.106 152.812 1.294 c
+152.937 1.478 153.099 1.625 153.296 1.735 c
+153.502 1.841 153.73 1.897 153.988 1.897 c
+154.389 1.897 154.693 1.794 154.899 1.588 c
+155.112 1.382 155.226 1.088 155.237 0.706 c
+155.237 -1.308 l
+155.237 -1.613 155.274 -1.878 155.355 -2.102 c
+155.355 -2.161 l
+h
+153.811 -1.646 m
+153.977 -1.646 154.127 -1.602 154.267 -1.514 c
+154.414 -1.425 154.52 -1.315 154.59 -1.176 c
+154.59 -0.235 l
+154.223 -0.235 l
+153.907 -0.235 153.664 -0.305 153.488 -0.44 c
+153.311 -0.569 153.223 -0.756 153.223 -0.999 c
+153.223 -1.227 153.267 -1.392 153.356 -1.499 c
+153.444 -1.598 153.595 -1.646 153.811 -1.646 c
+156.854 1.823 m
+156.868 1.382 l
+157.122 1.723 157.446 1.897 157.839 1.897 c
+158.545 1.897 158.901 1.426 158.912 0.485 c
+158.912 -2.161 l
+158.265 -2.161 l
+158.265 0.456 l
+158.265 0.769 158.21 0.989 158.104 1.118 c
+157.993 1.243 157.839 1.309 157.633 1.309 c
+157.475 1.309 157.328 1.253 157.192 1.147 c
+157.063 1.037 156.961 0.9 156.883 0.736 c
+156.883 -2.161 l
+156.236 -2.161 l
+156.236 1.823 l
+h
+160.97 -1.072 m
+161.69 1.823 l
+162.381 1.823 l
+161.088 -2.719 l
+160.988 -3.061 160.845 -3.322 160.661 -3.498 c
+160.484 -3.675 160.282 -3.763 160.058 -3.763 c
+159.97 -3.763 159.856 -3.74 159.721 -3.704 c
+159.721 -3.16 l
+159.867 -3.175 l
+160.051 -3.175 160.198 -3.131 160.309 -3.042 c
+160.415 -2.954 160.503 -2.796 160.573 -2.572 c
+160.691 -2.131 l
+159.529 1.823 l
+160.234 1.823 l
+h
+164.6 0.015 m
+164.6 0.592 164.737 1.048 165.012 1.382 c
+165.295 1.723 165.666 1.897 166.129 1.897 c
+166.588 1.897 166.956 1.727 167.232 1.397 c
+167.515 1.073 167.661 0.625 167.673 0.059 c
+167.673 -0.367 l
+167.673 -0.937 167.529 -1.392 167.247 -1.734 c
+166.971 -2.069 166.603 -2.234 166.144 -2.234 c
+165.681 -2.234 165.31 -2.072 165.026 -1.749 c
+164.751 -1.419 164.608 -0.977 164.6 -0.426 c
+h
+165.247 -0.367 m
+165.247 -0.771 165.325 -1.087 165.483 -1.323 c
+165.647 -1.558 165.868 -1.675 166.144 -1.675 c
+166.709 -1.675 167.004 -1.263 167.025 -0.44 c
+167.025 0.015 l
+167.025 0.416 166.941 0.736 166.776 0.971 c
+166.618 1.213 166.401 1.338 166.129 1.338 c
+165.865 1.338 165.647 1.213 165.483 0.971 c
+165.325 0.736 165.247 0.416 165.247 0.015 c
+h
+169.363 2.778 m
+169.363 1.823 l
+169.965 1.823 l
+169.965 1.294 l
+169.363 1.294 l
+169.363 -1.176 l
+169.363 -1.334 169.385 -1.452 169.437 -1.529 c
+169.495 -1.61 169.583 -1.646 169.701 -1.646 c
+169.789 -1.646 169.877 -1.631 169.965 -1.602 c
+169.965 -2.161 l
+169.819 -2.208 169.664 -2.234 169.51 -2.234 c
+169.252 -2.234 169.057 -2.142 168.922 -1.955 c
+168.782 -1.771 168.716 -1.51 168.716 -1.176 c
+168.716 1.294 l
+168.113 1.294 l
+168.113 1.823 l
+168.716 1.823 l
+168.716 2.778 l
+h
+171.376 1.411 m
+171.63 1.735 171.95 1.897 172.332 1.897 c
+173.038 1.897 173.394 1.426 173.405 0.485 c
+173.405 -2.161 l
+172.758 -2.161 l
+172.758 0.456 l
+172.758 0.769 172.703 0.989 172.596 1.118 c
+172.487 1.243 172.332 1.309 172.126 1.309 c
+171.968 1.309 171.821 1.253 171.685 1.147 c
+171.557 1.037 171.454 0.9 171.376 0.736 c
+171.376 -2.161 l
+170.73 -2.161 l
+170.73 3.484 l
+171.376 3.484 l
+h
+175.787 -2.234 m
+175.286 -2.234 174.904 -2.087 174.64 -1.793 c
+174.375 -1.499 174.243 -1.066 174.243 -0.484 c
+174.243 -0.014 l
+174.243 0.58 174.368 1.048 174.625 1.382 c
+174.89 1.723 175.249 1.897 175.713 1.897 c
+176.172 1.897 176.514 1.742 176.741 1.441 c
+176.977 1.147 177.098 0.684 177.109 0.059 c
+177.109 -0.367 l
+174.89 -0.367 l
+174.89 -0.455 l
+174.89 -0.889 174.967 -1.201 175.125 -1.396 c
+175.29 -1.583 175.521 -1.675 175.816 -1.675 c
+176.01 -1.675 176.184 -1.643 176.33 -1.573 c
+176.477 -1.496 176.613 -1.378 176.741 -1.22 c
+177.08 -1.631 l
+176.793 -2.036 176.363 -2.234 175.787 -2.234 c
+175.713 1.338 m
+175.438 1.338 175.235 1.243 175.11 1.058 c
+174.981 0.871 174.908 0.58 174.89 0.191 c
+176.462 0.191 l
+176.462 0.279 l
+176.44 0.661 176.375 0.93 176.257 1.088 c
+176.139 1.253 175.955 1.338 175.713 1.338 c
+179.534 1.206 m
+179.446 1.224 179.347 1.235 179.241 1.235 c
+178.906 1.235 178.671 1.051 178.535 0.691 c
+178.535 -2.161 l
+177.888 -2.161 l
+177.888 1.823 l
+178.52 1.823 l
+178.535 1.411 l
+178.711 1.735 178.954 1.897 179.27 1.897 c
+179.376 1.897 179.465 1.874 179.534 1.837 c
+h
+179.77 -1.808 m
+179.77 -1.691 179.803 -1.595 179.872 -1.514 c
+179.939 -1.437 180.042 -1.396 180.182 -1.396 c
+180.328 -1.396 180.435 -1.437 180.504 -1.514 c
+180.582 -1.595 180.622 -1.691 180.622 -1.808 c
+180.622 -1.918 180.582 -2.009 180.504 -2.087 c
+180.435 -2.165 180.328 -2.204 180.182 -2.204 c
+180.042 -2.204 179.939 -2.165 179.872 -2.087 c
+179.803 -2.009 179.77 -1.918 179.77 -1.808 c
+f
+Q
+730.676 99.115 -1.794 0.867 re
+731.587 97.247 m
+731.587 102.598 l
+733.013 102.598 l
+733.63 102.598 734.123 102.396 734.497 101.995 c
+734.869 101.602 735.06 101.062 735.071 100.379 c
+735.071 99.512 l
+735.071 98.806 734.883 98.251 734.512 97.85 c
+734.137 97.446 733.63 97.247 732.984 97.247 c
+h
+732.675 101.702 m
+732.675 98.145 l
+732.998 98.145 l
+733.358 98.145 733.616 98.236 733.763 98.423 c
+733.909 98.618 733.983 98.945 733.983 99.408 c
+733.983 100.349 l
+733.983 100.849 733.913 101.195 733.778 101.393 c
+733.637 101.588 733.402 101.69 733.072 101.702 c
+h
+f
+738.32 97.247 -0.647 3.984 re
+738.364 102.275 m
+738.364 102.164 738.334 102.072 738.275 101.995 c
+738.216 101.926 738.121 101.893 737.996 101.893 c
+737.878 101.893 737.782 101.926 737.716 101.995 c
+737.658 102.072 737.628 102.164 737.628 102.275 c
+737.628 102.392 737.658 102.484 737.716 102.554 c
+737.782 102.631 737.878 102.672 737.996 102.672 c
+738.121 102.672 738.216 102.631 738.275 102.554 c
+738.334 102.473 738.364 102.381 738.364 102.275 c
+739.951 101.231 m
+739.966 100.79 l
+740.219 101.132 740.542 101.305 740.936 101.305 c
+741.641 101.305 741.998 100.834 742.009 99.894 c
+742.009 97.247 l
+741.362 97.247 l
+741.362 99.864 l
+741.362 100.177 741.307 100.397 741.2 100.526 c
+741.09 100.651 740.936 100.717 740.73 100.717 c
+740.572 100.717 740.425 100.661 740.288 100.555 c
+740.161 100.445 740.057 100.308 739.98 100.144 c
+739.98 97.247 l
+739.334 97.247 l
+739.334 101.231 l
+h
+744.919 98.262 m
+744.919 98.409 744.864 98.53 744.757 98.629 c
+744.647 98.725 744.442 98.843 744.14 98.982 c
+743.795 99.129 743.552 99.25 743.405 99.35 c
+743.258 99.456 743.148 99.574 743.081 99.703 c
+743.012 99.828 742.979 99.986 742.979 100.173 c
+742.979 100.497 743.097 100.765 743.332 100.981 c
+743.567 101.195 743.868 101.305 744.243 101.305 c
+744.625 101.305 744.934 101.191 745.169 100.967 c
+745.404 100.738 745.522 100.452 745.522 100.1 c
+744.875 100.1 l
+744.875 100.275 744.816 100.426 744.699 100.555 c
+744.581 100.68 744.427 100.746 744.243 100.746 c
+744.045 100.746 743.894 100.691 743.787 100.584 c
+743.677 100.485 743.625 100.353 743.625 100.187 c
+743.625 100.059 743.662 99.952 743.743 99.864 c
+743.82 99.783 744.011 99.68 744.317 99.556 c
+744.795 99.368 745.125 99.18 745.302 98.997 c
+745.478 98.82 745.566 98.592 745.566 98.321 c
+745.566 97.968 745.441 97.688 745.198 97.482 c
+744.963 97.277 744.647 97.174 744.257 97.174 c
+743.835 97.174 743.497 97.291 743.243 97.527 c
+742.987 97.769 742.861 98.074 742.861 98.438 c
+743.508 98.438 l
+743.515 98.211 743.585 98.034 743.714 97.91 c
+743.839 97.792 744.022 97.733 744.257 97.733 c
+744.471 97.733 744.633 97.781 744.743 97.879 c
+744.86 97.975 744.919 98.104 744.919 98.262 c
+747.257 102.186 m
+747.257 101.231 l
+747.859 101.231 l
+747.859 100.702 l
+747.257 100.702 l
+747.257 98.232 l
+747.257 98.074 747.278 97.957 747.33 97.879 c
+747.388 97.799 747.477 97.762 747.594 97.762 c
+747.683 97.762 747.771 97.777 747.859 97.806 c
+747.859 97.247 l
+747.712 97.2 747.557 97.174 747.403 97.174 c
+747.146 97.174 746.952 97.266 746.815 97.453 c
+746.676 97.637 746.609 97.898 746.609 98.232 c
+746.609 100.702 l
+746.007 100.702 l
+746.007 101.231 l
+746.609 101.231 l
+746.609 102.186 l
+h
+750.049 97.174 m
+749.549 97.174 749.167 97.322 748.903 97.615 c
+748.638 97.91 748.506 98.342 748.506 98.924 c
+748.506 99.394 l
+748.506 99.989 748.631 100.456 748.888 100.79 c
+749.152 101.132 749.512 101.305 749.975 101.305 c
+750.435 101.305 750.777 101.15 751.004 100.849 c
+751.24 100.555 751.361 100.092 751.372 99.467 c
+751.372 99.041 l
+749.152 99.041 l
+749.152 98.953 l
+749.152 98.519 749.229 98.207 749.387 98.012 c
+749.553 97.825 749.784 97.733 750.079 97.733 c
+750.273 97.733 750.446 97.766 750.593 97.835 c
+750.74 97.912 750.876 98.03 751.004 98.188 c
+751.342 97.777 l
+751.056 97.372 750.626 97.174 750.049 97.174 c
+749.975 100.746 m
+749.7 100.746 749.498 100.651 749.373 100.466 c
+749.244 100.279 749.171 99.989 749.152 99.599 c
+750.725 99.599 l
+750.725 99.688 l
+750.703 100.069 750.637 100.339 750.519 100.497 c
+750.401 100.661 750.218 100.746 749.975 100.746 c
+754.194 97.247 m
+754.154 97.336 754.128 97.482 754.121 97.688 c
+753.886 97.343 753.591 97.174 753.239 97.174 c
+752.875 97.174 752.592 97.27 752.386 97.468 c
+752.188 97.674 752.092 97.96 752.092 98.336 c
+752.092 98.735 752.228 99.055 752.504 99.291 c
+752.776 99.533 753.15 99.658 753.621 99.658 c
+754.106 99.658 l
+754.106 100.085 l
+754.106 100.32 754.051 100.485 753.944 100.584 c
+753.834 100.691 753.672 100.746 753.459 100.746 c
+753.261 100.746 753.099 100.688 752.974 100.57 c
+752.857 100.452 752.797 100.305 752.797 100.129 c
+752.151 100.129 l
+752.151 100.323 752.209 100.514 752.327 100.702 c
+752.452 100.886 752.614 101.033 752.813 101.143 c
+753.019 101.249 753.246 101.305 753.503 101.305 c
+753.904 101.305 754.209 101.202 754.415 100.996 c
+754.628 100.79 754.742 100.497 754.752 100.114 c
+754.752 98.1 l
+754.752 97.795 754.79 97.53 754.87 97.307 c
+754.87 97.247 l
+h
+753.327 97.762 m
+753.493 97.762 753.643 97.806 753.782 97.894 c
+753.929 97.983 754.036 98.093 754.106 98.232 c
+754.106 99.173 l
+753.738 99.173 l
+753.422 99.173 753.18 99.103 753.003 98.968 c
+752.828 98.839 752.739 98.652 752.739 98.409 c
+752.739 98.181 752.783 98.016 752.871 97.91 c
+752.959 97.81 753.11 97.762 753.327 97.762 c
+755.62 99.423 m
+755.62 100.029 755.731 100.497 755.958 100.819 c
+756.194 101.143 756.52 101.305 756.943 101.305 c
+757.325 101.305 757.622 101.147 757.84 100.834 c
+757.84 102.892 l
+758.486 102.892 l
+758.486 97.247 l
+757.898 97.247 l
+757.854 97.674 l
+757.649 97.339 757.343 97.174 756.943 97.174 c
+756.531 97.174 756.208 97.328 755.972 97.644 c
+755.737 97.968 755.62 98.423 755.62 99.011 c
+h
+756.267 99.041 m
+756.267 98.6 756.329 98.269 756.458 98.056 c
+756.594 97.85 756.814 97.748 757.119 97.748 c
+757.443 97.748 757.682 97.91 757.84 98.232 c
+757.84 100.246 l
+757.67 100.559 757.432 100.717 757.119 100.717 c
+756.814 100.717 756.594 100.614 756.458 100.408 c
+756.329 100.202 756.267 99.878 756.267 99.438 c
+h
+761.073 99.423 m
+761.073 100 761.21 100.456 761.485 100.79 c
+761.768 101.132 762.139 101.305 762.602 101.305 c
+763.061 101.305 763.429 101.135 763.704 100.805 c
+763.988 100.482 764.134 100.033 764.146 99.467 c
+764.146 99.041 l
+764.146 98.471 764.002 98.016 763.719 97.674 c
+763.444 97.339 763.076 97.174 762.617 97.174 c
+762.154 97.174 761.782 97.336 761.499 97.659 c
+761.224 97.989 761.081 98.431 761.073 98.982 c
+h
+761.72 99.041 m
+761.72 98.637 761.797 98.321 761.956 98.085 c
+762.12 97.85 762.341 97.733 762.617 97.733 c
+763.182 97.733 763.477 98.145 763.498 98.968 c
+763.498 99.423 l
+763.498 99.824 763.415 100.144 763.249 100.379 c
+763.091 100.621 762.874 100.746 762.602 100.746 c
+762.338 100.746 762.12 100.621 761.956 100.379 c
+761.797 100.144 761.72 99.824 761.72 99.423 c
+h
+765.277 97.247 m
+765.277 100.702 l
+764.748 100.702 l
+764.748 101.231 l
+765.277 101.231 l
+765.277 101.687 l
+765.277 102.087 765.373 102.4 765.571 102.627 c
+765.777 102.851 766.056 102.966 766.409 102.966 c
+766.545 102.966 766.677 102.943 766.806 102.907 c
+766.777 102.363 l
+766.677 102.381 766.578 102.392 766.482 102.392 c
+766.108 102.392 765.924 102.128 765.924 101.598 c
+765.924 101.231 l
+766.6 101.231 l
+766.6 100.702 l
+765.924 100.702 l
+765.924 97.247 l
+h
+f
+714.551 89.707 -1.793 0.867 re
+715.271 89.957 m
+715.271 90.604 715.378 91.089 715.594 91.412 c
+715.819 91.735 716.142 91.897 716.565 91.897 c
+716.877 91.897 717.13 91.765 717.329 91.5 c
+717.329 93.484 l
+718.387 93.484 l
+718.387 87.84 l
+717.432 87.84 l
+717.388 88.252 l
+717.171 87.928 716.895 87.766 716.565 87.766 c
+716.153 87.766 715.833 87.921 715.609 88.237 c
+715.393 88.56 715.279 89.031 715.271 89.648 c
+h
+716.315 89.692 m
+716.315 89.299 716.351 89.023 716.432 88.869 c
+716.521 88.711 716.667 88.634 716.873 88.634 c
+717.079 88.634 717.23 88.726 717.329 88.913 c
+717.329 90.721 l
+717.23 90.916 717.079 91.015 716.873 91.015 c
+716.675 91.015 716.535 90.934 716.447 90.78 c
+716.359 90.633 716.315 90.361 716.315 89.972 c
+h
+f
+q 1 0 0 1 721.2686 87.8399 cm
+0 0 m
+0 3.454 l
+-0.53 3.454 l
+-0.53 3.984 l
+0 3.984 l
+0 4.439 l
+0 4.84 0.095 5.152 0.293 5.38 c
+0.5 5.604 0.779 5.719 1.132 5.719 c
+1.267 5.719 1.4 5.696 1.529 5.659 c
+1.499 5.116 l
+1.4 5.134 1.301 5.145 1.205 5.145 c
+0.831 5.145 0.646 4.881 0.646 4.351 c
+0.646 3.984 l
+1.323 3.984 l
+1.323 3.454 l
+0.646 3.454 l
+0.646 0 l
+h
+1.955 2.176 m
+1.955 2.753 2.09 3.209 2.366 3.543 c
+2.649 3.884 3.021 4.057 3.484 4.057 c
+3.943 4.057 4.31 3.888 4.586 3.558 c
+4.868 3.234 5.016 2.786 5.026 2.22 c
+5.026 1.794 l
+5.026 1.224 4.883 0.769 4.6 0.427 c
+4.325 0.092 3.958 -0.073 3.498 -0.073 c
+3.035 -0.073 2.664 0.088 2.381 0.412 c
+2.105 0.742 1.962 1.183 1.955 1.735 c
+h
+2.601 1.794 m
+2.601 1.389 2.678 1.073 2.836 0.838 c
+3.002 0.603 3.222 0.485 3.498 0.485 c
+4.064 0.485 4.358 0.897 4.38 1.721 c
+4.38 2.176 l
+4.38 2.577 4.295 2.897 4.13 3.132 c
+3.972 3.373 3.755 3.499 3.484 3.499 c
+3.219 3.499 3.002 3.373 2.836 3.132 c
+2.678 2.897 2.601 2.577 2.601 2.176 c
+h
+7.511 3.367 m
+7.422 3.385 7.324 3.396 7.217 3.396 c
+6.882 3.396 6.647 3.212 6.512 2.852 c
+6.512 0 l
+5.865 0 l
+5.865 3.984 l
+6.497 3.984 l
+6.512 3.572 l
+6.688 3.896 6.93 4.057 7.247 4.057 c
+7.353 4.057 7.441 4.035 7.511 3.998 c
+h
+9.466 0.485 m
+9.679 0.485 9.851 0.548 9.98 0.676 c
+10.117 0.813 10.19 1.004 10.2 1.25 c
+10.818 1.25 l
+10.796 0.867 10.66 0.548 10.406 0.294 c
+10.15 0.048 9.837 -0.073 9.466 -0.073 c
+8.974 -0.073 8.598 0.077 8.334 0.383 c
+8.077 0.695 7.952 1.162 7.952 1.779 c
+7.952 2.22 l
+7.952 2.816 8.077 3.271 8.334 3.587 c
+8.598 3.899 8.974 4.057 9.466 4.057 c
+9.866 4.057 10.186 3.925 10.422 3.66 c
+10.664 3.404 10.796 3.057 10.818 2.617 c
+10.2 2.617 l
+10.179 2.911 10.105 3.132 9.98 3.278 c
+9.863 3.425 9.69 3.499 9.466 3.499 c
+9.172 3.499 8.955 3.4 8.819 3.205 c
+8.679 3.017 8.606 2.708 8.598 2.278 c
+8.598 1.764 l
+8.598 1.294 8.665 0.96 8.804 0.765 c
+8.951 0.578 9.172 0.485 9.466 0.485 c
+12.993 -0.073 m
+12.494 -0.073 12.112 0.074 11.847 0.368 c
+11.582 0.662 11.451 1.095 11.451 1.676 c
+11.451 2.147 l
+11.451 2.741 11.575 3.209 11.833 3.543 c
+12.097 3.884 12.457 4.057 12.92 4.057 c
+13.379 4.057 13.722 3.903 13.949 3.602 c
+14.184 3.308 14.306 2.845 14.316 2.22 c
+14.316 1.794 l
+12.097 1.794 l
+12.097 1.706 l
+12.097 1.272 12.174 0.96 12.332 0.765 c
+12.498 0.578 12.729 0.485 13.023 0.485 c
+13.218 0.485 13.39 0.518 13.537 0.588 c
+13.685 0.665 13.82 0.783 13.949 0.941 c
+14.287 0.53 l
+14.001 0.125 13.57 -0.073 12.993 -0.073 c
+12.92 3.499 m
+12.644 3.499 12.442 3.404 12.317 3.219 c
+12.189 3.032 12.116 2.741 12.097 2.352 c
+13.67 2.352 l
+13.67 2.44 l
+13.648 2.822 13.581 3.091 13.464 3.249 c
+13.346 3.414 13.163 3.499 12.92 3.499 c
+17.036 1.015 m
+17.036 1.162 16.981 1.283 16.874 1.382 c
+16.764 1.478 16.558 1.595 16.257 1.735 c
+15.912 1.881 15.669 2.003 15.522 2.103 c
+15.374 2.209 15.264 2.326 15.199 2.455 c
+15.129 2.58 15.096 2.738 15.096 2.926 c
+15.096 3.249 15.214 3.517 15.449 3.734 c
+15.684 3.947 15.985 4.057 16.359 4.057 c
+16.742 4.057 17.051 3.944 17.286 3.72 c
+17.521 3.491 17.639 3.205 17.639 2.852 c
+16.992 2.852 l
+16.992 3.028 16.933 3.179 16.816 3.308 c
+16.698 3.433 16.544 3.499 16.359 3.499 c
+16.161 3.499 16.01 3.444 15.904 3.337 c
+15.794 3.238 15.742 3.105 15.742 2.94 c
+15.742 2.812 15.779 2.705 15.86 2.617 c
+15.937 2.536 16.128 2.433 16.433 2.309 c
+16.911 2.12 17.242 1.933 17.418 1.75 c
+17.595 1.573 17.683 1.345 17.683 1.073 c
+17.683 0.721 17.558 0.441 17.315 0.235 c
+17.08 0.03 16.764 -0.073 16.375 -0.073 c
+15.952 -0.073 15.613 0.044 15.36 0.279 c
+15.103 0.522 14.978 0.827 14.978 1.191 c
+15.625 1.191 l
+15.632 0.963 15.702 0.786 15.831 0.662 c
+15.956 0.545 16.139 0.485 16.375 0.485 c
+16.588 0.485 16.749 0.533 16.86 0.632 c
+16.978 0.728 17.036 0.857 17.036 1.015 c
+20.108 2.176 m
+20.108 2.782 20.218 3.249 20.446 3.572 c
+20.681 3.896 21.009 4.057 21.431 4.057 c
+21.813 4.057 22.111 3.899 22.327 3.587 c
+22.327 5.644 l
+22.975 5.644 l
+22.975 0 l
+22.387 0 l
+22.343 0.427 l
+22.137 0.092 21.832 -0.073 21.431 -0.073 c
+21.019 -0.073 20.696 0.081 20.461 0.397 c
+20.226 0.721 20.108 1.176 20.108 1.764 c
+h
+20.755 1.794 m
+20.755 1.353 20.818 1.022 20.945 0.809 c
+21.082 0.603 21.302 0.5 21.607 0.5 c
+21.93 0.5 22.169 0.662 22.327 0.985 c
+22.327 2.999 l
+22.158 3.311 21.92 3.469 21.607 3.469 c
+21.302 3.469 21.082 3.367 20.945 3.161 c
+20.818 2.955 20.755 2.631 20.755 2.191 c
+h
+25.4 -0.073 m
+24.899 -0.073 24.518 0.074 24.253 0.368 c
+23.989 0.662 23.856 1.095 23.856 1.676 c
+23.856 2.147 l
+23.856 2.741 23.981 3.209 24.238 3.543 c
+24.503 3.884 24.863 4.057 25.327 4.057 c
+25.786 4.057 26.127 3.903 26.355 3.602 c
+26.59 3.308 26.711 2.845 26.723 2.22 c
+26.723 1.794 l
+24.503 1.794 l
+24.503 1.706 l
+24.503 1.272 24.581 0.96 24.739 0.765 c
+24.903 0.578 25.135 0.485 25.429 0.485 c
+25.624 0.485 25.797 0.518 25.944 0.588 c
+26.09 0.665 26.227 0.783 26.355 0.941 c
+26.693 0.53 l
+26.406 0.125 25.977 -0.073 25.4 -0.073 c
+25.327 3.499 m
+25.051 3.499 24.849 3.404 24.724 3.219 c
+24.595 3.032 24.521 2.741 24.503 2.352 c
+26.075 2.352 l
+26.075 2.44 l
+26.054 2.822 25.988 3.091 25.87 3.249 c
+25.753 3.414 25.568 3.499 25.327 3.499 c
+28.207 0 -0.646 5.644 re
+30.647 -0.073 m
+30.148 -0.073 29.765 0.074 29.501 0.368 c
+29.236 0.662 29.104 1.095 29.104 1.676 c
+29.104 2.147 l
+29.104 2.741 29.229 3.209 29.486 3.543 c
+29.751 3.884 30.111 4.057 30.574 4.057 c
+31.033 4.057 31.375 3.903 31.602 3.602 c
+31.837 3.308 31.959 2.845 31.97 2.22 c
+31.97 1.794 l
+29.751 1.794 l
+29.751 1.706 l
+29.751 1.272 29.828 0.96 29.986 0.765 c
+30.152 0.578 30.383 0.485 30.677 0.485 c
+30.871 0.485 31.044 0.518 31.191 0.588 c
+31.338 0.665 31.474 0.783 31.602 0.941 c
+31.941 0.53 l
+31.654 0.125 31.224 -0.073 30.647 -0.073 c
+30.574 3.499 m
+30.298 3.499 30.096 3.404 29.971 3.219 c
+29.842 3.032 29.769 2.741 29.751 2.352 c
+31.324 2.352 l
+31.324 2.44 l
+31.301 2.822 31.235 3.091 31.118 3.249 c
+31 3.414 30.817 3.499 30.574 3.499 c
+33.601 4.939 m
+33.601 3.984 l
+34.204 3.984 l
+34.204 3.454 l
+33.601 3.454 l
+33.601 0.985 l
+33.601 0.827 33.624 0.709 33.676 0.632 c
+33.734 0.551 33.822 0.515 33.94 0.515 c
+34.028 0.515 34.116 0.53 34.204 0.559 c
+34.204 0 l
+34.058 -0.047 33.903 -0.073 33.749 -0.073 c
+33.491 -0.073 33.297 0.019 33.161 0.206 c
+33.021 0.389 32.955 0.651 32.955 0.985 c
+32.955 3.454 l
+32.352 3.454 l
+32.352 3.984 l
+32.955 3.984 l
+32.955 4.939 l
+h
+35.675 0 -0.647 3.984 re
+35.718 5.027 m
+35.718 4.917 35.689 4.825 35.63 4.748 c
+35.571 4.678 35.476 4.645 35.351 4.645 c
+35.234 4.645 35.138 4.678 35.072 4.748 c
+35.012 4.825 34.983 4.917 34.983 5.027 c
+34.983 5.145 35.012 5.237 35.072 5.307 c
+35.138 5.384 35.234 5.424 35.351 5.424 c
+35.476 5.424 35.571 5.384 35.63 5.307 c
+35.689 5.226 35.718 5.134 35.718 5.027 c
+36.556 2.176 m
+36.556 2.753 36.693 3.209 36.968 3.543 c
+37.25 3.884 37.622 4.057 38.085 4.057 c
+38.544 4.057 38.912 3.888 39.187 3.558 c
+39.471 3.234 39.617 2.786 39.629 2.22 c
+39.629 1.794 l
+39.629 1.224 39.485 0.769 39.202 0.427 c
+38.927 0.092 38.559 -0.073 38.1 -0.073 c
+37.637 -0.073 37.266 0.088 36.982 0.412 c
+36.707 0.742 36.564 1.183 36.556 1.735 c
+h
+37.203 1.794 m
+37.203 1.389 37.281 1.073 37.439 0.838 c
+37.603 0.603 37.824 0.485 38.1 0.485 c
+38.665 0.485 38.96 0.897 38.981 1.721 c
+38.981 2.176 l
+38.981 2.577 38.897 2.897 38.732 3.132 c
+38.574 3.373 38.357 3.499 38.085 3.499 c
+37.821 3.499 37.603 3.373 37.439 3.132 c
+37.281 2.897 37.203 2.577 37.203 2.176 c
+h
+41.084 3.984 m
+41.098 3.543 l
+41.352 3.884 41.676 4.057 42.068 4.057 c
+42.773 4.057 43.13 3.587 43.141 2.646 c
+43.141 0 l
+42.495 0 l
+42.495 2.617 l
+42.495 2.929 42.44 3.15 42.333 3.278 c
+42.223 3.404 42.068 3.469 41.863 3.469 c
+41.705 3.469 41.557 3.414 41.422 3.308 c
+41.293 3.198 41.19 3.061 41.113 2.897 c
+41.113 0 l
+40.466 0 l
+40.466 3.984 l
+h
+44.155 0.353 m
+44.155 0.47 44.188 0.566 44.259 0.647 c
+44.325 0.724 44.427 0.765 44.568 0.765 c
+44.714 0.765 44.821 0.724 44.89 0.647 c
+44.968 0.566 45.008 0.47 45.008 0.353 c
+45.008 0.243 44.968 0.151 44.89 0.074 c
+44.821 -0.004 44.714 -0.043 44.568 -0.043 c
+44.427 -0.043 44.325 -0.004 44.259 0.074 c
+44.188 0.151 44.155 0.243 44.155 0.353 c
+f
+Q
+ endstream endobj 295 0 obj <</I true/K false/S/Transparency/Type/Group>> endobj 297 0 obj <</BBox[325.823 554.164 757.387 480.746]/Group 298 0 R/Length 128/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>/Shading<</Sh0 64 0 R>>>>/Subtype/Form>>stream
+q
+325.823 554.164 431.564 -73.418 re
+W n
+q
+0 g
+/GS0 gs
+431.5641174 0 0 431.5641174 325.8230896 517.4552612 cm
+BX /Sh0 sh EX Q
+Q
+ endstream endobj 298 0 obj <</I false/K false/S/Transparency/Type/Group>> endobj 296 0 obj <</AIS false/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask 299 0 R/Type/ExtGState/ca 1.0/op false>> endobj 299 0 obj <</BC 300 0 R/G 301 0 R/S/Luminosity/Type/Mask>> endobj 300 0 obj [0.0] endobj 301 0 obj <</BBox[325.823 554.164 757.387 480.746]/Group 302 0 R/Length 92/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ExtGState<</GS0 12 0 R>>/XObject<</Fm0 303 0 R>>>>/Subtype/Form>>stream
+0 g
+/GS0 gs
+325.823 554.164 431.564 -73.418 re
+f
+q
+0 Tc 0 Tw 0 Ts 100 Tz 0 Tr 0 TL/Fm0 Do
+Q
+ endstream endobj 302 0 obj <</CS/DeviceGray/I false/K false/S/Transparency/Type/Group>> endobj 303 0 obj <</BBox[325.823 554.164 757.388 480.746]/Group 304 0 R/Length 128/Matrix[1.0 0.0 0.0 1.0 0.0 0.0]/Resources<</ColorSpace<</CS0 113 0 R>>/ExtGState<</GS0 12 0 R>>/Shading<</Sh0 127 0 R>>>>/Subtype/Form>>stream
+q
+325.823 554.164 431.564 -73.418 re
+W n
+q
+0 g
+/GS0 gs
+431.5641174 0 0 431.5641174 325.8227539 517.4550781 cm
+BX /Sh0 sh EX Q
+Q
+ endstream endobj 304 0 obj <</CS/DeviceCMYK/I true/K false/S/Transparency/Type/Group>> endobj 6 0 obj [5 0 R] endobj 305 0 obj <</CreationDate(D:20161031172420Z)/Creator(Adobe Illustrator CC 2015.3 \(Macintosh\))/ModDate(D:20161031172420Z)/Producer(Adobe PDF library 15.00)/Title(Untitled-2)>> endobj xref 0 306 0000000000 65535 f
+0000000016 00000 n
+0000000144 00000 n
+0000052539 00000 n
+0000000000 00000 f
+0001829223 00000 n
+0007345734 00000 n
+0000052596 00000 n
+0000052949 00000 n
+0005664025 00000 n
+0005664166 00000 n
+0001829413 00000 n
+0001821855 00000 n
+0005665528 00000 n
+0005664232 00000 n
+0000053303 00000 n
+0000053445 00000 n
+0000055549 00000 n
+0000053511 00000 n
+0000054988 00000 n
+0000055036 00000 n
+0001577808 00000 n
+0001825132 00000 n
+0001825248 00000 n
+0001825363 00000 n
+0001825486 00000 n
+0001825609 00000 n
+0001825732 00000 n
+0001577870 00000 n
+0001578205 00000 n
+0001578681 00000 n
+0001584621 00000 n
+0001596870 00000 n
+0001602617 00000 n
+0001616838 00000 n
+0001627887 00000 n
+0001628196 00000 n
+0001637380 00000 n
+0001647988 00000 n
+0001657309 00000 n
+0001660863 00000 n
+0001666195 00000 n
+0001669141 00000 n
+0001670268 00000 n
+0001679870 00000 n
+0001684168 00000 n
+0001688506 00000 n
+0001700981 00000 n
+0001705017 00000 n
+0001710819 00000 n
+0001717241 00000 n
+0001731952 00000 n
+0001741049 00000 n
+0001758297 00000 n
+0001772218 00000 n
+0001777518 00000 n
+0001777876 00000 n
+0001779807 00000 n
+0001786388 00000 n
+0001792684 00000 n
+0001803132 00000 n
+0001809040 00000 n
+0001814611 00000 n
+0001824567 00000 n
+0001824630 00000 n
+0001824504 00000 n
+0001824441 00000 n
+0001824378 00000 n
+0001824315 00000 n
+0001824252 00000 n
+0001824189 00000 n
+0001824126 00000 n
+0001824063 00000 n
+0001824000 00000 n
+0001823937 00000 n
+0001823874 00000 n
+0001823811 00000 n
+0001823748 00000 n
+0001823685 00000 n
+0001823622 00000 n
+0001823559 00000 n
+0001823496 00000 n
+0001823433 00000 n
+0001823370 00000 n
+0001823307 00000 n
+0001823244 00000 n
+0001823181 00000 n
+0001823118 00000 n
+0001823055 00000 n
+0001822992 00000 n
+0001822929 00000 n
+0001822346 00000 n
+0001822553 00000 n
+0001822409 00000 n
+0001822283 00000 n
+0001822220 00000 n
+0001822157 00000 n
+0001822094 00000 n
+0001822031 00000 n
+0001821968 00000 n
+0001821791 00000 n
+0001822716 00000 n
+0001822854 00000 n
+0001824778 00000 n
+0001824894 00000 n
+0001825023 00000 n
+0001827884 00000 n
+0001825848 00000 n
+0001825914 00000 n
+0001825937 00000 n
+0001826264 00000 n
+0001826342 00000 n
+0001826705 00000 n
+0001826928 00000 n
+0001826782 00000 n
+0001826991 00000 n
+0001827358 00000 n
+0001827746 00000 n
+0001827129 00000 n
+0001827205 00000 n
+0001827282 00000 n
+0001827801 00000 n
+0001827950 00000 n
+0001827973 00000 n
+0001828275 00000 n
+0001828353 00000 n
+0001828719 00000 n
+0001828796 00000 n
+0001828942 00000 n
+0001829058 00000 n
+0001829138 00000 n
+0001829295 00000 n
+0001829327 00000 n
+0001829482 00000 n
+0001833966 00000 n
+0001835264 00000 n
+0001847598 00000 n
+0001877099 00000 n
+0001899615 00000 n
+0001922108 00000 n
+0001944924 00000 n
+0001967003 00000 n
+0001989331 00000 n
+0002012637 00000 n
+0002035364 00000 n
+0002056686 00000 n
+0002078809 00000 n
+0002101782 00000 n
+0002136210 00000 n
+0002158624 00000 n
+0002181711 00000 n
+0002204289 00000 n
+0002228492 00000 n
+0002250164 00000 n
+0002272697 00000 n
+0002294933 00000 n
+0002318562 00000 n
+0002339903 00000 n
+0002362514 00000 n
+0002426019 00000 n
+0002449289 00000 n
+0002471861 00000 n
+0002494425 00000 n
+0002516757 00000 n
+0002539012 00000 n
+0002561573 00000 n
+0002583980 00000 n
+0002607446 00000 n
+0002630408 00000 n
+0002653946 00000 n
+0002695995 00000 n
+0002718800 00000 n
+0002741052 00000 n
+0002763140 00000 n
+0002784387 00000 n
+0002806152 00000 n
+0002827702 00000 n
+0002849139 00000 n
+0002870613 00000 n
+0002891878 00000 n
+0002914033 00000 n
+0002956912 00000 n
+0002978248 00000 n
+0002999119 00000 n
+0003020747 00000 n
+0003042038 00000 n
+0003064132 00000 n
+0003086377 00000 n
+0003108223 00000 n
+0003130683 00000 n
+0003152299 00000 n
+0003170763 00000 n
+0003233578 00000 n
+0003255689 00000 n
+0003277269 00000 n
+0003299242 00000 n
+0003321203 00000 n
+0003342098 00000 n
+0003363411 00000 n
+0003386193 00000 n
+0003409378 00000 n
+0003432490 00000 n
+0003453518 00000 n
+0003495238 00000 n
+0003510301 00000 n
+0003567696 00000 n
+0003615863 00000 n
+0003650891 00000 n
+0003669632 00000 n
+0003673380 00000 n
+0003683855 00000 n
+0003704357 00000 n
+0003718623 00000 n
+0003733633 00000 n
+0003759731 00000 n
+0003784054 00000 n
+0003806935 00000 n
+0003829767 00000 n
+0003852352 00000 n
+0003876992 00000 n
+0003900151 00000 n
+0003922783 00000 n
+0003945034 00000 n
+0003968047 00000 n
+0003991391 00000 n
+0004015741 00000 n
+0004039233 00000 n
+0004062214 00000 n
+0004085294 00000 n
+0004107633 00000 n
+0004133573 00000 n
+0004156970 00000 n
+0004181160 00000 n
+0004205488 00000 n
+0004229069 00000 n
+0004252246 00000 n
+0004276651 00000 n
+0004300732 00000 n
+0004323009 00000 n
+0004346653 00000 n
+0004369083 00000 n
+0004398651 00000 n
+0004422686 00000 n
+0004445807 00000 n
+0004468467 00000 n
+0004490778 00000 n
+0004512245 00000 n
+0004535999 00000 n
+0004558483 00000 n
+0004582152 00000 n
+0004605460 00000 n
+0004628178 00000 n
+0004657082 00000 n
+0004679662 00000 n
+0004703617 00000 n
+0004726684 00000 n
+0004749769 00000 n
+0004772895 00000 n
+0004796243 00000 n
+0004818968 00000 n
+0004840801 00000 n
+0004864877 00000 n
+0004887603 00000 n
+0004916892 00000 n
+0004940435 00000 n
+0004962612 00000 n
+0004986831 00000 n
+0005010044 00000 n
+0005032928 00000 n
+0005056580 00000 n
+0005078840 00000 n
+0005102970 00000 n
+0005124736 00000 n
+0005148071 00000 n
+0005177059 00000 n
+0005200432 00000 n
+0005223606 00000 n
+0005246594 00000 n
+0005269811 00000 n
+0005292409 00000 n
+0005314358 00000 n
+0005337995 00000 n
+0005361090 00000 n
+0005383650 00000 n
+0005407255 00000 n
+0005436020 00000 n
+0005458512 00000 n
+0005482512 00000 n
+0005507899 00000 n
+0005530123 00000 n
+0005551770 00000 n
+0005574745 00000 n
+0005597605 00000 n
+0005619438 00000 n
+0005642322 00000 n
+0007344240 00000 n
+0007344705 00000 n
+0007344303 00000 n
+0007344641 00000 n
+0007344822 00000 n
+0007344888 00000 n
+0007344911 00000 n
+0007345213 00000 n
+0007345291 00000 n
+0007345657 00000 n
+0007345757 00000 n
+trailer <</Size 306/Root 1 0 R/Info 305 0 R/ID[<303169ECE1024C918EE9BAFAA71271A8><267E8E7C61CE467AA831715E34FC8183>]>> startxref 7345941 %%EOF \ No newline at end of file
diff --git a/spec/fixtures/patchfiles/0001-A-commit-from-a-patch.patch b/spec/fixtures/patchfiles/0001-A-commit-from-a-patch.patch
new file mode 100644
index 00000000000..cc38682a0ab
--- /dev/null
+++ b/spec/fixtures/patchfiles/0001-A-commit-from-a-patch.patch
@@ -0,0 +1,19 @@
+From 3fee0042e610fb3563e4379e316704cb1210f3de Mon Sep 17 00:00:00 2001
+From: Patch User <patchuser@gitlab.org>
+Date: Thu, 18 Oct 2018 13:40:35 +0200
+Subject: [PATCH] A commit from a patch
+
+---
+ README | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/README b/README
+index 3742e48..e40a3b9 100644
+--- a/README
++++ b/README
+@@ -1 +1,3 @@
+ Sample repo for testing gitlab features
++
++This was applied in a patch!
+--
+2.19.1
diff --git a/spec/fixtures/patchfiles/0001-This-does-not-apply-to-the-feature-branch.patch b/spec/fixtures/patchfiles/0001-This-does-not-apply-to-the-feature-branch.patch
new file mode 100644
index 00000000000..905002ae898
--- /dev/null
+++ b/spec/fixtures/patchfiles/0001-This-does-not-apply-to-the-feature-branch.patch
@@ -0,0 +1,23 @@
+From 00c68c2b4f954370ce82a1162bc29c13f524897e Mon Sep 17 00:00:00 2001
+From: Patch User <patchuser@gitlab.org>
+Date: Mon, 22 Oct 2018 11:05:48 +0200
+Subject: [PATCH] This does not apply to the `feature` branch
+
+---
+ files/ruby/feature.rb | 5 +++++
+ 1 file changed, 5 insertions(+)
+ create mode 100644 files/ruby/feature.rb
+
+diff --git a/files/ruby/feature.rb b/files/ruby/feature.rb
+new file mode 100644
+index 0000000..fef26e4
+--- /dev/null
++++ b/files/ruby/feature.rb
+@@ -0,0 +1,5 @@
++class Feature
++ def bar
++ puts 'foo'
++ end
++end
+--
+2.19.1
diff --git a/spec/fixtures/security-reports/feature-branch.zip b/spec/fixtures/security-reports/feature-branch.zip
new file mode 100644
index 00000000000..730ce3dc5f8
--- /dev/null
+++ b/spec/fixtures/security-reports/feature-branch.zip
Binary files differ
diff --git a/spec/fixtures/security-reports/feature-branch/gl-container-scanning-report.json b/spec/fixtures/security-reports/feature-branch/gl-container-scanning-report.json
new file mode 100644
index 00000000000..9840382df6f
--- /dev/null
+++ b/spec/fixtures/security-reports/feature-branch/gl-container-scanning-report.json
@@ -0,0 +1,18 @@
+{
+ "image": "registry.gitlab.com/bikebilly/auto-devops-10-6/feature-branch:e7315ba964febb11bac8f5cd6ec433db8a3a1583",
+ "unapproved": [
+ "CVE-2017-15650"
+ ],
+ "vulnerabilities": [
+ {
+ "featurename": "musl",
+ "featureversion": "1.1.14-r15",
+ "vulnerability": "CVE-2017-15650",
+ "namespace": "alpine:v3.4",
+ "description": "",
+ "link": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15650",
+ "severity": "Medium",
+ "fixedby": "1.1.14-r16"
+ }
+ ]
+}
diff --git a/spec/fixtures/security-reports/feature-branch/gl-dast-report.json b/spec/fixtures/security-reports/feature-branch/gl-dast-report.json
new file mode 100644
index 00000000000..3a308bf047e
--- /dev/null
+++ b/spec/fixtures/security-reports/feature-branch/gl-dast-report.json
@@ -0,0 +1,40 @@
+{
+ "site": {
+ "alerts": [
+ {
+ "sourceid": "3",
+ "wascid": "15",
+ "cweid": "16",
+ "reference": "<p>http://msdn.microsoft.com/en-us/library/ie/gg622941%28v=vs.85%29.aspx</p><p>https://www.owasp.org/index.php/List_of_useful_HTTP_headers</p>",
+ "otherinfo": "<p>This issue still applies to error type pages (401, 403, 500, etc) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.</p><p>At \"High\" threshold this scanner will not alert on client or server error responses.</p>",
+ "solution": "<p>Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.</p><p>If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.</p>",
+ "count": "2",
+ "pluginid": "10021",
+ "alert": "X-Content-Type-Options Header Missing",
+ "name": "X-Content-Type-Options Header Missing",
+ "riskcode": "1",
+ "confidence": "2",
+ "riskdesc": "Low (Medium)",
+ "desc": "<p>The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.</p>",
+ "instances": [
+ {
+ "param": "X-Content-Type-Options",
+ "method": "GET",
+ "uri": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io"
+ },
+ {
+ "param": "X-Content-Type-Options",
+ "method": "GET",
+ "uri": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io/"
+ }
+ ]
+ }
+ ],
+ "@ssl": "false",
+ "@port": "80",
+ "@host": "bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io",
+ "@name": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io"
+ },
+ "@generated": "Fri, 13 Apr 2018 09:22:01",
+ "@version": "2.7.0"
+}
diff --git a/spec/fixtures/security-reports/feature-branch/gl-dependency-scanning-report.json b/spec/fixtures/security-reports/feature-branch/gl-dependency-scanning-report.json
new file mode 100644
index 00000000000..314f04107eb
--- /dev/null
+++ b/spec/fixtures/security-reports/feature-branch/gl-dependency-scanning-report.json
@@ -0,0 +1,154 @@
+[
+ {
+ "category": "dependency_scanning",
+ "name": "io.netty/netty - CVE-2014-3488",
+ "message": "DoS by CPU exhaustion when using malicious SSL packets",
+ "cve": "app/pom.xml:io.netty/netty@3.9.1.Final:CVE-2014-3488",
+ "severity": "Unknown",
+ "solution": "Upgrade to the latest version",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "app/pom.xml"
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
+ "value": "d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
+ "url": "https://deps.sec.gitlab.com/packages/maven/io.netty/netty/versions/3.9.1.Final/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2014-3488",
+ "value": "CVE-2014-3488",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3488"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://bugzilla.redhat.com/CVE-2014-3488"
+ },
+ {
+ "url": "http://netty.io/news/2014/06/11/3.html"
+ },
+ {
+ "url": "https://github.com/netty/netty/issues/2562"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "app/pom.xml",
+ "url": "https://bugzilla.redhat.com/CVE-2014-3488",
+ "tool": "gemnasium"
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "Django - CVE-2017-12794",
+ "message": "Possible XSS in traceback section of technical 500 debug page",
+ "cve": "app/requirements.txt:Django@1.11.3:CVE-2017-12794",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version or apply patch.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "app/requirements.txt"
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-6162a015-8635-4a15-8d7c-dc9321db366f",
+ "value": "6162a015-8635-4a15-8d7c-dc9321db366f",
+ "url": "https://deps.sec.gitlab.com/packages/pypi/Django/versions/1.11.3/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2017-12794",
+ "value": "CVE-2017-12794",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-12794"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "app/requirements.txt",
+ "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/",
+ "tool": "gemnasium"
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "nokogiri - USN-3424-1",
+ "message": "Vulnerabilities in libxml2",
+ "cve": "rails/Gemfile.lock:nokogiri@1.8.0:USN-3424-1",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "rails/Gemfile.lock"
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-06565b64-486d-4326-b906-890d9915804d",
+ "value": "06565b64-486d-4326-b906-890d9915804d",
+ "url": "https://deps.sec.gitlab.com/packages/gem/nokogiri/versions/1.8.0/advisories"
+ },
+ {
+ "type": "usn",
+ "name": "USN-3424-1",
+ "value": "USN-3424-1",
+ "url": "https://usn.ubuntu.com/3424-1/"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1673"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "rails/Gemfile.lock",
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1673",
+ "tool": "gemnasium"
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "ffi - CVE-2018-1000201",
+ "message": "ruby-ffi DDL loading issue on Windows OS",
+ "cve": "ffi:1.9.18:CVE-2018-1000201",
+ "severity": "High",
+ "solution": "upgrade to \u003e= 1.9.24",
+ "scanner": {
+ "id": "bundler_audit",
+ "name": "bundler-audit"
+ },
+ "location": {
+ "file": "sast-sample-rails/Gemfile.lock"
+ },
+ "identifiers": [
+ {
+ "type": "cve",
+ "name": "CVE-2018-1000201",
+ "value": "CVE-2018-1000201",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-1000201"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://github.com/ffi/ffi/releases/tag/1.9.24"
+ }
+ ],
+ "priority": "High",
+ "file": "sast-sample-rails/Gemfile.lock",
+ "url": "https://github.com/ffi/ffi/releases/tag/1.9.24",
+ "tool": "bundler_audit"
+ }
+]
diff --git a/spec/fixtures/security-reports/feature-branch/gl-license-management-report.json b/spec/fixtures/security-reports/feature-branch/gl-license-management-report.json
new file mode 100644
index 00000000000..c1d20fa02fa
--- /dev/null
+++ b/spec/fixtures/security-reports/feature-branch/gl-license-management-report.json
@@ -0,0 +1,242 @@
+{
+ "licenses": [
+ {
+ "count": 13,
+ "name": "MIT"
+ },
+ {
+ "count": 2,
+ "name": "New BSD"
+ },
+ {
+ "count": 1,
+ "name": "LGPL"
+ }
+ ],
+ "dependencies": [
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "bundler",
+ "url": "http://bundler.io",
+ "description": "The best way to manage your application's dependencies",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "concurrent-ruby",
+ "url": "http://www.concurrent-ruby.com",
+ "description": "Modern concurrency tools for Ruby. Inspired by Erlang, Clojure, Scala, Haskell, F#, C#, Java, and classic concurrency patterns.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "connection_pool",
+ "url": "https://github.com/mperham/connection_pool",
+ "description": "Generic connection pool for Ruby",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "mini_portile2",
+ "url": "http://github.com/flavorjones/mini_portile",
+ "description": "Simplistic port-like solution for developers",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "mustermann",
+ "url": "https://github.com/sinatra/mustermann",
+ "description": "Your personal string matching expert.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "nokogiri",
+ "url": "http://nokogiri.org",
+ "description": "Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "New BSD",
+ "url": "http://opensource.org/licenses/BSD-3-Clause"
+ },
+ "dependency": {
+ "name": "pg",
+ "url": "https://bitbucket.org/ged/ruby-pg",
+ "description": "Pg is the Ruby interface to the {PostgreSQL RDBMS}[http://www.postgresql.org/]",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "New BSD",
+ "url": "http://opensource.org/licenses/BSD-3-Clause"
+ },
+ "dependency": {
+ "name": "puma",
+ "url": "http://puma.io",
+ "description": "Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for Ruby/Rack applications",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "rack",
+ "url": "https://rack.github.io/",
+ "description": "a modular Ruby webserver interface",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "rack-protection",
+ "url": "http://github.com/sinatra/sinatra/tree/master/rack-protection",
+ "description": "Protect against typical web attacks, works with all Rack apps, including Rails.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "redis",
+ "url": "https://github.com/redis/redis-rb",
+ "description": "A Ruby client library for Redis",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "LGPL",
+ "url": "http://www.gnu.org/licenses/lgpl.txt"
+ },
+ "dependency": {
+ "name": "sidekiq",
+ "url": "http://sidekiq.org",
+ "description": "Simple, efficient background processing for Ruby",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "sinatra",
+ "url": "http://www.sinatrarb.com/",
+ "description": "Classy web-development dressed in a DSL",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "slim",
+ "url": "http://slim-lang.com/",
+ "description": "Slim is a template language.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "temple",
+ "url": "https://github.com/judofyr/temple",
+ "description": "Template compilation framework in Ruby",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "tilt",
+ "url": "http://github.com/rtomayko/tilt/",
+ "description": "Generic interface to multiple Ruby template engines",
+ "pathes": [
+ "."
+ ]
+ }
+ }
+ ]
+}
diff --git a/spec/fixtures/security-reports/feature-branch/gl-sast-report.json b/spec/fixtures/security-reports/feature-branch/gl-sast-report.json
new file mode 100644
index 00000000000..a85b9be8b5f
--- /dev/null
+++ b/spec/fixtures/security-reports/feature-branch/gl-sast-report.json
@@ -0,0 +1,944 @@
+[
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:52865813c884a507be1f152d654245af34aba8a391626d01f1ab6d3f52ec8779:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 1,
+ "end_line": 1
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B108",
+ "value": "B108",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "line": 1,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "name": "Predictable pseudorandom number generator",
+ "message": "Predictable pseudorandom number generator",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:47:PREDICTABLE_RANDOM",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 47,
+ "end_line": 47,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "generateSecretToken2"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-PREDICTABLE_RANDOM",
+ "value": "PREDICTABLE_RANDOM",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
+ }
+ ],
+ "priority": "Medium",
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "line": 47,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "name": "Predictable pseudorandom number generator",
+ "message": "Predictable pseudorandom number generator",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:41:PREDICTABLE_RANDOM",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 41,
+ "end_line": 41,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "generateSecretToken1"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-PREDICTABLE_RANDOM",
+ "value": "PREDICTABLE_RANDOM",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
+ }
+ ],
+ "priority": "Medium",
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "line": 41,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:cb203b465dffb0cb3a8e8bd8910b84b93b0a5995a938e4b903dbb0cd6ffa1254:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 11,
+ "end_line": 11
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 11,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:a7173c43ae66bd07466632d819d450e0071e02dbf782763640d1092981f9631b:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 12,
+ "end_line": 12
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 12,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:017017b77deb0b8369b6065947833eeea752a92ec8a700db590fece3e934cf0d:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 13,
+ "end_line": 13
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 13,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:45fc8c53aea7b84f06bc4e590cc667678d6073c4c8a1d471177ca2146fb22db2:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 14,
+ "end_line": 14
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 14,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Pickle library appears to be in use, possible security issue.",
+ "cve": "python/imports/imports-aliases.py:5f200d47291e7bbd8352db23019b85453ca048dd98ea0c291260fa7d009963a4:B301",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 15,
+ "end_line": 15
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B301",
+ "value": "B301"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 15,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "name": "ECB mode is insecure",
+ "message": "ECB mode is insecure",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:ECB_MODE",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 29,
+ "end_line": 29,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "insecureCypher"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-ECB_MODE",
+ "value": "ECB_MODE",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE"
+ }
+ ],
+ "priority": "Medium",
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "line": 29,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "name": "Cipher with no integrity",
+ "message": "Cipher with no integrity",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:CIPHER_INTEGRITY",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 29,
+ "end_line": 29,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "insecureCypher"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-CIPHER_INTEGRITY",
+ "value": "CIPHER_INTEGRITY",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY"
+ }
+ ],
+ "priority": "Medium",
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "line": 29,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:63dd4d626855555b816985d82c4614a790462a0a3ada89dc58eb97f9c50f3077:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 14,
+ "end_line": 14
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B108",
+ "value": "B108",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "line": 14,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:4ad6d4c40a8c263fc265f3384724014e0a4f8dd6200af83e51ff120420038031:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 10,
+ "end_line": 10
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B108",
+ "value": "B108",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "line": 10,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-aliases.py:2c3e1fa1e54c3c6646e8bcfaee2518153c6799b77587ff8d9a7b0631f6d34785:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 1,
+ "end_line": 1
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-aliases.py",
+ "line": 1,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports.py:af58d07f6ad519ef5287fcae65bf1a6999448a1a3a8bc1ac2a11daa80d0b96bf:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports.py",
+ "start_line": 2,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports.py",
+ "line": 2,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports.py:8de9bc98029d212db530785a5f6780cfa663548746ff228ab8fa96c5bb82f089:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports.py",
+ "start_line": 4,
+ "end_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports.py",
+ "line": 4,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:97c30f1d76d2a88913e3ce9ae74087874d740f87de8af697a9c455f01119f633:B106",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 22,
+ "end_line": 22
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B106",
+ "value": "B106",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 22,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'root'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:7431c73a0bc16d94ece2a2e75ef38f302574d42c37ac0c3c38ad0b3bf8a59f10:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 5,
+ "end_line": 5
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 5,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: ''",
+ "cve": "python/hardcoded/hardcoded-passwords.py:d2d1857c27caedd49c57bfbcdc23afcc92bd66a22701fcdc632869aab4ca73ee:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 9,
+ "end_line": 9
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 9,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'ajklawejrkl42348swfgkg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:fb3866215a61393a5c9c32a3b60e2058171a23219c353f722cbd3567acab21d2:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 13,
+ "end_line": 13
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 13,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:63c62a8b7e1e5224439bd26b28030585ac48741e28ca64561a6071080c560a5f:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 23,
+ "end_line": 23
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 23,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:4311b06d08df8fa58229b341c531da8e1a31ec4520597bdff920cd5c098d86f9:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 24,
+ "end_line": 24
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 24,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports-function.py:5858400c2f39047787702de44d03361ef8d954c9d14bd54ee1c2bef9e6a7df93:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-function.py",
+ "start_line": 4,
+ "end_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-function.py",
+ "line": 4,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports-function.py:dbda3cf4190279d30e0aad7dd137eca11272b0b225e8af4e8bf39682da67d956:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-function.py",
+ "start_line": 2,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-function.py",
+ "line": 2,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-from.py:eb8a0db9cd1a8c1ab39a77e6025021b1261cc2a0b026b2f4a11fca4e0636d8dd:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 7,
+ "end_line": 7
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-from.py",
+ "line": 7,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "subprocess call with shell=True seems safe, but may be changed in the future, consider rewriting without shell",
+ "cve": "python/imports/imports-aliases.py:f99f9721e27537fbcb6699a4cf39c6740d6234d2c6f06cfc2d9ea977313c483d:B602",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 9,
+ "end_line": 9
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B602",
+ "value": "B602",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-aliases.py",
+ "line": 9,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports-from.py:332a12ab1146698f614a905ce6a6a5401497a12281aef200e80522711c69dcf4:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 6,
+ "end_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-from.py",
+ "line": 6,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-from.py:0a48de4a3d5348853a03666cb574697e3982998355e7a095a798bd02a5947276:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 1,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-from.py",
+ "line": 1,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports-aliases.py:51b71661dff994bde3529639a727a678c8f5c4c96f00d300913f6d5be1bbdf26:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 7,
+ "end_line": 8
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-aliases.py",
+ "line": 7,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with loads module.",
+ "cve": "python/imports/imports-aliases.py:6ff02aeb3149c01ab68484d794a94f58d5d3e3bb0d58557ef4153644ea68ea54:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 6,
+ "end_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-aliases.py",
+ "line": 6,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
+ "cve": "c/subdir/utils.c:b466873101951fe96e1332f6728eb7010acbbd5dfc3b65d7d53571d091a06d9e:CWE-119!/CWE-120",
+ "confidence": "Low",
+ "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "c/subdir/utils.c",
+ "start_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-119",
+ "value": "119",
+ "url": "https://cwe.mitre.org/data/definitions/119.html"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
+ "file": "c/subdir/utils.c",
+ "line": 4,
+ "url": "https://cwe.mitre.org/data/definitions/119.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362)",
+ "cve": "c/subdir/utils.c:bab681140fcc8fc3085b6bba74081b44ea145c1c98b5e70cf19ace2417d30770:CWE-362",
+ "confidence": "Low",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "c/subdir/utils.c",
+ "start_line": 8
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-362",
+ "value": "362",
+ "url": "https://cwe.mitre.org/data/definitions/362.html"
+ }
+ ],
+ "file": "c/subdir/utils.c",
+ "line": 8,
+ "url": "https://cwe.mitre.org/data/definitions/362.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
+ "cve": "cplusplus/src/hello.cpp:c8c6dd0afdae6814194cf0930b719f757ab7b379cf8f261e7f4f9f2f323a818a:CWE-119!/CWE-120",
+ "confidence": "Low",
+ "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "cplusplus/src/hello.cpp",
+ "start_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-119",
+ "value": "119",
+ "url": "https://cwe.mitre.org/data/definitions/119.html"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
+ "file": "cplusplus/src/hello.cpp",
+ "line": 6,
+ "url": "https://cwe.mitre.org/data/definitions/119.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)",
+ "cve": "cplusplus/src/hello.cpp:331c04062c4fe0c7c486f66f59e82ad146ab33cdd76ae757ca41f392d568cbd0:CWE-120",
+ "confidence": "Low",
+ "solution": "Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "cplusplus/src/hello.cpp",
+ "start_line": 7
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
+ "file": "cplusplus/src/hello.cpp",
+ "line": 7,
+ "url": "https://cwe.mitre.org/data/definitions/120.html",
+ "tool": "flawfinder"
+ }
+]
diff --git a/spec/fixtures/security-reports/master.zip b/spec/fixtures/security-reports/master.zip
new file mode 100644
index 00000000000..4684aecb738
--- /dev/null
+++ b/spec/fixtures/security-reports/master.zip
Binary files differ
diff --git a/spec/fixtures/security-reports/master/gl-container-scanning-report.json b/spec/fixtures/security-reports/master/gl-container-scanning-report.json
new file mode 100644
index 00000000000..500c19e3abb
--- /dev/null
+++ b/spec/fixtures/security-reports/master/gl-container-scanning-report.json
@@ -0,0 +1,18 @@
+{
+ "image": "registry.gitlab.com/bikebilly/auto-devops-10-6/feature-branch:e7315ba964febb11bac8f5cd6ec433db8a3a1583",
+ "unapproved": [
+ "CVE-2017-15651"
+ ],
+ "vulnerabilities": [
+ {
+ "featurename": "musl",
+ "featureversion": "1.1.14-r15",
+ "vulnerability": "CVE-2017-15651",
+ "namespace": "alpine:v3.4",
+ "description": "",
+ "link": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15651",
+ "severity": "Medium",
+ "fixedby": "1.1.14-r16"
+ }
+ ]
+}
diff --git a/spec/fixtures/security-reports/master/gl-dast-report.json b/spec/fixtures/security-reports/master/gl-dast-report.json
new file mode 100644
index 00000000000..3a308bf047e
--- /dev/null
+++ b/spec/fixtures/security-reports/master/gl-dast-report.json
@@ -0,0 +1,40 @@
+{
+ "site": {
+ "alerts": [
+ {
+ "sourceid": "3",
+ "wascid": "15",
+ "cweid": "16",
+ "reference": "<p>http://msdn.microsoft.com/en-us/library/ie/gg622941%28v=vs.85%29.aspx</p><p>https://www.owasp.org/index.php/List_of_useful_HTTP_headers</p>",
+ "otherinfo": "<p>This issue still applies to error type pages (401, 403, 500, etc) as those pages are often still affected by injection issues, in which case there is still concern for browsers sniffing pages away from their actual content type.</p><p>At \"High\" threshold this scanner will not alert on client or server error responses.</p>",
+ "solution": "<p>Ensure that the application/web server sets the Content-Type header appropriately, and that it sets the X-Content-Type-Options header to 'nosniff' for all web pages.</p><p>If possible, ensure that the end user uses a standards-compliant and modern web browser that does not perform MIME-sniffing at all, or that can be directed by the web application/web server to not perform MIME-sniffing.</p>",
+ "count": "2",
+ "pluginid": "10021",
+ "alert": "X-Content-Type-Options Header Missing",
+ "name": "X-Content-Type-Options Header Missing",
+ "riskcode": "1",
+ "confidence": "2",
+ "riskdesc": "Low (Medium)",
+ "desc": "<p>The Anti-MIME-Sniffing header X-Content-Type-Options was not set to 'nosniff'. This allows older versions of Internet Explorer and Chrome to perform MIME-sniffing on the response body, potentially causing the response body to be interpreted and displayed as a content type other than the declared content type. Current (early 2014) and legacy versions of Firefox will use the declared content type (if one is set), rather than performing MIME-sniffing.</p>",
+ "instances": [
+ {
+ "param": "X-Content-Type-Options",
+ "method": "GET",
+ "uri": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io"
+ },
+ {
+ "param": "X-Content-Type-Options",
+ "method": "GET",
+ "uri": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io/"
+ }
+ ]
+ }
+ ],
+ "@ssl": "false",
+ "@port": "80",
+ "@host": "bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io",
+ "@name": "http://bikebilly-spring-auto-devops-review-feature-br-3y2gpb.35.192.176.43.xip.io"
+ },
+ "@generated": "Fri, 13 Apr 2018 09:22:01",
+ "@version": "2.7.0"
+}
diff --git a/spec/fixtures/security-reports/master/gl-dependency-scanning-report.json b/spec/fixtures/security-reports/master/gl-dependency-scanning-report.json
new file mode 100644
index 00000000000..314f04107eb
--- /dev/null
+++ b/spec/fixtures/security-reports/master/gl-dependency-scanning-report.json
@@ -0,0 +1,154 @@
+[
+ {
+ "category": "dependency_scanning",
+ "name": "io.netty/netty - CVE-2014-3488",
+ "message": "DoS by CPU exhaustion when using malicious SSL packets",
+ "cve": "app/pom.xml:io.netty/netty@3.9.1.Final:CVE-2014-3488",
+ "severity": "Unknown",
+ "solution": "Upgrade to the latest version",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "app/pom.xml"
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
+ "value": "d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
+ "url": "https://deps.sec.gitlab.com/packages/maven/io.netty/netty/versions/3.9.1.Final/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2014-3488",
+ "value": "CVE-2014-3488",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3488"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://bugzilla.redhat.com/CVE-2014-3488"
+ },
+ {
+ "url": "http://netty.io/news/2014/06/11/3.html"
+ },
+ {
+ "url": "https://github.com/netty/netty/issues/2562"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "app/pom.xml",
+ "url": "https://bugzilla.redhat.com/CVE-2014-3488",
+ "tool": "gemnasium"
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "Django - CVE-2017-12794",
+ "message": "Possible XSS in traceback section of technical 500 debug page",
+ "cve": "app/requirements.txt:Django@1.11.3:CVE-2017-12794",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version or apply patch.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "app/requirements.txt"
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-6162a015-8635-4a15-8d7c-dc9321db366f",
+ "value": "6162a015-8635-4a15-8d7c-dc9321db366f",
+ "url": "https://deps.sec.gitlab.com/packages/pypi/Django/versions/1.11.3/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2017-12794",
+ "value": "CVE-2017-12794",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-12794"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "app/requirements.txt",
+ "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/",
+ "tool": "gemnasium"
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "nokogiri - USN-3424-1",
+ "message": "Vulnerabilities in libxml2",
+ "cve": "rails/Gemfile.lock:nokogiri@1.8.0:USN-3424-1",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "rails/Gemfile.lock"
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-06565b64-486d-4326-b906-890d9915804d",
+ "value": "06565b64-486d-4326-b906-890d9915804d",
+ "url": "https://deps.sec.gitlab.com/packages/gem/nokogiri/versions/1.8.0/advisories"
+ },
+ {
+ "type": "usn",
+ "name": "USN-3424-1",
+ "value": "USN-3424-1",
+ "url": "https://usn.ubuntu.com/3424-1/"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1673"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "rails/Gemfile.lock",
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1673",
+ "tool": "gemnasium"
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "ffi - CVE-2018-1000201",
+ "message": "ruby-ffi DDL loading issue on Windows OS",
+ "cve": "ffi:1.9.18:CVE-2018-1000201",
+ "severity": "High",
+ "solution": "upgrade to \u003e= 1.9.24",
+ "scanner": {
+ "id": "bundler_audit",
+ "name": "bundler-audit"
+ },
+ "location": {
+ "file": "sast-sample-rails/Gemfile.lock"
+ },
+ "identifiers": [
+ {
+ "type": "cve",
+ "name": "CVE-2018-1000201",
+ "value": "CVE-2018-1000201",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-1000201"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://github.com/ffi/ffi/releases/tag/1.9.24"
+ }
+ ],
+ "priority": "High",
+ "file": "sast-sample-rails/Gemfile.lock",
+ "url": "https://github.com/ffi/ffi/releases/tag/1.9.24",
+ "tool": "bundler_audit"
+ }
+]
diff --git a/spec/fixtures/security-reports/master/gl-license-management-report.json b/spec/fixtures/security-reports/master/gl-license-management-report.json
new file mode 100644
index 00000000000..fe91e4fb7ee
--- /dev/null
+++ b/spec/fixtures/security-reports/master/gl-license-management-report.json
@@ -0,0 +1,150 @@
+{
+ "licenses": [
+ {
+ "count": 10,
+ "name": "MIT"
+ }
+ ],
+ "dependencies": [
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "mini_portile2",
+ "url": "http://github.com/flavorjones/mini_portile",
+ "description": "Simplistic port-like solution for developers",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "mustermann",
+ "url": "https://github.com/sinatra/mustermann",
+ "description": "Your personal string matching expert.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "nokogiri",
+ "url": "http://nokogiri.org",
+ "description": "Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "rack",
+ "url": "https://rack.github.io/",
+ "description": "a modular Ruby webserver interface",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "rack-protection",
+ "url": "http://github.com/sinatra/sinatra/tree/master/rack-protection",
+ "description": "Protect against typical web attacks, works with all Rack apps, including Rails.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "redis",
+ "url": "https://github.com/redis/redis-rb",
+ "description": "A Ruby client library for Redis",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "sinatra",
+ "url": "http://www.sinatrarb.com/",
+ "description": "Classy web-development dressed in a DSL",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "slim",
+ "url": "http://slim-lang.com/",
+ "description": "Slim is a template language.",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "temple",
+ "url": "https://github.com/judofyr/temple",
+ "description": "Template compilation framework in Ruby",
+ "pathes": [
+ "."
+ ]
+ }
+ },
+ {
+ "license": {
+ "name": "MIT",
+ "url": "http://opensource.org/licenses/mit-license"
+ },
+ "dependency": {
+ "name": "tilt",
+ "url": "http://github.com/rtomayko/tilt/",
+ "description": "Generic interface to multiple Ruby template engines",
+ "pathes": [
+ "."
+ ]
+ }
+ }
+ ]
+}
diff --git a/spec/fixtures/security-reports/master/gl-sast-report.json b/spec/fixtures/security-reports/master/gl-sast-report.json
new file mode 100644
index 00000000000..a85b9be8b5f
--- /dev/null
+++ b/spec/fixtures/security-reports/master/gl-sast-report.json
@@ -0,0 +1,944 @@
+[
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:52865813c884a507be1f152d654245af34aba8a391626d01f1ab6d3f52ec8779:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 1,
+ "end_line": 1
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B108",
+ "value": "B108",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "line": 1,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "name": "Predictable pseudorandom number generator",
+ "message": "Predictable pseudorandom number generator",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:47:PREDICTABLE_RANDOM",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 47,
+ "end_line": 47,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "generateSecretToken2"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-PREDICTABLE_RANDOM",
+ "value": "PREDICTABLE_RANDOM",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
+ }
+ ],
+ "priority": "Medium",
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "line": 47,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "name": "Predictable pseudorandom number generator",
+ "message": "Predictable pseudorandom number generator",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:41:PREDICTABLE_RANDOM",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 41,
+ "end_line": 41,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "generateSecretToken1"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-PREDICTABLE_RANDOM",
+ "value": "PREDICTABLE_RANDOM",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM"
+ }
+ ],
+ "priority": "Medium",
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "line": 41,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#PREDICTABLE_RANDOM",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:cb203b465dffb0cb3a8e8bd8910b84b93b0a5995a938e4b903dbb0cd6ffa1254:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 11,
+ "end_line": 11
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 11,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:a7173c43ae66bd07466632d819d450e0071e02dbf782763640d1092981f9631b:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 12,
+ "end_line": 12
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 12,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:017017b77deb0b8369b6065947833eeea752a92ec8a700db590fece3e934cf0d:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 13,
+ "end_line": 13
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 13,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Use of insecure MD2, MD4, or MD5 hash function.",
+ "cve": "python/imports/imports-aliases.py:45fc8c53aea7b84f06bc4e590cc667678d6073c4c8a1d471177ca2146fb22db2:B303",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 14,
+ "end_line": 14
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B303",
+ "value": "B303"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 14,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Pickle library appears to be in use, possible security issue.",
+ "cve": "python/imports/imports-aliases.py:5f200d47291e7bbd8352db23019b85453ca048dd98ea0c291260fa7d009963a4:B301",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 15,
+ "end_line": 15
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B301",
+ "value": "B301"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/imports/imports-aliases.py",
+ "line": 15,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "name": "ECB mode is insecure",
+ "message": "ECB mode is insecure",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:ECB_MODE",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 29,
+ "end_line": 29,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "insecureCypher"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-ECB_MODE",
+ "value": "ECB_MODE",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE"
+ }
+ ],
+ "priority": "Medium",
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "line": 29,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#ECB_MODE",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "name": "Cipher with no integrity",
+ "message": "Cipher with no integrity",
+ "cve": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy:29:CIPHER_INTEGRITY",
+ "severity": "Medium",
+ "confidence": "High",
+ "scanner": {
+ "id": "find_sec_bugs",
+ "name": "Find Security Bugs"
+ },
+ "location": {
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "start_line": 29,
+ "end_line": 29,
+ "class": "com.gitlab.security_products.tests.App",
+ "method": "insecureCypher"
+ },
+ "identifiers": [
+ {
+ "type": "find_sec_bugs_type",
+ "name": "Find Security Bugs-CIPHER_INTEGRITY",
+ "value": "CIPHER_INTEGRITY",
+ "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY"
+ }
+ ],
+ "priority": "Medium",
+ "file": "groovy/src/main/java/com/gitlab/security_products/tests/App.groovy",
+ "line": 29,
+ "url": "https://find-sec-bugs.github.io/bugs.htm#CIPHER_INTEGRITY",
+ "tool": "find_sec_bugs"
+ },
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:63dd4d626855555b816985d82c4614a790462a0a3ada89dc58eb97f9c50f3077:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 14,
+ "end_line": 14
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B108",
+ "value": "B108",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "line": 14,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Probable insecure usage of temp file/directory.",
+ "cve": "python/hardcoded/hardcoded-tmp.py:4ad6d4c40a8c263fc265f3384724014e0a4f8dd6200af83e51ff120420038031:B108",
+ "severity": "Medium",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "start_line": 10,
+ "end_line": 10
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B108",
+ "value": "B108",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html"
+ }
+ ],
+ "priority": "Medium",
+ "file": "python/hardcoded/hardcoded-tmp.py",
+ "line": 10,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b108_hardcoded_tmp_directory.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-aliases.py:2c3e1fa1e54c3c6646e8bcfaee2518153c6799b77587ff8d9a7b0631f6d34785:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 1,
+ "end_line": 1
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-aliases.py",
+ "line": 1,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports.py:af58d07f6ad519ef5287fcae65bf1a6999448a1a3a8bc1ac2a11daa80d0b96bf:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports.py",
+ "start_line": 2,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports.py",
+ "line": 2,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports.py:8de9bc98029d212db530785a5f6780cfa663548746ff228ab8fa96c5bb82f089:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports.py",
+ "start_line": 4,
+ "end_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports.py",
+ "line": 4,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:97c30f1d76d2a88913e3ce9ae74087874d740f87de8af697a9c455f01119f633:B106",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 22,
+ "end_line": 22
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B106",
+ "value": "B106",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 22,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b106_hardcoded_password_funcarg.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'root'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:7431c73a0bc16d94ece2a2e75ef38f302574d42c37ac0c3c38ad0b3bf8a59f10:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 5,
+ "end_line": 5
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 5,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: ''",
+ "cve": "python/hardcoded/hardcoded-passwords.py:d2d1857c27caedd49c57bfbcdc23afcc92bd66a22701fcdc632869aab4ca73ee:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 9,
+ "end_line": 9
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 9,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'ajklawejrkl42348swfgkg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:fb3866215a61393a5c9c32a3b60e2058171a23219c353f722cbd3567acab21d2:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 13,
+ "end_line": 13
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 13,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:63c62a8b7e1e5224439bd26b28030585ac48741e28ca64561a6071080c560a5f:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 23,
+ "end_line": 23
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 23,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Possible hardcoded password: 'blerg'",
+ "cve": "python/hardcoded/hardcoded-passwords.py:4311b06d08df8fa58229b341c531da8e1a31ec4520597bdff920cd5c098d86f9:B105",
+ "severity": "Low",
+ "confidence": "Medium",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "start_line": 24,
+ "end_line": 24
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B105",
+ "value": "B105",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/hardcoded/hardcoded-passwords.py",
+ "line": 24,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b105_hardcoded_password_string.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports-function.py:5858400c2f39047787702de44d03361ef8d954c9d14bd54ee1c2bef9e6a7df93:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-function.py",
+ "start_line": 4,
+ "end_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-function.py",
+ "line": 4,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports-function.py:dbda3cf4190279d30e0aad7dd137eca11272b0b225e8af4e8bf39682da67d956:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-function.py",
+ "start_line": 2,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-function.py",
+ "line": 2,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-from.py:eb8a0db9cd1a8c1ab39a77e6025021b1261cc2a0b026b2f4a11fca4e0636d8dd:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 7,
+ "end_line": 7
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-from.py",
+ "line": 7,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "subprocess call with shell=True seems safe, but may be changed in the future, consider rewriting without shell",
+ "cve": "python/imports/imports-aliases.py:f99f9721e27537fbcb6699a4cf39c6740d6234d2c6f06cfc2d9ea977313c483d:B602",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 9,
+ "end_line": 9
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B602",
+ "value": "B602",
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-aliases.py",
+ "line": 9,
+ "url": "https://docs.openstack.org/bandit/latest/plugins/b602_subprocess_popen_with_shell_equals_true.html",
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with subprocess module.",
+ "cve": "python/imports/imports-from.py:332a12ab1146698f614a905ce6a6a5401497a12281aef200e80522711c69dcf4:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 6,
+ "end_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-from.py",
+ "line": 6,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with Popen module.",
+ "cve": "python/imports/imports-from.py:0a48de4a3d5348853a03666cb574697e3982998355e7a095a798bd02a5947276:B404",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-from.py",
+ "start_line": 1,
+ "end_line": 2
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B404",
+ "value": "B404"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-from.py",
+ "line": 1,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with pickle module.",
+ "cve": "python/imports/imports-aliases.py:51b71661dff994bde3529639a727a678c8f5c4c96f00d300913f6d5be1bbdf26:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 7,
+ "end_line": 8
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-aliases.py",
+ "line": 7,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Consider possible security implications associated with loads module.",
+ "cve": "python/imports/imports-aliases.py:6ff02aeb3149c01ab68484d794a94f58d5d3e3bb0d58557ef4153644ea68ea54:B403",
+ "severity": "Low",
+ "confidence": "High",
+ "scanner": {
+ "id": "bandit",
+ "name": "Bandit"
+ },
+ "location": {
+ "file": "python/imports/imports-aliases.py",
+ "start_line": 6,
+ "end_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "bandit_test_id",
+ "name": "Bandit Test ID B403",
+ "value": "B403"
+ }
+ ],
+ "priority": "Low",
+ "file": "python/imports/imports-aliases.py",
+ "line": 6,
+ "tool": "bandit"
+ },
+ {
+ "category": "sast",
+ "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
+ "cve": "c/subdir/utils.c:b466873101951fe96e1332f6728eb7010acbbd5dfc3b65d7d53571d091a06d9e:CWE-119!/CWE-120",
+ "confidence": "Low",
+ "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "c/subdir/utils.c",
+ "start_line": 4
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-119",
+ "value": "119",
+ "url": "https://cwe.mitre.org/data/definitions/119.html"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
+ "file": "c/subdir/utils.c",
+ "line": 4,
+ "url": "https://cwe.mitre.org/data/definitions/119.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Check when opening files - can an attacker redirect it (via symlinks), force the opening of special file type (e.g., device files), move things around to create a race condition, control its ancestors, or change its contents? (CWE-362)",
+ "cve": "c/subdir/utils.c:bab681140fcc8fc3085b6bba74081b44ea145c1c98b5e70cf19ace2417d30770:CWE-362",
+ "confidence": "Low",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "c/subdir/utils.c",
+ "start_line": 8
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-362",
+ "value": "362",
+ "url": "https://cwe.mitre.org/data/definitions/362.html"
+ }
+ ],
+ "file": "c/subdir/utils.c",
+ "line": 8,
+ "url": "https://cwe.mitre.org/data/definitions/362.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Statically-sized arrays can be improperly restricted, leading to potential overflows or other issues (CWE-119!/CWE-120)",
+ "cve": "cplusplus/src/hello.cpp:c8c6dd0afdae6814194cf0930b719f757ab7b379cf8f261e7f4f9f2f323a818a:CWE-119!/CWE-120",
+ "confidence": "Low",
+ "solution": "Perform bounds checking, use functions that limit length, or ensure that the size is larger than the maximum possible length",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "cplusplus/src/hello.cpp",
+ "start_line": 6
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-119",
+ "value": "119",
+ "url": "https://cwe.mitre.org/data/definitions/119.html"
+ },
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
+ "file": "cplusplus/src/hello.cpp",
+ "line": 6,
+ "url": "https://cwe.mitre.org/data/definitions/119.html",
+ "tool": "flawfinder"
+ },
+ {
+ "category": "sast",
+ "message": "Does not check for buffer overflows when copying to destination [MS-banned] (CWE-120)",
+ "cve": "cplusplus/src/hello.cpp:331c04062c4fe0c7c486f66f59e82ad146ab33cdd76ae757ca41f392d568cbd0:CWE-120",
+ "confidence": "Low",
+ "solution": "Consider using snprintf, strcpy_s, or strlcpy (warning: strncpy easily misused)",
+ "scanner": {
+ "id": "flawfinder",
+ "name": "Flawfinder"
+ },
+ "location": {
+ "file": "cplusplus/src/hello.cpp",
+ "start_line": 7
+ },
+ "identifiers": [
+ {
+ "type": "cwe",
+ "name": "CWE-120",
+ "value": "120",
+ "url": "https://cwe.mitre.org/data/definitions/120.html"
+ }
+ ],
+ "file": "cplusplus/src/hello.cpp",
+ "line": 7,
+ "url": "https://cwe.mitre.org/data/definitions/120.html",
+ "tool": "flawfinder"
+ }
+]
diff --git a/spec/fixtures/ssh_host_example_key.pub b/spec/fixtures/ssh_host_example_key.pub
index 6bac42b3ad0..d43315ddae8 100644
--- a/spec/fixtures/ssh_host_example_key.pub
+++ b/spec/fixtures/ssh_host_example_key.pub
@@ -1 +1 @@
-random content
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuRkAgwaap/pXThwCpjX8Wd5tR36Tqx3sW2sVVHs3UKB7kd+xNknw7e4qpuEATv56xHrhKm2+ye/JidTuQ/1EwFhjaz7I5wTslfVawQpeH1ZqAGmvdO/xTw+l7fgEFVlGVx9y0HV3m52y2C9yw82qmg+BohbTVgPtjjutpFc+CwLQxLTnTrRhZf5udQgz+YlwLv+Y0kDx6+DWWOl8N9+TWuGyFKBln79CyBgFcK5NFmF48kYn8W+r7rmawfw9XbuF1aa+6JF+6cNR1mCEonyrRLdXP+vWcxpLKYfejB0NmA1y+W9M/K53AcIHA5zlRQ49tFh0P22eh/Gl8JQ6yyuin foo@bar.mynet
diff --git a/spec/fixtures/trace/sample_trace b/spec/fixtures/trace/sample_trace
index 7bfe3f83b7b..3d8beb0dec2 100644
--- a/spec/fixtures/trace/sample_trace
+++ b/spec/fixtures/trace/sample_trace
@@ -2334,12 +2334,12 @@ Boards::Lists::MoveService
keeps position of lists when list type is closed
when list type is set to label
keeps position of lists when new position is nil
- keeps position of lists when new positon is equal to old position
- keeps position of lists when new positon is negative
- keeps position of lists when new positon is equal to number of labels lists
- keeps position of lists when new positon is greater than number of labels lists
- increments position of intermediate lists when new positon is equal to first position
- decrements position of intermediate lists when new positon is equal to last position
+ keeps position of lists when new position is equal to old position
+ keeps position of lists when new position is negative
+ keeps position of lists when new position is equal to number of labels lists
+ keeps position of lists when new position is greater than number of labels lists
+ increments position of intermediate lists when new position is equal to first position
+ decrements position of intermediate lists when new position is equal to last position
decrements position of intermediate lists when new position is greater than old position
increments position of intermediate lists when new position is lower than old position
when board parent is a group
@@ -2347,12 +2347,12 @@ Boards::Lists::MoveService
keeps position of lists when list type is closed
when list type is set to label
keeps position of lists when new position is nil
- keeps position of lists when new positon is equal to old position
- keeps position of lists when new positon is negative
- keeps position of lists when new positon is equal to number of labels lists
- keeps position of lists when new positon is greater than number of labels lists
- increments position of intermediate lists when new positon is equal to first position
- decrements position of intermediate lists when new positon is equal to last position
+ keeps position of lists when new position is equal to old position
+ keeps position of lists when new position is negative
+ keeps position of lists when new position is equal to number of labels lists
+ keeps position of lists when new position is greater than number of labels lists
+ increments position of intermediate lists when new position is equal to first position
+ decrements position of intermediate lists when new position is equal to last position
decrements position of intermediate lists when new position is greater than old position
increments position of intermediate lists when new position is lower than old position
diff --git a/spec/fixtures/valid.po b/spec/fixtures/valid.po
index e43fd5fea15..dbe2f952bad 100644
--- a/spec/fixtures/valid.po
+++ b/spec/fixtures/valid.po
@@ -790,9 +790,6 @@ msgstr "Establezca una contraseña en su cuenta para actualizar o enviar a travÃ
msgid "Set up CI"
msgstr "Configurar CI"
-msgid "Set up Koding"
-msgstr "Configurar Koding"
-
msgid "Set up auto deploy"
msgstr "Configurar auto despliegue"
diff --git a/spec/graphql/resolvers/issues_resolver_spec.rb b/spec/graphql/resolvers/issues_resolver_spec.rb
new file mode 100644
index 00000000000..ca90673521c
--- /dev/null
+++ b/spec/graphql/resolvers/issues_resolver_spec.rb
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+describe Resolvers::IssuesResolver do
+ include GraphqlHelpers
+
+ let(:current_user) { create(:user) }
+ set(:project) { create(:project) }
+ set(:issue) { create(:issue, project: project) }
+ set(:issue2) { create(:issue, project: project, title: 'foo') }
+
+ before do
+ project.add_developer(current_user)
+ end
+
+ describe '#resolve' do
+ it 'finds all issues' do
+ expect(resolve_issues).to contain_exactly(issue, issue2)
+ end
+
+ it 'searches issues' do
+ expect(resolve_issues(search: 'foo')).to contain_exactly(issue2)
+ end
+
+ it 'sort issues' do
+ expect(resolve_issues(sort: 'created_desc')).to eq [issue2, issue]
+ end
+
+ it 'returns issues user can see' do
+ project.add_guest(current_user)
+
+ create(:issue, confidential: true)
+
+ expect(resolve_issues).to contain_exactly(issue, issue2)
+ end
+ end
+
+ def resolve_issues(args = {}, context = { current_user: current_user })
+ resolve(described_class, obj: project, args: args, ctx: context)
+ end
+end
diff --git a/spec/graphql/types/issue_type_spec.rb b/spec/graphql/types/issue_type_spec.rb
new file mode 100644
index 00000000000..63a07647a60
--- /dev/null
+++ b/spec/graphql/types/issue_type_spec.rb
@@ -0,0 +1,7 @@
+require 'spec_helper'
+
+describe GitlabSchema.types['Issue'] do
+ it { expect(described_class).to expose_permissions_using(Types::PermissionTypes::Issue) }
+
+ it { expect(described_class.graphql_name).to eq('Issue') }
+end
diff --git a/spec/graphql/types/permission_types/issue_spec.rb b/spec/graphql/types/permission_types/issue_spec.rb
new file mode 100644
index 00000000000..c3f84629aa2
--- /dev/null
+++ b/spec/graphql/types/permission_types/issue_spec.rb
@@ -0,0 +1,12 @@
+require 'spec_helper'
+
+describe Types::PermissionTypes::Issue do
+ it do
+ expected_permissions = [
+ :read_issue, :admin_issue, :update_issue,
+ :create_note, :reopen_issue
+ ]
+
+ expect(described_class).to have_graphql_fields(expected_permissions)
+ end
+end
diff --git a/spec/graphql/types/permission_types/project_spec.rb b/spec/graphql/types/permission_types/project_spec.rb
index 89eecef096e..927153adc5b 100644
--- a/spec/graphql/types/permission_types/project_spec.rb
+++ b/spec/graphql/types/permission_types/project_spec.rb
@@ -10,7 +10,7 @@ describe Types::PermissionTypes::Project do
:read_commit_status, :request_access, :create_pipeline, :create_pipeline_schedule,
:create_merge_request_from, :create_wiki, :push_code, :create_deployment, :push_to_delete_protected_branch,
:admin_wiki, :admin_project, :update_pages, :admin_remote_mirror, :create_label,
- :update_wiki, :destroy_wiki, :create_pages, :destroy_pages
+ :update_wiki, :destroy_wiki, :create_pages, :destroy_pages, :read_pages_content
]
expect(described_class).to have_graphql_fields(expected_permissions)
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index 49606c397b9..61d4c42665a 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -14,5 +14,9 @@ describe GitlabSchema.types['Project'] do
end
end
+ describe 'nested issues' do
+ it { expect(described_class).to have_graphql_field(:issues) }
+ end
+
it { is_expected.to have_graphql_field(:pipelines) }
end
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 1238cfbd1e7..4135f31e051 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -174,9 +174,7 @@ describe ApplicationHelper do
it 'returns paths for autocomplete_sources_controller' do
sources = helper.autocomplete_data_sources(project, noteable_type)
-
- expect(sources.keys).to match_array([:members, :issues, :mergeRequests, :labels, :milestones, :commands])
-
+ expect(sources.keys).to match_array([:members, :issues, :mergeRequests, :labels, :milestones, :commands, :snippets])
sources.keys.each do |key|
expect(sources[key]).not_to be_nil
end
diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
index 120b23e66ac..f0c2e4768ec 100644
--- a/spec/helpers/auth_helper_spec.rb
+++ b/spec/helpers/auth_helper_spec.rb
@@ -42,6 +42,16 @@ describe AuthHelper do
end
end
+ describe 'form_based_auth_provider_has_active_class?' do
+ it 'selects main LDAP server' do
+ allow(helper).to receive(:auth_providers) { [:twitter, :ldapprimary, :ldapsecondary, :kerberos] }
+ expect(helper.form_based_auth_provider_has_active_class?(:twitter)).to be(false)
+ expect(helper.form_based_auth_provider_has_active_class?(:ldapprimary)).to be(true)
+ expect(helper.form_based_auth_provider_has_active_class?(:ldapsecondary)).to be(false)
+ expect(helper.form_based_auth_provider_has_active_class?(:kerberos)).to be(false)
+ end
+ end
+
describe 'enabled_button_based_providers' do
before do
allow(helper).to receive(:auth_providers) { [:twitter, :github] }
diff --git a/spec/helpers/avatars_helper_spec.rb b/spec/helpers/avatars_helper_spec.rb
index 55ee87163f9..aa0442ab847 100644
--- a/spec/helpers/avatars_helper_spec.rb
+++ b/spec/helpers/avatars_helper_spec.rb
@@ -32,18 +32,6 @@ describe AvatarsHelper do
end
end
- context 'when providing a project path' do
- it_behaves_like 'resource with a default avatar', 'project' do
- let(:resource) { create(:project, name: 'foo') }
- let(:helper_args) { [resource.full_path] }
- end
-
- it_behaves_like 'resource with a custom avatar', 'project' do
- let(:resource) { create(:project, :public, avatar: File.open(uploaded_image_temp_path)) }
- let(:helper_args) { [resource.full_path] }
- end
- end
-
context 'when providing a group' do
it_behaves_like 'resource with a default avatar', 'group' do
let(:resource) { create(:group, name: 'foo') }
@@ -55,18 +43,6 @@ describe AvatarsHelper do
let(:helper_args) { [resource] }
end
end
-
- context 'when providing a group path' do
- it_behaves_like 'resource with a default avatar', 'group' do
- let(:resource) { create(:group, name: 'foo') }
- let(:helper_args) { [resource.full_path] }
- end
-
- it_behaves_like 'resource with a custom avatar', 'group' do
- let(:resource) { create(:group, avatar: File.open(uploaded_image_temp_path)) }
- let(:helper_args) { [resource.full_path] }
- end
- end
end
describe '#avatar_icon_for' do
diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb
index 1c216b3fe97..f709f152c92 100644
--- a/spec/helpers/blob_helper_spec.rb
+++ b/spec/helpers/blob_helper_spec.rb
@@ -3,63 +3,13 @@ require 'spec_helper'
describe BlobHelper do
include TreeHelper
- let(:blob_name) { 'test.lisp' }
- let(:no_context_content) { ":type \"assem\"))" }
- let(:blob_content) { "(make-pathname :defaults name\n#{no_context_content}" }
- let(:split_content) { blob_content.split("\n") }
- let(:multiline_content) do
- %q(
- def test(input):
- """This is line 1 of a multi-line comment.
- This is line 2.
- """
- )
- end
-
describe '#highlight' do
- it 'returns plaintext for unknown lexer context' do
- result = helper.highlight(blob_name, no_context_content)
- expect(result).to eq(%[<pre class="code highlight"><code><span id="LC1" class="line" lang="">:type "assem"))</span></code></pre>])
+ it 'wraps highlighted content' do
+ expect(helper.highlight('test.rb', '52')).to eq(%q[<pre class="code highlight"><code><span id="LC1" class="line" lang="ruby"><span class="mi">52</span></span></code></pre>])
end
- it 'returns plaintext for long blobs' do
- stub_const('Blob::MAXIMUM_TEXT_HIGHLIGHT_SIZE', 1)
- result = helper.highlight(blob_name, blob_content)
-
- expect(result).to eq(%[<pre class="code highlight"><code><span id="LC1" class="line" lang="">(make-pathname :defaults name</span>\n<span id="LC2" class="line" lang="">:type "assem"))</span></code></pre>])
- end
-
- it 'highlights single block' do
- expected = %Q[<pre class="code highlight"><code><span id="LC1" class="line" lang="common_lisp"><span class="p">(</span><span class="nb">make-pathname</span> <span class="ss">:defaults</span> <span class="nv">name</span></span>
-<span id="LC2" class="line" lang="common_lisp"><span class="ss">:type</span> <span class="s">"assem"</span><span class="p">))</span></span></code></pre>]
-
- expect(helper.highlight(blob_name, blob_content)).to eq(expected)
- end
-
- it 'highlights multi-line comments' do
- result = helper.highlight(blob_name, multiline_content)
- html = Nokogiri::HTML(result)
- lines = html.search('.s')
- expect(lines.count).to eq(3)
- expect(lines[0].text).to eq('"""This is line 1 of a multi-line comment.')
- expect(lines[1].text).to eq(' This is line 2.')
- expect(lines[2].text).to eq(' """')
- end
-
- context 'diff highlighting' do
- let(:blob_name) { 'test.diff' }
- let(:blob_content) { "+aaa\n+bbb\n- ccc\n ddd\n"}
- let(:expected) do
- %q(<pre class="code highlight"><code><span id="LC1" class="line" lang="diff"><span class="gi">+aaa</span></span>
-<span id="LC2" class="line" lang="diff"><span class="gi">+bbb</span></span>
-<span id="LC3" class="line" lang="diff"><span class="gd">- ccc</span></span>
-<span id="LC4" class="line" lang="diff"> ddd</span></code></pre>)
- end
-
- it 'highlights each line properly' do
- result = helper.highlight(blob_name, blob_content)
- expect(result).to eq(expected)
- end
+ it 'handles plain version' do
+ expect(helper.highlight('test.rb', '52', plain: true)).to eq(%q[<pre class="code highlight"><code><span id="LC1" class="line" lang="">52</span></code></pre>])
end
end
diff --git a/spec/helpers/commits_helper_spec.rb b/spec/helpers/commits_helper_spec.rb
index 4b6c7c33e5b..9c0e55739d6 100644
--- a/spec/helpers/commits_helper_spec.rb
+++ b/spec/helpers/commits_helper_spec.rb
@@ -37,7 +37,7 @@ describe CommitsHelper do
.not_to include('onmouseover="alert(1)"')
end
- it 'escapes the commiter name' do
+ it 'escapes the committer name' do
user = build_stubbed(:user, name: 'Foo <script>alert("XSS")</script>')
commit = double(committer: user, committer_name: '', committer_email: '')
diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb
index 466e018d68c..8d0679e5699 100644
--- a/spec/helpers/events_helper_spec.rb
+++ b/spec/helpers/events_helper_spec.rb
@@ -2,18 +2,18 @@ require 'spec_helper'
describe EventsHelper do
describe '#event_commit_title' do
- let(:message) { "foo & bar " + "A" * 70 + "\n" + "B" * 80 }
+ let(:message) { 'foo & bar ' + 'A' * 70 + '\n' + 'B' * 80 }
subject { helper.event_commit_title(message) }
- it "returns the first line, truncated to 70 chars" do
+ it 'returns the first line, truncated to 70 chars' do
is_expected.to eq(message[0..66] + "...")
end
- it "is not html-safe" do
+ it 'is not html-safe' do
is_expected.not_to be_a(ActiveSupport::SafeBuffer)
end
- it "handles empty strings" do
+ it 'handles empty strings' do
expect(helper.event_commit_title("")).to eq("")
end
@@ -22,7 +22,7 @@ describe EventsHelper do
end
it 'does not escape HTML entities' do
- expect(helper.event_commit_title("foo & bar")).to eq("foo & bar")
+ expect(helper.event_commit_title('foo & bar')).to eq('foo & bar')
end
end
@@ -30,38 +30,54 @@ describe EventsHelper do
let(:event) { create(:event) }
let(:project) { create(:project, :public, :repository) }
- it "returns project issue url" do
- event.target = create(:issue)
+ context 'issue' do
+ before do
+ event.target = create(:issue)
+ end
- expect(helper.event_feed_url(event)).to eq(project_issue_url(event.project, event.issue))
+ it 'returns the project issue url' do
+ expect(helper.event_feed_url(event)).to eq(project_issue_url(event.project, event.target))
+ end
+
+ it 'contains the project issue IID link' do
+ expect(helper.event_feed_title(event)).to include("##{event.target.iid}")
+ end
end
- it "returns project merge_request url" do
- event.target = create(:merge_request)
+ context 'merge request' do
+ before do
+ event.target = create(:merge_request)
+ end
+
+ it 'returns the project merge request url' do
+ expect(helper.event_feed_url(event)).to eq(project_merge_request_url(event.project, event.target))
+ end
- expect(helper.event_feed_url(event)).to eq(project_merge_request_url(event.project, event.merge_request))
+ it 'contains the project merge request IID link' do
+ expect(helper.event_feed_title(event)).to include("!#{event.target.iid}")
+ end
end
- it "returns project commit url" do
+ it 'returns project commit url' do
event.target = create(:note_on_commit, project: project)
expect(helper.event_feed_url(event)).to eq(project_commit_url(event.project, event.note_target))
end
- it "returns event note target url" do
+ it 'returns event note target url' do
event.target = create(:note)
expect(helper.event_feed_url(event)).to eq(event_note_target_url(event))
end
- it "returns project url" do
+ it 'returns project url' do
event.project = project
event.action = 1
expect(helper.event_feed_url(event)).to eq(project_url(event.project))
end
- it "returns push event feed url" do
+ it 'returns push event feed url' do
event = create(:push_event)
create(:push_event_payload, event: event, action: :pushed)
diff --git a/spec/helpers/labels_helper_spec.rb b/spec/helpers/labels_helper_spec.rb
index a2cda58e5d2..c04f679bcf0 100644
--- a/spec/helpers/labels_helper_spec.rb
+++ b/spec/helpers/labels_helper_spec.rb
@@ -211,4 +211,29 @@ describe LabelsHelper do
end
end
end
+
+ describe 'labels_filter_path' do
+ let(:group) { create(:group) }
+ let(:project) { create(:project) }
+
+ it 'links to the dashboard labels page' do
+ expect(labels_filter_path).to eq(dashboard_labels_path)
+ end
+
+ it 'links to the group labels page' do
+ assign(:group, group)
+
+ expect(helper.labels_filter_path).to eq(group_labels_path(group))
+ end
+
+ it 'links to the project labels page' do
+ assign(:project, project)
+
+ expect(helper.labels_filter_path).to eq(project_labels_path(project))
+ end
+
+ it 'supports json format' do
+ expect(labels_filter_path(format: :json)).to eq(dashboard_labels_path(format: :json))
+ end
+ end
end
diff --git a/spec/helpers/preferences_helper_spec.rb b/spec/helpers/preferences_helper_spec.rb
index 363ebc88afd..c112c8ed633 100644
--- a/spec/helpers/preferences_helper_spec.rb
+++ b/spec/helpers/preferences_helper_spec.rb
@@ -2,6 +2,13 @@ require 'spec_helper'
describe PreferencesHelper do
describe '#dashboard_choices' do
+ let(:user) { build(:user) }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ allow(helper).to receive(:can?).and_return(false)
+ end
+
it 'raises an exception when defined choices may be missing' do
expect(User).to receive(:dashboards).and_return(foo: 'foo')
expect { helper.dashboard_choices }.to raise_error(RuntimeError)
diff --git a/spec/helpers/profiles_helper_spec.rb b/spec/helpers/profiles_helper_spec.rb
index c1d0614c79e..8e336469c27 100644
--- a/spec/helpers/profiles_helper_spec.rb
+++ b/spec/helpers/profiles_helper_spec.rb
@@ -1,6 +1,40 @@
require 'rails_helper'
describe ProfilesHelper do
+ describe '#commit_email_select_options' do
+ it 'returns an array with private commit email along with all the verified emails' do
+ user = create(:user)
+ create(:email, user: user)
+ confirmed_email1 = create(:email, :confirmed, user: user)
+ confirmed_email2 = create(:email, :confirmed, user: user)
+
+ private_email = user.private_commit_email
+
+ emails = [
+ ["Use a private email - #{private_email}", Gitlab::PrivateCommitEmail::TOKEN],
+ user.email,
+ confirmed_email1.email,
+ confirmed_email2.email
+ ]
+
+ expect(helper.commit_email_select_options(user)).to match_array(emails)
+ end
+ end
+
+ describe '#selected_commit_email' do
+ let(:user) { create(:user) }
+
+ it 'returns main email when commit email attribute is nil' do
+ expect(helper.selected_commit_email(user)).to eq(user.email)
+ end
+
+ it 'returns DB stored commit_email' do
+ user.update(commit_email: Gitlab::PrivateCommitEmail::TOKEN)
+
+ expect(helper.selected_commit_email(user)).to eq(Gitlab::PrivateCommitEmail::TOKEN)
+ end
+ end
+
describe '#email_provider_label' do
it "returns nil for users without external email" do
user = create(:user)
diff --git a/spec/helpers/search_helper_spec.rb b/spec/helpers/search_helper_spec.rb
index 8bfd520528f..4945749f524 100644
--- a/spec/helpers/search_helper_spec.rb
+++ b/spec/helpers/search_helper_spec.rb
@@ -135,5 +135,40 @@ describe SearchHelper do
expect(search_filter_input_options('')[:data]['base-endpoint']).to eq("/groups#{group_path(@group)}")
end
end
+
+ context 'dashboard' do
+ it 'does not include group-id and project-id' do
+ expect(search_filter_input_options('')[:data]['project-id']).to eq(nil)
+ expect(search_filter_input_options('')[:data]['group-id']).to eq(nil)
+ end
+
+ it 'includes dashboard base-endpoint' do
+ expect(search_filter_input_options('')[:data]['base-endpoint']).to eq("/dashboard")
+ end
+ end
+ end
+
+ describe 'search_history_storage_prefix' do
+ context 'project' do
+ it 'returns project full_path' do
+ @project = create(:project, :repository)
+
+ expect(search_history_storage_prefix).to eq(@project.full_path)
+ end
+ end
+
+ context 'group' do
+ it 'returns group full_path' do
+ @group = create(:group, :nested, name: 'group-name')
+
+ expect(search_history_storage_prefix).to eq(@group.full_path)
+ end
+ end
+
+ context 'dashboard' do
+ it 'returns dashboard' do
+ expect(search_history_storage_prefix).to eq("dashboard")
+ end
+ end
end
end
diff --git a/spec/helpers/storage_health_helper_spec.rb b/spec/helpers/storage_health_helper_spec.rb
deleted file mode 100644
index 874498e6338..00000000000
--- a/spec/helpers/storage_health_helper_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-require 'spec_helper'
-
-describe StorageHealthHelper do
- describe '#failing_storage_health_message' do
- let(:health) do
- Gitlab::Git::Storage::Health.new(
- "<script>alert('storage name');)</script>",
- []
- )
- end
-
- it 'escapes storage names' do
- escaped_storage_name = '&lt;script&gt;alert(&#39;storage name&#39;);)&lt;/script&gt;'
-
- result = helper.failing_storage_health_message(health)
-
- expect(result).to include(escaped_storage_name)
- end
- end
-end
diff --git a/spec/helpers/time_helper_spec.rb b/spec/helpers/time_helper_spec.rb
index 0b371d69ecf..8bf378549fe 100644
--- a/spec/helpers/time_helper_spec.rb
+++ b/spec/helpers/time_helper_spec.rb
@@ -20,18 +20,19 @@ describe TimeHelper do
end
describe "#duration_in_numbers" do
- it "returns minutes and seconds" do
- durations_and_expectations = {
- 100 => "01:40",
- 121 => "02:01",
- 3721 => "01:02:01",
- 0 => "00:00",
- 42 => "00:42"
- }
+ using RSpec::Parameterized::TableSyntax
- durations_and_expectations.each do |duration, expectation|
- expect(duration_in_numbers(duration)).to eq(expectation)
- end
+ where(:duration, :formatted_string) do
+ 0 | "00:00"
+ 1.second | "00:01"
+ 42.seconds | "00:42"
+ 2.minutes + 1.second | "02:01"
+ 3.hours + 2.minutes + 1.second | "03:02:01"
+ 30.hours | "30:00:00"
+ end
+
+ with_them do
+ it { expect(duration_in_numbers(duration)).to eq formatted_string }
end
end
end
diff --git a/spec/helpers/tree_helper_spec.rb b/spec/helpers/tree_helper_spec.rb
index ffdf6561a53..4a62e696cd9 100644
--- a/spec/helpers/tree_helper_spec.rb
+++ b/spec/helpers/tree_helper_spec.rb
@@ -3,7 +3,17 @@ require 'spec_helper'
describe TreeHelper do
let(:project) { create(:project, :repository) }
let(:repository) { project.repository }
- let(:sha) { 'ce369011c189f62c815f5971d096b26759bab0d1' }
+ let(:sha) { 'c1c67abbaf91f624347bb3ae96eabe3a1b742478' }
+
+ def create_file(filename)
+ project.repository.create_file(
+ project.creator,
+ filename,
+ 'test this',
+ message: "Automatically created file #{filename}",
+ branch_name: 'master'
+ )
+ end
describe '.render_tree' do
before do
@@ -32,6 +42,67 @@ describe TreeHelper do
end
end
+ describe '.fast_project_blob_path' do
+ it 'generates the same path as project_blob_path' do
+ blob_path = repository.tree(sha, 'with space').entries.first.path
+ fast_path = fast_project_blob_path(project, blob_path)
+ std_path = project_blob_path(project, blob_path)
+
+ expect(fast_path).to eq(std_path)
+ end
+
+ it 'generates the same path with encoded file names' do
+ tree = repository.tree(sha, 'encoding')
+ blob_path = tree.entries.find { |entry| entry.path == 'encoding/テスト.txt' }.path
+ fast_path = fast_project_blob_path(project, blob_path)
+ std_path = project_blob_path(project, blob_path)
+
+ expect(fast_path).to eq(std_path)
+ end
+
+ it 'respects a configured relative URL' do
+ allow(Gitlab.config.gitlab).to receive(:relative_url_root).and_return('/gitlab/root')
+ blob_path = repository.tree(sha, '').entries.first.path
+ fast_path = fast_project_blob_path(project, blob_path)
+
+ expect(fast_path).to start_with('/gitlab/root')
+ end
+
+ it 'encodes files starting with #' do
+ filename = '#test-file'
+ create_file(filename)
+
+ fast_path = fast_project_blob_path(project, filename)
+
+ expect(fast_path).to end_with('%23test-file')
+ end
+ end
+
+ describe '.fast_project_tree_path' do
+ let(:tree_path) { repository.tree(sha, 'with space').path }
+ let(:fast_path) { fast_project_tree_path(project, tree_path) }
+ let(:std_path) { project_tree_path(project, tree_path) }
+
+ it 'generates the same path as project_tree_path' do
+ expect(fast_path).to eq(std_path)
+ end
+
+ it 'respects a configured relative URL' do
+ allow(Gitlab.config.gitlab).to receive(:relative_url_root).and_return('/gitlab/root')
+
+ expect(fast_path).to start_with('/gitlab/root')
+ end
+
+ it 'encodes files starting with #' do
+ filename = '#test-file'
+ create_file(filename)
+
+ fast_path = fast_project_tree_path(project, filename)
+
+ expect(fast_path).to end_with('%23test-file')
+ end
+ end
+
describe 'flatten_tree' do
let(:tree) { repository.tree(sha, 'files') }
let(:root_path) { 'files' }
diff --git a/spec/helpers/visibility_level_helper_spec.rb b/spec/helpers/visibility_level_helper_spec.rb
index a3be222b7bd..e565ac8c530 100644
--- a/spec/helpers/visibility_level_helper_spec.rb
+++ b/spec/helpers/visibility_level_helper_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe VisibilityLevelHelper do
+ include ProjectForksHelper
+
let(:project) { build(:project) }
let(:group) { build(:group) }
let(:personal_snippet) { build(:personal_snippet) }
@@ -83,13 +85,13 @@ describe VisibilityLevelHelper do
describe "disallowed_visibility_level?" do
describe "forks" do
- let(:project) { create(:project, :internal) }
- let(:fork_project) { create(:project, forked_from_project: project) }
+ let(:project) { create(:project, :internal) }
+ let(:forked_project) { fork_project(project) }
it "disallows levels" do
- expect(disallowed_visibility_level?(fork_project, Gitlab::VisibilityLevel::PUBLIC)).to be_truthy
- expect(disallowed_visibility_level?(fork_project, Gitlab::VisibilityLevel::INTERNAL)).to be_falsey
- expect(disallowed_visibility_level?(fork_project, Gitlab::VisibilityLevel::PRIVATE)).to be_falsey
+ expect(disallowed_visibility_level?(forked_project, Gitlab::VisibilityLevel::PUBLIC)).to be_truthy
+ expect(disallowed_visibility_level?(forked_project, Gitlab::VisibilityLevel::INTERNAL)).to be_falsey
+ expect(disallowed_visibility_level?(forked_project, Gitlab::VisibilityLevel::PRIVATE)).to be_falsey
end
end
diff --git a/spec/initializers/attr_encrypted_no_db_connection_spec.rb b/spec/initializers/attr_encrypted_no_db_connection_spec.rb
new file mode 100644
index 00000000000..2da9f1cbd96
--- /dev/null
+++ b/spec/initializers/attr_encrypted_no_db_connection_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+
+describe 'GitLab monkey-patches to AttrEncrypted' do
+ describe '#attribute_instance_methods_as_symbols_available?' do
+ it 'returns false' do
+ expect(ActiveRecord::Base.__send__(:attribute_instance_methods_as_symbols_available?)).to be_falsy
+ end
+
+ it 'does not define virtual attributes' do
+ klass = Class.new(ActiveRecord::Base) do
+ # We need some sort of table to work on
+ self.table_name = 'projects'
+
+ attr_encrypted :foo
+ end
+
+ instance = klass.new
+
+ aggregate_failures do
+ %w[
+ encrypted_foo encrypted_foo=
+ encrypted_foo_iv encrypted_foo_iv=
+ encrypted_foo_salt encrypted_foo_salt=
+ ].each do |method_name|
+ expect(instance).not_to respond_to(method_name)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/initializers/secret_token_spec.rb b/spec/initializers/secret_token_spec.rb
index c3dfd7bedbe..6366be30079 100644
--- a/spec/initializers/secret_token_spec.rb
+++ b/spec/initializers/secret_token_spec.rb
@@ -123,7 +123,7 @@ describe 'create_tokens' do
create_tokens
end
- it 'sets the the keys to the values from the environment and secrets.yml' do
+ it 'sets the keys to the values from the environment and secrets.yml' do
create_tokens
expect(secrets.secret_key_base).to eq('secret_key_base')
diff --git a/spec/javascripts/.eslintrc.yml b/spec/javascripts/.eslintrc.yml
index 5525c9f5bd0..b863156b57c 100644
--- a/spec/javascripts/.eslintrc.yml
+++ b/spec/javascripts/.eslintrc.yml
@@ -35,3 +35,5 @@ rules:
- error
- ignore:
- 'fixtures/blob'
+ # Temporarily disabled to facilitate an upgrade to eslint-plugin-jasmine
+ jasmine/prefer-toHaveBeenCalledWith: off
diff --git a/spec/javascripts/ajax_loading_spinner_spec.js b/spec/javascripts/ajax_loading_spinner_spec.js
index 261375d3a0e..9389fc94f17 100644
--- a/spec/javascripts/ajax_loading_spinner_spec.js
+++ b/spec/javascripts/ajax_loading_spinner_spec.js
@@ -10,8 +10,8 @@ describe('Ajax Loading Spinner', () => {
AjaxLoadingSpinner.init();
});
- it('change current icon with spinner icon and disable link while waiting ajax response', (done) => {
- spyOn($, 'ajax').and.callFake((req) => {
+ it('change current icon with spinner icon and disable link while waiting ajax response', done => {
+ spyOn($, 'ajax').and.callFake(req => {
const xhr = new XMLHttpRequest();
const ajaxLoadingSpinner = document.querySelector('.js-ajax-loading-spinner');
const icon = ajaxLoadingSpinner.querySelector('i');
@@ -33,8 +33,8 @@ describe('Ajax Loading Spinner', () => {
document.querySelector('.js-ajax-loading-spinner').click();
});
- it('use original icon again and enabled the link after complete the ajax request', (done) => {
- spyOn($, 'ajax').and.callFake((req) => {
+ it('use original icon again and enabled the link after complete the ajax request', done => {
+ spyOn($, 'ajax').and.callFake(req => {
const xhr = new XMLHttpRequest();
const ajaxLoadingSpinner = document.querySelector('.js-ajax-loading-spinner');
@@ -42,6 +42,7 @@ describe('Ajax Loading Spinner', () => {
req.complete({});
const icon = ajaxLoadingSpinner.querySelector('i');
+
expect(icon).toHaveClass('fa-trash-o');
expect(icon).not.toHaveClass('fa-spinner');
expect(icon).not.toHaveClass('fa-spin');
diff --git a/spec/javascripts/api_spec.js b/spec/javascripts/api_spec.js
index 54cb6d84109..7de38913bae 100644
--- a/spec/javascripts/api_spec.js
+++ b/spec/javascripts/api_spec.js
@@ -123,7 +123,7 @@ describe('Api', () => {
});
});
- describe('mergerequest', () => {
+ describe('projectMergeRequest', () => {
it('fetches a merge request', done => {
const projectPath = 'abc';
const mergeRequestId = '123456';
@@ -132,7 +132,7 @@ describe('Api', () => {
title: 'test',
});
- Api.mergeRequest(projectPath, mergeRequestId)
+ Api.projectMergeRequest(projectPath, mergeRequestId)
.then(({ data }) => {
expect(data.title).toBe('test');
})
@@ -141,7 +141,7 @@ describe('Api', () => {
});
});
- describe('mergerequest changes', () => {
+ describe('projectMergeRequestChanges', () => {
it('fetches the changes of a merge request', done => {
const projectPath = 'abc';
const mergeRequestId = '123456';
@@ -150,7 +150,7 @@ describe('Api', () => {
title: 'test',
});
- Api.mergeRequestChanges(projectPath, mergeRequestId)
+ Api.projectMergeRequestChanges(projectPath, mergeRequestId)
.then(({ data }) => {
expect(data.title).toBe('test');
})
@@ -159,7 +159,7 @@ describe('Api', () => {
});
});
- describe('mergerequest versions', () => {
+ describe('projectMergeRequestVersions', () => {
it('fetches the versions of a merge request', done => {
const projectPath = 'abc';
const mergeRequestId = '123456';
@@ -170,7 +170,7 @@ describe('Api', () => {
},
]);
- Api.mergeRequestVersions(projectPath, mergeRequestId)
+ Api.projectMergeRequestVersions(projectPath, mergeRequestId)
.then(({ data }) => {
expect(data.length).toBe(1);
expect(data[0].id).toBe(123);
@@ -250,71 +250,45 @@ describe('Api', () => {
});
});
- describe('licenseText', () => {
- it('fetches a license text', done => {
- const licenseKey = "driver's license";
- const data = { unused: 'option' };
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/templates/licenses/${licenseKey}`;
+ describe('issueTemplate', () => {
+ it('fetches an issue template', done => {
+ const namespace = 'some namespace';
+ const project = 'some project';
+ const templateKey = ' template #%?.key ';
+ const templateType = 'template type';
+ const expectedUrl = `${dummyUrlRoot}/${namespace}/${project}/templates/${templateType}/${encodeURIComponent(
+ templateKey,
+ )}`;
mock.onGet(expectedUrl).reply(200, 'test');
- Api.licenseText(licenseKey, data, response => {
+ Api.issueTemplate(namespace, project, templateKey, templateType, (error, response) => {
expect(response).toBe('test');
done();
});
});
});
- describe('gitignoreText', () => {
- it('fetches a gitignore text', done => {
- const gitignoreKey = 'ignore git';
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/templates/gitignores/${gitignoreKey}`;
- mock.onGet(expectedUrl).reply(200, 'test');
-
- Api.gitignoreText(gitignoreKey, response => {
- expect(response).toBe('test');
- done();
- });
- });
- });
+ describe('projectTemplates', () => {
+ it('fetches a list of templates', done => {
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/gitlab-org%2Fgitlab-ce/templates/licenses`;
- describe('gitlabCiYml', () => {
- it('fetches a .gitlab-ci.yml', done => {
- const gitlabCiYmlKey = 'Y CI ML';
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/templates/gitlab_ci_ymls/${gitlabCiYmlKey}`;
mock.onGet(expectedUrl).reply(200, 'test');
- Api.gitlabCiYml(gitlabCiYmlKey, response => {
+ Api.projectTemplates('gitlab-org/gitlab-ce', 'licenses', {}, response => {
expect(response).toBe('test');
done();
});
});
});
- describe('dockerfileYml', () => {
- it('fetches a Dockerfile', done => {
- const dockerfileYmlKey = 'a giant whale';
- const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/templates/dockerfiles/${dockerfileYmlKey}`;
- mock.onGet(expectedUrl).reply(200, 'test');
-
- Api.dockerfileYml(dockerfileYmlKey, response => {
- expect(response).toBe('test');
- done();
- });
- });
- });
+ describe('projectTemplate', () => {
+ it('fetches a single template', done => {
+ const data = { unused: 'option' };
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/gitlab-org%2Fgitlab-ce/templates/licenses/test%20license`;
- describe('issueTemplate', () => {
- it('fetches an issue template', done => {
- const namespace = 'some namespace';
- const project = 'some project';
- const templateKey = ' template #%?.key ';
- const templateType = 'template type';
- const expectedUrl = `${dummyUrlRoot}/${namespace}/${project}/templates/${templateType}/${encodeURIComponent(
- templateKey,
- )}`;
mock.onGet(expectedUrl).reply(200, 'test');
- Api.issueTemplate(namespace, project, templateKey, templateType, (error, response) => {
+ Api.projectTemplate('gitlab-org/gitlab-ce', 'licenses', 'test license', data, response => {
expect(response).toBe('test');
done();
});
diff --git a/spec/javascripts/avatar_helper_spec.js b/spec/javascripts/avatar_helper_spec.js
index b2f80678ae7..c1ef08e0f1b 100644
--- a/spec/javascripts/avatar_helper_spec.js
+++ b/spec/javascripts/avatar_helper_spec.js
@@ -21,7 +21,7 @@ describe('avatar_helper', () => {
it(`wraps around if id is bigger than ${IDENTICON_BG_COUNT}`, () => {
expect(getIdenticonBackgroundClass(IDENTICON_BG_COUNT + 4)).toEqual('bg5');
- expect(getIdenticonBackgroundClass((IDENTICON_BG_COUNT * 5) + 6)).toEqual('bg7');
+ expect(getIdenticonBackgroundClass(IDENTICON_BG_COUNT * 5 + 6)).toEqual('bg7');
});
});
diff --git a/spec/javascripts/awards_handler_spec.js b/spec/javascripts/awards_handler_spec.js
index ada26b37f4a..ce5d2022441 100644
--- a/spec/javascripts/awards_handler_spec.js
+++ b/spec/javascripts/awards_handler_spec.js
@@ -1,382 +1,400 @@
-/* eslint-disable no-var, one-var, one-var-declaration-per-line, no-unused-expressions, no-unused-vars, prefer-template, max-len */
-
import $ from 'jquery';
import Cookies from 'js-cookie';
import loadAwardsHandler from '~/awards_handler';
-
import '~/lib/utils/common_utils';
-(function() {
- var awardsHandler, lazyAssert, urlRoot, openAndWaitForEmojiMenu;
+window.gl = window.gl || {};
+window.gon = window.gon || {};
- awardsHandler = null;
+let openAndWaitForEmojiMenu;
+let awardsHandler = null;
+const urlRoot = gon.relative_url_root;
- window.gl || (window.gl = {});
+const lazyAssert = function(done, assertFn) {
+ setTimeout(function() {
+ assertFn();
+ done();
+ // Maybe jasmine.clock here?
+ }, 333);
+};
- window.gon || (window.gon = {});
+describe('AwardsHandler', function() {
+ preloadFixtures('snippets/show.html.raw');
+ beforeEach(function(done) {
+ loadFixtures('snippets/show.html.raw');
+ loadAwardsHandler(true)
+ .then(obj => {
+ awardsHandler = obj;
+ spyOn(awardsHandler, 'postEmoji').and.callFake((button, url, emoji, cb) => cb());
+ done();
+ })
+ .catch(fail);
- urlRoot = gon.relative_url_root;
+ let isEmojiMenuBuilt = false;
+ openAndWaitForEmojiMenu = function() {
+ return new Promise(resolve => {
+ if (isEmojiMenuBuilt) {
+ resolve();
+ } else {
+ $('.js-add-award')
+ .eq(0)
+ .click();
+ const $menu = $('.emoji-menu');
+ $menu.one('build-emoji-menu-finish', () => {
+ isEmojiMenuBuilt = true;
+ resolve();
+ });
+ }
+ });
+ };
+ });
- lazyAssert = function(done, assertFn) {
- return setTimeout(function() {
- assertFn();
- return done();
- // Maybe jasmine.clock here?
- }, 333);
- };
+ afterEach(function() {
+ // restore original url root value
+ gon.relative_url_root = urlRoot;
- describe('AwardsHandler', function() {
- preloadFixtures('snippets/show.html.raw');
- beforeEach(function(done) {
- loadFixtures('snippets/show.html.raw');
- loadAwardsHandler(true)
- .then(obj => {
- awardsHandler = obj;
- spyOn(awardsHandler, 'postEmoji').and.callFake((button, url, emoji, cb) => cb());
- done();
- })
- .catch(fail);
+ // Undo what we did to the shared <body>
+ $('body').removeAttr('data-page');
- let isEmojiMenuBuilt = false;
- openAndWaitForEmojiMenu = function() {
- return new Promise((resolve, reject) => {
- if (isEmojiMenuBuilt) {
- resolve();
- } else {
- $('.js-add-award')
- .eq(0)
- .click();
- const $menu = $('.emoji-menu');
- $menu.one('build-emoji-menu-finish', () => {
- isEmojiMenuBuilt = true;
- resolve();
- });
- }
- });
- };
- });
- afterEach(function() {
- // restore original url root value
- gon.relative_url_root = urlRoot;
+ awardsHandler.destroy();
+ });
- // Undo what we did to the shared <body>
- $('body').removeAttr('data-page');
+ describe('::showEmojiMenu', function() {
+ it('should show emoji menu when Add emoji button clicked', function(done) {
+ $('.js-add-award')
+ .eq(0)
+ .click();
+ lazyAssert(done, function() {
+ const $emojiMenu = $('.emoji-menu');
- awardsHandler.destroy();
- });
- describe('::showEmojiMenu', function() {
- it('should show emoji menu when Add emoji button clicked', function(done) {
- $('.js-add-award')
- .eq(0)
- .click();
- return lazyAssert(done, function() {
- var $emojiMenu;
- $emojiMenu = $('.emoji-menu');
- expect($emojiMenu.length).toBe(1);
- expect($emojiMenu.hasClass('is-visible')).toBe(true);
- expect($emojiMenu.find('.js-emoji-menu-search').length).toBe(1);
- return expect($('.js-awards-block.current').length).toBe(1);
- });
- });
- it('should also show emoji menu for the smiley icon in notes', function(done) {
- $('.js-add-award.note-action-button').click();
- return lazyAssert(done, function() {
- var $emojiMenu = $('.emoji-menu');
- return expect($emojiMenu.length).toBe(1);
- });
- });
- it('should remove emoji menu when body is clicked', function(done) {
- $('.js-add-award')
- .eq(0)
- .click();
- return lazyAssert(done, function() {
- var $emojiMenu;
- $emojiMenu = $('.emoji-menu');
- $('body').click();
- expect($emojiMenu.length).toBe(1);
- expect($emojiMenu.hasClass('is-visible')).toBe(false);
- return expect($('.js-awards-block.current').length).toBe(0);
- });
- });
- it('should not remove emoji menu when search is clicked', function(done) {
- $('.js-add-award')
- .eq(0)
- .click();
- return lazyAssert(done, function() {
- var $emojiMenu;
- $emojiMenu = $('.emoji-menu');
- $('.emoji-search').click();
- expect($emojiMenu.length).toBe(1);
- expect($emojiMenu.hasClass('is-visible')).toBe(true);
- return expect($('.js-awards-block.current').length).toBe(1);
- });
+ expect($emojiMenu.length).toBe(1);
+ expect($emojiMenu.hasClass('is-visible')).toBe(true);
+ expect($emojiMenu.find('.js-emoji-menu-search').length).toBe(1);
+ expect($('.js-awards-block.current').length).toBe(1);
});
});
- describe('::addAwardToEmojiBar', function() {
- it('should add emoji to votes block', function() {
- var $emojiButton, $votesBlock;
- $votesBlock = $('.js-awards-block').eq(0);
- awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false);
- $emojiButton = $votesBlock.find('[data-name=heart]');
- expect($emojiButton.length).toBe(1);
- expect($emojiButton.next('.js-counter').text()).toBe('1');
- return expect($votesBlock.hasClass('hidden')).toBe(false);
- });
- it('should remove the emoji when we click again', function() {
- var $emojiButton, $votesBlock;
- $votesBlock = $('.js-awards-block').eq(0);
- awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false);
- awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false);
- $emojiButton = $votesBlock.find('[data-name=heart]');
- return expect($emojiButton.length).toBe(0);
- });
- return it('should decrement the emoji counter', function() {
- var $emojiButton, $votesBlock;
- $votesBlock = $('.js-awards-block').eq(0);
- awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false);
- $emojiButton = $votesBlock.find('[data-name=heart]');
- $emojiButton.next('.js-counter').text(5);
- awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false);
- expect($emojiButton.length).toBe(1);
- return expect($emojiButton.next('.js-counter').text()).toBe('4');
+ it('should also show emoji menu for the smiley icon in notes', function(done) {
+ $('.js-add-award.note-action-button').click();
+ lazyAssert(done, function() {
+ const $emojiMenu = $('.emoji-menu');
+
+ expect($emojiMenu.length).toBe(1);
});
});
- describe('::userAuthored', function() {
- it('should update tooltip to user authored title', function() {
- var $thumbsUpEmoji, $votesBlock;
- $votesBlock = $('.js-awards-block').eq(0);
- $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
- $thumbsUpEmoji.attr('data-title', 'sam');
- awardsHandler.userAuthored($thumbsUpEmoji);
- return expect($thumbsUpEmoji.data('originalTitle')).toBe(
- 'You cannot vote on your own issue, MR and note',
- );
- });
- it('should restore tooltip back to initial vote list', function() {
- var $thumbsUpEmoji, $votesBlock;
- jasmine.clock().install();
- $votesBlock = $('.js-awards-block').eq(0);
- $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
- $thumbsUpEmoji.attr('data-title', 'sam');
- awardsHandler.userAuthored($thumbsUpEmoji);
- jasmine.clock().tick(2801);
- jasmine.clock().uninstall();
- return expect($thumbsUpEmoji.data('originalTitle')).toBe('sam');
+
+ it('should remove emoji menu when body is clicked', function(done) {
+ $('.js-add-award')
+ .eq(0)
+ .click();
+ lazyAssert(done, function() {
+ const $emojiMenu = $('.emoji-menu');
+ $('body').click();
+
+ expect($emojiMenu.length).toBe(1);
+ expect($emojiMenu.hasClass('is-visible')).toBe(false);
+ expect($('.js-awards-block.current').length).toBe(0);
});
});
- describe('::getAwardUrl', function() {
- return it('returns the url for request', function() {
- return expect(awardsHandler.getAwardUrl()).toBe(
- 'http://test.host/snippets/1/toggle_award_emoji',
- );
+
+ it('should not remove emoji menu when search is clicked', function(done) {
+ $('.js-add-award')
+ .eq(0)
+ .click();
+ lazyAssert(done, function() {
+ const $emojiMenu = $('.emoji-menu');
+ $('.emoji-search').click();
+
+ expect($emojiMenu.length).toBe(1);
+ expect($emojiMenu.hasClass('is-visible')).toBe(true);
+ expect($('.js-awards-block.current').length).toBe(1);
});
});
- describe('::addAward and ::checkMutuality', function() {
- return it('should handle :+1: and :-1: mutuality', function() {
- var $thumbsDownEmoji, $thumbsUpEmoji, $votesBlock, awardUrl;
- awardUrl = awardsHandler.getAwardUrl();
- $votesBlock = $('.js-awards-block').eq(0);
- $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
- $thumbsDownEmoji = $votesBlock.find('[data-name=thumbsdown]').parent();
- awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false);
- expect($thumbsUpEmoji.hasClass('active')).toBe(true);
- expect($thumbsDownEmoji.hasClass('active')).toBe(false);
- $thumbsUpEmoji.tooltip();
- $thumbsDownEmoji.tooltip();
- awardsHandler.addAward($votesBlock, awardUrl, 'thumbsdown', true);
- expect($thumbsUpEmoji.hasClass('active')).toBe(false);
- return expect($thumbsDownEmoji.hasClass('active')).toBe(true);
- });
+ });
+
+ describe('::addAwardToEmojiBar', function() {
+ it('should add emoji to votes block', function() {
+ const $votesBlock = $('.js-awards-block').eq(0);
+ awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false);
+ const $emojiButton = $votesBlock.find('[data-name=heart]');
+
+ expect($emojiButton.length).toBe(1);
+ expect($emojiButton.next('.js-counter').text()).toBe('1');
+ expect($votesBlock.hasClass('hidden')).toBe(false);
});
- describe('::removeEmoji', function() {
- return it('should remove emoji', function() {
- var $votesBlock, awardUrl;
- awardUrl = awardsHandler.getAwardUrl();
- $votesBlock = $('.js-awards-block').eq(0);
- awardsHandler.addAward($votesBlock, awardUrl, 'fire', false);
- expect($votesBlock.find('[data-name=fire]').length).toBe(1);
- awardsHandler.removeEmoji($votesBlock.find('[data-name=fire]').closest('button'));
- return expect($votesBlock.find('[data-name=fire]').length).toBe(0);
- });
+
+ it('should remove the emoji when we click again', function() {
+ const $votesBlock = $('.js-awards-block').eq(0);
+ awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false);
+ awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false);
+ const $emojiButton = $votesBlock.find('[data-name=heart]');
+
+ expect($emojiButton.length).toBe(0);
});
- describe('::addYouToUserList', function() {
- it('should prepend "You" to the award tooltip', function() {
- var $thumbsUpEmoji, $votesBlock, awardUrl;
- awardUrl = awardsHandler.getAwardUrl();
- $votesBlock = $('.js-awards-block').eq(0);
- $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
- $thumbsUpEmoji.attr('data-title', 'sam, jerry, max, and andy');
- awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false);
- $thumbsUpEmoji.tooltip();
- return expect($thumbsUpEmoji.data('originalTitle')).toBe('You, sam, jerry, max, and andy');
- });
- return it('handles the special case where "You" is not cleanly comma seperated', function() {
- var $thumbsUpEmoji, $votesBlock, awardUrl;
- awardUrl = awardsHandler.getAwardUrl();
- $votesBlock = $('.js-awards-block').eq(0);
- $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
- $thumbsUpEmoji.attr('data-title', 'sam');
- awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false);
- $thumbsUpEmoji.tooltip();
- return expect($thumbsUpEmoji.data('originalTitle')).toBe('You and sam');
- });
+
+ it('should decrement the emoji counter', function() {
+ const $votesBlock = $('.js-awards-block').eq(0);
+ awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false);
+ const $emojiButton = $votesBlock.find('[data-name=heart]');
+ $emojiButton.next('.js-counter').text(5);
+ awardsHandler.addAwardToEmojiBar($votesBlock, 'heart', false);
+
+ expect($emojiButton.length).toBe(1);
+ expect($emojiButton.next('.js-counter').text()).toBe('4');
});
- describe('::removeYouToUserList', function() {
- it('removes "You" from the front of the tooltip', function() {
- var $thumbsUpEmoji, $votesBlock, awardUrl;
- awardUrl = awardsHandler.getAwardUrl();
- $votesBlock = $('.js-awards-block').eq(0);
- $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
- $thumbsUpEmoji.attr('data-title', 'You, sam, jerry, max, and andy');
- $thumbsUpEmoji.addClass('active');
- awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false);
- $thumbsUpEmoji.tooltip();
- return expect($thumbsUpEmoji.data('originalTitle')).toBe('sam, jerry, max, and andy');
- });
- return it('handles the special case where "You" is not cleanly comma seperated', function() {
- var $thumbsUpEmoji, $votesBlock, awardUrl;
- awardUrl = awardsHandler.getAwardUrl();
- $votesBlock = $('.js-awards-block').eq(0);
- $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
- $thumbsUpEmoji.attr('data-title', 'You and sam');
- $thumbsUpEmoji.addClass('active');
- awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false);
- $thumbsUpEmoji.tooltip();
- return expect($thumbsUpEmoji.data('originalTitle')).toBe('sam');
- });
+ });
+
+ describe('::userAuthored', function() {
+ it('should update tooltip to user authored title', function() {
+ const $votesBlock = $('.js-awards-block').eq(0);
+ const $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
+ $thumbsUpEmoji.attr('data-title', 'sam');
+ awardsHandler.userAuthored($thumbsUpEmoji);
+
+ expect($thumbsUpEmoji.data('originalTitle')).toBe(
+ 'You cannot vote on your own issue, MR and note',
+ );
});
- describe('::searchEmojis', () => {
- it('should filter the emoji', function(done) {
- return openAndWaitForEmojiMenu()
- .then(() => {
- expect($('[data-name=angel]').is(':visible')).toBe(true);
- expect($('[data-name=anger]').is(':visible')).toBe(true);
- awardsHandler.searchEmojis('ali');
- expect($('[data-name=angel]').is(':visible')).toBe(false);
- expect($('[data-name=anger]').is(':visible')).toBe(false);
- expect($('[data-name=alien]').is(':visible')).toBe(true);
- expect($('.js-emoji-menu-search').val()).toBe('ali');
- })
- .then(done)
- .catch(err => {
- done.fail(`Failed to open and build emoji menu: ${err.message}`);
- });
- });
- it('should clear the search when searching for nothing', function(done) {
- return openAndWaitForEmojiMenu()
- .then(() => {
- awardsHandler.searchEmojis('ali');
- expect($('[data-name=angel]').is(':visible')).toBe(false);
- expect($('[data-name=anger]').is(':visible')).toBe(false);
- expect($('[data-name=alien]').is(':visible')).toBe(true);
- awardsHandler.searchEmojis('');
- expect($('[data-name=angel]').is(':visible')).toBe(true);
- expect($('[data-name=anger]').is(':visible')).toBe(true);
- expect($('[data-name=alien]').is(':visible')).toBe(true);
- expect($('.js-emoji-menu-search').val()).toBe('');
- })
- .then(done)
- .catch(err => {
- done.fail(`Failed to open and build emoji menu: ${err.message}`);
- });
+
+ it('should restore tooltip back to initial vote list', function() {
+ jasmine.clock().install();
+ const $votesBlock = $('.js-awards-block').eq(0);
+ const $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
+ $thumbsUpEmoji.attr('data-title', 'sam');
+ awardsHandler.userAuthored($thumbsUpEmoji);
+ jasmine.clock().tick(2801);
+ jasmine.clock().uninstall();
+
+ expect($thumbsUpEmoji.data('originalTitle')).toBe('sam');
+ });
+ });
+
+ describe('::getAwardUrl', function() {
+ it('returns the url for request', function() {
+ expect(awardsHandler.getAwardUrl()).toBe('http://test.host/snippets/1/toggle_award_emoji');
+ });
+ });
+
+ describe('::addAward and ::checkMutuality', function() {
+ it('should handle :+1: and :-1: mutuality', function() {
+ const awardUrl = awardsHandler.getAwardUrl();
+ const $votesBlock = $('.js-awards-block').eq(0);
+ const $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
+ const $thumbsDownEmoji = $votesBlock.find('[data-name=thumbsdown]').parent();
+ awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false);
+
+ expect($thumbsUpEmoji.hasClass('active')).toBe(true);
+ expect($thumbsDownEmoji.hasClass('active')).toBe(false);
+ $thumbsUpEmoji.tooltip();
+ $thumbsDownEmoji.tooltip();
+ awardsHandler.addAward($votesBlock, awardUrl, 'thumbsdown', true);
+
+ expect($thumbsUpEmoji.hasClass('active')).toBe(false);
+ expect($thumbsDownEmoji.hasClass('active')).toBe(true);
+ });
+ });
+
+ describe('::removeEmoji', function() {
+ it('should remove emoji', function() {
+ const awardUrl = awardsHandler.getAwardUrl();
+ const $votesBlock = $('.js-awards-block').eq(0);
+ awardsHandler.addAward($votesBlock, awardUrl, 'fire', false);
+
+ expect($votesBlock.find('[data-name=fire]').length).toBe(1);
+ awardsHandler.removeEmoji($votesBlock.find('[data-name=fire]').closest('button'));
+
+ expect($votesBlock.find('[data-name=fire]').length).toBe(0);
+ });
+ });
+
+ describe('::addYouToUserList', function() {
+ it('should prepend "You" to the award tooltip', function() {
+ const awardUrl = awardsHandler.getAwardUrl();
+ const $votesBlock = $('.js-awards-block').eq(0);
+ const $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
+ $thumbsUpEmoji.attr('data-title', 'sam, jerry, max, and andy');
+ awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false);
+ $thumbsUpEmoji.tooltip();
+
+ expect($thumbsUpEmoji.data('originalTitle')).toBe('You, sam, jerry, max, and andy');
+ });
+
+ it('handles the special case where "You" is not cleanly comma separated', function() {
+ const awardUrl = awardsHandler.getAwardUrl();
+ const $votesBlock = $('.js-awards-block').eq(0);
+ const $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
+ $thumbsUpEmoji.attr('data-title', 'sam');
+ awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false);
+ $thumbsUpEmoji.tooltip();
+
+ expect($thumbsUpEmoji.data('originalTitle')).toBe('You and sam');
+ });
+ });
+
+ describe('::removeYouToUserList', function() {
+ it('removes "You" from the front of the tooltip', function() {
+ const awardUrl = awardsHandler.getAwardUrl();
+ const $votesBlock = $('.js-awards-block').eq(0);
+ const $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
+ $thumbsUpEmoji.attr('data-title', 'You, sam, jerry, max, and andy');
+ $thumbsUpEmoji.addClass('active');
+ awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false);
+ $thumbsUpEmoji.tooltip();
+
+ expect($thumbsUpEmoji.data('originalTitle')).toBe('sam, jerry, max, and andy');
+ });
+
+ it('handles the special case where "You" is not cleanly comma separated', function() {
+ const awardUrl = awardsHandler.getAwardUrl();
+ const $votesBlock = $('.js-awards-block').eq(0);
+ const $thumbsUpEmoji = $votesBlock.find('[data-name=thumbsup]').parent();
+ $thumbsUpEmoji.attr('data-title', 'You and sam');
+ $thumbsUpEmoji.addClass('active');
+ awardsHandler.addAward($votesBlock, awardUrl, 'thumbsup', false);
+ $thumbsUpEmoji.tooltip();
+
+ expect($thumbsUpEmoji.data('originalTitle')).toBe('sam');
+ });
+ });
+
+ describe('::searchEmojis', () => {
+ it('should filter the emoji', function(done) {
+ openAndWaitForEmojiMenu()
+ .then(() => {
+ expect($('[data-name=angel]').is(':visible')).toBe(true);
+ expect($('[data-name=anger]').is(':visible')).toBe(true);
+ awardsHandler.searchEmojis('ali');
+
+ expect($('[data-name=angel]').is(':visible')).toBe(false);
+ expect($('[data-name=anger]').is(':visible')).toBe(false);
+ expect($('[data-name=alien]').is(':visible')).toBe(true);
+ expect($('.js-emoji-menu-search').val()).toBe('ali');
+ })
+ .then(done)
+ .catch(err => {
+ done.fail(`Failed to open and build emoji menu: ${err.message}`);
+ });
+ });
+
+ it('should clear the search when searching for nothing', function(done) {
+ openAndWaitForEmojiMenu()
+ .then(() => {
+ awardsHandler.searchEmojis('ali');
+
+ expect($('[data-name=angel]').is(':visible')).toBe(false);
+ expect($('[data-name=anger]').is(':visible')).toBe(false);
+ expect($('[data-name=alien]').is(':visible')).toBe(true);
+ awardsHandler.searchEmojis('');
+
+ expect($('[data-name=angel]').is(':visible')).toBe(true);
+ expect($('[data-name=anger]').is(':visible')).toBe(true);
+ expect($('[data-name=alien]').is(':visible')).toBe(true);
+ expect($('.js-emoji-menu-search').val()).toBe('');
+ })
+ .then(done)
+ .catch(err => {
+ done.fail(`Failed to open and build emoji menu: ${err.message}`);
+ });
+ });
+ });
+
+ describe('emoji menu', function() {
+ const emojiSelector = '[data-name="sunglasses"]';
+ const openEmojiMenuAndAddEmoji = function() {
+ return openAndWaitForEmojiMenu().then(() => {
+ const $menu = $('.emoji-menu');
+ const $block = $('.js-awards-block');
+ const $emoji = $menu.find(`.emoji-menu-list:not(.frequent-emojis) ${emojiSelector}`);
+
+ expect($emoji.length).toBe(1);
+ expect($block.find(emojiSelector).length).toBe(0);
+ $emoji.click();
+
+ expect($menu.hasClass('.is-visible')).toBe(false);
+ expect($block.find(emojiSelector).length).toBe(1);
});
+ };
+
+ it('should add selected emoji to awards block', function(done) {
+ openEmojiMenuAndAddEmoji()
+ .then(done)
+ .catch(err => {
+ done.fail(`Failed to open and build emoji menu: ${err.message}`);
+ });
});
- describe('emoji menu', function() {
- const emojiSelector = '[data-name="sunglasses"]';
- const openEmojiMenuAndAddEmoji = function() {
- return openAndWaitForEmojiMenu().then(() => {
- const $menu = $('.emoji-menu');
+ it('should remove already selected emoji', function(done) {
+ openEmojiMenuAndAddEmoji()
+ .then(() => {
+ $('.js-add-award')
+ .eq(0)
+ .click();
const $block = $('.js-awards-block');
- const $emoji = $menu.find('.emoji-menu-list:not(.frequent-emojis) ' + emojiSelector);
+ const $emoji = $('.emoji-menu').find(
+ `.emoji-menu-list:not(.frequent-emojis) ${emojiSelector}`,
+ );
+ $emoji.click();
- expect($emoji.length).toBe(1);
expect($block.find(emojiSelector).length).toBe(0);
- $emoji.click();
- expect($menu.hasClass('.is-visible')).toBe(false);
- expect($block.find(emojiSelector).length).toBe(1);
+ })
+ .then(done)
+ .catch(err => {
+ done.fail(`Failed to open and build emoji menu: ${err.message}`);
});
- };
- it('should add selected emoji to awards block', function(done) {
- return openEmojiMenuAndAddEmoji()
- .then(done)
- .catch(err => {
- done.fail(`Failed to open and build emoji menu: ${err.message}`);
- });
- });
- it('should remove already selected emoji', function(done) {
- return openEmojiMenuAndAddEmoji()
- .then(() => {
- $('.js-add-award')
- .eq(0)
- .click();
- const $block = $('.js-awards-block');
- const $emoji = $('.emoji-menu').find(
- `.emoji-menu-list:not(.frequent-emojis) ${emojiSelector}`,
- );
- $emoji.click();
- expect($block.find(emojiSelector).length).toBe(0);
- })
- .then(done)
- .catch(err => {
- done.fail(`Failed to open and build emoji menu: ${err.message}`);
- });
- });
});
+ });
- describe('frequently used emojis', function() {
- beforeEach(() => {
- // Clear it out
- Cookies.set('frequently_used_emojis', '');
- });
+ describe('frequently used emojis', function() {
+ beforeEach(() => {
+ // Clear it out
+ Cookies.set('frequently_used_emojis', '');
+ });
- it('shouldn\'t have any "Frequently used" heading if no frequently used emojis', function(done) {
- return openAndWaitForEmojiMenu()
- .then(() => {
- const emojiMenu = document.querySelector('.emoji-menu');
- Array.prototype.forEach.call(emojiMenu.querySelectorAll('.emoji-menu-title'), title => {
- expect(title.textContent.trim().toLowerCase()).not.toBe('frequently used');
- });
- })
- .then(done)
- .catch(err => {
- done.fail(`Failed to open and build emoji menu: ${err.message}`);
+ it('shouldn\'t have any "Frequently used" heading if no frequently used emojis', function(done) {
+ return openAndWaitForEmojiMenu()
+ .then(() => {
+ const emojiMenu = document.querySelector('.emoji-menu');
+ Array.prototype.forEach.call(emojiMenu.querySelectorAll('.emoji-menu-title'), title => {
+ expect(title.textContent.trim().toLowerCase()).not.toBe('frequently used');
});
- });
+ })
+ .then(done)
+ .catch(err => {
+ done.fail(`Failed to open and build emoji menu: ${err.message}`);
+ });
+ });
- it('should have any frequently used section when there are frequently used emojis', function(done) {
- awardsHandler.addEmojiToFrequentlyUsedList('8ball');
-
- return openAndWaitForEmojiMenu()
- .then(() => {
- const emojiMenu = document.querySelector('.emoji-menu');
- const hasFrequentlyUsedHeading = Array.prototype.some.call(
- emojiMenu.querySelectorAll('.emoji-menu-title'),
- title => title.textContent.trim().toLowerCase() === 'frequently used',
- );
-
- expect(hasFrequentlyUsedHeading).toBe(true);
- })
- .then(done)
- .catch(err => {
- done.fail(`Failed to open and build emoji menu: ${err.message}`);
- });
- });
+ it('should have any frequently used section when there are frequently used emojis', function(done) {
+ awardsHandler.addEmojiToFrequentlyUsedList('8ball');
- it('should disregard invalid frequently used emoji that are being attempted to be added', function() {
- awardsHandler.addEmojiToFrequentlyUsedList('8ball');
- awardsHandler.addEmojiToFrequentlyUsedList('invalid_emoji');
- awardsHandler.addEmojiToFrequentlyUsedList('grinning');
+ return openAndWaitForEmojiMenu()
+ .then(() => {
+ const emojiMenu = document.querySelector('.emoji-menu');
+ const hasFrequentlyUsedHeading = Array.prototype.some.call(
+ emojiMenu.querySelectorAll('.emoji-menu-title'),
+ title => title.textContent.trim().toLowerCase() === 'frequently used',
+ );
- expect(awardsHandler.getFrequentlyUsedEmojis()).toEqual(['8ball', 'grinning']);
- });
+ expect(hasFrequentlyUsedHeading).toBe(true);
+ })
+ .then(done)
+ .catch(err => {
+ done.fail(`Failed to open and build emoji menu: ${err.message}`);
+ });
+ });
- it('should disregard invalid frequently used emoji already set in cookie', function() {
- Cookies.set('frequently_used_emojis', '8ball,invalid_emoji,grinning');
+ it('should disregard invalid frequently used emoji that are being attempted to be added', function() {
+ awardsHandler.addEmojiToFrequentlyUsedList('8ball');
+ awardsHandler.addEmojiToFrequentlyUsedList('invalid_emoji');
+ awardsHandler.addEmojiToFrequentlyUsedList('grinning');
- expect(awardsHandler.getFrequentlyUsedEmojis()).toEqual(['8ball', 'grinning']);
- });
+ expect(awardsHandler.getFrequentlyUsedEmojis()).toEqual(['8ball', 'grinning']);
+ });
+
+ it('should disregard invalid frequently used emoji already set in cookie', function() {
+ Cookies.set('frequently_used_emojis', '8ball,invalid_emoji,grinning');
+
+ expect(awardsHandler.getFrequentlyUsedEmojis()).toEqual(['8ball', 'grinning']);
});
});
-}.call(window));
+});
diff --git a/spec/javascripts/badges/components/badge_form_spec.js b/spec/javascripts/badges/components/badge_form_spec.js
index 31195bd762b..651ac3ba3f9 100644
--- a/spec/javascripts/badges/components/badge_form_spec.js
+++ b/spec/javascripts/badges/components/badge_form_spec.js
@@ -66,8 +66,10 @@ describe('BadgeForm component', () => {
};
const expectInvalidInput = inputElementSelector => {
const inputElement = vm.$el.querySelector(inputElementSelector);
+
expect(inputElement).toBeMatchedBy(':invalid');
const feedbackElement = vm.$el.querySelector(`${inputElementSelector} + .invalid-feedback`);
+
expect(feedbackElement).toBeVisible();
};
@@ -90,6 +92,7 @@ describe('BadgeForm component', () => {
submitForm();
expectInvalidInput(imageUrlSelector);
+
expect(vm[submitAction]).not.toHaveBeenCalled();
});
@@ -99,6 +102,7 @@ describe('BadgeForm component', () => {
submitForm();
expectInvalidInput(imageUrlSelector);
+
expect(vm[submitAction]).not.toHaveBeenCalled();
});
@@ -108,6 +112,7 @@ describe('BadgeForm component', () => {
submitForm();
expectInvalidInput(linkUrlSelector);
+
expect(vm[submitAction]).not.toHaveBeenCalled();
});
@@ -117,6 +122,7 @@ describe('BadgeForm component', () => {
submitForm();
expectInvalidInput(linkUrlSelector);
+
expect(vm[submitAction]).not.toHaveBeenCalled();
});
@@ -143,8 +149,10 @@ describe('BadgeForm component', () => {
it('renders one button', () => {
expect(vm.$el.querySelector('.row-content-block')).toBeNull();
const buttons = vm.$el.querySelectorAll('.form-group:last-of-type button');
+
expect(buttons.length).toBe(1);
const buttonAddElement = buttons[0];
+
expect(buttonAddElement).toBeVisible();
expect(buttonAddElement).toHaveText('Add badge');
});
@@ -165,11 +173,14 @@ describe('BadgeForm component', () => {
it('renders two buttons', () => {
const buttons = vm.$el.querySelectorAll('.row-content-block button');
+
expect(buttons.length).toBe(2);
const buttonSaveElement = buttons[0];
+
expect(buttonSaveElement).toBeVisible();
expect(buttonSaveElement).toHaveText('Save changes');
const buttonCancelElement = buttons[1];
+
expect(buttonCancelElement).toBeVisible();
expect(buttonCancelElement).toHaveText('Cancel');
});
diff --git a/spec/javascripts/badges/components/badge_list_row_spec.js b/spec/javascripts/badges/components/badge_list_row_spec.js
index 21bd00d82f0..a5b47cc5f32 100644
--- a/spec/javascripts/badges/components/badge_list_row_spec.js
+++ b/spec/javascripts/badges/components/badge_list_row_spec.js
@@ -34,6 +34,7 @@ describe('BadgeListRow component', () => {
it('renders the badge', () => {
const badgeElement = vm.$el.querySelector('.project-badge');
+
expect(badgeElement).not.toBeNull();
expect(badgeElement.getAttribute('src')).toBe(badge.renderedImageUrl);
});
@@ -48,11 +49,14 @@ describe('BadgeListRow component', () => {
it('shows edit and delete buttons', () => {
const buttons = vm.$el.querySelectorAll('.table-button-footer button');
+
expect(buttons).toHaveLength(2);
const buttonEditElement = buttons[0];
+
expect(buttonEditElement).toBeVisible();
expect(buttonEditElement).toHaveSpriteIcon('pencil');
const buttonDeleteElement = buttons[1];
+
expect(buttonDeleteElement).toBeVisible();
expect(buttonDeleteElement).toHaveSpriteIcon('remove');
});
@@ -91,6 +95,7 @@ describe('BadgeListRow component', () => {
it('hides edit and delete buttons', () => {
const buttons = vm.$el.querySelectorAll('.table-button-footer button');
+
expect(buttons).toHaveLength(0);
});
});
diff --git a/spec/javascripts/badges/components/badge_list_spec.js b/spec/javascripts/badges/components/badge_list_spec.js
index 02e59ae0843..536671db377 100644
--- a/spec/javascripts/badges/components/badge_list_spec.js
+++ b/spec/javascripts/badges/components/badge_list_spec.js
@@ -34,11 +34,13 @@ describe('BadgeList component', () => {
it('renders a header with the badge count', () => {
const header = vm.$el.querySelector('.card-header');
+
expect(header).toHaveText(new RegExp(`Your badges\\s+${numberOfDummyBadges}`));
});
it('renders a row for each badge', () => {
const rows = vm.$el.querySelectorAll('.gl-responsive-table-row');
+
expect(rows).toHaveLength(numberOfDummyBadges);
});
@@ -59,6 +61,7 @@ describe('BadgeList component', () => {
Vue.nextTick()
.then(() => {
const loadingIcon = vm.$el.querySelector('.fa-spinner');
+
expect(loadingIcon).toBeVisible();
})
.then(done)
diff --git a/spec/javascripts/badges/components/badge_settings_spec.js b/spec/javascripts/badges/components/badge_settings_spec.js
index 59367c85125..aca26b736ca 100644
--- a/spec/javascripts/badges/components/badge_settings_spec.js
+++ b/spec/javascripts/badges/components/badge_settings_spec.js
@@ -38,6 +38,7 @@ describe('BadgeSettings component', () => {
$(modal).on('shown.bs.modal', () => {
expect(modal).toContainText('Delete badge?');
const badgeElement = modal.querySelector('img.project-badge');
+
expect(badgeElement).not.toBe(null);
expect(badgeElement.getAttribute('src')).toBe(badge.renderedImageUrl);
@@ -53,14 +54,17 @@ describe('BadgeSettings component', () => {
it('displays a form to add a badge', () => {
const form = vm.$el.querySelector('form:nth-of-type(2)');
+
expect(form).not.toBe(null);
const button = form.querySelector('.btn-success');
+
expect(button).not.toBe(null);
expect(button).toHaveText(/Add badge/);
});
it('displays badge list', () => {
const badgeListElement = vm.$el.querySelector('.card');
+
expect(badgeListElement).not.toBe(null);
expect(badgeListElement).toBeVisible();
expect(badgeListElement).toContainText('Your badges');
@@ -77,17 +81,21 @@ describe('BadgeSettings component', () => {
it('displays a form to edit a badge', () => {
const form = vm.$el.querySelector('form:nth-of-type(1)');
+
expect(form).not.toBe(null);
const submitButton = form.querySelector('.btn-success');
+
expect(submitButton).not.toBe(null);
expect(submitButton).toHaveText(/Save changes/);
const cancelButton = form.querySelector('.btn-cancel');
+
expect(cancelButton).not.toBe(null);
expect(cancelButton).toHaveText(/Cancel/);
});
it('displays no badge list', () => {
const badgeListElement = vm.$el.querySelector('.card');
+
expect(badgeListElement).toBeHidden();
});
});
@@ -102,6 +110,7 @@ describe('BadgeSettings component', () => {
deleteButton.click();
const badge = store.state.badgeInModal;
+
expect(vm.deleteBadge).toHaveBeenCalledWith(badge);
});
});
diff --git a/spec/javascripts/badges/components/badge_spec.js b/spec/javascripts/badges/components/badge_spec.js
index fd1ecc9cdd8..29805408bcf 100644
--- a/spec/javascripts/badges/components/badge_spec.js
+++ b/spec/javascripts/badges/components/badge_spec.js
@@ -107,6 +107,7 @@ describe('Badge component', () => {
expect(vm.isLoading).toBe(false);
expect(vm.hasError).toBe(false);
const { badgeImage, loadingIcon, reloadButton } = findElements();
+
expect(badgeImage).toBeVisible();
expect(loadingIcon).toBeHidden();
expect(reloadButton).toBeHidden();
@@ -119,6 +120,7 @@ describe('Badge component', () => {
Vue.nextTick()
.then(() => {
const { badgeImage, loadingIcon, reloadButton } = findElements();
+
expect(badgeImage).toBeHidden();
expect(loadingIcon).toBeVisible();
expect(reloadButton).toBeHidden();
@@ -134,6 +136,7 @@ describe('Badge component', () => {
Vue.nextTick()
.then(() => {
const { badgeImage, loadingIcon, reloadButton } = findElements();
+
expect(badgeImage).toBeHidden();
expect(loadingIcon).toBeHidden();
expect(reloadButton).toBeVisible();
diff --git a/spec/javascripts/badges/store/actions_spec.js b/spec/javascripts/badges/store/actions_spec.js
index bb6263c6de4..2623465ebd6 100644
--- a/spec/javascripts/badges/store/actions_spec.js
+++ b/spec/javascripts/badges/store/actions_spec.js
@@ -94,6 +94,7 @@ describe('Badges store actions', () => {
link_url: badgeInAddForm.linkUrl,
}),
);
+
expect(dispatch.calls.allArgs()).toEqual([['requestNewBadge']]);
dispatch.calls.reset();
return [200, dummyResponse];
@@ -117,6 +118,7 @@ describe('Badges store actions', () => {
link_url: badgeInAddForm.linkUrl,
}),
);
+
expect(dispatch.calls.allArgs()).toEqual([['requestNewBadge']]);
dispatch.calls.reset();
return [500, ''];
@@ -296,6 +298,7 @@ describe('Badges store actions', () => {
.loadBadges({ state, dispatch }, dummyData)
.then(() => {
const badges = dummyReponse.map(transformBackendBadge);
+
expect(dispatch.calls.allArgs()).toEqual([['receiveLoadBadges', badges]]);
})
.then(done)
@@ -416,6 +419,7 @@ describe('Badges store actions', () => {
.then(() => {
expect(axios.get.calls.count()).toBe(1);
const url = axios.get.calls.argsFor(0)[0];
+
expect(url).toMatch(`^${dummyEndpointUrl}/render?`);
expect(url).toMatch('\\?link_url=%3Cscript%3EI%20am%20dangerous!%3C%2Fscript%3E&');
expect(url).toMatch('&image_url=%26make-sandwhich%3Dtrue$');
@@ -436,6 +440,7 @@ describe('Badges store actions', () => {
.renderBadge({ state, dispatch })
.then(() => {
const renderedBadge = transformBackendBadge(dummyReponse);
+
expect(dispatch.calls.allArgs()).toEqual([['receiveRenderedBadge', renderedBadge]]);
})
.then(done)
@@ -525,6 +530,7 @@ describe('Badges store actions', () => {
link_url: badgeInEditForm.linkUrl,
}),
);
+
expect(dispatch.calls.allArgs()).toEqual([['requestUpdatedBadge']]);
dispatch.calls.reset();
return [200, dummyResponse];
@@ -548,6 +554,7 @@ describe('Badges store actions', () => {
link_url: badgeInEditForm.linkUrl,
}),
);
+
expect(dispatch.calls.allArgs()).toEqual([['requestUpdatedBadge']]);
dispatch.calls.reset();
return [500, ''];
diff --git a/spec/javascripts/behaviors/autosize_spec.js b/spec/javascripts/behaviors/autosize_spec.js
index c411c5174fb..59abae479d4 100644
--- a/spec/javascripts/behaviors/autosize_spec.js
+++ b/spec/javascripts/behaviors/autosize_spec.js
@@ -12,6 +12,7 @@ describe('Autosize behavior', () => {
it('does not overwrite the resize property', () => {
load();
+
expect($('textarea')).toHaveCss({
resize: 'vertical',
});
diff --git a/spec/javascripts/behaviors/bind_in_out_spec.js b/spec/javascripts/behaviors/bind_in_out_spec.js
index 5ff66167718..0c214f5886a 100644
--- a/spec/javascripts/behaviors/bind_in_out_spec.js
+++ b/spec/javascripts/behaviors/bind_in_out_spec.js
@@ -1,60 +1,60 @@
import BindInOut from '~/behaviors/bind_in_out';
import ClassSpecHelper from '../helpers/class_spec_helper';
-describe('BindInOut', function () {
- describe('constructor', function () {
- beforeEach(function () {
+describe('BindInOut', function() {
+ describe('constructor', function() {
+ beforeEach(function() {
this.in = {};
this.out = {};
this.bindInOut = new BindInOut(this.in, this.out);
});
- it('should set .in', function () {
+ it('should set .in', function() {
expect(this.bindInOut.in).toBe(this.in);
});
- it('should set .out', function () {
+ it('should set .out', function() {
expect(this.bindInOut.out).toBe(this.out);
});
- it('should set .eventWrapper', function () {
+ it('should set .eventWrapper', function() {
expect(this.bindInOut.eventWrapper).toEqual({});
});
- describe('if .in is an input', function () {
- beforeEach(function () {
+ describe('if .in is an input', function() {
+ beforeEach(function() {
this.bindInOut = new BindInOut({ tagName: 'INPUT' });
});
- it('should set .eventType to keyup ', function () {
+ it('should set .eventType to keyup ', function() {
expect(this.bindInOut.eventType).toEqual('keyup');
});
});
- describe('if .in is a textarea', function () {
- beforeEach(function () {
+ describe('if .in is a textarea', function() {
+ beforeEach(function() {
this.bindInOut = new BindInOut({ tagName: 'TEXTAREA' });
});
- it('should set .eventType to keyup ', function () {
+ it('should set .eventType to keyup ', function() {
expect(this.bindInOut.eventType).toEqual('keyup');
});
});
- describe('if .in is not an input or textarea', function () {
- beforeEach(function () {
+ describe('if .in is not an input or textarea', function() {
+ beforeEach(function() {
this.bindInOut = new BindInOut({ tagName: 'SELECT' });
});
- it('should set .eventType to change ', function () {
+ it('should set .eventType to change ', function() {
expect(this.bindInOut.eventType).toEqual('change');
});
});
});
- describe('addEvents', function () {
- beforeEach(function () {
+ describe('addEvents', function() {
+ beforeEach(function() {
this.in = jasmine.createSpyObj('in', ['addEventListener']);
this.bindInOut = new BindInOut(this.in);
@@ -62,25 +62,24 @@ describe('BindInOut', function () {
this.addEvents = this.bindInOut.addEvents();
});
- it('should set .eventWrapper.updateOut', function () {
+ it('should set .eventWrapper.updateOut', function() {
expect(this.bindInOut.eventWrapper.updateOut).toEqual(jasmine.any(Function));
});
- it('should call .addEventListener', function () {
- expect(this.in.addEventListener)
- .toHaveBeenCalledWith(
- this.bindInOut.eventType,
- this.bindInOut.eventWrapper.updateOut,
- );
+ it('should call .addEventListener', function() {
+ expect(this.in.addEventListener).toHaveBeenCalledWith(
+ this.bindInOut.eventType,
+ this.bindInOut.eventWrapper.updateOut,
+ );
});
- it('should return the instance', function () {
+ it('should return the instance', function() {
expect(this.addEvents).toBe(this.bindInOut);
});
});
- describe('updateOut', function () {
- beforeEach(function () {
+ describe('updateOut', function() {
+ beforeEach(function() {
this.in = { value: 'the-value' };
this.out = { textContent: 'not-the-value' };
@@ -89,17 +88,17 @@ describe('BindInOut', function () {
this.updateOut = this.bindInOut.updateOut();
});
- it('should set .out.textContent to .in.value', function () {
+ it('should set .out.textContent to .in.value', function() {
expect(this.out.textContent).toBe(this.in.value);
});
- it('should return the instance', function () {
+ it('should return the instance', function() {
expect(this.updateOut).toBe(this.bindInOut);
});
});
- describe('removeEvents', function () {
- beforeEach(function () {
+ describe('removeEvents', function() {
+ beforeEach(function() {
this.in = jasmine.createSpyObj('in', ['removeEventListener']);
this.updateOut = () => {};
@@ -109,21 +108,20 @@ describe('BindInOut', function () {
this.removeEvents = this.bindInOut.removeEvents();
});
- it('should call .removeEventListener', function () {
- expect(this.in.removeEventListener)
- .toHaveBeenCalledWith(
- this.bindInOut.eventType,
- this.updateOut,
- );
+ it('should call .removeEventListener', function() {
+ expect(this.in.removeEventListener).toHaveBeenCalledWith(
+ this.bindInOut.eventType,
+ this.updateOut,
+ );
});
- it('should return the instance', function () {
+ it('should return the instance', function() {
expect(this.removeEvents).toBe(this.bindInOut);
});
});
- describe('initAll', function () {
- beforeEach(function () {
+ describe('initAll', function() {
+ beforeEach(function() {
this.ins = [0, 1, 2];
this.instances = [];
@@ -136,43 +134,47 @@ describe('BindInOut', function () {
ClassSpecHelper.itShouldBeAStaticMethod(BindInOut, 'initAll');
- it('should call .querySelectorAll', function () {
+ it('should call .querySelectorAll', function() {
expect(document.querySelectorAll).toHaveBeenCalledWith('*[data-bind-in]');
});
- it('should call .map', function () {
+ it('should call .map', function() {
expect(Array.prototype.map).toHaveBeenCalledWith(jasmine.any(Function));
});
- it('should call .init for each element', function () {
+ it('should call .init for each element', function() {
expect(BindInOut.init.calls.count()).toEqual(3);
});
- it('should return an array of instances', function () {
+ it('should return an array of instances', function() {
expect(this.initAll).toEqual(jasmine.any(Array));
});
});
- describe('init', function () {
- beforeEach(function () {
- spyOn(BindInOut.prototype, 'addEvents').and.callFake(function () { return this; });
- spyOn(BindInOut.prototype, 'updateOut').and.callFake(function () { return this; });
+ describe('init', function() {
+ beforeEach(function() {
+ spyOn(BindInOut.prototype, 'addEvents').and.callFake(function() {
+ return this;
+ });
+ spyOn(BindInOut.prototype, 'updateOut').and.callFake(function() {
+ return this;
+ });
this.init = BindInOut.init({}, {});
});
ClassSpecHelper.itShouldBeAStaticMethod(BindInOut, 'init');
- it('should call .addEvents', function () {
+ it('should call .addEvents', function() {
expect(BindInOut.prototype.addEvents).toHaveBeenCalled();
});
- it('should call .updateOut', function () {
+ it('should call .updateOut', function() {
expect(BindInOut.prototype.updateOut).toHaveBeenCalled();
});
- describe('if no anOut is provided', function () {
- beforeEach(function () {
+ describe('if no anOut is provided', function() {
+ beforeEach(function() {
this.anIn = { dataset: { bindIn: 'the-data-bind-in' } };
spyOn(document, 'querySelector');
@@ -180,9 +182,10 @@ describe('BindInOut', function () {
BindInOut.init(this.anIn);
});
- it('should call .querySelector', function () {
- expect(document.querySelector)
- .toHaveBeenCalledWith(`*[data-bind-out="${this.anIn.dataset.bindIn}"]`);
+ it('should call .querySelector', function() {
+ expect(document.querySelector).toHaveBeenCalledWith(
+ `*[data-bind-out="${this.anIn.dataset.bindIn}"]`,
+ );
});
});
});
diff --git a/spec/javascripts/behaviors/copy_as_gfm_spec.js b/spec/javascripts/behaviors/copy_as_gfm_spec.js
index c2db81c6ce4..cf8c1b77861 100644
--- a/spec/javascripts/behaviors/copy_as_gfm_spec.js
+++ b/spec/javascripts/behaviors/copy_as_gfm_spec.js
@@ -29,6 +29,7 @@ describe('CopyAsGFM', () => {
it('wraps pasted code when not already in code tags', () => {
spyOn(window.gl.utils, 'insertText').and.callFake((el, textFunc) => {
const insertedText = textFunc('This is code: ', '');
+
expect(insertedText).toEqual('`code`');
});
@@ -38,6 +39,7 @@ describe('CopyAsGFM', () => {
it('does not wrap pasted code when already in code tags', () => {
spyOn(window.gl.utils, 'insertText').and.callFake((el, textFunc) => {
const insertedText = textFunc('This is code: `', '`');
+
expect(insertedText).toEqual('code');
});
@@ -54,7 +56,7 @@ describe('CopyAsGFM', () => {
const fragment = document.createDocumentFragment();
const node = document.createElement('div');
node.innerHTML = html;
- Array.from(node.childNodes).forEach((item) => fragment.appendChild(item));
+ Array.from(node.childNodes).forEach(item => fragment.appendChild(item));
return fragment;
},
}),
@@ -86,6 +88,7 @@ describe('CopyAsGFM', () => {
simulateCopy();
const expectedGFM = '- List Item1\n- List Item2';
+
expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
});
@@ -95,6 +98,7 @@ describe('CopyAsGFM', () => {
simulateCopy();
const expectedGFM = '1. List Item1\n1. List Item2';
+
expect(clipboardData.setData).toHaveBeenCalledWith('text/x-gfm', expectedGFM);
});
});
diff --git a/spec/javascripts/behaviors/gl_emoji/unicode_support_map_spec.js b/spec/javascripts/behaviors/gl_emoji/unicode_support_map_spec.js
index f96f20ed4a5..f656b97fec2 100644
--- a/spec/javascripts/behaviors/gl_emoji/unicode_support_map_spec.js
+++ b/spec/javascripts/behaviors/gl_emoji/unicode_support_map_spec.js
@@ -13,7 +13,7 @@ describe('Unicode Support Map', () => {
spyOn(JSON, 'stringify').and.returnValue(stringSupportMap);
});
- describe('if isLocalStorageAvailable is `true`', function () {
+ describe('if isLocalStorageAvailable is `true`', function() {
beforeEach(() => {
AccessorUtilities.isLocalStorageAccessSafe.and.returnValue(true);
@@ -36,7 +36,7 @@ describe('Unicode Support Map', () => {
});
});
- describe('if isLocalStorageAvailable is `false`', function () {
+ describe('if isLocalStorageAvailable is `false`', function() {
beforeEach(() => {
AccessorUtilities.isLocalStorageAccessSafe.and.returnValue(false);
diff --git a/spec/javascripts/behaviors/markdown/highlight_current_user_spec.js b/spec/javascripts/behaviors/markdown/highlight_current_user_spec.js
new file mode 100644
index 00000000000..3305ddc412d
--- /dev/null
+++ b/spec/javascripts/behaviors/markdown/highlight_current_user_spec.js
@@ -0,0 +1,55 @@
+import highlightCurrentUser from '~/behaviors/markdown/highlight_current_user';
+
+describe('highlightCurrentUser', () => {
+ let rootElement;
+ let elements;
+
+ beforeEach(() => {
+ setFixtures(`
+ <div id="dummy-root-element">
+ <div data-user="1">@first</div>
+ <div data-user="2">@second</div>
+ </div>
+ `);
+ rootElement = document.getElementById('dummy-root-element');
+ elements = rootElement.querySelectorAll('[data-user]');
+ });
+
+ describe('without current user', () => {
+ beforeEach(() => {
+ window.gon = window.gon || {};
+ window.gon.current_user_id = null;
+ });
+
+ afterEach(() => {
+ delete window.gon.current_user_id;
+ });
+
+ it('does not highlight the user', () => {
+ const initialHtml = rootElement.outerHTML;
+
+ highlightCurrentUser(elements);
+
+ expect(rootElement.outerHTML).toBe(initialHtml);
+ });
+ });
+
+ describe('with current user', () => {
+ beforeEach(() => {
+ window.gon = window.gon || {};
+ window.gon.current_user_id = 2;
+ });
+
+ afterEach(() => {
+ delete window.gon.current_user_id;
+ });
+
+ it('highlights current user', () => {
+ highlightCurrentUser(elements);
+
+ expect(elements.length).toBe(2);
+ expect(elements[0]).not.toHaveClass('current-user');
+ expect(elements[1]).toHaveClass('current-user');
+ });
+ });
+});
diff --git a/spec/javascripts/behaviors/quick_submit_spec.js b/spec/javascripts/behaviors/quick_submit_spec.js
index d8aa5c636da..681463aab66 100644
--- a/spec/javascripts/behaviors/quick_submit_spec.js
+++ b/spec/javascripts/behaviors/quick_submit_spec.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import '~/behaviors/quick_submit';
-describe('Quick Submit behavior', function () {
+describe('Quick Submit behavior', function() {
const keydownEvent = (options = { keyCode: 13, metaKey: true }) => $.Event('keydown', options);
preloadFixtures('snippets/show.html.raw');
@@ -30,6 +30,7 @@ describe('Quick Submit behavior', function () {
keyCode: 32,
}),
);
+
expect(this.spies.submit).not.toHaveBeenTriggered();
});
@@ -40,6 +41,7 @@ describe('Quick Submit behavior', function () {
metaKey: false,
}),
);
+
expect(this.spies.submit).not.toHaveBeenTriggered();
});
@@ -49,6 +51,7 @@ describe('Quick Submit behavior', function () {
repeat: true,
}),
);
+
expect(this.spies.submit).not.toHaveBeenTriggered();
});
@@ -58,12 +61,14 @@ describe('Quick Submit behavior', function () {
expect(submitButton).toBeDisabled();
});
+
it('disables button of type submit', () => {
const submitButton = $('.js-quick-submit input[type=submit]');
this.textarea.trigger(keydownEvent());
expect(submitButton).toBeDisabled();
});
+
it('only clicks one submit', () => {
const existingSubmit = $('.js-quick-submit input[type=submit]');
// Add an extra submit button
@@ -84,7 +89,8 @@ describe('Quick Submit behavior', function () {
describe('In Macintosh', () => {
it('responds to Meta+Enter', () => {
this.textarea.trigger(keydownEvent());
- return expect(this.spies.submit).toHaveBeenTriggered();
+
+ expect(this.spies.submit).toHaveBeenTriggered();
});
it('excludes other modifier keys', () => {
@@ -103,13 +109,15 @@ describe('Quick Submit behavior', function () {
shiftKey: true,
}),
);
- return expect(this.spies.submit).not.toHaveBeenTriggered();
+
+ expect(this.spies.submit).not.toHaveBeenTriggered();
});
});
} else {
it('responds to Ctrl+Enter', () => {
this.textarea.trigger(keydownEvent());
- return expect(this.spies.submit).toHaveBeenTriggered();
+
+ expect(this.spies.submit).toHaveBeenTriggered();
});
it('excludes other modifier keys', () => {
@@ -128,7 +136,8 @@ describe('Quick Submit behavior', function () {
shiftKey: true,
}),
);
- return expect(this.spies.submit).not.toHaveBeenTriggered();
+
+ expect(this.spies.submit).not.toHaveBeenTriggered();
});
}
});
diff --git a/spec/javascripts/behaviors/requires_input_spec.js b/spec/javascripts/behaviors/requires_input_spec.js
index a434949b9da..1bde2bb3024 100644
--- a/spec/javascripts/behaviors/requires_input_spec.js
+++ b/spec/javascripts/behaviors/requires_input_spec.js
@@ -12,33 +12,51 @@ describe('requiresInput', () => {
it('disables submit when any field is required', () => {
$('.js-requires-input').requiresInput();
+
expect(submitButton).toBeDisabled();
});
it('enables submit when no field is required', () => {
$('*[required=required]').prop('required', false);
$('.js-requires-input').requiresInput();
+
expect(submitButton).not.toBeDisabled();
});
it('enables submit when all required fields are pre-filled', () => {
$('*[required=required]').remove();
$('.js-requires-input').requiresInput();
+
expect($('.submit')).not.toBeDisabled();
});
it('enables submit when all required fields receive input', () => {
$('.js-requires-input').requiresInput();
- $('#required1').val('input1').change();
+ $('#required1')
+ .val('input1')
+ .change();
+
expect(submitButton).toBeDisabled();
- $('#optional1').val('input1').change();
+ $('#optional1')
+ .val('input1')
+ .change();
+
expect(submitButton).toBeDisabled();
- $('#required2').val('input2').change();
- $('#required3').val('input3').change();
- $('#required4').val('input4').change();
- $('#required5').val('1').change();
+ $('#required2')
+ .val('input2')
+ .change();
+ $('#required3')
+ .val('input3')
+ .change();
+ $('#required4')
+ .val('input4')
+ .change();
+ $('#required5')
+ .val('1')
+ .change();
+
expect($('.submit')).not.toBeDisabled();
});
});
diff --git a/spec/javascripts/behaviors/secret_values_spec.js b/spec/javascripts/behaviors/secret_values_spec.js
index 95122fcf30f..5aaab093c0c 100644
--- a/spec/javascripts/behaviors/secret_values_spec.js
+++ b/spec/javascripts/behaviors/secret_values_spec.js
@@ -36,12 +36,7 @@ function setupSecretFixture(
placeholderClass = 'js-secret-value-placeholder',
) {
const wrapper = document.createElement('div');
- wrapper.innerHTML = generateFixtureMarkup(
- secrets,
- isRevealed,
- valueClass,
- placeholderClass,
- );
+ wrapper.innerHTML = generateFixtureMarkup(secrets, isRevealed, valueClass, placeholderClass);
const secretValues = new SecretValues({
container: wrapper.querySelector('.js-secret-container'),
@@ -127,11 +122,12 @@ describe('setupSecretValues', () => {
const placeholders = wrapper.querySelectorAll('.js-secret-value-placeholder');
expect(values.length).toEqual(3);
- values.forEach((value) => {
+ values.forEach(value => {
expect(value.classList.contains('hide')).toEqual(true);
});
+
expect(placeholders.length).toEqual(3);
- placeholders.forEach((placeholder) => {
+ placeholders.forEach(placeholder => {
expect(placeholder.classList.contains('hide')).toEqual(false);
});
});
@@ -145,22 +141,24 @@ describe('setupSecretValues', () => {
revealButton.click();
expect(values.length).toEqual(3);
- values.forEach((value) => {
+ values.forEach(value => {
expect(value.classList.contains('hide')).toEqual(false);
});
+
expect(placeholders.length).toEqual(3);
- placeholders.forEach((placeholder) => {
+ placeholders.forEach(placeholder => {
expect(placeholder.classList.contains('hide')).toEqual(true);
});
revealButton.click();
expect(values.length).toEqual(3);
- values.forEach((value) => {
+ values.forEach(value => {
expect(value.classList.contains('hide')).toEqual(true);
});
+
expect(placeholders.length).toEqual(3);
- placeholders.forEach((placeholder) => {
+ placeholders.forEach(placeholder => {
expect(placeholder.classList.contains('hide')).toEqual(false);
});
});
@@ -172,7 +170,9 @@ describe('setupSecretValues', () => {
it('should toggle values and placeholders', () => {
const wrapper = setupSecretFixture(secrets, false);
// Insert the new dynamic row
- wrapper.querySelector('.js-secret-container').insertAdjacentHTML('afterbegin', generateValueMarkup('foobarbazdynamic'));
+ wrapper
+ .querySelector('.js-secret-container')
+ .insertAdjacentHTML('afterbegin', generateValueMarkup('foobarbazdynamic'));
const revealButton = wrapper.querySelector('.js-secret-value-reveal-button');
const values = wrapper.querySelectorAll('.js-secret-value');
@@ -181,22 +181,24 @@ describe('setupSecretValues', () => {
revealButton.click();
expect(values.length).toEqual(4);
- values.forEach((value) => {
+ values.forEach(value => {
expect(value.classList.contains('hide')).toEqual(false);
});
+
expect(placeholders.length).toEqual(4);
- placeholders.forEach((placeholder) => {
+ placeholders.forEach(placeholder => {
expect(placeholder.classList.contains('hide')).toEqual(true);
});
revealButton.click();
expect(values.length).toEqual(4);
- values.forEach((value) => {
+ values.forEach(value => {
expect(value.classList.contains('hide')).toEqual(true);
});
+
expect(placeholders.length).toEqual(4);
- placeholders.forEach((placeholder) => {
+ placeholders.forEach(placeholder => {
expect(placeholder.classList.contains('hide')).toEqual(false);
});
});
diff --git a/spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js b/spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js
index 01b5bc112b2..b709b937180 100644
--- a/spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js
+++ b/spec/javascripts/behaviors/shortcuts/shortcuts_issuable_spec.js
@@ -1,3 +1,7 @@
+/* eslint-disable
+ no-underscore-dangle
+*/
+
import $ from 'jquery';
import initCopyAsGFM from '~/behaviors/markdown/copy_as_gfm';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
@@ -27,13 +31,17 @@ describe('ShortcutsIssuable', function() {
describe('replyWithSelectedText', () => {
// Stub window.gl.utils.getSelectedFragment to return a node with the provided HTML.
- const stubSelection = html => {
- window.gl.utils.getSelectedFragment = () => {
+ const stubSelection = (html, invalidNode) => {
+ ShortcutsIssuable.__Rewire__('getSelectedFragment', () => {
+ const documentFragment = document.createDocumentFragment();
const node = document.createElement('div');
+
node.innerHTML = html;
+ if (!invalidNode) node.className = 'md';
- return node;
- };
+ documentFragment.appendChild(node);
+ return documentFragment;
+ });
};
describe('with empty selection', () => {
it('does not return an error', () => {
@@ -57,9 +65,11 @@ describe('ShortcutsIssuable', function() {
it('leaves existing input intact', () => {
$(FORM_SELECTOR).val('This text was already here.');
+
expect($(FORM_SELECTOR).val()).toBe('This text was already here.');
ShortcutsIssuable.replyWithSelectedText(true);
+
expect($(FORM_SELECTOR).val()).toBe('This text was already here.\n\n> Selected text.\n\n');
});
@@ -70,6 +80,7 @@ describe('ShortcutsIssuable', function() {
});
ShortcutsIssuable.replyWithSelectedText(true);
+
expect(triggered).toBe(true);
});
@@ -102,5 +113,133 @@ describe('ShortcutsIssuable', function() {
);
});
});
+
+ describe('with an invalid selection', () => {
+ beforeEach(() => {
+ stubSelection('<p>Selected text.</p>', true);
+ });
+
+ it('does not add anything to the input', () => {
+ ShortcutsIssuable.replyWithSelectedText(true);
+
+ expect($(FORM_SELECTOR).val()).toBe('');
+ });
+
+ it('triggers `focus`', () => {
+ const spy = spyOn(document.querySelector(FORM_SELECTOR), 'focus');
+ ShortcutsIssuable.replyWithSelectedText(true);
+
+ expect(spy).toHaveBeenCalled();
+ });
+ });
+
+ describe('with a semi-valid selection', () => {
+ beforeEach(() => {
+ stubSelection('<div class="md">Selected text.</div><p>Invalid selected text.</p>', true);
+ });
+
+ it('only adds the valid part to the input', () => {
+ ShortcutsIssuable.replyWithSelectedText(true);
+
+ expect($(FORM_SELECTOR).val()).toBe('> Selected text.\n\n');
+ });
+
+ it('triggers `focus`', () => {
+ const spy = spyOn(document.querySelector(FORM_SELECTOR), 'focus');
+ ShortcutsIssuable.replyWithSelectedText(true);
+
+ expect(spy).toHaveBeenCalled();
+ });
+
+ it('triggers `input`', () => {
+ let triggered = false;
+ $(FORM_SELECTOR).on('input', () => {
+ triggered = true;
+ });
+
+ ShortcutsIssuable.replyWithSelectedText(true);
+
+ expect(triggered).toBe(true);
+ });
+ });
+
+ describe('with a selection in a valid block', () => {
+ beforeEach(() => {
+ ShortcutsIssuable.__Rewire__('getSelectedFragment', () => {
+ const documentFragment = document.createDocumentFragment();
+ const node = document.createElement('div');
+ const originalNode = document.createElement('body');
+ originalNode.innerHTML = `<div class="issue">
+ <div class="otherElem">Text...</div>
+ <div class="md"><p><em>Selected text.</em></p></div>
+ </div>`;
+ documentFragment.originalNodes = [originalNode.querySelector('em')];
+
+ node.innerHTML = '<em>Selected text.</em>';
+
+ documentFragment.appendChild(node);
+
+ return documentFragment;
+ });
+ });
+
+ it('adds the quoted selection to the input', () => {
+ ShortcutsIssuable.replyWithSelectedText(true);
+
+ expect($(FORM_SELECTOR).val()).toBe('> _Selected text._\n\n');
+ });
+
+ it('triggers `focus`', () => {
+ const spy = spyOn(document.querySelector(FORM_SELECTOR), 'focus');
+ ShortcutsIssuable.replyWithSelectedText(true);
+
+ expect(spy).toHaveBeenCalled();
+ });
+
+ it('triggers `input`', () => {
+ let triggered = false;
+ $(FORM_SELECTOR).on('input', () => {
+ triggered = true;
+ });
+
+ ShortcutsIssuable.replyWithSelectedText(true);
+
+ expect(triggered).toBe(true);
+ });
+ });
+
+ describe('with a selection in an invalid block', () => {
+ beforeEach(() => {
+ ShortcutsIssuable.__Rewire__('getSelectedFragment', () => {
+ const documentFragment = document.createDocumentFragment();
+ const node = document.createElement('div');
+ const originalNode = document.createElement('body');
+ originalNode.innerHTML = `<div class="issue">
+ <div class="otherElem"><div><b>Selected text.</b></div></div>
+ <div class="md"><p><em>Valid text</em></p></div>
+ </div>`;
+ documentFragment.originalNodes = [originalNode.querySelector('b')];
+
+ node.innerHTML = '<b>Selected text.</b>';
+
+ documentFragment.appendChild(node);
+
+ return documentFragment;
+ });
+ });
+
+ it('does not add anything to the input', () => {
+ ShortcutsIssuable.replyWithSelectedText(true);
+
+ expect($(FORM_SELECTOR).val()).toBe('');
+ });
+
+ it('triggers `focus`', () => {
+ const spy = spyOn(document.querySelector(FORM_SELECTOR), 'focus');
+ ShortcutsIssuable.replyWithSelectedText(true);
+
+ expect(spy).toHaveBeenCalled();
+ });
+ });
});
});
diff --git a/spec/javascripts/blob/3d_viewer/mesh_object_spec.js b/spec/javascripts/blob/3d_viewer/mesh_object_spec.js
index 7651792be2e..60be285039f 100644
--- a/spec/javascripts/blob/3d_viewer/mesh_object_spec.js
+++ b/spec/javascripts/blob/3d_viewer/mesh_object_spec.js
@@ -1,21 +1,15 @@
-import {
- BoxGeometry,
-} from 'three/build/three.module';
+import { BoxGeometry } from 'three/build/three.module';
import MeshObject from '~/blob/3d_viewer/mesh_object';
describe('Mesh object', () => {
it('defaults to non-wireframe material', () => {
- const object = new MeshObject(
- new BoxGeometry(10, 10, 10),
- );
+ const object = new MeshObject(new BoxGeometry(10, 10, 10));
expect(object.material.wireframe).toBeFalsy();
});
it('changes to wirefame material', () => {
- const object = new MeshObject(
- new BoxGeometry(10, 10, 10),
- );
+ const object = new MeshObject(new BoxGeometry(10, 10, 10));
object.changeMaterial('wireframe');
@@ -23,18 +17,14 @@ describe('Mesh object', () => {
});
it('scales object down', () => {
- const object = new MeshObject(
- new BoxGeometry(10, 10, 10),
- );
+ const object = new MeshObject(new BoxGeometry(10, 10, 10));
const { radius } = object.geometry.boundingSphere;
expect(radius).not.toBeGreaterThan(4);
});
it('does not scale object down', () => {
- const object = new MeshObject(
- new BoxGeometry(1, 1, 1),
- );
+ const object = new MeshObject(new BoxGeometry(1, 1, 1));
const { radius } = object.geometry.boundingSphere;
expect(radius).toBeLessThan(1);
diff --git a/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js b/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js
index c726fa8e428..5f027f59fcf 100644
--- a/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js
+++ b/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js
@@ -16,10 +16,13 @@ describe('Balsamiq integration spec', () => {
});
describe('successful response', () => {
- beforeEach((done) => {
+ beforeEach(done => {
endpoint = bmprPath;
- balsamiqViewer.loadFile(endpoint).then(done).catch(done.fail);
+ balsamiqViewer
+ .loadFile(endpoint)
+ .then(done)
+ .catch(done.fail);
});
it('does not show loading icon', () => {
@@ -32,10 +35,13 @@ describe('Balsamiq integration spec', () => {
});
describe('error getting file', () => {
- beforeEach((done) => {
+ beforeEach(done => {
endpoint = 'invalid/path/to/file.bmpr';
- balsamiqViewer.loadFile(endpoint).then(done.fail, null).catch(done);
+ balsamiqViewer
+ .loadFile(endpoint)
+ .then(done.fail, null)
+ .catch(done);
});
it('does not show loading icon', () => {
diff --git a/spec/javascripts/blob/balsamiq/balsamiq_viewer_spec.js b/spec/javascripts/blob/balsamiq/balsamiq_viewer_spec.js
index cb0f2ba686d..fd73fb4bfcc 100644
--- a/spec/javascripts/blob/balsamiq/balsamiq_viewer_spec.js
+++ b/spec/javascripts/blob/balsamiq/balsamiq_viewer_spec.js
@@ -18,10 +18,6 @@ describe('BalsamiqViewer', () => {
});
});
- describe('fileLoaded', () => {
-
- });
-
describe('loadFile', () => {
let xhr;
let loadFile;
@@ -64,12 +60,16 @@ describe('BalsamiqViewer', () => {
viewer = jasmine.createSpyObj('viewer', ['appendChild']);
previews = [document.createElement('ul'), document.createElement('ul')];
- balsamiqViewer = jasmine.createSpyObj('balsamiqViewer', ['initDatabase', 'getPreviews', 'renderPreview']);
+ balsamiqViewer = jasmine.createSpyObj('balsamiqViewer', [
+ 'initDatabase',
+ 'getPreviews',
+ 'renderPreview',
+ ]);
balsamiqViewer.viewer = viewer;
balsamiqViewer.getPreviews.and.returnValue(previews);
balsamiqViewer.renderPreview.and.callFake(preview => preview);
- viewer.appendChild.and.callFake((containerElement) => {
+ viewer.appendChild.and.callFake(containerElement => {
container = containerElement;
});
@@ -198,7 +198,9 @@ describe('BalsamiqViewer', () => {
});
it('should call database.exec', () => {
- expect(database.exec).toHaveBeenCalledWith(`SELECT * FROM resources WHERE id = '${resourceID}'`);
+ expect(database.exec).toHaveBeenCalledWith(
+ `SELECT * FROM resources WHERE id = '${resourceID}'`,
+ );
});
it('should return the selected resource', () => {
@@ -281,7 +283,7 @@ describe('BalsamiqViewer', () => {
expect(BalsamiqViewer.parseTitle).toHaveBeenCalledWith(resource);
});
- it('should return the template string', function () {
+ it('should return the template string', function() {
expect(renderTemplate.replace(/\s/g, '')).toEqual(template.replace(/\s/g, ''));
});
});
diff --git a/spec/javascripts/blob/blob_file_dropzone_spec.js b/spec/javascripts/blob/blob_file_dropzone_spec.js
index 346f795c3f5..432d8a65b0a 100644
--- a/spec/javascripts/blob/blob_file_dropzone_spec.js
+++ b/spec/javascripts/blob/blob_file_dropzone_spec.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import BlobFileDropzone from '~/blob/blob_file_dropzone';
-describe('BlobFileDropzone', function () {
+describe('BlobFileDropzone', function() {
preloadFixtures('blob/show.html.raw');
beforeEach(() => {
diff --git a/spec/javascripts/blob/blob_fork_suggestion_spec.js b/spec/javascripts/blob/blob_fork_suggestion_spec.js
index d1ab0a32f85..9b81b7e6f92 100644
--- a/spec/javascripts/blob/blob_fork_suggestion_spec.js
+++ b/spec/javascripts/blob/blob_fork_suggestion_spec.js
@@ -16,8 +16,7 @@ describe('BlobForkSuggestion', () => {
cancelButtons: cancelButton,
suggestionSections: suggestionSection,
actionTextPieces: actionTextPiece,
- })
- .init();
+ }).init();
});
afterEach(() => {
@@ -26,6 +25,7 @@ describe('BlobForkSuggestion', () => {
it('showSuggestionSection', () => {
blobForkSuggestion.showSuggestionSection('/foo', 'foo');
+
expect(suggestionSection.classList.contains('hidden')).toEqual(false);
expect(forkButton.getAttribute('href')).toEqual('/foo');
expect(actionTextPiece.textContent).toEqual('foo');
@@ -33,6 +33,7 @@ describe('BlobForkSuggestion', () => {
it('hideSuggestionSection', () => {
blobForkSuggestion.hideSuggestionSection();
+
expect(suggestionSection.classList.contains('hidden')).toEqual(true);
});
});
diff --git a/spec/javascripts/blob/notebook/index_spec.js b/spec/javascripts/blob/notebook/index_spec.js
index 80c09a544d6..28d3b2f5ea3 100644
--- a/spec/javascripts/blob/notebook/index_spec.js
+++ b/spec/javascripts/blob/notebook/index_spec.js
@@ -12,29 +12,27 @@ describe('iPython notebook renderer', () => {
it('shows loading icon', () => {
renderNotebook();
- expect(
- document.querySelector('.loading'),
- ).not.toBeNull();
+ expect(document.querySelector('.loading')).not.toBeNull();
});
describe('successful response', () => {
let mock;
- beforeEach((done) => {
+ beforeEach(done => {
mock = new MockAdapter(axios);
mock.onGet('/test').reply(200, {
- cells: [{
- cell_type: 'markdown',
- source: ['# test'],
- }, {
- cell_type: 'code',
- execution_count: 1,
- source: [
- 'def test(str)',
- ' return str',
- ],
- outputs: [],
- }],
+ cells: [
+ {
+ cell_type: 'markdown',
+ source: ['# test'],
+ },
+ {
+ cell_type: 'code',
+ execution_count: 1,
+ source: ['def test(str)', ' return str'],
+ outputs: [],
+ },
+ ],
});
renderNotebook();
@@ -49,35 +47,23 @@ describe('iPython notebook renderer', () => {
});
it('does not show loading icon', () => {
- expect(
- document.querySelector('.loading'),
- ).toBeNull();
+ expect(document.querySelector('.loading')).toBeNull();
});
it('renders the notebook', () => {
- expect(
- document.querySelector('.md'),
- ).not.toBeNull();
+ expect(document.querySelector('.md')).not.toBeNull();
});
it('renders the markdown cell', () => {
- expect(
- document.querySelector('h1'),
- ).not.toBeNull();
+ expect(document.querySelector('h1')).not.toBeNull();
- expect(
- document.querySelector('h1').textContent.trim(),
- ).toBe('test');
+ expect(document.querySelector('h1').textContent.trim()).toBe('test');
});
it('highlights code', () => {
- expect(
- document.querySelector('.token'),
- ).not.toBeNull();
+ expect(document.querySelector('.token')).not.toBeNull();
- expect(
- document.querySelector('.language-python'),
- ).not.toBeNull();
+ expect(document.querySelector('.language-python')).not.toBeNull();
});
});
@@ -86,12 +72,10 @@ describe('iPython notebook renderer', () => {
beforeEach(done => {
mock = new MockAdapter(axios);
- mock
- .onGet('/test')
- .reply(() =>
- // eslint-disable-next-line prefer-promise-reject-errors
- Promise.reject({ status: 200, data: '{ "cells": [{"cell_type": "markdown"} }' }),
- );
+ mock.onGet('/test').reply(() =>
+ // eslint-disable-next-line prefer-promise-reject-errors
+ Promise.reject({ status: 200, data: '{ "cells": [{"cell_type": "markdown"} }' }),
+ );
renderNotebook();
@@ -105,22 +89,20 @@ describe('iPython notebook renderer', () => {
});
it('does not show loading icon', () => {
- expect(
- document.querySelector('.loading'),
- ).toBeNull();
+ expect(document.querySelector('.loading')).toBeNull();
});
it('shows error message', () => {
- expect(
- document.querySelector('.md').textContent.trim(),
- ).toBe('An error occurred whilst parsing the file.');
+ expect(document.querySelector('.md').textContent.trim()).toBe(
+ 'An error occurred whilst parsing the file.',
+ );
});
});
describe('error getting file', () => {
let mock;
- beforeEach((done) => {
+ beforeEach(done => {
mock = new MockAdapter(axios);
mock.onGet('/test').reply(500, '');
@@ -136,15 +118,13 @@ describe('iPython notebook renderer', () => {
});
it('does not show loading icon', () => {
- expect(
- document.querySelector('.loading'),
- ).toBeNull();
+ expect(document.querySelector('.loading')).toBeNull();
});
it('shows error message', () => {
- expect(
- document.querySelector('.md').textContent.trim(),
- ).toBe('An error occurred whilst loading the file. Please try again later.');
+ expect(document.querySelector('.md').textContent.trim()).toBe(
+ 'An error occurred whilst loading the file. Please try again later.',
+ );
});
});
});
diff --git a/spec/javascripts/blob/pdf/index_spec.js b/spec/javascripts/blob/pdf/index_spec.js
index bbe2500f8e3..be917a0613f 100644
--- a/spec/javascripts/blob/pdf/index_spec.js
+++ b/spec/javascripts/blob/pdf/index_spec.js
@@ -5,7 +5,7 @@ describe('PDF renderer', () => {
let viewer;
let app;
- const checkLoaded = (done) => {
+ const checkLoaded = done => {
if (app.loading) {
setTimeout(() => {
checkLoaded(done);
@@ -26,39 +26,31 @@ describe('PDF renderer', () => {
it('shows loading icon', () => {
renderPDF();
- expect(
- document.querySelector('.loading'),
- ).not.toBeNull();
+ expect(document.querySelector('.loading')).not.toBeNull();
});
describe('successful response', () => {
- beforeEach((done) => {
+ beforeEach(done => {
app = renderPDF();
checkLoaded(done);
});
it('does not show loading icon', () => {
- expect(
- document.querySelector('.loading'),
- ).toBeNull();
+ expect(document.querySelector('.loading')).toBeNull();
});
it('renders the PDF', () => {
- expect(
- document.querySelector('.pdf-viewer'),
- ).not.toBeNull();
+ expect(document.querySelector('.pdf-viewer')).not.toBeNull();
});
it('renders the PDF page', () => {
- expect(
- document.querySelector('.pdf-page'),
- ).not.toBeNull();
+ expect(document.querySelector('.pdf-page')).not.toBeNull();
});
});
describe('error getting file', () => {
- beforeEach((done) => {
+ beforeEach(done => {
viewer.dataset.endpoint = 'invalid/path/to/file.pdf';
app = renderPDF();
@@ -66,15 +58,13 @@ describe('PDF renderer', () => {
});
it('does not show loading icon', () => {
- expect(
- document.querySelector('.loading'),
- ).toBeNull();
+ expect(document.querySelector('.loading')).toBeNull();
});
it('shows error message', () => {
- expect(
- document.querySelector('.md').textContent.trim(),
- ).toBe('An error occurred whilst loading the file. Please try again later.');
+ expect(document.querySelector('.md').textContent.trim()).toBe(
+ 'An error occurred whilst loading the file. Please try again later.',
+ );
});
});
});
diff --git a/spec/javascripts/blob/sketch/index_spec.js b/spec/javascripts/blob/sketch/index_spec.js
index e062a068a92..2b1e81e9cbc 100644
--- a/spec/javascripts/blob/sketch/index_spec.js
+++ b/spec/javascripts/blob/sketch/index_spec.js
@@ -4,15 +4,13 @@ import SketchLoader from '~/blob/sketch';
describe('Sketch viewer', () => {
const generateZipFileArrayBuffer = (zipFile, resolve, done) => {
- zipFile
- .generateAsync({ type: 'arrayBuffer' })
- .then((content) => {
- resolve(content);
-
- setTimeout(() => {
- done();
- }, 100);
- });
+ zipFile.generateAsync({ type: 'arrayBuffer' }).then(content => {
+ resolve(content);
+
+ setTimeout(() => {
+ done();
+ }, 100);
+ });
};
preloadFixtures('static/sketch_viewer.html.raw');
@@ -22,60 +20,63 @@ describe('Sketch viewer', () => {
});
describe('with error message', () => {
- beforeEach((done) => {
- spyOn(SketchLoader.prototype, 'getZipFile').and.callFake(() => new Promise((resolve, reject) => {
- reject();
-
- setTimeout(() => {
- done();
- });
- }));
+ beforeEach(done => {
+ spyOn(SketchLoader.prototype, 'getZipFile').and.callFake(
+ () =>
+ new Promise((resolve, reject) => {
+ reject();
+
+ setTimeout(() => {
+ done();
+ });
+ }),
+ );
new SketchLoader(document.getElementById('js-sketch-viewer'));
});
it('renders error message', () => {
- expect(
- document.querySelector('#js-sketch-viewer p'),
- ).not.toBeNull();
+ expect(document.querySelector('#js-sketch-viewer p')).not.toBeNull();
- expect(
- document.querySelector('#js-sketch-viewer p').textContent.trim(),
- ).toContain('Cannot show preview.');
+ expect(document.querySelector('#js-sketch-viewer p').textContent.trim()).toContain(
+ 'Cannot show preview.',
+ );
});
it('removes render the loading icon', () => {
- expect(
- document.querySelector('.js-loading-icon'),
- ).toBeNull();
+ expect(document.querySelector('.js-loading-icon')).toBeNull();
});
});
describe('success', () => {
- beforeEach((done) => {
- spyOn(SketchLoader.prototype, 'getZipFile').and.callFake(() => new Promise((resolve) => {
- const zipFile = new JSZip();
- zipFile.folder('previews')
- .file('preview.png', 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAMAAAAoyzS7AAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAA1JREFUeNoBAgD9/wAAAAIAAVMrnDAAAAAASUVORK5CYII=', {
- base64: true,
- });
-
- generateZipFileArrayBuffer(zipFile, resolve, done);
- }));
+ beforeEach(done => {
+ spyOn(SketchLoader.prototype, 'getZipFile').and.callFake(
+ () =>
+ new Promise(resolve => {
+ const zipFile = new JSZip();
+ zipFile
+ .folder('previews')
+ .file(
+ 'preview.png',
+ 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAMAAAAoyzS7AAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAA1JREFUeNoBAgD9/wAAAAIAAVMrnDAAAAAASUVORK5CYII=',
+ {
+ base64: true,
+ },
+ );
+
+ generateZipFileArrayBuffer(zipFile, resolve, done);
+ }),
+ );
new SketchLoader(document.getElementById('js-sketch-viewer'));
});
it('does not render error message', () => {
- expect(
- document.querySelector('#js-sketch-viewer p'),
- ).toBeNull();
+ expect(document.querySelector('#js-sketch-viewer p')).toBeNull();
});
it('removes render the loading icon', () => {
- expect(
- document.querySelector('.js-loading-icon'),
- ).toBeNull();
+ expect(document.querySelector('.js-loading-icon')).toBeNull();
});
it('renders preview img', () => {
@@ -95,24 +96,25 @@ describe('Sketch viewer', () => {
});
describe('incorrect file', () => {
- beforeEach((done) => {
- spyOn(SketchLoader.prototype, 'getZipFile').and.callFake(() => new Promise((resolve) => {
- const zipFile = new JSZip();
+ beforeEach(done => {
+ spyOn(SketchLoader.prototype, 'getZipFile').and.callFake(
+ () =>
+ new Promise(resolve => {
+ const zipFile = new JSZip();
- generateZipFileArrayBuffer(zipFile, resolve, done);
- }));
+ generateZipFileArrayBuffer(zipFile, resolve, done);
+ }),
+ );
new SketchLoader(document.getElementById('js-sketch-viewer'));
});
it('renders error message', () => {
- expect(
- document.querySelector('#js-sketch-viewer p'),
- ).not.toBeNull();
+ expect(document.querySelector('#js-sketch-viewer p')).not.toBeNull();
- expect(
- document.querySelector('#js-sketch-viewer p').textContent.trim(),
- ).toContain('Cannot show preview.');
+ expect(document.querySelector('#js-sketch-viewer p').textContent.trim()).toContain(
+ 'Cannot show preview.',
+ );
});
});
});
diff --git a/spec/javascripts/blob/viewer/index_spec.js b/spec/javascripts/blob/viewer/index_spec.js
index 8b79624d9f4..93a942fe8d4 100644
--- a/spec/javascripts/blob/viewer/index_spec.js
+++ b/spec/javascripts/blob/viewer/index_spec.js
@@ -35,12 +35,13 @@ describe('Blob viewer', () => {
window.location.hash = '';
});
- it('loads source file after switching views', (done) => {
+ it('loads source file after switching views', done => {
document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click();
setTimeout(() => {
expect(
- document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]')
+ document
+ .querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]')
.classList.contains('hidden'),
).toBeFalsy();
@@ -48,14 +49,15 @@ describe('Blob viewer', () => {
});
});
- it('loads source file when line number is in hash', (done) => {
+ it('loads source file when line number is in hash', done => {
window.location.hash = '#L1';
new BlobViewer();
setTimeout(() => {
expect(
- document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]')
+ document
+ .querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]')
.classList.contains('hidden'),
).toBeFalsy();
@@ -63,12 +65,13 @@ describe('Blob viewer', () => {
});
});
- it('doesnt reload file if already loaded', (done) => {
- const asyncClick = () => new Promise((resolve) => {
- document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click();
+ it('doesnt reload file if already loaded', done => {
+ const asyncClick = () =>
+ new Promise(resolve => {
+ document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click();
- setTimeout(resolve);
- });
+ setTimeout(resolve);
+ });
asyncClick()
.then(() => asyncClick())
@@ -93,15 +96,13 @@ describe('Blob viewer', () => {
});
it('disabled on load', () => {
- expect(
- copyButton.classList.contains('disabled'),
- ).toBeTruthy();
+ expect(copyButton.classList.contains('disabled')).toBeTruthy();
});
it('has tooltip when disabled', () => {
- expect(
- copyButton.getAttribute('data-original-title'),
- ).toBe('Switch to the source to copy it to the clipboard');
+ expect(copyButton.getAttribute('data-original-title')).toBe(
+ 'Switch to the source to copy it to the clipboard',
+ );
});
it('is blurred when clicked and disabled', () => {
@@ -121,25 +122,21 @@ describe('Blob viewer', () => {
expect(copyButton.blur).not.toHaveBeenCalled();
});
- it('enables after switching to simple view', (done) => {
+ it('enables after switching to simple view', done => {
document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click();
setTimeout(() => {
- expect(
- copyButton.classList.contains('disabled'),
- ).toBeFalsy();
+ expect(copyButton.classList.contains('disabled')).toBeFalsy();
done();
});
});
- it('updates tooltip after switching to simple view', (done) => {
+ it('updates tooltip after switching to simple view', done => {
document.querySelector('.js-blob-viewer-switch-btn[data-viewer="simple"]').click();
setTimeout(() => {
- expect(
- copyButton.getAttribute('data-original-title'),
- ).toBe('Copy source to clipboard');
+ expect(copyButton.getAttribute('data-original-title')).toBe('Copy source to clipboard');
done();
});
@@ -162,9 +159,8 @@ describe('Blob viewer', () => {
blob.switchToViewer('simple');
- expect(
- simpleBtn.classList.contains('active'),
- ).toBeTruthy();
+ expect(simpleBtn.classList.contains('active')).toBeTruthy();
+
expect(simpleBtn.blur).toHaveBeenCalled();
});
diff --git a/spec/javascripts/blob_edit/blob_bundle_spec.js b/spec/javascripts/blob_edit/blob_bundle_spec.js
new file mode 100644
index 00000000000..759d170af77
--- /dev/null
+++ b/spec/javascripts/blob_edit/blob_bundle_spec.js
@@ -0,0 +1,30 @@
+import blobBundle from '~/blob_edit/blob_bundle';
+import $ from 'jquery';
+
+window.ace = {
+ config: {
+ set: () => {},
+ loadModule: () => {},
+ },
+ edit: () => ({ focus: () => {} }),
+};
+
+describe('EditBlob', () => {
+ beforeEach(() => {
+ setFixtures(`
+ <div class="js-edit-blob-form">
+ <button class="js-commit-button"></button>
+ </div>`);
+ blobBundle();
+ });
+
+ it('sets the window beforeunload listener to a function returning a string', () => {
+ expect(window.onbeforeunload()).toBe('');
+ });
+
+ it('removes beforeunload listener if commit button is clicked', () => {
+ $('.js-commit-button').click();
+
+ expect(window.onbeforeunload).toBeNull();
+ });
+});
diff --git a/spec/javascripts/boards/board_blank_state_spec.js b/spec/javascripts/boards/board_blank_state_spec.js
index 0e4e1697fd0..8e2a947b0dd 100644
--- a/spec/javascripts/boards/board_blank_state_spec.js
+++ b/spec/javascripts/boards/board_blank_state_spec.js
@@ -1,5 +1,5 @@
import Vue from 'vue';
-import '~/boards/stores/boards_store';
+import boardsStore from '~/boards/stores/boards_store';
import BoardBlankState from '~/boards/components/board_blank_state.vue';
import { mockBoardService } from './mock_data';
@@ -7,29 +7,35 @@ describe('Boards blank state', () => {
let vm;
let fail = false;
- beforeEach((done) => {
+ beforeEach(done => {
const Comp = Vue.extend(BoardBlankState);
- gl.issueBoards.BoardsStore.create();
+ boardsStore.create();
gl.boardService = mockBoardService();
- spyOn(gl.boardService, 'generateDefaultLists').and.callFake(() => new Promise((resolve, reject) => {
- if (fail) {
- reject();
- } else {
- resolve({
- data: [{
- id: 1,
- title: 'To Do',
- label: { id: 1 },
- }, {
- id: 2,
- title: 'Doing',
- label: { id: 2 },
- }],
- });
- }
- }));
+ spyOn(gl.boardService, 'generateDefaultLists').and.callFake(
+ () =>
+ new Promise((resolve, reject) => {
+ if (fail) {
+ reject();
+ } else {
+ resolve({
+ data: [
+ {
+ id: 1,
+ title: 'To Do',
+ label: { id: 1 },
+ },
+ {
+ id: 2,
+ title: 'Doing',
+ label: { id: 2 },
+ },
+ ],
+ });
+ }
+ }),
+ );
vm = new Comp();
@@ -40,49 +46,47 @@ describe('Boards blank state', () => {
});
it('renders pre-defined labels', () => {
- expect(
- vm.$el.querySelectorAll('.board-blank-state-list li').length,
- ).toBe(2);
+ expect(vm.$el.querySelectorAll('.board-blank-state-list li').length).toBe(2);
- expect(
- vm.$el.querySelectorAll('.board-blank-state-list li')[0].textContent.trim(),
- ).toEqual('To Do');
+ expect(vm.$el.querySelectorAll('.board-blank-state-list li')[0].textContent.trim()).toEqual(
+ 'To Do',
+ );
- expect(
- vm.$el.querySelectorAll('.board-blank-state-list li')[1].textContent.trim(),
- ).toEqual('Doing');
+ expect(vm.$el.querySelectorAll('.board-blank-state-list li')[1].textContent.trim()).toEqual(
+ 'Doing',
+ );
});
- it('clears blank state', (done) => {
+ it('clears blank state', done => {
vm.$el.querySelector('.btn-default').click();
setTimeout(() => {
- expect(gl.issueBoards.BoardsStore.welcomeIsHidden()).toBeTruthy();
+ expect(boardsStore.welcomeIsHidden()).toBeTruthy();
done();
});
});
- it('creates pre-defined labels', (done) => {
+ it('creates pre-defined labels', done => {
vm.$el.querySelector('.btn-success').click();
setTimeout(() => {
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2);
- expect(gl.issueBoards.BoardsStore.state.lists[0].title).toEqual('To Do');
- expect(gl.issueBoards.BoardsStore.state.lists[1].title).toEqual('Doing');
+ expect(boardsStore.state.lists.length).toBe(2);
+ expect(boardsStore.state.lists[0].title).toEqual('To Do');
+ expect(boardsStore.state.lists[1].title).toEqual('Doing');
done();
});
});
- it('resets the store if request fails', (done) => {
+ it('resets the store if request fails', done => {
fail = true;
vm.$el.querySelector('.btn-success').click();
setTimeout(() => {
- expect(gl.issueBoards.BoardsStore.welcomeIsHidden()).toBeFalsy();
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1);
+ expect(boardsStore.welcomeIsHidden()).toBeFalsy();
+ expect(boardsStore.state.lists.length).toBe(1);
done();
});
diff --git a/spec/javascripts/boards/board_card_spec.js b/spec/javascripts/boards/board_card_spec.js
index ad263791cd4..e1017130bed 100644
--- a/spec/javascripts/boards/board_card_spec.js
+++ b/spec/javascripts/boards/board_card_spec.js
@@ -10,7 +10,7 @@ import eventHub from '~/boards/eventhub';
import '~/vue_shared/models/label';
import '~/vue_shared/models/assignee';
import '~/boards/models/list';
-import '~/boards/stores/boards_store';
+import boardsStore from '~/boards/stores/boards_store';
import boardCard from '~/boards/components/board_card.vue';
import { listObj, boardsMockInterceptor, mockBoardService } from './mock_data';
@@ -18,13 +18,13 @@ describe('Board card', () => {
let vm;
let mock;
- beforeEach((done) => {
+ beforeEach(done => {
mock = new MockAdapter(axios);
mock.onAny().reply(boardsMockInterceptor);
gl.boardService = mockBoardService();
- gl.issueBoards.BoardsStore.create();
- gl.issueBoards.BoardsStore.detail.issue = {};
+ boardsStore.create();
+ boardsStore.detail.issue = {};
const BoardCardComp = Vue.extend(boardCard);
const list = new List(listObj);
@@ -62,7 +62,7 @@ describe('Board card', () => {
});
it('returns true when detailIssue is equal to card issue', () => {
- gl.issueBoards.BoardsStore.detail.issue = vm.issue;
+ boardsStore.detail.issue = vm.issue;
expect(vm.issueDetailVisible).toBe(true);
});
@@ -71,7 +71,7 @@ describe('Board card', () => {
expect(vm.$el.classList.contains('user-can-drag')).toBe(true);
});
- it('does not add user-can-drag class disabled', (done) => {
+ it('does not add user-can-drag class disabled', done => {
vm.disabled = true;
setTimeout(() => {
@@ -84,7 +84,7 @@ describe('Board card', () => {
expect(vm.$el.classList.contains('is-disabled')).toBe(false);
});
- it('adds disabled class is disabled is true', (done) => {
+ it('adds disabled class is disabled is true', done => {
vm.disabled = true;
setTimeout(() => {
@@ -96,8 +96,23 @@ describe('Board card', () => {
describe('mouse events', () => {
const triggerEvent = (eventName, el = vm.$el) => {
const event = document.createEvent('MouseEvents');
- event.initMouseEvent(eventName, true, true, window, 1, 0, 0, 0, 0, false, false,
- false, false, 0, null);
+ event.initMouseEvent(
+ eventName,
+ true,
+ true,
+ window,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0,
+ false,
+ false,
+ false,
+ false,
+ 0,
+ null,
+ );
el.dispatchEvent(event);
};
@@ -119,33 +134,35 @@ describe('Board card', () => {
});
it('does not set detail issue if showDetail is false', () => {
- expect(gl.issueBoards.BoardsStore.detail.issue).toEqual({});
+ expect(boardsStore.detail.issue).toEqual({});
});
it('does not set detail issue if link is clicked', () => {
triggerEvent('mouseup', vm.$el.querySelector('a'));
- expect(gl.issueBoards.BoardsStore.detail.issue).toEqual({});
+ expect(boardsStore.detail.issue).toEqual({});
});
it('does not set detail issue if button is clicked', () => {
triggerEvent('mouseup', vm.$el.querySelector('button'));
- expect(gl.issueBoards.BoardsStore.detail.issue).toEqual({});
+ expect(boardsStore.detail.issue).toEqual({});
});
- it('does not set detail issue if img is clicked', (done) => {
- vm.issue.assignees = [new ListAssignee({
- id: 1,
- name: 'testing 123',
- username: 'test',
- avatar: 'test_image',
- })];
+ it('does not set detail issue if img is clicked', done => {
+ vm.issue.assignees = [
+ new ListAssignee({
+ id: 1,
+ name: 'testing 123',
+ username: 'test',
+ avatar: 'test_image',
+ }),
+ ];
Vue.nextTick(() => {
triggerEvent('mouseup', vm.$el.querySelector('img'));
- expect(gl.issueBoards.BoardsStore.detail.issue).toEqual({});
+ expect(boardsStore.detail.issue).toEqual({});
done();
});
@@ -154,7 +171,7 @@ describe('Board card', () => {
it('does not set detail issue if showDetail is false after mouseup', () => {
triggerEvent('mouseup');
- expect(gl.issueBoards.BoardsStore.detail.issue).toEqual({});
+ expect(boardsStore.detail.issue).toEqual({});
});
it('sets detail issue to card issue on mouse up', () => {
@@ -164,10 +181,10 @@ describe('Board card', () => {
triggerEvent('mouseup');
expect(eventHub.$emit).toHaveBeenCalledWith('newDetailIssue', vm.issue);
- expect(gl.issueBoards.BoardsStore.detail.list).toEqual(vm.list);
+ expect(boardsStore.detail.list).toEqual(vm.list);
});
- it('adds active class if detail issue is set', (done) => {
+ it('adds active class if detail issue is set', done => {
vm.detailIssue.issue = vm.issue;
Vue.nextTick()
@@ -181,7 +198,7 @@ describe('Board card', () => {
it('resets detail issue to empty if already set', () => {
spyOn(eventHub, '$emit');
- gl.issueBoards.BoardsStore.detail.issue = vm.issue;
+ boardsStore.detail.issue = vm.issue;
triggerEvent('mousedown');
triggerEvent('mouseup');
diff --git a/spec/javascripts/boards/board_list_spec.js b/spec/javascripts/boards/board_list_spec.js
index 290600cf995..2642c8b1bdb 100644
--- a/spec/javascripts/boards/board_list_spec.js
+++ b/spec/javascripts/boards/board_list_spec.js
@@ -1,15 +1,15 @@
/* global List */
/* global ListIssue */
+
import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import Sortable from 'sortablejs';
import BoardList from '~/boards/components/board_list.vue';
import eventHub from '~/boards/eventhub';
-import '~/boards/mixins/sortable_default_options';
import '~/boards/models/issue';
import '~/boards/models/list';
-import '~/boards/stores/boards_store';
+import boardsStore from '~/boards/stores/boards_store';
import { listObj, boardsMockInterceptor, mockBoardService } from './mock_data';
window.Sortable = Sortable;
@@ -18,15 +18,14 @@ describe('Board list component', () => {
let mock;
let component;
- beforeEach((done) => {
+ beforeEach(done => {
const el = document.createElement('div');
document.body.appendChild(el);
mock = new MockAdapter(axios);
mock.onAny().reply(boardsMockInterceptor);
gl.boardService = mockBoardService();
- gl.issueBoards.BoardsStore.create();
- gl.IssueBoardsApp = new Vue();
+ boardsStore.create();
const BoardListComp = Vue.extend(BoardList);
const list = new List(listObj);
@@ -63,122 +62,102 @@ describe('Board list component', () => {
});
it('renders component', () => {
- expect(
- component.$el.classList.contains('board-list-component'),
- ).toBe(true);
+ expect(component.$el.classList.contains('board-list-component')).toBe(true);
});
- it('renders loading icon', (done) => {
+ it('renders loading icon', done => {
component.loading = true;
Vue.nextTick(() => {
- expect(
- component.$el.querySelector('.board-list-loading'),
- ).not.toBeNull();
+ expect(component.$el.querySelector('.board-list-loading')).not.toBeNull();
done();
});
});
it('renders issues', () => {
- expect(
- component.$el.querySelectorAll('.board-card').length,
- ).toBe(1);
+ expect(component.$el.querySelectorAll('.board-card').length).toBe(1);
});
it('sets data attribute with issue id', () => {
- expect(
- component.$el.querySelector('.board-card').getAttribute('data-issue-id'),
- ).toBe('1');
+ expect(component.$el.querySelector('.board-card').getAttribute('data-issue-id')).toBe('1');
});
- it('shows new issue form', (done) => {
+ it('shows new issue form', done => {
component.toggleForm();
Vue.nextTick(() => {
- expect(
- component.$el.querySelector('.board-new-issue-form'),
- ).not.toBeNull();
+ expect(component.$el.querySelector('.board-new-issue-form')).not.toBeNull();
- expect(
- component.$el.querySelector('.is-smaller'),
- ).not.toBeNull();
+ expect(component.$el.querySelector('.is-smaller')).not.toBeNull();
done();
});
});
- it('shows new issue form after eventhub event', (done) => {
+ it('shows new issue form after eventhub event', done => {
eventHub.$emit(`hide-issue-form-${component.list.id}`);
Vue.nextTick(() => {
- expect(
- component.$el.querySelector('.board-new-issue-form'),
- ).not.toBeNull();
+ expect(component.$el.querySelector('.board-new-issue-form')).not.toBeNull();
- expect(
- component.$el.querySelector('.is-smaller'),
- ).not.toBeNull();
+ expect(component.$el.querySelector('.is-smaller')).not.toBeNull();
done();
});
});
- it('does not show new issue form for closed list', (done) => {
+ it('does not show new issue form for closed list', done => {
component.list.type = 'closed';
component.toggleForm();
Vue.nextTick(() => {
- expect(
- component.$el.querySelector('.board-new-issue-form'),
- ).toBeNull();
+ expect(component.$el.querySelector('.board-new-issue-form')).toBeNull();
done();
});
});
- it('shows count list item', (done) => {
+ it('shows count list item', done => {
component.showCount = true;
Vue.nextTick(() => {
- expect(
- component.$el.querySelector('.board-list-count'),
- ).not.toBeNull();
+ expect(component.$el.querySelector('.board-list-count')).not.toBeNull();
- expect(
- component.$el.querySelector('.board-list-count').textContent.trim(),
- ).toBe('Showing all issues');
+ expect(component.$el.querySelector('.board-list-count').textContent.trim()).toBe(
+ 'Showing all issues',
+ );
done();
});
});
- it('sets data attribute with invalid id', (done) => {
+ it('sets data attribute with invalid id', done => {
component.showCount = true;
Vue.nextTick(() => {
- expect(
- component.$el.querySelector('.board-list-count').getAttribute('data-issue-id'),
- ).toBe('-1');
+ expect(component.$el.querySelector('.board-list-count').getAttribute('data-issue-id')).toBe(
+ '-1',
+ );
done();
});
});
- it('shows how many more issues to load', (done) => {
+ it('shows how many more issues to load', done => {
component.showCount = true;
component.list.issuesSize = 20;
Vue.nextTick(() => {
- expect(
- component.$el.querySelector('.board-list-count').textContent.trim(),
- ).toBe('Showing 1 of 20 issues');
+ expect(component.$el.querySelector('.board-list-count').textContent.trim()).toBe(
+ 'Showing 1 of 20 issues',
+ );
done();
});
});
- it('loads more issues after scrolling', (done) => {
+ it('loads more issues after scrolling', done => {
spyOn(component.list, 'nextPage');
component.$refs.list.style.height = '100px';
component.$refs.list.style.overflow = 'scroll';
@@ -201,7 +180,9 @@ describe('Board list component', () => {
});
it('does not load issues if already loading', () => {
- component.list.nextPage = spyOn(component.list, 'nextPage').and.returnValue(new Promise(() => {}));
+ component.list.nextPage = spyOn(component.list, 'nextPage').and.returnValue(
+ new Promise(() => {}),
+ );
component.onScroll();
component.onScroll();
@@ -209,14 +190,12 @@ describe('Board list component', () => {
expect(component.list.nextPage).toHaveBeenCalledTimes(1);
});
- it('shows loading more spinner', (done) => {
+ it('shows loading more spinner', done => {
component.showCount = true;
component.list.loadingMore = true;
Vue.nextTick(() => {
- expect(
- component.$el.querySelector('.board-list-count .fa-spinner'),
- ).not.toBeNull();
+ expect(component.$el.querySelector('.board-list-count .fa-spinner')).not.toBeNull();
done();
});
diff --git a/spec/javascripts/boards/board_new_issue_spec.js b/spec/javascripts/boards/board_new_issue_spec.js
index ee37821ad08..721d0b8172d 100644
--- a/spec/javascripts/boards/board_new_issue_spec.js
+++ b/spec/javascripts/boards/board_new_issue_spec.js
@@ -4,6 +4,7 @@ import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import boardNewIssue from '~/boards/components/board_new_issue.vue';
+import boardsStore from '~/boards/stores/boards_store';
import '~/boards/models/list';
import { listObj, boardsMockInterceptor, mockBoardService } from './mock_data';
@@ -27,7 +28,7 @@ describe('Issue boards new issue form', () => {
return vm.submit(dummySubmitEvent);
};
- beforeEach((done) => {
+ beforeEach(done => {
setFixtures('<div class="test-container"></div>');
const BoardNewIssueComp = Vue.extend(boardNewIssue);
@@ -36,8 +37,7 @@ describe('Issue boards new issue form', () => {
mock.onAny().reply(boardsMockInterceptor);
gl.boardService = mockBoardService();
- gl.issueBoards.BoardsStore.create();
- gl.IssueBoardsApp = new Vue();
+ boardsStore.create();
list = new List(listObj);
@@ -60,7 +60,7 @@ describe('Issue boards new issue form', () => {
mock.restore();
});
- it('calls submit if submit button is clicked', (done) => {
+ it('calls submit if submit button is clicked', done => {
spyOn(vm, 'submit').and.callFake(e => e.preventDefault());
vm.title = 'Testing Title';
@@ -69,7 +69,6 @@ describe('Issue boards new issue form', () => {
vm.$el.querySelector('.btn-success').click();
expect(vm.submit.calls.count()).toBe(1);
- expect(vm.$refs['submit-button']).toBe(vm.$el.querySelector('.btn-success'));
})
.then(done)
.catch(done.fail);
@@ -79,7 +78,7 @@ describe('Issue boards new issue form', () => {
expect(vm.$el.querySelector('.btn-success').disabled).toBe(true);
});
- it('enables submit button if title is not empty', (done) => {
+ it('enables submit button if title is not empty', done => {
vm.title = 'Testing Title';
Vue.nextTick()
@@ -91,7 +90,7 @@ describe('Issue boards new issue form', () => {
.catch(done.fail);
});
- it('clears title after clicking cancel', (done) => {
+ it('clears title after clicking cancel', done => {
vm.$el.querySelector('.btn-default').click();
Vue.nextTick()
@@ -102,7 +101,7 @@ describe('Issue boards new issue form', () => {
.catch(done.fail);
});
- it('does not create new issue if title is empty', (done) => {
+ it('does not create new issue if title is empty', done => {
submitIssue()
.then(() => {
expect(list.newIssue).not.toHaveBeenCalled();
@@ -112,7 +111,7 @@ describe('Issue boards new issue form', () => {
});
describe('submit success', () => {
- it('creates new issue', (done) => {
+ it('creates new issue', done => {
vm.title = 'submit title';
Vue.nextTick()
@@ -124,7 +123,7 @@ describe('Issue boards new issue form', () => {
.catch(done.fail);
});
- it('enables button after submit', (done) => {
+ it('enables button after submit', done => {
vm.title = 'submit issue';
Vue.nextTick()
@@ -136,7 +135,7 @@ describe('Issue boards new issue form', () => {
.catch(done.fail);
});
- it('clears title after submit', (done) => {
+ it('clears title after submit', done => {
vm.title = 'submit issue';
Vue.nextTick()
@@ -148,26 +147,26 @@ describe('Issue boards new issue form', () => {
.catch(done.fail);
});
- it('sets detail issue after submit', (done) => {
- expect(gl.issueBoards.BoardsStore.detail.issue.title).toBe(undefined);
+ it('sets detail issue after submit', done => {
+ expect(boardsStore.detail.issue.title).toBe(undefined);
vm.title = 'submit issue';
Vue.nextTick()
.then(submitIssue)
.then(() => {
- expect(gl.issueBoards.BoardsStore.detail.issue.title).toBe('submit issue');
+ expect(boardsStore.detail.issue.title).toBe('submit issue');
})
.then(done)
.catch(done.fail);
});
- it('sets detail list after submit', (done) => {
+ it('sets detail list after submit', done => {
vm.title = 'submit issue';
Vue.nextTick()
.then(submitIssue)
.then(() => {
- expect(gl.issueBoards.BoardsStore.detail.list.id).toBe(list.id);
+ expect(boardsStore.detail.list.id).toBe(list.id);
})
.then(done)
.catch(done.fail);
@@ -180,7 +179,7 @@ describe('Issue boards new issue form', () => {
vm.title = 'error';
});
- it('removes issue', (done) => {
+ it('removes issue', done => {
Vue.nextTick()
.then(submitIssue)
.then(() => {
@@ -190,7 +189,7 @@ describe('Issue boards new issue form', () => {
.catch(done.fail);
});
- it('shows error', (done) => {
+ it('shows error', done => {
Vue.nextTick()
.then(submitIssue)
.then(() => {
diff --git a/spec/javascripts/boards/boards_store_spec.js b/spec/javascripts/boards/boards_store_spec.js
index 1ee6f4cf680..54f1edfb1f9 100644
--- a/spec/javascripts/boards/boards_store_spec.js
+++ b/spec/javascripts/boards/boards_store_spec.js
@@ -1,4 +1,4 @@
-/* eslint-disable comma-dangle, no-unused-vars */
+/* eslint-disable no-unused-vars */
/* global ListIssue */
import Vue from 'vue';
@@ -11,7 +11,7 @@ import '~/vue_shared/models/assignee';
import '~/boards/models/issue';
import '~/boards/models/list';
import '~/boards/services/board_service';
-import '~/boards/stores/boards_store';
+import boardsStore from '~/boards/stores/boards_store';
import { listObj, listObjDuplicate, boardsMockInterceptor, mockBoardService } from './mock_data';
describe('Store', () => {
@@ -21,15 +21,18 @@ describe('Store', () => {
mock = new MockAdapter(axios);
mock.onAny().reply(boardsMockInterceptor);
gl.boardService = mockBoardService();
- gl.issueBoards.BoardsStore.create();
+ boardsStore.create();
- spyOn(gl.boardService, 'moveIssue').and.callFake(() => new Promise((resolve) => {
- resolve();
- }));
+ spyOn(gl.boardService, 'moveIssue').and.callFake(
+ () =>
+ new Promise(resolve => {
+ resolve();
+ }),
+ );
Cookies.set('issue_board_welcome_hidden', 'false', {
expires: 365 * 10,
- path: ''
+ path: '',
});
});
@@ -38,35 +41,35 @@ describe('Store', () => {
});
it('starts with a blank state', () => {
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(0);
+ expect(boardsStore.state.lists.length).toBe(0);
});
describe('lists', () => {
it('creates new list without persisting to DB', () => {
- gl.issueBoards.BoardsStore.addList(listObj);
+ boardsStore.addList(listObj);
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1);
+ expect(boardsStore.state.lists.length).toBe(1);
});
it('finds list by ID', () => {
- gl.issueBoards.BoardsStore.addList(listObj);
- const list = gl.issueBoards.BoardsStore.findList('id', listObj.id);
+ boardsStore.addList(listObj);
+ const list = boardsStore.findList('id', listObj.id);
expect(list.id).toBe(listObj.id);
});
it('finds list by type', () => {
- gl.issueBoards.BoardsStore.addList(listObj);
- const list = gl.issueBoards.BoardsStore.findList('type', 'label');
+ boardsStore.addList(listObj);
+ const list = boardsStore.findList('type', 'label');
expect(list).toBeDefined();
});
- it('gets issue when new list added', (done) => {
- gl.issueBoards.BoardsStore.addList(listObj);
- const list = gl.issueBoards.BoardsStore.findList('id', listObj.id);
+ it('gets issue when new list added', done => {
+ boardsStore.addList(listObj);
+ const list = boardsStore.findList('id', listObj.id);
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1);
+ expect(boardsStore.state.lists.length).toBe(1);
setTimeout(() => {
expect(list.issues.length).toBe(1);
@@ -75,21 +78,23 @@ describe('Store', () => {
}, 0);
});
- it('persists new list', (done) => {
- gl.issueBoards.BoardsStore.new({
+ it('persists new list', done => {
+ boardsStore.new({
title: 'Test',
list_type: 'label',
label: {
id: 1,
title: 'Testing',
color: 'red',
- description: 'testing;'
- }
+ description: 'testing;',
+ },
});
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1);
+
+ expect(boardsStore.state.lists.length).toBe(1);
setTimeout(() => {
- const list = gl.issueBoards.BoardsStore.findList('id', listObj.id);
+ const list = boardsStore.findList('id', listObj.id);
+
expect(list).toBeDefined();
expect(list.id).toBe(listObj.id);
expect(list.position).toBe(0);
@@ -98,61 +103,63 @@ describe('Store', () => {
});
it('check for blank state adding', () => {
- expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(true);
+ expect(boardsStore.shouldAddBlankState()).toBe(true);
});
it('check for blank state not adding', () => {
- gl.issueBoards.BoardsStore.addList(listObj);
- expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(false);
+ boardsStore.addList(listObj);
+
+ expect(boardsStore.shouldAddBlankState()).toBe(false);
});
it('check for blank state adding when closed list exist', () => {
- gl.issueBoards.BoardsStore.addList({
- list_type: 'closed'
+ boardsStore.addList({
+ list_type: 'closed',
});
- expect(gl.issueBoards.BoardsStore.shouldAddBlankState()).toBe(true);
+ expect(boardsStore.shouldAddBlankState()).toBe(true);
});
it('adds the blank state', () => {
- gl.issueBoards.BoardsStore.addBlankState();
+ boardsStore.addBlankState();
+
+ const list = boardsStore.findList('type', 'blank', 'blank');
- const list = gl.issueBoards.BoardsStore.findList('type', 'blank', 'blank');
expect(list).toBeDefined();
});
it('removes list from state', () => {
- gl.issueBoards.BoardsStore.addList(listObj);
+ boardsStore.addList(listObj);
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1);
+ expect(boardsStore.state.lists.length).toBe(1);
- gl.issueBoards.BoardsStore.removeList(listObj.id, 'label');
+ boardsStore.removeList(listObj.id, 'label');
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(0);
+ expect(boardsStore.state.lists.length).toBe(0);
});
it('moves the position of lists', () => {
- const listOne = gl.issueBoards.BoardsStore.addList(listObj);
- const listTwo = gl.issueBoards.BoardsStore.addList(listObjDuplicate);
+ const listOne = boardsStore.addList(listObj);
+ const listTwo = boardsStore.addList(listObjDuplicate);
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2);
+ expect(boardsStore.state.lists.length).toBe(2);
- gl.issueBoards.BoardsStore.moveList(listOne, [listObjDuplicate.id, listObj.id]);
+ boardsStore.moveList(listOne, [listObjDuplicate.id, listObj.id]);
expect(listOne.position).toBe(1);
});
- it('moves an issue from one list to another', (done) => {
- const listOne = gl.issueBoards.BoardsStore.addList(listObj);
- const listTwo = gl.issueBoards.BoardsStore.addList(listObjDuplicate);
+ it('moves an issue from one list to another', done => {
+ const listOne = boardsStore.addList(listObj);
+ const listTwo = boardsStore.addList(listObjDuplicate);
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2);
+ expect(boardsStore.state.lists.length).toBe(2);
setTimeout(() => {
expect(listOne.issues.length).toBe(1);
expect(listTwo.issues.length).toBe(1);
- gl.issueBoards.BoardsStore.moveIssueToList(listOne, listTwo, listOne.findIssue(1));
+ boardsStore.moveIssueToList(listOne, listTwo, listOne.findIssue(1));
expect(listOne.issues.length).toBe(0);
expect(listTwo.issues.length).toBe(1);
@@ -161,20 +168,20 @@ describe('Store', () => {
}, 0);
});
- it('moves an issue from backlog to a list', (done) => {
- const backlog = gl.issueBoards.BoardsStore.addList({
+ it('moves an issue from backlog to a list', done => {
+ const backlog = boardsStore.addList({
...listObj,
list_type: 'backlog',
});
- const listTwo = gl.issueBoards.BoardsStore.addList(listObjDuplicate);
+ const listTwo = boardsStore.addList(listObjDuplicate);
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2);
+ expect(boardsStore.state.lists.length).toBe(2);
setTimeout(() => {
expect(backlog.issues.length).toBe(1);
expect(listTwo.issues.length).toBe(1);
- gl.issueBoards.BoardsStore.moveIssueToList(backlog, listTwo, backlog.findIssue(1));
+ boardsStore.moveIssueToList(backlog, listTwo, backlog.findIssue(1));
expect(backlog.issues.length).toBe(0);
expect(listTwo.issues.length).toBe(1);
@@ -183,11 +190,11 @@ describe('Store', () => {
}, 0);
});
- it('moves issue to top of another list', (done) => {
- const listOne = gl.issueBoards.BoardsStore.addList(listObj);
- const listTwo = gl.issueBoards.BoardsStore.addList(listObjDuplicate);
+ it('moves issue to top of another list', done => {
+ const listOne = boardsStore.addList(listObj);
+ const listTwo = boardsStore.addList(listObjDuplicate);
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2);
+ expect(boardsStore.state.lists.length).toBe(2);
setTimeout(() => {
listOne.issues[0].id = 2;
@@ -195,7 +202,7 @@ describe('Store', () => {
expect(listOne.issues.length).toBe(1);
expect(listTwo.issues.length).toBe(1);
- gl.issueBoards.BoardsStore.moveIssueToList(listOne, listTwo, listOne.findIssue(2), 0);
+ boardsStore.moveIssueToList(listOne, listTwo, listOne.findIssue(2), 0);
expect(listOne.issues.length).toBe(0);
expect(listTwo.issues.length).toBe(2);
@@ -206,11 +213,11 @@ describe('Store', () => {
}, 0);
});
- it('moves issue to bottom of another list', (done) => {
- const listOne = gl.issueBoards.BoardsStore.addList(listObj);
- const listTwo = gl.issueBoards.BoardsStore.addList(listObjDuplicate);
+ it('moves issue to bottom of another list', done => {
+ const listOne = boardsStore.addList(listObj);
+ const listTwo = boardsStore.addList(listObjDuplicate);
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(2);
+ expect(boardsStore.state.lists.length).toBe(2);
setTimeout(() => {
listOne.issues[0].id = 2;
@@ -218,7 +225,7 @@ describe('Store', () => {
expect(listOne.issues.length).toBe(1);
expect(listTwo.issues.length).toBe(1);
- gl.issueBoards.BoardsStore.moveIssueToList(listOne, listTwo, listOne.findIssue(2), 1);
+ boardsStore.moveIssueToList(listOne, listTwo, listOne.findIssue(2), 1);
expect(listOne.issues.length).toBe(0);
expect(listTwo.issues.length).toBe(2);
@@ -229,7 +236,7 @@ describe('Store', () => {
}, 0);
});
- it('moves issue in list', (done) => {
+ it('moves issue in list', done => {
const issue = new ListIssue({
title: 'Testing',
id: 2,
@@ -238,14 +245,14 @@ describe('Store', () => {
labels: [],
assignees: [],
});
- const list = gl.issueBoards.BoardsStore.addList(listObj);
+ const list = boardsStore.addList(listObj);
setTimeout(() => {
list.addIssue(issue);
expect(list.issues.length).toBe(2);
- gl.issueBoards.BoardsStore.moveIssueInList(list, issue, 0, 1, [1, 2]);
+ boardsStore.moveIssueInList(list, issue, 0, 1, [1, 2]);
expect(list.issues[0].id).toBe(2);
expect(gl.boardService.moveIssue).toHaveBeenCalledWith(2, null, null, 1, null);
diff --git a/spec/javascripts/boards/components/board_spec.js b/spec/javascripts/boards/components/board_spec.js
index 19346e305cf..dee7841c088 100644
--- a/spec/javascripts/boards/components/board_spec.js
+++ b/spec/javascripts/boards/components/board_spec.js
@@ -1,6 +1,6 @@
import Vue from 'vue';
import '~/boards/services/board_service';
-import '~/boards/components/board';
+import Board from '~/boards/components/board';
import '~/boards/models/list';
import { mockBoardService } from '../mock_data';
@@ -8,7 +8,7 @@ describe('Board component', () => {
let vm;
let el;
- beforeEach((done) => {
+ beforeEach(done => {
loadFixtures('boards/show.html.raw');
el = document.createElement('div');
@@ -21,7 +21,7 @@ describe('Board component', () => {
boardId: 1,
});
- vm = new gl.issueBoards.Board({
+ vm = new Board({
propsData: {
boardId: '1',
disabled: false,
@@ -50,56 +50,46 @@ describe('Board component', () => {
});
it('board is expandable when list type is backlog', () => {
- expect(
- vm.$el.classList.contains('is-expandable'),
- ).toBe(true);
+ expect(vm.$el.classList.contains('is-expandable')).toBe(true);
});
- it('board is expandable when list type is closed', (done) => {
+ it('board is expandable when list type is closed', done => {
vm.list.type = 'closed';
Vue.nextTick(() => {
- expect(
- vm.$el.classList.contains('is-expandable'),
- ).toBe(true);
+ expect(vm.$el.classList.contains('is-expandable')).toBe(true);
done();
});
});
- it('board is not expandable when list type is label', (done) => {
+ it('board is not expandable when list type is label', done => {
vm.list.type = 'label';
vm.list.isExpandable = false;
Vue.nextTick(() => {
- expect(
- vm.$el.classList.contains('is-expandable'),
- ).toBe(false);
+ expect(vm.$el.classList.contains('is-expandable')).toBe(false);
done();
});
});
- it('collapses when clicking header', (done) => {
+ it('collapses when clicking header', done => {
vm.$el.querySelector('.board-header').click();
Vue.nextTick(() => {
- expect(
- vm.$el.classList.contains('is-collapsed'),
- ).toBe(true);
+ expect(vm.$el.classList.contains('is-collapsed')).toBe(true);
done();
});
});
- it('created sets isExpanded to true from localStorage', (done) => {
+ it('created sets isExpanded to true from localStorage', done => {
vm.$el.querySelector('.board-header').click();
return Vue.nextTick()
.then(() => {
- expect(
- vm.$el.classList.contains('is-collapsed'),
- ).toBe(true);
+ expect(vm.$el.classList.contains('is-collapsed')).toBe(true);
// call created manually
vm.$options.created[0].call(vm);
@@ -107,11 +97,10 @@ describe('Board component', () => {
return Vue.nextTick();
})
.then(() => {
- expect(
- vm.$el.classList.contains('is-collapsed'),
- ).toBe(true);
+ expect(vm.$el.classList.contains('is-collapsed')).toBe(true);
done();
- });
+ })
+ .catch(done.fail);
});
});
diff --git a/spec/javascripts/boards/components/issue_due_date_spec.js b/spec/javascripts/boards/components/issue_due_date_spec.js
new file mode 100644
index 00000000000..9e49330c052
--- /dev/null
+++ b/spec/javascripts/boards/components/issue_due_date_spec.js
@@ -0,0 +1,64 @@
+import Vue from 'vue';
+import dateFormat from 'dateformat';
+import IssueDueDate from '~/boards/components/issue_due_date.vue';
+import mountComponent from '../../helpers/vue_mount_component_helper';
+
+describe('Issue Due Date component', () => {
+ let vm;
+ let date;
+ const Component = Vue.extend(IssueDueDate);
+ const createComponent = (dueDate = new Date()) =>
+ mountComponent(Component, { date: dateFormat(dueDate, 'yyyy-mm-dd', true) });
+
+ beforeEach(() => {
+ date = new Date();
+ vm = createComponent();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('should render "Today" if the due date is today', () => {
+ const timeContainer = vm.$el.querySelector('time');
+
+ expect(timeContainer.textContent.trim()).toEqual('Today');
+ });
+
+ it('should render "Yesterday" if the due date is yesterday', () => {
+ date.setDate(date.getDate() - 1);
+ vm = createComponent(date);
+
+ expect(vm.$el.querySelector('time').textContent.trim()).toEqual('Yesterday');
+ });
+
+ it('should render "Tomorrow" if the due date is one day from now', () => {
+ date.setDate(date.getDate() + 1);
+ vm = createComponent(date);
+
+ expect(vm.$el.querySelector('time').textContent.trim()).toEqual('Tomorrow');
+ });
+
+ it('should render day of the week if due date is one week away', () => {
+ date.setDate(date.getDate() + 5);
+ vm = createComponent(date);
+
+ expect(vm.$el.querySelector('time').textContent.trim()).toEqual(dateFormat(date, 'dddd', true));
+ });
+
+ it('should render month and day for other dates', () => {
+ date.setDate(date.getDate() + 17);
+ vm = createComponent(date);
+
+ expect(vm.$el.querySelector('time').textContent.trim()).toEqual(
+ dateFormat(date, 'mmm d', true),
+ );
+ });
+
+ it('should contain the correct `.text-danger` css class for overdue issue', () => {
+ date.setDate(date.getDate() - 17);
+ vm = createComponent(date);
+
+ expect(vm.$el.querySelector('time').classList.contains('text-danger')).toEqual(true);
+ });
+});
diff --git a/spec/javascripts/boards/components/issue_time_estimate_spec.js b/spec/javascripts/boards/components/issue_time_estimate_spec.js
new file mode 100644
index 00000000000..ba65d3287da
--- /dev/null
+++ b/spec/javascripts/boards/components/issue_time_estimate_spec.js
@@ -0,0 +1,40 @@
+import Vue from 'vue';
+import IssueTimeEstimate from '~/boards/components/issue_time_estimate.vue';
+import mountComponent from '../../helpers/vue_mount_component_helper';
+
+describe('Issue Tine Estimate component', () => {
+ let vm;
+
+ beforeEach(() => {
+ const Component = Vue.extend(IssueTimeEstimate);
+ vm = mountComponent(Component, {
+ estimate: 374460,
+ });
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders the correct time estimate', () => {
+ expect(vm.$el.querySelector('time').textContent.trim()).toEqual('2w 3d 1m');
+ });
+
+ it('renders expanded time estimate in tooltip', () => {
+ expect(vm.$el.querySelector('.js-issue-time-estimate').textContent).toContain(
+ '2 weeks 3 days 1 minute',
+ );
+ });
+
+ it('prevents tooltip xss', done => {
+ const alertSpy = spyOn(window, 'alert');
+ vm.estimate = 'Foo <script>alert("XSS")</script>';
+
+ vm.$nextTick(() => {
+ expect(alertSpy).not.toHaveBeenCalled();
+ expect(vm.$el.querySelector('time').textContent.trim()).toEqual('0m');
+ expect(vm.$el.querySelector('.js-issue-time-estimate').textContent).toContain('0m');
+ done();
+ });
+ });
+});
diff --git a/spec/javascripts/boards/issue_card_spec.js b/spec/javascripts/boards/issue_card_spec.js
index b6c61e7bad7..6eda5047dd0 100644
--- a/spec/javascripts/boards/issue_card_spec.js
+++ b/spec/javascripts/boards/issue_card_spec.js
@@ -8,7 +8,6 @@ import '~/vue_shared/models/label';
import '~/vue_shared/models/assignee';
import '~/boards/models/issue';
import '~/boards/models/list';
-import '~/boards/stores/boards_store';
import IssueCardInner from '~/boards/components/issue_card_inner.vue';
import { listObj } from './mock_data';
@@ -118,11 +117,9 @@ describe('Issue card component', () => {
});
it('sets title', () => {
- expect(
- component.$el
- .querySelector('.board-card-assignee img')
- .getAttribute('data-original-title'),
- ).toContain(`Assigned to ${user.name}`);
+ expect(component.$el.querySelector('.js-assignee-tooltip').textContent).toContain(
+ `${user.name}`,
+ );
});
it('sets users path', () => {
@@ -155,7 +152,7 @@ describe('Issue card component', () => {
it('displays defaults avatar if users avatar is null', () => {
expect(component.$el.querySelector('.board-card-assignee img')).not.toBeNull();
expect(component.$el.querySelector('.board-card-assignee img').getAttribute('src')).toBe(
- 'default_avatar?width=20',
+ 'default_avatar?width=24',
);
});
});
@@ -164,7 +161,6 @@ describe('Issue card component', () => {
describe('multiple assignees', () => {
beforeEach(done => {
component.issue.assignees = [
- user,
new ListAssignee({
id: 2,
name: 'user2',
@@ -188,11 +184,11 @@ describe('Issue card component', () => {
Vue.nextTick(() => done());
});
- it('renders all four assignees', () => {
- expect(component.$el.querySelectorAll('.board-card-assignee .avatar').length).toEqual(4);
+ it('renders all three assignees', () => {
+ expect(component.$el.querySelectorAll('.board-card-assignee .avatar').length).toEqual(3);
});
- describe('more than four assignees', () => {
+ describe('more than three assignees', () => {
beforeEach(done => {
component.issue.assignees.push(
new ListAssignee({
@@ -208,12 +204,12 @@ describe('Issue card component', () => {
it('renders more avatar counter', () => {
expect(
- component.$el.querySelector('.board-card-assignee .avatar-counter').innerText,
+ component.$el.querySelector('.board-card-assignee .avatar-counter').innerText.trim(),
).toEqual('+2');
});
- it('renders three assignees', () => {
- expect(component.$el.querySelectorAll('.board-card-assignee .avatar').length).toEqual(3);
+ it('renders two assignees', () => {
+ expect(component.$el.querySelectorAll('.board-card-assignee .avatar').length).toEqual(2);
});
it('renders 99+ avatar counter', done => {
@@ -229,7 +225,7 @@ describe('Issue card component', () => {
Vue.nextTick(() => {
expect(
- component.$el.querySelector('.board-card-assignee .avatar-counter').innerText,
+ component.$el.querySelector('.board-card-assignee .avatar-counter').innerText.trim(),
).toEqual('99+');
done();
});
diff --git a/spec/javascripts/boards/issue_spec.js b/spec/javascripts/boards/issue_spec.js
index db68096e3bd..437ab4bb3df 100644
--- a/spec/javascripts/boards/issue_spec.js
+++ b/spec/javascripts/boards/issue_spec.js
@@ -1,4 +1,3 @@
-/* eslint-disable comma-dangle */
/* global ListIssue */
import Vue from 'vue';
@@ -7,7 +6,7 @@ import '~/vue_shared/models/assignee';
import '~/boards/models/issue';
import '~/boards/models/list';
import '~/boards/services/board_service';
-import '~/boards/stores/boards_store';
+import boardsStore from '~/boards/stores/boards_store';
import { mockBoardService } from './mock_data';
describe('Issue model', () => {
@@ -15,25 +14,29 @@ describe('Issue model', () => {
beforeEach(() => {
gl.boardService = mockBoardService();
- gl.issueBoards.BoardsStore.create();
+ boardsStore.create();
issue = new ListIssue({
title: 'Testing',
id: 1,
iid: 1,
confidential: false,
- labels: [{
- id: 1,
- title: 'test',
- color: 'red',
- description: 'testing'
- }],
- assignees: [{
- id: 1,
- name: 'name',
- username: 'username',
- avatar_url: 'http://avatar_url',
- }],
+ labels: [
+ {
+ id: 1,
+ title: 'test',
+ color: 'red',
+ description: 'testing',
+ },
+ ],
+ assignees: [
+ {
+ id: 1,
+ name: 'name',
+ username: 'username',
+ avatar_url: 'http://avatar_url',
+ },
+ ],
});
});
@@ -46,8 +49,9 @@ describe('Issue model', () => {
id: 2,
title: 'bug',
color: 'blue',
- description: 'bugs!'
+ description: 'bugs!',
});
+
expect(issue.labels.length).toBe(2);
});
@@ -56,7 +60,7 @@ describe('Issue model', () => {
id: 2,
title: 'test',
color: 'blue',
- description: 'bugs!'
+ description: 'bugs!',
});
expect(issue.labels.length).toBe(1);
@@ -64,12 +68,14 @@ describe('Issue model', () => {
it('finds label', () => {
const label = issue.findLabel(issue.labels[0]);
+
expect(label).toBeDefined();
});
it('removes label', () => {
const label = issue.findLabel(issue.labels[0]);
issue.removeLabel(label);
+
expect(issue.labels.length).toBe(0);
});
@@ -78,11 +84,13 @@ describe('Issue model', () => {
id: 2,
title: 'bug',
color: 'blue',
- description: 'bugs!'
+ description: 'bugs!',
});
+
expect(issue.labels.length).toBe(2);
issue.removeLabels([issue.labels[0], issue.labels[1]]);
+
expect(issue.labels.length).toBe(0);
});
@@ -99,17 +107,20 @@ describe('Issue model', () => {
it('finds assignee', () => {
const assignee = issue.findAssignee(issue.assignees[0]);
+
expect(assignee).toBeDefined();
});
it('removes assignee', () => {
const assignee = issue.findAssignee(issue.assignees[0]);
issue.removeAssignee(assignee);
+
expect(issue.assignees.length).toBe(0);
});
it('removes all assignees', () => {
issue.removeAllAssignees();
+
expect(issue.assignees.length).toBe(0);
});
@@ -132,6 +143,7 @@ describe('Issue model', () => {
it('updates data', () => {
issue.updateData({ subscribed: true });
+
expect(issue.subscribed).toBe(true);
});
@@ -150,7 +162,7 @@ describe('Issue model', () => {
});
describe('update', () => {
- it('passes assignee ids when there are assignees', (done) => {
+ it('passes assignee ids when there are assignees', done => {
spyOn(Vue.http, 'patch').and.callFake((url, data) => {
expect(data.issue.assignee_ids).toEqual([1]);
done();
@@ -159,7 +171,7 @@ describe('Issue model', () => {
issue.update('url');
});
- it('passes assignee ids of [0] when there are no assignees', (done) => {
+ it('passes assignee ids of [0] when there are no assignees', done => {
spyOn(Vue.http, 'patch').and.callFake((url, data) => {
expect(data.issue.assignee_ids).toEqual([0]);
done();
diff --git a/spec/javascripts/boards/list_spec.js b/spec/javascripts/boards/list_spec.js
index ac8bbb8f2a8..0d462a6f872 100644
--- a/spec/javascripts/boards/list_spec.js
+++ b/spec/javascripts/boards/list_spec.js
@@ -1,4 +1,3 @@
-/* eslint-disable comma-dangle */
/* global List */
/* global ListIssue */
@@ -10,7 +9,7 @@ import '~/vue_shared/models/assignee';
import '~/boards/models/issue';
import '~/boards/models/list';
import '~/boards/services/board_service';
-import '~/boards/stores/boards_store';
+import boardsStore from '~/boards/stores/boards_store';
import { listObj, listObjDuplicate, boardsMockInterceptor, mockBoardService } from './mock_data';
describe('List model', () => {
@@ -23,7 +22,7 @@ describe('List model', () => {
gl.boardService = mockBoardService({
bulkUpdatePath: '/test/issue-boards/board/1/lists',
});
- gl.issueBoards.BoardsStore.create();
+ boardsStore.create();
list = new List(listObj);
});
@@ -32,21 +31,21 @@ describe('List model', () => {
mock.restore();
});
- it('gets issues when created', (done) => {
+ it('gets issues when created', done => {
setTimeout(() => {
expect(list.issues.length).toBe(1);
done();
}, 0);
});
- it('saves list and returns ID', (done) => {
+ it('saves list and returns ID', done => {
list = new List({
title: 'test',
label: {
id: _.random(10000),
title: 'test',
- color: 'red'
- }
+ color: 'red',
+ },
});
list.save();
@@ -58,31 +57,35 @@ describe('List model', () => {
}, 0);
});
- it('destroys the list', (done) => {
- gl.issueBoards.BoardsStore.addList(listObj);
- list = gl.issueBoards.BoardsStore.findList('id', listObj.id);
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(1);
+ it('destroys the list', done => {
+ boardsStore.addList(listObj);
+ list = boardsStore.findList('id', listObj.id);
+
+ expect(boardsStore.state.lists.length).toBe(1);
list.destroy();
setTimeout(() => {
- expect(gl.issueBoards.BoardsStore.state.lists.length).toBe(0);
+ expect(boardsStore.state.lists.length).toBe(0);
done();
}, 0);
});
- it('gets issue from list', (done) => {
+ it('gets issue from list', done => {
setTimeout(() => {
const issue = list.findIssue(1);
+
expect(issue).toBeDefined();
done();
}, 0);
});
- it('removes issue', (done) => {
+ it('removes issue', done => {
setTimeout(() => {
const issue = list.findIssue(1);
+
expect(list.issues.length).toBe(1);
list.removeIssue(issue);
+
expect(list.issues.length).toBe(0);
done();
}, 0);
@@ -106,8 +109,13 @@ describe('List model', () => {
listDup.updateIssueLabel(issue, list);
- expect(gl.boardService.moveIssue)
- .toHaveBeenCalledWith(issue.id, list.id, listDup.id, undefined, undefined);
+ expect(gl.boardService.moveIssue).toHaveBeenCalledWith(
+ issue.id,
+ list.id,
+ listDup.id,
+ undefined,
+ undefined,
+ );
});
describe('page number', () => {
@@ -117,14 +125,16 @@ describe('List model', () => {
it('increase page number if current issue count is more than the page size', () => {
for (let i = 0; i < 30; i += 1) {
- list.issues.push(new ListIssue({
- title: 'Testing',
- id: _.random(10000) + i,
- iid: _.random(10000) + i,
- confidential: false,
- labels: [list.label],
- assignees: [],
- }));
+ list.issues.push(
+ new ListIssue({
+ title: 'Testing',
+ id: _.random(10000) + i,
+ iid: _.random(10000) + i,
+ confidential: false,
+ labels: [list.label],
+ assignees: [],
+ }),
+ );
}
list.issuesSize = 50;
@@ -137,13 +147,15 @@ describe('List model', () => {
});
it('does not increase page number if issue count is less than the page size', () => {
- list.issues.push(new ListIssue({
- title: 'Testing',
- id: _.random(10000),
- confidential: false,
- labels: [list.label],
- assignees: [],
- }));
+ list.issues.push(
+ new ListIssue({
+ title: 'Testing',
+ id: _.random(10000),
+ confidential: false,
+ labels: [list.label],
+ assignees: [],
+ }),
+ );
list.issuesSize = 2;
list.nextPage();
@@ -155,21 +167,25 @@ describe('List model', () => {
describe('newIssue', () => {
beforeEach(() => {
- spyOn(gl.boardService, 'newIssue').and.returnValue(Promise.resolve({
- data: {
- id: 42,
- },
- }));
+ spyOn(gl.boardService, 'newIssue').and.returnValue(
+ Promise.resolve({
+ data: {
+ id: 42,
+ },
+ }),
+ );
});
- it('adds new issue to top of list', (done) => {
- list.issues.push(new ListIssue({
- title: 'Testing',
- id: _.random(10000),
- confidential: false,
- labels: [list.label],
- assignees: [],
- }));
+ it('adds new issue to top of list', done => {
+ list.issues.push(
+ new ListIssue({
+ title: 'Testing',
+ id: _.random(10000),
+ confidential: false,
+ labels: [list.label],
+ assignees: [],
+ }),
+ );
const dummyIssue = new ListIssue({
title: 'new issue',
id: _.random(10000),
@@ -178,7 +194,8 @@ describe('List model', () => {
assignees: [],
});
- list.newIssue(dummyIssue)
+ list
+ .newIssue(dummyIssue)
.then(() => {
expect(list.issues.length).toBe(2);
expect(list.issues[0]).toBe(dummyIssue);
diff --git a/spec/javascripts/boards/mock_data.js b/spec/javascripts/boards/mock_data.js
index f380ef450db..c28e41ec175 100644
--- a/spec/javascripts/boards/mock_data.js
+++ b/spec/javascripts/boards/mock_data.js
@@ -1,4 +1,5 @@
-/* global BoardService */
+import BoardService from '~/boards/services/board_service';
+
export const listObj = {
id: 300,
position: 0,
diff --git a/spec/javascripts/bootstrap_jquery_spec.js b/spec/javascripts/bootstrap_jquery_spec.js
index 052465d8d88..35340a3bc42 100644
--- a/spec/javascripts/bootstrap_jquery_spec.js
+++ b/spec/javascripts/bootstrap_jquery_spec.js
@@ -3,41 +3,45 @@
import $ from 'jquery';
import '~/commons/bootstrap';
-(function() {
- describe('Bootstrap jQuery extensions', function() {
- describe('disable', function() {
- beforeEach(function() {
- return setFixtures('<input type="text" />');
- });
- it('adds the disabled attribute', function() {
- var $input;
- $input = $('input').first();
- $input.disable();
- return expect($input).toHaveAttr('disabled', 'disabled');
- });
- return it('adds the disabled class', function() {
- var $input;
- $input = $('input').first();
- $input.disable();
- return expect($input).toHaveClass('disabled');
- });
+describe('Bootstrap jQuery extensions', function() {
+ describe('disable', function() {
+ beforeEach(function() {
+ return setFixtures('<input type="text" />');
});
- return describe('enable', function() {
- beforeEach(function() {
- return setFixtures('<input type="text" disabled="disabled" class="disabled" />');
- });
- it('removes the disabled attribute', function() {
- var $input;
- $input = $('input').first();
- $input.enable();
- return expect($input).not.toHaveAttr('disabled');
- });
- return it('removes the disabled class', function() {
- var $input;
- $input = $('input').first();
- $input.enable();
- return expect($input).not.toHaveClass('disabled');
- });
+
+ it('adds the disabled attribute', function() {
+ var $input;
+ $input = $('input').first();
+ $input.disable();
+
+ expect($input).toHaveAttr('disabled', 'disabled');
+ });
+ return it('adds the disabled class', function() {
+ var $input;
+ $input = $('input').first();
+ $input.disable();
+
+ expect($input).toHaveClass('disabled');
+ });
+ });
+ return describe('enable', function() {
+ beforeEach(function() {
+ return setFixtures('<input type="text" disabled="disabled" class="disabled" />');
+ });
+
+ it('removes the disabled attribute', function() {
+ var $input;
+ $input = $('input').first();
+ $input.enable();
+
+ expect($input).not.toHaveAttr('disabled');
+ });
+ return it('removes the disabled class', function() {
+ var $input;
+ $input = $('input').first();
+ $input.enable();
+
+ expect($input).not.toHaveClass('disabled');
});
});
-}).call(window);
+});
diff --git a/spec/javascripts/bootstrap_linked_tabs_spec.js b/spec/javascripts/bootstrap_linked_tabs_spec.js
index 6f679369289..c3e3d78ff63 100644
--- a/spec/javascripts/bootstrap_linked_tabs_spec.js
+++ b/spec/javascripts/bootstrap_linked_tabs_spec.js
@@ -1,60 +1,67 @@
import LinkedTabs from '~/lib/utils/bootstrap_linked_tabs';
-(() => {
- describe('Linked Tabs', () => {
- preloadFixtures('static/linked_tabs.html.raw');
+describe('Linked Tabs', () => {
+ preloadFixtures('static/linked_tabs.html.raw');
+ beforeEach(() => {
+ loadFixtures('static/linked_tabs.html.raw');
+ });
+
+ describe('when is initialized', () => {
beforeEach(() => {
- loadFixtures('static/linked_tabs.html.raw');
+ spyOn(window.history, 'replaceState').and.callFake(function() {});
});
- describe('when is initialized', () => {
- beforeEach(() => {
- spyOn(window.history, 'replaceState').and.callFake(function () {});
+ it('should activate the tab correspondent to the given action', () => {
+ // eslint-disable-next-line no-new
+ new LinkedTabs({
+ action: 'tab1',
+ defaultAction: 'tab1',
+ parentEl: '.linked-tabs',
});
- it('should activate the tab correspondent to the given action', () => {
- const linkedTabs = new LinkedTabs({ // eslint-disable-line
- action: 'tab1',
- defaultAction: 'tab1',
- parentEl: '.linked-tabs',
- });
+ expect(document.querySelector('#tab1').classList).toContain('active');
+ });
- expect(document.querySelector('#tab1').classList).toContain('active');
+ it('should active the default tab action when the action is show', () => {
+ // eslint-disable-next-line no-new
+ new LinkedTabs({
+ action: 'show',
+ defaultAction: 'tab1',
+ parentEl: '.linked-tabs',
});
- it('should active the default tab action when the action is show', () => {
- const linkedTabs = new LinkedTabs({ // eslint-disable-line
- action: 'show',
- defaultAction: 'tab1',
- parentEl: '.linked-tabs',
- });
-
- expect(document.querySelector('#tab1').classList).toContain('active');
- });
+ expect(document.querySelector('#tab1').classList).toContain('active');
});
+ });
- describe('on click', () => {
- it('should change the url according to the clicked tab', () => {
- const historySpy = spyOn(window.history, 'replaceState').and.callFake(() => {});
+ describe('on click', () => {
+ it('should change the url according to the clicked tab', () => {
+ const historySpy = spyOn(window.history, 'replaceState').and.callFake(() => {});
- const linkedTabs = new LinkedTabs({
- action: 'show',
- defaultAction: 'tab1',
- parentEl: '.linked-tabs',
- });
+ const linkedTabs = new LinkedTabs({
+ action: 'show',
+ defaultAction: 'tab1',
+ parentEl: '.linked-tabs',
+ });
- const secondTab = document.querySelector('.linked-tabs li:nth-child(2) a');
- const newState = secondTab.getAttribute('href') + linkedTabs.currentLocation.search + linkedTabs.currentLocation.hash;
+ const secondTab = document.querySelector('.linked-tabs li:nth-child(2) a');
+ const newState =
+ secondTab.getAttribute('href') +
+ linkedTabs.currentLocation.search +
+ linkedTabs.currentLocation.hash;
- secondTab.click();
+ secondTab.click();
- if (historySpy) {
- expect(historySpy).toHaveBeenCalledWith({
+ if (historySpy) {
+ expect(historySpy).toHaveBeenCalledWith(
+ {
url: newState,
- }, document.title, newState);
- }
- });
+ },
+ document.title,
+ newState,
+ );
+ }
});
});
-})();
+});
diff --git a/spec/javascripts/breakpoints_spec.js b/spec/javascripts/breakpoints_spec.js
index b1b5d36c1fb..5ee777fee3f 100644
--- a/spec/javascripts/breakpoints_spec.js
+++ b/spec/javascripts/breakpoints_spec.js
@@ -1,9 +1,7 @@
-import bp, {
- breakpoints,
-} from '~/breakpoints';
+import bp, { breakpoints } from '~/breakpoints';
describe('breakpoints', () => {
- Object.keys(breakpoints).forEach((key) => {
+ Object.keys(breakpoints).forEach(key => {
const size = breakpoints[key];
it(`returns ${key} when larger than ${size}`, () => {
diff --git a/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js b/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js
index ee457a9c48c..1fc0e206d5e 100644
--- a/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js
+++ b/spec/javascripts/ci_variable_list/ajax_variable_list_spec.js
@@ -24,7 +24,7 @@ describe('AjaxFormVariableList', () => {
mock = new MockAdapter(axios);
const ajaxVariableListEl = document.querySelector('.js-ci-variable-list-section');
- saveButton = ajaxVariableListEl.querySelector('.js-secret-variables-save-button');
+ saveButton = ajaxVariableListEl.querySelector('.js-ci-variables-save-button');
errorBox = container.querySelector('.js-ci-variable-error-box');
ajaxVariableList = new AjaxFormVariableList({
container,
@@ -43,8 +43,8 @@ describe('AjaxFormVariableList', () => {
});
describe('onSaveClicked', () => {
- it('shows loading spinner while waiting for the request', (done) => {
- const loadingIcon = saveButton.querySelector('.js-secret-variables-save-loading-icon');
+ it('shows loading spinner while waiting for the request', done => {
+ const loadingIcon = saveButton.querySelector('.js-ci-variables-save-loading-icon');
mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(() => {
expect(loadingIcon.classList.contains(HIDE_CLASS)).toEqual(false);
@@ -54,7 +54,8 @@ describe('AjaxFormVariableList', () => {
expect(loadingIcon.classList.contains(HIDE_CLASS)).toEqual(true);
- ajaxVariableList.onSaveClicked()
+ ajaxVariableList
+ .onSaveClicked()
.then(() => {
expect(loadingIcon.classList.contains(HIDE_CLASS)).toEqual(true);
})
@@ -62,27 +63,30 @@ describe('AjaxFormVariableList', () => {
.catch(done.fail);
});
- it('calls `updateRowsWithPersistedVariables` with the persisted variables', (done) => {
+ it('calls `updateRowsWithPersistedVariables` with the persisted variables', done => {
const variablesResponse = [{ id: 1, key: 'foo', value: 'bar' }];
mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(200, {
variables: variablesResponse,
});
- ajaxVariableList.onSaveClicked()
+ ajaxVariableList
+ .onSaveClicked()
.then(() => {
- expect(ajaxVariableList.updateRowsWithPersistedVariables)
- .toHaveBeenCalledWith(variablesResponse);
+ expect(ajaxVariableList.updateRowsWithPersistedVariables).toHaveBeenCalledWith(
+ variablesResponse,
+ );
})
.then(done)
.catch(done.fail);
});
- it('hides any previous error box', (done) => {
+ it('hides any previous error box', done => {
mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(200);
expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(true);
- ajaxVariableList.onSaveClicked()
+ ajaxVariableList
+ .onSaveClicked()
.then(() => {
expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(true);
})
@@ -90,14 +94,15 @@ describe('AjaxFormVariableList', () => {
.catch(done.fail);
});
- it('disables remove buttons while waiting for the request', (done) => {
+ it('disables remove buttons while waiting for the request', done => {
mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(() => {
expect(ajaxVariableList.variableList.toggleEnableRow).toHaveBeenCalledWith(false);
return [200, {}];
});
- ajaxVariableList.onSaveClicked()
+ ajaxVariableList
+ .onSaveClicked()
.then(() => {
expect(ajaxVariableList.variableList.toggleEnableRow).toHaveBeenCalledWith(true);
})
@@ -105,7 +110,7 @@ describe('AjaxFormVariableList', () => {
.catch(done.fail);
});
- it('hides secret values', (done) => {
+ it('hides secret values', done => {
mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(200, {});
const row = container.querySelector('.js-row:first-child');
@@ -118,7 +123,8 @@ describe('AjaxFormVariableList', () => {
expect(valuePlaceholder.classList.contains(HIDE_CLASS)).toBe(true);
expect(valueInput.classList.contains(HIDE_CLASS)).toBe(false);
- ajaxVariableList.onSaveClicked()
+ ajaxVariableList
+ .onSaveClicked()
.then(() => {
expect(valuePlaceholder.classList.contains(HIDE_CLASS)).toBe(false);
expect(valueInput.classList.contains(HIDE_CLASS)).toBe(true);
@@ -127,29 +133,31 @@ describe('AjaxFormVariableList', () => {
.catch(done.fail);
});
- it('shows error box with validation errors', (done) => {
+ it('shows error box with validation errors', done => {
const validationError = 'some validation error';
- mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(400, [
- validationError,
- ]);
+ mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(400, [validationError]);
expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(true);
- ajaxVariableList.onSaveClicked()
+ ajaxVariableList
+ .onSaveClicked()
.then(() => {
expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(false);
- expect(errorBox.textContent.trim().replace(/\n+\s+/m, ' ')).toEqual(`Validation failed ${validationError}`);
+ expect(errorBox.textContent.trim().replace(/\n+\s+/m, ' ')).toEqual(
+ `Validation failed ${validationError}`,
+ );
})
.then(done)
.catch(done.fail);
});
- it('shows flash message when request fails', (done) => {
+ it('shows flash message when request fails', done => {
mock.onPatch(VARIABLE_PATCH_ENDPOINT).reply(500);
expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(true);
- ajaxVariableList.onSaveClicked()
+ ajaxVariableList
+ .onSaveClicked()
.then(() => {
expect(errorBox.classList.contains(HIDE_CLASS)).toEqual(true);
})
@@ -164,7 +172,7 @@ describe('AjaxFormVariableList', () => {
container = document.querySelector('.js-ci-variable-list-section');
const ajaxVariableListEl = document.querySelector('.js-ci-variable-list-section');
- saveButton = ajaxVariableListEl.querySelector('.js-secret-variables-save-button');
+ saveButton = ajaxVariableListEl.querySelector('.js-ci-variables-save-button');
errorBox = container.querySelector('.js-ci-variable-error-box');
ajaxVariableList = new AjaxFormVariableList({
container,
@@ -200,11 +208,13 @@ describe('AjaxFormVariableList', () => {
expect(idInput.value).toEqual('');
- ajaxVariableList.updateRowsWithPersistedVariables([{
- id: 3,
- key: 'foo',
- value: 'bar',
- }]);
+ ajaxVariableList.updateRowsWithPersistedVariables([
+ {
+ id: 3,
+ key: 'foo',
+ value: 'bar',
+ },
+ ]);
expect(idInput.value).toEqual('3');
expect(row.dataset.isPersisted).toEqual('true');
diff --git a/spec/javascripts/ci_variable_list/ci_variable_list_spec.js b/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
index 2fa50975f0f..30b15011def 100644
--- a/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
+++ b/spec/javascripts/ci_variable_list/ci_variable_list_spec.js
@@ -33,7 +33,8 @@ describe('VariableList', () => {
it('should add another row when editing the last rows key input', () => {
const $row = $wrapper.find('.js-row');
- $row.find('.js-ci-variable-input-key')
+ $row
+ .find('.js-ci-variable-input-key')
.val('foo')
.trigger('input');
@@ -41,12 +42,14 @@ describe('VariableList', () => {
// Check for the correct default in the new row
const $keyInput = $wrapper.find('.js-row:last-child').find('.js-ci-variable-input-key');
+
expect($keyInput.val()).toBe('');
});
it('should add another row when editing the last rows value textarea', () => {
const $row = $wrapper.find('.js-row');
- $row.find('.js-ci-variable-input-value')
+ $row
+ .find('.js-ci-variable-input-value')
.val('foo')
.trigger('input');
@@ -54,18 +57,21 @@ describe('VariableList', () => {
// Check for the correct default in the new row
const $valueInput = $wrapper.find('.js-row:last-child').find('.js-ci-variable-input-key');
+
expect($valueInput.val()).toBe('');
});
it('should remove empty row after blurring', () => {
const $row = $wrapper.find('.js-row');
- $row.find('.js-ci-variable-input-key')
+ $row
+ .find('.js-ci-variable-input-key')
.val('foo')
.trigger('input');
expect($wrapper.find('.js-row').length).toBe(2);
- $row.find('.js-ci-variable-input-key')
+ $row
+ .find('.js-ci-variable-input-key')
.val('')
.trigger('input')
.trigger('blur');
@@ -119,7 +125,7 @@ describe('VariableList', () => {
variableList.init();
});
- it('should add another row when editing the last rows protected checkbox', (done) => {
+ it('should add another row when editing the last rows protected checkbox', done => {
const $row = $wrapper.find('.js-row:last-child');
$row.find('.ci-variable-protected-item .js-project-feature-toggle').click();
@@ -128,7 +134,10 @@ describe('VariableList', () => {
expect($wrapper.find('.js-row').length).toBe(2);
// Check for the correct default in the new row
- const $protectedInput = $wrapper.find('.js-row:last-child').find('.js-ci-variable-input-protected');
+ const $protectedInput = $wrapper
+ .find('.js-row:last-child')
+ .find('.js-ci-variable-input-protected');
+
expect($protectedInput.val()).toBe('false');
})
.then(done)
@@ -166,6 +175,7 @@ describe('VariableList', () => {
it('should enable all remove buttons', () => {
variableList.toggleEnableRow(false);
+
expect($wrapper.find('.js-row-remove-button[disabled]').length).toBe(3);
variableList.toggleEnableRow(true);
@@ -175,6 +185,7 @@ describe('VariableList', () => {
it('should enable all key inputs', () => {
variableList.toggleEnableRow(false);
+
expect($wrapper.find('.js-ci-variable-input-key[disabled]').length).toBe(3);
variableList.toggleEnableRow(true);
@@ -200,7 +211,8 @@ describe('VariableList', () => {
const $inputValue = $row.find('.js-ci-variable-input-value');
const $placeholder = $row.find('.js-secret-value-placeholder');
- $row.find('.js-ci-variable-input-value')
+ $row
+ .find('.js-ci-variable-input-value')
.val('foo')
.trigger('input');
diff --git a/spec/javascripts/ci_variable_list/native_form_variable_list_spec.js b/spec/javascripts/ci_variable_list/native_form_variable_list_spec.js
index 94a0c999d66..997d0d54d79 100644
--- a/spec/javascripts/ci_variable_list/native_form_variable_list_spec.js
+++ b/spec/javascripts/ci_variable_list/native_form_variable_list_spec.js
@@ -19,8 +19,14 @@ describe('NativeFormVariableList', () => {
describe('onFormSubmit', () => {
it('should clear out the `name` attribute on the inputs for the last empty row on form submission (avoid BE validation)', () => {
const $row = $wrapper.find('.js-row');
- expect($row.find('.js-ci-variable-input-key').attr('name')).toBe('schedule[variables_attributes][][key]');
- expect($row.find('.js-ci-variable-input-value').attr('name')).toBe('schedule[variables_attributes][][secret_value]');
+
+ expect($row.find('.js-ci-variable-input-key').attr('name')).toBe(
+ 'schedule[variables_attributes][][key]',
+ );
+
+ expect($row.find('.js-ci-variable-input-value').attr('name')).toBe(
+ 'schedule[variables_attributes][][secret_value]',
+ );
$wrapper.closest('form').trigger('trigger-submit');
diff --git a/spec/javascripts/close_reopen_report_toggle_spec.js b/spec/javascripts/close_reopen_report_toggle_spec.js
index 925e959c85a..04a7ae7f429 100644
--- a/spec/javascripts/close_reopen_report_toggle_spec.js
+++ b/spec/javascripts/close_reopen_report_toggle_spec.js
@@ -1,3 +1,5 @@
+/* eslint-disable jasmine/no-unsafe-spy */
+
import CloseReopenReportToggle from '~/close_reopen_report_toggle';
import DropLab from '~/droplab/drop_lab';
@@ -8,7 +10,7 @@ describe('CloseReopenReportToggle', () => {
const button = {};
let commentTypeToggle;
- beforeEach(function () {
+ beforeEach(function() {
commentTypeToggle = new CloseReopenReportToggle({
dropdownTrigger,
dropdownList,
@@ -16,15 +18,15 @@ describe('CloseReopenReportToggle', () => {
});
});
- it('sets .dropdownTrigger', function () {
+ it('sets .dropdownTrigger', function() {
expect(commentTypeToggle.dropdownTrigger).toBe(dropdownTrigger);
});
- it('sets .dropdownList', function () {
+ it('sets .dropdownList', function() {
expect(commentTypeToggle.dropdownList).toBe(dropdownList);
});
- it('sets .button', function () {
+ it('sets .button', function() {
expect(commentTypeToggle.button).toBe(button);
});
});
diff --git a/spec/javascripts/clusters/clusters_bundle_spec.js b/spec/javascripts/clusters/clusters_bundle_spec.js
index d0e0b214509..880b469284b 100644
--- a/spec/javascripts/clusters/clusters_bundle_spec.js
+++ b/spec/javascripts/clusters/clusters_bundle_spec.js
@@ -21,21 +21,21 @@ describe('Clusters', () => {
});
describe('toggle', () => {
- it('should update the button and the input field on click', (done) => {
- const toggleButton = document.querySelector('.js-cluster-enable-toggle-area .js-project-feature-toggle');
- const toggleInput = document.querySelector('.js-cluster-enable-toggle-area .js-project-feature-toggle-input');
+ it('should update the button and the input field on click', done => {
+ const toggleButton = document.querySelector(
+ '.js-cluster-enable-toggle-area .js-project-feature-toggle',
+ );
+ const toggleInput = document.querySelector(
+ '.js-cluster-enable-toggle-area .js-project-feature-toggle-input',
+ );
toggleButton.click();
getSetTimeoutPromise()
.then(() => {
- expect(
- toggleButton.classList,
- ).not.toContain('is-checked');
+ expect(toggleButton.classList).not.toContain('is-checked');
- expect(
- toggleInput.getAttribute('value'),
- ).toEqual('false');
+ expect(toggleInput.getAttribute('value')).toEqual('false');
})
.then(done)
.catch(done.fail);
@@ -46,29 +46,21 @@ describe('Clusters', () => {
it('should update token field type', () => {
cluster.showTokenButton.click();
- expect(
- cluster.tokenField.getAttribute('type'),
- ).toEqual('text');
+ expect(cluster.tokenField.getAttribute('type')).toEqual('text');
cluster.showTokenButton.click();
- expect(
- cluster.tokenField.getAttribute('type'),
- ).toEqual('password');
+ expect(cluster.tokenField.getAttribute('type')).toEqual('password');
});
it('should update show token button text', () => {
cluster.showTokenButton.click();
- expect(
- cluster.showTokenButton.textContent,
- ).toEqual('Hide');
+ expect(cluster.showTokenButton.textContent).toEqual('Hide');
cluster.showTokenButton.click();
- expect(
- cluster.showTokenButton.textContent,
- ).toEqual('Show');
+ expect(cluster.showTokenButton.textContent).toEqual('Show');
});
});
@@ -86,37 +78,50 @@ describe('Clusters', () => {
});
const flashMessage = document.querySelector('.js-cluster-application-notice .flash-text');
+
expect(flashMessage).toBeNull();
});
it('shows an alert when something gets newly installed', () => {
- cluster.checkForNewInstalls({
- ...INITIAL_APP_MAP,
- helm: { status: APPLICATION_STATUS.INSTALLING, title: 'Helm Tiller' },
- }, {
- ...INITIAL_APP_MAP,
- helm: { status: APPLICATION_STATUS.INSTALLED, title: 'Helm Tiller' },
- });
+ cluster.checkForNewInstalls(
+ {
+ ...INITIAL_APP_MAP,
+ helm: { status: APPLICATION_STATUS.INSTALLING, title: 'Helm Tiller' },
+ },
+ {
+ ...INITIAL_APP_MAP,
+ helm: { status: APPLICATION_STATUS.INSTALLED, title: 'Helm Tiller' },
+ },
+ );
const flashMessage = document.querySelector('.js-cluster-application-notice .flash-text');
+
expect(flashMessage).not.toBeNull();
- expect(flashMessage.textContent.trim()).toEqual('Helm Tiller was successfully installed on your Kubernetes cluster');
+ expect(flashMessage.textContent.trim()).toEqual(
+ 'Helm Tiller was successfully installed on your Kubernetes cluster',
+ );
});
it('shows an alert when multiple things gets newly installed', () => {
- cluster.checkForNewInstalls({
- ...INITIAL_APP_MAP,
- helm: { status: APPLICATION_STATUS.INSTALLING, title: 'Helm Tiller' },
- ingress: { status: APPLICATION_STATUS.INSTALLABLE, title: 'Ingress' },
- }, {
- ...INITIAL_APP_MAP,
- helm: { status: APPLICATION_STATUS.INSTALLED, title: 'Helm Tiller' },
- ingress: { status: APPLICATION_STATUS.INSTALLED, title: 'Ingress' },
- });
+ cluster.checkForNewInstalls(
+ {
+ ...INITIAL_APP_MAP,
+ helm: { status: APPLICATION_STATUS.INSTALLING, title: 'Helm Tiller' },
+ ingress: { status: APPLICATION_STATUS.INSTALLABLE, title: 'Ingress' },
+ },
+ {
+ ...INITIAL_APP_MAP,
+ helm: { status: APPLICATION_STATUS.INSTALLED, title: 'Helm Tiller' },
+ ingress: { status: APPLICATION_STATUS.INSTALLED, title: 'Ingress' },
+ },
+ );
const flashMessage = document.querySelector('.js-cluster-application-notice .flash-text');
+
expect(flashMessage).not.toBeNull();
- expect(flashMessage.textContent.trim()).toEqual('Helm Tiller, Ingress was successfully installed on your Kubernetes cluster');
+ expect(flashMessage.textContent.trim()).toEqual(
+ 'Helm Tiller, Ingress was successfully installed on your Kubernetes cluster',
+ );
});
});
@@ -125,29 +130,21 @@ describe('Clusters', () => {
it('should show the creating container', () => {
cluster.updateContainer(null, 'creating');
- expect(
- cluster.creatingContainer.classList.contains('hidden'),
- ).toBeFalsy();
- expect(
- cluster.successContainer.classList.contains('hidden'),
- ).toBeTruthy();
- expect(
- cluster.errorContainer.classList.contains('hidden'),
- ).toBeTruthy();
+ expect(cluster.creatingContainer.classList.contains('hidden')).toBeFalsy();
+
+ expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy();
+
+ expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy();
});
it('should continue to show `creating` banner with subsequent updates of the same status', () => {
cluster.updateContainer('creating', 'creating');
- expect(
- cluster.creatingContainer.classList.contains('hidden'),
- ).toBeFalsy();
- expect(
- cluster.successContainer.classList.contains('hidden'),
- ).toBeTruthy();
- expect(
- cluster.errorContainer.classList.contains('hidden'),
- ).toBeTruthy();
+ expect(cluster.creatingContainer.classList.contains('hidden')).toBeFalsy();
+
+ expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy();
+
+ expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy();
});
});
@@ -155,29 +152,21 @@ describe('Clusters', () => {
it('should show the success container and fresh the page', () => {
cluster.updateContainer(null, 'created');
- expect(
- cluster.creatingContainer.classList.contains('hidden'),
- ).toBeTruthy();
- expect(
- cluster.successContainer.classList.contains('hidden'),
- ).toBeFalsy();
- expect(
- cluster.errorContainer.classList.contains('hidden'),
- ).toBeTruthy();
+ expect(cluster.creatingContainer.classList.contains('hidden')).toBeTruthy();
+
+ expect(cluster.successContainer.classList.contains('hidden')).toBeFalsy();
+
+ expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy();
});
it('should not show a banner when status is already `created`', () => {
cluster.updateContainer('created', 'created');
- expect(
- cluster.creatingContainer.classList.contains('hidden'),
- ).toBeTruthy();
- expect(
- cluster.successContainer.classList.contains('hidden'),
- ).toBeTruthy();
- expect(
- cluster.errorContainer.classList.contains('hidden'),
- ).toBeTruthy();
+ expect(cluster.creatingContainer.classList.contains('hidden')).toBeTruthy();
+
+ expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy();
+
+ expect(cluster.errorContainer.classList.contains('hidden')).toBeTruthy();
});
});
@@ -185,40 +174,31 @@ describe('Clusters', () => {
it('should show the error container', () => {
cluster.updateContainer(null, 'errored', 'this is an error');
- expect(
- cluster.creatingContainer.classList.contains('hidden'),
- ).toBeTruthy();
- expect(
- cluster.successContainer.classList.contains('hidden'),
- ).toBeTruthy();
- expect(
- cluster.errorContainer.classList.contains('hidden'),
- ).toBeFalsy();
-
- expect(
- cluster.errorReasonContainer.textContent,
- ).toContain('this is an error');
+ expect(cluster.creatingContainer.classList.contains('hidden')).toBeTruthy();
+
+ expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy();
+
+ expect(cluster.errorContainer.classList.contains('hidden')).toBeFalsy();
+
+ expect(cluster.errorReasonContainer.textContent).toContain('this is an error');
});
it('should show `error` banner when previously `creating`', () => {
cluster.updateContainer('creating', 'errored');
- expect(
- cluster.creatingContainer.classList.contains('hidden'),
- ).toBeTruthy();
- expect(
- cluster.successContainer.classList.contains('hidden'),
- ).toBeTruthy();
- expect(
- cluster.errorContainer.classList.contains('hidden'),
- ).toBeFalsy();
+ expect(cluster.creatingContainer.classList.contains('hidden')).toBeTruthy();
+
+ expect(cluster.successContainer.classList.contains('hidden')).toBeTruthy();
+
+ expect(cluster.errorContainer.classList.contains('hidden')).toBeFalsy();
});
});
});
describe('installApplication', () => {
- it('tries to install helm', (done) => {
+ it('tries to install helm', done => {
spyOn(cluster.service, 'installApplication').and.returnValue(Promise.resolve());
+
expect(cluster.store.state.applications.helm.requestStatus).toEqual(null);
cluster.installApplication({ id: 'helm' });
@@ -236,8 +216,9 @@ describe('Clusters', () => {
.catch(done.fail);
});
- it('tries to install ingress', (done) => {
+ it('tries to install ingress', done => {
spyOn(cluster.service, 'installApplication').and.returnValue(Promise.resolve());
+
expect(cluster.store.state.applications.ingress.requestStatus).toEqual(null);
cluster.installApplication({ id: 'ingress' });
@@ -255,8 +236,9 @@ describe('Clusters', () => {
.catch(done.fail);
});
- it('tries to install runner', (done) => {
+ it('tries to install runner', done => {
spyOn(cluster.service, 'installApplication').and.returnValue(Promise.resolve());
+
expect(cluster.store.state.applications.runner.requestStatus).toEqual(null);
cluster.installApplication({ id: 'runner' });
@@ -274,26 +256,35 @@ describe('Clusters', () => {
.catch(done.fail);
});
- it('tries to install jupyter', (done) => {
+ it('tries to install jupyter', done => {
spyOn(cluster.service, 'installApplication').and.returnValue(Promise.resolve());
+
expect(cluster.store.state.applications.jupyter.requestStatus).toEqual(null);
- cluster.installApplication({ id: 'jupyter', params: { hostname: cluster.store.state.applications.jupyter.hostname } });
+ cluster.installApplication({
+ id: 'jupyter',
+ params: { hostname: cluster.store.state.applications.jupyter.hostname },
+ });
expect(cluster.store.state.applications.jupyter.requestStatus).toEqual(REQUEST_LOADING);
expect(cluster.store.state.applications.jupyter.requestReason).toEqual(null);
- expect(cluster.service.installApplication).toHaveBeenCalledWith('jupyter', { hostname: cluster.store.state.applications.jupyter.hostname });
+ expect(cluster.service.installApplication).toHaveBeenCalledWith('jupyter', {
+ hostname: cluster.store.state.applications.jupyter.hostname,
+ });
getSetTimeoutPromise()
- .then(() => {
- expect(cluster.store.state.applications.jupyter.requestStatus).toEqual(REQUEST_SUCCESS);
- expect(cluster.store.state.applications.jupyter.requestReason).toEqual(null);
- })
- .then(done)
- .catch(done.fail);
+ .then(() => {
+ expect(cluster.store.state.applications.jupyter.requestStatus).toEqual(REQUEST_SUCCESS);
+ expect(cluster.store.state.applications.jupyter.requestReason).toEqual(null);
+ })
+ .then(done)
+ .catch(done.fail);
});
- it('sets error request status when the request fails', (done) => {
- spyOn(cluster.service, 'installApplication').and.returnValue(Promise.reject(new Error('STUBBED ERROR')));
+ it('sets error request status when the request fails', done => {
+ spyOn(cluster.service, 'installApplication').and.returnValue(
+ Promise.reject(new Error('STUBBED ERROR')),
+ );
+
expect(cluster.store.state.applications.helm.requestStatus).toEqual(null);
cluster.installApplication({ id: 'helm' });
diff --git a/spec/javascripts/clusters/components/application_row_spec.js b/spec/javascripts/clusters/components/application_row_spec.js
index 9da5c248371..45d56514930 100644
--- a/spec/javascripts/clusters/components/application_row_spec.js
+++ b/spec/javascripts/clusters/components/application_row_spec.js
@@ -112,6 +112,17 @@ describe('Application Row', () => {
expect(vm.installButtonDisabled).toEqual(true);
});
+ it('has disabled "Installed" when APPLICATION_STATUS.UPDATING', () => {
+ vm = mountComponent(ApplicationRow, {
+ ...DEFAULT_APPLICATION_STATE,
+ status: APPLICATION_STATUS.UPDATING,
+ });
+
+ expect(vm.installButtonLabel).toEqual('Installed');
+ expect(vm.installButtonLoading).toEqual(false);
+ expect(vm.installButtonDisabled).toEqual(true);
+ });
+
it('has enabled "Install" when APPLICATION_STATUS.ERROR', () => {
vm = mountComponent(ApplicationRow, {
...DEFAULT_APPLICATION_STATE,
@@ -215,7 +226,9 @@ describe('Application Row', () => {
status: null,
requestStatus: null,
});
- const generalErrorMessage = vm.$el.querySelector('.js-cluster-application-general-error-message');
+ const generalErrorMessage = vm.$el.querySelector(
+ '.js-cluster-application-general-error-message',
+ );
expect(generalErrorMessage).toBeNull();
});
@@ -227,10 +240,17 @@ describe('Application Row', () => {
status: APPLICATION_STATUS.ERROR,
statusReason,
});
- const generalErrorMessage = vm.$el.querySelector('.js-cluster-application-general-error-message');
- const statusErrorMessage = vm.$el.querySelector('.js-cluster-application-status-error-message');
+ const generalErrorMessage = vm.$el.querySelector(
+ '.js-cluster-application-general-error-message',
+ );
+ const statusErrorMessage = vm.$el.querySelector(
+ '.js-cluster-application-status-error-message',
+ );
+
+ expect(generalErrorMessage.textContent.trim()).toEqual(
+ `Something went wrong while installing ${DEFAULT_APPLICATION_STATE.title}`,
+ );
- expect(generalErrorMessage.textContent.trim()).toEqual(`Something went wrong while installing ${DEFAULT_APPLICATION_STATE.title}`);
expect(statusErrorMessage.textContent.trim()).toEqual(statusReason);
});
@@ -242,10 +262,17 @@ describe('Application Row', () => {
requestStatus: REQUEST_FAILURE,
requestReason,
});
- const generalErrorMessage = vm.$el.querySelector('.js-cluster-application-general-error-message');
- const requestErrorMessage = vm.$el.querySelector('.js-cluster-application-request-error-message');
+ const generalErrorMessage = vm.$el.querySelector(
+ '.js-cluster-application-general-error-message',
+ );
+ const requestErrorMessage = vm.$el.querySelector(
+ '.js-cluster-application-request-error-message',
+ );
+
+ expect(generalErrorMessage.textContent.trim()).toEqual(
+ `Something went wrong while installing ${DEFAULT_APPLICATION_STATE.title}`,
+ );
- expect(generalErrorMessage.textContent.trim()).toEqual(`Something went wrong while installing ${DEFAULT_APPLICATION_STATE.title}`);
expect(requestErrorMessage.textContent.trim()).toEqual(requestReason);
});
});
diff --git a/spec/javascripts/clusters/components/applications_spec.js b/spec/javascripts/clusters/components/applications_spec.js
index a70138c7eee..928bf70f3a2 100644
--- a/spec/javascripts/clusters/components/applications_spec.js
+++ b/spec/javascripts/clusters/components/applications_spec.js
@@ -20,9 +20,11 @@ describe('Applications', () => {
applications: {
helm: { title: 'Helm Tiller' },
ingress: { title: 'Ingress' },
+ cert_manager: { title: 'Cert-Manager' },
runner: { title: 'GitLab Runner' },
prometheus: { title: 'Prometheus' },
jupyter: { title: 'JupyterHub' },
+ knative: { title: 'Knative' },
},
});
});
@@ -35,6 +37,10 @@ describe('Applications', () => {
expect(vm.$el.querySelector('.js-cluster-application-row-ingress')).toBeDefined();
});
+ it('renders a row for Cert-Manager', () => {
+ expect(vm.$el.querySelector('.js-cluster-application-row-cert_manager')).toBeDefined();
+ });
+
it('renders a row for Prometheus', () => {
expect(vm.$el.querySelector('.js-cluster-application-row-prometheus')).toBeDefined();
});
@@ -46,6 +52,10 @@ describe('Applications', () => {
it('renders a row for Jupyter', () => {
expect(vm.$el.querySelector('.js-cluster-application-row-jupyter')).not.toBe(null);
});
+
+ it('renders a row for Knative', () => {
+ expect(vm.$el.querySelector('.js-cluster-application-row-knative')).not.toBe(null);
+ });
});
describe('Ingress application', () => {
@@ -60,9 +70,11 @@ describe('Applications', () => {
externalIp: '0.0.0.0',
},
helm: { title: 'Helm Tiller' },
+ cert_manager: { title: 'Cert-Manager' },
runner: { title: 'GitLab Runner' },
prometheus: { title: 'Prometheus' },
jupyter: { title: 'JupyterHub', hostname: '' },
+ knative: { title: 'Knative', hostname: '' },
},
});
@@ -83,9 +95,11 @@ describe('Applications', () => {
status: 'installed',
},
helm: { title: 'Helm Tiller' },
+ cert_manager: { title: 'Cert-Manager' },
runner: { title: 'GitLab Runner' },
prometheus: { title: 'Prometheus' },
jupyter: { title: 'JupyterHub', hostname: '' },
+ knative: { title: 'Knative', hostname: '' },
},
});
@@ -102,9 +116,11 @@ describe('Applications', () => {
applications: {
helm: { title: 'Helm Tiller' },
ingress: { title: 'Ingress' },
+ cert_manager: { title: 'Cert-Manager' },
runner: { title: 'GitLab Runner' },
prometheus: { title: 'Prometheus' },
jupyter: { title: 'JupyterHub', hostname: '' },
+ knative: { title: 'Knative', hostname: '' },
},
});
@@ -120,9 +136,11 @@ describe('Applications', () => {
applications: {
helm: { title: 'Helm Tiller', status: 'installed' },
ingress: { title: 'Ingress', status: 'installed', externalIp: '1.1.1.1' },
+ cert_manager: { title: 'Cert-Manager' },
runner: { title: 'GitLab Runner' },
prometheus: { title: 'Prometheus' },
jupyter: { title: 'JupyterHub', hostname: '', status: 'installable' },
+ knative: { title: 'Knative', hostname: '', status: 'installable' },
},
});
@@ -136,9 +154,11 @@ describe('Applications', () => {
applications: {
helm: { title: 'Helm Tiller', status: 'installed' },
ingress: { title: 'Ingress', status: 'installed' },
+ cert_manager: { title: 'Cert-Manager' },
runner: { title: 'GitLab Runner' },
prometheus: { title: 'Prometheus' },
jupyter: { title: 'JupyterHub', hostname: '', status: 'installable' },
+ knative: { title: 'Knative', hostname: '', status: 'installable' },
},
});
@@ -152,9 +172,11 @@ describe('Applications', () => {
applications: {
helm: { title: 'Helm Tiller', status: 'installed' },
ingress: { title: 'Ingress', status: 'installed', externalIp: '1.1.1.1' },
+ cert_manager: { title: 'Cert-Manager' },
runner: { title: 'GitLab Runner' },
prometheus: { title: 'Prometheus' },
jupyter: { title: 'JupyterHub', status: 'installed', hostname: '' },
+ knative: { title: 'Knative', status: 'installed', hostname: '' },
},
});
@@ -168,9 +190,11 @@ describe('Applications', () => {
applications: {
helm: { title: 'Helm Tiller' },
ingress: { title: 'Ingress' },
+ cert_manager: { title: 'Cert-Manager' },
runner: { title: 'GitLab Runner' },
prometheus: { title: 'Prometheus' },
jupyter: { title: 'JupyterHub', status: 'not_installable' },
+ knative: { title: 'Knative' },
},
});
});
diff --git a/spec/javascripts/clusters/services/mock_data.js b/spec/javascripts/clusters/services/mock_data.js
index c7c1412e1c6..540d7f30858 100644
--- a/spec/javascripts/clusters/services/mock_data.js
+++ b/spec/javascripts/clusters/services/mock_data.js
@@ -6,67 +6,99 @@ const CLUSTERS_MOCK_DATA = {
data: {
status: 'errored',
status_reason: 'Failed to request to CloudPlatform.',
- applications: [{
- name: 'helm',
- status: APPLICATION_STATUS.INSTALLABLE,
- status_reason: null,
- }, {
- name: 'ingress',
- status: APPLICATION_STATUS.ERROR,
- status_reason: 'Cannot connect',
- external_ip: null,
- }, {
- name: 'runner',
- status: APPLICATION_STATUS.INSTALLING,
- status_reason: null,
- },
- {
- name: 'prometheus',
- status: APPLICATION_STATUS.ERROR,
- status_reason: 'Cannot connect',
- }, {
- name: 'jupyter',
- status: APPLICATION_STATUS.INSTALLING,
- status_reason: 'Cannot connect',
- }],
+ applications: [
+ {
+ name: 'helm',
+ status: APPLICATION_STATUS.INSTALLABLE,
+ status_reason: null,
+ },
+ {
+ name: 'ingress',
+ status: APPLICATION_STATUS.ERROR,
+ status_reason: 'Cannot connect',
+ external_ip: null,
+ },
+ {
+ name: 'runner',
+ status: APPLICATION_STATUS.INSTALLING,
+ status_reason: null,
+ },
+ {
+ name: 'prometheus',
+ status: APPLICATION_STATUS.ERROR,
+ status_reason: 'Cannot connect',
+ },
+ {
+ name: 'jupyter',
+ status: APPLICATION_STATUS.INSTALLING,
+ status_reason: 'Cannot connect',
+ },
+ {
+ name: 'knative',
+ status: APPLICATION_STATUS.INSTALLING,
+ status_reason: 'Cannot connect',
+ },
+ {
+ name: 'cert_manager',
+ status: APPLICATION_STATUS.ERROR,
+ status_reason: 'Cannot connect',
+ },
+ ],
},
},
'/gitlab-org/gitlab-shell/clusters/2/status.json': {
data: {
status: 'errored',
status_reason: 'Failed to request to CloudPlatform.',
- applications: [{
- name: 'helm',
- status: APPLICATION_STATUS.INSTALLED,
- status_reason: null,
- }, {
- name: 'ingress',
- status: APPLICATION_STATUS.INSTALLED,
- status_reason: 'Cannot connect',
- external_ip: '1.1.1.1',
- }, {
- name: 'runner',
- status: APPLICATION_STATUS.INSTALLING,
- status_reason: null,
- },
- {
- name: 'prometheus',
- status: APPLICATION_STATUS.ERROR,
- status_reason: 'Cannot connect',
- }, {
- name: 'jupyter',
- status: APPLICATION_STATUS.INSTALLABLE,
- status_reason: 'Cannot connect',
- }],
+ applications: [
+ {
+ name: 'helm',
+ status: APPLICATION_STATUS.INSTALLED,
+ status_reason: null,
+ },
+ {
+ name: 'ingress',
+ status: APPLICATION_STATUS.INSTALLED,
+ status_reason: 'Cannot connect',
+ external_ip: '1.1.1.1',
+ },
+ {
+ name: 'runner',
+ status: APPLICATION_STATUS.INSTALLING,
+ status_reason: null,
+ },
+ {
+ name: 'prometheus',
+ status: APPLICATION_STATUS.ERROR,
+ status_reason: 'Cannot connect',
+ },
+ {
+ name: 'jupyter',
+ status: APPLICATION_STATUS.INSTALLABLE,
+ status_reason: 'Cannot connect',
+ },
+ {
+ name: 'knative',
+ status: APPLICATION_STATUS.INSTALLABLE,
+ status_reason: 'Cannot connect',
+ },
+ {
+ name: 'cert_manager',
+ status: APPLICATION_STATUS.ERROR,
+ status_reason: 'Cannot connect',
+ },
+ ],
},
},
},
POST: {
- '/gitlab-org/gitlab-shell/clusters/1/applications/helm': { },
- '/gitlab-org/gitlab-shell/clusters/1/applications/ingress': { },
- '/gitlab-org/gitlab-shell/clusters/1/applications/runner': { },
- '/gitlab-org/gitlab-shell/clusters/1/applications/prometheus': { },
- '/gitlab-org/gitlab-shell/clusters/1/applications/jupyter': { },
+ '/gitlab-org/gitlab-shell/clusters/1/applications/helm': {},
+ '/gitlab-org/gitlab-shell/clusters/1/applications/ingress': {},
+ '/gitlab-org/gitlab-shell/clusters/1/applications/cert_manager': {},
+ '/gitlab-org/gitlab-shell/clusters/1/applications/runner': {},
+ '/gitlab-org/gitlab-shell/clusters/1/applications/prometheus': {},
+ '/gitlab-org/gitlab-shell/clusters/1/applications/jupyter': {},
+ '/gitlab-org/gitlab-shell/clusters/1/applications/knative': {},
},
};
@@ -81,7 +113,4 @@ const DEFAULT_APPLICATION_STATE = {
requestReason: null,
};
-export {
- CLUSTERS_MOCK_DATA,
- DEFAULT_APPLICATION_STATE,
-};
+export { CLUSTERS_MOCK_DATA, DEFAULT_APPLICATION_STATE };
diff --git a/spec/javascripts/clusters/stores/clusters_store_spec.js b/spec/javascripts/clusters/stores/clusters_store_spec.js
index 104a064bdd3..7ea0878ad45 100644
--- a/spec/javascripts/clusters/stores/clusters_store_spec.js
+++ b/spec/javascripts/clusters/stores/clusters_store_spec.js
@@ -53,7 +53,8 @@ describe('Clusters Store', () => {
describe('updateStateFromServer', () => {
it('should store new polling data from server', () => {
- const mockResponseData = CLUSTERS_MOCK_DATA.GET['/gitlab-org/gitlab-shell/clusters/1/status.json'].data;
+ const mockResponseData =
+ CLUSTERS_MOCK_DATA.GET['/gitlab-org/gitlab-shell/clusters/1/status.json'].data;
store.updateStateFromServer(mockResponseData);
expect(store.state).toEqual({
@@ -99,18 +100,35 @@ describe('Clusters Store', () => {
requestReason: null,
hostname: '',
},
+ knative: {
+ title: 'Knative',
+ status: mockResponseData.applications[5].status,
+ statusReason: mockResponseData.applications[5].status_reason,
+ requestStatus: null,
+ requestReason: null,
+ hostname: null,
+ externalIp: null,
+ },
+ cert_manager: {
+ title: 'Cert-Manager',
+ status: mockResponseData.applications[6].status,
+ statusReason: mockResponseData.applications[6].status_reason,
+ requestStatus: null,
+ requestReason: null,
+ },
},
});
});
it('sets default hostname for jupyter when ingress has a ip address', () => {
- const mockResponseData = CLUSTERS_MOCK_DATA.GET['/gitlab-org/gitlab-shell/clusters/2/status.json'].data;
+ const mockResponseData =
+ CLUSTERS_MOCK_DATA.GET['/gitlab-org/gitlab-shell/clusters/2/status.json'].data;
store.updateStateFromServer(mockResponseData);
- expect(
- store.state.applications.jupyter.hostname,
- ).toEqual(`jupyter.${store.state.applications.ingress.externalIp}.nip.io`);
+ expect(store.state.applications.jupyter.hostname).toEqual(
+ `jupyter.${store.state.applications.ingress.externalIp}.nip.io`,
+ );
});
});
});
diff --git a/spec/javascripts/collapsed_sidebar_todo_spec.js b/spec/javascripts/collapsed_sidebar_todo_spec.js
index 8427e8a0ba7..dc5737558c0 100644
--- a/spec/javascripts/collapsed_sidebar_todo_spec.js
+++ b/spec/javascripts/collapsed_sidebar_todo_spec.js
@@ -18,10 +18,8 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
new Sidebar();
loadFixtures(fixtureName);
- document.querySelector('.js-right-sidebar')
- .classList.toggle('right-sidebar-expanded');
- document.querySelector('.js-right-sidebar')
- .classList.toggle('right-sidebar-collapsed');
+ document.querySelector('.js-right-sidebar').classList.toggle('right-sidebar-expanded');
+ document.querySelector('.js-right-sidebar').classList.toggle('right-sidebar-collapsed');
mock = new MockAdapter(axios);
@@ -44,13 +42,13 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
});
it('shows add todo button', () => {
- expect(
- document.querySelector('.js-issuable-todo.sidebar-collapsed-icon'),
- ).not.toBeNull();
+ expect(document.querySelector('.js-issuable-todo.sidebar-collapsed-icon')).not.toBeNull();
expect(
- document.querySelector('.js-issuable-todo.sidebar-collapsed-icon .fa-plus-square'),
- ).not.toBeNull();
+ document
+ .querySelector('.js-issuable-todo.sidebar-collapsed-icon svg use')
+ .getAttribute('xlink:href'),
+ ).toContain('todo-add');
expect(
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon .todo-undone'),
@@ -63,7 +61,7 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
).toBe('Add todo');
});
- it('toggle todo state', (done) => {
+ it('toggle todo state', done => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
setTimeout(() => {
@@ -72,14 +70,16 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
).not.toBeNull();
expect(
- document.querySelector('.js-issuable-todo.sidebar-collapsed-icon .fa-check-square'),
- ).not.toBeNull();
+ document
+ .querySelector('.js-issuable-todo.sidebar-collapsed-icon svg.todo-undone use')
+ .getAttribute('xlink:href'),
+ ).toContain('todo-done');
done();
});
});
- it('toggle todo state of expanded todo toggle', (done) => {
+ it('toggle todo state of expanded todo toggle', done => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
setTimeout(() => {
@@ -91,19 +91,21 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
});
});
- it('toggles todo button tooltip', (done) => {
+ it('toggles todo button tooltip', done => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
setTimeout(() => {
expect(
- document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').getAttribute('data-original-title'),
+ document
+ .querySelector('.js-issuable-todo.sidebar-collapsed-icon')
+ .getAttribute('data-original-title'),
).toBe('Mark todo as done');
done();
});
});
- it('marks todo as done', (done) => {
+ it('marks todo as done', done => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
timeoutPromise()
@@ -128,25 +130,29 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
.catch(done.fail);
});
- it('updates aria-label to mark todo as done', (done) => {
+ it('updates aria-label to mark todo as done', done => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
setTimeout(() => {
expect(
- document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').getAttribute('aria-label'),
+ document
+ .querySelector('.js-issuable-todo.sidebar-collapsed-icon')
+ .getAttribute('aria-label'),
).toBe('Mark todo as done');
done();
});
});
- it('updates aria-label to add todo', (done) => {
+ it('updates aria-label to add todo', done => {
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
timeoutPromise()
.then(() => {
expect(
- document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').getAttribute('aria-label'),
+ document
+ .querySelector('.js-issuable-todo.sidebar-collapsed-icon')
+ .getAttribute('aria-label'),
).toBe('Mark todo as done');
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').click();
@@ -154,7 +160,9 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
.then(timeoutPromise)
.then(() => {
expect(
- document.querySelector('.js-issuable-todo.sidebar-collapsed-icon').getAttribute('aria-label'),
+ document
+ .querySelector('.js-issuable-todo.sidebar-collapsed-icon')
+ .getAttribute('aria-label'),
).toBe('Add todo');
})
.then(done)
diff --git a/spec/javascripts/comment_type_toggle_spec.js b/spec/javascripts/comment_type_toggle_spec.js
index 0ba709298c5..8b1217a000f 100644
--- a/spec/javascripts/comment_type_toggle_spec.js
+++ b/spec/javascripts/comment_type_toggle_spec.js
@@ -1,9 +1,9 @@
import CommentTypeToggle from '~/comment_type_toggle';
import InputSetter from '~/droplab/plugins/input_setter';
-describe('CommentTypeToggle', function () {
- describe('class constructor', function () {
- beforeEach(function () {
+describe('CommentTypeToggle', function() {
+ describe('class constructor', function() {
+ beforeEach(function() {
this.dropdownTrigger = {};
this.dropdownList = {};
this.noteTypeInput = {};
@@ -19,33 +19,33 @@ describe('CommentTypeToggle', function () {
});
});
- it('should set .dropdownTrigger', function () {
+ it('should set .dropdownTrigger', function() {
expect(this.commentTypeToggle.dropdownTrigger).toBe(this.dropdownTrigger);
});
- it('should set .dropdownList', function () {
+ it('should set .dropdownList', function() {
expect(this.commentTypeToggle.dropdownList).toBe(this.dropdownList);
});
- it('should set .noteTypeInput', function () {
+ it('should set .noteTypeInput', function() {
expect(this.commentTypeToggle.noteTypeInput).toBe(this.noteTypeInput);
});
- it('should set .submitButton', function () {
+ it('should set .submitButton', function() {
expect(this.commentTypeToggle.submitButton).toBe(this.submitButton);
});
- it('should set .closeButton', function () {
+ it('should set .closeButton', function() {
expect(this.commentTypeToggle.closeButton).toBe(this.closeButton);
});
- it('should set .reopenButton', function () {
+ it('should set .reopenButton', function() {
expect(this.commentTypeToggle.reopenButton).toBe(this.reopenButton);
});
});
- describe('initDroplab', function () {
- beforeEach(function () {
+ describe('initDroplab', function() {
+ beforeEach(function() {
this.commentTypeToggle = {
dropdownTrigger: {},
dropdownList: {},
@@ -58,25 +58,27 @@ describe('CommentTypeToggle', function () {
this.droplab = jasmine.createSpyObj('droplab', ['init']);
- this.droplabConstructor = spyOnDependency(CommentTypeToggle, 'DropLab').and.returnValue(this.droplab);
+ this.droplabConstructor = spyOnDependency(CommentTypeToggle, 'DropLab').and.returnValue(
+ this.droplab,
+ );
spyOn(this.commentTypeToggle, 'setConfig').and.returnValue(this.config);
CommentTypeToggle.prototype.initDroplab.call(this.commentTypeToggle);
});
- it('should instantiate a DropLab instance', function () {
+ it('should instantiate a DropLab instance', function() {
expect(this.droplabConstructor).toHaveBeenCalled();
});
- it('should set .droplab', function () {
+ it('should set .droplab', function() {
expect(this.commentTypeToggle.droplab).toBe(this.droplab);
});
- it('should call .setConfig', function () {
+ it('should call .setConfig', function() {
expect(this.commentTypeToggle.setConfig).toHaveBeenCalled();
});
- it('should call DropLab.prototype.init', function () {
+ it('should call DropLab.prototype.init', function() {
expect(this.droplab.init).toHaveBeenCalledWith(
this.commentTypeToggle.dropdownTrigger,
this.commentTypeToggle.dropdownList,
@@ -86,9 +88,9 @@ describe('CommentTypeToggle', function () {
});
});
- describe('setConfig', function () {
- describe('if no .closeButton is provided', function () {
- beforeEach(function () {
+ describe('setConfig', function() {
+ describe('if no .closeButton is provided', function() {
+ beforeEach(function() {
this.commentTypeToggle = {
dropdownTrigger: {},
dropdownList: {},
@@ -100,28 +102,33 @@ describe('CommentTypeToggle', function () {
this.setConfig = CommentTypeToggle.prototype.setConfig.call(this.commentTypeToggle);
});
- it('should not add .closeButton related InputSetter config', function () {
+ it('should not add .closeButton related InputSetter config', function() {
expect(this.setConfig).toEqual({
- InputSetter: [{
- input: this.commentTypeToggle.noteTypeInput,
- valueAttribute: 'data-value',
- }, {
- input: this.commentTypeToggle.submitButton,
- valueAttribute: 'data-submit-text',
- }, {
- input: this.commentTypeToggle.reopenButton,
- valueAttribute: 'data-reopen-text',
- }, {
- input: this.commentTypeToggle.reopenButton,
- valueAttribute: 'data-reopen-text',
- inputAttribute: 'data-alternative-text',
- }],
+ InputSetter: [
+ {
+ input: this.commentTypeToggle.noteTypeInput,
+ valueAttribute: 'data-value',
+ },
+ {
+ input: this.commentTypeToggle.submitButton,
+ valueAttribute: 'data-submit-text',
+ },
+ {
+ input: this.commentTypeToggle.reopenButton,
+ valueAttribute: 'data-reopen-text',
+ },
+ {
+ input: this.commentTypeToggle.reopenButton,
+ valueAttribute: 'data-reopen-text',
+ inputAttribute: 'data-alternative-text',
+ },
+ ],
});
});
});
- describe('if no .reopenButton is provided', function () {
- beforeEach(function () {
+ describe('if no .reopenButton is provided', function() {
+ beforeEach(function() {
this.commentTypeToggle = {
dropdownTrigger: {},
dropdownList: {},
@@ -133,22 +140,27 @@ describe('CommentTypeToggle', function () {
this.setConfig = CommentTypeToggle.prototype.setConfig.call(this.commentTypeToggle);
});
- it('should not add .reopenButton related InputSetter config', function () {
+ it('should not add .reopenButton related InputSetter config', function() {
expect(this.setConfig).toEqual({
- InputSetter: [{
- input: this.commentTypeToggle.noteTypeInput,
- valueAttribute: 'data-value',
- }, {
- input: this.commentTypeToggle.submitButton,
- valueAttribute: 'data-submit-text',
- }, {
- input: this.commentTypeToggle.closeButton,
- valueAttribute: 'data-close-text',
- }, {
- input: this.commentTypeToggle.closeButton,
- valueAttribute: 'data-close-text',
- inputAttribute: 'data-alternative-text',
- }],
+ InputSetter: [
+ {
+ input: this.commentTypeToggle.noteTypeInput,
+ valueAttribute: 'data-value',
+ },
+ {
+ input: this.commentTypeToggle.submitButton,
+ valueAttribute: 'data-submit-text',
+ },
+ {
+ input: this.commentTypeToggle.closeButton,
+ valueAttribute: 'data-close-text',
+ },
+ {
+ input: this.commentTypeToggle.closeButton,
+ valueAttribute: 'data-close-text',
+ inputAttribute: 'data-alternative-text',
+ },
+ ],
});
});
});
diff --git a/spec/javascripts/commit/commit_pipeline_status_component_spec.js b/spec/javascripts/commit/commit_pipeline_status_component_spec.js
index d3776d0c3cf..f6b36e88a5f 100644
--- a/spec/javascripts/commit/commit_pipeline_status_component_spec.js
+++ b/spec/javascripts/commit/commit_pipeline_status_component_spec.js
@@ -22,19 +22,22 @@ describe('Commit pipeline status component', () => {
Component = Vue.extend(commitPipelineStatus);
});
- describe('While polling pipeline data succesfully', () => {
+ describe('While polling pipeline data successfully', () => {
beforeEach(() => {
mock = new MockAdapter(axios);
mock.onGet('/dummy/endpoint').reply(() => {
- const res = Promise.resolve([200, {
- pipelines: [
- {
- details: {
- status: mockCiStatus,
+ const res = Promise.resolve([
+ 200,
+ {
+ pipelines: [
+ {
+ details: {
+ status: mockCiStatus,
+ },
},
- },
- ],
- }]);
+ ],
+ },
+ ]);
return res;
});
vm = mountComponent(Component, {
@@ -48,7 +51,7 @@ describe('Commit pipeline status component', () => {
mock.restore();
});
- it('shows the loading icon when polling is starting', (done) => {
+ it('shows the loading icon when polling is starting', done => {
expect(vm.$el.querySelector('.loading-container')).not.toBe(null);
setTimeout(() => {
expect(vm.$el.querySelector('.loading-container')).toBe(null);
@@ -56,23 +59,25 @@ describe('Commit pipeline status component', () => {
});
});
- it('contains a ciStatus when the polling is succesful ', (done) => {
+ it('contains a ciStatus when the polling is successful ', done => {
setTimeout(() => {
expect(vm.ciStatus).toEqual(mockCiStatus);
done();
});
});
- it('contains a ci-status icon when polling is succesful', (done) => {
+ it('contains a ci-status icon when polling is successful', done => {
setTimeout(() => {
expect(vm.$el.querySelector('.ci-status-icon')).not.toBe(null);
- expect(vm.$el.querySelector('.ci-status-icon').classList).toContain(`ci-status-icon-${mockCiStatus.group}`);
+ expect(vm.$el.querySelector('.ci-status-icon').classList).toContain(
+ `ci-status-icon-${mockCiStatus.group}`,
+ );
done();
});
});
});
- describe('When polling data was not succesful', () => {
+ describe('When polling data was not successful', () => {
beforeEach(() => {
mock = new MockAdapter(axios);
mock.onGet('/dummy/endpoint').reply(502, {});
@@ -89,7 +94,7 @@ describe('Commit pipeline status component', () => {
mock.restore();
});
- it('calls an errorCallback', (done) => {
+ it('calls an errorCallback', done => {
spyOn(vm, 'errorCallback').and.callThrough();
vm.$mount();
setTimeout(() => {
diff --git a/spec/javascripts/commit/pipelines/pipelines_spec.js b/spec/javascripts/commit/pipelines/pipelines_spec.js
index a18e09da50a..04c8ab44405 100644
--- a/spec/javascripts/commit/pipelines/pipelines_spec.js
+++ b/spec/javascripts/commit/pipelines/pipelines_spec.js
@@ -4,7 +4,7 @@ import axios from '~/lib/utils/axios_utils';
import pipelinesTable from '~/commit/pipelines/pipelines_table.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
-describe('Pipelines table in Commits and Merge requests', function () {
+describe('Pipelines table in Commits and Merge requests', function() {
const jsonFixtureName = 'pipelines/pipelines.json';
let pipeline;
let PipelinesTable;
@@ -29,7 +29,7 @@ describe('Pipelines table in Commits and Merge requests', function () {
describe('successful request', () => {
describe('without pipelines', () => {
- beforeEach(function () {
+ beforeEach(function() {
mock.onGet('endpoint.json').reply(200, []);
vm = mountComponent(PipelinesTable, {
@@ -41,7 +41,7 @@ describe('Pipelines table in Commits and Merge requests', function () {
});
});
- it('should render the empty state', function (done) {
+ it('should render the empty state', function(done) {
setTimeout(() => {
expect(vm.$el.querySelector('.empty-state')).toBeDefined();
expect(vm.$el.querySelector('.realtime-loading')).toBe(null);
@@ -63,7 +63,7 @@ describe('Pipelines table in Commits and Merge requests', function () {
});
});
- it('should render a table with the received pipelines', (done) => {
+ it('should render a table with the received pipelines', done => {
setTimeout(() => {
expect(vm.$el.querySelectorAll('.ci-table .commit').length).toEqual(1);
expect(vm.$el.querySelector('.realtime-loading')).toBe(null);
@@ -72,6 +72,29 @@ describe('Pipelines table in Commits and Merge requests', function () {
done();
}, 0);
});
+
+ describe('with pagination', () => {
+ it('should make an API request when using pagination', done => {
+ setTimeout(() => {
+ spyOn(vm, 'updateContent');
+
+ vm.store.state.pageInfo = {
+ page: 1,
+ total: 10,
+ perPage: 2,
+ nextPage: 2,
+ totalPages: 5,
+ };
+
+ vm.$nextTick(() => {
+ vm.$el.querySelector('.js-next-button a').click();
+
+ expect(vm.updateContent).toHaveBeenCalledWith({ page: '2' });
+ done();
+ });
+ });
+ });
+ });
});
describe('pipeline badge counts', () => {
@@ -79,11 +102,11 @@ describe('Pipelines table in Commits and Merge requests', function () {
mock.onGet('endpoint.json').reply(200, [pipeline]);
});
- it('should receive update-pipelines-count event', (done) => {
+ it('should receive update-pipelines-count event', done => {
const element = document.createElement('div');
document.body.appendChild(element);
- element.addEventListener('update-pipelines-count', (event) => {
+ element.addEventListener('update-pipelines-count', event => {
expect(event.detail.pipelines).toEqual([pipeline]);
done();
});
@@ -114,7 +137,7 @@ describe('Pipelines table in Commits and Merge requests', function () {
});
});
- it('should render error state', function (done) {
+ it('should render error state', function(done) {
setTimeout(() => {
expect(vm.$el.querySelector('.js-pipelines-error-state')).toBeDefined();
expect(vm.$el.querySelector('.realtime-loading')).toBe(null);
diff --git a/spec/javascripts/commit_merge_requests_spec.js b/spec/javascripts/commit_merge_requests_spec.js
index 3466ef51ea8..82968e028d1 100644
--- a/spec/javascripts/commit_merge_requests_spec.js
+++ b/spec/javascripts/commit_merge_requests_spec.js
@@ -3,11 +3,16 @@ import * as CommitMergeRequests from '~/commit_merge_requests';
describe('CommitMergeRequests', () => {
describe('createContent', () => {
it('should return created content', () => {
- const content1 = CommitMergeRequests.createContent([{ iid: 1, path: '/path1', title: 'foo' }, { iid: 2, path: '/path2', title: 'baz' }])[0];
+ const content1 = CommitMergeRequests.createContent([
+ { iid: 1, path: '/path1', title: 'foo' },
+ { iid: 2, path: '/path2', title: 'baz' },
+ ])[0];
+
expect(content1.tagName).toEqual('SPAN');
expect(content1.childElementCount).toEqual(4);
const content2 = CommitMergeRequests.createContent([])[0];
+
expect(content2.tagName).toEqual('SPAN');
expect(content2.childElementCount).toEqual(0);
expect(content2.innerText).toEqual('No related merge requests found');
@@ -26,6 +31,7 @@ describe('CommitMergeRequests', () => {
describe('createHeader', () => {
it('should return created header', () => {
const header = CommitMergeRequests.createHeader(0, 1)[0];
+
expect(header.tagName).toEqual('SPAN');
expect(header.innerText).toEqual('1 merge request');
});
@@ -34,6 +40,7 @@ describe('CommitMergeRequests', () => {
describe('createItem', () => {
it('should return created item', () => {
const item = CommitMergeRequests.createItem({ iid: 1, path: '/path', title: 'foo' })[0];
+
expect(item.tagName).toEqual('SPAN');
expect(item.childElementCount).toEqual(2);
expect(item.children[0].tagName).toEqual('A');
@@ -44,6 +51,7 @@ describe('CommitMergeRequests', () => {
describe('createLink', () => {
it('should return created link', () => {
const link = CommitMergeRequests.createLink({ iid: 1, path: '/path', title: 'foo' })[0];
+
expect(link.tagName).toEqual('A');
expect(link.href).toMatch(/\/path$/);
expect(link.innerText).toEqual('!1');
@@ -53,6 +61,7 @@ describe('CommitMergeRequests', () => {
describe('createTitle', () => {
it('should return created title', () => {
const title = CommitMergeRequests.createTitle({ iid: 1, path: '/path', title: 'foo' })[0];
+
expect(title.tagName).toEqual('SPAN');
expect(title.innerText).toEqual('foo');
});
diff --git a/spec/javascripts/create_item_dropdown_spec.js b/spec/javascripts/create_item_dropdown_spec.js
index ee26122be12..9cf72d7c55b 100644
--- a/spec/javascripts/create_item_dropdown_spec.js
+++ b/spec/javascripts/create_item_dropdown_spec.js
@@ -1,19 +1,23 @@
import $ from 'jquery';
import CreateItemDropdown from '~/create_item_dropdown';
-const DROPDOWN_ITEM_DATA = [{
- title: 'one',
- id: 'one',
- text: 'one',
-}, {
- title: 'two',
- id: 'two',
- text: 'two',
-}, {
- title: 'three',
- id: 'three',
- text: 'three',
-}];
+const DROPDOWN_ITEM_DATA = [
+ {
+ title: 'one',
+ id: 'one',
+ text: 'one',
+ },
+ {
+ title: 'two',
+ id: 'two',
+ text: 'two',
+ },
+ {
+ title: 'three',
+ id: 'three',
+ text: 'three',
+ },
+];
describe('CreateItemDropdown', () => {
preloadFixtures('static/create_item_dropdown.html.raw');
@@ -23,7 +27,8 @@ describe('CreateItemDropdown', () => {
function createItemAndClearInput(text) {
// Filter for the new item
- $wrapperEl.find('.dropdown-input-field')
+ $wrapperEl
+ .find('.dropdown-input-field')
.val(text)
.trigger('input');
@@ -32,7 +37,8 @@ describe('CreateItemDropdown', () => {
$createButton.click();
// Clear out the filter
- $wrapperEl.find('.dropdown-input-field')
+ $wrapperEl
+ .find('.dropdown-input-field')
.val('')
.trigger('input');
}
@@ -63,6 +69,7 @@ describe('CreateItemDropdown', () => {
$('.js-dropdown-menu-toggle').click();
const $itemEls = $wrapperEl.find('.js-dropdown-content a');
+
expect($itemEls.length).toEqual(DROPDOWN_ITEM_DATA.length);
});
});
@@ -84,7 +91,8 @@ describe('CreateItemDropdown', () => {
$('.js-dropdown-menu-toggle').click();
// Filter for the new item
- $wrapperEl.find('.dropdown-input-field')
+ $wrapperEl
+ .find('.dropdown-input-field')
.val(NEW_ITEM_TEXT)
.trigger('input');
});
@@ -106,6 +114,7 @@ describe('CreateItemDropdown', () => {
createItemAndClearInput(NEW_ITEM_TEXT);
const $itemEls = $wrapperEl.find('.js-dropdown-content a');
+
expect($itemEls.length).toEqual(1 + DROPDOWN_ITEM_DATA.length);
expect($($itemEls.get(DROPDOWN_ITEM_DATA.length)).text()).toEqual(NEW_ITEM_TEXT);
});
@@ -114,6 +123,7 @@ describe('CreateItemDropdown', () => {
createItemAndClearInput(DROPDOWN_ITEM_DATA[0].text);
const $itemEls = $wrapperEl.find('.js-dropdown-content a');
+
expect($itemEls.length).toEqual(DROPDOWN_ITEM_DATA.length);
});
});
@@ -137,16 +147,16 @@ describe('CreateItemDropdown', () => {
$('.js-dropdown-menu-toggle').click();
// Filter for an item
- filterInput
- .val('one')
- .trigger('input');
+ filterInput.val('one').trigger('input');
const $itemElsAfterFilter = $wrapperEl.find('.js-dropdown-content a');
+
expect($itemElsAfterFilter.length).toEqual(1);
createItemDropdown.clearDropdown();
const $itemElsAfterClear = $wrapperEl.find('.js-dropdown-content a');
+
expect($itemElsAfterClear.length).toEqual(0);
expect(filterInput.val()).toEqual('');
});
@@ -176,6 +186,7 @@ describe('CreateItemDropdown', () => {
createItemAndClearInput('new-item');
const $itemEls = $wrapperEl.find('.js-dropdown-content a');
+
expect($itemEls.length).toEqual(1 + DROPDOWN_ITEM_DATA.length);
expect($($itemEls[3]).text()).toEqual('new-item-text');
expect($wrapperEl.find('.dropdown-toggle-text').text()).toEqual('new-item-title');
diff --git a/spec/javascripts/create_merge_request_dropdown_spec.js b/spec/javascripts/create_merge_request_dropdown_spec.js
index b229765a8c5..00fe3f451f5 100644
--- a/spec/javascripts/create_merge_request_dropdown_spec.js
+++ b/spec/javascripts/create_merge_request_dropdown_spec.js
@@ -59,6 +59,7 @@ describe('CreateMergeRequestDropdown', () => {
expect(dropdown.createBranchPath).toBe(
`${TEST_HOST}/branches?branch_name=contains%23hash&issue=42`,
);
+
expect(dropdown.createMrPath).toBe(
`${TEST_HOST}/create_merge_request?branch_name=contains%23hash&ref=master`,
);
diff --git a/spec/javascripts/cycle_analytics/banner_spec.js b/spec/javascripts/cycle_analytics/banner_spec.js
index 2815bdba0c2..3ce2c3c4f06 100644
--- a/spec/javascripts/cycle_analytics/banner_spec.js
+++ b/spec/javascripts/cycle_analytics/banner_spec.js
@@ -17,19 +17,20 @@ describe('Cycle analytics banner', () => {
});
it('should render cycle analytics information', () => {
- expect(
- vm.$el.querySelector('h4').textContent.trim(),
- ).toEqual('Introducing Cycle Analytics');
+ expect(vm.$el.querySelector('h4').textContent.trim()).toEqual('Introducing Cycle Analytics');
expect(
- vm.$el.querySelector('p').textContent.trim().replace(/[\r\n]+/g, ' '),
- ).toContain('Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.');
- expect(
- vm.$el.querySelector('a').textContent.trim(),
- ).toEqual('Read more');
- expect(
- vm.$el.querySelector('a').getAttribute('href'),
- ).toEqual('path');
+ vm.$el
+ .querySelector('p')
+ .textContent.trim()
+ .replace(/[\r\n]+/g, ' '),
+ ).toContain(
+ 'Cycle Analytics gives an overview of how much time it takes to go from idea to production in your project.',
+ );
+
+ expect(vm.$el.querySelector('a').textContent.trim()).toEqual('Read more');
+
+ expect(vm.$el.querySelector('a').getAttribute('href')).toEqual('path');
});
it('should emit an event when close button is clicked', () => {
diff --git a/spec/javascripts/datetime_utility_spec.js b/spec/javascripts/datetime_utility_spec.js
deleted file mode 100644
index 492171684dc..00000000000
--- a/spec/javascripts/datetime_utility_spec.js
+++ /dev/null
@@ -1,170 +0,0 @@
-import * as datetimeUtility from '~/lib/utils/datetime_utility';
-
-describe('Date time utils', () => {
- describe('timeFor', () => {
- it('returns `past due` when in past', () => {
- const date = new Date();
- date.setFullYear(date.getFullYear() - 1);
-
- expect(
- datetimeUtility.timeFor(date),
- ).toBe('Past due');
- });
-
- it('returns remaining time when in the future', () => {
- const date = new Date();
- date.setFullYear(date.getFullYear() + 1);
-
- // Add a day to prevent a transient error. If date is even 1 second
- // short of a full year, timeFor will return '11 months remaining'
- date.setDate(date.getDate() + 1);
-
- expect(
- datetimeUtility.timeFor(date),
- ).toBe('1 year remaining');
- });
- });
-
- describe('get day name', () => {
- it('should return Sunday', () => {
- const day = datetimeUtility.getDayName(new Date('07/17/2016'));
- expect(day).toBe('Sunday');
- });
-
- it('should return Monday', () => {
- const day = datetimeUtility.getDayName(new Date('07/18/2016'));
- expect(day).toBe('Monday');
- });
-
- it('should return Tuesday', () => {
- const day = datetimeUtility.getDayName(new Date('07/19/2016'));
- expect(day).toBe('Tuesday');
- });
-
- it('should return Wednesday', () => {
- const day = datetimeUtility.getDayName(new Date('07/20/2016'));
- expect(day).toBe('Wednesday');
- });
-
- it('should return Thursday', () => {
- const day = datetimeUtility.getDayName(new Date('07/21/2016'));
- expect(day).toBe('Thursday');
- });
-
- it('should return Friday', () => {
- const day = datetimeUtility.getDayName(new Date('07/22/2016'));
- expect(day).toBe('Friday');
- });
-
- it('should return Saturday', () => {
- const day = datetimeUtility.getDayName(new Date('07/23/2016'));
- expect(day).toBe('Saturday');
- });
- });
-
- describe('get day difference', () => {
- it('should return 7', () => {
- const firstDay = new Date('07/01/2016');
- const secondDay = new Date('07/08/2016');
- const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
- expect(difference).toBe(7);
- });
-
- it('should return 31', () => {
- const firstDay = new Date('07/01/2016');
- const secondDay = new Date('08/01/2016');
- const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
- expect(difference).toBe(31);
- });
-
- it('should return 365', () => {
- const firstDay = new Date('07/02/2015');
- const secondDay = new Date('07/01/2016');
- const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
- expect(difference).toBe(365);
- });
- });
-});
-
-describe('timeIntervalInWords', () => {
- it('should return string with number of minutes and seconds', () => {
- expect(datetimeUtility.timeIntervalInWords(9.54)).toEqual('9 seconds');
- expect(datetimeUtility.timeIntervalInWords(1)).toEqual('1 second');
- expect(datetimeUtility.timeIntervalInWords(200)).toEqual('3 minutes 20 seconds');
- expect(datetimeUtility.timeIntervalInWords(6008)).toEqual('100 minutes 8 seconds');
- });
-});
-
-describe('dateInWords', () => {
- const date = new Date('07/01/2016');
-
- it('should return date in words', () => {
- expect(datetimeUtility.dateInWords(date)).toEqual('July 1, 2016');
- });
-
- it('should return abbreviated month name', () => {
- expect(datetimeUtility.dateInWords(date, true)).toEqual('Jul 1, 2016');
- });
-
- it('should return date in words without year', () => {
- expect(datetimeUtility.dateInWords(date, true, true)).toEqual('Jul 1');
- });
-});
-
-describe('monthInWords', () => {
- const date = new Date('2017-01-20');
-
- it('returns month name from provided date', () => {
- expect(datetimeUtility.monthInWords(date)).toBe('January');
- });
-
- it('returns abbreviated month name from provided date', () => {
- expect(datetimeUtility.monthInWords(date, true)).toBe('Jan');
- });
-});
-
-describe('totalDaysInMonth', () => {
- it('returns number of days in a month for given date', () => {
- // 1st Feb, 2016 (leap year)
- expect(datetimeUtility.totalDaysInMonth(new Date(2016, 1, 1))).toBe(29);
-
- // 1st Feb, 2017
- expect(datetimeUtility.totalDaysInMonth(new Date(2017, 1, 1))).toBe(28);
-
- // 1st Jan, 2017
- expect(datetimeUtility.totalDaysInMonth(new Date(2017, 0, 1))).toBe(31);
- });
-});
-
-describe('getSundays', () => {
- it('returns array of dates representing all Sundays of the month', () => {
- // December, 2017 (it has 5 Sundays)
- const dateOfSundays = [3, 10, 17, 24, 31];
- const sundays = datetimeUtility.getSundays(new Date(2017, 11, 1));
-
- expect(sundays.length).toBe(5);
- sundays.forEach((sunday, index) => {
- expect(sunday.getDate()).toBe(dateOfSundays[index]);
- });
- });
-});
-
-describe('getTimeframeWindowFrom', () => {
- it('returns array of date objects upto provided length start with provided startDate', () => {
- const startDate = new Date(2018, 0, 1);
- const mockTimeframe = [
- new Date(2018, 0, 1),
- new Date(2018, 1, 1),
- new Date(2018, 2, 1),
- new Date(2018, 3, 1),
- new Date(2018, 4, 31),
- ];
- const timeframe = datetimeUtility.getTimeframeWindowFrom(startDate, 5);
- expect(timeframe.length).toBe(5);
- timeframe.forEach((timeframeItem, index) => {
- expect(timeframeItem.getFullYear() === mockTimeframe[index].getFullYear()).toBe(true);
- expect(timeframeItem.getMonth() === mockTimeframe[index].getMonth()).toBe(true);
- expect(timeframeItem.getDate() === mockTimeframe[index].getDate()).toBeTruthy();
- });
- });
-});
diff --git a/spec/javascripts/deploy_keys/components/app_spec.js b/spec/javascripts/deploy_keys/components/app_spec.js
index cd147bb2935..f81c0cb7124 100644
--- a/spec/javascripts/deploy_keys/components/app_spec.js
+++ b/spec/javascripts/deploy_keys/components/app_spec.js
@@ -10,7 +10,7 @@ describe('Deploy keys app component', () => {
let vm;
let mock;
- beforeEach((done) => {
+ beforeEach(done => {
// set up axios mock before component
mock = new MockAdapter(axios);
mock.onGet(`${TEST_HOST}/dummy/`).replyOnce(200, data);
@@ -60,6 +60,7 @@ describe('Deploy keys app component', () => {
expect(textContent('.js-deployKeys-tab-available_project_keys')).toContain(
'Privately accessible deploy keys',
);
+
expect(textContent('.js-deployKeys-tab-public_keys')).toContain(
'Publicly accessible deploy keys',
);
@@ -67,9 +68,11 @@ describe('Deploy keys app component', () => {
expect(textContent('.js-deployKeys-tab-enabled_keys .badge')).toBe(
`${vm.store.keys.enabled_keys.length}`,
);
+
expect(textContent('.js-deployKeys-tab-available_project_keys .badge')).toBe(
`${vm.store.keys.available_project_keys.length}`,
);
+
expect(textContent('.js-deployKeys-tab-public_keys .badge')).toBe(
`${vm.store.keys.public_keys.length}`,
);
diff --git a/spec/javascripts/deploy_keys/components/key_spec.js b/spec/javascripts/deploy_keys/components/key_spec.js
index d1de9d132b8..7117dc4a9ee 100644
--- a/spec/javascripts/deploy_keys/components/key_spec.js
+++ b/spec/javascripts/deploy_keys/components/key_spec.js
@@ -82,6 +82,7 @@ describe('Deploy keys key', () => {
it('shows expandable button if more than two projects', () => {
const labels = vm.$el.querySelectorAll('.deploy-project-label');
+
expect(labels.length).toBe(2);
expect(labels[1].textContent).toContain('others');
expect(labels[1].getAttribute('data-original-title')).toContain('Expand');
@@ -93,6 +94,7 @@ describe('Deploy keys key', () => {
Vue.nextTick(() => {
const labels = vm.$el.querySelectorAll('.deploy-project-label');
+
expect(labels.length).toBe(length);
expect(labels[1].textContent).not.toContain(`+${length} others`);
expect(labels[1].getAttribute('data-original-title')).not.toContain('Expand');
@@ -105,6 +107,7 @@ describe('Deploy keys key', () => {
Vue.nextTick(() => {
const labels = vm.$el.querySelectorAll('.deploy-project-label');
+
expect(labels.length).toBe(2);
expect(labels[1].textContent).toContain(
vm.deployKey.deploy_keys_projects[1].project.full_name,
diff --git a/spec/javascripts/diff_comments_store_spec.js b/spec/javascripts/diff_comments_store_spec.js
index d6fc6b56b82..a6d363ce88e 100644
--- a/spec/javascripts/diff_comments_store_spec.js
+++ b/spec/javascripts/diff_comments_store_spec.js
@@ -1,4 +1,4 @@
-/* eslint-disable jasmine/no-global-setup, dot-notation, jasmine/no-expect-in-setup-teardown, max-len */
+/* eslint-disable jasmine/no-global-setup, dot-notation, jasmine/no-expect-in-setup-teardown */
/* global CommentsStore */
import '~/diff_notes/models/discussion';
@@ -26,6 +26,7 @@ describe('New discussion', () => {
it('creates new discussion', () => {
expect(Object.keys(CommentsStore.state).length).toBe(0);
createDiscussion();
+
expect(Object.keys(CommentsStore.state).length).toBe(1);
});
@@ -34,6 +35,7 @@ describe('New discussion', () => {
createDiscussion(2);
const discussion = CommentsStore.state['a'];
+
expect(Object.keys(discussion.notes).length).toBe(2);
});
});
@@ -46,6 +48,7 @@ describe('Get note', () => {
it('gets note by ID', () => {
const note = CommentsStore.get('a', 1);
+
expect(note).toBeDefined();
expect(note.id).toBe(1);
});
@@ -59,17 +62,20 @@ describe('Delete discussion', () => {
it('deletes discussion by ID', () => {
CommentsStore.delete('a', 1);
+
expect(Object.keys(CommentsStore.state).length).toBe(0);
});
it('deletes discussion when no more notes', () => {
createDiscussion();
createDiscussion(2);
+
expect(Object.keys(CommentsStore.state).length).toBe(1);
expect(Object.keys(CommentsStore.state['a'].notes).length).toBe(2);
CommentsStore.delete('a', 1);
CommentsStore.delete('a', 2);
+
expect(Object.keys(CommentsStore.state).length).toBe(0);
});
});
@@ -84,6 +90,7 @@ describe('Update note', () => {
CommentsStore.update('a', 1, false, 'test');
const note = CommentsStore.get('a', 1);
+
expect(note.resolved).toBe(false);
});
});
@@ -96,6 +103,7 @@ describe('Discussion resolved', () => {
it('is resolved with single note', () => {
const discussion = CommentsStore.state['a'];
+
expect(discussion.isResolved()).toBe(true);
});
@@ -118,6 +126,7 @@ describe('Discussion resolved', () => {
createDiscussion(2, false);
discussion.resolveAllNotes();
+
expect(discussion.isResolved()).toBe(true);
});
@@ -126,6 +135,7 @@ describe('Discussion resolved', () => {
createDiscussion(2);
discussion.unResolveAllNotes();
+
expect(discussion.isResolved()).toBe(false);
});
});
diff --git a/spec/javascripts/diffs/components/app_spec.js b/spec/javascripts/diffs/components/app_spec.js
index 7be44a26ded..1e2f7ff4fd8 100644
--- a/spec/javascripts/diffs/components/app_spec.js
+++ b/spec/javascripts/diffs/components/app_spec.js
@@ -13,6 +13,8 @@ describe('diffs/components/app', () => {
beforeEach(() => {
// setup globals (needed for component to mount :/)
window.mrTabs = jasmine.createSpyObj('mrTabs', ['resetViewContainer']);
+ window.mrTabs.expandViewContainer = jasmine.createSpy();
+ window.location.hash = 'ABC_123';
// setup component
const store = createDiffsStore();
@@ -36,34 +38,16 @@ describe('diffs/components/app', () => {
vm.$destroy();
});
- it('shows comments message, with commit', done => {
- vm.$store.state.diffs.commit = {};
-
- vm.$nextTick()
- .then(() => {
- expect(vm.$el).toContainText('Only comments from the following commit are shown below');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('shows comments message, with old mergeRequestDiff', done => {
- vm.$store.state.diffs.mergeRequestDiff = { latest: false };
-
- vm.$nextTick()
- .then(() => {
- expect(vm.$el).toContainText("Not all comments are displayed because you're viewing an old version of the diff.");
- })
- .then(done)
- .catch(done.fail);
+ it('does not show commit info', () => {
+ expect(vm.$el).not.toContainElement('.blob-commit-info');
});
- it('shows comments message, with startVersion', done => {
- vm.$store.state.diffs.startVersion = 'test';
+ it('sets highlighted row if hash exists in location object', done => {
+ vm.$props.shouldShow = true;
vm.$nextTick()
.then(() => {
- expect(vm.$el).toContainText("Not all comments are displayed because you're comparing two versions of the diff.");
+ expect(vm.$store.state.diffs.highlightedRow).toBe('ABC_123');
})
.then(done)
.catch(done.fail);
diff --git a/spec/javascripts/diffs/components/changed_files_spec.js b/spec/javascripts/diffs/components/changed_files_spec.js
deleted file mode 100644
index 7f21273a991..00000000000
--- a/spec/javascripts/diffs/components/changed_files_spec.js
+++ /dev/null
@@ -1,105 +0,0 @@
-import Vue from 'vue';
-import Vuex from 'vuex';
-import { mountComponentWithStore } from 'spec/helpers';
-import diffsModule from '~/diffs/store/modules';
-import changedFiles from '~/diffs/components/changed_files.vue';
-
-describe('ChangedFiles', () => {
- const Component = Vue.extend(changedFiles);
- const store = new Vuex.Store({
- modules: {
- diffs: diffsModule(),
- },
- });
-
- let vm;
-
- beforeEach(() => {
- setFixtures(`
- <div id="dummy-element"></div>
- <div class="js-tabs-affix"></div>
- `);
-
- const props = {
- diffFiles: [
- {
- addedLines: 10,
- removedLines: 20,
- blob: {
- path: 'some/code.txt',
- },
- filePath: 'some/code.txt',
- },
- ],
- };
-
- vm = mountComponentWithStore(Component, { props, store });
- });
-
- describe('with single file added', () => {
- it('shows files changes', () => {
- expect(vm.$el).toContainText('1 changed file');
- });
-
- it('shows file additions and deletions', () => {
- expect(vm.$el).toContainText('10 additions');
- expect(vm.$el).toContainText('20 deletions');
- });
- });
-
- describe('diff view mode buttons', () => {
- let inlineButton;
- let parallelButton;
-
- beforeEach(() => {
- inlineButton = vm.$el.querySelector('.js-inline-diff-button');
- parallelButton = vm.$el.querySelector('.js-parallel-diff-button');
- });
-
- it('should have Inline and Side-by-side buttons', () => {
- expect(inlineButton).toBeDefined();
- expect(parallelButton).toBeDefined();
- });
-
- it('should add active class to Inline button', done => {
- vm.$store.state.diffs.diffViewType = 'inline';
-
- vm.$nextTick(() => {
- expect(inlineButton.classList.contains('active')).toEqual(true);
- expect(parallelButton.classList.contains('active')).toEqual(false);
-
- done();
- });
- });
-
- it('should toggle active state of buttons when diff view type changed', done => {
- vm.$store.state.diffs.diffViewType = 'parallel';
-
- vm.$nextTick(() => {
- expect(inlineButton.classList.contains('active')).toEqual(false);
- expect(parallelButton.classList.contains('active')).toEqual(true);
-
- done();
- });
- });
-
- describe('clicking them', () => {
- it('should toggle the diff view type', done => {
- parallelButton.click();
-
- vm.$nextTick(() => {
- expect(inlineButton.classList.contains('active')).toEqual(false);
- expect(parallelButton.classList.contains('active')).toEqual(true);
-
- inlineButton.click();
-
- vm.$nextTick(() => {
- expect(inlineButton.classList.contains('active')).toEqual(true);
- expect(parallelButton.classList.contains('active')).toEqual(false);
- done();
- });
- });
- });
- });
- });
-});
diff --git a/spec/javascripts/diffs/components/commit_item_spec.js b/spec/javascripts/diffs/components/commit_item_spec.js
new file mode 100644
index 00000000000..8b2ca6506c4
--- /dev/null
+++ b/spec/javascripts/diffs/components/commit_item_spec.js
@@ -0,0 +1,164 @@
+import Vue from 'vue';
+import { TEST_HOST } from 'spec/test_constants';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import { trimText } from 'spec/helpers/vue_component_helper';
+import { getTimeago } from '~/lib/utils/datetime_utility';
+import CommitItem from '~/diffs/components/commit_item.vue';
+import getDiffWithCommit from '../mock_data/diff_with_commit';
+
+const TEST_AUTHOR_NAME = 'test';
+const TEST_AUTHOR_EMAIL = 'test+test@gitlab.com';
+const TEST_AUTHOR_GRAVATAR = `${TEST_HOST}/avatar/test?s=36`;
+const TEST_SIGNATURE_HTML = '<a>Legit commit</a>';
+const TEST_PIPELINE_STATUS_PATH = `${TEST_HOST}/pipeline/status`;
+
+const getTitleElement = vm => vm.$el.querySelector('.commit-row-message.item-title');
+const getDescElement = vm => vm.$el.querySelector('pre.commit-row-description');
+const getDescExpandElement = vm =>
+ vm.$el.querySelector('.commit-content .text-expander.js-toggle-button');
+const getShaElement = vm => vm.$el.querySelector('.commit-sha-group');
+const getAvatarElement = vm => vm.$el.querySelector('.user-avatar-link');
+const getCommitterElement = vm => vm.$el.querySelector('.commiter');
+const getCommitActionsElement = vm => vm.$el.querySelector('.commit-actions');
+
+describe('diffs/components/commit_item', () => {
+ const Component = Vue.extend(CommitItem);
+ const timeago = getTimeago();
+ const { commit } = getDiffWithCommit();
+
+ let vm;
+
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ commit: getDiffWithCommit().commit,
+ });
+ });
+
+ it('renders commit title', () => {
+ const titleElement = getTitleElement(vm);
+
+ expect(titleElement).toHaveAttr('href', commit.commit_url);
+ expect(titleElement).toHaveText(commit.title_html);
+ });
+
+ it('renders commit description', () => {
+ const descElement = getDescElement(vm);
+ const descExpandElement = getDescExpandElement(vm);
+
+ const expected = commit.description_html.replace(/&#x000A;/g, '');
+
+ expect(trimText(descElement.innerHTML)).toEqual(trimText(expected));
+ expect(descExpandElement).not.toBeNull();
+ });
+
+ it('renders commit sha', () => {
+ const shaElement = getShaElement(vm);
+ const labelElement = shaElement.querySelector('.label');
+ const buttonElement = shaElement.querySelector('button');
+
+ expect(labelElement.textContent).toEqual(commit.short_id);
+ expect(buttonElement).toHaveData('clipboard-text', commit.id);
+ });
+
+ it('renders author avatar', () => {
+ const avatarElement = getAvatarElement(vm);
+ const imgElement = avatarElement.querySelector('img');
+
+ expect(avatarElement).toHaveAttr('href', commit.author.web_url);
+ expect(imgElement).toHaveClass('s36');
+ expect(imgElement).toHaveAttr('alt', commit.author.name);
+ expect(imgElement).toHaveAttr('src', commit.author.avatar_url);
+ });
+
+ it('renders committer text', () => {
+ const committerElement = getCommitterElement(vm);
+ const nameElement = committerElement.querySelector('a');
+
+ const expectTimeText = timeago.format(commit.authored_date);
+ const expectedText = `${commit.author.name} authored ${expectTimeText}`;
+
+ expect(trimText(committerElement.textContent)).toEqual(expectedText);
+ expect(nameElement).toHaveAttr('href', commit.author.web_url);
+ expect(nameElement).toHaveText(commit.author.name);
+ });
+
+ describe('without commit description', () => {
+ beforeEach(done => {
+ vm.commit.description_html = '';
+
+ vm.$nextTick()
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('hides description', () => {
+ const descElement = getDescElement(vm);
+ const descExpandElement = getDescExpandElement(vm);
+
+ expect(descElement).toBeNull();
+ expect(descExpandElement).toBeNull();
+ });
+ });
+
+ describe('with no matching user', () => {
+ beforeEach(done => {
+ vm.commit.author = null;
+ vm.commit.author_email = TEST_AUTHOR_EMAIL;
+ vm.commit.author_name = TEST_AUTHOR_NAME;
+ vm.commit.author_gravatar_url = TEST_AUTHOR_GRAVATAR;
+
+ vm.$nextTick()
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('renders author avatar', () => {
+ const avatarElement = getAvatarElement(vm);
+ const imgElement = avatarElement.querySelector('img');
+
+ expect(avatarElement).toHaveAttr('href', `mailto:${TEST_AUTHOR_EMAIL}`);
+ expect(imgElement).toHaveAttr('alt', TEST_AUTHOR_NAME);
+ expect(imgElement).toHaveAttr('src', TEST_AUTHOR_GRAVATAR);
+ });
+
+ it('renders committer text', () => {
+ const committerElement = getCommitterElement(vm);
+ const nameElement = committerElement.querySelector('a');
+
+ expect(nameElement).toHaveAttr('href', `mailto:${TEST_AUTHOR_EMAIL}`);
+ expect(nameElement).toHaveText(TEST_AUTHOR_NAME);
+ });
+ });
+
+ describe('with signature', () => {
+ beforeEach(done => {
+ vm.commit.signature_html = TEST_SIGNATURE_HTML;
+
+ vm.$nextTick()
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('renders signature html', () => {
+ const actionsElement = getCommitActionsElement(vm);
+
+ expect(actionsElement).toContainHtml(TEST_SIGNATURE_HTML);
+ });
+ });
+
+ describe('with pipeline status', () => {
+ beforeEach(done => {
+ vm.commit.pipeline_status_path = TEST_PIPELINE_STATUS_PATH;
+
+ vm.$nextTick()
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('renders pipeline status', () => {
+ const actionsElement = getCommitActionsElement(vm);
+
+ expect(actionsElement).toContainElement('.ci-status-link');
+ });
+ });
+});
diff --git a/spec/javascripts/diffs/components/commit_widget_spec.js b/spec/javascripts/diffs/components/commit_widget_spec.js
new file mode 100644
index 00000000000..2b60bd232ed
--- /dev/null
+++ b/spec/javascripts/diffs/components/commit_widget_spec.js
@@ -0,0 +1,24 @@
+import Vue from 'vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import CommitWidget from '~/diffs/components/commit_widget.vue';
+import getDiffWithCommit from '../mock_data/diff_with_commit';
+
+describe('diffs/components/commit_widget', () => {
+ const Component = Vue.extend(CommitWidget);
+ const { commit } = getDiffWithCommit();
+
+ let vm;
+
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ commit: getDiffWithCommit().commit,
+ });
+ });
+
+ it('renders commit item', () => {
+ const commitElement = vm.$el.querySelector('li.commit');
+
+ expect(commitElement).not.toBeNull();
+ expect(commitElement).toContainText(commit.short_id);
+ });
+});
diff --git a/spec/javascripts/diffs/components/compare_versions_spec.js b/spec/javascripts/diffs/components/compare_versions_spec.js
index 7237274eb43..75c66e9ca82 100644
--- a/spec/javascripts/diffs/components/compare_versions_spec.js
+++ b/spec/javascripts/diffs/components/compare_versions_spec.js
@@ -1 +1,146 @@
-// TODO: https://gitlab.com/gitlab-org/gitlab-ce/issues/48034
+import Vue from 'vue';
+import CompareVersionsComponent from '~/diffs/components/compare_versions.vue';
+import store from '~/mr_notes/stores';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import diffsMockData from '../mock_data/merge_request_diffs';
+import getDiffWithCommit from '../mock_data/diff_with_commit';
+
+describe('CompareVersions', () => {
+ let vm;
+ const targetBranch = { branchName: 'tmp-wine-dev', versionIndex: -1 };
+
+ beforeEach(() => {
+ vm = createComponentWithStore(Vue.extend(CompareVersionsComponent), store, {
+ mergeRequestDiffs: diffsMockData,
+ mergeRequestDiff: diffsMockData[0],
+ targetBranch,
+ }).$mount();
+ });
+
+ describe('template', () => {
+ it('should render Tree List toggle button with correct attribute values', () => {
+ const treeListBtn = vm.$el.querySelector('.js-toggle-tree-list');
+
+ expect(treeListBtn).not.toBeNull();
+ expect(treeListBtn.dataset.originalTitle).toBe('Toggle file browser');
+ expect(treeListBtn.querySelectorAll('svg use').length).not.toBe(0);
+ expect(treeListBtn.querySelector('svg use').getAttribute('xlink:href')).toContain(
+ '#hamburger',
+ );
+ });
+
+ it('should render comparison dropdowns with correct values', () => {
+ const sourceDropdown = vm.$el.querySelector('.mr-version-dropdown');
+ const targetDropdown = vm.$el.querySelector('.mr-version-compare-dropdown');
+
+ expect(sourceDropdown).not.toBeNull();
+ expect(targetDropdown).not.toBeNull();
+ expect(sourceDropdown.querySelector('a span').innerHTML).toContain('latest version');
+ expect(targetDropdown.querySelector('a span').innerHTML).toContain(targetBranch.branchName);
+ });
+
+ it('should not render comparison dropdowns if no mergeRequestDiffs are specified', () => {
+ vm.mergeRequestDiffs = [];
+
+ vm.$nextTick(() => {
+ const sourceDropdown = vm.$el.querySelector('.mr-version-dropdown');
+ const targetDropdown = vm.$el.querySelector('.mr-version-compare-dropdown');
+
+ expect(sourceDropdown).toBeNull();
+ expect(targetDropdown).toBeNull();
+ });
+ });
+
+ it('should render whitespace toggle button with correct attributes', () => {
+ const whitespaceBtn = vm.$el.querySelector('.qa-toggle-whitespace');
+ const href = vm.toggleWhitespacePath;
+
+ expect(whitespaceBtn).not.toBeNull();
+ expect(whitespaceBtn.getAttribute('href')).toEqual(href);
+ expect(whitespaceBtn.innerHTML).toContain('Hide whitespace changes');
+ });
+
+ it('should render view types buttons with correct values', () => {
+ const inlineBtn = vm.$el.querySelector('#inline-diff-btn');
+ const parallelBtn = vm.$el.querySelector('#parallel-diff-btn');
+
+ expect(inlineBtn).not.toBeNull();
+ expect(parallelBtn).not.toBeNull();
+ expect(inlineBtn.dataset.viewType).toEqual('inline');
+ expect(parallelBtn.dataset.viewType).toEqual('parallel');
+ expect(inlineBtn.innerHTML).toContain('Inline');
+ expect(parallelBtn.innerHTML).toContain('Side-by-side');
+ });
+ });
+
+ describe('setInlineDiffViewType', () => {
+ it('should persist the view type in the url', () => {
+ const viewTypeBtn = vm.$el.querySelector('#inline-diff-btn');
+ viewTypeBtn.click();
+
+ expect(window.location.toString()).toContain('?view=inline');
+ });
+ });
+
+ describe('setParallelDiffViewType', () => {
+ it('should persist the view type in the url', () => {
+ const viewTypeBtn = vm.$el.querySelector('#parallel-diff-btn');
+ viewTypeBtn.click();
+
+ expect(window.location.toString()).toContain('?view=parallel');
+ });
+ });
+
+ describe('comparableDiffs', () => {
+ it('should not contain the first item in the mergeRequestDiffs property', () => {
+ const { comparableDiffs } = vm;
+ const comparableDiffsMock = diffsMockData.slice(1);
+
+ expect(comparableDiffs).toEqual(comparableDiffsMock);
+ });
+ });
+
+ describe('isWhitespaceVisible', () => {
+ const originalHref = window.location.href;
+
+ afterEach(() => {
+ window.history.replaceState({}, null, originalHref);
+ });
+
+ it('should return "true" when no "w" flag is present in the URL (default)', () => {
+ expect(vm.isWhitespaceVisible()).toBe(true);
+ });
+
+ it('should return "false" when the flag is set to "1" in the URL', () => {
+ window.history.replaceState({}, null, '?w=1');
+
+ expect(vm.isWhitespaceVisible()).toBe(false);
+ });
+
+ it('should return "true" when the flag is set to "0" in the URL', () => {
+ window.history.replaceState({}, null, '?w=0');
+
+ expect(vm.isWhitespaceVisible()).toBe(true);
+ });
+ });
+
+ describe('commit', () => {
+ beforeEach(done => {
+ vm.$store.state.diffs.commit = getDiffWithCommit().commit;
+ vm.mergeRequestDiffs = [];
+
+ vm.$nextTick(done);
+ });
+
+ it('renders latest version button', () => {
+ expect(vm.$el.querySelector('.js-latest-version').textContent.trim()).toBe(
+ 'Show latest version',
+ );
+ });
+
+ it('renders short commit ID', () => {
+ expect(vm.$el.textContent).toContain('Viewing commit');
+ expect(vm.$el.textContent).toContain(vm.commit.short_id);
+ });
+ });
+});
diff --git a/spec/javascripts/diffs/components/diff_content_spec.js b/spec/javascripts/diffs/components/diff_content_spec.js
index dea600a783a..c25f6167163 100644
--- a/spec/javascripts/diffs/components/diff_content_spec.js
+++ b/spec/javascripts/diffs/components/diff_content_spec.js
@@ -1,20 +1,28 @@
import Vue from 'vue';
import DiffContentComponent from '~/diffs/components/diff_content.vue';
-import store from '~/mr_notes/stores';
+import { createStore } from '~/mr_notes/stores';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { GREEN_BOX_IMAGE_URL, RED_BOX_IMAGE_URL } from 'spec/test_constants';
+import '~/behaviors/markdown/render_gfm';
import diffFileMockData from '../mock_data/diff_file';
+import discussionsMockData from '../mock_data/diff_discussions';
describe('DiffContent', () => {
const Component = Vue.extend(DiffContentComponent);
let vm;
- const getDiffFileMock = () => Object.assign({}, diffFileMockData);
beforeEach(() => {
+ const store = createStore();
+ store.state.notes.noteableData = {
+ current_user: {
+ can_create_note: false,
+ },
+ };
+
vm = mountComponentWithStore(Component, {
store,
props: {
- diffFile: getDiffFileMock(),
+ diffFile: JSON.parse(JSON.stringify(diffFileMockData)),
},
});
});
@@ -43,25 +51,61 @@ describe('DiffContent', () => {
describe('Non-Text diffs', () => {
beforeEach(() => {
- vm.diffFile.text = false;
+ vm.diffFile.viewer.name = 'image';
});
describe('image diff', () => {
- beforeEach(() => {
- vm.diffFile.newPath = GREEN_BOX_IMAGE_URL;
- vm.diffFile.newSha = 'DEF';
- vm.diffFile.oldPath = RED_BOX_IMAGE_URL;
- vm.diffFile.oldSha = 'ABC';
- vm.diffFile.viewPath = '';
+ beforeEach(done => {
+ vm.diffFile.new_path = GREEN_BOX_IMAGE_URL;
+ vm.diffFile.new_sha = 'DEF';
+ vm.diffFile.old_path = RED_BOX_IMAGE_URL;
+ vm.diffFile.old_sha = 'ABC';
+ vm.diffFile.view_path = '';
+ vm.diffFile.discussions = [{ ...discussionsMockData }];
+ vm.$store.state.diffs.commentForms.push({
+ fileHash: vm.diffFile.file_hash,
+ x: 10,
+ y: 20,
+ width: 100,
+ height: 200,
+ });
+
+ vm.$nextTick(done);
});
- it('should have image diff view in place', done => {
- vm.$nextTick(() => {
- expect(vm.$el.querySelectorAll('.js-diff-inline-view').length).toEqual(0);
+ it('should have image diff view in place', () => {
+ expect(vm.$el.querySelectorAll('.js-diff-inline-view').length).toEqual(0);
- expect(vm.$el.querySelectorAll('.diff-viewer .image').length).toEqual(1);
+ expect(vm.$el.querySelectorAll('.diff-viewer .image').length).toEqual(1);
+ });
- done();
+ it('renders image diff overlay', () => {
+ expect(vm.$el.querySelector('.image-diff-overlay')).not.toBe(null);
+ });
+
+ it('renders diff file discussions', () => {
+ expect(vm.$el.querySelectorAll('.discussion .note.timeline-entry').length).toEqual(5);
+ });
+
+ describe('handleSaveNote', () => {
+ it('dispatches handleSaveNote', () => {
+ spyOn(vm.$store, 'dispatch').and.stub();
+
+ vm.handleSaveNote('test');
+
+ expect(vm.$store.dispatch).toHaveBeenCalledWith('diffs/saveDiffDiscussion', {
+ note: 'test',
+ formData: {
+ noteableData: jasmine.anything(),
+ noteableType: jasmine.anything(),
+ diffFile: vm.diffFile,
+ positionType: 'image',
+ x: 10,
+ y: 20,
+ width: 100,
+ height: 200,
+ },
+ });
});
});
});
@@ -69,10 +113,10 @@ describe('DiffContent', () => {
describe('file diff', () => {
it('should have download buttons in place', done => {
const el = vm.$el;
- vm.diffFile.newPath = 'test.abc';
- vm.diffFile.newSha = 'DEF';
- vm.diffFile.oldPath = 'test.abc';
- vm.diffFile.oldSha = 'ABC';
+ vm.diffFile.new_path = 'test.abc';
+ vm.diffFile.new_sha = 'DEF';
+ vm.diffFile.old_path = 'test.abc';
+ vm.diffFile.old_sha = 'ABC';
vm.$nextTick(() => {
expect(el.querySelectorAll('.js-diff-inline-view').length).toEqual(0);
diff --git a/spec/javascripts/diffs/components/diff_discussions_spec.js b/spec/javascripts/diffs/components/diff_discussions_spec.js
index 270f363825f..0bc9da5ad0f 100644
--- a/spec/javascripts/diffs/components/diff_discussions_spec.js
+++ b/spec/javascripts/diffs/components/diff_discussions_spec.js
@@ -1,24 +1,90 @@
import Vue from 'vue';
import DiffDiscussions from '~/diffs/components/diff_discussions.vue';
-import store from '~/mr_notes/stores';
+import { createStore } from '~/mr_notes/stores';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import '~/behaviors/markdown/render_gfm';
import discussionsMockData from '../mock_data/diff_discussions';
describe('DiffDiscussions', () => {
- let component;
+ let vm;
const getDiscussionsMockData = () => [Object.assign({}, discussionsMockData)];
- beforeEach(() => {
- component = createComponentWithStore(Vue.extend(DiffDiscussions), store, {
+ function createComponent(props = {}) {
+ const store = createStore();
+
+ vm = createComponentWithStore(Vue.extend(DiffDiscussions), store, {
discussions: getDiscussionsMockData(),
+ ...props,
}).$mount();
+ }
+
+ afterEach(() => {
+ vm.$destroy();
});
describe('template', () => {
it('should have notes list', () => {
- const { $el } = component;
+ createComponent();
+
+ expect(vm.$el.querySelectorAll('.discussion .note.timeline-entry').length).toEqual(5);
+ });
+ });
+
+ describe('image commenting', () => {
+ it('renders collapsible discussion button', () => {
+ createComponent({ shouldCollapseDiscussions: true });
+
+ expect(vm.$el.querySelector('.js-diff-notes-toggle')).not.toBe(null);
+ expect(vm.$el.querySelector('.js-diff-notes-toggle svg')).not.toBe(null);
+ expect(vm.$el.querySelector('.js-diff-notes-toggle').classList).toContain(
+ 'diff-notes-collapse',
+ );
+ });
+
+ it('dispatches toggleDiscussion when clicking collapse button', () => {
+ createComponent({ shouldCollapseDiscussions: true });
+
+ spyOn(vm.$store, 'dispatch').and.stub();
+
+ vm.$el.querySelector('.js-diff-notes-toggle').click();
+
+ expect(vm.$store.dispatch).toHaveBeenCalledWith('toggleDiscussion', {
+ discussionId: vm.discussions[0].id,
+ });
+ });
+
+ it('renders expand button when discussion is collapsed', done => {
+ createComponent({ shouldCollapseDiscussions: true });
+
+ vm.discussions[0].expanded = false;
+
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.js-diff-notes-toggle').textContent.trim()).toBe('1');
+ expect(vm.$el.querySelector('.js-diff-notes-toggle').className).toContain(
+ 'btn-transparent badge badge-pill',
+ );
+
+ done();
+ });
+ });
+
+ it('hides discussion when collapsed', done => {
+ createComponent({ shouldCollapseDiscussions: true });
+
+ vm.discussions[0].expanded = false;
+
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.note-discussion').style.display).toBe('none');
+
+ done();
+ });
+ });
+
+ it('renders badge on avatar', () => {
+ createComponent({ renderAvatarBadge: true, discussions: [{ ...discussionsMockData }] });
- expect($el.querySelectorAll('.discussion .note.timeline-entry').length).toEqual(5);
+ expect(vm.$el.querySelector('.user-avatar-link .badge-pill')).not.toBe(null);
+ expect(vm.$el.querySelector('.user-avatar-link .badge-pill').textContent.trim()).toBe('1');
});
});
});
diff --git a/spec/javascripts/diffs/components/diff_file_header_spec.js b/spec/javascripts/diffs/components/diff_file_header_spec.js
index c986ea604b2..b77907ff26f 100644
--- a/spec/javascripts/diffs/components/diff_file_header_spec.js
+++ b/spec/javascripts/diffs/components/diff_file_header_spec.js
@@ -3,9 +3,10 @@ import Vuex from 'vuex';
import diffsModule from '~/diffs/store/modules';
import notesModule from '~/notes/stores/modules';
import DiffFileHeader from '~/diffs/components/diff_file_header.vue';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+Vue.use(Vuex);
+
const discussionFixture = 'merge_requests/diff_discussion.json';
describe('diff_file_header', () => {
@@ -22,9 +23,9 @@ describe('diff_file_header', () => {
});
beforeEach(() => {
- const diffFile = convertObjectPropsToCamelCase(diffDiscussionMock.diff_file, { deep: true });
+ const diffFile = diffDiscussionMock.diff_file;
props = {
- diffFile,
+ diffFile: { ...diffFile },
canCurrentUserFork: false,
};
});
@@ -58,19 +59,19 @@ describe('diff_file_header', () => {
describe('titleLink', () => {
beforeEach(() => {
+ props.discussionPath = 'link://to/discussion';
Object.assign(props.diffFile, {
- fileHash: 'badc0ffee',
- submoduleLink: 'link://to/submodule',
- submoduleTreeUrl: 'some://tree/url',
+ submodule_link: 'link://to/submodule',
+ submodule_tree_url: 'some://tree/url',
});
});
- it('returns the fileHash for files', () => {
+ it('returns the discussionPath for files', () => {
props.diffFile.submodule = false;
vm = mountComponentWithStore(Component, { props, store });
- expect(vm.titleLink).toBe(`#${props.diffFile.fileHash}`);
+ expect(vm.titleLink).toBe(props.discussionPath);
});
it('returns the submoduleTreeUrl for submodules', () => {
@@ -78,18 +79,26 @@ describe('diff_file_header', () => {
vm = mountComponentWithStore(Component, { props, store });
- expect(vm.titleLink).toBe(props.diffFile.submoduleTreeUrl);
+ expect(vm.titleLink).toBe(props.diffFile.submodule_tree_url);
});
it('returns the submoduleLink for submodules without submoduleTreeUrl', () => {
Object.assign(props.diffFile, {
submodule: true,
- submoduleTreeUrl: null,
+ submodule_tree_url: null,
});
vm = mountComponentWithStore(Component, { props, store });
- expect(vm.titleLink).toBe(props.diffFile.submoduleLink);
+ expect(vm.titleLink).toBe(props.diffFile.submodule_link);
+ });
+
+ it('sets the correct path to the discussion', () => {
+ props.discussionPath = 'link://to/discussion';
+ vm = mountComponentWithStore(Component, { props, store });
+ const href = vm.$el.querySelector('.js-title-wrapper').getAttribute('href');
+
+ expect(href).toBe(vm.discussionPath);
});
});
@@ -97,7 +106,7 @@ describe('diff_file_header', () => {
beforeEach(() => {
Object.assign(props.diffFile, {
blob: { id: 'b10b1db10b1d' },
- filePath: 'path/to/file',
+ file_path: 'path/to/file',
});
});
@@ -106,7 +115,7 @@ describe('diff_file_header', () => {
vm = mountComponentWithStore(Component, { props, store });
- expect(vm.filePath).toBe(props.diffFile.filePath);
+ expect(vm.filePath).toBe(props.diffFile.file_path);
});
it('appends the truncated blob id for submodules', () => {
@@ -115,14 +124,14 @@ describe('diff_file_header', () => {
vm = mountComponentWithStore(Component, { props, store });
expect(vm.filePath).toBe(
- `${props.diffFile.filePath} @ ${props.diffFile.blob.id.substr(0, 8)}`,
+ `${props.diffFile.file_path} @ ${props.diffFile.blob.id.substr(0, 8)}`,
);
});
});
describe('titleTag', () => {
it('returns a link tag if fileHash is set', () => {
- props.diffFile.fileHash = 'some hash';
+ props.diffFile.file_hash = 'some hash';
vm = mountComponentWithStore(Component, { props, store });
@@ -130,7 +139,7 @@ describe('diff_file_header', () => {
});
it('returns a span tag if fileHash is not set', () => {
- props.diffFile.fileHash = null;
+ props.diffFile.file_hash = null;
vm = mountComponentWithStore(Component, { props, store });
@@ -141,8 +150,8 @@ describe('diff_file_header', () => {
describe('isUsingLfs', () => {
beforeEach(() => {
Object.assign(props.diffFile, {
- storedExternally: true,
- externalStorage: 'lfs',
+ stored_externally: true,
+ external_storage: 'lfs',
});
});
@@ -153,7 +162,7 @@ describe('diff_file_header', () => {
});
it('returns false if file is not stored externally', () => {
- props.diffFile.storedExternally = false;
+ props.diffFile.stored_externally = false;
vm = mountComponentWithStore(Component, { props, store });
@@ -161,7 +170,7 @@ describe('diff_file_header', () => {
});
it('returns false if file is not stored in LFS', () => {
- props.diffFile.externalStorage = 'not lfs';
+ props.diffFile.external_storage = 'not lfs';
vm = mountComponentWithStore(Component, { props, store });
@@ -190,7 +199,7 @@ describe('diff_file_header', () => {
describe('viewFileButtonText', () => {
it('contains the truncated content SHA', () => {
const dummySha = 'deebd00f is no SHA';
- props.diffFile.contentSha = dummySha;
+ props.diffFile.content_sha = dummySha;
vm = mountComponentWithStore(Component, { props, store });
@@ -202,7 +211,7 @@ describe('diff_file_header', () => {
describe('viewReplacedFileButtonText', () => {
it('contains the truncated base SHA', () => {
const dummySha = 'deadabba sings no more';
- props.diffFile.diffRefs.baseSha = dummySha;
+ props.diffFile.diff_refs.base_sha = dummySha;
vm = mountComponentWithStore(Component, { props, store });
@@ -261,6 +270,7 @@ describe('diff_file_header', () => {
it('displays an file icon in the title', () => {
vm = mountComponentWithStore(Component, { props, store });
+
expect(vm.$el.querySelector('svg.js-file-icon use').getAttribute('xlink:href')).toContain(
'ruby',
);
@@ -270,32 +280,32 @@ describe('diff_file_header', () => {
const filePaths = () => vm.$el.querySelectorAll('.file-title-name');
it('displays the path of a added file', () => {
- props.diffFile.renamedFile = false;
+ props.diffFile.renamed_file = false;
vm = mountComponentWithStore(Component, { props, store });
expect(filePaths()).toHaveLength(1);
- expect(filePaths()[0]).toHaveText(props.diffFile.filePath);
+ expect(filePaths()[0]).toHaveText(props.diffFile.file_path);
});
it('displays path for deleted file', () => {
- props.diffFile.renamedFile = false;
- props.diffFile.deletedFile = true;
+ props.diffFile.renamed_file = false;
+ props.diffFile.deleted_file = true;
vm = mountComponentWithStore(Component, { props, store });
expect(filePaths()).toHaveLength(1);
- expect(filePaths()[0]).toHaveText(`${props.diffFile.filePath} deleted`);
+ expect(filePaths()[0]).toHaveText(`${props.diffFile.file_path} deleted`);
});
it('displays old and new path if the file was renamed', () => {
- props.diffFile.renamedFile = true;
+ props.diffFile.renamed_file = true;
vm = mountComponentWithStore(Component, { props, store });
expect(filePaths()).toHaveLength(2);
- expect(filePaths()[0]).toHaveText(props.diffFile.oldPath);
- expect(filePaths()[1]).toHaveText(props.diffFile.newPath);
+ expect(filePaths()[0]).toHaveText(props.diffFile.old_path);
+ expect(filePaths()[1]).toHaveText(props.diffFile.new_path);
});
});
@@ -303,28 +313,33 @@ describe('diff_file_header', () => {
vm = mountComponentWithStore(Component, { props, store });
const button = vm.$el.querySelector('.btn-clipboard');
+
expect(button).not.toBe(null);
- expect(button.dataset.clipboardText).toBe('{"text":"files/ruby/popen.rb","gfm":"`files/ruby/popen.rb`"}');
+ expect(button.dataset.clipboardText).toBe(
+ '{"text":"files/ruby/popen.rb","gfm":"`files/ruby/popen.rb`"}',
+ );
});
describe('file mode', () => {
it('it displays old and new file mode if it changed', () => {
- props.diffFile.modeChanged = true;
+ props.diffFile.mode_changed = true;
vm = mountComponentWithStore(Component, { props, store });
const { fileMode } = vm.$refs;
+
expect(fileMode).not.toBe(undefined);
- expect(fileMode).toContainText(props.diffFile.aMode);
- expect(fileMode).toContainText(props.diffFile.bMode);
+ expect(fileMode).toContainText(props.diffFile.a_mode);
+ expect(fileMode).toContainText(props.diffFile.b_mode);
});
it('does not display the file mode if it has not changed', () => {
- props.diffFile.modeChanged = false;
+ props.diffFile.mode_changed = false;
vm = mountComponentWithStore(Component, { props, store });
const { fileMode } = vm.$refs;
+
expect(fileMode).toBe(undefined);
});
});
@@ -334,8 +349,8 @@ describe('diff_file_header', () => {
it('displays the LFS label for files stored in LFS', () => {
Object.assign(props.diffFile, {
- storedExternally: true,
- externalStorage: 'lfs',
+ stored_externally: true,
+ external_storage: 'lfs',
});
vm = mountComponentWithStore(Component, { props, store });
@@ -345,7 +360,7 @@ describe('diff_file_header', () => {
});
it('does not display the LFS label for files stored in repository', () => {
- props.diffFile.storedExternally = false;
+ props.diffFile.stored_externally = false;
vm = mountComponentWithStore(Component, { props, store });
@@ -362,7 +377,7 @@ describe('diff_file_header', () => {
it('should show edit button when file is editable', () => {
props.addMergeRequestButtons = true;
- props.diffFile.editPath = '/';
+ props.diffFile.edit_path = '/';
vm = mountComponentWithStore(Component, { props, store });
expect(vm.$el.querySelector('.js-edit-blob')).toContainText('Edit');
@@ -370,8 +385,8 @@ describe('diff_file_header', () => {
it('should not show edit button when file is deleted', () => {
props.addMergeRequestButtons = true;
- props.diffFile.deletedFile = true;
- props.diffFile.editPath = '/';
+ props.diffFile.deleted_file = true;
+ props.diffFile.edit_path = '/';
vm = mountComponentWithStore(Component, { props, store });
expect(vm.$el.querySelector('.js-edit-blob')).toEqual(null);
@@ -381,7 +396,7 @@ describe('diff_file_header', () => {
describe('addMergeRequestButtons', () => {
beforeEach(() => {
props.addMergeRequestButtons = true;
- props.diffFile.editPath = '';
+ props.diffFile.edit_path = '';
});
describe('view on environment button', () => {
@@ -389,8 +404,8 @@ describe('diff_file_header', () => {
const title = 'url.title';
it('displays link to external url', () => {
- props.diffFile.externalUrl = url;
- props.diffFile.formattedExternalUrl = title;
+ props.diffFile.external_url = url;
+ props.diffFile.formatted_external_url = title;
vm = mountComponentWithStore(Component, { props, store });
@@ -399,8 +414,8 @@ describe('diff_file_header', () => {
});
it('hides link if no external url', () => {
- props.diffFile.externalUrl = '';
- props.diffFile.formattedExternalUrl = title;
+ props.diffFile.external_url = '';
+ props.diffFile.formattedExternal_url = title;
vm = mountComponentWithStore(Component, { props, store });
@@ -418,11 +433,11 @@ describe('diff_file_header', () => {
path: 'lib/base.js',
name: 'base.js',
mode: '100644',
- readableText: true,
+ readable_text: true,
icon: 'file-text-o',
};
propsCopy.addMergeRequestButtons = true;
- propsCopy.diffFile.deletedFile = true;
+ propsCopy.diffFile.deleted_file = true;
vm = mountComponentWithStore(Component, {
props: propsCopy,
@@ -443,13 +458,17 @@ describe('diff_file_header', () => {
path: 'lib/base.js',
name: 'base.js',
mode: '100644',
- readableText: true,
+ readable_text: true,
icon: 'file-text-o',
};
propsCopy.addMergeRequestButtons = true;
- propsCopy.diffFile.deletedFile = true;
+ propsCopy.diffFile.deleted_file = true;
- const discussionGetter = () => [diffDiscussionMock];
+ const discussionGetter = () => [
+ {
+ ...diffDiscussionMock,
+ },
+ ];
const notesModuleMock = notesModule();
notesModuleMock.getters.discussions = discussionGetter;
vm = mountComponentWithStore(Component, {
diff --git a/spec/javascripts/diffs/components/diff_file_spec.js b/spec/javascripts/diffs/components/diff_file_spec.js
index 2a52cd2b179..51bb4807960 100644
--- a/spec/javascripts/diffs/components/diff_file_spec.js
+++ b/spec/javascripts/diffs/components/diff_file_spec.js
@@ -6,11 +6,10 @@ import diffFileMockData from '../mock_data/diff_file';
describe('DiffFile', () => {
let vm;
- const getDiffFileMock = () => Object.assign({}, diffFileMockData);
beforeEach(() => {
vm = createComponentWithStore(Vue.extend(DiffFileComponent), store, {
- file: getDiffFileMock(),
+ file: JSON.parse(JSON.stringify(diffFileMockData)),
canCurrentUserFork: false,
}).$mount();
});
@@ -18,21 +17,21 @@ describe('DiffFile', () => {
describe('template', () => {
it('should render component with file header, file content components', () => {
const el = vm.$el;
- const { fileHash, filePath } = diffFileMockData;
+ const { file_hash, file_path } = vm.file;
- expect(el.id).toEqual(fileHash);
+ expect(el.id).toEqual(file_hash);
expect(el.classList.contains('diff-file')).toEqual(true);
expect(el.querySelectorAll('.diff-content.hidden').length).toEqual(0);
expect(el.querySelector('.js-file-title')).toBeDefined();
- expect(el.querySelector('.file-title-name').innerText.indexOf(filePath) > -1).toEqual(true);
+ expect(el.querySelector('.file-title-name').innerText.indexOf(file_path)).toBeGreaterThan(-1);
expect(el.querySelector('.js-syntax-highlight')).toBeDefined();
expect(vm.file.renderIt).toEqual(false);
vm.file.renderIt = true;
vm.$nextTick(() => {
- expect(el.querySelectorAll('.line_content').length > 5).toEqual(true);
+ expect(el.querySelectorAll('.line_content').length).toBeGreaterThan(5);
});
});
@@ -53,7 +52,7 @@ describe('DiffFile', () => {
it('should have collapsed text and link', done => {
vm.file.renderIt = true;
vm.file.collapsed = false;
- vm.file.highlightedDiffLines = null;
+ vm.file.highlighted_diff_lines = null;
vm.$nextTick(() => {
expect(vm.$el.innerText).toContain('This diff is collapsed');
@@ -91,20 +90,43 @@ describe('DiffFile', () => {
describe('too large diff', () => {
it('should have too large warning and blob link', done => {
const BLOB_LINK = '/file/view/path';
- vm.file.tooLarge = true;
- vm.file.viewPath = BLOB_LINK;
+ vm.file.too_large = true;
+ vm.file.view_path = BLOB_LINK;
vm.$nextTick(() => {
expect(vm.$el.innerText).toContain(
'This source diff could not be displayed because it is too large',
);
+
expect(vm.$el.querySelector('.js-too-large-diff')).toBeDefined();
- expect(vm.$el.querySelector('.js-too-large-diff a').href.indexOf(BLOB_LINK) > -1).toEqual(
- true,
- );
+ expect(
+ vm.$el.querySelector('.js-too-large-diff a').href.indexOf(BLOB_LINK),
+ ).toBeGreaterThan(-1);
done();
});
});
});
+
+ describe('watch collapsed', () => {
+ it('calls handleLoadCollapsedDiff if collapsed changed & file has no lines', done => {
+ spyOn(vm, 'handleLoadCollapsedDiff');
+
+ vm.file.highlighted_diff_lines = undefined;
+ vm.file.parallel_diff_lines = [];
+ vm.file.collapsed = true;
+
+ vm.$nextTick()
+ .then(() => {
+ vm.file.collapsed = false;
+
+ return vm.$nextTick();
+ })
+ .then(() => {
+ expect(vm.handleLoadCollapsedDiff).toHaveBeenCalled();
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
});
diff --git a/spec/javascripts/diffs/components/diff_gutter_avatars_spec.js b/spec/javascripts/diffs/components/diff_gutter_avatars_spec.js
index 0085a16815a..ad2605a5c5c 100644
--- a/spec/javascripts/diffs/components/diff_gutter_avatars_spec.js
+++ b/spec/javascripts/diffs/components/diff_gutter_avatars_spec.js
@@ -23,6 +23,7 @@ describe('DiffGutterAvatars', () => {
it('should return false when all discussions are not expanded', () => {
component.discussions[0].expanded = false;
+
expect(component.discussionsExpanded).toEqual(false);
});
});
@@ -56,6 +57,7 @@ describe('DiffGutterAvatars', () => {
it('should return empty string if there is no discussion', () => {
component.discussions = [];
+
expect(component.moreText).toEqual('');
});
});
diff --git a/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js b/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js
index 663c0680845..038db8eaa7c 100644
--- a/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js
+++ b/spec/javascripts/diffs/components/diff_line_gutter_content_spec.js
@@ -11,16 +11,16 @@ describe('DiffLineGutterContent', () => {
const cmp = Vue.extend(DiffLineGutterContent);
const props = Object.assign({}, options);
props.line = {
- lineCode: 'LC_42',
+ line_code: 'LC_42',
type: 'new',
- oldLine: null,
- newLine: 1,
- discussions: [],
+ old_line: null,
+ new_line: 1,
+ discussions: [{ ...discussionsMockData }],
text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
- richText: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
- metaData: null,
+ rich_text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
+ meta_data: null,
};
- props.fileHash = getDiffFileMock().fileHash;
+ props.fileHash = getDiffFileMock().file_hash;
props.contextLinesPath = '/context/lines/path';
return createComponentWithStore(cmp, store, props).$mount();
@@ -31,12 +31,14 @@ describe('DiffLineGutterContent', () => {
it('should prepend # to lineCode', () => {
const lineCode = 'LC_42';
const component = createComponent();
+
expect(component.lineHref).toEqual(`#${lineCode}`);
});
it('should return # if there is no lineCode', () => {
const component = createComponent();
- component.line.lineCode = '';
+ component.line.line_code = '';
+
expect(component.lineHref).toEqual('#');
});
});
@@ -44,6 +46,8 @@ describe('DiffLineGutterContent', () => {
describe('discussions, hasDiscussions, shouldShowAvatarsOnGutter', () => {
it('should return empty array when there is no discussion', () => {
const component = createComponent();
+ component.line.discussions = [];
+
expect(component.hasDiscussions).toEqual(false);
expect(component.shouldShowAvatarsOnGutter).toEqual(false);
});
@@ -51,8 +55,8 @@ describe('DiffLineGutterContent', () => {
it('should return discussions for the given lineCode', () => {
const cmp = Vue.extend(DiffLineGutterContent);
const props = {
- line: getDiffFileMock().highlightedDiffLines[1],
- fileHash: getDiffFileMock().fileHash,
+ line: getDiffFileMock().highlighted_diff_lines[1],
+ fileHash: getDiffFileMock().file_hash,
showCommentButton: true,
contextLinesPath: '/context/lines/path',
};
@@ -94,17 +98,17 @@ describe('DiffLineGutterContent', () => {
const component = createComponent({ lineNumber, lineCode });
const link = component.$el.querySelector('a');
- expect(link.href.indexOf(`#${lineCode}`) > -1).toEqual(true);
+ expect(link.href.indexOf(`#${lineCode}`)).toBeGreaterThan(-1);
expect(link.dataset.linenumber).toEqual(lineNumber.toString());
});
it('should render user avatars', () => {
const component = createComponent({
showCommentButton: true,
- lineCode: getDiffFileMock().highlightedDiffLines[1].lineCode,
+ lineCode: getDiffFileMock().highlighted_diff_lines[1].line_code,
});
- expect(component.$el.querySelector('.diff-comment-avatar-holders')).toBeDefined();
+ expect(component.$el.querySelector('.diff-comment-avatar-holders')).not.toBe(null);
});
});
});
diff --git a/spec/javascripts/diffs/components/diff_line_note_form_spec.js b/spec/javascripts/diffs/components/diff_line_note_form_spec.js
index 6fe5fdaf7f9..b983dc35a57 100644
--- a/spec/javascripts/diffs/components/diff_line_note_form_spec.js
+++ b/spec/javascripts/diffs/components/diff_line_note_form_spec.js
@@ -13,10 +13,10 @@ describe('DiffLineNoteForm', () => {
beforeEach(() => {
diffFile = getDiffFileMock();
- diffLines = diffFile.highlightedDiffLines;
+ diffLines = diffFile.highlighted_diff_lines;
component = createComponentWithStore(Vue.extend(DiffLineNoteForm), store, {
- diffFileHash: diffFile.fileHash,
+ diffFileHash: diffFile.file_hash,
diffLines,
line: diffLines[0],
noteTargetLine: diffLines[0],
@@ -36,6 +36,7 @@ describe('DiffLineNoteForm', () => {
spyOn(window, 'confirm').and.returnValue(false);
component.handleCancelCommentForm(true, true);
+
expect(window.confirm).toHaveBeenCalled();
});
@@ -43,9 +44,11 @@ describe('DiffLineNoteForm', () => {
spyOn(window, 'confirm').and.returnValue(false);
component.handleCancelCommentForm(true, false);
+
expect(window.confirm).not.toHaveBeenCalled();
component.handleCancelCommentForm(false, true);
+
expect(window.confirm).not.toHaveBeenCalled();
});
@@ -58,8 +61,10 @@ describe('DiffLineNoteForm', () => {
expect(window.confirm).not.toHaveBeenCalled();
component.$nextTick(() => {
expect(component.cancelCommentForm).toHaveBeenCalledWith({
- lineCode: diffLines[0].lineCode,
+ lineCode: diffLines[0].line_code,
+ fileHash: component.diffFileHash,
});
+
expect(component.resetAutoSave).toHaveBeenCalled();
done();
@@ -69,22 +74,21 @@ describe('DiffLineNoteForm', () => {
describe('saveNoteForm', () => {
it('should call saveNote action with proper params', done => {
- let isPromiseCalled = false;
- const formDataSpy = spyOnDependency(DiffLineNoteForm, 'getNoteFormData').and.returnValue({
- postData: 1,
- });
- const saveNoteSpy = spyOn(component, 'saveNote').and.returnValue(
- new Promise(() => {
- isPromiseCalled = true;
- done();
- }),
+ const saveDiffDiscussionSpy = spyOn(component, 'saveDiffDiscussion').and.returnValue(
+ Promise.resolve(),
);
-
- component.handleSaveNote('note body');
-
- expect(formDataSpy).toHaveBeenCalled();
- expect(saveNoteSpy).toHaveBeenCalled();
- expect(isPromiseCalled).toEqual(true);
+ spyOnProperty(component, 'formData').and.returnValue('formData');
+
+ component
+ .handleSaveNote('note body')
+ .then(() => {
+ expect(saveDiffDiscussionSpy).toHaveBeenCalledWith({
+ note: 'note body',
+ formData: 'formData',
+ });
+ })
+ .then(done)
+ .catch(done.fail);
});
});
});
diff --git a/spec/javascripts/diffs/components/diff_table_cell_spec.js b/spec/javascripts/diffs/components/diff_table_cell_spec.js
new file mode 100644
index 00000000000..170e661beea
--- /dev/null
+++ b/spec/javascripts/diffs/components/diff_table_cell_spec.js
@@ -0,0 +1,37 @@
+import Vue from 'vue';
+import store from '~/mr_notes/stores';
+import DiffTableCell from '~/diffs/components/diff_table_cell.vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import diffFileMockData from '../mock_data/diff_file';
+
+describe('DiffTableCell', () => {
+ const createComponent = options =>
+ createComponentWithStore(Vue.extend(DiffTableCell), store, {
+ line: diffFileMockData.highlighted_diff_lines[0],
+ fileHash: diffFileMockData.file_hash,
+ contextLinesPath: 'contextLinesPath',
+ ...options,
+ }).$mount();
+
+ it('does not highlight row when isHighlighted prop is false', done => {
+ const vm = createComponent({ isHighlighted: false });
+
+ vm.$nextTick()
+ .then(() => {
+ expect(vm.$el.classList).not.toContain('hll');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('highlights row when isHighlighted prop is true', done => {
+ const vm = createComponent({ isHighlighted: true });
+
+ vm.$nextTick()
+ .then(() => {
+ expect(vm.$el.classList).toContain('hll');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+});
diff --git a/spec/javascripts/diffs/components/file_row_stats_spec.js b/spec/javascripts/diffs/components/file_row_stats_spec.js
new file mode 100644
index 00000000000..a8a7f3f1d82
--- /dev/null
+++ b/spec/javascripts/diffs/components/file_row_stats_spec.js
@@ -0,0 +1,33 @@
+import Vue from 'vue';
+import FileRowStats from '~/diffs/components/file_row_stats.vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+
+describe('Diff file row stats', () => {
+ let Component;
+ let vm;
+
+ beforeAll(() => {
+ Component = Vue.extend(FileRowStats);
+ });
+
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ file: {
+ addedLines: 20,
+ removedLines: 10,
+ },
+ });
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders added lines count', () => {
+ expect(vm.$el.querySelector('.cgreen').textContent).toContain('+20');
+ });
+
+ it('renders removed lines count', () => {
+ expect(vm.$el.querySelector('.cred').textContent).toContain('-10');
+ });
+});
diff --git a/spec/javascripts/diffs/components/image_diff_overlay_spec.js b/spec/javascripts/diffs/components/image_diff_overlay_spec.js
new file mode 100644
index 00000000000..d76ab745fe1
--- /dev/null
+++ b/spec/javascripts/diffs/components/image_diff_overlay_spec.js
@@ -0,0 +1,146 @@
+import Vue from 'vue';
+import ImageDiffOverlay from '~/diffs/components/image_diff_overlay.vue';
+import { createStore } from '~/mr_notes/stores';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import { imageDiffDiscussions } from '../mock_data/diff_discussions';
+
+describe('Diffs image diff overlay component', () => {
+ const dimensions = {
+ width: 100,
+ height: 200,
+ };
+ let Component;
+ let vm;
+
+ function createComponent(props = {}, extendStore = () => {}) {
+ const store = createStore();
+
+ extendStore(store);
+
+ vm = createComponentWithStore(Component, store, {
+ discussions: [...imageDiffDiscussions],
+ fileHash: 'ABC',
+ ...props,
+ });
+ }
+
+ beforeAll(() => {
+ Component = Vue.extend(ImageDiffOverlay);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders comment badges', () => {
+ createComponent();
+ spyOn(vm, 'getImageDimensions').and.returnValue(dimensions);
+ vm.$mount();
+
+ expect(vm.$el.querySelectorAll('.js-image-badge').length).toBe(2);
+ });
+
+ it('renders index of discussion in badge', () => {
+ createComponent();
+ spyOn(vm, 'getImageDimensions').and.returnValue(dimensions);
+ vm.$mount();
+
+ expect(vm.$el.querySelectorAll('.js-image-badge')[0].textContent.trim()).toBe('1');
+ expect(vm.$el.querySelectorAll('.js-image-badge')[1].textContent.trim()).toBe('2');
+ });
+
+ it('renders icon when showCommentIcon is true', () => {
+ createComponent({ showCommentIcon: true });
+ spyOn(vm, 'getImageDimensions').and.returnValue(dimensions);
+ vm.$mount();
+
+ expect(vm.$el.querySelector('.js-image-badge svg')).not.toBe(null);
+ });
+
+ it('sets badge comment positions', () => {
+ createComponent();
+ spyOn(vm, 'getImageDimensions').and.returnValue(dimensions);
+ vm.$mount();
+
+ expect(vm.$el.querySelectorAll('.js-image-badge')[0].style.left).toBe('10px');
+ expect(vm.$el.querySelectorAll('.js-image-badge')[0].style.top).toBe('10px');
+
+ expect(vm.$el.querySelectorAll('.js-image-badge')[1].style.left).toBe('5px');
+ expect(vm.$el.querySelectorAll('.js-image-badge')[1].style.top).toBe('5px');
+ });
+
+ it('renders single badge for discussion object', () => {
+ createComponent({
+ discussions: {
+ ...imageDiffDiscussions[0],
+ },
+ });
+ spyOn(vm, 'getImageDimensions').and.returnValue(dimensions);
+ vm.$mount();
+
+ expect(vm.$el.querySelectorAll('.js-image-badge').length).toBe(1);
+ });
+
+ it('dispatches openDiffFileCommentForm when clicking overlay', () => {
+ createComponent({ canComment: true });
+ spyOn(vm, 'getImageDimensions').and.returnValue(dimensions);
+ vm.$mount();
+
+ spyOn(vm.$store, 'dispatch').and.stub();
+
+ vm.$el.querySelector('.js-add-image-diff-note-button').click();
+
+ expect(vm.$store.dispatch).toHaveBeenCalledWith('diffs/openDiffFileCommentForm', {
+ fileHash: 'ABC',
+ x: 0,
+ y: 0,
+ width: 100,
+ height: 200,
+ });
+ });
+
+ describe('toggle discussion', () => {
+ it('disables buttons when shouldToggleDiscussion is false', () => {
+ createComponent({ shouldToggleDiscussion: false });
+ spyOn(vm, 'getImageDimensions').and.returnValue(dimensions);
+ vm.$mount();
+
+ expect(vm.$el.querySelector('.js-image-badge').hasAttribute('disabled')).toBe(true);
+ });
+
+ it('dispatches toggleDiscussion when clicking image badge', () => {
+ createComponent();
+ spyOn(vm, 'getImageDimensions').and.returnValue(dimensions);
+ vm.$mount();
+
+ spyOn(vm.$store, 'dispatch').and.stub();
+
+ vm.$el.querySelector('.js-image-badge').click();
+
+ expect(vm.$store.dispatch).toHaveBeenCalledWith('toggleDiscussion', { discussionId: '1' });
+ });
+ });
+
+ describe('comment form', () => {
+ beforeEach(() => {
+ createComponent({}, store => {
+ store.state.diffs.commentForms.push({
+ fileHash: 'ABC',
+ x: 20,
+ y: 10,
+ });
+ });
+ spyOn(vm, 'getImageDimensions').and.returnValue(dimensions);
+ vm.$mount();
+ });
+
+ it('renders comment form badge', () => {
+ expect(vm.$el.querySelector('.comment-indicator')).not.toBe(null);
+ });
+
+ it('sets comment form badge position', () => {
+ expect(vm.$el.querySelector('.comment-indicator').style.left).toBe('20px');
+ expect(vm.$el.querySelector('.comment-indicator').style.top).toBe('10px');
+ });
+ });
+});
diff --git a/spec/javascripts/diffs/components/inline_diff_table_row_spec.js b/spec/javascripts/diffs/components/inline_diff_table_row_spec.js
new file mode 100644
index 00000000000..97926f6625e
--- /dev/null
+++ b/spec/javascripts/diffs/components/inline_diff_table_row_spec.js
@@ -0,0 +1,42 @@
+import Vue from 'vue';
+import store from '~/mr_notes/stores';
+import InlineDiffTableRow from '~/diffs/components/inline_diff_table_row.vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import diffFileMockData from '../mock_data/diff_file';
+
+describe('InlineDiffTableRow', () => {
+ let vm;
+ const thisLine = diffFileMockData.highlighted_diff_lines[0];
+
+ beforeEach(() => {
+ vm = createComponentWithStore(Vue.extend(InlineDiffTableRow), store, {
+ line: thisLine,
+ fileHash: diffFileMockData.file_hash,
+ contextLinesPath: 'contextLinesPath',
+ isHighlighted: false,
+ }).$mount();
+ });
+
+ it('does not add hll class to line content when line does not match highlighted row', done => {
+ vm.$nextTick()
+ .then(() => {
+ expect(vm.$el.querySelector('.line_content').classList).not.toContain('hll');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('adds hll class to lineContent when line is the highlighted row', done => {
+ vm.$nextTick()
+ .then(() => {
+ vm.$store.state.diffs.highlightedRow = thisLine.line_code;
+
+ return vm.$nextTick();
+ })
+ .then(() => {
+ expect(vm.$el.querySelector('.line_content').classList).toContain('hll');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+});
diff --git a/spec/javascripts/diffs/components/inline_diff_view_spec.js b/spec/javascripts/diffs/components/inline_diff_view_spec.js
index b02328dd359..2316ee29106 100644
--- a/spec/javascripts/diffs/components/inline_diff_view_spec.js
+++ b/spec/javascripts/diffs/components/inline_diff_view_spec.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import '~/behaviors/markdown/render_gfm';
import InlineDiffView from '~/diffs/components/inline_diff_view.vue';
import store from '~/mr_notes/stores';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
@@ -10,14 +11,16 @@ describe('InlineDiffView', () => {
const getDiffFileMock = () => Object.assign({}, diffFileMockData);
const getDiscussionsMockData = () => [Object.assign({}, discussionsMockData)];
- beforeEach(() => {
+ beforeEach(done => {
const diffFile = getDiffFileMock();
store.dispatch('diffs/setInlineDiffViewType');
component = createComponentWithStore(Vue.extend(InlineDiffView), store, {
diffFile,
- diffLines: diffFile.highlightedDiffLines,
+ diffLines: diffFile.highlighted_diff_lines,
}).$mount();
+
+ Vue.nextTick(done);
});
describe('template', () => {
@@ -27,17 +30,17 @@ describe('InlineDiffView', () => {
expect(el.querySelectorAll('tr.line_holder').length).toEqual(6);
expect(el.querySelectorAll('tr.line_holder.new').length).toEqual(2);
expect(el.querySelectorAll('tr.line_holder.match').length).toEqual(1);
- expect(el.textContent.indexOf('Bad dates') > -1).toEqual(true);
+ expect(el.textContent.indexOf('Bad dates')).toBeGreaterThan(-1);
});
it('should render discussions', done => {
const el = component.$el;
- component.$store.dispatch('setInitialNotes', getDiscussionsMockData());
+ component.diffLines[1].discussions = getDiscussionsMockData();
Vue.nextTick(() => {
expect(el.querySelectorAll('.notes_holder').length).toEqual(1);
expect(el.querySelectorAll('.notes_holder .note-discussion li').length).toEqual(5);
- expect(el.innerText.indexOf('comment 5') > -1).toEqual(true);
+ expect(el.innerText.indexOf('comment 5')).toBeGreaterThan(-1);
component.$store.dispatch('setInitialNotes', []);
done();
diff --git a/spec/javascripts/diffs/components/parallel_diff_table_row_spec.js b/spec/javascripts/diffs/components/parallel_diff_table_row_spec.js
new file mode 100644
index 00000000000..311eaaaa7c8
--- /dev/null
+++ b/spec/javascripts/diffs/components/parallel_diff_table_row_spec.js
@@ -0,0 +1,85 @@
+import Vue from 'vue';
+import { createStore } from '~/mr_notes/stores';
+import ParallelDiffTableRow from '~/diffs/components/parallel_diff_table_row.vue';
+import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import diffFileMockData from '../mock_data/diff_file';
+
+describe('ParallelDiffTableRow', () => {
+ describe('when one side is empty', () => {
+ let vm;
+ const thisLine = diffFileMockData.parallel_diff_lines[0];
+ const rightLine = diffFileMockData.parallel_diff_lines[0].right;
+
+ beforeEach(() => {
+ vm = createComponentWithStore(Vue.extend(ParallelDiffTableRow), createStore(), {
+ line: thisLine,
+ fileHash: diffFileMockData.file_hash,
+ contextLinesPath: 'contextLinesPath',
+ isHighlighted: false,
+ }).$mount();
+ });
+
+ it('does not highlight non empty line content when line does not match highlighted row', done => {
+ vm.$nextTick()
+ .then(() => {
+ expect(vm.$el.querySelector('.line_content.right-side').classList).not.toContain('hll');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('highlights nonempty line content when line is the highlighted row', done => {
+ vm.$nextTick()
+ .then(() => {
+ vm.$store.state.diffs.highlightedRow = rightLine.line_code;
+
+ return vm.$nextTick();
+ })
+ .then(() => {
+ expect(vm.$el.querySelector('.line_content.right-side').classList).toContain('hll');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('when both sides have content', () => {
+ let vm;
+ const thisLine = diffFileMockData.parallel_diff_lines[2];
+ const rightLine = diffFileMockData.parallel_diff_lines[2].right;
+
+ beforeEach(() => {
+ vm = createComponentWithStore(Vue.extend(ParallelDiffTableRow), createStore(), {
+ line: thisLine,
+ fileHash: diffFileMockData.file_hash,
+ contextLinesPath: 'contextLinesPath',
+ isHighlighted: false,
+ }).$mount();
+ });
+
+ it('does not highlight either line when line does not match highlighted row', done => {
+ vm.$nextTick()
+ .then(() => {
+ expect(vm.$el.querySelector('.line_content.right-side').classList).not.toContain('hll');
+ expect(vm.$el.querySelector('.line_content.left-side').classList).not.toContain('hll');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('adds hll class to lineContent when line is the highlighted row', done => {
+ vm.$nextTick()
+ .then(() => {
+ vm.$store.state.diffs.highlightedRow = rightLine.line_code;
+
+ return vm.$nextTick();
+ })
+ .then(() => {
+ expect(vm.$el.querySelector('.line_content.right-side').classList).toContain('hll');
+ expect(vm.$el.querySelector('.line_content.left-side').classList).toContain('hll');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+});
diff --git a/spec/javascripts/diffs/components/parallel_diff_view_spec.js b/spec/javascripts/diffs/components/parallel_diff_view_spec.js
index 091e01868d3..6f6b1c41915 100644
--- a/spec/javascripts/diffs/components/parallel_diff_view_spec.js
+++ b/spec/javascripts/diffs/components/parallel_diff_view_spec.js
@@ -14,7 +14,7 @@ describe('ParallelDiffView', () => {
component = createComponentWithStore(Vue.extend(ParallelDiffView), store, {
diffFile,
- diffLines: diffFile.parallelDiffLines,
+ diffLines: diffFile.parallel_diff_lines,
}).$mount();
});
diff --git a/spec/javascripts/diffs/components/tree_list_spec.js b/spec/javascripts/diffs/components/tree_list_spec.js
new file mode 100644
index 00000000000..a0b380adfd6
--- /dev/null
+++ b/spec/javascripts/diffs/components/tree_list_spec.js
@@ -0,0 +1,188 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import TreeList from '~/diffs/components/tree_list.vue';
+import createStore from '~/diffs/store/modules';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+
+describe('Diffs tree list component', () => {
+ let Component;
+ let vm;
+
+ beforeAll(() => {
+ Component = Vue.extend(TreeList);
+ });
+
+ beforeEach(() => {
+ Vue.use(Vuex);
+
+ const store = new Vuex.Store({
+ modules: {
+ diffs: createStore(),
+ },
+ });
+
+ // Setup initial state
+ store.state.diffs.addedLines = 10;
+ store.state.diffs.removedLines = 20;
+ store.state.diffs.diffFiles.push('test');
+
+ vm = mountComponentWithStore(Component, { store });
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders diff stats', () => {
+ expect(vm.$el.textContent).toContain('1 changed file');
+ expect(vm.$el.textContent).toContain('10 additions');
+ expect(vm.$el.textContent).toContain('20 deletions');
+ });
+
+ it('renders empty text', () => {
+ expect(vm.$el.textContent).toContain('No files found');
+ });
+
+ describe('with files', () => {
+ beforeEach(done => {
+ Object.assign(vm.$store.state.diffs.treeEntries, {
+ 'index.js': {
+ addedLines: 0,
+ changed: true,
+ deleted: false,
+ fileHash: 'test',
+ key: 'index.js',
+ name: 'index.js',
+ path: 'app/index.js',
+ removedLines: 0,
+ tempFile: true,
+ type: 'blob',
+ },
+ app: {
+ key: 'app',
+ path: 'app',
+ name: 'app',
+ type: 'tree',
+ tree: [],
+ },
+ });
+ vm.$store.state.diffs.tree = [
+ vm.$store.state.diffs.treeEntries['index.js'],
+ vm.$store.state.diffs.treeEntries.app,
+ ];
+
+ vm.$nextTick(done);
+ });
+
+ it('renders tree', () => {
+ expect(vm.$el.querySelectorAll('.file-row').length).toBe(2);
+ expect(vm.$el.querySelectorAll('.file-row')[0].textContent).toContain('index.js');
+ expect(vm.$el.querySelectorAll('.file-row')[1].textContent).toContain('app');
+ });
+
+ it('filters tree list to blobs matching search', done => {
+ vm.search = 'app/index';
+
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelectorAll('.file-row').length).toBe(1);
+ expect(vm.$el.querySelectorAll('.file-row')[0].textContent).toContain('index.js');
+
+ done();
+ });
+ });
+
+ it('calls toggleTreeOpen when clicking folder', () => {
+ spyOn(vm.$store, 'dispatch').and.stub();
+
+ vm.$el.querySelectorAll('.file-row')[1].click();
+
+ expect(vm.$store.dispatch).toHaveBeenCalledWith('diffs/toggleTreeOpen', 'app');
+ });
+
+ it('calls scrollToFile when clicking blob', () => {
+ spyOn(vm.$store, 'dispatch').and.stub();
+
+ vm.$el.querySelector('.file-row').click();
+
+ expect(vm.$store.dispatch).toHaveBeenCalledWith('diffs/scrollToFile', 'app/index.js');
+ });
+
+ it('renders as file list when renderTreeList is false', done => {
+ vm.renderTreeList = false;
+
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelectorAll('.file-row').length).toBe(1);
+
+ done();
+ });
+ });
+
+ it('renders file paths when renderTreeList is false', done => {
+ vm.renderTreeList = false;
+
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.file-row').textContent).toContain('app/index.js');
+
+ done();
+ });
+ });
+
+ it('hides render buttons when input is focused', done => {
+ const focusEvent = new Event('focus');
+
+ vm.$el.querySelector('.form-control').dispatchEvent(focusEvent);
+
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector('.tree-list-view-toggle').style.display).toBe('none');
+
+ done();
+ });
+ });
+
+ it('shows render buttons when input is blurred', done => {
+ const blurEvent = new Event('blur');
+ vm.focusSearch = true;
+
+ vm.$nextTick()
+ .then(() => {
+ vm.$el.querySelector('.form-control').dispatchEvent(blurEvent);
+ })
+ .then(vm.$nextTick)
+ .then(() => {
+ expect(vm.$el.querySelector('.tree-list-view-toggle').style.display).not.toBe('none');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('clearSearch', () => {
+ it('resets search', () => {
+ vm.search = 'test';
+
+ vm.$el.querySelector('.tree-list-clear-icon').click();
+
+ expect(vm.search).toBe('');
+ });
+ });
+
+ describe('toggleRenderTreeList', () => {
+ it('updates renderTreeList', () => {
+ expect(vm.renderTreeList).toBe(true);
+
+ vm.toggleRenderTreeList(false);
+
+ expect(vm.renderTreeList).toBe(false);
+ });
+ });
+
+ describe('toggleFocusSearch', () => {
+ it('updates focusSearch', () => {
+ expect(vm.focusSearch).toBe(false);
+
+ vm.toggleFocusSearch(true);
+
+ expect(vm.focusSearch).toBe(true);
+ });
+ });
+});
diff --git a/spec/javascripts/diffs/mock_data/diff_discussions.js b/spec/javascripts/diffs/mock_data/diff_discussions.js
index b29a22da7c2..5ffe5a366ba 100644
--- a/spec/javascripts/diffs/mock_data/diff_discussions.js
+++ b/spec/javascripts/diffs/mock_data/diff_discussions.js
@@ -2,15 +2,13 @@ export default {
id: '6b232e05bea388c6b043ccc243ba505faac04ea8',
reply_id: '6b232e05bea388c6b043ccc243ba505faac04ea8',
position: {
- formatter: {
- old_line: null,
- new_line: 2,
- old_path: 'CHANGELOG',
- new_path: 'CHANGELOG',
- base_sha: 'e63f41fe459e62e1228fcef60d7189127aeba95a',
- start_sha: 'd9eaefe5a676b820c57ff18cf5b68316025f7962',
- head_sha: 'c48ee0d1bf3b30453f5b32250ce03134beaa6d13',
- },
+ old_line: null,
+ new_line: 2,
+ old_path: 'CHANGELOG',
+ new_path: 'CHANGELOG',
+ base_sha: 'e63f41fe459e62e1228fcef60d7189127aeba95a',
+ start_sha: 'd9eaefe5a676b820c57ff18cf5b68316025f7962',
+ head_sha: 'c48ee0d1bf3b30453f5b32250ce03134beaa6d13',
},
line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_2',
expanded: true,
@@ -494,3 +492,24 @@ export default {
image_diff_html:
'<div class="image js-replaced-image" data="">\n<div class="two-up view">\n<div class="wrap">\n<div class="frame deleted">\n<img alt="CHANGELOG" src="http://localhost:3000/gitlab-org/gitlab-test/raw/e63f41fe459e62e1228fcef60d7189127aeba95a/CHANGELOG" />\n</div>\n<p class="image-info hide">\n<span class="meta-filesize">22.3 KB</span>\n|\n<strong>W:</strong>\n<span class="meta-width"></span>\n|\n<strong>H:</strong>\n<span class="meta-height"></span>\n</p>\n</div>\n<div class="wrap">\n<div class="added frame js-image-frame" data-note-type="DiffNote" data-position="{&quot;base_sha&quot;:&quot;e63f41fe459e62e1228fcef60d7189127aeba95a&quot;,&quot;start_sha&quot;:&quot;d9eaefe5a676b820c57ff18cf5b68316025f7962&quot;,&quot;head_sha&quot;:&quot;c48ee0d1bf3b30453f5b32250ce03134beaa6d13&quot;,&quot;old_path&quot;:&quot;CHANGELOG&quot;,&quot;new_path&quot;:&quot;CHANGELOG&quot;,&quot;position_type&quot;:&quot;text&quot;,&quot;old_line&quot;:null,&quot;new_line&quot;:2}">\n<img alt="CHANGELOG" draggable="false" src="http://localhost:3000/gitlab-org/gitlab-test/raw/c48ee0d1bf3b30453f5b32250ce03134beaa6d13/CHANGELOG" />\n</div>\n\n<p class="image-info hide">\n<span class="meta-filesize">22.3 KB</span>\n|\n<strong>W:</strong>\n<span class="meta-width"></span>\n|\n<strong>H:</strong>\n<span class="meta-height"></span>\n</p>\n</div>\n</div>\n<div class="swipe view hide">\n<div class="swipe-frame">\n<div class="frame deleted">\n<img alt="CHANGELOG" src="http://localhost:3000/gitlab-org/gitlab-test/raw/e63f41fe459e62e1228fcef60d7189127aeba95a/CHANGELOG" />\n</div>\n<div class="swipe-wrap">\n<div class="added frame js-image-frame" data-note-type="DiffNote" data-position="{&quot;base_sha&quot;:&quot;e63f41fe459e62e1228fcef60d7189127aeba95a&quot;,&quot;start_sha&quot;:&quot;d9eaefe5a676b820c57ff18cf5b68316025f7962&quot;,&quot;head_sha&quot;:&quot;c48ee0d1bf3b30453f5b32250ce03134beaa6d13&quot;,&quot;old_path&quot;:&quot;CHANGELOG&quot;,&quot;new_path&quot;:&quot;CHANGELOG&quot;,&quot;position_type&quot;:&quot;text&quot;,&quot;old_line&quot;:null,&quot;new_line&quot;:2}">\n<img alt="CHANGELOG" draggable="false" src="http://localhost:3000/gitlab-org/gitlab-test/raw/c48ee0d1bf3b30453f5b32250ce03134beaa6d13/CHANGELOG" />\n</div>\n\n</div>\n<span class="swipe-bar">\n<span class="top-handle"></span>\n<span class="bottom-handle"></span>\n</span>\n</div>\n</div>\n<div class="onion-skin view hide">\n<div class="onion-skin-frame">\n<div class="frame deleted">\n<img alt="CHANGELOG" src="http://localhost:3000/gitlab-org/gitlab-test/raw/e63f41fe459e62e1228fcef60d7189127aeba95a/CHANGELOG" />\n</div>\n<div class="added frame js-image-frame" data-note-type="DiffNote" data-position="{&quot;base_sha&quot;:&quot;e63f41fe459e62e1228fcef60d7189127aeba95a&quot;,&quot;start_sha&quot;:&quot;d9eaefe5a676b820c57ff18cf5b68316025f7962&quot;,&quot;head_sha&quot;:&quot;c48ee0d1bf3b30453f5b32250ce03134beaa6d13&quot;,&quot;old_path&quot;:&quot;CHANGELOG&quot;,&quot;new_path&quot;:&quot;CHANGELOG&quot;,&quot;position_type&quot;:&quot;text&quot;,&quot;old_line&quot;:null,&quot;new_line&quot;:2}">\n<img alt="CHANGELOG" draggable="false" src="http://localhost:3000/gitlab-org/gitlab-test/raw/c48ee0d1bf3b30453f5b32250ce03134beaa6d13/CHANGELOG" />\n</div>\n\n<div class="controls">\n<div class="transparent"></div>\n<div class="drag-track">\n<div class="dragger" style="left: 0px;"></div>\n</div>\n<div class="opaque"></div>\n</div>\n</div>\n</div>\n</div>\n<div class="view-modes hide">\n<ul class="view-modes-menu">\n<li class="two-up" data-mode="two-up">2-up</li>\n<li class="swipe" data-mode="swipe">Swipe</li>\n<li class="onion-skin" data-mode="onion-skin">Onion skin</li>\n</ul>\n</div>\n',
};
+
+export const imageDiffDiscussions = [
+ {
+ id: '1',
+ position: {
+ x: 10,
+ y: 10,
+ width: 100,
+ height: 200,
+ },
+ },
+ {
+ id: '2',
+ position: {
+ x: 5,
+ y: 5,
+ width: 100,
+ height: 200,
+ },
+ },
+];
diff --git a/spec/javascripts/diffs/mock_data/diff_file.js b/spec/javascripts/diffs/mock_data/diff_file.js
index 372b8f066cf..031c9842f2f 100644
--- a/spec/javascripts/diffs/mock_data/diff_file.js
+++ b/spec/javascripts/diffs/mock_data/diff_file.js
@@ -1,127 +1,130 @@
export default {
submodule: false,
- submoduleLink: null,
+ submodule_link: null,
blob: {
id: '9e10516ca50788acf18c518a231914a21e5f16f7',
path: 'CHANGELOG',
name: 'CHANGELOG',
mode: '100644',
- readableText: true,
+ readable_text: true,
icon: 'file-text-o',
},
- blobPath: 'CHANGELOG',
- blobName: 'CHANGELOG',
- blobIcon: '<i aria-hidden="true" data-hidden="true" class="fa fa-file-text-o fa-fw"></i>',
- fileHash: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a',
- filePath: 'CHANGELOG',
- newFile: false,
- deletedFile: false,
- renamedFile: false,
- oldPath: 'CHANGELOG',
- newPath: 'CHANGELOG',
- modeChanged: false,
- aMode: '100644',
- bMode: '100644',
+ blob_path: 'CHANGELOG',
+ blob_name: 'CHANGELOG',
+ blob_icon: '<i aria-hidden="true" data-hidden="true" class="fa fa-file-text-o fa-fw"></i>',
+ file_hash: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a',
+ file_path: 'CHANGELOG',
+ new_file: false,
+ deleted_file: false,
+ renamed_file: false,
+ old_path: 'CHANGELOG',
+ new_path: 'CHANGELOG',
+ mode_changed: false,
+ a_mode: '100644',
+ b_mode: '100644',
text: true,
- addedLines: 2,
- removedLines: 0,
- diffRefs: {
- baseSha: 'e63f41fe459e62e1228fcef60d7189127aeba95a',
- startSha: 'd9eaefe5a676b820c57ff18cf5b68316025f7962',
- headSha: 'c48ee0d1bf3b30453f5b32250ce03134beaa6d13',
+ viewer: {
+ name: 'text',
},
- contentSha: 'c48ee0d1bf3b30453f5b32250ce03134beaa6d13',
- storedExternally: null,
- externalStorage: null,
- oldPathHtml: ['CHANGELOG', 'CHANGELOG'],
- newPathHtml: 'CHANGELOG',
- editPath: '/gitlab-org/gitlab-test/edit/spooky-stuff/CHANGELOG',
- viewPath: '/gitlab-org/gitlab-test/blob/spooky-stuff/CHANGELOG',
- replacedViewPath: null,
+ added_lines: 2,
+ removed_lines: 0,
+ diff_refs: {
+ base_sha: 'e63f41fe459e62e1228fcef60d7189127aeba95a',
+ start_sha: 'd9eaefe5a676b820c57ff18cf5b68316025f7962',
+ head_sha: 'c48ee0d1bf3b30453f5b32250ce03134beaa6d13',
+ },
+ content_sha: 'c48ee0d1bf3b30453f5b32250ce03134beaa6d13',
+ stored_externally: null,
+ external_storage: null,
+ old_path_html: 'CHANGELOG',
+ new_path_html: 'CHANGELOG',
+ edit_path: '/gitlab-org/gitlab-test/edit/spooky-stuff/CHANGELOG',
+ view_path: '/gitlab-org/gitlab-test/blob/spooky-stuff/CHANGELOG',
+ replaced_view_path: null,
collapsed: false,
renderIt: false,
- tooLarge: false,
- contextLinesPath:
+ too_large: false,
+ context_lines_path:
'/gitlab-org/gitlab-test/blob/c48ee0d1bf3b30453f5b32250ce03134beaa6d13/CHANGELOG/diff',
- highlightedDiffLines: [
+ highlighted_diff_lines: [
{
- lineCode: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_1',
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_1',
type: 'new',
- oldLine: null,
- newLine: 1,
+ old_line: null,
+ new_line: 1,
discussions: [],
text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
- richText: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
- metaData: null,
+ rich_text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
+ meta_data: null,
},
{
- lineCode: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_2',
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_2',
type: 'new',
- oldLine: null,
- newLine: 2,
+ old_line: null,
+ new_line: 2,
discussions: [],
text: '+<span id="LC2" class="line" lang="plaintext"></span>\n',
- richText: '+<span id="LC2" class="line" lang="plaintext"></span>\n',
- metaData: null,
+ rich_text: '+<span id="LC2" class="line" lang="plaintext"></span>\n',
+ meta_data: null,
},
{
- lineCode: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_3',
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_3',
type: null,
- oldLine: 1,
- newLine: 3,
+ old_line: 1,
+ new_line: 3,
discussions: [],
text: ' <span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
- richText: ' <span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
- metaData: null,
+ rich_text: ' <span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
+ meta_data: null,
},
{
- lineCode: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_2_4',
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_2_4',
type: null,
- oldLine: 2,
- newLine: 4,
+ old_line: 2,
+ new_line: 4,
discussions: [],
text: ' <span id="LC4" class="line" lang="plaintext"></span>\n',
- richText: ' <span id="LC4" class="line" lang="plaintext"></span>\n',
- metaData: null,
+ rich_text: ' <span id="LC4" class="line" lang="plaintext"></span>\n',
+ meta_data: null,
},
{
- lineCode: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_3_5',
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_3_5',
type: null,
- oldLine: 3,
- newLine: 5,
+ old_line: 3,
+ new_line: 5,
discussions: [],
text: ' <span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
- richText: ' <span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
- metaData: null,
+ rich_text: ' <span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
+ meta_data: null,
},
{
- lineCode: null,
+ line_code: null,
type: 'match',
- oldLine: null,
- newLine: null,
+ old_line: null,
+ new_line: null,
discussions: [],
text: '',
- richText: '',
- metaData: {
- oldPos: 3,
- newPos: 5,
+ rich_text: '',
+ meta_data: {
+ old_pos: 3,
+ new_pos: 5,
},
},
],
- parallelDiffLines: [
+ parallel_diff_lines: [
{
left: {
type: 'empty-cell',
},
right: {
- lineCode: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_1',
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_1',
type: 'new',
- oldLine: null,
- newLine: 1,
+ old_line: null,
+ new_line: 1,
discussions: [],
text: '+<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
- richText: '<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
- metaData: null,
+ rich_text: '<span id="LC1" class="line" lang="plaintext"> - Bad dates</span>\n',
+ meta_data: null,
},
},
{
@@ -129,109 +132,110 @@ export default {
type: 'empty-cell',
},
right: {
- lineCode: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_2',
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_2',
type: 'new',
- oldLine: null,
- newLine: 2,
+ old_line: null,
+ new_line: 2,
discussions: [],
text: '+<span id="LC2" class="line" lang="plaintext"></span>\n',
- richText: '<span id="LC2" class="line" lang="plaintext"></span>\n',
- metaData: null,
+ rich_text: '<span id="LC2" class="line" lang="plaintext"></span>\n',
+ meta_data: null,
},
},
{
left: {
- lineCode: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_3',
+ line_Code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_3',
type: null,
- oldLine: 1,
- newLine: 3,
+ old_line: 1,
+ new_line: 3,
discussions: [],
text: ' <span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
- richText: '<span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
- metaData: null,
+ rich_text: '<span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
+ meta_data: null,
},
right: {
- lineCode: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_3',
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_3',
type: null,
- oldLine: 1,
- newLine: 3,
+ old_line: 1,
+ new_line: 3,
discussions: [],
text: ' <span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
- richText: '<span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
- metaData: null,
+ rich_text: '<span id="LC3" class="line" lang="plaintext">v6.8.0</span>\n',
+ meta_data: null,
},
},
{
left: {
- lineCode: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_2_4',
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_2_4',
type: null,
- oldLine: 2,
- newLine: 4,
+ old_line: 2,
+ new_line: 4,
discussions: [],
text: ' <span id="LC4" class="line" lang="plaintext"></span>\n',
- richText: '<span id="LC4" class="line" lang="plaintext"></span>\n',
- metaData: null,
+ rich_text: '<span id="LC4" class="line" lang="plaintext"></span>\n',
+ meta_data: null,
},
right: {
- lineCode: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_2_4',
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_2_4',
type: null,
- oldLine: 2,
- newLine: 4,
+ old_line: 2,
+ new_line: 4,
discussions: [],
text: ' <span id="LC4" class="line" lang="plaintext"></span>\n',
- richText: '<span id="LC4" class="line" lang="plaintext"></span>\n',
- metaData: null,
+ rich_text: '<span id="LC4" class="line" lang="plaintext"></span>\n',
+ meta_data: null,
},
},
{
left: {
- lineCode: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_3_5',
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_3_5',
type: null,
- oldLine: 3,
- newLine: 5,
+ old_line: 3,
+ new_line: 5,
discussions: [],
text: ' <span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
- richText: '<span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
- metaData: null,
+ rich_text: '<span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
+ meta_data: null,
},
right: {
- lineCode: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_3_5',
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_3_5',
type: null,
- oldLine: 3,
- newLine: 5,
+ old_line: 3,
+ new_line: 5,
discussions: [],
text: ' <span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
- richText: '<span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
- metaData: null,
+ rich_text: '<span id="LC5" class="line" lang="plaintext">v6.7.0</span>\n',
+ meta_data: null,
},
},
{
left: {
- lineCode: null,
+ line_code: null,
type: 'match',
- oldLine: null,
- newLine: null,
+ old_line: null,
+ new_line: null,
discussions: [],
text: '',
- richText: '',
- metaData: {
- oldPos: 3,
- newPos: 5,
+ rich_text: '',
+ meta_data: {
+ old_pos: 3,
+ new_pos: 5,
},
},
right: {
- lineCode: null,
+ line_code: null,
type: 'match',
- oldLine: null,
- newLine: null,
+ old_line: null,
+ new_line: null,
discussions: [],
text: '',
- richText: '',
- metaData: {
- oldPos: 3,
- newPos: 5,
+ rich_text: '',
+ meta_data: {
+ old_pos: 3,
+ new_pos: 5,
},
},
},
],
+ discussions: [],
};
diff --git a/spec/javascripts/diffs/mock_data/diff_with_commit.js b/spec/javascripts/diffs/mock_data/diff_with_commit.js
new file mode 100644
index 00000000000..d646294ee84
--- /dev/null
+++ b/spec/javascripts/diffs/mock_data/diff_with_commit.js
@@ -0,0 +1,7 @@
+const FIXTURE = 'merge_request_diffs/with_commit.json';
+
+preloadFixtures(FIXTURE);
+
+export default function getDiffWithCommit() {
+ return getJSONFixture(FIXTURE);
+}
diff --git a/spec/javascripts/diffs/mock_data/merge_request_diffs.js b/spec/javascripts/diffs/mock_data/merge_request_diffs.js
new file mode 100644
index 00000000000..d72ad7818dd
--- /dev/null
+++ b/spec/javascripts/diffs/mock_data/merge_request_diffs.js
@@ -0,0 +1,42 @@
+export default [
+ {
+ versionIndex: 4,
+ createdAt: '2018-10-23T11:49:16.611Z',
+ commitsCount: 4,
+ latest: true,
+ shortCommitSha: 'de7a8f7f',
+ versionPath: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=37',
+ comparePath:
+ '/gnuwget/wget2/merge_requests/6/diffs?diff_id=37&start_sha=de7a8f7f20c3ea2e0bef3ba01cfd41c21f6b4995',
+ },
+ {
+ versionIndex: 3,
+ createdAt: '2018-10-23T11:46:40.617Z',
+ commitsCount: 3,
+ latest: false,
+ shortCommitSha: 'e78fc18f',
+ versionPath: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=36',
+ comparePath:
+ '/gnuwget/wget2/merge_requests/6/diffs?diff_id=37&start_sha=e78fc18fa37acb2185c59ca94d4a964464feb50e',
+ },
+ {
+ versionIndex: 2,
+ createdAt: '2018-10-04T09:57:39.648Z',
+ commitsCount: 2,
+ latest: false,
+ shortCommitSha: '48da7e7e',
+ versionPath: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=35',
+ comparePath:
+ '/gnuwget/wget2/merge_requests/6/diffs?diff_id=37&start_sha=48da7e7e9a99d41c852578bd9cb541ca4d864b3e',
+ },
+ {
+ versionIndex: 1,
+ createdAt: '2018-09-25T20:30:39.493Z',
+ commitsCount: 1,
+ latest: false,
+ shortCommitSha: '47bac2ed',
+ versionPath: '/gnuwget/wget2/merge_requests/6/diffs?diff_id=20',
+ comparePath:
+ '/gnuwget/wget2/merge_requests/6/diffs?diff_id=37&start_sha=47bac2ed972c5bee344c1cea159a22cd7f711dc0',
+ },
+];
diff --git a/spec/javascripts/diffs/store/actions_spec.js b/spec/javascripts/diffs/store/actions_spec.js
index 4c662fac231..205138bd845 100644
--- a/spec/javascripts/diffs/store/actions_spec.js
+++ b/spec/javascripts/diffs/store/actions_spec.js
@@ -21,9 +21,13 @@ import actions, {
loadCollapsedDiff,
expandAllFiles,
toggleFileDiscussions,
+ saveDiffDiscussion,
+ setHighlightedRow,
+ toggleTreeOpen,
+ scrollToFile,
+ toggleShowTreeList,
} from '~/diffs/store/actions';
import * as types from '~/diffs/store/mutation_types';
-import { reduceDiscussionsToLineCodes } from '~/notes/stores/utils';
import axios from '~/lib/utils/axios_utils';
import testAction from '../../helpers/vuex_action_helper';
@@ -89,51 +93,59 @@ describe('DiffsStoreActions', () => {
});
});
+ describe('setHighlightedRow', () => {
+ it('should set lineHash and fileHash of highlightedRow', () => {
+ testAction(setHighlightedRow, 'ABC_123', {}, [
+ { type: types.SET_HIGHLIGHTED_ROW, payload: 'ABC_123' },
+ ]);
+ });
+ });
+
describe('assignDiscussionsToDiff', () => {
it('should merge discussions into diffs', done => {
const state = {
diffFiles: [
{
- fileHash: 'ABC',
- parallelDiffLines: [
+ file_hash: 'ABC',
+ parallel_diff_lines: [
{
left: {
- lineCode: 'ABC_1_1',
+ line_code: 'ABC_1_1',
discussions: [],
},
right: {
- lineCode: 'ABC_1_1',
+ line_code: 'ABC_1_1',
discussions: [],
},
},
],
- highlightedDiffLines: [
+ highlighted_diff_lines: [
{
- lineCode: 'ABC_1_1',
+ line_code: 'ABC_1_1',
discussions: [],
- oldLine: 5,
- newLine: null,
+ old_line: 5,
+ new_line: null,
},
],
- diffRefs: {
- baseSha: 'abc',
- headSha: 'def',
- startSha: 'ghi',
+ diff_refs: {
+ base_sha: 'abc',
+ head_sha: 'def',
+ start_sha: 'ghi',
},
- newPath: 'file1',
- oldPath: 'file2',
+ new_path: 'file1',
+ old_path: 'file2',
},
],
};
const diffPosition = {
- baseSha: 'abc',
- headSha: 'def',
- startSha: 'ghi',
- newLine: null,
- newPath: 'file1',
- oldLine: 5,
- oldPath: 'file2',
+ base_sha: 'abc',
+ head_sha: 'def',
+ start_sha: 'ghi',
+ new_line: null,
+ new_path: 'file1',
+ old_line: 5,
+ old_path: 'file2',
};
const singleDiscussion = {
@@ -142,17 +154,13 @@ describe('DiffsStoreActions', () => {
diff_file: {
file_hash: 'ABC',
},
- fileHash: 'ABC',
+ file_hash: 'ABC',
resolvable: true,
- position: {
- formatter: diffPosition,
- },
- original_position: {
- formatter: diffPosition,
- },
+ position: diffPosition,
+ original_position: diffPosition,
};
- const discussions = reduceDiscussionsToLineCodes([singleDiscussion]);
+ const discussions = [singleDiscussion];
testAction(
assignDiscussionsToDiff,
@@ -162,27 +170,25 @@ describe('DiffsStoreActions', () => {
{
type: types.SET_LINE_DISCUSSIONS_FOR_FILE,
payload: {
- fileHash: 'ABC',
- discussions: [singleDiscussion],
+ discussion: singleDiscussion,
diffPositionByLineCode: {
ABC_1_1: {
- baseSha: 'abc',
- headSha: 'def',
- startSha: 'ghi',
- newLine: null,
- newPath: 'file1',
- oldLine: 5,
- oldPath: 'file2',
- lineCode: 'ABC_1_1',
+ base_sha: 'abc',
+ head_sha: 'def',
+ start_sha: 'ghi',
+ new_line: null,
+ new_path: 'file1',
+ old_line: 5,
+ old_path: 'file2',
+ line_code: 'ABC_1_1',
+ position_type: 'text',
},
},
},
},
],
[],
- () => {
- done();
- },
+ done,
);
});
});
@@ -192,11 +198,11 @@ describe('DiffsStoreActions', () => {
const state = {
diffFiles: [
{
- fileHash: 'ABC',
- parallelDiffLines: [
+ file_hash: 'ABC',
+ parallel_diff_lines: [
{
left: {
- lineCode: 'ABC_1_1',
+ line_code: 'ABC_1_1',
discussions: [
{
id: 1,
@@ -204,14 +210,14 @@ describe('DiffsStoreActions', () => {
],
},
right: {
- lineCode: 'ABC_1_1',
+ line_code: 'ABC_1_1',
discussions: [],
},
},
],
- highlightedDiffLines: [
+ highlighted_diff_lines: [
{
- lineCode: 'ABC_1_1',
+ line_code: 'ABC_1_1',
discussions: [],
},
],
@@ -219,7 +225,8 @@ describe('DiffsStoreActions', () => {
],
};
const singleDiscussion = {
- fileHash: 'ABC',
+ id: '1',
+ file_hash: 'ABC',
line_code: 'ABC_1_1',
};
@@ -231,21 +238,20 @@ describe('DiffsStoreActions', () => {
{
type: types.REMOVE_LINE_DISCUSSIONS_FOR_FILE,
payload: {
+ id: '1',
fileHash: 'ABC',
lineCode: 'ABC_1_1',
},
},
],
[],
- () => {
- done();
- },
+ done,
);
});
});
describe('startRenderDiffsQueue', () => {
- it('should set all files to RENDER_FILE', done => {
+ it('should set all files to RENDER_FILE', () => {
const state = {
diffFiles: [
{
@@ -268,16 +274,10 @@ describe('DiffsStoreActions', () => {
});
};
- startRenderDiffsQueue({ state, commit: pseudoCommit })
- .then(() => {
- expect(state.diffFiles[0].renderIt).toBeTruthy();
- expect(state.diffFiles[1].renderIt).toBeTruthy();
+ startRenderDiffsQueue({ state, commit: pseudoCommit });
- done();
- })
- .catch(() => {
- done.fail();
- });
+ expect(state.diffFiles[0].renderIt).toBe(true);
+ expect(state.diffFiles[1].renderIt).toBe(true);
});
});
@@ -319,13 +319,13 @@ describe('DiffsStoreActions', () => {
describe('showCommentForm', () => {
it('should call mutation to show comment form', done => {
- const payload = { lineCode: 'lineCode' };
+ const payload = { lineCode: 'lineCode', fileHash: 'hash' };
testAction(
showCommentForm,
payload,
{},
- [{ type: types.ADD_COMMENT_FORM_LINE, payload }],
+ [{ type: types.TOGGLE_LINE_HAS_FORM, payload: { ...payload, hasForm: true } }],
[],
done,
);
@@ -334,13 +334,13 @@ describe('DiffsStoreActions', () => {
describe('cancelCommentForm', () => {
it('should call mutation to cancel comment form', done => {
- const payload = { lineCode: 'lineCode' };
+ const payload = { lineCode: 'lineCode', fileHash: 'hash' };
testAction(
cancelCommentForm,
payload,
{},
- [{ type: types.REMOVE_COMMENT_FORM_LINE, payload }],
+ [{ type: types.TOGGLE_LINE_HAS_FORM, payload: { ...payload, hasForm: false } }],
[],
done,
);
@@ -425,7 +425,7 @@ describe('DiffsStoreActions', () => {
const getters = {
getDiffFileDiscussions: jasmine.createSpy().and.returnValue([{ id: 1 }]),
diffHasAllExpandedDiscussions: jasmine.createSpy().and.returnValue(true),
- diffHasAllCollpasedDiscussions: jasmine.createSpy().and.returnValue(false),
+ diffHasAllCollapsedDiscussions: jasmine.createSpy().and.returnValue(false),
};
const dispatch = jasmine.createSpy('dispatch');
@@ -443,7 +443,7 @@ describe('DiffsStoreActions', () => {
const getters = {
getDiffFileDiscussions: jasmine.createSpy().and.returnValue([{ id: 1 }]),
diffHasAllExpandedDiscussions: jasmine.createSpy().and.returnValue(false),
- diffHasAllCollpasedDiscussions: jasmine.createSpy().and.returnValue(true),
+ diffHasAllCollapsedDiscussions: jasmine.createSpy().and.returnValue(true),
};
const dispatch = jasmine.createSpy();
@@ -461,7 +461,7 @@ describe('DiffsStoreActions', () => {
const getters = {
getDiffFileDiscussions: jasmine.createSpy().and.returnValue([{ expanded: false, id: 1 }]),
diffHasAllExpandedDiscussions: jasmine.createSpy().and.returnValue(false),
- diffHasAllCollpasedDiscussions: jasmine.createSpy().and.returnValue(false),
+ diffHasAllCollapsedDiscussions: jasmine.createSpy().and.returnValue(false),
};
const dispatch = jasmine.createSpy();
@@ -478,7 +478,7 @@ describe('DiffsStoreActions', () => {
describe('scrollToLineIfNeededInline', () => {
const lineMock = {
- lineCode: 'ABC_123',
+ line_code: 'ABC_123',
};
it('should not call handleLocationHash when there is not hash', () => {
@@ -529,7 +529,7 @@ describe('DiffsStoreActions', () => {
const lineMock = {
left: null,
right: {
- lineCode: 'ABC_123',
+ line_code: 'ABC_123',
},
};
@@ -582,4 +582,118 @@ describe('DiffsStoreActions', () => {
expect(handleLocationHashSpy).toHaveBeenCalledTimes(1);
});
});
+
+ describe('saveDiffDiscussion', () => {
+ beforeEach(() => {
+ spyOnDependency(actions, 'getNoteFormData').and.returnValue('testData');
+ });
+
+ it('dispatches actions', done => {
+ const dispatch = jasmine.createSpy('dispatch').and.callFake(name => {
+ switch (name) {
+ case 'saveNote':
+ return Promise.resolve({
+ discussion: 'test',
+ });
+ case 'updateDiscussion':
+ return Promise.resolve('discussion');
+ default:
+ return Promise.resolve({});
+ }
+ });
+
+ saveDiffDiscussion({ dispatch }, { note: {}, formData: {} })
+ .then(() => {
+ expect(dispatch.calls.argsFor(0)).toEqual(['saveNote', 'testData', { root: true }]);
+ expect(dispatch.calls.argsFor(1)).toEqual(['updateDiscussion', 'test', { root: true }]);
+ expect(dispatch.calls.argsFor(2)).toEqual(['assignDiscussionsToDiff', ['discussion']]);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('toggleTreeOpen', () => {
+ it('commits TOGGLE_FOLDER_OPEN', done => {
+ testAction(
+ toggleTreeOpen,
+ 'path',
+ {},
+ [{ type: types.TOGGLE_FOLDER_OPEN, payload: 'path' }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('scrollToFile', () => {
+ let commit;
+
+ beforeEach(() => {
+ commit = jasmine.createSpy();
+ jasmine.clock().install();
+ });
+
+ afterEach(() => {
+ jasmine.clock().uninstall();
+ });
+
+ it('updates location hash', () => {
+ const state = {
+ treeEntries: {
+ path: {
+ fileHash: 'test',
+ },
+ },
+ };
+
+ scrollToFile({ state, commit }, 'path');
+
+ expect(document.location.hash).toBe('#test');
+ });
+
+ it('commits UPDATE_CURRENT_DIFF_FILE_ID', () => {
+ const state = {
+ treeEntries: {
+ path: {
+ fileHash: 'test',
+ },
+ },
+ };
+
+ scrollToFile({ state, commit }, 'path');
+
+ expect(commit).toHaveBeenCalledWith(types.UPDATE_CURRENT_DIFF_FILE_ID, 'test');
+ });
+
+ it('resets currentDiffId after timeout', () => {
+ const state = {
+ treeEntries: {
+ path: {
+ fileHash: 'test',
+ },
+ },
+ };
+
+ scrollToFile({ state, commit }, 'path');
+
+ jasmine.clock().tick(1000);
+
+ expect(commit.calls.argsFor(1)).toEqual([types.UPDATE_CURRENT_DIFF_FILE_ID, '']);
+ });
+ });
+
+ describe('toggleShowTreeList', () => {
+ it('commits toggle', done => {
+ testAction(toggleShowTreeList, null, {}, [{ type: types.TOGGLE_SHOW_TREE_LIST }], [], done);
+ });
+
+ it('updates localStorage', () => {
+ spyOn(localStorage, 'setItem');
+
+ toggleShowTreeList({ commit() {}, state: { showTreeList: true } });
+
+ expect(localStorage.setItem).toHaveBeenCalledWith('mr_tree_show', true);
+ });
+ });
});
diff --git a/spec/javascripts/diffs/store/getters_spec.js b/spec/javascripts/diffs/store/getters_spec.js
index 4747e437c4e..582535e0a53 100644
--- a/spec/javascripts/diffs/store/getters_spec.js
+++ b/spec/javascripts/diffs/store/getters_spec.js
@@ -49,15 +49,17 @@ describe('Diffs Module Getters', () => {
});
});
- describe('areAllFilesCollapsed', () => {
+ describe('hasCollapsedFile', () => {
it('returns true when all files are collapsed', () => {
localState.diffFiles = [{ collapsed: true }, { collapsed: true }];
- expect(getters.areAllFilesCollapsed(localState)).toEqual(true);
+
+ expect(getters.hasCollapsedFile(localState)).toEqual(true);
});
- it('returns false when at least one file is not collapsed', () => {
+ it('returns true when at least one file is collapsed', () => {
localState.diffFiles = [{ collapsed: false }, { collapsed: true }];
- expect(getters.areAllFilesCollapsed(localState)).toEqual(false);
+
+ expect(getters.hasCollapsedFile(localState)).toEqual(true);
});
});
@@ -104,13 +106,13 @@ describe('Diffs Module Getters', () => {
});
});
- describe('diffHasAllCollpasedDiscussions', () => {
+ describe('diffHasAllCollapsedDiscussions', () => {
it('returns true when all discussions are collapsed', () => {
discussionMock.diff_file.file_hash = diffFileMock.fileHash;
discussionMock.expanded = false;
expect(
- getters.diffHasAllCollpasedDiscussions(localState, {
+ getters.diffHasAllCollapsedDiscussions(localState, {
getDiffFileDiscussions: () => [discussionMock],
})(diffFileMock),
).toEqual(true);
@@ -118,7 +120,7 @@ describe('Diffs Module Getters', () => {
it('returns false when there are no discussions', () => {
expect(
- getters.diffHasAllCollpasedDiscussions(localState, {
+ getters.diffHasAllCollapsedDiscussions(localState, {
getDiffFileDiscussions: () => [],
})(diffFileMock),
).toEqual(false);
@@ -128,7 +130,7 @@ describe('Diffs Module Getters', () => {
discussionMock1.expanded = false;
expect(
- getters.diffHasAllCollpasedDiscussions(localState, {
+ getters.diffHasAllCollapsedDiscussions(localState, {
getDiffFileDiscussions: () => [discussionMock, discussionMock1],
})(diffFileMock),
).toEqual(false);
@@ -184,79 +186,9 @@ describe('Diffs Module Getters', () => {
});
});
- describe('shouldRenderParallelCommentRow', () => {
- let line;
-
- beforeEach(() => {
- line = {};
-
- discussionMock.expanded = true;
-
- line.left = {
- lineCode: 'ABC',
- discussions: [discussionMock],
- };
-
- line.right = {
- lineCode: 'DEF',
- discussions: [discussionMock1],
- };
- });
-
- it('returns true when discussion is expanded', () => {
- expect(getters.shouldRenderParallelCommentRow(localState)(line)).toEqual(true);
- });
-
- it('returns false when no discussion was found', () => {
- line.left.discussions = [];
- line.right.discussions = [];
-
- localState.diffLineCommentForms.ABC = false;
- localState.diffLineCommentForms.DEF = false;
-
- expect(getters.shouldRenderParallelCommentRow(localState)(line)).toEqual(false);
- });
-
- it('returns true when discussionForm was found', () => {
- localState.diffLineCommentForms.ABC = {};
-
- expect(getters.shouldRenderParallelCommentRow(localState)(line)).toEqual(true);
- });
- });
-
- describe('shouldRenderInlineCommentRow', () => {
- let line;
-
- beforeEach(() => {
- discussionMock.expanded = true;
-
- line = {
- lineCode: 'ABC',
- discussions: [discussionMock],
- };
- });
-
- it('returns true when diffLineCommentForms has form', () => {
- localState.diffLineCommentForms.ABC = {};
-
- expect(getters.shouldRenderInlineCommentRow(localState)(line)).toEqual(true);
- });
-
- it('returns false when no line discussions were found', () => {
- line.discussions = [];
- expect(getters.shouldRenderInlineCommentRow(localState)(line)).toEqual(false);
- });
-
- it('returns true if all found discussions are expanded', () => {
- discussionMock.expanded = true;
-
- expect(getters.shouldRenderInlineCommentRow(localState)(line)).toEqual(true);
- });
- });
-
describe('getDiffFileDiscussions', () => {
it('returns an array with discussions when fileHash matches and the discussion belongs to a diff', () => {
- discussionMock.diff_file.file_hash = diffFileMock.fileHash;
+ discussionMock.diff_file.file_hash = diffFileMock.file_hash;
expect(
getters.getDiffFileDiscussions(localState, {}, {}, { discussions: [discussionMock] })(
@@ -276,10 +208,10 @@ describe('Diffs Module Getters', () => {
describe('getDiffFileByHash', () => {
it('returns file by hash', () => {
const fileA = {
- fileHash: '123',
+ file_hash: '123',
};
const fileB = {
- fileHash: '456',
+ file_hash: '456',
};
localState.diffFiles = [fileA, fileB];
@@ -288,7 +220,35 @@ describe('Diffs Module Getters', () => {
it('returns null if no matching file is found', () => {
localState.diffFiles = [];
+
expect(getters.getDiffFileByHash(localState)('123')).toBeUndefined();
});
});
+
+ describe('allBlobs', () => {
+ it('returns an array of blobs', () => {
+ localState.treeEntries = {
+ file: {
+ type: 'blob',
+ },
+ tree: {
+ type: 'tree',
+ },
+ };
+
+ expect(getters.allBlobs(localState)).toEqual([
+ {
+ type: 'blob',
+ },
+ ]);
+ });
+ });
+
+ describe('diffFilesLength', () => {
+ it('returns length of diff files', () => {
+ localState.diffFiles.push('test', 'test 2');
+
+ expect(getters.diffFilesLength(localState)).toBe(2);
+ });
+ });
});
diff --git a/spec/javascripts/diffs/store/mutations_spec.js b/spec/javascripts/diffs/store/mutations_spec.js
index 9a5d8dfbd15..7a06c178f0b 100644
--- a/spec/javascripts/diffs/store/mutations_spec.js
+++ b/spec/javascripts/diffs/store/mutations_spec.js
@@ -1,3 +1,4 @@
+import createState from '~/diffs/store/modules/diff_state';
import mutations from '~/diffs/store/mutations';
import * as types from '~/diffs/store/mutation_types';
import { INLINE_DIFF_VIEW_TYPE } from '~/diffs/constants';
@@ -11,6 +12,7 @@ describe('DiffsStoreMutations', () => {
const projectPath = '/root/project';
mutations[types.SET_BASE_CONFIG](state, { endpoint, projectPath });
+
expect(state.endpoint).toEqual(endpoint);
expect(state.projectPath).toEqual(projectPath);
});
@@ -21,6 +23,7 @@ describe('DiffsStoreMutations', () => {
const state = {};
mutations[types.SET_LOADING](state, false);
+
expect(state.isLoading).toEqual(false);
});
});
@@ -34,7 +37,7 @@ describe('DiffsStoreMutations', () => {
mutations[types.SET_DIFF_DATA](state, diffMock);
- const firstLine = state.diffFiles[0].parallelDiffLines[0];
+ const firstLine = state.diffFiles[0].parallel_diff_lines[0];
expect(firstLine.right.text).toBeUndefined();
expect(state.diffFiles[0].renderIt).toEqual(true);
@@ -47,30 +50,8 @@ describe('DiffsStoreMutations', () => {
const state = {};
mutations[types.SET_DIFF_VIEW_TYPE](state, INLINE_DIFF_VIEW_TYPE);
- expect(state.diffViewType).toEqual(INLINE_DIFF_VIEW_TYPE);
- });
- });
-
- describe('ADD_COMMENT_FORM_LINE', () => {
- it('should set a truthy reference for the given line code in diffLineCommentForms', () => {
- const state = { diffLineCommentForms: {} };
- const lineCode = 'FDE';
-
- mutations[types.ADD_COMMENT_FORM_LINE](state, { lineCode });
- expect(state.diffLineCommentForms[lineCode]).toBeTruthy();
- });
- });
- describe('REMOVE_COMMENT_FORM_LINE', () => {
- it('should remove given reference from diffLineCommentForms', () => {
- const state = { diffLineCommentForms: {} };
- const lineCode = 'FDE';
-
- mutations[types.ADD_COMMENT_FORM_LINE](state, { lineCode });
- expect(state.diffLineCommentForms[lineCode]).toBeTruthy();
-
- mutations[types.REMOVE_COMMENT_FORM_LINE](state, { lineCode });
- expect(state.diffLineCommentForms[lineCode]).toBeUndefined();
+ expect(state.diffViewType).toEqual(INLINE_DIFF_VIEW_TYPE);
});
});
@@ -82,6 +63,7 @@ describe('DiffsStoreMutations', () => {
const state = { expandAllFiles: true, diffFiles: [diffFile] };
mutations[types.EXPAND_ALL_FILES](state);
+
expect(state.diffFiles[0].collapsed).toEqual(false);
});
});
@@ -90,19 +72,21 @@ describe('DiffsStoreMutations', () => {
it('should call utils.addContextLines with proper params', () => {
const options = {
lineNumbers: { oldLineNumber: 1, newLineNumber: 2 },
- contextLines: [{ oldLine: 1 }],
+ contextLines: [
+ { old_line: 1, new_line: 1, line_code: 'ff9200_1_1', discussions: [], hasForm: false },
+ ],
fileHash: 'ff9200',
params: {
bottom: true,
},
};
const diffFile = {
- fileHash: options.fileHash,
- highlightedDiffLines: [],
- parallelDiffLines: [],
+ file_hash: options.fileHash,
+ highlighted_diff_lines: [],
+ parallel_diff_lines: [],
};
const state = { diffFiles: [diffFile] };
- const lines = [{ oldLine: 1 }];
+ const lines = [{ old_line: 1, new_line: 1 }];
const findDiffFileSpy = spyOnDependency(mutations, 'findDiffFile').and.returnValue(diffFile);
const removeMatchLineSpy = spyOnDependency(mutations, 'removeMatchLine');
@@ -117,14 +101,16 @@ describe('DiffsStoreMutations', () => {
options.lineNumbers,
options.params.bottom,
);
+
expect(lineRefSpy).toHaveBeenCalledWith(
options.contextLines,
options.lineNumbers,
options.params.bottom,
);
+
expect(addContextLinesSpy).toHaveBeenCalledWith({
- inlineLines: diffFile.highlightedDiffLines,
- parallelLines: diffFile.parallelDiffLines,
+ inlineLines: diffFile.highlighted_diff_lines,
+ parallelLines: diffFile.parallel_diff_lines,
contextLines: options.contextLines,
bottom: options.params.bottom,
lineNumbers: options.lineNumbers,
@@ -134,171 +120,147 @@ describe('DiffsStoreMutations', () => {
describe('ADD_COLLAPSED_DIFFS', () => {
it('should update the state with the given data for the given file hash', () => {
- const spy = spyOnDependency(mutations, 'convertObjectPropsToCamelCase').and.callThrough();
-
const fileHash = 123;
- const state = { diffFiles: [{}, { fileHash, existingField: 0 }] };
- const data = { diff_files: [{ file_hash: fileHash, extra_field: 1, existingField: 1 }] };
+ const state = { diffFiles: [{}, { file_hash: fileHash, existing_field: 0 }] };
+ const data = { diff_files: [{ file_hash: fileHash, extra_field: 1, existing_field: 1 }] };
mutations[types.ADD_COLLAPSED_DIFFS](state, { file: state.diffFiles[1], data });
- expect(spy).toHaveBeenCalledWith(data, { deep: true });
- expect(state.diffFiles[1].fileHash).toEqual(fileHash);
- expect(state.diffFiles[1].existingField).toEqual(1);
- expect(state.diffFiles[1].extraField).toEqual(1);
+ expect(state.diffFiles[1].file_hash).toEqual(fileHash);
+ expect(state.diffFiles[1].existing_field).toEqual(1);
+ expect(state.diffFiles[1].extra_field).toEqual(1);
});
});
describe('SET_LINE_DISCUSSIONS_FOR_FILE', () => {
it('should add discussions to the given line', () => {
const diffPosition = {
- baseSha: 'ed13df29948c41ba367caa757ab3ec4892509910',
- headSha: 'b921914f9a834ac47e6fd9420f78db0f83559130',
- newLine: null,
- newPath: '500-lines-4.txt',
- oldLine: 5,
- oldPath: '500-lines-4.txt',
- startSha: 'ed13df29948c41ba367caa757ab3ec4892509910',
+ base_sha: 'ed13df29948c41ba367caa757ab3ec4892509910',
+ head_sha: 'b921914f9a834ac47e6fd9420f78db0f83559130',
+ new_line: null,
+ new_path: '500-lines-4.txt',
+ old_line: 5,
+ old_path: '500-lines-4.txt',
+ start_sha: 'ed13df29948c41ba367caa757ab3ec4892509910',
};
const state = {
latestDiff: true,
diffFiles: [
{
- fileHash: 'ABC',
- parallelDiffLines: [
+ file_hash: 'ABC',
+ parallel_diff_lines: [
{
left: {
- lineCode: 'ABC_1',
+ line_code: 'ABC_1',
discussions: [],
},
right: {
- lineCode: 'ABC_1',
+ line_code: 'ABC_1',
discussions: [],
},
},
],
- highlightedDiffLines: [
+ highlighted_diff_lines: [
{
- lineCode: 'ABC_1',
+ line_code: 'ABC_1',
discussions: [],
},
],
},
],
};
- const discussions = [
- {
- id: 1,
- line_code: 'ABC_1',
- diff_discussion: true,
- resolvable: true,
- original_position: {
- formatter: diffPosition,
- },
- position: {
- formatter: diffPosition,
- },
- },
- {
- id: 2,
- line_code: 'ABC_1',
- diff_discussion: true,
- resolvable: true,
- original_position: {
- formatter: diffPosition,
- },
- position: {
- formatter: diffPosition,
- },
+ const discussion = {
+ id: 1,
+ line_code: 'ABC_1',
+ diff_discussion: true,
+ resolvable: true,
+ original_position: diffPosition,
+ position: diffPosition,
+ diff_file: {
+ file_hash: state.diffFiles[0].file_hash,
},
- ];
+ };
const diffPositionByLineCode = {
ABC_1: diffPosition,
};
mutations[types.SET_LINE_DISCUSSIONS_FOR_FILE](state, {
- fileHash: 'ABC',
- discussions,
+ discussion,
diffPositionByLineCode,
});
- expect(state.diffFiles[0].parallelDiffLines[0].left.discussions.length).toEqual(2);
- expect(state.diffFiles[0].parallelDiffLines[0].left.discussions[1].id).toEqual(2);
+ expect(state.diffFiles[0].parallel_diff_lines[0].left.discussions.length).toEqual(1);
+ expect(state.diffFiles[0].parallel_diff_lines[0].left.discussions[0].id).toEqual(1);
+ expect(state.diffFiles[0].parallel_diff_lines[0].right.discussions).toEqual([]);
- expect(state.diffFiles[0].highlightedDiffLines[0].discussions.length).toEqual(2);
- expect(state.diffFiles[0].highlightedDiffLines[0].discussions[1].id).toEqual(2);
+ expect(state.diffFiles[0].highlighted_diff_lines[0].discussions.length).toEqual(1);
+ expect(state.diffFiles[0].highlighted_diff_lines[0].discussions[0].id).toEqual(1);
});
it('should add legacy discussions to the given line', () => {
const diffPosition = {
- baseSha: 'ed13df29948c41ba367caa757ab3ec4892509910',
- headSha: 'b921914f9a834ac47e6fd9420f78db0f83559130',
- newLine: null,
- newPath: '500-lines-4.txt',
- oldLine: 5,
- oldPath: '500-lines-4.txt',
- startSha: 'ed13df29948c41ba367caa757ab3ec4892509910',
- lineCode: 'ABC_1',
+ base_sha: 'ed13df29948c41ba367caa757ab3ec4892509910',
+ head_sha: 'b921914f9a834ac47e6fd9420f78db0f83559130',
+ new_line: null,
+ new_path: '500-lines-4.txt',
+ old_line: 5,
+ old_path: '500-lines-4.txt',
+ start_sha: 'ed13df29948c41ba367caa757ab3ec4892509910',
+ line_code: 'ABC_1',
};
const state = {
latestDiff: true,
diffFiles: [
{
- fileHash: 'ABC',
- parallelDiffLines: [
+ file_hash: 'ABC',
+ parallel_diff_lines: [
{
left: {
- lineCode: 'ABC_1',
+ line_code: 'ABC_1',
discussions: [],
},
right: {
- lineCode: 'ABC_1',
+ line_code: 'ABC_1',
discussions: [],
},
},
],
- highlightedDiffLines: [
+ highlighted_diff_lines: [
{
- lineCode: 'ABC_1',
+ line_code: 'ABC_1',
discussions: [],
},
],
},
],
};
- const discussions = [
- {
- id: 1,
- line_code: 'ABC_1',
- diff_discussion: true,
- active: true,
- },
- {
- id: 2,
- line_code: 'ABC_1',
- diff_discussion: true,
- active: true,
+ const discussion = {
+ id: 1,
+ line_code: 'ABC_1',
+ diff_discussion: true,
+ active: true,
+ diff_file: {
+ file_hash: state.diffFiles[0].file_hash,
},
- ];
+ };
const diffPositionByLineCode = {
ABC_1: diffPosition,
};
mutations[types.SET_LINE_DISCUSSIONS_FOR_FILE](state, {
- fileHash: 'ABC',
- discussions,
+ discussion,
diffPositionByLineCode,
});
- expect(state.diffFiles[0].parallelDiffLines[0].left.discussions.length).toEqual(2);
- expect(state.diffFiles[0].parallelDiffLines[0].left.discussions[1].id).toEqual(2);
+ expect(state.diffFiles[0].parallel_diff_lines[0].left.discussions.length).toEqual(1);
+ expect(state.diffFiles[0].parallel_diff_lines[0].left.discussions[0].id).toEqual(1);
- expect(state.diffFiles[0].highlightedDiffLines[0].discussions.length).toEqual(2);
- expect(state.diffFiles[0].highlightedDiffLines[0].discussions[1].id).toEqual(2);
+ expect(state.diffFiles[0].highlighted_diff_lines[0].discussions.length).toEqual(1);
+ expect(state.diffFiles[0].highlighted_diff_lines[0].discussions[0].id).toEqual(1);
});
});
@@ -307,11 +269,11 @@ describe('DiffsStoreMutations', () => {
const state = {
diffFiles: [
{
- fileHash: 'ABC',
- parallelDiffLines: [
+ file_hash: 'ABC',
+ parallel_diff_lines: [
{
left: {
- lineCode: 'ABC_1',
+ line_code: 'ABC_1',
discussions: [
{
id: 1,
@@ -324,14 +286,14 @@ describe('DiffsStoreMutations', () => {
],
},
right: {
- lineCode: 'ABC_1',
+ line_code: 'ABC_1',
discussions: [],
},
},
],
- highlightedDiffLines: [
+ highlighted_diff_lines: [
{
- lineCode: 'ABC_1',
+ line_code: 'ABC_1',
discussions: [
{
id: 1,
@@ -352,8 +314,90 @@ describe('DiffsStoreMutations', () => {
fileHash: 'ABC',
lineCode: 'ABC_1',
});
- expect(state.diffFiles[0].parallelDiffLines[0].left.discussions.length).toEqual(0);
- expect(state.diffFiles[0].highlightedDiffLines[0].discussions.length).toEqual(0);
+
+ expect(state.diffFiles[0].parallel_diff_lines[0].left.discussions.length).toEqual(0);
+ expect(state.diffFiles[0].highlighted_diff_lines[0].discussions.length).toEqual(0);
+ });
+ });
+
+ describe('TOGGLE_FOLDER_OPEN', () => {
+ it('toggles entry opened prop', () => {
+ const state = {
+ treeEntries: {
+ path: {
+ opened: false,
+ },
+ },
+ };
+
+ mutations[types.TOGGLE_FOLDER_OPEN](state, 'path');
+
+ expect(state.treeEntries.path.opened).toBe(true);
+ });
+ });
+
+ describe('TOGGLE_SHOW_TREE_LIST', () => {
+ it('toggles showTreeList', () => {
+ const state = createState();
+
+ mutations[types.TOGGLE_SHOW_TREE_LIST](state);
+
+ expect(state.showTreeList).toBe(false, 'Failed to toggle showTreeList to false');
+
+ mutations[types.TOGGLE_SHOW_TREE_LIST](state);
+
+ expect(state.showTreeList).toBe(true, 'Failed to toggle showTreeList to true');
+ });
+ });
+
+ describe('UPDATE_CURRENT_DIFF_FILE_ID', () => {
+ it('updates currentDiffFileId', () => {
+ const state = createState();
+
+ mutations[types.UPDATE_CURRENT_DIFF_FILE_ID](state, 'somefileid');
+
+ expect(state.currentDiffFileId).toBe('somefileid');
+ });
+ });
+
+ describe('Set highlighted row', () => {
+ it('sets highlighted row', () => {
+ const state = createState();
+
+ mutations[types.SET_HIGHLIGHTED_ROW](state, 'ABC_123');
+
+ expect(state.highlightedRow).toBe('ABC_123');
+ });
+ });
+
+ describe('TOGGLE_LINE_HAS_FORM', () => {
+ it('sets hasForm on lines', () => {
+ const file = {
+ file_hash: 'hash',
+ parallel_diff_lines: [
+ { left: { line_code: '123', hasForm: false }, right: {} },
+ { left: {}, right: { line_code: '124', hasForm: false } },
+ ],
+ highlighted_diff_lines: [
+ { line_code: '123', hasForm: false },
+ { line_code: '124', hasForm: false },
+ ],
+ };
+ const state = {
+ diffFiles: [file],
+ };
+
+ mutations[types.TOGGLE_LINE_HAS_FORM](state, {
+ lineCode: '123',
+ hasForm: true,
+ fileHash: 'hash',
+ });
+
+ expect(file.highlighted_diff_lines[0].hasForm).toBe(true);
+ expect(file.highlighted_diff_lines[1].hasForm).toBe(false);
+
+ expect(file.parallel_diff_lines[0].left.hasForm).toBe(true);
+ expect(file.parallel_diff_lines[1].right.hasForm).toBe(false);
});
});
});
diff --git a/spec/javascripts/diffs/store/utils_spec.js b/spec/javascripts/diffs/store/utils_spec.js
index 6138b9701f4..d4ef17c5ef8 100644
--- a/spec/javascripts/diffs/store/utils_spec.js
+++ b/spec/javascripts/diffs/store/utils_spec.js
@@ -18,7 +18,7 @@ const getDiffFileMock = () => Object.assign({}, diffFileMockData);
describe('DiffsStoreUtils', () => {
describe('findDiffFile', () => {
- const files = [{ fileHash: 1, name: 'one' }];
+ const files = [{ file_hash: 1, name: 'one' }];
it('should return correct file', () => {
expect(utils.findDiffFile(files, 1).name).toEqual('one');
@@ -41,13 +41,13 @@ describe('DiffsStoreUtils', () => {
describe('findIndexInInlineLines', () => {
it('should return correct index for given line numbers', () => {
- expectSet(utils.findIndexInInlineLines, getDiffFileMock().highlightedDiffLines);
+ expectSet(utils.findIndexInInlineLines, getDiffFileMock().highlighted_diff_lines);
});
});
describe('findIndexInParallelLines', () => {
it('should return correct index for given line numbers', () => {
- expectSet(utils.findIndexInParallelLines, getDiffFileMock().parallelDiffLines, {});
+ expectSet(utils.findIndexInParallelLines, getDiffFileMock().parallel_diff_lines, {});
});
});
});
@@ -56,42 +56,52 @@ describe('DiffsStoreUtils', () => {
it('should remove match line properly by regarding the bottom parameter', () => {
const diffFile = getDiffFileMock();
const lineNumbers = { oldLineNumber: 3, newLineNumber: 5 };
- const inlineIndex = utils.findIndexInInlineLines(diffFile.highlightedDiffLines, lineNumbers);
- const parallelIndex = utils.findIndexInParallelLines(diffFile.parallelDiffLines, lineNumbers);
- const atInlineIndex = diffFile.highlightedDiffLines[inlineIndex];
- const atParallelIndex = diffFile.parallelDiffLines[parallelIndex];
+ const inlineIndex = utils.findIndexInInlineLines(
+ diffFile.highlighted_diff_lines,
+ lineNumbers,
+ );
+ const parallelIndex = utils.findIndexInParallelLines(
+ diffFile.parallel_diff_lines,
+ lineNumbers,
+ );
+ const atInlineIndex = diffFile.highlighted_diff_lines[inlineIndex];
+ const atParallelIndex = diffFile.parallel_diff_lines[parallelIndex];
utils.removeMatchLine(diffFile, lineNumbers, false);
- expect(diffFile.highlightedDiffLines[inlineIndex]).not.toEqual(atInlineIndex);
- expect(diffFile.parallelDiffLines[parallelIndex]).not.toEqual(atParallelIndex);
+
+ expect(diffFile.highlighted_diff_lines[inlineIndex]).not.toEqual(atInlineIndex);
+ expect(diffFile.parallel_diff_lines[parallelIndex]).not.toEqual(atParallelIndex);
utils.removeMatchLine(diffFile, lineNumbers, true);
- expect(diffFile.highlightedDiffLines[inlineIndex + 1]).not.toEqual(atInlineIndex);
- expect(diffFile.parallelDiffLines[parallelIndex + 1]).not.toEqual(atParallelIndex);
+
+ expect(diffFile.highlighted_diff_lines[inlineIndex + 1]).not.toEqual(atInlineIndex);
+ expect(diffFile.parallel_diff_lines[parallelIndex + 1]).not.toEqual(atParallelIndex);
});
});
describe('addContextLines', () => {
it('should add context lines properly with bottom parameter', () => {
const diffFile = getDiffFileMock();
- const inlineLines = diffFile.highlightedDiffLines;
- const parallelLines = diffFile.parallelDiffLines;
+ const inlineLines = diffFile.highlighted_diff_lines;
+ const parallelLines = diffFile.parallel_diff_lines;
const lineNumbers = { oldLineNumber: 3, newLineNumber: 5 };
const contextLines = [{ lineNumber: 42 }];
const options = { inlineLines, parallelLines, contextLines, lineNumbers, bottom: true };
- const inlineIndex = utils.findIndexInInlineLines(diffFile.highlightedDiffLines, lineNumbers);
- const parallelIndex = utils.findIndexInParallelLines(diffFile.parallelDiffLines, lineNumbers);
+ const inlineIndex = utils.findIndexInInlineLines(inlineLines, lineNumbers);
+ const parallelIndex = utils.findIndexInParallelLines(parallelLines, lineNumbers);
const normalizedParallelLine = {
left: options.contextLines[0],
right: options.contextLines[0],
};
utils.addContextLines(options);
+
expect(inlineLines[inlineLines.length - 1]).toEqual(contextLines[0]);
expect(parallelLines[parallelLines.length - 1]).toEqual(normalizedParallelLine);
delete options.bottom;
utils.addContextLines(options);
+
expect(inlineLines[inlineIndex]).toEqual(contextLines[0]);
expect(parallelLines[parallelIndex]).toEqual(normalizedParallelLine);
});
@@ -108,40 +118,41 @@ describe('DiffsStoreUtils', () => {
noteableType: MERGE_REQUEST_NOTEABLE_TYPE,
diffFile,
noteTargetLine: {
- lineCode: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_3',
- metaData: null,
- newLine: 3,
- oldLine: 1,
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_3',
+ meta_data: null,
+ new_line: 3,
+ old_line: 1,
},
diffViewType: PARALLEL_DIFF_VIEW_TYPE,
linePosition: LINE_POSITION_LEFT,
};
const position = JSON.stringify({
- base_sha: diffFile.diffRefs.baseSha,
- start_sha: diffFile.diffRefs.startSha,
- head_sha: diffFile.diffRefs.headSha,
- old_path: diffFile.oldPath,
- new_path: diffFile.newPath,
+ base_sha: diffFile.diff_refs.base_sha,
+ start_sha: diffFile.diff_refs.start_sha,
+ head_sha: diffFile.diff_refs.head_sha,
+ old_path: diffFile.old_path,
+ new_path: diffFile.new_path,
position_type: TEXT_DIFF_POSITION_TYPE,
- old_line: options.noteTargetLine.oldLine,
- new_line: options.noteTargetLine.newLine,
+ old_line: options.noteTargetLine.old_line,
+ new_line: options.noteTargetLine.new_line,
});
const postData = {
view: options.diffViewType,
line_type: options.linePosition === LINE_POSITION_RIGHT ? NEW_LINE_TYPE : OLD_LINE_TYPE,
- merge_request_diff_head_sha: diffFile.diffRefs.headSha,
+ merge_request_diff_head_sha: diffFile.diff_refs.head_sha,
in_reply_to_discussion_id: '',
note_project_id: '',
target_type: options.noteableType,
target_id: options.noteableData.id,
+ return_discussion: true,
note: {
noteable_type: options.noteableType,
noteable_id: options.noteableData.id,
commit_id: '',
type: DIFF_NOTE_TYPE,
- line_code: options.noteTargetLine.lineCode,
+ line_code: options.noteTargetLine.line_code,
note: options.note,
position,
},
@@ -155,8 +166,8 @@ describe('DiffsStoreUtils', () => {
it('should create legacy note form data', () => {
const diffFile = getDiffFileMock();
- delete diffFile.diffRefs.startSha;
- delete diffFile.diffRefs.headSha;
+ delete diffFile.diff_refs.start_sha;
+ delete diffFile.diff_refs.head_sha;
noteableDataMock.targetType = MERGE_REQUEST_NOTEABLE_TYPE;
@@ -166,24 +177,24 @@ describe('DiffsStoreUtils', () => {
noteableType: MERGE_REQUEST_NOTEABLE_TYPE,
diffFile,
noteTargetLine: {
- lineCode: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_3',
- metaData: null,
- newLine: 3,
- oldLine: 1,
+ line_code: '1c497fbb3a46b78edf04cc2a2fa33f67e3ffbe2a_1_3',
+ meta_data: null,
+ new_line: 3,
+ old_line: 1,
},
diffViewType: PARALLEL_DIFF_VIEW_TYPE,
linePosition: LINE_POSITION_LEFT,
};
const position = JSON.stringify({
- base_sha: diffFile.diffRefs.baseSha,
+ base_sha: diffFile.diff_refs.base_sha,
start_sha: undefined,
head_sha: undefined,
- old_path: diffFile.oldPath,
- new_path: diffFile.newPath,
+ old_path: diffFile.old_path,
+ new_path: diffFile.new_path,
position_type: TEXT_DIFF_POSITION_TYPE,
- old_line: options.noteTargetLine.oldLine,
- new_line: options.noteTargetLine.newLine,
+ old_line: options.noteTargetLine.old_line,
+ new_line: options.noteTargetLine.new_line,
});
const postData = {
@@ -194,12 +205,13 @@ describe('DiffsStoreUtils', () => {
note_project_id: '',
target_type: options.noteableType,
target_id: options.noteableData.id,
+ return_discussion: true,
note: {
noteable_type: options.noteableType,
noteable_id: options.noteableData.id,
commit_id: '',
type: LEGACY_DIFF_NOTE_TYPE,
- line_code: options.noteTargetLine.lineCode,
+ line_code: options.noteTargetLine.line_code,
note: options.note,
position,
},
@@ -219,60 +231,61 @@ describe('DiffsStoreUtils', () => {
const lines = [{ type: null }, { type: MATCH_LINE_TYPE }];
const linesWithReferences = utils.addLineReferences(lines, lineNumbers, true);
- expect(linesWithReferences[0].oldLine).toEqual(lineNumbers.oldLineNumber + 1);
- expect(linesWithReferences[0].newLine).toEqual(lineNumbers.newLineNumber + 1);
- expect(linesWithReferences[1].metaData.oldPos).toEqual(4);
- expect(linesWithReferences[1].metaData.newPos).toEqual(5);
+ expect(linesWithReferences[0].old_line).toEqual(lineNumbers.oldLineNumber + 1);
+ expect(linesWithReferences[0].new_line).toEqual(lineNumbers.newLineNumber + 1);
+ expect(linesWithReferences[1].meta_data.old_pos).toEqual(4);
+ expect(linesWithReferences[1].meta_data.new_pos).toEqual(5);
});
it('should add correct line references when bottom falsy', () => {
const lines = [{ type: null }, { type: MATCH_LINE_TYPE }, { type: null }];
const linesWithReferences = utils.addLineReferences(lines, lineNumbers);
- expect(linesWithReferences[0].oldLine).toEqual(0);
- expect(linesWithReferences[0].newLine).toEqual(1);
- expect(linesWithReferences[1].metaData.oldPos).toEqual(2);
- expect(linesWithReferences[1].metaData.newPos).toEqual(3);
+ expect(linesWithReferences[0].old_line).toEqual(0);
+ expect(linesWithReferences[0].new_line).toEqual(1);
+ expect(linesWithReferences[1].meta_data.old_pos).toEqual(2);
+ expect(linesWithReferences[1].meta_data.new_pos).toEqual(3);
});
});
describe('trimFirstCharOfLineContent', () => {
it('trims the line when it starts with a space', () => {
- expect(utils.trimFirstCharOfLineContent({ richText: ' diff' })).toEqual({
+ expect(utils.trimFirstCharOfLineContent({ rich_text: ' diff' })).toEqual({
discussions: [],
- richText: 'diff',
+ rich_text: 'diff',
});
});
it('trims the line when it starts with a +', () => {
- expect(utils.trimFirstCharOfLineContent({ richText: '+diff' })).toEqual({
+ expect(utils.trimFirstCharOfLineContent({ rich_text: '+diff' })).toEqual({
discussions: [],
- richText: 'diff',
+ rich_text: 'diff',
});
});
it('trims the line when it starts with a -', () => {
- expect(utils.trimFirstCharOfLineContent({ richText: '-diff' })).toEqual({
+ expect(utils.trimFirstCharOfLineContent({ rich_text: '-diff' })).toEqual({
discussions: [],
- richText: 'diff',
+ rich_text: 'diff',
});
});
it('does not trims the line when it starts with a letter', () => {
- expect(utils.trimFirstCharOfLineContent({ richText: 'diff' })).toEqual({
+ expect(utils.trimFirstCharOfLineContent({ rich_text: 'diff' })).toEqual({
discussions: [],
- richText: 'diff',
+ rich_text: 'diff',
});
});
it('does not modify the provided object', () => {
const lineObj = {
discussions: [],
- richText: ' diff',
+ rich_text: ' diff',
};
utils.trimFirstCharOfLineContent(lineObj);
- expect(lineObj).toEqual({ discussions: [], richText: ' diff' });
+
+ expect(lineObj).toEqual({ discussions: [], rich_text: ' diff' });
});
it('handles a undefined or null parameter', () => {
@@ -282,29 +295,33 @@ describe('DiffsStoreUtils', () => {
describe('prepareDiffData', () => {
it('sets the renderIt and collapsed attribute on files', () => {
- const preparedDiff = { diffFiles: [getDiffFileMock()] };
+ const preparedDiff = { diff_files: [getDiffFileMock()] };
utils.prepareDiffData(preparedDiff);
- const firstParallelDiffLine = preparedDiff.diffFiles[0].parallelDiffLines[2];
+ const firstParallelDiffLine = preparedDiff.diff_files[0].parallel_diff_lines[2];
+
expect(firstParallelDiffLine.left.discussions.length).toBe(0);
expect(firstParallelDiffLine.left).not.toHaveAttr('text');
expect(firstParallelDiffLine.right.discussions.length).toBe(0);
expect(firstParallelDiffLine.right).not.toHaveAttr('text');
- const firstParallelChar = firstParallelDiffLine.right.richText.charAt(0);
+ const firstParallelChar = firstParallelDiffLine.right.rich_text.charAt(0);
+
expect(firstParallelChar).not.toBe(' ');
expect(firstParallelChar).not.toBe('+');
expect(firstParallelChar).not.toBe('-');
- const checkLine = preparedDiff.diffFiles[0].highlightedDiffLines[0];
+ const checkLine = preparedDiff.diff_files[0].highlighted_diff_lines[0];
+
expect(checkLine.discussions.length).toBe(0);
expect(checkLine).not.toHaveAttr('text');
- const firstChar = checkLine.richText.charAt(0);
+ const firstChar = checkLine.rich_text.charAt(0);
+
expect(firstChar).not.toBe(' ');
expect(firstChar).not.toBe('+');
expect(firstChar).not.toBe('-');
- expect(preparedDiff.diffFiles[0].renderIt).toBeTruthy();
- expect(preparedDiff.diffFiles[0].collapsed).toBeFalsy();
+ expect(preparedDiff.diff_files[0].renderIt).toBeTruthy();
+ expect(preparedDiff.diff_files[0].collapsed).toBeFalsy();
});
});
@@ -331,20 +348,12 @@ describe('DiffsStoreUtils', () => {
const discussions = {
upToDateDiscussion1: {
- original_position: {
- formatter: diffPosition,
- },
- position: {
- formatter: wrongDiffPosition,
- },
+ original_position: diffPosition,
+ position: wrongDiffPosition,
},
outDatedDiscussion1: {
- original_position: {
- formatter: wrongDiffPosition,
- },
- position: {
- formatter: wrongDiffPosition,
- },
+ original_position: wrongDiffPosition,
+ position: wrongDiffPosition,
},
};
@@ -395,7 +404,7 @@ describe('DiffsStoreUtils', () => {
discussion,
diffPosition: {
...diffPosition,
- lineCode: 'ABC_1',
+ line_code: 'ABC_1',
},
latestDiff: true,
}),
@@ -419,4 +428,135 @@ describe('DiffsStoreUtils', () => {
).toBe(false);
});
});
+
+ describe('generateTreeList', () => {
+ let files;
+
+ beforeAll(() => {
+ files = [
+ {
+ new_path: 'app/index.js',
+ deleted_file: false,
+ new_file: false,
+ removed_lines: 10,
+ added_lines: 0,
+ file_hash: 'test',
+ },
+ {
+ new_path: 'app/test/index.js',
+ deleted_file: false,
+ new_file: true,
+ removed_lines: 0,
+ added_lines: 0,
+ file_hash: 'test',
+ },
+ {
+ new_path: 'app/test/filepathneedstruncating.js',
+ deleted_file: false,
+ new_file: true,
+ removed_lines: 0,
+ added_lines: 0,
+ file_hash: 'test',
+ },
+ {
+ new_path: 'package.json',
+ deleted_file: true,
+ new_file: false,
+ removed_lines: 0,
+ added_lines: 0,
+ file_hash: 'test',
+ },
+ ];
+ });
+
+ it('creates a tree of files', () => {
+ const { tree } = utils.generateTreeList(files);
+
+ expect(tree).toEqual([
+ {
+ key: 'app',
+ path: 'app',
+ name: 'app',
+ type: 'tree',
+ tree: [
+ {
+ addedLines: 0,
+ changed: true,
+ deleted: false,
+ fileHash: 'test',
+ key: 'app/index.js',
+ name: 'index.js',
+ path: 'app/index.js',
+ removedLines: 10,
+ tempFile: false,
+ type: 'blob',
+ tree: [],
+ },
+ {
+ key: 'app/test',
+ path: 'app/test',
+ name: 'test',
+ type: 'tree',
+ opened: true,
+ tree: [
+ {
+ addedLines: 0,
+ changed: true,
+ deleted: false,
+ fileHash: 'test',
+ key: 'app/test/index.js',
+ name: 'index.js',
+ path: 'app/test/index.js',
+ removedLines: 0,
+ tempFile: true,
+ type: 'blob',
+ tree: [],
+ },
+ {
+ addedLines: 0,
+ changed: true,
+ deleted: false,
+ fileHash: 'test',
+ key: 'app/test/filepathneedstruncating.js',
+ name: 'filepathneedstruncating.js',
+ path: 'app/test/filepathneedstruncating.js',
+ removedLines: 0,
+ tempFile: true,
+ type: 'blob',
+ tree: [],
+ },
+ ],
+ },
+ ],
+ opened: true,
+ },
+ {
+ key: 'package.json',
+ path: 'package.json',
+ name: 'package.json',
+ type: 'blob',
+ changed: true,
+ tempFile: false,
+ deleted: true,
+ fileHash: 'test',
+ addedLines: 0,
+ removedLines: 0,
+ tree: [],
+ },
+ ]);
+ });
+
+ it('creates flat list of blobs & folders', () => {
+ const { treeEntries } = utils.generateTreeList(files);
+
+ expect(Object.keys(treeEntries)).toEqual([
+ 'app',
+ 'app/index.js',
+ 'app/test',
+ 'app/test/index.js',
+ 'app/test/filepathneedstruncating.js',
+ 'package.json',
+ ]);
+ });
+ });
});
diff --git a/spec/javascripts/dirty_submit/dirty_submit_collection_spec.js b/spec/javascripts/dirty_submit/dirty_submit_collection_spec.js
new file mode 100644
index 00000000000..08ffc44605f
--- /dev/null
+++ b/spec/javascripts/dirty_submit/dirty_submit_collection_spec.js
@@ -0,0 +1,29 @@
+import DirtySubmitCollection from '~/dirty_submit/dirty_submit_collection';
+import { setInput, createForm } from './helper';
+
+describe('DirtySubmitCollection', () => {
+ it('disables submits until there are changes', done => {
+ const testElementsCollection = [createForm(), createForm()];
+ const forms = testElementsCollection.map(testElements => testElements.form);
+
+ new DirtySubmitCollection(forms); // eslint-disable-line no-new
+
+ testElementsCollection.forEach(testElements => {
+ const { input, submit } = testElements;
+ const originalValue = input.value;
+
+ expect(submit.disabled).toBe(true);
+
+ return setInput(input, `${originalValue} changes`)
+ .then(() => {
+ expect(submit.disabled).toBe(false);
+ })
+ .then(() => setInput(input, originalValue))
+ .then(() => {
+ expect(submit.disabled).toBe(true);
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+});
diff --git a/spec/javascripts/dirty_submit/dirty_submit_factory_spec.js b/spec/javascripts/dirty_submit/dirty_submit_factory_spec.js
new file mode 100644
index 00000000000..40843a68582
--- /dev/null
+++ b/spec/javascripts/dirty_submit/dirty_submit_factory_spec.js
@@ -0,0 +1,18 @@
+import dirtySubmitFactory from '~/dirty_submit/dirty_submit_factory';
+import DirtySubmitForm from '~/dirty_submit/dirty_submit_form';
+import DirtySubmitCollection from '~/dirty_submit/dirty_submit_collection';
+import { createForm } from './helper';
+
+describe('DirtySubmitCollection', () => {
+ it('returns a DirtySubmitForm instance for single form elements', () => {
+ const { form } = createForm();
+
+ expect(dirtySubmitFactory(form) instanceof DirtySubmitForm).toBe(true);
+ });
+
+ it('returns a DirtySubmitCollection instance for a collection of form elements', () => {
+ const forms = [createForm().form, createForm().form];
+
+ expect(dirtySubmitFactory(forms) instanceof DirtySubmitCollection).toBe(true);
+ });
+});
diff --git a/spec/javascripts/dirty_submit/dirty_submit_form_spec.js b/spec/javascripts/dirty_submit/dirty_submit_form_spec.js
new file mode 100644
index 00000000000..093fec97951
--- /dev/null
+++ b/spec/javascripts/dirty_submit/dirty_submit_form_spec.js
@@ -0,0 +1,36 @@
+import DirtySubmitForm from '~/dirty_submit/dirty_submit_form';
+import { setInput, createForm } from './helper';
+
+function expectToToggleDisableOnDirtyUpdate(submit, input) {
+ const originalValue = input.value;
+
+ expect(submit.disabled).toBe(true);
+
+ return setInput(input, `${originalValue} changes`)
+ .then(() => expect(submit.disabled).toBe(false))
+ .then(() => setInput(input, originalValue))
+ .then(() => expect(submit.disabled).toBe(true));
+}
+
+describe('DirtySubmitForm', () => {
+ it('disables submit until there are changes', done => {
+ const { form, input, submit } = createForm();
+
+ new DirtySubmitForm(form); // eslint-disable-line no-new
+
+ return expectToToggleDisableOnDirtyUpdate(submit, input)
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('disables submit until there are changes when initializing with a falsy value', done => {
+ const { form, input, submit } = createForm();
+ input.value = '';
+
+ new DirtySubmitForm(form); // eslint-disable-line no-new
+
+ return expectToToggleDisableOnDirtyUpdate(submit, input)
+ .then(done)
+ .catch(done.fail);
+ });
+});
diff --git a/spec/javascripts/dirty_submit/helper.js b/spec/javascripts/dirty_submit/helper.js
new file mode 100644
index 00000000000..6d1e643553c
--- /dev/null
+++ b/spec/javascripts/dirty_submit/helper.js
@@ -0,0 +1,31 @@
+import DirtySubmitForm from '~/dirty_submit/dirty_submit_form';
+import setTimeoutPromiseHelper from '../helpers/set_timeout_promise_helper';
+
+export function setInput(element, value) {
+ element.value = value;
+
+ element.dispatchEvent(
+ new Event('input', {
+ bubbles: true,
+ cancelable: true,
+ }),
+ );
+
+ return setTimeoutPromiseHelper(DirtySubmitForm.THROTTLE_DURATION);
+}
+
+export function createForm() {
+ const form = document.createElement('form');
+ form.innerHTML = `
+ <input type="text" value="original" class="js-input" name="input" />
+ <button type="submit" class="js-dirty-submit"></button>
+ `;
+ const input = form.querySelector('.js-input');
+ const submit = form.querySelector('.js-dirty-submit');
+
+ return {
+ form,
+ input,
+ submit,
+ };
+}
diff --git a/spec/javascripts/droplab/drop_down_spec.js b/spec/javascripts/droplab/drop_down_spec.js
index 896a04a1a07..18ab03653f4 100644
--- a/spec/javascripts/droplab/drop_down_spec.js
+++ b/spec/javascripts/droplab/drop_down_spec.js
@@ -2,9 +2,9 @@ import DropDown from '~/droplab/drop_down';
import utils from '~/droplab/utils';
import { SELECTED_CLASS } from '~/droplab/constants';
-describe('DropLab DropDown', function () {
- describe('class constructor', function () {
- beforeEach(function () {
+describe('DropLab DropDown', function() {
+ describe('class constructor', function() {
+ beforeEach(function() {
spyOn(DropDown.prototype, 'getItems');
spyOn(DropDown.prototype, 'initTemplateString');
spyOn(DropDown.prototype, 'addEvents');
@@ -13,32 +13,32 @@ describe('DropLab DropDown', function () {
this.dropdown = new DropDown(this.list);
});
- it('sets the .hidden property to true', function () {
+ it('sets the .hidden property to true', function() {
expect(this.dropdown.hidden).toBe(true);
});
- it('sets the .list property', function () {
+ it('sets the .list property', function() {
expect(this.dropdown.list).toBe(this.list);
});
- it('calls .getItems', function () {
+ it('calls .getItems', function() {
expect(DropDown.prototype.getItems).toHaveBeenCalled();
});
- it('calls .initTemplateString', function () {
+ it('calls .initTemplateString', function() {
expect(DropDown.prototype.initTemplateString).toHaveBeenCalled();
});
- it('calls .addEvents', function () {
+ it('calls .addEvents', function() {
expect(DropDown.prototype.addEvents).toHaveBeenCalled();
});
- it('sets the .initialState property to the .list.innerHTML', function () {
+ it('sets the .initialState property to the .list.innerHTML', function() {
expect(this.dropdown.initialState).toBe(this.list.innerHTML);
});
- describe('if the list argument is a string', function () {
- beforeEach(function () {
+ describe('if the list argument is a string', function() {
+ beforeEach(function() {
this.element = {};
this.selector = '.selector';
@@ -47,18 +47,18 @@ describe('DropLab DropDown', function () {
this.dropdown = new DropDown(this.selector);
});
- it('calls .querySelector with the selector string', function () {
+ it('calls .querySelector with the selector string', function() {
expect(Document.prototype.querySelector).toHaveBeenCalledWith(this.selector);
});
- it('sets the .list property element', function () {
+ it('sets the .list property element', function() {
expect(this.dropdown.list).toBe(this.element);
});
});
});
- describe('getItems', function () {
- beforeEach(function () {
+ describe('getItems', function() {
+ beforeEach(function() {
this.list = { querySelectorAll: () => {} };
this.dropdown = { list: this.list };
this.nodeList = [];
@@ -68,37 +68,37 @@ describe('DropLab DropDown', function () {
this.getItems = DropDown.prototype.getItems.call(this.dropdown);
});
- it('calls .querySelectorAll with a list item query', function () {
+ it('calls .querySelectorAll with a list item query', function() {
expect(this.list.querySelectorAll).toHaveBeenCalledWith('li');
});
- it('sets the .items property to the returned list items', function () {
+ it('sets the .items property to the returned list items', function() {
expect(this.dropdown.items).toEqual(jasmine.any(Array));
});
- it('returns the .items', function () {
+ it('returns the .items', function() {
expect(this.getItems).toEqual(jasmine.any(Array));
});
});
- describe('initTemplateString', function () {
- beforeEach(function () {
+ describe('initTemplateString', function() {
+ beforeEach(function() {
this.items = [{ outerHTML: '<a></a>' }, { outerHTML: '<img>' }];
this.dropdown = { items: this.items };
DropDown.prototype.initTemplateString.call(this.dropdown);
});
- it('should set .templateString to the last items .outerHTML', function () {
+ it('should set .templateString to the last items .outerHTML', function() {
expect(this.dropdown.templateString).toBe(this.items[1].outerHTML);
});
- it('should not set .templateString to a non-last items .outerHTML', function () {
+ it('should not set .templateString to a non-last items .outerHTML', function() {
expect(this.dropdown.templateString).not.toBe(this.items[0].outerHTML);
});
- describe('if .items is not set', function () {
- beforeEach(function () {
+ describe('if .items is not set', function() {
+ beforeEach(function() {
this.dropdown = { getItems: () => {} };
spyOn(this.dropdown, 'getItems').and.returnValue([]);
@@ -106,26 +106,26 @@ describe('DropLab DropDown', function () {
DropDown.prototype.initTemplateString.call(this.dropdown);
});
- it('should call .getItems', function () {
+ it('should call .getItems', function() {
expect(this.dropdown.getItems).toHaveBeenCalled();
});
});
- describe('if items array is empty', function () {
- beforeEach(function () {
+ describe('if items array is empty', function() {
+ beforeEach(function() {
this.dropdown = { items: [] };
DropDown.prototype.initTemplateString.call(this.dropdown);
});
- it('should set .templateString to an empty string', function () {
+ it('should set .templateString to an empty string', function() {
expect(this.dropdown.templateString).toBe('');
});
});
});
- describe('clickEvent', function () {
- beforeEach(function () {
+ describe('clickEvent', function() {
+ beforeEach(function() {
this.classList = jasmine.createSpyObj('classList', ['contains']);
this.list = { dispatchEvent: () => {} };
this.dropdown = {
@@ -143,7 +143,7 @@ describe('DropLab DropDown', function () {
};
this.customEvent = {};
this.dummyListItem = document.createElement('li');
- spyOn(this.event.target, 'closest').and.callFake((selector) => {
+ spyOn(this.event.target, 'closest').and.callFake(selector => {
if (selector === 'li') {
return this.dummyListItem;
}
@@ -159,51 +159,51 @@ describe('DropLab DropDown', function () {
this.classList.contains.and.returnValue(false);
});
- it('should call event.target.closest', function () {
+ it('should call event.target.closest', function() {
DropDown.prototype.clickEvent.call(this.dropdown, this.event);
expect(this.event.target.closest).toHaveBeenCalledWith('.droplab-item-ignore');
expect(this.event.target.closest).toHaveBeenCalledWith('li');
});
- it('should call addSelectedClass', function () {
+ it('should call addSelectedClass', function() {
DropDown.prototype.clickEvent.call(this.dropdown, this.event);
expect(this.dropdown.addSelectedClass).toHaveBeenCalledWith(this.dummyListItem);
});
- it('should call .preventDefault', function () {
+ it('should call .preventDefault', function() {
DropDown.prototype.clickEvent.call(this.dropdown, this.event);
expect(this.event.preventDefault).toHaveBeenCalled();
});
- it('should call .hide', function () {
+ it('should call .hide', function() {
DropDown.prototype.clickEvent.call(this.dropdown, this.event);
expect(this.dropdown.hide).toHaveBeenCalled();
});
- it('should construct CustomEvent', function () {
+ it('should construct CustomEvent', function() {
DropDown.prototype.clickEvent.call(this.dropdown, this.event);
expect(window.CustomEvent).toHaveBeenCalledWith('click.dl', jasmine.any(Object));
});
- it('should call .dispatchEvent with the customEvent', function () {
+ it('should call .dispatchEvent with the customEvent', function() {
DropDown.prototype.clickEvent.call(this.dropdown, this.event);
expect(this.list.dispatchEvent).toHaveBeenCalledWith(this.customEvent);
});
- describe('if the target is a UL element', function () {
- beforeEach(function () {
+ describe('if the target is a UL element', function() {
+ beforeEach(function() {
this.event.target = document.createElement('ul');
spyOn(this.event.target, 'closest');
});
- it('should return immediately', function () {
+ it('should return immediately', function() {
DropDown.prototype.clickEvent.call(this.dropdown, this.event);
expect(this.event.target.closest).not.toHaveBeenCalled();
@@ -211,8 +211,8 @@ describe('DropLab DropDown', function () {
});
});
- describe('if the target has the droplab-item-ignore class', function () {
- beforeEach(function () {
+ describe('if the target has the droplab-item-ignore class', function() {
+ beforeEach(function() {
this.ignoredButton = document.createElement('button');
this.ignoredButton.classList.add('droplab-item-ignore');
this.event.target = this.ignoredButton;
@@ -220,7 +220,7 @@ describe('DropLab DropDown', function () {
spyOn(this.ignoredButton, 'closest').and.callThrough();
});
- it('does not select element', function () {
+ it('does not select element', function() {
DropDown.prototype.clickEvent.call(this.dropdown, this.event);
expect(this.ignoredButton.closest.calls.count()).toBe(1);
@@ -229,13 +229,13 @@ describe('DropLab DropDown', function () {
});
});
- describe('if no selected element exists', function () {
- beforeEach(function () {
+ describe('if no selected element exists', function() {
+ beforeEach(function() {
this.event.preventDefault.calls.reset();
this.dummyListItem = null;
});
- it('should return before .preventDefault is called', function () {
+ it('should return before .preventDefault is called', function() {
DropDown.prototype.clickEvent.call(this.dropdown, this.event);
expect(this.event.preventDefault).not.toHaveBeenCalled();
@@ -244,12 +244,12 @@ describe('DropLab DropDown', function () {
});
describe('if hideOnClick is false', () => {
- beforeEach(function () {
+ beforeEach(function() {
this.dropdown.hideOnClick = false;
this.dropdown.hide.calls.reset();
});
- it('should not call .hide', function () {
+ it('should not call .hide', function() {
DropDown.prototype.clickEvent.call(this.dropdown, this.event);
expect(this.dropdown.hide).not.toHaveBeenCalled();
@@ -257,8 +257,8 @@ describe('DropLab DropDown', function () {
});
});
- describe('addSelectedClass', function () {
- beforeEach(function () {
+ describe('addSelectedClass', function() {
+ beforeEach(function() {
this.items = Array(4).forEach((item, i) => {
this.items[i] = { classList: { add: () => {} } };
spyOn(this.items[i].classList, 'add');
@@ -272,17 +272,17 @@ describe('DropLab DropDown', function () {
DropDown.prototype.addSelectedClass.call(this.dropdown, this.selected);
});
- it('should call .removeSelectedClasses', function () {
+ it('should call .removeSelectedClasses', function() {
expect(this.dropdown.removeSelectedClasses).toHaveBeenCalled();
});
- it('should call .classList.add', function () {
+ it('should call .classList.add', function() {
expect(this.selected.classList.add).toHaveBeenCalledWith(SELECTED_CLASS);
});
});
- describe('removeSelectedClasses', function () {
- beforeEach(function () {
+ describe('removeSelectedClasses', function() {
+ beforeEach(function() {
this.items = Array(4);
this.items.forEach((item, i) => {
this.items[i] = { classList: { add: () => {} } };
@@ -293,14 +293,14 @@ describe('DropLab DropDown', function () {
DropDown.prototype.removeSelectedClasses.call(this.dropdown);
});
- it('should call .classList.remove for all items', function () {
+ it('should call .classList.remove for all items', function() {
this.items.forEach((item, i) => {
expect(this.items[i].classList.add).toHaveBeenCalledWith(SELECTED_CLASS);
});
});
- describe('if .items is not set', function () {
- beforeEach(function () {
+ describe('if .items is not set', function() {
+ beforeEach(function() {
this.dropdown = { getItems: () => {} };
spyOn(this.dropdown, 'getItems').and.returnValue([]);
@@ -308,14 +308,14 @@ describe('DropLab DropDown', function () {
DropDown.prototype.removeSelectedClasses.call(this.dropdown);
});
- it('should call .getItems', function () {
+ it('should call .getItems', function() {
expect(this.dropdown.getItems).toHaveBeenCalled();
});
});
});
- describe('addEvents', function () {
- beforeEach(function () {
+ describe('addEvents', function() {
+ beforeEach(function() {
this.list = {
addEventListener: () => {},
querySelectorAll: () => [],
@@ -328,7 +328,7 @@ describe('DropLab DropDown', function () {
};
});
- it('should call .addEventListener', function () {
+ it('should call .addEventListener', function() {
spyOn(this.list, 'addEventListener');
DropDown.prototype.addEvents.call(this.dropdown);
@@ -338,8 +338,8 @@ describe('DropLab DropDown', function () {
});
});
- describe('setData', function () {
- beforeEach(function () {
+ describe('setData', function() {
+ beforeEach(function() {
this.dropdown = { render: () => {} };
this.data = ['data'];
@@ -348,17 +348,17 @@ describe('DropLab DropDown', function () {
DropDown.prototype.setData.call(this.dropdown, this.data);
});
- it('should set .data', function () {
+ it('should set .data', function() {
expect(this.dropdown.data).toBe(this.data);
});
- it('should call .render with the .data', function () {
+ it('should call .render with the .data', function() {
expect(this.dropdown.render).toHaveBeenCalledWith(this.data);
});
});
- describe('addData', function () {
- beforeEach(function () {
+ describe('addData', function() {
+ beforeEach(function() {
this.dropdown = { render: () => {}, data: ['data1'] };
this.data = ['data2'];
@@ -368,20 +368,20 @@ describe('DropLab DropDown', function () {
DropDown.prototype.addData.call(this.dropdown, this.data);
});
- it('should call .concat with data', function () {
+ it('should call .concat with data', function() {
expect(Array.prototype.concat).toHaveBeenCalledWith(this.data);
});
- it('should set .data with concatination', function () {
+ it('should set .data with concatination', function() {
expect(this.dropdown.data).toEqual(['data1', 'data2']);
});
- it('should call .render with the .data', function () {
+ it('should call .render with the .data', function() {
expect(this.dropdown.render).toHaveBeenCalledWith(['data1', 'data2']);
});
- describe('if .data is undefined', function () {
- beforeEach(function () {
+ describe('if .data is undefined', function() {
+ beforeEach(function() {
this.dropdown = { render: () => {}, data: undefined };
this.data = ['data2'];
@@ -390,14 +390,14 @@ describe('DropLab DropDown', function () {
DropDown.prototype.addData.call(this.dropdown, this.data);
});
- it('should set .data with concatination', function () {
+ it('should set .data with concatination', function() {
expect(this.dropdown.data).toEqual(['data2']);
});
});
});
- describe('render', function () {
- beforeEach(function () {
+ describe('render', function() {
+ beforeEach(function() {
this.list = { querySelector: () => {}, dispatchEvent: () => {} };
this.dropdown = { renderChildren: () => {}, list: this.list };
this.renderableList = {};
@@ -413,45 +413,45 @@ describe('DropLab DropDown', function () {
DropDown.prototype.render.call(this.dropdown, this.data);
});
- it('should call .map', function () {
+ it('should call .map', function() {
expect(this.data.map).toHaveBeenCalledWith(jasmine.any(Function));
});
- it('should call .renderChildren for each data item', function () {
+ it('should call .renderChildren for each data item', function() {
expect(this.dropdown.renderChildren.calls.count()).toBe(this.data.length);
});
- it('sets the renderableList .innerHTML', function () {
+ it('sets the renderableList .innerHTML', function() {
expect(this.renderableList.innerHTML).toBe('01');
});
- it('should call render.dl', function () {
+ it('should call render.dl', function() {
expect(window.CustomEvent).toHaveBeenCalledWith('render.dl', jasmine.any(Object));
});
- it('should call dispatchEvent with the customEvent', function () {
+ it('should call dispatchEvent with the customEvent', function() {
expect(this.list.dispatchEvent).toHaveBeenCalledWith(this.customEvent);
});
- describe('if no data argument is passed', function () {
- beforeEach(function () {
+ describe('if no data argument is passed', function() {
+ beforeEach(function() {
this.data.map.calls.reset();
this.dropdown.renderChildren.calls.reset();
DropDown.prototype.render.call(this.dropdown, undefined);
});
- it('should not call .map', function () {
+ it('should not call .map', function() {
expect(this.data.map).not.toHaveBeenCalled();
});
- it('should not call .renderChildren', function () {
+ it('should not call .renderChildren', function() {
expect(this.dropdown.renderChildren).not.toHaveBeenCalled();
});
});
- describe('if no dynamic list is present', function () {
- beforeEach(function () {
+ describe('if no dynamic list is present', function() {
+ beforeEach(function() {
this.list = { querySelector: () => {}, dispatchEvent: () => {} };
this.dropdown = { renderChildren: () => {}, list: this.list };
this.data = [0, 1];
@@ -463,14 +463,14 @@ describe('DropLab DropDown', function () {
DropDown.prototype.render.call(this.dropdown, this.data);
});
- it('sets the .list .innerHTML', function () {
+ it('sets the .list .innerHTML', function() {
expect(this.list.innerHTML).toBe('01');
});
});
});
- describe('renderChildren', function () {
- beforeEach(function () {
+ describe('renderChildren', function() {
+ beforeEach(function() {
this.templateString = 'templateString';
this.dropdown = { templateString: this.templateString };
this.data = { droplab_hidden: true };
@@ -484,44 +484,44 @@ describe('DropLab DropDown', function () {
this.renderChildren = DropDown.prototype.renderChildren.call(this.dropdown, this.data);
});
- it('should call utils.t with .templateString and data', function () {
+ it('should call utils.t with .templateString and data', function() {
expect(utils.template).toHaveBeenCalledWith(this.templateString, this.data);
});
- it('should call document.createElement', function () {
+ it('should call document.createElement', function() {
expect(document.createElement).toHaveBeenCalledWith('div');
});
- it('should set the templates .innerHTML to the HTML', function () {
+ it('should set the templates .innerHTML to the HTML', function() {
expect(this.template.innerHTML).toBe(this.html);
});
- it('should call .setImagesSrc with the template', function () {
+ it('should call .setImagesSrc with the template', function() {
expect(DropDown.setImagesSrc).toHaveBeenCalledWith(this.template);
});
- it('should set the template display to none', function () {
+ it('should set the template display to none', function() {
expect(this.template.firstChild.style.display).toBe('none');
});
- it('should return the templates .firstChild.outerHTML', function () {
+ it('should return the templates .firstChild.outerHTML', function() {
expect(this.renderChildren).toBe(this.template.firstChild.outerHTML);
});
- describe('if droplab_hidden is false', function () {
- beforeEach(function () {
+ describe('if droplab_hidden is false', function() {
+ beforeEach(function() {
this.data = { droplab_hidden: false };
this.renderChildren = DropDown.prototype.renderChildren.call(this.dropdown, this.data);
});
- it('should set the template display to block', function () {
+ it('should set the template display to block', function() {
expect(this.template.firstChild.style.display).toBe('block');
});
});
});
- describe('setImagesSrc', function () {
- beforeEach(function () {
+ describe('setImagesSrc', function() {
+ beforeEach(function() {
this.template = { querySelectorAll: () => {} };
spyOn(this.template, 'querySelectorAll').and.returnValue([]);
@@ -529,64 +529,64 @@ describe('DropLab DropDown', function () {
DropDown.setImagesSrc(this.template);
});
- it('should call .querySelectorAll', function () {
+ it('should call .querySelectorAll', function() {
expect(this.template.querySelectorAll).toHaveBeenCalledWith('img[data-src]');
});
});
- describe('show', function () {
- beforeEach(function () {
+ describe('show', function() {
+ beforeEach(function() {
this.list = { style: {} };
this.dropdown = { list: this.list, hidden: true };
DropDown.prototype.show.call(this.dropdown);
});
- it('it should set .list display to block', function () {
+ it('it should set .list display to block', function() {
expect(this.list.style.display).toBe('block');
});
- it('it should set .hidden to false', function () {
+ it('it should set .hidden to false', function() {
expect(this.dropdown.hidden).toBe(false);
});
- describe('if .hidden is false', function () {
- beforeEach(function () {
+ describe('if .hidden is false', function() {
+ beforeEach(function() {
this.list = { style: {} };
this.dropdown = { list: this.list, hidden: false };
this.show = DropDown.prototype.show.call(this.dropdown);
});
- it('should return undefined', function () {
+ it('should return undefined', function() {
expect(this.show).toEqual(undefined);
});
- it('should not set .list display to block', function () {
+ it('should not set .list display to block', function() {
expect(this.list.style.display).not.toEqual('block');
});
});
});
- describe('hide', function () {
- beforeEach(function () {
+ describe('hide', function() {
+ beforeEach(function() {
this.list = { style: {} };
this.dropdown = { list: this.list };
DropDown.prototype.hide.call(this.dropdown);
});
- it('it should set .list display to none', function () {
+ it('it should set .list display to none', function() {
expect(this.list.style.display).toBe('none');
});
- it('it should set .hidden to true', function () {
+ it('it should set .hidden to true', function() {
expect(this.dropdown.hidden).toBe(true);
});
});
- describe('toggle', function () {
- beforeEach(function () {
+ describe('toggle', function() {
+ beforeEach(function() {
this.hidden = true;
this.dropdown = { hidden: this.hidden, show: () => {}, hide: () => {} };
@@ -596,12 +596,12 @@ describe('DropLab DropDown', function () {
DropDown.prototype.toggle.call(this.dropdown);
});
- it('should call .show', function () {
+ it('should call .show', function() {
expect(this.dropdown.show).toHaveBeenCalled();
});
- describe('if .hidden is false', function () {
- beforeEach(function () {
+ describe('if .hidden is false', function() {
+ beforeEach(function() {
this.hidden = false;
this.dropdown = { hidden: this.hidden, show: () => {}, hide: () => {} };
@@ -611,14 +611,14 @@ describe('DropLab DropDown', function () {
DropDown.prototype.toggle.call(this.dropdown);
});
- it('should call .hide', function () {
+ it('should call .hide', function() {
expect(this.dropdown.hide).toHaveBeenCalled();
});
});
});
- describe('destroy', function () {
- beforeEach(function () {
+ describe('destroy', function() {
+ beforeEach(function() {
this.list = { removeEventListener: () => {} };
this.eventWrapper = { clickEvent: 'clickEvent' };
this.dropdown = { list: this.list, hide: () => {}, eventWrapper: this.eventWrapper };
@@ -629,12 +629,15 @@ describe('DropLab DropDown', function () {
DropDown.prototype.destroy.call(this.dropdown);
});
- it('it should call .hide', function () {
+ it('it should call .hide', function() {
expect(this.dropdown.hide).toHaveBeenCalled();
});
- it('it should call .removeEventListener', function () {
- expect(this.list.removeEventListener).toHaveBeenCalledWith('click', this.eventWrapper.clickEvent);
+ it('it should call .removeEventListener', function() {
+ expect(this.list.removeEventListener).toHaveBeenCalledWith(
+ 'click',
+ this.eventWrapper.clickEvent,
+ );
});
});
});
diff --git a/spec/javascripts/droplab/hook_spec.js b/spec/javascripts/droplab/hook_spec.js
index 5eed1db2750..40470436f19 100644
--- a/spec/javascripts/droplab/hook_spec.js
+++ b/spec/javascripts/droplab/hook_spec.js
@@ -1,8 +1,8 @@
import Hook from '~/droplab/hook';
-describe('Hook', function () {
- describe('class constructor', function () {
- beforeEach(function () {
+describe('Hook', function() {
+ describe('class constructor', function() {
+ beforeEach(function() {
this.trigger = { id: 'id' };
this.list = {};
this.plugins = {};
@@ -14,58 +14,58 @@ describe('Hook', function () {
this.hook = new Hook(this.trigger, this.list, this.plugins, this.config);
});
- it('should set .trigger', function () {
+ it('should set .trigger', function() {
expect(this.hook.trigger).toBe(this.trigger);
});
- it('should set .list', function () {
+ it('should set .list', function() {
expect(this.hook.list).toBe(this.dropdown);
});
- it('should call DropDown constructor', function () {
+ it('should call DropDown constructor', function() {
expect(this.dropdownConstructor).toHaveBeenCalledWith(this.list, this.config);
});
- it('should set .type', function () {
+ it('should set .type', function() {
expect(this.hook.type).toBe('Hook');
});
- it('should set .event', function () {
+ it('should set .event', function() {
expect(this.hook.event).toBe('click');
});
- it('should set .plugins', function () {
+ it('should set .plugins', function() {
expect(this.hook.plugins).toBe(this.plugins);
});
- it('should set .config', function () {
+ it('should set .config', function() {
expect(this.hook.config).toBe(this.config);
});
- it('should set .id', function () {
+ it('should set .id', function() {
expect(this.hook.id).toBe(this.trigger.id);
});
- describe('if config argument is undefined', function () {
- beforeEach(function () {
+ describe('if config argument is undefined', function() {
+ beforeEach(function() {
this.config = undefined;
this.hook = new Hook(this.trigger, this.list, this.plugins, this.config);
});
- it('should set .config to an empty object', function () {
+ it('should set .config to an empty object', function() {
expect(this.hook.config).toEqual({});
});
});
- describe('if plugins argument is undefined', function () {
- beforeEach(function () {
+ describe('if plugins argument is undefined', function() {
+ beforeEach(function() {
this.plugins = undefined;
this.hook = new Hook(this.trigger, this.list, this.plugins, this.config);
});
- it('should set .plugins to an empty array', function () {
+ it('should set .plugins to an empty array', function() {
expect(this.hook.plugins).toEqual([]);
});
});
diff --git a/spec/javascripts/droplab/plugins/ajax_filter_spec.js b/spec/javascripts/droplab/plugins/ajax_filter_spec.js
index 8155d98b543..5dbe50af07f 100644
--- a/spec/javascripts/droplab/plugins/ajax_filter_spec.js
+++ b/spec/javascripts/droplab/plugins/ajax_filter_spec.js
@@ -38,8 +38,8 @@ describe('AjaxFilter', () => {
dummyList.list.appendChild(dynamicList);
});
- it('calls onLoadingFinished after loading data', (done) => {
- ajaxSpy = (url) => {
+ it('calls onLoadingFinished after loading data', done => {
+ ajaxSpy = url => {
expect(url).toBe('dummy endpoint?dummy search key=');
return Promise.resolve(dummyData);
};
@@ -52,16 +52,16 @@ describe('AjaxFilter', () => {
.catch(done.fail);
});
- it('does not call onLoadingFinished if Ajax call fails', (done) => {
+ it('does not call onLoadingFinished if Ajax call fails', done => {
const dummyError = new Error('My dummy is sick! :-(');
- ajaxSpy = (url) => {
+ ajaxSpy = url => {
expect(url).toBe('dummy endpoint?dummy search key=');
return Promise.reject(dummyError);
};
AjaxFilter.trigger()
.then(done.fail)
- .catch((error) => {
+ .catch(error => {
expect(error).toBe(dummyError);
expect(dummyConfig.onLoadingFinished.calls.count()).toBe(0);
})
diff --git a/spec/javascripts/droplab/plugins/ajax_spec.js b/spec/javascripts/droplab/plugins/ajax_spec.js
index 085f25764fe..2f492d00c0a 100644
--- a/spec/javascripts/droplab/plugins/ajax_spec.js
+++ b/spec/javascripts/droplab/plugins/ajax_spec.js
@@ -8,6 +8,7 @@ describe('Ajax', () => {
describe('is not configured', () => {
it('passes the data through', () => {
const data = ['data'];
+
expect(Ajax.preprocessing(config, data)).toEqual(data);
});
});
@@ -22,13 +23,17 @@ describe('Ajax', () => {
it('calls preprocessing', () => {
Ajax.preprocessing(config, []);
+
expect(config.preprocessing.calls.count()).toBe(1);
});
it('overrides AjaxCache', () => {
- spyOn(AjaxCache, 'override').and.callFake((endpoint, results) => expect(results).toEqual(processedArray));
+ spyOn(AjaxCache, 'override').and.callFake((endpoint, results) => {
+ expect(results).toEqual(processedArray);
+ });
Ajax.preprocessing(config, []);
+
expect(AjaxCache.override.calls.count()).toBe(1);
});
});
diff --git a/spec/javascripts/droplab/plugins/input_setter_spec.js b/spec/javascripts/droplab/plugins/input_setter_spec.js
index bd625f4ae80..711e0486bff 100644
--- a/spec/javascripts/droplab/plugins/input_setter_spec.js
+++ b/spec/javascripts/droplab/plugins/input_setter_spec.js
@@ -1,10 +1,8 @@
-/* eslint-disable */
-
import InputSetter from '~/droplab/plugins/input_setter';
-describe('InputSetter', function () {
- describe('init', function () {
- beforeEach(function () {
+describe('InputSetter', function() {
+ describe('init', function() {
+ beforeEach(function() {
this.config = { InputSetter: {} };
this.hook = { config: this.config };
this.inputSetter = jasmine.createSpyObj('inputSetter', ['addEvents']);
@@ -12,60 +10,62 @@ describe('InputSetter', function () {
InputSetter.init.call(this.inputSetter, this.hook);
});
- it('should set .hook', function () {
+ it('should set .hook', function() {
expect(this.inputSetter.hook).toBe(this.hook);
});
- it('should set .config', function () {
+ it('should set .config', function() {
expect(this.inputSetter.config).toBe(this.config.InputSetter);
});
- it('should set .eventWrapper', function () {
+ it('should set .eventWrapper', function() {
expect(this.inputSetter.eventWrapper).toEqual({});
});
- it('should call .addEvents', function () {
+ it('should call .addEvents', function() {
expect(this.inputSetter.addEvents).toHaveBeenCalled();
});
- describe('if config.InputSetter is not set', function () {
- beforeEach(function () {
+ describe('if config.InputSetter is not set', function() {
+ beforeEach(function() {
this.config = { InputSetter: undefined };
this.hook = { config: this.config };
InputSetter.init.call(this.inputSetter, this.hook);
});
- it('should set .config to an empty object', function () {
+ it('should set .config to an empty object', function() {
expect(this.inputSetter.config).toEqual({});
});
- it('should set hook.config to an empty object', function () {
+ it('should set hook.config to an empty object', function() {
expect(this.hook.config.InputSetter).toEqual({});
});
- })
+ });
});
- describe('addEvents', function () {
- beforeEach(function () {
+ describe('addEvents', function() {
+ beforeEach(function() {
this.hook = { list: { list: jasmine.createSpyObj('list', ['addEventListener']) } };
this.inputSetter = { eventWrapper: {}, hook: this.hook, setInputs: () => {} };
InputSetter.addEvents.call(this.inputSetter);
});
- it('should set .eventWrapper.setInputs', function () {
+ it('should set .eventWrapper.setInputs', function() {
expect(this.inputSetter.eventWrapper.setInputs).toEqual(jasmine.any(Function));
});
- it('should call .addEventListener', function () {
- expect(this.hook.list.list.addEventListener)
- .toHaveBeenCalledWith('click.dl', this.inputSetter.eventWrapper.setInputs);
+ it('should call .addEventListener', function() {
+ expect(this.hook.list.list.addEventListener).toHaveBeenCalledWith(
+ 'click.dl',
+ this.inputSetter.eventWrapper.setInputs,
+ );
});
});
- describe('removeEvents', function () {
- beforeEach(function () {
+ describe('removeEvents', function() {
+ beforeEach(function() {
this.hook = { list: { list: jasmine.createSpyObj('list', ['removeEventListener']) } };
this.eventWrapper = jasmine.createSpyObj('eventWrapper', ['setInputs']);
this.inputSetter = { eventWrapper: this.eventWrapper, hook: this.hook };
@@ -73,14 +73,16 @@ describe('InputSetter', function () {
InputSetter.removeEvents.call(this.inputSetter);
});
- it('should call .removeEventListener', function () {
- expect(this.hook.list.list.removeEventListener)
- .toHaveBeenCalledWith('click.dl', this.eventWrapper.setInputs);
+ it('should call .removeEventListener', function() {
+ expect(this.hook.list.list.removeEventListener).toHaveBeenCalledWith(
+ 'click.dl',
+ this.eventWrapper.setInputs,
+ );
});
});
- describe('setInputs', function () {
- beforeEach(function () {
+ describe('setInputs', function() {
+ beforeEach(function() {
this.event = { detail: { selected: {} } };
this.config = [0, 1];
this.inputSetter = { config: this.config, setInput: () => {} };
@@ -90,7 +92,7 @@ describe('InputSetter', function () {
InputSetter.setInputs.call(this.inputSetter, this.event);
});
- it('should call .setInput for each config element', function () {
+ it('should call .setInput for each config element', function() {
const allArgs = this.inputSetter.setInput.calls.allArgs();
expect(allArgs.length).toEqual(2);
@@ -101,21 +103,21 @@ describe('InputSetter', function () {
});
});
- describe('if config isnt an array', function () {
- beforeEach(function () {
+ describe('if config isnt an array', function() {
+ beforeEach(function() {
this.inputSetter = { config: {}, setInput: () => {} };
InputSetter.setInputs.call(this.inputSetter, this.event);
});
- it('should set .config to an array with .config as the first element', function () {
+ it('should set .config to an array with .config as the first element', function() {
expect(this.inputSetter.config).toEqual([{}]);
});
});
});
- describe('setInput', function () {
- beforeEach(function () {
+ describe('setInput', function() {
+ beforeEach(function() {
this.selectedItem = { getAttribute: () => {} };
this.input = { value: 'oldValue', tagName: 'INPUT', hasAttribute: () => {} };
this.config = { valueAttribute: {}, input: this.input };
@@ -128,20 +130,20 @@ describe('InputSetter', function () {
InputSetter.setInput.call(this.inputSetter, this.config, this.selectedItem);
});
- it('should call .getAttribute', function () {
+ it('should call .getAttribute', function() {
expect(this.selectedItem.getAttribute).toHaveBeenCalledWith(this.config.valueAttribute);
});
- it('should call .hasAttribute', function () {
+ it('should call .hasAttribute', function() {
expect(this.input.hasAttribute).toHaveBeenCalledWith(undefined);
});
- it('should set the value of the input', function () {
+ it('should set the value of the input', function() {
expect(this.input.value).toBe(this.newValue);
});
- describe('if no config.input is provided', function () {
- beforeEach(function () {
+ describe('if no config.input is provided', function() {
+ beforeEach(function() {
this.config = { valueAttribute: {} };
this.trigger = { value: 'oldValue', tagName: 'INPUT', hasAttribute: () => {} };
this.inputSetter = { hook: { trigger: this.trigger } };
@@ -149,26 +151,26 @@ describe('InputSetter', function () {
InputSetter.setInput.call(this.inputSetter, this.config, this.selectedItem);
});
- it('should set the value of the hook.trigger', function () {
+ it('should set the value of the hook.trigger', function() {
expect(this.trigger.value).toBe(this.newValue);
});
});
- describe('if the input tag is not INPUT', function () {
- beforeEach(function () {
+ describe('if the input tag is not INPUT', function() {
+ beforeEach(function() {
this.input = { textContent: 'oldValue', tagName: 'SPAN', hasAttribute: () => {} };
this.config = { valueAttribute: {}, input: this.input };
InputSetter.setInput.call(this.inputSetter, this.config, this.selectedItem);
});
- it('should set the textContent of the input', function () {
+ it('should set the textContent of the input', function() {
expect(this.input.textContent).toBe(this.newValue);
});
});
- describe('if there is an inputAttribute', function () {
- beforeEach(function () {
+ describe('if there is an inputAttribute', function() {
+ beforeEach(function() {
this.selectedItem = { getAttribute: () => {} };
this.input = { id: 'oldValue', hasAttribute: () => {}, setAttribute: () => {} };
this.inputSetter = { hook: { trigger: {} } };
@@ -187,25 +189,25 @@ describe('InputSetter', function () {
InputSetter.setInput.call(this.inputSetter, this.config, this.selectedItem);
});
- it('should call setAttribute', function () {
+ it('should call setAttribute', function() {
expect(this.input.setAttribute).toHaveBeenCalledWith(this.inputAttribute, this.newValue);
});
- it('should not set the value or textContent of the input', function () {
+ it('should not set the value or textContent of the input', function() {
expect(this.input.value).not.toBe('newValue');
expect(this.input.textContent).not.toBe('newValue');
});
});
});
- describe('destroy', function () {
- beforeEach(function () {
+ describe('destroy', function() {
+ beforeEach(function() {
this.inputSetter = jasmine.createSpyObj('inputSetter', ['removeEvents']);
InputSetter.destroy.call(this.inputSetter);
});
- it('should call .removeEvents', function () {
+ it('should call .removeEvents', function() {
expect(this.inputSetter.removeEvents).toHaveBeenCalled();
});
});
diff --git a/spec/javascripts/dropzone_input_spec.js b/spec/javascripts/dropzone_input_spec.js
index 0c6b1a8946d..326b2c029fb 100644
--- a/spec/javascripts/dropzone_input_spec.js
+++ b/spec/javascripts/dropzone_input_spec.js
@@ -7,12 +7,10 @@ const TEST_FILE = {
};
const TEST_UPLOAD_PATH = `${TEST_HOST}/upload/file`;
const TEST_ERROR_MESSAGE = 'A big error occurred!';
-const TEMPLATE = (
-`<form class="gfm-form" data-uploads-path="${TEST_UPLOAD_PATH}">
+const TEMPLATE = `<form class="gfm-form" data-uploads-path="${TEST_UPLOAD_PATH}">
<textarea class="js-gfm-input"></textarea>
<div class="uploading-error-message"></div>
-</form>`
-);
+</form>`;
describe('dropzone_input', () => {
let form;
diff --git a/spec/javascripts/emoji_spec.js b/spec/javascripts/emoji_spec.js
index 124d91f4477..3db4d9800f1 100644
--- a/spec/javascripts/emoji_spec.js
+++ b/spec/javascripts/emoji_spec.js
@@ -140,6 +140,7 @@ describe('gl_emoji', () => {
},
);
});
+
it('bomb emoji with sprite fallback', () => {
const emojiKey = 'bomb';
const markup = glEmojiTag(emojiFixtureMap[emojiKey].name, {
@@ -195,24 +196,31 @@ describe('gl_emoji', () => {
it('should gracefully handle empty string', () => {
expect(isFlagEmoji('')).toBeFalsy();
});
+
it('should detect flag_ac', () => {
expect(isFlagEmoji('🇦🇨')).toBeTruthy();
});
+
it('should detect flag_us', () => {
expect(isFlagEmoji('🇺🇸')).toBeTruthy();
});
+
it('should detect flag_zw', () => {
expect(isFlagEmoji('🇿🇼')).toBeTruthy();
});
+
it('should not detect flags', () => {
expect(isFlagEmoji('ðŸŽ')).toBeFalsy();
});
+
it('should not detect triangular_flag_on_post', () => {
expect(isFlagEmoji('🚩')).toBeFalsy();
});
+
it('should not detect single letter', () => {
expect(isFlagEmoji('🇦')).toBeFalsy();
});
+
it('should not detect >2 letters', () => {
expect(isFlagEmoji('🇦🇧🇨')).toBeFalsy();
});
@@ -222,15 +230,19 @@ describe('gl_emoji', () => {
it('should gracefully handle empty string', () => {
expect(isRainbowFlagEmoji('')).toBeFalsy();
});
+
it('should detect rainbow_flag', () => {
expect(isRainbowFlagEmoji('ðŸ³ðŸŒˆ')).toBeTruthy();
});
- it('should not detect flag_white on its\' own', () => {
+
+ it("should not detect flag_white on its' own", () => {
expect(isRainbowFlagEmoji('ðŸ³')).toBeFalsy();
});
- it('should not detect rainbow on its\' own', () => {
+
+ it("should not detect rainbow on its' own", () => {
expect(isRainbowFlagEmoji('🌈')).toBeFalsy();
});
+
it('should not detect flag_white with something else', () => {
expect(isRainbowFlagEmoji('ðŸ³ðŸ”µ')).toBeFalsy();
});
@@ -240,15 +252,19 @@ describe('gl_emoji', () => {
it('should gracefully handle empty string', () => {
expect(isKeycapEmoji('')).toBeFalsy();
});
+
it('should detect one(keycap)', () => {
expect(isKeycapEmoji('1ï¸âƒ£')).toBeTruthy();
});
+
it('should detect nine(keycap)', () => {
expect(isKeycapEmoji('9ï¸âƒ£')).toBeTruthy();
});
+
it('should not detect ten(keycap)', () => {
expect(isKeycapEmoji('🔟')).toBeFalsy();
});
+
it('should not detect hash(keycap)', () => {
expect(isKeycapEmoji('#⃣')).toBeFalsy();
});
@@ -258,24 +274,31 @@ describe('gl_emoji', () => {
it('should gracefully handle empty string', () => {
expect(isSkinToneComboEmoji('')).toBeFalsy();
});
+
it('should detect hand_splayed_tone5', () => {
expect(isSkinToneComboEmoji('ðŸ–ðŸ¿')).toBeTruthy();
});
+
it('should not detect hand_splayed', () => {
expect(isSkinToneComboEmoji('ðŸ–')).toBeFalsy();
});
+
it('should detect lifter_tone1', () => {
expect(isSkinToneComboEmoji('ðŸ‹ðŸ»')).toBeTruthy();
});
+
it('should not detect lifter', () => {
expect(isSkinToneComboEmoji('ðŸ‹')).toBeFalsy();
});
+
it('should detect rowboat_tone4', () => {
expect(isSkinToneComboEmoji('🚣ðŸ¾')).toBeTruthy();
});
+
it('should not detect rowboat', () => {
expect(isSkinToneComboEmoji('🚣')).toBeFalsy();
});
+
it('should not detect individual tone emoji', () => {
expect(isSkinToneComboEmoji('ðŸ»')).toBeFalsy();
});
@@ -285,9 +308,11 @@ describe('gl_emoji', () => {
it('should gracefully handle empty string', () => {
expect(isHorceRacingSkinToneComboEmoji('')).toBeFalsy();
});
+
it('should detect horse_racing_tone2', () => {
expect(isHorceRacingSkinToneComboEmoji('ðŸ‡ðŸ¼')).toBeTruthy();
});
+
it('should not detect horse_racing', () => {
expect(isHorceRacingSkinToneComboEmoji('ðŸ‡')).toBeFalsy();
});
@@ -297,36 +322,47 @@ describe('gl_emoji', () => {
it('should gracefully handle empty string', () => {
expect(isPersonZwjEmoji('')).toBeFalsy();
});
+
it('should detect couple_mm', () => {
expect(isPersonZwjEmoji('👨â€â¤ï¸â€ðŸ‘¨')).toBeTruthy();
});
+
it('should not detect couple_with_heart', () => {
expect(isPersonZwjEmoji('💑')).toBeFalsy();
});
+
it('should not detect couplekiss', () => {
expect(isPersonZwjEmoji('ðŸ’')).toBeFalsy();
});
+
it('should detect family_mmb', () => {
expect(isPersonZwjEmoji('👨â€ðŸ‘¨â€ðŸ‘¦')).toBeTruthy();
});
+
it('should detect family_mwgb', () => {
expect(isPersonZwjEmoji('👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦')).toBeTruthy();
});
+
it('should not detect family', () => {
expect(isPersonZwjEmoji('👪')).toBeFalsy();
});
+
it('should detect kiss_ww', () => {
expect(isPersonZwjEmoji('👩â€â¤ï¸â€ðŸ’‹â€ðŸ‘©')).toBeTruthy();
});
+
it('should not detect girl', () => {
expect(isPersonZwjEmoji('👧')).toBeFalsy();
});
+
it('should not detect girl_tone5', () => {
expect(isPersonZwjEmoji('👧ðŸ¿')).toBeFalsy();
});
+
it('should not detect man', () => {
expect(isPersonZwjEmoji('👨')).toBeFalsy();
});
+
it('should not detect woman', () => {
expect(isPersonZwjEmoji('👩')).toBeFalsy();
});
@@ -334,21 +370,17 @@ describe('gl_emoji', () => {
describe('isEmojiUnicodeSupported', () => {
it('should gracefully handle empty string with unicode support', () => {
- const isSupported = isEmojiUnicodeSupported(
- { '1.0': true },
- '',
- '1.0',
- );
+ const isSupported = isEmojiUnicodeSupported({ '1.0': true }, '', '1.0');
+
expect(isSupported).toBeTruthy();
});
+
it('should gracefully handle empty string without unicode support', () => {
- const isSupported = isEmojiUnicodeSupported(
- {},
- '',
- '1.0',
- );
+ const isSupported = isEmojiUnicodeSupported({}, '', '1.0');
+
expect(isSupported).toBeFalsy();
});
+
it('bomb(6.0) with 6.0 support', () => {
const emojiKey = 'bomb';
const unicodeSupportMap = Object.assign({}, emptySupportMap, {
@@ -359,6 +391,7 @@ describe('gl_emoji', () => {
emojiFixtureMap[emojiKey].moji,
emojiFixtureMap[emojiKey].unicodeVersion,
);
+
expect(isSupported).toBeTruthy();
});
@@ -370,6 +403,7 @@ describe('gl_emoji', () => {
emojiFixtureMap[emojiKey].moji,
emojiFixtureMap[emojiKey].unicodeVersion,
);
+
expect(isSupported).toBeFalsy();
});
@@ -383,6 +417,7 @@ describe('gl_emoji', () => {
emojiFixtureMap[emojiKey].moji,
emojiFixtureMap[emojiKey].unicodeVersion,
);
+
expect(isSupported).toBeFalsy();
});
@@ -408,6 +443,7 @@ describe('gl_emoji', () => {
emojiFixtureMap[emojiKey].moji,
emojiFixtureMap[emojiKey].unicodeVersion,
);
+
expect(isSupported).toBeFalsy();
});
@@ -425,6 +461,7 @@ describe('gl_emoji', () => {
emojiFixtureMap[emojiKey].moji,
emojiFixtureMap[emojiKey].unicodeVersion,
);
+
expect(isSupported).toBeTruthy();
});
@@ -442,6 +479,7 @@ describe('gl_emoji', () => {
emojiFixtureMap[emojiKey].moji,
emojiFixtureMap[emojiKey].unicodeVersion,
);
+
expect(isSupported).toBeFalsy();
});
});
diff --git a/spec/javascripts/environments/emtpy_state_spec.js b/spec/javascripts/environments/emtpy_state_spec.js
index 10a19af4175..1f986d49bc7 100644
--- a/spec/javascripts/environments/emtpy_state_spec.js
+++ b/spec/javascripts/environments/emtpy_state_spec.js
@@ -1,4 +1,3 @@
-
import Vue from 'vue';
import emptyState from '~/environments/components/empty_state.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
@@ -25,13 +24,13 @@ describe('environments empty state', () => {
});
it('renders empty state and new environment button', () => {
- expect(
- vm.$el.querySelector('.js-blank-state-title').textContent.trim(),
- ).toEqual('You don\'t have any environments right now.');
+ expect(vm.$el.querySelector('.js-blank-state-title').textContent.trim()).toEqual(
+ "You don't have any environments right now",
+ );
- expect(
- vm.$el.querySelector('.js-new-environment-button').getAttribute('href'),
- ).toEqual('foo');
+ expect(vm.$el.querySelector('.js-new-environment-button').getAttribute('href')).toEqual(
+ 'foo',
+ );
});
});
@@ -45,13 +44,11 @@ describe('environments empty state', () => {
});
it('renders empty state without new button', () => {
- expect(
- vm.$el.querySelector('.js-blank-state-title').textContent.trim(),
- ).toEqual('You don\'t have any environments right now.');
+ expect(vm.$el.querySelector('.js-blank-state-title').textContent.trim()).toEqual(
+ "You don't have any environments right now",
+ );
- expect(
- vm.$el.querySelector('.js-new-environment-button'),
- ).toBeNull();
+ expect(vm.$el.querySelector('.js-new-environment-button')).toBeNull();
});
});
});
diff --git a/spec/javascripts/environments/environment_actions_spec.js b/spec/javascripts/environments/environment_actions_spec.js
index ea40a1fcd4b..787df757d32 100644
--- a/spec/javascripts/environments/environment_actions_spec.js
+++ b/spec/javascripts/environments/environment_actions_spec.js
@@ -1,15 +1,19 @@
import Vue from 'vue';
-import actionsComp from '~/environments/components/environment_actions.vue';
+import eventHub from '~/environments/event_hub';
+import EnvironmentActions from '~/environments/components/environment_actions.vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import { TEST_HOST } from 'spec/test_constants';
-describe('Actions Component', () => {
- let ActionsComponent;
- let actionsMock;
- let component;
+describe('EnvironmentActions Component', () => {
+ const Component = Vue.extend(EnvironmentActions);
+ let vm;
- beforeEach(() => {
- ActionsComponent = Vue.extend(actionsComp);
+ afterEach(() => {
+ vm.$destroy();
+ });
- actionsMock = [
+ describe('manual actions', () => {
+ const actions = [
{
name: 'bar',
play_path: 'https://gitlab.com/play',
@@ -25,38 +29,89 @@ describe('Actions Component', () => {
},
];
- component = new ActionsComponent({
- propsData: {
- actions: actionsMock,
- },
- }).$mount();
- });
+ beforeEach(() => {
+ vm = mountComponent(Component, { actions });
+ });
+
+ it('should render a dropdown button with icon and title attribute', () => {
+ expect(vm.$el.querySelector('.fa-caret-down')).toBeDefined();
+ expect(vm.$el.querySelector('.dropdown-new').getAttribute('data-original-title')).toEqual(
+ 'Deploy to...',
+ );
- describe('computed', () => {
- it('title', () => {
- expect(component.title).toEqual('Deploy to...');
+ expect(vm.$el.querySelector('.dropdown-new').getAttribute('aria-label')).toEqual(
+ 'Deploy to...',
+ );
});
- });
- it('should render a dropdown button with icon and title attribute', () => {
- expect(component.$el.querySelector('.fa-caret-down')).toBeDefined();
- expect(component.$el.querySelector('.dropdown-new').getAttribute('data-original-title')).toEqual('Deploy to...');
- expect(component.$el.querySelector('.dropdown-new').getAttribute('aria-label')).toEqual('Deploy to...');
- });
+ it('should render a dropdown with the provided list of actions', () => {
+ expect(vm.$el.querySelectorAll('.dropdown-menu li').length).toEqual(actions.length);
+ });
+
+ it("should render a disabled action when it's not playable", () => {
+ expect(
+ vm.$el.querySelector('.dropdown-menu li:last-child button').getAttribute('disabled'),
+ ).toEqual('disabled');
- it('should render a dropdown with the provided list of actions', () => {
- expect(
- component.$el.querySelectorAll('.dropdown-menu li').length,
- ).toEqual(actionsMock.length);
+ expect(
+ vm.$el.querySelector('.dropdown-menu li:last-child button').classList.contains('disabled'),
+ ).toEqual(true);
+ });
});
- it('should render a disabled action when it\'s not playable', () => {
- expect(
- component.$el.querySelector('.dropdown-menu li:last-child button').getAttribute('disabled'),
- ).toEqual('disabled');
+ describe('scheduled jobs', () => {
+ const scheduledJobAction = {
+ name: 'scheduled action',
+ playPath: `${TEST_HOST}/scheduled/job/action`,
+ playable: true,
+ scheduledAt: '2063-04-05T00:42:00Z',
+ };
+ const expiredJobAction = {
+ name: 'expired action',
+ playPath: `${TEST_HOST}/expired/job/action`,
+ playable: true,
+ scheduledAt: '2018-10-05T08:23:00Z',
+ };
+ const findDropdownItem = action => {
+ const buttons = vm.$el.querySelectorAll('.dropdown-menu li button');
+ return Array.prototype.find.call(buttons, element =>
+ element.innerText.trim().startsWith(action.name),
+ );
+ };
+
+ beforeEach(() => {
+ spyOn(Date, 'now').and.callFake(() => new Date('2063-04-04T00:42:00Z').getTime());
+ vm = mountComponent(Component, { actions: [scheduledJobAction, expiredJobAction] });
+ });
- expect(
- component.$el.querySelector('.dropdown-menu li:last-child button').classList.contains('disabled'),
- ).toEqual(true);
+ it('emits postAction event after confirming', () => {
+ const emitSpy = jasmine.createSpy('emit');
+ eventHub.$on('postAction', emitSpy);
+ spyOn(window, 'confirm').and.callFake(() => true);
+
+ findDropdownItem(scheduledJobAction).click();
+
+ expect(window.confirm).toHaveBeenCalled();
+ expect(emitSpy).toHaveBeenCalledWith({ endpoint: scheduledJobAction.playPath });
+ });
+
+ it('does not emit postAction event if confirmation is cancelled', () => {
+ const emitSpy = jasmine.createSpy('emit');
+ eventHub.$on('postAction', emitSpy);
+ spyOn(window, 'confirm').and.callFake(() => false);
+
+ findDropdownItem(scheduledJobAction).click();
+
+ expect(window.confirm).toHaveBeenCalled();
+ expect(emitSpy).not.toHaveBeenCalled();
+ });
+
+ it('displays the remaining time in the dropdown', () => {
+ expect(findDropdownItem(scheduledJobAction)).toContainText('24:00:00');
+ });
+
+ it('displays 00:00:00 for expired jobs in the dropdown', () => {
+ expect(findDropdownItem(expiredJobAction)).toContainText('00:00:00');
+ });
});
});
diff --git a/spec/javascripts/environments/environment_item_spec.js b/spec/javascripts/environments/environment_item_spec.js
index 0b933dda431..7618c2f50ce 100644
--- a/spec/javascripts/environments/environment_item_spec.js
+++ b/spec/javascripts/environments/environment_item_spec.js
@@ -38,7 +38,9 @@ describe('Environment item', () => {
});
it('Should render the number of children in a badge', () => {
- expect(component.$el.querySelector('.folder-name .badge').textContent).toContain(mockItem.size);
+ expect(component.$el.querySelector('.folder-name .badge').textContent).toContain(
+ mockItem.size,
+ );
});
});
@@ -68,7 +70,8 @@ describe('Environment item', () => {
username: 'root',
id: 1,
state: 'active',
- avatar_url: 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
web_url: 'http://localhost:3000/root',
},
commit: {
@@ -84,7 +87,8 @@ describe('Environment item', () => {
username: 'root',
id: 1,
state: 'active',
- avatar_url: 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
web_url: 'http://localhost:3000/root',
},
commit_path: '/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd',
@@ -121,18 +125,18 @@ describe('Environment item', () => {
});
it('should render environment name', () => {
- expect(component.$el.querySelector('.environment-name').textContent).toContain(environment.name);
+ expect(component.$el.querySelector('.environment-name').textContent).toContain(
+ environment.name,
+ );
});
describe('With deployment', () => {
it('should render deployment internal id', () => {
- expect(
- component.$el.querySelector('.deployment-column span').textContent,
- ).toContain(environment.last_deployment.iid);
+ expect(component.$el.querySelector('.deployment-column span').textContent).toContain(
+ environment.last_deployment.iid,
+ );
- expect(
- component.$el.querySelector('.deployment-column span').textContent,
- ).toContain('#');
+ expect(component.$el.querySelector('.deployment-column span').textContent).toContain('#');
});
it('should render last deployment date', () => {
@@ -156,56 +160,46 @@ describe('Environment item', () => {
describe('With build url', () => {
it('Should link to build url provided', () => {
- expect(
- component.$el.querySelector('.build-link').getAttribute('href'),
- ).toEqual(environment.last_deployment.deployable.build_path);
+ expect(component.$el.querySelector('.build-link').getAttribute('href')).toEqual(
+ environment.last_deployment.deployable.build_path,
+ );
});
it('Should render deployable name and id', () => {
- expect(
- component.$el.querySelector('.build-link').getAttribute('href'),
- ).toEqual(environment.last_deployment.deployable.build_path);
+ expect(component.$el.querySelector('.build-link').getAttribute('href')).toEqual(
+ environment.last_deployment.deployable.build_path,
+ );
});
});
describe('With commit information', () => {
it('should render commit component', () => {
- expect(
- component.$el.querySelector('.js-commit-component'),
- ).toBeDefined();
+ expect(component.$el.querySelector('.js-commit-component')).toBeDefined();
});
});
});
describe('With manual actions', () => {
it('Should render actions component', () => {
- expect(
- component.$el.querySelector('.js-manual-actions-container'),
- ).toBeDefined();
+ expect(component.$el.querySelector('.js-manual-actions-container')).toBeDefined();
});
});
describe('With external URL', () => {
it('should render external url component', () => {
- expect(
- component.$el.querySelector('.js-external-url-container'),
- ).toBeDefined();
+ expect(component.$el.querySelector('.js-external-url-container')).toBeDefined();
});
});
describe('With stop action', () => {
it('Should render stop action component', () => {
- expect(
- component.$el.querySelector('.js-stop-component-container'),
- ).toBeDefined();
+ expect(component.$el.querySelector('.js-stop-component-container')).toBeDefined();
});
});
describe('With retry action', () => {
it('Should render rollback component', () => {
- expect(
- component.$el.querySelector('.js-rollback-component-container'),
- ).toBeDefined();
+ expect(component.$el.querySelector('.js-rollback-component-container')).toBeDefined();
});
});
});
diff --git a/spec/javascripts/environments/environments_app_spec.js b/spec/javascripts/environments/environments_app_spec.js
index 6968fbc7ce7..e2d81eb454a 100644
--- a/spec/javascripts/environments/environments_app_spec.js
+++ b/spec/javascripts/environments/environments_app_spec.js
@@ -31,9 +31,9 @@ describe('Environment', () => {
mock.restore();
});
- describe('successfull request', () => {
+ describe('successful request', () => {
describe('without environments', () => {
- beforeEach((done) => {
+ beforeEach(done => {
mock.onGet(mockData.endpoint).reply(200, { environments: [] });
component = mountComponent(EnvironmentsComponent, mockData);
@@ -44,30 +44,34 @@ describe('Environment', () => {
});
it('should render the empty state', () => {
- expect(
- component.$el.querySelector('.js-new-environment-button').textContent,
- ).toContain('New environment');
+ expect(component.$el.querySelector('.js-new-environment-button').textContent).toContain(
+ 'New environment',
+ );
- expect(
- component.$el.querySelector('.js-blank-state-title').textContent,
- ).toContain('You don\'t have any environments right now.');
+ expect(component.$el.querySelector('.js-blank-state-title').textContent).toContain(
+ "You don't have any environments right now",
+ );
});
});
describe('with paginated environments', () => {
- beforeEach((done) => {
- mock.onGet(mockData.endpoint).reply(200, {
- environments: [environment],
- stopped_count: 1,
- available_count: 0,
- }, {
- 'X-nExt-pAge': '2',
- 'x-page': '1',
- 'X-Per-Page': '1',
- 'X-Prev-Page': '',
- 'X-TOTAL': '37',
- 'X-Total-Pages': '2',
- });
+ beforeEach(done => {
+ mock.onGet(mockData.endpoint).reply(
+ 200,
+ {
+ environments: [environment],
+ stopped_count: 1,
+ available_count: 0,
+ },
+ {
+ 'X-nExt-pAge': '2',
+ 'x-page': '1',
+ 'X-Per-Page': '1',
+ 'X-Prev-Page': '',
+ 'X-TOTAL': '37',
+ 'X-Total-Pages': '2',
+ },
+ );
component = mountComponent(EnvironmentsComponent, mockData);
@@ -78,28 +82,27 @@ describe('Environment', () => {
it('should render a table with environments', () => {
expect(component.$el.querySelectorAll('table')).not.toBeNull();
- expect(
- component.$el.querySelector('.environment-name').textContent.trim(),
- ).toEqual(environment.name);
+ expect(component.$el.querySelector('.environment-name').textContent.trim()).toEqual(
+ environment.name,
+ );
});
describe('pagination', () => {
it('should render pagination', () => {
- expect(
- component.$el.querySelectorAll('.gl-pagination li').length,
- ).toEqual(5);
+ expect(component.$el.querySelectorAll('.gl-pagination li').length).toEqual(5);
});
- it('should make an API request when page is clicked', (done) => {
+ it('should make an API request when page is clicked', done => {
spyOn(component, 'updateContent');
setTimeout(() => {
component.$el.querySelector('.gl-pagination li:nth-child(5) a').click();
+
expect(component.updateContent).toHaveBeenCalledWith({ scope: 'available', page: '2' });
done();
}, 0);
});
- it('should make an API request when using tabs', (done) => {
+ it('should make an API request when using tabs', done => {
setTimeout(() => {
spyOn(component, 'updateContent');
component.$el.querySelector('.js-environments-tab-stopped').click();
@@ -113,7 +116,7 @@ describe('Environment', () => {
});
describe('unsuccessfull request', () => {
- beforeEach((done) => {
+ beforeEach(done => {
mock.onGet(mockData.endpoint).reply(500, {});
component = mountComponent(EnvironmentsComponent, mockData);
@@ -124,15 +127,16 @@ describe('Environment', () => {
});
it('should render empty state', () => {
- expect(
- component.$el.querySelector('.js-blank-state-title').textContent,
- ).toContain('You don\'t have any environments right now.');
+ expect(component.$el.querySelector('.js-blank-state-title').textContent).toContain(
+ "You don't have any environments right now",
+ );
});
});
describe('expandable folders', () => {
beforeEach(() => {
- mock.onGet(mockData.endpoint).reply(200,
+ mock.onGet(mockData.endpoint).reply(
+ 200,
{
environments: [folder],
stopped_count: 0,
@@ -153,23 +157,18 @@ describe('Environment', () => {
component = mountComponent(EnvironmentsComponent, mockData);
});
- it('should open a closed folder', (done) => {
+ it('should open a closed folder', done => {
setTimeout(() => {
component.$el.querySelector('.folder-name').click();
Vue.nextTick(() => {
- expect(
- component.$el.querySelector('.folder-icon i.fa-caret-right').getAttribute('style'),
- ).toContain('display: none');
- expect(
- component.$el.querySelector('.folder-icon i.fa-caret-down').getAttribute('style'),
- ).not.toContain('display: none');
+ expect(component.$el.querySelector('.folder-icon.ic-chevron-right')).toBe(null);
done();
});
}, 0);
});
- it('should close an opened folder', (done) => {
+ it('should close an opened folder', done => {
setTimeout(() => {
// open folder
component.$el.querySelector('.folder-name').click();
@@ -179,19 +178,14 @@ describe('Environment', () => {
component.$el.querySelector('.folder-name').click();
Vue.nextTick(() => {
- expect(
- component.$el.querySelector('.folder-icon i.fa-caret-down').getAttribute('style'),
- ).toContain('display: none');
- expect(
- component.$el.querySelector('.folder-icon i.fa-caret-right').getAttribute('style'),
- ).not.toContain('display: none');
+ expect(component.$el.querySelector('.folder-icon.ic-chevron-down')).toBe(null);
done();
});
});
}, 0);
});
- it('should show children environments and a button to show all environments', (done) => {
+ it('should show children environments and a button to show all environments', done => {
setTimeout(() => {
// open folder
component.$el.querySelector('.folder-name').click();
@@ -200,7 +194,9 @@ describe('Environment', () => {
// wait for next async request
setTimeout(() => {
expect(component.$el.querySelectorAll('.js-child-row').length).toEqual(1);
- expect(component.$el.querySelector('.text-center > a.btn').textContent).toContain('Show all');
+ expect(component.$el.querySelector('.text-center > a.btn').textContent).toContain(
+ 'Show all',
+ );
done();
});
});
@@ -210,7 +206,8 @@ describe('Environment', () => {
describe('methods', () => {
beforeEach(() => {
- mock.onGet(mockData.endpoint).reply(200,
+ mock.onGet(mockData.endpoint).reply(
+ 200,
{
environments: [],
stopped_count: 0,
@@ -224,8 +221,9 @@ describe('Environment', () => {
});
describe('updateContent', () => {
- it('should set given parameters', (done) => {
- component.updateContent({ scope: 'stopped', page: '3' })
+ it('should set given parameters', done => {
+ component
+ .updateContent({ scope: 'stopped', page: '3' })
.then(() => {
expect(component.page).toEqual('3');
expect(component.scope).toEqual('stopped');
diff --git a/spec/javascripts/environments/environments_store_spec.js b/spec/javascripts/environments/environments_store_spec.js
index f2c6ec24dd7..c3d16f10d72 100644
--- a/spec/javascripts/environments/environments_store_spec.js
+++ b/spec/javascripts/environments/environments_store_spec.js
@@ -17,23 +17,27 @@ describe('Store', () => {
it('should store environments', () => {
store.storeEnvironments(serverData);
+
expect(store.state.environments.length).toEqual(serverData.length);
expect(store.state.environments[0]).toEqual(environmentsList[0]);
});
it('should store available count', () => {
store.storeAvailableCount(2);
+
expect(store.state.availableCounter).toEqual(2);
});
it('should store stopped count', () => {
store.storeStoppedCount(2);
+
expect(store.state.stoppedCounter).toEqual(2);
});
describe('store environments', () => {
it('should store environments', () => {
store.storeEnvironments(serverData);
+
expect(store.state.environments.length).toEqual(serverData.length);
});
@@ -45,6 +49,7 @@ describe('Store', () => {
};
store.storeEnvironments([environment]);
+
expect(store.state.environments[0].isFolder).toEqual(true);
expect(store.state.environments[0].folderName).toEqual('bar');
});
@@ -61,17 +66,20 @@ describe('Store', () => {
};
store.storeEnvironments([environment]);
+
expect(store.state.environments[0].last_deployment).toEqual({});
expect(store.state.environments[0].isStoppable).toEqual(true);
});
it('should store latest.name when the environment is not a folder', () => {
store.storeEnvironments(serverData);
+
expect(store.state.environments[0].name).toEqual(serverData[0].latest.name);
});
it('should store root level name when environment is a folder', () => {
store.storeEnvironments(serverData);
+
expect(store.state.environments[1].folderName).toEqual(serverData[1].name);
});
});
@@ -81,9 +89,11 @@ describe('Store', () => {
store.storeEnvironments(serverData);
store.toggleFolder(store.state.environments[1]);
+
expect(store.state.environments[1].isOpen).toEqual(true);
store.toggleFolder(store.state.environments[1]);
+
expect(store.state.environments[1].isOpen).toEqual(false);
});
@@ -91,9 +101,11 @@ describe('Store', () => {
store.storeEnvironments(serverData);
store.toggleFolder(store.state.environments[1]);
+
expect(store.state.environments[1].isOpen).toEqual(true);
store.storeEnvironments(serverData);
+
expect(store.state.environments[1].isOpen).toEqual(true);
});
});
@@ -116,6 +128,7 @@ describe('Store', () => {
expect(store.state.environments[1].children.length).toEqual(serverData.length);
// poll
store.storeEnvironments(serverData);
+
expect(store.state.environments[1].children.length).toEqual(serverData.length);
});
});
@@ -141,6 +154,7 @@ describe('Store', () => {
};
store.setPagination(pagination);
+
expect(store.state.paginationInformation).toEqual(expectedResult);
});
});
@@ -150,6 +164,7 @@ describe('Store', () => {
store.storeEnvironments(serverData);
store.toggleFolder(store.state.environments[1]);
+
expect(store.getOpenFolders()[0]).toEqual(store.state.environments[1]);
});
});
diff --git a/spec/javascripts/environments/folder/environments_folder_view_spec.js b/spec/javascripts/environments/folder/environments_folder_view_spec.js
index 51d4213c38f..7f0a9475d5f 100644
--- a/spec/javascripts/environments/folder/environments_folder_view_spec.js
+++ b/spec/javascripts/environments/folder/environments_folder_view_spec.js
@@ -30,39 +30,43 @@ describe('Environments Folder View', () => {
component.$destroy();
});
- describe('successfull request', () => {
+ describe('successful request', () => {
beforeEach(() => {
- mock.onGet(mockData.endpoint).reply(200, {
- environments: environmentsList,
- stopped_count: 1,
- available_count: 0,
- }, {
- 'X-nExt-pAge': '2',
- 'x-page': '1',
- 'X-Per-Page': '2',
- 'X-Prev-Page': '',
- 'X-TOTAL': '20',
- 'X-Total-Pages': '10',
- });
+ mock.onGet(mockData.endpoint).reply(
+ 200,
+ {
+ environments: environmentsList,
+ stopped_count: 1,
+ available_count: 0,
+ },
+ {
+ 'X-nExt-pAge': '2',
+ 'x-page': '1',
+ 'X-Per-Page': '2',
+ 'X-Prev-Page': '',
+ 'X-TOTAL': '20',
+ 'X-Total-Pages': '10',
+ },
+ );
component = mountComponent(Component, mockData);
});
- it('should render a table with environments', (done) => {
+ it('should render a table with environments', done => {
setTimeout(() => {
expect(component.$el.querySelectorAll('table')).not.toBeNull();
- expect(
- component.$el.querySelector('.environment-name').textContent.trim(),
- ).toEqual(environmentsList[0].name);
+ expect(component.$el.querySelector('.environment-name').textContent.trim()).toEqual(
+ environmentsList[0].name,
+ );
done();
}, 0);
});
- it('should render available tab with count', (done) => {
+ it('should render available tab with count', done => {
setTimeout(() => {
- expect(
- component.$el.querySelector('.js-environments-tab-available').textContent,
- ).toContain('Available');
+ expect(component.$el.querySelector('.js-environments-tab-available').textContent).toContain(
+ 'Available',
+ );
expect(
component.$el.querySelector('.js-environments-tab-available .badge').textContent,
@@ -71,11 +75,11 @@ describe('Environments Folder View', () => {
}, 0);
});
- it('should render stopped tab with count', (done) => {
+ it('should render stopped tab with count', done => {
setTimeout(() => {
- expect(
- component.$el.querySelector('.js-environments-tab-stopped').textContent,
- ).toContain('Stopped');
+ expect(component.$el.querySelector('.js-environments-tab-stopped').textContent).toContain(
+ 'Stopped',
+ );
expect(
component.$el.querySelector('.js-environments-tab-stopped .badge').textContent,
@@ -84,36 +88,37 @@ describe('Environments Folder View', () => {
}, 0);
});
- it('should render parent folder name', (done) => {
+ it('should render parent folder name', done => {
setTimeout(() => {
- expect(
- component.$el.querySelector('.js-folder-name').textContent.trim(),
- ).toContain('Environments / review');
+ expect(component.$el.querySelector('.js-folder-name').textContent.trim()).toContain(
+ 'Environments / review',
+ );
done();
}, 0);
});
describe('pagination', () => {
- it('should render pagination', (done) => {
+ it('should render pagination', done => {
setTimeout(() => {
- expect(
- component.$el.querySelectorAll('.gl-pagination'),
- ).not.toBeNull();
+ expect(component.$el.querySelectorAll('.gl-pagination')).not.toBeNull();
done();
}, 0);
});
- it('should make an API request when changing page', (done) => {
+ it('should make an API request when changing page', done => {
spyOn(component, 'updateContent');
setTimeout(() => {
component.$el.querySelector('.gl-pagination .js-last-button a').click();
- expect(component.updateContent).toHaveBeenCalledWith({ scope: component.scope, page: '10' });
+ expect(component.updateContent).toHaveBeenCalledWith({
+ scope: component.scope,
+ page: '10',
+ });
done();
}, 0);
});
- it('should make an API request when using tabs', (done) => {
+ it('should make an API request when using tabs', done => {
setTimeout(() => {
spyOn(component, 'updateContent');
component.$el.querySelector('.js-environments-tab-stopped').click();
@@ -134,20 +139,18 @@ describe('Environments Folder View', () => {
component = mountComponent(Component, mockData);
});
- it('should not render a table', (done) => {
+ it('should not render a table', done => {
setTimeout(() => {
- expect(
- component.$el.querySelector('table'),
- ).toBe(null);
+ expect(component.$el.querySelector('table')).toBe(null);
done();
}, 0);
});
- it('should render available tab with count 0', (done) => {
+ it('should render available tab with count 0', done => {
setTimeout(() => {
- expect(
- component.$el.querySelector('.js-environments-tab-available').textContent,
- ).toContain('Available');
+ expect(component.$el.querySelector('.js-environments-tab-available').textContent).toContain(
+ 'Available',
+ );
expect(
component.$el.querySelector('.js-environments-tab-available .badge').textContent,
@@ -156,11 +159,11 @@ describe('Environments Folder View', () => {
}, 0);
});
- it('should render stopped tab with count 0', (done) => {
+ it('should render stopped tab with count 0', done => {
setTimeout(() => {
- expect(
- component.$el.querySelector('.js-environments-tab-stopped').textContent,
- ).toContain('Stopped');
+ expect(component.$el.querySelector('.js-environments-tab-stopped').textContent).toContain(
+ 'Stopped',
+ );
expect(
component.$el.querySelector('.js-environments-tab-stopped .badge').textContent,
@@ -181,8 +184,9 @@ describe('Environments Folder View', () => {
});
describe('updateContent', () => {
- it('should set given parameters', (done) => {
- component.updateContent({ scope: 'stopped', page: '4' })
+ it('should set given parameters', done => {
+ component
+ .updateContent({ scope: 'stopped', page: '4' })
.then(() => {
expect(component.page).toEqual('4');
expect(component.scope).toEqual('stopped');
diff --git a/spec/javascripts/feature_highlight/feature_highlight_helper_spec.js b/spec/javascripts/feature_highlight/feature_highlight_helper_spec.js
index 2ab6a0077b5..e5795d4cbb1 100644
--- a/spec/javascripts/feature_highlight/feature_highlight_helper_spec.js
+++ b/spec/javascripts/feature_highlight/feature_highlight_helper_spec.js
@@ -1,11 +1,7 @@
import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
-import {
- getSelector,
- dismiss,
- inserted,
-} from '~/feature_highlight/feature_highlight_helper';
+import { getSelector, dismiss, inserted } from '~/feature_highlight/feature_highlight_helper';
import { togglePopover } from '~/shared/popover';
import getSetTimeoutPromise from 'spec/helpers/set_timeout_promise_helper';
@@ -14,7 +10,10 @@ describe('feature highlight helper', () => {
describe('getSelector', () => {
it('returns js-feature-highlight selector', () => {
const highlightId = 'highlightId';
- expect(getSelector(highlightId)).toEqual(`.js-feature-highlight[data-highlight=${highlightId}]`);
+
+ expect(getSelector(highlightId)).toEqual(
+ `.js-feature-highlight[data-highlight=${highlightId}]`,
+ );
});
});
@@ -37,7 +36,7 @@ describe('feature highlight helper', () => {
mock.restore();
});
- it('calls persistent dismissal endpoint', (done) => {
+ it('calls persistent dismissal endpoint', done => {
const spy = jasmine.createSpy('dismiss-endpoint-hit');
mock.onPost('/-/callouts/dismiss').reply(spy);
@@ -59,7 +58,7 @@ describe('feature highlight helper', () => {
});
describe('inserted', () => {
- it('registers click event callback', (done) => {
+ it('registers click event callback', done => {
const context = {
getAttribute: () => 'popoverId',
dataset: {
@@ -67,7 +66,7 @@ describe('feature highlight helper', () => {
},
};
- spyOn($.fn, 'on').and.callFake((event) => {
+ spyOn($.fn, 'on').and.callFake(event => {
expect(event).toEqual('click');
done();
});
diff --git a/spec/javascripts/feature_highlight/feature_highlight_spec.js b/spec/javascripts/feature_highlight/feature_highlight_spec.js
index ec46d4f905a..0a9fba789c3 100644
--- a/spec/javascripts/feature_highlight/feature_highlight_spec.js
+++ b/spec/javascripts/feature_highlight/feature_highlight_spec.js
@@ -50,7 +50,7 @@ describe('feature highlight', () => {
expect(toggleSpy).toHaveBeenCalledWith(jasmine.any(Object), true);
});
- it('setup debounced mouseleave', (done) => {
+ it('setup debounced mouseleave', done => {
const toggleSpy = spyOn(popover.togglePopover, 'call');
$(selector).trigger('mouseleave');
@@ -63,7 +63,10 @@ describe('feature highlight', () => {
it('setup show.bs.popover', () => {
$(selector).trigger('show.bs.popover');
- expect(window.addEventListener).toHaveBeenCalledWith('scroll', jasmine.any(Function), { once: true });
+
+ expect(window.addEventListener).toHaveBeenCalledWith('scroll', jasmine.any(Function), {
+ once: true,
+ });
});
it('removes disabled attribute', () => {
@@ -73,6 +76,7 @@ describe('feature highlight', () => {
it('displays popover', () => {
expect(document.querySelector(selector).getAttribute('aria-describedby')).toBeFalsy();
$(selector).trigger('mouseenter');
+
expect(document.querySelector(selector).getAttribute('aria-describedby')).toBeTruthy();
});
diff --git a/spec/javascripts/filtered_search/components/recent_searches_dropdown_content_spec.js b/spec/javascripts/filtered_search/components/recent_searches_dropdown_content_spec.js
index 9d670afe206..d1742dcedfa 100644
--- a/spec/javascripts/filtered_search/components/recent_searches_dropdown_content_spec.js
+++ b/spec/javascripts/filtered_search/components/recent_searches_dropdown_content_spec.js
@@ -3,7 +3,7 @@ import eventHub from '~/filtered_search/event_hub';
import RecentSearchesDropdownContent from '~/filtered_search/components/recent_searches_dropdown_content.vue';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-const createComponent = (propsData) => {
+const createComponent = propsData => {
const Component = Vue.extend(RecentSearchesDropdownContent);
return new Component({
@@ -21,10 +21,7 @@ describe('RecentSearchesDropdownContent', () => {
allowedKeys: IssuableFilteredSearchTokenKeys.getKeys(),
};
const propsDataWithItems = {
- items: [
- 'foo',
- 'author:@root label:~foo bar',
- ],
+ items: ['foo', 'author:@root label:~foo bar'],
allowedKeys: IssuableFilteredSearchTokenKeys.getKeys(),
};
@@ -47,6 +44,7 @@ describe('RecentSearchesDropdownContent', () => {
expect(el.querySelector('.dropdown-info-note')).toBeDefined();
const items = el.querySelectorAll('.filtered-search-history-dropdown-item');
+
expect(items.length).toEqual(propsDataWithoutItems.items.length);
});
});
@@ -65,17 +63,27 @@ describe('RecentSearchesDropdownContent', () => {
it('should render recent search items', () => {
const items = el.querySelectorAll('.filtered-search-history-dropdown-item');
+
expect(items.length).toEqual(propsDataWithItems.items.length);
- expect(trimMarkupWhitespace(items[0].querySelector('.filtered-search-history-dropdown-search-token').textContent)).toEqual('foo');
+ expect(
+ trimMarkupWhitespace(
+ items[0].querySelector('.filtered-search-history-dropdown-search-token').textContent,
+ ),
+ ).toEqual('foo');
const item1Tokens = items[1].querySelectorAll('.filtered-search-history-dropdown-token');
+
expect(item1Tokens.length).toEqual(2);
expect(item1Tokens[0].querySelector('.name').textContent).toEqual('author:');
expect(item1Tokens[0].querySelector('.value').textContent).toEqual('@root');
expect(item1Tokens[1].querySelector('.name').textContent).toEqual('label:');
expect(item1Tokens[1].querySelector('.value').textContent).toEqual('~foo');
- expect(trimMarkupWhitespace(items[1].querySelector('.filtered-search-history-dropdown-search-token').textContent)).toEqual('bar');
+ expect(
+ trimMarkupWhitespace(
+ items[1].querySelector('.filtered-search-history-dropdown-search-token').textContent,
+ ),
+ ).toEqual('bar');
});
});
@@ -132,12 +140,14 @@ describe('RecentSearchesDropdownContent', () => {
it('with items', () => {
vm = createComponent(propsDataWithItems);
const { hasItems } = vm;
+
expect(hasItems).toEqual(true);
});
it('with no items', () => {
vm = createComponent(propsDataWithoutItems);
const { hasItems } = vm;
+
expect(hasItems).toEqual(false);
});
});
@@ -161,6 +171,7 @@ describe('RecentSearchesDropdownContent', () => {
it('emits event', () => {
expect(onRecentSearchesItemSelectedSpy).not.toHaveBeenCalled();
vm.onItemActivated('something');
+
expect(onRecentSearchesItemSelectedSpy).toHaveBeenCalledWith('something');
});
});
@@ -182,6 +193,7 @@ describe('RecentSearchesDropdownContent', () => {
it('emits event', () => {
expect(onRequestClearRecentSearchesSpy).not.toHaveBeenCalled();
vm.onRequestClearRecentSearches({ stopPropagation: () => {} });
+
expect(onRequestClearRecentSearchesSpy).toHaveBeenCalled();
});
});
diff --git a/spec/javascripts/filtered_search/dropdown_user_spec.js b/spec/javascripts/filtered_search/dropdown_user_spec.js
index b48b1456eff..e8fcc8592eb 100644
--- a/spec/javascripts/filtered_search/dropdown_user_spec.js
+++ b/spec/javascripts/filtered_search/dropdown_user_spec.js
@@ -28,14 +28,14 @@ describe('Dropdown User', () => {
it('should not return the single quote found in value', () => {
spyOn(FilteredSearchTokenizer, 'processTokens').and.returnValue({
- lastToken: '\'larry boy',
+ lastToken: "'larry boy",
});
expect(dropdownUser.getSearchInput()).toBe('larry boy');
});
});
- describe('config AjaxFilter\'s endpoint', () => {
+ describe("config AjaxFilter's endpoint", () => {
beforeEach(() => {
spyOn(DropdownUser.prototype, 'bindEvents').and.callFake(() => {});
spyOn(DropdownUser.prototype, 'getProjectId').and.callFake(() => {});
@@ -88,10 +88,12 @@ describe('Dropdown User', () => {
});
});
- const findCurrentUserElement = () => authorFilterDropdownElement.querySelector('.js-current-user');
+ const findCurrentUserElement = () =>
+ authorFilterDropdownElement.querySelector('.js-current-user');
it('hides the current user from dropdown', () => {
const currentUserElement = findCurrentUserElement();
+
expect(currentUserElement).not.toBe(null);
dropdown.hideCurrentUser();
@@ -102,6 +104,7 @@ describe('Dropdown User', () => {
it('does nothing if no user is logged in', () => {
const currentUserElement = findCurrentUserElement();
currentUserElement.parentNode.removeChild(currentUserElement);
+
expect(findCurrentUserElement()).toBe(null);
dropdown.hideCurrentUser();
diff --git a/spec/javascripts/filtered_search/dropdown_utils_spec.js b/spec/javascripts/filtered_search/dropdown_utils_spec.js
index 8792e99d461..6605b0a30d7 100644
--- a/spec/javascripts/filtered_search/dropdown_utils_spec.js
+++ b/spec/javascripts/filtered_search/dropdown_utils_spec.js
@@ -10,25 +10,30 @@ describe('Dropdown Utils', () => {
describe('getEscapedText', () => {
it('should return same word when it has no space', () => {
const escaped = DropdownUtils.getEscapedText('textWithoutSpace');
+
expect(escaped).toBe('textWithoutSpace');
});
it('should escape with double quotes', () => {
let escaped = DropdownUtils.getEscapedText('text with space');
+
expect(escaped).toBe('"text with space"');
- escaped = DropdownUtils.getEscapedText('won\'t fix');
+ escaped = DropdownUtils.getEscapedText("won't fix");
+
expect(escaped).toBe('"won\'t fix"');
});
it('should escape with single quotes', () => {
const escaped = DropdownUtils.getEscapedText('won"t fix');
- expect(escaped).toBe('\'won"t fix\'');
+
+ expect(escaped).toBe("'won\"t fix'");
});
it('should escape with single quotes by default', () => {
const escaped = DropdownUtils.getEscapedText('won"t\' fix');
- expect(escaped).toBe('\'won"t\' fix\'');
+
+ expect(escaped).toBe("'won\"t' fix'");
});
});
@@ -50,6 +55,7 @@ describe('Dropdown Utils', () => {
input.value = 'roo';
const updatedItem = DropdownUtils.filterWithSymbol('@', input, item);
+
expect(updatedItem.droplab_hidden).toBe(false);
});
@@ -57,6 +63,7 @@ describe('Dropdown Utils', () => {
input.value = '@roo';
const updatedItem = DropdownUtils.filterWithSymbol('@', input, item);
+
expect(updatedItem.droplab_hidden).toBe(false);
});
@@ -69,6 +76,7 @@ describe('Dropdown Utils', () => {
input.value = '"';
const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
+
expect(updatedItem.droplab_hidden).toBe(false);
});
@@ -76,6 +84,7 @@ describe('Dropdown Utils', () => {
input.value = '~"';
const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
+
expect(updatedItem.droplab_hidden).toBe(false);
});
@@ -83,6 +92,7 @@ describe('Dropdown Utils', () => {
input.value = '"community con';
const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
+
expect(updatedItem.droplab_hidden).toBe(false);
});
@@ -90,34 +100,39 @@ describe('Dropdown Utils', () => {
input.value = '~"community con';
const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
+
expect(updatedItem.droplab_hidden).toBe(false);
});
it('should filter with single quote', () => {
- input.value = '\'';
+ input.value = "'";
const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
+
expect(updatedItem.droplab_hidden).toBe(false);
});
it('should filter with single quote and symbol', () => {
- input.value = '~\'';
+ input.value = "~'";
const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
+
expect(updatedItem.droplab_hidden).toBe(false);
});
it('should filter with single quote and multiple words', () => {
- input.value = '\'community con';
+ input.value = "'community con";
const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
+
expect(updatedItem.droplab_hidden).toBe(false);
});
it('should filter with single quote, symbol and multiple words', () => {
- input.value = '~\'community con';
+ input.value = "~'community con";
const updatedItem = DropdownUtils.filterWithSymbol('~', input, multipleWordItem);
+
expect(updatedItem.droplab_hidden).toBe(false);
});
});
@@ -152,17 +167,20 @@ describe('Dropdown Utils', () => {
let updatedItem = DropdownUtils.filterHint(config(), {
hint: 'label',
});
+
expect(updatedItem.droplab_hidden).toBe(false);
input.value = 'o';
updatedItem = DropdownUtils.filterHint(config(), {
hint: 'label',
});
+
expect(updatedItem.droplab_hidden).toBe(true);
});
it('should return droplab_hidden false when item has no hint', () => {
const updatedItem = DropdownUtils.filterHint(config(), {}, '');
+
expect(updatedItem.droplab_hidden).toBe(false);
});
@@ -172,6 +190,7 @@ describe('Dropdown Utils', () => {
hint: 'label',
type: 'array',
});
+
expect(updatedItem.droplab_hidden).toBe(false);
});
@@ -180,12 +199,14 @@ describe('Dropdown Utils', () => {
let updatedItem = DropdownUtils.filterHint(config(), {
hint: 'milestone',
});
+
expect(updatedItem.droplab_hidden).toBe(true);
updatedItem = DropdownUtils.filterHint(config(), {
hint: 'milestone',
type: 'string',
});
+
expect(updatedItem.droplab_hidden).toBe(true);
});
});
@@ -205,6 +226,7 @@ describe('Dropdown Utils', () => {
};
const updated = DropdownUtils.mergeDuplicateLabels(dataMap, newLabel);
+
expect(updated[newLabel.title]).toEqual(newLabel);
});
@@ -215,6 +237,7 @@ describe('Dropdown Utils', () => {
};
const updated = DropdownUtils.mergeDuplicateLabels(dataMap, duplicate);
+
expect(updated.label.multipleColors).toEqual([dataMap.label.color, duplicate.color]);
});
});
@@ -222,39 +245,64 @@ describe('Dropdown Utils', () => {
describe('duplicateLabelColor', () => {
it('should linear-gradient 2 colors', () => {
const gradient = DropdownUtils.duplicateLabelColor(['#FFFFFF', '#000000']);
- expect(gradient).toEqual('linear-gradient(#FFFFFF 0%, #FFFFFF 50%, #000000 50%, #000000 100%)');
+
+ expect(gradient).toEqual(
+ 'linear-gradient(#FFFFFF 0%, #FFFFFF 50%, #000000 50%, #000000 100%)',
+ );
});
it('should linear-gradient 3 colors', () => {
const gradient = DropdownUtils.duplicateLabelColor(['#FFFFFF', '#000000', '#333333']);
- expect(gradient).toEqual('linear-gradient(#FFFFFF 0%, #FFFFFF 33%, #000000 33%, #000000 66%, #333333 66%, #333333 100%)');
+
+ expect(gradient).toEqual(
+ 'linear-gradient(#FFFFFF 0%, #FFFFFF 33%, #000000 33%, #000000 66%, #333333 66%, #333333 100%)',
+ );
});
it('should linear-gradient 4 colors', () => {
- const gradient = DropdownUtils.duplicateLabelColor(['#FFFFFF', '#000000', '#333333', '#DDDDDD']);
- expect(gradient).toEqual('linear-gradient(#FFFFFF 0%, #FFFFFF 25%, #000000 25%, #000000 50%, #333333 50%, #333333 75%, #DDDDDD 75%, #DDDDDD 100%)');
+ const gradient = DropdownUtils.duplicateLabelColor([
+ '#FFFFFF',
+ '#000000',
+ '#333333',
+ '#DDDDDD',
+ ]);
+
+ expect(gradient).toEqual(
+ 'linear-gradient(#FFFFFF 0%, #FFFFFF 25%, #000000 25%, #000000 50%, #333333 50%, #333333 75%, #DDDDDD 75%, #DDDDDD 100%)',
+ );
});
it('should not linear-gradient more than 4 colors', () => {
- const gradient = DropdownUtils.duplicateLabelColor(['#FFFFFF', '#000000', '#333333', '#DDDDDD', '#EEEEEE']);
- expect(gradient.indexOf('#EEEEEE') === -1).toEqual(true);
+ const gradient = DropdownUtils.duplicateLabelColor([
+ '#FFFFFF',
+ '#000000',
+ '#333333',
+ '#DDDDDD',
+ '#EEEEEE',
+ ]);
+
+ expect(gradient.indexOf('#EEEEEE')).toBe(-1);
});
});
describe('duplicateLabelPreprocessing', () => {
it('should set preprocessed to true', () => {
const results = DropdownUtils.duplicateLabelPreprocessing([]);
+
expect(results.preprocessed).toEqual(true);
});
it('should not mutate existing data if there are no duplicates', () => {
- const data = [{
- title: 'label1',
- color: '#FFFFFF',
- }, {
- title: 'label2',
- color: '#000000',
- }];
+ const data = [
+ {
+ title: 'label1',
+ color: '#FFFFFF',
+ },
+ {
+ title: 'label2',
+ color: '#000000',
+ },
+ ];
const results = DropdownUtils.duplicateLabelPreprocessing(data);
expect(results.length).toEqual(2);
@@ -263,13 +311,16 @@ describe('Dropdown Utils', () => {
});
describe('duplicate labels', () => {
- const data = [{
- title: 'label',
- color: '#FFFFFF',
- }, {
- title: 'label',
- color: '#000000',
- }];
+ const data = [
+ {
+ title: 'label',
+ color: '#FFFFFF',
+ },
+ {
+ title: 'label',
+ color: '#000000',
+ },
+ ];
const results = DropdownUtils.duplicateLabelPreprocessing(data);
it('should merge duplicate labels', () => {
@@ -288,25 +339,28 @@ describe('Dropdown Utils', () => {
describe('setDataValueIfSelected', () => {
beforeEach(() => {
- spyOn(FilteredSearchDropdownManager, 'addWordToInput')
- .and.callFake(() => {});
+ spyOn(FilteredSearchDropdownManager, 'addWordToInput').and.callFake(() => {});
});
it('calls addWordToInput when dataValue exists', () => {
const selected = {
getAttribute: () => 'value',
+ hasAttribute: () => false,
};
DropdownUtils.setDataValueIfSelected(null, selected);
+
expect(FilteredSearchDropdownManager.addWordToInput.calls.count()).toEqual(1);
});
it('returns true when dataValue exists', () => {
const selected = {
getAttribute: () => 'value',
+ hasAttribute: () => false,
};
const result = DropdownUtils.setDataValueIfSelected(null, selected);
+
expect(result).toBe(true);
});
@@ -316,6 +370,7 @@ describe('Dropdown Utils', () => {
};
const result = DropdownUtils.setDataValueIfSelected(null, selected);
+
expect(result).toBe(false);
});
});
diff --git a/spec/javascripts/filtered_search/filtered_search_manager_spec.js b/spec/javascripts/filtered_search/filtered_search_manager_spec.js
index a03d5a31b41..e076120f5cc 100644
--- a/spec/javascripts/filtered_search/filtered_search_manager_spec.js
+++ b/spec/javascripts/filtered_search/filtered_search_manager_spec.js
@@ -9,7 +9,7 @@ import FilteredSearchDropdownManager from '~/filtered_search/filtered_search_dro
import FilteredSearchManager from '~/filtered_search/filtered_search_manager';
import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
-describe('Filtered Search Manager', function () {
+describe('Filtered Search Manager', function() {
let input;
let manager;
let tokensContainer;
@@ -97,7 +97,9 @@ describe('Filtered Search Manager', function () {
});
it('should not instantiate Flash if an RecentSearchesServiceError is caught', () => {
- spyOn(RecentSearchesService.prototype, 'fetch').and.callFake(() => Promise.reject(new RecentSearchesServiceError()));
+ spyOn(RecentSearchesService.prototype, 'fetch').and.callFake(() =>
+ Promise.reject(new RecentSearchesServiceError()),
+ );
spyOn(window, 'Flash');
manager.setup();
@@ -134,6 +136,7 @@ describe('Filtered Search Manager', function () {
};
manager.searchState(e);
+
expect(FilteredSearchManager.prototype.search).not.toHaveBeenCalled();
});
@@ -149,6 +152,7 @@ describe('Filtered Search Manager', function () {
};
manager.searchState(e);
+
expect(FilteredSearchManager.prototype.search).toHaveBeenCalledWith('opened');
});
});
@@ -160,10 +164,10 @@ describe('Filtered Search Manager', function () {
initializeManager();
});
- it('should search with a single word', (done) => {
+ it('should search with a single word', done => {
input.value = 'searchTerm';
- spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake((url) => {
+ spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake(url => {
expect(url).toEqual(`${defaultParams}&search=searchTerm`);
done();
});
@@ -171,10 +175,10 @@ describe('Filtered Search Manager', function () {
manager.search();
});
- it('should search with multiple words', (done) => {
+ it('should search with multiple words', done => {
input.value = 'awesome search terms';
- spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake((url) => {
+ spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake(url => {
expect(url).toEqual(`${defaultParams}&search=awesome+search+terms`);
done();
});
@@ -182,24 +186,26 @@ describe('Filtered Search Manager', function () {
manager.search();
});
- it('should search with special characters', (done) => {
+ it('should search with special characters', done => {
input.value = '~!@#$%^&*()_+{}:<>,.?/';
- spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake((url) => {
- expect(url).toEqual(`${defaultParams}&search=~!%40%23%24%25%5E%26*()_%2B%7B%7D%3A%3C%3E%2C.%3F%2F`);
+ spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake(url => {
+ expect(url).toEqual(
+ `${defaultParams}&search=~!%40%23%24%25%5E%26*()_%2B%7B%7D%3A%3C%3E%2C.%3F%2F`,
+ );
done();
});
manager.search();
});
- it('removes duplicated tokens', (done) => {
+ it('removes duplicated tokens', done => {
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '~bug')}
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('label', '~bug')}
`);
- spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake((url) => {
+ spyOnDependency(FilteredSearchManager, 'visitUrl').and.callFake(url => {
expect(url).toEqual(`${defaultParams}&label_name[]=bug`);
done();
});
@@ -304,6 +310,7 @@ describe('Filtered Search Manager', function () {
);
tokensContainer.querySelector('.js-visual-token .remove-token').click();
+
expect(tokensContainer.querySelector('.js-visual-token')).toEqual(null);
});
@@ -437,12 +444,18 @@ describe('Filtered Search Manager', function () {
it('toggles on focus', () => {
input.focus();
- expect(document.querySelector('.filtered-search-box').classList.contains('focus')).toEqual(true);
+
+ expect(document.querySelector('.filtered-search-box').classList.contains('focus')).toEqual(
+ true,
+ );
});
it('toggles on blur', () => {
input.blur();
- expect(document.querySelector('.filtered-search-box').classList.contains('focus')).toEqual(false);
+
+ expect(document.querySelector('.filtered-search-box').classList.contains('focus')).toEqual(
+ false,
+ );
});
});
@@ -454,9 +467,12 @@ describe('Filtered Search Manager', function () {
});
it('correctly modifies params when custom modifier is passed', () => {
- const modifedParams = manager.getAllParams.call({
- modifyUrlParams: paramsArr => paramsArr.reverse(),
- }, [].concat(this.paramsArr));
+ const modifedParams = manager.getAllParams.call(
+ {
+ modifyUrlParams: paramsArr => paramsArr.reverse(),
+ },
+ [].concat(this.paramsArr),
+ );
expect(modifedParams[0]).toBe(this.paramsArr[1]);
});
diff --git a/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js b/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js
index ab0ab72720e..d1fea18dea8 100644
--- a/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js
+++ b/spec/javascripts/filtered_search/filtered_search_token_keys_spec.js
@@ -1,25 +1,28 @@
import FilteredSearchTokenKeys from '~/filtered_search/filtered_search_token_keys';
describe('Filtered Search Token Keys', () => {
- const tokenKeys = [{
- key: 'author',
- type: 'string',
- param: 'username',
- symbol: '@',
- icon: 'pencil',
- tag: '@author',
- }];
-
- const conditions = [{
- url: 'assignee_id=0',
- tokenKey: 'assignee',
- value: 'none',
- }];
+ const tokenKeys = [
+ {
+ key: 'author',
+ type: 'string',
+ param: 'username',
+ symbol: '@',
+ icon: 'pencil',
+ tag: '@author',
+ },
+ ];
+
+ const conditions = [
+ {
+ url: 'assignee_id=0',
+ tokenKey: 'assignee',
+ value: 'none',
+ },
+ ];
describe('get', () => {
-
it('should return tokenKeys', () => {
- expect(new FilteredSearchTokenKeys().get() !== null).toBe(true);
+ expect(new FilteredSearchTokenKeys().get()).not.toBeNull();
});
it('should return tokenKeys as an array', () => {
@@ -40,7 +43,7 @@ describe('Filtered Search Token Keys', () => {
describe('getConditions', () => {
it('should return conditions', () => {
- expect(new FilteredSearchTokenKeys().getConditions() !== null).toBe(true);
+ expect(new FilteredSearchTokenKeys().getConditions()).not.toBeNull();
});
it('should return conditions as an array', () => {
@@ -51,11 +54,13 @@ describe('Filtered Search Token Keys', () => {
describe('searchByKey', () => {
it('should return null when key not found', () => {
const tokenKey = new FilteredSearchTokenKeys(tokenKeys).searchByKey('notakey');
- expect(tokenKey === null).toBe(true);
+
+ expect(tokenKey).toBeNull();
});
it('should return tokenKey when found by key', () => {
const result = new FilteredSearchTokenKeys(tokenKeys).searchByKey(tokenKeys[0].key);
+
expect(result).toEqual(tokenKeys[0]);
});
});
@@ -63,11 +68,13 @@ describe('Filtered Search Token Keys', () => {
describe('searchBySymbol', () => {
it('should return null when symbol not found', () => {
const tokenKey = new FilteredSearchTokenKeys(tokenKeys).searchBySymbol('notasymbol');
- expect(tokenKey === null).toBe(true);
+
+ expect(tokenKey).toBeNull();
});
it('should return tokenKey when found by symbol', () => {
const result = new FilteredSearchTokenKeys(tokenKeys).searchBySymbol(tokenKeys[0].symbol);
+
expect(result).toEqual(tokenKeys[0]);
});
});
@@ -75,16 +82,23 @@ describe('Filtered Search Token Keys', () => {
describe('searchByKeyParam', () => {
it('should return null when key param not found', () => {
const tokenKey = new FilteredSearchTokenKeys(tokenKeys).searchByKeyParam('notakeyparam');
- expect(tokenKey === null).toBe(true);
+
+ expect(tokenKey).toBeNull();
});
it('should return tokenKey when found by key param', () => {
- const result = new FilteredSearchTokenKeys(tokenKeys).searchByKeyParam(`${tokenKeys[0].key}_${tokenKeys[0].param}`);
+ const result = new FilteredSearchTokenKeys(tokenKeys).searchByKeyParam(
+ `${tokenKeys[0].key}_${tokenKeys[0].param}`,
+ );
+
expect(result).toEqual(tokenKeys[0]);
});
it('should return alternative tokenKey when found by key param', () => {
- const result = new FilteredSearchTokenKeys(tokenKeys).searchByKeyParam(`${tokenKeys[0].key}_${tokenKeys[0].param}`);
+ const result = new FilteredSearchTokenKeys(tokenKeys).searchByKeyParam(
+ `${tokenKeys[0].key}_${tokenKeys[0].param}`,
+ );
+
expect(result).toEqual(tokenKeys[0]);
});
});
@@ -92,26 +106,35 @@ describe('Filtered Search Token Keys', () => {
describe('searchByConditionUrl', () => {
it('should return null when condition url not found', () => {
const condition = new FilteredSearchTokenKeys([], [], conditions).searchByConditionUrl(null);
- expect(condition === null).toBe(true);
+
+ expect(condition).toBeNull();
});
it('should return condition when found by url', () => {
- const result = new FilteredSearchTokenKeys([], [], conditions)
- .searchByConditionUrl(conditions[0].url);
+ const result = new FilteredSearchTokenKeys([], [], conditions).searchByConditionUrl(
+ conditions[0].url,
+ );
+
expect(result).toBe(conditions[0]);
});
});
describe('searchByConditionKeyValue', () => {
it('should return null when condition tokenKey and value not found', () => {
- const condition = new FilteredSearchTokenKeys([], [], conditions)
- .searchByConditionKeyValue(null, null);
- expect(condition === null).toBe(true);
+ const condition = new FilteredSearchTokenKeys([], [], conditions).searchByConditionKeyValue(
+ null,
+ null,
+ );
+
+ expect(condition).toBeNull();
});
it('should return condition when found by tokenKey and value', () => {
- const result = new FilteredSearchTokenKeys([], [], conditions)
- .searchByConditionKeyValue(conditions[0].tokenKey, conditions[0].value);
+ const result = new FilteredSearchTokenKeys([], [], conditions).searchByConditionKeyValue(
+ conditions[0].tokenKey,
+ conditions[0].value,
+ );
+
expect(result).toEqual(conditions[0]);
});
});
diff --git a/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js b/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js
index 4f9f546cbb5..dec03e5ab93 100644
--- a/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js
+++ b/spec/javascripts/filtered_search/filtered_search_tokenizer_spec.js
@@ -7,14 +7,18 @@ describe('Filtered Search Tokenizer', () => {
describe('processTokens', () => {
it('returns for input containing only search value', () => {
const results = FilteredSearchTokenizer.processTokens('searchTerm', allowedKeys);
+
expect(results.searchToken).toBe('searchTerm');
expect(results.tokens.length).toBe(0);
expect(results.lastToken).toBe(results.searchToken);
});
it('returns for input containing only tokens', () => {
- const results = FilteredSearchTokenizer
- .processTokens('author:@root label:~"Very Important" milestone:%v1.0 assignee:none', allowedKeys);
+ const results = FilteredSearchTokenizer.processTokens(
+ 'author:@root label:~"Very Important" milestone:%v1.0 assignee:none',
+ allowedKeys,
+ );
+
expect(results.searchToken).toBe('');
expect(results.tokens.length).toBe(4);
expect(results.tokens[3]).toBe(results.lastToken);
@@ -37,8 +41,11 @@ describe('Filtered Search Tokenizer', () => {
});
it('returns for input starting with search value and ending with tokens', () => {
- const results = FilteredSearchTokenizer
- .processTokens('searchTerm anotherSearchTerm milestone:none', allowedKeys);
+ const results = FilteredSearchTokenizer.processTokens(
+ 'searchTerm anotherSearchTerm milestone:none',
+ allowedKeys,
+ );
+
expect(results.searchToken).toBe('searchTerm anotherSearchTerm');
expect(results.tokens.length).toBe(1);
expect(results.tokens[0]).toBe(results.lastToken);
@@ -48,8 +55,10 @@ describe('Filtered Search Tokenizer', () => {
});
it('returns for input starting with tokens and ending with search value', () => {
- const results = FilteredSearchTokenizer
- .processTokens('assignee:@user searchTerm', allowedKeys);
+ const results = FilteredSearchTokenizer.processTokens(
+ 'assignee:@user searchTerm',
+ allowedKeys,
+ );
expect(results.searchToken).toBe('searchTerm');
expect(results.tokens.length).toBe(1);
@@ -60,8 +69,10 @@ describe('Filtered Search Tokenizer', () => {
});
it('returns for input containing search value wrapped between tokens', () => {
- const results = FilteredSearchTokenizer
- .processTokens('author:@root label:~"Won\'t fix" searchTerm anotherSearchTerm milestone:none', allowedKeys);
+ const results = FilteredSearchTokenizer.processTokens(
+ 'author:@root label:~"Won\'t fix" searchTerm anotherSearchTerm milestone:none',
+ allowedKeys,
+ );
expect(results.searchToken).toBe('searchTerm anotherSearchTerm');
expect(results.tokens.length).toBe(3);
@@ -81,8 +92,11 @@ describe('Filtered Search Tokenizer', () => {
});
it('returns for input containing search value in between tokens', () => {
- const results = FilteredSearchTokenizer
- .processTokens('author:@root searchTerm assignee:none anotherSearchTerm label:~Doing', allowedKeys);
+ const results = FilteredSearchTokenizer.processTokens(
+ 'author:@root searchTerm assignee:none anotherSearchTerm label:~Doing',
+ allowedKeys,
+ );
+
expect(results.searchToken).toBe('searchTerm anotherSearchTerm');
expect(results.tokens.length).toBe(3);
expect(results.tokens[2]).toBe(results.lastToken);
@@ -102,6 +116,7 @@ describe('Filtered Search Tokenizer', () => {
it('returns search value for invalid tokens', () => {
const results = FilteredSearchTokenizer.processTokens('fake:token', allowedKeys);
+
expect(results.lastToken).toBe('fake:token');
expect(results.searchToken).toBe('fake:token');
expect(results.tokens.length).toEqual(0);
@@ -109,6 +124,7 @@ describe('Filtered Search Tokenizer', () => {
it('returns search value and token for mix of valid and invalid tokens', () => {
const results = FilteredSearchTokenizer.processTokens('label:real fake:token', allowedKeys);
+
expect(results.tokens.length).toEqual(1);
expect(results.tokens[0].key).toBe('label');
expect(results.tokens[0].value).toBe('real');
@@ -119,12 +135,14 @@ describe('Filtered Search Tokenizer', () => {
it('returns search value for invalid symbols', () => {
const results = FilteredSearchTokenizer.processTokens('std::includes', allowedKeys);
+
expect(results.lastToken).toBe('std::includes');
expect(results.searchToken).toBe('std::includes');
});
it('removes duplicated values', () => {
const results = FilteredSearchTokenizer.processTokens('label:~foo label:~foo', allowedKeys);
+
expect(results.tokens.length).toBe(1);
expect(results.tokens[0].key).toBe('label');
expect(results.tokens[0].value).toBe('foo');
diff --git a/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js b/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js
index 756a654765b..4f561df7943 100644
--- a/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js
+++ b/spec/javascripts/filtered_search/filtered_search_visual_tokens_spec.js
@@ -9,7 +9,7 @@ import FilteredSearchSpecHelper from '../helpers/filtered_search_spec_helper';
describe('Filtered Search Visual Tokens', () => {
const subject = FilteredSearchVisualTokens;
- const findElements = (tokenElement) => {
+ const findElements = tokenElement => {
const tokenNameElement = tokenElement.querySelector('.name');
const tokenValueContainer = tokenElement.querySelector('.value-container');
const tokenValueElement = tokenValueContainer.querySelector('.value');
@@ -34,8 +34,7 @@ describe('Filtered Search Visual Tokens', () => {
describe('getLastVisualTokenBeforeInput', () => {
it('returns when there are no visual tokens', () => {
- const { lastVisualToken, isLastVisualTokenValid }
- = subject.getLastVisualTokenBeforeInput();
+ const { lastVisualToken, isLastVisualTokenValid } = subject.getLastVisualTokenBeforeInput();
expect(lastVisualToken).toEqual(null);
expect(isLastVisualTokenValid).toEqual(true);
@@ -47,8 +46,7 @@ describe('Filtered Search Visual Tokens', () => {
bugLabelToken.outerHTML,
);
- const { lastVisualToken, isLastVisualTokenValid }
- = subject.getLastVisualTokenBeforeInput();
+ const { lastVisualToken, isLastVisualTokenValid } = subject.getLastVisualTokenBeforeInput();
expect(lastVisualToken).toEqual(document.querySelector('.filtered-search-token'));
expect(isLastVisualTokenValid).toEqual(true);
@@ -59,8 +57,7 @@ describe('Filtered Search Visual Tokens', () => {
FilteredSearchSpecHelper.createNameFilterVisualTokenHTML('Author'),
);
- const { lastVisualToken, isLastVisualTokenValid }
- = subject.getLastVisualTokenBeforeInput();
+ const { lastVisualToken, isLastVisualTokenValid } = subject.getLastVisualTokenBeforeInput();
expect(lastVisualToken).toEqual(document.querySelector('.filtered-search-token'));
expect(isLastVisualTokenValid).toEqual(false);
@@ -73,8 +70,7 @@ describe('Filtered Search Visual Tokens', () => {
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('author', '@root')}
`);
- const { lastVisualToken, isLastVisualTokenValid }
- = subject.getLastVisualTokenBeforeInput();
+ const { lastVisualToken, isLastVisualTokenValid } = subject.getLastVisualTokenBeforeInput();
const items = document.querySelectorAll('.tokens-container .js-visual-token');
expect(lastVisualToken.isEqualNode(items[items.length - 1])).toEqual(true);
@@ -88,8 +84,7 @@ describe('Filtered Search Visual Tokens', () => {
${FilteredSearchSpecHelper.createNameFilterVisualTokenHTML('assignee')}
`);
- const { lastVisualToken, isLastVisualTokenValid }
- = subject.getLastVisualTokenBeforeInput();
+ const { lastVisualToken, isLastVisualTokenValid } = subject.getLastVisualTokenBeforeInput();
const items = document.querySelectorAll('.tokens-container .js-visual-token');
expect(lastVisualToken.isEqualNode(items[items.length - 1])).toEqual(true);
@@ -105,8 +100,7 @@ describe('Filtered Search Visual Tokens', () => {
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('author', '@root')}
`);
- const { lastVisualToken, isLastVisualTokenValid }
- = subject.getLastVisualTokenBeforeInput();
+ const { lastVisualToken, isLastVisualTokenValid } = subject.getLastVisualTokenBeforeInput();
expect(lastVisualToken).toEqual(document.querySelector('.filtered-search-token'));
expect(isLastVisualTokenValid).toEqual(true);
@@ -119,8 +113,7 @@ describe('Filtered Search Visual Tokens', () => {
${FilteredSearchSpecHelper.createFilterVisualTokenHTML('author', '@root')}
`);
- const { lastVisualToken, isLastVisualTokenValid }
- = subject.getLastVisualTokenBeforeInput();
+ const { lastVisualToken, isLastVisualTokenValid } = subject.getLastVisualTokenBeforeInput();
expect(lastVisualToken).toEqual(document.querySelector('.filtered-search-token'));
expect(isLastVisualTokenValid).toEqual(false);
@@ -131,6 +124,7 @@ describe('Filtered Search Visual Tokens', () => {
describe('getEndpointWithQueryParams', () => {
it('returns `endpoint` string as is when second param `endpointQueryParams` is undefined, null or empty string', () => {
const endpoint = 'foo/bar/labels.json';
+
expect(subject.getEndpointWithQueryParams(endpoint)).toBe(endpoint);
expect(subject.getEndpointWithQueryParams(endpoint, null)).toBe(endpoint);
expect(subject.getEndpointWithQueryParams(endpoint, '')).toBe(endpoint);
@@ -141,8 +135,13 @@ describe('Filtered Search Visual Tokens', () => {
const singleQueryParams = '{"foo":"true"}';
const multipleQueryParams = '{"foo":"true","bar":"true"}';
- expect(subject.getEndpointWithQueryParams(endpoint, singleQueryParams)).toBe(`${endpoint}?foo=true`);
- expect(subject.getEndpointWithQueryParams(endpoint, multipleQueryParams)).toBe(`${endpoint}?foo=true&bar=true`);
+ expect(subject.getEndpointWithQueryParams(endpoint, singleQueryParams)).toBe(
+ `${endpoint}?foo=true`,
+ );
+
+ expect(subject.getEndpointWithQueryParams(endpoint, multipleQueryParams)).toBe(
+ `${endpoint}?foo=true&bar=true`,
+ );
});
});
@@ -161,6 +160,7 @@ describe('Filtered Search Visual Tokens', () => {
`);
const selected = tokensContainer.querySelector('.js-visual-token .selected');
+
expect(selected.classList.contains('selected')).toEqual(true);
subject.unselectTokens();
@@ -240,13 +240,17 @@ describe('Filtered Search Visual Tokens', () => {
beforeEach(() => {
setFixtures(`
<div class="test-area">
- ${subject.createVisualTokenElementHTML()}
+ ${subject.createVisualTokenElementHTML('custom-token')}
</div>
`);
tokenElement = document.querySelector('.test-area').firstElementChild;
});
+ it('should add class name to token element', () => {
+ expect(document.querySelector('.test-area .custom-token')).toBeDefined();
+ });
+
it('contains name div', () => {
expect(tokenElement.querySelector('.name')).toEqual(jasmine.anything());
});
@@ -269,7 +273,9 @@ describe('Filtered Search Visual Tokens', () => {
describe('remove token', () => {
it('contains remove-token button', () => {
- expect(tokenElement.querySelector('.value-container .remove-token')).toEqual(jasmine.anything());
+ expect(tokenElement.querySelector('.value-container .remove-token')).toEqual(
+ jasmine.anything(),
+ );
});
it('contains fa-close icon', () => {
@@ -280,7 +286,7 @@ describe('Filtered Search Visual Tokens', () => {
describe('addVisualTokenElement', () => {
it('renders search visual tokens', () => {
- subject.addVisualTokenElement('search term', null, true);
+ subject.addVisualTokenElement('search term', null, { isSearchTerm: true });
const token = tokensContainer.querySelector('.js-visual-token');
expect(token.classList.contains('filtered-search-term')).toEqual(true);
@@ -307,7 +313,9 @@ describe('Filtered Search Visual Tokens', () => {
});
it('inserts visual token before input', () => {
- tokensContainer.appendChild(FilteredSearchSpecHelper.createFilterVisualToken('assignee', '@root'));
+ tokensContainer.appendChild(
+ FilteredSearchSpecHelper.createFilterVisualToken('assignee', '@root'),
+ );
subject.addVisualTokenElement('label', 'Frontend');
const tokens = tokensContainer.querySelectorAll('.js-visual-token');
@@ -546,7 +554,7 @@ describe('Filtered Search Visual Tokens', () => {
token = document.querySelector('.js-visual-token');
});
- it('tokenize\'s existing input', () => {
+ it("tokenize's existing input", () => {
input.value = 'some text';
spyOn(subject, 'tokenizeInput').and.callThrough();
@@ -619,7 +627,7 @@ describe('Filtered Search Visual Tokens', () => {
expect(subject.getLastVisualTokenBeforeInput).not.toHaveBeenCalled();
});
- it('tokenize\'s input', () => {
+ it("tokenize's input", () => {
tokensContainer.innerHTML = `
${FilteredSearchSpecHelper.createNameFilterVisualTokenHTML('label')}
${FilteredSearchSpecHelper.createInputHTML()}
@@ -671,13 +679,17 @@ describe('Filtered Search Visual Tokens', () => {
subject.moveInputToTheRight();
const token = tokensContainer.children[1];
+
expect(token.querySelector('.value').innerText).toEqual('~bug');
});
});
describe('renderVisualTokenValue', () => {
const keywordToken = FilteredSearchSpecHelper.createFilterVisualToken('search');
- const milestoneToken = FilteredSearchSpecHelper.createFilterVisualToken('milestone', 'upcoming');
+ const milestoneToken = FilteredSearchSpecHelper.createFilterVisualToken(
+ 'milestone',
+ 'upcoming',
+ );
let updateLabelTokenColorSpy;
let updateUserTokenAppearanceSpy;
@@ -698,8 +710,9 @@ describe('Filtered Search Visual Tokens', () => {
});
it('renders a author token value element', () => {
- const { tokenNameElement, tokenValueContainer, tokenValueElement } =
- findElements(authorToken);
+ const { tokenNameElement, tokenValueContainer, tokenValueElement } = findElements(
+ authorToken,
+ );
const tokenName = tokenNameElement.innerText;
const tokenValue = 'new value';
@@ -708,13 +721,15 @@ describe('Filtered Search Visual Tokens', () => {
expect(tokenValueElement.innerText).toBe(tokenValue);
expect(updateUserTokenAppearanceSpy.calls.count()).toBe(1);
const expectedArgs = [tokenValueContainer, tokenValueElement, tokenValue];
+
expect(updateUserTokenAppearanceSpy.calls.argsFor(0)).toEqual(expectedArgs);
expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
});
it('renders a label token value element', () => {
- const { tokenNameElement, tokenValueContainer, tokenValueElement } =
- findElements(bugLabelToken);
+ const { tokenNameElement, tokenValueContainer, tokenValueElement } = findElements(
+ bugLabelToken,
+ );
const tokenName = tokenNameElement.innerText;
const tokenValue = 'new value';
@@ -723,6 +738,7 @@ describe('Filtered Search Visual Tokens', () => {
expect(tokenValueElement.innerText).toBe(tokenValue);
expect(updateLabelTokenColorSpy.calls.count()).toBe(1);
const expectedArgs = [tokenValueContainer, tokenValue];
+
expect(updateLabelTokenColorSpy.calls.argsFor(0)).toEqual(expectedArgs);
expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
});
@@ -738,6 +754,50 @@ describe('Filtered Search Visual Tokens', () => {
expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
});
+
+ it('does not update user token appearance for `none` filter', () => {
+ const { tokenNameElement } = findElements(authorToken);
+
+ const tokenName = tokenNameElement.innerText;
+ const tokenValue = 'none';
+
+ subject.renderVisualTokenValue(authorToken, tokenName, tokenValue);
+
+ expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
+ });
+
+ it('does not update user token appearance for `any` filter', () => {
+ const { tokenNameElement } = findElements(authorToken);
+
+ const tokenName = tokenNameElement.innerText;
+ const tokenValue = 'any';
+
+ subject.renderVisualTokenValue(authorToken, tokenName, tokenValue);
+
+ expect(updateUserTokenAppearanceSpy.calls.count()).toBe(0);
+ });
+
+ it('does not update label token color for `none` filter', () => {
+ const { tokenNameElement } = findElements(bugLabelToken);
+
+ const tokenName = tokenNameElement.innerText;
+ const tokenValue = 'none';
+
+ subject.renderVisualTokenValue(bugLabelToken, tokenName, tokenValue);
+
+ expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
+ });
+
+ it('does not update label token color for `any` filter', () => {
+ const { tokenNameElement } = findElements(bugLabelToken);
+
+ const tokenName = tokenNameElement.innerText;
+ const tokenValue = 'any';
+
+ subject.renderVisualTokenValue(bugLabelToken, tokenName, tokenValue);
+
+ expect(updateLabelTokenColorSpy.calls.count()).toBe(0);
+ });
});
describe('updateUserTokenAppearance', () => {
@@ -747,96 +807,90 @@ describe('Filtered Search Visual Tokens', () => {
spyOn(UsersCache, 'retrieve').and.callFake(username => usersCacheSpy(username));
});
- it('ignores special value "none"', (done) => {
- usersCacheSpy = (username) => {
- expect(username).toBe('none');
- done.fail('Should not resolve "none"!');
- };
- const { tokenValueContainer, tokenValueElement } = findElements(authorToken);
-
- subject.updateUserTokenAppearance(tokenValueContainer, tokenValueElement, 'none')
- .then(done)
- .catch(done.fail);
- });
-
- it('ignores error if UsersCache throws', (done) => {
+ it('ignores error if UsersCache throws', done => {
spyOn(window, 'Flash');
const dummyError = new Error('Earth rotated backwards');
const { tokenValueContainer, tokenValueElement } = findElements(authorToken);
const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = (username) => {
+ usersCacheSpy = username => {
expect(`@${username}`).toBe(tokenValue);
return Promise.reject(dummyError);
};
- subject.updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
- .then(() => {
- expect(window.Flash.calls.count()).toBe(0);
- })
- .then(done)
- .catch(done.fail);
+ subject
+ .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
+ .then(() => {
+ expect(window.Flash.calls.count()).toBe(0);
+ })
+ .then(done)
+ .catch(done.fail);
});
- it('does nothing if user cannot be found', (done) => {
+ it('does nothing if user cannot be found', done => {
const { tokenValueContainer, tokenValueElement } = findElements(authorToken);
const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = (username) => {
+ usersCacheSpy = username => {
expect(`@${username}`).toBe(tokenValue);
return Promise.resolve(undefined);
};
- subject.updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
- .then(() => {
- expect(tokenValueElement.innerText).toBe(tokenValue);
- })
- .then(done)
- .catch(done.fail);
+ subject
+ .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
+ .then(() => {
+ expect(tokenValueElement.innerText).toBe(tokenValue);
+ })
+ .then(done)
+ .catch(done.fail);
});
- it('replaces author token with avatar and display name', (done) => {
+ it('replaces author token with avatar and display name', done => {
const dummyUser = {
name: 'Important Person',
avatar_url: 'https://host.invalid/mypics/avatar.png',
};
const { tokenValueContainer, tokenValueElement } = findElements(authorToken);
const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = (username) => {
+ usersCacheSpy = username => {
expect(`@${username}`).toBe(tokenValue);
return Promise.resolve(dummyUser);
};
- subject.updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
- .then(() => {
- expect(tokenValueContainer.dataset.originalValue).toBe(tokenValue);
- expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
- const avatar = tokenValueElement.querySelector('img.avatar');
- expect(avatar.src).toBe(dummyUser.avatar_url);
- expect(avatar.alt).toBe('');
- })
- .then(done)
- .catch(done.fail);
+ subject
+ .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
+ .then(() => {
+ expect(tokenValueContainer.dataset.originalValue).toBe(tokenValue);
+ expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
+ const avatar = tokenValueElement.querySelector('img.avatar');
+
+ expect(avatar.src).toBe(dummyUser.avatar_url);
+ expect(avatar.alt).toBe('');
+ })
+ .then(done)
+ .catch(done.fail);
});
- it('escapes user name when creating token', (done) => {
+ it('escapes user name when creating token', done => {
const dummyUser = {
name: '<script>',
avatar_url: `${gl.TEST_HOST}/mypics/avatar.png`,
};
const { tokenValueContainer, tokenValueElement } = findElements(authorToken);
const tokenValue = tokenValueElement.innerText;
- usersCacheSpy = (username) => {
+ usersCacheSpy = username => {
expect(`@${username}`).toBe(tokenValue);
return Promise.resolve(dummyUser);
};
- subject.updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
- .then(() => {
- expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
- tokenValueElement.querySelector('.avatar').remove();
- expect(tokenValueElement.innerHTML.trim()).toBe(_.escape(dummyUser.name));
- })
- .then(done)
- .catch(done.fail);
+ subject
+ .updateUserTokenAppearance(tokenValueContainer, tokenValueElement, tokenValue)
+ .then(() => {
+ expect(tokenValueElement.innerText.trim()).toBe(dummyUser.name);
+ tokenValueElement.querySelector('.avatar').remove();
+
+ expect(tokenValueElement.innerHTML.trim()).toBe(_.escape(dummyUser.name));
+ })
+ .then(done)
+ .catch(done.fail);
});
});
@@ -850,23 +904,31 @@ describe('Filtered Search Visual Tokens', () => {
it('should set backgroundColor', () => {
const originalBackgroundColor = bugLabelToken.style.backgroundColor;
const token = subject.setTokenStyle(bugLabelToken, 'blue', 'white');
+
expect(token.style.backgroundColor).toEqual('blue');
expect(token.style.backgroundColor).not.toEqual(originalBackgroundColor);
});
it('should not set backgroundColor when it is a linear-gradient', () => {
- const token = subject.setTokenStyle(bugLabelToken, 'linear-gradient(135deg, red, blue)', 'white');
+ const token = subject.setTokenStyle(
+ bugLabelToken,
+ 'linear-gradient(135deg, red, blue)',
+ 'white',
+ );
+
expect(token.style.backgroundColor).toEqual(bugLabelToken.style.backgroundColor);
});
it('should set textColor', () => {
const token = subject.setTokenStyle(bugLabelToken, 'white', 'black');
+
expect(token.style.color).toEqual('black');
expect(token.style.color).not.toEqual(originalTextColor);
});
it('should add inverted class when textColor is #FFFFFF', () => {
const token = subject.setTokenStyle(bugLabelToken, 'black', '#FFFFFF');
+
expect(token.style.color).toEqual('rgb(255, 255, 255)');
expect(token.style.color).not.toEqual(originalTextColor);
expect(token.querySelector('.remove-token').classList.contains('inverted')).toEqual(true);
@@ -890,14 +952,17 @@ describe('Filtered Search Visual Tokens', () => {
describe('not preprocessed before', () => {
it('returns preprocessed labels', () => {
let labels = [];
+
expect(labels.preprocessed).not.toEqual(true);
labels = FilteredSearchVisualTokens.preprocessLabel(endpoint, labels);
+
expect(labels.preprocessed).toEqual(true);
});
it('overrides AjaxCache with preprocessed results', () => {
spyOn(AjaxCache, 'override').and.callFake(() => {});
FilteredSearchVisualTokens.preprocessLabel(endpoint, []);
+
expect(AjaxCache.override.calls.count()).toEqual(1);
});
});
@@ -915,8 +980,14 @@ describe('Filtered Search Visual Tokens', () => {
labelData = getJSONFixture(jsonFixtureName);
});
- const missingLabelToken = FilteredSearchSpecHelper.createFilterVisualToken('label', '~doesnotexist');
- const spaceLabelToken = FilteredSearchSpecHelper.createFilterVisualToken('label', '~"some space"');
+ const missingLabelToken = FilteredSearchSpecHelper.createFilterVisualToken(
+ 'label',
+ '~doesnotexist',
+ );
+ const spaceLabelToken = FilteredSearchSpecHelper.createFilterVisualToken(
+ 'label',
+ '~"some space"',
+ );
beforeEach(() => {
tokensContainer.innerHTML = FilteredSearchSpecHelper.createTokensContainerHTML(`
@@ -928,11 +999,11 @@ describe('Filtered Search Visual Tokens', () => {
const filteredSearchInput = document.querySelector('.filtered-search');
filteredSearchInput.dataset.baseEndpoint = dummyEndpoint;
- AjaxCache.internalStorage = { };
+ AjaxCache.internalStorage = {};
AjaxCache.internalStorage[`${dummyEndpoint}/labels.json`] = labelData;
});
- const parseColor = (color) => {
+ const parseColor = color => {
const dummyElement = document.createElement('div');
dummyElement.style.color = color;
return dummyElement.style.color;
@@ -944,16 +1015,16 @@ describe('Filtered Search Visual Tokens', () => {
expect(tokenValueContainer.style.color).toBe(parseColor(label.text_color));
};
- const findLabel = tokenValue => labelData.find(
- label => tokenValue === `~${DropdownUtils.getEscapedText(label.title)}`,
- );
+ const findLabel = tokenValue =>
+ labelData.find(label => tokenValue === `~${DropdownUtils.getEscapedText(label.title)}`);
- it('updates the color of a label token', (done) => {
+ it('updates the color of a label token', done => {
const { tokenValueContainer, tokenValueElement } = findElements(bugLabelToken);
const tokenValue = tokenValueElement.innerText;
const matchingLabel = findLabel(tokenValue);
- subject.updateLabelTokenColor(tokenValueContainer, tokenValue)
+ subject
+ .updateLabelTokenColor(tokenValueContainer, tokenValue)
.then(() => {
expectValueContainerStyle(tokenValueContainer, matchingLabel);
})
@@ -961,12 +1032,13 @@ describe('Filtered Search Visual Tokens', () => {
.catch(done.fail);
});
- it('updates the color of a label token with spaces', (done) => {
+ it('updates the color of a label token with spaces', done => {
const { tokenValueContainer, tokenValueElement } = findElements(spaceLabelToken);
const tokenValue = tokenValueElement.innerText;
const matchingLabel = findLabel(tokenValue);
- subject.updateLabelTokenColor(tokenValueContainer, tokenValue)
+ subject
+ .updateLabelTokenColor(tokenValueContainer, tokenValue)
.then(() => {
expectValueContainerStyle(tokenValueContainer, matchingLabel);
})
@@ -974,13 +1046,15 @@ describe('Filtered Search Visual Tokens', () => {
.catch(done.fail);
});
- it('does not change color of a missing label', (done) => {
+ it('does not change color of a missing label', done => {
const { tokenValueContainer, tokenValueElement } = findElements(missingLabelToken);
const tokenValue = tokenValueElement.innerText;
const matchingLabel = findLabel(tokenValue);
+
expect(matchingLabel).toBe(undefined);
- subject.updateLabelTokenColor(tokenValueContainer, tokenValue)
+ subject
+ .updateLabelTokenColor(tokenValueContainer, tokenValue)
.then(() => {
expect(tokenValueContainer.getAttribute('style')).toBe(null);
})
diff --git a/spec/javascripts/filtered_search/recent_searches_root_spec.js b/spec/javascripts/filtered_search/recent_searches_root_spec.js
index d063fcf4f2d..70dd4e9570d 100644
--- a/spec/javascripts/filtered_search/recent_searches_root_spec.js
+++ b/spec/javascripts/filtered_search/recent_searches_root_spec.js
@@ -14,7 +14,7 @@ describe('RecentSearchesRoot', () => {
},
};
- VueSpy = spyOnDependency(RecentSearchesRoot, 'Vue').and.callFake((options) => {
+ VueSpy = spyOnDependency(RecentSearchesRoot, 'Vue').and.callFake(options => {
({ data, template } = options);
});
diff --git a/spec/javascripts/filtered_search/services/recent_searches_service_spec.js b/spec/javascripts/filtered_search/services/recent_searches_service_spec.js
index c293c0afa97..188f83eca16 100644
--- a/spec/javascripts/filtered_search/services/recent_searches_service_spec.js
+++ b/spec/javascripts/filtered_search/services/recent_searches_service_spec.js
@@ -15,48 +15,49 @@ describe('RecentSearchesService', () => {
spyOn(RecentSearchesService, 'isAvailable').and.returnValue(true);
});
- it('should default to empty array', (done) => {
+ it('should default to empty array', done => {
const fetchItemsPromise = service.fetch();
fetchItemsPromise
- .then((items) => {
+ .then(items => {
expect(items).toEqual([]);
})
.then(done)
.catch(done.fail);
});
- it('should reject when unable to parse', (done) => {
+ it('should reject when unable to parse', done => {
window.localStorage.setItem(service.localStorageKey, 'fail');
const fetchItemsPromise = service.fetch();
fetchItemsPromise
.then(done.fail)
- .catch((error) => {
+ .catch(error => {
expect(error).toEqual(jasmine.any(SyntaxError));
})
.then(done)
.catch(done.fail);
});
- it('should reject when service is unavailable', (done) => {
+ it('should reject when service is unavailable', done => {
RecentSearchesService.isAvailable.and.returnValue(false);
- service.fetch()
+ service
+ .fetch()
.then(done.fail)
- .catch((error) => {
+ .catch(error => {
expect(error).toEqual(jasmine.any(Error));
})
.then(done)
.catch(done.fail);
});
- it('should return items from localStorage', (done) => {
+ it('should return items from localStorage', done => {
window.localStorage.setItem(service.localStorageKey, '["foo", "bar"]');
const fetchItemsPromise = service.fetch();
fetchItemsPromise
- .then((items) => {
+ .then(items => {
expect(items).toEqual(['foo', 'bar']);
})
.then(done)
@@ -70,10 +71,11 @@ describe('RecentSearchesService', () => {
spyOn(window.localStorage, 'getItem');
});
- it('should not call .getItem', (done) => {
- RecentSearchesService.prototype.fetch()
+ it('should not call .getItem', done => {
+ RecentSearchesService.prototype
+ .fetch()
.then(done.fail)
- .catch((err) => {
+ .catch(err => {
expect(err).toEqual(new RecentSearchesServiceError());
expect(window.localStorage.getItem).not.toHaveBeenCalled();
})
@@ -92,6 +94,7 @@ describe('RecentSearchesService', () => {
const items = ['foo', 'bar'];
service.save(items);
const newLocalStorageValue = window.localStorage.getItem(service.localStorageKey);
+
expect(JSON.parse(newLocalStorageValue)).toEqual(items);
});
});
diff --git a/spec/javascripts/filtered_search/stores/recent_searches_store_spec.js b/spec/javascripts/filtered_search/stores/recent_searches_store_spec.js
index 1eebc6f2367..56bb82ae941 100644
--- a/spec/javascripts/filtered_search/stores/recent_searches_store_spec.js
+++ b/spec/javascripts/filtered_search/stores/recent_searches_store_spec.js
@@ -38,14 +38,8 @@ describe('RecentSearchesStore', () => {
describe('setRecentSearches', () => {
it('should override list', () => {
- store.setRecentSearches([
- 'foo',
- 'bar',
- ]);
- store.setRecentSearches([
- 'baz',
- 'qux',
- ]);
+ store.setRecentSearches(['foo', 'bar']);
+ store.setRecentSearches(['baz', 'qux']);
expect(store.state.recentSearches).toEqual(['baz', 'qux']);
});
diff --git a/spec/javascripts/fixtures/groups.rb b/spec/javascripts/fixtures/groups.rb
index a2035ceae15..b42f442557c 100644
--- a/spec/javascripts/fixtures/groups.rb
+++ b/spec/javascripts/fixtures/groups.rb
@@ -17,6 +17,16 @@ describe 'Groups (JavaScript fixtures)', type: :controller do
sign_in(admin)
end
+ describe GroupsController, '(JavaScript fixtures)', type: :controller do
+ it 'groups/edit.html.raw' do |example|
+ get :edit,
+ id: group
+
+ expect(response).to be_success
+ store_frontend_fixture(response, example.description)
+ end
+ end
+
describe Groups::Settings::CiCdController, '(JavaScript fixtures)', type: :controller do
it 'groups/ci_cd_settings.html.raw' do |example|
get :show,
diff --git a/spec/javascripts/fixtures/jobs.rb b/spec/javascripts/fixtures/jobs.rb
index 6d5c6d5334f..82d7a5e394e 100644
--- a/spec/javascripts/fixtures/jobs.rb
+++ b/spec/javascripts/fixtures/jobs.rb
@@ -5,16 +5,24 @@ describe Projects::JobsController, '(JavaScript fixtures)', type: :controller do
let(:admin) { create(:admin) }
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
- let(:project) { create(:project_empty_repo, namespace: namespace, path: 'builds-project') }
- let(:pipeline) { create(:ci_empty_pipeline, project: project) }
+ let(:project) { create(:project, :repository, namespace: namespace, path: 'builds-project') }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project, sha: project.commit.id) }
let!(:build_with_artifacts) { create(:ci_build, :success, :artifacts, :trace_artifact, pipeline: pipeline, stage: 'test', artifacts_expire_at: Time.now + 18.months) }
let!(:failed_build) { create(:ci_build, :failed, pipeline: pipeline, stage: 'build') }
let!(:pending_build) { create(:ci_build, :pending, pipeline: pipeline, stage: 'deploy') }
+ let!(:delayed_job) do
+ create(:ci_build, :scheduled,
+ pipeline: pipeline,
+ name: 'delayed job',
+ stage: 'test',
+ commands: 'test')
+ end
render_views
before(:all) do
clean_frontend_fixtures('builds/')
+ clean_frontend_fixtures('jobs/')
end
before do
@@ -34,4 +42,15 @@ describe Projects::JobsController, '(JavaScript fixtures)', type: :controller do
expect(response).to be_success
store_frontend_fixture(response, example.description)
end
+
+ it 'jobs/delayed.json' do |example|
+ get :show,
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ id: delayed_job.to_param,
+ format: :json
+
+ expect(response).to be_success
+ store_frontend_fixture(response, example.description)
+ end
end
diff --git a/spec/javascripts/fixtures/merge_requests_diffs.rb b/spec/javascripts/fixtures/merge_requests_diffs.rb
index ddce00bc0fe..afe34b834b0 100644
--- a/spec/javascripts/fixtures/merge_requests_diffs.rb
+++ b/spec/javascripts/fixtures/merge_requests_diffs.rb
@@ -9,6 +9,7 @@ describe Projects::MergeRequests::DiffsController, '(JavaScript fixtures)', type
let(:project) { create(:project, :repository, namespace: namespace, path: 'merge-requests-project') }
let(:merge_request) { create(:merge_request, :with_diffs, source_project: project, target_project: project, description: '- [ ] Task List Item') }
let(:path) { "files/ruby/popen.rb" }
+ let(:selected_commit) { merge_request.all_commits[0] }
let(:position) do
Gitlab::Diff::Position.new(
old_path: path,
@@ -33,6 +34,14 @@ describe Projects::MergeRequests::DiffsController, '(JavaScript fixtures)', type
remove_repository(project)
end
+ it 'merge_request_diffs/with_commit.json' do |example|
+ # Create a user that matches the selected commit author
+ # This is so that the "author" information will be populated
+ create(:user, email: selected_commit.author_email, name: selected_commit.author_name)
+
+ render_merge_request(example.description, merge_request, commit_id: selected_commit.sha)
+ end
+
it 'merge_request_diffs/inline_changes_tab_with_comments.json' do |example|
create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request)
create(:note_on_merge_request, author: admin, project: project, noteable: merge_request)
@@ -47,13 +56,14 @@ describe Projects::MergeRequests::DiffsController, '(JavaScript fixtures)', type
private
- def render_merge_request(fixture_file_name, merge_request, view: 'inline')
+ def render_merge_request(fixture_file_name, merge_request, view: 'inline', **extra_params)
get :show,
namespace_id: project.namespace.to_param,
project_id: project,
id: merge_request.to_param,
format: :json,
- view: view
+ view: view,
+ **extra_params
expect(response).to be_success
store_frontend_fixture(response, fixture_file_name)
diff --git a/spec/javascripts/flash_spec.js b/spec/javascripts/flash_spec.js
index 0a8e5a628c0..aecab331ead 100644
--- a/spec/javascripts/flash_spec.js
+++ b/spec/javascripts/flash_spec.js
@@ -1,9 +1,4 @@
-import flash, {
- createFlashEl,
- createAction,
- hideFlash,
- removeFlashClickListener,
-} from '~/flash';
+import flash, { createFlashEl, createAction, hideFlash, removeFlashClickListener } from '~/flash';
describe('Flash', () => {
describe('createFlashEl', () => {
@@ -20,28 +15,23 @@ describe('Flash', () => {
it('creates flash element with type', () => {
el.innerHTML = createFlashEl('testing', 'alert');
- expect(
- el.querySelector('.flash-alert'),
- ).not.toBeNull();
+ expect(el.querySelector('.flash-alert')).not.toBeNull();
});
it('escapes text', () => {
el.innerHTML = createFlashEl('<script>alert("a");</script>', 'alert');
- expect(
- el.querySelector('.flash-text').textContent.trim(),
- ).toBe('<script>alert("a");</script>');
+ expect(el.querySelector('.flash-text').textContent.trim()).toBe(
+ '<script>alert("a");</script>',
+ );
});
it('adds container classes when inside content wrapper', () => {
el.innerHTML = createFlashEl('testing', 'alert', true);
- expect(
- el.querySelector('.flash-text').classList.contains('container-fluid'),
- ).toBeTruthy();
- expect(
- el.querySelector('.flash-text').classList.contains('container-limited'),
- ).toBeTruthy();
+ expect(el.querySelector('.flash-text').classList.contains('container-fluid')).toBeTruthy();
+
+ expect(el.querySelector('.flash-text').classList.contains('container-limited')).toBeTruthy();
});
});
@@ -56,31 +46,23 @@ describe('Flash', () => {
it('sets transition style', () => {
hideFlash(el);
- expect(
- el.style['transition-property'],
- ).toBe('opacity');
- expect(
- el.style['transition-duration'],
- ).toBe('0.3s');
+ expect(el.style['transition-property']).toBe('opacity');
+
+ expect(el.style['transition-duration']).toBe('0.3s');
});
it('sets opacity style', () => {
hideFlash(el);
- expect(
- el.style.opacity,
- ).toBe('0');
+ expect(el.style.opacity).toBe('0');
});
it('does not set styles when fadeTransition is false', () => {
hideFlash(el, false);
- expect(
- el.style.opacity,
- ).toBe('');
- expect(
- el.style.transition,
- ).toBe('');
+ expect(el.style.opacity).toBe('');
+
+ expect(el.style.transition).toBe('');
});
it('removes element after transitionend', () => {
@@ -89,9 +71,7 @@ describe('Flash', () => {
hideFlash(el);
el.dispatchEvent(new Event('transitionend'));
- expect(
- document.querySelector('.js-testing'),
- ).toBeNull();
+ expect(document.querySelector('.js-testing')).toBeNull();
});
it('calls event listener callback once', () => {
@@ -103,9 +83,7 @@ describe('Flash', () => {
el.dispatchEvent(new Event('transitionend'));
el.dispatchEvent(new Event('transitionend'));
- expect(
- el.remove.calls.count(),
- ).toBe(1);
+ expect(el.remove.calls.count()).toBe(1);
});
});
@@ -122,9 +100,7 @@ describe('Flash', () => {
title: 'test',
});
- expect(
- el.querySelector('.flash-action').href,
- ).toContain('testing');
+ expect(el.querySelector('.flash-action').href).toContain('testing');
});
it('uses hash as href when no href is present', () => {
@@ -132,9 +108,7 @@ describe('Flash', () => {
title: 'test',
});
- expect(
- el.querySelector('.flash-action').href,
- ).toContain('#');
+ expect(el.querySelector('.flash-action').href).toContain('#');
});
it('adds role when no href is present', () => {
@@ -142,9 +116,7 @@ describe('Flash', () => {
title: 'test',
});
- expect(
- el.querySelector('.flash-action').getAttribute('role'),
- ).toBe('button');
+ expect(el.querySelector('.flash-action').getAttribute('role')).toBe('button');
});
it('escapes the title text', () => {
@@ -152,9 +124,9 @@ describe('Flash', () => {
title: '<script>alert("a")</script>',
});
- expect(
- el.querySelector('.flash-action').textContent.trim(),
- ).toBe('<script>alert("a")</script>');
+ expect(el.querySelector('.flash-action').textContent.trim()).toBe(
+ '<script>alert("a")</script>',
+ );
});
});
@@ -163,12 +135,9 @@ describe('Flash', () => {
it('does not add to the DOM', () => {
const flashEl = flash('testing');
- expect(
- flashEl,
- ).toBeNull();
- expect(
- document.querySelector('.flash-alert'),
- ).toBeNull();
+ expect(flashEl).toBeNull();
+
+ expect(document.querySelector('.flash-alert')).toBeNull();
});
});
@@ -188,42 +157,30 @@ describe('Flash', () => {
it('adds flash element into container', () => {
flash('test', 'alert', document, null, false, true);
- expect(
- document.querySelector('.flash-alert'),
- ).not.toBeNull();
+ expect(document.querySelector('.flash-alert')).not.toBeNull();
- expect(
- document.body.className,
- ).toContain('flash-shown');
+ expect(document.body.className).toContain('flash-shown');
});
it('adds flash into specified parent', () => {
- flash(
- 'test',
- 'alert',
- document.querySelector('.content-wrapper'),
- );
+ flash('test', 'alert', document.querySelector('.content-wrapper'));
- expect(
- document.querySelector('.content-wrapper .flash-alert'),
- ).not.toBeNull();
+ expect(document.querySelector('.content-wrapper .flash-alert')).not.toBeNull();
});
it('adds container classes when inside content-wrapper', () => {
flash('test');
- expect(
- document.querySelector('.flash-text').className,
- ).toBe('flash-text container-fluid container-limited');
+ expect(document.querySelector('.flash-text').className).toBe(
+ 'flash-text container-fluid container-limited limit-container-width',
+ );
});
it('does not add container when outside of content-wrapper', () => {
document.querySelector('.content-wrapper').className = 'js-content-wrapper';
flash('test');
- expect(
- document.querySelector('.flash-text').className.trim(),
- ).toBe('flash-text');
+ expect(document.querySelector('.flash-text').className.trim()).toContain('flash-text');
});
it('removes element after clicking', () => {
@@ -231,29 +188,18 @@ describe('Flash', () => {
document.querySelector('.flash-alert').click();
- expect(
- document.querySelector('.flash-alert'),
- ).toBeNull();
+ expect(document.querySelector('.flash-alert')).toBeNull();
- expect(
- document.body.className,
- ).not.toContain('flash-shown');
+ expect(document.body.className).not.toContain('flash-shown');
});
describe('with actionConfig', () => {
it('adds action link', () => {
- flash(
- 'test',
- 'alert',
- document,
- {
- title: 'test',
- },
- );
-
- expect(
- document.querySelector('.flash-action'),
- ).not.toBeNull();
+ flash('test', 'alert', document, {
+ title: 'test',
+ });
+
+ expect(document.querySelector('.flash-action')).not.toBeNull();
});
it('calls actionConfig clickHandler on click', () => {
@@ -262,18 +208,11 @@ describe('Flash', () => {
clickHandler: jasmine.createSpy('actionConfig'),
};
- flash(
- 'test',
- 'alert',
- document,
- actionConfig,
- );
+ flash('test', 'alert', document, actionConfig);
document.querySelector('.flash-action').click();
- expect(
- actionConfig.clickHandler,
- ).toHaveBeenCalled();
+ expect(actionConfig.clickHandler).toHaveBeenCalled();
});
});
});
@@ -284,7 +223,7 @@ describe('Flash', () => {
document.body.innerHTML += '<div class="flash-container"><div class="flash"></div></div>';
});
- it('removes global flash on click', (done) => {
+ it('removes global flash on click', done => {
const flashEl = document.querySelector('.flash');
removeFlashClickListener(flashEl, false);
diff --git a/spec/javascripts/fly_out_nav_spec.js b/spec/javascripts/fly_out_nav_spec.js
index eb9330f5e5b..7ef44f29c5b 100644
--- a/spec/javascripts/fly_out_nav_spec.js
+++ b/spec/javascripts/fly_out_nav_spec.js
@@ -45,9 +45,7 @@ describe('Fly out sidebar navigation', () => {
height: 100,
};
- expect(
- calculateTop(boundingRect, 100),
- ).toBe(100);
+ expect(calculateTop(boundingRect, 100)).toBe(100);
});
it('returns boundingRect - bottomOverflow', () => {
@@ -56,27 +54,22 @@ describe('Fly out sidebar navigation', () => {
height: 100,
};
- expect(
- calculateTop(boundingRect, 100),
- ).toBe(window.innerHeight - 50);
+ expect(calculateTop(boundingRect, 100)).toBe(window.innerHeight - 50);
});
});
describe('getHideSubItemsInterval', () => {
beforeEach(() => {
- el.innerHTML = '<div class="sidebar-sub-level-items" style="position: fixed; top: 0; left: 100px; height: 150px;"></div>';
+ el.innerHTML =
+ '<div class="sidebar-sub-level-items" style="position: fixed; top: 0; left: 100px; height: 150px;"></div>';
});
it('returns 0 if currentOpenMenu is nil', () => {
- expect(
- getHideSubItemsInterval(),
- ).toBe(0);
+ expect(getHideSubItemsInterval()).toBe(0);
});
it('returns 0 if mousePos is empty', () => {
- expect(
- getHideSubItemsInterval(),
- ).toBe(0);
+ expect(getHideSubItemsInterval()).toBe(0);
});
it('returns 0 when mouse above sub-items', () => {
@@ -90,9 +83,7 @@ describe('Fly out sidebar navigation', () => {
clientY: el.getBoundingClientRect().top - 50,
});
- expect(
- getHideSubItemsInterval(),
- ).toBe(0);
+ expect(getHideSubItemsInterval()).toBe(0);
});
it('returns 0 when mouse is below sub-items', () => {
@@ -105,12 +96,10 @@ describe('Fly out sidebar navigation', () => {
});
documentMouseMove({
clientX: el.getBoundingClientRect().left,
- clientY: (el.getBoundingClientRect().top - subItems.getBoundingClientRect().height) + 50,
+ clientY: el.getBoundingClientRect().top - subItems.getBoundingClientRect().height + 50,
});
- expect(
- getHideSubItemsInterval(),
- ).toBe(0);
+ expect(getHideSubItemsInterval()).toBe(0);
});
it('returns 300 when mouse is moved towards sub-items', () => {
@@ -124,9 +113,7 @@ describe('Fly out sidebar navigation', () => {
clientY: el.getBoundingClientRect().top + 10,
});
- expect(
- getHideSubItemsInterval(),
- ).toBe(300);
+ expect(getHideSubItemsInterval()).toBe(300);
});
});
@@ -138,9 +125,7 @@ describe('Fly out sidebar navigation', () => {
it('removes is-over class if currentOpenMenu is null', () => {
mouseLeaveTopItem(el);
- expect(
- el.classList.remove,
- ).toHaveBeenCalledWith('is-over');
+ expect(el.classList.remove).toHaveBeenCalledWith('is-over');
});
it('removes is-over class if currentOpenMenu is null & there are sub-items', () => {
@@ -148,9 +133,7 @@ describe('Fly out sidebar navigation', () => {
mouseLeaveTopItem(el);
- expect(
- el.classList.remove,
- ).toHaveBeenCalledWith('is-over');
+ expect(el.classList.remove).toHaveBeenCalledWith('is-over');
});
it('does not remove is-over class if currentOpenMenu is the passed in sub-items', () => {
@@ -159,34 +142,29 @@ describe('Fly out sidebar navigation', () => {
setOpenMenu(el.querySelector('.sidebar-sub-level-items'));
mouseLeaveTopItem(el);
- expect(
- el.classList.remove,
- ).not.toHaveBeenCalled();
+ expect(el.classList.remove).not.toHaveBeenCalled();
});
});
describe('mouseEnterTopItems', () => {
beforeEach(() => {
- el.innerHTML = '<div class="sidebar-sub-level-items" style="position: absolute; top: 0; left: 100px; height: 200px;"></div>';
+ el.innerHTML =
+ '<div class="sidebar-sub-level-items" style="position: absolute; top: 0; left: 100px; height: 200px;"></div>';
});
- it('shows sub-items after 0ms if no menu is open', (done) => {
+ it('shows sub-items after 0ms if no menu is open', done => {
mouseEnterTopItems(el);
- expect(
- getHideSubItemsInterval(),
- ).toBe(0);
+ expect(getHideSubItemsInterval()).toBe(0);
setTimeout(() => {
- expect(
- el.querySelector('.sidebar-sub-level-items').style.display,
- ).toBe('block');
+ expect(el.querySelector('.sidebar-sub-level-items').style.display).toBe('block');
done();
});
});
- it('shows sub-items after 300ms if a menu is currently open', (done) => {
+ it('shows sub-items after 300ms if a menu is currently open', done => {
documentMouseMove({
clientX: el.getBoundingClientRect().left,
clientY: el.getBoundingClientRect().top,
@@ -201,14 +179,10 @@ describe('Fly out sidebar navigation', () => {
mouseEnterTopItems(el, 0);
- expect(
- getHideSubItemsInterval(),
- ).toBe(300);
+ expect(getHideSubItemsInterval()).toBe(300);
setTimeout(() => {
- expect(
- el.querySelector('.sidebar-sub-level-items').style.display,
- ).toBe('block');
+ expect(el.querySelector('.sidebar-sub-level-items').style.display).toBe('block');
done();
});
@@ -225,9 +199,7 @@ describe('Fly out sidebar navigation', () => {
showSubLevelItems(el);
- expect(
- el.classList.add,
- ).toHaveBeenCalledWith('is-over');
+ expect(el.classList.add).toHaveBeenCalledWith('is-over');
});
it('does not show sub-items on mobile', () => {
@@ -235,17 +207,13 @@ describe('Fly out sidebar navigation', () => {
showSubLevelItems(el);
- expect(
- el.querySelector('.sidebar-sub-level-items').style.display,
- ).not.toBe('block');
+ expect(el.querySelector('.sidebar-sub-level-items').style.display).not.toBe('block');
});
it('shows sub-items', () => {
showSubLevelItems(el);
- expect(
- el.querySelector('.sidebar-sub-level-items').style.display,
- ).toBe('block');
+ expect(el.querySelector('.sidebar-sub-level-items').style.display).toBe('block');
});
it('shows collapsed only sub-items if icon only sidebar', () => {
@@ -258,9 +226,7 @@ describe('Fly out sidebar navigation', () => {
showSubLevelItems(el);
- expect(
- el.querySelector('.sidebar-sub-level-items').style.display,
- ).toBe('block');
+ expect(el.querySelector('.sidebar-sub-level-items').style.display).toBe('block');
});
it('does not show collapsed only sub-items if icon only sidebar', () => {
@@ -269,9 +235,7 @@ describe('Fly out sidebar navigation', () => {
showSubLevelItems(el);
- expect(
- subItems.style.display,
- ).not.toBe('block');
+ expect(subItems.style.display).not.toBe('block');
});
it('sets transform of sub-items', () => {
@@ -285,9 +249,10 @@ describe('Fly out sidebar navigation', () => {
setSidebar(sidebar);
showSubLevelItems(el);
- expect(
- subItems.style.transform,
- ).toBe(`translate3d(200px, ${Math.floor(el.getBoundingClientRect().top) - getHeaderHeight()}px, 0px)`);
+ expect(subItems.style.transform).toBe(
+ `translate3d(200px, ${Math.floor(el.getBoundingClientRect().top) -
+ getHeaderHeight()}px, 0px)`,
+ );
});
it('sets is-above when element is above', () => {
@@ -299,33 +264,25 @@ describe('Fly out sidebar navigation', () => {
showSubLevelItems(el);
- expect(
- subItems.classList.add,
- ).toHaveBeenCalledWith('is-above');
+ expect(subItems.classList.add).toHaveBeenCalledWith('is-above');
});
});
describe('canShowSubItems', () => {
it('returns true if on desktop size', () => {
- expect(
- canShowSubItems(),
- ).toBeTruthy();
+ expect(canShowSubItems()).toBeTruthy();
});
it('returns false if on mobile size', () => {
breakpointSize = 'xs';
- expect(
- canShowSubItems(),
- ).toBeFalsy();
+ expect(canShowSubItems()).toBeFalsy();
});
});
describe('canShowActiveSubItems', () => {
it('returns true by default', () => {
- expect(
- canShowActiveSubItems(el),
- ).toBeTruthy();
+ expect(canShowActiveSubItems(el)).toBeTruthy();
});
it('returns false when active & expanded sidebar', () => {
@@ -334,9 +291,7 @@ describe('Fly out sidebar navigation', () => {
setSidebar(sidebar);
- expect(
- canShowActiveSubItems(el),
- ).toBeFalsy();
+ expect(canShowActiveSubItems(el)).toBeFalsy();
});
it('returns true when active & collapsed sidebar', () => {
@@ -346,9 +301,7 @@ describe('Fly out sidebar navigation', () => {
setSidebar(sidebar);
- expect(
- canShowActiveSubItems(el),
- ).toBeTruthy();
+ expect(canShowActiveSubItems(el)).toBeTruthy();
});
});
@@ -362,18 +315,14 @@ describe('Fly out sidebar navigation', () => {
it('hides subMenu if element is not hovered', () => {
subItemsMouseLeave(el);
- expect(
- getOpenMenu(),
- ).toBeNull();
+ expect(getOpenMenu()).toBeNull();
});
it('does not hide subMenu if element is hovered', () => {
el.classList.add('is-over');
subItemsMouseLeave(el);
- expect(
- getOpenMenu(),
- ).not.toBeNull();
+ expect(getOpenMenu()).not.toBeNull();
});
});
});
diff --git a/spec/javascripts/frequent_items/components/app_spec.js b/spec/javascripts/frequent_items/components/app_spec.js
index 834f919524d..b1cc4d8dc8d 100644
--- a/spec/javascripts/frequent_items/components/app_spec.js
+++ b/spec/javascripts/frequent_items/components/app_spec.js
@@ -232,8 +232,7 @@ describe('Frequent Items App Component', () => {
expect(vm.$el.querySelectorAll('.frequent-items-list-container li').length).toBe(1);
vm.$store.dispatch('setSearchQuery', 'gitlab');
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
expect(vm.$el.querySelector('.loading-animation')).toBeDefined();
})
diff --git a/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js b/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js
index 201aca77b10..7deed985219 100644
--- a/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js
+++ b/spec/javascripts/frequent_items/components/frequent_items_list_item_spec.js
@@ -30,9 +30,11 @@ describe('FrequentItemsListItemComponent', () => {
describe('hasAvatar', () => {
it('should return `true` or `false` if whether avatar is present or not', () => {
vm.avatarUrl = 'path/to/avatar.png';
+
expect(vm.hasAvatar).toBe(true);
vm.avatarUrl = null;
+
expect(vm.hasAvatar).toBe(false);
});
});
@@ -40,11 +42,13 @@ describe('FrequentItemsListItemComponent', () => {
describe('highlightedItemName', () => {
it('should enclose part of project name in <b> & </b> which matches with `matcher` prop', () => {
vm.matcher = 'lab';
+
expect(vm.highlightedItemName).toContain('<b>Lab</b>');
});
it('should return project name as it is if `matcher` is not available', () => {
vm.matcher = null;
+
expect(vm.highlightedItemName).toBe(mockProject.name);
});
});
@@ -52,11 +56,13 @@ describe('FrequentItemsListItemComponent', () => {
describe('truncatedNamespace', () => {
it('should truncate project name from namespace string', () => {
vm.namespace = 'platform / nokia-3310';
+
expect(vm.truncatedNamespace).toBe('platform');
});
it('should truncate namespace string from the middle if it includes more than two groups in path', () => {
vm.namespace = 'platform / hardware / broadcom / Wifi Group / Mobile Chipset / nokia-3310';
+
expect(vm.truncatedNamespace).toBe('platform / ... / Mobile Chipset');
});
});
diff --git a/spec/javascripts/frequent_items/components/frequent_items_list_spec.js b/spec/javascripts/frequent_items/components/frequent_items_list_spec.js
index 3003b7ee000..8518a681a26 100644
--- a/spec/javascripts/frequent_items/components/frequent_items_list_spec.js
+++ b/spec/javascripts/frequent_items/components/frequent_items_list_spec.js
@@ -30,9 +30,11 @@ describe('FrequentItemsListComponent', () => {
describe('isListEmpty', () => {
it('should return `true` or `false` representing whether if `items` is empty or not with projects', () => {
vm.items = [];
+
expect(vm.isListEmpty).toBe(true);
vm.items = mockFrequentProjects;
+
expect(vm.isListEmpty).toBe(false);
});
});
@@ -40,9 +42,11 @@ describe('FrequentItemsListComponent', () => {
describe('fetched item messages', () => {
it('should return appropriate empty list message based on value of `localStorageFailed` prop with projects', () => {
vm.isFetchFailed = true;
+
expect(vm.listEmptyMessage).toBe('This feature requires browser localStorage support');
vm.isFetchFailed = false;
+
expect(vm.listEmptyMessage).toBe('Projects you visit often will appear here');
});
});
@@ -51,9 +55,11 @@ describe('FrequentItemsListComponent', () => {
it('should return appropriate empty list message based on value of `searchFailed` prop with projects', () => {
vm.hasSearchQuery = true;
vm.isFetchFailed = true;
+
expect(vm.listEmptyMessage).toBe('Something went wrong on our end.');
vm.isFetchFailed = false;
+
expect(vm.listEmptyMessage).toBe('Sorry, no projects matched your search');
});
});
diff --git a/spec/javascripts/frequent_items/components/frequent_items_search_input_spec.js b/spec/javascripts/frequent_items/components/frequent_items_search_input_spec.js
index 6a11038e70a..d564292f1ba 100644
--- a/spec/javascripts/frequent_items/components/frequent_items_search_input_spec.js
+++ b/spec/javascripts/frequent_items/components/frequent_items_search_input_spec.js
@@ -26,6 +26,7 @@ describe('FrequentItemsSearchInputComponent', () => {
spyOn(vm.$refs.search, 'focus');
vm.setFocus();
+
expect(vm.$refs.search.focus).toHaveBeenCalled();
});
});
diff --git a/spec/javascripts/gfm_auto_complete_spec.js b/spec/javascripts/gfm_auto_complete_spec.js
index 4f9cacf2724..6f414c8ccf1 100644
--- a/spec/javascripts/gfm_auto_complete_spec.js
+++ b/spec/javascripts/gfm_auto_complete_spec.js
@@ -6,39 +6,38 @@ import GfmAutoComplete from '~/gfm_auto_complete';
import 'vendor/jquery.caret';
import 'vendor/jquery.atwho';
-describe('GfmAutoComplete', function () {
+describe('GfmAutoComplete', function() {
const gfmAutoCompleteCallbacks = GfmAutoComplete.prototype.getDefaultCallbacks.call({
fetchData: () => {},
});
- describe('DefaultOptions.sorter', function () {
- describe('assets loading', function () {
- beforeEach(function () {
+ describe('DefaultOptions.sorter', function() {
+ describe('assets loading', function() {
+ beforeEach(function() {
spyOn(GfmAutoComplete, 'isLoading').and.returnValue(true);
this.atwhoInstance = { setting: {} };
this.items = [];
- this.sorterValue = gfmAutoCompleteCallbacks.sorter
- .call(this.atwhoInstance, '', this.items);
+ this.sorterValue = gfmAutoCompleteCallbacks.sorter.call(this.atwhoInstance, '', this.items);
});
- it('should disable highlightFirst', function () {
+ it('should disable highlightFirst', function() {
expect(this.atwhoInstance.setting.highlightFirst).toBe(false);
});
- it('should return the passed unfiltered items', function () {
+ it('should return the passed unfiltered items', function() {
expect(this.sorterValue).toEqual(this.items);
});
});
- describe('assets finished loading', function () {
- beforeEach(function () {
+ describe('assets finished loading', function() {
+ beforeEach(function() {
spyOn(GfmAutoComplete, 'isLoading').and.returnValue(false);
spyOn($.fn.atwho.default.callbacks, 'sorter');
});
- it('should enable highlightFirst if alwaysHighlightFirst is set', function () {
+ it('should enable highlightFirst if alwaysHighlightFirst is set', function() {
const atwhoInstance = { setting: { alwaysHighlightFirst: true } };
gfmAutoCompleteCallbacks.sorter.call(atwhoInstance);
@@ -46,7 +45,7 @@ describe('GfmAutoComplete', function () {
expect(atwhoInstance.setting.highlightFirst).toBe(true);
});
- it('should enable highlightFirst if a query is present', function () {
+ it('should enable highlightFirst if a query is present', function() {
const atwhoInstance = { setting: {} };
gfmAutoCompleteCallbacks.sorter.call(atwhoInstance, 'query');
@@ -54,7 +53,7 @@ describe('GfmAutoComplete', function () {
expect(atwhoInstance.setting.highlightFirst).toBe(true);
});
- it('should call the default atwho sorter', function () {
+ it('should call the default atwho sorter', function() {
const atwhoInstance = { setting: {} };
const query = 'query';
@@ -69,9 +68,8 @@ describe('GfmAutoComplete', function () {
});
describe('DefaultOptions.beforeInsert', () => {
- const beforeInsert = (context, value) => (
- gfmAutoCompleteCallbacks.beforeInsert.call(context, value)
- );
+ const beforeInsert = (context, value) =>
+ gfmAutoCompleteCallbacks.beforeInsert.call(context, value);
const atwhoInstance = { setting: { skipSpecialCharacterTest: false } };
@@ -98,29 +96,51 @@ describe('GfmAutoComplete', function () {
});
});
- describe('DefaultOptions.matcher', function () {
- const defaultMatcher = (context, flag, subtext) => (
- gfmAutoCompleteCallbacks.matcher.call(context, flag, subtext)
- );
+ describe('DefaultOptions.matcher', function() {
+ const defaultMatcher = (context, flag, subtext) =>
+ gfmAutoCompleteCallbacks.matcher.call(context, flag, subtext);
- const flagsUseDefaultMatcher = ['@', '#', '!', '~', '%'];
+ const flagsUseDefaultMatcher = ['@', '#', '!', '~', '%', '$'];
const otherFlags = ['/', ':'];
const flags = flagsUseDefaultMatcher.concat(otherFlags);
- const flagsHash = flags.reduce((hash, el) => { hash[el] = null; return hash; }, {});
+ const flagsHash = flags.reduce((hash, el) => {
+ hash[el] = null;
+ return hash;
+ }, {});
const atwhoInstance = { setting: {}, app: { controllers: flagsHash } };
const minLen = 1;
const maxLen = 20;
const argumentSize = [minLen, maxLen / 2, maxLen];
- const allowedSymbols = ['', 'a', 'n', 'z', 'A', 'Z', 'N', '0', '5', '9', 'Ð', 'а', 'Я', 'Ñ', '.', '\'', '+', '-', '_'];
+ const allowedSymbols = [
+ '',
+ 'a',
+ 'n',
+ 'z',
+ 'A',
+ 'Z',
+ 'N',
+ '0',
+ '5',
+ '9',
+ 'Ð',
+ 'а',
+ 'Я',
+ 'Ñ',
+ '.',
+ "'",
+ '+',
+ '-',
+ '_',
+ ];
const jointAllowedSymbols = allowedSymbols.join('');
describe('should match regular symbols', () => {
- flagsUseDefaultMatcher.forEach((flag) => {
- allowedSymbols.forEach((symbol) => {
- argumentSize.forEach((size) => {
+ flagsUseDefaultMatcher.forEach(flag => {
+ allowedSymbols.forEach(symbol => {
+ argumentSize.forEach(size => {
const query = new Array(size + 1).join(symbol);
const subtext = flag + query;
@@ -142,8 +162,8 @@ describe('GfmAutoComplete', function () {
const shouldNotBeFollowedBy = flags.concat(['\x00', '\x10', '\x3f', '\n', ' ']);
const shouldNotBePrependedBy = ['`'];
- flagsUseDefaultMatcher.forEach((atSign) => {
- shouldNotBeFollowedBy.forEach((followedSymbol) => {
+ flagsUseDefaultMatcher.forEach(atSign => {
+ shouldNotBeFollowedBy.forEach(followedSymbol => {
const seq = atSign + followedSymbol;
it(`should not match ${JSON.stringify(seq)}`, () => {
@@ -151,7 +171,7 @@ describe('GfmAutoComplete', function () {
});
});
- shouldNotBePrependedBy.forEach((prependedSymbol) => {
+ shouldNotBePrependedBy.forEach(prependedSymbol => {
const seq = prependedSymbol + atSign;
it(`should not match "${seq}"`, () => {
@@ -162,28 +182,26 @@ describe('GfmAutoComplete', function () {
});
});
- describe('isLoading', function () {
- it('should be true with loading data object item', function () {
+ describe('isLoading', function() {
+ it('should be true with loading data object item', function() {
expect(GfmAutoComplete.isLoading({ name: 'loading' })).toBe(true);
});
- it('should be true with loading data array', function () {
+ it('should be true with loading data array', function() {
expect(GfmAutoComplete.isLoading(['loading'])).toBe(true);
});
- it('should be true with loading data object array', function () {
+ it('should be true with loading data object array', function() {
expect(GfmAutoComplete.isLoading([{ name: 'loading' }])).toBe(true);
});
- it('should be false with actual array data', function () {
- expect(GfmAutoComplete.isLoading([
- { title: 'Foo' },
- { title: 'Bar' },
- { title: 'Qux' },
- ])).toBe(false);
+ it('should be false with actual array data', function() {
+ expect(
+ GfmAutoComplete.isLoading([{ title: 'Foo' }, { title: 'Bar' }, { title: 'Qux' }]),
+ ).toBe(false);
});
- it('should be false with actual data item', function () {
+ it('should be false with actual data item', function() {
expect(GfmAutoComplete.isLoading({ title: 'Foo' })).toBe(false);
});
});
diff --git a/spec/javascripts/gl_dropdown_spec.js b/spec/javascripts/gl_dropdown_spec.js
index af58dff7da7..85083653db8 100644
--- a/spec/javascripts/gl_dropdown_spec.js
+++ b/spec/javascripts/gl_dropdown_spec.js
@@ -1,4 +1,4 @@
-/* eslint-disable comma-dangle, no-param-reassign */
+/* eslint-disable no-param-reassign */
import $ from 'jquery';
import GLDropdown from '~/gl_dropdown';
@@ -8,7 +8,8 @@ describe('glDropdown', function describeDropdown() {
preloadFixtures('static/gl_dropdown.html.raw');
loadJSONFixtures('projects.json');
- const NON_SELECTABLE_CLASSES = '.divider, .separator, .dropdown-header, .dropdown-menu-empty-item';
+ const NON_SELECTABLE_CLASSES =
+ '.divider, .separator, .dropdown-header, .dropdown-menu-empty-item';
const SEARCH_INPUT_SELECTOR = '.dropdown-input-field';
const ITEM_SELECTOR = `.dropdown-content li:not(${NON_SELECTABLE_CLASSES})`;
const FOCUSED_ITEM_SELECTOR = `${ITEM_SELECTOR} a.is-focused`;
@@ -17,7 +18,7 @@ describe('glDropdown', function describeDropdown() {
DOWN: 40,
UP: 38,
ENTER: 13,
- ESC: 27
+ ESC: 27,
};
let remoteCallback;
@@ -28,7 +29,7 @@ describe('glDropdown', function describeDropdown() {
$('body').trigger({
type: 'keydown',
which: ARROW_KEYS[direction],
- keyCode: ARROW_KEYS[direction]
+ keyCode: ARROW_KEYS[direction],
});
i += 1;
if (i <= steps) {
@@ -43,17 +44,23 @@ describe('glDropdown', function describeDropdown() {
};
function initDropDown(hasRemote, isFilterable, extraOpts = {}) {
- const options = Object.assign({
- selectable: true,
- filterable: isFilterable,
- data: hasRemote ? remoteMock.bind({}, this.projectsData) : this.projectsData,
- search: {
- fields: ['name']
+ const options = Object.assign(
+ {
+ selectable: true,
+ filterable: isFilterable,
+ data: hasRemote ? remoteMock.bind({}, this.projectsData) : this.projectsData,
+ search: {
+ fields: ['name'],
+ },
+ text: project => project.name_with_namespace || project.name,
+ id: project => project.id,
},
- text: project => (project.name_with_namespace || project.name),
- id: project => project.id,
- }, extraOpts);
- this.dropdownButtonElement = $('#js-project-dropdown', this.dropdownContainerElement).glDropdown(options);
+ extraOpts,
+ );
+ this.dropdownButtonElement = $(
+ '#js-project-dropdown',
+ this.dropdownContainerElement,
+ ).glDropdown(options);
}
beforeEach(() => {
@@ -70,8 +77,10 @@ describe('glDropdown', function describeDropdown() {
it('should open on click', () => {
initDropDown.call(this, false);
+
expect(this.dropdownContainerElement).not.toHaveClass('show');
this.dropdownButtonElement.click();
+
expect(this.dropdownContainerElement).toHaveClass('show');
});
@@ -82,9 +91,7 @@ describe('glDropdown', function describeDropdown() {
this.dropdownButtonElement.click();
- expect(
- $('.dropdown-content li:first-child').text(),
- ).toBe('<script>alert("testing");</script>');
+ expect($('.dropdown-content li:first-child').text()).toBe('<script>alert("testing");</script>');
});
it('should output HTML when highlighting', () => {
@@ -97,13 +104,11 @@ describe('glDropdown', function describeDropdown() {
this.dropdownButtonElement.click();
- expect(
- $('.dropdown-content li:first-child').text(),
- ).toBe('testing');
+ expect($('.dropdown-content li:first-child').text()).toBe('testing');
- expect(
- $('.dropdown-content li:first-child a').html(),
- ).toBe('<b>t</b><b>e</b><b>s</b><b>t</b>ing');
+ expect($('.dropdown-content li:first-child a').html()).toBe(
+ '<b>t</b><b>e</b><b>s</b><b>t</b>ing',
+ );
});
describe('that is open', () => {
@@ -114,21 +119,28 @@ describe('glDropdown', function describeDropdown() {
it('should select a following item on DOWN keypress', () => {
expect($(FOCUSED_ITEM_SELECTOR, this.$dropdownMenuElement).length).toBe(0);
- const randomIndex = (Math.floor(Math.random() * (this.projectsData.length - 1)) + 0);
+ const randomIndex = Math.floor(Math.random() * (this.projectsData.length - 1)) + 0;
navigateWithKeys('down', randomIndex, () => {
expect($(FOCUSED_ITEM_SELECTOR, this.$dropdownMenuElement).length).toBe(1);
- expect($(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, this.$dropdownMenuElement)).toHaveClass('is-focused');
+ expect($(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, this.$dropdownMenuElement)).toHaveClass(
+ 'is-focused',
+ );
});
});
it('should select a previous item on UP keypress', () => {
expect($(FOCUSED_ITEM_SELECTOR, this.$dropdownMenuElement).length).toBe(0);
- navigateWithKeys('down', (this.projectsData.length - 1), () => {
+ navigateWithKeys('down', this.projectsData.length - 1, () => {
expect($(FOCUSED_ITEM_SELECTOR, this.$dropdownMenuElement).length).toBe(1);
- const randomIndex = (Math.floor(Math.random() * (this.projectsData.length - 2)) + 0);
+ const randomIndex = Math.floor(Math.random() * (this.projectsData.length - 2)) + 0;
navigateWithKeys('up', randomIndex, () => {
expect($(FOCUSED_ITEM_SELECTOR, this.$dropdownMenuElement).length).toBe(1);
- expect($(`${ITEM_SELECTOR}:eq(${((this.projectsData.length - 2) - randomIndex)}) a`, this.$dropdownMenuElement)).toHaveClass('is-focused');
+ expect(
+ $(
+ `${ITEM_SELECTOR}:eq(${this.projectsData.length - 2 - randomIndex}) a`,
+ this.$dropdownMenuElement,
+ ),
+ ).toHaveClass('is-focused');
});
});
});
@@ -141,9 +153,12 @@ describe('glDropdown', function describeDropdown() {
navigateWithKeys('enter', null, () => {
expect(this.dropdownContainerElement).not.toHaveClass('show');
const link = $(`${ITEM_SELECTOR}:eq(${randomIndex}) a`, this.$dropdownMenuElement);
+
expect(link).toHaveClass('is-active');
const linkedLocation = link.attr('href');
- if (linkedLocation && linkedLocation !== '#') expect(visitUrl).toHaveBeenCalledWith(linkedLocation);
+ if (linkedLocation && linkedLocation !== '#') {
+ expect(visitUrl).toHaveBeenCalledWith(linkedLocation);
+ }
});
});
});
@@ -153,8 +168,9 @@ describe('glDropdown', function describeDropdown() {
this.dropdownContainerElement.trigger({
type: 'keyup',
which: ARROW_KEYS.ESC,
- keyCode: ARROW_KEYS.ESC
+ keyCode: ARROW_KEYS.ESC,
});
+
expect(this.dropdownContainerElement).not.toHaveClass('show');
});
});
@@ -168,19 +184,22 @@ describe('glDropdown', function describeDropdown() {
it('should show loading indicator while search results are being fetched by backend', () => {
const dropdownMenu = document.querySelector('.dropdown-menu');
- expect(dropdownMenu.className.indexOf('is-loading') !== -1).toEqual(true);
+ expect(dropdownMenu.className.indexOf('is-loading')).not.toBe(-1);
remoteCallback();
- expect(dropdownMenu.className.indexOf('is-loading') !== -1).toEqual(false);
+
+ expect(dropdownMenu.className.indexOf('is-loading')).toBe(-1);
});
it('should not focus search input while remote task is not complete', () => {
expect($(document.activeElement)).not.toEqual($(SEARCH_INPUT_SELECTOR));
remoteCallback();
+
expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR));
});
it('should focus search input after remote task is complete', () => {
remoteCallback();
+
expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR));
});
@@ -189,10 +208,11 @@ describe('glDropdown', function describeDropdown() {
this.dropdownContainerElement.trigger({
type: 'keyup',
which: ARROW_KEYS.ESC,
- keyCode: ARROW_KEYS.ESC
+ keyCode: ARROW_KEYS.ESC,
});
this.dropdownButtonElement.click();
this.dropdownContainerElement.trigger('transitionend');
+
expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR));
});
});
@@ -202,6 +222,7 @@ describe('glDropdown', function describeDropdown() {
initDropDown.call(this, false, true);
this.dropdownButtonElement.click();
this.dropdownContainerElement.trigger('transitionend');
+
expect($(document.activeElement)).toEqual($(SEARCH_INPUT_SELECTOR));
});
});
@@ -213,11 +234,11 @@ describe('glDropdown', function describeDropdown() {
.trigger('focus')
.val('g')
.trigger('input');
+
expect($searchInput.val()).toEqual('g');
this.dropdownButtonElement.trigger('hidden.bs.dropdown');
- $searchInput
- .trigger('blur')
- .trigger('focus');
+ $searchInput.trigger('blur').trigger('focus');
+
expect($searchInput.val()).toEqual('g');
});
@@ -226,31 +247,31 @@ describe('glDropdown', function describeDropdown() {
let dropdown;
beforeEach(() => {
- const dropdownOptions = {
-
- };
+ const dropdownOptions = {};
const $dropdownDiv = $('<div />');
$dropdownDiv.glDropdown(dropdownOptions);
dropdown = $dropdownDiv.data('glDropdown');
});
it('marks items without ID as active', () => {
- const dummyData = { };
+ const dummyData = {};
const html = dropdown.renderItem(dummyData, null, null);
const link = html.querySelector('a');
+
expect(link).toHaveClass('is-active');
});
it('does not mark items with ID as active', () => {
const dummyData = {
- id: 'ea'
+ id: 'ea',
};
const html = dropdown.renderItem(dummyData, null, null);
const link = html.querySelector('a');
+
expect(link).not.toHaveClass('is-active');
});
});
@@ -271,13 +292,14 @@ describe('glDropdown', function describeDropdown() {
// select item the first time
this.dropdownButtonElement.click();
$item.click();
+
expect($item).toHaveClass('is-active');
// select item the second time
this.dropdownButtonElement.click();
$item.click();
+
expect($item).toHaveClass('is-active');
expect($('.dropdown-toggle-text')).toHaveText(this.projectsData[0].id.toString());
});
});
-
diff --git a/spec/javascripts/gl_field_errors_spec.js b/spec/javascripts/gl_field_errors_spec.js
index 21c462cd040..b463c9afbee 100644
--- a/spec/javascripts/gl_field_errors_spec.js
+++ b/spec/javascripts/gl_field_errors_spec.js
@@ -19,6 +19,7 @@ describe('GL Style Field Errors', function() {
expect(this.$form.length).toBe(1);
expect(this.fieldErrors).toBeDefined();
const { inputs } = this.fieldErrors.state;
+
expect(inputs.length).toBe(4);
});
@@ -28,29 +29,50 @@ describe('GL Style Field Errors', function() {
expect(customErrorElem.length).toBe(1);
- const customErrors = this.fieldErrors.state.inputs.filter((input) => {
+ const customErrors = this.fieldErrors.state.inputs.filter(input => {
return input.inputElement.hasClass(customErrorFlag);
});
+
expect(customErrors.length).toBe(0);
});
it('should not show any errors before submit attempt', function() {
- this.$form.find('.email').val('not-a-valid-email').keyup();
- this.$form.find('.text-required').val('').keyup();
- this.$form.find('.alphanumberic').val('?---*').keyup();
+ this.$form
+ .find('.email')
+ .val('not-a-valid-email')
+ .keyup();
+ this.$form
+ .find('.text-required')
+ .val('')
+ .keyup();
+ this.$form
+ .find('.alphanumberic')
+ .val('?---*')
+ .keyup();
const errorsShown = this.$form.find('.gl-field-error-outline');
+
expect(errorsShown.length).toBe(0);
});
it('should show errors when input valid is submitted', function() {
- this.$form.find('.email').val('not-a-valid-email').keyup();
- this.$form.find('.text-required').val('').keyup();
- this.$form.find('.alphanumberic').val('?---*').keyup();
+ this.$form
+ .find('.email')
+ .val('not-a-valid-email')
+ .keyup();
+ this.$form
+ .find('.text-required')
+ .val('')
+ .keyup();
+ this.$form
+ .find('.alphanumberic')
+ .val('?---*')
+ .keyup();
this.$form.submit();
const errorsShown = this.$form.find('.gl-field-error-outline');
+
expect(errorsShown.length).toBe(4);
});
@@ -68,30 +90,35 @@ describe('GL Style Field Errors', function() {
// Then invalid input
emailInputElement.val('not-a-valid-email').keyup();
+
expect(emailInputElement).toHaveClass('gl-field-error-outline');
expect(fieldState.empty).toBe(false);
expect(fieldState.valid).toBe(false);
// Then valid input
emailInputElement.val('email@gitlab.com').keyup();
+
expect(emailInputElement).not.toHaveClass('gl-field-error-outline');
expect(fieldState.empty).toBe(false);
expect(fieldState.valid).toBe(true);
// Then invalid input
emailInputElement.val('not-a-valid-email').keyup();
+
expect(emailInputElement).toHaveClass('gl-field-error-outline');
expect(fieldState.empty).toBe(false);
expect(fieldState.valid).toBe(false);
// Then empty input
emailInputElement.val('').keyup();
+
expect(emailInputElement).toHaveClass('gl-field-error-outline');
expect(fieldState.empty).toBe(true);
expect(fieldState.valid).toBe(false);
// Then valid input
emailInputElement.val('email@gitlab.com').keyup();
+
expect(emailInputElement).not.toHaveClass('gl-field-error-outline');
expect(fieldState.empty).toBe(false);
expect(fieldState.valid).toBe(true);
diff --git a/spec/javascripts/gl_form_spec.js b/spec/javascripts/gl_form_spec.js
index 74383f901b2..69b3dae743a 100644
--- a/spec/javascripts/gl_form_spec.js
+++ b/spec/javascripts/gl_form_spec.js
@@ -5,8 +5,8 @@ import '~/lib/utils/text_utility';
import '~/lib/utils/common_utils';
describe('GLForm', () => {
- describe('when instantiated', function () {
- beforeEach((done) => {
+ describe('when instantiated', function() {
+ beforeEach(done => {
this.form = $('<form class="gfm-form"><textarea class="js-gfm-input"></form>');
this.textarea = this.form.find('textarea');
spyOn($.prototype, 'off').and.returnValue(this.textarea);
@@ -23,7 +23,7 @@ describe('GLForm', () => {
});
describe('setupAutosize', () => {
- beforeEach((done) => {
+ beforeEach(done => {
this.glForm.setupAutosize();
setTimeout(() => {
done();
@@ -101,6 +101,7 @@ describe('GLForm', () => {
spyOn($.prototype, 'outerHeight').and.returnValue(200);
spyOn($.prototype, 'data').and.returnValue(200);
spyOn(autosize, 'destroy');
+
expect(this.glForm.destroyAutosize()).toBeUndefined();
expect(autosize.destroy).not.toHaveBeenCalled();
});
diff --git a/spec/javascripts/gpg_badges_spec.js b/spec/javascripts/gpg_badges_spec.js
index 78330dd9633..e73f6d3909e 100644
--- a/spec/javascripts/gpg_badges_spec.js
+++ b/spec/javascripts/gpg_badges_spec.js
@@ -69,6 +69,7 @@ describe('GpgBadges', () => {
.then(() => {
expect(document.querySelector('.js-loading-gpg-badge:empty')).toBe(null);
const spinners = document.querySelectorAll('.js-loading-gpg-badge i.fa.fa-spinner.fa-spin');
+
expect(spinners.length).toBe(1);
done();
})
@@ -82,6 +83,7 @@ describe('GpgBadges', () => {
.then(() => {
expect(document.querySelector('.js-loading-gpg-badge')).toBe(null);
const parentContainer = document.querySelector('.parent-container');
+
expect(parentContainer.innerHTML.trim()).toEqual(dummyBadgeHtml);
done();
})
diff --git a/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js b/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js
index d8a8c8cc260..563d134ca81 100644
--- a/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js
+++ b/spec/javascripts/graphs/stat_graph_contributors_graph_spec.js
@@ -1,99 +1,119 @@
-/* eslint-disable quotes, jasmine/no-suite-dupes, vars-on-top, no-var */
+/* eslint-disable jasmine/no-suite-dupes, vars-on-top, no-var */
+
import { scaleLinear, scaleTime } from 'd3-scale';
import { timeParse } from 'd3-time-format';
-import { ContributorsGraph, ContributorsMasterGraph } from '~/pages/projects/graphs/show/stat_graph_contributors_graph';
+import {
+ ContributorsGraph,
+ ContributorsMasterGraph,
+} from '~/pages/projects/graphs/show/stat_graph_contributors_graph';
const d3 = { scaleLinear, scaleTime, timeParse };
-describe("ContributorsGraph", function () {
- describe("#set_x_domain", function () {
- it("set the x_domain", function () {
+describe('ContributorsGraph', function() {
+ describe('#set_x_domain', function() {
+ it('set the x_domain', function() {
ContributorsGraph.set_x_domain(20);
+
expect(ContributorsGraph.prototype.x_domain).toEqual(20);
});
});
- describe("#set_y_domain", function () {
- it("sets the y_domain", function () {
+ describe('#set_y_domain', function() {
+ it('sets the y_domain', function() {
ContributorsGraph.set_y_domain([{ commits: 30 }]);
+
expect(ContributorsGraph.prototype.y_domain).toEqual([0, 30]);
});
});
- describe("#init_x_domain", function () {
- it("sets the initial x_domain", function () {
- ContributorsGraph.init_x_domain([{ date: "2013-01-31" }, { date: "2012-01-31" }]);
- expect(ContributorsGraph.prototype.x_domain).toEqual(["2012-01-31", "2013-01-31"]);
+ describe('#init_x_domain', function() {
+ it('sets the initial x_domain', function() {
+ ContributorsGraph.init_x_domain([{ date: '2013-01-31' }, { date: '2012-01-31' }]);
+
+ expect(ContributorsGraph.prototype.x_domain).toEqual(['2012-01-31', '2013-01-31']);
});
});
- describe("#init_y_domain", function () {
- it("sets the initial y_domain", function () {
+ describe('#init_y_domain', function() {
+ it('sets the initial y_domain', function() {
ContributorsGraph.init_y_domain([{ commits: 30 }]);
+
expect(ContributorsGraph.prototype.y_domain).toEqual([0, 30]);
});
});
- describe("#init_domain", function () {
- it("calls init_x_domain and init_y_domain", function () {
- spyOn(ContributorsGraph, "init_x_domain");
- spyOn(ContributorsGraph, "init_y_domain");
+ describe('#init_domain', function() {
+ it('calls init_x_domain and init_y_domain', function() {
+ spyOn(ContributorsGraph, 'init_x_domain');
+ spyOn(ContributorsGraph, 'init_y_domain');
ContributorsGraph.init_domain();
+
expect(ContributorsGraph.init_x_domain).toHaveBeenCalled();
expect(ContributorsGraph.init_y_domain).toHaveBeenCalled();
});
});
- describe("#set_dates", function () {
- it("sets the dates", function () {
- ContributorsGraph.set_dates("2013-12-01");
- expect(ContributorsGraph.prototype.dates).toEqual("2013-12-01");
+ describe('#set_dates', function() {
+ it('sets the dates', function() {
+ ContributorsGraph.set_dates('2013-12-01');
+
+ expect(ContributorsGraph.prototype.dates).toEqual('2013-12-01');
});
});
- describe("#set_x_domain", function () {
- it("sets the instance's x domain using the prototype's x_domain", function () {
+ describe('#set_x_domain', function() {
+ it("sets the instance's x domain using the prototype's x_domain", function() {
ContributorsGraph.prototype.x_domain = 20;
var instance = new ContributorsGraph();
- instance.x = d3.scaleTime().range([0, 100]).clamp(true);
+ instance.x = d3
+ .scaleTime()
+ .range([0, 100])
+ .clamp(true);
spyOn(instance.x, 'domain');
instance.set_x_domain();
+
expect(instance.x.domain).toHaveBeenCalledWith(20);
});
});
- describe("#set_y_domain", function () {
- it("sets the instance's y domain using the prototype's y_domain", function () {
+ describe('#set_y_domain', function() {
+ it("sets the instance's y domain using the prototype's y_domain", function() {
ContributorsGraph.prototype.y_domain = 30;
var instance = new ContributorsGraph();
- instance.y = d3.scaleLinear().range([100, 0]).nice();
+ instance.y = d3
+ .scaleLinear()
+ .range([100, 0])
+ .nice();
spyOn(instance.y, 'domain');
instance.set_y_domain();
+
expect(instance.y.domain).toHaveBeenCalledWith(30);
});
});
- describe("#set_domain", function () {
- it("calls set_x_domain and set_y_domain", function () {
+ describe('#set_domain', function() {
+ it('calls set_x_domain and set_y_domain', function() {
var instance = new ContributorsGraph();
spyOn(instance, 'set_x_domain');
spyOn(instance, 'set_y_domain');
instance.set_domain();
+
expect(instance.set_x_domain).toHaveBeenCalled();
expect(instance.set_y_domain).toHaveBeenCalled();
});
});
- describe("#set_data", function () {
- it("sets the data", function () {
+ describe('#set_data', function() {
+ it('sets the data', function() {
var instance = new ContributorsGraph();
- instance.set_data("20");
- expect(instance.data).toEqual("20");
+ instance.set_data('20');
+
+ expect(instance.data).toEqual('20');
});
});
});
-describe("ContributorsMasterGraph", function () {
+describe('ContributorsMasterGraph', function() {
// TODO: fix or remove
// describe("#process_dates", function () {
// it("gets and parses dates", function () {
@@ -109,21 +129,23 @@ describe("ContributorsMasterGraph", function () {
// });
// });
- describe("#get_dates", function () {
- it("plucks the date field from data collection", function () {
+ describe('#get_dates', function() {
+ it('plucks the date field from data collection', function() {
var graph = new ContributorsMasterGraph();
- var data = [{ date: "2013-01-01" }, { date: "2012-12-15" }];
- expect(graph.get_dates(data)).toEqual(["2013-01-01", "2012-12-15"]);
+ var data = [{ date: '2013-01-01' }, { date: '2012-12-15' }];
+
+ expect(graph.get_dates(data)).toEqual(['2013-01-01', '2012-12-15']);
});
});
- describe("#parse_dates", function () {
- it("parses the dates", function () {
+ describe('#parse_dates', function() {
+ it('parses the dates', function() {
var graph = new ContributorsMasterGraph();
- var parseDate = d3.timeParse("%Y-%m-%d");
- var data = [{ date: "2013-01-01" }, { date: "2012-12-15" }];
+ var parseDate = d3.timeParse('%Y-%m-%d');
+ var data = [{ date: '2013-01-01' }, { date: '2012-12-15' }];
var correct = [{ date: parseDate(data[0].date) }, { date: parseDate(data[1].date) }];
graph.parse_dates(data);
+
expect(data).toEqual(correct);
});
});
diff --git a/spec/javascripts/graphs/stat_graph_contributors_spec.js b/spec/javascripts/graphs/stat_graph_contributors_spec.js
index e03114c1cc5..2ebb6845a8b 100644
--- a/spec/javascripts/graphs/stat_graph_contributors_spec.js
+++ b/spec/javascripts/graphs/stat_graph_contributors_spec.js
@@ -20,7 +20,9 @@ describe('ContributorsStatGraph', () => {
graph.change_date_header();
- expect(document.getElementById('date_header').innerText).toBe('31. Januar 2012 – 31. Januar 2013');
+ expect(document.getElementById('date_header').innerText).toBe(
+ '31. Januar 2012 – 31. Januar 2013',
+ );
});
});
});
diff --git a/spec/javascripts/graphs/stat_graph_contributors_util_spec.js b/spec/javascripts/graphs/stat_graph_contributors_util_spec.js
index 22a9afe1a9d..511b660c671 100644
--- a/spec/javascripts/graphs/stat_graph_contributors_util_spec.js
+++ b/spec/javascripts/graphs/stat_graph_contributors_util_spec.js
@@ -1,57 +1,86 @@
-/* eslint-disable quotes, no-var, camelcase, object-property-newline, comma-dangle, max-len, vars-on-top, quote-props */
+/* eslint-disable no-var, camelcase, vars-on-top */
import ContributorsStatGraphUtil from '~/pages/projects/graphs/show/stat_graph_contributors_util';
-describe("ContributorsStatGraphUtil", function () {
- describe("#parse_log", function () {
- it("returns a correctly parsed log", function () {
+describe('ContributorsStatGraphUtil', function() {
+ describe('#parse_log', function() {
+ it('returns a correctly parsed log', function() {
var fake_log = [
- { author_email: "karlo@email.com", author_name: "Karlo Soriano", date: "2013-05-09", additions: 471 },
- { author_email: "dzaporozhets@email.com", author_name: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 6, deletions: 1 },
- { author_email: "dzaporozhets@email.com", author_name: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 19, deletions: 3 },
- { author_email: "dzaporozhets@email.com", author_name: "Dmitriy Zaporozhets", date: "2013-05-08", additions: 29, deletions: 3 }
+ {
+ author_email: 'karlo@email.com',
+ author_name: 'Karlo Soriano',
+ date: '2013-05-09',
+ additions: 471,
+ },
+ {
+ author_email: 'dzaporozhets@email.com',
+ author_name: 'Dmitriy Zaporozhets',
+ date: '2013-05-08',
+ additions: 6,
+ deletions: 1,
+ },
+ {
+ author_email: 'dzaporozhets@email.com',
+ author_name: 'Dmitriy Zaporozhets',
+ date: '2013-05-08',
+ additions: 19,
+ deletions: 3,
+ },
+ {
+ author_email: 'dzaporozhets@email.com',
+ author_name: 'Dmitriy Zaporozhets',
+ date: '2013-05-08',
+ additions: 29,
+ deletions: 3,
+ },
];
var correct_parsed_log = {
total: [
- { date: "2013-05-09", additions: 471, deletions: 0, commits: 1 },
- { date: "2013-05-08", additions: 54, deletions: 7, commits: 3 }
+ { date: '2013-05-09', additions: 471, deletions: 0, commits: 1 },
+ { date: '2013-05-08', additions: 54, deletions: 7, commits: 3 },
],
by_author: [
{
- author_name: "Karlo Soriano", author_email: "karlo@email.com",
- "2013-05-09": { date: "2013-05-09", additions: 471, deletions: 0, commits: 1 }
+ author_name: 'Karlo Soriano',
+ author_email: 'karlo@email.com',
+ '2013-05-09': { date: '2013-05-09', additions: 471, deletions: 0, commits: 1 },
},
{
- author_name: "Dmitriy Zaporozhets", author_email: "dzaporozhets@email.com",
- "2013-05-08": { date: "2013-05-08", additions: 54, deletions: 7, commits: 3 }
- }
- ]
+ author_name: 'Dmitriy Zaporozhets',
+ author_email: 'dzaporozhets@email.com',
+ '2013-05-08': { date: '2013-05-08', additions: 54, deletions: 7, commits: 3 },
+ },
+ ],
};
+
expect(ContributorsStatGraphUtil.parse_log(fake_log)).toEqual(correct_parsed_log);
});
});
- describe("#store_data", function () {
- var fake_entry = { author: "Karlo Soriano", date: "2013-05-09", additions: 471 };
+ describe('#store_data', function() {
+ var fake_entry = { author: 'Karlo Soriano', date: '2013-05-09', additions: 471 };
var fake_total = {};
var fake_by_author = {};
- it("calls #store_commits", function () {
+ it('calls #store_commits', function() {
spyOn(ContributorsStatGraphUtil, 'store_commits');
ContributorsStatGraphUtil.store_data(fake_entry, fake_total, fake_by_author);
+
expect(ContributorsStatGraphUtil.store_commits).toHaveBeenCalled();
});
- it("calls #store_additions", function () {
+ it('calls #store_additions', function() {
spyOn(ContributorsStatGraphUtil, 'store_additions');
ContributorsStatGraphUtil.store_data(fake_entry, fake_total, fake_by_author);
+
expect(ContributorsStatGraphUtil.store_additions).toHaveBeenCalled();
});
- it("calls #store_deletions", function () {
+ it('calls #store_deletions', function() {
spyOn(ContributorsStatGraphUtil, 'store_deletions');
ContributorsStatGraphUtil.store_data(fake_entry, fake_total, fake_by_author);
+
expect(ContributorsStatGraphUtil.store_deletions).toHaveBeenCalled();
});
});
@@ -68,16 +97,18 @@ describe("ContributorsStatGraphUtil", function () {
// });
// });
- describe("#add", function () {
- it("adds 1 to current test_field in collection", function () {
+ describe('#add', function() {
+ it('adds 1 to current test_field in collection', function() {
var fake_collection = { test_field: 10 };
- ContributorsStatGraphUtil.add(fake_collection, "test_field", 1);
+ ContributorsStatGraphUtil.add(fake_collection, 'test_field', 1);
+
expect(fake_collection.test_field).toEqual(11);
});
- it("inits and adds 1 if test_field in collection is not defined", function () {
+ it('inits and adds 1 if test_field in collection is not defined', function() {
var fake_collection = {};
- ContributorsStatGraphUtil.add(fake_collection, "test_field", 1);
+ ContributorsStatGraphUtil.add(fake_collection, 'test_field', 1);
+
expect(fake_collection.test_field).toEqual(1);
});
});
@@ -106,111 +137,161 @@ describe("ContributorsStatGraphUtil", function () {
// });
// });
- describe("#add_date", function () {
- it("adds a date field to the collection", function () {
- var fake_date = "2013-10-02";
+ describe('#add_date', function() {
+ it('adds a date field to the collection', function() {
+ var fake_date = '2013-10-02';
var fake_collection = {};
ContributorsStatGraphUtil.add_date(fake_date, fake_collection);
- expect(fake_collection[fake_date].date).toEqual("2013-10-02");
+
+ expect(fake_collection[fake_date].date).toEqual('2013-10-02');
});
});
- describe("#add_author", function () {
- it("adds an author field to the collection", function () {
- var fake_author = { author_name: "Author", author_email: 'fake@email.com' };
+ describe('#add_author', function() {
+ it('adds an author field to the collection', function() {
+ var fake_author = { author_name: 'Author', author_email: 'fake@email.com' };
var fake_author_collection = {};
var fake_email_collection = {};
- ContributorsStatGraphUtil.add_author(fake_author, fake_author_collection, fake_email_collection);
- expect(fake_author_collection[fake_author.author_name].author_name).toEqual("Author");
- expect(fake_email_collection[fake_author.author_email].author_name).toEqual("Author");
+ ContributorsStatGraphUtil.add_author(
+ fake_author,
+ fake_author_collection,
+ fake_email_collection,
+ );
+
+ expect(fake_author_collection[fake_author.author_name].author_name).toEqual('Author');
+ expect(fake_email_collection[fake_author.author_email].author_name).toEqual('Author');
});
});
- describe("#get_total_data", function () {
- it("returns the collection sorted via specified field", function () {
+ describe('#get_total_data', function() {
+ it('returns the collection sorted via specified field', function() {
var fake_parsed_log = {
total: [
- { date: "2013-05-09", additions: 471, deletions: 0, commits: 1 },
- { date: "2013-05-08", additions: 54, deletions: 7, commits: 3 }
+ { date: '2013-05-09', additions: 471, deletions: 0, commits: 1 },
+ { date: '2013-05-08', additions: 54, deletions: 7, commits: 3 },
],
by_author: [
{
- author: "Karlo Soriano",
- "2013-05-09": { date: "2013-05-09", additions: 471, deletions: 0, commits: 1 }
+ author: 'Karlo Soriano',
+ '2013-05-09': { date: '2013-05-09', additions: 471, deletions: 0, commits: 1 },
},
{
- author: "Dmitriy Zaporozhets",
- "2013-05-08": { date: "2013-05-08", additions: 54, deletions: 7, commits: 3 }
- }
- ]
+ author: 'Dmitriy Zaporozhets',
+ '2013-05-08': { date: '2013-05-08', additions: 54, deletions: 7, commits: 3 },
+ },
+ ],
};
var correct_total_data = [
- { date: "2013-05-08", commits: 3 },
- { date: "2013-05-09", commits: 1 }
+ { date: '2013-05-08', commits: 3 },
+ { date: '2013-05-09', commits: 1 },
];
- expect(ContributorsStatGraphUtil.get_total_data(fake_parsed_log, "commits")).toEqual(correct_total_data);
+
+ expect(ContributorsStatGraphUtil.get_total_data(fake_parsed_log, 'commits')).toEqual(
+ correct_total_data,
+ );
});
});
- describe("#pick_field", function () {
- it("returns the collection with only the specified field and date", function () {
+ describe('#pick_field', function() {
+ it('returns the collection with only the specified field and date', function() {
var fake_parsed_log_total = [
- { date: "2013-05-09", additions: 471, deletions: 0, commits: 1 },
- { date: "2013-05-08", additions: 54, deletions: 7, commits: 3 }
+ { date: '2013-05-09', additions: 471, deletions: 0, commits: 1 },
+ { date: '2013-05-08', additions: 54, deletions: 7, commits: 3 },
];
- ContributorsStatGraphUtil.pick_field(fake_parsed_log_total, "commits");
- var correct_pick_field_data = [{ date: "2013-05-09", commits: 1 }, { date: "2013-05-08", commits: 3 }];
- expect(ContributorsStatGraphUtil.pick_field(fake_parsed_log_total, "commits")).toEqual(correct_pick_field_data);
+ ContributorsStatGraphUtil.pick_field(fake_parsed_log_total, 'commits');
+ var correct_pick_field_data = [
+ { date: '2013-05-09', commits: 1 },
+ { date: '2013-05-08', commits: 3 },
+ ];
+
+ expect(ContributorsStatGraphUtil.pick_field(fake_parsed_log_total, 'commits')).toEqual(
+ correct_pick_field_data,
+ );
});
});
- describe("#get_author_data", function () {
- it("returns the log by author sorted by specified field", function () {
+ describe('#get_author_data', function() {
+ it('returns the log by author sorted by specified field', function() {
var fake_parsed_log = {
total: [
- { date: "2013-05-09", additions: 471, deletions: 0, commits: 1 },
- { date: "2013-05-08", additions: 54, deletions: 7, commits: 3 }
+ { date: '2013-05-09', additions: 471, deletions: 0, commits: 1 },
+ { date: '2013-05-08', additions: 54, deletions: 7, commits: 3 },
],
by_author: [
{
- author_name: "Karlo Soriano", author_email: "karlo@email.com",
- "2013-05-09": { date: "2013-05-09", additions: 471, deletions: 0, commits: 1 }
+ author_name: 'Karlo Soriano',
+ author_email: 'karlo@email.com',
+ '2013-05-09': { date: '2013-05-09', additions: 471, deletions: 0, commits: 1 },
},
{
- author_name: "Dmitriy Zaporozhets", author_email: "dzaporozhets@email.com",
- "2013-05-08": { date: "2013-05-08", additions: 54, deletions: 7, commits: 3 }
- }
- ]
+ author_name: 'Dmitriy Zaporozhets',
+ author_email: 'dzaporozhets@email.com',
+ '2013-05-08': { date: '2013-05-08', additions: 54, deletions: 7, commits: 3 },
+ },
+ ],
};
var correct_author_data = [
- { author_name: "Dmitriy Zaporozhets", author_email: "dzaporozhets@email.com", dates: { "2013-05-08": 3 }, deletions: 7, additions: 54, "commits": 3 },
- { author_name: "Karlo Soriano", author_email: "karlo@email.com", dates: { "2013-05-09": 1 }, deletions: 0, additions: 471, commits: 1 }
+ {
+ author_name: 'Dmitriy Zaporozhets',
+ author_email: 'dzaporozhets@email.com',
+ dates: { '2013-05-08': 3 },
+ deletions: 7,
+ additions: 54,
+ commits: 3,
+ },
+ {
+ author_name: 'Karlo Soriano',
+ author_email: 'karlo@email.com',
+ dates: { '2013-05-09': 1 },
+ deletions: 0,
+ additions: 471,
+ commits: 1,
+ },
];
- expect(ContributorsStatGraphUtil.get_author_data(fake_parsed_log, "commits")).toEqual(correct_author_data);
+
+ expect(ContributorsStatGraphUtil.get_author_data(fake_parsed_log, 'commits')).toEqual(
+ correct_author_data,
+ );
});
});
- describe("#parse_log_entry", function () {
- it("adds the corresponding info from the log entry to the author", function () {
- var fake_log_entry = { author_name: "Karlo Soriano", author_email: "karlo@email.com",
- "2013-05-09": { date: "2013-05-09", additions: 471, deletions: 0, commits: 1 }
+ describe('#parse_log_entry', function() {
+ it('adds the corresponding info from the log entry to the author', function() {
+ var fake_log_entry = {
+ author_name: 'Karlo Soriano',
+ author_email: 'karlo@email.com',
+ '2013-05-09': { date: '2013-05-09', additions: 471, deletions: 0, commits: 1 },
+ };
+ var correct_parsed_log = {
+ author_name: 'Karlo Soriano',
+ author_email: 'karlo@email.com',
+ dates: { '2013-05-09': 1 },
+ deletions: 0,
+ additions: 471,
+ commits: 1,
};
- var correct_parsed_log = { author_name: "Karlo Soriano", author_email: "karlo@email.com", dates: { "2013-05-09": 1 }, deletions: 0, additions: 471, commits: 1 };
- expect(ContributorsStatGraphUtil.parse_log_entry(fake_log_entry, 'commits', null)).toEqual(correct_parsed_log);
+
+ expect(ContributorsStatGraphUtil.parse_log_entry(fake_log_entry, 'commits', null)).toEqual(
+ correct_parsed_log,
+ );
});
});
- describe("#in_range", function () {
- var date = "2013-05-09";
- it("returns true if date_range is null", function () {
+ describe('#in_range', function() {
+ var date = '2013-05-09';
+ it('returns true if date_range is null', function() {
expect(ContributorsStatGraphUtil.in_range(date, null)).toEqual(true);
});
- it("returns true if date is in range", function () {
- var date_range = [new Date("2013-01-01"), new Date("2013-12-12")];
+
+ it('returns true if date is in range', function() {
+ var date_range = [new Date('2013-01-01'), new Date('2013-12-12')];
+
expect(ContributorsStatGraphUtil.in_range(date, date_range)).toEqual(true);
});
- it("returns false if date is not in range", function () {
- var date_range = [new Date("1999-12-01"), new Date("2000-12-01")];
+
+ it('returns false if date is not in range', function() {
+ var date_range = [new Date('1999-12-01'), new Date('2000-12-01')];
+
expect(ContributorsStatGraphUtil.in_range(date, date_range)).toEqual(false);
});
});
diff --git a/spec/javascripts/groups/components/app_spec.js b/spec/javascripts/groups/components/app_spec.js
index 89c07d1f06d..d832441dc93 100644
--- a/spec/javascripts/groups/components/app_spec.js
+++ b/spec/javascripts/groups/components/app_spec.js
@@ -76,6 +76,7 @@ describe('AppComponent', () => {
spyOn(vm.store, 'getGroups');
const { groups } = vm;
+
expect(vm.store.getGroups).toHaveBeenCalled();
expect(groups).not.toBeDefined();
});
@@ -86,6 +87,7 @@ describe('AppComponent', () => {
spyOn(vm.store, 'getPaginationInfo');
const { pageInfo } = vm;
+
expect(vm.store.getPaginationInfo).toHaveBeenCalled();
expect(pageInfo).not.toBeDefined();
});
@@ -154,6 +156,7 @@ describe('AppComponent', () => {
spyOn(vm, 'updateGroups').and.callThrough();
vm.fetchAllGroups();
+
expect(vm.isLoading).toBe(true);
expect(vm.fetchGroups).toHaveBeenCalled();
setTimeout(() => {
@@ -168,6 +171,7 @@ describe('AppComponent', () => {
spyOn(vm, 'updateGroups').and.callThrough();
vm.fetchAllGroups();
+
expect(vm.fetchGroups).toHaveBeenCalledWith({
page: null,
filterGroupsBy: null,
@@ -191,6 +195,7 @@ describe('AppComponent', () => {
spyOn($, 'scrollTo');
vm.fetchPage(2, null, null, true);
+
expect(vm.isLoading).toBe(true);
expect(vm.fetchGroups).toHaveBeenCalledWith({
page: 2,
@@ -210,6 +215,7 @@ describe('AppComponent', () => {
jasmine.any(String),
jasmine.any(String),
);
+
expect(vm.updateGroups).toHaveBeenCalled();
done();
}, 0);
@@ -230,6 +236,7 @@ describe('AppComponent', () => {
spyOn(vm.store, 'setGroupChildren');
vm.toggleChildren(groupItem);
+
expect(groupItem.isChildrenLoading).toBe(true);
expect(vm.fetchGroups).toHaveBeenCalledWith({
parentId: groupItem.id,
@@ -245,6 +252,7 @@ describe('AppComponent', () => {
groupItem.children = mockRawChildren;
vm.toggleChildren(groupItem);
+
expect(vm.fetchGroups).not.toHaveBeenCalled();
expect(groupItem.isOpen).toBe(true);
});
@@ -254,6 +262,7 @@ describe('AppComponent', () => {
groupItem.isOpen = true;
vm.toggleChildren(groupItem);
+
expect(vm.fetchGroups).not.toHaveBeenCalled();
expect(groupItem.isOpen).toBe(false);
});
@@ -262,6 +271,7 @@ describe('AppComponent', () => {
spyOn(vm, 'fetchGroups').and.returnValue(returnServicePromise({}, true));
vm.toggleChildren(groupItem);
+
expect(groupItem.isChildrenLoading).toBe(true);
setTimeout(() => {
expect(groupItem.isChildrenLoading).toBe(false);
@@ -273,18 +283,22 @@ describe('AppComponent', () => {
describe('showLeaveGroupModal', () => {
it('caches candidate group (as props) which is to be left', () => {
const group = Object.assign({}, mockParentGroupItem);
+
expect(vm.targetGroup).toBe(null);
expect(vm.targetParentGroup).toBe(null);
vm.showLeaveGroupModal(group, mockParentGroupItem);
+
expect(vm.targetGroup).not.toBe(null);
expect(vm.targetParentGroup).not.toBe(null);
});
it('updates props which show modal confirmation dialog', () => {
const group = Object.assign({}, mockParentGroupItem);
+
expect(vm.showModal).toBe(false);
expect(vm.groupLeaveConfirmationMessage).toBe('');
vm.showLeaveGroupModal(group, mockParentGroupItem);
+
expect(vm.showModal).toBe(true);
expect(vm.groupLeaveConfirmationMessage).toBe(
`Are you sure you want to leave the "${group.fullName}" group?`,
@@ -296,8 +310,10 @@ describe('AppComponent', () => {
it('hides modal confirmation which is shown before leaving the group', () => {
const group = Object.assign({}, mockParentGroupItem);
vm.showLeaveGroupModal(group, mockParentGroupItem);
+
expect(vm.showModal).toBe(true);
vm.hideLeaveGroupModal();
+
expect(vm.showModal).toBe(false);
});
});
@@ -323,6 +339,7 @@ describe('AppComponent', () => {
spyOn($, 'scrollTo');
vm.leaveGroup();
+
expect(vm.showModal).toBe(false);
expect(vm.targetGroup.isBeingRemoved).toBe(true);
expect(vm.service.leaveGroup).toHaveBeenCalledWith(vm.targetGroup.leavePath);
@@ -343,6 +360,7 @@ describe('AppComponent', () => {
spyOn(window, 'Flash');
vm.leaveGroup();
+
expect(vm.targetGroup.isBeingRemoved).toBe(true);
expect(vm.service.leaveGroup).toHaveBeenCalledWith(childGroupItem.leavePath);
setTimeout(() => {
@@ -362,6 +380,7 @@ describe('AppComponent', () => {
spyOn(window, 'Flash');
vm.leaveGroup(childGroupItem, groupItem);
+
expect(vm.targetGroup.isBeingRemoved).toBe(true);
expect(vm.service.leaveGroup).toHaveBeenCalledWith(childGroupItem.leavePath);
setTimeout(() => {
@@ -378,6 +397,7 @@ describe('AppComponent', () => {
spyOn(vm.store, 'setPaginationInfo');
vm.updatePagination(mockRawPageInfo);
+
expect(vm.store.setPaginationInfo).toHaveBeenCalledWith(mockRawPageInfo);
});
});
@@ -387,6 +407,7 @@ describe('AppComponent', () => {
spyOn(vm.store, 'setGroups');
vm.updateGroups(mockGroups);
+
expect(vm.store.setGroups).toHaveBeenCalledWith(mockGroups);
});
@@ -394,14 +415,17 @@ describe('AppComponent', () => {
spyOn(vm.store, 'setSearchedGroups');
vm.updateGroups(mockGroups, true);
+
expect(vm.store.setSearchedGroups).toHaveBeenCalledWith(mockGroups);
});
it('should set `isSearchEmpty` prop based on groups count', () => {
vm.updateGroups(mockGroups);
+
expect(vm.isSearchEmpty).toBe(false);
vm.updateGroups([]);
+
expect(vm.isSearchEmpty).toBe(true);
});
});
@@ -497,6 +521,7 @@ describe('AppComponent', () => {
vm.showModal = true;
Vue.nextTick(() => {
const modalDialogEl = vm.$el.querySelector('.modal');
+
expect(modalDialogEl).not.toBe(null);
expect(modalDialogEl.querySelector('.modal-title').innerText.trim()).toBe('Are you sure?');
expect(modalDialogEl.querySelector('.btn.btn-warning').innerText.trim()).toBe('Leave');
diff --git a/spec/javascripts/groups/components/group_folder_spec.js b/spec/javascripts/groups/components/group_folder_spec.js
index 4eb198595fb..fdfd1b82bd8 100644
--- a/spec/javascripts/groups/components/group_folder_spec.js
+++ b/spec/javascripts/groups/components/group_folder_spec.js
@@ -18,7 +18,7 @@ const createComponent = (groups = mockGroups, parentGroup = mockParentGroupItem)
describe('GroupFolderComponent', () => {
let vm;
- beforeEach((done) => {
+ beforeEach(done => {
Vue.component('group-item', groupItemComponent);
vm = createComponent();
@@ -59,6 +59,7 @@ describe('GroupFolderComponent', () => {
const newVm = createComponent(mockGroups, parentGroup);
newVm.$mount();
+
expect(newVm.$el.querySelector('li.group-row a.has-more-items')).toBeDefined();
newVm.$destroy();
});
diff --git a/spec/javascripts/groups/components/group_item_spec.js b/spec/javascripts/groups/components/group_item_spec.js
index d0cac5efc40..4d6d0c895b6 100644
--- a/spec/javascripts/groups/components/group_item_spec.js
+++ b/spec/javascripts/groups/components/group_item_spec.js
@@ -17,7 +17,7 @@ const createComponent = (group = mockParentGroupItem, parentGroup = mockChildren
describe('GroupItemComponent', () => {
let vm;
- beforeEach((done) => {
+ beforeEach(done => {
Vue.component('group-folder', groupFolderComponent);
vm = createComponent();
@@ -44,8 +44,8 @@ describe('GroupItemComponent', () => {
const { rowClass } = vm;
expect(Object.keys(rowClass).length).toBe(classes.length);
- Object.keys(rowClass).forEach((className) => {
- expect(classes.indexOf(className) > -1).toBeTruthy();
+ Object.keys(rowClass).forEach(className => {
+ expect(classes.indexOf(className)).toBeGreaterThan(-1);
});
});
});
@@ -57,11 +57,13 @@ describe('GroupItemComponent', () => {
group.childrenCount = 5;
newVm = createComponent(group);
+
expect(newVm.hasChildren).toBeTruthy();
newVm.$destroy();
group.childrenCount = 0;
newVm = createComponent(group);
+
expect(newVm.hasChildren).toBeFalsy();
newVm.$destroy();
});
@@ -74,11 +76,13 @@ describe('GroupItemComponent', () => {
group.avatarUrl = null;
newVm = createComponent(group);
+
expect(newVm.hasAvatar).toBeFalsy();
newVm.$destroy();
group.avatarUrl = '/uploads/group_avatar.png';
newVm = createComponent(group);
+
expect(newVm.hasAvatar).toBeTruthy();
newVm.$destroy();
});
@@ -91,11 +95,13 @@ describe('GroupItemComponent', () => {
group.type = 'group';
newVm = createComponent(group);
+
expect(newVm.isGroup).toBeTruthy();
newVm.$destroy();
group.type = 'project';
newVm = createComponent(group);
+
expect(newVm.isGroup).toBeFalsy();
newVm.$destroy();
});
@@ -127,10 +133,11 @@ describe('GroupItemComponent', () => {
spyOn(eventHub, '$emit');
vm.onClickRowGroup(event);
+
expect(eventHub.$emit).toHaveBeenCalledWith('toggleChildren', vm.group);
});
- it('should navigate page to group homepage if group does not have any children present', (done) => {
+ it('should navigate page to group homepage if group does not have any children present', done => {
const group = Object.assign({}, mockParentGroupItem);
group.childrenCount = 0;
const newVm = createComponent(group);
diff --git a/spec/javascripts/groups/components/groups_spec.js b/spec/javascripts/groups/components/groups_spec.js
index 793c4909d89..6ba4fe23a69 100644
--- a/spec/javascripts/groups/components/groups_spec.js
+++ b/spec/javascripts/groups/components/groups_spec.js
@@ -21,7 +21,7 @@ const createComponent = (searchEmpty = false) => {
describe('GroupsComponent', () => {
let vm;
- beforeEach((done) => {
+ beforeEach(done => {
Vue.component('group-folder', groupFolderComponent);
Vue.component('group-item', groupItemComponent);
@@ -42,23 +42,30 @@ describe('GroupsComponent', () => {
spyOn(eventHub, '$emit').and.stub();
vm.change(2);
- expect(eventHub.$emit).toHaveBeenCalledWith('fetchPage', 2, jasmine.any(Object), jasmine.any(Object), jasmine.any(Object));
+
+ expect(eventHub.$emit).toHaveBeenCalledWith(
+ 'fetchPage',
+ 2,
+ jasmine.any(Object),
+ jasmine.any(Object),
+ jasmine.any(Object),
+ );
});
});
});
describe('template', () => {
- it('should render component template correctly', (done) => {
+ it('should render component template correctly', done => {
Vue.nextTick(() => {
expect(vm.$el.querySelector('.groups-list-tree-container')).toBeDefined();
expect(vm.$el.querySelector('.group-list-tree')).toBeDefined();
expect(vm.$el.querySelector('.gl-pagination')).toBeDefined();
- expect(vm.$el.querySelectorAll('.has-no-search-results').length === 0).toBeTruthy();
+ expect(vm.$el.querySelectorAll('.has-no-search-results').length).toBe(0);
done();
});
});
- it('should render empty search message when `searchEmpty` is `true`', (done) => {
+ it('should render empty search message when `searchEmpty` is `true`', done => {
vm.searchEmpty = true;
Vue.nextTick(() => {
expect(vm.$el.querySelector('.has-no-search-results')).toBeDefined();
diff --git a/spec/javascripts/groups/components/item_actions_spec.js b/spec/javascripts/groups/components/item_actions_spec.js
index 15fd37ebcd2..3f66e7fd6f2 100644
--- a/spec/javascripts/groups/components/item_actions_spec.js
+++ b/spec/javascripts/groups/components/item_actions_spec.js
@@ -30,7 +30,12 @@ describe('ItemActionsComponent', () => {
it('emits `showLeaveGroupModal` event with `group` and `parentGroup` props', () => {
spyOn(eventHub, '$emit');
vm.onLeaveGroup();
- expect(eventHub.$emit).toHaveBeenCalledWith('showLeaveGroupModal', vm.group, vm.parentGroup);
+
+ expect(eventHub.$emit).toHaveBeenCalledWith(
+ 'showLeaveGroupModal',
+ vm.group,
+ vm.parentGroup,
+ );
});
});
});
@@ -46,6 +51,7 @@ describe('ItemActionsComponent', () => {
const newVm = createComponent(group);
const editBtn = newVm.$el.querySelector('a.edit-group');
+
expect(editBtn).toBeDefined();
expect(editBtn.classList.contains('no-expand')).toBeTruthy();
expect(editBtn.getAttribute('href')).toBe(group.editPath);
@@ -63,6 +69,7 @@ describe('ItemActionsComponent', () => {
const newVm = createComponent(group);
const leaveBtn = newVm.$el.querySelector('a.leave-group');
+
expect(leaveBtn).toBeDefined();
expect(leaveBtn.classList.contains('no-expand')).toBeTruthy();
expect(leaveBtn.getAttribute('href')).toBe(group.leavePath);
diff --git a/spec/javascripts/groups/components/item_caret_spec.js b/spec/javascripts/groups/components/item_caret_spec.js
index 36f838a104f..6e430dbcdb2 100644
--- a/spec/javascripts/groups/components/item_caret_spec.js
+++ b/spec/javascripts/groups/components/item_caret_spec.js
@@ -16,6 +16,7 @@ describe('ItemCaretComponent', () => {
describe('template', () => {
it('should render component template correctly', () => {
const vm = createComponent();
+
expect(vm.$el.classList.contains('folder-caret')).toBeTruthy();
expect(vm.$el.querySelectorAll('svg').length).toBe(1);
vm.$destroy();
@@ -23,12 +24,14 @@ describe('ItemCaretComponent', () => {
it('should render caret down icon if `isGroupOpen` prop is `true`', () => {
const vm = createComponent(true);
+
expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('angle-down');
vm.$destroy();
});
it('should render caret right icon if `isGroupOpen` prop is `false`', () => {
const vm = createComponent();
+
expect(vm.$el.querySelector('svg use').getAttribute('xlink:href')).toContain('angle-right');
vm.$destroy();
});
diff --git a/spec/javascripts/groups/components/item_stats_spec.js b/spec/javascripts/groups/components/item_stats_spec.js
index ee7ee18259e..00d6a4817d7 100644
--- a/spec/javascripts/groups/components/item_stats_spec.js
+++ b/spec/javascripts/groups/components/item_stats_spec.js
@@ -22,9 +22,10 @@ describe('ItemStatsComponent', () => {
describe('computed', () => {
describe('visibilityIcon', () => {
it('should return icon class based on `item.visibility` value', () => {
- Object.keys(VISIBILITY_TYPE_ICON).forEach((visibility) => {
+ Object.keys(VISIBILITY_TYPE_ICON).forEach(visibility => {
const item = Object.assign({}, mockParentGroupItem, { visibility });
const vm = createComponent(item);
+
expect(vm.visibilityIcon).toBe(VISIBILITY_TYPE_ICON[visibility]);
vm.$destroy();
});
@@ -33,24 +34,26 @@ describe('ItemStatsComponent', () => {
describe('visibilityTooltip', () => {
it('should return tooltip string for Group based on `item.visibility` value', () => {
- Object.keys(GROUP_VISIBILITY_TYPE).forEach((visibility) => {
+ Object.keys(GROUP_VISIBILITY_TYPE).forEach(visibility => {
const item = Object.assign({}, mockParentGroupItem, {
visibility,
type: ITEM_TYPE.GROUP,
});
const vm = createComponent(item);
+
expect(vm.visibilityTooltip).toBe(GROUP_VISIBILITY_TYPE[visibility]);
vm.$destroy();
});
});
it('should return tooltip string for Project based on `item.visibility` value', () => {
- Object.keys(PROJECT_VISIBILITY_TYPE).forEach((visibility) => {
+ Object.keys(PROJECT_VISIBILITY_TYPE).forEach(visibility => {
const item = Object.assign({}, mockParentGroupItem, {
visibility,
type: ITEM_TYPE.PROJECT,
});
const vm = createComponent(item);
+
expect(vm.visibilityTooltip).toBe(PROJECT_VISIBILITY_TYPE[visibility]);
vm.$destroy();
});
@@ -64,11 +67,13 @@ describe('ItemStatsComponent', () => {
item = Object.assign({}, mockParentGroupItem, { type: ITEM_TYPE.PROJECT });
vm = createComponent(item);
+
expect(vm.isProject).toBeTruthy();
vm.$destroy();
item = Object.assign({}, mockParentGroupItem, { type: ITEM_TYPE.GROUP });
vm = createComponent(item);
+
expect(vm.isProject).toBeFalsy();
vm.$destroy();
});
@@ -81,11 +86,13 @@ describe('ItemStatsComponent', () => {
item = Object.assign({}, mockParentGroupItem, { type: ITEM_TYPE.GROUP });
vm = createComponent(item);
+
expect(vm.isGroup).toBeTruthy();
vm.$destroy();
item = Object.assign({}, mockParentGroupItem, { type: ITEM_TYPE.PROJECT });
vm = createComponent(item);
+
expect(vm.isGroup).toBeFalsy();
vm.$destroy();
});
@@ -105,9 +112,10 @@ describe('ItemStatsComponent', () => {
const vm = createComponent();
const visibilityIconEl = vm.$el.querySelector('.item-visibility');
+
expect(visibilityIconEl).not.toBe(null);
expect(visibilityIconEl.dataset.originalTitle).toBe(vm.visibilityTooltip);
- expect(visibilityIconEl.querySelectorAll('svg').length > 0).toBeTruthy();
+ expect(visibilityIconEl.querySelectorAll('svg').length).toBeGreaterThan(0);
vm.$destroy();
});
@@ -120,10 +128,11 @@ describe('ItemStatsComponent', () => {
const vm = createComponent(item);
const projectStarIconEl = vm.$el.querySelector('.project-stars');
- expect(projectStarIconEl).not.toBe(null);
- expect(projectStarIconEl.querySelectorAll('svg').length > 0).toBeTruthy();
- expect(projectStarIconEl.querySelectorAll('.stat-value').length > 0).toBeTruthy();
- expect(vm.$el.querySelectorAll('.last-updated').length > 0).toBeTruthy();
+
+ expect(projectStarIconEl).not.toBeNull();
+ expect(projectStarIconEl.querySelectorAll('svg').length).toBeGreaterThan(0);
+ expect(projectStarIconEl.querySelectorAll('.stat-value').length).toBeGreaterThan(0);
+ expect(vm.$el.querySelectorAll('.last-updated').length).toBeGreaterThan(0);
vm.$destroy();
});
diff --git a/spec/javascripts/groups/components/item_stats_value_spec.js b/spec/javascripts/groups/components/item_stats_value_spec.js
index 5e35ae4d36c..ea8edcf49cd 100644
--- a/spec/javascripts/groups/components/item_stats_value_spec.js
+++ b/spec/javascripts/groups/components/item_stats_value_spec.js
@@ -29,11 +29,13 @@ describe('ItemStatsValueComponent', () => {
describe('isValuePresent', () => {
it('returns true if non-empty `value` is present', () => {
vm = createComponent(Object.assign({}, itemConfig, { value: 10 }));
+
expect(vm.isValuePresent).toBeTruthy();
});
it('returns false if empty `value` is present', () => {
vm = createComponent(itemConfig);
+
expect(vm.isValuePresent).toBeFalsy();
});
@@ -57,8 +59,8 @@ describe('ItemStatsValueComponent', () => {
it('renders component element correctly', () => {
expect(vm.$el.classList.contains('number-subgroups')).toBeTruthy();
- expect(vm.$el.querySelectorAll('svg').length > 0).toBeTruthy();
- expect(vm.$el.querySelectorAll('.stat-value').length > 0).toBeTruthy();
+ expect(vm.$el.querySelectorAll('svg').length).toBeGreaterThan(0);
+ expect(vm.$el.querySelectorAll('.stat-value').length).toBeGreaterThan(0);
});
it('renders element tooltip correctly', () => {
diff --git a/spec/javascripts/groups/components/item_type_icon_spec.js b/spec/javascripts/groups/components/item_type_icon_spec.js
index 24380689b29..73108512222 100644
--- a/spec/javascripts/groups/components/item_type_icon_spec.js
+++ b/spec/javascripts/groups/components/item_type_icon_spec.js
@@ -18,6 +18,7 @@ describe('ItemTypeIconComponent', () => {
it('should render component template correctly', () => {
const vm = createComponent();
vm.$mount();
+
expect(vm.$el.classList.contains('item-type-icon')).toBeTruthy();
vm.$destroy();
});
@@ -27,11 +28,13 @@ describe('ItemTypeIconComponent', () => {
vm = createComponent(ITEM_TYPE.GROUP, true);
vm.$mount();
+
expect(vm.$el.querySelector('use').getAttribute('xlink:href')).toContain('folder-open');
vm.$destroy();
vm = createComponent(ITEM_TYPE.GROUP);
vm.$mount();
+
expect(vm.$el.querySelector('use').getAttribute('xlink:href')).toContain('folder');
vm.$destroy();
});
@@ -41,11 +44,13 @@ describe('ItemTypeIconComponent', () => {
vm = createComponent(ITEM_TYPE.PROJECT);
vm.$mount();
+
expect(vm.$el.querySelector('use').getAttribute('xlink:href')).toContain('bookmark');
vm.$destroy();
vm = createComponent(ITEM_TYPE.GROUP);
vm.$mount();
+
expect(vm.$el.querySelector('use').getAttribute('xlink:href')).not.toContain('bookmark');
vm.$destroy();
});
diff --git a/spec/javascripts/groups/mock_data.js b/spec/javascripts/groups/mock_data.js
index 8bf6417487d..2fdc844f3d9 100644
--- a/spec/javascripts/groups/mock_data.js
+++ b/spec/javascripts/groups/mock_data.js
@@ -340,7 +340,8 @@ export const mockSearchedGroups = [
{
id: 17,
name: 'v4.4',
- description: 'Voluptatem qui ea error aperiam veritatis doloremque consequatur temporibus.',
+ description:
+ 'Voluptatem qui ea error aperiam veritatis doloremque consequatur temporibus.',
visibility: 'public',
full_name: 'platform / hardware / bsp / kernel / common / v4.4',
relative_path: '/platform/hardware/bsp/kernel/common/v4.4',
diff --git a/spec/javascripts/groups/service/groups_service_spec.js b/spec/javascripts/groups/service/groups_service_spec.js
index 20bb63687f7..339e5131615 100644
--- a/spec/javascripts/groups/service/groups_service_spec.js
+++ b/spec/javascripts/groups/service/groups_service_spec.js
@@ -24,9 +24,11 @@ describe('GroupsService', () => {
};
service.getGroups(55, 2, 'git', 'created_asc', true);
+
expect(service.groups.get).toHaveBeenCalledWith({ parent_id: 55 });
service.getGroups(null, 2, 'git', 'created_asc', true);
+
expect(service.groups.get).toHaveBeenCalledWith(queryParams);
});
});
@@ -36,6 +38,7 @@ describe('GroupsService', () => {
spyOn(Vue.http, 'delete').and.stub();
service.leaveGroup(mockParentGroupItem.leavePath);
+
expect(Vue.http.delete).toHaveBeenCalledWith(mockParentGroupItem.leavePath);
});
});
diff --git a/spec/javascripts/groups/store/groups_store_spec.js b/spec/javascripts/groups/store/groups_store_spec.js
index d74f38f476e..38de4b89f31 100644
--- a/spec/javascripts/groups/store/groups_store_spec.js
+++ b/spec/javascripts/groups/store/groups_store_spec.js
@@ -1,7 +1,9 @@
import GroupsStore from '~/groups/store/groups_store';
import {
- mockGroups, mockSearchedGroups,
- mockParentGroupItem, mockRawChildren,
+ mockGroups,
+ mockSearchedGroups,
+ mockParentGroupItem,
+ mockRawChildren,
mockRawPageInfo,
} from '../mock_data';
@@ -11,12 +13,14 @@ describe('ProjectsStore', () => {
let store;
store = new GroupsStore();
+
expect(Object.keys(store.state).length).toBe(2);
expect(Array.isArray(store.state.groups)).toBeTruthy();
expect(Object.keys(store.state.pageInfo).length).toBe(0);
expect(store.hideProjects).not.toBeDefined();
store = new GroupsStore(true);
+
expect(store.hideProjects).toBeTruthy();
});
});
@@ -27,9 +31,10 @@ describe('ProjectsStore', () => {
spyOn(store, 'formatGroupItem').and.callThrough();
store.setGroups(mockGroups);
+
expect(store.state.groups.length).toBe(mockGroups.length);
expect(store.formatGroupItem).toHaveBeenCalledWith(jasmine.any(Object));
- expect(Object.keys(store.state.groups[0]).indexOf('fullName') > -1).toBeTruthy();
+ expect(Object.keys(store.state.groups[0]).indexOf('fullName')).toBeGreaterThan(-1);
});
});
@@ -39,10 +44,13 @@ describe('ProjectsStore', () => {
spyOn(store, 'formatGroupItem').and.callThrough();
store.setSearchedGroups(mockSearchedGroups);
+
expect(store.state.groups.length).toBe(mockSearchedGroups.length);
expect(store.formatGroupItem).toHaveBeenCalledWith(jasmine.any(Object));
- expect(Object.keys(store.state.groups[0]).indexOf('fullName') > -1).toBeTruthy();
- expect(Object.keys(store.state.groups[0].children[0]).indexOf('fullName') > -1).toBeTruthy();
+ expect(Object.keys(store.state.groups[0]).indexOf('fullName')).toBeGreaterThan(-1);
+ expect(Object.keys(store.state.groups[0].children[0]).indexOf('fullName')).toBeGreaterThan(
+ -1,
+ );
});
});
@@ -52,9 +60,10 @@ describe('ProjectsStore', () => {
spyOn(store, 'formatGroupItem').and.callThrough();
store.setGroupChildren(mockParentGroupItem, mockRawChildren);
+
expect(store.formatGroupItem).toHaveBeenCalledWith(jasmine.any(Object));
expect(mockParentGroupItem.children.length).toBe(1);
- expect(Object.keys(mockParentGroupItem.children[0]).indexOf('fullName') > -1).toBeTruthy();
+ expect(Object.keys(mockParentGroupItem.children[0]).indexOf('fullName')).toBeGreaterThan(-1);
expect(mockParentGroupItem.isOpen).toBeTruthy();
expect(mockParentGroupItem.isChildrenLoading).toBeFalsy();
});
@@ -65,6 +74,7 @@ describe('ProjectsStore', () => {
const store = new GroupsStore();
store.setPaginationInfo(mockRawPageInfo);
+
expect(store.state.pageInfo.perPage).toBe(10);
expect(store.state.pageInfo.page).toBe(10);
expect(store.state.pageInfo.total).toBe(10);
@@ -81,14 +91,16 @@ describe('ProjectsStore', () => {
store = new GroupsStore();
updatedGroupItem = store.formatGroupItem(mockRawChildren[0]);
- expect(Object.keys(updatedGroupItem).indexOf('fullName') > -1).toBeTruthy();
+
+ expect(Object.keys(updatedGroupItem).indexOf('fullName')).toBeGreaterThan(-1);
expect(updatedGroupItem.childrenCount).toBe(mockRawChildren[0].children_count);
expect(updatedGroupItem.isChildrenLoading).toBe(false);
expect(updatedGroupItem.isBeingRemoved).toBe(false);
store = new GroupsStore(true);
updatedGroupItem = store.formatGroupItem(mockRawChildren[0]);
- expect(Object.keys(updatedGroupItem).indexOf('fullName') > -1).toBeTruthy();
+
+ expect(Object.keys(updatedGroupItem).indexOf('fullName')).toBeGreaterThan(-1);
expect(updatedGroupItem.childrenCount).toBe(mockRawChildren[0].subgroup_count);
});
});
@@ -104,6 +116,7 @@ describe('ProjectsStore', () => {
const childItem = store.state.groups[0].children[0];
store.removeGroup(childItem, store.state.groups[0]);
+
expect(store.state.groups[0].children.length).toBe(0);
});
});
diff --git a/spec/javascripts/header_spec.js b/spec/javascripts/header_spec.js
index 16ac438f7ac..2fe34e5a76f 100644
--- a/spec/javascripts/header_spec.js
+++ b/spec/javascripts/header_spec.js
@@ -1,7 +1,7 @@
import $ from 'jquery';
import initTodoToggle from '~/header';
-describe('Header', function () {
+describe('Header', function() {
const todosPendingCount = '.todos-count';
const fixtureTemplate = 'issues/open-issue.html.raw';
@@ -21,16 +21,19 @@ describe('Header', function () {
it('should update todos-count after receiving the todo:toggle event', () => {
triggerToggle('5');
+
expect($(todosPendingCount).text()).toEqual('5');
});
it('should hide todos-count when it is 0', () => {
triggerToggle('0');
+
expect(isTodosCountHidden()).toEqual(true);
});
it('should show todos-count when it is more than 0', () => {
triggerToggle('10');
+
expect(isTodosCountHidden()).toEqual(false);
});
diff --git a/spec/javascripts/helpers/class_spec_helper_spec.js b/spec/javascripts/helpers/class_spec_helper_spec.js
index fa104ae5bcd..f6268b0fb6d 100644
--- a/spec/javascripts/helpers/class_spec_helper_spec.js
+++ b/spec/javascripts/helpers/class_spec_helper_spec.js
@@ -2,11 +2,13 @@
import './class_spec_helper';
-describe('ClassSpecHelper', function () {
+describe('ClassSpecHelper', function() {
describe('itShouldBeAStaticMethod', () => {
beforeEach(() => {
class TestClass {
- instanceMethod() { this.prop = 'val'; }
+ instanceMethod() {
+ this.prop = 'val';
+ }
static staticMethod() {}
}
diff --git a/spec/javascripts/helpers/locale_helper.js b/spec/javascripts/helpers/locale_helper.js
index 99e6ce61234..80047b06003 100644
--- a/spec/javascripts/helpers/locale_helper.js
+++ b/spec/javascripts/helpers/locale_helper.js
@@ -1,6 +1,6 @@
/* eslint-disable import/prefer-default-export */
-export const setLanguage = (languageCode) => {
+export const setLanguage = languageCode => {
const htmlElement = document.querySelector('html');
if (languageCode) {
diff --git a/spec/javascripts/helpers/scroll_into_view_promise.js b/spec/javascripts/helpers/scroll_into_view_promise.js
new file mode 100644
index 00000000000..0edea2103da
--- /dev/null
+++ b/spec/javascripts/helpers/scroll_into_view_promise.js
@@ -0,0 +1,28 @@
+export default function scrollIntoViewPromise(intersectionTarget, timeout = 100, maxTries = 5) {
+ return new Promise((resolve, reject) => {
+ let intersectionObserver;
+ let retry = 0;
+
+ const intervalId = setInterval(() => {
+ if (retry >= maxTries) {
+ intersectionObserver.disconnect();
+ clearInterval(intervalId);
+ reject(new Error(`Could not scroll target into viewPort within ${timeout * maxTries} ms`));
+ }
+ retry += 1;
+ intersectionTarget.scrollIntoView();
+ }, timeout);
+
+ intersectionObserver = new IntersectionObserver(entries => {
+ if (entries[0].isIntersecting) {
+ intersectionObserver.disconnect();
+ clearInterval(intervalId);
+ resolve();
+ }
+ });
+
+ intersectionObserver.observe(intersectionTarget);
+
+ intersectionTarget.scrollIntoView();
+ });
+}
diff --git a/spec/javascripts/helpers/set_timeout_promise_helper.js b/spec/javascripts/helpers/set_timeout_promise_helper.js
index 1478073413c..47087619187 100644
--- a/spec/javascripts/helpers/set_timeout_promise_helper.js
+++ b/spec/javascripts/helpers/set_timeout_promise_helper.js
@@ -1,3 +1,4 @@
-export default (time = 0) => new Promise((resolve) => {
- setTimeout(resolve, time);
-});
+export default (time = 0) =>
+ new Promise(resolve => {
+ setTimeout(resolve, time);
+ });
diff --git a/spec/javascripts/helpers/user_mock_data_helper.js b/spec/javascripts/helpers/user_mock_data_helper.js
index f6c3ce5aecc..6999fa1f8a1 100644
--- a/spec/javascripts/helpers/user_mock_data_helper.js
+++ b/spec/javascripts/helpers/user_mock_data_helper.js
@@ -2,14 +2,12 @@ export default {
createNumberRandomUsers(numberUsers) {
const users = [];
for (let i = 0; i < numberUsers; i += 1) {
- users.push(
- {
- avatar: 'https://gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
- id: (i + 1),
- name: `GitLab User ${i}`,
- username: `gitlab${i}`,
- },
- );
+ users.push({
+ avatar: 'https://gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ id: i + 1,
+ name: `GitLab User ${i}`,
+ username: `gitlab${i}`,
+ });
}
return users;
},
diff --git a/spec/javascripts/helpers/vue_resource_helper.js b/spec/javascripts/helpers/vue_resource_helper.js
index 0d1bf5e2e80..0f58af09933 100644
--- a/spec/javascripts/helpers/vue_resource_helper.js
+++ b/spec/javascripts/helpers/vue_resource_helper.js
@@ -1,6 +1,6 @@
// eslint-disable-next-line import/prefer-default-export
export const headersInterceptor = (request, next) => {
- next((response) => {
+ next(response => {
const headers = {};
response.headers.forEach((value, key) => {
headers[key] = value;
diff --git a/spec/javascripts/helpers/wait_for_attribute_change.js b/spec/javascripts/helpers/wait_for_attribute_change.js
new file mode 100644
index 00000000000..8f22d569222
--- /dev/null
+++ b/spec/javascripts/helpers/wait_for_attribute_change.js
@@ -0,0 +1,16 @@
+export default (domElement, attributes, timeout = 1500) =>
+ new Promise((resolve, reject) => {
+ let observer;
+ const timeoutId = setTimeout(() => {
+ observer.disconnect();
+ reject(new Error(`Could not see an attribute update within ${timeout} ms`));
+ }, timeout);
+
+ observer = new MutationObserver(() => {
+ clearTimeout(timeoutId);
+ observer.disconnect();
+ resolve();
+ });
+
+ observer.observe(domElement, { attributes: true, attributeFilter: attributes });
+ });
diff --git a/spec/javascripts/ide/components/branches/item_spec.js b/spec/javascripts/ide/components/branches/item_spec.js
index 8b756c8f168..36b6736bfd4 100644
--- a/spec/javascripts/ide/components/branches/item_spec.js
+++ b/spec/javascripts/ide/components/branches/item_spec.js
@@ -29,13 +29,16 @@ describe('IDE branch item', () => {
it('renders branch name and timeago', () => {
const timeText = getTimeago().format(TEST_BRANCH.committedDate);
+
expect(vm.$el).toContainText(TEST_BRANCH.name);
expect(vm.$el.querySelector('time')).toHaveText(timeText);
expect(vm.$el.querySelector('.ic-mobile-issue-close')).toBe(null);
});
it('renders link to branch', () => {
- const expectedHref = router.resolve(`/project/${TEST_PROJECT_ID}/edit/${TEST_BRANCH.name}`).href;
+ const expectedHref = router.resolve(`/project/${TEST_PROJECT_ID}/edit/${TEST_BRANCH.name}`)
+ .href;
+
expect(vm.$el).toMatch('a');
expect(vm.$el).toHaveAttr('href', expectedHref);
});
diff --git a/spec/javascripts/ide/components/branches/search_list_spec.js b/spec/javascripts/ide/components/branches/search_list_spec.js
index c3f84ba1c24..72a3c2d5dcd 100644
--- a/spec/javascripts/ide/components/branches/search_list_spec.js
+++ b/spec/javascripts/ide/components/branches/search_list_spec.js
@@ -62,8 +62,9 @@ describe('IDE branches search list', () => {
});
it('renders list', () => {
- const elementText = Array.from(vm.$el.querySelectorAll('li strong'))
- .map(x => x.textContent.trim());
+ const elementText = Array.from(vm.$el.querySelectorAll('li strong')).map(x =>
+ x.textContent.trim(),
+ );
expect(elementText).toEqual(testBranches.map(x => x.name));
});
diff --git a/spec/javascripts/ide/components/changed_file_icon_spec.js b/spec/javascripts/ide/components/changed_file_icon_spec.js
deleted file mode 100644
index 7308219f705..00000000000
--- a/spec/javascripts/ide/components/changed_file_icon_spec.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import Vue from 'vue';
-import changedFileIcon from '~/ide/components/changed_file_icon.vue';
-import createComponent from 'spec/helpers/vue_mount_component_helper';
-
-describe('IDE changed file icon', () => {
- let vm;
-
- beforeEach(() => {
- const component = Vue.extend(changedFileIcon);
-
- vm = createComponent(component, {
- file: {
- tempFile: false,
- changed: true,
- },
- });
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('changedIcon', () => {
- it('equals file-modified when not a temp file and has changes', () => {
- expect(vm.changedIcon).toBe('file-modified');
- });
-
- it('equals file-addition when a temp file', () => {
- vm.file.tempFile = true;
-
- expect(vm.changedIcon).toBe('file-addition');
- });
- });
-
- describe('changedIconClass', () => {
- it('includes ide-file-modified when not a temp file', () => {
- expect(vm.changedIconClass).toContain('ide-file-modified');
- });
-
- it('includes ide-file-addition when a temp file', () => {
- vm.file.tempFile = true;
-
- expect(vm.changedIconClass).toContain('ide-file-addition');
- });
- });
-});
diff --git a/spec/javascripts/ide/components/commit_sidebar/list_item_spec.js b/spec/javascripts/ide/components/commit_sidebar/list_item_spec.js
index b45ae5bbb0f..bf48d7bfdad 100644
--- a/spec/javascripts/ide/components/commit_sidebar/list_item_spec.js
+++ b/spec/javascripts/ide/components/commit_sidebar/list_item_spec.js
@@ -33,10 +33,6 @@ describe('Multi-file editor commit sidebar list item', () => {
expect(vm.$el.querySelector('.multi-file-commit-list-path').textContent).toContain(f.path);
});
- it('renders actionn button', () => {
- expect(vm.$el.querySelector('.multi-file-discard-btn')).not.toBeNull();
- });
-
it('opens a closed file in the editor when clicking the file path', done => {
spyOn(vm, 'openPendingTab').and.callThrough();
spyOn(router, 'push');
diff --git a/spec/javascripts/ide/components/commit_sidebar/message_field_spec.js b/spec/javascripts/ide/components/commit_sidebar/message_field_spec.js
index 942cc19f46d..af67991eadd 100644
--- a/spec/javascripts/ide/components/commit_sidebar/message_field_spec.js
+++ b/spec/javascripts/ide/components/commit_sidebar/message_field_spec.js
@@ -36,8 +36,7 @@ describe('IDE commit message field', () => {
it('removed is-focused class on blur', done => {
vm.$el.querySelector('textarea').focus();
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
expect(vm.$el.querySelector('.is-focused')).not.toBeNull();
@@ -70,12 +69,12 @@ describe('IDE commit message field', () => {
it('does not highlight less than 50 characters', done => {
vm.text = 'text less than 50 chars';
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
expect(vm.$el.querySelector('.highlights span').textContent).toContain(
'text less than 50 chars',
);
+
expect(vm.$el.querySelector('mark').style.display).toBe('none');
})
.then(done)
@@ -86,12 +85,12 @@ describe('IDE commit message field', () => {
vm.text =
'text less than 50 chars that should not highlighted. text more than 50 should be highlighted';
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
expect(vm.$el.querySelector('.highlights span').textContent).toContain(
'text less than 50 chars that should not highlighte',
);
+
expect(vm.$el.querySelector('mark').style.display).not.toBe('none');
expect(vm.$el.querySelector('mark').textContent).toBe(
'd. text more than 50 should be highlighted',
@@ -106,8 +105,7 @@ describe('IDE commit message field', () => {
it('does not highlight body text less tan 72 characters', done => {
vm.text = 'subject line\nbody content';
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2);
expect(vm.$el.querySelectorAll('mark')[1].style.display).toBe('none');
@@ -120,8 +118,7 @@ describe('IDE commit message field', () => {
vm.text =
'subject line\nbody content that will be highlighted when it is more than 72 characters in length';
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2);
expect(vm.$el.querySelectorAll('mark')[1].style.display).not.toBe('none');
@@ -135,8 +132,7 @@ describe('IDE commit message field', () => {
vm.text =
'text less than 50 chars that should not highlighted\nbody content that will be highlighted when it is more than 72 characters in length';
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
expect(vm.$el.querySelectorAll('.highlights span').length).toBe(2);
expect(vm.$el.querySelectorAll('mark').length).toBe(2);
@@ -154,8 +150,7 @@ describe('IDE commit message field', () => {
it('updates transform of highlights', done => {
vm.text = 'subject line\n\n\n\n\n\n\n\n\n\n\nbody content';
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
vm.$el.querySelector('textarea').scrollTo(0, 50);
diff --git a/spec/javascripts/ide/components/file_finder/index_spec.js b/spec/javascripts/ide/components/file_finder/index_spec.js
index 4f208e946d2..4d934f92f72 100644
--- a/spec/javascripts/ide/components/file_finder/index_spec.js
+++ b/spec/javascripts/ide/components/file_finder/index_spec.js
@@ -85,8 +85,7 @@ describe('IDE File finder item spec', () => {
it('clear button resets searchText', done => {
vm.searchText = 'index';
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
vm.$el.querySelector('.dropdown-input-clear').click();
})
@@ -102,8 +101,7 @@ describe('IDE File finder item spec', () => {
spyOn(vm.$refs.searchInput, 'focus');
vm.searchText = 'index';
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
vm.$el.querySelector('.dropdown-input-clear').click();
})
@@ -178,8 +176,7 @@ describe('IDE File finder item spec', () => {
vm.searchText = 'test';
vm.$store.state.fileFindVisible = true;
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
vm.$store.state.fileFindVisible = false;
})
diff --git a/spec/javascripts/ide/components/file_row_extra_spec.js b/spec/javascripts/ide/components/file_row_extra_spec.js
index 60dabe28045..c93a939ad71 100644
--- a/spec/javascripts/ide/components/file_row_extra_spec.js
+++ b/spec/javascripts/ide/components/file_row_extra_spec.js
@@ -107,14 +107,14 @@ describe('IDE extra file row component', () => {
describe('changes file icon', () => {
it('hides when file is not changed', () => {
- expect(vm.$el.querySelector('.ide-file-changed-icon')).toBe(null);
+ expect(vm.$el.querySelector('.file-changed-icon')).toBe(null);
});
it('shows when file is changed', done => {
vm.file.changed = true;
vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ide-file-changed-icon')).not.toBe(null);
+ expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
done();
});
@@ -124,7 +124,7 @@ describe('IDE extra file row component', () => {
vm.file.staged = true;
vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ide-file-changed-icon')).not.toBe(null);
+ expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
done();
});
@@ -134,7 +134,7 @@ describe('IDE extra file row component', () => {
vm.file.tempFile = true;
vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ide-file-changed-icon')).not.toBe(null);
+ expect(vm.$el.querySelector('.file-changed-icon')).not.toBe(null);
done();
});
diff --git a/spec/javascripts/ide/components/ide_spec.js b/spec/javascripts/ide/components/ide_spec.js
index 49b8e934cdd..55f40be0e4e 100644
--- a/spec/javascripts/ide/components/ide_spec.js
+++ b/spec/javascripts/ide/components/ide_spec.js
@@ -29,7 +29,7 @@ describe('ide component', () => {
resetStore(vm.$store);
});
- it('does not render right right when no files open', () => {
+ it('does not render right when no files open', () => {
expect(vm.$el.querySelector('.panel-right')).toBeNull();
});
@@ -84,8 +84,7 @@ describe('ide component', () => {
it('calls toggleFileFinder on `t` key press', done => {
Mousetrap.trigger('t');
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
expect(vm.toggleFileFinder).toHaveBeenCalled();
})
@@ -96,8 +95,7 @@ describe('ide component', () => {
it('calls toggleFileFinder on `command+p` key press', done => {
Mousetrap.trigger('command+p');
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
expect(vm.toggleFileFinder).toHaveBeenCalled();
})
@@ -108,8 +106,7 @@ describe('ide component', () => {
it('calls toggleFileFinder on `ctrl+p` key press', done => {
Mousetrap.trigger('ctrl+p');
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
expect(vm.toggleFileFinder).toHaveBeenCalled();
})
diff --git a/spec/javascripts/ide/components/ide_status_bar_spec.js b/spec/javascripts/ide/components/ide_status_bar_spec.js
index 0e93c5193a1..ab032b4cb98 100644
--- a/spec/javascripts/ide/components/ide_status_bar_spec.js
+++ b/spec/javascripts/ide/components/ide_status_bar_spec.js
@@ -1,6 +1,7 @@
import Vue from 'vue';
import store from '~/ide/stores';
import ideStatusBar from '~/ide/components/ide_status_bar.vue';
+import { rightSidebarViews } from '~/ide/constants';
import { createComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
import { resetStore } from '../helpers';
import { projectData } from '../mock_data';
@@ -49,9 +50,11 @@ describe('ideStatusBar', () => {
expect(vm.commitAgeUpdate).not.toHaveBeenCalled();
jasmine.clock().tick(1100);
+
expect(vm.commitAgeUpdate.calls.count()).toEqual(1);
jasmine.clock().tick(1000);
+
expect(vm.commitAgeUpdate.calls.count()).toEqual(2);
});
});
@@ -64,7 +67,7 @@ describe('ideStatusBar', () => {
describe('pipeline status', () => {
it('opens right sidebar on clicking icon', done => {
- spyOn(vm, 'setRightPane');
+ spyOn(vm, 'openRightPane');
Vue.set(vm.$store.state.pipelines, 'latestPipeline', {
details: {
status: {
@@ -75,12 +78,11 @@ describe('ideStatusBar', () => {
},
});
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
vm.$el.querySelector('.ide-status-pipeline button').click();
- expect(vm.setRightPane).toHaveBeenCalledWith('pipelines-list');
+ expect(vm.openRightPane).toHaveBeenCalledWith(rightSidebarViews.pipelines);
})
.then(done)
.catch(done.fail);
diff --git a/spec/javascripts/ide/components/jobs/detail_spec.js b/spec/javascripts/ide/components/jobs/detail_spec.js
index 8f8d4b9709e..a4e6b81acba 100644
--- a/spec/javascripts/ide/components/jobs/detail_spec.js
+++ b/spec/javascripts/ide/components/jobs/detail_spec.js
@@ -109,8 +109,7 @@ describe('IDE jobs detail view', () => {
vm.scrollPos = 1;
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => vm.$el.querySelector('.btn-scroll').click())
.then(() => vm.$nextTick())
.then(() => {
diff --git a/spec/javascripts/ide/components/merge_requests/item_spec.js b/spec/javascripts/ide/components/merge_requests/item_spec.js
index 750948cae3c..155a247defb 100644
--- a/spec/javascripts/ide/components/merge_requests/item_spec.js
+++ b/spec/javascripts/ide/components/merge_requests/item_spec.js
@@ -29,7 +29,10 @@ describe('IDE merge request item', () => {
});
it('renders link with href', () => {
- const expectedHref = router.resolve(`/project/${vm.item.projectPathWithNamespace}/merge_requests/${vm.item.iid}`).href;
+ const expectedHref = router.resolve(
+ `/project/${vm.item.projectPathWithNamespace}/merge_requests/${vm.item.iid}`,
+ ).href;
+
expect(vm.$el).toMatch('a');
expect(vm.$el).toHaveAttr('href', expectedHref);
});
diff --git a/spec/javascripts/ide/components/merge_requests/list_spec.js b/spec/javascripts/ide/components/merge_requests/list_spec.js
index c761315444c..55e4f46d9ca 100644
--- a/spec/javascripts/ide/components/merge_requests/list_spec.js
+++ b/spec/javascripts/ide/components/merge_requests/list_spec.js
@@ -118,8 +118,9 @@ describe('IDE merge requests list', () => {
vm.$nextTick()
.then(() => {
const expectedSearchTypes = vm.$options.searchTypes.map(x => x.label);
- const renderedSearchTypes = Array.from(vm.$el.querySelectorAll('li'))
- .map(x => x.textContent.trim());
+ const renderedSearchTypes = Array.from(vm.$el.querySelectorAll('li')).map(x =>
+ x.textContent.trim(),
+ );
expect(renderedSearchTypes).toEqual(expectedSearchTypes);
})
diff --git a/spec/javascripts/ide/components/new_dropdown/index_spec.js b/spec/javascripts/ide/components/new_dropdown/index_spec.js
index 8a8cbd2cee4..83e530f0a6a 100644
--- a/spec/javascripts/ide/components/new_dropdown/index_spec.js
+++ b/spec/javascripts/ide/components/new_dropdown/index_spec.js
@@ -36,6 +36,7 @@ describe('new dropdown component', () => {
it('renders new file, upload and new directory links', () => {
const buttons = vm.$el.querySelectorAll('.dropdown-menu button');
+
expect(buttons[0].textContent.trim()).toBe('New file');
expect(buttons[1].textContent.trim()).toBe('Upload file');
expect(buttons[2].textContent.trim()).toBe('New directory');
diff --git a/spec/javascripts/ide/components/new_dropdown/upload_spec.js b/spec/javascripts/ide/components/new_dropdown/upload_spec.js
index 70b885ede26..878e17ac805 100644
--- a/spec/javascripts/ide/components/new_dropdown/upload_spec.js
+++ b/spec/javascripts/ide/components/new_dropdown/upload_spec.js
@@ -40,21 +40,10 @@ describe('new dropdown upload', () => {
describe('readFile', () => {
beforeEach(() => {
- spyOn(FileReader.prototype, 'readAsText');
spyOn(FileReader.prototype, 'readAsDataURL');
});
- it('calls readAsText for text files', () => {
- const file = {
- type: 'text/html',
- };
-
- vm.readFile(file);
-
- expect(FileReader.prototype.readAsText).toHaveBeenCalledWith(file);
- });
-
- it('calls readAsDataURL for non-text files', () => {
+ it('calls readAsDataURL for all files', () => {
const file = {
type: 'images/png',
};
@@ -66,32 +55,37 @@ describe('new dropdown upload', () => {
});
describe('createFile', () => {
- const target = {
- result: 'content',
+ const textTarget = {
+ result: 'base64,cGxhaW4gdGV4dA==',
};
const binaryTarget = {
- result: 'base64,base64content',
+ result: 'base64,w4I=',
+ };
+ const textFile = {
+ name: 'textFile',
+ type: 'text/plain',
};
- const file = {
- name: 'file',
+ const binaryFile = {
+ name: 'binaryFile',
+ type: 'image/png',
};
- it('creates new file', () => {
- vm.createFile(target, file, true);
+ it('creates file in plain text (without encoding) if the file content is plain text', () => {
+ vm.createFile(textTarget, textFile);
expect(vm.$emit).toHaveBeenCalledWith('create', {
- name: file.name,
+ name: textFile.name,
type: 'blob',
- content: target.result,
+ content: 'plain text',
base64: false,
});
});
it('splits content on base64 if binary', () => {
- vm.createFile(binaryTarget, file, false);
+ vm.createFile(binaryTarget, binaryFile);
expect(vm.$emit).toHaveBeenCalledWith('create', {
- name: file.name,
+ name: binaryFile.name,
type: 'blob',
content: binaryTarget.result.split('base64,')[1],
base64: true,
diff --git a/spec/javascripts/ide/components/panes/right_spec.js b/spec/javascripts/ide/components/panes/right_spec.js
index c75975d2af6..4899f850cf4 100644
--- a/spec/javascripts/ide/components/panes/right_spec.js
+++ b/spec/javascripts/ide/components/panes/right_spec.js
@@ -25,7 +25,8 @@ describe('IDE right pane', () => {
describe('active', () => {
it('renders merge request button as active', done => {
- vm.$store.state.rightPane = rightSidebarViews.mergeRequestInfo;
+ vm.$store.state.rightPane.isOpen = true;
+ vm.$store.state.rightPane.currentView = rightSidebarViews.mergeRequestInfo.name;
vm.$store.state.currentMergeRequestId = '123';
vm.$store.state.currentProjectId = 'gitlab-ce';
vm.$store.state.currentMergeRequestId = 1;
@@ -41,20 +42,21 @@ describe('IDE right pane', () => {
},
};
- vm.$nextTick(() => {
- expect(vm.$el.querySelector('.ide-sidebar-link.active')).not.toBe(null);
- expect(
- vm.$el.querySelector('.ide-sidebar-link.active').getAttribute('data-original-title'),
- ).toBe('Merge Request');
-
- done();
- });
+ vm.$nextTick()
+ .then(() => {
+ expect(vm.$el.querySelector('.ide-sidebar-link.active')).not.toBe(null);
+ expect(
+ vm.$el.querySelector('.ide-sidebar-link.active').getAttribute('data-original-title'),
+ ).toBe('Merge Request');
+ })
+ .then(done)
+ .catch(done.fail);
});
});
describe('click', () => {
beforeEach(() => {
- spyOn(vm, 'setRightPane');
+ spyOn(vm, 'open');
});
it('sets view to merge request', done => {
@@ -63,7 +65,7 @@ describe('IDE right pane', () => {
vm.$nextTick(() => {
vm.$el.querySelector('.ide-sidebar-link').click();
- expect(vm.setRightPane).toHaveBeenCalledWith(rightSidebarViews.mergeRequestInfo);
+ expect(vm.open).toHaveBeenCalledWith(rightSidebarViews.mergeRequestInfo);
done();
});
diff --git a/spec/javascripts/ide/components/preview/clientside_spec.js b/spec/javascripts/ide/components/preview/clientside_spec.js
index d6983f5a3b8..b9bf5c51ffe 100644
--- a/spec/javascripts/ide/components/preview/clientside_spec.js
+++ b/spec/javascripts/ide/components/preview/clientside_spec.js
@@ -59,8 +59,7 @@ describe('IDE clientside preview', () => {
}),
);
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => vm.initPreview())
.then(vm.$nextTick)
.then(done)
diff --git a/spec/javascripts/ide/components/repo_commit_section_spec.js b/spec/javascripts/ide/components/repo_commit_section_spec.js
index d09ccd7ac34..6c726c1e154 100644
--- a/spec/javascripts/ide/components/repo_commit_section_spec.js
+++ b/spec/javascripts/ide/components/repo_commit_section_spec.js
@@ -103,65 +103,6 @@ describe('RepoCommitSection', () => {
});
});
- it('adds changed files into staged files', done => {
- vm.$el.querySelector('.multi-file-discard-btn .btn').click();
- vm
- .$nextTick()
- .then(() => vm.$el.querySelector('.multi-file-discard-btn .btn').click())
- .then(vm.$nextTick)
- .then(() => {
- expect(vm.$el.querySelector('.ide-commit-list-container').textContent).toContain(
- 'There are no unstaged changes',
- );
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('stages a single file', done => {
- vm.$el.querySelector('.multi-file-discard-btn .btn').click();
-
- Vue.nextTick(() => {
- expect(
- vm.$el
- .querySelector('.ide-commit-list-container')
- .querySelectorAll('.multi-file-commit-list > li').length,
- ).toBe(1);
-
- done();
- });
- });
-
- it('discards a single file', done => {
- vm.$el.querySelector('.multi-file-commit-list li:first-child .js-modal-primary-action').click();
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.ide-commit-list-container').textContent).not.toContain('file1');
- expect(
- vm.$el
- .querySelector('.ide-commit-list-container')
- .querySelectorAll('.multi-file-commit-list > li').length,
- ).toBe(1);
-
- done();
- });
- });
-
- it('unstages a single file', done => {
- vm.$el
- .querySelectorAll('.multi-file-discard-btn')[2]
- .querySelector('.btn')
- .click();
-
- Vue.nextTick(() => {
- expect(
- vm.$el.querySelectorAll('.ide-commit-list-container')[1].querySelectorAll('li').length,
- ).toBe(1);
-
- done();
- });
- });
-
describe('mounted', () => {
it('opens last opened file', () => {
expect(store.state.openFiles.length).toBe(1);
diff --git a/spec/javascripts/ide/components/repo_editor_spec.js b/spec/javascripts/ide/components/repo_editor_spec.js
index 0e2e246defd..002b5a005b8 100644
--- a/spec/javascripts/ide/components/repo_editor_spec.js
+++ b/spec/javascripts/ide/components/repo_editor_spec.js
@@ -52,6 +52,7 @@ describe('RepoEditor', () => {
it('renders only an edit tab', done => {
Vue.nextTick(() => {
const tabs = vm.$el.querySelectorAll('.ide-mode-tabs .nav-links li');
+
expect(tabs.length).toBe(1);
expect(tabs[0].textContent.trim()).toBe('Edit');
@@ -72,6 +73,7 @@ describe('RepoEditor', () => {
it('renders an Edit and a Preview Tab', done => {
Vue.nextTick(() => {
const tabs = vm.$el.querySelectorAll('.ide-mode-tabs .nav-links li');
+
expect(tabs.length).toBe(2);
expect(tabs[0].textContent.trim()).toBe('Edit');
expect(tabs[1].textContent.trim()).toBe('Preview Markdown');
@@ -109,6 +111,7 @@ describe('RepoEditor', () => {
it('renders an Edit and a Preview Tab', done => {
Vue.nextTick(() => {
const tabs = vm.$el.querySelectorAll('.ide-mode-tabs .nav-links li');
+
expect(tabs.length).toBe(2);
expect(tabs[0].textContent.trim()).toBe('Review');
expect(tabs[1].textContent.trim()).toBe('Preview Markdown');
@@ -122,8 +125,7 @@ describe('RepoEditor', () => {
vm.file.path = `${vm.file.path}.md`;
vm.$store.state.entries[vm.file.path] = vm.file;
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
vm.$el.querySelectorAll('.ide-mode-tabs .nav-links a')[1].click();
})
@@ -294,8 +296,7 @@ describe('RepoEditor', () => {
it('calls updateDimensions when panelResizing is false', done => {
vm.$store.state.panelResizing = true;
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
vm.$store.state.panelResizing = false;
})
@@ -319,8 +320,8 @@ describe('RepoEditor', () => {
});
});
- it('calls updateDimensions when rightPane is updated', done => {
- vm.$store.state.rightPane = 'testing';
+ it('calls updateDimensions when rightPane is opened', done => {
+ vm.$store.state.rightPane.isOpen = true;
vm.$nextTick(() => {
expect(vm.editor.updateDimensions).toHaveBeenCalled();
@@ -363,8 +364,7 @@ describe('RepoEditor', () => {
vm.file.pending = true;
- vm
- .$nextTick()
+ vm.$nextTick()
.then(() => {
vm.file = file('testing');
diff --git a/spec/javascripts/ide/components/repo_loading_file_spec.js b/spec/javascripts/ide/components/repo_loading_file_spec.js
deleted file mode 100644
index 7c20b8302f9..00000000000
--- a/spec/javascripts/ide/components/repo_loading_file_spec.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import Vue from 'vue';
-import store from '~/ide/stores';
-import repoLoadingFile from '~/ide/components/repo_loading_file.vue';
-import { resetStore } from '../helpers';
-
-describe('RepoLoadingFile', () => {
- let vm;
-
- function createComponent() {
- const RepoLoadingFile = Vue.extend(repoLoadingFile);
-
- return new RepoLoadingFile({
- store,
- }).$mount();
- }
-
- function assertLines(lines) {
- lines.forEach((line, n) => {
- const index = n + 1;
- expect(line.classList.contains(`skeleton-line-${index}`)).toBeTruthy();
- });
- }
-
- function assertColumns(columns) {
- columns.forEach(column => {
- const container = column.querySelector('.animation-container');
- const lines = [...container.querySelectorAll(':scope > div')];
-
- expect(container).toBeTruthy();
- expect(lines.length).toEqual(3);
- assertLines(lines);
- });
- }
-
- afterEach(() => {
- vm.$destroy();
-
- resetStore(vm.$store);
- });
-
- it('renders 3 columns of animated LoC', () => {
- vm = createComponent();
- const columns = [...vm.$el.querySelectorAll('td')];
-
- expect(columns.length).toEqual(3);
- assertColumns(columns);
- });
-
- it('renders 1 column of animated LoC if isMini', done => {
- vm = createComponent();
- vm.$store.state.leftPanelCollapsed = true;
- vm.$store.state.openFiles.push('test');
-
- vm.$nextTick(() => {
- const columns = [...vm.$el.querySelectorAll('td')];
-
- expect(columns.length).toEqual(1);
- assertColumns(columns);
-
- done();
- });
- });
-});
diff --git a/spec/javascripts/ide/components/repo_tab_spec.js b/spec/javascripts/ide/components/repo_tab_spec.js
index 278a0753322..3b52f279bf2 100644
--- a/spec/javascripts/ide/components/repo_tab_spec.js
+++ b/spec/javascripts/ide/components/repo_tab_spec.js
@@ -93,13 +93,13 @@ describe('RepoTab', () => {
Vue.nextTick()
.then(() => {
- expect(vm.$el.querySelector('.ide-file-modified')).toBeNull();
+ expect(vm.$el.querySelector('.file-modified')).toBeNull();
vm.$el.dispatchEvent(new Event('mouseout'));
})
.then(Vue.nextTick)
.then(() => {
- expect(vm.$el.querySelector('.ide-file-modified')).not.toBeNull();
+ expect(vm.$el.querySelector('.file-modified')).not.toBeNull();
done();
})
diff --git a/spec/javascripts/ide/components/shared/tokened_input_spec.js b/spec/javascripts/ide/components/shared/tokened_input_spec.js
index 09940fe8c6a..b09bf760543 100644
--- a/spec/javascripts/ide/components/shared/tokened_input_spec.js
+++ b/spec/javascripts/ide/components/shared/tokened_input_spec.js
@@ -44,8 +44,7 @@ describe('IDE shared/TokenedInput', () => {
});
it('renders tokens', () => {
- const renderedTokens = getTokenElements(vm)
- .map(x => x.textContent.trim());
+ const renderedTokens = getTokenElements(vm).map(x => x.textContent.trim());
expect(renderedTokens).toEqual(TEST_TOKENS.map(x => x.label));
});
@@ -85,10 +84,12 @@ describe('IDE shared/TokenedInput', () => {
vm.value = '';
vm.onBackspace();
+
expect(vm.$emit).not.toHaveBeenCalled();
expect(vm.backspaceCount).toEqual(1);
vm.onBackspace();
+
expect(vm.$emit).toHaveBeenCalledWith('removeToken', TEST_TOKENS[TEST_TOKENS.length - 1]);
expect(vm.backspaceCount).toEqual(0);
});
diff --git a/spec/javascripts/ide/helpers.js b/spec/javascripts/ide/helpers.js
index 3ce9c9fcda1..7e107747346 100644
--- a/spec/javascripts/ide/helpers.js
+++ b/spec/javascripts/ide/helpers.js
@@ -6,6 +6,7 @@ import mergeRequestsState from '~/ide/stores/modules/merge_requests/state';
import pipelinesState from '~/ide/stores/modules/pipelines/state';
import branchesState from '~/ide/stores/modules/branches/state';
import fileTemplatesState from '~/ide/stores/modules/file_templates/state';
+import paneState from '~/ide/stores/modules/pane/state';
export const resetStore = store => {
const newState = {
@@ -15,6 +16,7 @@ export const resetStore = store => {
pipelines: pipelinesState(),
branches: branchesState(),
fileTemplates: fileTemplatesState(),
+ rightPane: paneState(),
};
store.replaceState(newState);
};
diff --git a/spec/javascripts/ide/stores/actions/file_spec.js b/spec/javascripts/ide/stores/actions/file_spec.js
index 1ca811e996b..7ddc734ff56 100644
--- a/spec/javascripts/ide/stores/actions/file_spec.js
+++ b/spec/javascripts/ide/stores/actions/file_spec.js
@@ -296,7 +296,7 @@ describe('IDE store file actions', () => {
.getFileData({ state: store.state, commit() {}, dispatch }, { path: localFile.path })
.then(() => {
expect(dispatch).toHaveBeenCalledWith('setErrorMessage', {
- text: 'An error occured whilst loading the file.',
+ text: 'An error occurred whilst loading the file.',
action: jasmine.any(Function),
actionText: 'Please try again',
actionPayload: {
@@ -408,7 +408,7 @@ describe('IDE store file actions', () => {
.then(done.fail)
.catch(() => {
expect(dispatch).toHaveBeenCalledWith('setErrorMessage', {
- text: 'An error occured whilst loading the file content.',
+ text: 'An error occurred whilst loading the file content.',
action: jasmine.any(Function),
actionText: 'Please try again',
actionPayload: {
diff --git a/spec/javascripts/ide/stores/actions/merge_request_spec.js b/spec/javascripts/ide/stores/actions/merge_request_spec.js
index 8564f04ce8a..9bfc7c397b8 100644
--- a/spec/javascripts/ide/stores/actions/merge_request_spec.js
+++ b/spec/javascripts/ide/stores/actions/merge_request_spec.js
@@ -82,7 +82,7 @@ describe('IDE store merge request actions', () => {
.then(done.fail)
.catch(() => {
expect(dispatch).toHaveBeenCalledWith('setErrorMessage', {
- text: 'An error occured whilst loading the merge request.',
+ text: 'An error occurred whilst loading the merge request.',
action: jasmine.any(Function),
actionText: 'Please try again',
actionPayload: {
@@ -155,7 +155,7 @@ describe('IDE store merge request actions', () => {
.then(done.fail)
.catch(() => {
expect(dispatch).toHaveBeenCalledWith('setErrorMessage', {
- text: 'An error occured whilst loading the merge request changes.',
+ text: 'An error occurred whilst loading the merge request changes.',
action: jasmine.any(Function),
actionText: 'Please try again',
actionPayload: {
@@ -225,7 +225,7 @@ describe('IDE store merge request actions', () => {
.then(done.fail)
.catch(() => {
expect(dispatch).toHaveBeenCalledWith('setErrorMessage', {
- text: 'An error occured whilst loading the merge request version data.',
+ text: 'An error occurred whilst loading the merge request version data.',
action: jasmine.any(Function),
actionText: 'Please try again',
actionPayload: {
@@ -262,16 +262,28 @@ describe('IDE store merge request actions', () => {
bar: {},
};
- spyOn(store, 'dispatch').and.callFake((type) => {
+ const originalDispatch = store.dispatch;
+
+ spyOn(store, 'dispatch').and.callFake((type, payload) => {
switch (type) {
case 'getMergeRequestData':
return Promise.resolve(testMergeRequest);
case 'getMergeRequestChanges':
return Promise.resolve(testMergeRequestChanges);
- default:
+ case 'getFiles':
+ case 'getMergeRequestVersions':
+ case 'getBranchData':
+ case 'setFileMrChange':
return Promise.resolve();
+ default:
+ return originalDispatch(type, payload);
}
});
+ spyOn(service, 'getFileData').and.callFake(() =>
+ Promise.resolve({
+ headers: {},
+ }),
+ );
});
it('dispatch actions for merge request data', done => {
@@ -280,14 +292,20 @@ describe('IDE store merge request actions', () => {
expect(store.dispatch.calls.allArgs()).toEqual([
['getMergeRequestData', mr],
['setCurrentBranchId', testMergeRequest.source_branch],
- ['getBranchData', {
- projectId: mr.projectId,
- branchId: testMergeRequest.source_branch,
- }],
- ['getFiles', {
- projectId: mr.projectId,
- branchId: testMergeRequest.source_branch,
- }],
+ [
+ 'getBranchData',
+ {
+ projectId: mr.projectId,
+ branchId: testMergeRequest.source_branch,
+ },
+ ],
+ [
+ 'getFiles',
+ {
+ projectId: mr.projectId,
+ branchId: testMergeRequest.source_branch,
+ },
+ ],
['getMergeRequestVersions', mr],
['getMergeRequestChanges', mr],
]);
@@ -297,25 +315,39 @@ describe('IDE store merge request actions', () => {
});
it('updates activity bar view and gets file data, if changes are found', done => {
+ store.state.entries.foo = {
+ url: 'test',
+ };
+ store.state.entries.bar = {
+ url: 'test',
+ };
+
testMergeRequestChanges.changes = [
- { new_path: 'foo' },
- { new_path: 'bar' },
+ { new_path: 'foo', path: 'foo' },
+ { new_path: 'bar', path: 'bar' },
];
openMergeRequest(store, mr)
.then(() => {
- expect(store.dispatch).toHaveBeenCalledWith('updateActivityBarView', activityBarViews.review);
+ expect(store.dispatch).toHaveBeenCalledWith(
+ 'updateActivityBarView',
+ activityBarViews.review,
+ );
testMergeRequestChanges.changes.forEach((change, i) => {
expect(store.dispatch).toHaveBeenCalledWith('setFileMrChange', {
file: store.state.entries[change.new_path],
mrChange: change,
});
+
expect(store.dispatch).toHaveBeenCalledWith('getFileData', {
path: change.new_path,
makeFileActive: i === 0,
+ openFile: true,
});
});
+
+ expect(store.state.openFiles.length).toBe(testMergeRequestChanges.changes.length);
})
.then(done)
.catch(done.fail);
@@ -334,7 +366,6 @@ describe('IDE store merge request actions', () => {
})
.then(done)
.catch(done.fail);
-
});
});
});
diff --git a/spec/javascripts/ide/stores/actions/project_spec.js b/spec/javascripts/ide/stores/actions/project_spec.js
index 667e3e0a7ef..7d8c9edd965 100644
--- a/spec/javascripts/ide/stores/actions/project_spec.js
+++ b/spec/javascripts/ide/stores/actions/project_spec.js
@@ -270,7 +270,10 @@ describe('IDE store project actions', () => {
it('does not handle tree entry action, if entry is pending', done => {
openBranch(store, { ...branch, basePath: 'foo/bar-pending' })
.then(() => {
- expect(store.dispatch).not.toHaveBeenCalledWith('handleTreeEntryAction', jasmine.anything());
+ expect(store.dispatch).not.toHaveBeenCalledWith(
+ 'handleTreeEntryAction',
+ jasmine.anything(),
+ );
})
.then(done)
.catch(done.fail);
diff --git a/spec/javascripts/ide/stores/actions/tree_spec.js b/spec/javascripts/ide/stores/actions/tree_spec.js
index 9f098eded08..bd41e87bf0e 100644
--- a/spec/javascripts/ide/stores/actions/tree_spec.js
+++ b/spec/javascripts/ide/stores/actions/tree_spec.js
@@ -71,6 +71,7 @@ describe('Multi-file store tree actions', () => {
.dispatch('getFiles', basicCallParameters)
.then(() => {
projectTree = store.state.trees['abcproject/master'];
+
expect(projectTree.tree.length).toBe(2);
expect(projectTree.tree[0].type).toBe('tree');
expect(projectTree.tree[0].tree[1].name).toBe('fileinfolder.js');
@@ -142,7 +143,7 @@ describe('Multi-file store tree actions', () => {
.then(done.fail)
.catch(() => {
expect(dispatch).toHaveBeenCalledWith('setErrorMessage', {
- text: 'An error occured whilst loading all the files.',
+ text: 'An error occurred whilst loading all the files.',
action: jasmine.any(Function),
actionText: 'Please try again',
actionPayload: { projectId: 'abc/def', branchId: 'master-testing' },
diff --git a/spec/javascripts/ide/stores/actions_spec.js b/spec/javascripts/ide/stores/actions_spec.js
index c9a1158a14e..df291ade3f7 100644
--- a/spec/javascripts/ide/stores/actions_spec.js
+++ b/spec/javascripts/ide/stores/actions_spec.js
@@ -279,8 +279,6 @@ describe('Multi-file store actions', () => {
});
});
- describe('popHistoryState', () => {});
-
describe('scrollToTab', () => {
it('focuses the current active element', done => {
document.body.innerHTML +=
diff --git a/spec/javascripts/ide/stores/modules/branches/actions_spec.js b/spec/javascripts/ide/stores/modules/branches/actions_spec.js
index 010f56af03b..9c61ba3d1a6 100644
--- a/spec/javascripts/ide/stores/modules/branches/actions_spec.js
+++ b/spec/javascripts/ide/stores/modules/branches/actions_spec.js
@@ -59,8 +59,7 @@ describe('IDE branches actions', () => {
});
describe('receiveBranchesError', () => {
- it('should should commit error', done => {
-
+ it('should commit error', done => {
testAction(
receiveBranchesError,
{ search: TEST_SEARCH },
diff --git a/spec/javascripts/ide/stores/modules/file_templates/actions_spec.js b/spec/javascripts/ide/stores/modules/file_templates/actions_spec.js
index c29dd9f0d06..734233100ab 100644
--- a/spec/javascripts/ide/stores/modules/file_templates/actions_spec.js
+++ b/spec/javascripts/ide/stores/modules/file_templates/actions_spec.js
@@ -69,11 +69,17 @@ describe('IDE file templates actions', () => {
describe('fetchTemplateTypes', () => {
describe('success', () => {
+ let nextPage;
+
beforeEach(() => {
- mock.onGet(/api\/(.*)\/templates\/licenses/).replyOnce(200, [
- {
- name: 'MIT',
- },
+ mock.onGet(/api\/(.*)\/templates\/licenses/).replyOnce(() => [
+ 200,
+ [
+ {
+ name: 'MIT',
+ },
+ ],
+ { 'X-NEXT-PAGE': nextPage },
]);
});
@@ -116,6 +122,38 @@ describe('IDE file templates actions', () => {
done,
);
});
+
+ it('dispatches actions for next page', done => {
+ nextPage = '2';
+ state.selectedTemplateType = {
+ key: 'licenses',
+ };
+
+ testAction(
+ actions.fetchTemplateTypes,
+ null,
+ state,
+ [],
+ [
+ {
+ type: 'requestTemplateTypes',
+ },
+ {
+ type: 'receiveTemplateTypesSuccess',
+ payload: [
+ {
+ name: 'MIT',
+ },
+ ],
+ },
+ {
+ type: 'fetchTemplateTypes',
+ payload: 2,
+ },
+ ],
+ done,
+ );
+ });
});
describe('error', () => {
diff --git a/spec/javascripts/ide/stores/modules/file_templates/mutations_spec.js b/spec/javascripts/ide/stores/modules/file_templates/mutations_spec.js
index a51527d699f..8e0e3ae99a1 100644
--- a/spec/javascripts/ide/stores/modules/file_templates/mutations_spec.js
+++ b/spec/javascripts/ide/stores/modules/file_templates/mutations_spec.js
@@ -49,6 +49,14 @@ describe('IDE file templates mutations', () => {
expect(state.selectedTemplateType).toBe('type');
});
+
+ it('clears templates', () => {
+ state.templates = ['test'];
+
+ mutations[types.SET_SELECTED_TEMPLATE_TYPE](state, 'type');
+
+ expect(state.templates).toEqual([]);
+ });
});
describe(types.SET_UPDATE_SUCCESS, () => {
diff --git a/spec/javascripts/ide/stores/modules/merge_requests/actions_spec.js b/spec/javascripts/ide/stores/modules/merge_requests/actions_spec.js
index 62699143a91..9e2ba1f5ce9 100644
--- a/spec/javascripts/ide/stores/modules/merge_requests/actions_spec.js
+++ b/spec/javascripts/ide/stores/modules/merge_requests/actions_spec.js
@@ -14,10 +14,14 @@ import testAction from '../../../../helpers/vuex_action_helper';
describe('IDE merge requests actions', () => {
let mockedState;
+ let mockedRootState;
let mock;
beforeEach(() => {
mockedState = state();
+ mockedRootState = {
+ currentProjectId: 7,
+ };
mock = new MockAdapter(axios);
});
@@ -39,7 +43,7 @@ describe('IDE merge requests actions', () => {
});
describe('receiveMergeRequestsError', () => {
- it('should should commit error', done => {
+ it('should commit error', done => {
testAction(
receiveMergeRequestsError,
{ type: 'created', search: '' },
@@ -86,13 +90,16 @@ describe('IDE merge requests actions', () => {
describe('success', () => {
beforeEach(() => {
- mock.onGet(/\/api\/v4\/merge_requests(.*)$/).replyOnce(200, mergeRequests);
+ mock.onGet(/\/api\/v4\/merge_requests\/?/).replyOnce(200, mergeRequests);
});
it('calls API with params', () => {
const apiSpy = spyOn(axios, 'get').and.callThrough();
- fetchMergeRequests({ dispatch() {}, state: mockedState }, { type: 'created' });
+ fetchMergeRequests(
+ { dispatch() {}, state: mockedState, rootState: mockedRootState },
+ { type: 'created' },
+ );
expect(apiSpy).toHaveBeenCalledWith(jasmine.anything(), {
params: {
@@ -107,7 +114,7 @@ describe('IDE merge requests actions', () => {
const apiSpy = spyOn(axios, 'get').and.callThrough();
fetchMergeRequests(
- { dispatch() {}, state: mockedState },
+ { dispatch() {}, state: mockedState, rootState: mockedRootState },
{ type: 'created', search: 'testing search' },
);
@@ -139,6 +146,49 @@ describe('IDE merge requests actions', () => {
});
});
+ describe('success without type', () => {
+ beforeEach(() => {
+ mock.onGet(/\/api\/v4\/projects\/.+\/merge_requests\/?$/).replyOnce(200, mergeRequests);
+ });
+
+ it('calls API with project', () => {
+ const apiSpy = spyOn(axios, 'get').and.callThrough();
+
+ fetchMergeRequests(
+ { dispatch() {}, state: mockedState, rootState: mockedRootState },
+ { type: null, search: 'testing search' },
+ );
+
+ expect(apiSpy).toHaveBeenCalledWith(
+ jasmine.stringMatching(`projects/${mockedRootState.currentProjectId}/merge_requests`),
+ {
+ params: {
+ state: 'opened',
+ search: 'testing search',
+ },
+ },
+ );
+ });
+
+ it('dispatches success with received data', done => {
+ testAction(
+ fetchMergeRequests,
+ { type: null },
+ { ...mockedState, ...mockedRootState },
+ [],
+ [
+ { type: 'requestMergeRequests' },
+ { type: 'resetMergeRequests' },
+ {
+ type: 'receiveMergeRequestsSuccess',
+ payload: mergeRequests,
+ },
+ ],
+ done,
+ );
+ });
+ });
+
describe('error', () => {
beforeEach(() => {
mock.onGet(/\/api\/v4\/merge_requests(.*)$/).replyOnce(500);
diff --git a/spec/javascripts/ide/stores/modules/pane/actions_spec.js b/spec/javascripts/ide/stores/modules/pane/actions_spec.js
new file mode 100644
index 00000000000..799bc89a0c3
--- /dev/null
+++ b/spec/javascripts/ide/stores/modules/pane/actions_spec.js
@@ -0,0 +1,66 @@
+import * as actions from '~/ide/stores/modules/pane/actions';
+import * as types from '~/ide/stores/modules/pane/mutation_types';
+import testAction from 'spec/helpers/vuex_action_helper';
+
+describe('IDE pane module actions', () => {
+ const TEST_VIEW = { name: 'test' };
+ const TEST_VIEW_KEEP_ALIVE = { name: 'test-keep-alive', keepAlive: true };
+
+ describe('toggleOpen', () => {
+ it('dispatches open if closed', done => {
+ testAction(
+ actions.toggleOpen,
+ TEST_VIEW,
+ { isOpen: false },
+ [],
+ [{ type: 'open', payload: TEST_VIEW }],
+ done,
+ );
+ });
+
+ it('dispatches close if opened', done => {
+ testAction(actions.toggleOpen, TEST_VIEW, { isOpen: true }, [], [{ type: 'close' }], done);
+ });
+ });
+
+ describe('open', () => {
+ it('commits SET_OPEN', done => {
+ testAction(actions.open, null, {}, [{ type: types.SET_OPEN, payload: true }], [], done);
+ });
+
+ it('commits SET_CURRENT_VIEW if view is given', done => {
+ testAction(
+ actions.open,
+ TEST_VIEW,
+ {},
+ [
+ { type: types.SET_OPEN, payload: true },
+ { type: types.SET_CURRENT_VIEW, payload: TEST_VIEW.name },
+ ],
+ [],
+ done,
+ );
+ });
+
+ it('commits KEEP_ALIVE_VIEW if keepAlive is true', done => {
+ testAction(
+ actions.open,
+ TEST_VIEW_KEEP_ALIVE,
+ {},
+ [
+ { type: types.SET_OPEN, payload: true },
+ { type: types.SET_CURRENT_VIEW, payload: TEST_VIEW_KEEP_ALIVE.name },
+ { type: types.KEEP_ALIVE_VIEW, payload: TEST_VIEW_KEEP_ALIVE.name },
+ ],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('close', () => {
+ it('commits SET_OPEN', done => {
+ testAction(actions.close, null, {}, [{ type: types.SET_OPEN, payload: false }], [], done);
+ });
+ });
+});
diff --git a/spec/javascripts/ide/stores/modules/pane/getters_spec.js b/spec/javascripts/ide/stores/modules/pane/getters_spec.js
new file mode 100644
index 00000000000..8a213323de0
--- /dev/null
+++ b/spec/javascripts/ide/stores/modules/pane/getters_spec.js
@@ -0,0 +1,55 @@
+import * as getters from '~/ide/stores/modules/pane/getters';
+import state from '~/ide/stores/modules/pane/state';
+
+describe('IDE pane module getters', () => {
+ const TEST_VIEW = 'test-view';
+ const TEST_KEEP_ALIVE_VIEWS = {
+ [TEST_VIEW]: true,
+ };
+
+ describe('isActiveView', () => {
+ it('returns true if given view matches currentView', () => {
+ const result = getters.isActiveView({ currentView: 'A' })('A');
+
+ expect(result).toBe(true);
+ });
+
+ it('returns false if given view does not match currentView', () => {
+ const result = getters.isActiveView({ currentView: 'A' })('B');
+
+ expect(result).toBe(false);
+ });
+ });
+
+ describe('isAliveView', () => {
+ it('returns true if given view is in keepAliveViews', () => {
+ const result = getters.isAliveView({ keepAliveViews: TEST_KEEP_ALIVE_VIEWS }, {})(TEST_VIEW);
+
+ expect(result).toBe(true);
+ });
+
+ it('returns true if given view is active view and open', () => {
+ const result = getters.isAliveView(
+ { ...state(), isOpen: true },
+ { isActiveView: () => true },
+ )(TEST_VIEW);
+
+ expect(result).toBe(true);
+ });
+
+ it('returns false if given view is active view and closed', () => {
+ const result = getters.isAliveView(state(), { isActiveView: () => true })(TEST_VIEW);
+
+ expect(result).toBe(false);
+ });
+
+ it('returns false if given view is not activeView', () => {
+ const result = getters.isAliveView(
+ { ...state(), isOpen: true },
+ { isActiveView: () => false },
+ )(TEST_VIEW);
+
+ expect(result).toBe(false);
+ });
+ });
+});
diff --git a/spec/javascripts/ide/stores/modules/pane/mutations_spec.js b/spec/javascripts/ide/stores/modules/pane/mutations_spec.js
new file mode 100644
index 00000000000..b5fcd35912e
--- /dev/null
+++ b/spec/javascripts/ide/stores/modules/pane/mutations_spec.js
@@ -0,0 +1,42 @@
+import state from '~/ide/stores/modules/pane/state';
+import mutations from '~/ide/stores/modules/pane/mutations';
+import * as types from '~/ide/stores/modules/pane/mutation_types';
+
+describe('IDE pane module mutations', () => {
+ const TEST_VIEW = 'test-view';
+ let mockedState;
+
+ beforeEach(() => {
+ mockedState = state();
+ });
+
+ describe('SET_OPEN', () => {
+ it('sets isOpen', () => {
+ mockedState.isOpen = false;
+
+ mutations[types.SET_OPEN](mockedState, true);
+
+ expect(mockedState.isOpen).toBe(true);
+ });
+ });
+
+ describe('SET_CURRENT_VIEW', () => {
+ it('sets currentView', () => {
+ mockedState.currentView = null;
+
+ mutations[types.SET_CURRENT_VIEW](mockedState, TEST_VIEW);
+
+ expect(mockedState.currentView).toEqual(TEST_VIEW);
+ });
+ });
+
+ describe('KEEP_ALIVE_VIEW', () => {
+ it('adds entry to keepAliveViews', () => {
+ mutations[types.KEEP_ALIVE_VIEW](mockedState, TEST_VIEW);
+
+ expect(mockedState.keepAliveViews).toEqual({
+ [TEST_VIEW]: true,
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/ide/stores/modules/pipelines/actions_spec.js b/spec/javascripts/ide/stores/modules/pipelines/actions_spec.js
index 91edb388791..0937ee38390 100644
--- a/spec/javascripts/ide/stores/modules/pipelines/actions_spec.js
+++ b/spec/javascripts/ide/stores/modules/pipelines/actions_spec.js
@@ -77,7 +77,7 @@ describe('IDE pipelines actions', () => {
{
type: 'setErrorMessage',
payload: {
- text: 'An error occured whilst fetching the latest pipline.',
+ text: 'An error occurred whilst fetching the latest pipeline.',
action: jasmine.any(Function),
actionText: 'Please try again',
actionPayload: null,
@@ -223,7 +223,7 @@ describe('IDE pipelines actions', () => {
{
type: 'setErrorMessage',
payload: {
- text: 'An error occured whilst loading the pipelines jobs.',
+ text: 'An error occurred whilst loading the pipelines jobs.',
action: jasmine.anything(),
actionText: 'Please try again',
actionPayload: { id: 1 },
@@ -315,29 +315,29 @@ describe('IDE pipelines actions', () => {
'job',
mockedState,
[{ type: types.SET_DETAIL_JOB, payload: 'job' }],
- [{ type: 'setRightPane', payload: 'jobs-detail' }],
+ [{ type: 'rightPane/open', payload: rightSidebarViews.jobsDetail }],
done,
);
});
- it('dispatches setRightPane as pipeline when job is null', done => {
+ it('dispatches rightPane/open as pipeline when job is null', done => {
testAction(
setDetailJob,
null,
mockedState,
[{ type: types.SET_DETAIL_JOB, payload: null }],
- [{ type: 'setRightPane', payload: rightSidebarViews.pipelines }],
+ [{ type: 'rightPane/open', payload: rightSidebarViews.pipelines }],
done,
);
});
- it('dispatches setRightPane as job', done => {
+ it('dispatches rightPane/open as job', done => {
testAction(
setDetailJob,
'job',
mockedState,
[{ type: types.SET_DETAIL_JOB, payload: 'job' }],
- [{ type: 'setRightPane', payload: rightSidebarViews.jobsDetail }],
+ [{ type: 'rightPane/open', payload: rightSidebarViews.jobsDetail }],
done,
);
});
@@ -360,7 +360,7 @@ describe('IDE pipelines actions', () => {
{
type: 'setErrorMessage',
payload: {
- text: 'An error occured whilst fetching the job trace.',
+ text: 'An error occurred whilst fetching the job trace.',
action: jasmine.any(Function),
actionText: 'Please try again',
actionPayload: null,
diff --git a/spec/javascripts/ide/stores/mutations/merge_request_spec.js b/spec/javascripts/ide/stores/mutations/merge_request_spec.js
index f724bf464f5..e30ca22022f 100644
--- a/spec/javascripts/ide/stores/mutations/merge_request_spec.js
+++ b/spec/javascripts/ide/stores/mutations/merge_request_spec.js
@@ -45,6 +45,7 @@ describe('IDE store merge request mutations', () => {
});
const newMr = localState.projects.abcproject.mergeRequests[1];
+
expect(newMr.changes.diff).toBe('abc');
});
});
@@ -58,6 +59,7 @@ describe('IDE store merge request mutations', () => {
});
const newMr = localState.projects.abcproject.mergeRequests[1];
+
expect(newMr.versions.length).toBe(1);
expect(newMr.versions[0].id).toBe(123);
});
diff --git a/spec/javascripts/image_diff/helpers/badge_helper_spec.js b/spec/javascripts/image_diff/helpers/badge_helper_spec.js
index ce3add1fd90..8ea05203d00 100644
--- a/spec/javascripts/image_diff/helpers/badge_helper_spec.js
+++ b/spec/javascripts/image_diff/helpers/badge_helper_spec.js
@@ -90,6 +90,7 @@ describe('badge helper', () => {
it('should create icon comment button', () => {
const iconEl = buttonEl.querySelector('svg');
+
expect(iconEl).toBeDefined();
});
});
diff --git a/spec/javascripts/image_diff/helpers/comment_indicator_helper_spec.js b/spec/javascripts/image_diff/helpers/comment_indicator_helper_spec.js
index a284b981d2a..8e3e7f1222e 100644
--- a/spec/javascripts/image_diff/helpers/comment_indicator_helper_spec.js
+++ b/spec/javascripts/image_diff/helpers/comment_indicator_helper_spec.js
@@ -29,10 +29,12 @@ describe('commentIndicatorHelper', () => {
it('should contain image-comment-dark svg', () => {
const svgEl = buttonEl.querySelector('svg');
+
expect(svgEl).toBeDefined();
const svgLink = svgEl.querySelector('use').getAttribute('xlink:href');
- expect(svgLink.indexOf('image-comment-dark') !== -1).toEqual(true);
+
+ expect(svgLink.indexOf('image-comment-dark')).not.toBe(-1);
});
});
});
@@ -40,6 +42,7 @@ describe('commentIndicatorHelper', () => {
describe('removeCommentIndicator', () => {
it('should return removed false if there is no comment-indicator', () => {
const result = commentIndicatorHelper.removeCommentIndicator(containerEl);
+
expect(result.removed).toEqual(false);
});
@@ -84,6 +87,7 @@ describe('commentIndicatorHelper', () => {
it('should set commentIndicator coordinates', () => {
const commentIndicatorEl = containerEl.querySelector('.comment-indicator');
+
expect(commentIndicatorEl.style.left).toEqual(`${coordinate.x}px`);
expect(commentIndicatorEl.style.top).toEqual(`${coordinate.y}px`);
});
@@ -96,6 +100,7 @@ describe('commentIndicatorHelper', () => {
it('should addCommentIndicator', () => {
const buttonEl = containerEl.querySelector('.comment-indicator');
+
expect(buttonEl).toBeDefined();
expect(buttonEl.style.left).toEqual(`${coordinate.x}px`);
expect(buttonEl.style.top).toEqual(`${coordinate.y}px`);
diff --git a/spec/javascripts/image_diff/helpers/dom_helper_spec.js b/spec/javascripts/image_diff/helpers/dom_helper_spec.js
index 8dde924e8ae..ffe712af2dd 100644
--- a/spec/javascripts/image_diff/helpers/dom_helper_spec.js
+++ b/spec/javascripts/image_diff/helpers/dom_helper_spec.js
@@ -92,6 +92,7 @@ describe('domHelper', () => {
it('should force formEl to display none', () => {
const formEl = element.querySelector('.discussion-form');
+
expect(formEl.style.display).toEqual('none');
});
});
@@ -111,6 +112,7 @@ describe('domHelper', () => {
it('should force formEl to display block', () => {
const formEl = element.querySelector('.discussion-form');
+
expect(formEl.style.display).toEqual('block');
});
});
diff --git a/spec/javascripts/image_diff/helpers/utils_helper_spec.js b/spec/javascripts/image_diff/helpers/utils_helper_spec.js
index 31949c39d9c..6f62ee3f93b 100644
--- a/spec/javascripts/image_diff/helpers/utils_helper_spec.js
+++ b/spec/javascripts/image_diff/helpers/utils_helper_spec.js
@@ -5,13 +5,7 @@ import ImageBadge from '~/image_diff/image_badge';
import * as mockData from '../mock_data';
describe('utilsHelper', () => {
- const {
- noteId,
- discussionId,
- image,
- imageProperties,
- imageMeta,
- } = mockData;
+ const { noteId, discussionId, image, imageProperties, imageMeta } = mockData;
describe('resizeCoordinatesToImageElement', () => {
let result;
@@ -57,6 +51,7 @@ describe('utilsHelper', () => {
it('should return actual image properties', () => {
const { actual } = result;
+
expect(actual.x).toEqual(imageMeta.x);
expect(actual.y).toEqual(imageMeta.y);
expect(actual.width).toEqual(imageMeta.width);
@@ -65,6 +60,7 @@ describe('utilsHelper', () => {
it('should return browser image properties', () => {
const { browser } = result;
+
expect(browser.x).toBeDefined();
expect(browser.y).toBeDefined();
expect(browser.width).toBeDefined();
@@ -106,6 +102,7 @@ describe('utilsHelper', () => {
const result = utilsHelper.getTargetSelection(event);
const { browser } = result;
+
expect(browser.x).toEqual(event.offsetX);
expect(browser.y).toEqual(event.offsetY);
expect(browser.width).toEqual(imageProperties.width);
@@ -117,6 +114,7 @@ describe('utilsHelper', () => {
const result = utilsHelper.getTargetSelection(event);
const { actual } = result;
+
expect(actual.x).toEqual(100);
expect(actual.y).toEqual(100);
expect(actual.width).toEqual(imageProperties.naturalWidth);
@@ -127,24 +125,28 @@ describe('utilsHelper', () => {
it('should return x = 0 if x < 0', () => {
const event = generateEvent(-5, 50);
const result = utilsHelper.getTargetSelection(event);
+
expect(result.browser.x).toEqual(0);
});
it('should return x = width if x > width', () => {
const event = generateEvent(1000, 50);
const result = utilsHelper.getTargetSelection(event);
+
expect(result.browser.x).toEqual(imageProperties.width);
});
it('should return y = 0 if y < 0', () => {
const event = generateEvent(50, -10);
const result = utilsHelper.getTargetSelection(event);
+
expect(result.browser.y).toEqual(0);
});
it('should return y = height if y > height', () => {
const event = generateEvent(50, 1000);
const result = utilsHelper.getTargetSelection(event);
+
expect(result.browser.y).toEqual(imageProperties.height);
});
});
@@ -178,6 +180,7 @@ describe('utilsHelper', () => {
`;
const imageDiff = utilsHelper.initImageDiff(fileEl, true, false);
+
expect(ImageDiff.prototype.init).toHaveBeenCalled();
expect(imageDiff.canCreateNote).toEqual(true);
expect(imageDiff.renderCommentBadge).toEqual(false);
@@ -191,6 +194,7 @@ describe('utilsHelper', () => {
`;
const replacedImageDiff = utilsHelper.initImageDiff(fileEl, false, true);
+
expect(ReplacedImageDiff.prototype.init).toHaveBeenCalled();
expect(replacedImageDiff.canCreateNote).toEqual(false);
expect(replacedImageDiff.renderCommentBadge).toEqual(true);
diff --git a/spec/javascripts/image_diff/image_badge_spec.js b/spec/javascripts/image_diff/image_badge_spec.js
index 87f98fc0926..2b23dce5d30 100644
--- a/spec/javascripts/image_diff/image_badge_spec.js
+++ b/spec/javascripts/image_diff/image_badge_spec.js
@@ -10,11 +10,14 @@ describe('ImageBadge', () => {
};
it('should save actual property', () => {
- const imageBadge = new ImageBadge(Object.assign({}, options, {
- actual: imageMeta,
- }));
+ const imageBadge = new ImageBadge(
+ Object.assign({}, options, {
+ actual: imageMeta,
+ }),
+ );
const { actual } = imageBadge;
+
expect(actual.x).toEqual(imageMeta.x);
expect(actual.y).toEqual(imageMeta.y);
expect(actual.width).toEqual(imageMeta.width);
@@ -22,11 +25,14 @@ describe('ImageBadge', () => {
});
it('should save browser property', () => {
- const imageBadge = new ImageBadge(Object.assign({}, options, {
- browser: imageMeta,
- }));
+ const imageBadge = new ImageBadge(
+ Object.assign({}, options, {
+ browser: imageMeta,
+ }),
+ );
const { browser } = imageBadge;
+
expect(browser.x).toEqual(imageMeta.x);
expect(browser.y).toEqual(imageMeta.y);
expect(browser.width).toEqual(imageMeta.width);
@@ -35,11 +41,13 @@ describe('ImageBadge', () => {
it('should save noteId', () => {
const imageBadge = new ImageBadge(options);
+
expect(imageBadge.noteId).toEqual(noteId);
});
it('should save discussionId', () => {
const imageBadge = new ImageBadge(options);
+
expect(imageBadge.discussionId).toEqual(discussionId);
});
@@ -52,6 +60,7 @@ describe('ImageBadge', () => {
it('should return defaultimageMeta if actual property is not provided', () => {
const { actual } = imageBadge;
+
expect(actual.x).toEqual(0);
expect(actual.y).toEqual(0);
expect(actual.width).toEqual(0);
@@ -60,6 +69,7 @@ describe('ImageBadge', () => {
it('should return defaultimageMeta if browser property is not provided', () => {
const { browser } = imageBadge;
+
expect(browser.x).toEqual(0);
expect(browser.y).toEqual(0);
expect(browser.width).toEqual(0);
@@ -73,9 +83,11 @@ describe('ImageBadge', () => {
});
it('should generate browser property', () => {
- const imageBadge = new ImageBadge(Object.assign({}, options, {
- imageEl: document.createElement('img'),
- }));
+ const imageBadge = new ImageBadge(
+ Object.assign({}, options, {
+ imageEl: document.createElement('img'),
+ }),
+ );
expect(imageDiffHelper.resizeCoordinatesToImageElement).toHaveBeenCalled();
expect(imageBadge.browser).toEqual(true);
diff --git a/spec/javascripts/image_diff/image_diff_spec.js b/spec/javascripts/image_diff/image_diff_spec.js
index 346282328c7..21e7b8e2e9b 100644
--- a/spec/javascripts/image_diff/image_diff_spec.js
+++ b/spec/javascripts/image_diff/image_diff_spec.js
@@ -117,23 +117,15 @@ describe('ImageDiff', () => {
it('should register click event delegation to js-diff-notes-toggle', () => {
element.querySelector('.js-diff-notes-toggle').click();
+
expect(imageDiffHelper.toggleCollapsed).toHaveBeenCalled();
});
it('should register click event delegation to comment-indicator', () => {
element.querySelector('.comment-indicator').click();
- expect(imageDiffHelper.commentIndicatorOnClick).toHaveBeenCalled();
- });
- });
- describe('image loaded', () => {
- beforeEach(() => {
- spyOn(imageUtility, 'isImageLoaded').and.returnValue(true);
- imageDiff = new ImageDiff(element);
- imageDiff.imageEl = imageEl;
+ expect(imageDiffHelper.commentIndicatorOnClick).toHaveBeenCalled();
});
-
- it('should renderBadges', () => {});
});
describe('image not loaded', () => {
@@ -147,6 +139,7 @@ describe('ImageDiff', () => {
it('should registers load eventListener', () => {
const loadEvent = new Event('load');
imageEl.dispatchEvent(loadEvent);
+
expect(imageDiff.renderBadges).toHaveBeenCalled();
});
});
@@ -164,24 +157,28 @@ describe('ImageDiff', () => {
it('should register click.imageDiff event', () => {
const event = new CustomEvent('click.imageDiff');
element.dispatchEvent(event);
+
expect(imageDiff.imageClicked).toHaveBeenCalled();
});
it('should register blur.imageDiff event', () => {
const event = new CustomEvent('blur.imageDiff');
element.dispatchEvent(event);
+
expect(imageDiffHelper.removeCommentIndicator).toHaveBeenCalled();
});
it('should register addBadge.imageDiff event', () => {
const event = new CustomEvent('addBadge.imageDiff');
element.dispatchEvent(event);
+
expect(imageDiff.addBadge).toHaveBeenCalled();
});
it('should register removeBadge.imageDiff event', () => {
const event = new CustomEvent('removeBadge.imageDiff');
element.dispatchEvent(event);
+
expect(imageDiff.removeBadge).toHaveBeenCalled();
});
});
@@ -197,6 +194,7 @@ describe('ImageDiff', () => {
it('should not register click.imageDiff event', () => {
const event = new CustomEvent('click.imageDiff');
element.dispatchEvent(event);
+
expect(imageDiff.imageClicked).not.toHaveBeenCalled();
});
});
@@ -240,6 +238,7 @@ describe('ImageDiff', () => {
it('should call renderBadge for each discussionEl', () => {
const discussionEls = element.querySelectorAll('.note-container .discussion-notes .notes');
+
expect(imageDiff.renderBadge.calls.count()).toEqual(discussionEls.length);
});
});
@@ -336,6 +335,7 @@ describe('ImageDiff', () => {
describe('cascade badge count', () => {
it('should update next imageBadgeEl value', () => {
const imageBadgeEls = imageDiff.imageFrameEl.querySelectorAll('.badge');
+
expect(imageBadgeEls[0].innerText).toEqual('1');
expect(imageBadgeEls[1].innerText).toEqual('2');
expect(imageBadgeEls.length).toEqual(2);
diff --git a/spec/javascripts/image_diff/init_discussion_tab_spec.js b/spec/javascripts/image_diff/init_discussion_tab_spec.js
index 7c447d6f70d..7cacc45ab62 100644
--- a/spec/javascripts/image_diff/init_discussion_tab_spec.js
+++ b/spec/javascripts/image_diff/init_discussion_tab_spec.js
@@ -11,7 +11,7 @@ describe('initDiscussionTab', () => {
`);
});
- it('should pass canCreateNote as false to initImageDiff', (done) => {
+ it('should pass canCreateNote as false to initImageDiff', done => {
spyOn(imageDiffHelper, 'initImageDiff').and.callFake((diffFileEl, canCreateNote) => {
expect(canCreateNote).toEqual(false);
done();
@@ -20,11 +20,13 @@ describe('initDiscussionTab', () => {
initDiscussionTab();
});
- it('should pass renderCommentBadge as true to initImageDiff', (done) => {
- spyOn(imageDiffHelper, 'initImageDiff').and.callFake((diffFileEl, canCreateNote, renderCommentBadge) => {
- expect(renderCommentBadge).toEqual(true);
- done();
- });
+ it('should pass renderCommentBadge as true to initImageDiff', done => {
+ spyOn(imageDiffHelper, 'initImageDiff').and.callFake(
+ (diffFileEl, canCreateNote, renderCommentBadge) => {
+ expect(renderCommentBadge).toEqual(true);
+ done();
+ },
+ );
initDiscussionTab();
});
@@ -32,6 +34,7 @@ describe('initDiscussionTab', () => {
it('should call initImageDiff for each diffFileEls', () => {
spyOn(imageDiffHelper, 'initImageDiff').and.callFake(() => {});
initDiscussionTab();
+
expect(imageDiffHelper.initImageDiff.calls.count()).toEqual(2);
});
});
diff --git a/spec/javascripts/image_diff/replaced_image_diff_spec.js b/spec/javascripts/image_diff/replaced_image_diff_spec.js
index 5f8cd7c531a..62e7c8b6c6a 100644
--- a/spec/javascripts/image_diff/replaced_image_diff_spec.js
+++ b/spec/javascripts/image_diff/replaced_image_diff_spec.js
@@ -37,16 +37,28 @@ describe('ReplacedImageDiff', () => {
function setupImageFrameEls() {
replacedImageDiff.imageFrameEls = [];
- replacedImageDiff.imageFrameEls[viewTypes.TWO_UP] = element.querySelector('.two-up .js-image-frame');
- replacedImageDiff.imageFrameEls[viewTypes.SWIPE] = element.querySelector('.swipe .js-image-frame');
- replacedImageDiff.imageFrameEls[viewTypes.ONION_SKIN] = element.querySelector('.onion-skin .js-image-frame');
+ replacedImageDiff.imageFrameEls[viewTypes.TWO_UP] = element.querySelector(
+ '.two-up .js-image-frame',
+ );
+ replacedImageDiff.imageFrameEls[viewTypes.SWIPE] = element.querySelector(
+ '.swipe .js-image-frame',
+ );
+ replacedImageDiff.imageFrameEls[viewTypes.ONION_SKIN] = element.querySelector(
+ '.onion-skin .js-image-frame',
+ );
}
function setupViewModesEls() {
replacedImageDiff.viewModesEls = [];
- replacedImageDiff.viewModesEls[viewTypes.TWO_UP] = element.querySelector('.view-modes-menu .two-up');
- replacedImageDiff.viewModesEls[viewTypes.SWIPE] = element.querySelector('.view-modes-menu .swipe');
- replacedImageDiff.viewModesEls[viewTypes.ONION_SKIN] = element.querySelector('.view-modes-menu .onion-skin');
+ replacedImageDiff.viewModesEls[viewTypes.TWO_UP] = element.querySelector(
+ '.view-modes-menu .two-up',
+ );
+ replacedImageDiff.viewModesEls[viewTypes.SWIPE] = element.querySelector(
+ '.view-modes-menu .swipe',
+ );
+ replacedImageDiff.viewModesEls[viewTypes.ONION_SKIN] = element.querySelector(
+ '.view-modes-menu .onion-skin',
+ );
}
function setupImageEls() {
@@ -58,6 +70,7 @@ describe('ReplacedImageDiff', () => {
it('should extend ImageDiff', () => {
replacedImageDiff = new ReplacedImageDiff(element);
+
expect(replacedImageDiff instanceof ImageDiff).toEqual(true);
});
@@ -72,18 +85,36 @@ describe('ReplacedImageDiff', () => {
it('should set imageFrameEls', () => {
const { imageFrameEls } = replacedImageDiff;
+
expect(imageFrameEls).toBeDefined();
- expect(imageFrameEls[viewTypes.TWO_UP]).toEqual(element.querySelector('.two-up .js-image-frame'));
- expect(imageFrameEls[viewTypes.SWIPE]).toEqual(element.querySelector('.swipe .js-image-frame'));
- expect(imageFrameEls[viewTypes.ONION_SKIN]).toEqual(element.querySelector('.onion-skin .js-image-frame'));
+ expect(imageFrameEls[viewTypes.TWO_UP]).toEqual(
+ element.querySelector('.two-up .js-image-frame'),
+ );
+
+ expect(imageFrameEls[viewTypes.SWIPE]).toEqual(
+ element.querySelector('.swipe .js-image-frame'),
+ );
+
+ expect(imageFrameEls[viewTypes.ONION_SKIN]).toEqual(
+ element.querySelector('.onion-skin .js-image-frame'),
+ );
});
it('should set viewModesEls', () => {
const { viewModesEls } = replacedImageDiff;
+
expect(viewModesEls).toBeDefined();
- expect(viewModesEls[viewTypes.TWO_UP]).toEqual(element.querySelector('.view-modes-menu .two-up'));
- expect(viewModesEls[viewTypes.SWIPE]).toEqual(element.querySelector('.view-modes-menu .swipe'));
- expect(viewModesEls[viewTypes.ONION_SKIN]).toEqual(element.querySelector('.view-modes-menu .onion-skin'));
+ expect(viewModesEls[viewTypes.TWO_UP]).toEqual(
+ element.querySelector('.view-modes-menu .two-up'),
+ );
+
+ expect(viewModesEls[viewTypes.SWIPE]).toEqual(
+ element.querySelector('.view-modes-menu .swipe'),
+ );
+
+ expect(viewModesEls[viewTypes.ONION_SKIN]).toEqual(
+ element.querySelector('.view-modes-menu .onion-skin'),
+ );
});
it('should generateImageEls', () => {
@@ -97,6 +128,7 @@ describe('ReplacedImageDiff', () => {
describe('currentView', () => {
it('should set currentView', () => {
replacedImageDiff.init(viewTypes.ONION_SKIN);
+
expect(replacedImageDiff.currentView).toEqual(viewTypes.ONION_SKIN);
});
@@ -121,6 +153,7 @@ describe('ReplacedImageDiff', () => {
it('should set imageEls', () => {
replacedImageDiff.generateImageEls();
const { imageEls } = replacedImageDiff;
+
expect(imageEls).toBeDefined();
expect(imageEls[viewTypes.TWO_UP]).toEqual(element.querySelector('.two-up img'));
expect(imageEls[viewTypes.SWIPE]).toEqual(element.querySelector('.swipe img'));
@@ -138,11 +171,12 @@ describe('ReplacedImageDiff', () => {
it('should call super.bindEvents', () => {
replacedImageDiff.bindEvents();
+
expect(ImageDiff.prototype.bindEvents).toHaveBeenCalled();
});
- it('should register click eventlistener to 2-up view mode', (done) => {
- spyOn(ReplacedImageDiff.prototype, 'changeView').and.callFake((viewMode) => {
+ it('should register click eventlistener to 2-up view mode', done => {
+ spyOn(ReplacedImageDiff.prototype, 'changeView').and.callFake(viewMode => {
expect(viewMode).toEqual(viewTypes.TWO_UP);
done();
});
@@ -151,8 +185,8 @@ describe('ReplacedImageDiff', () => {
replacedImageDiff.viewModesEls[viewTypes.TWO_UP].click();
});
- it('should register click eventlistener to swipe view mode', (done) => {
- spyOn(ReplacedImageDiff.prototype, 'changeView').and.callFake((viewMode) => {
+ it('should register click eventlistener to swipe view mode', done => {
+ spyOn(ReplacedImageDiff.prototype, 'changeView').and.callFake(viewMode => {
expect(viewMode).toEqual(viewTypes.SWIPE);
done();
});
@@ -161,8 +195,8 @@ describe('ReplacedImageDiff', () => {
replacedImageDiff.viewModesEls[viewTypes.SWIPE].click();
});
- it('should register click eventlistener to onion skin view mode', (done) => {
- spyOn(ReplacedImageDiff.prototype, 'changeView').and.callFake((viewMode) => {
+ it('should register click eventlistener to onion skin view mode', done => {
+ spyOn(ReplacedImageDiff.prototype, 'changeView').and.callFake(viewMode => {
expect(viewMode).toEqual(viewTypes.SWIPE);
done();
});
@@ -184,6 +218,7 @@ describe('ReplacedImageDiff', () => {
expect(replacedImageDiff.imageEl).toEqual(element.querySelector('.two-up img'));
replacedImageDiff.currentView = viewTypes.SWIPE;
+
expect(replacedImageDiff.imageEl).toEqual(element.querySelector('.swipe img'));
});
});
@@ -196,10 +231,15 @@ describe('ReplacedImageDiff', () => {
});
it('should return imageFrameEl based on currentView', () => {
- expect(replacedImageDiff.imageFrameEl).toEqual(element.querySelector('.two-up .js-image-frame'));
+ expect(replacedImageDiff.imageFrameEl).toEqual(
+ element.querySelector('.two-up .js-image-frame'),
+ );
replacedImageDiff.currentView = viewTypes.ONION_SKIN;
- expect(replacedImageDiff.imageFrameEl).toEqual(element.querySelector('.onion-skin .js-image-frame'));
+
+ expect(replacedImageDiff.imageFrameEl).toEqual(
+ element.querySelector('.onion-skin .js-image-frame'),
+ );
});
});
});
@@ -248,6 +288,7 @@ describe('ReplacedImageDiff', () => {
it('should call renderNewView', () => {
jasmine.clock().tick(251);
+
expect(replacedImageDiff.renderNewView).toHaveBeenCalled();
});
});
@@ -284,7 +325,7 @@ describe('ReplacedImageDiff', () => {
setupImageFrameEls();
});
- it('should pass showCommentIndicator normalized indicator values', (done) => {
+ it('should pass showCommentIndicator normalized indicator values', done => {
spyOn(imageDiffHelper, 'showCommentIndicator').and.callFake(() => {});
spyOn(imageDiffHelper, 'resizeCoordinatesToImageElement').and.callFake((imageEl, meta) => {
expect(meta.x).toEqual(indicator.x);
@@ -296,15 +337,17 @@ describe('ReplacedImageDiff', () => {
replacedImageDiff.renderNewView(indicator);
});
- it('should call showCommentIndicator', (done) => {
+ it('should call showCommentIndicator', done => {
const normalized = {
normalized: true,
};
spyOn(imageDiffHelper, 'resizeCoordinatesToImageElement').and.returnValue(normalized);
- spyOn(imageDiffHelper, 'showCommentIndicator').and.callFake((imageFrameEl, normalizedIndicator) => {
- expect(normalizedIndicator).toEqual(normalized);
- done();
- });
+ spyOn(imageDiffHelper, 'showCommentIndicator').and.callFake(
+ (imageFrameEl, normalizedIndicator) => {
+ expect(normalizedIndicator).toEqual(normalized);
+ done();
+ },
+ );
replacedImageDiff.renderNewView(indicator);
});
});
diff --git a/spec/javascripts/importer_status_spec.js b/spec/javascripts/importer_status_spec.js
index 63cdb3d5114..e7f195ed57c 100644
--- a/spec/javascripts/importer_status_spec.js
+++ b/spec/javascripts/importer_status_spec.js
@@ -35,38 +35,43 @@ describe('Importer Status', () => {
});
});
- it('sets table row to active after post request', (done) => {
+ it('sets table row to active after post request', done => {
mock.onPost(importUrl).reply(200, {
id: 1,
full_path: '/full_path',
});
- instance.addToImport({
- currentTarget: document.querySelector('.js-add-to-import'),
- })
- .then(() => {
- expect(document.querySelector('tr').classList.contains('table-active')).toEqual(true);
- done();
- })
- .catch(done.fail);
+ instance
+ .addToImport({
+ currentTarget: document.querySelector('.js-add-to-import'),
+ })
+ .then(() => {
+ expect(document.querySelector('tr').classList.contains('table-active')).toEqual(true);
+ done();
+ })
+ .catch(done.fail);
});
- it('shows error message after failed POST request', (done) => {
+ it('shows error message after failed POST request', done => {
appendSetFixtures('<div class="flash-container"></div>');
mock.onPost(importUrl).reply(422, {
errors: 'You forgot your lunch',
});
- instance.addToImport({
- currentTarget: document.querySelector('.js-add-to-import'),
- })
- .then(() => {
- const flashMessage = document.querySelector('.flash-text');
- expect(flashMessage.textContent.trim()).toEqual('An error occurred while importing project: You forgot your lunch');
- done();
- })
- .catch(done.fail);
+ instance
+ .addToImport({
+ currentTarget: document.querySelector('.js-add-to-import'),
+ })
+ .then(() => {
+ const flashMessage = document.querySelector('.flash-text');
+
+ expect(flashMessage.textContent.trim()).toEqual(
+ 'An error occurred while importing project: You forgot your lunch',
+ );
+ done();
+ })
+ .catch(done.fail);
});
});
@@ -92,14 +97,17 @@ describe('Importer Status', () => {
});
function setupMock(importStatus) {
- mock.onGet(jobsUrl).reply(200, [{
- id: 1,
- import_status: importStatus,
- }]);
+ mock.onGet(jobsUrl).reply(200, [
+ {
+ id: 1,
+ import_status: importStatus,
+ },
+ ]);
}
function expectJobStatus(done, status) {
- instance.autoUpdate()
+ instance
+ .autoUpdate()
.then(() => {
expect(document.querySelector('#project_1').innerText.trim()).toEqual(status);
done();
@@ -107,22 +115,22 @@ describe('Importer Status', () => {
.catch(done.fail);
}
- it('sets the job status to done', (done) => {
+ it('sets the job status to done', done => {
setupMock('finished');
expectJobStatus(done, 'Done');
});
- it('sets the job status to scheduled', (done) => {
+ it('sets the job status to scheduled', done => {
setupMock('scheduled');
expectJobStatus(done, 'Scheduled');
});
- it('sets the job status to started', (done) => {
+ it('sets the job status to started', done => {
setupMock('started');
expectJobStatus(done, 'Started');
});
- it('sets the job status to custom status', (done) => {
+ it('sets the job status to custom status', done => {
setupMock('custom status');
expectJobStatus(done, 'custom status');
});
diff --git a/spec/javascripts/integrations/integration_settings_form_spec.js b/spec/javascripts/integrations/integration_settings_form_spec.js
index e07343810d2..4f4c9a7b463 100644
--- a/spec/javascripts/integrations/integration_settings_form_spec.js
+++ b/spec/javascripts/integrations/integration_settings_form_spec.js
@@ -68,21 +68,27 @@ describe('IntegrationSettingsForm', () => {
integrationSettingsForm.canTestService = true;
integrationSettingsForm.toggleSubmitBtnLabel(true);
- expect(integrationSettingsForm.$submitBtnLabel.text()).toEqual('Test settings and save changes');
+
+ expect(integrationSettingsForm.$submitBtnLabel.text()).toEqual(
+ 'Test settings and save changes',
+ );
});
it('should set Save button label to "Save changes" when either serviceActive or canTestService (or both) is `false`', () => {
integrationSettingsForm.canTestService = false;
integrationSettingsForm.toggleSubmitBtnLabel(false);
+
expect(integrationSettingsForm.$submitBtnLabel.text()).toEqual('Save changes');
integrationSettingsForm.toggleSubmitBtnLabel(true);
+
expect(integrationSettingsForm.$submitBtnLabel.text()).toEqual('Save changes');
integrationSettingsForm.canTestService = true;
integrationSettingsForm.toggleSubmitBtnLabel(false);
+
expect(integrationSettingsForm.$submitBtnLabel.text()).toEqual('Save changes');
});
});
@@ -127,8 +133,9 @@ describe('IntegrationSettingsForm', () => {
mock.restore();
});
- it('should make an ajax request with provided `formData`', (done) => {
- integrationSettingsForm.testSettings(formData)
+ it('should make an ajax request with provided `formData`', done => {
+ integrationSettingsForm
+ .testSettings(formData)
.then(() => {
expect(axios.put).toHaveBeenCalledWith(integrationSettingsForm.testEndPoint, formData);
@@ -137,7 +144,7 @@ describe('IntegrationSettingsForm', () => {
.catch(done.fail);
});
- it('should show error Flash with `Save anyway` action if ajax request responds with error in test', (done) => {
+ it('should show error Flash with `Save anyway` action if ajax request responds with error in test', done => {
const errorMessage = 'Test failed.';
mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
error: true,
@@ -146,19 +153,32 @@ describe('IntegrationSettingsForm', () => {
test_failed: true,
});
- integrationSettingsForm.testSettings(formData)
+ integrationSettingsForm
+ .testSettings(formData)
.then(() => {
const $flashContainer = $('.flash-container');
- expect($flashContainer.find('.flash-text').text().trim()).toEqual('Test failed. some error');
+
+ expect(
+ $flashContainer
+ .find('.flash-text')
+ .text()
+ .trim(),
+ ).toEqual('Test failed. some error');
+
expect($flashContainer.find('.flash-action')).toBeDefined();
- expect($flashContainer.find('.flash-action').text().trim()).toEqual('Save anyway');
+ expect(
+ $flashContainer
+ .find('.flash-action')
+ .text()
+ .trim(),
+ ).toEqual('Save anyway');
done();
})
.catch(done.fail);
});
- it('should not show error Flash with `Save anyway` action if ajax request responds with error in validation', (done) => {
+ it('should not show error Flash with `Save anyway` action if ajax request responds with error in validation', done => {
const errorMessage = 'Validations failed.';
mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
error: true,
@@ -167,26 +187,40 @@ describe('IntegrationSettingsForm', () => {
test_failed: false,
});
- integrationSettingsForm.testSettings(formData)
+ integrationSettingsForm
+ .testSettings(formData)
.then(() => {
const $flashContainer = $('.flash-container');
- expect($flashContainer.find('.flash-text').text().trim()).toEqual('Validations failed. some error');
+
+ expect(
+ $flashContainer
+ .find('.flash-text')
+ .text()
+ .trim(),
+ ).toEqual('Validations failed. some error');
+
expect($flashContainer.find('.flash-action')).toBeDefined();
- expect($flashContainer.find('.flash-action').text().trim()).toEqual('');
+ expect(
+ $flashContainer
+ .find('.flash-action')
+ .text()
+ .trim(),
+ ).toEqual('');
done();
})
.catch(done.fail);
});
- it('should submit form if ajax request responds without any error in test', (done) => {
+ it('should submit form if ajax request responds without any error in test', done => {
spyOn(integrationSettingsForm.$form, 'submit');
mock.onPut(integrationSettingsForm.testEndPoint).reply(200, {
error: false,
});
- integrationSettingsForm.testSettings(formData)
+ integrationSettingsForm
+ .testSettings(formData)
.then(() => {
expect(integrationSettingsForm.$form.submit).toHaveBeenCalled();
@@ -195,7 +229,7 @@ describe('IntegrationSettingsForm', () => {
.catch(done.fail);
});
- it('should submit form when clicked on `Save anyway` action of error Flash', (done) => {
+ it('should submit form when clicked on `Save anyway` action of error Flash', done => {
spyOn(integrationSettingsForm.$form, 'submit');
const errorMessage = 'Test failed.';
@@ -205,9 +239,11 @@ describe('IntegrationSettingsForm', () => {
test_failed: true,
});
- integrationSettingsForm.testSettings(formData)
+ integrationSettingsForm
+ .testSettings(formData)
.then(() => {
const $flashAction = $('.flash-container .flash-action');
+
expect($flashAction).toBeDefined();
$flashAction.get(0).click();
@@ -220,26 +256,32 @@ describe('IntegrationSettingsForm', () => {
.catch(done.fail);
});
- it('should show error Flash if ajax request failed', (done) => {
+ it('should show error Flash if ajax request failed', done => {
const errorMessage = 'Something went wrong on our end.';
mock.onPut(integrationSettingsForm.testEndPoint).networkError();
- integrationSettingsForm.testSettings(formData)
+ integrationSettingsForm
+ .testSettings(formData)
.then(() => {
- expect($('.flash-container .flash-text').text().trim()).toEqual(errorMessage);
+ expect(
+ $('.flash-container .flash-text')
+ .text()
+ .trim(),
+ ).toEqual(errorMessage);
done();
})
.catch(done.fail);
});
- it('should always call `toggleSubmitBtnState` with `false` once request is completed', (done) => {
+ it('should always call `toggleSubmitBtnState` with `false` once request is completed', done => {
mock.onPut(integrationSettingsForm.testEndPoint).networkError();
spyOn(integrationSettingsForm, 'toggleSubmitBtnState');
- integrationSettingsForm.testSettings(formData)
+ integrationSettingsForm
+ .testSettings(formData)
.then(() => {
expect(integrationSettingsForm.toggleSubmitBtnState).toHaveBeenCalledWith(false);
diff --git a/spec/javascripts/issuable_spec.js b/spec/javascripts/issuable_spec.js
index 57bf746f080..25543053eba 100644
--- a/spec/javascripts/issuable_spec.js
+++ b/spec/javascripts/issuable_spec.js
@@ -8,6 +8,7 @@ describe('Issuable', () => {
describe('initBulkUpdate', () => {
it('should not set bulkUpdateSidebar', () => {
Issuable = new IssuableIndex('issue_');
+
expect(Issuable.bulkUpdateSidebar).not.toBeDefined();
});
@@ -17,6 +18,7 @@ describe('Issuable', () => {
document.body.appendChild(element);
Issuable = new IssuableIndex('issue_');
+
expect(Issuable.bulkUpdateSidebar).toBeDefined();
});
});
@@ -47,7 +49,7 @@ describe('Issuable', () => {
mock.restore();
});
- it('should send request to reset email token', (done) => {
+ it('should send request to reset email token', done => {
spyOn(axios, 'put').and.callThrough();
document.querySelector('.incoming-email-token-reset').click();
@@ -60,4 +62,3 @@ describe('Issuable', () => {
});
});
});
-
diff --git a/spec/javascripts/issuable_suggestions/components/app_spec.js b/spec/javascripts/issuable_suggestions/components/app_spec.js
new file mode 100644
index 00000000000..7bb8e26b81a
--- /dev/null
+++ b/spec/javascripts/issuable_suggestions/components/app_spec.js
@@ -0,0 +1,96 @@
+import { shallowMount } from '@vue/test-utils';
+import App from '~/issuable_suggestions/components/app.vue';
+import Suggestion from '~/issuable_suggestions/components/item.vue';
+
+describe('Issuable suggestions app component', () => {
+ let vm;
+
+ function createComponent(search = 'search') {
+ vm = shallowMount(App, {
+ propsData: {
+ search,
+ projectPath: 'project',
+ },
+ });
+ }
+
+ afterEach(() => {
+ vm.destroy();
+ });
+
+ it('does not render with empty search', () => {
+ createComponent('');
+
+ expect(vm.isVisible()).toBe(false);
+ });
+
+ describe('with data', () => {
+ let data;
+
+ beforeEach(() => {
+ data = { issues: [{ id: 1 }, { id: 2 }] };
+ });
+
+ it('renders component', () => {
+ createComponent();
+ vm.setData(data);
+
+ expect(vm.isEmpty()).toBe(false);
+ });
+
+ it('does not render with empty search', () => {
+ createComponent('');
+ vm.setData(data);
+
+ expect(vm.isVisible()).toBe(false);
+ });
+
+ it('does not render when loading', () => {
+ createComponent();
+ vm.setData({
+ ...data,
+ loading: 1,
+ });
+
+ expect(vm.isVisible()).toBe(false);
+ });
+
+ it('does not render with empty issues data', () => {
+ createComponent();
+ vm.setData({ issues: [] });
+
+ expect(vm.isVisible()).toBe(false);
+ });
+
+ it('renders list of issues', () => {
+ createComponent();
+ vm.setData(data);
+
+ expect(vm.findAll(Suggestion).length).toBe(2);
+ });
+
+ it('adds margin class to first item', () => {
+ createComponent();
+ vm.setData(data);
+
+ expect(
+ vm
+ .findAll('li')
+ .at(0)
+ .is('.append-bottom-default'),
+ ).toBe(true);
+ });
+
+ it('does not add margin class to last item', () => {
+ createComponent();
+ vm.setData(data);
+
+ expect(
+ vm
+ .findAll('li')
+ .at(1)
+ .is('.append-bottom-default'),
+ ).toBe(false);
+ });
+ });
+});
diff --git a/spec/javascripts/issuable_suggestions/components/item_spec.js b/spec/javascripts/issuable_suggestions/components/item_spec.js
new file mode 100644
index 00000000000..7bd1fe678f4
--- /dev/null
+++ b/spec/javascripts/issuable_suggestions/components/item_spec.js
@@ -0,0 +1,139 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlTooltip, GlLink } from '@gitlab/ui';
+import Icon from '~/vue_shared/components/icon.vue';
+import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
+import Suggestion from '~/issuable_suggestions/components/item.vue';
+import mockData from '../mock_data';
+
+describe('Issuable suggestions suggestion component', () => {
+ let vm;
+
+ function createComponent(suggestion = {}) {
+ vm = shallowMount(Suggestion, {
+ propsData: {
+ suggestion: {
+ ...mockData(),
+ ...suggestion,
+ },
+ },
+ });
+ }
+
+ afterEach(() => {
+ vm.destroy();
+ });
+
+ it('renders title', () => {
+ createComponent();
+
+ expect(vm.text()).toContain('Test issue');
+ });
+
+ it('renders issue link', () => {
+ createComponent();
+
+ const link = vm.find(GlLink);
+
+ expect(link.attributes('href')).toBe(`${gl.TEST_HOST}/test/issue/1`);
+ });
+
+ it('renders IID', () => {
+ createComponent();
+
+ expect(vm.text()).toContain('#1');
+ });
+
+ describe('opened state', () => {
+ it('renders icon', () => {
+ createComponent();
+
+ const icon = vm.find(Icon);
+
+ expect(icon.props('name')).toBe('issue-open-m');
+ });
+
+ it('renders created timeago', () => {
+ createComponent({
+ closedAt: '',
+ });
+
+ const tooltip = vm.find(GlTooltip);
+
+ expect(tooltip.find('.d-block').text()).toContain('Opened');
+ expect(tooltip.text()).toContain('3 days ago');
+ });
+ });
+
+ describe('closed state', () => {
+ it('renders icon', () => {
+ createComponent({
+ state: 'closed',
+ });
+
+ const icon = vm.find(Icon);
+
+ expect(icon.props('name')).toBe('issue-close');
+ });
+
+ it('renders closed timeago', () => {
+ createComponent();
+
+ const tooltip = vm.find(GlTooltip);
+
+ expect(tooltip.find('.d-block').text()).toContain('Opened');
+ expect(tooltip.text()).toContain('1 day ago');
+ });
+ });
+
+ describe('author', () => {
+ it('renders author info', () => {
+ createComponent();
+
+ const link = vm.findAll(GlLink).at(1);
+
+ expect(link.text()).toContain('Author Name');
+ expect(link.text()).toContain('@author.username');
+ });
+
+ it('renders author image', () => {
+ createComponent();
+
+ const image = vm.find(UserAvatarImage);
+
+ expect(image.props('imgSrc')).toBe(`${gl.TEST_HOST}/avatar`);
+ });
+ });
+
+ describe('counts', () => {
+ it('renders upvotes count', () => {
+ createComponent();
+
+ const count = vm.findAll('.suggestion-counts span').at(0);
+
+ expect(count.text()).toContain('1');
+ expect(count.find(Icon).props('name')).toBe('thumb-up');
+ });
+
+ it('renders notes count', () => {
+ createComponent();
+
+ const count = vm.findAll('.suggestion-counts span').at(1);
+
+ expect(count.text()).toContain('2');
+ expect(count.find(Icon).props('name')).toBe('comment');
+ });
+ });
+
+ describe('confidential', () => {
+ it('renders confidential icon', () => {
+ createComponent({
+ confidential: true,
+ });
+
+ const icon = vm.find(Icon);
+
+ expect(icon.props('name')).toBe('eye-slash');
+ expect(icon.attributes('data-original-title')).toBe('Confidential');
+ });
+ });
+});
diff --git a/spec/javascripts/issuable_suggestions/mock_data.js b/spec/javascripts/issuable_suggestions/mock_data.js
new file mode 100644
index 00000000000..4f0f9ef8d62
--- /dev/null
+++ b/spec/javascripts/issuable_suggestions/mock_data.js
@@ -0,0 +1,26 @@
+function getDate(daysMinus) {
+ const today = new Date();
+ today.setDate(today.getDate() - daysMinus);
+
+ return today.toISOString();
+}
+
+export default () => ({
+ id: 1,
+ iid: 1,
+ state: 'opened',
+ upvotes: 1,
+ userNotesCount: 2,
+ closedAt: getDate(1),
+ createdAt: getDate(3),
+ updatedAt: getDate(2),
+ confidential: false,
+ webUrl: `${gl.TEST_HOST}/test/issue/1`,
+ title: 'Test issue',
+ author: {
+ avatarUrl: `${gl.TEST_HOST}/avatar`,
+ name: 'Author Name',
+ username: 'author.username',
+ webUrl: `${gl.TEST_HOST}/author`,
+ },
+});
diff --git a/spec/javascripts/issue_show/components/app_spec.js b/spec/javascripts/issue_show/components/app_spec.js
index 36328382448..2bd1b3996dc 100644
--- a/spec/javascripts/issue_show/components/app_spec.js
+++ b/spec/javascripts/issue_show/components/app_spec.js
@@ -11,10 +11,7 @@ function formatText(text) {
return text.trim().replace(/\s\s+/g, ' ');
}
-const REALTIME_REQUEST_STACK = [
- issueShowData.initialRequest,
- issueShowData.secondRequest,
-];
+const REALTIME_REQUEST_STACK = [issueShowData.initialRequest, issueShowData.secondRequest];
describe('Issuable output', () => {
let mock;
@@ -23,7 +20,7 @@ describe('Issuable output', () => {
document.body.innerHTML = '<span id="task_status"></span>';
- beforeEach((done) => {
+ beforeEach(done => {
spyOn(eventHub, '$emit');
const IssuableDescriptionComponent = Vue.extend(issuableApp);
@@ -64,65 +61,67 @@ describe('Issuable output', () => {
vm.$destroy();
});
- it('should render a title/description/edited and update title/description/edited on update', (done) => {
+ it('should render a title/description/edited and update title/description/edited on update', done => {
let editedText;
Vue.nextTick()
- .then(() => {
- editedText = vm.$el.querySelector('.edited-text');
- })
- .then(() => {
- expect(document.querySelector('title').innerText).toContain('this is a title (#1)');
- expect(vm.$el.querySelector('.title').innerHTML).toContain('<p>this is a title</p>');
- expect(vm.$el.querySelector('.wiki').innerHTML).toContain('<p>this is a description!</p>');
- expect(vm.$el.querySelector('.js-task-list-field').value).toContain('this is a description');
- expect(formatText(editedText.innerText)).toMatch(/Edited[\s\S]+?by Some User/);
- expect(editedText.querySelector('.author-link').href).toMatch(/\/some_user$/);
- expect(editedText.querySelector('time')).toBeTruthy();
- })
- .then(() => {
- vm.poll.makeRequest();
- })
- .then(() => new Promise(resolve => setTimeout(resolve)))
- .then(() => {
- expect(document.querySelector('title').innerText).toContain('2 (#1)');
- expect(vm.$el.querySelector('.title').innerHTML).toContain('<p>2</p>');
- expect(vm.$el.querySelector('.wiki').innerHTML).toContain('<p>42</p>');
- expect(vm.$el.querySelector('.js-task-list-field').value).toContain('42');
- expect(vm.$el.querySelector('.edited-text')).toBeTruthy();
- expect(formatText(vm.$el.querySelector('.edited-text').innerText)).toMatch(/Edited[\s\S]+?by Other User/);
- expect(editedText.querySelector('.author-link').href).toMatch(/\/other_user$/);
- expect(editedText.querySelector('time')).toBeTruthy();
- })
- .then(done)
- .catch(done.fail);
+ .then(() => {
+ editedText = vm.$el.querySelector('.edited-text');
+ })
+ .then(() => {
+ expect(document.querySelector('title').innerText).toContain('this is a title (#1)');
+ expect(vm.$el.querySelector('.title').innerHTML).toContain('<p>this is a title</p>');
+ expect(vm.$el.querySelector('.wiki').innerHTML).toContain('<p>this is a description!</p>');
+ expect(vm.$el.querySelector('.js-task-list-field').value).toContain(
+ 'this is a description',
+ );
+
+ expect(formatText(editedText.innerText)).toMatch(/Edited[\s\S]+?by Some User/);
+ expect(editedText.querySelector('.author-link').href).toMatch(/\/some_user$/);
+ expect(editedText.querySelector('time')).toBeTruthy();
+ })
+ .then(() => {
+ vm.poll.makeRequest();
+ })
+ .then(() => new Promise(resolve => setTimeout(resolve)))
+ .then(() => {
+ expect(document.querySelector('title').innerText).toContain('2 (#1)');
+ expect(vm.$el.querySelector('.title').innerHTML).toContain('<p>2</p>');
+ expect(vm.$el.querySelector('.wiki').innerHTML).toContain('<p>42</p>');
+ expect(vm.$el.querySelector('.js-task-list-field').value).toContain('42');
+ expect(vm.$el.querySelector('.edited-text')).toBeTruthy();
+ expect(formatText(vm.$el.querySelector('.edited-text').innerText)).toMatch(
+ /Edited[\s\S]+?by Other User/,
+ );
+
+ expect(editedText.querySelector('.author-link').href).toMatch(/\/other_user$/);
+ expect(editedText.querySelector('time')).toBeTruthy();
+ })
+ .then(done)
+ .catch(done.fail);
});
- it('shows actions if permissions are correct', (done) => {
+ it('shows actions if permissions are correct', done => {
vm.showForm = true;
Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.btn'),
- ).not.toBeNull();
+ expect(vm.$el.querySelector('.btn')).not.toBeNull();
done();
});
});
- it('does not show actions if permissions are incorrect', (done) => {
+ it('does not show actions if permissions are incorrect', done => {
vm.showForm = true;
vm.canUpdate = false;
Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.btn'),
- ).toBeNull();
+ expect(vm.$el.querySelector('.btn')).toBeNull();
done();
});
});
- it('does not update formState if form is already open', (done) => {
+ it('does not update formState if form is already open', done => {
vm.openForm();
vm.state.titleText = 'testing 123';
@@ -130,25 +129,26 @@ describe('Issuable output', () => {
vm.openForm();
Vue.nextTick(() => {
- expect(
- vm.store.formState.title,
- ).not.toBe('testing 123');
+ expect(vm.store.formState.title).not.toBe('testing 123');
done();
});
});
describe('updateIssuable', () => {
- it('fetches new data after update', (done) => {
+ it('fetches new data after update', done => {
spyOn(vm.service, 'getData').and.callThrough();
- spyOn(vm.service, 'updateIssuable').and.callFake(() => new Promise((resolve) => {
- resolve({
- data: {
- confidential: false,
- web_url: window.location.pathname,
- },
- });
- }));
+ spyOn(vm.service, 'updateIssuable').and.callFake(
+ () =>
+ new Promise(resolve => {
+ resolve({
+ data: {
+ confidential: false,
+ web_url: window.location.pathname,
+ },
+ });
+ }),
+ );
vm.updateIssuable()
.then(() => {
@@ -158,10 +158,13 @@ describe('Issuable output', () => {
.catch(done.fail);
});
- it('correctly updates issuable data', (done) => {
- spyOn(vm.service, 'updateIssuable').and.callFake(() => new Promise((resolve) => {
- resolve();
- }));
+ it('correctly updates issuable data', done => {
+ spyOn(vm.service, 'updateIssuable').and.callFake(
+ () =>
+ new Promise(resolve => {
+ resolve();
+ }),
+ );
vm.updateIssuable()
.then(() => {
@@ -172,16 +175,19 @@ describe('Issuable output', () => {
.catch(done.fail);
});
- it('does not redirect if issue has not moved', (done) => {
+ it('does not redirect if issue has not moved', done => {
const visitUrl = spyOnDependency(issuableApp, 'visitUrl');
- spyOn(vm.service, 'updateIssuable').and.callFake(() => new Promise((resolve) => {
- resolve({
- data: {
- web_url: window.location.pathname,
- confidential: vm.isConfidential,
- },
- });
- }));
+ spyOn(vm.service, 'updateIssuable').and.callFake(
+ () =>
+ new Promise(resolve => {
+ resolve({
+ data: {
+ web_url: window.location.pathname,
+ confidential: vm.isConfidential,
+ },
+ });
+ }),
+ );
vm.updateIssuable();
@@ -191,16 +197,19 @@ describe('Issuable output', () => {
});
});
- it('redirects if returned web_url has changed', (done) => {
+ it('redirects if returned web_url has changed', done => {
const visitUrl = spyOnDependency(issuableApp, 'visitUrl');
- spyOn(vm.service, 'updateIssuable').and.callFake(() => new Promise((resolve) => {
- resolve({
- data: {
- web_url: '/testing-issue-move',
- confidential: vm.isConfidential,
- },
- });
- }));
+ spyOn(vm.service, 'updateIssuable').and.callFake(
+ () =>
+ new Promise(resolve => {
+ resolve({
+ data: {
+ web_url: '/testing-issue-move',
+ confidential: vm.isConfidential,
+ },
+ });
+ }),
+ );
vm.updateIssuable();
@@ -211,7 +220,7 @@ describe('Issuable output', () => {
});
describe('shows dialog when issue has unsaved changed', () => {
- it('confirms on title change', (done) => {
+ it('confirms on title change', done => {
vm.showForm = true;
vm.state.titleText = 'title has changed';
const e = { returnValue: null };
@@ -222,7 +231,7 @@ describe('Issuable output', () => {
});
});
- it('confirms on description change', (done) => {
+ it('confirms on description change', done => {
vm.showForm = true;
vm.state.descriptionText = 'description has changed';
const e = { returnValue: null };
@@ -233,7 +242,7 @@ describe('Issuable output', () => {
});
});
- it('does nothing when nothing has changed', (done) => {
+ it('does nothing when nothing has changed', done => {
const e = { returnValue: null };
vm.handleBeforeUnloadEvent(e);
Vue.nextTick(() => {
@@ -246,39 +255,36 @@ describe('Issuable output', () => {
describe('error when updating', () => {
beforeEach(() => {
spyOn(window, 'Flash').and.callThrough();
- spyOn(vm.service, 'updateIssuable').and.callFake(() => new Promise((resolve, reject) => {
- reject();
- }));
+ spyOn(vm.service, 'updateIssuable').and.callFake(
+ () =>
+ new Promise((resolve, reject) => {
+ reject();
+ }),
+ );
});
- it('closes form on error', (done) => {
+ it('closes form on error', done => {
vm.updateIssuable();
setTimeout(() => {
- expect(
- eventHub.$emit,
- ).toHaveBeenCalledWith('close.form');
- expect(
- window.Flash,
- ).toHaveBeenCalledWith('Error updating issue');
+ expect(eventHub.$emit).toHaveBeenCalledWith('close.form');
+
+ expect(window.Flash).toHaveBeenCalledWith('Error updating issue');
done();
});
});
- it('returns the correct error message for issuableType', (done) => {
+ it('returns the correct error message for issuableType', done => {
vm.issuableType = 'merge request';
Vue.nextTick(() => {
vm.updateIssuable();
setTimeout(() => {
- expect(
- eventHub.$emit,
- ).toHaveBeenCalledWith('close.form');
- expect(
- window.Flash,
- ).toHaveBeenCalledWith('Error updating merge request');
+ expect(eventHub.$emit).toHaveBeenCalledWith('close.form');
+
+ expect(window.Flash).toHaveBeenCalledWith('Error updating merge request');
done();
});
@@ -287,16 +293,18 @@ describe('Issuable output', () => {
});
});
- it('opens recaptcha modal if update rejected as spam', (done) => {
+ it('opens recaptcha modal if update rejected as spam', done => {
function mockScriptSrc() {
- const recaptchaChild = vm.$children
- .find(child => child.$options._componentTag === 'recaptcha-modal'); // eslint-disable-line no-underscore-dangle
+ const recaptchaChild = vm.$children.find(
+ // eslint-disable-next-line no-underscore-dangle
+ child => child.$options._componentTag === 'recaptcha-modal',
+ );
recaptchaChild.scriptSrc = '//scriptsrc';
}
let modal;
- const promise = new Promise((resolve) => {
+ const promise = new Promise(resolve => {
resolve({
data: {
recaptcha_html: '<div class="g-recaptcha">recaptcha_html</div>',
@@ -332,15 +340,18 @@ describe('Issuable output', () => {
});
describe('deleteIssuable', () => {
- it('changes URL when deleted', (done) => {
+ it('changes URL when deleted', done => {
const visitUrl = spyOnDependency(issuableApp, 'visitUrl');
- spyOn(vm.service, 'deleteIssuable').and.callFake(() => new Promise((resolve) => {
- resolve({
- data: {
- web_url: '/test',
- },
- });
- }));
+ spyOn(vm.service, 'deleteIssuable').and.callFake(
+ () =>
+ new Promise(resolve => {
+ resolve({
+ data: {
+ web_url: '/test',
+ },
+ });
+ }),
+ );
vm.deleteIssuable();
@@ -350,42 +361,43 @@ describe('Issuable output', () => {
});
});
- it('stops polling when deleting', (done) => {
+ it('stops polling when deleting', done => {
spyOnDependency(issuableApp, 'visitUrl');
spyOn(vm.poll, 'stop').and.callThrough();
- spyOn(vm.service, 'deleteIssuable').and.callFake(() => new Promise((resolve) => {
- resolve({
- data: {
- web_url: '/test',
- },
- });
- }));
+ spyOn(vm.service, 'deleteIssuable').and.callFake(
+ () =>
+ new Promise(resolve => {
+ resolve({
+ data: {
+ web_url: '/test',
+ },
+ });
+ }),
+ );
vm.deleteIssuable();
setTimeout(() => {
- expect(
- vm.poll.stop,
- ).toHaveBeenCalledWith();
+ expect(vm.poll.stop).toHaveBeenCalledWith();
done();
});
});
- it('closes form on error', (done) => {
+ it('closes form on error', done => {
spyOn(window, 'Flash').and.callThrough();
- spyOn(vm.service, 'deleteIssuable').and.callFake(() => new Promise((resolve, reject) => {
- reject();
- }));
+ spyOn(vm.service, 'deleteIssuable').and.callFake(
+ () =>
+ new Promise((resolve, reject) => {
+ reject();
+ }),
+ );
vm.deleteIssuable();
setTimeout(() => {
- expect(
- eventHub.$emit,
- ).toHaveBeenCalledWith('close.form');
- expect(
- window.Flash,
- ).toHaveBeenCalledWith('Error deleting issue');
+ expect(eventHub.$emit).toHaveBeenCalledWith('close.form');
+
+ expect(window.Flash).toHaveBeenCalledWith('Error deleting issue');
done();
});
@@ -393,7 +405,7 @@ describe('Issuable output', () => {
});
describe('open form', () => {
- it('shows locked warning if form is open & data is different', (done) => {
+ it('shows locked warning if form is open & data is different', done => {
vm.$nextTick()
.then(() => {
vm.openForm();
@@ -422,6 +434,7 @@ describe('Issuable output', () => {
it('should render if showInlineEditButton', () => {
vm.showInlineEditButton = true;
+
expect(vm.$el.querySelector('.title-container .note-action-button')).toBeDefined();
});
});
diff --git a/spec/javascripts/issue_show/components/description_spec.js b/spec/javascripts/issue_show/components/description_spec.js
index 889c8545faa..463f3c89926 100644
--- a/spec/javascripts/issue_show/components/description_spec.js
+++ b/spec/javascripts/issue_show/components/description_spec.js
@@ -33,7 +33,7 @@ describe('Description component', () => {
vm.$destroy();
});
- it('animates description changes', (done) => {
+ it('animates description changes', done => {
vm.descriptionHtml = 'changed';
Vue.nextTick(() => {
@@ -51,10 +51,12 @@ describe('Description component', () => {
});
});
- it('opens recaptcha dialog if update rejected as spam', (done) => {
+ it('opens recaptcha dialog if update rejected as spam', done => {
let modal;
- const recaptchaChild = vm.$children
- .find(child => child.$options._componentTag === 'recaptcha-modal'); // eslint-disable-line no-underscore-dangle
+ const recaptchaChild = vm.$children.find(
+ // eslint-disable-next-line no-underscore-dangle
+ child => child.$options._componentTag === 'recaptcha-modal',
+ );
recaptchaChild.scriptSrc = '//scriptsrc';
@@ -84,13 +86,16 @@ describe('Description component', () => {
let TaskList;
beforeEach(() => {
- vm = mountComponent(DescriptionComponent, Object.assign({}, props, {
- issuableType: 'issuableType',
- }));
+ vm = mountComponent(
+ DescriptionComponent,
+ Object.assign({}, props, {
+ issuableType: 'issuableType',
+ }),
+ );
TaskList = spyOnDependency(Description, 'TaskList');
});
- it('re-inits the TaskList when description changed', (done) => {
+ it('re-inits the TaskList when description changed', done => {
vm.descriptionHtml = 'changed';
setTimeout(() => {
@@ -99,7 +104,7 @@ describe('Description component', () => {
});
});
- it('does not re-init the TaskList when canUpdate is false', (done) => {
+ it('does not re-init the TaskList when canUpdate is false', done => {
vm.canUpdate = false;
vm.descriptionHtml = 'changed';
@@ -109,7 +114,7 @@ describe('Description component', () => {
});
});
- it('calls with issuableType dataType', (done) => {
+ it('calls with issuableType dataType', done => {
vm.descriptionHtml = 'changed';
setTimeout(() => {
@@ -125,44 +130,42 @@ describe('Description component', () => {
});
describe('taskStatus', () => {
- it('adds full taskStatus', (done) => {
+ it('adds full taskStatus', done => {
vm.taskStatus = '1 of 1';
setTimeout(() => {
- expect(
- document.querySelector('.issuable-meta #task_status').textContent.trim(),
- ).toBe('1 of 1');
+ expect(document.querySelector('.issuable-meta #task_status').textContent.trim()).toBe(
+ '1 of 1',
+ );
done();
});
});
- it('adds short taskStatus', (done) => {
+ it('adds short taskStatus', done => {
vm.taskStatus = '1 of 1';
setTimeout(() => {
- expect(
- document.querySelector('.issuable-meta #task_status_short').textContent.trim(),
- ).toBe('1/1 task');
+ expect(document.querySelector('.issuable-meta #task_status_short').textContent.trim()).toBe(
+ '1/1 task',
+ );
done();
});
});
- it('clears task status text when no tasks are present', (done) => {
+ it('clears task status text when no tasks are present', done => {
vm.taskStatus = '0 of 0';
setTimeout(() => {
- expect(
- document.querySelector('.issuable-meta #task_status').textContent.trim(),
- ).toBe('');
+ expect(document.querySelector('.issuable-meta #task_status').textContent.trim()).toBe('');
done();
});
});
});
- it('applies syntax highlighting and math when description changed', (done) => {
+ it('applies syntax highlighting and math when description changed', done => {
spyOn(vm, 'renderGFM').and.callThrough();
spyOn($.prototype, 'renderGFM').and.callThrough();
vm.descriptionHtml = 'changed';
diff --git a/spec/javascripts/issue_show/components/edit_actions_spec.js b/spec/javascripts/issue_show/components/edit_actions_spec.js
index a3772285527..d92c54ea83f 100644
--- a/spec/javascripts/issue_show/components/edit_actions_spec.js
+++ b/spec/javascripts/issue_show/components/edit_actions_spec.js
@@ -6,7 +6,7 @@ import Store from '~/issue_show/stores';
describe('Edit Actions components', () => {
let vm;
- beforeEach((done) => {
+ beforeEach(done => {
const Component = Vue.extend(editActions);
const store = new Store({
titleHtml: '',
@@ -21,6 +21,7 @@ describe('Edit Actions components', () => {
propsData: {
canDestroy: true,
formState: store.formState,
+ issuableType: 'issue',
},
}).$mount();
@@ -28,40 +29,32 @@ describe('Edit Actions components', () => {
});
it('renders all buttons as enabled', () => {
- expect(
- vm.$el.querySelectorAll('.disabled').length,
- ).toBe(0);
+ expect(vm.$el.querySelectorAll('.disabled').length).toBe(0);
- expect(
- vm.$el.querySelectorAll('[disabled]').length,
- ).toBe(0);
+ expect(vm.$el.querySelectorAll('[disabled]').length).toBe(0);
});
- it('does not render delete button if canUpdate is false', (done) => {
+ it('does not render delete button if canUpdate is false', done => {
vm.canDestroy = false;
Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.btn-danger'),
- ).toBeNull();
+ expect(vm.$el.querySelector('.btn-danger')).toBeNull();
done();
});
});
- it('disables submit button when title is blank', (done) => {
+ it('disables submit button when title is blank', done => {
vm.formState.title = '';
Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.btn-success').getAttribute('disabled'),
- ).toBe('disabled');
+ expect(vm.$el.querySelector('.btn-success').getAttribute('disabled')).toBe('disabled');
done();
});
});
- it('should not show delete button if showDeleteButton is false', (done) => {
+ it('should not show delete button if showDeleteButton is false', done => {
vm.showDeleteButton = false;
Vue.nextTick(() => {
@@ -74,30 +67,24 @@ describe('Edit Actions components', () => {
it('sends update.issauble event when clicking save button', () => {
vm.$el.querySelector('.btn-success').click();
- expect(
- eventHub.$emit,
- ).toHaveBeenCalledWith('update.issuable');
+ expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
});
- it('shows loading icon after clicking save button', (done) => {
+ it('shows loading icon after clicking save button', done => {
vm.$el.querySelector('.btn-success').click();
Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.btn-success .fa'),
- ).not.toBeNull();
+ expect(vm.$el.querySelector('.btn-success .fa')).not.toBeNull();
done();
});
});
- it('disabled button after clicking save button', (done) => {
+ it('disabled button after clicking save button', done => {
vm.$el.querySelector('.btn-success').click();
Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.btn-success').getAttribute('disabled'),
- ).toBe('disabled');
+ expect(vm.$el.querySelector('.btn-success').getAttribute('disabled')).toBe('disabled');
done();
});
@@ -108,9 +95,7 @@ describe('Edit Actions components', () => {
it('emits close.form when clicking cancel', () => {
vm.$el.querySelector('.btn-default').click();
- expect(
- eventHub.$emit,
- ).toHaveBeenCalledWith('close.form');
+ expect(eventHub.$emit).toHaveBeenCalledWith('close.form');
});
});
@@ -119,35 +104,28 @@ describe('Edit Actions components', () => {
spyOn(window, 'confirm').and.returnValue(true);
vm.$el.querySelector('.btn-danger').click();
- expect(
- eventHub.$emit,
- ).toHaveBeenCalledWith('delete.issuable');
+ expect(eventHub.$emit).toHaveBeenCalledWith('delete.issuable');
});
- it('shows loading icon after clicking delete button', (done) => {
+ it('shows loading icon after clicking delete button', done => {
spyOn(window, 'confirm').and.returnValue(true);
vm.$el.querySelector('.btn-danger').click();
Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.btn-danger .fa'),
- ).not.toBeNull();
+ expect(vm.$el.querySelector('.btn-danger .fa')).not.toBeNull();
done();
});
});
- it('does no actions when confirm is false', (done) => {
+ it('does no actions when confirm is false', done => {
spyOn(window, 'confirm').and.returnValue(false);
vm.$el.querySelector('.btn-danger').click();
Vue.nextTick(() => {
- expect(
- eventHub.$emit,
- ).not.toHaveBeenCalledWith('delete.issuable');
- expect(
- vm.$el.querySelector('.btn-danger .fa'),
- ).toBeNull();
+ expect(eventHub.$emit).not.toHaveBeenCalledWith('delete.issuable');
+
+ expect(vm.$el.querySelector('.btn-danger .fa')).toBeNull();
done();
});
diff --git a/spec/javascripts/issue_show/components/edited_spec.js b/spec/javascripts/issue_show/components/edited_spec.js
index 7f09db837bb..a1683f060c0 100644
--- a/spec/javascripts/issue_show/components/edited_spec.js
+++ b/spec/javascripts/issue_show/components/edited_spec.js
@@ -46,14 +46,4 @@ describe('edited', () => {
expect(editedComponent.$el.querySelector('.author-link')).toBeFalsy();
expect(editedComponent.$el.querySelector('time')).toBeTruthy();
});
-
- it('renders time ago tooltip at the bottom', () => {
- const editedComponent = new EditedComponent({
- propsData: {
- updatedAt: '2017-05-15T12:31:04.428Z',
- },
- }).$mount();
-
- expect(editedComponent.$el.querySelector('time').dataset.placement).toEqual('bottom');
- });
});
diff --git a/spec/javascripts/issue_show/components/fields/description_spec.js b/spec/javascripts/issue_show/components/fields/description_spec.js
index 299f88e7778..2c3efc8d4d4 100644
--- a/spec/javascripts/issue_show/components/fields/description_spec.js
+++ b/spec/javascripts/issue_show/components/fields/description_spec.js
@@ -8,7 +8,7 @@ describe('Description field component', () => {
let vm;
let store;
- beforeEach((done) => {
+ beforeEach(done => {
const Component = Vue.extend(descriptionField);
const el = document.createElement('div');
store = new Store({
@@ -35,42 +35,32 @@ describe('Description field component', () => {
});
it('renders markdown field with description', () => {
- expect(
- vm.$el.querySelector('.md-area textarea').value,
- ).toBe('test');
+ expect(vm.$el.querySelector('.md-area textarea').value).toBe('test');
});
- it('renders markdown field with a markdown description', (done) => {
+ it('renders markdown field with a markdown description', done => {
store.formState.description = '**test**';
Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.md-area textarea').value,
- ).toBe('**test**');
+ expect(vm.$el.querySelector('.md-area textarea').value).toBe('**test**');
done();
});
});
it('focuses field when mounted', () => {
- expect(
- document.activeElement,
- ).toBe(vm.$refs.textarea);
+ expect(document.activeElement).toBe(vm.$refs.textarea);
});
it('triggers update with meta+enter', () => {
vm.$el.querySelector('.md-area textarea').dispatchEvent(keyboardDownEvent(13, true));
- expect(
- eventHub.$emit,
- ).toHaveBeenCalled();
+ expect(eventHub.$emit).toHaveBeenCalled();
});
it('triggers update with ctrl+enter', () => {
vm.$el.querySelector('.md-area textarea').dispatchEvent(keyboardDownEvent(13, false, true));
- expect(
- eventHub.$emit,
- ).toHaveBeenCalled();
+ expect(eventHub.$emit).toHaveBeenCalled();
});
});
diff --git a/spec/javascripts/issue_show/components/fields/description_template_spec.js b/spec/javascripts/issue_show/components/fields/description_template_spec.js
index 30441faf844..8d77a620d76 100644
--- a/spec/javascripts/issue_show/components/fields/description_template_spec.js
+++ b/spec/javascripts/issue_show/components/fields/description_template_spec.js
@@ -5,7 +5,7 @@ describe('Issue description template component', () => {
let vm;
let formState;
- beforeEach((done) => {
+ beforeEach(done => {
const Component = Vue.extend(descriptionTemplate);
formState = {
description: 'test',
@@ -24,24 +24,20 @@ describe('Issue description template component', () => {
});
it('renders templates as JSON array in data attribute', () => {
- expect(
- vm.$el.querySelector('.js-issuable-selector').getAttribute('data-data'),
- ).toBe('[{"name":"test"}]');
+ expect(vm.$el.querySelector('.js-issuable-selector').getAttribute('data-data')).toBe(
+ '[{"name":"test"}]',
+ );
});
it('updates formState when changing template', () => {
vm.issuableTemplate.editor.setValue('test new template');
- expect(
- formState.description,
- ).toBe('test new template');
+ expect(formState.description).toBe('test new template');
});
it('returns formState description with editor getValue', () => {
formState.description = 'testing new template';
- expect(
- vm.issuableTemplate.editor.getValue(),
- ).toBe('testing new template');
+ expect(vm.issuableTemplate.editor.getValue()).toBe('testing new template');
});
});
diff --git a/spec/javascripts/issue_show/components/fields/title_spec.js b/spec/javascripts/issue_show/components/fields/title_spec.js
index a03b462689f..4b96a1feb29 100644
--- a/spec/javascripts/issue_show/components/fields/title_spec.js
+++ b/spec/javascripts/issue_show/components/fields/title_spec.js
@@ -27,24 +27,18 @@ describe('Title field component', () => {
});
it('renders form control with formState title', () => {
- expect(
- vm.$el.querySelector('.form-control').value,
- ).toBe('test');
+ expect(vm.$el.querySelector('.form-control').value).toBe('test');
});
it('triggers update with meta+enter', () => {
vm.$el.querySelector('.form-control').dispatchEvent(keyboardDownEvent(13, true));
- expect(
- eventHub.$emit,
- ).toHaveBeenCalled();
+ expect(eventHub.$emit).toHaveBeenCalled();
});
it('triggers update with ctrl+enter', () => {
vm.$el.querySelector('.form-control').dispatchEvent(keyboardDownEvent(13, false, true));
- expect(
- eventHub.$emit,
- ).toHaveBeenCalled();
+ expect(eventHub.$emit).toHaveBeenCalled();
});
});
diff --git a/spec/javascripts/issue_show/components/form_spec.js b/spec/javascripts/issue_show/components/form_spec.js
index 50ce019c32a..523954013cf 100644
--- a/spec/javascripts/issue_show/components/form_spec.js
+++ b/spec/javascripts/issue_show/components/form_spec.js
@@ -4,7 +4,7 @@ import formComponent from '~/issue_show/components/form.vue';
describe('Inline edit form component', () => {
let vm;
- beforeEach((done) => {
+ beforeEach(done => {
const Component = Vue.extend(formComponent);
vm = new Component({
@@ -15,6 +15,7 @@ describe('Inline edit form component', () => {
description: 'a',
lockedWarningVisible: false,
},
+ issuableType: 'issue',
markdownPreviewPath: '/',
markdownDocsPath: '/',
projectPath: '/',
@@ -26,36 +27,28 @@ describe('Inline edit form component', () => {
});
it('does not render template selector if no templates exist', () => {
- expect(
- vm.$el.querySelector('.js-issuable-selector-wrap'),
- ).toBeNull();
+ expect(vm.$el.querySelector('.js-issuable-selector-wrap')).toBeNull();
});
- it('renders template selector when templates exists', (done) => {
+ it('renders template selector when templates exists', done => {
vm.issuableTemplates = ['test'];
Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.js-issuable-selector-wrap'),
- ).not.toBeNull();
+ expect(vm.$el.querySelector('.js-issuable-selector-wrap')).not.toBeNull();
done();
});
});
it('hides locked warning by default', () => {
- expect(
- vm.$el.querySelector('.alert'),
- ).toBeNull();
+ expect(vm.$el.querySelector('.alert')).toBeNull();
});
- it('shows locked warning if formState is different', (done) => {
+ it('shows locked warning if formState is different', done => {
vm.formState.lockedWarningVisible = true;
Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.alert'),
- ).not.toBeNull();
+ expect(vm.$el.querySelector('.alert')).not.toBeNull();
done();
});
diff --git a/spec/javascripts/issue_show/components/title_spec.js b/spec/javascripts/issue_show/components/title_spec.js
index 5370f4e1fea..9754c8a6755 100644
--- a/spec/javascripts/issue_show/components/title_spec.js
+++ b/spec/javascripts/issue_show/components/title_spec.js
@@ -25,25 +25,21 @@ describe('Title component', () => {
});
it('renders title HTML', () => {
- expect(
- vm.$el.querySelector('.title').innerHTML.trim(),
- ).toBe('Testing <img>');
+ expect(vm.$el.querySelector('.title').innerHTML.trim()).toBe('Testing <img>');
});
- it('updates page title when changing titleHtml', (done) => {
+ it('updates page title when changing titleHtml', done => {
spyOn(vm, 'setPageTitle');
vm.titleHtml = 'test';
Vue.nextTick(() => {
- expect(
- vm.setPageTitle,
- ).toHaveBeenCalled();
+ expect(vm.setPageTitle).toHaveBeenCalled();
done();
});
});
- it('animates title changes', (done) => {
+ it('animates title changes', done => {
vm.titleHtml = 'test';
Vue.nextTick(() => {
@@ -61,14 +57,12 @@ describe('Title component', () => {
});
});
- it('updates page title after changing title', (done) => {
+ it('updates page title after changing title', done => {
vm.titleHtml = 'changed';
vm.titleText = 'changed';
Vue.nextTick(() => {
- expect(
- document.querySelector('title').textContent.trim(),
- ).toContain('changed');
+ expect(document.querySelector('title').textContent.trim()).toContain('changed');
done();
});
@@ -86,12 +80,14 @@ describe('Title component', () => {
it('should not show if canUpdate is false', () => {
vm.showInlineEditButton = true;
vm.canUpdate = false;
+
expect(vm.$el.querySelector('.btn-edit')).toBeNull();
});
it('should show if showInlineEditButton and canUpdate', () => {
vm.showInlineEditButton = true;
vm.canUpdate = true;
+
expect(vm.$el.querySelector('.btn-edit')).toBeDefined();
});
@@ -101,6 +97,7 @@ describe('Title component', () => {
Vue.nextTick(() => {
vm.$el.querySelector('.btn-edit').click();
+
expect(eventHub.$emit).toHaveBeenCalledWith('open.form');
});
});
diff --git a/spec/javascripts/issue_show/index_spec.js b/spec/javascripts/issue_show/index_spec.js
new file mode 100644
index 00000000000..fa0b426c06c
--- /dev/null
+++ b/spec/javascripts/issue_show/index_spec.js
@@ -0,0 +1,19 @@
+import initIssueableApp from '~/issue_show';
+
+describe('Issue show index', () => {
+ describe('initIssueableApp', () => {
+ it('should initialize app with no potential XSS attack', () => {
+ const d = document.createElement('div');
+ d.id = 'js-issuable-app-initial-data';
+ d.innerHTML = JSON.stringify({
+ initialDescriptionHtml: '&lt;img src=x onerror=alert(1)&gt;',
+ });
+ document.body.appendChild(d);
+
+ const alertSpy = spyOn(window, 'alert');
+ initIssueableApp();
+
+ expect(alertSpy).not.toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/javascripts/issue_spec.js b/spec/javascripts/issue_spec.js
index e12419b835d..7be495d1d35 100644
--- a/spec/javascripts/issue_spec.js
+++ b/spec/javascripts/issue_spec.js
@@ -1,4 +1,4 @@
-/* eslint-disable one-var, one-var-declaration-per-line, no-use-before-define, comma-dangle */
+/* eslint-disable one-var, no-use-before-define */
import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
@@ -15,6 +15,7 @@ describe('Issue', function() {
function expectErrorMessage() {
const $flashMessage = $('div.flash-alert');
+
expect($flashMessage).toExist();
expect($flashMessage).toBeVisible();
expect($flashMessage).toHaveText('Unable to update this issue at this time.');
@@ -23,6 +24,7 @@ describe('Issue', function() {
function expectIssueState(isIssueOpen) {
expectVisibility($boxClosed, !isIssueOpen);
expectVisibility($boxOpen, isIssueOpen);
+
expect($btn).toHaveText(isIssueOpen ? 'Close issue' : 'Reopen issue');
}
@@ -32,6 +34,7 @@ describe('Issue', function() {
}
const $available = Issue.$btnNewBranch.find('.available');
+
expect($available).toHaveText('New branch');
if (!isPending && canCreate) {
@@ -41,6 +44,7 @@ describe('Issue', function() {
}
const $unavailable = Issue.$btnNewBranch.find('.unavailable');
+
expect($unavailable).toHaveText('New branch unavailable');
if (!isPending && !canCreate) {
@@ -60,19 +64,22 @@ describe('Issue', function() {
function findElements(isIssueInitiallyOpen) {
$boxClosed = $('div.status-box-issue-closed');
+
expect($boxClosed).toExist();
expect($boxClosed).toHaveText('Closed');
$boxOpen = $('div.status-box-open');
+
expect($boxOpen).toExist();
expect($boxOpen).toHaveText('Open');
$btn = $('.js-issuable-close-button');
+
expect($btn).toExist();
expect($btn).toHaveText(isIssueInitiallyOpen ? 'Close issue' : 'Reopen issue');
}
- [true, false].forEach((isIssueInitiallyOpen) => {
+ [true, false].forEach(isIssueInitiallyOpen => {
describe(`with ${isIssueInitiallyOpen ? 'open' : 'closed'} issue`, function() {
const action = isIssueInitiallyOpen ? 'close' : 'reopen';
let mock;
@@ -127,7 +134,7 @@ describe('Issue', function() {
it(`${action}s the issue`, function(done) {
mockCloseButtonResponseSuccess(this.$triggeredButton.attr('href'), {
- id: 34
+ id: 34,
});
mockCanCreateBranch(!isIssueInitiallyOpen);
@@ -135,6 +142,7 @@ describe('Issue', function() {
setTimeout(() => {
expectIssueState(!isIssueInitiallyOpen);
+
expect(this.$triggeredButton.get(0).getAttribute('disabled')).toBeNull();
expect(this.$projectIssuesCounter.text()).toBe(isIssueInitiallyOpen ? '1,000' : '1,002');
expectNewBranchButtonState(false, !isIssueInitiallyOpen);
@@ -145,7 +153,7 @@ describe('Issue', function() {
it(`fails to ${action} the issue if saved:false`, function(done) {
mockCloseButtonResponseSuccess(this.$triggeredButton.attr('href'), {
- saved: false
+ saved: false,
});
mockCanCreateBranch(isIssueInitiallyOpen);
@@ -153,8 +161,10 @@ describe('Issue', function() {
setTimeout(() => {
expectIssueState(isIssueInitiallyOpen);
+
expect(this.$triggeredButton.get(0).getAttribute('disabled')).toBeNull();
expectErrorMessage();
+
expect(this.$projectIssuesCounter.text()).toBe('1,001');
expectNewBranchButtonState(false, isIssueInitiallyOpen);
@@ -170,8 +180,10 @@ describe('Issue', function() {
setTimeout(() => {
expectIssueState(isIssueInitiallyOpen);
+
expect(this.$triggeredButton.get(0).getAttribute('disabled')).toBeNull();
expectErrorMessage();
+
expect(this.$projectIssuesCounter.text()).toBe('1,001');
expectNewBranchButtonState(false, isIssueInitiallyOpen);
diff --git a/spec/javascripts/job_spec.js b/spec/javascripts/job_spec.js
deleted file mode 100644
index 2fcb5566ebc..00000000000
--- a/spec/javascripts/job_spec.js
+++ /dev/null
@@ -1,314 +0,0 @@
-import $ from 'jquery';
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import { numberToHumanSize } from '~/lib/utils/number_utils';
-import '~/lib/utils/datetime_utility';
-import Job from '~/job';
-import '~/breakpoints';
-import waitForPromises from 'spec/helpers/wait_for_promises';
-
-describe('Job', () => {
- const JOB_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/-/jobs/1`;
- let mock;
- let response;
- let job;
-
- preloadFixtures('builds/build-with-artifacts.html.raw');
-
- beforeEach(() => {
- loadFixtures('builds/build-with-artifacts.html.raw');
-
- spyOnDependency(Job, 'visitUrl');
-
- response = {};
-
- mock = new MockAdapter(axios);
-
- mock.onGet(new RegExp(`${JOB_URL}/trace.json?(.*)`)).reply(() => [200, response]);
- });
-
- afterEach(() => {
- mock.restore();
-
- clearTimeout(job.timeout);
- });
-
- describe('class constructor', () => {
- beforeEach(() => {
- jasmine.clock().install();
- });
-
- afterEach(() => {
- jasmine.clock().uninstall();
- });
-
- describe('setup', () => {
- beforeEach(function (done) {
- job = new Job();
-
- waitForPromises()
- .then(done)
- .catch(done.fail);
- });
-
- it('copies build options', function () {
- expect(job.pagePath).toBe(JOB_URL);
- expect(job.buildStatus).toBe('success');
- expect(job.buildStage).toBe('test');
- expect(job.state).toBe('');
- });
-
- it('only shows the jobs matching the current stage', () => {
- expect($('.build-job[data-stage="build"]').is(':visible')).toBe(false);
- expect($('.build-job[data-stage="test"]').is(':visible')).toBe(true);
- expect($('.build-job[data-stage="deploy"]').is(':visible')).toBe(false);
- });
-
- it('selects the current stage in the build dropdown menu', () => {
- expect($('.stage-selection').text()).toBe('test');
- });
-
- it('updates the jobs when the build dropdown changes', () => {
- $('.stage-item:contains("build")').click();
-
- expect($('.stage-selection').text()).toBe('build');
- expect($('.build-job[data-stage="build"]').is(':visible')).toBe(true);
- expect($('.build-job[data-stage="test"]').is(':visible')).toBe(false);
- expect($('.build-job[data-stage="deploy"]').is(':visible')).toBe(false);
- });
- });
-
- describe('running build', () => {
- it('updates the build trace on an interval', function (done) {
- response = {
- html: '<span>Update<span>',
- status: 'running',
- state: 'newstate',
- append: true,
- complete: false,
- };
-
- job = new Job();
-
- waitForPromises()
- .then(() => {
- expect($('#build-trace .js-build-output').text()).toMatch(/Update/);
- expect(job.state).toBe('newstate');
-
- response = {
- html: '<span>More</span>',
- status: 'running',
- state: 'finalstate',
- append: true,
- complete: true,
- };
- })
- .then(() => jasmine.clock().tick(4001))
- .then(waitForPromises)
- .then(() => {
- expect($('#build-trace .js-build-output').text()).toMatch(/UpdateMore/);
- expect(job.state).toBe('finalstate');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('replaces the entire build trace', (done) => {
- response = {
- html: '<span>Update<span>',
- status: 'running',
- append: false,
- complete: false,
- };
-
- job = new Job();
-
- waitForPromises()
- .then(() => {
- expect($('#build-trace .js-build-output').text()).toMatch(/Update/);
-
- response = {
- html: '<span>Different</span>',
- status: 'running',
- append: false,
- };
- })
- .then(() => jasmine.clock().tick(4001))
- .then(waitForPromises)
- .then(() => {
- expect($('#build-trace .js-build-output').text()).not.toMatch(/Update/);
- expect($('#build-trace .js-build-output').text()).toMatch(/Different/);
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('truncated information', () => {
- describe('when size is less than total', () => {
- it('shows information about truncated log', (done) => {
- response = {
- html: '<span>Update</span>',
- status: 'success',
- append: false,
- size: 50,
- total: 100,
- };
-
- job = new Job();
-
- waitForPromises()
- .then(() => {
- expect(document.querySelector('.js-truncated-info').classList).not.toContain('hidden');
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('shows the size in KiB', (done) => {
- const size = 50;
-
- response = {
- html: '<span>Update</span>',
- status: 'success',
- append: false,
- size,
- total: 100,
- };
-
- job = new Job();
-
- waitForPromises()
- .then(() => {
- expect(
- document.querySelector('.js-truncated-info-size').textContent.trim(),
- ).toEqual(`${numberToHumanSize(size)}`);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('shows incremented size', (done) => {
- response = {
- html: '<span>Update</span>',
- status: 'success',
- append: false,
- size: 50,
- total: 100,
- complete: false,
- };
-
- job = new Job();
-
- waitForPromises()
- .then(() => {
- expect(
- document.querySelector('.js-truncated-info-size').textContent.trim(),
- ).toEqual(`${numberToHumanSize(50)}`);
-
- response = {
- html: '<span>Update</span>',
- status: 'success',
- append: true,
- size: 10,
- total: 100,
- complete: true,
- };
- })
- .then(() => jasmine.clock().tick(4001))
- .then(waitForPromises)
- .then(() => {
- expect(
- document.querySelector('.js-truncated-info-size').textContent.trim(),
- ).toEqual(`${numberToHumanSize(60)}`);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('renders the raw link', () => {
- response = {
- html: '<span>Update</span>',
- status: 'success',
- append: false,
- size: 50,
- total: 100,
- };
-
- job = new Job();
-
- expect(
- document.querySelector('.js-raw-link').textContent.trim(),
- ).toContain('Complete Raw');
- });
- });
-
- describe('when size is equal than total', () => {
- it('does not show the trunctated information', (done) => {
- response = {
- html: '<span>Update</span>',
- status: 'success',
- append: false,
- size: 100,
- total: 100,
- };
-
- job = new Job();
-
- waitForPromises()
- .then(() => {
- expect(document.querySelector('.js-truncated-info').classList).toContain('hidden');
- })
- .then(done)
- .catch(done.fail);
- });
- });
- });
-
- describe('output trace', () => {
- beforeEach((done) => {
- response = {
- html: '<span>Update</span>',
- status: 'success',
- append: false,
- size: 50,
- total: 100,
- };
-
- job = new Job();
-
- waitForPromises()
- .then(done)
- .catch(done.fail);
- });
-
- it('should render trace controls', () => {
- const controllers = document.querySelector('.controllers');
-
- expect(controllers.querySelector('.js-raw-link-controller')).not.toBeNull();
- expect(controllers.querySelector('.js-scroll-up')).not.toBeNull();
- expect(controllers.querySelector('.js-scroll-down')).not.toBeNull();
- });
-
- it('should render received output', () => {
- expect(
- document.querySelector('.js-build-output').innerHTML,
- ).toEqual('<span>Update</span>');
- });
- });
- });
-
- describe('getBuildTrace', () => {
- it('should request build trace with state parameter', (done) => {
- spyOn(axios, 'get').and.callThrough();
- job = new Job();
-
- setTimeout(() => {
- expect(axios.get).toHaveBeenCalledWith(
- `${JOB_URL}/trace.json`, { params: { state: '' } },
- );
- done();
- }, 0);
- });
- });
-});
diff --git a/spec/javascripts/jobs/components/artifacts_block_spec.js b/spec/javascripts/jobs/components/artifacts_block_spec.js
index a06d287b3fa..2fa7ff653fe 100644
--- a/spec/javascripts/jobs/components/artifacts_block_spec.js
+++ b/spec/javascripts/jobs/components/artifacts_block_spec.js
@@ -11,6 +11,19 @@ describe('Artifacts block', () => {
const timeago = getTimeago();
const formatedDate = timeago.format(expireAt);
+ const expiredArtifact = {
+ expire_at: expireAt,
+ expired: true,
+ };
+
+ const nonExpiredArtifact = {
+ download_path: '/gitlab-org/gitlab-ce/-/jobs/98314558/artifacts/download',
+ browse_path: '/gitlab-org/gitlab-ce/-/jobs/98314558/artifacts/browse',
+ keep_path: '/gitlab-org/gitlab-ce/-/jobs/98314558/artifacts/keep',
+ expire_at: expireAt,
+ expired: false,
+ };
+
afterEach(() => {
vm.$destroy();
});
@@ -18,100 +31,87 @@ describe('Artifacts block', () => {
describe('with expired artifacts', () => {
it('renders expired artifact date and info', () => {
vm = mountComponent(Component, {
- haveArtifactsExpired: true,
- willArtifactsExpire: false,
- expireAt,
+ artifact: expiredArtifact,
});
expect(vm.$el.querySelector('.js-artifacts-removed')).not.toBeNull();
expect(vm.$el.querySelector('.js-artifacts-will-be-removed')).toBeNull();
expect(vm.$el.textContent).toContain(formatedDate);
+ expect(vm.$el.querySelector('.js-artifacts-removed').textContent.trim()).toEqual(
+ 'The artifacts were removed',
+ );
});
});
describe('with artifacts that will expire', () => {
it('renders will expire artifact date and info', () => {
vm = mountComponent(Component, {
- haveArtifactsExpired: false,
- willArtifactsExpire: true,
- expireAt,
+ artifact: nonExpiredArtifact,
});
expect(vm.$el.querySelector('.js-artifacts-removed')).toBeNull();
expect(vm.$el.querySelector('.js-artifacts-will-be-removed')).not.toBeNull();
expect(vm.$el.textContent).toContain(formatedDate);
+ expect(vm.$el.querySelector('.js-artifacts-will-be-removed').textContent.trim()).toEqual(
+ 'The artifacts will be removed in',
+ );
});
});
- describe('when the user can keep the artifacts', () => {
+ describe('with keep path', () => {
it('renders the keep button', () => {
vm = mountComponent(Component, {
- haveArtifactsExpired: true,
- willArtifactsExpire: false,
- expireAt,
- keepArtifactsPath: '/keep',
+ artifact: nonExpiredArtifact,
});
expect(vm.$el.querySelector('.js-keep-artifacts')).not.toBeNull();
});
});
- describe('when the user can not keep the artifacts', () => {
+ describe('without keep path', () => {
it('does not render the keep button', () => {
vm = mountComponent(Component, {
- haveArtifactsExpired: true,
- willArtifactsExpire: false,
- expireAt,
+ artifact: expiredArtifact,
});
expect(vm.$el.querySelector('.js-keep-artifacts')).toBeNull();
});
});
- describe('when the user can download the artifacts', () => {
+ describe('with download path', () => {
it('renders the download button', () => {
vm = mountComponent(Component, {
- haveArtifactsExpired: true,
- willArtifactsExpire: false,
- expireAt,
- downloadArtifactsPath: '/download',
+ artifact: nonExpiredArtifact,
});
expect(vm.$el.querySelector('.js-download-artifacts')).not.toBeNull();
});
});
- describe('when the user can not download the artifacts', () => {
+ describe('without download path', () => {
it('does not render the keep button', () => {
vm = mountComponent(Component, {
- haveArtifactsExpired: true,
- willArtifactsExpire: false,
- expireAt,
+ artifact: expiredArtifact,
});
expect(vm.$el.querySelector('.js-download-artifacts')).toBeNull();
});
});
- describe('when the user can browse the artifacts', () => {
+ describe('with browse path', () => {
it('does not render the browse button', () => {
vm = mountComponent(Component, {
- haveArtifactsExpired: true,
- willArtifactsExpire: false,
- expireAt,
- browseArtifactsPath: '/browse',
+ artifact: nonExpiredArtifact,
});
expect(vm.$el.querySelector('.js-browse-artifacts')).not.toBeNull();
});
});
- describe('when the user can not browse the artifacts', () => {
+ describe('without browse path', () => {
it('does not render the browse button', () => {
vm = mountComponent(Component, {
- haveArtifactsExpired: true,
- willArtifactsExpire: false,
- expireAt,
+ artifact: expiredArtifact,
});
expect(vm.$el.querySelector('.js-browse-artifacts')).toBeNull();
diff --git a/spec/javascripts/jobs/components/commit_block_spec.js b/spec/javascripts/jobs/components/commit_block_spec.js
index e21fa9c2874..98eba3ac976 100644
--- a/spec/javascripts/jobs/components/commit_block_spec.js
+++ b/spec/javascripts/jobs/components/commit_block_spec.js
@@ -7,11 +7,16 @@ describe('Commit block', () => {
let vm;
const props = {
- pipelineShortSha: '1f0fb84f',
- pipelineShaPath: 'commit/1f0fb84fb6770d74d97eee58118fd3909cd4f48c',
- mergeRequestReference: '!21244',
- mergeRequestPath: 'merge_requests/21244',
- gitCommitTitlte: 'Regenerate pot files',
+ commit: {
+ short_id: '1f0fb84f',
+ commit_path: 'commit/1f0fb84fb6770d74d97eee58118fd3909cd4f48c',
+ title: 'Update README.md',
+ },
+ mergeRequest: {
+ iid: '!21244',
+ path: 'merge_requests/21244',
+ },
+ isLastBlock: true,
};
afterEach(() => {
@@ -26,12 +31,19 @@ describe('Commit block', () => {
});
it('renders pipeline short sha link', () => {
- expect(vm.$el.querySelector('.js-commit-sha').getAttribute('href')).toEqual(props.pipelineShaPath);
- expect(vm.$el.querySelector('.js-commit-sha').textContent.trim()).toEqual(props.pipelineShortSha);
+ expect(vm.$el.querySelector('.js-commit-sha').getAttribute('href')).toEqual(
+ props.commit.commit_path,
+ );
+
+ expect(vm.$el.querySelector('.js-commit-sha').textContent.trim()).toEqual(
+ props.commit.short_id,
+ );
});
it('renders clipboard button', () => {
- expect(vm.$el.querySelector('button').getAttribute('data-clipboard-text')).toEqual(props.pipelineShortSha);
+ expect(vm.$el.querySelector('button').getAttribute('data-clipboard-text')).toEqual(
+ props.commit.short_id,
+ );
});
});
@@ -41,17 +53,20 @@ describe('Commit block', () => {
...props,
});
- expect(vm.$el.querySelector('.js-link-commit').getAttribute('href')).toEqual(props.mergeRequestPath);
- expect(vm.$el.querySelector('.js-link-commit').textContent.trim()).toEqual(props.mergeRequestReference);
+ expect(vm.$el.querySelector('.js-link-commit').getAttribute('href')).toEqual(
+ props.mergeRequest.path,
+ );
+ expect(vm.$el.querySelector('.js-link-commit').textContent.trim()).toEqual(
+ `!${props.mergeRequest.iid}`,
+ );
});
});
describe('without merge request', () => {
it('does not render merge request', () => {
const copyProps = Object.assign({}, props);
- delete copyProps.mergeRequestPath;
- delete copyProps.mergeRequestReference;
+ delete copyProps.mergeRequest;
vm = mountComponent(Component, {
...copyProps,
@@ -67,7 +82,7 @@ describe('Commit block', () => {
...props,
});
- expect(vm.$el.textContent).toContain(props.gitCommitTitlte);
+ expect(vm.$el.textContent).toContain(props.commit.title);
});
});
});
diff --git a/spec/javascripts/jobs/components/empty_state_spec.js b/spec/javascripts/jobs/components/empty_state_spec.js
index dcc2b3d8a20..a2df79bdda0 100644
--- a/spec/javascripts/jobs/components/empty_state_spec.js
+++ b/spec/javascripts/jobs/components/empty_state_spec.js
@@ -56,6 +56,7 @@ describe('Empty State', () => {
vm = mountComponent(Component, {
...props,
});
+
expect(vm.$el.querySelector('.js-job-empty-state-content')).toBeNull();
});
});
@@ -66,8 +67,8 @@ describe('Empty State', () => {
...props,
content,
action: {
- link: 'runner',
- title: 'Check runner',
+ path: 'runner',
+ button_title: 'Check runner',
method: 'post',
},
});
@@ -83,7 +84,9 @@ describe('Empty State', () => {
vm = mountComponent(Component, {
...props,
content,
+ action: null,
});
+
expect(vm.$el.querySelector('.js-job-empty-state-action')).toBeNull();
});
});
diff --git a/spec/javascripts/jobs/components/environments_block_spec.js b/spec/javascripts/jobs/components/environments_block_spec.js
index 015c26be9fc..0866ddd21d8 100644
--- a/spec/javascripts/jobs/components/environments_block_spec.js
+++ b/spec/javascripts/jobs/components/environments_block_spec.js
@@ -5,19 +5,16 @@ import mountComponent from '../../helpers/vue_mount_component_helper';
describe('Environments block', () => {
const Component = Vue.extend(component);
let vm;
- const icon = {
+ const status = {
group: 'success',
icon: 'status_success',
label: 'passed',
text: 'passed',
tooltip: 'passed',
};
- const deployment = {
- path: 'deployment',
- name: 'deployment name',
- };
+
const environment = {
- path: '/environment',
+ environment_path: '/environment',
name: 'environment',
};
@@ -25,15 +22,14 @@ describe('Environments block', () => {
vm.$destroy();
});
- describe('with latest deployment', () => {
+ describe('with last deployment', () => {
it('renders info for most recent deployment', () => {
vm = mountComponent(Component, {
deploymentStatus: {
- status: 'latest',
- icon,
- deployment,
+ status: 'last',
environment,
},
+ iconStatus: status,
});
expect(vm.$el.textContent.trim()).toEqual(
@@ -48,17 +44,18 @@ describe('Environments block', () => {
vm = mountComponent(Component, {
deploymentStatus: {
status: 'out_of_date',
- icon,
- deployment,
environment: Object.assign({}, environment, {
- last_deployment: { name: 'deployment', path: 'last_deployment' },
+ last_deployment: { iid: 'deployment', deployable: { build_path: 'bar' } },
}),
},
+ iconStatus: status,
});
expect(vm.$el.textContent.trim()).toEqual(
- 'This job is an out-of-date deployment to environment. View the most recent deployment deployment.',
+ 'This job is an out-of-date deployment to environment. View the most recent deployment #deployment.',
);
+
+ expect(vm.$el.querySelector('.js-job-deployment-link').getAttribute('href')).toEqual('bar');
});
});
@@ -67,10 +64,9 @@ describe('Environments block', () => {
vm = mountComponent(Component, {
deploymentStatus: {
status: 'out_of_date',
- icon,
- deployment: null,
environment,
},
+ iconStatus: status,
});
expect(vm.$el.textContent.trim()).toEqual(
@@ -85,10 +81,9 @@ describe('Environments block', () => {
vm = mountComponent(Component, {
deploymentStatus: {
status: 'failed',
- icon,
- deployment: null,
environment,
},
+ iconStatus: status,
});
expect(vm.$el.textContent.trim()).toEqual(
@@ -99,21 +94,25 @@ describe('Environments block', () => {
describe('creating deployment', () => {
describe('with last deployment', () => {
- it('renders info about creating deployment and overriding lastest deployment', () => {
+ it('renders info about creating deployment and overriding latest deployment', () => {
vm = mountComponent(Component, {
deploymentStatus: {
status: 'creating',
- icon,
- deployment,
environment: Object.assign({}, environment, {
- last_deployment: { name: 'deployment', path: 'last_deployment' },
+ last_deployment: {
+ iid: 'deployment',
+ deployable: { build_path: 'foo' },
+ },
}),
},
+ iconStatus: status,
});
expect(vm.$el.textContent.trim()).toEqual(
- 'This job is creating a deployment to environment and will overwrite the last deployment.',
+ 'This job is creating a deployment to environment and will overwrite the latest deployment.',
);
+
+ expect(vm.$el.querySelector('.js-job-deployment-link').getAttribute('href')).toEqual('foo');
});
});
@@ -122,10 +121,9 @@ describe('Environments block', () => {
vm = mountComponent(Component, {
deploymentStatus: {
status: 'creating',
- icon,
- deployment: null,
environment,
},
+ iconStatus: status,
});
expect(vm.$el.textContent.trim()).toEqual(
@@ -133,5 +131,19 @@ describe('Environments block', () => {
);
});
});
+
+ describe('without environment', () => {
+ it('does not render environment link', () => {
+ vm = mountComponent(Component, {
+ deploymentStatus: {
+ status: 'creating',
+ environment: null,
+ },
+ iconStatus: status,
+ });
+
+ expect(vm.$el.querySelector('.js-environment-link')).toBeNull();
+ });
+ });
});
});
diff --git a/spec/javascripts/jobs/components/erased_block_spec.js b/spec/javascripts/jobs/components/erased_block_spec.js
index a4ae0c7c81e..8e0433d3fb7 100644
--- a/spec/javascripts/jobs/components/erased_block_spec.js
+++ b/spec/javascripts/jobs/components/erased_block_spec.js
@@ -18,9 +18,10 @@ describe('Erased block', () => {
describe('with job erased by user', () => {
beforeEach(() => {
vm = mountComponent(Component, {
- erasedByUser: true,
- username: 'root',
- linkToUser: 'gitlab.com/root',
+ user: {
+ username: 'root',
+ web_url: 'gitlab.com/root',
+ },
erasedAt,
});
});
@@ -40,7 +41,6 @@ describe('Erased block', () => {
describe('with erased job', () => {
beforeEach(() => {
vm = mountComponent(Component, {
- erasedByUser: false,
erasedAt,
});
});
diff --git a/spec/javascripts/jobs/components/header_spec.js b/spec/javascripts/jobs/components/header_spec.js
deleted file mode 100644
index e21e2c6d6e3..00000000000
--- a/spec/javascripts/jobs/components/header_spec.js
+++ /dev/null
@@ -1,98 +0,0 @@
-import Vue from 'vue';
-import headerComponent from '~/jobs/components/header.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-describe('Job details header', () => {
- let HeaderComponent;
- let vm;
- let props;
-
- beforeEach(() => {
- HeaderComponent = Vue.extend(headerComponent);
-
- const threeWeeksAgo = new Date();
- threeWeeksAgo.setDate(threeWeeksAgo.getDate() - 21);
-
- const twoDaysAgo = new Date();
- twoDaysAgo.setDate(twoDaysAgo.getDate() - 2);
-
- props = {
- job: {
- status: {
- group: 'failed',
- icon: 'status_failed',
- label: 'failed',
- text: 'failed',
- details_path: 'path',
- },
- id: 123,
- created_at: threeWeeksAgo.toISOString(),
- user: {
- web_url: 'path',
- name: 'Foo',
- username: 'foobar',
- email: 'foo@bar.com',
- avatar_url: 'link',
- },
- started: twoDaysAgo.toISOString(),
- new_issue_path: 'path',
- },
- isLoading: false,
- };
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('job reason', () => {
- it('should not render the reason when reason is absent', () => {
- vm = mountComponent(HeaderComponent, props);
-
- expect(vm.shouldRenderReason).toBe(false);
- });
-
- it('should render the reason when reason is present', () => {
- props.job.callout_message = 'There is an unknown failure, please try again';
-
- vm = mountComponent(HeaderComponent, props);
-
- expect(vm.shouldRenderReason).toBe(true);
- });
- });
-
- describe('triggered job', () => {
- beforeEach(() => {
- vm = mountComponent(HeaderComponent, props);
- });
-
- it('should render provided job information', () => {
- expect(
- vm.$el
- .querySelector('.header-main-content')
- .textContent.replace(/\s+/g, ' ')
- .trim(),
- ).toEqual('failed Job #123 triggered 2 days ago by Foo');
- });
-
- it('should render new issue link', () => {
- expect(vm.$el.querySelector('.js-new-issue').getAttribute('href')).toEqual(
- props.job.new_issue_path,
- );
- });
- });
-
- describe('created job', () => {
- it('should render created key', () => {
- props.job.started = false;
- vm = mountComponent(HeaderComponent, props);
-
- expect(
- vm.$el
- .querySelector('.header-main-content')
- .textContent.replace(/\s+/g, ' ')
- .trim(),
- ).toEqual('failed Job #123 created 3 weeks ago by Foo');
- });
- });
-});
diff --git a/spec/javascripts/jobs/components/job_app_spec.js b/spec/javascripts/jobs/components/job_app_spec.js
new file mode 100644
index 00000000000..ba5d672f189
--- /dev/null
+++ b/spec/javascripts/jobs/components/job_app_spec.js
@@ -0,0 +1,633 @@
+import Vue from 'vue';
+import MockAdapter from 'axios-mock-adapter';
+import axios from '~/lib/utils/axios_utils';
+import jobApp from '~/jobs/components/job_app.vue';
+import createStore from '~/jobs/store';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import { resetStore } from '../store/helpers';
+import job from '../mock_data';
+
+describe('Job App ', () => {
+ const delayedJobFixture = getJSONFixture('jobs/delayed.json');
+ const Component = Vue.extend(jobApp);
+ let store;
+ let vm;
+ let mock;
+
+ const props = {
+ endpoint: `${gl.TEST_HOST}jobs/123.json`,
+ runnerHelpUrl: 'help/runner',
+ runnerSettingsUrl: 'settings/ci-cd/runners',
+ terminalPath: 'jobs/123/terminal',
+ pagePath: `${gl.TEST_HOST}jobs/123`,
+ logState:
+ 'eyJvZmZzZXQiOjE3NDUxLCJuX29wZW5fdGFncyI6MCwiZmdfY29sb3IiOm51bGwsImJnX2NvbG9yIjpudWxsLCJzdHlsZV9tYXNrIjowfQ%3D%3D',
+ };
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ store = createStore();
+ });
+
+ afterEach(() => {
+ resetStore(store);
+ vm.$destroy();
+ mock.restore();
+ });
+
+ describe('while loading', () => {
+ beforeEach(() => {
+ mock.onGet(props.endpoint).reply(200, job, {});
+ mock.onGet(`${props.pagePath}/trace.json`).reply(200, {});
+ vm = mountComponentWithStore(Component, { props, store });
+ });
+
+ it('renders loading icon', done => {
+ expect(vm.$el.querySelector('.js-job-loading')).not.toBeNull();
+ expect(vm.$el.querySelector('.js-job-sidebar')).toBeNull();
+ expect(vm.$el.querySelector('.js-job-content')).toBeNull();
+
+ setTimeout(() => {
+ done();
+ }, 0);
+ });
+ });
+
+ describe('with successful request', () => {
+ beforeEach(() => {
+ mock.onGet(`${props.pagePath}/trace.json`).replyOnce(200, {});
+ });
+
+ describe('Header section', () => {
+ describe('job callout message', () => {
+ it('should not render the reason when reason is absent', done => {
+ mock.onGet(props.endpoint).replyOnce(200, job);
+ vm = mountComponentWithStore(Component, { props, store });
+
+ setTimeout(() => {
+ expect(vm.shouldRenderCalloutMessage).toBe(false);
+
+ done();
+ }, 0);
+ });
+
+ it('should render the reason when reason is present', done => {
+ mock.onGet(props.endpoint).replyOnce(
+ 200,
+ Object.assign({}, job, {
+ callout_message: 'There is an unknown failure, please try again',
+ }),
+ );
+
+ vm = mountComponentWithStore(Component, { props, store });
+ setTimeout(() => {
+ expect(vm.shouldRenderCalloutMessage).toBe(true);
+ done();
+ }, 0);
+ });
+ });
+
+ describe('triggered job', () => {
+ beforeEach(() => {
+ mock
+ .onGet(props.endpoint)
+ .replyOnce(200, Object.assign({}, job, { started: '2017-05-24T10:59:52.000+01:00' }));
+ vm = mountComponentWithStore(Component, { props, store });
+ });
+
+ it('should render provided job information', done => {
+ setTimeout(() => {
+ expect(
+ vm.$el
+ .querySelector('.header-main-content')
+ .textContent.replace(/\s+/g, ' ')
+ .trim(),
+ ).toContain('passed Job #4757 triggered 1 year ago by Root');
+ done();
+ }, 0);
+ });
+
+ it('should render new issue link', done => {
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-new-issue').getAttribute('href')).toEqual(
+ job.new_issue_path,
+ );
+ done();
+ }, 0);
+ });
+ });
+
+ describe('created job', () => {
+ it('should render created key', done => {
+ mock.onGet(props.endpoint).replyOnce(200, job);
+ vm = mountComponentWithStore(Component, { props, store });
+
+ setTimeout(() => {
+ expect(
+ vm.$el
+ .querySelector('.header-main-content')
+ .textContent.replace(/\s+/g, ' ')
+ .trim(),
+ ).toContain('passed Job #4757 created 3 weeks ago by Root');
+ done();
+ }, 0);
+ });
+ });
+ });
+
+ describe('stuck block', () => {
+ describe('without active runners availabl', () => {
+ it('renders stuck block when there are no runners', done => {
+ mock.onGet(props.endpoint).replyOnce(
+ 200,
+ Object.assign({}, job, {
+ status: {
+ group: 'pending',
+ icon: 'status_pending',
+ label: 'pending',
+ text: 'pending',
+ details_path: 'path',
+ },
+ stuck: true,
+ runners: {
+ available: false,
+ online: false,
+ },
+ tags: [],
+ }),
+ );
+ vm = mountComponentWithStore(Component, { props, store });
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-stuck')).not.toBeNull();
+ expect(vm.$el.querySelector('.js-job-stuck .js-stuck-no-active-runner')).not.toBeNull();
+ done();
+ }, 0);
+ });
+ });
+
+ describe('when available runners can not run specified tag', () => {
+ it('renders tags in stuck block when there are no runners', done => {
+ mock.onGet(props.endpoint).replyOnce(
+ 200,
+ Object.assign({}, job, {
+ status: {
+ group: 'pending',
+ icon: 'status_pending',
+ label: 'pending',
+ text: 'pending',
+ details_path: 'path',
+ },
+ stuck: true,
+ runners: {
+ available: false,
+ online: false,
+ },
+ }),
+ );
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-stuck').textContent).toContain(job.tags[0]);
+ expect(vm.$el.querySelector('.js-job-stuck .js-stuck-with-tags')).not.toBeNull();
+ done();
+ }, 0);
+ });
+ });
+
+ describe('when runners are offline and build has tags', () => {
+ it('renders message about job being stuck because of no runners with the specified tags', done => {
+ mock.onGet(props.endpoint).replyOnce(
+ 200,
+ Object.assign({}, job, {
+ status: {
+ group: 'pending',
+ icon: 'status_pending',
+ label: 'pending',
+ text: 'pending',
+ details_path: 'path',
+ },
+ stuck: true,
+ runners: {
+ available: true,
+ online: true,
+ },
+ }),
+ );
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-stuck').textContent).toContain(job.tags[0]);
+ expect(vm.$el.querySelector('.js-job-stuck .js-stuck-with-tags')).not.toBeNull();
+ done();
+ }, 0);
+ });
+ });
+
+ it('does not renders stuck block when there are no runners', done => {
+ mock.onGet(props.endpoint).replyOnce(
+ 200,
+ Object.assign({}, job, {
+ runners: { available: true },
+ }),
+ );
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-stuck')).toBeNull();
+
+ done();
+ }, 0);
+ });
+ });
+
+ describe('environments block', () => {
+ it('renders environment block when job has environment', done => {
+ mock.onGet(props.endpoint).replyOnce(
+ 200,
+ Object.assign({}, job, {
+ deployment_status: {
+ environment: {
+ environment_path: '/path',
+ name: 'foo',
+ },
+ },
+ }),
+ );
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-environment')).not.toBeNull();
+
+ done();
+ }, 0);
+ });
+
+ it('does not render environment block when job has environment', done => {
+ mock.onGet(props.endpoint).replyOnce(200, job);
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-environment')).toBeNull();
+ done();
+ }, 0);
+ });
+ });
+
+ describe('erased block', () => {
+ it('renders erased block when `erased` is true', done => {
+ mock.onGet(props.endpoint).replyOnce(
+ 200,
+ Object.assign({}, job, {
+ erased_by: {
+ username: 'root',
+ web_url: 'gitlab.com/root',
+ },
+ erased_at: '2016-11-07T11:11:16.525Z',
+ }),
+ );
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-erased-block')).not.toBeNull();
+
+ done();
+ }, 0);
+ });
+
+ it('does not render erased block when `erased` is false', done => {
+ mock.onGet(props.endpoint).replyOnce(200, Object.assign({}, job, { erased_at: null }));
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-erased-block')).toBeNull();
+
+ done();
+ }, 0);
+ });
+ });
+
+ describe('empty states block', () => {
+ it('renders empty state when job does not have trace and is not running', done => {
+ mock.onGet(props.endpoint).replyOnce(
+ 200,
+ Object.assign({}, job, {
+ has_trace: false,
+ status: {
+ group: 'pending',
+ icon: 'status_pending',
+ label: 'pending',
+ text: 'pending',
+ details_path: 'path',
+ illustration: {
+ image: 'path',
+ size: '340',
+ title: 'Empty State',
+ content: 'This is an empty state',
+ },
+ action: {
+ button_title: 'Retry job',
+ method: 'post',
+ path: '/path',
+ },
+ },
+ }),
+ );
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-empty-state')).not.toBeNull();
+
+ done();
+ }, 0);
+ });
+
+ it('does not render empty state when job does not have trace but it is running', done => {
+ mock.onGet(props.endpoint).replyOnce(
+ 200,
+ Object.assign({}, job, {
+ has_trace: false,
+ status: {
+ group: 'running',
+ icon: 'status_running',
+ label: 'running',
+ text: 'running',
+ details_path: 'path',
+ },
+ }),
+ );
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-empty-state')).toBeNull();
+
+ done();
+ }, 0);
+ });
+
+ it('does not render empty state when job has trace but it is not running', done => {
+ mock.onGet(props.endpoint).replyOnce(200, Object.assign({}, job, { has_trace: true }));
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-job-empty-state')).toBeNull();
+
+ done();
+ }, 0);
+ });
+
+ it('displays remaining time for a delayed job', done => {
+ const oneHourInMilliseconds = 3600000;
+ spyOn(Date, 'now').and.callFake(
+ () => new Date(delayedJobFixture.scheduled_at).getTime() - oneHourInMilliseconds,
+ );
+ mock.onGet(props.endpoint).replyOnce(200, { ...delayedJobFixture });
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ store.subscribeAction(action => {
+ if (action.type !== 'receiveJobSuccess') {
+ return;
+ }
+
+ Vue.nextTick()
+ .then(() => {
+ expect(vm.$el.querySelector('.js-job-empty-state')).not.toBeNull();
+
+ const title = vm.$el.querySelector('.js-job-empty-state-title');
+
+ expect(title).toContainText('01:00:00');
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
+ });
+ });
+
+ describe('archived job', () => {
+ beforeEach(() => {
+ mock.onGet(props.endpoint).reply(200, Object.assign({}, job, { archived: true }), {});
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+ });
+
+ it('renders warning about job being archived', done => {
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-archived-job ')).not.toBeNull();
+ done();
+ }, 0);
+ });
+ });
+
+ describe('non-archived job', () => {
+ beforeEach(() => {
+ mock.onGet(props.endpoint).reply(200, job, {});
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+ });
+
+ it('does not warning about job being archived', done => {
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-archived-job ')).toBeNull();
+ done();
+ }, 0);
+ });
+ });
+
+ describe('trace output', () => {
+ beforeEach(() => {
+ mock.onGet(props.endpoint).reply(200, job, {});
+ });
+
+ describe('with append flag', () => {
+ it('appends the log content to the existing one', done => {
+ mock.onGet(`${props.pagePath}/trace.json`).reply(200, {
+ html: '<span>More<span>',
+ status: 'running',
+ state: 'newstate',
+ append: true,
+ complete: true,
+ });
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ vm.$store.state.trace = 'Update';
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-build-trace').textContent.trim()).toContain('Update');
+
+ done();
+ }, 0);
+ });
+ });
+
+ describe('without append flag', () => {
+ it('replaces the trace', done => {
+ mock.onGet(`${props.pagePath}/trace.json`).reply(200, {
+ html: '<span>Different<span>',
+ status: 'running',
+ append: false,
+ complete: true,
+ });
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+ vm.$store.state.trace = 'Update';
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-build-trace').textContent.trim()).not.toContain(
+ 'Update',
+ );
+
+ expect(vm.$el.querySelector('.js-build-trace').textContent.trim()).toContain('Different');
+ done();
+ }, 0);
+ });
+ });
+
+ describe('truncated information', () => {
+ describe('when size is less than total', () => {
+ it('shows information about truncated log', done => {
+ mock.onGet(`${props.pagePath}/trace.json`).reply(200, {
+ html: '<span>Update</span>',
+ status: 'success',
+ append: false,
+ size: 50,
+ total: 100,
+ complete: true,
+ });
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-truncated-info').textContent.trim()).toContain(
+ '50 bytes',
+ );
+ done();
+ }, 0);
+ });
+ });
+
+ describe('when size is equal than total', () => {
+ it('does not show the truncated information', done => {
+ mock.onGet(`${props.pagePath}/trace.json`).reply(200, {
+ html: '<span>Update</span>',
+ status: 'success',
+ append: false,
+ size: 100,
+ total: 100,
+ complete: true,
+ });
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-truncated-info').textContent.trim()).not.toContain(
+ '50 bytes',
+ );
+ done();
+ }, 0);
+ });
+ });
+ });
+
+ describe('trace controls', () => {
+ beforeEach(() => {
+ mock.onGet(`${props.pagePath}/trace.json`).reply(200, {
+ html: '<span>Update</span>',
+ status: 'success',
+ append: false,
+ size: 50,
+ total: 100,
+ complete: true,
+ });
+
+ vm = mountComponentWithStore(Component, {
+ props,
+ store,
+ });
+ });
+
+ it('should render scroll buttons', done => {
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-scroll-top')).not.toBeNull();
+ expect(vm.$el.querySelector('.js-scroll-bottom')).not.toBeNull();
+ done();
+ }, 0);
+ });
+
+ it('should render link to raw ouput', done => {
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-raw-link-controller')).not.toBeNull();
+ done();
+ }, 0);
+ });
+
+ it('should render link to erase job', done => {
+ setTimeout(() => {
+ expect(vm.$el.querySelector('.js-erase-link')).not.toBeNull();
+ done();
+ }, 0);
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/jobs/components/job_container_item_spec.js b/spec/javascripts/jobs/components/job_container_item_spec.js
new file mode 100644
index 00000000000..2d108f1ad7f
--- /dev/null
+++ b/spec/javascripts/jobs/components/job_container_item_spec.js
@@ -0,0 +1,99 @@
+import Vue from 'vue';
+import JobContainerItem from '~/jobs/components/job_container_item.vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import job from '../mock_data';
+
+describe('JobContainerItem', () => {
+ const delayedJobFixture = getJSONFixture('jobs/delayed.json');
+ const Component = Vue.extend(JobContainerItem);
+ let vm;
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ const sharedTests = () => {
+ it('displays a status icon', () => {
+ expect(vm.$el).toHaveSpriteIcon(job.status.icon);
+ });
+
+ it('displays the job name', () => {
+ expect(vm.$el).toContainText(job.name);
+ });
+
+ it('displays a link to the job', () => {
+ const link = vm.$el.querySelector('.js-job-link');
+
+ expect(link.href).toBe(job.status.details_path);
+ });
+ };
+
+ describe('when a job is not active and not retied', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ job,
+ isActive: false,
+ });
+ });
+
+ sharedTests();
+ });
+
+ describe('when a job is active', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ job,
+ isActive: true,
+ });
+ });
+
+ sharedTests();
+
+ it('displays an arrow', () => {
+ expect(vm.$el).toHaveSpriteIcon('arrow-right');
+ });
+ });
+
+ describe('when a job is retried', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ job: {
+ ...job,
+ retried: true,
+ },
+ isActive: false,
+ });
+ });
+
+ sharedTests();
+
+ it('displays an icon', () => {
+ expect(vm.$el).toHaveSpriteIcon('retry');
+ });
+ });
+
+ describe('for delayed job', () => {
+ beforeEach(() => {
+ const remainingMilliseconds = 1337000;
+ spyOn(Date, 'now').and.callFake(
+ () => new Date(delayedJobFixture.scheduled_at).getTime() - remainingMilliseconds,
+ );
+ });
+
+ it('displays remaining time in tooltip', done => {
+ vm = mountComponent(Component, {
+ job: delayedJobFixture,
+ isActive: false,
+ });
+
+ Vue.nextTick()
+ .then(() => {
+ expect(vm.$el.querySelector('.js-job-link').getAttribute('data-original-title')).toEqual(
+ 'delayed job - delayed manual action (00:22:17)',
+ );
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+});
diff --git a/spec/javascripts/jobs/components/job_details_mediator_spec.js b/spec/javascripts/jobs/components/job_details_mediator_spec.js
deleted file mode 100644
index 3e2fb7bfbbb..00000000000
--- a/spec/javascripts/jobs/components/job_details_mediator_spec.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import axios from '~/lib/utils/axios_utils';
-import JobMediator from '~/jobs/job_details_mediator';
-import job from '../mock_data';
-
-describe('JobMediator', () => {
- let mediator;
- let mock;
-
- beforeEach(() => {
- mediator = new JobMediator({ endpoint: 'jobs/40291672.json' });
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('should set defaults', () => {
- expect(mediator.store).toBeDefined();
- expect(mediator.service).toBeDefined();
- expect(mediator.options).toEqual({ endpoint: 'jobs/40291672.json' });
- expect(mediator.state.isLoading).toEqual(false);
- });
-
- describe('request and store data', () => {
- beforeEach(() => {
- mock.onGet().reply(200, job, {});
- });
-
- it('should store received data', (done) => {
- mediator.fetchJob();
- setTimeout(() => {
- expect(mediator.store.state.job).toEqual(job);
- done();
- }, 0);
- });
- });
-});
diff --git a/spec/javascripts/jobs/components/job_log_controllers_spec.js b/spec/javascripts/jobs/components/job_log_controllers_spec.js
index 416dfab8a48..d527c6708fc 100644
--- a/spec/javascripts/jobs/components/job_log_controllers_spec.js
+++ b/spec/javascripts/jobs/components/job_log_controllers_spec.js
@@ -10,50 +10,52 @@ describe('Job log controllers', () => {
vm.$destroy();
});
- describe('Truncate information', () => {
+ const props = {
+ rawPath: '/raw',
+ erasePath: '/erase',
+ size: 511952,
+ isScrollTopDisabled: false,
+ isScrollBottomDisabled: false,
+ isScrollingDown: true,
+ isTraceSizeVisible: true,
+ };
- beforeEach(() => {
- vm = mountComponent(Component, {
- rawTracePath: '/raw',
- canEraseJob: true,
- size: 511952,
- canScrollToTop: true,
- canScrollToBottom: true,
+ describe('Truncate information', () => {
+ describe('with isTraceSizeVisible', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, props);
});
- });
- it('renders size information', () => {
- expect(vm.$el.querySelector('.js-truncated-info').textContent).toContain('499.95 KiB');
- });
+ it('renders size information', () => {
+ expect(vm.$el.querySelector('.js-truncated-info').textContent).toContain('499.95 KiB');
+ });
- it('renders link to raw trace', () => {
- expect(vm.$el.querySelector('.js-raw-link').getAttribute('href')).toEqual('/raw');
+ it('renders link to raw trace', () => {
+ expect(vm.$el.querySelector('.js-raw-link').getAttribute('href')).toEqual('/raw');
+ });
});
-
});
describe('links section', () => {
describe('with raw trace path', () => {
it('renders raw trace link', () => {
- vm = mountComponent(Component, {
- rawTracePath: '/raw',
- canEraseJob: true,
- size: 511952,
- canScrollToTop: true,
- canScrollToBottom: true,
- });
+ vm = mountComponent(Component, props);
- expect(vm.$el.querySelector('.js-raw-link-controller').getAttribute('href')).toEqual('/raw');
+ expect(vm.$el.querySelector('.js-raw-link-controller').getAttribute('href')).toEqual(
+ '/raw',
+ );
});
});
describe('without raw trace path', () => {
it('does not render raw trace link', () => {
vm = mountComponent(Component, {
- canEraseJob: true,
+ erasePath: '/erase',
size: 511952,
- canScrollToTop: true,
- canScrollToBottom: true,
+ isScrollTopDisabled: true,
+ isScrollBottomDisabled: true,
+ isScrollingDown: false,
+ isTraceSizeVisible: true,
});
expect(vm.$el.querySelector('.js-raw-link-controller')).toBeNull();
@@ -62,52 +64,23 @@ describe('Job log controllers', () => {
describe('when is erasable', () => {
beforeEach(() => {
- vm = mountComponent(Component, {
- rawTracePath: '/raw',
- canEraseJob: true,
- size: 511952,
- canScrollToTop: true,
- canScrollToBottom: true,
- });
+ vm = mountComponent(Component, props);
});
- it('renders erase job button', () => {
+ it('renders erase job link', () => {
expect(vm.$el.querySelector('.js-erase-link')).not.toBeNull();
});
-
- describe('on click', () => {
- describe('when user confirms action', () => {
- it('emits eraseJob event', () => {
- spyOn(window, 'confirm').and.returnValue(true);
- spyOn(vm, '$emit');
-
- vm.$el.querySelector('.js-erase-link').click();
-
- expect(vm.$emit).toHaveBeenCalledWith('eraseJob');
- });
- });
-
- describe('when user does not confirm action', () => {
- it('does not emit eraseJob event', () => {
- spyOn(window, 'confirm').and.returnValue(false);
- spyOn(vm, '$emit');
-
- vm.$el.querySelector('.js-erase-link').click();
-
- expect(vm.$emit).not.toHaveBeenCalledWith('eraseJob');
- });
- });
- });
});
describe('when it is not erasable', () => {
it('does not render erase button', () => {
vm = mountComponent(Component, {
- rawTracePath: '/raw',
- canEraseJob: false,
+ rawPath: '/raw',
size: 511952,
- canScrollToTop: true,
- canScrollToBottom: true,
+ isScrollTopDisabled: true,
+ isScrollBottomDisabled: true,
+ isScrollingDown: false,
+ isTraceSizeVisible: true,
});
expect(vm.$el.querySelector('.js-erase-link')).toBeNull();
@@ -119,13 +92,7 @@ describe('Job log controllers', () => {
describe('scroll top button', () => {
describe('when user can scroll top', () => {
beforeEach(() => {
- vm = mountComponent(Component, {
- rawTracePath: '/raw',
- canEraseJob: true,
- size: 511952,
- canScrollToTop: true,
- canScrollToBottom: true,
- });
+ vm = mountComponent(Component, props);
});
it('renders enabled scroll top button', () => {
@@ -143,16 +110,20 @@ describe('Job log controllers', () => {
describe('when user can not scroll top', () => {
beforeEach(() => {
vm = mountComponent(Component, {
- rawTracePath: '/raw',
- canEraseJob: true,
+ rawPath: '/raw',
+ erasePath: '/erase',
size: 511952,
- canScrollToTop: false,
- canScrollToBottom: true,
+ isScrollTopDisabled: true,
+ isScrollBottomDisabled: false,
+ isScrollingDown: false,
+ isTraceSizeVisible: true,
});
});
it('renders disabled scroll top button', () => {
- expect(vm.$el.querySelector('.js-scroll-top').getAttribute('disabled')).toEqual('disabled');
+ expect(vm.$el.querySelector('.js-scroll-top').getAttribute('disabled')).toEqual(
+ 'disabled',
+ );
});
it('does not emit scrollJobLogTop event on click', () => {
@@ -167,13 +138,7 @@ describe('Job log controllers', () => {
describe('scroll bottom button', () => {
describe('when user can scroll bottom', () => {
beforeEach(() => {
- vm = mountComponent(Component, {
- rawTracePath: '/raw',
- canEraseJob: true,
- size: 511952,
- canScrollToTop: true,
- canScrollToBottom: true,
- });
+ vm = mountComponent(Component, props);
});
it('renders enabled scroll bottom button', () => {
@@ -191,17 +156,20 @@ describe('Job log controllers', () => {
describe('when user can not scroll bottom', () => {
beforeEach(() => {
vm = mountComponent(Component, {
- rawTracePath: '/raw',
- canEraseJob: true,
+ rawPath: '/raw',
+ erasePath: '/erase',
size: 511952,
- canScrollToTop: true,
- canScrollToBottom: false,
+ isScrollTopDisabled: false,
+ isScrollBottomDisabled: true,
+ isScrollingDown: false,
+ isTraceSizeVisible: true,
});
});
it('renders disabled scroll bottom button', () => {
- expect(vm.$el.querySelector('.js-scroll-bottom').getAttribute('disabled')).toEqual('disabled');
-
+ expect(vm.$el.querySelector('.js-scroll-bottom').getAttribute('disabled')).toEqual(
+ 'disabled',
+ );
});
it('does not emit scrollJobLogBottom event on click', () => {
@@ -211,7 +179,30 @@ describe('Job log controllers', () => {
expect(vm.$emit).not.toHaveBeenCalledWith('scrollJobLogBottom');
});
});
+
+ describe('while isScrollingDown is true', () => {
+ it('renders animate class for the scroll down button', () => {
+ vm = mountComponent(Component, props);
+
+ expect(vm.$el.querySelector('.js-scroll-bottom').className).toContain('animate');
+ });
+ });
+
+ describe('while isScrollingDown is false', () => {
+ it('does not render animate class for the scroll down button', () => {
+ vm = mountComponent(Component, {
+ rawPath: '/raw',
+ erasePath: '/erase',
+ size: 511952,
+ isScrollTopDisabled: true,
+ isScrollBottomDisabled: false,
+ isScrollingDown: false,
+ isTraceSizeVisible: true,
+ });
+
+ expect(vm.$el.querySelector('.js-scroll-bottom').className).not.toContain('animate');
+ });
+ });
});
});
});
-
diff --git a/spec/javascripts/jobs/components/job_log_spec.js b/spec/javascripts/jobs/components/job_log_spec.js
index 6a5b375a26c..dc0f77ceb80 100644
--- a/spec/javascripts/jobs/components/job_log_spec.js
+++ b/spec/javascripts/jobs/components/job_log_spec.js
@@ -1,31 +1,48 @@
import Vue from 'vue';
import component from '~/jobs/components/job_log.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
+import createStore from '~/jobs/store';
+import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper';
+import { resetStore } from '../store/helpers';
describe('Job Log', () => {
const Component = Vue.extend(component);
+ let store;
let vm;
- const trace = 'Running with gitlab-runner 11.1.0 (081978aa)<br> on docker-auto-scale-com d5ae8d25<br>Using Docker executor with image dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.4.4-golang-1.9-git-2.18-chrome-67.0-node-8.x-yarn-1.2-postgresql-9.6-graphicsmagick-1.3.29 ...<br>';
+ const trace =
+ 'Running with gitlab-runner 11.1.0 (081978aa)<br> on docker-auto-scale-com d5ae8d25<br>Using Docker executor with image dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.4.4-golang-1.9-git-2.18-chrome-67.0-node-8.x-yarn-1.2-postgresql-9.6-graphicsmagick-1.3.29 ...<br>';
+
+ beforeEach(() => {
+ store = createStore();
+ });
afterEach(() => {
+ resetStore(store);
vm.$destroy();
});
it('renders provided trace', () => {
- vm = mountComponent(Component, {
- trace,
- isReceivingBuildTrace: true,
+ vm = mountComponentWithStore(Component, {
+ props: {
+ trace,
+ isComplete: true,
+ },
+ store,
});
- expect(vm.$el.querySelector('code').textContent).toContain('Running with gitlab-runner 11.1.0 (081978aa)');
+ expect(vm.$el.querySelector('code').textContent).toContain(
+ 'Running with gitlab-runner 11.1.0 (081978aa)',
+ );
});
describe('while receiving trace', () => {
it('renders animation', () => {
- vm = mountComponent(Component, {
- trace,
- isReceivingBuildTrace: true,
+ vm = mountComponentWithStore(Component, {
+ props: {
+ trace,
+ isComplete: false,
+ },
+ store,
});
expect(vm.$el.querySelector('.js-log-animation')).not.toBeNull();
@@ -34,9 +51,12 @@ describe('Job Log', () => {
describe('when build trace has finishes', () => {
it('does not render animation', () => {
- vm = mountComponent(Component, {
- trace,
- isReceivingBuildTrace: false,
+ vm = mountComponentWithStore(Component, {
+ props: {
+ trace,
+ isComplete: true,
+ },
+ store,
});
expect(vm.$el.querySelector('.js-log-animation')).toBeNull();
diff --git a/spec/javascripts/jobs/components/job_store_spec.js b/spec/javascripts/jobs/components/job_store_spec.js
deleted file mode 100644
index 0dad5111b32..00000000000
--- a/spec/javascripts/jobs/components/job_store_spec.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import JobStore from '~/jobs/stores/job_store';
-import job from '../mock_data';
-
-describe('Job Store', () => {
- let store;
-
- beforeEach(() => {
- store = new JobStore();
- });
-
- it('should set defaults', () => {
- expect(store.state.job).toEqual({});
- });
-
- describe('storeJob', () => {
- it('should store empty object if none is provided', () => {
- store.storeJob();
- expect(store.state.job).toEqual({});
- });
-
- it('should store provided argument', () => {
- store.storeJob(job);
- expect(store.state.job).toEqual(job);
- });
- });
-});
diff --git a/spec/javascripts/jobs/components/jobs_container_spec.js b/spec/javascripts/jobs/components/jobs_container_spec.js
index f3f8ff0d031..fa3a2c4c266 100644
--- a/spec/javascripts/jobs/components/jobs_container_spec.js
+++ b/spec/javascripts/jobs/components/jobs_container_spec.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import component from '~/jobs/components/jobs_container.vue';
import mountComponent from '../../helpers/vue_mount_component_helper';
-describe('Artifacts block', () => {
+describe('Jobs List block', () => {
const Component = Vue.extend(component);
let vm;
@@ -16,8 +16,7 @@ describe('Artifacts block', () => {
text: 'passed',
tooltip: 'passed',
},
- path: 'job/233432756',
- id: '233432756',
+ id: 233432756,
tooltip: 'build - passed',
retried: true,
};
@@ -33,8 +32,7 @@ describe('Artifacts block', () => {
text: 'passed',
tooltip: 'passed',
},
- path: 'job/2322756',
- id: '2322756',
+ id: 2322756,
tooltip: 'build - passed',
active: true,
};
@@ -50,8 +48,7 @@ describe('Artifacts block', () => {
text: 'passed',
tooltip: 'passed',
},
- path: 'job/232153',
- id: '232153',
+ id: 232153,
tooltip: 'build - passed',
};
@@ -62,14 +59,16 @@ describe('Artifacts block', () => {
it('renders list of jobs', () => {
vm = mountComponent(Component, {
jobs: [job, retried, active],
+ jobId: 12313,
});
expect(vm.$el.querySelectorAll('a').length).toEqual(3);
});
- it('renders arrow right when job is active', () => {
+ it('renders arrow right when job id matches `jobId`', () => {
vm = mountComponent(Component, {
jobs: [active],
+ jobId: active.id,
});
expect(vm.$el.querySelector('a .js-arrow-right')).not.toBeNull();
@@ -78,6 +77,7 @@ describe('Artifacts block', () => {
it('does not render arrow right when job is not active', () => {
vm = mountComponent(Component, {
jobs: [job],
+ jobId: active.id,
});
expect(vm.$el.querySelector('a .js-arrow-right')).toBeNull();
@@ -86,6 +86,7 @@ describe('Artifacts block', () => {
it('renders job name when present', () => {
vm = mountComponent(Component, {
jobs: [job],
+ jobId: active.id,
});
expect(vm.$el.querySelector('a').textContent.trim()).toContain(job.name);
@@ -95,6 +96,7 @@ describe('Artifacts block', () => {
it('renders job id when job name is not available', () => {
vm = mountComponent(Component, {
jobs: [retried],
+ jobId: active.id,
});
expect(vm.$el.querySelector('a').textContent.trim()).toContain(retried.id);
@@ -103,14 +105,16 @@ describe('Artifacts block', () => {
it('links to the job page', () => {
vm = mountComponent(Component, {
jobs: [job],
+ jobId: active.id,
});
- expect(vm.$el.querySelector('a').getAttribute('href')).toEqual(job.path);
+ expect(vm.$el.querySelector('a').getAttribute('href')).toEqual(job.status.details_path);
});
it('renders retry icon when job was retried', () => {
vm = mountComponent(Component, {
jobs: [retried],
+ jobId: active.id,
});
expect(vm.$el.querySelector('.js-retry-icon')).not.toBeNull();
@@ -119,6 +123,7 @@ describe('Artifacts block', () => {
it('does not render retry icon when job was not retried', () => {
vm = mountComponent(Component, {
jobs: [job],
+ jobId: active.id,
});
expect(vm.$el.querySelector('.js-retry-icon')).toBeNull();
diff --git a/spec/javascripts/jobs/components/sidebar_detail_row_spec.js b/spec/javascripts/jobs/components/sidebar_detail_row_spec.js
index e6bfb0c4adc..42d11266dad 100644
--- a/spec/javascripts/jobs/components/sidebar_detail_row_spec.js
+++ b/spec/javascripts/jobs/components/sidebar_detail_row_spec.js
@@ -33,9 +33,9 @@ describe('Sidebar detail row', () => {
});
it('should render provided title and value', () => {
- expect(
- vm.$el.textContent.replace(/\s+/g, ' ').trim(),
- ).toEqual('this is the title: this is the value');
+ expect(vm.$el.textContent.replace(/\s+/g, ' ').trim()).toEqual(
+ 'this is the title: this is the value',
+ );
});
describe('when helpUrl not provided', () => {
diff --git a/spec/javascripts/jobs/components/sidebar_details_block_spec.js b/spec/javascripts/jobs/components/sidebar_details_block_spec.js
deleted file mode 100644
index ba19534dac2..00000000000
--- a/spec/javascripts/jobs/components/sidebar_details_block_spec.js
+++ /dev/null
@@ -1,139 +0,0 @@
-import Vue from 'vue';
-import sidebarDetailsBlock from '~/jobs/components/sidebar_details_block.vue';
-import job from '../mock_data';
-import mountComponent from '../../helpers/vue_mount_component_helper';
-
-describe('Sidebar details block', () => {
- let SidebarComponent;
- let vm;
-
- function trimWhitespace(element) {
- return element.textContent.replace(/\s+/g, ' ').trim();
- }
-
- beforeEach(() => {
- SidebarComponent = Vue.extend(sidebarDetailsBlock);
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('when it is loading', () => {
- it('should render a loading spinner', () => {
- vm = mountComponent(SidebarComponent, {
- job: {},
- isLoading: true,
- });
- expect(vm.$el.querySelector('.fa-spinner')).toBeDefined();
- });
- });
-
- describe('when there is no retry path retry', () => {
- it('should not render a retry button', () => {
- vm = mountComponent(SidebarComponent, {
- job: {},
- isLoading: false,
- });
-
- expect(vm.$el.querySelector('.js-retry-job')).toBeNull();
- });
- });
-
- describe('without terminal path', () => {
- it('does not render terminal link', () => {
- vm = mountComponent(SidebarComponent, {
- job,
- isLoading: false,
- });
-
- expect(vm.$el.querySelector('.js-terminal-link')).toBeNull();
- });
- });
-
- describe('with terminal path', () => {
- it('renders terminal link', () => {
- vm = mountComponent(SidebarComponent, {
- job,
- isLoading: false,
- terminalPath: 'job/43123/terminal',
- });
-
- expect(vm.$el.querySelector('.js-terminal-link')).not.toBeNull();
- });
- });
-
- beforeEach(() => {
- vm = mountComponent(SidebarComponent, {
- job,
- isLoading: false,
- });
- });
-
- describe('actions', () => {
- it('should render link to new issue', () => {
- expect(vm.$el.querySelector('.js-new-issue').getAttribute('href')).toEqual(
- job.new_issue_path,
- );
- expect(vm.$el.querySelector('.js-new-issue').textContent.trim()).toEqual('New issue');
- });
-
- it('should render link to retry job', () => {
- expect(vm.$el.querySelector('.js-retry-job').getAttribute('href')).toEqual(job.retry_path);
- });
-
- it('should render link to cancel job', () => {
- expect(vm.$el.querySelector('.js-cancel-job').getAttribute('href')).toEqual(job.cancel_path);
- });
- });
-
- describe('information', () => {
- it('should render merge request link', () => {
- expect(trimWhitespace(vm.$el.querySelector('.js-job-mr'))).toEqual('Merge Request: !2');
-
- expect(vm.$el.querySelector('.js-job-mr a').getAttribute('href')).toEqual(
- job.merge_request.path,
- );
- });
-
- it('should render job duration', () => {
- expect(trimWhitespace(vm.$el.querySelector('.js-job-duration'))).toEqual(
- 'Duration: 6 seconds',
- );
- });
-
- it('should render erased date', () => {
- expect(trimWhitespace(vm.$el.querySelector('.js-job-erased'))).toEqual('Erased: 3 weeks ago');
- });
-
- it('should render finished date', () => {
- expect(trimWhitespace(vm.$el.querySelector('.js-job-finished'))).toEqual(
- 'Finished: 3 weeks ago',
- );
- });
-
- it('should render queued date', () => {
- expect(trimWhitespace(vm.$el.querySelector('.js-job-queued'))).toEqual('Queued: 9 seconds');
- });
-
- it('should render runner ID', () => {
- expect(trimWhitespace(vm.$el.querySelector('.js-job-runner'))).toEqual(
- 'Runner: local ci runner (#1)',
- );
- });
-
- it('should render timeout information', () => {
- expect(trimWhitespace(vm.$el.querySelector('.js-job-timeout'))).toEqual(
- 'Timeout: 1m 40s (from runner)',
- );
- });
-
- it('should render coverage', () => {
- expect(trimWhitespace(vm.$el.querySelector('.js-job-coverage'))).toEqual('Coverage: 20%');
- });
-
- it('should render tags', () => {
- expect(trimWhitespace(vm.$el.querySelector('.js-job-tags'))).toEqual('Tags: tag');
- });
- });
-});
diff --git a/spec/javascripts/jobs/components/sidebar_spec.js b/spec/javascripts/jobs/components/sidebar_spec.js
new file mode 100644
index 00000000000..424092d2d88
--- /dev/null
+++ b/spec/javascripts/jobs/components/sidebar_spec.js
@@ -0,0 +1,189 @@
+import Vue from 'vue';
+import sidebarDetailsBlock from '~/jobs/components/sidebar.vue';
+import createStore from '~/jobs/store';
+import job, { stages, jobsInStage } from '../mock_data';
+import { mountComponentWithStore } from '../../helpers/vue_mount_component_helper';
+import { trimText } from '../../helpers/vue_component_helper';
+
+describe('Sidebar details block', () => {
+ const SidebarComponent = Vue.extend(sidebarDetailsBlock);
+ let vm;
+ let store;
+
+ beforeEach(() => {
+ store = createStore();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('when there is no retry path retry', () => {
+ it('should not render a retry button', () => {
+ const copy = Object.assign({}, job);
+ delete copy.retry_path;
+
+ store.dispatch('receiveJobSuccess', copy);
+ vm = mountComponentWithStore(SidebarComponent, {
+ store,
+ });
+
+ expect(vm.$el.querySelector('.js-retry-job')).toBeNull();
+ });
+ });
+
+ describe('without terminal path', () => {
+ it('does not render terminal link', () => {
+ store.dispatch('receiveJobSuccess', job);
+ vm = mountComponentWithStore(SidebarComponent, { store });
+
+ expect(vm.$el.querySelector('.js-terminal-link')).toBeNull();
+ });
+ });
+
+ describe('with terminal path', () => {
+ it('renders terminal link', () => {
+ store.dispatch(
+ 'receiveJobSuccess',
+ Object.assign({}, job, { terminal_path: 'job/43123/terminal' }),
+ );
+ vm = mountComponentWithStore(SidebarComponent, {
+ store,
+ });
+
+ expect(vm.$el.querySelector('.js-terminal-link')).not.toBeNull();
+ });
+ });
+
+ beforeEach(() => {
+ store.dispatch('receiveJobSuccess', job);
+ vm = mountComponentWithStore(SidebarComponent, { store });
+ });
+
+ describe('actions', () => {
+ it('should render link to new issue', () => {
+ expect(vm.$el.querySelector('.js-new-issue').getAttribute('href')).toEqual(
+ job.new_issue_path,
+ );
+
+ expect(vm.$el.querySelector('.js-new-issue').textContent.trim()).toEqual('New issue');
+ });
+
+ it('should render link to retry job', () => {
+ expect(vm.$el.querySelector('.js-retry-job').getAttribute('href')).toEqual(job.retry_path);
+ });
+
+ it('should render link to cancel job', () => {
+ expect(vm.$el.querySelector('.js-cancel-job').getAttribute('href')).toEqual(job.cancel_path);
+ });
+ });
+
+ describe('information', () => {
+ it('should render merge request link', () => {
+ expect(trimText(vm.$el.querySelector('.js-job-mr').textContent)).toEqual('Merge Request: !2');
+
+ expect(vm.$el.querySelector('.js-job-mr a').getAttribute('href')).toEqual(
+ job.merge_request.path,
+ );
+ });
+
+ it('should render job duration', () => {
+ expect(trimText(vm.$el.querySelector('.js-job-duration').textContent)).toEqual(
+ 'Duration: 6 seconds',
+ );
+ });
+
+ it('should render erased date', () => {
+ expect(trimText(vm.$el.querySelector('.js-job-erased').textContent)).toEqual(
+ 'Erased: 3 weeks ago',
+ );
+ });
+
+ it('should render finished date', () => {
+ expect(trimText(vm.$el.querySelector('.js-job-finished').textContent)).toEqual(
+ 'Finished: 3 weeks ago',
+ );
+ });
+
+ it('should render queued date', () => {
+ expect(trimText(vm.$el.querySelector('.js-job-queued').textContent)).toEqual(
+ 'Queued: 9 seconds',
+ );
+ });
+
+ it('should render runner ID', () => {
+ expect(trimText(vm.$el.querySelector('.js-job-runner').textContent)).toEqual(
+ 'Runner: local ci runner (#1)',
+ );
+ });
+
+ it('should render timeout information', () => {
+ expect(trimText(vm.$el.querySelector('.js-job-timeout').textContent)).toEqual(
+ 'Timeout: 1m 40s (from runner)',
+ );
+ });
+
+ it('should render coverage', () => {
+ expect(trimText(vm.$el.querySelector('.js-job-coverage').textContent)).toEqual(
+ 'Coverage: 20%',
+ );
+ });
+
+ it('should render tags', () => {
+ expect(trimText(vm.$el.querySelector('.js-job-tags').textContent)).toEqual('Tags: tag');
+ });
+ });
+
+ describe('stages dropdown', () => {
+ beforeEach(() => {
+ store.dispatch('receiveJobSuccess', job);
+ });
+
+ describe('while fetching stages', () => {
+ it('it does not render dropdown', () => {
+ store.dispatch('requestStages');
+ vm = mountComponentWithStore(SidebarComponent, { store });
+
+ expect(vm.$el.querySelector('.js-selected-stage')).toBeNull();
+ });
+ });
+
+ describe('with stages', () => {
+ beforeEach(() => {
+ store.dispatch('receiveStagesSuccess', stages);
+ vm = mountComponentWithStore(SidebarComponent, { store });
+ });
+
+ it('renders value provided as selectedStage as selected', () => {
+ expect(vm.$el.querySelector('.js-selected-stage').textContent.trim()).toEqual(
+ vm.selectedStage,
+ );
+ });
+ });
+
+ describe('without jobs for stages', () => {
+ beforeEach(() => {
+ store.dispatch('receiveJobSuccess', job);
+ store.dispatch('receiveStagesSuccess', stages);
+ vm = mountComponentWithStore(SidebarComponent, { store });
+ });
+
+ it('does not render job container', () => {
+ expect(vm.$el.querySelector('.js-jobs-container')).toBeNull();
+ });
+ });
+
+ describe('with jobs for stages', () => {
+ beforeEach(() => {
+ store.dispatch('receiveJobSuccess', job);
+ store.dispatch('receiveStagesSuccess', stages);
+ store.dispatch('receiveJobsForStageSuccess', jobsInStage.latest_statuses);
+ vm = mountComponentWithStore(SidebarComponent, { store });
+ });
+
+ it('renders list of jobs', () => {
+ expect(vm.$el.querySelector('.js-jobs-container')).not.toBeNull();
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/jobs/components/stages_dropdown_spec.js b/spec/javascripts/jobs/components/stages_dropdown_spec.js
index 402289345aa..9c731ae2f68 100644
--- a/spec/javascripts/jobs/components/stages_dropdown_spec.js
+++ b/spec/javascripts/jobs/components/stages_dropdown_spec.js
@@ -2,16 +2,27 @@ import Vue from 'vue';
import component from '~/jobs/components/stages_dropdown.vue';
import mountComponent from '../../helpers/vue_mount_component_helper';
-describe('Artifacts block', () => {
+describe('Stages Dropdown', () => {
const Component = Vue.extend(component);
let vm;
beforeEach(() => {
vm = mountComponent(Component, {
- pipelineId: 28029444,
- pipelinePath: 'pipeline/28029444',
- pipelineRef: '50101-truncated-job-information',
- pipelineRefPath: 'commits/50101-truncated-job-information',
+ pipeline: {
+ id: 28029444,
+ details: {
+ status: {
+ details_path: '/gitlab-org/gitlab-ce/pipelines/28029444',
+ group: 'success',
+ has_details: true,
+ icon: 'status_success',
+ label: 'passed',
+ text: 'passed',
+ tooltip: 'passed',
+ },
+ },
+ path: 'pipeline/28029444',
+ },
stages: [
{
name: 'build',
@@ -20,15 +31,7 @@ describe('Artifacts block', () => {
name: 'test',
},
],
- pipelineStatus: {
- details_path: '/gitlab-org/gitlab-ce/pipelines/28029444',
- group: 'success',
- has_details: true,
- icon: 'status_success',
- label: 'passed',
- text: 'passed',
- tooltip: 'passed',
- },
+ selectedStage: 'deploy',
});
});
@@ -47,17 +50,10 @@ describe('Artifacts block', () => {
});
it('renders dropdown with stages', () => {
- expect(vm.$el.querySelector('.dropdown button').textContent).toContain('build');
+ expect(vm.$el.querySelector('.dropdown .js-stage-item').textContent).toContain('build');
});
- it('updates selected stage on click', done => {
- vm.$el.querySelectorAll('.stage-item')[1].click();
- vm
- .$nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.dropdown button').textContent).toContain('test');
- })
- .then(done)
- .catch(done.fail);
+ it('rendes selected stage', () => {
+ expect(vm.$el.querySelector('.dropdown .js-selected-stage').textContent).toContain('deploy');
});
});
diff --git a/spec/javascripts/jobs/components/trigger_block_spec.js b/spec/javascripts/jobs/components/trigger_block_spec.js
new file mode 100644
index 00000000000..7254851a9e7
--- /dev/null
+++ b/spec/javascripts/jobs/components/trigger_block_spec.js
@@ -0,0 +1,76 @@
+import Vue from 'vue';
+import component from '~/jobs/components/trigger_block.vue';
+import mountComponent from '../../helpers/vue_mount_component_helper';
+
+describe('Trigger block', () => {
+ const Component = Vue.extend(component);
+ let vm;
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('with short token', () => {
+ it('renders short token', () => {
+ vm = mountComponent(Component, {
+ trigger: {
+ short_token: '0a666b2',
+ },
+ });
+
+ expect(vm.$el.querySelector('.js-short-token').textContent).toContain('0a666b2');
+ });
+ });
+
+ describe('without short token', () => {
+ it('does not render short token', () => {
+ vm = mountComponent(Component, { trigger: {} });
+
+ expect(vm.$el.querySelector('.js-short-token')).toBeNull();
+ });
+ });
+
+ describe('with variables', () => {
+ describe('reveal variables', () => {
+ it('reveals variables on click', done => {
+ vm = mountComponent(Component, {
+ trigger: {
+ short_token: 'bd7e',
+ variables: [
+ { key: 'UPLOAD_TO_GCS', value: 'false', public: false },
+ { key: 'UPLOAD_TO_S3', value: 'true', public: false },
+ ],
+ },
+ });
+
+ vm.$el.querySelector('.js-reveal-variables').click();
+
+ vm.$nextTick()
+ .then(() => {
+ expect(vm.$el.querySelector('.js-build-variables')).not.toBeNull();
+ expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
+ 'UPLOAD_TO_GCS',
+ );
+
+ expect(vm.$el.querySelector('.js-build-variables').textContent).toContain('false');
+ expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
+ 'UPLOAD_TO_S3',
+ );
+
+ expect(vm.$el.querySelector('.js-build-variables').textContent).toContain('true');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+ });
+
+ describe('without variables', () => {
+ it('does not render variables', () => {
+ vm = mountComponent(Component, { trigger: {} });
+
+ expect(vm.$el.querySelector('.js-reveal-variables')).toBeNull();
+ expect(vm.$el.querySelector('.js-build-variables')).toBeNull();
+ });
+ });
+});
diff --git a/spec/javascripts/jobs/components/trigger_value_spec.js b/spec/javascripts/jobs/components/trigger_value_spec.js
deleted file mode 100644
index 3d41a3cfac1..00000000000
--- a/spec/javascripts/jobs/components/trigger_value_spec.js
+++ /dev/null
@@ -1,66 +0,0 @@
-import Vue from 'vue';
-import component from '~/jobs/components/trigger_block.vue';
-import mountComponent from '../../helpers/vue_mount_component_helper';
-
-describe('Trigger block', () => {
- const Component = Vue.extend(component);
- let vm;
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('with short token', () => {
- it('renders short token', () => {
- vm = mountComponent(Component, {
- shortToken: '0a666b2',
- });
-
- expect(vm.$el.querySelector('.js-short-token').textContent).toContain('0a666b2');
- });
- });
-
- describe('without short token', () => {
- it('does not render short token', () => {
- vm = mountComponent(Component, {});
-
- expect(vm.$el.querySelector('.js-short-token')).toBeNull();
- });
- });
-
- describe('with variables', () => {
- describe('reveal variables', () => {
- it('reveals variables on click', done => {
- vm = mountComponent(Component, {
- variables: {
- key: 'value',
- variable: 'foo',
- },
- });
-
- vm.$el.querySelector('.js-reveal-variables').click();
-
- vm
- .$nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.js-build-variables')).not.toBeNull();
- expect(vm.$el.querySelector('.js-build-variables').textContent).toContain('key');
- expect(vm.$el.querySelector('.js-build-variables').textContent).toContain('value');
- expect(vm.$el.querySelector('.js-build-variables').textContent).toContain('variable');
- expect(vm.$el.querySelector('.js-build-variables').textContent).toContain('foo');
- })
- .then(done)
- .catch(done.fail);
- });
- });
- });
-
- describe('without variables', () => {
- it('does not render variables', () => {
- vm = mountComponent(Component);
-
- expect(vm.$el.querySelector('.js-reveal-variables')).toBeNull();
- expect(vm.$el.querySelector('.js-build-variables')).toBeNull();
- });
- });
-});
diff --git a/spec/javascripts/jobs/mixins/delayed_job_mixin_spec.js b/spec/javascripts/jobs/mixins/delayed_job_mixin_spec.js
new file mode 100644
index 00000000000..48a6b80b365
--- /dev/null
+++ b/spec/javascripts/jobs/mixins/delayed_job_mixin_spec.js
@@ -0,0 +1,93 @@
+import Vue from 'vue';
+import delayedJobMixin from '~/jobs/mixins/delayed_job_mixin';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+
+describe('DelayedJobMixin', () => {
+ const delayedJobFixture = getJSONFixture('jobs/delayed.json');
+ const dummyComponent = Vue.extend({
+ mixins: [delayedJobMixin],
+ props: {
+ job: {
+ type: Object,
+ required: true,
+ },
+ },
+ template: '<div>{{ remainingTime }}</div>',
+ });
+
+ let vm;
+
+ beforeEach(() => {
+ jasmine.clock().install();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ jasmine.clock().uninstall();
+ });
+
+ describe('if job is empty object', () => {
+ beforeEach(() => {
+ vm = mountComponent(dummyComponent, {
+ job: {},
+ });
+ });
+
+ it('sets remaining time to 00:00:00', () => {
+ expect(vm.$el.innerText).toBe('00:00:00');
+ });
+
+ describe('after mounting', () => {
+ beforeEach(done => {
+ Vue.nextTick()
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('doe not update remaining time', () => {
+ expect(vm.$el.innerText).toBe('00:00:00');
+ });
+ });
+ });
+
+ describe('if job is delayed job', () => {
+ let remainingTimeInMilliseconds = 42000;
+
+ beforeEach(() => {
+ spyOn(Date, 'now').and.callFake(
+ () => new Date(delayedJobFixture.scheduled_at).getTime() - remainingTimeInMilliseconds,
+ );
+ vm = mountComponent(dummyComponent, {
+ job: delayedJobFixture,
+ });
+ });
+
+ it('sets remaining time to 00:00:00', () => {
+ expect(vm.$el.innerText).toBe('00:00:00');
+ });
+
+ describe('after mounting', () => {
+ beforeEach(done => {
+ Vue.nextTick()
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('sets remaining time', () => {
+ expect(vm.$el.innerText).toBe('00:00:42');
+ });
+
+ it('updates remaining time', done => {
+ remainingTimeInMilliseconds = 41000;
+ jasmine.clock().tick(1000);
+
+ Vue.nextTick()
+ .then(() => {
+ expect(vm.$el.innerText).toBe('00:00:41');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/jobs/mock_data.js b/spec/javascripts/jobs/mock_data.js
index 8fdd9b309b7..0398f184c0a 100644
--- a/spec/javascripts/jobs/mock_data.js
+++ b/spec/javascripts/jobs/mock_data.js
@@ -1,3 +1,5 @@
+import { TEST_HOST } from 'spec/test_constants';
+
const threeWeeksAgo = new Date();
threeWeeksAgo.setDate(threeWeeksAgo.getDate() - 21);
@@ -19,8 +21,9 @@ export default {
label: 'passed',
group: 'success',
has_details: true,
- details_path: '/root/ci-mock/-/jobs/4757',
- favicon: '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png',
+ details_path: `${TEST_HOST}/root/ci-mock/-/jobs/4757`,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png',
action: {
icon: 'retry',
title: 'Retry',
@@ -30,6 +33,7 @@ export default {
},
coverage: 20,
erased_at: threeWeeksAgo.toISOString(),
+ erased: false,
duration: 6.785563,
tags: ['tag'],
user: {
@@ -37,7 +41,8 @@ export default {
username: 'root',
id: 1,
state: 'active',
- avatar_url: 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
web_url: 'http://localhost:3000/root',
},
erase_path: '/root/ci-mock/-/jobs/4757/erase',
@@ -54,7 +59,8 @@ export default {
username: 'root',
id: 1,
state: 'active',
- avatar_url: 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
web_url: 'http://localhost:3000/root',
},
active: false,
@@ -78,7 +84,8 @@ export default {
group: 'success',
has_details: true,
details_path: '/root/ci-mock/pipelines/140',
- favicon: '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png',
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-308b4fc054cdd1b68d0865e6cfb7b02e92e3472f201507418f8eddb74ac11a59.png',
},
duration: 6,
finished_at: '2017-06-01T17:32:00.042Z',
@@ -107,11 +114,14 @@ export default {
username: 'root',
id: 1,
state: 'active',
- avatar_url: 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
web_url: 'http://localhost:3000/root',
},
- author_gravatar_url: 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
- commit_url: 'http://localhost:3000/root/ci-mock/commit/c58647773a6b5faf066d4ad6ff2c9fbba5f180f6',
+ author_gravatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon',
+ commit_url:
+ 'http://localhost:3000/root/ci-mock/commit/c58647773a6b5faf066d4ad6ff2c9fbba5f180f6',
commit_path: '/root/ci-mock/commit/c58647773a6b5faf066d4ad6ff2c9fbba5f180f6',
},
},
@@ -124,4 +134,1031 @@ export default {
path: '/root/ci-mock/merge_requests/2',
},
raw_path: '/root/ci-mock/builds/4757/raw',
+ has_trace: true,
+};
+
+export const stages = [
+ {
+ name: 'build',
+ title: 'build: running',
+ groups: [
+ {
+ name: 'build:linux',
+ size: 1,
+ status: {
+ icon: 'status_pending',
+ text: 'pending',
+ label: 'pending',
+ group: 'pending',
+ tooltip: 'pending',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/1180',
+ illustration: {
+ image: 'illustrations/pending_job_empty.svg',
+ size: 'svg-430',
+ title: 'This job has not started yet',
+ content: 'This job is in pending state and is waiting to be picked by a runner',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png',
+ action: {
+ icon: 'cancel',
+ title: 'Cancel',
+ path: '/gitlab-org/gitlab-shell/-/jobs/1180/cancel',
+ method: 'post',
+ },
+ },
+ jobs: [
+ {
+ id: 1180,
+ name: 'build:linux',
+ started: false,
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/1180',
+ cancel_path: '/gitlab-org/gitlab-shell/-/jobs/1180/cancel',
+ playable: false,
+ created_at: '2018-09-28T11:09:57.229Z',
+ updated_at: '2018-09-28T11:09:57.503Z',
+ status: {
+ icon: 'status_pending',
+ text: 'pending',
+ label: 'pending',
+ group: 'pending',
+ tooltip: 'pending',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/1180',
+ illustration: {
+ image: 'illustrations/pending_job_empty.svg',
+ size: 'svg-430',
+ title: 'This job has not started yet',
+ content: 'This job is in pending state and is waiting to be picked by a runner',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png',
+ action: {
+ icon: 'cancel',
+ title: 'Cancel',
+ path: '/gitlab-org/gitlab-shell/-/jobs/1180/cancel',
+ method: 'post',
+ },
+ },
+ },
+ ],
+ },
+ {
+ name: 'build:osx',
+ size: 1,
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/444',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/444/retry',
+ method: 'post',
+ },
+ },
+ jobs: [
+ {
+ id: 444,
+ name: 'build:osx',
+ started: '2018-05-18T05:32:20.655Z',
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/444',
+ retry_path: '/gitlab-org/gitlab-shell/-/jobs/444/retry',
+ playable: false,
+ created_at: '2018-05-18T15:32:54.364Z',
+ updated_at: '2018-05-18T15:32:54.364Z',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/444',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/444/retry',
+ method: 'post',
+ },
+ },
+ },
+ ],
+ },
+ ],
+ status: {
+ icon: 'status_running',
+ text: 'running',
+ label: 'running',
+ group: 'running',
+ tooltip: 'running',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/pipelines/27#build',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_running-9c635b2419a8e1ec991c993061b89cc5aefc0743bb238ecd0c381e7741a70e8c.png',
+ },
+ path: '/gitlab-org/gitlab-shell/pipelines/27#build',
+ dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=build',
+ },
+ {
+ name: 'test',
+ title: 'test: passed with warnings',
+ groups: [
+ {
+ name: 'jenkins',
+ size: 1,
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: null,
+ group: 'success',
+ tooltip: null,
+ has_details: false,
+ details_path: null,
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ jobs: [
+ {
+ id: 459,
+ name: 'jenkins',
+ started: '2018-05-18T09:32:20.658Z',
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/459',
+ playable: false,
+ created_at: '2018-05-18T15:32:55.330Z',
+ updated_at: '2018-05-18T15:32:55.330Z',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: null,
+ group: 'success',
+ tooltip: null,
+ has_details: false,
+ details_path: null,
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ },
+ ],
+ },
+ {
+ name: 'rspec:linux',
+ size: 3,
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: false,
+ details_path: null,
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ jobs: [
+ {
+ id: 445,
+ name: 'rspec:linux 0 3',
+ started: '2018-05-18T07:32:20.655Z',
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/445',
+ retry_path: '/gitlab-org/gitlab-shell/-/jobs/445/retry',
+ playable: false,
+ created_at: '2018-05-18T15:32:54.425Z',
+ updated_at: '2018-05-18T15:32:54.425Z',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/445',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/445/retry',
+ method: 'post',
+ },
+ },
+ },
+ {
+ id: 446,
+ name: 'rspec:linux 1 3',
+ started: '2018-05-18T07:32:20.655Z',
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/446',
+ retry_path: '/gitlab-org/gitlab-shell/-/jobs/446/retry',
+ playable: false,
+ created_at: '2018-05-18T15:32:54.506Z',
+ updated_at: '2018-05-18T15:32:54.506Z',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/446',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/446/retry',
+ method: 'post',
+ },
+ },
+ },
+ {
+ id: 447,
+ name: 'rspec:linux 2 3',
+ started: '2018-05-18T07:32:20.656Z',
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/447',
+ retry_path: '/gitlab-org/gitlab-shell/-/jobs/447/retry',
+ playable: false,
+ created_at: '2018-05-18T15:32:54.572Z',
+ updated_at: '2018-05-18T15:32:54.572Z',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/447',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/447/retry',
+ method: 'post',
+ },
+ },
+ },
+ ],
+ },
+ {
+ name: 'rspec:osx',
+ size: 1,
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/452',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/452/retry',
+ method: 'post',
+ },
+ },
+ jobs: [
+ {
+ id: 452,
+ name: 'rspec:osx',
+ started: '2018-05-18T07:32:20.657Z',
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/452',
+ retry_path: '/gitlab-org/gitlab-shell/-/jobs/452/retry',
+ playable: false,
+ created_at: '2018-05-18T15:32:54.920Z',
+ updated_at: '2018-05-18T15:32:54.920Z',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/452',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/452/retry',
+ method: 'post',
+ },
+ },
+ },
+ ],
+ },
+ {
+ name: 'rspec:windows',
+ size: 3,
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: false,
+ details_path: null,
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ jobs: [
+ {
+ id: 448,
+ name: 'rspec:windows 0 3',
+ started: '2018-05-18T07:32:20.656Z',
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/448',
+ retry_path: '/gitlab-org/gitlab-shell/-/jobs/448/retry',
+ playable: false,
+ created_at: '2018-05-18T15:32:54.639Z',
+ updated_at: '2018-05-18T15:32:54.639Z',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/448',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/448/retry',
+ method: 'post',
+ },
+ },
+ },
+ {
+ id: 449,
+ name: 'rspec:windows 1 3',
+ started: '2018-05-18T07:32:20.656Z',
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/449',
+ retry_path: '/gitlab-org/gitlab-shell/-/jobs/449/retry',
+ playable: false,
+ created_at: '2018-05-18T15:32:54.703Z',
+ updated_at: '2018-05-18T15:32:54.703Z',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/449',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/449/retry',
+ method: 'post',
+ },
+ },
+ },
+ {
+ id: 451,
+ name: 'rspec:windows 2 3',
+ started: '2018-05-18T07:32:20.657Z',
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/451',
+ retry_path: '/gitlab-org/gitlab-shell/-/jobs/451/retry',
+ playable: false,
+ created_at: '2018-05-18T15:32:54.853Z',
+ updated_at: '2018-05-18T15:32:54.853Z',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/451',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/451/retry',
+ method: 'post',
+ },
+ },
+ },
+ ],
+ },
+ {
+ name: 'spinach:linux',
+ size: 1,
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/453',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/453/retry',
+ method: 'post',
+ },
+ },
+ jobs: [
+ {
+ id: 453,
+ name: 'spinach:linux',
+ started: '2018-05-18T07:32:20.657Z',
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/453',
+ retry_path: '/gitlab-org/gitlab-shell/-/jobs/453/retry',
+ playable: false,
+ created_at: '2018-05-18T15:32:54.993Z',
+ updated_at: '2018-05-18T15:32:54.993Z',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/453',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/453/retry',
+ method: 'post',
+ },
+ },
+ },
+ ],
+ },
+ {
+ name: 'spinach:osx',
+ size: 1,
+ status: {
+ icon: 'status_warning',
+ text: 'failed',
+ label: 'failed (allowed to fail)',
+ group: 'failed_with_warnings',
+ tooltip: 'failed - (unknown failure) (allowed to fail)',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/454',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/454/retry',
+ method: 'post',
+ },
+ },
+ jobs: [
+ {
+ id: 454,
+ name: 'spinach:osx',
+ started: '2018-05-18T07:32:20.657Z',
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/454',
+ retry_path: '/gitlab-org/gitlab-shell/-/jobs/454/retry',
+ playable: false,
+ created_at: '2018-05-18T15:32:55.053Z',
+ updated_at: '2018-05-18T15:32:55.053Z',
+ status: {
+ icon: 'status_warning',
+ text: 'failed',
+ label: 'failed (allowed to fail)',
+ group: 'failed_with_warnings',
+ tooltip: 'failed - (unknown failure) (allowed to fail)',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/454',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_failed-41304d7f7e3828808b0c26771f0309e55296819a9beea3ea9fbf6689d9857c12.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/454/retry',
+ method: 'post',
+ },
+ },
+ callout_message: 'There is an unknown failure, please try again',
+ recoverable: true,
+ },
+ ],
+ },
+ ],
+ status: {
+ icon: 'status_warning',
+ text: 'passed',
+ label: 'passed with warnings',
+ group: 'success_with_warnings',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/pipelines/27#test',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ },
+ path: '/gitlab-org/gitlab-shell/pipelines/27#test',
+ dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=test',
+ },
+ {
+ name: 'deploy',
+ title: 'deploy: running',
+ groups: [
+ {
+ name: 'production',
+ size: 1,
+ status: {
+ icon: 'status_created',
+ text: 'created',
+ label: 'created',
+ group: 'created',
+ tooltip: 'created',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/457',
+ illustration: {
+ image: 'illustrations/job_not_triggered.svg',
+ size: 'svg-306',
+ title: 'This job has not been triggered yet',
+ content:
+ 'This job depends on upstream jobs that need to succeed in order for this job to be triggered',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_created-4b975aa976d24e5a3ea7cd9a5713e6ce2cd9afd08b910415e96675de35f64955.png',
+ action: {
+ icon: 'cancel',
+ title: 'Cancel',
+ path: '/gitlab-org/gitlab-shell/-/jobs/457/cancel',
+ method: 'post',
+ },
+ },
+ jobs: [
+ {
+ id: 457,
+ name: 'production',
+ started: false,
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/457',
+ cancel_path: '/gitlab-org/gitlab-shell/-/jobs/457/cancel',
+ playable: false,
+ created_at: '2018-05-18T15:32:55.259Z',
+ updated_at: '2018-09-28T11:09:57.454Z',
+ status: {
+ icon: 'status_created',
+ text: 'created',
+ label: 'created',
+ group: 'created',
+ tooltip: 'created',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/457',
+ illustration: {
+ image: 'illustrations/job_not_triggered.svg',
+ size: 'svg-306',
+ title: 'This job has not been triggered yet',
+ content:
+ 'This job depends on upstream jobs that need to succeed in order for this job to be triggered',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_created-4b975aa976d24e5a3ea7cd9a5713e6ce2cd9afd08b910415e96675de35f64955.png',
+ action: {
+ icon: 'cancel',
+ title: 'Cancel',
+ path: '/gitlab-org/gitlab-shell/-/jobs/457/cancel',
+ method: 'post',
+ },
+ },
+ },
+ ],
+ },
+ {
+ name: 'staging',
+ size: 1,
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/455',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/455/retry',
+ method: 'post',
+ },
+ },
+ jobs: [
+ {
+ id: 455,
+ name: 'staging',
+ started: '2018-05-18T09:32:20.658Z',
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/455',
+ retry_path: '/gitlab-org/gitlab-shell/-/jobs/455/retry',
+ playable: false,
+ created_at: '2018-05-18T15:32:55.119Z',
+ updated_at: '2018-05-18T15:32:55.119Z',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/455',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/455/retry',
+ method: 'post',
+ },
+ },
+ },
+ ],
+ },
+ {
+ name: 'stop staging',
+ size: 1,
+ status: {
+ icon: 'status_created',
+ text: 'created',
+ label: 'created',
+ group: 'created',
+ tooltip: 'created',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/456',
+ illustration: {
+ image: 'illustrations/job_not_triggered.svg',
+ size: 'svg-306',
+ title: 'This job has not been triggered yet',
+ content:
+ 'This job depends on upstream jobs that need to succeed in order for this job to be triggered',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_created-4b975aa976d24e5a3ea7cd9a5713e6ce2cd9afd08b910415e96675de35f64955.png',
+ action: {
+ icon: 'cancel',
+ title: 'Cancel',
+ path: '/gitlab-org/gitlab-shell/-/jobs/456/cancel',
+ method: 'post',
+ },
+ },
+ jobs: [
+ {
+ id: 456,
+ name: 'stop staging',
+ started: false,
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/456',
+ cancel_path: '/gitlab-org/gitlab-shell/-/jobs/456/cancel',
+ playable: false,
+ created_at: '2018-05-18T15:32:55.205Z',
+ updated_at: '2018-09-28T11:09:57.396Z',
+ status: {
+ icon: 'status_created',
+ text: 'created',
+ label: 'created',
+ group: 'created',
+ tooltip: 'created',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/456',
+ illustration: {
+ image: 'illustrations/job_not_triggered.svg',
+ size: 'svg-306',
+ title: 'This job has not been triggered yet',
+ content:
+ 'This job depends on upstream jobs that need to succeed in order for this job to be triggered',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_created-4b975aa976d24e5a3ea7cd9a5713e6ce2cd9afd08b910415e96675de35f64955.png',
+ action: {
+ icon: 'cancel',
+ title: 'Cancel',
+ path: '/gitlab-org/gitlab-shell/-/jobs/456/cancel',
+ method: 'post',
+ },
+ },
+ },
+ ],
+ },
+ ],
+ status: {
+ icon: 'status_running',
+ text: 'running',
+ label: 'running',
+ group: 'running',
+ tooltip: 'running',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/pipelines/27#deploy',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_running-9c635b2419a8e1ec991c993061b89cc5aefc0743bb238ecd0c381e7741a70e8c.png',
+ },
+ path: '/gitlab-org/gitlab-shell/pipelines/27#deploy',
+ dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=deploy',
+ },
+ {
+ name: 'notify',
+ title: 'notify: manual action',
+ groups: [
+ {
+ name: 'slack',
+ size: 1,
+ status: {
+ icon: 'status_manual',
+ text: 'manual',
+ label: 'manual play action',
+ group: 'manual',
+ tooltip: 'manual action',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/458',
+ illustration: {
+ image: 'illustrations/manual_action.svg',
+ size: 'svg-394',
+ title: 'This job requires a manual action',
+ content:
+ 'This job depends on a user to trigger its process. Often they are used to deploy code to production environments',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png',
+ action: {
+ icon: 'play',
+ title: 'Play',
+ path: '/gitlab-org/gitlab-shell/-/jobs/458/play',
+ method: 'post',
+ },
+ },
+ jobs: [
+ {
+ id: 458,
+ name: 'slack',
+ started: null,
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/458',
+ play_path: '/gitlab-org/gitlab-shell/-/jobs/458/play',
+ playable: true,
+ created_at: '2018-05-18T15:32:55.303Z',
+ updated_at: '2018-05-18T15:34:08.535Z',
+ status: {
+ icon: 'status_manual',
+ text: 'manual',
+ label: 'manual play action',
+ group: 'manual',
+ tooltip: 'manual action',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/458',
+ illustration: {
+ image: 'illustrations/manual_action.svg',
+ size: 'svg-394',
+ title: 'This job requires a manual action',
+ content:
+ 'This job depends on a user to trigger its process. Often they are used to deploy code to production environments',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png',
+ action: {
+ icon: 'play',
+ title: 'Play',
+ path: '/gitlab-org/gitlab-shell/-/jobs/458/play',
+ method: 'post',
+ },
+ },
+ },
+ ],
+ },
+ ],
+ status: {
+ icon: 'status_manual',
+ text: 'manual',
+ label: 'manual action',
+ group: 'manual',
+ tooltip: 'manual action',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/pipelines/27#notify',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_manual-829a0804612cef47d9efc1618dba38325483657c847dba0546c3b9f0295bb36c.png',
+ },
+ path: '/gitlab-org/gitlab-shell/pipelines/27#notify',
+ dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=notify',
+ },
+];
+
+export const jobsInStage = {
+ name: 'build',
+ title: 'build: running',
+ latest_statuses: [
+ {
+ id: 1180,
+ name: 'build:linux',
+ started: false,
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/1180',
+ cancel_path: '/gitlab-org/gitlab-shell/-/jobs/1180/cancel',
+ playable: false,
+ created_at: '2018-09-28T11:09:57.229Z',
+ updated_at: '2018-09-28T11:09:57.503Z',
+ status: {
+ icon: 'status_pending',
+ text: 'pending',
+ label: 'pending',
+ group: 'pending',
+ tooltip: 'pending',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/1180',
+ illustration: {
+ image: 'illustrations/pending_job_empty.svg',
+ size: 'svg-430',
+ title: 'This job has not started yet',
+ content: 'This job is in pending state and is waiting to be picked by a runner',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png',
+ action: {
+ icon: 'cancel',
+ title: 'Cancel',
+ path: '/gitlab-org/gitlab-shell/-/jobs/1180/cancel',
+ method: 'post',
+ },
+ },
+ },
+ {
+ id: 444,
+ name: 'build:osx',
+ started: '2018-05-18T05:32:20.655Z',
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/444',
+ retry_path: '/gitlab-org/gitlab-shell/-/jobs/444/retry',
+ playable: false,
+ created_at: '2018-05-18T15:32:54.364Z',
+ updated_at: '2018-05-18T15:32:54.364Z',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/444',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/444/retry',
+ method: 'post',
+ },
+ },
+ },
+ ],
+ retried: [
+ {
+ id: 443,
+ name: 'build:linux',
+ started: '2018-05-18T06:32:20.655Z',
+ build_path: '/gitlab-org/gitlab-shell/-/jobs/443',
+ retry_path: '/gitlab-org/gitlab-shell/-/jobs/443/retry',
+ playable: false,
+ created_at: '2018-05-18T15:32:54.296Z',
+ updated_at: '2018-05-18T15:32:54.296Z',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ tooltip: 'passed (retried)',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/-/jobs/443',
+ illustration: {
+ image: 'illustrations/skipped-job_empty.svg',
+ size: 'svg-430',
+ title: 'This job does not have a trace.',
+ },
+ favicon:
+ '/assets/ci_favicons/favicon_status_success-8451333011eee8ce9f2ab25dc487fe24a8758c694827a582f17f42b0a90446a2.png',
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/gitlab-org/gitlab-shell/-/jobs/443/retry',
+ method: 'post',
+ },
+ },
+ },
+ ],
+ status: {
+ icon: 'status_running',
+ text: 'running',
+ label: 'running',
+ group: 'running',
+ tooltip: 'running',
+ has_details: true,
+ details_path: '/gitlab-org/gitlab-shell/pipelines/27#build',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_running-9c635b2419a8e1ec991c993061b89cc5aefc0743bb238ecd0c381e7741a70e8c.png',
+ },
+ path: '/gitlab-org/gitlab-shell/pipelines/27#build',
+ dropdown_path: '/gitlab-org/gitlab-shell/pipelines/27/stage.json?stage=build',
};
diff --git a/spec/javascripts/jobs/store/actions_spec.js b/spec/javascripts/jobs/store/actions_spec.js
index 5042718dfa0..77b44995b12 100644
--- a/spec/javascripts/jobs/store/actions_spec.js
+++ b/spec/javascripts/jobs/store/actions_spec.js
@@ -2,9 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import {
setJobEndpoint,
- setTraceEndpoint,
- setStagesEndpoint,
- setJobsEndpoint,
+ setTraceOptions,
clearEtagPoll,
stopPolling,
requestJob,
@@ -18,19 +16,17 @@ import {
stopPollingTrace,
receiveTraceSuccess,
receiveTraceError,
- fetchFavicon,
- requestStatusFavicon,
- receiveStatusFaviconSuccess,
- requestStatusFaviconError,
requestStages,
fetchStages,
receiveStagesSuccess,
receiveStagesError,
requestJobsForStage,
- setSelectedStage,
fetchJobsForStage,
receiveJobsForStageSuccess,
receiveJobsForStageError,
+ hideSidebar,
+ showSidebar,
+ toggleSidebar,
} from '~/jobs/store/actions';
import state from '~/jobs/store/state';
import * as types from '~/jobs/store/mutation_types';
@@ -57,42 +53,44 @@ describe('Job State actions', () => {
});
});
- describe('setTraceEndpoint', () => {
- it('should commit SET_TRACE_ENDPOINT mutation', done => {
+ describe('setTraceOptions', () => {
+ it('should commit SET_TRACE_OPTIONS mutation', done => {
testAction(
- setTraceEndpoint,
- 'job/872324/trace.json',
+ setTraceOptions,
+ { pagePath: 'job/872324/trace.json' },
mockedState,
- [{ type: types.SET_TRACE_ENDPOINT, payload: 'job/872324/trace.json' }],
+ [{ type: types.SET_TRACE_OPTIONS, payload: { pagePath: 'job/872324/trace.json' } }],
[],
done,
);
});
});
- describe('setStagesEndpoint', () => {
- it('should commit SET_STAGES_ENDPOINT mutation', done => {
- testAction(
- setStagesEndpoint,
- 'job/872324/stages.json',
- mockedState,
- [{ type: types.SET_STAGES_ENDPOINT, payload: 'job/872324/stages.json' }],
- [],
- done,
- );
+ describe('hideSidebar', () => {
+ it('should commit HIDE_SIDEBAR mutation', done => {
+ testAction(hideSidebar, null, mockedState, [{ type: types.HIDE_SIDEBAR }], [], done);
});
});
- describe('setJobsEndpoint', () => {
- it('should commit SET_JOBS_ENDPOINT mutation', done => {
- testAction(
- setJobsEndpoint,
- 'job/872324/stages/build.json',
- mockedState,
- [{ type: types.SET_JOBS_ENDPOINT, payload: 'job/872324/stages/build.json' }],
- [],
- done,
- );
+ describe('showSidebar', () => {
+ it('should commit HIDE_SIDEBAR mutation', done => {
+ testAction(showSidebar, null, mockedState, [{ type: types.SHOW_SIDEBAR }], [], done);
+ });
+ });
+
+ describe('toggleSidebar', () => {
+ describe('when isSidebarOpen is true', () => {
+ it('should dispatch hideSidebar', done => {
+ testAction(toggleSidebar, null, mockedState, [], [{ type: 'hideSidebar' }], done);
+ });
+ });
+
+ describe('when isSidebarOpen is false', () => {
+ it('should dispatch showSidebar', done => {
+ mockedState.isSidebarOpen = false;
+
+ testAction(toggleSidebar, null, mockedState, [], [{ type: 'showSidebar' }], done);
+ });
});
});
@@ -184,14 +182,14 @@ describe('Job State actions', () => {
});
describe('scrollTop', () => {
- it('should commit SCROLL_TO_TOP mutation', done => {
- testAction(scrollTop, null, mockedState, [{ type: types.SCROLL_TO_TOP }], [], done);
+ it('should dispatch toggleScrollButtons action', done => {
+ testAction(scrollTop, null, mockedState, [], [{ type: 'toggleScrollButtons' }], done);
});
});
describe('scrollBottom', () => {
- it('should commit SCROLL_TO_BOTTOM mutation', done => {
- testAction(scrollBottom, null, mockedState, [{ type: types.SCROLL_TO_BOTTOM }], [], done);
+ it('should dispatch toggleScrollButtons action', done => {
+ testAction(scrollBottom, null, mockedState, [], [{ type: 'toggleScrollButtons' }], done);
});
});
@@ -216,7 +214,7 @@ describe('Job State actions', () => {
});
describe('success', () => {
- it('dispatches requestTrace, fetchFavicon, receiveTraceSuccess and stopPollingTrace when job is complete', done => {
+ it('dispatches requestTrace, receiveTraceSuccess and stopPollingTrace when job is complete', done => {
mock.onGet(`${TEST_HOST}/endpoint/trace.json`).replyOnce(200, {
html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :',
complete: true,
@@ -229,14 +227,13 @@ describe('Job State actions', () => {
[],
[
{
- type: 'requestTrace',
- },
- {
- type: 'fetchFavicon',
+ type: 'toggleScrollisInBottom',
+ payload: true,
},
{
payload: {
- html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :', complete: true,
+ html: 'I, [2018-08-17T22:57:45.707325 #1841] INFO -- :',
+ complete: true,
},
type: 'receiveTraceSuccess',
},
@@ -262,9 +259,6 @@ describe('Job State actions', () => {
[],
[
{
- type: 'requestTrace',
- },
- {
type: 'receiveTraceError',
},
],
@@ -313,104 +307,6 @@ describe('Job State actions', () => {
});
});
- describe('fetchFavicon', () => {
- let mock;
-
- beforeEach(() => {
- mockedState.pagePath = `${TEST_HOST}/endpoint`;
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- describe('success', () => {
- it('dispatches requestStatusFavicon and receiveStatusFaviconSuccess ', done => {
- mock.onGet(`${TEST_HOST}/endpoint/status.json`).replyOnce(200);
-
- testAction(
- fetchFavicon,
- null,
- mockedState,
- [],
- [
- {
- type: 'requestStatusFavicon',
- },
- {
- type: 'receiveStatusFaviconSuccess',
- },
- ],
- done,
- );
- });
- });
-
- describe('error', () => {
- beforeEach(() => {
- mock.onGet(`${TEST_HOST}/endpoint/status.json`).replyOnce(500);
- });
-
- it('dispatches requestStatusFavicon and requestStatusFaviconError ', done => {
- testAction(
- fetchFavicon,
- null,
- mockedState,
- [],
- [
- {
- type: 'requestStatusFavicon',
- },
- {
- type: 'requestStatusFaviconError',
- },
- ],
- done,
- );
- });
- });
- });
-
- describe('requestStatusFavicon', () => {
- it('should commit REQUEST_STATUS_FAVICON mutation ', done => {
- testAction(
- requestStatusFavicon,
- null,
- mockedState,
- [{ type: types.REQUEST_STATUS_FAVICON }],
- [],
- done,
- );
- });
- });
-
- describe('receiveStatusFaviconSuccess', () => {
- it('should commit RECEIVE_STATUS_FAVICON_SUCCESS mutation ', done => {
- testAction(
- receiveStatusFaviconSuccess,
- null,
- mockedState,
- [{ type: types.RECEIVE_STATUS_FAVICON_SUCCESS }],
- [],
- done,
- );
- });
- });
-
- describe('requestStatusFaviconError', () => {
- it('should commit RECEIVE_STATUS_FAVICON_ERROR mutation ', done => {
- testAction(
- requestStatusFaviconError,
- null,
- mockedState,
- [{ type: types.RECEIVE_STATUS_FAVICON_ERROR }],
- [],
- done,
- );
- });
- });
-
describe('requestStages', () => {
it('should commit REQUEST_STAGES mutation ', done => {
testAction(requestStages, null, mockedState, [{ type: types.REQUEST_STAGES }], [], done);
@@ -421,7 +317,10 @@ describe('Job State actions', () => {
let mock;
beforeEach(() => {
- mockedState.stagesEndpoint = `${TEST_HOST}/endpoint.json`;
+ mockedState.job.pipeline = {
+ path: `${TEST_HOST}/endpoint`,
+ };
+ mockedState.selectedStage = 'deploy';
mock = new MockAdapter(axios);
});
@@ -430,8 +329,10 @@ describe('Job State actions', () => {
});
describe('success', () => {
- it('dispatches requestStages and receiveStagesSuccess ', done => {
- mock.onGet(`${TEST_HOST}/endpoint.json`).replyOnce(200, [{ id: 121212, name: 'build' }]);
+ it('dispatches requestStages and receiveStagesSuccess, fetchJobsForStage ', done => {
+ mock
+ .onGet(`${TEST_HOST}/endpoint.json`)
+ .replyOnce(200, { details: { stages: [{ name: 'build' }, { name: 'deploy' }] } });
testAction(
fetchStages,
@@ -443,9 +344,13 @@ describe('Job State actions', () => {
type: 'requestStages',
},
{
- payload: [{ id: 121212, name: 'build' }],
+ payload: [{ name: 'build' }, { name: 'deploy' }],
type: 'receiveStagesSuccess',
},
+ {
+ payload: { name: 'deploy' },
+ type: 'fetchJobsForStage',
+ },
],
done,
);
@@ -507,22 +412,9 @@ describe('Job State actions', () => {
it('should commit REQUEST_JOBS_FOR_STAGE mutation ', done => {
testAction(
requestJobsForStage,
- null,
- mockedState,
- [{ type: types.REQUEST_JOBS_FOR_STAGE }],
- [],
- done,
- );
- });
- });
-
- describe('setSelectedStage', () => {
- it('should commit SET_SELECTED_STAGE mutation ', done => {
- testAction(
- setSelectedStage,
- { name: 'build' },
+ { name: 'deploy' },
mockedState,
- [{ type: types.SET_SELECTED_STAGE, payload: { name: 'build' } }],
+ [{ type: types.REQUEST_JOBS_FOR_STAGE, payload: { name: 'deploy' } }],
[],
done,
);
@@ -533,7 +425,6 @@ describe('Job State actions', () => {
let mock;
beforeEach(() => {
- mockedState.stageJobsEndpoint = `${TEST_HOST}/endpoint.json`;
mock = new MockAdapter(axios);
});
@@ -542,21 +433,20 @@ describe('Job State actions', () => {
});
describe('success', () => {
- it('dispatches setSelectedStage, requestJobsForStage and receiveJobsForStageSuccess ', done => {
- mock.onGet(`${TEST_HOST}/endpoint.json`).replyOnce(200, [{ id: 121212, name: 'build' }]);
+ it('dispatches requestJobsForStage and receiveJobsForStageSuccess ', done => {
+ mock
+ .onGet(`${TEST_HOST}/jobs.json`)
+ .replyOnce(200, { latest_statuses: [{ id: 121212, name: 'build' }], retried: [] });
testAction(
fetchJobsForStage,
- null,
+ { dropdown_path: `${TEST_HOST}/jobs.json` },
mockedState,
[],
[
{
- type: 'setSelectedStage',
- payload: null,
- },
- {
type: 'requestJobsForStage',
+ payload: { dropdown_path: `${TEST_HOST}/jobs.json` },
},
{
payload: [{ id: 121212, name: 'build' }],
@@ -570,22 +460,19 @@ describe('Job State actions', () => {
describe('error', () => {
beforeEach(() => {
- mock.onGet(`${TEST_HOST}/endpoint.json`).reply(500);
+ mock.onGet(`${TEST_HOST}/jobs.json`).reply(500);
});
- it('dispatches setSelectedStage, requestJobsForStage and receiveJobsForStageError', done => {
+ it('dispatches requestJobsForStage and receiveJobsForStageError', done => {
testAction(
fetchJobsForStage,
- null,
+ { dropdown_path: `${TEST_HOST}/jobs.json` },
mockedState,
[],
[
{
- payload: null,
- type: 'setSelectedStage',
- },
- {
type: 'requestJobsForStage',
+ payload: { dropdown_path: `${TEST_HOST}/jobs.json` },
},
{
type: 'receiveJobsForStageError',
diff --git a/spec/javascripts/jobs/store/getters_spec.js b/spec/javascripts/jobs/store/getters_spec.js
new file mode 100644
index 00000000000..4195d9d3680
--- /dev/null
+++ b/spec/javascripts/jobs/store/getters_spec.js
@@ -0,0 +1,212 @@
+import * as getters from '~/jobs/store/getters';
+import state from '~/jobs/store/state';
+
+describe('Job Store Getters', () => {
+ let localState;
+
+ beforeEach(() => {
+ localState = state();
+ });
+
+ describe('headerActions', () => {
+ describe('with new issue path', () => {
+ it('returns an array with action to create a new issue', () => {
+ localState.job.new_issue_path = 'issues/new';
+
+ expect(getters.headerActions(localState)).toEqual([
+ {
+ label: 'New issue',
+ path: localState.job.new_issue_path,
+ cssClass:
+ 'js-new-issue btn btn-success btn-inverted d-none d-md-block d-lg-block d-xl-block',
+ type: 'link',
+ },
+ ]);
+ });
+ });
+
+ describe('without new issue path', () => {
+ it('returns an empty array', () => {
+ expect(getters.headerActions(localState)).toEqual([]);
+ });
+ });
+ });
+
+ describe('headerTime', () => {
+ describe('when the job has started key', () => {
+ it('returns started key', () => {
+ const started = '2018-08-31T16:20:49.023Z';
+ localState.job.started = started;
+
+ expect(getters.headerTime(localState)).toEqual(started);
+ });
+ });
+
+ describe('when the job does not have started key', () => {
+ it('returns created_at key', () => {
+ const created = '2018-08-31T16:20:49.023Z';
+ localState.job.created_at = created;
+
+ expect(getters.headerTime(localState)).toEqual(created);
+ });
+ });
+ });
+
+ describe('shouldRenderCalloutMessage', () => {
+ describe('with status and callout message', () => {
+ it('returns true', () => {
+ localState.job.callout_message = 'Callout message';
+ localState.job.status = { icon: 'passed' };
+
+ expect(getters.shouldRenderCalloutMessage(localState)).toEqual(true);
+ });
+ });
+
+ describe('without status & with callout message', () => {
+ it('returns false', () => {
+ localState.job.callout_message = 'Callout message';
+
+ expect(getters.shouldRenderCalloutMessage(localState)).toEqual(false);
+ });
+ });
+
+ describe('with status & without callout message', () => {
+ it('returns false', () => {
+ localState.job.status = { icon: 'passed' };
+
+ expect(getters.shouldRenderCalloutMessage(localState)).toEqual(false);
+ });
+ });
+ });
+
+ describe('shouldRenderTriggeredLabel', () => {
+ describe('when started equals null', () => {
+ it('returns false', () => {
+ localState.job.started = null;
+
+ expect(getters.shouldRenderTriggeredLabel(localState)).toEqual(false);
+ });
+ });
+
+ describe('when started equals string', () => {
+ it('returns true', () => {
+ localState.job.started = '2018-08-31T16:20:49.023Z';
+
+ expect(getters.shouldRenderTriggeredLabel(localState)).toEqual(true);
+ });
+ });
+ });
+
+ describe('hasEnvironment', () => {
+ describe('without `deployment_status`', () => {
+ it('returns false', () => {
+ expect(getters.hasEnvironment(localState)).toEqual(false);
+ });
+ });
+
+ describe('with an empty object for `deployment_status`', () => {
+ it('returns false', () => {
+ localState.job.deployment_status = {};
+
+ expect(getters.hasEnvironment(localState)).toEqual(false);
+ });
+ });
+
+ describe('when `deployment_status` is defined and not empty', () => {
+ it('returns true', () => {
+ localState.job.deployment_status = {
+ status: 'creating',
+ environment: {
+ last_deployment: {},
+ },
+ };
+
+ expect(getters.hasEnvironment(localState)).toEqual(true);
+ });
+ });
+ });
+
+ describe('hasTrace', () => {
+ describe('when has_trace is true', () => {
+ it('returns true', () => {
+ localState.job.has_trace = true;
+ localState.job.status = {};
+
+ expect(getters.hasTrace(localState)).toEqual(true);
+ });
+ });
+
+ describe('when job is running', () => {
+ it('returns true', () => {
+ localState.job.has_trace = false;
+ localState.job.status = { group: 'running' };
+
+ expect(getters.hasTrace(localState)).toEqual(true);
+ });
+ });
+
+ describe('when has_trace is false and job is not running', () => {
+ it('returns false', () => {
+ localState.job.has_trace = false;
+ localState.job.status = { group: 'pending' };
+
+ expect(getters.hasTrace(localState)).toEqual(false);
+ });
+ });
+ });
+
+ describe('emptyStateIllustration', () => {
+ describe('with defined illustration', () => {
+ it('returns the state illustration object', () => {
+ localState.job.status = {
+ illustration: {
+ path: 'foo',
+ },
+ };
+
+ expect(getters.emptyStateIllustration(localState)).toEqual({ path: 'foo' });
+ });
+ });
+
+ describe('when illustration is not defined', () => {
+ it('returns an empty object', () => {
+ expect(getters.emptyStateIllustration(localState)).toEqual({});
+ });
+ });
+ });
+
+ describe('hasRunnersForProject', () => {
+ describe('with available and offline runners', () => {
+ it('returns true', () => {
+ localState.job.runners = {
+ available: true,
+ online: false,
+ };
+
+ expect(getters.hasRunnersForProject(localState)).toEqual(true);
+ });
+ });
+
+ describe('with non available runners', () => {
+ it('returns false', () => {
+ localState.job.runners = {
+ available: false,
+ online: false,
+ };
+
+ expect(getters.hasRunnersForProject(localState)).toEqual(false);
+ });
+ });
+
+ describe('with online runners', () => {
+ it('returns false', () => {
+ localState.job.runners = {
+ available: false,
+ online: true,
+ };
+
+ expect(getters.hasRunnersForProject(localState)).toEqual(false);
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/jobs/store/helpers.js b/spec/javascripts/jobs/store/helpers.js
new file mode 100644
index 00000000000..81a769b4a6e
--- /dev/null
+++ b/spec/javascripts/jobs/store/helpers.js
@@ -0,0 +1,6 @@
+import state from '~/jobs/store/state';
+
+// eslint-disable-next-line import/prefer-default-export
+export const resetStore = store => {
+ store.replaceState(state());
+};
diff --git a/spec/javascripts/jobs/store/mutations_spec.js b/spec/javascripts/jobs/store/mutations_spec.js
index 6900b2e5602..d7908efcf13 100644
--- a/spec/javascripts/jobs/store/mutations_spec.js
+++ b/spec/javascripts/jobs/store/mutations_spec.js
@@ -12,24 +12,27 @@ describe('Jobs Store Mutations', () => {
stateCopy = state();
});
- describe('REQUEST_STATUS_FAVICON', () => {
- it('should set fetchingStatusFavicon to true', () => {
- mutations[types.REQUEST_STATUS_FAVICON](stateCopy);
- expect(stateCopy.fetchingStatusFavicon).toEqual(true);
+ describe('SET_JOB_ENDPOINT', () => {
+ it('should set jobEndpoint', () => {
+ mutations[types.SET_JOB_ENDPOINT](stateCopy, 'job/21312321.json');
+
+ expect(stateCopy.jobEndpoint).toEqual('job/21312321.json');
});
});
- describe('RECEIVE_STATUS_FAVICON_SUCCESS', () => {
- it('should set fetchingStatusFavicon to false', () => {
- mutations[types.RECEIVE_STATUS_FAVICON_SUCCESS](stateCopy);
- expect(stateCopy.fetchingStatusFavicon).toEqual(false);
+ describe('HIDE_SIDEBAR', () => {
+ it('should set isSidebarOpen to false', () => {
+ mutations[types.HIDE_SIDEBAR](stateCopy);
+
+ expect(stateCopy.isSidebarOpen).toEqual(false);
});
});
- describe('RECEIVE_STATUS_FAVICON_ERROR', () => {
- it('should set fetchingStatusFavicon to false', () => {
- mutations[types.RECEIVE_STATUS_FAVICON_ERROR](stateCopy);
- expect(stateCopy.fetchingStatusFavicon).toEqual(false);
+ describe('SHOW_SIDEBAR', () => {
+ it('should set isSidebarOpen to true', () => {
+ mutations[types.SHOW_SIDEBAR](stateCopy);
+
+ expect(stateCopy.isSidebarOpen).toEqual(true);
});
});
@@ -41,6 +44,7 @@ describe('Jobs Store Mutations', () => {
mutations[types.RECEIVE_TRACE_SUCCESS](stateCopy, {
state: stateLog,
});
+
expect(stateCopy.traceState).toEqual(stateLog);
});
});
@@ -70,6 +74,7 @@ describe('Jobs Store Mutations', () => {
size: 511846,
complete: true,
});
+
expect(stateCopy.trace).toEqual(html);
expect(stateCopy.traceSize).toEqual(511846);
expect(stateCopy.isTraceComplete).toEqual(true);
@@ -79,6 +84,7 @@ describe('Jobs Store Mutations', () => {
describe('STOP_POLLING_TRACE', () => {
it('sets isTraceComplete to true', () => {
mutations[types.STOP_POLLING_TRACE](stateCopy);
+
expect(stateCopy.isTraceComplete).toEqual(true);
});
});
@@ -86,9 +92,8 @@ describe('Jobs Store Mutations', () => {
describe('RECEIVE_TRACE_ERROR', () => {
it('resets trace state and sets error to true', () => {
mutations[types.RECEIVE_TRACE_ERROR](stateCopy);
- expect(stateCopy.isLoadingTrace).toEqual(false);
+
expect(stateCopy.isTraceComplete).toEqual(true);
- expect(stateCopy.hasTraceError).toEqual(true);
});
});
@@ -101,64 +106,54 @@ describe('Jobs Store Mutations', () => {
});
describe('RECEIVE_JOB_SUCCESS', () => {
- beforeEach(() => {
+ it('sets is loading to false', () => {
mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321 });
- });
- it('sets is loading to false', () => {
expect(stateCopy.isLoading).toEqual(false);
});
it('sets hasError to false', () => {
+ mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321 });
+
expect(stateCopy.hasError).toEqual(false);
});
it('sets job data', () => {
+ mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321 });
+
expect(stateCopy.job).toEqual({ id: 1312321 });
});
- });
- describe('RECEIVE_JOB_ERROR', () => {
- it('resets job data', () => {
- mutations[types.RECEIVE_JOB_ERROR](stateCopy);
+ it('sets selectedStage when the selectedStage is empty', () => {
+ expect(stateCopy.selectedStage).toEqual('');
+ mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321, stage: 'deploy' });
- expect(stateCopy.isLoading).toEqual(false);
- expect(stateCopy.hasError).toEqual(true);
- expect(stateCopy.job).toEqual({});
+ expect(stateCopy.selectedStage).toEqual('deploy');
});
- });
- describe('SCROLL_TO_TOP', () => {
- beforeEach(() => {
- mutations[types.SCROLL_TO_TOP](stateCopy);
- });
+ it('does not set selectedStage when the selectedStage is not More', () => {
+ stateCopy.selectedStage = 'notify';
- it('sets isTraceScrolledToBottom to false', () => {
- expect(stateCopy.isTraceScrolledToBottom).toEqual(false);
- });
+ expect(stateCopy.selectedStage).toEqual('notify');
+ mutations[types.RECEIVE_JOB_SUCCESS](stateCopy, { id: 1312321, stage: 'deploy' });
- it('sets hasBeenScrolled to true', () => {
- expect(stateCopy.hasBeenScrolled).toEqual(true);
+ expect(stateCopy.selectedStage).toEqual('notify');
});
});
- describe('SCROLL_TO_BOTTOM', () => {
- beforeEach(() => {
- mutations[types.SCROLL_TO_BOTTOM](stateCopy);
- });
-
- it('sets isTraceScrolledToBottom to true', () => {
- expect(stateCopy.isTraceScrolledToBottom).toEqual(true);
- });
+ describe('RECEIVE_JOB_ERROR', () => {
+ it('resets job data', () => {
+ mutations[types.RECEIVE_JOB_ERROR](stateCopy);
- it('sets hasBeenScrolled to true', () => {
- expect(stateCopy.hasBeenScrolled).toEqual(true);
+ expect(stateCopy.isLoading).toEqual(false);
+ expect(stateCopy.job).toEqual({});
});
});
describe('REQUEST_STAGES', () => {
it('sets isLoadingStages to true', () => {
mutations[types.REQUEST_STAGES](stateCopy);
+
expect(stateCopy.isLoadingStages).toEqual(true);
});
});
@@ -193,9 +188,16 @@ describe('Jobs Store Mutations', () => {
describe('REQUEST_JOBS_FOR_STAGE', () => {
it('sets isLoadingStages to true', () => {
- mutations[types.REQUEST_JOBS_FOR_STAGE](stateCopy);
+ mutations[types.REQUEST_JOBS_FOR_STAGE](stateCopy, { name: 'deploy' });
+
expect(stateCopy.isLoadingJobs).toEqual(true);
});
+
+ it('sets selectedStage', () => {
+ mutations[types.REQUEST_JOBS_FOR_STAGE](stateCopy, { name: 'deploy' });
+
+ expect(stateCopy.selectedStage).toEqual('deploy');
+ });
});
describe('RECEIVE_JOBS_FOR_STAGE_SUCCESS', () => {
diff --git a/spec/javascripts/labels_issue_sidebar_spec.js b/spec/javascripts/labels_issue_sidebar_spec.js
index 5aafb6ad8f0..e5678ee5379 100644
--- a/spec/javascripts/labels_issue_sidebar_spec.js
+++ b/spec/javascripts/labels_issue_sidebar_spec.js
@@ -12,88 +12,106 @@ import '~/api';
import '~/create_label';
import '~/users_select';
-(() => {
- let saveLabelCount = 0;
- let mock;
+let saveLabelCount = 0;
+let mock;
- describe('Issue dropdown sidebar', () => {
- preloadFixtures('static/issue_sidebar_label.html.raw');
+describe('Issue dropdown sidebar', () => {
+ preloadFixtures('static/issue_sidebar_label.html.raw');
- beforeEach(() => {
- loadFixtures('static/issue_sidebar_label.html.raw');
+ beforeEach(() => {
+ loadFixtures('static/issue_sidebar_label.html.raw');
- mock = new MockAdapter(axios);
+ mock = new MockAdapter(axios);
- new IssuableContext('{"id":1,"name":"Administrator","username":"root"}');
- new LabelsSelect();
+ new IssuableContext('{"id":1,"name":"Administrator","username":"root"}');
+ new LabelsSelect();
- mock.onGet('/root/test/labels.json').reply(() => {
- const labels = Array(10).fill().map((_, i) => ({
+ mock.onGet('/root/test/labels.json').reply(() => {
+ const labels = Array(10)
+ .fill()
+ .map((_, i) => ({
id: i,
title: `test ${i}`,
color: '#5CB85C',
}));
- return [200, labels];
- });
+ return [200, labels];
+ });
- mock.onPut('/root/test/issues/2.json').reply(() => {
- const labels = Array(saveLabelCount).fill().map((_, i) => ({
+ mock.onPut('/root/test/issues/2.json').reply(() => {
+ const labels = Array(saveLabelCount)
+ .fill()
+ .map((_, i) => ({
id: i,
title: `test ${i}`,
color: '#5CB85C',
}));
- return [200, { labels }];
- });
- });
-
- afterEach(() => {
- mock.restore();
+ return [200, { labels }];
});
+ });
- it('changes collapsed tooltip when changing labels when less than 5', (done) => {
- saveLabelCount = 5;
- $('.edit-link').get(0).click();
-
- setTimeout(() => {
- expect($('.dropdown-content a').length).toBe(10);
-
- $('.dropdown-content a').each(function (i) {
- if (i < saveLabelCount) {
- $(this).get(0).click();
- }
- });
-
- $('.edit-link').get(0).click();
+ afterEach(() => {
+ mock.restore();
+ });
- setTimeout(() => {
- expect($('.sidebar-collapsed-icon').attr('data-original-title')).toBe('test 0, test 1, test 2, test 3, test 4');
- done();
- }, 0);
- }, 0);
- });
+ it('changes collapsed tooltip when changing labels when less than 5', done => {
+ saveLabelCount = 5;
+ $('.edit-link')
+ .get(0)
+ .click();
+
+ setTimeout(() => {
+ expect($('.dropdown-content a').length).toBe(10);
+
+ $('.dropdown-content a').each(function(i) {
+ if (i < saveLabelCount) {
+ $(this)
+ .get(0)
+ .click();
+ }
+ });
- it('changes collapsed tooltip when changing labels when more than 5', (done) => {
- saveLabelCount = 6;
- $('.edit-link').get(0).click();
+ $('.edit-link')
+ .get(0)
+ .click();
setTimeout(() => {
- expect($('.dropdown-content a').length).toBe(10);
+ expect($('.sidebar-collapsed-icon').attr('data-original-title')).toBe(
+ 'test 0, test 1, test 2, test 3, test 4',
+ );
+ done();
+ }, 0);
+ }, 0);
+ });
- $('.dropdown-content a').each(function (i) {
- if (i < saveLabelCount) {
- $(this).get(0).click();
- }
- });
+ it('changes collapsed tooltip when changing labels when more than 5', done => {
+ saveLabelCount = 6;
+ $('.edit-link')
+ .get(0)
+ .click();
+
+ setTimeout(() => {
+ expect($('.dropdown-content a').length).toBe(10);
+
+ $('.dropdown-content a').each(function(i) {
+ if (i < saveLabelCount) {
+ $(this)
+ .get(0)
+ .click();
+ }
+ });
- $('.edit-link').get(0).click();
+ $('.edit-link')
+ .get(0)
+ .click();
- setTimeout(() => {
- expect($('.sidebar-collapsed-icon').attr('data-original-title')).toBe('test 0, test 1, test 2, test 3, test 4, and 1 more');
- done();
- }, 0);
+ setTimeout(() => {
+ expect($('.sidebar-collapsed-icon').attr('data-original-title')).toBe(
+ 'test 0, test 1, test 2, test 3, test 4, and 1 more',
+ );
+ done();
}, 0);
- });
+ }, 0);
});
-})();
+});
diff --git a/spec/javascripts/labels_select_spec.js b/spec/javascripts/labels_select_spec.js
index 386e00bfd0c..acfdc885032 100644
--- a/spec/javascripts/labels_select_spec.js
+++ b/spec/javascripts/labels_select_spec.js
@@ -19,10 +19,12 @@ describe('LabelsSelect', () => {
let $labelEl;
beforeEach(() => {
- $labelEl = $(LabelsSelect.getLabelTemplate({
- labels: mockLabels,
- issueUpdateURL: mockUrl,
- }));
+ $labelEl = $(
+ LabelsSelect.getLabelTemplate({
+ labels: mockLabels,
+ issueUpdateURL: mockUrl,
+ }),
+ );
});
it('generated label item template has correct label URL', () => {
@@ -38,7 +40,9 @@ describe('LabelsSelect', () => {
});
it('generated label item template has correct label styles', () => {
- expect($labelEl.find('span.label').attr('style')).toBe(`background-color: ${label.color}; color: ${label.text_color};`);
+ expect($labelEl.find('span.label').attr('style')).toBe(
+ `background-color: ${label.color}; color: ${label.text_color};`,
+ );
});
it('generated label item has a badge class', () => {
diff --git a/spec/javascripts/landing_spec.js b/spec/javascripts/landing_spec.js
index 7916073190a..2fe5a47b63e 100644
--- a/spec/javascripts/landing_spec.js
+++ b/spec/javascripts/landing_spec.js
@@ -1,9 +1,9 @@
import Landing from '~/landing';
import Cookies from 'js-cookie';
-describe('Landing', function () {
- describe('class constructor', function () {
- beforeEach(function () {
+describe('Landing', function() {
+ describe('class constructor', function() {
+ beforeEach(function() {
this.landingElement = {};
this.dismissButton = {};
this.cookieName = 'cookie_name';
@@ -11,25 +11,25 @@ describe('Landing', function () {
this.landing = new Landing(this.landingElement, this.dismissButton, this.cookieName);
});
- it('should set .landing', function () {
+ it('should set .landing', function() {
expect(this.landing.landingElement).toBe(this.landingElement);
});
- it('should set .cookieName', function () {
+ it('should set .cookieName', function() {
expect(this.landing.cookieName).toBe(this.cookieName);
});
- it('should set .dismissButton', function () {
+ it('should set .dismissButton', function() {
expect(this.landing.dismissButton).toBe(this.dismissButton);
});
- it('should set .eventWrapper', function () {
+ it('should set .eventWrapper', function() {
expect(this.landing.eventWrapper).toEqual({});
});
});
- describe('toggle', function () {
- beforeEach(function () {
+ describe('toggle', function() {
+ beforeEach(function() {
this.isDismissed = false;
this.landingElement = { classList: jasmine.createSpyObj('classList', ['toggle']) };
this.landing = {
@@ -44,20 +44,20 @@ describe('Landing', function () {
Landing.prototype.toggle.call(this.landing);
});
- it('should call .isDismissed', function () {
+ it('should call .isDismissed', function() {
expect(this.landing.isDismissed).toHaveBeenCalled();
});
- it('should call .classList.toggle', function () {
+ it('should call .classList.toggle', function() {
expect(this.landingElement.classList.toggle).toHaveBeenCalledWith('hidden', this.isDismissed);
});
- it('should call .addEvents', function () {
+ it('should call .addEvents', function() {
expect(this.landing.addEvents).toHaveBeenCalled();
});
- describe('if isDismissed is true', function () {
- beforeEach(function () {
+ describe('if isDismissed is true', function() {
+ beforeEach(function() {
this.isDismissed = true;
this.landingElement = { classList: jasmine.createSpyObj('classList', ['toggle']) };
this.landing = {
@@ -74,14 +74,14 @@ describe('Landing', function () {
Landing.prototype.toggle.call(this.landing);
});
- it('should not call .addEvents', function () {
+ it('should not call .addEvents', function() {
expect(this.landing.addEvents).not.toHaveBeenCalled();
});
});
});
- describe('addEvents', function () {
- beforeEach(function () {
+ describe('addEvents', function() {
+ beforeEach(function() {
this.dismissButton = jasmine.createSpyObj('dismissButton', ['addEventListener']);
this.eventWrapper = {};
this.landing = {
@@ -93,17 +93,20 @@ describe('Landing', function () {
Landing.prototype.addEvents.call(this.landing);
});
- it('should set .eventWrapper.dismissLanding', function () {
+ it('should set .eventWrapper.dismissLanding', function() {
expect(this.eventWrapper.dismissLanding).toEqual(jasmine.any(Function));
});
- it('should call .addEventListener', function () {
- expect(this.dismissButton.addEventListener).toHaveBeenCalledWith('click', this.eventWrapper.dismissLanding);
+ it('should call .addEventListener', function() {
+ expect(this.dismissButton.addEventListener).toHaveBeenCalledWith(
+ 'click',
+ this.eventWrapper.dismissLanding,
+ );
});
});
- describe('removeEvents', function () {
- beforeEach(function () {
+ describe('removeEvents', function() {
+ beforeEach(function() {
this.dismissButton = jasmine.createSpyObj('dismissButton', ['removeEventListener']);
this.eventWrapper = { dismissLanding: () => {} };
this.landing = {
@@ -114,13 +117,16 @@ describe('Landing', function () {
Landing.prototype.removeEvents.call(this.landing);
});
- it('should call .removeEventListener', function () {
- expect(this.dismissButton.removeEventListener).toHaveBeenCalledWith('click', this.eventWrapper.dismissLanding);
+ it('should call .removeEventListener', function() {
+ expect(this.dismissButton.removeEventListener).toHaveBeenCalledWith(
+ 'click',
+ this.eventWrapper.dismissLanding,
+ );
});
});
- describe('dismissLanding', function () {
- beforeEach(function () {
+ describe('dismissLanding', function() {
+ beforeEach(function() {
this.landingElement = { classList: jasmine.createSpyObj('classList', ['add']) };
this.cookieName = 'cookie_name';
this.landing = { landingElement: this.landingElement, cookieName: this.cookieName };
@@ -130,17 +136,17 @@ describe('Landing', function () {
Landing.prototype.dismissLanding.call(this.landing);
});
- it('should call .classList.add', function () {
+ it('should call .classList.add', function() {
expect(this.landingElement.classList.add).toHaveBeenCalledWith('hidden');
});
- it('should call Cookies.set', function () {
+ it('should call Cookies.set', function() {
expect(Cookies.set).toHaveBeenCalledWith(this.cookieName, 'true', { expires: 365 });
});
});
- describe('isDismissed', function () {
- beforeEach(function () {
+ describe('isDismissed', function() {
+ beforeEach(function() {
this.cookieName = 'cookie_name';
this.landing = { cookieName: this.cookieName };
@@ -149,11 +155,11 @@ describe('Landing', function () {
this.isDismissed = Landing.prototype.isDismissed.call(this.landing);
});
- it('should call Cookies.get', function () {
+ it('should call Cookies.get', function() {
expect(Cookies.get).toHaveBeenCalledWith(this.cookieName);
});
- it('should return a boolean', function () {
+ it('should return a boolean', function() {
expect(typeof this.isDismissed).toEqual('boolean');
});
});
diff --git a/spec/javascripts/lazy_loader_spec.js b/spec/javascripts/lazy_loader_spec.js
index c177d79b9e0..cbdc1644430 100644
--- a/spec/javascripts/lazy_loader_spec.js
+++ b/spec/javascripts/lazy_loader_spec.js
@@ -1,57 +1,244 @@
import LazyLoader from '~/lazy_loader';
+import { TEST_HOST } from './test_constants';
+import scrollIntoViewPromise from './helpers/scroll_into_view_promise';
+import waitForPromises from './helpers/wait_for_promises';
+import waitForAttributeChange from './helpers/wait_for_attribute_change';
-let lazyLoader = null;
+const execImmediately = callback => {
+ callback();
+};
describe('LazyLoader', function() {
+ let lazyLoader = null;
+
preloadFixtures('issues/issue_with_comment.html.raw');
- beforeEach(function() {
- loadFixtures('issues/issue_with_comment.html.raw');
- lazyLoader = new LazyLoader({
- observerNode: 'body',
+ describe('without IntersectionObserver', () => {
+ beforeEach(function() {
+ loadFixtures('issues/issue_with_comment.html.raw');
+
+ lazyLoader = new LazyLoader({
+ observerNode: 'foobar',
+ });
+
+ spyOn(LazyLoader, 'supportsIntersectionObserver').and.callFake(() => false);
+
+ spyOn(LazyLoader, 'loadImage').and.callThrough();
+
+ spyOn(window, 'requestAnimationFrame').and.callFake(execImmediately);
+ spyOn(window, 'requestIdleCallback').and.callFake(execImmediately);
+
+ // Doing everything that happens normally in onload
+ lazyLoader.register();
+ });
+
+ afterEach(() => {
+ lazyLoader.unregister();
+ });
+
+ it('should copy value from data-src to src for img 1', function(done) {
+ const img = document.querySelectorAll('img[data-src]')[0];
+ const originalDataSrc = img.getAttribute('data-src');
+
+ Promise.all([scrollIntoViewPromise(img), waitForAttributeChange(img, ['data-src', 'src'])])
+ .then(() => {
+ expect(LazyLoader.loadImage).toHaveBeenCalled();
+ expect(img.getAttribute('src')).toBe(originalDataSrc);
+ expect(img).toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('should lazy load dynamically added data-src images', function(done) {
+ const newImg = document.createElement('img');
+ const testPath = `${TEST_HOST}/img/testimg.png`;
+ newImg.className = 'lazy';
+ newImg.setAttribute('data-src', testPath);
+ document.body.appendChild(newImg);
+
+ Promise.all([
+ scrollIntoViewPromise(newImg),
+ waitForAttributeChange(newImg, ['data-src', 'src']),
+ ])
+ .then(() => {
+ expect(LazyLoader.loadImage).toHaveBeenCalled();
+ expect(newImg.getAttribute('src')).toBe(testPath);
+ expect(newImg).toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('should not alter normal images', function(done) {
+ const newImg = document.createElement('img');
+ const testPath = `${TEST_HOST}/img/testimg.png`;
+ newImg.setAttribute('src', testPath);
+ document.body.appendChild(newImg);
+
+ scrollIntoViewPromise(newImg)
+ .then(waitForPromises)
+ .then(() => {
+ expect(LazyLoader.loadImage).not.toHaveBeenCalled();
+ expect(newImg).not.toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('should not load dynamically added pictures if content observer is turned off', done => {
+ lazyLoader.stopContentObserver();
+
+ const newImg = document.createElement('img');
+ const testPath = `${TEST_HOST}/img/testimg.png`;
+ newImg.className = 'lazy';
+ newImg.setAttribute('data-src', testPath);
+ document.body.appendChild(newImg);
+
+ scrollIntoViewPromise(newImg)
+ .then(waitForPromises)
+ .then(() => {
+ expect(LazyLoader.loadImage).not.toHaveBeenCalled();
+ expect(newImg).not.toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('should load dynamically added pictures if content observer is turned off and on again', done => {
+ lazyLoader.stopContentObserver();
+ lazyLoader.startContentObserver();
+
+ const newImg = document.createElement('img');
+ const testPath = `${TEST_HOST}/img/testimg.png`;
+ newImg.className = 'lazy';
+ newImg.setAttribute('data-src', testPath);
+ document.body.appendChild(newImg);
+
+ Promise.all([
+ scrollIntoViewPromise(newImg),
+ waitForAttributeChange(newImg, ['data-src', 'src']),
+ ])
+ .then(waitForPromises)
+ .then(() => {
+ expect(LazyLoader.loadImage).toHaveBeenCalled();
+ expect(newImg).toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
});
- // Doing everything that happens normally in onload
- lazyLoader.loadCheck();
});
- describe('behavior', function() {
+
+ describe('with IntersectionObserver', () => {
+ beforeEach(function() {
+ loadFixtures('issues/issue_with_comment.html.raw');
+
+ lazyLoader = new LazyLoader({
+ observerNode: 'foobar',
+ });
+
+ spyOn(LazyLoader, 'loadImage').and.callThrough();
+
+ spyOn(window, 'requestAnimationFrame').and.callFake(execImmediately);
+ spyOn(window, 'requestIdleCallback').and.callFake(execImmediately);
+
+ // Doing everything that happens normally in onload
+ lazyLoader.register();
+ });
+
+ afterEach(() => {
+ lazyLoader.unregister();
+ });
+
it('should copy value from data-src to src for img 1', function(done) {
const img = document.querySelectorAll('img[data-src]')[0];
const originalDataSrc = img.getAttribute('data-src');
- img.scrollIntoView();
- setTimeout(() => {
- expect(img.getAttribute('src')).toBe(originalDataSrc);
- expect(document.getElementsByClassName('js-lazy-loaded').length).toBeGreaterThan(0);
- done();
- }, 100);
+ Promise.all([scrollIntoViewPromise(img), waitForAttributeChange(img, ['data-src', 'src'])])
+ .then(() => {
+ expect(LazyLoader.loadImage).toHaveBeenCalled();
+ expect(img.getAttribute('src')).toBe(originalDataSrc);
+ expect(img).toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
});
it('should lazy load dynamically added data-src images', function(done) {
const newImg = document.createElement('img');
- const testPath = '/img/testimg.png';
+ const testPath = `${TEST_HOST}/img/testimg.png`;
newImg.className = 'lazy';
newImg.setAttribute('data-src', testPath);
document.body.appendChild(newImg);
- newImg.scrollIntoView();
- setTimeout(() => {
- expect(newImg.getAttribute('src')).toBe(testPath);
- expect(document.getElementsByClassName('js-lazy-loaded').length).toBeGreaterThan(0);
- done();
- }, 100);
+ Promise.all([
+ scrollIntoViewPromise(newImg),
+ waitForAttributeChange(newImg, ['data-src', 'src']),
+ ])
+ .then(() => {
+ expect(LazyLoader.loadImage).toHaveBeenCalled();
+ expect(newImg.getAttribute('src')).toBe(testPath);
+ expect(newImg).toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
});
it('should not alter normal images', function(done) {
const newImg = document.createElement('img');
- const testPath = '/img/testimg.png';
+ const testPath = `${TEST_HOST}/img/testimg.png`;
newImg.setAttribute('src', testPath);
document.body.appendChild(newImg);
- newImg.scrollIntoView();
- setTimeout(() => {
- expect(newImg).not.toHaveClass('js-lazy-loaded');
- done();
- }, 100);
+ scrollIntoViewPromise(newImg)
+ .then(waitForPromises)
+ .then(() => {
+ expect(LazyLoader.loadImage).not.toHaveBeenCalled();
+ expect(newImg).not.toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('should not load dynamically added pictures if content observer is turned off', done => {
+ lazyLoader.stopContentObserver();
+
+ const newImg = document.createElement('img');
+ const testPath = `${TEST_HOST}/img/testimg.png`;
+ newImg.className = 'lazy';
+ newImg.setAttribute('data-src', testPath);
+ document.body.appendChild(newImg);
+
+ scrollIntoViewPromise(newImg)
+ .then(waitForPromises)
+ .then(() => {
+ expect(LazyLoader.loadImage).not.toHaveBeenCalled();
+ expect(newImg).not.toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
+ });
+
+ it('should load dynamically added pictures if content observer is turned off and on again', done => {
+ lazyLoader.stopContentObserver();
+ lazyLoader.startContentObserver();
+
+ const newImg = document.createElement('img');
+ const testPath = `${TEST_HOST}/img/testimg.png`;
+ newImg.className = 'lazy';
+ newImg.setAttribute('data-src', testPath);
+ document.body.appendChild(newImg);
+
+ Promise.all([
+ scrollIntoViewPromise(newImg),
+ waitForAttributeChange(newImg, ['data-src', 'src']),
+ ])
+ .then(() => {
+ expect(LazyLoader.loadImage).toHaveBeenCalled();
+ expect(newImg).toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
});
});
});
diff --git a/spec/javascripts/lib/utils/accessor_spec.js b/spec/javascripts/lib/utils/accessor_spec.js
index b768d6f2a68..0045330e470 100644
--- a/spec/javascripts/lib/utils/accessor_spec.js
+++ b/spec/javascripts/lib/utils/accessor_spec.js
@@ -13,7 +13,11 @@ describe('AccessorUtilities', () => {
});
it('should return `false` if access throws an error', () => {
- base = { get testProp() { throw testError; } };
+ base = {
+ get testProp() {
+ throw testError;
+ },
+ };
expect(AccessorUtilities.isPropertyAccessSafe(base, 'testProp')).toBe(false);
});
@@ -35,7 +39,9 @@ describe('AccessorUtilities', () => {
});
it('should return `false` if calling throws an error', () => {
- base.func = () => { throw new Error('test error'); };
+ base.func = () => {
+ throw new Error('test error');
+ };
expect(AccessorUtilities.isFunctionCallSafe(base, 'func')).toBe(false);
});
@@ -58,7 +64,9 @@ describe('AccessorUtilities', () => {
});
it('should return `false` if access to .setItem isnt safe', () => {
- window.localStorage.setItem.and.callFake(() => { throw testError; });
+ window.localStorage.setItem.and.callFake(() => {
+ throw testError;
+ });
expect(AccessorUtilities.isLocalStorageAccessSafe()).toBe(false);
});
diff --git a/spec/javascripts/lib/utils/ajax_cache_spec.js b/spec/javascripts/lib/utils/ajax_cache_spec.js
index 7603400b55e..dc0b04173bf 100644
--- a/spec/javascripts/lib/utils/ajax_cache_spec.js
+++ b/spec/javascripts/lib/utils/ajax_cache_spec.js
@@ -9,8 +9,8 @@ describe('AjaxCache', () => {
};
beforeEach(() => {
- AjaxCache.internalStorage = { };
- AjaxCache.pendingRequests = { };
+ AjaxCache.internalStorage = {};
+ AjaxCache.pendingRequests = {};
});
describe('get', () => {
@@ -59,7 +59,7 @@ describe('AjaxCache', () => {
it('does nothing if cache is empty', () => {
AjaxCache.remove(dummyEndpoint);
- expect(AjaxCache.internalStorage).toEqual({ });
+ expect(AjaxCache.internalStorage).toEqual({});
});
it('does nothing if cache contains no matching data', () => {
@@ -75,7 +75,7 @@ describe('AjaxCache', () => {
AjaxCache.remove(dummyEndpoint);
- expect(AjaxCache.internalStorage).toEqual({ });
+ expect(AjaxCache.internalStorage).toEqual({});
});
});
@@ -101,61 +101,61 @@ describe('AjaxCache', () => {
mock.restore();
});
- it('stores and returns data from Ajax call if cache is empty', (done) => {
+ it('stores and returns data from Ajax call if cache is empty', done => {
mock.onGet(dummyEndpoint).reply(200, dummyResponse);
AjaxCache.retrieve(dummyEndpoint)
- .then((data) => {
- expect(data).toEqual(dummyResponse);
- expect(AjaxCache.internalStorage[dummyEndpoint]).toEqual(dummyResponse);
- })
- .then(done)
- .catch(fail);
+ .then(data => {
+ expect(data).toEqual(dummyResponse);
+ expect(AjaxCache.internalStorage[dummyEndpoint]).toEqual(dummyResponse);
+ })
+ .then(done)
+ .catch(fail);
});
- it('makes no Ajax call if request is pending', (done) => {
+ it('makes no Ajax call if request is pending', done => {
mock.onGet(dummyEndpoint).reply(200, dummyResponse);
AjaxCache.retrieve(dummyEndpoint)
- .then(done)
- .catch(fail);
+ .then(done)
+ .catch(fail);
AjaxCache.retrieve(dummyEndpoint)
- .then(done)
- .catch(fail);
+ .then(done)
+ .catch(fail);
expect(axios.get.calls.count()).toBe(1);
});
- it('returns undefined if Ajax call fails and cache is empty', (done) => {
+ it('returns undefined if Ajax call fails and cache is empty', done => {
const errorMessage = 'Network Error';
mock.onGet(dummyEndpoint).networkError();
AjaxCache.retrieve(dummyEndpoint)
- .then(data => fail(`Received unexpected data: ${JSON.stringify(data)}`))
- .catch((error) => {
- expect(error.message).toBe(`${dummyEndpoint}: ${errorMessage}`);
- expect(error.textStatus).toBe(errorMessage);
- done();
- })
- .catch(fail);
+ .then(data => fail(`Received unexpected data: ${JSON.stringify(data)}`))
+ .catch(error => {
+ expect(error.message).toBe(`${dummyEndpoint}: ${errorMessage}`);
+ expect(error.textStatus).toBe(errorMessage);
+ done();
+ })
+ .catch(fail);
});
- it('makes no Ajax call if matching data exists', (done) => {
+ it('makes no Ajax call if matching data exists', done => {
AjaxCache.internalStorage[dummyEndpoint] = dummyResponse;
mock.onGet(dummyEndpoint).reply(() => {
fail(new Error('expected no Ajax call!'));
});
AjaxCache.retrieve(dummyEndpoint)
- .then((data) => {
- expect(data).toBe(dummyResponse);
- })
- .then(done)
- .catch(fail);
+ .then(data => {
+ expect(data).toBe(dummyResponse);
+ })
+ .then(done)
+ .catch(fail);
});
- it('makes Ajax call even if matching data exists when forceRequest parameter is provided', (done) => {
+ it('makes Ajax call even if matching data exists when forceRequest parameter is provided', done => {
const oldDummyResponse = {
important: 'old dummy data',
};
@@ -166,7 +166,7 @@ describe('AjaxCache', () => {
// Call without forceRetrieve param
AjaxCache.retrieve(dummyEndpoint)
- .then((data) => {
+ .then(data => {
expect(data).toBe(oldDummyResponse);
})
.then(done)
@@ -174,7 +174,7 @@ describe('AjaxCache', () => {
// Call with forceRetrieve param
AjaxCache.retrieve(dummyEndpoint, true)
- .then((data) => {
+ .then(data => {
expect(data).toEqual(dummyResponse);
})
.then(done)
diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js
index 28151c7e658..1ec1e8a8dd9 100644
--- a/spec/javascripts/lib/utils/common_utils_spec.js
+++ b/spec/javascripts/lib/utils/common_utils_spec.js
@@ -1,4 +1,3 @@
-/* eslint-disable promise/catch-or-return */
import axios from '~/lib/utils/axios_utils';
import * as commonUtils from '~/lib/utils/common_utils';
import MockAdapter from 'axios-mock-adapter';
@@ -9,6 +8,7 @@ describe('common_utils', () => {
it('returns an anchor tag with url', () => {
expect(commonUtils.parseUrl('/some/absolute/url').pathname).toContain('some/absolute/url');
});
+
it('url is escaped', () => {
// IE11 will return a relative pathname while other browsers will return a full pathname.
// parseUrl uses an anchor element for parsing an url. With relative urls, the anchor
@@ -35,38 +35,31 @@ describe('common_utils', () => {
});
it('should decode params', () => {
- expect(
- commonUtils.urlParamsToArray('?label_name%5B%5D=test')[0],
- ).toBe('label_name[]=test');
+ expect(commonUtils.urlParamsToArray('?label_name%5B%5D=test')[0]).toBe('label_name[]=test');
});
it('should remove the question mark from the search params', () => {
const paramsArray = commonUtils.urlParamsToArray('?test=thing');
- expect(paramsArray[0][0] !== '?').toBe(true);
+
+ expect(paramsArray[0][0]).not.toBe('?');
});
});
describe('urlParamsToObject', () => {
it('parses path for label with trailing +', () => {
- expect(
- commonUtils.urlParamsToObject('label_name[]=label%2B', {}),
- ).toEqual({
+ expect(commonUtils.urlParamsToObject('label_name[]=label%2B', {})).toEqual({
label_name: ['label+'],
});
});
it('parses path for milestone with trailing +', () => {
- expect(
- commonUtils.urlParamsToObject('milestone_title=A%2B', {}),
- ).toEqual({
+ expect(commonUtils.urlParamsToObject('milestone_title=A%2B', {})).toEqual({
milestone_title: 'A+',
});
});
it('parses path for search terms with spaces', () => {
- expect(
- commonUtils.urlParamsToObject('search=two+words', {}),
- ).toEqual({
+ expect(commonUtils.urlParamsToObject('search=two+words', {})).toEqual({
search: 'two words',
});
});
@@ -121,6 +114,7 @@ describe('common_utils', () => {
commonUtils.handleLocationHash();
expectGetElementIdToHaveBeenCalledWith('test');
+
expect(window.scrollY).toBe(document.getElementById('test').offsetTop);
document.getElementById('parent').remove();
@@ -139,6 +133,7 @@ describe('common_utils', () => {
expectGetElementIdToHaveBeenCalledWith('test');
expectGetElementIdToHaveBeenCalledWith('user-content-test');
+
expect(window.scrollY).toBe(document.getElementById('user-content-test').offsetTop);
document.getElementById('parent').remove();
@@ -159,6 +154,7 @@ describe('common_utils', () => {
expectGetElementIdToHaveBeenCalledWith('test');
expectGetElementIdToHaveBeenCalledWith('user-content-test');
+
expect(window.scrollY).toBe(document.getElementById('user-content-test').offsetTop - 50);
expect(window.scrollBy).toHaveBeenCalledWith(0, -50);
@@ -183,7 +179,11 @@ describe('common_utils', () => {
describe('parseQueryStringIntoObject', () => {
it('should return object with query parameters', () => {
- expect(commonUtils.parseQueryStringIntoObject('scope=all&page=2')).toEqual({ scope: 'all', page: '2' });
+ expect(commonUtils.parseQueryStringIntoObject('scope=all&page=2')).toEqual({
+ scope: 'all',
+ page: '2',
+ });
+
expect(commonUtils.parseQueryStringIntoObject('scope=all')).toEqual({ scope: 'all' });
expect(commonUtils.parseQueryStringIntoObject()).toEqual({});
});
@@ -207,7 +207,9 @@ describe('common_utils', () => {
describe('buildUrlWithCurrentLocation', () => {
it('should build an url with current location and given parameters', () => {
expect(commonUtils.buildUrlWithCurrentLocation()).toEqual(window.location.pathname);
- expect(commonUtils.buildUrlWithCurrentLocation('?page=2')).toEqual(`${window.location.pathname}?page=2`);
+ expect(commonUtils.buildUrlWithCurrentLocation('?page=2')).toEqual(
+ `${window.location.pathname}?page=2`,
+ );
});
});
@@ -222,20 +224,24 @@ describe('common_utils', () => {
it('should return valid parameter', () => {
const value = commonUtils.getParameterByName('scope');
+
expect(commonUtils.getParameterByName('p')).toEqual('2');
expect(value).toBe('all');
});
it('should return invalid parameter', () => {
const value = commonUtils.getParameterByName('fakeParameter');
+
expect(value).toBe(null);
});
it('should return valid paramentes if URL is provided', () => {
let value = commonUtils.getParameterByName('foo', 'http://cocteau.twins/?foo=bar');
+
expect(value).toBe('bar');
value = commonUtils.getParameterByName('manan', 'http://cocteau.twins/?foo=bar&manan=canchu');
+
expect(value).toBe('canchu');
});
});
@@ -258,21 +264,24 @@ describe('common_utils', () => {
});
describe('normalizeCRLFHeaders', () => {
- beforeEach(function () {
- this.CLRFHeaders = 'a-header: a-value\nAnother-Header: ANOTHER-VALUE\nLaSt-HeAdEr: last-VALUE';
+ beforeEach(function() {
+ this.CLRFHeaders =
+ 'a-header: a-value\nAnother-Header: ANOTHER-VALUE\nLaSt-HeAdEr: last-VALUE';
spyOn(String.prototype, 'split').and.callThrough();
this.normalizeCRLFHeaders = commonUtils.normalizeCRLFHeaders(this.CLRFHeaders);
});
- it('should split by newline', function () {
+ it('should split by newline', function() {
expect(String.prototype.split).toHaveBeenCalledWith('\n');
});
- it('should split by colon+space for each header', function () {
- expect(String.prototype.split.calls.allArgs().filter(args => args[0] === ': ').length).toBe(3);
+ it('should split by colon+space for each header', function() {
+ expect(String.prototype.split.calls.allArgs().filter(args => args[0] === ': ').length).toBe(
+ 3,
+ );
});
- it('should return a normalized headers object', function () {
+ it('should return a normalized headers object', function() {
expect(this.normalizeCRLFHeaders).toEqual({
'A-HEADER': 'a-value',
'ANOTHER-HEADER': 'ANOTHER-VALUE',
@@ -337,6 +346,24 @@ describe('common_utils', () => {
});
});
+ describe('parseBoolean', () => {
+ it('returns true for "true"', () => {
+ expect(commonUtils.parseBoolean('true')).toEqual(true);
+ });
+
+ it('returns false for "false"', () => {
+ expect(commonUtils.parseBoolean('false')).toEqual(false);
+ });
+
+ it('returns false for "something"', () => {
+ expect(commonUtils.parseBoolean('something')).toEqual(false);
+ });
+
+ it('returns false for null', () => {
+ expect(commonUtils.parseBoolean(null)).toEqual(false);
+ });
+ });
+
describe('convertPermissionToBoolean', () => {
it('should convert a boolean in a string to a boolean', () => {
expect(commonUtils.convertPermissionToBoolean('true')).toEqual(true);
@@ -351,60 +378,76 @@ describe('common_utils', () => {
spyOn(window, 'setTimeout').and.callFake(cb => origSetTimeout(cb, 0));
});
- it('solves the promise from the callback', (done) => {
+ it('solves the promise from the callback', done => {
const expectedResponseValue = 'Success!';
- commonUtils.backOff((next, stop) => (
- new Promise((resolve) => {
- resolve(expectedResponseValue);
- }).then((resp) => {
- stop(resp);
+ commonUtils
+ .backOff((next, stop) =>
+ new Promise(resolve => {
+ resolve(expectedResponseValue);
+ })
+ .then(resp => {
+ stop(resp);
+ })
+ .catch(done.fail),
+ )
+ .then(respBackoff => {
+ expect(respBackoff).toBe(expectedResponseValue);
+ done();
})
- )).then((respBackoff) => {
- expect(respBackoff).toBe(expectedResponseValue);
- done();
- });
+ .catch(done.fail);
});
- it('catches the rejected promise from the callback ', (done) => {
+ it('catches the rejected promise from the callback ', done => {
const errorMessage = 'Mistakes were made!';
- commonUtils.backOff((next, stop) => {
- new Promise((resolve, reject) => {
- reject(new Error(errorMessage));
- }).then((resp) => {
- stop(resp);
- }).catch(err => stop(err));
- }).catch((errBackoffResp) => {
- expect(errBackoffResp instanceof Error).toBe(true);
- expect(errBackoffResp.message).toBe(errorMessage);
- done();
- });
+ commonUtils
+ .backOff((next, stop) => {
+ new Promise((resolve, reject) => {
+ reject(new Error(errorMessage));
+ })
+ .then(resp => {
+ stop(resp);
+ })
+ .catch(err => stop(err));
+ })
+ .catch(errBackoffResp => {
+ expect(errBackoffResp instanceof Error).toBe(true);
+ expect(errBackoffResp.message).toBe(errorMessage);
+ done();
+ });
});
- it('solves the promise correctly after retrying a third time', (done) => {
+ it('solves the promise correctly after retrying a third time', done => {
let numberOfCalls = 1;
const expectedResponseValue = 'Success!';
- commonUtils.backOff((next, stop) => (
- Promise.resolve(expectedResponseValue)
- .then((resp) => {
- if (numberOfCalls < 3) {
- numberOfCalls += 1;
- next();
- } else {
- stop(resp);
- }
- })
- )).then((respBackoff) => {
- const timeouts = window.setTimeout.calls.allArgs().map(([, timeout]) => timeout);
- expect(timeouts).toEqual([2000, 4000]);
- expect(respBackoff).toBe(expectedResponseValue);
- done();
- });
+ commonUtils
+ .backOff((next, stop) =>
+ Promise.resolve(expectedResponseValue)
+ .then(resp => {
+ if (numberOfCalls < 3) {
+ numberOfCalls += 1;
+ next();
+ } else {
+ stop(resp);
+ }
+ })
+ .catch(done.fail),
+ )
+ .then(respBackoff => {
+ const timeouts = window.setTimeout.calls.allArgs().map(([, timeout]) => timeout);
+
+ expect(timeouts).toEqual([2000, 4000]);
+ expect(respBackoff).toBe(expectedResponseValue);
+ done();
+ })
+ .catch(done.fail);
});
- it('rejects the backOff promise after timing out', (done) => {
- commonUtils.backOff(next => next(), 64000)
- .catch((errBackoffResp) => {
+ it('rejects the backOff promise after timing out', done => {
+ commonUtils
+ .backOff(next => next(), 64000)
+ .catch(errBackoffResp => {
const timeouts = window.setTimeout.calls.allArgs().map(([, timeout]) => timeout);
+
expect(timeouts).toEqual([2000, 4000, 8000, 16000, 32000, 32000]);
expect(errBackoffResp instanceof Error).toBe(true);
expect(errBackoffResp.message).toBe('BACKOFF_TIMEOUT');
@@ -450,16 +493,20 @@ describe('common_utils', () => {
const favicon = document.getElementById('favicon');
favicon.setAttribute('href', 'new/favicon');
commonUtils.resetFavicon();
+
expect(document.getElementById('favicon').getAttribute('href')).toEqual('default/favicon');
});
});
describe('createOverlayIcon', () => {
- it('should return the favicon with the overlay', (done) => {
- commonUtils.createOverlayIcon(faviconDataUrl, overlayDataUrl).then((url) => {
- expect(url).toEqual(faviconWithOverlayDataUrl);
- done();
- });
+ it('should return the favicon with the overlay', done => {
+ commonUtils
+ .createOverlayIcon(faviconDataUrl, overlayDataUrl)
+ .then(url => {
+ expect(url).toEqual(faviconWithOverlayDataUrl);
+ done();
+ })
+ .catch(done.fail);
});
});
@@ -475,11 +522,16 @@ describe('common_utils', () => {
document.body.removeChild(document.getElementById('favicon'));
});
- it('should set page favicon to provided favicon overlay', (done) => {
- commonUtils.setFaviconOverlay(overlayDataUrl).then(() => {
- expect(document.getElementById('favicon').getAttribute('href')).toEqual(faviconWithOverlayDataUrl);
- done();
- });
+ it('should set page favicon to provided favicon overlay', done => {
+ commonUtils
+ .setFaviconOverlay(overlayDataUrl)
+ .then(() => {
+ expect(document.getElementById('favicon').getAttribute('href')).toEqual(
+ faviconWithOverlayDataUrl,
+ );
+ done();
+ })
+ .catch(done.fail);
});
});
@@ -501,25 +553,27 @@ describe('common_utils', () => {
document.body.removeChild(document.getElementById('favicon'));
});
- it('should reset favicon in case of error', (done) => {
+ it('should reset favicon in case of error', done => {
mock.onGet(BUILD_URL).replyOnce(500);
- commonUtils.setCiStatusFavicon(BUILD_URL)
- .catch(() => {
- const favicon = document.getElementById('favicon');
- expect(favicon.getAttribute('href')).toEqual(faviconDataUrl);
- done();
- });
+ commonUtils.setCiStatusFavicon(BUILD_URL).catch(() => {
+ const favicon = document.getElementById('favicon');
+
+ expect(favicon.getAttribute('href')).toEqual(faviconDataUrl);
+ done();
+ });
});
- it('should set page favicon to CI status favicon based on provided status', (done) => {
+ it('should set page favicon to CI status favicon based on provided status', done => {
mock.onGet(BUILD_URL).reply(200, {
favicon: overlayDataUrl,
});
- commonUtils.setCiStatusFavicon(BUILD_URL)
+ commonUtils
+ .setCiStatusFavicon(BUILD_URL)
.then(() => {
const favicon = document.getElementById('favicon');
+
expect(favicon.getAttribute('href')).toEqual(faviconWithOverlayDataUrl);
done();
})
@@ -541,11 +595,15 @@ describe('common_utils', () => {
});
it('should return the svg for a linked icon', () => {
- expect(commonUtils.spriteIcon('test')).toEqual('<svg ><use xlink:href="icons.svg#test" /></svg>');
+ expect(commonUtils.spriteIcon('test')).toEqual(
+ '<svg ><use xlink:href="icons.svg#test" /></svg>',
+ );
});
it('should set svg className when passed', () => {
- expect(commonUtils.spriteIcon('test', 'fa fa-test')).toEqual('<svg class="fa fa-test"><use xlink:href="icons.svg#test" /></svg>');
+ expect(commonUtils.spriteIcon('test', 'fa fa-test')).toEqual(
+ '<svg class="fa fa-test"><use xlink:href="icons.svg#test" /></svg>',
+ );
});
});
@@ -565,7 +623,7 @@ describe('common_utils', () => {
const convertedObj = commonUtils.convertObjectPropsToCamelCase(mockObj);
- Object.keys(convertedObj).forEach((prop) => {
+ Object.keys(convertedObj).forEach(prop => {
expect(snakeRegEx.test(prop)).toBeFalsy();
expect(convertedObj[prop]).toBe(mockObj[mappings[prop]]);
});
@@ -584,9 +642,7 @@ describe('common_utils', () => {
},
};
- expect(
- commonUtils.convertObjectPropsToCamelCase(obj),
- ).toEqual({
+ expect(commonUtils.convertObjectPropsToCamelCase(obj)).toEqual({
snakeKey: {
child_snake_key: 'value',
},
@@ -601,9 +657,7 @@ describe('common_utils', () => {
},
};
- expect(
- commonUtils.convertObjectPropsToCamelCase(obj, { deep: true }),
- ).toEqual({
+ expect(commonUtils.convertObjectPropsToCamelCase(obj, { deep: true })).toEqual({
snakeKey: {
childSnakeKey: 'value',
},
@@ -617,9 +671,7 @@ describe('common_utils', () => {
},
];
- expect(
- commonUtils.convertObjectPropsToCamelCase(arr, { deep: true }),
- ).toEqual([
+ expect(commonUtils.convertObjectPropsToCamelCase(arr, { deep: true })).toEqual([
{
childSnakeKey: 'value',
},
@@ -635,9 +687,7 @@ describe('common_utils', () => {
],
];
- expect(
- commonUtils.convertObjectPropsToCamelCase(arr, { deep: true }),
- ).toEqual([
+ expect(commonUtils.convertObjectPropsToCamelCase(arr, { deep: true })).toEqual([
[
{
childSnakeKey: 'value',
diff --git a/spec/javascripts/lib/utils/csrf_token_spec.js b/spec/javascripts/lib/utils/csrf_token_spec.js
index 81a39a97a84..867bee34ee5 100644
--- a/spec/javascripts/lib/utils/csrf_token_spec.js
+++ b/spec/javascripts/lib/utils/csrf_token_spec.js
@@ -1,9 +1,10 @@
import csrf from '~/lib/utils/csrf';
-describe('csrf', function () {
+describe('csrf', function() {
beforeEach(() => {
this.tokenKey = 'X-CSRF-Token';
- this.token = 'pH1cvjnP9grx2oKlhWEDvUZnJ8x2eXsIs1qzyHkF3DugSG5yTxR76CWeEZRhML2D1IeVB7NEW0t5l/axE4iJpQ==';
+ this.token =
+ 'pH1cvjnP9grx2oKlhWEDvUZnJ8x2eXsIs1qzyHkF3DugSG5yTxR76CWeEZRhML2D1IeVB7NEW0t5l/axE4iJpQ==';
});
it('returns the correct headerKey', () => {
diff --git a/spec/javascripts/lib/utils/datefix_spec.js b/spec/javascripts/lib/utils/datefix_spec.js
deleted file mode 100644
index a9f3abcf2a4..00000000000
--- a/spec/javascripts/lib/utils/datefix_spec.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import { pad, pikadayToString } from '~/lib/utils/datefix';
-
-describe('datefix', () => {
- describe('pad', () => {
- it('should add a 0 when length is smaller than 2', () => {
- expect(pad(2)).toEqual('02');
- });
-
- it('should not add a zero when lenght matches the default', () => {
- expect(pad(12)).toEqual('12');
- });
-
- it('should add a 0 when lenght is smaller than the provided', () => {
- expect(pad(12, 3)).toEqual('012');
- });
- });
-
- describe('parsePikadayDate', () => {
- // removed because of https://gitlab.com/gitlab-org/gitlab-ce/issues/39834
- });
-
- describe('pikadayToString', () => {
- it('should format a UTC date into yyyy-mm-dd format', () => {
- expect(pikadayToString(new Date('2020-01-29:00:00'))).toEqual('2020-01-29');
- });
- });
-});
diff --git a/spec/javascripts/lib/utils/datetime_utility_spec.js b/spec/javascripts/lib/utils/datetime_utility_spec.js
new file mode 100644
index 00000000000..bebe76f76c5
--- /dev/null
+++ b/spec/javascripts/lib/utils/datetime_utility_spec.js
@@ -0,0 +1,378 @@
+import * as datetimeUtility from '~/lib/utils/datetime_utility';
+
+describe('Date time utils', () => {
+ describe('timeFor', () => {
+ it('returns `past due` when in past', () => {
+ const date = new Date();
+ date.setFullYear(date.getFullYear() - 1);
+
+ expect(datetimeUtility.timeFor(date)).toBe('Past due');
+ });
+
+ it('returns remaining time when in the future', () => {
+ const date = new Date();
+ date.setFullYear(date.getFullYear() + 1);
+
+ // Add a day to prevent a transient error. If date is even 1 second
+ // short of a full year, timeFor will return '11 months remaining'
+ date.setDate(date.getDate() + 1);
+
+ expect(datetimeUtility.timeFor(date)).toBe('1 year remaining');
+ });
+ });
+
+ describe('get day name', () => {
+ it('should return Sunday', () => {
+ const day = datetimeUtility.getDayName(new Date('07/17/2016'));
+
+ expect(day).toBe('Sunday');
+ });
+
+ it('should return Monday', () => {
+ const day = datetimeUtility.getDayName(new Date('07/18/2016'));
+
+ expect(day).toBe('Monday');
+ });
+
+ it('should return Tuesday', () => {
+ const day = datetimeUtility.getDayName(new Date('07/19/2016'));
+
+ expect(day).toBe('Tuesday');
+ });
+
+ it('should return Wednesday', () => {
+ const day = datetimeUtility.getDayName(new Date('07/20/2016'));
+
+ expect(day).toBe('Wednesday');
+ });
+
+ it('should return Thursday', () => {
+ const day = datetimeUtility.getDayName(new Date('07/21/2016'));
+
+ expect(day).toBe('Thursday');
+ });
+
+ it('should return Friday', () => {
+ const day = datetimeUtility.getDayName(new Date('07/22/2016'));
+
+ expect(day).toBe('Friday');
+ });
+
+ it('should return Saturday', () => {
+ const day = datetimeUtility.getDayName(new Date('07/23/2016'));
+
+ expect(day).toBe('Saturday');
+ });
+ });
+
+ describe('get day difference', () => {
+ it('should return 7', () => {
+ const firstDay = new Date('07/01/2016');
+ const secondDay = new Date('07/08/2016');
+ const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
+
+ expect(difference).toBe(7);
+ });
+
+ it('should return 31', () => {
+ const firstDay = new Date('07/01/2016');
+ const secondDay = new Date('08/01/2016');
+ const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
+
+ expect(difference).toBe(31);
+ });
+
+ it('should return 365', () => {
+ const firstDay = new Date('07/02/2015');
+ const secondDay = new Date('07/01/2016');
+ const difference = datetimeUtility.getDayDifference(firstDay, secondDay);
+
+ expect(difference).toBe(365);
+ });
+ });
+});
+
+describe('timeIntervalInWords', () => {
+ it('should return string with number of minutes and seconds', () => {
+ expect(datetimeUtility.timeIntervalInWords(9.54)).toEqual('9 seconds');
+ expect(datetimeUtility.timeIntervalInWords(1)).toEqual('1 second');
+ expect(datetimeUtility.timeIntervalInWords(200)).toEqual('3 minutes 20 seconds');
+ expect(datetimeUtility.timeIntervalInWords(6008)).toEqual('100 minutes 8 seconds');
+ });
+});
+
+describe('dateInWords', () => {
+ const date = new Date('07/01/2016');
+
+ it('should return date in words', () => {
+ expect(datetimeUtility.dateInWords(date)).toEqual('July 1, 2016');
+ });
+
+ it('should return abbreviated month name', () => {
+ expect(datetimeUtility.dateInWords(date, true)).toEqual('Jul 1, 2016');
+ });
+
+ it('should return date in words without year', () => {
+ expect(datetimeUtility.dateInWords(date, true, true)).toEqual('Jul 1');
+ });
+});
+
+describe('monthInWords', () => {
+ const date = new Date('2017-01-20');
+
+ it('returns month name from provided date', () => {
+ expect(datetimeUtility.monthInWords(date)).toBe('January');
+ });
+
+ it('returns abbreviated month name from provided date', () => {
+ expect(datetimeUtility.monthInWords(date, true)).toBe('Jan');
+ });
+});
+
+describe('totalDaysInMonth', () => {
+ it('returns number of days in a month for given date', () => {
+ // 1st Feb, 2016 (leap year)
+ expect(datetimeUtility.totalDaysInMonth(new Date(2016, 1, 1))).toBe(29);
+
+ // 1st Feb, 2017
+ expect(datetimeUtility.totalDaysInMonth(new Date(2017, 1, 1))).toBe(28);
+
+ // 1st Jan, 2017
+ expect(datetimeUtility.totalDaysInMonth(new Date(2017, 0, 1))).toBe(31);
+ });
+});
+
+describe('getSundays', () => {
+ it('returns array of dates representing all Sundays of the month', () => {
+ // December, 2017 (it has 5 Sundays)
+ const dateOfSundays = [3, 10, 17, 24, 31];
+ const sundays = datetimeUtility.getSundays(new Date(2017, 11, 1));
+
+ expect(sundays.length).toBe(5);
+ sundays.forEach((sunday, index) => {
+ expect(sunday.getDate()).toBe(dateOfSundays[index]);
+ });
+ });
+});
+
+describe('getTimeframeWindowFrom', () => {
+ it('returns array of date objects upto provided length start with provided startDate', () => {
+ const startDate = new Date(2018, 0, 1);
+ const mockTimeframe = [
+ new Date(2018, 0, 1),
+ new Date(2018, 1, 1),
+ new Date(2018, 2, 1),
+ new Date(2018, 3, 1),
+ new Date(2018, 4, 31),
+ ];
+ const timeframe = datetimeUtility.getTimeframeWindowFrom(startDate, 5);
+
+ expect(timeframe.length).toBe(5);
+ timeframe.forEach((timeframeItem, index) => {
+ expect(timeframeItem.getFullYear()).toBe(mockTimeframe[index].getFullYear());
+ expect(timeframeItem.getMonth()).toBe(mockTimeframe[index].getMonth());
+ expect(timeframeItem.getDate()).toBe(mockTimeframe[index].getDate());
+ });
+ });
+});
+
+describe('formatTime', () => {
+ const expectedTimestamps = [
+ [0, '00:00:00'],
+ [1000, '00:00:01'],
+ [42000, '00:00:42'],
+ [121000, '00:02:01'],
+ [10921000, '03:02:01'],
+ [108000000, '30:00:00'],
+ ];
+
+ expectedTimestamps.forEach(([milliseconds, expectedTimestamp]) => {
+ it(`formats ${milliseconds}ms as ${expectedTimestamp}`, () => {
+ expect(datetimeUtility.formatTime(milliseconds)).toBe(expectedTimestamp);
+ });
+ });
+});
+
+describe('datefix', () => {
+ describe('pad', () => {
+ it('should add a 0 when length is smaller than 2', () => {
+ expect(datetimeUtility.pad(2)).toEqual('02');
+ });
+
+ it('should not add a zero when length matches the default', () => {
+ expect(datetimeUtility.pad(12)).toEqual('12');
+ });
+
+ it('should add a 0 when length is smaller than the provided', () => {
+ expect(datetimeUtility.pad(12, 3)).toEqual('012');
+ });
+ });
+
+ describe('parsePikadayDate', () => {
+ // removed because of https://gitlab.com/gitlab-org/gitlab-ce/issues/39834
+ });
+
+ describe('pikadayToString', () => {
+ it('should format a UTC date into yyyy-mm-dd format', () => {
+ expect(datetimeUtility.pikadayToString(new Date('2020-01-29:00:00'))).toEqual('2020-01-29');
+ });
+ });
+});
+
+describe('prettyTime methods', () => {
+ const assertTimeUnits = (obj, minutes, hours, days, weeks) => {
+ expect(obj.minutes).toBe(minutes);
+ expect(obj.hours).toBe(hours);
+ expect(obj.days).toBe(days);
+ expect(obj.weeks).toBe(weeks);
+ };
+
+ describe('parseSeconds', () => {
+ it('should correctly parse a negative value', () => {
+ const zeroSeconds = datetimeUtility.parseSeconds(-1000);
+
+ assertTimeUnits(zeroSeconds, 16, 0, 0, 0);
+ });
+
+ it('should correctly parse a zero value', () => {
+ const zeroSeconds = datetimeUtility.parseSeconds(0);
+
+ assertTimeUnits(zeroSeconds, 0, 0, 0, 0);
+ });
+
+ it('should correctly parse a small non-zero second values', () => {
+ const subOneMinute = datetimeUtility.parseSeconds(10);
+ const aboveOneMinute = datetimeUtility.parseSeconds(100);
+ const manyMinutes = datetimeUtility.parseSeconds(1000);
+
+ assertTimeUnits(subOneMinute, 0, 0, 0, 0);
+ assertTimeUnits(aboveOneMinute, 1, 0, 0, 0);
+ assertTimeUnits(manyMinutes, 16, 0, 0, 0);
+ });
+
+ it('should correctly parse large second values', () => {
+ const aboveOneHour = datetimeUtility.parseSeconds(4800);
+ const aboveOneDay = datetimeUtility.parseSeconds(110000);
+ const aboveOneWeek = datetimeUtility.parseSeconds(25000000);
+
+ assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
+ assertTimeUnits(aboveOneDay, 33, 6, 3, 0);
+ assertTimeUnits(aboveOneWeek, 26, 0, 3, 173);
+ });
+
+ it('should correctly accept a custom param for hoursPerDay', () => {
+ const config = { hoursPerDay: 24 };
+
+ const aboveOneHour = datetimeUtility.parseSeconds(4800, config);
+ const aboveOneDay = datetimeUtility.parseSeconds(110000, config);
+ const aboveOneWeek = datetimeUtility.parseSeconds(25000000, config);
+
+ assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
+ assertTimeUnits(aboveOneDay, 33, 6, 1, 0);
+ assertTimeUnits(aboveOneWeek, 26, 8, 4, 57);
+ });
+
+ it('should correctly accept a custom param for daysPerWeek', () => {
+ const config = { daysPerWeek: 7 };
+
+ const aboveOneHour = datetimeUtility.parseSeconds(4800, config);
+ const aboveOneDay = datetimeUtility.parseSeconds(110000, config);
+ const aboveOneWeek = datetimeUtility.parseSeconds(25000000, config);
+
+ assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
+ assertTimeUnits(aboveOneDay, 33, 6, 3, 0);
+ assertTimeUnits(aboveOneWeek, 26, 0, 0, 124);
+ });
+
+ it('should correctly accept custom params for daysPerWeek and hoursPerDay', () => {
+ const config = { daysPerWeek: 55, hoursPerDay: 14 };
+
+ const aboveOneHour = datetimeUtility.parseSeconds(4800, config);
+ const aboveOneDay = datetimeUtility.parseSeconds(110000, config);
+ const aboveOneWeek = datetimeUtility.parseSeconds(25000000, config);
+
+ assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
+ assertTimeUnits(aboveOneDay, 33, 2, 2, 0);
+ assertTimeUnits(aboveOneWeek, 26, 0, 1, 9);
+ });
+ });
+
+ describe('stringifyTime', () => {
+ it('should stringify values with all non-zero units', () => {
+ const timeObject = {
+ weeks: 1,
+ days: 4,
+ hours: 7,
+ minutes: 20,
+ };
+
+ const timeString = datetimeUtility.stringifyTime(timeObject);
+
+ expect(timeString).toBe('1w 4d 7h 20m');
+ });
+
+ it('should stringify values with some non-zero units', () => {
+ const timeObject = {
+ weeks: 0,
+ days: 4,
+ hours: 0,
+ minutes: 20,
+ };
+
+ const timeString = datetimeUtility.stringifyTime(timeObject);
+
+ expect(timeString).toBe('4d 20m');
+ });
+
+ it('should stringify values with no non-zero units', () => {
+ const timeObject = {
+ weeks: 0,
+ days: 0,
+ hours: 0,
+ minutes: 0,
+ };
+
+ const timeString = datetimeUtility.stringifyTime(timeObject);
+
+ expect(timeString).toBe('0m');
+ });
+
+ it('should return non-condensed representation of time object', () => {
+ const timeObject = { weeks: 1, days: 0, hours: 1, minutes: 0 };
+
+ expect(datetimeUtility.stringifyTime(timeObject, true)).toEqual('1 week 1 hour');
+ });
+ });
+
+ describe('abbreviateTime', () => {
+ it('should abbreviate stringified times for weeks', () => {
+ const fullTimeString = '1w 3d 4h 5m';
+
+ expect(datetimeUtility.abbreviateTime(fullTimeString)).toBe('1w');
+ });
+
+ it('should abbreviate stringified times for non-weeks', () => {
+ const fullTimeString = '0w 3d 4h 5m';
+
+ expect(datetimeUtility.abbreviateTime(fullTimeString)).toBe('3d');
+ });
+ });
+});
+
+describe('calculateRemainingMilliseconds', () => {
+ beforeEach(() => {
+ spyOn(Date, 'now').and.callFake(() => new Date('2063-04-04T00:42:00Z').getTime());
+ });
+
+ it('calculates the remaining time for a given end date', () => {
+ const milliseconds = datetimeUtility.calculateRemainingMilliseconds('2063-04-04T01:44:03Z');
+
+ expect(milliseconds).toBe(3723000);
+ });
+
+ it('returns 0 if the end date has passed', () => {
+ const milliseconds = datetimeUtility.calculateRemainingMilliseconds('2063-04-03T00:00:00Z');
+
+ expect(milliseconds).toBe(0);
+ });
+});
diff --git a/spec/javascripts/lib/utils/dom_utils_spec.js b/spec/javascripts/lib/utils/dom_utils_spec.js
index 867bf5912d1..1fb2e4584a0 100644
--- a/spec/javascripts/lib/utils/dom_utils_spec.js
+++ b/spec/javascripts/lib/utils/dom_utils_spec.js
@@ -18,6 +18,7 @@ describe('DOM Utils', () => {
it('adds class if element exists', () => {
const childElement = parentElement.querySelector('.child');
+
expect(childElement).not.toBe(null);
addClassIfElementExists(childElement, className);
@@ -27,6 +28,7 @@ describe('DOM Utils', () => {
it('does not throw if element does not exist', () => {
const childElement = parentElement.querySelector('.other-child');
+
expect(childElement).toBe(null);
addClassIfElementExists(childElement, className);
diff --git a/spec/javascripts/lib/utils/mock_data.js b/spec/javascripts/lib/utils/mock_data.js
index 93d0d6259b9..c466b0cd1ed 100644
--- a/spec/javascripts/lib/utils/mock_data.js
+++ b/spec/javascripts/lib/utils/mock_data.js
@@ -1,5 +1,8 @@
-export const faviconDataUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAACcFBMVEX////iQyniQyniQyniQyniQyniQyniQyniQynhRiriQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniRCniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQynhQiniQiniQiniQinhQinpUSjqUSjqTyjqTyjqTyjlSCniRCniQynjRCjqTyjsZSjrWyj8oib9kSb8pyb9pib8oyb8fyb3ZSb4Zib8fCb8oyb8oyb8oyb8pCb8cSbiQyn7bCb8cib8oyb8oSb8bSbtVSjpTij8nyb8oyb8oyb8lCb2Yyf3ZCf8mCb8oyb8oyb8oyb8iib8bSbiRCn8gyb8oyb8eCbpTinrUSj8oyb8oyb8oyb8pSb8bib4Zif0YCf8byb8oyb8oyb8oyb7oib8oyb8nCbjRSn9bib8ayb8nib8oyb8oyb8oyb8kSbpTyjpTyj8jib8oyb8oyb8oyb8fib0Xyf2ZSb8gCb8oyb6pSb8oyb8dib+cCbgQCnjRSn8cCb8oib8oyb8oyb8oybqUCjnSyn8bCb8oyb8oyb8oyb8myb2YyfyXyf8oyb8oyb8hibhQSn+bib8iSb8oyb8qCb+fSbmSSnqTyj8oib9pCb1YifxXyf7pSb8oCb8pCb+mCb0fCf8pSb7hSXvcSjiQyniQinqTyj9kCb9bib9byb+cCbqUSjiRCnsVCj+cSb8pib8bCb8bSbgQCn7bCb8bibjRSn8oyb8ayb8oib8aib8pCbjRCn8pybhQinhQSn8pSb7ayb7aSb6aib8eib///8IbM+7AAAAr3RSTlMBA3NtX2vT698HGQcRLwWLiXnv++3V+eEd/R8HE2V/Y5HjyefdFw99YWfJ+/3nwQP78/HvX1VTQ/kdA2HzbQXj9fX79/3DGf379/33T/v99/f7ba33+/f1+9/18/v59V339flzF/H9+fX3/fMhBwOh9/v5/fmvBV/z+fP3Awnp9/f38+UFgff7+/37+4c77/f7/flFz/f59dFr7/v98Wnr+/f3I5/197EDBU1ZAwUD8/kLUwAAAAFiS0dEAIgFHUgAAAAHdElNRQfhBQoLHiBV6/1lAAACHUlEQVQ4y41TZXsTQRCe4FAIUigN7m7FXY+iLRQKBG2x4g7BjhZ3Le7uMoEkFJprwyQk0CC/iZnNhUZaHt4vt6/szO7cHcD/wFKjZrJWq3YMq1M3eVc9rFzXR2yQkuA3RGxkjZLGiEk9miA2tURJs1RsnhhokYYtzaU13WZDbBVnW1sjo43J2vI6tZ0lLtFeAh1M0lECneI7dGYtrUtk3RUVIKaEJR25qw27yT0s3W0qEHuPlB4RradivXo7GX36xnbo51SQ+fWHARmCgYMGDxkaxbD3SssYPmIkwKgPLrfA87EETTg/fVaSa/SYsQDjSsd7DcGEsr+BieVKmaRNBsjUtClTfUI900y/5Mt05c8oJQKYSURZ2UqYFa0w283M588JEM2BuRwI5EqT8nmmXzZf4l8XsGNfCIv4QcHFklhiBpaqAsuC4tghj+ySyOdjeJYrP7RCCuR/E5tWAqxaLcmCNSyujdxjHZdbn8UHoA0bN/GoNm8hjQJb/ZzYpo6w3TB27JRduxxqrA7YzbWCezixN8RD2Oc2/Ptlfx7o5uT1A4XMiwzj4HfEikNe7+Ew0ZGjeuW70eEYaeHjxomTiKd++E4XnKGz8d+HDufOB3Ky3RcwdNF1qZiKLyf/B44r2tWf15wV143cwI2qfi8dbtKtX6Hbd+6G74EDqkTm/QcPH/0ufFyNLXjy9NnzF9Xb8BJevYY38C+8fZcg/AF3QTYemVkCwwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNy0wNS0xMFQxMTozMDozMiswMjowMMzup8UAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTctMDUtMTBUMTE6MzA6MzIrMDI6MDC9sx95AAAAAElFTkSuQmCC';
+export const faviconDataUrl =
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAACcFBMVEX////iQyniQyniQyniQyniQyniQyniQyniQynhRiriQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniRCniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQyniQynhQiniQiniQiniQinhQinpUSjqUSjqTyjqTyjqTyjlSCniRCniQynjRCjqTyjsZSjrWyj8oib9kSb8pyb9pib8oyb8fyb3ZSb4Zib8fCb8oyb8oyb8oyb8pCb8cSbiQyn7bCb8cib8oyb8oSb8bSbtVSjpTij8nyb8oyb8oyb8lCb2Yyf3ZCf8mCb8oyb8oyb8oyb8iib8bSbiRCn8gyb8oyb8eCbpTinrUSj8oyb8oyb8oyb8pSb8bib4Zif0YCf8byb8oyb8oyb8oyb7oib8oyb8nCbjRSn9bib8ayb8nib8oyb8oyb8oyb8kSbpTyjpTyj8jib8oyb8oyb8oyb8fib0Xyf2ZSb8gCb8oyb6pSb8oyb8dib+cCbgQCnjRSn8cCb8oib8oyb8oyb8oybqUCjnSyn8bCb8oyb8oyb8oyb8myb2YyfyXyf8oyb8oyb8hibhQSn+bib8iSb8oyb8qCb+fSbmSSnqTyj8oib9pCb1YifxXyf7pSb8oCb8pCb+mCb0fCf8pSb7hSXvcSjiQyniQinqTyj9kCb9bib9byb+cCbqUSjiRCnsVCj+cSb8pib8bCb8bSbgQCn7bCb8bibjRSn8oyb8ayb8oib8aib8pCbjRCn8pybhQinhQSn8pSb7ayb7aSb6aib8eib///8IbM+7AAAAr3RSTlMBA3NtX2vT698HGQcRLwWLiXnv++3V+eEd/R8HE2V/Y5HjyefdFw99YWfJ+/3nwQP78/HvX1VTQ/kdA2HzbQXj9fX79/3DGf379/33T/v99/f7ba33+/f1+9/18/v59V339flzF/H9+fX3/fMhBwOh9/v5/fmvBV/z+fP3Awnp9/f38+UFgff7+/37+4c77/f7/flFz/f59dFr7/v98Wnr+/f3I5/197EDBU1ZAwUD8/kLUwAAAAFiS0dEAIgFHUgAAAAHdElNRQfhBQoLHiBV6/1lAAACHUlEQVQ4y41TZXsTQRCe4FAIUigN7m7FXY+iLRQKBG2x4g7BjhZ3Le7uMoEkFJprwyQk0CC/iZnNhUZaHt4vt6/szO7cHcD/wFKjZrJWq3YMq1M3eVc9rFzXR2yQkuA3RGxkjZLGiEk9miA2tURJs1RsnhhokYYtzaU13WZDbBVnW1sjo43J2vI6tZ0lLtFeAh1M0lECneI7dGYtrUtk3RUVIKaEJR25qw27yT0s3W0qEHuPlB4RradivXo7GX36xnbo51SQ+fWHARmCgYMGDxkaxbD3SssYPmIkwKgPLrfA87EETTg/fVaSa/SYsQDjSsd7DcGEsr+BieVKmaRNBsjUtClTfUI900y/5Mt05c8oJQKYSURZ2UqYFa0w283M588JEM2BuRwI5EqT8nmmXzZf4l8XsGNfCIv4QcHFklhiBpaqAsuC4tghj+ySyOdjeJYrP7RCCuR/E5tWAqxaLcmCNSyujdxjHZdbn8UHoA0bN/GoNm8hjQJb/ZzYpo6w3TB27JRduxxqrA7YzbWCezixN8RD2Oc2/Ptlfx7o5uT1A4XMiwzj4HfEikNe7+Ew0ZGjeuW70eEYaeHjxomTiKd++E4XnKGz8d+HDufOB3Ky3RcwdNF1qZiKLyf/B44r2tWf15wV143cwI2qfi8dbtKtX6Hbd+6G74EDqkTm/QcPH/0ufFyNLXjy9NnzF9Xb8BJevYY38C+8fZcg/AF3QTYemVkCwwAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNy0wNS0xMFQxMTozMDozMiswMjowMMzup8UAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTctMDUtMTBUMTE6MzA6MzIrMDI6MDC9sx95AAAAAElFTkSuQmCC';
-export const overlayDataUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAA85JREFUWAntVllIVGEUPv/9b46O41KplYN7PeRkti8TjQlhCUGh3MmeQugpIsGKAi2soIcIooiohxYKK2daqDAlIpIiWwxtQaJcaHE0d5tMrbn37z9XRqfR0TvVW56Hudf//uec72zfEWBCJjIwkYGJDPzvGSD/KgExN3Oi2Q+2DJgSDYQEMwItVGH1iZGmJw/Si1y+/PwVAMYYib22MYc/8hVQFgKDEfYoId0KYzagAQebsos/ewMZoeB9wdffcTYpQSaCTWHKoqSQaDk7zkIt0+aCUR8BelEHrf3dUNv9AcqbnsHtT5UKB/hTASh0SLYjnjb/CIDRJi0XiFAaJOpCD8zLpdb4NB66b1OfelthX815dtdRRfiti2aAXLvVLiMQ6olGyztGDkSo4JGGXk8/QFdGpYzpHG2GBQTDhtgVhPEaVbbVpvI6GJz22rv4TcAfrYI1x7Rj5MWWAppomKFVVb2302SFzUkZHAbkG+0b1+Gh77yNYjrmqnWTrLBLRxdvBWv8qlFujH/kYjJYyvLkj71t78zAUvzMAMnHhpN4zf9UREJhd8omyssxu1IgazQDwDnHUcNuH6vhPIE1fmuBzHt74Hn7W89jWGtcAjoaIDOFrdcMYJBkgOCoaRF0Lj0oglddDbCj6tRvKjphEpgjkzEQs2YAKsNxMzjn3nKurhzK+Ly7xe28ua8TwgMMcHJZnvvT0BPtEEKM4tDJ+C8GvIIk4ylINIXVZ0EUKJxYuh3mhCeokbudl6TtVc88dfBdLwbyaWB6zQCYQJpBYSrDGQxBQ/ZWRM2B+VNmQnVnHWx7elyNuL2/R336co7KyJR8CL9oLgEuFlREevWUkEl6uGwpVEG4FBm0OEf9N10NMgPlvWYAuNVwsWDKvcUNYsHUWTCZ13ysyFEXe6TO6aC8CUr9IiK+A05TQrc8yjwmxARHeeMAPlfQJw+AQRwu0YhL/GDXi9NwufG+S8dYkuYMqIb4SsWthotlNMOUCOM6r+G9cqXxPmd1dqrBav/o1zJy2l5/NUjJA/VORwYuFnOUaTQcPs9wMqwV++Xv8oADxKAcZ8nLPr8AoGW+xR6HSqYk3GodAz2QNj0V+Gr26dT9ASNH5239Pf0gktVNWZca8ZvfAFBprWS6hSu1pqt++Y0PD+WIwDAhIWQGtzvSHDbcodfFUFB9hg1Gjs5LXqIdFL+acFBl+FddqYwdxsWC3I70OvgfUaA65zhq2O2c8VxYcyIGFTVlXegYtvCXANCQZJMobjVcLMjtSK/IcEgyOOe8Ve5w7ryKDefp2P3+C/5ohv8HZmVLAAAAAElFTkSuQmCC';
+export const overlayDataUrl =
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAA85JREFUWAntVllIVGEUPv/9b46O41KplYN7PeRkti8TjQlhCUGh3MmeQugpIsGKAi2soIcIooiohxYKK2daqDAlIpIiWwxtQaJcaHE0d5tMrbn37z9XRqfR0TvVW56Hudf//uec72zfEWBCJjIwkYGJDPzvGSD/KgExN3Oi2Q+2DJgSDYQEMwItVGH1iZGmJw/Si1y+/PwVAMYYib22MYc/8hVQFgKDEfYoId0KYzagAQebsos/ewMZoeB9wdffcTYpQSaCTWHKoqSQaDk7zkIt0+aCUR8BelEHrf3dUNv9AcqbnsHtT5UKB/hTASh0SLYjnjb/CIDRJi0XiFAaJOpCD8zLpdb4NB66b1OfelthX815dtdRRfiti2aAXLvVLiMQ6olGyztGDkSo4JGGXk8/QFdGpYzpHG2GBQTDhtgVhPEaVbbVpvI6GJz22rv4TcAfrYI1x7Rj5MWWAppomKFVVb2302SFzUkZHAbkG+0b1+Gh77yNYjrmqnWTrLBLRxdvBWv8qlFujH/kYjJYyvLkj71t78zAUvzMAMnHhpN4zf9UREJhd8omyssxu1IgazQDwDnHUcNuH6vhPIE1fmuBzHt74Hn7W89jWGtcAjoaIDOFrdcMYJBkgOCoaRF0Lj0oglddDbCj6tRvKjphEpgjkzEQs2YAKsNxMzjn3nKurhzK+Ly7xe28ua8TwgMMcHJZnvvT0BPtEEKM4tDJ+C8GvIIk4ylINIXVZ0EUKJxYuh3mhCeokbudl6TtVc88dfBdLwbyaWB6zQCYQJpBYSrDGQxBQ/ZWRM2B+VNmQnVnHWx7elyNuL2/R336co7KyJR8CL9oLgEuFlREevWUkEl6uGwpVEG4FBm0OEf9N10NMgPlvWYAuNVwsWDKvcUNYsHUWTCZ13ysyFEXe6TO6aC8CUr9IiK+A05TQrc8yjwmxARHeeMAPlfQJw+AQRwu0YhL/GDXi9NwufG+S8dYkuYMqIb4SsWthotlNMOUCOM6r+G9cqXxPmd1dqrBav/o1zJy2l5/NUjJA/VORwYuFnOUaTQcPs9wMqwV++Xv8oADxKAcZ8nLPr8AoGW+xR6HSqYk3GodAz2QNj0V+Gr26dT9ASNH5239Pf0gktVNWZca8ZvfAFBprWS6hSu1pqt++Y0PD+WIwDAhIWQGtzvSHDbcodfFUFB9hg1Gjs5LXqIdFL+acFBl+FddqYwdxsWC3I70OvgfUaA65zhq2O2c8VxYcyIGFTVlXegYtvCXANCQZJMobjVcLMjtSK/IcEgyOOe8Ve5w7ryKDefp2P3+C/5ohv8HZmVLAAAAAElFTkSuQmCC';
-export const faviconWithOverlayDataUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAGtElEQVRYR8WXf3CT9R3H35/nSdIQIktrCf0RStI0FYRjVBAccxTq5MDBKUoz4ZyjbPO87q4yBsPDMdExTjlvIsdQexyI0oMBeuKhdjsNHhwcMgpjIlublLIm/UlJKZSSJs/z/e6+T5v0CQ22wB/7/pPck8/383l9fj6fEOec8H88NAjAS1LwknsFSVLU8WXd1rtm85LUeKnwGQKzjj3s33azvsEAAEIlnn8ByHL4/Pa7BgAQLCm8QOBOh88vDQkQeMxjMkcQEYKqYsyJWWPhgs/80TsFafzROJtkNIXFfYI0pfXqPeennjqlxPUNikBoTuEmEF+lCRBV3G0aQiWFrwH8d30AWJubGdiEfZzdGqDEEwbICnADQGGHry7zTr0X94IlnnMACggwAWh0+PxOvb5EBGqmTTNkj7ySxWS62C+g5Usm1Zn95YXG24UQ+r5n75Li6Ux4LBkyc7/4t5YSLSr6Lgg9UvBLcKocMEYKON/gGB3YoA/bcGFCczzLQdieLE9bHL66FakBSjzCU0cSAHDa4at7aLhG9XLBEk8zAVnxZxyIEhBy+PwFgwAafpxvNzK5NZUhrX28JA07Cl6SmtvcOUwm4ZAouHj7ad+jMrN1dqb3iG7oS4EYPh2etQS+XiesC8TQ3ZD3yZJsHuUPgbMcI+ej5v3ncv5PasNlk1p7JJnzJL+I0/O5h+u0VCdqIDi78AQRHuirft3hYJzQPvawPydVdPI+/OnTnNNKBjYVXHRa8rFFGeb4w1he0wZ7d/84IXTEhxzxUsgitB2LPFGwvgGUfLSeZUpEXqEqrIdz0nr4iHOUfeOccb/tNMtutzWHPeWcJc0aMxm5lkxYDGloj1zB+Sv/RXXTSXzaeBwSY3j+bHNv2bdtMYCbpHtRkNFd36xFQN3tXkZhvgP1fdPi5kMEXL4oIXKVAA58M8aCVQs84BYLXi5aDq+zGJTqYr+i4PV2vHxmJ/7WUoOn2i/jz6yhW7JjrdSV8U4fQFV+I2Q4UIsedMCSSlcsgp72WtnSajOhzDsBNtsYfFD8e+Rbs4fdIG98uw9vnj+AX7FWvk4NHZOXXphF/INx2SpJIU2L8L4GDAoMwlP9kWSg6awcKVs83tyUnY5Dj75+W8bjutae3o5d9X/HTiWAuUtOS6RUOR8Hp48TxjgU/AMSeKJ1Ej/tMWXG1sxwGt98sBxe5+xhe64XVLiK2Z9XwNgdRLXyzQsC4ENwelIHAFxDBOdh1qdCdNLCoon8RnY+HZ6/+TtzPhTZweAxlJ94C5VqoI2U3a7rACzJjQqgBd24CGscos1kxPQZ38fqSU/jhQkDvN9lrKG7FeUnNuPVKcvwYOb4hGgvi2HSx8vwRKyJkVLl+hk43gdBAcfADBD1cA4RXIdZ1EN1Zjqem+DGoUc2oigjMUlvaV8YL/1qPVpuhOG+JwdH5m1Okn3m6Eacaz3V2jeI9uTbVYY6AKOSKw8MX0MBg2lXjh3r3Hk4s7ASdrMtSWxnoBpZIzIwP3e69lxv3Gay4q/F6zDJ5kq6s6amEnsafJ0Db8P9JKkx1w5wPJuY36IToojgNMzb8rLwmsuB2kW7YDWMSCgTg+YXx9+AQZKxdUaFZiju+a2Mi8uvnH0f2/2f9g4AVE4z4LlTilrlehag9xIpEam4jO4DXfdaV97nwtH5byW137VYD5Yc2YAz4YAGIYx2RLq0z1Sex8l//fUWfBI83jh4Kd1PEuAwqVGjWEwSS+nJJmt0sWu86d0frMQCR/LbWQ8hDAxlXMgUV69Q67ubv0q5FUNAlHKmVLnXE/gfREpUiaQHqAizXbO0UN98BMTSo39Cw7UW7E2Rc728qJGHP68ASbQyNYCQTkAUzCSwQ+CwvSjnsQPGLOnI/C0YO3Lwxq5yhhtqb1KNpGqT1TXvigJU0jh33xpAf7NymoGNDJ9sJtPkYuNkqTh7KnY8vGaoeZPy93+GA1joe4kzzv/SVLqvYngA/dFgVfnlb8tjtm6Ux+I39y/Gqone24IQM+GxL15UO3q7WrhsnhJatCs8PAC9md3OrPK0goaDyEj7uXsuXi0qg4HkIUGE52XHNqmXIl0RGOiHoUV7xb+v5K14SC39At79Ximdhc8ekjImuiyjsXryUszLnY40yThIhSi4bbUHsbfBJ6ZKE5dpQdz4HQOgf2a8tLvklY+M6cuvSnJummxSZ46+X+7biMzaRnSu84IauNYsE5HCOX+HDCPWi7DrKW8/BTcVZ2UN8Me57kc5448TaCYR5XJwC0BtHMwPjs/SgAP1pfuCqSL8Pxhr/wunLWAOAAAAAElFTkSuQmCC';
+export const faviconWithOverlayDataUrl =
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAGtElEQVRYR8WXf3CT9R3H35/nSdIQIktrCf0RStI0FYRjVBAccxTq5MDBKUoz4ZyjbPO87q4yBsPDMdExTjlvIsdQexyI0oMBeuKhdjsNHhwcMgpjIlublLIm/UlJKZSSJs/z/e6+T5v0CQ22wB/7/pPck8/383l9fj6fEOec8H88NAjAS1LwknsFSVLU8WXd1rtm85LUeKnwGQKzjj3s33azvsEAAEIlnn8ByHL4/Pa7BgAQLCm8QOBOh88vDQkQeMxjMkcQEYKqYsyJWWPhgs/80TsFafzROJtkNIXFfYI0pfXqPeennjqlxPUNikBoTuEmEF+lCRBV3G0aQiWFrwH8d30AWJubGdiEfZzdGqDEEwbICnADQGGHry7zTr0X94IlnnMACggwAWh0+PxOvb5EBGqmTTNkj7ySxWS62C+g5Usm1Zn95YXG24UQ+r5n75Li6Ux4LBkyc7/4t5YSLSr6Lgg9UvBLcKocMEYKON/gGB3YoA/bcGFCczzLQdieLE9bHL66FakBSjzCU0cSAHDa4at7aLhG9XLBEk8zAVnxZxyIEhBy+PwFgwAafpxvNzK5NZUhrX28JA07Cl6SmtvcOUwm4ZAouHj7ad+jMrN1dqb3iG7oS4EYPh2etQS+XiesC8TQ3ZD3yZJsHuUPgbMcI+ej5v3ncv5PasNlk1p7JJnzJL+I0/O5h+u0VCdqIDi78AQRHuirft3hYJzQPvawPydVdPI+/OnTnNNKBjYVXHRa8rFFGeb4w1he0wZ7d/84IXTEhxzxUsgitB2LPFGwvgGUfLSeZUpEXqEqrIdz0nr4iHOUfeOccb/tNMtutzWHPeWcJc0aMxm5lkxYDGloj1zB+Sv/RXXTSXzaeBwSY3j+bHNv2bdtMYCbpHtRkNFd36xFQN3tXkZhvgP1fdPi5kMEXL4oIXKVAA58M8aCVQs84BYLXi5aDq+zGJTqYr+i4PV2vHxmJ/7WUoOn2i/jz6yhW7JjrdSV8U4fQFV+I2Q4UIsedMCSSlcsgp72WtnSajOhzDsBNtsYfFD8e+Rbs4fdIG98uw9vnj+AX7FWvk4NHZOXXphF/INx2SpJIU2L8L4GDAoMwlP9kWSg6awcKVs83tyUnY5Dj75+W8bjutae3o5d9X/HTiWAuUtOS6RUOR8Hp48TxjgU/AMSeKJ1Ej/tMWXG1sxwGt98sBxe5+xhe64XVLiK2Z9XwNgdRLXyzQsC4ENwelIHAFxDBOdh1qdCdNLCoon8RnY+HZ6/+TtzPhTZweAxlJ94C5VqoI2U3a7rACzJjQqgBd24CGscos1kxPQZ38fqSU/jhQkDvN9lrKG7FeUnNuPVKcvwYOb4hGgvi2HSx8vwRKyJkVLl+hk43gdBAcfADBD1cA4RXIdZ1EN1Zjqem+DGoUc2oigjMUlvaV8YL/1qPVpuhOG+JwdH5m1Okn3m6Eacaz3V2jeI9uTbVYY6AKOSKw8MX0MBg2lXjh3r3Hk4s7ASdrMtSWxnoBpZIzIwP3e69lxv3Gay4q/F6zDJ5kq6s6amEnsafJ0Db8P9JKkx1w5wPJuY36IToojgNMzb8rLwmsuB2kW7YDWMSCgTg+YXx9+AQZKxdUaFZiju+a2Mi8uvnH0f2/2f9g4AVE4z4LlTilrlehag9xIpEam4jO4DXfdaV97nwtH5byW137VYD5Yc2YAz4YAGIYx2RLq0z1Sex8l//fUWfBI83jh4Kd1PEuAwqVGjWEwSS+nJJmt0sWu86d0frMQCR/LbWQ8hDAxlXMgUV69Q67ubv0q5FUNAlHKmVLnXE/gfREpUiaQHqAizXbO0UN98BMTSo39Cw7UW7E2Rc728qJGHP68ASbQyNYCQTkAUzCSwQ+CwvSjnsQPGLOnI/C0YO3Lwxq5yhhtqb1KNpGqT1TXvigJU0jh33xpAf7NymoGNDJ9sJtPkYuNkqTh7KnY8vGaoeZPy93+GA1joe4kzzv/SVLqvYngA/dFgVfnlb8tjtm6Ux+I39y/Gqone24IQM+GxL15UO3q7WrhsnhJatCs8PAC9md3OrPK0goaDyEj7uXsuXi0qg4HkIUGE52XHNqmXIl0RGOiHoUV7xb+v5K14SC39At79Ximdhc8ekjImuiyjsXryUszLnY40yThIhSi4bbUHsbfBJ6ZKE5dpQdz4HQOgf2a8tLvklY+M6cuvSnJummxSZ46+X+7biMzaRnSu84IauNYsE5HCOX+HDCPWi7DrKW8/BTcVZ2UN8Me57kc5448TaCYR5XJwC0BtHMwPjs/SgAP1pfuCqSL8Pxhr/wunLWAOAAAAAElFTkSuQmCC';
diff --git a/spec/javascripts/lib/utils/number_utility_spec.js b/spec/javascripts/lib/utils/number_utility_spec.js
index fcf27f6805f..94c6214c86a 100644
--- a/spec/javascripts/lib/utils/number_utility_spec.js
+++ b/spec/javascripts/lib/utils/number_utility_spec.js
@@ -1,4 +1,10 @@
-import { formatRelevantDigits, bytesToKiB, bytesToMiB, bytesToGiB, numberToHumanSize } from '~/lib/utils/number_utils';
+import {
+ formatRelevantDigits,
+ bytesToKiB,
+ bytesToMiB,
+ bytesToGiB,
+ numberToHumanSize,
+} from '~/lib/utils/number_utils';
describe('Number Utils', () => {
describe('formatRelevantDigits', () => {
@@ -10,6 +16,7 @@ describe('Number Utils', () => {
const formattedNumber = formatRelevantDigits('1000.1234567');
const rightFromDecimal = formattedNumber.split('.')[1];
const leftFromDecimal = formattedNumber.split('.')[0];
+
expect(rightFromDecimal.length).toBe(4);
expect(leftFromDecimal.length).toBe(4);
});
@@ -18,6 +25,7 @@ describe('Number Utils', () => {
const formattedNumber = formatRelevantDigits('0.1234567');
const rightFromDecimal = formattedNumber.split('.')[1];
const leftFromDecimal = formattedNumber.split('.')[0];
+
expect(rightFromDecimal.length).toBe(3);
expect(leftFromDecimal.length).toBe(1);
});
@@ -26,6 +34,7 @@ describe('Number Utils', () => {
const formattedNumber = formatRelevantDigits('10.1234567');
const rightFromDecimal = formattedNumber.split('.')[1];
const leftFromDecimal = formattedNumber.split('.')[0];
+
expect(rightFromDecimal.length).toBe(2);
expect(leftFromDecimal.length).toBe(2);
});
@@ -34,6 +43,7 @@ describe('Number Utils', () => {
const formattedNumber = formatRelevantDigits('100.1234567');
const rightFromDecimal = formattedNumber.split('.')[1];
const leftFromDecimal = formattedNumber.split('.')[0];
+
expect(rightFromDecimal.length).toBe(1);
expect(leftFromDecimal.length).toBe(3);
});
diff --git a/spec/javascripts/lib/utils/poll_spec.js b/spec/javascripts/lib/utils/poll_spec.js
index 523f4997bc0..d0da659c3d7 100644
--- a/spec/javascripts/lib/utils/poll_spec.js
+++ b/spec/javascripts/lib/utils/poll_spec.js
@@ -1,3 +1,5 @@
+/* eslint-disable jasmine/no-unsafe-spy */
+
import Poll from '~/lib/utils/poll';
import { successCodes } from '~/lib/utils/http_status';
@@ -45,7 +47,7 @@ describe('Poll', () => {
service.fetch.calls.reset();
});
- it('calls the success callback when no header for interval is provided', (done) => {
+ it('calls the success callback when no header for interval is provided', done => {
mockServiceCall(service, { status: 200 });
setup();
@@ -57,7 +59,7 @@ describe('Poll', () => {
});
});
- it('calls the error callback when the http request returns an error', (done) => {
+ it('calls the error callback when the http request returns an error', done => {
mockServiceCall(service, { status: 500 }, true);
setup();
@@ -69,7 +71,7 @@ describe('Poll', () => {
});
});
- it('skips the error callback when request is aborted', (done) => {
+ it('skips the error callback when request is aborted', done => {
mockServiceCall(service, { status: 0 }, true);
setup();
@@ -82,19 +84,21 @@ describe('Poll', () => {
});
});
- it('should call the success callback when the interval header is -1', (done) => {
+ it('should call the success callback when the interval header is -1', done => {
mockServiceCall(service, { status: 200, headers: { 'poll-interval': -1 } });
- setup().then(() => {
- expect(callbacks.success).toHaveBeenCalled();
- expect(callbacks.error).not.toHaveBeenCalled();
+ setup()
+ .then(() => {
+ expect(callbacks.success).toHaveBeenCalled();
+ expect(callbacks.error).not.toHaveBeenCalled();
- done();
- }).catch(done.fail);
+ done();
+ })
+ .catch(done.fail);
});
describe('for 2xx status code', () => {
successCodes.forEach(httpCode => {
- it(`starts polling when http status is ${httpCode} and interval header is provided`, (done) => {
+ it(`starts polling when http status is ${httpCode} and interval header is provided`, done => {
mockServiceCall(service, { status: httpCode, headers: { 'poll-interval': 1 } });
const Polling = new Poll({
@@ -122,7 +126,7 @@ describe('Poll', () => {
});
describe('stop', () => {
- it('stops polling when method is called', (done) => {
+ it('stops polling when method is called', done => {
mockServiceCall(service, { status: 200, headers: { 'poll-interval': 1 } });
const Polling = new Poll({
@@ -150,7 +154,7 @@ describe('Poll', () => {
});
describe('restart', () => {
- it('should restart polling when its called', (done) => {
+ it('should restart polling when its called', done => {
mockServiceCall(service, { status: 200, headers: { 'poll-interval': 1 } });
const Polling = new Poll({
diff --git a/spec/javascripts/lib/utils/sticky_spec.js b/spec/javascripts/lib/utils/sticky_spec.js
index b87c836654d..1b1e7da1ed3 100644
--- a/spec/javascripts/lib/utils/sticky_spec.js
+++ b/spec/javascripts/lib/utils/sticky_spec.js
@@ -22,25 +22,19 @@ describe('sticky', () => {
isSticky(el, 0, el.offsetTop);
isSticky(el, 0, el.offsetTop);
- expect(
- el.classList.contains('is-stuck'),
- ).toBeTruthy();
+ expect(el.classList.contains('is-stuck')).toBeTruthy();
});
it('adds is-stuck class', () => {
isSticky(el, 0, el.offsetTop);
- expect(
- el.classList.contains('is-stuck'),
- ).toBeTruthy();
+ expect(el.classList.contains('is-stuck')).toBeTruthy();
});
it('inserts placeholder element', () => {
isSticky(el, 0, el.offsetTop, true);
- expect(
- document.querySelector('.sticky-placeholder'),
- ).not.toBeNull();
+ expect(document.querySelector('.sticky-placeholder')).not.toBeNull();
});
});
@@ -51,29 +45,22 @@ describe('sticky', () => {
isSticky(el, 0, el.offsetTop);
isSticky(el, 0, 0);
- expect(
- el.classList.remove,
- ).toHaveBeenCalledWith('is-stuck');
- expect(
- el.classList.contains('is-stuck'),
- ).toBeFalsy();
+ expect(el.classList.remove).toHaveBeenCalledWith('is-stuck');
+
+ expect(el.classList.contains('is-stuck')).toBeFalsy();
});
it('does not add is-stuck class', () => {
isSticky(el, 0, 0);
- expect(
- el.classList.contains('is-stuck'),
- ).toBeFalsy();
+ expect(el.classList.contains('is-stuck')).toBeFalsy();
});
it('removes placeholder', () => {
isSticky(el, 0, el.offsetTop, true);
isSticky(el, 0, 0, true);
- expect(
- document.querySelector('.sticky-placeholder'),
- ).toBeNull();
+ expect(document.querySelector('.sticky-placeholder')).toBeNull();
});
});
});
diff --git a/spec/javascripts/lib/utils/text_markdown_spec.js b/spec/javascripts/lib/utils/text_markdown_spec.js
index ca0e7c395a0..f71d27eb4e4 100644
--- a/spec/javascripts/lib/utils/text_markdown_spec.js
+++ b/spec/javascripts/lib/utils/text_markdown_spec.js
@@ -21,7 +21,14 @@ describe('init markdown', () => {
textArea.selectionStart = 0;
textArea.selectionEnd = 0;
- insertMarkdownText(textArea, textArea.value, '*', null, '', false);
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag: '*',
+ blockTag: null,
+ selected: '',
+ wrap: false,
+ });
expect(textArea.value).toEqual(`${initialValue}* `);
});
@@ -32,7 +39,14 @@ describe('init markdown', () => {
textArea.value = initialValue;
textArea.setSelectionRange(initialValue.length, initialValue.length);
- insertMarkdownText(textArea, textArea.value, '*', null, '', false);
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag: '*',
+ blockTag: null,
+ selected: '',
+ wrap: false,
+ });
expect(textArea.value).toEqual(`${initialValue}\n* `);
});
@@ -43,7 +57,14 @@ describe('init markdown', () => {
textArea.value = initialValue;
textArea.setSelectionRange(initialValue.length, initialValue.length);
- insertMarkdownText(textArea, textArea.value, '*', null, '', false);
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag: '*',
+ blockTag: null,
+ selected: '',
+ wrap: false,
+ });
expect(textArea.value).toEqual(`${initialValue}* `);
});
@@ -54,9 +75,153 @@ describe('init markdown', () => {
textArea.value = initialValue;
textArea.setSelectionRange(initialValue.length, initialValue.length);
- insertMarkdownText(textArea, textArea.value, '*', null, '', false);
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag: '*',
+ blockTag: null,
+ selected: '',
+ wrap: false,
+ });
expect(textArea.value).toEqual(`${initialValue}* `);
});
+
+ it('places the cursor inside the tags', () => {
+ const start = 'lorem ';
+ const end = ' ipsum';
+ const tag = '*';
+
+ textArea.value = `${start}${end}`;
+ textArea.setSelectionRange(start.length, start.length);
+
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag,
+ blockTag: null,
+ selected: '',
+ wrap: true,
+ });
+
+ expect(textArea.value).toEqual(`${start}**${end}`);
+
+ // cursor placement should be between tags
+ expect(textArea.selectionStart).toBe(start.length + tag.length);
+ });
+ });
+
+ describe('with selection', () => {
+ const text = 'initial selected value';
+ const selected = 'selected';
+ beforeEach(() => {
+ textArea.value = text;
+ const selectedIndex = text.indexOf(selected);
+ textArea.setSelectionRange(selectedIndex, selectedIndex + selected.length);
+ });
+
+ it('applies the tag to the selected value', () => {
+ const selectedIndex = text.indexOf(selected);
+ const tag = '*';
+
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag,
+ blockTag: null,
+ selected,
+ wrap: true,
+ });
+
+ expect(textArea.value).toEqual(text.replace(selected, `*${selected}*`));
+
+ // cursor placement should be after selection + 2 tag lengths
+ expect(textArea.selectionStart).toBe(selectedIndex + selected.length + 2 * tag.length);
+ });
+
+ it('replaces the placeholder in the tag', () => {
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag: '[{text}](url)',
+ blockTag: null,
+ selected,
+ wrap: false,
+ });
+
+ expect(textArea.value).toEqual(text.replace(selected, `[${selected}](url)`));
+ });
+
+ describe('and text to be selected', () => {
+ const tag = '[{text}](url)';
+ const select = 'url';
+
+ it('selects the text', () => {
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag,
+ blockTag: null,
+ selected,
+ wrap: false,
+ select,
+ });
+
+ const expectedText = text.replace(selected, `[${selected}](url)`);
+
+ expect(textArea.value).toEqual(expectedText);
+ expect(textArea.selectionStart).toEqual(expectedText.indexOf(select));
+ expect(textArea.selectionEnd).toEqual(expectedText.indexOf(select) + select.length);
+ });
+
+ it('selects the right text when multiple tags are present', () => {
+ const initialValue = `${tag} ${tag} ${selected}`;
+ textArea.value = initialValue;
+ const selectedIndex = initialValue.indexOf(selected);
+ textArea.setSelectionRange(selectedIndex, selectedIndex + selected.length);
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag,
+ blockTag: null,
+ selected,
+ wrap: false,
+ select,
+ });
+
+ const expectedText = initialValue.replace(selected, `[${selected}](url)`);
+
+ expect(textArea.value).toEqual(expectedText);
+ expect(textArea.selectionStart).toEqual(expectedText.lastIndexOf(select));
+ expect(textArea.selectionEnd).toEqual(expectedText.lastIndexOf(select) + select.length);
+ });
+
+ it('should support selected urls', () => {
+ const expectedUrl = 'http://www.gitlab.com';
+ const expectedSelectionText = 'text';
+ const expectedText = `text [${expectedSelectionText}](${expectedUrl}) text`;
+ const initialValue = `text ${expectedUrl} text`;
+
+ textArea.value = initialValue;
+ const selectedIndex = initialValue.indexOf(expectedUrl);
+ textArea.setSelectionRange(selectedIndex, selectedIndex + expectedUrl.length);
+
+ insertMarkdownText({
+ textArea,
+ text: textArea.value,
+ tag,
+ blockTag: null,
+ selected: expectedUrl,
+ wrap: false,
+ select,
+ });
+
+ expect(textArea.value).toEqual(expectedText);
+ expect(textArea.selectionStart).toEqual(expectedText.indexOf(expectedSelectionText, 1));
+ expect(textArea.selectionEnd).toEqual(
+ expectedText.indexOf(expectedSelectionText, 1) + expectedSelectionText.length,
+ );
+ });
+ });
});
});
diff --git a/spec/javascripts/lib/utils/text_utility_spec.js b/spec/javascripts/lib/utils/text_utility_spec.js
index ac3270baef5..92ebfc38722 100644
--- a/spec/javascripts/lib/utils/text_utility_spec.js
+++ b/spec/javascripts/lib/utils/text_utility_spec.js
@@ -120,7 +120,7 @@ describe('text_utility', () => {
});
describe('getFirstCharacterCapitalized', () => {
- it('returns the first character captialized, if first character is alphabetic', () => {
+ it('returns the first character capitalized, if first character is alphabetic', () => {
expect(textUtils.getFirstCharacterCapitalized('loremIpsumDolar')).toEqual('L');
expect(textUtils.getFirstCharacterCapitalized('Sit amit !')).toEqual('S');
});
diff --git a/spec/javascripts/lib/utils/url_utility_spec.js b/spec/javascripts/lib/utils/url_utility_spec.js
index c7f4092911c..e4df8441793 100644
--- a/spec/javascripts/lib/utils/url_utility_spec.js
+++ b/spec/javascripts/lib/utils/url_utility_spec.js
@@ -1,4 +1,4 @@
-import { webIDEUrl } from '~/lib/utils/url_utility';
+import { webIDEUrl, mergeUrlParams } from '~/lib/utils/url_utility';
describe('URL utility', () => {
describe('webIDEUrl', () => {
@@ -26,4 +26,26 @@ describe('URL utility', () => {
});
});
});
+
+ describe('mergeUrlParams', () => {
+ it('adds w', () => {
+ expect(mergeUrlParams({ w: 1 }, '#frag')).toBe('?w=1#frag');
+ expect(mergeUrlParams({ w: 1 }, '/path#frag')).toBe('/path?w=1#frag');
+ expect(mergeUrlParams({ w: 1 }, 'https://host/path')).toBe('https://host/path?w=1');
+ expect(mergeUrlParams({ w: 1 }, 'https://host/path#frag')).toBe('https://host/path?w=1#frag');
+ expect(mergeUrlParams({ w: 1 }, 'https://h/p?k1=v1#frag')).toBe('https://h/p?k1=v1&w=1#frag');
+ });
+
+ it('updates w', () => {
+ expect(mergeUrlParams({ w: 1 }, '?k1=v1&w=0#frag')).toBe('?k1=v1&w=1#frag');
+ });
+
+ it('adds multiple params', () => {
+ expect(mergeUrlParams({ a: 1, b: 2, c: 3 }, '#frag')).toBe('?a=1&b=2&c=3#frag');
+ });
+
+ it('adds and updates encoded params', () => {
+ expect(mergeUrlParams({ a: '&', q: '?' }, '?a=%23#frag')).toBe('?a=%26&q=%3F#frag');
+ });
+ });
});
diff --git a/spec/javascripts/lib/utils/users_cache_spec.js b/spec/javascripts/lib/utils/users_cache_spec.js
index 50371c8c5f6..6adc19bdd51 100644
--- a/spec/javascripts/lib/utils/users_cache_spec.js
+++ b/spec/javascripts/lib/utils/users_cache_spec.js
@@ -6,12 +6,12 @@ describe('UsersCache', () => {
const dummyUser = 'has a farm';
beforeEach(() => {
- UsersCache.internalStorage = { };
+ UsersCache.internalStorage = {};
});
describe('get', () => {
it('returns undefined for empty cache', () => {
- expect(UsersCache.internalStorage).toEqual({ });
+ expect(UsersCache.internalStorage).toEqual({});
const user = UsersCache.get(dummyUsername);
@@ -37,7 +37,7 @@ describe('UsersCache', () => {
describe('hasData', () => {
it('returns false for empty cache', () => {
- expect(UsersCache.internalStorage).toEqual({ });
+ expect(UsersCache.internalStorage).toEqual({});
expect(UsersCache.hasData(dummyUsername)).toBe(false);
});
@@ -57,11 +57,11 @@ describe('UsersCache', () => {
describe('remove', () => {
it('does nothing if cache is empty', () => {
- expect(UsersCache.internalStorage).toEqual({ });
+ expect(UsersCache.internalStorage).toEqual({});
UsersCache.remove(dummyUsername);
- expect(UsersCache.internalStorage).toEqual({ });
+ expect(UsersCache.internalStorage).toEqual({});
});
it('does nothing if cache contains no matching data', () => {
@@ -77,7 +77,7 @@ describe('UsersCache', () => {
UsersCache.remove(dummyUsername);
- expect(UsersCache.internalStorage).toEqual({ });
+ expect(UsersCache.internalStorage).toEqual({});
});
});
@@ -88,7 +88,7 @@ describe('UsersCache', () => {
spyOn(Api, 'users').and.callFake((query, options) => apiSpy(query, options));
});
- it('stores and returns data from API call if cache is empty', (done) => {
+ it('stores and returns data from API call if cache is empty', done => {
apiSpy = (query, options) => {
expect(query).toBe('');
expect(options).toEqual({ username: dummyUsername });
@@ -98,15 +98,15 @@ describe('UsersCache', () => {
};
UsersCache.retrieve(dummyUsername)
- .then((user) => {
- expect(user).toBe(dummyUser);
- expect(UsersCache.internalStorage[dummyUsername]).toBe(dummyUser);
- })
- .then(done)
- .catch(done.fail);
+ .then(user => {
+ expect(user).toBe(dummyUser);
+ expect(UsersCache.internalStorage[dummyUsername]).toBe(dummyUser);
+ })
+ .then(done)
+ .catch(done.fail);
});
- it('returns undefined if Ajax call fails and cache is empty', (done) => {
+ it('returns undefined if Ajax call fails and cache is empty', done => {
const dummyError = new Error('server exploded');
apiSpy = (query, options) => {
expect(query).toBe('');
@@ -115,24 +115,24 @@ describe('UsersCache', () => {
};
UsersCache.retrieve(dummyUsername)
- .then(user => fail(`Received unexpected user: ${JSON.stringify(user)}`))
- .catch((error) => {
- expect(error).toBe(dummyError);
- })
- .then(done)
- .catch(done.fail);
+ .then(user => fail(`Received unexpected user: ${JSON.stringify(user)}`))
+ .catch(error => {
+ expect(error).toBe(dummyError);
+ })
+ .then(done)
+ .catch(done.fail);
});
- it('makes no Ajax call if matching data exists', (done) => {
+ it('makes no Ajax call if matching data exists', done => {
UsersCache.internalStorage[dummyUsername] = dummyUser;
apiSpy = () => fail(new Error('expected no Ajax call!'));
UsersCache.retrieve(dummyUsername)
- .then((user) => {
- expect(user).toBe(dummyUser);
- })
- .then(done)
- .catch(done.fail);
+ .then(user => {
+ expect(user).toBe(dummyUser);
+ })
+ .then(done)
+ .catch(done.fail);
});
});
});
diff --git a/spec/javascripts/line_highlighter_spec.js b/spec/javascripts/line_highlighter_spec.js
index 8cf0017f4d8..4eea364bd69 100644
--- a/spec/javascripts/line_highlighter_spec.js
+++ b/spec/javascripts/line_highlighter_spec.js
@@ -1,226 +1,265 @@
-/* eslint-disable no-var, quotes, prefer-template, no-else-return, dot-notation, no-return-assign, comma-dangle, no-new, one-var, one-var-declaration-per-line, no-underscore-dangle, max-len */
+/* eslint-disable no-var, prefer-template, no-else-return, dot-notation, no-return-assign, no-new, no-underscore-dangle */
import $ from 'jquery';
import LineHighlighter from '~/line_highlighter';
-(function() {
- describe('LineHighlighter', function() {
- var clickLine;
- preloadFixtures('static/line_highlighter.html.raw');
- clickLine = function(number, eventData = {}) {
- if ($.isEmptyObject(eventData)) {
- return $("#L" + number).click();
- } else {
- const e = $.Event('click', eventData);
- return $("#L" + number).trigger(e);
+describe('LineHighlighter', function() {
+ var clickLine;
+ preloadFixtures('static/line_highlighter.html.raw');
+ clickLine = function(number, eventData = {}) {
+ if ($.isEmptyObject(eventData)) {
+ return $('#L' + number).click();
+ } else {
+ const e = $.Event('click', eventData);
+ return $('#L' + number).trigger(e);
+ }
+ };
+ beforeEach(function() {
+ loadFixtures('static/line_highlighter.html.raw');
+ this['class'] = new LineHighlighter();
+ this.css = this['class'].highlightLineClass;
+ return (this.spies = {
+ __setLocationHash__: spyOn(this['class'], '__setLocationHash__').and.callFake(function() {}),
+ });
+ });
+
+ describe('behavior', function() {
+ it('highlights one line given in the URL hash', function() {
+ new LineHighlighter({ hash: '#L13' });
+
+ expect($('#LC13')).toHaveClass(this.css);
+ });
+
+ it('highlights one line given in the URL hash with given CSS class name', function() {
+ const hiliter = new LineHighlighter({ hash: '#L13', highlightLineClass: 'hilite' });
+
+ expect(hiliter.highlightLineClass).toBe('hilite');
+ expect($('#LC13')).toHaveClass('hilite');
+ expect($('#LC13')).not.toHaveClass('hll');
+ });
+
+ it('highlights a range of lines given in the URL hash', function() {
+ var line;
+ new LineHighlighter({ hash: '#L5-25' });
+
+ expect($('.' + this.css).length).toBe(21);
+ for (line = 5; line <= 25; line += 1) {
+ expect($('#LC' + line)).toHaveClass(this.css);
}
- };
- beforeEach(function() {
- loadFixtures('static/line_highlighter.html.raw');
- this["class"] = new LineHighlighter();
- this.css = this["class"].highlightLineClass;
- return this.spies = {
- __setLocationHash__: spyOn(this["class"], '__setLocationHash__').and.callFake(function() {})
+ });
+
+ it('scrolls to the first highlighted line on initial load', function() {
+ var spy;
+ spy = spyOn($, 'scrollTo');
+ new LineHighlighter({ hash: '#L5-25' });
+
+ expect(spy).toHaveBeenCalledWith('#L5', jasmine.anything());
+ });
+
+ it('discards click events', function() {
+ var spy;
+ spy = spyOnEvent('a[data-line-number]', 'click');
+ clickLine(13);
+
+ expect(spy).toHaveBeenPrevented();
+ });
+
+ it('handles garbage input from the hash', function() {
+ var func;
+ func = function() {
+ return new LineHighlighter({ fileHolderSelector: '#blob-content-holder' });
};
+
+ expect(func).not.toThrow();
});
- describe('behavior', function() {
- it('highlights one line given in the URL hash', function() {
- new LineHighlighter({ hash: '#L13' });
- return expect($('#LC13')).toHaveClass(this.css);
- });
- it('highlights one line given in the URL hash with given CSS class name', function() {
- const hiliter = new LineHighlighter({ hash: '#L13', highlightLineClass: 'hilite' });
- expect(hiliter.highlightLineClass).toBe('hilite');
- expect($('#LC13')).toHaveClass('hilite');
- expect($('#LC13')).not.toHaveClass('hll');
- });
- it('highlights a range of lines given in the URL hash', function() {
- var line, results;
- new LineHighlighter({ hash: '#L5-25' });
- expect($("." + this.css).length).toBe(21);
- results = [];
- for (line = 5; line <= 25; line += 1) {
- results.push(expect($("#LC" + line)).toHaveClass(this.css));
- }
- return results;
+ });
+
+ describe('clickHandler', function() {
+ it('handles clicking on a child icon element', function() {
+ var spy;
+ spy = spyOn(this['class'], 'setHash').and.callThrough();
+ $('#L13 i')
+ .mousedown()
+ .click();
+
+ expect(spy).toHaveBeenCalledWith(13);
+ expect($('#LC13')).toHaveClass(this.css);
+ });
+
+ describe('without shiftKey', function() {
+ it('highlights one line when clicked', function() {
+ clickLine(13);
+
+ expect($('#LC13')).toHaveClass(this.css);
});
- it('scrolls to the first highlighted line on initial load', function() {
- var spy;
- spy = spyOn($, 'scrollTo');
- new LineHighlighter({ hash: '#L5-25' });
- return expect(spy).toHaveBeenCalledWith('#L5', jasmine.anything());
+
+ it('unhighlights previously highlighted lines', function() {
+ clickLine(13);
+ clickLine(20);
+
+ expect($('#LC13')).not.toHaveClass(this.css);
+ expect($('#LC20')).toHaveClass(this.css);
});
- it('discards click events', function() {
+
+ it('sets the hash', function() {
var spy;
- spy = spyOnEvent('a[data-line-number]', 'click');
+ spy = spyOn(this['class'], 'setHash').and.callThrough();
clickLine(13);
- return expect(spy).toHaveBeenPrevented();
- });
- it('handles garbage input from the hash', function() {
- var func;
- func = function() {
- return new LineHighlighter({ fileHolderSelector: '#blob-content-holder' });
- };
- return expect(func).not.toThrow();
+
+ expect(spy).toHaveBeenCalledWith(13);
});
});
- describe('clickHandler', function() {
- it('handles clicking on a child icon element', function() {
+
+ describe('with shiftKey', function() {
+ it('sets the hash', function() {
var spy;
- spy = spyOn(this["class"], 'setHash').and.callThrough();
- $('#L13 i').mousedown().click();
+ spy = spyOn(this['class'], 'setHash').and.callThrough();
+ clickLine(13);
+ clickLine(20, {
+ shiftKey: true,
+ });
+
expect(spy).toHaveBeenCalledWith(13);
- return expect($('#LC13')).toHaveClass(this.css);
+ expect(spy).toHaveBeenCalledWith(13, 20);
});
- describe('without shiftKey', function() {
- it('highlights one line when clicked', function() {
- clickLine(13);
- return expect($('#LC13')).toHaveClass(this.css);
- });
- it('unhighlights previously highlighted lines', function() {
- clickLine(13);
- clickLine(20);
- expect($('#LC13')).not.toHaveClass(this.css);
- return expect($('#LC20')).toHaveClass(this.css);
- });
- return it('sets the hash', function() {
- var spy;
- spy = spyOn(this["class"], 'setHash').and.callThrough();
- clickLine(13);
- return expect(spy).toHaveBeenCalledWith(13);
+
+ describe('without existing highlight', function() {
+ it('highlights the clicked line', function() {
+ clickLine(13, {
+ shiftKey: true,
+ });
+
+ expect($('#LC13')).toHaveClass(this.css);
+ expect($('.' + this.css).length).toBe(1);
});
- });
- return describe('with shiftKey', function() {
+
it('sets the hash', function() {
var spy;
- spy = spyOn(this["class"], 'setHash').and.callThrough();
- clickLine(13);
- clickLine(20, {
- shiftKey: true
+ spy = spyOn(this['class'], 'setHash');
+ clickLine(13, {
+ shiftKey: true,
});
+
expect(spy).toHaveBeenCalledWith(13);
- return expect(spy).toHaveBeenCalledWith(13, 20);
});
- describe('without existing highlight', function() {
- it('highlights the clicked line', function() {
- clickLine(13, {
- shiftKey: true
- });
- expect($('#LC13')).toHaveClass(this.css);
- return expect($("." + this.css).length).toBe(1);
+ });
+
+ describe('with existing single-line highlight', function() {
+ it('uses existing line as last line when target is lesser', function() {
+ var line;
+ clickLine(20);
+ clickLine(15, {
+ shiftKey: true,
});
- return it('sets the hash', function() {
- var spy;
- spy = spyOn(this["class"], 'setHash');
- clickLine(13, {
- shiftKey: true
- });
- return expect(spy).toHaveBeenCalledWith(13);
+
+ expect($('.' + this.css).length).toBe(6);
+ for (line = 15; line <= 20; line += 1) {
+ expect($('#LC' + line)).toHaveClass(this.css);
+ }
+ });
+
+ it('uses existing line as first line when target is greater', function() {
+ var line;
+ clickLine(5);
+ clickLine(10, {
+ shiftKey: true,
});
+
+ expect($('.' + this.css).length).toBe(6);
+ for (line = 5; line <= 10; line += 1) {
+ expect($('#LC' + line)).toHaveClass(this.css);
+ }
});
- describe('with existing single-line highlight', function() {
- it('uses existing line as last line when target is lesser', function() {
- var line, results;
- clickLine(20);
- clickLine(15, {
- shiftKey: true
- });
- expect($("." + this.css).length).toBe(6);
- results = [];
- for (line = 15; line <= 20; line += 1) {
- results.push(expect($("#LC" + line)).toHaveClass(this.css));
- }
- return results;
+ });
+
+ describe('with existing multi-line highlight', function() {
+ beforeEach(function() {
+ clickLine(10, {
+ shiftKey: true,
});
- return it('uses existing line as first line when target is greater', function() {
- var line, results;
- clickLine(5);
- clickLine(10, {
- shiftKey: true
- });
- expect($("." + this.css).length).toBe(6);
- results = [];
- for (line = 5; line <= 10; line += 1) {
- results.push(expect($("#LC" + line)).toHaveClass(this.css));
- }
- return results;
+ clickLine(13, {
+ shiftKey: true,
});
});
- return describe('with existing multi-line highlight', function() {
- beforeEach(function() {
- clickLine(10, {
- shiftKey: true
- });
- return clickLine(13, {
- shiftKey: true
- });
- });
- it('uses target as first line when it is less than existing first line', function() {
- var line, results;
- clickLine(5, {
- shiftKey: true
- });
- expect($("." + this.css).length).toBe(6);
- results = [];
- for (line = 5; line <= 10; line += 1) {
- results.push(expect($("#LC" + line)).toHaveClass(this.css));
- }
- return results;
+
+ it('uses target as first line when it is less than existing first line', function() {
+ var line;
+ clickLine(5, {
+ shiftKey: true,
});
- return it('uses target as last line when it is greater than existing first line', function() {
- var line, results;
- clickLine(15, {
- shiftKey: true
- });
- expect($("." + this.css).length).toBe(6);
- results = [];
- for (line = 10; line <= 15; line += 1) {
- results.push(expect($("#LC" + line)).toHaveClass(this.css));
- }
- return results;
+
+ expect($('.' + this.css).length).toBe(6);
+ for (line = 5; line <= 10; line += 1) {
+ expect($('#LC' + line)).toHaveClass(this.css);
+ }
+ });
+
+ it('uses target as last line when it is greater than existing first line', function() {
+ var line;
+ clickLine(15, {
+ shiftKey: true,
});
+
+ expect($('.' + this.css).length).toBe(6);
+ for (line = 10; line <= 15; line += 1) {
+ expect($('#LC' + line)).toHaveClass(this.css);
+ }
});
});
});
- describe('hashToRange', function() {
- beforeEach(function() {
- return this.subject = this["class"].hashToRange;
- });
- it('extracts a single line number from the hash', function() {
- return expect(this.subject('#L5')).toEqual([5, null]);
- });
- it('extracts a range of line numbers from the hash', function() {
- return expect(this.subject('#L5-15')).toEqual([5, 15]);
- });
- return it('returns [null, null] when the hash is not a line number', function() {
- return expect(this.subject('#foo')).toEqual([null, null]);
- });
+ });
+
+ describe('hashToRange', function() {
+ beforeEach(function() {
+ this.subject = this['class'].hashToRange;
});
- describe('highlightLine', function() {
- beforeEach(function() {
- return this.subject = this["class"].highlightLine;
- });
- it('highlights the specified line', function() {
- this.subject(13);
- return expect($('#LC13')).toHaveClass(this.css);
- });
- return it('accepts a String-based number', function() {
- this.subject('13');
- return expect($('#LC13')).toHaveClass(this.css);
- });
+
+ it('extracts a single line number from the hash', function() {
+ expect(this.subject('#L5')).toEqual([5, null]);
});
- return describe('setHash', function() {
- beforeEach(function() {
- return this.subject = this["class"].setHash;
- });
- it('sets the location hash for a single line', function() {
- this.subject(5);
- return expect(this.spies.__setLocationHash__).toHaveBeenCalledWith('#L5');
- });
- return it('sets the location hash for a range', function() {
- this.subject(5, 15);
- return expect(this.spies.__setLocationHash__).toHaveBeenCalledWith('#L5-15');
- });
+
+ it('extracts a range of line numbers from the hash', function() {
+ expect(this.subject('#L5-15')).toEqual([5, 15]);
+ });
+
+ it('returns [null, null] when the hash is not a line number', function() {
+ expect(this.subject('#foo')).toEqual([null, null]);
+ });
+ });
+
+ describe('highlightLine', function() {
+ beforeEach(function() {
+ this.subject = this['class'].highlightLine;
+ });
+
+ it('highlights the specified line', function() {
+ this.subject(13);
+
+ expect($('#LC13')).toHaveClass(this.css);
+ });
+
+ it('accepts a String-based number', function() {
+ this.subject('13');
+
+ expect($('#LC13')).toHaveClass(this.css);
+ });
+ });
+
+ describe('setHash', function() {
+ beforeEach(function() {
+ this.subject = this['class'].setHash;
+ });
+
+ it('sets the location hash for a single line', function() {
+ this.subject(5);
+
+ expect(this.spies.__setLocationHash__).toHaveBeenCalledWith('#L5');
+ });
+
+ it('sets the location hash for a range', function() {
+ this.subject(5, 15);
+
+ expect(this.spies.__setLocationHash__).toHaveBeenCalledWith('#L5-15');
});
});
-}).call(window);
+});
diff --git a/spec/javascripts/locale/ensure_single_line_spec.js b/spec/javascripts/locale/ensure_single_line_spec.js
index bbefa8f40f3..20b04cab9c8 100644
--- a/spec/javascripts/locale/ensure_single_line_spec.js
+++ b/spec/javascripts/locale/ensure_single_line_spec.js
@@ -4,6 +4,7 @@ describe('locale', () => {
describe('ensureSingleLine', () => {
it('should remove newlines at the start of the string', () => {
const result = 'Test';
+
expect(ensureSingleLine(`\n${result}`)).toBe(result);
expect(ensureSingleLine(`\t\n\t${result}`)).toBe(result);
expect(ensureSingleLine(`\r\n${result}`)).toBe(result);
@@ -14,6 +15,7 @@ describe('locale', () => {
it('should remove newlines at the end of the string', () => {
const result = 'Test';
+
expect(ensureSingleLine(`${result}\n`)).toBe(result);
expect(ensureSingleLine(`${result}\t\n\t`)).toBe(result);
expect(ensureSingleLine(`${result}\r\n`)).toBe(result);
@@ -24,6 +26,7 @@ describe('locale', () => {
it('should replace newlines in the middle of the string with a single space', () => {
const result = 'Test';
+
expect(ensureSingleLine(`${result}\n${result}`)).toBe(`${result} ${result}`);
expect(ensureSingleLine(`${result}\t\n\t${result}`)).toBe(`${result} ${result}`);
expect(ensureSingleLine(`${result}\r\n${result}`)).toBe(`${result} ${result}`);
diff --git a/spec/javascripts/merge_request_spec.js b/spec/javascripts/merge_request_spec.js
index 7502f1fa2e1..1cb49b49ca7 100644
--- a/spec/javascripts/merge_request_spec.js
+++ b/spec/javascripts/merge_request_spec.js
@@ -7,123 +7,122 @@ import MergeRequest from '~/merge_request';
import CloseReopenReportToggle from '~/close_reopen_report_toggle';
import IssuablesHelper from '~/helpers/issuables_helper';
-(function() {
- describe('MergeRequest', function() {
- describe('task lists', function() {
- let mock;
+describe('MergeRequest', function() {
+ describe('task lists', function() {
+ let mock;
- preloadFixtures('merge_requests/merge_request_with_task_list.html.raw');
- beforeEach(function() {
- loadFixtures('merge_requests/merge_request_with_task_list.html.raw');
+ preloadFixtures('merge_requests/merge_request_with_task_list.html.raw');
+ beforeEach(function() {
+ loadFixtures('merge_requests/merge_request_with_task_list.html.raw');
- spyOn(axios, 'patch').and.callThrough();
- mock = new MockAdapter(axios);
+ spyOn(axios, 'patch').and.callThrough();
+ mock = new MockAdapter(axios);
- mock
- .onPatch(`${gl.TEST_HOST}/frontend-fixtures/merge-requests-project/merge_requests/1.json`)
- .reply(200, {});
+ mock
+ .onPatch(`${gl.TEST_HOST}/frontend-fixtures/merge-requests-project/merge_requests/1.json`)
+ .reply(200, {});
- return (this.merge = new MergeRequest());
- });
+ return (this.merge = new MergeRequest());
+ });
- afterEach(() => {
- mock.restore();
- });
+ afterEach(() => {
+ mock.restore();
+ });
- it('modifies the Markdown field', function() {
- spyOn($, 'ajax').and.stub();
- const changeEvent = document.createEvent('HTMLEvents');
- changeEvent.initEvent('change', true, true);
- $('input[type=checkbox]')
- .attr('checked', true)[0]
- .dispatchEvent(changeEvent);
- return expect($('.js-task-list-field').val()).toBe('- [x] Task List Item');
- });
+ it('modifies the Markdown field', function() {
+ spyOn($, 'ajax').and.stub();
+ const changeEvent = document.createEvent('HTMLEvents');
+ changeEvent.initEvent('change', true, true);
+ $('input[type=checkbox]')
+ .attr('checked', true)[0]
+ .dispatchEvent(changeEvent);
- it('submits an ajax request on tasklist:changed', done => {
- $('.js-task-list-field').trigger('tasklist:changed');
-
- setTimeout(() => {
- expect(axios.patch).toHaveBeenCalledWith(
- `${gl.TEST_HOST}/frontend-fixtures/merge-requests-project/merge_requests/1.json`,
- {
- merge_request: { description: '- [ ] Task List Item' },
- },
- );
- done();
- });
- });
+ expect($('.js-task-list-field').val()).toBe('- [x] Task List Item');
});
- describe('class constructor', () => {
- beforeEach(() => {
- spyOn($, 'ajax').and.stub();
+ it('submits an ajax request on tasklist:changed', done => {
+ $('.js-task-list-field').trigger('tasklist:changed');
+
+ setTimeout(() => {
+ expect(axios.patch).toHaveBeenCalledWith(
+ `${gl.TEST_HOST}/frontend-fixtures/merge-requests-project/merge_requests/1.json`,
+ {
+ merge_request: { description: '- [ ] Task List Item' },
+ },
+ );
+ done();
});
+ });
+ });
- it('calls .initCloseReopenReport', () => {
- spyOn(IssuablesHelper, 'initCloseReopenReport');
+ describe('class constructor', () => {
+ beforeEach(() => {
+ spyOn($, 'ajax').and.stub();
+ });
- new MergeRequest(); // eslint-disable-line no-new
+ it('calls .initCloseReopenReport', () => {
+ spyOn(IssuablesHelper, 'initCloseReopenReport');
- expect(IssuablesHelper.initCloseReopenReport).toHaveBeenCalled();
- });
+ new MergeRequest(); // eslint-disable-line no-new
- it('calls .initDroplab', () => {
- const container = jasmine.createSpyObj('container', ['querySelector']);
- const dropdownTrigger = {};
- const dropdownList = {};
- const button = {};
+ expect(IssuablesHelper.initCloseReopenReport).toHaveBeenCalled();
+ });
+
+ it('calls .initDroplab', () => {
+ const container = jasmine.createSpyObj('container', ['querySelector']);
+ const dropdownTrigger = {};
+ const dropdownList = {};
+ const button = {};
+
+ spyOn(CloseReopenReportToggle.prototype, 'initDroplab');
+ spyOn(document, 'querySelector').and.returnValue(container);
+ container.querySelector.and.returnValues(dropdownTrigger, dropdownList, button);
- spyOn(CloseReopenReportToggle.prototype, 'initDroplab');
- spyOn(document, 'querySelector').and.returnValue(container);
- container.querySelector.and.returnValues(dropdownTrigger, dropdownList, button);
+ new MergeRequest(); // eslint-disable-line no-new
+
+ expect(document.querySelector).toHaveBeenCalledWith('.js-issuable-close-dropdown');
+ expect(container.querySelector).toHaveBeenCalledWith('.js-issuable-close-toggle');
+ expect(container.querySelector).toHaveBeenCalledWith('.js-issuable-close-menu');
+ expect(container.querySelector).toHaveBeenCalledWith('.js-issuable-close-button');
+ expect(CloseReopenReportToggle.prototype.initDroplab).toHaveBeenCalled();
+ });
+ });
+ describe('hideCloseButton', () => {
+ describe('merge request of another user', () => {
+ beforeEach(() => {
+ loadFixtures('merge_requests/merge_request_with_task_list.html.raw');
+ this.el = document.querySelector('.js-issuable-actions');
new MergeRequest(); // eslint-disable-line no-new
+ MergeRequest.hideCloseButton();
+ });
- expect(document.querySelector).toHaveBeenCalledWith('.js-issuable-close-dropdown');
- expect(container.querySelector).toHaveBeenCalledWith('.js-issuable-close-toggle');
- expect(container.querySelector).toHaveBeenCalledWith('.js-issuable-close-menu');
- expect(container.querySelector).toHaveBeenCalledWith('.js-issuable-close-button');
- expect(CloseReopenReportToggle.prototype.initDroplab).toHaveBeenCalled();
+ it('hides the dropdown close item and selects the next item', () => {
+ const closeItem = this.el.querySelector('li.close-item');
+ const smallCloseItem = this.el.querySelector('.js-close-item');
+ const reportItem = this.el.querySelector('li.report-item');
+
+ expect(closeItem).toHaveClass('hidden');
+ expect(smallCloseItem).toHaveClass('hidden');
+ expect(reportItem).toHaveClass('droplab-item-selected');
+ expect(reportItem).not.toHaveClass('hidden');
});
});
- describe('hideCloseButton', () => {
- describe('merge request of another user', () => {
- beforeEach(() => {
- loadFixtures('merge_requests/merge_request_with_task_list.html.raw');
- this.el = document.querySelector('.js-issuable-actions');
- new MergeRequest(); // eslint-disable-line no-new
- MergeRequest.hideCloseButton();
- });
-
- it('hides the dropdown close item and selects the next item', () => {
- const closeItem = this.el.querySelector('li.close-item');
- const smallCloseItem = this.el.querySelector('.js-close-item');
- const reportItem = this.el.querySelector('li.report-item');
-
- expect(closeItem).toHaveClass('hidden');
- expect(smallCloseItem).toHaveClass('hidden');
- expect(reportItem).toHaveClass('droplab-item-selected');
- expect(reportItem).not.toHaveClass('hidden');
- });
+ describe('merge request of current_user', () => {
+ beforeEach(() => {
+ loadFixtures('merge_requests/merge_request_of_current_user.html.raw');
+ this.el = document.querySelector('.js-issuable-actions');
+ MergeRequest.hideCloseButton();
});
- describe('merge request of current_user', () => {
- beforeEach(() => {
- loadFixtures('merge_requests/merge_request_of_current_user.html.raw');
- this.el = document.querySelector('.js-issuable-actions');
- MergeRequest.hideCloseButton();
- });
-
- it('hides the close button', () => {
- const closeButton = this.el.querySelector('.btn-close');
- const smallCloseItem = this.el.querySelector('.js-close-item');
+ it('hides the close button', () => {
+ const closeButton = this.el.querySelector('.btn-close');
+ const smallCloseItem = this.el.querySelector('.js-close-item');
- expect(closeButton).toHaveClass('hidden');
- expect(smallCloseItem).toHaveClass('hidden');
- });
+ expect(closeButton).toHaveClass('hidden');
+ expect(smallCloseItem).toHaveClass('hidden');
});
});
});
-}.call(window));
+});
diff --git a/spec/javascripts/merge_request_tabs_spec.js b/spec/javascripts/merge_request_tabs_spec.js
index 7251ce19a90..c8df05eccf5 100644
--- a/spec/javascripts/merge_request_tabs_spec.js
+++ b/spec/javascripts/merge_request_tabs_spec.js
@@ -224,6 +224,14 @@ describe('MergeRequestTabs', function() {
expect($('.content-wrapper')).not.toContainElement('.container-limited');
});
+ it('does not add container-limited when fluid layout is prefered', function() {
+ $('.content-wrapper .container-fluid').removeClass('container-limited');
+
+ this.class.expandViewContainer(false);
+
+ expect($('.content-wrapper')).not.toContainElement('.container-limited');
+ });
+
it('does remove container-limited from breadcrumbs', function() {
$('.container-limited').addClass('breadcrumbs');
this.class.expandViewContainer();
@@ -231,4 +239,38 @@ describe('MergeRequestTabs', function() {
expect($('.content-wrapper')).toContainElement('.container-limited');
});
});
+
+ describe('tabShown', function() {
+ const mainContent = document.createElement('div');
+ const tabContent = document.createElement('div');
+
+ beforeEach(function() {
+ spyOn(mainContent, 'getBoundingClientRect').and.returnValue({ top: 10 });
+ spyOn(tabContent, 'getBoundingClientRect').and.returnValue({ top: 100 });
+ spyOn(document, 'querySelector').and.callFake(function(selector) {
+ return selector === '.content-wrapper' ? mainContent : tabContent;
+ });
+ this.class.currentAction = 'commits';
+ });
+
+ it('calls window scrollTo with options if document has scrollBehavior', function() {
+ document.documentElement.style.scrollBehavior = '';
+
+ spyOn(window, 'scrollTo');
+
+ this.class.tabShown('commits', 'foobar');
+
+ expect(window.scrollTo.calls.first().args[0]).toEqual({ top: 39, behavior: 'smooth' });
+ });
+
+ it('calls window scrollTo with two args if document does not have scrollBehavior', function() {
+ spyOnProperty(document.documentElement, 'style', 'get').and.returnValue({});
+
+ spyOn(window, 'scrollTo');
+
+ this.class.tabShown('commits', 'foobar');
+
+ expect(window.scrollTo.calls.first().args).toEqual([0, 39]);
+ });
+ });
});
diff --git a/spec/javascripts/mini_pipeline_graph_dropdown_spec.js b/spec/javascripts/mini_pipeline_graph_dropdown_spec.js
index 1879424c629..092ca9e1dab 100644
--- a/spec/javascripts/mini_pipeline_graph_dropdown_spec.js
+++ b/spec/javascripts/mini_pipeline_graph_dropdown_spec.js
@@ -39,10 +39,9 @@ describe('Mini Pipeline Graph Dropdown', () => {
});
it('should call getBuildsList', () => {
- const getBuildsListSpy = spyOn(
- MiniPipelineGraph.prototype,
- 'getBuildsList',
- ).and.callFake(function () {});
+ const getBuildsListSpy = spyOn(MiniPipelineGraph.prototype, 'getBuildsList').and.callFake(
+ function() {},
+ );
new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents();
@@ -61,10 +60,11 @@ describe('Mini Pipeline Graph Dropdown', () => {
new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents();
document.querySelector('.js-builds-dropdown-button').click();
+
expect(ajaxSpy.calls.allArgs()[0][0]).toEqual('foobar');
});
- it('should not close when user uses cmd/ctrl + click', (done) => {
+ it('should not close when user uses cmd/ctrl + click', done => {
mock.onGet('foobar').reply(200, {
html: `<li>
<a class="mini-pipeline-graph-dropdown-item" href="#">
@@ -90,7 +90,7 @@ describe('Mini Pipeline Graph Dropdown', () => {
.catch(done.fail);
});
- it('should close the dropdown when request returns an error', (done) => {
+ it('should close the dropdown when request returns an error', done => {
mock.onGet('foobar').networkError();
new MiniPipelineGraph({ container: '.js-builds-dropdown-tests' }).bindEvents();
diff --git a/spec/javascripts/monitoring/dashboard_spec.js b/spec/javascripts/monitoring/dashboard_spec.js
index 997163c7602..565b87de248 100644
--- a/spec/javascripts/monitoring/dashboard_spec.js
+++ b/spec/javascripts/monitoring/dashboard_spec.js
@@ -4,28 +4,33 @@ import Dashboard from '~/monitoring/components/dashboard.vue';
import axios from '~/lib/utils/axios_utils';
import { metricsGroupsAPIResponse, mockApiEndpoint, environmentData } from './mock_data';
+const propsData = {
+ hasMetrics: false,
+ documentationPath: '/path/to/docs',
+ settingsPath: '/path/to/settings',
+ clustersPath: '/path/to/clusters',
+ tagsPath: '/path/to/tags',
+ projectPath: '/path/to/project',
+ metricsEndpoint: mockApiEndpoint,
+ deploymentEndpoint: null,
+ emptyGettingStartedSvgPath: '/path/to/getting-started.svg',
+ emptyLoadingSvgPath: '/path/to/loading.svg',
+ emptyNoDataSvgPath: '/path/to/no-data.svg',
+ emptyUnableToConnectSvgPath: '/path/to/unable-to-connect.svg',
+ environmentsEndpoint: '/root/hello-prometheus/environments/35',
+ currentEnvironmentName: 'production',
+};
+
+export default propsData;
+
describe('Dashboard', () => {
let DashboardComponent;
- const propsData = {
- hasMetrics: false,
- documentationPath: '/path/to/docs',
- settingsPath: '/path/to/settings',
- clustersPath: '/path/to/clusters',
- tagsPath: '/path/to/tags',
- projectPath: '/path/to/project',
- metricsEndpoint: mockApiEndpoint,
- deploymentEndpoint: null,
- emptyGettingStartedSvgPath: '/path/to/getting-started.svg',
- emptyLoadingSvgPath: '/path/to/loading.svg',
- emptyNoDataSvgPath: '/path/to/no-data.svg',
- emptyUnableToConnectSvgPath: '/path/to/unable-to-connect.svg',
- environmentsEndpoint: '/root/hello-prometheus/environments/35',
- currentEnvironmentName: 'production',
- };
-
beforeEach(() => {
- setFixtures('<div class="prometheus-graphs"></div>');
+ setFixtures(`
+ <div class="prometheus-graphs"></div>
+ <div class="nav-sidebar"></div>
+ `);
DashboardComponent = Vue.extend(Dashboard);
});
@@ -102,11 +107,28 @@ describe('Dashboard', () => {
setTimeout(() => {
const dropdownMenuEnvironments = component.$el.querySelectorAll('.dropdown-menu ul li a');
+
expect(dropdownMenuEnvironments.length).toEqual(component.store.environmentsData.length);
done();
});
});
+ it('hides the dropdown list when there is no environments', done => {
+ const component = new DashboardComponent({
+ el: document.querySelector('.prometheus-graphs'),
+ propsData: { ...propsData, hasMetrics: true, showPanels: false },
+ });
+
+ component.store.storeEnvironmentsData([]);
+
+ setTimeout(() => {
+ const dropdownMenuEnvironments = component.$el.querySelectorAll('.dropdown-menu ul');
+
+ expect(dropdownMenuEnvironments.length).toEqual(0);
+ done();
+ });
+ });
+
it('renders the dropdown with a single is-active element', done => {
const component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
@@ -119,6 +141,7 @@ describe('Dashboard', () => {
const dropdownIsActiveElement = component.$el.querySelectorAll(
'.dropdown-menu ul li a.is-active',
);
+
expect(dropdownIsActiveElement.length).toEqual(1);
expect(dropdownIsActiveElement[0].textContent.trim()).toEqual(
component.currentEnvironmentName,
@@ -127,4 +150,41 @@ describe('Dashboard', () => {
});
});
});
+
+ describe('when the window resizes', () => {
+ let mock;
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
+ jasmine.clock().install();
+ });
+
+ afterEach(() => {
+ mock.restore();
+ jasmine.clock().uninstall();
+ });
+
+ it('rerenders the dashboard when the sidebar is resized', done => {
+ const component = new DashboardComponent({
+ el: document.querySelector('.prometheus-graphs'),
+ propsData: { ...propsData, hasMetrics: true, showPanels: false },
+ });
+
+ expect(component.forceRedraw).toEqual(0);
+
+ const navSidebarEl = document.querySelector('.nav-sidebar');
+ navSidebarEl.classList.add('nav-sidebar-collapsed');
+
+ Vue.nextTick()
+ .then(() => {
+ jasmine.clock().tick(1000);
+ return Vue.nextTick();
+ })
+ .then(() => {
+ expect(component.forceRedraw).toEqual(component.elWidth);
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
});
diff --git a/spec/javascripts/monitoring/dashboard_state_spec.js b/spec/javascripts/monitoring/dashboard_state_spec.js
index b4c5f4baa78..6b2be83aa8c 100644
--- a/spec/javascripts/monitoring/dashboard_state_spec.js
+++ b/spec/javascripts/monitoring/dashboard_state_spec.js
@@ -56,9 +56,17 @@ describe('EmptyState', () => {
});
expect(component.$el.querySelector('svg')).toBeDefined();
- expect(getTextFromNode(component, '.state-title')).toEqual(component.states.gettingStarted.title);
- expect(getTextFromNode(component, '.state-description')).toEqual(component.states.gettingStarted.description);
- expect(getTextFromNode(component, '.btn-success')).toEqual(component.states.gettingStarted.buttonText);
+ expect(getTextFromNode(component, '.state-title')).toEqual(
+ component.states.gettingStarted.title,
+ );
+
+ expect(getTextFromNode(component, '.state-description')).toEqual(
+ component.states.gettingStarted.description,
+ );
+
+ expect(getTextFromNode(component, '.btn-success')).toEqual(
+ component.states.gettingStarted.buttonText,
+ );
});
it('should show the loading state', () => {
@@ -68,7 +76,10 @@ describe('EmptyState', () => {
expect(component.$el.querySelector('svg')).toBeDefined();
expect(getTextFromNode(component, '.state-title')).toEqual(component.states.loading.title);
- expect(getTextFromNode(component, '.state-description')).toEqual(component.states.loading.description);
+ expect(getTextFromNode(component, '.state-description')).toEqual(
+ component.states.loading.description,
+ );
+
expect(getTextFromNode(component, '.btn-success')).toEqual(component.states.loading.buttonText);
});
@@ -78,8 +89,13 @@ describe('EmptyState', () => {
});
expect(component.$el.querySelector('svg')).toBeDefined();
- expect(getTextFromNode(component, '.state-title')).toEqual(component.states.unableToConnect.title);
+ expect(getTextFromNode(component, '.state-title')).toEqual(
+ component.states.unableToConnect.title,
+ );
+
expect(component.$el.querySelector('.state-description a')).toBeDefined();
- expect(getTextFromNode(component, '.btn-success')).toEqual(component.states.unableToConnect.buttonText);
+ expect(getTextFromNode(component, '.btn-success')).toEqual(
+ component.states.unableToConnect.buttonText,
+ );
});
});
diff --git a/spec/javascripts/monitoring/graph/deployment_spec.js b/spec/javascripts/monitoring/graph/deployment_spec.js
index d07db871d69..7d39c4345d2 100644
--- a/spec/javascripts/monitoring/graph/deployment_spec.js
+++ b/spec/javascripts/monitoring/graph/deployment_spec.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import GraphDeployment from '~/monitoring/components/graph/deployment.vue';
import { deploymentData } from '../mock_data';
-const createComponent = (propsData) => {
+const createComponent = propsData => {
const Component = Vue.extend(GraphDeployment);
return new Component({
@@ -33,9 +33,7 @@ describe('MonitoringDeployment', () => {
graphHeightOffset: 120,
});
- expect(
- component.transformDeploymentGroup({ xPos: 16 }),
- ).toContain('translate(11, 20)');
+ expect(component.transformDeploymentGroup({ xPos: 16 })).toContain('translate(11, 20)');
});
describe('Computed props', () => {
diff --git a/spec/javascripts/monitoring/graph/flag_spec.js b/spec/javascripts/monitoring/graph/flag_spec.js
index a837b71db0b..038bfffd44f 100644
--- a/spec/javascripts/monitoring/graph/flag_spec.js
+++ b/spec/javascripts/monitoring/graph/flag_spec.js
@@ -2,7 +2,7 @@ import Vue from 'vue';
import GraphFlag from '~/monitoring/components/graph/flag.vue';
import { deploymentData } from '../mock_data';
-const createComponent = (propsData) => {
+const createComponent = propsData => {
const Component = Vue.extend(GraphFlag);
return new Component({
@@ -51,8 +51,7 @@ describe('GraphFlag', () => {
it('has a line at the currentXCoordinate', () => {
component = createComponent(defaultValuesComponent);
- expect(component.$el.style.left)
- .toEqual(`${70 + component.currentXCoordinate}px`);
+ expect(component.$el.style.left).toEqual(`${70 + component.currentXCoordinate}px`);
});
describe('Deployment flag', () => {
@@ -62,9 +61,7 @@ describe('GraphFlag', () => {
deploymentFlagData,
});
- expect(
- deploymentFlagComponent.$el.querySelector('.popover-title'),
- ).toContainText('Deployed');
+ expect(deploymentFlagComponent.$el.querySelector('.popover-title')).toContainText('Deployed');
});
it('contains the ref when a tag is available', () => {
@@ -78,13 +75,13 @@ describe('GraphFlag', () => {
},
});
- expect(
- deploymentFlagComponent.$el.querySelector('.deploy-meta-content'),
- ).toContainText('f5bcd1d9');
+ expect(deploymentFlagComponent.$el.querySelector('.deploy-meta-content')).toContainText(
+ 'f5bcd1d9',
+ );
- expect(
- deploymentFlagComponent.$el.querySelector('.deploy-meta-content'),
- ).toContainText('1.0');
+ expect(deploymentFlagComponent.$el.querySelector('.deploy-meta-content')).toContainText(
+ '1.0',
+ );
});
it('does not contain the ref when a tag is unavailable', () => {
@@ -98,13 +95,13 @@ describe('GraphFlag', () => {
},
});
- expect(
- deploymentFlagComponent.$el.querySelector('.deploy-meta-content'),
- ).toContainText('f5bcd1d9');
+ expect(deploymentFlagComponent.$el.querySelector('.deploy-meta-content')).toContainText(
+ 'f5bcd1d9',
+ );
- expect(
- deploymentFlagComponent.$el.querySelector('.deploy-meta-content'),
- ).not.toContainText('1.0');
+ expect(deploymentFlagComponent.$el.querySelector('.deploy-meta-content')).not.toContainText(
+ '1.0',
+ );
});
});
diff --git a/spec/javascripts/monitoring/graph/legend_spec.js b/spec/javascripts/monitoring/graph/legend_spec.js
index abcc51aa077..9209e77dcf4 100644
--- a/spec/javascripts/monitoring/graph/legend_spec.js
+++ b/spec/javascripts/monitoring/graph/legend_spec.js
@@ -8,7 +8,7 @@ const convertedMetrics = convertDatesMultipleSeries(singleRowMetricsMultipleSeri
const defaultValuesComponent = {};
-const timeSeries = createTimeSeries(convertedMetrics[0].queries, 500, 300, 120);
+const { timeSeries } = createTimeSeries(convertedMetrics[0].queries, 500, 300, 120);
defaultValuesComponent.timeSeries = timeSeries;
diff --git a/spec/javascripts/monitoring/graph/track_info_spec.js b/spec/javascripts/monitoring/graph/track_info_spec.js
index d3121d553f9..ce93ae28842 100644
--- a/spec/javascripts/monitoring/graph/track_info_spec.js
+++ b/spec/javascripts/monitoring/graph/track_info_spec.js
@@ -5,7 +5,7 @@ import createTimeSeries from '~/monitoring/utils/multiple_time_series';
import { singleRowMetricsMultipleSeries, convertDatesMultipleSeries } from '../mock_data';
const convertedMetrics = convertDatesMultipleSeries(singleRowMetricsMultipleSeries);
-const timeSeries = createTimeSeries(convertedMetrics[0].queries, 500, 300, 120);
+const { timeSeries } = createTimeSeries(convertedMetrics[0].queries, 500, 300, 120);
describe('TrackInfo component', () => {
let vm;
diff --git a/spec/javascripts/monitoring/graph/track_line_spec.js b/spec/javascripts/monitoring/graph/track_line_spec.js
index 27602a861eb..2a4f89ddf6e 100644
--- a/spec/javascripts/monitoring/graph/track_line_spec.js
+++ b/spec/javascripts/monitoring/graph/track_line_spec.js
@@ -5,7 +5,7 @@ import createTimeSeries from '~/monitoring/utils/multiple_time_series';
import { singleRowMetricsMultipleSeries, convertDatesMultipleSeries } from '../mock_data';
const convertedMetrics = convertDatesMultipleSeries(singleRowMetricsMultipleSeries);
-const timeSeries = createTimeSeries(convertedMetrics[0].queries, 500, 300, 120);
+const { timeSeries } = createTimeSeries(convertedMetrics[0].queries, 500, 300, 120);
describe('TrackLine component', () => {
let vm;
diff --git a/spec/javascripts/monitoring/graph_path_spec.js b/spec/javascripts/monitoring/graph_path_spec.js
index 2515e2ad897..fd167b83d51 100644
--- a/spec/javascripts/monitoring/graph_path_spec.js
+++ b/spec/javascripts/monitoring/graph_path_spec.js
@@ -3,7 +3,7 @@ import GraphPath from '~/monitoring/components/graph/path.vue';
import createTimeSeries from '~/monitoring/utils/multiple_time_series';
import { singleRowMetricsMultipleSeries, convertDatesMultipleSeries } from './mock_data';
-const createComponent = (propsData) => {
+const createComponent = propsData => {
const Component = Vue.extend(GraphPath);
return new Component({
@@ -13,7 +13,7 @@ const createComponent = (propsData) => {
const convertedMetrics = convertDatesMultipleSeries(singleRowMetricsMultipleSeries);
-const timeSeries = createTimeSeries(convertedMetrics[0].queries, 428, 272, 120);
+const { timeSeries } = createTimeSeries(convertedMetrics[0].queries, 428, 272, 120);
const firstTimeSeries = timeSeries[0];
describe('Monitoring Paths', () => {
@@ -45,9 +45,11 @@ describe('Monitoring Paths', () => {
});
component.lineStyle = 'dashed';
+
expect(component.strokeDashArray).toBe('3, 1');
component.lineStyle = 'dotted';
+
expect(component.strokeDashArray).toBe('1, 1');
});
});
diff --git a/spec/javascripts/monitoring/graph_spec.js b/spec/javascripts/monitoring/graph_spec.js
index 990619b4109..59d6d4f3a7f 100644
--- a/spec/javascripts/monitoring/graph_spec.js
+++ b/spec/javascripts/monitoring/graph_spec.js
@@ -1,11 +1,11 @@
import Vue from 'vue';
import Graph from '~/monitoring/components/graph.vue';
import MonitoringMixins from '~/monitoring/mixins/monitoring_mixins';
-import eventHub from '~/monitoring/event_hub';
import {
deploymentData,
convertDatesMultipleSeries,
singleRowMetricsMultipleSeries,
+ queryWithoutData,
} from './mock_data';
const tagsPath = 'http://test.host/frontend-fixtures/environments-project/tags';
@@ -50,6 +50,7 @@ describe('Graph', () => {
});
const transformedHeight = `${component.graphHeight - 100}`;
+
expect(component.axisTransform.indexOf(transformedHeight)).not.toEqual(-1);
});
@@ -63,29 +64,13 @@ describe('Graph', () => {
});
const viewBoxArray = component.outerViewBox.split(' ');
+
expect(typeof component.outerViewBox).toEqual('string');
expect(viewBoxArray[2]).toEqual(component.graphWidth.toString());
expect(viewBoxArray[3]).toEqual((component.graphHeight - 50).toString());
});
});
- it('sends an event to the eventhub when it has finished resizing', done => {
- const component = createComponent({
- graphData: convertedMetrics[1],
- updateAspectRatio: false,
- deploymentData,
- tagsPath,
- projectPath,
- });
- spyOn(eventHub, '$emit');
-
- component.updateAspectRatio = true;
- Vue.nextTick(() => {
- expect(eventHub.$emit).toHaveBeenCalled();
- done();
- });
- });
-
it('has a title for the y-axis and the chart legend that comes from the backend', () => {
const component = createComponent({
graphData: convertedMetrics[1],
@@ -117,6 +102,26 @@ describe('Graph', () => {
component.seriesUnderMouse = component.timeSeries;
component.positionFlag();
+
expect(component.currentData).toBe(component.timeSeries[0].values[10]);
});
+
+ describe('Without data to display', () => {
+ it('shows a "no data to display" empty state on a graph', done => {
+ const component = createComponent({
+ graphData: queryWithoutData,
+ deploymentData,
+ tagsPath,
+ projectPath,
+ });
+
+ Vue.nextTick(() => {
+ expect(
+ component.$el.querySelector('.js-no-data-to-display text').textContent.trim(),
+ ).toEqual('No data to display');
+
+ done();
+ });
+ });
+ });
});
diff --git a/spec/javascripts/monitoring/mock_data.js b/spec/javascripts/monitoring/mock_data.js
index e4c98a3bcb5..18ad9843d22 100644
--- a/spec/javascripts/monitoring/mock_data.js
+++ b/spec/javascripts/monitoring/mock_data.js
@@ -8,12 +8,13 @@ export const metricsGroupsAPIResponse = {
priority: 1,
metrics: [
{
+ id: 5,
title: 'Memory usage',
weight: 1,
queries: [
{
query_range: 'avg(container_memory_usage_bytes{%{environment_filter}}) / 2^20',
- y_label: 'Memory',
+ label: 'Memory',
unit: 'MiB',
result: [
{
@@ -323,12 +324,15 @@ export const metricsGroupsAPIResponse = {
],
},
{
+ id: 6,
title: 'CPU usage',
weight: 1,
queries: [
{
query_range:
'avg(rate(container_cpu_usage_seconds_total{%{environment_filter}}[2m])) * 100',
+ label: 'Core Usage',
+ unit: 'Cores',
result: [
{
metric: {},
@@ -638,6 +642,39 @@ export const metricsGroupsAPIResponse = {
},
],
},
+ {
+ group: 'NGINX',
+ priority: 2,
+ metrics: [
+ {
+ id: 100,
+ title: 'Http Error Rate',
+ weight: 100,
+ queries: [
+ {
+ query_range:
+ 'sum(rate(nginx_upstream_responses_total{status_code="5xx", upstream=~"nginx-test-8691397-production-.*"}[2m])) / sum(rate(nginx_upstream_responses_total{upstream=~"nginx-test-8691397-production-.*"}[2m])) * 100',
+ label: '5xx errors',
+ unit: '%',
+ result: [
+ {
+ metric: {},
+ values: [
+ [1495700554.925, NaN],
+ [1495700614.925, NaN],
+ [1495700674.925, NaN],
+ [1495700734.925, NaN],
+ [1495700794.925, NaN],
+ [1495700854.925, NaN],
+ [1495700914.925, NaN],
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
],
last_update: '2017-05-25T13:18:34.949Z',
};
@@ -6525,6 +6562,21 @@ export const singleRowMetricsMultipleSeries = [
},
];
+export const queryWithoutData = {
+ title: 'HTTP Error rate',
+ weight: 10,
+ y_label: 'Http Error Rate',
+ queries: [
+ {
+ query_range:
+ 'sum(rate(nginx_upstream_responses_total{status_code="5xx", upstream=~"nginx-test-8691397-production-.*"}[2m])) / sum(rate(nginx_upstream_responses_total{upstream=~"nginx-test-8691397-production-.*"}[2m])) * 100',
+ label: '5xx errors',
+ unit: '%',
+ result: [],
+ },
+ ],
+};
+
export function convertDatesMultipleSeries(multipleSeries) {
const convertedMultiple = multipleSeries;
multipleSeries.forEach((column, index) => {
diff --git a/spec/javascripts/monitoring/monitoring_store_spec.js b/spec/javascripts/monitoring/monitoring_store_spec.js
index ccdf4eda563..d8a980c874d 100644
--- a/spec/javascripts/monitoring/monitoring_store_spec.js
+++ b/spec/javascripts/monitoring/monitoring_store_spec.js
@@ -1,29 +1,35 @@
import MonitoringStore from '~/monitoring/stores/monitoring_store';
import MonitoringMock, { deploymentData, environmentData } from './mock_data';
-describe('MonitoringStore', function () {
- this.store = new MonitoringStore();
- this.store.storeMetrics(MonitoringMock.data);
-
- it('contains one group that contains two queries sorted by priority', () => {
- expect(this.store.groups).toBeDefined();
- expect(this.store.groups.length).toEqual(1);
- expect(this.store.groups[0].metrics.length).toEqual(2);
+describe('MonitoringStore', () => {
+ const store = new MonitoringStore();
+ store.storeMetrics(MonitoringMock.data);
+
+ it('contains two groups that contains, one of which has two queries sorted by priority', () => {
+ expect(store.groups).toBeDefined();
+ expect(store.groups.length).toEqual(2);
+ expect(store.groups[0].metrics.length).toEqual(2);
});
it('gets the metrics count for every group', () => {
- expect(this.store.getMetricsCount()).toEqual(2);
+ expect(store.getMetricsCount()).toEqual(3);
});
it('contains deployment data', () => {
- this.store.storeDeploymentData(deploymentData);
- expect(this.store.deploymentData).toBeDefined();
- expect(this.store.deploymentData.length).toEqual(3);
- expect(typeof this.store.deploymentData[0]).toEqual('object');
+ store.storeDeploymentData(deploymentData);
+
+ expect(store.deploymentData).toBeDefined();
+ expect(store.deploymentData.length).toEqual(3);
+ expect(typeof store.deploymentData[0]).toEqual('object');
});
it('only stores environment data that contains deployments', () => {
- this.store.storeEnvironmentsData(environmentData);
- expect(this.store.environmentsData.length).toEqual(2);
+ store.storeEnvironmentsData(environmentData);
+
+ expect(store.environmentsData.length).toEqual(2);
+ });
+
+ it('removes the data if all the values from a query are not defined', () => {
+ expect(store.groups[1].metrics[0].queries[0].result.length).toEqual(0);
});
});
diff --git a/spec/javascripts/monitoring/utils/multiple_time_series_spec.js b/spec/javascripts/monitoring/utils/multiple_time_series_spec.js
index 99584c75287..8937b7d9680 100644
--- a/spec/javascripts/monitoring/utils/multiple_time_series_spec.js
+++ b/spec/javascripts/monitoring/utils/multiple_time_series_spec.js
@@ -2,7 +2,7 @@ import createTimeSeries from '~/monitoring/utils/multiple_time_series';
import { convertDatesMultipleSeries, singleRowMetricsMultipleSeries } from '../mock_data';
const convertedMetrics = convertDatesMultipleSeries(singleRowMetricsMultipleSeries);
-const timeSeries = createTimeSeries(convertedMetrics[0].queries, 428, 272, 120);
+const { timeSeries } = createTimeSeries(convertedMetrics[0].queries, 428, 272, 120);
const firstTimeSeries = timeSeries[0];
describe('Multiple time series', () => {
diff --git a/spec/javascripts/new_branch_spec.js b/spec/javascripts/new_branch_spec.js
index 122e5bc58b2..1d7b885e64f 100644
--- a/spec/javascripts/new_branch_spec.js
+++ b/spec/javascripts/new_branch_spec.js
@@ -1,168 +1,199 @@
-/* eslint-disable one-var, no-var, one-var-declaration-per-line, no-return-assign, quotes, max-len */
-
import $ from 'jquery';
import NewBranchForm from '~/new_branch_form';
-(function() {
- describe('Branch', function() {
- return describe('create a new branch', function() {
- var expectToHaveError, fillNameWith;
- preloadFixtures('branches/new_branch.html.raw');
- fillNameWith = function(value) {
- return $('.js-branch-name').val(value).trigger('blur');
- };
- expectToHaveError = function(error) {
- return expect($('.js-branch-name-error span').text()).toEqual(error);
- };
- beforeEach(function() {
- loadFixtures('branches/new_branch.html.raw');
- $('form').on('submit', function(e) {
- return e.preventDefault();
- });
- return this.form = new NewBranchForm($('.js-create-branch-form'), []);
- });
- it("can't start with a dot", function() {
- fillNameWith('.foo');
- return expectToHaveError("can't start with '.'");
- });
- it("can't start with a slash", function() {
- fillNameWith('/foo');
- return expectToHaveError("can't start with '/'");
- });
- it("can't have two consecutive dots", function() {
- fillNameWith('foo..bar');
- return expectToHaveError("can't contain '..'");
- });
- it("can't have spaces anywhere", function() {
- fillNameWith(' foo');
- expectToHaveError("can't contain spaces");
- fillNameWith('foo bar');
- expectToHaveError("can't contain spaces");
- fillNameWith('foo ');
- return expectToHaveError("can't contain spaces");
- });
- it("can't have ~ anywhere", function() {
- fillNameWith('~foo');
- expectToHaveError("can't contain '~'");
- fillNameWith('foo~bar');
- expectToHaveError("can't contain '~'");
- fillNameWith('foo~');
- return expectToHaveError("can't contain '~'");
- });
- it("can't have tilde anwhere", function() {
- fillNameWith('~foo');
- expectToHaveError("can't contain '~'");
- fillNameWith('foo~bar');
- expectToHaveError("can't contain '~'");
- fillNameWith('foo~');
- return expectToHaveError("can't contain '~'");
- });
- it("can't have caret anywhere", function() {
- fillNameWith('^foo');
- expectToHaveError("can't contain '^'");
- fillNameWith('foo^bar');
- expectToHaveError("can't contain '^'");
- fillNameWith('foo^');
- return expectToHaveError("can't contain '^'");
- });
- it("can't have : anywhere", function() {
- fillNameWith(':foo');
- expectToHaveError("can't contain ':'");
- fillNameWith('foo:bar');
- expectToHaveError("can't contain ':'");
- fillNameWith(':foo');
- return expectToHaveError("can't contain ':'");
- });
- it("can't have question mark anywhere", function() {
- fillNameWith('?foo');
- expectToHaveError("can't contain '?'");
- fillNameWith('foo?bar');
- expectToHaveError("can't contain '?'");
- fillNameWith('foo?');
- return expectToHaveError("can't contain '?'");
- });
- it("can't have asterisk anywhere", function() {
- fillNameWith('*foo');
- expectToHaveError("can't contain '*'");
- fillNameWith('foo*bar');
- expectToHaveError("can't contain '*'");
- fillNameWith('foo*');
- return expectToHaveError("can't contain '*'");
- });
- it("can't have open bracket anywhere", function() {
- fillNameWith('[foo');
- expectToHaveError("can't contain '['");
- fillNameWith('foo[bar');
- expectToHaveError("can't contain '['");
- fillNameWith('foo[');
- return expectToHaveError("can't contain '['");
- });
- it("can't have a backslash anywhere", function() {
- fillNameWith('\\foo');
- expectToHaveError("can't contain '\\'");
- fillNameWith('foo\\bar');
- expectToHaveError("can't contain '\\'");
- fillNameWith('foo\\');
- return expectToHaveError("can't contain '\\'");
- });
- it("can't contain a sequence @{ anywhere", function() {
- fillNameWith('@{foo');
- expectToHaveError("can't contain '@{'");
- fillNameWith('foo@{bar');
- expectToHaveError("can't contain '@{'");
- fillNameWith('foo@{');
- return expectToHaveError("can't contain '@{'");
- });
- it("can't have consecutive slashes", function() {
- fillNameWith('foo//bar');
- return expectToHaveError("can't contain consecutive slashes");
- });
- it("can't end with a slash", function() {
- fillNameWith('foo/');
- return expectToHaveError("can't end in '/'");
- });
- it("can't end with a dot", function() {
- fillNameWith('foo.');
- return expectToHaveError("can't end in '.'");
- });
- it("can't end with .lock", function() {
- fillNameWith('foo.lock');
- return expectToHaveError("can't end in '.lock'");
- });
- it("can't be the single character @", function() {
- fillNameWith('@');
- return expectToHaveError("can't be '@'");
- });
- it("concatenates all error messages", function() {
- fillNameWith('/foo bar?~.');
- return expectToHaveError("can't start with '/', can't contain spaces, '?', '~', can't end in '.'");
- });
- it("doesn't duplicate error messages", function() {
- fillNameWith('?foo?bar?zoo?');
- return expectToHaveError("can't contain '?'");
- });
- it("removes the error message when is a valid name", function() {
- fillNameWith('foo?bar');
- expect($('.js-branch-name-error span').length).toEqual(1);
- fillNameWith('foobar');
- return expect($('.js-branch-name-error span').length).toEqual(0);
- });
- it("can have dashes anywhere", function() {
- fillNameWith('-foo-bar-zoo-');
- return expect($('.js-branch-name-error span').length).toEqual(0);
- });
- it("can have underscores anywhere", function() {
- fillNameWith('_foo_bar_zoo_');
- return expect($('.js-branch-name-error span').length).toEqual(0);
- });
- it("can have numbers anywhere", function() {
- fillNameWith('1foo2bar3zoo4');
- return expect($('.js-branch-name-error span').length).toEqual(0);
- });
- return it("can be only letters", function() {
- fillNameWith('foo');
- return expect($('.js-branch-name-error span').length).toEqual(0);
+describe('Branch', function() {
+ describe('create a new branch', function() {
+ preloadFixtures('branches/new_branch.html.raw');
+
+ function fillNameWith(value) {
+ $('.js-branch-name')
+ .val(value)
+ .trigger('blur');
+ }
+
+ function expectToHaveError(error) {
+ expect($('.js-branch-name-error span').text()).toEqual(error);
+ }
+
+ beforeEach(function() {
+ loadFixtures('branches/new_branch.html.raw');
+ $('form').on('submit', function(e) {
+ return e.preventDefault();
});
+ this.form = new NewBranchForm($('.js-create-branch-form'), []);
+ });
+
+ it("can't start with a dot", function() {
+ fillNameWith('.foo');
+ expectToHaveError("can't start with '.'");
+ });
+
+ it("can't start with a slash", function() {
+ fillNameWith('/foo');
+ expectToHaveError("can't start with '/'");
+ });
+
+ it("can't have two consecutive dots", function() {
+ fillNameWith('foo..bar');
+ expectToHaveError("can't contain '..'");
+ });
+
+ it("can't have spaces anywhere", function() {
+ fillNameWith(' foo');
+ expectToHaveError("can't contain spaces");
+ fillNameWith('foo bar');
+ expectToHaveError("can't contain spaces");
+ fillNameWith('foo ');
+ expectToHaveError("can't contain spaces");
+ });
+
+ it("can't have ~ anywhere", function() {
+ fillNameWith('~foo');
+ expectToHaveError("can't contain '~'");
+ fillNameWith('foo~bar');
+ expectToHaveError("can't contain '~'");
+ fillNameWith('foo~');
+ expectToHaveError("can't contain '~'");
+ });
+
+ it("can't have tilde anwhere", function() {
+ fillNameWith('~foo');
+ expectToHaveError("can't contain '~'");
+ fillNameWith('foo~bar');
+ expectToHaveError("can't contain '~'");
+ fillNameWith('foo~');
+ expectToHaveError("can't contain '~'");
+ });
+
+ it("can't have caret anywhere", function() {
+ fillNameWith('^foo');
+ expectToHaveError("can't contain '^'");
+ fillNameWith('foo^bar');
+ expectToHaveError("can't contain '^'");
+ fillNameWith('foo^');
+ expectToHaveError("can't contain '^'");
+ });
+
+ it("can't have : anywhere", function() {
+ fillNameWith(':foo');
+ expectToHaveError("can't contain ':'");
+ fillNameWith('foo:bar');
+ expectToHaveError("can't contain ':'");
+ fillNameWith(':foo');
+ expectToHaveError("can't contain ':'");
+ });
+
+ it("can't have question mark anywhere", function() {
+ fillNameWith('?foo');
+ expectToHaveError("can't contain '?'");
+ fillNameWith('foo?bar');
+ expectToHaveError("can't contain '?'");
+ fillNameWith('foo?');
+ expectToHaveError("can't contain '?'");
+ });
+
+ it("can't have asterisk anywhere", function() {
+ fillNameWith('*foo');
+ expectToHaveError("can't contain '*'");
+ fillNameWith('foo*bar');
+ expectToHaveError("can't contain '*'");
+ fillNameWith('foo*');
+ expectToHaveError("can't contain '*'");
+ });
+
+ it("can't have open bracket anywhere", function() {
+ fillNameWith('[foo');
+ expectToHaveError("can't contain '['");
+ fillNameWith('foo[bar');
+ expectToHaveError("can't contain '['");
+ fillNameWith('foo[');
+ expectToHaveError("can't contain '['");
+ });
+
+ it("can't have a backslash anywhere", function() {
+ fillNameWith('\\foo');
+ expectToHaveError("can't contain '\\'");
+ fillNameWith('foo\\bar');
+ expectToHaveError("can't contain '\\'");
+ fillNameWith('foo\\');
+ expectToHaveError("can't contain '\\'");
+ });
+
+ it("can't contain a sequence @{ anywhere", function() {
+ fillNameWith('@{foo');
+ expectToHaveError("can't contain '@{'");
+ fillNameWith('foo@{bar');
+ expectToHaveError("can't contain '@{'");
+ fillNameWith('foo@{');
+ expectToHaveError("can't contain '@{'");
+ });
+
+ it("can't have consecutive slashes", function() {
+ fillNameWith('foo//bar');
+ expectToHaveError("can't contain consecutive slashes");
+ });
+
+ it("can't end with a slash", function() {
+ fillNameWith('foo/');
+ expectToHaveError("can't end in '/'");
+ });
+
+ it("can't end with a dot", function() {
+ fillNameWith('foo.');
+ expectToHaveError("can't end in '.'");
+ });
+
+ it("can't end with .lock", function() {
+ fillNameWith('foo.lock');
+ expectToHaveError("can't end in '.lock'");
+ });
+
+ it("can't be the single character @", function() {
+ fillNameWith('@');
+ expectToHaveError("can't be '@'");
+ });
+
+ it('concatenates all error messages', function() {
+ fillNameWith('/foo bar?~.');
+ expectToHaveError("can't start with '/', can't contain spaces, '?', '~', can't end in '.'");
+ });
+
+ it("doesn't duplicate error messages", function() {
+ fillNameWith('?foo?bar?zoo?');
+ expectToHaveError("can't contain '?'");
+ });
+
+ it('removes the error message when is a valid name', function() {
+ fillNameWith('foo?bar');
+
+ expect($('.js-branch-name-error span').length).toEqual(1);
+ fillNameWith('foobar');
+
+ expect($('.js-branch-name-error span').length).toEqual(0);
+ });
+
+ it('can have dashes anywhere', function() {
+ fillNameWith('-foo-bar-zoo-');
+
+ expect($('.js-branch-name-error span').length).toEqual(0);
+ });
+
+ it('can have underscores anywhere', function() {
+ fillNameWith('_foo_bar_zoo_');
+
+ expect($('.js-branch-name-error span').length).toEqual(0);
+ });
+
+ it('can have numbers anywhere', function() {
+ fillNameWith('1foo2bar3zoo4');
+
+ expect($('.js-branch-name-error span').length).toEqual(0);
+ });
+
+ it('can be only letters', function() {
+ fillNameWith('foo');
+
+ expect($('.js-branch-name-error span').length).toEqual(0);
});
});
-}).call(window);
+});
diff --git a/spec/javascripts/notebook/cells/code_spec.js b/spec/javascripts/notebook/cells/code_spec.js
index 0c432d73f67..4659b83d1b6 100644
--- a/spec/javascripts/notebook/cells/code_spec.js
+++ b/spec/javascripts/notebook/cells/code_spec.js
@@ -12,7 +12,7 @@ describe('Code component', () => {
});
describe('without output', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm = new Component({
propsData: {
cell: json.cells[0],
@@ -31,7 +31,7 @@ describe('Code component', () => {
});
describe('with output', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm = new Component({
propsData: {
cell: json.cells[2],
diff --git a/spec/javascripts/notebook/cells/markdown_spec.js b/spec/javascripts/notebook/cells/markdown_spec.js
index 0b1b11de1fd..540fc8a21f1 100644
--- a/spec/javascripts/notebook/cells/markdown_spec.js
+++ b/spec/javascripts/notebook/cells/markdown_spec.js
@@ -11,7 +11,7 @@ describe('Markdown component', () => {
let cell;
let json;
- beforeEach((done) => {
+ beforeEach(done => {
json = getJSONFixture('blob/notebook/basic.json');
// eslint-disable-next-line prefer-destructuring
@@ -34,18 +34,18 @@ describe('Markdown component', () => {
});
it('does not render the markdown text', () => {
- expect(
- vm.$el.querySelector('.markdown').innerHTML.trim(),
- ).not.toEqual(cell.source.join(''));
+ expect(vm.$el.querySelector('.markdown').innerHTML.trim()).not.toEqual(cell.source.join(''));
});
it('renders the markdown HTML', () => {
expect(vm.$el.querySelector('.markdown h1')).not.toBeNull();
});
- it('sanitizes output', (done) => {
+ it('sanitizes output', done => {
Object.assign(cell, {
- source: ['[XSS](data:text/html;base64,PHNjcmlwdD5hbGVydChkb2N1bWVudC5kb21haW4pPC9zY3JpcHQ+Cg==)\n'],
+ source: [
+ '[XSS](data:text/html;base64,PHNjcmlwdD5hbGVydChkb2N1bWVudC5kb21haW4pPC9zY3JpcHQ+Cg==)\n',
+ ],
});
Vue.nextTick(() => {
@@ -60,7 +60,7 @@ describe('Markdown component', () => {
json = getJSONFixture('blob/notebook/math.json');
});
- it('renders multi-line katex', (done) => {
+ it('renders multi-line katex', done => {
vm = new Component({
propsData: {
cell: json.cells[0],
@@ -68,15 +68,13 @@ describe('Markdown component', () => {
}).$mount();
Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.katex'),
- ).not.toBeNull();
+ expect(vm.$el.querySelector('.katex')).not.toBeNull();
done();
});
});
- it('renders inline katex', (done) => {
+ it('renders inline katex', done => {
vm = new Component({
propsData: {
cell: json.cells[1],
@@ -84,15 +82,13 @@ describe('Markdown component', () => {
}).$mount();
Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('p:first-child .katex'),
- ).not.toBeNull();
+ expect(vm.$el.querySelector('p:first-child .katex')).not.toBeNull();
done();
});
});
- it('renders multiple inline katex', (done) => {
+ it('renders multiple inline katex', done => {
vm = new Component({
propsData: {
cell: json.cells[1],
@@ -100,9 +96,7 @@ describe('Markdown component', () => {
}).$mount();
Vue.nextTick(() => {
- expect(
- vm.$el.querySelectorAll('p:nth-child(2) .katex').length,
- ).toBe(4);
+ expect(vm.$el.querySelectorAll('p:nth-child(2) .katex').length).toBe(4);
done();
});
diff --git a/spec/javascripts/notebook/cells/output/html_sanitize_tests.js b/spec/javascripts/notebook/cells/output/html_sanitize_tests.js
index d587573fc9e..74c48f04367 100644
--- a/spec/javascripts/notebook/cells/output/html_sanitize_tests.js
+++ b/spec/javascripts/notebook/cells/output/html_sanitize_tests.js
@@ -28,7 +28,8 @@ export default {
output: '<a>foo</a>',
},
'protocol-based JS injection: long UTF-8 encoding without semicolons': {
- input: '<a href=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>foo</a>',
+ input:
+ '<a href=&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041>foo</a>',
output: '<a>foo</a>',
},
'protocol-based JS injection: hex encoding': {
@@ -40,7 +41,8 @@ export default {
output: '<a>foo</a>',
},
'protocol-based JS injection: hex encoding without semicolons': {
- input: '<a href=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>foo</a>',
+ input:
+ '<a href=&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29>foo</a>',
output: '<a>foo</a>',
},
'protocol-based JS injection: null char': {
@@ -48,7 +50,7 @@ export default {
output: '<a>foo</a>',
},
'protocol-based JS injection: invalid URL char': {
- input: '<img src=java\script:alert("XSS")>', // eslint-disable-line no-useless-escape
+ input: '<img src=javascript:alert("XSS")>',
output: '<img>',
},
'protocol-based JS injection: Unicode': {
diff --git a/spec/javascripts/notebook/cells/output/html_spec.js b/spec/javascripts/notebook/cells/output/html_spec.js
index 9c5385f2922..bea62f54634 100644
--- a/spec/javascripts/notebook/cells/output/html_spec.js
+++ b/spec/javascripts/notebook/cells/output/html_spec.js
@@ -14,7 +14,7 @@ describe('html output cell', () => {
}
describe('sanitizes output', () => {
- Object.keys(sanitizeTests).forEach((key) => {
+ Object.keys(sanitizeTests).forEach(key => {
it(key, () => {
const test = sanitizeTests[key];
const vm = createComponent(test.input);
diff --git a/spec/javascripts/notebook/cells/output/index_spec.js b/spec/javascripts/notebook/cells/output/index_spec.js
index dbf79f85c7c..feab7ad4212 100644
--- a/spec/javascripts/notebook/cells/output/index_spec.js
+++ b/spec/javascripts/notebook/cells/output/index_spec.js
@@ -7,7 +7,7 @@ describe('Output component', () => {
let vm;
let json;
- const createComponent = (output) => {
+ const createComponent = output => {
vm = new Component({
propsData: {
output,
@@ -22,7 +22,7 @@ describe('Output component', () => {
});
describe('text output', () => {
- beforeEach((done) => {
+ beforeEach(done => {
createComponent(json.cells[2].outputs[0]);
setTimeout(() => {
@@ -40,7 +40,7 @@ describe('Output component', () => {
});
describe('image output', () => {
- beforeEach((done) => {
+ beforeEach(done => {
createComponent(json.cells[3].outputs[0]);
setTimeout(() => {
@@ -58,7 +58,7 @@ describe('Output component', () => {
});
describe('html output', () => {
- beforeEach((done) => {
+ beforeEach(done => {
createComponent(json.cells[4].outputs[0]);
setTimeout(() => {
@@ -77,7 +77,7 @@ describe('Output component', () => {
});
describe('svg output', () => {
- beforeEach((done) => {
+ beforeEach(done => {
createComponent(json.cells[5].outputs[0]);
setTimeout(() => {
@@ -95,7 +95,7 @@ describe('Output component', () => {
});
describe('default to plain text', () => {
- beforeEach((done) => {
+ beforeEach(done => {
createComponent(json.cells[6].outputs[0]);
setTimeout(() => {
@@ -112,7 +112,7 @@ describe('Output component', () => {
expect(vm.$el.querySelector('.prompt span')).not.toBeNull();
});
- it('renders as plain text when doesn\'t recognise other types', (done) => {
+ it("renders as plain text when doesn't recognise other types", done => {
createComponent(json.cells[7].outputs[0]);
setTimeout(() => {
diff --git a/spec/javascripts/notebook/cells/prompt_spec.js b/spec/javascripts/notebook/cells/prompt_spec.js
index 207fa433a59..cbbcb1e68e3 100644
--- a/spec/javascripts/notebook/cells/prompt_spec.js
+++ b/spec/javascripts/notebook/cells/prompt_spec.js
@@ -7,7 +7,7 @@ describe('Prompt component', () => {
let vm;
describe('input', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm = new Component({
propsData: {
type: 'In',
@@ -31,7 +31,7 @@ describe('Prompt component', () => {
});
describe('output', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm = new Component({
propsData: {
type: 'Out',
diff --git a/spec/javascripts/notebook/index_spec.js b/spec/javascripts/notebook/index_spec.js
index bd63ab35426..2e2ea5ad8af 100644
--- a/spec/javascripts/notebook/index_spec.js
+++ b/spec/javascripts/notebook/index_spec.js
@@ -14,7 +14,7 @@ describe('Notebook component', () => {
});
describe('without JSON', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm = new Component({
propsData: {
notebook: {},
@@ -33,7 +33,7 @@ describe('Notebook component', () => {
});
describe('with JSON', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm = new Component({
propsData: {
notebook: json,
@@ -65,7 +65,7 @@ describe('Notebook component', () => {
});
describe('with worksheets', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm = new Component({
propsData: {
notebook: jsonWithWorksheet,
@@ -80,7 +80,9 @@ describe('Notebook component', () => {
});
it('renders cells', () => {
- expect(vm.$el.querySelectorAll('.cell').length).toBe(jsonWithWorksheet.worksheets[0].cells.length);
+ expect(vm.$el.querySelectorAll('.cell').length).toBe(
+ jsonWithWorksheet.worksheets[0].cells.length,
+ );
});
it('renders markdown cell', () => {
diff --git a/spec/javascripts/notes/components/comment_form_spec.js b/spec/javascripts/notes/components/comment_form_spec.js
index 155c91dcc46..3c57fe51352 100644
--- a/spec/javascripts/notes/components/comment_form_spec.js
+++ b/spec/javascripts/notes/components/comment_form_spec.js
@@ -51,6 +51,7 @@ describe('issue_comment_form component', () => {
spyOn(vm, 'stopPolling');
vm.handleSave();
+
expect(vm.isSubmitting).toEqual(true);
expect(vm.note).toEqual('');
expect(vm.saveNote).toHaveBeenCalled();
@@ -77,10 +78,14 @@ describe('issue_comment_form component', () => {
vm.handleSave();
Vue.nextTick()
- .then(() => expect(actionButton.disabled).toBeTruthy())
+ .then(() => {
+ expect(actionButton.disabled).toBeTruthy();
+ })
.then(saveNotePromise)
.then(Vue.nextTick)
- .then(() => expect(actionButton.disabled).toBeFalsy())
+ .then(() => {
+ expect(actionButton.disabled).toBeFalsy();
+ })
.then(done)
.catch(done.fail);
});
@@ -121,6 +126,7 @@ describe('issue_comment_form component', () => {
it('should link to markdown docs', () => {
const { markdownDocsPath } = notesDataMock;
+
expect(vm.$el.querySelector(`a[href="${markdownDocsPath}"]`).textContent.trim()).toEqual(
'Markdown',
);
@@ -128,6 +134,7 @@ describe('issue_comment_form component', () => {
it('should link to quick actions docs', () => {
const { quickActionsDocsPath } = notesDataMock;
+
expect(
vm.$el.querySelector(`a[href="${quickActionsDocsPath}"]`).textContent.trim(),
).toEqual('quick actions');
@@ -215,6 +222,7 @@ describe('issue_comment_form component', () => {
expect(vm.$el.querySelector('.btn-comment-and-close').textContent.trim()).toEqual(
'Comment & close issue',
);
+
expect(vm.$el.querySelector('.js-note-discard')).toBeDefined();
done();
});
diff --git a/spec/javascripts/notes/components/diff_with_note_spec.js b/spec/javascripts/notes/components/diff_with_note_spec.js
index 239d7950907..0752bd05904 100644
--- a/spec/javascripts/notes/components/diff_with_note_spec.js
+++ b/spec/javascripts/notes/components/diff_with_note_spec.js
@@ -1,7 +1,6 @@
import Vue from 'vue';
import DiffWithNote from '~/notes/components/diff_with_note.vue';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import createStore from '~/notes/stores';
+import { createStore } from '~/mr_notes/stores';
import { mountComponentWithStore } from 'spec/helpers';
const discussionFixture = 'merge_requests/diff_discussion.json';
@@ -11,14 +10,14 @@ describe('diff_with_note', () => {
let store;
let vm;
const diffDiscussionMock = getJSONFixture(discussionFixture)[0];
- const diffDiscussion = convertObjectPropsToCamelCase(diffDiscussionMock);
+ const diffDiscussion = diffDiscussionMock;
const Component = Vue.extend(DiffWithNote);
const props = {
discussion: diffDiscussion,
};
const selectors = {
get container() {
- return vm.$refs.fileHolder;
+ return vm.$el;
},
get diffTable() {
return this.container.querySelector('.diff-content table');
@@ -65,13 +64,12 @@ describe('diff_with_note', () => {
describe('image diff', () => {
beforeEach(() => {
const imageDiffDiscussionMock = getJSONFixture(imageDiscussionFixture)[0];
- props.discussion = convertObjectPropsToCamelCase(imageDiffDiscussionMock);
+ props.discussion = imageDiffDiscussionMock;
});
it('shows image diff', () => {
vm = mountComponentWithStore(Component, { props, store });
- expect(selectors.container).toHaveClass('js-image-file');
expect(selectors.diffTable).not.toExist();
});
});
diff --git a/spec/javascripts/notes/components/discussion_filter_spec.js b/spec/javascripts/notes/components/discussion_filter_spec.js
new file mode 100644
index 00000000000..9070d968cfd
--- /dev/null
+++ b/spec/javascripts/notes/components/discussion_filter_spec.js
@@ -0,0 +1,86 @@
+import Vue from 'vue';
+import createStore from '~/notes/stores';
+import DiscussionFilter from '~/notes/components/discussion_filter.vue';
+import { mountComponentWithStore } from '../../helpers/vue_mount_component_helper';
+import { discussionFiltersMock, discussionMock } from '../mock_data';
+
+describe('DiscussionFilter component', () => {
+ let vm;
+ let store;
+
+ beforeEach(() => {
+ store = createStore();
+
+ const discussions = [
+ {
+ ...discussionMock,
+ id: discussionMock.id,
+ notes: [{ ...discussionMock.notes[0], resolvable: true, resolved: true }],
+ },
+ ];
+ const Component = Vue.extend(DiscussionFilter);
+ const selectedValue = discussionFiltersMock[0].value;
+
+ store.state.discussions = discussions;
+ vm = mountComponentWithStore(Component, {
+ el: null,
+ store,
+ props: {
+ filters: discussionFiltersMock,
+ selectedValue,
+ },
+ });
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders the all filters', () => {
+ expect(vm.$el.querySelectorAll('.dropdown-menu li').length).toEqual(
+ discussionFiltersMock.length,
+ );
+ });
+
+ it('renders the default selected item', () => {
+ expect(vm.$el.querySelector('#discussion-filter-dropdown').textContent.trim()).toEqual(
+ discussionFiltersMock[0].title,
+ );
+ });
+
+ it('updates to the selected item', () => {
+ const filterItem = vm.$el.querySelector('.dropdown-menu li:last-child button');
+ filterItem.click();
+
+ expect(vm.currentFilter.title).toEqual(filterItem.textContent.trim());
+ });
+
+ it('only updates when selected filter changes', () => {
+ const filterItem = vm.$el.querySelector('.dropdown-menu li:first-child button');
+
+ spyOn(vm, 'filterDiscussion');
+ filterItem.click();
+
+ expect(vm.filterDiscussion).not.toHaveBeenCalled();
+ });
+
+ it('disables commenting when "Show history only" filter is applied', () => {
+ const filterItem = vm.$el.querySelector('.dropdown-menu li:last-child button');
+ filterItem.click();
+
+ expect(vm.$store.state.commentsDisabled).toBe(true);
+ });
+
+ it('enables commenting when "Show history only" filter is not applied', () => {
+ const filterItem = vm.$el.querySelector('.dropdown-menu li:first-child button');
+ filterItem.click();
+
+ expect(vm.$store.state.commentsDisabled).toBe(false);
+ });
+
+ it('renders a dropdown divider for the default filter', () => {
+ const defaultFilter = vm.$el.querySelector('.dropdown-menu li:first-child');
+
+ expect(defaultFilter.lastChild.classList).toContain('dropdown-divider');
+ });
+});
diff --git a/spec/javascripts/notes/components/note_actions_spec.js b/spec/javascripts/notes/components/note_actions_spec.js
index d7298cb3483..f6c854e6def 100644
--- a/spec/javascripts/notes/components/note_actions_spec.js
+++ b/spec/javascripts/notes/components/note_actions_spec.js
@@ -55,7 +55,7 @@ describe('issue_note_actions component', () => {
expect(vm.$el.querySelector('.js-note-edit')).toBeDefined();
});
- it('should be possible to report as abuse', () => {
+ it('should be possible to report abuse to GitLab', () => {
expect(vm.$el.querySelector(`a[href="${props.reportAbusePath}"]`)).toBeDefined();
});
diff --git a/spec/javascripts/notes/components/note_app_spec.js b/spec/javascripts/notes/components/note_app_spec.js
index 7eb4d3aed29..0081f42c330 100644
--- a/spec/javascripts/notes/components/note_app_spec.js
+++ b/spec/javascripts/notes/components/note_app_spec.js
@@ -121,6 +121,13 @@ describe('note_app', () => {
).toEqual('Write a comment or drag your files here…');
});
+ it('should not render form when commenting is disabled', () => {
+ store.state.commentsDisabled = true;
+ vm = mountComponent();
+
+ expect(vm.$el.querySelector('.js-main-target-form')).toEqual(null);
+ });
+
it('should render form comment button as disabled', () => {
expect(vm.$el.querySelector('.js-note-new-discussion').getAttribute('disabled')).toEqual(
'disabled',
@@ -223,6 +230,7 @@ describe('note_app', () => {
it('should render markdown docs url', () => {
const { markdownDocsPath } = mockData.notesDataMock;
+
expect(vm.$el.querySelector(`a[href="${markdownDocsPath}"]`).textContent.trim()).toEqual(
'Markdown',
);
@@ -230,6 +238,7 @@ describe('note_app', () => {
it('should render quick action docs url', () => {
const { quickActionsDocsPath } = mockData.notesDataMock;
+
expect(vm.$el.querySelector(`a[href="${quickActionsDocsPath}"]`).textContent.trim()).toEqual(
'quick actions',
);
diff --git a/spec/javascripts/notes/components/note_form_spec.js b/spec/javascripts/notes/components/note_form_spec.js
index 147ffcf1b81..5db20fd285f 100644
--- a/spec/javascripts/notes/components/note_form_spec.js
+++ b/spec/javascripts/notes/components/note_form_spec.js
@@ -76,6 +76,7 @@ describe('issue_note_form component', () => {
it('should link to markdown docs', () => {
const { markdownDocsPath } = notesDataMock;
+
expect(vm.$el.querySelector(`a[href="${markdownDocsPath}"]`).textContent.trim()).toEqual(
'Markdown',
);
@@ -100,6 +101,7 @@ describe('issue_note_form component', () => {
expect(vm.handleUpdate).toHaveBeenCalled();
});
+
it('should save note when ctrl+enter is pressed', () => {
spyOn(vm, 'handleUpdate').and.callThrough();
vm.$el.querySelector('textarea').value = 'Foo';
diff --git a/spec/javascripts/notes/components/noteable_discussion_spec.js b/spec/javascripts/notes/components/noteable_discussion_spec.js
index 2a01bd85520..ab9c52346d6 100644
--- a/spec/javascripts/notes/components/noteable_discussion_spec.js
+++ b/spec/javascripts/notes/components/noteable_discussion_spec.js
@@ -3,6 +3,7 @@ import createStore from '~/notes/stores';
import noteableDiscussion from '~/notes/components/noteable_discussion.vue';
import '~/behaviors/markdown/render_gfm';
import { noteableDataMock, discussionMock, notesDataMock } from '../mock_data';
+import mockDiffFile from '../../diffs/mock_data/diff_file';
const discussionWithTwoUnresolvedNotes = 'merge_requests/resolved_diff_discussion.json';
@@ -33,9 +34,20 @@ describe('noteable_discussion component', () => {
expect(vm.$el.querySelector('.user-avatar-link')).not.toBeNull();
});
+ it('should not render discussion header for non diff discussions', () => {
+ expect(vm.$el.querySelector('.discussion-header')).toBeNull();
+ });
+
it('should render discussion header', () => {
- expect(vm.$el.querySelector('.discussion-header')).not.toBeNull();
- expect(vm.$el.querySelector('.notes').children.length).toEqual(discussionMock.notes.length);
+ const discussion = { ...discussionMock };
+ discussion.diff_file = mockDiffFile;
+ discussion.diff_discussion = true;
+ const diffDiscussionVm = new Component({
+ store,
+ propsData: { discussion },
+ }).$mount();
+
+ expect(diffDiscussionVm.$el.querySelector('.discussion-header')).not.toBeNull();
});
describe('actions', () => {
@@ -66,45 +78,6 @@ describe('noteable_discussion component', () => {
});
});
- describe('computed', () => {
- describe('hasMultipleUnresolvedDiscussions', () => {
- it('is false if there are no unresolved discussions', done => {
- spyOnProperty(vm, 'unresolvedDiscussions').and.returnValue([]);
-
- Vue.nextTick()
- .then(() => {
- expect(vm.hasMultipleUnresolvedDiscussions).toBe(false);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('is false if there is one unresolved discussion', done => {
- spyOnProperty(vm, 'unresolvedDiscussions').and.returnValue([discussionMock]);
-
- Vue.nextTick()
- .then(() => {
- expect(vm.hasMultipleUnresolvedDiscussions).toBe(false);
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('is true if there are two unresolved discussions', done => {
- const discussion = getJSONFixture(discussionWithTwoUnresolvedNotes)[0];
- discussion.notes[0].resolved = false;
- vm.$store.dispatch('setInitialNotes', [discussion, discussion]);
-
- Vue.nextTick()
- .then(() => {
- expect(vm.hasMultipleUnresolvedDiscussions).toBe(true);
- })
- .then(done)
- .catch(done.fail);
- });
- });
- });
-
describe('methods', () => {
describe('jumpToNextDiscussion', () => {
it('expands next unresolved discussion', done => {
@@ -133,4 +106,27 @@ describe('noteable_discussion component', () => {
});
});
});
+
+ describe('componentData', () => {
+ it('should return first note object for placeholder note', () => {
+ const data = {
+ isPlaceholderNote: true,
+ notes: [{ body: 'hello world!' }],
+ };
+
+ const note = vm.componentData(data);
+
+ expect(note).toEqual(data.notes[0]);
+ });
+
+ it('should return given note for nonplaceholder notes', () => {
+ const data = {
+ notes: [{ id: 12 }],
+ };
+
+ const note = vm.componentData(data);
+
+ expect(note).toEqual(data);
+ });
+ });
});
diff --git a/spec/javascripts/notes/components/noteable_note_spec.js b/spec/javascripts/notes/components/noteable_note_spec.js
index a31d17cacbb..8ade6fc2ced 100644
--- a/spec/javascripts/notes/components/noteable_note_spec.js
+++ b/spec/javascripts/notes/components/noteable_note_spec.js
@@ -36,6 +36,7 @@ describe('issue_note', () => {
it('should render note header content', () => {
const el = vm.$el.querySelector('.note-header .note-header-author-name');
+
expect(el.textContent.trim()).toEqual(note.author.name);
});
diff --git a/spec/javascripts/notes/components/toggle_replies_widget_spec.js b/spec/javascripts/notes/components/toggle_replies_widget_spec.js
new file mode 100644
index 00000000000..2ead8cc6e6a
--- /dev/null
+++ b/spec/javascripts/notes/components/toggle_replies_widget_spec.js
@@ -0,0 +1,78 @@
+import Vue from 'vue';
+import toggleRepliesWidget from '~/notes/components/toggle_replies_widget.vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import { note } from '../mock_data';
+
+const deepCloneObject = obj => JSON.parse(JSON.stringify(obj));
+
+describe('toggle replies widget for notes', () => {
+ let vm;
+ let ToggleRepliesWidget;
+ const noteFromOtherUser = deepCloneObject(note);
+ noteFromOtherUser.author.username = 'fatihacet';
+
+ const noteFromAnotherUser = deepCloneObject(note);
+ noteFromAnotherUser.author.username = 'mgreiling';
+ noteFromAnotherUser.author.name = 'Mike Greiling';
+
+ const replies = [note, note, note, noteFromOtherUser, noteFromAnotherUser];
+
+ beforeEach(() => {
+ ToggleRepliesWidget = Vue.extend(toggleRepliesWidget);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('collapsed state', () => {
+ beforeEach(() => {
+ vm = mountComponent(ToggleRepliesWidget, {
+ replies,
+ collapsed: true,
+ });
+ });
+
+ it('should render the collapsed', () => {
+ const vmTextContent = vm.$el.textContent.replace(/\s\s+/g, ' ');
+
+ expect(vm.$el.classList.contains('collapsed')).toEqual(true);
+ expect(vm.$el.querySelectorAll('.user-avatar-link').length).toEqual(3);
+ expect(vm.$el.querySelector('time')).not.toBeNull();
+ expect(vmTextContent).toContain('5 replies');
+ expect(vmTextContent).toContain(`Last reply by ${noteFromAnotherUser.author.name}`);
+ });
+
+ it('should emit toggle event when the replies text clicked', () => {
+ const spy = spyOn(vm, '$emit');
+
+ vm.$el.querySelector('.js-replies-text').click();
+
+ expect(spy).toHaveBeenCalledWith('toggle');
+ });
+ });
+
+ describe('expanded state', () => {
+ beforeEach(() => {
+ vm = mountComponent(ToggleRepliesWidget, {
+ replies,
+ collapsed: false,
+ });
+ });
+
+ it('should render expanded state', () => {
+ const vmTextContent = vm.$el.textContent.replace(/\s\s+/g, ' ');
+
+ expect(vm.$el.querySelector('.collapse-replies-btn')).not.toBeNull();
+ expect(vmTextContent).toContain('Collapse replies');
+ });
+
+ it('should emit toggle event when the collapse replies text called', () => {
+ const spy = spyOn(vm, '$emit');
+
+ vm.$el.querySelector('.js-collapse-replies').click();
+
+ expect(spy).toHaveBeenCalledWith('toggle');
+ });
+ });
+});
diff --git a/spec/javascripts/notes/helpers.js b/spec/javascripts/notes/helpers.js
index a7663710a56..3f349b40ba5 100644
--- a/spec/javascripts/notes/helpers.js
+++ b/spec/javascripts/notes/helpers.js
@@ -1,5 +1,5 @@
// eslint-disable-next-line import/prefer-default-export
-export const resetStore = (store) => {
+export const resetStore = store => {
store.replaceState({
notes: [],
targetNoteHash: null,
diff --git a/spec/javascripts/notes/mock_data.js b/spec/javascripts/notes/mock_data.js
index 1f030e5af28..ad0e793b915 100644
--- a/spec/javascripts/notes/mock_data.js
+++ b/spec/javascripts/notes/mock_data.js
@@ -1177,10 +1177,8 @@ export const discussion1 = {
file_path: 'about.md',
},
position: {
- formatter: {
- new_line: 50,
- old_line: null,
- },
+ new_line: 50,
+ old_line: null,
},
notes: [
{
@@ -1197,10 +1195,8 @@ export const resolvedDiscussion1 = {
file_path: 'about.md',
},
position: {
- formatter: {
- new_line: 50,
- old_line: null,
- },
+ new_line: 50,
+ old_line: null,
},
notes: [
{
@@ -1217,10 +1213,8 @@ export const discussion2 = {
file_path: 'README.md',
},
position: {
- formatter: {
- new_line: null,
- old_line: 20,
- },
+ new_line: null,
+ old_line: 20,
},
notes: [
{
@@ -1237,10 +1231,8 @@ export const discussion3 = {
file_path: 'README.md',
},
position: {
- formatter: {
- new_line: 21,
- old_line: null,
- },
+ new_line: 21,
+ old_line: null,
},
notes: [
{
@@ -1252,3 +1244,18 @@ export const discussion3 = {
export const unresolvableDiscussion = {
resolvable: false,
};
+
+export const discussionFiltersMock = [
+ {
+ title: 'Show all activity',
+ value: 0,
+ },
+ {
+ title: 'Show comments only',
+ value: 1,
+ },
+ {
+ title: 'Show system notes only',
+ value: 2,
+ },
+];
diff --git a/spec/javascripts/notes/stores/actions_spec.js b/spec/javascripts/notes/stores/actions_spec.js
index f4643fd55ed..24c2b3e6570 100644
--- a/spec/javascripts/notes/stores/actions_spec.js
+++ b/spec/javascripts/notes/stores/actions_spec.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import $ from 'jquery';
import _ from 'underscore';
import { headersInterceptor } from 'spec/helpers/vue_resource_helper';
import * as actions from '~/notes/stores/actions';
@@ -330,10 +331,14 @@ describe('Actions Notes Store', () => {
beforeEach(() => {
Vue.http.interceptors.push(interceptor);
+
+ $('body').attr('data-page', '');
});
afterEach(() => {
Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor);
+
+ $('body').attr('data-page', '');
});
it('commits DELETE_NOTE and dispatches updateMergeRequestWidget', done => {
@@ -353,6 +358,39 @@ describe('Actions Notes Store', () => {
{
type: 'updateMergeRequestWidget',
},
+ {
+ type: 'updateResolvableDiscussonsCounts',
+ },
+ ],
+ done,
+ );
+ });
+
+ it('dispatches removeDiscussionsFromDiff on merge request page', done => {
+ const note = { path: `${gl.TEST_HOST}`, id: 1 };
+
+ $('body').attr('data-page', 'projects:merge_requests:show');
+
+ testAction(
+ actions.deleteNote,
+ note,
+ store.state,
+ [
+ {
+ type: 'DELETE_NOTE',
+ payload: note,
+ },
+ ],
+ [
+ {
+ type: 'updateMergeRequestWidget',
+ },
+ {
+ type: 'updateResolvableDiscussonsCounts',
+ },
+ {
+ type: 'diffs/removeDiscussionsFromDiff',
+ },
],
done,
);
@@ -396,6 +434,12 @@ describe('Actions Notes Store', () => {
{
type: 'updateMergeRequestWidget',
},
+ {
+ type: 'startTaskList',
+ },
+ {
+ type: 'updateResolvableDiscussonsCounts',
+ },
],
done,
);
@@ -469,6 +513,9 @@ describe('Actions Notes Store', () => {
],
[
{
+ type: 'updateResolvableDiscussonsCounts',
+ },
+ {
type: 'updateMergeRequestWidget',
},
],
@@ -491,6 +538,9 @@ describe('Actions Notes Store', () => {
],
[
{
+ type: 'updateResolvableDiscussonsCounts',
+ },
+ {
type: 'updateMergeRequestWidget',
},
],
@@ -509,4 +559,30 @@ describe('Actions Notes Store', () => {
expect(mrWidgetEventHub.$emit).toHaveBeenCalledWith('mr.discussion.updated');
});
});
+
+ describe('setCommentsDisabled', () => {
+ it('should set comments disabled state', done => {
+ testAction(
+ actions.setCommentsDisabled,
+ true,
+ null,
+ [{ type: 'DISABLE_COMMENTS', payload: true }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('updateResolvableDiscussonsCounts', () => {
+ it('commits UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS', done => {
+ testAction(
+ actions.updateResolvableDiscussonsCounts,
+ null,
+ {},
+ [{ type: 'UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS' }],
+ [],
+ done,
+ );
+ });
+ });
});
diff --git a/spec/javascripts/notes/stores/collapse_utils_spec.js b/spec/javascripts/notes/stores/collapse_utils_spec.js
index 06a6aab932a..8ede9319088 100644
--- a/spec/javascripts/notes/stores/collapse_utils_spec.js
+++ b/spec/javascripts/notes/stores/collapse_utils_spec.js
@@ -4,10 +4,7 @@ import {
getTimeDifferenceMinutes,
collapseSystemNotes,
} from '~/notes/stores/collapse_utils';
-import {
- notesWithDescriptionChanges,
- collapsedSystemNotes,
-} from '../mock_data';
+import { notesWithDescriptionChanges, collapsedSystemNotes } from '../mock_data';
describe('Collapse utils', () => {
const mockSystemNote = {
@@ -22,14 +19,18 @@ describe('Collapse utils', () => {
});
it('returns false when a system note is not a description type', () => {
- expect(isDescriptionSystemNote(Object.assign({}, mockSystemNote, { note: 'foo' }))).toEqual(false);
+ expect(isDescriptionSystemNote(Object.assign({}, mockSystemNote, { note: 'foo' }))).toEqual(
+ false,
+ );
});
it('changes the description to contain the number of changed times', () => {
const changedNote = changeDescriptionNote(mockSystemNote, 3, 5);
expect(changedNote.times_updated).toEqual(3);
- expect(changedNote.note_html.trim()).toContain('<p dir="auto">changed the description 3 times within 5 minutes </p>');
+ expect(changedNote.note_html.trim()).toContain(
+ '<p dir="auto">changed the description 3 times within 5 minutes </p>',
+ );
});
it('gets the time difference between two notes', () => {
diff --git a/spec/javascripts/notes/stores/getters_spec.js b/spec/javascripts/notes/stores/getters_spec.js
index 7f8ede51508..c066975a43b 100644
--- a/spec/javascripts/notes/stores/getters_spec.js
+++ b/spec/javascripts/notes/stores/getters_spec.js
@@ -117,17 +117,15 @@ describe('Getters Notes Store', () => {
describe('allResolvableDiscussions', () => {
it('should return only resolvable discussions in same order', () => {
- const localGetters = {
- allDiscussions: [
- discussion3,
- unresolvableDiscussion,
- discussion1,
- unresolvableDiscussion,
- discussion2,
- ],
- };
+ state.discussions = [
+ discussion3,
+ unresolvableDiscussion,
+ discussion1,
+ unresolvableDiscussion,
+ discussion2,
+ ];
- expect(getters.allResolvableDiscussions(state, localGetters)).toEqual([
+ expect(getters.allResolvableDiscussions(state)).toEqual([
discussion3,
discussion1,
discussion2,
@@ -135,11 +133,9 @@ describe('Getters Notes Store', () => {
});
it('should return empty array if there are no resolvable discussions', () => {
- const localGetters = {
- allDiscussions: [unresolvableDiscussion, unresolvableDiscussion],
- };
+ state.discussions = [unresolvableDiscussion, unresolvableDiscussion];
- expect(getters.allResolvableDiscussions(state, localGetters)).toEqual([]);
+ expect(getters.allResolvableDiscussions(state)).toEqual([]);
});
});
@@ -205,6 +201,7 @@ describe('Getters Notes Store', () => {
'123',
'456',
]);
+
expect(getters.unresolvedDiscussionsIdsOrdered(state, localGetters)(undefined)).toEqual([
'123',
'456',
@@ -235,7 +232,7 @@ describe('Getters Notes Store', () => {
it('should return the ID of the discussion after the ID provided', () => {
expect(getters.nextUnresolvedDiscussionId(state, localGetters)('123')).toBe('456');
expect(getters.nextUnresolvedDiscussionId(state, localGetters)('456')).toBe('789');
- expect(getters.nextUnresolvedDiscussionId(state, localGetters)('789')).toBe(undefined);
+ expect(getters.nextUnresolvedDiscussionId(state, localGetters)('789')).toBe('123');
});
});
diff --git a/spec/javascripts/notes/stores/mutation_spec.js b/spec/javascripts/notes/stores/mutation_spec.js
index 1ecfe914859..1c4449d1055 100644
--- a/spec/javascripts/notes/stores/mutation_spec.js
+++ b/spec/javascripts/notes/stores/mutation_spec.js
@@ -30,11 +30,13 @@ describe('Notes Store mutations', () => {
expect(state).toEqual({
discussions: [noteData],
});
+
expect(state.discussions.length).toBe(1);
});
it('should not add the same note to the notes array', () => {
mutations.ADD_NEW_NOTE(state, note);
+
expect(state.discussions.length).toBe(1);
});
});
@@ -76,7 +78,7 @@ describe('Notes Store mutations', () => {
});
describe('COLLAPSE_DISCUSSION', () => {
- it('should collpase an expanded discussion', () => {
+ it('should collapse an expanded discussion', () => {
const discussion = Object.assign({}, discussionMock, { expanded: true });
const state = {
@@ -106,6 +108,7 @@ describe('Notes Store mutations', () => {
};
mutations.SET_NOTES_DATA(state, notesDataMock);
+
expect(state.notesData).toEqual(notesDataMock);
});
});
@@ -117,6 +120,7 @@ describe('Notes Store mutations', () => {
};
mutations.SET_NOTEABLE_DATA(state, noteableDataMock);
+
expect(state.noteableData).toEqual(noteableDataMock);
});
});
@@ -128,6 +132,7 @@ describe('Notes Store mutations', () => {
};
mutations.SET_USER_DATA(state, userDataMock);
+
expect(state.userData).toEqual(userDataMock);
});
});
@@ -151,6 +156,7 @@ describe('Notes Store mutations', () => {
};
mutations.SET_INITIAL_DISCUSSIONS(state, [note, legacyNote]);
+
expect(state.discussions[0].id).toEqual(note.id);
expect(state.discussions[1].notes[0].note).toBe(legacyNote.notes[0].note);
expect(state.discussions[2].notes[0].note).toBe(legacyNote.notes[1].note);
@@ -200,6 +206,7 @@ describe('Notes Store mutations', () => {
};
mutations.SET_LAST_FETCHED_AT(state, 'timestamp');
+
expect(state.lastFetchedAt).toEqual('timestamp');
});
});
@@ -211,6 +218,7 @@ describe('Notes Store mutations', () => {
};
mutations.SET_TARGET_NOTE_HASH(state, 'hash');
+
expect(state.targetNoteHash).toEqual('hash');
});
});
@@ -221,6 +229,7 @@ describe('Notes Store mutations', () => {
discussions: [],
};
mutations.SHOW_PLACEHOLDER_NOTE(state, note);
+
expect(state.discussions[0].isPlaceholderNote).toEqual(true);
});
});
@@ -261,6 +270,7 @@ describe('Notes Store mutations', () => {
awardName: 'bath_tone3',
};
mutations.TOGGLE_AWARD(state, data);
+
expect(state.discussions[0].award_emoji.length).toEqual(2);
});
});
@@ -316,6 +326,7 @@ describe('Notes Store mutations', () => {
};
mutations.CLOSE_ISSUE(state);
+
expect(state.noteableData.state).toEqual('closed');
});
});
@@ -333,6 +344,7 @@ describe('Notes Store mutations', () => {
};
mutations.REOPEN_ISSUE(state);
+
expect(state.noteableData.state).toEqual('reopened');
});
});
@@ -350,6 +362,7 @@ describe('Notes Store mutations', () => {
};
mutations.TOGGLE_STATE_BUTTON_LOADING(state, true);
+
expect(state.isToggleStateButtonLoading).toEqual(true);
});
@@ -365,6 +378,7 @@ describe('Notes Store mutations', () => {
};
mutations.TOGGLE_STATE_BUTTON_LOADING(state, false);
+
expect(state.isToggleStateButtonLoading).toEqual(false);
});
});
@@ -376,6 +390,7 @@ describe('Notes Store mutations', () => {
};
mutations.SET_NOTES_FETCHED_STATE(state, true);
+
expect(state.isNotesFetched).toEqual(true);
});
});
@@ -412,4 +427,61 @@ describe('Notes Store mutations', () => {
expect(state.discussions[0].expanded).toBe(true);
});
});
+
+ describe('DISABLE_COMMENTS', () => {
+ it('should set comments disabled state', () => {
+ const state = {};
+
+ mutations.DISABLE_COMMENTS(state, true);
+
+ expect(state.commentsDisabled).toEqual(true);
+ });
+ });
+
+ describe('UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS', () => {
+ it('updates resolvableDiscussionsCount', () => {
+ const state = {
+ discussions: [
+ { individual_note: false, resolvable: true, notes: [] },
+ { individual_note: true, resolvable: true, notes: [] },
+ { individual_note: false, resolvable: false, notes: [] },
+ ],
+ resolvableDiscussionsCount: 0,
+ };
+
+ mutations.UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS(state);
+
+ expect(state.resolvableDiscussionsCount).toBe(1);
+ });
+
+ it('updates unresolvedDiscussionsCount', () => {
+ const state = {
+ discussions: [
+ { individual_note: false, resolvable: true, notes: [{ resolved: false }] },
+ { individual_note: true, resolvable: true, notes: [{ resolved: false }] },
+ { individual_note: false, resolvable: false, notes: [{ resolved: false }] },
+ ],
+ unresolvedDiscussionsCount: 0,
+ };
+
+ mutations.UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS(state);
+
+ expect(state.unresolvedDiscussionsCount).toBe(1);
+ });
+
+ it('updates hasUnresolvedDiscussions', () => {
+ const state = {
+ discussions: [
+ { individual_note: false, resolvable: true, notes: [{ resolved: false }] },
+ { individual_note: false, resolvable: true, notes: [{ resolved: false }] },
+ { individual_note: false, resolvable: false, notes: [{ resolved: false }] },
+ ],
+ hasUnresolvedDiscussions: 0,
+ };
+
+ mutations.UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS(state);
+
+ expect(state.hasUnresolvedDiscussions).toBe(true);
+ });
+ });
});
diff --git a/spec/javascripts/notes_spec.js b/spec/javascripts/notes_spec.js
index faeedae40e9..694f581150f 100644
--- a/spec/javascripts/notes_spec.js
+++ b/spec/javascripts/notes_spec.js
@@ -10,1011 +10,1024 @@ import '~/behaviors/markdown/render_gfm';
import Notes from '~/notes';
import timeoutPromise from './helpers/set_timeout_promise_helper';
-(function() {
- window.gon || (window.gon = {});
- window.gl = window.gl || {};
- gl.utils = gl.utils || {};
-
- const htmlEscape = comment => {
- const escapedString = comment.replace(/["&'<>]/g, a => {
- const escapedToken = {
- '&': '&amp;',
- '<': '&lt;',
- '>': '&gt;',
- '"': '&quot;',
- "'": '&#x27;',
- '`': '&#x60;',
- }[a];
-
- return escapedToken;
- });
-
- return escapedString;
- };
-
- describe('Notes', function() {
- const FLASH_TYPE_ALERT = 'alert';
- const NOTES_POST_PATH = /(.*)\/notes\?html=true$/;
- var fixture = 'snippets/show.html.raw';
- preloadFixtures(fixture);
+window.gon || (window.gon = {});
+window.gl = window.gl || {};
+gl.utils = gl.utils || {};
+
+const htmlEscape = comment => {
+ const escapedString = comment.replace(/["&'<>]/g, a => {
+ const escapedToken = {
+ '&': '&amp;',
+ '<': '&lt;',
+ '>': '&gt;',
+ '"': '&quot;',
+ "'": '&#x27;',
+ '`': '&#x60;',
+ }[a];
+
+ return escapedToken;
+ });
- beforeEach(function() {
- loadFixtures(fixture);
- gl.utils.disableButtonIfEmptyField = _.noop;
- window.project_uploads_path = 'http://test.host/uploads';
- $('body').attr('data-page', 'projects:merge_requets:show');
- });
+ return escapedString;
+};
- afterEach(() => {
- // Undo what we did to the shared <body>
- $('body').removeAttr('data-page');
- });
+describe('Notes', function() {
+ const FLASH_TYPE_ALERT = 'alert';
+ const NOTES_POST_PATH = /(.*)\/notes\?html=true$/;
+ var fixture = 'snippets/show.html.raw';
+ preloadFixtures(fixture);
- describe('addBinding', () => {
- it('calls postComment when comment button is clicked', () => {
- spyOn(Notes.prototype, 'postComment');
- this.notes = new Notes('', []);
+ beforeEach(function() {
+ loadFixtures(fixture);
+ gl.utils.disableButtonIfEmptyField = _.noop;
+ window.project_uploads_path = 'http://test.host/uploads';
+ $('body').attr('data-page', 'projects:merge_requets:show');
+ });
- $('.js-comment-button').click();
+ afterEach(() => {
+ // Undo what we did to the shared <body>
+ $('body').removeAttr('data-page');
+ });
- expect(Notes.prototype.postComment).toHaveBeenCalled();
- });
+ describe('addBinding', () => {
+ it('calls postComment when comment button is clicked', () => {
+ spyOn(Notes.prototype, 'postComment');
+ this.notes = new Notes('', []);
+
+ $('.js-comment-button').click();
+
+ expect(Notes.prototype.postComment).toHaveBeenCalled();
});
+ });
- describe('task lists', function() {
- let mock;
+ describe('task lists', function() {
+ let mock;
- beforeEach(function() {
- spyOn(axios, 'patch').and.callFake(() => new Promise(() => {}));
- mock = new MockAdapter(axios);
- mock.onAny().reply(200, {});
+ beforeEach(function() {
+ spyOn(axios, 'patch').and.callFake(() => new Promise(() => {}));
+ mock = new MockAdapter(axios);
+ mock.onAny().reply(200, {});
- $('.js-comment-button').on('click', function(e) {
- e.preventDefault();
- });
- this.notes = new Notes('', []);
+ $('.js-comment-button').on('click', function(e) {
+ e.preventDefault();
});
+ this.notes = new Notes('', []);
+ });
- afterEach(() => {
- mock.restore();
- });
+ afterEach(() => {
+ mock.restore();
+ });
- it('modifies the Markdown field', function() {
- const changeEvent = document.createEvent('HTMLEvents');
- changeEvent.initEvent('change', true, true);
- $('input[type=checkbox]')
- .attr('checked', true)[0]
- .dispatchEvent(changeEvent);
+ it('modifies the Markdown field', function() {
+ const changeEvent = document.createEvent('HTMLEvents');
+ changeEvent.initEvent('change', true, true);
+ $('input[type=checkbox]')
+ .attr('checked', true)[0]
+ .dispatchEvent(changeEvent);
- expect($('.js-task-list-field.original-task-list').val()).toBe('- [x] Task List Item');
- });
+ expect($('.js-task-list-field.original-task-list').val()).toBe('- [x] Task List Item');
+ });
- it('submits an ajax request on tasklist:changed', function(done) {
- $('.js-task-list-container').trigger('tasklist:changed');
+ it('submits an ajax request on tasklist:changed', function(done) {
+ $('.js-task-list-container').trigger('tasklist:changed');
- setTimeout(() => {
- expect(axios.patch).toHaveBeenCalled();
- done();
- });
+ setTimeout(() => {
+ expect(axios.patch).toHaveBeenCalled();
+ done();
});
});
+ });
- describe('comments', function() {
- var textarea = '.js-note-text';
+ describe('comments', function() {
+ var textarea = '.js-note-text';
- beforeEach(function() {
- this.notes = new Notes('', []);
+ beforeEach(function() {
+ this.notes = new Notes('', []);
- this.autoSizeSpy = spyOnEvent($(textarea), 'autosize:update');
- spyOn(this.notes, 'renderNote').and.stub();
+ this.autoSizeSpy = spyOnEvent($(textarea), 'autosize:update');
+ spyOn(this.notes, 'renderNote').and.stub();
- $(textarea).data('autosave', {
- reset: function() {},
- });
+ $(textarea).data('autosave', {
+ reset: function() {},
+ });
- $('.js-comment-button').on('click', e => {
- const $form = $(this);
- e.preventDefault();
- this.notes.addNote($form);
- this.notes.reenableTargetFormSubmitButton(e);
- this.notes.resetMainTargetForm(e);
- });
+ $('.js-comment-button').on('click', e => {
+ const $form = $(this);
+ e.preventDefault();
+ this.notes.addNote($form);
+ this.notes.reenableTargetFormSubmitButton(e);
+ this.notes.resetMainTargetForm(e);
});
+ });
- it('autosizes after comment submission', function() {
- $(textarea).text('This is an example comment note');
- expect(this.autoSizeSpy).not.toHaveBeenTriggered();
+ it('autosizes after comment submission', function() {
+ $(textarea).text('This is an example comment note');
- $('.js-comment-button').click();
- expect(this.autoSizeSpy).toHaveBeenTriggered();
- });
+ expect(this.autoSizeSpy).not.toHaveBeenTriggered();
- it('should not place escaped text in the comment box in case of error', function() {
- const deferred = $.Deferred();
- spyOn($, 'ajax').and.returnValue(deferred.promise());
- $(textarea).text('A comment with `markup`.');
+ $('.js-comment-button').click();
- deferred.reject();
- $('.js-comment-button').click();
- expect($(textarea).val()).toEqual('A comment with `markup`.');
- });
+ expect(this.autoSizeSpy).toHaveBeenTriggered();
});
- describe('updateNote', () => {
- let sampleComment;
- let noteEntity;
- let $form;
- let $notesContainer;
- let mock;
+ it('should not place escaped text in the comment box in case of error', function() {
+ const deferred = $.Deferred();
+ spyOn($, 'ajax').and.returnValue(deferred.promise());
+ $(textarea).text('A comment with `markup`.');
- beforeEach(() => {
- this.notes = new Notes('', []);
- window.gon.current_username = 'root';
- window.gon.current_user_fullname = 'Administrator';
- sampleComment = 'foo';
- noteEntity = {
- id: 1234,
- html: `<li class="note note-row-1234 timeline-entry" id="note_1234">
- <div class="note-text">${sampleComment}</div>
- </li>`,
- note: sampleComment,
- valid: true,
- };
- $form = $('form.js-main-target-form');
- $notesContainer = $('ul.main-notes-list');
- $form.find('textarea.js-note-text').val(sampleComment);
+ deferred.reject();
+ $('.js-comment-button').click();
- mock = new MockAdapter(axios);
- mock.onPost(NOTES_POST_PATH).reply(200, noteEntity);
- });
+ expect($(textarea).val()).toEqual('A comment with `markup`.');
+ });
+ });
- afterEach(() => {
- mock.restore();
- });
+ describe('updateNote', () => {
+ let sampleComment;
+ let noteEntity;
+ let $form;
+ let $notesContainer;
+ let mock;
+
+ beforeEach(() => {
+ this.notes = new Notes('', []);
+ window.gon.current_username = 'root';
+ window.gon.current_user_fullname = 'Administrator';
+ sampleComment = 'foo';
+ noteEntity = {
+ id: 1234,
+ html: `<li class="note note-row-1234 timeline-entry" id="note_1234">
+ <div class="note-text">${sampleComment}</div>
+ </li>`,
+ note: sampleComment,
+ valid: true,
+ };
+ $form = $('form.js-main-target-form');
+ $notesContainer = $('ul.main-notes-list');
+ $form.find('textarea.js-note-text').val(sampleComment);
+
+ mock = new MockAdapter(axios);
+ mock.onPost(NOTES_POST_PATH).reply(200, noteEntity);
+ });
- it('updates note and resets edit form', done => {
- spyOn(this.notes, 'revertNoteEditForm');
- spyOn(this.notes, 'setupNewNote');
+ afterEach(() => {
+ mock.restore();
+ });
- $('.js-comment-button').click();
+ it('updates note and resets edit form', done => {
+ spyOn(this.notes, 'revertNoteEditForm');
+ spyOn(this.notes, 'setupNewNote');
- setTimeout(() => {
- const $targetNote = $notesContainer.find(`#note_${noteEntity.id}`);
- const updatedNote = Object.assign({}, noteEntity);
- updatedNote.note = 'bar';
- this.notes.updateNote(updatedNote, $targetNote);
+ $('.js-comment-button').click();
- expect(this.notes.revertNoteEditForm).toHaveBeenCalledWith($targetNote);
- expect(this.notes.setupNewNote).toHaveBeenCalled();
+ setTimeout(() => {
+ const $targetNote = $notesContainer.find(`#note_${noteEntity.id}`);
+ const updatedNote = Object.assign({}, noteEntity);
+ updatedNote.note = 'bar';
+ this.notes.updateNote(updatedNote, $targetNote);
- done();
- });
+ expect(this.notes.revertNoteEditForm).toHaveBeenCalledWith($targetNote);
+ expect(this.notes.setupNewNote).toHaveBeenCalled();
+
+ done();
});
});
+ });
- describe('updateNoteTargetSelector', () => {
- const hash = 'note_foo';
- let $note;
+ describe('updateNoteTargetSelector', () => {
+ const hash = 'note_foo';
+ let $note;
- beforeEach(() => {
- $note = $(`<div id="${hash}"></div>`);
- spyOn($note, 'filter').and.callThrough();
- spyOn($note, 'toggleClass').and.callThrough();
- });
+ beforeEach(() => {
+ $note = $(`<div id="${hash}"></div>`);
+ spyOn($note, 'filter').and.callThrough();
+ spyOn($note, 'toggleClass').and.callThrough();
+ });
- it('sets target when hash matches', () => {
- spyOnDependency(Notes, 'getLocationHash').and.returnValue(hash);
+ it('sets target when hash matches', () => {
+ spyOnDependency(Notes, 'getLocationHash').and.returnValue(hash);
- Notes.updateNoteTargetSelector($note);
+ Notes.updateNoteTargetSelector($note);
- expect($note.filter).toHaveBeenCalledWith(`#${hash}`);
- expect($note.toggleClass).toHaveBeenCalledWith('target', true);
- });
+ expect($note.filter).toHaveBeenCalledWith(`#${hash}`);
+ expect($note.toggleClass).toHaveBeenCalledWith('target', true);
+ });
- it('unsets target when hash does not match', () => {
- spyOnDependency(Notes, 'getLocationHash').and.returnValue('note_doesnotexist');
+ it('unsets target when hash does not match', () => {
+ spyOnDependency(Notes, 'getLocationHash').and.returnValue('note_doesnotexist');
- Notes.updateNoteTargetSelector($note);
+ Notes.updateNoteTargetSelector($note);
- expect($note.toggleClass).toHaveBeenCalledWith('target', false);
- });
+ expect($note.toggleClass).toHaveBeenCalledWith('target', false);
+ });
- it('unsets target when there is not a hash fragment anymore', () => {
- spyOnDependency(Notes, 'getLocationHash').and.returnValue(null);
+ it('unsets target when there is not a hash fragment anymore', () => {
+ spyOnDependency(Notes, 'getLocationHash').and.returnValue(null);
- Notes.updateNoteTargetSelector($note);
+ Notes.updateNoteTargetSelector($note);
- expect($note.toggleClass).toHaveBeenCalledWith('target', false);
- });
+ expect($note.toggleClass).toHaveBeenCalledWith('target', false);
});
+ });
- describe('renderNote', () => {
- let notes;
- let note;
- let $notesList;
+ describe('renderNote', () => {
+ let notes;
+ let note;
+ let $notesList;
- beforeEach(() => {
- note = {
- id: 1,
- valid: true,
- note: 'heya',
- html: '<div>heya</div>',
- };
- $notesList = jasmine.createSpyObj('$notesList', ['find', 'append']);
-
- notes = jasmine.createSpyObj('notes', [
- 'setupNewNote',
- 'refresh',
- 'collapseLongCommitList',
- 'updateNotesCount',
- 'putConflictEditWarningInPlace',
- ]);
- notes.taskList = jasmine.createSpyObj('tasklist', ['init']);
- notes.note_ids = [];
- notes.updatedNotesTrackingMap = {};
-
- spyOn(Notes, 'isNewNote').and.callThrough();
- spyOn(Notes, 'isUpdatedNote').and.callThrough();
- spyOn(Notes, 'animateAppendNote').and.callThrough();
- spyOn(Notes, 'animateUpdateNote').and.callThrough();
+ beforeEach(() => {
+ note = {
+ id: 1,
+ valid: true,
+ note: 'heya',
+ html: '<div>heya</div>',
+ };
+ $notesList = jasmine.createSpyObj('$notesList', ['find', 'append']);
+
+ notes = jasmine.createSpyObj('notes', [
+ 'setupNewNote',
+ 'refresh',
+ 'collapseLongCommitList',
+ 'updateNotesCount',
+ 'putConflictEditWarningInPlace',
+ ]);
+ notes.taskList = jasmine.createSpyObj('tasklist', ['init']);
+ notes.note_ids = [];
+ notes.updatedNotesTrackingMap = {};
+
+ spyOn(Notes, 'isNewNote').and.callThrough();
+ spyOn(Notes, 'isUpdatedNote').and.callThrough();
+ spyOn(Notes, 'animateAppendNote').and.callThrough();
+ spyOn(Notes, 'animateUpdateNote').and.callThrough();
+ });
+
+ describe('when adding note', () => {
+ it('should call .animateAppendNote', () => {
+ Notes.isNewNote.and.returnValue(true);
+ Notes.prototype.renderNote.call(notes, note, null, $notesList);
+
+ expect(Notes.animateAppendNote).toHaveBeenCalledWith(note.html, $notesList);
});
+ });
- describe('when adding note', () => {
- it('should call .animateAppendNote', () => {
- Notes.isNewNote.and.returnValue(true);
- Notes.prototype.renderNote.call(notes, note, null, $notesList);
+ describe('when note was edited', () => {
+ it('should call .animateUpdateNote', () => {
+ Notes.isNewNote.and.returnValue(false);
+ Notes.isUpdatedNote.and.returnValue(true);
+ const $note = $('<div>');
+ $notesList.find.and.returnValue($note);
+ const $newNote = $(note.html);
+ Notes.animateUpdateNote.and.returnValue($newNote);
- expect(Notes.animateAppendNote).toHaveBeenCalledWith(note.html, $notesList);
- });
+ Notes.prototype.renderNote.call(notes, note, null, $notesList);
+
+ expect(Notes.animateUpdateNote).toHaveBeenCalledWith(note.html, $note);
+ expect(notes.setupNewNote).toHaveBeenCalledWith($newNote);
});
- describe('when note was edited', () => {
- it('should call .animateUpdateNote', () => {
+ describe('while editing', () => {
+ it('should update textarea if nothing has been touched', () => {
Notes.isNewNote.and.returnValue(false);
Notes.isUpdatedNote.and.returnValue(true);
- const $note = $('<div>');
+ const $note = $(`<div class="is-editing">
+ <div class="original-note-content">initial</div>
+ <textarea class="js-note-text">initial</textarea>
+ </div>`);
$notesList.find.and.returnValue($note);
- const $newNote = $(note.html);
- Notes.animateUpdateNote.and.returnValue($newNote);
-
Notes.prototype.renderNote.call(notes, note, null, $notesList);
- expect(Notes.animateUpdateNote).toHaveBeenCalledWith(note.html, $note);
- expect(notes.setupNewNote).toHaveBeenCalledWith($newNote);
+ expect($note.find('.js-note-text').val()).toEqual(note.note);
});
- describe('while editing', () => {
- it('should update textarea if nothing has been touched', () => {
- Notes.isNewNote.and.returnValue(false);
- Notes.isUpdatedNote.and.returnValue(true);
- const $note = $(`<div class="is-editing">
- <div class="original-note-content">initial</div>
- <textarea class="js-note-text">initial</textarea>
- </div>`);
- $notesList.find.and.returnValue($note);
- Notes.prototype.renderNote.call(notes, note, null, $notesList);
-
- expect($note.find('.js-note-text').val()).toEqual(note.note);
- });
-
- it('should call .putConflictEditWarningInPlace', () => {
- Notes.isNewNote.and.returnValue(false);
- Notes.isUpdatedNote.and.returnValue(true);
- const $note = $(`<div class="is-editing">
- <div class="original-note-content">initial</div>
- <textarea class="js-note-text">different</textarea>
- </div>`);
- $notesList.find.and.returnValue($note);
- Notes.prototype.renderNote.call(notes, note, null, $notesList);
-
- expect(notes.putConflictEditWarningInPlace).toHaveBeenCalledWith(note, $note);
- });
+ it('should call .putConflictEditWarningInPlace', () => {
+ Notes.isNewNote.and.returnValue(false);
+ Notes.isUpdatedNote.and.returnValue(true);
+ const $note = $(`<div class="is-editing">
+ <div class="original-note-content">initial</div>
+ <textarea class="js-note-text">different</textarea>
+ </div>`);
+ $notesList.find.and.returnValue($note);
+ Notes.prototype.renderNote.call(notes, note, null, $notesList);
+
+ expect(notes.putConflictEditWarningInPlace).toHaveBeenCalledWith(note, $note);
});
});
});
+ });
- describe('isUpdatedNote', () => {
- it('should consider same note text as the same', () => {
- const result = Notes.isUpdatedNote(
- {
- note: 'initial',
- },
- $(`<div>
- <div class="original-note-content">initial</div>
- </div>`),
- );
+ describe('isUpdatedNote', () => {
+ it('should consider same note text as the same', () => {
+ const result = Notes.isUpdatedNote(
+ {
+ note: 'initial',
+ },
+ $(`<div>
+ <div class="original-note-content">initial</div>
+ </div>`),
+ );
- expect(result).toEqual(false);
- });
+ expect(result).toEqual(false);
+ });
- it('should consider same note with trailing newline as the same', () => {
- const result = Notes.isUpdatedNote(
- {
- note: 'initial\n',
- },
- $(`<div>
- <div class="original-note-content">initial\n</div>
- </div>`),
- );
+ it('should consider same note with trailing newline as the same', () => {
+ const result = Notes.isUpdatedNote(
+ {
+ note: 'initial\n',
+ },
+ $(`<div>
+ <div class="original-note-content">initial\n</div>
+ </div>`),
+ );
- expect(result).toEqual(false);
- });
+ expect(result).toEqual(false);
+ });
- it('should consider different notes as different', () => {
- const result = Notes.isUpdatedNote(
- {
- note: 'foo',
- },
- $(`<div>
- <div class="original-note-content">bar</div>
- </div>`),
- );
+ it('should consider different notes as different', () => {
+ const result = Notes.isUpdatedNote(
+ {
+ note: 'foo',
+ },
+ $(`<div>
+ <div class="original-note-content">bar</div>
+ </div>`),
+ );
- expect(result).toEqual(true);
- });
+ expect(result).toEqual(true);
+ });
+ });
+
+ describe('renderDiscussionNote', () => {
+ let discussionContainer;
+ let note;
+ let notes;
+ let $form;
+ let row;
+
+ beforeEach(() => {
+ note = {
+ html: '<li></li>',
+ discussion_html: '<div></div>',
+ discussion_id: 1,
+ discussion_resolvable: false,
+ diff_discussion_html: false,
+ };
+ $form = jasmine.createSpyObj('$form', ['closest', 'find']);
+ $form.length = 1;
+ row = jasmine.createSpyObj('row', ['prevAll', 'first', 'find']);
+
+ notes = jasmine.createSpyObj('notes', ['isParallelView', 'updateNotesCount']);
+ notes.note_ids = [];
+
+ spyOn(Notes, 'isNewNote');
+ spyOn(Notes, 'animateAppendNote');
+ Notes.isNewNote.and.returnValue(true);
+ notes.isParallelView.and.returnValue(false);
+ row.prevAll.and.returnValue(row);
+ row.first.and.returnValue(row);
+ row.find.and.returnValue(row);
});
- describe('renderDiscussionNote', () => {
- let discussionContainer;
- let note;
- let notes;
- let $form;
- let row;
+ describe('Discussion root note', () => {
+ let body;
beforeEach(() => {
- note = {
- html: '<li></li>',
- discussion_html: '<div></div>',
- discussion_id: 1,
- discussion_resolvable: false,
- diff_discussion_html: false,
- };
- $form = jasmine.createSpyObj('$form', ['closest', 'find']);
- $form.length = 1;
- row = jasmine.createSpyObj('row', ['prevAll', 'first', 'find']);
-
- notes = jasmine.createSpyObj('notes', ['isParallelView', 'updateNotesCount']);
- notes.note_ids = [];
+ body = jasmine.createSpyObj('body', ['attr']);
+ discussionContainer = { length: 0 };
- spyOn(Notes, 'isNewNote');
- spyOn(Notes, 'animateAppendNote');
- Notes.isNewNote.and.returnValue(true);
- notes.isParallelView.and.returnValue(false);
- row.prevAll.and.returnValue(row);
- row.first.and.returnValue(row);
- row.find.and.returnValue(row);
+ $form.closest.and.returnValues(row, $form);
+ $form.find.and.returnValues(discussionContainer);
+ body.attr.and.returnValue('');
});
- describe('Discussion root note', () => {
- let body;
-
- beforeEach(() => {
- body = jasmine.createSpyObj('body', ['attr']);
- discussionContainer = { length: 0 };
+ it('should call Notes.animateAppendNote', () => {
+ Notes.prototype.renderDiscussionNote.call(notes, note, $form);
- $form.closest.and.returnValues(row, $form);
- $form.find.and.returnValues(discussionContainer);
- body.attr.and.returnValue('');
- });
-
- it('should call Notes.animateAppendNote', () => {
- Notes.prototype.renderDiscussionNote.call(notes, note, $form);
-
- expect(Notes.animateAppendNote).toHaveBeenCalledWith(
- note.discussion_html,
- $('.main-notes-list'),
- );
- });
+ expect(Notes.animateAppendNote).toHaveBeenCalledWith(
+ note.discussion_html,
+ $('.main-notes-list'),
+ );
+ });
- it('should append to row selected with line_code', () => {
- $form.length = 0;
- note.discussion_line_code = 'line_code';
- note.diff_discussion_html = '<tr></tr>';
+ it('should append to row selected with line_code', () => {
+ $form.length = 0;
+ note.discussion_line_code = 'line_code';
+ note.diff_discussion_html = '<tr></tr>';
- const line = document.createElement('div');
- line.id = note.discussion_line_code;
- document.body.appendChild(line);
+ const line = document.createElement('div');
+ line.id = note.discussion_line_code;
+ document.body.appendChild(line);
- $form.closest.and.returnValues($form);
+ $form.closest.and.returnValues($form);
- Notes.prototype.renderDiscussionNote.call(notes, note, $form);
+ Notes.prototype.renderDiscussionNote.call(notes, note, $form);
- expect(line.nextSibling.outerHTML).toEqual(note.diff_discussion_html);
- });
+ expect(line.nextSibling.outerHTML).toEqual(note.diff_discussion_html);
});
+ });
- describe('Discussion sub note', () => {
- beforeEach(() => {
- discussionContainer = { length: 1 };
+ describe('Discussion sub note', () => {
+ beforeEach(() => {
+ discussionContainer = { length: 1 };
- $form.closest.and.returnValues(row, $form);
- $form.find.and.returnValues(discussionContainer);
+ $form.closest.and.returnValues(row, $form);
+ $form.find.and.returnValues(discussionContainer);
- Notes.prototype.renderDiscussionNote.call(notes, note, $form);
- });
+ Notes.prototype.renderDiscussionNote.call(notes, note, $form);
+ });
- it('should call Notes.animateAppendNote', () => {
- expect(Notes.animateAppendNote).toHaveBeenCalledWith(note.html, discussionContainer);
- });
+ it('should call Notes.animateAppendNote', () => {
+ expect(Notes.animateAppendNote).toHaveBeenCalledWith(note.html, discussionContainer);
});
});
+ });
- describe('animateAppendNote', () => {
- let noteHTML;
- let $notesList;
- let $resultantNote;
+ describe('animateAppendNote', () => {
+ let noteHTML;
+ let $notesList;
+ let $resultantNote;
- beforeEach(() => {
- noteHTML = '<div></div>';
- $notesList = jasmine.createSpyObj('$notesList', ['append']);
+ beforeEach(() => {
+ noteHTML = '<div></div>';
+ $notesList = jasmine.createSpyObj('$notesList', ['append']);
- $resultantNote = Notes.animateAppendNote(noteHTML, $notesList);
- });
+ $resultantNote = Notes.animateAppendNote(noteHTML, $notesList);
+ });
- it('should have `fade-in-full` class', () => {
- expect($resultantNote.hasClass('fade-in-full')).toEqual(true);
- });
+ it('should have `fade-in-full` class', () => {
+ expect($resultantNote.hasClass('fade-in-full')).toEqual(true);
+ });
- it('should append note to the notes list', () => {
- expect($notesList.append).toHaveBeenCalledWith($resultantNote);
- });
+ it('should append note to the notes list', () => {
+ expect($notesList.append).toHaveBeenCalledWith($resultantNote);
});
+ });
- describe('animateUpdateNote', () => {
- let noteHTML;
- let $note;
- let $updatedNote;
+ describe('animateUpdateNote', () => {
+ let noteHTML;
+ let $note;
+ let $updatedNote;
- beforeEach(() => {
- noteHTML = '<div></div>';
- $note = jasmine.createSpyObj('$note', ['replaceWith']);
+ beforeEach(() => {
+ noteHTML = '<div></div>';
+ $note = jasmine.createSpyObj('$note', ['replaceWith']);
- $updatedNote = Notes.animateUpdateNote(noteHTML, $note);
- });
+ $updatedNote = Notes.animateUpdateNote(noteHTML, $note);
+ });
- it('should have `fade-in` class', () => {
- expect($updatedNote.hasClass('fade-in')).toEqual(true);
- });
+ it('should have `fade-in` class', () => {
+ expect($updatedNote.hasClass('fade-in')).toEqual(true);
+ });
- it('should call replaceWith on $note', () => {
- expect($note.replaceWith).toHaveBeenCalledWith($updatedNote);
- });
+ it('should call replaceWith on $note', () => {
+ expect($note.replaceWith).toHaveBeenCalledWith($updatedNote);
});
+ });
- describe('putEditFormInPlace', () => {
- it('should call GLForm with GFM parameter passed through', () => {
- const notes = new Notes('', []);
- const $el = $(`
- <div>
- <form></form>
- </div>
- `);
+ describe('putEditFormInPlace', () => {
+ it('should call GLForm with GFM parameter passed through', () => {
+ const notes = new Notes('', []);
+ const $el = $(`
+ <div>
+ <form></form>
+ </div>
+ `);
- notes.putEditFormInPlace($el);
+ notes.putEditFormInPlace($el);
- expect(notes.glForm.enableGFM).toBeTruthy();
- });
+ expect(notes.glForm.enableGFM).toBeTruthy();
});
+ });
- describe('postComment & updateComment', () => {
- const sampleComment = 'foo';
- const updatedComment = 'bar';
- const note = {
- id: 1234,
- html: `<li class="note note-row-1234 timeline-entry" id="note_1234">
- <div class="note-text">${sampleComment}</div>
- </li>`,
- note: sampleComment,
- valid: true,
- };
- let $form;
- let $notesContainer;
- let mock;
+ describe('postComment & updateComment', () => {
+ const sampleComment = 'foo';
+ const updatedComment = 'bar';
+ const note = {
+ id: 1234,
+ html: `<li class="note note-row-1234 timeline-entry" id="note_1234">
+ <div class="note-text">${sampleComment}</div>
+ </li>`,
+ note: sampleComment,
+ valid: true,
+ };
+ let $form;
+ let $notesContainer;
+ let mock;
+
+ function mockNotesPost() {
+ mock.onPost(NOTES_POST_PATH).reply(200, note);
+ }
+
+ function mockNotesPostError() {
+ mock.onPost(NOTES_POST_PATH).networkError();
+ }
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+
+ this.notes = new Notes('', []);
+ window.gon.current_username = 'root';
+ window.gon.current_user_fullname = 'Administrator';
+ $form = $('form.js-main-target-form');
+ $notesContainer = $('ul.main-notes-list');
+ $form.find('textarea.js-note-text').val(sampleComment);
+ });
- function mockNotesPost() {
- mock.onPost(NOTES_POST_PATH).reply(200, note);
- }
+ afterEach(() => {
+ mock.restore();
+ });
- function mockNotesPostError() {
- mock.onPost(NOTES_POST_PATH).networkError();
- }
+ it('should show placeholder note while new comment is being posted', () => {
+ mockNotesPost();
- beforeEach(() => {
- mock = new MockAdapter(axios);
-
- this.notes = new Notes('', []);
- window.gon.current_username = 'root';
- window.gon.current_user_fullname = 'Administrator';
- $form = $('form.js-main-target-form');
- $notesContainer = $('ul.main-notes-list');
- $form.find('textarea.js-note-text').val(sampleComment);
- });
+ $('.js-comment-button').click();
- afterEach(() => {
- mock.restore();
- });
+ expect($notesContainer.find('.note.being-posted').length).toBeGreaterThan(0);
+ });
- it('should show placeholder note while new comment is being posted', () => {
- mockNotesPost();
+ it('should remove placeholder note when new comment is done posting', done => {
+ mockNotesPost();
- $('.js-comment-button').click();
- expect($notesContainer.find('.note.being-posted').length > 0).toEqual(true);
- });
+ $('.js-comment-button').click();
- it('should remove placeholder note when new comment is done posting', done => {
- mockNotesPost();
+ setTimeout(() => {
+ expect($notesContainer.find('.note.being-posted').length).toEqual(0);
- $('.js-comment-button').click();
+ done();
+ });
+ });
- setTimeout(() => {
- expect($notesContainer.find('.note.being-posted').length).toEqual(0);
+ describe('postComment', () => {
+ it('disables the submit button', done => {
+ const $submitButton = $form.find('.js-comment-submit-button');
- done();
+ expect($submitButton).not.toBeDisabled();
+ const dummyEvent = {
+ preventDefault() {},
+ target: $submitButton,
+ };
+ mock.onPost(NOTES_POST_PATH).replyOnce(() => {
+ expect($submitButton).toBeDisabled();
+ return [200, note];
});
- });
- describe('postComment', () => {
- it('disables the submit button', done => {
- const $submitButton = $form.find('.js-comment-submit-button');
- expect($submitButton).not.toBeDisabled();
- const dummyEvent = {
- preventDefault() {},
- target: $submitButton,
- };
- mock.onPost(NOTES_POST_PATH).replyOnce(() => {
- expect($submitButton).toBeDisabled();
- return [200, note];
- });
-
- this.notes
- .postComment(dummyEvent)
- .then(() => {
- expect($submitButton).not.toBeDisabled();
- })
- .then(done)
- .catch(done.fail);
- });
+ this.notes
+ .postComment(dummyEvent)
+ .then(() => {
+ expect($submitButton).not.toBeDisabled();
+ })
+ .then(done)
+ .catch(done.fail);
});
+ });
- it('should show actual note element when new comment is done posting', done => {
- mockNotesPost();
+ it('should show actual note element when new comment is done posting', done => {
+ mockNotesPost();
- $('.js-comment-button').click();
+ $('.js-comment-button').click();
- setTimeout(() => {
- expect($notesContainer.find(`#note_${note.id}`).length > 0).toEqual(true);
+ setTimeout(() => {
+ expect($notesContainer.find(`#note_${note.id}`).length).toBeGreaterThan(0);
- done();
- });
+ done();
});
+ });
- it('should reset Form when new comment is done posting', done => {
- mockNotesPost();
+ it('should reset Form when new comment is done posting', done => {
+ mockNotesPost();
- $('.js-comment-button').click();
+ $('.js-comment-button').click();
- setTimeout(() => {
- expect($form.find('textarea.js-note-text').val()).toEqual('');
+ setTimeout(() => {
+ expect($form.find('textarea.js-note-text').val()).toEqual('');
- done();
- });
+ done();
});
+ });
- it('should show flash error message when new comment failed to be posted', done => {
- mockNotesPostError();
+ it('should show flash error message when new comment failed to be posted', done => {
+ mockNotesPostError();
- $('.js-comment-button').click();
+ $('.js-comment-button').click();
- setTimeout(() => {
- expect(
- $notesContainer
- .parent()
- .find('.flash-container .flash-text')
- .is(':visible'),
- ).toEqual(true);
+ setTimeout(() => {
+ expect(
+ $notesContainer
+ .parent()
+ .find('.flash-container .flash-text')
+ .is(':visible'),
+ ).toEqual(true);
- done();
- });
+ done();
});
+ });
- it('should show flash error message when comment failed to be updated', done => {
- mockNotesPost();
+ it('should show flash error message when comment failed to be updated', done => {
+ mockNotesPost();
- $('.js-comment-button').click();
+ $('.js-comment-button').click();
- timeoutPromise()
- .then(() => {
- const $noteEl = $notesContainer.find(`#note_${note.id}`);
- $noteEl.find('.js-note-edit').click();
- $noteEl.find('textarea.js-note-text').val(updatedComment);
+ timeoutPromise()
+ .then(() => {
+ const $noteEl = $notesContainer.find(`#note_${note.id}`);
+ $noteEl.find('.js-note-edit').click();
+ $noteEl.find('textarea.js-note-text').val(updatedComment);
- mock.restore();
+ mock.restore();
- mockNotesPostError();
+ mockNotesPostError();
- $noteEl.find('.js-comment-save-button').click();
- })
- .then(timeoutPromise)
- .then(() => {
- const $updatedNoteEl = $notesContainer.find(`#note_${note.id}`);
- expect($updatedNoteEl.hasClass('.being-posted')).toEqual(false); // Remove being-posted visuals
- expect(
- $updatedNoteEl
- .find('.note-text')
- .text()
- .trim(),
- ).toEqual(sampleComment); // See if comment reverted back to original
- expect($('.flash-container').is(':visible')).toEqual(true); // Flash error message shown
-
- done();
- })
- .catch(done.fail);
- });
+ $noteEl.find('.js-comment-save-button').click();
+ })
+ .then(timeoutPromise)
+ .then(() => {
+ const $updatedNoteEl = $notesContainer.find(`#note_${note.id}`);
+
+ expect($updatedNoteEl.hasClass('.being-posted')).toEqual(false); // Remove being-posted visuals
+ expect(
+ $updatedNoteEl
+ .find('.note-text')
+ .text()
+ .trim(),
+ ).toEqual(sampleComment); // See if comment reverted back to original
+
+ expect($('.flash-container').is(':visible')).toEqual(true); // Flash error message shown
+
+ done();
+ })
+ .catch(done.fail);
});
+ });
- describe('postComment with Slash commands', () => {
- const sampleComment = '/assign @root\n/award :100:';
- const note = {
- commands_changes: {
- assignee_id: 1,
- emoji_award: '100',
- },
- errors: {
- commands_only: ['Commands applied'],
+ describe('postComment with Slash commands', () => {
+ const sampleComment = '/assign @root\n/award :100:';
+ const note = {
+ commands_changes: {
+ assignee_id: 1,
+ emoji_award: '100',
+ },
+ errors: {
+ commands_only: ['Commands applied'],
+ },
+ valid: false,
+ };
+ let $form;
+ let $notesContainer;
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ mock.onPost(NOTES_POST_PATH).reply(200, note);
+
+ this.notes = new Notes('', []);
+ window.gon.current_username = 'root';
+ window.gon.current_user_fullname = 'Administrator';
+ gl.awardsHandler = {
+ addAwardToEmojiBar: () => {},
+ scrollToAwards: () => {},
+ };
+ gl.GfmAutoComplete = {
+ dataSources: {
+ commands: '/root/test-project/autocomplete_sources/commands',
},
- valid: false,
};
- let $form;
- let $notesContainer;
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- mock.onPost(NOTES_POST_PATH).reply(200, note);
-
- this.notes = new Notes('', []);
- window.gon.current_username = 'root';
- window.gon.current_user_fullname = 'Administrator';
- gl.awardsHandler = {
- addAwardToEmojiBar: () => {},
- scrollToAwards: () => {},
- };
- gl.GfmAutoComplete = {
- dataSources: {
- commands: '/root/test-project/autocomplete_sources/commands',
- },
- };
- $form = $('form.js-main-target-form');
- $notesContainer = $('ul.main-notes-list');
- $form.find('textarea.js-note-text').val(sampleComment);
- });
+ $form = $('form.js-main-target-form');
+ $notesContainer = $('ul.main-notes-list');
+ $form.find('textarea.js-note-text').val(sampleComment);
+ });
- afterEach(() => {
- mock.restore();
- });
+ afterEach(() => {
+ mock.restore();
+ });
- it('should remove slash command placeholder when comment with slash commands is done posting', done => {
- spyOn(gl.awardsHandler, 'addAwardToEmojiBar').and.callThrough();
- $('.js-comment-button').click();
+ it('should remove slash command placeholder when comment with slash commands is done posting', done => {
+ spyOn(gl.awardsHandler, 'addAwardToEmojiBar').and.callThrough();
+ $('.js-comment-button').click();
- expect($notesContainer.find('.system-note.being-posted').length).toEqual(1); // Placeholder shown
+ expect($notesContainer.find('.system-note.being-posted').length).toEqual(1); // Placeholder shown
- setTimeout(() => {
- expect($notesContainer.find('.system-note.being-posted').length).toEqual(0); // Placeholder removed
- done();
- });
+ setTimeout(() => {
+ expect($notesContainer.find('.system-note.being-posted').length).toEqual(0); // Placeholder removed
+ done();
});
});
+ });
- describe('update comment with script tags', () => {
- const sampleComment = '<script></script>';
- const updatedComment = '<script></script>';
- const note = {
- id: 1234,
- html: `<li class="note note-row-1234 timeline-entry" id="note_1234">
- <div class="note-text">${sampleComment}</div>
- </li>`,
- note: sampleComment,
- valid: true,
- };
- let $form;
- let $notesContainer;
- let mock;
+ describe('update comment with script tags', () => {
+ const sampleComment = '<script></script>';
+ const updatedComment = '<script></script>';
+ const note = {
+ id: 1234,
+ html: `<li class="note note-row-1234 timeline-entry" id="note_1234">
+ <div class="note-text">${sampleComment}</div>
+ </li>`,
+ note: sampleComment,
+ valid: true,
+ };
+ let $form;
+ let $notesContainer;
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ mock.onPost(NOTES_POST_PATH).reply(200, note);
+
+ this.notes = new Notes('', []);
+ window.gon.current_username = 'root';
+ window.gon.current_user_fullname = 'Administrator';
+ $form = $('form.js-main-target-form');
+ $notesContainer = $('ul.main-notes-list');
+ $form.find('textarea.js-note-text').html(sampleComment);
+ });
- beforeEach(() => {
- mock = new MockAdapter(axios);
- mock.onPost(NOTES_POST_PATH).reply(200, note);
-
- this.notes = new Notes('', []);
- window.gon.current_username = 'root';
- window.gon.current_user_fullname = 'Administrator';
- $form = $('form.js-main-target-form');
- $notesContainer = $('ul.main-notes-list');
- $form.find('textarea.js-note-text').html(sampleComment);
- });
+ afterEach(() => {
+ mock.restore();
+ });
- afterEach(() => {
- mock.restore();
- });
+ it('should not render a script tag', done => {
+ $('.js-comment-button').click();
- it('should not render a script tag', done => {
- $('.js-comment-button').click();
+ setTimeout(() => {
+ const $noteEl = $notesContainer.find(`#note_${note.id}`);
+ $noteEl.find('.js-note-edit').click();
+ $noteEl.find('textarea.js-note-text').html(updatedComment);
+ $noteEl.find('.js-comment-save-button').click();
- setTimeout(() => {
- const $noteEl = $notesContainer.find(`#note_${note.id}`);
- $noteEl.find('.js-note-edit').click();
- $noteEl.find('textarea.js-note-text').html(updatedComment);
- $noteEl.find('.js-comment-save-button').click();
+ const $updatedNoteEl = $notesContainer
+ .find(`#note_${note.id}`)
+ .find('.js-task-list-container');
- const $updatedNoteEl = $notesContainer
- .find(`#note_${note.id}`)
- .find('.js-task-list-container');
- expect(
- $updatedNoteEl
- .find('.note-text')
- .text()
- .trim(),
- ).toEqual('');
+ expect(
+ $updatedNoteEl
+ .find('.note-text')
+ .text()
+ .trim(),
+ ).toEqual('');
- done();
- });
+ done();
});
});
+ });
- describe('getFormData', () => {
- let $form;
- let sampleComment;
+ describe('getFormData', () => {
+ let $form;
+ let sampleComment;
- beforeEach(() => {
- this.notes = new Notes('', []);
+ beforeEach(() => {
+ this.notes = new Notes('', []);
- $form = $('form');
- sampleComment = 'foobar';
- });
+ $form = $('form');
+ sampleComment = 'foobar';
+ });
- it('should return form metadata object from form reference', () => {
- $form.find('textarea.js-note-text').val(sampleComment);
- const { formData, formContent, formAction } = this.notes.getFormData($form);
+ it('should return form metadata object from form reference', () => {
+ $form.find('textarea.js-note-text').val(sampleComment);
+ const { formData, formContent, formAction } = this.notes.getFormData($form);
- expect(formData.indexOf(sampleComment) > -1).toBe(true);
- expect(formContent).toEqual(sampleComment);
- expect(formAction).toEqual($form.attr('action'));
- });
+ expect(formData.indexOf(sampleComment)).toBeGreaterThan(-1);
+ expect(formContent).toEqual(sampleComment);
+ expect(formAction).toEqual($form.attr('action'));
+ });
- it('should return form metadata with sanitized formContent from form reference', () => {
- spyOn(_, 'escape').and.callFake(htmlEscape);
+ it('should return form metadata with sanitized formContent from form reference', () => {
+ spyOn(_, 'escape').and.callFake(htmlEscape);
- sampleComment = '<script>alert("Boom!");</script>';
- $form.find('textarea.js-note-text').val(sampleComment);
+ sampleComment = '<script>alert("Boom!");</script>';
+ $form.find('textarea.js-note-text').val(sampleComment);
- const { formContent } = this.notes.getFormData($form);
+ const { formContent } = this.notes.getFormData($form);
- expect(_.escape).toHaveBeenCalledWith(sampleComment);
- expect(formContent).toEqual('&lt;script&gt;alert(&quot;Boom!&quot;);&lt;/script&gt;');
- });
+ expect(_.escape).toHaveBeenCalledWith(sampleComment);
+ expect(formContent).toEqual('&lt;script&gt;alert(&quot;Boom!&quot;);&lt;/script&gt;');
});
+ });
- describe('hasQuickActions', () => {
- beforeEach(() => {
- this.notes = new Notes('', []);
- });
+ describe('hasQuickActions', () => {
+ beforeEach(() => {
+ this.notes = new Notes('', []);
+ });
- it('should return true when comment begins with a quick action', () => {
- const sampleComment = '/wip\n/milestone %1.0\n/merge\n/unassign Merging this';
- const hasQuickActions = this.notes.hasQuickActions(sampleComment);
+ it('should return true when comment begins with a quick action', () => {
+ const sampleComment = '/wip\n/milestone %1.0\n/merge\n/unassign Merging this';
+ const hasQuickActions = this.notes.hasQuickActions(sampleComment);
- expect(hasQuickActions).toBeTruthy();
- });
+ expect(hasQuickActions).toBeTruthy();
+ });
- it('should return false when comment does NOT begin with a quick action', () => {
- const sampleComment = 'Hey, /unassign Merging this';
- const hasQuickActions = this.notes.hasQuickActions(sampleComment);
+ it('should return false when comment does NOT begin with a quick action', () => {
+ const sampleComment = 'Hey, /unassign Merging this';
+ const hasQuickActions = this.notes.hasQuickActions(sampleComment);
- expect(hasQuickActions).toBeFalsy();
- });
+ expect(hasQuickActions).toBeFalsy();
+ });
- it('should return false when comment does NOT have any quick actions', () => {
- const sampleComment = 'Looking good, Awesome!';
- const hasQuickActions = this.notes.hasQuickActions(sampleComment);
+ it('should return false when comment does NOT have any quick actions', () => {
+ const sampleComment = 'Looking good, Awesome!';
+ const hasQuickActions = this.notes.hasQuickActions(sampleComment);
- expect(hasQuickActions).toBeFalsy();
- });
+ expect(hasQuickActions).toBeFalsy();
});
+ });
- describe('stripQuickActions', () => {
- it('should strip quick actions from the comment which begins with a quick action', () => {
- this.notes = new Notes();
- const sampleComment = '/wip\n/milestone %1.0\n/merge\n/unassign Merging this';
- const stripedComment = this.notes.stripQuickActions(sampleComment);
+ describe('stripQuickActions', () => {
+ it('should strip quick actions from the comment which begins with a quick action', () => {
+ this.notes = new Notes();
+ const sampleComment = '/wip\n/milestone %1.0\n/merge\n/unassign Merging this';
+ const stripedComment = this.notes.stripQuickActions(sampleComment);
- expect(stripedComment).toBe('');
- });
+ expect(stripedComment).toBe('');
+ });
- it('should strip quick actions from the comment but leaves plain comment if it is present', () => {
- this.notes = new Notes();
- const sampleComment = '/wip\n/milestone %1.0\n/merge\n/unassign\nMerging this';
- const stripedComment = this.notes.stripQuickActions(sampleComment);
+ it('should strip quick actions from the comment but leaves plain comment if it is present', () => {
+ this.notes = new Notes();
+ const sampleComment = '/wip\n/milestone %1.0\n/merge\n/unassign\nMerging this';
+ const stripedComment = this.notes.stripQuickActions(sampleComment);
- expect(stripedComment).toBe('Merging this');
- });
+ expect(stripedComment).toBe('Merging this');
+ });
- it('should NOT strip string that has slashes within', () => {
- this.notes = new Notes();
- const sampleComment = 'http://127.0.0.1:3000/root/gitlab-shell/issues/1';
- const stripedComment = this.notes.stripQuickActions(sampleComment);
+ it('should NOT strip string that has slashes within', () => {
+ this.notes = new Notes();
+ const sampleComment = 'http://127.0.0.1:3000/root/gitlab-shell/issues/1';
+ const stripedComment = this.notes.stripQuickActions(sampleComment);
- expect(stripedComment).toBe(sampleComment);
- });
+ expect(stripedComment).toBe(sampleComment);
});
+ });
- describe('getQuickActionDescription', () => {
- const availableQuickActions = [
- { name: 'close', description: 'Close this issue', params: [] },
- { name: 'title', description: 'Change title', params: [{}] },
- { name: 'estimate', description: 'Set time estimate', params: [{}] },
- ];
+ describe('getQuickActionDescription', () => {
+ const availableQuickActions = [
+ { name: 'close', description: 'Close this issue', params: [] },
+ { name: 'title', description: 'Change title', params: [{}] },
+ { name: 'estimate', description: 'Set time estimate', params: [{}] },
+ ];
- beforeEach(() => {
- this.notes = new Notes();
- });
+ beforeEach(() => {
+ this.notes = new Notes();
+ });
- it('should return executing quick action description when note has single quick action', () => {
- const sampleComment = '/close';
- expect(this.notes.getQuickActionDescription(sampleComment, availableQuickActions)).toBe(
- 'Applying command to close this issue',
- );
- });
+ it('should return executing quick action description when note has single quick action', () => {
+ const sampleComment = '/close';
- it('should return generic multiple quick action description when note has multiple quick actions', () => {
- const sampleComment = '/close\n/title [Duplicate] Issue foobar';
- expect(this.notes.getQuickActionDescription(sampleComment, availableQuickActions)).toBe(
- 'Applying multiple commands',
- );
- });
+ expect(this.notes.getQuickActionDescription(sampleComment, availableQuickActions)).toBe(
+ 'Applying command to close this issue',
+ );
+ });
- it('should return generic quick action description when available quick actions list is not populated', () => {
- const sampleComment = '/close\n/title [Duplicate] Issue foobar';
- expect(this.notes.getQuickActionDescription(sampleComment)).toBe('Applying command');
- });
+ it('should return generic multiple quick action description when note has multiple quick actions', () => {
+ const sampleComment = '/close\n/title [Duplicate] Issue foobar';
+
+ expect(this.notes.getQuickActionDescription(sampleComment, availableQuickActions)).toBe(
+ 'Applying multiple commands',
+ );
});
- describe('createPlaceholderNote', () => {
- const sampleComment = 'foobar';
- const uniqueId = 'b1234-a4567';
- const currentUsername = 'root';
- const currentUserFullname = 'Administrator';
- const currentUserAvatar = 'avatar_url';
+ it('should return generic quick action description when available quick actions list is not populated', () => {
+ const sampleComment = '/close\n/title [Duplicate] Issue foobar';
- beforeEach(() => {
- this.notes = new Notes('', []);
- });
+ expect(this.notes.getQuickActionDescription(sampleComment)).toBe('Applying command');
+ });
+ });
- it('should return constructed placeholder element for regular note based on form contents', () => {
- const $tempNote = this.notes.createPlaceholderNote({
- formContent: sampleComment,
- uniqueId,
- isDiscussionNote: false,
- currentUsername,
- currentUserFullname,
- currentUserAvatar,
- });
- const $tempNoteHeader = $tempNote.find('.note-header');
-
- expect($tempNote.prop('nodeName')).toEqual('LI');
- expect($tempNote.attr('id')).toEqual(uniqueId);
- expect($tempNote.hasClass('being-posted')).toBeTruthy();
- expect($tempNote.hasClass('fade-in-half')).toBeTruthy();
- $tempNote.find('.timeline-icon > a, .note-header-info > a').each(function() {
- expect($(this).attr('href')).toEqual(`/${currentUsername}`);
- });
- expect($tempNote.find('.timeline-icon .avatar').attr('src')).toEqual(currentUserAvatar);
- expect($tempNote.find('.timeline-content').hasClass('discussion')).toBeFalsy();
- expect(
- $tempNoteHeader
- .find('.d-none.d-sm-inline-block')
- .text()
- .trim(),
- ).toEqual(currentUserFullname);
- expect(
- $tempNoteHeader
- .find('.note-headline-light')
- .text()
- .trim(),
- ).toEqual(`@${currentUsername}`);
- expect(
- $tempNote
- .find('.note-body .note-text p')
- .text()
- .trim(),
- ).toEqual(sampleComment);
- });
+ describe('createPlaceholderNote', () => {
+ const sampleComment = 'foobar';
+ const uniqueId = 'b1234-a4567';
+ const currentUsername = 'root';
+ const currentUserFullname = 'Administrator';
+ const currentUserAvatar = 'avatar_url';
- it('should return constructed placeholder element for discussion note based on form contents', () => {
- const $tempNote = this.notes.createPlaceholderNote({
- formContent: sampleComment,
- uniqueId,
- isDiscussionNote: true,
- currentUsername,
- currentUserFullname,
- });
+ beforeEach(() => {
+ this.notes = new Notes('', []);
+ });
- expect($tempNote.prop('nodeName')).toEqual('LI');
- expect($tempNote.find('.timeline-content').hasClass('discussion')).toBeTruthy();
- });
+ it('should return constructed placeholder element for regular note based on form contents', () => {
+ const $tempNote = this.notes.createPlaceholderNote({
+ formContent: sampleComment,
+ uniqueId,
+ isDiscussionNote: false,
+ currentUsername,
+ currentUserFullname,
+ currentUserAvatar,
+ });
+ const $tempNoteHeader = $tempNote.find('.note-header');
+
+ expect($tempNote.prop('nodeName')).toEqual('LI');
+ expect($tempNote.attr('id')).toEqual(uniqueId);
+ expect($tempNote.hasClass('being-posted')).toBeTruthy();
+ expect($tempNote.hasClass('fade-in-half')).toBeTruthy();
+ $tempNote.find('.timeline-icon > a, .note-header-info > a').each(function() {
+ expect($(this).attr('href')).toEqual(`/${currentUsername}`);
+ });
+
+ expect($tempNote.find('.timeline-icon .avatar').attr('src')).toEqual(currentUserAvatar);
+ expect($tempNote.find('.timeline-content').hasClass('discussion')).toBeFalsy();
+ expect(
+ $tempNoteHeader
+ .find('.d-none.d-sm-inline-block')
+ .text()
+ .trim(),
+ ).toEqual(currentUserFullname);
+
+ expect(
+ $tempNoteHeader
+ .find('.note-headline-light')
+ .text()
+ .trim(),
+ ).toEqual(`@${currentUsername}`);
+
+ expect(
+ $tempNote
+ .find('.note-body .note-text p')
+ .text()
+ .trim(),
+ ).toEqual(sampleComment);
+ });
- it('should return a escaped user name', () => {
- const currentUserFullnameXSS = 'Foo <script>alert("XSS")</script>';
- const $tempNote = this.notes.createPlaceholderNote({
- formContent: sampleComment,
- uniqueId,
- isDiscussionNote: false,
- currentUsername,
- currentUserFullname: currentUserFullnameXSS,
- currentUserAvatar,
- });
- const $tempNoteHeader = $tempNote.find('.note-header');
- expect(
- $tempNoteHeader
- .find('.d-none.d-sm-inline-block')
- .text()
- .trim(),
- ).toEqual('Foo &lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;');
+ it('should return constructed placeholder element for discussion note based on form contents', () => {
+ const $tempNote = this.notes.createPlaceholderNote({
+ formContent: sampleComment,
+ uniqueId,
+ isDiscussionNote: true,
+ currentUsername,
+ currentUserFullname,
});
+
+ expect($tempNote.prop('nodeName')).toEqual('LI');
+ expect($tempNote.find('.timeline-content').hasClass('discussion')).toBeTruthy();
});
- describe('createPlaceholderSystemNote', () => {
- const sampleCommandDescription = 'Applying command to close this issue';
- const uniqueId = 'b1234-a4567';
+ it('should return a escaped user name', () => {
+ const currentUserFullnameXSS = 'Foo <script>alert("XSS")</script>';
+ const $tempNote = this.notes.createPlaceholderNote({
+ formContent: sampleComment,
+ uniqueId,
+ isDiscussionNote: false,
+ currentUsername,
+ currentUserFullname: currentUserFullnameXSS,
+ currentUserAvatar,
+ });
+ const $tempNoteHeader = $tempNote.find('.note-header');
+
+ expect(
+ $tempNoteHeader
+ .find('.d-none.d-sm-inline-block')
+ .text()
+ .trim(),
+ ).toEqual('Foo &lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;');
+ });
+ });
- beforeEach(() => {
- this.notes = new Notes('', []);
- spyOn(_, 'escape').and.callFake(htmlEscape);
- });
+ describe('createPlaceholderSystemNote', () => {
+ const sampleCommandDescription = 'Applying command to close this issue';
+ const uniqueId = 'b1234-a4567';
- it('should return constructed placeholder element for system note based on form contents', () => {
- const $tempNote = this.notes.createPlaceholderSystemNote({
- formContent: sampleCommandDescription,
- uniqueId,
- });
+ beforeEach(() => {
+ this.notes = new Notes('', []);
+ spyOn(_, 'escape').and.callFake(htmlEscape);
+ });
- expect($tempNote.prop('nodeName')).toEqual('LI');
- expect($tempNote.attr('id')).toEqual(uniqueId);
- expect($tempNote.hasClass('being-posted')).toBeTruthy();
- expect($tempNote.hasClass('fade-in-half')).toBeTruthy();
- expect(
- $tempNote
- .find('.timeline-content i')
- .text()
- .trim(),
- ).toEqual(sampleCommandDescription);
- });
+ it('should return constructed placeholder element for system note based on form contents', () => {
+ const $tempNote = this.notes.createPlaceholderSystemNote({
+ formContent: sampleCommandDescription,
+ uniqueId,
+ });
+
+ expect($tempNote.prop('nodeName')).toEqual('LI');
+ expect($tempNote.attr('id')).toEqual(uniqueId);
+ expect($tempNote.hasClass('being-posted')).toBeTruthy();
+ expect($tempNote.hasClass('fade-in-half')).toBeTruthy();
+ expect(
+ $tempNote
+ .find('.timeline-content i')
+ .text()
+ .trim(),
+ ).toEqual(sampleCommandDescription);
});
+ });
- describe('appendFlash', () => {
- beforeEach(() => {
- this.notes = new Notes();
- });
+ describe('appendFlash', () => {
+ beforeEach(() => {
+ this.notes = new Notes();
+ });
- it('shows a flash message', () => {
- this.notes.addFlash('Error message', FLASH_TYPE_ALERT, this.notes.parentTimeline.get(0));
+ it('shows a flash message', () => {
+ this.notes.addFlash('Error message', FLASH_TYPE_ALERT, this.notes.parentTimeline.get(0));
- expect($('.flash-alert').is(':visible')).toBeTruthy();
- });
+ expect($('.flash-alert').is(':visible')).toBeTruthy();
});
+ });
- describe('clearFlash', () => {
- beforeEach(() => {
- $(document).off('ajax:success');
- this.notes = new Notes();
- });
+ describe('clearFlash', () => {
+ beforeEach(() => {
+ $(document).off('ajax:success');
+ this.notes = new Notes();
+ });
- it('hides visible flash message', () => {
- this.notes.addFlash('Error message 1', FLASH_TYPE_ALERT, this.notes.parentTimeline.get(0));
+ it('hides visible flash message', () => {
+ this.notes.addFlash('Error message 1', FLASH_TYPE_ALERT, this.notes.parentTimeline.get(0));
- this.notes.clearFlash();
+ this.notes.clearFlash();
- expect($('.flash-alert').is(':visible')).toBeFalsy();
- });
+ expect($('.flash-alert').is(':visible')).toBeFalsy();
});
});
-}.call(window));
+});
diff --git a/spec/javascripts/oauth_remember_me_spec.js b/spec/javascripts/oauth_remember_me_spec.js
index 8816fe6defb..2caa266b85f 100644
--- a/spec/javascripts/oauth_remember_me_spec.js
+++ b/spec/javascripts/oauth_remember_me_spec.js
@@ -13,8 +13,13 @@ describe('OAuthRememberMe', () => {
it('adds the "remember_me" query parameter to all OAuth login buttons', () => {
$('#oauth-container #remember_me').click();
- expect($('#oauth-container .oauth-login.twitter').attr('href')).toBe('http://example.com/?remember_me=1');
- expect($('#oauth-container .oauth-login.github').attr('href')).toBe('http://example.com/?remember_me=1');
+ expect($('#oauth-container .oauth-login.twitter').attr('href')).toBe(
+ 'http://example.com/?remember_me=1',
+ );
+
+ expect($('#oauth-container .oauth-login.github').attr('href')).toBe(
+ 'http://example.com/?remember_me=1',
+ );
});
it('removes the "remember_me" query parameter from all OAuth login buttons', () => {
diff --git a/spec/javascripts/pager_spec.js b/spec/javascripts/pager_spec.js
index 04f2e7ef4f9..93efc139254 100644
--- a/spec/javascripts/pager_spec.js
+++ b/spec/javascripts/pager_spec.js
@@ -30,6 +30,7 @@ describe('pager', () => {
const href = `${gl.TEST_HOST}/some_list.json`;
setFixtures(`<div class="content_list" data-href="${href}"></div>`);
Pager.init();
+
expect(Pager.url).toBe(href);
});
@@ -37,12 +38,14 @@ describe('pager', () => {
const href = `${gl.TEST_HOST}/some_list`;
spyOnDependency(Pager, 'removeParams').and.returnValue(href);
Pager.init();
+
expect(Pager.url).toBe(href);
});
it('should get initial offset from query parameter', () => {
window.history.replaceState({}, null, '?offset=100');
Pager.init();
+
expect(Pager.offset).toBe(100);
});
@@ -51,6 +54,7 @@ describe('pager', () => {
const href = `${gl.TEST_HOST}/some_list?filter=test`;
const removeParams = spyOnDependency(Pager, 'removeParams').and.returnValue(href);
Pager.init();
+
expect(removeParams).toHaveBeenCalledWith(['limit', 'offset']);
expect(Pager.url).toEqual(href);
});
@@ -132,6 +136,7 @@ describe('pager', () => {
offset: 100,
},
});
+
expect(url).toBe('/some_list');
done();
diff --git a/spec/javascripts/pages/admin/abuse_reports/abuse_reports_spec.js b/spec/javascripts/pages/admin/abuse_reports/abuse_reports_spec.js
index b0dc6ccc3d4..23d07056925 100644
--- a/spec/javascripts/pages/admin/abuse_reports/abuse_reports_spec.js
+++ b/spec/javascripts/pages/admin/abuse_reports/abuse_reports_spec.js
@@ -8,14 +8,15 @@ describe('Abuse Reports', () => {
let $messages;
- const assertMaxLength = $message => expect($message.text().length).toEqual(MAX_MESSAGE_LENGTH);
- const findMessage = searchText => $messages.filter(
- (index, element) => element.innerText.indexOf(searchText) > -1,
- ).first();
+ const assertMaxLength = $message => {
+ expect($message.text().length).toEqual(MAX_MESSAGE_LENGTH);
+ };
+ const findMessage = searchText =>
+ $messages.filter((index, element) => element.innerText.indexOf(searchText) > -1).first();
preloadFixtures(FIXTURE);
- beforeEach(function () {
+ beforeEach(function() {
loadFixtures(FIXTURE);
this.abuseReports = new AbuseReports();
$messages = $('.abuse-reports .message');
@@ -23,18 +24,21 @@ describe('Abuse Reports', () => {
it('should truncate long messages', () => {
const $longMessage = findMessage('LONG MESSAGE');
+
expect($longMessage.data('originalMessage')).toEqual(jasmine.anything());
assertMaxLength($longMessage);
});
it('should not truncate short messages', () => {
const $shortMessage = findMessage('SHORT MESSAGE');
+
expect($shortMessage.data('originalMessage')).not.toEqual(jasmine.anything());
});
it('should allow clicking a truncated message to expand and collapse the full message', () => {
const $longMessage = findMessage('LONG MESSAGE');
$longMessage.click();
+
expect($longMessage.data('originalMessage').length).toEqual($longMessage.text().length);
$longMessage.click();
assertMaxLength($longMessage);
diff --git a/spec/javascripts/pages/admin/application_settings/account_and_limits_spec.js b/spec/javascripts/pages/admin/application_settings/account_and_limits_spec.js
index 4dbfd8f0eaa..561bd2c96cb 100644
--- a/spec/javascripts/pages/admin/application_settings/account_and_limits_spec.js
+++ b/spec/javascripts/pages/admin/application_settings/account_and_limits_spec.js
@@ -1,6 +1,8 @@
import $ from 'jquery';
-import initUserInternalRegexPlaceholder, { PLACEHOLDER_USER_EXTERNAL_DEFAULT_FALSE,
- PLACEHOLDER_USER_EXTERNAL_DEFAULT_TRUE } from '~/pages/admin/application_settings/account_and_limits';
+import initUserInternalRegexPlaceholder, {
+ PLACEHOLDER_USER_EXTERNAL_DEFAULT_FALSE,
+ PLACEHOLDER_USER_EXTERNAL_DEFAULT_TRUE,
+} from '~/pages/admin/application_settings/account_and_limits';
describe('AccountAndLimits', () => {
const FIXTURE = 'application_settings/accounts_and_limit.html.raw';
@@ -22,8 +24,9 @@ describe('AccountAndLimits', () => {
expect($userInternalRegex.readOnly).toBeTruthy();
});
- it('is checked', (done) => {
+ it('is checked', done => {
if (!$userDefaultExternal.prop('checked')) $userDefaultExternal.click();
+
expect($userDefaultExternal.prop('checked')).toBeTruthy();
expect($userInternalRegex.placeholder).toEqual(PLACEHOLDER_USER_EXTERNAL_DEFAULT_TRUE);
expect($userInternalRegex.readOnly).toBeFalsy();
diff --git a/spec/javascripts/pages/admin/jobs/index/components/stop_jobs_modal_spec.js b/spec/javascripts/pages/admin/jobs/index/components/stop_jobs_modal_spec.js
index b69e5f9a3a0..6bfb3f5ca21 100644
--- a/spec/javascripts/pages/admin/jobs/index/components/stop_jobs_modal_spec.js
+++ b/spec/javascripts/pages/admin/jobs/index/components/stop_jobs_modal_spec.js
@@ -21,10 +21,10 @@ describe('stop_jobs_modal.vue', () => {
});
describe('onSubmit', () => {
- it('stops jobs and redirects to overview page', (done) => {
+ it('stops jobs and redirects to overview page', done => {
const responseURL = `${gl.TEST_HOST}/stop_jobs_modal.vue/jobs`;
const redirectSpy = spyOnDependency(stopJobsModal, 'redirectTo');
- spyOn(axios, 'post').and.callFake((url) => {
+ spyOn(axios, 'post').and.callFake(url => {
expect(url).toBe(props.url);
return Promise.resolve({
request: {
@@ -34,24 +34,24 @@ describe('stop_jobs_modal.vue', () => {
});
vm.onSubmit()
- .then(() => {
- expect(redirectSpy).toHaveBeenCalledWith(responseURL);
- })
- .then(done)
- .catch(done.fail);
+ .then(() => {
+ expect(redirectSpy).toHaveBeenCalledWith(responseURL);
+ })
+ .then(done)
+ .catch(done.fail);
});
- it('displays error if stopping jobs failed', (done) => {
+ it('displays error if stopping jobs failed', done => {
const dummyError = new Error('stopping jobs failed');
const redirectSpy = spyOnDependency(stopJobsModal, 'redirectTo');
- spyOn(axios, 'post').and.callFake((url) => {
+ spyOn(axios, 'post').and.callFake(url => {
expect(url).toBe(props.url);
return Promise.reject(dummyError);
});
vm.onSubmit()
.then(done.fail)
- .catch((error) => {
+ .catch(error => {
expect(error).toBe(dummyError);
expect(redirectSpy).not.toHaveBeenCalled();
})
diff --git a/spec/javascripts/pages/admin/users/new/index_spec.js b/spec/javascripts/pages/admin/users/new/index_spec.js
index 2bac3951c3a..5a849f34bc3 100644
--- a/spec/javascripts/pages/admin/users/new/index_spec.js
+++ b/spec/javascripts/pages/admin/users/new/index_spec.js
@@ -20,7 +20,7 @@ describe('UserInternalRegexHandler', () => {
});
describe('Behaviour of userExternal checkbox when', () => {
- it('matches email as internal', (done) => {
+ it('matches email as internal', done => {
expect($warningMessage.hasClass('hidden')).toBeTruthy();
$userEmail.val('test@').trigger('input');
@@ -30,7 +30,7 @@ describe('UserInternalRegexHandler', () => {
done();
});
- it('matches email as external', (done) => {
+ it('matches email as external', done => {
expect($warningMessage.hasClass('hidden')).toBeTruthy();
$userEmail.val('test.ext@').trigger('input');
diff --git a/spec/javascripts/pages/labels/components/promote_label_modal_spec.js b/spec/javascripts/pages/labels/components/promote_label_modal_spec.js
index a24f8204fe1..08a8362797b 100644
--- a/spec/javascripts/pages/labels/components/promote_label_modal_spec.js
+++ b/spec/javascripts/pages/labels/components/promote_label_modal_spec.js
@@ -25,7 +25,11 @@ describe('Promote label modal', () => {
});
it('contains the proper description', () => {
- expect(vm.text).toContain(`Promoting ${labelMockData.labelTitle} will make it available for all projects inside ${labelMockData.groupName}`);
+ expect(vm.text).toContain(
+ `Promoting ${labelMockData.labelTitle} will make it available for all projects inside ${
+ labelMockData.groupName
+ }`,
+ );
});
it('contains a label span with the color', () => {
@@ -48,11 +52,14 @@ describe('Promote label modal', () => {
vm.$destroy();
});
- it('redirects when a label is promoted', (done) => {
+ it('redirects when a label is promoted', done => {
const responseURL = `${gl.TEST_HOST}/dummy/endpoint`;
- spyOn(axios, 'post').and.callFake((url) => {
+ spyOn(axios, 'post').and.callFake(url => {
expect(url).toBe(labelMockData.url);
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestStarted', labelMockData.url);
+ expect(eventHub.$emit).toHaveBeenCalledWith(
+ 'promoteLabelModal.requestStarted',
+ labelMockData.url,
+ );
return Promise.resolve({
request: {
responseURL,
@@ -62,25 +69,34 @@ describe('Promote label modal', () => {
vm.onSubmit()
.then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', { labelUrl: labelMockData.url, successful: true });
+ expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', {
+ labelUrl: labelMockData.url,
+ successful: true,
+ });
})
.then(done)
.catch(done.fail);
});
- it('displays an error if promoting a label failed', (done) => {
+ it('displays an error if promoting a label failed', done => {
const dummyError = new Error('promoting label failed');
dummyError.response = { status: 500 };
- spyOn(axios, 'post').and.callFake((url) => {
+ spyOn(axios, 'post').and.callFake(url => {
expect(url).toBe(labelMockData.url);
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestStarted', labelMockData.url);
+ expect(eventHub.$emit).toHaveBeenCalledWith(
+ 'promoteLabelModal.requestStarted',
+ labelMockData.url,
+ );
return Promise.reject(dummyError);
});
vm.onSubmit()
- .catch((error) => {
+ .catch(error => {
expect(error).toBe(dummyError);
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', { labelUrl: labelMockData.url, successful: false });
+ expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', {
+ labelUrl: labelMockData.url,
+ successful: false,
+ });
})
.then(done)
.catch(done.fail);
diff --git a/spec/javascripts/pages/milestones/shared/components/delete_milestone_modal_spec.js b/spec/javascripts/pages/milestones/shared/components/delete_milestone_modal_spec.js
index 94401beb5c9..fe293083e4c 100644
--- a/spec/javascripts/pages/milestones/shared/components/delete_milestone_modal_spec.js
+++ b/spec/javascripts/pages/milestones/shared/components/delete_milestone_modal_spec.js
@@ -27,11 +27,14 @@ describe('delete_milestone_modal.vue', () => {
spyOn(eventHub, '$emit');
});
- it('deletes milestone and redirects to overview page', (done) => {
+ it('deletes milestone and redirects to overview page', done => {
const responseURL = `${gl.TEST_HOST}/delete_milestone_modal.vue/milestoneOverview`;
- spyOn(axios, 'delete').and.callFake((url) => {
+ spyOn(axios, 'delete').and.callFake(url => {
expect(url).toBe(props.milestoneUrl);
- expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestStarted', props.milestoneUrl);
+ expect(eventHub.$emit).toHaveBeenCalledWith(
+ 'deleteMilestoneModal.requestStarted',
+ props.milestoneUrl,
+ );
eventHub.$emit.calls.reset();
return Promise.resolve({
request: {
@@ -42,30 +45,39 @@ describe('delete_milestone_modal.vue', () => {
const redirectSpy = spyOnDependency(deleteMilestoneModal, 'redirectTo');
vm.onSubmit()
- .then(() => {
- expect(redirectSpy).toHaveBeenCalledWith(responseURL);
- expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', { milestoneUrl: props.milestoneUrl, successful: true });
- })
- .then(done)
- .catch(done.fail);
+ .then(() => {
+ expect(redirectSpy).toHaveBeenCalledWith(responseURL);
+ expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', {
+ milestoneUrl: props.milestoneUrl,
+ successful: true,
+ });
+ })
+ .then(done)
+ .catch(done.fail);
});
- it('displays error if deleting milestone failed', (done) => {
+ it('displays error if deleting milestone failed', done => {
const dummyError = new Error('deleting milestone failed');
dummyError.response = { status: 418 };
- spyOn(axios, 'delete').and.callFake((url) => {
+ spyOn(axios, 'delete').and.callFake(url => {
expect(url).toBe(props.milestoneUrl);
- expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestStarted', props.milestoneUrl);
+ expect(eventHub.$emit).toHaveBeenCalledWith(
+ 'deleteMilestoneModal.requestStarted',
+ props.milestoneUrl,
+ );
eventHub.$emit.calls.reset();
return Promise.reject(dummyError);
});
const redirectSpy = spyOnDependency(deleteMilestoneModal, 'redirectTo');
vm.onSubmit()
- .catch((error) => {
+ .catch(error => {
expect(error).toBe(dummyError);
expect(redirectSpy).not.toHaveBeenCalled();
- expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', { milestoneUrl: props.milestoneUrl, successful: false });
+ expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', {
+ milestoneUrl: props.milestoneUrl,
+ successful: false,
+ });
})
.then(done)
.catch(done.fail);
@@ -81,7 +93,8 @@ describe('delete_milestone_modal.vue', () => {
});
it('contains neither issue nor milestone count', () => {
- vm = mountComponent(Component, { ...props,
+ vm = mountComponent(Component, {
+ ...props,
issueCount: 0,
mergeRequestCount: 0,
});
diff --git a/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js b/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js
index 8b220423637..2ac73ef3024 100644
--- a/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js
+++ b/spec/javascripts/pages/milestones/shared/components/promote_milestone_modal_spec.js
@@ -23,7 +23,11 @@ describe('Promote milestone modal', () => {
});
it('contains the proper description', () => {
- expect(vm.text).toContain(`Promoting ${milestoneMockData.milestoneTitle} will make it available for all projects inside ${milestoneMockData.groupName}.`);
+ expect(vm.text).toContain(
+ `Promoting ${
+ milestoneMockData.milestoneTitle
+ } will make it available for all projects inside ${milestoneMockData.groupName}.`,
+ );
});
it('contains the correct title', () => {
@@ -43,11 +47,14 @@ describe('Promote milestone modal', () => {
vm.$destroy();
});
- it('redirects when a milestone is promoted', (done) => {
+ it('redirects when a milestone is promoted', done => {
const responseURL = `${gl.TEST_HOST}/dummy/endpoint`;
- spyOn(axios, 'post').and.callFake((url) => {
+ spyOn(axios, 'post').and.callFake(url => {
expect(url).toBe(milestoneMockData.url);
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteMilestoneModal.requestStarted', milestoneMockData.url);
+ expect(eventHub.$emit).toHaveBeenCalledWith(
+ 'promoteMilestoneModal.requestStarted',
+ milestoneMockData.url,
+ );
return Promise.resolve({
request: {
responseURL,
@@ -57,25 +64,34 @@ describe('Promote milestone modal', () => {
vm.onSubmit()
.then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteMilestoneModal.requestFinished', { milestoneUrl: milestoneMockData.url, successful: true });
+ expect(eventHub.$emit).toHaveBeenCalledWith('promoteMilestoneModal.requestFinished', {
+ milestoneUrl: milestoneMockData.url,
+ successful: true,
+ });
})
.then(done)
.catch(done.fail);
});
- it('displays an error if promoting a milestone failed', (done) => {
+ it('displays an error if promoting a milestone failed', done => {
const dummyError = new Error('promoting milestone failed');
dummyError.response = { status: 500 };
- spyOn(axios, 'post').and.callFake((url) => {
+ spyOn(axios, 'post').and.callFake(url => {
expect(url).toBe(milestoneMockData.url);
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteMilestoneModal.requestStarted', milestoneMockData.url);
+ expect(eventHub.$emit).toHaveBeenCalledWith(
+ 'promoteMilestoneModal.requestStarted',
+ milestoneMockData.url,
+ );
return Promise.reject(dummyError);
});
vm.onSubmit()
- .catch((error) => {
+ .catch(error => {
expect(error).toBe(dummyError);
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteMilestoneModal.requestFinished', { milestoneUrl: milestoneMockData.url, successful: false });
+ expect(eventHub.$emit).toHaveBeenCalledWith('promoteMilestoneModal.requestFinished', {
+ milestoneUrl: milestoneMockData.url,
+ successful: false,
+ });
})
.then(done)
.catch(done.fail);
diff --git a/spec/javascripts/pages/profiles/show/emoji_menu_spec.js b/spec/javascripts/pages/profiles/show/emoji_menu_spec.js
index b70368fc92f..864bda65736 100644
--- a/spec/javascripts/pages/profiles/show/emoji_menu_spec.js
+++ b/spec/javascripts/pages/profiles/show/emoji_menu_spec.js
@@ -81,6 +81,7 @@ describe('EmojiMenu', () => {
'mouseenter focus',
jasmine.anything(),
);
+
expect(emojiMenu.registerEventListener).toHaveBeenCalledWith(
'on',
jasmine.anything(),
@@ -107,6 +108,7 @@ describe('EmojiMenu', () => {
it('renders the menu with custom menu class', () => {
const menuElement = () =>
document.body.querySelector(`.emoji-menu.${dummyMenuClass} .emoji-menu-content`);
+
expect(menuElement()).toBe(null);
emojiMenu.createEmojiMenu();
diff --git a/spec/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js b/spec/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js
index 4655e29eed0..b20bc96f9be 100644
--- a/spec/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js
+++ b/spec/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input_spec.js
@@ -19,10 +19,10 @@ window.gl.pipelineScheduleFieldErrors = {
updateFormValidityState: () => {},
};
-describe('Interval Pattern Input Component', function () {
- describe('when prop initialCronInterval is passed (edit)', function () {
- describe('when prop initialCronInterval is custom', function () {
- beforeEach(function () {
+describe('Interval Pattern Input Component', function() {
+ describe('when prop initialCronInterval is passed (edit)', function() {
+ describe('when prop initialCronInterval is custom', function() {
+ beforeEach(function() {
this.initialCronInterval = '1 2 3 4 5';
this.intervalPatternComponent = new IntervalPatternInputComponent({
propsData: {
@@ -31,15 +31,15 @@ describe('Interval Pattern Input Component', function () {
}).$mount();
});
- it('is initialized as a Vue component', function () {
+ it('is initialized as a Vue component', function() {
expect(this.intervalPatternComponent).toBeDefined();
});
- it('prop initialCronInterval is set', function () {
+ it('prop initialCronInterval is set', function() {
expect(this.intervalPatternComponent.initialCronInterval).toBe(this.initialCronInterval);
});
- it('sets isEditable to true', function (done) {
+ it('sets isEditable to true', function(done) {
Vue.nextTick(() => {
expect(this.intervalPatternComponent.isEditable).toBe(true);
done();
@@ -47,8 +47,8 @@ describe('Interval Pattern Input Component', function () {
});
});
- describe('when prop initialCronInterval is preset', function () {
- beforeEach(function () {
+ describe('when prop initialCronInterval is preset', function() {
+ beforeEach(function() {
this.intervalPatternComponent = new IntervalPatternInputComponent({
propsData: {
inputNameAttribute,
@@ -57,11 +57,11 @@ describe('Interval Pattern Input Component', function () {
}).$mount();
});
- it('is initialized as a Vue component', function () {
+ it('is initialized as a Vue component', function() {
expect(this.intervalPatternComponent).toBeDefined();
});
- it('sets isEditable to false', function (done) {
+ it('sets isEditable to false', function(done) {
Vue.nextTick(() => {
expect(this.intervalPatternComponent.isEditable).toBe(false);
done();
@@ -70,8 +70,8 @@ describe('Interval Pattern Input Component', function () {
});
});
- describe('when prop initialCronInterval is not passed (new)', function () {
- beforeEach(function () {
+ describe('when prop initialCronInterval is not passed (new)', function() {
+ beforeEach(function() {
this.intervalPatternComponent = new IntervalPatternInputComponent({
propsData: {
inputNameAttribute,
@@ -79,16 +79,17 @@ describe('Interval Pattern Input Component', function () {
}).$mount();
});
- it('is initialized as a Vue component', function () {
+ it('is initialized as a Vue component', function() {
expect(this.intervalPatternComponent).toBeDefined();
});
- it('prop initialCronInterval is set', function () {
+ it('prop initialCronInterval is set', function() {
const defaultInitialCronInterval = '';
+
expect(this.intervalPatternComponent.initialCronInterval).toBe(defaultInitialCronInterval);
});
- it('sets isEditable to true', function (done) {
+ it('sets isEditable to true', function(done) {
Vue.nextTick(() => {
expect(this.intervalPatternComponent.isEditable).toBe(true);
done();
@@ -96,8 +97,8 @@ describe('Interval Pattern Input Component', function () {
});
});
- describe('User Actions', function () {
- beforeEach(function () {
+ describe('User Actions', function() {
+ beforeEach(function() {
// For an unknown reason, some browsers do not propagate click events
// on radio buttons in a way Vue can register. So, we have to mount
// to a fixture.
@@ -111,66 +112,79 @@ describe('Interval Pattern Input Component', function () {
}).$mount('#my-mount');
});
- it('cronInterval is updated when everyday preset interval is selected', function (done) {
+ it('cronInterval is updated when everyday preset interval is selected', function(done) {
this.intervalPatternComponent.$el.querySelector('#every-day').click();
Vue.nextTick(() => {
expect(this.intervalPatternComponent.cronInterval).toBe(cronIntervalPresets.everyDay);
- expect(this.intervalPatternComponent.$el.querySelector('.cron-interval-input').value).toBe(cronIntervalPresets.everyDay);
+ expect(this.intervalPatternComponent.$el.querySelector('.cron-interval-input').value).toBe(
+ cronIntervalPresets.everyDay,
+ );
done();
});
});
- it('cronInterval is updated when everyweek preset interval is selected', function (done) {
+ it('cronInterval is updated when everyweek preset interval is selected', function(done) {
this.intervalPatternComponent.$el.querySelector('#every-week').click();
Vue.nextTick(() => {
expect(this.intervalPatternComponent.cronInterval).toBe(cronIntervalPresets.everyWeek);
- expect(this.intervalPatternComponent.$el.querySelector('.cron-interval-input').value).toBe(cronIntervalPresets.everyWeek);
+ expect(this.intervalPatternComponent.$el.querySelector('.cron-interval-input').value).toBe(
+ cronIntervalPresets.everyWeek,
+ );
done();
});
});
- it('cronInterval is updated when everymonth preset interval is selected', function (done) {
+ it('cronInterval is updated when everymonth preset interval is selected', function(done) {
this.intervalPatternComponent.$el.querySelector('#every-month').click();
Vue.nextTick(() => {
expect(this.intervalPatternComponent.cronInterval).toBe(cronIntervalPresets.everyMonth);
- expect(this.intervalPatternComponent.$el.querySelector('.cron-interval-input').value).toBe(cronIntervalPresets.everyMonth);
+ expect(this.intervalPatternComponent.$el.querySelector('.cron-interval-input').value).toBe(
+ cronIntervalPresets.everyMonth,
+ );
done();
});
});
- it('only a space is added to cronInterval (trimmed later) when custom radio is selected', function (done) {
+ it('only a space is added to cronInterval (trimmed later) when custom radio is selected', function(done) {
this.intervalPatternComponent.$el.querySelector('#every-month').click();
this.intervalPatternComponent.$el.querySelector('#custom').click();
Vue.nextTick(() => {
const intervalWithSpaceAppended = `${cronIntervalPresets.everyMonth} `;
+
expect(this.intervalPatternComponent.cronInterval).toBe(intervalWithSpaceAppended);
- expect(this.intervalPatternComponent.$el.querySelector('.cron-interval-input').value).toBe(intervalWithSpaceAppended);
+ expect(this.intervalPatternComponent.$el.querySelector('.cron-interval-input').value).toBe(
+ intervalWithSpaceAppended,
+ );
done();
});
});
- it('text input is disabled when preset interval is selected', function (done) {
+ it('text input is disabled when preset interval is selected', function(done) {
this.intervalPatternComponent.$el.querySelector('#every-month').click();
Vue.nextTick(() => {
expect(this.intervalPatternComponent.isEditable).toBe(false);
- expect(this.intervalPatternComponent.$el.querySelector('.cron-interval-input').disabled).toBe(true);
+ expect(
+ this.intervalPatternComponent.$el.querySelector('.cron-interval-input').disabled,
+ ).toBe(true);
done();
});
});
- it('text input is enabled when custom is selected', function (done) {
+ it('text input is enabled when custom is selected', function(done) {
this.intervalPatternComponent.$el.querySelector('#every-month').click();
this.intervalPatternComponent.$el.querySelector('#custom').click();
Vue.nextTick(() => {
expect(this.intervalPatternComponent.isEditable).toBe(true);
- expect(this.intervalPatternComponent.$el.querySelector('.cron-interval-input').disabled).toBe(false);
+ expect(
+ this.intervalPatternComponent.$el.querySelector('.cron-interval-input').disabled,
+ ).toBe(false);
done();
});
});
diff --git a/spec/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js b/spec/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js
index fb7d2763b49..ea809e1f170 100644
--- a/spec/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js
+++ b/spec/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedule_callout_spec.js
@@ -6,7 +6,7 @@ const PipelineSchedulesCalloutComponent = Vue.extend(PipelineSchedulesCallout);
const cookieKey = 'pipeline_schedules_callout_dismissed';
const docsUrl = 'help/ci/scheduled_pipelines';
-describe('Pipeline Schedule Callout', function () {
+describe('Pipeline Schedule Callout', function() {
beforeEach(() => {
setFixtures(`
<div id='pipeline-schedules-callout' data-docs-url=${docsUrl}></div>
@@ -76,7 +76,7 @@ describe('Pipeline Schedule Callout', function () {
expect(this.calloutComponent.$el.outerHTML).toContain(docsUrl);
});
- it('updates calloutDismissed when close button is clicked', (done) => {
+ it('updates calloutDismissed when close button is clicked', done => {
this.calloutComponent.$el.querySelector('#dismiss-callout-btn').click();
Vue.nextTick(() => {
@@ -85,7 +85,7 @@ describe('Pipeline Schedule Callout', function () {
});
});
- it('#dismissCallout updates calloutDismissed', (done) => {
+ it('#dismissCallout updates calloutDismissed', done => {
this.calloutComponent.dismissCallout();
Vue.nextTick(() => {
@@ -94,7 +94,7 @@ describe('Pipeline Schedule Callout', function () {
});
});
- it('is hidden when close button is clicked', (done) => {
+ it('is hidden when close button is clicked', done => {
this.calloutComponent.$el.querySelector('#dismiss-callout-btn').click();
Vue.nextTick(() => {
diff --git a/spec/javascripts/pdf/index_spec.js b/spec/javascripts/pdf/index_spec.js
index 69230bb0937..699cf4871aa 100644
--- a/spec/javascripts/pdf/index_spec.js
+++ b/spec/javascripts/pdf/index_spec.js
@@ -11,7 +11,7 @@ const Component = Vue.extend(PDFLab);
describe('PDF component', () => {
let vm;
- const checkLoaded = (done) => {
+ const checkLoaded = done => {
if (vm.loading) {
setTimeout(() => {
checkLoaded(done);
@@ -22,7 +22,7 @@ describe('PDF component', () => {
};
describe('without PDF data', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm = new Component({
propsData: {
pdf: '',
@@ -40,7 +40,7 @@ describe('PDF component', () => {
});
describe('with PDF data', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm = new Component({
propsData: {
pdf,
diff --git a/spec/javascripts/pdf/page_spec.js b/spec/javascripts/pdf/page_spec.js
index a207f2afce6..ef967210b65 100644
--- a/spec/javascripts/pdf/page_spec.js
+++ b/spec/javascripts/pdf/page_spec.js
@@ -34,6 +34,7 @@ describe('Page component', () => {
page: testPage,
number: 1,
});
+
expect(vm.rendering).toBe(true);
promise
diff --git a/spec/javascripts/performance_bar/components/detailed_metric_spec.js b/spec/javascripts/performance_bar/components/detailed_metric_spec.js
index c4611dc7662..e91685e50c5 100644
--- a/spec/javascripts/performance_bar/components/detailed_metric_spec.js
+++ b/spec/javascripts/performance_bar/components/detailed_metric_spec.js
@@ -54,11 +54,9 @@ describe('detailedMetric', () => {
});
it('adds a modal with a table of the details', () => {
- vm.$el
- .querySelectorAll('.performance-bar-modal td strong')
- .forEach((duration, index) => {
- expect(duration.innerText).toContain(requestDetails[index].duration);
- });
+ vm.$el.querySelectorAll('.performance-bar-modal td strong').forEach((duration, index) => {
+ expect(duration.innerText).toContain(requestDetails[index].duration);
+ });
vm.$el
.querySelectorAll('.performance-bar-modal td:nth-child(2)')
@@ -69,7 +67,7 @@ describe('detailedMetric', () => {
vm.$el
.querySelectorAll('.performance-bar-modal td:nth-child(3)')
.forEach((request, index) => {
- expect(request.innerText).toContain(requestDetails[index].request);
+ expect(request.innerText).toEqual(requestDetails[index].request);
});
});
diff --git a/spec/javascripts/performance_bar/components/request_selector_spec.js b/spec/javascripts/performance_bar/components/request_selector_spec.js
index 6108a29f8c4..a272e03c0e1 100644
--- a/spec/javascripts/performance_bar/components/request_selector_spec.js
+++ b/spec/javascripts/performance_bar/components/request_selector_spec.js
@@ -11,8 +11,7 @@ describe('request selector', () => {
},
{
id: '789',
- url:
- 'https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/1.json?serializer=widget',
+ url: 'https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/1.json?serializer=widget',
},
];
diff --git a/spec/javascripts/performance_bar/index_spec.js b/spec/javascripts/performance_bar/index_spec.js
index 1784bd64adb..1444d1bb3cb 100644
--- a/spec/javascripts/performance_bar/index_spec.js
+++ b/spec/javascripts/performance_bar/index_spec.js
@@ -63,10 +63,7 @@ describe('performance bar wrapper', () => {
it('adds the request immediately', () => {
vm.loadRequestDetails('123', 'https://gitlab.com/');
- expect(vm.store.addRequest).toHaveBeenCalledWith(
- '123',
- 'https://gitlab.com/',
- );
+ expect(vm.store.addRequest).toHaveBeenCalledWith('123', 'https://gitlab.com/');
});
it('makes an HTTP request for the request details', () => {
diff --git a/spec/javascripts/performance_bar/services/performance_bar_service_spec.js b/spec/javascripts/performance_bar/services/performance_bar_service_spec.js
index bc6947dbe81..cfec4b779e4 100644
--- a/spec/javascripts/performance_bar/services/performance_bar_service_spec.js
+++ b/spec/javascripts/performance_bar/services/performance_bar_service_spec.js
@@ -8,28 +8,34 @@ describe('PerformanceBarService', () => {
}
it('returns false when the request URL is the peek URL', () => {
- expect(fireCallback({ headers: { 'x-request-id': '123' }, url: '/peek' }, '/peek'))
- .toBeFalsy();
+ expect(
+ fireCallback({ headers: { 'x-request-id': '123' }, url: '/peek' }, '/peek'),
+ ).toBeFalsy();
});
it('returns false when there is no request ID', () => {
- expect(fireCallback({ headers: {}, url: '/request' }, '/peek'))
- .toBeFalsy();
+ expect(fireCallback({ headers: {}, url: '/request' }, '/peek')).toBeFalsy();
});
it('returns false when the request is an API request', () => {
- expect(fireCallback({ headers: { 'x-request-id': '123' }, url: '/api/' }, '/peek'))
- .toBeFalsy();
+ expect(
+ fireCallback({ headers: { 'x-request-id': '123' }, url: '/api/' }, '/peek'),
+ ).toBeFalsy();
});
it('returns false when the response is from the cache', () => {
- expect(fireCallback({ headers: { 'x-request-id': '123', 'x-gitlab-from-cache': 'true' }, url: '/request' }, '/peek'))
- .toBeFalsy();
+ expect(
+ fireCallback(
+ { headers: { 'x-request-id': '123', 'x-gitlab-from-cache': 'true' }, url: '/request' },
+ '/peek',
+ ),
+ ).toBeFalsy();
});
it('returns true when all conditions are met', () => {
- expect(fireCallback({ headers: { 'x-request-id': '123' }, url: '/request' }, '/peek'))
- .toBeTruthy();
+ expect(
+ fireCallback({ headers: { 'x-request-id': '123' }, url: '/request' }, '/peek'),
+ ).toBeTruthy();
});
});
@@ -39,8 +45,7 @@ describe('PerformanceBarService', () => {
}
it('gets the request ID from the headers', () => {
- expect(requestId({ headers: { 'x-request-id': '123' } }, '/peek'))
- .toEqual('123');
+ expect(requestId({ headers: { 'x-request-id': '123' } }, '/peek')).toEqual('123');
});
});
@@ -50,13 +55,13 @@ describe('PerformanceBarService', () => {
}
it('gets the request URL from the response object', () => {
- expect(requestUrl({ headers: {}, url: '/request' }, '/peek'))
- .toEqual('/request');
+ expect(requestUrl({ headers: {}, url: '/request' }, '/peek')).toEqual('/request');
});
it('gets the request URL from response.config if present', () => {
- expect(requestUrl({ headers: {}, config: { url: '/config-url' }, url: '/request' }, '/peek'))
- .toEqual('/config-url');
+ expect(
+ requestUrl({ headers: {}, config: { url: '/config-url' }, url: '/request' }, '/peek'),
+ ).toEqual('/config-url');
});
});
});
diff --git a/spec/javascripts/pipelines/blank_state_spec.js b/spec/javascripts/pipelines/blank_state_spec.js
index b7a9b60d85c..033bd5ccb73 100644
--- a/spec/javascripts/pipelines/blank_state_spec.js
+++ b/spec/javascripts/pipelines/blank_state_spec.js
@@ -9,12 +9,10 @@ describe('Pipelines Blank State', () => {
beforeEach(() => {
Component = Vue.extend(component);
- vm = mountComponent(Component,
- {
- svgPath: 'foo',
- message: 'Blank State',
- },
- );
+ vm = mountComponent(Component, {
+ svgPath: 'foo',
+ message: 'Blank State',
+ });
});
it('should render svg', () => {
@@ -22,8 +20,6 @@ describe('Pipelines Blank State', () => {
});
it('should render message', () => {
- expect(
- vm.$el.querySelector('h4').textContent.trim(),
- ).toEqual('Blank State');
+ expect(vm.$el.querySelector('h4').textContent.trim()).toEqual('Blank State');
});
});
diff --git a/spec/javascripts/pipelines/empty_state_spec.js b/spec/javascripts/pipelines/empty_state_spec.js
index 1e41a7bfe7c..f12950b8fce 100644
--- a/spec/javascripts/pipelines/empty_state_spec.js
+++ b/spec/javascripts/pipelines/empty_state_spec.js
@@ -24,20 +24,35 @@ describe('Pipelines Empty State', () => {
expect(component.$el.querySelector('.svg-content svg')).toBeDefined();
});
- it('should render emtpy state information', () => {
+ it('should render empty state information', () => {
expect(component.$el.querySelector('h4').textContent).toContain('Build with confidence');
expect(
- component.$el.querySelector('p').innerHTML.trim().replace(/\n+\s+/m, ' ').replace(/\s\s+/g, ' '),
+ component.$el
+ .querySelector('p')
+ .innerHTML.trim()
+ .replace(/\n+\s+/m, ' ')
+ .replace(/\s\s+/g, ' '),
).toContain('Continuous Integration can help catch bugs by running your tests automatically,');
expect(
- component.$el.querySelector('p').innerHTML.trim().replace(/\n+\s+/m, ' ').replace(/\s\s+/g, ' '),
- ).toContain('while Continuous Deployment can help you deliver code to your product environment');
+ component.$el
+ .querySelector('p')
+ .innerHTML.trim()
+ .replace(/\n+\s+/m, ' ')
+ .replace(/\s\s+/g, ' '),
+ ).toContain(
+ 'while Continuous Deployment can help you deliver code to your product environment',
+ );
});
it('should render a link with provided help path', () => {
- expect(component.$el.querySelector('.js-get-started-pipelines').getAttribute('href')).toEqual('foo');
- expect(component.$el.querySelector('.js-get-started-pipelines').textContent).toContain('Get started with Pipelines');
+ expect(component.$el.querySelector('.js-get-started-pipelines').getAttribute('href')).toEqual(
+ 'foo',
+ );
+
+ expect(component.$el.querySelector('.js-get-started-pipelines').textContent).toContain(
+ 'Get started with Pipelines',
+ );
});
});
diff --git a/spec/javascripts/pipelines/graph/action_component_spec.js b/spec/javascripts/pipelines/graph/action_component_spec.js
index 568e679abe9..3d2232ff239 100644
--- a/spec/javascripts/pipelines/graph/action_component_spec.js
+++ b/spec/javascripts/pipelines/graph/action_component_spec.js
@@ -35,12 +35,13 @@ describe('pipeline graph action component', () => {
it('should update bootstrap tooltip when title changes', done => {
component.tooltipText = 'changed';
- component.$nextTick()
- .then(() => {
- expect(component.$el.getAttribute('data-original-title')).toBe('changed');
- })
- .then(done)
- .catch(done.fail);
+ component
+ .$nextTick()
+ .then(() => {
+ expect(component.$el.getAttribute('data-original-title')).toBe('changed');
+ })
+ .then(done)
+ .catch(done.fail);
});
it('should render an svg', () => {
@@ -49,12 +50,13 @@ describe('pipeline graph action component', () => {
});
describe('on click', () => {
- it('emits `pipelineActionRequestComplete` after a successfull request', done => {
+ it('emits `pipelineActionRequestComplete` after a successful request', done => {
spyOn(component, '$emit');
component.$el.click();
- component.$nextTick()
+ component
+ .$nextTick()
.then(() => {
expect(component.$emit).toHaveBeenCalledWith('pipelineActionRequestComplete');
})
diff --git a/spec/javascripts/pipelines/graph/dropdown_job_component_spec.js b/spec/javascripts/pipelines/graph/dropdown_job_component_spec.js
deleted file mode 100644
index 2b47ca236b2..00000000000
--- a/spec/javascripts/pipelines/graph/dropdown_job_component_spec.js
+++ /dev/null
@@ -1,85 +0,0 @@
-import Vue from 'vue';
-import component from '~/pipelines/components/graph/dropdown_job_component.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-describe('dropdown job component', () => {
- const Component = Vue.extend(component);
- let vm;
-
- const mock = {
- jobs: [
- {
- id: 4256,
- name: '<img src=x onerror=alert(document.domain)>',
- status: {
- icon: 'status_success',
- text: 'passed',
- label: 'passed',
- tooltip: 'passed',
- group: 'success',
- details_path: '/root/ci-mock/builds/4256',
- has_details: true,
- action: {
- icon: 'retry',
- title: 'Retry',
- path: '/root/ci-mock/builds/4256/retry',
- method: 'post',
- },
- },
- },
- {
- id: 4299,
- name: 'test',
- status: {
- icon: 'status_success',
- text: 'passed',
- label: 'passed',
- tooltip: 'passed',
- group: 'success',
- details_path: '/root/ci-mock/builds/4299',
- has_details: true,
- action: {
- icon: 'retry',
- title: 'Retry',
- path: '/root/ci-mock/builds/4299/retry',
- method: 'post',
- },
- },
- },
- ],
- name: 'rspec:linux',
- size: 2,
- status: {
- icon: 'status_success',
- text: 'passed',
- label: 'passed',
- tooltip: 'passed',
- group: 'success',
- details_path: '/root/ci-mock/builds/4256',
- has_details: true,
- action: {
- icon: 'retry',
- title: 'Retry',
- path: '/root/ci-mock/builds/4256/retry',
- method: 'post',
- },
- },
- };
-
- afterEach(() => {
- vm.$destroy();
- });
-
- beforeEach(() => {
- vm = mountComponent(Component, { job: mock });
- });
-
- it('renders button with job name and size', () => {
- expect(vm.$el.querySelector('button').textContent).toContain(mock.name);
- expect(vm.$el.querySelector('button').textContent).toContain(mock.size);
- });
-
- it('renders dropdown with jobs', () => {
- expect(vm.$el.querySelectorAll('.scrollable-menu>ul>li').length).toEqual(mock.jobs.length);
- });
-});
diff --git a/spec/javascripts/pipelines/graph/graph_component_spec.js b/spec/javascripts/pipelines/graph/graph_component_spec.js
index b6fa4272c8b..96a2d5f62fa 100644
--- a/spec/javascripts/pipelines/graph/graph_component_spec.js
+++ b/spec/javascripts/pipelines/graph/graph_component_spec.js
@@ -40,7 +40,9 @@ describe('graph component', () => {
).toEqual(true);
expect(
- component.$el.querySelector('.stage-column:nth-child(2) .build:nth-child(1)').classList.contains('left-connector'),
+ component.$el
+ .querySelector('.stage-column:nth-child(2) .build:nth-child(1)')
+ .classList.contains('left-connector'),
).toEqual(true);
expect(component.$el.querySelector('loading-icon')).toBe(null);
@@ -56,7 +58,9 @@ describe('graph component', () => {
pipeline: graphJSON,
});
- expect(component.$el.querySelector('.stage-column:nth-child(2) .stage-name').textContent.trim()).toEqual('Deploy &lt;img src=x onerror=alert(document.domain)&gt;');
+ expect(
+ component.$el.querySelector('.stage-column:nth-child(2) .stage-name').textContent.trim(),
+ ).toEqual('Deploy &lt;img src=x onerror=alert(document.domain)&gt;');
});
});
});
diff --git a/spec/javascripts/pipelines/graph/job_component_spec.js b/spec/javascripts/pipelines/graph/job_component_spec.js
deleted file mode 100644
index 0ae448f2ea8..00000000000
--- a/spec/javascripts/pipelines/graph/job_component_spec.js
+++ /dev/null
@@ -1,164 +0,0 @@
-import Vue from 'vue';
-import jobComponent from '~/pipelines/components/graph/job_component.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-describe('pipeline graph job component', () => {
- const JobComponent = Vue.extend(jobComponent);
- let component;
-
- const mockJob = {
- id: 4256,
- name: 'test',
- status: {
- icon: 'status_success',
- text: 'passed',
- label: 'passed',
- tooltip: 'passed',
- group: 'success',
- details_path: '/root/ci-mock/builds/4256',
- has_details: true,
- action: {
- icon: 'retry',
- title: 'Retry',
- path: '/root/ci-mock/builds/4256/retry',
- method: 'post',
- },
- },
- };
-
- afterEach(() => {
- component.$destroy();
- });
-
- describe('name with link', () => {
- it('should render the job name and status with a link', (done) => {
- component = mountComponent(JobComponent, { job: mockJob });
-
- Vue.nextTick(() => {
- const link = component.$el.querySelector('a');
-
- expect(link.getAttribute('href')).toEqual(mockJob.status.details_path);
-
- expect(
- link.getAttribute('data-original-title'),
- ).toEqual(`${mockJob.name} - ${mockJob.status.label}`);
-
- expect(component.$el.querySelector('.js-status-icon-success')).toBeDefined();
-
- expect(
- component.$el.querySelector('.ci-status-text').textContent.trim(),
- ).toEqual(mockJob.name);
-
- done();
- });
- });
- });
-
- describe('name without link', () => {
- it('it should render status and name', () => {
- component = mountComponent(JobComponent, {
- job: {
- id: 4257,
- name: 'test',
- status: {
- icon: 'status_success',
- text: 'passed',
- label: 'passed',
- group: 'success',
- details_path: '/root/ci-mock/builds/4257',
- has_details: false,
- },
- },
- });
-
- expect(component.$el.querySelector('.js-status-icon-success')).toBeDefined();
- expect(component.$el.querySelector('a')).toBeNull();
-
- expect(
- component.$el.querySelector('.ci-status-text').textContent.trim(),
- ).toEqual(mockJob.name);
- });
- });
-
- describe('action icon', () => {
- it('it should render the action icon', () => {
- component = mountComponent(JobComponent, { job: mockJob });
-
- expect(component.$el.querySelector('a.ci-action-icon-container')).toBeDefined();
- expect(component.$el.querySelector('i.ci-action-icon-wrapper')).toBeDefined();
- });
- });
-
- it('should render provided class name', () => {
- component = mountComponent(JobComponent, {
- job: mockJob,
- cssClassJobName: 'css-class-job-name',
- });
-
- expect(
- component.$el.querySelector('a').classList.contains('css-class-job-name'),
- ).toBe(true);
- });
-
- describe('status label', () => {
- it('should not render status label when it is not provided', () => {
- component = mountComponent(JobComponent, {
- job: {
- id: 4258,
- name: 'test',
- status: {
- icon: 'status_success',
- },
- },
- });
-
- expect(component.$el.querySelector('.js-job-component-tooltip').getAttribute('data-original-title')).toEqual('test');
- });
-
- it('should not render status label when it is provided', () => {
- component = mountComponent(JobComponent, {
- job: {
- id: 4259,
- name: 'test',
- status: {
- icon: 'status_success',
- label: 'success',
- tooltip: 'success',
- },
- },
- });
-
- expect(component.$el.querySelector('.js-job-component-tooltip').getAttribute('data-original-title')).toEqual('test - success');
- });
- });
-
- describe('tooltip placement', () => {
- const tooltipBoundary = 'a[data-boundary="viewport"]';
-
- it('does not set tooltip boundary by default', () => {
- component = mountComponent(JobComponent, {
- job: mockJob,
- });
-
- expect(component.$el.querySelector(tooltipBoundary)).toBeNull();
- });
-
- it('sets tooltip boundary to viewport for small dropdowns', () => {
- component = mountComponent(JobComponent, {
- job: mockJob,
- dropdownLength: 1,
- });
-
- expect(component.$el.querySelector(tooltipBoundary)).not.toBeNull();
- });
-
- it('does not set tooltip boundary for large lists', () => {
- component = mountComponent(JobComponent, {
- job: mockJob,
- dropdownLength: 7,
- });
-
- expect(component.$el.querySelector(tooltipBoundary)).toBeNull();
- });
- });
-});
diff --git a/spec/javascripts/pipelines/graph/job_group_dropdown_spec.js b/spec/javascripts/pipelines/graph/job_group_dropdown_spec.js
new file mode 100644
index 00000000000..24631cc1c89
--- /dev/null
+++ b/spec/javascripts/pipelines/graph/job_group_dropdown_spec.js
@@ -0,0 +1,85 @@
+import Vue from 'vue';
+import JobGroupDropdown from '~/pipelines/components/graph/job_group_dropdown.vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+
+describe('job group dropdown component', () => {
+ const Component = Vue.extend(JobGroupDropdown);
+ let vm;
+
+ const group = {
+ jobs: [
+ {
+ id: 4256,
+ name: '<img src=x onerror=alert(document.domain)>',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ tooltip: 'passed',
+ group: 'success',
+ details_path: '/root/ci-mock/builds/4256',
+ has_details: true,
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/root/ci-mock/builds/4256/retry',
+ method: 'post',
+ },
+ },
+ },
+ {
+ id: 4299,
+ name: 'test',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ tooltip: 'passed',
+ group: 'success',
+ details_path: '/root/ci-mock/builds/4299',
+ has_details: true,
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/root/ci-mock/builds/4299/retry',
+ method: 'post',
+ },
+ },
+ },
+ ],
+ name: 'rspec:linux',
+ size: 2,
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ tooltip: 'passed',
+ group: 'success',
+ details_path: '/root/ci-mock/builds/4256',
+ has_details: true,
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/root/ci-mock/builds/4256/retry',
+ method: 'post',
+ },
+ },
+ };
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ beforeEach(() => {
+ vm = mountComponent(Component, { group });
+ });
+
+ it('renders button with group name and size', () => {
+ expect(vm.$el.querySelector('button').textContent).toContain(group.name);
+ expect(vm.$el.querySelector('button').textContent).toContain(group.size);
+ });
+
+ it('renders dropdown with jobs', () => {
+ expect(vm.$el.querySelectorAll('.scrollable-menu>ul>li').length).toEqual(group.jobs.length);
+ });
+});
diff --git a/spec/javascripts/pipelines/graph/job_item_spec.js b/spec/javascripts/pipelines/graph/job_item_spec.js
new file mode 100644
index 00000000000..1cdb0aff524
--- /dev/null
+++ b/spec/javascripts/pipelines/graph/job_item_spec.js
@@ -0,0 +1,155 @@
+import Vue from 'vue';
+import JobItem from '~/pipelines/components/graph/job_item.vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+
+describe('pipeline graph job item', () => {
+ const JobComponent = Vue.extend(JobItem);
+ let component;
+
+ const delayedJobFixture = getJSONFixture('jobs/delayed.json');
+ const mockJob = {
+ id: 4256,
+ name: 'test',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ tooltip: 'passed',
+ group: 'success',
+ details_path: '/root/ci-mock/builds/4256',
+ has_details: true,
+ action: {
+ icon: 'retry',
+ title: 'Retry',
+ path: '/root/ci-mock/builds/4256/retry',
+ method: 'post',
+ },
+ },
+ };
+
+ afterEach(() => {
+ component.$destroy();
+ });
+
+ describe('name with link', () => {
+ it('should render the job name and status with a link', done => {
+ component = mountComponent(JobComponent, { job: mockJob });
+
+ Vue.nextTick(() => {
+ const link = component.$el.querySelector('a');
+
+ expect(link.getAttribute('href')).toEqual(mockJob.status.details_path);
+
+ expect(link.getAttribute('data-original-title')).toEqual(
+ `${mockJob.name} - ${mockJob.status.label}`,
+ );
+
+ expect(component.$el.querySelector('.js-status-icon-success')).toBeDefined();
+
+ expect(component.$el.querySelector('.ci-status-text').textContent.trim()).toEqual(
+ mockJob.name,
+ );
+
+ done();
+ });
+ });
+ });
+
+ describe('name without link', () => {
+ it('it should render status and name', () => {
+ component = mountComponent(JobComponent, {
+ job: {
+ id: 4257,
+ name: 'test',
+ status: {
+ icon: 'status_success',
+ text: 'passed',
+ label: 'passed',
+ group: 'success',
+ details_path: '/root/ci-mock/builds/4257',
+ has_details: false,
+ },
+ },
+ });
+
+ expect(component.$el.querySelector('.js-status-icon-success')).toBeDefined();
+ expect(component.$el.querySelector('a')).toBeNull();
+
+ expect(component.$el.querySelector('.ci-status-text').textContent.trim()).toEqual(
+ mockJob.name,
+ );
+ });
+ });
+
+ describe('action icon', () => {
+ it('it should render the action icon', () => {
+ component = mountComponent(JobComponent, { job: mockJob });
+
+ expect(component.$el.querySelector('a.ci-action-icon-container')).toBeDefined();
+ expect(component.$el.querySelector('i.ci-action-icon-wrapper')).toBeDefined();
+ });
+ });
+
+ it('should render provided class name', () => {
+ component = mountComponent(JobComponent, {
+ job: mockJob,
+ cssClassJobName: 'css-class-job-name',
+ });
+
+ expect(component.$el.querySelector('a').classList.contains('css-class-job-name')).toBe(true);
+ });
+
+ describe('status label', () => {
+ it('should not render status label when it is not provided', () => {
+ component = mountComponent(JobComponent, {
+ job: {
+ id: 4258,
+ name: 'test',
+ status: {
+ icon: 'status_success',
+ },
+ },
+ });
+
+ expect(
+ component.$el
+ .querySelector('.js-job-component-tooltip')
+ .getAttribute('data-original-title'),
+ ).toEqual('test');
+ });
+
+ it('should not render status label when it is provided', () => {
+ component = mountComponent(JobComponent, {
+ job: {
+ id: 4259,
+ name: 'test',
+ status: {
+ icon: 'status_success',
+ label: 'success',
+ tooltip: 'success',
+ },
+ },
+ });
+
+ expect(
+ component.$el
+ .querySelector('.js-job-component-tooltip')
+ .getAttribute('data-original-title'),
+ ).toEqual('test - success');
+ });
+ });
+
+ describe('for delayed job', () => {
+ it('displays remaining time in tooltip', () => {
+ component = mountComponent(JobComponent, {
+ job: delayedJobFixture,
+ });
+
+ expect(
+ component.$el
+ .querySelector('.js-pipeline-graph-job-link')
+ .getAttribute('data-original-title'),
+ ).toEqual(`delayed job - delayed manual action (${component.remainingTime})`);
+ });
+ });
+});
diff --git a/spec/javascripts/pipelines/graph/stage_column_component_spec.js b/spec/javascripts/pipelines/graph/stage_column_component_spec.js
index f6e6bd3132e..d0b8f877d6f 100644
--- a/spec/javascripts/pipelines/graph/stage_column_component_spec.js
+++ b/spec/javascripts/pipelines/graph/stage_column_component_spec.js
@@ -25,17 +25,16 @@ describe('stage column component', () => {
};
beforeEach(() => {
-
- const mockJobs = [];
+ const mockGroups = [];
for (let i = 0; i < 3; i += 1) {
const mockedJob = Object.assign({}, mockJob);
mockedJob.id += i;
- mockJobs.push(mockedJob);
+ mockGroups.push(mockedJob);
}
component = mountComponent(StageColumnComponent, {
title: 'foo',
- jobs: mockJobs,
+ groups: mockGroups,
});
});
@@ -43,14 +42,14 @@ describe('stage column component', () => {
expect(component.$el.querySelector('.stage-name').textContent.trim()).toEqual('foo');
});
- it('should render the provided jobs', () => {
+ it('should render the provided groups', () => {
expect(component.$el.querySelectorAll('.builds-container > ul > li').length).toEqual(3);
});
describe('jobId', () => {
it('escapes job name', () => {
component = mountComponent(StageColumnComponent, {
- jobs: [
+ groups: [
{
id: 4259,
name: '<img src=x onerror=alert(document.domain)>',
@@ -64,9 +63,9 @@ describe('stage column component', () => {
title: 'test',
});
- expect(
- component.$el.querySelector('.builds-container li').getAttribute('id'),
- ).toEqual('ci-badge-&lt;img src=x onerror=alert(document.domain)&gt;');
+ expect(component.$el.querySelector('.builds-container li').getAttribute('id')).toEqual(
+ 'ci-badge-&lt;img src=x onerror=alert(document.domain)&gt;',
+ );
});
});
});
diff --git a/spec/javascripts/pipelines/header_component_spec.js b/spec/javascripts/pipelines/header_component_spec.js
index 034d3b4957d..556a0976b29 100644
--- a/spec/javascripts/pipelines/header_component_spec.js
+++ b/spec/javascripts/pipelines/header_component_spec.js
@@ -47,13 +47,16 @@ describe('Pipeline details header', () => {
it('should render provided pipeline info', () => {
expect(
- vm.$el.querySelector('.header-main-content').textContent.replace(/\s+/g, ' ').trim(),
- ).toEqual('failed Pipeline #123 triggered 3 weeks ago by Foo');
+ vm.$el
+ .querySelector('.header-main-content')
+ .textContent.replace(/\s+/g, ' ')
+ .trim(),
+ ).toContain('failed Pipeline #123 triggered 3 weeks ago by Foo');
});
describe('action buttons', () => {
it('should call postAction when button action is clicked', () => {
- eventHub.$on('headerPostAction', (action) => {
+ eventHub.$on('headerPostAction', action => {
expect(action.path).toEqual('path');
});
diff --git a/spec/javascripts/pipelines/nav_controls_spec.js b/spec/javascripts/pipelines/nav_controls_spec.js
index d6232f5c567..7806cdf1477 100644
--- a/spec/javascripts/pipelines/nav_controls_spec.js
+++ b/spec/javascripts/pipelines/nav_controls_spec.js
@@ -24,7 +24,9 @@ describe('Pipelines Nav Controls', () => {
component = mountComponent(NavControlsComponent, mockData);
expect(component.$el.querySelector('.js-run-pipeline').textContent).toContain('Run Pipeline');
- expect(component.$el.querySelector('.js-run-pipeline').getAttribute('href')).toEqual(mockData.newPipelinePath);
+ expect(component.$el.querySelector('.js-run-pipeline').getAttribute('href')).toEqual(
+ mockData.newPipelinePath,
+ );
});
it('should not render link to create pipeline if no path is provided', () => {
@@ -50,7 +52,9 @@ describe('Pipelines Nav Controls', () => {
component = mountComponent(NavControlsComponent, mockData);
expect(component.$el.querySelector('.js-ci-lint').textContent.trim()).toContain('CI Lint');
- expect(component.$el.querySelector('.js-ci-lint').getAttribute('href')).toEqual(mockData.ciLintPath);
+ expect(component.$el.querySelector('.js-ci-lint').getAttribute('href')).toEqual(
+ mockData.ciLintPath,
+ );
});
describe('Reset Runners Cache', () => {
@@ -65,7 +69,9 @@ describe('Pipelines Nav Controls', () => {
});
it('should render button for resetting runner caches', () => {
- expect(component.$el.querySelector('.js-clear-cache').textContent.trim()).toContain('Clear Runner Caches');
+ expect(component.$el.querySelector('.js-clear-cache').textContent.trim()).toContain(
+ 'Clear Runner Caches',
+ );
});
it('should emit postAction event when reset runner cache button is clicked', () => {
diff --git a/spec/javascripts/pipelines/pipeline_store_spec.js b/spec/javascripts/pipelines/pipeline_store_spec.js
index ab2287cc344..1d5754d1f05 100644
--- a/spec/javascripts/pipelines/pipeline_store_spec.js
+++ b/spec/javascripts/pipelines/pipeline_store_spec.js
@@ -20,6 +20,7 @@ describe('Pipeline Store', () => {
it('should store received object', () => {
store.storePipeline({ foo: 'bar' });
+
expect(store.state.pipeline).toEqual({ foo: 'bar' });
});
});
diff --git a/spec/javascripts/pipelines/pipeline_url_spec.js b/spec/javascripts/pipelines/pipeline_url_spec.js
index ddd580ae8b7..d6c44f4c976 100644
--- a/spec/javascripts/pipelines/pipeline_url_spec.js
+++ b/spec/javascripts/pipelines/pipeline_url_spec.js
@@ -38,6 +38,7 @@ describe('Pipeline Url Component', () => {
expect(component.$el.querySelector('.js-pipeline-url-link').getAttribute('href')).toEqual(
'foo',
);
+
expect(component.$el.querySelector('.js-pipeline-url-link span').textContent).toEqual('#1');
});
@@ -62,11 +63,15 @@ describe('Pipeline Url Component', () => {
}).$mount();
const image = component.$el.querySelector('.js-pipeline-url-user img');
+ const tooltip = component.$el.querySelector(
+ '.js-pipeline-url-user .js-user-avatar-image-toolip',
+ );
expect(component.$el.querySelector('.js-pipeline-url-user').getAttribute('href')).toEqual(
mockData.pipeline.user.web_url,
);
- expect(image.getAttribute('data-original-title')).toEqual(mockData.pipeline.user.name);
+
+ expect(tooltip.textContent.trim()).toEqual(mockData.pipeline.user.name);
expect(image.getAttribute('src')).toEqual(`${mockData.pipeline.user.avatar_url}?width=20`);
});
@@ -105,6 +110,7 @@ describe('Pipeline Url Component', () => {
expect(component.$el.querySelector('.js-pipeline-url-yaml').textContent).toContain(
'yaml invalid',
);
+
expect(component.$el.querySelector('.js-pipeline-url-stuck').textContent).toContain('stuck');
});
diff --git a/spec/javascripts/pipelines/pipelines_actions_spec.js b/spec/javascripts/pipelines/pipelines_actions_spec.js
index 72fb0a8f9ef..a7dcd532f4f 100644
--- a/spec/javascripts/pipelines/pipelines_actions_spec.js
+++ b/spec/javascripts/pipelines/pipelines_actions_spec.js
@@ -1,46 +1,104 @@
import Vue from 'vue';
-import pipelinesActionsComp from '~/pipelines/components/pipelines_actions.vue';
+import eventHub from '~/pipelines/event_hub';
+import PipelinesActions from '~/pipelines/components/pipelines_actions.vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import { TEST_HOST } from 'spec/test_constants';
describe('Pipelines Actions dropdown', () => {
- let component;
- let actions;
- let ActionsComponent;
+ const Component = Vue.extend(PipelinesActions);
+ let vm;
- beforeEach(() => {
- ActionsComponent = Vue.extend(pipelinesActionsComp);
+ afterEach(() => {
+ vm.$destroy();
+ });
- actions = [
+ describe('manual actions', () => {
+ const actions = [
{
name: 'stop_review',
- path: '/root/review-app/builds/1893/play',
+ path: `${TEST_HOST}/root/review-app/builds/1893/play`,
},
{
name: 'foo',
- path: '#',
+ path: `${TEST_HOST}/disabled/pipeline/action`,
playable: false,
},
];
- component = new ActionsComponent({
- propsData: {
- actions,
- },
- }).$mount();
- });
+ beforeEach(() => {
+ vm = mountComponent(Component, { actions });
+ });
+
+ it('renders a dropdown with the provided actions', () => {
+ const dropdownItems = vm.$el.querySelectorAll('.dropdown-menu li');
- it('should render a dropdown with the provided actions', () => {
- expect(
- component.$el.querySelectorAll('.dropdown-menu li').length,
- ).toEqual(actions.length);
+ expect(dropdownItems.length).toEqual(actions.length);
+ });
+
+ it("renders a disabled action when it's not playable", () => {
+ const dropdownItem = vm.$el.querySelector('.dropdown-menu li:last-child button');
+
+ expect(dropdownItem).toBeDisabled();
+ });
});
- it('should render a disabled action when it\'s not playable', () => {
- expect(
- component.$el.querySelector('.dropdown-menu li:last-child button').getAttribute('disabled'),
- ).toEqual('disabled');
+ describe('scheduled jobs', () => {
+ const scheduledJobAction = {
+ name: 'scheduled action',
+ path: `${TEST_HOST}/scheduled/job/action`,
+ playable: true,
+ scheduled_at: '2063-04-05T00:42:00Z',
+ };
+ const expiredJobAction = {
+ name: 'expired action',
+ path: `${TEST_HOST}/expired/job/action`,
+ playable: true,
+ scheduled_at: '2018-10-05T08:23:00Z',
+ };
+ const findDropdownItem = action => {
+ const buttons = vm.$el.querySelectorAll('.dropdown-menu li button');
+ return Array.prototype.find.call(buttons, element =>
+ element.innerText.trim().startsWith(action.name),
+ );
+ };
+
+ beforeEach(done => {
+ spyOn(Date, 'now').and.callFake(() => new Date('2063-04-04T00:42:00Z').getTime());
+ vm = mountComponent(Component, { actions: [scheduledJobAction, expiredJobAction] });
+
+ Vue.nextTick()
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('emits postAction event after confirming', () => {
+ const emitSpy = jasmine.createSpy('emit');
+ eventHub.$on('postAction', emitSpy);
+ spyOn(window, 'confirm').and.callFake(() => true);
+
+ findDropdownItem(scheduledJobAction).click();
+
+ expect(window.confirm).toHaveBeenCalled();
+ expect(emitSpy).toHaveBeenCalledWith(scheduledJobAction.path);
+ });
+
+ it('does not emit postAction event if confirmation is cancelled', () => {
+ const emitSpy = jasmine.createSpy('emit');
+ eventHub.$on('postAction', emitSpy);
+ spyOn(window, 'confirm').and.callFake(() => false);
+
+ findDropdownItem(scheduledJobAction).click();
+
+ expect(window.confirm).toHaveBeenCalled();
+ expect(emitSpy).not.toHaveBeenCalled();
+ });
+
+ it('displays the remaining time in the dropdown', () => {
+ expect(findDropdownItem(scheduledJobAction)).toContainText('24:00:00');
+ });
- expect(
- component.$el.querySelector('.dropdown-menu li:last-child button').classList.contains('disabled'),
- ).toEqual(true);
+ it('displays 00:00:00 for expired jobs in the dropdown', () => {
+ expect(findDropdownItem(expiredJobAction)).toContainText('00:00:00');
+ });
});
});
diff --git a/spec/javascripts/pipelines/pipelines_artifacts_spec.js b/spec/javascripts/pipelines/pipelines_artifacts_spec.js
index a8a8e3e2cff..7705d5a19bf 100644
--- a/spec/javascripts/pipelines/pipelines_artifacts_spec.js
+++ b/spec/javascripts/pipelines/pipelines_artifacts_spec.js
@@ -23,18 +23,16 @@ describe('Pipelines Artifacts dropdown', () => {
});
it('should render a dropdown with the provided artifacts', () => {
- expect(
- component.$el.querySelectorAll('.dropdown-menu li').length,
- ).toEqual(artifacts.length);
+ expect(component.$el.querySelectorAll('.dropdown-menu li').length).toEqual(artifacts.length);
});
it('should render a link with the provided path', () => {
- expect(
- component.$el.querySelector('.dropdown-menu li a').getAttribute('href'),
- ).toEqual(artifacts[0].path);
+ expect(component.$el.querySelector('.dropdown-menu li a').getAttribute('href')).toEqual(
+ artifacts[0].path,
+ );
- expect(
- component.$el.querySelector('.dropdown-menu li a').textContent,
- ).toContain(artifacts[0].name);
+ expect(component.$el.querySelector('.dropdown-menu li a').textContent).toContain(
+ artifacts[0].name,
+ );
});
});
diff --git a/spec/javascripts/pipelines/pipelines_spec.js b/spec/javascripts/pipelines/pipelines_spec.js
index 50141bd99b4..97ded16db69 100644
--- a/spec/javascripts/pipelines/pipelines_spec.js
+++ b/spec/javascripts/pipelines/pipelines_spec.js
@@ -52,7 +52,7 @@ describe('Pipelines', () => {
describe('With permission', () => {
describe('With pipelines in main tab', () => {
- beforeEach((done) => {
+ beforeEach(done => {
mock.onGet('twitter/flight/pipelines.json').reply(200, pipelines);
vm = mountComponent(PipelinesComponent, {
@@ -72,7 +72,9 @@ describe('Pipelines', () => {
});
it('renders Run Pipeline link', () => {
- expect(vm.$el.querySelector('.js-run-pipeline').getAttribute('href')).toEqual(paths.newPipelinePath);
+ expect(vm.$el.querySelector('.js-run-pipeline').getAttribute('href')).toEqual(
+ paths.newPipelinePath,
+ );
});
it('renders CI Lint link', () => {
@@ -80,18 +82,20 @@ describe('Pipelines', () => {
});
it('renders Clear Runner Cache button', () => {
- expect(vm.$el.querySelector('.js-clear-cache').textContent.trim()).toEqual('Clear Runner Caches');
+ expect(vm.$el.querySelector('.js-clear-cache').textContent.trim()).toEqual(
+ 'Clear Runner Caches',
+ );
});
it('renders pipelines table', () => {
- expect(
- vm.$el.querySelectorAll('.gl-responsive-table-row').length,
- ).toEqual(pipelines.pipelines.length + 1);
+ expect(vm.$el.querySelectorAll('.gl-responsive-table-row').length).toEqual(
+ pipelines.pipelines.length + 1,
+ );
});
});
describe('Without pipelines on main tab with CI', () => {
- beforeEach((done) => {
+ beforeEach(done => {
mock.onGet('twitter/flight/pipelines.json').reply(200, {
pipelines: [],
count: {
@@ -118,7 +122,9 @@ describe('Pipelines', () => {
});
it('renders Run Pipeline link', () => {
- expect(vm.$el.querySelector('.js-run-pipeline').getAttribute('href')).toEqual(paths.newPipelinePath);
+ expect(vm.$el.querySelector('.js-run-pipeline').getAttribute('href')).toEqual(
+ paths.newPipelinePath,
+ );
});
it('renders CI Lint link', () => {
@@ -126,16 +132,20 @@ describe('Pipelines', () => {
});
it('renders Clear Runner Cache button', () => {
- expect(vm.$el.querySelector('.js-clear-cache').textContent.trim()).toEqual('Clear Runner Caches');
+ expect(vm.$el.querySelector('.js-clear-cache').textContent.trim()).toEqual(
+ 'Clear Runner Caches',
+ );
});
it('renders tab empty state', () => {
- expect(vm.$el.querySelector('.empty-state h4').textContent.trim()).toEqual('There are currently no pipelines.');
+ expect(vm.$el.querySelector('.empty-state h4').textContent.trim()).toEqual(
+ 'There are currently no pipelines.',
+ );
});
});
describe('Without pipelines nor CI', () => {
- beforeEach((done) => {
+ beforeEach(done => {
mock.onGet('twitter/flight/pipelines.json').reply(200, {
pipelines: [],
count: {
@@ -158,8 +168,13 @@ describe('Pipelines', () => {
});
it('renders empty state', () => {
- expect(vm.$el.querySelector('.js-empty-state h4').textContent.trim()).toEqual('Build with confidence');
- expect(vm.$el.querySelector('.js-get-started-pipelines').getAttribute('href')).toEqual(paths.helpPagePath);
+ expect(vm.$el.querySelector('.js-empty-state h4').textContent.trim()).toEqual(
+ 'Build with confidence',
+ );
+
+ expect(vm.$el.querySelector('.js-get-started-pipelines').getAttribute('href')).toEqual(
+ paths.helpPagePath,
+ );
});
it('does not render tabs nor buttons', () => {
@@ -171,7 +186,7 @@ describe('Pipelines', () => {
});
describe('When API returns error', () => {
- beforeEach((done) => {
+ beforeEach(done => {
mock.onGet('twitter/flight/pipelines.json').reply(500, {});
vm = mountComponent(PipelinesComponent, {
store: new Store(),
@@ -190,20 +205,27 @@ describe('Pipelines', () => {
});
it('renders buttons', () => {
- expect(vm.$el.querySelector('.js-run-pipeline').getAttribute('href')).toEqual(paths.newPipelinePath);
+ expect(vm.$el.querySelector('.js-run-pipeline').getAttribute('href')).toEqual(
+ paths.newPipelinePath,
+ );
+
expect(vm.$el.querySelector('.js-ci-lint').getAttribute('href')).toEqual(paths.ciLintPath);
- expect(vm.$el.querySelector('.js-clear-cache').textContent.trim()).toEqual('Clear Runner Caches');
+ expect(vm.$el.querySelector('.js-clear-cache').textContent.trim()).toEqual(
+ 'Clear Runner Caches',
+ );
});
it('renders error state', () => {
- expect(vm.$el.querySelector('.empty-state').textContent.trim()).toContain('There was an error fetching the pipelines.');
+ expect(vm.$el.querySelector('.empty-state').textContent.trim()).toContain(
+ 'There was an error fetching the pipelines.',
+ );
});
});
});
describe('Without permission', () => {
describe('With pipelines in main tab', () => {
- beforeEach((done) => {
+ beforeEach(done => {
mock.onGet('twitter/flight/pipelines.json').reply(200, pipelines);
vm = mountComponent(PipelinesComponent, {
@@ -229,14 +251,14 @@ describe('Pipelines', () => {
});
it('renders pipelines table', () => {
- expect(
- vm.$el.querySelectorAll('.gl-responsive-table-row').length,
- ).toEqual(pipelines.pipelines.length + 1);
+ expect(vm.$el.querySelectorAll('.gl-responsive-table-row').length).toEqual(
+ pipelines.pipelines.length + 1,
+ );
});
});
describe('Without pipelines on main tab with CI', () => {
- beforeEach((done) => {
+ beforeEach(done => {
mock.onGet('twitter/flight/pipelines.json').reply(200, {
pipelines: [],
count: {
@@ -270,12 +292,14 @@ describe('Pipelines', () => {
});
it('renders tab empty state', () => {
- expect(vm.$el.querySelector('.empty-state h4').textContent.trim()).toEqual('There are currently no pipelines.');
+ expect(vm.$el.querySelector('.empty-state h4').textContent.trim()).toEqual(
+ 'There are currently no pipelines.',
+ );
});
});
describe('Without pipelines nor CI', () => {
- beforeEach((done) => {
+ beforeEach(done => {
mock.onGet('twitter/flight/pipelines.json').reply(200, {
pipelines: [],
count: {
@@ -299,7 +323,10 @@ describe('Pipelines', () => {
});
it('renders empty state without button to set CI', () => {
- expect(vm.$el.querySelector('.js-empty-state').textContent.trim()).toEqual('This project is not currently set up to run pipelines.');
+ expect(vm.$el.querySelector('.js-empty-state').textContent.trim()).toEqual(
+ 'This project is not currently set up to run pipelines.',
+ );
+
expect(vm.$el.querySelector('.js-get-started-pipelines')).toBeNull();
});
@@ -312,7 +339,7 @@ describe('Pipelines', () => {
});
describe('When API returns error', () => {
- beforeEach((done) => {
+ beforeEach(done => {
mock.onGet('twitter/flight/pipelines.json').reply(500, {});
vm = mountComponent(PipelinesComponent, {
@@ -338,12 +365,14 @@ describe('Pipelines', () => {
});
it('renders error state', () => {
- expect(vm.$el.querySelector('.empty-state').textContent.trim()).toContain('There was an error fetching the pipelines.');
+ expect(vm.$el.querySelector('.empty-state').textContent.trim()).toContain(
+ 'There was an error fetching the pipelines.',
+ );
});
});
});
- describe('successfull request', () => {
+ describe('successful request', () => {
describe('with pipelines', () => {
beforeEach(() => {
mock.onGet('twitter/flight/pipelines.json').reply(200, pipelines);
@@ -356,41 +385,44 @@ describe('Pipelines', () => {
});
});
- it('should render table', (done) => {
+ it('should render table', done => {
setTimeout(() => {
expect(vm.$el.querySelector('.table-holder')).toBeDefined();
- expect(
- vm.$el.querySelectorAll('.gl-responsive-table-row').length,
- ).toEqual(pipelines.pipelines.length + 1);
+ expect(vm.$el.querySelectorAll('.gl-responsive-table-row').length).toEqual(
+ pipelines.pipelines.length + 1,
+ );
done();
});
});
- it('should render navigation tabs', (done) => {
+ it('should render navigation tabs', done => {
setTimeout(() => {
- expect(
- vm.$el.querySelector('.js-pipelines-tab-pending').textContent.trim(),
- ).toContain('Pending');
- expect(
- vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim(),
- ).toContain('All');
- expect(
- vm.$el.querySelector('.js-pipelines-tab-running').textContent.trim(),
- ).toContain('Running');
- expect(
- vm.$el.querySelector('.js-pipelines-tab-finished').textContent.trim(),
- ).toContain('Finished');
- expect(
- vm.$el.querySelector('.js-pipelines-tab-branches').textContent.trim(),
- ).toContain('Branches');
- expect(
- vm.$el.querySelector('.js-pipelines-tab-tags').textContent.trim(),
- ).toContain('Tags');
+ expect(vm.$el.querySelector('.js-pipelines-tab-pending').textContent.trim()).toContain(
+ 'Pending',
+ );
+
+ expect(vm.$el.querySelector('.js-pipelines-tab-all').textContent.trim()).toContain('All');
+
+ expect(vm.$el.querySelector('.js-pipelines-tab-running').textContent.trim()).toContain(
+ 'Running',
+ );
+
+ expect(vm.$el.querySelector('.js-pipelines-tab-finished').textContent.trim()).toContain(
+ 'Finished',
+ );
+
+ expect(vm.$el.querySelector('.js-pipelines-tab-branches').textContent.trim()).toContain(
+ 'Branches',
+ );
+
+ expect(vm.$el.querySelector('.js-pipelines-tab-tags').textContent.trim()).toContain(
+ 'Tags',
+ );
done();
});
});
- it('should make an API request when using tabs', (done) => {
+ it('should make an API request when using tabs', done => {
setTimeout(() => {
spyOn(vm, 'updateContent');
vm.$el.querySelector('.js-pipelines-tab-finished').click();
@@ -401,7 +433,7 @@ describe('Pipelines', () => {
});
describe('with pagination', () => {
- it('should make an API request when using pagination', (done) => {
+ it('should make an API request when using pagination', done => {
setTimeout(() => {
spyOn(vm, 'updateContent');
// Mock pagination
@@ -415,6 +447,7 @@ describe('Pipelines', () => {
vm.$nextTick(() => {
vm.$el.querySelector('.js-next-button a').click();
+
expect(vm.updateContent).toHaveBeenCalledWith({ scope: 'all', page: '2' });
done();
@@ -504,7 +537,7 @@ describe('Pipelines', () => {
});
describe('emptyTabMessage', () => {
- it('returns message with scope', (done) => {
+ it('returns message with scope', done => {
vm.scope = 'pending';
vm.$nextTick(() => {
@@ -523,7 +556,7 @@ describe('Pipelines', () => {
expect(vm.stateToRender).toEqual('loading');
});
- it('returns error state when app has error', (done) => {
+ it('returns error state when app has error', done => {
vm.hasError = true;
vm.isLoading = false;
@@ -533,7 +566,7 @@ describe('Pipelines', () => {
});
});
- it('returns table list when app has pipelines', (done) => {
+ it('returns table list when app has pipelines', done => {
vm.isLoading = false;
vm.hasError = false;
vm.state.pipelines = pipelines.pipelines;
@@ -545,7 +578,7 @@ describe('Pipelines', () => {
});
});
- it('returns empty tab when app does not have pipelines but project has pipelines', (done) => {
+ it('returns empty tab when app does not have pipelines but project has pipelines', done => {
vm.state.count.all = 10;
vm.isLoading = false;
@@ -556,7 +589,7 @@ describe('Pipelines', () => {
});
});
- it('returns empty tab when project has CI', (done) => {
+ it('returns empty tab when project has CI', done => {
vm.isLoading = false;
vm.$nextTick(() => {
expect(vm.stateToRender).toEqual('emptyTab');
@@ -565,7 +598,7 @@ describe('Pipelines', () => {
});
});
- it('returns empty state when project does not have pipelines nor CI', (done) => {
+ it('returns empty state when project does not have pipelines nor CI', done => {
vm.isLoading = false;
vm.hasGitlabCi = false;
vm.$nextTick(() => {
@@ -577,7 +610,7 @@ describe('Pipelines', () => {
});
describe('shouldRenderTabs', () => {
- it('returns true when state is loading & has already made the first request', (done) => {
+ it('returns true when state is loading & has already made the first request', done => {
vm.isLoading = true;
vm.hasMadeRequest = true;
@@ -588,7 +621,7 @@ describe('Pipelines', () => {
});
});
- it('returns true when state is tableList & has already made the first request', (done) => {
+ it('returns true when state is tableList & has already made the first request', done => {
vm.isLoading = false;
vm.state.pipelines = pipelines.pipelines;
vm.hasMadeRequest = true;
@@ -600,7 +633,7 @@ describe('Pipelines', () => {
});
});
- it('returns true when state is error & has already made the first request', (done) => {
+ it('returns true when state is error & has already made the first request', done => {
vm.isLoading = false;
vm.hasError = true;
vm.hasMadeRequest = true;
@@ -612,7 +645,7 @@ describe('Pipelines', () => {
});
});
- it('returns true when state is empty tab & has already made the first request', (done) => {
+ it('returns true when state is empty tab & has already made the first request', done => {
vm.isLoading = false;
vm.state.count.all = 10;
vm.hasMadeRequest = true;
@@ -624,7 +657,7 @@ describe('Pipelines', () => {
});
});
- it('returns false when has not made first request', (done) => {
+ it('returns false when has not made first request', done => {
vm.hasMadeRequest = false;
vm.$nextTick(() => {
@@ -634,7 +667,7 @@ describe('Pipelines', () => {
});
});
- it('returns false when state is emtpy state', (done) => {
+ it('returns false when state is empty state', done => {
vm.isLoading = false;
vm.hasMadeRequest = true;
vm.hasGitlabCi = false;
@@ -648,7 +681,7 @@ describe('Pipelines', () => {
});
describe('shouldRenderButtons', () => {
- it('returns true when it has paths & has made the first request', (done) => {
+ it('returns true when it has paths & has made the first request', done => {
vm.hasMadeRequest = true;
vm.$nextTick(() => {
@@ -658,7 +691,7 @@ describe('Pipelines', () => {
});
});
- it('returns false when it has not made the first request', (done) => {
+ it('returns false when it has not made the first request', done => {
vm.hasMadeRequest = false;
vm.$nextTick(() => {
@@ -675,19 +708,24 @@ describe('Pipelines', () => {
const copyPipeline = Object.assign({}, pipelineWithStages);
copyPipeline.id += 1;
mock
- .onGet('twitter/flight/pipelines.json').reply(200, {
- pipelines: [pipelineWithStages],
- count: {
- all: 1,
- finished: 1,
- pending: 0,
- running: 0,
+ .onGet('twitter/flight/pipelines.json')
+ .reply(
+ 200,
+ {
+ pipelines: [pipelineWithStages],
+ count: {
+ all: 1,
+ finished: 1,
+ pending: 0,
+ running: 0,
+ },
},
- }, {
- 'POLL-INTERVAL': 100,
- })
+ {
+ 'POLL-INTERVAL': 100,
+ },
+ )
.onGet(pipelineWithStages.details.stages[0].dropdown_path)
- .reply(200, stageReply);
+ .reply(200, stageReply);
vm = mountComponent(PipelinesComponent, {
store: new Store(),
@@ -698,7 +736,7 @@ describe('Pipelines', () => {
});
describe('when a request is being made', () => {
- it('stops polling, cancels the request, fetches pipelines & restarts polling', (done) => {
+ it('stops polling, cancels the request, fetches pipelines & restarts polling', done => {
spyOn(vm.poll, 'stop');
spyOn(vm.poll, 'restart');
spyOn(vm, 'getPipelines').and.returnValue(Promise.resolve());
@@ -706,7 +744,8 @@ describe('Pipelines', () => {
setTimeout(() => {
vm.isMakingRequest = true;
- return vm.$nextTick()
+ return vm
+ .$nextTick()
.then(() => {
vm.$el.querySelector('.js-builds-dropdown-button').click();
})
@@ -719,13 +758,14 @@ describe('Pipelines', () => {
expect(vm.poll.restart).toHaveBeenCalled();
done();
}, 0);
- });
+ })
+ .catch(done.fail);
}, 0);
});
});
describe('when no request is being made', () => {
- it('stops polling, fetches pipelines & restarts polling', (done) => {
+ it('stops polling, fetches pipelines & restarts polling', done => {
spyOn(vm.poll, 'stop');
spyOn(vm.poll, 'restart');
spyOn(vm, 'getPipelines').and.returnValue(Promise.resolve());
diff --git a/spec/javascripts/pipelines/pipelines_store_spec.js b/spec/javascripts/pipelines/pipelines_store_spec.js
index 10ff0c6bb84..ce21f788ed5 100644
--- a/spec/javascripts/pipelines/pipelines_store_spec.js
+++ b/spec/javascripts/pipelines/pipelines_store_spec.js
@@ -16,12 +16,14 @@ describe('Pipelines Store', () => {
describe('storePipelines', () => {
it('should use the default parameter if none is provided', () => {
store.storePipelines();
+
expect(store.state.pipelines).toEqual([]);
});
it('should store the provided array', () => {
const array = [{ id: 1, status: 'running' }, { id: 2, status: 'success' }];
store.storePipelines(array);
+
expect(store.state.pipelines).toEqual(array);
});
});
@@ -29,6 +31,7 @@ describe('Pipelines Store', () => {
describe('storeCount', () => {
it('should use the default parameter if none is provided', () => {
store.storeCount();
+
expect(store.state.count).toEqual({});
});
@@ -43,6 +46,7 @@ describe('Pipelines Store', () => {
describe('storePagination', () => {
it('should use the default parameter if none is provided', () => {
store.storePagination();
+
expect(store.state.pageInfo).toEqual({});
});
@@ -66,6 +70,7 @@ describe('Pipelines Store', () => {
};
store.storePagination(pagination);
+
expect(store.state.pageInfo).toEqual(expectedResult);
});
});
diff --git a/spec/javascripts/pipelines/pipelines_table_row_spec.js b/spec/javascripts/pipelines/pipelines_table_row_spec.js
index 03ffc122795..4c575536f0e 100644
--- a/spec/javascripts/pipelines/pipelines_table_row_spec.js
+++ b/spec/javascripts/pipelines/pipelines_table_row_spec.js
@@ -37,6 +37,7 @@ describe('Pipelines Table Row', () => {
it('should render a table row', () => {
component = buildComponent(pipeline);
+
expect(component.$el.getAttribute('class')).toContain('gl-responsive-table-row');
});
@@ -85,8 +86,8 @@ describe('Pipelines Table Row', () => {
expect(
component.$el
- .querySelector('.table-section:nth-child(2) img')
- .getAttribute('data-original-title'),
+ .querySelector('.table-section:nth-child(2) .js-user-avatar-image-toolip')
+ .textContent.trim(),
).toEqual(pipeline.user.name);
});
});
@@ -97,6 +98,7 @@ describe('Pipelines Table Row', () => {
component = buildComponent(pipeline);
const commitLink = component.$el.querySelector('.branch-commit .commit-sha');
+
expect(commitLink.getAttribute('href')).toEqual(pipeline.commit.commit_path);
});
@@ -110,8 +112,8 @@ describe('Pipelines Table Row', () => {
const commitAuthorLink = commitAuthorElement.getAttribute('href');
const commitAuthorName = commitAuthorElement
- .querySelector('img.avatar')
- .getAttribute('data-original-title');
+ .querySelector('.js-user-avatar-image-toolip')
+ .textContent.trim();
return { commitAuthorElement, commitAuthorLink, commitAuthorName };
};
@@ -158,8 +160,13 @@ describe('Pipelines Table Row', () => {
});
describe('actions column', () => {
+ const scheduledJobAction = {
+ name: 'some scheduled job',
+ };
+
beforeEach(() => {
const withActions = Object.assign({}, pipeline);
+ withActions.details.scheduled_actions = [scheduledJobAction];
withActions.flags.cancelable = true;
withActions.flags.retryable = true;
withActions.cancel_path = '/cancel';
@@ -171,6 +178,9 @@ describe('Pipelines Table Row', () => {
it('should render the provided actions', () => {
expect(component.$el.querySelector('.js-pipelines-retry-button')).not.toBeNull();
expect(component.$el.querySelector('.js-pipelines-cancel-button')).not.toBeNull();
+ const dropdownMenu = component.$el.querySelectorAll('.dropdown-menu');
+
+ expect(dropdownMenu).toContainText(scheduledJobAction.name);
});
it('emits `retryPipeline` event when retry button is clicked and toggles loading', () => {
@@ -179,6 +189,7 @@ describe('Pipelines Table Row', () => {
});
component.$el.querySelector('.js-pipelines-retry-button').click();
+
expect(component.isRetrying).toEqual(true);
});
@@ -193,7 +204,8 @@ describe('Pipelines Table Row', () => {
it('renders a loading icon when `cancelingPipeline` matches pipeline id', done => {
component.cancelingPipeline = pipeline.id;
- component.$nextTick()
+ component
+ .$nextTick()
.then(() => {
expect(component.isCancelling).toEqual(true);
})
diff --git a/spec/javascripts/pipelines/pipelines_table_spec.js b/spec/javascripts/pipelines/pipelines_table_spec.js
index d21ba35e96d..5c3387190ab 100644
--- a/spec/javascripts/pipelines/pipelines_table_spec.js
+++ b/spec/javascripts/pipelines/pipelines_table_spec.js
@@ -38,10 +38,21 @@ describe('Pipelines Table', () => {
});
it('should render table head with correct columns', () => {
- expect(component.$el.querySelector('.table-section.js-pipeline-status').textContent.trim()).toEqual('Status');
- expect(component.$el.querySelector('.table-section.js-pipeline-info').textContent.trim()).toEqual('Pipeline');
- expect(component.$el.querySelector('.table-section.js-pipeline-commit').textContent.trim()).toEqual('Commit');
- expect(component.$el.querySelector('.table-section.js-pipeline-stages').textContent.trim()).toEqual('Stages');
+ expect(
+ component.$el.querySelector('.table-section.js-pipeline-status').textContent.trim(),
+ ).toEqual('Status');
+
+ expect(
+ component.$el.querySelector('.table-section.js-pipeline-info').textContent.trim(),
+ ).toEqual('Pipeline');
+
+ expect(
+ component.$el.querySelector('.table-section.js-pipeline-commit').textContent.trim(),
+ ).toEqual('Commit');
+
+ expect(
+ component.$el.querySelector('.table-section.js-pipeline-stages').textContent.trim(),
+ ).toEqual('Stages');
});
});
@@ -54,6 +65,7 @@ describe('Pipelines Table', () => {
viewType: 'root',
},
}).$mount();
+
expect(component.$el.querySelectorAll('.commit.gl-responsive-table-row').length).toEqual(0);
});
});
diff --git a/spec/javascripts/pipelines/stage_spec.js b/spec/javascripts/pipelines/stage_spec.js
index 3f6789759ae..3c8b8032de8 100644
--- a/spec/javascripts/pipelines/stage_spec.js
+++ b/spec/javascripts/pipelines/stage_spec.js
@@ -40,7 +40,7 @@ describe('Pipelines stage component', () => {
expect(component.$el.querySelector('button').getAttribute('data-toggle')).toEqual('dropdown');
});
- describe('with successfull request', () => {
+ describe('with successful request', () => {
beforeEach(() => {
mock.onGet('path.json').reply(200, stageReply);
});
@@ -53,6 +53,7 @@ describe('Pipelines stage component', () => {
expect(
component.$el.querySelector('.js-builds-dropdown-container ul').textContent.trim(),
).toContain(stageReply.latest_statuses[0].name);
+
expect(eventHub.$emit).toHaveBeenCalledWith('clickedDropdown');
done();
}, 0);
@@ -119,12 +120,13 @@ describe('Pipelines stage component', () => {
setTimeout(() => {
component.$el.querySelector('.js-ci-action').click();
- component.$nextTick()
- .then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('refreshPipelinesTable');
- })
- .then(done)
- .catch(done.fail);
+ component
+ .$nextTick()
+ .then(() => {
+ expect(eventHub.$emit).toHaveBeenCalledWith('refreshPipelinesTable');
+ })
+ .then(done)
+ .catch(done.fail);
}, 0);
});
});
diff --git a/spec/javascripts/pipelines_spec.js b/spec/javascripts/pipelines_spec.js
index c08a73851be..6b86f9ea437 100644
--- a/spec/javascripts/pipelines_spec.js
+++ b/spec/javascripts/pipelines_spec.js
@@ -12,6 +12,8 @@ describe('Pipelines', () => {
});
it('should create a `Pipelines` instance without options', () => {
- expect(() => { new Pipelines(); }).not.toThrow(); //eslint-disable-line
+ expect(() => {
+ new Pipelines(); // eslint-disable-line no-new
+ }).not.toThrow();
});
});
diff --git a/spec/javascripts/polyfills/element_spec.js b/spec/javascripts/polyfills/element_spec.js
index ecaaf1907ea..d35df595c72 100644
--- a/spec/javascripts/polyfills/element_spec.js
+++ b/spec/javascripts/polyfills/element_spec.js
@@ -1,6 +1,6 @@
import '~/commons/polyfills/element';
-describe('Element polyfills', function () {
+describe('Element polyfills', function() {
beforeEach(() => {
this.element = document.createElement('ul');
});
diff --git a/spec/javascripts/pretty_time_spec.js b/spec/javascripts/pretty_time_spec.js
deleted file mode 100644
index 084ffe08917..00000000000
--- a/spec/javascripts/pretty_time_spec.js
+++ /dev/null
@@ -1,133 +0,0 @@
-import { parseSeconds, abbreviateTime, stringifyTime } from '~/lib/utils/pretty_time';
-
-function assertTimeUnits(obj, minutes, hours, days, weeks) {
- expect(obj.minutes).toBe(minutes);
- expect(obj.hours).toBe(hours);
- expect(obj.days).toBe(days);
- expect(obj.weeks).toBe(weeks);
-}
-
-describe('prettyTime methods', () => {
- describe('parseSeconds', () => {
- it('should correctly parse a negative value', () => {
- const zeroSeconds = parseSeconds(-1000);
-
- assertTimeUnits(zeroSeconds, 16, 0, 0, 0);
- });
-
- it('should correctly parse a zero value', () => {
- const zeroSeconds = parseSeconds(0);
-
- assertTimeUnits(zeroSeconds, 0, 0, 0, 0);
- });
-
- it('should correctly parse a small non-zero second values', () => {
- const subOneMinute = parseSeconds(10);
- const aboveOneMinute = parseSeconds(100);
- const manyMinutes = parseSeconds(1000);
-
- assertTimeUnits(subOneMinute, 0, 0, 0, 0);
- assertTimeUnits(aboveOneMinute, 1, 0, 0, 0);
- assertTimeUnits(manyMinutes, 16, 0, 0, 0);
- });
-
- it('should correctly parse large second values', () => {
- const aboveOneHour = parseSeconds(4800);
- const aboveOneDay = parseSeconds(110000);
- const aboveOneWeek = parseSeconds(25000000);
-
- assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
- assertTimeUnits(aboveOneDay, 33, 6, 3, 0);
- assertTimeUnits(aboveOneWeek, 26, 0, 3, 173);
- });
-
- it('should correctly accept a custom param for hoursPerDay', () => {
- const config = { hoursPerDay: 24 };
-
- const aboveOneHour = parseSeconds(4800, config);
- const aboveOneDay = parseSeconds(110000, config);
- const aboveOneWeek = parseSeconds(25000000, config);
-
- assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
- assertTimeUnits(aboveOneDay, 33, 6, 1, 0);
- assertTimeUnits(aboveOneWeek, 26, 8, 4, 57);
- });
-
- it('should correctly accept a custom param for daysPerWeek', () => {
- const config = { daysPerWeek: 7 };
-
- const aboveOneHour = parseSeconds(4800, config);
- const aboveOneDay = parseSeconds(110000, config);
- const aboveOneWeek = parseSeconds(25000000, config);
-
- assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
- assertTimeUnits(aboveOneDay, 33, 6, 3, 0);
- assertTimeUnits(aboveOneWeek, 26, 0, 0, 124);
- });
-
- it('should correctly accept custom params for daysPerWeek and hoursPerDay', () => {
- const config = { daysPerWeek: 55, hoursPerDay: 14 };
-
- const aboveOneHour = parseSeconds(4800, config);
- const aboveOneDay = parseSeconds(110000, config);
- const aboveOneWeek = parseSeconds(25000000, config);
-
- assertTimeUnits(aboveOneHour, 20, 1, 0, 0);
- assertTimeUnits(aboveOneDay, 33, 2, 2, 0);
- assertTimeUnits(aboveOneWeek, 26, 0, 1, 9);
- });
- });
-
- describe('stringifyTime', () => {
- it('should stringify values with all non-zero units', () => {
- const timeObject = {
- weeks: 1,
- days: 4,
- hours: 7,
- minutes: 20,
- };
-
- const timeString = stringifyTime(timeObject);
-
- expect(timeString).toBe('1w 4d 7h 20m');
- });
-
- it('should stringify values with some non-zero units', () => {
- const timeObject = {
- weeks: 0,
- days: 4,
- hours: 0,
- minutes: 20,
- };
-
- const timeString = stringifyTime(timeObject);
-
- expect(timeString).toBe('4d 20m');
- });
-
- it('should stringify values with no non-zero units', () => {
- const timeObject = {
- weeks: 0,
- days: 0,
- hours: 0,
- minutes: 0,
- };
-
- const timeString = stringifyTime(timeObject);
-
- expect(timeString).toBe('0m');
- });
- });
-
- describe('abbreviateTime', () => {
- it('should abbreviate stringified times for weeks', () => {
- const fullTimeString = '1w 3d 4h 5m';
- expect(abbreviateTime(fullTimeString)).toBe('1w');
- });
-
- it('should abbreviate stringified times for non-weeks', () => {
- const fullTimeString = '0w 3d 4h 5m';
- expect(abbreviateTime(fullTimeString)).toBe('3d');
- });
- });
-});
diff --git a/spec/javascripts/profile/account/components/delete_account_modal_spec.js b/spec/javascripts/profile/account/components/delete_account_modal_spec.js
index a0939ff5c20..d5f5cabc63e 100644
--- a/spec/javascripts/profile/account/components/delete_account_modal_spec.js
+++ b/spec/javascripts/profile/account/components/delete_account_modal_spec.js
@@ -28,7 +28,7 @@ describe('DeleteAccountModal component', () => {
};
describe('with password confirmation', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm = mountComponent(Component, {
actionUrl,
confirmWithPassword: true,
@@ -42,7 +42,7 @@ describe('DeleteAccountModal component', () => {
.catch(done.fail);
});
- it('does not accept empty password', (done) => {
+ it('does not accept empty password', done => {
const { form, input, submitButton } = findElements();
spyOn(form, 'submit');
input.value = '';
@@ -53,13 +53,14 @@ describe('DeleteAccountModal component', () => {
expect(vm.enteredPassword).toBe(input.value);
expect(submitButton).toHaveAttr('disabled', 'disabled');
submitButton.click();
+
expect(form.submit).not.toHaveBeenCalled();
})
.then(done)
.catch(done.fail);
});
- it('submits form with password', (done) => {
+ it('submits form with password', done => {
const { form, input, submitButton } = findElements();
spyOn(form, 'submit');
input.value = 'anything';
@@ -70,6 +71,7 @@ describe('DeleteAccountModal component', () => {
expect(vm.enteredPassword).toBe(input.value);
expect(submitButton).not.toHaveAttr('disabled', 'disabled');
submitButton.click();
+
expect(form.submit).toHaveBeenCalled();
})
.then(done)
@@ -78,7 +80,7 @@ describe('DeleteAccountModal component', () => {
});
describe('with username confirmation', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm = mountComponent(Component, {
actionUrl,
confirmWithPassword: false,
@@ -92,7 +94,7 @@ describe('DeleteAccountModal component', () => {
.catch(done.fail);
});
- it('does not accept wrong username', (done) => {
+ it('does not accept wrong username', done => {
const { form, input, submitButton } = findElements();
spyOn(form, 'submit');
input.value = 'this is wrong';
@@ -103,13 +105,14 @@ describe('DeleteAccountModal component', () => {
expect(vm.enteredUsername).toBe(input.value);
expect(submitButton).toHaveAttr('disabled', 'disabled');
submitButton.click();
+
expect(form.submit).not.toHaveBeenCalled();
})
.then(done)
.catch(done.fail);
});
- it('submits form with correct username', (done) => {
+ it('submits form with correct username', done => {
const { form, input, submitButton } = findElements();
spyOn(form, 'submit');
input.value = username;
@@ -120,6 +123,7 @@ describe('DeleteAccountModal component', () => {
expect(vm.enteredUsername).toBe(input.value);
expect(submitButton).not.toHaveAttr('disabled', 'disabled');
submitButton.click();
+
expect(form.submit).toHaveBeenCalled();
})
.then(done)
diff --git a/spec/javascripts/profile/account/components/update_username_spec.js b/spec/javascripts/profile/account/components/update_username_spec.js
index 5311499fb73..cc07a5f6e43 100644
--- a/spec/javascripts/profile/account/components/update_username_spec.js
+++ b/spec/javascripts/profile/account/components/update_username_spec.js
@@ -113,6 +113,7 @@ describe('UpdateUsername component', () => {
Vue.nextTick()
.then(() => {
confirmModalBtn.click();
+
expect(axios.put).toHaveBeenCalledWith(actionUrl, { user: { username: newUsername } });
})
.then(done)
@@ -131,8 +132,7 @@ describe('UpdateUsername component', () => {
vm.newUsername = newUsername;
- vm
- .onConfirm()
+ vm.onConfirm()
.then(() => {
expect(vm.username).toBe(newUsername);
expect(vm.newUsername).toBe(newUsername);
@@ -157,8 +157,7 @@ describe('UpdateUsername component', () => {
const invalidUsername = 'anything.git';
vm.newUsername = invalidUsername;
- vm
- .onConfirm()
+ vm.onConfirm()
.then(() => done.fail('Expected onConfirm to throw!'))
.catch(() => {
expect(vm.username).toBe(username);
diff --git a/spec/javascripts/project_select_combo_button_spec.js b/spec/javascripts/project_select_combo_button_spec.js
index 1b65f767f96..109a5000f5d 100644
--- a/spec/javascripts/project_select_combo_button_spec.js
+++ b/spec/javascripts/project_select_combo_button_spec.js
@@ -3,10 +3,10 @@ import ProjectSelectComboButton from '~/project_select_combo_button';
const fixturePath = 'static/project_select_combo_button.html.raw';
-describe('Project Select Combo Button', function () {
+describe('Project Select Combo Button', function() {
preloadFixtures(fixturePath);
- beforeEach(function () {
+ beforeEach(function() {
this.defaults = {
label: 'Select project to create issue',
groupId: 12345,
@@ -28,43 +28,44 @@ describe('Project Select Combo Button', function () {
this.projectSelectInput = document.querySelector('.project-item-select');
});
- describe('on page load when localStorage is empty', function () {
- beforeEach(function () {
+ describe('on page load when localStorage is empty', function() {
+ beforeEach(function() {
this.comboButton = new ProjectSelectComboButton(this.projectSelectInput);
});
- it('newItemBtn href is null', function () {
+ it('newItemBtn href is null', function() {
expect(this.newItemBtn.getAttribute('href')).toBe('');
});
- it('newItemBtn text is the plain default label', function () {
+ it('newItemBtn text is the plain default label', function() {
expect(this.newItemBtn.textContent).toBe(this.defaults.label);
});
});
- describe('on page load when localStorage is filled', function () {
- beforeEach(function () {
- window.localStorage
- .setItem(this.defaults.localStorageKey, JSON.stringify(this.defaults.projectMeta));
+ describe('on page load when localStorage is filled', function() {
+ beforeEach(function() {
+ window.localStorage.setItem(
+ this.defaults.localStorageKey,
+ JSON.stringify(this.defaults.projectMeta),
+ );
this.comboButton = new ProjectSelectComboButton(this.projectSelectInput);
});
- it('newItemBtn href is correctly set', function () {
+ it('newItemBtn href is correctly set', function() {
expect(this.newItemBtn.getAttribute('href')).toBe(this.defaults.projectMeta.url);
});
- it('newItemBtn text is the cached label', function () {
- expect(this.newItemBtn.textContent)
- .toBe(`New issue in ${this.defaults.projectMeta.name}`);
+ it('newItemBtn text is the cached label', function() {
+ expect(this.newItemBtn.textContent).toBe(`New issue in ${this.defaults.projectMeta.name}`);
});
- afterEach(function () {
+ afterEach(function() {
window.localStorage.clear();
});
});
- describe('after selecting a new project', function () {
- beforeEach(function () {
+ describe('after selecting a new project', function() {
+ beforeEach(function() {
this.comboButton = new ProjectSelectComboButton(this.projectSelectInput);
// mock the effect of selecting an item from the projects dropdown (select2)
@@ -73,23 +74,21 @@ describe('Project Select Combo Button', function () {
.trigger('change');
});
- it('newItemBtn href is correctly set', function () {
- expect(this.newItemBtn.getAttribute('href'))
- .toBe('http://myothercoolproject.com/issues/new');
+ it('newItemBtn href is correctly set', function() {
+ expect(this.newItemBtn.getAttribute('href')).toBe('http://myothercoolproject.com/issues/new');
});
- it('newItemBtn text is the selected project label', function () {
- expect(this.newItemBtn.textContent)
- .toBe(`New issue in ${this.defaults.newProjectMeta.name}`);
+ it('newItemBtn text is the selected project label', function() {
+ expect(this.newItemBtn.textContent).toBe(`New issue in ${this.defaults.newProjectMeta.name}`);
});
- afterEach(function () {
+ afterEach(function() {
window.localStorage.clear();
});
});
- describe('deriveTextVariants', function () {
- beforeEach(function () {
+ describe('deriveTextVariants', function() {
+ beforeEach(function() {
this.mockExecutionContext = {
resourceType: '',
resourceLabel: '',
@@ -100,7 +99,7 @@ describe('Project Select Combo Button', function () {
this.method = this.comboButton.deriveTextVariants.bind(this.mockExecutionContext);
});
- it('correctly derives test variants for merge requests', function () {
+ it('correctly derives test variants for merge requests', function() {
this.mockExecutionContext.resourceType = 'merge_requests';
this.mockExecutionContext.resourceLabel = 'New merge request';
@@ -111,7 +110,7 @@ describe('Project Select Combo Button', function () {
expect(returnedVariants.presetTextSuffix).toBe('merge request');
});
- it('correctly derives text variants for issues', function () {
+ it('correctly derives text variants for issues', function() {
this.mockExecutionContext.resourceType = 'issues';
this.mockExecutionContext.resourceLabel = 'New issue';
@@ -123,4 +122,3 @@ describe('Project Select Combo Button', function () {
});
});
});
-
diff --git a/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown_spec.js b/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown_spec.js
index 21805ef0b28..fdecb823cd2 100644
--- a/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown_spec.js
+++ b/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown_spec.js
@@ -90,14 +90,20 @@ describe('GkeMachineTypeDropdown', () => {
expect(vm.$el.querySelector('input').value).toBe('');
vm.$store.commit(SET_MACHINE_TYPES, gapiMachineTypesResponseMock.items);
- return vm.$nextTick().then(() => {
- vm.$el.querySelector('.dropdown-content button').click();
-
- return vm.$nextTick().then(() => {
- expect(vm.$el.querySelector('input').value).toBe(selectedMachineTypeMock);
- done();
- });
- });
+ return vm
+ .$nextTick()
+ .then(() => {
+ vm.$el.querySelector('.dropdown-content button').click();
+
+ return vm
+ .$nextTick()
+ .then(() => {
+ expect(vm.$el.querySelector('input').value).toBe(selectedMachineTypeMock);
+ done();
+ })
+ .catch(done.fail);
+ })
+ .catch(done.fail);
});
});
});
diff --git a/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown_spec.js b/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown_spec.js
index d4fcb2dc8ff..030662b4d90 100644
--- a/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown_spec.js
+++ b/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown_spec.js
@@ -48,45 +48,61 @@ describe('GkeProjectIdDropdown', () => {
it('returns project billing validation text', () => {
vm.setIsValidatingProjectBilling(true);
+
expect(vm.toggleText).toBe(LABELS.VALIDATING_PROJECT_BILLING);
});
it('returns default toggle text', done =>
- vm.$nextTick().then(() => {
- vm.setItem(emptyProjectMock);
+ vm
+ .$nextTick()
+ .then(() => {
+ vm.setItem(emptyProjectMock);
- expect(vm.toggleText).toBe(LABELS.DEFAULT);
- done();
- }));
+ expect(vm.toggleText).toBe(LABELS.DEFAULT);
+ done();
+ })
+ .catch(done.fail));
it('returns project name if project selected', done =>
- vm.$nextTick().then(() => {
- expect(vm.toggleText).toBe(selectedProjectMock.name);
- done();
- }));
+ vm
+ .$nextTick()
+ .then(() => {
+ expect(vm.toggleText).toBe(selectedProjectMock.name);
+ done();
+ })
+ .catch(done.fail));
it('returns empty toggle text', done =>
- vm.$nextTick().then(() => {
- vm.$store.commit(SET_PROJECTS, null);
- vm.setItem(emptyProjectMock);
+ vm
+ .$nextTick()
+ .then(() => {
+ vm.$store.commit(SET_PROJECTS, null);
+ vm.setItem(emptyProjectMock);
- expect(vm.toggleText).toBe(LABELS.EMPTY);
- done();
- }));
+ expect(vm.toggleText).toBe(LABELS.EMPTY);
+ done();
+ })
+ .catch(done.fail));
});
describe('selectItem', () => {
it('reflects new value when dropdown item is clicked', done => {
expect(vm.$el.querySelector('input').value).toBe('');
- return vm.$nextTick().then(() => {
- vm.$el.querySelector('.dropdown-content button').click();
-
- return vm.$nextTick().then(() => {
- expect(vm.$el.querySelector('input').value).toBe(selectedProjectMock.projectId);
- done();
- });
- });
+ return vm
+ .$nextTick()
+ .then(() => {
+ vm.$el.querySelector('.dropdown-content button').click();
+
+ return vm
+ .$nextTick()
+ .then(() => {
+ expect(vm.$el.querySelector('input').value).toBe(selectedProjectMock.projectId);
+ done();
+ })
+ .catch(done.fail);
+ })
+ .catch(done.fail);
});
});
});
diff --git a/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown_spec.js b/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown_spec.js
index 89a4a7ea2ce..95186e19ca1 100644
--- a/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown_spec.js
+++ b/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown_spec.js
@@ -75,14 +75,20 @@ describe('GkeZoneDropdown', () => {
expect(vm.$el.querySelector('input').value).toBe('');
vm.$store.commit(SET_ZONES, gapiZonesResponseMock.items);
- return vm.$nextTick().then(() => {
- vm.$el.querySelector('.dropdown-content button').click();
-
- return vm.$nextTick().then(() => {
- expect(vm.$el.querySelector('input').value).toBe(selectedZoneMock);
- done();
- });
- });
+ return vm
+ .$nextTick()
+ .then(() => {
+ vm.$el.querySelector('.dropdown-content button').click();
+
+ return vm
+ .$nextTick()
+ .then(() => {
+ expect(vm.$el.querySelector('input').value).toBe(selectedZoneMock);
+ done();
+ })
+ .catch(done.fail);
+ })
+ .catch(done.fail);
});
});
});
diff --git a/spec/javascripts/projects/project_new_spec.js b/spec/javascripts/projects/project_new_spec.js
index dace834a3c8..b61e0ac872f 100644
--- a/spec/javascripts/projects/project_new_spec.js
+++ b/spec/javascripts/projects/project_new_spec.js
@@ -27,7 +27,10 @@ describe('New Project', () => {
beforeEach(() => {
projectNew.bindEvents();
- $projectPath.val('').keyup().val(dummyImportUrl);
+ $projectPath
+ .val('')
+ .keyup()
+ .val(dummyImportUrl);
});
it('does not change project path for disabled $projectImportUrl', () => {
diff --git a/spec/javascripts/prometheus_metrics/prometheus_metrics_spec.js b/spec/javascripts/prometheus_metrics/prometheus_metrics_spec.js
index 955ec6a531c..94e2f959d46 100644
--- a/spec/javascripts/prometheus_metrics/prometheus_metrics_spec.js
+++ b/spec/javascripts/prometheus_metrics/prometheus_metrics_spec.js
@@ -85,9 +85,17 @@ describe('PrometheusMetrics', () => {
expect(prometheusMetrics.$monitoredMetricsLoading.hasClass('hidden')).toBeTruthy();
expect(prometheusMetrics.$monitoredMetricsList.hasClass('hidden')).toBeFalsy();
- expect(prometheusMetrics.$monitoredMetricsCount.text()).toEqual('3 exporters with 12 metrics were found');
+ expect(prometheusMetrics.$monitoredMetricsCount.text()).toEqual(
+ '3 exporters with 12 metrics were found',
+ );
+
expect($metricsListLi.length).toEqual(metrics.length);
- expect($metricsListLi.first().find('.badge').text()).toEqual(`${metrics[0].active_metrics}`);
+ expect(
+ $metricsListLi
+ .first()
+ .find('.badge')
+ .text(),
+ ).toEqual(`${metrics[0].active_metrics}`);
});
it('should show missing environment variables list', () => {
@@ -129,7 +137,7 @@ describe('PrometheusMetrics', () => {
mock.restore();
});
- it('should show loader animation while response is being loaded and hide it when request is complete', (done) => {
+ it('should show loader animation while response is being loaded and hide it when request is complete', done => {
mockSuccess();
prometheusMetrics.loadActiveMetrics();
@@ -143,7 +151,7 @@ describe('PrometheusMetrics', () => {
});
});
- it('should show empty state if response failed to load', (done) => {
+ it('should show empty state if response failed to load', done => {
mockError();
prometheusMetrics.loadActiveMetrics();
@@ -155,7 +163,7 @@ describe('PrometheusMetrics', () => {
});
});
- it('should populate metrics list once response is loaded', (done) => {
+ it('should populate metrics list once response is loaded', done => {
spyOn(prometheusMetrics, 'populateActiveMetrics');
mockSuccess();
diff --git a/spec/javascripts/raven/raven_config_spec.js b/spec/javascripts/raven/raven_config_spec.js
index c82658b9262..5cc59cc28d3 100644
--- a/spec/javascripts/raven/raven_config_spec.js
+++ b/spec/javascripts/raven/raven_config_spec.js
@@ -133,7 +133,7 @@ describe('RavenConfig', () => {
RavenConfig.setUser.call(ravenConfig);
});
- it('should call .setUserContext', function () {
+ it('should call .setUserContext', function() {
expect(Raven.setUserContext).toHaveBeenCalledWith({
id: ravenConfig.options.currentUserId,
});
diff --git a/spec/javascripts/registry/components/app_spec.js b/spec/javascripts/registry/components/app_spec.js
index cf1d0625397..92ff960277a 100644
--- a/spec/javascripts/registry/components/app_spec.js
+++ b/spec/javascripts/registry/components/app_spec.js
@@ -18,9 +18,11 @@ describe('Registry List', () => {
describe('with data', () => {
const interceptor = (request, next) => {
- next(request.respondWith(JSON.stringify(reposServerResponse), {
- status: 200,
- }));
+ next(
+ request.respondWith(JSON.stringify(reposServerResponse), {
+ status: 200,
+ }),
+ );
};
beforeEach(() => {
@@ -32,21 +34,21 @@ describe('Registry List', () => {
Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor);
});
- it('should render a list of repos', (done) => {
+ it('should render a list of repos', done => {
setTimeout(() => {
expect(vm.$store.state.repos.length).toEqual(reposServerResponse.length);
Vue.nextTick(() => {
- expect(
- vm.$el.querySelectorAll('.container-image').length,
- ).toEqual(reposServerResponse.length);
+ expect(vm.$el.querySelectorAll('.container-image').length).toEqual(
+ reposServerResponse.length,
+ );
done();
});
}, 0);
});
describe('delete repository', () => {
- it('should be possible to delete a repo', (done) => {
+ it('should be possible to delete a repo', done => {
setTimeout(() => {
Vue.nextTick(() => {
expect(vm.$el.querySelector('.container-image-head .js-remove-repo')).toBeDefined();
@@ -57,12 +59,14 @@ describe('Registry List', () => {
});
describe('toggle repository', () => {
- it('should open the container', (done) => {
+ it('should open the container', done => {
setTimeout(() => {
Vue.nextTick(() => {
vm.$el.querySelector('.js-toggle-repo').click();
Vue.nextTick(() => {
- expect(vm.$el.querySelector('.js-toggle-repo i').className).toEqual('fa fa-chevron-up');
+ expect(vm.$el.querySelector('.js-toggle-repo i').className).toEqual(
+ 'fa fa-chevron-up',
+ );
done();
});
});
@@ -73,9 +77,11 @@ describe('Registry List', () => {
describe('without data', () => {
const interceptor = (request, next) => {
- next(request.respondWith(JSON.stringify([]), {
- status: 200,
- }));
+ next(
+ request.respondWith(JSON.stringify([]), {
+ status: 200,
+ }),
+ );
};
beforeEach(() => {
@@ -87,11 +93,16 @@ describe('Registry List', () => {
Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor);
});
- it('should render empty message', (done) => {
+ it('should render empty message', done => {
setTimeout(() => {
expect(
- vm.$el.querySelector('p').textContent.trim().replace(/[\r\n]+/g, ' '),
- ).toEqual('No container images stored for this project. Add one by following the instructions above.');
+ vm.$el
+ .querySelector('p')
+ .textContent.trim()
+ .replace(/[\r\n]+/g, ' '),
+ ).toEqual(
+ 'No container images stored for this project. Add one by following the instructions above.',
+ );
done();
}, 0);
});
@@ -99,9 +110,11 @@ describe('Registry List', () => {
describe('while loading data', () => {
const interceptor = (request, next) => {
- next(request.respondWith(JSON.stringify(reposServerResponse), {
- status: 200,
- }));
+ next(
+ request.respondWith(JSON.stringify(reposServerResponse), {
+ status: 200,
+ }),
+ );
};
beforeEach(() => {
@@ -113,7 +126,7 @@ describe('Registry List', () => {
Vue.http.interceptors = _.without(Vue.http.interceptors, interceptor);
});
- it('should render a loading spinner', (done) => {
+ it('should render a loading spinner', done => {
Vue.nextTick(() => {
expect(vm.$el.querySelector('.fa-spinner')).not.toBe(null);
done();
diff --git a/spec/javascripts/registry/components/collapsible_container_spec.js b/spec/javascripts/registry/components/collapsible_container_spec.js
index 5891921318a..256a242f784 100644
--- a/spec/javascripts/registry/components/collapsible_container_spec.js
+++ b/spec/javascripts/registry/components/collapsible_container_spec.js
@@ -24,26 +24,32 @@ describe('collapsible registry container', () => {
describe('toggle', () => {
it('should be closed by default', () => {
expect(vm.$el.querySelector('.container-image-tags')).toBe(null);
- expect(vm.$el.querySelector('.container-image-head i').className).toEqual('fa fa-chevron-right');
+ expect(vm.$el.querySelector('.container-image-head i').className).toEqual(
+ 'fa fa-chevron-right',
+ );
});
- it('should be open when user clicks on closed repo', (done) => {
+ it('should be open when user clicks on closed repo', done => {
vm.$el.querySelector('.js-toggle-repo').click();
Vue.nextTick(() => {
expect(vm.$el.querySelector('.container-image-tags')).toBeDefined();
- expect(vm.$el.querySelector('.container-image-head i').className).toEqual('fa fa-chevron-up');
+ expect(vm.$el.querySelector('.container-image-head i').className).toEqual(
+ 'fa fa-chevron-up',
+ );
done();
});
});
- it('should be closed when the user clicks on an opened repo', (done) => {
+ it('should be closed when the user clicks on an opened repo', done => {
vm.$el.querySelector('.js-toggle-repo').click();
Vue.nextTick(() => {
vm.$el.querySelector('.js-toggle-repo').click();
Vue.nextTick(() => {
expect(vm.$el.querySelector('.container-image-tags')).toBe(null);
- expect(vm.$el.querySelector('.container-image-head i').className).toEqual('fa fa-chevron-right');
+ expect(vm.$el.querySelector('.container-image-head i').className).toEqual(
+ 'fa fa-chevron-right',
+ );
done();
});
});
diff --git a/spec/javascripts/registry/components/table_registry_spec.js b/spec/javascripts/registry/components/table_registry_spec.js
index 6aa61afc445..7f5252a7d6c 100644
--- a/spec/javascripts/registry/components/table_registry_spec.js
+++ b/spec/javascripts/registry/components/table_registry_spec.js
@@ -22,13 +22,15 @@ describe('table registry', () => {
});
it('should render a table with the registry list', () => {
- expect(
- vm.$el.querySelectorAll('table tbody tr').length,
- ).toEqual(repoPropsData.list.length);
+ expect(vm.$el.querySelectorAll('table tbody tr').length).toEqual(repoPropsData.list.length);
});
it('should render registry tag', () => {
- const textRendered = vm.$el.querySelector('.table tbody tr').textContent.trim().replace(/\s\s+/g, ' ');
+ const textRendered = vm.$el
+ .querySelector('.table tbody tr')
+ .textContent.trim()
+ .replace(/\s\s+/g, ' ');
+
expect(textRendered).toContain(repoPropsData.list[0].tag);
expect(textRendered).toContain(repoPropsData.list[0].shortRevision);
expect(textRendered).toContain(repoPropsData.list[0].layers);
@@ -36,9 +38,7 @@ describe('table registry', () => {
});
it('should be possible to delete a registry', () => {
- expect(
- vm.$el.querySelector('.table tbody tr .js-delete-registry'),
- ).toBeDefined();
+ expect(vm.$el.querySelector('.table tbody tr .js-delete-registry')).toBeDefined();
});
describe('pagination', () => {
diff --git a/spec/javascripts/registry/getters_spec.js b/spec/javascripts/registry/getters_spec.js
index 3d989541881..839aa718997 100644
--- a/spec/javascripts/registry/getters_spec.js
+++ b/spec/javascripts/registry/getters_spec.js
@@ -7,25 +7,28 @@ describe('Getters Registry Store', () => {
state = {
isLoading: false,
endpoint: '/root/empty-project/container_registry.json',
- repos: [{
- canDelete: true,
- destroyPath: 'bar',
- id: '134',
- isLoading: false,
- list: [],
- location: 'foo',
- name: 'gitlab-org/omnibus-gitlab/foo',
- tagsPath: 'foo',
- }, {
- canDelete: true,
- destroyPath: 'bar',
- id: '123',
- isLoading: false,
- list: [],
- location: 'foo',
- name: 'gitlab-org/omnibus-gitlab',
- tagsPath: 'foo',
- }],
+ repos: [
+ {
+ canDelete: true,
+ destroyPath: 'bar',
+ id: '134',
+ isLoading: false,
+ list: [],
+ location: 'foo',
+ name: 'gitlab-org/omnibus-gitlab/foo',
+ tagsPath: 'foo',
+ },
+ {
+ canDelete: true,
+ destroyPath: 'bar',
+ id: '123',
+ isLoading: false,
+ list: [],
+ location: 'foo',
+ name: 'gitlab-org/omnibus-gitlab',
+ tagsPath: 'foo',
+ },
+ ],
};
});
diff --git a/spec/javascripts/registry/mock_data.js b/spec/javascripts/registry/mock_data.js
index 6bffb47be55..22db203e77f 100644
--- a/spec/javascripts/registry/mock_data.js
+++ b/spec/javascripts/registry/mock_data.js
@@ -40,7 +40,8 @@ export const registryServerResponse = [
layers: 19,
location: 'location',
created_at: 1505828744434,
- }];
+ },
+];
export const parsedReposServerResponse = [
{
diff --git a/spec/javascripts/registry/stores/mutations_spec.js b/spec/javascripts/registry/stores/mutations_spec.js
index 2e4c0659daa..e19fe7a27cf 100644
--- a/spec/javascripts/registry/stores/mutations_spec.js
+++ b/spec/javascripts/registry/stores/mutations_spec.js
@@ -18,6 +18,7 @@ describe('Mutations Registry Store', () => {
it('should set the main endpoint', () => {
const expectedState = Object.assign({}, mockState, { endpoint: 'foo' });
mutations[types.SET_MAIN_ENDPOINT](mockState, 'foo');
+
expect(mockState).toEqual(expectedState);
});
});
@@ -25,6 +26,7 @@ describe('Mutations Registry Store', () => {
describe('SET_REPOS_LIST', () => {
it('should set a parsed repository list', () => {
mutations[types.SET_REPOS_LIST](mockState, reposServerResponse);
+
expect(mockState.repos).toEqual(parsedReposServerResponse);
});
});
@@ -32,6 +34,7 @@ describe('Mutations Registry Store', () => {
describe('TOGGLE_MAIN_LOADING', () => {
it('should set a parsed repository list', () => {
mutations[types.TOGGLE_MAIN_LOADING](mockState);
+
expect(mockState.isLoading).toEqual(true);
});
});
@@ -75,6 +78,7 @@ describe('Mutations Registry Store', () => {
});
mutations[types.TOGGLE_REGISTRY_LIST_LOADING](mockState, mockState.repos[0]);
+
expect(mockState.repos[0].isLoading).toEqual(true);
});
});
diff --git a/spec/javascripts/reports/components/grouped_test_reports_app_spec.js b/spec/javascripts/reports/components/grouped_test_reports_app_spec.js
index 333cefe5f8a..69767d9cf1c 100644
--- a/spec/javascripts/reports/components/grouped_test_reports_app_spec.js
+++ b/spec/javascripts/reports/components/grouped_test_reports_app_spec.js
@@ -42,6 +42,7 @@ describe('Grouped Test Reports App', () => {
expect(vm.$el.textContent).toContain(
'rspec:pg found no changed test results out of 8 total tests',
);
+
expect(vm.$el.textContent).toContain(
'java ant found no changed test results out of 3 total tests',
);
@@ -88,6 +89,7 @@ describe('Grouped Test Reports App', () => {
expect(vm.$el.textContent).toContain(
'rspec:pg found 2 failed test results out of 8 total tests',
);
+
expect(vm.$el.textContent).toContain('New');
expect(vm.$el.textContent).toContain(
'java ant found no changed test results out of 3 total tests',
@@ -115,6 +117,7 @@ describe('Grouped Test Reports App', () => {
expect(vm.$el.textContent).toContain(
'rspec:pg found 1 failed test result and 2 fixed test results out of 8 total tests',
);
+
expect(vm.$el.textContent).toContain('New');
expect(vm.$el.textContent).toContain(
' java ant found 1 failed test result out of 3 total tests',
@@ -148,10 +151,11 @@ describe('Grouped Test Reports App', () => {
it('renders resolved failures', done => {
setTimeout(() => {
- expect(vm.$el.querySelector('.js-mr-code-resolved-issues').textContent).toContain(
+ expect(vm.$el.querySelector('.report-block-container').textContent).toContain(
resolvedFailures.suites[0].resolved_failures[0].name,
);
- expect(vm.$el.querySelector('.js-mr-code-resolved-issues').textContent).toContain(
+
+ expect(vm.$el.querySelector('.report-block-container').textContent).toContain(
resolvedFailures.suites[0].resolved_failures[1].name,
);
done();
diff --git a/spec/javascripts/reports/components/modal_spec.js b/spec/javascripts/reports/components/modal_spec.js
index 3a567c40eca..6b8471381de 100644
--- a/spec/javascripts/reports/components/modal_spec.js
+++ b/spec/javascripts/reports/components/modal_spec.js
@@ -27,12 +27,19 @@ describe('Grouped Test Reports Modal', () => {
});
it('renders code block', () => {
- expect(vm.$el.querySelector('code').textContent).toEqual(modalDataStructure.system_output.value);
+ expect(vm.$el.querySelector('code').textContent).toEqual(
+ modalDataStructure.system_output.value,
+ );
});
it('renders link', () => {
- expect(vm.$el.querySelector('.js-modal-link').getAttribute('href')).toEqual(modalDataStructure.class.value);
- expect(trimText(vm.$el.querySelector('.js-modal-link').textContent)).toEqual(modalDataStructure.class.value);
+ expect(vm.$el.querySelector('.js-modal-link').getAttribute('href')).toEqual(
+ modalDataStructure.class.value,
+ );
+
+ expect(trimText(vm.$el.querySelector('.js-modal-link').textContent)).toEqual(
+ modalDataStructure.class.value,
+ );
});
it('renders miliseconds', () => {
@@ -40,6 +47,8 @@ describe('Grouped Test Reports Modal', () => {
});
it('render title', () => {
- expect(trimText(vm.$el.querySelector('.modal-title').textContent)).toEqual('Test#sum when a is 1 and b is 2 returns summary');
+ expect(trimText(vm.$el.querySelector('.modal-title').textContent)).toEqual(
+ 'Test#sum when a is 1 and b is 2 returns summary',
+ );
});
});
diff --git a/spec/javascripts/reports/components/report_link_spec.js b/spec/javascripts/reports/components/report_link_spec.js
index cd6911e2f59..f879899e9c5 100644
--- a/spec/javascripts/reports/components/report_link_spec.js
+++ b/spec/javascripts/reports/components/report_link_spec.js
@@ -45,8 +45,7 @@ describe('report link', () => {
vm = mountComponent(Component, {
issue: {
path: 'Gemfile.lock',
- urlPath:
- 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
+ urlPath: 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
line: 22,
},
});
@@ -60,8 +59,7 @@ describe('report link', () => {
vm = mountComponent(Component, {
issue: {
path: 'Gemfile.lock',
- urlPath:
- 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
+ urlPath: 'https://groups.google.com/forum/#!topic/rubyonrails-security/335P1DcLG00',
},
});
diff --git a/spec/javascripts/reports/components/report_section_spec.js b/spec/javascripts/reports/components/report_section_spec.js
index 6f6eb161d14..b02af8baaec 100644
--- a/spec/javascripts/reports/components/report_section_spec.js
+++ b/spec/javascripts/reports/components/report_section_spec.js
@@ -86,6 +86,7 @@ describe('Report section', () => {
});
});
});
+
describe('when it is loading', () => {
it('should render loading indicator', () => {
vm = mountComponent(ReportSection, {
@@ -96,6 +97,7 @@ describe('Report section', () => {
successText: 'Code quality improved on 1 point and degraded on 1 point',
hasIssues: false,
});
+
expect(vm.$el.textContent.trim()).toEqual('Loading codeclimate report');
});
});
@@ -118,7 +120,7 @@ describe('Report section', () => {
'Code quality improved on 1 point and degraded on 1 point',
);
- expect(vm.$el.querySelectorAll('.js-mr-code-resolved-issues li').length).toEqual(
+ expect(vm.$el.querySelectorAll('.report-block-container li').length).toEqual(
resolvedIssues.length,
);
});
@@ -168,6 +170,7 @@ describe('Report section', () => {
successText: 'Code quality improved on 1 point and degraded on 1 point',
hasIssues: false,
});
+
expect(vm.$el.textContent.trim()).toEqual('Failed to load codeclimate report');
});
});
diff --git a/spec/javascripts/reports/components/test_issue_body_spec.js b/spec/javascripts/reports/components/test_issue_body_spec.js
index 0ea81f714e7..32baf904ad7 100644
--- a/spec/javascripts/reports/components/test_issue_body_spec.js
+++ b/spec/javascripts/reports/components/test_issue_body_spec.js
@@ -29,6 +29,7 @@ describe('Test Issue body', () => {
spyOn(vm, 'openModal');
vm.$el.querySelector('button').click();
+
expect(vm.openModal).toHaveBeenCalledWith({
issue: commonProps.issue,
});
diff --git a/spec/javascripts/reports/store/mutations_spec.js b/spec/javascripts/reports/store/mutations_spec.js
index 7d19b16efb9..9446cd454ab 100644
--- a/spec/javascripts/reports/store/mutations_spec.js
+++ b/spec/javascripts/reports/store/mutations_spec.js
@@ -13,6 +13,7 @@ describe('Reports Store Mutations', () => {
describe('SET_ENDPOINT', () => {
it('should set endpoint', () => {
mutations[types.SET_ENDPOINT](stateCopy, 'endpoint.json');
+
expect(stateCopy.endpoint).toEqual('endpoint.json');
});
});
@@ -20,6 +21,7 @@ describe('Reports Store Mutations', () => {
describe('REQUEST_REPORTS', () => {
it('should set isLoading to true', () => {
mutations[types.REQUEST_REPORTS](stateCopy);
+
expect(stateCopy.isLoading).toEqual(true);
});
});
diff --git a/spec/javascripts/right_sidebar_spec.js b/spec/javascripts/right_sidebar_spec.js
index 6d49536a712..992e17978c1 100644
--- a/spec/javascripts/right_sidebar_spec.js
+++ b/spec/javascripts/right_sidebar_spec.js
@@ -1,124 +1,87 @@
-/* eslint-disable no-var, one-var, one-var-declaration-per-line, no-return-assign, vars-on-top, max-len */
-
import $ from 'jquery';
import MockAdapter from 'axios-mock-adapter';
import '~/commons/bootstrap';
import axios from '~/lib/utils/axios_utils';
import Sidebar from '~/right_sidebar';
-(function() {
- var $aside, $icon, $labelsIcon, $page, $toggle, assertSidebarState;
-
- $aside = null;
-
- $toggle = null;
-
- $icon = null;
-
- $page = null;
-
- $labelsIcon = null;
-
- assertSidebarState = function(state) {
- var shouldBeCollapsed, shouldBeExpanded;
- shouldBeExpanded = state === 'expanded';
- shouldBeCollapsed = state === 'collapsed';
- expect($aside.hasClass('right-sidebar-expanded')).toBe(shouldBeExpanded);
- expect($page.hasClass('right-sidebar-expanded')).toBe(shouldBeExpanded);
- expect($icon.hasClass('fa-angle-double-right')).toBe(shouldBeExpanded);
- expect($aside.hasClass('right-sidebar-collapsed')).toBe(shouldBeCollapsed);
- expect($page.hasClass('right-sidebar-collapsed')).toBe(shouldBeCollapsed);
- return expect($icon.hasClass('fa-angle-double-left')).toBe(shouldBeCollapsed);
- };
-
- describe('RightSidebar', function() {
- describe('fixture tests', () => {
- var fixtureName = 'issues/open-issue.html.raw';
- preloadFixtures(fixtureName);
- loadJSONFixtures('todos/todos.json');
- let mock;
-
- beforeEach(function() {
- loadFixtures(fixtureName);
- mock = new MockAdapter(axios);
- new Sidebar(); // eslint-disable-line no-new
- $aside = $('.right-sidebar');
- $page = $('.layout-page');
- $icon = $aside.find('i');
- $toggle = $aside.find('.js-sidebar-toggle');
- return $labelsIcon = $aside.find('.sidebar-collapsed-icon');
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- it('should expand/collapse the sidebar when arrow is clicked', function() {
- assertSidebarState('expanded');
- $toggle.click();
- assertSidebarState('collapsed');
- $toggle.click();
- assertSidebarState('expanded');
- });
- it('should float over the page and when sidebar icons clicked', function() {
- $labelsIcon.click();
- return assertSidebarState('expanded');
- });
- it('should collapse when the icon arrow clicked while it is floating on page', function() {
- $labelsIcon.click();
- assertSidebarState('expanded');
- $toggle.click();
- return assertSidebarState('collapsed');
- });
-
- it('should broadcast todo:toggle event when add todo clicked', function(done) {
- var todos = getJSONFixture('todos/todos.json');
- mock.onPost(/(.*)\/todos$/).reply(200, todos);
-
- var todoToggleSpy = spyOnEvent(document, 'todo:toggle');
-
- $('.issuable-sidebar-header .js-issuable-todo').click();
+let $aside = null;
+let $toggle = null;
+let $icon = null;
+let $page = null;
+let $labelsIcon = null;
+
+const assertSidebarState = function(state) {
+ const shouldBeExpanded = state === 'expanded';
+ const shouldBeCollapsed = state === 'collapsed';
+ expect($aside.hasClass('right-sidebar-expanded')).toBe(shouldBeExpanded);
+ expect($page.hasClass('right-sidebar-expanded')).toBe(shouldBeExpanded);
+ expect($icon.hasClass('fa-angle-double-right')).toBe(shouldBeExpanded);
+ expect($aside.hasClass('right-sidebar-collapsed')).toBe(shouldBeCollapsed);
+ expect($page.hasClass('right-sidebar-collapsed')).toBe(shouldBeCollapsed);
+ expect($icon.hasClass('fa-angle-double-left')).toBe(shouldBeCollapsed);
+};
+
+describe('RightSidebar', function() {
+ describe('fixture tests', () => {
+ const fixtureName = 'issues/open-issue.html.raw';
+ preloadFixtures(fixtureName);
+ loadJSONFixtures('todos/todos.json');
+ let mock;
+
+ beforeEach(function() {
+ loadFixtures(fixtureName);
+ mock = new MockAdapter(axios);
+ new Sidebar(); // eslint-disable-line no-new
+ $aside = $('.right-sidebar');
+ $page = $('.layout-page');
+ $icon = $aside.find('i');
+ $toggle = $aside.find('.js-sidebar-toggle');
+ $labelsIcon = $aside.find('.sidebar-collapsed-icon');
+ });
- setTimeout(() => {
- expect(todoToggleSpy.calls.count()).toEqual(1);
+ afterEach(() => {
+ mock.restore();
+ });
- done();
- });
- });
+ it('should expand/collapse the sidebar when arrow is clicked', function() {
+ assertSidebarState('expanded');
+ $toggle.click();
+ assertSidebarState('collapsed');
+ $toggle.click();
+ assertSidebarState('expanded');
+ });
- it('should not hide collapsed icons', () => {
- [].forEach.call(document.querySelectorAll('.sidebar-collapsed-icon'), (el) => {
- expect(el.querySelector('.fa, svg').classList.contains('hidden')).toBeFalsy();
- });
- });
+ it('should float over the page and when sidebar icons clicked', function() {
+ $labelsIcon.click();
+ assertSidebarState('expanded');
});
- describe('sidebarToggleClicked', () => {
- const event = jasmine.createSpyObj('event', ['preventDefault']);
+ it('should collapse when the icon arrow clicked while it is floating on page', function() {
+ $labelsIcon.click();
+ assertSidebarState('expanded');
+ $toggle.click();
+ assertSidebarState('collapsed');
+ });
- beforeEach(() => {
- spyOn($.fn, 'hasClass').and.returnValue(false);
- });
+ it('should broadcast todo:toggle event when add todo clicked', function(done) {
+ const todos = getJSONFixture('todos/todos.json');
+ mock.onPost(/(.*)\/todos$/).reply(200, todos);
- afterEach(() => {
- gl.lazyLoader = undefined;
- });
+ const todoToggleSpy = spyOnEvent(document, 'todo:toggle');
- it('calls loadCheck if lazyLoader is set', () => {
- gl.lazyLoader = jasmine.createSpyObj('lazyLoader', ['loadCheck']);
+ $('.issuable-sidebar-header .js-issuable-todo').click();
- Sidebar.prototype.sidebarToggleClicked(event);
+ setTimeout(() => {
+ expect(todoToggleSpy.calls.count()).toEqual(1);
- expect(gl.lazyLoader.loadCheck).toHaveBeenCalled();
+ done();
});
+ });
- it('does not throw if lazyLoader is not defined', () => {
- gl.lazyLoader = undefined;
-
- const toggle = Sidebar.prototype.sidebarToggleClicked.bind(null, event);
-
- expect(toggle).not.toThrow();
+ it('should not hide collapsed icons', () => {
+ [].forEach.call(document.querySelectorAll('.sidebar-collapsed-icon'), el => {
+ expect(el.querySelector('.fa, svg').classList.contains('hidden')).toBeFalsy();
});
});
});
-}).call(window);
+});
diff --git a/spec/javascripts/search_autocomplete_spec.js b/spec/javascripts/search_autocomplete_spec.js
index 646d843162c..7a4ca587313 100644
--- a/spec/javascripts/search_autocomplete_spec.js
+++ b/spec/javascripts/search_autocomplete_spec.js
@@ -1,4 +1,4 @@
-/* eslint-disable max-len, no-var, one-var, one-var-declaration-per-line, no-unused-expressions, consistent-return, no-param-reassign, default-case, no-return-assign, object-shorthand, prefer-template, vars-on-top, max-len */
+/* eslint-disable no-var, one-var, no-unused-expressions, consistent-return, no-param-reassign, default-case, no-return-assign, object-shorthand, vars-on-top */
import $ from 'jquery';
import '~/gl_dropdown';
@@ -109,15 +109,17 @@ describe('Search autocomplete dropdown', () => {
assertLinks = function(list, issuesPath, mrsPath) {
if (issuesPath) {
- const issuesAssignedToMeLink = `a[href="${issuesPath}/?assignee_id=${userId}"]`;
- const issuesIHaveCreatedLink = `a[href="${issuesPath}/?author_id=${userId}"]`;
+ const issuesAssignedToMeLink = `a[href="${issuesPath}/?assignee_username=${userName}"]`;
+ const issuesIHaveCreatedLink = `a[href="${issuesPath}/?author_username=${userName}"]`;
+
expect(list.find(issuesAssignedToMeLink).length).toBe(1);
expect(list.find(issuesAssignedToMeLink).text()).toBe('Issues assigned to me');
expect(list.find(issuesIHaveCreatedLink).length).toBe(1);
expect(list.find(issuesIHaveCreatedLink).text()).toBe("Issues I've created");
}
- const mrsAssignedToMeLink = `a[href="${mrsPath}/?assignee_id=${userId}"]`;
- const mrsIHaveCreatedLink = `a[href="${mrsPath}/?author_id=${userId}"]`;
+ const mrsAssignedToMeLink = `a[href="${mrsPath}/?assignee_username=${userName}"]`;
+ const mrsIHaveCreatedLink = `a[href="${mrsPath}/?author_username=${userName}"]`;
+
expect(list.find(mrsAssignedToMeLink).length).toBe(1);
expect(list.find(mrsAssignedToMeLink).text()).toBe('Merge requests assigned to me');
expect(list.find(mrsIHaveCreatedLink).length).toBe(1);
@@ -140,6 +142,7 @@ describe('Search autocomplete dropdown', () => {
removeBodyAttributes();
window.gon = {};
});
+
it('should show Dashboard specific dropdown menu', function() {
var list;
addBodyAttributes();
@@ -148,6 +151,7 @@ describe('Search autocomplete dropdown', () => {
list = widget.wrap.find('.dropdown-menu').find('ul');
return assertLinks(list, dashboardIssuesPath, dashboardMRsPath);
});
+
it('should show Group specific dropdown menu', function() {
var list;
addBodyAttributes('group');
@@ -156,6 +160,7 @@ describe('Search autocomplete dropdown', () => {
list = widget.wrap.find('.dropdown-menu').find('ul');
return assertLinks(list, groupIssuesPath, groupMRsPath);
});
+
it('should show Project specific dropdown menu', function() {
var list;
addBodyAttributes('project');
@@ -164,6 +169,7 @@ describe('Search autocomplete dropdown', () => {
list = widget.wrap.find('.dropdown-menu').find('ul');
return assertLinks(list, projectIssuesPath, projectMRsPath);
});
+
it('should show only Project mergeRequest dropdown menu items when project issues are disabled', function() {
addBodyAttributes('project');
disableProjectIssues();
@@ -172,6 +178,7 @@ describe('Search autocomplete dropdown', () => {
const list = widget.wrap.find('.dropdown-menu').find('ul');
assertLinks(list, null, projectMRsPath);
});
+
it('should not show category related menu if there is text in the input', function() {
var link, list;
addBodyAttributes('project');
@@ -179,9 +186,11 @@ describe('Search autocomplete dropdown', () => {
widget.searchInput.val('help');
widget.searchInput.triggerHandler('focus');
list = widget.wrap.find('.dropdown-menu').find('ul');
- link = "a[href='" + projectIssuesPath + '/?assignee_id=' + userId + "']";
- return expect(list.find(link).length).toBe(0);
+ link = `a[href='${projectIssuesPath}/?assignee_username=${userName}']`;
+
+ expect(list.find(link).length).toBe(0);
});
+
it('should not submit the search form when selecting an autocomplete row with the keyboard', function() {
var ENTER = 13;
var DOWN = 40;
diff --git a/spec/javascripts/search_spec.js b/spec/javascripts/search_spec.js
index 522851c584b..40bdbac7451 100644
--- a/spec/javascripts/search_spec.js
+++ b/spec/javascripts/search_spec.js
@@ -5,7 +5,7 @@ import Search from '~/pages/search/show/search';
describe('Search', () => {
const fixturePath = 'search/show.html.raw';
const searchTerm = 'some search';
- const fillDropdownInput = (dropdownSelector) => {
+ const fillDropdownInput = dropdownSelector => {
const dropdownElement = document.querySelector(dropdownSelector).parentNode;
const inputElement = dropdownElement.querySelector('.dropdown-input-field');
inputElement.value = searchTerm;
@@ -19,8 +19,8 @@ describe('Search', () => {
new Search(); // eslint-disable-line no-new
});
- it('requests groups from backend when filtering', (done) => {
- spyOn(Api, 'groups').and.callFake((term) => {
+ it('requests groups from backend when filtering', done => {
+ spyOn(Api, 'groups').and.callFake(term => {
expect(term).toBe(searchTerm);
done();
});
@@ -29,8 +29,8 @@ describe('Search', () => {
$(inputElement).trigger('input');
});
- it('requests projects from backend when filtering', (done) => {
- spyOn(Api, 'projects').and.callFake((term) => {
+ it('requests projects from backend when filtering', done => {
+ spyOn(Api, 'projects').and.callFake(term => {
expect(term).toBe(searchTerm);
done();
});
diff --git a/spec/javascripts/settings_panels_spec.js b/spec/javascripts/settings_panels_spec.js
index c1a69bd7018..3b681a9ff28 100644
--- a/spec/javascripts/settings_panels_spec.js
+++ b/spec/javascripts/settings_panels_spec.js
@@ -1,10 +1,11 @@
+import $ from 'jquery';
import initSettingsPanels from '~/settings_panels';
describe('Settings Panels', () => {
- preloadFixtures('projects/ci_cd_settings.html.raw');
+ preloadFixtures('groups/edit.html.raw');
beforeEach(() => {
- loadFixtures('projects/ci_cd_settings.html.raw');
+ loadFixtures('groups/edit.html.raw');
});
describe('initSettingsPane', () => {
@@ -13,17 +14,32 @@ describe('Settings Panels', () => {
});
it('should expand linked hash fragment panel', () => {
- window.location.hash = '#autodevops-settings';
+ window.location.hash = '#js-general-settings';
- const pipelineSettingsPanel = document.querySelector('#autodevops-settings');
+ const panel = document.querySelector('#js-general-settings');
// Our test environment automatically expands everything so we need to clear that out first
- pipelineSettingsPanel.classList.remove('expanded');
+ panel.classList.remove('expanded');
- expect(pipelineSettingsPanel.classList.contains('expanded')).toBe(false);
+ expect(panel.classList.contains('expanded')).toBe(false);
initSettingsPanels();
- expect(pipelineSettingsPanel.classList.contains('expanded')).toBe(true);
+ expect(panel.classList.contains('expanded')).toBe(true);
});
});
+
+ it('does not change the text content of triggers', () => {
+ const panel = document.querySelector('#js-general-settings');
+ const trigger = panel.querySelector('.js-settings-toggle-trigger-only');
+ const originalText = trigger.textContent;
+
+ initSettingsPanels();
+
+ expect(panel.classList.contains('expanded')).toBe(true);
+
+ $(trigger).click();
+
+ expect(panel.classList.contains('expanded')).toBe(false);
+ expect(trigger.textContent).toEqual(originalText);
+ });
});
diff --git a/spec/javascripts/shared/popover_spec.js b/spec/javascripts/shared/popover_spec.js
index 1d574c9424b..cc2b2014d38 100644
--- a/spec/javascripts/shared/popover_spec.js
+++ b/spec/javascripts/shared/popover_spec.js
@@ -1,9 +1,5 @@
import $ from 'jquery';
-import {
- togglePopover,
- mouseleave,
- mouseenter,
-} from '~/shared/popover';
+import { togglePopover, mouseleave, mouseenter } from '~/shared/popover';
describe('popover', () => {
describe('togglePopover', () => {
@@ -26,14 +22,14 @@ describe('popover', () => {
expect(togglePopover.call(context, true)).toEqual(false);
});
- it('shows popover', (done) => {
+ it('shows popover', done => {
const context = {
hasClass: () => false,
popover: () => {},
toggleClass: () => {},
};
- spyOn(context, 'popover').and.callFake((method) => {
+ spyOn(context, 'popover').and.callFake(method => {
expect(method).toEqual('show');
done();
});
@@ -41,7 +37,7 @@ describe('popover', () => {
togglePopover.call(context, true);
});
- it('adds disable-animation and js-popover-show class', (done) => {
+ it('adds disable-animation and js-popover-show class', done => {
const context = {
hasClass: () => false,
popover: () => {},
@@ -77,14 +73,14 @@ describe('popover', () => {
expect(togglePopover.call(context, false)).toEqual(false);
});
- it('hides popover', (done) => {
+ it('hides popover', done => {
const context = {
hasClass: () => true,
popover: () => {},
toggleClass: () => {},
};
- spyOn(context, 'popover').and.callFake((method) => {
+ spyOn(context, 'popover').and.callFake(method => {
expect(method).toEqual('hide');
done();
});
@@ -92,7 +88,7 @@ describe('popover', () => {
togglePopover.call(context, false);
});
- it('removes disable-animation and js-popover-show class', (done) => {
+ it('removes disable-animation and js-popover-show class', done => {
const context = {
hasClass: () => true,
popover: () => {},
@@ -116,9 +112,12 @@ describe('popover', () => {
length: 0,
};
- spyOn($.fn, 'init').and.callFake(selector => (selector === '.popover:hover' ? fakeJquery : $.fn));
+ spyOn($.fn, 'init').and.callFake(selector =>
+ selector === '.popover:hover' ? fakeJquery : $.fn,
+ );
spyOn(togglePopover, 'call');
mouseleave();
+
expect(togglePopover.call).toHaveBeenCalledWith(jasmine.any(Object), false);
});
@@ -127,9 +126,12 @@ describe('popover', () => {
length: 1,
};
- spyOn($.fn, 'init').and.callFake(selector => (selector === '.popover:hover' ? fakeJquery : $.fn));
+ spyOn($.fn, 'init').and.callFake(selector =>
+ selector === '.popover:hover' ? fakeJquery : $.fn,
+ );
spyOn(togglePopover, 'call');
mouseleave();
+
expect(togglePopover.call).not.toHaveBeenCalledWith(false);
});
});
@@ -140,12 +142,13 @@ describe('popover', () => {
it('shows popover', () => {
spyOn(togglePopover, 'call').and.returnValue(false);
mouseenter.call(context);
+
expect(togglePopover.call).toHaveBeenCalledWith(jasmine.any(Object), true);
});
- it('registers mouseleave event if popover is showed', (done) => {
+ it('registers mouseleave event if popover is showed', done => {
spyOn(togglePopover, 'call').and.returnValue(true);
- spyOn($.fn, 'on').and.callFake((eventName) => {
+ spyOn($.fn, 'on').and.callFake(eventName => {
expect(eventName).toEqual('mouseleave');
done();
});
@@ -156,6 +159,7 @@ describe('popover', () => {
spyOn(togglePopover, 'call').and.returnValue(false);
const spy = spyOn($.fn, 'on').and.callFake(() => {});
mouseenter.call(context);
+
expect(spy).not.toHaveBeenCalled();
});
});
diff --git a/spec/javascripts/sidebar/assignees_spec.js b/spec/javascripts/sidebar/assignees_spec.js
index 843e7002180..eced4925489 100644
--- a/spec/javascripts/sidebar/assignees_spec.js
+++ b/spec/javascripts/sidebar/assignees_spec.js
@@ -22,6 +22,7 @@ describe('Assignee component', () => {
}).$mount();
const collapsed = component.$el.querySelector('.sidebar-collapsed-icon');
+
expect(collapsed.childElementCount).toEqual(1);
expect(collapsed.children[0].getAttribute('aria-label')).toEqual('No Assignee');
expect(collapsed.children[0].classList.contains('fa')).toEqual(true);
@@ -67,6 +68,7 @@ describe('Assignee component', () => {
spyOn(component, '$emit');
component.$el.querySelector('.assign-yourself .btn-link').click();
+
expect(component.$emit).toHaveBeenCalledWith('assign-self');
});
});
@@ -76,18 +78,20 @@ describe('Assignee component', () => {
component = new AssigneeComponent({
propsData: {
rootPath: 'http://localhost:3000',
- users: [
- UsersMock.user,
- ],
+ users: [UsersMock.user],
editable: false,
},
}).$mount();
const collapsed = component.$el.querySelector('.sidebar-collapsed-icon');
const assignee = collapsed.children[0];
+
expect(collapsed.childElementCount).toEqual(1);
expect(assignee.querySelector('.avatar').getAttribute('src')).toEqual(UsersMock.user.avatar);
- expect(assignee.querySelector('.avatar').getAttribute('alt')).toEqual(`${UsersMock.user.name}'s avatar`);
+ expect(assignee.querySelector('.avatar').getAttribute('alt')).toEqual(
+ `${UsersMock.user.name}'s avatar`,
+ );
+
expect(assignee.querySelector('.author').innerText.trim()).toEqual(UsersMock.user.name);
});
@@ -95,34 +99,38 @@ describe('Assignee component', () => {
component = new AssigneeComponent({
propsData: {
rootPath: 'http://localhost:3000/',
- users: [
- UsersMock.user,
- ],
+ users: [UsersMock.user],
editable: true,
},
}).$mount();
expect(component.$el.querySelector('.author-link')).not.toBeNull();
// The image
- expect(component.$el.querySelector('.author-link img').getAttribute('src')).toEqual(UsersMock.user.avatar);
+ expect(component.$el.querySelector('.author-link img').getAttribute('src')).toEqual(
+ UsersMock.user.avatar,
+ );
// Author name
- expect(component.$el.querySelector('.author-link .author').innerText.trim()).toEqual(UsersMock.user.name);
+ expect(component.$el.querySelector('.author-link .author').innerText.trim()).toEqual(
+ UsersMock.user.name,
+ );
// Username
- expect(component.$el.querySelector('.author-link .username').innerText.trim()).toEqual(`@${UsersMock.user.username}`);
+ expect(component.$el.querySelector('.author-link .username').innerText.trim()).toEqual(
+ `@${UsersMock.user.username}`,
+ );
});
it('has the root url present in the assigneeUrl method', () => {
component = new AssigneeComponent({
propsData: {
rootPath: 'http://localhost:3000/',
- users: [
- UsersMock.user,
- ],
+ users: [UsersMock.user],
editable: true,
},
}).$mount();
- expect(component.assigneeUrl(UsersMock.user).indexOf('http://localhost:3000/')).not.toEqual(-1);
+ expect(component.assigneeUrl(UsersMock.user).indexOf('http://localhost:3000/')).not.toEqual(
+ -1,
+ );
});
});
@@ -138,16 +146,25 @@ describe('Assignee component', () => {
}).$mount();
const collapsed = component.$el.querySelector('.sidebar-collapsed-icon');
+
expect(collapsed.childElementCount).toEqual(2);
const first = collapsed.children[0];
+
expect(first.querySelector('.avatar').getAttribute('src')).toEqual(users[0].avatar);
- expect(first.querySelector('.avatar').getAttribute('alt')).toEqual(`${users[0].name}'s avatar`);
+ expect(first.querySelector('.avatar').getAttribute('alt')).toEqual(
+ `${users[0].name}'s avatar`,
+ );
+
expect(first.querySelector('.author').innerText.trim()).toEqual(users[0].name);
const second = collapsed.children[1];
+
expect(second.querySelector('.avatar').getAttribute('src')).toEqual(users[1].avatar);
- expect(second.querySelector('.avatar').getAttribute('alt')).toEqual(`${users[1].name}'s avatar`);
+ expect(second.querySelector('.avatar').getAttribute('alt')).toEqual(
+ `${users[1].name}'s avatar`,
+ );
+
expect(second.querySelector('.author').innerText.trim()).toEqual(users[1].name);
});
@@ -162,14 +179,20 @@ describe('Assignee component', () => {
}).$mount();
const collapsed = component.$el.querySelector('.sidebar-collapsed-icon');
+
expect(collapsed.childElementCount).toEqual(2);
const first = collapsed.children[0];
+
expect(first.querySelector('.avatar').getAttribute('src')).toEqual(users[0].avatar);
- expect(first.querySelector('.avatar').getAttribute('alt')).toEqual(`${users[0].name}'s avatar`);
+ expect(first.querySelector('.avatar').getAttribute('alt')).toEqual(
+ `${users[0].name}'s avatar`,
+ );
+
expect(first.querySelector('.author').innerText.trim()).toEqual(users[0].name);
const second = collapsed.children[1];
+
expect(second.querySelector('.avatar-counter').innerText.trim()).toEqual('+2');
});
@@ -187,7 +210,7 @@ describe('Assignee component', () => {
expect(component.$el.querySelector('.user-list-more')).toBe(null);
});
- it('Shows the "show-less" assignees label', (done) => {
+ it('Shows the "show-less" assignees label', done => {
const users = UsersMockHelper.createNumberRandomUsers(6);
component = new AssigneeComponent({
propsData: {
@@ -197,20 +220,26 @@ describe('Assignee component', () => {
},
}).$mount();
- expect(component.$el.querySelectorAll('.user-item').length).toEqual(component.defaultRenderCount);
+ expect(component.$el.querySelectorAll('.user-item').length).toEqual(
+ component.defaultRenderCount,
+ );
+
expect(component.$el.querySelector('.user-list-more')).not.toBe(null);
const usersLabelExpectation = users.length - component.defaultRenderCount;
- expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim())
- .not.toBe(`+${usersLabelExpectation} more`);
+
+ expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim()).not.toBe(
+ `+${usersLabelExpectation} more`,
+ );
component.toggleShowLess();
Vue.nextTick(() => {
- expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim())
- .toBe('- show less');
+ expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim()).toBe(
+ '- show less',
+ );
done();
});
});
- it('Shows the "show-less" when "n+ more " label is clicked', (done) => {
+ it('Shows the "show-less" when "n+ more " label is clicked', done => {
const users = UsersMockHelper.createNumberRandomUsers(6);
component = new AssigneeComponent({
propsData: {
@@ -222,8 +251,9 @@ describe('Assignee component', () => {
component.$el.querySelector('.user-list-more .btn-link').click();
Vue.nextTick(() => {
- expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim())
- .toBe('- show less');
+ expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim()).toBe(
+ '- show less',
+ );
done();
});
});
@@ -254,16 +284,18 @@ describe('Assignee component', () => {
});
it('shows "+1 more" label', () => {
- expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim())
- .toBe('+ 1 more');
+ expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim()).toBe(
+ '+ 1 more',
+ );
});
- it('shows "show less" label', (done) => {
+ it('shows "show less" label', done => {
component.toggleShowLess();
Vue.nextTick(() => {
- expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim())
- .toBe('- show less');
+ expect(component.$el.querySelector('.user-list-more .btn-link').innerText.trim()).toBe(
+ '- show less',
+ );
done();
});
});
diff --git a/spec/javascripts/sidebar/components/time_tracking/time_tracker_spec.js b/spec/javascripts/sidebar/components/time_tracking/time_tracker_spec.js
index 9dff52a9d49..4c3dd713589 100644
--- a/spec/javascripts/sidebar/components/time_tracking/time_tracker_spec.js
+++ b/spec/javascripts/sidebar/components/time_tracking/time_tracker_spec.js
@@ -8,7 +8,12 @@ describe('Issuable Time Tracker', () => {
let initialData;
let vm;
- const initTimeTrackingComponent = opts => {
+ const initTimeTrackingComponent = ({
+ timeEstimate,
+ timeSpent,
+ timeEstimateHumanReadable,
+ timeSpentHumanReadable,
+ }) => {
setFixtures(`
<div>
<div id="mock-container"></div>
@@ -16,10 +21,10 @@ describe('Issuable Time Tracker', () => {
`);
initialData = {
- time_estimate: opts.timeEstimate,
- time_spent: opts.timeSpent,
- human_time_estimate: opts.timeEstimateHumanReadable,
- human_time_spent: opts.timeSpentHumanReadable,
+ timeEstimate,
+ timeSpent,
+ humanTimeEstimate: timeEstimateHumanReadable,
+ humanTimeSpent: timeSpentHumanReadable,
rootPath: '/',
};
@@ -43,8 +48,8 @@ describe('Issuable Time Tracker', () => {
describe('Initialization', () => {
beforeEach(() => {
initTimeTrackingComponent({
- timeEstimate: 100000,
- timeSpent: 5000,
+ timeEstimate: 10000, // 2h 46m
+ timeSpent: 5000, // 1h 23m
timeEstimateHumanReadable: '2h 46m',
timeSpentHumanReadable: '1h 23m',
});
@@ -56,14 +61,14 @@ describe('Issuable Time Tracker', () => {
it('should correctly set timeEstimate', done => {
Vue.nextTick(() => {
- expect(vm.timeEstimate).toBe(initialData.time_estimate);
+ expect(vm.timeEstimate).toBe(initialData.timeEstimate);
done();
});
});
it('should correctly set time_spent', done => {
Vue.nextTick(() => {
- expect(vm.timeSpent).toBe(initialData.time_spent);
+ expect(vm.timeSpent).toBe(initialData.timeSpent);
done();
});
});
@@ -74,8 +79,8 @@ describe('Issuable Time Tracker', () => {
describe('Comparison pane', () => {
beforeEach(() => {
initTimeTrackingComponent({
- timeEstimate: 100000,
- timeSpent: 5000,
+ timeEstimate: 100000, // 1d 3h
+ timeSpent: 5000, // 1h 23m
timeEstimateHumanReadable: '',
timeSpentHumanReadable: '',
});
@@ -85,6 +90,7 @@ describe('Issuable Time Tracker', () => {
Vue.nextTick(() => {
expect(vm.showComparisonState).toBe(true);
const $comparisonPane = vm.$el.querySelector('.time-tracking-comparison-pane');
+
expect($comparisonPane).toBeVisible();
done();
});
@@ -93,23 +99,29 @@ describe('Issuable Time Tracker', () => {
describe('Remaining meter', () => {
it('should display the remaining meter with the correct width', done => {
Vue.nextTick(() => {
- expect(vm.$el.querySelector('.time-tracking-comparison-pane .progress[value="5"]')).not.toBeNull();
+ expect(
+ vm.$el.querySelector('.time-tracking-comparison-pane .progress[value="5"]'),
+ ).not.toBeNull();
done();
});
});
it('should display the remaining meter with the correct background color when within estimate', done => {
Vue.nextTick(() => {
- expect(vm.$el.querySelector('.time-tracking-comparison-pane .progress[variant="primary"]')).not.toBeNull();
+ expect(
+ vm.$el.querySelector('.time-tracking-comparison-pane .progress[variant="primary"]'),
+ ).not.toBeNull();
done();
});
});
it('should display the remaining meter with the correct background color when over estimate', done => {
- vm.time_estimate = 100000;
- vm.time_spent = 20000000;
+ vm.timeEstimate = 10000; // 2h 46m
+ vm.timeSpent = 20000000; // 231 days
Vue.nextTick(() => {
- expect(vm.$el.querySelector('.time-tracking-comparison-pane .progress[variant="danger"]')).not.toBeNull();
+ expect(
+ vm.$el.querySelector('.time-tracking-comparison-pane .progress[variant="danger"]'),
+ ).not.toBeNull();
done();
});
});
@@ -119,7 +131,7 @@ describe('Issuable Time Tracker', () => {
describe('Estimate only pane', () => {
beforeEach(() => {
initTimeTrackingComponent({
- timeEstimate: 100000,
+ timeEstimate: 10000, // 2h 46m
timeSpent: 0,
timeEstimateHumanReadable: '2h 46m',
timeSpentHumanReadable: '',
@@ -142,7 +154,7 @@ describe('Issuable Time Tracker', () => {
beforeEach(() => {
initTimeTrackingComponent({
timeEstimate: 0,
- timeSpent: 5000,
+ timeSpent: 5000, // 1h 23m
timeEstimateHumanReadable: '2h 46m',
timeSpentHumanReadable: '1h 23m',
});
diff --git a/spec/javascripts/sidebar/confidential_edit_buttons_spec.js b/spec/javascripts/sidebar/confidential_edit_buttons_spec.js
index 482be466aad..32da9f83112 100644
--- a/spec/javascripts/sidebar/confidential_edit_buttons_spec.js
+++ b/spec/javascripts/sidebar/confidential_edit_buttons_spec.js
@@ -7,8 +7,8 @@ describe('Edit Form Buttons', () => {
beforeEach(() => {
const Component = Vue.extend(editFormButtons);
- const toggleForm = () => { };
- const updateConfidentialAttribute = () => { };
+ const toggleForm = () => {};
+ const updateConfidentialAttribute = () => {};
vm1 = new Component({
propsData: {
@@ -28,12 +28,8 @@ describe('Edit Form Buttons', () => {
});
it('renders on or off text based on confidentiality', () => {
- expect(
- vm1.$el.innerHTML.includes('Turn Off'),
- ).toBe(true);
+ expect(vm1.$el.innerHTML.includes('Turn Off')).toBe(true);
- expect(
- vm2.$el.innerHTML.includes('Turn On'),
- ).toBe(true);
+ expect(vm2.$el.innerHTML.includes('Turn On')).toBe(true);
});
});
diff --git a/spec/javascripts/sidebar/confidential_edit_form_buttons_spec.js b/spec/javascripts/sidebar/confidential_edit_form_buttons_spec.js
index 724f5126945..369088cb258 100644
--- a/spec/javascripts/sidebar/confidential_edit_form_buttons_spec.js
+++ b/spec/javascripts/sidebar/confidential_edit_form_buttons_spec.js
@@ -7,8 +7,8 @@ describe('Edit Form Dropdown', () => {
beforeEach(() => {
const Component = Vue.extend(editForm);
- const toggleForm = () => { };
- const updateConfidentialAttribute = () => { };
+ const toggleForm = () => {};
+ const updateConfidentialAttribute = () => {};
vm1 = new Component({
propsData: {
@@ -28,12 +28,8 @@ describe('Edit Form Dropdown', () => {
});
it('renders on the appropriate warning text', () => {
- expect(
- vm1.$el.innerHTML.includes('You are going to turn off the confidentiality.'),
- ).toBe(true);
+ expect(vm1.$el.innerHTML.includes('You are going to turn off the confidentiality.')).toBe(true);
- expect(
- vm2.$el.innerHTML.includes('You are going to turn on the confidentiality.'),
- ).toBe(true);
+ expect(vm2.$el.innerHTML.includes('You are going to turn on the confidentiality.')).toBe(true);
});
});
diff --git a/spec/javascripts/sidebar/confidential_issue_sidebar_spec.js b/spec/javascripts/sidebar/confidential_issue_sidebar_spec.js
index 6110d5d89ac..486a7241e33 100644
--- a/spec/javascripts/sidebar/confidential_issue_sidebar_spec.js
+++ b/spec/javascripts/sidebar/confidential_issue_sidebar_spec.js
@@ -29,20 +29,14 @@ describe('Confidential Issue Sidebar Block', () => {
});
it('shows if confidential and/or editable', () => {
- expect(
- vm1.$el.innerHTML.includes('Edit'),
- ).toBe(true);
+ expect(vm1.$el.innerHTML.includes('Edit')).toBe(true);
- expect(
- vm1.$el.innerHTML.includes('This issue is confidential'),
- ).toBe(true);
+ expect(vm1.$el.innerHTML.includes('This issue is confidential')).toBe(true);
- expect(
- vm2.$el.innerHTML.includes('Not confidential'),
- ).toBe(true);
+ expect(vm2.$el.innerHTML.includes('Not confidential')).toBe(true);
});
- it('displays the edit form when editable', (done) => {
+ it('displays the edit form when editable', done => {
expect(vm1.edit).toBe(false);
vm1.$el.querySelector('.confidential-edit').click();
@@ -50,17 +44,15 @@ describe('Confidential Issue Sidebar Block', () => {
expect(vm1.edit).toBe(true);
setTimeout(() => {
- expect(
- vm1.$el
- .innerHTML
- .includes('You are going to turn off the confidentiality.'),
- ).toBe(true);
+ expect(vm1.$el.innerHTML.includes('You are going to turn off the confidentiality.')).toBe(
+ true,
+ );
done();
});
});
- it('displays the edit form when opened from collapsed state', (done) => {
+ it('displays the edit form when opened from collapsed state', done => {
expect(vm1.edit).toBe(false);
vm1.$el.querySelector('.sidebar-collapsed-icon').click();
@@ -68,11 +60,9 @@ describe('Confidential Issue Sidebar Block', () => {
expect(vm1.edit).toBe(true);
setTimeout(() => {
- expect(
- vm1.$el
- .innerHTML
- .includes('You are going to turn off the confidentiality.'),
- ).toBe(true);
+ expect(vm1.$el.innerHTML.includes('You are going to turn off the confidentiality.')).toBe(
+ true,
+ );
done();
});
diff --git a/spec/javascripts/sidebar/lock/edit_form_buttons_spec.js b/spec/javascripts/sidebar/lock/edit_form_buttons_spec.js
index deeea669de8..330f59f08b2 100644
--- a/spec/javascripts/sidebar/lock/edit_form_buttons_spec.js
+++ b/spec/javascripts/sidebar/lock/edit_form_buttons_spec.js
@@ -8,8 +8,8 @@ describe('EditFormButtons', () => {
beforeEach(() => {
const Component = Vue.extend(editFormButtons);
- const toggleForm = () => { };
- const updateLockedAttribute = () => { };
+ const toggleForm = () => {};
+ const updateLockedAttribute = () => {};
vm1 = mountComponent(Component, {
isLocked: true,
@@ -25,12 +25,8 @@ describe('EditFormButtons', () => {
});
it('renders unlock or lock text based on locked state', () => {
- expect(
- vm1.$el.innerHTML.includes('Unlock'),
- ).toBe(true);
+ expect(vm1.$el.innerHTML.includes('Unlock')).toBe(true);
- expect(
- vm2.$el.innerHTML.includes('Lock'),
- ).toBe(true);
+ expect(vm2.$el.innerHTML.includes('Lock')).toBe(true);
});
});
diff --git a/spec/javascripts/sidebar/lock/edit_form_spec.js b/spec/javascripts/sidebar/lock/edit_form_spec.js
index 7abd6997a18..ec10a999a40 100644
--- a/spec/javascripts/sidebar/lock/edit_form_spec.js
+++ b/spec/javascripts/sidebar/lock/edit_form_spec.js
@@ -7,8 +7,8 @@ describe('EditForm', () => {
beforeEach(() => {
const Component = Vue.extend(editForm);
- const toggleForm = () => { };
- const updateLockedAttribute = () => { };
+ const toggleForm = () => {};
+ const updateLockedAttribute = () => {};
vm1 = new Component({
propsData: {
@@ -30,12 +30,8 @@ describe('EditForm', () => {
});
it('renders on the appropriate warning text', () => {
- expect(
- vm1.$el.innerHTML.includes('Unlock this issue?'),
- ).toBe(true);
+ expect(vm1.$el.innerHTML.includes('Unlock this issue?')).toBe(true);
- expect(
- vm2.$el.innerHTML.includes('Lock this merge request?'),
- ).toBe(true);
+ expect(vm2.$el.innerHTML.includes('Lock this merge request?')).toBe(true);
});
});
diff --git a/spec/javascripts/sidebar/lock/lock_issue_sidebar_spec.js b/spec/javascripts/sidebar/lock/lock_issue_sidebar_spec.js
index 9abc3daf221..ca882032bdf 100644
--- a/spec/javascripts/sidebar/lock/lock_issue_sidebar_spec.js
+++ b/spec/javascripts/sidebar/lock/lock_issue_sidebar_spec.js
@@ -38,20 +38,14 @@ describe('LockIssueSidebar', () => {
});
it('shows if locked and/or editable', () => {
- expect(
- vm1.$el.innerHTML.includes('Edit'),
- ).toBe(true);
+ expect(vm1.$el.innerHTML.includes('Edit')).toBe(true);
- expect(
- vm1.$el.innerHTML.includes('Locked'),
- ).toBe(true);
+ expect(vm1.$el.innerHTML.includes('Locked')).toBe(true);
- expect(
- vm2.$el.innerHTML.includes('Unlocked'),
- ).toBe(true);
+ expect(vm2.$el.innerHTML.includes('Unlocked')).toBe(true);
});
- it('displays the edit form when editable', (done) => {
+ it('displays the edit form when editable', done => {
expect(vm1.isLockDialogOpen).toBe(false);
vm1.$el.querySelector('.lock-edit').click();
@@ -59,17 +53,13 @@ describe('LockIssueSidebar', () => {
expect(vm1.isLockDialogOpen).toBe(true);
vm1.$nextTick(() => {
- expect(
- vm1.$el
- .innerHTML
- .includes('Unlock this issue?'),
- ).toBe(true);
+ expect(vm1.$el.innerHTML.includes('Unlock this issue?')).toBe(true);
done();
});
});
- it('displays the edit form when opened from collapsed state', (done) => {
+ it('displays the edit form when opened from collapsed state', done => {
expect(vm1.isLockDialogOpen).toBe(false);
vm1.$el.querySelector('.sidebar-collapsed-icon').click();
@@ -77,11 +67,7 @@ describe('LockIssueSidebar', () => {
expect(vm1.isLockDialogOpen).toBe(true);
setTimeout(() => {
- expect(
- vm1.$el
- .innerHTML
- .includes('Unlock this issue?'),
- ).toBe(true);
+ expect(vm1.$el.innerHTML.includes('Unlock this issue?')).toBe(true);
done();
});
diff --git a/spec/javascripts/sidebar/participants_spec.js b/spec/javascripts/sidebar/participants_spec.js
index e796ddee62f..eb360fd256a 100644
--- a/spec/javascripts/sidebar/participants_spec.js
+++ b/spec/javascripts/sidebar/participants_spec.js
@@ -11,13 +11,9 @@ const PARTICIPANT = {
avatar_url: 'gravatar.com/avatar/xxx',
};
-const PARTICIPANT_LIST = [
- PARTICIPANT,
- { ...PARTICIPANT, id: 2 },
- { ...PARTICIPANT, id: 3 },
-];
+const PARTICIPANT_LIST = [PARTICIPANT, { ...PARTICIPANT, id: 2 }, { ...PARTICIPANT, id: 3 }];
-describe('Participants', function () {
+describe('Participants', function() {
let vm;
let Participants;
@@ -69,7 +65,7 @@ describe('Participants', function () {
expect(vm.$el.querySelector('.js-participants-expanded-loading-icon')).toBeDefined();
});
- it('when only showing visible participants, shows an avatar only for each participant under the limit', (done) => {
+ it('when only showing visible participants, shows an avatar only for each participant under the limit', done => {
const numberOfLessParticipants = 2;
vm = mountComponent(Participants, {
loading: false,
@@ -88,7 +84,7 @@ describe('Participants', function () {
.catch(done.fail);
});
- it('when only showing all participants, each has an avatar', (done) => {
+ it('when only showing all participants, each has an avatar', done => {
const numberOfLessParticipants = 2;
vm = mountComponent(Participants, {
loading: false,
@@ -120,7 +116,7 @@ describe('Participants', function () {
expect(moreParticipantLink).toBeNull();
});
- it('when too many participants, has more participants link to show more', (done) => {
+ it('when too many participants, has more participants link to show more', done => {
vm = mountComponent(Participants, {
loading: false,
participants: PARTICIPANT_LIST,
@@ -138,7 +134,7 @@ describe('Participants', function () {
.catch(done.fail);
});
- it('when too many participants and already showing them, has more participants link to show less', (done) => {
+ it('when too many participants and already showing them, has more participants link to show less', done => {
vm = mountComponent(Participants, {
loading: false,
participants: PARTICIPANT_LIST,
@@ -182,6 +178,7 @@ describe('Participants', function () {
const participantsIconEl = vm.$el.querySelector('.sidebar-collapsed-icon');
participantsIconEl.click();
+
expect(vm.$emit).toHaveBeenCalledWith('toggleSidebar');
});
});
diff --git a/spec/javascripts/sidebar/sidebar_assignees_spec.js b/spec/javascripts/sidebar/sidebar_assignees_spec.js
index ebaaa6e806b..3f0f67d71ca 100644
--- a/spec/javascripts/sidebar/sidebar_assignees_spec.js
+++ b/spec/javascripts/sidebar/sidebar_assignees_spec.js
@@ -24,10 +24,14 @@ describe('sidebar assignees', () => {
const SidebarAssigneeComponent = Vue.extend(SidebarAssignees);
sidebarAssigneesEl = document.querySelector('#js-vue-sidebar-assignees');
- vm = mountComponent(SidebarAssigneeComponent, {
- mediator,
- field: sidebarAssigneesEl.dataset.field,
- }, sidebarAssigneesEl);
+ vm = mountComponent(
+ SidebarAssigneeComponent,
+ {
+ mediator,
+ field: sidebarAssigneesEl.dataset.field,
+ },
+ sidebarAssigneesEl,
+ );
});
afterEach(() => {
@@ -39,6 +43,7 @@ describe('sidebar assignees', () => {
it('calls the mediator when saves the assignees', () => {
vm.saveAssignees();
+
expect(mediator.saveAssignees).toHaveBeenCalled();
});
@@ -49,8 +54,9 @@ describe('sidebar assignees', () => {
expect(mediator.store.assignees.length).toEqual(1);
});
- it('hides assignees until fetched', (done) => {
+ it('hides assignees until fetched', done => {
const currentAssignee = sidebarAssigneesEl.querySelector('.value');
+
expect(currentAssignee).toBe(null);
vm.store.isFetching.assignees = false;
diff --git a/spec/javascripts/sidebar/sidebar_mediator_spec.js b/spec/javascripts/sidebar/sidebar_mediator_spec.js
index da950258a94..2d853970fc4 100644
--- a/spec/javascripts/sidebar/sidebar_mediator_spec.js
+++ b/spec/javascripts/sidebar/sidebar_mediator_spec.js
@@ -25,20 +25,23 @@ describe('Sidebar mediator', function() {
expect(this.mediator.store.assignees[0]).toEqual(Mock.mediator.currentUser);
});
- it('saves assignees', (done) => {
- this.mediator.saveAssignees('issue[assignee_ids]')
- .then((resp) => {
+ it('saves assignees', done => {
+ this.mediator
+ .saveAssignees('issue[assignee_ids]')
+ .then(resp => {
expect(resp.status).toEqual(200);
done();
})
.catch(done.fail);
});
- it('fetches the data', (done) => {
- const mockData = Mock.responseMap.GET['/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar'];
+ it('fetches the data', done => {
+ const mockData =
+ Mock.responseMap.GET['/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar'];
spyOn(this.mediator, 'processFetchedData').and.callThrough();
- this.mediator.fetch()
+ this.mediator
+ .fetch()
.then(() => {
expect(this.mediator.processFetchedData).toHaveBeenCalledWith(mockData);
})
@@ -47,7 +50,8 @@ describe('Sidebar mediator', function() {
});
it('processes fetched data', () => {
- const mockData = Mock.responseMap.GET['/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar'];
+ const mockData =
+ Mock.responseMap.GET['/gitlab-org/gitlab-shell/issues/5.json?serializer=sidebar'];
this.mediator.processFetchedData(mockData);
expect(this.mediator.store.assignees).toEqual(mockData.assignees);
@@ -68,12 +72,13 @@ describe('Sidebar mediator', function() {
expect(this.mediator.store.setMoveToProjectId).toHaveBeenCalledWith(projectId);
});
- it('fetches autocomplete projects', (done) => {
+ it('fetches autocomplete projects', done => {
const searchTerm = 'foo';
spyOn(this.mediator.service, 'getProjectsAutocomplete').and.callThrough();
spyOn(this.mediator.store, 'setAutocompleteProjects').and.callThrough();
- this.mediator.fetchAutocompleteProjects(searchTerm)
+ this.mediator
+ .fetchAutocompleteProjects(searchTerm)
.then(() => {
expect(this.mediator.service.getProjectsAutocomplete).toHaveBeenCalledWith(searchTerm);
expect(this.mediator.store.setAutocompleteProjects).toHaveBeenCalled();
@@ -82,13 +87,14 @@ describe('Sidebar mediator', function() {
.catch(done.fail);
});
- it('moves issue', (done) => {
+ it('moves issue', done => {
const moveToProjectId = 7;
this.mediator.store.setMoveToProjectId(moveToProjectId);
spyOn(this.mediator.service, 'moveIssue').and.callThrough();
const visitUrl = spyOnDependency(SidebarMediator, 'visitUrl');
- this.mediator.moveIssue()
+ this.mediator
+ .moveIssue()
.then(() => {
expect(this.mediator.service.moveIssue).toHaveBeenCalledWith(moveToProjectId);
expect(visitUrl).toHaveBeenCalledWith('/root/some-project/issues/5');
@@ -97,11 +103,12 @@ describe('Sidebar mediator', function() {
.catch(done.fail);
});
- it('toggle subscription', (done) => {
+ it('toggle subscription', done => {
this.mediator.store.setSubscribedState(false);
spyOn(this.mediator.service, 'toggleSubscription').and.callThrough();
- this.mediator.toggleSubscription()
+ this.mediator
+ .toggleSubscription()
.then(() => {
expect(this.mediator.service.toggleSubscription).toHaveBeenCalled();
expect(this.mediator.store.subscribed).toEqual(true);
diff --git a/spec/javascripts/sidebar/sidebar_move_issue_spec.js b/spec/javascripts/sidebar/sidebar_move_issue_spec.js
index 8f35b9ca437..230e0a933a9 100644
--- a/spec/javascripts/sidebar/sidebar_move_issue_spec.js
+++ b/spec/javascripts/sidebar/sidebar_move_issue_spec.js
@@ -7,7 +7,7 @@ import SidebarService from '~/sidebar/services/sidebar_service';
import SidebarMoveIssue from '~/sidebar/lib/sidebar_move_issue';
import Mock from './mock_data';
-describe('SidebarMoveIssue', function () {
+describe('SidebarMoveIssue', function() {
beforeEach(() => {
Vue.http.interceptors.push(Mock.sidebarMockInterceptor);
this.mediator = new SidebarMediator(Mock.mediator);
@@ -72,11 +72,13 @@ describe('SidebarMoveIssue', function () {
expect($.fn.glDropdown).toHaveBeenCalled();
});
- it('escapes html from project name', (done) => {
+ it('escapes html from project name', done => {
this.$toggleButton.dropdown('toggle');
setTimeout(() => {
- expect(this.$content.find('.js-move-issue-dropdown-item')[1].innerHTML.trim()).toEqual('&lt;img src=x onerror=alert(document.domain)&gt; foo / bar');
+ expect(this.$content.find('.js-move-issue-dropdown-item')[1].innerHTML.trim()).toEqual(
+ '&lt;img src=x onerror=alert(document.domain)&gt; foo / bar',
+ );
done();
});
});
@@ -94,7 +96,7 @@ describe('SidebarMoveIssue', function () {
expect(this.$confirmButton.hasClass('is-loading')).toBe(true);
});
- it('should remove loading state from confirm button on failure', (done) => {
+ it('should remove loading state from confirm button on failure', done => {
spyOn(window, 'Flash');
spyOn(this.mediator, 'moveIssue').and.returnValue(Promise.reject());
this.mediator.setMoveToProjectId(7);
@@ -121,7 +123,7 @@ describe('SidebarMoveIssue', function () {
});
});
- it('should set moveToProjectId on dropdown item "No project" click', (done) => {
+ it('should set moveToProjectId on dropdown item "No project" click', done => {
spyOn(this.mediator, 'setMoveToProjectId');
// Open the dropdown
@@ -129,7 +131,10 @@ describe('SidebarMoveIssue', function () {
// Wait for the autocomplete request to finish
setTimeout(() => {
- this.$content.find('.js-move-issue-dropdown-item').eq(0).trigger('click');
+ this.$content
+ .find('.js-move-issue-dropdown-item')
+ .eq(0)
+ .trigger('click');
expect(this.mediator.setMoveToProjectId).toHaveBeenCalledWith(0);
expect(this.$confirmButton.prop('disabled')).toBeTruthy();
@@ -137,7 +142,7 @@ describe('SidebarMoveIssue', function () {
}, 0);
});
- it('should set moveToProjectId on dropdown item click', (done) => {
+ it('should set moveToProjectId on dropdown item click', done => {
spyOn(this.mediator, 'setMoveToProjectId');
// Open the dropdown
@@ -145,7 +150,10 @@ describe('SidebarMoveIssue', function () {
// Wait for the autocomplete request to finish
setTimeout(() => {
- this.$content.find('.js-move-issue-dropdown-item').eq(1).trigger('click');
+ this.$content
+ .find('.js-move-issue-dropdown-item')
+ .eq(1)
+ .trigger('click');
expect(this.mediator.setMoveToProjectId).toHaveBeenCalledWith(20);
expect(this.$confirmButton.attr('disabled')).toBe(undefined);
diff --git a/spec/javascripts/sidebar/sidebar_store_spec.js b/spec/javascripts/sidebar/sidebar_store_spec.js
index 08b112a54ba..85ff70fffbd 100644
--- a/spec/javascripts/sidebar/sidebar_store_spec.js
+++ b/spec/javascripts/sidebar/sidebar_store_spec.js
@@ -25,20 +25,17 @@ const PARTICIPANT = {
avatar_url: 'gravatar.com/avatar/xxx',
};
-const PARTICIPANT_LIST = [
- PARTICIPANT,
- { ...PARTICIPANT, id: 2 },
- { ...PARTICIPANT, id: 3 },
-];
+const PARTICIPANT_LIST = [PARTICIPANT, { ...PARTICIPANT, id: 2 }, { ...PARTICIPANT, id: 3 }];
-describe('Sidebar store', function () {
+describe('Sidebar store', function() {
beforeEach(() => {
this.store = new SidebarStore({
currentUser: {
id: 1,
name: 'Administrator',
username: 'root',
- avatar_url: 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ avatar_url:
+ 'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
},
editable: true,
rootPath: '/',
@@ -56,11 +53,13 @@ describe('Sidebar store', function () {
it('adds a new assignee', () => {
this.store.addAssignee(ASSIGNEE);
+
expect(this.store.assignees.length).toEqual(1);
});
it('removes an assignee', () => {
this.store.removeAssignee(ASSIGNEE);
+
expect(this.store.assignees.length).toEqual(0);
});
@@ -69,14 +68,17 @@ describe('Sidebar store', function () {
this.store.addAssignee(ASSIGNEE);
foundAssignee = this.store.findAssignee(ASSIGNEE);
+
expect(foundAssignee).toBeDefined();
expect(foundAssignee).toEqual(ASSIGNEE);
foundAssignee = this.store.findAssignee(ANOTHER_ASSINEE);
+
expect(foundAssignee).toBeUndefined();
});
it('removes all assignees', () => {
this.store.removeAllAssignees();
+
expect(this.store.assignees.length).toEqual(0);
});
@@ -108,6 +110,7 @@ describe('Sidebar store', function () {
};
this.store.setAssigneeData(users);
+
expect(this.store.isFetching.assignees).toBe(false);
expect(this.store.assignees.length).toEqual(3);
});
@@ -128,6 +131,7 @@ describe('Sidebar store', function () {
it('set time tracking data', () => {
this.store.setTimeTrackingData(Mock.time);
+
expect(this.store.timeEstimate).toEqual(Mock.time.time_estimate);
expect(this.store.totalTimeSpent).toEqual(Mock.time.total_time_spent);
expect(this.store.humanTimeEstimate).toEqual(Mock.time.human_time_estimate);
diff --git a/spec/javascripts/sidebar/sidebar_subscriptions_spec.js b/spec/javascripts/sidebar/sidebar_subscriptions_spec.js
index af2fde0a5be..88f64244237 100644
--- a/spec/javascripts/sidebar/sidebar_subscriptions_spec.js
+++ b/spec/javascripts/sidebar/sidebar_subscriptions_spec.js
@@ -6,7 +6,7 @@ import SidebarStore from '~/sidebar/stores/sidebar_store';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import Mock from './mock_data';
-describe('Sidebar Subscriptions', function () {
+describe('Sidebar Subscriptions', function() {
let vm;
let SidebarSubscriptions;
diff --git a/spec/javascripts/sidebar/subscriptions_spec.js b/spec/javascripts/sidebar/subscriptions_spec.js
index f0a53e573c3..32728e58b06 100644
--- a/spec/javascripts/sidebar/subscriptions_spec.js
+++ b/spec/javascripts/sidebar/subscriptions_spec.js
@@ -3,7 +3,7 @@ import subscriptions from '~/sidebar/components/subscriptions/subscriptions.vue'
import eventHub from '~/sidebar/event_hub';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
-describe('Subscriptions', function () {
+describe('Subscriptions', function() {
let vm;
let Subscriptions;
@@ -22,7 +22,9 @@ describe('Subscriptions', function () {
});
expect(vm.$refs.toggleButton.isLoading).toBe(true);
- expect(vm.$refs.toggleButton.$el.querySelector('.project-feature-toggle')).toHaveClass('is-loading');
+ expect(vm.$refs.toggleButton.$el.querySelector('.project-feature-toggle')).toHaveClass(
+ 'is-loading',
+ );
});
it('is toggled "off" when currently not subscribed', () => {
@@ -30,7 +32,9 @@ describe('Subscriptions', function () {
subscribed: false,
});
- expect(vm.$refs.toggleButton.$el.querySelector('.project-feature-toggle')).not.toHaveClass('is-checked');
+ expect(vm.$refs.toggleButton.$el.querySelector('.project-feature-toggle')).not.toHaveClass(
+ 'is-checked',
+ );
});
it('is toggled "on" when currently subscribed', () => {
@@ -38,7 +42,9 @@ describe('Subscriptions', function () {
subscribed: true,
});
- expect(vm.$refs.toggleButton.$el.querySelector('.project-feature-toggle')).toHaveClass('is-checked');
+ expect(vm.$refs.toggleButton.$el.querySelector('.project-feature-toggle')).toHaveClass(
+ 'is-checked',
+ );
});
it('toggleSubscription method emits `toggleSubscription` event on eventHub and Component', () => {
@@ -47,6 +53,7 @@ describe('Subscriptions', function () {
spyOn(vm, '$emit');
vm.toggleSubscription();
+
expect(eventHub.$emit).toHaveBeenCalledWith('toggleSubscription', jasmine.any(Object));
expect(vm.$emit).toHaveBeenCalledWith('toggleSubscription', jasmine.any(Object));
});
@@ -56,6 +63,7 @@ describe('Subscriptions', function () {
spyOn(vm, '$emit');
vm.onClickCollapsedIcon();
+
expect(vm.$emit).toHaveBeenCalledWith('toggleSidebar');
});
});
diff --git a/spec/javascripts/sidebar/todo_spec.js b/spec/javascripts/sidebar/todo_spec.js
index a929b804a29..657e88ecb96 100644
--- a/spec/javascripts/sidebar/todo_spec.js
+++ b/spec/javascripts/sidebar/todo_spec.js
@@ -42,7 +42,9 @@ describe('SidebarTodo', () => {
vm.collapsed = true;
Vue.nextTick()
.then(() => {
- expect(vm.buttonClasses).toBe('btn-blank btn-todo sidebar-collapsed-icon dont-change-state');
+ expect(vm.buttonClasses).toBe(
+ 'btn-blank btn-todo sidebar-collapsed-icon dont-change-state',
+ );
})
.then(done)
.catch(done.fail);
@@ -103,6 +105,7 @@ describe('SidebarTodo', () => {
it('emits `toggleTodo` event on component', () => {
spyOn(vm, '$emit');
vm.handleButtonClick();
+
expect(vm.$emit).toHaveBeenCalledWith('toggleTodo');
});
});
@@ -118,16 +121,18 @@ describe('SidebarTodo', () => {
container: 'body',
boundary: 'viewport',
};
+
expect(vm.$el.nodeName).toBe('BUTTON');
const elDataAttrs = vm.$el.dataset;
- Object.keys(elDataAttrs).forEach((attr) => {
+ Object.keys(elDataAttrs).forEach(attr => {
expect(elDataAttrs[attr]).toBe(dataAttributes[attr]);
});
});
it('renders button label element when `collapsed` prop is `false`', () => {
const buttonLabelEl = vm.$el.querySelector('span.issuable-todo-inner');
+
expect(buttonLabelEl).not.toBeNull();
expect(buttonLabelEl.innerText.trim()).toBe('Mark todo as done');
});
@@ -137,8 +142,11 @@ describe('SidebarTodo', () => {
Vue.nextTick()
.then(() => {
const buttonIconEl = vm.$el.querySelector('svg');
+
expect(buttonIconEl).not.toBeNull();
- expect(buttonIconEl.querySelector('use').getAttribute('xlink:href')).toContain('todo-done');
+ expect(buttonIconEl.querySelector('use').getAttribute('xlink:href')).toContain(
+ 'todo-done',
+ );
})
.then(done)
.catch(done.fail);
@@ -149,6 +157,7 @@ describe('SidebarTodo', () => {
Vue.nextTick()
.then(() => {
const loadingEl = vm.$el.querySelector('span.loading-container');
+
expect(loadingEl).not.toBeNull();
})
.then(done)
diff --git a/spec/javascripts/signin_tabs_memoizer_spec.js b/spec/javascripts/signin_tabs_memoizer_spec.js
index 9d3905fa1d8..52da6a79939 100644
--- a/spec/javascripts/signin_tabs_memoizer_spec.js
+++ b/spec/javascripts/signin_tabs_memoizer_spec.js
@@ -1,164 +1,170 @@
import AccessorUtilities from '~/lib/utils/accessor';
import SigninTabsMemoizer from '~/pages/sessions/new/signin_tabs_memoizer';
-(() => {
- describe('SigninTabsMemoizer', () => {
- const fixtureTemplate = 'static/signin_tabs.html.raw';
- const tabSelector = 'ul.new-session-tabs';
- const currentTabKey = 'current_signin_tab';
- let memo;
-
- function createMemoizer() {
- memo = new SigninTabsMemoizer({
- currentTabKey,
- tabSelector,
- });
- return memo;
- }
+describe('SigninTabsMemoizer', () => {
+ const fixtureTemplate = 'static/signin_tabs.html.raw';
+ const tabSelector = 'ul.new-session-tabs';
+ const currentTabKey = 'current_signin_tab';
+ let memo;
+
+ function createMemoizer() {
+ memo = new SigninTabsMemoizer({
+ currentTabKey,
+ tabSelector,
+ });
+ return memo;
+ }
- preloadFixtures(fixtureTemplate);
+ preloadFixtures(fixtureTemplate);
- beforeEach(() => {
- loadFixtures(fixtureTemplate);
+ beforeEach(() => {
+ loadFixtures(fixtureTemplate);
- spyOn(AccessorUtilities, 'isLocalStorageAccessSafe').and.returnValue(true);
- });
+ spyOn(AccessorUtilities, 'isLocalStorageAccessSafe').and.returnValue(true);
+ });
- it('does nothing if no tab was previously selected', () => {
- createMemoizer();
+ it('does nothing if no tab was previously selected', () => {
+ createMemoizer();
- expect(document.querySelector(`${tabSelector} > li.active a`).getAttribute('href')).toEqual('#ldap');
- });
+ expect(document.querySelector(`${tabSelector} > li.active a`).getAttribute('href')).toEqual(
+ '#ldap',
+ );
+ });
- it('shows last selected tab on boot', () => {
- createMemoizer().saveData('#ldap');
- const fakeTab = {
- click: () => {},
- };
- spyOn(document, 'querySelector').and.returnValue(fakeTab);
- spyOn(fakeTab, 'click');
+ it('shows last selected tab on boot', () => {
+ createMemoizer().saveData('#ldap');
+ const fakeTab = {
+ click: () => {},
+ };
+ spyOn(document, 'querySelector').and.returnValue(fakeTab);
+ spyOn(fakeTab, 'click');
- memo.bootstrap();
+ memo.bootstrap();
- // verify that triggers click on the last selected tab
- expect(document.querySelector).toHaveBeenCalledWith(`${tabSelector} a[href="#ldap"]`);
- expect(fakeTab.click).toHaveBeenCalled();
- });
+ // verify that triggers click on the last selected tab
+ expect(document.querySelector).toHaveBeenCalledWith(`${tabSelector} a[href="#ldap"]`);
+ expect(fakeTab.click).toHaveBeenCalled();
+ });
- it('clicks the first tab if value in local storage is bad', () => {
- createMemoizer().saveData('#bogus');
- const fakeTab = {
- click: () => {},
- };
- spyOn(document, 'querySelector').and.callFake(selector => (selector === `${tabSelector} a[href="#bogus"]` ? null : fakeTab));
- spyOn(fakeTab, 'click');
+ it('clicks the first tab if value in local storage is bad', () => {
+ createMemoizer().saveData('#bogus');
+ const fakeTab = {
+ click: () => {},
+ };
+ spyOn(document, 'querySelector').and.callFake(selector =>
+ selector === `${tabSelector} a[href="#bogus"]` ? null : fakeTab,
+ );
+ spyOn(fakeTab, 'click');
+
+ memo.bootstrap();
+
+ // verify that triggers click on stored selector and fallback
+ expect(document.querySelector.calls.allArgs()).toEqual([
+ ['ul.new-session-tabs a[href="#bogus"]'],
+ ['ul.new-session-tabs a'],
+ ]);
+
+ expect(fakeTab.click).toHaveBeenCalled();
+ });
- memo.bootstrap();
+ it('saves last selected tab on change', () => {
+ createMemoizer();
- // verify that triggers click on stored selector and fallback
- expect(document.querySelector.calls.allArgs()).toEqual([['ul.new-session-tabs a[href="#bogus"]'], ['ul.new-session-tabs a']]);
- expect(fakeTab.click).toHaveBeenCalled();
- });
+ document.querySelector('a[href="#login-pane"]').click();
- it('saves last selected tab on change', () => {
- createMemoizer();
+ expect(memo.readData()).toEqual('#login-pane');
+ });
- document.querySelector('a[href="#login-pane"]').click();
+ it('overrides last selected tab with hash tag when given', () => {
+ window.location.hash = '#ldap';
+ createMemoizer();
- expect(memo.readData()).toEqual('#login-pane');
- });
+ expect(memo.readData()).toEqual('#ldap');
+ });
- it('overrides last selected tab with hash tag when given', () => {
- window.location.hash = '#ldap';
- createMemoizer();
+ describe('class constructor', () => {
+ beforeEach(() => {
+ memo = createMemoizer();
+ });
- expect(memo.readData()).toEqual('#ldap');
+ it('should set .isLocalStorageAvailable', () => {
+ expect(AccessorUtilities.isLocalStorageAccessSafe).toHaveBeenCalled();
+ expect(memo.isLocalStorageAvailable).toBe(true);
});
+ });
- describe('class constructor', () => {
- beforeEach(() => {
- memo = createMemoizer();
- });
+ describe('saveData', () => {
+ beforeEach(() => {
+ memo = {
+ currentTabKey,
+ };
- it('should set .isLocalStorageAvailable', () => {
- expect(AccessorUtilities.isLocalStorageAccessSafe).toHaveBeenCalled();
- expect(memo.isLocalStorageAvailable).toBe(true);
- });
+ spyOn(localStorage, 'setItem');
});
- describe('saveData', () => {
- beforeEach(() => {
- memo = {
- currentTabKey,
- };
+ describe('if .isLocalStorageAvailable is `false`', () => {
+ beforeEach(function() {
+ memo.isLocalStorageAvailable = false;
- spyOn(localStorage, 'setItem');
+ SigninTabsMemoizer.prototype.saveData.call(memo);
});
- describe('if .isLocalStorageAvailable is `false`', () => {
- beforeEach(function () {
- memo.isLocalStorageAvailable = false;
-
- SigninTabsMemoizer.prototype.saveData.call(memo);
- });
-
- it('should not call .setItem', () => {
- expect(localStorage.setItem).not.toHaveBeenCalled();
- });
+ it('should not call .setItem', () => {
+ expect(localStorage.setItem).not.toHaveBeenCalled();
});
+ });
- describe('if .isLocalStorageAvailable is `true`', () => {
- const value = 'value';
+ describe('if .isLocalStorageAvailable is `true`', () => {
+ const value = 'value';
- beforeEach(function () {
- memo.isLocalStorageAvailable = true;
+ beforeEach(function() {
+ memo.isLocalStorageAvailable = true;
- SigninTabsMemoizer.prototype.saveData.call(memo, value);
- });
+ SigninTabsMemoizer.prototype.saveData.call(memo, value);
+ });
- it('should call .setItem', () => {
- expect(localStorage.setItem).toHaveBeenCalledWith(currentTabKey, value);
- });
+ it('should call .setItem', () => {
+ expect(localStorage.setItem).toHaveBeenCalledWith(currentTabKey, value);
});
});
+ });
- describe('readData', () => {
- const itemValue = 'itemValue';
- let readData;
+ describe('readData', () => {
+ const itemValue = 'itemValue';
+ let readData;
- beforeEach(() => {
- memo = {
- currentTabKey,
- };
+ beforeEach(() => {
+ memo = {
+ currentTabKey,
+ };
- spyOn(localStorage, 'getItem').and.returnValue(itemValue);
- });
+ spyOn(localStorage, 'getItem').and.returnValue(itemValue);
+ });
- describe('if .isLocalStorageAvailable is `false`', () => {
- beforeEach(function () {
- memo.isLocalStorageAvailable = false;
+ describe('if .isLocalStorageAvailable is `false`', () => {
+ beforeEach(function() {
+ memo.isLocalStorageAvailable = false;
- readData = SigninTabsMemoizer.prototype.readData.call(memo);
- });
+ readData = SigninTabsMemoizer.prototype.readData.call(memo);
+ });
- it('should not call .getItem and should return `null`', () => {
- expect(localStorage.getItem).not.toHaveBeenCalled();
- expect(readData).toBe(null);
- });
+ it('should not call .getItem and should return `null`', () => {
+ expect(localStorage.getItem).not.toHaveBeenCalled();
+ expect(readData).toBe(null);
});
+ });
- describe('if .isLocalStorageAvailable is `true`', () => {
- beforeEach(function () {
- memo.isLocalStorageAvailable = true;
+ describe('if .isLocalStorageAvailable is `true`', () => {
+ beforeEach(function() {
+ memo.isLocalStorageAvailable = true;
- readData = SigninTabsMemoizer.prototype.readData.call(memo);
- });
+ readData = SigninTabsMemoizer.prototype.readData.call(memo);
+ });
- it('should call .getItem and return the localStorage value', () => {
- expect(window.localStorage.getItem).toHaveBeenCalledWith(currentTabKey);
- expect(readData).toBe(itemValue);
- });
+ it('should call .getItem and return the localStorage value', () => {
+ expect(window.localStorage.getItem).toHaveBeenCalledWith(currentTabKey);
+ expect(readData).toBe(itemValue);
});
});
});
-})();
+});
diff --git a/spec/javascripts/smart_interval_spec.js b/spec/javascripts/smart_interval_spec.js
index d9b6dd1d487..c2c2a965e1d 100644
--- a/spec/javascripts/smart_interval_spec.js
+++ b/spec/javascripts/smart_interval_spec.js
@@ -3,7 +3,7 @@ import _ from 'underscore';
import SmartInterval from '~/smart_interval';
import waitForPromises from 'spec/helpers/wait_for_promises';
-describe('SmartInterval', function () {
+describe('SmartInterval', function() {
const DEFAULT_MAX_INTERVAL = 100;
const DEFAULT_STARTING_INTERVAL = 5;
const DEFAULT_SHORT_TIMEOUT = 75;
@@ -35,8 +35,8 @@ describe('SmartInterval', function () {
jasmine.clock().uninstall();
});
- describe('Increment Interval', function () {
- it('should increment the interval delay', (done) => {
+ describe('Increment Interval', function() {
+ it('should increment the interval delay', done => {
const smartInterval = createDefaultSmartInterval();
jasmine.clock().tick(DEFAULT_SHORT_TIMEOUT);
@@ -45,8 +45,8 @@ describe('SmartInterval', function () {
.then(() => {
const intervalConfig = smartInterval.cfg;
const iterationCount = 4;
- const maxIntervalAfterIterations = intervalConfig.startingInterval *
- (intervalConfig.incrementByFactorOf ** iterationCount);
+ const maxIntervalAfterIterations =
+ intervalConfig.startingInterval * intervalConfig.incrementByFactorOf ** iterationCount;
const currentInterval = smartInterval.getCurrentInterval();
// Provide some flexibility for performance of testing environment
@@ -57,7 +57,7 @@ describe('SmartInterval', function () {
.catch(done.fail);
});
- it('should not increment past maxInterval', (done) => {
+ it('should not increment past maxInterval', done => {
const smartInterval = createDefaultSmartInterval({ maxInterval: DEFAULT_STARTING_INTERVAL });
jasmine.clock().tick(DEFAULT_STARTING_INTERVAL);
@@ -66,6 +66,7 @@ describe('SmartInterval', function () {
waitForPromises()
.then(() => {
const currentInterval = smartInterval.getCurrentInterval();
+
expect(currentInterval).toBe(smartInterval.cfg.maxInterval);
})
.then(done)
@@ -82,6 +83,7 @@ describe('SmartInterval', function () {
waitForPromises()
.then(() => {
const oneInterval = smartInterval.cfg.startingInterval * DEFAULT_INCREMENT_FACTOR;
+
expect(smartInterval.getCurrentInterval()).toEqual(oneInterval);
})
.then(done)
@@ -89,12 +91,12 @@ describe('SmartInterval', function () {
});
});
- describe('Public methods', function () {
- beforeEach(function () {
+ describe('Public methods', function() {
+ beforeEach(function() {
this.smartInterval = createDefaultSmartInterval();
});
- it('should cancel an interval', function (done) {
+ it('should cancel an interval', function(done) {
const interval = this.smartInterval;
jasmine.clock().tick(DEFAULT_SHORT_TIMEOUT);
@@ -114,7 +116,7 @@ describe('SmartInterval', function () {
.catch(done.fail);
});
- it('should resume an interval', function (done) {
+ it('should resume an interval', function(done) {
const interval = this.smartInterval;
jasmine.clock().tick(DEFAULT_SHORT_TIMEOUT);
@@ -126,6 +128,7 @@ describe('SmartInterval', function () {
waitForPromises()
.then(() => {
const { intervalId } = interval.state;
+
expect(intervalId).toBeTruthy();
})
.then(done)
@@ -133,15 +136,15 @@ describe('SmartInterval', function () {
});
});
- describe('DOM Events', function () {
- beforeEach(function () {
+ describe('DOM Events', function() {
+ beforeEach(function() {
// This ensures DOM and DOM events are initialized for these specs.
setFixtures('<div></div>');
this.smartInterval = createDefaultSmartInterval();
});
- it('should pause when page is not visible', function (done) {
+ it('should pause when page is not visible', function(done) {
const interval = this.smartInterval;
jasmine.clock().tick(DEFAULT_SHORT_TIMEOUT);
@@ -168,8 +171,10 @@ describe('SmartInterval', function () {
waitForPromises()
.then(() => {
expect(interval.state.intervalId).toBeTruthy();
- expect(interval.getCurrentInterval() >= DEFAULT_STARTING_INTERVAL &&
- interval.getCurrentInterval() <= DEFAULT_MAX_INTERVAL).toBeTruthy();
+ expect(
+ interval.getCurrentInterval() >= DEFAULT_STARTING_INTERVAL &&
+ interval.getCurrentInterval() <= DEFAULT_MAX_INTERVAL,
+ ).toBeTruthy();
// simulates triggering of visibilitychange event
interval.handleVisibilityChange({ target: { visibilityState: 'hidden' } });
@@ -181,7 +186,7 @@ describe('SmartInterval', function () {
.catch(done.fail);
});
- it('should resume when page is becomes visible at the previous interval', function (done) {
+ it('should resume when page is becomes visible at the previous interval', function(done) {
const interval = this.smartInterval;
jasmine.clock().tick(DEFAULT_SHORT_TIMEOUT);
@@ -204,7 +209,7 @@ describe('SmartInterval', function () {
.catch(done.fail);
});
- it('should cancel on page unload', function (done) {
+ it('should cancel on page unload', function(done) {
const interval = this.smartInterval;
jasmine.clock().tick(DEFAULT_SHORT_TIMEOUT);
@@ -212,6 +217,7 @@ describe('SmartInterval', function () {
waitForPromises()
.then(() => {
$(document).triggerHandler('beforeunload');
+
expect(interval.state.intervalId).toBeUndefined();
expect(interval.getCurrentInterval()).toBe(interval.cfg.startingInterval);
})
@@ -219,8 +225,9 @@ describe('SmartInterval', function () {
.catch(done.fail);
});
- it('should execute callback before first interval', function () {
+ it('should execute callback before first interval', function() {
const interval = createDefaultSmartInterval({ immediateExecution: true });
+
expect(interval.cfg.immediateExecution).toBeFalsy();
});
});
diff --git a/spec/javascripts/syntax_highlight_spec.js b/spec/javascripts/syntax_highlight_spec.js
index 1c3dac3584e..5438368ccbe 100644
--- a/spec/javascripts/syntax_highlight_spec.js
+++ b/spec/javascripts/syntax_highlight_spec.js
@@ -1,4 +1,4 @@
-/* eslint-disable no-var, no-return-assign, quotes */
+/* eslint-disable no-var, no-return-assign */
import $ from 'jquery';
import syntaxHighlight from '~/syntax_highlight';
@@ -9,35 +9,44 @@ describe('Syntax Highlighter', function() {
if (window.gon == null) {
window.gon = {};
}
- return window.gon.user_color_scheme = value;
+ return (window.gon.user_color_scheme = value);
};
describe('on a js-syntax-highlight element', function() {
beforeEach(function() {
return setFixtures('<div class="js-syntax-highlight"></div>');
});
- return it('applies syntax highlighting', function() {
+
+ it('applies syntax highlighting', function() {
stubUserColorScheme('monokai');
syntaxHighlight($('.js-syntax-highlight'));
- return expect($('.js-syntax-highlight')).toHaveClass('monokai');
+
+ expect($('.js-syntax-highlight')).toHaveClass('monokai');
});
});
- return describe('on a parent element', function() {
+
+ describe('on a parent element', function() {
beforeEach(function() {
- return setFixtures("<div class=\"parent\">\n <div class=\"js-syntax-highlight\"></div>\n <div class=\"foo\"></div>\n <div class=\"js-syntax-highlight\"></div>\n</div>");
+ return setFixtures(
+ '<div class="parent">\n <div class="js-syntax-highlight"></div>\n <div class="foo"></div>\n <div class="js-syntax-highlight"></div>\n</div>',
+ );
});
+
it('applies highlighting to all applicable children', function() {
stubUserColorScheme('monokai');
syntaxHighlight($('.parent'));
+
expect($('.parent, .foo')).not.toHaveClass('monokai');
- return expect($('.monokai').length).toBe(2);
+ expect($('.monokai').length).toBe(2);
});
- return it('prevents an infinite loop when no matches exist', function() {
+
+ it('prevents an infinite loop when no matches exist', function() {
var highlight;
setFixtures('<div></div>');
highlight = function() {
return syntaxHighlight($('div'));
};
- return expect(highlight).not.toThrow();
+
+ expect(highlight).not.toThrow();
});
});
});
diff --git a/spec/javascripts/todos_spec.js b/spec/javascripts/todos_spec.js
index e74f4bdef7e..69e43274250 100644
--- a/spec/javascripts/todos_spec.js
+++ b/spec/javascripts/todos_spec.js
@@ -14,10 +14,10 @@ describe('Todos', () => {
});
describe('goToTodoUrl', () => {
- it('opens the todo url', (done) => {
+ it('opens the todo url', done => {
const todoLink = todoItem.dataset.url;
- spyOnDependency(Todos, 'visitUrl').and.callFake((url) => {
+ spyOnDependency(Todos, 'visitUrl').and.callFake(url => {
expect(url).toEqual(todoLink);
done();
});
diff --git a/spec/javascripts/toggle_buttons_spec.js b/spec/javascripts/toggle_buttons_spec.js
index 17d0b94ebe0..09756ff76ec 100644
--- a/spec/javascripts/toggle_buttons_spec.js
+++ b/spec/javascripts/toggle_buttons_spec.js
@@ -24,11 +24,14 @@ describe('ToggleButtons', () => {
it('should initialize as checked', () => {
const wrapper = setupFixture(true);
- expect(wrapper.querySelector('.js-project-feature-toggle').classList.contains('is-checked')).toEqual(true);
+ expect(
+ wrapper.querySelector('.js-project-feature-toggle').classList.contains('is-checked'),
+ ).toEqual(true);
+
expect(wrapper.querySelector('.js-project-feature-toggle-input').value).toEqual('true');
});
- it('should toggle to unchecked when clicked', (done) => {
+ it('should toggle to unchecked when clicked', done => {
const wrapper = setupFixture(true);
const toggleButton = wrapper.querySelector('.js-project-feature-toggle');
@@ -48,11 +51,14 @@ describe('ToggleButtons', () => {
it('should initialize as unchecked', () => {
const wrapper = setupFixture(false);
- expect(wrapper.querySelector('.js-project-feature-toggle').classList.contains('is-checked')).toEqual(false);
+ expect(
+ wrapper.querySelector('.js-project-feature-toggle').classList.contains('is-checked'),
+ ).toEqual(false);
+
expect(wrapper.querySelector('.js-project-feature-toggle-input').value).toEqual('false');
});
- it('should toggle to checked when clicked', (done) => {
+ it('should toggle to checked when clicked', done => {
const wrapper = setupFixture(false);
const toggleButton = wrapper.querySelector('.js-project-feature-toggle');
@@ -68,7 +74,7 @@ describe('ToggleButtons', () => {
});
});
- it('should emit `trigger-change` event', (done) => {
+ it('should emit `trigger-change` event', done => {
const changeSpy = jasmine.createSpy('changeEventHandler');
const wrapper = setupFixture(false);
const toggleButton = wrapper.querySelector('.js-project-feature-toggle');
@@ -87,7 +93,7 @@ describe('ToggleButtons', () => {
});
describe('clickCallback', () => {
- it('should show loading indicator while waiting', (done) => {
+ it('should show loading indicator while waiting', done => {
const isChecked = true;
const clickCallback = (newValue, toggleButton) => {
const input = toggleButton.querySelector('.js-project-feature-toggle-input');
diff --git a/spec/javascripts/u2f/authenticate_spec.js b/spec/javascripts/u2f/authenticate_spec.js
index 57e0caa692c..ddb09811dda 100644
--- a/spec/javascripts/u2f/authenticate_spec.js
+++ b/spec/javascripts/u2f/authenticate_spec.js
@@ -3,7 +3,7 @@ import U2FAuthenticate from '~/u2f/authenticate';
import 'vendor/u2f';
import MockU2FDevice from './mock_u2f_device';
-describe('U2FAuthenticate', function () {
+describe('U2FAuthenticate', function() {
preloadFixtures('u2f/authenticate.html.raw');
beforeEach(() => {
@@ -32,30 +32,40 @@ describe('U2FAuthenticate', function () {
window.u2f = this.oldu2f;
});
- it('falls back to normal 2fa', (done) => {
- this.component.start().then(() => {
- expect(this.component.switchToFallbackUI).toHaveBeenCalled();
- done();
- }).catch(done.fail);
+ it('falls back to normal 2fa', done => {
+ this.component
+ .start()
+ .then(() => {
+ expect(this.component.switchToFallbackUI).toHaveBeenCalled();
+ done();
+ })
+ .catch(done.fail);
});
});
describe('with u2f available', () => {
- beforeEach((done) => {
+ beforeEach(done => {
// bypass automatic form submission within renderAuthenticated
spyOn(this.component, 'renderAuthenticated').and.returnValue(true);
this.u2fDevice = new MockU2FDevice();
- this.component.start().then(done).catch(done.fail);
+ this.component
+ .start()
+ .then(done)
+ .catch(done.fail);
});
it('allows authenticating via a U2F device', () => {
const inProgressMessage = this.container.find('p');
+
expect(inProgressMessage.text()).toContain('Trying to communicate with your device');
this.u2fDevice.respondToAuthenticateRequest({
deviceData: 'this is data from the device',
});
- expect(this.component.renderAuthenticated).toHaveBeenCalledWith('{"deviceData":"this is data from the device"}');
+
+ expect(this.component.renderAuthenticated).toHaveBeenCalledWith(
+ '{"deviceData":"this is data from the device"}',
+ );
});
describe('errors', () => {
@@ -66,7 +76,8 @@ describe('U2FAuthenticate', function () {
errorCode: 'error!',
});
const errorMessage = this.container.find('p');
- return expect(errorMessage.text()).toContain('There was a problem communicating with your device');
+
+ expect(errorMessage.text()).toContain('There was a problem communicating with your device');
});
return it('allows retrying authentication after an error', () => {
let setupButton = this.container.find('#js-login-u2f-device');
@@ -81,7 +92,10 @@ describe('U2FAuthenticate', function () {
this.u2fDevice.respondToAuthenticateRequest({
deviceData: 'this is data from the device',
});
- expect(this.component.renderAuthenticated).toHaveBeenCalledWith('{"deviceData":"this is data from the device"}');
+
+ expect(this.component.renderAuthenticated).toHaveBeenCalledWith(
+ '{"deviceData":"this is data from the device"}',
+ );
});
});
});
diff --git a/spec/javascripts/u2f/mock_u2f_device.js b/spec/javascripts/u2f/mock_u2f_device.js
index 012a1cefbbf..26ddd8ade61 100644
--- a/spec/javascripts/u2f/mock_u2f_device.js
+++ b/spec/javascripts/u2f/mock_u2f_device.js
@@ -1,18 +1,18 @@
-/* eslint-disable wrap-iife, no-unused-expressions, no-return-assign, no-param-reassign */
+/* eslint-disable no-unused-expressions, no-return-assign, no-param-reassign */
export default class MockU2FDevice {
constructor() {
this.respondToAuthenticateRequest = this.respondToAuthenticateRequest.bind(this);
this.respondToRegisterRequest = this.respondToRegisterRequest.bind(this);
window.u2f || (window.u2f = {});
- window.u2f.register = (function (_this) {
- return function (appId, registerRequests, signRequests, callback) {
- return _this.registerCallback = callback;
+ window.u2f.register = (function(_this) {
+ return function(appId, registerRequests, signRequests, callback) {
+ return (_this.registerCallback = callback);
};
})(this);
- window.u2f.sign = (function (_this) {
- return function (appId, challenges, signRequests, callback) {
- return _this.authenticateCallback = callback;
+ window.u2f.sign = (function(_this) {
+ return function(appId, challenges, signRequests, callback) {
+ return (_this.authenticateCallback = callback);
};
})(this);
}
diff --git a/spec/javascripts/u2f/register_spec.js b/spec/javascripts/u2f/register_spec.js
index b774627651f..261db3d66d7 100644
--- a/spec/javascripts/u2f/register_spec.js
+++ b/spec/javascripts/u2f/register_spec.js
@@ -3,41 +3,48 @@ import U2FRegister from '~/u2f/register';
import 'vendor/u2f';
import MockU2FDevice from './mock_u2f_device';
-describe('U2FRegister', function () {
+describe('U2FRegister', function() {
preloadFixtures('u2f/register.html.raw');
- beforeEach((done) => {
+ beforeEach(done => {
loadFixtures('u2f/register.html.raw');
this.u2fDevice = new MockU2FDevice();
this.container = $('#js-register-u2f');
this.component = new U2FRegister(this.container, $('#js-register-u2f-templates'), {}, 'token');
- this.component.start().then(done).catch(done.fail);
+ this.component
+ .start()
+ .then(done)
+ .catch(done.fail);
});
it('allows registering a U2F device', () => {
const setupButton = this.container.find('#js-setup-u2f-device');
+
expect(setupButton.text()).toBe('Set up new U2F device');
setupButton.trigger('click');
const inProgressMessage = this.container.children('p');
+
expect(inProgressMessage.text()).toContain('Trying to communicate with your device');
this.u2fDevice.respondToRegisterRequest({
deviceData: 'this is data from the device',
});
const registeredMessage = this.container.find('p');
const deviceResponse = this.container.find('#js-device-response');
+
expect(registeredMessage.text()).toContain('Your device was successfully set up!');
- return expect(deviceResponse.val()).toBe('{"deviceData":"this is data from the device"}');
+ expect(deviceResponse.val()).toBe('{"deviceData":"this is data from the device"}');
});
- return describe('errors', () => {
- it('doesn\'t allow the same device to be registered twice (for the same user', () => {
+ describe('errors', () => {
+ it("doesn't allow the same device to be registered twice (for the same user", () => {
const setupButton = this.container.find('#js-setup-u2f-device');
setupButton.trigger('click');
this.u2fDevice.respondToRegisterRequest({
errorCode: 4,
});
const errorMessage = this.container.find('p');
- return expect(errorMessage.text()).toContain('already been registered with us');
+
+ expect(errorMessage.text()).toContain('already been registered with us');
});
it('displays an error message for other errors', () => {
@@ -47,10 +54,11 @@ describe('U2FRegister', function () {
errorCode: 'error!',
});
const errorMessage = this.container.find('p');
- return expect(errorMessage.text()).toContain('There was a problem communicating with your device');
+
+ expect(errorMessage.text()).toContain('There was a problem communicating with your device');
});
- return it('allows retrying registration after an error', () => {
+ it('allows retrying registration after an error', () => {
let setupButton = this.container.find('#js-setup-u2f-device');
setupButton.trigger('click');
this.u2fDevice.respondToRegisterRequest({
@@ -64,7 +72,8 @@ describe('U2FRegister', function () {
deviceData: 'this is data from the device',
});
const registeredMessage = this.container.find('p');
- return expect(registeredMessage.text()).toContain('Your device was successfully set up!');
+
+ expect(registeredMessage.text()).toContain('Your device was successfully set up!');
});
});
});
diff --git a/spec/javascripts/u2f/util_spec.js b/spec/javascripts/u2f/util_spec.js
index 4187183236f..32cd6891384 100644
--- a/spec/javascripts/u2f/util_spec.js
+++ b/spec/javascripts/u2f/util_spec.js
@@ -3,42 +3,58 @@ import { canInjectU2fApi } from '~/u2f/util';
describe('U2F Utils', () => {
describe('canInjectU2fApi', () => {
it('returns false for Chrome < 41', () => {
- const userAgent = 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.28 Safari/537.36';
+ const userAgent =
+ 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.28 Safari/537.36';
+
expect(canInjectU2fApi(userAgent)).toBe(false);
});
it('returns true for Chrome >= 41', () => {
- const userAgent = 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36';
+ const userAgent =
+ 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36';
+
expect(canInjectU2fApi(userAgent)).toBe(true);
});
it('returns false for Opera < 40', () => {
- const userAgent = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 OPR/32.0.1948.25';
+ const userAgent =
+ 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36 OPR/32.0.1948.25';
+
expect(canInjectU2fApi(userAgent)).toBe(false);
});
it('returns true for Opera >= 40', () => {
- const userAgent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 OPR/43.0.2442.991';
+ const userAgent =
+ 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 OPR/43.0.2442.991';
+
expect(canInjectU2fApi(userAgent)).toBe(true);
});
it('returns false for Safari', () => {
- const userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/10.1.1 Safari/603.2.4';
+ const userAgent =
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/603.2.4 (KHTML, like Gecko) Version/10.1.1 Safari/603.2.4';
+
expect(canInjectU2fApi(userAgent)).toBe(false);
});
it('returns false for Chrome on Android', () => {
- const userAgent = 'Mozilla/5.0 (Linux; Android 7.0; VS988 Build/NRD90U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3145.0 Mobile Safari/537.36';
+ const userAgent =
+ 'Mozilla/5.0 (Linux; Android 7.0; VS988 Build/NRD90U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3145.0 Mobile Safari/537.36';
+
expect(canInjectU2fApi(userAgent)).toBe(false);
});
it('returns false for Chrome on iOS', () => {
- const userAgent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1';
+ const userAgent =
+ 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) CriOS/56.0.2924.75 Mobile/14E5239e Safari/602.1';
+
expect(canInjectU2fApi(userAgent)).toBe(false);
});
it('returns false for Safari on iOS', () => {
- const userAgent = 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A356 Safari/604.1';
+ const userAgent =
+ 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A356 Safari/604.1';
+
expect(canInjectU2fApi(userAgent)).toBe(false);
});
});
diff --git a/spec/javascripts/version_check_image_spec.js b/spec/javascripts/version_check_image_spec.js
index 5f963e8c11e..0e69fcc4c5f 100644
--- a/spec/javascripts/version_check_image_spec.js
+++ b/spec/javascripts/version_check_image_spec.js
@@ -2,17 +2,19 @@ import $ from 'jquery';
import VersionCheckImage from '~/version_check_image';
import ClassSpecHelper from './helpers/class_spec_helper';
-describe('VersionCheckImage', function () {
- describe('bindErrorEvent', function () {
+describe('VersionCheckImage', function() {
+ describe('bindErrorEvent', function() {
ClassSpecHelper.itShouldBeAStaticMethod(VersionCheckImage, 'bindErrorEvent');
- beforeEach(function () {
+ beforeEach(function() {
this.imageElement = $('<div></div>');
});
- it('registers an error event', function () {
+ it('registers an error event', function() {
spyOn($.prototype, 'on');
- spyOn($.prototype, 'off').and.callFake(function () { return this; });
+ spyOn($.prototype, 'off').and.callFake(function() {
+ return this;
+ });
VersionCheckImage.bindErrorEvent(this.imageElement);
@@ -20,7 +22,7 @@ describe('VersionCheckImage', function () {
expect($.prototype.on).toHaveBeenCalledWith('error', jasmine.any(Function));
});
- it('hides the imageElement on error', function () {
+ it('hides the imageElement on error', function() {
spyOn($.prototype, 'hide');
VersionCheckImage.bindErrorEvent(this.imageElement);
diff --git a/spec/javascripts/vue_mr_widget/components/deployment_spec.js b/spec/javascripts/vue_mr_widget/components/deployment_spec.js
index 50c2b0e2bd0..e355416bd27 100644
--- a/spec/javascripts/vue_mr_widget/components/deployment_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/deployment_spec.js
@@ -2,43 +2,52 @@ import Vue from 'vue';
import deploymentComponent from '~/vue_merge_request_widget/components/deployment.vue';
import MRWidgetService from '~/vue_merge_request_widget/services/mr_widget_service';
import { getTimeago } from '~/lib/utils/datetime_utility';
+import mountComponent from '../../helpers/vue_mount_component_helper';
-const deploymentMockData = {
- id: 15,
- name: 'review/diplo',
- url: '/root/acets-review-apps/environments/15',
- stop_url: '/root/acets-review-apps/environments/15/stop',
- metrics_url: '/root/acets-review-apps/environments/15/deployments/1/metrics',
- metrics_monitoring_url: '/root/acets-review-apps/environments/15/metrics',
- external_url: 'http://diplo.',
- external_url_formatted: 'diplo.',
- deployed_at: '2017-03-22T22:44:42.258Z',
- deployed_at_formatted: 'Mar 22, 2017 10:44pm',
-};
-const createComponent = () => {
+describe('Deployment component', () => {
const Component = Vue.extend(deploymentComponent);
+ const deploymentMockData = {
+ id: 15,
+ name: 'review/diplo',
+ url: '/root/review-apps/environments/15',
+ stop_url: '/root/review-apps/environments/15/stop',
+ metrics_url: '/root/review-apps/environments/15/deployments/1/metrics',
+ metrics_monitoring_url: '/root/review-apps/environments/15/metrics',
+ external_url: 'http://gitlab.com.',
+ external_url_formatted: 'gitlab',
+ deployed_at: '2017-03-22T22:44:42.258Z',
+ deployed_at_formatted: 'Mar 22, 2017 10:44pm',
+ changes: [
+ {
+ path: 'index.html',
+ external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/index.html',
+ },
+ {
+ path: 'imgs/gallery.html',
+ external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/imgs/gallery.html',
+ },
+ {
+ path: 'about/',
+ external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/about/',
+ },
+ ],
+ };
- return new Component({
- el: document.createElement('div'),
- propsData: { deployment: { ...deploymentMockData } },
- });
-};
-
-describe('Deployment component', () => {
let vm;
- beforeEach(() => {
- vm = createComponent();
- });
-
afterEach(() => {
vm.$destroy();
});
- describe('computed', () => {
+ describe('', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, { deployment: { ...deploymentMockData }, showMetrics: true });
+ });
+
describe('deployTimeago', () => {
it('return formatted date', () => {
const readable = getTimeago().format(deploymentMockData.deployed_at);
+
expect(vm.deployTimeago).toEqual(readable);
});
});
@@ -96,24 +105,23 @@ describe('Deployment component', () => {
expect(vm.hasDeploymentMeta).toEqual(false);
});
});
- });
- describe('methods', () => {
describe('stopEnvironment', () => {
const url = '/foo/bar';
- const returnPromise = () => new Promise((resolve) => {
- resolve({
- data: {
- redirect_url: url,
- },
+ const returnPromise = () =>
+ new Promise(resolve => {
+ resolve({
+ data: {
+ redirect_url: url,
+ },
+ });
});
- });
const mockStopEnvironment = () => {
vm.stopEnvironment(deploymentMockData);
return vm;
};
- it('should show a confirm dialog and call service.stopEnvironment when confirmed', (done) => {
+ it('should show a confirm dialog and call service.stopEnvironment when confirmed', done => {
spyOn(window, 'confirm').and.returnValue(true);
spyOn(MRWidgetService, 'stopEnvironment').and.returnValue(returnPromise(true));
const visitUrl = spyOnDependency(deploymentComponent, 'visitUrl').and.returnValue(true);
@@ -136,36 +144,141 @@ describe('Deployment component', () => {
expect(MRWidgetService.stopEnvironment).not.toHaveBeenCalled();
});
});
- });
-
- describe('template', () => {
- let el;
-
- beforeEach(() => {
- vm = createComponent(deploymentMockData);
- el = vm.$el;
- });
it('renders deployment name', () => {
- expect(el.querySelector('.js-deploy-meta').getAttribute('href')).toEqual(deploymentMockData.url);
- expect(el.querySelector('.js-deploy-meta').innerText).toContain(deploymentMockData.name);
+ expect(vm.$el.querySelector('.js-deploy-meta').getAttribute('href')).toEqual(
+ deploymentMockData.url,
+ );
+
+ expect(vm.$el.querySelector('.js-deploy-meta').innerText).toContain(deploymentMockData.name);
});
it('renders external URL', () => {
- expect(el.querySelector('.js-deploy-url').getAttribute('href')).toEqual(deploymentMockData.external_url);
- expect(el.querySelector('.js-deploy-url').innerText).toContain('View app');
+ expect(vm.$el.querySelector('.js-deploy-url').getAttribute('href')).toEqual(
+ deploymentMockData.external_url,
+ );
+
+ expect(vm.$el.querySelector('.js-deploy-url').innerText).toContain('View app');
});
it('renders stop button', () => {
- expect(el.querySelector('.btn')).not.toBeNull();
+ expect(vm.$el.querySelector('.btn')).not.toBeNull();
});
it('renders deployment time', () => {
- expect(el.querySelector('.js-deploy-time').innerText).toContain(vm.deployTimeago);
+ expect(vm.$el.querySelector('.js-deploy-time').innerText).toContain(vm.deployTimeago);
});
it('renders metrics component', () => {
- expect(el.querySelector('.js-mr-memory-usage')).not.toBeNull();
+ expect(vm.$el.querySelector('.js-mr-memory-usage')).not.toBeNull();
+ });
+ });
+
+ describe('with showMetrics enabled', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, { deployment: { ...deploymentMockData }, showMetrics: true });
+ });
+
+ it('shows metrics', () => {
+ expect(vm.$el).toContainElement('.js-mr-memory-usage');
+ });
+ });
+
+ describe('with showMetrics disabled', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, { deployment: { ...deploymentMockData }, showMetrics: false });
+ });
+
+ it('hides metrics', () => {
+ expect(vm.$el).not.toContainElement('.js-mr-memory-usage');
+ });
+ });
+
+ describe('without changes', () => {
+ beforeEach(() => {
+ delete deploymentMockData.changes;
+
+ vm = mountComponent(Component, { deployment: { ...deploymentMockData }, showMetrics: true });
+ });
+
+ it('renders the link to the review app without dropdown', () => {
+ expect(vm.$el.querySelector('.js-mr-wigdet-deployment-dropdown')).toBeNull();
+ expect(vm.$el.querySelector('.js-deploy-url-feature-flag')).not.toBeNull();
+ });
+ });
+
+ describe('deployment status', () => {
+ describe('running', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ deployment: Object.assign({}, deploymentMockData, { status: 'running' }),
+ showMetrics: true,
+ });
+ });
+
+ it('renders information about running deployment', () => {
+ expect(vm.$el.querySelector('.js-deployment-info').textContent).toContain('Deploying to');
+ });
+
+ it('renders disabled stop button', () => {
+ expect(vm.$el.querySelector('.js-stop-env').getAttribute('disabled')).toBe('disabled');
+ });
+ });
+
+ describe('success', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ deployment: Object.assign({}, deploymentMockData, { status: 'success' }),
+ showMetrics: true,
+ });
+ });
+
+ it('renders information about finished deployment', () => {
+ expect(vm.$el.querySelector('.js-deployment-info').textContent).toContain('Deployed to');
+ });
+ });
+
+ describe('failed', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ deployment: Object.assign({}, deploymentMockData, { status: 'failed' }),
+ showMetrics: true,
+ });
+ });
+
+ it('renders information about finished deployment', () => {
+ expect(vm.$el.querySelector('.js-deployment-info').textContent).toContain(
+ 'Failed to deploy to',
+ );
+ });
+ });
+
+ describe('created', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ deployment: Object.assign({}, deploymentMockData, { status: 'created' }),
+ showMetrics: true,
+ });
+ });
+
+ it('renders information about created deployment', () => {
+ expect(vm.$el.querySelector('.js-deployment-info').textContent).toContain('Will deploy to');
+ });
+ });
+
+ describe('canceled', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ deployment: Object.assign({}, deploymentMockData, { status: 'canceled' }),
+ showMetrics: true,
+ });
+ });
+
+ it('renders information about canceled deployment', () => {
+ expect(vm.$el.querySelector('.js-deployment-info').textContent).toContain(
+ 'Failed to deploy to',
+ );
+ });
});
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_author_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_author_spec.js
index 00f4f2d7c39..b69082082ba 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_author_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_author_spec.js
@@ -13,9 +13,9 @@ describe('MrWidgetAuthor', () => {
name: 'Administrator',
username: 'root',
webUrl: 'http://localhost:3000/root',
- avatarUrl: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ avatarUrl:
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
},
-
});
});
@@ -28,9 +28,9 @@ describe('MrWidgetAuthor', () => {
});
it('renders image with avatar url', () => {
- expect(
- vm.$el.querySelector('img').getAttribute('src'),
- ).toEqual('http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon');
+ expect(vm.$el.querySelector('img').getAttribute('src')).toEqual(
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ );
});
it('renders author name', () => {
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_author_time_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_author_time_spec.js
index 10143402acf..787f44e478d 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_author_time_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_author_time_spec.js
@@ -14,7 +14,8 @@ describe('MrWidgetAuthorTime', () => {
name: 'Administrator',
username: 'root',
webUrl: 'http://localhost:3000/root',
- avatarUrl: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ avatarUrl:
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
},
dateTitle: '2017-03-23T23:02:00.807Z',
dateReadable: '12 hours ago',
@@ -34,7 +35,10 @@ describe('MrWidgetAuthorTime', () => {
});
it('renders provided time', () => {
- expect(vm.$el.querySelector('time').getAttribute('data-original-title')).toEqual('2017-03-23T23:02:00.807Z');
+ expect(vm.$el.querySelector('time').getAttribute('data-original-title')).toEqual(
+ '2017-03-23T23:02:00.807Z',
+ );
+
expect(vm.$el.querySelector('time').textContent.trim()).toEqual('12 hours ago');
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_container_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_container_spec.js
new file mode 100644
index 00000000000..16c8c939a6f
--- /dev/null
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_container_spec.js
@@ -0,0 +1,51 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import MrWidgetContainer from '~/vue_merge_request_widget/components/mr_widget_container.vue';
+
+const BODY_HTML = '<div class="test-body">Hello World</div>';
+const FOOTER_HTML = '<div class="test-footer">Goodbye!</div>';
+
+describe('MrWidgetContainer', () => {
+ let wrapper;
+
+ const factory = (options = {}) => {
+ const localVue = createLocalVue();
+
+ wrapper = shallowMount(localVue.extend(MrWidgetContainer), {
+ localVue,
+ ...options,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('has layout', () => {
+ factory();
+
+ expect(wrapper.is('.mr-widget-heading')).toBe(true);
+ expect(wrapper.contains('.mr-widget-content')).toBe(true);
+ });
+
+ it('accepts default slot', () => {
+ factory({
+ slots: {
+ default: BODY_HTML,
+ },
+ });
+
+ expect(wrapper.contains('.mr-widget-content .test-body')).toBe(true);
+ });
+
+ it('accepts footer slot', () => {
+ factory({
+ slots: {
+ default: BODY_HTML,
+ footer: FOOTER_HTML,
+ },
+ });
+
+ expect(wrapper.contains('.mr-widget-content .test-body')).toBe(true);
+ expect(wrapper.contains('.test-footer')).toBe(true);
+ });
+});
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js
index 237e2fa79f2..02c476f2871 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_header_spec.js
@@ -41,6 +41,7 @@ describe('MRWidgetHeader', () => {
statusPath: 'abc',
},
});
+
expect(vm.shouldShowCommitsBehindText).toEqual(false);
});
});
@@ -58,7 +59,9 @@ describe('MRWidgetHeader', () => {
},
});
- expect(vm.commitsBehindText).toEqual('The source branch is <a href="/foo/bar/master">1 commit behind</a> the target branch');
+ expect(vm.commitsBehindText).toEqual(
+ 'The source branch is <a href="/foo/bar/master">1 commit behind</a> the target branch',
+ );
});
it('returns plural when there is more than one commit', () => {
@@ -73,7 +76,9 @@ describe('MRWidgetHeader', () => {
},
});
- expect(vm.commitsBehindText).toEqual('The source branch is <a href="/foo/bar/master">2 commits behind</a> the target branch');
+ expect(vm.commitsBehindText).toEqual(
+ 'The source branch is <a href="/foo/bar/master">2 commits behind</a> the target branch',
+ );
});
});
});
@@ -165,6 +170,7 @@ describe('MRWidgetHeader', () => {
vm = mountComponent(Component, { mr });
const link = vm.$el.querySelector('.js-web-ide');
+
expect(link.classList.contains('disabled')).toBe(true);
expect(link.getAttribute('href')).toBeNull();
});
@@ -295,9 +301,18 @@ describe('MRWidgetHeader', () => {
});
it('renders diverged commits info', () => {
- expect(vm.$el.querySelector('.diverged-commits-count').textContent).toEqual('The source branch is 12 commits behind the target branch');
- expect(vm.$el.querySelector('.diverged-commits-count a').textContent).toEqual('12 commits behind');
- expect(vm.$el.querySelector('.diverged-commits-count a')).toHaveAttr('href', vm.mr.targetBranchPath);
+ expect(vm.$el.querySelector('.diverged-commits-count').textContent).toEqual(
+ 'The source branch is 12 commits behind the target branch',
+ );
+
+ expect(vm.$el.querySelector('.diverged-commits-count a').textContent).toEqual(
+ '12 commits behind',
+ );
+
+ expect(vm.$el.querySelector('.diverged-commits-count a')).toHaveAttr(
+ 'href',
+ vm.mr.targetBranchPath,
+ );
});
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_icon_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_icon_spec.js
new file mode 100644
index 00000000000..f7c2376eebf
--- /dev/null
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_icon_spec.js
@@ -0,0 +1,30 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import MrWidgetIcon from '~/vue_merge_request_widget/components/mr_widget_icon.vue';
+import Icon from '~/vue_shared/components/icon.vue';
+
+const TEST_ICON = 'commit';
+
+describe('MrWidgetIcon', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ const localVue = createLocalVue();
+
+ wrapper = shallowMount(localVue.extend(MrWidgetIcon), {
+ propsData: {
+ name: TEST_ICON,
+ },
+ sync: false,
+ localVue,
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders icon and container', () => {
+ expect(wrapper.is('.circle-icon-container')).toBe(true);
+ expect(wrapper.find(Icon).props('name')).toEqual(TEST_ICON);
+ });
+});
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_memory_usage_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_memory_usage_spec.js
index 91e81a0675a..4baaea9745a 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_memory_usage_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_memory_usage_spec.js
@@ -128,16 +128,10 @@ describe('MemoryUsage', () => {
describe('computeGraphData', () => {
it('should populate sparkline graph', () => {
vm.computeGraphData(metrics, deployment_time);
- const {
- hasMetrics,
- memoryMetrics,
- deploymentTime,
- memoryFrom,
- memoryTo,
- } = vm;
+ const { hasMetrics, memoryMetrics, deploymentTime, memoryFrom, memoryTo } = vm;
expect(hasMetrics).toBeTruthy();
- expect(memoryMetrics.length > 0).toBeTruthy();
+ expect(memoryMetrics.length).toBeGreaterThan(0);
expect(deploymentTime).toEqual(deployment_time);
expect(memoryFrom).toEqual('9.13');
expect(memoryTo).toEqual('4.28');
@@ -153,18 +147,13 @@ describe('MemoryUsage', () => {
});
it('should load metrics data using MRWidgetService', done => {
- spyOn(MRWidgetService, 'fetchMetrics').and.returnValue(
- returnServicePromise(true),
- );
+ spyOn(MRWidgetService, 'fetchMetrics').and.returnValue(returnServicePromise(true));
spyOn(vm, 'computeGraphData');
vm.loadMetrics();
setTimeout(() => {
expect(MRWidgetService.fetchMetrics).toHaveBeenCalledWith(url);
- expect(vm.computeGraphData).toHaveBeenCalledWith(
- metrics,
- deployment_time,
- );
+ expect(vm.computeGraphData).toHaveBeenCalledWith(metrics, deployment_time);
done();
}, 333);
});
@@ -183,15 +172,11 @@ describe('MemoryUsage', () => {
vm.loadFailed = false;
Vue.nextTick(() => {
- expect(
- el.querySelector('.js-usage-info.usage-info-loading'),
- ).toBeDefined();
- expect(
- el.querySelector('.js-usage-info .usage-info-load-spinner'),
- ).toBeDefined();
- expect(el.querySelector('.js-usage-info').innerText).toContain(
- messages.loadingMetrics,
- );
+ expect(el.querySelector('.js-usage-info.usage-info-loading')).toBeDefined();
+
+ expect(el.querySelector('.js-usage-info .usage-info-load-spinner')).toBeDefined();
+
+ expect(el.querySelector('.js-usage-info').innerText).toContain(messages.loadingMetrics);
done();
});
});
@@ -203,9 +188,7 @@ describe('MemoryUsage', () => {
Vue.nextTick(() => {
expect(el.querySelector('.memory-graph-container')).toBeDefined();
- expect(el.querySelector('.js-usage-info').innerText).toContain(
- messages.hasMetrics,
- );
+ expect(el.querySelector('.js-usage-info').innerText).toContain(messages.hasMetrics);
done();
});
});
@@ -216,12 +199,9 @@ describe('MemoryUsage', () => {
vm.loadFailed = true;
Vue.nextTick(() => {
- expect(
- el.querySelector('.js-usage-info.usage-info-failed'),
- ).toBeDefined();
- expect(el.querySelector('.js-usage-info').innerText).toContain(
- messages.loadFailed,
- );
+ expect(el.querySelector('.js-usage-info.usage-info-failed')).toBeDefined();
+
+ expect(el.querySelector('.js-usage-info').innerText).toContain(messages.loadFailed);
done();
});
});
@@ -232,12 +212,9 @@ describe('MemoryUsage', () => {
vm.loadFailed = false;
Vue.nextTick(() => {
- expect(
- el.querySelector('.js-usage-info.usage-info-unavailable'),
- ).toBeDefined();
- expect(el.querySelector('.js-usage-info').innerText).toContain(
- messages.metricsUnavailable,
- );
+ expect(el.querySelector('.js-usage-info.usage-info-unavailable')).toBeDefined();
+
+ expect(el.querySelector('.js-usage-info').innerText).toContain(messages.metricsUnavailable);
done();
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_merge_help_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_merge_help_spec.js
index 367c499daaf..2c554f3f3ab 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_merge_help_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_merge_help_spec.js
@@ -23,15 +23,23 @@ describe('MRWidgetMergeHelp', () => {
it('renders missing branch information', () => {
expect(
- vm.$el.textContent.trim().replace(/[\r\n]+/g, ' ').replace(/\s\s+/g, ' '),
+ vm.$el.textContent
+ .trim()
+ .replace(/[\r\n]+/g, ' ')
+ .replace(/\s\s+/g, ' '),
).toEqual(
'If the this-is-not-the-branch-you-are-looking-for branch exists in your local repository, you can merge this merge request manually using the command line',
);
});
it('renders button to open help modal', () => {
- expect(vm.$el.querySelector('.js-open-modal-help').getAttribute('data-target')).toEqual('#modal_merge_info');
- expect(vm.$el.querySelector('.js-open-modal-help').getAttribute('data-toggle')).toEqual('modal');
+ expect(vm.$el.querySelector('.js-open-modal-help').getAttribute('data-target')).toEqual(
+ '#modal_merge_info',
+ );
+
+ expect(vm.$el.querySelector('.js-open-modal-help').getAttribute('data-toggle')).toEqual(
+ 'modal',
+ );
});
});
@@ -42,15 +50,21 @@ describe('MRWidgetMergeHelp', () => {
it('renders information about how to merge manually', () => {
expect(
- vm.$el.textContent.trim().replace(/[\r\n]+/g, ' ').replace(/\s\s+/g, ' '),
- ).toEqual(
- 'You can merge this merge request manually using the command line',
- );
+ vm.$el.textContent
+ .trim()
+ .replace(/[\r\n]+/g, ' ')
+ .replace(/\s\s+/g, ' '),
+ ).toEqual('You can merge this merge request manually using the command line');
});
it('renders element to open a modal', () => {
- expect(vm.$el.querySelector('.js-open-modal-help').getAttribute('data-target')).toEqual('#modal_merge_info');
- expect(vm.$el.querySelector('.js-open-modal-help').getAttribute('data-toggle')).toEqual('modal');
+ expect(vm.$el.querySelector('.js-open-modal-help').getAttribute('data-target')).toEqual(
+ '#modal_merge_info',
+ );
+
+ expect(vm.$el.querySelector('.js-open-modal-help').getAttribute('data-toggle')).toEqual(
+ 'modal',
+ );
});
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
new file mode 100644
index 00000000000..e5155573f6f
--- /dev/null
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
@@ -0,0 +1,90 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import MrWidgetPipelineContainer from '~/vue_merge_request_widget/components/mr_widget_pipeline_container.vue';
+import MrWidgetPipeline from '~/vue_merge_request_widget/components/mr_widget_pipeline.vue';
+import { mockStore } from '../mock_data';
+
+describe('MrWidgetPipelineContainer', () => {
+ let wrapper;
+
+ const factory = (props = {}) => {
+ const localVue = createLocalVue();
+
+ wrapper = shallowMount(localVue.extend(MrWidgetPipelineContainer), {
+ propsData: {
+ mr: Object.assign({}, mockStore),
+ ...props,
+ },
+ localVue,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('when pre merge', () => {
+ beforeEach(() => {
+ factory();
+ });
+
+ it('renders pipeline', () => {
+ expect(wrapper.find(MrWidgetPipeline).exists()).toBe(true);
+ expect(wrapper.find(MrWidgetPipeline).props()).toEqual(
+ jasmine.objectContaining({
+ pipeline: mockStore.pipeline,
+ ciStatus: mockStore.ciStatus,
+ hasCi: mockStore.hasCI,
+ sourceBranch: mockStore.sourceBranch,
+ sourceBranchLink: mockStore.sourceBranchLink,
+ }),
+ );
+ });
+
+ it('renders deployments', () => {
+ const expectedProps = mockStore.deployments.map(dep =>
+ jasmine.objectContaining({
+ deployment: dep,
+ showMetrics: false,
+ }),
+ );
+
+ const deployments = wrapper.findAll('.mr-widget-extension .js-pre-deployment');
+
+ expect(deployments.wrappers.map(x => x.props())).toEqual(expectedProps);
+ });
+ });
+
+ describe('when post merge', () => {
+ beforeEach(() => {
+ factory({
+ isPostMerge: true,
+ });
+ });
+
+ it('renders pipeline', () => {
+ expect(wrapper.find(MrWidgetPipeline).exists()).toBe(true);
+ expect(wrapper.find(MrWidgetPipeline).props()).toEqual(
+ jasmine.objectContaining({
+ pipeline: mockStore.mergePipeline,
+ ciStatus: mockStore.ciStatus,
+ hasCi: mockStore.hasCI,
+ sourceBranch: mockStore.targetBranch,
+ sourceBranchLink: mockStore.targetBranch,
+ }),
+ );
+ });
+
+ it('renders deployments', () => {
+ const expectedProps = mockStore.postMergeDeployments.map(dep =>
+ jasmine.objectContaining({
+ deployment: dep,
+ showMetrics: true,
+ }),
+ );
+
+ const deployments = wrapper.findAll('.mr-widget-extension .js-post-deployment');
+
+ expect(deployments.wrappers.map(x => x.props())).toEqual(expectedProps);
+ });
+ });
+});
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
index ea8007d2029..d905bbe4040 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
@@ -22,6 +22,7 @@ describe('MRWidgetPipeline', () => {
pipeline: mockData.pipeline,
ciStatus: 'success',
hasCi: true,
+ troubleshootingDocsPath: 'help',
});
expect(vm.hasPipeline).toEqual(true);
@@ -30,6 +31,7 @@ describe('MRWidgetPipeline', () => {
it('should return false when there is no pipeline', () => {
vm = mountComponent(Component, {
pipeline: {},
+ troubleshootingDocsPath: 'help',
});
expect(vm.hasPipeline).toEqual(false);
@@ -42,6 +44,7 @@ describe('MRWidgetPipeline', () => {
pipeline: mockData.pipeline,
hasCi: true,
ciStatus: 'success',
+ troubleshootingDocsPath: 'help',
});
expect(vm.hasCIError).toEqual(false);
@@ -52,6 +55,7 @@ describe('MRWidgetPipeline', () => {
pipeline: mockData.pipeline,
hasCi: true,
ciStatus: null,
+ troubleshootingDocsPath: 'help',
});
expect(vm.hasCIError).toEqual(true);
@@ -65,11 +69,12 @@ describe('MRWidgetPipeline', () => {
pipeline: mockData.pipeline,
hasCi: true,
ciStatus: null,
+ troubleshootingDocsPath: 'help',
});
- expect(
- vm.$el.querySelector('.media-body').textContent.trim(),
- ).toEqual('Could not connect to the CI server. Please check your settings and try again');
+ expect(vm.$el.querySelector('.media-body').textContent.trim()).toContain(
+ 'Could not retrieve the pipeline status. For troubleshooting steps, read the documentation.',
+ );
});
describe('with a pipeline', () => {
@@ -78,38 +83,41 @@ describe('MRWidgetPipeline', () => {
pipeline: mockData.pipeline,
hasCi: true,
ciStatus: 'success',
+ troubleshootingDocsPath: 'help',
});
});
it('should render pipeline ID', () => {
- expect(
- vm.$el.querySelector('.pipeline-id').textContent.trim(),
- ).toEqual(`#${mockData.pipeline.id}`);
+ expect(vm.$el.querySelector('.pipeline-id').textContent.trim()).toEqual(
+ `#${mockData.pipeline.id}`,
+ );
});
it('should render pipeline status and commit id', () => {
- expect(
- vm.$el.querySelector('.media-body').textContent.trim(),
- ).toContain(mockData.pipeline.details.status.label);
+ expect(vm.$el.querySelector('.media-body').textContent.trim()).toContain(
+ mockData.pipeline.details.status.label,
+ );
- expect(
- vm.$el.querySelector('.js-commit-link').textContent.trim(),
- ).toEqual(mockData.pipeline.commit.short_id);
+ expect(vm.$el.querySelector('.js-commit-link').textContent.trim()).toEqual(
+ mockData.pipeline.commit.short_id,
+ );
- expect(
- vm.$el.querySelector('.js-commit-link').getAttribute('href'),
- ).toEqual(mockData.pipeline.commit.commit_path);
+ expect(vm.$el.querySelector('.js-commit-link').getAttribute('href')).toEqual(
+ mockData.pipeline.commit.commit_path,
+ );
});
it('should render pipeline graph', () => {
expect(vm.$el.querySelector('.mr-widget-pipeline-graph')).toBeDefined();
- expect(vm.$el.querySelectorAll('.stage-container').length).toEqual(mockData.pipeline.details.stages.length);
+ expect(vm.$el.querySelectorAll('.stage-container').length).toEqual(
+ mockData.pipeline.details.stages.length,
+ );
});
it('should render coverage information', () => {
- expect(
- vm.$el.querySelector('.media-body').textContent,
- ).toContain(`Coverage ${mockData.pipeline.coverage}`);
+ expect(vm.$el.querySelector('.media-body').textContent).toContain(
+ `Coverage ${mockData.pipeline.coverage}`,
+ );
});
});
@@ -122,34 +130,35 @@ describe('MRWidgetPipeline', () => {
pipeline: mockCopy.pipeline,
hasCi: true,
ciStatus: 'success',
+ troubleshootingDocsPath: 'help',
});
});
it('should render pipeline ID', () => {
- expect(
- vm.$el.querySelector('.pipeline-id').textContent.trim(),
- ).toEqual(`#${mockData.pipeline.id}`);
+ expect(vm.$el.querySelector('.pipeline-id').textContent.trim()).toEqual(
+ `#${mockData.pipeline.id}`,
+ );
});
it('should render pipeline status', () => {
- expect(
- vm.$el.querySelector('.media-body').textContent.trim(),
- ).toContain(mockData.pipeline.details.status.label);
+ expect(vm.$el.querySelector('.media-body').textContent.trim()).toContain(
+ mockData.pipeline.details.status.label,
+ );
- expect(
- vm.$el.querySelector('.js-commit-link'),
- ).toBeNull();
+ expect(vm.$el.querySelector('.js-commit-link')).toBeNull();
});
it('should render pipeline graph', () => {
expect(vm.$el.querySelector('.mr-widget-pipeline-graph')).toBeDefined();
- expect(vm.$el.querySelectorAll('.stage-container').length).toEqual(mockData.pipeline.details.stages.length);
+ expect(vm.$el.querySelectorAll('.stage-container').length).toEqual(
+ mockData.pipeline.details.stages.length,
+ );
});
it('should render coverage information', () => {
- expect(
- vm.$el.querySelector('.media-body').textContent,
- ).toContain(`Coverage ${mockData.pipeline.coverage}`);
+ expect(vm.$el.querySelector('.media-body').textContent).toContain(
+ `Coverage ${mockData.pipeline.coverage}`,
+ );
});
});
@@ -162,11 +171,10 @@ describe('MRWidgetPipeline', () => {
pipeline: mockCopy.pipeline,
hasCi: true,
ciStatus: 'success',
+ troubleshootingDocsPath: 'help',
});
- expect(
- vm.$el.querySelector('.media-body').textContent,
- ).not.toContain('Coverage');
+ expect(vm.$el.querySelector('.media-body').textContent).not.toContain('Coverage');
});
});
@@ -179,6 +187,7 @@ describe('MRWidgetPipeline', () => {
pipeline: mockCopy.pipeline,
hasCi: true,
ciStatus: 'success',
+ troubleshootingDocsPath: 'help',
});
expect(vm.$el.querySelector('.js-mini-pipeline-graph')).toEqual(null);
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_rebase_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_rebase_spec.js
index b453d180a40..300133dc602 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_rebase_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_rebase_spec.js
@@ -39,13 +39,19 @@ describe('Merge request widget rebase component', () => {
});
it('it should render rebase button and warning message', () => {
- const text = vm.$el.querySelector('.rebase-state-find-class-convention span').textContent.trim();
+ const text = vm.$el
+ .querySelector('.rebase-state-find-class-convention span')
+ .textContent.trim();
+
expect(text).toContain('Fast-forward merge is not possible.');
- expect(text).toContain('Rebase the source branch onto the target branch or merge target');
+ expect(text.replace(/\s\s+/g, ' ')).toContain(
+ 'Rebase the source branch onto the target branch or merge target',
+ );
+
expect(text).toContain('branch into source branch to allow this merge request to be merged.');
});
- it('it should render error message when it fails', (done) => {
+ it('it should render error message when it fails', done => {
vm.rebasingError = 'Something went wrong!';
Vue.nextTick(() => {
@@ -68,17 +74,19 @@ describe('Merge request widget rebase component', () => {
service: {},
});
- const text = vm.$el.querySelector('.rebase-state-find-class-convention span').textContent.trim();
+ const text = vm.$el
+ .querySelector('.rebase-state-find-class-convention span')
+ .textContent.trim();
expect(text).toContain('Fast-forward merge is not possible.');
expect(text).toContain('Rebase the source branch onto');
expect(text).toContain('foo');
- expect(text).toContain('to allow this merge request to be merged.');
+ expect(text.replace(/\s\s+/g, ' ')).toContain('to allow this merge request to be merged.');
});
});
describe('methods', () => {
- it('checkRebaseStatus', (done) => {
+ it('checkRebaseStatus', done => {
spyOn(eventHub, '$emit');
vm = mountComponent(Component, {
mr: {},
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_related_links_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_related_links_spec.js
index 5de6ac4079d..7a5d0efdea5 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_related_links_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_related_links_spec.js
@@ -5,7 +5,7 @@ import mountComponent from 'spec/helpers/vue_mount_component_helper';
describe('MRWidgetRelatedLinks', () => {
let vm;
- const createComponent = (data) => {
+ const createComponent = data => {
const Component = Vue.extend(relatedLinksComponent);
return mountComponent(Component, data);
@@ -19,16 +19,19 @@ describe('MRWidgetRelatedLinks', () => {
describe('closesText', () => {
it('returns Closes text for open merge request', () => {
vm = createComponent({ state: 'open', relatedLinks: {} });
+
expect(vm.closesText).toEqual('Closes');
});
it('returns correct text for closed merge request', () => {
vm = createComponent({ state: 'closed', relatedLinks: {} });
+
expect(vm.closesText).toEqual('Did not close');
});
it('returns correct tense for merged request', () => {
vm = createComponent({ state: 'merged', relatedLinks: {} });
+
expect(vm.closesText).toEqual('Closed');
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_status_icon_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_status_icon_spec.js
index 0b25500caf4..a0a336ae604 100644
--- a/spec/javascripts/vue_mr_widget/components/mr_widget_status_icon_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_status_icon_spec.js
@@ -17,6 +17,7 @@ describe('MR widget status icon component', () => {
describe('while loading', () => {
it('renders loading icon', () => {
vm = mountComponent(Component, { status: 'loading' });
+
expect(vm.$el.querySelector('.mr-widget-icon i').classList).toContain('fa-spinner');
});
});
@@ -24,6 +25,7 @@ describe('MR widget status icon component', () => {
describe('with status icon', () => {
it('renders ci status icon', () => {
vm = mountComponent(Component, { status: 'failed' });
+
expect(vm.$el.querySelector('.js-ci-status-icon-failed')).not.toBeNull();
});
});
@@ -31,6 +33,7 @@ describe('MR widget status icon component', () => {
describe('with disabled button', () => {
it('renders a disabled button', () => {
vm = mountComponent(Component, { status: 'failed', showDisabledButton: true });
+
expect(vm.$el.querySelector('.js-disabled-merge-button').textContent.trim()).toEqual('Merge');
});
});
@@ -38,6 +41,7 @@ describe('MR widget status icon component', () => {
describe('without disabled button', () => {
it('does not render a disabled button', () => {
vm = mountComponent(Component, { status: 'failed' });
+
expect(vm.$el.querySelector('.js-disabled-merge-button')).toBeNull();
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/review_app_link_spec.js b/spec/javascripts/vue_mr_widget/components/review_app_link_spec.js
new file mode 100644
index 00000000000..68a65bd21c6
--- /dev/null
+++ b/spec/javascripts/vue_mr_widget/components/review_app_link_spec.js
@@ -0,0 +1,38 @@
+import Vue from 'vue';
+import component from '~/vue_merge_request_widget/components/review_app_link.vue';
+import mountComponent from '../../helpers/vue_mount_component_helper';
+
+describe('review app link', () => {
+ const Component = Vue.extend(component);
+ const props = {
+ link: '/review',
+ cssClass: 'js-link',
+ };
+ let vm;
+ let el;
+
+ beforeEach(() => {
+ vm = mountComponent(Component, props);
+ el = vm.$el;
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('renders provided link as href attribute', () => {
+ expect(el.getAttribute('href')).toEqual(props.link);
+ });
+
+ it('renders provided cssClass as class attribute', () => {
+ expect(el.getAttribute('class')).toEqual(props.cssClass);
+ });
+
+ it('renders View app text', () => {
+ expect(el.textContent.trim()).toEqual('View app');
+ });
+
+ it('renders svg icon', () => {
+ expect(el.querySelector('svg')).not.toBeNull();
+ });
+});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_archived_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_archived_spec.js
index e818f87b4c8..b90f5881a4d 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_archived_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_archived_spec.js
@@ -24,8 +24,8 @@ describe('MRWidgetArchived', () => {
});
it('renders information', () => {
- expect(
- vm.$el.querySelector('.bold').textContent.trim(),
- ).toEqual('This project is archived, write access has been disabled');
+ expect(vm.$el.querySelector('.bold').textContent.trim()).toEqual(
+ 'This project is archived, write access has been disabled',
+ );
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js
index d069dc3fcc6..eb4fa0df727 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_auto_merge_failed_spec.js
@@ -30,7 +30,7 @@ describe('MRWidgetAutoMergeFailed', () => {
expect(vm.$el.querySelector('button').textContent.trim()).toEqual('Refresh');
});
- it('emits event and shows loading icon when button is clicked', (done) => {
+ it('emits event and shows loading icon when button is clicked', done => {
spyOn(eventHub, '$emit');
vm.$el.querySelector('button').click();
@@ -38,9 +38,7 @@ describe('MRWidgetAutoMergeFailed', () => {
Vue.nextTick(() => {
expect(vm.$el.querySelector('button').getAttribute('disabled')).toEqual('disabled');
- expect(
- vm.$el.querySelector('button i').classList,
- ).toContain('fa-spinner');
+ expect(vm.$el.querySelector('button i').classList).toContain('fa-spinner');
done();
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_checking_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_checking_spec.js
index 658612aad3c..7da27bb8890 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_checking_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_checking_spec.js
@@ -24,6 +24,8 @@ describe('MRWidgetChecking', () => {
});
it('renders information about merging', () => {
- expect(vm.$el.querySelector('.media-body').textContent.trim()).toEqual('Checking ability to merge automatically');
+ expect(vm.$el.querySelector('.media-body').textContent.trim()).toEqual(
+ 'Checking ability to merge automatically',
+ );
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_closed_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_closed_spec.js
index 0e3c134d3ac..9523e7d5474 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_closed_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_closed_spec.js
@@ -7,23 +7,26 @@ describe('MRWidgetClosed', () => {
beforeEach(() => {
const Component = Vue.extend(closedComponent);
- vm = mountComponent(Component, { mr: {
- metrics: {
- mergedBy: {},
- closedBy: {
- name: 'Administrator',
- username: 'root',
- webUrl: 'http://localhost:3000/root',
- avatarUrl: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ vm = mountComponent(Component, {
+ mr: {
+ metrics: {
+ mergedBy: {},
+ closedBy: {
+ name: 'Administrator',
+ username: 'root',
+ webUrl: 'http://localhost:3000/root',
+ avatarUrl:
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ },
+ mergedAt: 'Jan 24, 2018 1:02pm GMT+0000',
+ closedAt: 'Jan 24, 2018 1:02pm GMT+0000',
+ readableMergedAt: '',
+ readableClosedAt: 'less than a minute ago',
},
- mergedAt: 'Jan 24, 2018 1:02pm GMT+0000',
- closedAt: 'Jan 24, 2018 1:02pm GMT+0000',
- readableMergedAt: '',
- readableClosedAt: 'less than a minute ago',
+ targetBranchPath: '/twitter/flight/commits/so_long_jquery',
+ targetBranch: 'so_long_jquery',
},
- targetBranchPath: '/twitter/flight/commits/so_long_jquery',
- targetBranch: 'so_long_jquery',
- } });
+ });
});
afterEach(() => {
@@ -36,23 +39,31 @@ describe('MRWidgetClosed', () => {
it('renders closed by information with author and time', () => {
expect(
- vm.$el.querySelector('.js-mr-widget-author').textContent.trim().replace(/\s\s+/g, ' '),
- ).toContain(
- 'Closed by Administrator less than a minute ago',
- );
+ vm.$el
+ .querySelector('.js-mr-widget-author')
+ .textContent.trim()
+ .replace(/\s\s+/g, ' '),
+ ).toContain('Closed by Administrator less than a minute ago');
});
it('links to the user that closed the MR', () => {
- expect(vm.$el.querySelector('.author-link').getAttribute('href')).toEqual('http://localhost:3000/root');
+ expect(vm.$el.querySelector('.author-link').getAttribute('href')).toEqual(
+ 'http://localhost:3000/root',
+ );
});
it('renders information about the changes not being merged', () => {
expect(
- vm.$el.querySelector('.mr-info-list').textContent.trim().replace(/\s\s+/g, ' '),
+ vm.$el
+ .querySelector('.mr-info-list')
+ .textContent.trim()
+ .replace(/\s\s+/g, ' '),
).toContain('The changes were not merged into so_long_jquery');
});
it('renders link for target branch', () => {
- expect(vm.$el.querySelector('.label-branch').getAttribute('href')).toEqual('/twitter/flight/commits/so_long_jquery');
+ expect(vm.$el.querySelector('.label-branch').getAttribute('href')).toEqual(
+ '/twitter/flight/commits/so_long_jquery',
+ );
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
index 3d05dbfa305..f9cd5c8bd3c 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
@@ -59,7 +59,9 @@ describe('MRWidgetConflicts', () => {
});
it('should show proper message', () => {
- expect(vm.$el.textContent.trim().replace(/\s\s+/g, ' ')).toContain('ask someone with write access');
+ expect(vm.$el.textContent.trim().replace(/\s\s+/g, ' ')).toContain(
+ 'ask someone with write access',
+ );
});
it('should not have action buttons', () => {
@@ -79,9 +81,9 @@ describe('MRWidgetConflicts', () => {
});
it('should tell you to rebase locally', () => {
- expect(
- removeBreakLine(vm.$el.textContent).trim(),
- ).toContain('Fast-forward merge is not possible. To merge this request, first rebase locally.');
+ expect(removeBreakLine(vm.$el.textContent).trim()).toContain(
+ 'Fast-forward merge is not possible. To merge this request, first rebase locally.',
+ );
});
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js
index 8de99fd3c96..3229ddd5e27 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_failed_to_merge_spec.js
@@ -43,6 +43,7 @@ describe('MRWidgetFailedToMerge', () => {
expect(vm.timerText).toEqual('Refreshing in 10 seconds to show the updated status...');
vm.timer = 1;
+
expect(vm.timerText).toEqual('Refreshing in a second to show the updated status...');
});
});
@@ -73,6 +74,7 @@ describe('MRWidgetFailedToMerge', () => {
expect(vm.isRefreshing).toEqual(false);
vm.refresh();
+
expect(vm.isRefreshing).toEqual(true);
expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
expect(eventHub.$emit).toHaveBeenCalledWith('EnablePolling');
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js
index d47815a5b5a..d46ad0acc9b 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merge_when_pipeline_succeeds_spec.js
@@ -42,22 +42,27 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
it('should return false when user id is not the same with who set the MWPS', () => {
vm.mr.mergeUserId = 2;
+
expect(vm.canRemoveSourceBranch).toBeFalsy();
vm.mr.currentUserId = 2;
+
expect(vm.canRemoveSourceBranch).toBeTruthy();
vm.mr.currentUserId = 3;
+
expect(vm.canRemoveSourceBranch).toBeFalsy();
});
it('should return false when shouldRemoveSourceBranch set to false', () => {
vm.mr.shouldRemoveSourceBranch = true;
+
expect(vm.canRemoveSourceBranch).toBeFalsy();
});
it('should return false if user is not able to remove the source branch', () => {
vm.mr.canRemoveSourceBranch = false;
+
expect(vm.canRemoveSourceBranch).toBeFalsy();
});
});
@@ -65,15 +70,17 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
describe('methods', () => {
describe('cancelAutomaticMerge', () => {
- it('should set flag and call service then tell main component to update the widget with data', (done) => {
+ it('should set flag and call service then tell main component to update the widget with data', done => {
const mrObj = {
is_new_mr_data: true,
};
- spyOn(vm.service, 'cancelAutomaticMerge').and.returnValue(new Promise((resolve) => {
- resolve({
- data: mrObj,
- });
- }));
+ spyOn(vm.service, 'cancelAutomaticMerge').and.returnValue(
+ new Promise(resolve => {
+ resolve({
+ data: mrObj,
+ });
+ }),
+ );
vm.cancelAutomaticMerge();
setTimeout(() => {
@@ -85,12 +92,14 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
});
describe('removeSourceBranch', () => {
- it('should set flag and call service then request main component to update the widget', (done) => {
- spyOn(vm.service, 'merge').and.returnValue(Promise.resolve({
- data: {
- status: 'merge_when_pipeline_succeeds',
- },
- }));
+ it('should set flag and call service then request main component to update the widget', done => {
+ spyOn(vm.service, 'merge').and.returnValue(
+ Promise.resolve({
+ data: {
+ status: 'merge_when_pipeline_succeeds',
+ },
+ }),
+ );
vm.removeSourceBranch();
setTimeout(() => {
@@ -113,13 +122,19 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
expect(vm.$el.innerText).toContain('The changes will be merged into');
expect(vm.$el.innerText).toContain(targetBranch);
expect(vm.$el.innerText).toContain('The source branch will not be removed');
- expect(vm.$el.querySelector('.js-cancel-auto-merge').innerText).toContain('Cancel automatic merge');
+ expect(vm.$el.querySelector('.js-cancel-auto-merge').innerText).toContain(
+ 'Cancel automatic merge',
+ );
+
expect(vm.$el.querySelector('.js-cancel-auto-merge').getAttribute('disabled')).toBeFalsy();
- expect(vm.$el.querySelector('.js-remove-source-branch').innerText).toContain('Remove source branch');
+ expect(vm.$el.querySelector('.js-remove-source-branch').innerText).toContain(
+ 'Remove source branch',
+ );
+
expect(vm.$el.querySelector('.js-remove-source-branch').getAttribute('disabled')).toBeFalsy();
});
- it('should disable cancel auto merge button when the action is in progress', (done) => {
+ it('should disable cancel auto merge button when the action is in progress', done => {
vm.isCancellingAutoMerge = true;
Vue.nextTick(() => {
@@ -128,18 +143,19 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
});
});
- it('should show source branch will be removed text when it source branch set to remove', (done) => {
+ it('should show source branch will be removed text when it source branch set to remove', done => {
vm.mr.shouldRemoveSourceBranch = true;
Vue.nextTick(() => {
const normalizedText = vm.$el.innerText.replace(/\s+/g, ' ');
+
expect(normalizedText).toContain('The source branch will be removed');
expect(normalizedText).not.toContain('The source branch will not be removed');
done();
});
});
- it('should not show remove source branch button when user not able to remove source branch', (done) => {
+ it('should not show remove source branch button when user not able to remove source branch', done => {
vm.mr.currentUserId = 4;
Vue.nextTick(() => {
@@ -148,11 +164,13 @@ describe('MRWidgetMergeWhenPipelineSucceeds', () => {
});
});
- it('should disable remove source branch button when the action is in progress', (done) => {
+ it('should disable remove source branch button when the action is in progress', done => {
vm.isRemovingSourceBranch = true;
Vue.nextTick(() => {
- expect(vm.$el.querySelector('.js-remove-source-branch').getAttribute('disabled')).toBeTruthy();
+ expect(
+ vm.$el.querySelector('.js-remove-source-branch').getAttribute('disabled'),
+ ).toBeTruthy();
done();
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js
index efa5c878678..da5cb752c6f 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js
@@ -30,7 +30,8 @@ describe('MRWidgetMerged', () => {
name: 'Administrator',
username: 'root',
webUrl: 'http://localhost:3000/root',
- avatarUrl: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
+ avatarUrl:
+ 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
},
mergedAt: 'Jan 24, 2018 1:02pm GMT+0000',
readableMergedAt: '',
@@ -41,7 +42,8 @@ describe('MRWidgetMerged', () => {
updatedAt: 'mergedUpdatedAt',
shortMergeCommitSha: '958c0475',
mergeCommitSha: '958c047516e182dfc52317f721f696e8a1ee85ed',
- mergeCommitPath: 'http://localhost:3000/root/nautilus/commit/f7ce827c314c9340b075657fd61c789fb01cf74d',
+ mergeCommitPath:
+ 'http://localhost:3000/root/nautilus/commit/f7ce827c314c9340b075657fd61c789fb01cf74d',
sourceBranch: 'bar',
targetBranch,
};
@@ -63,23 +65,27 @@ describe('MRWidgetMerged', () => {
describe('shouldShowRemoveSourceBranch', () => {
it('returns true when sourceBranchRemoved is false', () => {
vm.mr.sourceBranchRemoved = false;
+
expect(vm.shouldShowRemoveSourceBranch).toEqual(true);
});
- it('returns false wehn sourceBranchRemoved is true', () => {
+ it('returns false when sourceBranchRemoved is true', () => {
vm.mr.sourceBranchRemoved = true;
+
expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
});
it('returns false when canRemoveSourceBranch is false', () => {
vm.mr.sourceBranchRemoved = false;
vm.mr.canRemoveSourceBranch = false;
+
expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
});
it('returns false when is making request', () => {
vm.mr.canRemoveSourceBranch = true;
vm.isMakingRequest = true;
+
expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
});
@@ -87,6 +93,7 @@ describe('MRWidgetMerged', () => {
vm.mr.isRemovingSourceBranch = true;
vm.mr.canRemoveSourceBranch = true;
vm.isMakingRequest = true;
+
expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
});
});
@@ -94,17 +101,21 @@ describe('MRWidgetMerged', () => {
describe('shouldShowSourceBranchRemoving', () => {
it('should correct value when fields changed', () => {
vm.mr.sourceBranchRemoved = false;
+
expect(vm.shouldShowSourceBranchRemoving).toEqual(false);
vm.mr.sourceBranchRemoved = true;
+
expect(vm.shouldShowRemoveSourceBranch).toEqual(false);
vm.mr.sourceBranchRemoved = false;
vm.isMakingRequest = true;
+
expect(vm.shouldShowSourceBranchRemoving).toEqual(true);
vm.isMakingRequest = false;
vm.mr.isRemovingSourceBranch = true;
+
expect(vm.shouldShowSourceBranchRemoving).toEqual(true);
});
});
@@ -112,18 +123,21 @@ describe('MRWidgetMerged', () => {
describe('methods', () => {
describe('removeSourceBranch', () => {
- it('should set flag and call service then request main component to update the widget', (done) => {
- spyOn(vm.service, 'removeSourceBranch').and.returnValue(new Promise((resolve) => {
- resolve({
- data: {
- message: 'Branch was removed',
- },
- });
- }));
+ it('should set flag and call service then request main component to update the widget', done => {
+ spyOn(vm.service, 'removeSourceBranch').and.returnValue(
+ new Promise(resolve => {
+ resolve({
+ data: {
+ message: 'Branch was removed',
+ },
+ });
+ }),
+ );
vm.removeSourceBranch();
setTimeout(() => {
const args = eventHub.$emit.calls.argsFor(0);
+
expect(vm.isMakingRequest).toEqual(true);
expect(args[0]).toEqual('MRWidgetUpdateRequested');
expect(args[1]).not.toThrow();
@@ -154,7 +168,19 @@ describe('MRWidgetMerged', () => {
it('shows button to copy commit SHA to clipboard', () => {
expect(selectors.copyMergeShaButton).toExist();
- expect(selectors.copyMergeShaButton.getAttribute('data-clipboard-text')).toBe(vm.mr.mergeCommitSha);
+ expect(selectors.copyMergeShaButton.getAttribute('data-clipboard-text')).toBe(
+ vm.mr.mergeCommitSha,
+ );
+ });
+
+ it('hides button to copy commit SHA if SHA does not exist', done => {
+ vm.mr.mergeCommitSha = null;
+
+ Vue.nextTick(() => {
+ expect(selectors.copyMergeShaButton).not.toExist();
+ expect(vm.$el.querySelector('.mr-info-list').innerText).not.toContain('with');
+ done();
+ });
});
it('shows merge commit SHA link', () => {
@@ -163,7 +189,7 @@ describe('MRWidgetMerged', () => {
expect(selectors.mergeCommitShaLink.href).toBe(vm.mr.mergeCommitPath);
});
- it('should not show source branch removed text', (done) => {
+ it('should not show source branch removed text', done => {
vm.mr.sourceBranchRemoved = false;
Vue.nextTick(() => {
@@ -173,7 +199,7 @@ describe('MRWidgetMerged', () => {
});
});
- it('should show source branch removing text', (done) => {
+ it('should show source branch removing text', done => {
vm.mr.isRemovingSourceBranch = true;
vm.mr.sourceBranchRemoved = false;
@@ -186,8 +212,8 @@ describe('MRWidgetMerged', () => {
});
it('should use mergedEvent mergedAt as tooltip title', () => {
- expect(
- vm.$el.querySelector('time').getAttribute('data-original-title'),
- ).toBe('Jan 24, 2018 1:02pm GMT+0000');
+ expect(vm.$el.querySelector('time').getAttribute('data-original-title')).toBe(
+ 'Jan 24, 2018 1:02pm GMT+0000',
+ );
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merging_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merging_spec.js
index d2d219e4bdb..57773d1648a 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merging_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merging_spec.js
@@ -7,10 +7,12 @@ describe('MRWidgetMerging', () => {
beforeEach(() => {
const Component = Vue.extend(mergingComponent);
- vm = mountComponent(Component, { mr: {
- targetBranchPath: '/branch-path',
- targetBranch: 'branch',
- } });
+ vm = mountComponent(Component, {
+ mr: {
+ targetBranchPath: '/branch-path',
+ targetBranch: 'branch',
+ },
+ });
});
afterEach(() => {
@@ -19,16 +21,23 @@ describe('MRWidgetMerging', () => {
it('renders information about merge request being merged', () => {
expect(
- vm.$el.querySelector('.media-body').textContent.trim().replace(/\s\s+/g, ' ').replace(/[\r\n]+/g, ' '),
+ vm.$el
+ .querySelector('.media-body')
+ .textContent.trim()
+ .replace(/\s\s+/g, ' ')
+ .replace(/[\r\n]+/g, ' '),
).toContain('This merge request is in the process of being merged');
});
it('renders branch information', () => {
expect(
- vm.$el.querySelector('.mr-info-list').textContent.trim().replace(/\s\s+/g, ' ').replace(/[\r\n]+/g, ' '),
+ vm.$el
+ .querySelector('.mr-info-list')
+ .textContent.trim()
+ .replace(/\s\s+/g, ' ')
+ .replace(/[\r\n]+/g, ' '),
).toEqual('The changes will be merged into branch');
- expect(
- vm.$el.querySelector('a').getAttribute('href'),
- ).toEqual('/branch-path');
+
+ expect(vm.$el.querySelector('a').getAttribute('href')).toEqual('/branch-path');
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js
index 34f76b39b28..5fd8093bf5c 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_missing_branch_spec.js
@@ -20,6 +20,7 @@ describe('MRWidgetMissingBranch', () => {
expect(vm.missingBranchName).toEqual('source');
vm.mr.sourceBranchRemoved = false;
+
expect(vm.missingBranchName).toEqual('target');
});
});
@@ -32,7 +33,7 @@ describe('MRWidgetMissingBranch', () => {
expect(el.classList.contains('mr-widget-body')).toBeTruthy();
expect(el.querySelector('button').getAttribute('disabled')).toBeTruthy();
- expect(content).toContain('source branch does not exist.');
+ expect(content.replace(/\s\s+/g, ' ')).toContain('source branch does not exist.');
expect(content).toContain('Please restore it or use a different source branch');
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_not_allowed_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_not_allowed_spec.js
index 9f8b96c118b..6b95ca3460b 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_not_allowed_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_not_allowed_spec.js
@@ -19,6 +19,8 @@ describe('MRWidgetNotAllowed', () => {
it('renders informative text', () => {
expect(vm.$el.innerText).toContain('Ready to be merged automatically.');
- expect(vm.$el.innerText).toContain('Ask someone with write access to this repository to merge this request');
+ expect(vm.$el.innerText).toContain(
+ 'Ask someone with write access to this repository to merge this request',
+ );
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_nothing_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_nothing_to_merge_spec.js
index 2a762c9336e..bd0bd36ebc2 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_nothing_to_merge_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_nothing_to_merge_spec.js
@@ -15,8 +15,13 @@ describe('NothingToMerge', () => {
it('should have correct elements', () => {
expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
expect(vm.$el.querySelector('a').href).toContain(newBlobPath);
- expect(vm.$el.innerText).toContain('Currently there are no changes in this merge request\'s source branch');
- expect(vm.$el.innerText).toContain('Please push new commits or use a different branch.');
+ expect(vm.$el.innerText).toContain(
+ "Currently there are no changes in this merge request's source branch",
+ );
+
+ expect(vm.$el.innerText.replace(/\s\s+/g, ' ')).toContain(
+ 'Please push new commits or use a different branch.',
+ );
});
it('should not show new blob link if there is no link available', () => {
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js
index ab096a56918..477041fa383 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_blocked_spec.js
@@ -19,8 +19,8 @@ describe('MRWidgetPipelineBlocked', () => {
});
it('renders information text', () => {
- expect(
- removeBreakLine(vm.$el.textContent).trim(),
- ).toContain('Pipeline blocked. The pipeline for this merge request requires a manual action to proceed');
+ expect(removeBreakLine(vm.$el.textContent).trim()).toContain(
+ 'Pipeline blocked. The pipeline for this merge request requires a manual action to proceed',
+ );
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js
index 5573d7c5c93..f7523a01963 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_pipeline_failed_spec.js
@@ -11,9 +11,9 @@ describe('PipelineFailed', () => {
it('should have correct elements', () => {
expect(vm.$el.classList.contains('mr-widget-body')).toBeTruthy();
expect(vm.$el.querySelector('button').getAttribute('disabled')).toBeTruthy();
- expect(
- removeBreakLine(vm.$el.innerText).trim(),
- ).toContain('The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure');
+ expect(removeBreakLine(vm.$el.innerText).trim()).toContain(
+ 'The pipeline for this merge request failed. Please retry the job or push a new commit to fix the failure',
+ );
});
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
index 81c16593eb4..2119a3b927a 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
@@ -76,11 +76,13 @@ describe('ReadyToMerge', () => {
describe('shouldShowMergeWhenPipelineSucceedsText', () => {
it('should return true with active pipeline', () => {
vm.mr.isPipelineActive = true;
+
expect(vm.shouldShowMergeWhenPipelineSucceedsText).toBeTruthy();
});
it('should return false with inactive pipeline', () => {
vm.mr.isPipelineActive = false;
+
expect(vm.shouldShowMergeWhenPipelineSucceedsText).toBeFalsy();
});
});
@@ -95,6 +97,7 @@ describe('ReadyToMerge', () => {
it('should return message without description', () => {
vm.useCommitMessageWithDescription = true;
+
expect(vm.commitMessageLinkTitle).toEqual(withoutDesc);
});
});
@@ -102,11 +105,13 @@ describe('ReadyToMerge', () => {
describe('status', () => {
it('defaults to success', () => {
vm.mr.pipeline = true;
+
expect(vm.status).toEqual('success');
});
it('returns failed when MR has CI but also has an unknown status', () => {
vm.mr.hasCI = true;
+
expect(vm.status).toEqual('failed');
});
@@ -117,12 +122,14 @@ describe('ReadyToMerge', () => {
it('returns pending when pipeline is active', () => {
vm.mr.pipeline = {};
vm.mr.isPipelineActive = true;
+
expect(vm.status).toEqual('pending');
});
it('returns failed when pipeline is failed', () => {
vm.mr.pipeline = {};
vm.mr.isPipelineFailed = true;
+
expect(vm.status).toEqual('failed');
});
});
@@ -138,17 +145,20 @@ describe('ReadyToMerge', () => {
it('returns success class for success status', () => {
vm.mr.pipeline = true;
+
expect(vm.mergeButtonClass).toEqual(defaultClass);
});
it('returns info class for pending status', () => {
vm.mr.pipeline = {};
vm.mr.isPipelineActive = true;
+
expect(vm.mergeButtonClass).toEqual(inActionClass);
});
it('returns failed class for failed status', () => {
vm.mr.hasCI = true;
+
expect(vm.mergeButtonClass).toEqual(failedClass);
});
});
@@ -160,22 +170,26 @@ describe('ReadyToMerge', () => {
it('shows tick for success status', () => {
vm.mr.pipeline = true;
+
expect(vm.iconClass).toEqual('success');
});
it('shows tick for pending status', () => {
vm.mr.pipeline = {};
vm.mr.isPipelineActive = true;
+
expect(vm.iconClass).toEqual('success');
});
it('shows warning icon for failed status', () => {
vm.mr.hasCI = true;
+
expect(vm.iconClass).toEqual('warning');
});
it('shows warning icon for merge not allowed', () => {
vm.mr.hasCI = true;
+
expect(vm.iconClass).toEqual('warning');
});
});
@@ -187,12 +201,14 @@ describe('ReadyToMerge', () => {
it('should return Merge in progress', () => {
vm.isMergingImmediately = true;
+
expect(vm.mergeButtonText).toEqual('Merge in progress');
});
it('should return Merge when pipeline succeeds', () => {
vm.isMergingImmediately = false;
vm.mr.isPipelineActive = true;
+
expect(vm.mergeButtonText).toEqual('Merge when pipeline succeeds');
});
});
@@ -204,12 +220,14 @@ describe('ReadyToMerge', () => {
it('should return true when pipeline active', () => {
vm.mr.isPipelineActive = true;
+
expect(vm.shouldShowMergeOptionsDropdown).toBeTruthy();
});
it('should return false when pipeline active but only merge when pipeline succeeds set in project options', () => {
vm.mr.isPipelineActive = true;
vm.mr.onlyAllowMergeIfPipelineSucceeds = true;
+
expect(vm.shouldShowMergeOptionsDropdown).toBeFalsy();
});
});
@@ -217,24 +235,28 @@ describe('ReadyToMerge', () => {
describe('isMergeButtonDisabled', () => {
it('should return false with initial data', () => {
vm.mr.isMergeAllowed = true;
+
expect(vm.isMergeButtonDisabled).toBeFalsy();
});
it('should return true when there is no commit message', () => {
vm.mr.isMergeAllowed = true;
vm.commitMessage = '';
+
expect(vm.isMergeButtonDisabled).toBeTruthy();
});
it('should return true if merge is not allowed', () => {
vm.mr.isMergeAllowed = false;
vm.mr.onlyAllowMergeIfPipelineSucceeds = true;
+
expect(vm.isMergeButtonDisabled).toBeTruthy();
});
it('should return true when the vm instance is making request', () => {
vm.mr.isMergeAllowed = true;
vm.isMakingRequest = true;
+
expect(vm.isMergeButtonDisabled).toBeTruthy();
});
});
@@ -245,24 +267,28 @@ describe('ReadyToMerge', () => {
it('should return false when an external pipeline is running and required to succeed', () => {
vm.mr.isMergeAllowed = false;
vm.mr.isPipelineActive = false;
+
expect(vm.shouldShowMergeControls()).toBeFalsy();
});
it('should return true when the build succeeded or build not required to succeed', () => {
vm.mr.isMergeAllowed = true;
vm.mr.isPipelineActive = false;
+
expect(vm.shouldShowMergeControls()).toBeTruthy();
});
it('should return true when showing the MWPS button and a pipeline is running that needs to be successful', () => {
vm.mr.isMergeAllowed = false;
vm.mr.isPipelineActive = true;
+
expect(vm.shouldShowMergeControls()).toBeTruthy();
});
it('should return true when showing the MWPS button but not required for the pipeline to succeed', () => {
vm.mr.isMergeAllowed = true;
vm.mr.isPipelineActive = true;
+
expect(vm.shouldShowMergeControls()).toBeTruthy();
});
});
@@ -272,9 +298,11 @@ describe('ReadyToMerge', () => {
expect(vm.useCommitMessageWithDescription).toBeFalsy();
expect(vm.commitMessage).toEqual(commitMessage);
vm.updateCommitMessage();
+
expect(vm.useCommitMessageWithDescription).toBeTruthy();
expect(vm.commitMessage).toEqual(commitMessageWithDescription);
vm.updateCommitMessage();
+
expect(vm.useCommitMessageWithDescription).toBeFalsy();
expect(vm.commitMessage).toEqual(commitMessage);
});
@@ -284,20 +312,22 @@ describe('ReadyToMerge', () => {
it('should toggle showCommitMessageEditor flag', () => {
expect(vm.showCommitMessageEditor).toBeFalsy();
vm.toggleCommitMessageEditor();
+
expect(vm.showCommitMessageEditor).toBeTruthy();
});
});
describe('handleMergeButtonClick', () => {
- const returnPromise = status => new Promise((resolve) => {
- resolve({
- data: {
- status,
- },
+ const returnPromise = status =>
+ new Promise(resolve => {
+ resolve({
+ data: {
+ status,
+ },
+ });
});
- });
- it('should handle merge when pipeline succeeds', (done) => {
+ it('should handle merge when pipeline succeeds', done => {
spyOn(eventHub, '$emit');
spyOn(vm.service, 'merge').and.returnValue(returnPromise('merge_when_pipeline_succeeds'));
vm.removeSourceBranch = false;
@@ -309,6 +339,7 @@ describe('ReadyToMerge', () => {
expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
const params = vm.service.merge.calls.argsFor(0)[0];
+
expect(params.sha).toEqual(vm.mr.sha);
expect(params.commit_message).toEqual(vm.mr.commitMessage);
expect(params.should_remove_source_branch).toBeFalsy();
@@ -317,7 +348,7 @@ describe('ReadyToMerge', () => {
}, 333);
});
- it('should handle merge failed', (done) => {
+ it('should handle merge failed', done => {
spyOn(eventHub, '$emit');
spyOn(vm.service, 'merge').and.returnValue(returnPromise('failed'));
vm.handleMergeButtonClick(false, true);
@@ -328,13 +359,14 @@ describe('ReadyToMerge', () => {
expect(eventHub.$emit).toHaveBeenCalledWith('FailedToMerge', undefined);
const params = vm.service.merge.calls.argsFor(0)[0];
+
expect(params.should_remove_source_branch).toBeTruthy();
expect(params.merge_when_pipeline_succeeds).toBeFalsy();
done();
}, 333);
});
- it('should handle merge action accepted case', (done) => {
+ it('should handle merge action accepted case', done => {
spyOn(vm.service, 'merge').and.returnValue(returnPromise('success'));
spyOn(vm, 'initiateMergePolling');
vm.handleMergeButtonClick();
@@ -345,6 +377,7 @@ describe('ReadyToMerge', () => {
expect(vm.initiateMergePolling).toHaveBeenCalled();
const params = vm.service.merge.calls.argsFor(0)[0];
+
expect(params.should_remove_source_branch).toBeTruthy();
expect(params.merge_when_pipeline_succeeds).toBeFalsy();
done();
@@ -356,25 +389,27 @@ describe('ReadyToMerge', () => {
it('should call simplePoll', () => {
const simplePoll = spyOnDependency(ReadyToMerge, 'simplePoll');
vm.initiateMergePolling();
+
expect(simplePoll).toHaveBeenCalled();
});
});
describe('handleMergePolling', () => {
- const returnPromise = state => new Promise((resolve) => {
- resolve({
- data: {
- state,
- source_branch_exists: true,
- },
+ const returnPromise = state =>
+ new Promise(resolve => {
+ resolve({
+ data: {
+ state,
+ source_branch_exists: true,
+ },
+ });
});
- });
beforeEach(() => {
loadFixtures('merge_requests/merge_request_of_current_user.html.raw');
});
- it('should call start and stop polling when MR merged', (done) => {
+ it('should call start and stop polling when MR merged', done => {
spyOn(eventHub, '$emit');
spyOn(vm.service, 'poll').and.returnValue(returnPromise('merged'));
spyOn(vm, 'initiateRemoveSourceBranchPolling');
@@ -382,7 +417,14 @@ describe('ReadyToMerge', () => {
let cpc = false; // continuePollingCalled
let spc = false; // stopPollingCalled
- vm.handleMergePolling(() => { cpc = true; }, () => { spc = true; });
+ vm.handleMergePolling(
+ () => {
+ cpc = true;
+ },
+ () => {
+ spc = true;
+ },
+ );
setTimeout(() => {
expect(vm.service.poll).toHaveBeenCalled();
expect(eventHub.$emit).toHaveBeenCalledWith('MRWidgetUpdateRequested');
@@ -395,7 +437,7 @@ describe('ReadyToMerge', () => {
}, 333);
});
- it('updates status box', (done) => {
+ it('updates status box', done => {
spyOn(vm.service, 'poll').and.returnValue(returnPromise('merged'));
spyOn(vm, 'initiateRemoveSourceBranchPolling');
@@ -403,6 +445,7 @@ describe('ReadyToMerge', () => {
setTimeout(() => {
const statusBox = document.querySelector('.status-box');
+
expect(statusBox.classList.contains('status-box-mr-merged')).toBeTruthy();
expect(statusBox.textContent).toContain('Merged');
@@ -410,7 +453,7 @@ describe('ReadyToMerge', () => {
});
});
- it('hides close button', (done) => {
+ it('hides close button', done => {
spyOn(vm.service, 'poll').and.returnValue(returnPromise('merged'));
spyOn(vm, 'initiateRemoveSourceBranchPolling');
@@ -423,7 +466,7 @@ describe('ReadyToMerge', () => {
});
});
- it('updates merge request count badge', (done) => {
+ it('updates merge request count badge', done => {
spyOn(vm.service, 'poll').and.returnValue(returnPromise('merged'));
spyOn(vm, 'initiateRemoveSourceBranchPolling');
@@ -436,14 +479,21 @@ describe('ReadyToMerge', () => {
});
});
- it('should continue polling until MR is merged', (done) => {
+ it('should continue polling until MR is merged', done => {
spyOn(vm.service, 'poll').and.returnValue(returnPromise('some_other_state'));
spyOn(vm, 'initiateRemoveSourceBranchPolling');
let cpc = false; // continuePollingCalled
let spc = false; // stopPollingCalled
- vm.handleMergePolling(() => { cpc = true; }, () => { spc = true; });
+ vm.handleMergePolling(
+ () => {
+ cpc = true;
+ },
+ () => {
+ spc = true;
+ },
+ );
setTimeout(() => {
expect(cpc).toBeTruthy();
expect(spc).toBeFalsy();
@@ -459,35 +509,46 @@ describe('ReadyToMerge', () => {
const simplePoll = spyOnDependency(ReadyToMerge, 'simplePoll');
vm.initiateRemoveSourceBranchPolling();
+
expect(eventHub.$emit).toHaveBeenCalledWith('SetBranchRemoveFlag', [true]);
expect(simplePoll).toHaveBeenCalled();
});
});
describe('handleRemoveBranchPolling', () => {
- const returnPromise = state => new Promise((resolve) => {
- resolve({
- data: {
- source_branch_exists: state,
- },
+ const returnPromise = state =>
+ new Promise(resolve => {
+ resolve({
+ data: {
+ source_branch_exists: state,
+ },
+ });
});
- });
- it('should call start and stop polling when MR merged', (done) => {
+ it('should call start and stop polling when MR merged', done => {
spyOn(eventHub, '$emit');
spyOn(vm.service, 'poll').and.returnValue(returnPromise(false));
let cpc = false; // continuePollingCalled
let spc = false; // stopPollingCalled
- vm.handleRemoveBranchPolling(() => { cpc = true; }, () => { spc = true; });
+ vm.handleRemoveBranchPolling(
+ () => {
+ cpc = true;
+ },
+ () => {
+ spc = true;
+ },
+ );
setTimeout(() => {
expect(vm.service.poll).toHaveBeenCalled();
const args = eventHub.$emit.calls.argsFor(0);
+
expect(args[0]).toEqual('MRWidgetUpdateRequested');
expect(args[1]).toBeDefined();
args[1]();
+
expect(eventHub.$emit).toHaveBeenCalledWith('SetBranchRemoveFlag', [false]);
expect(cpc).toBeFalsy();
@@ -497,13 +558,20 @@ describe('ReadyToMerge', () => {
}, 333);
});
- it('should continue polling until MR is merged', (done) => {
+ it('should continue polling until MR is merged', done => {
spyOn(vm.service, 'poll').and.returnValue(returnPromise(true));
let cpc = false; // continuePollingCalled
let spc = false; // stopPollingCalled
- vm.handleRemoveBranchPolling(() => { cpc = true; }, () => { spc = true; });
+ vm.handleRemoveBranchPolling(
+ () => {
+ cpc = true;
+ },
+ () => {
+ spc = true;
+ },
+ );
setTimeout(() => {
expect(cpc).toBeTruthy();
expect(spc).toBeFalsy();
@@ -518,6 +586,7 @@ describe('ReadyToMerge', () => {
describe('when user can merge but cannot delete branch', () => {
it('should be disabled in the rendered output', () => {
const checkboxElement = vm.$el.querySelector('#remove-source-branch-input');
+
expect(checkboxElement).toBeNull();
});
});
@@ -537,6 +606,7 @@ describe('ReadyToMerge', () => {
it('should be enabled in rendered output', () => {
const checkboxElement = customVm.$el.querySelector('#remove-source-branch-input');
+
expect(checkboxElement).not.toBeNull();
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js
index abf642c166a..36f8c7a9683 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_sha_mismatch_spec.js
@@ -18,8 +18,8 @@ describe('ShaMismatch', () => {
it('should render information message', () => {
expect(vm.$el.querySelector('button').disabled).toEqual(true);
- expect(
- removeBreakLine(vm.$el.textContent).trim(),
- ).toContain('The source branch HEAD has recently changed. Please reload the page and review the changes before merging');
+ expect(removeBreakLine(vm.$el.textContent).trim()).toContain(
+ 'The source branch HEAD has recently changed. Please reload the page and review the changes before merging',
+ );
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js
index d797f1266df..bd64d7b2926 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_unresolved_discussions_spec.js
@@ -12,13 +12,18 @@ describe('UnresolvedDiscussions', () => {
describe('with discussions path', () => {
beforeEach(() => {
- vm = mountComponent(Component, { mr: {
- createIssueToResolveDiscussionsPath: gl.TEST_HOST,
- } });
+ vm = mountComponent(Component, {
+ mr: {
+ createIssueToResolveDiscussionsPath: gl.TEST_HOST,
+ },
+ });
});
it('should have correct elements', () => {
- expect(vm.$el.innerText).toContain('There are unresolved discussions. Please resolve these discussions');
+ expect(vm.$el.innerText).toContain(
+ 'There are unresolved discussions. Please resolve these discussions',
+ );
+
expect(vm.$el.innerText).toContain('Create an issue to resolve them later');
expect(vm.$el.querySelector('.js-create-issue').getAttribute('href')).toEqual(gl.TEST_HOST);
});
@@ -30,7 +35,10 @@ describe('UnresolvedDiscussions', () => {
});
it('should not show create issue link if user cannot create issue', () => {
- expect(vm.$el.innerText).toContain('There are unresolved discussions. Please resolve these discussions');
+ expect(vm.$el.innerText).toContain(
+ 'There are unresolved discussions. Please resolve these discussions',
+ );
+
expect(vm.$el.querySelector('.js-create-issue')).toEqual(null);
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_wip_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_wip_spec.js
index cea603368bf..7b1d589dcf8 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_wip_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_wip_spec.js
@@ -33,6 +33,7 @@ describe('Wip', () => {
describe('data', () => {
it('should have default data', () => {
const vm = createComponent();
+
expect(vm.isMakingRequest).toBeFalsy();
});
});
@@ -43,22 +44,27 @@ describe('Wip', () => {
};
describe('removeWIP', () => {
- it('should make a request to service and handle response', (done) => {
+ it('should make a request to service and handle response', done => {
const vm = createComponent();
spyOn(window, 'Flash').and.returnValue(true);
spyOn(eventHub, '$emit');
- spyOn(vm.service, 'removeWIP').and.returnValue(new Promise((resolve) => {
- resolve({
- data: mrObj,
- });
- }));
+ spyOn(vm.service, 'removeWIP').and.returnValue(
+ new Promise(resolve => {
+ resolve({
+ data: mrObj,
+ });
+ }),
+ );
vm.removeWIP();
setTimeout(() => {
expect(vm.isMakingRequest).toBeTruthy();
expect(eventHub.$emit).toHaveBeenCalledWith('UpdateWidgetData', mrObj);
- expect(window.Flash).toHaveBeenCalledWith('The merge request can now be merged.', 'notice');
+ expect(window.Flash).toHaveBeenCalledWith(
+ 'The merge request can now be merged.',
+ 'notice',
+ );
done();
}, 333);
});
@@ -79,10 +85,12 @@ describe('Wip', () => {
expect(el.innerText).toContain('This is a Work in Progress');
expect(el.querySelector('button').getAttribute('disabled')).toBeTruthy();
expect(el.querySelector('button').innerText).toContain('Merge');
- expect(el.querySelector('.js-remove-wip').innerText).toContain('Resolve WIP status');
+ expect(el.querySelector('.js-remove-wip').innerText.replace(/\s\s+/g, ' ')).toContain(
+ 'Resolve WIP status',
+ );
});
- it('should not show removeWIP button is user cannot update MR', (done) => {
+ it('should not show removeWIP button is user cannot update MR', done => {
vm.mr.removeWIPPath = '';
Vue.nextTick(() => {
diff --git a/spec/javascripts/vue_mr_widget/mock_data.js b/spec/javascripts/vue_mr_widget/mock_data.js
index 7fd1a2350f7..072e98fc0e8 100644
--- a/spec/javascripts/vue_mr_widget/mock_data.js
+++ b/spec/javascripts/vue_mr_widget/mock_data.js
@@ -218,5 +218,20 @@ export default {
diverged_commits_count: 0,
only_allow_merge_if_pipeline_succeeds: false,
commit_change_content_path: '/root/acets-app/merge_requests/22/commit_change_content',
- merge_commit_path: 'http://localhost:3000/root/acets-app/commit/53027d060246c8f47e4a9310fb332aa52f221775',
+ merge_commit_path:
+ 'http://localhost:3000/root/acets-app/commit/53027d060246c8f47e4a9310fb332aa52f221775',
+ troubleshooting_docs_path: 'help',
+};
+
+export const mockStore = {
+ pipeline: { id: 0 },
+ mergePipeline: { id: 1 },
+ targetBranch: 'target-branch',
+ sourceBranch: 'source-branch',
+ sourceBranchLink: 'source-branch-link',
+ deployments: [{ id: 0, name: 'bogus' }, { id: 1, name: 'bogus-docs' }],
+ postMergeDeployments: [{ id: 0, name: 'prod' }, { id: 1, name: 'prod-docs' }],
+ troubleshootingDocsPath: 'troubleshooting-docs-path',
+ ciStatus: 'ci-status',
+ hasCI: true,
};
diff --git a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
index 6342ea00436..f72bf627c10 100644
--- a/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
@@ -7,11 +7,12 @@ import mountComponent from 'spec/helpers/vue_mount_component_helper';
import mockData from './mock_data';
import { faviconDataUrl, overlayDataUrl, faviconWithOverlayDataUrl } from '../lib/utils/mock_data';
-const returnPromise = data => new Promise((resolve) => {
- resolve({
- data,
+const returnPromise = data =>
+ new Promise(resolve => {
+ resolve({
+ data,
+ });
});
-});
describe('mrWidgetOptions', () => {
let vm;
@@ -27,6 +28,10 @@ describe('mrWidgetOptions', () => {
});
});
+ afterEach(() => {
+ vm.$destroy();
+ });
+
describe('data', () => {
it('should instantiate Store and Service', () => {
expect(vm.mr).toBeDefined();
@@ -42,6 +47,7 @@ describe('mrWidgetOptions', () => {
it('should return conflicts component', () => {
vm.mr.state = 'conflicts';
+
expect(vm.componentName).toEqual('mr-widget-conflicts');
});
});
@@ -53,6 +59,7 @@ describe('mrWidgetOptions', () => {
it('should return true for a state which requires help widget', () => {
vm.mr.state = 'conflicts';
+
expect(vm.shouldRenderMergeHelp).toBeTruthy();
});
});
@@ -78,6 +85,7 @@ describe('mrWidgetOptions', () => {
it('should return true if there is relatedLinks in MR', () => {
Vue.set(vm.mr, 'relatedLinks', {});
+
expect(vm.shouldRenderRelatedLinks).toBeTruthy();
});
});
@@ -128,7 +136,7 @@ describe('mrWidgetOptions', () => {
describe('methods', () => {
describe('checkStatus', () => {
- it('should tell service to check status', (done) => {
+ it('should tell service to check status', done => {
spyOn(vm.service, 'checkStatus').and.returnValue(returnPromise(mockData));
spyOn(vm.mr, 'setData');
spyOn(vm, 'handleNotification');
@@ -178,10 +186,10 @@ describe('mrWidgetOptions', () => {
});
describe('fetchDeployments', () => {
- it('should fetch deployments', (done) => {
+ it('should fetch deployments', done => {
spyOn(vm.service, 'fetchDeployments').and.returnValue(returnPromise([{ id: 1 }]));
- vm.fetchDeployments();
+ vm.fetchPreMergeDeployments();
setTimeout(() => {
expect(vm.service.fetchDeployments).toHaveBeenCalled();
@@ -193,7 +201,7 @@ describe('mrWidgetOptions', () => {
});
describe('fetchActionsContent', () => {
- it('should fetch content of Cherry Pick and Revert modals', (done) => {
+ it('should fetch content of Cherry Pick and Revert modals', done => {
spyOn(vm.service, 'fetchMergeActionsContent').and.returnValue(returnPromise('hello world'));
vm.fetchActionsContent();
@@ -219,18 +227,23 @@ describe('mrWidgetOptions', () => {
vm.bindEventHubListeners();
eventHub.$emit('SetBranchRemoveFlag', ['flag']);
+
expect(vm.mr.isRemovingSourceBranch).toEqual('flag');
eventHub.$emit('FailedToMerge');
+
expect(vm.mr.state).toEqual('failedToMerge');
eventHub.$emit('UpdateWidgetData', mockData);
+
expect(vm.mr.setData).toHaveBeenCalledWith(mockData);
eventHub.$emit('EnablePolling');
+
expect(vm.resumePolling).toHaveBeenCalled();
eventHub.$emit('DisablePolling');
+
expect(vm.stopPolling).toHaveBeenCalled();
const listenersWithServiceRequest = {
@@ -239,7 +252,7 @@ describe('mrWidgetOptions', () => {
};
const allArgs = eventHub.$on.calls.allArgs();
- allArgs.forEach((params) => {
+ allArgs.forEach(params => {
const eventName = params[0];
const callback = params[1];
@@ -249,22 +262,12 @@ describe('mrWidgetOptions', () => {
});
listenersWithServiceRequest.MRWidgetUpdateRequested();
+
expect(vm.checkStatus).toHaveBeenCalled();
listenersWithServiceRequest.FetchActionsContent();
- expect(vm.fetchActionsContent).toHaveBeenCalled();
- });
- });
- describe('handleMounted', () => {
- it('should call required methods to do the initial kick-off', () => {
- spyOn(vm, 'initDeploymentsPolling');
- spyOn(vm, 'setFaviconHelper');
-
- vm.handleMounted();
-
- expect(vm.setFaviconHelper).toHaveBeenCalled();
- expect(vm.initDeploymentsPolling).toHaveBeenCalled();
+ expect(vm.fetchActionsContent).toHaveBeenCalled();
});
});
@@ -284,13 +287,14 @@ describe('mrWidgetOptions', () => {
document.body.removeChild(document.getElementById('favicon'));
});
- it('should call setFavicon method', (done) => {
+ it('should call setFavicon method', done => {
vm.mr.ciStatusFaviconPath = overlayDataUrl;
- vm.setFaviconHelper().then(() => {
- expect(faviconElement.getAttribute('href')).toEqual(faviconWithOverlayDataUrl);
- done();
- })
- .catch(done.fail);
+ vm.setFaviconHelper()
+ .then(() => {
+ expect(faviconElement.getAttribute('href')).toEqual(faviconWithOverlayDataUrl);
+ done();
+ })
+ .catch(done.fail);
});
it('should not call setFavicon when there is no ciStatusFaviconPath', () => {
@@ -348,6 +352,7 @@ describe('mrWidgetOptions', () => {
spyOn(vm.pollingInterval, 'resume');
vm.resumePolling();
+
expect(vm.pollingInterval.resume).toHaveBeenCalled();
});
});
@@ -357,13 +362,14 @@ describe('mrWidgetOptions', () => {
spyOn(vm.pollingInterval, 'stopTimer');
vm.stopPolling();
+
expect(vm.pollingInterval.stopTimer).toHaveBeenCalled();
});
});
});
describe('rendering relatedLinks', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm.mr.relatedLinks = {
assignToMe: null,
closing: `
@@ -380,7 +386,7 @@ describe('mrWidgetOptions', () => {
expect(vm.$el.querySelector('.close-related-link')).toBeDefined();
});
- it('does not render if state is nothingToMerge', (done) => {
+ it('does not render if state is nothingToMerge', done => {
vm.mr.state = stateKey.nothingToMerge;
Vue.nextTick(() => {
expect(vm.$el.querySelector('.close-related-link')).toBeNull();
@@ -390,7 +396,7 @@ describe('mrWidgetOptions', () => {
});
describe('rendering source branch removal status', () => {
- it('renders when user cannot remove branch and branch should be removed', (done) => {
+ it('renders when user cannot remove branch and branch should be removed', done => {
vm.mr.canRemoveSourceBranch = false;
vm.mr.shouldRemoveSourceBranch = true;
vm.mr.state = 'readyToMerge';
@@ -407,7 +413,7 @@ describe('mrWidgetOptions', () => {
});
});
- it('does not render in merged state', (done) => {
+ it('does not render in merged state', done => {
vm.mr.canRemoveSourceBranch = false;
vm.mr.shouldRemoveSourceBranch = true;
vm.mr.state = 'merged';
@@ -422,6 +428,20 @@ describe('mrWidgetOptions', () => {
});
describe('rendering deployments', () => {
+ const changes = [
+ {
+ path: 'index.html',
+ external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/index.html',
+ },
+ {
+ path: 'imgs/gallery.html',
+ external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/imgs/gallery.html',
+ },
+ {
+ path: 'about/',
+ external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/about/',
+ },
+ ];
const deploymentMockData = {
id: 15,
name: 'review/diplo',
@@ -433,15 +453,20 @@ describe('mrWidgetOptions', () => {
external_url_formatted: 'diplo.',
deployed_at: '2017-03-22T22:44:42.258Z',
deployed_at_formatted: 'Mar 22, 2017 10:44pm',
+ changes,
+ status: 'success',
};
- beforeEach((done) => {
- vm.mr.deployments.push({
- ...deploymentMockData,
- }, {
- ...deploymentMockData,
- id: deploymentMockData.id + 1,
- });
+ beforeEach(done => {
+ vm.mr.deployments.push(
+ {
+ ...deploymentMockData,
+ },
+ {
+ ...deploymentMockData,
+ id: deploymentMockData.id + 1,
+ },
+ );
vm.$nextTick(done);
});
@@ -449,5 +474,201 @@ describe('mrWidgetOptions', () => {
it('renders multiple deployments', () => {
expect(vm.$el.querySelectorAll('.deploy-heading').length).toBe(2);
});
+
+ it('renders dropdpown with multiple file changes', () => {
+ expect(
+ vm.$el
+ .querySelector('.js-mr-wigdet-deployment-dropdown')
+ .querySelectorAll('.js-filtered-dropdown-result').length,
+ ).toEqual(changes.length);
+ });
+ });
+
+ describe('pipeline for target branch after merge', () => {
+ describe('with information for target branch pipeline', () => {
+ beforeEach(done => {
+ vm.mr.state = 'merged';
+ vm.mr.mergePipeline = {
+ id: 127,
+ user: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ state: 'active',
+ avatar_url: null,
+ web_url: 'http://localhost:3000/root',
+ status_tooltip_html: null,
+ path: '/root',
+ },
+ active: true,
+ coverage: null,
+ source: 'push',
+ created_at: '2018-10-22T11:41:35.186Z',
+ updated_at: '2018-10-22T11:41:35.433Z',
+ path: '/root/ci-web-terminal/pipelines/127',
+ flags: {
+ latest: true,
+ stuck: true,
+ auto_devops: false,
+ yaml_errors: false,
+ retryable: false,
+ cancelable: true,
+ failure_reason: false,
+ },
+ details: {
+ status: {
+ icon: 'status_pending',
+ text: 'pending',
+ label: 'pending',
+ group: 'pending',
+ tooltip: 'pending',
+ has_details: true,
+ details_path: '/root/ci-web-terminal/pipelines/127',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png',
+ },
+ duration: null,
+ finished_at: null,
+ stages: [
+ {
+ name: 'test',
+ title: 'test: pending',
+ status: {
+ icon: 'status_pending',
+ text: 'pending',
+ label: 'pending',
+ group: 'pending',
+ tooltip: 'pending',
+ has_details: true,
+ details_path: '/root/ci-web-terminal/pipelines/127#test',
+ illustration: null,
+ favicon:
+ '/assets/ci_favicons/favicon_status_pending-5bdf338420e5221ca24353b6bff1c9367189588750632e9a871b7af09ff6a2ae.png',
+ },
+ path: '/root/ci-web-terminal/pipelines/127#test',
+ dropdown_path: '/root/ci-web-terminal/pipelines/127/stage.json?stage=test',
+ },
+ ],
+ artifacts: [],
+ manual_actions: [],
+ scheduled_actions: [],
+ },
+ ref: {
+ name: 'master',
+ path: '/root/ci-web-terminal/commits/master',
+ tag: false,
+ branch: true,
+ },
+ commit: {
+ id: 'aa1939133d373c94879becb79d91828a892ee319',
+ short_id: 'aa193913',
+ title: "Merge branch 'master-test' into 'master'",
+ created_at: '2018-10-22T11:41:33.000Z',
+ parent_ids: [
+ '4622f4dd792468993003caf2e3be978798cbe096',
+ '76598df914cdfe87132d0c3c40f80db9fa9396a4',
+ ],
+ message:
+ "Merge branch 'master-test' into 'master'\n\nUpdate .gitlab-ci.yml\n\nSee merge request root/ci-web-terminal!1",
+ author_name: 'Administrator',
+ author_email: 'admin@example.com',
+ authored_date: '2018-10-22T11:41:33.000Z',
+ committer_name: 'Administrator',
+ committer_email: 'admin@example.com',
+ committed_date: '2018-10-22T11:41:33.000Z',
+ author: {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ state: 'active',
+ avatar_url: null,
+ web_url: 'http://localhost:3000/root',
+ status_tooltip_html: null,
+ path: '/root',
+ },
+ author_gravatar_url: null,
+ commit_url:
+ 'http://localhost:3000/root/ci-web-terminal/commit/aa1939133d373c94879becb79d91828a892ee319',
+ commit_path: '/root/ci-web-terminal/commit/aa1939133d373c94879becb79d91828a892ee319',
+ },
+ cancel_path: '/root/ci-web-terminal/pipelines/127/cancel',
+ };
+ vm.$nextTick(done);
+ });
+
+ it('renders pipeline block', () => {
+ expect(vm.$el.querySelector('.js-post-merge-pipeline')).not.toBeNull();
+ });
+
+ describe('with post merge deployments', () => {
+ beforeEach(done => {
+ vm.mr.postMergeDeployments = [
+ {
+ id: 15,
+ name: 'review/diplo',
+ url: '/root/acets-review-apps/environments/15',
+ stop_url: '/root/acets-review-apps/environments/15/stop',
+ metrics_url: '/root/acets-review-apps/environments/15/deployments/1/metrics',
+ metrics_monitoring_url: '/root/acets-review-apps/environments/15/metrics',
+ external_url: 'http://diplo.',
+ external_url_formatted: 'diplo.',
+ deployed_at: '2017-03-22T22:44:42.258Z',
+ deployed_at_formatted: 'Mar 22, 2017 10:44pm',
+ changes: [
+ {
+ path: 'index.html',
+ external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/index.html',
+ },
+ {
+ path: 'imgs/gallery.html',
+ external_url:
+ 'http://root-master-patch-91341.volatile-watch.surge.sh/imgs/gallery.html',
+ },
+ {
+ path: 'about/',
+ external_url: 'http://root-master-patch-91341.volatile-watch.surge.sh/about/',
+ },
+ ],
+ status: 'success',
+ },
+ ];
+
+ vm.$nextTick(done);
+ });
+
+ it('renders post deployment information', () => {
+ expect(vm.$el.querySelector('.js-post-deployment')).not.toBeNull();
+ });
+ });
+ });
+
+ describe('without information for target branch pipeline', () => {
+ beforeEach(done => {
+ vm.mr.state = 'merged';
+
+ vm.$nextTick(done);
+ });
+
+ it('does not render pipeline block', () => {
+ expect(vm.$el.querySelector('.js-post-merge-pipeline')).toBeNull();
+ });
+ });
+
+ describe('when state is not merged', () => {
+ beforeEach(done => {
+ vm.mr.state = 'archived';
+
+ vm.$nextTick(done);
+ });
+
+ it('does not render pipeline block', () => {
+ expect(vm.$el.querySelector('.js-post-merge-pipeline')).toBeNull();
+ });
+
+ it('does not render post deployment information', () => {
+ expect(vm.$el.querySelector('.js-post-deployment')).toBeNull();
+ });
+ });
});
});
diff --git a/spec/javascripts/vue_mr_widget/stores/get_state_key_spec.js b/spec/javascripts/vue_mr_widget/stores/get_state_key_spec.js
index 179e42a7cc4..9d34bdd1084 100644
--- a/spec/javascripts/vue_mr_widget/stores/get_state_key_spec.js
+++ b/spec/javascripts/vue_mr_widget/stores/get_state_key_spec.js
@@ -20,46 +20,60 @@ describe('getStateKey', () => {
work_in_progress: false,
};
const bound = getStateKey.bind(context, data);
+
expect(bound()).toEqual(null);
context.canBeMerged = true;
+
expect(bound()).toEqual('readyToMerge');
context.canMerge = false;
+
expect(bound()).toEqual('notAllowedToMerge');
context.mergeWhenPipelineSucceeds = true;
+
expect(bound()).toEqual('mergeWhenPipelineSucceeds');
context.hasSHAChanged = true;
+
expect(bound()).toEqual('shaMismatch');
context.isPipelineBlocked = true;
+
expect(bound()).toEqual('pipelineBlocked');
context.hasMergeableDiscussionsState = true;
+
expect(bound()).toEqual('unresolvedDiscussions');
context.onlyAllowMergeIfPipelineSucceeds = true;
context.isPipelineFailed = true;
+
expect(bound()).toEqual('pipelineFailed');
data.work_in_progress = true;
+
expect(bound()).toEqual('workInProgress');
data.has_conflicts = true;
+
expect(bound()).toEqual('conflicts');
context.mergeStatus = 'unchecked';
+
expect(bound()).toEqual('checking');
data.commits_count = 0;
+
expect(bound()).toEqual('nothingToMerge');
data.branch_missing = true;
+
expect(bound()).toEqual('missingBranch');
data.project_archived = true;
+
expect(bound()).toEqual('archived');
});
});
diff --git a/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js b/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js
index 33d052aceb2..f5079147f60 100644
--- a/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js
+++ b/spec/javascripts/vue_mr_widget/stores/mr_widget_store_spec.js
@@ -12,32 +12,38 @@ describe('MergeRequestStore', () => {
it('should set hasSHAChanged when the diff SHA changes', () => {
store.setData({ ...mockData, diff_head_sha: 'a-different-string' });
+
expect(store.hasSHAChanged).toBe(true);
});
it('should not set hasSHAChanged when other data changes', () => {
store.setData({ ...mockData, work_in_progress: !mockData.work_in_progress });
+
expect(store.hasSHAChanged).toBe(false);
});
describe('isPipelinePassing', () => {
it('is true when the CI status is `success`', () => {
store.setData({ ...mockData, ci_status: 'success' });
+
expect(store.isPipelinePassing).toBe(true);
});
it('is true when the CI status is `success_with_warnings`', () => {
store.setData({ ...mockData, ci_status: 'success_with_warnings' });
+
expect(store.isPipelinePassing).toBe(true);
});
it('is false when the CI status is `failed`', () => {
store.setData({ ...mockData, ci_status: 'failed' });
+
expect(store.isPipelinePassing).toBe(false);
});
it('is false when the CI status is anything except `success`', () => {
store.setData({ ...mockData, ci_status: 'foobarbaz' });
+
expect(store.isPipelinePassing).toBe(false);
});
});
@@ -45,11 +51,13 @@ describe('MergeRequestStore', () => {
describe('isPipelineSkipped', () => {
it('should set isPipelineSkipped=true when the CI status is `skipped`', () => {
store.setData({ ...mockData, ci_status: 'skipped' });
+
expect(store.isPipelineSkipped).toBe(true);
});
it('should set isPipelineSkipped=false when the CI status is anything except `skipped`', () => {
store.setData({ ...mockData, ci_status: 'foobarbaz' });
+
expect(store.isPipelineSkipped).toBe(false);
});
});
@@ -57,11 +65,13 @@ describe('MergeRequestStore', () => {
describe('isNothingToMergeState', () => {
it('returns true when nothingToMerge', () => {
store.state = stateKey.nothingToMerge;
+
expect(store.isNothingToMergeState).toEqual(true);
});
it('returns false when not nothingToMerge', () => {
store.state = 'state';
+
expect(store.isNothingToMergeState).toEqual(false);
});
});
diff --git a/spec/javascripts/vue_shared/components/bar_chart_spec.js b/spec/javascripts/vue_shared/components/bar_chart_spec.js
index 7e91cd6f63f..8f753876e44 100644
--- a/spec/javascripts/vue_shared/components/bar_chart_spec.js
+++ b/spec/javascripts/vue_shared/components/bar_chart_spec.js
@@ -71,12 +71,6 @@ describe('Bar chart component', () => {
expect(barChart.xAxisLocation).toEqual('translate(100, 250)');
});
- it('Contains a total of 4 ticks across the y axis', () => {
- const ticks = barChart.$el.querySelector('.y-axis').querySelectorAll('.tick').length;
-
- expect(ticks).toEqual(4);
- });
-
it('rotates the x axis labels a total of 90 degress (CCW)', () => {
const xAxisLabel = barChart.$el.querySelector('.x-axis').querySelectorAll('text')[0];
diff --git a/spec/javascripts/vue_shared/components/changed_file_icon_spec.js b/spec/javascripts/vue_shared/components/changed_file_icon_spec.js
new file mode 100644
index 00000000000..5b1038840c7
--- /dev/null
+++ b/spec/javascripts/vue_shared/components/changed_file_icon_spec.js
@@ -0,0 +1,46 @@
+import Vue from 'vue';
+import changedFileIcon from '~/vue_shared/components/changed_file_icon.vue';
+import createComponent from 'spec/helpers/vue_mount_component_helper';
+
+describe('Changed file icon', () => {
+ let vm;
+
+ beforeEach(() => {
+ const component = Vue.extend(changedFileIcon);
+
+ vm = createComponent(component, {
+ file: {
+ tempFile: false,
+ changed: true,
+ },
+ });
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('changedIcon', () => {
+ it('equals file-modified when not a temp file and has changes', () => {
+ expect(vm.changedIcon).toBe('file-modified');
+ });
+
+ it('equals file-addition when a temp file', () => {
+ vm.file.tempFile = true;
+
+ expect(vm.changedIcon).toBe('file-addition');
+ });
+ });
+
+ describe('changedIconClass', () => {
+ it('includes file-modified when not a temp file', () => {
+ expect(vm.changedIconClass).toContain('file-modified');
+ });
+
+ it('includes file-addition when a temp file', () => {
+ vm.file.tempFile = true;
+
+ expect(vm.changedIconClass).toContain('file-addition');
+ });
+ });
+});
diff --git a/spec/javascripts/vue_shared/components/ci_badge_link_spec.js b/spec/javascripts/vue_shared/components/ci_badge_link_spec.js
index 668742ebaee..4b0b7ba66e5 100644
--- a/spec/javascripts/vue_shared/components/ci_badge_link_spec.js
+++ b/spec/javascripts/vue_shared/components/ci_badge_link_spec.js
@@ -81,11 +81,12 @@ describe('CI Badge Link Component', () => {
});
it('should render each status badge', () => {
- Object.keys(statuses).map((status) => {
+ Object.keys(statuses).map(status => {
vm = mountComponent(CIBadge, { status: statuses[status] });
+
expect(vm.$el.getAttribute('href')).toEqual(statuses[status].details_path);
expect(vm.$el.textContent.trim()).toEqual(statuses[status].text);
- expect(vm.$el.getAttribute('class')).toEqual(`ci-status ci-${statuses[status].group}`);
+ expect(vm.$el.getAttribute('class')).toContain(`ci-status ci-${statuses[status].group}`);
expect(vm.$el.querySelector('svg')).toBeDefined();
return vm;
});
@@ -93,6 +94,7 @@ describe('CI Badge Link Component', () => {
it('should not render label', () => {
vm = mountComponent(CIBadge, { status: statuses.canceled, showText: false });
+
expect(vm.$el.textContent.trim()).toEqual('');
});
});
diff --git a/spec/javascripts/vue_shared/components/clipboard_button_spec.js b/spec/javascripts/vue_shared/components/clipboard_button_spec.js
index ea525b1e44f..fd17349d48f 100644
--- a/spec/javascripts/vue_shared/components/clipboard_button_spec.js
+++ b/spec/javascripts/vue_shared/components/clipboard_button_spec.js
@@ -27,8 +27,6 @@ describe('clipboard button', () => {
it('should have a tooltip with default values', () => {
expect(vm.$el.getAttribute('data-original-title')).toEqual('Copy this value into Clipboard!');
- expect(vm.$el.getAttribute('data-placement')).toEqual('top');
- expect(vm.$el.getAttribute('data-container')).toEqual(null);
});
it('should render provided classname', () => {
@@ -44,6 +42,7 @@ describe('clipboard button', () => {
title: 'Copy this value into Clipboard!',
cssClass: 'btn-danger',
});
+
expect(vm.$el.getAttribute('data-clipboard-text')).toEqual(
'{"text":"copy me","gfm":"`path/to/file`"}',
);
diff --git a/spec/javascripts/vue_shared/components/commit_spec.js b/spec/javascripts/vue_shared/components/commit_spec.js
index 7189e8cfcfa..18fcdf7ede1 100644
--- a/spec/javascripts/vue_shared/components/commit_spec.js
+++ b/spec/javascripts/vue_shared/components/commit_spec.js
@@ -78,6 +78,7 @@ describe('Commit component', () => {
expect(component.$el.querySelector('.commit-sha').getAttribute('href')).toEqual(
props.commitUrl,
);
+
expect(component.$el.querySelector('.commit-sha').textContent).toContain(props.shortSha);
});
@@ -97,9 +98,10 @@ describe('Commit component', () => {
it('Should render the author avatar with title and alt attributes', () => {
expect(
component.$el
- .querySelector('.commit-title .avatar-image-container img')
- .getAttribute('data-original-title'),
+ .querySelector('.commit-title .avatar-image-container .js-user-avatar-image-toolip')
+ .textContent.trim(),
).toContain(props.author.username);
+
expect(
component.$el
.querySelector('.commit-title .avatar-image-container img')
@@ -112,6 +114,7 @@ describe('Commit component', () => {
expect(component.$el.querySelector('a.commit-row-message').getAttribute('href')).toEqual(
props.commitUrl,
);
+
expect(component.$el.querySelector('a.commit-row-message').textContent).toContain(
props.title,
);
diff --git a/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js b/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js
index e2c34508b0d..4da8c6196b1 100644
--- a/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js
+++ b/spec/javascripts/vue_shared/components/content_viewer/content_viewer_spec.js
@@ -47,7 +47,7 @@ describe('ContentViewer', () => {
});
setTimeout(() => {
- expect(vm.$el.querySelector('.image_file img').getAttribute('src')).toBe(GREEN_BOX_IMAGE_URL);
+ expect(vm.$el.querySelector('img').getAttribute('src')).toBe(GREEN_BOX_IMAGE_URL);
done();
});
diff --git a/spec/javascripts/vue_shared/components/deprecated_modal_spec.js b/spec/javascripts/vue_shared/components/deprecated_modal_spec.js
index 59d4e549a91..be75be92158 100644
--- a/spec/javascripts/vue_shared/components/deprecated_modal_spec.js
+++ b/spec/javascripts/vue_shared/components/deprecated_modal_spec.js
@@ -47,7 +47,7 @@ describe('DeprecatedModal', () => {
});
});
- it('works with data-toggle="modal"', (done) => {
+ it('works with data-toggle="modal"', done => {
setFixtures(`
<button id="modal-button" data-toggle="modal" data-target="#my-modal"></button>
<div id="modal-container"></div>
@@ -55,9 +55,13 @@ describe('DeprecatedModal', () => {
const modalContainer = document.getElementById('modal-container');
const modalButton = document.getElementById('modal-button');
- vm = mountComponent(modalComponent, {
- id: 'my-modal',
- }, modalContainer);
+ vm = mountComponent(
+ modalComponent,
+ {
+ id: 'my-modal',
+ },
+ modalContainer,
+ );
const modalElement = vm.$el.querySelector('#my-modal');
$(modalElement).on('shown.bs.modal', () => done());
diff --git a/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js b/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js
index 71d9145bf22..67a3a2e08bc 100644
--- a/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js
+++ b/spec/javascripts/vue_shared/components/diff_viewer/diff_viewer_spec.js
@@ -30,11 +30,11 @@ describe('DiffViewer', () => {
});
setTimeout(() => {
- expect(vm.$el.querySelector('.deleted .image_file img').getAttribute('src')).toBe(
+ expect(vm.$el.querySelector('.deleted img').getAttribute('src')).toBe(
`//raw/DEF/${RED_BOX_IMAGE_URL}`,
);
- expect(vm.$el.querySelector('.added .image_file img').getAttribute('src')).toBe(
+ expect(vm.$el.querySelector('.added img').getAttribute('src')).toBe(
`//raw/ABC/${GREEN_BOX_IMAGE_URL}`,
);
@@ -55,6 +55,7 @@ describe('DiffViewer', () => {
expect(vm.$el.querySelector('.deleted .file-info').textContent.trim()).toContain(
'testold.abc',
);
+
expect(vm.$el.querySelector('.deleted .btn.btn-default').textContent.trim()).toContain(
'Download',
);
diff --git a/spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js b/spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js
index dde49b4a5d7..7f2e246d656 100644
--- a/spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js
+++ b/spec/javascripts/vue_shared/components/diff_viewer/viewers/image_diff_viewer_spec.js
@@ -52,17 +52,15 @@ describe('ImageDiffViewer', () => {
});
setTimeout(() => {
- expect(vm.$el.querySelector('.added .image_file img').getAttribute('src')).toBe(
- GREEN_BOX_IMAGE_URL,
- );
- expect(vm.$el.querySelector('.deleted .image_file img').getAttribute('src')).toBe(
- RED_BOX_IMAGE_URL,
- );
+ expect(vm.$el.querySelector('.added img').getAttribute('src')).toBe(GREEN_BOX_IMAGE_URL);
+
+ expect(vm.$el.querySelector('.deleted img').getAttribute('src')).toBe(RED_BOX_IMAGE_URL);
expect(vm.$el.querySelector('.view-modes-menu li.active').textContent.trim()).toBe('2-up');
expect(vm.$el.querySelector('.view-modes-menu li:nth-child(2)').textContent.trim()).toBe(
'Swipe',
);
+
expect(vm.$el.querySelector('.view-modes-menu li:nth-child(3)').textContent.trim()).toBe(
'Onion skin',
);
@@ -79,9 +77,7 @@ describe('ImageDiffViewer', () => {
});
setTimeout(() => {
- expect(vm.$el.querySelector('.added .image_file img').getAttribute('src')).toBe(
- GREEN_BOX_IMAGE_URL,
- );
+ expect(vm.$el.querySelector('.added img').getAttribute('src')).toBe(GREEN_BOX_IMAGE_URL);
done();
});
@@ -95,9 +91,27 @@ describe('ImageDiffViewer', () => {
});
setTimeout(() => {
- expect(vm.$el.querySelector('.deleted .image_file img').getAttribute('src')).toBe(
- RED_BOX_IMAGE_URL,
- );
+ expect(vm.$el.querySelector('.deleted img').getAttribute('src')).toBe(RED_BOX_IMAGE_URL);
+
+ done();
+ });
+ });
+
+ it('renders image diff for renamed', done => {
+ vm = new Vue({
+ components: {
+ imageDiffViewer,
+ },
+ template: `
+ <image-diff-viewer diff-mode="renamed" new-path="${GREEN_BOX_IMAGE_URL}" old-path="">
+ <span slot="image-overlay" class="overlay">test</span>
+ </image-diff-viewer>
+ `,
+ }).$mount();
+
+ setTimeout(() => {
+ expect(vm.$el.querySelector('img').getAttribute('src')).toBe(GREEN_BOX_IMAGE_URL);
+ expect(vm.$el.querySelector('.overlay')).not.toBe(null);
done();
});
diff --git a/spec/javascripts/vue_shared/components/dropdown/dropdown_button_spec.js b/spec/javascripts/vue_shared/components/dropdown/dropdown_button_spec.js
index 2796cd088c6..2fc4943de30 100644
--- a/spec/javascripts/vue_shared/components/dropdown/dropdown_button_spec.js
+++ b/spec/javascripts/vue_shared/components/dropdown/dropdown_button_spec.js
@@ -55,6 +55,7 @@ describe('DropdownButtonComponent', () => {
it('renders dropdown toggle text element', () => {
const dropdownToggleTextEl = vm.$el.querySelector('.dropdown-toggle-text');
+
expect(dropdownToggleTextEl).not.toBeNull();
expect(dropdownToggleTextEl.innerText.trim()).toBe(defaultLabel);
});
@@ -67,9 +68,12 @@ describe('DropdownButtonComponent', () => {
});
it('renders slot, if default slot exists', () => {
- vm = createComponent({}, {
- default: ['Lorem Ipsum Dolar'],
- });
+ vm = createComponent(
+ {},
+ {
+ default: ['Lorem Ipsum Dolar'],
+ },
+ );
expect(vm.$el).not.toContainElement('.dropdown-toggle-text');
expect(vm.$el).toHaveText('Lorem Ipsum Dolar');
diff --git a/spec/javascripts/vue_shared/components/expand_button_spec.js b/spec/javascripts/vue_shared/components/expand_button_spec.js
index 98fee9a74a5..2af4abc299a 100644
--- a/spec/javascripts/vue_shared/components/expand_button_spec.js
+++ b/spec/javascripts/vue_shared/components/expand_button_spec.js
@@ -18,7 +18,7 @@ describe('expand button', () => {
vm.$destroy();
});
- it('renders a collpased button', () => {
+ it('renders a collapsed button', () => {
expect(vm.$children[0].iconTestClass).toEqual('ic-ellipsis_h');
});
diff --git a/spec/javascripts/vue_shared/components/file_icon_spec.js b/spec/javascripts/vue_shared/components/file_icon_spec.js
index f2a09d08829..34c9b35e02a 100644
--- a/spec/javascripts/vue_shared/components/file_icon_spec.js
+++ b/spec/javascripts/vue_shared/components/file_icon_spec.js
@@ -28,7 +28,9 @@ describe('File Icon component', () => {
fileName: 'test.js',
});
- expect(vm.$el.firstChild.firstChild.getAttribute('xlink:href')).toBe(`${gon.sprite_file_icons}#javascript`);
+ expect(vm.$el.firstChild.firstChild.getAttribute('xlink:href')).toBe(
+ `${gon.sprite_file_icons}#javascript`,
+ );
});
it('should render a image icon based on file ending', () => {
@@ -36,7 +38,9 @@ describe('File Icon component', () => {
fileName: 'test.png',
});
- expect(vm.$el.firstChild.firstChild.getAttribute('xlink:href')).toBe(`${gon.sprite_file_icons}#image`);
+ expect(vm.$el.firstChild.firstChild.getAttribute('xlink:href')).toBe(
+ `${gon.sprite_file_icons}#image`,
+ );
});
it('should render a webpack icon based on file namer', () => {
@@ -44,7 +48,9 @@ describe('File Icon component', () => {
fileName: 'webpack.js',
});
- expect(vm.$el.firstChild.firstChild.getAttribute('xlink:href')).toBe(`${gon.sprite_file_icons}#webpack`);
+ expect(vm.$el.firstChild.firstChild.getAttribute('xlink:href')).toBe(
+ `${gon.sprite_file_icons}#webpack`,
+ );
});
it('should render a standard folder icon', () => {
@@ -53,7 +59,9 @@ describe('File Icon component', () => {
folder: true,
});
- expect(vm.$el.querySelector('span > svg > use').getAttribute('xlink:href')).toBe(`${gon.sprite_file_icons}#folder`);
+ expect(vm.$el.querySelector('span > svg > use').getAttribute('xlink:href')).toBe(
+ `${gon.sprite_file_icons}#folder`,
+ );
});
it('should render a loading icon', () => {
@@ -63,6 +71,7 @@ describe('File Icon component', () => {
});
const { classList } = vm.$el.querySelector('i');
+
expect(classList.contains('fa')).toEqual(true);
expect(classList.contains('fa-spin')).toEqual(true);
expect(classList.contains('fa-spinner')).toEqual(true);
@@ -79,6 +88,7 @@ describe('File Icon component', () => {
const { classList } = vm.$el.firstChild;
const containsSizeClass = classList.contains('s120');
const containsCustomClass = classList.contains('extraclasses');
+
expect(containsSizeClass).toBe(true);
expect(containsCustomClass).toBe(true);
});
diff --git a/spec/javascripts/vue_shared/components/file_row_spec.js b/spec/javascripts/vue_shared/components/file_row_spec.js
index 9914c0b70f3..67752c1c455 100644
--- a/spec/javascripts/vue_shared/components/file_row_spec.js
+++ b/spec/javascripts/vue_shared/components/file_row_spec.js
@@ -71,4 +71,40 @@ describe('RepoFile', () => {
expect(vm.$el.querySelector('.file-row-name').style.marginLeft).toBe('32px');
});
+
+ describe('outputText', () => {
+ beforeEach(done => {
+ createComponent({
+ file: {
+ ...file(),
+ path: 'app/assets/index.js',
+ },
+ level: 0,
+ });
+
+ vm.displayTextKey = 'path';
+
+ vm.$nextTick(done);
+ });
+
+ it('returns text if truncateStart is 0', done => {
+ vm.truncateStart = 0;
+
+ vm.$nextTick(() => {
+ expect(vm.outputText).toBe('app/assets/index.js');
+
+ done();
+ });
+ });
+
+ it('returns text truncated at start', done => {
+ vm.truncateStart = 5;
+
+ vm.$nextTick(() => {
+ expect(vm.outputText).toBe('...ssets/index.js');
+
+ done();
+ });
+ });
+ });
});
diff --git a/spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js b/spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js
new file mode 100644
index 00000000000..b84b5ae67a8
--- /dev/null
+++ b/spec/javascripts/vue_shared/components/filtered_search_dropdown_spec.js
@@ -0,0 +1,91 @@
+import Vue from 'vue';
+import component from '~/vue_shared/components/filtered_search_dropdown.vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+
+describe('Filtered search dropdown', () => {
+ const Component = Vue.extend(component);
+ let vm;
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('with an empty array of items', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ items: [],
+ filterKey: '',
+ });
+ });
+
+ it('renders empty list', () => {
+ expect(vm.$el.querySelectorAll('.js-filtered-dropdown-result').length).toEqual(0);
+ });
+
+ it('renders filter input', () => {
+ expect(vm.$el.querySelector('.js-filtered-dropdown-input')).not.toBeNull();
+ });
+ });
+
+ describe('when visible numbers is less than the items length', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ items: [{ title: 'One' }, { title: 'Two' }, { title: 'Three' }],
+ visibleItems: 2,
+ filterKey: 'title',
+ });
+ });
+
+ it('it renders only the maximum number provided', () => {
+ expect(vm.$el.querySelectorAll('.js-filtered-dropdown-result').length).toEqual(2);
+ });
+ });
+
+ describe('when visible number is bigger than the items length', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ items: [{ title: 'One' }, { title: 'Two' }, { title: 'Three' }],
+ filterKey: 'title',
+ });
+ });
+
+ it('it renders the full list of items the maximum number provided', () => {
+ expect(vm.$el.querySelectorAll('.js-filtered-dropdown-result').length).toEqual(3);
+ });
+ });
+
+ describe('while filtering', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ items: [
+ { title: 'One' },
+ { title: 'Two/three' },
+ { title: 'Three four' },
+ { title: 'Five' },
+ ],
+ filterKey: 'title',
+ });
+ });
+
+ it('updates the results to match the typed value', done => {
+ vm.$el.querySelector('.js-filtered-dropdown-input').value = 'three';
+ vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelectorAll('.js-filtered-dropdown-result').length).toEqual(2);
+ done();
+ });
+ });
+
+ describe('when no value matches the typed one', () => {
+ it('does not render any result', done => {
+ vm.$el.querySelector('.js-filtered-dropdown-input').value = 'six';
+ vm.$el.querySelector('.js-filtered-dropdown-input').dispatchEvent(new Event('input'));
+
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelectorAll('.js-filtered-dropdown-result').length).toEqual(0);
+ done();
+ });
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/vue_shared/components/gl_countdown_spec.js b/spec/javascripts/vue_shared/components/gl_countdown_spec.js
new file mode 100644
index 00000000000..929ffe219f4
--- /dev/null
+++ b/spec/javascripts/vue_shared/components/gl_countdown_spec.js
@@ -0,0 +1,77 @@
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import Vue from 'vue';
+import GlCountdown from '~/vue_shared/components/gl_countdown.vue';
+
+describe('GlCountdown', () => {
+ const Component = Vue.extend(GlCountdown);
+ let vm;
+ let now = '2000-01-01T00:00:00Z';
+
+ beforeEach(() => {
+ spyOn(Date, 'now').and.callFake(() => new Date(now).getTime());
+ jasmine.clock().install();
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ jasmine.clock().uninstall();
+ });
+
+ describe('when there is time remaining', () => {
+ beforeEach(done => {
+ vm = mountComponent(Component, {
+ endDateString: '2000-01-01T01:02:03Z',
+ });
+
+ Vue.nextTick()
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('displays remaining time', () => {
+ expect(vm.$el).toContainText('01:02:03');
+ });
+
+ it('updates remaining time', done => {
+ now = '2000-01-01T00:00:01Z';
+ jasmine.clock().tick(1000);
+
+ Vue.nextTick()
+ .then(() => {
+ expect(vm.$el).toContainText('01:02:02');
+ done();
+ })
+ .catch(done.fail);
+ });
+ });
+
+ describe('when there is no time remaining', () => {
+ beforeEach(done => {
+ vm = mountComponent(Component, {
+ endDateString: '1900-01-01T00:00:00Z',
+ });
+
+ Vue.nextTick()
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('displays 00:00:00', () => {
+ expect(vm.$el).toContainText('00:00:00');
+ });
+ });
+
+ describe('when an invalid date is passed', () => {
+ it('throws a validation error', () => {
+ spyOn(Vue.config, 'warnHandler').and.stub();
+ vm = mountComponent(Component, {
+ endDateString: 'this is invalid',
+ });
+
+ expect(Vue.config.warnHandler).toHaveBeenCalledTimes(1);
+ const [errorMessage] = Vue.config.warnHandler.calls.argsFor(0);
+
+ expect(errorMessage).toMatch(/^Invalid prop: .* "endDateString"/);
+ });
+ });
+});
diff --git a/spec/javascripts/vue_shared/components/gl_modal_spec.js b/spec/javascripts/vue_shared/components/gl_modal_spec.js
index 263824a102a..19af8b5d2f7 100644
--- a/spec/javascripts/vue_shared/components/gl_modal_spec.js
+++ b/spec/javascripts/vue_shared/components/gl_modal_spec.js
@@ -48,6 +48,7 @@ describe('GlModal', () => {
it('sets the modal title', () => {
const modalTitle = vm.$el.querySelector('.modal-title');
+
expect(modalTitle.innerHTML.trim()).toBe(props.headerTitleText);
});
});
@@ -63,6 +64,7 @@ describe('GlModal', () => {
it('sets the primary button class', () => {
const primaryButton = vm.$el.querySelector('.modal-footer button:last-of-type');
+
expect(primaryButton).toHaveClass(`btn-${props.footerPrimaryButtonVariant}`);
});
});
@@ -78,6 +80,7 @@ describe('GlModal', () => {
it('sets the primary button text', () => {
const primaryButton = vm.$el.querySelector('.modal-footer button:last-of-type');
+
expect(primaryButton.innerHTML.trim()).toBe(props.footerPrimaryButtonText);
});
});
@@ -173,6 +176,7 @@ describe('GlModal', () => {
it('sets the modal body', () => {
const modalBody = vm.$el.querySelector('.modal-body');
+
expect(modalBody.innerHTML).toBe(slotContent);
});
});
@@ -184,6 +188,7 @@ describe('GlModal', () => {
it('sets the modal header', () => {
const modalHeader = vm.$el.querySelector('.modal-header');
+
expect(modalHeader.innerHTML).toBe(slotContent);
});
});
@@ -195,6 +200,7 @@ describe('GlModal', () => {
it('sets the modal title', () => {
const modalTitle = vm.$el.querySelector('.modal-title');
+
expect(modalTitle.innerHTML).toBe(slotContent);
});
});
@@ -206,6 +212,7 @@ describe('GlModal', () => {
it('sets the modal footer', () => {
const modalFooter = vm.$el.querySelector('.modal-footer');
+
expect(modalFooter.innerHTML).toBe(slotContent);
});
});
diff --git a/spec/javascripts/vue_shared/components/header_ci_component_spec.js b/spec/javascripts/vue_shared/components/header_ci_component_spec.js
index f17818c17c7..7a741bdc067 100644
--- a/spec/javascripts/vue_shared/components/header_ci_component_spec.js
+++ b/spec/javascripts/vue_shared/components/header_ci_component_spec.js
@@ -59,9 +59,9 @@ describe('Header CI Component', () => {
it('should render status badge', () => {
expect(vm.$el.querySelector('.ci-failed')).toBeDefined();
expect(vm.$el.querySelector('.ci-status-icon-failed svg')).toBeDefined();
- expect(
- vm.$el.querySelector('.ci-failed').getAttribute('href'),
- ).toEqual(props.status.details_path);
+ expect(vm.$el.querySelector('.ci-failed').getAttribute('href')).toEqual(
+ props.status.details_path,
+ );
});
it('should render item name and id', () => {
@@ -73,7 +73,7 @@ describe('Header CI Component', () => {
});
it('should render user icon and name', () => {
- expect(vm.$el.querySelector('.js-user-link').textContent.trim()).toEqual(props.user.name);
+ expect(vm.$el.querySelector('.js-user-link').innerText.trim()).toContain(props.user.name);
});
it('should render provided actions', () => {
@@ -84,7 +84,7 @@ describe('Header CI Component', () => {
expect(vm.$el.querySelector('.link').getAttribute('href')).toEqual(props.actions[0].path);
});
- it('should show loading icon', (done) => {
+ it('should show loading icon', done => {
vm.actions[0].isLoading = true;
Vue.nextTick(() => {
@@ -94,7 +94,7 @@ describe('Header CI Component', () => {
});
it('should render sidebar toggle button', () => {
- expect(vm.$el.querySelector('.js-sidebar-build-toggle')).toBeDefined();
+ expect(vm.$el.querySelector('.js-sidebar-build-toggle')).not.toBeNull();
});
});
diff --git a/spec/javascripts/vue_shared/components/icon_spec.js b/spec/javascripts/vue_shared/components/icon_spec.js
index 01f4649339e..45eef2ad737 100644
--- a/spec/javascripts/vue_shared/components/icon_spec.js
+++ b/spec/javascripts/vue_shared/components/icon_spec.js
@@ -2,11 +2,11 @@ import Vue from 'vue';
import Icon from '~/vue_shared/components/icon.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
-describe('Sprite Icon Component', function () {
- describe('Initialization', function () {
+describe('Sprite Icon Component', function() {
+ describe('Initialization', function() {
let icon;
- beforeEach(function () {
+ beforeEach(function() {
const IconComponent = Vue.extend(Icon);
icon = mountComponent(IconComponent, {
@@ -21,20 +21,20 @@ describe('Sprite Icon Component', function () {
icon.$destroy();
});
- it('should return a defined Vue component', function () {
+ it('should return a defined Vue component', function() {
expect(icon).toBeDefined();
});
- it('should have <svg> as a child element', function () {
+ it('should have <svg> as a child element', function() {
expect(icon.$el.tagName).toBe('svg');
});
- it('should have <use> as a child element with the correct href', function () {
+ it('should have <use> as a child element with the correct href', function() {
expect(icon.$el.firstChild.tagName).toBe('use');
expect(icon.$el.firstChild.getAttribute('xlink:href')).toBe(`${gon.sprite_icons}#commit`);
});
- it('should properly compute iconSizeClass', function () {
+ it('should properly compute iconSizeClass', function() {
expect(icon.iconSizeClass).toBe('s32');
});
@@ -44,10 +44,11 @@ describe('Sprite Icon Component', function () {
expect(icon.$options.props.size.validator(9001)).toBeFalsy();
});
- it('should properly render img css', function () {
+ it('should properly render img css', function() {
const { classList } = icon.$el;
const containsSizeClass = classList.contains('s32');
const containsCustomClass = classList.contains('extraclasses');
+
expect(containsSizeClass).toBe(true);
expect(containsCustomClass).toBe(true);
});
diff --git a/spec/javascripts/vue_shared/components/identicon_spec.js b/spec/javascripts/vue_shared/components/identicon_spec.js
index 0719800c682..0b3dbb61c96 100644
--- a/spec/javascripts/vue_shared/components/identicon_spec.js
+++ b/spec/javascripts/vue_shared/components/identicon_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import identiconComponent from '~/vue_shared/components/identicon.vue';
-const createComponent = (sizeClass) => {
+const createComponent = sizeClass => {
const Component = Vue.extend(identiconComponent);
return new Component({
diff --git a/spec/javascripts/vue_shared/components/issue/issue_warning_spec.js b/spec/javascripts/vue_shared/components/issue/issue_warning_spec.js
index e6ed77dbb52..aa7d6ea2e34 100644
--- a/spec/javascripts/vue_shared/components/issue/issue_warning_spec.js
+++ b/spec/javascripts/vue_shared/components/issue/issue_warning_spec.js
@@ -6,7 +6,10 @@ const IssueWarning = Vue.extend(issueWarning);
function formatWarning(string) {
// Replace newlines with a space then replace multiple spaces with one space
- return string.trim().replace(/\n/g, ' ').replace(/\s\s+/g, ' ');
+ return string
+ .trim()
+ .replace(/\n/g, ' ')
+ .replace(/\s\s+/g, ' ');
}
describe('Issue Warning Component', () => {
@@ -17,7 +20,9 @@ describe('Issue Warning Component', () => {
});
expect(vm.$el.querySelector('.icon use').href.baseVal).toMatch(/lock$/);
- expect(formatWarning(vm.$el.querySelector('span').textContent)).toEqual('This issue is locked. Only project members can comment.');
+ expect(formatWarning(vm.$el.querySelector('span').textContent)).toEqual(
+ 'This issue is locked. Only project members can comment.',
+ );
});
});
@@ -28,7 +33,9 @@ describe('Issue Warning Component', () => {
});
expect(vm.$el.querySelector('.icon use').href.baseVal).toMatch(/eye-slash$/);
- expect(formatWarning(vm.$el.querySelector('span').textContent)).toEqual('This is a confidential issue. Your comment will not be visible to the public.');
+ expect(formatWarning(vm.$el.querySelector('span').textContent)).toEqual(
+ 'This is a confidential issue. Your comment will not be visible to the public.',
+ );
});
});
@@ -40,7 +47,9 @@ describe('Issue Warning Component', () => {
});
expect(vm.$el.querySelector('.icon')).toBeFalsy();
- expect(formatWarning(vm.$el.querySelector('span').textContent)).toEqual('This issue is confidential and locked. People without permission will never get a notification and won\'t be able to comment.');
+ expect(formatWarning(vm.$el.querySelector('span').textContent)).toEqual(
+ "This issue is confidential and locked. People without permission will never get a notification and won't be able to comment.",
+ );
});
});
});
diff --git a/spec/javascripts/vue_shared/components/loading_button_spec.js b/spec/javascripts/vue_shared/components/loading_button_spec.js
index 51c19cd4080..db89d4a934c 100644
--- a/spec/javascripts/vue_shared/components/loading_button_spec.js
+++ b/spec/javascripts/vue_shared/components/loading_button_spec.js
@@ -4,7 +4,7 @@ import mountComponent from 'spec/helpers/vue_mount_component_helper';
const LABEL = 'Hello';
-describe('LoadingButton', function () {
+describe('LoadingButton', function() {
let vm;
let LoadingButton;
@@ -69,6 +69,7 @@ describe('LoadingButton', function () {
describe('container class', () => {
it('should default to btn btn-align-content', () => {
vm = mountComponent(LoadingButton, {});
+
expect(vm.$el.classList.contains('btn')).toEqual(true);
expect(vm.$el.classList.contains('btn-align-content')).toEqual(true);
});
@@ -77,6 +78,7 @@ describe('LoadingButton', function () {
vm = mountComponent(LoadingButton, {
containerClass: 'test-class',
});
+
expect(vm.$el.classList.contains('btn')).toEqual(false);
expect(vm.$el.classList.contains('btn-align-content')).toEqual(false);
expect(vm.$el.classList.contains('test-class')).toEqual(true);
diff --git a/spec/javascripts/vue_shared/components/markdown/field_spec.js b/spec/javascripts/vue_shared/components/markdown/field_spec.js
index 69034975422..abb17440c0e 100644
--- a/spec/javascripts/vue_shared/components/markdown/field_spec.js
+++ b/spec/javascripts/vue_shared/components/markdown/field_spec.js
@@ -11,7 +11,7 @@ function assertMarkdownTabs(isWrite, writeLink, previewLink, vm) {
describe('Markdown field component', () => {
let vm;
- beforeEach((done) => {
+ beforeEach(done => {
vm = new Vue({
components: {
fieldComponent,
@@ -39,9 +39,7 @@ describe('Markdown field component', () => {
describe('mounted', () => {
it('renders textarea inside backdrop', () => {
- expect(
- vm.$el.querySelector('.zen-backdrop textarea'),
- ).not.toBeNull();
+ expect(vm.$el.querySelector('.zen-backdrop textarea')).not.toBeNull();
});
describe('markdown preview', () => {
@@ -49,73 +47,70 @@ describe('Markdown field component', () => {
let writeLink;
beforeEach(() => {
- spyOn(Vue.http, 'post').and.callFake(() => new Promise((resolve) => {
- setTimeout(() => {
- resolve({
- json() {
- return {
- body: '<p>markdown preview</p>',
- };
- },
- });
- });
- }));
+ spyOn(Vue.http, 'post').and.callFake(
+ () =>
+ new Promise(resolve => {
+ setTimeout(() => {
+ resolve({
+ json() {
+ return {
+ body: '<p>markdown preview</p>',
+ };
+ },
+ });
+ });
+ }),
+ );
previewLink = vm.$el.querySelector('.nav-links .js-preview-link');
writeLink = vm.$el.querySelector('.nav-links .js-write-link');
});
- it('sets preview link as active', (done) => {
+ it('sets preview link as active', done => {
previewLink.click();
Vue.nextTick(() => {
- expect(
- previewLink.parentNode.classList.contains('active'),
- ).toBeTruthy();
+ expect(previewLink.parentNode.classList.contains('active')).toBeTruthy();
done();
});
});
- it('shows preview loading text', (done) => {
+ it('shows preview loading text', done => {
previewLink.click();
Vue.nextTick(() => {
- expect(
- vm.$el.querySelector('.md-preview').textContent.trim(),
- ).toContain('Loading...');
+ expect(vm.$el.querySelector('.md-preview').textContent.trim()).toContain('Loading...');
done();
});
});
- it('renders markdown preview', (done) => {
+ it('renders markdown preview', done => {
previewLink.click();
setTimeout(() => {
- expect(
- vm.$el.querySelector('.md-preview').innerHTML,
- ).toContain('<p>markdown preview</p>');
+ expect(vm.$el.querySelector('.md-preview').innerHTML).toContain(
+ '<p>markdown preview</p>',
+ );
done();
});
});
- it('renders GFM with jQuery', (done) => {
+ it('renders GFM with jQuery', done => {
spyOn($.fn, 'renderGFM');
previewLink.click();
setTimeout(() => {
- expect(
- $.fn.renderGFM,
- ).toHaveBeenCalled();
+ expect($.fn.renderGFM).toHaveBeenCalled();
done();
}, 0);
});
- it('clicking already active write or preview link does nothing', (done) => {
+ it('clicking already active write or preview link does nothing', done => {
writeLink.click();
Vue.nextTick()
.then(() => assertMarkdownTabs(true, writeLink, previewLink, vm))
@@ -134,46 +129,40 @@ describe('Markdown field component', () => {
});
describe('markdown buttons', () => {
- it('converts single words', (done) => {
+ it('converts single words', done => {
const textarea = vm.$el.querySelector('textarea');
textarea.setSelectionRange(0, 7);
vm.$el.querySelector('.js-md').click();
Vue.nextTick(() => {
- expect(
- textarea.value,
- ).toContain('**testing**');
+ expect(textarea.value).toContain('**testing**');
done();
});
});
- it('converts a line', (done) => {
+ it('converts a line', done => {
const textarea = vm.$el.querySelector('textarea');
textarea.setSelectionRange(0, 0);
- vm.$el.querySelectorAll('.js-md')[4].click();
+ vm.$el.querySelectorAll('.js-md')[5].click();
Vue.nextTick(() => {
- expect(
- textarea.value,
- ).toContain('* testing');
+ expect(textarea.value).toContain('* testing');
done();
});
});
- it('converts multiple lines', (done) => {
+ it('converts multiple lines', done => {
const textarea = vm.$el.querySelector('textarea');
textarea.setSelectionRange(0, 50);
- vm.$el.querySelectorAll('.js-md')[4].click();
+ vm.$el.querySelectorAll('.js-md')[5].click();
Vue.nextTick(() => {
- expect(
- textarea.value,
- ).toContain('* testing\n* 123');
+ expect(textarea.value).toContain('* testing\n* 123');
done();
});
diff --git a/spec/javascripts/vue_shared/components/markdown/header_spec.js b/spec/javascripts/vue_shared/components/markdown/header_spec.js
index 488575df401..59613faa49f 100644
--- a/spec/javascripts/vue_shared/components/markdown/header_spec.js
+++ b/spec/javascripts/vue_shared/components/markdown/header_spec.js
@@ -17,8 +17,24 @@ describe('Markdown field header component', () => {
Vue.nextTick(done);
});
- it('renders markdown buttons', () => {
- expect(vm.$el.querySelectorAll('.js-md').length).toBe(7);
+ it('renders markdown header buttons', () => {
+ const buttons = [
+ 'Add bold text',
+ 'Add italic text',
+ 'Insert a quote',
+ 'Insert code',
+ 'Add a link',
+ 'Add a bullet list',
+ 'Add a numbered list',
+ 'Add a task list',
+ 'Add a table',
+ 'Go full screen',
+ ];
+ const elements = vm.$el.querySelectorAll('.toolbar-btn');
+
+ elements.forEach((buttonEl, index) => {
+ expect(buttonEl.getAttribute('data-original-title')).toBe(buttons[index]);
+ });
});
it('renders `write` link as active when previewMarkdown is false', () => {
@@ -51,14 +67,16 @@ describe('Markdown field header component', () => {
spyOn(vm, '$emit');
$(document).triggerHandler('markdown-preview:show', [
- $('<form><div class="js-vue-markdown-field"><textarea class="markdown-area"></textarea></div></form>'),
+ $(
+ '<form><div class="js-vue-markdown-field"><textarea class="markdown-area"></textarea></div></form>',
+ ),
]);
expect(vm.$emit).not.toHaveBeenCalled();
});
it('blurs preview link after click', done => {
- const link = vm.$el.querySelector('li:nth-child(2) a');
+ const link = vm.$el.querySelector('li:nth-child(2) button');
spyOn(HTMLElement.prototype, 'blur');
link.click();
@@ -69,4 +87,10 @@ describe('Markdown field header component', () => {
done();
});
});
+
+ it('renders markdown table template', () => {
+ expect(vm.mdTable).toEqual(
+ '| header | header |\n| ------ | ------ |\n| cell | cell |\n| cell | cell |',
+ );
+ });
});
diff --git a/spec/javascripts/vue_shared/components/markdown/toolbar_spec.js b/spec/javascripts/vue_shared/components/markdown/toolbar_spec.js
index 3e708f865c8..e6c7abd9d3b 100644
--- a/spec/javascripts/vue_shared/components/markdown/toolbar_spec.js
+++ b/spec/javascripts/vue_shared/components/markdown/toolbar_spec.js
@@ -25,9 +25,12 @@ describe('toolbar', () => {
describe('user cannot attach file', () => {
beforeEach(() => {
- vm = mountComponent(Toolbar, Object.assign({}, props, {
- canAttachFile: false,
- }));
+ vm = mountComponent(
+ Toolbar,
+ Object.assign({}, props, {
+ canAttachFile: false,
+ }),
+ );
});
it('should not render uploading-container', () => {
diff --git a/spec/javascripts/vue_shared/components/memory_graph_spec.js b/spec/javascripts/vue_shared/components/memory_graph_spec.js
index 65d8ed39ade..78c3ae3ddb3 100644
--- a/spec/javascripts/vue_shared/components/memory_graph_spec.js
+++ b/spec/javascripts/vue_shared/components/memory_graph_spec.js
@@ -52,8 +52,9 @@ describe('MemoryGraph', () => {
it('should show human readable median value based on provided median timestamp', () => {
vm.deploymentTime = mockMedian;
const formattedMedian = vm.getFormattedMedian;
- expect(formattedMedian.indexOf('Deployed') > -1).toBeTruthy();
- expect(formattedMedian.indexOf('ago') > -1).toBeTruthy();
+
+ expect(formattedMedian.indexOf('Deployed')).toBeGreaterThan(-1);
+ expect(formattedMedian.indexOf('ago')).toBeGreaterThan(-1);
});
});
});
@@ -62,6 +63,7 @@ describe('MemoryGraph', () => {
describe('getMedianMetricIndex', () => {
it('should return index of closest metric timestamp to that of median', () => {
const matchingIndex = vm.getMedianMetricIndex(mockMedian, mockMetrics);
+
expect(matchingIndex).toBe(mockMedianIndex);
});
});
@@ -69,6 +71,7 @@ describe('MemoryGraph', () => {
describe('getGraphPlotValues', () => {
it('should return Object containing values to plot graph', () => {
const plotValues = vm.getGraphPlotValues(mockMedian, mockMetrics);
+
expect(plotValues.pathD).toBeDefined();
expect(Array.isArray(plotValues.pathD)).toBeTruthy();
@@ -90,7 +93,7 @@ describe('MemoryGraph', () => {
expect(el.querySelector('svg')).toBeDefined();
});
- it('should render graph when renderGraph is called internally', (done) => {
+ it('should render graph when renderGraph is called internally', done => {
const { pathD, pathViewBox, dotX, dotY } = vm.getGraphPlotValues(mockMedian, mockMetrics);
vm.height = defaultHeight;
vm.width = defaultWidth;
@@ -101,16 +104,21 @@ describe('MemoryGraph', () => {
Vue.nextTick(() => {
const svgEl = el.querySelector('svg');
+
expect(svgEl).toBeDefined();
expect(svgEl.getAttribute('height')).toBe(defaultHeight);
expect(svgEl.getAttribute('width')).toBe(defaultWidth);
const pathEl = el.querySelector('path');
+
expect(pathEl).toBeDefined();
expect(pathEl.getAttribute('d')).toBe(`M ${pathD}`);
- expect(pathEl.getAttribute('viewBox')).toBe(`0 0 ${pathViewBox.lineWidth} ${pathViewBox.diff}`);
+ expect(pathEl.getAttribute('viewBox')).toBe(
+ `0 0 ${pathViewBox.lineWidth} ${pathViewBox.diff}`,
+ );
const circleEl = el.querySelector('circle');
+
expect(circleEl).toBeDefined();
expect(circleEl.getAttribute('r')).toBe('1.5');
expect(circleEl.getAttribute('transform')).toBe('translate(0 -1)');
diff --git a/spec/javascripts/vue_shared/components/navigation_tabs_spec.js b/spec/javascripts/vue_shared/components/navigation_tabs_spec.js
index 09fda95d7d3..462bfc10664 100644
--- a/spec/javascripts/vue_shared/components/navigation_tabs_spec.js
+++ b/spec/javascripts/vue_shared/components/navigation_tabs_spec.js
@@ -46,7 +46,9 @@ describe('navigation tabs component', () => {
it('should render badge', () => {
expect(vm.$el.querySelector('.js-pipelines-tab-all .badge').textContent.trim()).toEqual('1');
- expect(vm.$el.querySelector('.js-pipelines-tab-pending .badge').textContent.trim()).toEqual('0');
+ expect(vm.$el.querySelector('.js-pipelines-tab-pending .badge').textContent.trim()).toEqual(
+ '0',
+ );
});
it('should not render badge', () => {
@@ -56,6 +58,7 @@ describe('navigation tabs component', () => {
it('should trigger onTabClick', () => {
spyOn(vm, '$emit');
vm.$el.querySelector('.js-pipelines-tab-pending').click();
+
expect(vm.$emit).toHaveBeenCalledWith('onChangeTab', 'pending');
});
});
diff --git a/spec/javascripts/vue_shared/components/notes/placeholder_note_spec.js b/spec/javascripts/vue_shared/components/notes/placeholder_note_spec.js
index db665fdaad3..45f131194ca 100644
--- a/spec/javascripts/vue_shared/components/notes/placeholder_note_spec.js
+++ b/spec/javascripts/vue_shared/components/notes/placeholder_note_spec.js
@@ -26,6 +26,7 @@ describe('issue placeholder system note component', () => {
expect(vm.$el.querySelector('.user-avatar-link').getAttribute('href')).toEqual(
userDataMock.path,
);
+
expect(vm.$el.querySelector('.user-avatar-link img').getAttribute('src')).toEqual(
`${userDataMock.avatar_url}?width=40`,
);
@@ -37,6 +38,7 @@ describe('issue placeholder system note component', () => {
expect(vm.$el.querySelector('.note-header-info a').getAttribute('href')).toEqual(
userDataMock.path,
);
+
expect(
vm.$el.querySelector('.note-header-info .note-headline-light').textContent.trim(),
).toEqual(`@${userDataMock.username}`);
diff --git a/spec/javascripts/vue_shared/components/notes/placeholder_system_note_spec.js b/spec/javascripts/vue_shared/components/notes/placeholder_system_note_spec.js
index 262571efcb8..6013e85811a 100644
--- a/spec/javascripts/vue_shared/components/notes/placeholder_system_note_spec.js
+++ b/spec/javascripts/vue_shared/components/notes/placeholder_system_note_spec.js
@@ -20,6 +20,8 @@ describe('placeholder system note component', () => {
});
expect(vm.$el.tagName).toEqual('LI');
- expect(vm.$el.querySelector('.timeline-content em').textContent.trim()).toEqual('This is a placeholder');
+ expect(vm.$el.querySelector('.timeline-content em').textContent.trim()).toEqual(
+ 'This is a placeholder',
+ );
});
});
diff --git a/spec/javascripts/vue_shared/components/notes/timeline_entry_item_spec.js b/spec/javascripts/vue_shared/components/notes/timeline_entry_item_spec.js
new file mode 100644
index 00000000000..c15635f2105
--- /dev/null
+++ b/spec/javascripts/vue_shared/components/notes/timeline_entry_item_spec.js
@@ -0,0 +1,40 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
+
+describe(TimelineEntryItem.name, () => {
+ let wrapper;
+
+ const factory = (options = {}) => {
+ const localVue = createLocalVue();
+
+ wrapper = shallowMount(TimelineEntryItem, {
+ localVue,
+ ...options,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders correctly', () => {
+ factory();
+
+ expect(wrapper.is('.timeline-entry')).toBe(true);
+
+ expect(wrapper.contains('.timeline-entry-inner')).toBe(true);
+ });
+
+ it('accepts default slot', () => {
+ const dummyContent = '<p>some content</p>';
+ factory({
+ slots: {
+ default: dummyContent,
+ },
+ });
+
+ const content = wrapper.find('.timeline-entry-inner :first-child');
+
+ expect(content.html()).toBe(dummyContent);
+ });
+});
diff --git a/spec/javascripts/vue_shared/components/pagination_links_spec.js b/spec/javascripts/vue_shared/components/pagination_links_spec.js
index c9d183872b4..d0cb3731050 100644
--- a/spec/javascripts/vue_shared/components/pagination_links_spec.js
+++ b/spec/javascripts/vue_shared/components/pagination_links_spec.js
@@ -23,13 +23,10 @@ describe('Pagination links component', () => {
let destinationComponent;
beforeEach(() => {
- paginationLinks = mountComponent(
- paginationLinksComponent,
- {
- change,
- pageInfo,
- },
- );
+ paginationLinks = mountComponent(paginationLinksComponent, {
+ change,
+ pageInfo,
+ });
[glPagination] = paginationLinks.$children;
[destinationComponent] = glPagination.$children;
});
@@ -39,34 +36,24 @@ describe('Pagination links component', () => {
});
it('should provide translated text to GitLab UI pagination', () => {
- Object.entries(translations).forEach(entry =>
- expect(
- destinationComponent[entry[0]],
- ).toBe(entry[1]),
- );
+ Object.entries(translations).forEach(entry => {
+ expect(destinationComponent[entry[0]]).toBe(entry[1]);
+ });
});
it('should pass change to GitLab UI pagination', () => {
- expect(
- Object.is(glPagination.change, change),
- ).toBe(true);
+ expect(Object.is(glPagination.change, change)).toBe(true);
});
it('should pass page from pageInfo to GitLab UI pagination', () => {
- expect(
- destinationComponent.value,
- ).toBe(pageInfo.page);
+ expect(destinationComponent.value).toBe(pageInfo.page);
});
it('should pass per page from pageInfo to GitLab UI pagination', () => {
- expect(
- destinationComponent.perPage,
- ).toBe(pageInfo.perPage);
+ expect(destinationComponent.perPage).toBe(pageInfo.perPage);
});
it('should pass total items from pageInfo to GitLab UI pagination', () => {
- expect(
- destinationComponent.totalRows,
- ).toBe(pageInfo.total);
+ expect(destinationComponent.totalRows).toBe(pageInfo.total);
});
});
diff --git a/spec/javascripts/vue_shared/components/panel_resizer_spec.js b/spec/javascripts/vue_shared/components/panel_resizer_spec.js
index f1e62069462..49a580be06b 100644
--- a/spec/javascripts/vue_shared/components/panel_resizer_spec.js
+++ b/spec/javascripts/vue_shared/components/panel_resizer_spec.js
@@ -8,8 +8,23 @@ describe('Panel Resizer component', () => {
const triggerEvent = (eventName, el = vm.$el, clientX = 0) => {
const event = document.createEvent('MouseEvents');
- event.initMouseEvent(eventName, true, true, window, 1, clientX, 0, clientX, 0, false, false,
- false, false, 0, null);
+ event.initMouseEvent(
+ eventName,
+ true,
+ true,
+ window,
+ 1,
+ clientX,
+ 0,
+ clientX,
+ 0,
+ false,
+ false,
+ false,
+ false,
+ 0,
+ null,
+ );
el.dispatchEvent(event);
};
@@ -53,7 +68,13 @@ describe('Panel Resizer component', () => {
triggerEvent('mousedown', vm.$el);
triggerEvent('mousemove', document);
triggerEvent('mouseup', document);
- expect(vm.$emit.calls.allArgs()).toEqual([['resize-start', 100], ['update:size', 100], ['resize-end', 100]]);
+
+ expect(vm.$emit.calls.allArgs()).toEqual([
+ ['resize-start', 100],
+ ['update:size', 100],
+ ['resize-end', 100],
+ ]);
+
expect(vm.size).toBe(100);
});
});
diff --git a/spec/javascripts/vue_shared/components/pikaday_spec.js b/spec/javascripts/vue_shared/components/pikaday_spec.js
index b349e2a2a81..61f05e7a230 100644
--- a/spec/javascripts/vue_shared/components/pikaday_spec.js
+++ b/spec/javascripts/vue_shared/components/pikaday_spec.js
@@ -24,6 +24,7 @@ describe('datePicker', () => {
vm.$on('hidePicker', hidePicker);
vm.$el.querySelector('.dropdown-menu-toggle').click();
+
expect(hidePicker).toHaveBeenCalled();
});
});
diff --git a/spec/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js b/spec/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js
index 8c296af6652..6bff1521695 100644
--- a/spec/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js
+++ b/spec/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon_spec.js
@@ -30,6 +30,7 @@ describe('collapsedCalendarIcon', () => {
vm.$on('click', click);
vm.$el.click();
+
expect(click).toHaveBeenCalled();
});
});
diff --git a/spec/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js b/spec/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
index 9d60f9c758f..c507a97d37e 100644
--- a/spec/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
+++ b/spec/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
@@ -11,36 +11,22 @@ describe('collapsedGroupedDatePicker', () => {
});
});
- it('should render toggle sidebar if showToggleSidebar', (done) => {
- expect(vm.$el.querySelector('.issuable-sidebar-header')).toBeDefined();
-
- vm.showToggleSidebar = false;
- Vue.nextTick(() => {
- expect(vm.$el.querySelector('.issuable-sidebar-header')).toBeNull();
- done();
- });
- });
-
describe('toggleCollapse events', () => {
- beforeEach((done) => {
+ beforeEach(done => {
spyOn(vm, 'toggleSidebar');
vm.minDate = new Date('07/17/2016');
Vue.nextTick(done);
});
- it('should emit when sidebar is toggled', () => {
- vm.$el.querySelector('.gutter-toggle').click();
- expect(vm.toggleSidebar).toHaveBeenCalled();
- });
-
it('should emit when collapsed-calendar-icon is clicked', () => {
vm.$el.querySelector('.sidebar-collapsed-icon').click();
+
expect(vm.toggleSidebar).toHaveBeenCalled();
});
});
describe('minDate and maxDate', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm.minDate = new Date('07/17/2016');
vm.maxDate = new Date('07/17/2017');
Vue.nextTick(done);
@@ -48,6 +34,7 @@ describe('collapsedGroupedDatePicker', () => {
it('should render both collapsed-calendar-icon', () => {
const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
+
expect(icons.length).toEqual(2);
expect(icons[0].innerText.trim()).toEqual('Jul 17 2016');
expect(icons[1].innerText.trim()).toEqual('Jul 17 2017');
@@ -55,26 +42,28 @@ describe('collapsedGroupedDatePicker', () => {
});
describe('minDate', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm.minDate = new Date('07/17/2016');
Vue.nextTick(done);
});
it('should render minDate in collapsed-calendar-icon', () => {
const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
+
expect(icons.length).toEqual(1);
expect(icons[0].innerText.trim()).toEqual('From Jul 17 2016');
});
});
describe('maxDate', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm.maxDate = new Date('07/17/2017');
Vue.nextTick(done);
});
it('should render maxDate in collapsed-calendar-icon', () => {
const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
+
expect(icons.length).toEqual(1);
expect(icons[0].innerText.trim()).toEqual('Until Jul 17 2017');
});
@@ -83,8 +72,15 @@ describe('collapsedGroupedDatePicker', () => {
describe('no dates', () => {
it('should render None', () => {
const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
+
expect(icons.length).toEqual(1);
expect(icons[0].innerText.trim()).toEqual('None');
});
+
+ it('should have tooltip as `Start and due date`', () => {
+ const icons = vm.$el.querySelectorAll('.sidebar-collapsed-icon');
+
+ expect(icons[0].dataset.originalTitle).toBe('Start and due date');
+ });
});
});
diff --git a/spec/javascripts/vue_shared/components/sidebar/date_picker_spec.js b/spec/javascripts/vue_shared/components/sidebar/date_picker_spec.js
index 8840a5a9dbf..805ba7b9947 100644
--- a/spec/javascripts/vue_shared/components/sidebar/date_picker_spec.js
+++ b/spec/javascripts/vue_shared/components/sidebar/date_picker_spec.js
@@ -17,6 +17,7 @@ describe('sidebarDatePicker', () => {
vm.$on('toggleCollapse', toggleCollapse);
vm.$el.querySelector('.issuable-sidebar-header .gutter-toggle').click();
+
expect(toggleCollapse).toHaveBeenCalled();
});
@@ -40,7 +41,7 @@ describe('sidebarDatePicker', () => {
expect(vm.$el.querySelector('.value-content span').innerText.trim()).toEqual('None');
});
- it('should render date-picker when editing', (done) => {
+ it('should render date-picker when editing', done => {
vm.editing = true;
Vue.nextTick(() => {
expect(vm.$el.querySelector('.pika-label')).toBeDefined();
@@ -49,7 +50,7 @@ describe('sidebarDatePicker', () => {
});
describe('editable', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm.editable = true;
Vue.nextTick(done);
});
@@ -58,17 +59,18 @@ describe('sidebarDatePicker', () => {
expect(vm.$el.querySelector('.title .btn-blank').innerText.trim()).toEqual('Edit');
});
- it('should enable editing when edit button is clicked', (done) => {
+ it('should enable editing when edit button is clicked', done => {
vm.isLoading = false;
Vue.nextTick(() => {
vm.$el.querySelector('.title .btn-blank').click();
+
expect(vm.editing).toEqual(true);
done();
});
});
});
- it('should render date if selectedDate', (done) => {
+ it('should render date if selectedDate', done => {
vm.selectedDate = new Date('07/07/2017');
Vue.nextTick(() => {
expect(vm.$el.querySelector('.value-content strong').innerText.trim()).toEqual('Jul 7, 2017');
@@ -77,7 +79,7 @@ describe('sidebarDatePicker', () => {
});
describe('selectedDate and editable', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm.selectedDate = new Date('07/07/2017');
vm.editable = true;
Vue.nextTick(done);
@@ -92,12 +94,13 @@ describe('sidebarDatePicker', () => {
vm.$on('saveDate', saveDate);
vm.$el.querySelector('.value-content .btn-blank').click();
+
expect(saveDate).toHaveBeenCalled();
});
});
describe('showToggleSidebar', () => {
- beforeEach((done) => {
+ beforeEach(done => {
vm.showToggleSidebar = true;
Vue.nextTick(done);
});
@@ -111,6 +114,7 @@ describe('sidebarDatePicker', () => {
vm.$on('toggleCollapse', toggleCollapse);
vm.$el.querySelector('.title .gutter-toggle').click();
+
expect(toggleCollapse).toHaveBeenCalled();
});
});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/base_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/base_spec.js
index e8685ab48be..c44b04009ca 100644
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/base_spec.js
+++ b/spec/javascripts/vue_shared/components/sidebar/labels_select/base_spec.js
@@ -33,6 +33,7 @@ describe('BaseComponent', () => {
it('returns correct string when showCreate prop is `false`', () => {
const mockConfigNonEditable = Object.assign({}, mockConfig, { showCreate: false });
const vmNonEditable = createComponent(mockConfigNonEditable);
+
expect(vmNonEditable.hiddenInputName).toBe('label_id[]');
vmNonEditable.$destroy();
});
@@ -46,6 +47,7 @@ describe('BaseComponent', () => {
it('return `Create group label` when `isProject` prop is false', () => {
const mockConfigGroup = Object.assign({}, mockConfig, { isProject: false });
const vmGroup = createComponent(mockConfigGroup);
+
expect(vmGroup.createLabelTitle).toBe('Create group label');
vmGroup.$destroy();
});
@@ -59,6 +61,7 @@ describe('BaseComponent', () => {
it('return `Manage group labels` when `isProject` prop is false', () => {
const mockConfigGroup = Object.assign({}, mockConfig, { isProject: false });
const vmGroup = createComponent(mockConfigGroup);
+
expect(vmGroup.manageLabelsTitle).toBe('Manage group labels');
vmGroup.$destroy();
});
@@ -70,6 +73,7 @@ describe('BaseComponent', () => {
it('emits onLabelClick event with label and list of labels as params', () => {
spyOn(vm, '$emit');
vm.handleClick(mockLabels[0]);
+
expect(vm.$emit).toHaveBeenCalledWith('onLabelClick', mockLabels[0]);
});
});
@@ -78,6 +82,7 @@ describe('BaseComponent', () => {
it('emits toggleCollapse event on component', () => {
spyOn(vm, '$emit');
vm.handleCollapsedValueClick();
+
expect(vm.$emit).toHaveBeenCalledWith('toggleCollapse');
});
});
@@ -86,6 +91,7 @@ describe('BaseComponent', () => {
it('emits onDropdownClose event on component', () => {
spyOn(vm, '$emit');
vm.handleDropdownHidden();
+
expect(vm.$emit).toHaveBeenCalledWith('onDropdownClose');
});
});
@@ -114,6 +120,7 @@ describe('BaseComponent', () => {
it('renders `.dropdown-menu` element', () => {
const dropdownMenuEl = vm.$el.querySelector('.dropdown-menu');
+
expect(dropdownMenuEl).not.toBeNull();
expect(dropdownMenuEl.querySelector('.dropdown-page-one')).not.toBeNull();
expect(dropdownMenuEl.querySelector('.dropdown-content')).not.toBeNull();
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js
index f25c70db125..5cf6afebd7e 100644
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js
+++ b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_button_spec.js
@@ -34,6 +34,7 @@ describe('DropdownButtonComponent', () => {
it('returns text as `Label` when `labels` prop is empty array', () => {
const mockEmptyLabels = Object.assign({}, componentConfig, { labels: [] });
const vmEmptyLabels = createComponent(mockEmptyLabels);
+
expect(vmEmptyLabels.dropdownToggleText).toBe('Label');
vmEmptyLabels.$destroy();
});
@@ -43,6 +44,7 @@ describe('DropdownButtonComponent', () => {
labels: mockLabels.concat(mockLabels),
});
const vmMoreLabels = createComponent(mockMoreLabels);
+
expect(vmMoreLabels.dropdownToggleText).toBe('Foo Label +1 more');
vmMoreLabels.$destroy();
});
@@ -69,12 +71,14 @@ describe('DropdownButtonComponent', () => {
it('renders dropdown toggle text element', () => {
const dropdownToggleTextEl = vm.$el.querySelector('.dropdown-toggle-text');
+
expect(dropdownToggleTextEl).not.toBeNull();
expect(dropdownToggleTextEl.innerText.trim()).toBe('Foo Label');
});
it('renders dropdown button icon', () => {
const dropdownIconEl = vm.$el.querySelector('i.fa');
+
expect(dropdownIconEl).not.toBeNull();
expect(dropdownIconEl.classList.contains('fa-chevron-down')).toBe(true);
});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js
index ce559fe0335..b8f32f96332 100644
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js
+++ b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label_spec.js
@@ -6,7 +6,7 @@ import mountComponent from 'spec/helpers/vue_mount_component_helper';
import { mockSuggestedColors } from './mock_data';
-const createComponent = (headerTitle) => {
+const createComponent = headerTitle => {
const Component = Vue.extend(dropdownCreateLabelComponent);
return mountComponent(Component, {
@@ -38,13 +38,17 @@ describe('DropdownCreateLabelComponent', () => {
});
it('renders `Go back` button on component header', () => {
- const backButtonEl = vm.$el.querySelector('.dropdown-title button.dropdown-title-button.dropdown-menu-back');
+ const backButtonEl = vm.$el.querySelector(
+ '.dropdown-title button.dropdown-title-button.dropdown-menu-back',
+ );
+
expect(backButtonEl).not.toBe(null);
expect(backButtonEl.querySelector('.fa-arrow-left')).not.toBe(null);
});
it('renders component header element as `Create new label` when `headerTitle` prop is not provided', () => {
const headerEl = vm.$el.querySelector('.dropdown-title');
+
expect(headerEl.innerText.trim()).toContain('Create new label');
});
@@ -52,12 +56,16 @@ describe('DropdownCreateLabelComponent', () => {
const headerTitle = 'Create project label';
const vmWithHeaderTitle = createComponent(headerTitle);
const headerEl = vmWithHeaderTitle.$el.querySelector('.dropdown-title');
+
expect(headerEl.innerText.trim()).toContain(headerTitle);
vmWithHeaderTitle.$destroy();
});
it('renders `Close` button on component header', () => {
- const closeButtonEl = vm.$el.querySelector('.dropdown-title button.dropdown-title-button.dropdown-menu-close');
+ const closeButtonEl = vm.$el.querySelector(
+ '.dropdown-title button.dropdown-title-button.dropdown-menu-close',
+ );
+
expect(closeButtonEl).not.toBe(null);
expect(closeButtonEl.querySelector('.fa-times.dropdown-menu-close-icon')).not.toBe(null);
});
@@ -69,23 +77,29 @@ describe('DropdownCreateLabelComponent', () => {
it('renders suggested colors list elements', () => {
const colorsListContainerEl = vm.$el.querySelector('.suggest-colors.suggest-colors-dropdown');
+
expect(colorsListContainerEl).not.toBe(null);
expect(colorsListContainerEl.querySelectorAll('a').length).toBe(mockSuggestedColors.length);
const colorItemEl = colorsListContainerEl.querySelectorAll('a')[0];
+
expect(colorItemEl.dataset.color).toBe(vm.suggestedColors[0]);
expect(colorItemEl.getAttribute('style')).toBe('background-color: rgb(0, 51, 204);');
});
it('renders color input element', () => {
expect(vm.$el.querySelector('.dropdown-label-color-input')).not.toBe(null);
- expect(vm.$el.querySelector('.dropdown-label-color-preview.js-dropdown-label-color-preview')).not.toBe(null);
+ expect(
+ vm.$el.querySelector('.dropdown-label-color-preview.js-dropdown-label-color-preview'),
+ ).not.toBe(null);
+
expect(vm.$el.querySelector('input#new_label_color.default-dropdown-input')).not.toBe(null);
});
it('renders component action buttons', () => {
const createBtnEl = vm.$el.querySelector('button.js-new-label-btn');
const cancelBtnEl = vm.$el.querySelector('button.js-cancel-label-btn');
+
expect(createBtnEl).not.toBe(null);
expect(createBtnEl.innerText.trim()).toBe('Create');
expect(cancelBtnEl.innerText.trim()).toBe('Cancel');
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js
index debeab25bd6..3711e9dac8c 100644
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js
+++ b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_footer_spec.js
@@ -36,19 +36,24 @@ describe('DropdownFooterComponent', () => {
describe('template', () => {
it('renders link element with `Create new label` when `createLabelTitle` prop is not provided', () => {
const createLabelEl = vm.$el.querySelector('.dropdown-footer-list .dropdown-toggle-page');
+
expect(createLabelEl).not.toBeNull();
expect(createLabelEl.innerText.trim()).toBe('Create new label');
});
it('renders link element with value of `createLabelTitle` prop', () => {
const vmWithCreateLabelTitle = createComponent(mockConfig.labelsWebUrl, createLabelTitle);
- const createLabelEl = vmWithCreateLabelTitle.$el.querySelector('.dropdown-footer-list .dropdown-toggle-page');
+ const createLabelEl = vmWithCreateLabelTitle.$el.querySelector(
+ '.dropdown-footer-list .dropdown-toggle-page',
+ );
+
expect(createLabelEl.innerText.trim()).toBe(createLabelTitle);
vmWithCreateLabelTitle.$destroy();
});
it('renders link element with `Manage labels` when `manageLabelsTitle` prop is not provided', () => {
const manageLabelsEl = vm.$el.querySelector('.dropdown-footer-list .dropdown-external-link');
+
expect(manageLabelsEl).not.toBeNull();
expect(manageLabelsEl.getAttribute('href')).toBe(vm.labelsWebUrl);
expect(manageLabelsEl.innerText.trim()).toBe('Manage labels');
@@ -60,7 +65,10 @@ describe('DropdownFooterComponent', () => {
createLabelTitle,
manageLabelsTitle,
);
- const manageLabelsEl = vmWithManageLabelsTitle.$el.querySelector('.dropdown-footer-list .dropdown-external-link');
+ const manageLabelsEl = vmWithManageLabelsTitle.$el.querySelector(
+ '.dropdown-footer-list .dropdown-external-link',
+ );
+
expect(manageLabelsEl.innerText.trim()).toBe(manageLabelsTitle);
vmWithManageLabelsTitle.$destroy();
});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js
index cdf234bb0c4..115e21e4f9f 100644
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js
+++ b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_header_spec.js
@@ -24,11 +24,15 @@ describe('DropdownHeaderComponent', () => {
describe('template', () => {
it('renders header text element', () => {
const headerEl = vm.$el.querySelector('.dropdown-title span');
+
expect(headerEl.innerText.trim()).toBe('Assign labels');
});
it('renders `Close` button element', () => {
- const closeBtnEl = vm.$el.querySelector('.dropdown-title button.dropdown-title-button.dropdown-menu-close');
+ const closeBtnEl = vm.$el.querySelector(
+ '.dropdown-title button.dropdown-title-button.dropdown-menu-close',
+ );
+
expect(closeBtnEl).not.toBeNull();
expect(closeBtnEl.querySelector('.fa-times.dropdown-menu-close-icon')).not.toBeNull();
});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js
index 57608d957e7..c30e619e76b 100644
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js
+++ b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_search_input_spec.js
@@ -24,6 +24,7 @@ describe('DropdownSearchInputComponent', () => {
describe('template', () => {
it('renders input element with type `search`', () => {
const inputEl = vm.$el.querySelector('input.dropdown-input-field');
+
expect(inputEl).not.toBeNull();
expect(inputEl.getAttribute('type')).toBe('search');
});
@@ -33,7 +34,9 @@ describe('DropdownSearchInputComponent', () => {
});
it('renders clear search icon element', () => {
- expect(vm.$el.querySelector('.fa-times.dropdown-input-clear.js-dropdown-input-clear')).not.toBeNull();
+ expect(
+ vm.$el.querySelector('.fa-times.dropdown-input-clear.js-dropdown-input-clear'),
+ ).not.toBeNull();
});
});
});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js
index 7c3d2711f65..6c84d2e167c 100644
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js
+++ b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js
@@ -35,6 +35,7 @@ describe('DropdownTitleComponent', () => {
it('renders `Edit` button element', () => {
const editBtnEl = vm.$el.querySelector('button.edit-link.js-sidebar-dropdown-toggle');
+
expect(editBtnEl).not.toBeNull();
expect(editBtnEl.innerText.trim()).toBe('Edit');
});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
index da74595bcdc..804b33422bd 100644
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
+++ b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
@@ -29,12 +29,14 @@ describe('DropdownValueCollapsedComponent', () => {
describe('labelsList', () => {
it('returns empty text when `labels` prop is empty array', () => {
const vmEmptyLabels = createComponent([]);
+
expect(vmEmptyLabels.labelsList).toBe('');
vmEmptyLabels.$destroy();
});
it('returns labels names separated by coma when `labels` prop has more than one item', () => {
const vmMoreLabels = createComponent(mockLabels.concat(mockLabels));
+
expect(vmMoreLabels.labelsList).toBe('Foo Label, Foo Label');
vmMoreLabels.$destroy();
});
@@ -46,7 +48,10 @@ describe('DropdownValueCollapsedComponent', () => {
}
const vmMoreLabels = createComponent(mockMoreLabels);
- expect(vmMoreLabels.labelsList).toBe('Foo Label, Foo Label, Foo Label, Foo Label, Foo Label, and 2 more');
+
+ expect(vmMoreLabels.labelsList).toBe(
+ 'Foo Label, Foo Label, Foo Label, Foo Label, Foo Label, and 2 more',
+ );
vmMoreLabels.$destroy();
});
@@ -61,6 +66,7 @@ describe('DropdownValueCollapsedComponent', () => {
it('emits onValueClick event on component', () => {
spyOn(vm, '$emit');
vm.handleClick();
+
expect(vm.$emit).toHaveBeenCalledWith('onValueClick');
});
});
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js
index 370a296bd8f..3fff781594f 100644
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js
+++ b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_spec.js
@@ -33,6 +33,7 @@ describe('DropdownValueComponent', () => {
describe('isEmpty', () => {
it('returns true if `labels` prop is empty', () => {
const vmEmptyLabels = createComponent([]);
+
expect(vmEmptyLabels.isEmpty).toBe(true);
vmEmptyLabels.$destroy();
});
@@ -46,9 +47,11 @@ describe('DropdownValueComponent', () => {
describe('methods', () => {
describe('labelFilterUrl', () => {
it('returns URL string starting with labelFilterBasePath and encoded label.title', () => {
- expect(vm.labelFilterUrl({
- title: 'Foo bar',
- })).toBe('/gitlab-org/my-project/issues?label_name[]=Foo%20bar');
+ expect(
+ vm.labelFilterUrl({
+ title: 'Foo bar',
+ }),
+ ).toBe('/gitlab-org/my-project/issues?label_name[]=Foo%20bar');
});
});
@@ -68,21 +71,29 @@ describe('DropdownValueComponent', () => {
describe('template', () => {
it('renders component container element with classes `hide-collapsed value issuable-show-labels`', () => {
- expect(vm.$el.classList.contains('hide-collapsed', 'value', 'issuable-show-labels')).toBe(true);
+ expect(vm.$el.classList.contains('hide-collapsed', 'value', 'issuable-show-labels')).toBe(
+ true,
+ );
});
it('render slot content inside component when `labels` prop is empty', () => {
const vmEmptyLabels = createComponent([]);
- expect(vmEmptyLabels.$el.querySelector('.text-secondary').innerText.trim()).toBe(mockConfig.emptyValueText);
+
+ expect(vmEmptyLabels.$el.querySelector('.text-secondary').innerText.trim()).toBe(
+ mockConfig.emptyValueText,
+ );
vmEmptyLabels.$destroy();
});
it('renders label element with filter URL', () => {
- expect(vm.$el.querySelector('a').getAttribute('href')).toBe('/gitlab-org/my-project/issues?label_name[]=Foo%20Label');
+ expect(vm.$el.querySelector('a').getAttribute('href')).toBe(
+ '/gitlab-org/my-project/issues?label_name[]=Foo%20Label',
+ );
});
it('renders label element with tooltip and styles based on label details', () => {
const labelEl = vm.$el.querySelector('a span.badge.color-label');
+
expect(labelEl).not.toBeNull();
expect(labelEl.dataset.placement).toBe('bottom');
expect(labelEl.dataset.container).toBe('body');
diff --git a/spec/javascripts/vue_shared/components/skeleton_loading_container_spec.js b/spec/javascripts/vue_shared/components/skeleton_loading_container_spec.js
deleted file mode 100644
index 34487885cf0..00000000000
--- a/spec/javascripts/vue_shared/components/skeleton_loading_container_spec.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import Vue from 'vue';
-import skeletonLoadingContainer from '~/vue_shared/components/skeleton_loading_container.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-
-describe('Skeleton loading container', () => {
- let vm;
-
- beforeEach(() => {
- const component = Vue.extend(skeletonLoadingContainer);
- vm = mountComponent(component);
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('renders 3 skeleton lines by default', () => {
- expect(vm.$el.querySelector('.skeleton-line-3')).not.toBeNull();
- });
-
- it('renders in full mode by default', () => {
- expect(vm.$el.classList.contains('animation-container-small')).toBeFalsy();
- });
-
- describe('small', () => {
- beforeEach((done) => {
- vm.small = true;
-
- Vue.nextTick(done);
- });
-
- it('renders in small mode', () => {
- expect(vm.$el.classList.contains('animation-container-small')).toBeTruthy();
- });
- });
-
- describe('lines', () => {
- beforeEach((done) => {
- vm.lines = 5;
-
- Vue.nextTick(done);
- });
-
- it('renders 5 lines', () => {
- expect(vm.$el.querySelector('.skeleton-line-5')).not.toBeNull();
- expect(vm.$el.querySelector('.skeleton-line-6')).toBeNull();
- });
- });
-});
diff --git a/spec/javascripts/vue_shared/components/smart_virtual_list_spec.js b/spec/javascripts/vue_shared/components/smart_virtual_list_spec.js
new file mode 100644
index 00000000000..e723fead65e
--- /dev/null
+++ b/spec/javascripts/vue_shared/components/smart_virtual_list_spec.js
@@ -0,0 +1,83 @@
+import Vue from 'vue';
+import SmartVirtualScrollList from '~/vue_shared/components/smart_virtual_list.vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
+
+describe('Toggle Button', () => {
+ let vm;
+
+ const createComponent = ({ length, remain }) => {
+ const smartListProperties = {
+ rtag: 'section',
+ wtag: 'ul',
+ wclass: 'test-class',
+ // Size in pixels does not matter for our tests here
+ size: 35,
+ length,
+ remain,
+ };
+
+ const Component = Vue.extend({
+ components: {
+ SmartVirtualScrollList,
+ },
+ smartListProperties,
+ items: Array(length).fill(1),
+ template: `
+ <smart-virtual-scroll-list v-bind="$options.smartListProperties">
+ <li v-for="(val, key) in $options.items" :key="key">{{ key + 1 }}</li>
+ </smart-virtual-scroll-list>`,
+ });
+
+ return mountComponent(Component);
+ };
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('if the list is shorter than the maximum shown elements', () => {
+ const listLength = 10;
+
+ beforeEach(() => {
+ vm = createComponent({ length: listLength, remain: 20 });
+ });
+
+ it('renders without the vue-virtual-scroll-list component', () => {
+ expect(vm.$el.classList).not.toContain('js-virtual-list');
+ expect(vm.$el.classList).toContain('js-plain-element');
+ });
+
+ it('renders list with provided tags and classes for the wrapper elements', () => {
+ expect(vm.$el.tagName).toEqual('SECTION');
+ expect(vm.$el.firstChild.tagName).toEqual('UL');
+ expect(vm.$el.firstChild.classList).toContain('test-class');
+ });
+
+ it('renders all children list elements', () => {
+ expect(vm.$el.querySelectorAll('li').length).toEqual(listLength);
+ });
+ });
+
+ describe('if the list is longer than the maximum shown elements', () => {
+ const maxItemsShown = 20;
+
+ beforeEach(() => {
+ vm = createComponent({ length: 1000, remain: maxItemsShown });
+ });
+
+ it('uses the vue-virtual-scroll-list component', () => {
+ expect(vm.$el.classList).toContain('js-virtual-list');
+ expect(vm.$el.classList).not.toContain('js-plain-element');
+ });
+
+ it('renders list with provided tags and classes for the wrapper elements', () => {
+ expect(vm.$el.tagName).toEqual('SECTION');
+ expect(vm.$el.firstChild.tagName).toEqual('UL');
+ expect(vm.$el.firstChild.classList).toContain('test-class');
+ });
+
+ it('renders at max twice the maximum shown elements', () => {
+ expect(vm.$el.querySelectorAll('li').length).toBeLessThanOrEqual(2 * maxItemsShown);
+ });
+ });
+});
diff --git a/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js b/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js
index f1fe2e996fc..073d111989c 100644
--- a/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js
+++ b/spec/javascripts/vue_shared/components/stacked_progress_bar_spec.js
@@ -4,16 +4,20 @@ import stackedProgressBarComponent from '~/vue_shared/components/stacked_progres
import mountComponent from 'spec/helpers/vue_mount_component_helper';
-const createComponent = (config) => {
+const createComponent = config => {
const Component = Vue.extend(stackedProgressBarComponent);
- const defaultConfig = Object.assign({}, {
- successLabel: 'Synced',
- failureLabel: 'Failed',
- neutralLabel: 'Out of sync',
- successCount: 25,
- failureCount: 10,
- totalCount: 5000,
- }, config);
+ const defaultConfig = Object.assign(
+ {},
+ {
+ successLabel: 'Synced',
+ failureLabel: 'Failed',
+ neutralLabel: 'Out of sync',
+ successCount: 25,
+ failureCount: 10,
+ totalCount: 5000,
+ },
+ config,
+ );
return mountComponent(Component, defaultConfig);
};
@@ -72,6 +76,7 @@ describe('StackedProgressBarComponent', () => {
it('renders empty state when count is unavailable', () => {
const vmX = createComponent({ totalCount: 0, successCount: 0, failureCount: 0 });
+
expect(vmX.$el.querySelectorAll('.status-unavailable').length).not.toBe(0);
vmX.$destroy();
});
diff --git a/spec/javascripts/vue_shared/components/table_pagination_spec.js b/spec/javascripts/vue_shared/components/table_pagination_spec.js
index c36b607a34e..0dcb712e720 100644
--- a/spec/javascripts/vue_shared/components/table_pagination_spec.js
+++ b/spec/javascripts/vue_shared/components/table_pagination_spec.js
@@ -5,13 +5,13 @@ describe('Pagination component', () => {
let component;
let PaginationComponent;
let spy;
- let mountComponet;
+ let mountComponent;
beforeEach(() => {
spy = jasmine.createSpy('spy');
PaginationComponent = Vue.extend(paginationComp);
- mountComponet = function (props) {
+ mountComponent = function(props) {
return new PaginationComponent({
propsData: props,
}).$mount();
@@ -20,7 +20,7 @@ describe('Pagination component', () => {
describe('render', () => {
it('should not render anything', () => {
- component = mountComponet({
+ component = mountComponent({
pageInfo: {
nextPage: 1,
page: 1,
@@ -37,7 +37,7 @@ describe('Pagination component', () => {
describe('prev button', () => {
it('should be disabled and non clickable', () => {
- component = mountComponet({
+ component = mountComponent({
pageInfo: {
nextPage: 2,
page: 1,
@@ -59,7 +59,7 @@ describe('Pagination component', () => {
});
it('should be enabled and clickable', () => {
- component = mountComponet({
+ component = mountComponent({
pageInfo: {
nextPage: 3,
page: 2,
@@ -72,13 +72,14 @@ describe('Pagination component', () => {
});
component.$el.querySelector('.js-previous-button a').click();
+
expect(spy).toHaveBeenCalledWith(1);
});
});
describe('first button', () => {
it('should call the change callback with the first page', () => {
- component = mountComponet({
+ component = mountComponent({
pageInfo: {
nextPage: 3,
page: 2,
@@ -102,7 +103,7 @@ describe('Pagination component', () => {
describe('last button', () => {
it('should call the change callback with the last page', () => {
- component = mountComponet({
+ component = mountComponent({
pageInfo: {
nextPage: 3,
page: 2,
@@ -126,7 +127,7 @@ describe('Pagination component', () => {
describe('next button', () => {
it('should be disabled and non clickable', () => {
- component = mountComponet({
+ component = mountComponent({
pageInfo: {
nextPage: 5,
page: 5,
@@ -138,9 +139,7 @@ describe('Pagination component', () => {
change: spy,
});
- expect(
- component.$el.querySelector('.js-next-button').textContent.trim(),
- ).toEqual('Next');
+ expect(component.$el.querySelector('.js-next-button').textContent.trim()).toEqual('Next');
component.$el.querySelector('.js-next-button a').click();
@@ -148,7 +147,7 @@ describe('Pagination component', () => {
});
it('should be enabled and clickable', () => {
- component = mountComponet({
+ component = mountComponent({
pageInfo: {
nextPage: 4,
page: 3,
@@ -168,7 +167,7 @@ describe('Pagination component', () => {
describe('numbered buttons', () => {
it('should render 5 pages', () => {
- component = mountComponet({
+ component = mountComponent({
pageInfo: {
nextPage: 4,
page: 3,
@@ -185,7 +184,7 @@ describe('Pagination component', () => {
});
it('should render the spread operator', () => {
- component = mountComponet({
+ component = mountComponent({
pageInfo: {
nextPage: 4,
page: 3,
diff --git a/spec/javascripts/vue_shared/components/time_ago_tooltip_spec.js b/spec/javascripts/vue_shared/components/time_ago_tooltip_spec.js
index b4fb568f1d4..536bb57b946 100644
--- a/spec/javascripts/vue_shared/components/time_ago_tooltip_spec.js
+++ b/spec/javascripts/vue_shared/components/time_ago_tooltip_spec.js
@@ -22,27 +22,15 @@ describe('Time ago with tooltip component', () => {
}).$mount();
expect(vm.$el.tagName).toEqual('TIME');
- expect(
- vm.$el.getAttribute('data-original-title'),
- ).toEqual(formatDate('2017-05-08T14:57:39.781Z'));
- expect(vm.$el.getAttribute('data-placement')).toEqual('top');
+ expect(vm.$el.getAttribute('data-original-title')).toEqual(
+ formatDate('2017-05-08T14:57:39.781Z'),
+ );
const timeago = getTimeago();
expect(vm.$el.textContent.trim()).toEqual(timeago.format('2017-05-08T14:57:39.781Z'));
});
- it('should render tooltip placed in bottom', () => {
- vm = new TimeagoTooltip({
- propsData: {
- time: '2017-05-08T14:57:39.781Z',
- tooltipPlacement: 'bottom',
- },
- }).$mount();
-
- expect(vm.$el.getAttribute('data-placement')).toEqual('bottom');
- });
-
it('should render provided html class', () => {
vm = new TimeagoTooltip({
propsData: {
diff --git a/spec/javascripts/vue_shared/components/toggle_button_spec.js b/spec/javascripts/vue_shared/components/toggle_button_spec.js
index 71952cc39e0..444ca451534 100644
--- a/spec/javascripts/vue_shared/components/toggle_button_spec.js
+++ b/spec/javascripts/vue_shared/components/toggle_button_spec.js
@@ -51,9 +51,11 @@ describe('Toggle Button', () => {
it('sets aria-label representing toggle state', () => {
vm.value = true;
+
expect(vm.ariaLabel).toEqual('Toggle Status: ON');
vm.value = false;
+
expect(vm.ariaLabel).toEqual('Toggle Status: OFF');
});
diff --git a/spec/javascripts/vue_shared/components/tooltip_on_truncate_spec.js b/spec/javascripts/vue_shared/components/tooltip_on_truncate_spec.js
index 8465757deb6..997d84dcc42 100644
--- a/spec/javascripts/vue_shared/components/tooltip_on_truncate_spec.js
+++ b/spec/javascripts/vue_shared/components/tooltip_on_truncate_spec.js
@@ -79,9 +79,7 @@ describe('TooltipOnTruncate component', () => {
},
};
- vm = mountTooltipOnTruncate(options, (h) => [
- h('a', { style: STYLE_TRUNCATED }, TEST_TITLE),
- ]);
+ vm = mountTooltipOnTruncate(options, h => [h('a', { style: STYLE_TRUNCATED }, TEST_TITLE)]);
vm.$nextTick()
.then(() => {
@@ -99,9 +97,7 @@ describe('TooltipOnTruncate component', () => {
},
};
- vm = mountTooltipOnTruncate(options, (h) => [
- h('a', { style: STYLE_NORMAL }, TEST_TITLE),
- ]);
+ vm = mountTooltipOnTruncate(options, h => [h('a', { style: STYLE_NORMAL }, TEST_TITLE)]);
vm.$nextTick()
.then(() => {
@@ -118,11 +114,11 @@ describe('TooltipOnTruncate component', () => {
style: STYLE_NORMAL,
props: {
title: TEST_TITLE,
- truncateTarget: (el) => el.childNodes[1],
+ truncateTarget: el => el.childNodes[1],
},
};
- vm = mountTooltipOnTruncate(options, (h) => [
+ vm = mountTooltipOnTruncate(options, h => [
h('a', { style: STYLE_NORMAL }, TEST_TITLE),
h('span', { style: STYLE_TRUNCATED }, TEST_TITLE),
]);
@@ -146,9 +142,7 @@ describe('TooltipOnTruncate component', () => {
},
};
- vm = mountTooltipOnTruncate(options, (h) => [
- h('a', { style: STYLE_TRUNCATED }, TEST_TITLE),
- ]);
+ vm = mountTooltipOnTruncate(options, h => [h('a', { style: STYLE_TRUNCATED }, TEST_TITLE)]);
vm.$nextTick()
.then(() => {
diff --git a/spec/javascripts/vue_shared/components/user_avatar/user_avatar_image_spec.js b/spec/javascripts/vue_shared/components/user_avatar/user_avatar_image_spec.js
index dc7652c77f7..5c4aa7cf844 100644
--- a/spec/javascripts/vue_shared/components/user_avatar/user_avatar_image_spec.js
+++ b/spec/javascripts/vue_shared/components/user_avatar/user_avatar_image_spec.js
@@ -1,7 +1,7 @@
import Vue from 'vue';
import { placeholderImage } from '~/lazy_loader';
import userAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
+import mountComponent, { mountComponentWithSlots } from 'spec/helpers/vue_mount_component_helper';
const DEFAULT_PROPS = {
size: 99,
@@ -32,18 +32,12 @@ describe('User Avatar Image Component', function() {
});
it('should have <img> as a child element', function() {
- expect(vm.$el.tagName).toBe('IMG');
- expect(vm.$el.getAttribute('src')).toBe(`${DEFAULT_PROPS.imgSrc}?width=99`);
- expect(vm.$el.getAttribute('data-src')).toBe(`${DEFAULT_PROPS.imgSrc}?width=99`);
- expect(vm.$el.getAttribute('alt')).toBe(DEFAULT_PROPS.imgAlt);
- });
-
- it('should properly compute tooltipContainer', function() {
- expect(vm.tooltipContainer).toBe('body');
- });
+ const imageElement = vm.$el.querySelector('img');
- it('should properly render tooltipContainer', function() {
- expect(vm.$el.getAttribute('data-container')).toBe('body');
+ expect(imageElement).not.toBe(null);
+ expect(imageElement.getAttribute('src')).toBe(`${DEFAULT_PROPS.imgSrc}?width=99`);
+ expect(imageElement.getAttribute('data-src')).toBe(`${DEFAULT_PROPS.imgSrc}?width=99`);
+ expect(imageElement.getAttribute('alt')).toBe(DEFAULT_PROPS.imgAlt);
});
it('should properly compute avatarSizeClass', function() {
@@ -51,7 +45,7 @@ describe('User Avatar Image Component', function() {
});
it('should properly render img css', function() {
- const { classList } = vm.$el;
+ const { classList } = vm.$el.querySelector('img');
const containsAvatar = classList.contains('avatar');
const containsSizeClass = classList.contains('s99');
const containsCustomClass = classList.contains(DEFAULT_PROPS.cssClasses);
@@ -73,12 +67,41 @@ describe('User Avatar Image Component', function() {
});
it('should add lazy attributes', function() {
- const { classList } = vm.$el;
- const lazyClass = classList.contains('lazy');
+ const imageElement = vm.$el.querySelector('img');
+ const lazyClass = imageElement.classList.contains('lazy');
expect(lazyClass).toBe(true);
- expect(vm.$el.getAttribute('src')).toBe(placeholderImage);
- expect(vm.$el.getAttribute('data-src')).toBe(`${DEFAULT_PROPS.imgSrc}?width=99`);
+ expect(imageElement.getAttribute('src')).toBe(placeholderImage);
+ expect(imageElement.getAttribute('data-src')).toBe(`${DEFAULT_PROPS.imgSrc}?width=99`);
+ });
+ });
+
+ describe('dynamic tooltip content', () => {
+ const props = DEFAULT_PROPS;
+ const slots = {
+ default: ['Action!'],
+ };
+
+ beforeEach(() => {
+ vm = mountComponentWithSlots(UserAvatarImage, { props, slots }).$mount();
+ });
+
+ it('renders the tooltip slot', () => {
+ expect(vm.$el.querySelector('.js-user-avatar-image-toolip')).not.toBe(null);
+ });
+
+ it('renders the tooltip content', () => {
+ expect(vm.$el.querySelector('.js-user-avatar-image-toolip').textContent).toContain(
+ slots.default[0],
+ );
+ });
+
+ it('does not render tooltip data attributes for on avatar image', () => {
+ const avatarImg = vm.$el.querySelector('img');
+
+ expect(avatarImg.dataset.originalTitle).not.toBeDefined();
+ expect(avatarImg.dataset.placement).not.toBeDefined();
+ expect(avatarImg.dataset.container).not.toBeDefined();
});
});
});
diff --git a/spec/javascripts/vue_shared/components/user_avatar/user_avatar_link_spec.js b/spec/javascripts/vue_shared/components/user_avatar/user_avatar_link_spec.js
index 4c5c242cbb3..0151ad23ba2 100644
--- a/spec/javascripts/vue_shared/components/user_avatar/user_avatar_link_spec.js
+++ b/spec/javascripts/vue_shared/components/user_avatar/user_avatar_link_spec.js
@@ -2,8 +2,8 @@ import _ from 'underscore';
import Vue from 'vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
-describe('User Avatar Link Component', function () {
- beforeEach(function () {
+describe('User Avatar Link Component', function() {
+ beforeEach(function() {
this.propsData = {
linkHref: 'myavatarurl.com',
imgSize: 99,
@@ -24,67 +24,80 @@ describe('User Avatar Link Component', function () {
[this.userAvatarImage] = this.userAvatarLink.$children;
});
- it('should return a defined Vue component', function () {
+ it('should return a defined Vue component', function() {
expect(this.userAvatarLink).toBeDefined();
});
- it('should have user-avatar-image registered as child component', function () {
+ it('should have user-avatar-image registered as child component', function() {
expect(this.userAvatarLink.$options.components.userAvatarImage).toBeDefined();
});
- it('user-avatar-link should have user-avatar-image as child component', function () {
+ it('user-avatar-link should have user-avatar-image as child component', function() {
expect(this.userAvatarImage).toBeDefined();
});
- it('should render <a> as a child element', function () {
+ it('should render <a> as a child element', function() {
expect(this.userAvatarLink.$el.tagName).toBe('A');
});
- it('should have <img> as a child element', function () {
+ it('should have <img> as a child element', function() {
expect(this.userAvatarLink.$el.querySelector('img')).not.toBeNull();
});
- it('should return neccessary props as defined', function () {
+ it('should return necessary props as defined', function() {
_.each(this.propsData, (val, key) => {
expect(this.userAvatarLink[key]).toBeDefined();
});
});
- describe('no username', function () {
- beforeEach(function (done) {
+ describe('no username', function() {
+ beforeEach(function(done) {
this.userAvatarLink.username = '';
Vue.nextTick(done);
});
- it('should only render image tag in link', function () {
+ it('should only render image tag in link', function() {
const childElements = this.userAvatarLink.$el.childNodes;
- expect(childElements[0].tagName).toBe('IMG');
+
+ expect(this.userAvatarLink.$el.querySelector('img')).not.toBe('null');
// Vue will render the hidden component as <!---->
expect(childElements[1].tagName).toBeUndefined();
});
- it('should render avatar image tooltip', function () {
- expect(this.userAvatarLink.$el.querySelector('img').dataset.originalTitle).toEqual(this.propsData.tooltipText);
+ it('should render avatar image tooltip', function() {
+ expect(this.userAvatarLink.shouldShowUsername).toBe(false);
+ expect(this.userAvatarLink.avatarTooltipText).toEqual(this.propsData.tooltipText);
});
});
- describe('username', function () {
- it('should not render avatar image tooltip', function () {
- expect(this.userAvatarLink.$el.querySelector('img').dataset.originalTitle).toEqual('');
+ describe('username', function() {
+ it('should not render avatar image tooltip', function() {
+ expect(
+ this.userAvatarLink.$el.querySelector('.js-user-avatar-image-toolip').innerText.trim(),
+ ).toEqual('');
});
- it('should render username prop in <span>', function () {
- expect(this.userAvatarLink.$el.querySelector('span').innerText.trim()).toEqual(this.propsData.username);
+ it('should render username prop in <span>', function() {
+ expect(
+ this.userAvatarLink.$el.querySelector('.js-user-avatar-link-username').innerText.trim(),
+ ).toEqual(this.propsData.username);
});
- it('should render text tooltip for <span>', function () {
- expect(this.userAvatarLink.$el.querySelector('span').dataset.originalTitle).toEqual(this.propsData.tooltipText);
+ it('should render text tooltip for <span>', function() {
+ expect(
+ this.userAvatarLink.$el.querySelector('.js-user-avatar-link-username').dataset
+ .originalTitle,
+ ).toEqual(this.propsData.tooltipText);
});
- it('should render text tooltip placement for <span>', function () {
- expect(this.userAvatarLink.$el.querySelector('span').getAttribute('tooltip-placement')).toEqual(this.propsData.tooltipPlacement);
+ it('should render text tooltip placement for <span>', function() {
+ expect(
+ this.userAvatarLink.$el
+ .querySelector('.js-user-avatar-link-username')
+ .getAttribute('tooltip-placement'),
+ ).toEqual(this.propsData.tooltipPlacement);
});
});
});
diff --git a/spec/javascripts/vue_shared/components/user_avatar/user_avatar_svg_spec.js b/spec/javascripts/vue_shared/components/user_avatar/user_avatar_svg_spec.js
index b8d639ffbec..9152fa8e12f 100644
--- a/spec/javascripts/vue_shared/components/user_avatar/user_avatar_svg_spec.js
+++ b/spec/javascripts/vue_shared/components/user_avatar/user_avatar_svg_spec.js
@@ -4,9 +4,9 @@ import avatarSvg from 'icons/_icon_random.svg';
const UserAvatarSvgComponent = Vue.extend(UserAvatarSvg);
-describe('User Avatar Svg Component', function () {
- describe('Initialization', function () {
- beforeEach(function () {
+describe('User Avatar Svg Component', function() {
+ describe('Initialization', function() {
+ beforeEach(function() {
this.propsData = {
size: 99,
svg: avatarSvg,
@@ -17,11 +17,11 @@ describe('User Avatar Svg Component', function () {
}).$mount();
});
- it('should return a defined Vue component', function () {
+ it('should return a defined Vue component', function() {
expect(this.userAvatarSvg).toBeDefined();
});
- it('should have <svg> as a child element', function () {
+ it('should have <svg> as a child element', function() {
expect(this.userAvatarSvg.$el.tagName).toEqual('svg');
expect(this.userAvatarSvg.$el.innerHTML).toContain('<path');
});
diff --git a/spec/javascripts/vue_shared/directives/tooltip_spec.js b/spec/javascripts/vue_shared/directives/tooltip_spec.js
index 4a644913e44..1d516a280b0 100644
--- a/spec/javascripts/vue_shared/directives/tooltip_spec.js
+++ b/spec/javascripts/vue_shared/directives/tooltip_spec.js
@@ -13,24 +13,45 @@ describe('Tooltip directive', () => {
describe('with a single tooltip', () => {
beforeEach(() => {
- const SomeComponent = Vue.extend({
+ setFixtures('<div id="dummy-element"></div>');
+ vm = new Vue({
+ el: '#dummy-element',
directives: {
tooltip,
},
- template: `
- <div
- v-tooltip
- title="foo">
- </div>
- `,
+ data() {
+ return {
+ tooltip: 'some text',
+ };
+ },
+ template: '<div v-tooltip :title="tooltip"></div>',
});
-
- vm = new SomeComponent().$mount();
});
it('should have tooltip plugin applied', () => {
expect($(vm.$el).data('bs.tooltip')).toBeDefined();
});
+
+ it('displays the title as tooltip', () => {
+ $(vm.$el).tooltip('show');
+ const tooltipElement = document.querySelector('.tooltip-inner');
+
+ expect(tooltipElement.innerText).toContain('some text');
+ });
+
+ it('updates a visible tooltip', done => {
+ $(vm.$el).tooltip('show');
+ const tooltipElement = document.querySelector('.tooltip-inner');
+
+ vm.tooltip = 'other text';
+
+ Vue.nextTick()
+ .then(() => {
+ expect(tooltipElement).toContainText('other text');
+ done();
+ })
+ .catch(done.fail);
+ });
});
describe('with multiple tooltips', () => {
@@ -58,7 +79,11 @@ describe('Tooltip directive', () => {
});
it('should have tooltip plugin applied to all instances', () => {
- expect($(vm.$el).find('.js-look-for-tooltip').data('bs.tooltip')).toBeDefined();
+ expect(
+ $(vm.$el)
+ .find('.js-look-for-tooltip')
+ .data('bs.tooltip'),
+ ).toBeDefined();
});
});
});
diff --git a/spec/javascripts/zen_mode_spec.js b/spec/javascripts/zen_mode_spec.js
index bdeebe0de75..e5f1e6ae937 100644
--- a/spec/javascripts/zen_mode_spec.js
+++ b/spec/javascripts/zen_mode_spec.js
@@ -46,12 +46,14 @@ describe('ZenMode', () => {
it('should not call dropzone if element is not dropzone valid', () => {
$('.div-dropzone').addClass('js-invalid-dropzone');
exitZen();
+
expect(dropzoneForElementSpy.calls.count()).toEqual(0);
});
it('should call dropzone if element is dropzone valid', () => {
$('.div-dropzone').removeClass('js-invalid-dropzone');
exitZen();
+
expect(dropzoneForElementSpy.calls.count()).toEqual(2);
});
});
@@ -60,12 +62,14 @@ describe('ZenMode', () => {
it('pauses Mousetrap', () => {
const mouseTrapPauseSpy = spyOn(Mousetrap, 'pause');
enterZen();
+
expect(mouseTrapPauseSpy).toHaveBeenCalled();
});
it('removes textarea styling', () => {
$('.notes-form textarea').attr('style', 'height: 400px');
enterZen();
+
expect($('.notes-form textarea')).not.toHaveAttr('style');
});
});
@@ -75,6 +79,7 @@ describe('ZenMode', () => {
it('exits on Escape', () => {
escapeKeydown();
+
expect($('.notes-form .zen-backdrop')).not.toHaveClass('fullscreen');
});
});
@@ -85,12 +90,14 @@ describe('ZenMode', () => {
it('unpauses Mousetrap', () => {
const mouseTrapUnpauseSpy = spyOn(Mousetrap, 'unpause');
exitZen();
+
expect(mouseTrapUnpauseSpy).toHaveBeenCalled();
});
it('restores the scroll position', () => {
spyOn(zen, 'scrollTo');
exitZen();
+
expect(zen.scrollTo).toHaveBeenCalled();
});
});
diff --git a/spec/lib/api/helpers/custom_validators_spec.rb b/spec/lib/api/helpers/custom_validators_spec.rb
new file mode 100644
index 00000000000..41e6fb47b11
--- /dev/null
+++ b/spec/lib/api/helpers/custom_validators_spec.rb
@@ -0,0 +1,64 @@
+require 'spec_helper'
+
+describe API::Helpers::CustomValidators do
+ let(:scope) do
+ Struct.new(:opts) do
+ def full_name(attr_name)
+ attr_name
+ end
+ end
+ end
+
+ describe API::Helpers::CustomValidators::Absence do
+ subject do
+ described_class.new(['test'], {}, false, scope.new)
+ end
+
+ context 'empty param' do
+ it 'does not raise a validation error' do
+ expect_no_validation_error({})
+ end
+ end
+
+ context 'invalid parameters' do
+ it 'should raise a validation error' do
+ expect_validation_error({ 'test' => 'some_value' })
+ end
+ end
+ end
+
+ describe API::Helpers::CustomValidators::IntegerNoneAny do
+ subject do
+ described_class.new(['test'], {}, false, scope.new)
+ end
+
+ context 'valid parameters' do
+ it 'does not raise a validation error' do
+ expect_no_validation_error({ 'test' => 2 })
+ expect_no_validation_error({ 'test' => 100 })
+ expect_no_validation_error({ 'test' => 'None' })
+ expect_no_validation_error({ 'test' => 'Any' })
+ expect_no_validation_error({ 'test' => 'none' })
+ expect_no_validation_error({ 'test' => 'any' })
+ end
+ end
+
+ context 'invalid parameters' do
+ it 'should raise a validation error' do
+ expect_validation_error({ 'test' => 'some_other_string' })
+ end
+ end
+ end
+
+ def expect_no_validation_error(params)
+ expect { validate_test_param!(params) }.not_to raise_error
+ end
+
+ def expect_validation_error(params)
+ expect { validate_test_param!(params) }.to raise_error(Grape::Exceptions::Validation)
+ end
+
+ def validate_test_param!(params)
+ subject.validate_param!('test', params)
+ end
+end
diff --git a/spec/lib/backup/manager_spec.rb b/spec/lib/backup/manager_spec.rb
index ca319679e80..9633caac788 100644
--- a/spec/lib/backup/manager_spec.rb
+++ b/spec/lib/backup/manager_spec.rb
@@ -11,10 +11,6 @@ describe Backup::Manager do
allow(progress).to receive(:puts)
allow(progress).to receive(:print)
- allow_any_instance_of(String).to receive(:color) do |string, _color|
- string
- end
-
@old_progress = $progress # rubocop:disable Style/GlobalVars
$progress = progress # rubocop:disable Style/GlobalVars
end
diff --git a/spec/lib/backup/repository_spec.rb b/spec/lib/backup/repository_spec.rb
index c5a854b5660..fdeea814bb2 100644
--- a/spec/lib/backup/repository_spec.rb
+++ b/spec/lib/backup/repository_spec.rb
@@ -11,10 +11,6 @@ describe Backup::Repository do
allow(FileUtils).to receive(:mkdir_p).and_return(true)
allow(FileUtils).to receive(:mv).and_return(true)
- allow_any_instance_of(String).to receive(:color) do |string, _color|
- string
- end
-
allow_any_instance_of(described_class).to receive(:progress).and_return(progress)
end
diff --git a/spec/lib/banzai/cross_project_reference_spec.rb b/spec/lib/banzai/cross_project_reference_spec.rb
index aadfe7637dd..ba995e16be7 100644
--- a/spec/lib/banzai/cross_project_reference_spec.rb
+++ b/spec/lib/banzai/cross_project_reference_spec.rb
@@ -1,16 +1,21 @@
require 'spec_helper'
describe Banzai::CrossProjectReference do
- include described_class
+ let(:including_class) { Class.new.include(described_class).new }
+
+ before do
+ allow(including_class).to receive(:context).and_return({})
+ allow(including_class).to receive(:parent_from_ref).and_call_original
+ end
describe '#parent_from_ref' do
context 'when no project was referenced' do
it 'returns the project from context' do
project = double
- allow(self).to receive(:context).and_return({ project: project })
+ allow(including_class).to receive(:context).and_return({ project: project })
- expect(parent_from_ref(nil)).to eq project
+ expect(including_class.parent_from_ref(nil)).to eq project
end
end
@@ -18,15 +23,15 @@ describe Banzai::CrossProjectReference do
it 'returns the group from context' do
group = double
- allow(self).to receive(:context).and_return({ group: group })
+ allow(including_class).to receive(:context).and_return({ group: group })
- expect(parent_from_ref(nil)).to eq group
+ expect(including_class.parent_from_ref(nil)).to eq group
end
end
context 'when referenced project does not exist' do
it 'returns nil' do
- expect(parent_from_ref('invalid/reference')).to be_nil
+ expect(including_class.parent_from_ref('invalid/reference')).to be_nil
end
end
@@ -37,7 +42,7 @@ describe Banzai::CrossProjectReference do
expect(Project).to receive(:find_by_full_path)
.with('cross/reference').and_return(project2)
- expect(parent_from_ref('cross/reference')).to eq project2
+ expect(including_class.parent_from_ref('cross/reference')).to eq project2
end
end
end
diff --git a/spec/lib/banzai/filter/absolute_link_filter_spec.rb b/spec/lib/banzai/filter/absolute_link_filter_spec.rb
index a3ad056efcd..50be551cd90 100644
--- a/spec/lib/banzai/filter/absolute_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/absolute_link_filter_spec.rb
@@ -28,7 +28,7 @@ describe Banzai::Filter::AbsoluteLinkFilter do
end
context 'if relative_url_root is set' do
- it 'joins the url without without doubling the path' do
+ it 'joins the url without doubling the path' do
allow(Gitlab.config.gitlab).to receive(:url).and_return("#{fake_url}/gitlab/")
doc = filter(link("/gitlab/foo", 'gfm'), only_path_context)
expect(doc.at_css('a')['href']).to eq "#{fake_url}/gitlab/foo"
diff --git a/spec/lib/banzai/filter/autolink_filter_spec.rb b/spec/lib/banzai/filter/autolink_filter_spec.rb
index a50329473ad..7a457403b51 100644
--- a/spec/lib/banzai/filter/autolink_filter_spec.rb
+++ b/spec/lib/banzai/filter/autolink_filter_spec.rb
@@ -76,7 +76,7 @@ describe Banzai::Filter::AutolinkFilter do
expect(doc.at_css('a')['href']).to eq link
end
- it 'autolinks multiple occurences of smb' do
+ it 'autolinks multiple occurrences of smb' do
link1 = 'smb:///Volumes/shared/foo.pdf'
link2 = 'smb:///Volumes/shared/bar.pdf'
diff --git a/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb b/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb
index e1af5a15371..cbff2fdab14 100644
--- a/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/commit_range_reference_filter_spec.rb
@@ -60,6 +60,7 @@ describe Banzai::Filter::CommitRangeReferenceFilter do
exp = act = "See #{commit1.id.reverse}...#{commit2.id}"
allow(project.repository).to receive(:commit).with(commit1.id.reverse)
+ allow(project.repository).to receive(:commit).with(commit2.id)
expect(reference_filter(act).to_html).to eq exp
end
diff --git a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
index d9018a7e4fe..a0270d93d50 100644
--- a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
@@ -79,13 +79,9 @@ describe Banzai::Filter::ExternalIssueReferenceFilter do
expect(link).to eq helper.url_for_issue(issue_id, project, only_path: true)
end
- context 'with RequestStore enabled' do
+ context 'with RequestStore enabled', :request_store do
let(:reference_filter) { HTML::Pipeline.new([described_class]) }
- before do
- allow(RequestStore).to receive(:active?).and_return(true)
- end
-
it 'queries the collection on the first call' do
expect_any_instance_of(Project).to receive(:default_issues_tracker?).once.and_call_original
expect_any_instance_of(Project).to receive(:external_issue_reference_pattern).once.and_call_original
@@ -105,15 +101,24 @@ describe Banzai::Filter::ExternalIssueReferenceFilter do
context "redmine project" do
let(:project) { create(:redmine_project) }
- let(:issue) { ExternalIssue.new("#123", project) }
- let(:reference) { issue.to_reference }
before do
- project.issues_enabled = false
- project.save!
+ project.update!(issues_enabled: false)
end
- it_behaves_like "external issue tracker"
+ context "with a hash prefix" do
+ let(:issue) { ExternalIssue.new("#123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "with a single-letter prefix" do
+ let(:issue) { ExternalIssue.new("T-123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
end
context "jira project" do
@@ -126,6 +131,15 @@ describe Banzai::Filter::ExternalIssueReferenceFilter do
it_behaves_like "external issue tracker"
end
+ context "with a single-letter prefix" do
+ let(:issue) { ExternalIssue.new("J-123", project) }
+
+ it "ignores reference" do
+ exp = act = "Issue #{reference}"
+ expect(filter(act).to_html).to eq exp
+ end
+ end
+
context "with wrong markdown" do
let(:issue) { ExternalIssue.new("#123", project) }
diff --git a/spec/lib/banzai/filter/relative_link_filter_spec.rb b/spec/lib/banzai/filter/relative_link_filter_spec.rb
index ba8dc68ceda..415ded05e6e 100644
--- a/spec/lib/banzai/filter/relative_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/relative_link_filter_spec.rb
@@ -83,6 +83,11 @@ describe Banzai::Filter::RelativeLinkFilter do
expect { filter(act) }.not_to raise_error
end
+ it 'does not raise an exception with a space in the path' do
+ act = link("/uploads/d18213acd3732630991986120e167e3d/Landscape_8.jpg \nBut here's some more unexpected text :smile:)")
+ expect { filter(act) }.not_to raise_error
+ end
+
it 'ignores ref if commit is passed' do
doc = filter(link('non/existent.file'), commit: project.commit('empty-branch') )
expect(doc.at_css('a')['href'])
@@ -221,7 +226,7 @@ describe Banzai::Filter::RelativeLinkFilter do
let(:ref) {'mark#\'@],+;-._/#@!$&()+down'}
it 'correctly escapes the ref' do
- # Adressable won't escape the '#', so we do this manually
+ # Addressable won't escape the '#', so we do this manually
ref_escaped = 'mark%23\'@%5D,+;-._/%23@!$&()+down'
# Stub this method so the branch doesn't actually need to be in the repo
diff --git a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
index df24cef0b8b..91b0499375d 100644
--- a/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/gfm_pipeline_spec.rb
@@ -104,5 +104,17 @@ describe Banzai::Pipeline::GfmPipeline do
expect(output).to include("src=\"test%20image.png\"")
end
+
+ it 'sanitizes the fixed link' do
+ markdown_xss = "[xss](javascript: alert%28document.domain%29)"
+ output = described_class.to_html(markdown_xss, project: project)
+
+ expect(output).not_to include("javascript")
+
+ markdown_xss = "<invalidtag>\n[xss](javascript:alert%28document.domain%29)"
+ output = described_class.to_html(markdown_xss, project: project)
+
+ expect(output).not_to include("javascript")
+ end
end
end
diff --git a/spec/lib/banzai/reference_parser/base_parser_spec.rb b/spec/lib/banzai/reference_parser/base_parser_spec.rb
index 4e6e8eca38a..c6e9fc414a1 100644
--- a/spec/lib/banzai/reference_parser/base_parser_spec.rb
+++ b/spec/lib/banzai/reference_parser/base_parser_spec.rb
@@ -263,11 +263,10 @@ describe Banzai::ReferenceParser::BaseParser do
end
end
- context 'with RequestStore enabled' do
+ context 'with RequestStore enabled', :request_store do
before do
cache = Hash.new { |hash, key| hash[key] = {} }
- allow(RequestStore).to receive(:active?).and_return(true)
allow(subject).to receive(:collection_cache).and_return(cache)
end
diff --git a/spec/lib/banzai/reference_parser/commit_parser_spec.rb b/spec/lib/banzai/reference_parser/commit_parser_spec.rb
index cca53a8b9b9..f558dea209f 100644
--- a/spec/lib/banzai/reference_parser/commit_parser_spec.rb
+++ b/spec/lib/banzai/reference_parser/commit_parser_spec.rb
@@ -120,4 +120,22 @@ describe Banzai::ReferenceParser::CommitParser do
expect(subject.find_commits(project, %w{123})).to eq([])
end
end
+
+ context 'when checking commits on another projects' do
+ let(:control_links) do
+ [commit_link]
+ end
+
+ let(:actual_links) do
+ control_links + [commit_link, commit_link]
+ end
+
+ def commit_link
+ project = create(:project, :repository, :public)
+
+ Nokogiri::HTML.fragment(%Q{<a data-commit="#{project.commit.id}" data-project="#{project.id}"></a>}).children[0]
+ end
+
+ it_behaves_like 'no project N+1 queries'
+ end
end
diff --git a/spec/lib/bitbucket_server/client_spec.rb b/spec/lib/bitbucket_server/client_spec.rb
index f926ae963a4..5de0a9a65b5 100644
--- a/spec/lib/bitbucket_server/client_spec.rb
+++ b/spec/lib/bitbucket_server/client_spec.rb
@@ -13,7 +13,7 @@ describe BitbucketServer::Client do
let(:path) { "/projects/#{project}/repos/#{repo_slug}/pull-requests?state=ALL" }
it 'requests a collection' do
- expect(BitbucketServer::Paginator).to receive(:new).with(anything, path, :pull_request)
+ expect(BitbucketServer::Paginator).to receive(:new).with(anything, path, :pull_request, page_offset: 0, limit: nil)
subject.pull_requests(project, repo_slug)
end
@@ -29,7 +29,7 @@ describe BitbucketServer::Client do
let(:path) { "/projects/#{project}/repos/#{repo_slug}/pull-requests/1/activities" }
it 'requests a collection' do
- expect(BitbucketServer::Paginator).to receive(:new).with(anything, path, :activity)
+ expect(BitbucketServer::Paginator).to receive(:new).with(anything, path, :activity, page_offset: 0, limit: nil)
subject.activities(project, repo_slug, 1)
end
@@ -52,10 +52,16 @@ describe BitbucketServer::Client do
let(:path) { "/repos" }
it 'requests a collection' do
- expect(BitbucketServer::Paginator).to receive(:new).with(anything, path, :repo)
+ expect(BitbucketServer::Paginator).to receive(:new).with(anything, path, :repo, page_offset: 0, limit: nil)
subject.repos
end
+
+ it 'requests a collection with an offset and limit' do
+ expect(BitbucketServer::Paginator).to receive(:new).with(anything, path, :repo, page_offset: 10, limit: 25)
+
+ subject.repos(page_offset: 10, limit: 25)
+ end
end
describe '#create_branch' do
diff --git a/spec/lib/bitbucket_server/collection_spec.rb b/spec/lib/bitbucket_server/collection_spec.rb
new file mode 100644
index 00000000000..ddd02bac88a
--- /dev/null
+++ b/spec/lib/bitbucket_server/collection_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe BitbucketServer::Collection do
+ let(:connection) { instance_double(BitbucketServer::Connection) }
+ let(:page) { 1 }
+ let(:paginator) { BitbucketServer::Paginator.new(connection, 'http://more-data', :pull_request, page_offset: page) }
+
+ subject { described_class.new(paginator) }
+
+ describe '#current_page' do
+ it 'returns 1' do
+ expect(subject.current_page).to eq(1)
+ end
+ end
+
+ describe '#prev_page' do
+ it 'returns nil' do
+ expect(subject.prev_page).to be_nil
+ end
+ end
+
+ describe '#next_page' do
+ it 'returns 2' do
+ expect(subject.next_page).to eq(2)
+ end
+ end
+end
diff --git a/spec/lib/bitbucket_server/paginator_spec.rb b/spec/lib/bitbucket_server/paginator_spec.rb
index 2de50eba3c4..d268d4f23cf 100644
--- a/spec/lib/bitbucket_server/paginator_spec.rb
+++ b/spec/lib/bitbucket_server/paginator_spec.rb
@@ -20,6 +20,16 @@ describe BitbucketServer::Paginator do
expect { paginator.items }.to raise_error(StopIteration)
end
+ it 'obeys limits' do
+ limited = described_class.new(connection, 'http://more-data', :pull_request, page_offset: 0, limit: 1)
+ allow(limited).to receive(:fetch_next_page).and_return(first_page)
+
+ expect(limited.has_next_page?).to be_truthy
+ expect(limited.items).to match(['item_1'])
+ expect(limited.has_next_page?).to be_truthy
+ expect { limited.items }.to raise_error(StopIteration)
+ end
+
it 'calls the connection with different offsets' do
expect(connection).to receive(:get).with('http://more-data', start: 0, limit: BitbucketServer::Paginator::PAGE_LENGTH).and_return(page_attrs)
diff --git a/spec/lib/container_registry/blob_spec.rb b/spec/lib/container_registry/blob_spec.rb
index c73faa55513..d3fff5bad42 100644
--- a/spec/lib/container_registry/blob_spec.rb
+++ b/spec/lib/container_registry/blob_spec.rb
@@ -64,7 +64,7 @@ describe ContainerRegistry::Blob do
.to_return(status: 200)
end
- it 'returns true when blob has been successfuly deleted' do
+ it 'returns true when blob has been successfully deleted' do
expect(blob.delete).to be_truthy
end
end
diff --git a/spec/lib/event_filter_spec.rb b/spec/lib/event_filter_spec.rb
index 87ae6b6cf01..30016da6828 100644
--- a/spec/lib/event_filter_spec.rb
+++ b/spec/lib/event_filter_spec.rb
@@ -1,58 +1,119 @@
require 'spec_helper'
describe EventFilter do
+ describe 'FILTERS' do
+ it 'returns a definite list of filters' do
+ expect(described_class::FILTERS).to eq(%w[all push merged issue comments team])
+ end
+ end
+
+ describe '#filter' do
+ it 'returns "all" if given filter is nil' do
+ expect(described_class.new(nil).filter).to eq(described_class::ALL)
+ end
+
+ it 'returns "all" if given filter is ""' do
+ expect(described_class.new('').filter).to eq(described_class::ALL)
+ end
+
+ it 'returns "all" if given filter is "foo"' do
+ expect(described_class.new('foo').filter).to eq('all')
+ end
+ end
+
describe '#apply_filter' do
- let(:source_user) { create(:user) }
- let!(:public_project) { create(:project, :public) }
+ set(:public_project) { create(:project, :public) }
+
+ set(:push_event) { create(:push_event, project: public_project) }
+ set(:merged_event) { create(:event, :merged, project: public_project, target: public_project) }
+ set(:created_event) { create(:event, :created, project: public_project, target: public_project) }
+ set(:updated_event) { create(:event, :updated, project: public_project, target: public_project) }
+ set(:closed_event) { create(:event, :closed, project: public_project, target: public_project) }
+ set(:reopened_event) { create(:event, :reopened, project: public_project, target: public_project) }
+ set(:comments_event) { create(:event, :commented, project: public_project, target: public_project) }
+ set(:joined_event) { create(:event, :joined, project: public_project, target: public_project) }
+ set(:left_event) { create(:event, :left, project: public_project, target: public_project) }
- let!(:push_event) { create(:push_event, project: public_project, author: source_user) }
- let!(:merged_event) { create(:event, :merged, project: public_project, target: public_project, author: source_user) }
- let!(:created_event) { create(:event, :created, project: public_project, target: public_project, author: source_user) }
- let!(:updated_event) { create(:event, :updated, project: public_project, target: public_project, author: source_user) }
- let!(:closed_event) { create(:event, :closed, project: public_project, target: public_project, author: source_user) }
- let!(:reopened_event) { create(:event, :reopened, project: public_project, target: public_project, author: source_user) }
- let!(:comments_event) { create(:event, :commented, project: public_project, target: public_project, author: source_user) }
- let!(:joined_event) { create(:event, :joined, project: public_project, target: public_project, author: source_user) }
- let!(:left_event) { create(:event, :left, project: public_project, target: public_project, author: source_user) }
+ let(:filtered_events) { described_class.new(filter).apply_filter(Event.all) }
- it 'applies push filter' do
- events = described_class.new(described_class.push).apply_filter(Event.all)
- expect(events).to contain_exactly(push_event)
+ context 'with the "push" filter' do
+ let(:filter) { described_class::PUSH }
+
+ it 'filters push events only' do
+ expect(filtered_events).to contain_exactly(push_event)
+ end
end
- it 'applies merged filter' do
- events = described_class.new(described_class.merged).apply_filter(Event.all)
- expect(events).to contain_exactly(merged_event)
+ context 'with the "merged" filter' do
+ let(:filter) { described_class::MERGED }
+
+ it 'filters merged events only' do
+ expect(filtered_events).to contain_exactly(merged_event)
+ end
end
- it 'applies issue filter' do
- events = described_class.new(described_class.issue).apply_filter(Event.all)
- expect(events).to contain_exactly(created_event, updated_event, closed_event, reopened_event)
+ context 'with the "issue" filter' do
+ let(:filter) { described_class::ISSUE }
+
+ it 'filters issue events only' do
+ expect(filtered_events).to contain_exactly(created_event, updated_event, closed_event, reopened_event)
+ end
end
- it 'applies comments filter' do
- events = described_class.new(described_class.comments).apply_filter(Event.all)
- expect(events).to contain_exactly(comments_event)
+ context 'with the "comments" filter' do
+ let(:filter) { described_class::COMMENTS }
+
+ it 'filters comment events only' do
+ expect(filtered_events).to contain_exactly(comments_event)
+ end
end
- it 'applies team filter' do
- events = described_class.new(described_class.team).apply_filter(Event.all)
- expect(events).to contain_exactly(joined_event, left_event)
+ context 'with the "team" filter' do
+ let(:filter) { described_class::TEAM }
+
+ it 'filters team events only' do
+ expect(filtered_events).to contain_exactly(joined_event, left_event)
+ end
end
- it 'applies all filter' do
- events = described_class.new(described_class.all).apply_filter(Event.all)
- expect(events).to contain_exactly(push_event, merged_event, created_event, updated_event, closed_event, reopened_event, comments_event, joined_event, left_event)
+ context 'with the "all" filter' do
+ let(:filter) { described_class::ALL }
+
+ it 'returns all events' do
+ expect(filtered_events).to eq(Event.all)
+ end
+ end
+
+ context 'with an unknown filter' do
+ let(:filter) { 'foo' }
+
+ it 'returns all events' do
+ expect(filtered_events).to eq(Event.all)
+ end
+ end
+
+ context 'with a nil filter' do
+ let(:filter) { nil }
+
+ it 'returns all events' do
+ expect(filtered_events).to eq(Event.all)
+ end
+ end
+ end
+
+ describe '#active?' do
+ let(:event_filter) { described_class.new(described_class::TEAM) }
+
+ it 'returns false if filter does not include the given key' do
+ expect(event_filter.active?('foo')).to eq(false)
end
- it 'applies no filter' do
- events = described_class.new(nil).apply_filter(Event.all)
- expect(events).to contain_exactly(push_event, merged_event, created_event, updated_event, closed_event, reopened_event, comments_event, joined_event, left_event)
+ it 'returns false if the given key is nil' do
+ expect(event_filter.active?(nil)).to eq(false)
end
- it 'applies unknown filter' do
- events = described_class.new('').apply_filter(Event.all)
- expect(events).to contain_exactly(push_event, merged_event, created_event, updated_event, closed_event, reopened_event, comments_event, joined_event, left_event)
+ it 'returns true if filter does not include the given key' do
+ expect(event_filter.active?(described_class::TEAM)).to eq(true)
end
end
end
diff --git a/spec/lib/extracts_path_spec.rb b/spec/lib/extracts_path_spec.rb
index 8947e2ac4fb..e0691aba600 100644
--- a/spec/lib/extracts_path_spec.rb
+++ b/spec/lib/extracts_path_spec.rb
@@ -205,28 +205,18 @@ describe ExtractsPath do
end
describe '#lfs_blob_ids' do
- shared_examples '#lfs_blob_ids' do
- let(:tag) { @project.repository.add_tag(@project.owner, 'my-annotated-tag', 'master', 'test tag') }
- let(:ref) { tag.target }
- let(:params) { { ref: ref, path: 'README.md' } }
+ let(:tag) { @project.repository.add_tag(@project.owner, 'my-annotated-tag', 'master', 'test tag') }
+ let(:ref) { tag.target }
+ let(:params) { { ref: ref, path: 'README.md' } }
- before do
- @project = create(:project, :repository)
- end
-
- it 'handles annotated tags' do
- assign_ref_vars
-
- expect(lfs_blob_ids).to eq([])
- end
+ before do
+ @project = create(:project, :repository)
end
- context 'when gitaly is enabled' do
- it_behaves_like '#lfs_blob_ids'
- end
+ it 'handles annotated tags' do
+ assign_ref_vars
- context 'when gitaly is disabled', :skip_gitaly_mock do
- it_behaves_like '#lfs_blob_ids'
+ expect(lfs_blob_ids).to eq([])
end
end
end
diff --git a/spec/lib/feature_spec.rb b/spec/lib/feature_spec.rb
index 48c0ba8a653..9d56c62ae57 100644
--- a/spec/lib/feature_spec.rb
+++ b/spec/lib/feature_spec.rb
@@ -91,7 +91,11 @@ describe Feature do
end
describe '.flipper' do
- shared_examples 'a memoized Flipper instance' do
+ before do
+ described_class.instance_variable_set(:@flipper, nil)
+ end
+
+ context 'when request store is inactive' do
it 'memoizes the Flipper instance' do
expect(Flipper).to receive(:new).once.and_call_original
@@ -101,16 +105,14 @@ describe Feature do
end
end
- context 'when request store is inactive' do
- before do
+ context 'when request store is active', :request_store do
+ it 'memoizes the Flipper instance' do
+ expect(Flipper).to receive(:new).once.and_call_original
+
+ described_class.flipper
described_class.instance_variable_set(:@flipper, nil)
+ described_class.flipper
end
-
- it_behaves_like 'a memoized Flipper instance'
- end
-
- context 'when request store is inactive', :request_store do
- it_behaves_like 'a memoized Flipper instance'
end
end
diff --git a/spec/lib/gitaly/server_spec.rb b/spec/lib/gitaly/server_spec.rb
index 09bf21b5946..292ab870dad 100644
--- a/spec/lib/gitaly/server_spec.rb
+++ b/spec/lib/gitaly/server_spec.rb
@@ -26,9 +26,7 @@ describe Gitaly::Server do
end
end
- context 'when the storage is not readable' do
- let(:server) { described_class.new('broken') }
-
+ context 'when the storage is not readable', :broken_storage do
it 'returns false' do
expect(server).not_to be_readable
end
@@ -42,9 +40,7 @@ describe Gitaly::Server do
end
end
- context 'when the storage is not writeable' do
- let(:server) { described_class.new('broken') }
-
+ context 'when the storage is not writeable', :broken_storage do
it 'returns false' do
expect(server).not_to be_writeable
end
diff --git a/spec/lib/gitlab/auth/o_auth/user_spec.rb b/spec/lib/gitlab/auth/o_auth/user_spec.rb
index 3a8667e434d..dcbd12fe190 100644
--- a/spec/lib/gitlab/auth/o_auth/user_spec.rb
+++ b/spec/lib/gitlab/auth/o_auth/user_spec.rb
@@ -498,7 +498,7 @@ describe Gitlab::Auth::OAuth::User do
end
end
- describe 'ensure backwards compatibility with with sync email from provider option' do
+ describe 'ensure backwards compatibility with sync email from provider option' do
let!(:existing_user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'my-provider') }
before do
diff --git a/spec/lib/gitlab/auth/request_authenticator_spec.rb b/spec/lib/gitlab/auth/request_authenticator_spec.rb
index 242ab4a91dd..3d979132880 100644
--- a/spec/lib/gitlab/auth/request_authenticator_spec.rb
+++ b/spec/lib/gitlab/auth/request_authenticator_spec.rb
@@ -19,17 +19,17 @@ describe Gitlab::Auth::RequestAuthenticator do
allow_any_instance_of(described_class).to receive(:find_sessionless_user).and_return(sessionless_user)
allow_any_instance_of(described_class).to receive(:find_user_from_warden).and_return(session_user)
- expect(subject.user).to eq sessionless_user
+ expect(subject.user([:api])).to eq sessionless_user
end
it 'returns session user if no sessionless user found' do
allow_any_instance_of(described_class).to receive(:find_user_from_warden).and_return(session_user)
- expect(subject.user).to eq session_user
+ expect(subject.user([:api])).to eq session_user
end
it 'returns nil if no user found' do
- expect(subject.user).to be_blank
+ expect(subject.user([:api])).to be_blank
end
it 'bubbles up exceptions' do
@@ -42,26 +42,26 @@ describe Gitlab::Auth::RequestAuthenticator do
let!(:feed_token_user) { build(:user) }
it 'returns access_token user first' do
- allow_any_instance_of(described_class).to receive(:find_user_from_access_token).and_return(access_token_user)
+ allow_any_instance_of(described_class).to receive(:find_user_from_web_access_token).and_return(access_token_user)
allow_any_instance_of(described_class).to receive(:find_user_from_feed_token).and_return(feed_token_user)
- expect(subject.find_sessionless_user).to eq access_token_user
+ expect(subject.find_sessionless_user([:api])).to eq access_token_user
end
it 'returns feed_token user if no access_token user found' do
allow_any_instance_of(described_class).to receive(:find_user_from_feed_token).and_return(feed_token_user)
- expect(subject.find_sessionless_user).to eq feed_token_user
+ expect(subject.find_sessionless_user([:api])).to eq feed_token_user
end
it 'returns nil if no user found' do
- expect(subject.find_sessionless_user).to be_blank
+ expect(subject.find_sessionless_user([:api])).to be_blank
end
it 'rescue Gitlab::Auth::AuthenticationError exceptions' do
- allow_any_instance_of(described_class).to receive(:find_user_from_access_token).and_raise(Gitlab::Auth::UnauthorizedError)
+ allow_any_instance_of(described_class).to receive(:find_user_from_web_access_token).and_raise(Gitlab::Auth::UnauthorizedError)
- expect(subject.find_sessionless_user).to be_blank
+ expect(subject.find_sessionless_user([:api])).to be_blank
end
end
end
diff --git a/spec/lib/gitlab/auth/saml/auth_hash_spec.rb b/spec/lib/gitlab/auth/saml/auth_hash_spec.rb
index 76f49e778fb..3620e1afe25 100644
--- a/spec/lib/gitlab/auth/saml/auth_hash_spec.rb
+++ b/spec/lib/gitlab/auth/saml/auth_hash_spec.rb
@@ -82,6 +82,17 @@ describe Gitlab::Auth::Saml::AuthHash do
end
end
+ context 'with SAML 2.0 response_object' do
+ before do
+ auth_hash_data[:extra][:response_object] = { document:
+ saml_xml(File.read('spec/fixtures/authentication/saml2_response.xml')) }
+ end
+
+ it 'can extract authn_context' do
+ expect(saml_auth_hash.authn_context).to eq 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'
+ end
+ end
+
context 'without response_object' do
it 'returns an empty string' do
expect(saml_auth_hash.authn_context).to be_nil
diff --git a/spec/lib/gitlab/auth/user_auth_finders_spec.rb b/spec/lib/gitlab/auth/user_auth_finders_spec.rb
index 454ad1589b9..4e4c8b215c2 100644
--- a/spec/lib/gitlab/auth/user_auth_finders_spec.rb
+++ b/spec/lib/gitlab/auth/user_auth_finders_spec.rb
@@ -9,7 +9,7 @@ describe Gitlab::Auth::UserAuthFinders do
'rack.input' => ''
}
end
- let(:request) { Rack::Request.new(env)}
+ let(:request) { Rack::Request.new(env) }
def set_param(key, value)
request.update_param(key, value)
@@ -49,6 +49,7 @@ describe Gitlab::Auth::UserAuthFinders do
describe '#find_user_from_feed_token' do
context 'when the request format is atom' do
before do
+ env['SCRIPT_NAME'] = 'url.atom'
env['HTTP_ACCEPT'] = 'application/atom+xml'
end
@@ -56,17 +57,17 @@ describe Gitlab::Auth::UserAuthFinders do
it 'returns user if valid feed_token' do
set_param(:feed_token, user.feed_token)
- expect(find_user_from_feed_token).to eq user
+ expect(find_user_from_feed_token(:rss)).to eq user
end
it 'returns nil if feed_token is blank' do
- expect(find_user_from_feed_token).to be_nil
+ expect(find_user_from_feed_token(:rss)).to be_nil
end
it 'returns exception if invalid feed_token' do
set_param(:feed_token, 'invalid_token')
- expect { find_user_from_feed_token }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ expect { find_user_from_feed_token(:rss) }.to raise_error(Gitlab::Auth::UnauthorizedError)
end
end
@@ -74,34 +75,38 @@ describe Gitlab::Auth::UserAuthFinders do
it 'returns user if valid rssd_token' do
set_param(:rss_token, user.feed_token)
- expect(find_user_from_feed_token).to eq user
+ expect(find_user_from_feed_token(:rss)).to eq user
end
it 'returns nil if rss_token is blank' do
- expect(find_user_from_feed_token).to be_nil
+ expect(find_user_from_feed_token(:rss)).to be_nil
end
it 'returns exception if invalid rss_token' do
set_param(:rss_token, 'invalid_token')
- expect { find_user_from_feed_token }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ expect { find_user_from_feed_token(:rss) }.to raise_error(Gitlab::Auth::UnauthorizedError)
end
end
end
context 'when the request format is not atom' do
it 'returns nil' do
+ env['SCRIPT_NAME'] = 'json'
+
set_param(:feed_token, user.feed_token)
- expect(find_user_from_feed_token).to be_nil
+ expect(find_user_from_feed_token(:rss)).to be_nil
end
end
context 'when the request format is empty' do
it 'the method call does not modify the original value' do
+ env['SCRIPT_NAME'] = 'url.atom'
+
env.delete('action_dispatch.request.formats')
- find_user_from_feed_token
+ find_user_from_feed_token(:rss)
expect(env['action_dispatch.request.formats']).to be_nil
end
@@ -111,8 +116,12 @@ describe Gitlab::Auth::UserAuthFinders do
describe '#find_user_from_access_token' do
let(:personal_access_token) { create(:personal_access_token, user: user) }
+ before do
+ env['SCRIPT_NAME'] = 'url.atom'
+ end
+
it 'returns nil if no access_token present' do
- expect(find_personal_access_token).to be_nil
+ expect(find_user_from_access_token).to be_nil
end
context 'when validate_access_token! returns valid' do
@@ -131,9 +140,59 @@ describe Gitlab::Auth::UserAuthFinders do
end
end
+ describe '#find_user_from_web_access_token' do
+ let(:personal_access_token) { create(:personal_access_token, user: user) }
+
+ before do
+ env[Gitlab::Auth::UserAuthFinders::PRIVATE_TOKEN_HEADER] = personal_access_token.token
+ end
+
+ it 'returns exception if token has no user' do
+ allow_any_instance_of(PersonalAccessToken).to receive(:user).and_return(nil)
+
+ expect { find_user_from_access_token }.to raise_error(Gitlab::Auth::UnauthorizedError)
+ end
+
+ context 'no feed or API requests' do
+ it 'returns nil if the request is not RSS' do
+ expect(find_user_from_web_access_token(:rss)).to be_nil
+ end
+
+ it 'returns nil if the request is not ICS' do
+ expect(find_user_from_web_access_token(:ics)).to be_nil
+ end
+
+ it 'returns nil if the request is not API' do
+ expect(find_user_from_web_access_token(:api)).to be_nil
+ end
+ end
+
+ it 'returns the user for RSS requests' do
+ env['SCRIPT_NAME'] = 'url.atom'
+
+ expect(find_user_from_web_access_token(:rss)).to eq(user)
+ end
+
+ it 'returns the user for ICS requests' do
+ env['SCRIPT_NAME'] = 'url.ics'
+
+ expect(find_user_from_web_access_token(:ics)).to eq(user)
+ end
+
+ it 'returns the user for API requests' do
+ env['SCRIPT_NAME'] = '/api/endpoint'
+
+ expect(find_user_from_web_access_token(:api)).to eq(user)
+ end
+ end
+
describe '#find_personal_access_token' do
let(:personal_access_token) { create(:personal_access_token, user: user) }
+ before do
+ env['SCRIPT_NAME'] = 'url.atom'
+ end
+
context 'passed as header' do
it 'returns token if valid personal_access_token' do
env[Gitlab::Auth::UserAuthFinders::PRIVATE_TOKEN_HEADER] = personal_access_token.token
@@ -220,5 +279,20 @@ describe Gitlab::Auth::UserAuthFinders do
expect { validate_access_token!(scopes: [:sudo]) }.to raise_error(Gitlab::Auth::InsufficientScopeError)
end
end
+
+ context 'with impersonation token' do
+ let(:personal_access_token) { create(:personal_access_token, :impersonation, user: user) }
+
+ context 'when impersonation is disabled' do
+ before do
+ stub_config_setting(impersonation_enabled: false)
+ allow_any_instance_of(described_class).to receive(:access_token).and_return(personal_access_token)
+ end
+
+ it 'returns Gitlab::Auth::ImpersonationDisabled' do
+ expect { validate_access_token! }.to raise_error(Gitlab::Auth::ImpersonationDisabled)
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/background_migration/backfill_project_fullpath_in_repo_config_spec.rb b/spec/lib/gitlab/background_migration/backfill_project_fullpath_in_repo_config_spec.rb
new file mode 100644
index 00000000000..c66d7cd6148
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/backfill_project_fullpath_in_repo_config_spec.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::BackgroundMigration::BackfillProjectFullpathInRepoConfig, :migration, schema: 20181010133639 do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:group) { namespaces.create!(name: 'foo', path: 'foo') }
+ let(:subgroup) { namespaces.create!(name: 'bar', path: 'bar', parent_id: group.id) }
+
+ describe described_class::Storage::HashedProject do
+ let(:project) { double(id: 555) }
+ subject(:project_storage) { described_class.new(project) }
+
+ it 'has the correct disk_path' do
+ expect(project_storage.disk_path).to eq('@hashed/91/a7/91a73fd806ab2c005c13b4dc19130a884e909dea3f72d46e30266fe1a1f588d8')
+ end
+ end
+
+ describe described_class::Storage::LegacyProject do
+ let(:project) { double(full_path: 'this/is/the/full/path') }
+ subject(:project_storage) { described_class.new(project) }
+
+ it 'has the correct disk_path' do
+ expect(project_storage.disk_path).to eq('this/is/the/full/path')
+ end
+ end
+
+ describe described_class::Project do
+ let(:project_record) { projects.create!(namespace_id: subgroup.id, name: 'baz', path: 'baz') }
+ subject(:project) { described_class.find(project_record.id) }
+
+ describe '#full_path' do
+ it 'returns path containing all parent namespaces' do
+ expect(project.full_path).to eq('foo/bar/baz')
+ end
+
+ it 'raises OrphanedNamespaceError when any parent namespace does not exist' do
+ subgroup.update_attribute(:parent_id, namespaces.maximum(:id).succ)
+
+ expect { project.full_path }.to raise_error(Gitlab::BackgroundMigration::BackfillProjectFullpathInRepoConfig::OrphanedNamespaceError)
+ end
+ end
+ end
+
+ describe described_class::Up do
+ describe '#perform' do
+ subject(:migrate) { described_class.new.perform(projects.minimum(:id), projects.maximum(:id)) }
+
+ it 'asks the gitaly client to set config' do
+ projects.create!(namespace_id: subgroup.id, name: 'baz', path: 'baz')
+ projects.create!(namespace_id: subgroup.id, name: 'buzz', path: 'buzz', storage_version: 1)
+
+ expect_next_instance_of(Gitlab::GitalyClient::RepositoryService) do |repository_service|
+ allow(repository_service).to receive(:cleanup)
+ expect(repository_service).to receive(:set_config).with('gitlab.fullpath' => 'foo/bar/baz')
+ end
+
+ expect_next_instance_of(Gitlab::GitalyClient::RepositoryService) do |repository_service|
+ allow(repository_service).to receive(:cleanup)
+ expect(repository_service).to receive(:set_config).with('gitlab.fullpath' => 'foo/bar/buzz')
+ end
+
+ migrate
+ end
+ end
+ end
+
+ describe described_class::Down do
+ describe '#perform' do
+ subject(:migrate) { described_class.new.perform(projects.minimum(:id), projects.maximum(:id)) }
+
+ it 'asks the gitaly client to set config' do
+ projects.create!(namespace_id: subgroup.id, name: 'baz', path: 'baz')
+
+ expect_next_instance_of(Gitlab::GitalyClient::RepositoryService) do |repository_service|
+ allow(repository_service).to receive(:cleanup)
+ expect(repository_service).to receive(:delete_config).with(['gitlab.fullpath'])
+ end
+
+ migrate
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/create_fork_network_memberships_range_spec.rb b/spec/lib/gitlab/background_migration/create_fork_network_memberships_range_spec.rb
index e1c4f9cfea7..5076996474f 100644
--- a/spec/lib/gitlab/background_migration/create_fork_network_memberships_range_spec.rb
+++ b/spec/lib/gitlab/background_migration/create_fork_network_memberships_range_spec.rb
@@ -118,7 +118,7 @@ describe Gitlab::BackgroundMigration::CreateForkNetworkMembershipsRange, :migrat
expect(fork_network_members.count).to eq(12)
end
- it 'knows when not all memberships withing a batch have been created' do
+ it 'knows when not all memberships within a batch have been created' do
expect(migration.missing_members?(8, 10)).to be_truthy
end
end
diff --git a/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb b/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb
index 0735ebd6dcb..5dce3fcbcb6 100644
--- a/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb
+++ b/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :migration, schema: 20171114162227 do
+ include GitHelpers
+
let(:merge_request_diffs) { table(:merge_request_diffs) }
let(:merge_requests) { table(:merge_requests) }
@@ -9,11 +11,7 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :m
let(:merge_request) { merge_requests.create!(iid: 1, target_project_id: project.id, source_project_id: project.id, target_branch: 'feature', source_branch: 'master').becomes(MergeRequest) }
let(:merge_request_diff) { MergeRequest.find(merge_request.id).create_merge_request_diff }
let(:updated_merge_request_diff) { MergeRequestDiff.find(merge_request_diff.id) }
- let(:rugged) do
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.rugged
- end
- end
+ let(:rugged) { rugged_repo(project.repository) }
before do
allow_any_instance_of(MergeRequestDiff)
diff --git a/spec/lib/gitlab/background_migration/digest_column_spec.rb b/spec/lib/gitlab/background_migration/digest_column_spec.rb
new file mode 100644
index 00000000000..3e107ac3027
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/digest_column_spec.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::BackgroundMigration::DigestColumn, :migration, schema: 20180913142237 do
+ let(:personal_access_tokens) { table(:personal_access_tokens) }
+ let(:users) { table(:users) }
+
+ subject { described_class.new }
+
+ describe '#perform' do
+ context 'token is not yet hashed' do
+ before do
+ users.create(id: 1, email: 'user@example.com', projects_limit: 10)
+ personal_access_tokens.create!(id: 1, user_id: 1, name: 'pat-01', token: 'token-01')
+ end
+
+ it 'saves token digest' do
+ expect { subject.perform(PersonalAccessToken, :token, :token_digest, 1, 2) }.to(
+ change { PersonalAccessToken.find(1).token_digest }.from(nil).to(Gitlab::CryptoHelper.sha256('token-01')))
+ end
+
+ it 'erases token' do
+ expect { subject.perform(PersonalAccessToken, :token, :token_digest, 1, 2) }.to(
+ change { PersonalAccessToken.find(1).token }.from('token-01').to(nil))
+ end
+ end
+
+ context 'token is already hashed' do
+ before do
+ users.create(id: 1, email: 'user@example.com', projects_limit: 10)
+ personal_access_tokens.create!(id: 1, user_id: 1, name: 'pat-01', token_digest: 'token-digest-01')
+ end
+
+ it 'does not change existing token digest' do
+ expect { subject.perform(PersonalAccessToken, :token, :token_digest, 1, 2) }.not_to(
+ change { PersonalAccessToken.find(1).token_digest })
+ end
+
+ it 'leaves token empty' do
+ expect { subject.perform(PersonalAccessToken, :token, :token_digest, 1, 2) }.not_to(
+ change { PersonalAccessToken.find(1).token }.from(nil))
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/encrypt_columns_spec.rb b/spec/lib/gitlab/background_migration/encrypt_columns_spec.rb
new file mode 100644
index 00000000000..1d9bac79dcd
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/encrypt_columns_spec.rb
@@ -0,0 +1,94 @@
+require 'spec_helper'
+
+describe Gitlab::BackgroundMigration::EncryptColumns, :migration, schema: 20180910115836 do
+ let(:model) { Gitlab::BackgroundMigration::Models::EncryptColumns::WebHook }
+ let(:web_hooks) { table(:web_hooks) }
+
+ let(:plaintext_attrs) do
+ {
+ 'encrypted_token' => nil,
+ 'encrypted_url' => nil,
+ 'token' => 'secret',
+ 'url' => 'http://example.com?access_token=secret'
+ }
+ end
+
+ let(:encrypted_attrs) do
+ {
+ 'encrypted_token' => be_present,
+ 'encrypted_url' => be_present,
+ 'token' => nil,
+ 'url' => nil
+ }
+ end
+
+ describe '#perform' do
+ it 'encrypts columns for the specified range' do
+ hooks = web_hooks.create([plaintext_attrs] * 5).sort_by(&:id)
+
+ # Encrypt all but the first and last rows
+ subject.perform(model, [:token, :url], hooks[1].id, hooks[3].id)
+
+ hooks = web_hooks.where(id: hooks.map(&:id)).order(:id)
+
+ aggregate_failures do
+ expect(hooks[0]).to have_attributes(plaintext_attrs)
+ expect(hooks[1]).to have_attributes(encrypted_attrs)
+ expect(hooks[2]).to have_attributes(encrypted_attrs)
+ expect(hooks[3]).to have_attributes(encrypted_attrs)
+ expect(hooks[4]).to have_attributes(plaintext_attrs)
+ end
+ end
+
+ it 'acquires an exclusive lock for the update' do
+ relation = double('relation', each: nil)
+
+ expect(model).to receive(:where) { relation }
+ expect(relation).to receive(:lock) { relation }
+
+ subject.perform(model, [:token, :url], 1, 1)
+ end
+
+ it 'skips already-encrypted columns' do
+ values = {
+ 'encrypted_token' => 'known encrypted token',
+ 'encrypted_url' => 'known encrypted url',
+ 'token' => 'token',
+ 'url' => 'url'
+ }
+
+ hook = web_hooks.create(values)
+
+ subject.perform(model, [:token, :url], hook.id, hook.id)
+
+ hook.reload
+
+ expect(hook).to have_attributes(values)
+ end
+
+ it 'reloads the model column information' do
+ expect(model).to receive(:reset_column_information).and_call_original
+ expect(model).to receive(:define_attribute_methods).and_call_original
+
+ subject.perform(model, [:token, :url], 1, 1)
+ end
+
+ it 'fails if a source column is not present' do
+ columns = model.columns.reject { |c| c.name == 'url' }
+ allow(model).to receive(:columns) { columns }
+
+ expect do
+ subject.perform(model, [:token, :url], 1, 1)
+ end.to raise_error(/source column: url is missing/)
+ end
+
+ it 'fails if a destination column is not present' do
+ columns = model.columns.reject { |c| c.name == 'encrypted_url' }
+ allow(model).to receive(:columns) { columns }
+
+ expect do
+ subject.perform(model, [:token, :url], 1, 1)
+ end.to raise_error(/destination column: encrypted_url is missing/)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table_spec.rb b/spec/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table_spec.rb
new file mode 100644
index 00000000000..4f1b01eed41
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/populate_cluster_kubernetes_namespace_table_spec.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::BackgroundMigration::PopulateClusterKubernetesNamespaceTable, :migration, schema: 20181022173835 do
+ let(:migration) { described_class.new }
+ let(:clusters) { create_list(:cluster, 10, :project, :provided_by_gcp) }
+
+ before do
+ clusters
+ end
+
+ shared_examples 'consistent kubernetes namespace attributes' do
+ it 'should populate namespace and service account information' do
+ subject
+
+ clusters_with_namespace.each do |cluster|
+ project = cluster.project
+ cluster_project = cluster.cluster_projects.first
+ namespace = "#{project.path}-#{project.id}"
+ kubernetes_namespace = cluster.reload.kubernetes_namespace
+
+ expect(kubernetes_namespace).to be_present
+ expect(kubernetes_namespace.cluster_project).to eq(cluster_project)
+ expect(kubernetes_namespace.project).to eq(cluster_project.project)
+ expect(kubernetes_namespace.cluster).to eq(cluster_project.cluster)
+ expect(kubernetes_namespace.namespace).to eq(namespace)
+ expect(kubernetes_namespace.service_account_name).to eq("#{namespace}-service-account")
+ end
+ end
+ end
+
+ subject { migration.perform }
+
+ context 'when no Clusters::Project has a Clusters::KubernetesNamespace' do
+ let(:cluster_projects) { Clusters::Project.all }
+
+ it 'should create a Clusters::KubernetesNamespace per Clusters::Project' do
+ expect do
+ subject
+ end.to change(Clusters::KubernetesNamespace, :count).by(cluster_projects.count)
+ end
+
+ it_behaves_like 'consistent kubernetes namespace attributes' do
+ let(:clusters_with_namespace) { clusters }
+ end
+ end
+
+ context 'when every Clusters::Project has Clusters::KubernetesNamespace' do
+ before do
+ clusters.each do |cluster|
+ create(:cluster_kubernetes_namespace,
+ cluster_project: cluster.cluster_projects.first,
+ cluster: cluster,
+ project: cluster.project)
+ end
+ end
+
+ it 'should not create any Clusters::KubernetesNamespace' do
+ expect do
+ subject
+ end.not_to change(Clusters::KubernetesNamespace, :count)
+ end
+ end
+
+ context 'when only some Clusters::Project have Clusters::KubernetesNamespace related' do
+ let(:with_kubernetes_namespace) { clusters.first(6) }
+ let(:with_no_kubernetes_namespace) { clusters.last(4) }
+
+ before do
+ with_kubernetes_namespace.each do |cluster|
+ create(:cluster_kubernetes_namespace,
+ cluster_project: cluster.cluster_projects.first,
+ cluster: cluster,
+ project: cluster.project)
+ end
+ end
+
+ it 'creates limited number of Clusters::KubernetesNamespace' do
+ expect do
+ subject
+ end.to change(Clusters::KubernetesNamespace, :count).by(with_no_kubernetes_namespace.count)
+ end
+
+ it 'should not modify clusters with Clusters::KubernetesNamespace' do
+ subject
+
+ with_kubernetes_namespace.each do |cluster|
+ expect(cluster.kubernetes_namespaces.count).to eq(1)
+ end
+ end
+
+ it_behaves_like 'consistent kubernetes namespace attributes' do
+ let(:clusters_with_namespace) { with_no_kubernetes_namespace }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/populate_external_pipeline_source_spec.rb b/spec/lib/gitlab/background_migration/populate_external_pipeline_source_spec.rb
new file mode 100644
index 00000000000..c7b272cd6ca
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/populate_external_pipeline_source_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::BackgroundMigration::PopulateExternalPipelineSource, :migration, schema: 20180916011959 do
+ let(:migration) { described_class.new }
+
+ let!(:internal_pipeline) { create(:ci_pipeline, source: :web) }
+ let(:pipelines) { [internal_pipeline, unknown_pipeline].map(&:id) }
+
+ let!(:unknown_pipeline) do
+ build(:ci_pipeline, source: :unknown)
+ .tap { |pipeline| pipeline.save(validate: false) }
+ end
+
+ subject { migration.perform(pipelines.min, pipelines.max) }
+
+ shared_examples 'no changes' do
+ it 'does not change the pipeline source' do
+ expect { subject }.not_to change { unknown_pipeline.reload.source }
+ end
+ end
+
+ context 'when unknown pipeline is external' do
+ before do
+ create(:generic_commit_status, pipeline: unknown_pipeline)
+ end
+
+ it 'populates the pipeline source' do
+ subject
+
+ expect(unknown_pipeline.reload.source).to eq('external')
+ end
+
+ it 'can be repeated without effect' do
+ subject
+
+ expect { subject }.not_to change { unknown_pipeline.reload.source }
+ end
+ end
+
+ context 'when unknown pipeline has just a build' do
+ before do
+ create(:ci_build, pipeline: unknown_pipeline)
+ end
+
+ it_behaves_like 'no changes'
+ end
+
+ context 'when unknown pipeline has no statuses' do
+ it_behaves_like 'no changes'
+ end
+
+ context 'when unknown pipeline has a build and a status' do
+ before do
+ create(:generic_commit_status, pipeline: unknown_pipeline)
+ create(:ci_build, pipeline: unknown_pipeline)
+ end
+
+ it_behaves_like 'no changes'
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/redact_links_spec.rb b/spec/lib/gitlab/background_migration/redact_links_spec.rb
new file mode 100644
index 00000000000..a40e68069cc
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/redact_links_spec.rb
@@ -0,0 +1,96 @@
+require 'spec_helper'
+
+describe Gitlab::BackgroundMigration::RedactLinks, :migration, schema: 20181014121030 do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:issues) { table(:issues) }
+ let(:notes) { table(:notes) }
+ let(:snippets) { table(:snippets) }
+ let(:users) { table(:users) }
+ let(:merge_requests) { table(:merge_requests) }
+ let(:namespace) { namespaces.create(name: 'gitlab', path: 'gitlab-org') }
+ let(:project) { projects.create(namespace_id: namespace.id, name: 'foo') }
+ let(:user) { users.create!(email: 'test@example.com', projects_limit: 100, username: 'test') }
+
+ def create_merge_request(id, params)
+ params.merge!(id: id,
+ target_project_id: project.id,
+ target_branch: 'master',
+ source_project_id: project.id,
+ source_branch: 'mr name',
+ title: "mr name#{id}")
+
+ merge_requests.create(params)
+ end
+
+ def create_issue(id, params)
+ params.merge!(id: id, title: "issue#{id}", project_id: project.id)
+
+ issues.create(params)
+ end
+
+ def create_note(id, params)
+ params[:id] = id
+
+ notes.create(params)
+ end
+
+ def create_snippet(id, params)
+ params.merge!(id: id, author_id: user.id)
+
+ snippets.create(params)
+ end
+
+ def create_resource(model, id, params)
+ send("create_#{model.name.underscore}", id, params)
+ end
+
+ shared_examples_for 'redactable resource' do
+ it 'updates only matching texts' do
+ matching_text = 'some text /sent_notifications/00000000000000000000000000000000/unsubscribe more text'
+ redacted_text = 'some text /sent_notifications/REDACTED/unsubscribe more text'
+ create_resource(model, 1, { field => matching_text })
+ create_resource(model, 2, { field => 'not matching text' })
+ create_resource(model, 3, { field => matching_text })
+ create_resource(model, 4, { field => redacted_text })
+ create_resource(model, 5, { field => matching_text })
+
+ expected = { field => 'some text /sent_notifications/REDACTED/unsubscribe more text',
+ "#{field}_html" => nil }
+ expect_any_instance_of("Gitlab::BackgroundMigration::RedactLinks::#{model}".constantize).to receive(:update_columns).with(expected).and_call_original
+
+ subject.perform(model, field, 2, 4)
+
+ expect(model.where(field => matching_text).pluck(:id)).to eq [1, 5]
+ expect(model.find(3).reload[field]).to eq redacted_text
+ end
+ end
+
+ context 'resource is Issue' do
+ it_behaves_like 'redactable resource' do
+ let(:model) { Issue }
+ let(:field) { :description }
+ end
+ end
+
+ context 'resource is Merge Request' do
+ it_behaves_like 'redactable resource' do
+ let(:model) { MergeRequest }
+ let(:field) { :description }
+ end
+ end
+
+ context 'resource is Note' do
+ it_behaves_like 'redactable resource' do
+ let(:model) { Note }
+ let(:field) { :note }
+ end
+ end
+
+ context 'resource is Snippet' do
+ it_behaves_like 'redactable resource' do
+ let(:model) { Snippet }
+ let(:field) { :description }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb b/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb
index ed6fa3d229f..e2bee22cf1f 100644
--- a/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb
+++ b/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb
@@ -11,7 +11,7 @@ describe Gitlab::BitbucketImport::ProjectCreator do
owner: "asd",
full_name: 'Vim repo',
visibility_level: Gitlab::VisibilityLevel::PRIVATE,
- clone_url: 'ssh://git@bitbucket.org/asd/vim.git',
+ clone_url: 'http://bitbucket.org/asd/vim.git',
has_wiki?: false)
end
@@ -32,7 +32,7 @@ describe Gitlab::BitbucketImport::ProjectCreator do
project_creator = described_class.new(repo, 'vim', namespace, user, access_params)
project = project_creator.execute
- expect(project.import_url).to eq("ssh://git@bitbucket.org/asd/vim.git")
+ expect(project.import_url).to eq("http://bitbucket.org/asd/vim.git")
expect(project.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
end
end
diff --git a/spec/lib/gitlab/blob_helper_spec.rb b/spec/lib/gitlab/blob_helper_spec.rb
new file mode 100644
index 00000000000..0b56f8687c3
--- /dev/null
+++ b/spec/lib/gitlab/blob_helper_spec.rb
@@ -0,0 +1,125 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::BlobHelper do
+ include FakeBlobHelpers
+
+ let(:project) { create(:project) }
+ let(:blob) { fake_blob(path: 'file.txt') }
+ let(:large_blob) { fake_blob(path: 'test.pdf', size: 2.megabytes, binary: true) }
+
+ describe '#extname' do
+ it 'returns the extension' do
+ expect(blob.extname).to eq('.txt')
+ end
+ end
+
+ describe '#known_extension?' do
+ it 'returns true' do
+ expect(blob.known_extension?).to be_truthy
+ end
+ end
+
+ describe '#viewable' do
+ it 'returns true' do
+ expect(blob.viewable?).to be_truthy
+ end
+
+ it 'returns false' do
+ expect(large_blob.viewable?).to be_falsey
+ end
+ end
+
+ describe '#large?' do
+ it 'returns false' do
+ expect(blob.large?).to be_falsey
+ end
+
+ it 'returns true' do
+ expect(large_blob.large?).to be_truthy
+ end
+ end
+
+ describe '#binary?' do
+ it 'returns true' do
+ expect(large_blob.binary?).to be_truthy
+ end
+
+ it 'returns false' do
+ expect(blob.binary?).to be_falsey
+ end
+ end
+
+ describe '#text?' do
+ it 'returns true' do
+ expect(blob.text?).to be_truthy
+ end
+
+ it 'returns false' do
+ expect(large_blob.text?).to be_falsey
+ end
+ end
+
+ describe '#image?' do
+ it 'returns false' do
+ expect(blob.image?).to be_falsey
+ end
+ end
+
+ describe '#mime_type' do
+ it 'returns text/plain' do
+ expect(blob.mime_type).to eq('text/plain')
+ end
+
+ it 'returns application/pdf' do
+ expect(large_blob.mime_type).to eq('application/pdf')
+ end
+ end
+
+ describe '#binary_mime_type?' do
+ it 'returns false' do
+ expect(blob.binary_mime_type?).to be_falsey
+ end
+ end
+
+ describe '#lines' do
+ it 'returns the payload in an Array' do
+ expect(blob.lines).to eq(['foo'])
+ end
+ end
+
+ describe '#content_type' do
+ it 'returns text/plain' do
+ expect(blob.content_type).to eq('text/plain; charset=utf-8')
+ end
+
+ it 'returns text/plain' do
+ expect(large_blob.content_type).to eq('application/pdf')
+ end
+ end
+
+ describe '#encoded_newlines_re' do
+ it 'returns a regular expression' do
+ expect(blob.encoded_newlines_re).to eq(/\r\n|\r|\n/)
+ end
+ end
+
+ describe '#ruby_encoding' do
+ it 'returns UTF-8' do
+ expect(blob.ruby_encoding).to eq('UTF-8')
+ end
+ end
+
+ describe '#encoding' do
+ it 'returns UTF-8' do
+ expect(blob.ruby_encoding).to eq('UTF-8')
+ end
+ end
+
+ describe '#empty?' do
+ it 'returns false' do
+ expect(blob.empty?).to be_falsey
+ end
+ end
+end
diff --git a/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb b/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb
index 18658588a40..be9b2588c90 100644
--- a/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb
+++ b/spec/lib/gitlab/cache/ci/project_pipeline_status_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe Gitlab::Cache::Ci::ProjectPipelineStatus, :clean_gitlab_redis_cache do
let!(:project) { create(:project, :repository) }
let(:pipeline_status) { described_class.new(project) }
- let(:cache_key) { described_class.cache_key_for_project(project) }
+ let(:cache_key) { pipeline_status.cache_key }
describe '.load_for_project' do
it "loads the status" do
@@ -14,96 +14,24 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :clean_gitlab_redis_cache do
end
describe 'loading in batches' do
- let(:status) { 'success' }
- let(:sha) { '424d1b73bc0d3cb726eb7dc4ce17a4d48552f8c6' }
- let(:ref) { 'master' }
- let(:pipeline_info) { { sha: sha, status: status, ref: ref } }
- let!(:project_without_status) { create(:project, :repository) }
-
describe '.load_in_batch_for_projects' do
- it 'preloads pipeline_status on projects' do
+ it 'loads pipeline_status on projects' do
described_class.load_in_batch_for_projects([project])
# Don't call the accessor that would lazy load the variable
- expect(project.instance_variable_get('@pipeline_status')).to be_a(described_class)
- end
-
- describe 'without a status in redis_cache' do
- it 'loads the status from a commit when it was not in redis_cache' do
- empty_status = { sha: nil, status: nil, ref: nil }
- fake_pipeline = described_class.new(
- project_without_status,
- pipeline_info: empty_status,
- loaded_from_cache: false
- )
-
- expect(described_class).to receive(:new)
- .with(project_without_status,
- pipeline_info: empty_status,
- loaded_from_cache: false)
- .and_return(fake_pipeline)
- expect(fake_pipeline).to receive(:load_from_project)
- expect(fake_pipeline).to receive(:store_in_cache)
-
- described_class.load_in_batch_for_projects([project_without_status])
- end
-
- it 'only connects to redis twice' do
- # Stub circuitbreaker so it doesn't count the redis connections in there
- stub_circuit_breaker(project_without_status)
- expect(Gitlab::Redis::Cache).to receive(:with).exactly(2).and_call_original
-
- described_class.load_in_batch_for_projects([project_without_status])
-
- expect(project_without_status.pipeline_status).not_to be_nil
- end
- end
-
- describe 'when a status was cached in redis_cache' do
- before do
- Gitlab::Redis::Cache.with do |redis|
- redis.mapped_hmset(cache_key,
- { sha: sha, status: status, ref: ref })
- end
- end
-
- it 'loads the correct status' do
- described_class.load_in_batch_for_projects([project])
-
- pipeline_status = project.instance_variable_get('@pipeline_status')
-
- expect(pipeline_status.sha).to eq(sha)
- expect(pipeline_status.status).to eq(status)
- expect(pipeline_status.ref).to eq(ref)
- end
-
- it 'only connects to redis_cache once' do
- expect(Gitlab::Redis::Cache).to receive(:with).exactly(1).and_call_original
-
- described_class.load_in_batch_for_projects([project])
-
- expect(project.pipeline_status).not_to be_nil
- end
-
- it "doesn't load the status separatly" do
- expect_any_instance_of(described_class).not_to receive(:load_from_project)
- expect_any_instance_of(described_class).not_to receive(:load_from_cache)
+ project_pipeline_status = project.instance_variable_get('@pipeline_status')
- described_class.load_in_batch_for_projects([project])
- end
+ expect(project_pipeline_status).to be_a(described_class)
+ expect(project_pipeline_status).to be_loaded
end
- end
- describe '.cached_results_for_projects' do
- it 'loads a status from caching for all projects' do
- Gitlab::Redis::Cache.with do |redis|
- redis.mapped_hmset(cache_key, { sha: sha, status: status, ref: ref })
+ it 'loads 10 projects without hitting Gitaly call limit', :request_store do
+ projects = Gitlab::GitalyClient.allow_n_plus_1_calls do
+ (1..10).map { create(:project, :repository) }
end
+ Gitlab::GitalyClient.reset_counts
- result = [{ loaded_from_cache: false, pipeline_info: { sha: nil, status: nil, ref: nil } },
- { loaded_from_cache: true, pipeline_info: pipeline_info }]
-
- expect(described_class.cached_results_for_projects([project_without_status, project])).to eq(result)
+ expect { described_class.load_in_batch_for_projects(projects) }.not_to raise_error
end
end
end
@@ -200,7 +128,9 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :clean_gitlab_redis_cache do
status_for_empty_commit.load_status
- expect(status_for_empty_commit).to be_loaded
+ expect(status_for_empty_commit.sha).to be_nil
+ expect(status_for_empty_commit.status).to be_nil
+ expect(status_for_empty_commit.ref).to be_nil
end
end
@@ -284,6 +214,21 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :clean_gitlab_redis_cache do
expect(pipeline_status.status).to eq(status)
expect(pipeline_status.ref).to eq(ref)
end
+
+ context 'when status is empty string' do
+ before do
+ Gitlab::Redis::Cache.with do |redis|
+ redis.mapped_hmset(cache_key,
+ { sha: sha, status: '', ref: ref })
+ end
+ end
+
+ it 'reads the status as nil' do
+ pipeline_status.load_from_cache
+
+ expect(pipeline_status.status).to eq(nil)
+ end
+ end
end
describe '#has_cache?' do
@@ -302,13 +247,4 @@ describe Gitlab::Cache::Ci::ProjectPipelineStatus, :clean_gitlab_redis_cache do
end
end
end
-
- def stub_circuit_breaker(project)
- fake_circuitbreaker = double
- allow(fake_circuitbreaker).to receive(:perform).and_yield
- allow(project.repository.raw_repository)
- .to receive(:circuit_breaker).and_return(fake_circuitbreaker)
- allow(project.repository)
- .to receive(:circuit_breaker).and_return(fake_circuitbreaker)
- end
end
diff --git a/spec/lib/gitlab/checks/branch_check_spec.rb b/spec/lib/gitlab/checks/branch_check_spec.rb
new file mode 100644
index 00000000000..77366e91dca
--- /dev/null
+++ b/spec/lib/gitlab/checks/branch_check_spec.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Checks::BranchCheck do
+ include_context 'change access checks context'
+
+ describe '#validate!' do
+ it 'does not raise any error' do
+ expect { subject.validate! }.not_to raise_error
+ end
+
+ context 'trying to delete the default branch' do
+ let(:newrev) { '0000000000000000000000000000000000000000' }
+ let(:ref) { 'refs/heads/master' }
+
+ it 'raises an error' do
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'The default branch of a project cannot be deleted.')
+ end
+ end
+
+ context 'protected branches check' do
+ before do
+ allow(ProtectedBranch).to receive(:protected?).with(project, 'master').and_return(true)
+ allow(ProtectedBranch).to receive(:protected?).with(project, 'feature').and_return(true)
+ end
+
+ it 'raises an error if the user is not allowed to do forced pushes to protected branches' do
+ expect(Gitlab::Checks::ForcePush).to receive(:force_push?).and_return(true)
+
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to force push code to a protected branch on this project.')
+ end
+
+ it 'raises an error if the user is not allowed to merge to protected branches' do
+ expect_any_instance_of(Gitlab::Checks::MatchingMergeRequest).to receive(:match?).and_return(true)
+ expect(user_access).to receive(:can_merge_to_branch?).and_return(false)
+ expect(user_access).to receive(:can_push_to_branch?).and_return(false)
+
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to merge code into protected branches on this project.')
+ end
+
+ it 'raises an error if the user is not allowed to push to protected branches' do
+ expect(user_access).to receive(:can_push_to_branch?).and_return(false)
+
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to push code to protected branches on this project.')
+ end
+
+ context 'when project repository is empty' do
+ let(:project) { create(:project) }
+
+ it 'raises an error if the user is not allowed to push to protected branches' do
+ expect(user_access).to receive(:can_push_to_branch?).and_return(false)
+
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /Ask a project Owner or Maintainer to create a default branch/)
+ end
+ end
+
+ context 'branch deletion' do
+ let(:newrev) { '0000000000000000000000000000000000000000' }
+ let(:ref) { 'refs/heads/feature' }
+
+ context 'if the user is not allowed to delete protected branches' do
+ it 'raises an error' do
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to delete protected branches from this project. Only a project maintainer or owner can delete a protected branch.')
+ end
+ end
+
+ context 'if the user is allowed to delete protected branches' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ context 'through the web interface' do
+ let(:protocol) { 'web' }
+
+ it 'allows branch deletion' do
+ expect { subject.validate! }.not_to raise_error
+ end
+ end
+
+ context 'over SSH or HTTP' do
+ it 'raises an error' do
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You can only delete protected branches using the web interface.')
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/checks/change_access_spec.rb b/spec/lib/gitlab/checks/change_access_spec.rb
index 4df426c54ae..45fb33e9e4a 100644
--- a/spec/lib/gitlab/checks/change_access_spec.rb
+++ b/spec/lib/gitlab/checks/change_access_spec.rb
@@ -2,229 +2,56 @@ require 'spec_helper'
describe Gitlab::Checks::ChangeAccess do
describe '#exec' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
- let(:user_access) { Gitlab::UserAccess.new(user, project: project) }
- let(:oldrev) { 'be93687618e4b132087f430a4d8fc3a609c9b77c' }
- let(:newrev) { '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51' }
- let(:ref) { 'refs/heads/master' }
- let(:changes) { { oldrev: oldrev, newrev: newrev, ref: ref } }
- let(:protocol) { 'ssh' }
+ include_context 'change access checks context'
- subject(:change_access) do
- described_class.new(
- changes,
- project: project,
- user_access: user_access,
- protocol: protocol
- )
- end
-
- before do
- project.add_developer(user)
- end
+ subject { change_access }
context 'without failed checks' do
it "doesn't raise an error" do
expect { subject.exec }.not_to raise_error
end
- end
- context 'when the user is not allowed to push to the repo' do
- it 'raises an error' do
- expect(user_access).to receive(:can_do_action?).with(:push_code).and_return(false)
- expect(user_access).to receive(:can_push_to_branch?).with('master').and_return(false)
+ it 'calls pushes checks' do
+ expect_any_instance_of(Gitlab::Checks::PushCheck).to receive(:validate!)
- expect { subject.exec }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to push code to this project.')
+ subject.exec
end
- end
-
- context 'tags check' do
- let(:ref) { 'refs/tags/v1.0.0' }
- it 'raises an error if the user is not allowed to update tags' do
- allow(user_access).to receive(:can_do_action?).with(:push_code).and_return(true)
- expect(user_access).to receive(:can_do_action?).with(:admin_project).and_return(false)
+ it 'calls branches checks' do
+ expect_any_instance_of(Gitlab::Checks::BranchCheck).to receive(:validate!)
- expect { subject.exec }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to change existing tags on this project.')
+ subject.exec
end
- context 'with protected tag' do
- let!(:protected_tag) { create(:protected_tag, project: project, name: 'v*') }
-
- context 'as maintainer' do
- before do
- project.add_maintainer(user)
- end
-
- context 'deletion' do
- let(:oldrev) { 'be93687618e4b132087f430a4d8fc3a609c9b77c' }
- let(:newrev) { '0000000000000000000000000000000000000000' }
-
- it 'is prevented' do
- expect { subject.exec }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /cannot be deleted/)
- end
- end
-
- context 'update' do
- let(:oldrev) { 'be93687618e4b132087f430a4d8fc3a609c9b77c' }
- let(:newrev) { '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51' }
-
- it 'is prevented' do
- expect { subject.exec }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /cannot be updated/)
- end
- end
- end
-
- context 'creation' do
- let(:oldrev) { '0000000000000000000000000000000000000000' }
- let(:newrev) { '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51' }
- let(:ref) { 'refs/tags/v9.1.0' }
+ it 'calls tags checks' do
+ expect_any_instance_of(Gitlab::Checks::TagCheck).to receive(:validate!)
- it 'prevents creation below access level' do
- expect { subject.exec }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /allowed to create this tag as it is protected/)
- end
-
- context 'when user has access' do
- let!(:protected_tag) { create(:protected_tag, :developers_can_create, project: project, name: 'v*') }
-
- it 'allows tag creation' do
- expect { subject.exec }.not_to raise_error
- end
- end
- end
+ subject.exec
end
- end
- context 'branches check' do
- context 'trying to delete the default branch' do
- let(:newrev) { '0000000000000000000000000000000000000000' }
- let(:ref) { 'refs/heads/master' }
+ it 'calls lfs checks' do
+ expect_any_instance_of(Gitlab::Checks::LfsCheck).to receive(:validate!)
- it 'raises an error' do
- expect { subject.exec }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'The default branch of a project cannot be deleted.')
- end
+ subject.exec
end
- context 'protected branches check' do
- before do
- allow(ProtectedBranch).to receive(:protected?).with(project, 'master').and_return(true)
- allow(ProtectedBranch).to receive(:protected?).with(project, 'feature').and_return(true)
- end
-
- it 'raises an error if the user is not allowed to do forced pushes to protected branches' do
- expect(Gitlab::Checks::ForcePush).to receive(:force_push?).and_return(true)
-
- expect { subject.exec }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to force push code to a protected branch on this project.')
- end
-
- it 'raises an error if the user is not allowed to merge to protected branches' do
- expect_any_instance_of(Gitlab::Checks::MatchingMergeRequest).to receive(:match?).and_return(true)
- expect(user_access).to receive(:can_merge_to_branch?).and_return(false)
- expect(user_access).to receive(:can_push_to_branch?).and_return(false)
-
- expect { subject.exec }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to merge code into protected branches on this project.')
- end
-
- it 'raises an error if the user is not allowed to push to protected branches' do
- expect(user_access).to receive(:can_push_to_branch?).and_return(false)
-
- expect { subject.exec }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to push code to protected branches on this project.')
- end
-
- context 'when project repository is empty' do
- let(:project) { create(:project) }
-
- it 'raises an error if the user is not allowed to push to protected branches' do
- expect(user_access).to receive(:can_push_to_branch?).and_return(false)
+ it 'calls diff checks' do
+ expect_any_instance_of(Gitlab::Checks::DiffCheck).to receive(:validate!)
- expect { subject.exec }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /Ask a project Owner or Maintainer to create a default branch/)
- end
- end
-
- context 'branch deletion' do
- let(:newrev) { '0000000000000000000000000000000000000000' }
- let(:ref) { 'refs/heads/feature' }
-
- context 'if the user is not allowed to delete protected branches' do
- it 'raises an error' do
- expect { subject.exec }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to delete protected branches from this project. Only a project maintainer or owner can delete a protected branch.')
- end
- end
-
- context 'if the user is allowed to delete protected branches' do
- before do
- project.add_maintainer(user)
- end
-
- context 'through the web interface' do
- let(:protocol) { 'web' }
-
- it 'allows branch deletion' do
- expect { subject.exec }.not_to raise_error
- end
- end
-
- context 'over SSH or HTTP' do
- it 'raises an error' do
- expect { subject.exec }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You can only delete protected branches using the web interface.')
- end
- end
- end
- end
- end
- end
-
- context 'LFS integrity check' do
- it 'fails if any LFS blobs are missing' do
- allow_any_instance_of(Gitlab::Checks::LfsIntegrity).to receive(:objects_missing?).and_return(true)
-
- expect { subject.exec }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /LFS objects are missing/)
- end
-
- it 'succeeds if LFS objects have already been uploaded' do
- allow_any_instance_of(Gitlab::Checks::LfsIntegrity).to receive(:objects_missing?).and_return(false)
-
- expect { subject.exec }.not_to raise_error
+ subject.exec
end
end
- context 'LFS file lock check' do
- let(:owner) { create(:user) }
- let!(:lock) { create(:lfs_file_lock, user: owner, project: project, path: 'README') }
-
- before do
- allow(project.repository).to receive(:new_commits).and_return(
- project.repository.commits_between('be93687618e4b132087f430a4d8fc3a609c9b77c', '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51')
- )
- end
-
- context 'with LFS not enabled' do
- it 'skips the validation' do
- expect_any_instance_of(Gitlab::Checks::CommitCheck).not_to receive(:validate)
-
- subject.exec
- end
- end
-
- context 'with LFS enabled' do
- before do
- allow(project).to receive(:lfs_enabled?).and_return(true)
- end
-
- context 'when change is sent by a different user' do
- it 'raises an error if the user is not allowed to update the file' do
- expect { subject.exec }.to raise_error(Gitlab::GitAccess::UnauthorizedError, "The path 'README' is locked in Git LFS by #{lock.user.name}")
- end
- end
-
- context 'when change is sent by the author of the lock' do
- let(:user) { owner }
+ context 'when time limit was reached' do
+ it 'raises a TimeoutError' do
+ logger = Gitlab::Checks::TimedLogger.new(start_time: timeout.ago, timeout: timeout)
+ access = described_class.new(changes,
+ project: project,
+ user_access: user_access,
+ protocol: protocol,
+ logger: logger)
- it "doesn't raise any error" do
- expect { subject.exec }.not_to raise_error
- end
- end
+ expect { access.exec }.to raise_error(Gitlab::Checks::TimedLogger::TimeoutError)
end
end
end
diff --git a/spec/lib/gitlab/checks/diff_check_spec.rb b/spec/lib/gitlab/checks/diff_check_spec.rb
new file mode 100644
index 00000000000..eeec1e83179
--- /dev/null
+++ b/spec/lib/gitlab/checks/diff_check_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Checks::DiffCheck do
+ include_context 'change access checks context'
+
+ describe '#validate!' do
+ let(:owner) { create(:user) }
+ let!(:lock) { create(:lfs_file_lock, user: owner, project: project, path: 'README') }
+
+ before do
+ allow(project.repository).to receive(:new_commits).and_return(
+ project.repository.commits_between('be93687618e4b132087f430a4d8fc3a609c9b77c', '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51')
+ )
+ end
+
+ context 'with LFS not enabled' do
+ before do
+ allow(project).to receive(:lfs_enabled?).and_return(false)
+ end
+
+ it 'skips the validation' do
+ expect(subject).not_to receive(:validate_diff)
+ expect(subject).not_to receive(:validate_file_paths)
+
+ subject.validate!
+ end
+ end
+
+ context 'with LFS enabled' do
+ before do
+ allow(project).to receive(:lfs_enabled?).and_return(true)
+ end
+
+ context 'when change is sent by a different user' do
+ it 'raises an error if the user is not allowed to update the file' do
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, "The path 'README' is locked in Git LFS by #{lock.user.name}")
+ end
+ end
+
+ context 'when change is sent by the author of the lock' do
+ let(:user) { owner }
+
+ it "doesn't raise any error" do
+ expect { subject.validate! }.not_to raise_error
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/checks/lfs_check_spec.rb b/spec/lib/gitlab/checks/lfs_check_spec.rb
new file mode 100644
index 00000000000..35f8069c8a4
--- /dev/null
+++ b/spec/lib/gitlab/checks/lfs_check_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Checks::LfsCheck do
+ include_context 'change access checks context'
+
+ let(:blob_object) { project.repository.blob_at_branch('lfs', 'files/lfs/lfs_object.iso') }
+
+ before do
+ allow_any_instance_of(Gitlab::Git::LfsChanges).to receive(:new_pointers) do
+ [blob_object]
+ end
+ end
+
+ describe '#validate!' do
+ context 'with LFS not enabled' do
+ it 'skips integrity check' do
+ expect_any_instance_of(Gitlab::Git::LfsChanges).not_to receive(:new_pointers)
+
+ subject.validate!
+ end
+ end
+
+ context 'with LFS enabled' do
+ before do
+ allow(project).to receive(:lfs_enabled?).and_return(true)
+ end
+
+ context 'deletion' do
+ let(:changes) { { oldrev: oldrev, ref: ref } }
+
+ it 'skips integrity check' do
+ expect(project.repository).not_to receive(:new_objects)
+
+ subject.validate!
+ end
+ end
+
+ it 'fails if any LFS blobs are missing' do
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /LFS objects are missing/)
+ end
+
+ it 'succeeds if LFS objects have already been uploaded' do
+ lfs_object = create(:lfs_object, oid: blob_object.lfs_oid)
+ create(:lfs_objects_project, project: project, lfs_object: lfs_object)
+
+ expect { subject.validate! }.not_to raise_error
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/checks/lfs_integrity_spec.rb b/spec/lib/gitlab/checks/lfs_integrity_spec.rb
index ec22e3a198e..887ea8fc1e0 100644
--- a/spec/lib/gitlab/checks/lfs_integrity_spec.rb
+++ b/spec/lib/gitlab/checks/lfs_integrity_spec.rb
@@ -3,6 +3,7 @@ require 'spec_helper'
describe Gitlab::Checks::LfsIntegrity do
include ProjectForksHelper
+ let!(:time_left) { 50 }
let(:project) { create(:project, :repository) }
let(:repository) { project.repository }
let(:newrev) do
@@ -15,7 +16,7 @@ describe Gitlab::Checks::LfsIntegrity do
operations.commit_tree('8856a329dd38ca86dfb9ce5aa58a16d88cc119bd', "New LFS objects")
end
- subject { described_class.new(project, newrev) }
+ subject { described_class.new(project, newrev, time_left) }
describe '#objects_missing?' do
let(:blob_object) { repository.blob_at_branch('lfs', 'files/lfs/lfs_object.iso') }
@@ -67,7 +68,7 @@ describe Gitlab::Checks::LfsIntegrity do
expect(subject.objects_missing?).to be_truthy
end
- it 'is false parent project already conatins LFS objects for the fork' do
+ it 'is false parent project already contains LFS objects for the fork' do
lfs_object = create(:lfs_object, oid: blob_object.lfs_oid)
create(:lfs_objects_project, project: parent_project, lfs_object: lfs_object)
diff --git a/spec/lib/gitlab/checks/push_check_spec.rb b/spec/lib/gitlab/checks/push_check_spec.rb
new file mode 100644
index 00000000000..25f0d428cb9
--- /dev/null
+++ b/spec/lib/gitlab/checks/push_check_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Checks::PushCheck do
+ include_context 'change access checks context'
+
+ describe '#validate!' do
+ it 'does not raise any error' do
+ expect { subject.validate! }.not_to raise_error
+ end
+
+ context 'when the user is not allowed to push to the repo' do
+ it 'raises an error' do
+ expect(user_access).to receive(:can_do_action?).with(:push_code).and_return(false)
+ expect(user_access).to receive(:can_push_to_branch?).with('master').and_return(false)
+
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to push code to this project.')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/checks/tag_check_spec.rb b/spec/lib/gitlab/checks/tag_check_spec.rb
new file mode 100644
index 00000000000..b1258270611
--- /dev/null
+++ b/spec/lib/gitlab/checks/tag_check_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Checks::TagCheck do
+ include_context 'change access checks context'
+
+ describe '#validate!' do
+ let(:ref) { 'refs/tags/v1.0.0' }
+
+ it 'raises an error' do
+ allow(user_access).to receive(:can_do_action?).with(:push_code).and_return(true)
+ expect(user_access).to receive(:can_do_action?).with(:admin_project).and_return(false)
+
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, 'You are not allowed to change existing tags on this project.')
+ end
+
+ context 'with protected tag' do
+ let!(:protected_tag) { create(:protected_tag, project: project, name: 'v*') }
+
+ context 'as maintainer' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ context 'deletion' do
+ let(:oldrev) { 'be93687618e4b132087f430a4d8fc3a609c9b77c' }
+ let(:newrev) { '0000000000000000000000000000000000000000' }
+
+ it 'is prevented' do
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /cannot be deleted/)
+ end
+ end
+
+ context 'update' do
+ let(:oldrev) { 'be93687618e4b132087f430a4d8fc3a609c9b77c' }
+ let(:newrev) { '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51' }
+
+ it 'is prevented' do
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /cannot be updated/)
+ end
+ end
+ end
+
+ context 'creation' do
+ let(:oldrev) { '0000000000000000000000000000000000000000' }
+ let(:newrev) { '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51' }
+ let(:ref) { 'refs/tags/v9.1.0' }
+
+ it 'prevents creation below access level' do
+ expect { subject.validate! }.to raise_error(Gitlab::GitAccess::UnauthorizedError, /allowed to create this tag as it is protected/)
+ end
+
+ context 'when user has access' do
+ let!(:protected_tag) { create(:protected_tag, :developers_can_create, project: project, name: 'v*') }
+
+ it 'allows tag creation' do
+ expect { subject.validate! }.not_to raise_error
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/checks/timed_logger_spec.rb b/spec/lib/gitlab/checks/timed_logger_spec.rb
new file mode 100644
index 00000000000..0ed3940c038
--- /dev/null
+++ b/spec/lib/gitlab/checks/timed_logger_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Checks::TimedLogger do
+ let!(:timeout) { 50.seconds }
+ let!(:start) { Time.now }
+ let!(:ref) { "bar" }
+ let!(:logger) { described_class.new(start_time: start, timeout: timeout) }
+ let!(:log_messages) do
+ {
+ foo: "Foo message..."
+ }
+ end
+
+ before do
+ logger.append_message("Checking ref: #{ref}")
+ end
+
+ describe '#log_timed' do
+ it 'logs message' do
+ Timecop.freeze(start + 30.seconds) do
+ logger.log_timed(log_messages[:foo], start) { bar_check }
+ end
+
+ expect(logger.full_message).to eq("Checking ref: bar\nFoo message... (30000.0ms)")
+ end
+
+ context 'when time limit was reached' do
+ it 'cancels action' do
+ Timecop.freeze(start + 50.seconds) do
+ expect do
+ logger.log_timed(log_messages[:foo], start) do
+ bar_check
+ end
+ end.to raise_error(described_class::TimeoutError)
+ end
+
+ expect(logger.full_message).to eq("Checking ref: bar\nFoo message... (cancelled)")
+ end
+
+ it 'cancels action with time elapsed if work was performed' do
+ Timecop.freeze(start + 30.seconds) do
+ expect do
+ logger.log_timed(log_messages[:foo], start) do
+ grpc_check
+ end
+ end.to raise_error(described_class::TimeoutError)
+
+ expect(logger.full_message).to eq("Checking ref: bar\nFoo message... (cancelled after 30000.0ms)")
+ end
+ end
+ end
+ end
+
+ def bar_check
+ 2 + 2
+ end
+
+ def grpc_check
+ raise GRPC::DeadlineExceeded
+ end
+end
diff --git a/spec/lib/gitlab/ci/ansi2html_spec.rb b/spec/lib/gitlab/ci/ansi2html_spec.rb
index 7549e9941b6..5a5c071c639 100644
--- a/spec/lib/gitlab/ci/ansi2html_spec.rb
+++ b/spec/lib/gitlab/ci/ansi2html_spec.rb
@@ -7,7 +7,7 @@ describe Gitlab::Ci::Ansi2html do
expect(convert_html("Hello")).to eq('Hello')
end
- it "strips non-color-changing controll sequences" do
+ it "strips non-color-changing control sequences" do
expect(convert_html("Hello \e[2Kworld")).to eq('Hello world')
end
diff --git a/spec/lib/gitlab/ci/build/artifacts/adapters/gzip_stream_spec.rb b/spec/lib/gitlab/ci/build/artifacts/adapters/gzip_stream_spec.rb
new file mode 100644
index 00000000000..987c6b37aaa
--- /dev/null
+++ b/spec/lib/gitlab/ci/build/artifacts/adapters/gzip_stream_spec.rb
@@ -0,0 +1,56 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Build::Artifacts::Adapters::GzipStream do
+ describe '#initialize' do
+ context 'when stream is passed' do
+ let(:stream) { File.open(expand_fixture_path('junit/junit.xml.gz'), 'rb') }
+
+ it 'initialized' do
+ expect { described_class.new(stream) }.not_to raise_error
+ end
+ end
+
+ context 'when stream is not passed' do
+ let(:stream) { nil }
+
+ it 'raises an error' do
+ expect { described_class.new(stream) }.to raise_error(described_class::InvalidStreamError)
+ end
+ end
+ end
+
+ describe '#each_blob' do
+ let(:adapter) { described_class.new(stream) }
+
+ context 'when stream is gzip file' do
+ context 'when gzip file contains one file' do
+ let(:stream) { File.open(expand_fixture_path('junit/junit.xml.gz'), 'rb') }
+
+ it 'iterates content and file_name' do
+ expect { |b| adapter.each_blob(&b) }
+ .to yield_with_args(fixture_file('junit/junit.xml'), 'rspec.xml')
+ end
+ end
+
+ context 'when gzip file contains three files' do
+ let(:stream) { File.open(expand_fixture_path('junit/junit_with_three_testsuites.xml.gz'), 'rb') }
+
+ it 'iterates content and file_name' do
+ expect { |b| adapter.each_blob(&b) }
+ .to yield_successive_args(
+ [fixture_file('junit/junit_with_three_testsuites_1.xml'), 'rspec-3.xml'],
+ [fixture_file('junit/junit_with_three_testsuites_2.xml'), 'rspec-1.xml'],
+ [fixture_file('junit/junit_with_three_testsuites_3.xml'), 'rspec-2.xml'])
+ end
+ end
+ end
+
+ context 'when stream is zip file' do
+ let(:stream) { File.open(expand_fixture_path('ci_build_artifacts.zip'), 'rb') }
+
+ it 'raises an error' do
+ expect { |b| adapter.each_blob(&b) }.to raise_error(described_class::InvalidStreamError)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/build/artifacts/adapters/raw_stream_spec.rb b/spec/lib/gitlab/ci/build/artifacts/adapters/raw_stream_spec.rb
new file mode 100644
index 00000000000..ec2dd724b45
--- /dev/null
+++ b/spec/lib/gitlab/ci/build/artifacts/adapters/raw_stream_spec.rb
@@ -0,0 +1,47 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Build::Artifacts::Adapters::RawStream do
+ describe '#initialize' do
+ context 'when stream is passed' do
+ let(:stream) { File.open(expand_fixture_path('junit/junit.xml'), 'rb') }
+
+ it 'initialized' do
+ expect { described_class.new(stream) }.not_to raise_error
+ end
+ end
+
+ context 'when stream is not passed' do
+ let(:stream) { nil }
+
+ it 'raises an error' do
+ expect { described_class.new(stream) }.to raise_error(described_class::InvalidStreamError)
+ end
+ end
+ end
+
+ describe '#each_blob' do
+ let(:adapter) { described_class.new(stream) }
+
+ context 'when file is not empty' do
+ let(:stream) { File.open(expand_fixture_path('junit/junit.xml'), 'rb') }
+
+ it 'iterates content' do
+ expect { |b| adapter.each_blob(&b) }
+ .to yield_with_args(fixture_file('junit/junit.xml'), 'raw')
+ end
+ end
+
+ context 'when file is empty' do
+ let(:stream) { Tempfile.new }
+
+ after do
+ stream.unlink
+ end
+
+ it 'does not iterate content' do
+ expect { |b| adapter.each_blob(&b) }
+ .not_to yield_control
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/build/artifacts/gzip_file_adapter_spec.rb b/spec/lib/gitlab/ci/build/artifacts/gzip_file_adapter_spec.rb
deleted file mode 100644
index 384329dda18..00000000000
--- a/spec/lib/gitlab/ci/build/artifacts/gzip_file_adapter_spec.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Ci::Build::Artifacts::GzipFileAdapter do
- describe '#initialize' do
- context 'when stream is passed' do
- let(:stream) { File.open(expand_fixture_path('junit/junit.xml.gz'), 'rb') }
-
- it 'initialized' do
- expect { described_class.new(stream) }.not_to raise_error
- end
- end
-
- context 'when stream is not passed' do
- let(:stream) { nil }
-
- it 'raises an error' do
- expect { described_class.new(stream) }.to raise_error(described_class::InvalidStreamError)
- end
- end
- end
-
- describe '#each_blob' do
- let(:adapter) { described_class.new(stream) }
-
- context 'when stream is gzip file' do
- context 'when gzip file contains one file' do
- let(:stream) { File.open(expand_fixture_path('junit/junit.xml.gz'), 'rb') }
-
- it 'iterates content and file_name' do
- expect { |b| adapter.each_blob(&b) }
- .to yield_with_args(fixture_file('junit/junit.xml'), 'rspec.xml')
- end
- end
-
- context 'when gzip file contains three files' do
- let(:stream) { File.open(expand_fixture_path('junit/junit_with_three_testsuites.xml.gz'), 'rb') }
-
- it 'iterates content and file_name' do
- expect { |b| adapter.each_blob(&b) }
- .to yield_successive_args(
- [fixture_file('junit/junit_with_three_testsuites_1.xml'), 'rspec-3.xml'],
- [fixture_file('junit/junit_with_three_testsuites_2.xml'), 'rspec-1.xml'],
- [fixture_file('junit/junit_with_three_testsuites_3.xml'), 'rspec-2.xml'])
- end
- end
- end
-
- context 'when stream is zip file' do
- let(:stream) { File.open(expand_fixture_path('ci_build_artifacts.zip'), 'rb') }
-
- it 'raises an error' do
- expect { |b| adapter.each_blob(&b) }.to raise_error(described_class::InvalidStreamError)
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb b/spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb
index e327399d82d..a9a4af1f455 100644
--- a/spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb
+++ b/spec/lib/gitlab/ci/build/artifacts/metadata_spec.rb
@@ -112,4 +112,34 @@ describe Gitlab::Ci::Build::Artifacts::Metadata do
end
end
end
+
+ context 'generated metadata' do
+ let(:tmpfile) { Tempfile.new('test-metadata') }
+ let(:generator) { CiArtifactMetadataGenerator.new(tmpfile) }
+ let(:entry_count) { 5 }
+
+ before do
+ tmpfile.binmode
+
+ (1..entry_count).each do |index|
+ generator.add_entry("public/test-#{index}.txt")
+ end
+
+ generator.write
+ end
+
+ after do
+ File.unlink(tmpfile.path)
+ end
+
+ describe '#find_entries!' do
+ it 'reads expected number of entries' do
+ stream = File.open(tmpfile.path)
+
+ metadata = described_class.new(stream, 'public', { recursive: true })
+
+ expect(metadata.find_entries!.count).to eq entry_count
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/build/policy/changes_spec.rb b/spec/lib/gitlab/ci/build/policy/changes_spec.rb
new file mode 100644
index 00000000000..5fee37bb43e
--- /dev/null
+++ b/spec/lib/gitlab/ci/build/policy/changes_spec.rb
@@ -0,0 +1,119 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Build::Policy::Changes do
+ set(:project) { create(:project) }
+
+ describe '#satisfied_by?' do
+ describe 'paths matching' do
+ let(:pipeline) do
+ build(:ci_empty_pipeline, project: project,
+ ref: 'master',
+ source: :push,
+ sha: '1234abcd',
+ before_sha: '0123aabb')
+ end
+
+ let(:ci_build) do
+ build(:ci_build, pipeline: pipeline, project: project, ref: 'master')
+ end
+
+ let(:seed) { double('build seed', to_resource: ci_build) }
+
+ before do
+ allow(pipeline).to receive(:modified_paths) do
+ %w[some/modified/ruby/file.rb some/other_file.txt some/.dir/file]
+ end
+ end
+
+ it 'is satisfied by matching literal path' do
+ policy = described_class.new(%w[some/other_file.txt])
+
+ expect(policy).to be_satisfied_by(pipeline, seed)
+ end
+
+ it 'is satisfied by matching simple pattern' do
+ policy = described_class.new(%w[some/*.txt])
+
+ expect(policy).to be_satisfied_by(pipeline, seed)
+ end
+
+ it 'is satisfied by matching recusive pattern' do
+ policy = described_class.new(%w[some/**/*.rb])
+
+ expect(policy).to be_satisfied_by(pipeline, seed)
+ end
+
+ it 'is satisfied by matching a pattern with a dot' do
+ policy = described_class.new(%w[some/*/file])
+
+ expect(policy).to be_satisfied_by(pipeline, seed)
+ end
+
+ it 'is satisfied by matching a pattern with a glob' do
+ policy = described_class.new(%w[some/**/*.{rb,txt}])
+
+ expect(policy).to be_satisfied_by(pipeline, seed)
+ end
+
+ it 'is not satisfied when pattern does not match path' do
+ policy = described_class.new(%w[some/*.rb])
+
+ expect(policy).not_to be_satisfied_by(pipeline, seed)
+ end
+
+ it 'is not satisfied when pattern does not match' do
+ policy = described_class.new(%w[invalid/*.md])
+
+ expect(policy).not_to be_satisfied_by(pipeline, seed)
+ end
+
+ it 'is not satified when pattern with glob does not match' do
+ policy = described_class.new(%w[invalid/*.{md,rake}])
+
+ expect(policy).not_to be_satisfied_by(pipeline, seed)
+ end
+
+ context 'when pipelines does not run for a branch update' do
+ before do
+ pipeline.before_sha = Gitlab::Git::BLANK_SHA
+ end
+
+ it 'is always satisfied' do
+ policy = described_class.new(%w[invalid/*])
+
+ expect(policy).to be_satisfied_by(pipeline, seed)
+ end
+ end
+ end
+
+ describe 'gitaly integration' do
+ set(:project) { create(:project, :repository) }
+
+ let(:pipeline) do
+ create(:ci_empty_pipeline, project: project,
+ ref: 'master',
+ source: :push,
+ sha: '498214d',
+ before_sha: '281d3a7')
+ end
+
+ let(:build) do
+ create(:ci_build, pipeline: pipeline, project: project, ref: 'master')
+ end
+
+ let(:seed) { double('build seed', to_resource: build) }
+
+ it 'is satisfied by changes introduced by a push' do
+ policy = described_class.new(['with space/*.md'])
+
+ expect(policy).to be_satisfied_by(pipeline, seed)
+ end
+
+ it 'is not satisfied by changes that are not in the push' do
+ policy = described_class.new(%w[files/js/commit.js])
+
+ expect(policy).not_to be_satisfied_by(pipeline, seed)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/build/policy/refs_spec.rb b/spec/lib/gitlab/ci/build/policy/refs_spec.rb
index 7211187e511..553fc0fb9bf 100644
--- a/spec/lib/gitlab/ci/build/policy/refs_spec.rb
+++ b/spec/lib/gitlab/ci/build/policy/refs_spec.rb
@@ -16,7 +16,7 @@ describe Gitlab::Ci::Build::Policy::Refs do
end
end
- context 'when maching tags' do
+ context 'when matching tags' do
context 'when pipeline runs for a tag' do
let(:pipeline) do
build_stubbed(:ci_pipeline, ref: 'feature', tag: true)
@@ -56,10 +56,10 @@ describe Gitlab::Ci::Build::Policy::Refs do
end
end
- context 'when maching a source' do
+ context 'when matching a source' do
let(:pipeline) { build_stubbed(:ci_pipeline, source: :push) }
- it 'is satisifed when provided source keyword matches' do
+ it 'is satisfied when provided source keyword matches' do
expect(described_class.new(%w[pushes]))
.to be_satisfied_by(pipeline)
end
diff --git a/spec/lib/gitlab/ci/build/policy/variables_spec.rb b/spec/lib/gitlab/ci/build/policy/variables_spec.rb
index 2ce858836e3..c2c0742efc3 100644
--- a/spec/lib/gitlab/ci/build/policy/variables_spec.rb
+++ b/spec/lib/gitlab/ci/build/policy/variables_spec.rb
@@ -24,7 +24,7 @@ describe Gitlab::Ci::Build::Policy::Variables do
expect(policy).to be_satisfied_by(pipeline, seed)
end
- it 'is not satisfied by an overriden empty variable' do
+ it 'is not satisfied by an overridden empty variable' do
policy = described_class.new(['$CI_PROJECT_NAME'])
expect(policy).not_to be_satisfied_by(pipeline, seed)
@@ -54,7 +54,7 @@ describe Gitlab::Ci::Build::Policy::Variables do
expect(policy).not_to be_satisfied_by(pipeline, seed)
end
- it 'allows to evaluate regular secret variables' do
+ it 'allows to evaluate regular CI variables' do
create(:ci_variable, project: project, key: 'SECRET', value: 'my secret')
policy = described_class.new(["$SECRET == 'my secret'"])
diff --git a/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb b/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb
index d48aac15f28..bd1f2c92844 100644
--- a/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/artifacts_spec.rb
@@ -8,7 +8,7 @@ describe Gitlab::Ci::Config::Entry::Artifacts do
let(:config) { { paths: %w[public/] } }
describe '#value' do
- it 'returns artifacs configuration' do
+ it 'returns artifacts configuration' do
expect(entry.value).to eq config
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/attributable_spec.rb b/spec/lib/gitlab/ci/config/entry/attributable_spec.rb
deleted file mode 100644
index b028b771375..00000000000
--- a/spec/lib/gitlab/ci/config/entry/attributable_spec.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Ci::Config::Entry::Attributable do
- let(:node) do
- Class.new do
- include Gitlab::Ci::Config::Entry::Attributable
- end
- end
-
- let(:instance) { node.new }
-
- before do
- node.class_eval do
- attributes :name, :test
- end
- end
-
- context 'when config is a hash' do
- before do
- allow(instance)
- .to receive(:config)
- .and_return({ name: 'some name', test: 'some test' })
- end
-
- it 'returns the value of config' do
- expect(instance.name).to eq 'some name'
- expect(instance.test).to eq 'some test'
- end
-
- it 'returns no method error for unknown attributes' do
- expect { instance.unknown }.to raise_error(NoMethodError)
- end
- end
-
- context 'when config is not a hash' do
- before do
- allow(instance)
- .to receive(:config)
- .and_return('some test')
- end
-
- it 'returns nil' do
- expect(instance.test).to be_nil
- end
- end
-
- context 'when method is already defined in a superclass' do
- it 'raises an error' do
- expectation = expect do
- Class.new(String) do
- include Gitlab::Ci::Config::Entry::Attributable
-
- attributes :length
- end
- end
-
- expectation.to raise_error(ArgumentError, 'Method already defined!')
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/config/entry/boolean_spec.rb b/spec/lib/gitlab/ci/config/entry/boolean_spec.rb
deleted file mode 100644
index 5f067cad93c..00000000000
--- a/spec/lib/gitlab/ci/config/entry/boolean_spec.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Ci::Config::Entry::Boolean do
- let(:entry) { described_class.new(config) }
-
- describe 'validations' do
- context 'when entry config value is valid' do
- let(:config) { false }
-
- describe '#value' do
- it 'returns key value' do
- expect(entry.value).to eq false
- end
- end
-
- describe '#valid?' do
- it 'is valid' do
- expect(entry).to be_valid
- end
- end
- end
-
- context 'when entry value is not valid' do
- let(:config) { ['incorrect'] }
-
- describe '#errors' do
- it 'saves errors' do
- expect(entry.errors)
- .to include 'boolean config should be a boolean value'
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/config/entry/configurable_spec.rb b/spec/lib/gitlab/ci/config/entry/configurable_spec.rb
deleted file mode 100644
index 088d4b472da..00000000000
--- a/spec/lib/gitlab/ci/config/entry/configurable_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Ci::Config::Entry::Configurable do
- let(:entry) do
- Class.new(Gitlab::Ci::Config::Entry::Node) do
- include Gitlab::Ci::Config::Entry::Configurable
- end
- end
-
- describe 'validations' do
- context 'when entry is a hash' do
- let(:instance) { entry.new(key: 'value') }
-
- it 'correctly validates an instance' do
- expect(instance).to be_valid
- end
- end
-
- context 'when entry is not a hash' do
- let(:instance) { entry.new('ls') }
-
- it 'invalidates the instance' do
- expect(instance).not_to be_valid
- end
- end
- end
-
- describe 'configured entries' do
- before do
- entry.class_eval do
- entry :object, Object, description: 'test object'
- end
- end
-
- describe '.nodes' do
- it 'has valid nodes' do
- expect(entry.nodes).to include :object
- end
-
- it 'creates a node factory' do
- expect(entry.nodes[:object])
- .to be_an_instance_of Gitlab::Ci::Config::Entry::Factory
- end
-
- it 'returns a duplicated factory object' do
- first_factory = entry.nodes[:object]
- second_factory = entry.nodes[:object]
-
- expect(first_factory).not_to be_equal(second_factory)
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/config/entry/factory_spec.rb b/spec/lib/gitlab/ci/config/entry/factory_spec.rb
deleted file mode 100644
index 8dd48e4efae..00000000000
--- a/spec/lib/gitlab/ci/config/entry/factory_spec.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Ci::Config::Entry::Factory do
- describe '#create!' do
- let(:factory) { described_class.new(entry) }
- let(:entry) { Gitlab::Ci::Config::Entry::Script }
-
- context 'when setting a concrete value' do
- it 'creates entry with valid value' do
- entry = factory
- .value(%w(ls pwd))
- .create!
-
- expect(entry.value).to eq %w(ls pwd)
- end
-
- context 'when setting description' do
- it 'creates entry with description' do
- entry = factory
- .value(%w(ls pwd))
- .with(description: 'test description')
- .create!
-
- expect(entry.value).to eq %w(ls pwd)
- expect(entry.description).to eq 'test description'
- end
- end
-
- context 'when setting key' do
- it 'creates entry with custom key' do
- entry = factory
- .value(%w(ls pwd))
- .with(key: 'test key')
- .create!
-
- expect(entry.key).to eq 'test key'
- end
- end
-
- context 'when setting a parent' do
- let(:object) { Object.new }
-
- it 'creates entry with valid parent' do
- entry = factory
- .value('ls')
- .with(parent: object)
- .create!
-
- expect(entry.parent).to eq object
- end
- end
- end
-
- context 'when not setting a value' do
- it 'raises error' do
- expect { factory.create! }.to raise_error(
- Gitlab::Ci::Config::Entry::Factory::InvalidFactory
- )
- end
- end
-
- context 'when creating entry with nil value' do
- it 'creates an unspecified entry' do
- entry = factory
- .value(nil)
- .create!
-
- expect(entry)
- .not_to be_specified
- end
- end
-
- context 'when passing metadata' do
- let(:entry) { spy('entry') }
-
- it 'passes metadata as a parameter' do
- factory
- .value('some value')
- .metadata(some: 'hash')
- .create!
-
- expect(entry).to have_received(:new)
- .with('some value', { some: 'hash' })
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/config/entry/global_spec.rb b/spec/lib/gitlab/ci/config/entry/global_spec.rb
index 1860ed79bfd..7c18514934e 100644
--- a/spec/lib/gitlab/ci/config/entry/global_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/global_spec.rb
@@ -219,7 +219,7 @@ describe Gitlab::Ci::Config::Entry::Global do
##
# When nodes are specified but not defined, we assume that
- # configuration is valid, and we asume that entry is simply undefined,
+ # configuration is valid, and we assume that entry is simply undefined,
# despite the fact, that key is present. See issue #18775 for more
# details.
#
diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb
index 2c9758401b7..57d4577a90c 100644
--- a/spec/lib/gitlab/ci/config/entry/job_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb
@@ -1,5 +1,4 @@
-require 'fast_spec_helper'
-require_dependency 'active_model'
+require 'spec_helper'
describe Gitlab::Ci::Config::Entry::Job do
let(:entry) { described_class.new(config, name: :rspec) }
@@ -11,7 +10,7 @@ describe Gitlab::Ci::Config::Entry::Job do
let(:result) do
%i[before_script script stage type after_script cache
image services only except variables artifacts
- environment coverage]
+ environment coverage retry]
end
it { is_expected.to match_array result }
@@ -39,6 +38,14 @@ describe Gitlab::Ci::Config::Entry::Job do
expect(entry.errors).to include "job name can't be blank"
end
end
+
+ context 'when delayed job' do
+ context 'when start_in is specified' do
+ let(:config) { { script: 'echo', when: 'delayed', start_in: '1 day' } }
+
+ it { expect(entry).to be_valid }
+ end
+ end
end
context 'when entry value is not correct' do
@@ -91,43 +98,90 @@ describe Gitlab::Ci::Config::Entry::Job do
end
end
- context 'when retry value is not correct' do
+ context 'when parallel value is not correct' do
context 'when it is not a numeric value' do
- let(:config) { { retry: true } }
+ let(:config) { { parallel: true } }
it 'returns error about invalid type' do
expect(entry).not_to be_valid
- expect(entry.errors).to include 'job retry is not a number'
+ expect(entry.errors).to include 'job parallel is not a number'
end
end
- context 'when it is lower than zero' do
- let(:config) { { retry: -1 } }
+ context 'when it is lower than two' do
+ let(:config) { { parallel: 1 } }
it 'returns error about value too low' do
expect(entry).not_to be_valid
expect(entry.errors)
- .to include 'job retry must be greater than or equal to 0'
+ .to include 'job parallel must be greater than or equal to 2'
+ end
+ end
+
+ context 'when it is bigger than 50' do
+ let(:config) { { parallel: 51 } }
+
+ it 'returns error about value too high' do
+ expect(entry).not_to be_valid
+ expect(entry.errors)
+ .to include 'job parallel must be less than or equal to 50'
end
end
context 'when it is not an integer' do
- let(:config) { { retry: 1.5 } }
+ let(:config) { { parallel: 1.5 } }
it 'returns error about wrong value' do
expect(entry).not_to be_valid
- expect(entry.errors).to include 'job retry must be an integer'
+ expect(entry.errors).to include 'job parallel must be an integer'
end
end
+ end
- context 'when the value is too high' do
- let(:config) { { retry: 10 } }
+ context 'when delayed job' do
+ context 'when start_in is specified' do
+ let(:config) { { script: 'echo', when: 'delayed', start_in: '1 day' } }
- it 'returns error about value too high' do
+ it 'returns error about invalid type' do
+ expect(entry).to be_valid
+ end
+ end
+
+ context 'when start_in is empty' do
+ let(:config) { { when: 'delayed', start_in: nil } }
+
+ it 'returns error about invalid type' do
expect(entry).not_to be_valid
- expect(entry.errors).to include 'job retry must be less than or equal to 2'
+ expect(entry.errors).to include 'job start in should be a duration'
end
end
+
+ context 'when start_in is not formatted as a duration' do
+ let(:config) { { when: 'delayed', start_in: 'test' } }
+
+ it 'returns error about invalid type' do
+ expect(entry).not_to be_valid
+ expect(entry.errors).to include 'job start in should be a duration'
+ end
+ end
+
+ context 'when start_in is longer than one day' do
+ let(:config) { { when: 'delayed', start_in: '2 days' } }
+
+ it 'returns error about exceeding the limit' do
+ expect(entry).not_to be_valid
+ expect(entry.errors).to include 'job start in should not exceed the limit'
+ end
+ end
+ end
+
+ context 'when start_in specified without delayed specification' do
+ let(:config) { { start_in: '1 day' } }
+
+ it 'returns error about invalid type' do
+ expect(entry).not_to be_valid
+ expect(entry.errors).to include 'job start in must be blank'
+ end
end
end
end
@@ -238,6 +292,24 @@ describe Gitlab::Ci::Config::Entry::Job do
end
end
+ describe '#delayed?' do
+ context 'when job is a delayed' do
+ let(:config) { { script: 'deploy', when: 'delayed' } }
+
+ it 'is a delayed' do
+ expect(entry).to be_delayed
+ end
+ end
+
+ context 'when job is not a delayed' do
+ let(:config) { { script: 'deploy' } }
+
+ it 'is not a delayed' do
+ expect(entry).not_to be_delayed
+ end
+ end
+ end
+
describe '#ignored?' do
context 'when job is a manual action' do
context 'when it is not specified if job is allowed to fail' do
diff --git a/spec/lib/gitlab/ci/config/entry/policy_spec.rb b/spec/lib/gitlab/ci/config/entry/policy_spec.rb
index 83d39b82068..83001b7fdd8 100644
--- a/spec/lib/gitlab/ci/config/entry/policy_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/policy_spec.rb
@@ -1,4 +1,5 @@
-require 'spec_helper'
+require 'fast_spec_helper'
+require_dependency 'active_model'
describe Gitlab::Ci::Config::Entry::Policy do
let(:entry) { described_class.new(config) }
@@ -57,7 +58,7 @@ describe Gitlab::Ci::Config::Entry::Policy do
end
context 'when using complex policy' do
- context 'when specifiying refs policy' do
+ context 'when specifying refs policy' do
let(:config) { { refs: ['master'] } }
it 'is a correct configuraton' do
@@ -124,6 +125,23 @@ describe Gitlab::Ci::Config::Entry::Policy do
end
end
+ context 'when specifying a valid changes policy' do
+ let(:config) { { changes: %w[some/* paths/**/*.rb] } }
+
+ it 'is a correct configuraton' do
+ expect(entry).to be_valid
+ expect(entry.value).to eq(config)
+ end
+ end
+
+ context 'when changes policy is invalid' do
+ let(:config) { { changes: [1, 2] } }
+
+ it 'returns errors' do
+ expect(entry.errors).to include /changes should be an array of strings/
+ end
+ end
+
context 'when specifying unknown policy' do
let(:config) { { refs: ['master'], invalid: :something } }
diff --git a/spec/lib/gitlab/ci/config/entry/reports_spec.rb b/spec/lib/gitlab/ci/config/entry/reports_spec.rb
index b3a3a6bee1d..38943138cbf 100644
--- a/spec/lib/gitlab/ci/config/entry/reports_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/reports_spec.rb
@@ -3,27 +3,56 @@ require 'spec_helper'
describe Gitlab::Ci::Config::Entry::Reports do
let(:entry) { described_class.new(config) }
+ describe 'validates ALLOWED_KEYS' do
+ let(:artifact_file_types) { Ci::JobArtifact.file_types }
+
+ described_class::ALLOWED_KEYS.each do |keyword, _|
+ it "expects #{keyword} to be an artifact file_type" do
+ expect(artifact_file_types).to include(keyword)
+ end
+ end
+ end
+
describe 'validation' do
context 'when entry config value is correct' do
- let(:config) { { junit: %w[junit.xml] } }
+ using RSpec::Parameterized::TableSyntax
- describe '#value' do
- it 'returns artifacs configuration' do
- expect(entry.value).to eq config
+ shared_examples 'a valid entry' do |keyword, file|
+ describe '#value' do
+ it 'returns artifacts configuration' do
+ expect(entry.value).to eq({ "#{keyword}": [file] } )
+ end
end
- end
- describe '#valid?' do
- it 'is valid' do
- expect(entry).to be_valid
+ describe '#valid?' do
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
end
end
- context 'when value is not array' do
- let(:config) { { junit: 'junit.xml' } }
+ where(:keyword, :file) do
+ :junit | 'junit.xml'
+ :codequality | 'gl-code-quality-report.json'
+ :sast | 'gl-sast-report.json'
+ :dependency_scanning | 'gl-dependency-scanning-report.json'
+ :container_scanning | 'gl-container-scanning-report.json'
+ :dast | 'gl-dast-report.json'
+ :license_management | 'gl-license-management-report.json'
+ :performance | 'performance.json'
+ end
+
+ with_them do
+ context 'when value is an array' do
+ let(:config) { { "#{keyword}": [file] } }
- it 'converts to array' do
- expect(entry.value).to eq({ junit: ['junit.xml'] } )
+ it_behaves_like 'a valid entry', params[:keyword], params[:file]
+ end
+
+ context 'when value is not array' do
+ let(:config) { { "#{keyword}": file } }
+
+ it_behaves_like 'a valid entry', params[:keyword], params[:file]
end
end
end
@@ -31,11 +60,13 @@ describe Gitlab::Ci::Config::Entry::Reports do
context 'when entry value is not correct' do
describe '#errors' do
context 'when value of attribute is invalid' do
- let(:config) { { junit: 10 } }
+ where(key: described_class::ALLOWED_KEYS) do
+ let(:config) { { "#{key}": 10 } }
- it 'reports error' do
- expect(entry.errors)
- .to include 'reports junit should be an array of strings or a string'
+ it 'reports error' do
+ expect(entry.errors)
+ .to include "reports #{key} should be an array of strings or a string"
+ end
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/retry_spec.rb b/spec/lib/gitlab/ci/config/entry/retry_spec.rb
new file mode 100644
index 00000000000..164a9ed4c3d
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/entry/retry_spec.rb
@@ -0,0 +1,236 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::Entry::Retry do
+ let(:entry) { described_class.new(config) }
+
+ shared_context 'when retry value is a numeric', :numeric do
+ let(:config) { max }
+ let(:max) {}
+ end
+
+ shared_context 'when retry value is a hash', :hash do
+ let(:config) { { max: max, when: public_send(:when) }.compact }
+ let(:when) {}
+ let(:max) {}
+ end
+
+ describe '#value' do
+ subject(:value) { entry.value }
+
+ context 'when retry value is a numeric', :numeric do
+ let(:max) { 2 }
+
+ it 'is returned as a hash with max key' do
+ expect(value).to eq(max: 2)
+ end
+ end
+
+ context 'when retry value is a hash', :hash do
+ context 'and `when` is a string' do
+ let(:when) { 'unknown_failure' }
+
+ it 'returns when wrapped in an array' do
+ expect(value).to eq(when: ['unknown_failure'])
+ end
+ end
+
+ context 'and `when` is an array' do
+ let(:when) { %w[unknown_failure runner_system_failure] }
+
+ it 'returns when as it was passed' do
+ expect(value).to eq(when: %w[unknown_failure runner_system_failure])
+ end
+ end
+ end
+ end
+
+ describe 'validation' do
+ context 'when retry value is correct' do
+ context 'when it is a numeric', :numeric do
+ let(:max) { 2 }
+
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+
+ context 'when it is a hash', :hash do
+ context 'with max' do
+ let(:max) { 2 }
+
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+
+ context 'with string when' do
+ let(:when) { 'unknown_failure' }
+
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+
+ context 'with string when always' do
+ let(:when) { 'always' }
+
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+
+ context 'with array when' do
+ let(:when) { %w[unknown_failure runner_system_failure] }
+
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+
+ # Those values are documented at `doc/ci/yaml/README.md`. If any of
+ # those values gets invalid, documentation must be updated. To make
+ # sure this is catched, check explicitly that all of the documented
+ # values are valid. If they are not it means the documentation and this
+ # array must be updated.
+ RETRY_WHEN_IN_DOCUMENTATION = %w[
+ always
+ unknown_failure
+ script_failure
+ api_failure
+ stuck_or_timeout_failure
+ runner_system_failure
+ missing_dependency_failure
+ runner_unsupported
+ ].freeze
+
+ RETRY_WHEN_IN_DOCUMENTATION.each do |reason|
+ context "with when from documentation `#{reason}`" do
+ let(:when) { reason }
+
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+ end
+
+ ::Ci::Build.failure_reasons.each_key do |reason|
+ context "with when from CommitStatus.failure_reasons `#{reason}`" do
+ let(:when) { reason }
+
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+ end
+ end
+ end
+
+ context 'when retry value is not correct' do
+ context 'when it is not a numeric nor an array' do
+ let(:config) { true }
+
+ it 'returns error about invalid type' do
+ expect(entry).not_to be_valid
+ expect(entry.errors).to include 'retry config has to be either an integer or a hash'
+ end
+ end
+
+ context 'when it is a numeric', :numeric do
+ context 'when it is lower than zero' do
+ let(:max) { -1 }
+
+ it 'returns error about value too low' do
+ expect(entry).not_to be_valid
+ expect(entry.errors)
+ .to include 'retry config must be greater than or equal to 0'
+ end
+ end
+
+ context 'when it is not an integer' do
+ let(:max) { 1.5 }
+
+ it 'returns error about wrong value' do
+ expect(entry).not_to be_valid
+ expect(entry.errors).to include 'retry config has to be either an integer or a hash'
+ end
+ end
+
+ context 'when the value is too high' do
+ let(:max) { 10 }
+
+ it 'returns error about value too high' do
+ expect(entry).not_to be_valid
+ expect(entry.errors).to include 'retry config must be less than or equal to 2'
+ end
+ end
+ end
+
+ context 'when it is a hash', :hash do
+ context 'with unknown keys' do
+ let(:config) { { max: 2, unknown_key: :something, one_more: :key } }
+
+ it 'returns error about the unknown key' do
+ expect(entry).not_to be_valid
+ expect(entry.errors)
+ .to include 'retry config contains unknown keys: unknown_key, one_more'
+ end
+ end
+
+ context 'with max lower than zero' do
+ let(:max) { -1 }
+
+ it 'returns error about value too low' do
+ expect(entry).not_to be_valid
+ expect(entry.errors)
+ .to include 'retry max must be greater than or equal to 0'
+ end
+ end
+
+ context 'with max not an integer' do
+ let(:max) { 1.5 }
+
+ it 'returns error about wrong value' do
+ expect(entry).not_to be_valid
+ expect(entry.errors).to include 'retry max must be an integer'
+ end
+ end
+
+ context 'iwth max too high' do
+ let(:max) { 10 }
+
+ it 'returns error about value too high' do
+ expect(entry).not_to be_valid
+ expect(entry.errors).to include 'retry max must be less than or equal to 2'
+ end
+ end
+
+ context 'with when in wrong format' do
+ let(:when) { true }
+
+ it 'returns error about the wrong format' do
+ expect(entry).not_to be_valid
+ expect(entry.errors).to include 'retry when should be an array of strings or a string'
+ end
+ end
+
+ context 'with an unknown when string' do
+ let(:when) { 'unknown_reason' }
+
+ it 'returns error about the wrong format' do
+ expect(entry).not_to be_valid
+ expect(entry.errors).to include 'retry when is not included in the list'
+ end
+ end
+
+ context 'with an unknown failure reason in a when array' do
+ let(:when) { %w[unknown_reason runner_system_failure] }
+
+ it 'returns error about the wrong format' do
+ expect(entry).not_to be_valid
+ expect(entry.errors).to include 'retry when contains unknown values: unknown_reason'
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/entry/simplifiable_spec.rb b/spec/lib/gitlab/ci/config/entry/simplifiable_spec.rb
deleted file mode 100644
index 395062207a3..00000000000
--- a/spec/lib/gitlab/ci/config/entry/simplifiable_spec.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Ci::Config::Entry::Simplifiable do
- describe '.strategy' do
- let(:entry) do
- Class.new(described_class) do
- strategy :Something, if: -> { 'condition' }
- strategy :DifferentOne, if: -> { 'condition' }
- end
- end
-
- it 'defines entry strategies' do
- expect(entry.strategies.size).to eq 2
- expect(entry.strategies.map(&:name))
- .to eq %i[Something DifferentOne]
- end
- end
-
- describe 'setting strategy by a condition' do
- let(:first) { double('first strategy') }
- let(:second) { double('second strategy') }
- let(:unknown) { double('unknown strategy') }
-
- before do
- stub_const("#{described_class.name}::Something", first)
- stub_const("#{described_class.name}::DifferentOne", second)
- stub_const("#{described_class.name}::UnknownStrategy", unknown)
- end
-
- context 'when first strategy should be used' do
- let(:entry) do
- Class.new(described_class) do
- strategy :Something, if: -> (arg) { arg == 'something' }
- strategy :DifferentOne, if: -> (*) { false }
- end
- end
-
- it 'attemps to load a first strategy' do
- expect(first).to receive(:new).with('something', anything)
-
- entry.new('something')
- end
- end
-
- context 'when second strategy should be used' do
- let(:entry) do
- Class.new(described_class) do
- strategy :Something, if: -> (arg) { arg == 'something' }
- strategy :DifferentOne, if: -> (arg) { arg == 'test' }
- end
- end
-
- it 'attemps to load a second strategy' do
- expect(second).to receive(:new).with('test', anything)
-
- entry.new('test')
- end
- end
-
- context 'when neither one is a valid strategy' do
- let(:entry) do
- Class.new(described_class) do
- strategy :Something, if: -> (*) { false }
- strategy :DifferentOne, if: -> (*) { false }
- end
- end
-
- it 'instantiates an unknown strategy' do
- expect(unknown).to receive(:new).with('test', anything)
-
- entry.new('test')
- end
- end
- end
-
- context 'when a unknown strategy class is not defined' do
- let(:entry) do
- Class.new(described_class) do
- strategy :String, if: -> (*) { true }
- end
- end
-
- it 'raises an error when being initialized' do
- expect { entry.new('something') }
- .to raise_error ArgumentError, /UndefinedStrategy not available!/
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/config/entry/undefined_spec.rb b/spec/lib/gitlab/ci/config/entry/undefined_spec.rb
deleted file mode 100644
index fdf48d84192..00000000000
--- a/spec/lib/gitlab/ci/config/entry/undefined_spec.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Ci::Config::Entry::Undefined do
- let(:entry) { described_class.new }
-
- describe '#leaf?' do
- it 'is leaf node' do
- expect(entry).to be_leaf
- end
- end
-
- describe '#valid?' do
- it 'is always valid' do
- expect(entry).to be_valid
- end
- end
-
- describe '#errors' do
- it 'is does not contain errors' do
- expect(entry.errors).to be_empty
- end
- end
-
- describe '#value' do
- it 'returns nil' do
- expect(entry.value).to eq nil
- end
- end
-
- describe '#relevant?' do
- it 'is not relevant' do
- expect(entry.relevant?).to eq false
- end
- end
-
- describe '#specified?' do
- it 'is not defined' do
- expect(entry.specified?).to eq false
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/config/entry/unspecified_spec.rb b/spec/lib/gitlab/ci/config/entry/unspecified_spec.rb
deleted file mode 100644
index 66f88fa35b6..00000000000
--- a/spec/lib/gitlab/ci/config/entry/unspecified_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Ci::Config::Entry::Unspecified do
- let(:unspecified) { described_class.new(entry) }
- let(:entry) { spy('Entry') }
-
- describe '#valid?' do
- it 'delegates method to entry' do
- expect(unspecified.valid?).to eq entry
- end
- end
-
- describe '#errors' do
- it 'delegates method to entry' do
- expect(unspecified.errors).to eq entry
- end
- end
-
- describe '#value' do
- it 'delegates method to entry' do
- expect(unspecified.value).to eq entry
- end
- end
-
- describe '#specified?' do
- it 'is always false' do
- allow(entry).to receive(:specified?).and_return(true)
-
- expect(unspecified.specified?).to be false
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/config/entry/validatable_spec.rb b/spec/lib/gitlab/ci/config/entry/validatable_spec.rb
deleted file mode 100644
index ae2a7a51ba6..00000000000
--- a/spec/lib/gitlab/ci/config/entry/validatable_spec.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Ci::Config::Entry::Validatable do
- let(:entry) do
- Class.new(Gitlab::Ci::Config::Entry::Node) do
- include Gitlab::Ci::Config::Entry::Validatable
- end
- end
-
- describe '.validator' do
- before do
- entry.class_eval do
- attr_accessor :test_attribute
-
- validations do
- validates :test_attribute, presence: true
- end
- end
- end
-
- it 'returns validator' do
- expect(entry.validator.superclass)
- .to be Gitlab::Ci::Config::Entry::Validator
- end
-
- it 'returns only one validator to mitigate leaks' do
- expect { entry.validator }.not_to change { entry.validator }
- end
-
- context 'when validating entry instance' do
- let(:entry_instance) { entry.new('something') }
-
- context 'when attribute is valid' do
- before do
- entry_instance.test_attribute = 'valid'
- end
-
- it 'instance of validator is valid' do
- expect(entry.validator.new(entry_instance)).to be_valid
- end
- end
-
- context 'when attribute is not valid' do
- before do
- entry_instance.test_attribute = nil
- end
-
- it 'instance of validator is invalid' do
- expect(entry.validator.new(entry_instance)).to be_invalid
- end
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/config/entry/validator_spec.rb b/spec/lib/gitlab/ci/config/entry/validator_spec.rb
deleted file mode 100644
index 172b6b47a4f..00000000000
--- a/spec/lib/gitlab/ci/config/entry/validator_spec.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Ci::Config::Entry::Validator do
- let(:validator) { Class.new(described_class) }
- let(:validator_instance) { validator.new(node) }
- let(:node) { spy('node') }
-
- before do
- allow(node).to receive(:key).and_return('node')
- allow(node).to receive(:ancestors).and_return([])
- end
-
- describe 'delegated validator' do
- before do
- validator.class_eval do
- validates :test_attribute, presence: true
- end
- end
-
- context 'when node is valid' do
- before do
- allow(node).to receive(:test_attribute).and_return('valid value')
- end
-
- it 'validates attribute in node' do
- expect(node).to receive(:test_attribute)
- expect(validator_instance).to be_valid
- end
-
- it 'returns no errors' do
- validator_instance.validate
-
- expect(validator_instance.messages).to be_empty
- end
- end
-
- context 'when node is invalid' do
- before do
- allow(node).to receive(:test_attribute).and_return(nil)
- end
-
- it 'validates attribute in node' do
- expect(node).to receive(:test_attribute)
- expect(validator_instance).to be_invalid
- end
-
- it 'returns errors' do
- validator_instance.validate
-
- expect(validator_instance.messages)
- .to include /test attribute can't be blank/
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/config/external/file/base_spec.rb b/spec/lib/gitlab/ci/config/external/file/base_spec.rb
new file mode 100644
index 00000000000..2e92d5204d6
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/external/file/base_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+describe Gitlab::Ci::Config::External::File::Base do
+ subject { described_class.new(location) }
+
+ before do
+ allow_any_instance_of(described_class)
+ .to receive(:content).and_return('key: value')
+ end
+
+ describe '#valid?' do
+ context 'when location is not a YAML file' do
+ let(:location) { 'some/file.txt' }
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'when location has not a valid naming scheme' do
+ let(:location) { 'some/file/.yml' }
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'when location is a valid .yml extension' do
+ let(:location) { 'some/file/config.yml' }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when location is a valid .yaml extension' do
+ let(:location) { 'some/file/config.yaml' }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when there are YAML syntax errors' do
+ let(:location) { 'some/file/config.yml' }
+
+ before do
+ allow_any_instance_of(described_class)
+ .to receive(:content).and_return('invalid_syntax')
+ end
+
+ it 'is not a valid file' do
+ expect(subject).not_to be_valid
+ expect(subject.error_message).to match /does not have valid YAML syntax/
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/external/file/local_spec.rb b/spec/lib/gitlab/ci/config/external/file/local_spec.rb
new file mode 100644
index 00000000000..541deb13b97
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/external/file/local_spec.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::External::File::Local do
+ let(:project) { create(:project, :repository) }
+ let(:local_file) { described_class.new(location, { project: project, sha: '12345' }) }
+
+ describe '#valid?' do
+ context 'when is a valid local path' do
+ let(:location) { '/lib/gitlab/ci/templates/existent-file.yml' }
+
+ before do
+ allow_any_instance_of(described_class).to receive(:fetch_local_content).and_return("image: 'ruby2:2'")
+ end
+
+ it 'should return true' do
+ expect(local_file.valid?).to be_truthy
+ end
+ end
+
+ context 'when is not a valid local path' do
+ let(:location) { '/lib/gitlab/ci/templates/non-existent-file.yml' }
+
+ it 'should return false' do
+ expect(local_file.valid?).to be_falsy
+ end
+ end
+
+ context 'when is not a yaml file' do
+ let(:location) { '/config/application.rb' }
+
+ it 'should return false' do
+ expect(local_file.valid?).to be_falsy
+ end
+ end
+ end
+
+ describe '#content' do
+ context 'with a valid file' do
+ let(:local_file_content) do
+ <<~HEREDOC
+ before_script:
+ - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
+ - ruby -v
+ - which ruby
+ - gem install bundler --no-ri --no-rdoc
+ - bundle install --jobs $(nproc) "${FLAGS[@]}"
+ HEREDOC
+ end
+ let(:location) { '/lib/gitlab/ci/templates/existent-file.yml' }
+
+ before do
+ allow_any_instance_of(described_class).to receive(:fetch_local_content).and_return(local_file_content)
+ end
+
+ it 'should return the content of the file' do
+ expect(local_file.content).to eq(local_file_content)
+ end
+ end
+
+ context 'with an invalid file' do
+ let(:location) { '/lib/gitlab/ci/templates/non-existent-file.yml' }
+
+ it 'should be nil' do
+ expect(local_file.content).to be_nil
+ end
+ end
+ end
+
+ describe '#error_message' do
+ let(:location) { '/lib/gitlab/ci/templates/non-existent-file.yml' }
+
+ it 'should return an error message' do
+ expect(local_file.error_message).to eq("Local file `#{location}` does not exist!")
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/external/file/remote_spec.rb b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
new file mode 100644
index 00000000000..7c1a1c38736
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
@@ -0,0 +1,157 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::External::File::Remote do
+ let(:remote_file) { described_class.new(location) }
+ let(:location) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+ let(:remote_file_content) do
+ <<~HEREDOC
+ before_script:
+ - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
+ - ruby -v
+ - which ruby
+ - gem install bundler --no-ri --no-rdoc
+ - bundle install --jobs $(nproc) "${FLAGS[@]}"
+ HEREDOC
+ end
+
+ describe "#valid?" do
+ context 'when is a valid remote url' do
+ before do
+ WebMock.stub_request(:get, location).to_return(body: remote_file_content)
+ end
+
+ it 'should return true' do
+ expect(remote_file.valid?).to be_truthy
+ end
+ end
+
+ context 'with an irregular url' do
+ let(:location) { 'not-valid://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+
+ it 'should return false' do
+ expect(remote_file.valid?).to be_falsy
+ end
+ end
+
+ context 'with a timeout' do
+ before do
+ allow(Gitlab::HTTP).to receive(:get).and_raise(Timeout::Error)
+ end
+
+ it 'should be falsy' do
+ expect(remote_file.valid?).to be_falsy
+ end
+ end
+
+ context 'when is not a yaml file' do
+ let(:location) { 'https://asdasdasdaj48ggerexample.com' }
+
+ it 'should be falsy' do
+ expect(remote_file.valid?).to be_falsy
+ end
+ end
+
+ context 'with an internal url' do
+ let(:location) { 'http://localhost:8080' }
+
+ it 'should be falsy' do
+ expect(remote_file.valid?).to be_falsy
+ end
+ end
+ end
+
+ describe "#content" do
+ context 'with a valid remote file' do
+ before do
+ WebMock.stub_request(:get, location).to_return(body: remote_file_content)
+ end
+
+ it 'should return the content of the file' do
+ expect(remote_file.content).to eql(remote_file_content)
+ end
+ end
+
+ context 'with a timeout' do
+ before do
+ allow(Gitlab::HTTP).to receive(:get).and_raise(Timeout::Error)
+ end
+
+ it 'should be falsy' do
+ expect(remote_file.content).to be_falsy
+ end
+ end
+
+ context 'with an invalid remote url' do
+ let(:location) { 'https://asdasdasdaj48ggerexample.com' }
+
+ before do
+ WebMock.stub_request(:get, location).to_raise(SocketError.new('Some HTTP error'))
+ end
+
+ it 'should be nil' do
+ expect(remote_file.content).to be_nil
+ end
+ end
+
+ context 'with an internal url' do
+ let(:location) { 'http://localhost:8080' }
+
+ it 'should be nil' do
+ expect(remote_file.content).to be_nil
+ end
+ end
+ end
+
+ describe "#error_message" do
+ subject { remote_file.error_message }
+
+ context 'when remote file location is not valid' do
+ let(:location) { 'not-valid://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+
+ it 'returns an error message describing invalid address' do
+ expect(subject).to match /does not have a valid address!/
+ end
+ end
+
+ context 'when timeout error has been raised' do
+ before do
+ WebMock.stub_request(:get, location).to_timeout
+ end
+
+ it 'should returns error message about a timeout' do
+ expect(subject).to match /could not be fetched because of a timeout error!/
+ end
+ end
+
+ context 'when HTTP error has been raised' do
+ before do
+ WebMock.stub_request(:get, location).to_raise(Gitlab::HTTP::Error)
+ end
+
+ it 'should returns error message about a HTTP error' do
+ expect(subject).to match /could not be fetched because of HTTP error!/
+ end
+ end
+
+ context 'when response has 404 status' do
+ before do
+ WebMock.stub_request(:get, location).to_return(body: remote_file_content, status: 404)
+ end
+
+ it 'should returns error message about a timeout' do
+ expect(subject).to match /could not be fetched because of HTTP code `404` error!/
+ end
+ end
+
+ context 'when the URL is blocked' do
+ let(:location) { 'http://127.0.0.1/some/path/to/config.yaml' }
+
+ it 'should include details about blocked URL' do
+ expect(subject).to eq "Remote file could not be fetched because URL '#{location}' " \
+ 'is blocked: Requests to localhost are not allowed!'
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
new file mode 100644
index 00000000000..5b236fe99f1
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::External::Mapper do
+ let(:project) { create(:project, :repository) }
+ let(:file_content) do
+ <<~HEREDOC
+ image: 'ruby:2.2'
+ HEREDOC
+ end
+
+ describe '#process' do
+ subject { described_class.new(values, project, '123456').process }
+
+ context "when 'include' keyword is defined as string" do
+ context 'when the string is a local file' do
+ let(:values) do
+ {
+ include: '/lib/gitlab/ci/templates/non-existent-file.yml',
+ image: 'ruby:2.2'
+ }
+ end
+
+ it 'returns an array' do
+ expect(subject).to be_an(Array)
+ end
+
+ it 'returns File instances' do
+ expect(subject.first)
+ .to be_an_instance_of(Gitlab::Ci::Config::External::File::Local)
+ end
+ end
+
+ context 'when the string is a remote file' do
+ let(:remote_url) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+ let(:values) do
+ {
+ include: remote_url,
+ image: 'ruby:2.2'
+ }
+ end
+
+ before do
+ WebMock.stub_request(:get, remote_url).to_return(body: file_content)
+ end
+
+ it 'returns an array' do
+ expect(subject).to be_an(Array)
+ end
+
+ it 'returns File instances' do
+ expect(subject.first)
+ .to be_an_instance_of(Gitlab::Ci::Config::External::File::Remote)
+ end
+ end
+ end
+
+ context "when 'include' is defined as an array" do
+ let(:remote_url) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+ let(:values) do
+ {
+ include:
+ [
+ remote_url,
+ '/lib/gitlab/ci/templates/template.yml'
+ ],
+ image: 'ruby:2.2'
+ }
+ end
+
+ before do
+ WebMock.stub_request(:get, remote_url).to_return(body: file_content)
+ end
+
+ it 'returns an array' do
+ expect(subject).to be_an(Array)
+ end
+
+ it 'returns Files instances' do
+ expect(subject).to all(respond_to(:valid?))
+ expect(subject).to all(respond_to(:content))
+ end
+ end
+
+ context "when 'include' is not defined" do
+ let(:values) do
+ {
+ image: 'ruby:2.2'
+ }
+ end
+
+ it 'returns an empty array' do
+ expect(subject).to be_empty
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/external/processor_spec.rb b/spec/lib/gitlab/ci/config/external/processor_spec.rb
new file mode 100644
index 00000000000..1a05f716247
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/external/processor_spec.rb
@@ -0,0 +1,190 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Ci::Config::External::Processor do
+ let(:project) { create(:project, :repository) }
+ let(:processor) { described_class.new(values, project, '12345') }
+
+ describe "#perform" do
+ context 'when no external files defined' do
+ let(:values) { { image: 'ruby:2.2' } }
+
+ it 'should return the same values' do
+ expect(processor.perform).to eq(values)
+ end
+ end
+
+ context 'when an invalid local file is defined' do
+ let(:values) { { include: '/lib/gitlab/ci/templates/non-existent-file.yml', image: 'ruby:2.2' } }
+
+ it 'should raise an error' do
+ expect { processor.perform }.to raise_error(
+ described_class::IncludeError,
+ "Local file `/lib/gitlab/ci/templates/non-existent-file.yml` does not exist!"
+ )
+ end
+ end
+
+ context 'when an invalid remote file is defined' do
+ let(:remote_file) { 'http://doesntexist.com/.gitlab-ci-1.yml' }
+ let(:values) { { include: remote_file, image: 'ruby:2.2' } }
+
+ before do
+ WebMock.stub_request(:get, remote_file).to_raise(SocketError.new('Some HTTP error'))
+ end
+
+ it 'should raise an error' do
+ expect { processor.perform }.to raise_error(
+ described_class::IncludeError,
+ "Remote file `#{remote_file}` could not be fetched because of a socket error!"
+ )
+ end
+ end
+
+ context 'with a valid remote external file is defined' do
+ let(:remote_file) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+ let(:values) { { include: remote_file, image: 'ruby:2.2' } }
+ let(:external_file_content) do
+ <<-HEREDOC
+ before_script:
+ - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
+ - ruby -v
+ - which ruby
+ - gem install bundler --no-ri --no-rdoc
+ - bundle install --jobs $(nproc) "${FLAGS[@]}"
+
+ rspec:
+ script:
+ - bundle exec rspec
+
+ rubocop:
+ script:
+ - bundle exec rubocop
+ HEREDOC
+ end
+
+ before do
+ WebMock.stub_request(:get, remote_file).to_return(body: external_file_content)
+ end
+
+ it 'should append the file to the values' do
+ output = processor.perform
+ expect(output.keys).to match_array([:image, :before_script, :rspec, :rubocop])
+ end
+
+ it "should remove the 'include' keyword" do
+ expect(processor.perform[:include]).to be_nil
+ end
+ end
+
+ context 'with a valid local external file is defined' do
+ let(:values) { { include: '/lib/gitlab/ci/templates/template.yml', image: 'ruby:2.2' } }
+ let(:local_file_content) do
+ <<-HEREDOC
+ before_script:
+ - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
+ - ruby -v
+ - which ruby
+ - gem install bundler --no-ri --no-rdoc
+ - bundle install --jobs $(nproc) "${FLAGS[@]}"
+ HEREDOC
+ end
+
+ before do
+ allow_any_instance_of(Gitlab::Ci::Config::External::File::Local)
+ .to receive(:fetch_local_content).and_return(local_file_content)
+ end
+
+ it 'should append the file to the values' do
+ output = processor.perform
+ expect(output.keys).to match_array([:image, :before_script])
+ end
+
+ it "should remove the 'include' keyword" do
+ expect(processor.perform[:include]).to be_nil
+ end
+ end
+
+ context 'with multiple external files are defined' do
+ let(:remote_file) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+ let(:external_files) do
+ [
+ '/spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml',
+ remote_file
+ ]
+ end
+ let(:values) do
+ {
+ include: external_files,
+ image: 'ruby:2.2'
+ }
+ end
+
+ let(:remote_file_content) do
+ <<-HEREDOC
+ stages:
+ - build
+ - review
+ - cleanup
+ HEREDOC
+ end
+
+ before do
+ local_file_content = File.read(Rails.root.join('spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml'))
+
+ allow_any_instance_of(Gitlab::Ci::Config::External::File::Local)
+ .to receive(:fetch_local_content).and_return(local_file_content)
+
+ WebMock.stub_request(:get, remote_file).to_return(body: remote_file_content)
+ end
+
+ it 'should append the files to the values' do
+ expect(processor.perform.keys).to match_array([:image, :stages, :before_script, :rspec])
+ end
+
+ it "should remove the 'include' keyword" do
+ expect(processor.perform[:include]).to be_nil
+ end
+ end
+
+ context 'when external files are defined but not valid' do
+ let(:values) { { include: '/lib/gitlab/ci/templates/template.yml', image: 'ruby:2.2' } }
+
+ let(:local_file_content) { 'invalid content file ////' }
+
+ before do
+ allow_any_instance_of(Gitlab::Ci::Config::External::File::Local)
+ .to receive(:fetch_local_content).and_return(local_file_content)
+ end
+
+ it 'should raise an error' do
+ expect { processor.perform }.to raise_error(
+ described_class::IncludeError,
+ "Included file `/lib/gitlab/ci/templates/template.yml` does not have valid YAML syntax!"
+ )
+ end
+ end
+
+ context "when both external files and values defined the same key" do
+ let(:remote_file) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
+ let(:values) do
+ {
+ include: remote_file,
+ image: 'ruby:2.2'
+ }
+ end
+
+ let(:remote_file_content) do
+ <<~HEREDOC
+ image: php:5-fpm-alpine
+ HEREDOC
+ end
+
+ it 'should take precedence' do
+ WebMock.stub_request(:get, remote_file).to_return(body: remote_file_content)
+ expect(processor.perform[:image]).to eq('ruby:2.2')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config/loader_spec.rb b/spec/lib/gitlab/ci/config/loader_spec.rb
deleted file mode 100644
index 590fc8904c1..00000000000
--- a/spec/lib/gitlab/ci/config/loader_spec.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Ci::Config::Loader do
- let(:loader) { described_class.new(yml) }
-
- context 'when yaml syntax is correct' do
- let(:yml) { 'image: ruby:2.2' }
-
- describe '#valid?' do
- it 'returns true' do
- expect(loader.valid?).to be true
- end
- end
-
- describe '#load!' do
- it 'returns a valid hash' do
- expect(loader.load!).to eq(image: 'ruby:2.2')
- end
- end
- end
-
- context 'when yaml syntax is incorrect' do
- let(:yml) { '// incorrect' }
-
- describe '#valid?' do
- it 'returns false' do
- expect(loader.valid?).to be false
- end
- end
-
- describe '#load!' do
- it 'raises error' do
- expect { loader.load! }.to raise_error(
- Gitlab::Ci::Config::Loader::FormatError,
- 'Invalid configuration format'
- )
- end
- end
- end
-
- context 'when there is an unknown alias' do
- let(:yml) { 'steps: *bad_alias' }
-
- describe '#initialize' do
- it 'raises FormatError' do
- expect { loader }.to raise_error(Gitlab::Ci::Config::Loader::FormatError, 'Unknown alias: bad_alias')
- end
- end
- end
-
- context 'when yaml config is empty' do
- let(:yml) { '' }
-
- describe '#valid?' do
- it 'returns false' do
- expect(loader.valid?).to be false
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/config/normalizer_spec.rb b/spec/lib/gitlab/ci/config/normalizer_spec.rb
new file mode 100644
index 00000000000..97926695b6e
--- /dev/null
+++ b/spec/lib/gitlab/ci/config/normalizer_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+describe Gitlab::Ci::Config::Normalizer do
+ let(:job_name) { :rspec }
+ let(:job_config) { { script: 'rspec', parallel: 5, name: 'rspec' } }
+ let(:config) { { job_name => job_config } }
+
+ describe '.normalize_jobs' do
+ subject { described_class.new(config).normalize_jobs }
+
+ it 'does not have original job' do
+ is_expected.not_to include(job_name)
+ end
+
+ it 'has parallelized jobs' do
+ job_names = [:"rspec 1/5", :"rspec 2/5", :"rspec 3/5", :"rspec 4/5", :"rspec 5/5"]
+
+ is_expected.to include(*job_names)
+ end
+
+ it 'sets job instance in options' do
+ expect(subject.values).to all(include(:instance))
+ end
+
+ it 'parallelizes jobs with original config' do
+ original_config = config[job_name].except(:name)
+ configs = subject.values.map { |config| config.except(:name, :instance) }
+
+ expect(configs).to all(eq(original_config))
+ end
+
+ context 'when the job is not parallelized' do
+ let(:job_config) { { script: 'rspec', name: 'rspec' } }
+
+ it 'returns the same hash' do
+ is_expected.to eq(config)
+ end
+ end
+
+ context 'when there is a job with a slash in it' do
+ let(:job_name) { :"rspec 35/2" }
+
+ it 'properly parallelizes job names' do
+ job_names = [:"rspec 35/2 1/5", :"rspec 35/2 2/5", :"rspec 35/2 3/5", :"rspec 35/2 4/5", :"rspec 35/2 5/5"]
+
+ is_expected.to include(*job_names)
+ end
+ end
+
+ context 'when jobs depend on parallelized jobs' do
+ let(:config) { { job_name => job_config, other_job: { script: 'echo 1', dependencies: [job_name.to_s] } } }
+
+ it 'parallelizes dependencies' do
+ job_names = ["rspec 1/5", "rspec 2/5", "rspec 3/5", "rspec 4/5", "rspec 5/5"]
+
+ expect(subject[:other_job][:dependencies]).to include(*job_names)
+ end
+
+ it 'does not include original job name in dependencies' do
+ expect(subject[:other_job][:dependencies]).not_to include(job_name)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb
index b43aca8a354..975e11e8cc1 100644
--- a/spec/lib/gitlab/ci/config_spec.rb
+++ b/spec/lib/gitlab/ci/config_spec.rb
@@ -1,6 +1,4 @@
-require 'fast_spec_helper'
-
-require_dependency 'active_model'
+require 'spec_helper'
describe Gitlab::Ci::Config do
let(:config) do
@@ -202,8 +200,8 @@ describe Gitlab::Ci::Config do
it 'raises error YamlProcessor validationError' do
expect { config }.to raise_error(
- ::Gitlab::Ci::YamlProcessor::ValidationError,
- "Local file 'invalid' is not valid."
+ described_class::ConfigError,
+ "Included file `invalid` does not have YAML extension!"
)
end
end
diff --git a/spec/lib/gitlab/ci/external/file/local_spec.rb b/spec/lib/gitlab/ci/external/file/local_spec.rb
deleted file mode 100644
index 3f32d81a827..00000000000
--- a/spec/lib/gitlab/ci/external/file/local_spec.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe Gitlab::Ci::External::File::Local do
- let(:project) { create(:project, :repository) }
- let(:local_file) { described_class.new(location, { project: project, sha: '12345' }) }
-
- describe '#valid?' do
- context 'when is a valid local path' do
- let(:location) { '/vendor/gitlab-ci-yml/existent-file.yml' }
-
- before do
- allow_any_instance_of(described_class).to receive(:fetch_local_content).and_return("image: 'ruby2:2'")
- end
-
- it 'should return true' do
- expect(local_file.valid?).to be_truthy
- end
- end
-
- context 'when is not a valid local path' do
- let(:location) { '/vendor/gitlab-ci-yml/non-existent-file.yml' }
-
- it 'should return false' do
- expect(local_file.valid?).to be_falsy
- end
- end
-
- context 'when is not a yaml file' do
- let(:location) { '/config/application.rb' }
-
- it 'should return false' do
- expect(local_file.valid?).to be_falsy
- end
- end
- end
-
- describe '#content' do
- context 'with a a valid file' do
- let(:local_file_content) do
- <<~HEREDOC
- before_script:
- - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- - ruby -v
- - which ruby
- - gem install bundler --no-ri --no-rdoc
- - bundle install --jobs $(nproc) "${FLAGS[@]}"
- HEREDOC
- end
- let(:location) { '/vendor/gitlab-ci-yml/existent-file.yml' }
-
- before do
- allow_any_instance_of(described_class).to receive(:fetch_local_content).and_return(local_file_content)
- end
-
- it 'should return the content of the file' do
- expect(local_file.content).to eq(local_file_content)
- end
- end
-
- context 'with an invalid file' do
- let(:location) { '/vendor/gitlab-ci-yml/non-existent-file.yml' }
-
- it 'should be nil' do
- expect(local_file.content).to be_nil
- end
- end
- end
-
- describe '#error_message' do
- let(:location) { '/vendor/gitlab-ci-yml/non-existent-file.yml' }
-
- it 'should return an error message' do
- expect(local_file.error_message).to eq("Local file '#{location}' is not valid.")
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/external/file/remote_spec.rb b/spec/lib/gitlab/ci/external/file/remote_spec.rb
deleted file mode 100644
index b1819c8960b..00000000000
--- a/spec/lib/gitlab/ci/external/file/remote_spec.rb
+++ /dev/null
@@ -1,114 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe Gitlab::Ci::External::File::Remote do
- let(:remote_file) { described_class.new(location) }
- let(:location) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
- let(:remote_file_content) do
- <<~HEREDOC
- before_script:
- - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- - ruby -v
- - which ruby
- - gem install bundler --no-ri --no-rdoc
- - bundle install --jobs $(nproc) "${FLAGS[@]}"
- HEREDOC
- end
-
- describe "#valid?" do
- context 'when is a valid remote url' do
- before do
- WebMock.stub_request(:get, location).to_return(body: remote_file_content)
- end
-
- it 'should return true' do
- expect(remote_file.valid?).to be_truthy
- end
- end
-
- context 'with an irregular url' do
- let(:location) { 'not-valid://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
-
- it 'should return false' do
- expect(remote_file.valid?).to be_falsy
- end
- end
-
- context 'with a timeout' do
- before do
- allow(Gitlab::HTTP).to receive(:get).and_raise(Timeout::Error)
- end
-
- it 'should be falsy' do
- expect(remote_file.valid?).to be_falsy
- end
- end
-
- context 'when is not a yaml file' do
- let(:location) { 'https://asdasdasdaj48ggerexample.com' }
-
- it 'should be falsy' do
- expect(remote_file.valid?).to be_falsy
- end
- end
-
- context 'with an internal url' do
- let(:location) { 'http://localhost:8080' }
-
- it 'should be falsy' do
- expect(remote_file.valid?).to be_falsy
- end
- end
- end
-
- describe "#content" do
- context 'with a valid remote file' do
- before do
- WebMock.stub_request(:get, location).to_return(body: remote_file_content)
- end
-
- it 'should return the content of the file' do
- expect(remote_file.content).to eql(remote_file_content)
- end
- end
-
- context 'with a timeout' do
- before do
- allow(Gitlab::HTTP).to receive(:get).and_raise(Timeout::Error)
- end
-
- it 'should be falsy' do
- expect(remote_file.content).to be_falsy
- end
- end
-
- context 'with an invalid remote url' do
- let(:location) { 'https://asdasdasdaj48ggerexample.com' }
-
- before do
- WebMock.stub_request(:get, location).to_raise(SocketError.new('Some HTTP error'))
- end
-
- it 'should be nil' do
- expect(remote_file.content).to be_nil
- end
- end
-
- context 'with an internal url' do
- let(:location) { 'http://localhost:8080' }
-
- it 'should be nil' do
- expect(remote_file.content).to be_nil
- end
- end
- end
-
- describe "#error_message" do
- let(:location) { 'not-valid://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
-
- it 'should return an error message' do
- expect(remote_file.error_message).to eq("Remote file '#{location}' is not valid.")
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/external/mapper_spec.rb b/spec/lib/gitlab/ci/external/mapper_spec.rb
deleted file mode 100644
index 6270d27a36d..00000000000
--- a/spec/lib/gitlab/ci/external/mapper_spec.rb
+++ /dev/null
@@ -1,96 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe Gitlab::Ci::External::Mapper do
- let(:project) { create(:project, :repository) }
- let(:file_content) do
- <<~HEREDOC
- image: 'ruby:2.2'
- HEREDOC
- end
-
- describe '#process' do
- subject { described_class.new(values, project, '123456').process }
-
- context "when 'include' keyword is defined as string" do
- context 'when the string is a local file' do
- let(:values) do
- {
- include: '/vendor/gitlab-ci-yml/non-existent-file.yml',
- image: 'ruby:2.2'
- }
- end
-
- it 'returns an array' do
- expect(subject).to be_an(Array)
- end
-
- it 'returns File instances' do
- expect(subject.first).to be_an_instance_of(Gitlab::Ci::External::File::Local)
- end
- end
-
- context 'when the string is a remote file' do
- let(:remote_url) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
- let(:values) do
- {
- include: remote_url,
- image: 'ruby:2.2'
- }
- end
-
- before do
- WebMock.stub_request(:get, remote_url).to_return(body: file_content)
- end
-
- it 'returns an array' do
- expect(subject).to be_an(Array)
- end
-
- it 'returns File instances' do
- expect(subject.first).to be_an_instance_of(Gitlab::Ci::External::File::Remote)
- end
- end
- end
-
- context "when 'include' is defined as an array" do
- let(:remote_url) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
- let(:values) do
- {
- include:
- [
- remote_url,
- '/vendor/gitlab-ci-yml/template.yml'
- ],
- image: 'ruby:2.2'
- }
- end
-
- before do
- WebMock.stub_request(:get, remote_url).to_return(body: file_content)
- end
-
- it 'returns an array' do
- expect(subject).to be_an(Array)
- end
-
- it 'returns Files instances' do
- expect(subject).to all(respond_to(:valid?))
- expect(subject).to all(respond_to(:content))
- end
- end
-
- context "when 'include' is not defined" do
- let(:values) do
- {
- image: 'ruby:2.2'
- }
- end
-
- it 'returns an empty array' do
- expect(subject).to be_empty
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/external/processor_spec.rb b/spec/lib/gitlab/ci/external/processor_spec.rb
deleted file mode 100644
index 688c2b3c8aa..00000000000
--- a/spec/lib/gitlab/ci/external/processor_spec.rb
+++ /dev/null
@@ -1,182 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-describe Gitlab::Ci::External::Processor do
- let(:project) { create(:project, :repository) }
- let(:processor) { described_class.new(values, project, '12345') }
-
- describe "#perform" do
- context 'when no external files defined' do
- let(:values) { { image: 'ruby:2.2' } }
-
- it 'should return the same values' do
- expect(processor.perform).to eq(values)
- end
- end
-
- context 'when an invalid local file is defined' do
- let(:values) { { include: '/vendor/gitlab-ci-yml/non-existent-file.yml', image: 'ruby:2.2' } }
-
- it 'should raise an error' do
- expect { processor.perform }.to raise_error(
- described_class::FileError,
- "Local file '/vendor/gitlab-ci-yml/non-existent-file.yml' is not valid."
- )
- end
- end
-
- context 'when an invalid remote file is defined' do
- let(:remote_file) { 'http://doesntexist.com/.gitlab-ci-1.yml' }
- let(:values) { { include: remote_file, image: 'ruby:2.2' } }
-
- before do
- WebMock.stub_request(:get, remote_file).to_raise(SocketError.new('Some HTTP error'))
- end
-
- it 'should raise an error' do
- expect { processor.perform }.to raise_error(
- described_class::FileError,
- "Remote file '#{remote_file}' is not valid."
- )
- end
- end
-
- context 'with a valid remote external file is defined' do
- let(:remote_file) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
- let(:values) { { include: remote_file, image: 'ruby:2.2' } }
- let(:external_file_content) do
- <<-HEREDOC
- before_script:
- - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- - ruby -v
- - which ruby
- - gem install bundler --no-ri --no-rdoc
- - bundle install --jobs $(nproc) "${FLAGS[@]}"
-
- rspec:
- script:
- - bundle exec rspec
-
- rubocop:
- script:
- - bundle exec rubocop
- HEREDOC
- end
-
- before do
- WebMock.stub_request(:get, remote_file).to_return(body: external_file_content)
- end
-
- it 'should append the file to the values' do
- output = processor.perform
- expect(output.keys).to match_array([:image, :before_script, :rspec, :rubocop])
- end
-
- it "should remove the 'include' keyword" do
- expect(processor.perform[:include]).to be_nil
- end
- end
-
- context 'with a valid local external file is defined' do
- let(:values) { { include: '/vendor/gitlab-ci-yml/template.yml', image: 'ruby:2.2' } }
- let(:local_file_content) do
- <<-HEREDOC
- before_script:
- - apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- - ruby -v
- - which ruby
- - gem install bundler --no-ri --no-rdoc
- - bundle install --jobs $(nproc) "${FLAGS[@]}"
- HEREDOC
- end
-
- before do
- allow_any_instance_of(Gitlab::Ci::External::File::Local).to receive(:fetch_local_content).and_return(local_file_content)
- end
-
- it 'should append the file to the values' do
- output = processor.perform
- expect(output.keys).to match_array([:image, :before_script])
- end
-
- it "should remove the 'include' keyword" do
- expect(processor.perform[:include]).to be_nil
- end
- end
-
- context 'with multiple external files are defined' do
- let(:remote_file) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
- let(:external_files) do
- [
- '/spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml',
- remote_file
- ]
- end
- let(:values) do
- {
- include: external_files,
- image: 'ruby:2.2'
- }
- end
-
- let(:remote_file_content) do
- <<-HEREDOC
- stages:
- - build
- - review
- - cleanup
- HEREDOC
- end
-
- before do
- local_file_content = File.read(Rails.root.join('spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml'))
- allow_any_instance_of(Gitlab::Ci::External::File::Local).to receive(:fetch_local_content).and_return(local_file_content)
- WebMock.stub_request(:get, remote_file).to_return(body: remote_file_content)
- end
-
- it 'should append the files to the values' do
- expect(processor.perform.keys).to match_array([:image, :stages, :before_script, :rspec])
- end
-
- it "should remove the 'include' keyword" do
- expect(processor.perform[:include]).to be_nil
- end
- end
-
- context 'when external files are defined but not valid' do
- let(:values) { { include: '/vendor/gitlab-ci-yml/template.yml', image: 'ruby:2.2' } }
-
- let(:local_file_content) { 'invalid content file ////' }
-
- before do
- allow_any_instance_of(Gitlab::Ci::External::File::Local).to receive(:fetch_local_content).and_return(local_file_content)
- end
-
- it 'should raise an error' do
- expect { processor.perform }.to raise_error(Gitlab::Ci::Config::Loader::FormatError)
- end
- end
-
- context "when both external files and values defined the same key" do
- let(:remote_file) { 'https://gitlab.com/gitlab-org/gitlab-ce/blob/1234/.gitlab-ci-1.yml' }
- let(:values) do
- {
- include: remote_file,
- image: 'ruby:2.2'
- }
- end
-
- let(:remote_file_content) do
- <<~HEREDOC
- image: php:5-fpm-alpine
- HEREDOC
- end
-
- it 'should take precedence' do
- WebMock.stub_request(:get, remote_file).to_return(body: remote_file_content)
- expect(processor.perform[:image]).to eq('ruby:2.2')
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/parsers/junit_spec.rb b/spec/lib/gitlab/ci/parsers/junit_spec.rb
deleted file mode 100644
index 47497f06229..00000000000
--- a/spec/lib/gitlab/ci/parsers/junit_spec.rb
+++ /dev/null
@@ -1,172 +0,0 @@
-require 'fast_spec_helper'
-
-describe Gitlab::Ci::Parsers::Junit do
- describe '#parse!' do
- subject { described_class.new.parse!(junit, test_suite) }
-
- let(:test_suite) { Gitlab::Ci::Reports::TestSuite.new('rspec') }
- let(:test_cases) { flattened_test_cases(test_suite) }
-
- context 'when data is JUnit style XML' do
- context 'when there are no <testcases> in <testsuite>' do
- let(:junit) do
- <<-EOF.strip_heredoc
- <testsuite></testsuite>
- EOF
- end
-
- it 'ignores the case' do
- expect { subject }.not_to raise_error
-
- expect(test_cases.count).to eq(0)
- end
- end
-
- context 'when there are no <testcases> in <testsuites>' do
- let(:junit) do
- <<-EOF.strip_heredoc
- <testsuites><testsuite /></testsuites>
- EOF
- end
-
- it 'ignores the case' do
- expect { subject }.not_to raise_error
-
- expect(test_cases.count).to eq(0)
- end
- end
-
- context 'when there is only one <testcase> in <testsuite>' do
- let(:junit) do
- <<-EOF.strip_heredoc
- <testsuite>
- <testcase classname='Calculator' name='sumTest1' time='0.01'></testcase>
- </testsuite>
- EOF
- end
-
- it 'parses XML and adds a test case to a suite' do
- expect { subject }.not_to raise_error
-
- expect(test_cases[0].classname).to eq('Calculator')
- expect(test_cases[0].name).to eq('sumTest1')
- expect(test_cases[0].execution_time).to eq(0.01)
- end
- end
-
- context 'when there is only one <testsuite> in <testsuites>' do
- let(:junit) do
- <<-EOF.strip_heredoc
- <testsuites>
- <testsuite>
- <testcase classname='Calculator' name='sumTest1' time='0.01'></testcase>
- </testsuite>
- </testsuites>
- EOF
- end
-
- it 'parses XML and adds a test case to a suite' do
- expect { subject }.not_to raise_error
-
- expect(test_cases[0].classname).to eq('Calculator')
- expect(test_cases[0].name).to eq('sumTest1')
- expect(test_cases[0].execution_time).to eq(0.01)
- end
- end
-
- context 'PHPUnit' do
- let(:junit) do
- <<-EOF.strip_heredoc
- <testsuites>
- <testsuite name="Project Test Suite" tests="1" assertions="1" failures="0" errors="0" time="1.376748">
- <testsuite name="XXX\\FrontEnd\\WebBundle\\Tests\\Controller\\LogControllerTest" file="/Users/mcfedr/projects/xxx/server/tests/XXX/FrontEnd/WebBundle/Tests/Controller/LogControllerTest.php" tests="1" assertions="1" failures="0" errors="0" time="1.376748">
- <testcase name="testIndexAction" class="XXX\\FrontEnd\\WebBundle\\Tests\\Controller\\LogControllerTest" file="/Users/mcfedr/projects/xxx/server/tests/XXX/FrontEnd/WebBundle/Tests/Controller/LogControllerTest.php" line="9" assertions="1" time="1.376748"/>
- </testsuite>
- </testsuite>
- </testsuites>
- EOF
- end
-
- it 'parses XML and adds a test case to a suite' do
- expect { subject }.not_to raise_error
-
- expect(test_cases.count).to eq(1)
- end
- end
-
- context 'when there are two test cases' do
- let(:junit) do
- <<-EOF.strip_heredoc
- <testsuite>
- <testcase classname='Calculator' name='sumTest1' time='0.01'></testcase>
- <testcase classname='Calculator' name='sumTest2' time='0.02'></testcase>
- </testsuite>
- EOF
- end
-
- it 'parses XML and adds test cases to a suite' do
- expect { subject }.not_to raise_error
-
- expect(test_cases[0].classname).to eq('Calculator')
- expect(test_cases[0].name).to eq('sumTest1')
- expect(test_cases[0].execution_time).to eq(0.01)
- expect(test_cases[1].classname).to eq('Calculator')
- expect(test_cases[1].name).to eq('sumTest2')
- expect(test_cases[1].execution_time).to eq(0.02)
- end
- end
-
- context 'when there are two test suites' do
- let(:junit) do
- <<-EOF.strip_heredoc
- <testsuites>
- <testsuite>
- <testcase classname='Calculator' name='sumTest1' time='0.01'></testcase>
- <testcase classname='Calculator' name='sumTest2' time='0.02'></testcase>
- </testsuite>
- <testsuite>
- <testcase classname='Statemachine' name='happy path' time='100'></testcase>
- <testcase classname='Statemachine' name='unhappy path' time='200'></testcase>
- </testsuite>
- </testsuites>
- EOF
- end
-
- it 'parses XML and adds test cases to a suite' do
- expect { subject }.not_to raise_error
-
- expect(test_cases[0].classname).to eq('Calculator')
- expect(test_cases[0].name).to eq('sumTest1')
- expect(test_cases[0].execution_time).to eq(0.01)
- expect(test_cases[1].classname).to eq('Calculator')
- expect(test_cases[1].name).to eq('sumTest2')
- expect(test_cases[1].execution_time).to eq(0.02)
- expect(test_cases[2].classname).to eq('Statemachine')
- expect(test_cases[2].name).to eq('happy path')
- expect(test_cases[2].execution_time).to eq(100)
- expect(test_cases[3].classname).to eq('Statemachine')
- expect(test_cases[3].name).to eq('unhappy path')
- expect(test_cases[3].execution_time).to eq(200)
- end
- end
- end
-
- context 'when data is not JUnit style XML' do
- let(:junit) { { testsuite: 'abc' }.to_json }
-
- it 'raises an error' do
- expect { subject }.to raise_error(described_class::JunitParserError)
- end
- end
-
- private
-
- def flattened_test_cases(test_suite)
- test_suite.test_cases.map do |status, value|
- value.map do |key, test_case|
- test_case
- end
- end.flatten
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/parsers/test/junit_spec.rb b/spec/lib/gitlab/ci/parsers/test/junit_spec.rb
new file mode 100644
index 00000000000..a49402c7398
--- /dev/null
+++ b/spec/lib/gitlab/ci/parsers/test/junit_spec.rb
@@ -0,0 +1,172 @@
+require 'fast_spec_helper'
+
+describe Gitlab::Ci::Parsers::Test::Junit do
+ describe '#parse!' do
+ subject { described_class.new.parse!(junit, test_suite) }
+
+ let(:test_suite) { Gitlab::Ci::Reports::TestSuite.new('rspec') }
+ let(:test_cases) { flattened_test_cases(test_suite) }
+
+ context 'when data is JUnit style XML' do
+ context 'when there are no <testcases> in <testsuite>' do
+ let(:junit) do
+ <<-EOF.strip_heredoc
+ <testsuite></testsuite>
+ EOF
+ end
+
+ it 'ignores the case' do
+ expect { subject }.not_to raise_error
+
+ expect(test_cases.count).to eq(0)
+ end
+ end
+
+ context 'when there are no <testcases> in <testsuites>' do
+ let(:junit) do
+ <<-EOF.strip_heredoc
+ <testsuites><testsuite /></testsuites>
+ EOF
+ end
+
+ it 'ignores the case' do
+ expect { subject }.not_to raise_error
+
+ expect(test_cases.count).to eq(0)
+ end
+ end
+
+ context 'when there is only one <testcase> in <testsuite>' do
+ let(:junit) do
+ <<-EOF.strip_heredoc
+ <testsuite>
+ <testcase classname='Calculator' name='sumTest1' time='0.01'></testcase>
+ </testsuite>
+ EOF
+ end
+
+ it 'parses XML and adds a test case to a suite' do
+ expect { subject }.not_to raise_error
+
+ expect(test_cases[0].classname).to eq('Calculator')
+ expect(test_cases[0].name).to eq('sumTest1')
+ expect(test_cases[0].execution_time).to eq(0.01)
+ end
+ end
+
+ context 'when there is only one <testsuite> in <testsuites>' do
+ let(:junit) do
+ <<-EOF.strip_heredoc
+ <testsuites>
+ <testsuite>
+ <testcase classname='Calculator' name='sumTest1' time='0.01'></testcase>
+ </testsuite>
+ </testsuites>
+ EOF
+ end
+
+ it 'parses XML and adds a test case to a suite' do
+ expect { subject }.not_to raise_error
+
+ expect(test_cases[0].classname).to eq('Calculator')
+ expect(test_cases[0].name).to eq('sumTest1')
+ expect(test_cases[0].execution_time).to eq(0.01)
+ end
+ end
+
+ context 'PHPUnit' do
+ let(:junit) do
+ <<-EOF.strip_heredoc
+ <testsuites>
+ <testsuite name="Project Test Suite" tests="1" assertions="1" failures="0" errors="0" time="1.376748">
+ <testsuite name="XXX\\FrontEnd\\WebBundle\\Tests\\Controller\\LogControllerTest" file="/Users/mcfedr/projects/xxx/server/tests/XXX/FrontEnd/WebBundle/Tests/Controller/LogControllerTest.php" tests="1" assertions="1" failures="0" errors="0" time="1.376748">
+ <testcase name="testIndexAction" class="XXX\\FrontEnd\\WebBundle\\Tests\\Controller\\LogControllerTest" file="/Users/mcfedr/projects/xxx/server/tests/XXX/FrontEnd/WebBundle/Tests/Controller/LogControllerTest.php" line="9" assertions="1" time="1.376748"/>
+ </testsuite>
+ </testsuite>
+ </testsuites>
+ EOF
+ end
+
+ it 'parses XML and adds a test case to a suite' do
+ expect { subject }.not_to raise_error
+
+ expect(test_cases.count).to eq(1)
+ end
+ end
+
+ context 'when there are two test cases' do
+ let(:junit) do
+ <<-EOF.strip_heredoc
+ <testsuite>
+ <testcase classname='Calculator' name='sumTest1' time='0.01'></testcase>
+ <testcase classname='Calculator' name='sumTest2' time='0.02'></testcase>
+ </testsuite>
+ EOF
+ end
+
+ it 'parses XML and adds test cases to a suite' do
+ expect { subject }.not_to raise_error
+
+ expect(test_cases[0].classname).to eq('Calculator')
+ expect(test_cases[0].name).to eq('sumTest1')
+ expect(test_cases[0].execution_time).to eq(0.01)
+ expect(test_cases[1].classname).to eq('Calculator')
+ expect(test_cases[1].name).to eq('sumTest2')
+ expect(test_cases[1].execution_time).to eq(0.02)
+ end
+ end
+
+ context 'when there are two test suites' do
+ let(:junit) do
+ <<-EOF.strip_heredoc
+ <testsuites>
+ <testsuite>
+ <testcase classname='Calculator' name='sumTest1' time='0.01'></testcase>
+ <testcase classname='Calculator' name='sumTest2' time='0.02'></testcase>
+ </testsuite>
+ <testsuite>
+ <testcase classname='Statemachine' name='happy path' time='100'></testcase>
+ <testcase classname='Statemachine' name='unhappy path' time='200'></testcase>
+ </testsuite>
+ </testsuites>
+ EOF
+ end
+
+ it 'parses XML and adds test cases to a suite' do
+ expect { subject }.not_to raise_error
+
+ expect(test_cases[0].classname).to eq('Calculator')
+ expect(test_cases[0].name).to eq('sumTest1')
+ expect(test_cases[0].execution_time).to eq(0.01)
+ expect(test_cases[1].classname).to eq('Calculator')
+ expect(test_cases[1].name).to eq('sumTest2')
+ expect(test_cases[1].execution_time).to eq(0.02)
+ expect(test_cases[2].classname).to eq('Statemachine')
+ expect(test_cases[2].name).to eq('happy path')
+ expect(test_cases[2].execution_time).to eq(100)
+ expect(test_cases[3].classname).to eq('Statemachine')
+ expect(test_cases[3].name).to eq('unhappy path')
+ expect(test_cases[3].execution_time).to eq(200)
+ end
+ end
+ end
+
+ context 'when data is not JUnit style XML' do
+ let(:junit) { { testsuite: 'abc' }.to_json }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(described_class::JunitParserError)
+ end
+ end
+
+ private
+
+ def flattened_test_cases(test_suite)
+ test_suite.test_cases.map do |status, value|
+ value.map do |key, test_case|
+ test_case
+ end
+ end.flatten
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/parsers/test_spec.rb b/spec/lib/gitlab/ci/parsers/test_spec.rb
new file mode 100644
index 00000000000..0b85b432677
--- /dev/null
+++ b/spec/lib/gitlab/ci/parsers/test_spec.rb
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Parsers::Test do
+ describe '.fabricate!' do
+ subject { described_class.fabricate!(file_type) }
+
+ context 'when file_type exists' do
+ let(:file_type) { 'junit' }
+
+ it 'fabricates the class' do
+ is_expected.to be_a(described_class::Junit)
+ end
+ end
+
+ context 'when file_type does not exist' do
+ let(:file_type) { 'undefined' }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Ci::Parsers::Test::ParserNotFoundError)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/parsers_spec.rb b/spec/lib/gitlab/ci/parsers_spec.rb
deleted file mode 100644
index 2fa83c4abae..00000000000
--- a/spec/lib/gitlab/ci/parsers_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Ci::Parsers do
- describe '.fabricate!' do
- subject { described_class.fabricate!(file_type) }
-
- context 'when file_type exists' do
- let(:file_type) { 'junit' }
-
- it 'fabricates the class' do
- is_expected.to be_a(described_class::Junit)
- end
- end
-
- context 'when file_type does not exist' do
- let(:file_type) { 'undefined' }
-
- it 'raises an error' do
- expect { subject }.to raise_error(NameError)
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/string_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/string_spec.rb
index 1ccb792d1da..f54ef492e6d 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/lexeme/string_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/string_spec.rb
@@ -93,7 +93,7 @@ describe Gitlab::Ci::Pipeline::Expression::Lexeme::String do
end
describe '#evaluate' do
- it 'returns string value it is is present' do
+ it 'returns string value if it is present' do
string = described_class.new('my string')
expect(string.evaluate).to eq 'my string'
diff --git a/spec/lib/gitlab/ci/status/build/factory_spec.rb b/spec/lib/gitlab/ci/status/build/factory_spec.rb
index 8b92088902b..b379b08ad62 100644
--- a/spec/lib/gitlab/ci/status/build/factory_spec.rb
+++ b/spec/lib/gitlab/ci/status/build/factory_spec.rb
@@ -319,4 +319,53 @@ describe Gitlab::Ci::Status::Build::Factory do
end
end
end
+
+ context 'when build is a delayed action' do
+ let(:build) { create(:ci_build, :scheduled) }
+
+ it 'matches correct core status' do
+ expect(factory.core_status).to be_a Gitlab::Ci::Status::Scheduled
+ end
+
+ it 'matches correct extended statuses' do
+ expect(factory.extended_statuses)
+ .to eq [Gitlab::Ci::Status::Build::Scheduled,
+ Gitlab::Ci::Status::Build::Unschedule,
+ Gitlab::Ci::Status::Build::Action]
+ end
+
+ it 'fabricates action detailed status' do
+ expect(status).to be_a Gitlab::Ci::Status::Build::Action
+ end
+
+ it 'fabricates status with correct details' do
+ expect(status.text).to eq 'delayed'
+ expect(status.group).to eq 'scheduled'
+ expect(status.icon).to eq 'status_scheduled'
+ expect(status.favicon).to eq 'favicon_status_scheduled'
+ expect(status.illustration).to include(:image, :size, :title, :content)
+ expect(status.label).to include 'unschedule action'
+ expect(status).to have_details
+ expect(status.action_path).to include 'unschedule'
+ end
+
+ context 'when user has ability to play action' do
+ it 'fabricates status that has action' do
+ expect(status).to have_action
+ end
+ end
+
+ context 'when user does not have ability to play action' do
+ before do
+ allow(build.project).to receive(:empty_repo?).and_return(false)
+
+ create(:protected_branch, :no_one_can_push,
+ name: build.ref, project: build.project)
+ end
+
+ it 'fabricates status that has no action' do
+ expect(status).not_to have_action
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/status/build/scheduled_spec.rb b/spec/lib/gitlab/ci/status/build/scheduled_spec.rb
new file mode 100644
index 00000000000..68b87fea75d
--- /dev/null
+++ b/spec/lib/gitlab/ci/status/build/scheduled_spec.rb
@@ -0,0 +1,44 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Status::Build::Scheduled do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :stubbed_repository) }
+ let(:build) { create(:ci_build, :scheduled, project: project) }
+ let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
+
+ subject { described_class.new(status) }
+
+ describe '#illustration' do
+ it { expect(subject.illustration).to include(:image, :size, :title) }
+ end
+
+ describe '#status_tooltip' do
+ let(:build) { create(:ci_build, scheduled_at: 1.minute.since, project: project) }
+
+ it 'has a placeholder for the remaining time' do
+ expect(subject.status_tooltip).to include('%{remainingTime}')
+ end
+ end
+
+ describe '.matches?' do
+ subject { described_class.matches?(build, user) }
+
+ context 'when build is scheduled and scheduled_at is present' do
+ let(:build) { create(:ci_build, :expired_scheduled, project: project) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when build is scheduled' do
+ let(:build) { create(:ci_build, status: :scheduled, project: project) }
+
+ it { is_expected.to be_falsy }
+ end
+
+ context 'when scheduled_at is present' do
+ let(:build) { create(:ci_build, scheduled_at: 1.minute.since, project: project) }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/status/build/unschedule_spec.rb b/spec/lib/gitlab/ci/status/build/unschedule_spec.rb
new file mode 100644
index 00000000000..ed046d66ca5
--- /dev/null
+++ b/spec/lib/gitlab/ci/status/build/unschedule_spec.rb
@@ -0,0 +1,94 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Status::Build::Unschedule do
+ let(:status) { double('core status') }
+ let(:user) { double('user') }
+
+ subject do
+ described_class.new(status)
+ end
+
+ describe '#label' do
+ it { expect(subject.label).to eq 'unschedule action' }
+ end
+
+ describe 'action details' do
+ let(:user) { create(:user) }
+ let(:build) { create(:ci_build) }
+ let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
+
+ describe '#has_action?' do
+ context 'when user is allowed to update build' do
+ before do
+ stub_not_protect_default_branch
+
+ build.project.add_developer(user)
+ end
+
+ it { is_expected.to have_action }
+ end
+
+ context 'when user is not allowed to update build' do
+ it { is_expected.not_to have_action }
+ end
+ end
+
+ describe '#action_path' do
+ it { expect(subject.action_path).to include "#{build.id}/unschedule" }
+ end
+
+ describe '#action_icon' do
+ it { expect(subject.action_icon).to eq 'time-out' }
+ end
+
+ describe '#action_title' do
+ it { expect(subject.action_title).to eq 'Unschedule' }
+ end
+
+ describe '#action_button_title' do
+ it { expect(subject.action_button_title).to eq 'Unschedule job' }
+ end
+ end
+
+ describe '.matches?' do
+ subject { described_class.matches?(build, user) }
+
+ context 'when build is scheduled' do
+ context 'when build unschedules an delayed job' do
+ let(:build) { create(:ci_build, :scheduled) }
+
+ it 'is a correct match' do
+ expect(subject).to be true
+ end
+ end
+
+ context 'when build unschedules an normal job' do
+ let(:build) { create(:ci_build) }
+
+ it 'does not match' do
+ expect(subject).to be false
+ end
+ end
+ end
+ end
+
+ describe '#status_tooltip' do
+ it 'does not override status status_tooltip' do
+ expect(status).to receive(:status_tooltip)
+
+ subject.status_tooltip
+ end
+ end
+
+ describe '#badge_tooltip' do
+ let(:user) { create(:user) }
+ let(:build) { create(:ci_build, :playable) }
+ let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
+
+ it 'does not override status badge_tooltip' do
+ expect(status).to receive(:badge_tooltip)
+
+ subject.badge_tooltip
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/status/pipeline/delayed_spec.rb b/spec/lib/gitlab/ci/status/pipeline/delayed_spec.rb
new file mode 100644
index 00000000000..f89712d2b03
--- /dev/null
+++ b/spec/lib/gitlab/ci/status/pipeline/delayed_spec.rb
@@ -0,0 +1,42 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Status::Pipeline::Delayed do
+ let(:pipeline) { double('pipeline') }
+
+ subject do
+ described_class.new(pipeline)
+ end
+
+ describe '#text' do
+ it 'overrides status text' do
+ expect(subject.text).to eq 'delayed'
+ end
+ end
+
+ describe '#label' do
+ it 'overrides status label' do
+ expect(subject.label).to eq 'waiting for delayed job'
+ end
+ end
+
+ describe '.matches?' do
+ let(:user) { double('user') }
+ subject { described_class.matches?(pipeline, user) }
+
+ context 'when pipeline is scheduled' do
+ let(:pipeline) { create(:ci_pipeline, :scheduled) }
+
+ it 'is a correct match' do
+ expect(subject).to be true
+ end
+ end
+
+ context 'when pipeline is not scheduled' do
+ let(:pipeline) { create(:ci_pipeline, :success) }
+
+ it 'does not match' do
+ expect(subject).to be false
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/status/pipeline/factory_spec.rb b/spec/lib/gitlab/ci/status/pipeline/factory_spec.rb
index defb3fdc0df..466087a0e31 100644
--- a/spec/lib/gitlab/ci/status/pipeline/factory_spec.rb
+++ b/spec/lib/gitlab/ci/status/pipeline/factory_spec.rb
@@ -11,8 +11,7 @@ describe Gitlab::Ci::Status::Pipeline::Factory do
end
context 'when pipeline has a core status' do
- (HasStatus::AVAILABLE_STATUSES - [HasStatus::BLOCKED_STATUS])
- .each do |simple_status|
+ (HasStatus::AVAILABLE_STATUSES - HasStatus::BLOCKED_STATUS).each do |simple_status|
context "when core status is #{simple_status}" do
let(:pipeline) { create(:ci_pipeline, status: simple_status) }
@@ -61,6 +60,27 @@ describe Gitlab::Ci::Status::Pipeline::Factory do
.to include "pipelines/#{pipeline.id}"
end
end
+
+ context "when core status is scheduled" do
+ let(:pipeline) { create(:ci_pipeline, status: :scheduled) }
+
+ it "matches scheduled core status" do
+ expect(factory.core_status)
+ .to be_a Gitlab::Ci::Status::Scheduled
+ end
+
+ it 'matches a correct extended statuses' do
+ expect(factory.extended_statuses)
+ .to eq [Gitlab::Ci::Status::Pipeline::Delayed]
+ end
+
+ it 'extends core status with common pipeline methods' do
+ expect(status).to have_details
+ expect(status).not_to have_action
+ expect(status.details_path)
+ .to include "pipelines/#{pipeline.id}"
+ end
+ end
end
context 'when pipeline has warnings' do
diff --git a/spec/lib/gitlab/ci/status/scheduled_spec.rb b/spec/lib/gitlab/ci/status/scheduled_spec.rb
new file mode 100644
index 00000000000..b8ca3caa1f7
--- /dev/null
+++ b/spec/lib/gitlab/ci/status/scheduled_spec.rb
@@ -0,0 +1,27 @@
+require 'spec_helper'
+
+describe Gitlab::Ci::Status::Scheduled do
+ subject do
+ described_class.new(double('subject'), double('user'))
+ end
+
+ describe '#text' do
+ it { expect(subject.text).to eq 'delayed' }
+ end
+
+ describe '#label' do
+ it { expect(subject.label).to eq 'delayed' }
+ end
+
+ describe '#icon' do
+ it { expect(subject.icon).to eq 'status_scheduled' }
+ end
+
+ describe '#favicon' do
+ it { expect(subject.favicon).to eq 'favicon_status_scheduled' }
+ end
+
+ describe '#group' do
+ it { expect(subject.group).to eq 'scheduled' }
+ end
+end
diff --git a/spec/lib/gitlab/ci/templates/templates_spec.rb b/spec/lib/gitlab/ci/templates/templates_spec.rb
new file mode 100644
index 00000000000..0dd74399a47
--- /dev/null
+++ b/spec/lib/gitlab/ci/templates/templates_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe "CI YML Templates" do
+ Gitlab::Template::GitlabCiYmlTemplate.all.each do |template|
+ it "#{template.name} should be valid" do
+ expect { Gitlab::Ci::YamlProcessor.new(template.content) }.not_to raise_error
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/trace/chunked_io_spec.rb b/spec/lib/gitlab/ci/trace/chunked_io_spec.rb
index 6259b952add..546a9e7d0cc 100644
--- a/spec/lib/gitlab/ci/trace/chunked_io_spec.rb
+++ b/spec/lib/gitlab/ci/trace/chunked_io_spec.rb
@@ -116,6 +116,19 @@ describe Gitlab::Ci::Trace::ChunkedIO, :clean_gitlab_redis_cache do
chunked_io.each_line { |line| }
end
end
+
+ context 'when buffer consist of many empty lines' do
+ let(:sample_trace_raw) { Array.new(10, " ").join("\n") }
+
+ before do
+ build.trace.set(sample_trace_raw)
+ end
+
+ it 'yields lines' do
+ expect { |b| chunked_io.each_line(&b) }
+ .to yield_successive_args(*string_io.each_line.to_a)
+ end
+ end
end
context "#read" do
@@ -143,6 +156,22 @@ describe Gitlab::Ci::Trace::ChunkedIO, :clean_gitlab_redis_cache do
end
end
+ context 'when chunk is missing data' do
+ let(:length) { nil }
+
+ before do
+ stub_buffer_size(1024)
+ build.trace.set(sample_trace_raw)
+
+ # make second chunk to not have data
+ build.trace_chunks.second.append('', 0)
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error described_class::FailedToGetChunkError
+ end
+ end
+
context 'when read only first 100 bytes' do
let(:length) { 100 }
@@ -266,6 +295,40 @@ describe Gitlab::Ci::Trace::ChunkedIO, :clean_gitlab_redis_cache do
expect(chunked_io.readline).to eq(string_io.readline)
end
end
+
+ context 'when chunk is missing data' do
+ let(:length) { nil }
+
+ before do
+ build.trace.set(sample_trace_raw)
+
+ # make first chunk to have invalid data
+ build.trace_chunks.first.append('data', 0)
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error described_class::FailedToGetChunkError
+ end
+ end
+
+ context 'when utf-8 is being used' do
+ let(:sample_trace_raw) { sample_trace_raw_utf8.force_encoding(Encoding::BINARY) }
+ let(:sample_trace_raw_utf8) { "😺\n😺\n😺\n😺" }
+
+ before do
+ stub_buffer_size(3) # the utf-8 character has 4 bytes
+
+ build.trace.set(sample_trace_raw_utf8)
+ end
+
+ it 'has known length' do
+ expect(sample_trace_raw_utf8.bytesize).to eq(4 * 4 + 3 * 1)
+ expect(sample_trace_raw.bytesize).to eq(4 * 4 + 3 * 1)
+ expect(chunked_io.size).to eq(4 * 4 + 3 * 1)
+ end
+
+ it_behaves_like 'all line matching'
+ end
end
context "#write" do
diff --git a/spec/lib/gitlab/ci/trace/stream_spec.rb b/spec/lib/gitlab/ci/trace/stream_spec.rb
index 4f49958dd33..38626f728d7 100644
--- a/spec/lib/gitlab/ci/trace/stream_spec.rb
+++ b/spec/lib/gitlab/ci/trace/stream_spec.rb
@@ -257,7 +257,8 @@ describe Gitlab::Ci::Trace::Stream, :clean_gitlab_redis_cache do
let!(:last_result) { stream.html_with_state }
before do
- stream.append("5678", 4)
+ data_stream.seek(4, IO::SEEK_SET)
+ data_stream.write("5678")
stream.seek(0)
end
@@ -271,25 +272,29 @@ describe Gitlab::Ci::Trace::Stream, :clean_gitlab_redis_cache do
end
context 'when stream is StringIO' do
+ let(:data_stream) do
+ StringIO.new("1234")
+ end
+
let(:stream) do
- described_class.new do
- StringIO.new("1234")
- end
+ described_class.new { data_stream }
end
it_behaves_like 'html_with_states'
end
context 'when stream is ChunkedIO' do
- let(:stream) do
- described_class.new do
- Gitlab::Ci::Trace::ChunkedIO.new(build).tap do |chunked_io|
- chunked_io.write("1234")
- chunked_io.seek(0, IO::SEEK_SET)
- end
+ let(:data_stream) do
+ Gitlab::Ci::Trace::ChunkedIO.new(build).tap do |chunked_io|
+ chunked_io.write("1234")
+ chunked_io.seek(0, IO::SEEK_SET)
end
end
+ let(:stream) do
+ described_class.new { data_stream }
+ end
+
it_behaves_like 'html_with_states'
end
end
diff --git a/spec/lib/gitlab/ci/variables/collection/item_spec.rb b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
index 46874662edd..8bf44acb228 100644
--- a/spec/lib/gitlab/ci/variables/collection/item_spec.rb
+++ b/spec/lib/gitlab/ci/variables/collection/item_spec.rb
@@ -36,7 +36,7 @@ describe Gitlab::Ci::Variables::Collection::Item do
shared_examples 'raises error for invalid type' do
it do
expect { described_class.new(key: variable_key, value: variable_value) }
- .to raise_error ArgumentError, /`value` must be of type String, while it was:/
+ .to raise_error ArgumentError, /`#{variable_key}` must be of type String or nil value, while it was:/
end
end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index fcbdf71a4e9..441e8214181 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -53,11 +53,11 @@ module Gitlab
describe 'retry entry' do
context 'when retry count is specified' do
let(:config) do
- YAML.dump(rspec: { script: 'rspec', retry: 1 })
+ YAML.dump(rspec: { script: 'rspec', retry: { max: 1 } })
end
it 'includes retry count in build options attribute' do
- expect(subject[:options]).to include(retry: 1)
+ expect(subject[:options]).to include(retry: { max: 1 })
end
end
@@ -121,6 +121,21 @@ module Gitlab
end
end
end
+
+ describe 'delayed job entry' do
+ context 'when delayed is defined' do
+ let(:config) do
+ YAML.dump(rspec: { script: 'rollout 10%',
+ when: 'delayed',
+ start_in: '1 day' })
+ end
+
+ it 'has the attributes' do
+ expect(subject[:when]).to eq 'delayed'
+ expect(subject[:options][:start_in]).to eq '1 day'
+ end
+ end
+ end
end
describe '#stages_attributes' do
@@ -630,6 +645,33 @@ module Gitlab
end
end
+ describe 'Parallel' do
+ context 'when job is parallelized' do
+ let(:parallel) { 5 }
+
+ let(:config) do
+ YAML.dump(rspec: { script: 'rspec',
+ parallel: parallel })
+ end
+
+ it 'returns parallelized jobs' do
+ config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ builds = config_processor.stage_builds_attributes('test')
+ build_options = builds.map { |build| build[:options] }
+
+ expect(builds.size).to eq(5)
+ expect(build_options).to all(include(:instance, parallel: parallel))
+ end
+
+ it 'does not have the original job' do
+ config_processor = Gitlab::Ci::YamlProcessor.new(config)
+ builds = config_processor.stage_builds_attributes('test')
+
+ expect(builds).not_to include(:rspec)
+ end
+ end
+ end
+
describe 'cache' do
context 'when cache definition has unknown keys' do
it 'raises relevant validation error' do
@@ -1260,7 +1302,7 @@ module Gitlab
config = YAML.dump({ rspec: { script: "test", when: 1 } })
expect do
Gitlab::Ci::YamlProcessor.new(config)
- end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec when should be on_success, on_failure, always or manual")
+ end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec when should be on_success, on_failure, always, manual or delayed")
end
it "returns errors if job artifacts:name is not an a string" do
@@ -1354,7 +1396,7 @@ module Gitlab
end.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError, "jobs:rspec dependencies should be an array of strings")
end
- it 'returns errors if pipeline variables expression is invalid' do
+ it 'returns errors if pipeline variables expression policy is invalid' do
config = YAML.dump({ rspec: { script: 'test', only: { variables: ['== null'] } } })
expect { Gitlab::Ci::YamlProcessor.new(config) }
@@ -1362,24 +1404,20 @@ module Gitlab
'jobs:rspec:only variables invalid expression syntax')
end
- it 'returns errors if extended hash configuration is invalid' do
- config = YAML.dump({ rspec: { extends: 'something', script: 'test' } })
+ it 'returns errors if pipeline changes policy is invalid' do
+ config = YAML.dump({ rspec: { script: 'test', only: { changes: [1] } } })
expect { Gitlab::Ci::YamlProcessor.new(config) }
.to raise_error(Gitlab::Ci::YamlProcessor::ValidationError,
- 'rspec: unknown key in `extends`')
+ 'jobs:rspec:only changes should be an array of strings')
end
- end
-
- describe "Validate configuration templates" do
- templates = Dir.glob("#{Rails.root.join('vendor/gitlab-ci-yml')}/**/*.gitlab-ci.yml")
- templates.each do |file|
- it "does not return errors for #{file}" do
- file = File.read(file)
+ it 'returns errors if extended hash configuration is invalid' do
+ config = YAML.dump({ rspec: { extends: 'something', script: 'test' } })
- expect { Gitlab::Ci::YamlProcessor.new(file) }.not_to raise_error
- end
+ expect { Gitlab::Ci::YamlProcessor.new(config) }
+ .to raise_error(Gitlab::Ci::YamlProcessor::ValidationError,
+ 'rspec: unknown key in `extends`')
end
end
diff --git a/spec/lib/gitlab/config/entry/attributable_spec.rb b/spec/lib/gitlab/config/entry/attributable_spec.rb
new file mode 100644
index 00000000000..abb4fff3ad7
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/attributable_spec.rb
@@ -0,0 +1,60 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Attributable do
+ let(:node) do
+ Class.new do
+ include Gitlab::Config::Entry::Attributable
+ end
+ end
+
+ let(:instance) { node.new }
+
+ before do
+ node.class_eval do
+ attributes :name, :test
+ end
+ end
+
+ context 'when config is a hash' do
+ before do
+ allow(instance)
+ .to receive(:config)
+ .and_return({ name: 'some name', test: 'some test' })
+ end
+
+ it 'returns the value of config' do
+ expect(instance.name).to eq 'some name'
+ expect(instance.test).to eq 'some test'
+ end
+
+ it 'returns no method error for unknown attributes' do
+ expect { instance.unknown }.to raise_error(NoMethodError)
+ end
+ end
+
+ context 'when config is not a hash' do
+ before do
+ allow(instance)
+ .to receive(:config)
+ .and_return('some test')
+ end
+
+ it 'returns nil' do
+ expect(instance.test).to be_nil
+ end
+ end
+
+ context 'when method is already defined in a superclass' do
+ it 'raises an error' do
+ expectation = expect do
+ Class.new(String) do
+ include Gitlab::Config::Entry::Attributable
+
+ attributes :length
+ end
+ end
+
+ expectation.to raise_error(ArgumentError, 'Method already defined!')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/entry/boolean_spec.rb b/spec/lib/gitlab/config/entry/boolean_spec.rb
new file mode 100644
index 00000000000..1b7a3f850ec
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/boolean_spec.rb
@@ -0,0 +1,34 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Boolean do
+ let(:entry) { described_class.new(config) }
+
+ describe 'validations' do
+ context 'when entry config value is valid' do
+ let(:config) { false }
+
+ describe '#value' do
+ it 'returns key value' do
+ expect(entry.value).to eq false
+ end
+ end
+
+ describe '#valid?' do
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+ end
+
+ context 'when entry value is not valid' do
+ let(:config) { ['incorrect'] }
+
+ describe '#errors' do
+ it 'saves errors' do
+ expect(entry.errors)
+ .to include 'boolean config should be a boolean value'
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/entry/configurable_spec.rb b/spec/lib/gitlab/config/entry/configurable_spec.rb
new file mode 100644
index 00000000000..85a7cf1d241
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/configurable_spec.rb
@@ -0,0 +1,53 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Configurable do
+ let(:entry) do
+ Class.new(Gitlab::Config::Entry::Node) do
+ include Gitlab::Config::Entry::Configurable
+ end
+ end
+
+ describe 'validations' do
+ context 'when entry is a hash' do
+ let(:instance) { entry.new(key: 'value') }
+
+ it 'correctly validates an instance' do
+ expect(instance).to be_valid
+ end
+ end
+
+ context 'when entry is not a hash' do
+ let(:instance) { entry.new('ls') }
+
+ it 'invalidates the instance' do
+ expect(instance).not_to be_valid
+ end
+ end
+ end
+
+ describe 'configured entries' do
+ before do
+ entry.class_eval do
+ entry :object, Object, description: 'test object'
+ end
+ end
+
+ describe '.nodes' do
+ it 'has valid nodes' do
+ expect(entry.nodes).to include :object
+ end
+
+ it 'creates a node factory' do
+ expect(entry.nodes[:object])
+ .to be_an_instance_of Gitlab::Config::Entry::Factory
+ end
+
+ it 'returns a duplicated factory object' do
+ first_factory = entry.nodes[:object]
+ second_factory = entry.nodes[:object]
+
+ expect(first_factory).not_to be_equal(second_factory)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/entry/factory_spec.rb b/spec/lib/gitlab/config/entry/factory_spec.rb
new file mode 100644
index 00000000000..c29d17eaee3
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/factory_spec.rb
@@ -0,0 +1,95 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Factory do
+ describe '#create!' do
+ class Script < Gitlab::Config::Entry::Node
+ include Gitlab::Config::Entry::Validatable
+
+ validations do
+ validates :config, array_of_strings: true
+ end
+ end
+
+ let(:entry) { Script }
+ let(:factory) { described_class.new(entry) }
+
+ context 'when setting a concrete value' do
+ it 'creates entry with valid value' do
+ entry = factory
+ .value(%w(ls pwd))
+ .create!
+
+ expect(entry.value).to eq %w(ls pwd)
+ end
+
+ context 'when setting description' do
+ it 'creates entry with description' do
+ entry = factory
+ .value(%w(ls pwd))
+ .with(description: 'test description')
+ .create!
+
+ expect(entry.value).to eq %w(ls pwd)
+ expect(entry.description).to eq 'test description'
+ end
+ end
+
+ context 'when setting key' do
+ it 'creates entry with custom key' do
+ entry = factory
+ .value(%w(ls pwd))
+ .with(key: 'test key')
+ .create!
+
+ expect(entry.key).to eq 'test key'
+ end
+ end
+
+ context 'when setting a parent' do
+ let(:object) { Object.new }
+
+ it 'creates entry with valid parent' do
+ entry = factory
+ .value('ls')
+ .with(parent: object)
+ .create!
+
+ expect(entry.parent).to eq object
+ end
+ end
+ end
+
+ context 'when not setting a value' do
+ it 'raises error' do
+ expect { factory.create! }.to raise_error(
+ Gitlab::Config::Entry::Factory::InvalidFactory
+ )
+ end
+ end
+
+ context 'when creating entry with nil value' do
+ it 'creates an unspecified entry' do
+ entry = factory
+ .value(nil)
+ .create!
+
+ expect(entry)
+ .not_to be_specified
+ end
+ end
+
+ context 'when passing metadata' do
+ let(:entry) { spy('entry') }
+
+ it 'passes metadata as a parameter' do
+ factory
+ .value('some value')
+ .metadata(some: 'hash')
+ .create!
+
+ expect(entry).to have_received(:new)
+ .with('some value', { some: 'hash' })
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/entry/simplifiable_spec.rb b/spec/lib/gitlab/config/entry/simplifiable_spec.rb
new file mode 100644
index 00000000000..bc8387ada67
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/simplifiable_spec.rb
@@ -0,0 +1,88 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Simplifiable do
+ describe '.strategy' do
+ let(:entry) do
+ Class.new(described_class) do
+ strategy :Something, if: -> { 'condition' }
+ strategy :DifferentOne, if: -> { 'condition' }
+ end
+ end
+
+ it 'defines entry strategies' do
+ expect(entry.strategies.size).to eq 2
+ expect(entry.strategies.map(&:name))
+ .to eq %i[Something DifferentOne]
+ end
+ end
+
+ describe 'setting strategy by a condition' do
+ let(:first) { double('first strategy') }
+ let(:second) { double('second strategy') }
+ let(:unknown) { double('unknown strategy') }
+
+ before do
+ stub_const("#{described_class.name}::Something", first)
+ stub_const("#{described_class.name}::DifferentOne", second)
+ stub_const("#{described_class.name}::UnknownStrategy", unknown)
+ end
+
+ context 'when first strategy should be used' do
+ let(:entry) do
+ Class.new(described_class) do
+ strategy :Something, if: -> (arg) { arg == 'something' }
+ strategy :DifferentOne, if: -> (*) { false }
+ end
+ end
+
+ it 'attemps to load a first strategy' do
+ expect(first).to receive(:new).with('something', anything)
+
+ entry.new('something')
+ end
+ end
+
+ context 'when second strategy should be used' do
+ let(:entry) do
+ Class.new(described_class) do
+ strategy :Something, if: -> (arg) { arg == 'something' }
+ strategy :DifferentOne, if: -> (arg) { arg == 'test' }
+ end
+ end
+
+ it 'attemps to load a second strategy' do
+ expect(second).to receive(:new).with('test', anything)
+
+ entry.new('test')
+ end
+ end
+
+ context 'when neither one is a valid strategy' do
+ let(:entry) do
+ Class.new(described_class) do
+ strategy :Something, if: -> (*) { false }
+ strategy :DifferentOne, if: -> (*) { false }
+ end
+ end
+
+ it 'instantiates an unknown strategy' do
+ expect(unknown).to receive(:new).with('test', anything)
+
+ entry.new('test')
+ end
+ end
+ end
+
+ context 'when a unknown strategy class is not defined' do
+ let(:entry) do
+ Class.new(described_class) do
+ strategy :String, if: -> (*) { true }
+ end
+ end
+
+ it 'raises an error when being initialized' do
+ expect { entry.new('something') }
+ .to raise_error ArgumentError, /UndefinedStrategy not available!/
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/entry/undefined_spec.rb b/spec/lib/gitlab/config/entry/undefined_spec.rb
new file mode 100644
index 00000000000..48f9d276c95
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/undefined_spec.rb
@@ -0,0 +1,41 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Undefined do
+ let(:entry) { described_class.new }
+
+ describe '#leaf?' do
+ it 'is leaf node' do
+ expect(entry).to be_leaf
+ end
+ end
+
+ describe '#valid?' do
+ it 'is always valid' do
+ expect(entry).to be_valid
+ end
+ end
+
+ describe '#errors' do
+ it 'is does not contain errors' do
+ expect(entry.errors).to be_empty
+ end
+ end
+
+ describe '#value' do
+ it 'returns nil' do
+ expect(entry.value).to eq nil
+ end
+ end
+
+ describe '#relevant?' do
+ it 'is not relevant' do
+ expect(entry.relevant?).to eq false
+ end
+ end
+
+ describe '#specified?' do
+ it 'is not defined' do
+ expect(entry.specified?).to eq false
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/entry/unspecified_spec.rb b/spec/lib/gitlab/config/entry/unspecified_spec.rb
new file mode 100644
index 00000000000..64421824a12
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/unspecified_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Unspecified do
+ let(:unspecified) { described_class.new(entry) }
+ let(:entry) { spy('Entry') }
+
+ describe '#valid?' do
+ it 'delegates method to entry' do
+ expect(unspecified.valid?).to eq entry
+ end
+ end
+
+ describe '#errors' do
+ it 'delegates method to entry' do
+ expect(unspecified.errors).to eq entry
+ end
+ end
+
+ describe '#value' do
+ it 'delegates method to entry' do
+ expect(unspecified.value).to eq entry
+ end
+ end
+
+ describe '#specified?' do
+ it 'is always false' do
+ allow(entry).to receive(:specified?).and_return(true)
+
+ expect(unspecified.specified?).to be false
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/entry/validatable_spec.rb b/spec/lib/gitlab/config/entry/validatable_spec.rb
new file mode 100644
index 00000000000..5a8f9766d23
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/validatable_spec.rb
@@ -0,0 +1,54 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Validatable do
+ let(:entry) do
+ Class.new(Gitlab::Config::Entry::Node) do
+ include Gitlab::Config::Entry::Validatable
+ end
+ end
+
+ describe '.validator' do
+ before do
+ entry.class_eval do
+ attr_accessor :test_attribute
+
+ validations do
+ validates :test_attribute, presence: true
+ end
+ end
+ end
+
+ it 'returns validator' do
+ expect(entry.validator.superclass)
+ .to be Gitlab::Config::Entry::Validator
+ end
+
+ it 'returns only one validator to mitigate leaks' do
+ expect { entry.validator }.not_to change { entry.validator }
+ end
+
+ context 'when validating entry instance' do
+ let(:entry_instance) { entry.new('something') }
+
+ context 'when attribute is valid' do
+ before do
+ entry_instance.test_attribute = 'valid'
+ end
+
+ it 'instance of validator is valid' do
+ expect(entry.validator.new(entry_instance)).to be_valid
+ end
+ end
+
+ context 'when attribute is not valid' do
+ before do
+ entry_instance.test_attribute = nil
+ end
+
+ it 'instance of validator is invalid' do
+ expect(entry.validator.new(entry_instance)).to be_invalid
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/entry/validator_spec.rb b/spec/lib/gitlab/config/entry/validator_spec.rb
new file mode 100644
index 00000000000..efa16c4265c
--- /dev/null
+++ b/spec/lib/gitlab/config/entry/validator_spec.rb
@@ -0,0 +1,55 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Entry::Validator do
+ let(:validator) { Class.new(described_class) }
+ let(:validator_instance) { validator.new(node) }
+ let(:node) { spy('node') }
+
+ before do
+ allow(node).to receive(:key).and_return('node')
+ allow(node).to receive(:ancestors).and_return([])
+ end
+
+ describe 'delegated validator' do
+ before do
+ validator.class_eval do
+ validates :test_attribute, presence: true
+ end
+ end
+
+ context 'when node is valid' do
+ before do
+ allow(node).to receive(:test_attribute).and_return('valid value')
+ end
+
+ it 'validates attribute in node' do
+ expect(node).to receive(:test_attribute)
+ expect(validator_instance).to be_valid
+ end
+
+ it 'returns no errors' do
+ validator_instance.validate
+
+ expect(validator_instance.messages).to be_empty
+ end
+ end
+
+ context 'when node is invalid' do
+ before do
+ allow(node).to receive(:test_attribute).and_return(nil)
+ end
+
+ it 'validates attribute in node' do
+ expect(node).to receive(:test_attribute)
+ expect(validator_instance).to be_invalid
+ end
+
+ it 'returns errors' do
+ validator_instance.validate
+
+ expect(validator_instance.messages)
+ .to include /test attribute can't be blank/
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/config/loader/yaml_spec.rb b/spec/lib/gitlab/config/loader/yaml_spec.rb
new file mode 100644
index 00000000000..44c9a3896a8
--- /dev/null
+++ b/spec/lib/gitlab/config/loader/yaml_spec.rb
@@ -0,0 +1,60 @@
+require 'spec_helper'
+
+describe Gitlab::Config::Loader::Yaml do
+ let(:loader) { described_class.new(yml) }
+
+ context 'when yaml syntax is correct' do
+ let(:yml) { 'image: ruby:2.2' }
+
+ describe '#valid?' do
+ it 'returns true' do
+ expect(loader.valid?).to be true
+ end
+ end
+
+ describe '#load!' do
+ it 'returns a valid hash' do
+ expect(loader.load!).to eq(image: 'ruby:2.2')
+ end
+ end
+ end
+
+ context 'when yaml syntax is incorrect' do
+ let(:yml) { '// incorrect' }
+
+ describe '#valid?' do
+ it 'returns false' do
+ expect(loader.valid?).to be false
+ end
+ end
+
+ describe '#load!' do
+ it 'raises error' do
+ expect { loader.load! }.to raise_error(
+ Gitlab::Config::Loader::FormatError,
+ 'Invalid configuration format'
+ )
+ end
+ end
+ end
+
+ context 'when there is an unknown alias' do
+ let(:yml) { 'steps: *bad_alias' }
+
+ describe '#initialize' do
+ it 'raises FormatError' do
+ expect { loader }.to raise_error(Gitlab::Config::Loader::FormatError, 'Unknown alias: bad_alias')
+ end
+ end
+ end
+
+ context 'when yaml config is empty' do
+ let(:yml) { '' }
+
+ describe '#valid?' do
+ it 'returns false' do
+ expect(loader.valid?).to be false
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/conflict/file_spec.rb b/spec/lib/gitlab/conflict/file_spec.rb
index 9095ffbfd52..a955ce54e85 100644
--- a/spec/lib/gitlab/conflict/file_spec.rb
+++ b/spec/lib/gitlab/conflict/file_spec.rb
@@ -1,9 +1,11 @@
require 'spec_helper'
describe Gitlab::Conflict::File do
+ include GitHelpers
+
let(:project) { create(:project, :repository) }
let(:repository) { project.repository }
- let(:rugged) { Gitlab::GitalyClient::StorageSettings.allow_disk_access { repository.rugged } }
+ let(:rugged) { rugged_repo(repository) }
let(:their_commit) { rugged.branches['conflict-start'].target }
let(:our_commit) { rugged.branches['conflict-resolvable'].target }
let(:merge_request) { create(:merge_request, source_branch: 'conflict-resolvable', target_branch: 'conflict-start', source_project: project) }
@@ -265,11 +267,6 @@ FILE
it 'includes the full content of the conflict' do
expect(conflict_file.as_json(full_content: true)).to have_key(:content)
end
-
- it 'includes the detected language of the conflict file' do
- expect(conflict_file.as_json(full_content: true)[:blob_ace_mode])
- .to eq('ruby')
- end
end
end
end
diff --git a/spec/lib/gitlab/contributions_calendar_spec.rb b/spec/lib/gitlab/contributions_calendar_spec.rb
index 6d29044ffd5..b7924302014 100644
--- a/spec/lib/gitlab/contributions_calendar_spec.rb
+++ b/spec/lib/gitlab/contributions_calendar_spec.rb
@@ -135,7 +135,7 @@ describe Gitlab::ContributionsCalendar do
expect(calendar(contributor).events_by_date(today)).to contain_exactly(e1, e2, e3)
end
- context 'when the user cannot read read cross project' do
+ context 'when the user cannot read cross project' do
before do
allow(Ability).to receive(:allowed?).and_call_original
expect(Ability).to receive(:allowed?).with(user, :read_cross_project) { false }
diff --git a/spec/lib/gitlab/cross_project_access/check_info_spec.rb b/spec/lib/gitlab/cross_project_access/check_info_spec.rb
index bc9dbf2bece..ea7393a7006 100644
--- a/spec/lib/gitlab/cross_project_access/check_info_spec.rb
+++ b/spec/lib/gitlab/cross_project_access/check_info_spec.rb
@@ -50,7 +50,7 @@ describe Gitlab::CrossProjectAccess::CheckInfo do
expect(info.should_run?(dummy_controller)).to be_truthy
end
- it 'returns the the oposite of #should_skip? when the check is a skip' do
+ it 'returns the opposite of #should_skip? when the check is a skip' do
info = described_class.new({}, nil, nil, true)
expect(info).to receive(:should_skip?).with(dummy_controller).and_return(false)
@@ -101,7 +101,7 @@ describe Gitlab::CrossProjectAccess::CheckInfo do
expect(info.should_skip?(dummy_controller)).to be_truthy
end
- it 'returns the the oposite of #should_run? when the check is not a skip' do
+ it 'returns the opposite of #should_run? when the check is not a skip' do
info = described_class.new({}, nil, nil, false)
expect(info).to receive(:should_run?).with(dummy_controller).and_return(false)
diff --git a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
index 2e67c1c7f78..f8009709ce2 100644
--- a/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
@@ -44,15 +44,15 @@ describe Gitlab::CycleAnalytics::StageSummary do
describe "#deploys" do
it "finds the number of deploys made created after the 'from date'" do
- Timecop.freeze(5.days.ago) { create(:deployment, project: project) }
- Timecop.freeze(5.days.from_now) { create(:deployment, project: project) }
+ Timecop.freeze(5.days.ago) { create(:deployment, :success, project: project) }
+ Timecop.freeze(5.days.from_now) { create(:deployment, :success, project: project) }
expect(subject.third[:value]).to eq(1)
end
it "doesn't find commits from other projects" do
Timecop.freeze(5.days.from_now) do
- create(:deployment, project: create(:project, :repository))
+ create(:deployment, :success, project: create(:project, :repository))
end
expect(subject.third[:value]).to eq(0)
diff --git a/spec/lib/gitlab/data_builder/pipeline_spec.rb b/spec/lib/gitlab/data_builder/pipeline_spec.rb
index 9ca960502c8..98f1696badb 100644
--- a/spec/lib/gitlab/data_builder/pipeline_spec.rb
+++ b/spec/lib/gitlab/data_builder/pipeline_spec.rb
@@ -6,10 +6,10 @@ describe Gitlab::DataBuilder::Pipeline do
let(:pipeline) do
create(:ci_pipeline,
- project: project,
- status: 'success',
- sha: project.commit.sha,
- ref: project.default_branch)
+ project: project,
+ status: 'success',
+ sha: project.commit.sha,
+ ref: project.default_branch)
end
let!(:build) { create(:ci_build, pipeline: pipeline) }
@@ -20,18 +20,35 @@ describe Gitlab::DataBuilder::Pipeline do
let(:build_data) { data[:builds].first }
let(:project_data) { data[:project] }
- it { expect(attributes).to be_a(Hash) }
- it { expect(attributes[:ref]).to eq(pipeline.ref) }
- it { expect(attributes[:sha]).to eq(pipeline.sha) }
- it { expect(attributes[:tag]).to eq(pipeline.tag) }
- it { expect(attributes[:id]).to eq(pipeline.id) }
- it { expect(attributes[:status]).to eq(pipeline.status) }
- it { expect(attributes[:detailed_status]).to eq('passed') }
+ it 'has correct attributes' do
+ expect(attributes).to be_a(Hash)
+ expect(attributes[:ref]).to eq(pipeline.ref)
+ expect(attributes[:sha]).to eq(pipeline.sha)
+ expect(attributes[:tag]).to eq(pipeline.tag)
+ expect(attributes[:id]).to eq(pipeline.id)
+ expect(attributes[:status]).to eq(pipeline.status)
+ expect(attributes[:detailed_status]).to eq('passed')
+ expect(build_data).to be_a(Hash)
+ expect(build_data[:id]).to eq(build.id)
+ expect(build_data[:status]).to eq(build.status)
+ expect(project_data).to eq(project.hook_attrs(backward: false))
+ end
- it { expect(build_data).to be_a(Hash) }
- it { expect(build_data[:id]).to eq(build.id) }
- it { expect(build_data[:status]).to eq(build.status) }
+ context 'pipeline without variables' do
+ it 'has empty variables hash' do
+ expect(attributes[:variables]).to be_a(Array)
+ expect(attributes[:variables]).to be_empty()
+ end
+ end
- it { expect(project_data).to eq(project.hook_attrs(backward: false)) }
+ context 'pipeline with variables' do
+ let(:build) { create(:ci_build, pipeline: pipeline) }
+ let(:data) { described_class.build(pipeline) }
+ let(:attributes) { data[:object_attributes] }
+ let!(:pipeline_variable) { create(:ci_pipeline_variable, pipeline: pipeline, key: 'TRIGGER_KEY_1', value: 'TRIGGER_VALUE_1') }
+
+ it { expect(attributes[:variables]).to be_a(Array) }
+ it { expect(attributes[:variables]).to contain_exactly({ key: 'TRIGGER_KEY_1', value: 'TRIGGER_VALUE_1' }) }
+ end
end
end
diff --git a/spec/lib/gitlab/database/count/exact_count_strategy_spec.rb b/spec/lib/gitlab/database/count/exact_count_strategy_spec.rb
new file mode 100644
index 00000000000..f518bb3dc3e
--- /dev/null
+++ b/spec/lib/gitlab/database/count/exact_count_strategy_spec.rb
@@ -0,0 +1,34 @@
+require 'spec_helper'
+
+describe Gitlab::Database::Count::ExactCountStrategy do
+ before do
+ create_list(:project, 3)
+ create(:identity)
+ end
+
+ let(:models) { [Project, Identity] }
+
+ subject { described_class.new(models).count }
+
+ describe '#count' do
+ it 'counts all models' do
+ expect(models).to all(receive(:count).and_call_original)
+
+ expect(subject).to eq({ Project => 3, Identity => 1 })
+ end
+ end
+
+ describe '.enabled?' do
+ it 'is enabled for PostgreSQL' do
+ allow(Gitlab::Database).to receive(:postgresql?).and_return(true)
+
+ expect(described_class.enabled?).to be_truthy
+ end
+
+ it 'is enabled for MySQL' do
+ allow(Gitlab::Database).to receive(:postgresql?).and_return(false)
+
+ expect(described_class.enabled?).to be_truthy
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb b/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb
new file mode 100644
index 00000000000..b44e8c5a110
--- /dev/null
+++ b/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb
@@ -0,0 +1,48 @@
+require 'spec_helper'
+
+describe Gitlab::Database::Count::ReltuplesCountStrategy do
+ before do
+ create_list(:project, 3)
+ create(:identity)
+ end
+
+ let(:models) { [Project, Identity] }
+ subject { described_class.new(models).count }
+
+ describe '#count', :postgresql do
+ context 'when reltuples is up to date' do
+ before do
+ ActiveRecord::Base.connection.execute('ANALYZE projects')
+ ActiveRecord::Base.connection.execute('ANALYZE identities')
+ end
+
+ it 'uses statistics to do the count' do
+ models.each { |model| expect(model).not_to receive(:count) }
+
+ expect(subject).to eq({ Project => 3, Identity => 1 })
+ end
+ end
+
+ context 'insufficient permissions' do
+ it 'returns an empty hash' do
+ allow(ActiveRecord::Base).to receive(:transaction).and_raise(PG::InsufficientPrivilege)
+
+ expect(subject).to eq({})
+ end
+ end
+ end
+
+ describe '.enabled?' do
+ it 'is enabled for PostgreSQL' do
+ allow(Gitlab::Database).to receive(:postgresql?).and_return(true)
+
+ expect(described_class.enabled?).to be_truthy
+ end
+
+ it 'is disabled for MySQL' do
+ allow(Gitlab::Database).to receive(:postgresql?).and_return(false)
+
+ expect(described_class.enabled?).to be_falsey
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb b/spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb
new file mode 100644
index 00000000000..203f9344a41
--- /dev/null
+++ b/spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb
@@ -0,0 +1,65 @@
+require 'spec_helper'
+
+describe Gitlab::Database::Count::TablesampleCountStrategy do
+ before do
+ create_list(:project, 3)
+ create(:identity)
+ end
+
+ let(:models) { [Project, Identity] }
+ let(:strategy) { described_class.new(models) }
+
+ subject { strategy.count }
+
+ describe '#count', :postgresql do
+ let(:estimates) { { Project => threshold + 1, Identity => threshold - 1 } }
+ let(:threshold) { Gitlab::Database::Count::TablesampleCountStrategy::EXACT_COUNT_THRESHOLD }
+
+ before do
+ allow(strategy).to receive(:size_estimates).with(check_statistics: false).and_return(estimates)
+ end
+
+ context 'for tables with an estimated small size' do
+ it 'performs an exact count' do
+ expect(Identity).to receive(:count).and_call_original
+
+ expect(subject).to include({ Identity => 1 })
+ end
+ end
+
+ context 'for tables with an estimated large size' do
+ it 'performs a tablesample count' do
+ expect(Project).not_to receive(:count)
+
+ result = subject
+ expect(result[Project]).to eq(3)
+ end
+ end
+
+ context 'insufficient permissions' do
+ it 'returns an empty hash' do
+ allow(strategy).to receive(:size_estimates).and_raise(PG::InsufficientPrivilege)
+
+ expect(subject).to eq({})
+ end
+ end
+ end
+
+ describe '.enabled?' do
+ before do
+ stub_feature_flags(tablesample_counts: true)
+ end
+
+ it 'is enabled for PostgreSQL' do
+ allow(Gitlab::Database).to receive(:postgresql?).and_return(true)
+
+ expect(described_class.enabled?).to be_truthy
+ end
+
+ it 'is disabled for MySQL' do
+ allow(Gitlab::Database).to receive(:postgresql?).and_return(false)
+
+ expect(described_class.enabled?).to be_falsey
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/count_spec.rb b/spec/lib/gitlab/database/count_spec.rb
index 407d9470785..1d096b8fa7c 100644
--- a/spec/lib/gitlab/database/count_spec.rb
+++ b/spec/lib/gitlab/database/count_spec.rb
@@ -8,63 +8,51 @@ describe Gitlab::Database::Count do
let(:models) { [Project, Identity] }
- describe '.approximate_counts' do
- context 'with MySQL' do
- context 'when reltuples have not been updated' do
- it 'counts all models the normal way' do
- expect(Gitlab::Database).to receive(:postgresql?).and_return(false)
+ context '.approximate_counts' do
+ context 'selecting strategies' do
+ let(:strategies) { [double('s1', enabled?: true), double('s2', enabled?: false)] }
- expect(Project).to receive(:count).and_call_original
- expect(Identity).to receive(:count).and_call_original
+ it 'uses only enabled strategies' do
+ expect(strategies[0]).to receive(:new).and_return(double('strategy1', count: {}))
+ expect(strategies[1]).not_to receive(:new)
- expect(described_class.approximate_counts(models)).to eq({ Project => 3, Identity => 1 })
- end
+ described_class.approximate_counts(models, strategies: strategies)
end
end
- context 'with PostgreSQL', :postgresql do
- describe 'when reltuples have not been updated' do
- it 'counts all models the normal way' do
- expect(described_class).to receive(:reltuples_from_recently_updated).with(%w(projects identities)).and_return({})
+ context 'fallbacks' do
+ subject { described_class.approximate_counts(models, strategies: strategies) }
- expect(Project).to receive(:count).and_call_original
- expect(Identity).to receive(:count).and_call_original
- expect(described_class.approximate_counts(models)).to eq({ Project => 3, Identity => 1 })
- end
+ let(:strategies) do
+ [
+ double('s1', enabled?: true, new: first_strategy),
+ double('s2', enabled?: true, new: second_strategy)
+ ]
end
- describe 'no permission' do
- it 'falls back to standard query' do
- allow(described_class).to receive(:postgresql_estimate_query).and_raise(PG::InsufficientPrivilege)
+ let(:first_strategy) { double('first strategy', count: {}) }
+ let(:second_strategy) { double('second strategy', count: {}) }
- expect(Project).to receive(:count).and_call_original
- expect(Identity).to receive(:count).and_call_original
- expect(described_class.approximate_counts(models)).to eq({ Project => 3, Identity => 1 })
- end
+ it 'gets results from first strategy' do
+ expect(strategies[0]).to receive(:new).with(models).and_return(first_strategy)
+ expect(first_strategy).to receive(:count)
+
+ subject
end
- describe 'when some reltuples have been updated' do
- it 'counts projects in the fast way' do
- expect(described_class).to receive(:reltuples_from_recently_updated).with(%w(projects identities)).and_return({ 'projects' => 3 })
+ it 'gets more results from second strategy if some counts are missing' do
+ expect(first_strategy).to receive(:count).and_return({ Project => 3 })
+ expect(strategies[1]).to receive(:new).with([Identity]).and_return(second_strategy)
+ expect(second_strategy).to receive(:count).and_return({ Identity => 1 })
- expect(Project).not_to receive(:count).and_call_original
- expect(Identity).to receive(:count).and_call_original
- expect(described_class.approximate_counts(models)).to eq({ Project => 3, Identity => 1 })
- end
+ expect(subject).to eq({ Project => 3, Identity => 1 })
end
- describe 'when all reltuples have been updated' do
- before do
- ActiveRecord::Base.connection.execute('ANALYZE projects')
- ActiveRecord::Base.connection.execute('ANALYZE identities')
- end
-
- it 'counts models with the standard way' do
- expect(Project).not_to receive(:count)
- expect(Identity).not_to receive(:count)
+ it 'does not get more results as soon as all counts are present' do
+ expect(first_strategy).to receive(:count).and_return({ Project => 3, Identity => 1 })
+ expect(strategies[1]).not_to receive(:new)
- expect(described_class.approximate_counts(models)).to eq({ Project => 3, Identity => 1 })
- end
+ subject
end
end
end
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index 4e83b27e4a5..23f27939dd2 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -1338,7 +1338,12 @@ describe Gitlab::Database::MigrationHelpers do
end
describe '#index_exists_by_name?' do
- it 'returns true if an index exists' do
+ # TODO: remove rails5-only after removing rails4 tests
+ # rails 4 can not handle multiple indexes on the same column set if
+ # index was added by 't.index' - t.index is used by default in schema.rb in
+ # rails 5. Let's run this test only in rails 5 env:
+ # see https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21492#note_113602758
+ it 'returns true if an index exists', :rails5 do
expect(model.index_exists_by_name?(:projects, 'index_projects_on_path'))
.to be_truthy
end
diff --git a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb
index cc7cb3f23fd..248cca25a2c 100644
--- a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb
+++ b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_base_spec.rb
@@ -20,7 +20,7 @@ describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameBase, :delete
end
describe "#remove_last_ocurrence" do
- it "removes only the last occurance of a string" do
+ it "removes only the last occurrence of a string" do
input = "this/is/a-word-to-replace/namespace/with/a-word-to-replace"
expect(subject.remove_last_occurrence(input, "a-word-to-replace"))
diff --git a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb
index 0a8c77b0ad9..b6096d4faf6 100644
--- a/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb
+++ b/spec/lib/gitlab/database/rename_reserved_paths_migration/v1/rename_namespaces_spec.rb
@@ -165,7 +165,7 @@ describe Gitlab::Database::RenameReservedPathsMigration::V1::RenameNamespaces, :
end
describe '#rename_namespace_dependencies' do
- it "moves the the repository for a project in the namespace" do
+ it "moves the repository for a project in the namespace" do
create(:project, :repository, :legacy_storage, namespace: namespace, path: "the-path-project")
expected_repo = File.join(TestEnv.repos_path, "the-path0", "the-path-project.git")
diff --git a/spec/lib/gitlab/database_spec.rb b/spec/lib/gitlab/database_spec.rb
index 7d76519dddd..fc295b2deff 100644
--- a/spec/lib/gitlab/database_spec.rb
+++ b/spec/lib/gitlab/database_spec.rb
@@ -443,11 +443,17 @@ describe Gitlab::Database do
end
end
+ describe '.read_only?' do
+ it 'returns false' do
+ expect(described_class.read_only?).to be_falsey
+ end
+ end
+
describe '.db_read_only?' do
context 'when using PostgreSQL' do
before do
allow(ActiveRecord::Base.connection).to receive(:execute).and_call_original
- expect(described_class).to receive(:postgresql?).and_return(true)
+ allow(described_class).to receive(:postgresql?).and_return(true)
end
it 'detects a read only database' do
@@ -456,11 +462,25 @@ describe Gitlab::Database do
expect(described_class.db_read_only?).to be_truthy
end
+ # TODO: remove rails5-only tag after removing rails4 tests
+ it 'detects a read only database', :rails5 do
+ allow(ActiveRecord::Base.connection).to receive(:execute).with('SELECT pg_is_in_recovery()').and_return([{ "pg_is_in_recovery" => true }])
+
+ expect(described_class.db_read_only?).to be_truthy
+ end
+
it 'detects a read write database' do
allow(ActiveRecord::Base.connection).to receive(:execute).with('SELECT pg_is_in_recovery()').and_return([{ "pg_is_in_recovery" => "f" }])
expect(described_class.db_read_only?).to be_falsey
end
+
+ # TODO: remove rails5-only tag after removing rails4 tests
+ it 'detects a read write database', :rails5 do
+ allow(ActiveRecord::Base.connection).to receive(:execute).with('SELECT pg_is_in_recovery()').and_return([{ "pg_is_in_recovery" => false }])
+
+ expect(described_class.db_read_only?).to be_falsey
+ end
end
context 'when using MySQL' do
diff --git a/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb b/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb
index 4578da70bfc..fbcf515281e 100644
--- a/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb
+++ b/spec/lib/gitlab/diff/file_collection/merge_request_diff_spec.rb
@@ -37,17 +37,7 @@ describe Gitlab::Diff::FileCollection::MergeRequestDiff do
let(:stub_path) { '.gitignore' }
end
- shared_examples 'initializes a DiffCollection' do
- it 'returns a valid instance of a DiffCollection' do
- expect(diff_files).to be_a(Gitlab::Git::DiffCollection)
- end
- end
-
- context 'with Gitaly disabled', :disable_gitaly do
- it_behaves_like 'initializes a DiffCollection'
- end
-
- context 'with Gitaly enabled' do
- it_behaves_like 'initializes a DiffCollection'
+ it 'returns a valid instance of a DiffCollection' do
+ expect(diff_files).to be_a(Gitlab::Git::DiffCollection)
end
end
diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb
index 2f51642b58e..3417896e259 100644
--- a/spec/lib/gitlab/diff/file_spec.rb
+++ b/spec/lib/gitlab/diff/file_spec.rb
@@ -41,6 +41,52 @@ describe Gitlab::Diff::File do
end
end
+ describe '#unfold_diff_lines' do
+ let(:unfolded_lines) { double('expanded-lines') }
+ let(:unfolder) { instance_double(Gitlab::Diff::LinesUnfolder) }
+ let(:position) { instance_double(Gitlab::Diff::Position, old_line: 10) }
+
+ before do
+ allow(Gitlab::Diff::LinesUnfolder).to receive(:new) { unfolder }
+ end
+
+ context 'when unfold required' do
+ before do
+ allow(unfolder).to receive(:unfold_required?) { true }
+ allow(unfolder).to receive(:unfolded_diff_lines) { unfolded_lines }
+ end
+
+ it 'changes @unfolded to true' do
+ diff_file.unfold_diff_lines(position)
+
+ expect(diff_file).to be_unfolded
+ end
+
+ it 'updates @diff_lines' do
+ diff_file.unfold_diff_lines(position)
+
+ expect(diff_file.diff_lines).to eq(unfolded_lines)
+ end
+ end
+
+ context 'when unfold not required' do
+ before do
+ allow(unfolder).to receive(:unfold_required?) { false }
+ end
+
+ it 'keeps @unfolded false' do
+ diff_file.unfold_diff_lines(position)
+
+ expect(diff_file).not_to be_unfolded
+ end
+
+ it 'does not update @diff_lines' do
+ expect { diff_file.unfold_diff_lines(position) }
+ .not_to change(diff_file, :diff_lines)
+ end
+ end
+ end
+
describe '#mode_changed?' do
it { expect(diff_file.mode_changed?).to be_falsey }
end
diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb
index 3c8cf9c56cc..5d0a603d11d 100644
--- a/spec/lib/gitlab/diff/highlight_spec.rb
+++ b/spec/lib/gitlab/diff/highlight_spec.rb
@@ -8,6 +8,20 @@ describe Gitlab::Diff::Highlight do
let(:diff) { commit.raw_diffs.first }
let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: commit.diff_refs, repository: project.repository) }
+ shared_examples 'without inline diffs' do
+ let(:code) { '<h2 onmouseover="alert(2)">Test</h2>' }
+
+ before do
+ allow(Gitlab::Diff::InlineDiff).to receive(:for_lines).and_return([])
+ allow_any_instance_of(Gitlab::Diff::Line).to receive(:text).and_return(code)
+ end
+
+ it 'returns html escaped diff text' do
+ expect(subject[1].rich_text).to eq html_escape(code)
+ expect(subject[1].rich_text).to be_html_safe
+ end
+ end
+
describe '#highlight' do
context "with a diff file" do
let(:subject) { described_class.new(diff_file, repository: project.repository).highlight }
@@ -38,6 +52,16 @@ describe Gitlab::Diff::Highlight do
expect(subject[5].rich_text).to eq(code)
end
+
+ context 'when no diff_refs' do
+ before do
+ allow(diff_file).to receive(:diff_refs).and_return(nil)
+ end
+
+ context 'when no inline diffs' do
+ it_behaves_like 'without inline diffs'
+ end
+ end
end
context "with diff lines" do
@@ -93,6 +117,10 @@ describe Gitlab::Diff::Highlight do
expect { subject }. to raise_exception(RangeError)
end
end
+
+ context 'when no inline diffs' do
+ it_behaves_like 'without inline diffs'
+ end
end
end
end
diff --git a/spec/lib/gitlab/diff/inline_diff_marker_spec.rb b/spec/lib/gitlab/diff/inline_diff_marker_spec.rb
index 7296bbf5df3..97e65318059 100644
--- a/spec/lib/gitlab/diff/inline_diff_marker_spec.rb
+++ b/spec/lib/gitlab/diff/inline_diff_marker_spec.rb
@@ -16,7 +16,7 @@ describe Gitlab::Diff::InlineDiffMarker do
end
end
- context "when the text text is not html safe" do
+ context "when the text is not html safe" do
let(:rich) { "abc 'def' differs" }
it 'marks the range' do
diff --git a/spec/lib/gitlab/diff/lines_unfolder_spec.rb b/spec/lib/gitlab/diff/lines_unfolder_spec.rb
new file mode 100644
index 00000000000..8e00c8e0e30
--- /dev/null
+++ b/spec/lib/gitlab/diff/lines_unfolder_spec.rb
@@ -0,0 +1,750 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Diff::LinesUnfolder do
+ let(:raw_diff) do
+ <<-DIFF.strip_heredoc
+ @@ -7,9 +7,6 @@
+ "tags": ["devel", "development", "nightly"],
+ "desktop-file-name-prefix": "(Development) ",
+ "finish-args": [
+ - "--share=ipc", "--socket=x11",
+ - "--socket=wayland",
+ - "--talk-name=org.gnome.OnlineAccounts",
+ "--talk-name=org.freedesktop.Tracker1",
+ "--filesystem=home",
+ "--talk-name=org.gtk.vfs", "--talk-name=org.gtk.vfs.*",
+ @@ -62,7 +59,7 @@
+ },
+ {
+ "name": "gnome-desktop",
+ - "config-opts": ["--disable-debug-tools", "--disable-udev"],
+ + "config-opts": ["--disable-debug-tools", "--disable-"],
+ "sources": [
+ {
+ "type": "git",
+ @@ -83,11 +80,6 @@
+ "buildsystem": "meson",
+ "builddir": true,
+ "name": "nautilus",
+ - "config-opts": [
+ - "-Denable-desktop=false",
+ - "-Denable-selinux=false",
+ - "--libdir=/app/lib"
+ - ],
+ "sources": [
+ {
+ "type": "git",
+ DIFF
+ end
+
+ let(:raw_old_blob) do
+ <<-BLOB.strip_heredoc
+ {
+ "app-id": "org.gnome.Nautilus",
+ "runtime": "org.gnome.Platform",
+ "runtime-version": "master",
+ "sdk": "org.gnome.Sdk",
+ "command": "nautilus",
+ "tags": ["devel", "development", "nightly"],
+ "desktop-file-name-prefix": "(Development) ",
+ "finish-args": [
+ "--share=ipc", "--socket=x11",
+ "--socket=wayland",
+ "--talk-name=org.gnome.OnlineAccounts",
+ "--talk-name=org.freedesktop.Tracker1",
+ "--filesystem=home",
+ "--talk-name=org.gtk.vfs", "--talk-name=org.gtk.vfs.*",
+ "--filesystem=xdg-run/dconf", "--filesystem=~/.config/dconf:ro",
+ "--talk-name=ca.desrt.dconf", "--env=DCONF_USER_CONFIG_DIR=.config/dconf"
+ ],
+ "cleanup": [ "/include", "/share/bash-completion" ],
+ "modules": [
+ {
+ "name": "exiv2",
+ "sources": [
+ {
+ "type": "archive",
+ "url": "http://exiv2.org/builds/exiv2-0.26-trunk.tar.gz",
+ "sha256": "c75e3c4a0811bf700d92c82319373b7a825a2331c12b8b37d41eb58e4f18eafb"
+ },
+ {
+ "type": "shell",
+ "commands": [
+ "cp -f /usr/share/gnu-config/config.sub ./config/",
+ "cp -f /usr/share/gnu-config/config.guess ./config/"
+ ]
+ }
+ ]
+ },
+ {
+ "name": "gexiv2",
+ "config-opts": [ "--disable-introspection" ],
+ "sources": [
+ {
+ "type": "git",
+ "url": "https://git.gnome.org/browse/gexiv2"
+ }
+ ]
+ },
+ {
+ "name": "tracker",
+ "cleanup": [ "/bin", "/etc", "/libexec" ],
+ "config-opts": [ "--disable-miner-apps", "--disable-static",
+ "--disable-tracker-extract", "--disable-tracker-needle",
+ "--disable-tracker-preferences", "--disable-artwork",
+ "--disable-tracker-writeback", "--disable-miner-user-guides",
+ "--with-bash-completion-dir=no" ],
+ "sources": [
+ {
+ "type": "git",
+ "url": "https://git.gnome.org/browse/tracker"
+ }
+ ]
+ },
+ {
+ "name": "gnome-desktop",
+ "config-opts": ["--disable-debug-tools", "--disable-udev"],
+ "sources": [
+ {
+ "type": "git",
+ "url": "https://git.gnome.org/browse/gnome-desktop"
+ }
+ ]
+ },
+ {
+ "name": "gnome-autoar",
+ "sources": [
+ {
+ "type": "git",
+ "url": "https://git.gnome.org/browse/gnome-autoar"
+ }
+ ]
+ },
+ {
+ "buildsystem": "meson",
+ "builddir": true,
+ "name": "nautilus",
+ "config-opts": [
+ "-Denable-desktop=false",
+ "-Denable-selinux=false",
+ "--libdir=/app/lib"
+ ],
+ "sources": [
+ {
+ "type": "git",
+ "url": "https://gitlab.gnome.org/GNOME/nautilus.git"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "app-id": "foo",
+ "runtime": "foo",
+ "runtime-version": "foo",
+ "sdk": "foo",
+ "command": "foo",
+ "tags": ["foo", "bar", "kux"],
+ "desktop-file-name-prefix": "(Foo) ",
+ {
+ "buildsystem": "meson",
+ "builddir": true,
+ "name": "nautilus",
+ "sources": [
+ {
+ "type": "git",
+ "url": "https://gitlab.gnome.org/GNOME/nautilus.git"
+ }
+ ]
+ }
+ },
+ {
+ "app-id": "foo",
+ "runtime": "foo",
+ "runtime-version": "foo",
+ "sdk": "foo",
+ "command": "foo",
+ "tags": ["foo", "bar", "kux"],
+ "desktop-file-name-prefix": "(Foo) ",
+ {
+ "buildsystem": "meson",
+ "builddir": true,
+ "name": "nautilus",
+ "sources": [
+ {
+ "type": "git",
+ "url": "https://gitlab.gnome.org/GNOME/nautilus.git"
+ }
+ ]
+ }
+ }
+ BLOB
+ end
+
+ let(:project) { create(:project) }
+
+ let(:old_blob) { Gitlab::Git::Blob.new(data: raw_old_blob) }
+
+ let(:diff) do
+ Gitlab::Git::Diff.new(diff: raw_diff,
+ new_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ old_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ a_mode: "100644",
+ b_mode: "100644",
+ new_file: false,
+ renamed_file: false,
+ deleted_file: false,
+ too_large: false)
+ end
+
+ let(:diff_file) do
+ Gitlab::Diff::File.new(diff, repository: project.repository)
+ end
+
+ before do
+ allow(old_blob).to receive(:load_all_data!)
+ allow(diff_file).to receive(:old_blob) { old_blob }
+ end
+
+ subject { described_class.new(diff_file, position) }
+
+ context 'position requires a middle expansion and new match lines' do
+ let(:position) do
+ Gitlab::Diff::Position.new(base_sha: "1c59dfa64afbea8c721bb09a06a9d326c952ea19",
+ start_sha: "1c59dfa64afbea8c721bb09a06a9d326c952ea19",
+ head_sha: "1487062132228de836236c522fe52fed4980a46c",
+ old_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ new_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ position_type: "text",
+ old_line: 43,
+ new_line: 40)
+ end
+
+ context 'blob lines' do
+ let(:expected_blob_lines) do
+ [[40, 40, " \"config-opts\": [ \"--disable-introspection\" ],"],
+ [41, 41, " \"sources\": ["],
+ [42, 42, " {"],
+ [43, 43, " \"type\": \"git\","],
+ [44, 44, " \"url\": \"https://git.gnome.org/browse/gexiv2\""],
+ [45, 45, " }"],
+ [46, 46, " ]"]]
+ end
+
+ it 'returns the extracted blob lines correctly' do
+ extracted_lines = subject.blob_lines
+
+ expect(extracted_lines.size).to eq(7)
+
+ extracted_lines.each_with_index do |line, i|
+ expect([line.old_line, line.new_line, line.text]).to eq(expected_blob_lines[i])
+ end
+ end
+ end
+
+ context 'diff lines' do
+ let(:expected_diff_lines) do
+ [[7, 7, "@@ -7,9 +7,6 @@"],
+ [7, 7, " \"tags\": [\"devel\", \"development\", \"nightly\"],"],
+ [8, 8, " \"desktop-file-name-prefix\": \"(Development) \","],
+ [9, 9, " \"finish-args\": ["],
+ [10, 10, "- \"--share=ipc\", \"--socket=x11\","],
+ [11, 10, "- \"--socket=wayland\","],
+ [12, 10, "- \"--talk-name=org.gnome.OnlineAccounts\","],
+ [13, 10, " \"--talk-name=org.freedesktop.Tracker1\","],
+ [14, 11, " \"--filesystem=home\","],
+ [15, 12, " \"--talk-name=org.gtk.vfs\", \"--talk-name=org.gtk.vfs.*\","],
+
+ # New match line
+ [40, 37, "@@ -40,7+37,7 @@"],
+
+ # Injected blob lines
+ [40, 37, " \"config-opts\": [ \"--disable-introspection\" ],"],
+ [41, 38, " \"sources\": ["],
+ [42, 39, " {"],
+ [43, 40, " \"type\": \"git\","], # comment
+ [44, 41, " \"url\": \"https://git.gnome.org/browse/gexiv2\""],
+ [45, 42, " }"],
+ [46, 43, " ]"],
+ # end
+
+ # Second match line
+ [62, 59, "@@ -62,7+59,7 @@"],
+
+ [62, 59, " },"],
+ [63, 60, " {"],
+ [64, 61, " \"name\": \"gnome-desktop\","],
+ [65, 62, "- \"config-opts\": [\"--disable-debug-tools\", \"--disable-udev\"],"],
+ [66, 62, "+ \"config-opts\": [\"--disable-debug-tools\", \"--disable-\"],"],
+ [66, 63, " \"sources\": ["],
+ [67, 64, " {"],
+ [68, 65, " \"type\": \"git\","],
+ [83, 80, "@@ -83,11 +80,6 @@"],
+ [83, 80, " \"buildsystem\": \"meson\","],
+ [84, 81, " \"builddir\": true,"],
+ [85, 82, " \"name\": \"nautilus\","],
+ [86, 83, "- \"config-opts\": ["],
+ [87, 83, "- \"-Denable-desktop=false\","],
+ [88, 83, "- \"-Denable-selinux=false\","],
+ [89, 83, "- \"--libdir=/app/lib\""],
+ [90, 83, "- ],"],
+ [91, 83, " \"sources\": ["],
+ [92, 84, " {"],
+ [93, 85, " \"type\": \"git\","]]
+ end
+
+ it 'return merge of blob lines with diff lines correctly' do
+ new_diff_lines = subject.unfolded_diff_lines
+
+ expected_diff_lines.each_with_index do |expected_line, i|
+ line = new_diff_lines[i]
+
+ expect([line.old_pos, line.new_pos, line.text])
+ .to eq([expected_line[0], expected_line[1], expected_line[2]])
+ end
+ end
+
+ it 'merged lines have correct line codes' do
+ new_diff_lines = subject.unfolded_diff_lines
+
+ new_diff_lines.each_with_index do |line, i|
+ old_pos, new_pos = expected_diff_lines[i][0], expected_diff_lines[i][1]
+
+ unless line.type == 'match'
+ expect(line.line_code).to eq(Gitlab::Git.diff_line_code(diff_file.file_path, new_pos, old_pos))
+ end
+ end
+ end
+ end
+ end
+
+ context 'position requires a middle expansion and no top match line' do
+ let(:position) do
+ Gitlab::Diff::Position.new(base_sha: "1c59dfa64afbea8c721bb09a06a9d326c952ea19",
+ start_sha: "1c59dfa64afbea8c721bb09a06a9d326c952ea19",
+ head_sha: "1487062132228de836236c522fe52fed4980a46c",
+ old_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ new_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ position_type: "text",
+ old_line: 16,
+ new_line: 17)
+ end
+
+ context 'blob lines' do
+ let(:expected_blob_lines) do
+ [[16, 16, " \"--filesystem=xdg-run/dconf\", \"--filesystem=~/.config/dconf:ro\","],
+ [17, 17, " \"--talk-name=ca.desrt.dconf\", \"--env=DCONF_USER_CONFIG_DIR=.config/dconf\""],
+ [18, 18, " ],"],
+ [19, 19, " \"cleanup\": [ \"/include\", \"/share/bash-completion\" ],"]]
+ end
+
+ it 'returns the extracted blob lines correctly' do
+ extracted_lines = subject.blob_lines
+
+ expect(extracted_lines.size).to eq(4)
+
+ extracted_lines.each_with_index do |line, i|
+ expect([line.old_line, line.new_line, line.text]).to eq(expected_blob_lines[i])
+ end
+ end
+ end
+
+ context 'diff lines' do
+ let(:expected_diff_lines) do
+ [[7, 7, "@@ -7,9 +7,6 @@"],
+ [7, 7, " \"tags\": [\"devel\", \"development\", \"nightly\"],"],
+ [8, 8, " \"desktop-file-name-prefix\": \"(Development) \","],
+ [9, 9, " \"finish-args\": ["],
+ [10, 10, "- \"--share=ipc\", \"--socket=x11\","],
+ [11, 10, "- \"--socket=wayland\","],
+ [12, 10, "- \"--talk-name=org.gnome.OnlineAccounts\","],
+ [13, 10, " \"--talk-name=org.freedesktop.Tracker1\","],
+ [14, 11, " \"--filesystem=home\","],
+ [15, 12, " \"--talk-name=org.gtk.vfs\", \"--talk-name=org.gtk.vfs.*\","],
+ # No new match needed
+
+ # Injected blob lines
+ [16, 13, " \"--filesystem=xdg-run/dconf\", \"--filesystem=~/.config/dconf:ro\","],
+ [17, 14, " \"--talk-name=ca.desrt.dconf\", \"--env=DCONF_USER_CONFIG_DIR=.config/dconf\""],
+ [18, 15, " ],"],
+ [19, 16, " \"cleanup\": [ \"/include\", \"/share/bash-completion\" ],"],
+ # end
+
+ # Second match line
+ [62, 59, "@@ -62,4+59,4 @@"],
+
+ [62, 59, " },"],
+ [63, 60, " {"],
+ [64, 61, " \"name\": \"gnome-desktop\","],
+ [65, 62, "- \"config-opts\": [\"--disable-debug-tools\", \"--disable-udev\"],"],
+ [66, 62, "+ \"config-opts\": [\"--disable-debug-tools\", \"--disable-\"],"],
+ [66, 63, " \"sources\": ["],
+ [67, 64, " {"],
+ [68, 65, " \"type\": \"git\","],
+ [83, 80, "@@ -83,11 +80,6 @@"],
+ [83, 80, " \"buildsystem\": \"meson\","],
+ [84, 81, " \"builddir\": true,"],
+ [85, 82, " \"name\": \"nautilus\","],
+ [86, 83, "- \"config-opts\": ["],
+ [87, 83, "- \"-Denable-desktop=false\","],
+ [88, 83, "- \"-Denable-selinux=false\","],
+ [89, 83, "- \"--libdir=/app/lib\""],
+ [90, 83, "- ],"],
+ [91, 83, " \"sources\": ["],
+ [92, 84, " {"],
+ [93, 85, " \"type\": \"git\","]]
+ end
+
+ it 'return merge of blob lines with diff lines correctly' do
+ new_diff_lines = subject.unfolded_diff_lines
+
+ expected_diff_lines.each_with_index do |expected_line, i|
+ line = new_diff_lines[i]
+
+ expect([line.old_pos, line.new_pos, line.text])
+ .to eq([expected_line[0], expected_line[1], expected_line[2]])
+ end
+ end
+
+ it 'merged lines have correct line codes' do
+ new_diff_lines = subject.unfolded_diff_lines
+
+ new_diff_lines.each_with_index do |line, i|
+ old_pos, new_pos = expected_diff_lines[i][0], expected_diff_lines[i][1]
+
+ unless line.type == 'match'
+ expect(line.line_code).to eq(Gitlab::Git.diff_line_code(diff_file.file_path, new_pos, old_pos))
+ end
+ end
+ end
+ end
+ end
+
+ context 'position requires a middle expansion and no bottom match line' do
+ let(:position) do
+ Gitlab::Diff::Position.new(base_sha: "1c59dfa64afbea8c721bb09a06a9d326c952ea19",
+ start_sha: "1c59dfa64afbea8c721bb09a06a9d326c952ea19",
+ head_sha: "1487062132228de836236c522fe52fed4980a46c",
+ old_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ new_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ position_type: "text",
+ old_line: 82,
+ new_line: 79)
+ end
+
+ context 'blob lines' do
+ let(:expected_blob_lines) do
+ [[79, 79, " }"],
+ [80, 80, " ]"],
+ [81, 81, " },"],
+ [82, 82, " {"]]
+ end
+
+ it 'returns the extracted blob lines correctly' do
+ extracted_lines = subject.blob_lines
+
+ expect(extracted_lines.size).to eq(4)
+
+ extracted_lines.each_with_index do |line, i|
+ expect([line.old_line, line.new_line, line.text]).to eq(expected_blob_lines[i])
+ end
+ end
+ end
+
+ context 'diff lines' do
+ let(:expected_diff_lines) do
+ [[7, 7, "@@ -7,9 +7,6 @@"],
+ [7, 7, " \"tags\": [\"devel\", \"development\", \"nightly\"],"],
+ [8, 8, " \"desktop-file-name-prefix\": \"(Development) \","],
+ [9, 9, " \"finish-args\": ["],
+ [10, 10, "- \"--share=ipc\", \"--socket=x11\","],
+ [11, 10, "- \"--socket=wayland\","],
+ [12, 10, "- \"--talk-name=org.gnome.OnlineAccounts\","],
+ [13, 10, " \"--talk-name=org.freedesktop.Tracker1\","],
+ [14, 11, " \"--filesystem=home\","],
+ [15, 12, " \"--talk-name=org.gtk.vfs\", \"--talk-name=org.gtk.vfs.*\","],
+ [62, 59, "@@ -62,7 +59,7 @@"],
+ [62, 59, " },"],
+ [63, 60, " {"],
+ [64, 61, " \"name\": \"gnome-desktop\","],
+ [65, 62, "- \"config-opts\": [\"--disable-debug-tools\", \"--disable-udev\"],"],
+ [66, 62, "+ \"config-opts\": [\"--disable-debug-tools\", \"--disable-\"],"],
+ [66, 63, " \"sources\": ["],
+ [67, 64, " {"],
+ [68, 65, " \"type\": \"git\","],
+
+ # New top match line
+ [79, 76, "@@ -79,4+76,4 @@"],
+
+ # Injected blob lines
+ [79, 76, " }"],
+ [80, 77, " ]"],
+ [81, 78, " },"],
+ [82, 79, " {"],
+ # end
+
+ # No new second match line
+ [83, 80, " \"buildsystem\": \"meson\","],
+ [84, 81, " \"builddir\": true,"],
+ [85, 82, " \"name\": \"nautilus\","],
+ [86, 83, "- \"config-opts\": ["],
+ [87, 83, "- \"-Denable-desktop=false\","],
+ [88, 83, "- \"-Denable-selinux=false\","],
+ [89, 83, "- \"--libdir=/app/lib\""],
+ [90, 83, "- ],"],
+ [91, 83, " \"sources\": ["],
+ [92, 84, " {"],
+ [93, 85, " \"type\": \"git\","]]
+ end
+
+ it 'return merge of blob lines with diff lines correctly' do
+ new_diff_lines = subject.unfolded_diff_lines
+
+ expected_diff_lines.each_with_index do |expected_line, i|
+ line = new_diff_lines[i]
+
+ expect([line.old_pos, line.new_pos, line.text])
+ .to eq([expected_line[0], expected_line[1], expected_line[2]])
+ end
+ end
+
+ it 'merged lines have correct line codes' do
+ new_diff_lines = subject.unfolded_diff_lines
+
+ new_diff_lines.each_with_index do |line, i|
+ old_pos, new_pos = expected_diff_lines[i][0], expected_diff_lines[i][1]
+
+ unless line.type == 'match'
+ expect(line.line_code).to eq(Gitlab::Git.diff_line_code(diff_file.file_path, new_pos, old_pos))
+ end
+ end
+ end
+ end
+ end
+
+ context 'position requires a short top expansion' do
+ let(:position) do
+ Gitlab::Diff::Position.new(base_sha: "1c59dfa64afbea8c721bb09a06a9d326c952ea19",
+ start_sha: "1c59dfa64afbea8c721bb09a06a9d326c952ea19",
+ head_sha: "1487062132228de836236c522fe52fed4980a46c",
+ old_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ new_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ position_type: "text",
+ old_line: 6,
+ new_line: 6)
+ end
+
+ context 'blob lines' do
+ let(:expected_blob_lines) do
+ [[3, 3, " \"runtime\": \"org.gnome.Platform\","],
+ [4, 4, " \"runtime-version\": \"master\","],
+ [5, 5, " \"sdk\": \"org.gnome.Sdk\","],
+ [6, 6, " \"command\": \"nautilus\","]]
+ end
+
+ it 'returns the extracted blob lines correctly' do
+ extracted_lines = subject.blob_lines
+
+ expect(extracted_lines.size).to eq(4)
+
+ extracted_lines.each_with_index do |line, i|
+ expect([line.old_line, line.new_line, line.text]).to eq(expected_blob_lines[i])
+ end
+ end
+ end
+
+ context 'diff lines' do
+ let(:expected_diff_lines) do
+ # New match line
+ [[3, 3, "@@ -3,4+3,4 @@"],
+
+ # Injected blob lines
+ [3, 3, " \"runtime\": \"org.gnome.Platform\","],
+ [4, 4, " \"runtime-version\": \"master\","],
+ [5, 5, " \"sdk\": \"org.gnome.Sdk\","],
+ [6, 6, " \"command\": \"nautilus\","],
+ # end
+ [7, 7, " \"tags\": [\"devel\", \"development\", \"nightly\"],"],
+ [8, 8, " \"desktop-file-name-prefix\": \"(Development) \","],
+ [9, 9, " \"finish-args\": ["],
+ [10, 10, "- \"--share=ipc\", \"--socket=x11\","],
+ [11, 10, "- \"--socket=wayland\","],
+ [12, 10, "- \"--talk-name=org.gnome.OnlineAccounts\","],
+ [13, 10, " \"--talk-name=org.freedesktop.Tracker1\","],
+ [14, 11, " \"--filesystem=home\","],
+ [15, 12, " \"--talk-name=org.gtk.vfs\", \"--talk-name=org.gtk.vfs.*\","],
+ [62, 59, "@@ -62,7 +59,7 @@"],
+ [62, 59, " },"],
+ [63, 60, " {"],
+ [64, 61, " \"name\": \"gnome-desktop\","],
+ [65, 62, "- \"config-opts\": [\"--disable-debug-tools\", \"--disable-udev\"],"],
+ [66, 62, "+ \"config-opts\": [\"--disable-debug-tools\", \"--disable-\"],"],
+ [66, 63, " \"sources\": ["],
+ [67, 64, " {"],
+ [68, 65, " \"type\": \"git\","],
+ [83, 80, "@@ -83,11 +80,6 @@"],
+ [83, 80, " \"buildsystem\": \"meson\","],
+ [84, 81, " \"builddir\": true,"],
+ [85, 82, " \"name\": \"nautilus\","],
+ [86, 83, "- \"config-opts\": ["],
+ [87, 83, "- \"-Denable-desktop=false\","],
+ [88, 83, "- \"-Denable-selinux=false\","],
+ [89, 83, "- \"--libdir=/app/lib\""],
+ [90, 83, "- ],"],
+ [91, 83, " \"sources\": ["],
+ [92, 84, " {"],
+ [93, 85, " \"type\": \"git\","]]
+ end
+
+ it 'return merge of blob lines with diff lines correctly' do
+ new_diff_lines = subject.unfolded_diff_lines
+
+ expected_diff_lines.each_with_index do |expected_line, i|
+ line = new_diff_lines[i]
+
+ expect([line.old_pos, line.new_pos, line.text])
+ .to eq([expected_line[0], expected_line[1], expected_line[2]])
+ end
+ end
+
+ it 'merged lines have correct line codes' do
+ new_diff_lines = subject.unfolded_diff_lines
+
+ new_diff_lines.each_with_index do |line, i|
+ old_pos, new_pos = expected_diff_lines[i][0], expected_diff_lines[i][1]
+
+ unless line.type == 'match'
+ expect(line.line_code).to eq(Gitlab::Git.diff_line_code(diff_file.file_path, new_pos, old_pos))
+ end
+ end
+ end
+ end
+ end
+
+ context 'position sits between two match lines (no expasion needed)' do
+ let(:position) do
+ Gitlab::Diff::Position.new(base_sha: "1c59dfa64afbea8c721bb09a06a9d326c952ea19",
+ start_sha: "1c59dfa64afbea8c721bb09a06a9d326c952ea19",
+ head_sha: "1487062132228de836236c522fe52fed4980a46c",
+ old_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ new_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ position_type: "text",
+ old_line: 64,
+ new_line: 61)
+ end
+
+ context 'diff lines' do
+ it 'returns nil' do
+ expect(subject.unfolded_diff_lines).to be_nil
+ end
+ end
+ end
+
+ context 'position requires bottom expansion and new match lines' do
+ let(:position) do
+ Gitlab::Diff::Position.new(base_sha: "1c59dfa64afbea8c721bb09a06a9d326c952ea19",
+ start_sha: "1c59dfa64afbea8c721bb09a06a9d326c952ea19",
+ head_sha: "1487062132228de836236c522fe52fed4980a46c",
+ old_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ new_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ position_type: "text",
+ old_line: 107,
+ new_line: 99)
+ end
+
+ context 'blob lines' do
+ let(:expected_blob_lines) do
+ [[104, 104, " \"sdk\": \"foo\","],
+ [105, 105, " \"command\": \"foo\","],
+ [106, 106, " \"tags\": [\"foo\", \"bar\", \"kux\"],"],
+ [107, 107, " \"desktop-file-name-prefix\": \"(Foo) \","],
+ [108, 108, " {"],
+ [109, 109, " \"buildsystem\": \"meson\","],
+ [110, 110, " \"builddir\": true,"]]
+ end
+
+ it 'returns the extracted blob lines correctly' do
+ extracted_lines = subject.blob_lines
+
+ expect(extracted_lines.size).to eq(7)
+
+ extracted_lines.each_with_index do |line, i|
+ expect([line.old_line, line.new_line, line.text]).to eq(expected_blob_lines[i])
+ end
+ end
+ end
+
+ context 'diff lines' do
+ let(:expected_diff_lines) do
+ [[7, 7, "@@ -7,9 +7,6 @@"],
+ [7, 7, " \"tags\": [\"devel\", \"development\", \"nightly\"],"],
+ [8, 8, " \"desktop-file-name-prefix\": \"(Development) \","],
+ [9, 9, " \"finish-args\": ["],
+ [10, 10, "- \"--share=ipc\", \"--socket=x11\","],
+ [11, 10, "- \"--socket=wayland\","],
+ [12, 10, "- \"--talk-name=org.gnome.OnlineAccounts\","],
+ [13, 10, " \"--talk-name=org.freedesktop.Tracker1\","],
+ [14, 11, " \"--filesystem=home\","],
+ [15, 12, " \"--talk-name=org.gtk.vfs\", \"--talk-name=org.gtk.vfs.*\","],
+ [62, 59, "@@ -62,7 +59,7 @@"],
+ [62, 59, " },"],
+ [63, 60, " {"],
+ [64, 61, " \"name\": \"gnome-desktop\","],
+ [65, 62, "- \"config-opts\": [\"--disable-debug-tools\", \"--disable-udev\"],"],
+ [66, 62, "+ \"config-opts\": [\"--disable-debug-tools\", \"--disable-\"],"],
+ [66, 63, " \"sources\": ["],
+ [67, 64, " {"],
+ [68, 65, " \"type\": \"git\","],
+ [83, 80, "@@ -83,11 +80,6 @@"],
+ [83, 80, " \"buildsystem\": \"meson\","],
+ [84, 81, " \"builddir\": true,"],
+ [85, 82, " \"name\": \"nautilus\","],
+ [86, 83, "- \"config-opts\": ["],
+ [87, 83, "- \"-Denable-desktop=false\","],
+ [88, 83, "- \"-Denable-selinux=false\","],
+ [89, 83, "- \"--libdir=/app/lib\""],
+ [90, 83, "- ],"],
+ [91, 83, " \"sources\": ["],
+ [92, 84, " {"],
+ [93, 85, " \"type\": \"git\","],
+ # New match line
+ [104, 96, "@@ -104,7+96,7 @@"],
+
+ # Injected blob lines
+ [104, 96, " \"sdk\": \"foo\","],
+ [105, 97, " \"command\": \"foo\","],
+ [106, 98, " \"tags\": [\"foo\", \"bar\", \"kux\"],"],
+ [107, 99, " \"desktop-file-name-prefix\": \"(Foo) \","],
+ [108, 100, " {"],
+ [109, 101, " \"buildsystem\": \"meson\","],
+ [110, 102, " \"builddir\": true,"]]
+ # end
+ end
+
+ it 'return merge of blob lines with diff lines correctly' do
+ new_diff_lines = subject.unfolded_diff_lines
+
+ expected_diff_lines.each_with_index do |expected_line, i|
+ line = new_diff_lines[i]
+
+ expect([line.old_pos, line.new_pos, line.text])
+ .to eq([expected_line[0], expected_line[1], expected_line[2]])
+ end
+ end
+
+ it 'merged lines have correct line codes' do
+ new_diff_lines = subject.unfolded_diff_lines
+
+ new_diff_lines.each_with_index do |line, i|
+ old_pos, new_pos = expected_diff_lines[i][0], expected_diff_lines[i][1]
+
+ unless line.type == 'match'
+ expect(line.line_code).to eq(Gitlab::Git.diff_line_code(diff_file.file_path, new_pos, old_pos))
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/diff/position_spec.rb b/spec/lib/gitlab/diff/position_spec.rb
index 677eb373d22..cc4faf6f10b 100644
--- a/spec/lib/gitlab/diff/position_spec.rb
+++ b/spec/lib/gitlab/diff/position_spec.rb
@@ -5,6 +5,34 @@ describe Gitlab::Diff::Position do
let(:project) { create(:project, :repository) }
+ let(:args_for_img) do
+ {
+ old_path: "files/any.img",
+ new_path: "files/any.img",
+ base_sha: nil,
+ head_sha: nil,
+ start_sha: nil,
+ width: 100,
+ height: 100,
+ x: 1,
+ y: 100,
+ position_type: "image"
+ }
+ end
+
+ let(:args_for_text) do
+ {
+ old_path: "files/ruby/popen.rb",
+ new_path: "files/ruby/popen.rb",
+ old_line: nil,
+ new_line: 14,
+ base_sha: nil,
+ head_sha: nil,
+ start_sha: nil,
+ position_type: "text"
+ }
+ end
+
describe "position for an added text file" do
let(:commit) { project.commit("2ea1f3dec713d940208fb5ce4a38765ecb5d3f73") }
@@ -529,53 +557,49 @@ describe Gitlab::Diff::Position do
end
end
+ describe "#as_json" do
+ shared_examples "diff position json" do
+ let(:diff_position) { described_class.new(args) }
+
+ it "returns the position as JSON" do
+ expect(diff_position.as_json).to eq(args.stringify_keys)
+ end
+ end
+
+ context "for text position" do
+ let(:args) { args_for_text }
+
+ it_behaves_like "diff position json"
+ end
+
+ context "for image position" do
+ let(:args) { args_for_img }
+
+ it_behaves_like "diff position json"
+ end
+ end
+
describe "#to_json" do
shared_examples "diff position json" do
+ let(:diff_position) { described_class.new(args) }
+
it "returns the position as JSON" do
- expect(JSON.parse(diff_position.to_json)).to eq(hash.stringify_keys)
+ expect(JSON.parse(diff_position.to_json)).to eq(args.stringify_keys)
end
it "works when nested under another hash" do
- expect(JSON.parse(JSON.generate(pos: diff_position))).to eq('pos' => hash.stringify_keys)
+ expect(JSON.parse(JSON.generate(pos: diff_position))).to eq('pos' => args.stringify_keys)
end
end
- context "for text positon" do
- let(:hash) do
- {
- old_path: "files/ruby/popen.rb",
- new_path: "files/ruby/popen.rb",
- old_line: nil,
- new_line: 14,
- base_sha: nil,
- head_sha: nil,
- start_sha: nil,
- position_type: "text"
- }
- end
-
- let(:diff_position) { described_class.new(hash) }
+ context "for text position" do
+ let(:args) { args_for_text }
it_behaves_like "diff position json"
end
- context "for image positon" do
- let(:hash) do
- {
- old_path: "files/any.img",
- new_path: "files/any.img",
- base_sha: nil,
- head_sha: nil,
- start_sha: nil,
- width: 100,
- height: 100,
- x: 1,
- y: 100,
- position_type: "image"
- }
- end
-
- let(:diff_position) { described_class.new(hash) }
+ context "for image position" do
+ let(:args) { args_for_img }
it_behaves_like "diff position json"
end
diff --git a/spec/lib/gitlab/diff/position_tracer_spec.rb b/spec/lib/gitlab/diff/position_tracer_spec.rb
index ddc4f6c5b5c..a2eed07ca55 100644
--- a/spec/lib/gitlab/diff/position_tracer_spec.rb
+++ b/spec/lib/gitlab/diff/position_tracer_spec.rb
@@ -43,7 +43,7 @@ describe Gitlab::Diff::PositionTracer do
#
# In any case, all of this means that the tests below will be extremely
# (excessively, unjustifiably) thorough for scenarios where "the file was
- # created in the old diff" and then drop off to comparitively lackluster
+ # created in the old diff" and then drop off to comparatively lackluster
# testing of other scenarios.
#
# I did still try to cover most of the obvious and potentially tricky
diff --git a/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb b/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb
index ace3104f36f..f276f1a8ddf 100644
--- a/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb
@@ -93,5 +93,74 @@ describe Gitlab::Email::Handler::CreateMergeRequestHandler do
end
end
end
+
+ context 'when the email contains patch attachments' do
+ let(:email_raw) { fixture_file("emails/valid_merge_request_with_patch.eml") }
+
+ it 'creates the source branch and applies the patches' do
+ receiver.execute
+
+ branch = project.repository.find_branch('new-branch-with-a-patch')
+
+ expect(branch).not_to be_nil
+ expect(branch.dereferenced_target.message).to include('A commit from a patch')
+ end
+
+ it 'creates the merge request' do
+ expect { receiver.execute }
+ .to change { project.merge_requests.where(source_branch: 'new-branch-with-a-patch').size }.by(1)
+ end
+
+ it 'does not mention the patches in the created merge request' do
+ receiver.execute
+
+ merge_request = project.merge_requests.find_by!(source_branch: 'new-branch-with-a-patch')
+
+ expect(merge_request.description).not_to include('0001-A-commit-from-a-patch.patch')
+ end
+
+ context 'when the patch could not be applied' do
+ let(:email_raw) { fixture_file("emails/merge_request_with_conflicting_patch.eml") }
+
+ it 'raises an error' do
+ expect { receiver.execute }.to raise_error(Gitlab::Email::InvalidAttachment)
+ end
+ end
+
+ context 'when specifying the target branch using quick actions' do
+ let(:email_raw) { fixture_file('emails/merge_request_with_patch_and_target_branch.eml') }
+
+ it 'creates the merge request with the correct target branch' do
+ receiver.execute
+
+ merge_request = project.merge_requests.find_by!(source_branch: 'new-branch-with-a-patch')
+
+ expect(merge_request.target_branch).to eq('with-codeowners')
+ end
+
+ it 'based the merge request of the target_branch' do
+ receiver.execute
+
+ merge_request = project.merge_requests.find_by!(source_branch: 'new-branch-with-a-patch')
+
+ expect(merge_request.diff_base_commit).to eq(project.repository.commit('with-codeowners'))
+ end
+ end
+ end
+ end
+
+ describe '#patch_attachments' do
+ let(:email_raw) { fixture_file('emails/merge_request_multiple_patches.eml') }
+ let(:mail) { Mail::Message.new(email_raw) }
+ subject(:handler) { described_class.new(mail, mail_key) }
+
+ it 'orders attachments ending in `.patch` by name' do
+ expected_filenames = ["0001-A-commit-from-a-patch.patch",
+ "0002-This-does-not-apply-to-the-feature-branch.patch"]
+
+ attachments = handler.__send__(:patch_attachments).map(&:filename)
+
+ expect(attachments).to eq(expected_filenames)
+ end
end
end
diff --git a/spec/lib/gitlab/email/reply_parser_spec.rb b/spec/lib/gitlab/email/reply_parser_spec.rb
index 0989188f7ee..376d3accd55 100644
--- a/spec/lib/gitlab/email/reply_parser_spec.rb
+++ b/spec/lib/gitlab/email/reply_parser_spec.rb
@@ -49,7 +49,7 @@ describe Gitlab::Email::ReplyParser do
expect(test_parse_body(fixture_file("emails/paragraphs.eml")))
.to eq(
<<-BODY.strip_heredoc.chomp
- Is there any reason the *old* candy can't be be kept in silos while the new candy
+ Is there any reason the *old* candy can't be kept in silos while the new candy
is imported into *new* silos?
The thing about candy is it stays delicious for a long time -- we can just keep
diff --git a/spec/lib/gitlab/exclusive_lease_helpers_spec.rb b/spec/lib/gitlab/exclusive_lease_helpers_spec.rb
index 2e3656b52fb..5107e1efbbd 100644
--- a/spec/lib/gitlab/exclusive_lease_helpers_spec.rb
+++ b/spec/lib/gitlab/exclusive_lease_helpers_spec.rb
@@ -11,6 +11,14 @@ describe Gitlab::ExclusiveLeaseHelpers, :clean_gitlab_redis_shared_state do
let(:options) { {} }
+ context 'when unique key is not set' do
+ let(:unique_key) { }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error ArgumentError
+ end
+ end
+
context 'when the lease is not obtained yet' do
before do
stub_exclusive_lease(unique_key, 'uuid')
diff --git a/spec/lib/gitlab/favicon_spec.rb b/spec/lib/gitlab/favicon_spec.rb
index 68abcb3520a..49a423191bb 100644
--- a/spec/lib/gitlab/favicon_spec.rb
+++ b/spec/lib/gitlab/favicon_spec.rb
@@ -58,6 +58,7 @@ RSpec.describe Gitlab::Favicon, :request_store do
favicon_status_not_found
favicon_status_pending
favicon_status_running
+ favicon_status_scheduled
favicon_status_skipped
favicon_status_success
favicon_status_warning
diff --git a/spec/lib/gitlab/file_detector_spec.rb b/spec/lib/gitlab/file_detector_spec.rb
index 9e351368b22..4ba9094b24e 100644
--- a/spec/lib/gitlab/file_detector_spec.rb
+++ b/spec/lib/gitlab/file_detector_spec.rb
@@ -15,7 +15,20 @@ describe Gitlab::FileDetector do
describe '.type_of' do
it 'returns the type of a README file' do
- expect(described_class.type_of('README.md')).to eq(:readme)
+ filenames = Gitlab::MarkupHelper::PLAIN_FILENAMES + Gitlab::MarkupHelper::PLAIN_FILENAMES.map(&:upcase)
+ extensions = Gitlab::MarkupHelper::EXTENSIONS + Gitlab::MarkupHelper::EXTENSIONS.map(&:upcase)
+
+ filenames.each do |filename|
+ expect(described_class.type_of(filename)).to eq(:readme)
+
+ extensions.each do |extname|
+ expect(described_class.type_of("#{filename}.#{extname}")).to eq(:readme)
+ end
+ end
+ end
+
+ it 'returns nil for a README.rb file' do
+ expect(described_class.type_of('README.rb')).to be_nil
end
it 'returns nil for a README file in a directory' do
@@ -46,10 +59,6 @@ describe Gitlab::FileDetector do
expect(described_class.type_of('.gitignore')).to eq(:gitignore)
end
- it 'returns the type of a Koding config file' do
- expect(described_class.type_of('.koding.yml')).to eq(:koding)
- end
-
it 'returns the type of a GitLab CI config file' do
expect(described_class.type_of('.gitlab-ci.yml')).to eq(:gitlab_ci)
end
diff --git a/spec/lib/gitlab/git/attributes_at_ref_parser_spec.rb b/spec/lib/gitlab/git/attributes_at_ref_parser_spec.rb
index ca067a29174..134bd5657e7 100644
--- a/spec/lib/gitlab/git/attributes_at_ref_parser_spec.rb
+++ b/spec/lib/gitlab/git/attributes_at_ref_parser_spec.rb
@@ -17,7 +17,7 @@ describe Gitlab::Git::AttributesAtRefParser, :seed_helper do
end
it 'handles missing blobs' do
- expect { described_class.new(repository, 'non-existant-branch') }.not_to raise_error
+ expect { described_class.new(repository, 'non-existent-branch') }.not_to raise_error
end
describe '#attributes' do
diff --git a/spec/lib/gitlab/git/attributes_parser_spec.rb b/spec/lib/gitlab/git/attributes_parser_spec.rb
index 18ebfef38f0..f431d4e2a53 100644
--- a/spec/lib/gitlab/git/attributes_parser_spec.rb
+++ b/spec/lib/gitlab/git/attributes_parser_spec.rb
@@ -94,7 +94,7 @@ describe Gitlab::Git::AttributesParser, :seed_helper do
# It's a bit hard to test for something _not_ being processed. As such we'll
# just test the number of entries.
it 'ignores any comments and empty lines' do
- expect(subject.patterns.length).to eq(10)
+ expect(subject.patterns.length).to eq(12)
end
end
@@ -126,7 +126,7 @@ describe Gitlab::Git::AttributesParser, :seed_helper do
describe '#each_line' do
it 'iterates over every line in the attributes file' do
- args = [String] * 14 # the number of lines in the file
+ args = [String] * 16 # the number of lines in the file
expect { |b| subject.each_line(&b) }.to yield_successive_args(*args)
end
diff --git a/spec/lib/gitlab/git/blob_snippet_spec.rb b/spec/lib/gitlab/git/blob_snippet_spec.rb
deleted file mode 100644
index 6effec8295c..00000000000
--- a/spec/lib/gitlab/git/blob_snippet_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# encoding: UTF-8
-
-require "spec_helper"
-
-describe Gitlab::Git::BlobSnippet, :seed_helper do
- describe '#data' do
- context 'empty lines' do
- let(:snippet) { Gitlab::Git::BlobSnippet.new('master', nil, nil, nil) }
-
- it { expect(snippet.data).to be_nil }
- end
-
- context 'present lines' do
- let(:snippet) { Gitlab::Git::BlobSnippet.new('master', %w(wow much), 1, 'wow.rb') }
-
- it { expect(snippet.data).to eq("wow\nmuch") }
- end
- end
-end
diff --git a/spec/lib/gitlab/git/blob_spec.rb b/spec/lib/gitlab/git/blob_spec.rb
index ea49502ae2e..80dd3dcc58e 100644
--- a/spec/lib/gitlab/git/blob_spec.rb
+++ b/spec/lib/gitlab/git/blob_spec.rb
@@ -4,6 +4,9 @@ require "spec_helper"
describe Gitlab::Git::Blob, :seed_helper do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
+ let(:rugged) do
+ Rugged::Repository.new(File.join(TestEnv.repos_path, TEST_REPO_PATH))
+ end
describe 'initialize' do
let(:blob) { Gitlab::Git::Blob.new(name: 'test') }
@@ -125,7 +128,7 @@ describe Gitlab::Git::Blob, :seed_helper do
end
end
- shared_examples 'finding blobs by ID' do
+ describe '.raw' do
let(:raw_blob) { Gitlab::Git::Blob.raw(repository, SeedRepo::RubyBlob::ID) }
let(:bad_blob) { Gitlab::Git::Blob.raw(repository, SeedRepo::BigCommit::ID) }
@@ -139,9 +142,7 @@ describe Gitlab::Git::Blob, :seed_helper do
it 'limits the size of a large file' do
blob_size = Gitlab::Git::Blob::MAX_DATA_DISPLAY_SIZE + 1
buffer = Array.new(blob_size, 0)
- rugged_blob = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- Rugged::Blob.from_buffer(repository.rugged, buffer.join(''))
- end
+ rugged_blob = Rugged::Blob.from_buffer(rugged, buffer.join(''))
blob = Gitlab::Git::Blob.raw(repository, rugged_blob)
expect(blob.size).to eq(blob_size)
@@ -156,9 +157,7 @@ describe Gitlab::Git::Blob, :seed_helper do
context 'when sha references a tree' do
it 'returns nil' do
- tree = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- repository.rugged.rev_parse('master^{tree}')
- end
+ tree = rugged.rev_parse('master^{tree}')
blob = Gitlab::Git::Blob.raw(repository, tree.oid)
@@ -167,16 +166,6 @@ describe Gitlab::Git::Blob, :seed_helper do
end
end
- describe '.raw' do
- context 'when the blob_raw Gitaly feature is enabled' do
- it_behaves_like 'finding blobs by ID'
- end
-
- context 'when the blob_raw Gitaly feature is disabled', :skip_gitaly_mock do
- it_behaves_like 'finding blobs by ID'
- end
- end
-
describe '.batch' do
let(:blob_references) do
[
@@ -262,11 +251,7 @@ describe Gitlab::Git::Blob, :seed_helper do
end
describe '.batch_lfs_pointers' do
- let(:tree_object) do
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- repository.rugged.rev_parse('master^{tree}')
- end
- end
+ let(:tree_object) { rugged.rev_parse('master^{tree}') }
let(:non_lfs_blob) do
Gitlab::Git::Blob.find(
diff --git a/spec/lib/gitlab/git/branch_spec.rb b/spec/lib/gitlab/git/branch_spec.rb
index 79ccbb79966..0df282d0ae3 100644
--- a/spec/lib/gitlab/git/branch_spec.rb
+++ b/spec/lib/gitlab/git/branch_spec.rb
@@ -3,9 +3,7 @@ require "spec_helper"
describe Gitlab::Git::Branch, :seed_helper do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:rugged) do
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- repository.rugged
- end
+ Rugged::Repository.new(File.join(TestEnv.repos_path, repository.relative_path))
end
subject { repository.branches }
@@ -74,9 +72,7 @@ describe Gitlab::Git::Branch, :seed_helper do
Gitlab::Git.committer_hash(email: user.email, name: user.name)
end
let(:params) do
- parents = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- [repository.rugged.head.target]
- end
+ parents = [rugged.head.target]
tree = parents.first.tree
{
diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb
index 2718a3c5e49..db68062e433 100644
--- a/spec/lib/gitlab/git/commit_spec.rb
+++ b/spec/lib/gitlab/git/commit_spec.rb
@@ -1,19 +1,17 @@
require "spec_helper"
describe Gitlab::Git::Commit, :seed_helper do
+ include GitHelpers
+
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
- let(:commit) { described_class.find(repository, SeedRepo::Commit::ID) }
- let(:rugged_commit) do
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- repository.rugged.lookup(SeedRepo::Commit::ID)
- end
+ let(:rugged_repo) do
+ Rugged::Repository.new(File.join(TestEnv.repos_path, TEST_REPO_PATH))
end
+ let(:commit) { described_class.find(repository, SeedRepo::Commit::ID) }
+ let(:rugged_commit) { rugged_repo.lookup(SeedRepo::Commit::ID) }
+
describe "Commit info" do
before do
- repo = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '').rugged
- end
-
@committer = {
email: 'mike@smith.com',
name: "Mike Smith",
@@ -26,12 +24,12 @@ describe Gitlab::Git::Commit, :seed_helper do
time: Time.now
}
- @parents = [repo.head.target]
+ @parents = [rugged_repo.head.target]
@gitlab_parents = @parents.map { |c| described_class.find(repository, c.oid) }
@tree = @parents.first.tree
sha = Rugged::Commit.create(
- repo,
+ rugged_repo,
author: @author,
committer: @committer,
tree: @tree,
@@ -40,7 +38,7 @@ describe Gitlab::Git::Commit, :seed_helper do
update_ref: "HEAD"
)
- @raw_commit = repo.lookup(sha)
+ @raw_commit = rugged_repo.lookup(sha)
@commit = described_class.find(repository, sha)
end
@@ -61,10 +59,7 @@ describe Gitlab::Git::Commit, :seed_helper do
after do
# Erase the new commit so other tests get the original repo
- repo = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '').rugged
- end
- repo.references.update("refs/heads/master", SeedRepo::LastCommit::ID)
+ rugged_repo.references.update("refs/heads/master", SeedRepo::LastCommit::ID)
end
end
@@ -99,7 +94,7 @@ describe Gitlab::Git::Commit, :seed_helper do
context 'body_size less than threshold' do
let(:body_size) { 123 }
- it 'fetches commit message seperately' do
+ it 'fetches commit message separately' do
expect(described_class).to receive(:get_message).with(repository, id)
commit.safe_message
@@ -120,9 +115,7 @@ describe Gitlab::Git::Commit, :seed_helper do
describe '.find' do
it "should return first head commit if without params" do
expect(described_class.last(repository).id).to eq(
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- repository.rugged.head.target.oid
- end
+ rugged_repo.head.target.oid
)
end
@@ -190,110 +183,100 @@ describe Gitlab::Git::Commit, :seed_helper do
end
end
- shared_examples '.where' do
- context 'path is empty string' do
- subject do
- commits = described_class.where(
- repo: repository,
- ref: 'master',
- path: '',
- limit: 10
- )
-
- commits.map { |c| c.id }
- end
+ context 'path is empty string' do
+ subject do
+ commits = described_class.where(
+ repo: repository,
+ ref: 'master',
+ path: '',
+ limit: 10
+ )
- it 'has 10 elements' do
- expect(subject.size).to eq(10)
- end
- it { is_expected.to include(SeedRepo::EmptyCommit::ID) }
+ commits.map { |c| c.id }
end
- context 'path is nil' do
- subject do
- commits = described_class.where(
- repo: repository,
- ref: 'master',
- path: nil,
- limit: 10
- )
-
- commits.map { |c| c.id }
- end
-
- it 'has 10 elements' do
- expect(subject.size).to eq(10)
- end
- it { is_expected.to include(SeedRepo::EmptyCommit::ID) }
+ it 'has 10 elements' do
+ expect(subject.size).to eq(10)
end
+ it { is_expected.to include(SeedRepo::EmptyCommit::ID) }
+ end
- context 'ref is branch name' do
- subject do
- commits = described_class.where(
- repo: repository,
- ref: 'master',
- path: 'files',
- limit: 3,
- offset: 1
- )
+ context 'path is nil' do
+ subject do
+ commits = described_class.where(
+ repo: repository,
+ ref: 'master',
+ path: nil,
+ limit: 10
+ )
- commits.map { |c| c.id }
- end
+ commits.map { |c| c.id }
+ end
- it 'has 3 elements' do
- expect(subject.size).to eq(3)
- end
- it { is_expected.to include("d14d6c0abdd253381df51a723d58691b2ee1ab08") }
- it { is_expected.not_to include("eb49186cfa5c4338011f5f590fac11bd66c5c631") }
+ it 'has 10 elements' do
+ expect(subject.size).to eq(10)
end
+ it { is_expected.to include(SeedRepo::EmptyCommit::ID) }
+ end
- context 'ref is commit id' do
- subject do
- commits = described_class.where(
- repo: repository,
- ref: "874797c3a73b60d2187ed6e2fcabd289ff75171e",
- path: 'files',
- limit: 3,
- offset: 1
- )
+ context 'ref is branch name' do
+ subject do
+ commits = described_class.where(
+ repo: repository,
+ ref: 'master',
+ path: 'files',
+ limit: 3,
+ offset: 1
+ )
- commits.map { |c| c.id }
- end
+ commits.map { |c| c.id }
+ end
- it 'has 3 elements' do
- expect(subject.size).to eq(3)
- end
- it { is_expected.to include("2f63565e7aac07bcdadb654e253078b727143ec4") }
- it { is_expected.not_to include(SeedRepo::Commit::ID) }
+ it 'has 3 elements' do
+ expect(subject.size).to eq(3)
end
+ it { is_expected.to include("d14d6c0abdd253381df51a723d58691b2ee1ab08") }
+ it { is_expected.not_to include("eb49186cfa5c4338011f5f590fac11bd66c5c631") }
+ end
- context 'ref is tag' do
- subject do
- commits = described_class.where(
- repo: repository,
- ref: 'v1.0.0',
- path: 'files',
- limit: 3,
- offset: 1
- )
+ context 'ref is commit id' do
+ subject do
+ commits = described_class.where(
+ repo: repository,
+ ref: "874797c3a73b60d2187ed6e2fcabd289ff75171e",
+ path: 'files',
+ limit: 3,
+ offset: 1
+ )
- commits.map { |c| c.id }
- end
+ commits.map { |c| c.id }
+ end
- it 'has 3 elements' do
- expect(subject.size).to eq(3)
- end
- it { is_expected.to include("874797c3a73b60d2187ed6e2fcabd289ff75171e") }
- it { is_expected.not_to include(SeedRepo::Commit::ID) }
+ it 'has 3 elements' do
+ expect(subject.size).to eq(3)
end
+ it { is_expected.to include("2f63565e7aac07bcdadb654e253078b727143ec4") }
+ it { is_expected.not_to include(SeedRepo::Commit::ID) }
end
- describe '.where with gitaly' do
- it_should_behave_like '.where'
- end
+ context 'ref is tag' do
+ subject do
+ commits = described_class.where(
+ repo: repository,
+ ref: 'v1.0.0',
+ path: 'files',
+ limit: 3,
+ offset: 1
+ )
- describe '.where without gitaly', :skip_gitaly_mock do
- it_should_behave_like '.where'
+ commits.map { |c| c.id }
+ end
+
+ it 'has 3 elements' do
+ expect(subject.size).to eq(3)
+ end
+ it { is_expected.to include("874797c3a73b60d2187ed6e2fcabd289ff75171e") }
+ it { is_expected.not_to include(SeedRepo::Commit::ID) }
end
describe '.between' do
@@ -467,11 +450,17 @@ describe Gitlab::Git::Commit, :seed_helper do
described_class.extract_signature_lazily(repository, commit_id)
end
+ other_repository = double(:repository)
+ described_class.extract_signature_lazily(other_repository, commit_ids.first)
+
expect(described_class).to receive(:batch_signature_extraction)
.with(repository, commit_ids)
.once
.and_return({})
+ expect(described_class).not_to receive(:batch_signature_extraction)
+ .with(other_repository, commit_ids.first)
+
2.times { signatures.each(&:itself) }
end
end
@@ -515,7 +504,7 @@ describe Gitlab::Git::Commit, :seed_helper do
end
end
- shared_examples '#stats' do
+ describe '#stats' do
subject { commit.stats }
describe '#additions' do
@@ -534,14 +523,6 @@ describe Gitlab::Git::Commit, :seed_helper do
end
end
- describe '#stats with gitaly on' do
- it_should_behave_like '#stats'
- end
-
- describe '#stats with gitaly disabled', :skip_gitaly_mock do
- it_should_behave_like '#stats'
- end
-
describe '#has_zero_stats?' do
it { expect(commit.has_zero_stats?).to eq(false) }
end
@@ -584,25 +565,15 @@ describe Gitlab::Git::Commit, :seed_helper do
commit_ids.map { |id| described_class.get_message(repository, id) }
end
- shared_examples 'getting commit messages' do
- it 'gets commit messages' do
- expect(subject).to contain_exactly(
- "Added contributing guide\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
- "Add submodule\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n"
- )
- end
- end
-
- context 'when Gitaly commit_messages feature is enabled' do
- it_behaves_like 'getting commit messages'
-
- it 'gets messages in one batch', :request_store do
- expect { subject.map(&:itself) }.to change { Gitlab::GitalyClient.get_request_count }.by(1)
- end
+ it 'gets commit messages' do
+ expect(subject).to contain_exactly(
+ "Added contributing guide\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
+ "Add submodule\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n"
+ )
end
- context 'when Gitaly commit_messages feature is disabled', :disable_gitaly do
- it_behaves_like 'getting commit messages'
+ it 'gets messages in one batch', :request_store do
+ expect { subject.map(&:itself) }.to change { Gitlab::GitalyClient.get_request_count }.by(1)
end
end
diff --git a/spec/lib/gitlab/git/diff_spec.rb b/spec/lib/gitlab/git/diff_spec.rb
index 27d803e0117..8a4415506c4 100644
--- a/spec/lib/gitlab/git/diff_spec.rb
+++ b/spec/lib/gitlab/git/diff_spec.rb
@@ -64,9 +64,22 @@ EOT
end
end
- context 'using a Rugged::Patch' do
+ context 'using a GitalyClient::Diff' do
+ let(:gitaly_diff) do
+ Gitlab::GitalyClient::Diff.new(
+ to_path: ".gitmodules",
+ from_path: ".gitmodules",
+ old_mode: 0100644,
+ new_mode: 0100644,
+ from_id: '357406f3075a57708d0163752905cc1576fceacc',
+ to_id: '8e5177d718c561d36efde08bad36b43687ee6bf0',
+ patch: raw_patch
+ )
+ end
+ let(:diff) { described_class.new(gitaly_diff) }
+
context 'with a small diff' do
- let(:diff) { described_class.new(gitaly_diff) }
+ let(:raw_patch) { @raw_diff_hash[:diff] }
it 'initializes the diff' do
expect(diff.to_hash).to eq(@raw_diff_hash)
@@ -78,16 +91,17 @@ EOT
end
context 'using a diff that is too large' do
- it 'prunes the diff' do
- gitaly_diff.too_large = true
- diff = described_class.new(gitaly_diff)
+ let(:raw_patch) { 'a' * 204800 }
+ it 'prunes the diff' do
expect(diff.diff).to be_empty
expect(diff).to be_too_large
end
end
context 'using a collapsable diff that is too large' do
+ let(:raw_patch) { 'a' * 204800 }
+
it 'prunes the diff as a large diff instead of as a collapsed diff' do
gitaly_diff.too_large = true
diff = described_class.new(gitaly_diff, expanded: false)
@@ -97,43 +111,6 @@ EOT
expect(diff).not_to be_collapsed
end
end
- end
-
- context 'using a GitalyClient::Diff' do
- let(:diff) do
- described_class.new(
- Gitlab::GitalyClient::Diff.new(
- to_path: ".gitmodules",
- from_path: ".gitmodules",
- old_mode: 0100644,
- new_mode: 0100644,
- from_id: '357406f3075a57708d0163752905cc1576fceacc',
- to_id: '8e5177d718c561d36efde08bad36b43687ee6bf0',
- patch: raw_patch
- )
- )
- end
-
- context 'with a small diff' do
- let(:raw_patch) { @raw_diff_hash[:diff] }
-
- it 'initializes the diff' do
- expect(diff.to_hash).to eq(@raw_diff_hash)
- end
-
- it 'does not prune the diff' do
- expect(diff).not_to be_too_large
- end
- end
-
- context 'using a diff that is too large' do
- let(:raw_patch) { 'a' * 204800 }
-
- it 'prunes the diff' do
- expect(diff.diff).to be_empty
- expect(diff).to be_too_large
- end
- end
context 'when the patch passed is not UTF-8-encoded' do
let(:raw_patch) { @raw_diff_hash[:diff].encode(Encoding::ASCII_8BIT) }
diff --git a/spec/lib/gitlab/git/diff_stats_collection_spec.rb b/spec/lib/gitlab/git/diff_stats_collection_spec.rb
index 89927cbb3a6..b07690ef39c 100644
--- a/spec/lib/gitlab/git/diff_stats_collection_spec.rb
+++ b/spec/lib/gitlab/git/diff_stats_collection_spec.rb
@@ -14,7 +14,7 @@ describe Gitlab::Git::DiffStatsCollection do
let(:diff_stats) { [stats_a, stats_b] }
let(:collection) { described_class.new(diff_stats) }
- describe '.find_by_path' do
+ describe '#find_by_path' do
it 'returns stats by path when found' do
expect(collection.find_by_path('foo')).to eq(stats_a)
end
@@ -23,4 +23,10 @@ describe Gitlab::Git::DiffStatsCollection do
expect(collection.find_by_path('no-file')).to be_nil
end
end
+
+ describe '#paths' do
+ it 'returns only modified paths' do
+ expect(collection.paths).to eq %w[foo bar]
+ end
+ end
end
diff --git a/spec/lib/gitlab/git/hook_env_spec.rb b/spec/lib/gitlab/git/hook_env_spec.rb
index e6aa5ad8c90..5e49ea6da7a 100644
--- a/spec/lib/gitlab/git/hook_env_spec.rb
+++ b/spec/lib/gitlab/git/hook_env_spec.rb
@@ -4,11 +4,7 @@ describe Gitlab::Git::HookEnv do
let(:gl_repository) { 'project-123' }
describe ".set" do
- context 'with RequestStore.store disabled' do
- before do
- allow(RequestStore).to receive(:active?).and_return(false)
- end
-
+ context 'with RequestStore disabled' do
it 'does not store anything' do
described_class.set(gl_repository, GIT_OBJECT_DIRECTORY_RELATIVE: 'foo')
@@ -16,11 +12,7 @@ describe Gitlab::Git::HookEnv do
end
end
- context 'with RequestStore.store enabled' do
- before do
- allow(RequestStore).to receive(:active?).and_return(true)
- end
-
+ context 'with RequestStore enabled', :request_store do
it 'whitelist some `GIT_*` variables and stores them using RequestStore' do
described_class.set(
gl_repository,
@@ -41,9 +33,8 @@ describe Gitlab::Git::HookEnv do
end
describe ".all" do
- context 'with RequestStore.store enabled' do
+ context 'with RequestStore enabled', :request_store do
before do
- allow(RequestStore).to receive(:active?).and_return(true)
described_class.set(
gl_repository,
GIT_OBJECT_DIRECTORY_RELATIVE: 'foo',
@@ -60,7 +51,7 @@ describe Gitlab::Git::HookEnv do
end
describe ".to_env_hash" do
- context 'with RequestStore.store enabled' do
+ context 'with RequestStore enabled', :request_store do
using RSpec::Parameterized::TableSyntax
let(:key) { 'GIT_OBJECT_DIRECTORY_RELATIVE' }
@@ -76,7 +67,6 @@ describe Gitlab::Git::HookEnv do
with_them do
before do
- allow(RequestStore).to receive(:active?).and_return(true)
described_class.set(gl_repository, key.to_sym => input)
end
@@ -92,7 +82,7 @@ describe Gitlab::Git::HookEnv do
end
describe 'thread-safety' do
- context 'with RequestStore.store enabled' do
+ context 'with RequestStore enabled', :request_store do
before do
allow(RequestStore).to receive(:active?).and_return(true)
described_class.set(gl_repository, GIT_OBJECT_DIRECTORY_RELATIVE: 'foo')
diff --git a/spec/lib/gitlab/git/lfs_changes_spec.rb b/spec/lib/gitlab/git/lfs_changes_spec.rb
index c5e7ab959b2..d035df7e0c2 100644
--- a/spec/lib/gitlab/git/lfs_changes_spec.rb
+++ b/spec/lib/gitlab/git/lfs_changes_spec.rb
@@ -15,5 +15,9 @@ describe Gitlab::Git::LfsChanges do
it 'limits new_objects using object_limit' do
expect(subject.new_pointers(object_limit: 1)).to eq([])
end
+
+ it 'times out if given a small dynamic timeout' do
+ expect { subject.new_pointers(dynamic_timeout: 0.001) }.to raise_error(GRPC::DeadlineExceeded)
+ end
end
end
diff --git a/spec/lib/gitlab/git/merge_base_spec.rb b/spec/lib/gitlab/git/merge_base_spec.rb
index 2f4e043a20f..8d16d451730 100644
--- a/spec/lib/gitlab/git/merge_base_spec.rb
+++ b/spec/lib/gitlab/git/merge_base_spec.rb
@@ -82,7 +82,7 @@ describe Gitlab::Git::MergeBase do
end
describe '#unknown_refs', :missing_ref do
- it 'returns the the refs passed that are not part of the repository' do
+ it 'returns the refs passed that are not part of the repository' do
expect(merge_base.unknown_refs).to contain_exactly('aaaa')
end
diff --git a/spec/lib/gitlab/git/patches/collection_spec.rb b/spec/lib/gitlab/git/patches/collection_spec.rb
new file mode 100644
index 00000000000..080be141c59
--- /dev/null
+++ b/spec/lib/gitlab/git/patches/collection_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::Git::Patches::Collection do
+ let(:patches_folder) { Rails.root.join('spec/fixtures/patchfiles') }
+ let(:patch_content1) do
+ File.read(File.join(patches_folder, "0001-This-does-not-apply-to-the-feature-branch.patch"))
+ end
+ let(:patch_content2) do
+ File.read(File.join(patches_folder, "0001-A-commit-from-a-patch.patch"))
+ end
+
+ subject(:collection) { described_class.new([patch_content1, patch_content2]) }
+
+ describe '#size' do
+ it 'combines the size of the patches' do
+ expect(collection.size).to eq(549.bytes + 424.bytes)
+ end
+ end
+
+ describe '#valid_size?' do
+ it 'is not valid if the total size is bigger than 2MB' do
+ expect(collection).to receive(:size).and_return(2500.kilobytes)
+
+ expect(collection).not_to be_valid_size
+ end
+ end
+end
diff --git a/spec/lib/gitlab/git/patches/commit_patches_spec.rb b/spec/lib/gitlab/git/patches/commit_patches_spec.rb
new file mode 100644
index 00000000000..760112155ce
--- /dev/null
+++ b/spec/lib/gitlab/git/patches/commit_patches_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::Git::Patches::CommitPatches do
+ describe '#commit' do
+ let(:patches) do
+ patches_folder = Rails.root.join('spec/fixtures/patchfiles')
+ content_1 = File.read(File.join(patches_folder, "0001-This-does-not-apply-to-the-feature-branch.patch"))
+ content_2 = File.read(File.join(patches_folder, "0001-A-commit-from-a-patch.patch"))
+
+ Gitlab::Git::Patches::Collection.new([content_1, content_2])
+ end
+ let(:user) { build(:user) }
+ let(:branch_name) { 'branch-with-patches' }
+ let(:repository) { create(:project, :repository).repository }
+
+ subject(:commit_patches) do
+ described_class.new(user, repository, branch_name, patches)
+ end
+
+ it 'applies the patches' do
+ new_rev = commit_patches.commit
+
+ expect(repository.commit(new_rev)).not_to be_nil
+ end
+
+ it 'updates the branch cache' do
+ expect(repository).to receive(:after_create_branch)
+
+ commit_patches.commit
+ end
+
+ context 'when the repository does not exist' do
+ let(:repository) { create(:project).repository }
+
+ it 'raises the correct error' do
+ expect { commit_patches.commit }.to raise_error(Gitlab::Git::Repository::NoRepository)
+ end
+ end
+
+ context 'when the patch does not apply' do
+ let(:branch_name) { 'feature' }
+
+ it 'raises the correct error' do
+ expect { commit_patches.commit }.to raise_error(Gitlab::Git::CommandError)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/git/patches/patch_spec.rb b/spec/lib/gitlab/git/patches/patch_spec.rb
new file mode 100644
index 00000000000..7466e853b65
--- /dev/null
+++ b/spec/lib/gitlab/git/patches/patch_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Gitlab::Git::Patches::Patch do
+ let(:patches_folder) { Rails.root.join('spec/fixtures/patchfiles') }
+ let(:patch_content) do
+ File.read(File.join(patches_folder, "0001-This-does-not-apply-to-the-feature-branch.patch"))
+ end
+ let(:patch) { described_class.new(patch_content) }
+
+ describe '#size' do
+ it 'is correct' do
+ expect(patch.size).to eq(549.bytes)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/git/push_spec.rb b/spec/lib/gitlab/git/push_spec.rb
new file mode 100644
index 00000000000..566c8209504
--- /dev/null
+++ b/spec/lib/gitlab/git/push_spec.rb
@@ -0,0 +1,166 @@
+require 'spec_helper'
+
+describe Gitlab::Git::Push do
+ set(:project) { create(:project, :repository) }
+
+ let(:oldrev) { project.commit('HEAD~2').id }
+ let(:newrev) { project.commit.id }
+ let(:ref) { 'refs/heads/some-branch' }
+
+ subject { described_class.new(project, oldrev, newrev, ref) }
+
+ describe '#branch_name' do
+ context 'when it is a branch push' do
+ let(:ref) { 'refs/heads/my-branch' }
+
+ it 'returns branch name' do
+ expect(subject.branch_name).to eq 'my-branch'
+ end
+ end
+
+ context 'when it is a tag push' do
+ let(:ref) { 'refs/tags/my-branch' }
+
+ it 'returns nil' do
+ expect(subject.branch_name).to be_nil
+ end
+ end
+ end
+
+ describe '#branch_push?' do
+ context 'when pushing a branch ref' do
+ let(:ref) { 'refs/heads/my-branch' }
+
+ it { is_expected.to be_branch_push }
+ end
+
+ context 'when it is a tag push' do
+ let(:ref) { 'refs/tags/my-tag' }
+
+ it { is_expected.not_to be_branch_push }
+ end
+ end
+
+ describe '#branch_updated?' do
+ context 'when it is a branch push with correct old and new revisions' do
+ it { is_expected.to be_branch_updated }
+ end
+
+ context 'when it is not a branch push' do
+ let(:ref) { 'refs/tags/my-tag' }
+
+ it { is_expected.not_to be_branch_updated }
+ end
+
+ context 'when old revision is blank' do
+ let(:oldrev) { Gitlab::Git::BLANK_SHA }
+
+ it { is_expected.not_to be_branch_updated }
+ end
+
+ context 'when it is not a branch push' do
+ let(:newrev) { Gitlab::Git::BLANK_SHA }
+
+ it { is_expected.not_to be_branch_updated }
+ end
+
+ context 'when oldrev is nil' do
+ let(:oldrev) { nil }
+
+ it { is_expected.not_to be_branch_updated }
+ end
+ end
+
+ describe '#force_push?' do
+ context 'when old revision is an ancestor of the new revision' do
+ let(:oldrev) { 'HEAD~3' }
+ let(:newrev) { 'HEAD~1' }
+
+ it { is_expected.not_to be_force_push }
+ end
+
+ context 'when old revision is not an ancestor of the new revision' do
+ let(:oldrev) { 'HEAD~3' }
+ let(:newrev) { '123456' }
+
+ it { is_expected.to be_force_push }
+ end
+ end
+
+ describe '#branch_added?' do
+ context 'when old revision is defined' do
+ it { is_expected.not_to be_branch_added }
+ end
+
+ context 'when old revision is not defined' do
+ let(:oldrev) { Gitlab::Git::BLANK_SHA }
+
+ it { is_expected.to be_branch_added }
+ end
+ end
+
+ describe '#branch_removed?' do
+ context 'when new revision is defined' do
+ it { is_expected.not_to be_branch_removed }
+ end
+
+ context 'when new revision is not defined' do
+ let(:newrev) { Gitlab::Git::BLANK_SHA }
+
+ it { is_expected.to be_branch_removed }
+ end
+ end
+
+ describe '#modified_paths' do
+ context 'when a push is a branch update' do
+ let(:newrev) { '498214d' }
+ let(:oldrev) { '281d3a7' }
+
+ it 'returns modified paths' do
+ expect(subject.modified_paths).to eq ['bar/branch-test.txt',
+ 'files/js/commit.coffee',
+ 'with space/README.md']
+ end
+ end
+
+ context 'when a push is not a branch update' do
+ let(:oldrev) { Gitlab::Git::BLANK_SHA }
+
+ it 'raises an error' do
+ expect { subject.modified_paths }.to raise_error(ArgumentError)
+ end
+ end
+ end
+
+ describe '#oldrev' do
+ context 'when a valid oldrev is provided' do
+ it 'returns oldrev' do
+ expect(subject.oldrev).to eq oldrev
+ end
+ end
+
+ context 'when a nil valud is provided' do
+ let(:oldrev) { nil }
+
+ it 'returns blank SHA' do
+ expect(subject.oldrev).to eq Gitlab::Git::BLANK_SHA
+ end
+ end
+ end
+
+ describe '#newrev' do
+ context 'when valid newrev is provided' do
+ it 'returns newrev' do
+ expect(subject.newrev).to eq newrev
+ end
+ end
+
+ context 'when a nil valud is provided' do
+ let(:newrev) { nil }
+
+ it 'returns blank SHA' do
+ expect(subject.newrev).to eq Gitlab::Git::BLANK_SHA
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/git/remote_mirror_spec.rb b/spec/lib/gitlab/git/remote_mirror_spec.rb
new file mode 100644
index 00000000000..dc63eef7814
--- /dev/null
+++ b/spec/lib/gitlab/git/remote_mirror_spec.rb
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+describe Gitlab::Git::RemoteMirror do
+ describe '#update' do
+ let(:project) { create(:project, :repository) }
+ let(:repository) { project.repository }
+ let(:ref_name) { 'foo' }
+ let(:options) { { only_branches_matching: ['master'], ssh_key: 'KEY', known_hosts: 'KNOWN HOSTS' } }
+
+ subject(:remote_mirror) { described_class.new(repository, ref_name, **options) }
+
+ it 'delegates to the Gitaly client' do
+ expect(repository.gitaly_remote_client)
+ .to receive(:update_remote_mirror)
+ .with(ref_name, ['master'], ssh_key: 'KEY', known_hosts: 'KNOWN HOSTS')
+
+ remote_mirror.update
+ end
+
+ it 'wraps gitaly errors' do
+ expect(repository.gitaly_remote_client)
+ .to receive(:update_remote_mirror)
+ .and_raise(StandardError)
+
+ expect { remote_mirror.update }.to raise_error(StandardError)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index d02536a2fb4..852ee9c96af 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -19,7 +19,10 @@ describe Gitlab::Git::Repository, :seed_helper do
end
end
+ let(:mutable_repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
+ let(:repository_path) { File.join(TestEnv.repos_path, repository.relative_path) }
+ let(:repository_rugged) { Rugged::Repository.new(repository_path) }
let(:storage_path) { TestEnv.repos_path }
let(:user) { build(:user) }
@@ -71,7 +74,6 @@ describe Gitlab::Git::Repository, :seed_helper do
describe "Respond to" do
subject { repository }
- it { is_expected.to respond_to(:rugged) }
it { is_expected.to respond_to(:root_ref) }
it { is_expected.to respond_to(:tags) }
end
@@ -91,57 +93,6 @@ describe Gitlab::Git::Repository, :seed_helper do
end
end
- describe "#rugged" do
- describe 'when storage is broken', :broken_storage do
- it 'raises a storage exception when storage is not available' do
- broken_repo = described_class.new('broken', 'a/path.git', '')
-
- expect { broken_repo.rugged }.to raise_error(Gitlab::Git::Storage::Inaccessible)
- end
- end
-
- it 'raises a no repository exception when there is no repo' do
- broken_repo = described_class.new('default', 'a/path.git', '')
-
- expect do
- Gitlab::GitalyClient::StorageSettings.allow_disk_access { broken_repo.rugged }
- end.to raise_error(Gitlab::Git::Repository::NoRepository)
- end
-
- describe 'alternates keyword argument' do
- context 'with no Git env stored' do
- before do
- allow(Gitlab::Git::HookEnv).to receive(:all).and_return({})
- end
-
- it "is passed an empty array" do
- expect(Rugged::Repository).to receive(:new).with(repository_path, alternates: [])
-
- repository_rugged
- end
- end
-
- context 'with absolute and relative Git object dir envvars stored' do
- before do
- allow(Gitlab::Git::HookEnv).to receive(:all).and_return({
- 'GIT_OBJECT_DIRECTORY_RELATIVE' => './objects/foo',
- 'GIT_ALTERNATE_OBJECT_DIRECTORIES_RELATIVE' => ['./objects/bar', './objects/baz'],
- 'GIT_OBJECT_DIRECTORY' => 'ignored',
- 'GIT_ALTERNATE_OBJECT_DIRECTORIES' => %w[ignored ignored],
- 'GIT_OTHER' => 'another_env'
- })
- end
-
- it "is passed the relative object dir envvars after being converted to absolute ones" do
- alternates = %w[foo bar baz].map { |d| File.join(repository_path, './objects', d) }
- expect(Rugged::Repository).to receive(:new).with(repository_path, alternates: alternates)
-
- repository_rugged
- end
- end
- end
- end
-
describe '#branch_names' do
subject { repository.branch_names }
@@ -284,7 +235,6 @@ describe Gitlab::Git::Repository, :seed_helper do
end
describe '#submodule_url_for' do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
let(:ref) { 'master' }
def submodule_url(path)
@@ -336,7 +286,7 @@ describe Gitlab::Git::Repository, :seed_helper do
it { expect(repository.has_local_branches?).to eq(true) }
context 'mutable' do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
+ let(:repository) { mutable_repository }
after do
ensure_seeds
@@ -369,7 +319,7 @@ describe Gitlab::Git::Repository, :seed_helper do
end
describe "#delete_branch" do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
+ let(:repository) { mutable_repository }
after do
ensure_seeds
@@ -393,7 +343,7 @@ describe Gitlab::Git::Repository, :seed_helper do
end
describe "#create_branch" do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
+ let(:repository) { mutable_repository }
after do
ensure_seeds
@@ -418,39 +368,33 @@ describe Gitlab::Git::Repository, :seed_helper do
end
describe '#delete_refs' do
- let(:repo) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
-
- def repo_rugged
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- repo.rugged
- end
- end
+ let(:repository) { mutable_repository }
after do
ensure_seeds
end
it 'deletes the ref' do
- repo.delete_refs('refs/heads/feature')
+ repository.delete_refs('refs/heads/feature')
- expect(repo_rugged.references['refs/heads/feature']).to be_nil
+ expect(repository_rugged.references['refs/heads/feature']).to be_nil
end
it 'deletes all refs' do
refs = %w[refs/heads/wip refs/tags/v1.1.0]
- repo.delete_refs(*refs)
+ repository.delete_refs(*refs)
refs.each do |ref|
- expect(repo_rugged.references[ref]).to be_nil
+ expect(repository_rugged.references[ref]).to be_nil
end
end
it 'does not fail when deleting an empty list of refs' do
- expect { repo.delete_refs(*[]) }.not_to raise_error
+ expect { repository.delete_refs(*[]) }.not_to raise_error
end
it 'raises an error if it failed' do
- expect { repo.delete_refs('refs\heads\fix') }.to raise_error(Gitlab::Git::Repository::GitError)
+ expect { repository.delete_refs('refs\heads\fix') }.to raise_error(Gitlab::Git::Repository::GitError)
end
end
@@ -528,9 +472,28 @@ describe Gitlab::Git::Repository, :seed_helper do
end
def new_repository_path
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- new_repository.path
- end
+ File.join(TestEnv.repos_path, new_repository.relative_path)
+ end
+ end
+
+ describe '#fetch_remote' do
+ it 'delegates to the gitaly RepositoryService' do
+ ssh_auth = double(:ssh_auth)
+ expected_opts = {
+ ssh_auth: ssh_auth,
+ forced: true,
+ no_tags: true,
+ timeout: described_class::GITLAB_PROJECTS_TIMEOUT,
+ prune: false
+ }
+
+ expect(repository.gitaly_repository_client).to receive(:fetch_remote).with('remote-name', expected_opts)
+
+ repository.fetch_remote('remote-name', ssh_auth: ssh_auth, forced: true, no_tags: true, prune: false)
+ end
+
+ it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::RepositoryService, :fetch_remote do
+ subject { repository.fetch_remote('remote-name') }
end
end
@@ -577,18 +540,16 @@ describe Gitlab::Git::Repository, :seed_helper do
Gitlab::Git::Commit.find(repository, @rename_commit_id)
end
- before(:context) do
+ before do
# Add new commits so that there's a renamed file in the commit history
- repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '').rugged
- @commit_with_old_name_id = new_commit_edit_old_file(repo).oid
- @rename_commit_id = new_commit_move_file(repo).oid
- @commit_with_new_name_id = new_commit_edit_new_file(repo).oid
+ @commit_with_old_name_id = new_commit_edit_old_file(repository_rugged).oid
+ @rename_commit_id = new_commit_move_file(repository_rugged).oid
+ @commit_with_new_name_id = new_commit_edit_new_file(repository_rugged).oid
end
- after(:context) do
+ after do
# Erase our commits so other tests get the original repo
- repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '').rugged
- repo.references.update("refs/heads/master", SeedRepo::LastCommit::ID)
+ repository_rugged.references.update("refs/heads/master", SeedRepo::LastCommit::ID)
end
context "where 'follow' == true" do
@@ -1010,12 +971,10 @@ describe Gitlab::Git::Repository, :seed_helper do
subject { repository.branches }
context 'with local and remote branches' do
- let(:repository) do
- Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
- end
+ let(:repository) { mutable_repository }
before do
- create_remote_branch(repository, 'joe', 'remote_branch', 'master')
+ create_remote_branch('joe', 'remote_branch', 'master')
repository.create_branch('local_branch', 'master')
end
@@ -1038,12 +997,10 @@ describe Gitlab::Git::Repository, :seed_helper do
end
context 'with local and remote branches' do
- let(:repository) do
- Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
- end
+ let(:repository) { mutable_repository }
before do
- create_remote_branch(repository, 'joe', 'remote_branch', 'master')
+ create_remote_branch('joe', 'remote_branch', 'master')
repository.create_branch('local_branch', 'master')
end
@@ -1138,12 +1095,26 @@ describe Gitlab::Git::Repository, :seed_helper do
end
it 'returns no Gitaly::DiffStats when there is a nil SHA' do
+ expect_any_instance_of(Gitlab::GitalyClient::CommitService)
+ .not_to receive(:diff_stats)
+
collection = repository.diff_stats(nil, 'master')
expect(collection).to be_a(Gitlab::Git::DiffStatsCollection)
expect(collection).to be_a(Enumerable)
expect(collection.to_a).to be_empty
end
+
+ it 'returns no Gitaly::DiffStats when there is a BLANK_SHA' do
+ expect_any_instance_of(Gitlab::GitalyClient::CommitService)
+ .not_to receive(:diff_stats)
+
+ collection = repository.diff_stats(Gitlab::Git::BLANK_SHA, 'master')
+
+ expect(collection).to be_a(Gitlab::Git::DiffStatsCollection)
+ expect(collection).to be_a(Enumerable)
+ expect(collection.to_a).to be_empty
+ end
end
describe "#ls_files" do
@@ -1258,6 +1229,34 @@ describe Gitlab::Git::Repository, :seed_helper do
end
end
+ describe '#gitattribute' do
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_GITATTRIBUTES_REPO_PATH, '') }
+
+ after do
+ ensure_seeds
+ end
+
+ it 'returns matching language attribute' do
+ expect(repository.gitattribute("custom-highlighting/test.gitlab-custom", 'gitlab-language')).to eq('ruby')
+ end
+
+ it 'returns matching language attribute with additional options' do
+ expect(repository.gitattribute("custom-highlighting/test.gitlab-cgi", 'gitlab-language')).to eq('erb?parent=json')
+ end
+
+ it 'returns nil if nothing matches' do
+ expect(repository.gitattribute("report.xslt", 'gitlab-language')).to eq(nil)
+ end
+
+ context 'without gitattributes file' do
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
+
+ it 'returns nil' do
+ expect(repository.gitattribute("README.md", 'gitlab-language')).to eq(nil)
+ end
+ end
+ end
+
describe '#ref_exists?' do
it 'returns true for an existing tag' do
expect(repository.ref_exists?('refs/heads/master')).to eq(true)
@@ -1303,24 +1302,24 @@ describe Gitlab::Git::Repository, :seed_helper do
end
describe '#local_branches' do
- before(:all) do
- @repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
+ let(:repository) { mutable_repository }
+
+ before do
+ create_remote_branch('joe', 'remote_branch', 'master')
+ repository.create_branch('local_branch', 'master')
end
- after(:all) do
+ after do
ensure_seeds
end
it 'returns the local branches' do
- create_remote_branch(@repo, 'joe', 'remote_branch', 'master')
- @repo.create_branch('local_branch', 'master')
-
- expect(@repo.local_branches.any? { |branch| branch.name == 'remote_branch' }).to eq(false)
- expect(@repo.local_branches.any? { |branch| branch.name == 'local_branch' }).to eq(true)
+ expect(repository.local_branches.any? { |branch| branch.name == 'remote_branch' }).to eq(false)
+ expect(repository.local_branches.any? { |branch| branch.name == 'local_branch' }).to eq(true)
end
it 'returns a Branch with UTF-8 fields' do
- branches = @repo.local_branches.to_a
+ branches = repository.local_branches.to_a
expect(branches.size).to be > 0
branches.each do |branch|
expect(branch.name).to be_utf8
@@ -1331,11 +1330,11 @@ describe Gitlab::Git::Repository, :seed_helper do
it 'gets the branches from GitalyClient' do
expect_any_instance_of(Gitlab::GitalyClient::RefService).to receive(:local_branches)
.and_return([])
- @repo.local_branches
+ repository.local_branches
end
it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::RefService, :local_branches do
- subject { @repo.local_branches }
+ subject { repository.local_branches }
end
end
@@ -1391,8 +1390,7 @@ describe Gitlab::Git::Repository, :seed_helper do
describe '#fetch_source_branch!' do
let(:local_ref) { 'refs/merge-requests/1/head' }
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
- let(:source_repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
+ let(:source_repository) { mutable_repository }
after do
ensure_seeds
@@ -1401,7 +1399,8 @@ describe Gitlab::Git::Repository, :seed_helper do
context 'when the branch exists' do
context 'when the commit does not exist locally' do
let(:source_branch) { 'new-branch-for-fetch-source-branch' }
- let(:source_rugged) { Gitlab::GitalyClient::StorageSettings.allow_disk_access { source_repository.rugged } }
+ let(:source_path) { File.join(TestEnv.repos_path, source_repository.relative_path) }
+ let(:source_rugged) { Rugged::Repository.new(source_path) }
let(:new_oid) { new_commit_edit_old_file(source_rugged).oid }
before do
@@ -1470,6 +1469,19 @@ describe Gitlab::Git::Repository, :seed_helper do
end
end
end
+
+ it 'writes the HEAD' do
+ repository.write_ref('HEAD', 'refs/heads/feature')
+
+ expect(repository.commit('HEAD')).to eq(repository.commit('feature'))
+ expect(repository.root_ref).to eq('feature')
+ end
+
+ it 'writes other refs' do
+ repository.write_ref('refs/heads/feature', SeedRepo::Commit::ID)
+
+ expect(repository.commit('feature').sha).to eq(SeedRepo::Commit::ID)
+ end
end
describe '#write_config' do
@@ -1513,8 +1525,7 @@ describe Gitlab::Git::Repository, :seed_helper do
end
describe '#set_config' do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
- let(:rugged) { repository_rugged }
+ let(:repository) { mutable_repository }
let(:entries) do
{
'test.foo1' => 'bla bla',
@@ -1526,19 +1537,18 @@ describe Gitlab::Git::Repository, :seed_helper do
it 'can set config settings' do
expect(repository.set_config(entries)).to be_nil
- expect(rugged.config['test.foo1']).to eq('bla bla')
- expect(rugged.config['test.foo2']).to eq('1234')
- expect(rugged.config['test.foo3']).to eq('true')
+ expect(repository_rugged.config['test.foo1']).to eq('bla bla')
+ expect(repository_rugged.config['test.foo2']).to eq('1234')
+ expect(repository_rugged.config['test.foo3']).to eq('true')
end
after do
- entries.keys.each { |k| rugged.config.delete(k) }
+ entries.keys.each { |k| repository_rugged.config.delete(k) }
end
end
describe '#delete_config' do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '') }
- let(:rugged) { repository_rugged }
+ let(:repository) { mutable_repository }
let(:entries) do
{
'test.foo1' => 'bla bla',
@@ -1549,21 +1559,19 @@ describe Gitlab::Git::Repository, :seed_helper do
it 'can delete config settings' do
entries.each do |key, value|
- rugged.config[key] = value
+ repository_rugged.config[key] = value
end
expect(repository.delete_config(*%w[does.not.exist test.foo1 test.foo2])).to be_nil
- config_keys = rugged.config.each_key.to_a
+ config_keys = repository_rugged.config.each_key.to_a
expect(config_keys).not_to include('test.foo1')
expect(config_keys).not_to include('test.foo2')
end
end
describe '#merge' do
- let(:repository) do
- Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
- end
+ let(:repository) { mutable_repository }
let(:source_sha) { '913c66a37b4a45b9769037c55c2d238bd0942d2e' }
let(:target_branch) { 'test-merge-target-branch' }
@@ -1602,9 +1610,7 @@ describe Gitlab::Git::Repository, :seed_helper do
end
describe '#ff_merge' do
- let(:repository) do
- Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
- end
+ let(:repository) { mutable_repository }
let(:branch_head) { '6d394385cf567f80a8fd85055db1ab4c5295806f' }
let(:source_sha) { 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660' }
let(:target_branch) { 'test-ff-target-branch' }
@@ -1667,9 +1673,7 @@ describe Gitlab::Git::Repository, :seed_helper do
end
describe '#delete_all_refs_except' do
- let(:repository) do
- Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
- end
+ let(:repository) { mutable_repository }
before do
repository.write_ref("refs/delete/a", "0b4bc9a49b562e85de7cc9e834518ea6828729b9")
@@ -1693,12 +1697,7 @@ describe Gitlab::Git::Repository, :seed_helper do
end
describe 'remotes' do
- let(:repository) do
- Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
- end
- let(:rugged) do
- Gitlab::GitalyClient::StorageSettings.allow_disk_access { repository.rugged }
- end
+ let(:repository) { mutable_repository }
let(:remote_name) { 'my-remote' }
let(:url) { 'http://my-repo.git' }
@@ -1711,26 +1710,26 @@ describe Gitlab::Git::Repository, :seed_helper do
it 'added the remote' do
begin
- rugged.remotes.delete(remote_name)
+ repository_rugged.remotes.delete(remote_name)
rescue Rugged::ConfigError
end
repository.add_remote(remote_name, url, mirror_refmap: mirror_refmap)
- expect(rugged.remotes[remote_name]).not_to be_nil
- expect(rugged.config["remote.#{remote_name}.mirror"]).to eq('true')
- expect(rugged.config["remote.#{remote_name}.prune"]).to eq('true')
- expect(rugged.config["remote.#{remote_name}.fetch"]).to eq(mirror_refmap)
+ expect(repository_rugged.remotes[remote_name]).not_to be_nil
+ expect(repository_rugged.config["remote.#{remote_name}.mirror"]).to eq('true')
+ expect(repository_rugged.config["remote.#{remote_name}.prune"]).to eq('true')
+ expect(repository_rugged.config["remote.#{remote_name}.fetch"]).to eq(mirror_refmap)
end
end
describe '#remove_remote' do
it 'removes the remote' do
- rugged.remotes.create(remote_name, url)
+ repository_rugged.remotes.create(remote_name, url)
repository.remove_remote(remote_name)
- expect(rugged.remotes[remote_name]).to be_nil
+ expect(repository_rugged.remotes[remote_name]).to be_nil
end
end
end
@@ -1901,13 +1900,11 @@ describe Gitlab::Git::Repository, :seed_helper do
end
context 'when the diff contains a rename' do
- let(:repo) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '').rugged }
- let(:end_sha) { new_commit_move_file(repo).oid }
+ let(:end_sha) { new_commit_move_file(repository_rugged).oid }
after do
# Erase our commits so other tests get the original repo
- repo = Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '').rugged
- repo.references.update('refs/heads/master', SeedRepo::LastCommit::ID)
+ repository_rugged.references.update('refs/heads/master', SeedRepo::LastCommit::ID)
end
it 'does not include the renamed file in the sparse checkout' do
@@ -1954,10 +1951,9 @@ describe Gitlab::Git::Repository, :seed_helper do
end
end
- def create_remote_branch(repository, remote_name, branch_name, source_branch_name)
+ def create_remote_branch(remote_name, branch_name, source_branch_name)
source_branch = repository.branches.find { |branch| branch.name == source_branch_name }
- rugged = repository_rugged
- rugged.references.create("refs/remotes/#{remote_name}/#{branch_name}", source_branch.dereferenced_target.sha)
+ repository_rugged.references.create("refs/remotes/#{remote_name}/#{branch_name}", source_branch.dereferenced_target.sha)
end
# Build the options hash that's passed to Rugged::Commit#create
@@ -2035,16 +2031,4 @@ describe Gitlab::Git::Repository, :seed_helper do
line.split("\t").last
end
end
-
- def repository_rugged
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- repository.rugged
- end
- end
-
- def repository_path
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- repository.path
- end
- end
end
diff --git a/spec/lib/gitlab/git/storage/checker_spec.rb b/spec/lib/gitlab/git/storage/checker_spec.rb
deleted file mode 100644
index d74c3bcb04c..00000000000
--- a/spec/lib/gitlab/git/storage/checker_spec.rb
+++ /dev/null
@@ -1,132 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Git::Storage::Checker, :clean_gitlab_redis_shared_state do
- let(:storage_name) { 'default' }
- let(:hostname) { Gitlab::Environment.hostname }
- let(:cache_key) { "storage_accessible:#{storage_name}:#{hostname}" }
-
- subject(:checker) { described_class.new(storage_name) }
-
- def value_from_redis(name)
- Gitlab::Git::Storage.redis.with do |redis|
- redis.hmget(cache_key, name)
- end.first
- end
-
- def set_in_redis(name, value)
- Gitlab::Git::Storage.redis.with do |redis|
- redis.hmset(cache_key, name, value)
- end.first
- end
-
- describe '.check_all' do
- it 'calls a check for each storage' do
- fake_checker_default = double
- fake_checker_broken = double
- fake_logger = fake_logger
-
- expect(described_class).to receive(:new).with('default', fake_logger) { fake_checker_default }
- expect(described_class).to receive(:new).with('broken', fake_logger) { fake_checker_broken }
- expect(fake_checker_default).to receive(:check_with_lease)
- expect(fake_checker_broken).to receive(:check_with_lease)
-
- described_class.check_all(fake_logger)
- end
-
- context 'with broken storage', :broken_storage do
- it 'returns the results' do
- expected_result = [
- { storage: 'default', success: true },
- { storage: 'broken', success: false }
- ]
-
- expect(described_class.check_all).to eq(expected_result)
- end
- end
- end
-
- describe '#initialize' do
- it 'assigns the settings' do
- expect(checker.hostname).to eq(hostname)
- expect(checker.storage).to eq('default')
- expect(checker.storage_path).to eq(TestEnv.repos_path)
- end
- end
-
- describe '#check_with_lease' do
- it 'only allows one check at a time' do
- expect(checker).to receive(:check).once { sleep 1 }
-
- thread = Thread.new { checker.check_with_lease }
- checker.check_with_lease
- thread.join
- end
-
- it 'returns a result hash' do
- expect(checker.check_with_lease).to eq(storage: 'default', success: true)
- end
- end
-
- describe '#check' do
- it 'tracks that the storage was accessible' do
- set_in_redis(:failure_count, 10)
- set_in_redis(:last_failure, Time.now.to_f)
-
- checker.check
-
- expect(value_from_redis(:failure_count).to_i).to eq(0)
- expect(value_from_redis(:last_failure)).to be_empty
- expect(value_from_redis(:first_failure)).to be_empty
- end
-
- it 'calls the check with the correct arguments' do
- stub_application_setting(circuitbreaker_storage_timeout: 30,
- circuitbreaker_access_retries: 3)
-
- expect(Gitlab::Git::Storage::ForkedStorageCheck)
- .to receive(:storage_available?).with(TestEnv.repos_path, 30, 3)
- .and_call_original
-
- checker.check
- end
-
- it 'returns `true`' do
- expect(checker.check).to eq(true)
- end
-
- it 'maintains known storage keys' do
- Timecop.freeze do
- # Insert an old key to expire
- old_entry = Time.now.to_i - 3.days.to_i
- Gitlab::Git::Storage.redis.with do |redis|
- redis.zadd(Gitlab::Git::Storage::REDIS_KNOWN_KEYS, old_entry, 'to_be_removed')
- end
-
- checker.check
-
- known_keys = Gitlab::Git::Storage.redis.with do |redis|
- redis.zrange(Gitlab::Git::Storage::REDIS_KNOWN_KEYS, 0, -1)
- end
-
- expect(known_keys).to contain_exactly(cache_key)
- end
- end
-
- context 'the storage is not available', :broken_storage do
- let(:storage_name) { 'broken' }
-
- it 'tracks that the storage was inaccessible' do
- Timecop.freeze do
- expect { checker.check }.to change { value_from_redis(:failure_count).to_i }.by(1)
-
- expect(value_from_redis(:last_failure)).not_to be_empty
- expect(value_from_redis(:first_failure)).not_to be_empty
- end
- end
-
- it 'returns `false`' do
- expect(checker.check).to eq(false)
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb b/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb
deleted file mode 100644
index 210b90bfba9..00000000000
--- a/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb
+++ /dev/null
@@ -1,187 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Git::Storage::CircuitBreaker, :broken_storage do
- let(:storage_name) { 'default' }
- let(:circuit_breaker) { described_class.new(storage_name, hostname) }
- let(:hostname) { Gitlab::Environment.hostname }
- let(:cache_key) { "storage_accessible:#{storage_name}:#{hostname}" }
-
- def set_in_redis(name, value)
- Gitlab::Git::Storage.redis.with do |redis|
- redis.zadd(Gitlab::Git::Storage::REDIS_KNOWN_KEYS, 0, cache_key)
- redis.hmset(cache_key, name, value)
- end.first
- end
-
- before do
- # Override test-settings for the circuitbreaker with something more realistic
- # for these specs.
- stub_storage_settings('default' => {
- 'path' => TestEnv.repos_path
- },
- 'broken' => {
- 'path' => 'tmp/tests/non-existent-repositories'
- },
- 'nopath' => { 'path' => nil }
- )
- end
-
- describe '.for_storage', :request_store do
- it 'only builds a single circuitbreaker per storage' do
- expect(described_class).to receive(:new).once.and_call_original
-
- breaker = described_class.for_storage('default')
-
- expect(breaker).to be_a(described_class)
- expect(described_class.for_storage('default')).to eq(breaker)
- end
-
- it 'returns a broken circuit breaker for an unknown storage' do
- expect(described_class.for_storage('unknown').circuit_broken?).to be_truthy
- end
-
- it 'returns a broken circuit breaker when the path is not set' do
- expect(described_class.for_storage('nopath').circuit_broken?).to be_truthy
- end
- end
-
- describe '#initialize' do
- it 'assigns the settings' do
- expect(circuit_breaker.hostname).to eq(hostname)
- expect(circuit_breaker.storage).to eq('default')
- end
- end
-
- context 'circuitbreaker settings' do
- before do
- stub_application_setting(circuitbreaker_failure_count_threshold: 0,
- circuitbreaker_failure_wait_time: 1,
- circuitbreaker_failure_reset_time: 2,
- circuitbreaker_storage_timeout: 3,
- circuitbreaker_access_retries: 4,
- circuitbreaker_backoff_threshold: 5)
- end
-
- describe '#failure_count_threshold' do
- it 'reads the value from settings' do
- expect(circuit_breaker.failure_count_threshold).to eq(0)
- end
- end
-
- describe '#check_interval' do
- it 'reads the value from settings' do
- expect(circuit_breaker.check_interval).to eq(1)
- end
- end
-
- describe '#failure_reset_time' do
- it 'reads the value from settings' do
- expect(circuit_breaker.failure_reset_time).to eq(2)
- end
- end
-
- describe '#storage_timeout' do
- it 'reads the value from settings' do
- expect(circuit_breaker.storage_timeout).to eq(3)
- end
- end
-
- describe '#access_retries' do
- it 'reads the value from settings' do
- expect(circuit_breaker.access_retries).to eq(4)
- end
- end
- end
-
- describe '#perform' do
- it 'raises the correct exception when the circuit is open' do
- set_in_redis(:last_failure, 1.day.ago.to_f)
- set_in_redis(:failure_count, 999)
-
- expect { |b| circuit_breaker.perform(&b) }
- .to raise_error do |exception|
- expect(exception).to be_kind_of(Gitlab::Git::Storage::CircuitOpen)
- expect(exception.retry_after).to eq(1800)
- end
- end
-
- it 'yields the block' do
- expect { |b| circuit_breaker.perform(&b) }
- .to yield_control
- end
-
- it 'checks if the storage is available' do
- expect(circuit_breaker).to receive(:check_storage_accessible!)
- .and_call_original
-
- circuit_breaker.perform { 'hello world' }
- end
-
- it 'returns the value of the block' do
- result = circuit_breaker.perform { 'return value' }
-
- expect(result).to eq('return value')
- end
-
- it 'raises possible errors' do
- expect { circuit_breaker.perform { raise Rugged::OSError.new('Broken') } }
- .to raise_error(Rugged::OSError)
- end
-
- context 'with the feature disabled' do
- before do
- stub_feature_flags(git_storage_circuit_breaker: false)
- end
-
- it 'returns the block without checking accessibility' do
- expect(circuit_breaker).not_to receive(:check_storage_accessible!)
-
- result = circuit_breaker.perform { 'hello' }
-
- expect(result).to eq('hello')
- end
-
- it 'allows enabling the feature using an ENV var' do
- stub_env('GIT_STORAGE_CIRCUIT_BREAKER', 'true')
- expect(circuit_breaker).to receive(:check_storage_accessible!)
-
- result = circuit_breaker.perform { 'hello' }
-
- expect(result).to eq('hello')
- end
- end
- end
-
- describe '#circuit_broken?' do
- it 'is working when there is no last failure' do
- set_in_redis(:last_failure, nil)
- set_in_redis(:failure_count, 0)
-
- expect(circuit_breaker.circuit_broken?).to be_falsey
- end
-
- it 'is broken when there are too many failures' do
- set_in_redis(:last_failure, 1.day.ago.to_f)
- set_in_redis(:failure_count, 200)
-
- expect(circuit_breaker.circuit_broken?).to be_truthy
- end
- end
-
- describe '#last_failure' do
- it 'returns the last failure time' do
- time = Time.parse("2017-05-26 17:52:30")
- set_in_redis(:last_failure, time.to_i)
-
- expect(circuit_breaker.last_failure).to eq(time)
- end
- end
-
- describe '#failure_count' do
- it 'returns the failure count' do
- set_in_redis(:failure_count, 7)
-
- expect(circuit_breaker.failure_count).to eq(7)
- end
- end
-end
diff --git a/spec/lib/gitlab/git/storage/failure_info_spec.rb b/spec/lib/gitlab/git/storage/failure_info_spec.rb
deleted file mode 100644
index bae88fdda86..00000000000
--- a/spec/lib/gitlab/git/storage/failure_info_spec.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Git::Storage::FailureInfo, :broken_storage do
- let(:storage_name) { 'default' }
- let(:hostname) { Gitlab::Environment.hostname }
- let(:cache_key) { "storage_accessible:#{storage_name}:#{hostname}" }
-
- def value_from_redis(name)
- Gitlab::Git::Storage.redis.with do |redis|
- redis.hmget(cache_key, name)
- end.first
- end
-
- def set_in_redis(name, value)
- Gitlab::Git::Storage.redis.with do |redis|
- redis.zadd(Gitlab::Git::Storage::REDIS_KNOWN_KEYS, 0, cache_key)
- redis.hmset(cache_key, name, value)
- end.first
- end
-
- describe '.reset_all!' do
- it 'clears all entries form redis' do
- set_in_redis(:failure_count, 10)
-
- described_class.reset_all!
-
- key_exists = Gitlab::Git::Storage.redis.with { |redis| redis.exists(cache_key) }
-
- expect(key_exists).to be_falsey
- end
-
- it 'does not break when there are no keys in redis' do
- expect { described_class.reset_all! }.not_to raise_error
- end
- end
-
- describe '.load' do
- it 'loads failure information for a storage on a host' do
- first_failure = Time.parse("2017-11-14 17:52:30")
- last_failure = Time.parse("2017-11-14 18:54:37")
- failure_count = 11
-
- set_in_redis(:first_failure, first_failure.to_i)
- set_in_redis(:last_failure, last_failure.to_i)
- set_in_redis(:failure_count, failure_count.to_i)
-
- info = described_class.load(cache_key)
-
- expect(info.first_failure).to eq(first_failure)
- expect(info.last_failure).to eq(last_failure)
- expect(info.failure_count).to eq(failure_count)
- end
- end
-
- describe '#no_failures?' do
- it 'is true when there are no failures' do
- info = described_class.new(nil, nil, 0)
-
- expect(info.no_failures?).to be_truthy
- end
-
- it 'is false when there are failures' do
- info = described_class.new(Time.parse("2017-11-14 17:52:30"),
- Time.parse("2017-11-14 18:54:37"),
- 20)
-
- expect(info.no_failures?).to be_falsy
- end
- end
-end
diff --git a/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb b/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb
deleted file mode 100644
index 39a5d020bb4..00000000000
--- a/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Git::Storage::ForkedStorageCheck, broken_storage: true, skip_database_cleaner: true do
- let(:existing_path) do
- existing_path = TestEnv.repos_path
- FileUtils.mkdir_p(existing_path)
- existing_path
- end
-
- describe '.storage_accessible?' do
- it 'detects when a storage is not available' do
- expect(described_class.storage_available?('/non/existant/path')).to be_falsey
- end
-
- it 'detects when a storage is available' do
- expect(described_class.storage_available?(existing_path)).to be_truthy
- end
-
- it 'returns false when the check takes to long' do
- # We're forking a process here that takes too long
- # It will be killed it's parent process will be killed by it's parent
- # and waited for inside `Gitlab::Git::Storage::ForkedStorageCheck.timeout_check`
- allow(described_class).to receive(:check_filesystem_in_process) do
- Process.spawn("sleep 10")
- end
- result = true
-
- runtime = Benchmark.realtime do
- result = described_class.storage_available?(existing_path, 0.5)
- end
-
- expect(result).to be_falsey
- expect(runtime).to be < 1.0
- end
-
- it 'will try the specified amount of times before failing' do
- allow(described_class).to receive(:check_filesystem_in_process) do
- Process.spawn("sleep 10")
- end
-
- expect(Process).to receive(:spawn).with('sleep 10').twice
- .and_call_original
-
- runtime = Benchmark.realtime do
- described_class.storage_available?(existing_path, 0.5, 2)
- end
-
- expect(runtime).to be < 1.0
- end
-
- describe 'when using paths with spaces' do
- let(:test_dir) { Rails.root.join('tmp', 'tests', 'storage_check') }
- let(:path_with_spaces) { File.join(test_dir, 'path with spaces') }
-
- around do |example|
- FileUtils.mkdir_p(path_with_spaces)
- example.run
- FileUtils.rm_r(test_dir)
- end
-
- it 'works for paths with spaces' do
- expect(described_class.storage_available?(path_with_spaces)).to be_truthy
- end
-
- it 'works for a realpath with spaces' do
- symlink_location = File.join(test_dir, 'a symlink')
- FileUtils.ln_s(path_with_spaces, symlink_location)
-
- expect(described_class.storage_available?(symlink_location)).to be_truthy
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/git/storage/health_spec.rb b/spec/lib/gitlab/git/storage/health_spec.rb
deleted file mode 100644
index bb670fc5d94..00000000000
--- a/spec/lib/gitlab/git/storage/health_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Git::Storage::Health, broken_storage: true do
- let(:host1_key) { 'storage_accessible:broken:web01' }
- let(:host2_key) { 'storage_accessible:default:kiq01' }
-
- def set_in_redis(cache_key, value)
- Gitlab::Git::Storage.redis.with do |redis|
- redis.zadd(Gitlab::Git::Storage::REDIS_KNOWN_KEYS, 0, cache_key)
- redis.hmset(cache_key, :failure_count, value)
- end.first
- end
-
- describe '.for_failing_storages' do
- it 'only includes health status for failures' do
- set_in_redis(host1_key, 10)
- set_in_redis(host2_key, 0)
-
- expect(described_class.for_failing_storages.map(&:storage_name))
- .to contain_exactly('broken')
- end
- end
-
- describe '.for_all_storages' do
- it 'loads health status for all configured storages' do
- healths = described_class.for_all_storages
-
- expect(healths.map(&:storage_name)).to contain_exactly('default', 'broken')
- end
- end
-
- describe '#failing_info' do
- it 'only contains storages that have failures' do
- health = described_class.new('broken', [{ name: host1_key, failure_count: 0 },
- { name: host2_key, failure_count: 3 }])
-
- expect(health.failing_info).to contain_exactly({ name: host2_key, failure_count: 3 })
- end
- end
-
- describe '#total_failures' do
- it 'sums up all the failures' do
- health = described_class.new('broken', [{ name: host1_key, failure_count: 2 },
- { name: host2_key, failure_count: 3 }])
-
- expect(health.total_failures).to eq(5)
- end
- end
-
- describe '#failing_on_hosts' do
- it 'collects only the failing hostnames' do
- health = described_class.new('broken', [{ name: host1_key, failure_count: 2 },
- { name: host2_key, failure_count: 0 }])
-
- expect(health.failing_on_hosts).to contain_exactly('web01')
- end
- end
-end
diff --git a/spec/lib/gitlab/git/storage/null_circuit_breaker_spec.rb b/spec/lib/gitlab/git/storage/null_circuit_breaker_spec.rb
deleted file mode 100644
index 93ad20011de..00000000000
--- a/spec/lib/gitlab/git/storage/null_circuit_breaker_spec.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::Git::Storage::NullCircuitBreaker do
- let(:storage) { 'default' }
- let(:hostname) { 'localhost' }
- let(:error) { nil }
-
- subject(:breaker) { described_class.new(storage, hostname, error: error) }
-
- context 'with an error' do
- let(:error) { Gitlab::Git::Storage::Misconfiguration.new('error') }
-
- describe '#perform' do
- it { expect { breaker.perform { 'ok' } }.to raise_error(error) }
- end
-
- describe '#circuit_broken?' do
- it { expect(breaker.circuit_broken?).to be_truthy }
- end
-
- describe '#last_failure' do
- it { Timecop.freeze { expect(breaker.last_failure).to eq(Time.now) } }
- end
-
- describe '#failure_count' do
- it { expect(breaker.failure_count).to eq(breaker.failure_count_threshold) }
- end
-
- describe '#failure_info' do
- it { expect(breaker.failure_info.no_failures?).to be_falsy }
- end
- end
-
- context 'not broken' do
- describe '#perform' do
- it { expect(breaker.perform { 'ok' }).to eq('ok') }
- end
-
- describe '#circuit_broken?' do
- it { expect(breaker.circuit_broken?).to be_falsy }
- end
-
- describe '#last_failure' do
- it { expect(breaker.last_failure).to be_nil }
- end
-
- describe '#failure_count' do
- it { expect(breaker.failure_count).to eq(0) }
- end
-
- describe '#failure_info' do
- it { expect(breaker.failure_info.no_failures?).to be_truthy }
- end
- end
-
- describe '#failure_count_threshold' do
- before do
- stub_application_setting(circuitbreaker_failure_count_threshold: 1)
- end
-
- it { expect(breaker.failure_count_threshold).to eq(1) }
- end
-
- it 'implements the CircuitBreaker interface' do
- ours = described_class.public_instance_methods
- theirs = Gitlab::Git::Storage::CircuitBreaker.public_instance_methods
-
- expect(theirs - ours).to be_empty
- end
-end
diff --git a/spec/lib/gitlab/git/tag_spec.rb b/spec/lib/gitlab/git/tag_spec.rb
index 2d9db576a6c..b51e3879f49 100644
--- a/spec/lib/gitlab/git/tag_spec.rb
+++ b/spec/lib/gitlab/git/tag_spec.rb
@@ -3,7 +3,7 @@ require "spec_helper"
describe Gitlab::Git::Tag, :seed_helper do
let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
- shared_examples 'Gitlab::Git::Repository#tags' do
+ describe '#tags' do
describe 'first tag' do
let(:tag) { repository.tags.first }
@@ -25,14 +25,6 @@ describe Gitlab::Git::Tag, :seed_helper do
it { expect(repository.tags.size).to eq(SeedRepo::Repo::TAGS.size) }
end
- context 'when Gitaly tags feature is enabled' do
- it_behaves_like 'Gitlab::Git::Repository#tags'
- end
-
- context 'when Gitaly tags feature is disabled', :skip_gitaly_mock do
- it_behaves_like 'Gitlab::Git::Repository#tags'
- end
-
describe '.get_message' do
let(:tag_ids) { %w[f4e6814c3e4e7a0de82a9e7cd20c626cc963a2f8 8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b] }
@@ -40,23 +32,16 @@ describe Gitlab::Git::Tag, :seed_helper do
tag_ids.map { |id| described_class.get_message(repository, id) }
end
- shared_examples 'getting tag messages' do
- it 'gets tag messages' do
- expect(subject[0]).to eq("Release\n")
- expect(subject[1]).to eq("Version 1.1.0\n")
- end
+ it 'gets tag messages' do
+ expect(subject[0]).to eq("Release\n")
+ expect(subject[1]).to eq("Version 1.1.0\n")
end
- context 'when Gitaly tag_messages feature is enabled' do
- it_behaves_like 'getting tag messages'
-
- it 'gets messages in one batch', :request_store do
- expect { subject.map(&:itself) }.to change { Gitlab::GitalyClient.get_request_count }.by(1)
- end
- end
+ it 'gets messages in one batch', :request_store do
+ other_repository = double(:repository)
+ described_class.get_message(other_repository, tag_ids.first)
- context 'when Gitaly tag_messages feature is disabled', :disable_gitaly do
- it_behaves_like 'getting tag messages'
+ expect { subject.map(&:itself) }.to change { Gitlab::GitalyClient.get_request_count }.by(1)
end
end
@@ -68,7 +53,7 @@ describe Gitlab::Git::Tag, :seed_helper do
context 'message_size less than threshold' do
let(:message_size) { 123 }
- it 'fetches tag message seperately' do
+ it 'fetches tag message separately' do
expect(described_class).to receive(:get_message).with(repository, gitaly_tag.id)
tag.message
diff --git a/spec/lib/gitlab/git/tree_spec.rb b/spec/lib/gitlab/git/tree_spec.rb
index 3792d6bf67b..bec875fb03d 100644
--- a/spec/lib/gitlab/git/tree_spec.rb
+++ b/spec/lib/gitlab/git/tree_spec.rb
@@ -80,18 +80,8 @@ describe Gitlab::Git::Tree, :seed_helper do
end
describe '#where' do
- shared_examples '#where' do
- it 'returns an empty array when called with an invalid ref' do
- expect(described_class.where(repository, 'foobar-does-not-exist')).to eq([])
- end
- end
-
- context 'with gitaly' do
- it_behaves_like '#where'
- end
-
- context 'without gitaly', :skip_gitaly_mock do
- it_behaves_like '#where'
+ it 'returns an empty array when called with an invalid ref' do
+ expect(described_class.where(repository, 'foobar-does-not-exist')).to eq([])
end
end
end
diff --git a/spec/lib/gitlab/git/wiki_spec.rb b/spec/lib/gitlab/git/wiki_spec.rb
index c5666e4ec61..ded5d7576df 100644
--- a/spec/lib/gitlab/git/wiki_spec.rb
+++ b/spec/lib/gitlab/git/wiki_spec.rb
@@ -1,10 +1,13 @@
require 'spec_helper'
describe Gitlab::Git::Wiki do
+ using RSpec::Parameterized::TableSyntax
+
let(:project) { create(:project) }
let(:user) { project.owner }
let(:project_wiki) { ProjectWiki.new(project, user) }
- subject { project_wiki.wiki }
+
+ subject(:wiki) { project_wiki.wiki }
describe '#pages' do
before do
@@ -64,8 +67,44 @@ describe Gitlab::Git::Wiki do
end
end
- def create_page(name, content)
- subject.write_page(name, :markdown, content, commit_details(name))
+ describe '#preview_slug' do
+ where(:title, :format, :expected_slug) do
+ 'The Best Thing' | :markdown | 'The-Best-Thing'
+ 'The Best Thing' | :md | 'The-Best-Thing'
+ 'The Best Thing' | :txt | 'The-Best-Thing'
+ 'A Subject/Title Here' | :txt | 'A-Subject/Title-Here'
+ 'A subject' | :txt | 'A-subject'
+ 'A 1/B 2/C 3' | :txt | 'A-1/B-2/C-3'
+ 'subject/title' | :txt | 'subject/title'
+ 'subject/title.md' | :txt | 'subject/title.md'
+ 'foo<bar>+baz' | :txt | 'foo-bar--baz'
+ 'foo%2Fbar' | :txt | 'foo%2Fbar'
+ '' | :markdown | '.md'
+ '' | :md | '.md'
+ '' | :txt | '.txt'
+ end
+
+ with_them do
+ subject { wiki.preview_slug(title, format) }
+
+ let(:gitaly_slug) { wiki.pages.first }
+
+ it { is_expected.to eq(expected_slug) }
+
+ it 'matches the slug generated by gitaly' do
+ skip('Gitaly cannot generate a slug for an empty title') unless title.present?
+
+ create_page(title, 'content', format: format)
+
+ gitaly_slug = wiki.pages.first.url_path
+
+ is_expected.to eq(gitaly_slug)
+ end
+ end
+ end
+
+ def create_page(name, content, format: :markdown)
+ wiki.write_page(name, format, content, commit_details(name))
end
def commit_details(name)
@@ -73,7 +112,7 @@ describe Gitlab::Git::Wiki do
end
def destroy_page(title, dir = '')
- page = subject.page(title: title, dir: dir)
+ page = wiki.page(title: title, dir: dir)
project_wiki.delete_page(page, "test commit")
end
end
diff --git a/spec/lib/gitlab/git/wraps_gitaly_errors_spec.rb b/spec/lib/gitlab/git/wraps_gitaly_errors_spec.rb
new file mode 100644
index 00000000000..bcf4814edb6
--- /dev/null
+++ b/spec/lib/gitlab/git/wraps_gitaly_errors_spec.rb
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+describe Gitlab::Git::WrapsGitalyErrors do
+ subject(:wrapper) do
+ klazz = Class.new { include Gitlab::Git::WrapsGitalyErrors }
+ klazz.new
+ end
+
+ describe "#wrapped_gitaly_errors" do
+ mapping = {
+ GRPC::NotFound => Gitlab::Git::Repository::NoRepository,
+ GRPC::InvalidArgument => ArgumentError,
+ GRPC::BadStatus => Gitlab::Git::CommandError
+ }
+
+ mapping.each do |grpc_error, error|
+ it "wraps #{grpc_error} in a #{error}" do
+ expect { wrapper.wrapped_gitaly_errors { raise grpc_error.new('wrapped') } }
+ .to raise_error(error)
+ end
+ end
+
+ it 'does not swallow other errors' do
+ expect { wrapper.wrapped_gitaly_errors { raise 'raised' } }
+ .to raise_error(RuntimeError)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb
index dbd64c4bec0..a417ef77c9e 100644
--- a/spec/lib/gitlab/git_access_spec.rb
+++ b/spec/lib/gitlab/git_access_spec.rb
@@ -2,6 +2,7 @@ require 'spec_helper'
describe Gitlab::GitAccess do
include TermsHelper
+ include GitHelpers
let(:user) { create(:user) }
@@ -736,21 +737,19 @@ describe Gitlab::GitAccess do
def merge_into_protected_branch
@protected_branch_merge_commit ||= begin
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.add_branch(user, unprotected_branch, 'feature')
- rugged = project.repository.rugged
- target_branch = rugged.rev_parse('feature')
- source_branch = project.repository.create_file(
- user,
- 'filename',
- 'This is the file content',
- message: 'This is a good commit message',
- branch_name: unprotected_branch)
- author = { email: "email@example.com", time: Time.now, name: "Example Git User" }
-
- merge_index = rugged.merge_commits(target_branch, source_branch)
- Rugged::Commit.create(rugged, author: author, committer: author, message: "commit message", parents: [target_branch, source_branch], tree: merge_index.write_tree(rugged))
- end
+ project.repository.add_branch(user, unprotected_branch, 'feature')
+ rugged = rugged_repo(project.repository)
+ target_branch = rugged.rev_parse('feature')
+ source_branch = project.repository.create_file(
+ user,
+ 'filename',
+ 'This is the file content',
+ message: 'This is a good commit message',
+ branch_name: unprotected_branch)
+ author = { email: "email@example.com", time: Time.now, name: "Example Git User" }
+
+ merge_index = rugged.merge_commits(target_branch, source_branch)
+ Rugged::Commit.create(rugged, author: author, committer: author, message: "commit message", parents: [target_branch, source_branch], tree: merge_index.write_tree(rugged))
end
end
@@ -935,6 +934,16 @@ describe Gitlab::GitAccess do
# There is still an N+1 query with protected branches
expect { access.check('git-receive-pack', changes) }.not_to exceed_query_limit(control_count).with_threshold(1)
end
+
+ it 'raises TimeoutError when #check_single_change_access raises a timeout error' do
+ message = "Push operation timed out\n\nTiming information for debugging purposes:\nRunning checks for ref: wow"
+
+ expect_next_instance_of(Gitlab::Checks::ChangeAccess) do |check|
+ expect(check).to receive(:exec).and_raise(Gitlab::Checks::TimedLogger::TimeoutError)
+ end
+
+ expect { access.check('git-receive-pack', changes) }.to raise_error(described_class::TimeoutError, message)
+ end
end
end
diff --git a/spec/lib/gitlab/git_ref_validator_spec.rb b/spec/lib/gitlab/git_ref_validator_spec.rb
index ba7fb168a3b..3ab04a1c46d 100644
--- a/spec/lib/gitlab/git_ref_validator_spec.rb
+++ b/spec/lib/gitlab/git_ref_validator_spec.rb
@@ -27,4 +27,5 @@ describe Gitlab::GitRefValidator do
it { expect(described_class.validate('-branch')).to be_falsey }
it { expect(described_class.validate('.tag')).to be_falsey }
it { expect(described_class.validate('my branch')).to be_falsey }
+ it { expect(described_class.validate("\xA0\u0000\xB0")).to be_falsey }
end
diff --git a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
index eaf64e3c9b4..b37fe2686b6 100644
--- a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb
@@ -335,4 +335,37 @@ describe Gitlab::GitalyClient::OperationService do
end
end
end
+
+ describe '#user_commit_patches' do
+ let(:patches_folder) { Rails.root.join('spec/fixtures/patchfiles') }
+ let(:patch_content) do
+ patch_names.map { |name| File.read(File.join(patches_folder, name)) }.join("\n")
+ end
+ let(:patch_names) { %w(0001-This-does-not-apply-to-the-feature-branch.patch) }
+ let(:branch_name) { 'branch-with-patches' }
+
+ subject(:commit_patches) do
+ client.user_commit_patches(user, branch_name, patch_content)
+ end
+
+ it 'applies the patch correctly' do
+ branch_update = commit_patches
+
+ expect(branch_update).to be_branch_created
+
+ commit = repository.commit(branch_update.newrev)
+ expect(commit.author_email).to eq('patchuser@gitlab.org')
+ expect(commit.committer_email).to eq(user.email)
+ expect(commit.message.chomp).to eq('This does not apply to the `feature` branch')
+ end
+
+ context 'when the patch could not be applied' do
+ let(:patch_names) { %w(0001-This-does-not-apply-to-the-feature-branch.patch) }
+ let(:branch_name) { 'feature' }
+
+ it 'raises the correct error' do
+ expect { commit_patches }.to raise_error(GRPC::FailedPrecondition)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/gitaly_client/remote_service_spec.rb b/spec/lib/gitlab/gitaly_client/remote_service_spec.rb
index 9030a49983d..aff47599ad6 100644
--- a/spec/lib/gitlab/gitaly_client/remote_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/remote_service_spec.rb
@@ -68,6 +68,8 @@ describe Gitlab::GitalyClient::RemoteService do
describe '#update_remote_mirror' do
let(:ref_name) { 'remote_mirror_1' }
let(:only_branches_matching) { ['my-branch', 'master'] }
+ let(:ssh_key) { 'KEY' }
+ let(:known_hosts) { 'KNOWN HOSTS' }
it 'sends an update_remote_mirror message' do
expect_any_instance_of(Gitaly::RemoteService::Stub)
@@ -75,7 +77,7 @@ describe Gitlab::GitalyClient::RemoteService do
.with(kind_of(Enumerator), kind_of(Hash))
.and_return(double(:update_remote_mirror_response))
- client.update_remote_mirror(ref_name, only_branches_matching)
+ client.update_remote_mirror(ref_name, only_branches_matching, ssh_key: ssh_key, known_hosts: known_hosts)
end
end
diff --git a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
index 1547d447197..46ca2340389 100644
--- a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe Gitlab::GitalyClient::RepositoryService do
+ using RSpec::Parameterized::TableSyntax
+
let(:project) { create(:project) }
let(:storage_name) { project.repository_storage }
let(:relative_path) { project.disk_path + '.git' }
@@ -107,16 +109,67 @@ describe Gitlab::GitalyClient::RepositoryService do
end
describe '#fetch_remote' do
- let(:ssh_auth) { double(:ssh_auth, ssh_import?: true, ssh_key_auth?: false, ssh_known_hosts: nil) }
- let(:import_url) { 'ssh://example.com' }
+ let(:remote) { 'remote-name' }
it 'sends a fetch_remote_request message' do
+ expected_request = gitaly_request_with_params(
+ remote: remote,
+ ssh_key: '',
+ known_hosts: '',
+ force: false,
+ no_tags: false,
+ no_prune: false
+ )
+
expect_any_instance_of(Gitaly::RepositoryService::Stub)
.to receive(:fetch_remote)
- .with(gitaly_request_with_params(no_prune: false), kind_of(Hash))
+ .with(expected_request, kind_of(Hash))
.and_return(double(value: true))
- client.fetch_remote(import_url, ssh_auth: ssh_auth, forced: false, no_tags: false, timeout: 60)
+ client.fetch_remote(remote, ssh_auth: nil, forced: false, no_tags: false, timeout: 1)
+ end
+
+ context 'SSH auth' do
+ where(:ssh_mirror_url, :ssh_key_auth, :ssh_private_key, :ssh_known_hosts, :expected_params) do
+ false | false | 'key' | 'known_hosts' | {}
+ false | true | 'key' | 'known_hosts' | {}
+ true | false | 'key' | 'known_hosts' | { known_hosts: 'known_hosts' }
+ true | true | 'key' | 'known_hosts' | { ssh_key: 'key', known_hosts: 'known_hosts' }
+ true | true | 'key' | nil | { ssh_key: 'key' }
+ true | true | nil | 'known_hosts' | { known_hosts: 'known_hosts' }
+ true | true | nil | nil | {}
+ true | true | '' | '' | {}
+ end
+
+ with_them do
+ let(:ssh_auth) do
+ double(
+ :ssh_auth,
+ ssh_mirror_url?: ssh_mirror_url,
+ ssh_key_auth?: ssh_key_auth,
+ ssh_private_key: ssh_private_key,
+ ssh_known_hosts: ssh_known_hosts
+ )
+ end
+
+ it do
+ expected_request = gitaly_request_with_params({
+ remote: remote,
+ ssh_key: '',
+ known_hosts: '',
+ force: false,
+ no_tags: false,
+ no_prune: false
+ }.update(expected_params))
+
+ expect_any_instance_of(Gitaly::RepositoryService::Stub)
+ .to receive(:fetch_remote)
+ .with(expected_request, kind_of(Hash))
+ .and_return(double(value: true))
+
+ client.fetch_remote(remote, ssh_auth: ssh_auth, forced: false, no_tags: false, timeout: 1)
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/gitaly_client/wiki_service_spec.rb b/spec/lib/gitlab/gitaly_client/wiki_service_spec.rb
index 5f67fe6b952..d82c9c28da0 100644
--- a/spec/lib/gitlab/gitaly_client/wiki_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/wiki_service_spec.rb
@@ -39,6 +39,10 @@ describe Gitlab::GitalyClient::WikiService do
expect(wiki_page.title).to eq('My Page')
expect(wiki_page.raw_data).to eq('ab')
expect(wiki_page_version.format).to eq('markdown')
+
+ expect(wiki_page.title).to be_utf8
+ expect(wiki_page.path).to be_utf8
+ expect(wiki_page.name).to be_utf8
end
end
diff --git a/spec/lib/gitlab/gitaly_client_spec.rb b/spec/lib/gitlab/gitaly_client_spec.rb
index 81bcd8c28ed..5eda4d041a8 100644
--- a/spec/lib/gitlab/gitaly_client_spec.rb
+++ b/spec/lib/gitlab/gitaly_client_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
# We stub Gitaly in `spec/support/gitaly.rb` for other tests. We don't want
# those stubs while testing the GitalyClient itself.
-describe Gitlab::GitalyClient, skip_gitaly_mock: true do
+describe Gitlab::GitalyClient do
describe '.stub_class' do
it 'returns the gRPC health check stub' do
expect(described_class.stub_class(:health_check)).to eq(::Grpc::Health::V1::Health::Stub)
@@ -191,102 +191,13 @@ describe Gitlab::GitalyClient, skip_gitaly_mock: true do
let(:feature_name) { 'my_feature' }
let(:real_feature_name) { "gitaly_#{feature_name}" }
- context 'when Gitaly is disabled' do
- before do
- allow(described_class).to receive(:enabled?).and_return(false)
- end
-
- it 'returns false' do
- expect(described_class.feature_enabled?(feature_name)).to be(false)
- end
- end
-
- context 'when the feature status is DISABLED' do
- let(:feature_status) { Gitlab::GitalyClient::MigrationStatus::DISABLED }
-
- it 'returns false' do
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(false)
- end
- end
-
- context 'when the feature_status is OPT_IN' do
- let(:feature_status) { Gitlab::GitalyClient::MigrationStatus::OPT_IN }
-
- context "when the feature flag hasn't been set" do
- it 'returns false' do
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(false)
- end
- end
-
- context "when the feature flag is set to disable" do
- before do
- Feature.get(real_feature_name).disable
- end
-
- it 'returns false' do
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(false)
- end
- end
-
- context "when the feature flag is set to enable" do
- before do
- Feature.get(real_feature_name).enable
- end
-
- it 'returns true' do
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(true)
- end
- end
-
- context "when the feature flag is set to a percentage of time" do
- before do
- Feature.get(real_feature_name).enable_percentage_of_time(70)
- end
-
- it 'bases the result on pseudo-random numbers' do
- expect(Random).to receive(:rand).and_return(0.3)
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(true)
-
- expect(Random).to receive(:rand).and_return(0.8)
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(false)
- end
- end
-
- context "when a feature is not persisted" do
- it 'returns false when opt_into_all_features is off' do
- allow(Feature).to receive(:persisted?).and_return(false)
- allow(described_class).to receive(:opt_into_all_features?).and_return(false)
-
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(false)
- end
-
- it 'returns true when the override is on' do
- allow(Feature).to receive(:persisted?).and_return(false)
- allow(described_class).to receive(:opt_into_all_features?).and_return(true)
-
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(true)
- end
- end
+ before do
+ allow(Feature).to receive(:enabled?).and_return(false)
end
- context 'when the feature_status is OPT_OUT' do
- let(:feature_status) { Gitlab::GitalyClient::MigrationStatus::OPT_OUT }
-
- context "when the feature flag hasn't been set" do
- it 'returns true' do
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(true)
- end
- end
-
- context "when the feature flag is set to disable" do
- before do
- Feature.get(real_feature_name).disable
- end
-
- it 'returns false' do
- expect(described_class.feature_enabled?(feature_name, status: feature_status)).to be(false)
- end
- end
+ it 'returns false' do
+ expect(Feature).to receive(:enabled?).with(real_feature_name)
+ expect(described_class.feature_enabled?(feature_name)).to be(false)
end
end
@@ -305,4 +216,29 @@ describe Gitlab::GitalyClient, skip_gitaly_mock: true do
end
end
end
+
+ describe 'Peek Performance bar details' do
+ let(:gitaly_server) { Gitaly::Server.all.first }
+
+ before do
+ Gitlab::SafeRequestStore[:peek_enabled] = true
+ end
+
+ context 'when the request store is active', :request_store do
+ it 'records call details if a RPC is called' do
+ gitaly_server.server_version
+
+ expect(described_class.list_call_details).not_to be_empty
+ expect(described_class.list_call_details.size).to be(1)
+ end
+ end
+
+ context 'when no request store is active' do
+ it 'records nothing' do
+ gitaly_server.server_version
+
+ expect(described_class.list_call_details).to be_empty
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb b/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb
index 25684ea9e2c..efca8564894 100644
--- a/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb
@@ -240,7 +240,12 @@ describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redi
.and_return(user.id)
end
- it 'returns the existing merge request' do
+ # TODO: remove rails5-only after removing rails4 tests
+ # rails 4 can not handle multiple indexes on the same column set if
+ # index was added by 't.index' - t.index is used by default in schema.rb in
+ # rails 5. Let's run this test only in rails 5 env:
+ # see https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21492#note_113602758
+ it 'returns the existing merge request', :rails5 do
mr1, exists1 = importer.create_merge_request
mr2, exists2 = importer.create_merge_request
diff --git a/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb b/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb
index d8f01dcb76b..77f5b2ffa37 100644
--- a/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/repository_importer_spec.rb
@@ -218,7 +218,7 @@ describe Gitlab::GithubImport::Importer::RepositoryImporter do
describe '#fail_import' do
it 'marks the import as failed' do
- expect(project).to receive(:mark_import_as_failed).with('foo')
+ expect(project.import_state).to receive(:mark_as_failed).with('foo')
expect(importer.fail_import('foo')).to eq(false)
end
diff --git a/spec/lib/gitlab/github_import/parallel_importer_spec.rb b/spec/lib/gitlab/github_import/parallel_importer_spec.rb
index 20b48c1de68..f5df38c9aaf 100644
--- a/spec/lib/gitlab/github_import/parallel_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/parallel_importer_spec.rb
@@ -36,7 +36,7 @@ describe Gitlab::GithubImport::ParallelImporter do
it 'updates the import JID of the project' do
importer.execute
- expect(project.reload.import_jid).to eq("github-importer/#{project.id}")
+ expect(project.import_state.reload.jid).to eq("github-importer/#{project.id}")
end
end
end
diff --git a/spec/lib/gitlab/gon_helper_spec.rb b/spec/lib/gitlab/gon_helper_spec.rb
new file mode 100644
index 00000000000..c6f09ca2112
--- /dev/null
+++ b/spec/lib/gitlab/gon_helper_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::GonHelper do
+ let(:helper) do
+ Class.new do
+ include Gitlab::GonHelper
+ end.new
+ end
+
+ describe '#push_frontend_feature_flag' do
+ it 'pushes a feature flag to the frontend' do
+ gon = instance_double('gon')
+
+ allow(helper)
+ .to receive(:gon)
+ .and_return(gon)
+
+ expect(Feature)
+ .to receive(:enabled?)
+ .with(:my_feature_flag, 10)
+ .and_return(true)
+
+ expect(gon)
+ .to receive(:push)
+ .with({ features: { 'myFeatureFlag' => true } }, true)
+
+ helper.push_frontend_feature_flag(:my_feature_flag, 10)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/gpg_spec.rb b/spec/lib/gitlab/gpg_spec.rb
index 47f37cae98f..39d09c49989 100644
--- a/spec/lib/gitlab/gpg_spec.rb
+++ b/spec/lib/gitlab/gpg_spec.rb
@@ -96,7 +96,7 @@ describe Gitlab::Gpg do
expect(described_class.current_home_dir).to eq default_home_dir
end
- it 'returns the explicitely set home dir' do
+ it 'returns the explicitly set home dir' do
GPGME::Engine.home_dir = '/tmp/gpg'
expect(described_class.current_home_dir).to eq '/tmp/gpg'
@@ -104,7 +104,7 @@ describe Gitlab::Gpg do
GPGME::Engine.home_dir = GPGME::Engine.dirinfo('homedir')
end
- it 'returns the default value when explicitely setting the home dir to nil' do
+ it 'returns the default value when explicitly setting the home dir to nil' do
GPGME::Engine.home_dir = nil
expect(described_class.current_home_dir).to eq default_home_dir
diff --git a/spec/lib/gitlab/graphql/loaders/batch_model_loader_spec.rb b/spec/lib/gitlab/graphql/loaders/batch_model_loader_spec.rb
new file mode 100644
index 00000000000..4609593ef6a
--- /dev/null
+++ b/spec/lib/gitlab/graphql/loaders/batch_model_loader_spec.rb
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+describe Gitlab::Graphql::Loaders::BatchModelLoader do
+ describe '#find' do
+ let(:issue) { create(:issue) }
+ let(:user) { create(:user) }
+
+ it 'finds a model by id' do
+ issue_result = described_class.new(Issue, issue.id).find
+ user_result = described_class.new(User, user.id).find
+
+ expect(issue_result.__sync).to eq(issue)
+ expect(user_result.__sync).to eq(user)
+ end
+
+ it 'only queries once per model' do
+ other_user = create(:user)
+ user
+ issue
+
+ expect do
+ [described_class.new(User, other_user.id).find,
+ described_class.new(User, user.id).find,
+ described_class.new(Issue, issue.id).find].map(&:__sync)
+ end.not_to exceed_query_limit(2)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/highlight_spec.rb b/spec/lib/gitlab/highlight_spec.rb
index 29e61d15726..fe0e9702f8a 100644
--- a/spec/lib/gitlab/highlight_spec.rb
+++ b/spec/lib/gitlab/highlight_spec.rb
@@ -5,44 +5,85 @@ describe Gitlab::Highlight do
let(:project) { create(:project, :repository) }
let(:repository) { project.repository }
- let(:commit) { project.commit(sample_commit.id) }
-
- describe 'custom highlighting from .gitattributes' do
- let(:branch) { 'gitattributes' }
- let(:blob) { repository.blob_at_branch(branch, path) }
+ describe 'language provided' do
let(:highlighter) do
- described_class.new(blob.path, blob.data, repository: repository)
+ described_class.new('foo.erb', 'bar', language: 'erb?parent=json')
end
- before do
- project.change_head('gitattributes')
+ it 'sets correct lexer' do
+ expect(highlighter.lexer.tag).to eq 'erb'
+ expect(highlighter.lexer.parent.tag).to eq 'json'
end
+ end
- describe 'basic language selection' do
- let(:path) { 'custom-highlighting/test.gitlab-custom' }
- it 'highlights as ruby' do
- expect(highlighter.lexer.tag).to eq 'ruby'
- end
+ describe '#highlight' do
+ let(:file_name) { 'test.lisp' }
+ let(:no_context_content) { ":type \"assem\"))" }
+ let(:content) { "(make-pathname :defaults name\n#{no_context_content}" }
+ let(:multiline_content) do
+ %q(
+ def test(input):
+ """This is line 1 of a multi-line comment.
+ This is line 2.
+ """
+ )
+ end
+
+ it 'highlights' do
+ expected = %Q[<span id="LC1" class="line" lang="common_lisp"><span class="p">(</span><span class="nb">make-pathname</span> <span class="ss">:defaults</span> <span class="nv">name</span></span>
+<span id="LC2" class="line" lang="common_lisp"><span class="ss">:type</span> <span class="s">"assem"</span><span class="p">))</span></span>]
+
+ expect(described_class.highlight(file_name, content)).to eq(expected)
+ end
+
+ it 'returns plain version for unknown lexer context' do
+ result = described_class.highlight(file_name, no_context_content)
+
+ expect(result).to eq(%[<span id="LC1" class="line" lang="">:type "assem"))</span>])
+ end
+
+ it 'returns plain version for long content' do
+ stub_const('Gitlab::Highlight::MAXIMUM_TEXT_HIGHLIGHT_SIZE', 1)
+ result = described_class.highlight(file_name, content)
+
+ expect(result).to eq(%[<span id="LC1" class="line" lang="">(make-pathname :defaults name</span>\n<span id="LC2" class="line" lang="">:type "assem"))</span>])
+ end
+
+ it 'highlights multi-line comments' do
+ result = described_class.highlight(file_name, multiline_content)
+ html = Nokogiri::HTML(result)
+ lines = html.search('.s')
+
+ expect(lines.count).to eq(3)
+ expect(lines[0].text).to eq('"""This is line 1 of a multi-line comment.')
+ expect(lines[1].text).to eq(' This is line 2.')
+ expect(lines[2].text).to eq(' """')
end
- describe 'cgi options' do
- let(:path) { 'custom-highlighting/test.gitlab-cgi' }
+ context 'diff highlighting' do
+ let(:file_name) { 'test.diff' }
+ let(:content) { "+aaa\n+bbb\n- ccc\n ddd\n"}
+ let(:expected) do
+ %q(<span id="LC1" class="line" lang="diff"><span class="gi">+aaa</span></span>
+<span id="LC2" class="line" lang="diff"><span class="gi">+bbb</span></span>
+<span id="LC3" class="line" lang="diff"><span class="gd">- ccc</span></span>
+<span id="LC4" class="line" lang="diff"> ddd</span>)
+ end
+
+ it 'highlights each line properly' do
+ result = described_class.highlight(file_name, content)
- it 'highlights as json with erb' do
- expect(highlighter.lexer.tag).to eq 'erb'
- expect(highlighter.lexer.parent.tag).to eq 'json'
+ expect(result).to eq(expected)
end
end
- end
- describe '#highlight' do
describe 'with CRLF' do
let(:branch) { 'crlf-diff' }
let(:path) { 'files/whitespace' }
let(:blob) { repository.blob_at_branch(branch, path) }
let(:lines) do
- described_class.highlight(blob.path, blob.data, repository: repository).lines
+ described_class.highlight(blob.path, blob.data).lines
end
it 'strips extra LFs' do
@@ -56,5 +97,22 @@ describe Gitlab::Highlight do
described_class.highlight('file.name', 'Contents')
end
+
+ context 'timeout' do
+ subject { described_class.new('file.name', 'Contents') }
+
+ it 'utilizes timeout for web' do
+ expect(Timeout).to receive(:timeout).with(described_class::TIMEOUT_FOREGROUND).and_call_original
+
+ subject.highlight("Content")
+ end
+
+ it 'utilizes longer timeout for sidekiq' do
+ allow(Sidekiq).to receive(:server?).and_return(true)
+ expect(Timeout).to receive(:timeout).with(described_class::TIMEOUT_BACKGROUND).and_call_original
+
+ subject.highlight("Content")
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/hook_data/base_builder_spec.rb b/spec/lib/gitlab/hook_data/base_builder_spec.rb
index a921dd766c3..e3c5ee3b905 100644
--- a/spec/lib/gitlab/hook_data/base_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/base_builder_spec.rb
@@ -8,57 +8,94 @@ describe Gitlab::HookData::BaseBuilder do
end
end
- subject { subclass.new(nil) }
-
using RSpec::Parameterized::TableSyntax
- where do
- {
- 'relative image URL' => {
- input: '![an image](foo.png)',
- output: "![an image](#{Gitlab.config.gitlab.url}/foo.png)"
- },
- 'HTTP URL' => {
- input: '![an image](http://example.com/foo.png)',
- output: '![an image](http://example.com/foo.png)'
- },
- 'HTTPS URL' => {
- input: '![an image](https://example.com/foo.png)',
- output: '![an image](https://example.com/foo.png)'
- },
- 'protocol-relative URL' => {
- input: '![an image](//example.com/foo.png)',
- output: '![an image](//example.com/foo.png)'
- },
- 'URL reference by title' => {
- input: "![foo]\n\n[foo]: foo.png",
- output: "![foo]\n\n[foo]: foo.png"
- },
- 'URL reference by label' => {
- input: "![][foo]\n\n[foo]: foo.png",
- output: "![][foo]\n\n[foo]: foo.png"
- },
- 'in Markdown inline code block' => {
- input: '`![an image](foo.png)`',
- output: "`![an image](#{Gitlab.config.gitlab.url}/foo.png)`"
- },
- 'in HTML tag on the same line' => {
- input: '<p>![an image](foo.png)</p>',
- output: "<p>![an image](#{Gitlab.config.gitlab.url}/foo.png)</p>"
- },
- 'in Markdown multi-line code block' => {
- input: "```\n![an image](foo.png)\n```",
- output: "```\n![an image](foo.png)\n```"
- },
- 'in HTML tag on different lines' => {
- input: "<p>\n![an image](foo.png)\n</p>",
- output: "<p>\n![an image](foo.png)\n</p>"
+ context 'with an upload prefix specified' do
+ let(:project_with_path) { double(full_path: 'baz/bar') }
+ let(:object_with_project) { double(project: project_with_path) }
+ subject { subclass.new(object_with_project) }
+
+ where do
+ {
+ 'relative image URL' => {
+ input: '![an image](foo.png)',
+ output: "![an image](#{Gitlab.config.gitlab.url}/foo.png)"
+ },
+ 'absolute upload URL' => {
+ input: '![an image](/uploads/foo.png)',
+ output: "![an image](#{Gitlab.config.gitlab.url}/baz/bar/uploads/foo.png)"
+ },
+ 'absolute non-upload URL' => {
+ input: '![an image](/downloads/foo.png)',
+ output: "![an image](#{Gitlab.config.gitlab.url}/downloads/foo.png)"
+ }
}
- }
+ end
+
+ with_them do
+ it { expect(subject.absolute_image_urls(input)).to eq(output) }
+ end
end
- with_them do
- it { expect(subject.absolute_image_urls(input)).to eq(output) }
+ context 'without an upload prefix specified' do
+ subject { subclass.new(nil) }
+
+ where do
+ {
+ 'relative image URL' => {
+ input: '![an image](foo.png)',
+ output: "![an image](#{Gitlab.config.gitlab.url}/foo.png)"
+ },
+ 'absolute upload URL' => {
+ input: '![an image](/uploads/foo.png)',
+ output: "![an image](#{Gitlab.config.gitlab.url}/uploads/foo.png)"
+ },
+ 'absolute non-upload URL' => {
+ input: '![an image](/downloads/foo.png)',
+ output: "![an image](#{Gitlab.config.gitlab.url}/downloads/foo.png)"
+ },
+ 'HTTP URL' => {
+ input: '![an image](http://example.com/foo.png)',
+ output: '![an image](http://example.com/foo.png)'
+ },
+ 'HTTPS URL' => {
+ input: '![an image](https://example.com/foo.png)',
+ output: '![an image](https://example.com/foo.png)'
+ },
+ 'protocol-relative URL' => {
+ input: '![an image](//example.com/foo.png)',
+ output: '![an image](//example.com/foo.png)'
+ },
+ 'URL reference by title' => {
+ input: "![foo]\n\n[foo]: foo.png",
+ output: "![foo]\n\n[foo]: foo.png"
+ },
+ 'URL reference by label' => {
+ input: "![][foo]\n\n[foo]: foo.png",
+ output: "![][foo]\n\n[foo]: foo.png"
+ },
+ 'in Markdown inline code block' => {
+ input: '`![an image](foo.png)`',
+ output: "`![an image](#{Gitlab.config.gitlab.url}/foo.png)`"
+ },
+ 'in HTML tag on the same line' => {
+ input: '<p>![an image](foo.png)</p>',
+ output: "<p>![an image](#{Gitlab.config.gitlab.url}/foo.png)</p>"
+ },
+ 'in Markdown multi-line code block' => {
+ input: "```\n![an image](foo.png)\n```",
+ output: "```\n![an image](foo.png)\n```"
+ },
+ 'in HTML tag on different lines' => {
+ input: "<p>\n![an image](foo.png)\n</p>",
+ output: "<p>\n![an image](foo.png)\n</p>"
+ }
+ }
+ end
+
+ with_them do
+ it { expect(subject.absolute_image_urls(input)).to eq(output) }
+ end
end
end
end
diff --git a/spec/lib/gitlab/hook_data/issue_builder_spec.rb b/spec/lib/gitlab/hook_data/issue_builder_spec.rb
index 60093474f8a..f066c0e3813 100644
--- a/spec/lib/gitlab/hook_data/issue_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/issue_builder_spec.rb
@@ -46,7 +46,10 @@ describe Gitlab::HookData::IssueBuilder do
let(:builder) { described_class.new(issue_with_description) }
it 'sets the image to use an absolute URL' do
- expect(data[:description]).to eq("test![Issue_Image](#{Settings.gitlab.url}/uploads/abc/Issue_Image.png)")
+ expected_path = "#{issue_with_description.project.path_with_namespace}/uploads/abc/Issue_Image.png"
+
+ expect(data[:description])
+ .to eq("test![Issue_Image](#{Settings.gitlab.url}/#{expected_path})")
end
end
end
diff --git a/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb b/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
index dd586af6118..9ce697adbba 100644
--- a/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
@@ -58,11 +58,14 @@ describe Gitlab::HookData::MergeRequestBuilder do
end
context 'when the MR has an image in the description' do
- let(:mr_with_description) { create(:merge_request, description: 'test![Issue_Image](/uploads/abc/Issue_Image.png)') }
+ let(:mr_with_description) { create(:merge_request, description: 'test![MR_Image](/uploads/abc/MR_Image.png)') }
let(:builder) { described_class.new(mr_with_description) }
it 'sets the image to use an absolute URL' do
- expect(data[:description]).to eq("test![Issue_Image](#{Settings.gitlab.url}/uploads/abc/Issue_Image.png)")
+ expected_path = "#{mr_with_description.project.path_with_namespace}/uploads/abc/MR_Image.png"
+
+ expect(data[:description])
+ .to eq("test![MR_Image](#{Settings.gitlab.url}/#{expected_path})")
end
end
end
diff --git a/spec/lib/gitlab/http_spec.rb b/spec/lib/gitlab/http_spec.rb
index d0dadfa78da..6c37c157f5d 100644
--- a/spec/lib/gitlab/http_spec.rb
+++ b/spec/lib/gitlab/http_spec.rb
@@ -46,4 +46,30 @@ describe Gitlab::HTTP do
end
end
end
+
+ describe 'handle redirect loops' do
+ before do
+ WebMock.stub_request(:any, "http://example.org").to_raise(HTTParty::RedirectionTooDeep.new("Redirection Too Deep"))
+ end
+
+ it 'handles GET requests' do
+ expect { described_class.get('http://example.org') }.to raise_error(Gitlab::HTTP::RedirectionTooDeep)
+ end
+
+ it 'handles POST requests' do
+ expect { described_class.post('http://example.org') }.to raise_error(Gitlab::HTTP::RedirectionTooDeep)
+ end
+
+ it 'handles PUT requests' do
+ expect { described_class.put('http://example.org') }.to raise_error(Gitlab::HTTP::RedirectionTooDeep)
+ end
+
+ it 'handles DELETE requests' do
+ expect { described_class.delete('http://example.org') }.to raise_error(Gitlab::HTTP::RedirectionTooDeep)
+ end
+
+ it 'handles HEAD requests' do
+ expect { described_class.head('http://example.org') }.to raise_error(Gitlab::HTTP::RedirectionTooDeep)
+ end
+ end
end
diff --git a/spec/lib/gitlab/identifier_spec.rb b/spec/lib/gitlab/identifier_spec.rb
index 0385dd762c2..1e583f4cee2 100644
--- a/spec/lib/gitlab/identifier_spec.rb
+++ b/spec/lib/gitlab/identifier_spec.rb
@@ -11,11 +11,8 @@ describe Gitlab::Identifier do
describe '#identify' do
context 'without an identifier' do
- it 'identifies the user using a commit' do
- expect(identifier).to receive(:identify_using_commit)
- .with(project, '123')
-
- identifier.identify('', project, '123')
+ it 'returns nil' do
+ expect(identifier.identify('')).to be nil
end
end
@@ -24,7 +21,7 @@ describe Gitlab::Identifier do
expect(identifier).to receive(:identify_using_user)
.with("user-#{user.id}")
- identifier.identify("user-#{user.id}", project, '123')
+ identifier.identify("user-#{user.id}")
end
end
@@ -33,49 +30,11 @@ describe Gitlab::Identifier do
expect(identifier).to receive(:identify_using_ssh_key)
.with("key-#{key.id}")
- identifier.identify("key-#{key.id}", project, '123')
+ identifier.identify("key-#{key.id}")
end
end
end
- describe '#identify_using_commit' do
- it "returns the User for an existing commit author's Email address" do
- commit = double(:commit, author: user, author_email: user.email)
-
- expect(project).to receive(:commit).with('123').and_return(commit)
-
- expect(identifier.identify_using_commit(project, '123')).to eq(user)
- end
-
- it 'returns nil when no user could be found' do
- allow(project).to receive(:commit).with('123').and_return(nil)
-
- expect(identifier.identify_using_commit(project, '123')).to be_nil
- end
-
- it 'returns nil when the commit does not have an author Email' do
- commit = double(:commit, author_email: nil)
-
- expect(project).to receive(:commit).with('123').and_return(commit)
-
- expect(identifier.identify_using_commit(project, '123')).to be_nil
- end
-
- it 'caches the found users per Email' do
- commit = double(:commit, author: user, author_email: user.email)
-
- expect(project).to receive(:commit).with('123').twice.and_return(commit)
-
- 2.times do
- expect(identifier.identify_using_commit(project, '123')).to eq(user)
- end
- end
-
- it 'returns nil if the project & ref are not present' do
- expect(identifier.identify_using_commit(nil, nil)).to be_nil
- end
- end
-
describe '#identify_using_user' do
it 'returns the User for an existing ID in the identifier' do
found = identifier.identify_using_user("user-#{user.id}")
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index ec2bdbe22e1..31ab11bbf8d 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -117,9 +117,12 @@ pipelines:
- retryable_builds
- cancelable_statuses
- manual_actions
+- scheduled_actions
- artifacts
- pipeline_schedule
- merge_requests
+- deployments
+- environments
pipeline_variables:
- pipeline
stages:
@@ -197,6 +200,7 @@ project:
- last_event
- services
- campfire_service
+- discord_service
- drone_ci_service
- emails_on_push_service
- pipelines_email_service
@@ -228,9 +232,8 @@ project:
- mock_ci_service
- mock_deployment_service
- mock_monitoring_service
-- forked_project_link
+- forked_to_members
- forked_from_project
-- forked_project_links
- forks
- merge_requests
- fork_merge_requests
@@ -244,6 +247,7 @@ project:
- protected_branches
- protected_tags
- project_members
+- project_repository
- users
- requesters
- deploy_keys_projects
@@ -299,6 +303,7 @@ project:
- ci_cd_settings
- import_export_upload
- repository_languages
+- pool_repository
award_emoji:
- awardable
- user
diff --git a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb
index 65f073b2df3..87ab81d8169 100644
--- a/spec/lib/gitlab/import_export/attribute_configuration_spec.rb
+++ b/spec/lib/gitlab/import_export/attribute_configuration_spec.rb
@@ -23,15 +23,23 @@ describe 'Import/Export attribute configuration' do
let(:safe_attributes_file) { 'spec/lib/gitlab/import_export/safe_model_attributes.yml' }
let(:safe_model_attributes) { YAML.load_file(safe_attributes_file) }
+ let(:ee_safe_attributes_file) { 'ee/spec/lib/gitlab/import_export/safe_model_attributes.yml' }
+ let(:ee_safe_model_attributes) { File.exist?(ee_safe_attributes_file) ? YAML.load_file(ee_safe_attributes_file) : {} }
+
it 'has no new columns' do
relation_names.each do |relation_name|
relation_class = relation_class_for_name(relation_name)
relation_attributes = relation_class.new.attributes.keys
- expect(safe_model_attributes[relation_class.to_s]).not_to be_nil, "Expected exported class #{relation_class} to exist in safe_model_attributes"
-
current_attributes = parsed_attributes(relation_name, relation_attributes)
- safe_attributes = safe_model_attributes[relation_class.to_s]
+ safe_attributes = safe_model_attributes[relation_class.to_s].dup || []
+
+ ee_safe_model_attributes[relation_class.to_s].to_a.each do |attribute|
+ safe_attributes << attribute
+ end
+
+ expect(safe_attributes).not_to be_nil, "Expected exported class #{relation_class} to exist in safe_model_attributes"
+
new_attributes = current_attributes - safe_attributes
expect(new_attributes).to be_empty, failure_message(relation_class.to_s, new_attributes)
@@ -43,6 +51,7 @@ describe 'Import/Export attribute configuration' do
It looks like #{relation_class}, which is exported using the project Import/Export, has new attributes: #{new_attributes.join(',')}
Please add the attribute(s) to SAFE_MODEL_ATTRIBUTES if you consider this can be exported.
+ #{"If the model/associations are EE-specific, use `#{File.expand_path(ee_safe_attributes_file)}`.\n" if ee_safe_model_attributes.any?}
Otherwise, please blacklist the attribute(s) in IMPORT_EXPORT_CONFIG by adding it to its correspondent
model in the +excluded_attributes+ section.
diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json
index eefd00e7383..58949f76bd6 100644
--- a/spec/lib/gitlab/import_export/project.json
+++ b/spec/lib/gitlab/import_export/project.json
@@ -2556,7 +2556,7 @@
"merge_request_diff_id": 27,
"relative_order": 0,
"sha": "bb5206fee213d983da88c47f9cf4cc6caf9c66dc",
- "message": "Feature conflcit added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
+ "message": "Feature conflict added\n\nSigned-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>\n",
"authored_date": "2014-08-06T08:35:52.000+02:00",
"author_name": "Dmitriy Zaporozhets",
"author_email": "dmitriy.zaporozhets@gmail.com",
@@ -3605,7 +3605,7 @@
"merge_request_diff_id": 14,
"relative_order": 8,
"sha": "08f22f255f082689c0d7d39d19205085311542bc",
- "message": "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n",
+ "message": "remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n",
"authored_date": "2015-11-13T06:00:16.000+01:00",
"author_name": "윤민ì‹",
"author_email": "minsik.yoon@samsung.com",
@@ -4290,7 +4290,7 @@
"merge_request_diff_id": 13,
"relative_order": 8,
"sha": "08f22f255f082689c0d7d39d19205085311542bc",
- "message": "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n",
+ "message": "remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n",
"authored_date": "2015-11-13T06:00:16.000+01:00",
"author_name": "윤민ì‹",
"author_email": "minsik.yoon@samsung.com",
@@ -4799,7 +4799,7 @@
"merge_request_diff_id": 12,
"relative_order": 8,
"sha": "08f22f255f082689c0d7d39d19205085311542bc",
- "message": "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n",
+ "message": "remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n",
"authored_date": "2015-11-13T06:00:16.000+01:00",
"author_name": "윤민ì‹",
"author_email": "minsik.yoon@samsung.com",
@@ -5507,7 +5507,7 @@
"merge_request_diff_id": 10,
"relative_order": 8,
"sha": "08f22f255f082689c0d7d39d19205085311542bc",
- "message": "remove emtpy file.(beacase git ignore empty file)\nadd whitespace test file.\n",
+ "message": "remove empty file.(beacase git ignore empty file)\nadd whitespace test file.\n",
"authored_date": "2015-11-13T06:00:16.000+01:00",
"author_name": "윤민ì‹",
"author_email": "minsik.yoon@samsung.com",
@@ -6143,7 +6143,7 @@
"id": 36,
"project_id": 5,
"ref": "master",
- "sha": "be93687618e4b132087f430a4d8fc3a609c9b77c",
+ "sha": "sha-notes",
"before_sha": null,
"push_data": null,
"created_at": "2016-03-22T15:20:35.755Z",
@@ -6154,6 +6154,7 @@
"status": "failed",
"started_at": null,
"finished_at": null,
+ "user_id": 9999,
"duration": null,
"notes": [
{
@@ -6353,6 +6354,7 @@
},
{
"id": 38,
+ "iid": 1,
"project_id": 5,
"ref": "master",
"sha": "5f923865dde3436854e9ceb9cdb7815618d4e849",
diff --git a/spec/lib/gitlab/import_export/project.light.json b/spec/lib/gitlab/import_export/project.light.json
index ba2248073f5..2971ca0f0f8 100644
--- a/spec/lib/gitlab/import_export/project.light.json
+++ b/spec/lib/gitlab/import_export/project.light.json
@@ -101,6 +101,28 @@
]
}
],
+ "services": [
+ {
+ "id": 100,
+ "title": "JetBrains TeamCity CI",
+ "project_id": 5,
+ "created_at": "2016-06-14T15:01:51.315Z",
+ "updated_at": "2016-06-14T15:01:51.315Z",
+ "active": false,
+ "properties": {},
+ "template": true,
+ "push_events": true,
+ "issues_events": true,
+ "merge_requests_events": true,
+ "tag_push_events": true,
+ "note_events": true,
+ "job_events": true,
+ "type": "TeamcityService",
+ "category": "ci",
+ "default": false,
+ "wiki_page_events": true
+ }
+ ],
"snippets": [],
"hooks": []
}
diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
index 3ff6be595a8..7171e12a849 100644
--- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
@@ -59,7 +59,11 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
end
it 'creates a valid pipeline note' do
- expect(Ci::Pipeline.first.notes).not_to be_empty
+ expect(Ci::Pipeline.find_by_sha('sha-notes').notes).not_to be_empty
+ end
+
+ it 'pipeline has the correct user ID' do
+ expect(Ci::Pipeline.find_by_sha('sha-notes').user_id).to eq(@user.id)
end
it 'restores pipelines with missing ref' do
@@ -293,7 +297,8 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
issues: 1,
labels: 1,
milestones: 1,
- first_issue_labels: 1
+ first_issue_labels: 1,
+ services: 1
context 'project.json file access check' do
it 'does not read a symlink' do
@@ -317,7 +322,7 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
end
end
- context 'when the project has overriden params in import data' do
+ context 'when the project has overridden params in import data' do
it 'overwrites the params stored in the JSON' do
project.create_import_data(data: { override_params: { description: "Overridden" } })
@@ -331,7 +336,7 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
restored_project_json
- expect(project.lfs_enabled).to be_nil
+ expect(project.lfs_enabled).to be_falsey
end
end
@@ -378,6 +383,12 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
project_tree_restorer.instance_variable_set(:@path, "spec/lib/gitlab/import_export/project.light.json")
end
+ it 'does not import any templated services' do
+ restored_project_json
+
+ expect(project.services.where(template: true).count).to eq(0)
+ end
+
it 'imports labels' do
create(:group_label, name: 'Another label', group: project.group)
diff --git a/spec/lib/gitlab/import_export/relation_factory_spec.rb b/spec/lib/gitlab/import_export/relation_factory_spec.rb
index cf9e0f71910..a31f77484d8 100644
--- a/spec/lib/gitlab/import_export/relation_factory_spec.rb
+++ b/spec/lib/gitlab/import_export/relation_factory_spec.rb
@@ -191,9 +191,7 @@ describe Gitlab::ImportExport::RelationFactory do
"author" => {
"name" => "Administrator"
},
- "events" => [
-
- ]
+ "events" => []
}
end
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index e9f1be172b0..f7935149b23 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -300,6 +300,7 @@ CommitStatus:
- retried
- protected
- failure_reason
+- scheduled_at
Ci::Variable:
- id
- project_id
@@ -492,6 +493,7 @@ ProjectFeature:
- snippets_access_level
- builds_access_level
- repository_access_level
+- pages_access_level
- created_at
- updated_at
ProtectedBranch::MergeAccessLevel:
diff --git a/spec/lib/gitlab/kubernetes/helm/api_spec.rb b/spec/lib/gitlab/kubernetes/helm/api_spec.rb
index 25c3b37753d..c7f92cbb143 100644
--- a/spec/lib/gitlab/kubernetes/helm/api_spec.rb
+++ b/spec/lib/gitlab/kubernetes/helm/api_spec.rb
@@ -36,9 +36,11 @@ describe Gitlab::Kubernetes::Helm::Api do
describe '#install' do
before do
allow(client).to receive(:create_pod).and_return(nil)
+ allow(client).to receive(:get_config_map).and_return(nil)
allow(client).to receive(:create_config_map).and_return(nil)
allow(client).to receive(:create_service_account).and_return(nil)
allow(client).to receive(:create_cluster_role_binding).and_return(nil)
+ allow(client).to receive(:delete_pod).and_return(nil)
allow(namespace).to receive(:ensure_exists!).once
end
@@ -49,6 +51,13 @@ describe Gitlab::Kubernetes::Helm::Api do
subject.install(command)
end
+ it 'removes an existing pod before installing' do
+ expect(client).to receive(:delete_pod).with('install-app-name', 'gitlab-managed-apps').once.ordered
+ expect(client).to receive(:create_pod).once.ordered
+
+ subject.install(command)
+ end
+
context 'with a ConfigMap' do
let(:resource) { Gitlab::Kubernetes::ConfigMap.new(application_name, files).generate }
@@ -57,6 +66,18 @@ describe Gitlab::Kubernetes::Helm::Api do
subject.install(command)
end
+
+ context 'config map already exists' do
+ before do
+ expect(client).to receive(:get_config_map).with("values-content-configuration-#{application_name}", gitlab_namespace).and_return(resource)
+ end
+
+ it 'updates the config map' do
+ expect(client).to receive(:update_config_map).with(resource).once
+
+ subject.install(command)
+ end
+ end
end
context 'without a service account' do
@@ -88,8 +109,8 @@ describe Gitlab::Kubernetes::Helm::Api do
context 'service account and cluster role binding does not exist' do
before do
- expect(client).to receive('get_service_account').with('tiller', 'gitlab-managed-apps').and_raise(Kubeclient::HttpError.new(404, 'Not found', nil))
- expect(client).to receive('get_cluster_role_binding').with('tiller-admin').and_raise(Kubeclient::HttpError.new(404, 'Not found', nil))
+ expect(client).to receive(:get_service_account).with('tiller', 'gitlab-managed-apps').and_raise(Kubeclient::ResourceNotFoundError.new(404, 'Not found', nil))
+ expect(client).to receive(:get_cluster_role_binding).with('tiller-admin').and_raise(Kubeclient::ResourceNotFoundError.new(404, 'Not found', nil))
end
it 'creates a service account, followed the cluster role binding on kubeclient' do
@@ -102,8 +123,8 @@ describe Gitlab::Kubernetes::Helm::Api do
context 'service account already exists' do
before do
- expect(client).to receive('get_service_account').with('tiller', 'gitlab-managed-apps').and_return(service_account_resource)
- expect(client).to receive('get_cluster_role_binding').with('tiller-admin').and_raise(Kubeclient::HttpError.new(404, 'Not found', nil))
+ expect(client).to receive(:get_service_account).with('tiller', 'gitlab-managed-apps').and_return(service_account_resource)
+ expect(client).to receive(:get_cluster_role_binding).with('tiller-admin').and_raise(Kubeclient::ResourceNotFoundError.new(404, 'Not found', nil))
end
it 'updates the service account, followed by creating the cluster role binding' do
@@ -116,8 +137,8 @@ describe Gitlab::Kubernetes::Helm::Api do
context 'service account and cluster role binding already exists' do
before do
- expect(client).to receive('get_service_account').with('tiller', 'gitlab-managed-apps').and_return(service_account_resource)
- expect(client).to receive('get_cluster_role_binding').with('tiller-admin').and_return(cluster_role_binding_resource)
+ expect(client).to receive(:get_service_account).with('tiller', 'gitlab-managed-apps').and_return(service_account_resource)
+ expect(client).to receive(:get_cluster_role_binding).with('tiller-admin').and_return(cluster_role_binding_resource)
end
it 'updates the service account, followed by creating the cluster role binding' do
@@ -130,7 +151,7 @@ describe Gitlab::Kubernetes::Helm::Api do
context 'a non-404 error is thrown' do
before do
- expect(client).to receive('get_service_account').with('tiller', 'gitlab-managed-apps').and_raise(Kubeclient::HttpError.new(401, 'Unauthorized', nil))
+ expect(client).to receive(:get_service_account).with('tiller', 'gitlab-managed-apps').and_raise(Kubeclient::HttpError.new(401, 'Unauthorized', nil))
end
it 'raises an error' do
@@ -150,6 +171,51 @@ describe Gitlab::Kubernetes::Helm::Api do
end
end
+ describe '#update' do
+ let(:rbac) { false }
+
+ let(:command) do
+ Gitlab::Kubernetes::Helm::UpgradeCommand.new(
+ application_name,
+ chart: 'chart-name',
+ files: files,
+ rbac: rbac
+ )
+ end
+
+ before do
+ allow(namespace).to receive(:ensure_exists!).once
+
+ allow(client).to receive(:update_config_map).and_return(nil)
+ allow(client).to receive(:create_pod).and_return(nil)
+ allow(client).to receive(:delete_pod).and_return(nil)
+ end
+
+ it 'ensures the namespace exists before creating the pod' do
+ expect(namespace).to receive(:ensure_exists!).once.ordered
+ expect(client).to receive(:create_pod).once.ordered
+
+ subject.update(command)
+ end
+
+ it 'removes an existing pod before updating' do
+ expect(client).to receive(:delete_pod).with('upgrade-app-name', 'gitlab-managed-apps').once.ordered
+ expect(client).to receive(:create_pod).once.ordered
+
+ subject.update(command)
+ end
+
+ it 'updates the config map on kubeclient when one exists' do
+ resource = Gitlab::Kubernetes::ConfigMap.new(
+ application_name, files
+ ).generate
+
+ expect(client).to receive(:update_config_map).with(resource).once
+
+ subject.update(command)
+ end
+ end
+
describe '#status' do
let(:phase) { Gitlab::Kubernetes::Pod::RUNNING }
let(:pod) { Kubeclient::Resource.new(status: { phase: phase }) } # partial representation
@@ -174,9 +240,39 @@ describe Gitlab::Kubernetes::Helm::Api do
describe '#delete_pod!' do
it 'deletes the POD from kubernetes cluster' do
- expect(client).to receive(:delete_pod).with(command.pod_name, gitlab_namespace).once
+ expect(client).to receive(:delete_pod).with('install-app-name', 'gitlab-managed-apps').once
+
+ subject.delete_pod!('install-app-name')
+ end
+
+ context 'when the resource being deleted does not exist' do
+ it 'catches the error' do
+ expect(client).to receive(:delete_pod).with('install-app-name', 'gitlab-managed-apps')
+ .and_raise(Kubeclient::ResourceNotFoundError.new(404, 'Not found', nil))
+
+ subject.delete_pod!('install-app-name')
+ end
+ end
+ end
+
+ describe '#get_config_map' do
+ before do
+ allow(namespace).to receive(:ensure_exists!).once
+ allow(client).to receive(:get_config_map).and_return(nil)
+ end
+
+ it 'ensures the namespace exists before retrieving the config map' do
+ expect(namespace).to receive(:ensure_exists!).once
+
+ subject.get_config_map('example-config-map-name')
+ end
+
+ it 'gets the config map on kubeclient' do
+ expect(client).to receive(:get_config_map)
+ .with('example-config-map-name', namespace.name)
+ .once
- subject.delete_pod!(command.pod_name)
+ subject.get_config_map('example-config-map-name')
end
end
end
diff --git a/spec/lib/gitlab/kubernetes/helm/init_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/init_command_spec.rb
index 72dc1817936..4a3b9d4bf6a 100644
--- a/spec/lib/gitlab/kubernetes/helm/init_command_spec.rb
+++ b/spec/lib/gitlab/kubernetes/helm/init_command_spec.rb
@@ -8,7 +8,7 @@ describe Gitlab::Kubernetes::Helm::InitCommand do
let(:commands) do
<<~EOS
- helm init --tiller-tls --tiller-tls-verify --tls-ca-cert /data/helm/helm/config/ca.pem --tiller-tls-cert /data/helm/helm/config/cert.pem --tiller-tls-key /data/helm/helm/config/key.pem >/dev/null
+ helm init --tiller-tls --tiller-tls-verify --tls-ca-cert /data/helm/helm/config/ca.pem --tiller-tls-cert /data/helm/helm/config/cert.pem --tiller-tls-key /data/helm/helm/config/key.pem
EOS
end
@@ -22,7 +22,7 @@ describe Gitlab::Kubernetes::Helm::InitCommand do
it_behaves_like 'helm commands' do
let(:commands) do
<<~EOS
- helm init --tiller-tls --tiller-tls-verify --tls-ca-cert /data/helm/helm/config/ca.pem --tiller-tls-cert /data/helm/helm/config/cert.pem --tiller-tls-key /data/helm/helm/config/key.pem --service-account tiller >/dev/null
+ helm init --tiller-tls --tiller-tls-verify --tls-ca-cert /data/helm/helm/config/ca.pem --tiller-tls-cert /data/helm/helm/config/cert.pem --tiller-tls-key /data/helm/helm/config/key.pem --service-account tiller
EOS
end
end
diff --git a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
index f28941ce58f..82ed4d47857 100644
--- a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
+++ b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
@@ -5,6 +5,8 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
let(:repository) { 'https://repository.example.com' }
let(:rbac) { false }
let(:version) { '1.2.3' }
+ let(:preinstall) { nil }
+ let(:postinstall) { nil }
let(:install_command) do
described_class.new(
@@ -13,7 +15,9 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
rbac: rbac,
files: files,
version: version,
- repository: repository
+ repository: repository,
+ preinstall: preinstall,
+ postinstall: postinstall
)
end
@@ -22,8 +26,10 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
it_behaves_like 'helm commands' do
let(:commands) do
<<~EOS
- helm init --client-only >/dev/null
+ helm init --upgrade
+ for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done
helm repo add app-name https://repository.example.com
+ helm repo update
#{helm_install_comand}
EOS
end
@@ -37,8 +43,9 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
--tls-cert /data/helm/app-name/config/cert.pem
--tls-key /data/helm/app-name/config/key.pem
--version 1.2.3
+ --set rbac.create\\=false,rbac.enabled\\=false
--namespace gitlab-managed-apps
- -f /data/helm/app-name/config/values.yaml >/dev/null
+ -f /data/helm/app-name/config/values.yaml
EOS
end
end
@@ -49,8 +56,10 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
it_behaves_like 'helm commands' do
let(:commands) do
<<~EOS
- helm init --client-only >/dev/null
+ helm init --upgrade
+ for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done
helm repo add app-name https://repository.example.com
+ helm repo update
#{helm_install_command}
EOS
end
@@ -66,7 +75,7 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
--version 1.2.3
--set rbac.create\\=true,rbac.enabled\\=true
--namespace gitlab-managed-apps
- -f /data/helm/app-name/config/values.yaml >/dev/null
+ -f /data/helm/app-name/config/values.yaml
EOS
end
end
@@ -78,7 +87,8 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
it_behaves_like 'helm commands' do
let(:commands) do
<<~EOS
- helm init --client-only >/dev/null
+ helm init --upgrade
+ for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done
#{helm_install_command}
EOS
end
@@ -92,8 +102,57 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
--tls-cert /data/helm/app-name/config/cert.pem
--tls-key /data/helm/app-name/config/key.pem
--version 1.2.3
+ --set rbac.create\\=false,rbac.enabled\\=false
--namespace gitlab-managed-apps
- -f /data/helm/app-name/config/values.yaml >/dev/null
+ -f /data/helm/app-name/config/values.yaml
+ EOS
+ end
+ end
+ end
+
+ context 'when there is a pre-install script' do
+ let(:preinstall) { ['/bin/date', '/bin/true'] }
+
+ it_behaves_like 'helm commands' do
+ let(:commands) do
+ <<~EOS
+ helm init --upgrade
+ for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done
+ helm repo add app-name https://repository.example.com
+ helm repo update
+ #{helm_install_command}
+ EOS
+ end
+
+ let(:helm_install_command) do
+ <<~EOS.strip
+ /bin/date
+ /bin/true
+ helm install chart-name --name app-name --tls --tls-ca-cert /data/helm/app-name/config/ca.pem --tls-cert /data/helm/app-name/config/cert.pem --tls-key /data/helm/app-name/config/key.pem --version 1.2.3 --set rbac.create\\=false,rbac.enabled\\=false --namespace gitlab-managed-apps -f /data/helm/app-name/config/values.yaml
+ EOS
+ end
+ end
+ end
+
+ context 'when there is a post-install script' do
+ let(:postinstall) { ['/bin/date', "/bin/false\n"] }
+
+ it_behaves_like 'helm commands' do
+ let(:commands) do
+ <<~EOS
+ helm init --upgrade
+ for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done
+ helm repo add app-name https://repository.example.com
+ helm repo update
+ #{helm_install_command}
+ EOS
+ end
+
+ let(:helm_install_command) do
+ <<~EOS.strip
+ helm install chart-name --name app-name --tls --tls-ca-cert /data/helm/app-name/config/ca.pem --tls-cert /data/helm/app-name/config/cert.pem --tls-key /data/helm/app-name/config/key.pem --version 1.2.3 --set rbac.create\\=false,rbac.enabled\\=false --namespace gitlab-managed-apps -f /data/helm/app-name/config/values.yaml
+ /bin/date
+ /bin/false
EOS
end
end
@@ -105,8 +164,10 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
it_behaves_like 'helm commands' do
let(:commands) do
<<~EOS
- helm init --client-only >/dev/null
+ helm init --upgrade
+ for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done
helm repo add app-name https://repository.example.com
+ helm repo update
#{helm_install_command}
EOS
end
@@ -116,8 +177,9 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
helm install chart-name
--name app-name
--version 1.2.3
+ --set rbac.create\\=false,rbac.enabled\\=false
--namespace gitlab-managed-apps
- -f /data/helm/app-name/config/values.yaml >/dev/null
+ -f /data/helm/app-name/config/values.yaml
EOS
end
end
@@ -129,8 +191,10 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
it_behaves_like 'helm commands' do
let(:commands) do
<<~EOS
- helm init --client-only >/dev/null
+ helm init --upgrade
+ for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done
helm repo add app-name https://repository.example.com
+ helm repo update
#{helm_install_command}
EOS
end
@@ -143,8 +207,9 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
--tls-ca-cert /data/helm/app-name/config/ca.pem
--tls-cert /data/helm/app-name/config/cert.pem
--tls-key /data/helm/app-name/config/key.pem
+ --set rbac.create\\=false,rbac.enabled\\=false
--namespace gitlab-managed-apps
- -f /data/helm/app-name/config/values.yaml >/dev/null
+ -f /data/helm/app-name/config/values.yaml
EOS
end
end
diff --git a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb
index b333b334f36..2dd3a570a1d 100644
--- a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb
+++ b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb
@@ -30,7 +30,7 @@ describe Gitlab::Kubernetes::Helm::Pod do
it 'should generate the appropriate specifications for the container' do
container = subject.generate.spec.containers.first
expect(container.name).to eq('helm')
- expect(container.image).to eq('alpine:3.6')
+ expect(container.image).to eq('registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/2.11.0-kube-1.11.0')
expect(container.env.count).to eq(3)
expect(container.env.map(&:name)).to match_array([:HELM_VERSION, :TILLER_NAMESPACE, :COMMAND_SCRIPT])
expect(container.command).to match_array(["/bin/sh"])
diff --git a/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb
new file mode 100644
index 00000000000..9b201dae417
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/helm/upgrade_command_spec.rb
@@ -0,0 +1,140 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe Gitlab::Kubernetes::Helm::UpgradeCommand do
+ let(:application) { build(:clusters_applications_prometheus) }
+ let(:files) { { 'ca.pem': 'some file content' } }
+ let(:namespace) { ::Gitlab::Kubernetes::Helm::NAMESPACE }
+ let(:rbac) { false }
+ let(:upgrade_command) do
+ described_class.new(
+ application.name,
+ chart: application.chart,
+ files: files,
+ rbac: rbac
+ )
+ end
+
+ subject { upgrade_command }
+
+ it_behaves_like 'helm commands' do
+ let(:commands) do
+ <<~EOS
+ helm init --upgrade
+ for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done
+ helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml
+ EOS
+ end
+ end
+
+ context 'rbac is true' do
+ let(:rbac) { true }
+
+ it_behaves_like 'helm commands' do
+ let(:commands) do
+ <<~EOS
+ helm init --upgrade
+ for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done
+ helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml
+ EOS
+ end
+ end
+ end
+
+ context 'with an application with a repository' do
+ let(:ci_runner) { create(:ci_runner) }
+ let(:application) { build(:clusters_applications_runner, runner: ci_runner) }
+ let(:upgrade_command) do
+ described_class.new(
+ application.name,
+ chart: application.chart,
+ files: files,
+ rbac: rbac,
+ repository: application.repository
+ )
+ end
+
+ it_behaves_like 'helm commands' do
+ let(:commands) do
+ <<~EOS
+ helm init --upgrade
+ for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done
+ helm repo add #{application.name} #{application.repository}
+ helm upgrade #{application.name} #{application.chart} --tls --tls-ca-cert /data/helm/#{application.name}/config/ca.pem --tls-cert /data/helm/#{application.name}/config/cert.pem --tls-key /data/helm/#{application.name}/config/key.pem --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml
+ EOS
+ end
+ end
+ end
+
+ context 'when there is no ca.pem file' do
+ let(:files) { { 'file.txt': 'some content' } }
+
+ it_behaves_like 'helm commands' do
+ let(:commands) do
+ <<~EOS
+ helm init --upgrade
+ for i in $(seq 1 30); do helm version && break; sleep 1s; echo "Retrying ($i)..."; done
+ helm upgrade #{application.name} #{application.chart} --reset-values --install --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml
+ EOS
+ end
+ end
+ end
+
+ describe '#pod_resource' do
+ subject { upgrade_command.pod_resource }
+
+ context 'rbac is enabled' do
+ let(:rbac) { true }
+
+ it 'generates a pod that uses the tiller serviceAccountName' do
+ expect(subject.spec.serviceAccountName).to eq('tiller')
+ end
+ end
+
+ context 'rbac is not enabled' do
+ let(:rbac) { false }
+
+ it 'generates a pod that uses the default serviceAccountName' do
+ expect(subject.spec.serviceAcccountName).to be_nil
+ end
+ end
+ end
+
+ describe '#config_map_resource' do
+ let(:metadata) do
+ {
+ name: "values-content-configuration-#{application.name}",
+ namespace: namespace,
+ labels: { name: "values-content-configuration-#{application.name}" }
+ }
+ end
+ let(:resource) { ::Kubeclient::Resource.new(metadata: metadata, data: files) }
+
+ it 'returns a KubeClient resource with config map content for the application' do
+ expect(subject.config_map_resource).to eq(resource)
+ end
+ end
+
+ describe '#rbac?' do
+ subject { upgrade_command.rbac? }
+
+ context 'rbac is enabled' do
+ let(:rbac) { true }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'rbac is not enabled' do
+ let(:rbac) { false }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ describe '#pod_name' do
+ it 'returns the pod name' do
+ expect(subject.pod_name).to eq("upgrade-#{application.name}")
+ end
+ end
+end
diff --git a/spec/lib/gitlab/kubernetes/kube_client_spec.rb b/spec/lib/gitlab/kubernetes/kube_client_spec.rb
index 53c5a4e7c94..3979a43216c 100644
--- a/spec/lib/gitlab/kubernetes/kube_client_spec.rb
+++ b/spec/lib/gitlab/kubernetes/kube_client_spec.rb
@@ -6,104 +6,77 @@ describe Gitlab::Kubernetes::KubeClient do
include KubernetesHelpers
let(:api_url) { 'https://kubernetes.example.com/prefix' }
- let(:api_groups) { ['api', 'apis/rbac.authorization.k8s.io'] }
- let(:api_version) { 'v1' }
let(:kubeclient_options) { { auth_options: { bearer_token: 'xyz' } } }
- let(:client) { described_class.new(api_url, api_groups, api_version, kubeclient_options) }
+ let(:client) { described_class.new(api_url, kubeclient_options) }
before do
stub_kubeclient_discover(api_url)
end
- describe '#hashed_clients' do
- subject { client.hashed_clients }
-
- it 'has keys from api groups' do
- expect(subject.keys).to match_array api_groups
- end
-
- it 'has values of Kubeclient::Client' do
- expect(subject.values).to all(be_an_instance_of Kubeclient::Client)
- end
- end
-
- describe '#clients' do
- subject { client.clients }
-
- it 'is not empty' do
- is_expected.to be_present
- end
-
- it 'is an array of Kubeclient::Client objects' do
- is_expected.to all(be_an_instance_of Kubeclient::Client)
- end
-
- it 'has each API group url' do
- expected_urls = api_groups.map { |group| "#{api_url}/#{group}" }
-
- expect(subject.map(&:api_endpoint).map(&:to_s)).to match_array(expected_urls)
+ shared_examples 'a Kubeclient' do
+ it 'is a Kubeclient::Client' do
+ is_expected.to be_an_instance_of Kubeclient::Client
end
it 'has the kubeclient options' do
- subject.each do |client|
- expect(client.auth_options).to eq({ bearer_token: 'xyz' })
- end
- end
-
- it 'has the api_version' do
- subject.each do |client|
- expect(client.instance_variable_get(:@api_version)).to eq('v1')
- end
+ expect(subject.auth_options).to eq({ bearer_token: 'xyz' })
end
end
describe '#core_client' do
subject { client.core_client }
- it 'is a Kubeclient::Client' do
- is_expected.to be_an_instance_of Kubeclient::Client
- end
+ it_behaves_like 'a Kubeclient'
it 'has the core API endpoint' do
expect(subject.api_endpoint.to_s).to match(%r{\/api\Z})
end
+
+ it 'has the api_version' do
+ expect(subject.instance_variable_get(:@api_version)).to eq('v1')
+ end
end
describe '#rbac_client' do
subject { client.rbac_client }
- it 'is a Kubeclient::Client' do
- is_expected.to be_an_instance_of Kubeclient::Client
- end
+ it_behaves_like 'a Kubeclient'
it 'has the RBAC API group endpoint' do
expect(subject.api_endpoint.to_s).to match(%r{\/apis\/rbac.authorization.k8s.io\Z})
end
+
+ it 'has the api_version' do
+ expect(subject.instance_variable_get(:@api_version)).to eq('v1')
+ end
end
describe '#extensions_client' do
subject { client.extensions_client }
- let(:api_groups) { ['apis/extensions'] }
-
- it 'is a Kubeclient::Client' do
- is_expected.to be_an_instance_of Kubeclient::Client
- end
+ it_behaves_like 'a Kubeclient'
it 'has the extensions API group endpoint' do
expect(subject.api_endpoint.to_s).to match(%r{\/apis\/extensions\Z})
end
+
+ it 'has the api_version' do
+ expect(subject.instance_variable_get(:@api_version)).to eq('v1beta1')
+ end
end
- describe '#discover!' do
- it 'makes a discovery request for each API group' do
- client.discover!
+ describe '#knative_client' do
+ subject { client.knative_client }
- api_groups.each do |api_group|
- discovery_url = api_url + '/' + api_group + '/v1'
- expect(WebMock).to have_requested(:get, discovery_url).once
- end
+ it_behaves_like 'a Kubeclient'
+
+ it 'has the extensions API group endpoint' do
+ expect(subject.api_endpoint.to_s).to match(%r{\/apis\/serving.knative.dev\Z})
+ end
+
+ it 'has the api_version' do
+ expect(subject.instance_variable_get(:@api_version)).to eq('v1alpha1')
end
end
@@ -156,21 +129,12 @@ describe Gitlab::Kubernetes::KubeClient do
it 'responds to the method' do
expect(client).to respond_to method
end
-
- context 'no rbac client' do
- let(:api_groups) { ['api'] }
-
- it 'throws an error' do
- expect { client.public_send(method) }.to raise_error(Module::DelegationError)
- end
- end
end
end
end
describe 'extensions API group' do
let(:api_groups) { ['apis/extensions'] }
- let(:api_version) { 'v1beta1' }
let(:extensions_client) { client.extensions_client }
describe '#get_deployments' do
@@ -181,22 +145,11 @@ describe Gitlab::Kubernetes::KubeClient do
it 'responds to the method' do
expect(client).to respond_to :get_deployments
end
-
- context 'no extensions client' do
- let(:api_groups) { ['api'] }
- let(:api_version) { 'v1' }
-
- it 'throws an error' do
- expect { client.get_deployments }.to raise_error(Module::DelegationError)
- end
- end
end
end
describe 'non-entity methods' do
it 'does not proxy for non-entity methods' do
- expect(client.clients.first).to respond_to :proxy_url
-
expect(client).not_to respond_to :proxy_url
end
@@ -211,14 +164,6 @@ describe Gitlab::Kubernetes::KubeClient do
it 'is delegated to the core client' do
expect(client).to delegate_method(:get_pod_log).to(:core_client)
end
-
- context 'when no core client' do
- let(:api_groups) { ['apis/extensions'] }
-
- it 'throws an error' do
- expect { client.get_pod_log('pod-name') }.to raise_error(Module::DelegationError)
- end
- end
end
describe '#watch_pod_log' do
@@ -227,14 +172,6 @@ describe Gitlab::Kubernetes::KubeClient do
it 'is delegated to the core client' do
expect(client).to delegate_method(:watch_pod_log).to(:core_client)
end
-
- context 'when no core client' do
- let(:api_groups) { ['apis/extensions'] }
-
- it 'throws an error' do
- expect { client.watch_pod_log('pod-name') }.to raise_error(Module::DelegationError)
- end
- end
end
describe 'methods that do not exist on any client' do
diff --git a/spec/lib/gitlab/kubernetes/namespace_spec.rb b/spec/lib/gitlab/kubernetes/namespace_spec.rb
index e098612f6fb..e1c35c355f4 100644
--- a/spec/lib/gitlab/kubernetes/namespace_spec.rb
+++ b/spec/lib/gitlab/kubernetes/namespace_spec.rb
@@ -9,7 +9,7 @@ describe Gitlab::Kubernetes::Namespace do
describe '#exists?' do
context 'when namespace do not exits' do
- let(:exception) { ::Kubeclient::HttpError.new(404, "namespace #{name} not found", nil) }
+ let(:exception) { ::Kubeclient::ResourceNotFoundError.new(404, "namespace #{name} not found", nil) }
it 'returns false' do
expect(client).to receive(:get_namespace).with(name).once.and_raise(exception)
diff --git a/spec/lib/gitlab/kubernetes/role_binding_spec.rb b/spec/lib/gitlab/kubernetes/role_binding_spec.rb
new file mode 100644
index 00000000000..a1a59533bfb
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/role_binding_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Kubernetes::RoleBinding, '#generate' do
+ let(:role_name) { 'edit' }
+ let(:namespace) { 'my-namespace' }
+ let(:service_account_name) { 'my-service-account' }
+
+ let(:subjects) do
+ [
+ {
+ kind: 'ServiceAccount',
+ name: service_account_name,
+ namespace: namespace
+ }
+ ]
+ end
+
+ let(:role_ref) do
+ {
+ apiGroup: 'rbac.authorization.k8s.io',
+ kind: 'ClusterRole',
+ name: role_name
+ }
+ end
+
+ let(:resource) do
+ ::Kubeclient::Resource.new(
+ metadata: { name: "gitlab-#{namespace}", namespace: namespace },
+ roleRef: role_ref,
+ subjects: subjects
+ )
+ end
+
+ subject do
+ described_class.new(
+ name: "gitlab-#{namespace}",
+ role_name: role_name,
+ namespace: namespace,
+ service_account_name: service_account_name
+ ).generate
+ end
+
+ it 'should build a Kubeclient Resource' do
+ is_expected.to eq(resource)
+ end
+end
diff --git a/spec/lib/gitlab/language_data_spec.rb b/spec/lib/gitlab/language_data_spec.rb
new file mode 100644
index 00000000000..b08150855fe
--- /dev/null
+++ b/spec/lib/gitlab/language_data_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::LanguageData do
+ describe '#extensions' do
+ before do
+ described_class.clear_extensions!
+ end
+
+ it 'loads the extensions once' do
+ expect(YAML).to receive(:load_file).once.and_call_original
+
+ 2.times do
+ expect(described_class.extensions).to be_a(Set)
+ expect(described_class.extensions.count).to be > 0
+ # Sanity check for known extensions
+ expect(described_class.extensions).to include(*%w(.rb .yml .json))
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/legacy_github_import/importer_spec.rb b/spec/lib/gitlab/legacy_github_import/importer_spec.rb
index 20514486727..d2df21d7bb5 100644
--- a/spec/lib/gitlab/legacy_github_import/importer_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/importer_spec.rb
@@ -174,7 +174,7 @@ describe Gitlab::LegacyGithubImport::Importer do
described_class.new(project).execute
- expect(project.import_error).to eq error.to_json
+ expect(project.import_state.last_error).to eq error.to_json
end
end
diff --git a/spec/lib/gitlab/multi_collection_paginator_spec.rb b/spec/lib/gitlab/multi_collection_paginator_spec.rb
index 68bd4f93159..28cd704b05a 100644
--- a/spec/lib/gitlab/multi_collection_paginator_spec.rb
+++ b/spec/lib/gitlab/multi_collection_paginator_spec.rb
@@ -28,7 +28,7 @@ describe Gitlab::MultiCollectionPaginator do
expect(paginator.paginate(1)).to eq(all_projects.take(3))
end
- it 'fils the second page with a mixture of of the first & second collection' do
+ it 'fils the second page with a mixture of the first & second collection' do
first_collection_element = all_projects.last
second_collection_elements = all_groups.take(2)
diff --git a/spec/lib/gitlab/null_request_store_spec.rb b/spec/lib/gitlab/null_request_store_spec.rb
new file mode 100644
index 00000000000..c023dac53ad
--- /dev/null
+++ b/spec/lib/gitlab/null_request_store_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::NullRequestStore do
+ let(:null_store) { described_class.new }
+
+ describe '#store' do
+ it 'returns an empty hash' do
+ expect(null_store.store).to eq({})
+ end
+ end
+
+ describe '#active?' do
+ it 'returns falsey' do
+ expect(null_store.active?).to be_falsey
+ end
+ end
+
+ describe '#read' do
+ it 'returns nil' do
+ expect(null_store.read('foo')).to be nil
+ end
+ end
+
+ describe '#[]' do
+ it 'returns nil' do
+ expect(null_store['foo']).to be nil
+ end
+ end
+
+ describe '#write' do
+ it 'returns the same value' do
+ expect(null_store.write('key', 'value')).to eq('value')
+ end
+ end
+
+ describe '#[]=' do
+ it 'returns the same value' do
+ expect(null_store['key'] = 'value').to eq('value')
+ end
+ end
+
+ describe '#exist?' do
+ it 'returns falsey' do
+ expect(null_store.exist?('foo')).to be_falsey
+ end
+ end
+
+ describe '#fetch' do
+ it 'returns the block result' do
+ expect(null_store.fetch('key') { 'block result' }).to eq('block result')
+ end
+ end
+
+ describe '#delete' do
+ context 'when a block is given' do
+ it 'yields the key to the block' do
+ expect do |b|
+ null_store.delete('foo', &b)
+ end.to yield_with_args('foo')
+ end
+
+ it 'returns the block result' do
+ expect(null_store.delete('foo') { |key| 'block result' }).to eq('block result')
+ end
+ end
+
+ context 'when a block is not given' do
+ it 'returns nil' do
+ expect(null_store.delete('foo')).to be nil
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/patch/draw_route_spec.rb b/spec/lib/gitlab/patch/draw_route_spec.rb
new file mode 100644
index 00000000000..4009b903dc3
--- /dev/null
+++ b/spec/lib/gitlab/patch/draw_route_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+describe Gitlab::Patch::DrawRoute do
+ subject do
+ Class.new do
+ include Gitlab::Patch::DrawRoute
+
+ def route_path(route_name)
+ File.expand_path("../../../../#{route_name}", __dir__)
+ end
+ end.new
+ end
+
+ before do
+ allow(subject).to receive(:instance_eval)
+ end
+
+ it 'evaluates CE only route' do
+ subject.draw(:help)
+
+ expect(subject).to have_received(:instance_eval)
+ .with(File.read(subject.route_path('config/routes/help.rb')))
+ .once
+
+ expect(subject).to have_received(:instance_eval)
+ .once
+ end
+end
diff --git a/spec/lib/gitlab/private_commit_email_spec.rb b/spec/lib/gitlab/private_commit_email_spec.rb
new file mode 100644
index 00000000000..10bf624bbdd
--- /dev/null
+++ b/spec/lib/gitlab/private_commit_email_spec.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::PrivateCommitEmail do
+ let(:hostname) { Gitlab::CurrentSettings.current_application_settings.commit_email_hostname }
+ let(:id) { 1 }
+ let(:valid_email) { "#{id}-foo@#{hostname}" }
+ let(:invalid_email) { "#{id}-foo@users.noreply.bar.com" }
+
+ context '.regex' do
+ subject { described_class.regex }
+
+ it { is_expected.to match("1-foo@#{hostname}") }
+ it { is_expected.not_to match("1-foo@#{hostname}.foo") }
+ it { is_expected.not_to match('1-foo@users.noreply.gitlab.com') }
+ it { is_expected.not_to match('foo-1@users.noreply.gitlab.com') }
+ it { is_expected.not_to match('foobar@gitlab.com') }
+ end
+
+ context '.user_id_for_email' do
+ it 'parses user id from email' do
+ expect(described_class.user_id_for_email(valid_email)).to eq(id)
+ end
+
+ it 'returns nil on invalid commit email' do
+ expect(described_class.user_id_for_email(invalid_email)).to be_nil
+ end
+ end
+
+ context '.user_ids_for_email' do
+ it 'returns deduplicated user IDs for each valid email' do
+ result = described_class.user_ids_for_emails([valid_email, valid_email, invalid_email])
+
+ expect(result).to eq([id])
+ end
+
+ it 'returns an empty array with no valid emails' do
+ result = described_class.user_ids_for_emails([invalid_email])
+ expect(result).to eq([])
+ end
+ end
+
+ context '.for_user' do
+ it 'returns email in the format id-username@hostname' do
+ user = create(:user)
+
+ expect(described_class.for_user(user)).to eq("#{user.id}-#{user.username}@#{hostname}")
+ end
+ end
+end
diff --git a/spec/lib/gitlab/profiler_spec.rb b/spec/lib/gitlab/profiler_spec.rb
index 4059188fba1..8bb0c1a0b8a 100644
--- a/spec/lib/gitlab/profiler_spec.rb
+++ b/spec/lib/gitlab/profiler_spec.rb
@@ -43,31 +43,16 @@ describe Gitlab::Profiler do
it 'uses the user for auth if given' do
user = double(:user)
- user_token = 'user'
- allow(user).to receive_message_chain(:personal_access_tokens, :active, :pluck, :first).and_return(user_token)
-
- expect(app).to receive(:get).with('/', nil, 'Private-Token' => user_token)
- expect(app).to receive(:get).with('/api/v4/users')
+ expect(described_class).to receive(:with_user).with(user)
described_class.profile('/', user: user)
end
- context 'when providing a user without a personal access token' do
- it 'raises an error' do
- user = double(:user)
- allow(user).to receive_message_chain(:personal_access_tokens, :active, :pluck).and_return([])
-
- expect { described_class.profile('/', user: user) }.to raise_error('Your user must have a personal_access_token')
- end
- end
-
it 'uses the private_token for auth if both it and user are set' do
user = double(:user)
- user_token = 'user'
-
- allow(user).to receive_message_chain(:personal_access_tokens, :active, :pluck, :first).and_return(user_token)
+ expect(described_class).to receive(:with_user).with(nil).and_call_original
expect(app).to receive(:get).with('/', nil, 'Private-Token' => private_token)
expect(app).to receive(:get).with('/api/v4/users')
@@ -210,6 +195,29 @@ describe Gitlab::Profiler do
end
end
+ describe '.with_user' do
+ context 'when the user is set' do
+ let(:user) { double(:user) }
+
+ it 'overrides auth in ApplicationController to use the given user' do
+ expect(described_class.with_user(user) { ApplicationController.new.current_user }).to eq(user)
+ end
+
+ it 'cleans up ApplicationController afterwards' do
+ expect { described_class.with_user(user) { } }
+ .to not_change { ActionController.instance_methods(false) }
+ end
+ end
+
+ context 'when the user is nil' do
+ it 'does not define methods on ApplicationController' do
+ expect(ApplicationController).not_to receive(:define_method)
+
+ described_class.with_user(nil) { }
+ end
+ end
+ end
+
describe '.log_load_times_by_model' do
it 'logs the model, query count, and time by slowest first' do
expect(null_logger).to receive(:load_times_by_model).and_return(
diff --git a/spec/lib/gitlab/prometheus/query_variables_spec.rb b/spec/lib/gitlab/prometheus/query_variables_spec.rb
new file mode 100644
index 00000000000..78974cadb69
--- /dev/null
+++ b/spec/lib/gitlab/prometheus/query_variables_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Prometheus::QueryVariables do
+ describe '.call' do
+ set(:environment) { create(:environment) }
+ let(:slug) { environment.slug }
+
+ subject { described_class.call(environment) }
+
+ it { is_expected.to include(ci_environment_slug: slug) }
+
+ it do
+ is_expected.to include(environment_filter:
+ %{container_name!="POD",environment="#{slug}"})
+ end
+
+ context 'without deployment platform' do
+ it { is_expected.to include(kube_namespace: '') }
+ end
+
+ context 'with deplyoment platform' do
+ let(:kube_namespace) { environment.deployment_platform.actual_namespace }
+
+ before do
+ create(:cluster, :provided_by_user, projects: [environment.project])
+ end
+
+ it { is_expected.to include(kube_namespace: kube_namespace) }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/quick_actions/command_definition_spec.rb b/spec/lib/gitlab/quick_actions/command_definition_spec.rb
index b03c1e23ca3..5dae82a63b4 100644
--- a/spec/lib/gitlab/quick_actions/command_definition_spec.rb
+++ b/spec/lib/gitlab/quick_actions/command_definition_spec.rb
@@ -210,6 +210,19 @@ describe Gitlab::QuickActions::CommandDefinition do
end
end
+ context 'when warning is set' do
+ before do
+ subject.explanation = 'Explanation'
+ subject.warning = 'dangerous!'
+ end
+
+ it 'returns this static string' do
+ result = subject.explain({}, nil)
+
+ expect(result).to eq 'Explanation (dangerous!)'
+ end
+ end
+
context 'when the explanation is dynamic' do
before do
subject.explanation = proc { |arg| "Dynamic #{arg}" }
diff --git a/spec/lib/gitlab/quick_actions/dsl_spec.rb b/spec/lib/gitlab/quick_actions/dsl_spec.rb
index 067a30fd7e2..fd4df8694ba 100644
--- a/spec/lib/gitlab/quick_actions/dsl_spec.rb
+++ b/spec/lib/gitlab/quick_actions/dsl_spec.rb
@@ -12,6 +12,7 @@ describe Gitlab::QuickActions::Dsl do
params 'The first argument'
explanation 'Static explanation'
+ warning 'Possible problem!'
command :explanation_with_aliases, :once, :first do |arg|
arg
end
@@ -64,6 +65,7 @@ describe Gitlab::QuickActions::Dsl do
expect(no_args_def.condition_block).to be_nil
expect(no_args_def.action_block).to be_a_kind_of(Proc)
expect(no_args_def.parse_params_block).to be_nil
+ expect(no_args_def.warning).to eq('')
expect(explanation_with_aliases_def.name).to eq(:explanation_with_aliases)
expect(explanation_with_aliases_def.aliases).to eq([:once, :first])
@@ -73,6 +75,7 @@ describe Gitlab::QuickActions::Dsl do
expect(explanation_with_aliases_def.condition_block).to be_nil
expect(explanation_with_aliases_def.action_block).to be_a_kind_of(Proc)
expect(explanation_with_aliases_def.parse_params_block).to be_nil
+ expect(explanation_with_aliases_def.warning).to eq('Possible problem!')
expect(dynamic_description_def.name).to eq(:dynamic_description)
expect(dynamic_description_def.aliases).to eq([])
@@ -82,6 +85,7 @@ describe Gitlab::QuickActions::Dsl do
expect(dynamic_description_def.condition_block).to be_nil
expect(dynamic_description_def.action_block).to be_a_kind_of(Proc)
expect(dynamic_description_def.parse_params_block).to be_nil
+ expect(dynamic_description_def.warning).to eq('')
expect(cc_def.name).to eq(:cc)
expect(cc_def.aliases).to eq([])
@@ -91,6 +95,7 @@ describe Gitlab::QuickActions::Dsl do
expect(cc_def.condition_block).to be_nil
expect(cc_def.action_block).to be_nil
expect(cc_def.parse_params_block).to be_nil
+ expect(cc_def.warning).to eq('')
expect(cond_action_def.name).to eq(:cond_action)
expect(cond_action_def.aliases).to eq([])
@@ -100,6 +105,7 @@ describe Gitlab::QuickActions::Dsl do
expect(cond_action_def.condition_block).to be_a_kind_of(Proc)
expect(cond_action_def.action_block).to be_a_kind_of(Proc)
expect(cond_action_def.parse_params_block).to be_nil
+ expect(cond_action_def.warning).to eq('')
expect(with_params_parsing_def.name).to eq(:with_params_parsing)
expect(with_params_parsing_def.aliases).to eq([])
@@ -109,6 +115,7 @@ describe Gitlab::QuickActions::Dsl do
expect(with_params_parsing_def.condition_block).to be_nil
expect(with_params_parsing_def.action_block).to be_a_kind_of(Proc)
expect(with_params_parsing_def.parse_params_block).to be_a_kind_of(Proc)
+ expect(with_params_parsing_def.warning).to eq('')
expect(substitution_def.name).to eq(:something)
expect(substitution_def.aliases).to eq([])
@@ -118,6 +125,7 @@ describe Gitlab::QuickActions::Dsl do
expect(substitution_def.condition_block).to be_nil
expect(substitution_def.action_block.call('text')).to eq('text Some complicated thing you want in here')
expect(substitution_def.parse_params_block).to be_nil
+ expect(substitution_def.warning).to eq('')
end
end
end
diff --git a/spec/lib/gitlab/quick_actions/extractor_spec.rb b/spec/lib/gitlab/quick_actions/extractor_spec.rb
index 0166f6c2ee0..873bb359d6e 100644
--- a/spec/lib/gitlab/quick_actions/extractor_spec.rb
+++ b/spec/lib/gitlab/quick_actions/extractor_spec.rb
@@ -272,5 +272,24 @@ describe Gitlab::QuickActions::Extractor do
expect(commands).to be_empty
expect(msg).to eq expected
end
+
+ it 'limits to passed commands when they are passed' do
+ msg = <<~MSG.strip
+ Hello, we should only extract the commands passed
+ /reopen
+ /labels hello world
+ /power
+ MSG
+ expected_msg = <<~EXPECTED.strip
+ Hello, we should only extract the commands passed
+ /power
+ EXPECTED
+ expected_commands = [['reopen'], ['labels', 'hello world']]
+
+ msg, commands = extractor.extract_commands(msg, only: [:open, :labels])
+
+ expect(commands).to eq(expected_commands)
+ expect(msg).to eq expected_msg
+ end
end
end
diff --git a/spec/lib/gitlab/repository_cache_adapter_spec.rb b/spec/lib/gitlab/repository_cache_adapter_spec.rb
index 5bd4d6c6a48..0295138fc3a 100644
--- a/spec/lib/gitlab/repository_cache_adapter_spec.rb
+++ b/spec/lib/gitlab/repository_cache_adapter_spec.rb
@@ -65,6 +65,144 @@ describe Gitlab::RepositoryCacheAdapter do
end
end
+ describe '#cache_method_output_asymmetrically', :use_clean_rails_memory_store_caching, :request_store do
+ let(:request_store_cache) { repository.send(:request_store_cache) }
+
+ context 'with a non-existing repository' do
+ let(:project) { create(:project) } # No repository
+ let(:object) { double }
+
+ subject do
+ repository.cache_method_output_asymmetrically(:cats) do
+ object.cats_call_stub
+ end
+ end
+
+ it 'returns the output of the original method' do
+ expect(object).to receive(:cats_call_stub).and_return('output')
+
+ expect(subject).to eq('output')
+ end
+ end
+
+ context 'with a method throwing a non-existing-repository error' do
+ subject do
+ repository.cache_method_output_asymmetrically(:cats) do
+ raise Gitlab::Git::Repository::NoRepository
+ end
+ end
+
+ it 'returns nil' do
+ expect(subject).to eq(nil)
+ end
+
+ it 'does not cache the data' do
+ subject
+
+ expect(repository.instance_variable_defined?(:@cats)).to eq(false)
+ expect(cache.exist?(:cats)).to eq(false)
+ end
+ end
+
+ context 'with an existing repository' do
+ let(:object) { double }
+
+ context 'when it returns truthy' do
+ before do
+ expect(object).to receive(:cats).once.and_return('truthy output')
+ end
+
+ it 'caches the output in RequestStore' do
+ expect do
+ repository.cache_method_output_asymmetrically(:cats) { object.cats }
+ end.to change { request_store_cache.read(:cats) }.from(nil).to('truthy output')
+ end
+
+ it 'caches the output in RepositoryCache' do
+ expect do
+ repository.cache_method_output_asymmetrically(:cats) { object.cats }
+ end.to change { cache.read(:cats) }.from(nil).to('truthy output')
+ end
+ end
+
+ context 'when it returns false' do
+ before do
+ expect(object).to receive(:cats).once.and_return(false)
+ end
+
+ it 'caches the output in RequestStore' do
+ expect do
+ repository.cache_method_output_asymmetrically(:cats) { object.cats }
+ end.to change { request_store_cache.read(:cats) }.from(nil).to(false)
+ end
+
+ it 'does NOT cache the output in RepositoryCache' do
+ expect do
+ repository.cache_method_output_asymmetrically(:cats) { object.cats }
+ end.not_to change { cache.read(:cats) }.from(nil)
+ end
+ end
+ end
+ end
+
+ describe '#memoize_method_output' do
+ let(:fallback) { 10 }
+
+ context 'with a non-existing repository' do
+ let(:project) { create(:project) } # No repository
+
+ subject do
+ repository.memoize_method_output(:cats, fallback: fallback) do
+ repository.cats_call_stub
+ end
+ end
+
+ it 'returns the fallback value' do
+ expect(subject).to eq(fallback)
+ end
+
+ it 'avoids calling the original method' do
+ expect(repository).not_to receive(:cats_call_stub)
+
+ subject
+ end
+
+ it 'does not set the instance variable' do
+ subject
+
+ expect(repository.instance_variable_defined?(:@cats)).to eq(false)
+ end
+ end
+
+ context 'with a method throwing a non-existing-repository error' do
+ subject do
+ repository.memoize_method_output(:cats, fallback: fallback) do
+ raise Gitlab::Git::Repository::NoRepository
+ end
+ end
+
+ it 'returns the fallback value' do
+ expect(subject).to eq(fallback)
+ end
+
+ it 'does not set the instance variable' do
+ subject
+
+ expect(repository.instance_variable_defined?(:@cats)).to eq(false)
+ end
+ end
+
+ context 'with an existing repository' do
+ it 'sets the instance variable' do
+ repository.memoize_method_output(:cats, fallback: fallback) do
+ 'block output'
+ end
+
+ expect(repository.instance_variable_get(:@cats)).to eq('block output')
+ end
+ end
+ end
+
describe '#expire_method_caches' do
it 'expires the caches of the given methods' do
expect(cache).to receive(:expire).with(:rendered_readme)
diff --git a/spec/lib/gitlab/repository_cache_spec.rb b/spec/lib/gitlab/repository_cache_spec.rb
index fc259cf1208..1b9a8b4ab0d 100644
--- a/spec/lib/gitlab/repository_cache_spec.rb
+++ b/spec/lib/gitlab/repository_cache_spec.rb
@@ -4,14 +4,14 @@ describe Gitlab::RepositoryCache do
let(:backend) { double('backend').as_null_object }
let(:project) { create(:project) }
let(:repository) { project.repository }
- let(:namespace) { "#{repository.full_path}:#{project.id}" }
+ let(:namespace) { "project:#{project.id}" }
let(:cache) { described_class.new(repository, backend: backend) }
describe '#cache_key' do
subject { cache.cache_key(:foo) }
it 'includes the namespace' do
- expect(subject).to eq "foo:#{namespace}"
+ expect(subject).to eq "#{namespace}:foo"
end
context 'with a given namespace' do
@@ -22,7 +22,7 @@ describe Gitlab::RepositoryCache do
end
it 'includes the full namespace' do
- expect(subject).to eq "foo:#{namespace}:#{extra_namespace}"
+ expect(subject).to eq "#{namespace}:#{extra_namespace}:foo"
end
end
end
@@ -30,21 +30,106 @@ describe Gitlab::RepositoryCache do
describe '#expire' do
it 'expires the given key from the cache' do
cache.expire(:foo)
- expect(backend).to have_received(:delete).with("foo:#{namespace}")
+ expect(backend).to have_received(:delete).with("#{namespace}:foo")
end
end
describe '#fetch' do
it 'fetches the given key from the cache' do
cache.fetch(:bar)
- expect(backend).to have_received(:fetch).with("bar:#{namespace}")
+ expect(backend).to have_received(:fetch).with("#{namespace}:bar")
end
it 'accepts a block' do
p = -> {}
cache.fetch(:baz, &p)
- expect(backend).to have_received(:fetch).with("baz:#{namespace}", &p)
+ expect(backend).to have_received(:fetch).with("#{namespace}:baz", &p)
+ end
+ end
+
+ describe '#fetch_without_caching_false', :use_clean_rails_memory_store_caching do
+ let(:key) { :foo }
+ let(:backend) { Rails.cache }
+
+ it 'requires a block' do
+ expect do
+ cache.fetch_without_caching_false(key)
+ end.to raise_error(LocalJumpError)
+ end
+
+ context 'when the key does not exist in the cache' do
+ context 'when the result of the block is truthy' do
+ it 'returns the result of the block' do
+ result = cache.fetch_without_caching_false(key) { true }
+
+ expect(result).to be true
+ end
+
+ it 'caches the value' do
+ expect(backend).to receive(:write).with("#{namespace}:#{key}", true)
+
+ cache.fetch_without_caching_false(key) { true }
+ end
+ end
+
+ context 'when the result of the block is falsey' do
+ let(:p) { -> { false } }
+
+ it 'returns the result of the block' do
+ result = cache.fetch_without_caching_false(key, &p)
+
+ expect(result).to be false
+ end
+
+ it 'does not cache the value' do
+ expect(backend).not_to receive(:write).with("#{namespace}:#{key}", true)
+
+ cache.fetch_without_caching_false(key, &p)
+ end
+ end
+ end
+
+ context 'when the cached value is truthy' do
+ before do
+ backend.write("#{namespace}:#{key}", true)
+ end
+
+ it 'returns the cached value' do
+ result = cache.fetch_without_caching_false(key) { 'block result' }
+
+ expect(result).to be true
+ end
+
+ it 'does not execute the block' do
+ expect do |b|
+ cache.fetch_without_caching_false(key, &b)
+ end.not_to yield_control
+ end
+
+ it 'does not write to the cache' do
+ expect(backend).not_to receive(:write)
+
+ cache.fetch_without_caching_false(key) { 'block result' }
+ end
+ end
+
+ context 'when the cached value is falsey' do
+ before do
+ backend.write("#{namespace}:#{key}", false)
+ end
+
+ it 'returns the result of the block' do
+ result = cache.fetch_without_caching_false(key) { 'block result' }
+
+ expect(result).to eq 'block result'
+ end
+
+ it 'writes the truthy value to the cache' do
+ expect(backend).to receive(:write).with("#{namespace}:#{key}", 'block result')
+
+ cache.fetch_without_caching_false(key) { 'block result' }
+ end
end
end
end
diff --git a/spec/lib/gitlab/safe_request_store_spec.rb b/spec/lib/gitlab/safe_request_store_spec.rb
new file mode 100644
index 00000000000..c797171dbe2
--- /dev/null
+++ b/spec/lib/gitlab/safe_request_store_spec.rb
@@ -0,0 +1,245 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::SafeRequestStore do
+ describe '.store' do
+ context 'when RequestStore is active', :request_store do
+ it 'uses RequestStore' do
+ expect(described_class.store).to eq(RequestStore)
+ end
+ end
+
+ context 'when RequestStore is NOT active' do
+ it 'does not use RequestStore' do
+ expect(described_class.store).to be_a(Gitlab::NullRequestStore)
+ end
+ end
+ end
+
+ describe '.begin!' do
+ context 'when RequestStore is active', :request_store do
+ it 'uses RequestStore' do
+ expect(RequestStore).to receive(:begin!)
+
+ described_class.begin!
+ end
+ end
+
+ context 'when RequestStore is NOT active' do
+ it 'uses RequestStore' do
+ expect(RequestStore).to receive(:begin!)
+
+ described_class.begin!
+ end
+ end
+ end
+
+ describe '.clear!' do
+ context 'when RequestStore is active', :request_store do
+ it 'uses RequestStore' do
+ expect(RequestStore).to receive(:clear!).twice.and_call_original
+
+ described_class.clear!
+ end
+ end
+
+ context 'when RequestStore is NOT active' do
+ it 'uses RequestStore' do
+ expect(RequestStore).to receive(:clear!).and_call_original
+
+ described_class.clear!
+ end
+ end
+ end
+
+ describe '.end!' do
+ context 'when RequestStore is active', :request_store do
+ it 'uses RequestStore' do
+ expect(RequestStore).to receive(:end!).twice.and_call_original
+
+ described_class.end!
+ end
+ end
+
+ context 'when RequestStore is NOT active' do
+ it 'uses RequestStore' do
+ expect(RequestStore).to receive(:end!).and_call_original
+
+ described_class.end!
+ end
+ end
+ end
+
+ describe '.write' do
+ context 'when RequestStore is active', :request_store do
+ it 'uses RequestStore' do
+ expect do
+ described_class.write('foo', true)
+ end.to change { described_class.read('foo') }.from(nil).to(true)
+ end
+ end
+
+ context 'when RequestStore is NOT active' do
+ it 'does not use RequestStore' do
+ expect do
+ described_class.write('foo', true)
+ end.not_to change { described_class.read('foo') }.from(nil)
+ end
+ end
+ end
+
+ describe '.[]=' do
+ context 'when RequestStore is active', :request_store do
+ it 'uses RequestStore' do
+ expect do
+ described_class['foo'] = true
+ end.to change { described_class.read('foo') }.from(nil).to(true)
+ end
+ end
+
+ context 'when RequestStore is NOT active' do
+ it 'does not use RequestStore' do
+ expect do
+ described_class['foo'] = true
+ end.not_to change { described_class.read('foo') }.from(nil)
+ end
+ end
+ end
+
+ describe '.read' do
+ context 'when RequestStore is active', :request_store do
+ it 'uses RequestStore' do
+ expect do
+ RequestStore.write('foo', true)
+ end.to change { described_class.read('foo') }.from(nil).to(true)
+ end
+ end
+
+ context 'when RequestStore is NOT active' do
+ it 'does not use RequestStore' do
+ expect do
+ RequestStore.write('foo', true)
+ end.not_to change { described_class.read('foo') }.from(nil)
+
+ RequestStore.clear! # Clean up
+ end
+ end
+ end
+
+ describe '.[]' do
+ context 'when RequestStore is active', :request_store do
+ it 'uses RequestStore' do
+ expect do
+ RequestStore.write('foo', true)
+ end.to change { described_class['foo'] }.from(nil).to(true)
+ end
+ end
+
+ context 'when RequestStore is NOT active' do
+ it 'does not use RequestStore' do
+ expect do
+ RequestStore.write('foo', true)
+ end.not_to change { described_class['foo'] }.from(nil)
+
+ RequestStore.clear! # Clean up
+ end
+ end
+ end
+
+ describe '.exist?' do
+ context 'when RequestStore is active', :request_store do
+ it 'uses RequestStore' do
+ expect do
+ RequestStore.write('foo', 'not nil')
+ end.to change { described_class.exist?('foo') }.from(false).to(true)
+ end
+ end
+
+ context 'when RequestStore is NOT active' do
+ it 'does not use RequestStore' do
+ expect do
+ RequestStore.write('foo', 'not nil')
+ end.not_to change { described_class.exist?('foo') }.from(false)
+
+ RequestStore.clear! # Clean up
+ end
+ end
+ end
+
+ describe '.fetch' do
+ context 'when RequestStore is active', :request_store do
+ it 'uses RequestStore' do
+ expect do
+ described_class.fetch('foo') { 'block result' }
+ end.to change { described_class.read('foo') }.from(nil).to('block result')
+ end
+ end
+
+ context 'when RequestStore is NOT active' do
+ it 'does not use RequestStore' do
+ RequestStore.clear! # Ensure clean
+
+ expect do
+ described_class.fetch('foo') { 'block result' }
+ end.not_to change { described_class.read('foo') }.from(nil)
+
+ RequestStore.clear! # Clean up
+ end
+ end
+ end
+
+ describe '.delete' do
+ context 'when RequestStore is active', :request_store do
+ it 'uses RequestStore' do
+ described_class.write('foo', true)
+
+ expect do
+ described_class.delete('foo')
+ end.to change { described_class.read('foo') }.from(true).to(nil)
+ end
+
+ context 'when given a block and the key exists' do
+ it 'does not execute the block' do
+ described_class.write('foo', true)
+
+ expect do |b|
+ described_class.delete('foo', &b)
+ end.not_to yield_control
+ end
+ end
+
+ context 'when given a block and the key does not exist' do
+ it 'yields the key and returns the block result' do
+ result = described_class.delete('foo') { |key| "#{key} block result" }
+
+ expect(result).to eq('foo block result')
+ end
+ end
+ end
+
+ context 'when RequestStore is NOT active' do
+ before do
+ RequestStore.write('foo', true)
+ end
+
+ after do
+ RequestStore.clear! # Clean up
+ end
+
+ it 'does not use RequestStore' do
+ expect do
+ described_class.delete('foo')
+ end.not_to change { RequestStore.read('foo') }.from(true)
+ end
+
+ context 'when given a block' do
+ it 'yields the key and returns the block result' do
+ result = described_class.delete('foo') { |key| "#{key} block result" }
+
+ expect(result).to eq('foo block result')
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/sentry_spec.rb b/spec/lib/gitlab/sentry_spec.rb
index 499757da061..d3b41b27b80 100644
--- a/spec/lib/gitlab/sentry_spec.rb
+++ b/spec/lib/gitlab/sentry_spec.rb
@@ -52,4 +52,28 @@ describe Gitlab::Sentry do
end
end
end
+
+ context '.track_acceptable_exception' do
+ let(:exception) { RuntimeError.new('boom') }
+
+ before do
+ allow(described_class).to receive(:enabled?).and_return(true)
+ end
+
+ it 'calls Raven.capture_exception' do
+ expected_extras = {
+ some_other_info: 'info',
+ issue_url: 'http://gitlab.com/gitlab-org/gitlab-ce/issues/1'
+ }
+
+ expect(Raven).to receive(:capture_exception)
+ .with(exception, extra: a_hash_including(expected_extras))
+
+ described_class.track_acceptable_exception(
+ exception,
+ issue_url: 'http://gitlab.com/gitlab-org/gitlab-ce/issues/1',
+ extra: { some_other_info: 'info' }
+ )
+ end
+ end
end
diff --git a/spec/lib/gitlab/shell_spec.rb b/spec/lib/gitlab/shell_spec.rb
index b1b7c427313..6ce9d515a0f 100644
--- a/spec/lib/gitlab/shell_spec.rb
+++ b/spec/lib/gitlab/shell_spec.rb
@@ -498,126 +498,6 @@ describe Gitlab::Shell do
end
end
- describe '#fetch_remote' do
- def fetch_remote(ssh_auth = nil, prune = true)
- gitlab_shell.fetch_remote(repository.raw_repository, 'remote-name', ssh_auth: ssh_auth, prune: prune)
- end
-
- def expect_call(fail, options = {})
- receive_fetch_remote =
- if fail
- receive(:fetch_remote).and_raise(GRPC::NotFound)
- else
- receive(:fetch_remote).and_return(true)
- end
-
- expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive_fetch_remote
- end
-
- def build_ssh_auth(opts = {})
- defaults = {
- ssh_import?: true,
- ssh_key_auth?: false,
- ssh_known_hosts: nil,
- ssh_private_key: nil
- }
-
- double(:ssh_auth, defaults.merge(opts))
- end
-
- it 'returns true when the command succeeds' do
- expect_call(false, force: false, tags: true, prune: true)
-
- expect(fetch_remote).to be_truthy
- end
-
- it 'returns true when the command succeeds' do
- expect_call(false, force: false, tags: true, prune: false)
-
- expect(fetch_remote(nil, false)).to be_truthy
- end
-
- it 'raises an exception when the command fails' do
- expect_call(true, force: false, tags: true, prune: true)
-
- expect { fetch_remote }.to raise_error(Gitlab::Shell::Error)
- end
-
- it 'allows forced and no_tags to be changed' do
- expect_call(false, force: true, tags: false, prune: true)
-
- result = gitlab_shell.fetch_remote(repository.raw_repository, 'remote-name', forced: true, no_tags: true, prune: true)
- expect(result).to be_truthy
- end
-
- context 'SSH auth' do
- it 'passes the SSH key if specified' do
- expect_call(false, force: false, tags: true, prune: true, ssh_key: 'foo')
-
- ssh_auth = build_ssh_auth(ssh_key_auth?: true, ssh_private_key: 'foo')
-
- expect(fetch_remote(ssh_auth)).to be_truthy
- end
-
- it 'does not pass an empty SSH key' do
- expect_call(false, force: false, tags: true, prune: true)
-
- ssh_auth = build_ssh_auth(ssh_key_auth: true, ssh_private_key: '')
-
- expect(fetch_remote(ssh_auth)).to be_truthy
- end
-
- it 'does not pass the key unless SSH key auth is to be used' do
- expect_call(false, force: false, tags: true, prune: true)
-
- ssh_auth = build_ssh_auth(ssh_key_auth: false, ssh_private_key: 'foo')
-
- expect(fetch_remote(ssh_auth)).to be_truthy
- end
-
- it 'passes the known_hosts data if specified' do
- expect_call(false, force: false, tags: true, prune: true, known_hosts: 'foo')
-
- ssh_auth = build_ssh_auth(ssh_known_hosts: 'foo')
-
- expect(fetch_remote(ssh_auth)).to be_truthy
- end
-
- it 'does not pass empty known_hosts data' do
- expect_call(false, force: false, tags: true, prune: true)
-
- ssh_auth = build_ssh_auth(ssh_known_hosts: '')
-
- expect(fetch_remote(ssh_auth)).to be_truthy
- end
-
- it 'does not pass known_hosts data unless SSH is to be used' do
- expect_call(false, force: false, tags: true, prune: true)
-
- ssh_auth = build_ssh_auth(ssh_import?: false, ssh_known_hosts: 'foo')
-
- expect(fetch_remote(ssh_auth)).to be_truthy
- end
- end
-
- context 'gitaly call' do
- let(:remote_name) { 'remote-name' }
- let(:ssh_auth) { double(:ssh_auth) }
-
- subject do
- gitlab_shell.fetch_remote(repository.raw_repository, remote_name,
- forced: true, no_tags: true, ssh_auth: ssh_auth)
- end
-
- it 'passes the correct params to the gitaly service' do
- expect(repository.gitaly_repository_client).to receive(:fetch_remote)
- .with(remote_name, ssh_auth: ssh_auth, forced: true, no_tags: true, prune: true, timeout: timeout)
-
- subject
- end
- end
- end
-
describe '#import_repository' do
let(:import_url) { 'https://gitlab.com/gitlab-org/gitlab-ce.git' }
diff --git a/spec/lib/gitlab/sidekiq_throttler_spec.rb b/spec/lib/gitlab/sidekiq_throttler_spec.rb
deleted file mode 100644
index 2dbb7bb7c34..00000000000
--- a/spec/lib/gitlab/sidekiq_throttler_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::SidekiqThrottler do
- describe '#execute!' do
- context 'when job throttling is enabled' do
- before do
- Sidekiq.options[:concurrency] = 35
-
- stub_application_setting(
- sidekiq_throttling_enabled: true,
- sidekiq_throttling_factor: 0.1,
- sidekiq_throttling_queues: %w[build project_cache]
- )
- end
-
- it 'requires sidekiq-limit_fetch' do
- expect(described_class).to receive(:require).with('sidekiq-limit_fetch').and_call_original
-
- described_class.execute!
- end
-
- it 'sets limits on the selected queues' do
- described_class.execute!
-
- expect(Sidekiq::Queue['build'].limit).to eq 4
- expect(Sidekiq::Queue['project_cache'].limit).to eq 4
- end
-
- it 'does not set limits on other queues' do
- described_class.execute!
-
- expect(Sidekiq::Queue['merge'].limit).to be_nil
- end
- end
-
- context 'when job throttling is disabled' do
- it 'does not require sidekiq-limit_fetch' do
- expect(described_class).not_to receive(:require).with('sidekiq-limit_fetch')
-
- described_class.execute!
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/slash_commands/command_spec.rb b/spec/lib/gitlab/slash_commands/command_spec.rb
index 194cae8c645..eceacac58af 100644
--- a/spec/lib/gitlab/slash_commands/command_spec.rb
+++ b/spec/lib/gitlab/slash_commands/command_spec.rb
@@ -44,7 +44,7 @@ describe Gitlab::SlashCommands::Command do
let!(:build) { create(:ci_build, pipeline: pipeline) }
let!(:pipeline) { create(:ci_pipeline, project: project) }
let!(:staging) { create(:environment, name: 'staging', project: project) }
- let!(:deployment) { create(:deployment, environment: staging, deployable: build) }
+ let!(:deployment) { create(:deployment, :success, environment: staging, deployable: build) }
let!(:manual) do
create(:ci_build, :manual, pipeline: pipeline,
diff --git a/spec/lib/gitlab/slash_commands/deploy_spec.rb b/spec/lib/gitlab/slash_commands/deploy_spec.rb
index 0d57334aa4c..25f3e8a0409 100644
--- a/spec/lib/gitlab/slash_commands/deploy_spec.rb
+++ b/spec/lib/gitlab/slash_commands/deploy_spec.rb
@@ -31,7 +31,7 @@ describe Gitlab::SlashCommands::Deploy do
let!(:staging) { create(:environment, name: 'staging', project: project) }
let!(:pipeline) { create(:ci_pipeline, project: project) }
let!(:build) { create(:ci_build, pipeline: pipeline) }
- let!(:deployment) { create(:deployment, environment: staging, deployable: build) }
+ let!(:deployment) { create(:deployment, :success, environment: staging, deployable: build) }
context 'without actions' do
it 'does not execute an action' do
diff --git a/spec/lib/gitlab/storage_check/cli_spec.rb b/spec/lib/gitlab/storage_check/cli_spec.rb
deleted file mode 100644
index 6db0925899c..00000000000
--- a/spec/lib/gitlab/storage_check/cli_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::StorageCheck::CLI do
- let(:options) { Gitlab::StorageCheck::Options.new('unix://tmp/socket.sock', nil, 1, false) }
- subject(:runner) { described_class.new(options) }
-
- describe '#update_settings' do
- it 'updates the interval when changed in a valid response and logs the change' do
- fake_response = double
- expect(fake_response).to receive(:valid?).and_return(true)
- expect(fake_response).to receive(:check_interval).and_return(42)
- expect(runner.logger).to receive(:info)
-
- runner.update_settings(fake_response)
-
- expect(options.interval).to eq(42)
- end
- end
-end
diff --git a/spec/lib/gitlab/storage_check/gitlab_caller_spec.rb b/spec/lib/gitlab/storage_check/gitlab_caller_spec.rb
deleted file mode 100644
index d869022fd31..00000000000
--- a/spec/lib/gitlab/storage_check/gitlab_caller_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::StorageCheck::GitlabCaller do
- let(:options) { Gitlab::StorageCheck::Options.new('unix://tmp/socket.sock', nil, nil, false) }
- subject(:gitlab_caller) { described_class.new(options) }
-
- describe '#call!' do
- context 'when a socket is given' do
- it 'calls a socket' do
- fake_connection = double
- expect(fake_connection).to receive(:post)
- expect(Excon).to receive(:new).with('unix://tmp/socket.sock', socket: "tmp/socket.sock") { fake_connection }
-
- gitlab_caller.call!
- end
- end
-
- context 'when a host is given' do
- let(:options) { Gitlab::StorageCheck::Options.new('http://localhost:8080', nil, nil, false) }
-
- it 'it calls a http response' do
- fake_connection = double
- expect(Excon).to receive(:new).with('http://localhost:8080', socket: nil) { fake_connection }
- expect(fake_connection).to receive(:post)
-
- gitlab_caller.call!
- end
- end
- end
-
- describe '#headers' do
- it 'Adds the JSON header' do
- headers = gitlab_caller.headers
-
- expect(headers['Content-Type']).to eq('application/json')
- end
-
- context 'when a token was provided' do
- let(:options) { Gitlab::StorageCheck::Options.new('unix://tmp/socket.sock', 'atoken', nil, false) }
-
- it 'adds it to the headers' do
- expect(gitlab_caller.headers['TOKEN']).to eq('atoken')
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/storage_check/option_parser_spec.rb b/spec/lib/gitlab/storage_check/option_parser_spec.rb
deleted file mode 100644
index cad4dfbefcf..00000000000
--- a/spec/lib/gitlab/storage_check/option_parser_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::StorageCheck::OptionParser do
- describe '.parse!' do
- it 'assigns all options' do
- args = %w(--target unix://tmp/hello/world.sock --token thetoken --interval 42)
-
- options = described_class.parse!(args)
-
- expect(options.token).to eq('thetoken')
- expect(options.interval).to eq(42)
- expect(options.target).to eq('unix://tmp/hello/world.sock')
- end
-
- it 'requires the interval to be a number' do
- args = %w(--target unix://tmp/hello/world.sock --interval fortytwo)
-
- expect { described_class.parse!(args) }.to raise_error(OptionParser::InvalidArgument)
- end
-
- it 'raises an error if the scheme is not included' do
- args = %w(--target tmp/hello/world.sock)
-
- expect { described_class.parse!(args) }.to raise_error(OptionParser::InvalidArgument)
- end
-
- it 'raises an error if both socket and host are missing' do
- expect { described_class.parse!([]) }.to raise_error(OptionParser::InvalidArgument)
- end
- end
-end
diff --git a/spec/lib/gitlab/storage_check/response_spec.rb b/spec/lib/gitlab/storage_check/response_spec.rb
deleted file mode 100644
index 0ff2963e443..00000000000
--- a/spec/lib/gitlab/storage_check/response_spec.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-require 'spec_helper'
-
-describe Gitlab::StorageCheck::Response do
- let(:fake_json) do
- {
- check_interval: 42,
- results: [
- { storage: 'working', success: true },
- { storage: 'skipped', success: nil },
- { storage: 'failing', success: false }
- ]
- }.to_json
- end
-
- let(:fake_http_response) do
- fake_response = instance_double("Excon::Response - Status check")
- allow(fake_response).to receive(:status).and_return(200)
- allow(fake_response).to receive(:body).and_return(fake_json)
- allow(fake_response).to receive(:headers).and_return('Content-Type' => 'application/json')
-
- fake_response
- end
- let(:response) { described_class.new(fake_http_response) }
-
- describe '#valid?' do
- it 'is valid for a success response with parseable JSON' do
- expect(response).to be_valid
- end
- end
-
- describe '#check_interval' do
- it 'returns the result from the JSON' do
- expect(response.check_interval).to eq(42)
- end
- end
-
- describe '#responsive_shards' do
- it 'contains the names of working shards' do
- expect(response.responsive_shards).to contain_exactly('working')
- end
- end
-
- describe '#skipped_shards' do
- it 'contains the names of skipped shards' do
- expect(response.skipped_shards).to contain_exactly('skipped')
- end
- end
-
- describe '#failing_shards' do
- it 'contains the name of failing shards' do
- expect(response.failing_shards).to contain_exactly('failing')
- end
- end
-end
diff --git a/spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb b/spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb
index e2fa76522bc..fe46c67a920 100644
--- a/spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb
+++ b/spec/lib/gitlab/template/gitlab_ci_yml_template_spec.rb
@@ -40,7 +40,7 @@ describe Gitlab::Template::GitlabCiYmlTemplate do
describe '#content' do
it 'loads the full file' do
- gitignore = subject.new(Rails.root.join('vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml'))
+ gitignore = subject.new(Rails.root.join('lib/gitlab/ci/templates/Ruby.gitlab-ci.yml'))
expect(gitignore.name).to eq 'Ruby'
expect(gitignore.content).to start_with('#')
diff --git a/spec/lib/gitlab/url_blocker_spec.rb b/spec/lib/gitlab/url_blocker_spec.rb
index 624e2add860..39e0a17a307 100644
--- a/spec/lib/gitlab/url_blocker_spec.rb
+++ b/spec/lib/gitlab/url_blocker_spec.rb
@@ -10,8 +10,8 @@ describe Gitlab::UrlBlocker do
expect(described_class.blocked_url?(import_url)).to be false
end
- it 'allows imports from configured SSH host and port' do
- import_url = "http://#{Gitlab.config.gitlab_shell.ssh_host}:#{Gitlab.config.gitlab_shell.ssh_port}/t.git"
+ it 'allows mirroring from configured SSH host and port' do
+ import_url = "ssh://#{Gitlab.config.gitlab_shell.ssh_host}:#{Gitlab.config.gitlab_shell.ssh_port}/t.git"
expect(described_class.blocked_url?(import_url)).to be false
end
@@ -29,14 +29,46 @@ describe Gitlab::UrlBlocker do
expect(described_class.blocked_url?('https://gitlab.com/foo/foo.git', protocols: ['http'])).to be true
end
+ it 'returns true for bad protocol on configured web/SSH host and ports' do
+ web_url = "javascript://#{Gitlab.config.gitlab.host}:#{Gitlab.config.gitlab.port}/t.git%0aalert(1)"
+ expect(described_class.blocked_url?(web_url)).to be true
+
+ ssh_url = "javascript://#{Gitlab.config.gitlab_shell.ssh_host}:#{Gitlab.config.gitlab_shell.ssh_port}/t.git%0aalert(1)"
+ expect(described_class.blocked_url?(ssh_url)).to be true
+ end
+
+ it 'returns true for localhost IPs' do
+ expect(described_class.blocked_url?('https://[0:0:0:0:0:0:0:0]/foo/foo.git')).to be true
+ expect(described_class.blocked_url?('https://0.0.0.0/foo/foo.git')).to be true
+ expect(described_class.blocked_url?('https://[::]/foo/foo.git')).to be true
+ end
+
+ it 'returns true for loopback IP' do
+ expect(described_class.blocked_url?('https://127.0.0.2/foo/foo.git')).to be true
+ expect(described_class.blocked_url?('https://127.0.0.1/foo/foo.git')).to be true
+ expect(described_class.blocked_url?('https://[::1]/foo/foo.git')).to be true
+ end
+
it 'returns true for alternative version of 127.0.0.1 (0177.1)' do
expect(described_class.blocked_url?('https://0177.1:65535/foo/foo.git')).to be true
end
+ it 'returns true for alternative version of 127.0.0.1 (017700000001)' do
+ expect(described_class.blocked_url?('https://017700000001:65535/foo/foo.git')).to be true
+ end
+
it 'returns true for alternative version of 127.0.0.1 (0x7f.1)' do
expect(described_class.blocked_url?('https://0x7f.1:65535/foo/foo.git')).to be true
end
+ it 'returns true for alternative version of 127.0.0.1 (0x7f.0.0.1)' do
+ expect(described_class.blocked_url?('https://0x7f.0.0.1:65535/foo/foo.git')).to be true
+ end
+
+ it 'returns true for alternative version of 127.0.0.1 (0x7f000001)' do
+ expect(described_class.blocked_url?('https://0x7f000001:65535/foo/foo.git')).to be true
+ end
+
it 'returns true for alternative version of 127.0.0.1 (2130706433)' do
expect(described_class.blocked_url?('https://2130706433:65535/foo/foo.git')).to be true
end
@@ -45,6 +77,27 @@ describe Gitlab::UrlBlocker do
expect(described_class.blocked_url?('https://127.000.000.001:65535/foo/foo.git')).to be true
end
+ it 'returns true for alternative version of 127.0.0.1 (127.0.1)' do
+ expect(described_class.blocked_url?('https://127.0.1:65535/foo/foo.git')).to be true
+ end
+
+ context 'with ipv6 mapped address' do
+ it 'returns true for localhost IPs' do
+ expect(described_class.blocked_url?('https://[0:0:0:0:0:ffff:0.0.0.0]/foo/foo.git')).to be true
+ expect(described_class.blocked_url?('https://[::ffff:0.0.0.0]/foo/foo.git')).to be true
+ expect(described_class.blocked_url?('https://[::ffff:0:0]/foo/foo.git')).to be true
+ end
+
+ it 'returns true for loopback IPs' do
+ expect(described_class.blocked_url?('https://[0:0:0:0:0:ffff:127.0.0.1]/foo/foo.git')).to be true
+ expect(described_class.blocked_url?('https://[::ffff:127.0.0.1]/foo/foo.git')).to be true
+ expect(described_class.blocked_url?('https://[::ffff:7f00:1]/foo/foo.git')).to be true
+ expect(described_class.blocked_url?('https://[0:0:0:0:0:ffff:127.0.0.2]/foo/foo.git')).to be true
+ expect(described_class.blocked_url?('https://[::ffff:127.0.0.2]/foo/foo.git')).to be true
+ expect(described_class.blocked_url?('https://[::ffff:7f00:2]/foo/foo.git')).to be true
+ end
+ end
+
it 'returns true for a non-alphanumeric hostname' do
stub_resolv
@@ -68,7 +121,22 @@ describe Gitlab::UrlBlocker do
end
context 'when allow_local_network is' do
- let(:local_ips) { ['192.168.1.2', '10.0.0.2', '172.16.0.2'] }
+ let(:local_ips) do
+ [
+ '192.168.1.2',
+ '[0:0:0:0:0:ffff:192.168.1.2]',
+ '[::ffff:c0a8:102]',
+ '10.0.0.2',
+ '[0:0:0:0:0:ffff:10.0.0.2]',
+ '[::ffff:a00:2]',
+ '172.16.0.2',
+ '[0:0:0:0:0:ffff:172.16.0.2]',
+ '[::ffff:ac10:20]',
+ '[feef::1]',
+ '[fee2::]',
+ '[fc00:bf8b:e62c:abcd:abcd:aaaa:aaaa:aaaa]'
+ ]
+ end
let(:fake_domain) { 'www.fakedomain.fake' }
context 'true (default)' do
@@ -84,15 +152,29 @@ describe Gitlab::UrlBlocker do
end
end
+ it 'allows localhost endpoints' do
+ expect(described_class).not_to be_blocked_url('http://0.0.0.0', allow_localhost: true)
+ expect(described_class).not_to be_blocked_url('http://localhost', allow_localhost: true)
+ expect(described_class).not_to be_blocked_url('http://127.0.0.1', allow_localhost: true)
+ end
+
+ it 'allows loopback endpoints' do
+ expect(described_class).not_to be_blocked_url('http://127.0.0.2', allow_localhost: true)
+ end
+
it 'allows IPv4 link-local endpoints' do
expect(described_class).not_to be_blocked_url('http://169.254.169.254')
expect(described_class).not_to be_blocked_url('http://169.254.168.100')
end
- # This is blocked due to the hostname check: https://gitlab.com/gitlab-org/gitlab-ce/issues/50227
- it 'blocks IPv6 link-local endpoints' do
- expect(described_class).to be_blocked_url('http://[::ffff:169.254.169.254]')
- expect(described_class).to be_blocked_url('http://[::ffff:169.254.168.100]')
+ it 'allows IPv6 link-local endpoints' do
+ expect(described_class).not_to be_blocked_url('http://[0:0:0:0:0:ffff:169.254.169.254]')
+ expect(described_class).not_to be_blocked_url('http://[::ffff:169.254.169.254]')
+ expect(described_class).not_to be_blocked_url('http://[::ffff:a9fe:a9fe]')
+ expect(described_class).not_to be_blocked_url('http://[0:0:0:0:0:ffff:169.254.168.100]')
+ expect(described_class).not_to be_blocked_url('http://[::ffff:169.254.168.100]')
+ expect(described_class).not_to be_blocked_url('http://[::ffff:a9fe:a864]')
+ expect(described_class).not_to be_blocked_url('http://[fe80::c800:eff:fe74:8]')
end
end
@@ -115,14 +197,20 @@ describe Gitlab::UrlBlocker do
end
it 'blocks IPv6 link-local endpoints' do
+ expect(described_class).to be_blocked_url('http://[0:0:0:0:0:ffff:169.254.169.254]', allow_local_network: false)
expect(described_class).to be_blocked_url('http://[::ffff:169.254.169.254]', allow_local_network: false)
+ expect(described_class).to be_blocked_url('http://[::ffff:a9fe:a9fe]', allow_local_network: false)
+ expect(described_class).to be_blocked_url('http://[0:0:0:0:0:ffff:169.254.168.100]', allow_local_network: false)
expect(described_class).to be_blocked_url('http://[::ffff:169.254.168.100]', allow_local_network: false)
- expect(described_class).to be_blocked_url('http://[FE80::C800:EFF:FE74:8]', allow_local_network: false)
+ expect(described_class).to be_blocked_url('http://[::ffff:a9fe:a864]', allow_local_network: false)
+ expect(described_class).to be_blocked_url('http://[fe80::c800:eff:fe74:8]', allow_local_network: false)
end
end
def stub_domain_resolv(domain, ip)
- allow(Addrinfo).to receive(:getaddrinfo).with(domain, any_args).and_return([double(ip_address: ip, ipv4_private?: true, ipv6_link_local?: false)])
+ address = double(ip_address: ip, ipv4_private?: true, ipv6_link_local?: false, ipv4_loopback?: false, ipv6_loopback?: false)
+ allow(Addrinfo).to receive(:getaddrinfo).with(domain, any_args).and_return([address])
+ allow(address).to receive(:ipv6_v4mapped?).and_return(false)
end
def unstub_domain_resolv
@@ -163,6 +251,36 @@ describe Gitlab::UrlBlocker do
end
end
+ describe '#validate_hostname!' do
+ let(:ip_addresses) do
+ [
+ '2001:db8:1f70::999:de8:7648:6e8',
+ 'FE80::C800:EFF:FE74:8',
+ '::ffff:127.0.0.1',
+ '::ffff:169.254.168.100',
+ '::ffff:7f00:1',
+ '0:0:0:0:0:ffff:0.0.0.0',
+ 'localhost',
+ '127.0.0.1',
+ '127.000.000.001',
+ '0x7f000001',
+ '0x7f.0.0.1',
+ '0x7f.0.0.1',
+ '017700000001',
+ '0177.1',
+ '2130706433',
+ '::',
+ '::1'
+ ]
+ end
+
+ it 'does not raise error for valid Ip addresses' do
+ ip_addresses.each do |ip|
+ expect { described_class.send(:validate_hostname!, ip) }.not_to raise_error
+ end
+ end
+ end
+
# Resolv does not support resolving UTF-8 domain names
# See https://bugs.ruby-lang.org/issues/4270
def stub_resolv
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 1ec1fe10744..5390f237073 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -8,6 +8,7 @@ describe Gitlab::UsageData do
before do
create(:jira_service, project: projects[0])
create(:jira_service, project: projects[1])
+ create(:jira_cloud_service, project: projects[2])
create(:prometheus_service, project: projects[1])
create(:service, project: projects[0], type: 'SlackSlashCommandsService', active: true)
create(:service, project: projects[1], type: 'SlackService', active: true)
@@ -18,8 +19,10 @@ describe Gitlab::UsageData do
create(:cluster, :provided_by_user, :disabled)
create(:clusters_applications_helm, :installed, cluster: gcp_cluster)
create(:clusters_applications_ingress, :installed, cluster: gcp_cluster)
+ create(:clusters_applications_cert_managers, :installed, cluster: gcp_cluster)
create(:clusters_applications_prometheus, :installed, cluster: gcp_cluster)
create(:clusters_applications_runner, :installed, cluster: gcp_cluster)
+ create(:clusters_applications_knative, :installed, cluster: gcp_cluster)
end
subject { described_class.data }
@@ -46,6 +49,7 @@ describe Gitlab::UsageData do
git
database
avg_cycle_analytics
+ web_ide_commits
))
end
@@ -78,8 +82,10 @@ describe Gitlab::UsageData do
clusters_platforms_user
clusters_applications_helm
clusters_applications_ingress
+ clusters_applications_cert_managers
clusters_applications_prometheus
clusters_applications_runner
+ clusters_applications_knative
in_review_folder
groups
issues
@@ -94,6 +100,8 @@ describe Gitlab::UsageData do
projects
projects_imported_from_github
projects_jira_active
+ projects_jira_server_active
+ projects_jira_cloud_active
projects_slack_notifications_active
projects_slack_slash_active
projects_prometheus_active
@@ -113,7 +121,9 @@ describe Gitlab::UsageData do
expect(count_data[:projects]).to eq(3)
expect(count_data[:projects_prometheus_active]).to eq(1)
- expect(count_data[:projects_jira_active]).to eq(2)
+ expect(count_data[:projects_jira_active]).to eq(3)
+ expect(count_data[:projects_jira_server_active]).to eq(2)
+ expect(count_data[:projects_jira_cloud_active]).to eq(1)
expect(count_data[:projects_slack_notifications_active]).to eq(2)
expect(count_data[:projects_slack_slash_active]).to eq(1)
@@ -123,8 +133,17 @@ describe Gitlab::UsageData do
expect(count_data[:clusters_platforms_user]).to eq(1)
expect(count_data[:clusters_applications_helm]).to eq(1)
expect(count_data[:clusters_applications_ingress]).to eq(1)
+ expect(count_data[:clusters_applications_cert_managers]).to eq(1)
expect(count_data[:clusters_applications_prometheus]).to eq(1)
expect(count_data[:clusters_applications_runner]).to eq(1)
+ expect(count_data[:clusters_applications_knative]).to eq(1)
+ end
+
+ it 'works when queries time out' do
+ allow_any_instance_of(ActiveRecord::Relation)
+ .to receive(:count).and_raise(ActiveRecord::StatementInvalid.new(''))
+
+ expect { subject }.not_to raise_error
end
end
diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb
index 4ba99009855..ad2c9d7f2af 100644
--- a/spec/lib/gitlab/utils_spec.rb
+++ b/spec/lib/gitlab/utils_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Gitlab::Utils do
delegate :to_boolean, :boolean_to_yes_no, :slugify, :random_string, :which, :ensure_array_from_string,
- :bytes_to_megabytes, to: :described_class
+ :bytes_to_megabytes, :append_path, to: :described_class
describe '.slugify' do
{
@@ -106,4 +106,25 @@ describe Gitlab::Utils do
expect(bytes_to_megabytes(bytes)).to eq(1)
end
end
+
+ describe '.append_path' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:host, :path, :result) do
+ 'http://test/' | '/foo/bar' | 'http://test/foo/bar'
+ 'http://test/' | '//foo/bar' | 'http://test/foo/bar'
+ 'http://test//' | '/foo/bar' | 'http://test/foo/bar'
+ 'http://test' | 'foo/bar' | 'http://test/foo/bar'
+ 'http://test//' | '' | 'http://test/'
+ 'http://test//' | nil | 'http://test/'
+ '' | '/foo/bar' | '/foo/bar'
+ nil | '/foo/bar' | '/foo/bar'
+ end
+
+ with_them do
+ it 'makes sure there is only one slash as path separator' do
+ expect(append_path(host, path)).to eq(result)
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/version_info_spec.rb b/spec/lib/gitlab/version_info_spec.rb
index c8a1e433d59..30035c79e58 100644
--- a/spec/lib/gitlab/version_info_spec.rb
+++ b/spec/lib/gitlab/version_info_spec.rb
@@ -57,6 +57,9 @@ describe 'Gitlab::VersionInfo' do
context 'parse' do
it { expect(Gitlab::VersionInfo.parse("1.0.0")).to eq(@v1_0_0) }
it { expect(Gitlab::VersionInfo.parse("1.0.0.1")).to eq(@v1_0_0) }
+ it { expect(Gitlab::VersionInfo.parse("1.0.0-ee")).to eq(@v1_0_0) }
+ it { expect(Gitlab::VersionInfo.parse("1.0.0-rc1")).to eq(@v1_0_0) }
+ it { expect(Gitlab::VersionInfo.parse("1.0.0-rc1-ee")).to eq(@v1_0_0) }
it { expect(Gitlab::VersionInfo.parse("git 1.0.0b1")).to eq(@v1_0_0) }
it { expect(Gitlab::VersionInfo.parse("git 1.0b1")).not_to be_valid }
end
diff --git a/spec/lib/gitlab/view/presenter/base_spec.rb b/spec/lib/gitlab/view/presenter/base_spec.rb
index 4eca53032a2..02c2fd47197 100644
--- a/spec/lib/gitlab/view/presenter/base_spec.rb
+++ b/spec/lib/gitlab/view/presenter/base_spec.rb
@@ -40,7 +40,7 @@ describe Gitlab::View::Presenter::Base do
end
end
- context 'subject is overriden' do
+ context 'subject is overridden' do
it 'returns true' do
presenter = presenter_class.new(build_stubbed(:project, :public))
diff --git a/spec/lib/gitlab/web_ide_commits_counter_spec.rb b/spec/lib/gitlab/web_ide_commits_counter_spec.rb
new file mode 100644
index 00000000000..c51889a1c63
--- /dev/null
+++ b/spec/lib/gitlab/web_ide_commits_counter_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::WebIdeCommitsCounter, :clean_gitlab_redis_shared_state do
+ describe '.increment' do
+ it 'increments the web ide commits counter by 1' do
+ expect do
+ described_class.increment
+ end.to change { described_class.total_count }.from(0).to(1)
+ end
+ end
+
+ describe '.total_count' do
+ it 'returns the total amount of web ide commits' do
+ expect(described_class.total_count).to eq(0)
+ end
+ end
+end
diff --git a/spec/lib/json_web_token/hmac_token_spec.rb b/spec/lib/json_web_token/hmac_token_spec.rb
new file mode 100644
index 00000000000..f2cbc381967
--- /dev/null
+++ b/spec/lib/json_web_token/hmac_token_spec.rb
@@ -0,0 +1,133 @@
+# frozen_string_literal: true
+
+require 'json'
+require 'timecop'
+
+describe JSONWebToken::HMACToken do
+ let(:secret) { 'shh secret squirrel' }
+
+ shared_examples 'a valid, non-expired token' do
+ it 'is an Array with two elements' do
+ expect(decoded_token).to be_a(Array)
+ expect(decoded_token.count).to eq(2)
+ end
+
+ it 'contains the following keys in the first Array element Hash - jti, iat, nbf, exp' do
+ expect(decoded_token[0].keys).to include('jti', 'iat', 'nbf', 'exp')
+ end
+
+ it 'contains the following keys in the second Array element Hash - typ and alg' do
+ expect(decoded_token[1]['typ']).to eql('JWT')
+ expect(decoded_token[1]['alg']).to eql('HS256')
+ end
+ end
+
+ describe '.decode' do
+ let(:leeway) { described_class::IAT_LEEWAY }
+ let(:decoded_token) { described_class.decode(encoded_token, secret, leeway: leeway) }
+
+ context 'with an invalid token' do
+ context 'that is junk' do
+ let(:encoded_token) { 'junk' }
+
+ it "raises exception saying 'Not enough or too many segments'" do
+ expect { decoded_token }.to raise_error(JWT::DecodeError, 'Not enough or too many segments')
+ end
+ end
+
+ context 'that has been fiddled with' do
+ let(:encoded_token) do
+ described_class.new(secret).encoded.tap { |token| token[0] = 'E' }
+ end
+
+ it "raises exception saying 'Invalid segment encoding'" do
+ expect { decoded_token }.to raise_error(JWT::DecodeError, 'Invalid segment encoding')
+ end
+ end
+
+ context 'that was generated using a different secret' do
+ let(:encoded_token) { described_class.new('some other secret').encoded }
+
+ it "raises exception saying 'Signature verification raised" do
+ expect { decoded_token }.to raise_error(JWT::VerificationError, 'Signature verification raised')
+ end
+ end
+
+ context 'that is expired' do
+ # Needs the ! so Timecop.freeze() is effective
+ let!(:encoded_token) { described_class.new(secret).encoded }
+
+ it "raises exception saying 'Signature has expired'" do
+ # Needs to be 120 seconds, because the default expiry is 60 seconds
+ # with an additional 60 second leeway.
+ Timecop.freeze(Time.now + 120) do
+ expect { decoded_token }.to raise_error(JWT::ExpiredSignature, 'Signature has expired')
+ end
+ end
+ end
+ end
+
+ context 'with a valid token' do
+ let(:encoded_token) do
+ hmac_token = described_class.new(secret)
+ hmac_token.expire_time = Time.now + expire_time
+ hmac_token.encoded
+ end
+
+ context 'that has expired' do
+ let(:expire_time) { 0 }
+
+ context 'with the default leeway' do
+ Timecop.freeze(Time.now + 1) do
+ it_behaves_like 'a valid, non-expired token'
+ end
+ end
+
+ context 'with a leeway of 0 seconds' do
+ let(:leeway) { 0 }
+
+ it "raises exception saying 'Signature has expired'" do
+ Timecop.freeze(Time.now + 1) do
+ expect { decoded_token }.to raise_error(JWT::ExpiredSignature, 'Signature has expired')
+ end
+ end
+ end
+ end
+
+ context 'that has not expired' do
+ let(:expire_time) { described_class::DEFAULT_EXPIRE_TIME }
+
+ it_behaves_like 'a valid, non-expired token'
+ end
+ end
+ end
+
+ describe '#encoded' do
+ let(:decoded_token) { described_class.decode(encoded_token, secret) }
+
+ context 'without data' do
+ let(:encoded_token) { described_class.new(secret).encoded }
+
+ it_behaves_like 'a valid, non-expired token'
+ end
+
+ context 'with data' do
+ let(:data) { { secret_key: 'secret value' }.to_json }
+ let(:encoded_token) do
+ ec = described_class.new(secret)
+ ec[:data] = data
+ ec.encoded
+ end
+
+ it_behaves_like 'a valid, non-expired token'
+
+ it "contains the 'data' key in the first Array element Hash" do
+ expect(decoded_token[0]).to have_key('data')
+ end
+
+ it 'can re-read back the data' do
+ expect(decoded_token[0]['data']).to eql(data)
+ end
+ end
+ end
+end
diff --git a/spec/lib/microsoft_teams/notifier_spec.rb b/spec/lib/microsoft_teams/notifier_spec.rb
index c9756544bd6..2aaa7c24ad8 100644
--- a/spec/lib/microsoft_teams/notifier_spec.rb
+++ b/spec/lib/microsoft_teams/notifier_spec.rb
@@ -48,7 +48,7 @@ describe MicrosoftTeams::Notifier do
stub_request(:post, webhook_url).with(body: JSON(body), headers: { 'Content-Type' => 'application/json' }).to_return(status: 200, body: "", headers: {})
end
- it 'expects to receive successfull answer' do
+ it 'expects to receive successful answer' do
expect(subject.ping(options)).to be true
end
end
diff --git a/spec/lib/quality/helm_client_spec.rb b/spec/lib/quality/helm_client_spec.rb
new file mode 100644
index 00000000000..7abb9688d5a
--- /dev/null
+++ b/spec/lib/quality/helm_client_spec.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Quality::HelmClient do
+ let(:namespace) { 'review-apps-ee' }
+ let(:release_name) { 'my-release' }
+ let(:raw_helm_list_page1) do
+ <<~OUTPUT
+ {"Next":"review-6709-group-t40qbv",
+ "Releases":[
+ {"Name":"review-qa-60-reor-1mugd1", "Revision":1,"Updated":"Thu Oct 4 17:52:31 2018","Status":"FAILED", "Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
+ {"Name":"review-7846-fix-s-261vd6","Revision":1,"Updated":"Thu Oct 4 17:33:29 2018","Status":"FAILED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
+ {"Name":"review-7867-snowp-lzo3iy","Revision":1,"Updated":"Thu Oct 4 17:22:14 2018","Status":"DEPLOYED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
+ {"Name":"review-rename-geo-o4a780","Revision":1,"Updated":"Thu Oct 4 17:14:57 2018","Status":"DEPLOYED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
+ {"Name":"review-5781-opera-0k93fx","Revision":1,"Updated":"Thu Oct 4 17:06:15 2018","Status":"FAILED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
+ {"Name":"review-6709-group-2pzeec","Revision":1,"Updated":"Thu Oct 4 16:36:59 2018","Status":"FAILED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
+ {"Name":"review-ce-to-ee-2-l554mn","Revision":1,"Updated":"Thu Oct 4 16:27:02 2018","Status":"FAILED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
+ {"Name":"review-epics-e2e-m690eb","Revision":1,"Updated":"Thu Oct 4 16:08:26 2018","Status":"DEPLOYED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
+ {"Name":"review-7126-admin-06fae2","Revision":1,"Updated":"Thu Oct 4 15:56:35 2018","Status":"FAILED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"},
+ {"Name":"review-6983-promo-xyou11","Revision":1,"Updated":"Thu Oct 4 15:15:34 2018","Status":"FAILED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"}
+ ]}
+ OUTPUT
+ end
+ let(:raw_helm_list_page2) do
+ <<~OUTPUT
+ {"Releases":[
+ {"Name":"review-6709-group-t40qbv","Revision":1,"Updated":"Thu Oct 4 17:52:31 2018","Status":"FAILED","Chart":"gitlab-1.1.3","AppVersion":"master","Namespace":"#{namespace}"}
+ ]}
+ OUTPUT
+ end
+
+ subject { described_class.new(namespace: namespace) }
+
+ describe '#releases' do
+ it 'raises an error if the Helm command fails' do
+ expect(Gitlab::Popen).to receive(:popen_with_detail)
+ .with([%(helm list --namespace "#{namespace}" --tiller-namespace "#{namespace}" --output json)])
+ .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false)))
+
+ expect { subject.releases.to_a }.to raise_error(described_class::CommandFailedError)
+ end
+
+ it 'calls helm list with default arguments' do
+ expect(Gitlab::Popen).to receive(:popen_with_detail)
+ .with([%(helm list --namespace "#{namespace}" --tiller-namespace "#{namespace}" --output json)])
+ .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
+
+ subject.releases.to_a
+ end
+
+ it 'calls helm list with extra arguments' do
+ expect(Gitlab::Popen).to receive(:popen_with_detail)
+ .with([%(helm list --namespace "#{namespace}" --tiller-namespace "#{namespace}" --output json --deployed)])
+ .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
+
+ subject.releases(args: ['--deployed']).to_a
+ end
+
+ it 'returns a list of Release objects' do
+ expect(Gitlab::Popen).to receive(:popen_with_detail)
+ .with([%(helm list --namespace "#{namespace}" --tiller-namespace "#{namespace}" --output json --deployed)])
+ .and_return(Gitlab::Popen::Result.new([], raw_helm_list_page2, '', double(success?: true)))
+
+ releases = subject.releases(args: ['--deployed']).to_a
+
+ expect(releases.size).to eq(1)
+ expect(releases[0]).to have_attributes(
+ name: 'review-6709-group-t40qbv',
+ revision: 1,
+ last_update: Time.parse('Thu Oct 4 17:52:31 2018'),
+ status: 'FAILED',
+ chart: 'gitlab-1.1.3',
+ app_version: 'master',
+ namespace: namespace
+ )
+ end
+
+ it 'automatically paginates releases' do
+ expect(Gitlab::Popen).to receive(:popen_with_detail).ordered
+ .with([%(helm list --namespace "#{namespace}" --tiller-namespace "#{namespace}" --output json)])
+ .and_return(Gitlab::Popen::Result.new([], raw_helm_list_page1, '', double(success?: true)))
+ expect(Gitlab::Popen).to receive(:popen_with_detail).ordered
+ .with([%(helm list --namespace "#{namespace}" --tiller-namespace "#{namespace}" --output json --offset review-6709-group-t40qbv)])
+ .and_return(Gitlab::Popen::Result.new([], raw_helm_list_page2, '', double(success?: true)))
+
+ releases = subject.releases.to_a
+
+ expect(releases.size).to eq(11)
+ expect(releases.last.name).to eq('review-6709-group-t40qbv')
+ end
+ end
+
+ describe '#delete' do
+ it 'raises an error if the Helm command fails' do
+ expect(Gitlab::Popen).to receive(:popen_with_detail)
+ .with([%(helm delete --tiller-namespace "#{namespace}" --purge #{release_name})])
+ .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false)))
+
+ expect { subject.delete(release_name: release_name) }.to raise_error(described_class::CommandFailedError)
+ end
+
+ it 'calls helm delete with default arguments' do
+ expect(Gitlab::Popen).to receive(:popen_with_detail)
+ .with([%(helm delete --tiller-namespace "#{namespace}" --purge #{release_name})])
+ .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
+
+ expect(subject.delete(release_name: release_name)).to eq('')
+ end
+ end
+end
diff --git a/spec/lib/quality/kubernetes_client_spec.rb b/spec/lib/quality/kubernetes_client_spec.rb
new file mode 100644
index 00000000000..f35d9464d48
--- /dev/null
+++ b/spec/lib/quality/kubernetes_client_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+RSpec.describe Quality::KubernetesClient do
+ let(:namespace) { 'review-apps-ee' }
+ let(:release_name) { 'my-release' }
+
+ subject { described_class.new(namespace: namespace) }
+
+ describe '#cleanup' do
+ it 'raises an error if the Kubernetes command fails' do
+ expect(Gitlab::Popen).to receive(:popen_with_detail)
+ .with([%(kubectl --namespace "#{namespace}" delete ) \
+ 'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa ' \
+ "--now -l release=\"#{release_name}\""])
+ .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: false)))
+
+ expect { subject.cleanup(release_name: release_name) }.to raise_error(described_class::CommandFailedError)
+ end
+
+ it 'calls kubectl with the correct arguments' do
+ expect(Gitlab::Popen).to receive(:popen_with_detail)
+ .with([%(kubectl --namespace "#{namespace}" delete ) \
+ 'ingress,svc,pdb,hpa,deploy,statefulset,job,pod,secret,configmap,pvc,secret,clusterrole,clusterrolebinding,role,rolebinding,sa ' \
+ "--now -l release=\"#{release_name}\""])
+ .and_return(Gitlab::Popen::Result.new([], '', '', double(success?: true)))
+
+ # We're not verifying the output here, just silencing it
+ expect { subject.cleanup(release_name: release_name) }.to output.to_stdout
+ end
+ end
+end
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index ff1a5aa2536..150c00e4bfe 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -522,7 +522,7 @@ describe Notify do
let(:project_snippet) { create(:project_snippet, project: project) }
let(:project_snippet_note) { create(:note_on_project_snippet, project: project, noteable: project_snippet) }
- subject { described_class.note_snippet_email(project_snippet_note.author_id, project_snippet_note.id) }
+ subject { described_class.note_project_snippet_email(project_snippet_note.author_id, project_snippet_note.id) }
it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
let(:model) { project_snippet }
diff --git a/spec/migrations/add_pages_access_level_to_project_feature_spec.rb b/spec/migrations/add_pages_access_level_to_project_feature_spec.rb
new file mode 100644
index 00000000000..3946602c5be
--- /dev/null
+++ b/spec/migrations/add_pages_access_level_to_project_feature_spec.rb
@@ -0,0 +1,30 @@
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20180423204600_add_pages_access_level_to_project_feature.rb')
+
+describe AddPagesAccessLevelToProjectFeature, :migration do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:features) { table(:project_features) }
+ let!(:namespace) { namespaces.create(name: 'gitlab', path: 'gitlab') }
+ let!(:first_project) { projects.create(name: 'gitlab1', path: 'gitlab1', namespace_id: namespace.id) }
+ let!(:first_project_features) { features.create(project_id: first_project.id) }
+ let!(:second_project) { projects.create(name: 'gitlab2', path: 'gitlab2', namespace_id: namespace.id) }
+ let!(:second_project_features) { features.create(project_id: second_project.id) }
+
+ it 'correctly migrate pages for old projects to be public' do
+ migrate!
+
+ # For old projects pages should be public
+ expect(first_project_features.reload.pages_access_level).to eq ProjectFeature::PUBLIC
+ expect(second_project_features.reload.pages_access_level).to eq ProjectFeature::PUBLIC
+ end
+
+ it 'after migration pages are enabled as default' do
+ migrate!
+
+ # For new project default is enabled
+ third_project = projects.create(name: 'gitlab3', path: 'gitlab3', namespace_id: namespace.id)
+ third_project_features = features.create(project_id: third_project.id)
+ expect(third_project_features.reload.pages_access_level).to eq ProjectFeature::ENABLED
+ end
+end
diff --git a/spec/migrations/backfill_store_project_full_path_in_repo_spec.rb b/spec/migrations/backfill_store_project_full_path_in_repo_spec.rb
new file mode 100644
index 00000000000..34f4a36d63d
--- /dev/null
+++ b/spec/migrations/backfill_store_project_full_path_in_repo_spec.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require Rails.root.join('db', 'post_migrate', '20181010133639_backfill_store_project_full_path_in_repo.rb')
+
+describe BackfillStoreProjectFullPathInRepo, :migration do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:group) { namespaces.create!(name: 'foo', path: 'foo') }
+ let(:subgroup) { namespaces.create!(name: 'bar', path: 'bar', parent_id: group.id) }
+
+ subject(:migration) { described_class.new }
+
+ around do |example|
+ Sidekiq::Testing.inline! do
+ example.run
+ end
+ end
+
+ describe '#up' do
+ shared_examples_for 'writes the full path to git config' do
+ it 'writes the git config' do
+ expect_next_instance_of(Gitlab::GitalyClient::RepositoryService) do |repository_service|
+ allow(repository_service).to receive(:cleanup)
+ expect(repository_service).to receive(:set_config).with('gitlab.fullpath' => expected_path)
+ end
+
+ migration.up
+ end
+
+ it 'retries in case of failure' do
+ repository_service = spy(:repository_service)
+
+ allow(Gitlab::GitalyClient::RepositoryService).to receive(:new).and_return(repository_service)
+
+ allow(repository_service).to receive(:set_config).and_raise(GRPC::BadStatus, 'Retry me')
+ expect(repository_service).to receive(:set_config).exactly(3).times
+
+ migration.up
+ end
+
+ it 'cleans up repository before writing the config' do
+ expect_next_instance_of(Gitlab::GitalyClient::RepositoryService) do |repository_service|
+ expect(repository_service).to receive(:cleanup).ordered
+ expect(repository_service).to receive(:set_config).ordered
+ end
+
+ migration.up
+ end
+
+ context 'legacy storage' do
+ it 'finds the repository at the correct location' do
+ Project.find(project.id).create_repository
+
+ expect { migration.up }.not_to raise_error
+ end
+ end
+
+ context 'hashed storage' do
+ it 'finds the repository at the correct location' do
+ project.update_attribute(:storage_version, 1)
+
+ Project.find(project.id).create_repository
+
+ expect { migration.up }.not_to raise_error
+ end
+ end
+ end
+
+ context 'project in group' do
+ let!(:project) { projects.create!(namespace_id: group.id, name: 'baz', path: 'baz') }
+ let(:expected_path) { 'foo/baz' }
+
+ it_behaves_like 'writes the full path to git config'
+ end
+
+ context 'project in subgroup' do
+ let!(:project) { projects.create!(namespace_id: subgroup.id, name: 'baz', path: 'baz') }
+ let(:expected_path) { 'foo/bar/baz' }
+
+ it_behaves_like 'writes the full path to git config'
+ end
+ end
+
+ describe '#down' do
+ context 'project in group' do
+ let!(:project) { projects.create!(namespace_id: group.id, name: 'baz', path: 'baz') }
+
+ it 'deletes the gitlab full config value' do
+ expect_any_instance_of(Gitlab::GitalyClient::RepositoryService)
+ .to receive(:delete_config).with(['gitlab.fullpath'])
+
+ migration.down
+ end
+ end
+ end
+end
diff --git a/spec/migrations/clean_up_for_members_spec.rb b/spec/migrations/clean_up_for_members_spec.rb
index 0258860d169..7876536cb3e 100644
--- a/spec/migrations/clean_up_for_members_spec.rb
+++ b/spec/migrations/clean_up_for_members_spec.rb
@@ -3,6 +3,7 @@ require Rails.root.join('db', 'migrate', '20171216111734_clean_up_for_members.rb
describe CleanUpForMembers, :migration do
let(:migration) { described_class.new }
+ let(:groups) { table(:namespaces) }
let!(:group_member) { create_group_member }
let!(:unbinded_group_member) { create_group_member }
let!(:invited_group_member) { create_group_member(true) }
@@ -25,7 +26,7 @@ describe CleanUpForMembers, :migration do
end
def create_group_member(invited = false)
- fill_member(GroupMember.new(group: create_group), invited)
+ fill_member(GroupMember.new(source_id: create_group.id, source_type: 'Namespace'), invited)
end
def create_project_member(invited = false)
@@ -54,7 +55,7 @@ describe CleanUpForMembers, :migration do
def create_group
name = FFaker::Lorem.characters(10)
- Group.create(name: name, path: name.downcase.gsub(/\s/, '_'))
+ groups.create!(type: 'Group', name: name, path: name.downcase.gsub(/\s/, '_'))
end
def create_project
diff --git a/spec/migrations/cleanup_environments_external_url_spec.rb b/spec/migrations/cleanup_environments_external_url_spec.rb
new file mode 100644
index 00000000000..07ddaf3d38f
--- /dev/null
+++ b/spec/migrations/cleanup_environments_external_url_spec.rb
@@ -0,0 +1,28 @@
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20181108091549_cleanup_environments_external_url.rb')
+
+describe CleanupEnvironmentsExternalUrl, :migration do
+ let(:environments) { table(:environments) }
+ let(:invalid_entries) { environments.where(environments.arel_table[:external_url].matches('javascript://%')) }
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+
+ before do
+ namespace = namespaces.create(name: 'foo', path: 'foo')
+ project = projects.create!(namespace_id: namespace.id)
+
+ environments.create!(id: 1, project_id: project.id, name: 'poisoned', slug: 'poisoned', external_url: 'javascript://alert("1")')
+ end
+
+ it 'clears every environment with a javascript external_url' do
+ expect do
+ subject.up
+ end.to change { invalid_entries.count }.from(1).to(0)
+ end
+
+ it 'do not removes environments' do
+ expect do
+ subject.up
+ end.not_to change { environments.count }
+ end
+end
diff --git a/spec/migrations/delete_inconsistent_internal_id_records_spec.rb b/spec/migrations/delete_inconsistent_internal_id_records_spec.rb
index becb71cf427..8c55daf0d37 100644
--- a/spec/migrations/delete_inconsistent_internal_id_records_spec.rb
+++ b/spec/migrations/delete_inconsistent_internal_id_records_spec.rb
@@ -65,6 +65,21 @@ describe DeleteInconsistentInternalIdRecords, :migration do
context 'for deployments' do
let(:scope) { :deployment }
+ let(:deployments) { table(:deployments) }
+ let(:internal_ids) { table(:internal_ids) }
+
+ before do
+ internal_ids.create!(project_id: project1.id, usage: 2, last_value: 2)
+ internal_ids.create!(project_id: project2.id, usage: 2, last_value: 2)
+ internal_ids.create!(project_id: project3.id, usage: 2, last_value: 2)
+ end
+
+ let(:create_models) do
+ 3.times { |i| deployments.create!(project_id: project1.id, iid: i, environment_id: 1, ref: 'master', sha: 'a', tag: false) }
+ 3.times { |i| deployments.create!(project_id: project2.id, iid: i, environment_id: 1, ref: 'master', sha: 'a', tag: false) }
+ 3.times { |i| deployments.create!(project_id: project3.id, iid: i, environment_id: 1, ref: 'master', sha: 'a', tag: false) }
+ end
+
it_behaves_like 'deleting inconsistent internal_id records'
end
@@ -79,17 +94,18 @@ describe DeleteInconsistentInternalIdRecords, :migration do
end
context 'for milestones (by group)' do
- # milestones (by group) is a little different than all of the other models
- let!(:group1) { create(:group) }
- let!(:group2) { create(:group) }
- let!(:group3) { create(:group) }
+ # milestones (by group) is a little different than most of the other models
+ let(:groups) { table(:namespaces) }
+ let(:group1) { groups.create(name: 'Group 1', type: 'Group', path: 'group_1') }
+ let(:group2) { groups.create(name: 'Group 2', type: 'Group', path: 'group_2') }
+ let(:group3) { groups.create(name: 'Group 2', type: 'Group', path: 'group_3') }
let(:internal_id_query) { ->(group) { InternalId.where(usage: InternalId.usages['milestones'], namespace: group) } }
before do
- 3.times { create(:milestone, group: group1) }
- 3.times { create(:milestone, group: group2) }
- 3.times { create(:milestone, group: group3) }
+ 3.times { create(:milestone, group_id: group1.id) }
+ 3.times { create(:milestone, group_id: group2.id) }
+ 3.times { create(:milestone, group_id: group3.id) }
internal_id_query.call(group1).first.tap do |iid|
iid.last_value = iid.last_value - 2
diff --git a/spec/migrations/enqueue_redact_links_spec.rb b/spec/migrations/enqueue_redact_links_spec.rb
new file mode 100644
index 00000000000..a5da76977b7
--- /dev/null
+++ b/spec/migrations/enqueue_redact_links_spec.rb
@@ -0,0 +1,42 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20181014121030_enqueue_redact_links.rb')
+
+describe EnqueueRedactLinks, :migration, :sidekiq do
+ let(:merge_requests) { table(:merge_requests) }
+ let(:issues) { table(:issues) }
+ let(:notes) { table(:notes) }
+ let(:projects) { table(:projects) }
+ let(:namespaces) { table(:namespaces) }
+ let(:snippets) { table(:snippets) }
+ let(:users) { table(:users) }
+ let(:user) { users.create!(email: 'test@example.com', projects_limit: 100, username: 'test') }
+
+ before do
+ stub_const("#{described_class.name}::BATCH_SIZE", 1)
+
+ text = 'some text /sent_notifications/00000000000000000000000000000000/unsubscribe more text'
+ group = namespaces.create!(name: 'gitlab', path: 'gitlab')
+ project = projects.create!(namespace_id: group.id)
+
+ merge_requests.create!(id: 1, target_project_id: project.id, source_project_id: project.id, target_branch: 'feature', source_branch: 'master', description: text)
+ issues.create!(id: 1, description: text)
+ notes.create!(id: 1, note: text)
+ notes.create!(id: 2, note: text)
+ snippets.create!(id: 1, description: text, author_id: user.id)
+ end
+
+ it 'correctly schedules background migrations' do
+ Sidekiq::Testing.fake! do
+ Timecop.freeze do
+ migrate!
+
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(5.minutes, "Note", "note", 1, 1)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(10.minutes, "Note", "note", 2, 2)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(5.minutes, "Issue", "description", 1, 1)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(5.minutes, "MergeRequest", "description", 1, 1)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(5.minutes, "Snippet", "description", 1, 1)
+ expect(BackgroundMigrationWorker.jobs.size).to eq 5
+ end
+ end
+ end
+end
diff --git a/spec/migrations/fill_empty_finished_at_in_deployments_spec.rb b/spec/migrations/fill_empty_finished_at_in_deployments_spec.rb
new file mode 100644
index 00000000000..cf5c10f77e1
--- /dev/null
+++ b/spec/migrations/fill_empty_finished_at_in_deployments_spec.rb
@@ -0,0 +1,70 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20181030135124_fill_empty_finished_at_in_deployments')
+
+describe FillEmptyFinishedAtInDeployments, :migration do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:environments) { table(:environments) }
+ let(:deployments) { table(:deployments) }
+
+ context 'when a deployment row does not have a value on finished_at' do
+ context 'when a deployment succeeded' do
+ before do
+ namespaces.create!(id: 123, name: 'gitlab1', path: 'gitlab1')
+ projects.create!(id: 1, name: 'gitlab1', path: 'gitlab1', namespace_id: 123)
+ environments.create!(id: 1, name: 'production', slug: 'production', project_id: 1)
+ deployments.create!(id: 1, iid: 1, project_id: 1, environment_id: 1, ref: 'master', sha: 'xxx', tag: false)
+ end
+
+ it 'correctly replicates finished_at by created_at' do
+ expect(deployments.last.created_at).not_to be_nil
+ expect(deployments.last.finished_at).to be_nil
+
+ migrate!
+
+ expect(deployments.last.created_at).not_to be_nil
+ expect(deployments.last.finished_at).to eq(deployments.last.created_at)
+ end
+ end
+
+ context 'when a deployment is running' do
+ before do
+ namespaces.create!(id: 123, name: 'gitlab1', path: 'gitlab1')
+ projects.create!(id: 1, name: 'gitlab1', path: 'gitlab1', namespace_id: 123)
+ environments.create!(id: 1, name: 'production', slug: 'production', project_id: 1)
+ deployments.create!(id: 1, iid: 1, project_id: 1, environment_id: 1, ref: 'master', sha: 'xxx', tag: false, status: 1)
+ end
+
+ it 'does not fill finished_at' do
+ expect(deployments.last.created_at).not_to be_nil
+ expect(deployments.last.finished_at).to be_nil
+
+ migrate!
+
+ expect(deployments.last.created_at).not_to be_nil
+ expect(deployments.last.finished_at).to be_nil
+ end
+ end
+ end
+
+ context 'when a deployment row does has a value on finished_at' do
+ let(:finished_at) { '2018-10-30 11:12:02 UTC' }
+
+ before do
+ namespaces.create!(id: 123, name: 'gitlab1', path: 'gitlab1')
+ projects.create!(id: 1, name: 'gitlab1', path: 'gitlab1', namespace_id: 123)
+ environments.create!(id: 1, name: 'production', slug: 'production', project_id: 1)
+ deployments.create!(id: 1, iid: 1, project_id: 1, environment_id: 1, ref: 'master', sha: 'xxx', tag: false, finished_at: finished_at)
+ end
+
+ it 'does not affect existing value' do
+ expect(deployments.last.created_at).not_to be_nil
+ expect(deployments.last.finished_at).not_to be_nil
+
+ migrate!
+
+ expect(deployments.last.created_at).not_to be_nil
+ expect(deployments.last.finished_at).to eq(finished_at)
+ end
+ end
+end
diff --git a/spec/migrations/migrate_forbidden_redirect_uris_spec.rb b/spec/migrations/migrate_forbidden_redirect_uris_spec.rb
new file mode 100644
index 00000000000..0bc13a3974a
--- /dev/null
+++ b/spec/migrations/migrate_forbidden_redirect_uris_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20181026091631_migrate_forbidden_redirect_uris.rb')
+
+describe MigrateForbiddenRedirectUris, :migration do
+ let(:oauth_application) { table(:oauth_applications) }
+ let(:oauth_access_grant) { table(:oauth_access_grants) }
+
+ let!(:control_app) { oauth_application.create(random_params) }
+ let!(:control_access_grant) { oauth_application.create(random_params) }
+ let!(:forbidden_js_app) { oauth_application.create(random_params.merge(redirect_uri: 'javascript://alert()')) }
+ let!(:forbidden_vb_app) { oauth_application.create(random_params.merge(redirect_uri: 'VBSCRIPT://alert()')) }
+ let!(:forbidden_access_grant) { oauth_application.create(random_params.merge(redirect_uri: 'vbscript://alert()')) }
+
+ context 'oauth application' do
+ it 'migrates forbidden javascript URI' do
+ expect { migrate! }.to change { forbidden_js_app.reload.redirect_uri }.to('http://forbidden-scheme-has-been-overwritten')
+ end
+
+ it 'migrates forbidden VBScript URI' do
+ expect { migrate! }.to change { forbidden_vb_app.reload.redirect_uri }.to('http://forbidden-scheme-has-been-overwritten')
+ end
+
+ it 'does not migrate a valid URI' do
+ expect { migrate! }.not_to change { control_app.reload.redirect_uri }
+ end
+ end
+
+ context 'access grant' do
+ it 'migrates forbidden VBScript URI' do
+ expect { migrate! }.to change { forbidden_access_grant.reload.redirect_uri }.to('http://forbidden-scheme-has-been-overwritten')
+ end
+
+ it 'does not migrate a valid URI' do
+ expect { migrate! }.not_to change { control_access_grant.reload.redirect_uri }
+ end
+ end
+
+ def random_params
+ {
+ name: 'test',
+ secret: 'test',
+ uid: Doorkeeper::OAuth::Helpers::UniqueToken.generate,
+ redirect_uri: 'http://valid.com'
+ }
+ end
+end
diff --git a/spec/migrations/migrate_issues_to_ghost_user_spec.rb b/spec/migrations/migrate_issues_to_ghost_user_spec.rb
index 9220b49a736..0016f058a17 100644
--- a/spec/migrations/migrate_issues_to_ghost_user_spec.rb
+++ b/spec/migrations/migrate_issues_to_ghost_user_spec.rb
@@ -18,33 +18,33 @@ describe MigrateIssuesToGhostUser, :migration do
let!(:ghost) { users.create(ghost: true, email: 'ghost@example.com') }
it 'does not create a new user' do
- expect { schema_migrate_up! }.not_to change { User.count }
+ expect { migrate! }.not_to change { User.count }
end
it 'migrates issues where author = nil to the ghost user' do
- schema_migrate_up!
+ migrate!
expect(issues.first.reload.author_id).to eq(ghost.id)
end
it 'does not change issues authored by an existing user' do
- expect { schema_migrate_up! }.not_to change { issues.second.reload.author_id}
+ expect { migrate! }.not_to change { issues.second.reload.author_id}
end
end
context 'when ghost user does not exist' do
it 'creates a new user' do
- expect { schema_migrate_up! }.to change { User.count }.by(1)
+ expect { migrate! }.to change { User.count }.by(1)
end
it 'migrates issues where author = nil to the ghost user' do
- schema_migrate_up!
+ migrate!
expect(issues.first.reload.author_id).to eq(User.ghost.id)
end
it 'does not change issues authored by an existing user' do
- expect { schema_migrate_up! }.not_to change { issues.second.reload.author_id}
+ expect { migrate! }.not_to change { issues.second.reload.author_id}
end
end
end
diff --git a/spec/migrations/migrate_old_artifacts_spec.rb b/spec/migrations/migrate_old_artifacts_spec.rb
index 4187ab149a5..af77d64fdbf 100644
--- a/spec/migrations/migrate_old_artifacts_spec.rb
+++ b/spec/migrations/migrate_old_artifacts_spec.rb
@@ -76,7 +76,7 @@ describe MigrateOldArtifacts do
end
end
- context 'when there are aritfacts in old and new directory' do
+ context 'when there are artifacts in old and new directory' do
before do
store_artifacts_in_legacy_path(build2)
diff --git a/spec/migrations/rename_more_reserved_project_names_spec.rb b/spec/migrations/rename_more_reserved_project_names_spec.rb
index 034e8a6a4e5..baf16c2ce53 100644
--- a/spec/migrations/rename_more_reserved_project_names_spec.rb
+++ b/spec/migrations/rename_more_reserved_project_names_spec.rb
@@ -31,7 +31,16 @@ describe RenameMoreReservedProjectNames, :delete do
context 'when exception is raised during rename' do
before do
- allow(project).to receive(:rename_repo).and_raise(StandardError)
+ service = instance_double('service')
+
+ allow(service)
+ .to receive(:execute)
+ .and_raise(Projects::AfterRenameService::RenameFailedError)
+
+ allow(Projects::AfterRenameService)
+ .to receive(:new)
+ .with(project)
+ .and_return(service)
end
it 'captures exception from project rename' do
diff --git a/spec/migrations/rename_reserved_project_names_spec.rb b/spec/migrations/rename_reserved_project_names_spec.rb
index 592ac2b5fb9..7818aa0d560 100644
--- a/spec/migrations/rename_reserved_project_names_spec.rb
+++ b/spec/migrations/rename_reserved_project_names_spec.rb
@@ -35,7 +35,16 @@ describe RenameReservedProjectNames, :migration, schema: :latest do
context 'when exception is raised during rename' do
before do
- allow(project).to receive(:rename_repo).and_raise(StandardError)
+ service = instance_double('service')
+
+ allow(service)
+ .to receive(:execute)
+ .and_raise(Projects::AfterRenameService::RenameFailedError)
+
+ allow(Projects::AfterRenameService)
+ .to receive(:new)
+ .with(project)
+ .and_return(service)
end
it 'captures exception from project rename' do
diff --git a/spec/migrations/schedule_digest_personal_access_tokens_spec.rb b/spec/migrations/schedule_digest_personal_access_tokens_spec.rb
new file mode 100644
index 00000000000..6d155f78342
--- /dev/null
+++ b/spec/migrations/schedule_digest_personal_access_tokens_spec.rb
@@ -0,0 +1,46 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20180913142237_schedule_digest_personal_access_tokens.rb')
+
+describe ScheduleDigestPersonalAccessTokens, :migration, :sidekiq do
+ let(:personal_access_tokens) { table(:personal_access_tokens) }
+ let(:users) { table(:users) }
+
+ before do
+ stub_const("#{described_class.name}::BATCH_SIZE", 4)
+
+ users.create(id: 1, email: 'user@example.com', projects_limit: 10)
+
+ personal_access_tokens.create!(id: 1, user_id: 1, name: 'pat-01', token: 'token-01')
+ personal_access_tokens.create!(id: 2, user_id: 1, name: 'pat-02', token: 'token-02')
+ personal_access_tokens.create!(id: 3, user_id: 1, name: 'pat-03', token_digest: 'token_digest')
+ personal_access_tokens.create!(id: 4, user_id: 1, name: 'pat-04', token: 'token-04')
+ personal_access_tokens.create!(id: 5, user_id: 1, name: 'pat-05', token: 'token-05')
+ personal_access_tokens.create!(id: 6, user_id: 1, name: 'pat-06', token: 'token-06')
+ end
+
+ it 'correctly schedules background migrations' do
+ Sidekiq::Testing.fake! do
+ migrate!
+
+ expect(described_class::MIGRATION).to(
+ be_scheduled_delayed_migration(
+ 5.minutes, 'PersonalAccessToken', 'token', 'token_digest', 1, 5))
+ expect(described_class::MIGRATION).to(
+ be_scheduled_delayed_migration(
+ 10.minutes, 'PersonalAccessToken', 'token', 'token_digest', 6, 6))
+ expect(BackgroundMigrationWorker.jobs.size).to eq 2
+ end
+ end
+
+ it 'schedules background migrations' do
+ perform_enqueued_jobs do
+ plain_text_token = 'token IS NOT NULL'
+
+ expect(personal_access_tokens.where(plain_text_token).count).to eq 5
+
+ migrate!
+
+ expect(personal_access_tokens.where(plain_text_token).count).to eq 0
+ end
+ end
+end
diff --git a/spec/migrations/steal_fill_store_upload_spec.rb b/spec/migrations/steal_fill_store_upload_spec.rb
new file mode 100644
index 00000000000..ed809baf2b5
--- /dev/null
+++ b/spec/migrations/steal_fill_store_upload_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20181105201455_steal_fill_store_upload.rb')
+
+describe StealFillStoreUpload, :migration do
+ let(:uploads) { table(:uploads) }
+
+ describe '#up' do
+ it 'steals the FillStoreUpload background migration' do
+ expect(Gitlab::BackgroundMigration).to receive(:steal).with('FillStoreUpload').and_call_original
+
+ migrate!
+ end
+
+ it 'does not run migration if not needed' do
+ uploads.create(size: 100.kilobytes,
+ uploader: 'AvatarUploader',
+ path: 'uploads/-/system/avatar.jpg',
+ store: 1)
+
+ expect_any_instance_of(Gitlab::BackgroundMigration::FillStoreUpload).not_to receive(:perform)
+
+ migrate!
+ end
+
+ it 'ensures all rows are migrated' do
+ uploads.create(size: 100.kilobytes,
+ uploader: 'AvatarUploader',
+ path: 'uploads/-/system/avatar.jpg',
+ store: nil)
+
+ expect_any_instance_of(Gitlab::BackgroundMigration::FillStoreUpload).to receive(:perform).and_call_original
+
+ expect do
+ migrate!
+ end.to change { uploads.where(store: nil).count }.from(1).to(0)
+ end
+ end
+end
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index 9647c1b9f63..96aa9a82b71 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -25,6 +25,9 @@ describe ApplicationSetting do
it { is_expected.to allow_value(https).for(:after_sign_out_path) }
it { is_expected.not_to allow_value(ftp).for(:after_sign_out_path) }
+ it { is_expected.to allow_value("dev.gitlab.com").for(:commit_email_hostname) }
+ it { is_expected.not_to allow_value("@dev.gitlab").for(:commit_email_hostname) }
+
describe 'default_artifacts_expire_in' do
it 'sets an error if it cannot parse' do
setting.update(default_artifacts_expire_in: 'a')
@@ -107,6 +110,14 @@ describe ApplicationSetting do
it { expect(setting.repository_storages).to eq(['default']) }
end
+ context '#commit_email_hostname' do
+ it 'returns configured gitlab hostname if commit_email_hostname is not defined' do
+ setting.update(commit_email_hostname: nil)
+
+ expect(setting.commit_email_hostname).to eq("users.noreply.#{Gitlab.config.gitlab.host}")
+ end
+ end
+
context 'auto_devops_domain setting' do
context 'when auto_devops_enabled? is true' do
before do
@@ -141,19 +152,6 @@ describe ApplicationSetting do
end
end
- context 'circuitbreaker settings' do
- [:circuitbreaker_failure_count_threshold,
- :circuitbreaker_check_interval,
- :circuitbreaker_failure_reset_time,
- :circuitbreaker_storage_timeout].each do |field|
- it "Validates #{field} as number" do
- is_expected.to validate_numericality_of(field)
- .only_integer
- .is_greater_than_or_equal_to(0)
- end
- end
- end
-
context 'repository storages' do
before do
storages = {
@@ -592,4 +590,39 @@ describe ApplicationSetting do
it { is_expected.to eq(result) }
end
end
+
+ context 'diff limit settings' do
+ describe '#diff_max_patch_bytes' do
+ context 'validations' do
+ it { is_expected.to validate_presence_of(:diff_max_patch_bytes) }
+
+ it do
+ is_expected.to validate_numericality_of(:diff_max_patch_bytes)
+ .only_integer
+ .is_greater_than_or_equal_to(Gitlab::Git::Diff::DEFAULT_MAX_PATCH_BYTES)
+ .is_less_than_or_equal_to(Gitlab::Git::Diff::MAX_PATCH_BYTES_UPPER_BOUND)
+ end
+ end
+ end
+ end
+
+ describe '#archive_builds_older_than' do
+ subject { setting.archive_builds_older_than }
+
+ context 'when the archive_builds_in_seconds is set' do
+ before do
+ setting.archive_builds_in_seconds = 3600
+ end
+
+ it { is_expected.to be_within(1.minute).of(1.hour.ago) }
+ end
+
+ context 'when the archive_builds_in_seconds is set' do
+ before do
+ setting.archive_builds_in_seconds = nil
+ end
+
+ it { is_expected.to be_nil }
+ end
+ end
end
diff --git a/spec/models/blob_spec.rb b/spec/models/blob_spec.rb
index 81e35e6c931..ed93f94d893 100644
--- a/spec/models/blob_spec.rb
+++ b/spec/models/blob_spec.rb
@@ -18,14 +18,23 @@ describe Blob do
describe '.lazy' do
let(:project) { create(:project, :repository) }
- let(:commit) { project.commit_by(oid: 'e63f41fe459e62e1228fcef60d7189127aeba95a') }
+ let(:other_project) { create(:project, :repository) }
+ let(:commit_id) { 'e63f41fe459e62e1228fcef60d7189127aeba95a' }
- it 'fetches all blobs when the first is accessed' do
- changelog = described_class.lazy(project, commit.id, 'CHANGELOG')
- contributing = described_class.lazy(project, commit.id, 'CONTRIBUTING.md')
+ it 'does not fetch blobs when none are accessed' do
+ expect(project.repository).not_to receive(:blobs_at)
- expect(Gitlab::Git::Blob).to receive(:batch).once.and_call_original
- expect(Gitlab::Git::Blob).not_to receive(:find)
+ described_class.lazy(project, commit_id, 'CHANGELOG')
+ end
+
+ it 'fetches all blobs for the same repository when one is accessed' do
+ expect(project.repository).to receive(:blobs_at).with([[commit_id, 'CHANGELOG'], [commit_id, 'CONTRIBUTING.md']]).once.and_call_original
+ expect(other_project.repository).not_to receive(:blobs_at)
+
+ changelog = described_class.lazy(project, commit_id, 'CHANGELOG')
+ contributing = described_class.lazy(project, commit_id, 'CONTRIBUTING.md')
+
+ described_class.lazy(other_project, commit_id, 'CHANGELOG')
# Access property so the values are loaded
changelog.id
diff --git a/spec/models/blob_viewer/package_json_spec.rb b/spec/models/blob_viewer/package_json_spec.rb
index 5ed2f4400bc..fbaa8d47a71 100644
--- a/spec/models/blob_viewer/package_json_spec.rb
+++ b/spec/models/blob_viewer/package_json_spec.rb
@@ -40,13 +40,14 @@ describe BlobViewer::PackageJson do
end
context 'when package.json has "private": true' do
+ let(:homepage) { 'http://example.com' }
let(:data) do
<<-SPEC.strip_heredoc
{
"name": "module-name",
"version": "10.3.1",
"private": true,
- "homepage": "myawesomepackage.com"
+ "homepage": #{homepage.to_json}
}
SPEC
end
@@ -54,10 +55,22 @@ describe BlobViewer::PackageJson do
subject { described_class.new(blob) }
describe '#package_url' do
- it 'returns homepage if any' do
- expect(subject).to receive(:prepare!)
+ context 'when the homepage has a valid URL' do
+ it 'returns homepage URL' do
+ expect(subject).to receive(:prepare!)
+
+ expect(subject.package_url).to eq(homepage)
+ end
+ end
+
+ context 'when the homepage has an invalid URL' do
+ let(:homepage) { 'javascript:alert()' }
+
+ it 'returns nil' do
+ expect(subject).to receive(:prepare!)
- expect(subject.package_url).to eq('myawesomepackage.com')
+ expect(subject.package_url).to be_nil
+ end
end
end
diff --git a/spec/models/board_group_recent_visit_spec.rb b/spec/models/board_group_recent_visit_spec.rb
new file mode 100644
index 00000000000..59ad4e5417e
--- /dev/null
+++ b/spec/models/board_group_recent_visit_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe BoardGroupRecentVisit do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:board) { create(:board, group: group) }
+
+ describe 'relationships' do
+ it { is_expected.to belong_to(:user) }
+ it { is_expected.to belong_to(:group) }
+ it { is_expected.to belong_to(:board) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:user) }
+ it { is_expected.to validate_presence_of(:group) }
+ it { is_expected.to validate_presence_of(:board) }
+ end
+
+ describe '#visited' do
+ it 'creates a visit if one does not exists' do
+ expect { described_class.visited!(user, board) }.to change(described_class, :count).by(1)
+ end
+
+ shared_examples 'was visited previously' do
+ let!(:visit) { create :board_group_recent_visit, group: board.group, board: board, user: user, updated_at: 7.days.ago }
+
+ it 'updates the timestamp' do
+ Timecop.freeze do
+ described_class.visited!(user, board)
+
+ expect(described_class.count).to eq 1
+ expect(described_class.first.updated_at).to be_like_time(Time.zone.now)
+ end
+ end
+ end
+
+ it_behaves_like 'was visited previously'
+
+ context 'when we try to create a visit that is not unique' do
+ before do
+ expect(described_class).to receive(:find_or_create_by).and_raise(ActiveRecord::RecordNotUnique, 'record not unique')
+ expect(described_class).to receive(:find_or_create_by).and_return(visit)
+ end
+
+ it_behaves_like 'was visited previously'
+ end
+ end
+
+ describe '#latest' do
+ it 'returns the most recent visited' do
+ board2 = create(:board, group: group)
+ board3 = create(:board, group: group)
+
+ create :board_group_recent_visit, group: board.group, board: board, user: user, updated_at: 7.days.ago
+ create :board_group_recent_visit, group: board2.group, board: board2, user: user, updated_at: 5.days.ago
+ recent = create :board_group_recent_visit, group: board3.group, board: board3, user: user, updated_at: 1.day.ago
+
+ expect(described_class.latest(user, group)).to eq recent
+ end
+ end
+end
diff --git a/spec/models/board_project_recent_visit_spec.rb b/spec/models/board_project_recent_visit_spec.rb
new file mode 100644
index 00000000000..275581945fa
--- /dev/null
+++ b/spec/models/board_project_recent_visit_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe BoardProjectRecentVisit do
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+ let(:board) { create(:board, project: project) }
+
+ describe 'relationships' do
+ it { is_expected.to belong_to(:user) }
+ it { is_expected.to belong_to(:project) }
+ it { is_expected.to belong_to(:board) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:user) }
+ it { is_expected.to validate_presence_of(:project) }
+ it { is_expected.to validate_presence_of(:board) }
+ end
+
+ describe '#visited' do
+ it 'creates a visit if one does not exists' do
+ expect { described_class.visited!(user, board) }.to change(described_class, :count).by(1)
+ end
+
+ shared_examples 'was visited previously' do
+ let!(:visit) { create :board_project_recent_visit, project: board.project, board: board, user: user, updated_at: 7.days.ago }
+
+ it 'updates the timestamp' do
+ Timecop.freeze do
+ described_class.visited!(user, board)
+
+ expect(described_class.count).to eq 1
+ expect(described_class.first.updated_at).to be_like_time(Time.zone.now)
+ end
+ end
+ end
+
+ it_behaves_like 'was visited previously'
+
+ context 'when we try to create a visit that is not unique' do
+ before do
+ expect(described_class).to receive(:find_or_create_by).and_raise(ActiveRecord::RecordNotUnique, 'record not unique')
+ expect(described_class).to receive(:find_or_create_by).and_return(visit)
+ end
+
+ it_behaves_like 'was visited previously'
+ end
+ end
+
+ describe '#latest' do
+ it 'returns the most recent visited' do
+ board2 = create(:board, project: project)
+ board3 = create(:board, project: project)
+
+ create :board_project_recent_visit, project: board.project, board: board, user: user, updated_at: 7.days.ago
+ create :board_project_recent_visit, project: board2.project, board: board2, user: user, updated_at: 5.days.ago
+ recent = create :board_project_recent_visit, project: board3.project, board: board3, user: user, updated_at: 1.day.ago
+
+ expect(described_class.latest(user, project)).to eq recent
+ end
+ end
+end
diff --git a/spec/models/ci/build_metadata_spec.rb b/spec/models/ci/build_metadata_spec.rb
index 6dba132184c..519968b9e48 100644
--- a/spec/models/ci/build_metadata_spec.rb
+++ b/spec/models/ci/build_metadata_spec.rb
@@ -15,6 +15,8 @@ describe Ci::BuildMetadata do
let(:build) { create(:ci_build, pipeline: pipeline) }
let(:build_metadata) { build.metadata }
+ it_behaves_like 'having unique enum values'
+
describe '#update_timeout_state' do
subject { build_metadata }
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index dbebda20ce0..d02c3a5765f 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -17,8 +17,8 @@ describe Ci::Build do
it { is_expected.to belong_to(:runner) }
it { is_expected.to belong_to(:trigger_request) }
it { is_expected.to belong_to(:erased_by) }
- it { is_expected.to have_many(:deployments) }
it { is_expected.to have_many(:trace_sections)}
+ it { is_expected.to have_one(:deployment) }
it { is_expected.to have_one(:runner_session)}
it { is_expected.to validate_presence_of(:ref) }
it { is_expected.to respond_to(:has_trace?) }
@@ -176,9 +176,7 @@ describe Ci::Build do
it 'does not execute a query for selecting job artifact one by one' do
recorded = ActiveRecord::QueryRecorder.new do
subject.each do |build|
- Ci::JobArtifact::TEST_REPORT_FILE_TYPES.each do |file_type|
- build.public_send("job_artifacts_#{file_type}").file.exists?
- end
+ build.job_artifacts.map { |a| a.file.exists? }
end
end
@@ -211,6 +209,143 @@ describe Ci::Build do
end
end
+ describe '#schedulable?' do
+ subject { build.schedulable? }
+
+ context 'when build is schedulable' do
+ let(:build) { create(:ci_build, :created, :schedulable, project: project) }
+
+ it { expect(subject).to be_truthy }
+ end
+
+ context 'when build is not schedulable' do
+ let(:build) { create(:ci_build, :created, project: project) }
+
+ it { expect(subject).to be_falsy }
+ end
+ end
+
+ describe '#schedule' do
+ subject { build.schedule }
+
+ before do
+ project.add_developer(user)
+ end
+
+ let(:build) { create(:ci_build, :created, :schedulable, user: user, project: project) }
+
+ it 'transits to scheduled' do
+ allow(Ci::BuildScheduleWorker).to receive(:perform_at)
+
+ subject
+
+ expect(build).to be_scheduled
+ end
+
+ it 'updates scheduled_at column' do
+ allow(Ci::BuildScheduleWorker).to receive(:perform_at)
+
+ subject
+
+ expect(build.scheduled_at).not_to be_nil
+ end
+
+ it 'schedules BuildScheduleWorker at the right time' do
+ Timecop.freeze do
+ expect(Ci::BuildScheduleWorker)
+ .to receive(:perform_at).with(be_like_time(1.minute.since), build.id)
+
+ subject
+ end
+ end
+ end
+
+ describe '#unschedule' do
+ subject { build.unschedule }
+
+ context 'when build is scheduled' do
+ let(:build) { create(:ci_build, :scheduled, pipeline: pipeline) }
+
+ it 'cleans scheduled_at column' do
+ subject
+
+ expect(build.scheduled_at).to be_nil
+ end
+
+ it 'transits to manual' do
+ subject
+
+ expect(build).to be_manual
+ end
+ end
+
+ context 'when build is not scheduled' do
+ let(:build) { create(:ci_build, :created, pipeline: pipeline) }
+
+ it 'does not transit status' do
+ subject
+
+ expect(build).to be_created
+ end
+ end
+ end
+
+ describe '#options_scheduled_at' do
+ subject { build.options_scheduled_at }
+
+ let(:build) { build_stubbed(:ci_build, options: option) }
+
+ context 'when start_in is 1 day' do
+ let(:option) { { start_in: '1 day' } }
+
+ it 'returns date after 1 day' do
+ Timecop.freeze do
+ is_expected.to eq(1.day.since)
+ end
+ end
+ end
+
+ context 'when start_in is 1 week' do
+ let(:option) { { start_in: '1 week' } }
+
+ it 'returns date after 1 week' do
+ Timecop.freeze do
+ is_expected.to eq(1.week.since)
+ end
+ end
+ end
+ end
+
+ describe '#enqueue_scheduled' do
+ subject { build.enqueue_scheduled }
+
+ context 'when build is scheduled and the right time has not come yet' do
+ let(:build) { create(:ci_build, :scheduled, pipeline: pipeline) }
+
+ it 'does not transits the status' do
+ subject
+
+ expect(build).to be_scheduled
+ end
+ end
+
+ context 'when build is scheduled and the right time has already come' do
+ let(:build) { create(:ci_build, :expired_scheduled, pipeline: pipeline) }
+
+ it 'cleans scheduled_at column' do
+ subject
+
+ expect(build.scheduled_at).to be_nil
+ end
+
+ it 'transits to pending' do
+ subject
+
+ expect(build).to be_pending
+ end
+ end
+ end
+
describe '#any_runners_online?' do
subject { build.any_runners_online? }
@@ -550,44 +685,22 @@ describe Ci::Build do
end
end
- describe '#has_test_reports?' do
- subject { build.has_test_reports? }
+ describe '#has_job_artifacts?' do
+ subject { build.has_job_artifacts? }
- context 'when build has a test report' do
- let(:build) { create(:ci_build, :test_reports) }
+ context 'when build has a job artifact' do
+ let(:build) { create(:ci_build, :artifacts) }
it { is_expected.to be_truthy }
end
- context 'when build does not have test reports' do
- let(:build) { create(:ci_build, :artifacts) }
+ context 'when build does not have job artifacts' do
+ let(:build) { create(:ci_build, :legacy_artifacts) }
it { is_expected.to be_falsy }
end
end
- describe '#erase_test_reports!' do
- subject { build.erase_test_reports! }
-
- context 'when build has a test report' do
- let!(:build) { create(:ci_build, :test_reports) }
-
- it 'removes a test report' do
- subject
-
- expect(build.has_test_reports?).to be_falsy
- end
- end
-
- context 'when build does not have test reports' do
- let!(:build) { create(:ci_build, :artifacts) }
-
- it 'does not erase anything' do
- expect { subject }.not_to change { Ci::JobArtifact.count }
- end
- end
- end
-
describe '#has_old_trace?' do
subject { build.has_old_trace? }
@@ -686,17 +799,100 @@ describe Ci::Build do
end
end
+ describe 'state transition as a deployable' do
+ let!(:build) { create(:ci_build, :start_review_app) }
+ let(:deployment) { build.deployment }
+ let(:environment) { deployment.environment }
+
+ it 'has deployments record with created status' do
+ expect(deployment).to be_created
+ expect(environment.name).to eq('review/master')
+ end
+
+ context 'when transits to running' do
+ before do
+ build.run!
+ end
+
+ it 'transits deployment status to running' do
+ expect(deployment).to be_running
+ end
+ end
+
+ context 'when transits to success' do
+ before do
+ allow(Deployments::SuccessWorker).to receive(:perform_async)
+ build.success!
+ end
+
+ it 'transits deployment status to success' do
+ expect(deployment).to be_success
+ end
+ end
+
+ context 'when transits to failed' do
+ before do
+ build.drop!
+ end
+
+ it 'transits deployment status to failed' do
+ expect(deployment).to be_failed
+ end
+ end
+
+ context 'when transits to skipped' do
+ before do
+ build.skip!
+ end
+
+ it 'transits deployment status to canceled' do
+ expect(deployment).to be_canceled
+ end
+ end
+
+ context 'when transits to canceled' do
+ before do
+ build.cancel!
+ end
+
+ it 'transits deployment status to canceled' do
+ expect(deployment).to be_canceled
+ end
+ end
+ end
+
+ describe '#on_stop' do
+ subject { build.on_stop }
+
+ context 'when a job has a specification that it can be stopped from the other job' do
+ let(:build) { create(:ci_build, :start_review_app) }
+
+ it 'returns the other job name' do
+ is_expected.to eq('stop_review_app')
+ end
+ end
+
+ context 'when a job does not have environment information' do
+ let(:build) { create(:ci_build) }
+
+ it 'returns nil' do
+ is_expected.to be_nil
+ end
+ end
+ end
+
describe 'deployment' do
- describe '#last_deployment' do
- subject { build.last_deployment }
+ describe '#has_deployment?' do
+ subject { build.has_deployment? }
- context 'when multiple deployments are created' do
- let!(:deployment1) { create(:deployment, deployable: build) }
- let!(:deployment2) { create(:deployment, deployable: build) }
+ context 'when build has a deployment' do
+ let!(:deployment) { create(:deployment, deployable: build) }
- it 'returns the latest one' do
- is_expected.to eq(deployment2)
- end
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when build does not have a deployment' do
+ it { is_expected.to be_falsy }
end
end
@@ -705,14 +901,14 @@ describe Ci::Build do
context 'when build succeeded' do
let(:build) { create(:ci_build, :success) }
- let!(:deployment) { create(:deployment, deployable: build) }
+ let!(:deployment) { create(:deployment, :success, deployable: build) }
context 'current deployment is latest' do
it { is_expected.to be_falsey }
end
context 'current deployment is not latest on environment' do
- let!(:deployment2) { create(:deployment, environment: deployment.environment) }
+ let!(:deployment2) { create(:deployment, :success, environment: deployment.environment) }
it { is_expected.to be_truthy }
end
@@ -850,8 +1046,8 @@ describe Ci::Build do
expect(build.artifacts_metadata.exists?).to be_falsy
end
- it 'removes test reports' do
- expect(build.job_artifacts.test_reports.count).to eq(0)
+ it 'removes all job_artifacts' do
+ expect(build.job_artifacts.count).to eq(0)
end
it 'erases build trace in trace file' do
@@ -1022,6 +1218,32 @@ describe Ci::Build do
end
end
+ describe '#erase_erasable_artifacts!' do
+ let!(:build) { create(:ci_build, :success) }
+
+ subject { build.erase_erasable_artifacts! }
+
+ before do
+ Ci::JobArtifact.file_types.keys.each do |file_type|
+ create(:ci_job_artifact, job: build, file_type: file_type, file_format: Ci::JobArtifact::TYPE_AND_FORMAT_PAIRS[file_type.to_sym])
+ end
+ end
+
+ it "erases erasable artifacts" do
+ subject
+
+ expect(build.job_artifacts.erasable).to be_empty
+ end
+
+ it "keeps non erasable artifacts" do
+ subject
+
+ Ci::JobArtifact::NON_ERASABLE_FILE_TYPES.each do |file_type|
+ expect(build.send("job_artifacts_#{file_type}")).not_to be_nil
+ end
+ end
+ end
+
describe '#first_pending' do
let!(:first) { create(:ci_build, pipeline: pipeline, status: 'pending', created_at: Date.yesterday) }
let!(:second) { create(:ci_build, pipeline: pipeline, status: 'pending') }
@@ -1175,6 +1397,14 @@ describe Ci::Build do
it { is_expected.not_to be_retryable }
end
+
+ context 'when build is degenerated' do
+ before do
+ build.degenerate!
+ end
+
+ it { is_expected.not_to be_retryable }
+ end
end
end
@@ -1191,6 +1421,12 @@ describe Ci::Build do
it { is_expected.to be_truthy }
end
+ context 'when is set to delayed' do
+ let(:value) { 'delayed' }
+
+ it { is_expected.to be_truthy }
+ end
+
context 'when set to something else' do
let(:value) { 'something else' }
@@ -1236,21 +1472,127 @@ describe Ci::Build do
end
describe '#retries_max' do
- context 'when max retries value is defined' do
- subject { create(:ci_build, options: { retry: 1 }) }
+ context 'with retries max config option' do
+ subject { create(:ci_build, options: { retry: { max: 1 } }) }
- it 'returns a number of configured max retries' do
+ it 'returns the number of configured max retries' do
expect(subject.retries_max).to eq 1
end
end
- context 'when max retries value is not defined' do
+ context 'without retries max config option' do
subject { create(:ci_build) }
it 'returns zero' do
expect(subject.retries_max).to eq 0
end
end
+
+ context 'when build is degenerated' do
+ subject { create(:ci_build, :degenerated) }
+
+ it 'returns zero' do
+ expect(subject.retries_max).to eq 0
+ end
+ end
+
+ context 'with integer only config option' do
+ subject { create(:ci_build, options: { retry: 1 }) }
+
+ it 'returns the number of configured max retries' do
+ expect(subject.retries_max).to eq 1
+ end
+ end
+ end
+
+ describe '#retry_when' do
+ context 'with retries when config option' do
+ subject { create(:ci_build, options: { retry: { when: ['some_reason'] } }) }
+
+ it 'returns the configured when' do
+ expect(subject.retry_when).to eq ['some_reason']
+ end
+ end
+
+ context 'without retries when config option' do
+ subject { create(:ci_build) }
+
+ it 'returns always array' do
+ expect(subject.retry_when).to eq ['always']
+ end
+ end
+
+ context 'with integer only config option' do
+ subject { create(:ci_build, options: { retry: 1 }) }
+
+ it 'returns always array' do
+ expect(subject.retry_when).to eq ['always']
+ end
+ end
+ end
+
+ describe '#retry_failure?' do
+ subject { create(:ci_build) }
+
+ context 'when retries max is zero' do
+ before do
+ expect(subject).to receive(:retries_max).at_least(:once).and_return(0)
+ end
+
+ it 'returns false' do
+ expect(subject.retry_failure?).to eq false
+ end
+ end
+
+ context 'when retries max equals retries count' do
+ before do
+ expect(subject).to receive(:retries_max).at_least(:once).and_return(1)
+ expect(subject).to receive(:retries_count).at_least(:once).and_return(1)
+ end
+
+ it 'returns false' do
+ expect(subject.retry_failure?).to eq false
+ end
+ end
+
+ context 'when retries max is higher than retries count' do
+ before do
+ expect(subject).to receive(:retries_max).at_least(:once).and_return(2)
+ expect(subject).to receive(:retries_count).at_least(:once).and_return(1)
+ end
+
+ context 'and retry when is always' do
+ before do
+ expect(subject).to receive(:retry_when).at_least(:once).and_return(['always'])
+ end
+
+ it 'returns true' do
+ expect(subject.retry_failure?).to eq true
+ end
+ end
+
+ context 'and retry when includes the failure_reason' do
+ before do
+ expect(subject).to receive(:failure_reason).at_least(:once).and_return('some_reason')
+ expect(subject).to receive(:retry_when).at_least(:once).and_return(['some_reason'])
+ end
+
+ it 'returns true' do
+ expect(subject.retry_failure?).to eq true
+ end
+ end
+
+ context 'and retry when does not include failure_reason' do
+ before do
+ expect(subject).to receive(:failure_reason).at_least(:once).and_return('some_reason')
+ expect(subject).to receive(:retry_when).at_least(:once).and_return(['some', 'other failure'])
+ end
+
+ it 'returns false' do
+ expect(subject.retry_failure?).to eq false
+ end
+ end
+ end
end
end
@@ -1276,6 +1618,19 @@ describe Ci::Build do
end
end
+ describe '#artifacts_file_for_type' do
+ let(:build) { create(:ci_build, :artifacts) }
+ let(:file_type) { :archive }
+
+ subject { build.artifacts_file_for_type(file_type) }
+
+ it 'queries artifacts for type' do
+ expect(build).to receive_message_chain(:job_artifacts, :find_by).with(file_type: Ci::JobArtifact.file_types[file_type])
+
+ subject
+ end
+ end
+
describe '#merge_request' do
def create_mr(build, pipeline, factory: :merge_request, created_at: Time.now)
create(factory, source_project: pipeline.project,
@@ -1353,11 +1708,11 @@ describe Ci::Build do
end
end
- describe '#other_actions' do
+ describe '#other_manual_actions' do
let(:build) { create(:ci_build, :manual, pipeline: pipeline) }
let!(:other_build) { create(:ci_build, :manual, pipeline: pipeline, name: 'other action') }
- subject { build.other_actions }
+ subject { build.other_manual_actions }
before do
project.add_developer(user)
@@ -1388,6 +1743,48 @@ describe Ci::Build do
end
end
+ describe '#other_scheduled_actions' do
+ let(:build) { create(:ci_build, :scheduled, pipeline: pipeline) }
+
+ subject { build.other_scheduled_actions }
+
+ before do
+ project.add_developer(user)
+ end
+
+ context "when other build's status is success" do
+ let!(:other_build) { create(:ci_build, :schedulable, :success, pipeline: pipeline, name: 'other action') }
+
+ it 'returns other actions' do
+ is_expected.to contain_exactly(other_build)
+ end
+ end
+
+ context "when other build's status is failed" do
+ let!(:other_build) { create(:ci_build, :schedulable, :failed, pipeline: pipeline, name: 'other action') }
+
+ it 'returns other actions' do
+ is_expected.to contain_exactly(other_build)
+ end
+ end
+
+ context "when other build's status is running" do
+ let!(:other_build) { create(:ci_build, :schedulable, :running, pipeline: pipeline, name: 'other action') }
+
+ it 'does not return other actions' do
+ is_expected.to be_empty
+ end
+ end
+
+ context "when other build's status is scheduled" do
+ let!(:other_build) { create(:ci_build, :scheduled, pipeline: pipeline, name: 'other action') }
+
+ it 'does not return other actions' do
+ is_expected.to contain_exactly(other_build)
+ end
+ end
+ end
+
describe '#persisted_environment' do
let!(:environment) do
create(:environment, project: project, name: "foo-#{project.default_branch}")
@@ -1459,6 +1856,18 @@ describe Ci::Build do
it { is_expected.to be_playable }
end
+
+ context 'when build is a manual and degenerated' do
+ subject { build_stubbed(:ci_build, :manual, :degenerated, status: :manual) }
+
+ it { is_expected.not_to be_playable }
+ end
+ end
+
+ context 'when build is scheduled' do
+ subject { build_stubbed(:ci_build, :scheduled) }
+
+ it { is_expected.to be_playable }
end
context 'when build is not a manual action' do
@@ -1519,12 +1928,26 @@ describe Ci::Build do
describe '#repo_url' do
subject { build.repo_url }
- it { is_expected.to be_a(String) }
- it { is_expected.to end_with(".git") }
- it { is_expected.to start_with(project.web_url[0..6]) }
- it { is_expected.to include(build.token) }
- it { is_expected.to include('gitlab-ci-token') }
- it { is_expected.to include(project.web_url[7..-1]) }
+ context 'when token is set' do
+ before do
+ build.ensure_token
+ end
+
+ it { is_expected.to be_a(String) }
+ it { is_expected.to end_with(".git") }
+ it { is_expected.to start_with(project.web_url[0..6]) }
+ it { is_expected.to include(build.token) }
+ it { is_expected.to include('gitlab-ci-token') }
+ it { is_expected.to include(project.web_url[7..-1]) }
+ end
+
+ context 'when token is empty' do
+ before do
+ build.token = nil
+ end
+
+ it { is_expected.to be_nil}
+ end
end
describe '#stuck?' do
@@ -1634,7 +2057,8 @@ describe Ci::Build do
end
context 'use from gitlab-ci.yml' do
- let(:pipeline) { create(:ci_pipeline) }
+ let(:project) { create(:project, :repository) }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
before do
stub_ci_pipeline_yaml_file(config)
@@ -1676,51 +2100,6 @@ describe Ci::Build do
describe '#variables' do
let(:container_registry_enabled) { false }
- let(:predefined_variables) do
- [
- { key: 'CI_PIPELINE_ID', value: pipeline.id.to_s, public: true },
- { key: 'CI_PIPELINE_URL', value: project.web_url + "/pipelines/#{pipeline.id}", public: true },
- { key: 'CI_JOB_ID', value: build.id.to_s, public: true },
- { key: 'CI_JOB_URL', value: project.web_url + "/-/jobs/#{build.id}", public: true },
- { key: 'CI_JOB_TOKEN', value: build.token, public: false },
- { key: 'CI_BUILD_ID', value: build.id.to_s, public: true },
- { key: 'CI_BUILD_TOKEN', value: build.token, public: false },
- { key: 'CI_REGISTRY_USER', value: 'gitlab-ci-token', public: true },
- { key: 'CI_REGISTRY_PASSWORD', value: build.token, public: false },
- { key: 'CI_REPOSITORY_URL', value: build.repo_url, public: false },
- { key: 'CI', value: 'true', public: true },
- { key: 'GITLAB_CI', value: 'true', public: true },
- { key: 'GITLAB_FEATURES', value: project.licensed_features.join(','), public: true },
- { key: 'CI_SERVER_NAME', value: 'GitLab', public: true },
- { key: 'CI_SERVER_VERSION', value: Gitlab::VERSION, public: true },
- { key: 'CI_SERVER_REVISION', value: Gitlab.revision, public: true },
- { key: 'CI_JOB_NAME', value: 'test', public: true },
- { key: 'CI_JOB_STAGE', value: 'test', public: true },
- { key: 'CI_COMMIT_SHA', value: build.sha, public: true },
- { key: 'CI_COMMIT_BEFORE_SHA', value: build.before_sha, public: true },
- { key: 'CI_COMMIT_REF_NAME', value: build.ref, public: true },
- { key: 'CI_COMMIT_REF_SLUG', value: build.ref_slug, public: true },
- { key: 'CI_BUILD_REF', value: build.sha, public: true },
- { key: 'CI_BUILD_BEFORE_SHA', value: build.before_sha, public: true },
- { key: 'CI_BUILD_REF_NAME', value: build.ref, public: true },
- { key: 'CI_BUILD_REF_SLUG', value: build.ref_slug, public: true },
- { key: 'CI_BUILD_NAME', value: 'test', public: true },
- { key: 'CI_BUILD_STAGE', value: 'test', public: true },
- { key: 'CI_PROJECT_ID', value: project.id.to_s, public: true },
- { key: 'CI_PROJECT_NAME', value: project.path, public: true },
- { key: 'CI_PROJECT_PATH', value: project.full_path, public: true },
- { key: 'CI_PROJECT_PATH_SLUG', value: project.full_path_slug, public: true },
- { key: 'CI_PROJECT_NAMESPACE', value: project.namespace.full_path, public: true },
- { key: 'CI_PROJECT_URL', value: project.web_url, public: true },
- { key: 'CI_PROJECT_VISIBILITY', value: 'private', public: true },
- { key: 'CI_PIPELINE_IID', value: pipeline.iid.to_s, public: true },
- { key: 'CI_CONFIG_PATH', value: pipeline.ci_yaml_file_path, public: true },
- { key: 'CI_PIPELINE_SOURCE', value: pipeline.source, public: true },
- { key: 'CI_COMMIT_MESSAGE', value: pipeline.git_commit_message, public: true },
- { key: 'CI_COMMIT_TITLE', value: pipeline.git_commit_title, public: true },
- { key: 'CI_COMMIT_DESCRIPTION', value: pipeline.git_commit_description, public: true }
- ]
- end
before do
stub_container_registry_config(enabled: container_registry_enabled, host_port: 'registry.example.com')
@@ -1729,11 +2108,174 @@ describe Ci::Build do
subject { build.variables }
context 'returns variables' do
+ let(:predefined_variables) do
+ [
+ { key: 'CI_PIPELINE_ID', value: pipeline.id.to_s, public: true },
+ { key: 'CI_PIPELINE_URL', value: project.web_url + "/pipelines/#{pipeline.id}", public: true },
+ { key: 'CI_JOB_ID', value: build.id.to_s, public: true },
+ { key: 'CI_JOB_URL', value: project.web_url + "/-/jobs/#{build.id}", public: true },
+ { key: 'CI_JOB_TOKEN', value: 'my-token', public: false },
+ { key: 'CI_BUILD_ID', value: build.id.to_s, public: true },
+ { key: 'CI_BUILD_TOKEN', value: 'my-token', public: false },
+ { key: 'CI_REGISTRY_USER', value: 'gitlab-ci-token', public: true },
+ { key: 'CI_REGISTRY_PASSWORD', value: 'my-token', public: false },
+ { key: 'CI_REPOSITORY_URL', value: build.repo_url, public: false },
+ { key: 'CI', value: 'true', public: true },
+ { key: 'GITLAB_CI', value: 'true', public: true },
+ { key: 'GITLAB_FEATURES', value: project.licensed_features.join(','), public: true },
+ { key: 'CI_SERVER_NAME', value: 'GitLab', public: true },
+ { key: 'CI_SERVER_VERSION', value: Gitlab::VERSION, public: true },
+ { key: 'CI_SERVER_VERSION_MAJOR', value: Gitlab.version_info.major.to_s, public: true },
+ { key: 'CI_SERVER_VERSION_MINOR', value: Gitlab.version_info.minor.to_s, public: true },
+ { key: 'CI_SERVER_VERSION_PATCH', value: Gitlab.version_info.patch.to_s, public: true },
+ { key: 'CI_SERVER_REVISION', value: Gitlab.revision, public: true },
+ { key: 'CI_JOB_NAME', value: 'test', public: true },
+ { key: 'CI_JOB_STAGE', value: 'test', public: true },
+ { key: 'CI_COMMIT_SHA', value: build.sha, public: true },
+ { key: 'CI_COMMIT_BEFORE_SHA', value: build.before_sha, public: true },
+ { key: 'CI_COMMIT_REF_NAME', value: build.ref, public: true },
+ { key: 'CI_COMMIT_REF_SLUG', value: build.ref_slug, public: true },
+ { key: 'CI_NODE_TOTAL', value: '1', public: true },
+ { key: 'CI_BUILD_REF', value: build.sha, public: true },
+ { key: 'CI_BUILD_BEFORE_SHA', value: build.before_sha, public: true },
+ { key: 'CI_BUILD_REF_NAME', value: build.ref, public: true },
+ { key: 'CI_BUILD_REF_SLUG', value: build.ref_slug, public: true },
+ { key: 'CI_BUILD_NAME', value: 'test', public: true },
+ { key: 'CI_BUILD_STAGE', value: 'test', public: true },
+ { key: 'CI_PROJECT_ID', value: project.id.to_s, public: true },
+ { key: 'CI_PROJECT_NAME', value: project.path, public: true },
+ { key: 'CI_PROJECT_PATH', value: project.full_path, public: true },
+ { key: 'CI_PROJECT_PATH_SLUG', value: project.full_path_slug, public: true },
+ { key: 'CI_PROJECT_NAMESPACE', value: project.namespace.full_path, public: true },
+ { key: 'CI_PROJECT_URL', value: project.web_url, public: true },
+ { key: 'CI_PROJECT_VISIBILITY', value: 'private', public: true },
+ { key: 'CI_PIPELINE_IID', value: pipeline.iid.to_s, public: true },
+ { key: 'CI_CONFIG_PATH', value: pipeline.ci_yaml_file_path, public: true },
+ { key: 'CI_PIPELINE_SOURCE', value: pipeline.source, public: true },
+ { key: 'CI_COMMIT_MESSAGE', value: pipeline.git_commit_message, public: true },
+ { key: 'CI_COMMIT_TITLE', value: pipeline.git_commit_title, public: true },
+ { key: 'CI_COMMIT_DESCRIPTION', value: pipeline.git_commit_description, public: true }
+ ]
+ end
+
before do
+ build.token = 'my-token'
build.yaml_variables = []
end
it { is_expected.to include(*predefined_variables) }
+
+ context 'when yaml variables are undefined' do
+ let(:pipeline) do
+ create(:ci_pipeline, project: project,
+ sha: project.commit.id,
+ ref: project.default_branch)
+ end
+
+ before do
+ build.yaml_variables = nil
+ end
+
+ context 'use from gitlab-ci.yml' do
+ before do
+ stub_ci_pipeline_yaml_file(config)
+ end
+
+ context 'when config is not found' do
+ let(:config) { nil }
+
+ it { is_expected.to include(*predefined_variables) }
+ end
+
+ context 'when config does not have a questioned job' do
+ let(:config) do
+ YAML.dump({
+ test_other: {
+ script: 'Hello World'
+ }
+ })
+ end
+
+ it { is_expected.to include(*predefined_variables) }
+ end
+
+ context 'when config has variables' do
+ let(:config) do
+ YAML.dump({
+ test: {
+ script: 'Hello World',
+ variables: {
+ KEY: 'value'
+ }
+ }
+ })
+ end
+
+ let(:variables) do
+ [{ key: 'KEY', value: 'value', public: true }]
+ end
+
+ it { is_expected.to include(*predefined_variables) }
+ it { is_expected.to include(*variables) }
+ end
+ end
+ end
+
+ describe 'variables ordering' do
+ context 'when variables hierarchy is stubbed' do
+ let(:build_pre_var) { { key: 'build', value: 'value', public: true } }
+ let(:project_pre_var) { { key: 'project', value: 'value', public: true } }
+ let(:pipeline_pre_var) { { key: 'pipeline', value: 'value', public: true } }
+ let(:build_yaml_var) { { key: 'yaml', value: 'value', public: true } }
+
+ before do
+ allow(build).to receive(:predefined_variables) { [build_pre_var] }
+ allow(build).to receive(:yaml_variables) { [build_yaml_var] }
+ allow(build).to receive(:persisted_variables) { [] }
+
+ allow_any_instance_of(Project)
+ .to receive(:predefined_variables) { [project_pre_var] }
+
+ project.variables.create!(key: 'secret', value: 'value')
+
+ allow_any_instance_of(Ci::Pipeline)
+ .to receive(:predefined_variables) { [pipeline_pre_var] }
+ end
+
+ it 'returns variables in order depending on resource hierarchy' do
+ is_expected.to eq(
+ [build_pre_var,
+ project_pre_var,
+ pipeline_pre_var,
+ build_yaml_var,
+ { key: 'secret', value: 'value', public: false }])
+ end
+ end
+
+ context 'when build has environment and user-provided variables' do
+ let(:expected_variables) do
+ predefined_variables.map { |variable| variable.fetch(:key) } +
+ %w[YAML_VARIABLE CI_ENVIRONMENT_NAME CI_ENVIRONMENT_SLUG
+ CI_ENVIRONMENT_URL]
+ end
+
+ before do
+ create(:environment, project: build.project,
+ name: 'staging')
+
+ build.yaml_variables = [{ key: 'YAML_VARIABLE',
+ value: 'var',
+ public: true }]
+ build.environment = 'staging'
+ end
+
+ it 'matches explicit variables ordering' do
+ received_variables = subject.map { |variable| variable.fetch(:key) }
+
+ expect(received_variables).to eq expected_variables
+ end
+ end
+ end
end
context 'when build has user' do
@@ -1847,17 +2389,17 @@ describe Ci::Build do
it { is_expected.to include(tag_variable) }
end
- context 'when secret variable is defined' do
- let(:secret_variable) do
+ context 'when CI variable is defined' do
+ let(:ci_variable) do
{ key: 'SECRET_KEY', value: 'secret_value', public: false }
end
before do
create(:ci_variable,
- secret_variable.slice(:key, :value).merge(project: project))
+ ci_variable.slice(:key, :value).merge(project: project))
end
- it { is_expected.to include(secret_variable) }
+ it { is_expected.to include(ci_variable) }
end
context 'when protected variable is defined' do
@@ -1892,17 +2434,17 @@ describe Ci::Build do
end
end
- context 'when group secret variable is defined' do
- let(:secret_variable) do
+ context 'when group CI variable is defined' do
+ let(:ci_variable) do
{ key: 'SECRET_KEY', value: 'secret_value', public: false }
end
before do
create(:ci_group_variable,
- secret_variable.slice(:key, :value).merge(group: group))
+ ci_variable.slice(:key, :value).merge(group: group))
end
- it { is_expected.to include(secret_variable) }
+ it { is_expected.to include(ci_variable) }
end
context 'when group protected variable is defined' do
@@ -1995,75 +2537,20 @@ describe Ci::Build do
end
before do
- pipeline_schedule.pipelines << pipeline
+ pipeline_schedule.pipelines << pipeline.reload
pipeline_schedule.reload
end
it { is_expected.to include(pipeline_schedule_variable.to_runner_variable) }
end
- context 'when yaml_variables are undefined' do
- let(:pipeline) do
- create(:ci_pipeline, project: project,
- sha: project.commit.id,
- ref: project.default_branch)
- end
-
- before do
- build.yaml_variables = nil
- end
-
- context 'use from gitlab-ci.yml' do
- before do
- stub_ci_pipeline_yaml_file(config)
- end
-
- context 'when config is not found' do
- let(:config) { nil }
-
- it { is_expected.to include(*predefined_variables) }
- end
-
- context 'when config does not have a questioned job' do
- let(:config) do
- YAML.dump({
- test_other: {
- script: 'Hello World'
- }
- })
- end
-
- it { is_expected.to include(*predefined_variables) }
- end
-
- context 'when config has variables' do
- let(:config) do
- YAML.dump({
- test: {
- script: 'Hello World',
- variables: {
- KEY: 'value'
- }
- }
- })
- end
- let(:variables) do
- [{ key: 'KEY', value: 'value', public: true }]
- end
-
- it { is_expected.to include(*predefined_variables) }
- it { is_expected.to include(*variables) }
- end
- end
- end
-
context 'when container registry is enabled' do
let(:container_registry_enabled) { true }
let(:ci_registry) do
- { key: 'CI_REGISTRY', value: 'registry.example.com', public: true }
+ { key: 'CI_REGISTRY', value: 'registry.example.com', public: true }
end
let(:ci_registry_image) do
- { key: 'CI_REGISTRY_IMAGE', value: project.container_registry_url, public: true }
+ { key: 'CI_REGISTRY_IMAGE', value: project.container_registry_url, public: true }
end
context 'and is disabled for project' do
@@ -2161,63 +2648,26 @@ describe Ci::Build do
end
end
- describe 'variables ordering' do
- context 'when variables hierarchy is stubbed' do
- let(:build_pre_var) { { key: 'build', value: 'value', public: true } }
- let(:project_pre_var) { { key: 'project', value: 'value', public: true } }
- let(:pipeline_pre_var) { { key: 'pipeline', value: 'value', public: true } }
- let(:build_yaml_var) { { key: 'yaml', value: 'value', public: true } }
+ context 'when build is parallelized' do
+ let(:total) { 5 }
+ let(:index) { 3 }
- before do
- allow(build).to receive(:predefined_variables) { [build_pre_var] }
- allow(build).to receive(:yaml_variables) { [build_yaml_var] }
- allow(build).to receive(:persisted_variables) { [] }
-
- allow_any_instance_of(Project)
- .to receive(:predefined_variables) { [project_pre_var] }
-
- allow_any_instance_of(Project)
- .to receive(:secret_variables_for)
- .with(ref: 'master', environment: nil) do
- [create(:ci_variable, key: 'secret', value: 'value')]
- end
-
- allow_any_instance_of(Ci::Pipeline)
- .to receive(:predefined_variables) { [pipeline_pre_var] }
- end
-
- it 'returns variables in order depending on resource hierarchy' do
- is_expected.to eq(
- [build_pre_var,
- project_pre_var,
- pipeline_pre_var,
- build_yaml_var,
- { key: 'secret', value: 'value', public: false }])
- end
+ before do
+ build.options[:parallel] = total
+ build.options[:instance] = index
+ build.name = "#{build.name} #{index}/#{total}"
end
- context 'when build has environment and user-provided variables' do
- let(:expected_variables) do
- predefined_variables.map { |variable| variable.fetch(:key) } +
- %w[YAML_VARIABLE CI_ENVIRONMENT_NAME CI_ENVIRONMENT_SLUG
- CI_ENVIRONMENT_URL]
- end
-
- before do
- create(:environment, project: build.project,
- name: 'staging')
-
- build.yaml_variables = [{ key: 'YAML_VARIABLE',
- value: 'var',
- public: true }]
- build.environment = 'staging'
- end
-
- it 'matches explicit variables ordering' do
- received_variables = subject.map { |variable| variable.fetch(:key) }
+ it 'includes CI_NODE_INDEX' do
+ is_expected.to include(
+ { key: 'CI_NODE_INDEX', value: index.to_s, public: true }
+ )
+ end
- expect(received_variables).to eq expected_variables
- end
+ it 'includes correct CI_NODE_TOTAL' do
+ is_expected.to include(
+ { key: 'CI_NODE_TOTAL', value: total.to_s, public: true }
+ )
end
end
@@ -2328,7 +2778,7 @@ describe Ci::Build do
end
describe '#scoped_variables_hash' do
- context 'when overriding secret variables' do
+ context 'when overriding CI variables' do
before do
project.variables.create!(key: 'MY_VAR', value: 'my value 1')
pipeline.variables.create!(key: 'MY_VAR', value: 'my value 2')
@@ -2548,7 +2998,7 @@ describe Ci::Build do
end
context 'when build is configured to be retried' do
- subject { create(:ci_build, :running, options: { retry: 3 }, project: project, user: user) }
+ subject { create(:ci_build, :running, options: { retry: { max: 3 } }, project: project, user: user) }
it 'retries build and assigns the same user to it' do
expect(described_class).to receive(:retry)
@@ -2844,16 +3294,10 @@ describe Ci::Build do
end
it 'raises an error' do
- expect { subject }.to raise_error(Gitlab::Ci::Parsers::Junit::JunitParserError)
+ expect { subject }.to raise_error(Gitlab::Ci::Parsers::Test::Junit::JunitParserError)
end
end
end
-
- context 'when build does not have test reports' do
- it 'raises an error' do
- expect { subject }.to raise_error(NoMethodError)
- end
- end
end
describe '#artifacts_metadata_entry' do
@@ -2983,10 +3427,14 @@ describe Ci::Build do
end
describe '#deployment_status' do
+ before do
+ allow_any_instance_of(described_class).to receive(:create_deployment)
+ end
+
context 'when build is a last deployment' do
let(:build) { create(:ci_build, :success, environment: 'production') }
let(:environment) { create(:environment, name: 'production', project: build.project) }
- let!(:deployment) { create(:deployment, environment: environment, project: environment.project, deployable: build) }
+ let!(:deployment) { create(:deployment, :success, environment: environment, project: environment.project, deployable: build) }
it { expect(build.deployment_status).to eq(:last) }
end
@@ -2994,8 +3442,8 @@ describe Ci::Build do
context 'when there is a newer build with deployment' do
let(:build) { create(:ci_build, :success, environment: 'production') }
let(:environment) { create(:environment, name: 'production', project: build.project) }
- let!(:deployment) { create(:deployment, environment: environment, project: environment.project, deployable: build) }
- let!(:last_deployment) { create(:deployment, environment: environment, project: environment.project) }
+ let!(:deployment) { create(:deployment, :success, environment: environment, project: environment.project, deployable: build) }
+ let!(:last_deployment) { create(:deployment, :success, environment: environment, project: environment.project) }
it { expect(build.deployment_status).to eq(:out_of_date) }
end
@@ -3003,7 +3451,7 @@ describe Ci::Build do
context 'when build with deployment has failed' do
let(:build) { create(:ci_build, :failed, environment: 'production') }
let(:environment) { create(:environment, name: 'production', project: build.project) }
- let!(:deployment) { create(:deployment, environment: environment, project: environment.project, deployable: build) }
+ let!(:deployment) { create(:deployment, :success, environment: environment, project: environment.project, deployable: build) }
it { expect(build.deployment_status).to eq(:failed) }
end
@@ -3011,16 +3459,59 @@ describe Ci::Build do
context 'when build with deployment is running' do
let(:build) { create(:ci_build, environment: 'production') }
let(:environment) { create(:environment, name: 'production', project: build.project) }
- let!(:deployment) { create(:deployment, environment: environment, project: environment.project, deployable: build) }
+ let!(:deployment) { create(:deployment, :success, environment: environment, project: environment.project, deployable: build) }
it { expect(build.deployment_status).to eq(:creating) }
end
+ end
+
+ describe '#degenerated?' do
+ context 'when build is degenerated' do
+ subject { create(:ci_build, :degenerated) }
+
+ it { is_expected.to be_degenerated }
+ end
- context 'when build is successful but deployment is not ready yet' do
- let(:build) { create(:ci_build, :success, environment: 'production') }
- let(:environment) { create(:environment, name: 'production', project: build.project) }
+ context 'when build is valid' do
+ subject { create(:ci_build) }
- it { expect(build.deployment_status).to eq(:creating) }
+ it { is_expected.not_to be_degenerated }
+
+ context 'and becomes degenerated' do
+ before do
+ subject.degenerate!
+ end
+
+ it { is_expected.to be_degenerated }
+ end
+ end
+ end
+
+ describe '#archived?' do
+ context 'when build is degenerated' do
+ subject { create(:ci_build, :degenerated) }
+
+ it { is_expected.to be_archived }
+ end
+
+ context 'for old build' do
+ subject { create(:ci_build, created_at: 1.day.ago) }
+
+ context 'when archive_builds_in is set' do
+ before do
+ stub_application_setting(archive_builds_in_seconds: 3600)
+ end
+
+ it { is_expected.to be_archived }
+ end
+
+ context 'when archive_builds_in is not set' do
+ before do
+ stub_application_setting(archive_builds_in_seconds: nil)
+ end
+
+ it { is_expected.not_to be_archived }
+ end
end
end
end
diff --git a/spec/models/ci/build_trace_chunk_spec.rb b/spec/models/ci/build_trace_chunk_spec.rb
index 915bf134d57..d214fdf369a 100644
--- a/spec/models/ci/build_trace_chunk_spec.rb
+++ b/spec/models/ci/build_trace_chunk_spec.rb
@@ -12,6 +12,8 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
described_class.new(build: build, chunk_index: chunk_index, data_store: data_store, raw_data: raw_data)
end
+ it_behaves_like 'having unique enum values'
+
before do
stub_feature_flags(ci_enable_live_trace: true)
stub_artifacts_object_storage
@@ -45,11 +47,11 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
is_expected.to eq(%w[redis database fog])
end
- it 'returns redis store as the the lowest precedence' do
+ it 'returns redis store as the lowest precedence' do
expect(subject.first).to eq('redis')
end
- it 'returns fog store as the the highest precedence' do
+ it 'returns fog store as the highest precedence' do
expect(subject.last).to eq('fog')
end
end
@@ -436,32 +438,47 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
let(:data_store) { :redis }
context 'when data exists' do
- let(:data) { 'Sample data in redis' }
-
before do
build_trace_chunk.send(:unsafe_set_data!, data)
end
- it 'persists the data' do
- expect(build_trace_chunk.redis?).to be_truthy
- expect(Ci::BuildTraceChunks::Redis.new.data(build_trace_chunk)).to eq(data)
- expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil
- expect { Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk) }.to raise_error(Excon::Error::NotFound)
+ context 'when data size reached CHUNK_SIZE' do
+ let(:data) { 'a' * described_class::CHUNK_SIZE }
- subject
+ it 'persists the data' do
+ expect(build_trace_chunk.redis?).to be_truthy
+ expect(Ci::BuildTraceChunks::Redis.new.data(build_trace_chunk)).to eq(data)
+ expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil
+ expect { Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk) }.to raise_error(Excon::Error::NotFound)
+
+ subject
+
+ expect(build_trace_chunk.fog?).to be_truthy
+ expect(Ci::BuildTraceChunks::Redis.new.data(build_trace_chunk)).to be_nil
+ expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil
+ expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data)
+ end
- expect(build_trace_chunk.fog?).to be_truthy
- expect(Ci::BuildTraceChunks::Redis.new.data(build_trace_chunk)).to be_nil
- expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil
- expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data)
+ it_behaves_like 'Atomic operation'
end
- it_behaves_like 'Atomic operation'
+ context 'when data size has not reached CHUNK_SIZE' do
+ let(:data) { 'Sample data in redis' }
+
+ it 'does not persist the data and the orignal data is intact' do
+ expect { subject }.to raise_error(described_class::FailedToPersistDataError)
+
+ expect(build_trace_chunk.redis?).to be_truthy
+ expect(Ci::BuildTraceChunks::Redis.new.data(build_trace_chunk)).to eq(data)
+ expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil
+ expect { Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk) }.to raise_error(Excon::Error::NotFound)
+ end
+ end
end
context 'when data does not exist' do
it 'does not persist' do
- expect { subject }.to raise_error('Can not persist empty data')
+ expect { subject }.to raise_error(described_class::FailedToPersistDataError)
end
end
end
@@ -470,32 +487,47 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
let(:data_store) { :database }
context 'when data exists' do
- let(:data) { 'Sample data in database' }
-
before do
build_trace_chunk.send(:unsafe_set_data!, data)
end
- it 'persists the data' do
- expect(build_trace_chunk.database?).to be_truthy
- expect(Ci::BuildTraceChunks::Redis.new.data(build_trace_chunk)).to be_nil
- expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to eq(data)
- expect { Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk) }.to raise_error(Excon::Error::NotFound)
+ context 'when data size reached CHUNK_SIZE' do
+ let(:data) { 'a' * described_class::CHUNK_SIZE }
- subject
+ it 'persists the data' do
+ expect(build_trace_chunk.database?).to be_truthy
+ expect(Ci::BuildTraceChunks::Redis.new.data(build_trace_chunk)).to be_nil
+ expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to eq(data)
+ expect { Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk) }.to raise_error(Excon::Error::NotFound)
+
+ subject
+
+ expect(build_trace_chunk.fog?).to be_truthy
+ expect(Ci::BuildTraceChunks::Redis.new.data(build_trace_chunk)).to be_nil
+ expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil
+ expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data)
+ end
- expect(build_trace_chunk.fog?).to be_truthy
- expect(Ci::BuildTraceChunks::Redis.new.data(build_trace_chunk)).to be_nil
- expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil
- expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data)
+ it_behaves_like 'Atomic operation'
end
- it_behaves_like 'Atomic operation'
+ context 'when data size has not reached CHUNK_SIZE' do
+ let(:data) { 'Sample data in database' }
+
+ it 'does not persist the data and the orignal data is intact' do
+ expect { subject }.to raise_error(described_class::FailedToPersistDataError)
+
+ expect(build_trace_chunk.database?).to be_truthy
+ expect(Ci::BuildTraceChunks::Redis.new.data(build_trace_chunk)).to be_nil
+ expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to eq(data)
+ expect { Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk) }.to raise_error(Excon::Error::NotFound)
+ end
+ end
end
context 'when data does not exist' do
it 'does not persist' do
- expect { subject }.to raise_error('Can not persist empty data')
+ expect { subject }.to raise_error(described_class::FailedToPersistDataError)
end
end
end
@@ -504,27 +536,37 @@ describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
let(:data_store) { :fog }
context 'when data exists' do
- let(:data) { 'Sample data in fog' }
-
before do
build_trace_chunk.send(:unsafe_set_data!, data)
end
- it 'does not change data store' do
- expect(build_trace_chunk.fog?).to be_truthy
- expect(Ci::BuildTraceChunks::Redis.new.data(build_trace_chunk)).to be_nil
- expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil
- expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data)
+ context 'when data size reached CHUNK_SIZE' do
+ let(:data) { 'a' * described_class::CHUNK_SIZE }
- subject
+ it 'does not change data store' do
+ expect(build_trace_chunk.fog?).to be_truthy
+ expect(Ci::BuildTraceChunks::Redis.new.data(build_trace_chunk)).to be_nil
+ expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil
+ expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data)
+
+ subject
- expect(build_trace_chunk.fog?).to be_truthy
- expect(Ci::BuildTraceChunks::Redis.new.data(build_trace_chunk)).to be_nil
- expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil
- expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data)
+ expect(build_trace_chunk.fog?).to be_truthy
+ expect(Ci::BuildTraceChunks::Redis.new.data(build_trace_chunk)).to be_nil
+ expect(Ci::BuildTraceChunks::Database.new.data(build_trace_chunk)).to be_nil
+ expect(Ci::BuildTraceChunks::Fog.new.data(build_trace_chunk)).to eq(data)
+ end
+
+ it_behaves_like 'Atomic operation'
end
- it_behaves_like 'Atomic operation'
+ context 'when data size has not reached CHUNK_SIZE' do
+ let(:data) { 'Sample data in fog' }
+
+ it 'does not raise error' do
+ expect { subject }.not_to raise_error
+ end
+ end
end
end
end
diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb
index 1bf338f4c70..c68ba02b8de 100644
--- a/spec/models/ci/job_artifact_spec.rb
+++ b/spec/models/ci/job_artifact_spec.rb
@@ -15,6 +15,8 @@ describe Ci::JobArtifact do
it { is_expected.to delegate_method(:open).to(:file) }
it { is_expected.to delegate_method(:exists?).to(:file) }
+ it_behaves_like 'having unique enum values'
+
describe '.test_reports' do
subject { described_class.test_reports }
@@ -31,6 +33,22 @@ describe Ci::JobArtifact do
end
end
+ describe '.erasable' do
+ subject { described_class.erasable }
+
+ context 'when there is an erasable artifact' do
+ let!(:artifact) { create(:ci_job_artifact, :junit) }
+
+ it { is_expected.to eq([artifact]) }
+ end
+
+ context 'when there are no erasable artifacts' do
+ let!(:artifact) { create(:ci_job_artifact, :trace) }
+
+ it { is_expected.to be_empty }
+ end
+ end
+
describe 'callbacks' do
subject { create(:ci_job_artifact, :archive) }
@@ -106,34 +124,46 @@ describe Ci::JobArtifact do
describe 'validates file format' do
subject { artifact }
- context 'when archive type with zip format' do
- let(:artifact) { build(:ci_job_artifact, :archive, file_format: :zip) }
+ described_class::TYPE_AND_FORMAT_PAIRS.except(:trace).each do |file_type, file_format|
+ context "when #{file_type} type with #{file_format} format" do
+ let(:artifact) { build(:ci_job_artifact, file_type: file_type, file_format: file_format) }
- it { is_expected.to be_valid }
- end
+ it { is_expected.to be_valid }
+ end
- context 'when archive type with gzip format' do
- let(:artifact) { build(:ci_job_artifact, :archive, file_format: :gzip) }
+ context "when #{file_type} type without format specification" do
+ let(:artifact) { build(:ci_job_artifact, file_type: file_type, file_format: nil) }
- it { is_expected.not_to be_valid }
- end
+ it { is_expected.not_to be_valid }
+ end
- context 'when archive type without format specification' do
- let(:artifact) { build(:ci_job_artifact, :archive, file_format: nil) }
+ context "when #{file_type} type with other formats" do
+ described_class.file_formats.except(file_format).values.each do |other_format|
+ let(:artifact) { build(:ci_job_artifact, file_type: file_type, file_format: other_format) }
- it { is_expected.not_to be_valid }
+ it { is_expected.not_to be_valid }
+ end
+ end
end
+ end
- context 'when junit type with zip format' do
- let(:artifact) { build(:ci_job_artifact, :junit, file_format: :zip) }
+ describe 'validates DEFAULT_FILE_NAMES' do
+ subject { described_class::DEFAULT_FILE_NAMES }
- it { is_expected.not_to be_valid }
+ described_class.file_types.each do |file_type, _|
+ it "expects #{file_type} to be included" do
+ is_expected.to include(file_type.to_sym)
+ end
end
+ end
- context 'when junit type with gzip format' do
- let(:artifact) { build(:ci_job_artifact, :junit, file_format: :gzip) }
+ describe 'validates TYPE_AND_FORMAT_PAIRS' do
+ subject { described_class::TYPE_AND_FORMAT_PAIRS }
- it { is_expected.to be_valid }
+ described_class.file_types.each do |file_type, _|
+ it "expects #{file_type} to be included" do
+ expect(described_class.file_formats).to include(subject[file_type.to_sym])
+ end
end
end
@@ -166,6 +196,14 @@ describe Ci::JobArtifact do
end
end
+ context 'when file format is raw' do
+ let(:artifact) { build(:ci_job_artifact, :codequality, file_format: :raw) }
+
+ it 'iterates blob once' do
+ expect { |b| artifact.each_blob(&b) }.to yield_control.once
+ end
+ end
+
context 'when there are no adapters for the file format' do
let(:artifact) { build(:ci_job_artifact, :junit, file_format: :zip) }
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 4755702c0e9..3fe351e78d5 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -8,6 +8,8 @@ describe Ci::Pipeline, :mailer do
create(:ci_empty_pipeline, status: :created, project: project)
end
+ it_behaves_like 'having unique enum values'
+
it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:user) }
it { is_expected.to belong_to(:auto_canceled_by) }
@@ -75,6 +77,18 @@ describe Ci::Pipeline, :mailer do
end
end
+ describe '#delay' do
+ subject { pipeline.delay }
+
+ let(:pipeline) { build(:ci_pipeline, status: :created) }
+
+ it 'changes pipeline status to schedule' do
+ subject
+
+ expect(pipeline).to be_scheduled
+ end
+ end
+
describe '#valid_commit_sha' do
context 'commit.sha can not start with 00000000' do
before do
@@ -767,6 +781,41 @@ describe Ci::Pipeline, :mailer do
end
end
+ describe 'ref_exists?' do
+ context 'when repository exists' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:project) { create(:project, :repository) }
+
+ where(:tag, :ref, :result) do
+ false | 'master' | true
+ false | 'non-existent-branch' | false
+ true | 'v1.1.0' | true
+ true | 'non-existent-tag' | false
+ end
+
+ with_them do
+ let(:pipeline) do
+ create(:ci_empty_pipeline, project: project, tag: tag, ref: ref)
+ end
+
+ it "correctly detects ref" do
+ expect(pipeline.ref_exists?).to be result
+ end
+ end
+ end
+
+ context 'when repository does not exist' do
+ let(:pipeline) do
+ create(:ci_empty_pipeline, project: project, ref: 'master')
+ end
+
+ it 'always returns false' do
+ expect(pipeline.ref_exists?).to eq false
+ end
+ end
+ end
+
context 'with non-empty project' do
let(:project) { create(:project, :repository) }
@@ -825,6 +874,57 @@ describe Ci::Pipeline, :mailer do
end
end
+ describe '#branch_updated?' do
+ context 'when pipeline has before SHA' do
+ before do
+ pipeline.update_column(:before_sha, 'a1b2c3d4')
+ end
+
+ it 'runs on a branch update push' do
+ expect(pipeline.before_sha).not_to be Gitlab::Git::BLANK_SHA
+ expect(pipeline.branch_updated?).to be true
+ end
+ end
+
+ context 'when pipeline does not have before SHA' do
+ before do
+ pipeline.update_column(:before_sha, Gitlab::Git::BLANK_SHA)
+ end
+
+ it 'does not run on a branch updating push' do
+ expect(pipeline.branch_updated?).to be false
+ end
+ end
+ end
+
+ describe '#modified_paths' do
+ context 'when old and new revisions are set' do
+ let(:project) { create(:project, :repository) }
+
+ before do
+ pipeline.update(before_sha: '1234abcd', sha: '2345bcde')
+ end
+
+ it 'fetches stats for changes between commits' do
+ expect(project.repository)
+ .to receive(:diff_stats).with('1234abcd', '2345bcde')
+ .and_call_original
+
+ pipeline.modified_paths
+ end
+ end
+
+ context 'when either old or new revision is missing' do
+ before do
+ pipeline.update_column(:before_sha, Gitlab::Git::BLANK_SHA)
+ end
+
+ it 'raises an error' do
+ expect { pipeline.modified_paths }.to raise_error(ArgumentError)
+ end
+ end
+ end
+
describe '#has_kubernetes_active?' do
context 'when kubernetes is active' do
shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
@@ -945,6 +1045,11 @@ describe Ci::Pipeline, :mailer do
expect(described_class.newest_first.pluck(:status))
.to eq(%w[skipped failed success canceled])
end
+
+ it 'searches limited backlog' do
+ expect(described_class.newest_first(limit: 1).pluck(:status))
+ .to eq(%w[skipped])
+ end
end
describe '.latest_status' do
@@ -1050,6 +1155,19 @@ describe Ci::Pipeline, :mailer do
end
end
+ describe '.latest_successful_ids_per_project' do
+ let(:projects) { create_list(:project, 2) }
+ let!(:pipeline1) { create(:ci_pipeline, :success, project: projects[0]) }
+ let!(:pipeline2) { create(:ci_pipeline, :success, project: projects[0]) }
+ let!(:pipeline3) { create(:ci_pipeline, :failed, project: projects[0]) }
+ let!(:pipeline4) { create(:ci_pipeline, :success, project: projects[1]) }
+
+ it 'returns expected pipeline ids' do
+ expect(described_class.latest_successful_ids_per_project)
+ .to contain_exactly(pipeline2, pipeline4)
+ end
+ end
+
describe '.internal_sources' do
subject { described_class.internal_sources }
@@ -1288,6 +1406,19 @@ describe Ci::Pipeline, :mailer do
end
end
+ context 'when updating status to scheduled' do
+ before do
+ allow(pipeline)
+ .to receive_message_chain(:statuses, :latest, :status)
+ .and_return(:scheduled)
+ end
+
+ it 'updates pipeline status to scheduled' do
+ expect { pipeline.update_status }
+ .to change { pipeline.reload.status }.to 'scheduled'
+ end
+ end
+
context 'when statuses status was not recognized' do
before do
allow(pipeline)
@@ -1968,4 +2099,34 @@ describe Ci::Pipeline, :mailer do
end
end
end
+
+ describe '#default_branch?' do
+ let(:default_branch) { 'master'}
+
+ subject { pipeline.default_branch? }
+
+ before do
+ allow(project).to receive(:default_branch).and_return(default_branch)
+ end
+
+ context 'when pipeline ref is the default branch of the project' do
+ let(:pipeline) do
+ build(:ci_empty_pipeline, status: :created, project: project, ref: default_branch)
+ end
+
+ it "returns true" do
+ expect(subject).to be_truthy
+ end
+ end
+
+ context 'when pipeline ref is not the default branch of the project' do
+ let(:pipeline) do
+ build(:ci_empty_pipeline, status: :created, project: project, ref: 'another_branch')
+ end
+
+ it "returns false" do
+ expect(subject).to be_falsey
+ end
+ end
+ end
end
diff --git a/spec/models/ci/pipeline_variable_spec.rb b/spec/models/ci/pipeline_variable_spec.rb
index 889c243c8d8..03d09cb31d6 100644
--- a/spec/models/ci/pipeline_variable_spec.rb
+++ b/spec/models/ci/pipeline_variable_spec.rb
@@ -5,4 +5,13 @@ describe Ci::PipelineVariable do
it { is_expected.to include_module(HasVariable) }
it { is_expected.to validate_uniqueness_of(:key).scoped_to(:pipeline_id) }
+
+ describe '#hook_attrs' do
+ let(:variable) { create(:ci_pipeline_variable, key: 'foo', value: 'bar') }
+
+ subject { variable.hook_attrs }
+
+ it { is_expected.to be_a(Hash) }
+ it { is_expected.to eq({ key: 'foo', value: 'bar' }) }
+ end
end
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index b545e036aa1..ad79f8d4ce0 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe Ci::Runner do
+ it_behaves_like 'having unique enum values'
+
describe 'validation' do
it { is_expected.to validate_presence_of(:access_level) }
it { is_expected.to validate_presence_of(:runner_type) }
diff --git a/spec/models/ci/stage_spec.rb b/spec/models/ci/stage_spec.rb
index 22a4556c10c..3228c400155 100644
--- a/spec/models/ci/stage_spec.rb
+++ b/spec/models/ci/stage_spec.rb
@@ -3,6 +3,8 @@ require 'spec_helper'
describe Ci::Stage, :models do
let(:stage) { create(:ci_stage_entity) }
+ it_behaves_like 'having unique enum values'
+
describe 'associations' do
before do
create(:ci_build, stage_id: stage.id)
@@ -89,6 +91,18 @@ describe Ci::Stage, :models do
end
end
+ context 'when stage is scheduled because of scheduled builds' do
+ before do
+ create(:ci_build, :scheduled, stage_id: stage.id)
+ end
+
+ it 'updates status to scheduled' do
+ expect { stage.update_status }
+ .to change { stage.reload.status }
+ .to 'scheduled'
+ end
+ end
+
context 'when stage is skipped because is empty' do
it 'updates status to skipped' do
expect { stage.update_status }
@@ -188,6 +202,18 @@ describe Ci::Stage, :models do
end
end
+ describe '#delay' do
+ subject { stage.delay }
+
+ let(:stage) { create(:ci_stage_entity, status: :created) }
+
+ it 'updates stage status' do
+ subject
+
+ expect(stage).to be_scheduled
+ end
+ end
+
describe '#position' do
context 'when stage has been imported and does not have position index set' do
before do
diff --git a/spec/models/clusters/applications/cert_manager_spec.rb b/spec/models/clusters/applications/cert_manager_spec.rb
new file mode 100644
index 00000000000..170c6001eaf
--- /dev/null
+++ b/spec/models/clusters/applications/cert_manager_spec.rb
@@ -0,0 +1,79 @@
+require 'rails_helper'
+
+describe Clusters::Applications::CertManager do
+ let(:cert_manager) { create(:clusters_applications_cert_managers) }
+
+ include_examples 'cluster application core specs', :clusters_applications_cert_managers
+
+ describe '#make_installing!' do
+ before do
+ application.make_installing!
+ end
+
+ context 'application install previously errored with older version' do
+ let(:application) { create(:clusters_applications_cert_managers, :scheduled, version: 'v0.4.0') }
+
+ it 'updates the application version' do
+ expect(application.reload.version).to eq('v0.5.0')
+ end
+ end
+ end
+
+ describe '#install_command' do
+ let(:cluster_issuer_file) { { "cluster_issuer.yaml": "---\napiVersion: certmanager.k8s.io/v1alpha1\nkind: ClusterIssuer\nmetadata:\n name: letsencrypt-prod\nspec:\n acme:\n server: https://acme-v02.api.letsencrypt.org/directory\n email: admin@example.com\n privateKeySecretRef:\n name: letsencrypt-prod\n http01: {}\n" } }
+ subject { cert_manager.install_command }
+
+ it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
+
+ it 'should be initialized with cert_manager arguments' do
+ expect(subject.name).to eq('certmanager')
+ expect(subject.chart).to eq('stable/cert-manager')
+ expect(subject.version).to eq('v0.5.0')
+ expect(subject).not_to be_rbac
+ expect(subject.files).to eq(cert_manager.files.merge(cluster_issuer_file))
+ expect(subject.postinstall).to eq(['/usr/bin/kubectl create -f /data/helm/certmanager/config/cluster_issuer.yaml'])
+ end
+
+ context 'for a specific user' do
+ before do
+ cert_manager.email = 'abc@xyz.com'
+ cluster_issuer_file[:'cluster_issuer.yaml'].gsub! 'admin@example.com', 'abc@xyz.com'
+ end
+
+ it 'should use his/her email to register issuer with certificate provider' do
+ expect(subject.files).to eq(cert_manager.files.merge(cluster_issuer_file))
+ end
+ end
+
+ context 'on a rbac enabled cluster' do
+ before do
+ cert_manager.cluster.platform_kubernetes.rbac!
+ end
+
+ it { is_expected.to be_rbac }
+ end
+
+ context 'application failed to install previously' do
+ let(:cert_manager) { create(:clusters_applications_cert_managers, :errored, version: '0.0.1') }
+
+ it 'should be initialized with the locked version' do
+ expect(subject.version).to eq('v0.5.0')
+ end
+ end
+ end
+
+ describe '#files' do
+ let(:application) { cert_manager }
+ let(:values) { subject[:'values.yaml'] }
+
+ subject { application.files }
+
+ it 'should include cert_manager specific keys in the values.yaml file' do
+ expect(values).to include('ingressShim')
+ end
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:email) }
+ end
+end
diff --git a/spec/models/clusters/applications/ingress_spec.rb b/spec/models/clusters/applications/ingress_spec.rb
index c55953c8d22..cd28f1fe9c6 100644
--- a/spec/models/clusters/applications/ingress_spec.rb
+++ b/spec/models/clusters/applications/ingress_spec.rb
@@ -3,8 +3,11 @@ require 'rails_helper'
describe Clusters::Applications::Ingress do
let(:ingress) { create(:clusters_applications_ingress) }
+ it_behaves_like 'having unique enum values'
+
include_examples 'cluster application core specs', :clusters_applications_ingress
- include_examples 'cluster application status specs', :cluster_application_ingress
+ include_examples 'cluster application status specs', :clusters_applications_ingress
+ include_examples 'cluster application helm specs', :clusters_applications_ingress
before do
allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_in)
@@ -121,28 +124,5 @@ describe Clusters::Applications::Ingress do
expect(values).to include('stats')
expect(values).to include('podAnnotations')
end
-
- context 'when the helm application does not have a ca_cert' do
- before do
- application.cluster.application_helm.ca_cert = nil
- end
-
- it 'should not include cert files' do
- expect(subject[:'ca.pem']).not_to be_present
- expect(subject[:'cert.pem']).not_to be_present
- expect(subject[:'key.pem']).not_to be_present
- end
- end
-
- it 'should include cert files' do
- expect(subject[:'ca.pem']).to be_present
- expect(subject[:'ca.pem']).to eq(application.cluster.application_helm.ca_cert)
-
- expect(subject[:'cert.pem']).to be_present
- expect(subject[:'key.pem']).to be_present
-
- cert = OpenSSL::X509::Certificate.new(subject[:'cert.pem'])
- expect(cert.not_after).to be < 60.minutes.from_now
- end
end
end
diff --git a/spec/models/clusters/applications/jupyter_spec.rb b/spec/models/clusters/applications/jupyter_spec.rb
index 591a01d78a9..a40edbf267b 100644
--- a/spec/models/clusters/applications/jupyter_spec.rb
+++ b/spec/models/clusters/applications/jupyter_spec.rb
@@ -2,6 +2,7 @@ require 'rails_helper'
describe Clusters::Applications::Jupyter do
include_examples 'cluster application core specs', :clusters_applications_jupyter
+ include_examples 'cluster application helm specs', :clusters_applications_jupyter
it { is_expected.to belong_to(:oauth_application) }
@@ -79,37 +80,21 @@ describe Clusters::Applications::Jupyter do
subject { application.files }
- it 'should include cert files' do
- expect(subject[:'ca.pem']).to be_present
- expect(subject[:'ca.pem']).to eq(application.cluster.application_helm.ca_cert)
-
- expect(subject[:'cert.pem']).to be_present
- expect(subject[:'key.pem']).to be_present
-
- cert = OpenSSL::X509::Certificate.new(subject[:'cert.pem'])
- expect(cert.not_after).to be < 60.minutes.from_now
- end
-
- context 'when the helm application does not have a ca_cert' do
- before do
- application.cluster.application_helm.ca_cert = nil
- end
-
- it 'should not include cert files' do
- expect(subject[:'ca.pem']).not_to be_present
- expect(subject[:'cert.pem']).not_to be_present
- expect(subject[:'key.pem']).not_to be_present
- end
- end
-
it 'should include valid values' do
expect(values).to include('ingress')
expect(values).to include('hub')
expect(values).to include('rbac')
expect(values).to include('proxy')
expect(values).to include('auth')
+ expect(values).to include('singleuser')
expect(values).to match(/clientId: '?#{application.oauth_application.uid}/)
expect(values).to match(/callbackUrl: '?#{application.callback_url}/)
end
+
+ context 'when cluster belongs to a project' do
+ it 'sets GitLab project id' do
+ expect(values).to match(/GITLAB_CLUSTER_ID: '?#{application.cluster.id}/)
+ end
+ end
end
end
diff --git a/spec/models/clusters/applications/knative_spec.rb b/spec/models/clusters/applications/knative_spec.rb
new file mode 100644
index 00000000000..d43d88c2924
--- /dev/null
+++ b/spec/models/clusters/applications/knative_spec.rb
@@ -0,0 +1,124 @@
+require 'rails_helper'
+
+describe Clusters::Applications::Knative do
+ let(:knative) { create(:clusters_applications_knative) }
+
+ include_examples 'cluster application core specs', :clusters_applications_knative
+ include_examples 'cluster application status specs', :clusters_applications_knative
+ include_examples 'cluster application helm specs', :clusters_applications_knative
+
+ before do
+ allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_in)
+ allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_async)
+ end
+
+ describe '.installed' do
+ subject { described_class.installed }
+
+ let!(:cluster) { create(:clusters_applications_knative, :installed) }
+
+ before do
+ create(:clusters_applications_knative, :errored)
+ end
+
+ it { is_expected.to contain_exactly(cluster) }
+ end
+
+ describe '#make_installing!' do
+ before do
+ application.make_installing!
+ end
+
+ context 'application install previously errored with older version' do
+ let(:application) { create(:clusters_applications_knative, :scheduled, version: '0.1.3') }
+
+ it 'updates the application version' do
+ expect(application.reload.version).to eq('0.1.3')
+ end
+ end
+ end
+
+ describe '#make_installed' do
+ subject { described_class.installed }
+
+ let!(:cluster) { create(:clusters_applications_knative, :installed) }
+
+ before do
+ create(:clusters_applications_knative, :errored)
+ end
+
+ it { is_expected.to contain_exactly(cluster) }
+ end
+
+ describe 'make_installed with external_ip' do
+ before do
+ application.make_installed!
+ end
+
+ let(:application) { create(:clusters_applications_knative, :installing) }
+
+ it 'schedules a ClusterWaitForIngressIpAddressWorker' do
+ expect(ClusterWaitForIngressIpAddressWorker).to have_received(:perform_in)
+ .with(Clusters::Applications::Knative::FETCH_IP_ADDRESS_DELAY, 'knative', application.id)
+ end
+ end
+
+ describe '#schedule_status_update with external_ip' do
+ let(:application) { create(:clusters_applications_knative, :installed) }
+
+ before do
+ application.schedule_status_update
+ end
+
+ it 'schedules a ClusterWaitForIngressIpAddressWorker' do
+ expect(ClusterWaitForIngressIpAddressWorker).to have_received(:perform_async)
+ .with('knative', application.id)
+ end
+
+ context 'when the application is not installed' do
+ let(:application) { create(:clusters_applications_knative, :installing) }
+
+ it 'does not schedule a ClusterWaitForIngressIpAddressWorker' do
+ expect(ClusterWaitForIngressIpAddressWorker).not_to have_received(:perform_async)
+ end
+ end
+
+ context 'when there is already an external_ip' do
+ let(:application) { create(:clusters_applications_knative, :installed, external_ip: '111.222.222.111') }
+
+ it 'does not schedule a ClusterWaitForIngressIpAddressWorker' do
+ expect(ClusterWaitForIngressIpAddressWorker).not_to have_received(:perform_in)
+ end
+ end
+ end
+
+ describe '#install_command' do
+ subject { knative.install_command }
+
+ it 'should be an instance of Helm::InstallCommand' do
+ expect(subject).to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand)
+ end
+
+ it 'should be initialized with knative arguments' do
+ expect(subject.name).to eq('knative')
+ expect(subject.chart).to eq('knative/knative')
+ expect(subject.version).to eq('0.1.3')
+ expect(subject.files).to eq(knative.files)
+ end
+ end
+
+ describe '#files' do
+ let(:application) { knative }
+ let(:values) { subject[:'values.yaml'] }
+
+ subject { application.files }
+
+ it 'should include knative specific keys in the values.yaml file' do
+ expect(values).to include('domain')
+ end
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:hostname) }
+ end
+end
diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb
index f34b4ece8db..893ed3e3f64 100644
--- a/spec/models/clusters/applications/prometheus_spec.rb
+++ b/spec/models/clusters/applications/prometheus_spec.rb
@@ -4,7 +4,8 @@ describe Clusters::Applications::Prometheus do
include KubernetesHelpers
include_examples 'cluster application core specs', :clusters_applications_prometheus
- include_examples 'cluster application status specs', :cluster_application_prometheus
+ include_examples 'cluster application status specs', :clusters_applications_prometheus
+ include_examples 'cluster application helm specs', :clusters_applications_prometheus
describe '.installed' do
subject { described_class.installed }
@@ -34,7 +35,7 @@ describe Clusters::Applications::Prometheus do
describe 'transition to installed' do
let(:project) { create(:project) }
- let(:cluster) { create(:cluster, projects: [project]) }
+ let(:cluster) { create(:cluster, :with_installed_helm, projects: [project]) }
let(:prometheus_service) { double('prometheus_service') }
subject { create(:clusters_applications_prometheus, :installing, cluster: cluster) }
@@ -109,14 +110,20 @@ describe Clusters::Applications::Prometheus do
end
context 'cluster has kubeclient' do
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:kubernetes_url) { subject.cluster.platform_kubernetes.api_url }
let(:kube_client) { subject.cluster.kubeclient.core_client }
- subject { create(:clusters_applications_prometheus) }
+ subject { create(:clusters_applications_prometheus, cluster: cluster) }
before do
subject.cluster.platform_kubernetes.namespace = 'a-namespace'
- stub_kubeclient_discover(subject.cluster.platform_kubernetes.api_url)
+ stub_kubeclient_discover(cluster.platform_kubernetes.api_url)
+
+ create(:cluster_kubernetes_namespace,
+ cluster: cluster,
+ cluster_project: cluster.cluster_project,
+ project: cluster.cluster_project.project)
end
it 'creates proxy prometheus rest client' do
@@ -181,29 +188,6 @@ describe Clusters::Applications::Prometheus do
subject { application.files }
- it 'should include cert files' do
- expect(subject[:'ca.pem']).to be_present
- expect(subject[:'ca.pem']).to eq(application.cluster.application_helm.ca_cert)
-
- expect(subject[:'cert.pem']).to be_present
- expect(subject[:'key.pem']).to be_present
-
- cert = OpenSSL::X509::Certificate.new(subject[:'cert.pem'])
- expect(cert.not_after).to be < 60.minutes.from_now
- end
-
- context 'when the helm application does not have a ca_cert' do
- before do
- application.cluster.application_helm.ca_cert = nil
- end
-
- it 'should not include cert files' do
- expect(subject[:'ca.pem']).not_to be_present
- expect(subject[:'cert.pem']).not_to be_present
- expect(subject[:'key.pem']).not_to be_present
- end
- end
-
it 'should include prometheus valid values' do
expect(values).to include('alertmanager')
expect(values).to include('kubeStateMetrics')
diff --git a/spec/models/clusters/applications/runner_spec.rb b/spec/models/clusters/applications/runner_spec.rb
index eda8d519f60..97e50809647 100644
--- a/spec/models/clusters/applications/runner_spec.rb
+++ b/spec/models/clusters/applications/runner_spec.rb
@@ -4,7 +4,8 @@ describe Clusters::Applications::Runner do
let(:ci_runner) { create(:ci_runner) }
include_examples 'cluster application core specs', :clusters_applications_runner
- include_examples 'cluster application status specs', :cluster_application_runner
+ include_examples 'cluster application status specs', :clusters_applications_runner
+ include_examples 'cluster application helm specs', :clusters_applications_runner
it { is_expected.to belong_to(:runner) }
@@ -17,7 +18,7 @@ describe Clusters::Applications::Runner do
let(:application) { create(:clusters_applications_runner, :scheduled, version: '0.1.30') }
it 'updates the application version' do
- expect(application.reload.version).to eq('0.1.31')
+ expect(application.reload.version).to eq('0.1.38')
end
end
end
@@ -45,7 +46,7 @@ describe Clusters::Applications::Runner do
it 'should be initialized with 4 arguments' do
expect(subject.name).to eq('runner')
expect(subject.chart).to eq('runner/gitlab-runner')
- expect(subject.version).to eq('0.1.31')
+ expect(subject.version).to eq('0.1.38')
expect(subject).not_to be_rbac
expect(subject.repository).to eq('https://charts.gitlab.io')
expect(subject.files).to eq(gitlab_runner.files)
@@ -63,7 +64,7 @@ describe Clusters::Applications::Runner do
let(:gitlab_runner) { create(:clusters_applications_runner, :errored, runner: ci_runner, version: '0.1.13') }
it 'should be initialized with the locked version' do
- expect(subject.version).to eq('0.1.31')
+ expect(subject.version).to eq('0.1.38')
end
end
end
@@ -74,29 +75,6 @@ describe Clusters::Applications::Runner do
subject { application.files }
- it 'should include cert files' do
- expect(subject[:'ca.pem']).to be_present
- expect(subject[:'ca.pem']).to eq(application.cluster.application_helm.ca_cert)
-
- expect(subject[:'cert.pem']).to be_present
- expect(subject[:'key.pem']).to be_present
-
- cert = OpenSSL::X509::Certificate.new(subject[:'cert.pem'])
- expect(cert.not_after).to be < 60.minutes.from_now
- end
-
- context 'when the helm application does not have a ca_cert' do
- before do
- application.cluster.application_helm.ca_cert = nil
- end
-
- it 'should not include cert files' do
- expect(subject[:'ca.pem']).not_to be_present
- expect(subject[:'cert.pem']).not_to be_present
- expect(subject[:'key.pem']).not_to be_present
- end
- end
-
it 'should include runner valid values' do
expect(values).to include('concurrent')
expect(values).to include('checkInterval')
@@ -112,7 +90,7 @@ describe Clusters::Applications::Runner do
context 'without a runner' do
let(:project) { create(:project) }
let(:cluster) { create(:cluster, :with_installed_helm, projects: [project]) }
- let(:application) { create(:clusters_applications_runner, cluster: cluster) }
+ let(:application) { create(:clusters_applications_runner, runner: nil, cluster: cluster) }
it 'creates a runner' do
expect do
diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb
index 2727191eb9b..7dcf97276b2 100644
--- a/spec/models/clusters/cluster_spec.rb
+++ b/spec/models/clusters/cluster_spec.rb
@@ -1,22 +1,35 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe Clusters::Cluster do
+ it_behaves_like 'having unique enum values'
+
it { is_expected.to belong_to(:user) }
+ it { is_expected.to have_many(:cluster_projects) }
it { is_expected.to have_many(:projects) }
+ it { is_expected.to have_many(:cluster_groups) }
+ it { is_expected.to have_many(:groups) }
it { is_expected.to have_one(:provider_gcp) }
it { is_expected.to have_one(:platform_kubernetes) }
it { is_expected.to have_one(:application_helm) }
it { is_expected.to have_one(:application_ingress) }
it { is_expected.to have_one(:application_prometheus) }
it { is_expected.to have_one(:application_runner) }
+ it { is_expected.to have_many(:kubernetes_namespaces) }
+ it { is_expected.to have_one(:kubernetes_namespace) }
+ it { is_expected.to have_one(:cluster_project) }
+
it { is_expected.to delegate_method(:status).to(:provider) }
it { is_expected.to delegate_method(:status_reason).to(:provider) }
it { is_expected.to delegate_method(:status_name).to(:provider) }
it { is_expected.to delegate_method(:on_creation?).to(:provider) }
it { is_expected.to delegate_method(:active?).to(:platform_kubernetes).with_prefix }
it { is_expected.to delegate_method(:rbac?).to(:platform_kubernetes).with_prefix }
- it { is_expected.to delegate_method(:installed?).to(:application_helm).with_prefix }
- it { is_expected.to delegate_method(:installed?).to(:application_ingress).with_prefix }
+ it { is_expected.to delegate_method(:available?).to(:application_helm).with_prefix }
+ it { is_expected.to delegate_method(:available?).to(:application_ingress).with_prefix }
+ it { is_expected.to delegate_method(:available?).to(:application_prometheus).with_prefix }
+
it { is_expected.to respond_to :project }
describe '.enabled' do
@@ -171,6 +184,53 @@ describe Clusters::Cluster do
it { expect(cluster.update(enabled: false)).to be_truthy }
end
end
+
+ describe 'cluster_type validations' do
+ let(:instance_cluster) { create(:cluster, :instance) }
+ let(:group_cluster) { create(:cluster, :group) }
+ let(:project_cluster) { create(:cluster, :project) }
+
+ it 'validates presence' do
+ cluster = build(:cluster, :project, cluster_type: nil)
+
+ expect(cluster).not_to be_valid
+ expect(cluster.errors.full_messages).to include("Cluster type can't be blank")
+ end
+
+ context 'project_type cluster' do
+ it 'does not allow setting group' do
+ project_cluster.groups << build(:group)
+
+ expect(project_cluster).not_to be_valid
+ expect(project_cluster.errors.full_messages).to include('Cluster cannot have groups assigned')
+ end
+ end
+
+ context 'group_type cluster' do
+ it 'does not allow setting project' do
+ group_cluster.projects << build(:project)
+
+ expect(group_cluster).not_to be_valid
+ expect(group_cluster.errors.full_messages).to include('Cluster cannot have projects assigned')
+ end
+ end
+
+ context 'instance_type cluster' do
+ it 'does not allow setting group' do
+ instance_cluster.groups << build(:group)
+
+ expect(instance_cluster).not_to be_valid
+ expect(instance_cluster.errors.full_messages).to include('Cluster cannot have groups assigned')
+ end
+
+ it 'does not allow setting project' do
+ instance_cluster.projects << build(:project)
+
+ expect(instance_cluster).not_to be_valid
+ expect(instance_cluster.errors.full_messages).to include('Cluster cannot have projects assigned')
+ end
+ end
+ end
end
describe '#provider' do
@@ -222,6 +282,23 @@ describe Clusters::Cluster do
end
end
+ describe '#group' do
+ subject { cluster.group }
+
+ context 'when cluster belongs to a group' do
+ let(:cluster) { create(:cluster, :group) }
+ let(:group) { cluster.groups.first }
+
+ it { is_expected.to eq(group) }
+ end
+
+ context 'when cluster does not belong to any group' do
+ let(:cluster) { create(:cluster) }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
describe '#applications' do
set(:cluster) { create(:cluster) }
@@ -236,12 +313,14 @@ describe Clusters::Cluster do
context 'when applications are created' do
let!(:helm) { create(:clusters_applications_helm, cluster: cluster) }
let!(:ingress) { create(:clusters_applications_ingress, cluster: cluster) }
+ let!(:cert_manager) { create(:clusters_applications_cert_managers, cluster: cluster) }
let!(:prometheus) { create(:clusters_applications_prometheus, cluster: cluster) }
let!(:runner) { create(:clusters_applications_runner, cluster: cluster) }
let!(:jupyter) { create(:clusters_applications_jupyter, cluster: cluster) }
+ let!(:knative) { create(:clusters_applications_knative, cluster: cluster) }
it 'returns a list of created applications' do
- is_expected.to contain_exactly(helm, ingress, prometheus, runner, jupyter)
+ is_expected.to contain_exactly(helm, ingress, cert_manager, prometheus, runner, jupyter, knative)
end
end
end
@@ -267,4 +346,26 @@ describe Clusters::Cluster do
it { is_expected.to eq(false) }
end
end
+
+ describe '#allow_user_defined_namespace?' do
+ let(:cluster) { create(:cluster, :provided_by_gcp) }
+
+ subject { cluster.allow_user_defined_namespace? }
+
+ context 'project type cluster' do
+ it { is_expected.to be_truthy }
+ end
+
+ context 'group type cluster' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :group) }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'instance type cluster' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :instance) }
+
+ it { is_expected.to be_falsey }
+ end
+ end
end
diff --git a/spec/models/clusters/group_spec.rb b/spec/models/clusters/group_spec.rb
new file mode 100644
index 00000000000..ba145342cb8
--- /dev/null
+++ b/spec/models/clusters/group_spec.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Clusters::Group do
+ it { is_expected.to belong_to(:cluster) }
+ it { is_expected.to belong_to(:group) }
+end
diff --git a/spec/models/clusters/kubernetes_namespace_spec.rb b/spec/models/clusters/kubernetes_namespace_spec.rb
new file mode 100644
index 00000000000..56c98d016c9
--- /dev/null
+++ b/spec/models/clusters/kubernetes_namespace_spec.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Clusters::KubernetesNamespace, type: :model do
+ it { is_expected.to belong_to(:cluster_project) }
+ it { is_expected.to belong_to(:project) }
+ it { is_expected.to belong_to(:cluster) }
+ it { is_expected.to have_one(:platform_kubernetes) }
+
+ describe 'has_service_account_token' do
+ subject { described_class.has_service_account_token }
+
+ context 'namespace has service_account_token' do
+ let!(:namespace) { create(:cluster_kubernetes_namespace, :with_token) }
+
+ it { is_expected.to include(namespace) }
+ end
+
+ context 'namespace has no service_account_token' do
+ let!(:namespace) { create(:cluster_kubernetes_namespace) }
+
+ it { is_expected.not_to include(namespace) }
+ end
+ end
+
+ describe 'namespace uniqueness validation' do
+ let(:cluster_project) { create(:cluster_project) }
+ let(:kubernetes_namespace) { build(:cluster_kubernetes_namespace, namespace: 'my-namespace') }
+
+ subject { kubernetes_namespace }
+
+ context 'when cluster is using the namespace' do
+ before do
+ create(:cluster_kubernetes_namespace,
+ cluster: kubernetes_namespace.cluster,
+ namespace: 'my-namespace')
+ end
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'when cluster is not using the namespace' do
+ it { is_expected.to be_valid }
+ end
+ end
+
+ describe '#set_defaults' do
+ let(:kubernetes_namespace) { build(:cluster_kubernetes_namespace) }
+ let(:cluster) { kubernetes_namespace.cluster }
+ let(:platform) { kubernetes_namespace.platform_kubernetes }
+
+ subject { kubernetes_namespace.set_defaults }
+
+ describe '#namespace' do
+ before do
+ platform.update_column(:namespace, namespace)
+ end
+
+ context 'when platform has a namespace assigned' do
+ let(:namespace) { 'platform-namespace' }
+
+ it 'should copy the namespace' do
+ subject
+
+ expect(kubernetes_namespace.namespace).to eq('platform-namespace')
+ end
+ end
+
+ context 'when platform does not have namespace assigned' do
+ let(:project) { kubernetes_namespace.project }
+ let(:namespace) { nil }
+ let(:project_slug) { "#{project.path}-#{project.id}" }
+
+ it 'should fallback to project namespace' do
+ subject
+
+ expect(kubernetes_namespace.namespace).to eq(project_slug)
+ end
+ end
+ end
+
+ describe '#service_account_name' do
+ let(:service_account_name) { "#{kubernetes_namespace.namespace}-service-account" }
+
+ it 'should set a service account name based on namespace' do
+ subject
+
+ expect(kubernetes_namespace.service_account_name).to eq(service_account_name)
+ end
+ end
+ end
+
+ describe '#predefined_variables' do
+ let(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, cluster: cluster, service_account_token: token) }
+ let(:cluster) { create(:cluster, :project, platform_kubernetes: platform) }
+ let(:platform) { create(:cluster_platform_kubernetes, api_url: api_url, ca_cert: ca_pem, token: token) }
+
+ let(:api_url) { 'https://kube.domain.com' }
+ let(:ca_pem) { 'CA PEM DATA' }
+ let(:token) { 'token' }
+
+ let(:kubeconfig) do
+ config_file = expand_fixture_path('config/kubeconfig.yml')
+ config = YAML.safe_load(File.read(config_file))
+ config.dig('users', 0, 'user')['token'] = token
+ config.dig('contexts', 0, 'context')['namespace'] = kubernetes_namespace.namespace
+ config.dig('clusters', 0, 'cluster')['certificate-authority-data'] =
+ Base64.strict_encode64(ca_pem)
+
+ YAML.dump(config)
+ end
+
+ it 'sets the variables' do
+ expect(kubernetes_namespace.predefined_variables).to include(
+ { key: 'KUBE_SERVICE_ACCOUNT', value: kubernetes_namespace.service_account_name, public: true },
+ { key: 'KUBE_NAMESPACE', value: kubernetes_namespace.namespace, public: true },
+ { key: 'KUBE_TOKEN', value: kubernetes_namespace.service_account_token, public: false },
+ { key: 'KUBECONFIG', value: kubeconfig, public: false, file: true }
+ )
+ end
+ end
+end
diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb
index 66198d5ee2b..062d2fd0768 100644
--- a/spec/models/clusters/platforms/kubernetes_spec.rb
+++ b/spec/models/clusters/platforms/kubernetes_spec.rb
@@ -9,6 +9,17 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
it { is_expected.to be_kind_of(ReactiveCaching) }
it { is_expected.to respond_to :ca_pem }
+ it { is_expected.to validate_exclusion_of(:namespace).in_array(%w(gitlab-managed-apps)) }
+ it { is_expected.to validate_presence_of(:api_url) }
+ it { is_expected.to validate_presence_of(:token) }
+
+ it { is_expected.to delegate_method(:project).to(:cluster) }
+ it { is_expected.to delegate_method(:enabled?).to(:cluster) }
+ it { is_expected.to delegate_method(:managed?).to(:cluster) }
+ it { is_expected.to delegate_method(:kubernetes_namespace).to(:cluster) }
+
+ it_behaves_like 'having unique enum values'
+
describe 'before_validation' do
context 'when namespace includes upper case' do
let(:kubernetes) { create(:cluster_platform_kubernetes, :configured, namespace: namespace) }
@@ -49,6 +60,18 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
it { is_expected.to be_truthy }
end
+
+ context 'for group cluster' do
+ let(:namespace) { 'namespace-123' }
+ let(:cluster) { build(:cluster, :group, :provided_by_user) }
+ let(:kubernetes) { cluster.platform_kubernetes }
+
+ before do
+ kubernetes.namespace = namespace
+ end
+
+ it { is_expected.to be_falsey }
+ end
end
context 'when validates api_url' do
@@ -90,12 +113,42 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
it { expect(kubernetes.save).to be_falsey }
end
end
+
+ describe 'when using reserved namespaces' do
+ subject { build(:cluster_platform_kubernetes, namespace: namespace) }
+
+ context 'when no namespace is manually assigned' do
+ let(:namespace) { nil }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when no reserved namespace is assigned' do
+ let(:namespace) { 'my-namespace' }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when reserved namespace is assigned' do
+ let(:namespace) { 'gitlab-managed-apps' }
+
+ it { is_expected.not_to be_valid }
+ end
+ end
end
describe '#kubeclient' do
+ let(:cluster) { create(:cluster, :project) }
+ let(:kubernetes) { build(:cluster_platform_kubernetes, :configured, namespace: 'a-namespace', cluster: cluster) }
+
subject { kubernetes.kubeclient }
- let(:kubernetes) { build(:cluster_platform_kubernetes, :configured, namespace: 'a-namespace') }
+ before do
+ create(:cluster_kubernetes_namespace,
+ cluster: kubernetes.cluster,
+ cluster_project: kubernetes.cluster.cluster_project,
+ project: kubernetes.cluster.cluster_project.project)
+ end
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::KubeClient) }
end
@@ -117,75 +170,84 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
end
describe '#actual_namespace' do
- subject { kubernetes.actual_namespace }
-
- let!(:cluster) { create(:cluster, :project, platform_kubernetes: kubernetes) }
+ let(:cluster) { create(:cluster, :project) }
let(:project) { cluster.project }
- let(:kubernetes) { create(:cluster_platform_kubernetes, :configured, namespace: namespace) }
- context 'when namespace is present' do
+ let(:platform) do
+ create(:cluster_platform_kubernetes,
+ cluster: cluster,
+ namespace: namespace)
+ end
+
+ subject { platform.actual_namespace }
+
+ context 'with a namespace assigned' do
let(:namespace) { 'namespace-123' }
it { is_expected.to eq(namespace) }
end
- context 'when namespace is not present' do
+ context 'with no namespace assigned' do
let(:namespace) { nil }
- it { is_expected.to eq("#{project.path}-#{project.id}") }
- end
- end
+ context 'when kubernetes namespace is present' do
+ let(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, cluster: cluster) }
- describe '#default_namespace' do
- subject { kubernetes.send(:default_namespace) }
+ before do
+ kubernetes_namespace
+ end
- let(:kubernetes) { create(:cluster_platform_kubernetes, :configured) }
-
- context 'when cluster belongs to a project' do
- let!(:cluster) { create(:cluster, :project, platform_kubernetes: kubernetes) }
- let(:project) { cluster.project }
-
- it { is_expected.to eq("#{project.path}-#{project.id}") }
- end
-
- context 'when cluster belongs to nothing' do
- let!(:cluster) { create(:cluster, platform_kubernetes: kubernetes) }
+ it { is_expected.to eq(kubernetes_namespace.namespace) }
+ end
- it { is_expected.to be_nil }
+ context 'when kubernetes namespace is not present' do
+ it { is_expected.to eq("#{project.path}-#{project.id}") }
+ end
end
end
describe '#predefined_variables' do
let!(:cluster) { create(:cluster, :project, platform_kubernetes: kubernetes) }
- let(:kubernetes) { create(:cluster_platform_kubernetes, api_url: api_url, ca_cert: ca_pem, token: token) }
+ let(:kubernetes) { create(:cluster_platform_kubernetes, api_url: api_url, ca_cert: ca_pem) }
let(:api_url) { 'https://kube.domain.com' }
let(:ca_pem) { 'CA PEM DATA' }
- let(:token) { 'token' }
- let(:kubeconfig) do
- config_file = expand_fixture_path('config/kubeconfig.yml')
- config = YAML.load(File.read(config_file))
- config.dig('users', 0, 'user')['token'] = token
- config.dig('contexts', 0, 'context')['namespace'] = namespace
- config.dig('clusters', 0, 'cluster')['certificate-authority-data'] =
- Base64.strict_encode64(ca_pem)
-
- YAML.dump(config)
- end
+ subject { kubernetes.predefined_variables(project: cluster.project) }
shared_examples 'setting variables' do
it 'sets the variables' do
- expect(kubernetes.predefined_variables).to include(
+ expect(subject).to include(
{ key: 'KUBE_URL', value: api_url, public: true },
- { key: 'KUBE_TOKEN', value: token, public: false },
- { key: 'KUBE_NAMESPACE', value: namespace, public: true },
- { key: 'KUBECONFIG', value: kubeconfig, public: false, file: true },
{ key: 'KUBE_CA_PEM', value: ca_pem, public: true },
{ key: 'KUBE_CA_PEM_FILE', value: ca_pem, public: true, file: true }
)
end
end
+ context 'kubernetes namespace is created with no service account token' do
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, cluster: cluster) }
+
+ it_behaves_like 'setting variables'
+
+ it 'sets KUBE_TOKEN' do
+ expect(subject).to include(
+ { key: 'KUBE_TOKEN', value: kubernetes.token, public: false }
+ )
+ end
+ end
+
+ context 'kubernetes namespace is created with no service account token' do
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token, cluster: cluster) }
+
+ it_behaves_like 'setting variables'
+
+ it 'sets KUBE_TOKEN' do
+ expect(subject).to include(
+ { key: 'KUBE_TOKEN', value: kubernetes_namespace.service_account_token, public: false }
+ )
+ end
+ end
+
context 'namespace is provided' do
let(:namespace) { 'my-project' }
@@ -194,6 +256,12 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
end
it_behaves_like 'setting variables'
+
+ it 'sets KUBE_TOKEN' do
+ expect(subject).to include(
+ { key: 'KUBE_TOKEN', value: kubernetes.token, public: false }
+ )
+ end
end
context 'no namespace provided' do
@@ -201,11 +269,40 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
it_behaves_like 'setting variables'
- it 'sets the KUBE_NAMESPACE' do
- kube_namespace = kubernetes.predefined_variables.find { |h| h[:key] == 'KUBE_NAMESPACE' }
+ it 'sets KUBE_TOKEN' do
+ expect(subject).to include(
+ { key: 'KUBE_TOKEN', value: kubernetes.token, public: false }
+ )
+ end
+ end
+
+ context 'group level cluster' do
+ let!(:cluster) { create(:cluster, :group, platform_kubernetes: kubernetes) }
+
+ let(:project) { create(:project, group: cluster.group) }
+
+ subject { kubernetes.predefined_variables(project: project) }
+
+ context 'no kubernetes namespace for the project' do
+ it_behaves_like 'setting variables'
- expect(kube_namespace).not_to be_nil
- expect(kube_namespace[:value]).to match(/\A#{Gitlab::PathRegex::PATH_REGEX_STR}-\d+\z/)
+ it 'does not return KUBE_TOKEN' do
+ expect(subject).not_to include(
+ { key: 'KUBE_TOKEN', value: kubernetes.token, public: false }
+ )
+ end
+ end
+
+ context 'kubernetes namespace exists for the project' do
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token, cluster: cluster, project: project) }
+
+ it_behaves_like 'setting variables'
+
+ it 'sets KUBE_TOKEN' do
+ expect(subject).to include(
+ { key: 'KUBE_TOKEN', value: kubernetes_namespace.service_account_token, public: false }
+ )
+ end
end
end
end
@@ -290,4 +387,27 @@ describe Clusters::Platforms::Kubernetes, :use_clean_rails_memory_store_caching
it { is_expected.to include(pods: []) }
end
end
+
+ describe '#update_kubernetes_namespace' do
+ let(:cluster) { create(:cluster, :provided_by_gcp) }
+ let(:platform) { cluster.platform }
+
+ context 'when namespace is updated' do
+ it 'should call ConfigureWorker' do
+ expect(ClusterPlatformConfigureWorker).to receive(:perform_async).with(cluster.id).once
+
+ platform.namespace = 'new-namespace'
+ platform.save
+ end
+ end
+
+ context 'when namespace is not updated' do
+ it 'should not call ConfigureWorker' do
+ expect(ClusterPlatformConfigureWorker).not_to receive(:perform_async)
+
+ platform.username = "new-username"
+ platform.save
+ end
+ end
+ end
end
diff --git a/spec/models/clusters/project_spec.rb b/spec/models/clusters/project_spec.rb
index 7d75d6ab345..82ef5a23c18 100644
--- a/spec/models/clusters/project_spec.rb
+++ b/spec/models/clusters/project_spec.rb
@@ -3,4 +3,6 @@ require 'spec_helper'
describe Clusters::Project do
it { is_expected.to belong_to(:cluster) }
it { is_expected.to belong_to(:project) }
+ it { is_expected.to have_many(:kubernetes_namespaces) }
+ it { is_expected.to have_one(:kubernetes_namespace) }
end
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index d5f88e930d4..2a0039a0635 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -65,13 +65,14 @@ describe Commit do
key = "Commit:author:#{commit.author_email.downcase}"
- expect(RequestStore.store[key]).to eq(user)
+ expect(Gitlab::SafeRequestStore[key]).to eq(user)
expect(commit.author).to eq(user)
end
context 'using eager loading' do
let!(:alice) { create(:user, email: 'alice@example.com') }
let!(:bob) { create(:user, email: 'hunter2@example.com') }
+ let!(:jeff) { create(:user) }
let(:alice_commit) do
described_class.new(RepoHelpers.sample_commit, project).tap do |c|
@@ -93,7 +94,14 @@ describe Commit do
end
end
- let!(:commits) { [alice_commit, bob_commit, eve_commit] }
+ let(:jeff_commit) do
+ # The commit for Jeff uses his private commit email
+ described_class.new(RepoHelpers.sample_commit, project).tap do |c|
+ c.author_email = jeff.private_commit_email
+ end
+ end
+
+ let!(:commits) { [alice_commit, bob_commit, eve_commit, jeff_commit] }
before do
create(:email, user: bob, email: 'bob@example.com')
@@ -125,6 +133,20 @@ describe Commit do
expect(bob_commit.author).to eq(bob)
end
+ it "preloads the authors for Commits using a User's private commit Email" do
+ commits.each(&:lazy_author)
+
+ expect(jeff_commit.author).to eq(jeff)
+ end
+
+ it "preloads the authors for Commits using a User's outdated private commit Email" do
+ jeff.update!(username: 'new-username')
+
+ commits.each(&:lazy_author)
+
+ expect(jeff_commit.author).to eq(jeff)
+ end
+
it 'sets the author to Nil if an author could not be found for a Commit' do
commits.each(&:lazy_author)
@@ -270,11 +292,11 @@ eos
let(:issue) { create :issue, project: project }
let(:other_project) { create(:project, :public) }
let(:other_issue) { create :issue, project: other_project }
- let(:commiter) { create :user }
+ let(:committer) { create :user }
before do
- project.add_developer(commiter)
- other_project.add_developer(commiter)
+ project.add_developer(committer)
+ other_project.add_developer(committer)
end
it 'detects issues that this commit is marked as closing' do
@@ -282,7 +304,7 @@ eos
allow(commit).to receive_messages(
safe_message: "Fixes ##{issue.iid} and #{ext_ref}",
- committer_email: commiter.email
+ committer_email: committer.email
)
expect(commit.closes_issues).to include(issue)
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index f3f2bc28d2c..8b7c88805c1 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -13,6 +13,8 @@ describe CommitStatus do
create(:commit_status, pipeline: pipeline, **opts)
end
+ it_behaves_like 'having unique enum values'
+
it { is_expected.to belong_to(:pipeline) }
it { is_expected.to belong_to(:user) }
it { is_expected.to belong_to(:project) }
@@ -129,6 +131,20 @@ describe CommitStatus do
end
end
+ describe '#cancel' do
+ subject { job.cancel }
+
+ context 'when status is scheduled' do
+ let(:job) { build(:commit_status, :scheduled) }
+
+ it 'updates the status' do
+ subject
+
+ expect(job).to be_canceled
+ end
+ end
+ end
+
describe '#auto_canceled?' do
subject { commit_status.auto_canceled? }
@@ -564,6 +580,12 @@ describe CommitStatus do
it_behaves_like 'commit status enqueued'
end
+
+ context 'when initial state is :scheduled' do
+ let(:commit_status) { create(:commit_status, :scheduled) }
+
+ it_behaves_like 'commit status enqueued'
+ end
end
describe '#present' do
diff --git a/spec/models/compare_spec.rb b/spec/models/compare_spec.rb
index 8e88bb81162..0bc3ee014e6 100644
--- a/spec/models/compare_spec.rb
+++ b/spec/models/compare_spec.rb
@@ -92,4 +92,33 @@ describe Compare do
expect(subject.diff_refs.head_sha).to eq(head_commit.id)
end
end
+
+ describe '#modified_paths' do
+ context 'changes are present' do
+ let(:raw_compare) do
+ Gitlab::Git::Compare.new(
+ project.repository.raw_repository, 'before-create-delete-modify-move', 'after-create-delete-modify-move'
+ )
+ end
+
+ it 'returns affected file paths, without duplication' do
+ expect(subject.modified_paths).to contain_exactly(*%w{
+ foo/for_move.txt
+ foo/bar/for_move.txt
+ foo/for_create.txt
+ foo/for_delete.txt
+ foo/for_edit.txt
+ })
+ end
+ end
+
+ context 'changes are absent' do
+ let(:start_commit) { sample_commit }
+ let(:head_commit) { sample_commit }
+
+ it 'returns empty array' do
+ expect(subject.modified_paths).to eq([])
+ end
+ end
+ end
end
diff --git a/spec/models/concerns/awardable_spec.rb b/spec/models/concerns/awardable_spec.rb
index 69083bdc125..5713106418d 100644
--- a/spec/models/concerns/awardable_spec.rb
+++ b/spec/models/concerns/awardable_spec.rb
@@ -24,13 +24,29 @@ describe Awardable do
end
end
- describe ".awarded" do
+ describe "#awarded" do
it "filters by user and emoji name" do
expect(Issue.awarded(award_emoji.user, "thumbsup")).to be_empty
expect(Issue.awarded(award_emoji.user, "thumbsdown")).to eq [issue]
expect(Issue.awarded(award_emoji2.user, "thumbsup")).to eq [issue2]
expect(Issue.awarded(award_emoji2.user, "thumbsdown")).to be_empty
end
+
+ it "filters by user and any emoji" do
+ issue3 = create(:issue)
+ create(:award_emoji, awardable: issue3, name: "star", user: award_emoji.user)
+ create(:award_emoji, awardable: issue3, name: "star", user: award_emoji2.user)
+
+ expect(Issue.awarded(award_emoji.user)).to contain_exactly(issue, issue3)
+ expect(Issue.awarded(award_emoji2.user)).to contain_exactly(issue2, issue3)
+ end
+ end
+
+ describe "#not_awarded" do
+ it "returns issues not awarded by user" do
+ expect(Issue.not_awarded(award_emoji.user)).to eq [issue2]
+ expect(Issue.not_awarded(award_emoji2.user)).to eq [issue]
+ end
end
end
diff --git a/spec/models/concerns/blob_language_from_git_attributes_spec.rb b/spec/models/concerns/blob_language_from_git_attributes_spec.rb
new file mode 100644
index 00000000000..7f05073b08e
--- /dev/null
+++ b/spec/models/concerns/blob_language_from_git_attributes_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe BlobLanguageFromGitAttributes do
+ include FakeBlobHelpers
+
+ let(:project) { build(:project, :repository) }
+
+ describe '#language_from_gitattributes' do
+ subject(:blob) { fake_blob(path: 'file.md') }
+
+ it 'returns return value from gitattribute' do
+ expect(blob.project.repository).to receive(:gitattribute).with(blob.path, 'gitlab-language').and_return('erb?parent=json')
+
+ expect(blob.language_from_gitattributes).to eq('erb?parent=json')
+ end
+
+ it 'returns nil if project is absent' do
+ allow(blob).to receive(:project).and_return(nil)
+
+ expect(blob.language_from_gitattributes).to eq(nil)
+ end
+ end
+end
diff --git a/spec/models/concerns/cache_markdown_field_spec.rb b/spec/models/concerns/cache_markdown_field_spec.rb
index da26d802688..f8d50e89d40 100644
--- a/spec/models/concerns/cache_markdown_field_spec.rb
+++ b/spec/models/concerns/cache_markdown_field_spec.rb
@@ -331,11 +331,12 @@ describe CacheMarkdownField do
end
context 'with a project' do
- let(:thing) { thing_subclass(:project).new(foo: markdown, foo_html: html, project: :project_value) }
+ let(:project) { create(:project, group: create(:group)) }
+ let(:thing) { thing_subclass(:project).new(foo: markdown, foo_html: html, project: project) }
it 'sets the project in the context' do
is_expected.to have_key(:project)
- expect(context[:project]).to eq(:project_value)
+ expect(context[:project]).to eq(project)
end
it 'invalidates the cache when project changes' do
diff --git a/spec/models/concerns/cacheable_attributes_spec.rb b/spec/models/concerns/cacheable_attributes_spec.rb
index f8c2e29fadd..827fbc9d7d5 100644
--- a/spec/models/concerns/cacheable_attributes_spec.rb
+++ b/spec/models/concerns/cacheable_attributes_spec.rb
@@ -41,7 +41,7 @@ describe CacheableAttributes do
expect(minimal_test_class.current_without_cache).to eq(minimal_test_class.last)
end
- it 'can be overriden' do
+ it 'can be overridden' do
minimal_test_class.define_singleton_method(:current_without_cache) do
first
end
@@ -64,7 +64,7 @@ describe CacheableAttributes do
context 'with defaults defined' do
include_context 'with defaults'
- it 'can be overriden' do
+ it 'can be overridden' do
expect(minimal_test_class.defaults).to eq({ foo: 'a', bar: 'b', baz: 'c' })
end
end
diff --git a/spec/models/concerns/deployable_spec.rb b/spec/models/concerns/deployable_spec.rb
new file mode 100644
index 00000000000..6951be903fe
--- /dev/null
+++ b/spec/models/concerns/deployable_spec.rb
@@ -0,0 +1,74 @@
+require 'rails_helper'
+
+describe Deployable do
+ describe '#create_deployment' do
+ let(:deployment) { job.deployment }
+ let(:environment) { deployment&.environment }
+
+ before do
+ job.reload
+ end
+
+ context 'when the deployable object will deploy to production' do
+ let!(:job) { create(:ci_build, :start_review_app) }
+
+ it 'creates a deployment and environment record' do
+ expect(deployment.project).to eq(job.project)
+ expect(deployment.ref).to eq(job.ref)
+ expect(deployment.tag).to eq(job.tag)
+ expect(deployment.sha).to eq(job.sha)
+ expect(deployment.user).to eq(job.user)
+ expect(deployment.deployable).to eq(job)
+ expect(deployment.on_stop).to eq('stop_review_app')
+ expect(environment.name).to eq('review/master')
+ end
+ end
+
+ context 'when the deployable object will stop an environment' do
+ let!(:job) { create(:ci_build, :stop_review_app) }
+
+ it 'does not create a deployment record' do
+ expect(deployment).to be_nil
+ end
+ end
+
+ context 'when the deployable object has already had a deployment' do
+ let!(:job) { create(:ci_build, :start_review_app, deployment: race_deployment) }
+ let!(:race_deployment) { create(:deployment, :success) }
+
+ it 'does not create a new deployment' do
+ expect(deployment).to eq(race_deployment)
+ end
+ end
+
+ context 'when the deployable object will not deploy' do
+ let!(:job) { create(:ci_build) }
+
+ it 'does not create a deployment and environment record' do
+ expect(deployment).to be_nil
+ expect(environment).to be_nil
+ end
+ end
+
+ context 'when environment scope contains invalid character' do
+ let(:job) do
+ create(
+ :ci_build,
+ name: 'job:deploy-to-test-site',
+ environment: '$CI_JOB_NAME',
+ options: {
+ environment: {
+ name: '$CI_JOB_NAME',
+ url: 'http://staging.example.com/$CI_JOB_NAME',
+ on_stop: 'stop_review_app'
+ }
+ })
+ end
+
+ it 'does not create a deployment and environment record' do
+ expect(deployment).to be_nil
+ expect(environment).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/models/concerns/each_batch_spec.rb b/spec/models/concerns/each_batch_spec.rb
index 951690a217b..17224c09693 100644
--- a/spec/models/concerns/each_batch_spec.rb
+++ b/spec/models/concerns/each_batch_spec.rb
@@ -14,40 +14,45 @@ describe EachBatch do
5.times { create(:user, updated_at: 1.day.ago) }
end
- it 'yields an ActiveRecord::Relation when a block is given' do
- model.each_batch do |relation|
- expect(relation).to be_a_kind_of(ActiveRecord::Relation)
+ shared_examples 'each_batch handling' do |kwargs|
+ it 'yields an ActiveRecord::Relation when a block is given' do
+ model.each_batch(kwargs) do |relation|
+ expect(relation).to be_a_kind_of(ActiveRecord::Relation)
+ end
end
- end
- it 'yields a batch index as the second argument' do
- model.each_batch do |_, index|
- expect(index).to eq(1)
+ it 'yields a batch index as the second argument' do
+ model.each_batch(kwargs) do |_, index|
+ expect(index).to eq(1)
+ end
end
- end
- it 'accepts a custom batch size' do
- amount = 0
+ it 'accepts a custom batch size' do
+ amount = 0
- model.each_batch(of: 1) { amount += 1 }
+ model.each_batch(kwargs.merge({ of: 1 })) { amount += 1 }
- expect(amount).to eq(5)
- end
+ expect(amount).to eq(5)
+ end
- it 'does not include ORDER BYs in the yielded relations' do
- model.each_batch do |relation|
- expect(relation.to_sql).not_to include('ORDER BY')
+ it 'does not include ORDER BYs in the yielded relations' do
+ model.each_batch do |relation|
+ expect(relation.to_sql).not_to include('ORDER BY')
+ end
end
- end
- it 'allows updating of the yielded relations' do
- time = Time.now
+ it 'allows updating of the yielded relations' do
+ time = Time.now
- model.each_batch do |relation|
- relation.update_all(updated_at: time)
- end
+ model.each_batch do |relation|
+ relation.update_all(updated_at: time)
+ end
- expect(model.where(updated_at: time).count).to eq(5)
+ expect(model.where(updated_at: time).count).to eq(5)
+ end
end
+
+ it_behaves_like 'each_batch handling', {}
+ it_behaves_like 'each_batch handling', { order_hint: :updated_at }
end
end
diff --git a/spec/models/concerns/has_status_spec.rb b/spec/models/concerns/has_status_spec.rb
index 6866b43432c..6b1038cb8fd 100644
--- a/spec/models/concerns/has_status_spec.rb
+++ b/spec/models/concerns/has_status_spec.rb
@@ -270,11 +270,11 @@ describe HasStatus do
describe '.cancelable' do
subject { CommitStatus.cancelable }
- %i[running pending created].each do |status|
+ %i[running pending created scheduled].each do |status|
it_behaves_like 'containing the job', status
end
- %i[failed success skipped canceled].each do |status|
+ %i[failed success skipped canceled manual].each do |status|
it_behaves_like 'not containing the job', status
end
end
@@ -290,6 +290,18 @@ describe HasStatus do
it_behaves_like 'not containing the job', status
end
end
+
+ describe '.scheduled' do
+ subject { CommitStatus.scheduled }
+
+ %i[scheduled].each do |status|
+ it_behaves_like 'containing the job', status
+ end
+
+ %i[failed success skipped canceled].each do |status|
+ it_behaves_like 'not containing the job', status
+ end
+ end
end
describe '::DEFAULT_STATUS' do
@@ -300,7 +312,41 @@ describe HasStatus do
describe '::BLOCKED_STATUS' do
it 'is a status manual' do
- expect(described_class::BLOCKED_STATUS).to eq 'manual'
+ expect(described_class::BLOCKED_STATUS).to eq %w[manual scheduled]
+ end
+ end
+
+ describe 'blocked?' do
+ subject { object.blocked? }
+
+ %w[ci_pipeline ci_stage ci_build generic_commit_status].each do |type|
+ let(:object) { build(type, status: status) }
+
+ context 'when status is scheduled' do
+ let(:status) { :scheduled }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when status is manual' do
+ let(:status) { :manual }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when status is created' do
+ let(:status) { :created }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+ end
+
+ describe '.status_sql' do
+ subject { Ci::Build.status_sql }
+
+ it 'returns SQL' do
+ puts subject
end
end
end
diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb
index ec6374f3963..a4bf3e2350a 100644
--- a/spec/models/concerns/issuable_spec.rb
+++ b/spec/models/concerns/issuable_spec.rb
@@ -519,7 +519,7 @@ describe Issuable do
end
end
- context 'substracting time' do
+ context 'subtracting time' do
before do
spend_time(1800)
end
@@ -530,7 +530,7 @@ describe Issuable do
expect(issue.total_time_spent).to eq(900)
end
- context 'when time to substract exceeds the total time spent' do
+ context 'when time to subtract exceeds the total time spent' do
it 'raise a validation error' do
Timecop.travel(1.minute.from_now) do
expect do
diff --git a/spec/models/concerns/redactable_spec.rb b/spec/models/concerns/redactable_spec.rb
new file mode 100644
index 00000000000..7d320edd492
--- /dev/null
+++ b/spec/models/concerns/redactable_spec.rb
@@ -0,0 +1,69 @@
+require 'spec_helper'
+
+describe Redactable do
+ shared_examples 'model with redactable field' do
+ it 'redacts unsubscribe token' do
+ model[field] = 'some text /sent_notifications/00000000000000000000000000000000/unsubscribe more text'
+
+ model.save!
+
+ expect(model[field]).to eq 'some text /sent_notifications/REDACTED/unsubscribe more text'
+ end
+
+ it 'ignores not hexadecimal tokens' do
+ text = 'some text /sent_notifications/token/unsubscribe more text'
+ model[field] = text
+
+ model.save!
+
+ expect(model[field]).to eq text
+ end
+
+ it 'ignores not matching texts' do
+ text = 'some text /sent_notifications/.*/unsubscribe more text'
+ model[field] = text
+
+ model.save!
+
+ expect(model[field]).to eq text
+ end
+
+ it 'redacts the field when saving the model before creating markdown cache' do
+ model[field] = 'some text /sent_notifications/00000000000000000000000000000000/unsubscribe more text'
+
+ model.save!
+
+ expected = 'some text /sent_notifications/REDACTED/unsubscribe more text'
+ expect(model[field]).to eq expected
+ expect(model["#{field}_html"]).to eq "<p dir=\"auto\">#{expected}</p>"
+ end
+ end
+
+ context 'when model is an issue' do
+ it_behaves_like 'model with redactable field' do
+ let(:model) { create(:issue) }
+ let(:field) { :description }
+ end
+ end
+
+ context 'when model is a merge request' do
+ it_behaves_like 'model with redactable field' do
+ let(:model) { create(:merge_request) }
+ let(:field) { :description }
+ end
+ end
+
+ context 'when model is a note' do
+ it_behaves_like 'model with redactable field' do
+ let(:model) { create(:note) }
+ let(:field) { :note }
+ end
+ end
+
+ context 'when model is a snippet' do
+ it_behaves_like 'model with redactable field' do
+ let(:model) { create(:snippet) }
+ let(:field) { :description }
+ end
+ end
+end
diff --git a/spec/models/concerns/relative_positioning_spec.rb b/spec/models/concerns/relative_positioning_spec.rb
index 729056b6abc..ac8da30b6c9 100644
--- a/spec/models/concerns/relative_positioning_spec.rb
+++ b/spec/models/concerns/relative_positioning_spec.rb
@@ -6,9 +6,21 @@ describe RelativePositioning do
let(:issue1) { create(:issue, project: project) }
let(:new_issue) { create(:issue, project: project) }
- before do
- [issue, issue1].each do |issue|
- issue.move_to_end && issue.save
+ describe '.move_to_end' do
+ it 'moves the object to the end' do
+ Issue.move_to_end([issue, issue1])
+
+ expect(issue1.prev_relative_position).to eq issue.relative_position
+ expect(issue.prev_relative_position).to eq nil
+ expect(issue1.next_relative_position).to eq nil
+ end
+
+ it 'does not perform any moves if all issues have their relative_position set' do
+ issue.update!(relative_position: 1)
+
+ expect(issue).not_to receive(:save)
+
+ Issue.move_to_end([issue])
end
end
@@ -59,6 +71,12 @@ describe RelativePositioning do
end
describe '#move_to_end' do
+ before do
+ [issue, issue1].each do |issue|
+ issue.move_to_end && issue.save
+ end
+ end
+
it 'moves issue to the end' do
new_issue.move_to_end
@@ -67,6 +85,12 @@ describe RelativePositioning do
end
describe '#shift_after?' do
+ before do
+ [issue, issue1].each do |issue|
+ issue.move_to_end && issue.save
+ end
+ end
+
it 'returns true' do
issue.update(relative_position: issue1.relative_position - 1)
@@ -81,6 +105,12 @@ describe RelativePositioning do
end
describe '#shift_before?' do
+ before do
+ [issue, issue1].each do |issue|
+ issue.move_to_end && issue.save
+ end
+ end
+
it 'returns true' do
issue.update(relative_position: issue1.relative_position + 1)
@@ -95,6 +125,12 @@ describe RelativePositioning do
end
describe '#move_between' do
+ before do
+ [issue, issue1].each do |issue|
+ issue.move_to_end && issue.save
+ end
+ end
+
it 'positions issue between two other' do
new_issue.move_between(issue, issue1)
diff --git a/spec/models/concerns/token_authenticatable_spec.rb b/spec/models/concerns/token_authenticatable_spec.rb
index 9b804429138..782687516ae 100644
--- a/spec/models/concerns/token_authenticatable_spec.rb
+++ b/spec/models/concerns/token_authenticatable_spec.rb
@@ -2,8 +2,6 @@ require 'spec_helper'
shared_examples 'TokenAuthenticatable' do
describe 'dynamically defined methods' do
- it { expect(described_class).to be_private_method_defined(:generate_token) }
- it { expect(described_class).to be_private_method_defined(:write_new_token) }
it { expect(described_class).to respond_to("find_by_#{token_field}") }
it { is_expected.to respond_to("ensure_#{token_field}") }
it { is_expected.to respond_to("set_#{token_field}") }
@@ -66,13 +64,275 @@ describe ApplicationSetting, 'TokenAuthenticatable' do
end
describe 'multiple token fields' do
- before do
+ before(:all) do
described_class.send(:add_authentication_token_field, :yet_another_token)
end
- describe '.token_fields' do
- subject { described_class.authentication_token_fields }
- it { is_expected.to include(:runners_registration_token, :yet_another_token) }
+ it { is_expected.to respond_to(:ensure_runners_registration_token) }
+ it { is_expected.to respond_to(:ensure_yet_another_token) }
+ end
+
+ describe 'setting same token field multiple times' do
+ subject { described_class.send(:add_authentication_token_field, :runners_registration_token) }
+
+ it 'raises error' do
+ expect {subject}.to raise_error(ArgumentError)
+ end
+ end
+end
+
+describe PersonalAccessToken, 'TokenAuthenticatable' do
+ let(:personal_access_token_name) { 'test-pat-01' }
+ let(:token_value) { 'token' }
+ let(:user) { create(:user) }
+ let(:personal_access_token) do
+ described_class.new(name: personal_access_token_name,
+ user_id: user.id,
+ scopes: [:api],
+ token: token,
+ token_digest: token_digest)
+ end
+
+ before do
+ allow(Devise).to receive(:friendly_token).and_return(token_value)
+ end
+
+ describe '.find_by_token' do
+ subject { PersonalAccessToken.find_by_token(token_value) }
+
+ before do
+ personal_access_token.save
+ end
+
+ context 'token_digest already exists' do
+ let(:token) { nil }
+ let(:token_digest) { Gitlab::CryptoHelper.sha256(token_value) }
+
+ it 'finds the token' do
+ expect(subject).not_to be_nil
+ expect(subject.name).to eql(personal_access_token_name)
+ end
+ end
+
+ context 'token_digest does not exist' do
+ let(:token) { token_value }
+ let(:token_digest) { nil }
+
+ it 'finds the token' do
+ expect(subject).not_to be_nil
+ expect(subject.name).to eql(personal_access_token_name)
+ end
+ end
+ end
+
+ describe '#set_token' do
+ let(:new_token_value) { 'new-token' }
+ subject { personal_access_token.set_token(new_token_value) }
+
+ context 'token_digest already exists' do
+ let(:token) { nil }
+ let(:token_digest) { Gitlab::CryptoHelper.sha256(token_value) }
+
+ it 'overwrites token_digest' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(new_token_value)
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(new_token_value))
+ end
+ end
+
+ context 'token_digest does not exist but token does' do
+ let(:token) { token_value }
+ let(:token_digest) { nil }
+
+ it 'creates new token_digest and clears token' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(new_token_value)
+ expect(personal_access_token.token_digest).to eql(Gitlab::CryptoHelper.sha256(new_token_value))
+ end
+ end
+
+ context 'token_digest does not exist, nor token' do
+ let(:token) { nil }
+ let(:token_digest) { nil }
+
+ it 'creates new token_digest' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(new_token_value)
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(new_token_value))
+ end
+ end
+ end
+
+ describe '#ensure_token' do
+ subject { personal_access_token.ensure_token }
+
+ context 'token_digest already exists' do
+ let(:token) { nil }
+ let(:token_digest) { Gitlab::CryptoHelper.sha256(token_value) }
+
+ it 'does not change token fields' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to be_nil
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
+ end
+ end
+
+ context 'token_digest does not exist but token does' do
+ let(:token) { token_value }
+ let(:token_digest) { nil }
+
+ it 'does not change token fields' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to eql(token_value)
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to be_nil
+ end
+ end
+
+ context 'token_digest does not exist, nor token' do
+ let(:token) { nil }
+ let(:token_digest) { nil }
+
+ it 'creates token_digest' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
+ end
+ end
+ end
+
+ describe '#ensure_token!' do
+ subject { personal_access_token.ensure_token! }
+
+ context 'token_digest already exists' do
+ let(:token) { nil }
+ let(:token_digest) { Gitlab::CryptoHelper.sha256(token_value) }
+
+ it 'does not change token fields' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to be_nil
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
+ end
+ end
+
+ context 'token_digest does not exist but token does' do
+ let(:token) { token_value }
+ let(:token_digest) { nil }
+
+ it 'does not change token fields' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to eql(token_value)
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to be_nil
+ end
+ end
+
+ context 'token_digest does not exist, nor token' do
+ let(:token) { nil }
+ let(:token_digest) { nil }
+
+ it 'creates token_digest' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
+ end
+ end
+ end
+
+ describe '#reset_token!' do
+ subject { personal_access_token.reset_token! }
+
+ context 'token_digest already exists' do
+ let(:token) { nil }
+ let(:token_digest) { Gitlab::CryptoHelper.sha256('old-token') }
+
+ it 'creates new token_digest' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
+ end
+ end
+
+ context 'token_digest does not exist but token does' do
+ let(:token) { 'old-token' }
+ let(:token_digest) { nil }
+
+ it 'creates new token_digest and clears token' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to eql(Gitlab::CryptoHelper.sha256(token_value))
+ end
+ end
+
+ context 'token_digest does not exist, nor token' do
+ let(:token) { nil }
+ let(:token_digest) { nil }
+
+ it 'creates new token_digest' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
+ end
+ end
+
+ context 'token_digest exists and newly generated token would be the same' do
+ let(:token) { nil }
+ let(:token_digest) { Gitlab::CryptoHelper.sha256('old-token') }
+
+ before do
+ personal_access_token.save
+ allow(Devise).to receive(:friendly_token).and_return(
+ 'old-token', token_value, 'boom!')
+ end
+
+ it 'regenerates a new token_digest' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
+ end
+ end
+
+ context 'token exists and newly generated token would be the same' do
+ let(:token) { 'old-token' }
+ let(:token_digest) { nil }
+
+ before do
+ personal_access_token.save
+ allow(Devise).to receive(:friendly_token).and_return(
+ 'old-token', token_value, 'boom!')
+ end
+
+ it 'regenerates a new token_digest' do
+ subject
+
+ expect(personal_access_token.read_attribute('token')).to be_nil
+ expect(personal_access_token.token).to eql(token_value)
+ expect(personal_access_token.token_digest).to eql( Gitlab::CryptoHelper.sha256(token_value))
+ end
end
end
end
diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb
index b335e0fbeb3..a8d53cfcd7d 100644
--- a/spec/models/deployment_spec.rb
+++ b/spec/models/deployment_spec.rb
@@ -16,6 +16,24 @@ describe Deployment do
it { is_expected.to validate_presence_of(:ref) }
it { is_expected.to validate_presence_of(:sha) }
+ it_behaves_like 'having unique enum values'
+
+ describe '#scheduled_actions' do
+ subject { deployment.scheduled_actions }
+
+ let(:project) { create(:project, :repository) }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+ let(:build) { create(:ci_build, :success, pipeline: pipeline) }
+ let(:deployment) { create(:deployment, deployable: build) }
+
+ it 'delegates to other_scheduled_actions' do
+ expect_any_instance_of(Ci::Build)
+ .to receive(:other_scheduled_actions)
+
+ subject
+ end
+ end
+
describe 'modules' do
it_behaves_like 'AtomicInternalId' do
let(:internal_id_attribute) { :iid }
@@ -26,16 +44,197 @@ describe Deployment do
end
end
- describe 'after_create callbacks' do
- let(:environment) { create(:environment) }
- let(:store) { Gitlab::EtagCaching::Store.new }
+ describe '.success' do
+ subject { described_class.success }
+
+ context 'when deployment status is success' do
+ let(:deployment) { create(:deployment, :success) }
+
+ it { is_expected.to eq([deployment]) }
+ end
+
+ context 'when deployment status is created' do
+ let(:deployment) { create(:deployment, :created) }
+
+ it { is_expected.to be_empty }
+ end
+
+ context 'when deployment status is running' do
+ let(:deployment) { create(:deployment, :running) }
+
+ it { is_expected.to be_empty }
+ end
+ end
+
+ describe 'state machine' do
+ context 'when deployment runs' do
+ let(:deployment) { create(:deployment) }
+
+ before do
+ deployment.run!
+ end
+
+ it 'starts running' do
+ Timecop.freeze do
+ expect(deployment).to be_running
+ expect(deployment.finished_at).to be_nil
+ end
+ end
+ end
+
+ context 'when deployment succeeded' do
+ let(:deployment) { create(:deployment, :running) }
+
+ it 'has correct status' do
+ Timecop.freeze do
+ deployment.succeed!
+
+ expect(deployment).to be_success
+ expect(deployment.finished_at).to be_like_time(Time.now)
+ end
+ end
+
+ it 'executes Deployments::SuccessWorker asynchronously' do
+ expect(Deployments::SuccessWorker)
+ .to receive(:perform_async).with(deployment.id)
+
+ deployment.succeed!
+ end
+ end
+
+ context 'when deployment failed' do
+ let(:deployment) { create(:deployment, :running) }
+
+ it 'has correct status' do
+ Timecop.freeze do
+ deployment.drop!
+
+ expect(deployment).to be_failed
+ expect(deployment.finished_at).to be_like_time(Time.now)
+ end
+ end
+ end
+
+ context 'when deployment was canceled' do
+ let(:deployment) { create(:deployment, :running) }
+
+ it 'has correct status' do
+ Timecop.freeze do
+ deployment.cancel!
+
+ expect(deployment).to be_canceled
+ expect(deployment.finished_at).to be_like_time(Time.now)
+ end
+ end
+ end
+ end
+
+ describe '#success?' do
+ subject { deployment.success? }
+
+ context 'when deployment status is success' do
+ let(:deployment) { create(:deployment, :success) }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when deployment status is failed' do
+ let(:deployment) { create(:deployment, :failed) }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
+ describe '#status_name' do
+ subject { deployment.status_name }
+
+ context 'when deployment status is success' do
+ let(:deployment) { create(:deployment, :success) }
+
+ it { is_expected.to eq(:success) }
+ end
+
+ context 'when deployment status is failed' do
+ let(:deployment) { create(:deployment, :failed) }
+
+ it { is_expected.to eq(:failed) }
+ end
+ end
+
+ describe '#finished_at' do
+ subject { deployment.finished_at }
+
+ context 'when deployment status is created' do
+ let(:deployment) { create(:deployment) }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when deployment status is success' do
+ let(:deployment) { create(:deployment, :success) }
+
+ it { is_expected.to eq(deployment.read_attribute(:finished_at)) }
+ end
- it 'invalidates the environment etag cache' do
- old_value = store.get(environment.etag_cache_key)
+ context 'when deployment status is success' do
+ let(:deployment) { create(:deployment, :success, finished_at: nil) }
- create(:deployment, environment: environment)
+ before do
+ deployment.update_column(:finished_at, nil)
+ end
- expect(store.get(environment.etag_cache_key)).not_to eq(old_value)
+ it { is_expected.to eq(deployment.read_attribute(:created_at)) }
+ end
+
+ context 'when deployment status is running' do
+ let(:deployment) { create(:deployment, :running) }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ describe '#deployed_at' do
+ subject { deployment.deployed_at }
+
+ context 'when deployment status is created' do
+ let(:deployment) { create(:deployment) }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'when deployment status is success' do
+ let(:deployment) { create(:deployment, :success) }
+
+ it { is_expected.to eq(deployment.read_attribute(:finished_at)) }
+ end
+
+ context 'when deployment status is running' do
+ let(:deployment) { create(:deployment, :running) }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ describe 'scopes' do
+ describe 'last_for_environment' do
+ let(:production) { create(:environment) }
+ let(:staging) { create(:environment) }
+ let(:testing) { create(:environment) }
+
+ let!(:deployments) do
+ [
+ create(:deployment, environment: production),
+ create(:deployment, environment: staging),
+ create(:deployment, environment: production)
+ ]
+ end
+
+ it 'retrieves last deployments for environments' do
+ last_deployments = described_class.last_for_environment([staging, production, testing])
+
+ expect(last_deployments.size).to eq(2)
+ expect(last_deployments).to match_array(deployments.last(2))
+ end
end
end
@@ -73,7 +272,7 @@ describe Deployment do
end
describe '#metrics' do
- let(:deployment) { create(:deployment) }
+ let(:deployment) { create(:deployment, :success) }
let(:prometheus_adapter) { double('prometheus_adapter', can_query?: true) }
subject { deployment.metrics }
@@ -102,7 +301,7 @@ describe Deployment do
describe '#additional_metrics' do
let(:project) { create(:project, :repository) }
- let(:deployment) { create(:deployment, project: project) }
+ let(:deployment) { create(:deployment, :succeed, project: project) }
subject { deployment.additional_metrics }
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index c65e0b81451..9a3f1f1c5a1 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -53,6 +53,25 @@ describe Environment do
end
end
+ describe '.with_deployment' do
+ subject { described_class.with_deployment(sha) }
+
+ let(:environment) { create(:environment) }
+ let(:sha) { RepoHelpers.sample_commit.id }
+
+ context 'when deployment has the specified sha' do
+ let!(:deployment) { create(:deployment, environment: environment, sha: sha) }
+
+ it { is_expected.to eq([environment]) }
+ end
+
+ context 'when deployment does not have the specified sha' do
+ let!(:deployment) { create(:deployment, environment: environment, sha: 'abc') }
+
+ it { is_expected.to be_empty }
+ end
+ end
+
describe '#folder_name' do
context 'when it is inside a folder' do
subject(:environment) do
@@ -95,7 +114,7 @@ describe Environment do
context 'with a last deployment' do
let!(:deployment) do
- create(:deployment, environment: environment, sha: project.commit('master').id)
+ create(:deployment, :success, environment: environment, sha: project.commit('master').id)
end
context 'in the same branch' do
@@ -136,8 +155,8 @@ describe Environment do
describe '#first_deployment_for' do
let(:project) { create(:project, :repository) }
- let!(:deployment) { create(:deployment, environment: environment, ref: commit.parent.id) }
- let!(:deployment1) { create(:deployment, environment: environment, ref: commit.id) }
+ let!(:deployment) { create(:deployment, :succeed, environment: environment, ref: commit.parent.id) }
+ let!(:deployment1) { create(:deployment, :succeed, environment: environment, ref: commit.id) }
let(:head_commit) { project.commit }
let(:commit) { project.commit.parent }
@@ -181,7 +200,8 @@ describe Environment do
let(:build) { create(:ci_build) }
let!(:deployment) do
- create(:deployment, environment: environment,
+ create(:deployment, :success,
+ environment: environment,
deployable: build,
on_stop: 'close_app')
end
@@ -249,7 +269,8 @@ describe Environment do
let(:build) { create(:ci_build, pipeline: pipeline) }
let!(:deployment) do
- create(:deployment, environment: environment,
+ create(:deployment, :success,
+ environment: environment,
deployable: build,
on_stop: 'close_app')
end
@@ -304,7 +325,7 @@ describe Environment do
context 'when last deployment to environment is the most recent one' do
before do
- create(:deployment, environment: environment, ref: 'feature')
+ create(:deployment, :success, environment: environment, ref: 'feature')
end
it { is_expected.to be true }
@@ -312,8 +333,8 @@ describe Environment do
context 'when last deployment to environment is not the most recent' do
before do
- create(:deployment, environment: environment, ref: 'feature')
- create(:deployment, environment: environment, ref: 'master')
+ create(:deployment, :success, environment: environment, ref: 'feature')
+ create(:deployment, :success, environment: environment, ref: 'master')
end
it { is_expected.to be false }
@@ -321,7 +342,7 @@ describe Environment do
end
describe '#actions_for' do
- let(:deployment) { create(:deployment, environment: environment) }
+ let(:deployment) { create(:deployment, :success, environment: environment) }
let(:pipeline) { deployment.deployable.pipeline }
let!(:review_action) { create(:ci_build, :manual, name: 'review-apps', pipeline: pipeline, environment: 'review/$CI_COMMIT_REF_NAME' )}
let!(:production_action) { create(:ci_build, :manual, name: 'production', pipeline: pipeline, environment: 'production' )}
@@ -331,14 +352,78 @@ describe Environment do
end
end
+ describe '.deployments' do
+ subject { environment.deployments }
+
+ context 'when there is a deployment record with created status' do
+ let(:deployment) { create(:deployment, :created, environment: environment) }
+
+ it 'does not return the record' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'when there is a deployment record with running status' do
+ let(:deployment) { create(:deployment, :running, environment: environment) }
+
+ it 'does not return the record' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'when there is a deployment record with success status' do
+ let(:deployment) { create(:deployment, :success, environment: environment) }
+
+ it 'returns the record' do
+ is_expected.to eq([deployment])
+ end
+ end
+ end
+
+ describe '.last_deployment' do
+ subject { environment.last_deployment }
+
+ before do
+ allow_any_instance_of(Deployment).to receive(:create_ref)
+ end
+
+ context 'when there is an old deployment record' do
+ let!(:previous_deployment) { create(:deployment, :success, environment: environment) }
+
+ context 'when there is a deployment record with created status' do
+ let!(:deployment) { create(:deployment, environment: environment) }
+
+ it 'returns the previous deployment' do
+ is_expected.to eq(previous_deployment)
+ end
+ end
+
+ context 'when there is a deployment record with running status' do
+ let!(:deployment) { create(:deployment, :running, environment: environment) }
+
+ it 'returns the previous deployment' do
+ is_expected.to eq(previous_deployment)
+ end
+ end
+
+ context 'when there is a deployment record with success status' do
+ let!(:deployment) { create(:deployment, :success, environment: environment) }
+
+ it 'returns the latest successful deployment' do
+ is_expected.to eq(deployment)
+ end
+ end
+ end
+ end
+
describe '#has_terminals?' do
subject { environment.has_terminals? }
- context 'when the enviroment is available' do
+ context 'when the environment is available' do
context 'with a deployment service' do
shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
context 'and a deployment' do
- let!(:deployment) { create(:deployment, environment: environment) }
+ let!(:deployment) { create(:deployment, :success, environment: environment) }
it { is_expected.to be_truthy }
end
@@ -447,7 +532,7 @@ describe Environment do
describe '#has_metrics?' do
subject { environment.has_metrics? }
- context 'when the enviroment is available' do
+ context 'when the environment is available' do
context 'with a deployment service' do
let(:project) { create(:prometheus_project) }
@@ -456,8 +541,8 @@ describe Environment do
it { is_expected.to be_truthy }
end
- context 'but no deployments' do
- it { is_expected.to be_falsy }
+ context 'and no deployments' do
+ it { is_expected.to be_truthy }
end
end
@@ -504,39 +589,6 @@ describe Environment do
end
end
- describe '#has_metrics?' do
- subject { environment.has_metrics? }
-
- context 'when the enviroment is available' do
- context 'with a deployment service' do
- let(:project) { create(:prometheus_project) }
-
- context 'and a deployment' do
- let!(:deployment) { create(:deployment, environment: environment) }
- it { is_expected.to be_truthy }
- end
-
- context 'but no deployments' do
- it { is_expected.to be_falsy }
- end
- end
-
- context 'without a monitoring service' do
- it { is_expected.to be_falsy }
- end
- end
-
- context 'when the environment is unavailable' do
- let(:project) { create(:prometheus_project) }
-
- before do
- environment.stop
- end
-
- it { is_expected.to be_falsy }
- end
- end
-
describe '#additional_metrics' do
let(:project) { create(:prometheus_project) }
subject { environment.additional_metrics }
diff --git a/spec/models/environment_status_spec.rb b/spec/models/environment_status_spec.rb
new file mode 100644
index 00000000000..9da16dea929
--- /dev/null
+++ b/spec/models/environment_status_spec.rb
@@ -0,0 +1,194 @@
+require 'spec_helper'
+
+describe EnvironmentStatus do
+ include ProjectForksHelper
+
+ let(:deployment) { create(:deployment, :succeed, :review_app) }
+ let(:environment) { deployment.environment }
+ let(:project) { deployment.project }
+ let(:merge_request) { create(:merge_request, :deployed_review_app, deployment: deployment) }
+ let(:sha) { deployment.sha }
+
+ subject(:environment_status) { described_class.new(environment, merge_request, sha) }
+
+ it { is_expected.to delegate_method(:id).to(:environment) }
+ it { is_expected.to delegate_method(:name).to(:environment) }
+ it { is_expected.to delegate_method(:project).to(:environment) }
+ it { is_expected.to delegate_method(:deployed_at).to(:deployment) }
+ it { is_expected.to delegate_method(:status).to(:deployment) }
+
+ describe '#project' do
+ subject { environment_status.project }
+
+ it { is_expected.to eq(project) }
+ end
+
+ describe '#merge_request' do
+ subject { environment_status.merge_request }
+
+ it { is_expected.to eq(merge_request) }
+ end
+
+ describe '#deployment' do
+ subject { environment_status.deployment }
+
+ it { is_expected.to eq(deployment) }
+ end
+
+ # $ git diff --stat pages-deploy-target...pages-deploy
+ # .gitlab/route-map.yml | 5 +++++
+ # files/html/500.html | 13 -------------
+ # files/html/page.html | 3 +++
+ # files/js/application.js | 3 +++
+ # files/markdown/ruby-style-guide.md | 4 ++++
+ # pages-deploy.txt | 1 +
+ #
+ # $ cat .gitlab/route-map.yml
+ # - source: /files\/markdown\/(.+)\.md$/
+ # public: '\1.html'
+ #
+ # - source: /files\/(.+)/
+ # public: '\1'
+ describe '#changes' do
+ it 'contains only added and modified public pages' do
+ expect(environment_status.changes).to contain_exactly(
+ {
+ path: 'ruby-style-guide.html',
+ external_url: "#{environment.external_url}/ruby-style-guide.html"
+ }, {
+ path: 'html/page.html',
+ external_url: "#{environment.external_url}/html/page.html"
+ }
+ )
+ end
+ end
+
+ describe '.for_merge_request' do
+ let(:admin) { create(:admin) }
+ let(:pipeline) { create(:ci_pipeline, sha: sha) }
+
+ it 'is based on merge_request.diff_head_sha' do
+ expect(merge_request).to receive(:diff_head_sha)
+ expect(merge_request).not_to receive(:merge_commit_sha)
+
+ described_class.for_merge_request(merge_request, admin)
+ end
+ end
+
+ describe '.after_merge_request' do
+ let(:admin) { create(:admin) }
+ let(:pipeline) { create(:ci_pipeline, sha: sha) }
+
+ before do
+ merge_request.mark_as_merged!
+ end
+
+ it 'is based on merge_request.merge_commit_sha' do
+ expect(merge_request).to receive(:merge_commit_sha)
+ expect(merge_request).not_to receive(:diff_head_sha)
+
+ described_class.after_merge_request(merge_request, admin)
+ end
+ end
+
+ describe '.build_environments_status' do
+ subject { described_class.send(:build_environments_status, merge_request, user, pipeline) }
+
+ let!(:build) { create(:ci_build, :deploy_to_production, pipeline: pipeline) }
+ let(:environment) { build.deployment.environment }
+ let(:user) { project.owner }
+
+ context 'when environment is created on a forked project' do
+ let(:project) { create(:project, :repository) }
+ let(:forked) { fork_project(project, user, repository: true) }
+ let(:sha) { forked.commit.sha }
+ let(:pipeline) { create(:ci_pipeline, sha: sha, project: forked) }
+
+ let(:merge_request) do
+ create(:merge_request,
+ source_project: forked,
+ target_project: project,
+ target_branch: 'master',
+ head_pipeline: pipeline)
+ end
+
+ it 'returns environment status' do
+ expect(subject.count).to eq(1)
+ expect(subject[0].environment).to eq(environment)
+ expect(subject[0].merge_request).to eq(merge_request)
+ expect(subject[0].sha).to eq(sha)
+ end
+ end
+
+ context 'when environment is created on a target project' do
+ let(:project) { create(:project, :repository) }
+ let(:sha) { project.commit.sha }
+ let(:pipeline) { create(:ci_pipeline, sha: sha, project: project) }
+
+ let(:merge_request) do
+ create(:merge_request,
+ source_project: project,
+ source_branch: 'feature',
+ target_project: project,
+ target_branch: 'master',
+ head_pipeline: pipeline)
+ end
+
+ it 'returns environment status' do
+ expect(subject.count).to eq(1)
+ expect(subject[0].environment).to eq(environment)
+ expect(subject[0].merge_request).to eq(merge_request)
+ expect(subject[0].sha).to eq(sha)
+ end
+
+ context 'when the build stops an environment' do
+ let!(:build) { create(:ci_build, :stop_review_app, pipeline: pipeline) }
+
+ it 'does not return environment status' do
+ expect(subject.count).to eq(0)
+ end
+ end
+
+ context 'when user does not have a permission to see the environment' do
+ let(:user) { create(:user) }
+
+ it 'does not return environment status' do
+ expect(subject.count).to eq(0)
+ end
+ end
+
+ context 'when multiple deployments with the same SHA in different environments' do
+ let(:pipeline2) { create(:ci_pipeline, sha: sha, project: project) }
+ let!(:build2) { create(:ci_build, :start_review_app, pipeline: pipeline2) }
+
+ it 'returns deployments related to the head pipeline' do
+ expect(subject.count).to eq(1)
+ expect(subject[0].environment).to eq(environment)
+ expect(subject[0].merge_request).to eq(merge_request)
+ expect(subject[0].sha).to eq(sha)
+ end
+ end
+
+ context 'when multiple deployments in the same pipeline for the same environments' do
+ let!(:build2) { create(:ci_build, :deploy_to_production, pipeline: pipeline) }
+
+ it 'returns unique entries' do
+ expect(subject.count).to eq(1)
+ expect(subject[0].environment).to eq(environment)
+ expect(subject[0].merge_request).to eq(merge_request)
+ expect(subject[0].sha).to eq(sha)
+ end
+ end
+
+ context 'when environment is stopped' do
+ before do
+ environment.stop!
+ end
+
+ it 'does not return environment status' do
+ expect(subject.count).to eq(0)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/event_collection_spec.rb b/spec/models/event_collection_spec.rb
index e0a87c18cc7..6078f429bdc 100644
--- a/spec/models/event_collection_spec.rb
+++ b/spec/models/event_collection_spec.rb
@@ -41,7 +41,7 @@ describe EventCollection do
end
it 'allows filtering of events using an EventFilter' do
- filter = EventFilter.new(EventFilter.issue)
+ filter = EventFilter.new(EventFilter::ISSUE)
events = described_class.new(projects, filter: filter).to_a
expect(events.length).to eq(1)
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index c1eac4fa489..81748681528 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -148,9 +148,14 @@ describe Event do
let(:admin) { create(:admin) }
let(:issue) { create(:issue, project: project, author: author, assignees: [assignee]) }
let(:confidential_issue) { create(:issue, :confidential, project: project, author: author, assignees: [assignee]) }
+ let(:project_snippet) { create(:project_snippet, :public, project: project, author: author) }
+ let(:personal_snippet) { create(:personal_snippet, :public, author: author) }
let(:note_on_commit) { create(:note_on_commit, project: project) }
let(:note_on_issue) { create(:note_on_issue, noteable: issue, project: project) }
let(:note_on_confidential_issue) { create(:note_on_issue, noteable: confidential_issue, project: project) }
+ let(:note_on_project_snippet) { create(:note_on_project_snippet, author: author, noteable: project_snippet, project: project) }
+ let(:note_on_personal_snippet) { create(:note_on_personal_snippet, author: author, noteable: personal_snippet, project: nil) }
+ let(:milestone_on_project) { create(:milestone, project: project) }
let(:event) { described_class.new(project: project, target: target, author_id: author.id) }
before do
@@ -268,6 +273,125 @@ describe Event do
end
end
end
+
+ context 'milestone event' do
+ let(:target) { milestone_on_project }
+
+ it do
+ expect(event.visible_to_user?(nil)).to be_truthy
+ expect(event.visible_to_user?(non_member)).to be_truthy
+ expect(event.visible_to_user?(member)).to be_truthy
+ expect(event.visible_to_user?(guest)).to be_truthy
+ expect(event.visible_to_user?(admin)).to be_truthy
+ end
+
+ context 'on public project with private issue tracker and merge requests' do
+ let(:project) { create(:project, :public, :issues_private, :merge_requests_private) }
+
+ it do
+ expect(event.visible_to_user?(nil)).to be_falsy
+ expect(event.visible_to_user?(non_member)).to be_falsy
+ expect(event.visible_to_user?(member)).to be_truthy
+ expect(event.visible_to_user?(guest)).to be_truthy
+ expect(event.visible_to_user?(admin)).to be_truthy
+ end
+ end
+
+ context 'on private project' do
+ let(:project) { create(:project, :private) }
+
+ it do
+ expect(event.visible_to_user?(nil)).to be_falsy
+ expect(event.visible_to_user?(non_member)).to be_falsy
+ expect(event.visible_to_user?(member)).to be_truthy
+ expect(event.visible_to_user?(guest)).to be_truthy
+ expect(event.visible_to_user?(admin)).to be_truthy
+ end
+ end
+ end
+
+ context 'project snippet note event' do
+ let(:target) { note_on_project_snippet }
+
+ it do
+ expect(event.visible_to_user?(nil)).to be_truthy
+ expect(event.visible_to_user?(non_member)).to be_truthy
+ expect(event.visible_to_user?(author)).to be_truthy
+ expect(event.visible_to_user?(member)).to be_truthy
+ expect(event.visible_to_user?(guest)).to be_truthy
+ expect(event.visible_to_user?(admin)).to be_truthy
+ end
+
+ context 'on public project with private snippets' do
+ let(:project) { create(:project, :public, :snippets_private) }
+
+ it do
+ expect(event.visible_to_user?(nil)).to be_falsy
+ expect(event.visible_to_user?(non_member)).to be_falsy
+
+ # Normally, we'd expect the author of a comment to be able to view it.
+ # However, this doesn't seem to be the case for comments on snippets.
+ expect(event.visible_to_user?(author)).to be_falsy
+
+ expect(event.visible_to_user?(member)).to be_truthy
+ expect(event.visible_to_user?(guest)).to be_truthy
+ expect(event.visible_to_user?(admin)).to be_truthy
+ end
+ end
+
+ context 'on private project' do
+ let(:project) { create(:project, :private) }
+
+ it do
+ expect(event.visible_to_user?(nil)).to be_falsy
+ expect(event.visible_to_user?(non_member)).to be_falsy
+
+ # Normally, we'd expect the author of a comment to be able to view it.
+ # However, this doesn't seem to be the case for comments on snippets.
+ expect(event.visible_to_user?(author)).to be_falsy
+
+ expect(event.visible_to_user?(member)).to be_truthy
+ expect(event.visible_to_user?(guest)).to be_truthy
+ expect(event.visible_to_user?(admin)).to be_truthy
+ end
+ end
+ end
+
+ context 'personal snippet note event' do
+ let(:target) { note_on_personal_snippet }
+
+ it do
+ expect(event.visible_to_user?(nil)).to be_truthy
+ expect(event.visible_to_user?(non_member)).to be_truthy
+ expect(event.visible_to_user?(author)).to be_truthy
+ expect(event.visible_to_user?(admin)).to be_truthy
+ end
+
+ context 'on internal snippet' do
+ let(:personal_snippet) { create(:personal_snippet, :internal, author: author) }
+
+ it do
+ expect(event.visible_to_user?(nil)).to be_falsy
+ expect(event.visible_to_user?(non_member)).to be_truthy
+ expect(event.visible_to_user?(author)).to be_truthy
+ expect(event.visible_to_user?(admin)).to be_truthy
+ end
+ end
+
+ context 'on private snippet' do
+ let(:personal_snippet) { create(:personal_snippet, :private, author: author) }
+
+ it do
+ expect(event.visible_to_user?(nil)).to be_falsy
+ expect(event.visible_to_user?(non_member)).to be_falsy
+ expect(event.visible_to_user?(author)).to be_truthy
+
+ # It is very unexpected that a private personal snippet is not visible
+ # to an instance administrator. This should be fixed in the future.
+ expect(event.visible_to_user?(admin)).to be_falsy
+ end
+ end
+ end
end
describe '.limit_recent' do
diff --git a/spec/models/forked_project_link_spec.rb b/spec/models/forked_project_link_spec.rb
deleted file mode 100644
index 32e33e8f42f..00000000000
--- a/spec/models/forked_project_link_spec.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-require 'spec_helper'
-
-describe ForkedProjectLink, "add link on fork" do
- include ProjectForksHelper
-
- let(:project_from) { create(:project, :repository) }
- let(:project_to) { fork_project(project_from, user) }
- let(:user) { create(:user) }
-
- before do
- project_from.add_reporter(user)
- end
-
- it 'project_from knows its forks' do
- _ = project_to
-
- expect(project_from.forks.count).to eq(1)
- end
-
- it "project_to knows it is forked" do
- expect(project_to.forked?).to be_truthy
- end
-
- it "project knows who it is forked from" do
- expect(project_to.forked_from_project).to eq(project_from)
- end
-
- context 'project_to is pending_delete' do
- before do
- project_to.update!(pending_delete: true)
- end
-
- it { expect(project_from.forks.count).to eq(0) }
- end
-
- context 'project_from is pending_delete' do
- before do
- project_from.update!(pending_delete: true)
- end
-
- it { expect(project_to.forked_from_project).to be_nil }
- end
-
- describe '#forked?' do
- let(:project_to) { create(:project, :repository, forked_project_link: forked_project_link) }
- let(:forked_project_link) { create(:forked_project_link) }
-
- before do
- forked_project_link.forked_from_project = project_from
- forked_project_link.forked_to_project = project_to
- forked_project_link.save!
- end
-
- it "project_to knows it is forked" do
- expect(project_to.forked?).to be_truthy
- end
-
- it "project_from is not forked" do
- expect(project_from.forked?).to be_falsey
- end
-
- it "project_to.destroy destroys fork_link" do
- project_to.destroy
-
- expect(ForkedProjectLink.exists?(id: forked_project_link.id)).to eq(false)
- end
- end
-end
diff --git a/spec/models/global_milestone_spec.rb b/spec/models/global_milestone_spec.rb
index ab58f5c5021..b6355455c1d 100644
--- a/spec/models/global_milestone_spec.rb
+++ b/spec/models/global_milestone_spec.rb
@@ -92,41 +92,6 @@ describe GlobalMilestone do
end
end
- describe '.states_count' do
- context 'when the projects have milestones' do
- before do
- create(:closed_milestone, title: 'Active Group Milestone', project: project3)
- create(:active_milestone, title: 'Active Group Milestone', project: project1)
- create(:active_milestone, title: 'Active Group Milestone', project: project2)
- create(:closed_milestone, title: 'Closed Group Milestone', project: project1)
- create(:closed_milestone, title: 'Closed Group Milestone', project: project2)
- create(:closed_milestone, title: 'Closed Group Milestone', project: project3)
- end
-
- it 'returns the quantity of global milestones in each possible state' do
- expected_count = { opened: 1, closed: 2, all: 2 }
-
- count = described_class.states_count(Project.all)
-
- expect(count).to eq(expected_count)
- end
- end
-
- context 'when the projects do not have milestones' do
- before do
- project1
- end
-
- it 'returns 0 as the quantity of global milestones in each state' do
- expected_count = { opened: 0, closed: 0, all: 0 }
-
- count = described_class.states_count(Project.all)
-
- expect(count).to eq(expected_count)
- end
- end
- end
-
describe '#initialize' do
let(:milestone1_project1) { create(:milestone, title: "Milestone v1.2", project: project1) }
let(:milestone1_project2) { create(:milestone, title: "Milestone v1.2", project: project2) }
diff --git a/spec/models/gpg_signature_spec.rb b/spec/models/gpg_signature_spec.rb
index 0136bb61c07..cdd7dea2064 100644
--- a/spec/models/gpg_signature_spec.rb
+++ b/spec/models/gpg_signature_spec.rb
@@ -8,6 +8,8 @@ RSpec.describe GpgSignature do
let(:gpg_key) { create(:gpg_key) }
let(:gpg_key_subkey) { create(:gpg_key_subkey) }
+ it_behaves_like 'having unique enum values'
+
describe 'associations' do
it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:gpg_key) }
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 0729eb99e78..ada00f03928 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -19,6 +19,8 @@ describe Group do
it { is_expected.to have_one(:chat_team) }
it { is_expected.to have_many(:custom_attributes).class_name('GroupCustomAttribute') }
it { is_expected.to have_many(:badges).class_name('GroupBadge') }
+ it { is_expected.to have_many(:cluster_groups).class_name('Clusters::Group') }
+ it { is_expected.to have_many(:clusters).class_name('Clusters::Cluster') }
describe '#members & #requesters' do
let(:requester) { create(:user) }
@@ -169,22 +171,42 @@ describe Group do
end
end
- describe '.visible_to_user' do
- let!(:group) { create(:group) }
- let!(:user) { create(:user) }
+ describe '.public_or_visible_to_user' do
+ let!(:private_group) { create(:group, :private) }
+ let!(:internal_group) { create(:group, :internal) }
- subject { described_class.visible_to_user(user) }
+ subject { described_class.public_or_visible_to_user(user) }
- describe 'when the user has access to a group' do
- before do
- group.add_user(user, Gitlab::Access::MAINTAINER)
- end
+ context 'when user is nil' do
+ let!(:user) { nil }
- it { is_expected.to eq([group]) }
+ it { is_expected.to match_array([group]) }
end
- describe 'when the user does not have access to any groups' do
- it { is_expected.to eq([]) }
+ context 'when user' do
+ let!(:user) { create(:user) }
+
+ context 'when user does not have access to any private group' do
+ it { is_expected.to match_array([internal_group, group]) }
+ end
+
+ context 'when user is a member of private group' do
+ before do
+ private_group.add_user(user, Gitlab::Access::DEVELOPER)
+ end
+
+ it { is_expected.to match_array([private_group, internal_group, group]) }
+ end
+
+ context 'when user is a member of private subgroup', :postgresql do
+ let!(:private_subgroup) { create(:group, :private, parent: private_group) }
+
+ before do
+ private_subgroup.add_user(user, Gitlab::Access::DEVELOPER)
+ end
+
+ it { is_expected.to match_array([private_subgroup, internal_group, group]) }
+ end
end
end
@@ -631,10 +653,10 @@ describe Group do
end
end
- describe '#secret_variables_for' do
+ describe '#ci_variables_for' do
let(:project) { create(:project, group: group) }
- let!(:secret_variable) do
+ let!(:ci_variable) do
create(:ci_group_variable, value: 'secret', group: group)
end
@@ -642,11 +664,11 @@ describe Group do
create(:ci_group_variable, :protected, value: 'protected', group: group)
end
- subject { group.secret_variables_for('ref', project) }
+ subject { group.ci_variables_for('ref', project) }
shared_examples 'ref is protected' do
it 'contains all the variables' do
- is_expected.to contain_exactly(secret_variable, protected_variable)
+ is_expected.to contain_exactly(ci_variable, protected_variable)
end
end
@@ -656,8 +678,8 @@ describe Group do
default_branch_protection: Gitlab::Access::PROTECTION_NONE)
end
- it 'contains only the secret variables' do
- is_expected.to contain_exactly(secret_variable)
+ it 'contains only the CI variables' do
+ is_expected.to contain_exactly(ci_variable)
end
end
@@ -690,9 +712,9 @@ describe Group do
end
it 'returns all variables belong to the group and parent groups' do
- expected_array1 = [protected_variable, secret_variable]
+ expected_array1 = [protected_variable, ci_variable]
expected_array2 = [variable_child, variable_child_2, variable_child_3]
- got_array = group_child_3.secret_variables_for('ref', project).to_a
+ got_array = group_child_3.ci_variables_for('ref', project).to_a
expect(got_array.shift(2)).to contain_exactly(*expected_array1)
expect(got_array).to eq(expected_array2)
diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb
index a4181631f01..a308ac6e33a 100644
--- a/spec/models/hooks/web_hook_spec.rb
+++ b/spec/models/hooks/web_hook_spec.rb
@@ -57,6 +57,12 @@ describe WebHook do
end
end
+ describe 'encrypted attributes' do
+ subject { described_class.encrypted_attributes.keys }
+
+ it { is_expected.to contain_exactly(:token, :url) }
+ end
+
describe 'execute' do
let(:data) { { key: 'value' } }
let(:hook_name) { 'project hook' }
diff --git a/spec/models/instance_configuration_spec.rb b/spec/models/instance_configuration_spec.rb
index 34db94920f3..cb3d6c7cda2 100644
--- a/spec/models/instance_configuration_spec.rb
+++ b/spec/models/instance_configuration_spec.rb
@@ -1,11 +1,11 @@
require 'spec_helper'
-RSpec.describe InstanceConfiguration do
+describe InstanceConfiguration do
context 'without cache' do
describe '#settings' do
describe '#ssh_algorithms_hashes' do
- let(:md5) { '54:e0:f8:70:d6:4f:4c:b1:b3:02:44:77:cf:cd:0d:fc' }
- let(:sha256) { '9327f0d15a48c4d9f6a3aee65a1825baf9a3412001c98169c5fd022ac27762fc' }
+ let(:md5) { '5a:65:6c:4d:d4:4c:6d:e6:59:25:b8:cf:ba:34:e7:64' }
+ let(:sha256) { 'SHA256:2KJDT7xf2i68mBgJ3TVsjISntg4droLbXYLfQj0VvSY' }
it 'does not return anything if file does not exist' do
stub_pub_file(exist: false)
diff --git a/spec/models/internal_id_spec.rb b/spec/models/internal_id_spec.rb
index f2aad455d5f..4696341c05f 100644
--- a/spec/models/internal_id_spec.rb
+++ b/spec/models/internal_id_spec.rb
@@ -7,6 +7,8 @@ describe InternalId do
let(:scope) { { project: project } }
let(:init) { ->(s) { s.project.issues.size } }
+ it_behaves_like 'having unique enum values'
+
context 'validations' do
it { is_expected.to validate_presence_of(:usage) }
end
@@ -65,7 +67,8 @@ describe InternalId do
context 'with an insufficient schema version' do
before do
described_class.reset_column_information
- expect(ActiveRecord::Migrator).to receive(:current_version).and_return(InternalId::REQUIRED_SCHEMA_VERSION - 1)
+ # Project factory will also call the current_version
+ expect(ActiveRecord::Migrator).to receive(:current_version).twice.and_return(InternalId::REQUIRED_SCHEMA_VERSION - 1)
end
let(:init) { double('block') }
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index c21d85fb2a4..6f900a60213 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -84,15 +84,32 @@ describe Issue do
end
end
- describe '#closed_at' do
- it 'sets closed_at to Time.now when issue is closed' do
- issue = create(:issue, state: 'opened')
+ describe '#close' do
+ subject(:issue) { create(:issue, state: 'opened') }
- expect(issue.closed_at).to be_nil
+ it 'sets closed_at to Time.now when an issue is closed' do
+ expect { issue.close }.to change { issue.closed_at }.from(nil)
+ end
+
+ it 'changes the state to closed' do
+ expect { issue.close }.to change { issue.state }.from('opened').to('closed')
+ end
+ end
+
+ describe '#reopen' do
+ let(:user) { create(:user) }
+ let(:issue) { create(:issue, state: 'closed', closed_at: Time.now, closed_by: user) }
- issue.close
+ it 'sets closed_at to nil when an issue is reopend' do
+ expect { issue.reopen }.to change { issue.closed_at }.to(nil)
+ end
+
+ it 'sets closed_by to nil when an issue is reopend' do
+ expect { issue.reopen }.to change { issue.closed_by }.from(user).to(nil)
+ end
- expect(issue.closed_at).to be_present
+ it 'changes the state to opened' do
+ expect { issue.reopen }.to change { issue.state }.from('closed').to('opened')
end
end
@@ -251,45 +268,6 @@ describe Issue do
end
end
- describe '#related_branches' do
- let(:user) { create(:admin) }
-
- before do
- allow(subject.project.repository).to receive(:branch_names)
- .and_return(["mpempe", "#{subject.iid}mepmep", subject.to_branch_name, "#{subject.iid}-branch"])
-
- # Without this stub, the `create(:merge_request)` above fails because it can't find
- # the source branch. This seems like a reasonable compromise, in comparison with
- # setting up a full repo here.
- allow_any_instance_of(MergeRequest).to receive(:create_merge_request_diff)
- end
-
- it "selects the right branches when there are no referenced merge requests" do
- expect(subject.related_branches(user)).to eq([subject.to_branch_name, "#{subject.iid}-branch"])
- end
-
- it "selects the right branches when there is a referenced merge request" do
- merge_request = create(:merge_request, { description: "Closes ##{subject.iid}",
- source_project: subject.project,
- source_branch: "#{subject.iid}-branch" })
- merge_request.create_cross_references!(user)
-
- referenced_merge_requests = Issues::ReferencedMergeRequestsService
- .new(subject.project, user)
- .referenced_merge_requests(subject)
-
- expect(referenced_merge_requests).not_to be_empty
- expect(subject.related_branches(user)).to eq([subject.to_branch_name])
- end
-
- it 'excludes stable branches from the related branches' do
- allow(subject.project.repository).to receive(:branch_names)
- .and_return(["#{subject.iid}-0-stable"])
-
- expect(subject.related_branches(user)).to eq []
- end
- end
-
describe '#suggested_branch_name' do
let(:repository) { double }
diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb
index 99670af786a..3fc6c06b7fa 100644
--- a/spec/models/label_spec.rb
+++ b/spec/models/label_spec.rb
@@ -155,4 +155,40 @@ describe Label do
expect(described_class.search('feature')).to be_empty
end
end
+
+ describe '.subscribed_by' do
+ let!(:user) { create(:user) }
+ let!(:label) { create(:label) }
+ let!(:label2) { create(:label) }
+
+ before do
+ label.subscribe(user)
+ end
+
+ it 'returns subscribed labels' do
+ expect(described_class.subscribed_by(user.id)).to eq([label])
+ end
+
+ it 'returns nothing' do
+ expect(described_class.subscribed_by(0)).to be_empty
+ end
+ end
+
+ describe '.optionally_subscribed_by' do
+ let!(:user) { create(:user) }
+ let!(:label) { create(:label) }
+ let!(:label2) { create(:label) }
+
+ before do
+ label.subscribe(user)
+ end
+
+ it 'returns subscribed labels' do
+ expect(described_class.optionally_subscribed_by(user.id)).to eq([label])
+ end
+
+ it 'returns all labels if user_id is nil' do
+ expect(described_class.optionally_subscribed_by(nil)).to match_array([label, label2])
+ end
+ end
end
diff --git a/spec/models/lfs_object_spec.rb b/spec/models/lfs_object_spec.rb
index 6e35511e848..3f929710862 100644
--- a/spec/models/lfs_object_spec.rb
+++ b/spec/models/lfs_object_spec.rb
@@ -2,19 +2,13 @@ require 'spec_helper'
describe LfsObject do
describe '#local_store?' do
- it 'returns true when file_store is nil' do
- subject.file_store = nil
-
- expect(subject.local_store?).to eq true
- end
-
it 'returns true when file_store is equal to LfsObjectUploader::Store::LOCAL' do
subject.file_store = LfsObjectUploader::Store::LOCAL
expect(subject.local_store?).to eq true
end
- it 'returns false whe file_store is equal to LfsObjectUploader::Store::REMOTE' do
+ it 'returns false when file_store is equal to LfsObjectUploader::Store::REMOTE' do
subject.file_store = LfsObjectUploader::Store::REMOTE
expect(subject.local_store?).to eq false
@@ -83,19 +77,6 @@ describe LfsObject do
describe 'file is being stored' do
let(:lfs_object) { create(:lfs_object, :with_file) }
- context 'when object has nil store' do
- before do
- lfs_object.update_column(:file_store, nil)
- lfs_object.reload
- end
-
- it 'is stored locally' do
- expect(lfs_object.file_store).to be(nil)
- expect(lfs_object.file).to be_file_storage
- expect(lfs_object.file.object_store).to eq(ObjectStorage::Store::LOCAL)
- end
- end
-
context 'when existing object has local store' do
it 'is stored locally' do
expect(lfs_object.file_store).to be(ObjectStorage::Store::LOCAL)
diff --git a/spec/models/license_template_spec.rb b/spec/models/license_template_spec.rb
index c633e1908d4..dd912eefac1 100644
--- a/spec/models/license_template_spec.rb
+++ b/spec/models/license_template_spec.rb
@@ -54,6 +54,6 @@ describe LicenseTemplate do
end
def build_template(content)
- described_class.new(id: 'foo', name: 'foo', category: :Other, content: content)
+ described_class.new(key: 'foo', name: 'foo', category: :Other, content: content)
end
end
diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb
index a6cc01bea5f..a51580f8292 100644
--- a/spec/models/list_spec.rb
+++ b/spec/models/list_spec.rb
@@ -1,6 +1,8 @@
require 'rails_helper'
describe List do
+ it_behaves_like 'having unique enum values'
+
describe 'relationships' do
it { is_expected.to belong_to(:board) }
it { is_expected.to belong_to(:label) }
@@ -22,13 +24,13 @@ describe List do
end
describe '#destroy' do
- it 'can be destroyed when when list_type is set to label' do
+ it 'can be destroyed when list_type is set to label' do
subject = create(:list)
expect(subject.destroy).to be_truthy
end
- it 'can not be destroyed when when list_type is set to closed' do
+ it 'can not be destroyed when list_type is set to closed' do
subject = create(:closed_list)
expect(subject.destroy).to be_falsey
diff --git a/spec/models/merge_request_diff_spec.rb b/spec/models/merge_request_diff_spec.rb
index 90cce826b6c..cbe60b3a4a5 100644
--- a/spec/models/merge_request_diff_spec.rb
+++ b/spec/models/merge_request_diff_spec.rb
@@ -52,9 +52,9 @@ describe MergeRequestDiff do
context 'when it was not cleaned by the system' do
it 'returns persisted diffs' do
- expect(diff).to receive(:load_diffs)
+ expect(diff).to receive(:load_diffs).and_call_original
- diff.diffs
+ diff.diffs.diff_files
end
end
@@ -76,19 +76,19 @@ describe MergeRequestDiff do
end
it 'returns persisted diffs if cannot compare with diff refs' do
- expect(diff).to receive(:load_diffs)
+ expect(diff).to receive(:load_diffs).and_call_original
diff.update!(head_commit_sha: 'invalid-sha')
- diff.diffs
+ diff.diffs.diff_files
end
it 'returns persisted diffs if diff refs does not exist' do
- expect(diff).to receive(:load_diffs)
+ expect(diff).to receive(:load_diffs).and_call_original
diff.update!(start_commit_sha: nil, base_commit_sha: nil)
- diff.diffs
+ diff.diffs.diff_files
end
end
end
@@ -211,4 +211,38 @@ describe MergeRequestDiff do
expect(diff_with_commits.commits_count).to eq(29)
end
end
+
+ describe '#commits_by_shas' do
+ let(:commit_shas) { diff_with_commits.commit_shas }
+
+ it 'returns empty if no SHAs were provided' do
+ expect(diff_with_commits.commits_by_shas([])).to be_empty
+ end
+
+ it 'returns one SHA' do
+ commits = diff_with_commits.commits_by_shas([commit_shas.first, Gitlab::Git::BLANK_SHA])
+
+ expect(commits.count).to eq(1)
+ end
+
+ it 'returns all matching SHAs' do
+ commits = diff_with_commits.commits_by_shas(commit_shas)
+
+ expect(commits.count).to eq(commit_shas.count)
+ expect(commits.map(&:sha)).to match_array(commit_shas)
+ end
+ end
+
+ describe '#modified_paths' do
+ subject do
+ diff = create(:merge_request_diff)
+ create(:merge_request_diff_file, :new_file, merge_request_diff: diff)
+ create(:merge_request_diff_file, :renamed_file, merge_request_diff: diff)
+ diff
+ end
+
+ it 'returns affected file paths' do
+ expect(subject.modified_paths).to eq(%w{foo bar baz})
+ end
+ end
end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 48f4e53b93e..ad55c280399 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -13,51 +13,55 @@ describe MergeRequest do
it { is_expected.to belong_to(:merge_user).class_name("User") }
it { is_expected.to belong_to(:assignee) }
it { is_expected.to have_many(:merge_request_diffs) }
- end
- describe '#squash_in_progress?' do
- shared_examples 'checking whether a squash is in progress' do
- let(:repo_path) do
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- subject.source_project.repository.path
- end
- end
- let(:squash_path) { File.join(repo_path, "gitlab-worktree", "squash-#{subject.id}") }
+ context 'for forks' do
+ let!(:project) { create(:project) }
+ let!(:fork) { fork_project(project) }
+ let!(:merge_request) { create(:merge_request, target_project: project, source_project: fork) }
- before do
- system(*%W(#{Gitlab.config.git.bin_path} -C #{repo_path} worktree add --detach #{squash_path} master))
+ it 'does not load another project due to inverse relationship' do
+ expect(project.merge_requests.first.target_project.object_id).to eq(project.object_id)
end
- it 'returns true when there is a current squash directory' do
- expect(subject.squash_in_progress?).to be_truthy
+ it 'finds the associated merge request' do
+ expect(project.merge_requests.find(merge_request.id)).to eq(merge_request)
end
+ end
+ end
- it 'returns false when there is no squash directory' do
- FileUtils.rm_rf(squash_path)
-
- expect(subject.squash_in_progress?).to be_falsey
+ describe '#squash_in_progress?' do
+ let(:repo_path) do
+ Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ subject.source_project.repository.path
end
+ end
+ let(:squash_path) { File.join(repo_path, "gitlab-worktree", "squash-#{subject.id}") }
- it 'returns false when the squash directory has expired' do
- time = 20.minutes.ago.to_time
- File.utime(time, time, squash_path)
+ before do
+ system(*%W(#{Gitlab.config.git.bin_path} -C #{repo_path} worktree add --detach #{squash_path} master))
+ end
- expect(subject.squash_in_progress?).to be_falsey
- end
+ it 'returns true when there is a current squash directory' do
+ expect(subject.squash_in_progress?).to be_truthy
+ end
- it 'returns false when the source project has been removed' do
- allow(subject).to receive(:source_project).and_return(nil)
+ it 'returns false when there is no squash directory' do
+ FileUtils.rm_rf(squash_path)
- expect(subject.squash_in_progress?).to be_falsey
- end
+ expect(subject.squash_in_progress?).to be_falsey
end
- context 'when Gitaly squash_in_progress is enabled' do
- it_behaves_like 'checking whether a squash is in progress'
+ it 'returns false when the squash directory has expired' do
+ time = 20.minutes.ago.to_time
+ File.utime(time, time, squash_path)
+
+ expect(subject.squash_in_progress?).to be_falsey
end
- context 'when Gitaly squash_in_progress is disabled', :disable_gitaly do
- it_behaves_like 'checking whether a squash is in progress'
+ it 'returns false when the source project has been removed' do
+ allow(subject).to receive(:source_project).and_return(nil)
+
+ expect(subject.squash_in_progress?).to be_falsey
end
end
@@ -538,9 +542,9 @@ describe MergeRequest do
it 'delegates to the MR diffs' do
merge_request.save
- expect(merge_request.merge_request_diff).to receive(:raw_diffs).with(hash_including(options))
+ expect(merge_request.merge_request_diff).to receive(:raw_diffs).with(hash_including(options)).and_call_original
- merge_request.diffs(options)
+ merge_request.diffs(options).diff_files
end
end
@@ -617,6 +621,44 @@ describe MergeRequest do
end
end
+ describe '#modified_paths' do
+ let(:paths) { double(:paths) }
+ subject(:merge_request) { build(:merge_request) }
+
+ before do
+ expect(diff).to receive(:modified_paths).and_return(paths)
+ end
+
+ context 'when past_merge_request_diff is specified' do
+ let(:another_diff) { double(:merge_request_diff) }
+ let(:diff) { another_diff }
+
+ it 'returns affected file paths from specified past_merge_request_diff' do
+ expect(merge_request.modified_paths(past_merge_request_diff: another_diff)).to eq(paths)
+ end
+ end
+
+ context 'when compare is present' do
+ let(:compare) { double(:compare) }
+ let(:diff) { compare }
+
+ it 'returns affected file paths from compare' do
+ merge_request.compare = compare
+
+ expect(merge_request.modified_paths).to eq(paths)
+ end
+ end
+
+ context 'when no arguments provided' do
+ let(:diff) { merge_request.merge_request_diff }
+ subject(:merge_request) { create(:merge_request, source_branch: 'feature', target_branch: 'master') }
+
+ it 'returns affected file paths for merge_request_diff' do
+ expect(merge_request.modified_paths).to eq(paths)
+ end
+ end
+ end
+
describe "#related_notes" do
let!(:merge_request) { create(:merge_request) }
@@ -746,7 +788,7 @@ describe MergeRequest do
end
describe "#wipless_title" do
- ['WIP ', 'WIP:', 'WIP: ', '[WIP]', '[WIP] ', ' [WIP] WIP [WIP] WIP: WIP '].each do |wip_prefix|
+ ['WIP ', 'WIP:', 'WIP: ', '[WIP]', '[WIP] ', '[WIP] WIP [WIP] WIP: WIP '].each do |wip_prefix|
it "removes the '#{wip_prefix}' prefix" do
wipless_title = subject.title
subject.title = "#{wip_prefix}#{subject.title}"
@@ -1058,6 +1100,26 @@ describe MergeRequest do
end
end
+ describe '#merge_pipeline' do
+ it 'returns nil when not merged' do
+ expect(subject.merge_pipeline).to be_nil
+ end
+
+ context 'when the MR is merged' do
+ let(:sha) { subject.target_project.commit.id }
+ let(:pipeline) { create(:ci_empty_pipeline, sha: sha, ref: subject.target_branch, project: subject.target_project) }
+
+ before do
+ subject.mark_as_merged!
+ subject.update_attribute(:merge_commit_sha, pipeline.sha)
+ end
+
+ it 'returns the post-merge pipeline' do
+ expect(subject.merge_pipeline).to eq(pipeline)
+ end
+ end
+ end
+
describe '#has_ci?' do
let(:merge_request) { build_stubbed(:merge_request) }
@@ -1710,7 +1772,7 @@ describe MergeRequest do
allow(subject).to receive(:head_pipeline) { nil }
end
- it { expect(subject.mergeable_ci_state?).to be_truthy }
+ it { expect(subject.mergeable_ci_state?).to be_falsey }
end
end
@@ -1802,8 +1864,8 @@ describe MergeRequest do
let(:environments) { create_list(:environment, 3, project: project) }
before do
- create(:deployment, environment: environments.first, ref: 'master', sha: project.commit('master').id)
- create(:deployment, environment: environments.second, ref: 'feature', sha: project.commit('feature').id)
+ create(:deployment, :success, environment: environments.first, ref: 'master', sha: project.commit('master').id)
+ create(:deployment, :success, environment: environments.second, ref: 'feature', sha: project.commit('feature').id)
end
it 'selects deployed environments' do
@@ -1823,7 +1885,7 @@ describe MergeRequest do
let(:source_environment) { create(:environment, project: source_project) }
before do
- create(:deployment, environment: source_environment, ref: 'feature', sha: merge_request.diff_head_sha)
+ create(:deployment, :success, environment: source_environment, ref: 'feature', sha: merge_request.diff_head_sha)
end
it 'selects deployed environments' do
@@ -1834,7 +1896,7 @@ describe MergeRequest do
let(:target_environment) { create(:environment, project: project) }
before do
- create(:deployment, environment: target_environment, tag: true, sha: merge_request.diff_head_sha)
+ create(:deployment, :success, environment: target_environment, tag: true, sha: merge_request.diff_head_sha)
end
it 'selects deployed environments' do
@@ -2515,14 +2577,6 @@ describe MergeRequest do
expect(subject.rebase_in_progress?).to be_falsey
end
end
-
- context 'when Gitaly rebase_in_progress is enabled' do
- it_behaves_like 'checking whether a rebase is in progress'
- end
-
- context 'when Gitaly rebase_in_progress is enabled', :disable_gitaly do
- it_behaves_like 'checking whether a rebase is in progress'
- end
end
describe '#allow_collaboration' do
@@ -2577,6 +2631,36 @@ describe MergeRequest do
end
end
+ describe '#includes_any_commits?' do
+ it 'returns false' do
+ expect(subject.includes_any_commits?([])).to be_falsey
+ end
+
+ it 'returns false' do
+ expect(subject.includes_any_commits?([Gitlab::Git::BLANK_SHA])).to be_falsey
+ end
+
+ it 'returns true' do
+ expect(subject.includes_any_commits?([subject.merge_request_diff.head_commit_sha])).to be_truthy
+ end
+
+ it 'returns true even when there is a non-existent comit' do
+ expect(subject.includes_any_commits?([Gitlab::Git::BLANK_SHA, subject.merge_request_diff.head_commit_sha])).to be_truthy
+ end
+
+ context 'unpersisted merge request' do
+ let(:new_mr) { build(:merge_request) }
+
+ it 'returns false' do
+ expect(new_mr.includes_any_commits?([Gitlab::Git::BLANK_SHA])).to be_falsey
+ end
+
+ it 'returns true' do
+ expect(new_mr.includes_any_commits?([subject.merge_request_diff.head_commit_sha])).to be_truthy
+ end
+ end
+ end
+
describe '#can_allow_collaboration?' do
let(:target_project) { create(:project, :public) }
let(:source_project) { fork_project(target_project) }
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index 27d4e622710..d11eb46159e 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -348,4 +348,41 @@ describe Milestone do
end
end
end
+
+ describe '.states_count' do
+ context 'when the projects have milestones' do
+ before do
+ project_1 = create(:project)
+ project_2 = create(:project)
+ group_1 = create(:group)
+ group_2 = create(:group)
+
+ create(:active_milestone, title: 'Active Group Milestone', project: project_1)
+ create(:closed_milestone, title: 'Closed Group Milestone', project: project_1)
+ create(:active_milestone, title: 'Active Group Milestone', project: project_2)
+ create(:closed_milestone, title: 'Closed Group Milestone', project: project_2)
+ create(:closed_milestone, title: 'Active Group Milestone', group: group_1)
+ create(:closed_milestone, title: 'Closed Group Milestone', group: group_1)
+ create(:closed_milestone, title: 'Active Group Milestone', group: group_2)
+ create(:closed_milestone, title: 'Closed Group Milestone', group: group_2)
+ end
+
+ it 'returns the quantity of milestones in each possible state' do
+ expected_count = { opened: 5, closed: 6, all: 11 }
+
+ count = described_class.states_count(Project.all, Group.all)
+ expect(count).to eq(expected_count)
+ end
+ end
+
+ context 'when the projects do not have milestones' do
+ it 'returns 0 as the quantity of global milestones in each state' do
+ expected_count = { opened: 0, closed: 0, all: 0 }
+
+ count = described_class.states_count([project])
+
+ expect(count).to eq(expected_count)
+ end
+ end
+ end
end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 3649990670b..2db42fe802a 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -2,6 +2,7 @@ require 'spec_helper'
describe Namespace do
include ProjectForksHelper
+ include GitHelpers
let!(:namespace) { create(:namespace) }
let(:gitlab_shell) { Gitlab::Shell.new }
@@ -82,6 +83,27 @@ describe Namespace do
it { expect(namespace.human_name).to eq(namespace.owner_name) }
end
+ describe '#first_project_with_container_registry_tags' do
+ let(:container_repository) { create(:container_repository) }
+ let!(:project) { create(:project, namespace: namespace, container_repositories: [container_repository]) }
+
+ before do
+ stub_container_registry_config(enabled: true)
+ end
+
+ it 'returns the project' do
+ stub_container_registry_tags(repository: :any, tags: ['tag'])
+
+ expect(namespace.first_project_with_container_registry_tags).to eq(project)
+ end
+
+ it 'returns no project' do
+ stub_container_registry_tags(repository: :any, tags: nil)
+
+ expect(namespace.first_project_with_container_registry_tags).to be_nil
+ end
+ end
+
describe '.search' do
let(:namespace) { create(:namespace) }
@@ -184,7 +206,8 @@ describe Namespace do
end
it 'raises an error about not movable project' do
- expect { namespace.move_dir }.to raise_error(/Namespace cannot be moved/)
+ expect { namespace.move_dir }.to raise_error(Gitlab::UpdatePathError,
+ /Namespace .* cannot be moved/)
end
end
end
@@ -339,9 +362,7 @@ describe Namespace do
end
def project_rugged(project)
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.rugged
- end
+ rugged_repo(project.repository)
end
end
@@ -541,6 +562,17 @@ describe Namespace do
it { expect(group.all_projects.to_a).to match_array([project2, project1]) }
end
+ describe '#all_pipelines' do
+ let(:group) { create(:group) }
+ let(:child) { create(:group, parent: group) }
+ let!(:project1) { create(:project_empty_repo, namespace: group) }
+ let!(:project2) { create(:project_empty_repo, namespace: child) }
+ let!(:pipeline1) { create(:ci_empty_pipeline, project: project1) }
+ let!(:pipeline2) { create(:ci_empty_pipeline, project: project2) }
+
+ it { expect(group.all_pipelines.to_a).to match_array([pipeline1, pipeline2]) }
+ end
+
describe '#share_with_group_lock with subgroups', :nested_groups do
context 'when creating a subgroup' do
let(:subgroup) { create(:group, parent: root_group )}
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index 947be44c903..bcdfe3cf1eb 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -231,33 +231,60 @@ describe Note do
let(:ext_proj) { create(:project, :public) }
let(:ext_issue) { create(:issue, project: ext_proj) }
- let(:note) do
- create :note,
- noteable: ext_issue, project: ext_proj,
- note: "mentioned in issue #{private_issue.to_reference(ext_proj)}",
- system: true
- end
+ shared_examples "checks references" do
+ it "returns true" do
+ expect(note.cross_reference_not_visible_for?(ext_issue.author)).to be_truthy
+ end
- it "returns true" do
- expect(note.cross_reference_not_visible_for?(ext_issue.author)).to be_truthy
- end
+ it "returns false" do
+ expect(note.cross_reference_not_visible_for?(private_user)).to be_falsy
+ end
- it "returns false" do
- expect(note.cross_reference_not_visible_for?(private_user)).to be_falsy
+ it "returns false if user visible reference count set" do
+ note.user_visible_reference_count = 1
+ note.total_reference_count = 1
+
+ expect(note).not_to receive(:reference_mentionables)
+ expect(note.cross_reference_not_visible_for?(ext_issue.author)).to be_falsy
+ end
+
+ it "returns true if ref count is 0" do
+ note.user_visible_reference_count = 0
+
+ expect(note).not_to receive(:reference_mentionables)
+ expect(note.cross_reference_not_visible_for?(ext_issue.author)).to be_truthy
+ end
end
- it "returns false if user visible reference count set" do
- note.user_visible_reference_count = 1
+ context "when there is one reference in note" do
+ let(:note) do
+ create :note,
+ noteable: ext_issue, project: ext_proj,
+ note: "mentioned in issue #{private_issue.to_reference(ext_proj)}",
+ system: true
+ end
- expect(note).not_to receive(:reference_mentionables)
- expect(note.cross_reference_not_visible_for?(ext_issue.author)).to be_falsy
+ it_behaves_like "checks references"
end
- it "returns true if ref count is 0" do
- note.user_visible_reference_count = 0
+ context "when there are two references in note" do
+ let(:note) do
+ create :note,
+ noteable: ext_issue, project: ext_proj,
+ note: "mentioned in issue #{private_issue.to_reference(ext_proj)} and " \
+ "public issue #{ext_issue.to_reference(ext_proj)}",
+ system: true
+ end
+
+ it_behaves_like "checks references"
- expect(note).not_to receive(:reference_mentionables)
- expect(note.cross_reference_not_visible_for?(ext_issue.author)).to be_truthy
+ it "returns true if user visible reference count set and there is a private reference" do
+ note.user_visible_reference_count = 1
+ note.total_reference_count = 2
+
+ expect(note).not_to receive(:reference_mentionables)
+ expect(note.cross_reference_not_visible_for?(ext_issue.author)).to be_truthy
+ end
end
end
@@ -269,7 +296,7 @@ describe Note do
end
context 'when the note might contain cross references' do
- SystemNoteMetadata::TYPES_WITH_CROSS_REFERENCES.each do |type|
+ SystemNoteMetadata.new.cross_reference_types.each do |type|
let(:note) { create(:note, :system) }
let!(:metadata) { create(:system_note_metadata, note: note, action: type) }
@@ -490,7 +517,7 @@ describe Note do
describe '#to_ability_name' do
it 'returns snippet for a project snippet note' do
- expect(build(:note_on_project_snippet).to_ability_name).to eq('snippet')
+ expect(build(:note_on_project_snippet).to_ability_name).to eq('project_snippet')
end
it 'returns personal_snippet for a personal snippet note' do
@@ -838,5 +865,29 @@ describe Note do
note.save!
end
end
+
+ describe '#with_notes_filter' do
+ let!(:comment) { create(:note) }
+ let!(:system_note) { create(:note, system: true) }
+
+ context 'when notes filter is nil' do
+ subject { described_class.with_notes_filter(nil) }
+
+ it { is_expected.to include(comment, system_note) }
+ end
+
+ context 'when notes filter is set to all notes' do
+ subject { described_class.with_notes_filter(UserPreference::NOTES_FILTERS[:all_notes]) }
+
+ it { is_expected.to include(comment, system_note) }
+ end
+
+ context 'when notes filter is set to only comments' do
+ subject { described_class.with_notes_filter(UserPreference::NOTES_FILTERS[:only_comments]) }
+
+ it { is_expected.to include(comment) }
+ it { is_expected.not_to include(system_note) }
+ end
+ end
end
end
diff --git a/spec/models/notification_setting_spec.rb b/spec/models/notification_setting_spec.rb
index e545b674b4f..771d834c4bc 100644
--- a/spec/models/notification_setting_spec.rb
+++ b/spec/models/notification_setting_spec.rb
@@ -1,6 +1,8 @@
require 'rails_helper'
RSpec.describe NotificationSetting do
+ it_behaves_like 'having unique enum values'
+
describe "Associations" do
it { is_expected.to belong_to(:user) }
it { is_expected.to belong_to(:source) }
diff --git a/spec/models/personal_access_token_spec.rb b/spec/models/personal_access_token_spec.rb
index 2bb1c49b740..c82ab9c9e62 100644
--- a/spec/models/personal_access_token_spec.rb
+++ b/spec/models/personal_access_token_spec.rb
@@ -49,18 +49,36 @@ describe PersonalAccessToken do
describe 'Redis storage' do
let(:user_id) { 123 }
- let(:token) { 'abc000foo' }
+ let(:token) { 'KS3wegQYXBLYhQsciwsj' }
- before do
- subject.redis_store!(user_id, token)
+ context 'reading encrypted data' do
+ before do
+ subject.redis_store!(user_id, token)
+ end
+
+ it 'returns stored data' do
+ expect(subject.redis_getdel(user_id)).to eq(token)
+ end
end
- it 'returns stored data' do
- expect(subject.redis_getdel(user_id)).to eq(token)
+ context 'reading unencrypted data' do
+ before do
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set(described_class.redis_shared_state_key(user_id),
+ token,
+ ex: PersonalAccessToken::REDIS_EXPIRY_TIME)
+ end
+ end
+
+ it 'returns stored data unmodified' do
+ expect(subject.redis_getdel(user_id)).to eq(token)
+ end
end
context 'after deletion' do
before do
+ subject.redis_store!(user_id, token)
+
expect(subject.redis_getdel(user_id)).to eq(token)
end
diff --git a/spec/models/pool_repository_spec.rb b/spec/models/pool_repository_spec.rb
new file mode 100644
index 00000000000..541e78507e5
--- /dev/null
+++ b/spec/models/pool_repository_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe PoolRepository do
+ describe 'associations' do
+ it { is_expected.to belong_to(:shard) }
+ it { is_expected.to have_many(:member_projects) }
+ end
+
+ describe 'validations' do
+ let!(:pool_repository) { create(:pool_repository) }
+
+ it { is_expected.to validate_presence_of(:shard) }
+ end
+
+ describe '#disk_path' do
+ it 'sets the hashed disk_path' do
+ pool = create(:pool_repository)
+
+ elements = File.split(pool.disk_path)
+
+ expect(elements).to all( match(/\d{2,}/) )
+ end
+ end
+end
diff --git a/spec/models/postgresql/replication_slot_spec.rb b/spec/models/postgresql/replication_slot_spec.rb
index 919a7526803..e100af7ddc7 100644
--- a/spec/models/postgresql/replication_slot_spec.rb
+++ b/spec/models/postgresql/replication_slot_spec.rb
@@ -3,7 +3,27 @@
require 'spec_helper'
describe Postgresql::ReplicationSlot, :postgresql do
+ describe '.in_use?' do
+ it 'returns true when replication slots are present' do
+ expect(described_class).to receive(:exists?).and_return(true)
+ expect(described_class.in_use?).to be_truthy
+ end
+
+ it 'returns false when replication slots are not present' do
+ expect(described_class.in_use?).to be_falsey
+ end
+
+ it 'returns false if the existence check is invalid' do
+ expect(described_class).to receive(:exists?).and_raise(ActiveRecord::StatementInvalid.new('PG::FeatureNotSupported'))
+ expect(described_class.in_use?).to be_falsey
+ end
+ end
+
describe '.lag_too_great?' do
+ before do
+ expect(described_class).to receive(:in_use?).and_return(true)
+ end
+
it 'returns true when replication lag is too great' do
expect(described_class)
.to receive(:pluck)
diff --git a/spec/models/project_auto_devops_spec.rb b/spec/models/project_auto_devops_spec.rb
index 797d767465a..7ff64c76e37 100644
--- a/spec/models/project_auto_devops_spec.rb
+++ b/spec/models/project_auto_devops_spec.rb
@@ -3,6 +3,8 @@ require 'spec_helper'
describe ProjectAutoDevops do
set(:project) { build(:project) }
+ it_behaves_like 'having unique enum values'
+
it { is_expected.to belong_to(:project) }
it { is_expected.to define_enum_for(:deploy_strategy) }
@@ -70,24 +72,31 @@ describe ProjectAutoDevops do
end
context 'when deploy_strategy is manual' do
- let(:domain) { 'example.com' }
-
- before do
- auto_devops.deploy_strategy = 'manual'
+ let(:auto_devops) { build_stubbed(:project_auto_devops, :manual_deployment, project: project) }
+ let(:expected_variables) do
+ [
+ { key: 'INCREMENTAL_ROLLOUT_MODE', value: 'manual' },
+ { key: 'STAGING_ENABLED', value: '1' },
+ { key: 'INCREMENTAL_ROLLOUT_ENABLED', value: '1' }
+ ]
end
+ it { expect(auto_devops.predefined_variables).to include(*expected_variables) }
+ end
+
+ context 'when deploy_strategy is continuous' do
+ let(:auto_devops) { build_stubbed(:project_auto_devops, :continuous_deployment, project: project) }
+
it do
expect(auto_devops.predefined_variables.map { |var| var[:key] })
- .to include("STAGING_ENABLED", "INCREMENTAL_ROLLOUT_ENABLED")
+ .not_to include("STAGING_ENABLED", "INCREMENTAL_ROLLOUT_ENABLED")
end
end
- context 'when deploy_strategy is continuous' do
- let(:domain) { 'example.com' }
+ context 'when deploy_strategy is timed_incremental' do
+ let(:auto_devops) { build_stubbed(:project_auto_devops, :timed_incremental_deployment, project: project) }
- before do
- auto_devops.deploy_strategy = 'continuous'
- end
+ it { expect(auto_devops.predefined_variables).to include(key: 'INCREMENTAL_ROLLOUT_MODE', value: 'timed') }
it do
expect(auto_devops.predefined_variables.map { |var| var[:key] })
diff --git a/spec/models/project_feature_spec.rb b/spec/models/project_feature_spec.rb
index 10617edec0f..fee7d65c217 100644
--- a/spec/models/project_feature_spec.rb
+++ b/spec/models/project_feature_spec.rb
@@ -17,7 +17,7 @@ describe ProjectFeature do
end
describe '#feature_available?' do
- let(:features) { %w(issues wiki builds merge_requests snippets repository) }
+ let(:features) { %w(issues wiki builds merge_requests snippets repository pages) }
context 'when features are disabled' do
it "returns false" do
@@ -73,6 +73,22 @@ describe ProjectFeature do
end
end
end
+
+ context 'when feature is disabled by a feature flag' do
+ it 'returns false' do
+ stub_feature_flags(issues: false)
+
+ expect(project.feature_available?(:issues, user)).to eq(false)
+ end
+ end
+
+ context 'when feature is enabled by a feature flag' do
+ it 'returns true' do
+ stub_feature_flags(issues: true)
+
+ expect(project.feature_available?(:issues, user)).to eq(true)
+ end
+ end
end
context 'repository related features' do
@@ -96,6 +112,19 @@ describe ProjectFeature do
end
end
+ context 'public features' do
+ it "does not allow public for other than pages" do
+ features = %w(issues wiki builds merge_requests snippets repository)
+ project_feature = project.project_feature
+
+ features.each do |feature|
+ field = "#{feature}_access_level".to_sym
+ project_feature.update_attribute(field, ProjectFeature::PUBLIC)
+ expect(project_feature.valid?).to be_falsy
+ end
+ end
+ end
+
describe '#*_enabled?' do
let(:features) { %w(wiki builds merge_requests) }
@@ -119,46 +148,4 @@ describe ProjectFeature do
end
end
end
-
- context 'Site Statistics' do
- set(:project_with_wiki) { create(:project, :wiki_enabled) }
- set(:project_without_wiki) { create(:project, :wiki_disabled) }
-
- context 'when creating a project' do
- it 'tracks wiki availability when wikis are enabled by default' do
- expect { create(:project) }.to change { SiteStatistic.fetch.wikis_count }.by(1)
- end
-
- it 'does not track wiki availability when wikis are disabled by default' do
- expect { create(:project, :wiki_disabled) }.not_to change { SiteStatistic.fetch.wikis_count }
- end
- end
-
- context 'when updating a project_feature' do
- it 'untracks wiki availability when disabling wiki access' do
- expect { project_with_wiki.project_feature.update_attribute(:wiki_access_level, ProjectFeature::DISABLED) }
- .to change { SiteStatistic.fetch.wikis_count }.by(-1)
- end
-
- it 'tracks again wiki availability when re-enabling wiki access as public' do
- expect { project_without_wiki.project_feature.update_attribute(:wiki_access_level, ProjectFeature::ENABLED) }
- .to change { SiteStatistic.fetch.wikis_count }.by(1)
- end
-
- it 'tracks again wiki availability when re-enabling wiki access as private' do
- expect { project_without_wiki.project_feature.update_attribute(:wiki_access_level, ProjectFeature::PRIVATE) }
- .to change { SiteStatistic.fetch.wikis_count }.by(1)
- end
- end
-
- context 'when removing a project' do
- it 'untracks wiki availability when removing a project with previous wiki access' do
- expect { project_with_wiki.destroy }.to change { SiteStatistic.fetch.wikis_count }.by(-1)
- end
-
- it 'does not untrack wiki availability when removing a project without wiki access' do
- expect { project_without_wiki.destroy }.not_to change { SiteStatistic.fetch.wikis_count }
- end
- end
- end
end
diff --git a/spec/models/project_import_state_spec.rb b/spec/models/project_import_state_spec.rb
index f7033b28c76..e3b2d971419 100644
--- a/spec/models/project_import_state_spec.rb
+++ b/spec/models/project_import_state_spec.rb
@@ -10,4 +10,116 @@ describe ProjectImportState, type: :model do
describe 'validations' do
it { is_expected.to validate_presence_of(:project) }
end
+
+ describe 'Project import job' do
+ let(:import_state) { create(:import_state, import_url: generate(:url)) }
+ let(:project) { import_state.project }
+
+ before do
+ allow_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive(:import_repository)
+ .with(project.import_url).and_return(true)
+
+ # Works around https://github.com/rspec/rspec-mocks/issues/910
+ allow(Project).to receive(:find).with(project.id).and_return(project)
+ expect(project.repository).to receive(:after_import).and_call_original
+ expect(project.wiki.repository).to receive(:after_import).and_call_original
+ end
+
+ it 'imports a project' do
+ expect(RepositoryImportWorker).to receive(:perform_async).and_call_original
+
+ expect { import_state.schedule }.to change { import_state.jid }
+ expect(import_state.status).to eq('finished')
+ end
+ end
+
+ describe '#human_status_name' do
+ context 'when import_state exists' do
+ it 'returns the humanized status name' do
+ import_state = build(:import_state, :started)
+
+ expect(import_state.human_status_name).to eq("started")
+ end
+ end
+ end
+
+ describe 'import state transitions' do
+ context 'state transition: [:started] => [:finished]' do
+ let(:after_import_service) { spy(:after_import_service) }
+ let(:housekeeping_service) { spy(:housekeeping_service) }
+
+ before do
+ allow(Projects::AfterImportService)
+ .to receive(:new) { after_import_service }
+
+ allow(after_import_service)
+ .to receive(:execute) { housekeeping_service.execute }
+
+ allow(Projects::HousekeepingService)
+ .to receive(:new) { housekeeping_service }
+ end
+
+ it 'resets last_error' do
+ error_message = 'Some error'
+ import_state = create(:import_state, :started, last_error: error_message)
+
+ expect { import_state.finish }.to change { import_state.last_error }.from(error_message).to(nil)
+ end
+
+ it 'performs housekeeping when an import of a fresh project is completed' do
+ project = create(:project_empty_repo, :import_started, import_type: :github)
+
+ project.import_state.finish
+
+ expect(after_import_service).to have_received(:execute)
+ expect(housekeeping_service).to have_received(:execute)
+ end
+
+ it 'does not perform housekeeping when project repository does not exist' do
+ project = create(:project, :import_started, import_type: :github)
+
+ project.import_state.finish
+
+ expect(housekeeping_service).not_to have_received(:execute)
+ end
+
+ it 'does not perform housekeeping when project does not have a valid import type' do
+ project = create(:project, :import_started, import_type: nil)
+
+ project.import_state.finish
+
+ expect(housekeeping_service).not_to have_received(:execute)
+ end
+ end
+ end
+
+ describe '#remove_jid', :clean_gitlab_redis_cache do
+ let(:project) { }
+
+ context 'without an JID' do
+ it 'does nothing' do
+ import_state = create(:import_state)
+
+ expect(Gitlab::SidekiqStatus)
+ .not_to receive(:unset)
+
+ import_state.remove_jid
+ end
+ end
+
+ context 'with an JID' do
+ it 'unsets the JID' do
+ import_state = create(:import_state, jid: '123')
+
+ expect(Gitlab::SidekiqStatus)
+ .to receive(:unset)
+ .with('123')
+ .and_call_original
+
+ import_state.remove_jid
+
+ expect(import_state.jid).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/models/project_repository_spec.rb b/spec/models/project_repository_spec.rb
new file mode 100644
index 00000000000..c966447fedc
--- /dev/null
+++ b/spec/models/project_repository_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ProjectRepository do
+ describe 'associations' do
+ it { is_expected.to belong_to(:shard) }
+ it { is_expected.to belong_to(:project) }
+ end
+
+ describe '.find_project' do
+ it 'finds project by disk path' do
+ project = create(:project)
+ project.track_project_repository
+
+ expect(described_class.find_project(project.disk_path)).to eq(project)
+ end
+
+ it 'returns nil when it does not find the project' do
+ expect(described_class.find_project('@@unexisting/path/to/project')).to be_nil
+ end
+ end
+end
diff --git a/spec/models/project_services/bamboo_service_spec.rb b/spec/models/project_services/bamboo_service_spec.rb
index f4f7afb1b92..ee84fa95f0e 100644
--- a/spec/models/project_services/bamboo_service_spec.rb
+++ b/spec/models/project_services/bamboo_service_spec.rb
@@ -245,6 +245,7 @@ describe BambooService, :use_clean_rails_memory_store_caching do
end
def bamboo_response(result_key: 42, build_state: 'success', size: 1)
- %Q({"results":{"results":{"size":"#{size}","result":{"buildState":"#{build_state}","planResultKey":{"key":"#{result_key}"}}}}})
+ # reference: https://docs.atlassian.com/atlassian-bamboo/REST/6.2.5/#d2e786
+ %Q({"results":{"results":{"size":"#{size}","result":[{"buildState":"#{build_state}","planResultKey":{"key":"#{result_key}"}}]}}})
end
end
diff --git a/spec/models/project_services/chat_message/push_message_spec.rb b/spec/models/project_services/chat_message/push_message_spec.rb
index 19c2862264f..973d6bdb2a0 100644
--- a/spec/models/project_services/chat_message/push_message_spec.rb
+++ b/spec/models/project_services/chat_message/push_message_spec.rb
@@ -48,12 +48,12 @@ describe ChatMessage::PushMessage do
'test.user pushed to branch [master](http://url.com/commits/master) of [project_name](http://url.com) ([Compare changes](http://url.com/compare/before...after))')
expect(subject.attachments).to eq(
"[abcdefgh](http://url1.com): message1 - author1\n\n[12345678](http://url2.com): message2 - author2")
- expect(subject.activity).to eq({
- title: 'test.user pushed to branch',
+ expect(subject.activity).to eq(
+ title: 'test.user pushed to branch [master](http://url.com/commits/master)',
subtitle: 'in [project_name](http://url.com)',
text: '[Compare changes](http://url.com/compare/before...after)',
image: 'http://someavatar.com'
- })
+ )
end
end
end
@@ -89,12 +89,53 @@ describe ChatMessage::PushMessage do
expect(subject.pretext).to eq(
'test.user pushed new tag [new_tag](http://url.com/commits/new_tag) to [project_name](http://url.com)')
expect(subject.attachments).to be_empty
- expect(subject.activity).to eq({
- title: 'test.user created tag',
+ expect(subject.activity).to eq(
+ title: 'test.user pushed new tag [new_tag](http://url.com/commits/new_tag)',
subtitle: 'in [project_name](http://url.com)',
text: '[Compare changes](http://url.com/compare/0000000000000000000000000000000000000000...after)',
image: 'http://someavatar.com'
- })
+ )
+ end
+ end
+ end
+
+ context 'removed tag' do
+ let(:args) do
+ {
+ after: Gitlab::Git::BLANK_SHA,
+ before: 'before',
+ project_name: 'project_name',
+ ref: 'refs/tags/new_tag',
+ user_name: 'test.user',
+ user_avatar: 'http://someavatar.com',
+ project_url: 'http://url.com'
+ }
+ end
+
+ context 'without markdown' do
+ it 'returns a message regarding removal of tags' do
+ expect(subject.pretext).to eq('test.user removed tag ' \
+ 'new_tag from ' \
+ '<http://url.com|project_name>')
+ expect(subject.attachments).to be_empty
+ end
+ end
+
+ context 'with markdown' do
+ before do
+ args[:markdown] = true
+ end
+
+ it 'returns a message regarding removal of tags' do
+ expect(subject.pretext).to eq(
+ 'test.user removed tag new_tag from [project_name](http://url.com)')
+ expect(subject.attachments).to be_empty
+ expect(subject.activity).to eq(
+ title: 'test.user removed tag new_tag',
+ subtitle: 'in [project_name](http://url.com)',
+ text: '[Compare changes](http://url.com/compare/before...0000000000000000000000000000000000000000)',
+ image: 'http://someavatar.com'
+ )
end
end
end
@@ -122,12 +163,12 @@ describe ChatMessage::PushMessage do
expect(subject.pretext).to eq(
'test.user pushed new branch [master](http://url.com/commits/master) to [project_name](http://url.com)')
expect(subject.attachments).to be_empty
- expect(subject.activity).to eq({
- title: 'test.user created branch',
+ expect(subject.activity).to eq(
+ title: 'test.user pushed new branch [master](http://url.com/commits/master)',
subtitle: 'in [project_name](http://url.com)',
text: '[Compare changes](http://url.com/compare/0000000000000000000000000000000000000000...after)',
image: 'http://someavatar.com'
- })
+ )
end
end
end
@@ -154,12 +195,12 @@ describe ChatMessage::PushMessage do
expect(subject.pretext).to eq(
'test.user removed branch master from [project_name](http://url.com)')
expect(subject.attachments).to be_empty
- expect(subject.activity).to eq({
- title: 'test.user removed branch',
+ expect(subject.activity).to eq(
+ title: 'test.user removed branch master',
subtitle: 'in [project_name](http://url.com)',
text: '[Compare changes](http://url.com/compare/before...0000000000000000000000000000000000000000)',
image: 'http://someavatar.com'
- })
+ )
end
end
end
diff --git a/spec/models/project_services/discord_service_spec.rb b/spec/models/project_services/discord_service_spec.rb
new file mode 100644
index 00000000000..be82f223478
--- /dev/null
+++ b/spec/models/project_services/discord_service_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+describe DiscordService do
+ it_behaves_like "chat service", "Discord notifications" do
+ let(:client) { Discordrb::Webhooks::Client }
+ let(:client_arguments) { { url: webhook_url } }
+ let(:content_key) { :content }
+ end
+end
diff --git a/spec/models/project_services/hangouts_chat_service_spec.rb b/spec/models/project_services/hangouts_chat_service_spec.rb
index cfa55188a64..0505ac9b49c 100644
--- a/spec/models/project_services/hangouts_chat_service_spec.rb
+++ b/spec/models/project_services/hangouts_chat_service_spec.rb
@@ -1,246 +1,11 @@
-require 'spec_helper'
+# frozen_string_literal: true
-describe HangoutsChatService do
- describe 'Associations' do
- it { is_expected.to belong_to :project }
- it { is_expected.to have_one :service_hook }
- end
-
- describe 'Validations' do
- context 'when service is active' do
- before do
- subject.active = true
- end
-
- it { is_expected.to validate_presence_of(:webhook) }
- it_behaves_like 'issue tracker service URL attribute', :webhook
- end
-
- context 'when service is inactive' do
- before do
- subject.active = false
- end
-
- it { is_expected.not_to validate_presence_of(:webhook) }
- end
- end
-
- describe '#execute' do
- let(:user) { create(:user) }
- let(:project) { create(:project, :repository) }
- let(:webhook_url) { 'https://example.gitlab.com/' }
-
- before do
- allow(subject).to receive_messages(
- project: project,
- project_id: project.id,
- service_hook: true,
- webhook: webhook_url
- )
-
- WebMock.stub_request(:post, webhook_url)
- end
-
- shared_examples 'Hangouts Chat service' do
- it 'calls Hangouts Chat API' do
- subject.execute(sample_data)
-
- expect(WebMock)
- .to have_requested(:post, webhook_url)
- .with { |req| req.body =~ /\A{"text":.+}\Z/ }
- .once
- end
- end
-
- context 'with push events' do
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build_sample(project, user)
- end
-
- it_behaves_like 'Hangouts Chat service'
-
- it 'specifies the webhook when it is configured' do
- expect(HangoutsChat::Sender).to receive(:new).with(webhook_url).and_return(double(:hangouts_chat_service).as_null_object)
-
- subject.execute(sample_data)
- end
-
- context 'with not default branch' do
- let(:sample_data) do
- Gitlab::DataBuilder::Push.build(project, user, nil, nil, 'not-the-default-branch')
- end
-
- context 'when notify_only_default_branch enabled' do
- before do
- subject.notify_only_default_branch = true
- end
-
- it 'does not call the Hangouts Chat API' do
- result = subject.execute(sample_data)
-
- expect(result).to be_falsy
- end
- end
-
- context 'when notify_only_default_branch disabled' do
- before do
- subject.notify_only_default_branch = false
- end
-
- it_behaves_like 'Hangouts Chat service'
- end
- end
- end
-
- context 'with issue events' do
- let(:opts) { { title: 'Awesome issue', description: 'please fix' } }
- let(:sample_data) do
- service = Issues::CreateService.new(project, user, opts)
- issue = service.execute
- service.hook_data(issue, 'open')
- end
-
- it_behaves_like 'Hangouts Chat service'
- end
-
- context 'with merge events' do
- let(:opts) do
- {
- title: 'Awesome merge_request',
- description: 'please fix',
- source_branch: 'feature',
- target_branch: 'master'
- }
- end
-
- let(:sample_data) do
- service = MergeRequests::CreateService.new(project, user, opts)
- merge_request = service.execute
- service.hook_data(merge_request, 'open')
- end
-
- before do
- project.add_developer(user)
- end
+require "spec_helper"
- it_behaves_like 'Hangouts Chat service'
- end
-
- context 'with wiki page events' do
- let(:opts) do
- {
- title: 'Awesome wiki_page',
- content: 'Some text describing some thing or another',
- format: 'md',
- message: 'user created page: Awesome wiki_page'
- }
- end
- let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: opts) }
- let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, 'create') }
-
- it_behaves_like 'Hangouts Chat service'
- end
-
- context 'with note events' do
- let(:sample_data) { Gitlab::DataBuilder::Note.build(note, user) }
-
- context 'with commit comment' do
- let(:note) do
- create(:note_on_commit, author: user,
- project: project,
- commit_id: project.repository.commit.id,
- note: 'a comment on a commit')
- end
-
- it_behaves_like 'Hangouts Chat service'
- end
-
- context 'with merge request comment' do
- let(:note) do
- create(:note_on_merge_request, project: project,
- note: 'merge request note')
- end
-
- it_behaves_like 'Hangouts Chat service'
- end
-
- context 'with issue comment' do
- let(:note) do
- create(:note_on_issue, project: project, note: 'issue note')
- end
-
- it_behaves_like 'Hangouts Chat service'
- end
-
- context 'with snippet comment' do
- let(:note) do
- create(:note_on_project_snippet, project: project,
- note: 'snippet note')
- end
-
- it_behaves_like 'Hangouts Chat service'
- end
- end
-
- context 'with pipeline events' do
- let(:pipeline) do
- create(:ci_pipeline,
- project: project, status: status,
- sha: project.commit.sha, ref: project.default_branch)
- end
- let(:sample_data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
-
- context 'with failed pipeline' do
- let(:status) { 'failed' }
-
- it_behaves_like 'Hangouts Chat service'
- end
-
- context 'with succeeded pipeline' do
- let(:status) { 'success' }
-
- context 'with default notify_only_broken_pipelines' do
- it 'does not call Hangouts Chat API' do
- result = subject.execute(sample_data)
-
- expect(result).to be_falsy
- end
- end
-
- context 'when notify_only_broken_pipelines is false' do
- before do
- subject.notify_only_broken_pipelines = false
- end
-
- it_behaves_like 'Hangouts Chat service'
- end
- end
-
- context 'with not default branch' do
- let(:pipeline) do
- create(:ci_pipeline, project: project, status: 'failed', ref: 'not-the-default-branch')
- end
-
- context 'when notify_only_default_branch enabled' do
- before do
- subject.notify_only_default_branch = true
- end
-
- it 'does not call the Hangouts Chat API' do
- result = subject.execute(sample_data)
-
- expect(result).to be_falsy
- end
- end
-
- context 'when notify_only_default_branch disabled' do
- before do
- subject.notify_only_default_branch = false
- end
-
- it_behaves_like 'Hangouts Chat service'
- end
- end
- end
+describe HangoutsChatService do
+ it_behaves_like "chat service", "Hangouts Chat" do
+ let(:client) { HangoutsChat::Sender }
+ let(:client_arguments) { webhook_url }
+ let(:content_key) { :text }
end
end
diff --git a/spec/models/project_services/hipchat_service_spec.rb b/spec/models/project_services/hipchat_service_spec.rb
index 0cd712e2f40..b0fd2ceead0 100644
--- a/spec/models/project_services/hipchat_service_spec.rb
+++ b/spec/models/project_services/hipchat_service_spec.rb
@@ -387,4 +387,22 @@ describe HipchatService do
end
end
end
+
+ context 'with UrlBlocker' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:hipchat) { described_class.new(project: project) }
+ let(:push_sample_data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
+
+ describe '#execute' do
+ before do
+ hipchat.server = 'http://localhost:9123'
+ end
+
+ it 'raises UrlBlocker for localhost' do
+ expect(Gitlab::UrlBlocker).to receive(:validate!).and_call_original
+ expect { hipchat.execute(push_sample_data) }.to raise_error(Gitlab::HTTP::BlockedUrlError)
+ end
+ end
+ end
end
diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb
index 68ab9fd08ec..9c27357ffaf 100644
--- a/spec/models/project_services/kubernetes_service_spec.rb
+++ b/spec/models/project_services/kubernetes_service_spec.rb
@@ -253,7 +253,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
end
end
- describe '#predefined_variables' do
+ describe '#predefined_variable' do
let(:kubeconfig) do
config_file = expand_fixture_path('config/kubeconfig.yml')
config = YAML.load(File.read(config_file))
@@ -274,7 +274,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
shared_examples 'setting variables' do
it 'sets the variables' do
- expect(subject.predefined_variables).to include(
+ expect(subject.predefined_variables(project: project)).to include(
{ key: 'KUBE_URL', value: 'https://kube.domain.com', public: true },
{ key: 'KUBE_TOKEN', value: 'token', public: false },
{ key: 'KUBE_NAMESPACE', value: namespace, public: true },
@@ -301,7 +301,7 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
it_behaves_like 'setting variables'
it 'sets the KUBE_NAMESPACE' do
- kube_namespace = subject.predefined_variables.find { |h| h[:key] == 'KUBE_NAMESPACE' }
+ kube_namespace = subject.predefined_variables(project: project).find { |h| h[:key] == 'KUBE_NAMESPACE' }
expect(kube_namespace).not_to be_nil
expect(kube_namespace[:value]).to match(/\A#{Gitlab::PathRegex::PATH_REGEX_STR}-\d+\z/)
diff --git a/spec/models/project_services/prometheus_service_spec.rb b/spec/models/project_services/prometheus_service_spec.rb
index 7afb1b4a8e3..b6cf4c72450 100644
--- a/spec/models/project_services/prometheus_service_spec.rb
+++ b/spec/models/project_services/prometheus_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe PrometheusService, :use_clean_rails_memory_store_caching do
@@ -11,6 +13,23 @@ describe PrometheusService, :use_clean_rails_memory_store_caching do
it { is_expected.to belong_to :project }
end
+ context 'redirects' do
+ it 'does not follow redirects' do
+ redirect_to = 'https://redirected.example.com'
+ redirect_req_stub = stub_prometheus_request(prometheus_query_url('1'), status: 302, headers: { location: redirect_to })
+ redirected_req_stub = stub_prometheus_request(redirect_to, body: { 'status': 'success' })
+
+ result = service.test
+
+ # result = { success: false, result: error }
+ expect(result[:success]).to be_falsy
+ expect(result[:result]).to be_instance_of(Gitlab::PrometheusClient::Error)
+
+ expect(redirect_req_stub).to have_been_requested
+ expect(redirected_req_stub).not_to have_been_requested
+ end
+ end
+
describe 'Validations' do
context 'when manual_configuration is enabled' do
before do
@@ -83,13 +102,22 @@ describe PrometheusService, :use_clean_rails_memory_store_caching do
end
end
- describe '#prometheus_installed?' do
+ describe '#prometheus_available?' do
context 'clusters with installed prometheus' do
let!(:cluster) { create(:cluster, projects: [project]) }
let!(:prometheus) { create(:clusters_applications_prometheus, :installed, cluster: cluster) }
it 'returns true' do
- expect(service.prometheus_installed?).to be(true)
+ expect(service.prometheus_available?).to be(true)
+ end
+ end
+
+ context 'clusters with updated prometheus' do
+ let!(:cluster) { create(:cluster, projects: [project]) }
+ let!(:prometheus) { create(:clusters_applications_prometheus, :updated, cluster: cluster) }
+
+ it 'returns true' do
+ expect(service.prometheus_available?).to be(true)
end
end
@@ -98,7 +126,7 @@ describe PrometheusService, :use_clean_rails_memory_store_caching do
let!(:prometheus) { create(:clusters_applications_prometheus, cluster: cluster) }
it 'returns false' do
- expect(service.prometheus_installed?).to be(false)
+ expect(service.prometheus_available?).to be(false)
end
end
@@ -106,13 +134,13 @@ describe PrometheusService, :use_clean_rails_memory_store_caching do
let(:cluster) { create(:cluster, projects: [project]) }
it 'returns false' do
- expect(service.prometheus_installed?).to be(false)
+ expect(service.prometheus_available?).to be(false)
end
end
context 'no clusters' do
it 'returns false' do
- expect(service.prometheus_installed?).to be(false)
+ expect(service.prometheus_available?).to be(false)
end
end
end
@@ -150,7 +178,7 @@ describe PrometheusService, :use_clean_rails_memory_store_caching do
context 'with prometheus installed in the cluster' do
before do
- allow(service).to receive(:prometheus_installed?).and_return(true)
+ allow(service).to receive(:prometheus_available?).and_return(true)
end
context 'when service is inactive' do
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 567b66b54eb..3f99fd12e38 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -2,11 +2,15 @@ require 'spec_helper'
describe Project do
include ProjectForksHelper
+ include GitHelpers
+
+ it_behaves_like 'having unique enum values'
describe 'associations' do
it { is_expected.to belong_to(:group) }
it { is_expected.to belong_to(:namespace) }
it { is_expected.to belong_to(:creator).class_name('User') }
+ it { is_expected.to belong_to(:pool_repository) }
it { is_expected.to have_many(:users) }
it { is_expected.to have_many(:services) }
it { is_expected.to have_many(:events) }
@@ -22,7 +26,6 @@ describe Project do
it { is_expected.to have_many(:deploy_keys) }
it { is_expected.to have_many(:hooks) }
it { is_expected.to have_many(:protected_branches) }
- it { is_expected.to have_one(:forked_project_link) }
it { is_expected.to have_one(:slack_service) }
it { is_expected.to have_one(:microsoft_teams_service) }
it { is_expected.to have_one(:mattermost_service) }
@@ -32,6 +35,7 @@ describe Project do
it { is_expected.to have_one(:asana_service) }
it { is_expected.to have_many(:boards) }
it { is_expected.to have_one(:campfire_service) }
+ it { is_expected.to have_one(:discord_service) }
it { is_expected.to have_one(:drone_ci_service) }
it { is_expected.to have_one(:emails_on_push_service) }
it { is_expected.to have_one(:pipelines_email_service) }
@@ -52,10 +56,11 @@ describe Project do
it { is_expected.to have_one(:gitlab_issue_tracker_service) }
it { is_expected.to have_one(:external_wiki_service) }
it { is_expected.to have_one(:project_feature) }
+ it { is_expected.to have_one(:project_repository) }
it { is_expected.to have_one(:statistics).class_name('ProjectStatistics') }
it { is_expected.to have_one(:import_data).class_name('ProjectImportData') }
it { is_expected.to have_one(:last_event).class_name('Event') }
- it { is_expected.to have_one(:forked_from_project).through(:forked_project_link) }
+ it { is_expected.to have_one(:forked_from_project).through(:fork_network_member) }
it { is_expected.to have_one(:auto_devops).class_name('ProjectAutoDevops') }
it { is_expected.to have_many(:commit_statuses) }
it { is_expected.to have_many(:pipelines) }
@@ -76,7 +81,8 @@ describe Project do
it { is_expected.to have_many(:lfs_objects_projects) }
it { is_expected.to have_many(:project_group_links) }
it { is_expected.to have_many(:notification_settings).dependent(:delete_all) }
- it { is_expected.to have_many(:forks).through(:forked_project_links) }
+ it { is_expected.to have_many(:forked_to_members).class_name('ForkNetworkMember') }
+ it { is_expected.to have_many(:forks).through(:forked_to_members) }
it { is_expected.to have_many(:uploads) }
it { is_expected.to have_many(:pipeline_schedules) }
it { is_expected.to have_many(:members_and_requesters) }
@@ -87,6 +93,10 @@ describe Project do
it { is_expected.to have_many(:project_deploy_tokens) }
it { is_expected.to have_many(:deploy_tokens).through(:project_deploy_tokens) }
+ it 'has an inverse relationship with merge requests' do
+ expect(described_class.reflect_on_association(:merge_requests).has_inverse?).to eq(:target_project)
+ end
+
context 'after initialized' do
it "has a project_feature" do
expect(described_class.new.project_feature).to be_present
@@ -102,22 +112,6 @@ describe Project do
end
end
- context 'Site Statistics' do
- context 'when creating a new project' do
- it 'tracks project in SiteStatistic' do
- expect { create(:project) }.to change { SiteStatistic.fetch.repositories_count }.by(1)
- end
- end
-
- context 'when deleting a project' do
- it 'untracks project in SiteStatistic' do
- project = create(:project)
-
- expect { project.destroy }.to change { SiteStatistic.fetch.repositories_count }.by(-1)
- end
- end
- end
-
context 'updating cd_cd_settings' do
it 'does not raise an error' do
project = create(:project)
@@ -227,55 +221,93 @@ describe Project do
end
end
- it 'does not allow an invalid URI as import_url' do
- project2 = build(:project, import_url: 'invalid://')
+ describe 'import_url' do
+ it 'does not allow an invalid URI as import_url' do
+ project = build(:project, import_url: 'invalid://')
- expect(project2).not_to be_valid
- end
+ expect(project).not_to be_valid
+ end
- it 'does allow a valid URI as import_url' do
- project2 = build(:project, import_url: 'ssh://test@gitlab.com/project.git')
+ it 'does allow a SSH URI as import_url for persisted projects' do
+ project = create(:project)
+ project.import_url = 'ssh://test@gitlab.com/project.git'
- expect(project2).to be_valid
- end
+ expect(project).to be_valid
+ end
- it 'allows an empty URI' do
- project2 = build(:project, import_url: '')
+ it 'does not allow a SSH URI as import_url for new projects' do
+ project = build(:project, import_url: 'ssh://test@gitlab.com/project.git')
- expect(project2).to be_valid
- end
+ expect(project).not_to be_valid
+ end
- it 'does not produce import data on an empty URI' do
- project2 = build(:project, import_url: '')
+ it 'does allow a valid URI as import_url' do
+ project = build(:project, import_url: 'http://gitlab.com/project.git')
- expect(project2.import_data).to be_nil
- end
+ expect(project).to be_valid
+ end
- it 'does not produce import data on an invalid URI' do
- project2 = build(:project, import_url: 'test://')
+ it 'allows an empty URI' do
+ project = build(:project, import_url: '')
- expect(project2.import_data).to be_nil
- end
+ expect(project).to be_valid
+ end
- it "does not allow import_url pointing to localhost" do
- project2 = build(:project, import_url: 'http://localhost:9000/t.git')
+ it 'does not produce import data on an empty URI' do
+ project = build(:project, import_url: '')
- expect(project2).to be_invalid
- expect(project2.errors[:import_url].first).to include('Requests to localhost are not allowed')
- end
+ expect(project.import_data).to be_nil
+ end
- it "does not allow import_url with invalid ports" do
- project2 = build(:project, import_url: 'http://github.com:25/t.git')
+ it 'does not produce import data on an invalid URI' do
+ project = build(:project, import_url: 'test://')
- expect(project2).to be_invalid
- expect(project2.errors[:import_url].first).to include('Only allowed ports are 22, 80, 443')
- end
+ expect(project.import_data).to be_nil
+ end
+
+ it "does not allow import_url pointing to localhost" do
+ project = build(:project, import_url: 'http://localhost:9000/t.git')
+
+ expect(project).to be_invalid
+ expect(project.errors[:import_url].first).to include('Requests to localhost are not allowed')
+ end
+
+ it "does not allow import_url with invalid ports for new projects" do
+ project = build(:project, import_url: 'http://github.com:25/t.git')
+
+ expect(project).to be_invalid
+ expect(project.errors[:import_url].first).to include('Only allowed ports are 80, 443')
+ end
+
+ it "does not allow import_url with invalid ports for persisted projects" do
+ project = create(:project)
+ project.import_url = 'http://github.com:25/t.git'
+
+ expect(project).to be_invalid
+ expect(project.errors[:import_url].first).to include('Only allowed ports are 22, 80, 443')
+ end
+
+ it "does not allow import_url with invalid user" do
+ project = build(:project, import_url: 'http://$user:password@github.com/t.git')
- it "does not allow import_url with invalid user" do
- project2 = build(:project, import_url: 'http://$user:password@github.com/t.git')
+ expect(project).to be_invalid
+ expect(project.errors[:import_url].first).to include('Username needs to start with an alphanumeric character')
+ end
+
+ include_context 'invalid urls'
+
+ it 'does not allow urls with CR or LF characters' do
+ project = build(:project)
- expect(project2).to be_invalid
- expect(project2.errors[:import_url].first).to include('Username needs to start with an alphanumeric character')
+ aggregate_failures do
+ urls_with_CRLF.each do |url|
+ project.import_url = url
+
+ expect(project).not_to be_valid
+ expect(project.errors.full_messages.first).to match(/is blocked: URI is invalid/)
+ end
+ end
+ end
end
describe 'project pending deletion' do
@@ -505,28 +537,28 @@ describe Project do
end
describe "#readme_url" do
- let(:project) { create(:project, :repository, path: "somewhere") }
-
context 'with a non-existing repository' do
- it 'returns nil' do
- allow(project.repository).to receive(:tree).with(:head).and_return(nil)
+ let(:project) { create(:project) }
+ it 'returns nil' do
expect(project.readme_url).to be_nil
end
end
context 'with an existing repository' do
context 'when no README exists' do
- it 'returns nil' do
- allow_any_instance_of(Tree).to receive(:readme).and_return(nil)
+ let(:project) { create(:project, :empty_repo) }
+ it 'returns nil' do
expect(project.readme_url).to be_nil
end
end
context 'when a README exists' do
+ let(:project) { create(:project, :repository) }
+
it 'returns the README' do
- expect(project.readme_url).to eql("#{Gitlab.config.gitlab.url}/#{project.namespace.full_path}/somewhere/blob/master/README.md")
+ expect(project.readme_url).to eq("#{project.web_url}/blob/master/README.md")
end
end
end
@@ -1358,7 +1390,7 @@ describe Project do
context 'when checking on forked project' do
let(:project) { create(:project, :internal) }
- let(:forked_project) { create(:project, forked_from_project: project) }
+ let(:forked_project) { fork_project(project) }
it { expect(forked_project.visibility_level_allowed?(Gitlab::VisibilityLevel::PRIVATE)).to be_truthy }
it { expect(forked_project.visibility_level_allowed?(Gitlab::VisibilityLevel::INTERNAL)).to be_truthy }
@@ -1589,6 +1621,30 @@ describe Project do
end
end
+ describe '#track_project_repository' do
+ let(:project) { create(:project, :repository) }
+
+ it 'creates a project_repository' do
+ project.track_project_repository
+
+ expect(project.reload.project_repository).to be_present
+ expect(project.project_repository.disk_path).to eq(project.disk_path)
+ expect(project.project_repository.shard_name).to eq(project.repository_storage)
+ end
+
+ it 'updates the project_repository' do
+ project.track_project_repository
+
+ allow(project).to receive(:disk_path).and_return('@fancy/new/path')
+
+ expect do
+ project.track_project_repository
+ end.not_to change(ProjectRepository, :count)
+
+ expect(project.reload.project_repository.disk_path).to eq(project.disk_path)
+ end
+ end
+
describe '#create_repository' do
let(:project) { create(:project, :repository) }
let(:shell) { Gitlab::Shell.new }
@@ -1674,6 +1730,16 @@ describe Project do
end
end
+ describe 'handling import URL' do
+ it 'returns the sanitized URL' do
+ project = create(:project, :import_started, import_url: 'http://user:pass@test.com')
+
+ project.import_state.finish
+
+ expect(project.reload.import_url).to eq('http://test.com')
+ end
+ end
+
describe '#container_registry_url' do
let(:project) { create(:project) }
@@ -1787,106 +1853,6 @@ describe Project do
end
end
- describe '#human_import_status_name' do
- context 'when import_state exists' do
- it 'returns the humanized status name' do
- project = create(:project)
- create(:import_state, :started, project: project)
-
- expect(project.human_import_status_name).to eq("started")
- end
- end
-
- context 'when import_state was not created yet' do
- let(:project) { create(:project, :import_started) }
-
- it 'ensures import_state is created and returns humanized status name' do
- expect do
- project.human_import_status_name
- end.to change { ProjectImportState.count }.from(0).to(1)
- end
-
- it 'returns humanized status name' do
- expect(project.human_import_status_name).to eq("started")
- end
- end
- end
-
- describe 'Project import job' do
- let(:project) { create(:project, import_url: generate(:url)) }
-
- before do
- allow_any_instance_of(Gitlab::Shell).to receive(:import_repository)
- .with(project.repository_storage, project.disk_path, project.import_url)
- .and_return(true)
-
- # Works around https://github.com/rspec/rspec-mocks/issues/910
- allow(described_class).to receive(:find).with(project.id).and_return(project)
- expect(project.repository).to receive(:after_import)
- .and_call_original
- expect(project.wiki.repository).to receive(:after_import)
- .and_call_original
- end
-
- it 'imports a project' do
- expect_any_instance_of(RepositoryImportWorker).to receive(:perform).and_call_original
-
- expect { project.import_schedule }.to change { project.import_jid }
- expect(project.reload.import_status).to eq('finished')
- end
- end
-
- describe 'project import state transitions' do
- context 'state transition: [:started] => [:finished]' do
- let(:after_import_service) { spy(:after_import_service) }
- let(:housekeeping_service) { spy(:housekeeping_service) }
-
- before do
- allow(Projects::AfterImportService)
- .to receive(:new) { after_import_service }
-
- allow(after_import_service)
- .to receive(:execute) { housekeeping_service.execute }
-
- allow(Projects::HousekeepingService)
- .to receive(:new) { housekeeping_service }
- end
-
- it 'resets project import_error' do
- error_message = 'Some error'
- mirror = create(:project_empty_repo, :import_started)
- mirror.import_state.update(last_error: error_message)
-
- expect { mirror.import_finish }.to change { mirror.import_error }.from(error_message).to(nil)
- end
-
- it 'performs housekeeping when an import of a fresh project is completed' do
- project = create(:project_empty_repo, :import_started, import_type: :github)
-
- project.import_finish
-
- expect(after_import_service).to have_received(:execute)
- expect(housekeeping_service).to have_received(:execute)
- end
-
- it 'does not perform housekeeping when project repository does not exist' do
- project = create(:project, :import_started, import_type: :github)
-
- project.import_finish
-
- expect(housekeeping_service).not_to have_received(:execute)
- end
-
- it 'does not perform housekeeping when project does not have a valid import type' do
- project = create(:project, :import_started, import_type: nil)
-
- project.import_finish
-
- expect(housekeeping_service).not_to have_received(:execute)
- end
- end
- end
-
describe '#latest_successful_builds_for' do
def create_pipeline(status = 'success')
create(:ci_pipeline, project: project,
@@ -1966,13 +1932,52 @@ describe Project do
end
end
+ describe '#import_status' do
+ context 'with import_state' do
+ it 'returns the right status' do
+ project = create(:project, :import_started)
+
+ expect(project.import_status).to eq("started")
+ end
+ end
+
+ context 'without import_state' do
+ it 'returns none' do
+ project = create(:project)
+
+ expect(project.import_status).to eq('none')
+ end
+ end
+ end
+
+ describe '#human_import_status_name' do
+ context 'with import_state' do
+ it 'returns the right human import status' do
+ project = create(:project, :import_started)
+
+ expect(project.human_import_status_name).to eq('started')
+ end
+ end
+
+ context 'without import_state' do
+ it 'returns none' do
+ project = create(:project)
+
+ expect(project.human_import_status_name).to eq('none')
+ end
+ end
+ end
+
describe '#add_import_job' do
let(:import_jid) { '123' }
context 'forked' do
- let(:forked_project_link) { create(:forked_project_link, :forked_to_empty_project) }
- let(:forked_from_project) { forked_project_link.forked_from_project }
- let(:project) { forked_project_link.forked_to_project }
+ let(:forked_from_project) { create(:project, :repository) }
+ let(:project) { create(:project) }
+
+ before do
+ fork_project(forked_from_project, nil, target_project: project)
+ end
it 'schedules a RepositoryForkWorker job' do
expect(RepositoryForkWorker).to receive(:perform_async).with(project.id).and_return(import_jid)
@@ -2172,12 +2177,6 @@ describe Project do
project.change_head(project.default_branch)
end
- it 'creates the new reference with rugged' do
- expect(project.repository.raw_repository).to receive(:write_ref).with('HEAD', "refs/heads/#{project.default_branch}", shell: false)
-
- project.change_head(project.default_branch)
- end
-
it 'copies the gitattributes' do
expect(project.repository).to receive(:copy_gitattributes).with(project.default_branch)
project.change_head(project.default_branch)
@@ -2259,6 +2258,12 @@ describe Project do
end
end
+ describe '#forks' do
+ it 'includes direct forks of the project' do
+ expect(project.forks).to contain_exactly(forked_project)
+ end
+ end
+
describe '#lfs_storage_project' do
it 'returns self for non-forks' do
expect(project.lfs_storage_project).to eq project
@@ -2370,12 +2375,24 @@ describe Project do
it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
end
- context 'when user configured kubernetes from CI/CD > Clusters' do
+ context 'when user configured kubernetes from CI/CD > Clusters and KubernetesNamespace migration has not been executed' do
let!(:cluster) { create(:cluster, :project, :provided_by_gcp) }
let(:project) { cluster.project }
it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
end
+
+ context 'when user configured kubernetes from CI/CD > Clusters and KubernetesNamespace migration has been executed' do
+ let!(:kubernetes_namespace) { create(:cluster_kubernetes_namespace, :with_token) }
+ let!(:cluster) { kubernetes_namespace.cluster }
+ let(:project) { kubernetes_namespace.project }
+
+ it 'should return token from kubernetes namespace' do
+ expect(project.deployment_variables).to include(
+ { key: 'KUBE_TOKEN', value: kubernetes_namespace.service_account_token, public: false }
+ )
+ end
+ end
end
end
@@ -2401,10 +2418,10 @@ describe Project do
end
end
- describe '#secret_variables_for' do
+ describe '#ci_variables_for' do
let(:project) { create(:project) }
- let!(:secret_variable) do
+ let!(:ci_variable) do
create(:ci_variable, value: 'secret', project: project)
end
@@ -2412,7 +2429,7 @@ describe Project do
create(:ci_variable, :protected, value: 'protected', project: project)
end
- subject { project.reload.secret_variables_for(ref: 'ref') }
+ subject { project.reload.ci_variables_for(ref: 'ref') }
before do
stub_application_setting(
@@ -2421,13 +2438,13 @@ describe Project do
shared_examples 'ref is protected' do
it 'contains all the variables' do
- is_expected.to contain_exactly(secret_variable, protected_variable)
+ is_expected.to contain_exactly(ci_variable, protected_variable)
end
end
context 'when the ref is not protected' do
- it 'contains only the secret variables' do
- is_expected.to contain_exactly(secret_variable)
+ it 'contains only the CI variables' do
+ is_expected.to contain_exactly(ci_variable)
end
end
@@ -2715,7 +2732,7 @@ describe Project do
.to raise_error(ActiveRecord::RecordNotSaved, error_message)
end
- it 'updates the project succesfully' do
+ it 'updates the project successfully' do
merge_request = create(:merge_request, target_project: project, source_project: project)
expect { project.append_or_update_attribute(:merge_requests, [merge_request]) }
@@ -2934,88 +2951,6 @@ describe Project do
end
end
- describe '#rename_repo' do
- before do
- # Project#gitlab_shell returns a new instance of Gitlab::Shell on every
- # call. This makes testing a bit easier.
- allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
- allow(project).to receive(:previous_changes).and_return('path' => ['foo'])
- stub_feature_flags(skip_hashed_storage_upgrade: false)
- end
-
- it 'renames a repository' do
- stub_container_registry_config(enabled: false)
-
- expect(gitlab_shell).to receive(:mv_repository)
- .ordered
- .with(project.repository_storage, "#{project.namespace.full_path}/foo", "#{project.full_path}")
- .and_return(true)
-
- expect(gitlab_shell).to receive(:mv_repository)
- .ordered
- .with(project.repository_storage, "#{project.namespace.full_path}/foo.wiki", "#{project.full_path}.wiki")
- .and_return(true)
-
- expect_any_instance_of(SystemHooksService)
- .to receive(:execute_hooks_for)
- .with(project, :rename)
-
- expect_any_instance_of(Gitlab::UploadsTransfer)
- .to receive(:rename_project)
- .with('foo', project.path, project.namespace.full_path)
-
- expect(project).to receive(:expire_caches_before_rename)
-
- project.rename_repo
- end
-
- context 'container registry with images' do
- let(:container_repository) { create(:container_repository) }
-
- before do
- stub_container_registry_config(enabled: true)
- stub_container_registry_tags(repository: :any, tags: ['tag'])
- project.container_repositories << container_repository
- end
-
- subject { project.rename_repo }
-
- it { expect { subject }.to raise_error(StandardError) }
- end
-
- context 'gitlab pages' do
- before do
- expect(project_storage).to receive(:rename_repo) { true }
- end
-
- it 'moves pages folder to new location' do
- expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project)
-
- project.rename_repo
- end
- end
-
- context 'attachments' do
- before do
- expect(project_storage).to receive(:rename_repo) { true }
- end
-
- it 'moves uploads folder to new location' do
- expect_any_instance_of(Gitlab::UploadsTransfer).to receive(:rename_project)
-
- project.rename_repo
- end
- end
-
- it 'updates project full path in .git/config' do
- allow(project_storage).to receive(:rename_repo).and_return(true)
-
- project.rename_repo
-
- expect(rugged_config['gitlab.fullpath']).to eq(project.full_path)
- end
- end
-
describe '#pages_path' do
it 'returns a path where pages are stored' do
expect(project.pages_path).to eq(File.join(Settings.pages.path, project.namespace.full_path, project.path))
@@ -3106,91 +3041,6 @@ describe Project do
end
end
- describe '#rename_repo' do
- before do
- # Project#gitlab_shell returns a new instance of Gitlab::Shell on every
- # call. This makes testing a bit easier.
- allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
- allow(project).to receive(:previous_changes).and_return('path' => ['foo'])
- stub_feature_flags(skip_hashed_storage_upgrade: false)
- end
-
- context 'migration to hashed storage' do
- it 'calls HashedStorageMigrationService with correct options' do
- project = create(:project, :repository, :legacy_storage)
- allow(project).to receive(:previous_changes).and_return('path' => ['foo'])
-
- expect_next_instance_of(::Projects::HashedStorageMigrationService) do |service|
- expect(service).to receive(:execute).and_return(true)
- end
-
- project.rename_repo
- end
- end
-
- it 'renames a repository' do
- stub_container_registry_config(enabled: false)
-
- expect(gitlab_shell).not_to receive(:mv_repository)
-
- expect_any_instance_of(SystemHooksService)
- .to receive(:execute_hooks_for)
- .with(project, :rename)
-
- expect(project).to receive(:expire_caches_before_rename)
-
- project.rename_repo
- end
-
- context 'container registry with images' do
- let(:container_repository) { create(:container_repository) }
-
- before do
- stub_container_registry_config(enabled: true)
- stub_container_registry_tags(repository: :any, tags: ['tag'])
- project.container_repositories << container_repository
- end
-
- subject { project.rename_repo }
-
- it { expect { subject }.to raise_error(StandardError) }
- end
-
- context 'gitlab pages' do
- it 'moves pages folder to new location' do
- expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project)
-
- project.rename_repo
- end
- end
-
- context 'attachments' do
- it 'keeps uploads folder location unchanged' do
- expect_any_instance_of(Gitlab::UploadsTransfer).not_to receive(:rename_project)
-
- project.rename_repo
- end
-
- context 'when not rolled out' do
- let(:project) { create(:project, :repository, storage_version: 1, skip_disk_validation: true) }
-
- it 'moves pages folder to hashed storage' do
- expect_next_instance_of(Projects::HashedStorage::MigrateAttachmentsService) do |service|
- expect(service).to receive(:execute)
- end
-
- project.rename_repo
- end
- end
- end
-
- it 'updates project full path in .git/config' do
- project.rename_repo
-
- expect(rugged_config['gitlab.fullpath']).to eq(project.full_path)
- end
- end
-
describe '#pages_path' do
it 'returns a path where pages are stored' do
expect(project.pages_path).to eq(File.join(Settings.pages.path, project.namespace.full_path, project.path))
@@ -3205,6 +3055,14 @@ describe Project do
it 'does not flag as read-only' do
expect { project.migrate_to_hashed_storage! }.not_to change { project.repository_read_only }
end
+
+ context 'when partially migrated' do
+ it 'returns true' do
+ project = create(:project, storage_version: 1, skip_disk_validation: true)
+
+ expect(project.migrate_to_hashed_storage!).to be_truthy
+ end
+ end
end
end
@@ -3450,7 +3308,7 @@ describe Project do
end
end
- context 'when explicitely enabled' do
+ context 'when explicitly enabled' do
context 'when domain is empty' do
before do
create(:project_auto_devops, project: project, domain: nil)
@@ -3546,13 +3404,14 @@ describe Project do
describe '#after_import' do
let(:project) { create(:project) }
+ let(:import_state) { create(:import_state, project: project) }
it 'runs the correct hooks' do
expect(project.repository).to receive(:after_import)
expect(project.wiki.repository).to receive(:after_import)
- expect(project).to receive(:import_finish)
+ expect(import_state).to receive(:finish)
expect(project).to receive(:update_project_counter_caches)
- expect(project).to receive(:remove_import_jid)
+ expect(import_state).to receive(:remove_jid)
expect(project).to receive(:after_create_default_branch)
expect(project).to receive(:refresh_markdown_cache!)
@@ -3562,6 +3421,10 @@ describe Project do
context 'branch protection' do
let(:project) { create(:project, :repository) }
+ before do
+ create(:import_state, :started, project: project)
+ end
+
it 'does not protect when branch protection is disabled' do
stub_application_setting(default_branch_protection: Gitlab::Access::PROTECTION_NONE)
@@ -3617,37 +3480,6 @@ describe Project do
end
end
- describe '#remove_import_jid', :clean_gitlab_redis_cache do
- let(:project) { }
-
- context 'without an import JID' do
- it 'does nothing' do
- project = create(:project)
-
- expect(Gitlab::SidekiqStatus)
- .not_to receive(:unset)
-
- project.remove_import_jid
- end
- end
-
- context 'with an import JID' do
- it 'unsets the import JID' do
- project = create(:project)
- create(:import_state, project: project, jid: '123')
-
- expect(Gitlab::SidekiqStatus)
- .to receive(:unset)
- .with('123')
- .and_call_original
-
- project.remove_import_jid
-
- expect(project.import_jid).to be_nil
- end
- end
- end
-
describe '#wiki_repository_exists?' do
it 'returns true when the wiki repository exists' do
project = create(:project, :wiki_repo)
@@ -3995,43 +3827,163 @@ describe Project do
end
end
- describe '#update_root_ref' do
- let(:project) { create(:project, :repository) }
+ context '#members_among' do
+ let(:users) { create_list(:user, 3) }
+ set(:group) { create(:group) }
+ set(:project) { create(:project, namespace: group) }
+
+ before do
+ project.add_guest(users.first)
+ project.group.add_maintainer(users.last)
+ end
- it 'updates the default branch when HEAD has changed' do
- stub_find_remote_root_ref(project, ref: 'feature')
+ context 'when users is an Array' do
+ it 'returns project members among the users' do
+ expect(project.members_among(users)).to eq([users.first, users.last])
+ end
- expect { project.update_root_ref('origin') }
- .to change { project.default_branch }
- .from('master')
- .to('feature')
+ it 'maintains input order' do
+ expect(project.members_among(users.reverse)).to eq([users.last, users.first])
+ end
+
+ it 'returns empty array if users is empty' do
+ result = project.members_among([])
+
+ expect(result).to be_empty
+ end
end
- it 'does not update the default branch when HEAD does not change' do
- stub_find_remote_root_ref(project, ref: 'master')
+ context 'when users is a relation' do
+ it 'returns project members among the users' do
+ result = project.members_among(User.where(id: users.map(&:id)))
- expect { project.update_root_ref('origin') }
- .not_to change { project.default_branch }
+ expect(result).to be_a(ActiveRecord::Relation)
+ expect(result).to eq([users.first, users.last])
+ end
+
+ it 'returns empty relation if users is empty' do
+ result = project.members_among(User.none)
+
+ expect(result).to be_a(ActiveRecord::Relation)
+ expect(result).to be_empty
+ end
end
+ end
+
+ describe "#find_or_initialize_services" do
+ subject { build(:project) }
- it 'does not update the default branch when HEAD does not exist' do
- stub_find_remote_root_ref(project, ref: 'foo')
+ it 'returns only enabled services' do
+ allow(Service).to receive(:available_services_names).and_return(%w(prometheus pushover))
+ allow(subject).to receive(:disabled_services).and_return(%w(prometheus))
- expect { project.update_root_ref('origin') }
- .not_to change { project.default_branch }
+ services = subject.find_or_initialize_services
+
+ expect(services.count).to eq 1
+ expect(services).to include(PushoverService)
end
+ end
+
+ describe "#find_or_initialize_service" do
+ subject { build(:project) }
+
+ it 'avoids N+1 database queries' do
+ allow(Service).to receive(:available_services_names).and_return(%w(prometheus pushover))
- def stub_find_remote_root_ref(project, ref:)
- allow(project.repository)
- .to receive(:find_remote_root_ref)
- .with('origin')
- .and_return(ref)
+ control_count = ActiveRecord::QueryRecorder.new { subject.find_or_initialize_service('prometheus') }.count
+
+ allow(Service).to receive(:available_services_names).and_call_original
+
+ expect { subject.find_or_initialize_service('prometheus') }.not_to exceed_query_limit(control_count)
+ end
+
+ it 'returns nil if service is disabled' do
+ allow(subject).to receive(:disabled_services).and_return(%w(prometheus))
+
+ expect(subject.find_or_initialize_service('prometheus')).to be_nil
end
end
- def rugged_config
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.rugged.config
+ describe '.find_without_deleted' do
+ it 'returns nil if the project is about to be removed' do
+ project = create(:project, pending_delete: true)
+
+ expect(described_class.find_without_deleted(project.id)).to be_nil
+ end
+
+ it 'returns a project when it is not about to be removed' do
+ project = create(:project)
+
+ expect(described_class.find_without_deleted(project.id)).to eq(project)
+ end
+ end
+
+ describe '.for_group' do
+ it 'returns the projects for a given group' do
+ group = create(:group)
+ project = create(:project, namespace: group)
+
+ expect(described_class.for_group(group)).to eq([project])
+ end
+ end
+
+ describe '.deployments' do
+ subject { project.deployments }
+
+ let(:project) { create(:project) }
+
+ before do
+ allow_any_instance_of(Deployment).to receive(:create_ref)
+ end
+
+ context 'when there is a deployment record with created status' do
+ let(:deployment) { create(:deployment, :created, project: project) }
+
+ it 'does not return the record' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'when there is a deployment record with running status' do
+ let(:deployment) { create(:deployment, :running, project: project) }
+
+ it 'does not return the record' do
+ is_expected.to be_empty
+ end
end
+
+ context 'when there is a deployment record with success status' do
+ let(:deployment) { create(:deployment, :success, project: project) }
+
+ it 'returns the record' do
+ is_expected.to eq([deployment])
+ end
+ end
+ end
+
+ describe '#snippets_visible?' do
+ it 'returns true when a logged in user can read snippets' do
+ project = create(:project, :public)
+ user = create(:user)
+
+ expect(project.snippets_visible?(user)).to eq(true)
+ end
+
+ it 'returns true when an anonymous user can read snippets' do
+ project = create(:project, :public)
+
+ expect(project.snippets_visible?).to eq(true)
+ end
+
+ it 'returns false when a user can not read snippets' do
+ project = create(:project, :private)
+ user = create(:user)
+
+ expect(project.snippets_visible?(user)).to eq(false)
+ end
+ end
+
+ def rugged_config
+ rugged_repo(project.repository).config
end
end
diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb
index f38fc191943..48a43801b9f 100644
--- a/spec/models/project_wiki_spec.rb
+++ b/spec/models/project_wiki_spec.rb
@@ -130,63 +130,53 @@ describe ProjectWiki do
end
describe "#find_page" do
- shared_examples 'finding a wiki page' do
- before do
- create_page("index page", "This is an awesome Gollum Wiki")
- end
-
- after do
- subject.pages.each { |page| destroy_page(page.page) }
- end
+ before do
+ create_page("index page", "This is an awesome Gollum Wiki")
+ end
- it "returns the latest version of the page if it exists" do
- page = subject.find_page("index page")
- expect(page.title).to eq("index page")
- end
+ after do
+ subject.pages.each { |page| destroy_page(page.page) }
+ end
- it "returns nil if the page does not exist" do
- expect(subject.find_page("non-existant")).to eq(nil)
- end
+ it "returns the latest version of the page if it exists" do
+ page = subject.find_page("index page")
+ expect(page.title).to eq("index page")
+ end
- it "can find a page by slug" do
- page = subject.find_page("index-page")
- expect(page.title).to eq("index page")
- end
+ it "returns nil if the page does not exist" do
+ expect(subject.find_page("non-existent")).to eq(nil)
+ end
- it "returns a WikiPage instance" do
- page = subject.find_page("index page")
- expect(page).to be_a WikiPage
- end
+ it "can find a page by slug" do
+ page = subject.find_page("index-page")
+ expect(page.title).to eq("index page")
+ end
- context 'pages with multibyte-character title' do
- before do
- create_page("autre pagé", "C'est un génial Gollum Wiki")
- end
+ it "returns a WikiPage instance" do
+ page = subject.find_page("index page")
+ expect(page).to be_a WikiPage
+ end
- it "can find a page by slug" do
- page = subject.find_page("autre pagé")
- expect(page.title).to eq("autre pagé")
- end
+ context 'pages with multibyte-character title' do
+ before do
+ create_page("autre pagé", "C'est un génial Gollum Wiki")
end
- context 'pages with invalidly-encoded content' do
- before do
- create_page("encoding is fun", "f\xFCr".b)
- end
-
- it "can find the page" do
- page = subject.find_page("encoding is fun")
- expect(page.content).to eq("fr")
- end
+ it "can find a page by slug" do
+ page = subject.find_page("autre pagé")
+ expect(page.title).to eq("autre pagé")
end
end
- context 'when Gitaly wiki_find_page is enabled' do
- it_behaves_like 'finding a wiki page'
- end
+ context 'pages with invalidly-encoded content' do
+ before do
+ create_page("encoding is fun", "f\xFCr".b)
+ end
- context 'when Gitaly wiki_find_page is disabled', :skip_gitaly_mock do
- it_behaves_like 'finding a wiki page'
+ it "can find the page" do
+ page = subject.find_page("encoding is fun")
+ expect(page.content).to eq("fr")
+ end
end
end
@@ -207,100 +197,80 @@ describe ProjectWiki do
end
describe '#find_file' do
- shared_examples 'finding a wiki file' do
- let(:image) { File.open(Rails.root.join('spec', 'fixtures', 'big-image.png')) }
-
- before do
- subject.wiki # Make sure the wiki repo exists
-
- repo_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- subject.repository.path_to_repo
- end
-
- BareRepoOperations.new(repo_path).commit_file(image, 'image.png')
- end
+ let(:image) { File.open(Rails.root.join('spec', 'fixtures', 'big-image.png')) }
- it 'returns the latest version of the file if it exists' do
- file = subject.find_file('image.png')
- expect(file.mime_type).to eq('image/png')
- end
+ before do
+ subject.wiki # Make sure the wiki repo exists
- it 'returns nil if the page does not exist' do
- expect(subject.find_file('non-existant')).to eq(nil)
+ repo_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ subject.repository.path_to_repo
end
- it 'returns a Gitlab::Git::WikiFile instance' do
- file = subject.find_file('image.png')
- expect(file).to be_a Gitlab::Git::WikiFile
- end
+ BareRepoOperations.new(repo_path).commit_file(image, 'image.png')
+ end
- it 'returns the whole file' do
- file = subject.find_file('image.png')
- image.rewind
+ it 'returns the latest version of the file if it exists' do
+ file = subject.find_file('image.png')
+ expect(file.mime_type).to eq('image/png')
+ end
- expect(file.raw_data.b).to eq(image.read.b)
- end
+ it 'returns nil if the page does not exist' do
+ expect(subject.find_file('non-existent')).to eq(nil)
end
- context 'when Gitaly wiki_find_file is enabled' do
- it_behaves_like 'finding a wiki file'
+ it 'returns a Gitlab::Git::WikiFile instance' do
+ file = subject.find_file('image.png')
+ expect(file).to be_a Gitlab::Git::WikiFile
end
- context 'when Gitaly wiki_find_file is disabled', :skip_gitaly_mock do
- it_behaves_like 'finding a wiki file'
+ it 'returns the whole file' do
+ file = subject.find_file('image.png')
+ image.rewind
+
+ expect(file.raw_data.b).to eq(image.read.b)
end
end
describe "#create_page" do
- shared_examples 'creating a wiki page' do
- after do
- destroy_page(subject.pages.first.page)
- end
-
- it "creates a new wiki page" do
- expect(subject.create_page("test page", "this is content")).not_to eq(false)
- expect(subject.pages.count).to eq(1)
- end
-
- it "returns false when a duplicate page exists" do
- subject.create_page("test page", "content")
- expect(subject.create_page("test page", "content")).to eq(false)
- end
-
- it "stores an error message when a duplicate page exists" do
- 2.times { subject.create_page("test page", "content") }
- expect(subject.error_message).to match(/Duplicate page:/)
- end
+ after do
+ destroy_page(subject.pages.first.page)
+ end
- it "sets the correct commit message" do
- subject.create_page("test page", "some content", :markdown, "commit message")
- expect(subject.pages.first.page.version.message).to eq("commit message")
- end
+ it "creates a new wiki page" do
+ expect(subject.create_page("test page", "this is content")).not_to eq(false)
+ expect(subject.pages.count).to eq(1)
+ end
- it 'sets the correct commit email' do
- subject.create_page('test page', 'content')
+ it "returns false when a duplicate page exists" do
+ subject.create_page("test page", "content")
+ expect(subject.create_page("test page", "content")).to eq(false)
+ end
- expect(user.commit_email).not_to eq(user.email)
- expect(commit.author_email).to eq(user.commit_email)
- expect(commit.committer_email).to eq(user.commit_email)
- end
+ it "stores an error message when a duplicate page exists" do
+ 2.times { subject.create_page("test page", "content") }
+ expect(subject.error_message).to match(/Duplicate page:/)
+ end
- it 'updates project activity' do
- subject.create_page('Test Page', 'This is content')
+ it "sets the correct commit message" do
+ subject.create_page("test page", "some content", :markdown, "commit message")
+ expect(subject.pages.first.page.version.message).to eq("commit message")
+ end
- project.reload
+ it 'sets the correct commit email' do
+ subject.create_page('test page', 'content')
- expect(project.last_activity_at).to be_within(1.minute).of(Time.now)
- expect(project.last_repository_updated_at).to be_within(1.minute).of(Time.now)
- end
+ expect(user.commit_email).not_to eq(user.email)
+ expect(commit.author_email).to eq(user.commit_email)
+ expect(commit.committer_email).to eq(user.commit_email)
end
- context 'when Gitaly wiki_write_page is enabled' do
- it_behaves_like 'creating a wiki page'
- end
+ it 'updates project activity' do
+ subject.create_page('Test Page', 'This is content')
- context 'when Gitaly wiki_write_page is disabled', :skip_gitaly_mock do
- it_behaves_like 'creating a wiki page'
+ project.reload
+
+ expect(project.last_activity_at).to be_within(1.minute).of(Time.now)
+ expect(project.last_repository_updated_at).to be_within(1.minute).of(Time.now)
end
end
@@ -351,41 +321,31 @@ describe ProjectWiki do
end
describe "#delete_page" do
- shared_examples 'deleting a wiki page' do
- before do
- create_page("index", "some content")
- @page = subject.wiki.page(title: "index")
- end
-
- it "deletes the page" do
- subject.delete_page(@page)
- expect(subject.pages.count).to eq(0)
- end
-
- it 'sets the correct commit email' do
- subject.delete_page(@page)
-
- expect(user.commit_email).not_to eq(user.email)
- expect(commit.author_email).to eq(user.commit_email)
- expect(commit.committer_email).to eq(user.commit_email)
- end
+ before do
+ create_page("index", "some content")
+ @page = subject.wiki.page(title: "index")
+ end
- it 'updates project activity' do
- subject.delete_page(@page)
+ it "deletes the page" do
+ subject.delete_page(@page)
+ expect(subject.pages.count).to eq(0)
+ end
- project.reload
+ it 'sets the correct commit email' do
+ subject.delete_page(@page)
- expect(project.last_activity_at).to be_within(1.minute).of(Time.now)
- expect(project.last_repository_updated_at).to be_within(1.minute).of(Time.now)
- end
+ expect(user.commit_email).not_to eq(user.email)
+ expect(commit.author_email).to eq(user.commit_email)
+ expect(commit.committer_email).to eq(user.commit_email)
end
- context 'when Gitaly wiki_delete_page is enabled' do
- it_behaves_like 'deleting a wiki page'
- end
+ it 'updates project activity' do
+ subject.delete_page(@page)
+
+ project.reload
- context 'when Gitaly wiki_delete_page is disabled', :skip_gitaly_mock do
- it_behaves_like 'deleting a wiki page'
+ expect(project.last_activity_at).to be_within(1.minute).of(Time.now)
+ expect(project.last_repository_updated_at).to be_within(1.minute).of(Time.now)
end
end
diff --git a/spec/models/prometheus_metric_spec.rb b/spec/models/prometheus_metric_spec.rb
index a83a31ae88c..3692fe9a559 100644
--- a/spec/models/prometheus_metric_spec.rb
+++ b/spec/models/prometheus_metric_spec.rb
@@ -6,6 +6,8 @@ describe PrometheusMetric do
subject { build(:prometheus_metric) }
let(:other_project) { build(:project) }
+ it_behaves_like 'having unique enum values'
+
it { is_expected.to belong_to(:project) }
it { is_expected.to validate_presence_of(:title) }
it { is_expected.to validate_presence_of(:query) }
diff --git a/spec/models/push_event_payload_spec.rb b/spec/models/push_event_payload_spec.rb
index a049ad35584..69a4922b6fd 100644
--- a/spec/models/push_event_payload_spec.rb
+++ b/spec/models/push_event_payload_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe PushEventPayload do
+ it_behaves_like 'having unique enum values'
+
describe 'saving payloads' do
it 'does not allow commit messages longer than 70 characters' do
event = create(:push_event)
diff --git a/spec/models/remote_mirror_spec.rb b/spec/models/remote_mirror_spec.rb
index 269d5deca20..b12ca79847c 100644
--- a/spec/models/remote_mirror_spec.rb
+++ b/spec/models/remote_mirror_spec.rb
@@ -1,6 +1,8 @@
require 'rails_helper'
describe RemoteMirror do
+ include GitHelpers
+
describe 'URL validation' do
context 'with a valid URL' do
it 'should be valid' do
@@ -74,9 +76,7 @@ describe RemoteMirror do
mirror.update_attribute(:url, 'http://foo:baz@test.com')
- config = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- repo.raw_repository.rugged.config
- end
+ config = rugged_repo(repo).config
expect(config["remote.#{mirror.remote_name}.url"]).to eq('http://foo:baz@test.com')
end
@@ -174,7 +174,15 @@ describe RemoteMirror do
end
context 'with remote mirroring enabled' do
+ it 'defaults to disabling only protected branches' do
+ expect(remote_mirror.only_protected_branches?).to be_falsey
+ end
+
context 'with only protected branches enabled' do
+ before do
+ remote_mirror.only_protected_branches = true
+ end
+
context 'when it did not update in the last minute' do
it 'schedules a RepositoryUpdateRemoteMirrorWorker to run now' do
expect(RepositoryUpdateRemoteMirrorWorker).to receive(:perform_async).with(remote_mirror.id, Time.now)
@@ -222,14 +230,26 @@ describe RemoteMirror do
context '#ensure_remote!' do
let(:remote_mirror) { create(:project, :repository, :remote_mirror).remote_mirrors.first }
+ let(:project) { remote_mirror.project }
+ let(:repository) { project.repository }
it 'adds a remote multiple times with no errors' do
- expect(remote_mirror.project.repository).to receive(:add_remote).with(remote_mirror.remote_name, remote_mirror.url).twice.and_call_original
+ expect(repository).to receive(:add_remote).with(remote_mirror.remote_name, remote_mirror.url).twice.and_call_original
2.times do
remote_mirror.ensure_remote!
end
end
+
+ context 'SSH public-key authentication' do
+ it 'omits the password from the URL' do
+ remote_mirror.update!(auth_method: 'ssh_public_key', url: 'ssh://git:pass@example.com')
+
+ expect(repository).to receive(:add_remote).with(remote_mirror.remote_name, 'ssh://git@example.com')
+
+ remote_mirror.ensure_remote!
+ end
+ end
end
context '#updated_since?' do
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index dffac05152b..f09b4b67061 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -2,6 +2,8 @@ require 'spec_helper'
describe Repository do
include RepoHelpers
+ include GitHelpers
+
TestBlob = Struct.new(:path)
let(:project) { create(:project, :repository) }
@@ -28,7 +30,7 @@ describe Repository do
def expect_to_raise_storage_error
expect { yield }.to raise_error do |exception|
- storage_exceptions = [Gitlab::Git::Storage::Inaccessible, Gitlab::Git::CommandError, GRPC::Unavailable]
+ storage_exceptions = [Gitlab::Git::CommandError, GRPC::Unavailable]
known_exception = storage_exceptions.select { |e| exception.is_a?(e) }
expect(known_exception).not_to be_nil
@@ -36,49 +38,29 @@ describe Repository do
end
describe '#branch_names_contains' do
- shared_examples '#branch_names_contains' do
- set(:project) { create(:project, :repository) }
- let(:repository) { project.repository }
+ set(:project) { create(:project, :repository) }
+ let(:repository) { project.repository }
- subject { repository.branch_names_contains(sample_commit.id) }
+ subject { repository.branch_names_contains(sample_commit.id) }
- it { is_expected.to include('master') }
- it { is_expected.not_to include('feature') }
- it { is_expected.not_to include('fix') }
+ it { is_expected.to include('master') }
+ it { is_expected.not_to include('feature') }
+ it { is_expected.not_to include('fix') }
- describe 'when storage is broken', :broken_storage do
- it 'should raise a storage error' do
- expect_to_raise_storage_error do
- broken_repository.branch_names_contains(sample_commit.id)
- end
+ describe 'when storage is broken', :broken_storage do
+ it 'should raise a storage error' do
+ expect_to_raise_storage_error do
+ broken_repository.branch_names_contains(sample_commit.id)
end
end
end
-
- context 'when gitaly is enabled' do
- it_behaves_like '#branch_names_contains'
- end
-
- context 'when gitaly is disabled', :skip_gitaly_mock do
- it_behaves_like '#branch_names_contains'
- end
end
describe '#tag_names_contains' do
- shared_examples '#tag_names_contains' do
- subject { repository.tag_names_contains(sample_commit.id) }
-
- it { is_expected.to include('v1.1.0') }
- it { is_expected.not_to include('v1.0.0') }
- end
+ subject { repository.tag_names_contains(sample_commit.id) }
- context 'when gitaly is enabled' do
- it_behaves_like '#tag_names_contains'
- end
-
- context 'when gitaly is enabled', :skip_gitaly_mock do
- it_behaves_like '#tag_names_contains'
- end
+ it { is_expected.to include('v1.1.0') }
+ it { is_expected.not_to include('v1.0.0') }
end
describe 'tags_sorted_by' do
@@ -137,9 +119,7 @@ describe Repository do
options = { message: 'test tag message\n',
tagger: { name: 'John Smith', email: 'john@gmail.com' } }
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- repository.rugged.tags.create(annotated_tag_name, 'a48e4fc218069f68ef2e769dd8dfea3991362175', options)
- end
+ rugged_repo(repository).tags.create(annotated_tag_name, 'a48e4fc218069f68ef2e769dd8dfea3991362175', options)
double_first = double(committed_date: Time.now - 1.second)
double_last = double(committed_date: Time.now)
@@ -151,9 +131,7 @@ describe Repository do
it { is_expected.to eq(['v1.1.0', 'v1.0.0', annotated_tag_name]) }
after do
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- repository.rugged.tags.delete(annotated_tag_name)
- end
+ rugged_repo(repository).tags.delete(annotated_tag_name)
end
end
end
@@ -188,61 +166,92 @@ describe Repository do
end
end
- describe '#last_commit_for_path' do
- shared_examples 'getting last commit for path' do
- subject { repository.last_commit_for_path(sample_commit.id, '.gitignore').id }
+ describe '#list_last_commits_for_tree' do
+ let(:path_to_commit) do
+ {
+ "encoding" => "913c66a37b4a45b9769037c55c2d238bd0942d2e",
+ "files" => "570e7b2abdd848b95f2f578043fc23bd6f6fd24d",
+ ".gitignore" => "c1acaa58bbcbc3eafe538cb8274ba387047b69f8",
+ ".gitmodules" => "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9",
+ "CHANGELOG" => "913c66a37b4a45b9769037c55c2d238bd0942d2e",
+ "CONTRIBUTING.md" => "6d394385cf567f80a8fd85055db1ab4c5295806f",
+ "Gemfile.zip" => "ae73cb07c9eeaf35924a10f713b364d32b2dd34f",
+ "LICENSE" => "1a0b36b3cdad1d2ee32457c102a8c0b7056fa863",
+ "MAINTENANCE.md" => "913c66a37b4a45b9769037c55c2d238bd0942d2e",
+ "PROCESS.md" => "913c66a37b4a45b9769037c55c2d238bd0942d2e",
+ "README.md" => "1a0b36b3cdad1d2ee32457c102a8c0b7056fa863",
+ "VERSION" => "913c66a37b4a45b9769037c55c2d238bd0942d2e",
+ "gitlab-shell" => "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9",
+ "six" => "cfe32cf61b73a0d5e9f13e774abde7ff789b1660"
+ }
+ end
- it { is_expected.to eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8') }
+ subject { repository.list_last_commits_for_tree(sample_commit.id, '.').id }
- describe 'when storage is broken', :broken_storage do
- it 'should raise a storage error' do
- expect_to_raise_storage_error do
- broken_repository.last_commit_id_for_path(sample_commit.id, '.gitignore')
- end
- end
+ it 'returns the last commits for every entry in the current path' do
+ result = repository.list_last_commits_for_tree(sample_commit.id, '.')
+
+ result.each do |key, value|
+ result[key] = value.id
end
+
+ expect(result).to include(path_to_commit)
end
- context 'when Gitaly feature last_commit_for_path is enabled' do
- it_behaves_like 'getting last commit for path'
+ it 'returns the last commits for every entry in the current path starting from the offset' do
+ result = repository.list_last_commits_for_tree(sample_commit.id, '.', offset: path_to_commit.size - 1)
+
+ expect(result.size).to eq(1)
end
- context 'when Gitaly feature last_commit_for_path is disabled', :skip_gitaly_mock do
- it_behaves_like 'getting last commit for path'
+ it 'returns a limited number of last commits for every entry in the current path starting from the offset' do
+ result = repository.list_last_commits_for_tree(sample_commit.id, '.', limit: 1)
+
+ expect(result.size).to eq(1)
end
- end
- describe '#last_commit_id_for_path' do
- shared_examples 'getting last commit ID for path' do
- subject { repository.last_commit_id_for_path(sample_commit.id, '.gitignore') }
+ it 'returns an empty hash when offset is out of bounds' do
+ result = repository.list_last_commits_for_tree(sample_commit.id, '.', offset: path_to_commit.size)
- it "returns last commit id for a given path" do
- is_expected.to eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8')
- end
+ expect(result.size).to eq(0)
+ end
+ end
- it "caches last commit id for a given path" do
- cache = repository.send(:cache)
- key = "last_commit_id_for_path:#{sample_commit.id}:#{Digest::SHA1.hexdigest('.gitignore')}"
+ describe '#last_commit_for_path' do
+ subject { repository.last_commit_for_path(sample_commit.id, '.gitignore').id }
- expect(cache).to receive(:fetch).with(key).and_return('c1acaa5')
- is_expected.to eq('c1acaa5')
- end
+ it { is_expected.to eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8') }
- describe 'when storage is broken', :broken_storage do
- it 'should raise a storage error' do
- expect_to_raise_storage_error do
- broken_repository.last_commit_for_path(sample_commit.id, '.gitignore').id
- end
+ describe 'when storage is broken', :broken_storage do
+ it 'should raise a storage error' do
+ expect_to_raise_storage_error do
+ broken_repository.last_commit_id_for_path(sample_commit.id, '.gitignore')
end
end
end
+ end
+
+ describe '#last_commit_id_for_path' do
+ subject { repository.last_commit_id_for_path(sample_commit.id, '.gitignore') }
+
+ it "returns last commit id for a given path" do
+ is_expected.to eq('c1acaa58bbcbc3eafe538cb8274ba387047b69f8')
+ end
+
+ it "caches last commit id for a given path" do
+ cache = repository.send(:cache)
+ key = "last_commit_id_for_path:#{sample_commit.id}:#{Digest::SHA1.hexdigest('.gitignore')}"
- context 'when Gitaly feature last_commit_for_path is enabled' do
- it_behaves_like 'getting last commit ID for path'
+ expect(cache).to receive(:fetch).with(key).and_return('c1acaa5')
+ is_expected.to eq('c1acaa5')
end
- context 'when Gitaly feature last_commit_for_path is disabled', :skip_gitaly_mock do
- it_behaves_like 'getting last commit ID for path'
+ describe 'when storage is broken', :broken_storage do
+ it 'should raise a storage error' do
+ expect_to_raise_storage_error do
+ broken_repository.last_commit_for_path(sample_commit.id, '.gitignore').id
+ end
+ end
end
end
@@ -325,78 +334,57 @@ describe Repository do
describe '#commits_by' do
set(:project) { create(:project, :repository) }
+ let(:oids) { TestEnv::BRANCH_SHA.values }
- shared_examples 'batch commits fetching' do
- let(:oids) { TestEnv::BRANCH_SHA.values }
+ subject { project.repository.commits_by(oids: oids) }
- subject { project.repository.commits_by(oids: oids) }
+ it 'finds each commit' do
+ expect(subject).not_to include(nil)
+ expect(subject.size).to eq(oids.size)
+ end
- it 'finds each commit' do
- expect(subject).not_to include(nil)
- expect(subject.size).to eq(oids.size)
- end
+ it 'returns only Commit instances' do
+ expect(subject).to all( be_a(Commit) )
+ end
- it 'returns only Commit instances' do
- expect(subject).to all( be_a(Commit) )
+ context 'when some commits are not found ' do
+ let(:oids) do
+ ['deadbeef'] + TestEnv::BRANCH_SHA.values.first(10)
end
- context 'when some commits are not found ' do
- let(:oids) do
- ['deadbeef'] + TestEnv::BRANCH_SHA.values.first(10)
- end
-
- it 'returns only found commits' do
- expect(subject).not_to include(nil)
- expect(subject.size).to eq(10)
- end
+ it 'returns only found commits' do
+ expect(subject).not_to include(nil)
+ expect(subject.size).to eq(10)
end
+ end
- context 'when no oids are passed' do
- let(:oids) { [] }
+ context 'when no oids are passed' do
+ let(:oids) { [] }
- it 'does not call #batch_by_oid' do
- expect(Gitlab::Git::Commit).not_to receive(:batch_by_oid)
+ it 'does not call #batch_by_oid' do
+ expect(Gitlab::Git::Commit).not_to receive(:batch_by_oid)
- subject
- end
+ subject
end
end
-
- context 'when Gitaly list_commits_by_oid is enabled' do
- it_behaves_like 'batch commits fetching'
- end
-
- context 'when Gitaly list_commits_by_oid is enabled', :disable_gitaly do
- it_behaves_like 'batch commits fetching'
- end
end
describe '#find_commits_by_message' do
- shared_examples 'finding commits by message' do
- it 'returns commits with messages containing a given string' do
- commit_ids = repository.find_commits_by_message('submodule').map(&:id)
+ it 'returns commits with messages containing a given string' do
+ commit_ids = repository.find_commits_by_message('submodule').map(&:id)
- expect(commit_ids).to include(
- '5937ac0a7beb003549fc5fd26fc247adbce4a52e',
- '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9',
- 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660'
- )
- expect(commit_ids).not_to include('913c66a37b4a45b9769037c55c2d238bd0942d2e')
- end
-
- it 'is case insensitive' do
- commit_ids = repository.find_commits_by_message('SUBMODULE').map(&:id)
-
- expect(commit_ids).to include('5937ac0a7beb003549fc5fd26fc247adbce4a52e')
- end
+ expect(commit_ids).to include(
+ '5937ac0a7beb003549fc5fd26fc247adbce4a52e',
+ '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9',
+ 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660'
+ )
+ expect(commit_ids).not_to include('913c66a37b4a45b9769037c55c2d238bd0942d2e')
end
- context 'when Gitaly commits_by_message feature is enabled' do
- it_behaves_like 'finding commits by message'
- end
+ it 'is case insensitive' do
+ commit_ids = repository.find_commits_by_message('SUBMODULE').map(&:id)
- context 'when Gitaly commits_by_message feature is disabled', :skip_gitaly_mock do
- it_behaves_like 'finding commits by message'
+ expect(commit_ids).to include('5937ac0a7beb003549fc5fd26fc247adbce4a52e')
end
describe 'when storage is broken', :broken_storage do
@@ -412,6 +400,24 @@ describe Repository do
it { is_expected.to be_nil }
end
+
+ context 'regular blob' do
+ subject { repository.blob_at(repository.head_commit.sha, '.gitignore') }
+
+ it { is_expected.to be_an_instance_of(::Blob) }
+ end
+
+ context 'readme blob on HEAD' do
+ subject { repository.blob_at(repository.head_commit.sha, 'README.md') }
+
+ it { is_expected.to be_an_instance_of(::ReadmeBlob) }
+ end
+
+ context 'readme blob not on HEAD' do
+ subject { repository.blob_at(repository.find_branch('feature').target, 'README.md') }
+
+ it { is_expected.to be_an_instance_of(::Blob) }
+ end
end
describe '#merged_to_root_ref?' do
@@ -1044,6 +1050,47 @@ describe Repository do
expect_to_raise_storage_error { broken_repository.exists? }
end
end
+
+ context 'asymmetric caching', :use_clean_rails_memory_store_caching, :request_store do
+ let(:cache) { repository.send(:cache) }
+ let(:request_store_cache) { repository.send(:request_store_cache) }
+
+ context 'when it returns true' do
+ before do
+ expect(repository.raw_repository).to receive(:exists?).once.and_return(true)
+ end
+
+ it 'caches the output in RequestStore' do
+ expect do
+ repository.exists?
+ end.to change { request_store_cache.read(:exists?) }.from(nil).to(true)
+ end
+
+ it 'caches the output in RepositoryCache' do
+ expect do
+ repository.exists?
+ end.to change { cache.read(:exists?) }.from(nil).to(true)
+ end
+ end
+
+ context 'when it returns false' do
+ before do
+ expect(repository.raw_repository).to receive(:exists?).once.and_return(false)
+ end
+
+ it 'caches the output in RequestStore' do
+ expect do
+ repository.exists?
+ end.to change { request_store_cache.read(:exists?) }.from(nil).to(false)
+ end
+
+ it 'does NOT cache the output in RepositoryCache' do
+ expect do
+ repository.exists?
+ end.not_to change { cache.read(:exists?) }.from(nil)
+ end
+ end
+ end
end
describe '#has_visible_content?' do
@@ -1220,34 +1267,23 @@ describe Repository do
describe '#merge' do
let(:merge_request) { create(:merge_request, source_branch: 'feature', target_branch: 'master', source_project: project) }
-
let(:message) { 'Test \r\n\r\n message' }
- shared_examples '#merge' do
- it 'merges the code and returns the commit id' do
- expect(merge_commit).to be_present
- expect(repository.blob_at(merge_commit.id, 'files/ruby/feature.rb')).to be_present
- end
-
- it 'sets the `in_progress_merge_commit_sha` flag for the given merge request' do
- merge_commit_id = merge(repository, user, merge_request, message)
-
- expect(merge_request.in_progress_merge_commit_sha).to eq(merge_commit_id)
- end
+ it 'merges the code and returns the commit id' do
+ expect(merge_commit).to be_present
+ expect(repository.blob_at(merge_commit.id, 'files/ruby/feature.rb')).to be_present
+ end
- it 'removes carriage returns from commit message' do
- merge_commit_id = merge(repository, user, merge_request, message)
+ it 'sets the `in_progress_merge_commit_sha` flag for the given merge request' do
+ merge_commit_id = merge(repository, user, merge_request, message)
- expect(repository.commit(merge_commit_id).message).to eq(message.delete("\r"))
- end
+ expect(merge_request.in_progress_merge_commit_sha).to eq(merge_commit_id)
end
- context 'with gitaly' do
- it_behaves_like '#merge'
- end
+ it 'removes carriage returns from commit message' do
+ merge_commit_id = merge(repository, user, merge_request, message)
- context 'without gitaly', :skip_gitaly_mock do
- it_behaves_like '#merge'
+ expect(repository.commit(merge_commit_id).message).to eq(message.delete("\r"))
end
def merge(repository, user, merge_request, message)
@@ -1284,98 +1320,78 @@ describe Repository do
end
describe '#revert' do
- shared_examples 'reverting a commit' do
- let(:new_image_commit) { repository.commit('33f3729a45c02fc67d00adb1b8bca394b0e761d9') }
- let(:update_image_commit) { repository.commit('2f63565e7aac07bcdadb654e253078b727143ec4') }
- let(:message) { 'revert message' }
-
- context 'when there is a conflict' do
- it 'raises an error' do
- expect { repository.revert(user, new_image_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
- end
- end
+ let(:new_image_commit) { repository.commit('33f3729a45c02fc67d00adb1b8bca394b0e761d9') }
+ let(:update_image_commit) { repository.commit('2f63565e7aac07bcdadb654e253078b727143ec4') }
+ let(:message) { 'revert message' }
- context 'when commit was already reverted' do
- it 'raises an error' do
- repository.revert(user, update_image_commit, 'master', message)
-
- expect { repository.revert(user, update_image_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
- end
- end
-
- context 'when commit can be reverted' do
- it 'reverts the changes' do
- expect(repository.revert(user, update_image_commit, 'master', message)).to be_truthy
- end
+ context 'when there is a conflict' do
+ it 'raises an error' do
+ expect { repository.revert(user, new_image_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
end
+ end
- context 'reverting a merge commit' do
- it 'reverts the changes' do
- merge_commit
- expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).to be_present
+ context 'when commit was already reverted' do
+ it 'raises an error' do
+ repository.revert(user, update_image_commit, 'master', message)
- repository.revert(user, merge_commit, 'master', message)
- expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).not_to be_present
- end
+ expect { repository.revert(user, update_image_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
end
end
- context 'when Gitaly revert feature is enabled' do
- it_behaves_like 'reverting a commit'
+ context 'when commit can be reverted' do
+ it 'reverts the changes' do
+ expect(repository.revert(user, update_image_commit, 'master', message)).to be_truthy
+ end
end
- context 'when Gitaly revert feature is disabled', :disable_gitaly do
- it_behaves_like 'reverting a commit'
+ context 'reverting a merge commit' do
+ it 'reverts the changes' do
+ merge_commit
+ expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).to be_present
+
+ repository.revert(user, merge_commit, 'master', message)
+ expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).not_to be_present
+ end
end
end
describe '#cherry_pick' do
- shared_examples 'cherry-picking a commit' do
- let(:conflict_commit) { repository.commit('c642fe9b8b9f28f9225d7ea953fe14e74748d53b') }
- let(:pickable_commit) { repository.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') }
- let(:pickable_merge) { repository.commit('e56497bb5f03a90a51293fc6d516788730953899') }
- let(:message) { 'cherry-pick message' }
-
- context 'when there is a conflict' do
- it 'raises an error' do
- expect { repository.cherry_pick(user, conflict_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
- end
+ let(:conflict_commit) { repository.commit('c642fe9b8b9f28f9225d7ea953fe14e74748d53b') }
+ let(:pickable_commit) { repository.commit('7d3b0f7cff5f37573aea97cebfd5692ea1689924') }
+ let(:pickable_merge) { repository.commit('e56497bb5f03a90a51293fc6d516788730953899') }
+ let(:message) { 'cherry-pick message' }
+
+ context 'when there is a conflict' do
+ it 'raises an error' do
+ expect { repository.cherry_pick(user, conflict_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
end
+ end
- context 'when commit was already cherry-picked' do
- it 'raises an error' do
- repository.cherry_pick(user, pickable_commit, 'master', message)
+ context 'when commit was already cherry-picked' do
+ it 'raises an error' do
+ repository.cherry_pick(user, pickable_commit, 'master', message)
- expect { repository.cherry_pick(user, pickable_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
- end
+ expect { repository.cherry_pick(user, pickable_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
end
+ end
- context 'when commit can be cherry-picked' do
- it 'cherry-picks the changes' do
- expect(repository.cherry_pick(user, pickable_commit, 'master', message)).to be_truthy
- end
+ context 'when commit can be cherry-picked' do
+ it 'cherry-picks the changes' do
+ expect(repository.cherry_pick(user, pickable_commit, 'master', message)).to be_truthy
end
+ end
- context 'cherry-picking a merge commit' do
- it 'cherry-picks the changes' do
- expect(repository.blob_at_branch('improve/awesome', 'foo/bar/.gitkeep')).to be_nil
+ context 'cherry-picking a merge commit' do
+ it 'cherry-picks the changes' do
+ expect(repository.blob_at_branch('improve/awesome', 'foo/bar/.gitkeep')).to be_nil
- cherry_pick_commit_sha = repository.cherry_pick(user, pickable_merge, 'improve/awesome', message)
- cherry_pick_commit_message = project.commit(cherry_pick_commit_sha).message
+ cherry_pick_commit_sha = repository.cherry_pick(user, pickable_merge, 'improve/awesome', message)
+ cherry_pick_commit_message = project.commit(cherry_pick_commit_sha).message
- expect(repository.blob_at_branch('improve/awesome', 'foo/bar/.gitkeep')).not_to be_nil
- expect(cherry_pick_commit_message).to eq(message)
- end
+ expect(repository.blob_at_branch('improve/awesome', 'foo/bar/.gitkeep')).not_to be_nil
+ expect(cherry_pick_commit_message).to eq(message)
end
end
-
- context 'when Gitaly cherry_pick feature is enabled' do
- it_behaves_like 'cherry-picking a commit'
- end
-
- context 'when Gitaly cherry_pick feature is disabled', :disable_gitaly do
- it_behaves_like 'cherry-picking a commit'
- end
end
describe '#before_delete' do
@@ -1472,12 +1488,12 @@ describe Repository do
:size,
:commit_count,
:rendered_readme,
+ :readme_path,
:contribution_guide,
:changelog,
:license_blob,
:license_key,
:gitignore,
- :koding_yml,
:gitlab_ci_yml,
:branch_names,
:tag_names,
@@ -1586,10 +1602,7 @@ describe Repository do
it 'returns the number of branches' do
expect(repository.branch_count).to be_an(Integer)
- # NOTE: Until rugged goes away, make sure rugged and gitaly are in sync
- rugged_count = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- repository.raw_repository.rugged.branches.count
- end
+ rugged_count = rugged_repo(repository).branches.count
expect(repository.branch_count).to eq(rugged_count)
end
@@ -1599,10 +1612,7 @@ describe Repository do
it 'returns the number of tags' do
expect(repository.tag_count).to be_an(Integer)
- # NOTE: Until rugged goes away, make sure rugged and gitaly are in sync
- rugged_count = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- repository.raw_repository.rugged.tags.count
- end
+ rugged_count = rugged_repo(repository).tags.count
expect(repository.tag_count).to eq(rugged_count)
end
@@ -1716,12 +1726,19 @@ describe Repository do
describe '#expire_exists_cache' do
let(:cache) { repository.send(:cache) }
+ let(:request_store_cache) { repository.send(:request_store_cache) }
it 'expires the cache' do
expect(cache).to receive(:expire).with(:exists?)
repository.expire_exists_cache
end
+
+ it 'expires the request store cache', :request_store do
+ expect(request_store_cache).to receive(:expire).with(:exists?)
+
+ repository.expire_exists_cache
+ end
end
describe '#xcode_project?' do
@@ -1830,40 +1847,65 @@ describe Repository do
end
end
- describe '#koding_yml', :use_clean_rails_memory_store_caching do
- it 'returns and caches the output' do
- expect(repository).to receive(:file_on_head)
- .with(:koding)
- .and_return(Gitlab::Git::Tree.new(path: '.koding.yml'))
- .once
+ describe '#readme', :use_clean_rails_memory_store_caching do
+ context 'with a non-existing repository' do
+ let(:project) { create(:project) }
- 2.times do
- expect(repository.koding_yml).to be_an_instance_of(Gitlab::Git::Tree)
+ it 'returns nil' do
+ expect(repository.readme).to be_nil
+ end
+ end
+
+ context 'with an existing repository' do
+ context 'when no README exists' do
+ let(:project) { create(:project, :empty_repo) }
+
+ it 'returns nil' do
+ expect(repository.readme).to be_nil
+ end
+ end
+
+ context 'when a README exists' do
+ let(:project) { create(:project, :repository) }
+
+ it 'returns the README' do
+ expect(repository.readme).to be_an_instance_of(ReadmeBlob)
+ end
end
end
end
- describe '#readme', :use_clean_rails_memory_store_caching do
+ describe '#readme_path', :use_clean_rails_memory_store_caching do
context 'with a non-existing repository' do
- it 'returns nil' do
- allow(repository).to receive(:tree).with(:head).and_return(nil)
+ let(:project) { create(:project) }
- expect(repository.readme).to be_nil
+ it 'returns nil' do
+ expect(repository.readme_path).to be_nil
end
end
context 'with an existing repository' do
context 'when no README exists' do
- it 'returns nil' do
- allow_any_instance_of(Tree).to receive(:readme).and_return(nil)
+ let(:project) { create(:project, :empty_repo) }
- expect(repository.readme).to be_nil
+ it 'returns nil' do
+ expect(repository.readme_path).to be_nil
end
end
context 'when a README exists' do
+ let(:project) { create(:project, :repository) }
+
it 'returns the README' do
- expect(repository.readme).to be_an_instance_of(ReadmeBlob)
+ expect(repository.readme_path).to eq("README.md")
+ end
+
+ it 'caches the response' do
+ expect(repository).to receive(:readme).and_call_original.once
+
+ 2.times do
+ expect(repository.readme_path).to eq("README.md")
+ end
end
end
end
@@ -1892,7 +1934,7 @@ describe Repository do
match[1].to_sym if match
end.compact
- expect(methods).to match_array(Repository::CACHED_METHODS + Repository::MEMOIZED_CACHED_METHODS)
+ expect(Repository::CACHED_METHODS + Repository::MEMOIZED_CACHED_METHODS).to include(*methods)
end
end
@@ -2037,9 +2079,10 @@ describe Repository do
describe '#refresh_method_caches' do
it 'refreshes the caches of the given types' do
expect(repository).to receive(:expire_method_caches)
- .with(%i(rendered_readme license_blob license_key license))
+ .with(%i(rendered_readme readme_path license_blob license_key license))
expect(repository).to receive(:rendered_readme)
+ expect(repository).to receive(:readme_path)
expect(repository).to receive(:license_blob)
expect(repository).to receive(:license_key)
expect(repository).to receive(:license)
@@ -2085,9 +2128,7 @@ describe Repository do
end
def create_remote_branch(remote_name, branch_name, target)
- rugged = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- repository.rugged
- end
+ rugged = rugged_repo(repository)
rugged.references.create("refs/remotes/#{remote_name}/#{branch_name}", target.id)
end
@@ -2095,33 +2136,23 @@ describe Repository do
let(:commit) { repository.commit }
let(:ancestor) { commit.parents.first }
- shared_examples '#ancestor?' do
- it 'it is an ancestor' do
- expect(repository.ancestor?(ancestor.id, commit.id)).to eq(true)
- end
-
- it 'it is not an ancestor' do
- expect(repository.ancestor?(commit.id, ancestor.id)).to eq(false)
- end
-
- it 'returns false on nil-values' do
- expect(repository.ancestor?(nil, commit.id)).to eq(false)
- expect(repository.ancestor?(ancestor.id, nil)).to eq(false)
- expect(repository.ancestor?(nil, nil)).to eq(false)
- end
+ it 'it is an ancestor' do
+ expect(repository.ancestor?(ancestor.id, commit.id)).to eq(true)
+ end
- it 'returns false for invalid commit IDs' do
- expect(repository.ancestor?(commit.id, Gitlab::Git::BLANK_SHA)).to eq(false)
- expect(repository.ancestor?( Gitlab::Git::BLANK_SHA, commit.id)).to eq(false)
- end
+ it 'it is not an ancestor' do
+ expect(repository.ancestor?(commit.id, ancestor.id)).to eq(false)
end
- context 'with Gitaly enabled' do
- it_behaves_like('#ancestor?')
+ it 'returns false on nil-values' do
+ expect(repository.ancestor?(nil, commit.id)).to eq(false)
+ expect(repository.ancestor?(ancestor.id, nil)).to eq(false)
+ expect(repository.ancestor?(nil, nil)).to eq(false)
end
- context 'with Gitaly disabled', :skip_gitaly_mock do
- it_behaves_like('#ancestor?')
+ it 'returns false for invalid commit IDs' do
+ expect(repository.ancestor?(commit.id, Gitlab::Git::BLANK_SHA)).to eq(false)
+ expect(repository.ancestor?( Gitlab::Git::BLANK_SHA, commit.id)).to eq(false)
end
end
@@ -2297,4 +2328,33 @@ describe Repository do
end
end
end
+
+ describe '#merge_base' do
+ set(:project) { create(:project, :repository) }
+ subject(:repository) { project.repository }
+
+ it 'only makes one gitaly call' do
+ expect(Gitlab::GitalyClient).to receive(:call).once.and_call_original
+
+ repository.merge_base('master', 'fix')
+ end
+ end
+
+ describe '#cache' do
+ subject(:cache) { repository.send(:cache) }
+
+ it 'returns a RepositoryCache' do
+ expect(subject).to be_kind_of Gitlab::RepositoryCache
+ end
+
+ it 'when is_wiki it includes wiki as part of key' do
+ allow(repository).to receive(:is_wiki) { true }
+
+ expect(subject.namespace).to include('wiki')
+ end
+
+ it 'when is_wiki is false extra_namespace is nil' do
+ expect(subject.namespace).not_to include('wiki')
+ end
+ end
end
diff --git a/spec/models/resource_label_event_spec.rb b/spec/models/resource_label_event_spec.rb
index da6e1b5610d..e7e3f7376e6 100644
--- a/spec/models/resource_label_event_spec.rb
+++ b/spec/models/resource_label_event_spec.rb
@@ -7,6 +7,8 @@ RSpec.describe ResourceLabelEvent, type: :model do
let(:issue) { create(:issue) }
let(:merge_request) { create(:merge_request) }
+ it_behaves_like 'having unique enum values'
+
describe 'associations' do
it { is_expected.to belong_to(:user) }
it { is_expected.to belong_to(:issue) }
diff --git a/spec/models/shard_spec.rb b/spec/models/shard_spec.rb
new file mode 100644
index 00000000000..83104711b55
--- /dev/null
+++ b/spec/models/shard_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literals: true
+require 'spec_helper'
+
+describe Shard do
+ describe '.populate!' do
+ it 'creates shards based on the config file' do
+ expect(described_class.all).to be_empty
+
+ stub_storage_settings(foo: {}, bar: {}, baz: {})
+
+ described_class.populate!
+
+ expect(described_class.all.map(&:name)).to match_array(%w[default foo bar baz])
+ end
+ end
+
+ describe '.by_name' do
+ let(:default_shard) { described_class.find_by(name: 'default') }
+
+ before do
+ described_class.populate!
+ end
+
+ it 'returns an existing shard' do
+ expect(described_class.by_name('default')).to eq(default_shard)
+ end
+
+ it 'creates a new shard' do
+ result = described_class.by_name('foo')
+
+ expect(result).not_to eq(default_shard)
+ expect(result.name).to eq('foo')
+ end
+
+ it 'retries if creation races' do
+ expect(described_class)
+ .to receive(:find_or_create_by)
+ .with(name: 'default')
+ .and_raise(ActiveRecord::RecordNotUnique, 'fail')
+ .once
+
+ expect(described_class)
+ .to receive(:find_or_create_by)
+ .with(name: 'default')
+ .and_call_original
+
+ expect(described_class.by_name('default')).to eq(default_shard)
+ end
+ end
+end
diff --git a/spec/models/site_statistic_spec.rb b/spec/models/site_statistic_spec.rb
deleted file mode 100644
index 9b056fbf332..00000000000
--- a/spec/models/site_statistic_spec.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-require 'spec_helper'
-
-describe SiteStatistic do
- describe '.fetch' do
- context 'existing record' do
- it 'returns existing SiteStatistic model' do
- statistics = create(:site_statistics)
-
- expect(described_class.fetch).to be_a(described_class)
- expect(described_class.fetch).to eq(statistics)
- end
- end
-
- context 'non existing record' do
- it 'creates a new SiteStatistic model' do
- expect(described_class.first).to be_nil
- expect(described_class.fetch).to be_a(described_class)
- end
- end
- end
-
- describe '.track' do
- context 'with allowed attributes' do
- let(:statistics) { create(:site_statistics) }
-
- it 'increases the attribute counter' do
- expect { described_class.track('repositories_count') }.to change { statistics.reload.repositories_count }.by(1)
- expect { described_class.track('wikis_count') }.to change { statistics.reload.wikis_count }.by(1)
- end
-
- it 'doesnt increase the attribute counter when an exception happens during transaction' do
- expect do
- begin
- described_class.transaction do
- described_class.track('repositories_count')
-
- raise StandardError
- end
- rescue StandardError
- # no-op
- end
- end.not_to change { statistics.reload.repositories_count }
- end
- end
-
- context 'with not allowed attributes' do
- it 'returns error' do
- expect { described_class.track('something_else') }.to raise_error(ArgumentError).with_message(/Invalid attribute: \'something_else\' to \'track\' method/)
- end
- end
- end
-
- describe '.untrack' do
- context 'with allowed attributes' do
- let(:statistics) { create(:site_statistics) }
-
- it 'decreases the attribute counter' do
- expect { described_class.untrack('repositories_count') }.to change { statistics.reload.repositories_count }.by(-1)
- expect { described_class.untrack('wikis_count') }.to change { statistics.reload.wikis_count }.by(-1)
- end
-
- it 'doesnt decrease the attribute counter when an exception happens during transaction' do
- expect do
- begin
- described_class.transaction do
- described_class.track('repositories_count')
-
- raise StandardError
- end
- rescue StandardError
- # no-op
- end
- end.not_to change { described_class.fetch.repositories_count }
- end
- end
-
- context 'with not allowed attributes' do
- it 'returns error' do
- expect { described_class.untrack('something_else') }.to raise_error(ArgumentError).with_message(/Invalid attribute: \'something_else\' to \'untrack\' method/)
- end
- end
- end
-end
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index e09d89d235d..7a7272ccb60 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -131,6 +131,217 @@ describe Snippet do
end
end
+ describe '.with_optional_visibility' do
+ context 'when a visibility level is provided' do
+ it 'returns snippets with the given visibility' do
+ create(:snippet, :private)
+
+ snippet = create(:snippet, :public)
+ snippets = described_class
+ .with_optional_visibility(Gitlab::VisibilityLevel::PUBLIC)
+
+ expect(snippets).to eq([snippet])
+ end
+ end
+
+ context 'when a visibility level is not provided' do
+ it 'returns all snippets' do
+ snippet1 = create(:snippet, :public)
+ snippet2 = create(:snippet, :private)
+ snippets = described_class.with_optional_visibility
+
+ expect(snippets).to include(snippet1, snippet2)
+ end
+ end
+ end
+
+ describe '.only_global_snippets' do
+ it 'returns snippets not associated with any projects' do
+ create(:project_snippet)
+
+ snippet = create(:snippet)
+ snippets = described_class.only_global_snippets
+
+ expect(snippets).to eq([snippet])
+ end
+ end
+
+ describe '.only_include_projects_visible_to' do
+ let!(:project1) { create(:project, :public) }
+ let!(:project2) { create(:project, :internal) }
+ let!(:project3) { create(:project, :private) }
+ let!(:snippet1) { create(:project_snippet, project: project1) }
+ let!(:snippet2) { create(:project_snippet, project: project2) }
+ let!(:snippet3) { create(:project_snippet, project: project3) }
+
+ context 'when a user is provided' do
+ it 'returns snippets visible to the user' do
+ user = create(:user)
+
+ snippets = described_class.only_include_projects_visible_to(user)
+
+ expect(snippets).to include(snippet1, snippet2)
+ expect(snippets).not_to include(snippet3)
+ end
+ end
+
+ context 'when a user is not provided' do
+ it 'returns snippets visible to anonymous users' do
+ snippets = described_class.only_include_projects_visible_to
+
+ expect(snippets).to include(snippet1)
+ expect(snippets).not_to include(snippet2, snippet3)
+ end
+ end
+ end
+
+ describe 'only_include_projects_with_snippets_enabled' do
+ context 'when the include_private option is enabled' do
+ it 'includes snippets for projects with snippets set to private' do
+ project = create(:project)
+
+ project.project_feature
+ .update(snippets_access_level: ProjectFeature::PRIVATE)
+
+ snippet = create(:project_snippet, project: project)
+
+ snippets = described_class
+ .only_include_projects_with_snippets_enabled(include_private: true)
+
+ expect(snippets).to eq([snippet])
+ end
+ end
+
+ context 'when the include_private option is not enabled' do
+ it 'does not include snippets for projects that have snippets set to private' do
+ project = create(:project)
+
+ project.project_feature
+ .update(snippets_access_level: ProjectFeature::PRIVATE)
+
+ create(:project_snippet, project: project)
+
+ snippets = described_class.only_include_projects_with_snippets_enabled
+
+ expect(snippets).to be_empty
+ end
+ end
+
+ it 'includes snippets for projects with snippets enabled' do
+ project = create(:project)
+
+ project.project_feature
+ .update(snippets_access_level: ProjectFeature::ENABLED)
+
+ snippet = create(:project_snippet, project: project)
+ snippets = described_class.only_include_projects_with_snippets_enabled
+
+ expect(snippets).to eq([snippet])
+ end
+ end
+
+ describe '.only_include_authorized_projects' do
+ it 'only includes snippets for projects the user is authorized to see' do
+ user = create(:user)
+ project1 = create(:project, :private)
+ project2 = create(:project, :private)
+
+ project1.team.add_developer(user)
+
+ create(:project_snippet, project: project2)
+
+ snippet = create(:project_snippet, project: project1)
+ snippets = described_class.only_include_authorized_projects(user)
+
+ expect(snippets).to eq([snippet])
+ end
+ end
+
+ describe '.for_project_with_user' do
+ context 'when a user is provided' do
+ it 'returns an empty collection if the user can not view the snippets' do
+ project = create(:project, :private)
+ user = create(:user)
+
+ project.project_feature
+ .update(snippets_access_level: ProjectFeature::ENABLED)
+
+ create(:project_snippet, :public, project: project)
+
+ expect(described_class.for_project_with_user(project, user)).to be_empty
+ end
+
+ it 'returns the snippets if the user is a member of the project' do
+ project = create(:project, :private)
+ user = create(:user)
+ snippet = create(:project_snippet, project: project)
+
+ project.team.add_developer(user)
+
+ snippets = described_class.for_project_with_user(project, user)
+
+ expect(snippets).to eq([snippet])
+ end
+
+ it 'returns public snippets for a public project the user is not a member of' do
+ project = create(:project, :public)
+
+ project.project_feature
+ .update(snippets_access_level: ProjectFeature::ENABLED)
+
+ user = create(:user)
+ snippet = create(:project_snippet, :public, project: project)
+
+ create(:project_snippet, :private, project: project)
+
+ snippets = described_class.for_project_with_user(project, user)
+
+ expect(snippets).to eq([snippet])
+ end
+ end
+
+ context 'when a user is not provided' do
+ it 'returns an empty collection for a private project' do
+ project = create(:project, :private)
+
+ project.project_feature
+ .update(snippets_access_level: ProjectFeature::ENABLED)
+
+ create(:project_snippet, :public, project: project)
+
+ expect(described_class.for_project_with_user(project)).to be_empty
+ end
+
+ it 'returns public snippets for a public project' do
+ project = create(:project, :public)
+ snippet = create(:project_snippet, :public, project: project)
+
+ project.project_feature
+ .update(snippets_access_level: ProjectFeature::PUBLIC)
+
+ create(:project_snippet, :private, project: project)
+
+ snippets = described_class.for_project_with_user(project)
+
+ expect(snippets).to eq([snippet])
+ end
+ end
+ end
+
+ describe '.visible_to_or_authored_by' do
+ it 'returns snippets visible to the user' do
+ user = create(:user)
+ snippet1 = create(:snippet, :public)
+ snippet2 = create(:snippet, :private, author: user)
+ snippet3 = create(:snippet, :private)
+
+ snippets = described_class.visible_to_or_authored_by(user)
+
+ expect(snippets).to include(snippet1, snippet2)
+ expect(snippets).not_to include(snippet3)
+ end
+ end
+
describe '#participants' do
let(:project) { create(:project, :public) }
let(:snippet) { create(:snippet, content: 'foo', project: project) }
diff --git a/spec/models/ssh_host_key_spec.rb b/spec/models/ssh_host_key_spec.rb
new file mode 100644
index 00000000000..75db43b3d56
--- /dev/null
+++ b/spec/models/ssh_host_key_spec.rb
@@ -0,0 +1,164 @@
+require 'spec_helper'
+
+describe SshHostKey do
+ using RSpec::Parameterized::TableSyntax
+ include ReactiveCachingHelpers
+
+ let(:key1) do
+ 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC3UpyF2iLqy1d63M6k3jH1vuEnq/NWtE+o' \
+ 'rJe1Xn7JoRbduKd6zpsJ0JhBGWgcQK0ph0aGW5PcudzzBSc+SlYfCc4GTaxDtmj41hW0o72m' \
+ 'NiuDW3oKXXShOiVRde2ZOquH8Z865jGiZIC8BI/bXZD29IGUih0hPu7Rjp70VYiE+35QRf/p' \
+ 'sD0Ddrz8QUIG3A/2dMzLI5F5ZORk3BIX2F3mJwJOvZxRhR/SqyphDMZ5eZ0EzqbFBCDE6HAB' \
+ 'Woz9ck8RBGLvCIggmDHj3FmMLcQGMDiy6wKp7QdnBtxjCP6vtE6YPUM223AqsWt+9NTtCfB8' \
+ 'YdNAH7YcHHOR1FgtSk1x'
+ end
+
+ let(:key2) do
+ 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDLIp+4ciR2YO9f9rpldc7InNQw/TBUtcNb' \
+ 'J2XR0rr15/5ytz7YM16xXG0Qjx576PNSmqs4gbTrvTuFZak+v1Jx/9deHRq/yqp9f+tv33+i' \
+ 'aJGCQCX/+OVY7aWgV2R9YsS7XQ4mnv4XlOTEssib/rGAIT+ATd/GcdYSEOO+dh4O09/6O/jI' \
+ 'MGSeP+NNetgn1nPCnLOjrXFZUnUtNDi6EEKeIlrliJjSb7Jr4f7gjvZnv4RskWHHFo8FgAAq' \
+ 't0gOMT6EmKrnypBe2vLGSAXbtkXr01q6/DNPH+n9VA1LTV6v1KN/W5CN5tQV11wRSKiM8g5O' \
+ 'Ebi86VjJRi2sOuYoXQU1'
+ end
+
+ # Purposefully ordered so that `sort` will make changes
+ let(:known_hosts) do
+ <<~EOF
+ example.com #{key1} git@localhost
+ @revoked other.example.com #{key2} git@localhost
+ EOF
+ end
+
+ let(:extra) { known_hosts + "foo\nbar\n" }
+ let(:reversed) { known_hosts.lines.reverse.join }
+
+ let(:compare_host_keys) { nil }
+
+ def stub_ssh_keyscan(args, status: true, stdout: "", stderr: "")
+ stdin = StringIO.new
+ stdout = double(:stdout, read: stdout)
+ stderr = double(:stderr, read: stderr)
+ wait_thr = double(:wait_thr, value: double(success?: status))
+
+ expect(Open3).to receive(:popen3).with({}, 'ssh-keyscan', *args).and_yield(stdin, stdout, stderr, wait_thr)
+
+ stdin
+ end
+
+ let(:project) { build(:project) }
+
+ subject(:ssh_host_key) { described_class.new(project: project, url: 'ssh://example.com:2222', compare_host_keys: compare_host_keys) }
+
+ describe '#fingerprints', :use_clean_rails_memory_store_caching do
+ it 'returns an array of indexed fingerprints when the cache is filled' do
+ stub_reactive_cache(ssh_host_key, known_hosts: known_hosts)
+
+ expected = [key1, key2]
+ .map { |data| Gitlab::SSHPublicKey.new(data) }
+ .each_with_index
+ .map { |key, i| { bits: key.bits, fingerprint: key.fingerprint, type: key.type, index: i } }
+
+ expect(ssh_host_key.fingerprints.as_json).to eq(expected)
+ end
+
+ it 'returns an empty array when the cache is empty' do
+ expect(ssh_host_key.fingerprints).to eq([])
+ end
+ end
+
+ describe '#fingerprints', :use_clean_rails_memory_store_caching do
+ it 'returns an array of indexed fingerprints when the cache is filled' do
+ stub_reactive_cache(ssh_host_key, known_hosts: known_hosts)
+
+ expect(ssh_host_key.fingerprints.as_json).to eq(
+ [
+ { bits: 2048, fingerprint: Gitlab::SSHPublicKey.new(key1).fingerprint, type: :rsa, index: 0 },
+ { bits: 2048, fingerprint: Gitlab::SSHPublicKey.new(key2).fingerprint, type: :rsa, index: 1 }
+ ]
+ )
+ end
+
+ it 'returns an empty array when the cache is empty' do
+ expect(ssh_host_key.fingerprints).to eq([])
+ end
+ end
+
+ describe '#host_keys_changed?' do
+ where(:known_hosts_a, :known_hosts_b, :result) do
+ known_hosts | extra | true
+ known_hosts | "foo\n" | true
+ known_hosts | '' | true
+ known_hosts | nil | true
+ known_hosts | known_hosts | false
+ reversed | known_hosts | false
+ extra | "foo\n" | true
+ '' | '' | false
+ nil | nil | false
+ '' | nil | false
+ end
+
+ with_them do
+ let(:compare_host_keys) { known_hosts_b }
+
+ subject { ssh_host_key.host_keys_changed? }
+
+ context '(normal)' do
+ let(:compare_host_keys) { known_hosts_b }
+
+ before do
+ expect(ssh_host_key).to receive(:known_hosts).and_return(known_hosts_a)
+ end
+
+ it { is_expected.to eq(result) }
+ end
+
+ # Comparisons should be symmetrical, so test the reverse too
+ context '(reversed)' do
+ let(:compare_host_keys) { known_hosts_a }
+
+ before do
+ expect(ssh_host_key).to receive(:known_hosts).and_return(known_hosts_b)
+ end
+
+ it { is_expected.to eq(result) }
+ end
+ end
+ end
+
+ describe '#calculate_reactive_cache' do
+ subject(:cache) { ssh_host_key.calculate_reactive_cache }
+
+ it 'writes the hostname to STDIN' do
+ stdin = stub_ssh_keyscan(%w[-T 5 -p 2222 -f-])
+
+ cache
+
+ expect(stdin.string).to eq("example.com\n")
+ end
+
+ context 'successful key scan' do
+ it 'stores the cleaned known_hosts data' do
+ stub_ssh_keyscan(%w[-T 5 -p 2222 -f-], stdout: "KEY 1\nKEY 1\n\n# comment\nKEY 2\n")
+
+ is_expected.to eq(known_hosts: "KEY 1\nKEY 2\n")
+ end
+ end
+
+ context 'failed key scan (exit code 1)' do
+ it 'returns a generic error' do
+ stub_ssh_keyscan(%w[-T 5 -p 2222 -f-], stdout: 'blarg', status: false)
+
+ is_expected.to eq(error: 'Failed to detect SSH host keys')
+ end
+ end
+
+ context 'failed key scan (exit code 0)' do
+ it 'returns a generic error' do
+ stub_ssh_keyscan(%w[-T 5 -p 2222 -f-], stderr: 'Unknown host')
+
+ is_expected.to eq(error: 'Failed to detect SSH host keys')
+ end
+ end
+ end
+end
diff --git a/spec/models/todo_spec.rb b/spec/models/todo_spec.rb
index f29abcf536e..3682e21ca40 100644
--- a/spec/models/todo_spec.rb
+++ b/spec/models/todo_spec.rb
@@ -173,4 +173,130 @@ describe Todo do
expect(subject).not_to be_self_assigned
end
end
+
+ describe '.for_action' do
+ it 'returns the todos for a given action' do
+ create(:todo, action: Todo::MENTIONED)
+
+ todo = create(:todo, action: Todo::ASSIGNED)
+
+ expect(described_class.for_action(Todo::ASSIGNED)).to eq([todo])
+ end
+ end
+
+ describe '.for_author' do
+ it 'returns the todos for a given author' do
+ user1 = create(:user)
+ user2 = create(:user)
+ todo = create(:todo, author: user1)
+
+ create(:todo, author: user2)
+
+ expect(described_class.for_author(user1)).to eq([todo])
+ end
+ end
+
+ describe '.for_project' do
+ it 'returns the todos for a given project' do
+ project1 = create(:project)
+ project2 = create(:project)
+ todo = create(:todo, project: project1)
+
+ create(:todo, project: project2)
+
+ expect(described_class.for_project(project1)).to eq([todo])
+ end
+ end
+
+ describe '.for_group' do
+ it 'returns the todos for a given group' do
+ group1 = create(:group)
+ group2 = create(:group)
+ todo = create(:todo, group: group1)
+
+ create(:todo, group: group2)
+
+ expect(described_class.for_group(group1)).to eq([todo])
+ end
+ end
+
+ describe '.for_type' do
+ it 'returns the todos for a given target type' do
+ todo = create(:todo, target: create(:issue))
+
+ create(:todo, target: create(:merge_request))
+
+ expect(described_class.for_type(Issue.name)).to eq([todo])
+ end
+ end
+
+ describe '.for_target' do
+ it 'returns the todos for a given target' do
+ todo = create(:todo, target: create(:issue))
+
+ create(:todo, target: create(:merge_request))
+
+ expect(described_class.for_type(Issue.name).for_target(todo.target))
+ .to contain_exactly(todo)
+ end
+ end
+
+ describe '.for_commit' do
+ it 'returns the todos for a commit ID' do
+ todo = create(:todo, commit_id: '123')
+
+ create(:todo, commit_id: '456')
+
+ expect(described_class.for_commit('123')).to eq([todo])
+ end
+ end
+
+ describe '.for_group_and_descendants' do
+ it 'returns the todos for a group and its descendants' do
+ parent_group = create(:group)
+ child_group = create(:group, parent: parent_group)
+
+ todo1 = create(:todo, group: parent_group)
+ todo2 = create(:todo, group: child_group)
+ todos = described_class.for_group_and_descendants(parent_group)
+
+ expect(todos).to include(todo1)
+
+ # Nested groups only work on PostgreSQL, so on MySQL todo2 won't be
+ # present.
+ expect(todos).to include(todo2) if Gitlab::Database.postgresql?
+ end
+ end
+
+ describe '.any_for_target?' do
+ it 'returns true if there are todos for a given target' do
+ todo = create(:todo)
+
+ expect(described_class.any_for_target?(todo.target)).to eq(true)
+ end
+
+ it 'returns false if there are no todos for a given target' do
+ issue = create(:issue)
+
+ expect(described_class.any_for_target?(issue)).to eq(false)
+ end
+ end
+
+ describe '.update_state' do
+ it 'updates the state of todos' do
+ todo = create(:todo, :pending)
+ ids = described_class.update_state(:done)
+
+ todo.reload
+
+ expect(ids).to eq([todo.id])
+ expect(todo.state).to eq('done')
+ end
+
+ it 'does not update todos that already have the given state' do
+ create(:todo, :pending)
+
+ expect(described_class.update_state(:pending)).to be_empty
+ end
+ end
end
diff --git a/spec/models/upload_spec.rb b/spec/models/upload_spec.rb
index 36b8e5d304f..5a0df9fbbb0 100644
--- a/spec/models/upload_spec.rb
+++ b/spec/models/upload_spec.rb
@@ -21,7 +21,8 @@ describe Upload do
path: __FILE__,
size: described_class::CHECKSUM_THRESHOLD + 1.kilobyte,
model: build_stubbed(:user),
- uploader: double('ExampleUploader')
+ uploader: double('ExampleUploader'),
+ store: ObjectStorage::Store::LOCAL
)
expect(UploadChecksumWorker)
@@ -35,7 +36,8 @@ describe Upload do
path: __FILE__,
size: described_class::CHECKSUM_THRESHOLD,
model: build_stubbed(:user),
- uploader: double('ExampleUploader')
+ uploader: double('ExampleUploader'),
+ store: ObjectStorage::Store::LOCAL
)
expect { upload.save }
@@ -60,7 +62,7 @@ describe Upload do
describe '#absolute_path' do
it 'returns the path directly when already absolute' do
path = '/path/to/namespace/project/secret/file.jpg'
- upload = described_class.new(path: path)
+ upload = described_class.new(path: path, store: ObjectStorage::Store::LOCAL)
expect(upload).not_to receive(:uploader_class)
@@ -69,7 +71,7 @@ describe Upload do
it "delegates to the uploader's absolute_path method" do
uploader = spy('FakeUploader')
- upload = described_class.new(path: 'secret/file.jpg')
+ upload = described_class.new(path: 'secret/file.jpg', store: ObjectStorage::Store::LOCAL)
expect(upload).to receive(:uploader_class).and_return(uploader)
upload.absolute_path
@@ -81,7 +83,8 @@ describe Upload do
describe '#calculate_checksum!' do
let(:upload) do
described_class.new(path: __FILE__,
- size: described_class::CHECKSUM_THRESHOLD - 1.megabyte)
+ size: described_class::CHECKSUM_THRESHOLD - 1.megabyte,
+ store: ObjectStorage::Store::LOCAL)
end
it 'sets `checksum` to SHA256 sum of the file' do
@@ -91,7 +94,7 @@ describe Upload do
.to change { upload.checksum }.from(nil).to(expected)
end
- it 'sets `checksum` to nil for a non-existant file' do
+ it 'sets `checksum` to nil for a non-existent file' do
expect(upload).to receive(:exist?).and_return(false)
checksum = Digest::SHA256.file(__FILE__).hexdigest
@@ -104,15 +107,56 @@ describe Upload do
describe '#exist?' do
it 'returns true when the file exists' do
- upload = described_class.new(path: __FILE__)
+ upload = described_class.new(path: __FILE__, store: ObjectStorage::Store::LOCAL)
expect(upload).to exist
end
- it 'returns false when the file does not exist' do
- upload = described_class.new(path: "#{__FILE__}-nope")
+ context 'when the file does not exist' do
+ it 'returns false' do
+ upload = described_class.new(path: "#{__FILE__}-nope", store: ObjectStorage::Store::LOCAL)
- expect(upload).not_to exist
+ expect(upload).not_to exist
+ end
+
+ context 'when the record is persisted' do
+ it 'sends a message to Sentry' do
+ upload = create(:upload, :issuable_upload)
+
+ expect(Gitlab::Sentry).to receive(:enabled?).and_return(true)
+ expect(Raven).to receive(:capture_message).with("Upload file does not exist", extra: upload.attributes)
+
+ upload.exist?
+ end
+
+ it 'increments a metric counter to signal a problem' do
+ upload = create(:upload, :issuable_upload)
+
+ counter = double(:counter)
+ expect(counter).to receive(:increment)
+ expect(Gitlab::Metrics).to receive(:counter).with(:upload_file_does_not_exist_total, 'The number of times an upload record could not find its file').and_return(counter)
+
+ upload.exist?
+ end
+ end
+
+ context 'when the record is not persisted' do
+ it 'does not send a message to Sentry' do
+ upload = described_class.new(path: "#{__FILE__}-nope", store: ObjectStorage::Store::LOCAL)
+
+ expect(Raven).not_to receive(:capture_message)
+
+ upload.exist?
+ end
+
+ it 'does not increment a metric counter' do
+ upload = described_class.new(path: "#{__FILE__}-nope", store: ObjectStorage::Store::LOCAL)
+
+ expect(Gitlab::Metrics).not_to receive(:counter)
+
+ upload.exist?
+ end
+ end
end
end
diff --git a/spec/models/user_callout_spec.rb b/spec/models/user_callout_spec.rb
index 64ba17c81fe..d54355afe12 100644
--- a/spec/models/user_callout_spec.rb
+++ b/spec/models/user_callout_spec.rb
@@ -3,6 +3,8 @@ require 'rails_helper'
describe UserCallout do
let!(:callout) { create(:user_callout) }
+ it_behaves_like 'having unique enum values'
+
describe 'relationships' do
it { is_expected.to belong_to(:user) }
end
diff --git a/spec/models/user_preference_spec.rb b/spec/models/user_preference_spec.rb
new file mode 100644
index 00000000000..2898613545c
--- /dev/null
+++ b/spec/models/user_preference_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe UserPreference do
+ describe '#set_notes_filter' do
+ let(:issuable) { build_stubbed(:issue) }
+ let(:user_preference) { create(:user_preference) }
+
+ shared_examples 'setting system notes' do
+ it 'returns updated discussion filter' do
+ filter_name =
+ user_preference.set_notes_filter(filter, issuable)
+
+ expect(filter_name).to eq(filter)
+ end
+
+ it 'updates discussion filter for issuable class' do
+ user_preference.set_notes_filter(filter, issuable)
+
+ expect(user_preference.reload.issue_notes_filter).to eq(filter)
+ end
+ end
+
+ context 'when filter is set to all notes' do
+ let(:filter) { described_class::NOTES_FILTERS[:all_notes] }
+
+ it_behaves_like 'setting system notes'
+ end
+
+ context 'when filter is set to only comments' do
+ let(:filter) { described_class::NOTES_FILTERS[:only_comments] }
+
+ it_behaves_like 'setting system notes'
+ end
+
+ context 'when filter is set to only activity' do
+ let(:filter) { described_class::NOTES_FILTERS[:only_activity] }
+
+ it_behaves_like 'setting system notes'
+ end
+
+ context 'when notes_filter parameter is invalid' do
+ let(:only_comments) { described_class::NOTES_FILTERS[:only_comments] }
+
+ it 'returns the current notes filter' do
+ user_preference.set_notes_filter(only_comments, issuable)
+
+ expect(user_preference.set_notes_filter(9999, issuable)).to eq(only_comments)
+ end
+ end
+ end
+end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 99d17f563d9..e5490e0a156 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -4,6 +4,8 @@ describe User do
include ProjectForksHelper
include TermsHelper
+ it_behaves_like 'having unique enum values'
+
describe 'modules' do
subject { described_class }
@@ -183,6 +185,12 @@ describe User do
expect(found_user.commit_email).to eq(user.email)
end
+ it 'returns the private commit email when commit_email has _private' do
+ user.update_column(:commit_email, Gitlab::PrivateCommitEmail::TOKEN)
+
+ expect(user.commit_email).to eq(user.private_commit_email)
+ end
+
it 'can be set to a confirmed email' do
confirmed = create(:email, :confirmed, user: user)
user.commit_email = confirmed.email
@@ -333,6 +341,40 @@ describe User do
expect(user).to be_valid
end
end
+
+ context 'set_commit_email' do
+ it 'keeps commit email when private commit email is being used' do
+ user = create(:user, commit_email: Gitlab::PrivateCommitEmail::TOKEN)
+
+ expect(user.read_attribute(:commit_email)).to eq(Gitlab::PrivateCommitEmail::TOKEN)
+ end
+
+ it 'keeps the commit email when nil' do
+ user = create(:user, commit_email: nil)
+
+ expect(user.read_attribute(:commit_email)).to be_nil
+ end
+
+ it 'reverts to nil when email is not verified' do
+ user = create(:user, commit_email: "foo@bar.com")
+
+ expect(user.read_attribute(:commit_email)).to be_nil
+ end
+ end
+
+ context 'owns_commit_email' do
+ it 'accepts private commit email' do
+ user = build(:user, commit_email: Gitlab::PrivateCommitEmail::TOKEN)
+
+ expect(user).to be_valid
+ end
+
+ it 'accepts nil commit email' do
+ user = build(:user, commit_email: nil)
+
+ expect(user).to be_valid
+ end
+ end
end
end
@@ -715,12 +757,29 @@ describe User do
end
end
+ describe 'ensure user preference' do
+ it 'has user preference upon user initialization' do
+ user = build(:user)
+
+ expect(user.user_preference).to be_present
+ expect(user.user_preference).not_to be_persisted
+ end
+ end
+
describe 'ensure incoming email token' do
it 'has incoming email token' do
user = create(:user)
expect(user.incoming_email_token).not_to be_blank
end
+
+ it 'uses SecureRandom to generate the incoming email token' do
+ expect(SecureRandom).to receive(:hex).and_return('3b8ca303')
+
+ user = create(:user)
+
+ expect(user.incoming_email_token).to eql('gitlab')
+ end
end
describe '#ensure_user_rights_and_limits' do
@@ -1058,6 +1117,14 @@ describe User do
end
describe '.find_by_any_email' do
+ it 'finds user through private commit email' do
+ user = create(:user)
+ private_email = user.private_commit_email
+
+ expect(described_class.find_by_any_email(private_email)).to eq(user)
+ expect(described_class.find_by_any_email(private_email, confirmed: true)).to eq(user)
+ end
+
it 'finds by primary email' do
user = create(:user, email: 'foo@example.com')
@@ -1065,12 +1132,45 @@ describe User do
expect(described_class.find_by_any_email(user.email, confirmed: true)).to eq user
end
- it 'finds by secondary email' do
- email = create(:email, email: 'foo@example.com')
- user = email.user
+ it 'finds by uppercased email' do
+ user = create(:user, email: 'foo@example.com')
+
+ expect(described_class.find_by_any_email(user.email.upcase)).to eq user
+ expect(described_class.find_by_any_email(user.email.upcase, confirmed: true)).to eq user
+ end
+
+ context 'finds by secondary email' do
+ let(:user) { email.user }
+
+ context 'primary email confirmed' do
+ context 'secondary email confirmed' do
+ let!(:email) { create(:email, :confirmed, email: 'foo@example.com') }
+
+ it 'finds user respecting the confirmed flag' do
+ expect(described_class.find_by_any_email(email.email)).to eq user
+ expect(described_class.find_by_any_email(email.email, confirmed: true)).to eq user
+ end
+ end
+
+ context 'secondary email not confirmed' do
+ let!(:email) { create(:email, email: 'foo@example.com') }
- expect(described_class.find_by_any_email(email.email)).to eq user
- expect(described_class.find_by_any_email(email.email, confirmed: true)).to eq user
+ it 'finds user respecting the confirmed flag' do
+ expect(described_class.find_by_any_email(email.email)).to eq user
+ expect(described_class.find_by_any_email(email.email, confirmed: true)).to be_nil
+ end
+ end
+ end
+
+ context 'primary email not confirmed' do
+ let(:user) { create(:user, confirmed_at: nil) }
+ let!(:email) { create(:email, :confirmed, user: user, email: 'foo@example.com') }
+
+ it 'finds user respecting the confirmed flag' do
+ expect(described_class.find_by_any_email(email.email)).to eq user
+ expect(described_class.find_by_any_email(email.email, confirmed: true)).to be_nil
+ end
+ end
end
it 'returns nil when nothing found' do
@@ -1102,6 +1202,22 @@ describe User do
expect(described_class.by_any_email(user.email, confirmed: true)).to eq([user])
end
+
+ it 'finds user through a private commit email' do
+ user = create(:user)
+ private_email = user.private_commit_email
+
+ expect(described_class.by_any_email(private_email)).to eq([user])
+ expect(described_class.by_any_email(private_email, confirmed: true)).to eq([user])
+ end
+
+ it 'finds user through a private commit email in an array' do
+ user = create(:user)
+ private_email = user.private_commit_email
+
+ expect(described_class.by_any_email([private_email])).to eq([user])
+ expect(described_class.by_any_email([private_email], confirmed: true)).to eq([user])
+ end
end
describe '.search' do
@@ -1429,7 +1545,12 @@ describe User do
email_unconfirmed = create :email, user: user
user.reload
- expect(user.all_emails).to match_array([user.email, email_unconfirmed.email, email_confirmed.email])
+ expect(user.all_emails).to contain_exactly(
+ user.email,
+ user.private_commit_email,
+ email_unconfirmed.email,
+ email_confirmed.email
+ )
end
end
@@ -1440,7 +1561,11 @@ describe User do
email_confirmed = create :email, user: user, confirmed_at: Time.now
create :email, user: user
- expect(user.verified_emails).to match_array([user.email, email_confirmed.email])
+ expect(user.verified_emails).to contain_exactly(
+ user.email,
+ user.private_commit_email,
+ email_confirmed.email
+ )
end
end
@@ -1456,6 +1581,18 @@ describe User do
expect(user.verified_email?(email_confirmed.email.titlecase)).to be_truthy
end
+ it 'returns true when user is found through private commit email' do
+ expect(user.verified_email?(user.private_commit_email)).to be_truthy
+ end
+
+ it 'returns true for an outdated private commit email' do
+ old_email = user.private_commit_email
+
+ user.update!(username: 'changed-username')
+
+ expect(user.verified_email?(old_email)).to be_truthy
+ end
+
it 'returns false when the email is not verified/confirmed' do
email_unconfirmed = create :email, user: user
user.reload
@@ -1651,6 +1788,24 @@ describe User do
end
end
+ describe '.find_by_private_commit_email' do
+ context 'with email' do
+ set(:user) { create(:user) }
+
+ it 'returns user through private commit email' do
+ expect(described_class.find_by_private_commit_email(user.private_commit_email)).to eq(user)
+ end
+
+ it 'returns nil when email other than private_commit_email is used' do
+ expect(described_class.find_by_private_commit_email(user.email)).to be_nil
+ end
+ end
+
+ it 'returns nil when email is nil' do
+ expect(described_class.find_by_private_commit_email(nil)).to be_nil
+ end
+ end
+
describe '#sort_by_attribute' do
before do
described_class.delete_all
diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb
index 63850939be1..cba22b2cc4e 100644
--- a/spec/models/wiki_page_spec.rb
+++ b/spec/models/wiki_page_spec.rb
@@ -77,7 +77,7 @@ describe WikiPage do
end
describe "#initialize" do
- context "when initialized with an existing gollum page" do
+ context "when initialized with an existing page" do
before do
create_page("test page", "test content")
@page = wiki.wiki.page(title: "test page")
@@ -126,23 +126,34 @@ describe WikiPage do
end
end
- before do
- @wiki_attr = { title: "Index", content: "Home Page", format: "markdown" }
- end
-
describe "#create" do
+ let(:wiki_attr) do
+ {
+ title: "Index",
+ content: "Home Page",
+ format: "markdown",
+ message: 'Custom Commit Message'
+ }
+ end
+
after do
destroy_page("Index")
end
context "with valid attributes" do
it "saves the wiki page" do
- subject.create(@wiki_attr)
+ subject.create(wiki_attr)
expect(wiki.find_page("Index")).not_to be_nil
end
it "returns true" do
- expect(subject.create(@wiki_attr)).to eq(true)
+ expect(subject.create(wiki_attr)).to eq(true)
+ end
+
+ it 'saves the wiki page with message' do
+ subject.create(wiki_attr)
+
+ expect(wiki.find_page("Index").message).to eq 'Custom Commit Message'
end
end
end
@@ -189,180 +200,160 @@ describe WikiPage do
end
describe '#create' do
- shared_examples 'create method' do
- context 'with valid attributes' do
- it 'raises an error if a page with the same path already exists' do
- create_page('New Page', 'content')
- create_page('foo/bar', 'content')
- expect { create_page('New Page', 'other content') }.to raise_error Gitlab::Git::Wiki::DuplicatePageError
- expect { create_page('foo/bar', 'other content') }.to raise_error Gitlab::Git::Wiki::DuplicatePageError
-
- destroy_page('New Page')
- destroy_page('bar', 'foo')
- end
+ context 'with valid attributes' do
+ it 'raises an error if a page with the same path already exists' do
+ create_page('New Page', 'content')
+ create_page('foo/bar', 'content')
+ expect { create_page('New Page', 'other content') }.to raise_error Gitlab::Git::Wiki::DuplicatePageError
+ expect { create_page('foo/bar', 'other content') }.to raise_error Gitlab::Git::Wiki::DuplicatePageError
+
+ destroy_page('New Page')
+ destroy_page('bar', 'foo')
+ end
- it 'if the title is preceded by a / it is removed' do
- create_page('/New Page', 'content')
+ it 'if the title is preceded by a / it is removed' do
+ create_page('/New Page', 'content')
- expect(wiki.find_page('New Page')).not_to be_nil
+ expect(wiki.find_page('New Page')).not_to be_nil
- destroy_page('New Page')
- end
+ destroy_page('New Page')
end
end
+ end
- context 'when Gitaly is enabled' do
- it_behaves_like 'create method'
+ describe "#update" do
+ before do
+ create_page("Update", "content")
+ @page = wiki.find_page("Update")
end
- context 'when Gitaly is disabled', :skip_gitaly_mock do
- it_behaves_like 'create method'
+ after do
+ destroy_page(@page.title, @page.directory)
end
- end
- describe "#update" do
- shared_examples 'update method' do
- before do
- create_page("Update", "content")
+ context "with valid attributes" do
+ it "updates the content of the page" do
+ new_content = "new content"
+
+ @page.update(content: new_content)
@page = wiki.find_page("Update")
- end
- after do
- destroy_page(@page.title, @page.directory)
+ expect(@page.content).to eq("new content")
end
- context "with valid attributes" do
- it "updates the content of the page" do
- new_content = "new content"
-
- @page.update(content: new_content)
- @page = wiki.find_page("Update")
-
- expect(@page.content).to eq("new content")
- end
+ it "updates the title of the page" do
+ new_title = "Index v.1.2.4"
- it "updates the title of the page" do
- new_title = "Index v.1.2.4"
+ @page.update(title: new_title)
+ @page = wiki.find_page(new_title)
- @page.update(title: new_title)
- @page = wiki.find_page(new_title)
-
- expect(@page.title).to eq(new_title)
- end
+ expect(@page.title).to eq(new_title)
+ end
- it "returns true" do
- expect(@page.update(content: "more content")).to be_truthy
- end
+ it "returns true" do
+ expect(@page.update(content: "more content")).to be_truthy
end
+ end
- context 'with same last commit sha' do
- it 'returns true' do
- expect(@page.update(content: 'more content', last_commit_sha: @page.last_commit_sha)).to be_truthy
- end
+ context 'with same last commit sha' do
+ it 'returns true' do
+ expect(@page.update(content: 'more content', last_commit_sha: @page.last_commit_sha)).to be_truthy
end
+ end
- context 'with different last commit sha' do
- it 'raises exception' do
- expect { @page.update(content: 'more content', last_commit_sha: 'xxx') }.to raise_error(WikiPage::PageChangedError)
- end
+ context 'with different last commit sha' do
+ it 'raises exception' do
+ expect { @page.update(content: 'more content', last_commit_sha: 'xxx') }.to raise_error(WikiPage::PageChangedError)
end
+ end
- context 'when renaming a page' do
- it 'raises an error if the page already exists' do
- create_page('Existing Page', 'content')
+ context 'when renaming a page' do
+ it 'raises an error if the page already exists' do
+ create_page('Existing Page', 'content')
- expect { @page.update(title: 'Existing Page', content: 'new_content') }.to raise_error(WikiPage::PageRenameError)
- expect(@page.title).to eq 'Update'
- expect(@page.content).to eq 'new_content'
+ expect { @page.update(title: 'Existing Page', content: 'new_content') }.to raise_error(WikiPage::PageRenameError)
+ expect(@page.title).to eq 'Update'
+ expect(@page.content).to eq 'new_content'
- destroy_page('Existing Page')
- end
+ destroy_page('Existing Page')
+ end
- it 'updates the content and rename the file' do
- new_title = 'Renamed Page'
- new_content = 'updated content'
+ it 'updates the content and rename the file' do
+ new_title = 'Renamed Page'
+ new_content = 'updated content'
- expect(@page.update(title: new_title, content: new_content)).to be_truthy
+ expect(@page.update(title: new_title, content: new_content)).to be_truthy
- @page = wiki.find_page(new_title)
+ @page = wiki.find_page(new_title)
- expect(@page).not_to be_nil
- expect(@page.content).to eq new_content
- end
+ expect(@page).not_to be_nil
+ expect(@page.content).to eq new_content
end
+ end
- context 'when moving a page' do
- it 'raises an error if the page already exists' do
- create_page('foo/Existing Page', 'content')
-
- expect { @page.update(title: 'foo/Existing Page', content: 'new_content') }.to raise_error(WikiPage::PageRenameError)
- expect(@page.title).to eq 'Update'
- expect(@page.content).to eq 'new_content'
-
- destroy_page('Existing Page', 'foo')
- end
+ context 'when moving a page' do
+ it 'raises an error if the page already exists' do
+ create_page('foo/Existing Page', 'content')
- it 'updates the content and moves the file' do
- new_title = 'foo/Other Page'
- new_content = 'new_content'
+ expect { @page.update(title: 'foo/Existing Page', content: 'new_content') }.to raise_error(WikiPage::PageRenameError)
+ expect(@page.title).to eq 'Update'
+ expect(@page.content).to eq 'new_content'
- expect(@page.update(title: new_title, content: new_content)).to be_truthy
+ destroy_page('Existing Page', 'foo')
+ end
- page = wiki.find_page(new_title)
+ it 'updates the content and moves the file' do
+ new_title = 'foo/Other Page'
+ new_content = 'new_content'
- expect(page).not_to be_nil
- expect(page.content).to eq new_content
- end
+ expect(@page.update(title: new_title, content: new_content)).to be_truthy
- context 'in subdir' do
- before do
- create_page('foo/Existing Page', 'content')
- @page = wiki.find_page('foo/Existing Page')
- end
+ page = wiki.find_page(new_title)
- it 'moves the page to the root folder if the title is preceded by /', :skip_gitaly_mock do
- expect(@page.slug).to eq 'foo/Existing-Page'
- expect(@page.update(title: '/Existing Page', content: 'new_content')).to be_truthy
- expect(@page.slug).to eq 'Existing-Page'
- end
+ expect(page).not_to be_nil
+ expect(page.content).to eq new_content
+ end
- it 'does nothing if it has the same title' do
- original_path = @page.slug
+ context 'in subdir' do
+ before do
+ create_page('foo/Existing Page', 'content')
+ @page = wiki.find_page('foo/Existing Page')
+ end
- expect(@page.update(title: 'Existing Page', content: 'new_content')).to be_truthy
- expect(@page.slug).to eq original_path
- end
+ it 'moves the page to the root folder if the title is preceded by /' do
+ expect(@page.slug).to eq 'foo/Existing-Page'
+ expect(@page.update(title: '/Existing Page', content: 'new_content')).to be_truthy
+ expect(@page.slug).to eq 'Existing-Page'
end
- context 'in root dir' do
- it 'does nothing if the title is preceded by /' do
- original_path = @page.slug
+ it 'does nothing if it has the same title' do
+ original_path = @page.slug
- expect(@page.update(title: '/Update', content: 'new_content')).to be_truthy
- expect(@page.slug).to eq original_path
- end
+ expect(@page.update(title: 'Existing Page', content: 'new_content')).to be_truthy
+ expect(@page.slug).to eq original_path
end
end
- context "with invalid attributes" do
- it 'aborts update if title blank' do
- expect(@page.update(title: '', content: 'new_content')).to be_falsey
- expect(@page.content).to eq 'new_content'
-
- page = wiki.find_page('Update')
- expect(page.content).to eq 'content'
+ context 'in root dir' do
+ it 'does nothing if the title is preceded by /' do
+ original_path = @page.slug
- @page.title = 'Update'
+ expect(@page.update(title: '/Update', content: 'new_content')).to be_truthy
+ expect(@page.slug).to eq original_path
end
end
end
- context 'when Gitaly is enabled' do
- it_behaves_like 'update method'
- end
+ context "with invalid attributes" do
+ it 'aborts update if title blank' do
+ expect(@page.update(title: '', content: 'new_content')).to be_falsey
+ expect(@page.content).to eq 'new_content'
- context 'when Gitaly is disabled', :skip_gitaly_mock do
- it_behaves_like 'update method'
+ page = wiki.find_page('Update')
+ expect(page.content).to eq 'content'
+
+ @page.title = 'Update'
+ end
end
end
@@ -383,34 +374,24 @@ describe WikiPage do
end
describe "#versions" do
- shared_examples 'wiki page versions' do
- let(:page) { wiki.find_page("Update") }
-
- before do
- create_page("Update", "content")
- end
-
- after do
- destroy_page("Update")
- end
+ let(:page) { wiki.find_page("Update") }
- it "returns an array of all commits for the page" do
- 3.times { |i| page.update(content: "content #{i}") }
-
- expect(page.versions.count).to eq(4)
- end
+ before do
+ create_page("Update", "content")
+ end
- it 'returns instances of WikiPageVersion' do
- expect(page.versions).to all( be_a(Gitlab::Git::WikiPageVersion) )
- end
+ after do
+ destroy_page("Update")
end
- context 'when Gitaly is enabled' do
- it_behaves_like 'wiki page versions'
+ it "returns an array of all commits for the page" do
+ 3.times { |i| page.update(content: "content #{i}") }
+
+ expect(page.versions.count).to eq(4)
end
- context 'when Gitaly is disabled', :disable_gitaly do
- it_behaves_like 'wiki page versions'
+ it 'returns instances of WikiPageVersion' do
+ expect(page.versions).to all( be_a(Gitlab::Git::WikiPageVersion) )
end
end
@@ -457,6 +438,12 @@ describe WikiPage do
end
describe '#historical?' do
+ let(:page) { wiki.find_page('Update') }
+ let(:old_version) { page.versions.last.id }
+ let(:old_page) { wiki.find_page('Update', old_version) }
+ let(:latest_version) { page.versions.first.id }
+ let(:latest_page) { wiki.find_page('Update', latest_version) }
+
before do
create_page('Update', 'content')
@page = wiki.find_page('Update')
@@ -468,23 +455,27 @@ describe WikiPage do
end
it 'returns true when requesting an old version' do
- old_version = @page.versions.last.id
- old_page = wiki.find_page('Update', old_version)
-
- expect(old_page.historical?).to eq true
+ expect(old_page.historical?).to be_truthy
end
it 'returns false when requesting latest version' do
- latest_version = @page.versions.first.id
- latest_page = wiki.find_page('Update', latest_version)
-
- expect(latest_page.historical?).to eq false
+ expect(latest_page.historical?).to be_falsy
end
it 'returns false when version is nil' do
- latest_page = wiki.find_page('Update', nil)
+ expect(latest_page.historical?).to be_falsy
+ end
+
+ it 'returns false when the last version is nil' do
+ expect(old_page).to receive(:last_version) { nil }
+
+ expect(old_page.historical?).to be_falsy
+ end
+
+ it 'returns false when the version is nil' do
+ expect(old_page).to receive(:version) { nil }
- expect(latest_page.historical?).to eq false
+ expect(old_page.historical?).to be_falsy
end
end
@@ -534,23 +525,13 @@ describe WikiPage do
end
describe '#formatted_content' do
- shared_examples 'fetching page formatted content' do
- it 'returns processed content of the page' do
- subject.create({ title: "RDoc", content: "*bold*", format: "rdoc" })
- page = wiki.find_page('RDoc')
+ it 'returns processed content of the page' do
+ subject.create({ title: "RDoc", content: "*bold*", format: "rdoc" })
+ page = wiki.find_page('RDoc')
- expect(page.formatted_content).to eq("\n<p><strong>bold</strong></p>\n")
-
- destroy_page('RDoc')
- end
- end
-
- context 'when Gitaly wiki_page_formatted_data is enabled' do
- it_behaves_like 'fetching page formatted content'
- end
+ expect(page.formatted_content).to eq("\n<p><strong>bold</strong></p>\n")
- context 'when Gitaly wiki_page_formatted_data is disabled', :disable_gitaly do
- it_behaves_like 'fetching page formatted content'
+ destroy_page('RDoc')
end
end
diff --git a/spec/policies/ci/pipeline_policy_spec.rb b/spec/policies/ci/pipeline_policy_spec.rb
index bd32faf06ef..8022f61e67d 100644
--- a/spec/policies/ci/pipeline_policy_spec.rb
+++ b/spec/policies/ci/pipeline_policy_spec.rb
@@ -74,5 +74,23 @@ describe Ci::PipelinePolicy, :models do
expect(policy).to be_allowed :update_pipeline
end
end
+
+ describe 'destroy_pipeline' do
+ let(:project) { create(:project, :public) }
+
+ context 'when user has owner access' do
+ let(:user) { project.owner }
+
+ it 'is enabled' do
+ expect(policy).to be_allowed :destroy_pipeline
+ end
+ end
+
+ context 'when user is not owner' do
+ it 'is disabled' do
+ expect(policy).not_to be_allowed :destroy_pipeline
+ end
+ end
+ end
end
end
diff --git a/spec/policies/ci/pipeline_schedule_policy_spec.rb b/spec/policies/ci/pipeline_schedule_policy_spec.rb
index f1d3cd04e32..5a56e91cd69 100644
--- a/spec/policies/ci/pipeline_schedule_policy_spec.rb
+++ b/spec/policies/ci/pipeline_schedule_policy_spec.rb
@@ -70,7 +70,7 @@ describe Ci::PipelineSchedulePolicy, :models do
pipeline_schedule.update(owner: user)
end
- it 'includes abilities to do do all operations on pipeline schedule' do
+ it 'includes abilities to do all operations on pipeline schedule' do
expect(policy).to be_allowed :play_pipeline_schedule
expect(policy).to be_allowed :update_pipeline_schedule
expect(policy).to be_allowed :admin_pipeline_schedule
@@ -82,7 +82,7 @@ describe Ci::PipelineSchedulePolicy, :models do
project.add_maintainer(user)
end
- it 'includes abilities to do do all operations on pipeline schedule' do
+ it 'includes abilities to do all operations on pipeline schedule' do
expect(policy).to be_allowed :play_pipeline_schedule
expect(policy).to be_allowed :update_pipeline_schedule
expect(policy).to be_allowed :admin_pipeline_schedule
diff --git a/spec/policies/clusters/cluster_policy_spec.rb b/spec/policies/clusters/cluster_policy_spec.rb
index ced969830d8..b2f0ca1bc30 100644
--- a/spec/policies/clusters/cluster_policy_spec.rb
+++ b/spec/policies/clusters/cluster_policy_spec.rb
@@ -24,5 +24,47 @@ describe Clusters::ClusterPolicy, :models do
it { expect(policy).to be_allowed :update_cluster }
it { expect(policy).to be_allowed :admin_cluster }
end
+
+ context 'group cluster' do
+ let(:cluster) { create(:cluster, :group) }
+ let(:group) { cluster.group }
+ let(:project) { create(:project, namespace: group) }
+
+ context 'when group developer' do
+ before do
+ group.add_developer(user)
+ end
+
+ it { expect(policy).to be_disallowed :update_cluster }
+ it { expect(policy).to be_disallowed :admin_cluster }
+ end
+
+ context 'when group maintainer' do
+ before do
+ group.add_maintainer(user)
+ end
+
+ it { expect(policy).to be_allowed :update_cluster }
+ it { expect(policy).to be_allowed :admin_cluster }
+ end
+
+ context 'when project maintainer' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it { expect(policy).to be_disallowed :update_cluster }
+ it { expect(policy).to be_disallowed :admin_cluster }
+ end
+
+ context 'when project developer' do
+ before do
+ project.add_developer(user)
+ end
+
+ it { expect(policy).to be_disallowed :update_cluster }
+ it { expect(policy).to be_disallowed :admin_cluster }
+ end
+ end
end
end
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index 5e583be457e..9d0093e8159 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -21,7 +21,11 @@ describe GroupPolicy do
let(:maintainer_permissions) do
[
- :create_projects
+ :create_projects,
+ :read_cluster,
+ :create_cluster,
+ :update_cluster,
+ :admin_cluster
]
end
diff --git a/spec/policies/issue_policy_spec.rb b/spec/policies/issue_policy_spec.rb
index 93e85b3a6fa..008d118b557 100644
--- a/spec/policies/issue_policy_spec.rb
+++ b/spec/policies/issue_policy_spec.rb
@@ -112,7 +112,7 @@ describe IssuePolicy do
let(:project) { create(:project, :public) }
let(:issue) { create(:issue, project: project, assignees: [assignee], author: author) }
let(:issue_no_assignee) { create(:issue, project: project) }
- let(:issue_locked) { create(:issue, project: project, discussion_locked: true, author: author, assignees: [assignee]) }
+ let(:issue_locked) { create(:issue, :locked, project: project, author: author, assignees: [assignee]) }
before do
project.add_guest(guest)
diff --git a/spec/policies/note_policy_spec.rb b/spec/policies/note_policy_spec.rb
index e8096358f7d..7e25c53e77c 100644
--- a/spec/policies/note_policy_spec.rb
+++ b/spec/policies/note_policy_spec.rb
@@ -10,11 +10,50 @@ describe NotePolicy, mdoels: true do
return @policies if @policies
noteable ||= issue
- note = create(:note, noteable: noteable, author: user, project: project)
+ note = if noteable.is_a?(Commit)
+ create(:note_on_commit, commit_id: noteable.id, author: user, project: project)
+ else
+ create(:note, noteable: noteable, author: user, project: project)
+ end
@policies = described_class.new(user, note)
end
+ shared_examples_for 'a discussion with a private noteable' do
+ let(:noteable) { issue }
+ let(:policy) { policies(noteable) }
+
+ context 'when the note author can no longer see the noteable' do
+ it 'can not edit nor read the note' do
+ expect(policy).to be_disallowed(:admin_note)
+ expect(policy).to be_disallowed(:resolve_note)
+ expect(policy).to be_disallowed(:read_note)
+ end
+ end
+
+ context 'when the note author can still see the noteable' do
+ before do
+ project.add_developer(user)
+ end
+
+ it 'can edit the note' do
+ expect(policy).to be_allowed(:admin_note)
+ expect(policy).to be_allowed(:resolve_note)
+ expect(policy).to be_allowed(:read_note)
+ end
+ end
+ end
+
+ context 'when the project is private' do
+ let(:project) { create(:project, :private, :repository) }
+
+ context 'when the noteable is a commit' do
+ it_behaves_like 'a discussion with a private noteable' do
+ let(:noteable) { project.repository.head_commit }
+ end
+ end
+ end
+
context 'when the project is public' do
context 'when the note author is not a project member' do
it 'can edit a note' do
@@ -24,14 +63,48 @@ describe NotePolicy, mdoels: true do
end
end
- context 'when the noteable is a snippet' do
+ context 'when the noteable is a project snippet' do
+ it 'can edit note' do
+ policies = policies(create(:project_snippet, :public, project: project))
+
+ expect(policies).to be_allowed(:admin_note)
+ expect(policies).to be_allowed(:resolve_note)
+ expect(policies).to be_allowed(:read_note)
+ end
+
+ context 'when it is private' do
+ it_behaves_like 'a discussion with a private noteable' do
+ let(:noteable) { create(:project_snippet, :private, project: project) }
+ end
+ end
+ end
+
+ context 'when the noteable is a personal snippet' do
it 'can edit note' do
- policies = policies(create(:project_snippet, project: project))
+ policies = policies(create(:personal_snippet, :public))
expect(policies).to be_allowed(:admin_note)
expect(policies).to be_allowed(:resolve_note)
expect(policies).to be_allowed(:read_note)
end
+
+ context 'when it is private' do
+ it 'can not edit nor read the note' do
+ policies = policies(create(:personal_snippet, :private))
+
+ expect(policies).to be_disallowed(:admin_note)
+ expect(policies).to be_disallowed(:resolve_note)
+ expect(policies).to be_disallowed(:read_note)
+ end
+ end
+ end
+
+ context 'when a discussion is confidential' do
+ before do
+ issue.update_attribute(:confidential, true)
+ end
+
+ it_behaves_like 'a discussion with a private noteable'
end
context 'when a discussion is locked' do
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index b7ec35d6ec5..69468f9ad85 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -163,7 +163,7 @@ describe ProjectPolicy do
:create_build, :read_build, :update_build, :admin_build, :destroy_build,
:create_pipeline_schedule, :read_pipeline_schedule, :update_pipeline_schedule, :admin_pipeline_schedule, :destroy_pipeline_schedule,
:create_environment, :read_environment, :update_environment, :admin_environment, :destroy_environment,
- :create_cluster, :read_cluster, :update_cluster, :admin_cluster, :destroy_cluster,
+ :create_cluster, :read_cluster, :update_cluster, :admin_cluster,
:create_deployment, :read_deployment, :update_deployment, :admin_deployment, :destroy_deployment
]
@@ -182,7 +182,7 @@ describe ProjectPolicy do
:create_build, :read_build, :update_build, :admin_build, :destroy_build,
:create_pipeline_schedule, :read_pipeline_schedule, :update_pipeline_schedule, :admin_pipeline_schedule, :destroy_pipeline_schedule,
:create_environment, :read_environment, :update_environment, :admin_environment, :destroy_environment,
- :create_cluster, :read_cluster, :update_cluster, :admin_cluster, :destroy_cluster,
+ :create_cluster, :read_cluster, :update_cluster, :admin_cluster,
:create_deployment, :read_deployment, :update_deployment, :admin_deployment, :destroy_deployment
]
@@ -223,7 +223,7 @@ describe ProjectPolicy do
expect_disallowed(*other_write_abilities)
end
- it 'does not disable other other abilities' do
+ it 'does not disable other abilities' do
expect_allowed(*(regular_abilities - feature_write_abilities - other_write_abilities))
end
end
diff --git a/spec/presenters/blob_presenter_spec.rb b/spec/presenters/blob_presenter_spec.rb
new file mode 100644
index 00000000000..e85e7a41017
--- /dev/null
+++ b/spec/presenters/blob_presenter_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe BlobPresenter, :seed_helper do
+ let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH, '') }
+
+ let(:git_blob) do
+ Gitlab::Git::Blob.find(
+ repository,
+ 'fa1b1e6c004a68b7d8763b86455da9e6b23e36d6',
+ 'files/ruby/regex.rb'
+ )
+ end
+ let(:blob) { Blob.new(git_blob) }
+
+ describe '#highlight' do
+ subject { described_class.new(blob) }
+
+ it 'returns highlighted content' do
+ expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', git_blob.data, plain: nil, language: nil)
+
+ subject.highlight
+ end
+
+ it 'returns plain content when :plain is true' do
+ expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', git_blob.data, plain: true, language: nil)
+
+ subject.highlight(plain: true)
+ end
+
+ context 'gitlab-language contains a match' do
+ before do
+ allow(blob).to receive(:language_from_gitattributes).and_return('ruby')
+ end
+
+ it 'passes language to inner call' do
+ expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', git_blob.data, plain: nil, language: 'ruby')
+
+ subject.highlight
+ end
+ end
+ end
+end
diff --git a/spec/presenters/ci/build_presenter_spec.rb b/spec/presenters/ci/build_presenter_spec.rb
index 547d95e0908..676835b3880 100644
--- a/spec/presenters/ci/build_presenter_spec.rb
+++ b/spec/presenters/ci/build_presenter_spec.rb
@@ -218,6 +218,42 @@ describe Ci::BuildPresenter do
end
end
+ describe '#execute_in' do
+ subject { presenter.execute_in }
+
+ context 'when build is scheduled' do
+ context 'when schedule is not expired' do
+ let(:build) { create(:ci_build, :scheduled) }
+
+ it 'returns execution time' do
+ Timecop.freeze do
+ is_expected.to be_like_time(60.0)
+ end
+ end
+ end
+
+ context 'when schedule is expired' do
+ let(:build) { create(:ci_build, :expired_scheduled) }
+
+ it 'returns execution time' do
+ Timecop.freeze do
+ is_expected.to eq(0)
+ end
+ end
+ end
+ end
+
+ context 'when build is not delayed' do
+ let(:build) { create(:ci_build) }
+
+ it 'does not return execution time' do
+ Timecop.freeze do
+ is_expected.to be_falsy
+ end
+ end
+ end
+ end
+
describe '#callout_failure_message' do
let(:build) { create(:ci_build, :failed, :api_failure) }
@@ -231,7 +267,7 @@ describe Ci::BuildPresenter do
let(:build) { create(:ci_build, :failed, :script_failure) }
context 'when is a script or missing dependency failure' do
- let(:failure_reasons) { %w(script_failure missing_dependency_failure) }
+ let(:failure_reasons) { %w(script_failure missing_dependency_failure archived_failure) }
it 'should return false' do
failure_reasons.each do |failure_reason|
diff --git a/spec/presenters/ci/build_runner_presenter_spec.rb b/spec/presenters/ci/build_runner_presenter_spec.rb
index e7019b990dd..170e0ac5717 100644
--- a/spec/presenters/ci/build_runner_presenter_spec.rb
+++ b/spec/presenters/ci/build_runner_presenter_spec.rb
@@ -3,7 +3,6 @@ require 'spec_helper'
describe Ci::BuildRunnerPresenter do
let(:presenter) { described_class.new(build) }
let(:archive) { { paths: ['sample.txt'] } }
- let(:junit) { { junit: ['junit.xml'] } }
let(:archive_expectation) do
{
@@ -14,16 +13,6 @@ describe Ci::BuildRunnerPresenter do
}
end
- let(:junit_expectation) do
- {
- name: 'junit.xml',
- artifact_type: :junit,
- artifact_format: :gzip,
- paths: ['junit.xml'],
- when: 'always'
- }
- end
-
describe '#artifacts' do
context "when option contains archive-type artifacts" do
let(:build) { create(:ci_build, options: { artifacts: archive } ) }
@@ -49,20 +38,46 @@ describe Ci::BuildRunnerPresenter do
end
end
- context "when option has 'junit' keyword" do
- let(:build) { create(:ci_build, options: { artifacts: { reports: junit } } ) }
-
- it 'presents correct hash' do
- expect(presenter.artifacts.first).to include(junit_expectation)
+ context "with reports" do
+ Ci::JobArtifact::DEFAULT_FILE_NAMES.each do |file_type, filename|
+ context file_type.to_s do
+ let(:report) { { "#{file_type}": [filename] } }
+ let(:build) { create(:ci_build, options: { artifacts: { reports: report } } ) }
+
+ let(:report_expectation) do
+ {
+ name: filename,
+ artifact_type: :"#{file_type}",
+ artifact_format: Ci::JobArtifact::TYPE_AND_FORMAT_PAIRS.fetch(file_type),
+ paths: [filename],
+ when: 'always'
+ }
+ end
+
+ it 'presents correct hash' do
+ expect(presenter.artifacts.first).to include(report_expectation)
+ end
+ end
end
end
context "when option has both archive and reports specification" do
- let(:build) { create(:ci_build, options: { script: 'echo', artifacts: { **archive, reports: junit } } ) }
+ let(:report) { { junit: ['junit.xml'] } }
+ let(:build) { create(:ci_build, options: { script: 'echo', artifacts: { **archive, reports: report } } ) }
+
+ let(:report_expectation) do
+ {
+ name: 'junit.xml',
+ artifact_type: :junit,
+ artifact_format: :gzip,
+ paths: ['junit.xml'],
+ when: 'always'
+ }
+ end
it 'presents correct hash' do
expect(presenter.artifacts.first).to include(archive_expectation)
- expect(presenter.artifacts.second).to include(junit_expectation)
+ expect(presenter.artifacts.second).to include(report_expectation)
end
context "when archive specifies 'expire_in' keyword" do
@@ -70,7 +85,7 @@ describe Ci::BuildRunnerPresenter do
it 'inherits expire_in from archive' do
expect(presenter.artifacts.first).to include({ **archive_expectation, expire_in: '3 mins 4 sec' })
- expect(presenter.artifacts.second).to include({ **junit_expectation, expire_in: '3 mins 4 sec' })
+ expect(presenter.artifacts.second).to include({ **report_expectation, expire_in: '3 mins 4 sec' })
end
end
end
diff --git a/spec/presenters/clusterable_presenter_spec.rb b/spec/presenters/clusterable_presenter_spec.rb
new file mode 100644
index 00000000000..4f4ae5e07c5
--- /dev/null
+++ b/spec/presenters/clusterable_presenter_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ClusterablePresenter do
+ include Gitlab::Routing.url_helpers
+
+ describe '.fabricate' do
+ let(:project) { create(:project) }
+
+ subject { described_class.fabricate(project) }
+
+ it 'creates an object from a descendant presenter' do
+ expect(subject).to be_kind_of(ProjectClusterablePresenter)
+ end
+ end
+end
diff --git a/spec/presenters/clusters/cluster_presenter_spec.rb b/spec/presenters/clusters/cluster_presenter_spec.rb
index e96dbfb73c0..72c5eac3ede 100644
--- a/spec/presenters/clusters/cluster_presenter_spec.rb
+++ b/spec/presenters/clusters/cluster_presenter_spec.rb
@@ -1,7 +1,9 @@
require 'spec_helper'
describe Clusters::ClusterPresenter do
- let(:cluster) { create(:cluster, :provided_by_gcp) }
+ include Gitlab::Routing.url_helpers
+
+ let(:cluster) { create(:cluster, :provided_by_gcp, :project) }
subject(:presenter) do
described_class.new(cluster)
@@ -71,4 +73,21 @@ describe Clusters::ClusterPresenter do
it { is_expected.to eq(false) }
end
end
+
+ describe '#show_path' do
+ subject { described_class.new(cluster).show_path }
+
+ context 'project_type cluster' do
+ let(:project) { cluster.project }
+
+ it { is_expected.to eq(project_cluster_path(project, cluster)) }
+ end
+
+ context 'group_type cluster' do
+ let(:group) { cluster.group }
+ let(:cluster) { create(:cluster, :provided_by_gcp, :group) }
+
+ it { is_expected.to eq(group_cluster_path(group, cluster)) }
+ end
+ end
end
diff --git a/spec/presenters/group_clusterable_presenter_spec.rb b/spec/presenters/group_clusterable_presenter_spec.rb
new file mode 100644
index 00000000000..205160742bf
--- /dev/null
+++ b/spec/presenters/group_clusterable_presenter_spec.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe GroupClusterablePresenter do
+ include Gitlab::Routing.url_helpers
+
+ let(:presenter) { described_class.new(group) }
+ let(:cluster) { create(:cluster, :provided_by_gcp, :group) }
+ let(:group) { cluster.group }
+
+ describe '#can_create_cluster?' do
+ let(:user) { create(:user) }
+
+ subject { presenter.can_create_cluster? }
+
+ before do
+ allow(presenter).to receive(:current_user).and_return(user)
+ end
+
+ context 'when user can create' do
+ before do
+ group.add_maintainer(user)
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when user cannot create' do
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ describe '#index_path' do
+ subject { presenter.index_path }
+
+ it { is_expected.to eq(group_clusters_path(group)) }
+ end
+
+ describe '#new_path' do
+ subject { presenter.new_path }
+
+ it { is_expected.to eq(new_group_cluster_path(group)) }
+ end
+
+ describe '#create_user_clusters_path' do
+ subject { presenter.create_user_clusters_path }
+
+ it { is_expected.to eq(create_user_group_clusters_path(group)) }
+ end
+
+ describe '#create_gcp_clusters_path' do
+ subject { presenter.create_gcp_clusters_path }
+
+ it { is_expected.to eq(create_gcp_group_clusters_path(group)) }
+ end
+
+ describe '#cluster_status_cluster_path' do
+ subject { presenter.cluster_status_cluster_path(cluster) }
+
+ it { is_expected.to eq(cluster_status_group_cluster_path(group, cluster)) }
+ end
+
+ describe '#install_applications_cluster_path' do
+ let(:application) { :helm }
+
+ subject { presenter.install_applications_cluster_path(cluster, application) }
+
+ it { is_expected.to eq(install_applications_group_cluster_path(group, cluster, application)) }
+ end
+
+ describe '#cluster_path' do
+ subject { presenter.cluster_path(cluster) }
+
+ it { is_expected.to eq(group_cluster_path(group, cluster)) }
+ end
+end
diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb
index a1b52d8692d..bafcddebbb7 100644
--- a/spec/presenters/merge_request_presenter_spec.rb
+++ b/spec/presenters/merge_request_presenter_spec.rb
@@ -403,6 +403,15 @@ describe MergeRequestPresenter do
is_expected
.to eq("<a href=\"/#{resource.source_project.full_path}/tree/#{resource.source_branch}\">#{resource.source_branch}</a>")
end
+
+ it 'escapes html, when source_branch does not exist' do
+ xss_attempt = "<img src='x' onerror=alert('bad stuff') />"
+
+ allow(resource).to receive(:source_branch) { xss_attempt }
+ allow(resource).to receive(:source_branch_exists?) { false }
+
+ is_expected.to eq(ERB::Util.html_escape(xss_attempt))
+ end
end
describe '#rebase_path' do
diff --git a/spec/presenters/project_clusterable_presenter_spec.rb b/spec/presenters/project_clusterable_presenter_spec.rb
new file mode 100644
index 00000000000..c50d90ae1e8
--- /dev/null
+++ b/spec/presenters/project_clusterable_presenter_spec.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ProjectClusterablePresenter do
+ include Gitlab::Routing.url_helpers
+
+ let(:presenter) { described_class.new(project) }
+ let(:project) { create(:project) }
+ let(:cluster) { create(:cluster, :provided_by_gcp, projects: [project]) }
+
+ describe '#can_create_cluster?' do
+ let(:user) { create(:user) }
+
+ subject { presenter.can_create_cluster? }
+
+ before do
+ allow(presenter).to receive(:current_user).and_return(user)
+ end
+
+ context 'when user can create' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when user cannot create' do
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ describe '#index_path' do
+ subject { presenter.index_path }
+
+ it { is_expected.to eq(project_clusters_path(project)) }
+ end
+
+ describe '#new_path' do
+ subject { presenter.new_path }
+
+ it { is_expected.to eq(new_project_cluster_path(project)) }
+ end
+
+ describe '#create_user_clusters_path' do
+ subject { presenter.create_user_clusters_path }
+
+ it { is_expected.to eq(create_user_project_clusters_path(project)) }
+ end
+
+ describe '#create_gcp_clusters_path' do
+ subject { presenter.create_gcp_clusters_path }
+
+ it { is_expected.to eq(create_gcp_project_clusters_path(project)) }
+ end
+
+ describe '#cluster_status_cluster_path' do
+ subject { presenter.cluster_status_cluster_path(cluster) }
+
+ it { is_expected.to eq(cluster_status_project_cluster_path(project, cluster)) }
+ end
+
+ describe '#install_applications_cluster_path' do
+ let(:application) { :helm }
+
+ subject { presenter.install_applications_cluster_path(cluster, application) }
+
+ it { is_expected.to eq(install_applications_project_cluster_path(project, cluster, application)) }
+ end
+
+ describe '#cluster_path' do
+ subject { presenter.cluster_path(cluster) }
+
+ it { is_expected.to eq(project_cluster_path(project, cluster)) }
+ end
+end
diff --git a/spec/presenters/project_presenter_spec.rb b/spec/presenters/project_presenter_spec.rb
index 96193784072..7b0192fa9c8 100644
--- a/spec/presenters/project_presenter_spec.rb
+++ b/spec/presenters/project_presenter_spec.rb
@@ -239,7 +239,7 @@ describe ProjectPresenter do
expect(presenter.new_file_anchor_data).to have_attributes(enabled: false,
label: "New file",
link: presenter.project_new_blob_path(project, 'master'),
- class_modifier: 'new')
+ class_modifier: 'success')
end
it 'returns nil if user cannot push' do
@@ -410,36 +410,5 @@ describe ProjectPresenter do
end
end
end
-
- describe '#koding_anchor_data' do
- it 'returns link to set up Koding if user can push and no koding YML exists' do
- project.add_developer(user)
- allow(project.repository).to receive(:koding_yml).and_return(nil)
- allow(Gitlab::CurrentSettings).to receive(:koding_enabled?).and_return(true)
-
- expect(presenter.koding_anchor_data).to have_attributes(enabled: false,
- label: 'Set up Koding',
- link: presenter.add_koding_stack_path)
- end
-
- it 'returns nil if user cannot push' do
- expect(presenter.koding_anchor_data).to be_nil
- end
-
- it 'returns nil if koding is not enabled' do
- project.add_developer(user)
- allow(Gitlab::CurrentSettings).to receive(:koding_enabled?).and_return(false)
-
- expect(presenter.koding_anchor_data).to be_nil
- end
-
- it 'returns nil if koding YML already exists' do
- project.add_developer(user)
- allow(project.repository).to receive(:koding_yml).and_return(double)
- allow(Gitlab::CurrentSettings).to receive(:koding_enabled?).and_return(true)
-
- expect(presenter.koding_anchor_data).to be_nil
- end
- end
end
end
diff --git a/spec/rack_servers/configs/config.ru b/spec/rack_servers/configs/config.ru
new file mode 100644
index 00000000000..63daeb9eec5
--- /dev/null
+++ b/spec/rack_servers/configs/config.ru
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+app = proc do |env|
+ if env['REQUEST_METHOD'] == 'GET'
+ [200, {}, ["#{Process.pid}"]]
+ else
+ Process.kill(env['QUERY_STRING'], Process.pid)
+ [200, {}, ['Bye!']]
+ end
+end
+
+run app
diff --git a/spec/rack_servers/configs/puma.rb b/spec/rack_servers/configs/puma.rb
new file mode 100644
index 00000000000..d6b6d83d648
--- /dev/null
+++ b/spec/rack_servers/configs/puma.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+# Note: this file is used for testing puma in `spec/rack_servers/puma_spec.rb` only
+# Note: as per the convention in `config/puma.example.development.rb`,
+# this file will replace `/home/git` with the actual working directory
+
+directory '/home/git'
+threads 1, 10
+queue_requests false
+pidfile '/home/git/gitlab/tmp/pids/puma.pid'
+bind 'unix:///home/git/gitlab/tmp/tests/puma.socket'
+workers 1
+preload_app!
+worker_timeout 60
+
+require_relative "/home/git/gitlab/lib/gitlab/cluster/lifecycle_events"
+require_relative "/home/git/gitlab/lib/gitlab/cluster/puma_worker_killer_initializer"
+
+before_fork do
+ Gitlab::Cluster::PumaWorkerKillerInitializer.start @config.options
+ Gitlab::Cluster::LifecycleEvents.do_before_fork
+end
+
+Gitlab::Cluster::LifecycleEvents.set_puma_options @config.options
+on_worker_boot do
+ Gitlab::Cluster::LifecycleEvents.do_worker_start
+ File.write('/home/git/gitlab/tmp/tests/puma-worker-ready', Process.pid)
+end
+
+on_restart do
+ Gitlab::Cluster::LifecycleEvents.do_master_restart
+end
diff --git a/spec/rack_servers/puma_spec.rb b/spec/rack_servers/puma_spec.rb
new file mode 100644
index 00000000000..431fab87857
--- /dev/null
+++ b/spec/rack_servers/puma_spec.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+require 'fileutils'
+
+require 'excon'
+
+require 'spec_helper'
+
+describe 'Puma' do
+ before(:all) do
+ project_root = File.expand_path('../..', __dir__)
+
+ config_lines = File.read('spec/rack_servers/configs/puma.rb')
+ .gsub('/home/git/gitlab', project_root)
+ .gsub('/home/git', project_root)
+
+ config_path = File.join(project_root, "tmp/tests/puma.rb")
+ @socket_path = File.join(project_root, 'tmp/tests/puma.socket')
+
+ File.write(config_path, config_lines)
+
+ cmd = %W[puma -e test -C #{config_path} #{File.join(__dir__, 'configs/config.ru')}]
+ @puma_master_pid = spawn(*cmd)
+ wait_puma_boot!(@puma_master_pid, File.join(project_root, 'tmp/tests/puma-worker-ready'))
+ WebMock.allow_net_connect!
+ end
+
+ %w[SIGQUIT SIGTERM SIGKILL].each do |signal|
+ it "has a worker that self-terminates on signal #{signal}" do
+ response = Excon.get('unix://', socket: @socket_path)
+ expect(response.status).to eq(200)
+
+ worker_pid = response.body.to_i
+ expect(worker_pid).to be > 0
+
+ begin
+ Excon.post("unix://?#{signal}", socket: @socket_path)
+ rescue Excon::Error::Socket
+ # The connection may be closed abruptly
+ end
+
+ expect(pid_gone?(worker_pid)).to eq(true)
+ end
+ end
+
+ after(:all) do
+ begin
+ WebMock.disable_net_connect!(allow_localhost: true)
+ Process.kill('TERM', @puma_master_pid)
+ rescue Errno::ESRCH
+ end
+ end
+
+ def wait_puma_boot!(master_pid, ready_file)
+ # We have seen the boot timeout after 2 minutes in CI so let's set it to 5 minutes.
+ timeout = 5 * 60
+ timeout.times do
+ return if File.exist?(ready_file)
+
+ pid = Process.waitpid(master_pid, Process::WNOHANG)
+ raise "puma failed to boot: #{$?}" unless pid.nil?
+
+ sleep 1
+ end
+
+ raise "puma boot timed out after #{timeout} seconds"
+ end
+
+ def pid_gone?(pid)
+ # Worker termination should take less than a second. That makes 10
+ # seconds a generous timeout.
+ 10.times do
+ begin
+ Process.kill(0, pid)
+ rescue Errno::ESRCH
+ return true
+ end
+
+ sleep 1
+ end
+
+ false
+ end
+end
diff --git a/spec/rack_servers/unicorn_spec.rb b/spec/rack_servers/unicorn_spec.rb
new file mode 100644
index 00000000000..6a02ebcd048
--- /dev/null
+++ b/spec/rack_servers/unicorn_spec.rb
@@ -0,0 +1,105 @@
+# frozen_string_literal: true
+
+require 'fileutils'
+
+require 'excon'
+
+require 'spec_helper'
+
+describe 'Unicorn' do
+ before(:all) do
+ project_root = File.expand_path('../..', __dir__)
+
+ config_lines = File.read('config/unicorn.rb.example')
+ .gsub('/home/git/gitlab', project_root)
+ .gsub('/home/git', project_root)
+ .split("\n")
+
+ # Remove these because they make setup harder.
+ config_lines = config_lines.reject do |line|
+ %w[
+ worker_processes
+ listen
+ pid
+ stderr_path
+ stdout_path
+ ].any? { |prefix| line.start_with?(prefix) }
+ end
+
+ config_lines << "working_directory '#{Rails.root}'"
+
+ # We want to have exactly 1 worker process because that makes it
+ # predictable which process will handle our requests.
+ config_lines << 'worker_processes 1'
+
+ @socket_path = File.join(project_root, 'tmp/tests/unicorn.socket')
+ config_lines << "listen '#{@socket_path}'"
+
+ ready_file = File.join(project_root, 'tmp/tests/unicorn-worker-ready')
+ FileUtils.rm_f(ready_file)
+ after_fork_index = config_lines.index { |l| l.start_with?('after_fork') }
+ config_lines.insert(after_fork_index + 1, "File.write('#{ready_file}', Process.pid)")
+
+ config_path = File.join(project_root, 'tmp/tests/unicorn.rb')
+ File.write(config_path, config_lines.join("\n") + "\n")
+
+ cmd = %W[unicorn -E test -c #{config_path} spec/rack_servers/configs/config.ru]
+ @unicorn_master_pid = spawn(*cmd)
+ wait_unicorn_boot!(@unicorn_master_pid, ready_file)
+ WebMock.allow_net_connect!
+ end
+
+ %w[SIGQUIT SIGTERM SIGKILL].each do |signal|
+ it "has a worker that self-terminates on signal #{signal}" do
+ response = Excon.get('unix://', socket: @socket_path)
+ expect(response.status).to eq(200)
+
+ worker_pid = response.body.to_i
+ expect(worker_pid).to be > 0
+
+ begin
+ Excon.post("unix://?#{signal}", socket: @socket_path)
+ rescue Excon::Error::Socket
+ # The connection may be closed abruptly
+ end
+
+ expect(pid_gone?(worker_pid)).to eq(true)
+ end
+ end
+
+ after(:all) do
+ WebMock.disable_net_connect!(allow_localhost: true)
+ Process.kill('TERM', @unicorn_master_pid)
+ end
+
+ def wait_unicorn_boot!(master_pid, ready_file)
+ # We have seen the boot timeout after 2 minutes in CI so let's set it to 5 minutes.
+ timeout = 5 * 60
+ timeout.times do
+ return if File.exist?(ready_file)
+
+ pid = Process.waitpid(master_pid, Process::WNOHANG)
+ raise "unicorn failed to boot: #{$?}" unless pid.nil?
+
+ sleep 1
+ end
+
+ raise "unicorn boot timed out after #{timeout} seconds"
+ end
+
+ def pid_gone?(pid)
+ # Worker termination should take less than a second. That makes 10
+ # seconds a generous timeout.
+ 10.times do
+ begin
+ Process.kill(0, pid)
+ rescue Errno::ESRCH
+ return true
+ end
+
+ sleep 1
+ end
+
+ false
+ end
+end
diff --git a/spec/requests/api/applications_spec.rb b/spec/requests/api/applications_spec.rb
index f56bc932f40..6154be5c425 100644
--- a/spec/requests/api/applications_spec.rb
+++ b/spec/requests/api/applications_spec.rb
@@ -5,6 +5,7 @@ describe API::Applications, :api do
let(:admin_user) { create(:user, admin: true) }
let(:user) { create(:user, admin: false) }
+ let!(:application) { create(:application, name: 'another_application', redirect_uri: 'http://other_application.url', scopes: '') }
describe 'POST /applications' do
context 'authenticated and authorized user' do
@@ -15,7 +16,7 @@ describe API::Applications, :api do
application = Doorkeeper::Application.find_by(name: 'application_name', redirect_uri: 'http://application.url')
- expect(response).to have_http_status 201
+ expect(response).to have_gitlab_http_status(201)
expect(json_response).to be_a Hash
expect(json_response['application_id']).to eq application.uid
expect(json_response['secret']).to eq application.secret
@@ -24,20 +25,30 @@ describe API::Applications, :api do
it 'does not allow creating an application with the wrong redirect_uri format' do
expect do
- post api('/applications', admin_user), name: 'application_name', redirect_uri: 'wrong_url_format', scopes: ''
+ post api('/applications', admin_user), name: 'application_name', redirect_uri: 'http://', scopes: ''
end.not_to change { Doorkeeper::Application.count }
- expect(response).to have_http_status 400
+ expect(response).to have_gitlab_http_status(400)
expect(json_response).to be_a Hash
expect(json_response['message']['redirect_uri'][0]).to eq('must be an absolute URI.')
end
+ it 'does not allow creating an application with a forbidden URI format' do
+ expect do
+ post api('/applications', admin_user), name: 'application_name', redirect_uri: 'javascript://alert()', scopes: ''
+ end.not_to change { Doorkeeper::Application.count }
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response).to be_a Hash
+ expect(json_response['message']['redirect_uri'][0]).to eq('is forbidden by the server.')
+ end
+
it 'does not allow creating an application without a name' do
expect do
post api('/applications', admin_user), redirect_uri: 'http://application.url', scopes: ''
end.not_to change { Doorkeeper::Application.count }
- expect(response).to have_http_status 400
+ expect(response).to have_gitlab_http_status(400)
expect(json_response).to be_a Hash
expect(json_response['error']).to eq('name is missing')
end
@@ -47,7 +58,7 @@ describe API::Applications, :api do
post api('/applications', admin_user), name: 'application_name', scopes: ''
end.not_to change { Doorkeeper::Application.count }
- expect(response).to have_http_status 400
+ expect(response).to have_gitlab_http_status(400)
expect(json_response).to be_a Hash
expect(json_response['error']).to eq('redirect_uri is missing')
end
@@ -57,7 +68,7 @@ describe API::Applications, :api do
post api('/applications', admin_user), name: 'application_name', redirect_uri: 'http://application.url'
end.not_to change { Doorkeeper::Application.count }
- expect(response).to have_http_status 400
+ expect(response).to have_gitlab_http_status(400)
expect(json_response).to be_a Hash
expect(json_response['error']).to eq('scopes is missing')
end
@@ -69,7 +80,7 @@ describe API::Applications, :api do
post api('/applications', user), name: 'application_name', redirect_uri: 'http://application.url', scopes: ''
end.not_to change { Doorkeeper::Application.count }
- expect(response).to have_http_status 403
+ expect(response).to have_gitlab_http_status(403)
end
end
@@ -79,7 +90,62 @@ describe API::Applications, :api do
post api('/applications'), name: 'application_name', redirect_uri: 'http://application.url'
end.not_to change { Doorkeeper::Application.count }
- expect(response).to have_http_status 401
+ expect(response).to have_gitlab_http_status(401)
+ end
+ end
+ end
+
+ describe 'GET /applications' do
+ context 'authenticated and authorized user' do
+ it 'can list application' do
+ get api('/applications', admin_user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to be_a(Array)
+ end
+ end
+
+ context 'authorized user without authorization' do
+ it 'cannot list application' do
+ get api('/applications', user)
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+
+ context 'non-authenticated user' do
+ it 'cannot list application' do
+ get api('/applications')
+
+ expect(response).to have_gitlab_http_status(401)
+ end
+ end
+ end
+
+ describe 'DELETE /applications/:id' do
+ context 'authenticated and authorized user' do
+ it 'can delete an application' do
+ expect do
+ delete api("/applications/#{application.id}", admin_user)
+ end.to change { Doorkeeper::Application.count }.by(-1)
+
+ expect(response).to have_gitlab_http_status(204)
+ end
+ end
+
+ context 'authorized user without authorization' do
+ it 'cannot delete an application' do
+ delete api("/applications/#{application.id}", user)
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+
+ context 'non-authenticated user' do
+ it 'cannot delete an application' do
+ delete api("/applications/#{application.id}")
+
+ expect(response).to have_gitlab_http_status(401)
end
end
end
diff --git a/spec/requests/api/circuit_breakers_spec.rb b/spec/requests/api/circuit_breakers_spec.rb
index fe76f057115..6c7cb151c74 100644
--- a/spec/requests/api/circuit_breakers_spec.rb
+++ b/spec/requests/api/circuit_breakers_spec.rb
@@ -1,8 +1,8 @@
require 'spec_helper'
describe API::CircuitBreakers do
- let(:user) { create(:user) }
- let(:admin) { create(:admin) }
+ set(:user) { create(:user) }
+ set(:admin) { create(:admin) }
describe 'GET circuit_breakers/repository_storage' do
it 'returns a 401 for anonymous users' do
@@ -18,37 +18,26 @@ describe API::CircuitBreakers do
end
it 'returns an Array of storages' do
- expect(Gitlab::Git::Storage::Health).to receive(:for_all_storages) do
- [Gitlab::Git::Storage::Health.new('broken', [{ name: 'prefix:broken:web01', failure_count: 4 }])]
- end
-
get api('/circuit_breakers/repository_storage', admin)
expect(response).to have_gitlab_http_status(200)
expect(json_response).to be_kind_of(Array)
- expect(json_response.first['storage_name']).to eq('broken')
- expect(json_response.first['failing_on_hosts']).to eq(['web01'])
- expect(json_response.first['total_failures']).to eq(4)
+ expect(json_response).to be_empty
end
describe 'GET circuit_breakers/repository_storage/failing' do
it 'returns an array of failing storages' do
- expect(Gitlab::Git::Storage::Health).to receive(:for_failing_storages) do
- [Gitlab::Git::Storage::Health.new('broken', [{ name: 'prefix:broken:web01', failure_count: 4 }])]
- end
-
get api('/circuit_breakers/repository_storage/failing', admin)
expect(response).to have_gitlab_http_status(200)
expect(json_response).to be_kind_of(Array)
+ expect(json_response).to be_empty
end
end
end
describe 'DELETE circuit_breakers/repository_storage' do
it 'clears all circuit_breakers' do
- expect(Gitlab::Git::Storage::FailureInfo).to receive(:reset_all!)
-
delete api('/circuit_breakers/repository_storage', admin)
expect(response).to have_gitlab_http_status(204)
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index d5b31610dad..329d069ef3d 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -238,7 +238,7 @@ describe API::Commits do
describe 'create' do
let(:message) { 'Created file' }
- let!(:invalid_c_params) do
+ let(:invalid_c_params) do
{
branch: 'master',
commit_message: message,
@@ -251,7 +251,7 @@ describe API::Commits do
]
}
end
- let!(:valid_c_params) do
+ let(:valid_c_params) do
{
branch: 'master',
commit_message: message,
@@ -264,7 +264,7 @@ describe API::Commits do
]
}
end
- let!(:valid_utf8_c_params) do
+ let(:valid_utf8_c_params) do
{
branch: 'master',
commit_message: message,
@@ -278,6 +278,12 @@ describe API::Commits do
}
end
+ it 'does not increment the usage counters using access token authentication' do
+ expect(::Gitlab::WebIdeCommitsCounter).not_to receive(:increment)
+
+ post api(url, user), valid_c_params
+ end
+
it 'a new file in project repo' do
post api(url, user), valid_c_params
@@ -315,7 +321,7 @@ describe API::Commits do
describe 'delete' do
let(:message) { 'Deleted file' }
- let!(:invalid_d_params) do
+ let(:invalid_d_params) do
{
branch: 'markdown',
commit_message: message,
@@ -327,7 +333,7 @@ describe API::Commits do
]
}
end
- let!(:valid_d_params) do
+ let(:valid_d_params) do
{
branch: 'markdown',
commit_message: message,
@@ -356,7 +362,7 @@ describe API::Commits do
describe 'move' do
let(:message) { 'Moved file' }
- let!(:invalid_m_params) do
+ let(:invalid_m_params) do
{
branch: 'feature',
commit_message: message,
@@ -370,7 +376,7 @@ describe API::Commits do
]
}
end
- let!(:valid_m_params) do
+ let(:valid_m_params) do
{
branch: 'feature',
commit_message: message,
@@ -401,7 +407,7 @@ describe API::Commits do
describe 'update' do
let(:message) { 'Updated file' }
- let!(:invalid_u_params) do
+ let(:invalid_u_params) do
{
branch: 'master',
commit_message: message,
@@ -414,7 +420,7 @@ describe API::Commits do
]
}
end
- let!(:valid_u_params) do
+ let(:valid_u_params) do
{
branch: 'master',
commit_message: message,
@@ -442,9 +448,57 @@ describe API::Commits do
end
end
+ describe 'chmod' do
+ let(:message) { 'Chmod +x file' }
+ let(:file_path) { 'files/ruby/popen.rb' }
+ let(:execute_filemode) { true }
+ let(:params) do
+ {
+ branch: 'master',
+ commit_message: message,
+ actions: [
+ {
+ action: 'chmod',
+ file_path: file_path,
+ execute_filemode: execute_filemode
+ }
+ ]
+ }
+ end
+
+ it 'responds with success' do
+ post api(url, user), params
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['title']).to eq(message)
+ end
+
+ context 'when execute_filemode is false' do
+ let(:execute_filemode) { false }
+
+ it 'responds with success' do
+ post api(url, user), params
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response['title']).to eq(message)
+ end
+ end
+
+ context "when the file doesn't exists" do
+ let(:file_path) { 'foo/bar.baz' }
+
+ it "responds with 400" do
+ post api(url, user), params
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response['message']).to eq("A file with this name doesn't exist")
+ end
+ end
+ end
+
describe 'multiple operations' do
let(:message) { 'Multiple actions' }
- let!(:invalid_mo_params) do
+ let(:invalid_mo_params) do
{
branch: 'master',
commit_message: message,
@@ -468,11 +522,16 @@ describe API::Commits do
action: 'update',
file_path: 'foo/bar.baz',
content: 'puts 8'
+ },
+ {
+ action: 'chmod',
+ file_path: 'files/ruby/popen.rb',
+ execute_filemode: true
}
]
}
end
- let!(:valid_mo_params) do
+ let(:valid_mo_params) do
{
branch: 'master',
commit_message: message,
@@ -496,18 +555,37 @@ describe API::Commits do
action: 'update',
file_path: 'files/ruby/popen.rb',
content: 'puts 8'
+ },
+ {
+ action: 'chmod',
+ file_path: 'files/ruby/popen.rb',
+ execute_filemode: true
}
]
}
end
- it 'are commited as one in project repo' do
+ it 'are committed as one in project repo' do
post api(url, user), valid_mo_params
expect(response).to have_gitlab_http_status(201)
expect(json_response['title']).to eq(message)
end
+ it 'includes the commit stats' do
+ post api(url, user), valid_mo_params
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response).to include 'stats'
+ end
+
+ it "doesn't include the commit stats when stats is false" do
+ post api(url, user), valid_mo_params.merge(stats: false)
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(json_response).not_to include 'stats'
+ end
+
it 'return a 400 bad request if there are any issues' do
post api(url, user), invalid_mo_params
@@ -1130,6 +1208,118 @@ describe API::Commits do
end
end
+ describe 'POST :id/repository/commits/:sha/revert' do
+ let(:commit_id) { 'b83d6e391c22777fca1ed3012fce84f633d7fed0' }
+ let(:commit) { project.commit(commit_id) }
+ let(:branch) { 'master' }
+ let(:route) { "/projects/#{project_id}/repository/commits/#{commit_id}/revert" }
+
+ shared_examples_for 'ref revert' do
+ context 'when ref exists' do
+ it 'reverts the ref commit' do
+ post api(route, current_user), branch: branch
+
+ expect(response).to have_gitlab_http_status(201)
+ expect(response).to match_response_schema('public_api/v4/commit/basic')
+
+ expect(json_response['message']).to eq(commit.revert_message(user))
+ expect(json_response['author_name']).to eq(user.name)
+ expect(json_response['committer_name']).to eq(user.name)
+ expect(json_response['parent_ids']).to contain_exactly(commit_id)
+ end
+ end
+
+ context 'when repository is disabled' do
+ include_context 'disabled repository'
+
+ it_behaves_like '403 response' do
+ let(:request) { post api(route, current_user), branch: branch }
+ end
+ end
+ end
+
+ context 'when unauthenticated', 'and project is public' do
+ let(:project) { create(:project, :public, :repository) }
+
+ it_behaves_like '403 response' do
+ let(:request) { post api(route), branch: branch }
+ end
+ end
+
+ context 'when unauthenticated', 'and project is private' do
+ it_behaves_like '404 response' do
+ let(:request) { post api(route), branch: branch }
+ let(:message) { '404 Project Not Found' }
+ end
+ end
+
+ context 'when authenticated', 'as an owner' do
+ let(:current_user) { user }
+
+ it_behaves_like 'ref revert'
+
+ context 'when ref does not exist' do
+ let(:commit_id) { 'unknown' }
+
+ it_behaves_like '404 response' do
+ let(:request) { post api(route, current_user), branch: branch }
+ let(:message) { '404 Commit Not Found' }
+ end
+ end
+
+ context 'when branch is missing' do
+ it_behaves_like '400 response' do
+ let(:request) { post api(route, current_user) }
+ end
+ end
+
+ context 'when branch is empty' do
+ ['', ' '].each do |branch|
+ it_behaves_like '400 response' do
+ let(:request) { post api(route, current_user), branch: branch }
+ end
+ end
+ end
+
+ context 'when branch does not exist' do
+ it_behaves_like '404 response' do
+ let(:request) { post api(route, current_user), branch: 'foo' }
+ let(:message) { '404 Branch Not Found' }
+ end
+ end
+
+ context 'when ref contains a dot' do
+ let(:commit_id) { branch_with_dot.name }
+ let(:commit) { project.repository.commit(commit_id) }
+
+ it_behaves_like '400 response' do
+ let(:request) { post api(route, current_user) }
+ end
+ end
+ end
+
+ context 'when authenticated', 'as a developer' do
+ let(:current_user) { user }
+
+ before do
+ project.add_developer(user)
+ end
+
+ context 'when branch is protected' do
+ before do
+ create(:protected_branch, project: project, name: 'feature')
+ end
+
+ it 'returns 400 if you are not allowed to push to the target branch' do
+ post api(route, current_user), branch: 'feature'
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ expect(json_response['message']).to match(/You are not allowed to push into this branch/)
+ end
+ end
+ end
+ end
+
describe 'POST /projects/:id/repository/commits/:sha/comments' do
let(:commit) { project.repository.commit }
let(:commit_id) { commit.id }
diff --git a/spec/requests/api/deployments_spec.rb b/spec/requests/api/deployments_spec.rb
index 61ae053cea7..3dac7225b7a 100644
--- a/spec/requests/api/deployments_spec.rb
+++ b/spec/requests/api/deployments_spec.rb
@@ -10,9 +10,9 @@ describe API::Deployments do
describe 'GET /projects/:id/deployments' do
let(:project) { create(:project) }
- let!(:deployment_1) { create(:deployment, project: project, iid: 11, ref: 'master', created_at: Time.now) }
- let!(:deployment_2) { create(:deployment, project: project, iid: 12, ref: 'feature', created_at: 1.day.ago) }
- let!(:deployment_3) { create(:deployment, project: project, iid: 8, ref: 'feature', created_at: 2.days.ago) }
+ let!(:deployment_1) { create(:deployment, :success, project: project, iid: 11, ref: 'master', created_at: Time.now) }
+ let!(:deployment_2) { create(:deployment, :success, project: project, iid: 12, ref: 'feature', created_at: 1.day.ago) }
+ let!(:deployment_3) { create(:deployment, :success, project: project, iid: 8, ref: 'patch', created_at: 2.days.ago) }
context 'as member of the project' do
it 'returns projects deployments sorted by id asc' do
@@ -53,8 +53,8 @@ describe API::Deployments do
'id' | 'desc' | [:deployment_3, :deployment_2, :deployment_1]
'iid' | 'asc' | [:deployment_3, :deployment_1, :deployment_2]
'iid' | 'desc' | [:deployment_2, :deployment_1, :deployment_3]
- 'ref' | 'asc' | [:deployment_2, :deployment_3, :deployment_1]
- 'ref' | 'desc' | [:deployment_1, :deployment_2, :deployment_3]
+ 'ref' | 'asc' | [:deployment_2, :deployment_1, :deployment_3]
+ 'ref' | 'desc' | [:deployment_3, :deployment_1, :deployment_2]
end
with_them do
@@ -76,7 +76,7 @@ describe API::Deployments do
describe 'GET /projects/:id/deployments/:deployment_id' do
let(:project) { deployment.environment.project }
- let!(:deployment) { create(:deployment) }
+ let!(:deployment) { create(:deployment, :success) }
context 'as a member of the project' do
it 'returns the projects deployment' do
diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb
index a2b41d56b8b..334dbb1c34c 100644
--- a/spec/requests/api/files_spec.rb
+++ b/spec/requests/api/files_spec.rb
@@ -178,6 +178,14 @@ describe API::Files do
expect(response).to have_gitlab_http_status(200)
end
+ it 'forces attachment content disposition' do
+ url = route(file_path) + "/raw"
+
+ get api(url, current_user), params
+
+ expect(headers['Content-Disposition']).to match(/^attachment/)
+ end
+
context 'when mandatory params are not given' do
it_behaves_like '400 response' do
let(:request) { get api(route("any%2Ffile"), current_user) }
diff --git a/spec/requests/api/graphql/project/issues_spec.rb b/spec/requests/api/graphql/project/issues_spec.rb
new file mode 100644
index 00000000000..355336ad7e2
--- /dev/null
+++ b/spec/requests/api/graphql/project/issues_spec.rb
@@ -0,0 +1,59 @@
+require 'spec_helper'
+
+describe 'getting an issue list for a project' do
+ include GraphqlHelpers
+
+ let(:project) { create(:project, :repository, :public) }
+ let(:current_user) { create(:user) }
+ let(:issues_data) { graphql_data['project']['issues']['edges'] }
+ let!(:issues) do
+ create(:issue, project: project, discussion_locked: true)
+ create(:issue, project: project)
+ end
+ let(:fields) do
+ <<~QUERY
+ edges {
+ node {
+ #{all_graphql_fields_for('issues'.classify)}
+ }
+ }
+ QUERY
+ end
+
+ let(:query) do
+ graphql_query_for(
+ 'project',
+ { 'fullPath' => project.full_path },
+ query_graphql_field('issues', {}, fields)
+ )
+ end
+
+ it_behaves_like 'a working graphql query' do
+ before do
+ post_graphql(query, current_user: current_user)
+ end
+ end
+
+ it 'includes a web_url' do
+ post_graphql(query, current_user: current_user)
+
+ expect(issues_data[0]['node']['webUrl']).to be_present
+ end
+
+ it 'includes discussion locked' do
+ post_graphql(query, current_user: current_user)
+
+ expect(issues_data[0]['node']['discussionLocked']).to eq false
+ expect(issues_data[1]['node']['discussionLocked']).to eq true
+ end
+
+ context 'when the user does not have access to the issue' do
+ it 'returns nil' do
+ project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
+
+ post_graphql(query)
+
+ expect(issues_data).to eq []
+ end
+ end
+end
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 3a8948f8477..688d91113ad 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -155,7 +155,7 @@ describe API::Groups do
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(response_groups).to eq(Group.visible_to_user(user1).order(:name).pluck(:name))
+ expect(response_groups).to eq(groups_visible_to_user(user1).order(:name).pluck(:name))
end
it "sorts in descending order when passed" do
@@ -164,7 +164,7 @@ describe API::Groups do
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(response_groups).to eq(Group.visible_to_user(user1).order(name: :desc).pluck(:name))
+ expect(response_groups).to eq(groups_visible_to_user(user1).order(name: :desc).pluck(:name))
end
it "sorts by path in order_by param" do
@@ -173,7 +173,7 @@ describe API::Groups do
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(response_groups).to eq(Group.visible_to_user(user1).order(:path).pluck(:name))
+ expect(response_groups).to eq(groups_visible_to_user(user1).order(:path).pluck(:name))
end
it "sorts by id in the order_by param" do
@@ -182,7 +182,7 @@ describe API::Groups do
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(response_groups).to eq(Group.visible_to_user(user1).order(:id).pluck(:name))
+ expect(response_groups).to eq(groups_visible_to_user(user1).order(:id).pluck(:name))
end
it "sorts also by descending id with pagination fix" do
@@ -191,7 +191,7 @@ describe API::Groups do
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(response_groups).to eq(Group.visible_to_user(user1).order(id: :desc).pluck(:name))
+ expect(response_groups).to eq(groups_visible_to_user(user1).order(id: :desc).pluck(:name))
end
it "sorts identical keys by id for good pagination" do
@@ -211,6 +211,10 @@ describe API::Groups do
expect(json_response).to be_an Array
expect(response_groups_ids).to eq(Group.select { |group| group['name'] == 'same-name' }.map { |group| group['id'] }.sort)
end
+
+ def groups_visible_to_user(user)
+ Group.where(id: user.authorized_groups.select(:id).reorder(nil))
+ end
end
context 'when using owned in the request' do
@@ -486,7 +490,7 @@ describe API::Groups do
expect(json_response.first['visibility']).not_to be_present
end
- it 'filters the groups projects' do
+ it "filters the groups projects" do
public_project = create(:project, :public, path: 'test1', group: group1)
get api("/groups/#{group1.id}/projects", user1), visibility: 'public'
@@ -498,6 +502,32 @@ describe API::Groups do
expect(json_response.first['name']).to eq(public_project.name)
end
+ it "returns projects excluding shared" do
+ create(:project_group_link, project: create(:project), group: group1)
+ create(:project_group_link, project: create(:project), group: group1)
+ create(:project_group_link, project: create(:project), group: group1)
+
+ get api("/groups/#{group1.id}/projects", user1), with_shared: false
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an(Array)
+ expect(json_response.length).to eq(2)
+ end
+
+ it "returns projects including those in subgroups", :nested_groups do
+ subgroup = create(:group, parent: group1)
+ create(:project, group: subgroup)
+ create(:project, group: subgroup)
+
+ get api("/groups/#{group1.id}/projects", user1), include_subgroups: true
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an(Array)
+ expect(json_response.length).to eq(4)
+ end
+
it "does not return a non existing group" do
get api("/groups/1328/projects", user1)
diff --git a/spec/requests/api/helpers_spec.rb b/spec/requests/api/helpers_spec.rb
index 0a789d58fd8..2c40e266f5f 100644
--- a/spec/requests/api/helpers_spec.rb
+++ b/spec/requests/api/helpers_spec.rb
@@ -206,6 +206,19 @@ describe API::Helpers do
expect { current_user }.to raise_error Gitlab::Auth::ExpiredError
end
+
+ context 'when impersonation is disabled' do
+ let(:personal_access_token) { create(:personal_access_token, :impersonation, user: user) }
+
+ before do
+ stub_config_setting(impersonation_enabled: false)
+ env[Gitlab::Auth::UserAuthFinders::PRIVATE_TOKEN_HEADER] = personal_access_token.token
+ end
+
+ it 'does not allow impersonation tokens' do
+ expect { current_user }.to raise_error Gitlab::Auth::ImpersonationDisabled
+ end
+ end
end
end
@@ -368,6 +381,14 @@ describe API::Helpers do
it_behaves_like 'successful sudo'
end
+ context 'when providing username (case insensitive)' do
+ before do
+ env[API::Helpers::SUDO_HEADER] = user.username.upcase
+ end
+
+ it_behaves_like 'successful sudo'
+ end
+
context 'when providing user ID' do
before do
env[API::Helpers::SUDO_HEADER] = user.id.to_s
@@ -386,6 +407,14 @@ describe API::Helpers do
it_behaves_like 'successful sudo'
end
+ context 'when providing username (case insensitive)' do
+ before do
+ set_param(API::Helpers::SUDO_PARAM, user.username.upcase)
+ end
+
+ it_behaves_like 'successful sudo'
+ end
+
context 'when providing user ID' do
before do
set_param(API::Helpers::SUDO_PARAM, user.id.to_s)
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb
index e0b5b34f9c4..2ebcb787d06 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal_spec.rb
@@ -494,6 +494,24 @@ describe API::Internal do
end
end
+ context 'request times out' do
+ context 'git push' do
+ it 'responds with a gateway timeout' do
+ personal_project = create(:project, namespace: user.namespace)
+
+ expect_next_instance_of(Gitlab::GitAccess) do |access|
+ expect(access).to receive(:check).and_raise(Gitlab::GitAccess::TimeoutError, "Foo")
+ end
+ push(key, personal_project)
+
+ expect(response).to have_gitlab_http_status(503)
+ expect(json_response['status']).to be_falsey
+ expect(json_response['message']).to eq("Foo")
+ expect(user.reload.last_activity_on).to be_nil
+ end
+ end
+ end
+
context "archived project" do
before do
project.add_developer(user)
diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
index f64815feffa..1827da61e2d 100644
--- a/spec/requests/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -55,7 +55,8 @@ describe API::Issues do
end
let!(:note) { create(:note_on_issue, author: user, project: project, noteable: issue) }
- let(:no_milestone_title) { URI.escape(Milestone::None.title) }
+ let(:no_milestone_title) { "None" }
+ let(:any_milestone_title) { "Any" }
before(:all) do
project.add_reporter(user)
@@ -168,16 +169,53 @@ describe API::Issues do
expect(first_issue['id']).to eq(issue2.id)
end
- it 'returns issues reacted by the authenticated user by the given emoji' do
- issue2 = create(:issue, project: project, author: user, assignees: [user])
- award_emoji = create(:award_emoji, awardable: issue2, user: user2, name: 'star')
+ it 'returns issues with no assignee' do
+ issue2 = create(:issue, author: user2, project: project)
- get api('/issues', user2), my_reaction_emoji: award_emoji.name, scope: 'all'
+ get api('/issues', user), assignee_id: 0, scope: 'all'
expect_paginated_array_response(size: 1)
expect(first_issue['id']).to eq(issue2.id)
end
+ it 'returns issues with no assignee' do
+ issue2 = create(:issue, author: user2, project: project)
+
+ get api('/issues', user), assignee_id: 'None', scope: 'all'
+
+ expect_paginated_array_response(size: 1)
+ expect(first_issue['id']).to eq(issue2.id)
+ end
+
+ it 'returns issues with any assignee' do
+ # This issue without assignee should not be returned
+ create(:issue, author: user2, project: project)
+
+ get api('/issues', user), assignee_id: 'Any', scope: 'all'
+
+ expect_paginated_array_response(size: 3)
+ end
+
+ it 'returns issues reacted by the authenticated user' do
+ issue2 = create(:issue, project: project, author: user, assignees: [user])
+ create(:award_emoji, awardable: issue2, user: user2, name: 'star')
+
+ create(:award_emoji, awardable: issue, user: user2, name: 'thumbsup')
+
+ get api('/issues', user2), my_reaction_emoji: 'Any', scope: 'all'
+
+ expect_paginated_array_response(size: 2)
+ end
+
+ it 'returns issues not reacted by the authenticated user' do
+ issue2 = create(:issue, project: project, author: user, assignees: [user])
+ create(:award_emoji, awardable: issue2, user: user2, name: 'star')
+
+ get api('/issues', user2), my_reaction_emoji: 'None', scope: 'all'
+
+ expect_paginated_array_response(size: 2)
+ end
+
it 'returns issues matching given search string for title' do
get api("/issues", user), search: issue.title
@@ -262,17 +300,31 @@ describe API::Issues do
expect(json_response.first['state']).to eq('opened')
end
- it 'returns unlabeled issues for "No Label" label' do
- get api("/issues", user), labels: 'No Label'
+ it 'returns an empty array if no issue matches labels and state filters' do
+ get api("/issues", user), labels: label.title, state: :closed
+
+ expect_paginated_array_response(size: 0)
+ end
+
+ it 'returns an array of issues with any label' do
+ get api("/issues", user), labels: IssuesFinder::FILTER_ANY
expect_paginated_array_response(size: 1)
- expect(json_response.first['labels']).to be_empty
+ expect(json_response.first['id']).to eq(issue.id)
end
- it 'returns an empty array if no issue matches labels and state filters' do
- get api("/issues?labels=#{label.title}&state=closed", user)
+ it 'returns an array of issues with no label' do
+ get api("/issues", user), labels: IssuesFinder::FILTER_NONE
- expect_paginated_array_response(size: 0)
+ expect_paginated_array_response(size: 1)
+ expect(json_response.first['id']).to eq(closed_issue.id)
+ end
+
+ it 'returns an array of issues with no label when using the legacy No+Label filter' do
+ get api("/issues", user), labels: "No Label"
+
+ expect_paginated_array_response(size: 1)
+ expect(json_response.first['id']).to eq(closed_issue.id)
end
it 'returns an empty array if no issue matches milestone' do
@@ -454,58 +506,58 @@ describe API::Issues do
end
it 'returns group issues without confidential issues for non project members' do
- get api("#{base_url}?state=opened", non_member)
+ get api(base_url, non_member), state: :opened
expect_paginated_array_response(size: 1)
expect(json_response.first['title']).to eq(group_issue.title)
end
it 'returns group confidential issues for author' do
- get api("#{base_url}?state=opened", author)
+ get api(base_url, author), state: :opened
expect_paginated_array_response(size: 2)
end
it 'returns group confidential issues for assignee' do
- get api("#{base_url}?state=opened", assignee)
+ get api(base_url, assignee), state: :opened
expect_paginated_array_response(size: 2)
end
it 'returns group issues with confidential issues for project members' do
- get api("#{base_url}?state=opened", user)
+ get api(base_url, user), state: :opened
expect_paginated_array_response(size: 2)
end
it 'returns group confidential issues for admin' do
- get api("#{base_url}?state=opened", admin)
+ get api(base_url, admin), state: :opened
expect_paginated_array_response(size: 2)
end
it 'returns an array of labeled group issues' do
- get api("#{base_url}?labels=#{group_label.title}", user)
+ get api(base_url, user), labels: group_label.title
expect_paginated_array_response(size: 1)
expect(json_response.first['labels']).to eq([group_label.title])
end
it 'returns an array of labeled group issues where all labels match' do
- get api("#{base_url}?labels=#{group_label.title},foo,bar", user)
+ get api(base_url, user), labels: "#{group_label.title},foo,bar"
expect_paginated_array_response(size: 0)
end
it 'returns issues matching given search string for title' do
- get api("#{base_url}?search=#{group_issue.title}", user)
+ get api(base_url, user), search: group_issue.title
expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(group_issue.id)
end
it 'returns issues matching given search string for description' do
- get api("#{base_url}?search=#{group_issue.description}", user)
+ get api(base_url, user), search: group_issue.description
expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(group_issue.id)
@@ -518,7 +570,7 @@ describe API::Issues do
create(:label_link, label: label_b, target: group_issue)
create(:label_link, label: label_c, target: group_issue)
- get api("#{base_url}", user), labels: "#{group_label.title},#{label_b.title},#{label_c.title}"
+ get api(base_url, user), labels: "#{group_label.title},#{label_b.title},#{label_c.title}"
expect_paginated_array_response(size: 1)
expect(json_response.first['labels']).to eq([label_c.title, label_b.title, group_label.title])
@@ -538,40 +590,55 @@ describe API::Issues do
end
it 'returns an empty array if no group issue matches labels' do
- get api("#{base_url}?labels=foo,bar", user)
+ get api(base_url, user), labels: 'foo,bar'
expect_paginated_array_response(size: 0)
end
+ it 'returns an array of group issues with any label' do
+ get api(base_url, user), labels: IssuesFinder::FILTER_ANY
+
+ expect_paginated_array_response(size: 1)
+ expect(json_response.first['id']).to eq(group_issue.id)
+ end
+
+ it 'returns an array of group issues with no label' do
+ get api(base_url, user), labels: IssuesFinder::FILTER_NONE
+
+ response_ids = json_response.map { |issue| issue['id'] }
+
+ expect_paginated_array_response(size: 2)
+ expect(response_ids).to contain_exactly(group_closed_issue.id, group_confidential_issue.id)
+ end
+
it 'returns an empty array if no issue matches milestone' do
- get api("#{base_url}?milestone=#{group_empty_milestone.title}", user)
+ get api(base_url, user), milestone: group_empty_milestone.title
expect_paginated_array_response(size: 0)
end
it 'returns an empty array if milestone does not exist' do
- get api("#{base_url}?milestone=foo", user)
+ get api(base_url, user), milestone: 'foo'
expect_paginated_array_response(size: 0)
end
it 'returns an array of issues in given milestone' do
- get api("#{base_url}?state=opened&milestone=#{group_milestone.title}", user)
+ get api(base_url, user), state: :opened, milestone: group_milestone.title
expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(group_issue.id)
end
it 'returns an array of issues matching state in milestone' do
- get api("#{base_url}?milestone=#{group_milestone.title}"\
- '&state=closed', user)
+ get api(base_url, user), milestone: group_milestone.title, state: :closed
expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(group_closed_issue.id)
end
it 'returns an array of issues with no milestone' do
- get api("#{base_url}?milestone=#{no_milestone_title}", user)
+ get api(base_url, user), milestone: no_milestone_title
expect(response).to have_gitlab_http_status(200)
@@ -607,7 +674,7 @@ describe API::Issues do
end
it 'sorts by updated_at ascending when requested' do
- get api("#{base_url}?order_by=updated_at&sort=asc", user)
+ get api(base_url, user), order_by: :updated_at, sort: :asc
response_dates = json_response.map { |issue| issue['updated_at'] }
@@ -710,7 +777,7 @@ describe API::Issues do
end
it 'returns an array of labeled project issues' do
- get api("#{base_url}/issues?labels=#{label.title}", user)
+ get api("#{base_url}/issues", user), labels: label.title
expect_paginated_array_response(size: 1)
expect(json_response.first['labels']).to eq([label.title])
@@ -762,26 +829,42 @@ describe API::Issues do
expect_paginated_array_response(size: 0)
end
+ it 'returns an array of project issues with any label' do
+ get api("#{base_url}/issues", user), labels: IssuesFinder::FILTER_ANY
+
+ expect_paginated_array_response(size: 1)
+ expect(json_response.first['id']).to eq(issue.id)
+ end
+
+ it 'returns an array of project issues with no label' do
+ get api("#{base_url}/issues", user), labels: IssuesFinder::FILTER_NONE
+
+ response_ids = json_response.map { |issue| issue['id'] }
+
+ expect_paginated_array_response(size: 2)
+ expect(response_ids).to contain_exactly(closed_issue.id, confidential_issue.id)
+ end
+
it 'returns an empty array if no project issue matches labels' do
- get api("#{base_url}/issues?labels=foo,bar", user)
+ get api("#{base_url}/issues", user), labels: 'foo,bar'
expect_paginated_array_response(size: 0)
end
it 'returns an empty array if no issue matches milestone' do
- get api("#{base_url}/issues?milestone=#{empty_milestone.title}", user)
+ get api("#{base_url}/issues", user), milestone: empty_milestone.title
expect_paginated_array_response(size: 0)
end
it 'returns an empty array if milestone does not exist' do
- get api("#{base_url}/issues?milestone=foo", user)
+ get api("#{base_url}/issues", user), milestone: :foo
expect_paginated_array_response(size: 0)
end
it 'returns an array of issues in given milestone' do
- get api("#{base_url}/issues?milestone=#{milestone.title}", user)
+ get api("#{base_url}/issues", user), milestone: milestone.title
expect_paginated_array_response(size: 2)
expect(json_response.first['id']).to eq(issue.id)
@@ -789,19 +872,28 @@ describe API::Issues do
end
it 'returns an array of issues matching state in milestone' do
- get api("#{base_url}/issues?milestone=#{milestone.title}&state=closed", user)
+ get api("#{base_url}/issues", user), milestone: milestone.title, state: :closed
expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(closed_issue.id)
end
it 'returns an array of issues with no milestone' do
- get api("#{base_url}/issues?milestone=#{no_milestone_title}", user)
+ get api("#{base_url}/issues", user), milestone: no_milestone_title
expect_paginated_array_response(size: 1)
expect(json_response.first['id']).to eq(confidential_issue.id)
end
+ it 'returns an array of issues with any milestone' do
+ get api("#{base_url}/issues", user), milestone: any_milestone_title
+
+ response_ids = json_response.map { |issue| issue['id'] }
+
+ expect_paginated_array_response(size: 2)
+ expect(response_ids).to contain_exactly(closed_issue.id, issue.id)
+ end
+
it 'sorts by created_at descending by default' do
get api("#{base_url}/issues", user)
@@ -812,7 +904,7 @@ describe API::Issues do
end
it 'sorts ascending when requested' do
- get api("#{base_url}/issues?sort=asc", user)
+ get api("#{base_url}/issues", user), sort: :asc
response_dates = json_response.map { |issue| issue['created_at'] }
@@ -821,7 +913,7 @@ describe API::Issues do
end
it 'sorts by updated_at descending when requested' do
- get api("#{base_url}/issues?order_by=updated_at", user)
+ get api("#{base_url}/issues", user), order_by: :updated_at
response_dates = json_response.map { |issue| issue['updated_at'] }
@@ -830,7 +922,7 @@ describe API::Issues do
end
it 'sorts by updated_at ascending when requested' do
- get api("#{base_url}/issues?order_by=updated_at&sort=asc", user)
+ get api("#{base_url}/issues", user), order_by: :updated_at, sort: :asc
response_dates = json_response.map { |issue| issue['updated_at'] }
@@ -1754,6 +1846,74 @@ describe API::Issues do
end
end
+ describe 'GET :id/issues/:issue_iid/related_merge_requests' do
+ def get_related_merge_requests(project_id, issue_iid, user = nil)
+ get api("/projects/#{project_id}/issues/#{issue_iid}/related_merge_requests", user)
+ end
+
+ def create_referencing_mr(user, project, issue)
+ attributes = {
+ author: user,
+ source_project: project,
+ target_project: project,
+ source_branch: "master",
+ target_branch: "test",
+ description: "See #{issue.to_reference}"
+ }
+ create(:merge_request, attributes).tap do |merge_request|
+ create(:note, :system, project: project, noteable: issue, author: user, note: merge_request.to_reference(full: true))
+ end
+ end
+
+ let!(:related_mr) { create_referencing_mr(user, project, issue) }
+
+ context 'when unauthenticated' do
+ it 'return list of referenced merge requests from issue' do
+ get_related_merge_requests(project.id, issue.iid)
+
+ expect_paginated_array_response(size: 1)
+ end
+
+ it 'renders 404 if project is not visible' do
+ private_project = create(:project, :private)
+ private_issue = create(:issue, project: private_project)
+ create_referencing_mr(user, private_project, private_issue)
+
+ get_related_merge_requests(private_project.id, private_issue.iid)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ it 'returns merge requests that mentioned a issue' do
+ create(:merge_request,
+ :simple,
+ author: user,
+ source_project: project,
+ target_project: project,
+ description: "Some description")
+
+ get_related_merge_requests(project.id, issue.iid, user)
+
+ expect_paginated_array_response(size: 1)
+ expect(json_response.first['id']).to eq(related_mr.id)
+ end
+
+ context 'no merge request mentioned a issue' do
+ it 'returns empty array' do
+ get_related_merge_requests(project.id, closed_issue.iid, user)
+
+ expect_paginated_array_response(size: 0)
+ end
+ end
+
+ it "returns 404 when issue doesn't exists" do
+ get_related_merge_requests(project.id, 999999, user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
describe "GET /projects/:id/issues/:issue_iid/user_agent_detail" do
let!(:user_agent_detail) { create(:user_agent_detail, subject: issue) }
diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb
index 6adbbb40489..8770365c893 100644
--- a/spec/requests/api/jobs_spec.rb
+++ b/spec/requests/api/jobs_spec.rb
@@ -721,7 +721,7 @@ describe API::Jobs do
expect(job.trace.exist?).to be_falsy
expect(job.artifacts_file.exists?).to be_falsy
expect(job.artifacts_metadata.exists?).to be_falsy
- expect(job.has_test_reports?).to be_falsy
+ expect(job.has_job_artifacts?).to be_falsy
end
it 'updates job' do
diff --git a/spec/requests/api/markdown_spec.rb b/spec/requests/api/markdown_spec.rb
index a55796cf343..e369c1435f0 100644
--- a/spec/requests/api/markdown_spec.rb
+++ b/spec/requests/api/markdown_spec.rb
@@ -106,6 +106,52 @@ describe API::Markdown do
.and include("#1</a>")
end
end
+
+ context 'with a public project and confidential issue' do
+ let(:public_project) { create(:project, :public) }
+ let(:confidential_issue) { create(:issue, :confidential, project: public_project, title: 'Confidential title') }
+
+ let(:text) { ":tada: Hello world! :100: #{confidential_issue.to_reference}" }
+ let(:params) { { text: text, gfm: true, project: public_project.full_path } }
+
+ shared_examples 'user without proper access' do
+ it 'does not render the title or link' do
+ expect(response).to have_http_status(201)
+ expect(json_response["html"]).not_to include('Confidential title')
+ expect(json_response["html"]).not_to include('<a href=')
+ expect(json_response["html"]).to include('Hello world!')
+ .and include('data-name="tada"')
+ .and include('data-name="100"')
+ .and include('#1</p>')
+ end
+ end
+
+ context 'when not logged in' do
+ let(:user) { }
+
+ it_behaves_like 'user without proper access'
+ end
+
+ context 'when logged in as user without access' do
+ let(:user) { create(:user) }
+
+ it_behaves_like 'user without proper access'
+ end
+
+ context 'when logged in as author' do
+ let(:user) { confidential_issue.author }
+
+ it 'renders the title or link' do
+ expect(response).to have_http_status(201)
+ expect(json_response["html"]).to include('Confidential title')
+ expect(json_response["html"]).to include('Hello world!')
+ .and include('data-name="tada"')
+ .and include('data-name="100"')
+ .and include("<a href=\"#{IssuesHelper.url_for_issue(confidential_issue.iid, public_project)}\"")
+ .and include("#1</a>")
+ end
+ end
+ end
end
end
end
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index e987eee6e91..27bcde77860 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -81,6 +81,35 @@ describe API::MergeRequests do
let(:user2) { create(:user) }
it 'returns an array of all merge requests except unauthorized ones' do
+ get api('/merge_requests', user), scope: :all
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.map { |mr| mr['id'] })
+ .to contain_exactly(merge_request.id, merge_request_closed.id, merge_request_merged.id, merge_request_locked.id, merge_request2.id)
+ end
+
+ it "returns an array of no merge_requests when wip=yes" do
+ get api("/merge_requests", user), wip: 'yes'
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(0)
+ end
+
+ it "returns an array of no merge_requests when wip=no" do
+ get api("/merge_requests", user), wip: 'no'
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.map { |mr| mr['id'] })
+ .to contain_exactly(merge_request.id, merge_request_closed.id, merge_request_merged.id, merge_request_locked.id, merge_request2.id)
+ end
+
+ it 'does not return unauthorized merge requests' do
private_project = create(:project, :private)
merge_request3 = create(:merge_request, :simple, source_project: private_project, target_project: private_project, source_branch: 'other-branch')
@@ -114,6 +143,23 @@ describe API::MergeRequests do
expect_response_ordered_exactly(merge_request3)
end
+ it 'returns an array of merge requests with no assignee' do
+ merge_request3 = create(:merge_request, :simple, author: user, source_project: project2, target_project: project2, source_branch: 'other-branch')
+
+ get api('/merge_requests', user), assignee_id: 'None', scope: :all
+
+ expect_response_ordered_exactly(merge_request3)
+ end
+
+ it 'returns an array of merge requests with any assignee' do
+ # This MR with no assignee should not be returned
+ create(:merge_request, :simple, author: user, source_project: project2, target_project: project2, source_branch: 'other-branch')
+
+ get api('/merge_requests', user), assignee_id: 'Any', scope: :all
+
+ expect_response_contain_exactly(merge_request, merge_request2, merge_request_closed, merge_request_merged, merge_request_locked)
+ end
+
it 'returns an array of merge requests assigned to me' do
merge_request3 = create(:merge_request, :simple, author: user, assignee: user2, source_project: project2, target_project: project2, source_branch: 'other-branch')
@@ -244,6 +290,15 @@ describe API::MergeRequests do
expect(response).to have_gitlab_http_status(404)
end
+ it "returns an array of no merge_requests when wip=yes" do
+ get api("/projects/#{project.id}/merge_requests", user), wip: 'yes'
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(0)
+ end
+
it 'returns merge_request by "iids" array' do
get api(endpoint_path, user), iids: [merge_request.iid, merge_request_closed.iid]
@@ -304,6 +359,8 @@ describe API::MergeRequests do
expect(json_response['should_close_merge_request']).to be_falsy
expect(json_response['force_close_merge_request']).to be_falsy
expect(json_response['changes_count']).to eq(merge_request.merge_request_diff.real_size)
+ expect(json_response['merge_error']).to eq(merge_request.merge_error)
+ expect(json_response).not_to include('rebase_in_progress')
end
it 'exposes description and title html when render_html is true' do
@@ -314,6 +371,14 @@ describe API::MergeRequests do
expect(json_response).to include('title_html', 'description_html')
end
+ it 'exposes rebase_in_progress when include_rebase_in_progress is true' do
+ get api("/projects/#{project.id}/merge_requests/#{merge_request.iid}", user), include_rebase_in_progress: true
+
+ expect(response).to have_gitlab_http_status(200)
+
+ expect(json_response).to include('rebase_in_progress')
+ end
+
context 'merge_request_metrics' do
before do
merge_request.metrics.update!(merged_by: user,
@@ -1126,6 +1191,26 @@ describe API::MergeRequests do
end
end
+ describe 'PUT :id/merge_requests/:merge_request_iid/rebase' do
+ it 'enqueues a rebase of the merge request against the target branch' do
+ Sidekiq::Testing.fake! do
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/rebase", user)
+ end
+
+ expect(response).to have_gitlab_http_status(202)
+ expect(RebaseWorker.jobs.size).to eq(1)
+ end
+
+ it 'returns 403 if the user cannot push to the branch' do
+ guest = create(:user)
+ project.add_guest(guest)
+
+ put api("/projects/#{project.id}/merge_requests/#{merge_request.iid}/rebase", guest)
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+
describe 'Time tracking' do
let(:issuable) { merge_request }
diff --git a/spec/requests/api/namespaces_spec.rb b/spec/requests/api/namespaces_spec.rb
index e2000ab42e8..145356c4df5 100644
--- a/spec/requests/api/namespaces_spec.rb
+++ b/spec/requests/api/namespaces_spec.rb
@@ -3,7 +3,7 @@ require 'spec_helper'
describe API::Namespaces do
let(:admin) { create(:admin) }
let(:user) { create(:user) }
- let!(:group1) { create(:group) }
+ let!(:group1) { create(:group, name: 'group.one') }
let!(:group2) { create(:group, :nested) }
describe "GET /namespaces" do
diff --git a/spec/requests/api/pages/internal_access_spec.rb b/spec/requests/api/pages/internal_access_spec.rb
new file mode 100644
index 00000000000..c41eabe0a48
--- /dev/null
+++ b/spec/requests/api/pages/internal_access_spec.rb
@@ -0,0 +1,88 @@
+require 'spec_helper'
+
+describe "Internal Project Pages Access" do
+ using RSpec::Parameterized::TableSyntax
+ include AccessMatchers
+
+ set(:group) { create(:group) }
+ set(:project) { create(:project, :internal, pages_access_level: ProjectFeature::ENABLED, namespace: group) }
+
+ set(:admin) { create(:admin) }
+ set(:owner) { create(:user) }
+ set(:master) { create(:user) }
+ set(:developer) { create(:user) }
+ set(:reporter) { create(:user) }
+ set(:guest) { create(:user) }
+ set(:user) { create(:user) }
+
+ before do
+ allow(Gitlab.config.pages).to receive(:access_control).and_return(true)
+ group.add_owner(owner)
+ project.add_master(master)
+ project.add_developer(developer)
+ project.add_reporter(reporter)
+ project.add_guest(guest)
+ end
+
+ describe "Project should be internal" do
+ describe '#internal?' do
+ subject { project.internal? }
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ describe "GET /projects/:id/pages_access" do
+ context 'access depends on the level' do
+ where(:pages_access_level, :with_user, :expected_result) do
+ ProjectFeature::DISABLED | "admin" | 403
+ ProjectFeature::DISABLED | "owner" | 403
+ ProjectFeature::DISABLED | "master" | 403
+ ProjectFeature::DISABLED | "developer" | 403
+ ProjectFeature::DISABLED | "reporter" | 403
+ ProjectFeature::DISABLED | "guest" | 403
+ ProjectFeature::DISABLED | "user" | 403
+ ProjectFeature::DISABLED | nil | 404
+ ProjectFeature::PUBLIC | "admin" | 200
+ ProjectFeature::PUBLIC | "owner" | 200
+ ProjectFeature::PUBLIC | "master" | 200
+ ProjectFeature::PUBLIC | "developer" | 200
+ ProjectFeature::PUBLIC | "reporter" | 200
+ ProjectFeature::PUBLIC | "guest" | 200
+ ProjectFeature::PUBLIC | "user" | 200
+ ProjectFeature::PUBLIC | nil | 404
+ ProjectFeature::ENABLED | "admin" | 200
+ ProjectFeature::ENABLED | "owner" | 200
+ ProjectFeature::ENABLED | "master" | 200
+ ProjectFeature::ENABLED | "developer" | 200
+ ProjectFeature::ENABLED | "reporter" | 200
+ ProjectFeature::ENABLED | "guest" | 200
+ ProjectFeature::ENABLED | "user" | 200
+ ProjectFeature::ENABLED | nil | 404
+ ProjectFeature::PRIVATE | "admin" | 200
+ ProjectFeature::PRIVATE | "owner" | 200
+ ProjectFeature::PRIVATE | "master" | 200
+ ProjectFeature::PRIVATE | "developer" | 200
+ ProjectFeature::PRIVATE | "reporter" | 200
+ ProjectFeature::PRIVATE | "guest" | 200
+ ProjectFeature::PRIVATE | "user" | 403
+ ProjectFeature::PRIVATE | nil | 404
+ end
+
+ with_them do
+ before do
+ project.project_feature.update(pages_access_level: pages_access_level)
+ end
+ it "correct return value" do
+ if !with_user.nil?
+ user = public_send(with_user)
+ get api("/projects/#{project.id}/pages_access", user)
+ else
+ get api("/projects/#{project.id}/pages_access")
+ end
+
+ expect(response).to have_gitlab_http_status(expected_result)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/pages/private_access_spec.rb b/spec/requests/api/pages/private_access_spec.rb
new file mode 100644
index 00000000000..d69c15b0477
--- /dev/null
+++ b/spec/requests/api/pages/private_access_spec.rb
@@ -0,0 +1,88 @@
+require 'spec_helper'
+
+describe "Private Project Pages Access" do
+ using RSpec::Parameterized::TableSyntax
+ include AccessMatchers
+
+ set(:group) { create(:group) }
+ set(:project) { create(:project, :private, pages_access_level: ProjectFeature::ENABLED, namespace: group) }
+
+ set(:admin) { create(:admin) }
+ set(:owner) { create(:user) }
+ set(:master) { create(:user) }
+ set(:developer) { create(:user) }
+ set(:reporter) { create(:user) }
+ set(:guest) { create(:user) }
+ set(:user) { create(:user) }
+
+ before do
+ allow(Gitlab.config.pages).to receive(:access_control).and_return(true)
+ group.add_owner(owner)
+ project.add_master(master)
+ project.add_developer(developer)
+ project.add_reporter(reporter)
+ project.add_guest(guest)
+ end
+
+ describe "Project should be private" do
+ describe '#private?' do
+ subject { project.private? }
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ describe "GET /projects/:id/pages_access" do
+ context 'access depends on the level' do
+ where(:pages_access_level, :with_user, :expected_result) do
+ ProjectFeature::DISABLED | "admin" | 403
+ ProjectFeature::DISABLED | "owner" | 403
+ ProjectFeature::DISABLED | "master" | 403
+ ProjectFeature::DISABLED | "developer" | 403
+ ProjectFeature::DISABLED | "reporter" | 403
+ ProjectFeature::DISABLED | "guest" | 403
+ ProjectFeature::DISABLED | "user" | 404
+ ProjectFeature::DISABLED | nil | 404
+ ProjectFeature::PUBLIC | "admin" | 200
+ ProjectFeature::PUBLIC | "owner" | 200
+ ProjectFeature::PUBLIC | "master" | 200
+ ProjectFeature::PUBLIC | "developer" | 200
+ ProjectFeature::PUBLIC | "reporter" | 200
+ ProjectFeature::PUBLIC | "guest" | 200
+ ProjectFeature::PUBLIC | "user" | 404
+ ProjectFeature::PUBLIC | nil | 404
+ ProjectFeature::ENABLED | "admin" | 200
+ ProjectFeature::ENABLED | "owner" | 200
+ ProjectFeature::ENABLED | "master" | 200
+ ProjectFeature::ENABLED | "developer" | 200
+ ProjectFeature::ENABLED | "reporter" | 200
+ ProjectFeature::ENABLED | "guest" | 200
+ ProjectFeature::ENABLED | "user" | 404
+ ProjectFeature::ENABLED | nil | 404
+ ProjectFeature::PRIVATE | "admin" | 200
+ ProjectFeature::PRIVATE | "owner" | 200
+ ProjectFeature::PRIVATE | "master" | 200
+ ProjectFeature::PRIVATE | "developer" | 200
+ ProjectFeature::PRIVATE | "reporter" | 200
+ ProjectFeature::PRIVATE | "guest" | 200
+ ProjectFeature::PRIVATE | "user" | 404
+ ProjectFeature::PRIVATE | nil | 404
+ end
+
+ with_them do
+ before do
+ project.project_feature.update(pages_access_level: pages_access_level)
+ end
+ it "correct return value" do
+ if !with_user.nil?
+ user = public_send(with_user)
+ get api("/projects/#{project.id}/pages_access", user)
+ else
+ get api("/projects/#{project.id}/pages_access")
+ end
+
+ expect(response).to have_gitlab_http_status(expected_result)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/pages/public_access_spec.rb b/spec/requests/api/pages/public_access_spec.rb
new file mode 100644
index 00000000000..882ca26ac51
--- /dev/null
+++ b/spec/requests/api/pages/public_access_spec.rb
@@ -0,0 +1,88 @@
+require 'spec_helper'
+
+describe "Public Project Pages Access" do
+ using RSpec::Parameterized::TableSyntax
+ include AccessMatchers
+
+ set(:group) { create(:group) }
+ set(:project) { create(:project, :public, pages_access_level: ProjectFeature::ENABLED, namespace: group) }
+
+ set(:admin) { create(:admin) }
+ set(:owner) { create(:user) }
+ set(:master) { create(:user) }
+ set(:developer) { create(:user) }
+ set(:reporter) { create(:user) }
+ set(:guest) { create(:user) }
+ set(:user) { create(:user) }
+
+ before do
+ allow(Gitlab.config.pages).to receive(:access_control).and_return(true)
+ group.add_owner(owner)
+ project.add_master(master)
+ project.add_developer(developer)
+ project.add_reporter(reporter)
+ project.add_guest(guest)
+ end
+
+ describe "Project should be public" do
+ describe '#public?' do
+ subject { project.public? }
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ describe "GET /projects/:id/pages_access" do
+ context 'access depends on the level' do
+ where(:pages_access_level, :with_user, :expected_result) do
+ ProjectFeature::DISABLED | "admin" | 403
+ ProjectFeature::DISABLED | "owner" | 403
+ ProjectFeature::DISABLED | "master" | 403
+ ProjectFeature::DISABLED | "developer" | 403
+ ProjectFeature::DISABLED | "reporter" | 403
+ ProjectFeature::DISABLED | "guest" | 403
+ ProjectFeature::DISABLED | "user" | 403
+ ProjectFeature::DISABLED | nil | 403
+ ProjectFeature::PUBLIC | "admin" | 200
+ ProjectFeature::PUBLIC | "owner" | 200
+ ProjectFeature::PUBLIC | "master" | 200
+ ProjectFeature::PUBLIC | "developer" | 200
+ ProjectFeature::PUBLIC | "reporter" | 200
+ ProjectFeature::PUBLIC | "guest" | 200
+ ProjectFeature::PUBLIC | "user" | 200
+ ProjectFeature::PUBLIC | nil | 200
+ ProjectFeature::ENABLED | "admin" | 200
+ ProjectFeature::ENABLED | "owner" | 200
+ ProjectFeature::ENABLED | "master" | 200
+ ProjectFeature::ENABLED | "developer" | 200
+ ProjectFeature::ENABLED | "reporter" | 200
+ ProjectFeature::ENABLED | "guest" | 200
+ ProjectFeature::ENABLED | "user" | 200
+ ProjectFeature::ENABLED | nil | 200
+ ProjectFeature::PRIVATE | "admin" | 200
+ ProjectFeature::PRIVATE | "owner" | 200
+ ProjectFeature::PRIVATE | "master" | 200
+ ProjectFeature::PRIVATE | "developer" | 200
+ ProjectFeature::PRIVATE | "reporter" | 200
+ ProjectFeature::PRIVATE | "guest" | 200
+ ProjectFeature::PRIVATE | "user" | 403
+ ProjectFeature::PRIVATE | nil | 403
+ end
+
+ with_them do
+ before do
+ project.project_feature.update(pages_access_level: pages_access_level)
+ end
+ it "correct return value" do
+ if !with_user.nil?
+ user = public_send(with_user)
+ get api("/projects/#{project.id}/pages_access", user)
+ else
+ get api("/projects/#{project.id}/pages_access")
+ end
+
+ expect(response).to have_gitlab_http_status(expected_result)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/pipelines_spec.rb b/spec/requests/api/pipelines_spec.rb
index f0e1992bccd..638cc9767d4 100644
--- a/spec/requests/api/pipelines_spec.rb
+++ b/spec/requests/api/pipelines_spec.rb
@@ -438,6 +438,67 @@ describe API::Pipelines do
end
end
+ describe 'DELETE /projects/:id/pipelines/:pipeline_id' do
+ context 'authorized user' do
+ let(:owner) { project.owner }
+
+ it 'destroys the pipeline' do
+ delete api("/projects/#{project.id}/pipelines/#{pipeline.id}", owner)
+
+ expect(response).to have_gitlab_http_status(204)
+ expect { pipeline.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+
+ it 'returns 404 when it does not exist' do
+ delete api("/projects/#{project.id}/pipelines/123456", owner)
+
+ expect(response).to have_gitlab_http_status(404)
+ expect(json_response['message']).to eq '404 Not found'
+ end
+
+ it 'logs an audit event' do
+ expect { delete api("/projects/#{project.id}/pipelines/#{pipeline.id}", owner) }.to change { SecurityEvent.count }.by(1)
+ end
+
+ context 'when the pipeline has jobs' do
+ let!(:build) { create(:ci_build, project: project, pipeline: pipeline) }
+
+ it 'destroys associated jobs' do
+ delete api("/projects/#{project.id}/pipelines/#{pipeline.id}", owner)
+
+ expect(response).to have_gitlab_http_status(204)
+ expect { build.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+ end
+
+ context 'unauthorized user' do
+ context 'when user is not member' do
+ it 'should return a 404' do
+ delete api("/projects/#{project.id}/pipelines/#{pipeline.id}", non_member)
+
+ expect(response).to have_gitlab_http_status(404)
+ expect(json_response['message']).to eq '404 Project Not Found'
+ end
+ end
+
+ context 'when user is developer' do
+ let(:developer) { create(:user) }
+
+ before do
+ project.add_developer(developer)
+ end
+
+ it 'should return a 403' do
+ delete api("/projects/#{project.id}/pipelines/#{pipeline.id}", developer)
+
+ expect(response).to have_gitlab_http_status(403)
+ expect(json_response['message']).to eq '403 Forbidden'
+ end
+ end
+ end
+ end
+
describe 'POST /projects/:id/pipelines/:pipeline_id/retry' do
context 'authorized user' do
let!(:pipeline) do
diff --git a/spec/requests/api/project_import_spec.rb b/spec/requests/api/project_import_spec.rb
index c8fa4754810..204702b8a5a 100644
--- a/spec/requests/api/project_import_spec.rb
+++ b/spec/requests/api/project_import_spec.rb
@@ -42,7 +42,7 @@ describe API::ProjectImport do
end
it 'does not schedule an import for a namespace that does not exist' do
- expect_any_instance_of(Project).not_to receive(:import_schedule)
+ expect_any_instance_of(ProjectImportState).not_to receive(:schedule)
expect(::Projects::CreateService).not_to receive(:new)
post api('/projects/import', user), namespace: 'nonexistent', path: 'test-import2', file: fixture_file_upload(file)
@@ -52,7 +52,7 @@ describe API::ProjectImport do
end
it 'does not schedule an import if the user has no permission to the namespace' do
- expect_any_instance_of(Project).not_to receive(:import_schedule)
+ expect_any_instance_of(ProjectImportState).not_to receive(:schedule)
post(api('/projects/import', create(:user)),
path: 'test-import3',
@@ -64,7 +64,7 @@ describe API::ProjectImport do
end
it 'does not schedule an import if the user uploads no valid file' do
- expect_any_instance_of(Project).not_to receive(:import_schedule)
+ expect_any_instance_of(ProjectImportState).not_to receive(:schedule)
post api('/projects/import', user), path: 'test-import3', file: './random/test'
@@ -119,7 +119,7 @@ describe API::ProjectImport do
let(:existing_project) { create(:project, namespace: user.namespace) }
it 'does not schedule an import' do
- expect_any_instance_of(Project).not_to receive(:import_schedule)
+ expect_any_instance_of(ProjectImportState).not_to receive(:schedule)
post api('/projects/import', user), path: existing_project.path, file: fixture_file_upload(file)
@@ -139,7 +139,7 @@ describe API::ProjectImport do
end
def stub_import(namespace)
- expect_any_instance_of(Project).to receive(:import_schedule)
+ expect_any_instance_of(ProjectImportState).to receive(:schedule)
expect(::Projects::CreateService).to receive(:new).with(user, hash_including(namespace_id: namespace.id)).and_call_original
end
end
diff --git a/spec/requests/api/project_templates_spec.rb b/spec/requests/api/project_templates_spec.rb
new file mode 100644
index 00000000000..86e33f23951
--- /dev/null
+++ b/spec/requests/api/project_templates_spec.rb
@@ -0,0 +1,145 @@
+require 'spec_helper'
+
+describe API::ProjectTemplates do
+ let(:public_project) { create(:project, :public) }
+ let(:private_project) { create(:project, :private) }
+ let(:developer) { create(:user) }
+
+ before do
+ private_project.add_developer(developer)
+ end
+
+ describe 'GET /projects/:id/templates/:type' do
+ it 'returns dockerfiles' do
+ get api("/projects/#{public_project.id}/templates/dockerfiles")
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(response).to match_response_schema('public_api/v4/template_list')
+ expect(json_response).to satisfy_one { |template| template['key'] == 'Binary' }
+ end
+
+ it 'returns gitignores' do
+ get api("/projects/#{public_project.id}/templates/gitignores")
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(response).to match_response_schema('public_api/v4/template_list')
+ expect(json_response).to satisfy_one { |template| template['key'] == 'Actionscript' }
+ end
+
+ it 'returns gitlab_ci_ymls' do
+ get api("/projects/#{public_project.id}/templates/gitlab_ci_ymls")
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(response).to match_response_schema('public_api/v4/template_list')
+ expect(json_response).to satisfy_one { |template| template['key'] == 'Android' }
+ end
+
+ it 'returns licenses' do
+ get api("/projects/#{public_project.id}/templates/licenses")
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(response).to match_response_schema('public_api/v4/template_list')
+ expect(json_response).to satisfy_one { |template| template['key'] == 'mit' }
+ end
+
+ it 'returns 400 for an unknown template type' do
+ get api("/projects/#{public_project.id}/templates/unknown")
+
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'denies access to an anonymous user on a private project' do
+ get api("/projects/#{private_project.id}/templates/licenses")
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'permits access to a developer on a private project' do
+ get api("/projects/#{private_project.id}/templates/licenses", developer)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/template_list')
+ end
+ end
+
+ describe 'GET /projects/:id/templates/licenses' do
+ it 'returns key and name for the listed licenses' do
+ get api("/projects/#{public_project.id}/templates/licenses")
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/template_list')
+ end
+ end
+
+ describe 'GET /projects/:id/templates/:type/:key' do
+ it 'returns a specific dockerfile' do
+ get api("/projects/#{public_project.id}/templates/dockerfiles/Binary")
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/template')
+ expect(json_response['name']).to eq('Binary')
+ end
+
+ it 'returns a specific gitignore' do
+ get api("/projects/#{public_project.id}/templates/gitignores/Actionscript")
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/template')
+ expect(json_response['name']).to eq('Actionscript')
+ end
+
+ it 'returns a specific gitlab_ci_yml' do
+ get api("/projects/#{public_project.id}/templates/gitlab_ci_ymls/Android")
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/template')
+ expect(json_response['name']).to eq('Android')
+ end
+
+ it 'returns a specific license' do
+ get api("/projects/#{public_project.id}/templates/licenses/mit")
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/license')
+ end
+
+ it 'returns 404 for an unknown specific template' do
+ get api("/projects/#{public_project.id}/templates/licenses/unknown")
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'denies access to an anonymous user on a private project' do
+ get api("/projects/#{private_project.id}/templates/licenses/mit")
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'permits access to a developer on a private project' do
+ get api("/projects/#{private_project.id}/templates/licenses/mit", developer)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/license')
+ end
+ end
+
+ describe 'GET /projects/:id/templates/licenses/:key' do
+ it 'fills placeholders in the license' do
+ get api("/projects/#{public_project.id}/templates/licenses/agpl-3.0"),
+ project: 'Project Placeholder',
+ fullname: 'Fullname Placeholder'
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to match_response_schema('public_api/v4/license')
+
+ content = json_response['content']
+
+ expect(content).to include('Project Placeholder')
+ expect(content).to include("Copyright (C) #{Time.now.year} Fullname Placeholder")
+ end
+ end
+end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index c8e98e6024c..62b6a3ce42e 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -200,6 +200,24 @@ describe API::Projects do
expect(json_response.first).to include 'statistics'
end
+ it "does not include license by default" do
+ get api('/projects', user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.first).not_to include('license', 'license_url')
+ end
+
+ it "does not include license if requested" do
+ get api('/projects', user), license: true
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.first).not_to include('license', 'license_url')
+ end
+
context 'when external issue tracker is enabled' do
let!(:jira_service) { create(:jira_service, project: project) }
@@ -994,6 +1012,26 @@ describe API::Projects do
})
end
+ it "does not include license fields by default" do
+ get api("/projects/#{project.id}", user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).not_to include('license', 'license_url')
+ end
+
+ it 'includes license fields when requested' do
+ get api("/projects/#{project.id}", user), license: true
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['license']).to eq({
+ 'key' => project.repository.license.key,
+ 'name' => project.repository.license.name,
+ 'nickname' => project.repository.license.nickname,
+ 'html_url' => project.repository.license.url,
+ 'source_url' => project.repository.license.meta['source']
+ })
+ end
+
it "does not include statistics by default" do
get api("/projects/#{project.id}", user)
@@ -1196,7 +1234,7 @@ describe API::Projects do
expect(response).to have_gitlab_http_status(201)
expect(project_fork_target.forked_from_project.id).to eq(project_fork_source.id)
- expect(project_fork_target.forked_project_link).to be_present
+ expect(project_fork_target.fork_network_member).to be_present
expect(project_fork_target).to be_forked
end
diff --git a/spec/requests/api/redacted_events_spec.rb b/spec/requests/api/redacted_events_spec.rb
new file mode 100644
index 00000000000..086dd3df9ba
--- /dev/null
+++ b/spec/requests/api/redacted_events_spec.rb
@@ -0,0 +1,68 @@
+require 'spec_helper'
+
+describe 'Redacted events in API::Events' do
+ shared_examples 'private events are redacted' do
+ it 'redacts events the user does not have access to' do
+ expect_any_instance_of(Event).to receive(:visible_to_user?).and_call_original
+
+ get api(path), user
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to contain_exactly(
+ 'project_id' => nil,
+ 'action_name' => nil,
+ 'target_id' => nil,
+ 'target_iid' => nil,
+ 'target_type' => nil,
+ 'author_id' => nil,
+ 'target_title' => 'Confidential event',
+ 'created_at' => nil,
+ 'author_username' => nil
+ )
+ end
+ end
+
+ describe '/users/:id/events' do
+ let(:project) { create(:project, :public) }
+ let(:path) { "/users/#{project.owner.id}/events" }
+ let(:issue) { create(:issue, :confidential, project: project) }
+
+ before do
+ EventCreateService.new.open_issue(issue, issue.author)
+ end
+
+ context 'unauthenticated user views another user with private events' do
+ let(:user) { nil }
+
+ include_examples 'private events are redacted'
+ end
+
+ context 'authenticated user without access views another user with private events' do
+ let(:user) { create(:user) }
+
+ include_examples 'private events are redacted'
+ end
+ end
+
+ describe '/projects/:id/events' do
+ let(:project) { create(:project, :public) }
+ let(:path) { "/projects/#{project.id}/events" }
+ let(:issue) { create(:issue, :confidential, project: project) }
+
+ before do
+ EventCreateService.new.open_issue(issue, issue.author)
+ end
+
+ context 'unauthenticated user views public project' do
+ let(:user) { nil }
+
+ include_examples 'private events are redacted'
+ end
+
+ context 'authenticated user without access views public project' do
+ let(:user) { create(:user) }
+
+ include_examples 'private events are redacted'
+ end
+ end
+end
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index 519638ebb82..de141377793 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -168,6 +168,12 @@ describe API::Repositories do
expect(response).to have_gitlab_http_status(200)
end
+ it 'forces attachment content disposition' do
+ get api(route, current_user)
+
+ expect(headers['Content-Disposition']).to match(/^attachment/)
+ end
+
context 'when sha does not exist' do
it_behaves_like '404 response' do
let(:request) { get api(route.sub(sample_blob.oid, '123456'), current_user) }
@@ -468,7 +474,7 @@ describe API::Repositories do
describe 'GET :id/repository/merge_base' do
let(:refs) do
- %w(304d257dcb821665ab5110318fc58a007bd104ed 0031876facac3f2b2702a0e53a26e89939a42209)
+ %w(304d257dcb821665ab5110318fc58a007bd104ed 0031876facac3f2b2702a0e53a26e89939a42209 570e7b2abdd848b95f2f578043fc23bd6f6fd24d)
end
subject(:request) do
@@ -534,7 +540,7 @@ describe API::Repositories do
request
expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['message']).to eq('Provide exactly 2 refs')
+ expect(json_response['message']).to eq('Provide at least 2 refs')
end
end
end
diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb
index 43ceb332cfb..b36087b86a7 100644
--- a/spec/requests/api/runner_spec.rb
+++ b/spec/requests/api/runner_spec.rb
@@ -797,6 +797,24 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
it { expect(job).to be_runner_system_failure }
end
+
+ context 'when failure_reason is unrecognized value' do
+ before do
+ update_job(state: 'failed', failure_reason: 'what_is_this')
+ job.reload
+ end
+
+ it { expect(job).to be_unknown_failure }
+ end
+
+ context 'when failure_reason is job_execution_timeout' do
+ before do
+ update_job(state: 'failed', failure_reason: 'job_execution_timeout')
+ job.reload
+ end
+
+ it { expect(job).to be_job_execution_timeout }
+ end
end
context 'when trace is given' do
@@ -812,6 +830,18 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
expect(job.trace.raw).to eq 'BUILD TRACE UPDATED'
expect(job.job_artifacts_trace.open.read).to eq 'BUILD TRACE UPDATED'
end
+
+ context 'when concurrent update of trace is happening' do
+ before do
+ job.trace.write('wb') do
+ update_job(state: 'success', trace: 'BUILD TRACE UPDATED')
+ end
+ end
+
+ it 'returns that operation conflicts' do
+ expect(response.status).to eq(409)
+ end
+ end
end
context 'when no trace is given' do
@@ -1004,6 +1034,18 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
end
end
+ context 'when concurrent update of trace is happening' do
+ before do
+ job.trace.write('wb') do
+ patch_the_trace
+ end
+ end
+
+ it 'returns that operation conflicts' do
+ expect(response.status).to eq(409)
+ end
+ end
+
context 'when the job is canceled' do
before do
job.cancel
diff --git a/spec/requests/api/runners_spec.rb b/spec/requests/api/runners_spec.rb
index 3ebdb54f71f..49a79d2ccf9 100644
--- a/spec/requests/api/runners_spec.rb
+++ b/spec/requests/api/runners_spec.rb
@@ -25,36 +25,71 @@ describe API::Runners do
describe 'GET /runners' do
context 'authorized user' do
- it 'returns user available runners' do
+ it 'returns response status and headers' do
get api('/runners', user)
- shared = json_response.any? { |r| r['is_shared'] }
- descriptions = json_response.map { |runner| runner['description'] }
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response[0]).to have_key('ip_address')
- expect(descriptions).to contain_exactly(
- 'Project runner', 'Two projects runner', 'Group runner'
- )
- expect(shared).to be_falsey
+ end
+
+ it 'returns user available runners' do
+ get api('/runners', user)
+
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Project runner'),
+ a_hash_including('description' => 'Two projects runner'),
+ a_hash_including('description' => 'Group runner')
+ ]
end
it 'filters runners by scope' do
- get api('/runners?scope=active', user)
+ create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project])
+
+ get api('/runners?scope=paused', user)
- shared = json_response.any? { |r| r['is_shared'] }
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response[0]).to have_key('ip_address')
- expect(shared).to be_falsey
+
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Inactive project runner')
+ ]
end
it 'avoids filtering if scope is invalid' do
get api('/runners?scope=unknown', user)
expect(response).to have_gitlab_http_status(400)
end
+
+ it 'filters runners by type' do
+ get api('/runners?type=project_type', user)
+
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Project runner'),
+ a_hash_including('description' => 'Two projects runner')
+ ]
+ end
+
+ it 'does not filter by invalid type' do
+ get api('/runners?type=bogus', user)
+
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'filters runners by status' do
+ create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project])
+
+ get api('/runners?status=paused', user)
+
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Inactive project runner')
+ ]
+ end
+
+ it 'does not filter by invalid status' do
+ get api('/runners?status=bogus', user)
+
+ expect(response).to have_gitlab_http_status(400)
+ end
end
context 'unauthorized user' do
@@ -69,51 +104,91 @@ describe API::Runners do
describe 'GET /runners/all' do
context 'authorized user' do
context 'with admin privileges' do
+ it 'returns response status and headers' do
+ get api('/runners/all', admin)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ end
+
it 'returns all runners' do
get api('/runners/all', admin)
- shared = json_response.any? { |r| r['is_shared'] }
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Project runner'),
+ a_hash_including('description' => 'Two projects runner'),
+ a_hash_including('description' => 'Group runner'),
+ a_hash_including('description' => 'Shared runner')
+ ]
+ end
+
+ it 'filters runners by scope' do
+ get api('/runners/all?scope=shared', admin)
+
+ shared = json_response.all? { |r| r['is_shared'] }
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response[0]).to have_key('ip_address')
expect(shared).to be_truthy
end
- end
- context 'without admin privileges' do
- it 'does not return runners list' do
- get api('/runners/all', user)
+ it 'filters runners by scope' do
+ get api('/runners/all?scope=specific', admin)
- expect(response).to have_gitlab_http_status(403)
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Project runner'),
+ a_hash_including('description' => 'Two projects runner'),
+ a_hash_including('description' => 'Group runner')
+ ]
end
- end
- it 'filters runners by scope' do
- get api('/runners/all?scope=shared', admin)
+ it 'avoids filtering if scope is invalid' do
+ get api('/runners/all?scope=unknown', admin)
+ expect(response).to have_gitlab_http_status(400)
+ end
- shared = json_response.all? { |r| r['is_shared'] }
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response[0]).to have_key('ip_address')
- expect(shared).to be_truthy
- end
+ it 'filters runners by type' do
+ get api('/runners/all?type=project_type', admin)
- it 'filters runners by scope' do
- get api('/runners/all?scope=specific', admin)
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Project runner'),
+ a_hash_including('description' => 'Two projects runner')
+ ]
+ end
- shared = json_response.any? { |r| r['is_shared'] }
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response[0]).to have_key('ip_address')
- expect(shared).to be_falsey
+ it 'does not filter by invalid type' do
+ get api('/runners/all?type=bogus', admin)
+
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'filters runners by status' do
+ create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project])
+
+ get api('/runners/all?status=paused', admin)
+
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Inactive project runner')
+ ]
+ end
+
+ it 'does not filter by invalid status' do
+ get api('/runners/all?status=bogus', admin)
+
+ expect(response).to have_gitlab_http_status(400)
+ end
end
- it 'avoids filtering if scope is invalid' do
- get api('/runners?scope=unknown', admin)
- expect(response).to have_gitlab_http_status(400)
+ context 'without admin privileges' do
+ it 'does not return runners list' do
+ get api('/runners/all', user)
+
+ expect(response).to have_gitlab_http_status(403)
+ end
end
end
@@ -577,15 +652,69 @@ describe API::Runners do
describe 'GET /projects/:id/runners' do
context 'authorized user with maintainer privileges' do
- it "returns project's runners" do
+ it 'returns response status and headers' do
+ get api('/runners/all', admin)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ end
+
+ it 'returns all runners' do
get api("/projects/#{project.id}/runners", user)
- shared = json_response.any? { |r| r['is_shared'] }
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Project runner'),
+ a_hash_including('description' => 'Two projects runner'),
+ a_hash_including('description' => 'Shared runner')
+ ]
+ end
+
+ it 'filters runners by scope' do
+ get api("/projects/#{project.id}/runners?scope=specific", user)
+
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response[0]).to have_key('ip_address')
- expect(shared).to be_truthy
+
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Project runner'),
+ a_hash_including('description' => 'Two projects runner')
+ ]
+ end
+
+ it 'avoids filtering if scope is invalid' do
+ get api("/projects/#{project.id}/runners?scope=unknown", user)
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'filters runners by type' do
+ get api("/projects/#{project.id}/runners?type=project_type", user)
+
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Project runner'),
+ a_hash_including('description' => 'Two projects runner')
+ ]
+ end
+
+ it 'does not filter by invalid type' do
+ get api("/projects/#{project.id}/runners?type=bogus", user)
+
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'filters runners by status' do
+ create(:ci_runner, :project, :inactive, description: 'Inactive project runner', projects: [project])
+
+ get api("/projects/#{project.id}/runners?status=paused", user)
+
+ expect(json_response).to match_array [
+ a_hash_including('description' => 'Inactive project runner')
+ ]
+ end
+
+ it 'does not filter by invalid status' do
+ get api("/projects/#{project.id}/runners?status=bogus", user)
+
+ expect(response).to have_gitlab_http_status(400)
end
end
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 3e0f47b84a1..84c7210f6bb 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -2,18 +2,17 @@ require 'spec_helper'
describe API::Settings, 'Settings' do
let(:user) { create(:user) }
- let(:admin) { create(:admin) }
+ set(:admin) { create(:admin) }
describe "GET /application/settings" do
it "returns application settings" do
get api("/application/settings", admin)
+
expect(response).to have_gitlab_http_status(200)
expect(json_response).to be_an Hash
expect(json_response['default_projects_limit']).to eq(42)
expect(json_response['password_authentication_enabled_for_web']).to be_truthy
expect(json_response['repository_storages']).to eq(['default'])
- expect(json_response['koding_enabled']).to be_falsey
- expect(json_response['koding_url']).to be_nil
expect(json_response['plantuml_enabled']).to be_falsey
expect(json_response['plantuml_url']).to be_nil
expect(json_response['default_project_visibility']).to be_a String
@@ -23,7 +22,6 @@ describe API::Settings, 'Settings' do
expect(json_response['dsa_key_restriction']).to eq(0)
expect(json_response['ecdsa_key_restriction']).to eq(0)
expect(json_response['ed25519_key_restriction']).to eq(0)
- expect(json_response['circuitbreaker_failure_count_threshold']).not_to be_nil
expect(json_response['performance_bar_allowed_group_id']).to be_nil
expect(json_response['instance_statistics_visibility_private']).to be(false)
expect(json_response).not_to have_key('performance_bar_allowed_group_path')
@@ -47,8 +45,6 @@ describe API::Settings, 'Settings' do
default_projects_limit: 3,
password_authentication_enabled_for_web: false,
repository_storages: ['custom'],
- koding_enabled: true,
- koding_url: 'http://koding.example.com',
plantuml_enabled: true,
plantuml_url: 'http://plantuml.example.com',
default_snippet_visibility: 'internal',
@@ -62,18 +58,16 @@ describe API::Settings, 'Settings' do
dsa_key_restriction: 2048,
ecdsa_key_restriction: 384,
ed25519_key_restriction: 256,
- circuitbreaker_check_interval: 2,
enforce_terms: true,
terms: 'Hello world!',
performance_bar_allowed_group_path: group.full_path,
- instance_statistics_visibility_private: true
+ instance_statistics_visibility_private: true,
+ diff_max_patch_bytes: 150_000
expect(response).to have_gitlab_http_status(200)
expect(json_response['default_projects_limit']).to eq(3)
expect(json_response['password_authentication_enabled_for_web']).to be_falsey
expect(json_response['repository_storages']).to eq(['custom'])
- expect(json_response['koding_enabled']).to be_truthy
- expect(json_response['koding_url']).to eq('http://koding.example.com')
expect(json_response['plantuml_enabled']).to be_truthy
expect(json_response['plantuml_url']).to eq('http://plantuml.example.com')
expect(json_response['default_snippet_visibility']).to eq('internal')
@@ -87,11 +81,11 @@ describe API::Settings, 'Settings' do
expect(json_response['dsa_key_restriction']).to eq(2048)
expect(json_response['ecdsa_key_restriction']).to eq(384)
expect(json_response['ed25519_key_restriction']).to eq(256)
- expect(json_response['circuitbreaker_check_interval']).to eq(2)
expect(json_response['enforce_terms']).to be(true)
expect(json_response['terms']).to eq('Hello world!')
expect(json_response['performance_bar_allowed_group_id']).to eq(group.id)
expect(json_response['instance_statistics_visibility_private']).to be(true)
+ expect(json_response['diff_max_patch_bytes']).to eq(150_000)
end
end
@@ -112,15 +106,6 @@ describe API::Settings, 'Settings' do
expect(json_response['performance_bar_allowed_group_id']).to be_nil
end
- context "missing koding_url value when koding_enabled is true" do
- it "returns a blank parameter error message" do
- put api("/application/settings", admin), koding_enabled: true
-
- expect(response).to have_gitlab_http_status(400)
- expect(json_response['error']).to eq('koding_url is missing')
- end
- end
-
context "missing plantuml_url value when plantuml_enabled is true" do
it "returns a blank parameter error message" do
put api("/application/settings", admin), plantuml_enabled: true
diff --git a/spec/requests/api/snippets_spec.rb b/spec/requests/api/snippets_spec.rb
index 6da769cb3ed..c546ba3e127 100644
--- a/spec/requests/api/snippets_spec.rb
+++ b/spec/requests/api/snippets_spec.rb
@@ -94,6 +94,12 @@ describe API::Snippets do
expect(response.body).to eq(snippet.content)
end
+ it 'forces attachment content disposition' do
+ get api("/snippets/#{snippet.id}/raw", user)
+
+ expect(headers['Content-Disposition']).to match(/^attachment/)
+ end
+
it 'returns 404 for invalid snippet id' do
get api("/snippets/1234/raw", user)
diff --git a/spec/requests/api/submodules_spec.rb b/spec/requests/api/submodules_spec.rb
new file mode 100644
index 00000000000..fa447c028c2
--- /dev/null
+++ b/spec/requests/api/submodules_spec.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe API::Submodules do
+ let(:user) { create(:user) }
+ let!(:project) { create(:project, :repository, namespace: user.namespace ) }
+ let(:guest) { create(:user) { |u| project.add_guest(u) } }
+ let(:submodule) { 'six' }
+ let(:commit_sha) { 'e25eda1fece24ac7a03624ed1320f82396f35bd8' }
+ let(:branch) { 'master' }
+ let(:commit_message) { 'whatever' }
+
+ let(:params) do
+ {
+ submodule: submodule,
+ commit_sha: commit_sha,
+ branch: branch,
+ commit_message: commit_message
+ }
+ end
+
+ before do
+ project.add_developer(user)
+ end
+
+ def route(submodule = nil)
+ "/projects/#{project.id}/repository/submodules/#{submodule}"
+ end
+
+ describe "PUT /projects/:id/repository/submodule/:submodule" do
+ context 'when unauthenticated' do
+ it 'returns 401' do
+ put api(route(submodule)), params
+
+ expect(response).to have_gitlab_http_status(401)
+ end
+ end
+
+ context 'when authenticated', 'as a guest' do
+ it 'returns 403' do
+ put api(route(submodule), guest), params
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+ end
+
+ context 'when authenticated', 'as a developer' do
+ it 'returns 400 if params is missing' do
+ put api(route(submodule), user)
+
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'returns 400 if branch is missing' do
+ put api(route(submodule), user), params.except(:branch)
+
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'returns 400 if commit_sha is missing' do
+ put api(route(submodule), user), params.except(:commit_sha)
+
+ expect(response).to have_gitlab_http_status(400)
+ end
+
+ it 'returns the commmit' do
+ head_commit = project.repository.commit.id
+
+ put api(route(submodule), user), params
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['message']).to eq commit_message
+ expect(json_response['author_name']).to eq user.name
+ expect(json_response['committer_name']).to eq user.name
+ expect(json_response['parent_ids'].first).to eq head_commit
+ end
+
+ context 'when the submodule name is urlencoded' do
+ let(:submodule) { 'test_inside_folder/another_folder/six' }
+ let(:branch) { 'submodule_inside_folder' }
+ let(:encoded_submodule) { CGI.escape(submodule) }
+
+ it 'returns the commmit' do
+ expect(Submodules::UpdateService)
+ .to receive(:new)
+ .with(any_args, hash_including(submodule: submodule))
+ .and_call_original
+
+ put api(route(encoded_submodule), user), params
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response['id']).to eq project.repository.commit(branch).id
+ expect(project.repository.blob_at(branch, submodule).id).to eq commit_sha
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index b7d62df0663..bb913ae0e79 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -51,6 +51,15 @@ describe API::Users do
expect(json_response[0]['username']).to eq(user.username)
end
+ it "returns the user when a valid `username` parameter is passed (case insensitive)" do
+ get api("/users"), username: user.username.upcase
+
+ expect(response).to match_response_schema('public_api/v4/user/basics')
+ expect(json_response.size).to eq(1)
+ expect(json_response[0]['id']).to eq(user.id)
+ expect(json_response[0]['username']).to eq(user.username)
+ end
+
it "returns an empty response when an invalid `username` parameter is passed" do
get api("/users"), username: 'invalid'
@@ -132,6 +141,14 @@ describe API::Users do
expect(json_response.first['username']).to eq(omniauth_user.username)
end
+ it "returns one user (case insensitive)" do
+ get api("/users?username=#{omniauth_user.username.upcase}", user)
+
+ expect(response).to match_response_schema('public_api/v4/user/basics')
+ expect(response).to include_pagination_headers
+ expect(json_response.first['username']).to eq(omniauth_user.username)
+ end
+
it "returns a 403 when non-admin user searches by external UID" do
get api("/users?extern_uid=#{omniauth_user.identities.first.extern_uid}&provider=#{omniauth_user.identities.first.provider}", user)
@@ -343,6 +360,12 @@ describe API::Users do
let(:path) { "/users/#{user.username}/status" }
end
end
+
+ context 'when finding the user by username (case insensitive)' do
+ it_behaves_like 'rendering user status' do
+ let(:path) { "/users/#{user.username.upcase}/status" }
+ end
+ end
end
describe "POST /users" do
@@ -528,6 +551,18 @@ describe API::Users do
expect(json_response['message']).to eq('Username has already been taken')
end
+ it 'returns 409 conflict error if same username exists (case insensitive)' do
+ expect do
+ post api('/users', admin),
+ name: 'foo',
+ email: 'foo@example.com',
+ password: 'password',
+ username: 'TEST'
+ end.to change { User.count }.by(0)
+ expect(response).to have_gitlab_http_status(409)
+ expect(json_response['message']).to eq('Username has already been taken')
+ end
+
it 'creates user with new identity' do
post api("/users", admin), attributes_for(:user, provider: 'github', extern_uid: '67890')
@@ -749,6 +784,14 @@ describe API::Users do
expect(response).to have_gitlab_http_status(409)
expect(@user.reload.username).to eq(@user.username)
end
+
+ it 'returns 409 conflict error if username taken (case insensitive)' do
+ @user_id = User.all.last.id
+ put api("/users/#{@user.id}", admin), username: 'TEST'
+
+ expect(response).to have_gitlab_http_status(409)
+ expect(@user.reload.username).to eq(@user.username)
+ end
end
end
@@ -785,35 +828,25 @@ describe API::Users do
end
describe 'GET /user/:id/keys' do
- before do
- admin
- end
+ it 'returns 404 for non-existing user' do
+ user_id = not_existing_user_id
- context 'when unauthenticated' do
- it 'returns authentication error' do
- get api("/users/#{user.id}/keys")
- expect(response).to have_gitlab_http_status(401)
- end
- end
+ get api("/users/#{user_id}/keys")
- context 'when authenticated' do
- it 'returns 404 for non-existing user' do
- get api('/users/999999/keys', admin)
- expect(response).to have_gitlab_http_status(404)
- expect(json_response['message']).to eq('404 User Not Found')
- end
+ expect(response).to have_gitlab_http_status(404)
+ expect(json_response['message']).to eq('404 User Not Found')
+ end
- it 'returns array of ssh keys' do
- user.keys << key
- user.save
+ it 'returns array of ssh keys' do
+ user.keys << key
+ user.save
- get api("/users/#{user.id}/keys", admin)
+ get api("/users/#{user.id}/keys")
- expect(response).to have_gitlab_http_status(200)
- expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.first['title']).to eq(key.title)
- end
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.first['title']).to eq(key.title)
end
end
@@ -1985,11 +2018,11 @@ describe API::Users do
expect(json_response['message']).to eq('403 Forbidden')
end
- it 'returns a personal access token' do
+ it 'returns an impersonation token' do
get api("/users/#{user.id}/impersonation_tokens/#{impersonation_token.id}", admin)
expect(response).to have_gitlab_http_status(200)
- expect(json_response['token']).to be_present
+ expect(json_response['token']).not_to be_present
expect(json_response['impersonation']).to be_truthy
end
end
diff --git a/spec/requests/api/wikis_spec.rb b/spec/requests/api/wikis_spec.rb
index c40d01e1a14..08bada44178 100644
--- a/spec/requests/api/wikis_spec.rb
+++ b/spec/requests/api/wikis_spec.rb
@@ -158,6 +158,16 @@ describe API::Wikis do
expect(json_response.size).to eq(1)
expect(json_response['error']).to eq('file is missing')
end
+
+ it 'responds with validation error on invalid temp file' do
+ payload[:file] = { tempfile: '/etc/hosts' }
+
+ post(api(url, user), payload)
+
+ expect(response).to have_gitlab_http_status(400)
+ expect(json_response.size).to eq(1)
+ expect(json_response['error']).to eq('file is invalid')
+ end
end
describe 'GET /projects/:id/wikis' do
diff --git a/spec/requests/git_http_spec.rb b/spec/requests/git_http_spec.rb
index c71eae9164a..0dc459d9b5a 100644
--- a/spec/requests/git_http_spec.rb
+++ b/spec/requests/git_http_spec.rb
@@ -302,7 +302,7 @@ describe 'Git HTTP requests' do
it 'rejects pushes with 403 Forbidden' do
upload(path, env) do |response|
expect(response).to have_gitlab_http_status(:forbidden)
- expect(response.body).to eq(change_access_error(:push_code))
+ expect(response.body).to eq('You are not allowed to push code to this project.')
end
end
diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb
index 5abc6d81958..5c3b37ef11c 100644
--- a/spec/routing/project_routing_spec.rb
+++ b/spec/routing/project_routing_spec.rb
@@ -36,36 +36,33 @@ describe 'project routing' do
shared_examples 'RESTful project resources' do
let(:actions) { [:index, :create, :new, :edit, :show, :update, :destroy] }
let(:controller_path) { controller }
- let(:id) { { id: '1' } }
- let(:format) { {} } # response format, e.g. { format: :html }
- let(:params) { { namespace_id: 'gitlab', project_id: 'gitlabhq' } }
it 'to #index' do
- expect(get("/gitlab/gitlabhq/#{controller_path}")).to route_to("projects/#{controller}#index", params) if actions.include?(:index)
+ expect(get("/gitlab/gitlabhq/#{controller_path}")).to route_to("projects/#{controller}#index", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:index)
end
it 'to #create' do
- expect(post("/gitlab/gitlabhq/#{controller_path}")).to route_to("projects/#{controller}#create", params) if actions.include?(:create)
+ expect(post("/gitlab/gitlabhq/#{controller_path}")).to route_to("projects/#{controller}#create", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:create)
end
it 'to #new' do
- expect(get("/gitlab/gitlabhq/#{controller_path}/new")).to route_to("projects/#{controller}#new", params) if actions.include?(:new)
+ expect(get("/gitlab/gitlabhq/#{controller_path}/new")).to route_to("projects/#{controller}#new", namespace_id: 'gitlab', project_id: 'gitlabhq') if actions.include?(:new)
end
it 'to #edit' do
- expect(get("/gitlab/gitlabhq/#{controller_path}/1/edit")).to route_to("projects/#{controller}#edit", params.merge(**id, **format)) if actions.include?(:edit)
+ expect(get("/gitlab/gitlabhq/#{controller_path}/1/edit")).to route_to("projects/#{controller}#edit", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:edit)
end
it 'to #show' do
- expect(get("/gitlab/gitlabhq/#{controller_path}/1")).to route_to("projects/#{controller}#show", params.merge(**id, **format)) if actions.include?(:show)
+ expect(get("/gitlab/gitlabhq/#{controller_path}/1")).to route_to("projects/#{controller}#show", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:show)
end
it 'to #update' do
- expect(put("/gitlab/gitlabhq/#{controller_path}/1")).to route_to("projects/#{controller}#update", params.merge(id)) if actions.include?(:update)
+ expect(put("/gitlab/gitlabhq/#{controller_path}/1")).to route_to("projects/#{controller}#update", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:update)
end
it 'to #destroy' do
- expect(delete("/gitlab/gitlabhq/#{controller_path}/1")).to route_to("projects/#{controller}#destroy", params.merge(**id, **format)) if actions.include?(:destroy)
+ expect(delete("/gitlab/gitlabhq/#{controller_path}/1")).to route_to("projects/#{controller}#destroy", namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1') if actions.include?(:destroy)
end
end
@@ -133,8 +130,9 @@ describe 'project routing' do
# labels_namespace_project_autocomplete_sources_path GET /:project_id/autocomplete_sources/labels(.:format) projects/autocomplete_sources#labels
# milestones_namespace_project_autocomplete_sources_path GET /:project_id/autocomplete_sources/milestones(.:format) projects/autocomplete_sources#milestones
# commands_namespace_project_autocomplete_sources_path GET /:project_id/autocomplete_sources/commands(.:format) projects/autocomplete_sources#commands
+ # snippets_namespace_project_autocomplete_sources_path GET /:project_id/autocomplete_sources/snippets(.:format) projects/autocomplete_sources#snippets
describe Projects::AutocompleteSourcesController, 'routing' do
- [:members, :issues, :merge_requests, :labels, :milestones, :commands].each do |action|
+ [:members, :issues, :merge_requests, :labels, :milestones, :commands, :snippets].each do |action|
it "to ##{action}" do
expect(get("/gitlab/gitlabhq/autocomplete_sources/#{action}")).to route_to("projects/autocomplete_sources##{action}", namespace_id: 'gitlab', project_id: 'gitlabhq')
end
@@ -153,13 +151,12 @@ describe 'project routing' do
end
it 'to #history' do
- expect(get('/gitlab/gitlabhq/wikis/1/history')).to route_to('projects/wikis#history', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1', format: :html)
+ expect(get('/gitlab/gitlabhq/wikis/1/history')).to route_to('projects/wikis#history', namespace_id: 'gitlab', project_id: 'gitlabhq', id: '1')
end
it_behaves_like 'RESTful project resources' do
let(:actions) { [:create, :edit, :show, :destroy] }
let(:controller) { 'wikis' }
- let(:format) { { format: :html } }
end
end
@@ -258,10 +255,10 @@ describe 'project routing' do
end
it 'to #logs_tree' do
- expect(get('/gitlab/gitlabhq/refs/stable/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable')
- expect(get('/gitlab/gitlabhq/refs/feature%2345/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45')
- expect(get('/gitlab/gitlabhq/refs/feature%2B45/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45')
- expect(get('/gitlab/gitlabhq/refs/feature@45/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45')
+ expect(get('/gitlab/gitlabhq/refs/stable/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable')
+ expect(get('/gitlab/gitlabhq/refs/feature%2345/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45')
+ expect(get('/gitlab/gitlabhq/refs/feature%2B45/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45')
+ expect(get('/gitlab/gitlabhq/refs/feature@45/logs_tree')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature@45')
expect(get('/gitlab/gitlabhq/refs/stable/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz')
expect(get('/gitlab/gitlabhq/refs/feature%2345/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature#45', path: 'foo/bar/baz')
expect(get('/gitlab/gitlabhq/refs/feature%2B45/logs_tree/foo/bar/baz')).to route_to('projects/refs#logs_tree', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'feature+45', path: 'foo/bar/baz')
diff --git a/spec/routing/routing_spec.rb b/spec/routing/routing_spec.rb
index dd8f6239587..a170bb14144 100644
--- a/spec/routing/routing_spec.rb
+++ b/spec/routing/routing_spec.rb
@@ -140,13 +140,6 @@ describe HelpController, "routing" do
end
end
-# koding GET /koding(.:format) koding#index
-describe KodingController, "routing" do
- it "to #index" do
- expect(get("/koding")).to route_to('koding#index')
- end
-end
-
# profile_account GET /profile/account(.:format) profile#account
# profile_history GET /profile/history(.:format) profile#history
# profile_password PUT /profile/password(.:format) profile#password_update
diff --git a/spec/rubocop/cop/group_public_or_visible_to_user_spec.rb b/spec/rubocop/cop/group_public_or_visible_to_user_spec.rb
new file mode 100644
index 00000000000..7b5235a3da7
--- /dev/null
+++ b/spec/rubocop/cop/group_public_or_visible_to_user_spec.rb
@@ -0,0 +1,28 @@
+require 'spec_helper'
+require 'rubocop'
+require 'rubocop/rspec/support'
+require_relative '../../../rubocop/cop/group_public_or_visible_to_user'
+
+describe RuboCop::Cop::GroupPublicOrVisibleToUser do
+ include CopHelper
+
+ subject(:cop) { described_class.new }
+
+ it 'flags the use of Group.public_or_visible_to_user with a constant receiver' do
+ inspect_source('Group.public_or_visible_to_user')
+
+ expect(cop.offenses.size).to eq(1)
+ end
+
+ it 'does not flat the use of public_or_visible_to_user with a constant that is not Group' do
+ inspect_source('Project.public_or_visible_to_user')
+
+ expect(cop.offenses.size).to eq(0)
+ end
+
+ it 'does not flag the use of Group.public_or_visible_to_user with a send receiver' do
+ inspect_source('foo.public_or_visible_to_user')
+
+ expect(cop.offenses.size).to eq(0)
+ end
+end
diff --git a/spec/rubocop/cop/migration/add_reference_spec.rb b/spec/rubocop/cop/migration/add_reference_spec.rb
index 8f795bb561e..c348fc0efac 100644
--- a/spec/rubocop/cop/migration/add_reference_spec.rb
+++ b/spec/rubocop/cop/migration/add_reference_spec.rb
@@ -29,7 +29,7 @@ describe RuboCop::Cop::Migration::AddReference do
expect_offense(<<~RUBY)
call do
add_reference(:projects, :users)
- ^^^^^^^^^^^^^ `add_reference` requires `index: true`
+ ^^^^^^^^^^^^^ `add_reference` requires `index: true` or `index: { options... }`
end
RUBY
end
@@ -38,7 +38,7 @@ describe RuboCop::Cop::Migration::AddReference do
expect_offense(<<~RUBY)
def up
add_reference(:projects, :users, index: false)
- ^^^^^^^^^^^^^ `add_reference` requires `index: true`
+ ^^^^^^^^^^^^^ `add_reference` requires `index: true` or `index: { options... }`
end
RUBY
end
@@ -50,5 +50,13 @@ describe RuboCop::Cop::Migration::AddReference do
end
RUBY
end
+
+ it 'does not register an offense when the index is unique' do
+ expect_no_offenses(<<~RUBY)
+ def up
+ add_reference(:projects, :users, index: { unique: true } )
+ end
+ RUBY
+ end
end
end
diff --git a/spec/rubocop/cop/qa/element_with_pattern_spec.rb b/spec/rubocop/cop/qa/element_with_pattern_spec.rb
new file mode 100644
index 00000000000..c5beb40f9fd
--- /dev/null
+++ b/spec/rubocop/cop/qa/element_with_pattern_spec.rb
@@ -0,0 +1,50 @@
+require 'spec_helper'
+
+require 'rubocop'
+require 'rubocop/rspec/support'
+
+require_relative '../../../../rubocop/cop/qa/element_with_pattern'
+
+describe RuboCop::Cop::QA::ElementWithPattern do
+ include CopHelper
+
+ let(:source_file) { 'qa/page.rb' }
+
+ subject(:cop) { described_class.new }
+
+ context 'in a QA file' do
+ before do
+ allow(cop).to receive(:in_qa_file?).and_return(true)
+ end
+
+ it "registers an offense for elements with a pattern" do
+ expect_offense(<<-RUBY)
+ view 'app/views/shared/groups/_search_form.html.haml' do
+ element :groups_filter, 'search_field_tag :filter'
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't use a pattern for element, create a corresponding `qa-groups-filter` instead.
+ element :groups_filter_placeholder, /Search by name/
+ ^^^^^^^^^^^^^^^^ Don't use a pattern for element, create a corresponding `qa-groups-filter-placeholder` instead.
+ end
+ RUBY
+ end
+
+ it "does not register an offense for element without a pattern" do
+ expect_no_offenses(<<-RUBY)
+ view 'app/views/shared/groups/_search_form.html.haml' do
+ element :groups_filter
+ element :groups_filter_placeholder
+ end
+ RUBY
+ end
+ end
+
+ context 'outside of a migration spec file' do
+ it "does not register an offense" do
+ expect_no_offenses(<<-RUBY)
+ describe 'foo' do
+ let(:user) { create(:user) }
+ end
+ RUBY
+ end
+ end
+end
diff --git a/spec/rubocop/cop/safe_params_spec.rb b/spec/rubocop/cop/safe_params_spec.rb
new file mode 100644
index 00000000000..4f02b8e9008
--- /dev/null
+++ b/spec/rubocop/cop/safe_params_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'rubocop'
+require 'rubocop/rspec/support'
+require_relative '../../../rubocop/cop/safe_params'
+
+describe RuboCop::Cop::SafeParams do
+ include CopHelper
+
+ subject(:cop) { described_class.new }
+
+ it 'flags the params as an argument of url_for' do
+ expect_offense(<<~SOURCE)
+ url_for(params)
+ ^^^^^^^^^^^^^^^ Use `safe_params` instead of `params` in url_for.
+ SOURCE
+ end
+
+ it 'flags the merged params as an argument of url_for' do
+ expect_offense(<<~SOURCE)
+ url_for(params.merge(additional_params))
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `safe_params` instead of `params` in url_for.
+ SOURCE
+ end
+
+ it 'flags the merged params arg as an argument of url_for' do
+ expect_offense(<<~SOURCE)
+ url_for(something.merge(additional).merge(params))
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `safe_params` instead of `params` in url_for.
+ SOURCE
+ end
+
+ it 'does not flag other argument of url_for' do
+ expect_no_offenses(<<~SOURCE)
+ url_for(something)
+ SOURCE
+ end
+end
diff --git a/spec/rubocop/qa_helpers_spec.rb b/spec/rubocop/qa_helpers_spec.rb
new file mode 100644
index 00000000000..26e4c1ca6f0
--- /dev/null
+++ b/spec/rubocop/qa_helpers_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'rubocop'
+require_relative '../../rubocop/qa_helpers'
+
+describe RuboCop::QAHelpers do
+ def parse_source(source, path = 'foo.rb')
+ buffer = Parser::Source::Buffer.new(path)
+ buffer.source = source
+
+ builder = RuboCop::AST::Builder.new
+ parser = Parser::CurrentRuby.new(builder)
+
+ parser.parse(buffer)
+ end
+
+ let(:cop) do
+ Class.new do
+ include RuboCop::QAHelpers
+ end.new
+ end
+
+ describe '#in_qa_file?' do
+ it 'returns true for a node in the qa/ directory' do
+ node = parse_source('10', Rails.root.join('qa', 'qa', 'page', 'dashboard', 'groups.rb'))
+
+ expect(cop.in_qa_file?(node)).to eq(true)
+ end
+
+ it 'returns false for a node outside the qa/ directory' do
+ node = parse_source('10', Rails.root.join('app', 'foo', 'foo.rb'))
+
+ expect(cop.in_qa_file?(node)).to eq(false)
+ end
+ end
+end
diff --git a/spec/serializers/build_action_entity_spec.rb b/spec/serializers/build_action_entity_spec.rb
index 15720d86583..ea88951ebc6 100644
--- a/spec/serializers/build_action_entity_spec.rb
+++ b/spec/serializers/build_action_entity_spec.rb
@@ -22,5 +22,21 @@ describe BuildActionEntity do
it 'contains whether it is playable' do
expect(subject[:playable]).to eq job.playable?
end
+
+ context 'when job is scheduled' do
+ let(:job) { create(:ci_build, :scheduled) }
+
+ it 'returns scheduled' do
+ expect(subject[:scheduled]).to be_truthy
+ end
+
+ it 'returns scheduled_at' do
+ expect(subject[:scheduled_at]).to eq(job.scheduled_at)
+ end
+
+ it 'returns unschedule path' do
+ expect(subject[:unschedule_path]).to include "jobs/#{job.id}/unschedule"
+ end
+ end
end
end
diff --git a/spec/serializers/commit_entity_spec.rb b/spec/serializers/commit_entity_spec.rb
index 04247c78549..b9995818e98 100644
--- a/spec/serializers/commit_entity_spec.rb
+++ b/spec/serializers/commit_entity_spec.rb
@@ -1,10 +1,11 @@
require 'spec_helper'
describe CommitEntity do
+ SIGNATURE_HTML = 'TEST'.freeze
+
let(:entity) do
described_class.new(commit, request: request)
end
-
let(:request) { double('request') }
let(:project) { create(:project, :repository) }
let(:commit) { project.commit }
@@ -12,7 +13,11 @@ describe CommitEntity do
subject { entity.as_json }
before do
+ render = double('render')
+ allow(render).to receive(:call).and_return(SIGNATURE_HTML)
+
allow(request).to receive(:project).and_return(project)
+ allow(request).to receive(:render).and_return(render)
end
context 'when commit author is a user' do
@@ -51,4 +56,56 @@ describe CommitEntity do
it 'exposes gravatar url that belongs to author' do
expect(subject.fetch(:author_gravatar_url)).to match /gravatar/
end
+
+ context 'when type is not set' do
+ it 'does not expose extra properties' do
+ expect(subject).not_to include(:description_html)
+ expect(subject).not_to include(:title_html)
+ end
+ end
+
+ context 'when type is "full"' do
+ let(:entity) do
+ described_class.new(commit, request: request, type: :full, pipeline_ref: project.default_branch, pipeline_project: project)
+ end
+
+ it 'exposes extra properties' do
+ expect(subject).to include(:description_html)
+ expect(subject).to include(:title_html)
+ expect(subject.fetch(:description_html)).not_to be_nil
+ expect(subject.fetch(:title_html)).not_to be_nil
+ end
+
+ context 'when commit has signature' do
+ let(:commit) { project.commit(TestEnv::BRANCH_SHA['signed-commits']) }
+
+ it 'exposes "signature_html"' do
+ expect(request.render).to receive(:call)
+ expect(subject.fetch(:signature_html)).to be SIGNATURE_HTML
+ end
+ end
+
+ context 'when commit has pipeline' do
+ before do
+ create(:ci_pipeline, project: project, sha: commit.id)
+ end
+
+ it 'exposes "pipeline_status_path"' do
+ expect(subject.fetch(:pipeline_status_path)).not_to be_nil
+ end
+ end
+ end
+
+ context 'when commit_url_params is set' do
+ let(:entity) do
+ params = { merge_request_iid: 3 }
+
+ described_class.new(commit, request: request, commit_url_params: params)
+ end
+
+ it 'adds commit_url_params to url and path' do
+ expect(subject[:commit_path]).to include "?merge_request_iid=3"
+ expect(subject[:commit_url]).to include "?merge_request_iid=3"
+ end
+ end
end
diff --git a/spec/serializers/deployment_entity_spec.rb b/spec/serializers/deployment_entity_spec.rb
index 522c92ce295..8793a762f9d 100644
--- a/spec/serializers/deployment_entity_spec.rb
+++ b/spec/serializers/deployment_entity_spec.rb
@@ -22,4 +22,26 @@ describe DeploymentEntity do
it 'exposes creation date' do
expect(subject).to include(:created_at)
end
+
+ describe 'scheduled_actions' do
+ let(:project) { create(:project, :repository) }
+ let(:pipeline) { create(:ci_pipeline, project: project, user: user) }
+ let(:build) { create(:ci_build, :success, pipeline: pipeline) }
+ let(:deployment) { create(:deployment, deployable: build) }
+
+ context 'when the same pipeline has a scheduled action' do
+ let(:other_build) { create(:ci_build, :schedulable, :success, pipeline: pipeline, name: 'other build') }
+ let!(:other_deployment) { create(:deployment, deployable: other_build) }
+
+ it 'returns other scheduled actions' do
+ expect(subject[:scheduled_actions][0][:name]).to eq 'other build'
+ end
+ end
+
+ context 'when the same pipeline does not have a scheduled action' do
+ it 'does not return other actions' do
+ expect(subject[:scheduled_actions]).to be_empty
+ end
+ end
+ end
end
diff --git a/spec/serializers/deployment_serializer_spec.rb b/spec/serializers/deployment_serializer_spec.rb
new file mode 100644
index 00000000000..4834f5ede3c
--- /dev/null
+++ b/spec/serializers/deployment_serializer_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe DeploymentSerializer do
+ set(:project) { create(:project, :repository) }
+ set(:user) { create(:user, email: project.commit.author_email) }
+
+ let(:resource) { create(:deployment, project: project, sha: project.commit.id) }
+ let(:serializer) { described_class.new(request) }
+
+ shared_examples 'json schema' do
+ let(:json_entity) { subject.as_json }
+
+ it 'matches deployment entity schema' do
+ expect(json_entity).to match_schema('deployment')
+ end
+ end
+
+ describe '#represent' do
+ subject { serializer.represent(resource) }
+
+ let(:request) { { project: project, current_user: user } }
+
+ it_behaves_like 'json schema'
+ end
+
+ describe '#represent_concise' do
+ subject { serializer.represent_concise(resource) }
+
+ let(:request) { { project: project } }
+
+ it_behaves_like 'json schema'
+ end
+end
diff --git a/spec/serializers/diff_file_entity_spec.rb b/spec/serializers/diff_file_entity_spec.rb
index 3d90ce44dfb..7497b8f27bd 100644
--- a/spec/serializers/diff_file_entity_spec.rb
+++ b/spec/serializers/diff_file_entity_spec.rb
@@ -26,6 +26,11 @@ describe DiffFileEntity do
)
end
+ it 'includes viewer' do
+ expect(subject[:viewer].with_indifferent_access)
+ .to match_schema('entities/diff_viewer')
+ end
+
# Converted diff files from GitHub import does not contain blob file
# and content sha.
context 'when diff file does not have a blob and content sha' do
diff --git a/spec/serializers/diff_line_entity_spec.rb b/spec/serializers/diff_line_entity_spec.rb
new file mode 100644
index 00000000000..2549f64bcd3
--- /dev/null
+++ b/spec/serializers/diff_line_entity_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe DiffLineEntity do
+ include RepoHelpers
+
+ let(:code) { 'hello world' }
+ let(:line) { Gitlab::Diff::Line.new(code, 'new', 1, nil, 1) }
+ let(:entity) { described_class.new(line, request: {}) }
+
+ subject { entity.as_json }
+
+ it 'exposes correct attributes' do
+ expect(subject).to include(
+ :line_code, :type, :old_line, :new_line, :text, :meta_data, :rich_text
+ )
+ end
+
+ describe '#rich_text' do
+ let(:code) { '<h2 onmouseover="alert(2)">Test</h2>' }
+ let(:rich_text_value) { nil }
+
+ before do
+ line.instance_variable_set(:@rich_text, rich_text_value)
+ end
+
+ shared_examples 'escapes html tags' do
+ it do
+ expect(subject[:rich_text]).to eq html_escape(code)
+ expect(subject[:rich_text]).to be_html_safe
+ end
+ end
+
+ context 'when rich_line is present' do
+ let(:rich_text_value) { code }
+
+ it_behaves_like 'escapes html tags'
+ end
+
+ context 'when rich_line is not present' do
+ it_behaves_like 'escapes html tags'
+ end
+ end
+end
diff --git a/spec/serializers/diff_viewer_entity_spec.rb b/spec/serializers/diff_viewer_entity_spec.rb
new file mode 100644
index 00000000000..66ac6ef2adc
--- /dev/null
+++ b/spec/serializers/diff_viewer_entity_spec.rb
@@ -0,0 +1,19 @@
+require 'spec_helper'
+
+describe DiffViewerEntity do
+ include RepoHelpers
+
+ let(:project) { create(:project, :repository) }
+ let(:repository) { project.repository }
+ let(:commit) { project.commit(sample_commit.id) }
+ let(:diff_refs) { commit.diff_refs }
+ let(:diff) { commit.raw_diffs.first }
+ let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: diff_refs, repository: repository) }
+ let(:viewer) { diff_file.simple_viewer }
+
+ subject { described_class.new(viewer).as_json }
+
+ it 'serializes diff file viewer' do
+ expect(subject.with_indifferent_access).to match_schema('entities/diff_viewer')
+ end
+end
diff --git a/spec/serializers/discussion_entity_spec.rb b/spec/serializers/discussion_entity_spec.rb
index 378540a35b6..0590304e832 100644
--- a/spec/serializers/discussion_entity_spec.rb
+++ b/spec/serializers/discussion_entity_spec.rb
@@ -36,6 +36,13 @@ describe DiscussionEntity do
)
end
+ it 'resolved_by matches note_user_entity schema' do
+ Notes::ResolveService.new(note.project, user).execute(note)
+
+ expect(subject[:resolved_by].with_indifferent_access)
+ .to match_schema('entities/note_user_entity')
+ end
+
context 'when is LegacyDiffDiscussion' do
let(:project) { create(:project) }
let(:merge_request) { create(:merge_request, source_project: project) }
diff --git a/spec/serializers/environment_serializer_spec.rb b/spec/serializers/environment_serializer_spec.rb
index 0f0ab5ac796..87493a28d1f 100644
--- a/spec/serializers/environment_serializer_spec.rb
+++ b/spec/serializers/environment_serializer_spec.rb
@@ -14,7 +14,8 @@ describe EnvironmentSerializer do
let(:project) { create(:project, :repository) }
let(:deployable) { create(:ci_build) }
let(:deployment) do
- create(:deployment, deployable: deployable,
+ create(:deployment, :success,
+ deployable: deployable,
user: user,
project: project,
sha: project.commit.id)
diff --git a/spec/serializers/environment_status_entity_spec.rb b/spec/serializers/environment_status_entity_spec.rb
new file mode 100644
index 00000000000..8a6a38fe5f8
--- /dev/null
+++ b/spec/serializers/environment_status_entity_spec.rb
@@ -0,0 +1,79 @@
+require 'spec_helper'
+
+describe EnvironmentStatusEntity do
+ let(:user) { create(:user) }
+ let(:request) { double('request') }
+
+ let(:deployment) { create(:deployment, :succeed, :review_app) }
+ let(:environment) { deployment.environment }
+ let(:project) { deployment.project }
+ let(:merge_request) { create(:merge_request, :deployed_review_app, deployment: deployment) }
+
+ let(:environment_status) { EnvironmentStatus.new(environment, merge_request, merge_request.diff_head_sha) }
+ let(:entity) { described_class.new(environment_status, request: request) }
+
+ subject { entity.as_json }
+
+ before do
+ deployment.update(sha: merge_request.diff_head_sha)
+ allow(request).to receive(:current_user).and_return(user)
+ end
+
+ it { is_expected.to include(:id) }
+ it { is_expected.to include(:name) }
+ it { is_expected.to include(:url) }
+ it { is_expected.to include(:external_url) }
+ it { is_expected.to include(:external_url_formatted) }
+ it { is_expected.to include(:deployed_at) }
+ it { is_expected.to include(:deployed_at_formatted) }
+ it { is_expected.to include(:changes) }
+ it { is_expected.to include(:status) }
+
+ it { is_expected.not_to include(:stop_url) }
+ it { is_expected.not_to include(:metrics_url) }
+ it { is_expected.not_to include(:metrics_monitoring_url) }
+
+ context 'when the user is project maintainer' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it { is_expected.to include(:stop_url) }
+ end
+
+ context 'when deployment has metrics' do
+ let(:prometheus_adapter) { double('prometheus_adapter', can_query?: true) }
+
+ let(:simple_metrics) do
+ {
+ success: true,
+ metrics: {},
+ last_update: 42
+ }
+ end
+
+ before do
+ project.add_maintainer(user)
+ allow(deployment).to receive(:prometheus_adapter).and_return(prometheus_adapter)
+ allow(prometheus_adapter).to receive(:query).with(:deployment, deployment).and_return(simple_metrics)
+ allow(entity).to receive(:deployment).and_return(deployment)
+ end
+
+ context 'when deployment succeeded' do
+ let(:deployment) { create(:deployment, :succeed, :review_app) }
+
+ it 'returns metrics url' do
+ expect(subject[:metrics_url])
+ .to eq("/#{project.namespace.name}/#{project.name}/environments/#{environment.id}/deployments/#{deployment.iid}/metrics")
+ end
+ end
+
+ context 'when deployment is running' do
+ let(:deployment) { create(:deployment, :running, :review_app) }
+
+ it 'does not return metrics url' do
+ expect(subject[:metrics_url]).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/serializers/job_entity_spec.rb b/spec/serializers/job_entity_spec.rb
index 8e1ca3f308d..851b41a7f7e 100644
--- a/spec/serializers/job_entity_spec.rb
+++ b/spec/serializers/job_entity_spec.rb
@@ -109,6 +109,19 @@ describe JobEntity do
end
end
+ context 'when job is scheduled' do
+ let(:job) { create(:ci_build, :scheduled) }
+
+ it 'contains path to unschedule action' do
+ expect(subject).to include(:unschedule_path)
+ end
+
+ it 'contains scheduled_at' do
+ expect(subject[:scheduled]).to be_truthy
+ expect(subject[:scheduled_at]).to eq(job.scheduled_at)
+ end
+ end
+
context 'when job is generic commit status' do
let(:job) { create(:generic_commit_status, target_url: 'http://google.com') }
diff --git a/spec/serializers/merge_request_widget_entity_spec.rb b/spec/serializers/merge_request_widget_entity_spec.rb
index 0ba2539a717..561421d5ac8 100644
--- a/spec/serializers/merge_request_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_widget_entity_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe MergeRequestWidgetEntity do
+ include ProjectForksHelper
+
let(:project) { create :project, :repository }
let(:resource) { create(:merge_request, source_project: project, target_project: project) }
let(:user) { create(:user) }
@@ -50,6 +52,40 @@ describe MergeRequestWidgetEntity do
end
end
+ describe 'merge_pipeline' do
+ it 'returns nil' do
+ expect(subject[:merge_pipeline]).to be_nil
+ end
+
+ context 'when is merged' do
+ let(:resource) { create(:merged_merge_request, source_project: project, merge_commit_sha: project.commit.id) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project, ref: resource.target_branch, sha: resource.merge_commit_sha) }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'returns merge_pipeline' do
+ pipeline.reload
+ pipeline_payload = PipelineDetailsEntity
+ .represent(pipeline, request: request)
+ .as_json
+
+ expect(subject[:merge_pipeline]).to eq(pipeline_payload)
+ end
+
+ context 'when user cannot read pipelines on target project' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'returns nil' do
+ expect(subject[:merge_pipeline]).to be_nil
+ end
+ end
+ end
+ end
+
describe 'metrics' do
context 'when metrics record exists with merged data' do
before do
@@ -206,12 +242,12 @@ describe MergeRequestWidgetEntity do
describe 'when source project is deleted' do
let(:project) { create(:project, :repository) }
- let(:fork_project) { create(:project, :repository, forked_from_project: project) }
- let(:merge_request) { create(:merge_request, source_project: fork_project, target_project: project) }
+ let(:forked_project) { fork_project(project) }
+ let(:merge_request) { create(:merge_request, source_project: forked_project, target_project: project) }
it 'returns a blank rebase_path' do
allow(merge_request).to receive(:should_be_rebased?).and_return(true)
- fork_project.destroy
+ forked_project.destroy
merge_request.reload
entity = described_class.new(merge_request, request: request).as_json
diff --git a/spec/serializers/pipeline_details_entity_spec.rb b/spec/serializers/pipeline_details_entity_spec.rb
index 45e18086894..8e73a3e67c6 100644
--- a/spec/serializers/pipeline_details_entity_spec.rb
+++ b/spec/serializers/pipeline_details_entity_spec.rb
@@ -29,7 +29,7 @@ describe PipelineDetailsEntity do
expect(subject[:details])
.to include :duration, :finished_at
expect(subject[:details])
- .to include :stages, :artifacts, :manual_actions
+ .to include :stages, :artifacts, :manual_actions, :scheduled_actions
expect(subject[:details][:status]).to include :icon, :favicon, :text, :label
end
diff --git a/spec/serializers/project_mirror_entity_spec.rb b/spec/serializers/project_mirror_entity_spec.rb
new file mode 100644
index 00000000000..ad0a8bbdff0
--- /dev/null
+++ b/spec/serializers/project_mirror_entity_spec.rb
@@ -0,0 +1,12 @@
+require 'spec_helper'
+
+describe ProjectMirrorEntity do
+ let(:project) { create(:project, :repository, :remote_mirror) }
+ let(:entity) { described_class.new(project) }
+
+ subject { entity.as_json }
+
+ it 'exposes project-specific elements' do
+ is_expected.to include(:id, :remote_mirrors_attributes)
+ end
+end
diff --git a/spec/serializers/remote_mirror_entity_spec.rb b/spec/serializers/remote_mirror_entity_spec.rb
new file mode 100644
index 00000000000..885b0b9b423
--- /dev/null
+++ b/spec/serializers/remote_mirror_entity_spec.rb
@@ -0,0 +1,16 @@
+require 'spec_helper'
+
+describe RemoteMirrorEntity do
+ let(:project) { create(:project, :repository, :remote_mirror) }
+ let(:remote_mirror) { project.remote_mirrors.first }
+ let(:entity) { described_class.new(remote_mirror) }
+
+ subject { entity.as_json }
+
+ it 'exposes remote-mirror-specific elements' do
+ is_expected.to include(
+ :id, :url, :enabled, :auth_method,
+ :ssh_known_hosts, :ssh_public_key, :ssh_known_hosts_fingerprints
+ )
+ end
+end
diff --git a/spec/services/application_settings/update_service_spec.rb b/spec/services/application_settings/update_service_spec.rb
index 6337ee7d724..daf5dfba6b1 100644
--- a/spec/services/application_settings/update_service_spec.rb
+++ b/spec/services/application_settings/update_service_spec.rb
@@ -10,6 +10,9 @@ describe ApplicationSettings::UpdateService do
before do
# So the caching behaves like it would in production
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
+
+ # Creating these settings first ensures they're used by other factories
+ application_settings
end
describe 'updating terms' do
diff --git a/spec/services/applications/create_service_spec.rb b/spec/services/applications/create_service_spec.rb
index 9c43b56744b..c8134087fa1 100644
--- a/spec/services/applications/create_service_spec.rb
+++ b/spec/services/applications/create_service_spec.rb
@@ -1,17 +1,14 @@
+# frozen_string_literal: true
+
require "spec_helper"
describe ::Applications::CreateService do
+ include TestRequestHelpers
+
let(:user) { create(:user) }
let(:params) { attributes_for(:application) }
- let(:request) do
- if Gitlab.rails5?
- ActionController::TestRequest.new({ remote_ip: "127.0.0.1" }, ActionController::TestSession.new)
- else
- ActionController::TestRequest.new(remote_ip: "127.0.0.1")
- end
- end
subject { described_class.new(user, params) }
- it { expect { subject.execute(request) }.to change { Doorkeeper::Application.count }.by(1) }
+ it { expect { subject.execute(test_request) }.to change { Doorkeeper::Application.count }.by(1) }
end
diff --git a/spec/services/audit_event_service_spec.rb b/spec/services/audit_event_service_spec.rb
new file mode 100644
index 00000000000..32fd98e6ef9
--- /dev/null
+++ b/spec/services/audit_event_service_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe AuditEventService do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:project_member) { create(:project_member, user: user) }
+ let(:service) { described_class.new(user, project, { action: :destroy }) }
+ let(:logger) { instance_double(Gitlab::AuditJsonLogger) }
+
+ describe '#security_event' do
+ before do
+ expect(service).to receive(:file_logger).and_return(logger)
+ end
+
+ it 'creates an event and logs to a file' do
+ expect(logger).to receive(:info).with(author_id: user.id,
+ entity_id: project.id,
+ entity_type: "Project",
+ action: :destroy)
+
+ expect { service.security_event }.to change(SecurityEvent, :count).by(1)
+ end
+ end
+end
diff --git a/spec/services/boards/visits/create_service_spec.rb b/spec/services/boards/visits/create_service_spec.rb
new file mode 100644
index 00000000000..6baf7ac9deb
--- /dev/null
+++ b/spec/services/boards/visits/create_service_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Boards::Visits::CreateService do
+ describe '#execute' do
+ let(:user) { create(:user) }
+
+ context 'when a project board' do
+ let(:project) { create(:project) }
+ let(:project_board) { create(:board, project: project) }
+
+ subject(:service) { described_class.new(project_board.parent, user) }
+
+ it 'returns nil when there is no user' do
+ service.current_user = nil
+
+ expect(service.execute(project_board)).to eq nil
+ end
+
+ it 'returns nil when database is read only' do
+ allow(Gitlab::Database).to receive(:read_only?) { true }
+
+ expect(service.execute(project_board)).to eq nil
+ end
+
+ it 'records the visit' do
+ expect(BoardProjectRecentVisit).to receive(:visited!).once
+
+ service.execute(project_board)
+ end
+ end
+
+ context 'when a group board' do
+ let(:group) { create(:group) }
+ let(:group_board) { create(:board, group: group) }
+
+ subject(:service) { described_class.new(group_board.parent, user) }
+
+ it 'returns nil when there is no user' do
+ service.current_user = nil
+
+ expect(service.execute(group_board)).to eq nil
+ end
+
+ it 'records the visit' do
+ expect(BoardGroupRecentVisit).to receive(:visited!).once
+
+ service.execute(group_board)
+ end
+ end
+ end
+end
diff --git a/spec/services/boards/visits/latest_service_spec.rb b/spec/services/boards/visits/latest_service_spec.rb
new file mode 100644
index 00000000000..e55d599e2cc
--- /dev/null
+++ b/spec/services/boards/visits/latest_service_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Boards::Visits::LatestService do
+ describe '#execute' do
+ let(:user) { create(:user) }
+
+ context 'when a project board' do
+ let(:project) { create(:project) }
+ let(:project_board) { create(:board, project: project) }
+
+ subject(:service) { described_class.new(project_board.parent, user) }
+
+ it 'returns nil when there is no user' do
+ service.current_user = nil
+
+ expect(service.execute).to eq nil
+ end
+
+ it 'queries for most recent visit' do
+ expect(BoardProjectRecentVisit).to receive(:latest).once
+
+ service.execute
+ end
+ end
+
+ context 'when a group board' do
+ let(:group) { create(:group) }
+ let(:group_board) { create(:board, group: group) }
+
+ subject(:service) { described_class.new(group_board.parent, user) }
+
+ it 'returns nil when there is no user' do
+ service.current_user = nil
+
+ expect(service.execute).to eq nil
+ end
+
+ it 'queries for most recent visit' do
+ expect(BoardGroupRecentVisit).to receive(:latest).once
+
+ service.execute
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/archive_trace_service_spec.rb b/spec/services/ci/archive_trace_service_spec.rb
new file mode 100644
index 00000000000..8e9cb65f3bc
--- /dev/null
+++ b/spec/services/ci/archive_trace_service_spec.rb
@@ -0,0 +1,51 @@
+require 'spec_helper'
+
+describe Ci::ArchiveTraceService, '#execute' do
+ subject { described_class.new.execute(job) }
+
+ context 'when job is finished' do
+ let(:job) { create(:ci_build, :success, :trace_live) }
+
+ it 'creates an archived trace' do
+ expect { subject }.not_to raise_error
+
+ expect(job.reload.job_artifacts_trace).to be_exist
+ end
+
+ context 'when trace is already archived' do
+ let!(:job) { create(:ci_build, :success, :trace_artifact) }
+
+ it 'ignores an exception' do
+ expect { subject }.not_to raise_error
+ end
+
+ it 'does not create an archived trace' do
+ expect { subject }.not_to change { Ci::JobArtifact.trace.count }
+ end
+ end
+ end
+
+ context 'when job is running' do
+ let(:job) { create(:ci_build, :running, :trace_live) }
+
+ it 'increments Prometheus counter, sends crash report to Sentry and ignore an error for continuing to archive' do
+ expect(Gitlab::Sentry)
+ .to receive(:track_exception)
+ .with(::Gitlab::Ci::Trace::ArchiveError,
+ issue_url: 'https://gitlab.com/gitlab-org/gitlab-ce/issues/51502',
+ extra: { job_id: job.id } ).once
+
+ expect(Rails.logger)
+ .to receive(:error)
+ .with("Failed to archive trace. id: #{job.id} message: Job is not finished yet")
+ .and_call_original
+
+ expect(Gitlab::Metrics)
+ .to receive(:counter)
+ .with(:job_trace_archive_failed_total, "Counter of failed attempts of trace archiving")
+ .and_call_original
+
+ expect { subject }.not_to raise_error
+ end
+ end
+end
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index 054b7b1561c..a4582d1bc64 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -387,15 +387,24 @@ describe Ci::CreatePipelineService do
context 'with environment' do
before do
- config = YAML.dump(deploy: { environment: { name: "review/$CI_COMMIT_REF_NAME" }, script: 'ls' })
+ config = YAML.dump(
+ deploy: {
+ environment: { name: "review/$CI_COMMIT_REF_NAME" },
+ script: 'ls',
+ tags: ['hello']
+ })
+
stub_ci_pipeline_yaml_file(config)
end
- it 'creates the environment' do
+ it 'creates the environment with tags' do
result = execute_service
expect(result).to be_persisted
expect(Environment.find_by(name: "review/master")).to be_present
+ expect(result.builds.first.tag_list).to contain_exactly('hello')
+ expect(result.builds.first.deployment).to be_persisted
+ expect(result.builds.first.deployment.deployable).to be_a(Ci::Build)
end
end
@@ -435,16 +444,34 @@ describe Ci::CreatePipelineService do
end
context 'when builds with auto-retries are configured' do
- before do
- config = YAML.dump(rspec: { script: 'rspec', retry: 2 })
- stub_ci_pipeline_yaml_file(config)
+ context 'as an integer' do
+ before do
+ config = YAML.dump(rspec: { script: 'rspec', retry: 2 })
+ stub_ci_pipeline_yaml_file(config)
+ end
+
+ it 'correctly creates builds with auto-retry value configured' do
+ pipeline = execute_service
+
+ expect(pipeline).to be_persisted
+ expect(pipeline.builds.find_by(name: 'rspec').retries_max).to eq 2
+ expect(pipeline.builds.find_by(name: 'rspec').retry_when).to eq ['always']
+ end
end
- it 'correctly creates builds with auto-retry value configured' do
- pipeline = execute_service
+ context 'as hash' do
+ before do
+ config = YAML.dump(rspec: { script: 'rspec', retry: { max: 2, when: 'runner_system_failure' } })
+ stub_ci_pipeline_yaml_file(config)
+ end
+
+ it 'correctly creates builds with auto-retry value configured' do
+ pipeline = execute_service
- expect(pipeline).to be_persisted
- expect(pipeline.builds.find_by(name: 'rspec').retries_max).to eq 2
+ expect(pipeline).to be_persisted
+ expect(pipeline.builds.find_by(name: 'rspec').retries_max).to eq 2
+ expect(pipeline.builds.find_by(name: 'rspec').retry_when).to eq ['runner_system_failure']
+ end
end
end
@@ -581,5 +608,86 @@ describe Ci::CreatePipelineService do
.to eq variables_attributes.map(&:with_indifferent_access)
end
end
+
+ context 'when pipeline has a job with environment' do
+ let(:pipeline) { execute_service }
+
+ before do
+ stub_ci_pipeline_yaml_file(YAML.dump(config))
+ end
+
+ context 'when environment name is valid' do
+ let(:config) do
+ {
+ review_app: {
+ script: 'deploy',
+ environment: {
+ name: 'review/${CI_COMMIT_REF_NAME}',
+ url: 'http://${CI_COMMIT_REF_SLUG}-staging.example.com'
+ }
+ }
+ }
+ end
+
+ it 'has a job with environment' do
+ expect(pipeline.builds.count).to eq(1)
+ expect(pipeline.builds.first.persisted_environment.name).to eq('review/master')
+ expect(pipeline.builds.first.deployment).to be_created
+ end
+ end
+
+ context 'when environment name is invalid' do
+ let(:config) do
+ {
+ 'job:deploy-to-test-site': {
+ script: 'deploy',
+ environment: {
+ name: '${CI_JOB_NAME}',
+ url: 'https://$APP_URL'
+ }
+ }
+ }
+ end
+
+ it 'has a job without environment' do
+ expect(pipeline.builds.count).to eq(1)
+ expect(pipeline.builds.first.persisted_environment).to be_nil
+ expect(pipeline.builds.first.deployment).to be_nil
+ end
+ end
+ end
+ end
+
+ describe '#execute!' do
+ subject { service.execute!(*args) }
+
+ let(:service) { described_class.new(project, user, ref: ref_name) }
+ let(:args) { [:push] }
+
+ context 'when user has a permission to create a pipeline' do
+ let(:user) { create(:user) }
+
+ before do
+ project.add_developer(user)
+ end
+
+ it 'does not raise an error' do
+ expect { subject }.not_to raise_error
+ end
+
+ it 'creates a pipeline' do
+ expect { subject }.to change { Ci::Pipeline.count }.by(1)
+ end
+ end
+
+ context 'when user does not have a permission to create a pipeline' do
+ let(:user) { create(:user) }
+
+ it 'raises an error' do
+ expect { subject }
+ .to raise_error(described_class::CreateError)
+ .with_message('Insufficient permissions to create a new pipeline')
+ end
+ end
end
end
diff --git a/spec/services/ci/destroy_pipeline_service_spec.rb b/spec/services/ci/destroy_pipeline_service_spec.rb
new file mode 100644
index 00000000000..097daf67feb
--- /dev/null
+++ b/spec/services/ci/destroy_pipeline_service_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ::Ci::DestroyPipelineService do
+ let(:project) { create(:project) }
+ let!(:pipeline) { create(:ci_pipeline, project: project) }
+
+ subject { described_class.new(project, user).execute(pipeline) }
+
+ context 'user is owner' do
+ let(:user) { project.owner }
+
+ it 'destroys the pipeline' do
+ subject
+
+ expect { pipeline.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+
+ it 'logs an audit event' do
+ expect { subject }.to change { SecurityEvent.count }.by(1)
+ end
+
+ context 'when the pipeline has jobs' do
+ let!(:build) { create(:ci_build, project: project, pipeline: pipeline) }
+
+ it 'destroys associated jobs' do
+ subject
+
+ expect { build.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+
+ it 'destroys associated stages' do
+ stages = pipeline.stages
+
+ subject
+
+ expect(stages).to all(raise_error(ActiveRecord::RecordNotFound))
+ end
+
+ context 'when job has artifacts' do
+ let!(:artifact) { create(:ci_job_artifact, :archive, job: build) }
+
+ it 'destroys associated artifacts' do
+ subject
+
+ expect { artifact.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ end
+ end
+ end
+ end
+
+ context 'user is not owner' do
+ let(:user) { create(:user) }
+
+ it 'raises an exception' do
+ expect { subject }.to raise_error(Gitlab::Access::AccessDeniedError)
+ end
+ end
+end
diff --git a/spec/services/ci/enqueue_build_service_spec.rb b/spec/services/ci/enqueue_build_service_spec.rb
deleted file mode 100644
index e41b8e4800b..00000000000
--- a/spec/services/ci/enqueue_build_service_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-require 'spec_helper'
-
-describe Ci::EnqueueBuildService, '#execute' do
- let(:user) { create(:user) }
- let(:project) { create(:project) }
- let(:ci_build) { create(:ci_build, :created) }
-
- subject { described_class.new(project, user).execute(ci_build) }
-
- it 'enqueues the build' do
- subject
-
- expect(ci_build.pending?).to be_truthy
- end
-end
diff --git a/spec/services/ci/process_build_service_spec.rb b/spec/services/ci/process_build_service_spec.rb
new file mode 100644
index 00000000000..704685417bb
--- /dev/null
+++ b/spec/services/ci/process_build_service_spec.rb
@@ -0,0 +1,117 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Ci::ProcessBuildService, '#execute' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+
+ subject { described_class.new(project, user).execute(build, current_status) }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ context 'when build has on_success option' do
+ let(:build) { create(:ci_build, :created, when: :on_success, user: user, project: project) }
+
+ context 'when current status is success' do
+ let(:current_status) { 'success' }
+
+ it 'changes the build status' do
+ expect { subject }.to change { build.status }.to('pending')
+ end
+ end
+
+ context 'when current status is failed' do
+ let(:current_status) { 'failed' }
+
+ it 'does not change the build status' do
+ expect { subject }.to change { build.status }.to('skipped')
+ end
+ end
+ end
+
+ context 'when build has on_failure option' do
+ let(:build) { create(:ci_build, :created, when: :on_failure, user: user, project: project) }
+
+ context 'when current status is success' do
+ let(:current_status) { 'success' }
+
+ it 'changes the build status' do
+ expect { subject }.to change { build.status }.to('skipped')
+ end
+ end
+
+ context 'when current status is failed' do
+ let(:current_status) { 'failed' }
+
+ it 'does not change the build status' do
+ expect { subject }.to change { build.status }.to('pending')
+ end
+ end
+ end
+
+ context 'when build has always option' do
+ let(:build) { create(:ci_build, :created, when: :always, user: user, project: project) }
+
+ context 'when current status is success' do
+ let(:current_status) { 'success' }
+
+ it 'changes the build status' do
+ expect { subject }.to change { build.status }.to('pending')
+ end
+ end
+
+ context 'when current status is failed' do
+ let(:current_status) { 'failed' }
+
+ it 'does not change the build status' do
+ expect { subject }.to change { build.status }.to('pending')
+ end
+ end
+ end
+
+ context 'when build has manual option' do
+ let(:build) { create(:ci_build, :created, :actionable, user: user, project: project) }
+
+ context 'when current status is success' do
+ let(:current_status) { 'success' }
+
+ it 'changes the build status' do
+ expect { subject }.to change { build.status }.to('manual')
+ end
+ end
+
+ context 'when current status is failed' do
+ let(:current_status) { 'failed' }
+
+ it 'does not change the build status' do
+ expect { subject }.to change { build.status }.to('skipped')
+ end
+ end
+ end
+
+ context 'when build has delayed option' do
+ before do
+ allow(Ci::BuildScheduleWorker).to receive(:perform_at) { }
+ end
+
+ let(:build) { create(:ci_build, :created, :schedulable, user: user, project: project) }
+
+ context 'when current status is success' do
+ let(:current_status) { 'success' }
+
+ it 'changes the build status' do
+ expect { subject }.to change { build.status }.to('scheduled')
+ end
+ end
+
+ context 'when current status is failed' do
+ let(:current_status) { 'failed' }
+
+ it 'does not change the build status' do
+ expect { subject }.to change { build.status }.to('skipped')
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/process_pipeline_service_spec.rb b/spec/services/ci/process_pipeline_service_spec.rb
index feb5120bc68..538992b621e 100644
--- a/spec/services/ci/process_pipeline_service_spec.rb
+++ b/spec/services/ci/process_pipeline_service_spec.rb
@@ -31,17 +31,14 @@ describe Ci::ProcessPipelineService, '#execute' do
succeed_pending
expect(builds.success.count).to eq(2)
- expect(process_pipeline).to be_truthy
succeed_pending
expect(builds.success.count).to eq(4)
- expect(process_pipeline).to be_truthy
succeed_pending
expect(builds.success.count).to eq(5)
- expect(process_pipeline).to be_falsey
end
it 'does not process pipeline if existing stage is running' do
@@ -242,6 +239,187 @@ describe Ci::ProcessPipelineService, '#execute' do
end
end
+ context 'when delayed jobs are defined' do
+ context 'when the scene is timed incremental rollout' do
+ before do
+ create_build('build', stage_idx: 0)
+ create_build('rollout10%', **delayed_options, stage_idx: 1)
+ create_build('rollout100%', **delayed_options, stage_idx: 2)
+ create_build('cleanup', stage_idx: 3)
+
+ allow(Ci::BuildScheduleWorker).to receive(:perform_at)
+ end
+
+ context 'when builds are successful' do
+ it 'properly processes the pipeline' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names_and_statuses).to eq({ 'build': 'pending' })
+
+ succeed_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'scheduled' })
+
+ enqueue_scheduled('rollout10%')
+ succeed_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'success', 'rollout100%': 'scheduled' })
+
+ enqueue_scheduled('rollout100%')
+ succeed_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'success', 'rollout100%': 'success', 'cleanup': 'pending' })
+
+ succeed_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'success', 'rollout100%': 'success', 'cleanup': 'success' })
+ expect(pipeline.reload.status).to eq 'success'
+ end
+ end
+
+ context 'when build job fails' do
+ it 'properly processes the pipeline' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names_and_statuses).to eq({ 'build': 'pending' })
+
+ fail_running_or_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'failed' })
+ expect(pipeline.reload.status).to eq 'failed'
+ end
+ end
+
+ context 'when rollout 10% is unscheduled' do
+ it 'properly processes the pipeline' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names_and_statuses).to eq({ 'build': 'pending' })
+
+ succeed_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'scheduled' })
+
+ unschedule
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'manual' })
+ expect(pipeline.reload.status).to eq 'manual'
+ end
+
+ context 'when user plays rollout 10%' do
+ it 'schedules rollout100%' do
+ process_pipeline
+ succeed_pending
+ unschedule
+ play_manual_action('rollout10%')
+ succeed_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'success', 'rollout100%': 'scheduled' })
+ expect(pipeline.reload.status).to eq 'scheduled'
+ end
+ end
+ end
+
+ context 'when rollout 10% fails' do
+ it 'properly processes the pipeline' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names_and_statuses).to eq({ 'build': 'pending' })
+
+ succeed_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'scheduled' })
+
+ enqueue_scheduled('rollout10%')
+ fail_running_or_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'failed' })
+ expect(pipeline.reload.status).to eq 'failed'
+ end
+
+ context 'when user retries rollout 10%' do
+ it 'does not schedule rollout10% again' do
+ process_pipeline
+ succeed_pending
+ enqueue_scheduled('rollout10%')
+ fail_running_or_pending
+ retry_build('rollout10%')
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'pending' })
+ expect(pipeline.reload.status).to eq 'running'
+ end
+ end
+ end
+
+ context 'when rollout 10% is played immidiately' do
+ it 'properly processes the pipeline' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names_and_statuses).to eq({ 'build': 'pending' })
+
+ succeed_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'scheduled' })
+
+ play_manual_action('rollout10%')
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'pending' })
+ expect(pipeline.reload.status).to eq 'running'
+ end
+ end
+ end
+
+ context 'when only one scheduled job exists in a pipeline' do
+ before do
+ create_build('delayed', **delayed_options, stage_idx: 0)
+
+ allow(Ci::BuildScheduleWorker).to receive(:perform_at)
+ end
+
+ it 'properly processes the pipeline' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names_and_statuses).to eq({ 'delayed': 'scheduled' })
+
+ expect(pipeline.reload.status).to eq 'scheduled'
+ end
+ end
+
+ context 'when there are two delayed jobs in a stage' do
+ before do
+ create_build('delayed1', **delayed_options, stage_idx: 0)
+ create_build('delayed2', **delayed_options, stage_idx: 0)
+ create_build('job', stage_idx: 1)
+
+ allow(Ci::BuildScheduleWorker).to receive(:perform_at)
+ end
+
+ it 'blocks the stage until all scheduled jobs finished' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names_and_statuses).to eq({ 'delayed1': 'scheduled', 'delayed2': 'scheduled' })
+
+ enqueue_scheduled('delayed1')
+
+ expect(builds_names_and_statuses).to eq({ 'delayed1': 'pending', 'delayed2': 'scheduled' })
+ expect(pipeline.reload.status).to eq 'running'
+ end
+ end
+
+ context 'when a delayed job is allowed to fail' do
+ before do
+ create_build('delayed', **delayed_options, allow_failure: true, stage_idx: 0)
+ create_build('job', stage_idx: 1)
+
+ allow(Ci::BuildScheduleWorker).to receive(:perform_at)
+ end
+
+ it 'blocks the stage and continues after it failed' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names_and_statuses).to eq({ 'delayed': 'scheduled' })
+
+ enqueue_scheduled('delayed')
+ fail_running_or_pending
+
+ expect(builds_names_and_statuses).to eq({ 'delayed': 'failed', 'job': 'pending' })
+ expect(pipeline.reload.status).to eq 'pending'
+ end
+ end
+ end
+
context 'when there are manual action in earlier stages' do
context 'when first stage has only optional manual actions' do
before do
@@ -493,9 +671,9 @@ describe Ci::ProcessPipelineService, '#execute' do
context 'when builds with auto-retries are configured' do
before do
- create_build('build:1', stage_idx: 0, user: user, options: { retry: 2 })
+ create_build('build:1', stage_idx: 0, user: user, options: { retry: { max: 2 } })
create_build('test:1', stage_idx: 1, user: user, when: :on_failure)
- create_build('test:2', stage_idx: 1, user: user, options: { retry: 1 })
+ create_build('test:2', stage_idx: 1, user: user, options: { retry: { max: 1 } })
end
it 'automatically retries builds in a valid order' do
@@ -536,6 +714,13 @@ describe Ci::ProcessPipelineService, '#execute' do
builds.pluck(:name)
end
+ def builds_names_and_statuses
+ builds.each_with_object({}) do |b, h|
+ h[b.name.to_sym] = b.status
+ h
+ end
+ end
+
def all_builds_names
all_builds.pluck(:name)
end
@@ -549,7 +734,7 @@ describe Ci::ProcessPipelineService, '#execute' do
end
def succeed_pending
- builds.pending.update_all(status: 'success')
+ builds.pending.map(&:success)
end
def succeed_running_or_pending
@@ -568,6 +753,14 @@ describe Ci::ProcessPipelineService, '#execute' do
builds.find_by(name: name).play(user)
end
+ def enqueue_scheduled(name)
+ builds.scheduled.find_by(name: name).enqueue
+ end
+
+ def retry_build(name)
+ Ci::Build.retry(builds.find_by(name: name), user)
+ end
+
def manual_actions
pipeline.manual_actions(true)
end
@@ -575,4 +768,12 @@ describe Ci::ProcessPipelineService, '#execute' do
def create_build(name, **opts)
create(:ci_build, :created, pipeline: pipeline, name: name, **opts)
end
+
+ def delayed_options
+ { when: 'delayed', options: { start_in: '1 minute' } }
+ end
+
+ def unschedule
+ pipeline.builds.scheduled.map(&:unschedule)
+ end
end
diff --git a/spec/services/ci/register_job_service_spec.rb b/spec/services/ci/register_job_service_spec.rb
index a6565709641..56e2a405bcd 100644
--- a/spec/services/ci/register_job_service_spec.rb
+++ b/spec/services/ci/register_job_service_spec.rb
@@ -478,6 +478,20 @@ module Ci
it_behaves_like 'validation is not active'
end
end
+
+ context 'when build is degenerated' do
+ let!(:pending_job) { create(:ci_build, :pending, :degenerated, pipeline: pipeline) }
+
+ subject { execute(specific_runner, {}) }
+
+ it 'does not pick the build and drops the build' do
+ expect(subject).to be_nil
+
+ pending_job.reload
+ expect(pending_job).to be_failed
+ expect(pending_job).to be_archived_failure
+ end
+ end
end
describe '#register_success' do
diff --git a/spec/services/ci/retry_build_service_spec.rb b/spec/services/ci/retry_build_service_spec.rb
index 18d52082399..e779675744c 100644
--- a/spec/services/ci/retry_build_service_spec.rb
+++ b/spec/services/ci/retry_build_service_spec.rb
@@ -24,11 +24,15 @@ describe Ci::RetryBuildService do
artifacts_file artifacts_metadata artifacts_size created_at
updated_at started_at finished_at queued_at erased_by
erased_at auto_canceled_by job_artifacts job_artifacts_archive
- job_artifacts_metadata job_artifacts_trace job_artifacts_junit].freeze
+ job_artifacts_metadata job_artifacts_trace job_artifacts_junit
+ job_artifacts_sast job_artifacts_dependency_scanning
+ job_artifacts_container_scanning job_artifacts_dast
+ job_artifacts_license_management job_artifacts_performance
+ job_artifacts_codequality scheduled_at].freeze
IGNORE_ACCESSORS =
%i[type lock_version target_url base_tags trace_sections
- commit_id deployments erased_by_id last_deployment project_id
+ commit_id deployment erased_by_id project_id
runner_id tag_taggings taggings tags trigger_request_id
user_id auto_canceled_by_id retried failure_reason
artifacts_file_store artifacts_metadata_store
@@ -38,11 +42,11 @@ describe Ci::RetryBuildService do
let(:another_pipeline) { create(:ci_empty_pipeline, project: project) }
let(:build) do
- create(:ci_build, :failed, :artifacts, :test_reports, :expired, :erased,
- :queued, :coverage, :tags, :allowed_to_fail, :on_tag,
- :triggered, :trace_artifact, :teardown_environment,
+ create(:ci_build, :failed, :expired, :erased, :queued, :coverage, :tags,
+ :allowed_to_fail, :on_tag, :triggered, :teardown_environment,
description: 'my-job', stage: 'test', stage_id: stage.id,
- pipeline: pipeline, auto_canceled_by: another_pipeline)
+ pipeline: pipeline, auto_canceled_by: another_pipeline,
+ scheduled_at: 10.seconds.since)
end
before do
@@ -50,6 +54,15 @@ describe Ci::RetryBuildService do
# can reset one of the fields when assigning another. We plan to deprecate
# and remove legacy `stage` column in the future.
build.update(stage: 'test', stage_id: stage.id)
+
+ # Make sure we have one instance for every possible job_artifact_X
+ # associations to check they are correctly rejected on build duplication.
+ Ci::JobArtifact::TYPE_AND_FORMAT_PAIRS.each do |file_type, file_format|
+ create(:ci_job_artifact, file_format,
+ file_type: file_type, job: build, expire_at: build.artifacts_expire_at)
+ end
+
+ build.reload
end
describe 'clone accessors' do
diff --git a/spec/services/ci/run_scheduled_build_service_spec.rb b/spec/services/ci/run_scheduled_build_service_spec.rb
new file mode 100644
index 00000000000..be2aad33ef4
--- /dev/null
+++ b/spec/services/ci/run_scheduled_build_service_spec.rb
@@ -0,0 +1,62 @@
+require 'spec_helper'
+
+describe Ci::RunScheduledBuildService do
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+
+ subject { described_class.new(project, user).execute(build) }
+
+ context 'when user can update build' do
+ before do
+ project.add_developer(user)
+
+ create(:protected_branch, :developers_can_merge,
+ name: pipeline.ref, project: project)
+ end
+
+ context 'when build is scheduled' do
+ context 'when scheduled_at is expired' do
+ let(:build) { create(:ci_build, :expired_scheduled, user: user, project: project, pipeline: pipeline) }
+
+ it 'can run the build' do
+ expect { subject }.not_to raise_error
+
+ expect(build).to be_pending
+ end
+ end
+
+ context 'when scheduled_at is not expired' do
+ let(:build) { create(:ci_build, :scheduled, user: user, project: project, pipeline: pipeline) }
+
+ it 'can not run the build' do
+ expect { subject }.to raise_error(StateMachines::InvalidTransition)
+
+ expect(build).to be_scheduled
+ end
+ end
+ end
+
+ context 'when build is not scheduled' do
+ let(:build) { create(:ci_build, :created, user: user, project: project, pipeline: pipeline) }
+
+ it 'can not run the build' do
+ expect { subject }.to raise_error(StateMachines::InvalidTransition)
+
+ expect(build).to be_created
+ end
+ end
+ end
+
+ context 'when user can not update build' do
+ context 'when build is scheduled' do
+ let(:build) { create(:ci_build, :scheduled, user: user, project: project, pipeline: pipeline) }
+
+ it 'can not run the build' do
+ expect { subject }.to raise_error(Gitlab::Access::AccessDeniedError)
+
+ expect(build).to be_scheduled
+ end
+ end
+ end
+end
diff --git a/spec/services/clusters/applications/check_ingress_ip_address_service_spec.rb b/spec/services/clusters/applications/check_ingress_ip_address_service_spec.rb
index eb0bdb61ee3..f3036fbcb0e 100644
--- a/spec/services/clusters/applications/check_ingress_ip_address_service_spec.rb
+++ b/spec/services/clusters/applications/check_ingress_ip_address_service_spec.rb
@@ -28,41 +28,7 @@ describe Clusters::Applications::CheckIngressIpAddressService do
allow(application.cluster).to receive(:kubeclient).and_return(kubeclient)
end
- describe '#execute' do
- context 'when the ingress ip address is available' do
- it 'updates the external_ip for the app' do
- subject
+ include_examples 'check ingress ip executions', :clusters_applications_ingress
- expect(application.external_ip).to eq('111.222.111.222')
- end
- end
-
- context 'when the ingress ip address is not available' do
- let(:ingress) { nil }
-
- it 'does not error' do
- subject
- end
- end
-
- context 'when the exclusive lease cannot be obtained' do
- it 'does not call kubeclient' do
- stub_exclusive_lease_taken(lease_key, timeout: 15.seconds.to_i)
-
- subject
-
- expect(kubeclient).not_to have_received(:get_service)
- end
- end
-
- context 'when there is already an external_ip' do
- let(:application) { create(:clusters_applications_ingress, :installed, external_ip: '001.111.002.111') }
-
- it 'does not call kubeclient' do
- subject
-
- expect(kubeclient).not_to have_received(:get_service)
- end
- end
- end
+ include_examples 'check ingress ip executions', :clusters_applications_knative
end
diff --git a/spec/services/clusters/applications/check_installation_progress_service_spec.rb b/spec/services/clusters/applications/check_installation_progress_service_spec.rb
index 986f11410fd..45b8ce94815 100644
--- a/spec/services/clusters/applications/check_installation_progress_service_spec.rb
+++ b/spec/services/clusters/applications/check_installation_progress_service_spec.rb
@@ -8,17 +8,13 @@ describe Clusters::Applications::CheckInstallationProgressService do
let(:phase) { Gitlab::Kubernetes::Pod::UNKNOWN }
let(:errors) { nil }
- shared_examples 'a terminated installation' do
- it 'removes the installation POD' do
- expect(service).to receive(:remove_installation_pod).once
-
- service.execute
- end
- end
-
shared_examples 'a not yet terminated installation' do |a_phase|
let(:phase) { a_phase }
+ before do
+ expect(service).to receive(:installation_phase).once.and_return(phase)
+ end
+
context "when phase is #{a_phase}" do
context 'when not timeouted' do
it 'reschedule a new check' do
@@ -35,23 +31,19 @@ describe Clusters::Applications::CheckInstallationProgressService do
context 'when timeouted' do
let(:application) { create(:clusters_applications_helm, :timeouted) }
- it_behaves_like 'a terminated installation'
-
it 'make the application errored' do
expect(ClusterWaitForAppInstallationWorker).not_to receive(:perform_in)
service.execute
expect(application).to be_errored
- expect(application.status_reason).to match(/\btimed out\b/)
+ expect(application.status_reason).to eq("Installation timed out. Check pod logs for install-helm for more details.")
end
end
end
end
before do
- expect(service).to receive(:installation_phase).once.and_return(phase)
-
allow(service).to receive(:installation_errors).and_return(errors)
allow(service).to receive(:remove_installation_pod).and_return(nil)
end
@@ -60,7 +52,15 @@ describe Clusters::Applications::CheckInstallationProgressService do
context 'when installation POD succeeded' do
let(:phase) { Gitlab::Kubernetes::Pod::SUCCEEDED }
- it_behaves_like 'a terminated installation'
+ before do
+ expect(service).to receive(:installation_phase).once.and_return(phase)
+ end
+
+ it 'removes the installation POD' do
+ expect(service).to receive(:remove_installation_pod).once
+
+ service.execute
+ end
it 'make the application installed' do
expect(ClusterWaitForAppInstallationWorker).not_to receive(:perform_in)
@@ -76,16 +76,41 @@ describe Clusters::Applications::CheckInstallationProgressService do
let(:phase) { Gitlab::Kubernetes::Pod::FAILED }
let(:errors) { 'test installation failed' }
- it_behaves_like 'a terminated installation'
+ before do
+ expect(service).to receive(:installation_phase).once.and_return(phase)
+ end
it 'make the application errored' do
service.execute
expect(application).to be_errored
- expect(application.status_reason).to eq(errors)
+ expect(application.status_reason).to eq("Installation failed. Check pod logs for install-helm for more details.")
end
end
RESCHEDULE_PHASES.each { |phase| it_behaves_like 'a not yet terminated installation', phase }
+
+ context 'when installation raises a Kubeclient::HttpError' do
+ let(:cluster) { create(:cluster, :provided_by_user, :project) }
+
+ before do
+ application.update!(cluster: cluster)
+
+ expect(service).to receive(:installation_phase).and_raise(Kubeclient::HttpError.new(401, 'Unauthorized', nil))
+ end
+
+ it 'shows the response code from the error' do
+ service.execute
+
+ expect(application).to be_errored
+ expect(application.status_reason).to eq('Kubernetes error: 401')
+ end
+
+ it 'should log error' do
+ expect(service.send(:logger)).to receive(:error)
+
+ service.execute
+ end
+ end
end
end
diff --git a/spec/services/clusters/applications/create_service_spec.rb b/spec/services/clusters/applications/create_service_spec.rb
new file mode 100644
index 00000000000..0bd7719345e
--- /dev/null
+++ b/spec/services/clusters/applications/create_service_spec.rb
@@ -0,0 +1,130 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Clusters::Applications::CreateService do
+ include TestRequestHelpers
+
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:user) { create(:user) }
+ let(:params) { { application: 'helm' } }
+ let(:service) { described_class.new(cluster, user, params) }
+
+ describe '#execute' do
+ before do
+ allow(ClusterInstallAppWorker).to receive(:perform_async)
+ end
+
+ subject { service.execute(test_request) }
+
+ it 'creates an application' do
+ expect do
+ subject
+
+ cluster.reload
+ end.to change(cluster, :application_helm)
+ end
+
+ it 'schedules an install via worker' do
+ expect(ClusterInstallAppWorker).to receive(:perform_async).with('helm', anything).once
+
+ subject
+ end
+
+ context 'jupyter application' do
+ let(:params) do
+ {
+ application: 'jupyter',
+ hostname: 'example.com'
+ }
+ end
+
+ before do
+ allow_any_instance_of(Clusters::Applications::ScheduleInstallationService).to receive(:execute)
+ end
+
+ it 'creates the application' do
+ expect do
+ subject
+
+ cluster.reload
+ end.to change(cluster, :application_jupyter)
+ end
+
+ it 'sets the hostname' do
+ expect(subject.hostname).to eq('example.com')
+ end
+
+ it 'sets the oauth_application' do
+ expect(subject.oauth_application).to be_present
+ end
+ end
+
+ context 'knative application' do
+ let(:params) do
+ {
+ application: 'knative',
+ hostname: 'example.com'
+ }
+ end
+
+ before do
+ allow_any_instance_of(Clusters::Applications::ScheduleInstallationService).to receive(:execute)
+ end
+
+ it 'creates the application' do
+ expect do
+ subject
+
+ cluster.reload
+ end.to change(cluster, :application_knative)
+ end
+
+ it 'sets the hostname' do
+ expect(subject.hostname).to eq('example.com')
+ end
+ end
+
+ context 'invalid application' do
+ let(:params) { { application: 'non-existent' } }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Clusters::Applications::CreateService::InvalidApplicationError)
+ end
+ end
+
+ context 'group cluster' do
+ let(:cluster) { create(:cluster, :provided_by_gcp, :group) }
+
+ using RSpec::Parameterized::TableSyntax
+
+ before do
+ allow_any_instance_of(Clusters::Applications::ScheduleInstallationService).to receive(:execute)
+ end
+
+ where(:application, :association, :allowed) do
+ 'helm' | :application_helm | true
+ 'ingress' | :application_ingress | true
+ 'runner' | :application_runner | false
+ 'jupyter' | :application_jupyter | false
+ 'prometheus' | :application_prometheus | false
+ end
+
+ with_them do
+ let(:params) { { application: application } }
+
+ it 'executes for each application' do
+ if allowed
+ expect do
+ subject
+
+ cluster.reload
+ end.to change(cluster, association)
+ else
+ expect { subject }.to raise_error(Clusters::Applications::CreateService::InvalidApplicationError)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/clusters/applications/install_service_spec.rb b/spec/services/clusters/applications/install_service_spec.rb
index a744ec30b65..018d9822d3e 100644
--- a/spec/services/clusters/applications/install_service_spec.rb
+++ b/spec/services/clusters/applications/install_service_spec.rb
@@ -33,8 +33,9 @@ describe Clusters::Applications::InstallService do
end
context 'when k8s cluster communication fails' do
+ let(:error) { Kubeclient::HttpError.new(500, 'system failure', nil) }
+
before do
- error = Kubeclient::HttpError.new(500, 'system failure', nil)
expect(helm_client).to receive(:install).with(install_command).and_raise(error)
end
@@ -42,20 +43,83 @@ describe Clusters::Applications::InstallService do
service.execute
expect(application).to be_errored
- expect(application.status_reason).to match(/kubernetes error:/i)
+ expect(application.status_reason).to match('Kubernetes error: 500')
+ end
+
+ it 'logs errors' do
+ expect(service.send(:logger)).to receive(:error).with(
+ {
+ exception: 'Kubeclient::HttpError',
+ message: 'system failure',
+ service: 'Clusters::Applications::InstallService',
+ app_id: application.id,
+ project_ids: application.cluster.project_ids,
+ group_ids: [],
+ error_code: 500
+ }
+ )
+
+ expect(Gitlab::Sentry).to receive(:track_acceptable_exception).with(
+ error,
+ extra: {
+ exception: 'Kubeclient::HttpError',
+ message: 'system failure',
+ service: 'Clusters::Applications::InstallService',
+ app_id: application.id,
+ project_ids: application.cluster.project_ids,
+ group_ids: [],
+ error_code: 500
+ }
+ )
+
+ service.execute
end
end
- context 'when application cannot be persisted' do
+ context 'a non kubernetes error happens' do
let(:application) { create(:clusters_applications_helm, :scheduled) }
+ let(:error) { StandardError.new("something bad happened") }
+
+ before do
+ expect(application).to receive(:make_installing!).once.and_raise(error)
+ end
it 'make the application errored' do
- expect(application).to receive(:make_installing!).once.and_raise(ActiveRecord::RecordInvalid)
expect(helm_client).not_to receive(:install)
service.execute
expect(application).to be_errored
+ expect(application.status_reason).to eq("Can't start installation process.")
+ end
+
+ it 'logs errors' do
+ expect(service.send(:logger)).to receive(:error).with(
+ {
+ exception: 'StandardError',
+ error_code: nil,
+ message: 'something bad happened',
+ service: 'Clusters::Applications::InstallService',
+ app_id: application.id,
+ project_ids: application.cluster.projects.pluck(:id),
+ group_ids: []
+ }
+ )
+
+ expect(Gitlab::Sentry).to receive(:track_acceptable_exception).with(
+ error,
+ extra: {
+ exception: 'StandardError',
+ error_code: nil,
+ message: 'something bad happened',
+ service: 'Clusters::Applications::InstallService',
+ app_id: application.id,
+ project_ids: application.cluster.projects.pluck(:id),
+ group_ids: []
+ }
+ )
+
+ service.execute
end
end
end
diff --git a/spec/services/clusters/applications/schedule_installation_service_spec.rb b/spec/services/clusters/applications/schedule_installation_service_spec.rb
index bca1e71bef2..21797edd533 100644
--- a/spec/services/clusters/applications/schedule_installation_service_spec.rb
+++ b/spec/services/clusters/applications/schedule_installation_service_spec.rb
@@ -10,14 +10,13 @@ describe Clusters::Applications::ScheduleInstallationService do
expect(ClusterInstallAppWorker).not_to receive(:perform_async)
count_before = count_scheduled
- expect { service.execute(application) }.to raise_error(StandardError)
+ expect { service.execute }.to raise_error(StandardError)
expect(count_scheduled).to eq(count_before)
end
end
describe '#execute' do
- let(:project) { double(:project) }
- let(:service) { described_class.new(project, nil) }
+ let(:service) { described_class.new(application) }
context 'when application is installable' do
let(:application) { create(:clusters_applications_helm, :installable) }
@@ -25,7 +24,7 @@ describe Clusters::Applications::ScheduleInstallationService do
it 'make the application scheduled' do
expect(ClusterInstallAppWorker).to receive(:perform_async).with(application.name, kind_of(Numeric)).once
- expect { service.execute(application) }.to change { application.class.with_status(:scheduled).count }.by(1)
+ expect { service.execute }.to change { application.class.with_status(:scheduled).count }.by(1)
end
end
diff --git a/spec/services/clusters/create_service_spec.rb b/spec/services/clusters/create_service_spec.rb
index 1685dc748bd..274880f2c49 100644
--- a/spec/services/clusters/create_service_spec.rb
+++ b/spec/services/clusters/create_service_spec.rb
@@ -5,18 +5,43 @@ describe Clusters::CreateService do
let(:project) { create(:project) }
let(:user) { create(:user) }
- subject { described_class.new(project, user, params).execute(access_token) }
+ subject { described_class.new(user, params).execute(access_token: access_token) }
context 'when provider is gcp' do
context 'when project has no clusters' do
context 'when correct params' do
- include_context 'valid cluster create params'
+ let(:params) do
+ {
+ name: 'test-cluster',
+ provider_type: :gcp,
+ provider_gcp_attributes: {
+ gcp_project_id: 'gcp-project',
+ zone: 'us-central1-a',
+ num_nodes: 1,
+ machine_type: 'machine_type-a',
+ legacy_abac: 'true'
+ },
+ clusterable: project
+ }
+ end
include_examples 'create cluster service success'
end
context 'when invalid params' do
- include_context 'invalid cluster create params'
+ let(:params) do
+ {
+ name: 'test-cluster',
+ provider_type: :gcp,
+ provider_gcp_attributes: {
+ gcp_project_id: '!!!!!!!',
+ zone: 'us-central1-a',
+ num_nodes: 1,
+ machine_type: 'machine_type-a'
+ },
+ clusterable: project
+ }
+ end
include_examples 'create cluster service error'
end
diff --git a/spec/services/clusters/gcp/fetch_operation_service_spec.rb b/spec/services/clusters/gcp/fetch_operation_service_spec.rb
index e2fa93904c5..55f123ee786 100644
--- a/spec/services/clusters/gcp/fetch_operation_service_spec.rb
+++ b/spec/services/clusters/gcp/fetch_operation_service_spec.rb
@@ -24,7 +24,7 @@ describe Clusters::Gcp::FetchOperationService do
end
end
- context 'when suceeded to fetch operation' do
+ context 'when succeeded to fetch operation' do
before do
stub_cloud_platform_get_zone_operation(gcp_project_id, zone, operation_id)
end
diff --git a/spec/services/clusters/gcp/finalize_creation_service_spec.rb b/spec/services/clusters/gcp/finalize_creation_service_spec.rb
index 0f484222228..efee158739d 100644
--- a/spec/services/clusters/gcp/finalize_creation_service_spec.rb
+++ b/spec/services/clusters/gcp/finalize_creation_service_spec.rb
@@ -1,156 +1,176 @@
+# frozen_string_literal: true
+
require 'spec_helper'
-describe Clusters::Gcp::FinalizeCreationService do
+describe Clusters::Gcp::FinalizeCreationService, '#execute' do
include GoogleApi::CloudPlatformHelpers
include KubernetesHelpers
- describe '#execute' do
- let(:cluster) { create(:cluster, :project, :providing_by_gcp) }
- let(:provider) { cluster.provider }
- let(:platform) { cluster.platform }
- let(:gcp_project_id) { provider.gcp_project_id }
- let(:zone) { provider.zone }
- let(:cluster_name) { cluster.name }
+ let(:cluster) { create(:cluster, :project, :providing_by_gcp) }
+ let(:provider) { cluster.provider }
+ let(:platform) { cluster.platform }
+ let(:endpoint) { '111.111.111.111' }
+ let(:api_url) { 'https://' + endpoint }
+ let(:username) { 'sample-username' }
+ let(:password) { 'sample-password' }
+ let(:secret_name) { 'gitlab-token' }
+ let(:token) { 'sample-token' }
+ let(:namespace) { "#{cluster.project.path}-#{cluster.project.id}" }
- subject { described_class.new.execute(provider) }
+ subject { described_class.new.execute(provider) }
- shared_examples 'success' do
- it 'configures provider and kubernetes' do
- subject
+ shared_examples 'success' do
+ it 'configures provider and kubernetes' do
+ subject
- expect(provider).to be_created
- end
+ expect(provider).to be_created
end
- shared_examples 'error' do
- it 'sets an error to provider object' do
- subject
+ it 'properly configures database models' do
+ subject
- expect(provider.reload).to be_errored
- end
+ cluster.reload
+
+ expect(provider.endpoint).to eq(endpoint)
+ expect(platform.api_url).to eq(api_url)
+ expect(platform.ca_cert).to eq(Base64.decode64(load_sample_cert).strip)
+ expect(platform.username).to eq(username)
+ expect(platform.password).to eq(password)
+ expect(platform.token).to eq(token)
+ end
+
+ it 'creates kubernetes namespace model' do
+ subject
+
+ kubernetes_namespace = cluster.reload.kubernetes_namespace
+ expect(kubernetes_namespace).to be_persisted
+ expect(kubernetes_namespace.namespace).to eq(namespace)
+ expect(kubernetes_namespace.service_account_name).to eq("#{namespace}-service-account")
+ expect(kubernetes_namespace.service_account_token).to be_present
end
+ end
+
+ shared_examples 'error' do
+ it 'sets an error to provider object' do
+ subject
- context 'when suceeded to fetch gke cluster info' do
- let(:endpoint) { '111.111.111.111' }
- let(:api_url) { 'https://' + endpoint }
- let(:username) { 'sample-username' }
- let(:password) { 'sample-password' }
- let(:secret_name) { 'gitlab-token' }
+ expect(provider.reload).to be_errored
+ end
+ end
+ shared_examples 'kubernetes information not successfully fetched' do
+ context 'when failed to fetch gke cluster info' do
before do
- stub_cloud_platform_get_zone_cluster(
- gcp_project_id, zone, cluster_name,
- {
- endpoint: endpoint,
- username: username,
- password: password
- }
- )
+ stub_cloud_platform_get_zone_cluster_error(provider.gcp_project_id, provider.zone, cluster.name)
end
- context 'service account and token created' do
- before do
- stub_kubeclient_discover(api_url)
- stub_kubeclient_create_service_account(api_url)
- stub_kubeclient_create_secret(api_url)
- end
-
- shared_context 'kubernetes token successfully fetched' do
- let(:token) { 'sample-token' }
-
- before do
- stub_kubeclient_get_secret(
- api_url,
- {
- metadata_name: secret_name,
- token: Base64.encode64(token)
- } )
- end
- end
-
- context 'provider legacy_abac is enabled' do
- include_context 'kubernetes token successfully fetched'
-
- it_behaves_like 'success'
-
- it 'properly configures database models' do
- subject
-
- cluster.reload
-
- expect(provider.endpoint).to eq(endpoint)
- expect(platform.api_url).to eq(api_url)
- expect(platform.ca_cert).to eq(Base64.decode64(load_sample_cert))
- expect(platform.username).to eq(username)
- expect(platform.password).to eq(password)
- expect(platform).to be_abac
- expect(platform.authorization_type).to eq('abac')
- expect(platform.token).to eq(token)
- end
- end
-
- context 'provider legacy_abac is disabled' do
- before do
- provider.legacy_abac = false
- end
-
- include_context 'kubernetes token successfully fetched'
-
- context 'cluster role binding created' do
- before do
- stub_kubeclient_create_cluster_role_binding(api_url)
- end
-
- it_behaves_like 'success'
-
- it 'properly configures database models' do
- subject
-
- cluster.reload
-
- expect(provider.endpoint).to eq(endpoint)
- expect(platform.api_url).to eq(api_url)
- expect(platform.ca_cert).to eq(Base64.decode64(load_sample_cert))
- expect(platform.username).to eq(username)
- expect(platform.password).to eq(password)
- expect(platform).to be_rbac
- expect(platform.token).to eq(token)
- end
- end
- end
-
- context 'when token is empty' do
- before do
- stub_kubeclient_get_secret(api_url, token: '', metadata_name: secret_name)
- end
-
- it_behaves_like 'error'
- end
-
- context 'when failed to fetch kubernetes token' do
- before do
- stub_kubeclient_get_secret_error(api_url, secret_name)
- end
-
- it_behaves_like 'error'
- end
-
- context 'when service account fails to create' do
- before do
- stub_kubeclient_create_service_account_error(api_url)
- end
-
- it_behaves_like 'error'
- end
+ it_behaves_like 'error'
+ end
+
+ context 'when token is empty' do
+ let(:token) { '' }
+
+ it_behaves_like 'error'
+ end
+
+ context 'when failed to fetch kubernetes token' do
+ before do
+ stub_kubeclient_get_secret_error(api_url, secret_name, namespace: 'default')
end
+
+ it_behaves_like 'error'
end
- context 'when failed to fetch gke cluster info' do
+ context 'when service account fails to create' do
before do
- stub_cloud_platform_get_zone_cluster_error(gcp_project_id, zone, cluster_name)
+ stub_kubeclient_create_service_account_error(api_url, namespace: 'default')
end
it_behaves_like 'error'
end
end
+
+ shared_context 'kubernetes information successfully fetched' do
+ before do
+ stub_cloud_platform_get_zone_cluster(
+ provider.gcp_project_id, provider.zone, cluster.name,
+ {
+ endpoint: endpoint,
+ username: username,
+ password: password
+ }
+ )
+
+ stub_kubeclient_discover(api_url)
+ stub_kubeclient_get_namespace(api_url)
+ stub_kubeclient_create_namespace(api_url)
+ stub_kubeclient_create_service_account(api_url)
+ stub_kubeclient_create_secret(api_url)
+
+ stub_kubeclient_get_secret(
+ api_url,
+ {
+ metadata_name: secret_name,
+ token: Base64.encode64(token),
+ namespace: 'default'
+ }
+ )
+
+ stub_kubeclient_get_namespace(api_url, namespace: namespace)
+ stub_kubeclient_create_service_account(api_url, namespace: namespace)
+ stub_kubeclient_create_secret(api_url, namespace: namespace)
+
+ stub_kubeclient_get_secret(
+ api_url,
+ {
+ metadata_name: "#{namespace}-token",
+ token: Base64.encode64(token),
+ namespace: namespace
+ }
+ )
+ end
+ end
+
+ context 'With a legacy ABAC cluster' do
+ before do
+ provider.legacy_abac = true
+ end
+
+ include_context 'kubernetes information successfully fetched'
+
+ it_behaves_like 'success'
+
+ it 'uses ABAC authorization type' do
+ subject
+ cluster.reload
+
+ expect(platform).to be_abac
+ expect(platform.authorization_type).to eq('abac')
+ end
+
+ it_behaves_like 'kubernetes information not successfully fetched'
+ end
+
+ context 'With an RBAC cluster' do
+ before do
+ provider.legacy_abac = false
+
+ stub_kubeclient_create_cluster_role_binding(api_url)
+ stub_kubeclient_create_role_binding(api_url, namespace: namespace)
+ end
+
+ include_context 'kubernetes information successfully fetched'
+
+ it_behaves_like 'success'
+
+ it 'uses RBAC authorization type' do
+ subject
+ cluster.reload
+
+ expect(platform).to be_rbac
+ expect(platform.authorization_type).to eq('rbac')
+ end
+
+ it_behaves_like 'kubernetes information not successfully fetched'
+ end
end
diff --git a/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb b/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb
new file mode 100644
index 00000000000..661364ac765
--- /dev/null
+++ b/spec/services/clusters/gcp/kubernetes/create_or_update_namespace_service_spec.rb
@@ -0,0 +1,115 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService, '#execute' do
+ include KubernetesHelpers
+
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+ let(:platform) { cluster.platform }
+ let(:api_url) { 'https://kubernetes.example.com' }
+ let(:project) { cluster.project }
+ let(:cluster_project) { cluster.cluster_project }
+
+ subject do
+ described_class.new(
+ cluster: cluster,
+ kubernetes_namespace: kubernetes_namespace
+ ).execute
+ end
+
+ shared_context 'kubernetes requests' do
+ before do
+ stub_kubeclient_discover(api_url)
+ stub_kubeclient_get_namespace(api_url)
+ stub_kubeclient_create_service_account(api_url)
+ stub_kubeclient_create_secret(api_url)
+
+ stub_kubeclient_get_namespace(api_url, namespace: namespace)
+ stub_kubeclient_create_service_account(api_url, namespace: namespace)
+ stub_kubeclient_create_secret(api_url, namespace: namespace)
+
+ stub_kubeclient_get_secret(
+ api_url,
+ {
+ metadata_name: "#{namespace}-token",
+ token: Base64.encode64('sample-token'),
+ namespace: namespace
+ }
+ )
+ end
+ end
+
+ context 'when kubernetes namespace is not persisted' do
+ let(:namespace) { "#{project.path}-#{project.id}" }
+
+ let(:kubernetes_namespace) do
+ create(:cluster_kubernetes_namespace,
+ cluster: cluster,
+ project: cluster_project.project,
+ cluster_project: cluster_project)
+ end
+
+ include_context 'kubernetes requests'
+
+ it 'creates a Clusters::KubernetesNamespace' do
+ expect do
+ subject
+ end.to change(Clusters::KubernetesNamespace, :count).by(1)
+ end
+
+ it 'creates project service account' do
+ expect_any_instance_of(Clusters::Gcp::Kubernetes::CreateServiceAccountService).to receive(:execute).once
+
+ subject
+ end
+
+ it 'configures kubernetes token' do
+ subject
+
+ kubernetes_namespace.reload
+ expect(kubernetes_namespace.namespace).to eq(namespace)
+ expect(kubernetes_namespace.service_account_name).to eq("#{namespace}-service-account")
+ expect(kubernetes_namespace.encrypted_service_account_token).to be_present
+ end
+ end
+
+ context 'when there is a Kubernetes Namespace associated' do
+ let(:namespace) { 'new-namespace' }
+
+ let(:kubernetes_namespace) do
+ create(:cluster_kubernetes_namespace,
+ cluster: cluster,
+ project: cluster_project.project,
+ cluster_project: cluster_project)
+ end
+
+ include_context 'kubernetes requests'
+
+ before do
+ platform.update_column(:namespace, 'new-namespace')
+ end
+
+ it 'does not create any Clusters::KubernetesNamespace' do
+ subject
+
+ expect(cluster.kubernetes_namespace).to eq(kubernetes_namespace)
+ end
+
+ it 'creates project service account' do
+ expect_any_instance_of(Clusters::Gcp::Kubernetes::CreateServiceAccountService).to receive(:execute).once
+
+ subject
+ end
+
+ it 'updates Clusters::KubernetesNamespace' do
+ subject
+
+ kubernetes_namespace.reload
+
+ expect(kubernetes_namespace.namespace).to eq(namespace)
+ expect(kubernetes_namespace.service_account_name).to eq("#{namespace}-service-account")
+ expect(kubernetes_namespace.encrypted_service_account_token).to be_present
+ end
+ end
+end
diff --git a/spec/services/clusters/gcp/kubernetes/create_service_account_service_spec.rb b/spec/services/clusters/gcp/kubernetes/create_service_account_service_spec.rb
index 065d021db5e..588edff85d4 100644
--- a/spec/services/clusters/gcp/kubernetes/create_service_account_service_spec.rb
+++ b/spec/services/clusters/gcp/kubernetes/create_service_account_service_spec.rb
@@ -1,95 +1,165 @@
# frozen_string_literal: true
-
require 'spec_helper'
describe Clusters::Gcp::Kubernetes::CreateServiceAccountService do
include KubernetesHelpers
- let(:service) { described_class.new(kubeclient, rbac: rbac) }
+ let(:api_url) { 'http://111.111.111.111' }
+ let(:platform_kubernetes) { cluster.platform_kubernetes }
+ let(:cluster_project) { cluster.cluster_project }
+ let(:project) { cluster_project.project }
+ let(:cluster) do
+ create(:cluster,
+ :project, :provided_by_gcp,
+ platform_kubernetes: create(:cluster_platform_kubernetes, :configured))
+ end
+
+ let(:kubeclient) do
+ Gitlab::Kubernetes::KubeClient.new(
+ api_url,
+ auth_options: { username: 'admin', password: 'xxx' }
+ )
+ end
- describe '#execute' do
- let(:rbac) { false }
- let(:api_url) { 'http://111.111.111.111' }
- let(:username) { 'admin' }
- let(:password) { 'xxx' }
+ shared_examples 'creates service account and token' do
+ it 'creates a kubernetes service account' do
+ subject
+
+ expect(WebMock).to have_requested(:post, api_url + "/api/v1/namespaces/#{namespace}/serviceaccounts").with(
+ body: hash_including(
+ kind: 'ServiceAccount',
+ metadata: { name: service_account_name, namespace: namespace }
+ )
+ )
+ end
- let(:kubeclient) do
- Gitlab::Kubernetes::KubeClient.new(
- api_url,
- ['api', 'apis/rbac.authorization.k8s.io'],
- auth_options: { username: username, password: password }
+ it 'creates a kubernetes secret' do
+ subject
+
+ expect(WebMock).to have_requested(:post, api_url + "/api/v1/namespaces/#{namespace}/secrets").with(
+ body: hash_including(
+ kind: 'Secret',
+ metadata: {
+ name: token_name,
+ namespace: namespace,
+ annotations: {
+ 'kubernetes.io/service-account.name': service_account_name
+ }
+ },
+ type: 'kubernetes.io/service-account-token'
+ )
)
end
+ end
+
+ before do
+ stub_kubeclient_discover(api_url)
+ stub_kubeclient_get_namespace(api_url, namespace: namespace)
+ stub_kubeclient_create_service_account(api_url, namespace: namespace )
+ stub_kubeclient_create_secret(api_url, namespace: namespace)
+ end
+
+ describe '.gitlab_creator' do
+ let(:namespace) { 'default' }
+ let(:service_account_name) { 'gitlab' }
+ let(:token_name) { 'gitlab-token' }
+
+ subject { described_class.gitlab_creator(kubeclient, rbac: rbac).execute }
+
+ context 'with ABAC cluster' do
+ let(:rbac) { false }
+
+ it_behaves_like 'creates service account and token'
+ end
- subject { service.execute }
+ context 'with RBAC cluster' do
+ let(:rbac) { true }
- context 'when params are correct' do
before do
- stub_kubeclient_discover(api_url)
- stub_kubeclient_create_service_account(api_url)
- stub_kubeclient_create_secret(api_url)
- end
+ cluster.platform_kubernetes.rbac!
- shared_examples 'creates service account and token' do
- it 'creates a kubernetes service account' do
- subject
+ stub_kubeclient_create_cluster_role_binding(api_url)
+ end
- expect(WebMock).to have_requested(:post, api_url + '/api/v1/namespaces/default/serviceaccounts').with(
- body: hash_including(
- kind: 'ServiceAccount',
- metadata: { name: 'gitlab', namespace: 'default' }
- )
- )
- end
-
- it 'creates a kubernetes secret of type ServiceAccountToken' do
- subject
-
- expect(WebMock).to have_requested(:post, api_url + '/api/v1/namespaces/default/secrets').with(
- body: hash_including(
- kind: 'Secret',
- metadata: {
- name: 'gitlab-token',
- namespace: 'default',
- annotations: {
- 'kubernetes.io/service-account.name': 'gitlab'
- }
- },
- type: 'kubernetes.io/service-account-token'
- )
+ it_behaves_like 'creates service account and token'
+
+ it 'should create a cluster role binding with cluster-admin access' do
+ subject
+
+ expect(WebMock).to have_requested(:post, api_url + "/apis/rbac.authorization.k8s.io/v1/clusterrolebindings").with(
+ body: hash_including(
+ kind: 'ClusterRoleBinding',
+ metadata: { name: 'gitlab-admin' },
+ roleRef: {
+ apiGroup: 'rbac.authorization.k8s.io',
+ kind: 'ClusterRole',
+ name: 'cluster-admin'
+ },
+ subjects: [
+ {
+ kind: 'ServiceAccount',
+ name: service_account_name,
+ namespace: namespace
+ }
+ ]
)
- end
+ )
end
+ end
+ end
+
+ describe '.namespace_creator' do
+ let(:namespace) { "#{project.path}-#{project.id}" }
+ let(:service_account_name) { "#{namespace}-service-account" }
+ let(:token_name) { "#{namespace}-token" }
+
+ subject do
+ described_class.namespace_creator(
+ kubeclient,
+ service_account_name: service_account_name,
+ service_account_namespace: namespace,
+ rbac: rbac
+ ).execute
+ end
+
+ context 'with ABAC cluster' do
+ let(:rbac) { false }
+
+ it_behaves_like 'creates service account and token'
+ end
+
+ context 'With RBAC enabled cluster' do
+ let(:rbac) { true }
+
+ before do
+ cluster.platform_kubernetes.rbac!
- context 'abac enabled cluster' do
- it_behaves_like 'creates service account and token'
+ stub_kubeclient_create_role_binding(api_url, namespace: namespace)
end
- context 'rbac enabled cluster' do
- let(:rbac) { true }
-
- before do
- stub_kubeclient_create_cluster_role_binding(api_url)
- end
-
- it_behaves_like 'creates service account and token'
-
- it 'creates a kubernetes cluster role binding' do
- subject
-
- expect(WebMock).to have_requested(:post, api_url + '/apis/rbac.authorization.k8s.io/v1/clusterrolebindings').with(
- body: hash_including(
- kind: 'ClusterRoleBinding',
- metadata: { name: 'gitlab-admin' },
- roleRef: {
- apiGroup: 'rbac.authorization.k8s.io',
- kind: 'ClusterRole',
- name: 'cluster-admin'
- },
- subjects: [{ kind: 'ServiceAccount', namespace: 'default', name: 'gitlab' }]
- )
+ it_behaves_like 'creates service account and token'
+
+ it 'creates a namespaced role binding with edit access' do
+ subject
+
+ expect(WebMock).to have_requested(:post, api_url + "/apis/rbac.authorization.k8s.io/v1/namespaces/#{namespace}/rolebindings").with(
+ body: hash_including(
+ kind: 'RoleBinding',
+ metadata: { name: "gitlab-#{namespace}", namespace: "#{namespace}" },
+ roleRef: {
+ apiGroup: 'rbac.authorization.k8s.io',
+ kind: 'ClusterRole',
+ name: 'edit'
+ },
+ subjects: [
+ {
+ kind: 'ServiceAccount',
+ name: service_account_name,
+ namespace: namespace
+ }
+ ]
)
- end
+ )
end
end
end
diff --git a/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb b/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb
index c543de21d5b..a5806559b14 100644
--- a/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb
+++ b/spec/services/clusters/gcp/kubernetes/fetch_kubernetes_token_service_spec.rb
@@ -1,57 +1,59 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
describe Clusters::Gcp::Kubernetes::FetchKubernetesTokenService do
+ include KubernetesHelpers
+
describe '#execute' do
let(:api_url) { 'http://111.111.111.111' }
- let(:username) { 'admin' }
- let(:password) { 'xxx' }
+ let(:namespace) { 'my-namespace' }
+ let(:service_account_token_name) { 'gitlab-token' }
let(:kubeclient) do
Gitlab::Kubernetes::KubeClient.new(
api_url,
- ['api', 'apis/rbac.authorization.k8s.io'],
- auth_options: { username: username, password: password }
+ auth_options: { username: 'admin', password: 'xxx' }
)
end
- subject { described_class.new(kubeclient).execute }
+ subject { described_class.new(kubeclient, service_account_token_name, namespace).execute }
+
+ before do
+ stub_kubeclient_discover(api_url)
+ end
context 'when params correct' do
let(:decoded_token) { 'xxx.token.xxx' }
let(:token) { Base64.encode64(decoded_token) }
- let(:secret_json) do
- {
- 'metadata': {
- name: 'gitlab-token'
- },
- 'data': {
- 'token': token
- }
- }
- end
-
- before do
- allow_any_instance_of(Kubeclient::Client)
- .to receive(:get_secret).and_return(secret_json)
- end
-
context 'when gitlab-token exists' do
- let(:metadata_name) { 'gitlab-token' }
+ before do
+ stub_kubeclient_get_secret(
+ api_url,
+ {
+ metadata_name: service_account_token_name,
+ namespace: namespace,
+ token: token
+ }
+ )
+ end
it { is_expected.to eq(decoded_token) }
end
- context 'when gitlab-token does not exist' do
- let(:secret_json) { {} }
+ context 'when there is a 500 error' do
+ before do
+ stub_kubeclient_get_secret_error(api_url, service_account_token_name, namespace: namespace, status: 500)
+ end
- it { is_expected.to be_nil }
+ it { expect { subject }.to raise_error(Kubeclient::HttpError) }
end
- context 'when token is nil' do
- let(:token) { nil }
+ context 'when gitlab-token does not exist' do
+ before do
+ stub_kubeclient_get_secret_error(api_url, service_account_token_name, namespace: namespace, status: 404)
+ end
it { is_expected.to be_nil }
end
diff --git a/spec/services/clusters/gcp/provision_service_spec.rb b/spec/services/clusters/gcp/provision_service_spec.rb
index f48afdc83b2..c0bdac40938 100644
--- a/spec/services/clusters/gcp/provision_service_spec.rb
+++ b/spec/services/clusters/gcp/provision_service_spec.rb
@@ -26,7 +26,7 @@ describe Clusters::Gcp::ProvisionService do
end
end
- context 'when suceeded to request provision' do
+ context 'when succeeded to request provision' do
before do
stub_cloud_platform_create_cluster(gcp_project_id, zone)
end
diff --git a/spec/services/clusters/update_service_spec.rb b/spec/services/clusters/update_service_spec.rb
index 2d91a21035d..73f9be242a3 100644
--- a/spec/services/clusters/update_service_spec.rb
+++ b/spec/services/clusters/update_service_spec.rb
@@ -1,8 +1,10 @@
require 'spec_helper'
describe Clusters::UpdateService do
+ include KubernetesHelpers
+
describe '#execute' do
- subject { described_class.new(cluster.project, cluster.user, params).execute(cluster) }
+ subject { described_class.new(cluster.user, params).execute(cluster) }
let(:cluster) { create(:cluster, :project, :provided_by_user) }
@@ -34,6 +36,11 @@ describe Clusters::UpdateService do
}
end
+ before do
+ allow(ClusterPlatformConfigureWorker).to receive(:perform_async)
+ stub_kubeclient_get_namespace('https://kubernetes.example.com', namespace: 'my-namespace')
+ end
+
it 'updates namespace' do
is_expected.to eq(true)
expect(cluster.platform.namespace).to eq('custom-namespace')
@@ -55,5 +62,32 @@ describe Clusters::UpdateService do
expect(cluster.errors[:"platform_kubernetes.namespace"]).to be_present
end
end
+
+ context 'when cluster is provided by GCP' do
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+
+ let(:params) do
+ {
+ name: 'my-new-name'
+ }
+ end
+
+ it 'does not change cluster name' do
+ is_expected.to eq(false)
+
+ cluster.reload
+ expect(cluster.name).to eq('test-cluster')
+ end
+
+ context 'when cluster is being created' do
+ let(:cluster) { create(:cluster, :providing_by_gcp) }
+
+ it 'rejects changes' do
+ is_expected.to eq(false)
+
+ expect(cluster.errors.full_messages).to include('cannot modify during creation')
+ end
+ end
+ end
end
end
diff --git a/spec/services/commits/commit_patch_service_spec.rb b/spec/services/commits/commit_patch_service_spec.rb
new file mode 100644
index 00000000000..f4fcec2fbc2
--- /dev/null
+++ b/spec/services/commits/commit_patch_service_spec.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Commits::CommitPatchService do
+ describe '#execute' do
+ let(:patches) do
+ patches_folder = Rails.root.join('spec/fixtures/patchfiles')
+ content_1 = File.read(File.join(patches_folder, "0001-This-does-not-apply-to-the-feature-branch.patch"))
+ content_2 = File.read(File.join(patches_folder, "0001-A-commit-from-a-patch.patch"))
+
+ [content_1, content_2]
+ end
+ let(:user) { project.creator }
+ let(:branch_name) { 'branch-with-patches' }
+ let(:project) { create(:project, :repository) }
+ let(:start_branch) { nil }
+ let(:params) { { branch_name: branch_name, patches: patches, start_branch: start_branch } }
+
+ subject(:service) do
+ described_class.new(project, user, params)
+ end
+
+ it 'returns a successful result' do
+ result = service.execute
+
+ branch = project.repository.find_branch(branch_name)
+
+ expect(result[:status]).to eq(:success)
+ expect(result[:result]).to eq(branch.target)
+ end
+
+ it 'is based off HEAD when no start ref is passed' do
+ service.execute
+
+ merge_base = project.repository.merge_base(project.repository.root_ref, branch_name)
+
+ expect(merge_base).to eq(project.repository.commit('HEAD').sha)
+ end
+
+ context 'when specifying a different start branch' do
+ let(:start_branch) { 'with-codeowners' }
+
+ it 'is based of the correct branch' do
+ service.execute
+
+ merge_base = project.repository.merge_base(start_branch, branch_name)
+
+ expect(merge_base).to eq(project.repository.commit(start_branch).sha)
+ end
+ end
+
+ shared_examples 'an error response' do |expected_message|
+ it 'returns the correct error' do
+ result = service.execute
+
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to match(expected_message)
+ end
+ end
+
+ context 'when the user does not have access' do
+ let(:user) { create(:user) }
+
+ it_behaves_like 'an error response',
+ 'You are not allowed to push into this branch'
+ end
+
+ context 'when the patches are not valid' do
+ let(:patches) { "a" * 2.1.megabytes }
+
+ it_behaves_like 'an error response', 'Patches are too big'
+ end
+
+ context 'when the new branch name is invalid' do
+ let(:branch_name) { 'HEAD' }
+
+ it_behaves_like 'an error response', 'Branch name is invalid'
+ end
+
+ context 'when the patches do not apply' do
+ let(:branch_name) { 'feature' }
+
+ it_behaves_like 'an error response', 'Patch failed at'
+ end
+
+ context 'when specifying a non existent start branch' do
+ let(:start_branch) { 'does-not-exist' }
+
+ it_behaves_like 'an error response', 'Invalid reference name'
+ end
+ end
+end
diff --git a/spec/services/create_deployment_service_spec.rb b/spec/services/create_deployment_service_spec.rb
deleted file mode 100644
index b9bfbb11511..00000000000
--- a/spec/services/create_deployment_service_spec.rb
+++ /dev/null
@@ -1,335 +0,0 @@
-require 'spec_helper'
-
-describe CreateDeploymentService do
- let(:user) { create(:user) }
- let(:options) { nil }
-
- let(:job) do
- create(:ci_build,
- ref: 'master',
- tag: false,
- environment: 'production',
- options: { environment: options })
- end
-
- let(:project) { job.project }
-
- let!(:environment) do
- create(:environment, project: project, name: 'production')
- end
-
- let(:service) { described_class.new(job) }
-
- before do
- allow_any_instance_of(Deployment).to receive(:create_ref)
- end
-
- describe '#execute' do
- subject { service.execute }
-
- context 'when environment exists' do
- it 'creates a deployment' do
- expect(subject).to be_persisted
- end
- end
-
- context 'when environment does not exist' do
- let(:environment) {}
-
- it 'does not create a deployment' do
- expect do
- expect(subject).to be_nil
- end.not_to change { Deployment.count }
- end
- end
-
- context 'when start action is defined' do
- let(:options) { { action: 'start' } }
-
- context 'and environment is stopped' do
- before do
- environment.stop
- end
-
- it 'makes environment available' do
- subject
-
- expect(environment.reload).to be_available
- end
-
- it 'creates a deployment' do
- expect(subject).to be_persisted
- end
- end
- end
-
- context 'when stop action is defined' do
- let(:options) { { action: 'stop' } }
-
- context 'and environment is available' do
- before do
- environment.start
- end
-
- it 'makes environment stopped' do
- subject
-
- expect(environment.reload).to be_stopped
- end
-
- it 'does not create a deployment' do
- expect(subject).to be_nil
- end
- end
- end
-
- context 'when variables are used' do
- let(:options) do
- { name: 'review-apps/$CI_COMMIT_REF_NAME',
- url: 'http://$CI_COMMIT_REF_NAME.review-apps.gitlab.com' }
- end
-
- before do
- environment.update(name: 'review-apps/master')
- job.update(environment: 'review-apps/$CI_COMMIT_REF_NAME')
- end
-
- it 'creates a new deployment' do
- expect(subject).to be_persisted
- end
-
- it 'does not create a new environment' do
- expect { subject }.not_to change { Environment.count }
- end
-
- it 'updates external url' do
- subject
-
- expect(subject.environment.name).to eq('review-apps/master')
- expect(subject.environment.external_url).to eq('http://master.review-apps.gitlab.com')
- end
- end
-
- context 'when project was removed' do
- let(:environment) {}
-
- before do
- job.update(project: nil)
- end
-
- it 'does not create deployment or environment' do
- expect { subject }.not_to raise_error
-
- expect(Environment.count).to be_zero
- expect(Deployment.count).to be_zero
- end
- end
- end
-
- describe '#expanded_environment_url' do
- subject { service.send(:expanded_environment_url) }
-
- context 'when yaml environment uses $CI_COMMIT_REF_NAME' do
- let(:job) do
- create(:ci_build,
- ref: 'master',
- options: { environment: { url: 'http://review/$CI_COMMIT_REF_NAME' } })
- end
-
- it { is_expected.to eq('http://review/master') }
- end
-
- context 'when yaml environment uses $CI_ENVIRONMENT_SLUG' do
- let(:job) do
- create(:ci_build,
- ref: 'master',
- environment: 'production',
- options: { environment: { url: 'http://review/$CI_ENVIRONMENT_SLUG' } })
- end
-
- let!(:environment) do
- create(:environment,
- project: job.project,
- name: 'production',
- slug: 'prod-slug',
- external_url: 'http://review/old')
- end
-
- it { is_expected.to eq('http://review/prod-slug') }
- end
-
- context 'when yaml environment uses yaml_variables containing symbol keys' do
- let(:job) do
- create(:ci_build,
- yaml_variables: [{ key: :APP_HOST, value: 'host' }],
- options: { environment: { url: 'http://review/$APP_HOST' } })
- end
-
- it { is_expected.to eq('http://review/host') }
- end
-
- context 'when yaml environment does not have url' do
- let(:job) { create(:ci_build, environment: 'staging') }
-
- let!(:environment) do
- create(:environment, project: job.project, name: job.environment)
- end
-
- it 'returns the external_url from persisted environment' do
- is_expected.to be_nil
- end
- end
- end
-
- describe 'processing of builds' do
- shared_examples 'does not create deployment' do
- it 'does not create a new deployment' do
- expect { subject }.not_to change { Deployment.count }
- end
-
- it 'does not call a service' do
- expect_any_instance_of(described_class).not_to receive(:execute)
-
- subject
- end
- end
-
- shared_examples 'creates deployment' do
- it 'creates a new deployment' do
- expect { subject }.to change { Deployment.count }.by(1)
- end
-
- it 'calls a service' do
- expect_any_instance_of(described_class).to receive(:execute)
-
- subject
- end
-
- it 'is set as deployable' do
- subject
-
- expect(Deployment.last.deployable).to eq(deployable)
- end
-
- it 'updates environment URL' do
- subject
-
- expect(Deployment.last.environment.external_url).not_to be_nil
- end
- end
-
- context 'without environment specified' do
- let(:job) { create(:ci_build) }
-
- it_behaves_like 'does not create deployment' do
- subject { job.success }
- end
- end
-
- context 'when environment is specified' do
- let(:deployable) { job }
-
- let(:options) do
- { environment: { name: 'production', url: 'http://gitlab.com' } }
- end
-
- context 'when job succeeds' do
- it_behaves_like 'creates deployment' do
- subject { job.success }
- end
- end
-
- context 'when job fails' do
- it_behaves_like 'does not create deployment' do
- subject { job.drop }
- end
- end
-
- context 'when job is retried' do
- it_behaves_like 'creates deployment' do
- before do
- stub_not_protect_default_branch
-
- project.add_developer(user)
- end
-
- let(:deployable) { Ci::Build.retry(job, user) }
-
- subject { deployable.success }
- end
- end
- end
- end
-
- describe "merge request metrics" do
- let(:merge_request) { create(:merge_request, target_branch: 'master', source_branch: 'feature', source_project: project) }
-
- context "while updating the 'first_deployed_to_production_at' time" do
- before do
- merge_request.metrics.update!(merged_at: Time.now)
- end
-
- context "for merge requests merged before the current deploy" do
- it "sets the time if the deploy's environment is 'production'" do
- time = Time.now
- Timecop.freeze(time) { service.execute }
-
- expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_like_time(time)
- end
-
- it "doesn't set the time if the deploy's environment is not 'production'" do
- job.update(environment: 'staging')
- service = described_class.new(job)
- service.execute
-
- expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_nil
- end
-
- it 'does not raise errors if the merge request does not have a metrics record' do
- merge_request.metrics.destroy
-
- expect(merge_request.reload.metrics).to be_nil
- expect { service.execute }.not_to raise_error
- end
- end
-
- context "for merge requests merged before the previous deploy" do
- context "if the 'first_deployed_to_production_at' time is already set" do
- it "does not overwrite the older 'first_deployed_to_production_at' time" do
- # Previous deploy
- time = Time.now
- Timecop.freeze(time) { service.execute }
-
- expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_like_time(time)
-
- # Current deploy
- service = described_class.new(job)
- Timecop.freeze(time + 12.hours) { service.execute }
-
- expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_like_time(time)
- end
- end
-
- context "if the 'first_deployed_to_production_at' time is not already set" do
- it "does not overwrite the older 'first_deployed_to_production_at' time" do
- # Previous deploy
- time = 5.minutes.from_now
- Timecop.freeze(time) { service.execute }
-
- expect(merge_request.reload.metrics.merged_at).to be < merge_request.reload.metrics.first_deployed_to_production_at
-
- merge_request.reload.metrics.update(first_deployed_to_production_at: nil)
-
- expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_nil
-
- # Current deploy
- service = described_class.new(job)
- Timecop.freeze(time + 12.hours) { service.execute }
-
- expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_nil
- end
- end
- end
- end
- end
-end
diff --git a/spec/services/files/multi_service_spec.rb b/spec/services/files/multi_service_spec.rb
index 3bdedaf3770..84c48d63c64 100644
--- a/spec/services/files/multi_service_spec.rb
+++ b/spec/services/files/multi_service_spec.rb
@@ -11,6 +11,7 @@ describe Files::MultiService do
let(:new_file_path) { 'files/ruby/popen.rb' }
let(:file_content) { 'New content' }
let(:action) { 'update' }
+ let(:commit_message) { 'Update File' }
let!(:original_commit_id) do
Gitlab::Git::Commit.last_for_path(project.repository, branch_name, original_file_path).sha
@@ -30,7 +31,7 @@ describe Files::MultiService do
let(:commit_params) do
{
- commit_message: "Update File",
+ commit_message: commit_message,
branch_name: branch_name,
start_branch: branch_name,
actions: actions
@@ -84,30 +85,84 @@ describe Files::MultiService do
end
end
+ describe 'changing execute_filemode of a file' do
+ let(:commit_message) { 'Chmod +x file' }
+ let(:file_path) { original_file_path }
+ let(:default_action) do
+ {
+ action: 'chmod',
+ file_path: file_path,
+ execute_filemode: true
+ }
+ end
+
+ it 'accepts the commit' do
+ results = subject.execute
+
+ expect(results[:status]).to eq(:success)
+ end
+
+ it 'updates the execute_filemode of the file' do
+ expect { subject.execute }.to change { repository.blob_at_branch(branch_name, file_path).mode }.from('100644').to('100755')
+ end
+
+ context "when the file doesn't exists" do
+ let(:file_path) { 'files/wrong_path.rb' }
+
+ it 'rejects the commit' do
+ results = subject.execute
+
+ expect(results[:status]).to eq(:error)
+ expect(results[:message]).to eq("A file with this name doesn't exist")
+ end
+ end
+ end
+
context 'when moving a file' do
let(:action) { 'move' }
let(:new_file_path) { 'files/ruby/new_popen.rb' }
+ let(:result) { subject.execute }
+ let(:blob) { repository.blob_at_branch(branch_name, new_file_path) }
+
context 'when original file has been updated' do
before do
update_file(original_file_path)
end
it 'rejects the commit' do
- results = subject.execute
-
- expect(results[:status]).to eq(:error)
- expect(results[:message]).to match(original_file_path)
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to match(original_file_path)
end
end
- context 'when original file have not been updated' do
+ context 'when original file has not been updated' do
it 'moves the file' do
- results = subject.execute
- blob = project.repository.blob_at_branch(branch_name, new_file_path)
-
- expect(results[:status]).to eq(:success)
+ expect(result[:status]).to eq(:success)
expect(blob).to be_present
+ expect(blob.data).to eq(file_content)
+ end
+
+ context 'when content is nil' do
+ let(:file_content) { nil }
+
+ it 'moves the existing content untouched' do
+ original_content = repository.blob_at_branch(branch_name, original_file_path).data
+
+ expect(result[:status]).to eq(:success)
+ expect(blob).to be_present
+ expect(blob.data).to eq(original_content)
+ end
+ end
+
+ context 'when content is an empty string' do
+ let(:file_content) { '' }
+
+ it 'moves the file and empties it' do
+ expect(result[:status]).to eq(:success)
+ expect(blob).not_to be_nil
+ expect(blob.data).to eq('')
+ end
end
end
end
diff --git a/spec/services/git_tag_push_service_spec.rb b/spec/services/git_tag_push_service_spec.rb
index 92159e1e372..2699f6e7bcd 100644
--- a/spec/services/git_tag_push_service_spec.rb
+++ b/spec/services/git_tag_push_service_spec.rb
@@ -2,6 +2,7 @@ require 'spec_helper'
describe GitTagPushService do
include RepoHelpers
+ include GitHelpers
let(:user) { create(:user) }
let(:project) { create(:project, :repository) }
@@ -118,9 +119,7 @@ describe GitTagPushService do
before do
# Create the lightweight tag
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.raw_repository.rugged.tags.create(tag_name, newrev)
- end
+ rugged_repo(project.repository).tags.create(tag_name, newrev)
# Clear tag list cache
project.repository.expire_tags_cache
diff --git a/spec/services/groups/destroy_service_spec.rb b/spec/services/groups/destroy_service_spec.rb
index 97a88b5d697..d80d0f5a8a8 100644
--- a/spec/services/groups/destroy_service_spec.rb
+++ b/spec/services/groups/destroy_service_spec.rb
@@ -35,14 +35,6 @@ describe Groups::DestroyService do
it { expect(NotificationSetting.unscoped.all).not_to include(notification_setting) }
end
- context 'site statistics' do
- it 'doesnt trigger project deletion hooks twice' do
- expect_any_instance_of(Project).to receive(:untrack_site_statistics).once
-
- destroy_group(group, user, async)
- end
- end
-
context 'mattermost team' do
let!(:chat_team) { create(:chat_team, namespace: group) }
diff --git a/spec/services/groups/transfer_service_spec.rb b/spec/services/groups/transfer_service_spec.rb
index d71ccfb4334..dd8a1cee074 100644
--- a/spec/services/groups/transfer_service_spec.rb
+++ b/spec/services/groups/transfer_service_spec.rb
@@ -177,7 +177,7 @@ describe Groups::TransferService, :postgresql do
it 'should add an error on group' do
transfer_service.execute(new_parent_group)
- expect(transfer_service.error).to eq('Transfer failed: Validation failed: Path has already been taken')
+ expect(transfer_service.error).to eq('Transfer failed: Validation failed: Group URL has already been taken')
end
end
@@ -347,7 +347,7 @@ describe Groups::TransferService, :postgresql do
end
end
- context 'when transfering a group with nested groups and projects' do
+ context 'when transferring a group with nested groups and projects' do
let!(:group) { create(:group, :public) }
let!(:project1) { create(:project, :repository, :private, namespace: group) }
let!(:subgroup1) { create(:group, :private, parent: group) }
diff --git a/spec/services/groups/update_service_spec.rb b/spec/services/groups/update_service_spec.rb
index 7c5c7409cc1..84cfa53ea05 100644
--- a/spec/services/groups/update_service_spec.rb
+++ b/spec/services/groups/update_service_spec.rb
@@ -24,6 +24,12 @@ describe Groups::UpdateService do
expect(TodosDestroyer::GroupPrivateWorker).not_to receive(:perform_in)
end
+
+ it "returns false if save failed" do
+ allow(public_group).to receive(:save).and_return(false)
+
+ expect(service.execute).to be_falsey
+ end
end
context "internal group with internal project" do
diff --git a/spec/services/issuable/bulk_update_service_spec.rb b/spec/services/issuable/bulk_update_service_spec.rb
index 53c85f73cde..f0b0f7956ce 100644
--- a/spec/services/issuable/bulk_update_service_spec.rb
+++ b/spec/services/issuable/bulk_update_service_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Issuable::BulkUpdateService do
let(:user) { create(:user) }
- let(:project) { create(:project, namespace: user.namespace) }
+ let(:project) { create(:project, :repository, namespace: user.namespace) }
def bulk_update(issuables, extra_params = {})
bulk_update_params = extra_params
diff --git a/spec/services/issuable/clone/attributes_rewriter_spec.rb b/spec/services/issuable/clone/attributes_rewriter_spec.rb
new file mode 100644
index 00000000000..20bda6984bd
--- /dev/null
+++ b/spec/services/issuable/clone/attributes_rewriter_spec.rb
@@ -0,0 +1,79 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Issuable::Clone::AttributesRewriter do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:project1) { create(:project, :public, group: group) }
+ let(:project2) { create(:project, :public, group: group) }
+ let(:original_issue) { create(:issue, project: project1) }
+ let(:new_issue) { create(:issue, project: project2) }
+
+ subject { described_class.new(user, original_issue, new_issue) }
+
+ context 'setting labels' do
+ it 'sets labels present in the new project and group labels' do
+ project1_label_1 = create(:label, title: 'label1', project: project1)
+ project1_label_2 = create(:label, title: 'label2', project: project1)
+ project2_label_1 = create(:label, title: 'label1', project: project2)
+ group_label = create(:group_label, title: 'group_label', group: group)
+ create(:label, title: 'label3', project: project2)
+
+ original_issue.update(labels: [project1_label_1, project1_label_2, group_label])
+
+ subject.execute
+
+ expect(new_issue.reload.labels).to match_array([project2_label_1, group_label])
+ end
+
+ it 'does not set any labels when not used on the original issue' do
+ subject.execute
+
+ expect(new_issue.reload.labels).to be_empty
+ end
+
+ it 'copies the resource label events' do
+ resource_label_events = create_list(:resource_label_event, 2, issue: original_issue)
+
+ subject.execute
+
+ expected = resource_label_events.map(&:label_id)
+
+ expect(new_issue.resource_label_events.map(&:label_id)).to match_array(expected)
+ end
+ end
+
+ context 'setting milestones' do
+ it 'sets milestone to nil when old issue milestone is not in the new project' do
+ milestone = create(:milestone, title: 'milestone', project: project1)
+
+ original_issue.update(milestone: milestone)
+
+ subject.execute
+
+ expect(new_issue.reload.milestone).to be_nil
+ end
+
+ it 'copies the milestone when old issue milestone title is in the new project' do
+ milestone_project1 = create(:milestone, title: 'milestone', project: project1)
+ milestone_project2 = create(:milestone, title: 'milestone', project: project2)
+
+ original_issue.update(milestone: milestone_project1)
+
+ subject.execute
+
+ expect(new_issue.reload.milestone).to eq(milestone_project2)
+ end
+
+ it 'copies the milestone when old issue milestone is a group milestone' do
+ milestone = create(:milestone, title: 'milestone', group: group)
+
+ original_issue.update(milestone: milestone)
+
+ subject.execute
+
+ expect(new_issue.reload.milestone).to eq(milestone)
+ end
+ end
+end
diff --git a/spec/services/issuable/clone/content_rewriter_spec.rb b/spec/services/issuable/clone/content_rewriter_spec.rb
new file mode 100644
index 00000000000..4d3cb0bd254
--- /dev/null
+++ b/spec/services/issuable/clone/content_rewriter_spec.rb
@@ -0,0 +1,153 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Issuable::Clone::ContentRewriter do
+ let(:user) { create(:user) }
+ let(:group) { create(:group) }
+ let(:project1) { create(:project, :public, group: group) }
+ let(:project2) { create(:project, :public, group: group) }
+
+ let(:other_issue) { create(:issue, project: project1) }
+ let(:merge_request) { create(:merge_request) }
+
+ subject { described_class.new(user, original_issue, new_issue)}
+
+ let(:description) { 'Simple text' }
+ let(:original_issue) { create(:issue, description: description, project: project1) }
+ let(:new_issue) { create(:issue, project: project2) }
+
+ context 'rewriting award emojis' do
+ it 'copies the award emojis' do
+ create(:award_emoji, awardable: original_issue, name: 'thumbsup')
+ create(:award_emoji, awardable: original_issue, name: 'thumbsdown')
+
+ expect { subject.execute }.to change { AwardEmoji.count }.by(2)
+
+ expect(new_issue.award_emoji.map(&:name)).to match_array(%w(thumbsup thumbsdown))
+ end
+ end
+
+ context 'rewriting description' do
+ before do
+ subject.execute
+ end
+
+ context 'when description is a simple text' do
+ it 'does not rewrite the description' do
+ expect(new_issue.reload.description).to eq(original_issue.description)
+ end
+ end
+
+ context 'when description contains a local reference' do
+ let(:description) { "See ##{other_issue.iid}" }
+
+ it 'rewrites the local reference correctly' do
+ expected_description = "See #{project1.path}##{other_issue.iid}"
+
+ expect(new_issue.reload.description).to eq(expected_description)
+ end
+ end
+
+ context 'when description contains a cross reference' do
+ let(:description) { "See #{merge_request.project.full_path}!#{merge_request.iid}" }
+
+ it 'rewrites the cross reference correctly' do
+ expected_description = "See #{merge_request.project.full_path}!#{merge_request.iid}"
+
+ expect(new_issue.reload.description).to eq(expected_description)
+ end
+ end
+
+ context 'when description contains a user reference' do
+ let(:description) { "FYU #{user.to_reference}" }
+
+ it 'works with a user reference' do
+ expect(new_issue.reload.description).to eq("FYU #{user.to_reference}")
+ end
+ end
+
+ context 'when description contains uploads' do
+ let(:uploader) { build(:file_uploader, project: project1) }
+ let(:description) { "Text and #{uploader.markdown_link}" }
+
+ it 'rewrites uploads in the description' do
+ upload = Upload.last
+
+ expect(new_issue.description).not_to eq(description)
+ expect(new_issue.description).to match(/Text and #{FileUploader::MARKDOWN_PATTERN}/)
+ expect(upload.secret).not_to eq(uploader.secret)
+ expect(new_issue.description).to include(upload.secret)
+ expect(new_issue.description).to include(upload.path)
+ end
+ end
+ end
+
+ context 'rewriting notes' do
+ context 'simple notes' do
+ let!(:notes) do
+ [
+ create(:note, noteable: original_issue, project: project1,
+ created_at: 2.weeks.ago, updated_at: 1.week.ago),
+ create(:note, noteable: original_issue, project: project1),
+ create(:note, system: true, noteable: original_issue, project: project1)
+ ]
+ end
+ let!(:system_note_metadata) { create(:system_note_metadata, note: notes.last) }
+ let!(:award_emoji) { create(:award_emoji, awardable: notes.first, name: 'thumbsup')}
+
+ before do
+ subject.execute
+ end
+
+ it 'rewrites existing notes in valid order' do
+ expect(new_issue.notes.order('id ASC').pluck(:note).first(3)).to eq(notes.map(&:note))
+ end
+
+ it 'copies all the issue notes' do
+ expect(new_issue.notes.count).to eq(3)
+ end
+
+ it 'does not change the note attributes' do
+ subject.execute
+
+ new_note = new_issue.notes.first
+
+ expect(new_note.note).to eq(notes.first.note)
+ expect(new_note.author).to eq(notes.first.author)
+ end
+
+ it 'copies the award emojis' do
+ subject.execute
+
+ new_note = new_issue.notes.first
+ new_note.award_emoji.first.name = 'thumbsup'
+ end
+
+ it 'copies system_note_metadata for system note' do
+ new_note = new_issue.notes.last
+
+ expect(new_note.system_note_metadata.action).to eq(system_note_metadata.action)
+ expect(new_note.system_note_metadata.id).not_to eq(system_note_metadata.id)
+ end
+ end
+
+ context 'notes with reference' do
+ let(:text) do
+ "See ##{other_issue.iid} and #{merge_request.project.full_path}!#{merge_request.iid}"
+ end
+ let!(:note) { create(:note, noteable: original_issue, note: text, project: project1) }
+
+ it 'rewrites the references correctly' do
+ subject.execute
+
+ new_note = new_issue.notes.first
+
+ expected_text = "See #{other_issue.project.path}##{other_issue.iid} and #{merge_request.project.full_path}!#{merge_request.iid}"
+
+ expect(new_note.note).to eq(expected_text)
+ expect(new_note.author).to eq(note.author)
+ end
+ end
+ end
+end
diff --git a/spec/services/issues/move_service_spec.rb b/spec/services/issues/move_service_spec.rb
index b5767583952..1e088bc7d9b 100644
--- a/spec/services/issues/move_service_spec.rb
+++ b/spec/services/issues/move_service_spec.rb
@@ -10,11 +10,9 @@ describe Issues::MoveService do
let(:sub_group_2) { create(:group, :private, parent: group) }
let(:old_project) { create(:project, namespace: sub_group_1) }
let(:new_project) { create(:project, namespace: sub_group_2) }
- let(:milestone1) { create(:milestone, project_id: old_project.id, title: 'v9.0') }
let(:old_issue) do
- create(:issue, title: title, description: description,
- project: old_project, author: author, milestone: milestone1)
+ create(:issue, title: title, description: description, project: old_project, author: author)
end
subject(:move_service) do
@@ -25,16 +23,6 @@ describe Issues::MoveService do
before do
old_project.add_reporter(user)
new_project.add_reporter(user)
-
- labels = Array.new(2) { |x| "label%d" % (x + 1) }
-
- labels.each do |label|
- old_issue.labels << create(:label,
- project_id: old_project.id,
- title: label)
-
- new_project.labels << create(:label, title: label)
- end
end
end
@@ -48,91 +36,6 @@ describe Issues::MoveService do
context 'issue movable' do
include_context 'user can move issue'
- context 'move to new milestone' do
- let(:new_issue) { move_service.execute(old_issue, new_project) }
-
- context 'project milestone' do
- let!(:milestone2) do
- create(:milestone, project_id: new_project.id, title: 'v9.0')
- end
-
- it 'assigns milestone to new issue' do
- expect(new_issue.reload.milestone.title).to eq 'v9.0'
- expect(new_issue.reload.milestone).to eq(milestone2)
- end
- end
-
- context 'group milestones' do
- let!(:group) { create(:group, :private) }
- let!(:group_milestone_1) do
- create(:milestone, group_id: group.id, title: 'v9.0_group')
- end
-
- before do
- old_issue.update(milestone: group_milestone_1)
- old_project.update(namespace: group)
- new_project.update(namespace: group)
-
- group.add_users([user], GroupMember::DEVELOPER)
- end
-
- context 'when moving to a project of the same group' do
- it 'keeps the same group milestone' do
- expect(new_issue.reload.project).to eq(new_project)
- expect(new_issue.reload.milestone).to eq(group_milestone_1)
- end
- end
-
- context 'when moving to a project of a different group' do
- let!(:group_2) { create(:group, :private) }
-
- let!(:group_milestone_2) do
- create(:milestone, group_id: group_2.id, title: 'v9.0_group')
- end
-
- before do
- old_issue.update(milestone: group_milestone_1)
- new_project.update(namespace: group_2)
-
- group_2.add_users([user], GroupMember::DEVELOPER)
- end
-
- it 'assigns to new group milestone of same title' do
- expect(new_issue.reload.project).to eq(new_project)
- expect(new_issue.reload.milestone).to eq(group_milestone_2)
- end
- end
- end
- end
-
- context 'issue with group labels', :nested_groups do
- it 'assigns group labels to new issue' do
- label = create(:group_label, group: group)
- label_issue = create(:labeled_issue, description: description, project: old_project,
- milestone: milestone1, labels: [label])
- old_project.add_reporter(user)
- new_project.add_reporter(user)
-
- new_issue = move_service.execute(label_issue, new_project)
-
- expect(new_issue).to have_attributes(
- project: new_project,
- labels: include(label)
- )
- end
- end
-
- context 'issue with resource label events' do
- it 'assigns resource label events to new issue' do
- old_issue.resource_label_events = create_list(:resource_label_event, 2, issue: old_issue)
-
- new_issue = move_service.execute(old_issue, new_project)
-
- expected = old_issue.resource_label_events.map(&:label_id)
- expect(new_issue.resource_label_events.map(&:label_id)).to match_array(expected)
- end
- end
-
context 'generic issue' do
include_context 'issue move executed'
@@ -140,18 +43,6 @@ describe Issues::MoveService do
expect(new_issue.project).to eq new_project
end
- it 'assign labels to new issue' do
- expected_label_titles = new_issue.reload.labels.map(&:title)
- expect(expected_label_titles).to include 'label1'
- expect(expected_label_titles).to include 'label2'
- expect(expected_label_titles.size).to eq 2
-
- new_issue.labels.each do |label|
- expect(new_project.labels).to include(label)
- expect(old_project.labels).not_to include(label)
- end
- end
-
it 'rewrites issue title' do
expect(new_issue.title).to eq title
end
@@ -203,140 +94,25 @@ describe Issues::MoveService do
end
end
- context 'issue with notes' do
- context 'notes without references' do
- let(:notes_params) do
- [{ system: false, note: 'Some comment 1' },
- { system: true, note: 'Some system note' },
- { system: false, note: 'Some comment 2' }]
- end
- let(:award_names) { %w(thumbsup thumbsdown facepalm) }
- let(:notes_contents) { notes_params.map { |n| n[:note] } }
-
- before do
- note_params = { noteable: old_issue, project: old_project, author: author }
- notes_params.each_with_index do |note, index|
- new_note = create(:note, note_params.merge(note))
- award_emoji_params = { awardable: new_note, name: award_names[index] }
- create(:award_emoji, award_emoji_params)
- end
- end
-
- include_context 'issue move executed'
-
- let(:all_notes) { new_issue.notes.order('id ASC') }
- let(:system_notes) { all_notes.system }
- let(:user_notes) { all_notes.user }
-
- it 'rewrites existing notes in valid order' do
- expect(all_notes.pluck(:note).first(3)).to eq notes_contents
- end
-
- it 'creates new emojis for the new notes' do
- expect(all_notes.map(&:award_emoji).to_a.flatten.map(&:name)).to eq award_names
- end
-
- it 'adds a system note about move after rewritten notes' do
- expect(system_notes.last.note).to match /^moved from/
- end
-
- it 'preserves orignal author of comment' do
- expect(user_notes.pluck(:author_id)).to all(eq(author.id))
- end
- end
-
- context 'note that has been updated' do
- let!(:note) do
- create(:note, noteable: old_issue, project: old_project,
- author: author, updated_at: Date.yesterday,
- created_at: Date.yesterday)
- end
-
- include_context 'issue move executed'
-
- it 'preserves time when note has been created at' do
- expect(new_issue.notes.first.created_at).to eq note.created_at
- end
+ context 'issue with assignee' do
+ let(:assignee) { create(:user) }
- it 'preserves time when note has been updated at' do
- expect(new_issue.notes.first.updated_at).to eq note.updated_at
- end
- end
-
- context 'issue with assignee' do
- let(:assignee) { create(:user) }
-
- before do
- old_issue.assignees = [assignee]
- end
-
- it 'preserves assignee with access to the new issue' do
- new_project.add_reporter(assignee)
-
- new_issue = move_service.execute(old_issue, new_project)
-
- expect(new_issue.assignees).to eq([assignee])
- end
-
- it 'ignores assignee without access to the new issue' do
- new_issue = move_service.execute(old_issue, new_project)
-
- expect(new_issue.assignees).to be_empty
- end
- end
-
- context 'notes with references' do
- before do
- create(:merge_request, source_project: old_project)
- create(:note, noteable: old_issue, project: old_project, author: author,
- note: 'Note with reference to merge request !1')
- end
-
- include_context 'issue move executed'
- let(:new_note) { new_issue.notes.first }
-
- it 'rewrites references using a cross reference to old project' do
- expect(new_note.note)
- .to eq "Note with reference to merge request #{old_project.to_reference(new_project)}!1"
- end
- end
-
- context 'issue description with uploads' do
- let(:uploader) { build(:file_uploader, project: old_project) }
- let(:description) { "Text and #{uploader.markdown_link}" }
-
- include_context 'issue move executed'
-
- it 'rewrites uploads in description' do
- expect(new_issue.description).not_to eq description
- expect(new_issue.description)
- .to match(/Text and #{FileUploader::MARKDOWN_PATTERN}/)
- expect(new_issue.description).not_to include uploader.secret
- end
+ before do
+ old_issue.assignees = [assignee]
end
- end
- describe 'rewriting references' do
- include_context 'issue move executed'
+ it 'preserves assignee with access to the new issue' do
+ new_project.add_reporter(assignee)
- context 'issue references' do
- let(:another_issue) { create(:issue, project: old_project) }
- let(:description) { "Some description #{another_issue.to_reference}" }
+ new_issue = move_service.execute(old_issue, new_project)
- it 'rewrites referenced issues creating cross project reference' do
- expect(new_issue.description)
- .to eq "Some description #{another_issue.to_reference(new_project)}"
- end
+ expect(new_issue.assignees).to eq([assignee])
end
- context "user references" do
- let(:another_issue) { create(:issue, project: old_project) }
- let(:description) { "Some description #{user.to_reference}" }
+ it 'ignores assignee without access to the new issue' do
+ new_issue = move_service.execute(old_issue, new_project)
- it "doesn't throw any errors for issues containing user references" do
- expect(new_issue.description)
- .to eq "Some description #{user.to_reference}"
- end
+ expect(new_issue.assignees).to be_empty
end
end
@@ -416,25 +192,5 @@ describe Issues::MoveService do
it { expect { move }.to raise_error(StandardError, /permissions/) }
end
end
-
- context 'movable issue with no assigned labels' do
- before do
- old_project.add_reporter(user)
- new_project.add_reporter(user)
-
- labels = Array.new(2) { |x| "label%d" % (x + 1) }
-
- labels.each do |label|
- new_project.labels << create(:label, title: label)
- end
- end
-
- include_context 'issue move executed'
-
- it 'does not assign labels to new issue' do
- expected_label_titles = new_issue.reload.labels.map(&:title)
- expect(expected_label_titles.size).to eq 0
- end
- end
end
end
diff --git a/spec/services/issues/related_branches_service_spec.rb b/spec/services/issues/related_branches_service_spec.rb
new file mode 100644
index 00000000000..c2e1eba6a63
--- /dev/null
+++ b/spec/services/issues/related_branches_service_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_helper'
+
+describe Issues::RelatedBranchesService do
+ let(:user) { create(:admin) }
+ let(:issue) { create(:issue) }
+
+ subject { described_class.new(issue.project, user) }
+
+ describe '#execute' do
+ before do
+ allow(issue.project.repository).to receive(:branch_names).and_return(["mpempe", "#{issue.iid}mepmep", issue.to_branch_name, "#{issue.iid}-branch"])
+ end
+
+ it "selects the right branches when there are no referenced merge requests" do
+ expect(subject.execute(issue)).to eq([issue.to_branch_name, "#{issue.iid}-branch"])
+ end
+
+ it "selects the right branches when there is a referenced merge request" do
+ merge_request = create(:merge_request, { description: "Closes ##{issue.iid}",
+ source_project: issue.project,
+ source_branch: "#{issue.iid}-branch" })
+ merge_request.create_cross_references!(user)
+
+ referenced_merge_requests = Issues::ReferencedMergeRequestsService
+ .new(issue.project, user)
+ .referenced_merge_requests(issue)
+
+ expect(referenced_merge_requests).not_to be_empty
+ expect(subject.execute(issue)).to eq([issue.to_branch_name])
+ end
+
+ it 'excludes stable branches from the related branches' do
+ allow(issue.project.repository).to receive(:branch_names)
+ .and_return(["#{issue.iid}-0-stable"])
+
+ expect(subject.execute(issue)).to eq []
+ end
+ end
+end
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index 07aa8449a66..bd519e7f077 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -343,7 +343,42 @@ describe Issues::UpdateService, :mailer do
end
end
- context 'when the milestone change' do
+ context 'when the milestone is removed' do
+ let!(:non_subscriber) { create(:user) }
+
+ let!(:subscriber) do
+ create(:user) do |u|
+ issue.toggle_subscription(u, project)
+ project.add_developer(u)
+ end
+ end
+
+ it_behaves_like 'system notes for milestones'
+
+ it 'sends notifications for subscribers of changed milestone' do
+ issue.milestone = create(:milestone)
+
+ issue.save
+
+ perform_enqueued_jobs do
+ update_issue(milestone_id: "")
+ end
+
+ should_email(subscriber)
+ should_not_email(non_subscriber)
+ end
+ end
+
+ context 'when the milestone is changed' do
+ let!(:non_subscriber) { create(:user) }
+
+ let!(:subscriber) do
+ create(:user) do |u|
+ issue.toggle_subscription(u, project)
+ project.add_developer(u)
+ end
+ end
+
it 'marks todos as done' do
update_issue(milestone: create(:milestone))
@@ -351,6 +386,15 @@ describe Issues::UpdateService, :mailer do
end
it_behaves_like 'system notes for milestones'
+
+ it 'sends notifications for subscribers of changed milestone' do
+ perform_enqueued_jobs do
+ update_issue(milestone: create(:milestone))
+ end
+
+ should_email(subscriber)
+ should_not_email(non_subscriber)
+ end
end
context 'when the labels change' do
@@ -374,7 +418,7 @@ describe Issues::UpdateService, :mailer do
let!(:non_subscriber) { create(:user) }
let!(:subscriber) do
- create(:user).tap do |u|
+ create(:user) do |u|
label.toggle_subscription(u, project)
project.add_developer(u)
end
diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb
index 9f1da7d9419..1894d8c8d0e 100644
--- a/spec/services/merge_requests/build_service_spec.rb
+++ b/spec/services/merge_requests/build_service_spec.rb
@@ -21,15 +21,20 @@ describe MergeRequests::BuildService do
let(:commit_2) { double(:commit_2, sha: 'f00ba7', safe_message: 'This is a bad commit message!') }
let(:commits) { nil }
+ let(:params) do
+ {
+ description: description,
+ source_branch: source_branch,
+ target_branch: target_branch,
+ source_project: source_project,
+ target_project: target_project,
+ milestone_id: milestone_id,
+ label_ids: label_ids
+ }
+ end
+
let(:service) do
- described_class.new(project, user,
- description: description,
- source_branch: source_branch,
- target_branch: target_branch,
- source_project: source_project,
- target_project: target_project,
- milestone_id: milestone_id,
- label_ids: label_ids)
+ described_class.new(project, user, params)
end
before do
@@ -56,6 +61,19 @@ describe MergeRequests::BuildService do
merge_request
end
+ it 'does not assign force_remove_source_branch' do
+ expect(merge_request.force_remove_source_branch?).to be_falsey
+ end
+
+ context 'with force_remove_source_branch parameter' do
+ let(:mr_params) { params.merge(force_remove_source_branch: '1') }
+ let(:merge_request) { described_class.new(project, user, mr_params).execute }
+
+ it 'assigns force_remove_source_branch' do
+ expect(merge_request.force_remove_source_branch?).to be_truthy
+ end
+ end
+
context 'missing source branch' do
let(:source_branch) { '' }
@@ -392,5 +410,13 @@ describe MergeRequests::BuildService do
expect(merge_request.source_project).to eq(project)
end
end
+
+ context 'when specifying target branch in the description' do
+ let(:description) { "A merge request targeting another branch\n\n/target_branch with-codeowners" }
+
+ it 'sets the attribute from the quick actions' do
+ expect(merge_request.target_branch).to eq('with-codeowners')
+ end
+ end
end
end
diff --git a/spec/services/merge_requests/create_from_issue_service_spec.rb b/spec/services/merge_requests/create_from_issue_service_spec.rb
index b1882df732d..393299cce00 100644
--- a/spec/services/merge_requests/create_from_issue_service_spec.rb
+++ b/spec/services/merge_requests/create_from_issue_service_spec.rb
@@ -61,7 +61,15 @@ describe MergeRequests::CreateFromIssueService do
expect(project.repository.branch_exists?(custom_source_branch)).to be_truthy
end
- it 'creates a system note' do
+ it 'creates the new_merge_request system note' do
+ expect(SystemNoteService).to receive(:new_merge_request).with(issue, project, user, instance_of(MergeRequest))
+
+ service.execute
+ end
+
+ it 'creates the new_issue_branch system note when the branch could be created but the merge_request cannot be created' do
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::DISABLED)
+
expect(SystemNoteService).to receive(:new_issue_branch).with(issue, project, user, issue.to_branch_name)
service.execute
diff --git a/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb b/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb
index 8838742a637..52bbd4e794d 100644
--- a/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb
+++ b/spec/services/merge_requests/merge_when_pipeline_succeeds_service_spec.rb
@@ -95,7 +95,7 @@ describe MergeRequests::MergeWhenPipelineSucceedsService do
sha: '1234abcdef', status: 'success')
end
- it 'it does not merge merge request' do
+ it 'it does not merge request' do
expect(MergeWorker).not_to receive(:perform_async)
service.trigger(old_pipeline)
end
diff --git a/spec/services/merge_requests/rebase_service_spec.rb b/spec/services/merge_requests/rebase_service_spec.rb
index 2703da7ae44..427a2d63a88 100644
--- a/spec/services/merge_requests/rebase_service_spec.rb
+++ b/spec/services/merge_requests/rebase_service_spec.rb
@@ -87,7 +87,7 @@ describe MergeRequests::RebaseService do
expect(merge_request.reload.rebase_commit_sha).to eq(head_sha)
end
- it 'logs correct author and commiter' do
+ it 'logs correct author and committer' do
head_commit = merge_request.source_project.repository.commit(merge_request.source_branch)
expect(head_commit.author_email).to eq('dmitriy.zaporozhets@gmail.com')
diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb
index 2536c6e2514..61c6ba7d550 100644
--- a/spec/services/merge_requests/refresh_service_spec.rb
+++ b/spec/services/merge_requests/refresh_service_spec.rb
@@ -306,6 +306,66 @@ describe MergeRequests::RefreshService do
end
end
+ context 'forked projects with the same source branch name as target branch' do
+ let!(:first_commit) do
+ @fork_project.repository.create_file(@user, 'test1.txt', 'Test data',
+ message: 'Test commit',
+ branch_name: 'master')
+ end
+ let!(:second_commit) do
+ @fork_project.repository.create_file(@user, 'test2.txt', 'More test data',
+ message: 'Second test commit',
+ branch_name: 'master')
+ end
+ let!(:forked_master_mr) do
+ create(:merge_request,
+ source_project: @fork_project,
+ source_branch: 'master',
+ target_branch: 'master',
+ target_project: @project)
+ end
+ let(:force_push_commit) { @project.commit('feature').id }
+
+ it 'should reload a new diff for a push to the forked project' do
+ expect do
+ service.new(@fork_project, @user).execute(@oldrev, first_commit, 'refs/heads/master')
+ reload_mrs
+ end.to change { forked_master_mr.merge_request_diffs.count }.by(1)
+ end
+
+ it 'should reload a new diff for a force push to the source branch' do
+ expect do
+ service.new(@fork_project, @user).execute(@oldrev, force_push_commit, 'refs/heads/master')
+ reload_mrs
+ end.to change { forked_master_mr.merge_request_diffs.count }.by(1)
+ end
+
+ it 'should reload a new diff for a force push to the target branch' do
+ expect do
+ service.new(@project, @user).execute(@oldrev, force_push_commit, 'refs/heads/master')
+ reload_mrs
+ end.to change { forked_master_mr.merge_request_diffs.count }.by(1)
+ end
+
+ it 'should reload a new diff for a push to the target project that contains a commit in the MR' do
+ expect do
+ service.new(@project, @user).execute(@oldrev, first_commit, 'refs/heads/master')
+ reload_mrs
+ end.to change { forked_master_mr.merge_request_diffs.count }.by(1)
+ end
+
+ it 'should not increase the diff count for a new push to target branch' do
+ new_commit = @project.repository.create_file(@user, 'new-file.txt', 'A new file',
+ message: 'This is a test',
+ branch_name: 'master')
+
+ expect do
+ service.new(@project, @user).execute(@newrev, new_commit, 'refs/heads/master')
+ reload_mrs
+ end.not_to change { forked_master_mr.merge_request_diffs.count }
+ end
+ end
+
context 'push to origin repo target branch after fork project was removed' do
before do
@fork_project.destroy
diff --git a/spec/services/merge_requests/reload_diffs_service_spec.rb b/spec/services/merge_requests/reload_diffs_service_spec.rb
index 21f369a3818..5acd01828cb 100644
--- a/spec/services/merge_requests/reload_diffs_service_spec.rb
+++ b/spec/services/merge_requests/reload_diffs_service_spec.rb
@@ -31,35 +31,25 @@ describe MergeRequests::ReloadDiffsService, :use_clean_rails_memory_store_cachin
end
context 'cache clearing' do
- before do
- allow_any_instance_of(Gitlab::Diff::File).to receive(:text?).and_return(true)
- allow_any_instance_of(Gitlab::Diff::File).to receive(:diffable?).and_return(true)
- end
-
- it 'retrieves the diff files to cache the highlighted result' do
- new_diff = merge_request.create_merge_request_diff
- cache_key = new_diff.diffs_collection.cache_key
-
- expect(merge_request).to receive(:create_merge_request_diff).and_return(new_diff)
- expect(Rails.cache).to receive(:read).with(cache_key).and_call_original
- expect(Rails.cache).to receive(:write).with(cache_key, anything, anything).and_call_original
-
- subject.execute
- end
-
it 'clears the cache for older diffs on the merge request' do
old_diff = merge_request.merge_request_diff
old_cache_key = old_diff.diffs_collection.cache_key
- new_diff = merge_request.create_merge_request_diff
- new_cache_key = new_diff.diffs_collection.cache_key
- expect(merge_request).to receive(:create_merge_request_diff).and_return(new_diff)
expect(Rails.cache).to receive(:delete).with(old_cache_key).and_call_original
- expect(Rails.cache).to receive(:read).with(new_cache_key).and_call_original
- expect(Rails.cache).to receive(:write).with(new_cache_key, anything, anything).and_call_original
subject.execute
end
+
+ it 'avoids N+1 queries', :request_store do
+ current_user
+ merge_request
+
+ control_count = ActiveRecord::QueryRecorder.new do
+ subject.execute
+ end.count
+
+ expect { subject.execute }.not_to exceed_query_limit(control_count)
+ end
end
end
end
diff --git a/spec/services/merge_requests/squash_service_spec.rb b/spec/services/merge_requests/squash_service_spec.rb
index 8ab09412f55..53bce15735c 100644
--- a/spec/services/merge_requests/squash_service_spec.rb
+++ b/spec/services/merge_requests/squash_service_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe MergeRequests::SquashService do
+ include GitHelpers
+
let(:service) { described_class.new(project, user, {}) }
let(:user) { project.owner }
let(:project) { create(:project, :repository) }
@@ -63,9 +65,7 @@ describe MergeRequests::SquashService do
end
it 'has the same diff as the merge request, but a different SHA' do
- rugged = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.rugged
- end
+ rugged = rugged_repo(project.repository)
mr_diff = rugged.diff(merge_request.diff_base_sha, merge_request.diff_head_sha)
squash_diff = rugged.diff(merge_request.diff_start_sha, squash_sha)
diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb
index 55dfab81c26..be5ad849ba7 100644
--- a/spec/services/merge_requests/update_service_spec.rb
+++ b/spec/services/merge_requests/update_service_spec.rb
@@ -315,7 +315,42 @@ describe MergeRequests::UpdateService, :mailer do
end
end
- context 'when the milestone change' do
+ context 'when the milestone is removed' do
+ let!(:non_subscriber) { create(:user) }
+
+ let!(:subscriber) do
+ create(:user) do |u|
+ merge_request.toggle_subscription(u, project)
+ project.add_developer(u)
+ end
+ end
+
+ it_behaves_like 'system notes for milestones'
+
+ it 'sends notifications for subscribers of changed milestone' do
+ merge_request.milestone = create(:milestone)
+
+ merge_request.save
+
+ perform_enqueued_jobs do
+ update_merge_request(milestone_id: "")
+ end
+
+ should_email(subscriber)
+ should_not_email(non_subscriber)
+ end
+ end
+
+ context 'when the milestone is changed' do
+ let!(:non_subscriber) { create(:user) }
+
+ let!(:subscriber) do
+ create(:user) do |u|
+ merge_request.toggle_subscription(u, project)
+ project.add_developer(u)
+ end
+ end
+
it 'marks pending todos as done' do
update_merge_request({ milestone: create(:milestone) })
@@ -323,6 +358,15 @@ describe MergeRequests::UpdateService, :mailer do
end
it_behaves_like 'system notes for milestones'
+
+ it 'sends notifications for subscribers of changed milestone' do
+ perform_enqueued_jobs do
+ update_merge_request(milestone: create(:milestone))
+ end
+
+ should_email(subscriber)
+ should_not_email(non_subscriber)
+ end
end
context 'when the labels change' do
@@ -549,8 +593,8 @@ describe MergeRequests::UpdateService, :mailer do
end
context 'setting `allow_collaboration`' do
- let(:target_project) { create(:project, :public) }
- let(:source_project) { fork_project(target_project) }
+ let(:target_project) { create(:project, :repository, :public) }
+ let(:source_project) { fork_project(target_project, nil, repository: true) }
let(:user) { create(:user) }
let(:merge_request) do
create(:merge_request,
diff --git a/spec/services/milestones/destroy_service_spec.rb b/spec/services/milestones/destroy_service_spec.rb
index 8680e428517..9d2be30c636 100644
--- a/spec/services/milestones/destroy_service_spec.rb
+++ b/spec/services/milestones/destroy_service_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Milestones::DestroyService do
let(:user) { create(:user) }
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:milestone) { create(:milestone, title: 'Milestone v1.0', project: project) }
before do
diff --git a/spec/services/notes/build_service_spec.rb b/spec/services/notes/build_service_spec.rb
index 6e1c1fe6c02..ff85c261cd4 100644
--- a/spec/services/notes/build_service_spec.rb
+++ b/spec/services/notes/build_service_spec.rb
@@ -4,6 +4,8 @@ describe Notes::BuildService do
let(:note) { create(:discussion_note_on_issue) }
let(:project) { note.project }
let(:author) { note.author }
+ let(:merge_request) { create(:merge_request, source_project: project) }
+ let(:mr_note) { create(:discussion_note_on_merge_request, noteable: merge_request, project: project, author: author) }
describe '#execute' do
context 'when in_reply_to_discussion_id is specified' do
@@ -12,6 +14,19 @@ describe Notes::BuildService do
new_note = described_class.new(project, author, note: 'Test', in_reply_to_discussion_id: note.discussion_id).execute
expect(new_note).to be_valid
expect(new_note.in_reply_to?(note)).to be_truthy
+ expect(new_note.resolved?).to be_falsey
+ end
+
+ context 'when discussion is resolved' do
+ before do
+ mr_note.resolve!(author)
+ end
+
+ it 'resolves the note' do
+ new_note = described_class.new(project, author, note: 'Test', in_reply_to_discussion_id: mr_note.discussion_id).execute
+ expect(new_note).to be_valid
+ expect(new_note.resolved?).to be_truthy
+ end
end
end
diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb
index b1290fd0d47..80b015d4cd0 100644
--- a/spec/services/notes/create_service_spec.rb
+++ b/spec/services/notes/create_service_spec.rb
@@ -57,6 +57,57 @@ describe Notes::CreateService do
end
end
+ context 'noteable highlight cache clearing' do
+ let(:project_with_repo) { create(:project, :repository) }
+ let(:merge_request) do
+ create(:merge_request, source_project: project_with_repo,
+ target_project: project_with_repo)
+ end
+
+ let(:position) do
+ Gitlab::Diff::Position.new(old_path: "files/ruby/popen.rb",
+ new_path: "files/ruby/popen.rb",
+ old_line: nil,
+ new_line: 14,
+ diff_refs: merge_request.diff_refs)
+ end
+
+ let(:new_opts) do
+ opts.merge(in_reply_to_discussion_id: nil,
+ type: 'DiffNote',
+ noteable_type: 'MergeRequest',
+ noteable_id: merge_request.id,
+ position: position.to_h)
+ end
+
+ before do
+ allow_any_instance_of(Gitlab::Diff::Position)
+ .to receive(:unfolded_diff?) { true }
+ end
+
+ it 'clears noteable diff cache when it was unfolded for the note position' do
+ expect_any_instance_of(Gitlab::Diff::HighlightCache).to receive(:clear)
+
+ described_class.new(project_with_repo, user, new_opts).execute
+ end
+
+ it 'does not clear cache when note is not the first of the discussion' do
+ prev_note =
+ create(:diff_note_on_merge_request, noteable: merge_request,
+ project: project_with_repo)
+ reply_opts =
+ opts.merge(in_reply_to_discussion_id: prev_note.discussion_id,
+ type: 'DiffNote',
+ noteable_type: 'MergeRequest',
+ noteable_id: merge_request.id,
+ position: position.to_h)
+
+ expect(merge_request).not_to receive(:diffs)
+
+ described_class.new(project_with_repo, user, reply_opts).execute
+ end
+ end
+
context 'note diff file' do
let(:project_with_repo) { create(:project, :repository) }
let(:merge_request) do
diff --git a/spec/services/notes/destroy_service_spec.rb b/spec/services/notes/destroy_service_spec.rb
index 64445be560e..b1f4e87e8ea 100644
--- a/spec/services/notes/destroy_service_spec.rb
+++ b/spec/services/notes/destroy_service_spec.rb
@@ -21,5 +21,38 @@ describe Notes::DestroyService do
expect { described_class.new(project, user).execute(note) }
.to change { user.todos_pending_count }.from(1).to(0)
end
+
+ context 'noteable highlight cache clearing' do
+ let(:repo_project) { create(:project, :repository) }
+ let(:merge_request) do
+ create(:merge_request, source_project: repo_project,
+ target_project: repo_project)
+ end
+
+ let(:note) do
+ create(:diff_note_on_merge_request, project: repo_project,
+ noteable: merge_request)
+ end
+
+ before do
+ allow(note.position).to receive(:unfolded_diff?) { true }
+ end
+
+ it 'clears noteable diff cache when it was unfolded for the note position' do
+ expect(merge_request).to receive_message_chain(:diffs, :clear_cache)
+
+ described_class.new(repo_project, user).execute(note)
+ end
+
+ it 'does not clear cache when note is not the first of the discussion' do
+ reply_note = create(:diff_note_on_merge_request, in_reply_to: note,
+ project: repo_project,
+ noteable: merge_request)
+
+ expect(merge_request).not_to receive(:diffs)
+
+ described_class.new(repo_project, user).execute(reply_note)
+ end
+ end
end
end
diff --git a/spec/services/notes/quick_actions_service_spec.rb b/spec/services/notes/quick_actions_service_spec.rb
index a8c994c101c..14d62763a5b 100644
--- a/spec/services/notes/quick_actions_service_spec.rb
+++ b/spec/services/notes/quick_actions_service_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Notes::QuickActionsService do
shared_context 'note on noteable' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:maintainer) { create(:user).tap { |u| project.add_maintainer(u) } }
let(:assignee) { create(:user) }
diff --git a/spec/services/notification_recipient_service_spec.rb b/spec/services/notification_recipient_service_spec.rb
index 14ba6b7bed2..cea5ea125b9 100644
--- a/spec/services/notification_recipient_service_spec.rb
+++ b/spec/services/notification_recipient_service_spec.rb
@@ -10,27 +10,50 @@ describe NotificationRecipientService do
let(:issue) { create(:issue, project: project, assignees: [assignee]) }
let(:note) { create(:note_on_issue, noteable: issue, project_id: issue.project_id) }
- def create_watcher
- watcher = create(:user)
- create(:notification_setting, source: project, user: watcher, level: :watch)
+ shared_examples 'no N+1 queries' do
+ it 'avoids N+1 queries', :request_store do
+ create_user
- other_projects.each do |other_project|
- create(:notification_setting, source: other_project, user: watcher, level: :watch)
+ service.build_new_note_recipients(note)
+
+ control_count = ActiveRecord::QueryRecorder.new do
+ service.build_new_note_recipients(note)
+ end
+
+ create_user
+
+ expect { service.build_new_note_recipients(note) }.not_to exceed_query_limit(control_count)
end
end
- it 'avoids N+1 queries', :request_store do
- create_watcher
+ context 'when there are multiple watchers' do
+ def create_user
+ watcher = create(:user)
+ create(:notification_setting, source: project, user: watcher, level: :watch)
+
+ other_projects.each do |other_project|
+ create(:notification_setting, source: other_project, user: watcher, level: :watch)
+ end
+ end
- service.build_new_note_recipients(note)
+ include_examples 'no N+1 queries'
+ end
- control_count = ActiveRecord::QueryRecorder.new do
- service.build_new_note_recipients(note)
+ context 'when there are multiple subscribers' do
+ def create_user
+ subscriber = create(:user)
+ issue.subscriptions.create(user: subscriber, project: project, subscribed: true)
end
- create_watcher
+ include_examples 'no N+1 queries'
- expect { service.build_new_note_recipients(note) }.not_to exceed_query_limit(control_count)
+ context 'when the project is private' do
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ include_examples 'no N+1 queries'
+ end
end
end
end
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index 68a361fa882..2d8da7673dc 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -13,6 +13,54 @@ describe NotificationService, :mailer do
end
end
+ shared_examples 'altered milestone notification on issue' do
+ it 'sends the email to the correct people' do
+ should_email(subscriber_to_new_milestone)
+ issue.assignees.each do |a|
+ should_email(a)
+ end
+ should_email(@u_watcher)
+ should_email(@u_guest_watcher)
+ should_email(@u_participant_mentioned)
+ should_email(@subscriber)
+ should_email(@subscribed_participant)
+ should_email(@watcher_and_subscriber)
+ should_not_email(@u_guest_custom)
+ should_not_email(@u_committer)
+ should_not_email(@unsubscriber)
+ should_not_email(@u_participating)
+ should_not_email(@u_lazy_participant)
+ should_not_email(issue.author)
+ should_not_email(@u_disabled)
+ should_not_email(@u_custom_global)
+ should_not_email(@u_mentioned)
+ end
+ end
+
+ shared_examples 'altered milestone notification on merge request' do
+ it 'sends the email to the correct people' do
+ should_email(subscriber_to_new_milestone)
+ merge_request.assignees.each do |a|
+ should_email(a)
+ end
+ should_email(@u_watcher)
+ should_email(@u_guest_watcher)
+ should_email(@u_participant_mentioned)
+ should_email(@subscriber)
+ should_email(@subscribed_participant)
+ should_email(@watcher_and_subscriber)
+ should_not_email(@u_guest_custom)
+ should_not_email(@u_committer)
+ should_not_email(@unsubscriber)
+ should_not_email(@u_participating)
+ should_not_email(@u_lazy_participant)
+ should_not_email(merge_request.author)
+ should_not_email(@u_disabled)
+ should_not_email(@u_custom_global)
+ should_not_email(@u_mentioned)
+ end
+ end
+
shared_examples 'notifications for new mentions' do
it 'sends no emails when no new mentions are present' do
send_notifications
@@ -952,6 +1000,96 @@ describe NotificationService, :mailer do
end
end
+ describe '#removed_milestone_issue' do
+ it_behaves_like 'altered milestone notification on issue' do
+ let(:milestone) { create(:milestone, project: project, issues: [issue]) }
+ let!(:subscriber_to_new_milestone) { create(:user) { |u| issue.toggle_subscription(u, project) } }
+
+ before do
+ notification.removed_milestone_issue(issue, issue.author)
+ end
+ end
+
+ context 'confidential issues' do
+ let(:author) { create(:user) }
+ let(:assignee) { create(:user) }
+ let(:non_member) { create(:user) }
+ let(:member) { create(:user) }
+ let(:guest) { create(:user) }
+ let(:admin) { create(:admin) }
+ let(:confidential_issue) { create(:issue, :confidential, project: project, title: 'Confidential issue', author: author, assignees: [assignee]) }
+ let(:milestone) { create(:milestone, project: project, issues: [confidential_issue]) }
+
+ it "emails subscribers of the issue's milestone that can read the issue" do
+ project.add_developer(member)
+ project.add_guest(guest)
+
+ confidential_issue.subscribe(non_member, project)
+ confidential_issue.subscribe(author, project)
+ confidential_issue.subscribe(assignee, project)
+ confidential_issue.subscribe(member, project)
+ confidential_issue.subscribe(guest, project)
+ confidential_issue.subscribe(admin, project)
+
+ reset_delivered_emails!
+
+ notification.removed_milestone_issue(confidential_issue, @u_disabled)
+
+ should_not_email(non_member)
+ should_not_email(guest)
+ should_email(author)
+ should_email(assignee)
+ should_email(member)
+ should_email(admin)
+ end
+ end
+ end
+
+ describe '#changed_milestone_issue' do
+ it_behaves_like 'altered milestone notification on issue' do
+ let(:new_milestone) { create(:milestone, project: project, issues: [issue]) }
+ let!(:subscriber_to_new_milestone) { create(:user) { |u| issue.toggle_subscription(u, project) } }
+
+ before do
+ notification.changed_milestone_issue(issue, new_milestone, issue.author)
+ end
+ end
+
+ context 'confidential issues' do
+ let(:author) { create(:user) }
+ let(:assignee) { create(:user) }
+ let(:non_member) { create(:user) }
+ let(:member) { create(:user) }
+ let(:guest) { create(:user) }
+ let(:admin) { create(:admin) }
+ let(:confidential_issue) { create(:issue, :confidential, project: project, title: 'Confidential issue', author: author, assignees: [assignee]) }
+ let(:new_milestone) { create(:milestone, project: project, issues: [confidential_issue]) }
+
+ it "emails subscribers of the issue's milestone that can read the issue" do
+ project.add_developer(member)
+ project.add_guest(guest)
+
+ confidential_issue.subscribe(non_member, project)
+ confidential_issue.subscribe(author, project)
+ confidential_issue.subscribe(assignee, project)
+ confidential_issue.subscribe(member, project)
+ confidential_issue.subscribe(guest, project)
+ confidential_issue.subscribe(admin, project)
+
+ reset_delivered_emails!
+
+ notification.changed_milestone_issue(confidential_issue, new_milestone, @u_disabled)
+
+ should_not_email(non_member)
+ should_not_email(guest)
+ should_email(author)
+ should_email(assignee)
+ should_email(member)
+ should_email(admin)
+ end
+ end
+ end
+
describe '#close_issue' do
before do
update_custom_notification(:close_issue, @u_guest_custom, resource: project)
@@ -1304,6 +1442,28 @@ describe NotificationService, :mailer do
end
end
+ describe '#removed_milestone_merge_request' do
+ it_behaves_like 'altered milestone notification on merge request' do
+ let(:milestone) { create(:milestone, project: project, merge_requests: [merge_request]) }
+ let!(:subscriber_to_new_milestone) { create(:user) { |u| merge_request.toggle_subscription(u, project) } }
+
+ before do
+ notification.removed_milestone_merge_request(merge_request, merge_request.author)
+ end
+ end
+ end
+
+ describe '#changed_milestone_merge_request' do
+ it_behaves_like 'altered milestone notification on merge request' do
+ let(:new_milestone) { create(:milestone, project: project, merge_requests: [merge_request]) }
+ let!(:subscriber_to_new_milestone) { create(:user) { |u| merge_request.toggle_subscription(u, project) } }
+
+ before do
+ notification.changed_milestone_merge_request(merge_request, new_milestone, merge_request.author)
+ end
+ end
+ end
+
describe '#merge_request_unmergeable' do
it "sends email to merge request author" do
notification.merge_request_unmergeable(merge_request)
diff --git a/spec/services/projects/after_import_service_spec.rb b/spec/services/projects/after_import_service_spec.rb
index cd52bc88f4c..4dd6c6dab86 100644
--- a/spec/services/projects/after_import_service_spec.rb
+++ b/spec/services/projects/after_import_service_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe Projects::AfterImportService do
+ include GitHelpers
+
subject { described_class.new(project) }
let(:project) { create(:project, :repository) }
@@ -53,7 +55,7 @@ describe Projects::AfterImportService do
end
def rugged
- Gitlab::GitalyClient::StorageSettings.allow_disk_access { repository.rugged }
+ rugged_repo(repository)
end
end
end
diff --git a/spec/services/projects/after_rename_service_spec.rb b/spec/services/projects/after_rename_service_spec.rb
new file mode 100644
index 00000000000..b4718a07204
--- /dev/null
+++ b/spec/services/projects/after_rename_service_spec.rb
@@ -0,0 +1,198 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Projects::AfterRenameService do
+ let(:rugged_config) { rugged_repo(project.repository).config }
+
+ describe '#execute' do
+ context 'using legacy storage' do
+ let(:project) { create(:project, :repository, :legacy_storage) }
+ let(:gitlab_shell) { Gitlab::Shell.new }
+ let(:project_storage) { project.send(:storage) }
+
+ before do
+ # Project#gitlab_shell returns a new instance of Gitlab::Shell on every
+ # call. This makes testing a bit easier.
+ allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
+
+ allow(project)
+ .to receive(:previous_changes)
+ .and_return('path' => ['foo'])
+
+ allow(project)
+ .to receive(:path_was)
+ .and_return('foo')
+
+ stub_feature_flags(skip_hashed_storage_upgrade: false)
+ end
+
+ it 'renames a repository' do
+ stub_container_registry_config(enabled: false)
+
+ expect(gitlab_shell).to receive(:mv_repository)
+ .ordered
+ .with(project.repository_storage, "#{project.namespace.full_path}/foo", "#{project.full_path}")
+ .and_return(true)
+
+ expect(gitlab_shell).to receive(:mv_repository)
+ .ordered
+ .with(project.repository_storage, "#{project.namespace.full_path}/foo.wiki", "#{project.full_path}.wiki")
+ .and_return(true)
+
+ expect_any_instance_of(SystemHooksService)
+ .to receive(:execute_hooks_for)
+ .with(project, :rename)
+
+ expect_any_instance_of(Gitlab::UploadsTransfer)
+ .to receive(:rename_project)
+ .with('foo', project.path, project.namespace.full_path)
+
+ expect(project).to receive(:expire_caches_before_rename)
+
+ described_class.new(project).execute
+ end
+
+ context 'container registry with images' do
+ let(:container_repository) { create(:container_repository) }
+
+ before do
+ stub_container_registry_config(enabled: true)
+ stub_container_registry_tags(repository: :any, tags: ['tag'])
+ project.container_repositories << container_repository
+ end
+
+ it 'raises a RenameFailedError' do
+ expect { described_class.new(project).execute }
+ .to raise_error(described_class::RenameFailedError)
+ end
+ end
+
+ context 'gitlab pages' do
+ before do
+ expect(project_storage).to receive(:rename_repo) { true }
+ end
+
+ it 'moves pages folder to new location' do
+ expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project)
+
+ described_class.new(project).execute
+ end
+ end
+
+ context 'attachments' do
+ before do
+ expect(project_storage).to receive(:rename_repo) { true }
+ end
+
+ it 'moves uploads folder to new location' do
+ expect_any_instance_of(Gitlab::UploadsTransfer).to receive(:rename_project)
+
+ described_class.new(project).execute
+ end
+ end
+
+ it 'updates project full path in .git/config' do
+ allow(project_storage).to receive(:rename_repo).and_return(true)
+
+ described_class.new(project).execute
+
+ expect(rugged_config['gitlab.fullpath']).to eq(project.full_path)
+ end
+ end
+
+ context 'using hashed storage' do
+ let(:project) { create(:project, :repository, skip_disk_validation: true) }
+ let(:gitlab_shell) { Gitlab::Shell.new }
+ let(:hash) { Digest::SHA2.hexdigest(project.id.to_s) }
+ let(:hashed_prefix) { File.join('@hashed', hash[0..1], hash[2..3]) }
+ let(:hashed_path) { File.join(hashed_prefix, hash) }
+
+ before do
+ # Project#gitlab_shell returns a new instance of Gitlab::Shell on every
+ # call. This makes testing a bit easier.
+ allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
+ allow(project).to receive(:previous_changes).and_return('path' => ['foo'])
+
+ stub_feature_flags(skip_hashed_storage_upgrade: false)
+ stub_application_setting(hashed_storage_enabled: true)
+ end
+
+ context 'migration to hashed storage' do
+ it 'calls HashedStorageMigrationService with correct options' do
+ project = create(:project, :repository, :legacy_storage)
+ allow(project).to receive(:previous_changes).and_return('path' => ['foo'])
+
+ expect_next_instance_of(::Projects::HashedStorageMigrationService) do |service|
+ expect(service).to receive(:execute).and_return(true)
+ end
+
+ described_class.new(project).execute
+ end
+ end
+
+ it 'renames a repository' do
+ stub_container_registry_config(enabled: false)
+
+ expect(gitlab_shell).not_to receive(:mv_repository)
+
+ expect_any_instance_of(SystemHooksService)
+ .to receive(:execute_hooks_for)
+ .with(project, :rename)
+
+ expect(project).to receive(:expire_caches_before_rename)
+
+ described_class.new(project).execute
+ end
+
+ context 'container registry with images' do
+ let(:container_repository) { create(:container_repository) }
+
+ before do
+ stub_container_registry_config(enabled: true)
+ stub_container_registry_tags(repository: :any, tags: ['tag'])
+ project.container_repositories << container_repository
+ end
+
+ it 'raises a RenameFailedError' do
+ expect { described_class.new(project).execute }
+ .to raise_error(described_class::RenameFailedError)
+ end
+ end
+
+ context 'gitlab pages' do
+ it 'moves pages folder to new location' do
+ expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project)
+
+ described_class.new(project).execute
+ end
+ end
+
+ context 'attachments' do
+ it 'keeps uploads folder location unchanged' do
+ expect_any_instance_of(Gitlab::UploadsTransfer).not_to receive(:rename_project)
+
+ described_class.new(project).execute
+ end
+
+ context 'when not rolled out' do
+ let(:project) { create(:project, :repository, storage_version: 1, skip_disk_validation: true) }
+
+ it 'moves pages folder to hashed storage' do
+ expect_next_instance_of(Projects::HashedStorage::MigrateAttachmentsService) do |service|
+ expect(service).to receive(:execute)
+ end
+
+ described_class.new(project).execute
+ end
+ end
+ end
+
+ it 'updates project full path in .git/config' do
+ described_class.new(project).execute
+
+ expect(rugged_config['gitlab.fullpath']).to eq(project.full_path)
+ end
+ end
+ end
+end
diff --git a/spec/services/projects/autocomplete_service_spec.rb b/spec/services/projects/autocomplete_service_spec.rb
index e98df375d48..373fe7cb7dd 100644
--- a/spec/services/projects/autocomplete_service_spec.rb
+++ b/spec/services/projects/autocomplete_service_spec.rb
@@ -148,7 +148,7 @@ describe Projects::AutocompleteService do
let!(:label1) { create(:label, project: project) }
let!(:label2) { create(:label, project: project) }
let!(:sub_group_label) { create(:group_label, group: sub_group) }
- let!(:parent_group_label) { create(:group_label, group: group.parent) }
+ let!(:parent_group_label) { create(:group_label, group: group.parent, group_id: group.id) }
before do
create(:group_member, group: group, user: user)
@@ -156,7 +156,7 @@ describe Projects::AutocompleteService do
it 'returns labels from project and ancestor groups' do
service = described_class.new(project, user)
- results = service.labels_as_hash
+ results = service.labels_as_hash(nil)
expected_labels = [label1, label2, parent_group_label]
expect_labels_to_equal(results, expected_labels)
diff --git a/spec/services/projects/create_from_template_service_spec.rb b/spec/services/projects/create_from_template_service_spec.rb
index 141ccf7c4d8..da078dd36c6 100644
--- a/spec/services/projects/create_from_template_service_spec.rb
+++ b/spec/services/projects/create_from_template_service_spec.rb
@@ -47,7 +47,7 @@ describe Projects::CreateFromTemplateService do
end
it 'is not scheduled' do
- expect(project.import_scheduled?).to be(false)
+ expect(project.import_scheduled?).to be_nil
end
it 'repository is empty' do
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index bb3f1501f0e..08de27ca44a 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe Projects::CreateService, '#execute' do
+ include GitHelpers
+
let(:gitlab_shell) { Gitlab::Shell.new }
let(:user) { create :user }
let(:opts) do
@@ -293,11 +295,20 @@ describe Projects::CreateService, '#execute' do
end
end
+ it 'calls the passed block' do
+ fake_block = double('block')
+ opts[:relations_block] = fake_block
+
+ expect_next_instance_of(Project) do |project|
+ expect(fake_block).to receive(:call).with(project)
+ end
+
+ create_project(user, opts)
+ end
+
it 'writes project full path to .git/config' do
project = create_project(user, opts)
- rugged = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.rugged
- end
+ rugged = rugged_repo(project.repository)
expect(rugged.config['gitlab.fullpath']).to eq project.full_path
end
diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb
index beff499f2be..12ddf8447bd 100644
--- a/spec/services/projects/destroy_service_spec.rb
+++ b/spec/services/projects/destroy_service_spec.rb
@@ -65,10 +65,12 @@ describe Projects::DestroyService do
context 'Sidekiq inline' do
before do
- # Run sidekiq immediatly to check that renamed repository will be removed
+ # Run sidekiq immediately to check that renamed repository will be removed
perform_enqueued_jobs { destroy_project(project, user, {}) }
end
+ it_behaves_like 'deleting the project'
+
context 'when has remote mirrors' do
let!(:project) do
create(:project, :repository, namespace: user.namespace).tap do |project|
@@ -82,13 +84,28 @@ describe Projects::DestroyService do
end
end
- it_behaves_like 'deleting the project'
-
it 'invalidates personal_project_count cache' do
expect(user).to receive(:invalidate_personal_projects_count)
destroy_project(project, user)
end
+
+ context 'when project has exports' do
+ let!(:project_with_export) do
+ create(:project, :repository, namespace: user.namespace).tap do |project|
+ create(:import_export_upload,
+ project: project,
+ export_file: fixture_file_upload('spec/fixtures/project_export.tar.gz'))
+ end
+ end
+ let!(:async) { true }
+
+ it 'destroys project and export' do
+ expect { destroy_project(project_with_export, user) }.to change(ImportExportUpload, :count).by(-1)
+
+ expect(Project.all).not_to include(project_with_export)
+ end
+ end
end
context 'Sidekiq fake' do
@@ -242,7 +259,6 @@ describe Projects::DestroyService do
before do
project.lfs_objects << create(:lfs_object)
- forked_project.forked_project_link.destroy
forked_project.reload
end
diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb
index 947cb61038d..a3d24ae312a 100644
--- a/spec/services/projects/fork_service_spec.rb
+++ b/spec/services/projects/fork_service_spec.rb
@@ -31,6 +31,10 @@ describe Projects::ForkService do
it { is_expected.not_to be_persisted }
it { expect(subject.errors[:forked_from_project_id]).to eq(['is forbidden']) }
+
+ it 'does not create a fork network' do
+ expect { subject }.not_to change { @from_project.reload.fork_network }
+ end
end
describe "successfully creates project in the user namespace" do
@@ -70,6 +74,12 @@ describe Projects::ForkService do
expect(fork_network.root_project).to eq(@from_project)
expect(fork_network.projects).to contain_exactly(@from_project, to_project)
end
+
+ it 'imports the repository of the forked project' do
+ to_project = fork_project(@from_project, @to_user, repository: true)
+
+ expect(to_project.empty_repo?).to be_falsy
+ end
end
context 'creating a fork of a fork' do
@@ -247,11 +257,13 @@ describe Projects::ForkService do
context 'if project is not forked' do
it 'creates fork relation' do
- expect(fork_to_project.forked?).to be false
+ expect(fork_to_project.forked?).to be_falsy
expect(forked_from_project(fork_to_project)).to be_nil
subject.execute(fork_to_project)
+ fork_to_project.reload
+
expect(fork_to_project.forked?).to be true
expect(forked_from_project(fork_to_project)).to eq fork_from_project
expect(fork_to_project.forked_from_project).to eq fork_from_project
@@ -272,6 +284,17 @@ describe Projects::ForkService do
.to change { fork_to_project.lfs_objects_projects.count }
.to(0)
end
+
+ context 'if the fork is not allowed' do
+ let(:fork_from_project) { create(:project, :private) }
+
+ it 'does not delete the LFS objects' do
+ create(:lfs_objects_project, project: fork_to_project)
+
+ expect { subject.execute(fork_to_project) }
+ .not_to change { fork_to_project.lfs_objects_projects.size }
+ end
+ end
end
end
end
diff --git a/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb b/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb
index 5f67c325223..0e82194e9ee 100644
--- a/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb
+++ b/spec/services/projects/hashed_storage/migrate_repository_service_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe Projects::HashedStorage::MigrateRepositoryService do
+ include GitHelpers
+
let(:gitlab_shell) { Gitlab::Shell.new }
let(:project) { create(:project, :legacy_storage, :repository, :wiki_repo) }
let(:legacy_storage) { Storage::LegacyProject.new(project) }
@@ -38,9 +40,7 @@ describe Projects::HashedStorage::MigrateRepositoryService do
it 'writes project full path to .git/config' do
service.execute
- rugged_config = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.rugged.config['gitlab.fullpath']
- end
+ rugged_config = rugged_repo(project.repository).config['gitlab.fullpath']
expect(rugged_config).to eq project.full_path
end
diff --git a/spec/services/projects/import_service_spec.rb b/spec/services/projects/import_service_spec.rb
index e2a600d12d1..06f865dc848 100644
--- a/spec/services/projects/import_service_spec.rb
+++ b/spec/services/projects/import_service_spec.rb
@@ -125,7 +125,7 @@ describe Projects::ImportService do
project.import_type = 'bitbucket'
end
- it 'succeeds if repository import is successfull' do
+ it 'succeeds if repository import is successful' do
expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).and_return(true)
expect_any_instance_of(Gitlab::BitbucketImport::Importer).to receive(:execute).and_return(true)
expect_any_instance_of(Projects::LfsPointers::LfsImportService).to receive(:execute).and_return({})
@@ -235,7 +235,7 @@ describe Projects::ImportService do
result = described_class.new(project, user).execute
expect(result[:status]).to eq :error
- expect(result[:message]).to include('Only allowed ports are 22, 80, 443')
+ expect(result[:message]).to include('Only allowed ports are 80, 443')
end
end
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index 92c5ac7354a..2e07d4f8013 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe Projects::TransferService do
+ include GitHelpers
+
let(:gitlab_shell) { Gitlab::Shell.new }
let(:user) { create(:user) }
let(:group) { create(:group) }
@@ -123,7 +125,7 @@ describe Projects::TransferService do
it { expect(project.errors.messages[:new_namespace].first).to eq 'Please select a new namespace for your project.' }
end
- context 'disallow transfering of project with tags' do
+ context 'disallow transferring of project with tags' do
let(:container_repository) { create(:container_repository) }
before do
@@ -291,8 +293,6 @@ describe Projects::TransferService do
end
def rugged_config
- Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.rugged.config
- end
+ rugged_repo(project.repository).config
end
end
diff --git a/spec/services/projects/unlink_fork_service_spec.rb b/spec/services/projects/unlink_fork_service_spec.rb
index 3ec6139bfa6..014aab44281 100644
--- a/spec/services/projects/unlink_fork_service_spec.rb
+++ b/spec/services/projects/unlink_fork_service_spec.rb
@@ -5,13 +5,12 @@ describe Projects::UnlinkForkService do
subject { described_class.new(forked_project, user) }
- let(:fork_link) { forked_project.forked_project_link }
let(:project) { create(:project, :public) }
let(:forked_project) { fork_project(project, user) }
let(:user) { create(:user) }
context 'with opened merge request on the source project' do
- let(:merge_request) { create(:merge_request, source_project: forked_project, target_project: fork_link.forked_from_project) }
+ let(:merge_request) { create(:merge_request, source_project: forked_project, target_project: forked_project.forked_from_project) }
let(:merge_request2) { create(:merge_request, source_project: forked_project, target_project: fork_project(project)) }
let(:merge_request_in_fork) { create(:merge_request, source_project: forked_project, target_project: forked_project) }
@@ -35,12 +34,6 @@ describe Projects::UnlinkForkService do
end
end
- it 'remove fork relation' do
- expect(forked_project.forked_project_link).to receive(:destroy)
-
- subject.execute
- end
-
it 'removes the link to the fork network' do
expect(forked_project.fork_network_member).to be_present
expect(forked_project.fork_network).to be_present
diff --git a/spec/services/projects/update_remote_mirror_service_spec.rb b/spec/services/projects/update_remote_mirror_service_spec.rb
index 56a36432462..c1e5f788146 100644
--- a/spec/services/projects/update_remote_mirror_service_spec.rb
+++ b/spec/services/projects/update_remote_mirror_service_spec.rb
@@ -16,8 +16,7 @@ describe Projects::UpdateRemoteMirrorService do
end
it "ensures the remote exists" do
- stub_fetch_remote(project, remote_name: remote_name)
- stub_find_remote_root_ref(project, remote_name: remote_name)
+ stub_fetch_remote(project, remote_name: remote_name, ssh_auth: remote_mirror)
expect(remote_mirror).to receive(:ensure_remote!)
@@ -25,35 +24,15 @@ describe Projects::UpdateRemoteMirrorService do
end
it "fetches the remote repository" do
- stub_find_remote_root_ref(project, remote_name: remote_name)
-
expect(project.repository)
.to receive(:fetch_remote)
- .with(remote_mirror.remote_name, no_tags: true)
+ .with(remote_mirror.remote_name, no_tags: true, ssh_auth: remote_mirror)
service.execute(remote_mirror)
end
- it "updates the default branch when HEAD has changed" do
- stub_fetch_remote(project, remote_name: remote_name)
- stub_find_remote_root_ref(project, remote_name: remote_name, ref: "existing-branch")
-
- expect { service.execute(remote_mirror) }
- .to change { project.default_branch }
- .from("master")
- .to("existing-branch")
- end
-
- it "does not update the default branch when HEAD does not change" do
- stub_fetch_remote(project, remote_name: remote_name)
- stub_find_remote_root_ref(project, remote_name: remote_name, ref: "master")
-
- expect { service.execute(remote_mirror) }.not_to change { project.default_branch }
- end
-
it "returns success when updated succeeds" do
- stub_fetch_remote(project, remote_name: remote_name)
- stub_find_remote_root_ref(project, remote_name: remote_name)
+ stub_fetch_remote(project, remote_name: remote_name, ssh_auth: remote_mirror)
result = service.execute(remote_mirror)
@@ -62,8 +41,7 @@ describe Projects::UpdateRemoteMirrorService do
context 'when syncing all branches' do
it "push all the branches the first time" do
- stub_fetch_remote(project, remote_name: remote_name)
- stub_find_remote_root_ref(project, remote_name: remote_name)
+ stub_fetch_remote(project, remote_name: remote_name, ssh_auth: remote_mirror)
expect(remote_mirror).to receive(:update_repository).with({})
@@ -73,8 +51,7 @@ describe Projects::UpdateRemoteMirrorService do
context 'when only syncing protected branches' do
it "sync updated protected branches" do
- stub_fetch_remote(project, remote_name: remote_name)
- stub_find_remote_root_ref(project, remote_name: remote_name)
+ stub_fetch_remote(project, remote_name: remote_name, ssh_auth: remote_mirror)
protected_branch = create_protected_branch(project)
remote_mirror.only_protected_branches = true
@@ -92,17 +69,10 @@ describe Projects::UpdateRemoteMirrorService do
end
end
- def stub_find_remote_root_ref(project, ref: 'master', remote_name:)
- allow(project.repository)
- .to receive(:find_remote_root_ref)
- .with(remote_name)
- .and_return(ref)
- end
-
- def stub_fetch_remote(project, remote_name:)
+ def stub_fetch_remote(project, remote_name:, ssh_auth:)
allow(project.repository)
.to receive(:fetch_remote)
- .with(remote_name, no_tags: true) { fetch_remote(project.repository, remote_name) }
+ .with(remote_name, no_tags: true, ssh_auth: ssh_auth) { fetch_remote(project.repository, remote_name) }
end
def fetch_remote(repository, remote_name)
diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb
index 695b9980548..d58ff2cedc0 100644
--- a/spec/services/projects/update_service_spec.rb
+++ b/spec/services/projects/update_service_spec.rb
@@ -340,6 +340,27 @@ describe Projects::UpdateService do
call_service
end
end
+
+ context 'when updating #pages_access_level' do
+ subject(:call_service) do
+ update_project(project, admin, project_feature_attributes: { pages_access_level: ProjectFeature::PRIVATE })
+ end
+
+ it 'updates the attribute' do
+ expect { call_service }
+ .to change { project.project_feature.pages_access_level }
+ .to(ProjectFeature::PRIVATE)
+ end
+
+ it 'calls Projects::UpdatePagesConfigurationService' do
+ expect(Projects::UpdatePagesConfigurationService)
+ .to receive(:new)
+ .with(project)
+ .and_call_original
+
+ call_service
+ end
+ end
end
describe '#run_auto_devops_pipeline?' do
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index 06cad9c00d2..938764f40b0 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe QuickActions::InterpretService do
@@ -313,7 +315,7 @@ describe QuickActions::InterpretService do
end
shared_examples 'award command' do
- it 'toggle award 100 emoji if content containts /award :100:' do
+ it 'toggle award 100 emoji if content contains /award :100:' do
_, updates = service.execute(content, issuable)
expect(updates).to eq(emoji_award: "100")
@@ -378,6 +380,14 @@ describe QuickActions::InterpretService do
end
end
+ shared_examples 'assign command' do
+ it 'assigns to a single user' do
+ _, updates = service.execute(content, issuable)
+
+ expect(updates).to eq(assignee_ids: [developer.id])
+ end
+ end
+
it_behaves_like 'reopen command' do
let(:content) { '/reopen' }
let(:issuable) { issue }
@@ -472,67 +482,56 @@ describe QuickActions::InterpretService do
let(:issuable) { issue }
end
- context 'assign command' do
- let(:content) { "/assign @#{developer.username}" }
-
- context 'Issue' do
- it 'fetches assignee and populates assignee_ids if content contains /assign' do
- _, updates = service.execute(content, issue)
-
- expect(updates[:assignee_ids]).to match_array([developer.id])
- end
+ context 'assign command with one user' do
+ it_behaves_like 'assign command' do
+ let(:content) { "/assign @#{developer.username}" }
+ let(:issuable) { issue }
end
- context 'Merge Request' do
- it 'fetches assignee and populates assignee_ids if content contains /assign' do
- _, updates = service.execute(content, merge_request)
-
- expect(updates).to eq(assignee_ids: [developer.id])
- end
+ it_behaves_like 'assign command' do
+ let(:content) { "/assign @#{developer.username}" }
+ let(:issuable) { merge_request }
end
end
+ # CE does not have multiple assignees
context 'assign command with multiple assignees' do
- let(:content) { "/assign @#{developer.username} @#{developer2.username}" }
-
before do
project.add_developer(developer2)
end
- context 'Issue' do
- it 'fetches assignee and populates assignee_ids if content contains /assign' do
- _, updates = service.execute(content, issue)
-
- expect(updates[:assignee_ids]).to match_array([developer.id])
- end
+ it_behaves_like 'assign command' do
+ let(:content) { "/assign @#{developer.username} @#{developer2.username}" }
+ let(:issuable) { issue }
end
- context 'Merge Request' do
- it 'fetches assignee and populates assignee_ids if content contains /assign' do
- _, updates = service.execute(content, merge_request)
-
- expect(updates).to eq(assignee_ids: [developer.id])
- end
+ it_behaves_like 'assign command' do
+ let(:content) { "/assign @#{developer.username} @#{developer2.username}" }
+ let(:issuable) { merge_request }
end
end
context 'assign command with me alias' do
- let(:content) { "/assign me" }
-
- context 'Issue' do
- it 'fetches assignee and populates assignee_ids if content contains /assign' do
- _, updates = service.execute(content, issue)
+ it_behaves_like 'assign command' do
+ let(:content) { '/assign me' }
+ let(:issuable) { issue }
+ end
- expect(updates).to eq(assignee_ids: [developer.id])
- end
+ it_behaves_like 'assign command' do
+ let(:content) { '/assign me' }
+ let(:issuable) { merge_request }
end
+ end
- context 'Merge Request' do
- it 'fetches assignee and populates assignee_ids if content contains /assign' do
- _, updates = service.execute(content, merge_request)
+ context 'assign command with me alias and whitespace' do
+ it_behaves_like 'assign command' do
+ let(:content) { '/assign me ' }
+ let(:issuable) { issue }
+ end
- expect(updates).to eq(assignee_ids: [developer.id])
- end
+ it_behaves_like 'assign command' do
+ let(:content) { '/assign me ' }
+ let(:issuable) { merge_request }
end
end
@@ -863,6 +862,13 @@ describe QuickActions::InterpretService do
let(:source_issuable) { create(:labeled_issue, project: project, labels: [inreview_label, todo_label]) }
let(:content) { "/copy_metadata #{source_issuable.to_reference}" }
+ let(:issuable) { build(:issue, project: project) }
+ end
+
+ it_behaves_like 'copy_metadata command' do
+ let(:source_issuable) { create(:labeled_issue, project: project, labels: [inreview_label, todo_label]) }
+
+ let(:content) { "/copy_metadata #{source_issuable.to_reference}" }
let(:issuable) { issue }
end
@@ -1207,6 +1213,46 @@ describe QuickActions::InterpretService do
end
end
end
+
+ it 'limits to commands passed ' do
+ content = "/shrug\n/close"
+
+ text, commands = service.execute(content, issue, only: [:shrug])
+
+ expect(commands).to be_empty
+ expect(text).to eq("#{described_class::SHRUG}\n/close")
+ end
+
+ context '/create_merge_request command' do
+ let(:branch_name) { '1-feature' }
+ let(:content) { "/create_merge_request #{branch_name}" }
+ let(:issuable) { issue }
+
+ context 'if issuable is not an Issue' do
+ let(:issuable) { merge_request }
+
+ it_behaves_like 'empty command'
+ end
+
+ context "when logged user cannot create_merge_requests in the project" do
+ let(:project) { create(:project, :archived) }
+
+ it_behaves_like 'empty command'
+ end
+
+ context 'when logged user cannot push code to the project' do
+ let(:project) { create(:project, :private) }
+ let(:service) { described_class.new(project, create(:user)) }
+
+ it_behaves_like 'empty command'
+ end
+
+ it 'populates create_merge_request with branch_name and issue iid' do
+ _, updates = service.execute(content, issuable)
+
+ expect(updates).to eq(create_merge_request: { branch_name: branch_name, issue_iid: issuable.iid })
+ end
+ end
end
describe '#explain' do
@@ -1389,7 +1435,7 @@ describe QuickActions::InterpretService do
it 'includes the formatted duration and proper verb' do
_, explanations = service.explain(content, issue)
- expect(explanations).to eq(['Substracts 2h spent time.'])
+ expect(explanations).to eq(['Subtracts 2h spent time.'])
end
end
@@ -1458,5 +1504,27 @@ describe QuickActions::InterpretService do
end
end
end
+
+ describe 'create a merge request' do
+ context 'with no branch name' do
+ let(:content) { '/create_merge_request' }
+
+ it 'uses the default branch name' do
+ _, explanations = service.explain(content, issue)
+
+ expect(explanations).to eq(['Creates a branch and a merge request to resolve this issue'])
+ end
+ end
+
+ context 'with a branch name' do
+ let(:content) { '/create_merge_request foo' }
+
+ it 'uses the given branch name' do
+ _, explanations = service.explain(content, issue)
+
+ expect(explanations).to eq(["Creates branch 'foo' and a merge request to resolve this issue"])
+ end
+ end
+ end
end
end
diff --git a/spec/services/resource_events/merge_into_notes_service_spec.rb b/spec/services/resource_events/merge_into_notes_service_spec.rb
index 0d333d541c9..c76f6e6f77e 100644
--- a/spec/services/resource_events/merge_into_notes_service_spec.rb
+++ b/spec/services/resource_events/merge_into_notes_service_spec.rb
@@ -66,5 +66,14 @@ describe ResourceEvents::MergeIntoNotesService do
expect(notes.count).to eq 1
expect(notes.first.discussion_id).to eq event.discussion_id
end
+
+ it "preloads the note author's status" do
+ event = create_event(created_at: time)
+ create(:user_status, user: event.user)
+
+ notes = described_class.new(resource, user).execute
+
+ expect(notes.first.author.association(:status)).to be_loaded
+ end
end
end
diff --git a/spec/services/submodules/update_service_spec.rb b/spec/services/submodules/update_service_spec.rb
new file mode 100644
index 00000000000..cf92350c1b2
--- /dev/null
+++ b/spec/services/submodules/update_service_spec.rb
@@ -0,0 +1,212 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+describe Submodules::UpdateService do
+ let(:project) { create(:project, :repository) }
+ let(:repository) { project.repository }
+ let(:user) { create(:user, :commit_email) }
+ let(:branch_name) { project.default_branch }
+ let(:submodule) { 'six' }
+ let(:commit_sha) { 'e25eda1fece24ac7a03624ed1320f82396f35bd8' }
+ let(:commit_message) { 'whatever' }
+ let(:current_sha) { repository.blob_at('HEAD', submodule).id }
+ let(:commit_params) do
+ {
+ submodule: submodule,
+ commit_message: commit_message,
+ commit_sha: commit_sha,
+ branch_name: branch_name
+ }
+ end
+
+ subject { described_class.new(project, user, commit_params) }
+
+ describe "#execute" do
+ shared_examples 'returns error result' do
+ it do
+ result = subject.execute
+
+ expect(result[:status]).to eq :error
+ expect(result[:message]).to eq error_message
+ end
+ end
+
+ context 'when the user is not authorized' do
+ it_behaves_like 'returns error result' do
+ let(:error_message) { 'You are not allowed to push into this branch' }
+ end
+ end
+
+ context 'when the user is authorized' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ context 'when the branch is protected' do
+ before do
+ create(:protected_branch, :no_one_can_push, project: project, name: branch_name)
+ end
+
+ it_behaves_like 'returns error result' do
+ let(:error_message) { 'You are not allowed to push into this branch' }
+ end
+ end
+
+ context 'validations' do
+ context 'when submodule' do
+ context 'is empty' do
+ let(:submodule) { '' }
+
+ it_behaves_like 'returns error result' do
+ let(:error_message) { 'Invalid parameters' }
+ end
+ end
+
+ context 'is not present' do
+ let(:submodule) { nil }
+
+ it_behaves_like 'returns error result' do
+ let(:error_message) { 'Invalid parameters' }
+ end
+ end
+
+ context 'is invalid' do
+ let(:submodule) { 'VERSION' }
+
+ it_behaves_like 'returns error result' do
+ let(:error_message) { 'Invalid submodule path' }
+ end
+ end
+
+ context 'does not exist' do
+ let(:submodule) { 'non-existent-submodule' }
+
+ it_behaves_like 'returns error result' do
+ let(:error_message) { 'Invalid submodule path' }
+ end
+ end
+
+ context 'has traversal path' do
+ let(:submodule) { '../six' }
+
+ it_behaves_like 'returns error result' do
+ let(:error_message) { 'Invalid parameters' }
+ end
+ end
+ end
+
+ context 'commit_sha' do
+ context 'is empty' do
+ let(:commit_sha) { '' }
+
+ it_behaves_like 'returns error result' do
+ let(:error_message) { 'Invalid parameters' }
+ end
+ end
+
+ context 'is not present' do
+ let(:commit_sha) { nil }
+
+ it_behaves_like 'returns error result' do
+ let(:error_message) { 'Invalid parameters' }
+ end
+ end
+
+ context 'is invalid' do
+ let(:commit_sha) { '1' }
+
+ it_behaves_like 'returns error result' do
+ let(:error_message) { 'Invalid parameters' }
+ end
+ end
+
+ context 'is the same as the current ref' do
+ let(:commit_sha) { current_sha }
+
+ it_behaves_like 'returns error result' do
+ let(:error_message) { "The submodule #{submodule} is already at #{commit_sha}" }
+ end
+ end
+ end
+
+ context 'branch_name' do
+ context 'is empty' do
+ let(:branch_name) { '' }
+
+ it_behaves_like 'returns error result' do
+ let(:error_message) { 'You can only create or edit files when you are on a branch' }
+ end
+ end
+
+ context 'is not present' do
+ let(:branch_name) { nil }
+
+ it_behaves_like 'returns error result' do
+ let(:error_message) { 'You can only create or edit files when you are on a branch' }
+ end
+ end
+
+ context 'does not exist' do
+ let(:branch_name) { 'non/existent-branch' }
+
+ it_behaves_like 'returns error result' do
+ let(:error_message) { 'You can only create or edit files when you are on a branch' }
+ end
+ end
+
+ context 'when commit message is empty' do
+ let(:commit_message) { '' }
+
+ it 'a default commit message is set' do
+ message = "Update submodule #{submodule} with oid #{commit_sha}"
+
+ expect(repository).to receive(:update_submodule).with(any_args, hash_including(message: message))
+
+ subject.execute
+ end
+ end
+ end
+ end
+
+ context 'when there is an unexpected error' do
+ before do
+ allow(repository).to receive(:update_submodule).and_raise(StandardError, 'error message')
+ end
+
+ it_behaves_like 'returns error result' do
+ let(:error_message) { 'error message' }
+ end
+ end
+
+ it 'updates the submodule reference' do
+ result = subject.execute
+
+ expect(result[:status]).to eq :success
+ expect(result[:result]).to eq repository.head_commit.id
+ expect(repository.blob_at('HEAD', submodule).id).to eq commit_sha
+ end
+
+ context 'when submodule is inside a directory' do
+ let(:submodule) { 'test_inside_folder/another_folder/six' }
+ let(:branch_name) { 'submodule_inside_folder' }
+
+ it 'updates the submodule reference' do
+ expect(repository.blob_at(branch_name, submodule).id).not_to eq commit_sha
+
+ subject.execute
+
+ expect(repository.blob_at(branch_name, submodule).id).to eq commit_sha
+ end
+ end
+
+ context 'when repository is empty' do
+ let(:project) { create(:project, :empty_repo) }
+ let(:branch_name) { 'master' }
+
+ it_behaves_like 'returns error result' do
+ let(:error_message) { 'The repository is empty' }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/system_hooks_service_spec.rb b/spec/services/system_hooks_service_spec.rb
index e0335880e8e..81b2c17fdb5 100644
--- a/spec/services/system_hooks_service_spec.rb
+++ b/spec/services/system_hooks_service_spec.rb
@@ -32,7 +32,7 @@ describe SystemHooksService do
end
it do
- project.old_path_with_namespace = 'transfered_from_path'
+ project.old_path_with_namespace = 'transferred_from_path'
expect(event_data(project, :transfer)).to include(
:event_name, :name, :created_at, :updated_at, :path, :project_id,
:owner_name, :owner_email, :project_visibility,
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index f4b7cb8c90a..0fbfcb34e50 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -324,7 +324,7 @@ describe SystemNoteService do
end
it "posts the 'merge when pipeline succeeds' system note" do
- expect(subject.note).to eq "canceled the automatic merge"
+ expect(subject.note).to eq "canceled the automatic merge"
end
end
@@ -432,6 +432,20 @@ describe SystemNoteService do
end
end
+ describe '.new_merge_request' do
+ subject { described_class.new_merge_request(noteable, project, author, merge_request) }
+
+ let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
+
+ it_behaves_like 'a system note' do
+ let(:action) { 'merge' }
+ end
+
+ it 'sets the new merge request note text' do
+ expect(subject.note).to eq("created merge request #{merge_request.to_reference} to address this issue")
+ end
+ end
+
describe '.cross_reference' do
subject { described_class.cross_reference(noteable, mentioner, author) }
diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb
index 1746721b0d0..c52515aefd8 100644
--- a/spec/services/todo_service_spec.rb
+++ b/spec/services/todo_service_spec.rb
@@ -10,7 +10,7 @@ describe TodoService do
let(:john_doe) { create(:user) }
let(:skipped) { create(:user) }
let(:skip_users) { [skipped] }
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:mentions) { 'FYI: ' + [author, assignee, john_doe, member, guest, non_member, admin, skipped].map(&:to_reference).join(' ') }
let(:directly_addressed) { [author, assignee, john_doe, member, guest, non_member, admin, skipped].map(&:to_reference).join(' ') }
let(:directly_addressed_and_mentioned) { member.to_reference + ", what do you think? cc: " + [guest, admin, skipped].map(&:to_reference).join(' ') }
diff --git a/spec/services/update_deployment_service_spec.rb b/spec/services/update_deployment_service_spec.rb
new file mode 100644
index 00000000000..3c55dd9659a
--- /dev/null
+++ b/spec/services/update_deployment_service_spec.rb
@@ -0,0 +1,217 @@
+require 'spec_helper'
+
+describe UpdateDeploymentService do
+ let(:user) { create(:user) }
+ let(:options) { { name: 'production' } }
+
+ let(:job) do
+ create(:ci_build,
+ ref: 'master',
+ tag: false,
+ environment: 'production',
+ options: { environment: options },
+ project: project)
+ end
+
+ let(:project) { create(:project, :repository) }
+ let(:environment) { deployment.environment }
+ let(:deployment) { job.deployment }
+ let(:service) { described_class.new(deployment) }
+
+ before do
+ job.success! # Create/Succeed deployment
+ end
+
+ describe '#execute' do
+ subject { service.execute }
+
+ let(:store) { Gitlab::EtagCaching::Store.new }
+
+ it 'invalidates the environment etag cache' do
+ old_value = store.get(environment.etag_cache_key)
+
+ subject
+
+ expect(store.get(environment.etag_cache_key)).not_to eq(old_value)
+ end
+
+ it 'creates ref' do
+ expect_any_instance_of(Repository)
+ .to receive(:create_ref)
+ .with(deployment.ref, deployment.send(:ref_path))
+
+ subject
+ end
+
+ it 'updates merge request metrics' do
+ expect_any_instance_of(Deployment)
+ .to receive(:update_merge_request_metrics!)
+
+ subject
+ end
+
+ context 'when start action is defined' do
+ let(:options) { { name: 'production', action: 'start' } }
+
+ context 'and environment is stopped' do
+ before do
+ environment.stop
+ end
+
+ it 'makes environment available' do
+ subject
+
+ expect(environment.reload).to be_available
+ end
+ end
+ end
+
+ context 'when variables are used' do
+ let(:options) do
+ { name: 'review-apps/$CI_COMMIT_REF_NAME',
+ url: 'http://$CI_COMMIT_REF_NAME.review-apps.gitlab.com' }
+ end
+
+ before do
+ environment.update(name: 'review-apps/master')
+ job.update(environment: 'review-apps/$CI_COMMIT_REF_NAME')
+ end
+
+ it 'does not create a new environment' do
+ expect { subject }.not_to change { Environment.count }
+ end
+
+ it 'updates external url' do
+ subject
+
+ expect(subject.environment.name).to eq('review-apps/master')
+ expect(subject.environment.external_url).to eq('http://master.review-apps.gitlab.com')
+ end
+ end
+ end
+
+ describe '#expanded_environment_url' do
+ subject { service.send(:expanded_environment_url) }
+
+ context 'when yaml environment uses $CI_COMMIT_REF_NAME' do
+ let(:job) do
+ create(:ci_build,
+ ref: 'master',
+ environment: 'production',
+ project: project,
+ options: { environment: { name: 'production', url: 'http://review/$CI_COMMIT_REF_NAME' } })
+ end
+
+ it { is_expected.to eq('http://review/master') }
+ end
+
+ context 'when yaml environment uses $CI_ENVIRONMENT_SLUG' do
+ let(:job) do
+ create(:ci_build,
+ ref: 'master',
+ environment: 'prod-slug',
+ project: project,
+ options: { environment: { name: 'prod-slug', url: 'http://review/$CI_ENVIRONMENT_SLUG' } })
+ end
+
+ it { is_expected.to eq('http://review/prod-slug') }
+ end
+
+ context 'when yaml environment uses yaml_variables containing symbol keys' do
+ let(:job) do
+ create(:ci_build,
+ yaml_variables: [{ key: :APP_HOST, value: 'host' }],
+ environment: 'production',
+ project: project,
+ options: { environment: { name: 'production', url: 'http://review/$APP_HOST' } })
+ end
+
+ it { is_expected.to eq('http://review/host') }
+ end
+
+ context 'when yaml environment does not have url' do
+ let(:job) { create(:ci_build, environment: 'staging', project: project) }
+
+ it 'returns the external_url from persisted environment' do
+ is_expected.to be_nil
+ end
+ end
+ end
+
+ describe "merge request metrics" do
+ let(:merge_request) { create(:merge_request, target_branch: 'master', source_branch: 'feature', source_project: project) }
+
+ context "while updating the 'first_deployed_to_production_at' time" do
+ before do
+ merge_request.metrics.update!(merged_at: 1.hour.ago)
+ end
+
+ context "for merge requests merged before the current deploy" do
+ it "sets the time if the deploy's environment is 'production'" do
+ service.execute
+
+ expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_like_time(deployment.finished_at)
+ end
+
+ context 'when job deploys to staging' do
+ let(:job) do
+ create(:ci_build,
+ ref: 'master',
+ tag: false,
+ environment: 'staging',
+ options: { environment: { name: 'staging' } },
+ project: project)
+ end
+
+ it "doesn't set the time if the deploy's environment is not 'production'" do
+ service.execute
+
+ expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_nil
+ end
+ end
+
+ it 'does not raise errors if the merge request does not have a metrics record' do
+ merge_request.metrics.destroy
+
+ expect(merge_request.reload.metrics).to be_nil
+ expect { service.execute }.not_to raise_error
+ end
+ end
+
+ context "for merge requests merged before the previous deploy" do
+ context "if the 'first_deployed_to_production_at' time is already set" do
+ it "does not overwrite the older 'first_deployed_to_production_at' time" do
+ # Previous deploy
+ service.execute
+
+ expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_like_time(deployment.finished_at)
+
+ # Current deploy
+ Timecop.travel(12.hours.from_now) do
+ service.execute
+
+ expect(merge_request.reload.metrics.first_deployed_to_production_at).to be_like_time(deployment.finished_at)
+ end
+ end
+ end
+
+ context "if the 'first_deployed_to_production_at' time is not already set" do
+ it "does not overwrite the older 'first_deployed_to_production_at' time" do
+ # Previous deploy
+ time = 5.minutes.from_now
+ Timecop.freeze(time) { service.execute }
+
+ expect(merge_request.reload.metrics.merged_at).to be < merge_request.reload.metrics.first_deployed_to_production_at
+
+ previous_time = merge_request.reload.metrics.first_deployed_to_production_at
+
+ # Current deploy
+ Timecop.freeze(time + 12.hours) { service.execute }
+
+ expect(merge_request.reload.metrics.first_deployed_to_production_at).to eq(previous_time)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/users/build_service_spec.rb b/spec/services/users/build_service_spec.rb
index b987fe45138..b7b9817efdb 100644
--- a/spec/services/users/build_service_spec.rb
+++ b/spec/services/users/build_service_spec.rb
@@ -8,12 +8,55 @@ describe Users::BuildService do
context 'with an admin user' do
let(:admin_user) { create(:admin) }
- let(:service) { described_class.new(admin_user, params) }
+ let(:service) { described_class.new(admin_user, ActionController::Parameters.new(params).permit!) }
it 'returns a valid user' do
expect(service.execute).to be_valid
end
+ context 'allowed params' do
+ let(:params) do
+ {
+ access_level: 1,
+ admin: 1,
+ avatar: anything,
+ bio: 1,
+ can_create_group: 1,
+ color_scheme_id: 1,
+ email: 1,
+ external: 1,
+ force_random_password: 1,
+ hide_no_password: 1,
+ hide_no_ssh_key: 1,
+ linkedin: 1,
+ name: 1,
+ password: 1,
+ password_automatically_set: 1,
+ password_expires_at: 1,
+ projects_limit: 1,
+ remember_me: 1,
+ skip_confirmation: 1,
+ skype: 1,
+ theme_id: 1,
+ twitter: 1,
+ username: 1,
+ website_url: 1,
+ private_profile: 1,
+ organization: 1,
+ location: 1,
+ public_email: 1
+ }
+ end
+
+ it 'sets all allowed attributes' do
+ admin_user # call first so the admin gets created before setting `expect`
+
+ expect(User).to receive(:new).with(hash_including(params)).and_call_original
+
+ service.execute
+ end
+ end
+
context 'with "user_default_external" application setting' do
using RSpec::Parameterized::TableSyntax
@@ -116,9 +159,9 @@ describe Users::BuildService do
true | true | 'fl@example.com' | '' | true
true | false | 'fl@example.com' | '' | true
- true | nil | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | true
- true | true | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | true
- true | false | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | true
+ true | nil | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
+ true | true | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
+ true | false | 'fl@example.com' | '^(?:(?!\.ext@).)*$\r?' | false
true | nil | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | true
true | true | 'tester.ext@domain.com' | '^(?:(?!\.ext@).)*$\r?' | true
diff --git a/spec/services/users/set_status_service_spec.rb b/spec/services/users/set_status_service_spec.rb
index 8a8458ab9de..7c26be48345 100644
--- a/spec/services/users/set_status_service_spec.rb
+++ b/spec/services/users/set_status_service_spec.rb
@@ -7,7 +7,7 @@ describe Users::SetStatusService do
subject(:service) { described_class.new(current_user, params) }
describe '#execute' do
- context 'when when params are set' do
+ context 'when params are set' do
let(:params) { { emoji: 'taurus', message: 'a random status' } }
it 'creates a status' do
diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb
index 622e56e1da5..b1cc6d2eb83 100644
--- a/spec/services/web_hook_service_spec.rb
+++ b/spec/services/web_hook_service_spec.rb
@@ -97,7 +97,7 @@ describe WebHookService do
end
it 'handles exceptions' do
- exceptions = [SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Net::OpenTimeout, Net::ReadTimeout, Gitlab::HTTP::BlockedUrlError]
+ exceptions = [SocketError, OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Net::OpenTimeout, Net::ReadTimeout, Gitlab::HTTP::BlockedUrlError, Gitlab::HTTP::RedirectionTooDeep]
exceptions.each do |exception_class|
exception = exception_class.new('Exception message')
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index d1337325973..3fedb9ed48c 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -34,6 +34,11 @@ Rainbow.enabled = false
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
# Requires helpers, and shared contexts/examples first since they're used in other support files
+
+# Load these first since they may be required by other helpers
+require Rails.root.join("spec/support/helpers/git_helpers.rb")
+
+# Then the rest
Dir[Rails.root.join("spec/support/helpers/*.rb")].each { |f| require f }
Dir[Rails.root.join("spec/support/shared_contexts/*.rb")].each { |f| require f }
Dir[Rails.root.join("spec/support/shared_examples/*.rb")].each { |f| require f }
@@ -230,6 +235,10 @@ RSpec.configure do |config|
example.run if Gitlab::Database.mysql?
end
+ config.around(:each, :rails5) do |example|
+ example.run if Gitlab.rails5?
+ end
+
# This makes sure the `ApplicationController#can?` method is stubbed with the
# original implementation for all view specs.
config.before(:each, type: :view) do
diff --git a/spec/support/active_record_enum.rb b/spec/support/active_record_enum.rb
new file mode 100644
index 00000000000..fb1189c7f17
--- /dev/null
+++ b/spec/support/active_record_enum.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+shared_examples 'having unique enum values' do
+ described_class.defined_enums.each do |name, enum|
+ it "has unique values in #{name.inspect}" do
+ duplicated = enum.group_by(&:last).select { |key, value| value.size > 1 }
+
+ expect(duplicated).to be_empty,
+ "Duplicated values detected: #{duplicated.values.map(&Hash.method(:[]))}"
+ end
+ end
+end
diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb
index c0ceb0f6605..18a7a392c12 100644
--- a/spec/support/capybara.rb
+++ b/spec/support/capybara.rb
@@ -100,7 +100,7 @@ RSpec.configure do |config|
# capybara/rspec already calls Capybara.reset_sessions! in an `after` hook,
# but `block_and_wait_for_requests_complete` is called before it so by
- # calling it explicitely here, we prevent any new requests from being fired
+ # calling it explicitly here, we prevent any new requests from being fired
# See https://github.com/teamcapybara/capybara/blob/ffb41cfad620de1961bb49b1562a9fa9b28c0903/lib/capybara/rspec.rb#L20-L25
# We don't reset the session when the example failed, because we need capybara-screenshot to have access to it.
Capybara.reset_sessions! unless example.exception
diff --git a/spec/support/controllers/githubish_import_controller_shared_examples.rb b/spec/support/controllers/githubish_import_controller_shared_examples.rb
index 1c1b68c12a2..140490f2dc2 100644
--- a/spec/support/controllers/githubish_import_controller_shared_examples.rb
+++ b/spec/support/controllers/githubish_import_controller_shared_examples.rb
@@ -22,6 +22,18 @@ shared_examples 'a GitHub-ish import controller: POST personal_access_token' do
expect(session[:"#{provider}_access_token"]).to eq(token)
expect(controller).to redirect_to(status_import_url)
end
+
+ it "strips access token with spaces" do
+ token = 'asdfasdf9876'
+
+ allow_any_instance_of(Gitlab::LegacyGithubImport::Client)
+ .to receive(:user).and_return(true)
+
+ post :personal_access_token, personal_access_token: " #{token} "
+
+ expect(session[:"#{provider}_access_token"]).to eq(token)
+ expect(controller).to redirect_to(status_import_url)
+ end
end
shared_examples 'a GitHub-ish import controller: GET new' do
diff --git a/spec/support/controllers/sessionless_auth_controller_shared_examples.rb b/spec/support/controllers/sessionless_auth_controller_shared_examples.rb
new file mode 100644
index 00000000000..7e4958f177a
--- /dev/null
+++ b/spec/support/controllers/sessionless_auth_controller_shared_examples.rb
@@ -0,0 +1,92 @@
+shared_examples 'authenticates sessionless user' do |path, format, params|
+ params ||= {}
+
+ before do
+ stub_authentication_activity_metrics(debug: false)
+ end
+
+ let(:user) { create(:user) }
+ let(:personal_access_token) { create(:personal_access_token, user: user) }
+ let(:default_params) { { format: format }.merge(params.except(:public) || {}) }
+
+ context "when the 'personal_access_token' param is populated with the personal access token" do
+ it 'logs the user in' do
+ expect(authentication_metrics)
+ .to increment(:user_authenticated_counter)
+ .and increment(:user_session_override_counter)
+ .and increment(:user_sessionless_authentication_counter)
+
+ get path, default_params.merge(private_token: personal_access_token.token)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(controller.current_user).to eq(user)
+ end
+
+ it 'does not log the user in if page is public', if: params[:public] do
+ get path, default_params
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(controller.current_user).to be_nil
+ end
+ end
+
+ context 'when the personal access token has no api scope', unless: params[:public] do
+ it 'does not log the user in' do
+ expect(authentication_metrics)
+ .to increment(:user_unauthenticated_counter)
+
+ personal_access_token.update(scopes: [:read_user])
+
+ get path, default_params.merge(private_token: personal_access_token.token)
+
+ expect(response).not_to have_gitlab_http_status(200)
+ end
+ end
+
+ context "when the 'PERSONAL_ACCESS_TOKEN' header is populated with the personal access token" do
+ it 'logs the user in' do
+ expect(authentication_metrics)
+ .to increment(:user_authenticated_counter)
+ .and increment(:user_session_override_counter)
+ .and increment(:user_sessionless_authentication_counter)
+
+ @request.headers['PRIVATE-TOKEN'] = personal_access_token.token
+ get path, default_params
+
+ expect(response).to have_gitlab_http_status(200)
+ end
+ end
+
+ context "when the 'feed_token' param is populated with the feed token", if: format == :rss do
+ it "logs the user in" do
+ expect(authentication_metrics)
+ .to increment(:user_authenticated_counter)
+ .and increment(:user_session_override_counter)
+ .and increment(:user_sessionless_authentication_counter)
+
+ get path, default_params.merge(feed_token: user.feed_token)
+
+ expect(response).to have_gitlab_http_status 200
+ end
+ end
+
+ context "when the 'feed_token' param is populated with an invalid feed token", if: format == :rss, unless: params[:public] do
+ it "logs the user" do
+ expect(authentication_metrics)
+ .to increment(:user_unauthenticated_counter)
+
+ get path, default_params.merge(feed_token: 'token')
+
+ expect(response.status).not_to eq 200
+ end
+ end
+
+ it "doesn't log the user in otherwise", unless: params[:public] do
+ expect(authentication_metrics)
+ .to increment(:user_unauthenticated_counter)
+
+ get path, default_params.merge(private_token: 'token')
+
+ expect(response.status).not_to eq(200)
+ end
+end
diff --git a/spec/support/features/discussion_comments_shared_example.rb b/spec/support/features/discussion_comments_shared_example.rb
index 80604395adf..922f3df144d 100644
--- a/spec/support/features/discussion_comments_shared_example.rb
+++ b/spec/support/features/discussion_comments_shared_example.rb
@@ -142,6 +142,14 @@ shared_examples 'discussion comments' do |resource_name|
find(comments_selector, match: :first)
end
+ def submit_reply(text)
+ find("#{comments_selector} .js-vue-discussion-reply").click
+ find("#{comments_selector} .note-textarea").send_keys(text)
+
+ click_button "Comment"
+ wait_for_requests
+ end
+
it 'clicking "Start discussion" will post a discussion' do
new_comment = all(comments_selector).last
@@ -149,18 +157,39 @@ shared_examples 'discussion comments' do |resource_name|
expect(new_comment).to have_selector '.discussion'
end
+ if resource_name =~ /(issue|merge request)/
+ it 'can be replied to' do
+ submit_reply('some text')
+
+ expect(page).to have_css('.discussion-notes .note', count: 2)
+ expect(page).to have_content 'Collapse replies'
+ end
+
+ it 'can be collapsed' do
+ submit_reply('another text')
+
+ find('.js-collapse-replies').click
+ expect(page).to have_css('.discussion-notes .note', count: 1)
+ expect(page).to have_content '1 reply'
+ end
+ end
+
if resource_name == 'merge request'
- let(:note_id) { find("#{comments_selector} .note", match: :first)['data-note-id'] }
+ let(:note_id) { find("#{comments_selector} .note:first-child", match: :first)['data-note-id'] }
+ let(:reply_id) { find("#{comments_selector} .note:last-child", match: :first)['data-note-id'] }
it 'shows resolved discussion when toggled' do
+ submit_reply('a')
+
click_button "Resolve discussion"
+ wait_for_requests
expect(page).to have_selector(".note-row-#{note_id}", visible: true)
refresh
- click_button "Toggle discussion"
+ click_button "1 reply"
- expect(page).to have_selector(".note-row-#{note_id}", visible: true)
+ expect(page).to have_selector(".note-row-#{reply_id}", visible: true)
end
end
end
diff --git a/spec/support/features/issuable_quick_actions_shared_examples.rb b/spec/support/features/issuable_quick_actions_shared_examples.rb
index 846e697eb96..2a883ce1074 100644
--- a/spec/support/features/issuable_quick_actions_shared_examples.rb
+++ b/spec/support/features/issuable_quick_actions_shared_examples.rb
@@ -77,6 +77,15 @@ shared_examples 'issuable record that supports quick actions in its description
expect(issuable.labels).to eq [label_bug]
expect(issuable.milestone).to eq milestone
end
+
+ it 'removes the quick action from note and explains it in the preview' do
+ preview_note("Awesome!\n\n/close")
+
+ expect(page).to have_content 'Awesome!'
+ expect(page).not_to have_content '/close'
+ issuable_name = issuable.is_a?(Issue) ? 'issue' : 'merge request'
+ expect(page).to have_content "Closes this #{issuable_name}."
+ end
end
context 'with a note containing only commands' do
diff --git a/spec/support/features/reportable_note_shared_examples.rb b/spec/support/features/reportable_note_shared_examples.rb
index 89a5518239d..8cfce49da8a 100644
--- a/spec/support/features/reportable_note_shared_examples.rb
+++ b/spec/support/features/reportable_note_shared_examples.rb
@@ -20,7 +20,7 @@ shared_examples 'reportable note' do |type|
dropdown = comment.find(more_actions_selector)
open_dropdown(dropdown)
- expect(dropdown).to have_link('Report as abuse', href: abuse_report_path)
+ expect(dropdown).to have_link('Report abuse to GitLab', href: abuse_report_path)
if type == 'issue' || type == 'merge_request'
expect(dropdown).to have_button('Delete comment')
@@ -33,7 +33,7 @@ shared_examples 'reportable note' do |type|
dropdown = comment.find(more_actions_selector)
open_dropdown(dropdown)
- dropdown.click_link('Report as abuse')
+ dropdown.click_link('Report abuse to GitLab')
expect(find('#user_name')['value']).to match(note.author.username)
expect(find('#abuse_report_message')['value']).to match(noteable_note_url(note))
diff --git a/spec/support/features/variable_list_shared_examples.rb b/spec/support/features/variable_list_shared_examples.rb
index f7f851eb1eb..bce1fb01355 100644
--- a/spec/support/features/variable_list_shared_examples.rb
+++ b/spec/support/features/variable_list_shared_examples.rb
@@ -5,7 +5,7 @@ shared_examples 'variable list' do
end
end
- it 'adds new secret variable' do
+ it 'adds new CI variable' do
page.within('.js-ci-variable-list-section .js-row:last-child') do
find('.js-ci-variable-input-key').set('key')
find('.js-ci-variable-input-value').set('key value')
diff --git a/spec/support/gitaly.rb b/spec/support/gitaly.rb
deleted file mode 100644
index 614aaa73693..00000000000
--- a/spec/support/gitaly.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-RSpec.configure do |config|
- config.before(:each) do |example|
- if example.metadata[:disable_gitaly]
- # Use 'and_wrap_original' to make sure the arguments are valid
- allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_wrap_original { |m, *args| m.call(*args) && false }
- else
- next if example.metadata[:skip_gitaly_mock]
-
- # Use 'and_wrap_original' to make sure the arguments are valid
- allow(Gitlab::GitalyClient).to receive(:feature_enabled?).and_wrap_original do |m, *args|
- m.call(*args)
- !Gitlab::GitalyClient.explicit_opt_in_required.include?(args.first)
- end
- end
- end
-end
diff --git a/spec/support/helpers/ci_artifact_metadata_generator.rb b/spec/support/helpers/ci_artifact_metadata_generator.rb
new file mode 100644
index 00000000000..ef638d59d2d
--- /dev/null
+++ b/spec/support/helpers/ci_artifact_metadata_generator.rb
@@ -0,0 +1,48 @@
+# frozen_sting_literal: true
+
+# This generates fake CI metadata .gz for testing
+# Based off https://gitlab.com/gitlab-org/gitlab-workhorse/blob/master/internal/zipartifacts/metadata.go
+class CiArtifactMetadataGenerator
+ attr_accessor :entries, :output
+
+ ARTIFACT_METADATA = "GitLab Build Artifacts Metadata 0.0.2\n".freeze
+
+ def initialize(stream)
+ @entries = {}
+ @output = Zlib::GzipWriter.new(stream)
+ end
+
+ def add_entry(filename)
+ @entries[filename] = { CRC: rand(0xfffffff), Comment: FFaker::Lorem.sentence(10) }
+ end
+
+ def write
+ write_version
+ write_errors
+ write_entries
+ output.close
+ end
+
+ private
+
+ def write_version
+ write_string(ARTIFACT_METADATA)
+ end
+
+ def write_errors
+ write_string('{}')
+ end
+
+ def write_entries
+ entries.each do |filename, metadata|
+ write_string(filename)
+ write_string(metadata.to_json + "\n")
+ end
+ end
+
+ def write_string(data)
+ bytes = [data.length].pack('L>')
+ output.write(bytes)
+ output.write(data)
+ end
+end
diff --git a/spec/support/helpers/cycle_analytics_helpers.rb b/spec/support/helpers/cycle_analytics_helpers.rb
index e0fceae88de..ecefdc23811 100644
--- a/spec/support/helpers/cycle_analytics_helpers.rb
+++ b/spec/support/helpers/cycle_analytics_helpers.rb
@@ -1,4 +1,6 @@
module CycleAnalyticsHelpers
+ include GitHelpers
+
def create_commit_referencing_issue(issue, branch_name: generate(:branch))
project.repository.add_branch(user, branch_name, 'master')
create_commit("Commit for ##{issue.iid}", issue.project, user, branch_name)
@@ -9,7 +11,7 @@ module CycleAnalyticsHelpers
oldrev = repository.commit(branch_name)&.sha || Gitlab::Git::BLANK_SHA
if Timecop.frozen? && Gitlab::GitalyClient.feature_enabled?(:operation_user_commit_files)
- mock_gitaly_multi_action_dates(repository.raw, commit_time)
+ mock_gitaly_multi_action_dates(repository, commit_time)
end
commit_shas = Array.new(count) do |index|
@@ -83,7 +85,7 @@ module CycleAnalyticsHelpers
raise ArgumentError
end
- CreateDeploymentService.new(dummy_job).execute
+ dummy_job.success! # State machine automatically update associated deployment/environment record
end
def dummy_production_job(user, project)
@@ -95,7 +97,7 @@ module CycleAnalyticsHelpers
end
def dummy_pipeline(project)
- Ci::Pipeline.new(
+ create(:ci_pipeline,
sha: project.repository.commit('master').sha,
ref: 'master',
source: :push,
@@ -104,9 +106,7 @@ module CycleAnalyticsHelpers
end
def new_dummy_job(user, project, environment)
- project.environments.find_or_create_by(name: environment)
-
- Ci::Build.new(
+ create(:ci_build,
project: project,
user: user,
environment: environment,
@@ -118,18 +118,15 @@ module CycleAnalyticsHelpers
protected: false)
end
- def mock_gitaly_multi_action_dates(raw_repository, commit_time)
- allow(raw_repository).to receive(:multi_action).and_wrap_original do |m, *args|
+ def mock_gitaly_multi_action_dates(repository, commit_time)
+ allow(repository.raw).to receive(:multi_action).and_wrap_original do |m, *args|
new_date = commit_time || Time.now
branch_update = m.call(*args)
if branch_update.newrev
_, opts = args
- commit = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- rugged = raw_repository.rugged
- rugged.rev_parse(branch_update.newrev)
- end
+ commit = rugged_repo(repository).rev_parse(branch_update.newrev)
branch_update.newrev = commit.amend(
update_ref: "#{Gitlab::Git::BRANCH_REF_PREFIX}#{opts[:branch_name]}",
diff --git a/spec/support/helpers/devise_helpers.rb b/spec/support/helpers/devise_helpers.rb
index 66874e10f38..d32bc2424c0 100644
--- a/spec/support/helpers/devise_helpers.rb
+++ b/spec/support/helpers/devise_helpers.rb
@@ -8,8 +8,15 @@ module DeviseHelpers
end
def env_from_context(context)
+ # When we modify env_config, that is on the global
+ # Rails.application, and we need to stub it and allow it to be
+ # modified in-place, without polluting later tests.
if context.respond_to?(:env_config)
- context.env_config
+ context.env_config.deep_dup.tap do |env|
+ allow(context).to receive(:env_config).and_return(env)
+ end
+ # When we modify env, then the context is a request, or something
+ # else that only lives for a single spec.
elsif context.respond_to?(:env)
context.env
end
diff --git a/spec/support/helpers/features/branches_helpers.rb b/spec/support/helpers/features/branches_helpers.rb
index 3525d9a70a7..df88fd425c9 100644
--- a/spec/support/helpers/features/branches_helpers.rb
+++ b/spec/support/helpers/features/branches_helpers.rb
@@ -20,7 +20,7 @@ module Spec
end
def select_branch(branch_name)
- find(".git-revision-dropdown-toggle").click
+ find(".js-branch-select").click
page.within("#new-branch-form .dropdown-menu") do
click_link(branch_name)
diff --git a/spec/support/helpers/features/sorting_helpers.rb b/spec/support/helpers/features/sorting_helpers.rb
index ad0053ec5cf..a1ae428586e 100644
--- a/spec/support/helpers/features/sorting_helpers.rb
+++ b/spec/support/helpers/features/sorting_helpers.rb
@@ -13,7 +13,7 @@ module Spec
module Features
module SortingHelpers
def sort_by(value)
- find('button.dropdown-toggle').click
+ find('.filter-dropdown-container button.dropdown-menu-toggle').click
page.within('.content ul.dropdown-menu.dropdown-menu-right li') do
click_link(value)
diff --git a/spec/support/helpers/filter_item_select_helper.rb b/spec/support/helpers/filter_item_select_helper.rb
deleted file mode 100644
index 519e84d359e..00000000000
--- a/spec/support/helpers/filter_item_select_helper.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# Helper allows you to select value from filter-items
-#
-# Params
-# value - value for select
-# selector - css selector of item
-#
-# Usage:
-#
-# filter_item_select('Any Author', '.js-author-search')
-#
-module FilterItemSelectHelper
- def filter_item_select(value, selector)
- find(selector).click
- wait_for_requests
- page.within('.dropdown-content') do
- click_link value
- end
- end
-end
diff --git a/spec/support/helpers/filtered_search_helpers.rb b/spec/support/helpers/filtered_search_helpers.rb
index 5f42ff77fb2..6569feec39b 100644
--- a/spec/support/helpers/filtered_search_helpers.rb
+++ b/spec/support/helpers/filtered_search_helpers.rb
@@ -120,8 +120,12 @@ module FilteredSearchHelpers
create_token('Label', label_name, symbol)
end
- def emoji_token(emoji_name = nil)
- { name: 'My-Reaction', emoji_name: emoji_name }
+ def reaction_token(reaction_name = nil, is_emoji = true)
+ if is_emoji
+ { name: 'My-Reaction', emoji_name: reaction_name }
+ else
+ create_token('My-Reaction', reaction_name)
+ end
end
def default_placeholder
diff --git a/spec/support/helpers/git_helpers.rb b/spec/support/helpers/git_helpers.rb
index fc92bc38561..99a7c39852e 100644
--- a/spec/support/helpers/git_helpers.rb
+++ b/spec/support/helpers/git_helpers.rb
@@ -1,6 +1,12 @@
# frozen_string_literal: true
module GitHelpers
+ def rugged_repo(repository)
+ path = File.join(TestEnv.repos_path, repository.disk_path + '.git')
+
+ Rugged::Repository.new(path)
+ end
+
def project_hook_exists?(project)
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
project_path = project.repository.raw_repository.path
diff --git a/spec/support/helpers/git_http_helpers.rb b/spec/support/helpers/git_http_helpers.rb
index b8289e6c5f1..9a5845af90c 100644
--- a/spec/support/helpers/git_http_helpers.rb
+++ b/spec/support/helpers/git_http_helpers.rb
@@ -60,9 +60,4 @@ module GitHttpHelpers
message = Gitlab::GitAccessWiki::ERROR_MESSAGES[error_key]
message || raise("GitAccessWiki error message key '#{error_key}' not found")
end
-
- def change_access_error(error_key)
- message = Gitlab::Checks::ChangeAccess::ERROR_MESSAGES[error_key]
- message || raise("ChangeAccess error message key '#{error_key}' not found")
- end
end
diff --git a/spec/support/helpers/gpg_helpers.rb b/spec/support/helpers/gpg_helpers.rb
index 3f7279a50e0..8d1637228d0 100644
--- a/spec/support/helpers/gpg_helpers.rb
+++ b/spec/support/helpers/gpg_helpers.rb
@@ -1,5 +1,9 @@
+# frozen_string_literal: true
+
module GpgHelpers
- SIGNED_COMMIT_SHA = '8a852d50dda17cc8fd1408d2fd0c5b0f24c76ca4'.freeze
+ SIGNED_COMMIT_SHA = '8a852d50dda17cc8fd1408d2fd0c5b0f24c76ca4'
+ SIGNED_AND_AUTHORED_SHA = '3c1d9a0266cb0c62d926f4a6c649beed561846f5'
+ DIFFERING_EMAIL_SHA = 'a17a9f66543673edf0a3d1c6b93bdda3fe600f32'
module User1
extend self
diff --git a/spec/support/helpers/kubernetes_helpers.rb b/spec/support/helpers/kubernetes_helpers.rb
index c077ca9f15b..ccaf86aa3a6 100644
--- a/spec/support/helpers/kubernetes_helpers.rb
+++ b/spec/support/helpers/kubernetes_helpers.rb
@@ -17,6 +17,7 @@ module KubernetesHelpers
WebMock.stub_request(:get, api_url + '/api/v1').to_return(kube_response(kube_v1_discovery_body))
WebMock.stub_request(:get, api_url + '/apis/extensions/v1beta1').to_return(kube_response(kube_v1beta1_discovery_body))
WebMock.stub_request(:get, api_url + '/apis/rbac.authorization.k8s.io/v1').to_return(kube_response(kube_v1_rbac_authorization_discovery_body))
+ WebMock.stub_request(:get, api_url + '/apis/serving.knative.dev/v1alpha1').to_return(kube_response(kube_v1alpha1_serving_knative_discovery_body))
end
def stub_kubeclient_pods(response = nil)
@@ -33,16 +34,17 @@ module KubernetesHelpers
WebMock.stub_request(:get, deployments_url).to_return(response || kube_deployments_response)
end
- def stub_kubeclient_get_secret(api_url, namespace: 'default', **options)
+ def stub_kubeclient_get_secret(api_url, **options)
options[:metadata_name] ||= "default-token-1"
+ options[:namespace] ||= "default"
- WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{namespace}/secrets/#{options[:metadata_name]}")
+ WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{options[:namespace]}/secrets/#{options[:metadata_name]}")
.to_return(kube_response(kube_v1_secret_body(options)))
end
- def stub_kubeclient_get_secret_error(api_url, name, namespace: 'default')
+ def stub_kubeclient_get_secret_error(api_url, name, namespace: 'default', status: 404)
WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{namespace}/secrets/#{name}")
- .to_return(status: [404, "Internal Server Error"])
+ .to_return(status: [status, "Internal Server Error"])
end
def stub_kubeclient_create_service_account(api_url, namespace: 'default')
@@ -65,6 +67,21 @@ module KubernetesHelpers
.to_return(kube_response({}))
end
+ def stub_kubeclient_create_role_binding(api_url, namespace: 'default')
+ WebMock.stub_request(:post, api_url + "/apis/rbac.authorization.k8s.io/v1/namespaces/#{namespace}/rolebindings")
+ .to_return(kube_response({}))
+ end
+
+ def stub_kubeclient_create_namespace(api_url)
+ WebMock.stub_request(:post, api_url + "/api/v1/namespaces")
+ .to_return(kube_response({}))
+ end
+
+ def stub_kubeclient_get_namespace(api_url, namespace: 'default')
+ WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{namespace}")
+ .to_return(kube_response({}))
+ end
+
def kube_v1_secret_body(**options)
{
"kind" => "SecretList",
@@ -87,7 +104,8 @@ module KubernetesHelpers
{ "name" => "deployments", "namespaced" => true, "kind" => "Deployment" },
{ "name" => "secrets", "namespaced" => true, "kind" => "Secret" },
{ "name" => "serviceaccounts", "namespaced" => true, "kind" => "ServiceAccount" },
- { "name" => "services", "namespaced" => true, "kind" => "Service" }
+ { "name" => "services", "namespaced" => true, "kind" => "Service" },
+ { "name" => "namespaces", "namespaced" => true, "kind" => "Namespace" }
]
}
end
@@ -117,6 +135,18 @@ module KubernetesHelpers
}
end
+ def kube_v1alpha1_serving_knative_discovery_body
+ {
+ "kind" => "APIResourceList",
+ "resources" => [
+ { "name" => "revisions", "namespaced" => true, "kind" => "Revision" },
+ { "name" => "services", "namespaced" => true, "kind" => "Service" },
+ { "name" => "configurations", "namespaced" => true, "kind" => "Configuration" },
+ { "name" => "routes", "namespaced" => true, "kind" => "Route" }
+ ]
+ }
+ end
+
def kube_pods_body
{
"kind" => "PodList",
diff --git a/spec/support/helpers/migrations_helpers.rb b/spec/support/helpers/migrations_helpers.rb
index 0bc235701eb..5887c3eab74 100644
--- a/spec/support/helpers/migrations_helpers.rb
+++ b/spec/support/helpers/migrations_helpers.rb
@@ -1,8 +1,16 @@
module MigrationsHelpers
+ def active_record_base
+ ActiveRecord::Base
+ end
+
def table(name)
- Class.new(ActiveRecord::Base) do
+ Class.new(active_record_base) do
self.table_name = name
self.inheritance_column = :_type_disabled
+
+ def self.name
+ table_name.singularize.camelcase
+ end
end
end
@@ -15,7 +23,7 @@ module MigrationsHelpers
end
def clear_schema_cache!
- ActiveRecord::Base.connection_pool.connections.each do |conn|
+ active_record_base.connection_pool.connections.each do |conn|
conn.schema_cache.clear!
end
end
@@ -36,11 +44,18 @@ module MigrationsHelpers
# Reset column information for the most offending classes **after** we
# migrated the schema up, otherwise, column information could be
# outdated. We have a separate method for this so we can override it in EE.
- ActiveRecord::Base.descendants.each(&method(:reset_column_information))
+ active_record_base.descendants.each(&method(:reset_column_information))
+ end
- # Without that, we get errors because of missing attributes, e.g.
+ def refresh_attribute_methods
+ # Without this, we get errors because of missing attributes, e.g.
# super: no superclass method `elasticsearch_indexing' for #<ApplicationSetting:0x00007f85628508d8>
- ApplicationSetting.define_attribute_methods
+ # attr_encrypted also expects ActiveRecord attribute methods to be
+ # defined, or it will override the accessors:
+ # https://gitlab.com/gitlab-org/gitlab-ee/issues/8234#note_113976421
+ [ApplicationSetting, SystemHook].each do |model|
+ model.define_attribute_methods
+ end
end
def reset_column_information(klass)
@@ -80,6 +95,7 @@ module MigrationsHelpers
end
reset_column_in_all_models
+ refresh_attribute_methods
end
def disable_migrations_output
diff --git a/spec/support/helpers/project_forks_helper.rb b/spec/support/helpers/project_forks_helper.rb
index 2c501a2a27c..9a86560da2a 100644
--- a/spec/support/helpers/project_forks_helper.rb
+++ b/spec/support/helpers/project_forks_helper.rb
@@ -24,7 +24,7 @@ module ProjectForksHelper
allow(service).to receive(:gitlab_shell).and_return(shell)
end
- forked_project = service.execute
+ forked_project = service.execute(params[:target_project])
# Reload the both projects so they know about their newly created fork_network
if forked_project.persisted?
@@ -35,7 +35,7 @@ module ProjectForksHelper
if create_repository
# The call to project.repository.after_import in RepositoryForkWorker does
# not reset the @exists variable of this forked_project.repository
- # so we have to explicitely call this method to clear the @exists variable.
+ # so we have to explicitly call this method to clear the @exists variable.
# of the instance we're returning here.
forked_project.repository.after_import
end
diff --git a/spec/support/helpers/prometheus_helpers.rb b/spec/support/helpers/prometheus_helpers.rb
index 4212be2cc88..ce1f9fce10d 100644
--- a/spec/support/helpers/prometheus_helpers.rb
+++ b/spec/support/helpers/prometheus_helpers.rb
@@ -49,11 +49,11 @@ module PrometheusHelpers
"https://prometheus.example.com/api/v1/series?#{query}"
end
- def stub_prometheus_request(url, body: {}, status: 200)
+ def stub_prometheus_request(url, body: {}, status: 200, headers: {})
WebMock.stub_request(:get, url)
.to_return({
status: status,
- headers: { 'Content-Type' => 'application/json' },
+ headers: { 'Content-Type' => 'application/json' }.merge(headers),
body: body.to_json
})
end
diff --git a/spec/support/helpers/reference_parser_helpers.rb b/spec/support/helpers/reference_parser_helpers.rb
index c01897ed1a1..9f27502aa52 100644
--- a/spec/support/helpers/reference_parser_helpers.rb
+++ b/spec/support/helpers/reference_parser_helpers.rb
@@ -3,7 +3,7 @@ module ReferenceParserHelpers
Nokogiri::HTML.fragment('<a></a>').children[0]
end
- shared_examples 'no N+1 queries' do
+ shared_examples 'no project N+1 queries' do
it 'avoids N+1 queries in #nodes_visible_to_user', :request_store do
context = Banzai::RenderContext.new(project, user)
@@ -19,6 +19,10 @@ module ReferenceParserHelpers
expect(actual.count).to be <= control.count
expect(actual.cached_count).to be <= control.cached_count
end
+ end
+
+ shared_examples 'no N+1 queries' do
+ it_behaves_like 'no project N+1 queries'
it 'avoids N+1 queries in #records_for_nodes', :request_store do
context = Banzai::RenderContext.new(project, user)
diff --git a/spec/support/helpers/seed_helper.rb b/spec/support/helpers/seed_helper.rb
index 25781f5e679..90d7f60fdeb 100644
--- a/spec/support/helpers/seed_helper.rb
+++ b/spec/support/helpers/seed_helper.rb
@@ -1,15 +1,18 @@
+# frozen_string_literal: true
+
require_relative 'test_env'
# This file is specific to specs in spec/lib/gitlab/git/
SEED_STORAGE_PATH = TestEnv.repos_path
-TEST_REPO_PATH = 'gitlab-git-test.git'.freeze
-TEST_NORMAL_REPO_PATH = 'not-bare-repo.git'.freeze
-TEST_MUTABLE_REPO_PATH = 'mutable-repo.git'.freeze
-TEST_BROKEN_REPO_PATH = 'broken-repo.git'.freeze
+TEST_REPO_PATH = 'gitlab-git-test.git'
+TEST_NORMAL_REPO_PATH = 'not-bare-repo.git'
+TEST_MUTABLE_REPO_PATH = 'mutable-repo.git'
+TEST_BROKEN_REPO_PATH = 'broken-repo.git'
+TEST_GITATTRIBUTES_REPO_PATH = 'with-git-attributes.git'
module SeedHelper
- GITLAB_GIT_TEST_REPO_URL = File.expand_path('../gitlab-git-test.git', __dir__).freeze
+ GITLAB_GIT_TEST_REPO_URL = File.expand_path('../gitlab-git-test.git', __dir__)
def ensure_seeds
if File.exist?(SEED_STORAGE_PATH)
@@ -66,6 +69,11 @@ module SeedHelper
end
def create_git_attributes
+ system(git_env, *%W(#{Gitlab.config.git.bin_path} clone --bare #{TEST_REPO_PATH} #{TEST_GITATTRIBUTES_REPO_PATH}),
+ chdir: SEED_STORAGE_PATH,
+ out: '/dev/null',
+ err: '/dev/null')
+
dir = File.join(SEED_STORAGE_PATH, 'with-git-attributes.git', 'info')
FileUtils.mkdir_p(dir)
@@ -82,6 +90,8 @@ foo/bar.* foo
*.cgi key=value?p1=v1&p2=v2
/*.png gitlab-language=png
*.binary binary
+/custom-highlighting/*.gitlab-custom gitlab-language=ruby
+/custom-highlighting/*.gitlab-cgi gitlab-language=erb?parent=json
# This uses a tab instead of spaces to ensure the parser also supports this.
*.md\tgitlab-language=markdown
diff --git a/spec/support/helpers/sorting_helper.rb b/spec/support/helpers/sorting_helper.rb
index 9496a94d8f4..e505a6b7258 100644
--- a/spec/support/helpers/sorting_helper.rb
+++ b/spec/support/helpers/sorting_helper.rb
@@ -10,7 +10,7 @@
#
module SortingHelper
def sorting_by(value)
- find('button.dropdown-toggle').click
+ find('.filter-dropdown-container button.dropdown-menu-toggle').click
page.within('.content ul.dropdown-menu.dropdown-menu-right li') do
click_link value
end
diff --git a/spec/support/helpers/stub_configuration.rb b/spec/support/helpers/stub_configuration.rb
index 776119564ec..2851cd9733c 100644
--- a/spec/support/helpers/stub_configuration.rb
+++ b/spec/support/helpers/stub_configuration.rb
@@ -27,6 +27,11 @@ module StubConfiguration
allow(Gitlab.config.gitlab).to receive_messages(to_settings(messages))
end
+ def stub_default_url_options(host: "localhost", protocol: "http")
+ url_options = { host: host, protocol: protocol }
+ allow(Rails.application.routes).to receive(:default_url_options).and_return(url_options)
+ end
+
def stub_gravatar_setting(messages)
allow(Gitlab.config.gravatar).to receive_messages(to_settings(messages))
end
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index 97875669d0e..1f00cdf7e92 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -31,6 +31,8 @@ module TestEnv
'symlink-expand-diff' => '81e6355',
'expand-collapse-files' => '025db92',
'expand-collapse-lines' => '238e82d',
+ 'pages-deploy' => '7897d5b',
+ 'pages-deploy-target' => '7975be0',
'video' => '8879059',
'add-balsamiq-file' => 'b89b56d',
'crlf-diff' => '5938907',
@@ -53,7 +55,11 @@ module TestEnv
'update-gitlab-shell-v-6-0-1' => '2f61d70',
'update-gitlab-shell-v-6-0-3' => 'de78448',
'2-mb-file' => 'bf12d25',
- 'with-codeowners' => '219560e'
+ 'before-create-delete-modify-move' => '845009f',
+ 'between-create-delete-modify-move' => '3f5f443',
+ 'after-create-delete-modify-move' => 'ba3faa7',
+ 'with-codeowners' => '219560e',
+ 'submodule_inside_folder' => 'b491b92'
}.freeze
# gitlab-test-fork is a fork of gitlab-fork, but we don't necessarily
@@ -68,7 +74,6 @@ module TestEnv
TMP_TEST_PATH = Rails.root.join('tmp', 'tests', '**')
REPOS_STORAGE = 'default'.freeze
- BROKEN_STORAGE = 'broken'.freeze
# Test environment
#
@@ -157,12 +162,9 @@ module TestEnv
version: Gitlab::GitalyClient.expected_server_version,
task: "gitlab:gitaly:install[#{gitaly_dir},#{repos_path}]") do
- # Re-create config, to specify the broken storage path
- storage_paths = { 'default' => repos_path, 'broken' => broken_path }
- Gitlab::SetupHelper.create_gitaly_configuration(gitaly_dir, storage_paths, force: true)
-
- start_gitaly(gitaly_dir)
- end
+ Gitlab::SetupHelper.create_gitaly_configuration(gitaly_dir, { 'default' => repos_path }, force: true)
+ start_gitaly(gitaly_dir)
+ end
end
def start_gitaly(gitaly_dir)
@@ -171,6 +173,8 @@ module TestEnv
return
end
+ FileUtils.mkdir_p("tmp/tests/second_storage") unless File.exist?("tmp/tests/second_storage")
+
spawn_script = Rails.root.join('scripts/gitaly-test-spawn').to_s
Bundler.with_original_env do
raise "gitaly spawn failed" unless system(spawn_script)
@@ -255,10 +259,6 @@ module TestEnv
@repos_path ||= Gitlab.config.repositories.storages[REPOS_STORAGE].legacy_disk_path
end
- def broken_path
- @broken_path ||= Gitlab.config.repositories.storages[BROKEN_STORAGE].legacy_disk_path
- end
-
def backup_path
Gitlab.config.backup.path
end
diff --git a/spec/support/helpers/test_request_helpers.rb b/spec/support/helpers/test_request_helpers.rb
new file mode 100644
index 00000000000..187a0e07891
--- /dev/null
+++ b/spec/support/helpers/test_request_helpers.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module TestRequestHelpers
+ def test_request(remote_ip: '127.0.0.1')
+ if Gitlab.rails5?
+ ActionController::TestRequest.new({ remote_ip: remote_ip }, ActionController::TestSession.new)
+ else
+ ActionController::TestRequest.new(remote_ip: remote_ip)
+ end
+ end
+end
diff --git a/spec/support/helpers/user_login_helper.rb b/spec/support/helpers/user_login_helper.rb
new file mode 100644
index 00000000000..36c002f53af
--- /dev/null
+++ b/spec/support/helpers/user_login_helper.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module UserLoginHelper
+ def ensure_tab_pane_correctness(visit_path = true)
+ if visit_path
+ visit new_user_session_path
+ end
+
+ ensure_tab_pane_counts
+ ensure_one_active_tab
+ ensure_one_active_pane
+ end
+
+ def ensure_tab_pane_counts
+ tabs_count = page.all('[role="tab"]').size
+ expect(page).to have_selector('[role="tabpanel"]', count: tabs_count)
+ end
+
+ def ensure_one_active_tab
+ expect(page).to have_selector('ul.new-session-tabs > li > a.active', count: 1)
+ end
+
+ def ensure_one_active_pane
+ expect(page).to have_selector('.tab-pane.active', count: 1)
+ end
+end
diff --git a/spec/support/helpers/wiki_helpers.rb b/spec/support/helpers/wiki_helpers.rb
new file mode 100644
index 00000000000..8165403cb60
--- /dev/null
+++ b/spec/support/helpers/wiki_helpers.rb
@@ -0,0 +1,13 @@
+module WikiHelpers
+ extend self
+
+ def upload_file_to_wiki(project, user, file_name)
+ opts = {
+ file_name: file_name,
+ file_content: File.read(expand_fixture_path(file_name))
+ }
+
+ ::Wikis::CreateAttachmentService.new(project, user, opts)
+ .execute[:result][:file_path]
+ end
+end
diff --git a/spec/support/import_export/export_file_helper.rb b/spec/support/import_export/export_file_helper.rb
index d9ed405baf4..a49036c3b80 100644
--- a/spec/support/import_export/export_file_helper.rb
+++ b/spec/support/import_export/export_file_helper.rb
@@ -123,7 +123,7 @@ module ExportFileHelper
false
end
- # Compares model attributes with those those found in the hash
+ # Compares model attributes with those found in the hash
# and returns true if there is a match, ignoring some excluded attributes.
def safe_model?(model, excluded_attributes, parent)
excluded_attributes += associations_for(model)
diff --git a/spec/support/services/clusters/create_service_shared.rb b/spec/support/services/clusters/create_service_shared.rb
index 22f712f3fcf..b0bf942aa09 100644
--- a/spec/support/services/clusters/create_service_shared.rb
+++ b/spec/support/services/clusters/create_service_shared.rb
@@ -30,10 +30,6 @@ shared_context 'invalid cluster create params' do
end
shared_examples 'create cluster service success' do
- before do
- stub_feature_flags(rbac_clusters: false)
- end
-
it 'creates a cluster object and performs a worker' do
expect(ClusterProvisionWorker).to receive(:perform_async)
diff --git a/spec/support/shared_contexts/change_access_checks_shared_context.rb b/spec/support/shared_contexts/change_access_checks_shared_context.rb
new file mode 100644
index 00000000000..aca18b0c73b
--- /dev/null
+++ b/spec/support/shared_contexts/change_access_checks_shared_context.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+shared_context 'change access checks context' do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:user_access) { Gitlab::UserAccess.new(user, project: project) }
+ let(:oldrev) { 'be93687618e4b132087f430a4d8fc3a609c9b77c' }
+ let(:newrev) { '54fcc214b94e78d7a41a9a8fe6d87a5e59500e51' }
+ let(:ref) { 'refs/heads/master' }
+ let(:changes) { { oldrev: oldrev, newrev: newrev, ref: ref } }
+ let(:protocol) { 'ssh' }
+ let(:timeout) { Gitlab::GitAccess::INTERNAL_TIMEOUT }
+ let(:logger) { Gitlab::Checks::TimedLogger.new(timeout: timeout) }
+ let(:change_access) do
+ Gitlab::Checks::ChangeAccess.new(
+ changes,
+ project: project,
+ user_access: user_access,
+ protocol: protocol,
+ logger: logger
+ )
+ end
+
+ subject { described_class.new(change_access) }
+
+ before do
+ project.add_developer(user)
+ end
+end
diff --git a/spec/support/shared_contexts/url_shared_context.rb b/spec/support/shared_contexts/url_shared_context.rb
new file mode 100644
index 00000000000..1b1f67daac3
--- /dev/null
+++ b/spec/support/shared_contexts/url_shared_context.rb
@@ -0,0 +1,17 @@
+shared_context 'invalid urls' do
+ let(:urls_with_CRLF) do
+ ["http://127.0.0.1:333/pa\rth",
+ "http://127.0.0.1:333/pa\nth",
+ "http://127.0a.0.1:333/pa\r\nth",
+ "http://127.0.0.1:333/path?param=foo\r\nbar",
+ "http://127.0.0.1:333/path?param=foo\rbar",
+ "http://127.0.0.1:333/path?param=foo\nbar",
+ "http://127.0.0.1:333/pa%0dth",
+ "http://127.0.0.1:333/pa%0ath",
+ "http://127.0a.0.1:333/pa%0d%0th",
+ "http://127.0.0.1:333/pa%0D%0Ath",
+ "http://127.0.0.1:333/path?param=foo%0Abar",
+ "http://127.0.0.1:333/path?param=foo%0Dbar",
+ "http://127.0.0.1:333/path?param=foo%0D%0Abar"]
+ end
+end
diff --git a/spec/support/shared_examples/ci_trace_shared_examples.rb b/spec/support/shared_examples/ci_trace_shared_examples.rb
index 94e82b8ce90..377bd82b67e 100644
--- a/spec/support/shared_examples/ci_trace_shared_examples.rb
+++ b/spec/support/shared_examples/ci_trace_shared_examples.rb
@@ -272,16 +272,11 @@ shared_examples_for 'common trace features' do
include ExclusiveLeaseHelpers
before do
- stub_exclusive_lease_taken("trace:archive:#{trace.job.id}", timeout: 1.hour)
+ stub_exclusive_lease_taken("trace:write:lock:#{trace.job.id}", timeout: 1.minute)
end
it 'blocks concurrent archiving' do
- expect(Rails.logger).to receive(:error).with('Cannot obtain an exclusive lease. There must be another instance already in execution.')
-
- subject
-
- build.reload
- expect(build.job_artifacts_trace).to be_nil
+ expect { subject }.to raise_error(::Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError)
end
end
end
diff --git a/spec/support/shared_examples/controllers/issuable_notes_filter_shared_examples.rb b/spec/support/shared_examples/controllers/issuable_notes_filter_shared_examples.rb
new file mode 100644
index 00000000000..95e69328080
--- /dev/null
+++ b/spec/support/shared_examples/controllers/issuable_notes_filter_shared_examples.rb
@@ -0,0 +1,66 @@
+shared_examples 'issuable notes filter' do
+ it 'sets discussion filter' do
+ notes_filter = UserPreference::NOTES_FILTERS[:only_comments]
+
+ get :discussions, namespace_id: project.namespace, project_id: project, id: issuable.iid, notes_filter: notes_filter
+
+ expect(user.reload.notes_filter_for(issuable)).to eq(notes_filter)
+ expect(UserPreference.count).to eq(1)
+ end
+
+ it 'expires notes e-tag cache for issuable if filter changed' do
+ notes_filter = UserPreference::NOTES_FILTERS[:only_comments]
+
+ expect_any_instance_of(issuable.class).to receive(:expire_note_etag_cache)
+
+ get :discussions, namespace_id: project.namespace, project_id: project, id: issuable.iid, notes_filter: notes_filter
+ end
+
+ it 'does not expires notes e-tag cache for issuable if filter did not change' do
+ notes_filter = UserPreference::NOTES_FILTERS[:only_comments]
+ user.set_notes_filter(notes_filter, issuable)
+
+ expect_any_instance_of(issuable.class).not_to receive(:expire_note_etag_cache)
+
+ get :discussions, namespace_id: project.namespace, project_id: project, id: issuable.iid, notes_filter: notes_filter
+ end
+
+ it 'does not set notes filter when database is in read only mode' do
+ allow(Gitlab::Database).to receive(:read_only?).and_return(true)
+ notes_filter = UserPreference::NOTES_FILTERS[:only_comments]
+
+ get :discussions, namespace_id: project.namespace, project_id: project, id: issuable.iid, notes_filter: notes_filter
+
+ expect(user.reload.notes_filter_for(issuable)).to eq(0)
+ end
+
+ it 'returns only user comments' do
+ user.set_notes_filter(UserPreference::NOTES_FILTERS[:only_comments], issuable)
+
+ get :discussions, namespace_id: project.namespace, project_id: project, id: issuable.iid
+ discussions = JSON.parse(response.body)
+
+ expect(discussions.count).to eq(1)
+ expect(discussions.first["notes"].first["system"]).to be(false)
+ end
+
+ it 'returns only activity notes' do
+ user.set_notes_filter(UserPreference::NOTES_FILTERS[:only_activity], issuable)
+
+ get :discussions, namespace_id: project.namespace, project_id: project, id: issuable.iid
+ discussions = JSON.parse(response.body)
+
+ expect(discussions.count).to eq(1)
+ expect(discussions.first["notes"].first["system"]).to be(true)
+ end
+
+ context 'when filter is set to "only_comments"' do
+ it 'does not merge label event notes' do
+ user.set_notes_filter(UserPreference::NOTES_FILTERS[:only_comments], issuable)
+
+ expect(ResourceEvents::MergeIntoNotesService).not_to receive(:new)
+
+ get :discussions, namespace_id: project.namespace, project_id: project, id: issuable.iid
+ end
+ end
+end
diff --git a/spec/support/shared_examples/dirty_submit_form_shared_examples.rb b/spec/support/shared_examples/dirty_submit_form_shared_examples.rb
new file mode 100644
index 00000000000..ba363593120
--- /dev/null
+++ b/spec/support/shared_examples/dirty_submit_form_shared_examples.rb
@@ -0,0 +1,24 @@
+shared_examples 'dirty submit form' do |selector_args|
+ selectors = selector_args.is_a?(Array) ? selector_args : [selector_args]
+
+ selectors.each do |selector|
+ it "disables #{selector[:form]} submit until there are changes", :js do
+ form = find(selector[:form])
+ submit = form.first('.js-dirty-submit')
+ input = form.first(selector[:input])
+ original_value = input.value
+
+ expect(submit.disabled?).to be true
+
+ input.set("#{original_value} changes")
+
+ form.find('.js-dirty-submit:not([disabled])', match: :first)
+ expect(submit.disabled?).to be false
+
+ input.set(original_value)
+
+ form.find('.js-dirty-submit[disabled]', match: :first)
+ expect(submit.disabled?).to be true
+ end
+ end
+end
diff --git a/spec/support/shared_examples/helm_generated_script.rb b/spec/support/shared_examples/helm_generated_script.rb
index ef9bb7f5533..ba9b7d3bdcf 100644
--- a/spec/support/shared_examples/helm_generated_script.rb
+++ b/spec/support/shared_examples/helm_generated_script.rb
@@ -2,18 +2,12 @@ shared_examples 'helm commands' do
describe '#generate_script' do
let(:helm_setup) do
<<~EOS
- set -eo pipefail
- ALPINE_VERSION=$(cat /etc/alpine-release | cut -d '.' -f 1,2)
- echo http://mirror.clarkson.edu/alpine/v$ALPINE_VERSION/main >> /etc/apk/repositories
- echo http://mirror1.hs-esslingen.de/pub/Mirrors/alpine/v$ALPINE_VERSION/main >> /etc/apk/repositories
- apk add -U wget ca-certificates openssl >/dev/null
- wget -q -O - https://kubernetes-helm.storage.googleapis.com/helm-v2.7.2-linux-amd64.tar.gz | tar zxC /tmp >/dev/null
- mv /tmp/linux-amd64/helm /usr/bin/
+ set -xeo pipefail
EOS
end
it 'should return appropriate command' do
- expect(subject.generate_script).to eq(helm_setup + commands)
+ expect(subject.generate_script.strip).to eq((helm_setup + commands).strip)
end
end
end
diff --git a/spec/support/shared_examples/models/chat_service_spec.rb b/spec/support/shared_examples/models/chat_service_spec.rb
new file mode 100644
index 00000000000..cf1d52a9616
--- /dev/null
+++ b/spec/support/shared_examples/models/chat_service_spec.rb
@@ -0,0 +1,242 @@
+require "spec_helper"
+
+shared_examples_for "chat service" do |service_name|
+ describe "Associations" do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe "Validations" do
+ context "when service is active" do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:webhook) }
+ it_behaves_like "issue tracker service URL attribute", :webhook
+ end
+
+ context "when service is inactive" do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:webhook) }
+ end
+ end
+
+ describe "#execute" do
+ let(:user) { create(:user) }
+ let(:project) { create(:project, :repository) }
+ let(:webhook_url) { "https://example.gitlab.com/" }
+
+ before do
+ allow(subject).to receive_messages(
+ project: project,
+ project_id: project.id,
+ service_hook: true,
+ webhook: webhook_url
+ )
+
+ WebMock.stub_request(:post, webhook_url)
+ end
+
+ shared_examples "#{service_name} service" do
+ it "calls #{service_name} API" do
+ subject.execute(sample_data)
+
+ expect(WebMock).to have_requested(:post, webhook_url).with { |req| req.body =~ /\A{"#{content_key}":.+}\Z/ }.once
+ end
+ end
+
+ context "with push events" do
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build_sample(project, user)
+ end
+
+ it_behaves_like "#{service_name} service"
+
+ it "specifies the webhook when it is configured" do
+ expect(client).to receive(:new).with(client_arguments).and_return(double(:chat_service).as_null_object)
+
+ subject.execute(sample_data)
+ end
+
+ context "with not default branch" do
+ let(:sample_data) do
+ Gitlab::DataBuilder::Push.build(project, user, nil, nil, "not-the-default-branch")
+ end
+
+ context "when notify_only_default_branch enabled" do
+ before do
+ subject.notify_only_default_branch = true
+ end
+
+ it "does not call the Discord Webhooks API" do
+ result = subject.execute(sample_data)
+
+ expect(result).to be_falsy
+ end
+ end
+
+ context "when notify_only_default_branch disabled" do
+ before do
+ subject.notify_only_default_branch = false
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+ end
+ end
+
+ context "with issue events" do
+ let(:opts) { { title: "Awesome issue", description: "please fix" } }
+ let(:sample_data) do
+ service = Issues::CreateService.new(project, user, opts)
+ issue = service.execute
+ service.hook_data(issue, "open")
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with merge events" do
+ let(:opts) do
+ {
+ title: "Awesome merge_request",
+ description: "please fix",
+ source_branch: "feature",
+ target_branch: "master"
+ }
+ end
+
+ let(:sample_data) do
+ service = MergeRequests::CreateService.new(project, user, opts)
+ merge_request = service.execute
+ service.hook_data(merge_request, "open")
+ end
+
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with wiki page events" do
+ let(:opts) do
+ {
+ title: "Awesome wiki_page",
+ content: "Some text describing some thing or another",
+ format: "md",
+ message: "user created page: Awesome wiki_page"
+ }
+ end
+ let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: opts) }
+ let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, "create") }
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with note events" do
+ let(:sample_data) { Gitlab::DataBuilder::Note.build(note, user) }
+
+ context "with commit comment" do
+ let(:note) do
+ create(:note_on_commit,
+ author: user,
+ project: project,
+ commit_id: project.repository.commit.id,
+ note: "a comment on a commit")
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with merge request comment" do
+ let(:note) do
+ create(:note_on_merge_request, project: project, note: "merge request note")
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with issue comment" do
+ let(:note) do
+ create(:note_on_issue, project: project, note: "issue note")
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with snippet comment" do
+ let(:note) do
+ create(:note_on_project_snippet, project: project, note: "snippet note")
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+ end
+
+ context "with pipeline events" do
+ let(:pipeline) do
+ create(:ci_pipeline,
+ project: project, status: status,
+ sha: project.commit.sha, ref: project.default_branch)
+ end
+ let(:sample_data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
+
+ context "with failed pipeline" do
+ let(:status) { "failed" }
+
+ it_behaves_like "#{service_name} service"
+ end
+
+ context "with succeeded pipeline" do
+ let(:status) { "success" }
+
+ context "with default notify_only_broken_pipelines" do
+ it "does not call Discord Webhooks API" do
+ result = subject.execute(sample_data)
+
+ expect(result).to be_falsy
+ end
+ end
+
+ context "when notify_only_broken_pipelines is false" do
+ before do
+ subject.notify_only_broken_pipelines = false
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+ end
+
+ context "with not default branch" do
+ let(:pipeline) do
+ create(:ci_pipeline, project: project, status: "failed", ref: "not-the-default-branch")
+ end
+
+ context "when notify_only_default_branch enabled" do
+ before do
+ subject.notify_only_default_branch = true
+ end
+
+ it "does not call the Discord Webhooks API" do
+ result = subject.execute(sample_data)
+
+ expect(result).to be_falsy
+ end
+ end
+
+ context "when notify_only_default_branch disabled" do
+ before do
+ subject.notify_only_default_branch = false
+ end
+
+ it_behaves_like "#{service_name} service"
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb b/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb
index 87d12a784ba..1f76b981292 100644
--- a/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb
+++ b/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb
@@ -11,60 +11,4 @@ shared_examples 'cluster application core specs' do |application_name|
expect(Clusters::Cluster::APPLICATIONS[subject.name]).to eq(described_class)
end
end
-
- describe 'status state machine' do
- describe '#make_installing' do
- subject { create(application_name, :scheduled) }
-
- it 'is installing' do
- subject.make_installing!
-
- expect(subject).to be_installing
- end
- end
-
- describe '#make_installed' do
- subject { create(application_name, :installing) }
-
- it 'is installed' do
- subject.make_installed
-
- expect(subject).to be_installed
- end
- end
-
- describe '#make_errored' do
- subject { create(application_name, :installing) }
- let(:reason) { 'some errors' }
-
- it 'is errored' do
- subject.make_errored(reason)
-
- expect(subject).to be_errored
- expect(subject.status_reason).to eq(reason)
- end
- end
-
- describe '#make_scheduled' do
- subject { create(application_name, :installable) }
-
- it 'is scheduled' do
- subject.make_scheduled
-
- expect(subject).to be_scheduled
- end
-
- describe 'when was errored' do
- subject { create(application_name, :errored) }
-
- it 'clears #status_reason' do
- expect(subject.status_reason).not_to be_nil
-
- subject.make_scheduled!
-
- expect(subject.status_reason).to be_nil
- end
- end
- end
- end
end
diff --git a/spec/support/shared_examples/models/cluster_application_helm_cert_examples.rb b/spec/support/shared_examples/models/cluster_application_helm_cert_examples.rb
new file mode 100644
index 00000000000..d87b3181e80
--- /dev/null
+++ b/spec/support/shared_examples/models/cluster_application_helm_cert_examples.rb
@@ -0,0 +1,25 @@
+shared_examples 'cluster application helm specs' do |application_name|
+ let(:application) { create(application_name) }
+
+ describe '#files' do
+ subject { application.files }
+
+ context 'when the helm application does not have a ca_cert' do
+ before do
+ application.cluster.application_helm.ca_cert = nil
+ end
+
+ it 'should not include cert files when there is no ca_cert entry' do
+ expect(subject).not_to include(:'ca.pem', :'cert.pem', :'key.pem')
+ end
+ end
+
+ it 'should include cert files when there is a ca_cert entry' do
+ expect(subject).to include(:'ca.pem', :'cert.pem', :'key.pem')
+ expect(subject[:'ca.pem']).to eq(application.cluster.application_helm.ca_cert)
+
+ cert = OpenSSL::X509::Certificate.new(subject[:'cert.pem'])
+ expect(cert.not_after).to be < 60.minutes.from_now
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb b/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb
index 765dd32f4ba..c391cc48f4e 100644
--- a/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb
+++ b/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb
@@ -28,4 +28,117 @@ shared_examples 'cluster application status specs' do |application_name|
end
end
end
+
+ describe 'status state machine' do
+ describe '#make_installing' do
+ subject { create(application_name, :scheduled) }
+
+ it 'is installing' do
+ subject.make_installing!
+
+ expect(subject).to be_installing
+ end
+ end
+
+ describe '#make_installed' do
+ subject { create(application_name, :installing) }
+
+ it 'is installed' do
+ subject.make_installed!
+
+ expect(subject).to be_installed
+ end
+
+ it 'updates helm version' do
+ subject.cluster.application_helm.update!(version: '1.2.3')
+
+ subject.make_installed!
+
+ subject.cluster.application_helm.reload
+
+ expect(subject.cluster.application_helm.version).to eq(Gitlab::Kubernetes::Helm::HELM_VERSION)
+ end
+ end
+
+ describe '#make_updated' do
+ subject { create(application_name, :updating) }
+
+ it 'is updated' do
+ subject.make_updated!
+
+ expect(subject).to be_updated
+ end
+
+ it 'updates helm version' do
+ subject.cluster.application_helm.update!(version: '1.2.3')
+
+ subject.make_updated!
+
+ subject.cluster.application_helm.reload
+
+ expect(subject.cluster.application_helm.version).to eq(Gitlab::Kubernetes::Helm::HELM_VERSION)
+ end
+ end
+
+ describe '#make_errored' do
+ subject { create(application_name, :installing) }
+ let(:reason) { 'some errors' }
+
+ it 'is errored' do
+ subject.make_errored(reason)
+
+ expect(subject).to be_errored
+ expect(subject.status_reason).to eq(reason)
+ end
+ end
+
+ describe '#make_scheduled' do
+ subject { create(application_name, :installable) }
+
+ it 'is scheduled' do
+ subject.make_scheduled
+
+ expect(subject).to be_scheduled
+ end
+
+ describe 'when was errored' do
+ subject { create(application_name, :errored) }
+
+ it 'clears #status_reason' do
+ expect(subject.status_reason).not_to be_nil
+
+ subject.make_scheduled!
+
+ expect(subject.status_reason).to be_nil
+ end
+ end
+ end
+ end
+
+ describe '#available?' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:trait, :available) do
+ :not_installable | false
+ :installable | false
+ :scheduled | false
+ :installing | false
+ :installed | true
+ :updating | false
+ :updated | true
+ :errored | false
+ :update_errored | false
+ :timeouted | false
+ end
+
+ with_them do
+ subject { build(application_name, trait) }
+
+ if params[:available]
+ it { is_expected.to be_available }
+ else
+ it { is_expected.not_to be_available }
+ end
+ end
+ end
end
diff --git a/spec/support/shared_examples/notify_shared_examples.rb b/spec/support/shared_examples/notify_shared_examples.rb
index 5fb9ced3b63..66536e80db2 100644
--- a/spec/support/shared_examples/notify_shared_examples.rb
+++ b/spec/support/shared_examples/notify_shared_examples.rb
@@ -45,6 +45,20 @@ shared_examples 'an email that contains a header with author username' do
end
end
+shared_examples 'an email with X-GitLab headers containing IDs' do
+ it 'has X-GitLab-*-ID header' do
+ is_expected.to have_header "X-GitLab-#{model.class.name}-ID", "#{model.id}"
+ end
+
+ it 'has X-GitLab-*-IID header if model has iid defined' do
+ if model.respond_to?(:iid)
+ is_expected.to have_header "X-GitLab-#{model.class.name}-IID", "#{model.iid}"
+ else
+ expect(subject.header["X-GitLab-#{model.class.name}-IID"]).to eq nil
+ end
+ end
+end
+
shared_examples 'an email with X-GitLab headers containing project details' do
it 'has X-GitLab-Project headers' do
aggregate_failures do
@@ -69,6 +83,7 @@ end
shared_examples 'a thread answer email with reply-by-email enabled' do
include_examples 'an email with X-GitLab headers containing project details'
+ include_examples 'an email with X-GitLab headers containing IDs'
it 'has the characteristics of a threaded reply' do
host = Gitlab.config.gitlab.host
@@ -85,6 +100,7 @@ end
shared_examples 'an email starting a new thread with reply-by-email enabled' do
include_examples 'an email with X-GitLab headers containing project details'
+ include_examples 'an email with X-GitLab headers containing IDs'
include_examples 'a new thread email with reply-by-email enabled'
it 'includes "Reply to this email directly or <View it on GitLab>"' do
@@ -109,6 +125,7 @@ end
shared_examples 'an answer to an existing thread with reply-by-email enabled' do
include_examples 'an email with X-GitLab headers containing project details'
+ include_examples 'an email with X-GitLab headers containing IDs'
include_examples 'a thread answer email with reply-by-email enabled'
context 'when reply-by-email is enabled with incoming address with %{key}' do
diff --git a/spec/support/shared_examples/requests/api/merge_requests_list.rb b/spec/support/shared_examples/requests/api/merge_requests_list.rb
index 1aed8ab0113..92d4dd598d5 100644
--- a/spec/support/shared_examples/requests/api/merge_requests_list.rb
+++ b/spec/support/shared_examples/requests/api/merge_requests_list.rb
@@ -16,7 +16,12 @@ shared_examples 'merge requests list' do
create(:merge_request, state: 'closed', milestone: milestone1, author: user, assignee: user, source_project: project, target_project: project, title: 'Test', created_at: base_time)
- create(:merge_request, milestone: milestone1, author: user, assignee: user, source_project: project, target_project: project, title: 'Test', created_at: base_time)
+ merge_request = create(:merge_request, milestone: milestone1, author: user, assignee: user, source_project: project, target_project: project, title: 'Test', created_at: base_time)
+
+ merge_request.metrics.update!(merged_by: user,
+ latest_closed_by: user,
+ latest_closed_at: 1.hour.ago,
+ merged_at: 2.hours.ago)
expect do
get api(endpoint_path, user)
@@ -181,6 +186,23 @@ shared_examples 'merge requests list' do
expect(json_response.length).to eq(0)
end
+ it 'returns an array of merge requests with any label when filtering by any label' do
+ get api(endpoint_path, user), labels: IssuesFinder::FILTER_ANY
+
+ expect_paginated_array_response
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['id']).to eq(merge_request.id)
+ end
+
+ it 'returns an array of merge requests without a label when filtering by no label' do
+ get api(endpoint_path, user), labels: IssuesFinder::FILTER_NONE
+
+ response_ids = json_response.map { |merge_request| merge_request['id'] }
+
+ expect_paginated_array_response
+ expect(response_ids).to contain_exactly(merge_request_closed.id, merge_request_merged.id, merge_request_locked.id)
+ end
+
it 'returns an array of labeled merge requests that are merged for a milestone' do
bug_label = create(:label, title: 'bug', color: '#FFAABB', project: project)
diff --git a/spec/support/shared_examples/services/boards/issues_move_service.rb b/spec/support/shared_examples/services/boards/issues_move_service.rb
index 6d29a97c56d..ec44b99d10e 100644
--- a/spec/support/shared_examples/services/boards/issues_move_service.rb
+++ b/spec/support/shared_examples/services/boards/issues_move_service.rb
@@ -34,7 +34,7 @@ shared_examples 'issues move service' do |group|
described_class.new(parent, user, params).execute(issue)
issue.reload
- expect(issue.labels).to contain_exactly(bug)
+ expect(issue.labels).to contain_exactly(bug, regression)
expect(issue).to be_closed
end
end
diff --git a/spec/support/shared_examples/services/boards/lists_move_service.rb b/spec/support/shared_examples/services/boards/lists_move_service.rb
index 07c98cb29b7..2cdb968a45d 100644
--- a/spec/support/shared_examples/services/boards/lists_move_service.rb
+++ b/spec/support/shared_examples/services/boards/lists_move_service.rb
@@ -14,7 +14,7 @@ shared_examples 'lists move service' do
expect(current_list_positions).to eq [0, 1, 2, 3]
end
- it 'keeps position of lists when new positon is equal to old position' do
+ it 'keeps position of lists when new position is equal to old position' do
service = described_class.new(parent, user, position: planning.position)
service.execute(planning)
@@ -22,7 +22,7 @@ shared_examples 'lists move service' do
expect(current_list_positions).to eq [0, 1, 2, 3]
end
- it 'keeps position of lists when new positon is negative' do
+ it 'keeps position of lists when new position is negative' do
service = described_class.new(parent, user, position: -1)
service.execute(planning)
@@ -30,7 +30,7 @@ shared_examples 'lists move service' do
expect(current_list_positions).to eq [0, 1, 2, 3]
end
- it 'keeps position of lists when new positon is equal to number of labels lists' do
+ it 'keeps position of lists when new position is equal to number of labels lists' do
service = described_class.new(parent, user, position: board.lists.label.size)
service.execute(planning)
@@ -38,7 +38,7 @@ shared_examples 'lists move service' do
expect(current_list_positions).to eq [0, 1, 2, 3]
end
- it 'keeps position of lists when new positon is greater than number of labels lists' do
+ it 'keeps position of lists when new position is greater than number of labels lists' do
service = described_class.new(parent, user, position: board.lists.label.size + 1)
service.execute(planning)
@@ -46,7 +46,7 @@ shared_examples 'lists move service' do
expect(current_list_positions).to eq [0, 1, 2, 3]
end
- it 'increments position of intermediate lists when new positon is equal to first position' do
+ it 'increments position of intermediate lists when new position is equal to first position' do
service = described_class.new(parent, user, position: 0)
service.execute(staging)
@@ -54,7 +54,7 @@ shared_examples 'lists move service' do
expect(current_list_positions).to eq [1, 2, 3, 0]
end
- it 'decrements position of intermediate lists when new positon is equal to last position' do
+ it 'decrements position of intermediate lists when new position is equal to last position' do
service = described_class.new(parent, user, position: board.lists.label.last.position)
service.execute(planning)
diff --git a/spec/support/shared_examples/services/check_ingress_ip_address_service_shared_examples.rb b/spec/support/shared_examples/services/check_ingress_ip_address_service_shared_examples.rb
new file mode 100644
index 00000000000..14638a574a5
--- /dev/null
+++ b/spec/support/shared_examples/services/check_ingress_ip_address_service_shared_examples.rb
@@ -0,0 +1,33 @@
+shared_examples 'check ingress ip executions' do |app_name|
+ describe '#execute' do
+ let(:application) { create(app_name, :installed) }
+ let(:service) { described_class.new(application) }
+ let(:kubeclient) { double(::Kubeclient::Client, get_service: kube_service) }
+
+ context 'when the ingress ip address is available' do
+ it 'updates the external_ip for the app' do
+ subject
+
+ expect(application.external_ip).to eq('111.222.111.222')
+ end
+ end
+
+ context 'when the ingress ip address is not available' do
+ let(:ingress) { nil }
+
+ it 'does not error' do
+ subject
+ end
+ end
+
+ context 'when the exclusive lease cannot be obtained' do
+ it 'does not call kubeclient' do
+ stub_exclusive_lease_taken(lease_key, timeout: 15.seconds.to_i)
+
+ subject
+
+ expect(kubeclient).not_to have_received(:get_service)
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/uploaders/gitlab_uploader_shared_examples.rb b/spec/support/shared_examples/uploaders/gitlab_uploader_shared_examples.rb
index 93c21a99e59..1190863d88e 100644
--- a/spec/support/shared_examples/uploaders/gitlab_uploader_shared_examples.rb
+++ b/spec/support/shared_examples/uploaders/gitlab_uploader_shared_examples.rb
@@ -33,6 +33,14 @@ shared_examples "builds correct paths" do |**patterns|
it_behaves_like "matches the method pattern", :upload_path
end
+ describe "#relative_path" do
+ it 'is relative' do
+ skip 'Path not set, skipping.' unless subject.path
+
+ expect(Pathname.new(subject.relative_path)).to be_relative
+ end
+ end
+
describe ".absolute_path" do
it_behaves_like "matches the method pattern", :absolute_path do
let(:target) { subject.class }
diff --git a/spec/support/stored_repositories.rb b/spec/support/stored_repositories.rb
index 26f823cb6ef..55212355daa 100644
--- a/spec/support/stored_repositories.rb
+++ b/spec/support/stored_repositories.rb
@@ -1,30 +1,7 @@
RSpec.configure do |config|
- config.before(:all, :broken_storage) do
- FileUtils.rm_rf Gitlab.config.repositories.storages.broken.legacy_disk_path
- end
-
config.before(:each, :broken_storage) do
allow(Gitlab::GitalyClient).to receive(:call) do
raise GRPC::Unavailable.new('Gitaly broken in this spec')
end
-
- # Track the maximum number of failures
- first_failure = Time.parse("2017-11-14 17:52:30")
- last_failure = Time.parse("2017-11-14 18:54:37")
- failure_count = Gitlab::CurrentSettings.circuitbreaker_failure_count_threshold + 1
- cache_key = "#{Gitlab::Git::Storage::REDIS_KEY_PREFIX}broken:#{Gitlab::Environment.hostname}"
-
- Gitlab::Git::Storage.redis.with do |redis|
- redis.pipelined do
- redis.zadd(Gitlab::Git::Storage::REDIS_KNOWN_KEYS, 0, cache_key)
- redis.hset(cache_key, :first_failure, first_failure.to_i)
- redis.hset(cache_key, :last_failure, last_failure.to_i)
- redis.hset(cache_key, :failure_count, failure_count.to_i)
- end
- end
- end
-
- config.after(:each, :broken_storage) do
- Gitlab::Git::Storage.redis.with(&:flushall)
end
end
diff --git a/spec/support/stub_version.rb b/spec/support/stub_version.rb
new file mode 100644
index 00000000000..594ab64e7c6
--- /dev/null
+++ b/spec/support/stub_version.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+module StubVersion
+ def stub_version(version, revision)
+ stub_const('Gitlab::VERSION', version)
+ allow(Gitlab).to receive(:revision).and_return(revision)
+ end
+end
diff --git a/spec/tasks/cache/clear/redis_spec.rb b/spec/tasks/cache/clear/redis_spec.rb
index cca2b864e9b..97c8c943f3a 100644
--- a/spec/tasks/cache/clear/redis_spec.rb
+++ b/spec/tasks/cache/clear/redis_spec.rb
@@ -6,7 +6,10 @@ describe 'clearing redis cache' do
end
describe 'clearing pipeline status cache' do
- let(:pipeline_status) { create(:ci_pipeline).project.pipeline_status }
+ let(:pipeline_status) do
+ project = create(:project, :repository)
+ create(:ci_pipeline, project: project).project.pipeline_status
+ end
before do
allow(pipeline_status).to receive(:loaded).and_return(nil)
diff --git a/spec/tasks/gitlab/backup_rake_spec.rb b/spec/tasks/gitlab/backup_rake_spec.rb
index 3ba6caf1337..8c4360d4cf0 100644
--- a/spec/tasks/gitlab/backup_rake_spec.rb
+++ b/spec/tasks/gitlab/backup_rake_spec.rb
@@ -251,7 +251,7 @@ describe 'gitlab:app namespace rake task' do
allow(Gitlab.config.repositories).to receive(:storages).and_return(storages)
- # Avoid asking gitaly about the root ref (which will fail beacuse of the
+ # Avoid asking gitaly about the root ref (which will fail because of the
# mocked storages)
allow_any_instance_of(Repository).to receive(:empty?).and_return(false)
end
diff --git a/spec/tasks/gitlab/site_statistics_rake_spec.rb b/spec/tasks/gitlab/site_statistics_rake_spec.rb
deleted file mode 100644
index 20f0df65e63..00000000000
--- a/spec/tasks/gitlab/site_statistics_rake_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-require 'rake_helper'
-
-describe 'rake gitlab:refresh_site_statistics' do
- before do
- Rake.application.rake_require 'tasks/gitlab/site_statistics'
-
- create(:project)
- SiteStatistic.fetch.update(repositories_count: 0, wikis_count: 0)
- end
-
- let(:task) { 'gitlab:refresh_site_statistics' }
-
- it 'recalculates existing counters' do
- run_rake_task(task)
-
- expect(SiteStatistic.fetch.repositories_count).to eq(1)
- expect(SiteStatistic.fetch.wikis_count).to eq(1)
- end
-
- it 'displays message listing counters' do
- expect { run_rake_task(task) }.to output(/Updating Site Statistics counters:.* Repositories\.\.\. OK!.* Wikis\.\.\. OK!/m).to_stdout
- end
-end
diff --git a/spec/tasks/gitlab/uploads/migrate_rake_spec.rb b/spec/tasks/gitlab/uploads/migrate_rake_spec.rb
index 6fcfae358ec..9588e8be5dc 100644
--- a/spec/tasks/gitlab/uploads/migrate_rake_spec.rb
+++ b/spec/tasks/gitlab/uploads/migrate_rake_spec.rb
@@ -38,14 +38,6 @@ describe 'gitlab:uploads:migrate rake tasks' do
let!(:projects) { create_list(:project, 10, :with_avatar) }
it_behaves_like 'enqueue jobs in batch', batch: 4
-
- context 'Upload has store = nil' do
- before do
- Upload.where(model: projects).update_all(store: nil)
- end
-
- it_behaves_like 'enqueue jobs in batch', batch: 4
- end
end
context "for Group" do
diff --git a/spec/unicorn/unicorn_spec.rb b/spec/unicorn/unicorn_spec.rb
deleted file mode 100644
index a4cf479a339..00000000000
--- a/spec/unicorn/unicorn_spec.rb
+++ /dev/null
@@ -1,114 +0,0 @@
-require 'fileutils'
-
-require 'excon'
-
-require 'spec_helper'
-
-describe 'Unicorn' do
- before(:all) do
- config_lines = File.read('config/unicorn.rb.example').split("\n")
-
- # Remove these because they make setup harder.
- config_lines = config_lines.reject do |line|
- %w[
- working_directory
- worker_processes
- listen
- pid
- stderr_path
- stdout_path
- ].any? { |prefix| line.start_with?(prefix) }
- end
-
- config_lines << "working_directory '#{Rails.root}'"
-
- # We want to have exactly 1 worker process because that makes it
- # predictable which process will handle our requests.
- config_lines << 'worker_processes 1'
-
- @socket_path = File.join(Dir.pwd, 'tmp/tests/unicorn.socket')
- config_lines << "listen '#{@socket_path}'"
-
- ready_file = 'tmp/tests/unicorn-worker-ready'
- FileUtils.rm_f(ready_file)
- after_fork_index = config_lines.index { |l| l.start_with?('after_fork') }
- config_lines.insert(after_fork_index + 1, "File.write('#{ready_file}', Process.pid)")
-
- config_path = 'tmp/tests/unicorn.rb'
- File.write(config_path, config_lines.join("\n") + "\n")
-
- rackup_path = 'tmp/tests/config.ru'
- File.write(rackup_path, <<~EOS)
- app =
- proc do |env|
- if env['REQUEST_METHOD'] == 'GET'
- [200, {}, [Process.pid]]
- else
- Process.kill(env['QUERY_STRING'], Process.pid)
- [200, {}, ['Bye!']]
- end
- end
-
- run app
- EOS
-
- cmd = %W[unicorn -E test -c #{config_path} #{rackup_path}]
- @unicorn_master_pid = spawn(*cmd)
- wait_unicorn_boot!(@unicorn_master_pid, ready_file)
- WebMock.allow_net_connect!
- end
-
- %w[SIGQUIT SIGTERM SIGKILL].each do |signal|
- it "has a worker that self-terminates on signal #{signal}" do
- response = Excon.get('unix://', socket: @socket_path)
- expect(response.status).to eq(200)
-
- worker_pid = response.body.to_i
- expect(worker_pid).to be > 0
-
- begin
- Excon.post("unix://?#{signal}", socket: @socket_path)
- rescue Excon::Error::Socket
- # The connection may be closed abruptly
- end
-
- expect(pid_gone?(worker_pid)).to eq(true)
- end
- end
-
- after(:all) do
- WebMock.disable_net_connect!(allow_localhost: true)
- Process.kill('TERM', @unicorn_master_pid)
- end
-
- def wait_unicorn_boot!(master_pid, ready_file)
- # We have seen the boot timeout after 2 minutes in CI so let's set it to 5 minutes.
- timeout = 5 * 60
- timeout.times do
- return if File.exist?(ready_file)
-
- pid = Process.waitpid(master_pid, Process::WNOHANG)
- raise "unicorn failed to boot: #{$?}" unless pid.nil?
-
- sleep 1
- end
-
- raise "unicorn boot timed out after #{timeout} seconds"
- end
-
- def pid_gone?(pid)
- # Worker termination should take less than a second. That makes 10
- # seconds a generous timeout.
- 10.times do
- begin
- Process.kill(0, pid)
- rescue Errno::ESRCH
- return true
- end
-
- sleep 1
- end
-
- false
- end
-end
diff --git a/spec/uploaders/file_uploader_spec.rb b/spec/uploaders/file_uploader_spec.rb
index 7e24efda5dd..c74e0bf1955 100644
--- a/spec/uploaders/file_uploader_spec.rb
+++ b/spec/uploaders/file_uploader_spec.rb
@@ -81,19 +81,24 @@ describe FileUploader do
end
describe 'copy_to' do
+ let(:new_project) { create(:project) }
+ let(:moved) { described_class.copy_to(subject, new_project) }
+
shared_examples 'returns a valid uploader' do
describe 'returned uploader' do
- let(:new_project) { create(:project) }
- let(:moved) { described_class.copy_to(subject, new_project) }
-
it 'generates a new secret' do
expect(subject).to be
expect(described_class).to receive(:generate_secret).once.and_call_original
expect(moved).to be
end
- it 'create new upload' do
- expect(moved.upload).not_to eq(subject.upload)
+ it 'creates new upload correctly' do
+ upload = moved.upload
+
+ expect(upload).not_to eq(subject.upload)
+ expect(upload.model).to eq(new_project)
+ expect(upload.uploader).to eq('FileUploader')
+ expect(upload.secret).not_to eq(subject.upload.secret)
end
it 'copies the file' do
@@ -111,6 +116,12 @@ describe FileUploader do
end
include_examples 'returns a valid uploader'
+
+ it 'copies the file to the correct location' do
+ expect(moved.upload.path).to eq("#{moved.upload.secret}/dk.png")
+ expect(moved.file.path).to end_with("public/uploads/#{new_project.disk_path}/#{moved.upload.secret}/dk.png")
+ expect(moved.filename).to eq('dk.png')
+ end
end
context 'files are stored remotely' do
@@ -121,6 +132,12 @@ describe FileUploader do
end
include_examples 'returns a valid uploader'
+
+ it 'copies the file to the correct location' do
+ expect(moved.upload.path).to eq("#{new_project.disk_path}/#{moved.upload.secret}/dk.png")
+ expect(moved.file.path).to eq("#{new_project.disk_path}/#{moved.upload.secret}/dk.png")
+ expect(moved.filename).to eq('dk.png')
+ end
end
end
diff --git a/spec/uploaders/namespace_file_uploader_spec.rb b/spec/uploaders/namespace_file_uploader_spec.rb
index 799c6db57fa..d09725ee4be 100644
--- a/spec/uploaders/namespace_file_uploader_spec.rb
+++ b/spec/uploaders/namespace_file_uploader_spec.rb
@@ -55,4 +55,62 @@ describe NamespaceFileUploader do
it_behaves_like "migrates", to_store: described_class::Store::REMOTE
it_behaves_like "migrates", from_store: described_class::Store::REMOTE, to_store: described_class::Store::LOCAL
end
+
+ describe 'copy_to' do
+ let(:group) { create(:group) }
+ let(:moved) { described_class.copy_to(subject, group) }
+
+ shared_examples 'returns a valid uploader' do
+ it 'generates a new secret' do
+ expect(subject).to be
+ expect(described_class).to receive(:generate_secret).once.and_call_original
+ expect(moved).to be
+ end
+
+ it 'creates new upload correctly' do
+ upload = moved.upload
+
+ expect(upload).not_to eq(subject.upload)
+ expect(upload.model).to eq(group)
+ expect(upload.uploader).to eq('NamespaceFileUploader')
+ expect(upload.secret).not_to eq(subject.upload.secret)
+ end
+
+ it 'copies the file' do
+ expect(subject.file).to exist
+ expect(moved.file).to exist
+ expect(subject.file).not_to eq(moved.file)
+ expect(subject.object_store).to eq(moved.object_store)
+ end
+ end
+
+ context 'files are stored locally' do
+ before do
+ subject.store!(fixture_file_upload('spec/fixtures/dk.png'))
+ end
+
+ include_examples 'returns a valid uploader'
+
+ it 'copies the file to the correct location' do
+ expect(moved.upload.path).to eq("#{moved.upload.secret}/dk.png")
+ expect(moved.file.path).to end_with("system/namespace/#{group.id}/#{moved.upload.secret}/dk.png")
+ expect(moved.filename).to eq('dk.png')
+ end
+ end
+
+ context 'files are stored remotely' do
+ before do
+ stub_uploads_object_storage
+ subject.store!(fixture_file_upload('spec/fixtures/dk.png'))
+ subject.migrate!(ObjectStorage::Store::REMOTE)
+ end
+
+ include_examples 'returns a valid uploader'
+
+ it 'copies the file to the correct location' do
+ expect(moved.file.path).to eq("namespace/#{group.id}/#{moved.upload.secret}/dk.png")
+ expect(moved.filename).to eq('dk.png')
+ end
+ end
+ end
end
diff --git a/spec/validators/url_validator_spec.rb b/spec/validators/url_validator_spec.rb
index ab6100509a6..082d09d3f16 100644
--- a/spec/validators/url_validator_spec.rb
+++ b/spec/validators/url_validator_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
require 'spec_helper'
describe UrlValidator do
@@ -6,6 +8,30 @@ describe UrlValidator do
include_examples 'url validator examples', described_class::DEFAULT_PROTOCOLS
+ describe 'validations' do
+ include_context 'invalid urls'
+
+ let(:validator) { described_class.new(attributes: [:link_url]) }
+
+ it 'returns error when url is nil' do
+ expect(validator.validate_each(badge, :link_url, nil)).to be_nil
+ expect(badge.errors.first[1]).to eq 'must be a valid URL'
+ end
+
+ it 'returns error when url is empty' do
+ expect(validator.validate_each(badge, :link_url, '')).to be_nil
+ expect(badge.errors.first[1]).to eq 'must be a valid URL'
+ end
+
+ it 'does not allow urls with CR or LF characters' do
+ aggregate_failures do
+ urls_with_CRLF.each do |url|
+ expect(validator.validate_each(badge, :link_url, url)[0]).to eq 'is blocked: URI is invalid'
+ end
+ end
+ end
+ end
+
context 'by default' do
let(:validator) { described_class.new(attributes: [:link_url]) }
diff --git a/spec/views/help/index.html.haml_spec.rb b/spec/views/help/index.html.haml_spec.rb
index 4b4de540d9e..34e93d929a7 100644
--- a/spec/views/help/index.html.haml_spec.rb
+++ b/spec/views/help/index.html.haml_spec.rb
@@ -1,11 +1,18 @@
+# frozen_string_literal: true
+
require 'rails_helper'
describe 'help/index' do
+ include StubVersion
+
describe 'version information' do
+ before do
+ stub_helpers
+ end
+
it 'is hidden from guests' do
stub_user(nil)
stub_version('8.0.2', 'abcdefg')
- stub_helpers
render
@@ -13,15 +20,28 @@ describe 'help/index' do
expect(rendered).not_to match 'abcdefg'
end
- it 'is shown to users' do
- stub_user
- stub_version('8.0.2', 'abcdefg')
- stub_helpers
+ context 'when logged in' do
+ before do
+ stub_user
+ end
- render
+ it 'shows a link to the tag to users' do
+ stub_version('8.0.2', 'abcdefg')
+
+ render
+
+ expect(rendered).to match '8.0.2'
+ expect(rendered).to have_link('8.0.2', href: %r{https://gitlab.com/gitlab-org/gitlab-(ce|ee)/tags/v8.0.2})
+ end
+
+ it 'shows a link to the commit for pre-releases' do
+ stub_version('8.0.2-pre', 'abcdefg')
- expect(rendered).to match '8.0.2'
- expect(rendered).to have_link('abcdefg', href: 'https://gitlab.com/gitlab-org/gitlab-ce/commits/abcdefg')
+ render
+
+ expect(rendered).to match '8.0.2'
+ expect(rendered).to have_link('abcdefg', href: %r{https://gitlab.com/gitlab-org/gitlab-(ce|ee)/commits/abcdefg})
+ end
end
end
@@ -37,11 +57,6 @@ describe 'help/index' do
allow(view).to receive(:user_signed_in?).and_return(user)
end
- def stub_version(version, revision)
- stub_const('Gitlab::VERSION', version)
- allow(Gitlab).to receive(:revision).and_return(revision)
- end
-
def stub_helpers
allow(view).to receive(:markdown).and_return('')
allow(view).to receive(:version_status_badge).and_return('')
diff --git a/spec/views/layouts/header/_new_dropdown.haml_spec.rb b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
new file mode 100644
index 00000000000..2e19d0cec26
--- /dev/null
+++ b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
@@ -0,0 +1,134 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'layouts/header/_new_dropdown' do
+ let(:user) { create(:user) }
+
+ context 'group-specific links' do
+ let(:group) { create(:group) }
+
+ before do
+ stub_current_user(user)
+
+ assign(:group, group)
+ end
+
+ context 'as a Group owner' do
+ before do
+ group.add_owner(user)
+ end
+
+ it 'has a "New project" link' do
+ render
+
+ expect(rendered).to have_link(
+ 'New project',
+ href: new_project_path(namespace_id: group.id)
+ )
+ end
+
+ it 'has a "New subgroup" link', :nested_groups do
+ render
+
+ expect(rendered).to have_link(
+ 'New subgroup',
+ href: new_group_path(parent_id: group.id)
+ )
+ end
+ end
+ end
+
+ context 'project-specific links' do
+ let(:project) { create(:project, creator: user, namespace: user.namespace) }
+
+ before do
+ assign(:project, project)
+ end
+
+ context 'as a Project owner' do
+ before do
+ stub_current_user(user)
+ end
+
+ it 'has a "New issue" link' do
+ render
+
+ expect(rendered).to have_link(
+ 'New issue',
+ href: new_project_issue_path(project)
+ )
+ end
+
+ it 'has a "New merge request" link' do
+ render
+
+ expect(rendered).to have_link(
+ 'New merge request',
+ href: project_new_merge_request_path(project)
+ )
+ end
+
+ it 'has a "New snippet" link' do
+ render
+
+ expect(rendered).to have_link(
+ 'New snippet',
+ href: new_project_snippet_path(project)
+ )
+ end
+ end
+
+ context 'as a Project guest' do
+ let(:guest) { create(:user) }
+
+ before do
+ stub_current_user(guest)
+ project.add_guest(guest)
+ end
+
+ it 'has no "New merge request" link' do
+ render
+
+ expect(rendered).not_to have_link('New merge request')
+ end
+
+ it 'has no "New snippet" link' do
+ render
+
+ expect(rendered).not_to have_link(
+ 'New snippet',
+ href: new_project_snippet_path(project)
+ )
+ end
+ end
+ end
+
+ context 'global links' do
+ before do
+ stub_current_user(user)
+ end
+
+ it 'has a "New project" link' do
+ render
+
+ expect(rendered).to have_link('New project', href: new_project_path)
+ end
+
+ it 'has a "New group" link' do
+ render
+
+ expect(rendered).to have_link('New group', href: new_group_path)
+ end
+
+ it 'has a "New snippet" link' do
+ render
+
+ expect(rendered).to have_link('New snippet', href: new_snippet_path)
+ end
+ end
+
+ def stub_current_user(current_user)
+ allow(view).to receive(:current_user).and_return(current_user)
+ end
+end
diff --git a/spec/views/projects/blob/_viewer.html.haml_spec.rb b/spec/views/projects/blob/_viewer.html.haml_spec.rb
index aedbaa66d34..95f7f87d37b 100644
--- a/spec/views/projects/blob/_viewer.html.haml_spec.rb
+++ b/spec/views/projects/blob/_viewer.html.haml_spec.rb
@@ -29,6 +29,8 @@ describe 'projects/blob/_viewer.html.haml' do
controller.params[:namespace_id] = project.namespace.to_param
controller.params[:project_id] = project.to_param
controller.params[:id] = File.join('master', blob.path)
+
+ allow(project.repository).to receive(:gitattribute).and_return(nil)
end
def render_view
diff --git a/spec/views/projects/jobs/show.html.haml_spec.rb b/spec/views/projects/jobs/show.html.haml_spec.rb
index c93152b88e3..e06a9ecb98b 100644
--- a/spec/views/projects/jobs/show.html.haml_spec.rb
+++ b/spec/views/projects/jobs/show.html.haml_spec.rb
@@ -18,161 +18,6 @@ describe 'projects/jobs/show' do
allow(view).to receive(:can?).and_return(true)
end
- describe 'environment info in job view' do
- context 'job with latest deployment' do
- let(:build) do
- create(:ci_build, :success, :trace_artifact, environment: 'staging')
- end
-
- before do
- create(:environment, name: 'staging')
- create(:deployment, deployable: build)
- end
-
- it 'shows deployment message' do
- expected_text = 'This job is the most recent deployment'
- render
-
- expect(rendered).to have_css(
- '.environment-information', text: expected_text)
- end
- end
-
- context 'job with outdated deployment' do
- let(:build) do
- create(:ci_build, :success, :trace_artifact, environment: 'staging', pipeline: pipeline)
- end
-
- let(:second_build) do
- create(:ci_build, :success, :trace_artifact, environment: 'staging', pipeline: pipeline)
- end
-
- let(:environment) do
- create(:environment, name: 'staging', project: project)
- end
-
- let!(:first_deployment) do
- create(:deployment, environment: environment, deployable: build)
- end
-
- let!(:second_deployment) do
- create(:deployment, environment: environment, deployable: second_build)
- end
-
- it 'shows deployment message' do
- expected_text = 'This job is an out-of-date deployment ' \
- "to staging.\nView the most recent deployment ##{second_deployment.iid}."
- render
-
- expect(rendered).to have_css('.environment-information', text: expected_text)
- end
- end
-
- context 'job failed to deploy' do
- let(:build) do
- create(:ci_build, :failed, :trace_artifact, environment: 'staging', pipeline: pipeline)
- end
-
- let!(:environment) do
- create(:environment, name: 'staging', project: project)
- end
-
- it 'shows deployment message' do
- expected_text = 'The deployment of this job to staging did not succeed.'
- render
-
- expect(rendered).to have_css(
- '.environment-information', text: expected_text)
- end
- end
-
- context 'job will deploy' do
- let(:build) do
- create(:ci_build, :running, :trace_live, environment: 'staging', pipeline: pipeline)
- end
-
- context 'when environment exists' do
- let!(:environment) do
- create(:environment, name: 'staging', project: project)
- end
-
- it 'shows deployment message' do
- expected_text = 'This job is creating a deployment to staging'
- render
-
- expect(rendered).to have_css(
- '.environment-information', text: expected_text)
- end
-
- context 'when it has deployment' do
- let!(:deployment) do
- create(:deployment, environment: environment)
- end
-
- it 'shows that deployment will be overwritten' do
- expected_text = 'This job is creating a deployment to staging'
- render
-
- expect(rendered).to have_css(
- '.environment-information', text: expected_text)
- expect(rendered).to have_css(
- '.environment-information', text: 'latest deployment')
- end
- end
- end
-
- context 'when environment does not exist' do
- it 'shows deployment message' do
- expected_text = 'This job is creating a deployment to staging'
- render
-
- expect(rendered).to have_css(
- '.environment-information', text: expected_text)
- expect(rendered).not_to have_css(
- '.environment-information', text: 'latest deployment')
- end
- end
- end
-
- context 'job that failed to deploy and environment has not been created' do
- let(:build) do
- create(:ci_build, :failed, :trace_artifact, environment: 'staging', pipeline: pipeline)
- end
-
- let!(:environment) do
- create(:environment, name: 'staging', project: project)
- end
-
- it 'shows deployment message' do
- expected_text = 'The deployment of this job to staging did not succeed'
- render
-
- expect(rendered).to have_css(
- '.environment-information', text: expected_text)
- end
- end
-
- context 'job that will deploy and environment has not been created' do
- let(:build) do
- create(:ci_build, :running, :trace_live, environment: 'staging', pipeline: pipeline)
- end
-
- let!(:environment) do
- create(:environment, name: 'staging', project: project)
- end
-
- it 'shows deployment message' do
- expected_text = 'This job is creating a deployment to staging'
- render
-
- expect(rendered).to have_css(
- '.environment-information', text: expected_text)
- expect(rendered).not_to have_css(
- '.environment-information', text: 'latest deployment')
- end
- end
- end
-
context 'when job is running' do
let(:build) { create(:ci_build, :trace_live, :running, pipeline: pipeline) }
@@ -188,40 +33,4 @@ describe 'projects/jobs/show' do
expect(rendered).not_to have_link('New issue')
end
end
-
- context 'when incomplete trigger_request is used' do
- before do
- build.trigger_request = FactoryBot.build(:ci_trigger_request, trigger: nil)
- end
-
- it 'test should not render token block' do
- render
-
- expect(rendered).not_to have_content('Token')
- end
- end
-
- context 'when complete trigger_request is used' do
- before do
- build.trigger_request = FactoryBot.build(:ci_trigger_request)
- end
-
- it 'should render token' do
- render
-
- expect(rendered).to have_content('Token')
- expect(rendered).to have_content(build.trigger_request.trigger.short_token)
- end
- end
-
- describe 'commit title in sidebar' do
- let(:commit_title) { project.commit.title }
-
- it 'shows commit title and not show commit message' do
- render
-
- expect(rendered).to have_css('p.build-light-text.append-bottom-0',
- text: /\A\n#{Regexp.escape(commit_title)}\n\Z/)
- end
- end
end
diff --git a/spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb b/spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb
index 8befae39d3a..0206928a211 100644
--- a/spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb
+++ b/spec/views/projects/merge_requests/creations/_new_submit.html.haml_spec.rb
@@ -12,6 +12,7 @@ describe 'projects/merge_requests/creations/_new_submit.html.haml' do
assign(:hidden_commit_count, 0)
assign(:total_commit_count, merge_request.commits.count)
assign(:project, merge_request.target_project)
+ assign(:mr_presenter, merge_request.present(current_user: merge_request.author))
allow(view).to receive(:can?).and_return(true)
allow(view).to receive(:url_for).and_return('#')
diff --git a/spec/views/projects/merge_requests/edit.html.haml_spec.rb b/spec/views/projects/merge_requests/edit.html.haml_spec.rb
index 9b74a7e1946..c13eab30054 100644
--- a/spec/views/projects/merge_requests/edit.html.haml_spec.rb
+++ b/spec/views/projects/merge_requests/edit.html.haml_spec.rb
@@ -24,6 +24,7 @@ describe 'projects/merge_requests/edit.html.haml' do
before do
assign(:project, project)
assign(:merge_request, closed_merge_request)
+ assign(:mr_presenter, closed_merge_request.present(current_user: user))
allow(view).to receive(:can?).and_return(true)
allow(view).to receive(:current_user)
diff --git a/spec/views/projects/notes/_more_actions_dropdown.html.haml_spec.rb b/spec/views/projects/notes/_more_actions_dropdown.html.haml_spec.rb
index 9c0be249a50..8a9ab02eaca 100644
--- a/spec/views/projects/notes/_more_actions_dropdown.html.haml_spec.rb
+++ b/spec/views/projects/notes/_more_actions_dropdown.html.haml_spec.rb
@@ -12,10 +12,10 @@ describe 'projects/notes/_more_actions_dropdown' do
assign(:project, project)
end
- it 'shows Report as abuse button if not editable and not current users comment' do
+ it 'shows Report abuse to GitLab button if not editable and not current users comment' do
render 'projects/notes/more_actions_dropdown', current_user: not_author_user, note_editable: false, note: note
- expect(rendered).to have_link('Report as abuse')
+ expect(rendered).to have_link('Report abuse to GitLab')
end
it 'does not show the More actions button if not editable and current users comment' do
@@ -24,10 +24,10 @@ describe 'projects/notes/_more_actions_dropdown' do
expect(rendered).not_to have_selector('.dropdown.more-actions')
end
- it 'shows Report as abuse and Delete buttons if editable and not current users comment' do
+ it 'shows Report abuse to GitLab and Delete buttons if editable and not current users comment' do
render 'projects/notes/more_actions_dropdown', current_user: not_author_user, note_editable: true, note: note
- expect(rendered).to have_link('Report as abuse')
+ expect(rendered).to have_link('Report abuse to GitLab')
expect(rendered).to have_link('Delete comment')
end
diff --git a/spec/views/projects/tree/_blob_item.html.haml_spec.rb b/spec/views/projects/tree/_blob_item.html.haml_spec.rb
deleted file mode 100644
index 6a477c712ff..00000000000
--- a/spec/views/projects/tree/_blob_item.html.haml_spec.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-require 'spec_helper'
-
-describe 'projects/tree/_blob_item' do
- let(:project) { create(:project, :repository) }
- let(:repository) { project.repository }
- let(:blob_item) { Gitlab::Git::Tree.where(repository, SeedRepo::Commit::ID, 'files/ruby').first }
-
- before do
- assign(:project, project)
- assign(:repository, repository)
- assign(:id, File.join('master', ''))
- assign(:lfs_blob_ids, [])
- end
-
- it 'renders blob item' do
- render_partial(blob_item)
-
- expect(rendered).to have_content(blob_item.name)
- expect(rendered).not_to have_selector('.label-lfs', text: 'LFS')
- end
-
- describe 'LFS blob' do
- before do
- assign(:lfs_blob_ids, [blob_item].map(&:id))
-
- render_partial(blob_item)
- end
-
- it 'renders LFS badge' do
- expect(rendered).to have_selector('.label-lfs', text: 'LFS')
- end
- end
-
- def render_partial(blob_item)
- render partial: 'projects/tree/blob_item', locals: {
- blob_item: blob_item,
- type: 'blob'
- }
- end
-end
diff --git a/spec/views/projects/tree/_tree_row.html.haml_spec.rb b/spec/views/projects/tree/_tree_row.html.haml_spec.rb
new file mode 100644
index 00000000000..3353b7665e2
--- /dev/null
+++ b/spec/views/projects/tree/_tree_row.html.haml_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe 'projects/tree/_tree_row' do
+ let(:project) { create(:project, :repository) }
+ let(:repository) { project.repository }
+ let(:blob_item) { Gitlab::Git::Tree.where(repository, SeedRepo::Commit::ID, 'files/ruby').first }
+
+ before do
+ assign(:project, project)
+ assign(:repository, repository)
+ assign(:id, File.join('master', ''))
+ assign(:lfs_blob_ids, [])
+ end
+
+ it 'renders blob item' do
+ render_partial(blob_item)
+
+ expect(rendered).to have_content(blob_item.name)
+ expect(rendered).not_to have_selector('.label-lfs', text: 'LFS')
+ end
+
+ describe 'LFS blob' do
+ before do
+ assign(:lfs_blob_ids, [blob_item].map(&:id))
+
+ render_partial(blob_item)
+ end
+
+ it 'renders LFS badge' do
+ expect(rendered).to have_selector('.label-lfs', text: 'LFS')
+ end
+ end
+
+ def render_partial(items)
+ render partial: 'projects/tree/tree_row', collection: [items].flatten
+ end
+end
diff --git a/spec/views/shared/runners/show.html.haml_spec.rb b/spec/views/shared/runners/show.html.haml_spec.rb
new file mode 100644
index 00000000000..5e92928b143
--- /dev/null
+++ b/spec/views/shared/runners/show.html.haml_spec.rb
@@ -0,0 +1,155 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'shared/runners/show.html.haml' do
+ include PageLayoutHelper
+
+ let(:runner) do
+ create(:ci_runner, name: 'test runner',
+ version: '11.4.0',
+ ip_address: '127.1.2.3',
+ revision: 'abcd1234',
+ architecture: 'amd64' )
+ end
+
+ before do
+ assign(:runner, runner)
+ end
+
+ subject do
+ render
+ rendered
+ end
+
+ describe 'Page title' do
+ before do
+ expect_any_instance_of(PageLayoutHelper).to receive(:page_title).with("#{runner.description} ##{runner.id}", 'Runners')
+ end
+
+ it 'sets proper page title' do
+ render
+ end
+ end
+
+ describe 'Runner id and type' do
+ context 'when runner is of type instance' do
+ it { is_expected.to have_content("Runner ##{runner.id} Shared") }
+ end
+
+ context 'when runner is of type group' do
+ let(:runner) { create(:ci_runner, :group) }
+
+ it { is_expected.to have_content("Runner ##{runner.id} Group") }
+ end
+
+ context 'when runner is of type project' do
+ let(:runner) { create(:ci_runner, :project) }
+
+ it { is_expected.to have_content("Runner ##{runner.id} Specific") }
+ end
+ end
+
+ describe 'Active value' do
+ context 'when runner is active' do
+ it { is_expected.to have_content('Active Yes') }
+ end
+
+ context 'when runner is inactive' do
+ let(:runner) { create(:ci_runner, :inactive) }
+
+ it { is_expected.to have_content('Active No') }
+ end
+ end
+
+ describe 'Protected value' do
+ context 'when runner is not protected' do
+ it { is_expected.to have_content('Protected No') }
+ end
+
+ context 'when runner is protected' do
+ let(:runner) { create(:ci_runner, :ref_protected) }
+
+ it { is_expected.to have_content('Protected Yes') }
+ end
+ end
+
+ describe 'Can run untagged jobs value' do
+ context 'when runner run untagged job is set' do
+ it { is_expected.to have_content('Can run untagged jobs Yes') }
+ end
+
+ context 'when runner run untagged job is unset' do
+ let(:runner) { create(:ci_runner, :tagged_only) }
+
+ it { is_expected.to have_content('Can run untagged jobs No') }
+ end
+ end
+
+ describe 'Locked to this project value' do
+ context 'when runner locked is not set' do
+ it { is_expected.to have_content('Locked to this project No') }
+
+ context 'when runner is of type group' do
+ let(:runner) { create(:ci_runner, :group) }
+
+ it { is_expected.not_to have_content('Locked to this project') }
+ end
+ end
+
+ context 'when runner locked is set' do
+ let(:runner) { create(:ci_runner, :locked) }
+
+ it { is_expected.to have_content('Locked to this project Yes') }
+
+ context 'when runner is of type group' do
+ let(:runner) { create(:ci_runner, :group, :locked) }
+
+ it { is_expected.not_to have_content('Locked to this project') }
+ end
+ end
+ end
+
+ describe 'Tags value' do
+ context 'when runner does not have tags' do
+ it { is_expected.to have_content('Tags') }
+ it { is_expected.not_to have_selector('span.badge.badge-primary')}
+ end
+
+ context 'when runner have tags' do
+ let(:runner) { create(:ci_runner, tag_list: %w(tag2 tag3 tag1)) }
+
+ it { is_expected.to have_content('Tags tag1 tag2 tag3') }
+ it { is_expected.to have_selector('span.badge.badge-primary')}
+ end
+ end
+
+ describe 'Metadata values' do
+ it { is_expected.to have_content("Name #{runner.name}") }
+ it { is_expected.to have_content("Version #{runner.version}") }
+ it { is_expected.to have_content("IP Address #{runner.ip_address}") }
+ it { is_expected.to have_content("Revision #{runner.revision}") }
+ it { is_expected.to have_content("Platform #{runner.platform}") }
+ it { is_expected.to have_content("Architecture #{runner.architecture}") }
+ it { is_expected.to have_content("Description #{runner.description}") }
+ end
+
+ describe 'Maximum job timeout value' do
+ let(:runner) { create(:ci_runner, maximum_timeout: 5400) }
+
+ it { is_expected.to have_content('Maximum job timeout 1h 30m') }
+ end
+
+ describe 'Last contact value' do
+ context 'when runner have not contacted yet' do
+ it { is_expected.to have_content('Last contact Never') }
+ end
+
+ context 'when runner have already contacted' do
+ let(:runner) { create(:ci_runner, contacted_at: DateTime.now - 6.days) }
+ let(:expected_contacted_at) { I18n.localize(runner.contacted_at, format: "%b %d, %Y") }
+
+ it { is_expected.to have_content("Last contact #{expected_contacted_at}") }
+ end
+ end
+end
diff --git a/spec/workers/archive_trace_worker_spec.rb b/spec/workers/archive_trace_worker_spec.rb
index b768588c6e1..7244ad4f199 100644
--- a/spec/workers/archive_trace_worker_spec.rb
+++ b/spec/workers/archive_trace_worker_spec.rb
@@ -5,10 +5,11 @@ describe ArchiveTraceWorker do
subject { described_class.new.perform(job&.id) }
context 'when job is found' do
- let(:job) { create(:ci_build) }
+ let(:job) { create(:ci_build, :trace_live) }
it 'executes service' do
- expect_any_instance_of(Gitlab::Ci::Trace).to receive(:archive!)
+ expect_any_instance_of(Ci::ArchiveTraceService)
+ .to receive(:execute).with(job)
subject
end
@@ -18,7 +19,8 @@ describe ArchiveTraceWorker do
let(:job) { nil }
it 'does not execute service' do
- expect_any_instance_of(Gitlab::Ci::Trace).not_to receive(:archive!)
+ expect_any_instance_of(Ci::ArchiveTraceService)
+ .not_to receive(:execute)
subject
end
diff --git a/spec/workers/build_success_worker_spec.rb b/spec/workers/build_success_worker_spec.rb
index dba70883130..5eb9709ded9 100644
--- a/spec/workers/build_success_worker_spec.rb
+++ b/spec/workers/build_success_worker_spec.rb
@@ -2,15 +2,39 @@ require 'spec_helper'
describe BuildSuccessWorker do
describe '#perform' do
+ subject { described_class.new.perform(build.id) }
+
+ before do
+ allow_any_instance_of(Deployment).to receive(:create_ref)
+ end
+
context 'when build exists' do
- context 'when build belogs to the environment' do
- let!(:build) { create(:ci_build, environment: 'production') }
+ context 'when deployment was not created with the build creation' do # An edge case during the transition period
+ let!(:build) { create(:ci_build, :deploy_to_production) }
+
+ before do
+ Deployment.delete_all
+ build.reload
+ end
- it 'executes deployment service' do
- expect_any_instance_of(CreateDeploymentService)
- .to receive(:execute)
+ it 'creates a successful deployment' do
+ expect(build).not_to be_has_deployment
- described_class.new.perform(build.id)
+ subject
+
+ build.reload
+ expect(build).to be_has_deployment
+ expect(build.deployment).to be_success
+ end
+ end
+
+ context 'when deployment was created with the build creation' do # Counter part of the above edge case
+ let!(:build) { create(:ci_build, :deploy_to_production) }
+
+ it 'does not create a new deployment' do
+ expect(build).to be_has_deployment
+
+ expect { subject }.not_to change { Deployment.count }
end
end
@@ -18,10 +42,22 @@ describe BuildSuccessWorker do
let!(:build) { create(:ci_build, project: nil) }
it 'does not create deployment' do
- expect_any_instance_of(CreateDeploymentService)
- .not_to receive(:execute)
+ subject
+
+ expect(build.reload).not_to be_has_deployment
+ end
+ end
+
+ context 'when the build will stop an environment' do
+ let!(:build) { create(:ci_build, :stop_review_app, environment: environment.name, project: environment.project) }
+ let(:environment) { create(:environment, state: :available) }
+
+ it 'stops the environment' do
+ expect(environment).to be_available
+
+ subject
- described_class.new.perform(build.id)
+ expect(environment.reload).to be_stopped
end
end
end
diff --git a/spec/workers/ci/archive_traces_cron_worker_spec.rb b/spec/workers/ci/archive_traces_cron_worker_spec.rb
index 23f5dda298a..478fb7d2c0f 100644
--- a/spec/workers/ci/archive_traces_cron_worker_spec.rb
+++ b/spec/workers/ci/archive_traces_cron_worker_spec.rb
@@ -30,6 +30,13 @@ describe Ci::ArchiveTracesCronWorker do
it_behaves_like 'archives trace'
+ it 'executes service' do
+ expect_any_instance_of(Ci::ArchiveTraceService)
+ .to receive(:execute).with(build)
+
+ subject
+ end
+
context 'when a trace had already been archived' do
let!(:build) { create(:ci_build, :success, :trace_live, :trace_artifact) }
let!(:build2) { create(:ci_build, :success, :trace_live) }
@@ -46,11 +53,12 @@ describe Ci::ArchiveTracesCronWorker do
let!(:build) { create(:ci_build, :success, :trace_live) }
before do
+ allow(Gitlab::Sentry).to receive(:track_exception)
allow_any_instance_of(Gitlab::Ci::Trace).to receive(:archive!).and_raise('Unexpected error')
end
it 'puts a log' do
- expect(Rails.logger).to receive(:error).with("Failed to archive stale live trace. id: #{build.id} message: Unexpected error")
+ expect(Rails.logger).to receive(:error).with("Failed to archive trace. id: #{build.id} message: Unexpected error")
subject
end
diff --git a/spec/workers/ci/build_schedule_worker_spec.rb b/spec/workers/ci/build_schedule_worker_spec.rb
new file mode 100644
index 00000000000..4a3fe84d7f7
--- /dev/null
+++ b/spec/workers/ci/build_schedule_worker_spec.rb
@@ -0,0 +1,40 @@
+require 'spec_helper'
+
+describe Ci::BuildScheduleWorker do
+ subject { described_class.new.perform(build.id) }
+
+ context 'when build is found' do
+ context 'when build is scheduled' do
+ let(:build) { create(:ci_build, :scheduled) }
+
+ it 'executes RunScheduledBuildService' do
+ expect_any_instance_of(Ci::RunScheduledBuildService)
+ .to receive(:execute).once
+
+ subject
+ end
+ end
+
+ context 'when build is not scheduled' do
+ let(:build) { create(:ci_build, :created) }
+
+ it 'executes RunScheduledBuildService' do
+ expect_any_instance_of(Ci::RunScheduledBuildService)
+ .not_to receive(:execute)
+
+ subject
+ end
+ end
+ end
+
+ context 'when build is not found' do
+ let(:build) { build_stubbed(:ci_build, :scheduled) }
+
+ it 'does nothing' do
+ expect_any_instance_of(Ci::RunScheduledBuildService)
+ .not_to receive(:execute)
+
+ subject
+ end
+ end
+end
diff --git a/spec/workers/cluster_platform_configure_worker_spec.rb b/spec/workers/cluster_platform_configure_worker_spec.rb
new file mode 100644
index 00000000000..b51f6e07c6a
--- /dev/null
+++ b/spec/workers/cluster_platform_configure_worker_spec.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe ClusterPlatformConfigureWorker, '#execute' do
+ context 'when provider type is gcp' do
+ let(:cluster) { create(:cluster, :project, :provided_by_gcp) }
+
+ it 'configures kubernetes platform' do
+ expect_any_instance_of(Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService).to receive(:execute)
+
+ described_class.new.perform(cluster.id)
+ end
+ end
+
+ context 'when provider type is user' do
+ let(:cluster) { create(:cluster, :project, :provided_by_user) }
+
+ it 'configures kubernetes platform' do
+ expect_any_instance_of(Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService).to receive(:execute)
+
+ described_class.new.perform(cluster.id)
+ end
+ end
+
+ context 'when cluster does not exist' do
+ it 'does not provision a cluster' do
+ expect_any_instance_of(Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService).not_to receive(:execute)
+
+ described_class.new.perform(123)
+ end
+ end
+
+ context 'when kubeclient raises error' do
+ let(:cluster) { create(:cluster, :project) }
+
+ it 'rescues and logs the error' do
+ allow_any_instance_of(Clusters::Gcp::Kubernetes::CreateOrUpdateNamespaceService).to receive(:execute).and_raise(::Kubeclient::HttpError.new(500, 'something baaaad happened', ''))
+
+ expect(Rails.logger)
+ .to receive(:error)
+ .with("Failed to create/update Kubernetes namespace for cluster_id: #{cluster.id} with error: something baaaad happened")
+
+ described_class.new.perform(cluster.id)
+ end
+ end
+end
diff --git a/spec/workers/cluster_provision_worker_spec.rb b/spec/workers/cluster_provision_worker_spec.rb
index 8054ec11a48..0a2dfef36a4 100644
--- a/spec/workers/cluster_provision_worker_spec.rb
+++ b/spec/workers/cluster_provision_worker_spec.rb
@@ -14,18 +14,25 @@ describe ClusterProvisionWorker do
end
context 'when provider type is user' do
- let(:cluster) { create(:cluster, provider_type: :user) }
+ let(:cluster) { create(:cluster, :provided_by_user) }
it 'does not provision a cluster' do
expect_any_instance_of(Clusters::Gcp::ProvisionService).not_to receive(:execute)
described_class.new.perform(cluster.id)
end
+
+ it 'configures kubernetes platform' do
+ expect(ClusterPlatformConfigureWorker).to receive(:perform_async).with(cluster.id)
+
+ described_class.new.perform(cluster.id)
+ end
end
context 'when cluster does not exist' do
it 'does not provision a cluster' do
expect_any_instance_of(Clusters::Gcp::ProvisionService).not_to receive(:execute)
+ expect(ClusterPlatformConfigureWorker).not_to receive(:perform_async)
described_class.new.perform(123)
end
diff --git a/spec/workers/concerns/gitlab/github_import/stage_methods_spec.rb b/spec/workers/concerns/gitlab/github_import/stage_methods_spec.rb
index 241e8a2b6d3..d85a87f2cb0 100644
--- a/spec/workers/concerns/gitlab/github_import/stage_methods_spec.rb
+++ b/spec/workers/concerns/gitlab/github_import/stage_methods_spec.rb
@@ -58,14 +58,16 @@ describe Gitlab::GithubImport::StageMethods do
end
describe '#find_project' do
+ let(:import_state) { create(:import_state, project: project) }
+
it 'returns a Project for an existing ID' do
- project.update_column(:import_status, 'started')
+ import_state.update_column(:status, 'started')
expect(worker.find_project(project.id)).to eq(project)
end
it 'returns nil for a project that failed importing' do
- project.update_column(:import_status, 'failed')
+ import_state.update_column(:status, 'failed')
expect(worker.find_project(project.id)).to be_nil
end
diff --git a/spec/workers/concerns/project_import_options_spec.rb b/spec/workers/concerns/project_import_options_spec.rb
index b6c111df8b9..3699fd83a9a 100644
--- a/spec/workers/concerns/project_import_options_spec.rb
+++ b/spec/workers/concerns/project_import_options_spec.rb
@@ -28,13 +28,23 @@ describe ProjectImportOptions do
worker_class.sidekiq_retries_exhausted_block.call(job)
- expect(project.reload.import_error).to include("fork")
+ expect(project.import_state.reload.last_error).to include("fork")
end
it 'logs the appropriate error message for forked projects' do
worker_class.sidekiq_retries_exhausted_block.call(job)
- expect(project.reload.import_error).to include("import")
+ expect(project.import_state.reload.last_error).to include("import")
+ end
+
+ context 'when project does not have import_state' do
+ let(:project) { create(:project) }
+
+ it 'raises an error' do
+ expect do
+ worker_class.sidekiq_retries_exhausted_block.call(job)
+ end.to raise_error(NoMethodError)
+ end
end
end
end
diff --git a/spec/workers/deployments/success_worker_spec.rb b/spec/workers/deployments/success_worker_spec.rb
new file mode 100644
index 00000000000..ba7d45eca01
--- /dev/null
+++ b/spec/workers/deployments/success_worker_spec.rb
@@ -0,0 +1,36 @@
+require 'spec_helper'
+
+describe Deployments::SuccessWorker do
+ subject { described_class.new.perform(deployment&.id) }
+
+ context 'when successful deployment' do
+ let(:deployment) { create(:deployment, :success) }
+
+ it 'executes UpdateDeploymentService' do
+ expect(UpdateDeploymentService)
+ .to receive(:new).with(deployment).and_call_original
+
+ subject
+ end
+ end
+
+ context 'when canceled deployment' do
+ let(:deployment) { create(:deployment, :canceled) }
+
+ it 'does not execute UpdateDeploymentService' do
+ expect(UpdateDeploymentService).not_to receive(:new)
+
+ subject
+ end
+ end
+
+ context 'when deploy record does not exist' do
+ let(:deployment) { nil }
+
+ it 'does not execute UpdateDeploymentService' do
+ expect(UpdateDeploymentService).not_to receive(:new)
+
+ subject
+ end
+ end
+end
diff --git a/spec/workers/email_receiver_worker_spec.rb b/spec/workers/email_receiver_worker_spec.rb
index e4e77c667b3..045135255d6 100644
--- a/spec/workers/email_receiver_worker_spec.rb
+++ b/spec/workers/email_receiver_worker_spec.rb
@@ -46,6 +46,21 @@ describe EmailReceiverWorker, :mailer do
should_not_email_anyone
end
end
+
+ context 'when the error is Gitlab::Email::InvalidAttachment' do
+ let(:error) { Gitlab::Email::InvalidAttachment.new("Could not deal with that") }
+
+ it 'reports the error to the sender' do
+ perform_enqueued_jobs do
+ described_class.new.perform(raw_message)
+ end
+
+ email = ActionMailer::Base.deliveries.last
+ expect(email).not_to be_nil
+ expect(email.to).to eq(["jake@adventuretime.ooo"])
+ expect(email.body.parts.last.to_s).to include("Could not deal with that")
+ end
+ end
end
end
diff --git a/spec/workers/emails_on_push_worker_spec.rb b/spec/workers/emails_on_push_worker_spec.rb
index f17c5ac6aac..05b4fb49ea3 100644
--- a/spec/workers/emails_on_push_worker_spec.rb
+++ b/spec/workers/emails_on_push_worker_spec.rb
@@ -101,7 +101,7 @@ describe EmailsOnPushWorker, :mailer do
context "when there are multiple recipients" do
before do
- # This is a hack because we modify the mail object before sending, for efficency,
+ # This is a hack because we modify the mail object before sending, for efficiency,
# but the TestMailer adapter just appends the objects to an array. To clone a mail
# object, create a new one!
# https://github.com/mikel/mail/issues/314#issuecomment-12750108
diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb
index 2106959e23c..ebe02373275 100644
--- a/spec/workers/every_sidekiq_worker_spec.rb
+++ b/spec/workers/every_sidekiq_worker_spec.rb
@@ -9,7 +9,7 @@ describe 'Every Sidekiq worker' do
expect(Gitlab::SidekiqConfig.cron_workers.map(&:queue)).to all(start_with('cronjob:'))
end
- it 'has its queue in app/workers/all_queues.yml', :aggregate_failures do
+ it 'has its queue in Gitlab::SidekiqConfig::QUEUE_CONFIG_PATHS', :aggregate_failures do
file_worker_queues = Gitlab::SidekiqConfig.worker_queues.to_set
worker_queues = Gitlab::SidekiqConfig.workers.map(&:queue).to_set
@@ -17,10 +17,10 @@ describe 'Every Sidekiq worker' do
worker_queues << 'default'
missing_from_file = worker_queues - file_worker_queues
- expect(missing_from_file).to be_empty, "expected #{missing_from_file.to_a.inspect} to be in app/workers/all_queues.yml"
+ expect(missing_from_file).to be_empty, "expected #{missing_from_file.to_a.inspect} to be in Gitlab::SidekiqConfig::QUEUE_CONFIG_PATHS"
unncessarily_in_file = file_worker_queues - worker_queues
- expect(unncessarily_in_file).to be_empty, "expected #{unncessarily_in_file.to_a.inspect} not to be in app/workers/all_queues.yml"
+ expect(unncessarily_in_file).to be_empty, "expected #{unncessarily_in_file.to_a.inspect} not to be in Gitlab::SidekiqConfig::QUEUE_CONFIG_PATHS"
end
it 'has its queue or namespace in config/sidekiq_queues.yml', :aggregate_failures do
diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb
index 30e67e67e0e..a159f24f876 100644
--- a/spec/workers/git_garbage_collect_worker_spec.rb
+++ b/spec/workers/git_garbage_collect_worker_spec.rb
@@ -3,6 +3,8 @@ require 'fileutils'
require 'spec_helper'
describe GitGarbageCollectWorker do
+ include GitHelpers
+
let(:project) { create(:project, :repository) }
let(:shell) { Gitlab::Shell.new }
let!(:lease_uuid) { SecureRandom.uuid }
@@ -197,9 +199,7 @@ describe GitGarbageCollectWorker do
# Create a new commit on a random new branch
def create_objects(project)
- rugged = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.rugged
- end
+ rugged = rugged_repo(project.repository)
old_commit = rugged.branches.first.target
new_commit_sha = Rugged::Commit.create(
rugged,
diff --git a/spec/workers/gitlab/github_import/advance_stage_worker_spec.rb b/spec/workers/gitlab/github_import/advance_stage_worker_spec.rb
index 0f78c5cc644..fc7aafbc0c9 100644
--- a/spec/workers/gitlab/github_import/advance_stage_worker_spec.rb
+++ b/spec/workers/gitlab/github_import/advance_stage_worker_spec.rb
@@ -17,8 +17,8 @@ describe Gitlab::GithubImport::AdvanceStageWorker, :clean_gitlab_redis_shared_st
context 'when there are remaining jobs' do
before do
allow(worker)
- .to receive(:find_project)
- .and_return(project)
+ .to receive(:find_import_state)
+ .and_return(import_state)
end
it 'reschedules itself' do
@@ -38,8 +38,8 @@ describe Gitlab::GithubImport::AdvanceStageWorker, :clean_gitlab_redis_shared_st
context 'when there are no remaining jobs' do
before do
allow(worker)
- .to receive(:find_project)
- .and_return(project)
+ .to receive(:find_import_state)
+ .and_return(import_state)
allow(worker)
.to receive(:wait_for_jobs)
@@ -48,8 +48,8 @@ describe Gitlab::GithubImport::AdvanceStageWorker, :clean_gitlab_redis_shared_st
end
it 'schedules the next stage' do
- expect(project)
- .to receive(:refresh_import_jid_expiration)
+ expect(import_state)
+ .to receive(:refresh_jid_expiration)
expect(Gitlab::GithubImport::Stage::FinishImportWorker)
.to receive(:perform_async)
@@ -96,22 +96,18 @@ describe Gitlab::GithubImport::AdvanceStageWorker, :clean_gitlab_redis_shared_st
end
end
- describe '#find_project' do
- it 'returns a Project' do
- project.update_column(:import_status, 'started')
+ describe '#find_import_state' do
+ it 'returns a ProjectImportState' do
+ import_state.update_column(:status, 'started')
- found = worker.find_project(project.id)
+ found = worker.find_import_state(project.id)
- expect(found).to be_an_instance_of(Project)
-
- # This test is there to make sure we only select the columns we care
- # about.
- # TODO: enable this assertion back again
- # expect(found.attributes).to include({ 'id' => nil, 'import_jid' => '123' })
+ expect(found).to be_an_instance_of(ProjectImportState)
+ expect(found.attributes.keys).to match_array(%w(id jid))
end
it 'returns nil if the project import is not running' do
- expect(worker.find_project(project.id)).to be_nil
+ expect(worker.find_import_state(project.id)).to be_nil
end
end
end
diff --git a/spec/workers/gitlab/github_import/refresh_import_jid_worker_spec.rb b/spec/workers/gitlab/github_import/refresh_import_jid_worker_spec.rb
index 25ada575a44..7ff133f1049 100644
--- a/spec/workers/gitlab/github_import/refresh_import_jid_worker_spec.rb
+++ b/spec/workers/gitlab/github_import/refresh_import_jid_worker_spec.rb
@@ -29,7 +29,7 @@ describe Gitlab::GithubImport::RefreshImportJidWorker do
context 'when the job is running' do
it 'refreshes the import JID and reschedules itself' do
allow(worker)
- .to receive(:find_project)
+ .to receive(:find_import_state)
.with(project.id)
.and_return(project)
@@ -39,7 +39,7 @@ describe Gitlab::GithubImport::RefreshImportJidWorker do
.and_return(true)
expect(project)
- .to receive(:refresh_import_jid_expiration)
+ .to receive(:refresh_jid_expiration)
expect(worker.class)
.to receive(:perform_in_the_future)
@@ -52,7 +52,7 @@ describe Gitlab::GithubImport::RefreshImportJidWorker do
context 'when the job is no longer running' do
it 'returns' do
allow(worker)
- .to receive(:find_project)
+ .to receive(:find_import_state)
.with(project.id)
.and_return(project)
@@ -62,18 +62,18 @@ describe Gitlab::GithubImport::RefreshImportJidWorker do
.and_return(false)
expect(project)
- .not_to receive(:refresh_import_jid_expiration)
+ .not_to receive(:refresh_jid_expiration)
worker.perform(project.id, '123')
end
end
end
- describe '#find_project' do
- it 'returns a Project' do
+ describe '#find_import_state' do
+ it 'returns a ProjectImportState' do
project = create(:project, :import_started)
- expect(worker.find_project(project.id)).to be_an_instance_of(Project)
+ expect(worker.find_import_state(project.id)).to be_an_instance_of(ProjectImportState)
end
# it 'only selects the import JID field' do
@@ -84,14 +84,14 @@ describe Gitlab::GithubImport::RefreshImportJidWorker do
# .to eq({ 'id' => nil, 'import_jid' => '123abc' })
# end
- it 'returns nil for a project for which the import process failed' do
+ it 'returns nil for a import state for which the import process failed' do
project = create(:project, :import_failed)
- expect(worker.find_project(project.id)).to be_nil
+ expect(worker.find_import_state(project.id)).to be_nil
end
- it 'returns nil for a non-existing project' do
- expect(worker.find_project(-1)).to be_nil
+ it 'returns nil for a non-existing find_import_state' do
+ expect(worker.find_import_state(-1)).to be_nil
end
end
end
diff --git a/spec/workers/gitlab/github_import/stage/import_base_data_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_base_data_worker_spec.rb
index 8c80d660287..ad6154cc4a4 100644
--- a/spec/workers/gitlab/github_import/stage/import_base_data_worker_spec.rb
+++ b/spec/workers/gitlab/github_import/stage/import_base_data_worker_spec.rb
@@ -2,6 +2,7 @@ require 'spec_helper'
describe Gitlab::GithubImport::Stage::ImportBaseDataWorker do
let(:project) { create(:project) }
+ let(:import_state) { create(:import_state, project: project) }
let(:worker) { described_class.new }
describe '#import' do
@@ -18,7 +19,7 @@ describe Gitlab::GithubImport::Stage::ImportBaseDataWorker do
expect(importer).to receive(:execute)
end
- expect(project).to receive(:refresh_import_jid_expiration)
+ expect(import_state).to receive(:refresh_jid_expiration)
expect(Gitlab::GithubImport::Stage::ImportPullRequestsWorker)
.to receive(:perform_async)
diff --git a/spec/workers/gitlab/github_import/stage/import_pull_requests_worker_spec.rb b/spec/workers/gitlab/github_import/stage/import_pull_requests_worker_spec.rb
index 2fc91a3e80a..1fbb073a34a 100644
--- a/spec/workers/gitlab/github_import/stage/import_pull_requests_worker_spec.rb
+++ b/spec/workers/gitlab/github_import/stage/import_pull_requests_worker_spec.rb
@@ -2,6 +2,7 @@ require 'spec_helper'
describe Gitlab::GithubImport::Stage::ImportPullRequestsWorker do
let(:project) { create(:project) }
+ let(:import_state) { create(:import_state, project: project) }
let(:worker) { described_class.new }
describe '#import' do
@@ -19,8 +20,8 @@ describe Gitlab::GithubImport::Stage::ImportPullRequestsWorker do
.to receive(:execute)
.and_return(waiter)
- expect(project)
- .to receive(:refresh_import_jid_expiration)
+ expect(import_state)
+ .to receive(:refresh_jid_expiration)
expect(Gitlab::GithubImport::AdvanceStageWorker)
.to receive(:perform_async)
diff --git a/spec/workers/namespaceless_project_destroy_worker_spec.rb b/spec/workers/namespaceless_project_destroy_worker_spec.rb
index eec110dfbfb..2f21a1321e1 100644
--- a/spec/workers/namespaceless_project_destroy_worker_spec.rb
+++ b/spec/workers/namespaceless_project_destroy_worker_spec.rb
@@ -71,10 +71,10 @@ describe NamespacelessProjectDestroyWorker do
expect(merge_request.reload).to be_closed
end
- it 'destroys the link' do
+ it 'destroys fork network members' do
subject.perform(project.id)
- expect(parent_project.forked_project_links).to be_empty
+ expect(parent_project.forked_to_members).to be_empty
end
end
end
diff --git a/spec/workers/pipeline_schedule_worker_spec.rb b/spec/workers/pipeline_schedule_worker_spec.rb
index a2fe4734d47..c5a60e9855b 100644
--- a/spec/workers/pipeline_schedule_worker_spec.rb
+++ b/spec/workers/pipeline_schedule_worker_spec.rb
@@ -56,17 +56,89 @@ describe PipelineScheduleWorker do
expect { subject }.not_to change { project.pipelines.count }
end
end
+
+ context 'when gitlab-ci.yml is corrupted' do
+ before do
+ stub_ci_pipeline_yaml_file(YAML.dump(rspec: { variables: 'rspec' } ))
+ end
+
+ it 'creates a failed pipeline with the reason' do
+ expect { subject }.to change { project.pipelines.count }.by(1)
+ expect(Ci::Pipeline.last).to be_config_error
+ expect(Ci::Pipeline.last.yaml_errors).not_to be_nil
+ end
+ end
end
context 'when the schedule is not runnable by the user' do
- it 'deactivates the schedule' do
+ before do
+ expect(Gitlab::Sentry)
+ .to receive(:track_exception)
+ .with(Ci::CreatePipelineService::CreateError,
+ issue_url: 'https://gitlab.com/gitlab-org/gitlab-ce/issues/41231',
+ extra: { schedule_id: pipeline_schedule.id } ).once
+ end
+
+ it 'does not deactivate the schedule' do
+ subject
+
+ expect(pipeline_schedule.reload.active).to be_truthy
+ end
+
+ it 'increments Prometheus counter' do
+ expect(Gitlab::Metrics)
+ .to receive(:counter)
+ .with(:pipeline_schedule_creation_failed_total, "Counter of failed attempts of pipeline schedule creation")
+ .and_call_original
+
+ subject
+ end
+
+ it 'logging a pipeline error' do
+ expect(Rails.logger)
+ .to receive(:error)
+ .with(a_string_matching("Insufficient permissions to create a new pipeline"))
+ .and_call_original
+
subject
+ end
+
+ it 'does not create a pipeline' do
+ expect { subject }.not_to change { project.pipelines.count }
+ end
- expect(pipeline_schedule.reload.active).to be_falsy
+ it 'does not raise an exception' do
+ expect { subject }.not_to raise_error
end
+ end
+
+ context 'when .gitlab-ci.yml is missing in the project' do
+ before do
+ stub_ci_pipeline_yaml_file(nil)
+ project.add_maintainer(user)
- it 'does not schedule a pipeline' do
+ expect(Gitlab::Sentry)
+ .to receive(:track_exception)
+ .with(Ci::CreatePipelineService::CreateError,
+ issue_url: 'https://gitlab.com/gitlab-org/gitlab-ce/issues/41231',
+ extra: { schedule_id: pipeline_schedule.id } ).once
+ end
+
+ it 'logging a pipeline error' do
+ expect(Rails.logger)
+ .to receive(:error)
+ .with(a_string_matching("Missing .gitlab-ci.yml file"))
+ .and_call_original
+
+ subject
+ end
+
+ it 'does not create a pipeline' do
expect { subject }.not_to change { project.pipelines.count }
end
+
+ it 'does not raise an exception' do
+ expect { subject }.not_to raise_error
+ end
end
end
diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb
index cd6661f09a1..9176eb12b12 100644
--- a/spec/workers/post_receive_spec.rb
+++ b/spec/workers/post_receive_spec.rb
@@ -6,7 +6,7 @@ describe PostReceive do
let(:base64_changes) { Base64.encode64(wrongly_encoded_changes) }
let(:gl_repository) { "project-#{project.id}" }
let(:key) { create(:key, user: project.owner) }
- let(:key_id) { key.shell_id }
+ let!(:key_id) { key.shell_id }
let(:project) do
create(:project, :repository, auto_cancel_pending_pipelines: 'disabled')
@@ -31,85 +31,108 @@ describe PostReceive do
end
describe "#process_project_changes" do
- before do
- allow_any_instance_of(Gitlab::GitPostReceive).to receive(:identify).and_return(project.owner)
+ context 'empty changes' do
+ it "does not call any PushService but runs after project hooks" do
+ expect(GitPushService).not_to receive(:new)
+ expect(GitTagPushService).not_to receive(:new)
+ expect_next_instance_of(SystemHooksService) { |service| expect(service).to receive(:execute_hooks) }
+
+ described_class.new.perform(gl_repository, key_id, "")
+ end
end
- context "branches" do
- let(:changes) { "123456 789012 refs/heads/tést" }
+ context 'unidentified user' do
+ let!(:key_id) { "" }
- it "calls GitTagPushService" do
- expect_any_instance_of(GitPushService).to receive(:execute).and_return(true)
- expect_any_instance_of(GitTagPushService).not_to receive(:execute)
- described_class.new.perform(gl_repository, key_id, base64_changes)
+ it 'returns false' do
+ expect(GitPushService).not_to receive(:new)
+ expect(GitTagPushService).not_to receive(:new)
+
+ expect(described_class.new.perform(gl_repository, key_id, base64_changes)).to be false
end
end
- context "tags" do
- let(:changes) { "123456 789012 refs/tags/tag" }
+ context 'with changes' do
+ before do
+ allow_any_instance_of(Gitlab::GitPostReceive).to receive(:identify).and_return(project.owner)
+ end
+
+ context "branches" do
+ let(:changes) { "123456 789012 refs/heads/tést" }
- it "calls GitTagPushService" do
- expect_any_instance_of(GitPushService).not_to receive(:execute)
- expect_any_instance_of(GitTagPushService).to receive(:execute).and_return(true)
- described_class.new.perform(gl_repository, key_id, base64_changes)
+ it "calls GitPushService" do
+ expect_any_instance_of(GitPushService).to receive(:execute).and_return(true)
+ expect_any_instance_of(GitTagPushService).not_to receive(:execute)
+ described_class.new.perform(gl_repository, key_id, base64_changes)
+ end
end
- end
- context "merge-requests" do
- let(:changes) { "123456 789012 refs/merge-requests/123" }
+ context "tags" do
+ let(:changes) { "123456 789012 refs/tags/tag" }
- it "does not call any of the services" do
- expect_any_instance_of(GitPushService).not_to receive(:execute)
- expect_any_instance_of(GitTagPushService).not_to receive(:execute)
- described_class.new.perform(gl_repository, key_id, base64_changes)
+ it "calls GitTagPushService" do
+ expect_any_instance_of(GitPushService).not_to receive(:execute)
+ expect_any_instance_of(GitTagPushService).to receive(:execute).and_return(true)
+ described_class.new.perform(gl_repository, key_id, base64_changes)
+ end
end
- end
- context "gitlab-ci.yml" do
- let(:changes) { "123456 789012 refs/heads/feature\n654321 210987 refs/tags/tag" }
+ context "merge-requests" do
+ let(:changes) { "123456 789012 refs/merge-requests/123" }
- subject { described_class.new.perform(gl_repository, key_id, base64_changes) }
+ it "does not call any of the services" do
+ expect_any_instance_of(GitPushService).not_to receive(:execute)
+ expect_any_instance_of(GitTagPushService).not_to receive(:execute)
+ described_class.new.perform(gl_repository, key_id, base64_changes)
+ end
+ end
- context "creates a Ci::Pipeline for every change" do
- before do
- stub_ci_pipeline_to_return_yaml_file
+ context "gitlab-ci.yml" do
+ let(:changes) { "123456 789012 refs/heads/feature\n654321 210987 refs/tags/tag" }
- allow_any_instance_of(Project)
- .to receive(:commit)
- .and_return(project.commit)
+ subject { described_class.new.perform(gl_repository, key_id, base64_changes) }
- allow_any_instance_of(Repository)
- .to receive(:branch_exists?)
- .and_return(true)
- end
+ context "creates a Ci::Pipeline for every change" do
+ before do
+ stub_ci_pipeline_to_return_yaml_file
- it { expect { subject }.to change { Ci::Pipeline.count }.by(2) }
- end
+ allow_any_instance_of(Project)
+ .to receive(:commit)
+ .and_return(project.commit)
- context "does not create a Ci::Pipeline" do
- before do
- stub_ci_pipeline_yaml_file(nil)
+ allow_any_instance_of(Repository)
+ .to receive(:branch_exists?)
+ .and_return(true)
+ end
+
+ it { expect { subject }.to change { Ci::Pipeline.count }.by(2) }
end
- it { expect { subject }.not_to change { Ci::Pipeline.count } }
+ context "does not create a Ci::Pipeline" do
+ before do
+ stub_ci_pipeline_yaml_file(nil)
+ end
+
+ it { expect { subject }.not_to change { Ci::Pipeline.count } }
+ end
end
- end
- context 'after project changes hooks' do
- let(:changes) { '123456 789012 refs/heads/tést' }
- let(:fake_hook_data) { Hash.new(event_name: 'repository_update') }
+ context 'after project changes hooks' do
+ let(:changes) { '123456 789012 refs/heads/tést' }
+ let(:fake_hook_data) { Hash.new(event_name: 'repository_update') }
- before do
- allow_any_instance_of(Gitlab::DataBuilder::Repository).to receive(:update).and_return(fake_hook_data)
- # silence hooks so we can isolate
- allow_any_instance_of(Key).to receive(:post_create_hook).and_return(true)
- allow_any_instance_of(GitPushService).to receive(:execute).and_return(true)
- end
+ before do
+ allow_any_instance_of(Gitlab::DataBuilder::Repository).to receive(:update).and_return(fake_hook_data)
+ # silence hooks so we can isolate
+ allow_any_instance_of(Key).to receive(:post_create_hook).and_return(true)
+ allow_any_instance_of(GitPushService).to receive(:execute).and_return(true)
+ end
- it 'calls SystemHooksService' do
- expect_any_instance_of(SystemHooksService).to receive(:execute_hooks).with(fake_hook_data, :repository_update_hooks).and_return(true)
+ it 'calls SystemHooksService' do
+ expect_any_instance_of(SystemHooksService).to receive(:execute_hooks).with(fake_hook_data, :repository_update_hooks).and_return(true)
- described_class.new.perform(gl_repository, key_id, base64_changes)
+ described_class.new.perform(gl_repository, key_id, base64_changes)
+ end
end
end
end
diff --git a/spec/workers/prune_old_events_worker_spec.rb b/spec/workers/prune_old_events_worker_spec.rb
index ea974355050..b999a6fd5b6 100644
--- a/spec/workers/prune_old_events_worker_spec.rb
+++ b/spec/workers/prune_old_events_worker_spec.rb
@@ -4,23 +4,29 @@ describe PruneOldEventsWorker do
describe '#perform' do
let(:user) { create(:user) }
- let!(:expired_event) { create(:event, :closed, author: user, created_at: 13.months.ago) }
- let!(:not_expired_event) { create(:event, :closed, author: user, created_at: 1.day.ago) }
- let!(:exactly_12_months_event) { create(:event, :closed, author: user, created_at: 12.months.ago) }
+ let!(:expired_event) { create(:event, :closed, author: user, created_at: 25.months.ago) }
+ let!(:not_expired_1_day_event) { create(:event, :closed, author: user, created_at: 1.day.ago) }
+ let!(:not_expired_13_month_event) { create(:event, :closed, author: user, created_at: 13.months.ago) }
+ let!(:not_expired_2_years_event) { create(:event, :closed, author: user, created_at: 2.years.ago) }
- it 'prunes events older than 12 months' do
+ it 'prunes events older than 2 years' do
expect { subject.perform }.to change { Event.count }.by(-1)
expect(Event.find_by(id: expired_event.id)).to be_nil
end
it 'leaves fresh events' do
subject.perform
- expect(not_expired_event.reload).to be_present
+ expect(not_expired_1_day_event.reload).to be_present
end
- it 'leaves events from exactly 12 months ago' do
+ it 'leaves events from 13 months ago' do
subject.perform
- expect(exactly_12_months_event).to be_present
+ expect(not_expired_13_month_event.reload).to be_present
+ end
+
+ it 'leaves events from 2 years ago' do
+ subject.perform
+ expect(not_expired_2_years_event).to be_present
end
end
end
diff --git a/spec/workers/rebase_worker_spec.rb b/spec/workers/rebase_worker_spec.rb
index 20aff020dbb..936b9deaecc 100644
--- a/spec/workers/rebase_worker_spec.rb
+++ b/spec/workers/rebase_worker_spec.rb
@@ -1,25 +1,23 @@
require 'spec_helper'
describe RebaseWorker, '#perform' do
+ include ProjectForksHelper
+
context 'when rebasing an MR from a fork where upstream has protected branches' do
let(:upstream_project) { create(:project, :repository) }
- let(:fork_project) { create(:project, :repository) }
+ let(:forked_project) { fork_project(upstream_project, nil, repository: true) }
let(:merge_request) do
create(:merge_request,
- source_project: fork_project,
+ source_project: forked_project,
source_branch: 'feature_conflict',
target_project: upstream_project,
target_branch: 'master')
end
- before do
- create(:forked_project_link, forked_to_project: fork_project, forked_from_project: upstream_project)
- end
-
it 'sets the correct project for running hooks' do
expect(MergeRequests::RebaseService)
- .to receive(:new).with(fork_project, merge_request.author).and_call_original
+ .to receive(:new).with(forked_project, merge_request.author).and_call_original
subject.perform(merge_request, merge_request.author)
end
diff --git a/spec/workers/repository_check/batch_worker_spec.rb b/spec/workers/repository_check/batch_worker_spec.rb
index ede271b2cdd..50b93fce2dc 100644
--- a/spec/workers/repository_check/batch_worker_spec.rb
+++ b/spec/workers/repository_check/batch_worker_spec.rb
@@ -51,7 +51,7 @@ describe RepositoryCheck::BatchWorker do
it 'does nothing when shard is unhealthy' do
shard_name = 'broken'
- create(:project, created_at: 1.week.ago, repository_storage: shard_name)
+ create(:project, :broken_storage, created_at: 1.week.ago)
expect(subject.perform(shard_name)).to eq(nil)
end
diff --git a/spec/workers/repository_fork_worker_spec.rb b/spec/workers/repository_fork_worker_spec.rb
index ac8716ecfb1..781f91ac9ca 100644
--- a/spec/workers/repository_fork_worker_spec.rb
+++ b/spec/workers/repository_fork_worker_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
describe RepositoryForkWorker do
+ include ProjectForksHelper
+
describe 'modules' do
it 'includes ProjectImportOptions' do
expect(described_class).to include_module(ProjectImportOptions)
@@ -8,9 +10,13 @@ describe RepositoryForkWorker do
end
describe "#perform" do
- let(:project) { create(:project, :repository) }
+ let(:project) { create(:project, :public, :repository) }
let(:shell) { Gitlab::Shell.new }
- let(:fork_project) { create(:project, :repository, :import_scheduled, forked_from_project: project) }
+ let(:forked_project) { create(:project, :repository, :import_scheduled) }
+
+ before do
+ fork_project(project, forked_project.creator, target_project: forked_project, repository: true)
+ end
shared_examples 'RepositoryForkWorker performing' do
before do
@@ -21,8 +27,8 @@ describe RepositoryForkWorker do
expect(shell).to receive(:fork_repository).with(
'default',
project.disk_path,
- fork_project.repository_storage,
- fork_project.disk_path
+ forked_project.repository_storage,
+ forked_project.disk_path
)
end
@@ -49,28 +55,28 @@ describe RepositoryForkWorker do
perform!
- expect(fork_project.protected_branches.first.name).to eq(fork_project.default_branch)
+ expect(forked_project.protected_branches.first.name).to eq(forked_project.default_branch)
end
it 'flushes various caches' do
expect_fork_repository.and_return(true)
# Works around https://github.com/rspec/rspec-mocks/issues/910
- expect(Project).to receive(:find).with(fork_project.id).and_return(fork_project)
- expect(fork_project.repository).to receive(:expire_emptiness_caches)
+ expect(Project).to receive(:find).with(forked_project.id).and_return(forked_project)
+ expect(forked_project.repository).to receive(:expire_emptiness_caches)
.and_call_original
- expect(fork_project.repository).to receive(:expire_exists_cache)
+ expect(forked_project.repository).to receive(:expire_exists_cache)
.and_call_original
- expect(fork_project.wiki.repository).to receive(:expire_emptiness_caches)
+ expect(forked_project.wiki.repository).to receive(:expire_emptiness_caches)
.and_call_original
- expect(fork_project.wiki.repository).to receive(:expire_exists_cache)
+ expect(forked_project.wiki.repository).to receive(:expire_exists_cache)
.and_call_original
perform!
end
it "handles bad fork" do
- error_message = "Unable to fork project #{fork_project.id} for repository #{project.disk_path} -> #{fork_project.disk_path}"
+ error_message = "Unable to fork project #{forked_project.id} for repository #{project.disk_path} -> #{forked_project.disk_path}"
expect_fork_repository.and_return(false)
@@ -80,7 +86,7 @@ describe RepositoryForkWorker do
context 'only project ID passed' do
def perform!
- subject.perform(fork_project.id)
+ subject.perform(forked_project.id)
end
it_behaves_like 'RepositoryForkWorker performing'
@@ -88,7 +94,7 @@ describe RepositoryForkWorker do
context 'project ID, storage and repo paths passed' do
def perform!
- subject.perform(fork_project.id, TestEnv.repos_path, project.disk_path)
+ subject.perform(forked_project.id, TestEnv.repos_path, project.disk_path)
end
it_behaves_like 'RepositoryForkWorker performing'
diff --git a/spec/workers/repository_import_worker_spec.rb b/spec/workers/repository_import_worker_spec.rb
index d07e40377d4..87ac4bc05c1 100644
--- a/spec/workers/repository_import_worker_spec.rb
+++ b/spec/workers/repository_import_worker_spec.rb
@@ -9,13 +9,13 @@ describe RepositoryImportWorker do
describe '#perform' do
let(:project) { create(:project, :import_scheduled) }
+ let(:import_state) { project.import_state }
context 'when worker was reset without cleanup' do
it 'imports the project successfully' do
jid = '12345678'
started_project = create(:project)
-
- create(:import_state, :started, project: started_project, jid: jid)
+ started_import_state = create(:import_state, :started, project: started_project, jid: jid)
allow(subject).to receive(:jid).and_return(jid)
@@ -23,12 +23,12 @@ describe RepositoryImportWorker do
.and_return({ status: :ok })
# Works around https://github.com/rspec/rspec-mocks/issues/910
- expect(Project).to receive(:find).with(project.id).and_return(project)
- expect(project.repository).to receive(:expire_emptiness_caches)
- expect(project.wiki.repository).to receive(:expire_emptiness_caches)
- expect(project).to receive(:import_finish)
+ expect(Project).to receive(:find).with(started_project.id).and_return(started_project)
+ expect(started_project.repository).to receive(:expire_emptiness_caches)
+ expect(started_project.wiki.repository).to receive(:expire_emptiness_caches)
+ expect(started_import_state).to receive(:finish)
- subject.perform(project.id)
+ subject.perform(started_project.id)
end
end
@@ -41,7 +41,7 @@ describe RepositoryImportWorker do
expect(Project).to receive(:find).with(project.id).and_return(project)
expect(project.repository).to receive(:expire_emptiness_caches)
expect(project.wiki.repository).to receive(:expire_emptiness_caches)
- expect(project).to receive(:import_finish)
+ expect(import_state).to receive(:finish)
subject.perform(project.id)
end
@@ -51,26 +51,27 @@ describe RepositoryImportWorker do
it 'hide the credentials that were used in the import URL' do
error = %q{remote: Not Found fatal: repository 'https://user:pass@test.com/root/repoC.git/' not found }
- project.update(import_jid: '123')
+ import_state.update(jid: '123')
expect_any_instance_of(Projects::ImportService).to receive(:execute).and_return({ status: :error, message: error })
expect do
subject.perform(project.id)
end.to raise_error(RuntimeError, error)
- expect(project.reload.import_jid).not_to be_nil
+ expect(import_state.reload.jid).not_to be_nil
end
it 'updates the error on Import/Export' do
error = %q{remote: Not Found fatal: repository 'https://user:pass@test.com/root/repoC.git/' not found }
- project.update(import_jid: '123', import_type: 'gitlab_project')
+ project.update(import_type: 'gitlab_project')
+ import_state.update(jid: '123')
expect_any_instance_of(Projects::ImportService).to receive(:execute).and_return({ status: :error, message: error })
expect do
subject.perform(project.id)
end.to raise_error(RuntimeError, error)
- expect(project.reload.import_error).not_to be_nil
+ expect(import_state.reload.last_error).not_to be_nil
end
end
@@ -90,8 +91,8 @@ describe RepositoryImportWorker do
.to receive(:async?)
.and_return(true)
- expect_any_instance_of(Project)
- .not_to receive(:import_finish)
+ expect_any_instance_of(ProjectImportState)
+ .not_to receive(:finish)
subject.perform(project.id)
end
diff --git a/spec/workers/repository_remove_remote_worker_spec.rb b/spec/workers/repository_remove_remote_worker_spec.rb
index a653f6f926c..6ddb653d142 100644
--- a/spec/workers/repository_remove_remote_worker_spec.rb
+++ b/spec/workers/repository_remove_remote_worker_spec.rb
@@ -2,6 +2,7 @@ require 'rails_helper'
describe RepositoryRemoveRemoteWorker do
include ExclusiveLeaseHelpers
+ include GitHelpers
describe '#perform' do
let!(:project) { create(:project, :repository) }
@@ -50,9 +51,7 @@ describe RepositoryRemoveRemoteWorker do
end
def create_remote_branch(remote_name, branch_name, target)
- rugged = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
- project.repository.rugged
- end
+ rugged = rugged_repo(project.repository)
rugged.references.create("refs/remotes/#{remote_name}/#{branch_name}", target.id)
end
diff --git a/spec/workers/stuck_ci_jobs_worker_spec.rb b/spec/workers/stuck_ci_jobs_worker_spec.rb
index 856886e3df5..e09b8e5b964 100644
--- a/spec/workers/stuck_ci_jobs_worker_spec.rb
+++ b/spec/workers/stuck_ci_jobs_worker_spec.rb
@@ -5,7 +5,7 @@ describe StuckCiJobsWorker do
let!(:runner) { create :ci_runner }
let!(:job) { create :ci_build, runner: runner }
- let(:trace_lease_key) { "trace:archive:#{job.id}" }
+ let(:trace_lease_key) { "trace:write:lock:#{job.id}" }
let(:trace_lease_uuid) { SecureRandom.uuid }
let(:worker_lease_key) { StuckCiJobsWorker::EXCLUSIVE_LEASE_KEY }
let(:worker_lease_uuid) { SecureRandom.uuid }
@@ -127,6 +127,47 @@ describe StuckCiJobsWorker do
end
end
+ describe 'drop stale scheduled builds' do
+ let(:status) { 'scheduled' }
+ let(:updated_at) { }
+
+ context 'when scheduled at 2 hours ago but it is not executed yet' do
+ let!(:job) { create(:ci_build, :scheduled, scheduled_at: 2.hours.ago) }
+
+ it 'drops the stale scheduled build' do
+ expect(Ci::Build.scheduled.count).to eq(1)
+ expect(job).to be_scheduled
+
+ worker.perform
+ job.reload
+
+ expect(Ci::Build.scheduled.count).to eq(0)
+ expect(job).to be_failed
+ expect(job).to be_stale_schedule
+ end
+ end
+
+ context 'when scheduled at 30 minutes ago but it is not executed yet' do
+ let!(:job) { create(:ci_build, :scheduled, scheduled_at: 30.minutes.ago) }
+
+ it 'does not drop the stale scheduled build yet' do
+ expect(Ci::Build.scheduled.count).to eq(1)
+ expect(job).to be_scheduled
+
+ worker.perform
+
+ expect(Ci::Build.scheduled.count).to eq(1)
+ expect(job).to be_scheduled
+ end
+ end
+
+ context 'when there are no stale scheduled builds' do
+ it 'does not drop the stale scheduled build yet' do
+ expect { worker.perform }.not_to raise_error
+ end
+ end
+ end
+
describe 'exclusive lease' do
let(:status) { 'running' }
let(:updated_at) { 2.days.ago }
diff --git a/spec/workers/stuck_import_jobs_worker_spec.rb b/spec/workers/stuck_import_jobs_worker_spec.rb
index 2169c14218b..e94d2be9850 100644
--- a/spec/workers/stuck_import_jobs_worker_spec.rb
+++ b/spec/workers/stuck_import_jobs_worker_spec.rb
@@ -8,29 +8,29 @@ describe StuckImportJobsWorker do
context 'when the import status was already updated' do
before do
allow(Gitlab::SidekiqStatus).to receive(:completed_jids) do
- project.import_start
- project.import_finish
+ import_state.start
+ import_state.finish
- [project.import_jid]
+ [import_state.jid]
end
end
it 'does not mark the project as failed' do
worker.perform
- expect(project.reload.import_status).to eq('finished')
+ expect(import_state.reload.status).to eq('finished')
end
end
context 'when the import status was not updated' do
before do
- allow(Gitlab::SidekiqStatus).to receive(:completed_jids).and_return([project.import_jid])
+ allow(Gitlab::SidekiqStatus).to receive(:completed_jids).and_return([import_state.jid])
end
it 'marks the project as failed' do
worker.perform
- expect(project.reload.import_status).to eq('failed')
+ expect(import_state.reload.status).to eq('failed')
end
end
end
@@ -41,27 +41,27 @@ describe StuckImportJobsWorker do
end
it 'does not mark the project as failed' do
- expect { worker.perform }.not_to change { project.reload.import_status }
+ expect { worker.perform }.not_to change { import_state.reload.status }
end
end
end
describe 'with scheduled import_status' do
it_behaves_like 'project import job detection' do
- let(:project) { create(:project, :import_scheduled) }
+ let(:import_state) { create(:project, :import_scheduled).import_state }
before do
- project.import_state.update(jid: '123')
+ import_state.update(jid: '123')
end
end
end
describe 'with started import_status' do
it_behaves_like 'project import job detection' do
- let(:project) { create(:project, :import_started) }
+ let(:import_state) { create(:project, :import_started).import_state }
before do
- project.import_state.update(jid: '123')
+ import_state.update(jid: '123')
end
end
end
diff --git a/vendor/cert_manager/cluster_issuer.yaml b/vendor/cert_manager/cluster_issuer.yaml
new file mode 100644
index 00000000000..23fa6eff4b2
--- /dev/null
+++ b/vendor/cert_manager/cluster_issuer.yaml
@@ -0,0 +1,11 @@
+apiVersion: certmanager.k8s.io/v1alpha1
+kind: ClusterIssuer
+metadata:
+ name: letsencrypt-prod
+spec:
+ acme:
+ server: https://acme-v02.api.letsencrypt.org/directory
+ email: my-email@example.com
+ privateKeySecretRef:
+ name: letsencrypt-prod
+ http01: {}
diff --git a/vendor/cert_manager/values.yaml b/vendor/cert_manager/values.yaml
new file mode 100644
index 00000000000..4515e3e39c7
--- /dev/null
+++ b/vendor/cert_manager/values.yaml
@@ -0,0 +1,5 @@
+# These options provide fully automated TLS.
+# See https://github.com/jetstack/cert-manager/blob/master/docs/reference/ingress-shim.rst#configuration
+ingressShim:
+ defaultIssuerKind: "ClusterIssuer"
+ defaultIssuerName: "letsencrypt-prod"
diff --git a/vendor/gitignore/Android.gitignore b/vendor/gitignore/Android.gitignore
index 39b6783cef8..69eda01429a 100644
--- a/vendor/gitignore/Android.gitignore
+++ b/vendor/gitignore/Android.gitignore
@@ -1,6 +1,7 @@
# Built application files
*.apk
*.ap_
+*.aab
# Files for the ART/Dalvik VM
*.dex
@@ -43,8 +44,9 @@ captures/
.idea/caches
# Keystore files
-# Uncomment the following line if you do not want to check your keystore files in.
+# Uncomment the following lines if you do not want to check your keystore files in.
#*.jks
+#*.keystore
# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
diff --git a/vendor/gitignore/Delphi.gitignore b/vendor/gitignore/Delphi.gitignore
index 000ee5f104b..9532800ba22 100644
--- a/vendor/gitignore/Delphi.gitignore
+++ b/vendor/gitignore/Delphi.gitignore
@@ -64,3 +64,6 @@ __recovery/
# Castalia statistics file (since XE7 Castalia is distributed with Delphi)
*.stat
+
+# Boss dependency manager vendor folder https://github.com/HashLoad/boss
+modules/
diff --git a/vendor/gitignore/Elixir.gitignore b/vendor/gitignore/Elixir.gitignore
index 86e4c3f3905..b263cd10f37 100644
--- a/vendor/gitignore/Elixir.gitignore
+++ b/vendor/gitignore/Elixir.gitignore
@@ -7,3 +7,4 @@ erl_crash.dump
*.ez
*.beam
/config/*.secret.exs
+.elixir_ls/
diff --git a/vendor/gitignore/Global/Images.gitignore b/vendor/gitignore/Global/Images.gitignore
new file mode 100644
index 00000000000..97dcdbe6a95
--- /dev/null
+++ b/vendor/gitignore/Global/Images.gitignore
@@ -0,0 +1,63 @@
+# JPEG
+*.jpg
+*.jpeg
+*.jpe
+*.jif
+*.jfif
+*.jfi
+
+# JPEG 2000
+*.jp2
+*.j2k
+*.jpf
+*.jpx
+*.jpm
+*.mj2
+
+# JPEG XR
+*.jxr
+*.hdp
+*.wdp
+
+# Graphics Interchange Format
+*.gif
+
+# RAW
+*.raw
+
+# Web P
+*.webp
+
+# Portable Network Graphics
+*.png
+
+# Animated Portable Network Graphics
+*.apng
+
+# Multiple-image Network Graphics
+*.mng
+
+# Tagged Image File Format
+*.tiff
+*.tif
+
+# Scalable Vector Graphics
+*.svg
+*.svgz
+
+# Portable Document Format
+*.pdf
+
+# X BitMap
+*.xbm
+
+# BMP
+*.bmp
+*.dib
+
+# ICO
+*.ico
+
+# 3D Images
+*.3dm
+*.max
diff --git a/vendor/gitignore/Global/JetBrains.gitignore b/vendor/gitignore/Global/JetBrains.gitignore
index 343be1a3b8e..72f4d988a19 100644
--- a/vendor/gitignore/Global/JetBrains.gitignore
+++ b/vendor/gitignore/Global/JetBrains.gitignore
@@ -61,3 +61,6 @@ fabric.properties
# Editor-based Rest Client
.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
diff --git a/vendor/gitignore/Global/NetBeans.gitignore b/vendor/gitignore/Global/NetBeans.gitignore
index 254108cd23b..863bc7fa66e 100644
--- a/vendor/gitignore/Global/NetBeans.gitignore
+++ b/vendor/gitignore/Global/NetBeans.gitignore
@@ -1,4 +1,4 @@
-nbproject/private/
+**/nbproject/private/
build/
nbbuild/
dist/
diff --git a/vendor/gitignore/Global/PSoCCreator.gitignore b/vendor/gitignore/Global/PSoCCreator.gitignore
new file mode 100644
index 00000000000..15ae040bcda
--- /dev/null
+++ b/vendor/gitignore/Global/PSoCCreator.gitignore
@@ -0,0 +1,18 @@
+# Project Settings
+*.cywrk.*
+*.cyprj.*
+
+# Generated Assets and Resources
+Debug/
+Release/
+Export/
+*/codegentemp
+*/Generated_Source
+*_datasheet.pdf
+*_timing.html
+*.cycdx
+*.cyfit
+*.rpt
+*.svd
+*.log
+*.zip
diff --git a/vendor/gitignore/Global/Xcode.gitignore b/vendor/gitignore/Global/Xcode.gitignore
index cd0c7d3e45a..b01314d3a64 100644
--- a/vendor/gitignore/Global/Xcode.gitignore
+++ b/vendor/gitignore/Global/Xcode.gitignore
@@ -2,17 +2,11 @@
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
-## User settings
-xcuserdata/
-
-## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
-*.xcscmblueprint
-*.xccheckout
-
-## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
+## Build generated
build/
DerivedData/
-*.moved-aside
+
+## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
@@ -21,3 +15,65 @@ DerivedData/
!default.mode2v3
*.perspectivev3
!default.perspectivev3
+xcuserdata/
+
+## Other
+*.moved-aside
+*.xccheckout
+*.xcscmblueprint
+
+## Obj-C/Swift specific
+*.hmap
+*.ipa
+*.dSYM.zip
+*.dSYM
+
+## Playgrounds
+timeline.xctimeline
+playground.xcworkspace
+
+# Swift Package Manager
+#
+# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
+# Packages/
+# Package.pins
+# Package.resolved
+.build/
+
+# CocoaPods
+#
+# We recommend against adding the Pods directory to your .gitignore. However
+# you should judge for yourself, the pros and cons are mentioned at:
+# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
+#
+# Pods/
+#
+# Add this line if you want to avoid checking in source code from the Xcode workspace
+# *.xcworkspace
+
+# Carthage
+#
+# Add this line if you want to avoid checking in source code from Carthage dependencies.
+# Carthage/Checkouts
+
+Carthage/Build
+
+# fastlane
+#
+# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
+# screenshots whenever they are needed.
+# For more information about the recommended setup visit:
+# https://docs.fastlane.tools/best-practices/source-control/#source-control
+
+fastlane/report.xml
+fastlane/Preview.html
+fastlane/screenshots/**/*.png
+fastlane/test_output
+
+# Code Injection
+#
+# After new code Injection tools there's a generated folder /iOSInjectionProject
+# https://github.com/johnno1962/injectionforxcode
+
+iOSInjectionProject/
+
diff --git a/vendor/gitignore/Laravel.gitignore b/vendor/gitignore/Laravel.gitignore
index 67e2146f2bc..6552ddf8a06 100644
--- a/vendor/gitignore/Laravel.gitignore
+++ b/vendor/gitignore/Laravel.gitignore
@@ -1,4 +1,4 @@
-vendor/
+/vendor/
node_modules/
npm-debug.log
yarn-error.log
diff --git a/vendor/gitignore/Magento.gitignore b/vendor/gitignore/Magento.gitignore
index 6f1fa223992..abe6d79fedb 100644
--- a/vendor/gitignore/Magento.gitignore
+++ b/vendor/gitignore/Magento.gitignore
@@ -2,6 +2,8 @@
# Magento Default Files #
#--------------------------#
+/PATCH_*.sh
+
/app/etc/local.xml
/media/*
diff --git a/vendor/gitignore/Node.gitignore b/vendor/gitignore/Node.gitignore
index 3a4c8581b3a..e1da6ae8ea5 100644
--- a/vendor/gitignore/Node.gitignore
+++ b/vendor/gitignore/Node.gitignore
@@ -20,7 +20,7 @@ coverage
# nyc test coverage
.nyc_output
-# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
@@ -71,3 +71,6 @@ typings/
# Serverless directories
.serverless
+
+# FuseBox cache
+.fusebox/
diff --git a/vendor/gitignore/Python.gitignore b/vendor/gitignore/Python.gitignore
index 6f7a6d9c3d7..510c73d0fdb 100644
--- a/vendor/gitignore/Python.gitignore
+++ b/vendor/gitignore/Python.gitignore
@@ -109,3 +109,6 @@ venv.bak/
.mypy_cache/
.dmypy.json
dmypy.json
+
+# Pyre type checker
+.pyre/
diff --git a/vendor/gitignore/Rails.gitignore b/vendor/gitignore/Rails.gitignore
index 78eb74fdc26..38ba1b5b38c 100644
--- a/vendor/gitignore/Rails.gitignore
+++ b/vendor/gitignore/Rails.gitignore
@@ -50,6 +50,7 @@ node_modules/
# Ignore precompiled javascript packs
/public/packs
/public/packs-test
+/public/assets
# Ignore yarn files
/yarn-error.log
diff --git a/vendor/gitignore/TeX.gitignore b/vendor/gitignore/TeX.gitignore
index ff87d483645..753f2b954ff 100644
--- a/vendor/gitignore/TeX.gitignore
+++ b/vendor/gitignore/TeX.gitignore
@@ -64,6 +64,9 @@ acs-*.bib
# changes
*.soc
+# comment
+*.cut
+
# cprotect
*.cpt
@@ -205,6 +208,9 @@ pythontex-files-*/
# easy-todo
*.lod
+# xcolor
+*.xcp
+
# xmpincl
*.xmpi
diff --git a/vendor/gitignore/Unity.gitignore b/vendor/gitignore/Unity.gitignore
index 0210746b1a5..833e6d4291c 100644
--- a/vendor/gitignore/Unity.gitignore
+++ b/vendor/gitignore/Unity.gitignore
@@ -23,6 +23,7 @@ ExportedObj/
*.svd
*.pdb
*.opendb
+*.VC.db
# Unity3D generated meta files
*.pidb.meta
diff --git a/vendor/gitignore/VisualStudio.gitignore b/vendor/gitignore/VisualStudio.gitignore
index 94b41b913fb..4d13c54854e 100644
--- a/vendor/gitignore/VisualStudio.gitignore
+++ b/vendor/gitignore/VisualStudio.gitignore
@@ -4,6 +4,7 @@
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
+*.rsuser
*.suo
*.user
*.userosscache
@@ -76,6 +77,7 @@ StyleCopReport.xml
*.tlh
*.tmp
*.tmp_proj
+*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
@@ -290,8 +292,8 @@ paket-files/
.idea/
*.sln.iml
-# CodeRush
-.cr/
+# CodeRush personal settings
+.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
diff --git a/vendor/gitlab-ci-yml/.gitlab-ci.yml b/vendor/gitlab-ci-yml/.gitlab-ci.yml
deleted file mode 100644
index e2a55163682..00000000000
--- a/vendor/gitlab-ci-yml/.gitlab-ci.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-image: ruby:2.4-alpine
-
-test:
- script: ./verify_templates.rb
diff --git a/vendor/gitlab-ci-yml/Android.gitlab-ci.yml b/vendor/gitlab-ci-yml/Android.gitlab-ci.yml
deleted file mode 100644
index 5f9d54ff574..00000000000
--- a/vendor/gitlab-ci-yml/Android.gitlab-ci.yml
+++ /dev/null
@@ -1,51 +0,0 @@
-# Read more about this script on this blog post https://about.gitlab.com/2016/11/30/setting-up-gitlab-ci-for-android-projects/, by Greyson Parrelli
-image: openjdk:8-jdk
-
-variables:
- ANDROID_COMPILE_SDK: "25"
- ANDROID_BUILD_TOOLS: "24.0.0"
- ANDROID_SDK_TOOLS: "24.4.1"
-
-before_script:
- - apt-get --quiet update --yes
- - apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1
- - wget --quiet --output-document=android-sdk.tgz https://dl.google.com/android/android-sdk_r${ANDROID_SDK_TOOLS}-linux.tgz
- - tar --extract --gzip --file=android-sdk.tgz
- - echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter android-${ANDROID_COMPILE_SDK}
- - echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter platform-tools
- - echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter build-tools-${ANDROID_BUILD_TOOLS}
- - echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter extra-android-m2repository
- - echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter extra-google-google_play_services
- - echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter extra-google-m2repository
- - export ANDROID_HOME=$PWD/android-sdk-linux
- - export PATH=$PATH:$PWD/android-sdk-linux/platform-tools/
- - chmod +x ./gradlew
-
-stages:
- - build
- - test
-
-build:
- stage: build
- script:
- - ./gradlew assembleDebug
- artifacts:
- paths:
- - app/build/outputs/
-
-unitTests:
- stage: test
- script:
- - ./gradlew test
-
-functionalTests:
- stage: test
- script:
- - wget --quiet --output-document=android-wait-for-emulator https://raw.githubusercontent.com/travis-ci/travis-cookbooks/0f497eb71291b52a703143c5cd63a217c8766dc9/community-cookbooks/android-sdk/files/default/android-wait-for-emulator
- - chmod +x android-wait-for-emulator
- - echo y | android-sdk-linux/tools/android --silent update sdk --no-ui --all --filter sys-img-x86-google_apis-${ANDROID_COMPILE_SDK}
- - echo no | android-sdk-linux/tools/android create avd -n test -t android-${ANDROID_COMPILE_SDK} --abi google_apis/x86
- - android-sdk-linux/tools/emulator64-x86 -avd test -no-window -no-audio &
- - ./android-wait-for-emulator
- - adb shell input keyevent 82
- - ./gradlew cAT
diff --git a/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml b/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml
deleted file mode 100644
index 33ae9c6ad7e..00000000000
--- a/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml
+++ /dev/null
@@ -1,823 +0,0 @@
-# Auto DevOps
-# This CI/CD configuration provides a standard pipeline for
-# * building a Docker image (using a buildpack if necessary),
-# * storing the image in the container registry,
-# * running tests from a buildpack,
-# * running code quality analysis,
-# * creating a review app for each topic branch,
-# * and continuous deployment to production
-#
-# Test jobs may be disabled by setting environment variables:
-# * test: TEST_DISABLED
-# * code_quality: CODE_QUALITY_DISABLED
-# * license_management: LICENSE_MANAGEMENT_DISABLED
-# * performance: PERFORMANCE_DISABLED
-# * sast: SAST_DISABLED
-# * dependency_scanning: DEPENDENCY_SCANNING_DISABLED
-# * container_scanning: CONTAINER_SCANNING_DISABLED
-# * dast: DAST_DISABLED
-# * review: REVIEW_DISABLED
-# * stop_review: REVIEW_DISABLED
-#
-# In order to deploy, you must have a Kubernetes cluster configured either
-# via a project integration, or via group/project variables.
-# AUTO_DEVOPS_DOMAIN must also be set as a variable at the group or project
-# level, or manually added below.
-#
-# Continuous deployment to production is enabled by default.
-# If you want to deploy to staging first, or enable incremental rollouts,
-# set STAGING_ENABLED or INCREMENTAL_ROLLOUT_ENABLED environment variables.
-# If you want to use canary deployments, set CANARY_ENABLED environment variable.
-#
-# If Auto DevOps fails to detect the proper buildpack, or if you want to
-# specify a custom buildpack, set a project variable `BUILDPACK_URL` to the
-# repository URL of the buildpack.
-# e.g. BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-ruby.git#v142
-# If you need multiple buildpacks, add a file to your project called
-# `.buildpacks` that contains the URLs, one on each line, in order.
-# Note: Auto CI does not work with multiple buildpacks yet
-
-image: alpine:latest
-
-variables:
- # AUTO_DEVOPS_DOMAIN is the application deployment domain and should be set as a variable at the group or project level.
- # AUTO_DEVOPS_DOMAIN: domain.example.com
-
- POSTGRES_USER: user
- POSTGRES_PASSWORD: testing-password
- POSTGRES_ENABLED: "true"
- POSTGRES_DB: $CI_ENVIRONMENT_SLUG
-
- KUBERNETES_VERSION: 1.8.6
- HELM_VERSION: 2.6.1
-
- DOCKER_DRIVER: overlay2
-
-stages:
- - build
- - test
- - review
- - dast
- - staging
- - canary
- - production
- - performance
- - cleanup
-
-build:
- stage: build
- image: docker:stable-git
- services:
- - docker:stable-dind
- script:
- - setup_docker
- - build
- only:
- - branches
-
-test:
- services:
- - postgres:latest
- variables:
- POSTGRES_DB: test
- stage: test
- image: gliderlabs/herokuish:latest
- script:
- - setup_test_db
- - cp -R . /tmp/app
- - /bin/herokuish buildpack test
- only:
- - branches
- except:
- variables:
- - $TEST_DISABLED
-
-code_quality:
- stage: test
- image: docker:stable
- allow_failure: true
- services:
- - docker:stable-dind
- script:
- - setup_docker
- - code_quality
- artifacts:
- paths: [gl-code-quality-report.json]
- only:
- - branches
- except:
- variables:
- - $CODE_QUALITY_DISABLED
-
-license_management:
- stage: test
- image: docker:stable
- allow_failure: true
- services:
- - docker:stable-dind
- script:
- - setup_docker
- - license_management
- artifacts:
- paths: [gl-license-management-report.json]
- only:
- - branches
- except:
- variables:
- - $LICENSE_MANAGEMENT_DISABLED
-
-performance:
- stage: performance
- image: docker:stable
- allow_failure: true
- services:
- - docker:stable-dind
- script:
- - setup_docker
- - performance
- artifacts:
- paths:
- - performance.json
- - sitespeed-results/
- only:
- refs:
- - branches
- kubernetes: active
- except:
- variables:
- - $PERFORMANCE_DISABLED
-
-sast:
- stage: test
- image: docker:stable
- allow_failure: true
- services:
- - docker:stable-dind
- script:
- - setup_docker
- - sast
- artifacts:
- paths: [gl-sast-report.json]
- only:
- - branches
- except:
- variables:
- - $SAST_DISABLED
-
-dependency_scanning:
- stage: test
- image: docker:stable
- allow_failure: true
- services:
- - docker:stable-dind
- script:
- - setup_docker
- - dependency_scanning
- artifacts:
- paths: [gl-dependency-scanning-report.json]
- only:
- - branches
- except:
- variables:
- - $DEPENDENCY_SCANNING_DISABLED
-
-container_scanning:
- stage: test
- image: docker:stable
- allow_failure: true
- services:
- - docker:stable-dind
- script:
- - setup_docker
- - container_scanning
- artifacts:
- paths: [gl-container-scanning-report.json]
- only:
- - branches
- except:
- variables:
- - $CONTAINER_SCANNING_DISABLED
-
-dast:
- stage: dast
- allow_failure: true
- image: registry.gitlab.com/gitlab-org/security-products/zaproxy
- variables:
- POSTGRES_DB: "false"
- script:
- - dast
- artifacts:
- paths: [gl-dast-report.json]
- only:
- refs:
- - branches
- kubernetes: active
- except:
- refs:
- - master
- variables:
- - $DAST_DISABLED
-
-review:
- stage: review
- script:
- - check_kube_domain
- - install_dependencies
- - download_chart
- - ensure_namespace
- - install_tiller
- - create_secret
- - deploy
- - persist_environment_url
- environment:
- name: review/$CI_COMMIT_REF_NAME
- url: http://$CI_PROJECT_PATH_SLUG-$CI_ENVIRONMENT_SLUG.$AUTO_DEVOPS_DOMAIN
- on_stop: stop_review
- artifacts:
- paths: [environment_url.txt]
- only:
- refs:
- - branches
- kubernetes: active
- except:
- refs:
- - master
- variables:
- - $REVIEW_DISABLED
-
-stop_review:
- stage: cleanup
- variables:
- GIT_STRATEGY: none
- script:
- - install_dependencies
- - delete
- environment:
- name: review/$CI_COMMIT_REF_NAME
- action: stop
- when: manual
- allow_failure: true
- only:
- refs:
- - branches
- kubernetes: active
- except:
- refs:
- - master
- variables:
- - $REVIEW_DISABLED
-
-# Keys that start with a dot (.) will not be processed by GitLab CI.
-# Staging and canary jobs are disabled by default, to enable them
-# remove the dot (.) before the job name.
-# https://docs.gitlab.com/ee/ci/yaml/README.html#hidden-keys
-
-# Staging deploys are disabled by default since
-# continuous deployment to production is enabled by default
-# If you prefer to automatically deploy to staging and
-# only manually promote to production, enable this job by setting
-# STAGING_ENABLED.
-
-staging:
- stage: staging
- script:
- - check_kube_domain
- - install_dependencies
- - download_chart
- - ensure_namespace
- - install_tiller
- - create_secret
- - deploy
- environment:
- name: staging
- url: http://$CI_PROJECT_PATH_SLUG-staging.$AUTO_DEVOPS_DOMAIN
- only:
- refs:
- - master
- kubernetes: active
- variables:
- - $STAGING_ENABLED
-
-# Canaries are also disabled by default, but if you want them,
-# and know what the downsides are, you can enable this by setting
-# CANARY_ENABLED.
-
-canary:
- stage: canary
- script:
- - check_kube_domain
- - install_dependencies
- - download_chart
- - ensure_namespace
- - install_tiller
- - create_secret
- - deploy canary
- environment:
- name: production
- url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN
- when: manual
- only:
- refs:
- - master
- kubernetes: active
- variables:
- - $CANARY_ENABLED
-
-.production: &production_template
- stage: production
- script:
- - check_kube_domain
- - install_dependencies
- - download_chart
- - ensure_namespace
- - install_tiller
- - create_secret
- - deploy
- - delete canary
- - delete rollout
- - persist_environment_url
- environment:
- name: production
- url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN
- artifacts:
- paths: [environment_url.txt]
-
-production:
- <<: *production_template
- only:
- refs:
- - master
- kubernetes: active
- except:
- variables:
- - $STAGING_ENABLED
- - $CANARY_ENABLED
- - $INCREMENTAL_ROLLOUT_ENABLED
-
-production_manual:
- <<: *production_template
- when: manual
- allow_failure: false
- only:
- refs:
- - master
- kubernetes: active
- variables:
- - $STAGING_ENABLED
- - $CANARY_ENABLED
- except:
- variables:
- - $INCREMENTAL_ROLLOUT_ENABLED
-
-# This job implements incremental rollout on for every push to `master`.
-
-.rollout: &rollout_template
- stage: production
- script:
- - check_kube_domain
- - install_dependencies
- - download_chart
- - ensure_namespace
- - install_tiller
- - create_secret
- - deploy rollout $ROLLOUT_PERCENTAGE
- - scale stable $((100-ROLLOUT_PERCENTAGE))
- - delete canary
- - persist_environment_url
- environment:
- name: production
- url: http://$CI_PROJECT_PATH_SLUG.$AUTO_DEVOPS_DOMAIN
- artifacts:
- paths: [environment_url.txt]
-
-rollout 10%:
- <<: *rollout_template
- variables:
- ROLLOUT_PERCENTAGE: 10
- when: manual
- only:
- refs:
- - master
- kubernetes: active
- variables:
- - $INCREMENTAL_ROLLOUT_ENABLED
-
-rollout 25%:
- <<: *rollout_template
- variables:
- ROLLOUT_PERCENTAGE: 25
- when: manual
- only:
- refs:
- - master
- kubernetes: active
- variables:
- - $INCREMENTAL_ROLLOUT_ENABLED
-
-rollout 50%:
- <<: *rollout_template
- variables:
- ROLLOUT_PERCENTAGE: 50
- when: manual
- only:
- refs:
- - master
- kubernetes: active
- variables:
- - $INCREMENTAL_ROLLOUT_ENABLED
-
-rollout 100%:
- <<: *production_template
- when: manual
- allow_failure: false
- only:
- refs:
- - master
- kubernetes: active
- variables:
- - $INCREMENTAL_ROLLOUT_ENABLED
-
-# ---------------------------------------------------------------------------
-
-.auto_devops: &auto_devops |
- # Auto DevOps variables and functions
- [[ "$TRACE" ]] && set -x
- auto_database_url=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${CI_ENVIRONMENT_SLUG}-postgres:5432/${POSTGRES_DB}
- export DATABASE_URL=${DATABASE_URL-$auto_database_url}
- export CI_APPLICATION_REPOSITORY=$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG
- export CI_APPLICATION_TAG=$CI_COMMIT_SHA
- export CI_CONTAINER_NAME=ci_job_build_${CI_JOB_ID}
- export TILLER_NAMESPACE=$KUBE_NAMESPACE
- # Extract "MAJOR.MINOR" from CI_SERVER_VERSION and generate "MAJOR-MINOR-stable" for Security Products
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
-
- function registry_login() {
- if [[ -n "$CI_REGISTRY_USER" ]]; then
- echo "Logging to GitLab Container Registry with CI credentials..."
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
- echo ""
- fi
- }
-
- function container_scanning() {
- registry_login
-
- docker run -d --name db arminc/clair-db:latest
- docker run -p 6060:6060 --link db:postgres -d --name clair --restart on-failure arminc/clair-local-scan:v2.0.1
- apk add -U wget ca-certificates
- docker pull ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG}
- wget https://github.com/arminc/clair-scanner/releases/download/v8/clair-scanner_linux_amd64
- mv clair-scanner_linux_amd64 clair-scanner
- chmod +x clair-scanner
- touch clair-whitelist.yml
- retries=0
- echo "Waiting for clair daemon to start"
- while( ! wget -T 10 -q -O /dev/null http://docker:6060/v1/namespaces ) ; do sleep 1 ; echo -n "." ; if [ $retries -eq 10 ] ; then echo " Timeout, aborting." ; exit 1 ; fi ; retries=$(($retries+1)) ; done
- ./clair-scanner -c http://docker:6060 --ip $(hostname -i) -r gl-container-scanning-report.json -l clair.log -w clair-whitelist.yml ${CI_APPLICATION_REPOSITORY}:${CI_APPLICATION_TAG} || true
- }
-
- function code_quality() {
- docker run --env SOURCE_CODE="$PWD" \
- --volume "$PWD":/code \
- --volume /var/run/docker.sock:/var/run/docker.sock \
- "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
- }
-
- function license_management() {
- if echo $GITLAB_FEATURES |grep license_management > /dev/null ; then
- # Extract "MAJOR.MINOR" from CI_SERVER_VERSION and generate "MAJOR-MINOR-stable"
- LICENSE_MANAGEMENT_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
-
- docker run --volume "$PWD:/code" \
- "registry.gitlab.com/gitlab-org/security-products/license-management:$LICENSE_MANAGEMENT_VERSION" analyze /code
- else
- echo "License management is not available in your subscription"
- fi
- }
-
- function sast() {
- case "$CI_SERVER_VERSION" in
- *-ee)
-
- # Deprecation notice for CONFIDENCE_LEVEL variable
- if [ -z "$SAST_CONFIDENCE_LEVEL" -a "$CONFIDENCE_LEVEL" ]; then
- SAST_CONFIDENCE_LEVEL="$CONFIDENCE_LEVEL"
- echo "WARNING: CONFIDENCE_LEVEL is deprecated and MUST be replaced with SAST_CONFIDENCE_LEVEL"
- fi
-
- docker run --env SAST_CONFIDENCE_LEVEL="${SAST_CONFIDENCE_LEVEL:-3}" \
- --volume "$PWD:/code" \
- --volume /var/run/docker.sock:/var/run/docker.sock \
- "registry.gitlab.com/gitlab-org/security-products/sast:$SP_VERSION" /app/bin/run /code
- ;;
- *)
- echo "GitLab EE is required"
- ;;
- esac
- }
-
- function dependency_scanning() {
- case "$CI_SERVER_VERSION" in
- *-ee)
- docker run --env DEP_SCAN_DISABLE_REMOTE_CHECKS="${DEP_SCAN_DISABLE_REMOTE_CHECKS:-false}" \
- --volume "$PWD:/code" \
- --volume /var/run/docker.sock:/var/run/docker.sock \
- "registry.gitlab.com/gitlab-org/security-products/dependency-scanning:$SP_VERSION" /code
- ;;
- *)
- echo "GitLab EE is required"
- ;;
- esac
- }
-
- function get_replicas() {
- track="${1:-stable}"
- percentage="${2:-100}"
-
- env_track=$( echo $track | tr -s '[:lower:]' '[:upper:]' )
- env_slug=$( echo ${CI_ENVIRONMENT_SLUG//-/_} | tr -s '[:lower:]' '[:upper:]' )
-
- if [[ "$track" == "stable" ]] || [[ "$track" == "rollout" ]]; then
- # for stable track get number of replicas from `PRODUCTION_REPLICAS`
- eval new_replicas=\$${env_slug}_REPLICAS
- if [[ -z "$new_replicas" ]]; then
- new_replicas=$REPLICAS
- fi
- else
- # for all tracks get number of replicas from `CANARY_PRODUCTION_REPLICAS`
- eval new_replicas=\$${env_track}_${env_slug}_REPLICAS
- if [[ -z "$new_replicas" ]]; then
- eval new_replicas=\${env_track}_REPLICAS
- fi
- fi
-
- replicas="${new_replicas:-1}"
- replicas="$(($replicas * $percentage / 100))"
-
- # always return at least one replicas
- if [[ $replicas -gt 0 ]]; then
- echo "$replicas"
- else
- echo 1
- fi
- }
-
- function deploy() {
- track="${1-stable}"
- percentage="${2:-100}"
- name="$CI_ENVIRONMENT_SLUG"
-
- replicas="1"
- service_enabled="true"
- postgres_enabled="$POSTGRES_ENABLED"
-
- # if track is different than stable,
- # re-use all attached resources
- if [[ "$track" != "stable" ]]; then
- name="$name-$track"
- service_enabled="false"
- postgres_enabled="false"
- fi
-
- replicas=$(get_replicas "$track" "$percentage")
-
- if [[ "$CI_PROJECT_VISIBILITY" != "public" ]]; then
- secret_name='gitlab-registry'
- else
- secret_name=''
- fi
-
- helm upgrade --install \
- --wait \
- --set service.enabled="$service_enabled" \
- --set releaseOverride="$CI_ENVIRONMENT_SLUG" \
- --set image.repository="$CI_APPLICATION_REPOSITORY" \
- --set image.tag="$CI_APPLICATION_TAG" \
- --set image.pullPolicy=IfNotPresent \
- --set image.secrets[0].name="$secret_name" \
- --set application.track="$track" \
- --set application.database_url="$DATABASE_URL" \
- --set service.url="$CI_ENVIRONMENT_URL" \
- --set replicaCount="$replicas" \
- --set postgresql.enabled="$postgres_enabled" \
- --set postgresql.nameOverride="postgres" \
- --set postgresql.postgresUser="$POSTGRES_USER" \
- --set postgresql.postgresPassword="$POSTGRES_PASSWORD" \
- --set postgresql.postgresDatabase="$POSTGRES_DB" \
- --namespace="$KUBE_NAMESPACE" \
- --version="$CI_PIPELINE_ID-$CI_JOB_ID" \
- "$name" \
- chart/
-
- kubectl rollout status -n "$KUBE_NAMESPACE" -w "deployment/$name"
- }
-
- function scale() {
- track="${1-stable}"
- percentage="${2-100}"
- name="$CI_ENVIRONMENT_SLUG"
-
- if [[ "$track" != "stable" ]]; then
- name="$name-$track"
- fi
-
- replicas=$(get_replicas "$track" "$percentage")
-
- if [[ -n "$(helm ls -q "^$name$")" ]]; then
- helm upgrade --reuse-values \
- --wait \
- --set replicaCount="$replicas" \
- --namespace="$KUBE_NAMESPACE" \
- "$name" \
- chart/
- fi
- }
-
- function install_dependencies() {
- apk add -U openssl curl tar gzip bash ca-certificates git
- curl -L -o /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub
- curl -L -O https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.28-r0/glibc-2.28-r0.apk
- apk add glibc-2.28-r0.apk
- rm glibc-2.28-r0.apk
-
- curl "https://kubernetes-helm.storage.googleapis.com/helm-v${HELM_VERSION}-linux-amd64.tar.gz" | tar zx
- mv linux-amd64/helm /usr/bin/
- helm version --client
-
- curl -L -o /usr/bin/kubectl "https://storage.googleapis.com/kubernetes-release/release/v${KUBERNETES_VERSION}/bin/linux/amd64/kubectl"
- chmod +x /usr/bin/kubectl
- kubectl version --client
- }
-
- function setup_docker() {
- if ! docker info &>/dev/null; then
- if [ -z "$DOCKER_HOST" -a "$KUBERNETES_PORT" ]; then
- export DOCKER_HOST='tcp://localhost:2375'
- fi
- fi
- }
-
- function setup_test_db() {
- if [ -z ${KUBERNETES_PORT+x} ]; then
- DB_HOST=postgres
- else
- DB_HOST=localhost
- fi
- export DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${DB_HOST}:5432/${POSTGRES_DB}"
- }
-
- function download_chart() {
- if [[ ! -d chart ]]; then
- auto_chart=${AUTO_DEVOPS_CHART:-gitlab/auto-deploy-app}
- auto_chart_name=$(basename $auto_chart)
- auto_chart_name=${auto_chart_name%.tgz}
- auto_chart_name=${auto_chart_name%.tar.gz}
- else
- auto_chart="chart"
- auto_chart_name="chart"
- fi
-
- helm init --client-only
- helm repo add gitlab https://charts.gitlab.io
- if [[ ! -d "$auto_chart" ]]; then
- helm fetch ${auto_chart} --untar
- fi
- if [ "$auto_chart_name" != "chart" ]; then
- mv ${auto_chart_name} chart
- fi
-
- helm dependency update chart/
- helm dependency build chart/
- }
-
- function ensure_namespace() {
- kubectl describe namespace "$KUBE_NAMESPACE" || kubectl create namespace "$KUBE_NAMESPACE"
- }
-
- function check_kube_domain() {
- if [ -z ${AUTO_DEVOPS_DOMAIN+x} ]; then
- echo "In order to deploy or use Review Apps, AUTO_DEVOPS_DOMAIN variable must be set"
- echo "You can do it in Auto DevOps project settings or defining a variable at group or project level"
- echo "You can also manually add it in .gitlab-ci.yml"
- false
- else
- true
- fi
- }
-
- function build() {
- registry_login
-
- if [[ -f Dockerfile ]]; then
- echo "Building Dockerfile-based application..."
- docker build \
- --build-arg HTTP_PROXY="$HTTP_PROXY" \
- --build-arg http_proxy="$http_proxy" \
- --build-arg HTTPS_PROXY="$HTTPS_PROXY" \
- --build-arg https_proxy="$https_proxy" \
- --build-arg FTP_PROXY="$FTP_PROXY" \
- --build-arg ftp_proxy="$ftp_proxy" \
- --build-arg NO_PROXY="$NO_PROXY" \
- --build-arg no_proxy="$no_proxy" \
- -t "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" .
- else
- echo "Building Heroku-based application using gliderlabs/herokuish docker image..."
- docker run -i \
- -e BUILDPACK_URL \
- -e HTTP_PROXY \
- -e http_proxy \
- -e HTTPS_PROXY \
- -e https_proxy \
- -e FTP_PROXY \
- -e ftp_proxy \
- -e NO_PROXY \
- -e no_proxy \
- --name="$CI_CONTAINER_NAME" -v "$(pwd):/tmp/app:ro" gliderlabs/herokuish /bin/herokuish buildpack build
- docker commit "$CI_CONTAINER_NAME" "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG"
- docker rm "$CI_CONTAINER_NAME" >/dev/null
- echo ""
-
- echo "Configuring $CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG docker image..."
- docker create --expose 5000 --env PORT=5000 --name="$CI_CONTAINER_NAME" "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG" /bin/herokuish procfile start web
- docker commit "$CI_CONTAINER_NAME" "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG"
- docker rm "$CI_CONTAINER_NAME" >/dev/null
- echo ""
- fi
-
- echo "Pushing to GitLab Container Registry..."
- docker push "$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG"
- echo ""
- }
-
- function install_tiller() {
- echo "Checking Tiller..."
- helm init --upgrade
- kubectl rollout status -n "$TILLER_NAMESPACE" -w "deployment/tiller-deploy"
- if ! helm version --debug; then
- echo "Failed to init Tiller."
- return 1
- fi
- echo ""
- }
-
- function create_secret() {
- echo "Create secret..."
- if [[ "$CI_PROJECT_VISIBILITY" == "public" ]]; then
- return
- fi
-
- kubectl create secret -n "$KUBE_NAMESPACE" \
- docker-registry gitlab-registry \
- --docker-server="$CI_REGISTRY" \
- --docker-username="${CI_DEPLOY_USER:-$CI_REGISTRY_USER}" \
- --docker-password="${CI_DEPLOY_PASSWORD:-$CI_REGISTRY_PASSWORD}" \
- --docker-email="$GITLAB_USER_EMAIL" \
- -o yaml --dry-run | kubectl replace -n "$KUBE_NAMESPACE" --force -f -
- }
-
- function dast() {
- export CI_ENVIRONMENT_URL=$(cat environment_url.txt)
-
- mkdir /zap/wrk/
- /zap/zap-baseline.py -J gl-dast-report.json -t "$CI_ENVIRONMENT_URL" || true
- cp /zap/wrk/gl-dast-report.json .
- }
-
- function performance() {
- export CI_ENVIRONMENT_URL=$(cat environment_url.txt)
-
- mkdir gitlab-exporter
- wget -O gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/10-5/index.js
-
- mkdir sitespeed-results
-
- if [ -f .gitlab-urls.txt ]
- then
- sed -i -e 's@^@'"$CI_ENVIRONMENT_URL"'@' .gitlab-urls.txt
- docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:6.3.1 --plugins.add ./gitlab-exporter --outputFolder sitespeed-results .gitlab-urls.txt
- else
- docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:6.3.1 --plugins.add ./gitlab-exporter --outputFolder sitespeed-results "$CI_ENVIRONMENT_URL"
- fi
-
- mv sitespeed-results/data/performance.json performance.json
- }
-
- function persist_environment_url() {
- echo $CI_ENVIRONMENT_URL > environment_url.txt
- }
-
- function delete() {
- track="${1-stable}"
- name="$CI_ENVIRONMENT_SLUG"
-
- if [[ "$track" != "stable" ]]; then
- name="$name-$track"
- fi
-
- if [[ -n "$(helm ls -q "^$name$")" ]]; then
- helm delete --purge "$name"
- fi
- }
-
-before_script:
- - *auto_devops
diff --git a/vendor/gitlab-ci-yml/CONTRIBUTING.md b/vendor/gitlab-ci-yml/CONTRIBUTING.md
deleted file mode 100644
index d33a1f06f26..00000000000
--- a/vendor/gitlab-ci-yml/CONTRIBUTING.md
+++ /dev/null
@@ -1,46 +0,0 @@
-## Developer Certificate of Origin + License
-
-By contributing to GitLab B.V., You accept and agree to the following terms and
-conditions for Your present and future Contributions submitted to GitLab B.V.
-Except for the license granted herein to GitLab B.V. and recipients of software
-distributed by GitLab B.V., You reserve all right, title, and interest in and to
-Your Contributions. All Contributions are subject to the following DCO + License
-terms.
-
-[DCO + License](https://gitlab.com/gitlab-org/dco/blob/master/README.md)
-
-_This notice should stay as the first item in the CONTRIBUTING.md file._
-
-## Code of conduct
-
-As contributors and maintainers of this project, we pledge to respect all people
-who contribute through reporting issues, posting feature requests, updating
-documentation, submitting pull requests or patches, and other activities.
-
-We are committed to making participation in this project a harassment-free
-experience for everyone, regardless of level of experience, gender, gender
-identity and expression, sexual orientation, disability, personal appearance,
-body size, race, ethnicity, age, or religion.
-
-Examples of unacceptable behavior by participants include the use of sexual
-language or imagery, derogatory comments or personal attacks, trolling, public
-or private harassment, insults, or other unprofessional conduct.
-
-Project maintainers have the right and responsibility to remove, edit, or reject
-comments, commits, code, wiki edits, issues, and other contributions that are
-not aligned to this Code of Conduct. Project maintainers who do not follow the
-Code of Conduct may be removed from the project team.
-
-This code of conduct applies both within project spaces and in public spaces
-when an individual is representing the project or its community.
-
-Instances of abusive, harassing, or otherwise unacceptable behavior can be
-reported by emailing contact@gitlab.com.
-
-This Code of Conduct is adapted from the [Contributor Covenant][contributor-covenant], version 1.1.0,
-available at [http://contributor-covenant.org/version/1/1/0/](http://contributor-covenant.org/version/1/1/0/).
-
-[contributor-covenant]: http://contributor-covenant.org
-[individual-agreement]: https://docs.gitlab.com/ee/legal/individual_contributor_license_agreement.html
-[corporate-agreement]: https://docs.gitlab.com/ee/legal/corporate_contributor_license_agreement.html
-
diff --git a/vendor/gitlab-ci-yml/Julia.gitlab-ci.yml b/vendor/gitlab-ci-yml/Julia.gitlab-ci.yml
deleted file mode 100644
index 140cb4635f3..00000000000
--- a/vendor/gitlab-ci-yml/Julia.gitlab-ci.yml
+++ /dev/null
@@ -1,54 +0,0 @@
-# An example .gitlab-ci.yml file to test (and optionally report the coverage
-# results of) your [Julia][1] packages. Please refer to the [documentation][2]
-# for more information about package development in Julia.
-#
-# Here, it is assumed that your Julia package is named `MyPackage`. Change it to
-# whatever name you have given to your package.
-#
-# [1]: http://julialang.org/
-# [2]: http://julia.readthedocs.org/
-
-# Below is the template to run your tests in Julia
-.test_template: &test_definition
- # Uncomment below if you would like to run the tests on specific references
- # only, such as the branches `master`, `development`, etc.
- # only:
- # - master
- # - development
- script:
- # Let's run the tests. Substitute `coverage = false` below, if you do not
- # want coverage results.
- - /opt/julia/bin/julia -e 'Pkg.clone(pwd()); Pkg.test("MyPackage",
- coverage = true)'
- # Comment out below if you do not want coverage results.
- - /opt/julia/bin/julia -e 'Pkg.add("Coverage"); cd(Pkg.dir("MyPackage"));
- using Coverage; cl, tl = get_summary(process_folder());
- println("(", cl/tl*100, "%) covered")'
-
-# Name a test and select an appropriate image.
-test:0.4.6:
- image: julialang/julia:v0.4.6
- <<: *test_definition
-
-# Maybe you would like to test your package against the development branch:
-test:0.5.0-dev:
- image: julialang/julia:v0.5.0-dev
- # ... allowing for failures, since we are testing against the development
- # branch:
- allow_failure: true
- <<: *test_definition
-
-# REMARK: Do not forget to enable the coverage feature for your project, if you
-# are using code coverage reporting above. This can be done by
-#
-# - Navigating to the `CI/CD Pipelines` settings of your project,
-# - Copying and pasting the default `Simplecov` regex example provided, i.e.,
-# `\(\d+.\d+\%\) covered` in the `test coverage parsing` textfield.
-#
-# WARNING: This template is using the `julialang/julia` images from [Docker
-# Hub][3]. One can use custom Julia images and/or the official ones found
-# in the same place. However, care must be taken to correctly locate the binary
-# file (`/opt/julia/bin/julia` above), which is usually given on the image's
-# description page.
-#
-# [3]: http://hub.docker.com/
diff --git a/vendor/gitlab-ci-yml/LICENSE b/vendor/gitlab-ci-yml/LICENSE
deleted file mode 100644
index 27a215686e7..00000000000
--- a/vendor/gitlab-ci-yml/LICENSE
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2011-2017 GitLab B.V.
-
-With regard to the GitLab Software:
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-For all third party components incorporated into the GitLab Software, those
-components are licensed under the original license provided by the owner of the
-applicable component.
diff --git a/vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml b/vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml
deleted file mode 100644
index 0688f77a1d2..00000000000
--- a/vendor/gitlab-ci-yml/Laravel.gitlab-ci.yml
+++ /dev/null
@@ -1,82 +0,0 @@
-# Official framework image. Look for the different tagged releases at:
-# https://hub.docker.com/r/library/php
-image: php:latest
-
-# Pick zero or more services to be used on all builds.
-# Only needed when using a docker container to run your tests in.
-# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service
-services:
- - mysql:latest
-
-variables:
- MYSQL_DATABASE: project_name
- MYSQL_ROOT_PASSWORD: secret
-
-# This folder is cached between builds
-# http://docs.gitlab.com/ce/ci/yaml/README.html#cache
-cache:
- paths:
- - vendor/
- - node_modules/
-
-# This is a basic example for a gem or script which doesn't use
-# services such as redis or postgres
-before_script:
- # Update packages
- - apt-get update -yqq
-
- # Upgrade to Node 7
- - curl -sL https://deb.nodesource.com/setup_7.x | bash -
-
- # Install dependencies
- - apt-get install git nodejs libcurl4-gnutls-dev libicu-dev libmcrypt-dev libvpx-dev libjpeg-dev libpng-dev libxpm-dev zlib1g-dev libfreetype6-dev libxml2-dev libexpat1-dev libbz2-dev libgmp3-dev libldap2-dev unixodbc-dev libpq-dev libsqlite3-dev libaspell-dev libsnmp-dev libpcre3-dev libtidy-dev -yqq
-
- # Install php extensions
- - docker-php-ext-install mbstring pdo_mysql curl json intl gd xml zip bz2 opcache
-
- # Install & enable Xdebug for code coverage reports
- - pecl install xdebug
- - docker-php-ext-enable xdebug
-
- # Install Composer and project dependencies.
- - curl -sS https://getcomposer.org/installer | php
- - php composer.phar install
-
- # Install Node dependencies.
- # comment this out if you don't have a node dependency
- - npm install
-
- # Copy over testing configuration.
- # Don't forget to set the database config in .env.testing correctly
- # DB_HOST=mysql
- # DB_DATABASE=project_name
- # DB_USERNAME=root
- # DB_PASSWORD=secret
- - cp .env.testing .env
-
- # Run npm build
- # comment this out if you don't have a frontend build
- # you can change this to to your frontend building script like
- # npm run build
- - npm run dev
-
- # Generate an application key. Re-cache.
- - php artisan key:generate
- - php artisan config:cache
-
- # Run database migrations.
- - php artisan migrate
-
- # Run database seed
- - php artisan db:seed
-
-test:
- script:
- # run laravel tests
- - php vendor/bin/phpunit --coverage-text --colors=never
-
- # run frontend tests
- # if you have any task for testing frontend
- # set it in your package.json script
- # comment this out if you don't have a frontend test
- - npm test
diff --git a/vendor/gitlab-ci-yml/Maven.gitlab-ci.yml b/vendor/gitlab-ci-yml/Maven.gitlab-ci.yml
deleted file mode 100644
index d61ff239e13..00000000000
--- a/vendor/gitlab-ci-yml/Maven.gitlab-ci.yml
+++ /dev/null
@@ -1,102 +0,0 @@
----
-# Build JAVA applications using Apache Maven (http://maven.apache.org)
-# For docker image tags see https://hub.docker.com/_/maven/
-#
-# For general lifecycle information see https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
-#
-# This template will build and test your projects as well as create the documentation.
-#
-# * Caches downloaded dependencies and plugins between invocation.
-# * Verify but don't deploy merge requests.
-# * Deploy built artifacts from master branch only.
-# * Shows how to use multiple jobs in test stage for verifying functionality
-# with multiple JDKs.
-# * Uses site:stage to collect the documentation for multi-module projects.
-# * Publishes the documentation for `master` branch.
-
-variables:
- # This will supress any download for dependencies and plugins or upload messages which would clutter the console log.
- # `showDateTime` will show the passed time in milliseconds. You need to specify `--batch-mode` to make this work.
- MAVEN_OPTS: "-Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true"
- # As of Maven 3.3.0 instead of this you may define these options in `.mvn/maven.config` so the same config is used
- # when running from the command line.
- # `installAtEnd` and `deployAtEnd` are only effective with recent version of the corresponding plugins.
- MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true"
-
-# Cache downloaded dependencies and plugins between builds.
-# To keep cache across branches add 'key: "$CI_JOB_NAME"'
-cache:
- paths:
- - .m2/repository
-
-# This will only validate and compile stuff and run e.g. maven-enforcer-plugin.
-# Because some enforcer rules might check dependency convergence and class duplications
-# we use `test-compile` here instead of `validate`, so the correct classpath is picked up.
-.validate: &validate
- stage: build
- script:
- - 'mvn $MAVEN_CLI_OPTS test-compile'
-
-# For merge requests do not `deploy` but only run `verify`.
-# See https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
-.verify: &verify
- stage: test
- script:
- - 'mvn $MAVEN_CLI_OPTS verify site site:stage'
- except:
- - master
-
-# Validate merge requests using JDK7
-validate:jdk7:
- <<: *validate
- image: maven:3.3.9-jdk-7
-
-# Validate merge requests using JDK8
-validate:jdk8:
- <<: *validate
- image: maven:3.3.9-jdk-8
-
-# Verify merge requests using JDK7
-verify:jdk7:
- <<: *verify
- image: maven:3.3.9-jdk-7
-
-# Verify merge requests using JDK8
-verify:jdk8:
- <<: *verify
- image: maven:3.3.9-jdk-8
-
-
-# For `master` branch run `mvn deploy` automatically.
-# Here you need to decide whether you want to use JDK7 or 8.
-# To get this working you need to define a volume while configuring your gitlab-ci-multi-runner.
-# Mount your `settings.xml` as `/root/.m2/settings.xml` which holds your secrets.
-# See https://maven.apache.org/settings.html
-deploy:jdk8:
- # Use stage test here, so the pages job may later pickup the created site.
- stage: test
- script:
- - 'mvn $MAVEN_CLI_OPTS deploy site site:stage'
- only:
- - master
- # Archive up the built documentation site.
- artifacts:
- paths:
- - target/staging
- image: maven:3.3.9-jdk-8
-
-
-pages:
- image: busybox:latest
- stage: deploy
- script:
- # Because Maven appends the artifactId automatically to the staging path if you did define a parent pom,
- # you might need to use `mv target/staging/YOUR_ARTIFACT_ID public` instead.
- - mv target/staging public
- dependencies:
- - deploy:jdk8
- artifacts:
- paths:
- - public
- only:
- - master
diff --git a/vendor/gitlab-ci-yml/Python.gitlab-ci.yml b/vendor/gitlab-ci-yml/Python.gitlab-ci.yml
deleted file mode 100644
index 2e0589de652..00000000000
--- a/vendor/gitlab-ci-yml/Python.gitlab-ci.yml
+++ /dev/null
@@ -1,51 +0,0 @@
-# Official language image. Look for the different tagged releases at:
-# https://hub.docker.com/r/library/python/tags/
-image: python:latest
-
-# Change pip's cache directory to be inside the project directory since we can
-# only cache local items.
-variables:
- PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache"
-
-# Pip's cache doesn't store the python packages
-# https://pip.pypa.io/en/stable/reference/pip_install/#caching
-#
-# If you want to also cache the installed packages, you have to install
-# them in a virtualenv and cache it as well.
-cache:
- paths:
- - .cache/pip
- - venv/
-
-before_script:
- - python -V # Print out python version for debugging
- - pip install virtualenv
- - virtualenv venv
- - source venv/bin/activate
-
-test:
- script:
- - python setup.py test
- - pip install tox flake8 # you can also use tox
- - tox -e py36,flake8
-
-run:
- script:
- - python setup.py bdist_wheel
- # an alternative approach is to install and run:
- - pip install dist/*
- # run the command here
- artifacts:
- paths:
- - dist/*.whl
-
-pages:
- script:
- - pip install sphinx sphinx-rtd-theme
- - cd doc ; make html
- - mv build/html/ ../public/
- artifacts:
- paths:
- - public
- only:
- - master
diff --git a/vendor/gitlab-ci-yml/Swift.gitlab-ci.yml b/vendor/gitlab-ci-yml/Swift.gitlab-ci.yml
deleted file mode 100644
index b97bfd460f2..00000000000
--- a/vendor/gitlab-ci-yml/Swift.gitlab-ci.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-# Lifted from: https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/
-# This file assumes an own GitLab CI runner, set up on a macOS system.
-stages:
- - build
- - archive
-
-build_project:
- stage: build
- script:
- - xcodebuild clean -project ProjectName.xcodeproj -scheme SchemeName | xcpretty
- - xcodebuild test -project ProjectName.xcodeproj -scheme SchemeName -destination 'platform=iOS Simulator,name=iPhone 8,OS=11.3' | xcpretty -s
- tags:
- - ios_11-3
- - xcode_9-3
- - macos_10-13
-
-archive_project:
- stage: archive
- script:
- - xcodebuild clean archive -archivePath build/ProjectName -scheme SchemeName
- - xcodebuild -exportArchive -exportFormat ipa -archivePath "build/ProjectName.xcarchive" -exportPath "build/ProjectName.ipa" -exportProvisioningProfile "ProvisioningProfileName"
- only:
- - master
- artifacts:
- paths:
- - build/ProjectName.ipa
- tags:
- - ios_11-3
- - xcode_9-3
- - macos_10-13
diff --git a/vendor/jupyter/values.yaml b/vendor/jupyter/values.yaml
index 4ea5b44c59c..781d6e3042f 100644
--- a/vendor/jupyter/values.yaml
+++ b/vendor/jupyter/values.yaml
@@ -13,8 +13,13 @@ auth:
singleuser:
defaultUrl: "/lab"
+ lifecycleHooks:
+ postStart:
+ exec:
+ command: ["sh", "-c", "git clone https://gitlab.com/gitlab-org/nurtch-demo.git DevOps-Runbook-Demo || true"]
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: "nginx"
+ kubernetes.io/tls-acme: "true"
diff --git a/vendor/languages.yml b/vendor/languages.yml
new file mode 100755
index 00000000000..a6edb0415b2
--- /dev/null
+++ b/vendor/languages.yml
@@ -0,0 +1,5488 @@
+# Extracted from https://github.com/github/linguist/blob/master/lib/linguist/languages.yml
+
+# Defines all Languages known to GitHub.
+#
+# type - Either data, programming, markup, prose, or nil
+# aliases - An Array of additional aliases (implicitly
+# includes name.downcase)
+# ace_mode - A String name of the Ace Mode used for highlighting whenever
+# a file is edited. This must match one of the filenames in http://git.io/3XO_Cg.
+# Use "text" if a mode does not exist.
+# codemirror_mode - A String name of the CodeMirror Mode used for highlighting whenever a file is edited.
+# This must match a mode from https://git.io/vi9Fx
+# codemirror_mime_type - A String name of the file mime type used for highlighting whenever a file is edited.
+# This should match the `mime` associated with the mode from https://git.io/f4SoQ
+# wrap - Boolean wrap to enable line wrapping (default: false)
+# extensions - An Array of associated extensions (the first one is
+# considered the primary extension, the others should be
+# listed alphabetically)
+# filenames - An Array of filenames commonly associated with the language
+# interpreters - An Array of associated interpreters
+# searchable - Boolean flag to enable searching (defaults to true)
+# language_id - Integer used as a language-name-independent indexed field so that we can rename
+# languages in Linguist without reindexing all the code on GitHub. Must not be
+# changed for existing languages without the explicit permission of GitHub staff.
+# color - CSS hex color to represent the language. Only used if type is "programming" or "prose".
+# tm_scope - The TextMate scope that represents this programming
+# language. This should match one of the scopes listed in
+# the grammars.yml file. Use "none" if there is no grammar
+# for this language.
+# group - Name of the parent language. Languages in a group are counted
+# in the statistics as the parent language.
+#
+# Any additions or modifications (even trivial) should have corresponding
+# test changes in `test/test_blob.rb`.
+#
+# Please keep this list alphabetized. Capitalization comes before lowercase.
+
+---
+1C Enterprise:
+ type: programming
+ color: "#814CCC"
+ extensions:
+ - ".bsl"
+ - ".os"
+ tm_scope: source.bsl
+ ace_mode: text
+ language_id: 0
+ABAP:
+ type: programming
+ color: "#E8274B"
+ extensions:
+ - ".abap"
+ ace_mode: abap
+ language_id: 1
+ABNF:
+ type: data
+ ace_mode: text
+ extensions:
+ - ".abnf"
+ tm_scope: source.abnf
+ language_id: 429
+AGS Script:
+ type: programming
+ color: "#B9D9FF"
+ aliases:
+ - ags
+ extensions:
+ - ".asc"
+ - ".ash"
+ tm_scope: source.c++
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-c++src
+ language_id: 2
+AMPL:
+ type: programming
+ color: "#E6EFBB"
+ extensions:
+ - ".ampl"
+ - ".mod"
+ tm_scope: source.ampl
+ ace_mode: text
+ language_id: 3
+ANTLR:
+ type: programming
+ color: "#9DC3FF"
+ extensions:
+ - ".g4"
+ ace_mode: text
+ language_id: 4
+API Blueprint:
+ type: markup
+ color: "#2ACCA8"
+ ace_mode: markdown
+ extensions:
+ - ".apib"
+ tm_scope: text.html.markdown.source.gfm.apib
+ language_id: 5
+APL:
+ type: programming
+ color: "#5A8164"
+ extensions:
+ - ".apl"
+ - ".dyalog"
+ interpreters:
+ - apl
+ - aplx
+ - dyalog
+ tm_scope: source.apl
+ ace_mode: text
+ codemirror_mode: apl
+ codemirror_mime_type: text/apl
+ language_id: 6
+ASN.1:
+ type: data
+ extensions:
+ - ".asn"
+ - ".asn1"
+ tm_scope: source.asn
+ ace_mode: text
+ codemirror_mode: asn.1
+ codemirror_mime_type: text/x-ttcn-asn
+ language_id: 7
+ASP:
+ type: programming
+ color: "#6a40fd"
+ tm_scope: text.html.asp
+ aliases:
+ - aspx
+ - aspx-vb
+ extensions:
+ - ".asp"
+ - ".asax"
+ - ".ascx"
+ - ".ashx"
+ - ".asmx"
+ - ".aspx"
+ - ".axd"
+ ace_mode: text
+ codemirror_mode: htmlembedded
+ codemirror_mime_type: application/x-aspx
+ language_id: 8
+ATS:
+ type: programming
+ color: "#1ac620"
+ aliases:
+ - ats2
+ extensions:
+ - ".dats"
+ - ".hats"
+ - ".sats"
+ tm_scope: source.ats
+ ace_mode: ocaml
+ language_id: 9
+ActionScript:
+ type: programming
+ tm_scope: source.actionscript.3
+ color: "#882B0F"
+ aliases:
+ - actionscript 3
+ - actionscript3
+ - as3
+ extensions:
+ - ".as"
+ ace_mode: actionscript
+ language_id: 10
+Ada:
+ type: programming
+ color: "#02f88c"
+ extensions:
+ - ".adb"
+ - ".ada"
+ - ".ads"
+ aliases:
+ - ada95
+ - ada2005
+ ace_mode: ada
+ language_id: 11
+Adobe Font Metrics:
+ type: data
+ tm_scope: source.afm
+ extensions:
+ - ".afm"
+ aliases:
+ - acfm
+ - adobe composite font metrics
+ - adobe multiple font metrics
+ - amfm
+ ace_mode: text
+ language_id: 147198098
+Agda:
+ type: programming
+ color: "#315665"
+ extensions:
+ - ".agda"
+ ace_mode: text
+ language_id: 12
+Alloy:
+ type: programming
+ color: "#64C800"
+ extensions:
+ - ".als"
+ ace_mode: text
+ language_id: 13
+Alpine Abuild:
+ type: programming
+ group: Shell
+ aliases:
+ - abuild
+ - apkbuild
+ filenames:
+ - APKBUILD
+ tm_scope: source.shell
+ ace_mode: sh
+ codemirror_mode: shell
+ codemirror_mime_type: text/x-sh
+ language_id: 14
+AngelScript:
+ type: programming
+ color: "#C7D7DC"
+ extensions:
+ - ".as"
+ - ".angelscript"
+ tm_scope: source.angelscript
+ ace_mode: text
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-c++src
+ language_id: 389477596
+Ant Build System:
+ type: data
+ tm_scope: text.xml.ant
+ filenames:
+ - ant.xml
+ - build.xml
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: application/xml
+ language_id: 15
+ApacheConf:
+ type: data
+ aliases:
+ - aconf
+ - apache
+ extensions:
+ - ".apacheconf"
+ - ".vhost"
+ filenames:
+ - ".htaccess"
+ - apache2.conf
+ - httpd.conf
+ tm_scope: source.apache-config
+ ace_mode: apache_conf
+ language_id: 16
+Apex:
+ type: programming
+ extensions:
+ - ".cls"
+ tm_scope: source.java
+ ace_mode: java
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-java
+ language_id: 17
+Apollo Guidance Computer:
+ type: programming
+ group: Assembly
+ extensions:
+ - ".agc"
+ tm_scope: source.agc
+ ace_mode: assembly_x86
+ language_id: 18
+AppleScript:
+ type: programming
+ aliases:
+ - osascript
+ extensions:
+ - ".applescript"
+ - ".scpt"
+ interpreters:
+ - osascript
+ ace_mode: applescript
+ color: "#101F1F"
+ language_id: 19
+Arc:
+ type: programming
+ color: "#aa2afe"
+ extensions:
+ - ".arc"
+ tm_scope: none
+ ace_mode: text
+ language_id: 20
+AsciiDoc:
+ type: prose
+ ace_mode: asciidoc
+ wrap: true
+ extensions:
+ - ".asciidoc"
+ - ".adoc"
+ - ".asc"
+ tm_scope: text.html.asciidoc
+ language_id: 22
+AspectJ:
+ type: programming
+ color: "#a957b0"
+ extensions:
+ - ".aj"
+ tm_scope: source.aspectj
+ ace_mode: text
+ language_id: 23
+Assembly:
+ type: programming
+ color: "#6E4C13"
+ aliases:
+ - asm
+ - nasm
+ extensions:
+ - ".asm"
+ - ".a51"
+ - ".inc"
+ - ".nasm"
+ tm_scope: source.assembly
+ ace_mode: assembly_x86
+ language_id: 24
+Augeas:
+ type: programming
+ extensions:
+ - ".aug"
+ tm_scope: none
+ ace_mode: text
+ language_id: 25
+AutoHotkey:
+ type: programming
+ color: "#6594b9"
+ aliases:
+ - ahk
+ extensions:
+ - ".ahk"
+ - ".ahkl"
+ tm_scope: source.ahk
+ ace_mode: autohotkey
+ language_id: 26
+AutoIt:
+ type: programming
+ color: "#1C3552"
+ aliases:
+ - au3
+ - AutoIt3
+ - AutoItScript
+ extensions:
+ - ".au3"
+ tm_scope: source.autoit
+ ace_mode: autohotkey
+ language_id: 27
+Awk:
+ type: programming
+ extensions:
+ - ".awk"
+ - ".auk"
+ - ".gawk"
+ - ".mawk"
+ - ".nawk"
+ interpreters:
+ - awk
+ - gawk
+ - mawk
+ - nawk
+ ace_mode: text
+ language_id: 28
+Ballerina:
+ type: programming
+ extensions:
+ - ".bal"
+ tm_scope: source.ballerina
+ ace_mode: text
+ color: "#FF5000"
+ language_id: 720859680
+Batchfile:
+ type: programming
+ aliases:
+ - bat
+ - batch
+ - dosbatch
+ - winbatch
+ extensions:
+ - ".bat"
+ - ".cmd"
+ tm_scope: source.batchfile
+ ace_mode: batchfile
+ color: "#C1F12E"
+ language_id: 29
+Befunge:
+ type: programming
+ extensions:
+ - ".befunge"
+ ace_mode: text
+ language_id: 30
+Bison:
+ type: programming
+ group: Yacc
+ tm_scope: source.bison
+ extensions:
+ - ".bison"
+ ace_mode: text
+ language_id: 31
+BitBake:
+ type: programming
+ tm_scope: none
+ extensions:
+ - ".bb"
+ ace_mode: text
+ language_id: 32
+Blade:
+ type: markup
+ group: HTML
+ extensions:
+ - ".blade"
+ - ".blade.php"
+ tm_scope: text.html.php.blade
+ ace_mode: text
+ language_id: 33
+BlitzBasic:
+ type: programming
+ aliases:
+ - b3d
+ - blitz3d
+ - blitzplus
+ - bplus
+ extensions:
+ - ".bb"
+ - ".decls"
+ tm_scope: source.blitzmax
+ ace_mode: text
+ language_id: 34
+BlitzMax:
+ type: programming
+ color: "#cd6400"
+ extensions:
+ - ".bmx"
+ aliases:
+ - bmax
+ ace_mode: text
+ language_id: 35
+Bluespec:
+ type: programming
+ extensions:
+ - ".bsv"
+ tm_scope: source.bsv
+ ace_mode: verilog
+ language_id: 36
+Boo:
+ type: programming
+ color: "#d4bec1"
+ extensions:
+ - ".boo"
+ ace_mode: text
+ tm_scope: source.boo
+ language_id: 37
+Brainfuck:
+ type: programming
+ color: "#2F2530"
+ extensions:
+ - ".b"
+ - ".bf"
+ tm_scope: source.bf
+ ace_mode: text
+ codemirror_mode: brainfuck
+ codemirror_mime_type: text/x-brainfuck
+ language_id: 38
+Brightscript:
+ type: programming
+ extensions:
+ - ".brs"
+ tm_scope: source.brightscript
+ ace_mode: text
+ language_id: 39
+Bro:
+ type: programming
+ extensions:
+ - ".bro"
+ ace_mode: text
+ language_id: 40
+C:
+ type: programming
+ color: "#555555"
+ extensions:
+ - ".c"
+ - ".cats"
+ - ".h"
+ - ".idc"
+ interpreters:
+ - tcc
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csrc
+ language_id: 41
+C#:
+ type: programming
+ ace_mode: csharp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csharp
+ tm_scope: source.cs
+ color: "#178600"
+ aliases:
+ - csharp
+ extensions:
+ - ".cs"
+ - ".cake"
+ - ".cshtml"
+ - ".csx"
+ language_id: 42
+C++:
+ type: programming
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-c++src
+ color: "#f34b7d"
+ aliases:
+ - cpp
+ extensions:
+ - ".cpp"
+ - ".c++"
+ - ".cc"
+ - ".cp"
+ - ".cxx"
+ - ".h"
+ - ".h++"
+ - ".hh"
+ - ".hpp"
+ - ".hxx"
+ - ".inc"
+ - ".inl"
+ - ".ino"
+ - ".ipp"
+ - ".re"
+ - ".tcc"
+ - ".tpp"
+ language_id: 43
+C-ObjDump:
+ type: data
+ extensions:
+ - ".c-objdump"
+ tm_scope: objdump.x86asm
+ ace_mode: assembly_x86
+ language_id: 44
+C2hs Haskell:
+ type: programming
+ group: Haskell
+ aliases:
+ - c2hs
+ extensions:
+ - ".chs"
+ tm_scope: source.haskell
+ ace_mode: haskell
+ codemirror_mode: haskell
+ codemirror_mime_type: text/x-haskell
+ language_id: 45
+CLIPS:
+ type: programming
+ extensions:
+ - ".clp"
+ tm_scope: source.clips
+ ace_mode: text
+ language_id: 46
+CMake:
+ type: programming
+ extensions:
+ - ".cmake"
+ - ".cmake.in"
+ filenames:
+ - CMakeLists.txt
+ ace_mode: text
+ codemirror_mode: cmake
+ codemirror_mime_type: text/x-cmake
+ language_id: 47
+COBOL:
+ type: programming
+ extensions:
+ - ".cob"
+ - ".cbl"
+ - ".ccp"
+ - ".cobol"
+ - ".cpy"
+ ace_mode: cobol
+ codemirror_mode: cobol
+ codemirror_mime_type: text/x-cobol
+ language_id: 48
+COLLADA:
+ type: data
+ extensions:
+ - ".dae"
+ tm_scope: text.xml
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ language_id: 49
+CSON:
+ type: data
+ group: CoffeeScript
+ tm_scope: source.coffee
+ ace_mode: coffee
+ codemirror_mode: coffeescript
+ codemirror_mime_type: text/x-coffeescript
+ searchable: false
+ extensions:
+ - ".cson"
+ language_id: 424
+CSS:
+ type: markup
+ tm_scope: source.css
+ ace_mode: css
+ codemirror_mode: css
+ codemirror_mime_type: text/css
+ color: "#563d7c"
+ extensions:
+ - ".css"
+ language_id: 50
+CSV:
+ type: data
+ ace_mode: text
+ tm_scope: none
+ extensions:
+ - ".csv"
+ language_id: 51
+CWeb:
+ type: programming
+ extensions:
+ - ".w"
+ tm_scope: none
+ ace_mode: text
+ language_id: 657332628
+Cap'n Proto:
+ type: programming
+ tm_scope: source.capnp
+ extensions:
+ - ".capnp"
+ ace_mode: text
+ language_id: 52
+CartoCSS:
+ type: programming
+ aliases:
+ - Carto
+ extensions:
+ - ".mss"
+ ace_mode: text
+ tm_scope: source.css.mss
+ language_id: 53
+Ceylon:
+ type: programming
+ color: "#dfa535"
+ extensions:
+ - ".ceylon"
+ tm_scope: source.ceylon
+ ace_mode: text
+ language_id: 54
+Chapel:
+ type: programming
+ color: "#8dc63f"
+ aliases:
+ - chpl
+ extensions:
+ - ".chpl"
+ ace_mode: text
+ language_id: 55
+Charity:
+ type: programming
+ extensions:
+ - ".ch"
+ tm_scope: none
+ ace_mode: text
+ language_id: 56
+ChucK:
+ type: programming
+ extensions:
+ - ".ck"
+ tm_scope: source.java
+ ace_mode: java
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-java
+ language_id: 57
+Cirru:
+ type: programming
+ color: "#ccccff"
+ ace_mode: cirru
+ extensions:
+ - ".cirru"
+ language_id: 58
+Clarion:
+ type: programming
+ color: "#db901e"
+ ace_mode: text
+ extensions:
+ - ".clw"
+ tm_scope: source.clarion
+ language_id: 59
+Clean:
+ type: programming
+ color: "#3F85AF"
+ extensions:
+ - ".icl"
+ - ".dcl"
+ tm_scope: source.clean
+ ace_mode: text
+ language_id: 60
+Click:
+ type: programming
+ color: "#E4E6F3"
+ extensions:
+ - ".click"
+ tm_scope: source.click
+ ace_mode: text
+ language_id: 61
+Clojure:
+ type: programming
+ ace_mode: clojure
+ codemirror_mode: clojure
+ codemirror_mime_type: text/x-clojure
+ color: "#db5855"
+ extensions:
+ - ".clj"
+ - ".boot"
+ - ".cl2"
+ - ".cljc"
+ - ".cljs"
+ - ".cljs.hl"
+ - ".cljscm"
+ - ".cljx"
+ - ".hic"
+ filenames:
+ - riemann.config
+ language_id: 62
+Closure Templates:
+ type: markup
+ group: HTML
+ ace_mode: soy_template
+ codemirror_mode: soy
+ codemirror_mime_type: text/x-soy
+ aliases:
+ - soy
+ extensions:
+ - ".soy"
+ tm_scope: text.html.soy
+ language_id: 357046146
+Cloud Firestore Security Rules:
+ type: data
+ ace_mode: less
+ codemirror_mode: css
+ codemirror_mime_type: text/css
+ tm_scope: source.firestore
+ filenames:
+ - firestore.rules
+ language_id: 407996372
+CoNLL-U:
+ type: data
+ extensions:
+ - ".conllu"
+ - ".conll"
+ tm_scope: text.conllu
+ ace_mode: text
+ aliases:
+ - CoNLL
+ - CoNLL-X
+ language_id: 421026389
+CoffeeScript:
+ type: programming
+ tm_scope: source.coffee
+ ace_mode: coffee
+ codemirror_mode: coffeescript
+ codemirror_mime_type: text/x-coffeescript
+ color: "#244776"
+ aliases:
+ - coffee
+ - coffee-script
+ extensions:
+ - ".coffee"
+ - "._coffee"
+ - ".cake"
+ - ".cjsx"
+ - ".iced"
+ filenames:
+ - Cakefile
+ interpreters:
+ - coffee
+ language_id: 63
+ColdFusion:
+ type: programming
+ ace_mode: coldfusion
+ color: "#ed2cd6"
+ aliases:
+ - cfm
+ - cfml
+ - coldfusion html
+ extensions:
+ - ".cfm"
+ - ".cfml"
+ tm_scope: text.html.cfm
+ language_id: 64
+ColdFusion CFC:
+ type: programming
+ group: ColdFusion
+ ace_mode: coldfusion
+ aliases:
+ - cfc
+ extensions:
+ - ".cfc"
+ tm_scope: source.cfscript
+ language_id: 65
+Common Lisp:
+ type: programming
+ tm_scope: source.lisp
+ color: "#3fb68b"
+ aliases:
+ - lisp
+ extensions:
+ - ".lisp"
+ - ".asd"
+ - ".cl"
+ - ".l"
+ - ".lsp"
+ - ".ny"
+ - ".podsl"
+ - ".sexp"
+ interpreters:
+ - lisp
+ - sbcl
+ - ccl
+ - clisp
+ - ecl
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ language_id: 66
+Common Workflow Language:
+ aliases:
+ - cwl
+ type: programming
+ ace_mode: yaml
+ codemirror_mode: yaml
+ codemirror_mime_type: text/x-yaml
+ extensions:
+ - ".cwl"
+ interpreters:
+ - cwl-runner
+ color: "#B5314C"
+ tm_scope: source.cwl
+ language_id: 988547172
+Component Pascal:
+ type: programming
+ color: "#B0CE4E"
+ extensions:
+ - ".cp"
+ - ".cps"
+ tm_scope: source.pascal
+ aliases:
+ - delphi
+ - objectpascal
+ ace_mode: pascal
+ codemirror_mode: pascal
+ codemirror_mime_type: text/x-pascal
+ language_id: 67
+Cool:
+ type: programming
+ extensions:
+ - ".cl"
+ tm_scope: source.cool
+ ace_mode: text
+ language_id: 68
+Coq:
+ type: programming
+ extensions:
+ - ".coq"
+ - ".v"
+ ace_mode: text
+ language_id: 69
+Cpp-ObjDump:
+ type: data
+ extensions:
+ - ".cppobjdump"
+ - ".c++-objdump"
+ - ".c++objdump"
+ - ".cpp-objdump"
+ - ".cxx-objdump"
+ tm_scope: objdump.x86asm
+ aliases:
+ - c++-objdump
+ ace_mode: assembly_x86
+ language_id: 70
+Creole:
+ type: prose
+ wrap: true
+ extensions:
+ - ".creole"
+ tm_scope: text.html.creole
+ ace_mode: text
+ language_id: 71
+Crystal:
+ type: programming
+ color: "#776791"
+ extensions:
+ - ".cr"
+ ace_mode: ruby
+ codemirror_mode: crystal
+ codemirror_mime_type: text/x-crystal
+ tm_scope: source.crystal
+ interpreters:
+ - crystal
+ language_id: 72
+Csound:
+ type: programming
+ aliases:
+ - csound-orc
+ extensions:
+ - ".orc"
+ - ".udo"
+ tm_scope: source.csound
+ ace_mode: csound_orchestra
+ language_id: 73
+Csound Document:
+ type: programming
+ aliases:
+ - csound-csd
+ extensions:
+ - ".csd"
+ tm_scope: source.csound-document
+ ace_mode: csound_document
+ language_id: 74
+Csound Score:
+ type: programming
+ aliases:
+ - csound-sco
+ extensions:
+ - ".sco"
+ tm_scope: source.csound-score
+ ace_mode: csound_score
+ language_id: 75
+Cuda:
+ type: programming
+ extensions:
+ - ".cu"
+ - ".cuh"
+ tm_scope: source.cuda-c++
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-c++src
+ color: "#3A4E3A"
+ language_id: 77
+Cycript:
+ type: programming
+ extensions:
+ - ".cy"
+ tm_scope: source.js
+ ace_mode: javascript
+ codemirror_mode: javascript
+ codemirror_mime_type: text/javascript
+ language_id: 78
+Cython:
+ type: programming
+ group: Python
+ extensions:
+ - ".pyx"
+ - ".pxd"
+ - ".pxi"
+ aliases:
+ - pyrex
+ ace_mode: text
+ codemirror_mode: python
+ codemirror_mime_type: text/x-cython
+ language_id: 79
+D:
+ type: programming
+ color: "#ba595e"
+ extensions:
+ - ".d"
+ - ".di"
+ ace_mode: d
+ codemirror_mode: d
+ codemirror_mime_type: text/x-d
+ language_id: 80
+D-ObjDump:
+ type: data
+ extensions:
+ - ".d-objdump"
+ tm_scope: objdump.x86asm
+ ace_mode: assembly_x86
+ language_id: 81
+DIGITAL Command Language:
+ type: programming
+ aliases:
+ - dcl
+ extensions:
+ - ".com"
+ tm_scope: none
+ ace_mode: text
+ language_id: 82
+DM:
+ type: programming
+ color: "#447265"
+ extensions:
+ - ".dm"
+ aliases:
+ - byond
+ tm_scope: source.dm
+ ace_mode: c_cpp
+ language_id: 83
+DNS Zone:
+ type: data
+ extensions:
+ - ".zone"
+ - ".arpa"
+ tm_scope: text.zone_file
+ ace_mode: text
+ language_id: 84
+DTrace:
+ type: programming
+ aliases:
+ - dtrace-script
+ extensions:
+ - ".d"
+ interpreters:
+ - dtrace
+ tm_scope: source.c
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csrc
+ language_id: 85
+Darcs Patch:
+ type: data
+ aliases:
+ - dpatch
+ extensions:
+ - ".darcspatch"
+ - ".dpatch"
+ tm_scope: none
+ ace_mode: text
+ language_id: 86
+Dart:
+ type: programming
+ color: "#00B4AB"
+ extensions:
+ - ".dart"
+ interpreters:
+ - dart
+ ace_mode: dart
+ codemirror_mode: dart
+ codemirror_mime_type: application/dart
+ language_id: 87
+DataWeave:
+ type: programming
+ color: "#003a52"
+ extensions:
+ - ".dwl"
+ ace_mode: text
+ tm_scope: source.data-weave
+ language_id: 974514097
+Diff:
+ type: data
+ extensions:
+ - ".diff"
+ - ".patch"
+ aliases:
+ - udiff
+ tm_scope: source.diff
+ ace_mode: diff
+ codemirror_mode: diff
+ codemirror_mime_type: text/x-diff
+ language_id: 88
+Dockerfile:
+ type: programming
+ color: "#0db7ed"
+ tm_scope: source.dockerfile
+ extensions:
+ - ".dockerfile"
+ filenames:
+ - Dockerfile
+ ace_mode: dockerfile
+ codemirror_mode: dockerfile
+ codemirror_mime_type: text/x-dockerfile
+ language_id: 89
+Dogescript:
+ type: programming
+ color: "#cca760"
+ extensions:
+ - ".djs"
+ tm_scope: none
+ ace_mode: text
+ language_id: 90
+Dylan:
+ type: programming
+ color: "#6c616e"
+ extensions:
+ - ".dylan"
+ - ".dyl"
+ - ".intr"
+ - ".lid"
+ ace_mode: text
+ codemirror_mode: dylan
+ codemirror_mime_type: text/x-dylan
+ language_id: 91
+E:
+ type: programming
+ color: "#ccce35"
+ extensions:
+ - ".E"
+ interpreters:
+ - rune
+ tm_scope: none
+ ace_mode: text
+ language_id: 92
+EBNF:
+ type: data
+ extensions:
+ - ".ebnf"
+ tm_scope: source.ebnf
+ ace_mode: text
+ codemirror_mode: ebnf
+ codemirror_mime_type: text/x-ebnf
+ language_id: 430
+ECL:
+ type: programming
+ color: "#8a1267"
+ extensions:
+ - ".ecl"
+ - ".eclxml"
+ tm_scope: none
+ ace_mode: text
+ codemirror_mode: ecl
+ codemirror_mime_type: text/x-ecl
+ language_id: 93
+ECLiPSe:
+ type: programming
+ group: prolog
+ extensions:
+ - ".ecl"
+ tm_scope: source.prolog.eclipse
+ ace_mode: prolog
+ language_id: 94
+EJS:
+ type: markup
+ group: HTML
+ extensions:
+ - ".ejs"
+ tm_scope: text.html.js
+ ace_mode: ejs
+ language_id: 95
+EQ:
+ type: programming
+ color: "#a78649"
+ extensions:
+ - ".eq"
+ tm_scope: source.cs
+ ace_mode: csharp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csharp
+ language_id: 96
+Eagle:
+ type: data
+ extensions:
+ - ".sch"
+ - ".brd"
+ tm_scope: text.xml
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ language_id: 97
+Easybuild:
+ type: data
+ group: Python
+ ace_mode: python
+ codemirror_mode: python
+ codemirror_mime_type: text/x-python
+ tm_scope: source.python
+ extensions:
+ - ".eb"
+ language_id: 342840477
+Ecere Projects:
+ type: data
+ group: JavaScript
+ extensions:
+ - ".epj"
+ tm_scope: source.json
+ ace_mode: json
+ codemirror_mode: javascript
+ codemirror_mime_type: application/json
+ language_id: 98
+Edje Data Collection:
+ type: data
+ extensions:
+ - ".edc"
+ tm_scope: source.json
+ ace_mode: json
+ codemirror_mode: javascript
+ codemirror_mime_type: application/json
+ language_id: 342840478
+Eiffel:
+ type: programming
+ color: "#946d57"
+ extensions:
+ - ".e"
+ ace_mode: eiffel
+ codemirror_mode: eiffel
+ codemirror_mime_type: text/x-eiffel
+ language_id: 99
+Elixir:
+ type: programming
+ color: "#6e4a7e"
+ extensions:
+ - ".ex"
+ - ".exs"
+ ace_mode: elixir
+ filenames:
+ - mix.lock
+ interpreters:
+ - elixir
+ language_id: 100
+Elm:
+ type: programming
+ color: "#60B5CC"
+ extensions:
+ - ".elm"
+ tm_scope: source.elm
+ ace_mode: elm
+ codemirror_mode: elm
+ codemirror_mime_type: text/x-elm
+ language_id: 101
+Emacs Lisp:
+ type: programming
+ tm_scope: source.emacs.lisp
+ color: "#c065db"
+ aliases:
+ - elisp
+ - emacs
+ filenames:
+ - ".abbrev_defs"
+ - ".emacs"
+ - ".emacs.desktop"
+ - ".gnus"
+ - ".spacemacs"
+ - ".viper"
+ - Cask
+ - Project.ede
+ - _emacs
+ - abbrev_defs
+ extensions:
+ - ".el"
+ - ".emacs"
+ - ".emacs.desktop"
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ language_id: 102
+EmberScript:
+ type: programming
+ color: "#FFF4F3"
+ extensions:
+ - ".em"
+ - ".emberscript"
+ tm_scope: source.coffee
+ ace_mode: coffee
+ codemirror_mode: coffeescript
+ codemirror_mime_type: text/x-coffeescript
+ language_id: 103
+Erlang:
+ type: programming
+ color: "#B83998"
+ extensions:
+ - ".erl"
+ - ".app.src"
+ - ".es"
+ - ".escript"
+ - ".hrl"
+ - ".xrl"
+ - ".yrl"
+ filenames:
+ - Emakefile
+ - rebar.config
+ - rebar.config.lock
+ - rebar.lock
+ ace_mode: erlang
+ codemirror_mode: erlang
+ codemirror_mime_type: text/x-erlang
+ interpreters:
+ - escript
+ language_id: 104
+F#:
+ type: programming
+ color: "#b845fc"
+ aliases:
+ - fsharp
+ extensions:
+ - ".fs"
+ - ".fsi"
+ - ".fsx"
+ tm_scope: source.fsharp
+ ace_mode: text
+ codemirror_mode: mllike
+ codemirror_mime_type: text/x-fsharp
+ language_id: 105
+FLUX:
+ type: programming
+ color: "#88ccff"
+ extensions:
+ - ".fx"
+ - ".flux"
+ tm_scope: none
+ ace_mode: text
+ language_id: 106
+Factor:
+ type: programming
+ color: "#636746"
+ extensions:
+ - ".factor"
+ filenames:
+ - ".factor-boot-rc"
+ - ".factor-rc"
+ ace_mode: text
+ codemirror_mode: factor
+ codemirror_mime_type: text/x-factor
+ language_id: 108
+Fancy:
+ type: programming
+ color: "#7b9db4"
+ extensions:
+ - ".fy"
+ - ".fancypack"
+ filenames:
+ - Fakefile
+ ace_mode: text
+ language_id: 109
+Fantom:
+ type: programming
+ color: "#14253c"
+ extensions:
+ - ".fan"
+ tm_scope: source.fan
+ ace_mode: text
+ language_id: 110
+Filebench WML:
+ type: programming
+ extensions:
+ - ".f"
+ tm_scope: none
+ ace_mode: text
+ language_id: 111
+Filterscript:
+ type: programming
+ group: RenderScript
+ extensions:
+ - ".fs"
+ tm_scope: none
+ ace_mode: text
+ language_id: 112
+Formatted:
+ type: data
+ extensions:
+ - ".for"
+ - ".eam.fs"
+ tm_scope: none
+ ace_mode: text
+ language_id: 113
+Forth:
+ type: programming
+ color: "#341708"
+ extensions:
+ - ".fth"
+ - ".4th"
+ - ".f"
+ - ".for"
+ - ".forth"
+ - ".fr"
+ - ".frt"
+ - ".fs"
+ ace_mode: forth
+ codemirror_mode: forth
+ codemirror_mime_type: text/x-forth
+ language_id: 114
+Fortran:
+ type: programming
+ color: "#4d41b1"
+ extensions:
+ - ".f90"
+ - ".f"
+ - ".f03"
+ - ".f08"
+ - ".f77"
+ - ".f95"
+ - ".for"
+ - ".fpp"
+ tm_scope: source.fortran.modern
+ ace_mode: text
+ codemirror_mode: fortran
+ codemirror_mime_type: text/x-fortran
+ language_id: 107
+FreeMarker:
+ type: programming
+ color: "#0050b2"
+ aliases:
+ - ftl
+ extensions:
+ - ".ftl"
+ tm_scope: text.html.ftl
+ ace_mode: ftl
+ language_id: 115
+Frege:
+ type: programming
+ color: "#00cafe"
+ extensions:
+ - ".fr"
+ tm_scope: source.haskell
+ ace_mode: haskell
+ language_id: 116
+G-code:
+ type: data
+ extensions:
+ - ".g"
+ - ".gco"
+ - ".gcode"
+ tm_scope: source.gcode
+ ace_mode: gcode
+ language_id: 117
+GAMS:
+ type: programming
+ extensions:
+ - ".gms"
+ tm_scope: none
+ ace_mode: text
+ language_id: 118
+GAP:
+ type: programming
+ extensions:
+ - ".g"
+ - ".gap"
+ - ".gd"
+ - ".gi"
+ - ".tst"
+ tm_scope: source.gap
+ ace_mode: text
+ language_id: 119
+GCC Machine Description:
+ type: programming
+ extensions:
+ - ".md"
+ tm_scope: source.lisp
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ language_id: 121
+GDB:
+ type: programming
+ extensions:
+ - ".gdb"
+ - ".gdbinit"
+ tm_scope: source.gdb
+ ace_mode: text
+ language_id: 122
+GDScript:
+ type: programming
+ color: "#355570"
+ extensions:
+ - ".gd"
+ tm_scope: source.gdscript
+ ace_mode: text
+ language_id: 123
+GLSL:
+ type: programming
+ extensions:
+ - ".glsl"
+ - ".fp"
+ - ".frag"
+ - ".frg"
+ - ".fs"
+ - ".fsh"
+ - ".fshader"
+ - ".geo"
+ - ".geom"
+ - ".glslv"
+ - ".gshader"
+ - ".shader"
+ - ".tesc"
+ - ".tese"
+ - ".vert"
+ - ".vrx"
+ - ".vsh"
+ - ".vshader"
+ ace_mode: glsl
+ language_id: 124
+GN:
+ type: data
+ extensions:
+ - ".gn"
+ - ".gni"
+ interpreters:
+ - gn
+ filenames:
+ - ".gn"
+ tm_scope: source.gn
+ ace_mode: python
+ codemirror_mode: python
+ codemirror_mime_type: text/x-python
+ language_id: 302957008
+Game Maker Language:
+ type: programming
+ color: "#8fb200"
+ extensions:
+ - ".gml"
+ tm_scope: source.c++
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-c++src
+ language_id: 125
+Genie:
+ type: programming
+ ace_mode: text
+ extensions:
+ - ".gs"
+ color: "#fb855d"
+ tm_scope: none
+ language_id: 792408528
+Genshi:
+ type: programming
+ extensions:
+ - ".kid"
+ tm_scope: text.xml.genshi
+ aliases:
+ - xml+genshi
+ - xml+kid
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ language_id: 126
+Gentoo Ebuild:
+ type: programming
+ group: Shell
+ extensions:
+ - ".ebuild"
+ tm_scope: source.shell
+ ace_mode: sh
+ codemirror_mode: shell
+ codemirror_mime_type: text/x-sh
+ language_id: 127
+Gentoo Eclass:
+ type: programming
+ group: Shell
+ extensions:
+ - ".eclass"
+ tm_scope: source.shell
+ ace_mode: sh
+ codemirror_mode: shell
+ codemirror_mime_type: text/x-sh
+ language_id: 128
+Gerber Image:
+ type: data
+ aliases:
+ - rs-274x
+ extensions:
+ - ".gbr"
+ - ".gbl"
+ - ".gbo"
+ - ".gbp"
+ - ".gbs"
+ - ".gko"
+ - ".gpb"
+ - ".gpt"
+ - ".gtl"
+ - ".gto"
+ - ".gtp"
+ - ".gts"
+ interpreters:
+ - gerbv
+ - gerbview
+ tm_scope: source.gerber
+ ace_mode: text
+ language_id: 404627610
+Gettext Catalog:
+ type: prose
+ searchable: false
+ aliases:
+ - pot
+ extensions:
+ - ".po"
+ - ".pot"
+ tm_scope: source.po
+ ace_mode: text
+ language_id: 129
+Gherkin:
+ type: programming
+ extensions:
+ - ".feature"
+ tm_scope: text.gherkin.feature
+ aliases:
+ - cucumber
+ ace_mode: text
+ color: "#5B2063"
+ language_id: 76
+Glyph:
+ type: programming
+ color: "#c1ac7f"
+ extensions:
+ - ".glf"
+ tm_scope: source.tcl
+ ace_mode: tcl
+ codemirror_mode: tcl
+ codemirror_mime_type: text/x-tcl
+ language_id: 130
+Gnuplot:
+ type: programming
+ color: "#f0a9f0"
+ extensions:
+ - ".gp"
+ - ".gnu"
+ - ".gnuplot"
+ - ".plot"
+ - ".plt"
+ interpreters:
+ - gnuplot
+ ace_mode: text
+ language_id: 131
+Go:
+ type: programming
+ color: "#375eab"
+ aliases:
+ - golang
+ extensions:
+ - ".go"
+ ace_mode: golang
+ codemirror_mode: go
+ codemirror_mime_type: text/x-go
+ language_id: 132
+Golo:
+ type: programming
+ color: "#88562A"
+ extensions:
+ - ".golo"
+ tm_scope: source.golo
+ ace_mode: text
+ language_id: 133
+Gosu:
+ type: programming
+ color: "#82937f"
+ extensions:
+ - ".gs"
+ - ".gst"
+ - ".gsx"
+ - ".vark"
+ tm_scope: source.gosu.2
+ ace_mode: text
+ language_id: 134
+Grace:
+ type: programming
+ extensions:
+ - ".grace"
+ tm_scope: source.grace
+ ace_mode: text
+ language_id: 135
+Gradle:
+ type: data
+ extensions:
+ - ".gradle"
+ tm_scope: source.groovy.gradle
+ ace_mode: text
+ language_id: 136
+Grammatical Framework:
+ type: programming
+ aliases:
+ - gf
+ wrap: false
+ extensions:
+ - ".gf"
+ searchable: true
+ color: "#79aa7a"
+ tm_scope: source.haskell
+ ace_mode: haskell
+ codemirror_mode: haskell
+ codemirror_mime_type: text/x-haskell
+ language_id: 137
+Graph Modeling Language:
+ type: data
+ extensions:
+ - ".gml"
+ tm_scope: none
+ ace_mode: text
+ language_id: 138
+GraphQL:
+ type: data
+ extensions:
+ - ".graphql"
+ - ".gql"
+ tm_scope: source.graphql
+ ace_mode: text
+ language_id: 139
+Graphviz (DOT):
+ type: data
+ tm_scope: source.dot
+ extensions:
+ - ".dot"
+ - ".gv"
+ ace_mode: text
+ language_id: 140
+Groovy:
+ type: programming
+ ace_mode: groovy
+ codemirror_mode: groovy
+ codemirror_mime_type: text/x-groovy
+ color: "#e69f56"
+ extensions:
+ - ".groovy"
+ - ".grt"
+ - ".gtpl"
+ - ".gvy"
+ interpreters:
+ - groovy
+ filenames:
+ - Jenkinsfile
+ language_id: 142
+Groovy Server Pages:
+ type: programming
+ group: Groovy
+ aliases:
+ - gsp
+ - java server page
+ extensions:
+ - ".gsp"
+ tm_scope: text.html.jsp
+ ace_mode: jsp
+ codemirror_mode: htmlembedded
+ codemirror_mime_type: application/x-jsp
+ language_id: 143
+HCL:
+ type: programming
+ extensions:
+ - ".hcl"
+ - ".tf"
+ - ".tfvars"
+ ace_mode: ruby
+ codemirror_mode: ruby
+ codemirror_mime_type: text/x-ruby
+ tm_scope: source.terraform
+ language_id: 144
+HLSL:
+ type: programming
+ extensions:
+ - ".hlsl"
+ - ".cginc"
+ - ".fx"
+ - ".fxh"
+ - ".hlsli"
+ ace_mode: text
+ tm_scope: source.hlsl
+ language_id: 145
+HTML:
+ type: markup
+ tm_scope: text.html.basic
+ ace_mode: html
+ codemirror_mode: htmlmixed
+ codemirror_mime_type: text/html
+ color: "#e34c26"
+ aliases:
+ - xhtml
+ extensions:
+ - ".html"
+ - ".htm"
+ - ".html.hl"
+ - ".inc"
+ - ".st"
+ - ".xht"
+ - ".xhtml"
+ language_id: 146
+HTML+Django:
+ type: markup
+ tm_scope: text.html.django
+ group: HTML
+ extensions:
+ - ".jinja"
+ - ".jinja2"
+ - ".mustache"
+ - ".njk"
+ aliases:
+ - django
+ - html+django/jinja
+ - html+jinja
+ - htmldjango
+ - njk
+ - nunjucks
+ ace_mode: django
+ codemirror_mode: django
+ codemirror_mime_type: text/x-django
+ language_id: 147
+HTML+ECR:
+ type: markup
+ tm_scope: text.html.ecr
+ group: HTML
+ aliases:
+ - ecr
+ extensions:
+ - ".ecr"
+ ace_mode: text
+ codemirror_mode: htmlmixed
+ codemirror_mime_type: text/html
+ language_id: 148
+HTML+EEX:
+ type: markup
+ tm_scope: text.html.elixir
+ group: HTML
+ aliases:
+ - eex
+ extensions:
+ - ".eex"
+ ace_mode: text
+ codemirror_mode: htmlmixed
+ codemirror_mime_type: text/html
+ language_id: 149
+HTML+ERB:
+ type: markup
+ tm_scope: text.html.erb
+ group: HTML
+ aliases:
+ - erb
+ extensions:
+ - ".erb"
+ - ".erb.deface"
+ ace_mode: text
+ codemirror_mode: htmlembedded
+ codemirror_mime_type: application/x-erb
+ language_id: 150
+HTML+PHP:
+ type: markup
+ tm_scope: text.html.php
+ group: HTML
+ extensions:
+ - ".phtml"
+ ace_mode: php
+ codemirror_mode: php
+ codemirror_mime_type: application/x-httpd-php
+ language_id: 151
+HTTP:
+ type: data
+ extensions:
+ - ".http"
+ tm_scope: source.httpspec
+ ace_mode: text
+ codemirror_mode: http
+ codemirror_mime_type: message/http
+ language_id: 152
+HXML:
+ type: data
+ ace_mode: text
+ extensions:
+ - ".hxml"
+ tm_scope: source.hxml
+ language_id: 786683730
+Hack:
+ type: programming
+ ace_mode: php
+ codemirror_mode: php
+ codemirror_mime_type: application/x-httpd-php
+ extensions:
+ - ".hh"
+ - ".php"
+ tm_scope: text.html.php
+ color: "#878787"
+ language_id: 153
+Haml:
+ group: HTML
+ type: markup
+ extensions:
+ - ".haml"
+ - ".haml.deface"
+ ace_mode: haml
+ codemirror_mode: haml
+ codemirror_mime_type: text/x-haml
+ language_id: 154
+Handlebars:
+ type: markup
+ group: HTML
+ aliases:
+ - hbs
+ - htmlbars
+ extensions:
+ - ".handlebars"
+ - ".hbs"
+ tm_scope: text.html.handlebars
+ ace_mode: handlebars
+ language_id: 155
+Harbour:
+ type: programming
+ color: "#0e60e3"
+ extensions:
+ - ".hb"
+ tm_scope: source.harbour
+ ace_mode: text
+ language_id: 156
+Haskell:
+ type: programming
+ color: "#5e5086"
+ extensions:
+ - ".hs"
+ - ".hsc"
+ interpreters:
+ - runhaskell
+ ace_mode: haskell
+ codemirror_mode: haskell
+ codemirror_mime_type: text/x-haskell
+ language_id: 157
+Haxe:
+ type: programming
+ ace_mode: haxe
+ codemirror_mode: haxe
+ codemirror_mime_type: text/x-haxe
+ color: "#df7900"
+ extensions:
+ - ".hx"
+ - ".hxsl"
+ tm_scope: source.hx
+ language_id: 158
+HiveQL:
+ type: programming
+ extensions:
+ - ".q"
+ color: "#dce200"
+ tm_scope: source.hql
+ ace_mode: sql
+ language_id: 931814087
+Hy:
+ type: programming
+ ace_mode: text
+ color: "#7790B2"
+ extensions:
+ - ".hy"
+ interpreters:
+ - "hy"
+ aliases:
+ - hylang
+ tm_scope: none
+ language_id: 159
+HyPhy:
+ type: programming
+ ace_mode: text
+ extensions:
+ - ".bf"
+ tm_scope: none
+ language_id: 160
+IDL:
+ type: programming
+ color: "#a3522f"
+ extensions:
+ - ".pro"
+ - ".dlm"
+ ace_mode: text
+ codemirror_mode: idl
+ codemirror_mime_type: text/x-idl
+ language_id: 161
+IGOR Pro:
+ type: programming
+ extensions:
+ - ".ipf"
+ aliases:
+ - igor
+ - igorpro
+ tm_scope: none
+ ace_mode: text
+ language_id: 162
+INI:
+ type: data
+ extensions:
+ - ".ini"
+ - ".cfg"
+ - ".prefs"
+ - ".pro"
+ - ".properties"
+ filenames:
+ - ".editorconfig"
+ - ".gitconfig"
+ - buildozer.spec
+ tm_scope: source.ini
+ aliases:
+ - dosini
+ ace_mode: ini
+ codemirror_mode: properties
+ codemirror_mime_type: text/x-properties
+ language_id: 163
+IRC log:
+ type: data
+ aliases:
+ - irc
+ - irc logs
+ extensions:
+ - ".irclog"
+ - ".weechatlog"
+ tm_scope: none
+ ace_mode: text
+ codemirror_mode: mirc
+ codemirror_mime_type: text/mirc
+ language_id: 164
+Idris:
+ type: programming
+ color: "#b30000"
+ extensions:
+ - ".idr"
+ - ".lidr"
+ ace_mode: text
+ tm_scope: source.idris
+ language_id: 165
+Inform 7:
+ type: programming
+ wrap: true
+ extensions:
+ - ".ni"
+ - ".i7x"
+ tm_scope: source.inform7
+ aliases:
+ - i7
+ - inform7
+ ace_mode: text
+ language_id: 166
+Inno Setup:
+ type: programming
+ extensions:
+ - ".iss"
+ tm_scope: none
+ ace_mode: text
+ language_id: 167
+Io:
+ type: programming
+ color: "#a9188d"
+ extensions:
+ - ".io"
+ interpreters:
+ - io
+ ace_mode: io
+ language_id: 168
+Ioke:
+ type: programming
+ color: "#078193"
+ extensions:
+ - ".ik"
+ interpreters:
+ - ioke
+ ace_mode: text
+ language_id: 169
+Isabelle:
+ type: programming
+ color: "#FEFE00"
+ extensions:
+ - ".thy"
+ tm_scope: source.isabelle.theory
+ ace_mode: text
+ language_id: 170
+Isabelle ROOT:
+ type: programming
+ group: Isabelle
+ filenames:
+ - ROOT
+ tm_scope: source.isabelle.root
+ ace_mode: text
+ language_id: 171
+J:
+ type: programming
+ color: "#9EEDFF"
+ extensions:
+ - ".ijs"
+ interpreters:
+ - jconsole
+ tm_scope: source.j
+ ace_mode: text
+ language_id: 172
+JFlex:
+ type: programming
+ group: Lex
+ extensions:
+ - ".flex"
+ - ".jflex"
+ tm_scope: source.jflex
+ ace_mode: text
+ language_id: 173
+JSON:
+ type: data
+ tm_scope: source.json
+ group: JavaScript
+ ace_mode: json
+ codemirror_mode: javascript
+ codemirror_mime_type: application/json
+ searchable: false
+ extensions:
+ - ".json"
+ - ".avsc"
+ - ".geojson"
+ - ".gltf"
+ - ".JSON-tmLanguage"
+ - ".jsonl"
+ - ".tfstate"
+ - ".tfstate.backup"
+ - ".topojson"
+ - ".webapp"
+ - ".webmanifest"
+ filenames:
+ - ".arcconfig"
+ - ".htmlhintrc"
+ - ".tern-config"
+ - ".tern-project"
+ - composer.lock
+ - mcmod.info
+ language_id: 174
+JSON with Comments:
+ type: data
+ group: JSON
+ tm_scope: source.js
+ ace_mode: javascript
+ codemirror_mode: javascript
+ codemirror_mime_type: text/javascript
+ aliases:
+ - jsonc
+ extensions:
+ - ".sublime-build"
+ - ".sublime-commands"
+ - ".sublime-completions"
+ - ".sublime-keymap"
+ - ".sublime-macro"
+ - ".sublime-menu"
+ - ".sublime-mousemap"
+ - ".sublime-project"
+ - ".sublime-settings"
+ - ".sublime-theme"
+ - ".sublime-workspace"
+ - ".sublime_metrics"
+ - ".sublime_session"
+ filenames:
+ - ".babelrc"
+ - ".eslintrc.json"
+ - ".jscsrc"
+ - ".jshintrc"
+ - ".jslintrc"
+ - tsconfig.json
+ language_id: 423
+JSON5:
+ type: data
+ extensions:
+ - ".json5"
+ tm_scope: source.js
+ ace_mode: javascript
+ codemirror_mode: javascript
+ codemirror_mime_type: application/json
+ language_id: 175
+JSONLD:
+ type: data
+ group: JavaScript
+ ace_mode: javascript
+ extensions:
+ - ".jsonld"
+ tm_scope: source.js
+ language_id: 176
+JSONiq:
+ color: "#40d47e"
+ type: programming
+ ace_mode: jsoniq
+ codemirror_mode: javascript
+ codemirror_mime_type: application/json
+ extensions:
+ - ".jq"
+ tm_scope: source.jq
+ language_id: 177
+JSX:
+ type: programming
+ group: JavaScript
+ extensions:
+ - ".jsx"
+ tm_scope: source.js.jsx
+ ace_mode: javascript
+ codemirror_mode: jsx
+ codemirror_mime_type: text/jsx
+ language_id: 178
+Jasmin:
+ type: programming
+ ace_mode: java
+ extensions:
+ - ".j"
+ tm_scope: source.jasmin
+ language_id: 180
+Java:
+ type: programming
+ ace_mode: java
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-java
+ color: "#b07219"
+ extensions:
+ - ".java"
+ language_id: 181
+Java Server Pages:
+ type: programming
+ group: Java
+ aliases:
+ - jsp
+ extensions:
+ - ".jsp"
+ tm_scope: text.html.jsp
+ ace_mode: jsp
+ codemirror_mode: htmlembedded
+ codemirror_mime_type: application/x-jsp
+ language_id: 182
+JavaScript:
+ type: programming
+ tm_scope: source.js
+ ace_mode: javascript
+ codemirror_mode: javascript
+ codemirror_mime_type: text/javascript
+ color: "#f1e05a"
+ aliases:
+ - js
+ - node
+ extensions:
+ - ".js"
+ - "._js"
+ - ".bones"
+ - ".es"
+ - ".es6"
+ - ".frag"
+ - ".gs"
+ - ".jake"
+ - ".jsb"
+ - ".jscad"
+ - ".jsfl"
+ - ".jsm"
+ - ".jss"
+ - ".mjs"
+ - ".njs"
+ - ".pac"
+ - ".sjs"
+ - ".ssjs"
+ - ".xsjs"
+ - ".xsjslib"
+ filenames:
+ - Jakefile
+ interpreters:
+ - node
+ language_id: 183
+Jison:
+ type: programming
+ group: Yacc
+ extensions:
+ - ".jison"
+ tm_scope: source.jison
+ ace_mode: text
+ language_id: 284531423
+Jison Lex:
+ type: programming
+ group: Lex
+ extensions:
+ - ".jisonlex"
+ tm_scope: source.jisonlex
+ ace_mode: text
+ language_id: 406395330
+Jolie:
+ type: programming
+ extensions:
+ - ".ol"
+ - ".iol"
+ interpreters:
+ - jolie
+ color: "#843179"
+ ace_mode: text
+ tm_scope: source.jolie
+ language_id: 998078858
+Julia:
+ type: programming
+ extensions:
+ - ".jl"
+ interpreters:
+ - julia
+ color: "#a270ba"
+ ace_mode: julia
+ codemirror_mode: julia
+ codemirror_mime_type: text/x-julia
+ language_id: 184
+Jupyter Notebook:
+ type: markup
+ ace_mode: json
+ codemirror_mode: javascript
+ codemirror_mime_type: application/json
+ tm_scope: source.json
+ color: "#DA5B0B"
+ extensions:
+ - ".ipynb"
+ filenames:
+ - Notebook
+ aliases:
+ - IPython Notebook
+ language_id: 185
+KRL:
+ type: programming
+ color: "#28430A"
+ extensions:
+ - ".krl"
+ tm_scope: none
+ ace_mode: text
+ language_id: 186
+KiCad Layout:
+ type: data
+ aliases:
+ - pcbnew
+ extensions:
+ - ".kicad_pcb"
+ - ".kicad_mod"
+ - ".kicad_wks"
+ filenames:
+ - fp-lib-table
+ tm_scope: source.pcb.sexp
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ language_id: 187
+KiCad Legacy Layout:
+ type: data
+ extensions:
+ - ".brd"
+ tm_scope: source.pcb.board
+ ace_mode: text
+ language_id: 140848857
+KiCad Schematic:
+ type: data
+ aliases:
+ - eeschema schematic
+ extensions:
+ - ".sch"
+ tm_scope: source.pcb.schematic
+ ace_mode: text
+ language_id: 622447435
+Kit:
+ type: markup
+ ace_mode: html
+ codemirror_mode: htmlmixed
+ codemirror_mime_type: text/html
+ extensions:
+ - ".kit"
+ tm_scope: text.html.basic
+ language_id: 188
+Kotlin:
+ type: programming
+ color: "#F18E33"
+ extensions:
+ - ".kt"
+ - ".ktm"
+ - ".kts"
+ tm_scope: source.kotlin
+ ace_mode: text
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-kotlin
+ language_id: 189
+LFE:
+ type: programming
+ color: "#4C3023"
+ extensions:
+ - ".lfe"
+ tm_scope: source.lisp
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ language_id: 190
+LLVM:
+ type: programming
+ extensions:
+ - ".ll"
+ ace_mode: text
+ color: "#185619"
+ language_id: 191
+LOLCODE:
+ type: programming
+ extensions:
+ - ".lol"
+ color: "#cc9900"
+ tm_scope: none
+ ace_mode: text
+ language_id: 192
+LSL:
+ type: programming
+ ace_mode: lsl
+ extensions:
+ - ".lsl"
+ - ".lslp"
+ interpreters:
+ - lsl
+ color: "#3d9970"
+ language_id: 193
+LabVIEW:
+ type: programming
+ extensions:
+ - ".lvproj"
+ tm_scope: text.xml
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ language_id: 194
+Lasso:
+ type: programming
+ color: "#999999"
+ extensions:
+ - ".lasso"
+ - ".las"
+ - ".lasso8"
+ - ".lasso9"
+ - ".ldml"
+ tm_scope: file.lasso
+ aliases:
+ - lassoscript
+ ace_mode: text
+ language_id: 195
+Latte:
+ type: markup
+ group: HTML
+ extensions:
+ - ".latte"
+ tm_scope: text.html.smarty
+ ace_mode: smarty
+ codemirror_mode: smarty
+ codemirror_mime_type: text/x-smarty
+ language_id: 196
+Lean:
+ type: programming
+ extensions:
+ - ".lean"
+ - ".hlean"
+ ace_mode: text
+ language_id: 197
+Less:
+ type: markup
+ group: CSS
+ extensions:
+ - ".less"
+ tm_scope: source.css.less
+ ace_mode: less
+ codemirror_mode: css
+ codemirror_mime_type: text/css
+ language_id: 198
+Lex:
+ type: programming
+ color: "#DBCA00"
+ aliases:
+ - flex
+ extensions:
+ - ".l"
+ - ".lex"
+ tm_scope: none
+ ace_mode: text
+ language_id: 199
+LilyPond:
+ type: programming
+ extensions:
+ - ".ly"
+ - ".ily"
+ ace_mode: text
+ language_id: 200
+Limbo:
+ type: programming
+ extensions:
+ - ".b"
+ - ".m"
+ tm_scope: none
+ ace_mode: text
+ language_id: 201
+Linker Script:
+ type: data
+ extensions:
+ - ".ld"
+ - ".lds"
+ - ".x"
+ filenames:
+ - ld.script
+ tm_scope: none
+ ace_mode: text
+ language_id: 202
+Linux Kernel Module:
+ type: data
+ extensions:
+ - ".mod"
+ tm_scope: none
+ ace_mode: text
+ language_id: 203
+Liquid:
+ type: markup
+ extensions:
+ - ".liquid"
+ tm_scope: text.html.liquid
+ ace_mode: liquid
+ language_id: 204
+Literate Agda:
+ type: programming
+ group: Agda
+ extensions:
+ - ".lagda"
+ tm_scope: none
+ ace_mode: text
+ language_id: 205
+Literate CoffeeScript:
+ type: programming
+ tm_scope: source.litcoffee
+ group: CoffeeScript
+ ace_mode: text
+ wrap: true
+ aliases:
+ - litcoffee
+ extensions:
+ - ".litcoffee"
+ language_id: 206
+Literate Haskell:
+ type: programming
+ group: Haskell
+ aliases:
+ - lhaskell
+ - lhs
+ extensions:
+ - ".lhs"
+ tm_scope: text.tex.latex.haskell
+ ace_mode: text
+ codemirror_mode: haskell-literate
+ codemirror_mime_type: text/x-literate-haskell
+ language_id: 207
+LiveScript:
+ type: programming
+ color: "#499886"
+ aliases:
+ - live-script
+ - ls
+ extensions:
+ - ".ls"
+ - "._ls"
+ filenames:
+ - Slakefile
+ ace_mode: livescript
+ codemirror_mode: livescript
+ codemirror_mime_type: text/x-livescript
+ language_id: 208
+Logos:
+ type: programming
+ extensions:
+ - ".xm"
+ - ".x"
+ - ".xi"
+ ace_mode: text
+ tm_scope: source.logos
+ language_id: 209
+Logtalk:
+ type: programming
+ extensions:
+ - ".lgt"
+ - ".logtalk"
+ ace_mode: text
+ language_id: 210
+LookML:
+ type: programming
+ ace_mode: yaml
+ codemirror_mode: yaml
+ codemirror_mime_type: text/x-yaml
+ color: "#652B81"
+ extensions:
+ - ".lookml"
+ - ".model.lkml"
+ - ".view.lkml"
+ tm_scope: source.yaml
+ language_id: 211
+LoomScript:
+ type: programming
+ extensions:
+ - ".ls"
+ tm_scope: source.loomscript
+ ace_mode: text
+ language_id: 212
+Lua:
+ type: programming
+ ace_mode: lua
+ codemirror_mode: lua
+ codemirror_mime_type: text/x-lua
+ color: "#000080"
+ extensions:
+ - ".lua"
+ - ".fcgi"
+ - ".nse"
+ - ".p8"
+ - ".pd_lua"
+ - ".rbxs"
+ - ".wlua"
+ interpreters:
+ - lua
+ language_id: 213
+M:
+ type: programming
+ aliases:
+ - mumps
+ extensions:
+ - ".mumps"
+ - ".m"
+ ace_mode: text
+ codemirror_mode: mumps
+ codemirror_mime_type: text/x-mumps
+ language_id: 214
+ tm_scope: none
+M4:
+ type: programming
+ extensions:
+ - ".m4"
+ tm_scope: none
+ ace_mode: text
+ language_id: 215
+M4Sugar:
+ type: programming
+ group: M4
+ aliases:
+ - autoconf
+ extensions:
+ - ".m4"
+ filenames:
+ - configure.ac
+ tm_scope: none
+ ace_mode: text
+ language_id: 216
+MAXScript:
+ type: programming
+ color: "#00a6a6"
+ extensions:
+ - ".ms"
+ - ".mcr"
+ tm_scope: source.maxscript
+ ace_mode: text
+ language_id: 217
+MQL4:
+ type: programming
+ color: "#62A8D6"
+ extensions:
+ - ".mq4"
+ - ".mqh"
+ tm_scope: source.mql5
+ ace_mode: c_cpp
+ language_id: 426
+MQL5:
+ type: programming
+ color: "#4A76B8"
+ extensions:
+ - ".mq5"
+ - ".mqh"
+ tm_scope: source.mql5
+ ace_mode: c_cpp
+ language_id: 427
+MTML:
+ type: markup
+ color: "#b7e1f4"
+ extensions:
+ - ".mtml"
+ tm_scope: text.html.basic
+ ace_mode: html
+ codemirror_mode: htmlmixed
+ codemirror_mime_type: text/html
+ language_id: 218
+MUF:
+ type: programming
+ group: Forth
+ extensions:
+ - ".muf"
+ - ".m"
+ tm_scope: none
+ ace_mode: forth
+ codemirror_mode: forth
+ codemirror_mime_type: text/x-forth
+ language_id: 219
+Makefile:
+ type: programming
+ color: "#427819"
+ aliases:
+ - bsdmake
+ - make
+ - mf
+ extensions:
+ - ".mak"
+ - ".d"
+ - ".make"
+ - ".mk"
+ - ".mkfile"
+ filenames:
+ - BSDmakefile
+ - GNUmakefile
+ - Kbuild
+ - Makefile
+ - Makefile.am
+ - Makefile.boot
+ - Makefile.frag
+ - Makefile.in
+ - Makefile.inc
+ - Makefile.wat
+ - makefile
+ - makefile.sco
+ - mkfile
+ interpreters:
+ - make
+ ace_mode: makefile
+ codemirror_mode: cmake
+ codemirror_mime_type: text/x-cmake
+ language_id: 220
+Mako:
+ type: programming
+ extensions:
+ - ".mako"
+ - ".mao"
+ tm_scope: text.html.mako
+ ace_mode: text
+ language_id: 221
+Markdown:
+ type: prose
+ aliases:
+ - pandoc
+ ace_mode: markdown
+ codemirror_mode: gfm
+ codemirror_mime_type: text/x-gfm
+ wrap: true
+ extensions:
+ - ".md"
+ - ".markdown"
+ - ".mdown"
+ - ".mdwn"
+ - ".mkd"
+ - ".mkdn"
+ - ".mkdown"
+ - ".ronn"
+ - ".workbook"
+ tm_scope: source.gfm
+ language_id: 222
+Marko:
+ group: HTML
+ type: markup
+ tm_scope: text.marko
+ extensions:
+ - ".marko"
+ aliases:
+ - markojs
+ ace_mode: text
+ codemirror_mode: htmlmixed
+ codemirror_mime_type: text/html
+ language_id: 932782397
+Mask:
+ type: markup
+ color: "#f97732"
+ ace_mode: mask
+ extensions:
+ - ".mask"
+ tm_scope: source.mask
+ language_id: 223
+Mathematica:
+ type: programming
+ extensions:
+ - ".mathematica"
+ - ".cdf"
+ - ".m"
+ - ".ma"
+ - ".mt"
+ - ".nb"
+ - ".nbp"
+ - ".wl"
+ - ".wlt"
+ aliases:
+ - mma
+ ace_mode: text
+ codemirror_mode: mathematica
+ codemirror_mime_type: text/x-mathematica
+ language_id: 224
+Matlab:
+ type: programming
+ color: "#e16737"
+ aliases:
+ - octave
+ extensions:
+ - ".matlab"
+ - ".m"
+ ace_mode: matlab
+ codemirror_mode: octave
+ codemirror_mime_type: text/x-octave
+ language_id: 225
+Maven POM:
+ type: data
+ tm_scope: text.xml.pom
+ filenames:
+ - pom.xml
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ language_id: 226
+Max:
+ type: programming
+ color: "#c4a79c"
+ aliases:
+ - max/msp
+ - maxmsp
+ extensions:
+ - ".maxpat"
+ - ".maxhelp"
+ - ".maxproj"
+ - ".mxt"
+ - ".pat"
+ tm_scope: source.json
+ ace_mode: json
+ codemirror_mode: javascript
+ codemirror_mime_type: application/json
+ language_id: 227
+MediaWiki:
+ type: prose
+ wrap: true
+ extensions:
+ - ".mediawiki"
+ - ".wiki"
+ tm_scope: text.html.mediawiki
+ ace_mode: text
+ language_id: 228
+Mercury:
+ type: programming
+ color: "#ff2b2b"
+ ace_mode: prolog
+ interpreters:
+ - mmi
+ extensions:
+ - ".m"
+ - ".moo"
+ tm_scope: source.mercury
+ language_id: 229
+Meson:
+ type: programming
+ color: "#007800"
+ filenames:
+ - meson.build
+ - meson_options.txt
+ tm_scope: source.meson
+ ace_mode: text
+ language_id: 799141244
+Metal:
+ type: programming
+ color: "#8f14e9"
+ extensions:
+ - ".metal"
+ tm_scope: source.c++
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-c++src
+ language_id: 230
+MiniD:
+ type: programming
+ searchable: false
+ extensions:
+ - ".minid"
+ tm_scope: none
+ ace_mode: text
+ language_id: 231
+Mirah:
+ type: programming
+ color: "#c7a938"
+ extensions:
+ - ".druby"
+ - ".duby"
+ - ".mirah"
+ tm_scope: source.ruby
+ ace_mode: ruby
+ codemirror_mode: ruby
+ codemirror_mime_type: text/x-ruby
+ language_id: 232
+Modelica:
+ type: programming
+ extensions:
+ - ".mo"
+ tm_scope: source.modelica
+ ace_mode: text
+ codemirror_mode: modelica
+ codemirror_mime_type: text/x-modelica
+ language_id: 233
+Modula-2:
+ type: programming
+ extensions:
+ - ".mod"
+ tm_scope: source.modula2
+ ace_mode: text
+ language_id: 234
+Modula-3:
+ type: programming
+ extensions:
+ - ".i3"
+ - ".ig"
+ - ".m3"
+ - ".mg"
+ color: "#223388"
+ ace_mode: text
+ tm_scope: source.modula-3
+ language_id: 564743864
+Module Management System:
+ type: programming
+ extensions:
+ - ".mms"
+ - ".mmk"
+ filenames:
+ - descrip.mmk
+ - descrip.mms
+ tm_scope: none
+ ace_mode: text
+ language_id: 235
+Monkey:
+ type: programming
+ extensions:
+ - ".monkey"
+ - ".monkey2"
+ ace_mode: text
+ tm_scope: source.monkey
+ language_id: 236
+Moocode:
+ type: programming
+ extensions:
+ - ".moo"
+ tm_scope: none
+ ace_mode: text
+ language_id: 237
+MoonScript:
+ type: programming
+ extensions:
+ - ".moon"
+ interpreters:
+ - moon
+ ace_mode: text
+ language_id: 238
+Myghty:
+ type: programming
+ extensions:
+ - ".myt"
+ tm_scope: none
+ ace_mode: text
+ language_id: 239
+NCL:
+ type: programming
+ color: "#28431f"
+ extensions:
+ - ".ncl"
+ tm_scope: source.ncl
+ ace_mode: text
+ language_id: 240
+NL:
+ type: data
+ extensions:
+ - ".nl"
+ tm_scope: none
+ ace_mode: text
+ language_id: 241
+NSIS:
+ type: programming
+ extensions:
+ - ".nsi"
+ - ".nsh"
+ ace_mode: text
+ codemirror_mode: nsis
+ codemirror_mime_type: text/x-nsis
+ language_id: 242
+Nearley:
+ type: programming
+ ace_mode: text
+ color: "#990000"
+ extensions:
+ - ".ne"
+ - ".nearley"
+ tm_scope: source.ne
+ language_id: 521429430
+Nemerle:
+ type: programming
+ color: "#3d3c6e"
+ extensions:
+ - ".n"
+ ace_mode: text
+ language_id: 243
+NetLinx:
+ type: programming
+ color: "#0aa0ff"
+ extensions:
+ - ".axs"
+ - ".axi"
+ tm_scope: source.netlinx
+ ace_mode: text
+ language_id: 244
+NetLinx+ERB:
+ type: programming
+ color: "#747faa"
+ extensions:
+ - ".axs.erb"
+ - ".axi.erb"
+ tm_scope: source.netlinx.erb
+ ace_mode: text
+ language_id: 245
+NetLogo:
+ type: programming
+ color: "#ff6375"
+ extensions:
+ - ".nlogo"
+ tm_scope: source.lisp
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ language_id: 246
+NewLisp:
+ type: programming
+ color: "#87AED7"
+ extensions:
+ - ".nl"
+ - ".lisp"
+ - ".lsp"
+ interpreters:
+ - newlisp
+ tm_scope: source.lisp
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ language_id: 247
+Nextflow:
+ type: programming
+ ace_mode: groovy
+ tm_scope: source.nextflow
+ color: "#3ac486"
+ extensions:
+ - ".nf"
+ filenames:
+ - nextflow.config
+ interpreters:
+ - nextflow
+ language_id: 506780613
+Nginx:
+ type: data
+ extensions:
+ - ".nginxconf"
+ - ".vhost"
+ filenames:
+ - nginx.conf
+ tm_scope: source.nginx
+ aliases:
+ - nginx configuration file
+ ace_mode: text
+ codemirror_mode: nginx
+ codemirror_mime_type: text/x-nginx-conf
+ language_id: 248
+Nim:
+ type: programming
+ color: "#37775b"
+ extensions:
+ - ".nim"
+ - ".nimrod"
+ ace_mode: text
+ tm_scope: source.nim
+ language_id: 249
+Ninja:
+ type: data
+ tm_scope: source.ninja
+ extensions:
+ - ".ninja"
+ ace_mode: text
+ language_id: 250
+Nit:
+ type: programming
+ color: "#009917"
+ extensions:
+ - ".nit"
+ tm_scope: source.nit
+ ace_mode: text
+ language_id: 251
+Nix:
+ type: programming
+ color: "#7e7eff"
+ extensions:
+ - ".nix"
+ aliases:
+ - nixos
+ tm_scope: source.nix
+ ace_mode: nix
+ language_id: 252
+Nu:
+ type: programming
+ color: "#c9df40"
+ aliases:
+ - nush
+ extensions:
+ - ".nu"
+ filenames:
+ - Nukefile
+ tm_scope: source.nu
+ ace_mode: scheme
+ codemirror_mode: scheme
+ codemirror_mime_type: text/x-scheme
+ interpreters:
+ - nush
+ language_id: 253
+NumPy:
+ type: programming
+ group: Python
+ extensions:
+ - ".numpy"
+ - ".numpyw"
+ - ".numsc"
+ tm_scope: none
+ ace_mode: text
+ codemirror_mode: python
+ codemirror_mime_type: text/x-python
+ language_id: 254
+OCaml:
+ type: programming
+ ace_mode: ocaml
+ codemirror_mode: mllike
+ codemirror_mime_type: text/x-ocaml
+ color: "#3be133"
+ extensions:
+ - ".ml"
+ - ".eliom"
+ - ".eliomi"
+ - ".ml4"
+ - ".mli"
+ - ".mll"
+ - ".mly"
+ interpreters:
+ - ocaml
+ - ocamlrun
+ - ocamlscript
+ tm_scope: source.ocaml
+ language_id: 255
+ObjDump:
+ type: data
+ extensions:
+ - ".objdump"
+ tm_scope: objdump.x86asm
+ ace_mode: assembly_x86
+ language_id: 256
+Objective-C:
+ type: programming
+ tm_scope: source.objc
+ color: "#438eff"
+ aliases:
+ - obj-c
+ - objc
+ - objectivec
+ extensions:
+ - ".m"
+ - ".h"
+ ace_mode: objectivec
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-objectivec
+ language_id: 257
+Objective-C++:
+ type: programming
+ tm_scope: source.objc++
+ color: "#6866fb"
+ aliases:
+ - obj-c++
+ - objc++
+ - objectivec++
+ extensions:
+ - ".mm"
+ ace_mode: objectivec
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-objectivec
+ language_id: 258
+Objective-J:
+ type: programming
+ color: "#ff0c5a"
+ aliases:
+ - obj-j
+ - objectivej
+ - objj
+ extensions:
+ - ".j"
+ - ".sj"
+ tm_scope: source.js.objj
+ ace_mode: text
+ language_id: 259
+Omgrofl:
+ type: programming
+ extensions:
+ - ".omgrofl"
+ color: "#cabbff"
+ tm_scope: none
+ ace_mode: text
+ language_id: 260
+Opa:
+ type: programming
+ extensions:
+ - ".opa"
+ ace_mode: text
+ language_id: 261
+Opal:
+ type: programming
+ color: "#f7ede0"
+ extensions:
+ - ".opal"
+ tm_scope: source.opal
+ ace_mode: text
+ language_id: 262
+OpenCL:
+ type: programming
+ group: C
+ extensions:
+ - ".cl"
+ - ".opencl"
+ tm_scope: source.c
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csrc
+ language_id: 263
+OpenEdge ABL:
+ type: programming
+ aliases:
+ - progress
+ - openedge
+ - abl
+ extensions:
+ - ".p"
+ - ".cls"
+ - ".w"
+ tm_scope: source.abl
+ ace_mode: text
+ language_id: 264
+OpenRC runscript:
+ type: programming
+ group: Shell
+ aliases:
+ - openrc
+ interpreters:
+ - openrc-run
+ tm_scope: source.shell
+ ace_mode: sh
+ codemirror_mode: shell
+ codemirror_mime_type: text/x-sh
+ language_id: 265
+OpenSCAD:
+ type: programming
+ extensions:
+ - ".scad"
+ tm_scope: source.scad
+ ace_mode: scad
+ language_id: 266
+OpenType Feature File:
+ type: data
+ aliases:
+ - AFDKO
+ extensions:
+ - ".fea"
+ tm_scope: source.opentype
+ ace_mode: text
+ language_id: 374317347
+Org:
+ type: prose
+ wrap: true
+ extensions:
+ - ".org"
+ tm_scope: none
+ ace_mode: text
+ language_id: 267
+Ox:
+ type: programming
+ extensions:
+ - ".ox"
+ - ".oxh"
+ - ".oxo"
+ tm_scope: source.ox
+ ace_mode: text
+ language_id: 268
+Oxygene:
+ type: programming
+ color: "#cdd0e3"
+ extensions:
+ - ".oxygene"
+ tm_scope: none
+ ace_mode: text
+ language_id: 269
+Oz:
+ type: programming
+ color: "#fab738"
+ extensions:
+ - ".oz"
+ tm_scope: source.oz
+ ace_mode: text
+ codemirror_mode: oz
+ codemirror_mime_type: text/x-oz
+ language_id: 270
+P4:
+ type: programming
+ color: "#7055b5"
+ extensions:
+ - ".p4"
+ tm_scope: source.p4
+ ace_mode: text
+ language_id: 348895984
+PAWN:
+ type: programming
+ color: "#dbb284"
+ extensions:
+ - ".pwn"
+ - ".inc"
+ tm_scope: source.pawn
+ ace_mode: text
+ language_id: 271
+PHP:
+ type: programming
+ tm_scope: text.html.php
+ ace_mode: php
+ codemirror_mode: php
+ codemirror_mime_type: application/x-httpd-php
+ color: "#4F5D95"
+ extensions:
+ - ".php"
+ - ".aw"
+ - ".ctp"
+ - ".fcgi"
+ - ".inc"
+ - ".php3"
+ - ".php4"
+ - ".php5"
+ - ".phps"
+ - ".phpt"
+ filenames:
+ - ".php"
+ - ".php_cs"
+ - ".php_cs.dist"
+ - Phakefile
+ interpreters:
+ - php
+ aliases:
+ - inc
+ language_id: 272
+PLSQL:
+ type: programming
+ ace_mode: sql
+ codemirror_mode: sql
+ codemirror_mime_type: text/x-plsql
+ tm_scope: none
+ color: "#dad8d8"
+ extensions:
+ - ".pls"
+ - ".bdy"
+ - ".ddl"
+ - ".fnc"
+ - ".pck"
+ - ".pkb"
+ - ".pks"
+ - ".plb"
+ - ".plsql"
+ - ".prc"
+ - ".spc"
+ - ".sql"
+ - ".tpb"
+ - ".tps"
+ - ".trg"
+ - ".vw"
+ language_id: 273
+PLpgSQL:
+ type: programming
+ ace_mode: pgsql
+ codemirror_mode: sql
+ codemirror_mime_type: text/x-sql
+ tm_scope: source.sql
+ extensions:
+ - ".sql"
+ language_id: 274
+POV-Ray SDL:
+ type: programming
+ aliases:
+ - pov-ray
+ - povray
+ extensions:
+ - ".pov"
+ - ".inc"
+ ace_mode: text
+ language_id: 275
+Pan:
+ type: programming
+ color: "#cc0000"
+ extensions:
+ - ".pan"
+ tm_scope: source.pan
+ ace_mode: text
+ language_id: 276
+Papyrus:
+ type: programming
+ color: "#6600cc"
+ extensions:
+ - ".psc"
+ tm_scope: source.papyrus.skyrim
+ ace_mode: text
+ language_id: 277
+Parrot:
+ type: programming
+ color: "#f3ca0a"
+ extensions:
+ - ".parrot"
+ tm_scope: none
+ ace_mode: text
+ language_id: 278
+Parrot Assembly:
+ group: Parrot
+ type: programming
+ aliases:
+ - pasm
+ extensions:
+ - ".pasm"
+ interpreters:
+ - parrot
+ tm_scope: none
+ ace_mode: text
+ language_id: 279
+Parrot Internal Representation:
+ group: Parrot
+ tm_scope: source.parrot.pir
+ type: programming
+ aliases:
+ - pir
+ extensions:
+ - ".pir"
+ interpreters:
+ - parrot
+ ace_mode: text
+ language_id: 280
+Pascal:
+ type: programming
+ color: "#E3F171"
+ extensions:
+ - ".pas"
+ - ".dfm"
+ - ".dpr"
+ - ".inc"
+ - ".lpr"
+ - ".pascal"
+ - ".pp"
+ interpreters:
+ - instantfpc
+ ace_mode: pascal
+ codemirror_mode: pascal
+ codemirror_mime_type: text/x-pascal
+ language_id: 281
+Pep8:
+ type: programming
+ color: "#C76F5B"
+ extensions:
+ - ".pep"
+ ace_mode: text
+ tm_scope: source.pep8
+ language_id: 840372442
+Perl:
+ type: programming
+ tm_scope: source.perl
+ ace_mode: perl
+ codemirror_mode: perl
+ codemirror_mime_type: text/x-perl
+ color: "#0298c3"
+ extensions:
+ - ".pl"
+ - ".al"
+ - ".cgi"
+ - ".fcgi"
+ - ".perl"
+ - ".ph"
+ - ".plx"
+ - ".pm"
+ - ".psgi"
+ - ".t"
+ filenames:
+ - Makefile.PL
+ - Rexfile
+ - ack
+ - cpanfile
+ interpreters:
+ - cperl
+ - perl
+ aliases:
+ - cperl
+ language_id: 282
+Perl 6:
+ type: programming
+ color: "#0000fb"
+ extensions:
+ - ".6pl"
+ - ".6pm"
+ - ".nqp"
+ - ".p6"
+ - ".p6l"
+ - ".p6m"
+ - ".pl"
+ - ".pl6"
+ - ".pm"
+ - ".pm6"
+ - ".t"
+ interpreters:
+ - perl6
+ aliases:
+ - perl6
+ tm_scope: source.perl6fe
+ ace_mode: perl
+ codemirror_mode: perl
+ codemirror_mime_type: text/x-perl
+ language_id: 283
+Pic:
+ type: markup
+ group: Roff
+ tm_scope: source.pic
+ extensions:
+ - ".pic"
+ - ".chem"
+ ace_mode: text
+ codemirror_mode: troff
+ codemirror_mime_type: text/troff
+ language_id: 425
+Pickle:
+ type: data
+ extensions:
+ - ".pkl"
+ tm_scope: none
+ ace_mode: text
+ language_id: 284
+PicoLisp:
+ type: programming
+ extensions:
+ - ".l"
+ interpreters:
+ - picolisp
+ - pil
+ tm_scope: source.lisp
+ ace_mode: lisp
+ language_id: 285
+PigLatin:
+ type: programming
+ color: "#fcd7de"
+ extensions:
+ - ".pig"
+ tm_scope: source.pig_latin
+ ace_mode: text
+ language_id: 286
+Pike:
+ type: programming
+ color: "#005390"
+ extensions:
+ - ".pike"
+ - ".pmod"
+ interpreters:
+ - pike
+ ace_mode: text
+ language_id: 287
+Pod:
+ type: prose
+ ace_mode: perl
+ codemirror_mode: perl
+ codemirror_mime_type: text/x-perl
+ wrap: true
+ extensions:
+ - ".pod"
+ interpreters:
+ - perl
+ tm_scope: none
+ language_id: 288
+PogoScript:
+ type: programming
+ color: "#d80074"
+ extensions:
+ - ".pogo"
+ tm_scope: source.pogoscript
+ ace_mode: text
+ language_id: 289
+Pony:
+ type: programming
+ extensions:
+ - ".pony"
+ tm_scope: source.pony
+ ace_mode: text
+ language_id: 290
+PostCSS:
+ type: markup
+ tm_scope: source.postcss
+ group: CSS
+ extensions:
+ - ".pcss"
+ ace_mode: text
+ language_id: 262764437
+PostScript:
+ type: markup
+ color: "#da291c"
+ extensions:
+ - ".ps"
+ - ".eps"
+ - ".pfa"
+ tm_scope: source.postscript
+ aliases:
+ - postscr
+ ace_mode: text
+ language_id: 291
+PowerBuilder:
+ type: programming
+ color: "#8f0f8d"
+ extensions:
+ - ".pbt"
+ - ".sra"
+ - ".sru"
+ - ".srw"
+ tm_scope: none
+ ace_mode: text
+ language_id: 292
+PowerShell:
+ type: programming
+ color: "#012456"
+ ace_mode: powershell
+ codemirror_mode: powershell
+ codemirror_mime_type: application/x-powershell
+ aliases:
+ - posh
+ - pwsh
+ extensions:
+ - ".ps1"
+ - ".psd1"
+ - ".psm1"
+ interpreters:
+ - pwsh
+ language_id: 293
+Processing:
+ type: programming
+ color: "#0096D8"
+ extensions:
+ - ".pde"
+ ace_mode: text
+ language_id: 294
+Prolog:
+ type: programming
+ color: "#74283c"
+ extensions:
+ - ".pl"
+ - ".pro"
+ - ".prolog"
+ - ".yap"
+ interpreters:
+ - swipl
+ - yap
+ tm_scope: source.prolog
+ ace_mode: prolog
+ language_id: 295
+Propeller Spin:
+ type: programming
+ color: "#7fa2a7"
+ extensions:
+ - ".spin"
+ tm_scope: source.spin
+ ace_mode: text
+ language_id: 296
+Protocol Buffer:
+ type: data
+ aliases:
+ - protobuf
+ - Protocol Buffers
+ extensions:
+ - ".proto"
+ tm_scope: source.protobuf
+ ace_mode: protobuf
+ codemirror_mode: protobuf
+ codemirror_mime_type: text/x-protobuf
+ language_id: 297
+Public Key:
+ type: data
+ extensions:
+ - ".asc"
+ - ".pub"
+ tm_scope: none
+ ace_mode: text
+ codemirror_mode: asciiarmor
+ codemirror_mime_type: application/pgp
+ language_id: 298
+Pug:
+ group: HTML
+ type: markup
+ extensions:
+ - ".jade"
+ - ".pug"
+ tm_scope: text.jade
+ ace_mode: jade
+ codemirror_mode: pug
+ codemirror_mime_type: text/x-pug
+ language_id: 179
+Puppet:
+ type: programming
+ color: "#302B6D"
+ extensions:
+ - ".pp"
+ filenames:
+ - Modulefile
+ ace_mode: text
+ codemirror_mode: puppet
+ codemirror_mime_type: text/x-puppet
+ tm_scope: source.puppet
+ language_id: 299
+Pure Data:
+ type: data
+ extensions:
+ - ".pd"
+ tm_scope: none
+ ace_mode: text
+ language_id: 300
+PureBasic:
+ type: programming
+ color: "#5a6986"
+ extensions:
+ - ".pb"
+ - ".pbi"
+ tm_scope: none
+ ace_mode: text
+ language_id: 301
+PureScript:
+ type: programming
+ color: "#1D222D"
+ extensions:
+ - ".purs"
+ tm_scope: source.purescript
+ ace_mode: haskell
+ codemirror_mode: haskell
+ codemirror_mime_type: text/x-haskell
+ language_id: 302
+Python:
+ type: programming
+ ace_mode: python
+ codemirror_mode: python
+ codemirror_mime_type: text/x-python
+ color: "#3572A5"
+ extensions:
+ - ".py"
+ - ".bzl"
+ - ".cgi"
+ - ".fcgi"
+ - ".gyp"
+ - ".gypi"
+ - ".lmi"
+ - ".py3"
+ - ".pyde"
+ - ".pyi"
+ - ".pyp"
+ - ".pyt"
+ - ".pyw"
+ - ".rpy"
+ - ".spec"
+ - ".tac"
+ - ".wsgi"
+ - ".xpy"
+ filenames:
+ - ".gclient"
+ - BUCK
+ - BUILD
+ - BUILD.bazel
+ - SConscript
+ - SConstruct
+ - Snakefile
+ - WORKSPACE
+ - wscript
+ interpreters:
+ - python
+ - python2
+ - python3
+ aliases:
+ - rusthon
+ - python3
+ language_id: 303
+Python console:
+ type: programming
+ group: Python
+ searchable: false
+ aliases:
+ - pycon
+ tm_scope: text.python.console
+ ace_mode: text
+ language_id: 428
+Python traceback:
+ type: data
+ group: Python
+ searchable: false
+ extensions:
+ - ".pytb"
+ tm_scope: text.python.traceback
+ ace_mode: text
+ language_id: 304
+QML:
+ type: programming
+ color: "#44a51c"
+ extensions:
+ - ".qml"
+ - ".qbs"
+ tm_scope: source.qml
+ ace_mode: text
+ language_id: 305
+QMake:
+ type: programming
+ extensions:
+ - ".pro"
+ - ".pri"
+ interpreters:
+ - qmake
+ ace_mode: text
+ language_id: 306
+Quake:
+ type: programming
+ filenames:
+ - m3makefile
+ - m3overrides
+ color: "#882233"
+ ace_mode: text
+ tm_scope: source.quake
+ language_id: 375265331
+R:
+ type: programming
+ color: "#198CE7"
+ aliases:
+ - R
+ - Rscript
+ - splus
+ extensions:
+ - ".r"
+ - ".rd"
+ - ".rsx"
+ filenames:
+ - ".Rprofile"
+ - expr-dist
+ interpreters:
+ - Rscript
+ ace_mode: r
+ codemirror_mode: r
+ codemirror_mime_type: text/x-rsrc
+ language_id: 307
+RAML:
+ type: markup
+ ace_mode: yaml
+ codemirror_mode: yaml
+ codemirror_mime_type: text/x-yaml
+ tm_scope: source.yaml
+ color: "#77d9fb"
+ extensions:
+ - ".raml"
+ language_id: 308
+RDoc:
+ type: prose
+ ace_mode: rdoc
+ wrap: true
+ extensions:
+ - ".rdoc"
+ tm_scope: text.rdoc
+ language_id: 309
+REALbasic:
+ type: programming
+ extensions:
+ - ".rbbas"
+ - ".rbfrm"
+ - ".rbmnu"
+ - ".rbres"
+ - ".rbtbar"
+ - ".rbuistate"
+ tm_scope: source.vbnet
+ ace_mode: text
+ language_id: 310
+REXX:
+ type: programming
+ aliases:
+ - arexx
+ extensions:
+ - ".rexx"
+ - ".pprx"
+ - ".rex"
+ interpreters:
+ - regina
+ - rexx
+ tm_scope: source.rexx
+ ace_mode: text
+ language_id: 311
+RHTML:
+ type: markup
+ group: HTML
+ extensions:
+ - ".rhtml"
+ tm_scope: text.html.erb
+ aliases:
+ - html+ruby
+ ace_mode: rhtml
+ codemirror_mode: htmlembedded
+ codemirror_mime_type: application/x-erb
+ language_id: 312
+RMarkdown:
+ type: prose
+ wrap: true
+ ace_mode: markdown
+ codemirror_mode: gfm
+ codemirror_mime_type: text/x-gfm
+ extensions:
+ - ".rmd"
+ tm_scope: source.gfm
+ language_id: 313
+RPC:
+ type: programming
+ aliases:
+ - rpcgen
+ - oncrpc
+ - xdr
+ ace_mode: c_cpp
+ extensions:
+ - ".x"
+ tm_scope: source.c
+ language_id: 1031374237
+RPM Spec:
+ type: data
+ tm_scope: source.rpm-spec
+ extensions:
+ - ".spec"
+ aliases:
+ - specfile
+ ace_mode: text
+ codemirror_mode: rpm
+ codemirror_mime_type: text/x-rpm-spec
+ language_id: 314
+RUNOFF:
+ type: markup
+ color: "#665a4e"
+ extensions:
+ - ".rnh"
+ - ".rno"
+ tm_scope: text.runoff
+ ace_mode: text
+ language_id: 315
+Racket:
+ type: programming
+ color: "#22228f"
+ extensions:
+ - ".rkt"
+ - ".rktd"
+ - ".rktl"
+ - ".scrbl"
+ interpreters:
+ - racket
+ tm_scope: source.racket
+ ace_mode: lisp
+ language_id: 316
+Ragel:
+ type: programming
+ color: "#9d5200"
+ extensions:
+ - ".rl"
+ aliases:
+ - ragel-rb
+ - ragel-ruby
+ tm_scope: none
+ ace_mode: text
+ language_id: 317
+Rascal:
+ type: programming
+ color: "#fffaa0"
+ extensions:
+ - ".rsc"
+ tm_scope: source.rascal
+ ace_mode: text
+ language_id: 173616037
+Raw token data:
+ type: data
+ aliases:
+ - raw
+ extensions:
+ - ".raw"
+ tm_scope: none
+ ace_mode: text
+ language_id: 318
+Reason:
+ type: programming
+ group: OCaml
+ ace_mode: rust
+ codemirror_mode: rust
+ codemirror_mime_type: text/x-rustsrc
+ extensions:
+ - ".re"
+ - ".rei"
+ interpreters:
+ - ocaml
+ tm_scope: source.reason
+ language_id: 869538413
+Rebol:
+ type: programming
+ color: "#358a5b"
+ extensions:
+ - ".reb"
+ - ".r"
+ - ".r2"
+ - ".r3"
+ - ".rebol"
+ ace_mode: text
+ tm_scope: source.rebol
+ language_id: 319
+Red:
+ type: programming
+ color: "#f50000"
+ extensions:
+ - ".red"
+ - ".reds"
+ aliases:
+ - red/system
+ tm_scope: source.red
+ ace_mode: text
+ language_id: 320
+Redcode:
+ type: programming
+ extensions:
+ - ".cw"
+ tm_scope: none
+ ace_mode: text
+ language_id: 321
+Regular Expression:
+ type: data
+ extensions:
+ - ".regexp"
+ - ".regex"
+ aliases:
+ - regexp
+ - regex
+ ace_mode: text
+ tm_scope: source.regexp
+ language_id: 363378884
+Ren'Py:
+ type: programming
+ aliases:
+ - renpy
+ color: "#ff7f7f"
+ extensions:
+ - ".rpy"
+ tm_scope: source.renpy
+ ace_mode: python
+ language_id: 322
+RenderScript:
+ type: programming
+ extensions:
+ - ".rs"
+ - ".rsh"
+ tm_scope: none
+ ace_mode: text
+ language_id: 323
+Ring:
+ type: programming
+ color: "#2D54CB"
+ extensions:
+ - ".ring"
+ tm_scope: source.ring
+ ace_mode: text
+ language_id: 431
+RobotFramework:
+ type: programming
+ extensions:
+ - ".robot"
+ tm_scope: text.robot
+ ace_mode: text
+ language_id: 324
+Roff:
+ type: markup
+ color: "#ecdebe"
+ extensions:
+ - ".man"
+ - ".1"
+ - ".1in"
+ - ".1m"
+ - ".1x"
+ - ".2"
+ - ".3"
+ - ".3in"
+ - ".3m"
+ - ".3qt"
+ - ".3x"
+ - ".4"
+ - ".5"
+ - ".6"
+ - ".7"
+ - ".8"
+ - ".9"
+ - ".l"
+ - ".me"
+ - ".ms"
+ - ".n"
+ - ".nr"
+ - ".rno"
+ - ".roff"
+ - ".tmac"
+ filenames:
+ - mmn
+ - mmt
+ tm_scope: text.roff
+ aliases:
+ - nroff
+ ace_mode: text
+ codemirror_mode: troff
+ codemirror_mime_type: text/troff
+ language_id: 141
+Rouge:
+ type: programming
+ ace_mode: clojure
+ codemirror_mode: clojure
+ codemirror_mime_type: text/x-clojure
+ color: "#cc0088"
+ extensions:
+ - ".rg"
+ tm_scope: source.clojure
+ language_id: 325
+Ruby:
+ type: programming
+ ace_mode: ruby
+ codemirror_mode: ruby
+ codemirror_mime_type: text/x-ruby
+ color: "#701516"
+ aliases:
+ - jruby
+ - macruby
+ - rake
+ - rb
+ - rbx
+ extensions:
+ - ".rb"
+ - ".builder"
+ - ".eye"
+ - ".fcgi"
+ - ".gemspec"
+ - ".god"
+ - ".jbuilder"
+ - ".mspec"
+ - ".pluginspec"
+ - ".podspec"
+ - ".rabl"
+ - ".rake"
+ - ".rbuild"
+ - ".rbw"
+ - ".rbx"
+ - ".ru"
+ - ".ruby"
+ - ".spec"
+ - ".thor"
+ - ".watchr"
+ interpreters:
+ - ruby
+ - macruby
+ - rake
+ - jruby
+ - rbx
+ filenames:
+ - ".irbrc"
+ - ".pryrc"
+ - Appraisals
+ - Berksfile
+ - Brewfile
+ - Buildfile
+ - Capfile
+ - Dangerfile
+ - Deliverfile
+ - Fastfile
+ - Gemfile
+ - Gemfile.lock
+ - Guardfile
+ - Jarfile
+ - Mavenfile
+ - Podfile
+ - Puppetfile
+ - Rakefile
+ - Snapfile
+ - Thorfile
+ - Vagrantfile
+ - buildfile
+ language_id: 326
+Rust:
+ type: programming
+ color: "#dea584"
+ extensions:
+ - ".rs"
+ - ".rs.in"
+ ace_mode: rust
+ codemirror_mode: rust
+ codemirror_mime_type: text/x-rustsrc
+ language_id: 327
+SAS:
+ type: programming
+ color: "#B34936"
+ extensions:
+ - ".sas"
+ tm_scope: source.sas
+ ace_mode: text
+ codemirror_mode: sas
+ codemirror_mime_type: text/x-sas
+ language_id: 328
+SCSS:
+ type: markup
+ tm_scope: source.scss
+ group: CSS
+ ace_mode: scss
+ codemirror_mode: css
+ codemirror_mime_type: text/x-scss
+ extensions:
+ - ".scss"
+ language_id: 329
+SMT:
+ type: programming
+ extensions:
+ - ".smt2"
+ - ".smt"
+ interpreters:
+ - boolector
+ - cvc4
+ - mathsat5
+ - opensmt
+ - smtinterpol
+ - smt-rat
+ - stp
+ - verit
+ - yices2
+ - z3
+ tm_scope: source.smt
+ ace_mode: text
+ language_id: 330
+SPARQL:
+ type: data
+ tm_scope: source.sparql
+ ace_mode: text
+ codemirror_mode: sparql
+ codemirror_mime_type: application/sparql-query
+ extensions:
+ - ".sparql"
+ - ".rq"
+ language_id: 331
+SQF:
+ type: programming
+ color: "#3F3F3F"
+ extensions:
+ - ".sqf"
+ - ".hqf"
+ tm_scope: source.sqf
+ ace_mode: text
+ language_id: 332
+SQL:
+ type: data
+ tm_scope: source.sql
+ ace_mode: sql
+ codemirror_mode: sql
+ codemirror_mime_type: text/x-sql
+ extensions:
+ - ".sql"
+ - ".cql"
+ - ".ddl"
+ - ".inc"
+ - ".mysql"
+ - ".prc"
+ - ".tab"
+ - ".udf"
+ - ".viw"
+ language_id: 333
+SQLPL:
+ type: programming
+ ace_mode: sql
+ codemirror_mode: sql
+ codemirror_mime_type: text/x-sql
+ tm_scope: source.sql
+ extensions:
+ - ".sql"
+ - ".db2"
+ language_id: 334
+SRecode Template:
+ type: markup
+ color: "#348a34"
+ tm_scope: source.lisp
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ extensions:
+ - ".srt"
+ language_id: 335
+STON:
+ type: data
+ group: Smalltalk
+ extensions:
+ - ".ston"
+ tm_scope: source.smalltalk
+ ace_mode: text
+ language_id: 336
+SVG:
+ type: data
+ extensions:
+ - ".svg"
+ tm_scope: text.xml
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ language_id: 337
+Sage:
+ type: programming
+ group: Python
+ extensions:
+ - ".sage"
+ - ".sagews"
+ tm_scope: source.python
+ ace_mode: python
+ codemirror_mode: python
+ codemirror_mime_type: text/x-python
+ language_id: 338
+SaltStack:
+ type: programming
+ color: "#646464"
+ aliases:
+ - saltstate
+ - salt
+ extensions:
+ - ".sls"
+ tm_scope: source.yaml.salt
+ ace_mode: yaml
+ codemirror_mode: yaml
+ codemirror_mime_type: text/x-yaml
+ language_id: 339
+Sass:
+ type: markup
+ tm_scope: source.sass
+ group: CSS
+ extensions:
+ - ".sass"
+ ace_mode: sass
+ codemirror_mode: sass
+ codemirror_mime_type: text/x-sass
+ language_id: 340
+Scala:
+ type: programming
+ ace_mode: scala
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-scala
+ color: "#c22d40"
+ extensions:
+ - ".scala"
+ - ".kojo"
+ - ".sbt"
+ - ".sc"
+ interpreters:
+ - scala
+ language_id: 341
+Scaml:
+ group: HTML
+ type: markup
+ extensions:
+ - ".scaml"
+ tm_scope: source.scaml
+ ace_mode: text
+ language_id: 342
+Scheme:
+ type: programming
+ color: "#1e4aec"
+ extensions:
+ - ".scm"
+ - ".sch"
+ - ".sld"
+ - ".sls"
+ - ".sps"
+ - ".ss"
+ interpreters:
+ - guile
+ - bigloo
+ - chicken
+ - csi
+ - gosh
+ - r6rs
+ ace_mode: scheme
+ codemirror_mode: scheme
+ codemirror_mime_type: text/x-scheme
+ language_id: 343
+Scilab:
+ type: programming
+ extensions:
+ - ".sci"
+ - ".sce"
+ - ".tst"
+ ace_mode: text
+ language_id: 344
+Self:
+ type: programming
+ color: "#0579aa"
+ extensions:
+ - ".self"
+ tm_scope: none
+ ace_mode: text
+ language_id: 345
+ShaderLab:
+ type: programming
+ extensions:
+ - ".shader"
+ ace_mode: text
+ tm_scope: source.shaderlab
+ language_id: 664257356
+Shell:
+ type: programming
+ color: "#89e051"
+ aliases:
+ - sh
+ - shell-script
+ - bash
+ - zsh
+ extensions:
+ - ".sh"
+ - ".bash"
+ - ".bats"
+ - ".cgi"
+ - ".command"
+ - ".fcgi"
+ - ".ksh"
+ - ".sh.in"
+ - ".tmux"
+ - ".tool"
+ - ".zsh"
+ filenames:
+ - ".bash_history"
+ - ".bash_logout"
+ - ".bash_profile"
+ - ".bashrc"
+ - ".cshrc"
+ - ".login"
+ - ".profile"
+ - ".zlogin"
+ - ".zlogout"
+ - ".zprofile"
+ - ".zshenv"
+ - ".zshrc"
+ - 9fs
+ - PKGBUILD
+ - bash_logout
+ - bash_profile
+ - bashrc
+ - cshrc
+ - gradlew
+ - login
+ - man
+ - profile
+ - zlogin
+ - zlogout
+ - zprofile
+ - zshenv
+ - zshrc
+ interpreters:
+ - ash
+ - bash
+ - dash
+ - ksh
+ - mksh
+ - pdksh
+ - rc
+ - sh
+ - zsh
+ ace_mode: sh
+ codemirror_mode: shell
+ codemirror_mime_type: text/x-sh
+ language_id: 346
+ShellSession:
+ type: programming
+ extensions:
+ - ".sh-session"
+ aliases:
+ - bash session
+ - console
+ tm_scope: text.shell-session
+ ace_mode: sh
+ codemirror_mode: shell
+ codemirror_mime_type: text/x-sh
+ language_id: 347
+Shen:
+ type: programming
+ color: "#120F14"
+ extensions:
+ - ".shen"
+ tm_scope: source.shen
+ ace_mode: text
+ language_id: 348
+Slash:
+ type: programming
+ color: "#007eff"
+ extensions:
+ - ".sl"
+ tm_scope: text.html.slash
+ ace_mode: text
+ language_id: 349
+Slim:
+ group: HTML
+ type: markup
+ extensions:
+ - ".slim"
+ tm_scope: text.slim
+ ace_mode: text
+ codemirror_mode: slim
+ codemirror_mime_type: text/x-slim
+ language_id: 350
+Smali:
+ type: programming
+ extensions:
+ - ".smali"
+ ace_mode: text
+ tm_scope: source.smali
+ language_id: 351
+Smalltalk:
+ type: programming
+ color: "#596706"
+ extensions:
+ - ".st"
+ - ".cs"
+ aliases:
+ - squeak
+ ace_mode: text
+ codemirror_mode: smalltalk
+ codemirror_mime_type: text/x-stsrc
+ language_id: 352
+Smarty:
+ type: programming
+ extensions:
+ - ".tpl"
+ ace_mode: smarty
+ codemirror_mode: smarty
+ codemirror_mime_type: text/x-smarty
+ tm_scope: text.html.smarty
+ language_id: 353
+Solidity:
+ type: programming
+ color: "#AA6746"
+ ace_mode: text
+ tm_scope: source.solidity
+ language_id: 237469032
+SourcePawn:
+ type: programming
+ color: "#5c7611"
+ aliases:
+ - sourcemod
+ extensions:
+ - ".sp"
+ - ".inc"
+ - ".sma"
+ tm_scope: source.sp
+ ace_mode: text
+ language_id: 354
+Spline Font Database:
+ type: data
+ extensions:
+ - ".sfd"
+ tm_scope: text.sfd
+ ace_mode: yaml
+ language_id: 767169629
+Squirrel:
+ type: programming
+ color: "#800000"
+ extensions:
+ - ".nut"
+ tm_scope: source.c++
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-c++src
+ language_id: 355
+Stan:
+ type: programming
+ color: "#b2011d"
+ extensions:
+ - ".stan"
+ ace_mode: text
+ tm_scope: source.stan
+ language_id: 356
+Standard ML:
+ type: programming
+ color: "#dc566d"
+ aliases:
+ - sml
+ extensions:
+ - ".ML"
+ - ".fun"
+ - ".sig"
+ - ".sml"
+ tm_scope: source.ml
+ ace_mode: text
+ codemirror_mode: mllike
+ codemirror_mime_type: text/x-ocaml
+ language_id: 357
+Stata:
+ type: programming
+ extensions:
+ - ".do"
+ - ".ado"
+ - ".doh"
+ - ".ihlp"
+ - ".mata"
+ - ".matah"
+ - ".sthlp"
+ ace_mode: text
+ language_id: 358
+Stylus:
+ type: markup
+ group: CSS
+ extensions:
+ - ".styl"
+ tm_scope: source.stylus
+ ace_mode: stylus
+ language_id: 359
+SubRip Text:
+ type: data
+ extensions:
+ - ".srt"
+ ace_mode: text
+ tm_scope: text.srt
+ language_id: 360
+SugarSS:
+ type: markup
+ tm_scope: source.css.postcss.sugarss
+ group: CSS
+ extensions:
+ - ".sss"
+ ace_mode: text
+ language_id: 826404698
+SuperCollider:
+ type: programming
+ color: "#46390b"
+ extensions:
+ - ".sc"
+ - ".scd"
+ interpreters:
+ - sclang
+ - scsynth
+ tm_scope: source.supercollider
+ ace_mode: text
+ language_id: 361
+Swift:
+ type: programming
+ color: "#ffac45"
+ extensions:
+ - ".swift"
+ ace_mode: text
+ codemirror_mode: swift
+ codemirror_mime_type: text/x-swift
+ language_id: 362
+SystemVerilog:
+ type: programming
+ color: "#DAE1C2"
+ extensions:
+ - ".sv"
+ - ".svh"
+ - ".vh"
+ ace_mode: verilog
+ codemirror_mode: verilog
+ codemirror_mime_type: text/x-systemverilog
+ language_id: 363
+TI Program:
+ type: programming
+ ace_mode: text
+ color: "#A0AA87"
+ extensions:
+ - ".8xp"
+ - ".8xk"
+ - ".8xk.txt"
+ - ".8xp.txt"
+ language_id: 422
+ tm_scope: none
+TLA:
+ type: programming
+ extensions:
+ - ".tla"
+ tm_scope: source.tla
+ ace_mode: text
+ language_id: 364
+TOML:
+ type: data
+ extensions:
+ - ".toml"
+ filenames:
+ - Cargo.lock
+ - Gopkg.lock
+ tm_scope: source.toml
+ ace_mode: toml
+ codemirror_mode: toml
+ codemirror_mime_type: text/x-toml
+ language_id: 365
+TXL:
+ type: programming
+ extensions:
+ - ".txl"
+ tm_scope: source.txl
+ ace_mode: text
+ language_id: 366
+Tcl:
+ type: programming
+ color: "#e4cc98"
+ extensions:
+ - ".tcl"
+ - ".adp"
+ - ".tm"
+ filenames:
+ - owh
+ - starfield
+ interpreters:
+ - tclsh
+ - wish
+ ace_mode: tcl
+ codemirror_mode: tcl
+ codemirror_mime_type: text/x-tcl
+ language_id: 367
+Tcsh:
+ type: programming
+ group: Shell
+ extensions:
+ - ".tcsh"
+ - ".csh"
+ tm_scope: source.shell
+ ace_mode: sh
+ codemirror_mode: shell
+ codemirror_mime_type: text/x-sh
+ language_id: 368
+TeX:
+ type: markup
+ color: "#3D6117"
+ ace_mode: tex
+ codemirror_mode: stex
+ codemirror_mime_type: text/x-stex
+ wrap: true
+ aliases:
+ - latex
+ extensions:
+ - ".tex"
+ - ".aux"
+ - ".bbx"
+ - ".bib"
+ - ".cbx"
+ - ".cls"
+ - ".dtx"
+ - ".ins"
+ - ".lbx"
+ - ".ltx"
+ - ".mkii"
+ - ".mkiv"
+ - ".mkvi"
+ - ".sty"
+ - ".toc"
+ language_id: 369
+Tea:
+ type: markup
+ extensions:
+ - ".tea"
+ tm_scope: source.tea
+ ace_mode: text
+ language_id: 370
+Terra:
+ type: programming
+ extensions:
+ - ".t"
+ color: "#00004c"
+ ace_mode: lua
+ codemirror_mode: lua
+ codemirror_mime_type: text/x-lua
+ interpreters:
+ - lua
+ language_id: 371
+Text:
+ type: prose
+ wrap: true
+ aliases:
+ - fundamental
+ extensions:
+ - ".txt"
+ - ".fr"
+ - ".nb"
+ - ".ncl"
+ - ".no"
+ filenames:
+ - COPYING
+ - COPYING.regex
+ - COPYRIGHT.regex
+ - FONTLOG
+ - INSTALL
+ - INSTALL.mysql
+ - LICENSE
+ - LICENSE.mysql
+ - NEWS
+ - README.1ST
+ - README.me
+ - README.mysql
+ - click.me
+ - delete.me
+ - keep.me
+ - read.me
+ - readme.1st
+ - test.me
+ tm_scope: none
+ ace_mode: text
+ language_id: 372
+Textile:
+ type: prose
+ ace_mode: textile
+ codemirror_mode: textile
+ codemirror_mime_type: text/x-textile
+ wrap: true
+ extensions:
+ - ".textile"
+ tm_scope: none
+ language_id: 373
+Thrift:
+ type: programming
+ tm_scope: source.thrift
+ extensions:
+ - ".thrift"
+ ace_mode: text
+ language_id: 374
+Turing:
+ type: programming
+ color: "#cf142b"
+ extensions:
+ - ".t"
+ - ".tu"
+ tm_scope: source.turing
+ ace_mode: text
+ language_id: 375
+Turtle:
+ type: data
+ extensions:
+ - ".ttl"
+ tm_scope: source.turtle
+ ace_mode: text
+ codemirror_mode: turtle
+ codemirror_mime_type: text/turtle
+ language_id: 376
+Twig:
+ type: markup
+ group: HTML
+ extensions:
+ - ".twig"
+ tm_scope: text.html.twig
+ ace_mode: twig
+ codemirror_mode: twig
+ codemirror_mime_type: text/x-twig
+ language_id: 377
+Type Language:
+ type: data
+ aliases:
+ - tl
+ extensions:
+ - ".tl"
+ tm_scope: source.tl
+ ace_mode: text
+ language_id: 632765617
+TypeScript:
+ type: programming
+ color: "#2b7489"
+ aliases:
+ - ts
+ extensions:
+ - ".ts"
+ - ".tsx"
+ tm_scope: source.ts
+ ace_mode: typescript
+ codemirror_mode: javascript
+ codemirror_mime_type: application/typescript
+ language_id: 378
+Unified Parallel C:
+ type: programming
+ group: C
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csrc
+ extensions:
+ - ".upc"
+ tm_scope: source.c
+ language_id: 379
+Unity3D Asset:
+ type: data
+ ace_mode: yaml
+ codemirror_mode: yaml
+ codemirror_mime_type: text/x-yaml
+ extensions:
+ - ".anim"
+ - ".asset"
+ - ".mat"
+ - ".meta"
+ - ".prefab"
+ - ".unity"
+ tm_scope: source.yaml
+ language_id: 380
+Unix Assembly:
+ type: programming
+ group: Assembly
+ extensions:
+ - ".s"
+ - ".ms"
+ tm_scope: source.x86
+ ace_mode: assembly_x86
+ language_id: 120
+Uno:
+ type: programming
+ extensions:
+ - ".uno"
+ ace_mode: csharp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csharp
+ tm_scope: source.cs
+ language_id: 381
+UnrealScript:
+ type: programming
+ color: "#a54c4d"
+ extensions:
+ - ".uc"
+ tm_scope: source.java
+ ace_mode: java
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-java
+ language_id: 382
+UrWeb:
+ type: programming
+ aliases:
+ - Ur/Web
+ - Ur
+ extensions:
+ - ".ur"
+ - ".urs"
+ tm_scope: source.ur
+ ace_mode: text
+ language_id: 383
+VCL:
+ type: programming
+ color: "#148AA8"
+ extensions:
+ - ".vcl"
+ tm_scope: source.varnish.vcl
+ ace_mode: text
+ language_id: 384
+VHDL:
+ type: programming
+ color: "#adb2cb"
+ extensions:
+ - ".vhdl"
+ - ".vhd"
+ - ".vhf"
+ - ".vhi"
+ - ".vho"
+ - ".vhs"
+ - ".vht"
+ - ".vhw"
+ ace_mode: vhdl
+ codemirror_mode: vhdl
+ codemirror_mime_type: text/x-vhdl
+ language_id: 385
+Vala:
+ type: programming
+ color: "#fbe5cd"
+ extensions:
+ - ".vala"
+ - ".vapi"
+ ace_mode: vala
+ language_id: 386
+Verilog:
+ type: programming
+ color: "#b2b7f8"
+ extensions:
+ - ".v"
+ - ".veo"
+ ace_mode: verilog
+ codemirror_mode: verilog
+ codemirror_mime_type: text/x-verilog
+ language_id: 387
+Vim script:
+ type: programming
+ color: "#199f4b"
+ tm_scope: source.viml
+ aliases:
+ - vim
+ - viml
+ - nvim
+ extensions:
+ - ".vim"
+ filenames:
+ - ".gvimrc"
+ - ".nvimrc"
+ - ".vimrc"
+ - _vimrc
+ - gvimrc
+ - nvimrc
+ - vimrc
+ ace_mode: text
+ language_id: 388
+Visual Basic:
+ type: programming
+ color: "#945db7"
+ extensions:
+ - ".vb"
+ - ".bas"
+ - ".cls"
+ - ".frm"
+ - ".frx"
+ - ".vba"
+ - ".vbhtml"
+ - ".vbs"
+ tm_scope: source.vbnet
+ aliases:
+ - vb.net
+ - vbnet
+ ace_mode: text
+ codemirror_mode: vb
+ codemirror_mime_type: text/x-vb
+ language_id: 389
+Volt:
+ type: programming
+ color: "#1F1F1F"
+ extensions:
+ - ".volt"
+ tm_scope: source.d
+ ace_mode: d
+ codemirror_mode: d
+ codemirror_mime_type: text/x-d
+ language_id: 390
+Vue:
+ type: markup
+ color: "#2c3e50"
+ extensions:
+ - ".vue"
+ tm_scope: text.html.vue
+ ace_mode: html
+ language_id: 391
+Wavefront Material:
+ type: data
+ extensions:
+ - ".mtl"
+ tm_scope: source.wavefront.mtl
+ ace_mode: text
+ language_id: 392
+Wavefront Object:
+ type: data
+ extensions:
+ - ".obj"
+ tm_scope: source.wavefront.obj
+ ace_mode: text
+ language_id: 393
+Web Ontology Language:
+ type: data
+ extensions:
+ - ".owl"
+ tm_scope: text.xml
+ ace_mode: xml
+ language_id: 394
+WebAssembly:
+ type: programming
+ color: "#04133b"
+ extensions:
+ - ".wast"
+ - ".wat"
+ aliases:
+ - wast
+ - wasm
+ tm_scope: source.webassembly
+ ace_mode: lisp
+ codemirror_mode: commonlisp
+ codemirror_mime_type: text/x-common-lisp
+ language_id: 956556503
+WebIDL:
+ type: programming
+ extensions:
+ - ".webidl"
+ tm_scope: source.webidl
+ ace_mode: text
+ codemirror_mode: webidl
+ codemirror_mime_type: text/x-webidl
+ language_id: 395
+World of Warcraft Addon Data:
+ type: data
+ extensions:
+ - ".toc"
+ tm_scope: source.toc
+ ace_mode: text
+ language_id: 396
+X BitMap:
+ type: data
+ group: C
+ aliases:
+ - xbm
+ extensions:
+ - ".xbm"
+ ace_mode: c_cpp
+ tm_scope: source.c
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csrc
+ language_id: 782911107
+X PixMap:
+ type: data
+ group: C
+ aliases:
+ - xpm
+ extensions:
+ - ".xpm"
+ - ".pm"
+ ace_mode: c_cpp
+ tm_scope: source.c
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csrc
+ language_id: 781846279
+X10:
+ type: programming
+ aliases:
+ - xten
+ ace_mode: text
+ extensions:
+ - ".x10"
+ color: "#4B6BEF"
+ tm_scope: source.x10
+ language_id: 397
+XC:
+ type: programming
+ color: "#99DA07"
+ extensions:
+ - ".xc"
+ tm_scope: source.xc
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csrc
+ language_id: 398
+XCompose:
+ type: data
+ filenames:
+ - ".XCompose"
+ - XCompose
+ - xcompose
+ tm_scope: config.xcompose
+ ace_mode: text
+ language_id: 225167241
+XML:
+ type: data
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ aliases:
+ - rss
+ - xsd
+ - wsdl
+ extensions:
+ - ".xml"
+ - ".adml"
+ - ".admx"
+ - ".ant"
+ - ".axml"
+ - ".builds"
+ - ".ccproj"
+ - ".ccxml"
+ - ".clixml"
+ - ".cproject"
+ - ".cscfg"
+ - ".csdef"
+ - ".csl"
+ - ".csproj"
+ - ".ct"
+ - ".depproj"
+ - ".dita"
+ - ".ditamap"
+ - ".ditaval"
+ - ".dll.config"
+ - ".dotsettings"
+ - ".filters"
+ - ".fsproj"
+ - ".fxml"
+ - ".glade"
+ - ".gml"
+ - ".grxml"
+ - ".iml"
+ - ".ivy"
+ - ".jelly"
+ - ".jsproj"
+ - ".kml"
+ - ".launch"
+ - ".mdpolicy"
+ - ".mjml"
+ - ".mm"
+ - ".mod"
+ - ".mxml"
+ - ".natvis"
+ - ".ncl"
+ - ".ndproj"
+ - ".nproj"
+ - ".nuspec"
+ - ".odd"
+ - ".osm"
+ - ".pkgproj"
+ - ".plist"
+ - ".pluginspec"
+ - ".proj"
+ - ".props"
+ - ".ps1xml"
+ - ".psc1"
+ - ".pt"
+ - ".rdf"
+ - ".resx"
+ - ".rss"
+ - ".sch"
+ - ".scxml"
+ - ".sfproj"
+ - ".shproj"
+ - ".srdf"
+ - ".storyboard"
+ - ".stTheme"
+ - ".sublime-snippet"
+ - ".targets"
+ - ".tmCommand"
+ - ".tml"
+ - ".tmLanguage"
+ - ".tmPreferences"
+ - ".tmSnippet"
+ - ".tmTheme"
+ - ".ts"
+ - ".tsx"
+ - ".ui"
+ - ".urdf"
+ - ".ux"
+ - ".vbproj"
+ - ".vcxproj"
+ - ".vsixmanifest"
+ - ".vssettings"
+ - ".vstemplate"
+ - ".vxml"
+ - ".wixproj"
+ - ".wsdl"
+ - ".wsf"
+ - ".wxi"
+ - ".wxl"
+ - ".wxs"
+ - ".x3d"
+ - ".xacro"
+ - ".xaml"
+ - ".xib"
+ - ".xlf"
+ - ".xliff"
+ - ".xmi"
+ - ".xml.dist"
+ - ".xproj"
+ - ".xsd"
+ - ".xspec"
+ - ".xul"
+ - ".zcml"
+ filenames:
+ - ".classpath"
+ - ".cproject"
+ - ".project"
+ - App.config
+ - NuGet.config
+ - Settings.StyleCop
+ - Web.Debug.config
+ - Web.Release.config
+ - Web.config
+ - packages.config
+ language_id: 399
+XPages:
+ type: data
+ extensions:
+ - ".xsp-config"
+ - ".xsp.metadata"
+ tm_scope: text.xml
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ language_id: 400
+XProc:
+ type: programming
+ extensions:
+ - ".xpl"
+ - ".xproc"
+ tm_scope: text.xml
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ language_id: 401
+XQuery:
+ type: programming
+ color: "#5232e7"
+ extensions:
+ - ".xquery"
+ - ".xq"
+ - ".xql"
+ - ".xqm"
+ - ".xqy"
+ ace_mode: xquery
+ codemirror_mode: xquery
+ codemirror_mime_type: application/xquery
+ tm_scope: source.xq
+ language_id: 402
+XS:
+ type: programming
+ extensions:
+ - ".xs"
+ tm_scope: source.c
+ ace_mode: c_cpp
+ codemirror_mode: clike
+ codemirror_mime_type: text/x-csrc
+ language_id: 403
+XSLT:
+ type: programming
+ aliases:
+ - xsl
+ extensions:
+ - ".xslt"
+ - ".xsl"
+ tm_scope: text.xml.xsl
+ ace_mode: xml
+ codemirror_mode: xml
+ codemirror_mime_type: text/xml
+ color: "#EB8CEB"
+ language_id: 404
+Xojo:
+ type: programming
+ extensions:
+ - ".xojo_code"
+ - ".xojo_menu"
+ - ".xojo_report"
+ - ".xojo_script"
+ - ".xojo_toolbar"
+ - ".xojo_window"
+ tm_scope: source.vbnet
+ ace_mode: text
+ language_id: 405
+Xtend:
+ type: programming
+ extensions:
+ - ".xtend"
+ ace_mode: text
+ language_id: 406
+YAML:
+ type: data
+ tm_scope: source.yaml
+ aliases:
+ - yml
+ extensions:
+ - ".yml"
+ - ".mir"
+ - ".reek"
+ - ".rviz"
+ - ".sublime-syntax"
+ - ".syntax"
+ - ".yaml"
+ - ".yaml-tmlanguage"
+ - ".yml.mysql"
+ filenames:
+ - ".clang-format"
+ - ".clang-tidy"
+ - ".gemrc"
+ - glide.lock
+ ace_mode: yaml
+ codemirror_mode: yaml
+ codemirror_mime_type: text/x-yaml
+ language_id: 407
+YANG:
+ type: data
+ extensions:
+ - ".yang"
+ tm_scope: source.yang
+ ace_mode: text
+ language_id: 408
+YARA:
+ type: data
+ ace_mode: text
+ extensions:
+ - ".yar"
+ - ".yara"
+ tm_scope: source.yara
+ language_id: 805122868
+Yacc:
+ type: programming
+ extensions:
+ - ".y"
+ - ".yacc"
+ - ".yy"
+ tm_scope: source.bison
+ ace_mode: text
+ color: "#4B6C4B"
+ language_id: 409
+Zephir:
+ type: programming
+ color: "#118f9e"
+ extensions:
+ - ".zep"
+ tm_scope: source.php.zephir
+ ace_mode: php
+ language_id: 410
+Zimpl:
+ type: programming
+ extensions:
+ - ".zimpl"
+ - ".zmpl"
+ - ".zpl"
+ tm_scope: none
+ ace_mode: text
+ language_id: 411
+desktop:
+ type: data
+ extensions:
+ - ".desktop"
+ - ".desktop.in"
+ tm_scope: source.desktop
+ ace_mode: text
+ language_id: 412
+eC:
+ type: programming
+ color: "#913960"
+ extensions:
+ - ".ec"
+ - ".eh"
+ tm_scope: source.c.ec
+ ace_mode: text
+ language_id: 413
+edn:
+ type: data
+ ace_mode: clojure
+ codemirror_mode: clojure
+ codemirror_mime_type: text/x-clojure
+ extensions:
+ - ".edn"
+ tm_scope: source.clojure
+ language_id: 414
+fish:
+ type: programming
+ group: Shell
+ interpreters:
+ - fish
+ extensions:
+ - ".fish"
+ tm_scope: source.fish
+ ace_mode: text
+ language_id: 415
+mupad:
+ type: programming
+ extensions:
+ - ".mu"
+ ace_mode: text
+ language_id: 416
+nesC:
+ type: programming
+ color: "#94B0C7"
+ extensions:
+ - ".nc"
+ ace_mode: text
+ tm_scope: source.nesc
+ language_id: 417
+ooc:
+ type: programming
+ color: "#b0b77e"
+ extensions:
+ - ".ooc"
+ ace_mode: text
+ language_id: 418
+q:
+ type: programming
+ extensions:
+ - ".q"
+ tm_scope: source.q
+ ace_mode: text
+ color: "#0040cd"
+ language_id: 970539067
+reStructuredText:
+ type: prose
+ wrap: true
+ aliases:
+ - rst
+ extensions:
+ - ".rst"
+ - ".rest"
+ - ".rest.txt"
+ - ".rst.txt"
+ ace_mode: text
+ codemirror_mode: rst
+ codemirror_mime_type: text/x-rst
+ language_id: 419
+sed:
+ type: programming
+ color: "#64b970"
+ extensions:
+ - ".sed"
+ interpreters:
+ - gsed
+ - minised
+ - sed
+ - ssed
+ ace_mode: text
+ tm_scope: source.sed
+ language_id: 847830017
+wdl:
+ type: programming
+ color: "#42f1f4"
+ extensions:
+ - ".wdl"
+ tm_scope: source.wdl
+ ace_mode: text
+ language_id: 374521672
+wisp:
+ type: programming
+ ace_mode: clojure
+ codemirror_mode: clojure
+ codemirror_mime_type: text/x-clojure
+ color: "#7582D1"
+ extensions:
+ - ".wisp"
+ tm_scope: source.clojure
+ language_id: 420
+xBase:
+ type: programming
+ color: "#403a40"
+ aliases:
+ - advpl
+ - clipper
+ - foxpro
+ extensions:
+ - ".prg"
+ - ".ch"
+ - ".prw"
+ tm_scope: source.harbour
+ ace_mode: text
+ language_id: 421
diff --git a/vendor/licenses.csv b/vendor/licenses.csv
index 85b7d16db54..f6fd1efaa83 100644
--- a/vendor/licenses.csv
+++ b/vendor/licenses.csv
@@ -1,31 +1,102 @@
-@gitlab-org/gitlab-svgs,1.29.0,MIT
-@gitlab-org/gitlab-ui,1.1.0,MIT
+@babel/code-frame,7.0.0,MIT
+@babel/core,7.1.2,MIT
+@babel/generator,7.1.2,MIT
+@babel/helper-annotate-as-pure,7.0.0,MIT
+@babel/helper-builder-binary-assignment-operator-visitor,7.1.0,MIT
+@babel/helper-call-delegate,7.1.0,MIT
+@babel/helper-define-map,7.1.0,MIT
+@babel/helper-explode-assignable-expression,7.1.0,MIT
+@babel/helper-function-name,7.1.0,MIT
+@babel/helper-get-function-arity,7.0.0,MIT
+@babel/helper-hoist-variables,7.0.0,MIT
+@babel/helper-member-expression-to-functions,7.0.0,MIT
+@babel/helper-module-imports,7.0.0,MIT
+@babel/helper-module-transforms,7.1.0,MIT
+@babel/helper-optimise-call-expression,7.0.0,MIT
+@babel/helper-plugin-utils,7.0.0,MIT
+@babel/helper-regex,7.0.0,MIT
+@babel/helper-remap-async-to-generator,7.1.0,MIT
+@babel/helper-replace-supers,7.1.0,MIT
+@babel/helper-simple-access,7.1.0,MIT
+@babel/helper-split-export-declaration,7.0.0,MIT
+@babel/helper-wrap-function,7.1.0,MIT
+@babel/helpers,7.1.2,MIT
+@babel/highlight,7.0.0,MIT
+@babel/parser,7.1.2,MIT
+@babel/plugin-proposal-async-generator-functions,7.1.0,MIT
+@babel/plugin-proposal-class-properties,7.1.0,MIT
+@babel/plugin-proposal-json-strings,7.0.0,MIT
+@babel/plugin-proposal-object-rest-spread,7.0.0,MIT
+@babel/plugin-proposal-optional-catch-binding,7.0.0,MIT
+@babel/plugin-proposal-unicode-property-regex,7.0.0,MIT
+@babel/plugin-syntax-async-generators,7.0.0,MIT
+@babel/plugin-syntax-class-properties,7.0.0,MIT
+@babel/plugin-syntax-dynamic-import,7.0.0,MIT
+@babel/plugin-syntax-import-meta,7.0.0,MIT
+@babel/plugin-syntax-json-strings,7.0.0,MIT
+@babel/plugin-syntax-object-rest-spread,7.0.0,MIT
+@babel/plugin-syntax-optional-catch-binding,7.0.0,MIT
+@babel/plugin-transform-arrow-functions,7.0.0,MIT
+@babel/plugin-transform-async-to-generator,7.1.0,MIT
+@babel/plugin-transform-block-scoped-functions,7.0.0,MIT
+@babel/plugin-transform-block-scoping,7.0.0,MIT
+@babel/plugin-transform-classes,7.1.0,MIT
+@babel/plugin-transform-computed-properties,7.0.0,MIT
+@babel/plugin-transform-destructuring,7.1.2,MIT
+@babel/plugin-transform-dotall-regex,7.0.0,MIT
+@babel/plugin-transform-duplicate-keys,7.0.0,MIT
+@babel/plugin-transform-exponentiation-operator,7.1.0,MIT
+@babel/plugin-transform-for-of,7.0.0,MIT
+@babel/plugin-transform-function-name,7.1.0,MIT
+@babel/plugin-transform-literals,7.0.0,MIT
+@babel/plugin-transform-modules-amd,7.1.0,MIT
+@babel/plugin-transform-modules-commonjs,7.1.0,MIT
+@babel/plugin-transform-modules-systemjs,7.0.0,MIT
+@babel/plugin-transform-modules-umd,7.1.0,MIT
+@babel/plugin-transform-new-target,7.0.0,MIT
+@babel/plugin-transform-object-super,7.1.0,MIT
+@babel/plugin-transform-parameters,7.1.0,MIT
+@babel/plugin-transform-regenerator,7.0.0,MIT
+@babel/plugin-transform-shorthand-properties,7.0.0,MIT
+@babel/plugin-transform-spread,7.0.0,MIT
+@babel/plugin-transform-sticky-regex,7.0.0,MIT
+@babel/plugin-transform-template-literals,7.0.0,MIT
+@babel/plugin-transform-typeof-symbol,7.0.0,MIT
+@babel/plugin-transform-unicode-regex,7.0.0,MIT
+@babel/preset-env,7.1.0,MIT
+@babel/template,7.1.2,MIT
+@babel/traverse,7.1.0,MIT
+@babel/types,7.1.2,MIT
+@gitlab/svgs,1.35.0,MIT
+@gitlab/ui,1.11.0,MIT
@sindresorhus/is,0.7.0,MIT
@types/jquery,2.0.48,MIT
-@vue/component-compiler-utils,1.2.1,MIT
-@webassemblyjs/ast,1.5.13,MIT
-@webassemblyjs/floating-point-hex-parser,1.5.13,MIT
-@webassemblyjs/helper-api-error,1.5.13,MIT
-@webassemblyjs/helper-buffer,1.5.13,MIT
-@webassemblyjs/helper-code-frame,1.5.13,MIT
-@webassemblyjs/helper-fsm,1.5.13,ISC
-@webassemblyjs/helper-module-context,1.5.13,MIT
-@webassemblyjs/helper-wasm-bytecode,1.5.13,MIT
-@webassemblyjs/helper-wasm-section,1.5.13,MIT
-@webassemblyjs/ieee754,1.5.13,MIT
-@webassemblyjs/leb128,1.5.13,MIT
-@webassemblyjs/utf8,1.5.13,MIT
-@webassemblyjs/wasm-edit,1.5.13,MIT
-@webassemblyjs/wasm-gen,1.5.13,MIT
-@webassemblyjs/wasm-opt,1.5.13,MIT
-@webassemblyjs/wasm-parser,1.5.13,MIT
-@webassemblyjs/wast-parser,1.5.13,MIT
-@webassemblyjs/wast-printer,1.5.13,MIT
+@vue/component-compiler-utils,2.2.0,MIT
+@webassemblyjs/ast,1.7.6,MIT
+@webassemblyjs/floating-point-hex-parser,1.7.6,MIT
+@webassemblyjs/helper-api-error,1.7.6,MIT
+@webassemblyjs/helper-buffer,1.7.6,MIT
+@webassemblyjs/helper-code-frame,1.7.6,MIT
+@webassemblyjs/helper-fsm,1.7.6,ISC
+@webassemblyjs/helper-module-context,1.7.6,MIT
+@webassemblyjs/helper-wasm-bytecode,1.7.6,MIT
+@webassemblyjs/helper-wasm-section,1.7.6,MIT
+@webassemblyjs/ieee754,1.7.6,MIT
+@webassemblyjs/leb128,1.7.6,MIT
+@webassemblyjs/utf8,1.7.6,MIT
+@webassemblyjs/wasm-edit,1.7.6,MIT
+@webassemblyjs/wasm-gen,1.7.6,MIT
+@webassemblyjs/wasm-opt,1.7.6,MIT
+@webassemblyjs/wasm-parser,1.7.6,MIT
+@webassemblyjs/wast-parser,1.7.6,MIT
+@webassemblyjs/wast-printer,1.7.6,MIT
+@xtuc/ieee754,1.2.0,New BSD
+@xtuc/long,4.2.1,Apache 2.0
RedCloth,4.3.2,MIT
-abbrev,1.1.1,ISC
-accepts,1.3.4,MIT
+abbrev,1.0.9,ISC
+accepts,1.3.5,MIT
ace-rails-ap,4.1.2,MIT
-acorn,5.7.1,MIT
+acorn,5.7.3,MIT
acorn-dynamic-import,3.0.0,MIT
actionmailer,4.2.10,MIT
actionpack,4.2.10,MIT
@@ -37,8 +108,9 @@ activesupport,4.2.10,MIT
acts-as-taggable-on,5.0.0,MIT
addressable,2.5.2,Apache 2.0
aes_key_wrap,1.0.1,MIT
-ajv,6.1.1,MIT
-ajv-keywords,3.1.0,MIT
+ajv,6.5.3,MIT
+ajv-errors,1.0.0,MIT
+ajv-keywords,3.2.0,MIT
akismet,2.0.0,MIT
ansi-escapes,1.4.0,MIT
ansi-escapes,3.0.0,MIT
@@ -61,7 +133,6 @@ asciidoctor,1.5.6.2,MIT
asciidoctor-plantuml,0.0.8,MIT
asn1.js,4.10.1,MIT
assert,1.4.1,MIT
-asset_sync,2.4.0,MIT
assign-symbols,1.0.0,MIT
async-each,1.0.1,MIT
async-limiter,1.0.0,MIT
@@ -73,78 +144,10 @@ autosize,4.0.0,MIT
axiom-types,0.1.1,MIT
axios,0.17.1,MIT
babel-code-frame,6.26.0,MIT
-babel-core,6.26.3,MIT
-babel-generator,6.26.0,MIT
-babel-helper-bindify-decorators,6.24.1,MIT
-babel-helper-builder-binary-assignment-operator-visitor,6.24.1,MIT
-babel-helper-call-delegate,6.24.1,MIT
-babel-helper-define-map,6.26.0,MIT
-babel-helper-explode-assignable-expression,6.24.1,MIT
-babel-helper-explode-class,6.24.1,MIT
-babel-helper-function-name,6.24.1,MIT
-babel-helper-get-function-arity,6.24.1,MIT
-babel-helper-hoist-variables,6.24.1,MIT
-babel-helper-optimise-call-expression,6.24.1,MIT
-babel-helper-regex,6.26.0,MIT
-babel-helper-remap-async-to-generator,6.24.1,MIT
-babel-helper-replace-supers,6.24.1,MIT
-babel-helpers,6.24.1,MIT
-babel-loader,7.1.5,MIT
-babel-messages,6.23.0,MIT
-babel-plugin-check-es2015-constants,6.22.0,MIT
-babel-plugin-syntax-async-functions,6.13.0,MIT
-babel-plugin-syntax-async-generators,6.13.0,MIT
-babel-plugin-syntax-class-properties,6.13.0,MIT
-babel-plugin-syntax-decorators,6.13.0,MIT
-babel-plugin-syntax-dynamic-import,6.18.0,MIT
-babel-plugin-syntax-exponentiation-operator,6.13.0,MIT
-babel-plugin-syntax-object-rest-spread,6.13.0,MIT
-babel-plugin-syntax-trailing-function-commas,6.22.0,MIT
-babel-plugin-transform-async-generator-functions,6.24.1,MIT
-babel-plugin-transform-async-to-generator,6.24.1,MIT
-babel-plugin-transform-class-properties,6.24.1,MIT
-babel-plugin-transform-decorators,6.24.1,MIT
-babel-plugin-transform-define,1.3.0,MIT
-babel-plugin-transform-es2015-arrow-functions,6.22.0,MIT
-babel-plugin-transform-es2015-block-scoped-functions,6.22.0,MIT
-babel-plugin-transform-es2015-block-scoping,6.26.0,MIT
-babel-plugin-transform-es2015-classes,6.24.1,MIT
-babel-plugin-transform-es2015-computed-properties,6.24.1,MIT
-babel-plugin-transform-es2015-destructuring,6.23.0,MIT
-babel-plugin-transform-es2015-duplicate-keys,6.24.1,MIT
-babel-plugin-transform-es2015-for-of,6.23.0,MIT
-babel-plugin-transform-es2015-function-name,6.24.1,MIT
-babel-plugin-transform-es2015-literals,6.22.0,MIT
-babel-plugin-transform-es2015-modules-amd,6.24.1,MIT
-babel-plugin-transform-es2015-modules-commonjs,6.26.0,MIT
-babel-plugin-transform-es2015-modules-systemjs,6.24.1,MIT
-babel-plugin-transform-es2015-modules-umd,6.24.1,MIT
-babel-plugin-transform-es2015-object-super,6.24.1,MIT
-babel-plugin-transform-es2015-parameters,6.24.1,MIT
-babel-plugin-transform-es2015-shorthand-properties,6.24.1,MIT
-babel-plugin-transform-es2015-spread,6.22.0,MIT
-babel-plugin-transform-es2015-sticky-regex,6.24.1,MIT
-babel-plugin-transform-es2015-template-literals,6.22.0,MIT
-babel-plugin-transform-es2015-typeof-symbol,6.23.0,MIT
-babel-plugin-transform-es2015-unicode-regex,6.24.1,MIT
-babel-plugin-transform-exponentiation-operator,6.24.1,MIT
-babel-plugin-transform-object-rest-spread,6.23.0,MIT
-babel-plugin-transform-regenerator,6.26.0,MIT
-babel-plugin-transform-strict-mode,6.24.1,MIT
+babel-loader,8.0.4,MIT
babel-polyfill,6.23.0,MIT
-babel-preset-es2015,6.24.1,MIT
-babel-preset-es2016,6.24.1,MIT
-babel-preset-es2017,6.24.1,MIT
-babel-preset-latest,6.24.1,MIT
-babel-preset-stage-2,6.24.1,MIT
-babel-preset-stage-3,6.24.1,MIT
-babel-register,6.26.0,MIT
babel-runtime,6.26.0,MIT
-babel-template,6.26.0,MIT
-babel-traverse,6.26.0,MIT
-babel-types,6.26.0,MIT
babosa,1.0.2,MIT
-babylon,6.18.0,MIT
balanced-match,1.0.0,MIT
base,0.11.2,MIT
base32,0.3.2,MIT
@@ -152,16 +155,15 @@ base64-js,1.2.3,MIT
batch-loader,1.2.1,MIT
bcrypt,3.1.12,MIT
bcrypt_pbkdf,1.0.0,MIT
-bfj-node4,5.2.1,MIT
-big.js,3.1.3,MIT
+bfj,6.1.1,MIT
+big.js,3.2.0,MIT
binary-extensions,1.11.0,MIT
binaryextensions,2.1.1,MIT
bindata,2.4.3,ruby
-blackst0ne-mermaid,7.1.0-fixed,MIT
bluebird,3.5.1,MIT
bn.js,4.11.8,MIT
body-parser,1.18.2,MIT
-bootstrap,4.1.2,MIT
+bootstrap,4.1.1,MIT
bootstrap-vue,2.0.0-rc.11,MIT
bootstrap_form,2.7.0,MIT
brace-expansion,1.1.11,MIT
@@ -174,6 +176,7 @@ browserify-des,1.0.0,MIT
browserify-rsa,4.0.1,MIT
browserify-sign,4.0.4,ISC
browserify-zlib,0.2.0,MIT
+browserslist,4.1.1,MIT
buffer,4.9.1,MIT
buffer-from,1.0.0,MIT
buffer-xor,1.0.3,MIT
@@ -181,10 +184,12 @@ builder,3.2.3,MIT
builtin-status-codes,3.0.0,MIT
bytes,3.0.0,MIT
cacache,10.0.4,ISC
+cacache,11.2.0,ISC
cache-base,1.0.1,MIT
cache-loader,1.2.2,MIT
cacheable-request,2.1.4,MIT
camelcase,4.1.0,MIT
+caniuse-lite,1.0.30000888,CC-BY-4.0
carrierwave,1.2.3,MIT
cause,0.1,MIT
chalk,1.1.3,MIT
@@ -216,31 +221,31 @@ codesandbox-import-util-types,1.2.11,LGPL
codesandbox-import-utils,1.2.11,LGPL
coercible,1.0.0,MIT
collection-visit,1.0.0,MIT
-color-convert,1.9.1,MIT
-color-name,1.1.2,MIT
+color-convert,1.9.3,MIT
+color-name,1.1.3,MIT
commander,2.13.0,MIT
-commander,2.15.1,MIT
+commander,2.18.0,MIT
commondir,1.0.1,MIT
-commonmarker,0.17.8,MIT
+commonmarker,0.17.13,MIT
component-emitter,1.2.1,MIT
-compression-webpack-plugin,1.1.11,MIT
+compression-webpack-plugin,2.0.0,MIT
concat-map,0.0.1,MIT
concat-stream,1.6.2,MIT
concurrent-ruby-ext,1.0.5,MIT
-connection_pool,2.2.1,MIT
+connection_pool,2.2.2,MIT
console-browserify,1.1.0,MIT
console-control-strings,1.1.0,ISC
consolidate,0.15.1,MIT
constants-browserify,1.0.0,MIT
content-disposition,0.5.2,MIT
content-type,1.0.4,MIT
-convert-source-map,1.5.1,MIT
+convert-source-map,1.6.0,MIT
cookie,0.3.1,MIT
cookie-signature,1.0.6,MIT
copy-concurrently,1.0.5,ISC
copy-descriptor,0.1.1,MIT
core-js,2.3.0,MIT
-core-js,2.5.3,MIT
+core-js,2.5.7,MIT
core-util-is,1.0.2,MIT
crack,0.4.3,MIT
crass,1.0.4,MIT
@@ -249,7 +254,6 @@ create-hash,1.1.3,MIT
create-hmac,1.1.6,MIT
creole,0.5.0,ruby
cropper,2.3.0,MIT
-cross-spawn,5.1.0,MIT
cross-spawn,6.0.5,MIT
crypt,0.0.2,New BSD
crypto-browserify,3.12.0,MIT
@@ -258,8 +262,8 @@ css-selector-tokenizer,0.7.0,MIT
css_parser,1.5.0,MIT
cssesc,0.1.0,MIT
cyclist,0.2.2,MIT*
-d3,3.5.17,New BSD
d3,4.12.2,New BSD
+d3,4.13.0,New BSD
d3-array,1.2.1,New BSD
d3-axis,1.0.8,New BSD
d3-brush,1.0.4,New BSD
@@ -272,6 +276,7 @@ d3-dsv,1.0.8,New BSD
d3-ease,1.0.3,New BSD
d3-force,1.1.0,New BSD
d3-format,1.2.1,New BSD
+d3-format,1.2.2,New BSD
d3-geo,1.9.1,New BSD
d3-hierarchy,1.1.5,New BSD
d3-interpolate,1.1.6,New BSD
@@ -283,6 +288,7 @@ d3-random,1.1.0,New BSD
d3-request,1.0.6,New BSD
d3-scale,1.0.7,New BSD
d3-selection,1.2.0,New BSD
+d3-selection,1.3.0,New BSD
d3-shape,1.2.0,New BSD
d3-time,1.0.8,New BSD
d3-time-format,2.1.1,New BSD
@@ -290,15 +296,15 @@ d3-timer,1.0.7,New BSD
d3-transition,1.1.1,New BSD
d3-voronoi,1.1.2,New BSD
d3-zoom,1.7.1,New BSD
-dagre-d3-renderer,0.4.24,MIT
-dagre-layout,0.8.0,MIT
+dagre-d3-renderer,0.5.8,MIT
+dagre-layout,0.8.8,MIT
date-now,0.1.4,MIT
dateformat,3.0.3,MIT
de-indent,1.0.2,MIT
debug,2.6.9,MIT
-debug,3.1.0,MIT
+debug,3.2.5,MIT
debugger-ruby_core_source,1.3.8,MIT
-decamelize,1.2.0,MIT
+decamelize,2.0.0,MIT
deckar01-task_list,2.0.0,MIT
declarative,0.0.10,MIT
declarative-option,0.1.0,MIT
@@ -306,22 +312,22 @@ decode-uri-component,0.2.0,MIT
decompress-response,3.3.0,MIT
deep-extend,0.4.2,MIT
default_value_for,3.0.2,MIT
+define-properties,1.1.3,MIT
define-property,0.2.5,MIT
define-property,1.0.0,MIT
define-property,2.0.2,MIT
delegate,3.1.2,MIT
delegates,1.0.0,MIT
depd,1.1.1,MIT
+depd,1.1.2,MIT
des.js,1.0.0,MIT
descendants_tracker,0.0.4,MIT
destroy,1.0.4,MIT
-detect-indent,4.0.0,MIT
detect-libc,1.0.3,Apache 2.0
device_detector,1.0.0,LGPL
devise,4.4.3,MIT
devise-two-factor,3.0.0,MIT
diff,3.5.0,New BSD
-diff-lcs,1.3,"MIT,Artistic-2.0,GPL-2.0+"
diffie-hellman,5.0.2,MIT
diffy,3.1.0,MIT
document-register-element,1.3.0,MIT
@@ -336,14 +342,14 @@ doorkeeper,4.3.2,MIT
doorkeeper-openid_connect,1.5.0,MIT
dot-prop,4.2.0,MIT
dropzone,4.2.0,MIT
-dropzonejs-rails,0.7.2,MIT
duplexer,0.1.1,MIT
duplexer3,0.1.4,New BSD
duplexify,3.5.3,MIT
ed25519,1.2.4,MIT
editions,1.3.4,MIT
ee-first,1.1.1,MIT
-ejs,2.5.9,Apache 2.0
+ejs,2.6.1,Apache 2.0
+electron-to-chromium,1.3.73,ISC
elliptic,6.4.0,MIT
email_reply_trimmer,0.1.6,MIT
emoji-unicode-version,0.2.1,MIT
@@ -357,11 +363,14 @@ entities,1.1.1,Simplified BSD
equalizer,0.0.11,MIT
errno,0.1.7,MIT
erubis,2.7.0,MIT
+es-abstract,1.12.0,MIT
+es-to-primitive,1.1.1,MIT
es6-promise,3.0.2,MIT
escape-html,1.0.3,MIT
escape-string-regexp,1.0.5,MIT
escape_utils,1.1.1,MIT
-eslint-scope,3.7.1,Simplified BSD
+escaper,2.5.3,MIT
+eslint-scope,4.0.0,Simplified BSD
esrecurse,4.2.1,Simplified BSD
estraverse,4.2.0,Simplified BSD
esutils,2.0.2,Simplified BSD
@@ -371,11 +380,11 @@ eve-raphael,0.5.0,Apache 2.0
events,1.1.1,MIT
evp_bytestokey,1.0.3,MIT
excon,0.62.0,MIT
-execa,0.7.0,MIT
+execa,0.10.0,MIT
execjs,2.6.0,MIT
expand-brackets,2.1.4,MIT
exports-loader,0.7.0,MIT
-express,4.16.2,MIT
+express,4.16.3,MIT
expression_parser,0.9.0,MIT
extend-shallow,2.0.1,MIT
extend-shallow,3.0.2,MIT
@@ -385,19 +394,22 @@ extglob,2.0.4,MIT
faraday,0.12.2,MIT
faraday_middleware,0.12.2,MIT
faraday_middleware-multi_json,0.0.6,MIT
-fast-deep-equal,1.0.0,MIT
+fast-deep-equal,2.0.1,MIT
fast-json-stable-stringify,2.0.0,MIT
fast_blank,1.0.0,MIT
fast_gettext,1.6.0,"MIT,ruby"
fastparse,1.1.1,MIT
ffi,1.9.25,New BSD
+figgy-pudding,3.5.1,ISC
figures,2.0.0,MIT
-file-loader,1.1.11,MIT
-filesize,3.6.0,New BSD
+file-loader,2.0.0,MIT
+filesize,3.6.1,New BSD
fill-range,4.0.0,MIT
-finalhandler,1.1.0,MIT
+finalhandler,1.1.1,MIT
find-cache-dir,1.0.0,MIT
+find-cache-dir,2.0.0,MIT
find-up,2.1.0,MIT
+find-up,3.0.0,MIT
flipper,0.13.0,MIT
flipper-active_record,0.13.0,MIT
flipper-active_support_cache_store,0.13.0,MIT
@@ -425,6 +437,7 @@ fs-minipass,1.2.5,ISC
fs-write-stream-atomic,1.0.10,ISC
fs.realpath,1.0.0,ISC
fsevents,1.2.4,MIT
+function-bind,1.1.1,MIT
fuzzaldrin-plus,0.5.0,MIT
gauge,2.7.4,ISC
gemojione,3.3.0,MIT
@@ -434,44 +447,41 @@ get-value,2.0.6,MIT
get_process_mem,0.2.0,MIT
gettext_i18n_rails,1.8.0,MIT
gettext_i18n_rails_js,1.3.0,MIT
-gitaly-proto,0.117.0,MIT
-github-linguist,5.3.3,MIT
+gitaly-proto,0.123.0,MIT
github-markup,1.7.0,MIT
-gitlab-flowdock-git-hook,1.0.1,MIT
-gitlab-gollum-lib,4.2.7.5,MIT
-gitlab-gollum-rugged_adapter,0.4.4.1,MIT
-gitlab-grit,2.8.2,MIT
gitlab-markup,1.6.4,MIT
+gitlab-sidekiq-fetcher,0.3.0,LGPL
gitlab_omniauth-ldap,2.0.4,MIT
-glob,7.1.2,ISC
+glob,7.1.3,ISC
glob-parent,3.1.0,ISC
global-modules-path,2.1.0,Apache 2.0
globalid,0.4.1,MIT
-globals,9.18.0,MIT
-gollum-grit_adapter,1.0.1,MIT
+globals,11.7.0,MIT
gon,6.2.0,MIT
good-listener,1.2.2,MIT
google-api-client,0.23.4,Apache 2.0
-google-protobuf,3.5.1,New BSD
-googleapis-common-protos-types,1.0.1,Apache 2.0
-googleauth,0.6.2,Apache 2.0
+google-protobuf,3.6.1,New BSD
+googleapis-common-protos-types,1.0.2,Apache 2.0
+googleauth,0.6.6,Apache 2.0
got,8.3.0,MIT
gpgme,2.0.13,LGPL-2.1+
graceful-fs,4.1.11,ISC
-grape,1.0.3,MIT
+grape,1.1.0,MIT
grape-entity,0.7.1,MIT
grape-path-helpers,1.0.6,MIT
grape_logging,1.7.0,MIT
graphiql-rails,1.4.10,MIT
-graphlib,2.1.1,MIT
+graphlibrary,2.2.0,MIT
graphql,1.8.1,MIT
-grpc,1.11.0,Apache 2.0
-gzip-size,4.1.0,MIT
+grpc,1.15.0,Apache 2.0
+gzip-size,5.0.0,MIT
hamlit,2.8.8,MIT
hangouts-chat,0.0.5,MIT
+has,1.0.1,MIT
has-ansi,2.0.0,MIT
has-flag,3.0.0,MIT
has-symbol-support-x,1.3.0,MIT
+has-symbols,1.0.0,MIT
has-to-string-tag-x,1.3.0,MIT
has-unicode,2.0.1,ISC
has-value,0.3.1,MIT
@@ -488,7 +498,7 @@ he,1.1.1,MIT
health_check,2.6.0,MIT
hipchat,1.5.2,MIT
hmac-drbg,1.0.1,MIT
-home-or-tmp,2.0.0,MIT
+hoopy,0.1.4,MIT
html-pipeline,2.8.4,MIT
html2text,0.2.0,MIT
htmlentities,4.3.4,MIT
@@ -524,25 +534,26 @@ inherits,2.0.1,ISC
inherits,2.0.3,ISC
ini,1.3.5,ISC
inquirer,3.0.6,MIT
-inquirer,6.0.0,MIT
+inquirer,6.2.0,MIT
interpret,1.1.0,MIT
into-stream,3.1.0,MIT
-invariant,2.2.2,New BSD
-invert-kv,1.0.0,MIT
-ipaddr.js,1.6.0,MIT
+invariant,2.2.4,MIT
+invert-kv,2.0.0,MIT
+ipaddr.js,1.8.0,MIT
ipaddress,0.8.3,MIT
is-accessor-descriptor,0.1.6,MIT
is-accessor-descriptor,1.0.0,MIT
is-binary-path,1.0.1,MIT
is-buffer,1.1.6,MIT
+is-callable,1.1.4,MIT
is-data-descriptor,0.1.4,MIT
is-data-descriptor,1.0.0,MIT
+is-date-object,1.0.1,MIT
is-descriptor,0.1.6,MIT
is-descriptor,1.0.2,MIT
is-extendable,0.1.1,MIT
is-extendable,1.0.1,MIT
is-extglob,2.1.1,MIT
-is-finite,1.0.2,MIT
is-fullwidth-code-point,1.0.0,MIT
is-fullwidth-code-point,2.0.0,MIT
is-glob,3.1.0,MIT
@@ -555,8 +566,11 @@ is-odd,2.0.0,MIT
is-plain-obj,1.1.0,MIT
is-plain-object,2.0.4,MIT
is-promise,2.1.0,MIT
+is-regex,1.0.4,MIT
+is-regexp,1.0.0,MIT
is-retry-allowed,1.1.0,MIT
is-stream,1.1.0,MIT
+is-symbol,1.0.2,MIT
is-windows,1.0.2,MIT
isarray,1.0.0,MIT
isexe,2.0.0,ISC
@@ -571,15 +585,17 @@ jquery-atwho-rails,1.3.2,MIT
jquery-ujs,1.2.2,MIT
jquery.waitforimages,2.2.0,MIT
js-cookie,2.1.3,MIT
+js-levenshtein,1.1.4,MIT
js-tokens,3.0.2,MIT
+js-tokens,4.0.0,MIT
js_regex,2.2.1,MIT
jsesc,0.5.0,MIT
-jsesc,1.3.0,MIT
+jsesc,2.5.1,MIT
json,1.8.6,ruby
json-buffer,3.0.0,MIT
json-jwt,1.9.4,MIT
json-parse-better-errors,1.0.2,MIT
-json-schema-traverse,0.3.1,MIT
+json-schema-traverse,0.4.1,MIT
json5,0.5.1,MIT
jszip,3.1.3,(MIT OR GPL-3.0)
jszip-utils,0.0.2,MIT or GPLv3
@@ -588,7 +604,7 @@ kaminari,1.0.1,MIT
kaminari-actionview,1.0.1,MIT
kaminari-activerecord,1.0.1,MIT
kaminari-core,1.0.1,MIT
-katex,0.8.3,MIT
+katex,0.9.0,MIT
keyv,3.0.0,MIT
kgio,2.10.0,LGPL-2.1+
kind-of,3.2.2,MIT
@@ -597,16 +613,15 @@ kind-of,5.1.0,MIT
kind-of,6.0.2,MIT
kubeclient,3.1.0,MIT
lazy-cache,2.0.2,MIT
-lcid,1.0.0,MIT
+lcid,2.0.0,MIT
licensee,8.9.2,MIT
lie,3.1.1,MIT
-little-plugger,1.1.4,MIT
loader-runner,2.3.0,MIT
loader-utils,1.1.0,MIT
locale,2.1.2,"ruby,LGPLv3+"
locate-path,2.0.0,MIT
-lodash,4.17.10,MIT
-lodash,4.17.4,MIT
+locate-path,3.0.0,MIT
+lodash,4.17.11,MIT
lodash.camelcase,4.3.0,MIT
lodash.clonedeep,4.5.0,MIT
lodash.debounce,4.0.8,MIT
@@ -615,30 +630,29 @@ lodash.get,4.4.2,MIT
lodash.isequal,4.5.0,MIT
lodash.mergewith,4.6.0,MIT
lodash.startcase,4.4.0,MIT
-logging,2.2.2,MIT
lograge,0.10.0,MIT
-long,3.2.0,Apache 2.0
-long,4.0.0,Apache 2.0
loofah,2.2.2,MIT
-loose-envify,1.3.1,MIT
+loose-envify,1.4.0,MIT
lowercase-keys,1.0.0,MIT
lru-cache,4.1.3,ISC
lz-string,1.4.4,WTFPL
mail,2.7.0,MIT
mail_room,0.9.1,MIT
-make-dir,1.2.0,MIT
+make-dir,1.3.0,MIT
mamacro,0.0.3,MIT
+map-age-cleaner,0.1.2,MIT
map-cache,0.2.2,MIT
map-visit,1.0.0,MIT
marked,0.3.12,MIT
match-at,0.1.1,MIT
md5.js,1.3.4,MIT
media-typer,0.3.0,MIT
-mem,1.1.0,MIT
+mem,4.0.0,MIT
memoist,0.16.0,MIT
memory-fs,0.4.1,MIT
merge-descriptors,1.0.1,MIT
merge-source-map,1.1.0,MIT
+mermaid,8.0.0-rc.8,MIT
method_source,0.9.0,MIT
methods,1.1.2,MIT
micromatch,3.1.10,MIT
@@ -653,7 +667,7 @@ mimemagic,0.3.0,MIT
mimic-fn,1.1.0,MIT
mimic-response,1.0.0,MIT
mini_magick,4.8.0,MIT
-mini_mime,1.0.0,MIT
+mini_mime,1.0.1,MIT
mini_portile2,2.3.0,MIT
minimalistic-assert,1.0.0,ISC
minimalistic-crypto-utils,1.0.1,MIT
@@ -663,20 +677,21 @@ minimist,1.2.0,MIT
minipass,2.3.3,ISC
minizlib,1.1.0,MIT
mississippi,2.0.0,Simplified BSD
+mississippi,3.0.0,Simplified BSD
mixin-deep,1.3.1,MIT
mkdirp,0.5.1,MIT
-moment,2.19.2,MIT
+moment,2.22.2,MIT
monaco-editor,0.14.3,MIT
-monaco-editor-webpack-plugin,1.5.2,MIT
+monaco-editor-webpack-plugin,1.5.4,MIT
mousetrap,1.4.6,Apache 2.0
-mousetrap-rails,1.4.6,"MIT,Apache"
move-concurrently,1.0.1,ISC
ms,2.0.0,MIT
+ms,2.1.1,MIT
msgpack,1.2.4,Apache 2.0
multi_json,1.13.1,MIT
multi_xml,0.6.0,MIT
multipart-post,2.0.0,MIT
-mustermann,1.0.2,MIT
+mustermann,1.0.3,MIT
mustermann-grape,1.0.0,MIT
mute-stream,0.0.7,ISC
mysql2,0.4.10,MIT
@@ -692,6 +707,7 @@ nice-try,1.0.4,MIT
node-fetch,1.6.3,MIT
node-libs-browser,2.1.0,MIT
node-pre-gyp,0.10.0,New BSD
+node-releases,1.0.0-alpha.12,CC-BY-4.0
nokogiri,1.8.4,MIT
nokogumbo,1.5.0,Apache 2.0
nopt,4.0.1,ISC
@@ -707,7 +723,9 @@ oauth,0.5.4,MIT
oauth2,1.4.0,MIT
object-assign,4.1.1,MIT
object-copy,0.1.0,MIT
+object-keys,1.0.12,MIT
object-visit,1.0.1,MIT
+object.getownpropertydescriptors,2.0.3,MIT
object.pick,1.3.0,MIT
octokit,4.9.0,MIT
omniauth,1.8.1,MIT
@@ -732,23 +750,27 @@ on-finished,2.3.0,MIT
once,1.4.0,ISC
onetime,2.0.1,MIT
opencollective,1.0.3,MIT
-opener,1.4.3,(WTFPL OR MIT)
+opener,1.5.1,(WTFPL OR MIT)
opn,4.0.2,MIT
org-ruby,0.9.12,MIT
orm_adapter,0.5.0,MIT
-os,0.9.6,MIT
+os,1.0.0,MIT
os-browserify,0.3.0,MIT
os-homedir,1.0.2,MIT
-os-locale,2.1.0,MIT
+os-locale,3.0.1,MIT
os-tmpdir,1.0.2,MIT
osenv,0.1.5,ISC
p-cancelable,0.4.1,MIT
+p-defer,1.0.0,MIT
p-finally,1.0.0,MIT
p-is-promise,1.1.0,MIT
p-limit,1.2.0,MIT
+p-limit,2.0.0,MIT
p-locate,2.0.0,MIT
+p-locate,3.0.0,MIT
p-timeout,2.0.1,MIT
p-try,1.0.0,MIT
+p-try,2.0.0,MIT
pako,1.0.6,(MIT AND Zlib)
parallel-transform,1.1.0,MIT
parse-asn1,5.1.0,ISC
@@ -759,6 +781,7 @@ path-dirname,1.0.2,MIT
path-exists,3.0.0,MIT
path-is-absolute,1.0.1,MIT
path-key,2.0.1,MIT
+path-parse,1.0.6,MIT
path-to-regexp,0.1.7,MIT
pbkdf2,3.0.14,MIT
peek,1.0.1,MIT
@@ -767,17 +790,16 @@ peek-mysql2,1.1.0,MIT
peek-pg,1.3.0,MIT
peek-rblineprof,0.2.0,MIT
peek-redis,1.2.0,MIT
-peek-sidekiq,1.0.3,MIT
pg,0.18.4,"BSD,ruby,GPL"
pify,3.0.0,MIT
pikaday,1.6.1,MIT
pinkie,2.0.4,MIT
pinkie-promise,2.0.1,MIT
pkg-dir,2.0.0,MIT
+pkg-dir,3.0.0,MIT
po_to_json,1.0.1,MIT
popper.js,1.14.3,MIT
posix-character-classes,0.1.1,MIT
-posix-spawn,0.3.13,MIT
postcss,6.0.23,MIT
postcss-modules-extract-imports,1.2.0,ISC
postcss-modules-local-by-default,1.2.0,MIT
@@ -788,7 +810,7 @@ postcss-value-parser,3.3.0,MIT
premailer,1.10.4,New BSD
premailer-rails,1.9.7,MIT
prepend-http,2.0.0,MIT
-prettier,1.12.1,MIT
+prettier,1.13.7,MIT
prismjs,1.6.0,MIT
private,0.1.8,MIT
process,0.11.10,MIT
@@ -796,15 +818,18 @@ process-nextick-args,1.0.7,MIT
process-nextick-args,2.0.0,MIT
prometheus-client-mmap,0.9.4,Apache 2.0
promise-inflight,1.0.1,ISC
-proxy-addr,2.0.3,MIT
+proxy-addr,2.0.4,MIT
prr,1.0.1,MIT
pseudomap,1.0.2,ISC
public-encrypt,4.0.0,MIT
-public_suffix,3.0.2,MIT
+public_suffix,3.0.3,MIT
+puma,3.12.0,New BSD
+puma_worker_killer,0.1.0,MIT
pump,2.0.1,MIT
+pump,3.0.0,MIT
pumpify,1.4.0,MIT
punycode,1.3.2,MIT
-punycode,1.4.1,MIT
+punycode,2.1.1,MIT
pyu-ruby-sasl,0.0.3.3,MIT
qs,6.5.1,New BSD
query-string,5.1.1,MIT
@@ -815,7 +840,7 @@ rack-accept,0.4.5,MIT
rack-attack,4.4.1,MIT
rack-cors,1.0.2,MIT
rack-oauth2,1.2.3,MIT
-rack-protection,2.0.1,MIT
+rack-protection,2.0.3,MIT
rack-proxy,0.6.0,MIT
rack-test,0.6.3,MIT
rails,4.2.10,MIT
@@ -853,24 +878,27 @@ redis-namespace,1.6.0,MIT
redis-rack,2.0.4,MIT
redis-rails,5.0.2,MIT
redis-store,1.4.1,MIT
-regenerate,1.3.2,MIT
+regenerate,1.4.0,MIT
+regenerate-unicode-properties,7.0.0,MIT
regenerator-runtime,0.10.5,MIT
-regenerator-runtime,0.11.0,MIT
-regenerator-transform,0.10.1,BSD
+regenerator-runtime,0.11.1,MIT
+regenerator-transform,0.13.3,MIT
regex-not,1.0.2,MIT
regexp_parser,0.5.0,MIT
regexpu-core,1.0.0,MIT
-regexpu-core,2.0.0,MIT
+regexpu-core,4.2.0,MIT
regjsgen,0.2.0,MIT
+regjsgen,0.4.0,MIT
regjsparser,0.1.5,Simplified BSD
+regjsparser,0.3.0,Simplified BSD
remove-trailing-separator,1.1.0,ISC
repeat-element,1.1.2,MIT
repeat-string,1.6.1,MIT
-repeating,2.0.1,MIT
representable,3.0.4,MIT
request_store,1.3.1,MIT
require-directory,2.1.1,MIT
require-main-filename,1.0.1,ISC
+resolve,1.8.1,MIT
resolve-cwd,2.0.0,MIT
resolve-from,3.0.0,MIT
resolve-url,0.2.1,MIT
@@ -884,7 +912,7 @@ rimraf,2.6.2,ISC
rinku,2.0.0,ISC
ripemd160,2.0.1,MIT
rotp,2.1.2,MIT
-rouge,3.2.1,MIT
+rouge,3.3.0,MIT
rqrcode,0.7.0,MIT
rqrcode-rails3,0.1.7,MIT
ruby-enum,0.7.2,MIT
@@ -896,7 +924,7 @@ ruby_parser,3.9.0,MIT
rubyntlm,0.6.2,MIT
rubypants,0.2.0,BSD
rufus-scheduler,3.4.0,MIT
-rugged,0.27.4,MIT
+rugged,0.27.5,MIT
run-async,2.3.0,MIT
run-queue,1.0.3,ISC
rw,1.3.3,New BSD
@@ -915,15 +943,17 @@ sass-rails,5.0.6,MIT
sawyer,0.8.1,MIT
sax,1.2.4,ISC
schema-utils,0.4.5,MIT
+schema-utils,1.0.0,MIT
+scope-css,1.2.1,MIT
seed-fu,2.3.7,MIT
select,1.1.2,MIT
select2,3.5.2-browserify,Apache*
select2-rails,3.5.9.3,MIT
-semver,5.5.0,ISC
-send,0.16.1,MIT
+semver,5.5.1,ISC
+send,0.16.2,MIT
sentry-raven,2.7.2,Apache 2.0
serialize-javascript,1.4.0,New BSD
-serve-static,1.13.1,MIT
+serve-static,1.13.2,MIT
set-blocking,2.0.0,ISC
set-getter,0.1.0,MIT
set-immediate-shim,1.0.1,MIT
@@ -938,13 +968,12 @@ sha.js,2.4.10,MIT
sha1,1.1.1,New BSD
shebang-command,1.2.0,MIT
shebang-regex,1.0.0,MIT
-sidekiq,5.1.3,LGPL
+sidekiq,5.2.1,LGPL
sidekiq-cron,0.6.0,MIT
-sidekiq-limit_fetch,3.4.0,MIT
signal-exit,3.0.2,ISC
-signet,0.8.1,Apache 2.0
+signet,0.11.0,Apache 2.0
slack-notifier,1.5.1,MIT
-slash,1.0.0,MIT
+slugify,1.3.1,MIT
smooshpack,0.0.48,LGPL
snapdragon,0.8.1,MIT
snapdragon-node,2.1.1,MIT
@@ -956,7 +985,6 @@ source-map,0.5.0,New BSD
source-map,0.5.7,New BSD
source-map,0.6.1,New BSD
source-map-resolve,0.5.1,MIT
-source-map-support,0.4.18,MIT
source-map-url,0.4.0,MIT
split-string,3.1.0,MIT
sprockets,3.7.2,MIT
@@ -965,12 +993,12 @@ sql.js,0.4.0,MIT
srcset,1.0.0,MIT
sshkey,1.9.0,MIT
ssri,5.2.4,ISC
+ssri,6.0.1,ISC
state_machines,0.5.0,MIT
state_machines-activemodel,0.5.1,MIT
state_machines-activerecord,0.5.1,MIT
static-extend,0.1.2,MIT
-statuses,1.3.1,MIT
-statuses,1.5.0,MIT
+statuses,1.4.0,MIT
stickyfilljs,2.0.5,MIT
stream-browserify,2.0.1,MIT
stream-each,1.2.2,MIT
@@ -981,17 +1009,17 @@ string-width,1.0.2,MIT
string-width,2.1.1,MIT
string_decoder,0.10.31,MIT
string_decoder,1.1.1,MIT
-stringex,2.8.4,MIT
strip-ansi,3.0.1,MIT
strip-ansi,4.0.0,MIT
+strip-css-comments,3.0.0,MIT
strip-eof,1.0.0,MIT
strip-json-comments,2.0.1,MIT
-style-loader,0.21.0,MIT
+style-loader,0.23.0,MIT
supports-color,2.0.0,MIT
-supports-color,5.4.0,MIT
+supports-color,5.5.0,MIT
svg4everybody,2.1.9,CC0-1.0
sys-filesystem,1.1.6,Artistic 2.0
-tapable,1.0.0,MIT
+tapable,1.1.0,MIT
tar,4.4.4,ISC
temple,0.8.0,MIT
text,1.3.1,MIT
@@ -1011,12 +1039,11 @@ timfel-krb5-auth,0.8.3,LGPL
tiny-emitter,2.0.2,MIT
tmp,0.0.33,MIT
to-arraybuffer,1.0.1,MIT
-to-fast-properties,1.0.3,MIT
+to-fast-properties,2.0.0,MIT
to-object-path,0.3.0,MIT
to-regex,3.0.2,MIT
to-regex-range,2.1.1,MIT
toml-rb,1.0.0,MIT
-traverse,0.6.6,MIT
trim-right,1.0.1,MIT
trollop,2.1.3,MIT
truncato,0.7.10,MIT
@@ -1031,10 +1058,13 @@ uber,0.1.0,MIT
uglifier,2.7.2,MIT
uglify-es,3.3.9,Simplified BSD
uglifyjs-webpack-plugin,1.2.5,MIT
-ultron,1.1.1,MIT
underscore,1.9.0,MIT
unf,0.1.4,BSD
unf_ext,0.0.7.5,MIT
+unicode-canonical-property-names-ecmascript,1.0.4,MIT
+unicode-match-property-ecmascript,1.0.4,MIT
+unicode-match-property-value-ecmascript,1.0.2,MIT
+unicode-property-aliases-ecmascript,1.0.4,MIT
unicorn,5.1.0,ruby
unicorn-worker-killer,0.4.4,ruby
union-value,1.0.0,MIT
@@ -1044,14 +1074,16 @@ unique-slug,2.0.0,ISC
unpipe,1.0.0,MIT
unset-value,1.0.0,MIT
upath,1.1.0,MIT
+uri-js,4.2.2,Simplified BSD
urix,0.1.0,MIT
url,0.11.0,MIT
-url-loader,1.0.1,MIT
+url-loader,1.1.1,MIT
url-parse-lax,3.0.0,MIT
url-to-options,1.0.1,MIT
use,2.0.2,MIT
util,0.10.3,MIT
util-deprecate,1.0.2,MIT
+util.promisify,1.0.0,MIT
utils-merge,1.0.1,MIT
v8-compile-cache,2.0.0,MIT
validates_hostname,1.0.6,MIT
@@ -1061,24 +1093,24 @@ virtus,1.0.5,MIT
visibilityjs,1.2.4,MIT
vm-browserify,0.0.4,MIT
vmstat,2.3.0,MIT
-vue,2.5.16,MIT
+vue,2.5.17,MIT
vue-functional-data-merge,2.0.6,MIT
vue-hot-reload-api,2.3.0,MIT
-vue-loader,15.2.4,MIT
+vue-loader,15.4.2,MIT
vue-resource,1.5.0,MIT
vue-router,3.0.1,MIT
vue-style-loader,4.1.0,MIT
-vue-template-compiler,2.5.16,MIT
+vue-template-compiler,2.5.17,MIT
vue-template-es2015-compiler,1.6.0,MIT
vue-virtual-scroll-list,1.2.5,MIT
vuex,3.0.1,MIT
warden,1.2.7,MIT
watchpack,1.5.0,MIT
-webpack,4.16.0,MIT
-webpack-bundle-analyzer,2.13.1,MIT
-webpack-cli,3.0.8,MIT
-webpack-rails,0.9.10,MIT
-webpack-sources,1.1.0,MIT
+webpack,4.19.1,MIT
+webpack-bundle-analyzer,3.0.2,MIT
+webpack-cli,3.1.0,MIT
+webpack-rails,0.9.11,MIT
+webpack-sources,1.3.0,MIT
webpack-stats-plugin,0.2.1,MIT
which,1.3.0,ISC
which-module,2.0.0,ISC
@@ -1088,14 +1120,14 @@ worker-farm,1.5.2,MIT
worker-loader,2.0.0,MIT
wrap-ansi,2.1.0,MIT
wrappy,1.0.2,ISC
-ws,4.0.0,MIT
+ws,6.0.0,MIT
xml-simple,1.1.5,ruby
xmlhttprequest,1.8.0,MIT
+xregexp,4.0.0,MIT
xtend,4.0.1,MIT
xterm,3.5.0,MIT
-y18n,3.2.1,ISC
y18n,4.0.0,ISC
yallist,2.1.2,ISC
yallist,3.0.2,ISC
-yargs,11.1.0,MIT
-yargs-parser,9.0.2,ISC
+yargs,12.0.2,MIT
+yargs-parser,10.1.0,ISC
diff --git a/vendor/prometheus/values.yaml b/vendor/prometheus/values.yaml
index c432be72163..02ec3e2d9fe 100644
--- a/vendor/prometheus/values.yaml
+++ b/vendor/prometheus/values.yaml
@@ -1,5 +1,7 @@
alertmanager:
enabled: false
+ image:
+ tag: v0.15.2
kubeStateMetrics:
enabled: true
@@ -16,7 +18,7 @@ rbac:
server:
fullnameOverride: "prometheus-prometheus-server"
image:
- tag: v2.1.0
+ tag: v2.4.3
serverFiles:
alerts: {}
diff --git a/yarn.lock b/yarn.lock
index fe4702f3a78..623e38815aa 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,105 +2,672 @@
# yarn lockfile v1
-"@babel/code-frame@7.0.0-beta.44":
- version "7.0.0-beta.44"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.44.tgz#2a02643368de80916162be70865c97774f3adbd9"
+"@babel/code-frame@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8"
+ integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==
dependencies:
- "@babel/highlight" "7.0.0-beta.44"
+ "@babel/highlight" "^7.0.0"
-"@babel/generator@7.0.0-beta.44":
- version "7.0.0-beta.44"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.0.0-beta.44.tgz#c7e67b9b5284afcf69b309b50d7d37f3e5033d42"
+"@babel/core@^7.1.2":
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.1.2.tgz#f8d2a9ceb6832887329a7b60f9d035791400ba4e"
+ integrity sha512-IFeSSnjXdhDaoysIlev//UzHZbdEmm7D0EIH2qtse9xK7mXEZQpYjs2P00XlP1qYsYvid79p+Zgg6tz1mp6iVw==
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ "@babel/generator" "^7.1.2"
+ "@babel/helpers" "^7.1.2"
+ "@babel/parser" "^7.1.2"
+ "@babel/template" "^7.1.2"
+ "@babel/traverse" "^7.1.0"
+ "@babel/types" "^7.1.2"
+ convert-source-map "^1.1.0"
+ debug "^3.1.0"
+ json5 "^0.5.0"
+ lodash "^4.17.10"
+ resolve "^1.3.2"
+ semver "^5.4.1"
+ source-map "^0.5.0"
+
+"@babel/generator@^7.0.0", "@babel/generator@^7.1.2":
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.1.2.tgz#fde75c072575ce7abbd97322e8fef5bae67e4630"
+ integrity sha512-70A9HWLS/1RHk3Ck8tNHKxOoKQuSKocYgwDN85Pyl/RBduss6AKxUR7RIZ/lzduQMSYfWEM4DDBu6A+XGbkFig==
dependencies:
- "@babel/types" "7.0.0-beta.44"
+ "@babel/types" "^7.1.2"
jsesc "^2.5.1"
- lodash "^4.2.0"
+ lodash "^4.17.10"
source-map "^0.5.0"
trim-right "^1.0.1"
-"@babel/helper-function-name@7.0.0-beta.44":
- version "7.0.0-beta.44"
- resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.44.tgz#e18552aaae2231100a6e485e03854bc3532d44dd"
+"@babel/helper-annotate-as-pure@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32"
+ integrity sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==
dependencies:
- "@babel/helper-get-function-arity" "7.0.0-beta.44"
- "@babel/template" "7.0.0-beta.44"
- "@babel/types" "7.0.0-beta.44"
+ "@babel/types" "^7.0.0"
-"@babel/helper-get-function-arity@7.0.0-beta.44":
- version "7.0.0-beta.44"
- resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.44.tgz#d03ca6dd2b9f7b0b1e6b32c56c72836140db3a15"
+"@babel/helper-builder-binary-assignment-operator-visitor@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz#6b69628dfe4087798e0c4ed98e3d4a6b2fbd2f5f"
+ integrity sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==
dependencies:
- "@babel/types" "7.0.0-beta.44"
+ "@babel/helper-explode-assignable-expression" "^7.1.0"
+ "@babel/types" "^7.0.0"
-"@babel/helper-split-export-declaration@7.0.0-beta.44":
- version "7.0.0-beta.44"
- resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0-beta.44.tgz#c0b351735e0fbcb3822c8ad8db4e583b05ebd9dc"
+"@babel/helper-call-delegate@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.1.0.tgz#6a957f105f37755e8645343d3038a22e1449cc4a"
+ integrity sha512-YEtYZrw3GUK6emQHKthltKNZwszBcHK58Ygcis+gVUrF4/FmTVr5CCqQNSfmvg2y+YDEANyYoaLz/SHsnusCwQ==
dependencies:
- "@babel/types" "7.0.0-beta.44"
+ "@babel/helper-hoist-variables" "^7.0.0"
+ "@babel/traverse" "^7.1.0"
+ "@babel/types" "^7.0.0"
-"@babel/highlight@7.0.0-beta.44":
- version "7.0.0-beta.44"
- resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0-beta.44.tgz#18c94ce543916a80553edcdcf681890b200747d5"
+"@babel/helper-define-map@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.1.0.tgz#3b74caec329b3c80c116290887c0dd9ae468c20c"
+ integrity sha512-yPPcW8dc3gZLN+U1mhYV91QU3n5uTbx7DUdf8NnPbjS0RMwBuHi9Xt2MUgppmNz7CJxTBWsGczTiEp1CSOTPRg==
+ dependencies:
+ "@babel/helper-function-name" "^7.1.0"
+ "@babel/types" "^7.0.0"
+ lodash "^4.17.10"
+
+"@babel/helper-explode-assignable-expression@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz#537fa13f6f1674df745b0c00ec8fe4e99681c8f6"
+ integrity sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==
+ dependencies:
+ "@babel/traverse" "^7.1.0"
+ "@babel/types" "^7.0.0"
+
+"@babel/helper-function-name@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53"
+ integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==
+ dependencies:
+ "@babel/helper-get-function-arity" "^7.0.0"
+ "@babel/template" "^7.1.0"
+ "@babel/types" "^7.0.0"
+
+"@babel/helper-get-function-arity@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3"
+ integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==
+ dependencies:
+ "@babel/types" "^7.0.0"
+
+"@babel/helper-hoist-variables@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.0.0.tgz#46adc4c5e758645ae7a45deb92bab0918c23bb88"
+ integrity sha512-Ggv5sldXUeSKsuzLkddtyhyHe2YantsxWKNi7A+7LeD12ExRDWTRk29JCXpaHPAbMaIPZSil7n+lq78WY2VY7w==
+ dependencies:
+ "@babel/types" "^7.0.0"
+
+"@babel/helper-member-expression-to-functions@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz#8cd14b0a0df7ff00f009e7d7a436945f47c7a16f"
+ integrity sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==
+ dependencies:
+ "@babel/types" "^7.0.0"
+
+"@babel/helper-module-imports@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d"
+ integrity sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==
+ dependencies:
+ "@babel/types" "^7.0.0"
+
+"@babel/helper-module-transforms@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.1.0.tgz#470d4f9676d9fad50b324cdcce5fbabbc3da5787"
+ integrity sha512-0JZRd2yhawo79Rcm4w0LwSMILFmFXjugG3yqf+P/UsKsRS1mJCmMwwlHDlMg7Avr9LrvSpp4ZSULO9r8jpCzcw==
+ dependencies:
+ "@babel/helper-module-imports" "^7.0.0"
+ "@babel/helper-simple-access" "^7.1.0"
+ "@babel/helper-split-export-declaration" "^7.0.0"
+ "@babel/template" "^7.1.0"
+ "@babel/types" "^7.0.0"
+ lodash "^4.17.10"
+
+"@babel/helper-optimise-call-expression@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz#a2920c5702b073c15de51106200aa8cad20497d5"
+ integrity sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==
+ dependencies:
+ "@babel/types" "^7.0.0"
+
+"@babel/helper-plugin-utils@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250"
+ integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==
+
+"@babel/helper-regex@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.0.0.tgz#2c1718923b57f9bbe64705ffe5640ac64d9bdb27"
+ integrity sha512-TR0/N0NDCcUIUEbqV6dCO+LptmmSQFQ7q70lfcEB4URsjD0E1HzicrwUH+ap6BAQ2jhCX9Q4UqZy4wilujWlkg==
+ dependencies:
+ lodash "^4.17.10"
+
+"@babel/helper-remap-async-to-generator@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz#361d80821b6f38da75bd3f0785ece20a88c5fe7f"
+ integrity sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.0.0"
+ "@babel/helper-wrap-function" "^7.1.0"
+ "@babel/template" "^7.1.0"
+ "@babel/traverse" "^7.1.0"
+ "@babel/types" "^7.0.0"
+
+"@babel/helper-replace-supers@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.1.0.tgz#5fc31de522ec0ef0899dc9b3e7cf6a5dd655f362"
+ integrity sha512-BvcDWYZRWVuDeXTYZWxekQNO5D4kO55aArwZOTFXw6rlLQA8ZaDicJR1sO47h+HrnCiDFiww0fSPV0d713KBGQ==
+ dependencies:
+ "@babel/helper-member-expression-to-functions" "^7.0.0"
+ "@babel/helper-optimise-call-expression" "^7.0.0"
+ "@babel/traverse" "^7.1.0"
+ "@babel/types" "^7.0.0"
+
+"@babel/helper-simple-access@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz#65eeb954c8c245beaa4e859da6188f39d71e585c"
+ integrity sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==
+ dependencies:
+ "@babel/template" "^7.1.0"
+ "@babel/types" "^7.0.0"
+
+"@babel/helper-split-export-declaration@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz#3aae285c0311c2ab095d997b8c9a94cad547d813"
+ integrity sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==
+ dependencies:
+ "@babel/types" "^7.0.0"
+
+"@babel/helper-wrap-function@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.1.0.tgz#8cf54e9190706067f016af8f75cb3df829cc8c66"
+ integrity sha512-R6HU3dete+rwsdAfrOzTlE9Mcpk4RjU3aX3gi9grtmugQY0u79X7eogUvfXA5sI81Mfq1cn6AgxihfN33STjJA==
+ dependencies:
+ "@babel/helper-function-name" "^7.1.0"
+ "@babel/template" "^7.1.0"
+ "@babel/traverse" "^7.1.0"
+ "@babel/types" "^7.0.0"
+
+"@babel/helpers@^7.1.2":
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.1.2.tgz#ab752e8c35ef7d39987df4e8586c63b8846234b5"
+ integrity sha512-Myc3pUE8eswD73aWcartxB16K6CGmHDv9KxOmD2CeOs/FaEAQodr3VYGmlvOmog60vNQ2w8QbatuahepZwrHiA==
+ dependencies:
+ "@babel/template" "^7.1.2"
+ "@babel/traverse" "^7.1.0"
+ "@babel/types" "^7.1.2"
+
+"@babel/highlight@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4"
+ integrity sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==
dependencies:
chalk "^2.0.0"
esutils "^2.0.2"
- js-tokens "^3.0.0"
-
-"@babel/template@7.0.0-beta.44":
- version "7.0.0-beta.44"
- resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.44.tgz#f8832f4fdcee5d59bf515e595fc5106c529b394f"
- dependencies:
- "@babel/code-frame" "7.0.0-beta.44"
- "@babel/types" "7.0.0-beta.44"
- babylon "7.0.0-beta.44"
- lodash "^4.2.0"
-
-"@babel/traverse@7.0.0-beta.44":
- version "7.0.0-beta.44"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.44.tgz#a970a2c45477ad18017e2e465a0606feee0d2966"
- dependencies:
- "@babel/code-frame" "7.0.0-beta.44"
- "@babel/generator" "7.0.0-beta.44"
- "@babel/helper-function-name" "7.0.0-beta.44"
- "@babel/helper-split-export-declaration" "7.0.0-beta.44"
- "@babel/types" "7.0.0-beta.44"
- babylon "7.0.0-beta.44"
+ js-tokens "^4.0.0"
+
+"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.1.2":
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.1.2.tgz#85c5c47af6d244fab77bce6b9bd830e38c978409"
+ integrity sha512-x5HFsW+E/nQalGMw7hu+fvPqnBeBaIr0lWJ2SG0PPL2j+Pm9lYvCrsZJGIgauPIENx0v10INIyFjmSNUD/gSqQ==
+
+"@babel/plugin-proposal-async-generator-functions@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.1.0.tgz#41c1a702e10081456e23a7b74d891922dd1bb6ce"
+ integrity sha512-Fq803F3Jcxo20MXUSDdmZZXrPe6BWyGcWBPPNB/M7WaUYESKDeKMOGIxEzQOjGSmW/NWb6UaPZrtTB2ekhB/ew==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-remap-async-to-generator" "^7.1.0"
+ "@babel/plugin-syntax-async-generators" "^7.0.0"
+
+"@babel/plugin-proposal-class-properties@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.1.0.tgz#9af01856b1241db60ec8838d84691aa0bd1e8df4"
+ integrity sha512-/PCJWN+CKt5v1xcGn4vnuu13QDoV+P7NcICP44BoonAJoPSGwVkgrXihFIQGiEjjPlUDBIw1cM7wYFLARS2/hw==
+ dependencies:
+ "@babel/helper-function-name" "^7.1.0"
+ "@babel/helper-member-expression-to-functions" "^7.0.0"
+ "@babel/helper-optimise-call-expression" "^7.0.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-replace-supers" "^7.1.0"
+ "@babel/plugin-syntax-class-properties" "^7.0.0"
+
+"@babel/plugin-proposal-json-strings@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.0.0.tgz#3b4d7b5cf51e1f2e70f52351d28d44fc2970d01e"
+ integrity sha512-kfVdUkIAGJIVmHmtS/40i/fg/AGnw/rsZBCaapY5yjeO5RA9m165Xbw9KMOu2nqXP5dTFjEjHdfNdoVcHv133Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/plugin-syntax-json-strings" "^7.0.0"
+
+"@babel/plugin-proposal-object-rest-spread@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.0.0.tgz#9a17b547f64d0676b6c9cecd4edf74a82ab85e7e"
+ integrity sha512-14fhfoPcNu7itSen7Py1iGN0gEm87hX/B+8nZPqkdmANyyYWYMY2pjA3r8WXbWVKMzfnSNS0xY8GVS0IjXi/iw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/plugin-syntax-object-rest-spread" "^7.0.0"
+
+"@babel/plugin-proposal-optional-catch-binding@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.0.0.tgz#b610d928fe551ff7117d42c8bb410eec312a6425"
+ integrity sha512-JPqAvLG1s13B/AuoBjdBYvn38RqW6n1TzrQO839/sIpqLpbnXKacsAgpZHzLD83Sm8SDXMkkrAvEnJ25+0yIpw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.0.0"
+
+"@babel/plugin-proposal-unicode-property-regex@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.0.0.tgz#498b39cd72536cd7c4b26177d030226eba08cd33"
+ integrity sha512-tM3icA6GhC3ch2SkmSxv7J/hCWKISzwycub6eGsDrFDgukD4dZ/I+x81XgW0YslS6mzNuQ1Cbzh5osjIMgepPQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-regex" "^7.0.0"
+ regexpu-core "^4.2.0"
+
+"@babel/plugin-syntax-async-generators@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.0.0.tgz#bf0891dcdbf59558359d0c626fdc9490e20bc13c"
+ integrity sha512-im7ged00ddGKAjcZgewXmp1vxSZQQywuQXe2B1A7kajjZmDeY/ekMPmWr9zJgveSaQH0k7BcGrojQhcK06l0zA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-class-properties@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.0.0.tgz#e051af5d300cbfbcec4a7476e37a803489881634"
+ integrity sha512-cR12g0Qzn4sgkjrbrzWy2GE7m9vMl/sFkqZ3gIpAQdrvPDnLM8180i+ANDFIXfjHo9aqp0ccJlQ0QNZcFUbf9w==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-dynamic-import@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.0.0.tgz#6dfb7d8b6c3be14ce952962f658f3b7eb54c33ee"
+ integrity sha512-Gt9xNyRrCHCiyX/ZxDGOcBnlJl0I3IWicpZRC4CdC0P5a/I07Ya2OAMEBU+J7GmRFVmIetqEYRko6QYRuKOESw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-import-meta@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.0.0.tgz#ca946b73216c29c39a55ef2d739097fee8a85d69"
+ integrity sha512-FEoGvhXVAiWzpDjyZIlBGzKyNk/lnRPy7aPke3PjVkiAY0QFsvFfkjUg5diRwVfowBA8SJqvFt0ZoXNSjl70hQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-json-strings@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.0.0.tgz#0d259a68090e15b383ce3710e01d5b23f3770cbd"
+ integrity sha512-UlSfNydC+XLj4bw7ijpldc1uZ/HB84vw+U6BTuqMdIEmz/LDe63w/GHtpQMdXWdqQZFeAI9PjnHe/vDhwirhKA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-object-rest-spread@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.0.0.tgz#37d8fbcaf216bd658ea1aebbeb8b75e88ebc549b"
+ integrity sha512-5A0n4p6bIiVe5OvQPxBnesezsgFJdHhSs3uFSvaPdMqtsovajLZ+G2vZyvNe10EzJBWWo3AcHGKhAFUxqwp2dw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-syntax-optional-catch-binding@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.0.0.tgz#886f72008b3a8b185977f7cb70713b45e51ee475"
+ integrity sha512-Wc+HVvwjcq5qBg1w5RG9o9RVzmCaAg/Vp0erHCKpAYV8La6I94o4GQAmFYNmkzoMO6gzoOSulpKeSSz6mPEoZw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-arrow-functions@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.0.0.tgz#a6c14875848c68a3b4b3163a486535ef25c7e749"
+ integrity sha512-2EZDBl1WIO/q4DIkIp4s86sdp4ZifL51MoIviLY/gG/mLSuOIEg7J8o6mhbxOTvUJkaN50n+8u41FVsr5KLy/w==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-async-to-generator@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.1.0.tgz#109e036496c51dd65857e16acab3bafdf3c57811"
+ integrity sha512-rNmcmoQ78IrvNCIt/R9U+cixUHeYAzgusTFgIAv+wQb9HJU4szhpDD6e5GCACmj/JP5KxuCwM96bX3L9v4ZN/g==
+ dependencies:
+ "@babel/helper-module-imports" "^7.0.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-remap-async-to-generator" "^7.1.0"
+
+"@babel/plugin-transform-block-scoped-functions@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.0.0.tgz#482b3f75103927e37288b3b67b65f848e2aa0d07"
+ integrity sha512-AOBiyUp7vYTqz2Jibe1UaAWL0Hl9JUXEgjFvvvcSc9MVDItv46ViXFw2F7SVt1B5k+KWjl44eeXOAk3UDEaJjQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-block-scoping@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.0.0.tgz#1745075edffd7cdaf69fab2fb6f9694424b7e9bc"
+ integrity sha512-GWEMCrmHQcYWISilUrk9GDqH4enf3UmhOEbNbNrlNAX1ssH3MsS1xLOS6rdjRVPgA7XXVPn87tRkdTEoA/dxEg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ lodash "^4.17.10"
+
+"@babel/plugin-transform-classes@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.1.0.tgz#ab3f8a564361800cbc8ab1ca6f21108038432249"
+ integrity sha512-rNaqoD+4OCBZjM7VaskladgqnZ1LO6o2UxuWSDzljzW21pN1KXkB7BstAVweZdxQkHAujps5QMNOTWesBciKFg==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.0.0"
+ "@babel/helper-define-map" "^7.1.0"
+ "@babel/helper-function-name" "^7.1.0"
+ "@babel/helper-optimise-call-expression" "^7.0.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-replace-supers" "^7.1.0"
+ "@babel/helper-split-export-declaration" "^7.0.0"
+ globals "^11.1.0"
+
+"@babel/plugin-transform-computed-properties@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.0.0.tgz#2fbb8900cd3e8258f2a2ede909b90e7556185e31"
+ integrity sha512-ubouZdChNAv4AAWAgU7QKbB93NU5sHwInEWfp+/OzJKA02E6Woh9RVoX4sZrbRwtybky/d7baTUqwFx+HgbvMA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-destructuring@^7.0.0":
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.1.2.tgz#5fa77d473f5a0a3f5266ad7ce2e8c995a164d60a"
+ integrity sha512-cvToXvp/OsYxtEn57XJu9BvsGSEYjAh9UeUuXpoi7x6QHB7YdWyQ4lRU/q0Fu1IJNT0o0u4FQ1DMQBzJ8/8vZg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-dotall-regex@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.0.0.tgz#73a24da69bc3c370251f43a3d048198546115e58"
+ integrity sha512-00THs8eJxOJUFVx1w8i1MBF4XH4PsAjKjQ1eqN/uCH3YKwP21GCKfrn6YZFZswbOk9+0cw1zGQPHVc1KBlSxig==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-regex" "^7.0.0"
+ regexpu-core "^4.1.3"
+
+"@babel/plugin-transform-duplicate-keys@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.0.0.tgz#a0601e580991e7cace080e4cf919cfd58da74e86"
+ integrity sha512-w2vfPkMqRkdxx+C71ATLJG30PpwtTpW7DDdLqYt2acXU7YjztzeWW2Jk1T6hKqCLYCcEA5UQM/+xTAm+QCSnuQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-exponentiation-operator@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.1.0.tgz#9c34c2ee7fd77e02779cfa37e403a2e1003ccc73"
+ integrity sha512-uZt9kD1Pp/JubkukOGQml9tqAeI8NkE98oZnHZ2qHRElmeKCodbTZgOEUtujSCSLhHSBWbzNiFSDIMC4/RBTLQ==
+ dependencies:
+ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.1.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-for-of@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.0.0.tgz#f2ba4eadb83bd17dc3c7e9b30f4707365e1c3e39"
+ integrity sha512-TlxKecN20X2tt2UEr2LNE6aqA0oPeMT1Y3cgz8k4Dn1j5ObT8M3nl9aA37LLklx0PBZKETC9ZAf9n/6SujTuXA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-function-name@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.1.0.tgz#29c5550d5c46208e7f730516d41eeddd4affadbb"
+ integrity sha512-VxOa1TMlFMtqPW2IDYZQaHsFrq/dDoIjgN098NowhexhZcz3UGlvPgZXuE1jEvNygyWyxRacqDpCZt+par1FNg==
+ dependencies:
+ "@babel/helper-function-name" "^7.1.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-literals@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.0.0.tgz#2aec1d29cdd24c407359c930cdd89e914ee8ff86"
+ integrity sha512-1NTDBWkeNXgpUcyoVFxbr9hS57EpZYXpje92zv0SUzjdu3enaRwF/l3cmyRnXLtIdyJASyiS6PtybK+CgKf7jA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-modules-amd@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.1.0.tgz#f9e0a7072c12e296079b5a59f408ff5b97bf86a8"
+ integrity sha512-wt8P+xQ85rrnGNr2x1iV3DW32W8zrB6ctuBkYBbf5/ZzJY99Ob4MFgsZDFgczNU76iy9PWsy4EuxOliDjdKw6A==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.1.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-modules-commonjs@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.1.0.tgz#0a9d86451cbbfb29bd15186306897c67f6f9a05c"
+ integrity sha512-wtNwtMjn1XGwM0AXPspQgvmE6msSJP15CX2RVfpTSTNPLhKhaOjaIfBaVfj4iUZ/VrFSodcFedwtPg/NxwQlPA==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.1.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-simple-access" "^7.1.0"
+
+"@babel/plugin-transform-modules-systemjs@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.0.0.tgz#8873d876d4fee23209decc4d1feab8f198cf2df4"
+ integrity sha512-8EDKMAsitLkiF/D4Zhe9CHEE2XLh4bfLbb9/Zf3FgXYQOZyZYyg7EAel/aT2A7bHv62jwHf09q2KU/oEexr83g==
+ dependencies:
+ "@babel/helper-hoist-variables" "^7.0.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-modules-umd@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.1.0.tgz#a29a7d85d6f28c3561c33964442257cc6a21f2a8"
+ integrity sha512-enrRtn5TfRhMmbRwm7F8qOj0qEYByqUvTttPEGimcBH4CJHphjyK1Vg7sdU7JjeEmgSpM890IT/efS2nMHwYig==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.1.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-new-target@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.0.0.tgz#ae8fbd89517fa7892d20e6564e641e8770c3aa4a"
+ integrity sha512-yin069FYjah+LbqfGeTfzIBODex/e++Yfa0rH0fpfam9uTbuEeEOx5GLGr210ggOV77mVRNoeqSYqeuaqSzVSw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-object-super@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.1.0.tgz#b1ae194a054b826d8d4ba7ca91486d4ada0f91bb"
+ integrity sha512-/O02Je1CRTSk2SSJaq0xjwQ8hG4zhZGNjE8psTsSNPXyLRCODv7/PBozqT5AmQMzp7MI3ndvMhGdqp9c96tTEw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-replace-supers" "^7.1.0"
+
+"@babel/plugin-transform-parameters@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.1.0.tgz#44f492f9d618c9124026e62301c296bf606a7aed"
+ integrity sha512-vHV7oxkEJ8IHxTfRr3hNGzV446GAb+0hgbA7o/0Jd76s+YzccdWuTU296FOCOl/xweU4t/Ya4g41yWz80RFCRw==
+ dependencies:
+ "@babel/helper-call-delegate" "^7.1.0"
+ "@babel/helper-get-function-arity" "^7.0.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-regenerator@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.0.0.tgz#5b41686b4ed40bef874d7ed6a84bdd849c13e0c1"
+ integrity sha512-sj2qzsEx8KDVv1QuJc/dEfilkg3RRPvPYx/VnKLtItVQRWt1Wqf5eVCOLZm29CiGFfYYsA3VPjfizTCV0S0Dlw==
+ dependencies:
+ regenerator-transform "^0.13.3"
+
+"@babel/plugin-transform-shorthand-properties@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.0.0.tgz#85f8af592dcc07647541a0350e8c95c7bf419d15"
+ integrity sha512-g/99LI4vm5iOf5r1Gdxq5Xmu91zvjhEG5+yZDJW268AZELAu4J1EiFLnkSG3yuUsZyOipVOVUKoGPYwfsTymhw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-spread@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.0.0.tgz#93583ce48dd8c85e53f3a46056c856e4af30b49b"
+ integrity sha512-L702YFy2EvirrR4shTj0g2xQp7aNwZoWNCkNu2mcoU0uyzMl0XRwDSwzB/xp6DSUFiBmEXuyAyEN16LsgVqGGQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-sticky-regex@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.0.0.tgz#30a9d64ac2ab46eec087b8530535becd90e73366"
+ integrity sha512-LFUToxiyS/WD+XEWpkx/XJBrUXKewSZpzX68s+yEOtIbdnsRjpryDw9U06gYc6klYEij/+KQVRnD3nz3AoKmjw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-regex" "^7.0.0"
+
+"@babel/plugin-transform-template-literals@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.0.0.tgz#084f1952efe5b153ddae69eb8945f882c7a97c65"
+ integrity sha512-vA6rkTCabRZu7Nbl9DfLZE1imj4tzdWcg5vtdQGvj+OH9itNNB6hxuRMHuIY8SGnEt1T9g5foqs9LnrHzsqEFg==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.0.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-typeof-symbol@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.0.0.tgz#4dcf1e52e943e5267b7313bff347fdbe0f81cec9"
+ integrity sha512-1r1X5DO78WnaAIvs5uC48t41LLckxsYklJrZjNKcevyz83sF2l4RHbw29qrCPr/6ksFsdfRpT/ZgxNWHXRnffg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+
+"@babel/plugin-transform-unicode-regex@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.0.0.tgz#c6780e5b1863a76fe792d90eded9fcd5b51d68fc"
+ integrity sha512-uJBrJhBOEa3D033P95nPHu3nbFwFE9ZgXsfEitzoIXIwqAZWk7uXcg06yFKXz9FSxBH5ucgU/cYdX0IV8ldHKw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/helper-regex" "^7.0.0"
+ regexpu-core "^4.1.3"
+
+"@babel/preset-env@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.1.0.tgz#e67ea5b0441cfeab1d6f41e9b5c79798800e8d11"
+ integrity sha512-ZLVSynfAoDHB/34A17/JCZbyrzbQj59QC1Anyueb4Bwjh373nVPq5/HMph0z+tCmcDjXDe+DlKQq9ywQuvWrQg==
+ dependencies:
+ "@babel/helper-module-imports" "^7.0.0"
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/plugin-proposal-async-generator-functions" "^7.1.0"
+ "@babel/plugin-proposal-json-strings" "^7.0.0"
+ "@babel/plugin-proposal-object-rest-spread" "^7.0.0"
+ "@babel/plugin-proposal-optional-catch-binding" "^7.0.0"
+ "@babel/plugin-proposal-unicode-property-regex" "^7.0.0"
+ "@babel/plugin-syntax-async-generators" "^7.0.0"
+ "@babel/plugin-syntax-object-rest-spread" "^7.0.0"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.0.0"
+ "@babel/plugin-transform-arrow-functions" "^7.0.0"
+ "@babel/plugin-transform-async-to-generator" "^7.1.0"
+ "@babel/plugin-transform-block-scoped-functions" "^7.0.0"
+ "@babel/plugin-transform-block-scoping" "^7.0.0"
+ "@babel/plugin-transform-classes" "^7.1.0"
+ "@babel/plugin-transform-computed-properties" "^7.0.0"
+ "@babel/plugin-transform-destructuring" "^7.0.0"
+ "@babel/plugin-transform-dotall-regex" "^7.0.0"
+ "@babel/plugin-transform-duplicate-keys" "^7.0.0"
+ "@babel/plugin-transform-exponentiation-operator" "^7.1.0"
+ "@babel/plugin-transform-for-of" "^7.0.0"
+ "@babel/plugin-transform-function-name" "^7.1.0"
+ "@babel/plugin-transform-literals" "^7.0.0"
+ "@babel/plugin-transform-modules-amd" "^7.1.0"
+ "@babel/plugin-transform-modules-commonjs" "^7.1.0"
+ "@babel/plugin-transform-modules-systemjs" "^7.0.0"
+ "@babel/plugin-transform-modules-umd" "^7.1.0"
+ "@babel/plugin-transform-new-target" "^7.0.0"
+ "@babel/plugin-transform-object-super" "^7.1.0"
+ "@babel/plugin-transform-parameters" "^7.1.0"
+ "@babel/plugin-transform-regenerator" "^7.0.0"
+ "@babel/plugin-transform-shorthand-properties" "^7.0.0"
+ "@babel/plugin-transform-spread" "^7.0.0"
+ "@babel/plugin-transform-sticky-regex" "^7.0.0"
+ "@babel/plugin-transform-template-literals" "^7.0.0"
+ "@babel/plugin-transform-typeof-symbol" "^7.0.0"
+ "@babel/plugin-transform-unicode-regex" "^7.0.0"
+ browserslist "^4.1.0"
+ invariant "^2.2.2"
+ js-levenshtein "^1.1.3"
+ semver "^5.3.0"
+
+"@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.1.2":
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.1.2.tgz#090484a574fef5a2d2d7726a674eceda5c5b5644"
+ integrity sha512-SY1MmplssORfFiLDcOETrW7fCLl+PavlwMh92rrGcikQaRq4iWPVH0MpwPpY3etVMx6RnDjXtr6VZYr/IbP/Ag==
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ "@babel/parser" "^7.1.2"
+ "@babel/types" "^7.1.2"
+
+"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0":
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.1.0.tgz#503ec6669387efd182c3888c4eec07bcc45d91b2"
+ integrity sha512-bwgln0FsMoxm3pLOgrrnGaXk18sSM9JNf1/nHC/FksmNGFbYnPWY4GYCfLxyP1KRmfsxqkRpfoa6xr6VuuSxdw==
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ "@babel/generator" "^7.0.0"
+ "@babel/helper-function-name" "^7.1.0"
+ "@babel/helper-split-export-declaration" "^7.0.0"
+ "@babel/parser" "^7.1.0"
+ "@babel/types" "^7.0.0"
debug "^3.1.0"
globals "^11.1.0"
- invariant "^2.2.0"
- lodash "^4.2.0"
+ lodash "^4.17.10"
-"@babel/types@7.0.0-beta.44":
- version "7.0.0-beta.44"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.44.tgz#6b1b164591f77dec0a0342aca995f2d046b3a757"
+"@babel/types@^7.0.0", "@babel/types@^7.1.2":
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.1.2.tgz#183e7952cf6691628afdc2e2b90d03240bac80c0"
+ integrity sha512-pb1I05sZEKiSlMUV9UReaqsCPUpgbHHHu2n1piRm7JkuBkm6QxcaIzKu6FMnMtCbih/cEYTR+RGYYC96Yk9HAg==
dependencies:
esutils "^2.0.2"
- lodash "^4.2.0"
+ lodash "^4.17.10"
to-fast-properties "^2.0.0"
-"@gitlab-org/gitlab-svgs@^1.23.0", "@gitlab-org/gitlab-svgs@^1.29.0":
- version "1.29.0"
- resolved "https://registry.yarnpkg.com/@gitlab-org/gitlab-svgs/-/gitlab-svgs-1.29.0.tgz#03b65b513f9099bbda6ecf94d673a2952f8c6c70"
-
-"@gitlab-org/gitlab-ui@^1.5.0":
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/@gitlab-org/gitlab-ui/-/gitlab-ui-1.5.0.tgz#320ba164ba8812ff64f94b1cae79a7b749f5bc03"
+"@gitlab/eslint-config@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/eslint-config/-/eslint-config-1.2.0.tgz#115568a70edabbc024f1bc13ba1ba499a9ba05a9"
+ integrity sha512-TnZO5T7JjLQjw30aIGtKIsAX4pRnSbqOir3Ji5zPwtCVWY53DnG6Lcesgy7WYdsnnkt3oQPXFTOZlkymUs2PsA==
+ dependencies:
+ babel-eslint "^10.0.1"
+ eslint-config-airbnb-base "^13.1.0"
+ eslint-config-prettier "^3.1.0"
+ eslint-plugin-filenames "^1.3.2"
+ eslint-plugin-import "^2.14.0"
+ eslint-plugin-promise "^4.0.1"
+ eslint-plugin-vue "^5.0.0-beta.3"
+
+"@gitlab/svgs@^1.40.0":
+ version "1.40.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.40.0.tgz#58d7545fde3a7af3c290b419d1de2405973e58c5"
+ integrity sha512-Y5QkaZH5N84qSNSGPxaj+NNlI4kthUNet7eRS1QCnaskwcvuWd/vF0xYCPd/tbRnK9MIhkKzhbxatUYDZVgXTQ==
+
+"@gitlab/ui@^1.11.0":
+ version "1.11.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-1.11.0.tgz#b771c2c3d627cf9efbe98c71ee5739624f2ff51f"
+ integrity sha512-hGMHM45kcv9725R6G+n/HxvF3KfVb9oBGRNf1+4n3xAGmtXJ2NlPdIXIsDaye3EeVF9PTOtjLuaqrcp6AGNqZg==
dependencies:
- "@gitlab-org/gitlab-svgs" "^1.23.0"
+ babel-standalone "^6.26.0"
bootstrap-vue "^2.0.0-rc.11"
+ copy-to-clipboard "^3.0.8"
+ highlight.js "^9.13.1"
+ js-beautify "^1.8.8"
+ lodash "^4.17.11"
+ url-search-params-polyfill "^5.0.0"
vue "^2.5.16"
+ vue-loader "^15.4.2"
"@sindresorhus/is@^0.7.0":
version "0.7.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd"
+ integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==
+
+"@types/async@2.0.50":
+ version "2.0.50"
+ resolved "https://registry.yarnpkg.com/@types/async/-/async-2.0.50.tgz#117540e026d64e1846093abbd5adc7e27fda7bcb"
+ integrity sha512-VMhZMMQgV1zsR+lX/0IBfAk+8Eb7dPVMWiQGFAt3qjo5x7Ml6b77jUo0e1C3ToD+XRDXqtrfw+6AB0uUsPEr3Q==
"@types/events@*":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86"
+ integrity sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==
"@types/glob@^5":
version "5.0.35"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-5.0.35.tgz#1ae151c802cece940443b5ac246925c85189f32a"
+ integrity sha512-wc+VveszMLyMWFvXLkloixT4n0harUIVZjnpzztaZ0nKLuul7Z32iMt2fUFGAaZ4y1XWjFRMtCI5ewvyh4aIeg==
dependencies:
"@types/events" "*"
"@types/minimatch" "*"
@@ -109,22 +676,37 @@
"@types/jquery@^2.0.40":
version "2.0.48"
resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-2.0.48.tgz#3e90d8cde2d29015e5583017f7830cb3975b2eef"
+ integrity sha512-nNLzUrVjaRV/Ds1eHZLYTd7IZxs38cwwLSaqMJj8OTXY8xNUbxSK69bi9cMLvQ7dm/IBeQ1wHwQ0S1uYa0rd2w==
"@types/minimatch@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
+ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==
-"@types/node@*":
- version "10.5.2"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-10.5.2.tgz#f19f05314d5421fe37e74153254201a7bf00a707"
+"@types/node@*", "@types/node@^10.11.7":
+ version "10.12.9"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.9.tgz#a07bfa74331471e1dc22a47eb72026843f7b95c8"
+ integrity sha512-eajkMXG812/w3w4a1OcBlaTwsFPO5F7fJ/amy+tieQxEMWBlbV1JGSjkFM+zkHNf81Cad+dfIRA+IBkvmvdAeA==
"@types/parse5@^5":
version "5.0.0"
resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.0.tgz#9ae2106efc443d7c1e26570aa8247828c9c80f11"
+ integrity sha512-J5D3z703XTDIGQFYXsnU9uRCW9e9mMEFO0Kpe6kykyiboqziru/RlZ0hM2P+PKTG4NHG1SjLrqae/NrV2iJApQ==
-"@vue/component-compiler-utils@^1.2.1":
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-1.2.1.tgz#3d543baa75cfe5dab96e29415b78366450156ef6"
+"@types/semver@^5.5.0":
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45"
+ integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==
+
+"@types/zen-observable@^0.8.0":
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.0.tgz#8b63ab7f1aa5321248aad5ac890a485656dcea4d"
+ integrity sha512-te5lMAWii1uEJ4FwLjzdlbw3+n0FZNOvFXHxQDKeT0dilh7HOzdMzV2TrJVUzq8ep7J4Na8OUYPRLSQkJHAlrg==
+
+"@vue/component-compiler-utils@^2.0.0":
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-2.2.0.tgz#bbbb7ed38a9a8a7c93abe7ef2e54a90a04b631b4"
+ integrity sha512-pS4zlcdD7BvedyB+IfiTfrbi6C977UMIfulSk8r6uL0BU46ZE2+fUj/zbSNSfVxeaj9ElmnSni5OMwF9np+b+w==
dependencies:
consolidate "^0.15.1"
hash-sum "^1.0.2"
@@ -132,352 +714,488 @@
merge-source-map "^1.1.0"
postcss "^6.0.20"
postcss-selector-parser "^3.1.1"
- prettier "^1.11.1"
+ prettier "1.13.7"
source-map "^0.5.6"
vue-template-es2015-compiler "^1.6.0"
-"@webassemblyjs/ast@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.5.13.tgz#81155a570bd5803a30ec31436bc2c9c0ede38f25"
- dependencies:
- "@webassemblyjs/helper-module-context" "1.5.13"
- "@webassemblyjs/helper-wasm-bytecode" "1.5.13"
- "@webassemblyjs/wast-parser" "1.5.13"
- debug "^3.1.0"
- mamacro "^0.0.3"
-
-"@webassemblyjs/floating-point-hex-parser@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.5.13.tgz#29ce0baa97411f70e8cce68ce9c0f9d819a4e298"
-
-"@webassemblyjs/helper-api-error@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.5.13.tgz#e49b051d67ee19a56e29b9aa8bd949b5b4442a59"
-
-"@webassemblyjs/helper-buffer@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.5.13.tgz#873bb0a1b46449231137c1262ddfd05695195a1e"
- dependencies:
- debug "^3.1.0"
-
-"@webassemblyjs/helper-code-frame@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.5.13.tgz#1bd2181b6a0be14e004f0fe9f5a660d265362b58"
+"@vue/test-utils@^1.0.0-beta.25":
+ version "1.0.0-beta.25"
+ resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.0.0-beta.25.tgz#4703076de3076bac42cdd242cd53e6fb8752ed8c"
+ integrity sha512-mfvguEmEpAn0BuT4u+qm+0J1NTKgQS+ffUyWHY1QeSovIkJcy98fj1rO+PJgiZSEvGjjnDNX+qmofYFPLrofbA==
dependencies:
- "@webassemblyjs/wast-printer" "1.5.13"
-
-"@webassemblyjs/helper-fsm@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.5.13.tgz#cdf3d9d33005d543a5c5e5adaabf679ffa8db924"
+ lodash "^4.17.4"
-"@webassemblyjs/helper-module-context@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.5.13.tgz#dc29ddfb51ed657655286f94a5d72d8a489147c5"
+"@webassemblyjs/ast@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.7.6.tgz#3ef8c45b3e5e943a153a05281317474fef63e21e"
+ integrity sha512-8nkZS48EVsMUU0v6F1LCIOw4RYWLm2plMtbhFTjNgeXmsTNLuU3xTRtnljt9BFQB+iPbLRobkNrCWftWnNC7wQ==
dependencies:
- debug "^3.1.0"
+ "@webassemblyjs/helper-module-context" "1.7.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.7.6"
+ "@webassemblyjs/wast-parser" "1.7.6"
mamacro "^0.0.3"
-"@webassemblyjs/helper-wasm-bytecode@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.5.13.tgz#03245817f0a762382e61733146f5773def15a747"
+"@webassemblyjs/floating-point-hex-parser@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.6.tgz#7cb37d51a05c3fe09b464ae7e711d1ab3837801f"
+ integrity sha512-VBOZvaOyBSkPZdIt5VBMg3vPWxouuM13dPXGWI1cBh3oFLNcFJ8s9YA7S9l4mPI7+Q950QqOmqj06oa83hNWBA==
-"@webassemblyjs/helper-wasm-section@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.5.13.tgz#efc76f44a10d3073b584b43c38a179df173d5c7d"
- dependencies:
- "@webassemblyjs/ast" "1.5.13"
- "@webassemblyjs/helper-buffer" "1.5.13"
- "@webassemblyjs/helper-wasm-bytecode" "1.5.13"
- "@webassemblyjs/wasm-gen" "1.5.13"
- debug "^3.1.0"
+"@webassemblyjs/helper-api-error@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.6.tgz#99b7e30e66f550a2638299a109dda84a622070ef"
+ integrity sha512-SCzhcQWHXfrfMSKcj8zHg1/kL9kb3aa5TN4plc/EREOs5Xop0ci5bdVBApbk2yfVi8aL+Ly4Qpp3/TRAUInjrg==
-"@webassemblyjs/ieee754@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.5.13.tgz#573e97c8c12e4eebb316ca5fde0203ddd90b0364"
- dependencies:
- ieee754 "^1.1.11"
+"@webassemblyjs/helper-buffer@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.6.tgz#ba0648be12bbe560c25c997e175c2018df39ca3e"
+ integrity sha512-1/gW5NaGsEOZ02fjnFiU8/OEEXU1uVbv2um0pQ9YVL3IHSkyk6xOwokzyqqO1qDZQUAllb+V8irtClPWntbVqw==
-"@webassemblyjs/leb128@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.5.13.tgz#ab52ebab9cec283c1c1897ac1da833a04a3f4cee"
+"@webassemblyjs/helper-code-frame@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.6.tgz#5a94d21b0057b69a7403fca0c253c3aaca95b1a5"
+ integrity sha512-+suMJOkSn9+vEvDvgyWyrJo5vJsWSDXZmJAjtoUq4zS4eqHyXImpktvHOZwXp1XQjO5H+YQwsBgqTQEc0J/5zg==
dependencies:
- long "4.0.0"
+ "@webassemblyjs/wast-printer" "1.7.6"
-"@webassemblyjs/utf8@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.5.13.tgz#6b53d2cd861cf94fa99c1f12779dde692fbc2469"
+"@webassemblyjs/helper-fsm@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.6.tgz#ae1741c6f6121213c7a0b587fb964fac492d3e49"
+ integrity sha512-HCS6KN3wgxUihGBW7WFzEC/o8Eyvk0d56uazusnxXthDPnkWiMv+kGi9xXswL2cvfYfeK5yiM17z2K5BVlwypw==
-"@webassemblyjs/wasm-edit@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.5.13.tgz#c9cef5664c245cf11b3b3a73110c9155831724a8"
+"@webassemblyjs/helper-module-context@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.6.tgz#116d19a51a6cebc8900ad53ca34ff8269c668c23"
+ integrity sha512-e8/6GbY7OjLM+6OsN7f2krC2qYVNaSr0B0oe4lWdmq5sL++8dYDD1TFbD1TdAdWMRTYNr/Qq7ovXWzia2EbSjw==
dependencies:
- "@webassemblyjs/ast" "1.5.13"
- "@webassemblyjs/helper-buffer" "1.5.13"
- "@webassemblyjs/helper-wasm-bytecode" "1.5.13"
- "@webassemblyjs/helper-wasm-section" "1.5.13"
- "@webassemblyjs/wasm-gen" "1.5.13"
- "@webassemblyjs/wasm-opt" "1.5.13"
- "@webassemblyjs/wasm-parser" "1.5.13"
- "@webassemblyjs/wast-printer" "1.5.13"
- debug "^3.1.0"
+ mamacro "^0.0.3"
-"@webassemblyjs/wasm-gen@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.5.13.tgz#8e6ea113c4b432fa66540189e79b16d7a140700e"
- dependencies:
- "@webassemblyjs/ast" "1.5.13"
- "@webassemblyjs/helper-wasm-bytecode" "1.5.13"
- "@webassemblyjs/ieee754" "1.5.13"
- "@webassemblyjs/leb128" "1.5.13"
- "@webassemblyjs/utf8" "1.5.13"
+"@webassemblyjs/helper-wasm-bytecode@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.6.tgz#98e515eaee611aa6834eb5f6a7f8f5b29fefb6f1"
+ integrity sha512-PzYFCb7RjjSdAOljyvLWVqd6adAOabJW+8yRT+NWhXuf1nNZWH+igFZCUK9k7Cx7CsBbzIfXjJc7u56zZgFj9Q==
+
+"@webassemblyjs/helper-wasm-section@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.6.tgz#783835867bdd686df7a95377ab64f51a275e8333"
+ integrity sha512-3GS628ppDPSuwcYlQ7cDCGr4W2n9c4hLzvnRKeuz+lGsJSmc/ADVoYpm1ts2vlB1tGHkjtQMni+yu8mHoMlKlA==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.6"
+ "@webassemblyjs/helper-buffer" "1.7.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.7.6"
+ "@webassemblyjs/wasm-gen" "1.7.6"
+
+"@webassemblyjs/ieee754@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.7.6.tgz#c34fc058f2f831fae0632a8bb9803cf2d3462eb1"
+ integrity sha512-V4cIp0ruyw+hawUHwQLn6o2mFEw4t50tk530oKsYXQhEzKR+xNGDxs/SFFuyTO7X3NzEu4usA3w5jzhl2RYyzQ==
+ dependencies:
+ "@xtuc/ieee754" "^1.2.0"
+
+"@webassemblyjs/leb128@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.7.6.tgz#197f75376a29f6ed6ace15898a310d871d92f03b"
+ integrity sha512-ojdlG8WpM394lBow4ncTGJoIVZ4aAtNOWHhfAM7m7zprmkVcKK+2kK5YJ9Bmj6/ketTtOn7wGSHCtMt+LzqgYQ==
+ dependencies:
+ "@xtuc/long" "4.2.1"
+
+"@webassemblyjs/utf8@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.7.6.tgz#eb62c66f906af2be70de0302e29055d25188797d"
+ integrity sha512-oId+tLxQ+AeDC34ELRYNSqJRaScB0TClUU6KQfpB8rNT6oelYlz8axsPhf6yPTg7PBJ/Z5WcXmUYiHEWgbbHJw==
+
+"@webassemblyjs/wasm-edit@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.6.tgz#fa41929160cd7d676d4c28ecef420eed5b3733c5"
+ integrity sha512-pTNjLO3o41v/Vz9VFLl+I3YLImpCSpodFW77pNoH4agn5I6GgSxXHXtvWDTvYJFty0jSeXZWLEmbaSIRUDlekg==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.6"
+ "@webassemblyjs/helper-buffer" "1.7.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.7.6"
+ "@webassemblyjs/helper-wasm-section" "1.7.6"
+ "@webassemblyjs/wasm-gen" "1.7.6"
+ "@webassemblyjs/wasm-opt" "1.7.6"
+ "@webassemblyjs/wasm-parser" "1.7.6"
+ "@webassemblyjs/wast-printer" "1.7.6"
+
+"@webassemblyjs/wasm-gen@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.6.tgz#695ac38861ab3d72bf763c8c75e5f087ffabc322"
+ integrity sha512-mQvFJVumtmRKEUXMohwn8nSrtjJJl6oXwF3FotC5t6e2hlKMh8sIaW03Sck2MDzw9xPogZD7tdP5kjPlbH9EcQ==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.7.6"
+ "@webassemblyjs/ieee754" "1.7.6"
+ "@webassemblyjs/leb128" "1.7.6"
+ "@webassemblyjs/utf8" "1.7.6"
+
+"@webassemblyjs/wasm-opt@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.6.tgz#fbafa78e27e1a75ab759a4b658ff3d50b4636c21"
+ integrity sha512-go44K90fSIsDwRgtHhX14VtbdDPdK2sZQtZqUcMRvTojdozj5tLI0VVJAzLCfz51NOkFXezPeVTAYFqrZ6rI8Q==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.6"
+ "@webassemblyjs/helper-buffer" "1.7.6"
+ "@webassemblyjs/wasm-gen" "1.7.6"
+ "@webassemblyjs/wasm-parser" "1.7.6"
+
+"@webassemblyjs/wasm-parser@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.6.tgz#84eafeeff405ad6f4c4b5777d6a28ae54eed51fe"
+ integrity sha512-t1T6TfwNY85pDA/HWPA8kB9xA4sp9ajlRg5W7EKikqrynTyFo+/qDzIpvdkOkOGjlS6d4n4SX59SPuIayR22Yg==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.6"
+ "@webassemblyjs/helper-api-error" "1.7.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.7.6"
+ "@webassemblyjs/ieee754" "1.7.6"
+ "@webassemblyjs/leb128" "1.7.6"
+ "@webassemblyjs/utf8" "1.7.6"
+
+"@webassemblyjs/wast-parser@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.7.6.tgz#ca4d20b1516e017c91981773bd7e819d6bd9c6a7"
+ integrity sha512-1MaWTErN0ziOsNUlLdvwS+NS1QWuI/kgJaAGAMHX8+fMJFgOJDmN/xsG4h/A1Gtf/tz5VyXQciaqHZqp2q0vfg==
+ dependencies:
+ "@webassemblyjs/ast" "1.7.6"
+ "@webassemblyjs/floating-point-hex-parser" "1.7.6"
+ "@webassemblyjs/helper-api-error" "1.7.6"
+ "@webassemblyjs/helper-code-frame" "1.7.6"
+ "@webassemblyjs/helper-fsm" "1.7.6"
+ "@xtuc/long" "4.2.1"
+ mamacro "^0.0.3"
-"@webassemblyjs/wasm-opt@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.5.13.tgz#147aad7717a7ee4211c36b21a5f4c30dddf33138"
+"@webassemblyjs/wast-printer@1.7.6":
+ version "1.7.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.7.6.tgz#a6002c526ac5fa230fe2c6d2f1bdbf4aead43a5e"
+ integrity sha512-vHdHSK1tOetvDcl1IV1OdDeGNe/NDDQ+KzuZHMtqTVP1xO/tZ/IKNpj5BaGk1OYFdsDWQqb31PIwdEyPntOWRQ==
dependencies:
- "@webassemblyjs/ast" "1.5.13"
- "@webassemblyjs/helper-buffer" "1.5.13"
- "@webassemblyjs/wasm-gen" "1.5.13"
- "@webassemblyjs/wasm-parser" "1.5.13"
- debug "^3.1.0"
+ "@webassemblyjs/ast" "1.7.6"
+ "@webassemblyjs/wast-parser" "1.7.6"
+ "@xtuc/long" "4.2.1"
-"@webassemblyjs/wasm-parser@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.5.13.tgz#6f46516c5bb23904fbdf58009233c2dd8a54c72f"
- dependencies:
- "@webassemblyjs/ast" "1.5.13"
- "@webassemblyjs/helper-api-error" "1.5.13"
- "@webassemblyjs/helper-wasm-bytecode" "1.5.13"
- "@webassemblyjs/ieee754" "1.5.13"
- "@webassemblyjs/leb128" "1.5.13"
- "@webassemblyjs/utf8" "1.5.13"
-
-"@webassemblyjs/wast-parser@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.5.13.tgz#5727a705d397ae6a3ae99d7f5460acf2ec646eea"
- dependencies:
- "@webassemblyjs/ast" "1.5.13"
- "@webassemblyjs/floating-point-hex-parser" "1.5.13"
- "@webassemblyjs/helper-api-error" "1.5.13"
- "@webassemblyjs/helper-code-frame" "1.5.13"
- "@webassemblyjs/helper-fsm" "1.5.13"
- long "^3.2.0"
- mamacro "^0.0.3"
+"@xtuc/ieee754@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
+ integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==
-"@webassemblyjs/wast-printer@1.5.13":
- version "1.5.13"
- resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.5.13.tgz#bb34d528c14b4f579e7ec11e793ec50ad7cd7c95"
- dependencies:
- "@webassemblyjs/ast" "1.5.13"
- "@webassemblyjs/wast-parser" "1.5.13"
- long "^3.2.0"
+"@xtuc/long@4.2.1":
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.1.tgz#5c85d662f76fa1d34575766c5dcd6615abcd30d8"
+ integrity sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==
abbrev@1, abbrev@1.0.x:
version "1.0.9"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135"
+ integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU=
-accepts@~1.3.3, accepts@~1.3.4:
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f"
+accepts@~1.3.4, accepts@~1.3.5:
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2"
+ integrity sha1-63d99gEXI6OxTopywIBcjoZ0a9I=
dependencies:
- mime-types "~2.1.16"
+ mime-types "~2.1.18"
negotiator "0.6.1"
acorn-dynamic-import@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz#901ceee4c7faaef7e07ad2a47e890675da50a278"
+ integrity sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==
dependencies:
acorn "^5.0.0"
-acorn-jsx@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b"
+acorn-jsx@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-4.1.1.tgz#e8e41e48ea2fe0c896740610ab6a4ffd8add225e"
+ integrity sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==
dependencies:
- acorn "^3.0.4"
-
-acorn@^3.0.4:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
+ acorn "^5.0.3"
-acorn@^5.0.0, acorn@^5.3.0, acorn@^5.5.0, acorn@^5.6.2:
- version "5.7.1"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8"
+acorn@^5.0.0, acorn@^5.0.3, acorn@^5.6.0, acorn@^5.6.2, acorn@^5.7.3:
+ version "5.7.3"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279"
+ integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==
after@0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f"
+ integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=
-ajv-keywords@^2.1.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762"
-
-ajv-keywords@^3.1.0:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.1.0.tgz#ac2b27939c543e95d2c06e7f7f5c27be4aa543be"
+ajv-errors@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.0.tgz#ecf021fa108fd17dfb5e6b383f2dd233e31ffc59"
+ integrity sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk=
-ajv@^5.2.3, ajv@^5.3.0:
- version "5.5.2"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
- dependencies:
- co "^4.6.0"
- fast-deep-equal "^1.0.0"
- fast-json-stable-stringify "^2.0.0"
- json-schema-traverse "^0.3.0"
+ajv-keywords@^3.0.0, ajv-keywords@^3.1.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a"
+ integrity sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=
-ajv@^6.1.0:
- version "6.1.1"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.1.1.tgz#978d597fbc2b7d0e5a5c3ddeb149a682f2abfa0e"
+ajv@^6.0.1, ajv@^6.1.0, ajv@^6.5.3:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.3.tgz#71a569d189ecf4f4f321224fecb166f071dd90f9"
+ integrity sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==
dependencies:
- fast-deep-equal "^1.0.0"
+ fast-deep-equal "^2.0.1"
fast-json-stable-stringify "^2.0.0"
- json-schema-traverse "^0.3.0"
-
-align-text@^0.1.1, align-text@^0.1.3:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
- dependencies:
- kind-of "^3.0.2"
- longest "^1.0.1"
- repeat-string "^1.5.2"
+ json-schema-traverse "^0.4.1"
+ uri-js "^4.2.2"
amdefine@>=0.0.4:
version "1.0.1"
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
+ integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=
ansi-align@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f"
+ integrity sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=
dependencies:
string-width "^2.0.0"
+ansi-colors@^3.0.0:
+ version "3.0.5"
+ resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.0.5.tgz#cb9dc64993b64fd6945485f797fc3853137d9a7b"
+ integrity sha512-VVjWpkfaphxUBFarydrQ3n26zX5nIK7hcbT3/ielrvwDDyBBjuh2vuSw1P9zkPq0cfqvdw7lkYHnu+OLSfIBsg==
+
ansi-escapes@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
+ integrity sha1-06ioOzGapneTZisT52HHkRQiMG4=
ansi-escapes@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92"
+ integrity sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==
ansi-html@0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e"
+ integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4=
ansi-regex@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
+ integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
ansi-regex@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
+ integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
+ integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=
ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+ integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
dependencies:
color-convert "^1.9.0"
anymatch@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb"
+ integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==
dependencies:
micromatch "^3.1.4"
normalize-path "^2.1.1"
-append-transform@^0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991"
+apollo-boost@^0.1.20:
+ version "0.1.20"
+ resolved "https://registry.yarnpkg.com/apollo-boost/-/apollo-boost-0.1.20.tgz#cc3e418ebd2bea857656685d32a7a20443493363"
+ integrity sha512-n2MiEY5IGpD/cy0RH+pM9vbmobM/JZ5qz38XQAUA41FxxMPlLFQxf0IUMm0tijLOJvJJBub3pDt+Of4TVPBCqA==
+ dependencies:
+ apollo-cache "^1.1.20"
+ apollo-cache-inmemory "^1.3.9"
+ apollo-client "^2.4.5"
+ apollo-link "^1.0.6"
+ apollo-link-error "^1.0.3"
+ apollo-link-http "^1.3.1"
+ apollo-link-state "^0.4.0"
+ graphql-tag "^2.4.2"
+
+apollo-cache-inmemory@^1.3.9:
+ version "1.3.9"
+ resolved "https://registry.yarnpkg.com/apollo-cache-inmemory/-/apollo-cache-inmemory-1.3.9.tgz#10738ba6a04faaeeb0da21bbcc1f7c0b5902910c"
+ integrity sha512-Q2k84p/OqIuMUyeWGc6XbVXXZu0erYOO+wTx9p+CnQUspnNvf7zmvFNgFnmudXzfuG1m1CSzePk6fC/M1ehOqQ==
+ dependencies:
+ apollo-cache "^1.1.20"
+ apollo-utilities "^1.0.25"
+ optimism "^0.6.6"
+
+apollo-cache@1.1.20, apollo-cache@^1.1.20:
+ version "1.1.20"
+ resolved "https://registry.yarnpkg.com/apollo-cache/-/apollo-cache-1.1.20.tgz#6152cc4baf6a63e376efee79f75de4f5c84bf90e"
+ integrity sha512-+Du0/4kUSuf5PjPx0+pvgMGV12ezbHA8/hubYuqRQoy/4AWb4faa61CgJNI6cKz2mhDd9m94VTNKTX11NntwkQ==
+ dependencies:
+ apollo-utilities "^1.0.25"
+
+apollo-client@^2.4.5:
+ version "2.4.5"
+ resolved "https://registry.yarnpkg.com/apollo-client/-/apollo-client-2.4.5.tgz#545beda1ef60814943b5622f0feabc9f29ee9822"
+ integrity sha512-nUm06EGa4TP/IY68OzmC3lTD32TqkjLOQdb69uYo+lHl8NnwebtrAw3qFtsQtTEz6ueBp/Z/HasNZng4jwafVQ==
+ dependencies:
+ "@types/zen-observable" "^0.8.0"
+ apollo-cache "1.1.20"
+ apollo-link "^1.0.0"
+ apollo-link-dedup "^1.0.0"
+ apollo-utilities "1.0.25"
+ symbol-observable "^1.0.2"
+ zen-observable "^0.8.0"
+ optionalDependencies:
+ "@types/async" "2.0.50"
+
+apollo-link-dedup@^1.0.0:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/apollo-link-dedup/-/apollo-link-dedup-1.0.10.tgz#7b94589fe7f969777efd18a129043c78430800ae"
+ integrity sha512-tpUI9lMZsidxdNygSY1FxflXEkUZnvKRkMUsXXuQUNoSLeNtEvUX7QtKRAl4k9ubLl8JKKc9X3L3onAFeGTK8w==
+ dependencies:
+ apollo-link "^1.2.3"
+
+apollo-link-error@^1.0.3:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/apollo-link-error/-/apollo-link-error-1.1.1.tgz#69d7124d4dc11ce60f505c940f05d4f1aa0945fb"
+ integrity sha512-/yPcaQWcBdB94vpJ4FsiCJt1dAGGRm+6Tsj3wKwP+72taBH+UsGRQQZk7U/1cpZwl1yqhHZn+ZNhVOebpPcIlA==
+ dependencies:
+ apollo-link "^1.2.3"
+
+apollo-link-http-common@^0.2.5:
+ version "0.2.5"
+ resolved "https://registry.yarnpkg.com/apollo-link-http-common/-/apollo-link-http-common-0.2.5.tgz#d094beb7971523203359bf830bfbfa7b4e7c30ed"
+ integrity sha512-6FV1wr5AqAyJ64Em1dq5hhGgiyxZE383VJQmhIoDVc3MyNcFL92TkhxREOs4rnH2a9X2iJMko7nodHSGLC6d8w==
+ dependencies:
+ apollo-link "^1.2.3"
+
+apollo-link-http@^1.3.1:
+ version "1.5.5"
+ resolved "https://registry.yarnpkg.com/apollo-link-http/-/apollo-link-http-1.5.5.tgz#7dbe851821771ad67fa29e3900c57f38cbd80da8"
+ integrity sha512-C5N6N/mRwmepvtzO27dgMEU3MMtRKSqcljBkYNZmWwH11BxkUQ5imBLPM3V4QJXNE7NFuAQAB5PeUd4ligivTQ==
+ dependencies:
+ apollo-link "^1.2.3"
+ apollo-link-http-common "^0.2.5"
+
+apollo-link-state@^0.4.0:
+ version "0.4.2"
+ resolved "https://registry.yarnpkg.com/apollo-link-state/-/apollo-link-state-0.4.2.tgz#ac00e9be9b0ca89eae0be6ba31fe904b80bbe2e8"
+ integrity sha512-xMPcAfuiPVYXaLwC6oJFIZrKgV3GmdO31Ag2eufRoXpvT0AfJZjdaPB4450Nu9TslHRePN9A3quxNueILlQxlw==
dependencies:
- default-require-extensions "^1.0.0"
+ apollo-utilities "^1.0.8"
+ graphql-anywhere "^4.1.0-alpha.0"
+
+apollo-link@^1.0.0, apollo-link@^1.0.6, apollo-link@^1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.3.tgz#9bd8d5fe1d88d31dc91dae9ecc22474d451fb70d"
+ integrity sha512-iL9yS2OfxYhigme5bpTbmRyC+Htt6tyo2fRMHT3K1XRL/C5IQDDz37OjpPy4ndx7WInSvfSZaaOTKFja9VWqSw==
+ dependencies:
+ apollo-utilities "^1.0.0"
+ zen-observable-ts "^0.8.10"
+
+apollo-utilities@1.0.25, apollo-utilities@^1.0.0, apollo-utilities@^1.0.25, apollo-utilities@^1.0.8:
+ version "1.0.25"
+ resolved "https://registry.yarnpkg.com/apollo-utilities/-/apollo-utilities-1.0.25.tgz#899b00f5f990fb451675adf84cb3de82eb6372ea"
+ integrity sha512-AXvqkhni3Ir1ffm4SA1QzXn8k8I5BBl4PVKEyak734i4jFdp+xgfUyi2VCqF64TJlFTA/B73TRDUvO2D+tKtZg==
+ dependencies:
+ fast-json-stable-stringify "^2.0.0"
+
+append-transform@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab"
+ integrity sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==
+ dependencies:
+ default-require-extensions "^2.0.0"
aproba@^1.0.3, aproba@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
+ integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
are-we-there-yet@~1.1.2:
version "1.1.4"
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d"
+ integrity sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=
dependencies:
delegates "^1.0.0"
readable-stream "^2.0.6"
argparse@^1.0.7:
- version "1.0.9"
- resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86"
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
+ integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
dependencies:
sprintf-js "~1.0.2"
arr-diff@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
+ integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=
arr-flatten@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
+ integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==
arr-union@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4"
-
-array-find-index@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
+ integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=
array-find@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/array-find/-/array-find-1.0.0.tgz#6c8e286d11ed768327f8e62ecee87353ca3e78b8"
+ integrity sha1-bI4obRHtdoMn+OYuzuhzU8o+eLg=
array-flatten@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
+ integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
array-flatten@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.1.tgz#426bb9da84090c1838d812c8150af20a8331e296"
-
-array-includes@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d"
- dependencies:
- define-properties "^1.1.2"
- es-abstract "^1.7.0"
+ integrity sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=
array-slice@^0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5"
+ integrity sha1-3Tz7gO15c6dRF82sabC5nshhhvU=
array-union@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
+ integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=
dependencies:
array-uniq "^1.0.1"
array-uniq@^1.0.1, array-uniq@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
+ integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=
array-unique@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
+ integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=
array-unique@^0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
+ integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=
arraybuffer.slice@~0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675"
+ integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==
arrify@^1.0.0, arrify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
+ integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
asn1.js@^4.0.0:
version "4.10.1"
resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0"
+ integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==
dependencies:
bn.js "^4.0.0"
inherits "^2.0.1"
@@ -486,628 +1204,140 @@ asn1.js@^4.0.0:
assert@^1.1.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91"
+ integrity sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=
dependencies:
util "0.10.3"
assign-symbols@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
+ integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=
async-each@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
+ integrity sha1-GdOGodntxufByF04iu28xW0zYC0=
async-limiter@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8"
+ integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==
-async@1.x, async@^1.4.0, async@^1.5.2:
+async@1.x, async@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
+ integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=
-async@^2.0.0, async@^2.1.4:
+async@^2.0.0, async@^2.5.0, async@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610"
+ integrity sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==
dependencies:
lodash "^4.17.10"
atob@^2.0.0:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/atob/-/atob-2.0.3.tgz#19c7a760473774468f20b2d2d03372ad7d4cbf5d"
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
+ integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
autosize@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/autosize/-/autosize-4.0.0.tgz#7a0599b1ba84d73bd7589b0d9da3870152c69237"
+ integrity sha1-egWZsbqE1zvXWJsNnaOHAVLGkjc=
axios-mock-adapter@^1.15.0:
version "1.15.0"
resolved "https://registry.yarnpkg.com/axios-mock-adapter/-/axios-mock-adapter-1.15.0.tgz#fbc06825d8302c95c3334d21023bba996255d45d"
+ integrity sha1-+8BoJdgwLJXDM00hAju6mWJV1F0=
dependencies:
deep-equal "^1.0.1"
axios@^0.17.1:
version "0.17.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.17.1.tgz#2d8e3e5d0bdbd7327f91bc814f5c57660f81824d"
+ integrity sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=
dependencies:
follow-redirects "^1.2.5"
is-buffer "^1.1.5"
-babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
+babel-code-frame@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
+ integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=
dependencies:
chalk "^1.1.3"
esutils "^2.0.2"
js-tokens "^3.0.2"
-babel-core@^6.26.0, babel-core@^6.26.3:
- version "6.26.3"
- resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207"
+babel-eslint@^10.0.1:
+ version "10.0.1"
+ resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.1.tgz#919681dc099614cd7d31d45c8908695092a1faed"
+ integrity sha512-z7OT1iNV+TjOwHNLLyJk+HN+YVWX+CLE6fPD2SymJZOZQBs+QIexFjhm4keGTm8MW9xr4EC9Q0PbaLB24V5GoQ==
dependencies:
- babel-code-frame "^6.26.0"
- babel-generator "^6.26.0"
- babel-helpers "^6.24.1"
- babel-messages "^6.23.0"
- babel-register "^6.26.0"
- babel-runtime "^6.26.0"
- babel-template "^6.26.0"
- babel-traverse "^6.26.0"
- babel-types "^6.26.0"
- babylon "^6.18.0"
- convert-source-map "^1.5.1"
- debug "^2.6.9"
- json5 "^0.5.1"
- lodash "^4.17.4"
- minimatch "^3.0.4"
- path-is-absolute "^1.0.1"
- private "^0.1.8"
- slash "^1.0.0"
- source-map "^0.5.7"
-
-babel-eslint@^8.2.3:
- version "8.2.3"
- resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.2.3.tgz#1a2e6681cc9bc4473c32899e59915e19cd6733cf"
- dependencies:
- "@babel/code-frame" "7.0.0-beta.44"
- "@babel/traverse" "7.0.0-beta.44"
- "@babel/types" "7.0.0-beta.44"
- babylon "7.0.0-beta.44"
- eslint-scope "~3.7.1"
+ "@babel/code-frame" "^7.0.0"
+ "@babel/parser" "^7.0.0"
+ "@babel/traverse" "^7.0.0"
+ "@babel/types" "^7.0.0"
+ eslint-scope "3.7.1"
eslint-visitor-keys "^1.0.0"
-babel-generator@^6.18.0, babel-generator@^6.26.0:
- version "6.26.0"
- resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5"
- dependencies:
- babel-messages "^6.23.0"
- babel-runtime "^6.26.0"
- babel-types "^6.26.0"
- detect-indent "^4.0.0"
- jsesc "^1.3.0"
- lodash "^4.17.4"
- source-map "^0.5.6"
- trim-right "^1.0.1"
-
-babel-helper-bindify-decorators@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330"
- dependencies:
- babel-runtime "^6.22.0"
- babel-traverse "^6.24.1"
- babel-types "^6.24.1"
-
-babel-helper-builder-binary-assignment-operator-visitor@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664"
- dependencies:
- babel-helper-explode-assignable-expression "^6.24.1"
- babel-runtime "^6.22.0"
- babel-types "^6.24.1"
-
-babel-helper-call-delegate@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d"
- dependencies:
- babel-helper-hoist-variables "^6.24.1"
- babel-runtime "^6.22.0"
- babel-traverse "^6.24.1"
- babel-types "^6.24.1"
-
-babel-helper-define-map@^6.24.1:
- version "6.26.0"
- resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f"
- dependencies:
- babel-helper-function-name "^6.24.1"
- babel-runtime "^6.26.0"
- babel-types "^6.26.0"
- lodash "^4.17.4"
-
-babel-helper-explode-assignable-expression@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa"
- dependencies:
- babel-runtime "^6.22.0"
- babel-traverse "^6.24.1"
- babel-types "^6.24.1"
-
-babel-helper-explode-class@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb"
- dependencies:
- babel-helper-bindify-decorators "^6.24.1"
- babel-runtime "^6.22.0"
- babel-traverse "^6.24.1"
- babel-types "^6.24.1"
-
-babel-helper-function-name@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9"
- dependencies:
- babel-helper-get-function-arity "^6.24.1"
- babel-runtime "^6.22.0"
- babel-template "^6.24.1"
- babel-traverse "^6.24.1"
- babel-types "^6.24.1"
-
-babel-helper-get-function-arity@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d"
- dependencies:
- babel-runtime "^6.22.0"
- babel-types "^6.24.1"
-
-babel-helper-hoist-variables@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76"
- dependencies:
- babel-runtime "^6.22.0"
- babel-types "^6.24.1"
-
-babel-helper-optimise-call-expression@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257"
- dependencies:
- babel-runtime "^6.22.0"
- babel-types "^6.24.1"
-
-babel-helper-regex@^6.24.1:
- version "6.26.0"
- resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72"
- dependencies:
- babel-runtime "^6.26.0"
- babel-types "^6.26.0"
- lodash "^4.17.4"
-
-babel-helper-remap-async-to-generator@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b"
- dependencies:
- babel-helper-function-name "^6.24.1"
- babel-runtime "^6.22.0"
- babel-template "^6.24.1"
- babel-traverse "^6.24.1"
- babel-types "^6.24.1"
-
-babel-helper-replace-supers@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a"
- dependencies:
- babel-helper-optimise-call-expression "^6.24.1"
- babel-messages "^6.23.0"
- babel-runtime "^6.22.0"
- babel-template "^6.24.1"
- babel-traverse "^6.24.1"
- babel-types "^6.24.1"
-
-babel-helpers@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2"
- dependencies:
- babel-runtime "^6.22.0"
- babel-template "^6.24.1"
-
-babel-loader@^7.1.5:
- version "7.1.5"
- resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-7.1.5.tgz#e3ee0cd7394aa557e013b02d3e492bfd07aa6d68"
+babel-loader@^8.0.4:
+ version "8.0.4"
+ resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.4.tgz#7bbf20cbe4560629e2e41534147692d3fecbdce6"
+ integrity sha512-fhBhNkUToJcW9nV46v8w87AJOwAJDz84c1CL57n3Stj73FANM/b9TbCUK4YhdOwEyZ+OxhYpdeZDNzSI29Firw==
dependencies:
find-cache-dir "^1.0.0"
loader-utils "^1.0.2"
mkdirp "^0.5.1"
+ util.promisify "^1.0.0"
babel-messages@^6.23.0:
version "6.23.0"
resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
+ integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=
dependencies:
babel-runtime "^6.22.0"
-babel-plugin-check-es2015-constants@^6.22.0:
- version "6.22.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a"
- dependencies:
- babel-runtime "^6.22.0"
-
-babel-plugin-istanbul@^4.1.6:
- version "4.1.6"
- resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-4.1.6.tgz#36c59b2192efce81c5b378321b74175add1c9a45"
- dependencies:
- babel-plugin-syntax-object-rest-spread "^6.13.0"
- find-up "^2.1.0"
- istanbul-lib-instrument "^1.10.1"
- test-exclude "^4.2.1"
-
-babel-plugin-rewire@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-rewire/-/babel-plugin-rewire-1.1.0.tgz#a6b966d9d8c06c03d95dcda2eec4e2521519549b"
-
-babel-plugin-syntax-async-functions@^6.8.0:
- version "6.13.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
-
-babel-plugin-syntax-async-generators@^6.5.0:
- version "6.13.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a"
-
-babel-plugin-syntax-class-properties@^6.8.0:
- version "6.13.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de"
-
-babel-plugin-syntax-decorators@^6.13.0:
- version "6.13.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b"
-
-babel-plugin-syntax-dynamic-import@^6.18.0:
- version "6.18.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da"
-
-babel-plugin-syntax-exponentiation-operator@^6.8.0:
- version "6.13.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de"
-
-babel-plugin-syntax-object-rest-spread@^6.13.0, babel-plugin-syntax-object-rest-spread@^6.8.0:
- version "6.13.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
-
-babel-plugin-syntax-trailing-function-commas@^6.22.0:
- version "6.22.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3"
-
-babel-plugin-transform-async-generator-functions@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db"
- dependencies:
- babel-helper-remap-async-to-generator "^6.24.1"
- babel-plugin-syntax-async-generators "^6.5.0"
- babel-runtime "^6.22.0"
-
-babel-plugin-transform-async-to-generator@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761"
- dependencies:
- babel-helper-remap-async-to-generator "^6.24.1"
- babel-plugin-syntax-async-functions "^6.8.0"
- babel-runtime "^6.22.0"
-
-babel-plugin-transform-class-properties@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac"
- dependencies:
- babel-helper-function-name "^6.24.1"
- babel-plugin-syntax-class-properties "^6.8.0"
- babel-runtime "^6.22.0"
- babel-template "^6.24.1"
-
-babel-plugin-transform-decorators@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d"
- dependencies:
- babel-helper-explode-class "^6.24.1"
- babel-plugin-syntax-decorators "^6.13.0"
- babel-runtime "^6.22.0"
- babel-template "^6.24.1"
- babel-types "^6.24.1"
-
-babel-plugin-transform-define@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-define/-/babel-plugin-transform-define-1.3.0.tgz#94c5f9459c810c738cc7c50cbd44a31829d6f319"
- dependencies:
- lodash "4.17.4"
- traverse "0.6.6"
-
-babel-plugin-transform-es2015-arrow-functions@^6.22.0:
- version "6.22.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221"
- dependencies:
- babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-block-scoped-functions@^6.22.0:
- version "6.22.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141"
- dependencies:
- babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-block-scoping@^6.24.1:
- version "6.26.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f"
- dependencies:
- babel-runtime "^6.26.0"
- babel-template "^6.26.0"
- babel-traverse "^6.26.0"
- babel-types "^6.26.0"
- lodash "^4.17.4"
-
-babel-plugin-transform-es2015-classes@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db"
- dependencies:
- babel-helper-define-map "^6.24.1"
- babel-helper-function-name "^6.24.1"
- babel-helper-optimise-call-expression "^6.24.1"
- babel-helper-replace-supers "^6.24.1"
- babel-messages "^6.23.0"
- babel-runtime "^6.22.0"
- babel-template "^6.24.1"
- babel-traverse "^6.24.1"
- babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-computed-properties@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3"
- dependencies:
- babel-runtime "^6.22.0"
- babel-template "^6.24.1"
-
-babel-plugin-transform-es2015-destructuring@^6.22.0:
- version "6.23.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d"
- dependencies:
- babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-duplicate-keys@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e"
- dependencies:
- babel-runtime "^6.22.0"
- babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-for-of@^6.22.0:
- version "6.23.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691"
- dependencies:
- babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-function-name@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b"
- dependencies:
- babel-helper-function-name "^6.24.1"
- babel-runtime "^6.22.0"
- babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-literals@^6.22.0:
- version "6.22.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e"
- dependencies:
- babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-modules-amd@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154"
- dependencies:
- babel-plugin-transform-es2015-modules-commonjs "^6.24.1"
- babel-runtime "^6.22.0"
- babel-template "^6.24.1"
-
-babel-plugin-transform-es2015-modules-commonjs@^6.24.1:
- version "6.26.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a"
- dependencies:
- babel-plugin-transform-strict-mode "^6.24.1"
- babel-runtime "^6.26.0"
- babel-template "^6.26.0"
- babel-types "^6.26.0"
-
-babel-plugin-transform-es2015-modules-systemjs@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23"
- dependencies:
- babel-helper-hoist-variables "^6.24.1"
- babel-runtime "^6.22.0"
- babel-template "^6.24.1"
-
-babel-plugin-transform-es2015-modules-umd@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468"
- dependencies:
- babel-plugin-transform-es2015-modules-amd "^6.24.1"
- babel-runtime "^6.22.0"
- babel-template "^6.24.1"
-
-babel-plugin-transform-es2015-object-super@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d"
- dependencies:
- babel-helper-replace-supers "^6.24.1"
- babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-parameters@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b"
- dependencies:
- babel-helper-call-delegate "^6.24.1"
- babel-helper-get-function-arity "^6.24.1"
- babel-runtime "^6.22.0"
- babel-template "^6.24.1"
- babel-traverse "^6.24.1"
- babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-shorthand-properties@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0"
- dependencies:
- babel-runtime "^6.22.0"
- babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-spread@^6.22.0:
- version "6.22.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1"
- dependencies:
- babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-sticky-regex@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc"
- dependencies:
- babel-helper-regex "^6.24.1"
- babel-runtime "^6.22.0"
- babel-types "^6.24.1"
-
-babel-plugin-transform-es2015-template-literals@^6.22.0:
- version "6.22.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d"
- dependencies:
- babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-typeof-symbol@^6.22.0:
- version "6.23.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372"
- dependencies:
- babel-runtime "^6.22.0"
-
-babel-plugin-transform-es2015-unicode-regex@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9"
- dependencies:
- babel-helper-regex "^6.24.1"
- babel-runtime "^6.22.0"
- regexpu-core "^2.0.0"
-
-babel-plugin-transform-exponentiation-operator@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e"
- dependencies:
- babel-helper-builder-binary-assignment-operator-visitor "^6.24.1"
- babel-plugin-syntax-exponentiation-operator "^6.8.0"
- babel-runtime "^6.22.0"
-
-babel-plugin-transform-object-rest-spread@^6.22.0:
- version "6.23.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.23.0.tgz#875d6bc9be761c58a2ae3feee5dc4895d8c7f921"
- dependencies:
- babel-plugin-syntax-object-rest-spread "^6.8.0"
- babel-runtime "^6.22.0"
-
-babel-plugin-transform-regenerator@^6.24.1:
- version "6.26.0"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f"
+babel-plugin-istanbul@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.0.tgz#6892f529eff65a3e2d33d87dc5888ffa2ecd4a30"
+ integrity sha512-CLoXPRSUWiR8yao8bShqZUIC6qLfZVVY3X1wj+QPNXu0wfmrRRfarh1LYy+dYMVI+bDj0ghy3tuqFFRFZmL1Nw==
dependencies:
- regenerator-transform "^0.10.0"
+ find-up "^3.0.0"
+ istanbul-lib-instrument "^3.0.0"
+ test-exclude "^5.0.0"
-babel-plugin-transform-strict-mode@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758"
- dependencies:
- babel-runtime "^6.22.0"
- babel-types "^6.24.1"
+babel-plugin-rewire@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-rewire/-/babel-plugin-rewire-1.2.0.tgz#822562d72ed2c84e47c0f95ee232c920853e9d89"
+ integrity sha512-JBZxczHw3tScS+djy6JPLMjblchGhLI89ep15H3SyjujIzlxo5nr6Yjo7AXotdeVczeBmWs0tF8PgJWDdgzAkQ==
babel-polyfill@6.23.0:
version "6.23.0"
resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.23.0.tgz#8364ca62df8eafb830499f699177466c3b03499d"
+ integrity sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0=
dependencies:
babel-runtime "^6.22.0"
core-js "^2.4.0"
regenerator-runtime "^0.10.0"
-babel-preset-es2015@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939"
- dependencies:
- babel-plugin-check-es2015-constants "^6.22.0"
- babel-plugin-transform-es2015-arrow-functions "^6.22.0"
- babel-plugin-transform-es2015-block-scoped-functions "^6.22.0"
- babel-plugin-transform-es2015-block-scoping "^6.24.1"
- babel-plugin-transform-es2015-classes "^6.24.1"
- babel-plugin-transform-es2015-computed-properties "^6.24.1"
- babel-plugin-transform-es2015-destructuring "^6.22.0"
- babel-plugin-transform-es2015-duplicate-keys "^6.24.1"
- babel-plugin-transform-es2015-for-of "^6.22.0"
- babel-plugin-transform-es2015-function-name "^6.24.1"
- babel-plugin-transform-es2015-literals "^6.22.0"
- babel-plugin-transform-es2015-modules-amd "^6.24.1"
- babel-plugin-transform-es2015-modules-commonjs "^6.24.1"
- babel-plugin-transform-es2015-modules-systemjs "^6.24.1"
- babel-plugin-transform-es2015-modules-umd "^6.24.1"
- babel-plugin-transform-es2015-object-super "^6.24.1"
- babel-plugin-transform-es2015-parameters "^6.24.1"
- babel-plugin-transform-es2015-shorthand-properties "^6.24.1"
- babel-plugin-transform-es2015-spread "^6.22.0"
- babel-plugin-transform-es2015-sticky-regex "^6.24.1"
- babel-plugin-transform-es2015-template-literals "^6.22.0"
- babel-plugin-transform-es2015-typeof-symbol "^6.22.0"
- babel-plugin-transform-es2015-unicode-regex "^6.24.1"
- babel-plugin-transform-regenerator "^6.24.1"
-
-babel-preset-es2016@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-preset-es2016/-/babel-preset-es2016-6.24.1.tgz#f900bf93e2ebc0d276df9b8ab59724ebfd959f8b"
- dependencies:
- babel-plugin-transform-exponentiation-operator "^6.24.1"
-
-babel-preset-es2017@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-preset-es2017/-/babel-preset-es2017-6.24.1.tgz#597beadfb9f7f208bcfd8a12e9b2b29b8b2f14d1"
- dependencies:
- babel-plugin-syntax-trailing-function-commas "^6.22.0"
- babel-plugin-transform-async-to-generator "^6.24.1"
-
-babel-preset-latest@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-preset-latest/-/babel-preset-latest-6.24.1.tgz#677de069154a7485c2d25c577c02f624b85b85e8"
- dependencies:
- babel-preset-es2015 "^6.24.1"
- babel-preset-es2016 "^6.24.1"
- babel-preset-es2017 "^6.24.1"
-
-babel-preset-stage-2@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1"
- dependencies:
- babel-plugin-syntax-dynamic-import "^6.18.0"
- babel-plugin-transform-class-properties "^6.24.1"
- babel-plugin-transform-decorators "^6.24.1"
- babel-preset-stage-3 "^6.24.1"
-
-babel-preset-stage-3@^6.24.1:
- version "6.24.1"
- resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395"
- dependencies:
- babel-plugin-syntax-trailing-function-commas "^6.22.0"
- babel-plugin-transform-async-generator-functions "^6.24.1"
- babel-plugin-transform-async-to-generator "^6.24.1"
- babel-plugin-transform-exponentiation-operator "^6.24.1"
- babel-plugin-transform-object-rest-spread "^6.22.0"
-
-babel-register@^6.26.0:
- version "6.26.0"
- resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
- dependencies:
- babel-core "^6.26.0"
- babel-runtime "^6.26.0"
- core-js "^2.5.0"
- home-or-tmp "^2.0.0"
- lodash "^4.17.4"
- mkdirp "^0.5.1"
- source-map-support "^0.4.15"
-
-babel-runtime@^6.0.0, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0:
+babel-runtime@^6.22.0, babel-runtime@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
+ integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
dependencies:
core-js "^2.4.0"
regenerator-runtime "^0.11.0"
-babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0:
+babel-standalone@^6.26.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-standalone/-/babel-standalone-6.26.0.tgz#15fb3d35f2c456695815ebf1ed96fe7f015b6886"
+ integrity sha1-Ffs9NfLEVmlYFevx7Zb+fwFbaIY=
+
+babel-template@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
+ integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=
dependencies:
babel-runtime "^6.26.0"
babel-traverse "^6.26.0"
@@ -1115,9 +1345,10 @@ babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0:
babylon "^6.18.0"
lodash "^4.17.4"
-babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0:
+babel-traverse@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
+ integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=
dependencies:
babel-code-frame "^6.26.0"
babel-messages "^6.23.0"
@@ -1129,46 +1360,50 @@ babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0:
invariant "^2.2.2"
lodash "^4.17.4"
-babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0:
+babel-types@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
+ integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=
dependencies:
babel-runtime "^6.26.0"
esutils "^2.0.2"
lodash "^4.17.4"
to-fast-properties "^1.0.3"
-babylon@7.0.0-beta.44:
- version "7.0.0-beta.44"
- resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.44.tgz#89159e15e6e30c5096e22d738d8c0af8a0e8ca1d"
-
babylon@^6.18.0:
version "6.18.0"
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
+ integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==
backo2@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
+ integrity sha1-MasayLEpNjRj41s+u2n038+6eUc=
balanced-match@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
+ integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
base64-arraybuffer@0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
+ integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg=
base64-js@^1.0.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.3.tgz#fb13668233d9614cf5fb4bce95a9ba4096cdf801"
+ integrity sha512-MsAhsUW1GxCdgYSO6tAfZrNapmUKk7mWx/k5mFY/A1gBtkaCaNapTg+FExCw1r9yeaZhqx/xPg43xgTFH6KL5w==
base64id@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6"
+ integrity sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=
base@^0.11.1:
version "0.11.2"
resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
+ integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==
dependencies:
cache-base "^1.0.1"
class-utils "^0.3.5"
@@ -1181,59 +1416,59 @@ base@^0.11.1:
batch@0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
+ integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=
better-assert@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522"
+ integrity sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=
dependencies:
callsite "1.0.0"
-bfj-node4@^5.2.0:
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/bfj-node4/-/bfj-node4-5.2.1.tgz#3a6aa2730cf6911ba2afb836c2f88f015d718f3f"
+bfj@^6.1.1:
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.1.tgz#05a3b7784fbd72cfa3c22e56002ef99336516c48"
+ integrity sha512-+GUNvzHR4nRyGybQc2WpNJL4MJazMuvf92ueIyA0bIkPRwhhQu3IfZQ2PSoVPpCBJfmoSdOxu5rnotfFLlvYRQ==
dependencies:
bluebird "^3.5.1"
check-types "^7.3.0"
+ hoopy "^0.1.2"
tryer "^1.0.0"
big.js@^3.1.3:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.1.3.tgz#4cada2193652eb3ca9ec8e55c9015669c9806978"
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e"
+ integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==
binary-extensions@^1.0.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205"
+ integrity sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=
binaryextensions@2:
version "2.1.1"
resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.1.1.tgz#3209a51ca4a4ad541a3b8d3d6a6d5b83a2485935"
-
-blackst0ne-mermaid@^7.1.0-fixed:
- version "7.1.0-fixed"
- resolved "https://registry.yarnpkg.com/blackst0ne-mermaid/-/blackst0ne-mermaid-7.1.0-fixed.tgz#3707b3a113d78610e3068e18a588f46b4688de49"
- dependencies:
- d3 "3.5.17"
- dagre-d3-renderer "^0.4.24"
- dagre-layout "^0.8.0"
- he "^1.1.1"
- lodash "^4.17.4"
- moment "^2.18.1"
+ integrity sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==
blob@0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921"
+ integrity sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=
bluebird@^3.1.1, bluebird@^3.3.0, bluebird@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
+ integrity sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
version "4.11.8"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
+ integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==
body-parser@1.18.2, body-parser@^1.16.1:
version "1.18.2"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454"
+ integrity sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=
dependencies:
bytes "3.0.0"
content-type "~1.0.4"
@@ -1249,6 +1484,7 @@ body-parser@1.18.2, body-parser@^1.16.1:
bonjour@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5"
+ integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU=
dependencies:
array-flatten "^2.1.0"
deep-equal "^1.0.1"
@@ -1260,6 +1496,7 @@ bonjour@^3.5.0:
bootstrap-vue@^2.0.0-rc.11:
version "2.0.0-rc.11"
resolved "https://registry.yarnpkg.com/bootstrap-vue/-/bootstrap-vue-2.0.0-rc.11.tgz#47aaa6d2a8d390477de75e636d8ea652b1d03f59"
+ integrity sha512-LxR+oL8yKr1DVoWUWTX+XhiT0xaTMH6142u2VSFDm4tewTH8HIrzN2YIl7HLZrw2DIuE9bRMIdWJqqn3aQe7Hw==
dependencies:
bootstrap "^4.1.1"
lodash.get "^4.4.2"
@@ -1268,17 +1505,15 @@ bootstrap-vue@^2.0.0-rc.11:
popper.js "^1.12.9"
vue-functional-data-merge "^2.0.5"
-bootstrap@4.1.1:
- version "4.1.1"
- resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.1.1.tgz#3aec85000fa619085da8d2e4983dfd67cf2114cb"
-
-bootstrap@^4.1.1:
+bootstrap@4.1.3, bootstrap@^4.1.1:
version "4.1.3"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.1.3.tgz#0eb371af2c8448e8c210411d0cb824a6409a12be"
+ integrity sha512-rDFIzgXcof0jDyjNosjv4Sno77X4KuPeFxG2XZZv1/Kc8DRVGVADdoQyyOVDwPqL36DDmtCQbrpMCqvpPLJQ0w==
boxen@^1.2.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
+ integrity sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==
dependencies:
ansi-align "^2.0.0"
camelcase "^4.0.0"
@@ -1291,6 +1526,7 @@ boxen@^1.2.1:
brace-expansion@^1.1.7, brace-expansion@^1.1.8:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
dependencies:
balanced-match "^1.0.0"
concat-map "0.0.1"
@@ -1298,12 +1534,14 @@ brace-expansion@^1.1.7, brace-expansion@^1.1.8:
braces@^0.1.2:
version "0.1.5"
resolved "https://registry.yarnpkg.com/braces/-/braces-0.1.5.tgz#c085711085291d8b75fdd74eab0f8597280711e6"
+ integrity sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=
dependencies:
expand-range "^0.1.0"
braces@^2.3.0, braces@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.1.tgz#7086c913b4e5a08dbe37ac0ee6a2500c4ba691bb"
+ integrity sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==
dependencies:
arr-flatten "^1.1.0"
array-unique "^0.3.2"
@@ -1321,10 +1559,12 @@ braces@^2.3.0, braces@^2.3.1:
brorand@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
+ integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
browserify-aes@^1.0.0, browserify-aes@^1.0.4:
version "1.1.1"
resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.1.1.tgz#38b7ab55edb806ff2dcda1a7f1620773a477c49f"
+ integrity sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==
dependencies:
buffer-xor "^1.0.3"
cipher-base "^1.0.0"
@@ -1336,6 +1576,7 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4:
browserify-cipher@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.0.tgz#9988244874bf5ed4e28da95666dcd66ac8fc363a"
+ integrity sha1-mYgkSHS/XtTijalWZtzWasj8Njo=
dependencies:
browserify-aes "^1.0.4"
browserify-des "^1.0.0"
@@ -1344,6 +1585,7 @@ browserify-cipher@^1.0.0:
browserify-des@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.0.tgz#daa277717470922ed2fe18594118a175439721dd"
+ integrity sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=
dependencies:
cipher-base "^1.0.1"
des.js "^1.0.0"
@@ -1352,6 +1594,7 @@ browserify-des@^1.0.0:
browserify-rsa@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524"
+ integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=
dependencies:
bn.js "^4.1.0"
randombytes "^2.0.1"
@@ -1359,6 +1602,7 @@ browserify-rsa@^4.0.0:
browserify-sign@^4.0.0:
version "4.0.4"
resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298"
+ integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=
dependencies:
bn.js "^4.1.1"
browserify-rsa "^4.0.0"
@@ -1371,24 +1615,38 @@ browserify-sign@^4.0.0:
browserify-zlib@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f"
+ integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==
dependencies:
pako "~1.0.5"
+browserslist@^4.1.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.1.1.tgz#328eb4ff1215b12df6589e9ab82f8adaa4fc8cd6"
+ integrity sha512-VBorw+tgpOtZ1BYhrVSVTzTt/3+vSE3eFUh0N2GCFK1HffceOaf32YS/bs6WiFhjDAblAFrx85jMy3BG9fBK2Q==
+ dependencies:
+ caniuse-lite "^1.0.30000884"
+ electron-to-chromium "^1.3.62"
+ node-releases "^1.0.0-alpha.11"
+
buffer-from@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.0.0.tgz#4cb8832d23612589b0406e9e2956c17f06fdf531"
+ integrity sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==
buffer-indexof@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.0.tgz#f54f647c4f4e25228baa656a2e57e43d5f270982"
+ integrity sha1-9U9kfE9OJSKLqmVqLlfkPV8nCYI=
buffer-xor@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
+ integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=
buffer@^4.3.0:
version "4.9.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298"
+ integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=
dependencies:
base64-js "^1.0.2"
ieee754 "^1.1.4"
@@ -1397,22 +1655,22 @@ buffer@^4.3.0:
builtin-modules@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
+ integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
builtin-status-codes@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
-
-bytes@2.5.0:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.5.0.tgz#4c9423ea2d252c270c41b2bdefeff9bb6b62c06a"
+ integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=
bytes@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
+ integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=
-cacache@^10.0.1, cacache@^10.0.4:
+cacache@^10.0.4:
version "10.0.4"
resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460"
+ integrity sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==
dependencies:
bluebird "^3.5.1"
chownr "^1.0.1"
@@ -1428,9 +1686,30 @@ cacache@^10.0.1, cacache@^10.0.4:
unique-filename "^1.1.0"
y18n "^4.0.0"
+cacache@^11.2.0:
+ version "11.2.0"
+ resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.2.0.tgz#617bdc0b02844af56310e411c0878941d5739965"
+ integrity sha512-IFWl6lfK6wSeYCHUXh+N1lY72UDrpyrYQJNIVQf48paDuWbv5RbAtJYf/4gUQFObTCHZwdZ5sI8Iw7nqwP6nlQ==
+ dependencies:
+ bluebird "^3.5.1"
+ chownr "^1.0.1"
+ figgy-pudding "^3.1.0"
+ glob "^7.1.2"
+ graceful-fs "^4.1.11"
+ lru-cache "^4.1.3"
+ mississippi "^3.0.0"
+ mkdirp "^0.5.1"
+ move-concurrently "^1.0.1"
+ promise-inflight "^1.0.1"
+ rimraf "^2.6.2"
+ ssri "^6.0.0"
+ unique-filename "^1.1.0"
+ y18n "^4.0.0"
+
cache-base@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2"
+ integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==
dependencies:
collection-visit "^1.0.0"
component-emitter "^1.2.1"
@@ -1445,6 +1724,7 @@ cache-base@^1.0.1:
cache-loader@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/cache-loader/-/cache-loader-1.2.2.tgz#6d5c38ded959a09cc5d58190ab5af6f73bd353f5"
+ integrity sha512-rsGh4SIYyB9glU+d0OcHwiXHXBoUgDhHZaQ1KAbiXqfz1CDPxtTboh1gPbJ0q2qdO8a9lfcjgC5CJ2Ms32y5bw==
dependencies:
loader-utils "^1.1.0"
mkdirp "^0.5.1"
@@ -1454,6 +1734,7 @@ cache-loader@^1.2.2:
cacheable-request@^2.1.1:
version "2.1.4"
resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d"
+ integrity sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=
dependencies:
clone-response "1.0.2"
get-stream "3.0.0"
@@ -1466,50 +1747,39 @@ cacheable-request@^2.1.1:
caller-path@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
+ integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=
dependencies:
callsites "^0.2.0"
callsite@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20"
+ integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA=
callsites@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca"
-
-camelcase-keys@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
- dependencies:
- camelcase "^2.0.0"
- map-obj "^1.0.0"
-
-camelcase@^1.0.2:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
-
-camelcase@^2.0.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
+ integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=
camelcase@^4.0.0, camelcase@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
+ integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
+
+caniuse-lite@^1.0.30000884:
+ version "1.0.30000888"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000888.tgz#22edb50d91dd70612b5898e3b36f460600c6492f"
+ integrity sha512-vftg+5p/lPsQGpnhSo/yBuYL36ai/cyjLvU3dOPJY1kkKrekLWIy8SLm+wzjX0hpCUdFTasC4/ZT7uqw4rKOnQ==
capture-stack-trace@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d"
-
-center-align@^0.1.1:
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad"
- dependencies:
- align-text "^0.1.3"
- lazy-cache "^1.0.3"
+ integrity sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=
chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
+ integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=
dependencies:
ansi-styles "^2.2.1"
escape-string-regexp "^1.0.2"
@@ -1517,9 +1787,10 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
-chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1:
+chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e"
+ integrity sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==
dependencies:
ansi-styles "^3.2.1"
escape-string-regexp "^1.0.5"
@@ -1528,26 +1799,32 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1:
chardet@^0.4.0:
version "0.4.2"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2"
+ integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=
chardet@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.5.0.tgz#fe3ac73c00c3d865ffcc02a0682e2c20b6a06029"
+ integrity sha512-9ZTaoBaePSCFvNlNGrsyI8ZVACP2svUtq0DkM7t4K2ClAa96sqOIRjAzDTc8zXzFt1cZR46rRzLTiHFSJ+Qw0g==
"charenc@>= 0.0.1":
version "0.0.2"
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
+ integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
chart.js@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-1.0.2.tgz#ad57d2229cfd8ccf5955147e8121b4911e69dfe7"
+ integrity sha1-rVfSIpz9jM9ZVRR+gSG0kR5p3+c=
check-types@^7.3.0:
version "7.3.0"
resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.3.0.tgz#468f571a4435c24248f5fd0cb0e8d87c3c341e7d"
+ integrity sha1-Ro9XGkQ1wkJI9f0MsOjYfDw0Hn0=
chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26"
+ integrity sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==
dependencies:
anymatch "^2.0.0"
async-each "^1.0.0"
@@ -1567,16 +1844,19 @@ chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3:
chownr@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181"
+ integrity sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=
chrome-trace-event@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz#45a91bd2c20c9411f0963b5aaeb9a1b95e09cc48"
+ integrity sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==
dependencies:
tslib "^1.9.0"
cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
+ integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==
dependencies:
inherits "^2.0.1"
safe-buffer "^5.0.1"
@@ -1584,14 +1864,17 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
circular-json@^0.3.1:
version "0.3.3"
resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66"
+ integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==
circular-json@^0.5.5:
version "0.5.5"
resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.5.5.tgz#64182ef359042d37cd8e767fc9de878b1e9447d3"
+ integrity sha512-13YaR6kiz0kBNmIVM87Io8Hp7bWOo4r61vkEANy8iH9R9bc6avud/1FT0SBpqR1RpIQADOh/Q+yHZDA1iL6ysA==
class-utils@^0.3.5:
version "0.3.6"
resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463"
+ integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==
dependencies:
arr-union "^3.1.0"
define-property "^0.2.5"
@@ -1601,40 +1884,38 @@ class-utils@^0.3.5:
classlist-polyfill@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/classlist-polyfill/-/classlist-polyfill-1.2.0.tgz#935bc2dfd9458a876b279617514638bcaa964a2e"
+ integrity sha1-k1vC39lFiodrJ5YXUUY4vKqWSi4=
cli-boxes@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143"
+ integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM=
cli-cursor@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
+ integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=
dependencies:
restore-cursor "^2.0.0"
cli-width@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a"
+ integrity sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=
clipboard@^1.5.5, clipboard@^1.7.1:
version "1.7.1"
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-1.7.1.tgz#360d6d6946e99a7a1fef395e42ba92b5e9b5a16b"
+ integrity sha1-Ng1taUbpmnof7zleQrqStem1oWs=
dependencies:
good-listener "^1.2.2"
select "^1.1.2"
tiny-emitter "^2.0.0"
-cliui@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1"
- dependencies:
- center-align "^0.1.1"
- right-align "^0.1.1"
- wordwrap "0.0.2"
-
cliui@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.0.0.tgz#743d4650e05f36d1ed2575b59638d87322bfbbcc"
+ integrity sha512-nY3W5Gu2racvdDk//ELReY+dHjb9PlIcVDFXP72nVIhq2Gy3LuVXYwJoPVudwQnv1shtohpgkdCKT2YaKY0CKw==
dependencies:
string-width "^2.1.1"
strip-ansi "^4.0.0"
@@ -1643,28 +1924,29 @@ cliui@^4.0.0:
clone-response@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b"
+ integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=
dependencies:
mimic-response "^1.0.0"
-co@^4.6.0:
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
-
code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
+ integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
-codesandbox-api@^0.0.18:
- version "0.0.18"
- resolved "https://registry.yarnpkg.com/codesandbox-api/-/codesandbox-api-0.0.18.tgz#56b96b37533f80d20c21861e5e477d3557e613ca"
+codesandbox-api@^0.0.20:
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/codesandbox-api/-/codesandbox-api-0.0.20.tgz#174bcd76c9f31521175c6bceabc37da6b1fbc30b"
+ integrity sha512-jhxZzAmjCKBZad8QWMeueiQVFE87igK6F2DBOEVFFJO6jgTXT8qjuzGYepr+B8bjgo/icN7bc/2xmEMBA63s2w==
codesandbox-import-util-types@^1.2.11:
version "1.2.11"
resolved "https://registry.yarnpkg.com/codesandbox-import-util-types/-/codesandbox-import-util-types-1.2.11.tgz#68e812f21d6b309e9a52eec5cf027c3e63b4c703"
+ integrity sha512-n1PC/OQ0tcD9o6N5TStBB/A7tKOggUjuhnNxUU5GnVol8vmKMMLvmC6tK+8iDovQb2X2+xoDCBnl5BBgZ5OcIQ==
codesandbox-import-utils@^1.2.3:
version "1.2.11"
resolved "https://registry.yarnpkg.com/codesandbox-import-utils/-/codesandbox-import-utils-1.2.11.tgz#b88423a4a7c785175c784c84e87f5950820280e1"
+ integrity sha512-KPuf7tR/SMPSRfqjWbTrYvIaW6Yt9Ajt/1FB64RsOv4BLjBNo6CwLCCPoRHYcrAKSafpWkghTZ2Bffyz7EX7AA==
dependencies:
codesandbox-import-util-types "^1.2.11"
istextorbinary "^2.2.1"
@@ -1673,98 +1955,134 @@ codesandbox-import-utils@^1.2.3:
collection-visit@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0"
+ integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=
dependencies:
map-visit "^1.0.0"
object-visit "^1.0.0"
color-convert@^1.9.0:
- version "1.9.1"
- resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed"
+ version "1.9.3"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+ integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
dependencies:
- color-name "^1.1.1"
+ color-name "1.1.3"
-color-name@^1.1.1:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.2.tgz#5c8ab72b64bd2215d617ae9559ebb148475cf98d"
+color-name@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+ integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
colors@^1.1.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
+ integrity sha1-FopHAXVran9RoSzgyXv6KMCE7WM=
combine-lists@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/combine-lists/-/combine-lists-1.0.1.tgz#458c07e09e0d900fc28b70a3fec2dacd1d2cb7f6"
+ integrity sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=
dependencies:
lodash "^4.5.0"
-commander@2, commander@^2.13.0, commander@^2.15.1:
- version "2.15.1"
- resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
+commander@2, commander@^2.18.0, commander@^2.19.0:
+ version "2.19.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
+ integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
commander@~2.13.0:
version "2.13.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c"
+ integrity sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==
+
+commander@~2.17.1:
+ version "2.17.1"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf"
+ integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==
commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
+ integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
+
+compare-versions@^3.2.1:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.4.0.tgz#e0747df5c9cb7f054d6d3dc3e1dbc444f9e92b26"
+ integrity sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg==
component-bind@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1"
+ integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=
component-emitter@1.2.1, component-emitter@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6"
+ integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=
component-inherit@0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
+ integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=
-compressible@~2.0.10:
- version "2.0.11"
- resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.11.tgz#16718a75de283ed8e604041625a2064586797d8a"
+compressible@~2.0.14:
+ version "2.0.15"
+ resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.15.tgz#857a9ab0a7e5a07d8d837ed43fe2defff64fe212"
+ integrity sha512-4aE67DL33dSW9gw4CI2H/yTxqHLNcxp0yS6jB+4h+wr3e43+1z7vm0HU9qXOH8j+qjKuL8+UtkOxYQSMq60Ylw==
dependencies:
- mime-db ">= 1.29.0 < 2"
+ mime-db ">= 1.36.0 < 2"
-compression-webpack-plugin@^1.1.11:
- version "1.1.11"
- resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-1.1.11.tgz#8384c7a6ead1d2e2efb190bdfcdcf35878ed8266"
+compression-webpack-plugin@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-2.0.0.tgz#46476350c1eb27f783dccc79ac2f709baa2cffbc"
+ integrity sha512-bDgd7oTUZC8EkRx8j0sjyCfeiO+e5sFcfgaFcjVhfQf5lLya7oY2BczxcJ7IUuVjz5m6fy8IECFmVFew3xLk8Q==
dependencies:
- cacache "^10.0.1"
- find-cache-dir "^1.0.0"
+ cacache "^11.2.0"
+ find-cache-dir "^2.0.0"
neo-async "^2.5.0"
+ schema-utils "^1.0.0"
serialize-javascript "^1.4.0"
webpack-sources "^1.0.1"
compression@^1.5.2:
- version "1.7.0"
- resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.0.tgz#030c9f198f1643a057d776a738e922da4373012d"
+ version "1.7.3"
+ resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.3.tgz#27e0e176aaf260f7f2c2813c3e440adb9f1993db"
+ integrity sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==
dependencies:
- accepts "~1.3.3"
- bytes "2.5.0"
- compressible "~2.0.10"
- debug "2.6.8"
+ accepts "~1.3.5"
+ bytes "3.0.0"
+ compressible "~2.0.14"
+ debug "2.6.9"
on-headers "~1.0.1"
- safe-buffer "5.1.1"
- vary "~1.1.1"
+ safe-buffer "5.1.2"
+ vary "~1.1.2"
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
-concat-stream@^1.5.0, concat-stream@^1.6.0:
+concat-stream@^1.5.0:
version "1.6.2"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
+ integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
dependencies:
buffer-from "^1.0.0"
inherits "^2.0.3"
readable-stream "^2.2.2"
typedarray "^0.0.6"
+config-chain@~1.1.5:
+ version "1.1.12"
+ resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
+ integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==
+ dependencies:
+ ini "^1.3.4"
+ proto-list "~1.2.1"
+
configstore@^3.0.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.1.tgz#094ee662ab83fad9917678de114faaea8fcdca90"
+ integrity sha512-5oNkD/L++l0O6xGXxb1EWS7SivtjfGQlRyxJsYgE0Z495/L81e2h4/d3r969hoPXuFItzNOKMtsXgYG4c7dYvw==
dependencies:
dot-prop "^4.1.0"
graceful-fs "^4.1.2"
@@ -1776,10 +2094,12 @@ configstore@^3.0.0:
connect-history-api-fallback@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.3.0.tgz#e51d17f8f0ef0db90a64fdb47de3051556e9f169"
+ integrity sha1-5R0X+PDvDbkKZP20feMFFVbp8Wk=
connect@^3.6.0:
version "3.6.6"
resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.6.tgz#09eff6c55af7236e137135a72574858b6786f524"
+ integrity sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=
dependencies:
debug "2.6.9"
finalhandler "1.1.0"
@@ -1789,50 +2109,63 @@ connect@^3.6.0:
console-browserify@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10"
+ integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=
dependencies:
date-now "^0.1.4"
console-control-strings@^1.0.0, console-control-strings@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
+ integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
consolidate@^0.15.1:
version "0.15.1"
resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.15.1.tgz#21ab043235c71a07d45d9aad98593b0dba56bab7"
+ integrity sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==
dependencies:
bluebird "^3.1.1"
constants-browserify@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
+ integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=
contains-path@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a"
+ integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=
content-disposition@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
+ integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ=
content-type@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
+ integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
-convert-source-map@^1.5.1:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5"
+convert-source-map@^1.1.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20"
+ integrity sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==
+ dependencies:
+ safe-buffer "~5.1.1"
cookie-signature@1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
+ integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
cookie@0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb"
+ integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=
copy-concurrently@^1.0.0:
version "1.0.5"
resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0"
+ integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==
dependencies:
aproba "^1.1.1"
fs-write-stream-atomic "^1.0.8"
@@ -1844,22 +2177,34 @@ copy-concurrently@^1.0.0:
copy-descriptor@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
+ integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
-core-js@^2.2.0, core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0:
- version "2.5.3"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e"
+copy-to-clipboard@^3.0.8:
+ version "3.0.8"
+ resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.0.8.tgz#f4e82f4a8830dce4666b7eb8ded0c9bcc313aba9"
+ integrity sha512-c3GdeY8qxCHGezVb1EFQfHYK/8NZRemgcTIzPq7PuxjHAf/raKibn2QdhHPb/y6q74PMgH6yizaDZlRmw6QyKw==
+ dependencies:
+ toggle-selection "^1.0.3"
+
+core-js@^2.2.0, core-js@^2.4.0, core-js@^2.4.1:
+ version "2.5.7"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e"
+ integrity sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==
core-js@~2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.3.0.tgz#fab83fbb0b2d8dc85fa636c4b9d34c75420c6d65"
+ integrity sha1-+rg/uwstjchfpjbEudNMdUIMbWU=
core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+ integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
create-ecdh@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d"
+ integrity sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=
dependencies:
bn.js "^4.1.0"
elliptic "^6.0.0"
@@ -1867,12 +2212,14 @@ create-ecdh@^4.0.0:
create-error-class@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6"
+ integrity sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=
dependencies:
capture-stack-trace "^1.0.0"
create-hash@^1.1.0, create-hash@^1.1.2:
version "1.1.3"
resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.3.tgz#606042ac8b9262750f483caddab0f5819172d8fd"
+ integrity sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=
dependencies:
cipher-base "^1.0.1"
inherits "^2.0.1"
@@ -1882,6 +2229,7 @@ create-hash@^1.1.0, create-hash@^1.1.2:
create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
version "1.1.6"
resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.6.tgz#acb9e221a4e17bdb076e90657c42b93e3726cf06"
+ integrity sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=
dependencies:
cipher-base "^1.0.3"
create-hash "^1.1.0"
@@ -1893,20 +2241,23 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
cropper@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/cropper/-/cropper-2.3.0.tgz#607461d4e7aa7a7fe15a26834b14b7f0c2801562"
+ integrity sha1-YHRh1Oeqen/hWiaDSxS38MKAFWI=
dependencies:
jquery ">= 1.9.1"
-cross-spawn@^5.0.1, cross-spawn@^5.1.0:
+cross-spawn@^5.0.1:
version "5.1.0"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
+ integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=
dependencies:
lru-cache "^4.0.1"
shebang-command "^1.2.0"
which "^1.2.9"
-cross-spawn@^6.0.5:
+cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
+ integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
dependencies:
nice-try "^1.0.4"
path-key "^2.0.1"
@@ -1917,10 +2268,12 @@ cross-spawn@^6.0.5:
"crypt@>= 0.0.1":
version "0.0.2"
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
+ integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=
crypto-browserify@^3.11.0:
version "3.12.0"
resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
+ integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==
dependencies:
browserify-cipher "^1.0.0"
browserify-sign "^4.0.0"
@@ -1937,10 +2290,12 @@ crypto-browserify@^3.11.0:
crypto-random-string@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
+ integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=
css-loader@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-1.0.0.tgz#9f46aaa5ca41dbe31860e3b62b8e23c42916bf56"
+ integrity sha512-tMXlTYf3mIMt3b0dDCOQFJiVvxbocJ5Ho577WiGPYPZcqVEO218L2iU22pDXzkTZCLDE+9AmGSUkWxeh/nZReA==
dependencies:
babel-code-frame "^6.26.0"
css-selector-tokenizer "^0.7.0"
@@ -1958,10 +2313,12 @@ css-loader@^1.0.0:
css-selector-parser@^1.3:
version "1.3.0"
resolved "https://registry.yarnpkg.com/css-selector-parser/-/css-selector-parser-1.3.0.tgz#5f1ad43e2d8eefbfdc304fcd39a521664943e3eb"
+ integrity sha1-XxrUPi2O77/cME/NOaUhZklD4+s=
css-selector-tokenizer@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz#e6988474ae8c953477bf5e7efecfceccd9cf4c86"
+ integrity sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=
dependencies:
cssesc "^0.1.0"
fastparse "^1.1.1"
@@ -1970,32 +2327,32 @@ css-selector-tokenizer@^0.7.0:
cssesc@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4"
-
-currently-unhandled@^0.4.1:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
- dependencies:
- array-find-index "^1.0.1"
+ integrity sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=
custom-event@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425"
+ integrity sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=
cyclist@~0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
+ integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=
d3-array@1, d3-array@1.2.1, d3-array@^1.2.0, d3-array@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.1.tgz#d1ca33de2f6ac31efadb8e050a021d7e2396d5dc"
+ integrity sha512-CyINJQ0SOUHojDdFDH4JEM0552vCR1utGyLHegJHyYH0JyCpSeTPxi4OBqHMA2jJZq4NH782LtaJWBImqI/HBw==
d3-axis@1.0.8, d3-axis@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-1.0.8.tgz#31a705a0b535e65759de14173a31933137f18efa"
+ integrity sha1-MacFoLU15ldZ3hQXOjGTMTfxjvo=
d3-brush@1.0.4, d3-brush@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-1.0.4.tgz#00c2f238019f24f6c0a194a26d41a1530ffe7bc4"
+ integrity sha1-AMLyOAGfJPbAoZSibUGhUw/+e8Q=
dependencies:
d3-dispatch "1"
d3-drag "1"
@@ -2006,6 +2363,7 @@ d3-brush@1.0.4, d3-brush@^1.0.4:
d3-chord@1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-1.0.4.tgz#7dec4f0ba886f713fe111c45f763414f6f74ca2c"
+ integrity sha1-fexPC6iG9xP+ERxF92NBT290yiw=
dependencies:
d3-array "1"
d3-path "1"
@@ -2013,18 +2371,22 @@ d3-chord@1.0.4:
d3-collection@1, d3-collection@1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/d3-collection/-/d3-collection-1.0.4.tgz#342dfd12837c90974f33f1cc0a785aea570dcdc2"
+ integrity sha1-NC39EoN8kJdPM/HMCnha6lcNzcI=
d3-color@1, d3-color@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-1.0.3.tgz#bc7643fca8e53a8347e2fbdaffa236796b58509b"
+ integrity sha1-vHZD/KjlOoNH4vva/6I2eWtYUJs=
d3-dispatch@1, d3-dispatch@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-1.0.3.tgz#46e1491eaa9b58c358fce5be4e8bed626e7871f8"
+ integrity sha1-RuFJHqqbWMNY/OW+TovtYm54cfg=
d3-drag@1, d3-drag@1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-1.2.1.tgz#df8dd4c502fb490fc7462046a8ad98a5c479282d"
+ integrity sha512-Cg8/K2rTtzxzrb0fmnYOUeZHvwa4PHzwXOLZZPwtEs2SKLLKLXeYwZKBB+DlOxUvFmarOnmt//cU4+3US2lyyQ==
dependencies:
d3-dispatch "1"
d3-selection "1"
@@ -2032,6 +2394,7 @@ d3-drag@1, d3-drag@1.2.1:
d3-dsv@1, d3-dsv@1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-1.0.8.tgz#907e240d57b386618dc56468bacfe76bf19764ae"
+ integrity sha512-IVCJpQ+YGe3qu6odkPQI0KPqfxkhbP/oM1XhhE/DFiYmcXKfCRub4KXyiuehV1d4drjWVXHUWx4gHqhdZb6n/A==
dependencies:
commander "2"
iconv-lite "0.4"
@@ -2040,59 +2403,71 @@ d3-dsv@1, d3-dsv@1.0.8:
d3-ease@1, d3-ease@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-1.0.3.tgz#68bfbc349338a380c44d8acc4fbc3304aa2d8c0e"
+ integrity sha1-aL+8NJM4o4DETYrMT7wzBKotjA4=
d3-force@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-1.1.0.tgz#cebf3c694f1078fcc3d4daf8e567b2fbd70d4ea3"
+ integrity sha512-2HVQz3/VCQs0QeRNZTYb7GxoUCeb6bOzMp/cGcLa87awY9ZsPvXOGeZm0iaGBjXic6I1ysKwMn+g+5jSAdzwcg==
dependencies:
d3-collection "1"
d3-dispatch "1"
d3-quadtree "1"
d3-timer "1"
-d3-format@1, d3-format@1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.2.1.tgz#4e19ecdb081a341dafaf5f555ee956bcfdbf167f"
+d3-format@1, d3-format@1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.2.2.tgz#1a39c479c8a57fe5051b2e67a3bee27061a74e7a"
+ integrity sha512-zH9CfF/3C8zUI47nsiKfD0+AGDEuM8LwBIP7pBVpyR4l/sKkZqITmMtxRp04rwBrlshIZ17XeFAaovN3++wzkw==
d3-geo@1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-1.9.1.tgz#157e3b0f917379d0f73bebfff3be537f49fa7356"
+ integrity sha512-l9wL/cEQkyZQYXw3xbmLsH3eQ5ij+icNfo4r0GrLa5rOCZR/e/3am45IQ0FvQ5uMsv+77zBRunLc9ufTWSQYFA==
dependencies:
d3-array "1"
d3-hierarchy@1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.1.5.tgz#a1c845c42f84a206bcf1c01c01098ea4ddaa7a26"
+ integrity sha1-ochFxC+Eoga88cAcAQmOpN2qeiY=
d3-interpolate@1, d3-interpolate@1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.1.6.tgz#2cf395ae2381804df08aa1bf766b7f97b5f68fb6"
+ integrity sha512-mOnv5a+pZzkNIHtw/V6I+w9Lqm9L5bG3OTXPM5A+QO0yyVMQ4W1uZhR+VOJmazaOZXri2ppbiZ5BUNWT0pFM9A==
dependencies:
d3-color "1"
d3-path@1, d3-path@1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.5.tgz#241eb1849bd9e9e8021c0d0a799f8a0e8e441764"
+ integrity sha1-JB6xhJvZ6egCHA0KeZ+KDo5EF2Q=
d3-polygon@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-1.0.3.tgz#16888e9026460933f2b179652ad378224d382c62"
+ integrity sha1-FoiOkCZGCTPysXllKtN4Ik04LGI=
d3-quadtree@1, d3-quadtree@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-1.0.3.tgz#ac7987e3e23fe805a990f28e1b50d38fcb822438"
+ integrity sha1-rHmH4+I/6AWpkPKOG1DTj8uCJDg=
d3-queue@3.0.7:
version "3.0.7"
resolved "https://registry.yarnpkg.com/d3-queue/-/d3-queue-3.0.7.tgz#c93a2e54b417c0959129d7d73f6cf7d4292e7618"
+ integrity sha1-yTouVLQXwJWRKdfXP2z31Ckudhg=
d3-random@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-1.1.0.tgz#6642e506c6fa3a648595d2b2469788a8d12529d3"
+ integrity sha1-ZkLlBsb6OmSFldKyRpeIqNElKdM=
d3-request@1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/d3-request/-/d3-request-1.0.6.tgz#a1044a9ef4ec28c824171c9379fae6d79474b19f"
+ integrity sha512-FJj8ySY6GYuAJHZMaCQ83xEYE4KbkPkmxZ3Hu6zA1xxG2GD+z6P+Lyp+zjdsHf0xEbp2xcluDI50rCS855EQ6w==
dependencies:
d3-collection "1"
d3-dispatch "1"
@@ -2102,6 +2477,7 @@ d3-request@1.0.6:
d3-scale@1.0.7, d3-scale@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-1.0.7.tgz#fa90324b3ea8a776422bd0472afab0b252a0945d"
+ integrity sha512-KvU92czp2/qse5tUfGms6Kjig0AhHOwkzXG0+PqIJB3ke0WUv088AHMZI0OssO9NCkXt4RP8yju9rpH8aGB7Lw==
dependencies:
d3-array "^1.2.0"
d3-collection "1"
@@ -2111,33 +2487,39 @@ d3-scale@1.0.7, d3-scale@^1.0.7:
d3-time "1"
d3-time-format "2"
-d3-selection@1, d3-selection@1.2.0, d3-selection@^1.1.0, d3-selection@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.2.0.tgz#1b8ec1c7cedadfb691f2ba20a4a3cfbeb71bbc88"
+d3-selection@1, d3-selection@1.3.0, d3-selection@^1.1.0, d3-selection@^1.2.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.3.0.tgz#d53772382d3dc4f7507bfb28bcd2d6aed2a0ad6d"
+ integrity sha512-qgpUOg9tl5CirdqESUAu0t9MU/t3O9klYfGfyKsXEmhyxyzLpzpeh08gaxBUTQw1uXIOkr/30Ut2YRjSSxlmHA==
d3-shape@1.2.0, d3-shape@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.2.0.tgz#45d01538f064bafd05ea3d6d2cb748fd8c41f777"
+ integrity sha1-RdAVOPBkuv0F6j1tLLdI/YxB93c=
dependencies:
d3-path "1"
d3-time-format@2, d3-time-format@2.1.1, d3-time-format@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.1.1.tgz#85b7cdfbc9ffca187f14d3c456ffda268081bb31"
+ integrity sha512-8kAkymq2WMfzW7e+s/IUNAtN/y3gZXGRrdGfo6R8NKPAA85UBTxZg5E61bR6nLwjPjj4d3zywSQe1CkYLPFyrw==
dependencies:
d3-time "1"
d3-time@1, d3-time@1.0.8, d3-time@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.0.8.tgz#dbd2d6007bf416fe67a76d17947b784bffea1e84"
+ integrity sha512-YRZkNhphZh3KcnBfitvF3c6E0JOFGikHZ4YqD+Lzv83ZHn1/u6yGenRU1m+KAk9J1GnZMnKcrtfvSktlA1DXNQ==
d3-timer@1, d3-timer@1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.7.tgz#df9650ca587f6c96607ff4e60cc38229e8dd8531"
+ integrity sha512-vMZXR88XujmG/L5oB96NNKH5lCWwiLM/S2HyyAQLcjWJCloK5shxta4CwOFYLZoY3AWX73v8Lgv4cCAdWtRmOA==
d3-transition@1, d3-transition@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-1.1.1.tgz#d8ef89c3b848735b060e54a39b32aaebaa421039"
+ integrity sha512-xeg8oggyQ+y5eb4J13iDgKIjUcEfIOZs2BqV/eEmXm2twx80wTzJ4tB4vaZ5BKfz7XsI/DFmQL5me6O27/5ykQ==
dependencies:
d3-color "1"
d3-dispatch "1"
@@ -2149,10 +2531,12 @@ d3-transition@1, d3-transition@1.1.1:
d3-voronoi@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/d3-voronoi/-/d3-voronoi-1.1.2.tgz#1687667e8f13a2d158c80c1480c5a29cb0d8973c"
+ integrity sha1-Fodmfo8TotFYyAwUgMWinLDYlzw=
d3-zoom@1.7.1:
version "1.7.1"
resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-1.7.1.tgz#02f43b3c3e2db54f364582d7e4a236ccc5506b63"
+ integrity sha512-sZHQ55DGq5BZBFGnRshUT8tm2sfhPHFnOlmPbbwTkAoPeVdRTkB4Xsf9GCY0TSHrTD8PeJPZGmP/TpGicwJDJQ==
dependencies:
d3-dispatch "1"
d3-drag "1"
@@ -2160,13 +2544,10 @@ d3-zoom@1.7.1:
d3-selection "1"
d3-transition "1"
-d3@3.5.17:
- version "3.5.17"
- resolved "https://registry.yarnpkg.com/d3/-/d3-3.5.17.tgz#bc46748004378b21a360c9fc7cf5231790762fb8"
-
-d3@4.12.2:
- version "4.12.2"
- resolved "https://registry.yarnpkg.com/d3/-/d3-4.12.2.tgz#12f775564c6a9de229f63db03446e2cb7bb56c8f"
+d3@^4.13.0:
+ version "4.13.0"
+ resolved "https://registry.yarnpkg.com/d3/-/d3-4.13.0.tgz#ab236ff8cf0cfc27a81e69bf2fb7518bc9b4f33d"
+ integrity sha512-l8c4+0SldjVKLaE2WG++EQlqD7mh/dmQjvi2L2lKPadAVC+TbJC4ci7Uk9bRi+To0+ansgsS0iWfPjD7DBy+FQ==
dependencies:
d3-array "1.2.1"
d3-axis "1.0.8"
@@ -2179,7 +2560,7 @@ d3@4.12.2:
d3-dsv "1.0.8"
d3-ease "1.0.3"
d3-force "1.1.0"
- d3-format "1.2.1"
+ d3-format "1.2.2"
d3-geo "1.9.1"
d3-hierarchy "1.1.5"
d3-interpolate "1.1.6"
@@ -2190,7 +2571,7 @@ d3@4.12.2:
d3-random "1.1.0"
d3-request "1.0.6"
d3-scale "1.0.7"
- d3-selection "1.2.0"
+ d3-selection "1.3.0"
d3-shape "1.2.0"
d3-time "1.0.8"
d3-time-format "2.1.1"
@@ -2199,114 +2580,142 @@ d3@4.12.2:
d3-voronoi "1.1.2"
d3-zoom "1.7.1"
-dagre-d3-renderer@^0.4.24:
- version "0.4.24"
- resolved "https://registry.yarnpkg.com/dagre-d3-renderer/-/dagre-d3-renderer-0.4.24.tgz#b36ce2fe4ea20de43e7698627c6ede2a9f15ec45"
+dagre-d3-renderer@^0.5.8:
+ version "0.5.8"
+ resolved "https://registry.yarnpkg.com/dagre-d3-renderer/-/dagre-d3-renderer-0.5.8.tgz#aa071bb71d3c4d67426925906f3f6ddead49c1a3"
+ integrity sha512-XH2a86isUHRxzIYbjQVEuZtJnWEufb64H5DuXIUmn8esuB40jgLEbUUclulWOW62/ZoXlj2ZDyL8SJ+YRxs+jQ==
dependencies:
- d3 "3.5.17"
- dagre-layout "^0.8.0"
- graphlib "^2.1.1"
- lodash "^4.17.4"
+ dagre-layout "^0.8.8"
+ lodash "^4.17.5"
-dagre-layout@^0.8.0:
- version "0.8.0"
- resolved "https://registry.yarnpkg.com/dagre-layout/-/dagre-layout-0.8.0.tgz#7147b6afb655602f855158dfea171db9aa98d4ff"
+dagre-layout@^0.8.8:
+ version "0.8.8"
+ resolved "https://registry.yarnpkg.com/dagre-layout/-/dagre-layout-0.8.8.tgz#9b6792f24229f402441c14162c1049e3f261f6d9"
+ integrity sha512-ZNV15T9za7X+fV8Z07IZquUKugCxm5owoiPPxfEx6OJRD331nkiIaF3vSt0JEY5FkrY0KfRQxcpQ3SpXB7pLPQ==
dependencies:
- graphlib "^2.1.1"
- lodash "^4.17.4"
+ graphlibrary "^2.2.0"
+ lodash "^4.17.5"
date-format@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/date-format/-/date-format-1.2.0.tgz#615e828e233dd1ab9bb9ae0950e0ceccfa6ecad8"
+ integrity sha1-YV6CjiM90aubua4JUODOzPpuytg=
date-now@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
+ integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=
dateformat@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
+ integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
de-indent@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
+ integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=
-debug@2.6.8:
- version "2.6.8"
- resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
- dependencies:
- ms "2.0.0"
-
-debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9:
+debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+ integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
dependencies:
ms "2.0.0"
-debug@^3.0.1, debug@^3.1.0, debug@~3.1.0:
+debug@^3.1.0, debug@^3.2.5:
+ version "3.2.6"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
+ integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
+ dependencies:
+ ms "^2.1.1"
+
+debug@~3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+ integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
-decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+decamelize@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-2.0.0.tgz#656d7bbc8094c4c788ea53c5840908c9c7d063c7"
+ integrity sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==
+ dependencies:
+ xregexp "4.0.0"
deckar01-task_list@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/deckar01-task_list/-/deckar01-task_list-2.0.0.tgz#7f7a595430d21b3036ed5dfbf97d6b65de18e2c9"
+ integrity sha1-f3pZVDDSGzA27V37+X1rZd4Y4sk=
decode-uri-component@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
+ integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
decompress-response@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3"
+ integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=
dependencies:
mimic-response "^1.0.0"
deep-equal@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
+ integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=
-deep-extend@~0.4.0:
- version "0.4.2"
- resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f"
+deep-extend@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
+ integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
deep-is@~0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
+ integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
-default-require-extensions@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8"
+default-gateway@^2.6.0:
+ version "2.7.2"
+ resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-2.7.2.tgz#b7ef339e5e024b045467af403d50348db4642d0f"
+ integrity sha512-lAc4i9QJR0YHSDFdzeBQKfZ1SRDG3hsJNEkrpcZa8QhBfidLAilT60BDEIVUUGqosFp425KOgB3uYqcnQrWafQ==
dependencies:
- strip-bom "^2.0.0"
+ execa "^0.10.0"
+ ip-regex "^2.1.0"
+
+default-require-extensions@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7"
+ integrity sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=
+ dependencies:
+ strip-bom "^3.0.0"
define-properties@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94"
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
+ integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
dependencies:
- foreach "^2.0.5"
- object-keys "^1.0.8"
+ object-keys "^1.0.12"
define-property@^0.2.5:
version "0.2.5"
resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116"
+ integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=
dependencies:
is-descriptor "^0.1.0"
define-property@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6"
+ integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY=
dependencies:
is-descriptor "^1.0.0"
define-property@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d"
+ integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==
dependencies:
is-descriptor "^1.0.2"
isobject "^3.0.1"
@@ -2314,6 +2723,7 @@ define-property@^2.0.2:
del@^2.0.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8"
+ integrity sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=
dependencies:
globby "^5.0.0"
is-path-cwd "^1.0.0"
@@ -2326,6 +2736,7 @@ del@^2.0.2:
del@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5"
+ integrity sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=
dependencies:
globby "^6.1.0"
is-path-cwd "^1.0.0"
@@ -2337,18 +2748,27 @@ del@^3.0.0:
delegate@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.1.2.tgz#1e1bc6f5cadda6cb6cbf7e6d05d0bcdd5712aebe"
+ integrity sha1-HhvG9crdpstsv35tBdC83VcSrr4=
delegates@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
+ integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
-depd@1.1.1, depd@~1.1.1:
+depd@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359"
+ integrity sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=
+
+depd@~1.1.1, depd@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
+ integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
des.js@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc"
+ integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=
dependencies:
inherits "^2.0.1"
minimalistic-assert "^1.0.0"
@@ -2356,32 +2776,32 @@ des.js@^1.0.0:
destroy@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
-
-detect-indent@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208"
- dependencies:
- repeating "^2.0.0"
+ integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
detect-libc@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
+ integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
detect-node@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127"
+ integrity sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=
di@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
+ integrity sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=
diff@^3.2.0, diff@^3.4.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
+ integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
diffie-hellman@^5.0.0:
version "5.0.2"
resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e"
+ integrity sha1-tYNXOScM/ias9jIJn97SoH8gnl4=
dependencies:
bn.js "^4.1.0"
miller-rabin "^4.0.0"
@@ -2390,10 +2810,12 @@ diffie-hellman@^5.0.0:
dns-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
+ integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0=
dns-packet@^1.0.1:
version "1.2.2"
resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.2.2.tgz#a8a26bec7646438963fc86e06f8f8b16d6c8bf7a"
+ integrity sha512-kN+DjfGF7dJGUL7nWRktL9Z18t1rWP3aQlyZdY8XlpvU3Nc6GeFTQApftcjtWKxAZfiggZSGrCEoszNgvnpwDg==
dependencies:
ip "^1.1.0"
safe-buffer "^5.0.1"
@@ -2401,29 +2823,34 @@ dns-packet@^1.0.1:
dns-txt@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6"
+ integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=
dependencies:
buffer-indexof "^1.0.0"
doctrine@1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
+ integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=
dependencies:
esutils "^2.0.2"
isarray "^1.0.0"
-doctrine@^2.0.2:
+doctrine@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
+ integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==
dependencies:
esutils "^2.0.2"
document-register-element@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/document-register-element/-/document-register-element-1.3.0.tgz#fb3babb523c74662be47be19c6bc33e71990d940"
+ integrity sha1-+zurtSPHRmK+R74Zxrwz5xmQ2UA=
dom-serialize@^2.2.0:
version "2.2.1"
resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b"
+ integrity sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=
dependencies:
custom-event "~1.0.0"
ent "~2.2.0"
@@ -2433,6 +2860,7 @@ dom-serialize@^2.2.0:
dom-serializer@0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82"
+ integrity sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=
dependencies:
domelementtype "~1.1.1"
entities "~1.1.1"
@@ -2440,24 +2868,29 @@ dom-serializer@0:
domain-browser@^1.1.1:
version "1.1.7"
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc"
+ integrity sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=
domelementtype@1, domelementtype@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2"
+ integrity sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=
domelementtype@~1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b"
+ integrity sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=
domhandler@^2.3.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.1.tgz#892e47000a99be55bbf3774ffea0561d8879c259"
+ integrity sha1-iS5HAAqZvlW783dP/qBWHYh5wlk=
dependencies:
domelementtype "1"
domutils@^1.5.1:
version "1.6.2"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.6.2.tgz#1958cc0b4c9426e9ed367fb1c8e854891b0fa3ff"
+ integrity sha1-GVjMC0yUJuntNn+xyOhUiRsPo/8=
dependencies:
dom-serializer "0"
domelementtype "1"
@@ -2465,24 +2898,29 @@ domutils@^1.5.1:
dot-prop@^4.1.0, dot-prop@^4.1.1:
version "4.2.0"
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57"
+ integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==
dependencies:
is-obj "^1.0.0"
dropzone@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/dropzone/-/dropzone-4.2.0.tgz#fbe7acbb9918e0706489072ef663effeef8a79f3"
+ integrity sha1-++esu5kY4HBkiQcu9mPv/u+KefM=
duplexer3@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
+ integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
duplexer@^0.1.1, duplexer@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
+ integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=
duplexify@^3.4.2, duplexify@^3.5.3:
version "3.5.3"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.3.tgz#8b5818800df92fd0125b27ab896491912858243e"
+ integrity sha512-g8ID9OroF9hKt2POf8YLayy+9594PzmM3scI00/uBXocX3TWNgoB67hjzkFe9ITAbQOne/lLdBxHXvYUM4ZgGA==
dependencies:
end-of-stream "^1.0.0"
inherits "^2.0.1"
@@ -2492,18 +2930,39 @@ duplexify@^3.4.2, duplexify@^3.5.3:
editions@^1.3.3:
version "1.3.4"
resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b"
+ integrity sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==
+
+editorconfig@^0.15.0:
+ version "0.15.2"
+ resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.2.tgz#047be983abb9ab3c2eefe5199cb2b7c5689f0702"
+ integrity sha512-GWjSI19PVJAM9IZRGOS+YKI8LN+/sjkSjNyvxL5ucqP9/IqtYNXBaQ/6c/hkPNYQHyOHra2KoXZI/JVpuqwmcQ==
+ dependencies:
+ "@types/node" "^10.11.7"
+ "@types/semver" "^5.5.0"
+ commander "^2.19.0"
+ lru-cache "^4.1.3"
+ semver "^5.6.0"
+ sigmund "^1.0.1"
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+ integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
-ejs@^2.5.7:
- version "2.5.9"
- resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.9.tgz#7ba254582a560d267437109a68354112475b0ce5"
+ejs@^2.6.1:
+ version "2.6.1"
+ resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0"
+ integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==
+
+electron-to-chromium@^1.3.62:
+ version "1.3.73"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.73.tgz#aa67787067d58cc3920089368b3b8d6fe0fc12f6"
+ integrity sha512-6PIg7v9zRoVGh6EheRF8h6Plti+3Yo/qtHobS4/Htyt53DNHmKKGFqSae1AIk0k1S4gCQvt7I2WgpbuZNcDY+g==
elliptic@^6.0.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df"
+ integrity sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=
dependencies:
bn.js "^4.4.0"
brorand "^1.0.1"
@@ -2516,30 +2975,36 @@ elliptic@^6.0.0:
emoji-unicode-version@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/emoji-unicode-version/-/emoji-unicode-version-0.2.1.tgz#0ebf3666b5414097971d34994e299fce75cdbafc"
+ integrity sha1-Dr82ZrVBQJeXHTSZTimfznXNuvw=
emojis-list@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
+ integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k=
-encodeurl@~1.0.1:
+encodeurl@~1.0.1, encodeurl@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
+ integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
encoding@^0.1.11:
version "0.1.12"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
+ integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=
dependencies:
iconv-lite "~0.4.13"
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
+ integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==
dependencies:
once "^1.4.0"
engine.io-client@~3.2.0:
version "3.2.1"
resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-3.2.1.tgz#6f54c0475de487158a1a7c77d10178708b6add36"
+ integrity sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==
dependencies:
component-emitter "1.2.1"
component-inherit "0.0.3"
@@ -2556,6 +3021,7 @@ engine.io-client@~3.2.0:
engine.io-parser@~2.1.0, engine.io-parser@~2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-2.1.2.tgz#4c0f4cff79aaeecbbdcfdea66a823c6085409196"
+ integrity sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==
dependencies:
after "0.8.2"
arraybuffer.slice "~0.0.7"
@@ -2566,6 +3032,7 @@ engine.io-parser@~2.1.0, engine.io-parser@~2.1.1:
engine.io@~3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-3.2.0.tgz#54332506f42f2edc71690d2f2a42349359f3bf7d"
+ integrity sha512-mRbgmAtQ4GAlKwuPnnAvXXwdPhEx+jkc0OBCLrXuD/CRvwNK3AxRSnqK4FSqmAMRRHryVJP8TopOvmEaA64fKw==
dependencies:
accepts "~1.3.4"
base64id "1.0.0"
@@ -2577,6 +3044,7 @@ engine.io@~3.2.0:
enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f"
+ integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==
dependencies:
graceful-fs "^4.1.2"
memory-fs "^0.4.0"
@@ -2585,6 +3053,7 @@ enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0:
enhanced-resolve@~0.9.0:
version "0.9.1"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e"
+ integrity sha1-TW5omzcl+GCQknzMhs2fFjW4ni4=
dependencies:
graceful-fs "^4.1.2"
memory-fs "^0.2.0"
@@ -2593,26 +3062,31 @@ enhanced-resolve@~0.9.0:
ent@~2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d"
+ integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0=
entities@^1.1.1, entities@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
+ integrity sha1-blwtClYhtdra7O+AuQ7ftc13cvA=
errno@^0.1.3, errno@^0.1.4:
version "0.1.7"
resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618"
+ integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==
dependencies:
prr "~1.0.1"
-error-ex@^1.2.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.0.tgz#e67b43f3e82c96ea3a584ffee0b9fc3325d802d9"
+error-ex@^1.2.0, error-ex@^1.3.1:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
+ integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
dependencies:
is-arrayish "^0.2.1"
-es-abstract@^1.7.0:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.10.0.tgz#1ecb36c197842a00d8ee4c2dfd8646bb97d60864"
+es-abstract@^1.5.1, es-abstract@^1.6.1:
+ version "1.12.0"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165"
+ integrity sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==
dependencies:
es-to-primitive "^1.1.1"
function-bind "^1.1.1"
@@ -2623,6 +3097,7 @@ es-abstract@^1.7.0:
es-to-primitive@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d"
+ integrity sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=
dependencies:
is-callable "^1.1.1"
is-date-object "^1.0.1"
@@ -2631,18 +3106,27 @@ es-to-primitive@^1.1.1:
es6-promise@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.0.2.tgz#010d5858423a5f118979665f46486a95c6ee2bb6"
+ integrity sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=
escape-html@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+ integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+ integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
+
+escaper@^2.5.3:
+ version "2.5.3"
+ resolved "https://registry.yarnpkg.com/escaper/-/escaper-2.5.3.tgz#8b8fe90ba364054151ab7eff18b4ce43b1e13ab5"
+ integrity sha512-QGb9sFxBVpbzMggrKTX0ry1oiI4CSDAl9vIL702hzl1jGW8VZs7qfqTRX7WDOjoNDoEVGcEtu1ZOQgReSfT2kQ==
escodegen@1.8.x:
version "1.8.1"
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018"
+ integrity sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=
dependencies:
esprima "^2.7.1"
estraverse "^1.9.1"
@@ -2651,22 +3135,34 @@ escodegen@1.8.x:
optionalDependencies:
source-map "~0.2.0"
-eslint-config-airbnb-base@^12.1.0:
- version "12.1.0"
- resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-12.1.0.tgz#386441e54a12ccd957b0a92564a4bafebd747944"
+eslint-config-airbnb-base@^13.1.0:
+ version "13.1.0"
+ resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-13.1.0.tgz#b5a1b480b80dfad16433d6c4ad84e6605052c05c"
+ integrity sha512-XWwQtf3U3zIoKO1BbHh6aUhJZQweOwSt4c2JrPDg9FP3Ltv3+YfEv7jIDB8275tVnO/qOHbfuYg3kzw6Je7uWw==
dependencies:
eslint-restricted-globals "^0.1.1"
+ object.assign "^4.1.0"
+ object.entries "^1.0.4"
+
+eslint-config-prettier@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-3.1.0.tgz#2c26d2cdcfa3a05f0642cd7e6e4ef3316cdabfa2"
+ integrity sha512-QYGfmzuc4q4J6XIhlp8vRKdI/fI0tQfQPy1dME3UOLprE+v4ssH/3W9LM2Q7h5qBcy5m0ehCrBDU2YF8q6OY8w==
+ dependencies:
+ get-stdin "^6.0.0"
eslint-import-resolver-node@^0.3.1:
version "0.3.2"
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a"
+ integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==
dependencies:
debug "^2.6.9"
resolve "^1.5.0"
-eslint-import-resolver-webpack@^0.10.0:
- version "0.10.0"
- resolved "https://registry.yarnpkg.com/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.10.0.tgz#b6f2468dc3e8b4ea076e5d75bece8da932789b07"
+eslint-import-resolver-webpack@^0.10.1:
+ version "0.10.1"
+ resolved "https://registry.yarnpkg.com/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.10.1.tgz#4cbceed2c0c43e488a74775c30861e58e00fb290"
+ integrity sha512-RN49nnyQpBCP3TqVhct+duJjH8kaVg08fFevWvA+4Cr1xeN7OFQRse4wMvzBto9/4VmOJWvqPfdmNTEG3jc8SQ==
dependencies:
array-find "^1.0.0"
debug "^2.6.8"
@@ -2682,28 +3178,32 @@ eslint-import-resolver-webpack@^0.10.0:
eslint-module-utils@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz#b270362cd88b1a48ad308976ce7fa54e98411746"
+ integrity sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=
dependencies:
debug "^2.6.8"
pkg-dir "^1.0.0"
-eslint-plugin-filenames@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-filenames/-/eslint-plugin-filenames-1.2.0.tgz#aee9c1c90189c95d2e49902c160eceefecd99f53"
+eslint-plugin-filenames@^1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-filenames/-/eslint-plugin-filenames-1.3.2.tgz#7094f00d7aefdd6999e3ac19f72cea058e590cf7"
+ integrity sha512-tqxJTiEM5a0JmRCUYQmxw23vtTxrb2+a3Q2mMOPhFxvt7ZQQJmdiuMby9B/vUAuVMghyP7oET+nIf6EO6CBd/w==
dependencies:
lodash.camelcase "4.3.0"
lodash.kebabcase "4.1.1"
lodash.snakecase "4.1.1"
lodash.upperfirst "4.3.1"
-eslint-plugin-html@4.0.3:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-4.0.3.tgz#97d52dcf9e22724505d02719fbd02754013c8a17"
+eslint-plugin-html@4.0.5:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-4.0.5.tgz#e8ec7e16485124460f3bff312016feb0a54d9659"
+ integrity sha512-yULqYldzhYXTwZEaJXM30HhfgJdtTzuVH3LeoANybESHZ5+2ztLD72BsB2wR124/kk/PvQqZofDFSdNIk+kykw==
dependencies:
htmlparser2 "^3.8.2"
-eslint-plugin-import@^2.12.0:
- version "2.12.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.12.0.tgz#dad31781292d6664b25317fd049d2e2b2f02205d"
+eslint-plugin-import@^2.14.0:
+ version "2.14.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz#6b17626d2e3e6ad52cfce8807a845d15e22111a8"
+ integrity sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==
dependencies:
contains-path "^0.1.0"
debug "^2.6.8"
@@ -2716,127 +3216,159 @@ eslint-plugin-import@^2.12.0:
read-pkg-up "^2.0.0"
resolve "^1.6.0"
-eslint-plugin-jasmine@^2.1.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-jasmine/-/eslint-plugin-jasmine-2.2.0.tgz#7135879383c39a667c721d302b9f20f0389543de"
+eslint-plugin-jasmine@^2.10.1:
+ version "2.10.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-jasmine/-/eslint-plugin-jasmine-2.10.1.tgz#5733b709e751f4bc40e31e1c16989bd2cdfbec97"
+ integrity sha1-VzO3CedR9LxA4x4cFpib0s377Jc=
-eslint-plugin-promise@^3.8.0:
- version "3.8.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz#65ebf27a845e3c1e9d6f6a5622ddd3801694b621"
+eslint-plugin-promise@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz#2d074b653f35a23d1ba89d8e976a985117d1c6a2"
+ integrity sha512-Si16O0+Hqz1gDHsys6RtFRrW7cCTB6P7p3OJmKp3Y3dxpQE2qwOA7d3xnV+0mBmrPoi0RBnxlCKvqu70te6wjg==
-eslint-plugin-vue@^4.5.0:
- version "4.5.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-4.5.0.tgz#09d6597f4849e31a3846c2c395fccf17685b69c3"
+eslint-plugin-vue@^5.0.0-beta.3:
+ version "5.0.0-beta.3"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-5.0.0-beta.3.tgz#f3fa9f109b76e20fc1e45a71ce7c6d567118924e"
+ integrity sha512-EOQo3ax4CIM6Itcl522p4cGlSBgR/KZBJo2Xc29PWknbYH/DRZorGutF8NATUpbZ4HYOG+Gcyd1nL08iyYF3Tg==
dependencies:
- vue-eslint-parser "^2.0.3"
+ vue-eslint-parser "^3.2.1"
eslint-restricted-globals@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz#35f0d5cbc64c2e3ed62e93b4b1a7af05ba7ed4d7"
+ integrity sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=
-eslint-scope@^3.7.1, eslint-scope@~3.7.1:
+eslint-scope@3.7.1:
version "3.7.1"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8"
+ integrity sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=
+ dependencies:
+ esrecurse "^4.1.0"
+ estraverse "^4.1.1"
+
+eslint-scope@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172"
+ integrity sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==
dependencies:
esrecurse "^4.1.0"
estraverse "^4.1.1"
+eslint-utils@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512"
+ integrity sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==
+
eslint-visitor-keys@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
+ integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==
-eslint@~4.12.1:
- version "4.12.1"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.12.1.tgz#5ec1973822b4a066b353770c3c6d69a2a188e880"
+eslint@~5.6.0:
+ version "5.6.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.6.0.tgz#b6f7806041af01f71b3f1895cbb20971ea4b6223"
+ integrity sha512-/eVYs9VVVboX286mBK7bbKnO1yamUy2UCRjiY6MryhQL2PaaXCExsCQ2aO83OeYRhU2eCU/FMFP+tVMoOrzNrA==
dependencies:
- ajv "^5.3.0"
- babel-code-frame "^6.22.0"
+ "@babel/code-frame" "^7.0.0"
+ ajv "^6.5.3"
chalk "^2.1.0"
- concat-stream "^1.6.0"
- cross-spawn "^5.1.0"
- debug "^3.0.1"
- doctrine "^2.0.2"
- eslint-scope "^3.7.1"
- espree "^3.5.2"
- esquery "^1.0.0"
- estraverse "^4.2.0"
+ cross-spawn "^6.0.5"
+ debug "^3.1.0"
+ doctrine "^2.1.0"
+ eslint-scope "^4.0.0"
+ eslint-utils "^1.3.1"
+ eslint-visitor-keys "^1.0.0"
+ espree "^4.0.0"
+ esquery "^1.0.1"
esutils "^2.0.2"
file-entry-cache "^2.0.0"
functional-red-black-tree "^1.0.1"
glob "^7.1.2"
- globals "^11.0.1"
- ignore "^3.3.3"
+ globals "^11.7.0"
+ ignore "^4.0.6"
imurmurhash "^0.1.4"
- inquirer "^3.0.6"
- is-resolvable "^1.0.0"
- js-yaml "^3.9.1"
+ inquirer "^6.1.0"
+ is-resolvable "^1.1.0"
+ js-yaml "^3.12.0"
json-stable-stringify-without-jsonify "^1.0.1"
levn "^0.3.0"
- lodash "^4.17.4"
- minimatch "^3.0.2"
+ lodash "^4.17.5"
+ minimatch "^3.0.4"
mkdirp "^0.5.1"
natural-compare "^1.4.0"
optionator "^0.8.2"
path-is-inside "^1.0.2"
pluralize "^7.0.0"
progress "^2.0.0"
+ regexpp "^2.0.0"
require-uncached "^1.0.3"
- semver "^5.3.0"
+ semver "^5.5.1"
strip-ansi "^4.0.0"
- strip-json-comments "~2.0.1"
- table "^4.0.1"
- text-table "~0.2.0"
+ strip-json-comments "^2.0.1"
+ table "^4.0.3"
+ text-table "^0.2.0"
-espree@^3.5.2:
- version "3.5.4"
- resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7"
+espree@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-4.0.0.tgz#253998f20a0f82db5d866385799d912a83a36634"
+ integrity sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==
dependencies:
- acorn "^5.5.0"
- acorn-jsx "^3.0.0"
+ acorn "^5.6.0"
+ acorn-jsx "^4.1.1"
esprima@2.7.x, esprima@^2.7.1:
version "2.7.3"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581"
+ integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=
esprima@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804"
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
+ integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
-esquery@^1.0.0:
+esquery@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708"
+ integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==
dependencies:
estraverse "^4.0.0"
esrecurse@^4.1.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf"
+ integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==
dependencies:
estraverse "^4.1.0"
estraverse@^1.9.1:
version "1.9.3"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44"
+ integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=
-estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
+estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1:
version "4.2.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
+ integrity sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=
esutils@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
+ integrity sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=
etag@~1.8.1:
version "1.8.1"
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
+ integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
eve-raphael@0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/eve-raphael/-/eve-raphael-0.5.0.tgz#17c754b792beef3fa6684d79cf5a47c63c4cda30"
+ integrity sha1-F8dUt5K+7z+maE15z1pHxjxM2jA=
event-stream@~3.3.0:
version "3.3.4"
resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
+ integrity sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=
dependencies:
duplexer "~0.1.1"
from "~0"
@@ -2849,27 +3381,45 @@ event-stream@~3.3.0:
eventemitter3@1.x.x:
version "1.2.0"
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508"
+ integrity sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=
events@^1.0.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
+ integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=
-eventsource@0.1.6:
- version "0.1.6"
- resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-0.1.6.tgz#0acede849ed7dd1ccc32c811bb11b944d4f29232"
+eventsource@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.0.7.tgz#8fbc72c93fcd34088090bc0a4e64f4b5cee6d8d0"
+ integrity sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==
dependencies:
- original ">=0.0.5"
+ original "^1.0.0"
evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02"
+ integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==
dependencies:
md5.js "^1.3.4"
safe-buffer "^5.1.1"
+execa@^0.10.0:
+ version "0.10.0"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-0.10.0.tgz#ff456a8f53f90f8eccc71a96d11bdfc7f082cb50"
+ integrity sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==
+ dependencies:
+ cross-spawn "^6.0.0"
+ get-stream "^3.0.0"
+ is-stream "^1.1.0"
+ npm-run-path "^2.0.0"
+ p-finally "^1.0.0"
+ signal-exit "^3.0.0"
+ strip-eof "^1.0.0"
+
execa@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
+ integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=
dependencies:
cross-spawn "^5.0.1"
get-stream "^3.0.0"
@@ -2882,6 +3432,7 @@ execa@^0.7.0:
expand-braces@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/expand-braces/-/expand-braces-0.1.2.tgz#488b1d1d2451cb3d3a6b192cfc030f44c5855fea"
+ integrity sha1-SIsdHSRRyz06axks/AMPRMWFX+o=
dependencies:
array-slice "^0.2.3"
array-unique "^0.2.1"
@@ -2890,6 +3441,7 @@ expand-braces@^0.1.1:
expand-brackets@^2.1.4:
version "2.1.4"
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
+ integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI=
dependencies:
debug "^2.3.3"
define-property "^0.2.5"
@@ -2902,6 +3454,7 @@ expand-brackets@^2.1.4:
expand-range@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-0.1.1.tgz#4cb8eda0993ca56fa4f41fc42f3cbb4ccadff044"
+ integrity sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=
dependencies:
is-number "^0.1.1"
repeat-string "^0.2.2"
@@ -2909,15 +3462,17 @@ expand-range@^0.1.0:
exports-loader@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/exports-loader/-/exports-loader-0.7.0.tgz#84881c784dea6036b8e1cd1dac3da9b6409e21a5"
+ integrity sha512-RKwCrO4A6IiKm0pG3c9V46JxIHcDplwwGJn6+JJ1RcVnh/WSGJa0xkmk5cRVtgOPzCAtTMGj2F7nluh9L0vpSA==
dependencies:
loader-utils "^1.1.0"
source-map "0.5.0"
-express@^4.16.2:
- version "4.16.2"
- resolved "https://registry.yarnpkg.com/express/-/express-4.16.2.tgz#e35c6dfe2d64b7dca0a5cd4f21781be3299e076c"
+express@^4.16.2, express@^4.16.3:
+ version "4.16.3"
+ resolved "http://registry.npmjs.org/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53"
+ integrity sha1-avilAjUNsyRuzEvs9rWjTSL37VM=
dependencies:
- accepts "~1.3.4"
+ accepts "~1.3.5"
array-flatten "1.1.1"
body-parser "1.18.2"
content-disposition "0.5.2"
@@ -2925,49 +3480,53 @@ express@^4.16.2:
cookie "0.3.1"
cookie-signature "1.0.6"
debug "2.6.9"
- depd "~1.1.1"
- encodeurl "~1.0.1"
+ depd "~1.1.2"
+ encodeurl "~1.0.2"
escape-html "~1.0.3"
etag "~1.8.1"
- finalhandler "1.1.0"
+ finalhandler "1.1.1"
fresh "0.5.2"
merge-descriptors "1.0.1"
methods "~1.1.2"
on-finished "~2.3.0"
parseurl "~1.3.2"
path-to-regexp "0.1.7"
- proxy-addr "~2.0.2"
+ proxy-addr "~2.0.3"
qs "6.5.1"
range-parser "~1.2.0"
safe-buffer "5.1.1"
- send "0.16.1"
- serve-static "1.13.1"
+ send "0.16.2"
+ serve-static "1.13.2"
setprototypeof "1.1.0"
- statuses "~1.3.1"
- type-is "~1.6.15"
+ statuses "~1.4.0"
+ type-is "~1.6.16"
utils-merge "1.0.1"
vary "~1.1.2"
extend-shallow@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f"
+ integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=
dependencies:
is-extendable "^0.1.0"
extend-shallow@^3.0.0, extend-shallow@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8"
+ integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=
dependencies:
assign-symbols "^1.0.0"
is-extendable "^1.0.1"
extend@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
+ integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
-external-editor@^2.0.1, external-editor@^2.0.4:
+external-editor@^2.0.1:
version "2.2.0"
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5"
+ integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==
dependencies:
chardet "^0.4.0"
iconv-lite "^0.4.17"
@@ -2976,6 +3535,7 @@ external-editor@^2.0.1, external-editor@^2.0.4:
external-editor@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.0.tgz#dc35c48c6f98a30ca27a20e9687d7f3c77704bb6"
+ integrity sha512-mpkfj0FEdxrIhOC04zk85X7StNtr0yXnG7zCb+8ikO8OJi2jsHh5YGoknNTyXgsbHOf1WOOcVU3kPFWT2WgCkQ==
dependencies:
chardet "^0.5.0"
iconv-lite "^0.4.22"
@@ -2984,6 +3544,7 @@ external-editor@^3.0.0:
extglob@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
+ integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==
dependencies:
array-unique "^0.3.2"
define-property "^1.0.0"
@@ -2994,68 +3555,85 @@ extglob@^2.0.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
-fast-deep-equal@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff"
+fast-deep-equal@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
+ integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
fast-json-stable-stringify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
+ integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
fast-levenshtein@~2.0.4:
version "2.0.6"
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+ integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
fastparse@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8"
+ integrity sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=
faye-websocket@^0.10.0:
version "0.10.0"
resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4"
+ integrity sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=
dependencies:
websocket-driver ">=0.5.1"
-faye-websocket@~0.11.0:
+faye-websocket@~0.11.1:
version "0.11.1"
resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.1.tgz#f0efe18c4f56e4f40afc7e06c719fd5ee6188f38"
+ integrity sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=
dependencies:
websocket-driver ">=0.5.1"
+figgy-pudding@^3.1.0, figgy-pudding@^3.5.1:
+ version "3.5.1"
+ resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
+ integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==
+
figures@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
+ integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=
dependencies:
escape-string-regexp "^1.0.5"
file-entry-cache@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361"
+ integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=
dependencies:
flat-cache "^1.2.1"
object-assign "^4.0.1"
-file-loader@^1.1.11:
- version "1.1.11"
- resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-1.1.11.tgz#6fe886449b0f2a936e43cabaac0cdbfb369506f8"
+file-loader@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-2.0.0.tgz#39749c82f020b9e85901dcff98e8004e6401cfde"
+ integrity sha512-YCsBfd1ZGCyonOKLxPiKPdu+8ld9HAaMEvJewzz+b2eTF7uL5Zm/HdBF6FjCrpCMRq25Mi0U1gl4pwn2TlH7hQ==
dependencies:
loader-utils "^1.0.2"
- schema-utils "^0.4.5"
+ schema-utils "^1.0.0"
-fileset@^2.0.2:
+fileset@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0"
+ integrity sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=
dependencies:
glob "^7.0.3"
minimatch "^3.0.3"
-filesize@^3.5.11:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.0.tgz#22d079615624bb6fd3c04026120628a41b3f4efa"
+filesize@^3.6.1:
+ version "3.6.1"
+ resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317"
+ integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==
fill-range@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
+ integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=
dependencies:
extend-shallow "^2.0.1"
is-number "^3.0.0"
@@ -3065,6 +3643,7 @@ fill-range@^4.0.0:
finalhandler@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5"
+ integrity sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=
dependencies:
debug "2.6.9"
encodeurl "~1.0.1"
@@ -3074,21 +3653,46 @@ finalhandler@1.1.0:
statuses "~1.3.1"
unpipe "~1.0.0"
+finalhandler@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105"
+ integrity sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==
+ dependencies:
+ debug "2.6.9"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ on-finished "~2.3.0"
+ parseurl "~1.3.2"
+ statuses "~1.4.0"
+ unpipe "~1.0.0"
+
find-cache-dir@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f"
+ integrity sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=
dependencies:
commondir "^1.0.1"
make-dir "^1.0.0"
pkg-dir "^2.0.0"
+find-cache-dir@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.0.0.tgz#4c1faed59f45184530fb9d7fa123a4d04a98472d"
+ integrity sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==
+ dependencies:
+ commondir "^1.0.1"
+ make-dir "^1.0.0"
+ pkg-dir "^3.0.0"
+
find-root@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4"
+ integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==
find-up@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
+ integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=
dependencies:
path-exists "^2.0.0"
pinkie-promise "^2.0.0"
@@ -3096,12 +3700,21 @@ find-up@^1.0.0:
find-up@^2.0.0, find-up@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
+ integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c=
dependencies:
locate-path "^2.0.0"
+find-up@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
+ integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
+ dependencies:
+ locate-path "^3.0.0"
+
flat-cache@^1.2.1:
version "1.2.2"
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96"
+ integrity sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=
dependencies:
circular-json "^0.3.1"
del "^2.0.2"
@@ -3111,6 +3724,7 @@ flat-cache@^1.2.1:
flush-write-stream@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.2.tgz#c81b90d8746766f1a609a46809946c45dd8ae417"
+ integrity sha1-yBuQ2HRnZvGmCaRoCZRsRd2K5Bc=
dependencies:
inherits "^2.0.1"
readable-stream "^2.0.4"
@@ -3118,38 +3732,41 @@ flush-write-stream@^1.0.0:
follow-redirects@^1.2.5:
version "1.2.6"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.2.6.tgz#4dcdc7e4ab3dd6765a97ff89c3b4c258117c79bf"
+ integrity sha512-FrMqZ/FONtHnbqO651UPpfRUVukIEwJhXMfdr/JWAmrDbeYBu773b1J6gdWDyRIj4hvvzQEHoEOTrdR8o6KLYA==
dependencies:
debug "^3.1.0"
for-in@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
-
-foreach@^2.0.5:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99"
+ integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
formdata-polyfill@^3.0.11:
version "3.0.11"
resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-3.0.11.tgz#c82b4b4bea3356c0a6752219e54ce1edb2a7fb5b"
+ integrity sha512-lDyjdlptnGL1Fk7q+hketv31EN9rWaVC/SLz1tRaUktGrsCijyueIcjn7Tw3xKEdCjS5SeBrWp5aNLWUQq+QLg==
forwarded@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
+ integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=
fragment-cache@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
+ integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=
dependencies:
map-cache "^0.2.2"
fresh@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+ integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
from2@^2.1.0, from2@^2.1.1:
version "2.3.0"
resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af"
+ integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=
dependencies:
inherits "^2.0.1"
readable-stream "^2.0.0"
@@ -3157,22 +3774,26 @@ from2@^2.1.0, from2@^2.1.1:
from@~0:
version "0.1.7"
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
+ integrity sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=
fs-access@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/fs-access/-/fs-access-1.0.1.tgz#d6a87f262271cefebec30c553407fb995da8777a"
+ integrity sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=
dependencies:
null-check "^1.0.0"
fs-minipass@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d"
+ integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==
dependencies:
minipass "^2.2.1"
fs-write-stream-atomic@^1.0.8:
version "1.0.10"
resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9"
+ integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=
dependencies:
graceful-fs "^4.1.2"
iferr "^0.1.5"
@@ -3182,29 +3803,35 @@ fs-write-stream-atomic@^1.0.8:
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+ integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
fsevents@^1.2.2:
version "1.2.4"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426"
+ integrity sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==
dependencies:
nan "^2.9.2"
node-pre-gyp "^0.10.0"
-function-bind@^1.0.2, function-bind@^1.1.1:
+function-bind@^1.0.2, function-bind@^1.1.0, function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+ integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
functional-red-black-tree@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
+ integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
fuzzaldrin-plus@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/fuzzaldrin-plus/-/fuzzaldrin-plus-0.5.0.tgz#ef5f26f0c2fc7e9e9a16ea149a802d6cb4804b1e"
+ integrity sha1-718m8ML8fp6aFuoUmoAtbLSASx4=
gauge@~2.7.3:
version "2.7.4"
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
+ integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=
dependencies:
aproba "^1.0.3"
console-control-strings "^1.0.0"
@@ -3218,22 +3845,27 @@ gauge@~2.7.3:
get-caller-file@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
+ integrity sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=
-get-stdin@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
+get-stdin@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b"
+ integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==
get-stream@3.0.0, get-stream@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
+ integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
get-value@^2.0.3, get-value@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
+ integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=
gettext-extractor-vue@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/gettext-extractor-vue/-/gettext-extractor-vue-4.0.1.tgz#69d2737eb8f1938803ffcf9317133ed59fb2372f"
+ integrity sha512-UnkWVO5jQQrs17L7HSlKj3O7U8C4+AQFzE05MK/I+JkMZdQdB6JMjA0IK0c4GObSlkgx4aiCCG6zWqIBnDR95w==
dependencies:
bluebird "^3.5.1"
glob "^7.1.2"
@@ -3242,6 +3874,7 @@ gettext-extractor-vue@^4.0.1:
gettext-extractor@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/gettext-extractor/-/gettext-extractor-3.3.2.tgz#d5172ba8d175678bd40a5abe7f908fa2a9d9473b"
+ integrity sha1-1RcrqNF1Z4vUClq+f5CPoqnZRzs=
dependencies:
"@types/glob" "^5"
"@types/parse5" "^5"
@@ -3254,13 +3887,15 @@ gettext-extractor@^3.3.2:
glob-parent@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
+ integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=
dependencies:
is-glob "^3.1.0"
path-dirname "^1.0.0"
"glob@5 - 7", glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2:
- version "7.1.2"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
+ version "7.1.3"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
+ integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
@@ -3272,6 +3907,7 @@ glob-parent@^3.1.0:
glob@^5.0.15:
version "5.0.15"
resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1"
+ integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=
dependencies:
inflight "^1.0.4"
inherits "2"
@@ -3282,24 +3918,29 @@ glob@^5.0.15:
global-dirs@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445"
+ integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=
dependencies:
ini "^1.3.4"
global-modules-path@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/global-modules-path/-/global-modules-path-2.1.0.tgz#923ec524e8726bb0c1a4ed4b8e21e1ff80c88bbb"
+ integrity sha512-3DrmGj2TP+96cABk9TfMp6f3knH/Y46dqvWznTU3Tf6/bDGLDAn15tFluQ7BcloykOcdY16U0WGq0BQblYOxJQ==
-globals@^11.0.1, globals@^11.1.0:
- version "11.5.0"
- resolved "https://registry.yarnpkg.com/globals/-/globals-11.5.0.tgz#6bc840de6771173b191f13d3a9c94d441ee92642"
+globals@^11.1.0, globals@^11.7.0:
+ version "11.7.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-11.7.0.tgz#a583faa43055b1aca771914bf68258e2fc125673"
+ integrity sha512-K8BNSPySfeShBQXsahYB/AbbWruVOTyVpgoIDnl8odPpeSfP2J5QO2oLFFdl2j7GfDCtZj2bMKar2T49itTPCg==
globals@^9.18.0:
version "9.18.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
+ integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==
globby@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
+ integrity sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=
dependencies:
array-union "^1.0.1"
arrify "^1.0.0"
@@ -3311,6 +3952,7 @@ globby@^5.0.0:
globby@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c"
+ integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=
dependencies:
array-union "^1.0.1"
glob "^7.0.3"
@@ -3321,12 +3963,14 @@ globby@^6.1.0:
good-listener@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
+ integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=
dependencies:
delegate "^3.1.2"
got@^6.7.1:
version "6.7.1"
resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0"
+ integrity sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=
dependencies:
create-error-class "^3.0.0"
duplexer3 "^0.1.4"
@@ -3343,6 +3987,7 @@ got@^6.7.1:
got@^8.0.3:
version "8.3.0"
resolved "https://registry.yarnpkg.com/got/-/got-8.3.0.tgz#6ba26e75f8a6cc4c6b3eb1fe7ce4fec7abac8533"
+ integrity sha512-kBNy/S2CGwrYgDSec5KTWGKUvupwkkTVAjIsVFF2shXO13xpZdFP4d4kxa//CLX2tN/rV0aYwK8vY6UKWGn2vQ==
dependencies:
"@sindresorhus/is" "^0.7.0"
cacheable-request "^2.1.1"
@@ -3365,16 +4010,38 @@ got@^8.0.3:
graceful-fs@^4.1.11, graceful-fs@^4.1.2:
version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
+ integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=
-graphlib@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.1.tgz#42352c52ba2f4d035cb566eb91f7395f76ebc951"
+graphlibrary@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/graphlibrary/-/graphlibrary-2.2.0.tgz#017a14899775228dec4497a39babfdd6bf56eac6"
+ integrity sha512-XTcvT55L8u4MBZrM37zXoUxsgxs/7sow7YSygd9CIwfWTVO8RVu7AYXhhCiTuFEf+APKgx6Jk4SuQbYR0vYKmQ==
dependencies:
- lodash "^4.11.1"
+ lodash "^4.17.5"
-gzip-size@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-4.1.0.tgz#8ae096257eabe7d69c45be2b67c448124ffb517c"
+graphql-anywhere@^4.1.0-alpha.0:
+ version "4.1.22"
+ resolved "https://registry.yarnpkg.com/graphql-anywhere/-/graphql-anywhere-4.1.22.tgz#1c831ba3c9e5664a0dd24d10d23a9e9512d92056"
+ integrity sha512-qm2/1cKM8nfotxDhm4J0r1znVlK0Yge/yEKt26EVVBgpIhvxjXYFALCGbr7cvfDlvzal1iSPpaYa+8YTtjsxQA==
+ dependencies:
+ apollo-utilities "^1.0.25"
+
+graphql-tag@^2.10.0, graphql-tag@^2.4.2:
+ version "2.10.0"
+ resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.10.0.tgz#87da024be863e357551b2b8700e496ee2d4353ae"
+ integrity sha512-9FD6cw976TLLf9WYIUPCaaTpniawIjHWZSwIRZSjrfufJamcXbVVYfN2TWvJYbw0Xf2JjYbl1/f2+wDnBVw3/w==
+
+graphql@^14.0.2:
+ version "14.0.2"
+ resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.0.2.tgz#7dded337a4c3fd2d075692323384034b357f5650"
+ integrity sha512-gUC4YYsaiSJT1h40krG3J+USGlwhzNTXSb4IOZljn9ag5Tj+RkoXrWp+Kh7WyE3t1NCfab5kzCuxBIvOMERMXw==
+ dependencies:
+ iterall "^1.2.2"
+
+gzip-size@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.0.0.tgz#a55ecd99222f4c48fd8c01c625ce3b349d0a0e80"
+ integrity sha512-5iI7omclyqrnWw4XbXAmGhPsABkSIDQonv2K0h61lybgofWa6iZyvrI3r2zsJH4P8Nb64fFVzlvfhs0g7BBxAA==
dependencies:
duplexer "^0.1.1"
pify "^3.0.0"
@@ -3382,58 +4049,74 @@ gzip-size@^4.1.0:
handle-thing@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4"
+ integrity sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=
-handlebars@^4.0.1, handlebars@^4.0.3:
- version "4.0.6"
- resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.6.tgz#2ce4484850537f9c97a8026d5399b935c4ed4ed7"
+handlebars@^4.0.1, handlebars@^4.0.11:
+ version "4.0.12"
+ resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.12.tgz#2c15c8a96d46da5e266700518ba8cb8d919d5bc5"
+ integrity sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==
dependencies:
- async "^1.4.0"
+ async "^2.5.0"
optimist "^0.6.1"
- source-map "^0.4.4"
+ source-map "^0.6.1"
optionalDependencies:
- uglify-js "^2.6"
+ uglify-js "^3.1.4"
has-ansi@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91"
+ integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=
dependencies:
ansi-regex "^2.0.0"
has-binary2@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/has-binary2/-/has-binary2-1.0.2.tgz#e83dba49f0b9be4d026d27365350d9f03f54be98"
+ integrity sha1-6D26SfC5vk0CbSc2U1DZ8D9Uvpg=
dependencies:
isarray "2.0.1"
has-cors@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39"
+ integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=
has-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
+ integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=
has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+ integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
has-symbol-support-x@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.3.0.tgz#588bd6927eaa0e296afae24160659167fc2be4f8"
+ integrity sha512-kLtS+N9qwz+Buc6TUfcW5iGb59hLLr5qfxTACi/0uGpH1u5NMNWsdU57KoYRBywvPykeRmu5qfB5x0chpDSWlg==
+
+has-symbols@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44"
+ integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=
has-to-string-tag-x@^1.2.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.3.0.tgz#78e3d98c3c0ec9413e970eb8d766249a1e13058f"
+ integrity sha512-Fu9Nwv8/VNJMvKjkldzXHO+yeX+TCelwUQ9dGW2LrAfHfHi6zVqQt+Qjilf0qGHvpl6Fap6o8aDhWhMt5hY/1g==
dependencies:
has-symbol-support-x "^1.3.0"
has-unicode@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
+ integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=
has-value@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
+ integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=
dependencies:
get-value "^2.0.3"
has-values "^0.1.4"
@@ -3442,6 +4125,7 @@ has-value@^0.3.1:
has-value@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177"
+ integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=
dependencies:
get-value "^2.0.6"
has-values "^1.0.0"
@@ -3450,10 +4134,12 @@ has-value@^1.0.0:
has-values@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771"
+ integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E=
has-values@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f"
+ integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=
dependencies:
is-number "^3.0.0"
kind-of "^4.0.0"
@@ -3461,18 +4147,21 @@ has-values@^1.0.0:
has@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28"
+ integrity sha1-hGFzP1OLCDfJNh45qauelwTcLyg=
dependencies:
function-bind "^1.0.2"
hash-base@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1"
+ integrity sha1-ZuodhW206KVHDK32/OI65SRO8uE=
dependencies:
inherits "^2.0.1"
hash-base@^3.0.0:
version "3.0.4"
resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918"
+ integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=
dependencies:
inherits "^2.0.1"
safe-buffer "^5.0.1"
@@ -3480,10 +4169,12 @@ hash-base@^3.0.0:
hash-sum@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-1.0.2.tgz#33b40777754c6432573c120cc3808bbd10d47f04"
+ integrity sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=
hash.js@^1.0.0, hash.js@^1.0.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846"
+ integrity sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==
dependencies:
inherits "^2.0.3"
minimalistic-assert "^1.0.0"
@@ -3491,29 +4182,36 @@ hash.js@^1.0.0, hash.js@^1.0.3:
he@^1.1.0, he@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
+ integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0=
+
+highlight.js@^9.13.1:
+ version "9.13.1"
+ resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e"
+ integrity sha512-Sc28JNQNDzaH6PORtRLMvif9RSn1mYuOoX3omVjnb0+HbpPygU2ALBI0R/wsiqCb4/fcp07Gdo8g+fhtFrQl6A==
hmac-drbg@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
+ integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=
dependencies:
hash.js "^1.0.3"
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
-home-or-tmp@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8"
- dependencies:
- os-homedir "^1.0.0"
- os-tmpdir "^1.0.1"
+hoopy@^0.1.2:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d"
+ integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==
hosted-git-info@^2.1.4:
version "2.2.0"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.2.0.tgz#7a0d097863d886c0fabbdcd37bf1758d8becf8a5"
+ integrity sha1-eg0JeGPYhsD6u9zTe/F1jYvs+KU=
hpack.js@^2.1.6:
version "2.1.6"
resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2"
+ integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=
dependencies:
inherits "^2.0.1"
obuf "^1.0.0"
@@ -3523,10 +4221,12 @@ hpack.js@^2.1.6:
html-entities@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.0.tgz#41948caf85ce82fed36e4e6a0ed371a6664379e2"
+ integrity sha1-QZSMr4XOgv7Tbk5qDtNxpmZDeeI=
htmlparser2@^3.8.2, htmlparser2@^3.9.0:
version "3.9.2"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338"
+ integrity sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=
dependencies:
domelementtype "^1.3.0"
domhandler "^2.3.0"
@@ -3538,14 +4238,17 @@ htmlparser2@^3.8.2, htmlparser2@^3.9.0:
http-cache-semantics@3.8.1:
version "3.8.1"
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2"
+ integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==
http-deceiver@^1.2.7:
version "1.2.7"
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
+ integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=
-http-errors@1.6.2, http-errors@~1.6.1, http-errors@~1.6.2:
+http-errors@1.6.2, http-errors@~1.6.2:
version "1.6.2"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
+ integrity sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=
dependencies:
depd "1.1.1"
inherits "2.0.3"
@@ -3555,6 +4258,7 @@ http-errors@1.6.2, http-errors@~1.6.1, http-errors@~1.6.2:
http-proxy-middleware@~0.18.0:
version "0.18.0"
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz#0987e6bb5a5606e5a69168d8f967a87f15dd8aab"
+ integrity sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==
dependencies:
http-proxy "^1.16.2"
is-glob "^4.0.0"
@@ -3564,6 +4268,7 @@ http-proxy-middleware@~0.18.0:
http-proxy@^1.13.0, http-proxy@^1.16.2:
version "1.16.2"
resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.16.2.tgz#06dff292952bf64dbe8471fa9df73066d4f37742"
+ integrity sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=
dependencies:
eventemitter3 "1.x.x"
requires-port "1.x.x"
@@ -3571,67 +4276,94 @@ http-proxy@^1.13.0, http-proxy@^1.16.2:
https-browserify@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
+ integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
iconv-lite@0.4, iconv-lite@^0.4.17, iconv-lite@^0.4.22, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
version "0.4.23"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63"
+ integrity sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==
dependencies:
safer-buffer ">= 2.1.2 < 3"
iconv-lite@0.4.19:
version "0.4.19"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
+ integrity sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==
icss-replace-symbols@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded"
+ integrity sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=
icss-utils@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-2.1.0.tgz#83f0a0ec378bf3246178b6c2ad9136f135b1c962"
+ integrity sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=
dependencies:
postcss "^6.0.1"
-ieee754@^1.1.11, ieee754@^1.1.4:
+ieee754@^1.1.4:
version "1.1.11"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.11.tgz#c16384ffe00f5b7835824e67b6f2bd44a5229455"
+ integrity sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==
iferr@^0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
+ integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE=
ignore-by-default@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
+ integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk=
ignore-walk@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8"
+ integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==
dependencies:
minimatch "^3.0.4"
-ignore@^3.3.3, ignore@^3.3.7:
- version "3.3.8"
- resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.8.tgz#3f8e9c35d38708a3a7e0e9abb6c73e7ee7707b2b"
+ignore@^4.0.6:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
+ integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
immediate@~3.0.5:
version "3.0.6"
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
+ integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=
+
+immutable-tuple@^0.4.9:
+ version "0.4.9"
+ resolved "https://registry.yarnpkg.com/immutable-tuple/-/immutable-tuple-0.4.9.tgz#473ebdd6c169c461913a454bf87ef8f601a20ff0"
+ integrity sha512-LWbJPZnidF8eczu7XmcnLBsumuyRBkpwIRPCZxlojouhBo5jEBO4toj6n7hMy6IxHU/c+MqDSWkvaTpPlMQcyA==
import-lazy@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
+ integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=
import-local@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc"
+ integrity sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==
dependencies:
pkg-dir "^2.0.0"
resolve-cwd "^2.0.0"
+import-local@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d"
+ integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==
+ dependencies:
+ pkg-dir "^3.0.0"
+ resolve-cwd "^2.0.0"
+
imports-loader@^0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/imports-loader/-/imports-loader-0.8.0.tgz#030ea51b8ca05977c40a3abfd9b4088fe0be9a69"
+ integrity sha512-kXWL7Scp8KQ4552ZcdVTeaQCZSLW+e6nJfp3cwUMB673T7Hr98Xjx5JK+ql7ADlJUvj1JS5O01RLbKoutN5QDQ==
dependencies:
loader-utils "^1.0.2"
source-map "^0.6.1"
@@ -3639,24 +4371,22 @@ imports-loader@^0.8.0:
imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
-
-indent-string@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
- dependencies:
- repeating "^2.0.0"
+ integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
indexes-of@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
+ integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc=
indexof@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
+ integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
dependencies:
once "^1.3.0"
wrappy "1"
@@ -3664,18 +4394,22 @@ inflight@^1.0.4:
inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+ integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
inherits@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
+ integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=
ini@^1.3.4, ini@~1.3.0:
version "1.3.5"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
+ integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
inquirer@3.0.6:
version "3.0.6"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347"
+ integrity sha1-4EqqnQW3o8ubD0B9BDdfBEcZA0c=
dependencies:
ansi-escapes "^1.1.0"
chalk "^1.0.0"
@@ -3691,28 +4425,10 @@ inquirer@3.0.6:
strip-ansi "^3.0.0"
through "^2.3.6"
-inquirer@^3.0.6:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9"
- dependencies:
- ansi-escapes "^3.0.0"
- chalk "^2.0.0"
- cli-cursor "^2.1.0"
- cli-width "^2.0.0"
- external-editor "^2.0.4"
- figures "^2.0.0"
- lodash "^4.3.0"
- mute-stream "0.0.7"
- run-async "^2.2.0"
- rx-lite "^4.0.8"
- rx-lite-aggregates "^4.0.8"
- string-width "^2.1.0"
- strip-ansi "^4.0.0"
- through "^2.3.6"
-
-inquirer@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.0.0.tgz#e8c20303ddc15bbfc2c12a6213710ccd9e1413d8"
+inquirer@^6.0.0, inquirer@^6.1.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.0.tgz#51adcd776f661369dc1e894859c2560a224abdd8"
+ integrity sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==
dependencies:
ansi-escapes "^3.0.0"
chalk "^2.0.0"
@@ -3720,7 +4436,7 @@ inquirer@^6.0.0:
cli-width "^2.0.0"
external-editor "^3.0.0"
figures "^2.0.0"
- lodash "^4.3.0"
+ lodash "^4.17.10"
mute-stream "0.0.7"
run-async "^2.2.0"
rxjs "^6.1.0"
@@ -3728,96 +4444,120 @@ inquirer@^6.0.0:
strip-ansi "^4.0.0"
through "^2.3.6"
-internal-ip@1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-1.2.0.tgz#ae9fbf93b984878785d50a8de1b356956058cf5c"
+internal-ip@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-3.0.1.tgz#df5c99876e1d2eb2ea2d74f520e3f669a00ece27"
+ integrity sha512-NXXgESC2nNVtU+pqmC9e6R8B1GpKxzsAQhffvh5AL79qKnodd+L7tnEQmTiUAVngqLalPbSqRA7XGIEL5nCd0Q==
dependencies:
- meow "^3.3.0"
+ default-gateway "^2.6.0"
+ ipaddr.js "^1.5.2"
interpret@^1.0.0, interpret@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614"
+ integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=
into-stream@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6"
+ integrity sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=
dependencies:
from2 "^2.1.1"
p-is-promise "^1.1.0"
-invariant@^2.2.0, invariant@^2.2.2:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360"
+invariant@^2.2.2:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
+ integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
dependencies:
loose-envify "^1.0.0"
-invert-kv@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
+invert-kv@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
+ integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==
+
+ip-regex@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
+ integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=
ip@^1.1.0, ip@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
+ integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
-ipaddr.js@1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.6.0.tgz#e3fa357b773da619f26e95f049d055c72796f86b"
+ipaddr.js@1.8.0, ipaddr.js@^1.5.2:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e"
+ integrity sha1-6qM9bd16zo9/b+DJygRA5wZzix4=
is-accessor-descriptor@^0.1.6:
version "0.1.6"
resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6"
+ integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=
dependencies:
kind-of "^3.0.2"
is-accessor-descriptor@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656"
+ integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==
dependencies:
kind-of "^6.0.0"
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+ integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
is-binary-path@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
+ integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=
dependencies:
binary-extensions "^1.0.0"
is-buffer@^1.1.5:
version "1.1.6"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
+ integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
is-builtin-module@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
+ integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74=
dependencies:
builtin-modules "^1.0.0"
is-callable@^1.1.1, is-callable@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2"
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
+ integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==
is-data-descriptor@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
+ integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=
dependencies:
kind-of "^3.0.2"
is-data-descriptor@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7"
+ integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==
dependencies:
kind-of "^6.0.0"
is-date-object@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
+ integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=
is-descriptor@^0.1.0:
version "0.1.6"
resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca"
+ integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==
dependencies:
is-accessor-descriptor "^0.1.6"
is-data-descriptor "^0.1.4"
@@ -3826,6 +4566,7 @@ is-descriptor@^0.1.0:
is-descriptor@^1.0.0, is-descriptor@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec"
+ integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==
dependencies:
is-accessor-descriptor "^1.0.0"
is-data-descriptor "^1.0.0"
@@ -3834,48 +4575,50 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2:
is-extendable@^0.1.0, is-extendable@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
+ integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=
is-extendable@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4"
+ integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==
dependencies:
is-plain-object "^2.0.4"
is-extglob@^2.1.0, is-extglob@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
-
-is-finite@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
- dependencies:
- number-is-nan "^1.0.0"
+ integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
is-fullwidth-code-point@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
+ integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
dependencies:
number-is-nan "^1.0.0"
is-fullwidth-code-point@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
+ integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
is-glob@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a"
+ integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=
dependencies:
is-extglob "^2.1.0"
is-glob@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0"
+ integrity sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=
dependencies:
is-extglob "^2.1.1"
is-installed-globally@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80"
+ integrity sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=
dependencies:
global-dirs "^0.1.0"
is-path-inside "^1.0.0"
@@ -3883,197 +4626,233 @@ is-installed-globally@^0.1.0:
is-npm@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4"
+ integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ=
is-number@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-0.1.1.tgz#69a7af116963d47206ec9bd9b48a14216f1e3806"
+ integrity sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=
is-number@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
+ integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=
dependencies:
kind-of "^3.0.2"
is-number@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
+ integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==
is-obj@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
+ integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
is-object@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470"
+ integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA=
is-odd@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24"
+ integrity sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==
dependencies:
is-number "^4.0.0"
is-path-cwd@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
+ integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=
is-path-in-cwd@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc"
+ integrity sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=
dependencies:
is-path-inside "^1.0.0"
is-path-inside@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f"
+ integrity sha1-/AbloWg/vaE95mev9xe7wQpI838=
dependencies:
path-is-inside "^1.0.1"
is-plain-obj@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
+ integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
+ integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==
dependencies:
isobject "^3.0.1"
is-promise@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa"
+ integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=
is-redirect@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24"
+ integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=
is-regex@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
+ integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=
dependencies:
has "^1.0.1"
-is-resolvable@^1.0.0:
+is-regexp@^1.0.0:
version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62"
- dependencies:
- tryit "^1.0.1"
+ resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
+ integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk=
+
+is-resolvable@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88"
+ integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==
is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34"
+ integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=
is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+ integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
is-symbol@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572"
-
-is-utf8@^0.2.0:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38"
+ integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==
+ dependencies:
+ has-symbols "^1.0.0"
is-windows@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
+ integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
is-wsl@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
+ integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=
isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+ integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
isarray@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e"
+ integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=
isbinaryfile@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621"
+ integrity sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+ integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
isobject@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
+ integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=
dependencies:
isarray "1.0.0"
isobject@^3.0.0, isobject@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
+ integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
-istanbul-api@^1.1.14:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.2.1.tgz#0c60a0515eb11c7d65c6b50bba2c6e999acd8620"
- dependencies:
- async "^2.1.4"
- fileset "^2.0.2"
- istanbul-lib-coverage "^1.1.1"
- istanbul-lib-hook "^1.1.0"
- istanbul-lib-instrument "^1.9.1"
- istanbul-lib-report "^1.1.2"
- istanbul-lib-source-maps "^1.2.2"
- istanbul-reports "^1.1.3"
- js-yaml "^3.7.0"
- mkdirp "^0.5.1"
+istanbul-api@^2.0.5:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-2.0.6.tgz#cd7b33ee678f6c01531d05f5e567ebbcd25f8ecc"
+ integrity sha512-8W5oeAGWXhtTJjAyVfvavOLVyZCTNCKsyF6GON/INKlBdO7uJ/bv3qnPj5M6ERKzmMCJS1kntnjjGuJ86fn3rQ==
+ dependencies:
+ async "^2.6.1"
+ compare-versions "^3.2.1"
+ fileset "^2.0.3"
+ istanbul-lib-coverage "^2.0.1"
+ istanbul-lib-hook "^2.0.1"
+ istanbul-lib-instrument "^3.0.0"
+ istanbul-lib-report "^2.0.2"
+ istanbul-lib-source-maps "^2.0.1"
+ istanbul-reports "^2.0.1"
+ js-yaml "^3.12.0"
+ make-dir "^1.3.0"
once "^1.4.0"
-istanbul-lib-coverage@^1.1.1, istanbul-lib-coverage@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz#f7d8f2e42b97e37fe796114cb0f9d68b5e3a4341"
+istanbul-lib-coverage@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#2aee0e073ad8c5f6a0b00e0dfbf52b4667472eda"
+ integrity sha512-nPvSZsVlbG9aLhZYaC3Oi1gT/tpyo3Yt5fNyf6NmcKIayz4VV/txxJFFKAK/gU4dcNn8ehsanBbVHVl0+amOLA==
-istanbul-lib-hook@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz#8538d970372cb3716d53e55523dd54b557a8d89b"
+istanbul-lib-hook@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.1.tgz#918a57b75a0f951d552a08487ca1fa5336433d72"
+ integrity sha512-ufiZoiJ8CxY577JJWEeFuxXZoMqiKpq/RqZtOAYuQLvlkbJWscq9n3gc4xrCGH9n4pW0qnTxOz1oyMmVtk8E1w==
dependencies:
- append-transform "^0.4.0"
+ append-transform "^1.0.0"
-istanbul-lib-instrument@^1.10.1, istanbul-lib-instrument@^1.9.1:
- version "1.10.1"
- resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz#724b4b6caceba8692d3f1f9d0727e279c401af7b"
- dependencies:
- babel-generator "^6.18.0"
- babel-template "^6.16.0"
- babel-traverse "^6.18.0"
- babel-types "^6.18.0"
- babylon "^6.18.0"
- istanbul-lib-coverage "^1.2.0"
- semver "^5.3.0"
+istanbul-lib-instrument@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.0.0.tgz#b5f066b2a161f75788be17a9d556f40a0cf2afc9"
+ integrity sha512-eQY9vN9elYjdgN9Iv6NS/00bptm02EBBk70lRMaVjeA6QYocQgenVrSgC28TJurdnZa80AGO3ASdFN+w/njGiQ==
+ dependencies:
+ "@babel/generator" "^7.0.0"
+ "@babel/parser" "^7.0.0"
+ "@babel/template" "^7.0.0"
+ "@babel/traverse" "^7.0.0"
+ "@babel/types" "^7.0.0"
+ istanbul-lib-coverage "^2.0.1"
+ semver "^5.5.0"
-istanbul-lib-report@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.2.tgz#922be27c13b9511b979bd1587359f69798c1d425"
+istanbul-lib-report@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.2.tgz#430a2598519113e1da7af274ba861bd42dd97535"
+ integrity sha512-rJ8uR3peeIrwAxoDEbK4dJ7cqqtxBisZKCuwkMtMv0xYzaAnsAi3AHrHPAAtNXzG/bcCgZZ3OJVqm1DTi9ap2Q==
dependencies:
- istanbul-lib-coverage "^1.1.1"
- mkdirp "^0.5.1"
- path-parse "^1.0.5"
- supports-color "^3.1.2"
+ istanbul-lib-coverage "^2.0.1"
+ make-dir "^1.3.0"
+ supports-color "^5.4.0"
-istanbul-lib-source-maps@^1.2.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.2.tgz#750578602435f28a0c04ee6d7d9e0f2960e62c1c"
+istanbul-lib-source-maps@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-2.0.1.tgz#ce8b45131d8293fdeaa732f4faf1852d13d0a97e"
+ integrity sha512-30l40ySg+gvBLcxTrLzR4Z2XTRj3HgRCA/p2rnbs/3OiTaoj054gAbuP5DcLOtwqmy4XW8qXBHzrmP2/bQ9i3A==
dependencies:
debug "^3.1.0"
- istanbul-lib-coverage "^1.1.1"
- mkdirp "^0.5.1"
- rimraf "^2.6.1"
- source-map "^0.5.3"
+ istanbul-lib-coverage "^2.0.1"
+ make-dir "^1.3.0"
+ rimraf "^2.6.2"
+ source-map "^0.6.1"
-istanbul-reports@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.3.tgz#3b9e1e8defb6d18b1d425da8e8b32c5a163f2d10"
+istanbul-reports@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.0.1.tgz#fb8d6ea850701a3984350b977a969e9a556116a7"
+ integrity sha512-CT0QgMBJqs6NJLF678ZHcquUAZIoBIUNzdJrRJfpkI9OnzG6MkUfHxbJC3ln981dMswC7/B1mfX3LNkhgJxsuw==
dependencies:
- handlebars "^4.0.3"
+ handlebars "^4.0.11"
istanbul@^0.4.5:
version "0.4.5"
resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b"
+ integrity sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=
dependencies:
abbrev "1.0.x"
async "1.x"
@@ -4093,6 +4872,7 @@ istanbul@^0.4.5:
istextorbinary@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-2.2.1.tgz#a5231a08ef6dd22b268d0895084cf8d58b5bec53"
+ integrity sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==
dependencies:
binaryextensions "2"
editions "^1.3.3"
@@ -4101,100 +4881,142 @@ istextorbinary@^2.2.1:
isurl@^1.0.0-alpha5:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67"
+ integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==
dependencies:
has-to-string-tag-x "^1.2.0"
is-object "^1.0.1"
+iterall@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/iterall/-/iterall-1.2.2.tgz#92d70deb8028e0c39ff3164fdbf4d8b088130cd7"
+ integrity sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA==
+
jasmine-core@^2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.9.0.tgz#bfbb56defcd30789adec5a3fbba8504233289c72"
+ integrity sha1-v7tW3vzTB4mt7Fo/u6hQQjMonHI=
jasmine-diff@^0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/jasmine-diff/-/jasmine-diff-0.1.3.tgz#93ccc2dcc41028c5ddd4606558074839f2deeaa8"
+ integrity sha1-k8zC3MQQKMXd1GBlWAdIOfLe6qg=
dependencies:
diff "^3.2.0"
jasmine-jquery@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/jasmine-jquery/-/jasmine-jquery-2.1.1.tgz#d4095e646944a26763235769ab018d9f30f0d47b"
+ integrity sha1-1AleZGlEomdjI1dpqwGNnzDw1Hs=
jed@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/jed/-/jed-1.1.1.tgz#7a549bbd9ffe1585b0cd0a191e203055bee574b4"
+ integrity sha1-elSbvZ/+FYWwzQoZHiAwVb7ldLQ=
jquery-ujs@1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/jquery-ujs/-/jquery-ujs-1.2.2.tgz#6a8ef1020e6b6dda385b90a4bddc128c21c56397"
+ integrity sha1-ao7xAg5rbdo4W5CkvdwSjCHFY5c=
dependencies:
jquery ">=1.8.0"
jquery.waitforimages@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/jquery.waitforimages/-/jquery.waitforimages-2.2.0.tgz#63f23131055a1b060dc913e6d874bcc9b9e6b16b"
+ integrity sha1-Y/IxMQVaGwYNyRPm2HS8ybnmsWs=
"jquery@>= 1.9.1", jquery@>=1.8.0, jquery@^3.2.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
+ integrity sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==
+
+js-beautify@^1.8.8:
+ version "1.8.8"
+ resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.8.8.tgz#1eb175b73a3571a5f1ed8d98e7cf2b05bfa98471"
+ integrity sha512-qVNq7ZZ7ZbLdzorvSlRDadS0Rh5oyItaE95v6I4wbbuSiijxn7SnnsV6dvKlcXuO2jX7lK8tn9fBulx34K/Ejg==
+ dependencies:
+ config-chain "~1.1.5"
+ editorconfig "^0.15.0"
+ mkdirp "~0.5.0"
+ nopt "~4.0.1"
js-cookie@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.1.3.tgz#48071625217ac9ecfab8c343a13d42ec09ff0526"
+ integrity sha1-SAcWJSF6yez6uMNDoT1C7An/BSY=
+
+js-levenshtein@^1.1.3:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.4.tgz#3a56e3cbf589ca0081eb22cd9ba0b1290a16d26e"
+ integrity sha512-PxfGzSs0ztShKrUYPIn5r0MtyAhYcCwmndozzpz8YObbPnD1jFxzlBGbRnX2mIu6Z13xN6+PTu05TQFnZFlzow==
-js-tokens@^3.0.0, js-tokens@^3.0.2:
+"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
+ integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+
+js-tokens@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
+ integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=
-js-yaml@3.x, js-yaml@^3.7.0, js-yaml@^3.9.1:
- version "3.11.0"
- resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef"
+js-yaml@3.x, js-yaml@^3.12.0:
+ version "3.12.0"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1"
+ integrity sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"
-jsesc@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b"
-
jsesc@^2.5.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe"
+ integrity sha1-5CGiqOINawgZ3yiQj3glJrlt0f4=
jsesc@~0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
+ integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=
json-buffer@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898"
+ integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=
-json-parse-better-errors@^1.0.2:
+json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
+ integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
-json-schema-traverse@^0.3.0:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
+json-schema-traverse@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+ integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
json-stable-stringify-without-jsonify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
+ integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
json3@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
+ integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=
-json5@^0.5.0, json5@^0.5.1:
+json5@^0.5.0:
version "0.5.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
+ integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=
jszip-utils@^0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/jszip-utils/-/jszip-utils-0.0.2.tgz#457d5cbca60a1c2e0706e9da2b544e8e7bc50bf8"
+ integrity sha1-RX1cvKYKHC4HBunaK1ROjnvFC/g=
jszip@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.1.3.tgz#8a920403b2b1651c0fc126be90192d9080957c37"
+ integrity sha1-ipIEA7KxZRwPwSa+kBktkICVfDc=
dependencies:
core-js "~2.3.0"
es6-promise "~3.0.2"
@@ -4205,24 +5027,28 @@ jszip@^3.1.3:
karma-chrome-launcher@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz#cf1b9d07136cc18fe239327d24654c3dbc368acf"
+ integrity sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==
dependencies:
fs-access "^1.0.0"
which "^1.2.1"
-karma-coverage-istanbul-reporter@^1.4.2:
- version "1.4.2"
- resolved "https://registry.yarnpkg.com/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.2.tgz#a8d0c8815c7d6f6cea15a394a7c4b39ef151a939"
+karma-coverage-istanbul-reporter@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-2.0.4.tgz#402ae4ed6eadb9d9dafbd408ffda17897c0d003a"
+ integrity sha512-xJS7QSQIVU6VK9HuJ/ieE5yynxKhjCCkd96NLY/BX/HXsx0CskU9JJiMQbd4cHALiddMwI4OWh1IIzeWrsavJw==
dependencies:
- istanbul-api "^1.1.14"
+ istanbul-api "^2.0.5"
minimatch "^3.0.4"
karma-jasmine@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/karma-jasmine/-/karma-jasmine-1.1.2.tgz#394f2b25ffb4a644b9ada6f22d443e2fd08886c3"
+ integrity sha1-OU8rJf+0pkS5rabyLUQ+L9CIhsM=
karma-junit-reporter@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/karma-junit-reporter/-/karma-junit-reporter-1.2.0.tgz#4f9c40cedfb1a395f8aef876abf96189917c6396"
+ integrity sha1-T5xAzt+xo5X4rvh2q/lhiZF8Y5Y=
dependencies:
path-is-absolute "^1.0.0"
xmlbuilder "8.2.2"
@@ -4230,6 +5056,7 @@ karma-junit-reporter@^1.2.0:
karma-mocha-reporter@^2.2.5:
version "2.2.5"
resolved "https://registry.yarnpkg.com/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz#15120095e8ed819186e47a0b012f3cd741895560"
+ integrity sha1-FRIAlejtgZGG5HoLAS8810GJVWA=
dependencies:
chalk "^2.1.0"
log-symbols "^2.1.0"
@@ -4238,23 +5065,25 @@ karma-mocha-reporter@^2.2.5:
karma-sourcemap-loader@^0.3.7:
version "0.3.7"
resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz#91322c77f8f13d46fed062b042e1009d4c4505d8"
+ integrity sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=
dependencies:
graceful-fs "^4.1.2"
karma-webpack@^4.0.0-beta.0:
- version "4.0.0-beta.0"
- resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-4.0.0-beta.0.tgz#2b386df6c364f588f896ffbdae57c2e51513d1ba"
+ version "4.0.0-rc.2"
+ resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-4.0.0-rc.2.tgz#4c194e94789842af7f0ffa0de77ee7715739c7c1"
+ integrity sha512-Wuiq/xFBsbJMsHhYy5SYXxSp7Q0b8uzAG8+Siuo56ntoi5GluPE5LK3Mzl2UtD4k1leFwL6IeIE6Q+tk4F6k9Q==
dependencies:
async "^2.0.0"
- babel-runtime "^6.0.0"
- loader-utils "^1.0.0"
- lodash "^4.0.0"
+ loader-utils "^1.1.0"
+ lodash "^4.17.10"
source-map "^0.5.6"
- webpack-dev-middleware "^3.0.1"
+ webpack-dev-middleware "^3.2.0"
karma@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/karma/-/karma-3.0.0.tgz#6da83461a8a28d8224575c3b5b874e271b4730c3"
+ integrity sha512-ZTjyuDXVXhXsvJ1E4CnZzbCjSxD6sEdzEsFYogLuZM0yqvg/mgz+O+R1jb0J7uAQeuzdY8kJgx6hSNXLwFuHIQ==
dependencies:
bluebird "^3.3.0"
body-parser "^1.16.1"
@@ -4287,64 +5116,71 @@ karma@^3.0.0:
katex@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/katex/-/katex-0.9.0.tgz#26a7d082c21d53725422d2d71da9b2d8455fbd4a"
+ integrity sha512-lp3x90LT1tDZBW2tjLheJ98wmRMRjUHwk4QpaswT9bhqoQZ+XA4cPcjcQBxgOQNwaOSt6ZeL/a6GKQ1of3LFxQ==
dependencies:
match-at "^0.1.1"
keyv@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373"
+ integrity sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==
dependencies:
json-buffer "3.0.0"
killable@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.0.tgz#da8b84bd47de5395878f95d64d02f2449fe05e6b"
+ integrity sha1-2ouEvUfeU5WHj5XWTQLyRJ/gXms=
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
version "3.2.2"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
+ integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=
dependencies:
is-buffer "^1.1.5"
kind-of@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57"
+ integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc=
dependencies:
is-buffer "^1.1.5"
kind-of@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d"
+ integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==
kind-of@^6.0.0, kind-of@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051"
+ integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==
latest-version@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15"
+ integrity sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=
dependencies:
package-json "^4.0.0"
-lazy-cache@^1.0.3:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
-
lazy-cache@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264"
+ integrity sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=
dependencies:
set-getter "^0.1.0"
-lcid@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
+lcid@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
+ integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==
dependencies:
- invert-kv "^1.0.0"
+ invert-kv "^2.0.0"
levn@^0.3.0, levn@~0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
+ integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=
dependencies:
prelude-ls "~1.1.2"
type-check "~0.3.2"
@@ -4352,35 +5188,39 @@ levn@^0.3.0, levn@~0.3.0:
lie@~3.1.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e"
+ integrity sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=
dependencies:
immediate "~3.0.5"
-load-json-file@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
- dependencies:
- graceful-fs "^4.1.2"
- parse-json "^2.2.0"
- pify "^2.0.0"
- pinkie-promise "^2.0.0"
- strip-bom "^2.0.0"
-
load-json-file@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8"
+ integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=
dependencies:
graceful-fs "^4.1.2"
parse-json "^2.2.0"
pify "^2.0.0"
strip-bom "^3.0.0"
+load-json-file@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
+ integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs=
+ dependencies:
+ graceful-fs "^4.1.2"
+ parse-json "^4.0.0"
+ pify "^3.0.0"
+ strip-bom "^3.0.0"
+
loader-runner@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2"
+ integrity sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=
loader-utils@^1.0.0, loader-utils@^1.0.2, loader-utils@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd"
+ integrity sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=
dependencies:
big.js "^3.1.3"
emojis-list "^2.0.0"
@@ -4389,71 +5229,90 @@ loader-utils@^1.0.0, loader-utils@^1.0.2, loader-utils@^1.1.0:
locate-path@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
+ integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=
dependencies:
p-locate "^2.0.0"
path-exists "^3.0.0"
+locate-path@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
+ integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
+ dependencies:
+ p-locate "^3.0.0"
+ path-exists "^3.0.0"
+
lodash.camelcase@4.3.0, lodash.camelcase@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
+ integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
lodash.clonedeep@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
+ integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
lodash.debounce@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
+ integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
lodash.escaperegexp@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347"
+ integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=
lodash.get@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
+ integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
+ integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
lodash.kebabcase@4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36"
+ integrity sha1-hImxyw0p/4gZXM7KRI/21swpXDY=
lodash.mergewith@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz#150cf0a16791f5903b8891eab154609274bdea55"
+ integrity sha1-FQzwoWeR9ZA7iJHqsVRgknS96lU=
lodash.snakecase@4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d"
+ integrity sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40=
lodash.startcase@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.startcase/-/lodash.startcase-4.4.0.tgz#9436e34ed26093ed7ffae1936144350915d9add8"
+ integrity sha1-lDbjTtJgk+1/+uGTYUQ1CRXZrdg=
lodash.upperfirst@4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce"
+ integrity sha1-E2Xt9DFIBIHvDRxolXpe2Z1J984=
-lodash@4.17.4:
- version "4.17.4"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
-
-lodash@^4.0.0, lodash@^4.11.1, lodash@^4.17.10, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.0:
- version "4.17.10"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7"
+lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.0:
+ version "4.17.11"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
+ integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
log-symbols@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a"
+ integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==
dependencies:
chalk "^2.0.1"
log4js@^3.0.0:
version "3.0.5"
resolved "https://registry.yarnpkg.com/log4js/-/log4js-3.0.5.tgz#b80146bfebad68b430d4f3569556d8a6edfef303"
+ integrity sha512-IX5c3G/7fuTtdr0JjOT2OIR12aTESVhsH6cEsijloYwKgcPRlO6DgOU72v0UFhWcoV1HN6+M3dwT89qVPLXm0w==
dependencies:
circular-json "^0.5.5"
date-format "^1.2.0"
@@ -4464,47 +5323,29 @@ log4js@^3.0.0:
loglevel@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.4.1.tgz#95b383f91a3c2756fd4ab093667e4309161f2bcd"
-
-loglevelnext@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/loglevelnext/-/loglevelnext-1.0.3.tgz#0f69277e73bbbf2cd61b94d82313216bf87ac66e"
-
-long@4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
-
-long@^3.2.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/long/-/long-3.2.0.tgz#d821b7138ca1cb581c172990ef14db200b5c474b"
-
-longest@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
+ integrity sha1-lbOD+Ro8J1b9SrCTZn5DCRYfK80=
loose-envify@^1.0.0:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
- dependencies:
- js-tokens "^3.0.0"
-
-loud-rejection@^1.0.0, loud-rejection@^1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
+ integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
dependencies:
- currently-unhandled "^0.4.1"
- signal-exit "^3.0.0"
+ js-tokens "^3.0.0 || ^4.0.0"
lowercase-keys@1.0.0, lowercase-keys@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306"
+ integrity sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=
lru-cache@2.2.x:
version "2.2.4"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d"
+ integrity sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=
-lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2:
+lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2, lru-cache@^4.1.3:
version "4.1.3"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c"
+ integrity sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==
dependencies:
pseudomap "^1.0.2"
yallist "^2.1.2"
@@ -4512,46 +5353,58 @@ lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2:
lz-string@^1.4.4:
version "1.4.4"
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26"
+ integrity sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=
-make-dir@^1.0.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.2.0.tgz#6d6a49eead4aae296c53bbf3a1a008bd6c89469b"
+make-dir@^1.0.0, make-dir@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
+ integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==
dependencies:
pify "^3.0.0"
mamacro@^0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4"
+ integrity sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==
+
+map-age-cleaner@^0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.2.tgz#098fb15538fd3dbe461f12745b0ca8568d4e3f74"
+ integrity sha512-UN1dNocxQq44IhJyMI4TU8phc2m9BddacHRPRjKGLYaF0jqd3xLz0jS0skpAU9WgYyoR4gHtUpzytNBS385FWQ==
+ dependencies:
+ p-defer "^1.0.0"
map-cache@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
-
-map-obj@^1.0.0, map-obj@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
+ integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=
map-stream@~0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194"
+ integrity sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=
map-visit@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
+ integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=
dependencies:
object-visit "^1.0.0"
marked@^0.3.12:
version "0.3.12"
resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.12.tgz#7cf25ff2252632f3fe2406bde258e94eee927519"
+ integrity sha512-k4NaW+vS7ytQn6MgJn3fYpQt20/mOgYM5Ft9BYMfQJDz2QT6yEeS9XJ8k2Nw8JTeWK/znPPW2n3UJGzyYEiMoA==
match-at@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/match-at/-/match-at-0.1.1.tgz#25d040d291777704d5e6556bbb79230ec2de0540"
+ integrity sha512-h4Yd392z9mST+dzc+yjuybOGFNOZjmXIPKWjxBd1Bb23r4SmDOsk2NYCU2BMUBGbSpZqwVsZYNq26QS3xfaT3Q==
md5.js@^1.3.4:
version "1.3.4"
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d"
+ integrity sha1-6b296UogpawYsENA/Fdk1bCdkB0=
dependencies:
hash-base "^3.0.0"
inherits "^2.0.1"
@@ -4559,56 +5412,65 @@ md5.js@^1.3.4:
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+ integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=
-mem@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76"
+mem@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/mem/-/mem-4.0.0.tgz#6437690d9471678f6cc83659c00cbafcd6b0cdaf"
+ integrity sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==
dependencies:
+ map-age-cleaner "^0.1.1"
mimic-fn "^1.0.0"
+ p-is-promise "^1.1.0"
memory-fs@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290"
+ integrity sha1-8rslNovBIeORwlIN6Slpyu4KApA=
memory-fs@^0.4.0, memory-fs@~0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
+ integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=
dependencies:
errno "^0.1.3"
readable-stream "^2.0.1"
-meow@^3.3.0:
- version "3.7.0"
- resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
- dependencies:
- camelcase-keys "^2.0.0"
- decamelize "^1.1.2"
- loud-rejection "^1.0.0"
- map-obj "^1.0.1"
- minimist "^1.1.3"
- normalize-package-data "^2.3.4"
- object-assign "^4.0.1"
- read-pkg-up "^1.0.1"
- redent "^1.0.0"
- trim-newlines "^1.0.0"
-
merge-descriptors@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
+ integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
merge-source-map@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646"
+ integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==
dependencies:
source-map "^0.6.1"
+mermaid@^8.0.0-rc.8:
+ version "8.0.0-rc.8"
+ resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-8.0.0-rc.8.tgz#74ed54d0d46e9ee71c4db2730b2d83d516a21e72"
+ integrity sha512-GbF9jHWfqE7YGx9vQySmBxy2Ahlclxmpk4tJ9ntNyafENl96s96ggUK/NQS5ydYoFab6MavTm4YMTIPKqWVvPQ==
+ dependencies:
+ d3 "^4.13.0"
+ dagre-d3-renderer "^0.5.8"
+ dagre-layout "^0.8.8"
+ graphlibrary "^2.2.0"
+ he "^1.1.1"
+ lodash "^4.17.5"
+ moment "^2.21.0"
+ scope-css "^1.0.5"
+
methods@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
+ integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=
micromatch@^3.1.4, micromatch@^3.1.8, micromatch@^3.1.9:
version "3.1.10"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
+ integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==
dependencies:
arr-diff "^4.0.0"
array-unique "^0.3.2"
@@ -4627,65 +5489,79 @@ micromatch@^3.1.4, micromatch@^3.1.8, micromatch@^3.1.9:
miller-rabin@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
+ integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==
dependencies:
bn.js "^4.0.0"
brorand "^1.0.1"
-"mime-db@>= 1.29.0 < 2", mime-db@~1.33.0:
- version "1.33.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db"
+"mime-db@>= 1.36.0 < 2", mime-db@~1.37.0:
+ version "1.37.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8"
+ integrity sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==
-mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.18:
- version "2.1.18"
- resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8"
+mime-types@~2.1.17, mime-types@~2.1.18:
+ version "2.1.21"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96"
+ integrity sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==
dependencies:
- mime-db "~1.33.0"
+ mime-db "~1.37.0"
mime@1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
+ integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==
-mime@^2.0.3, mime@^2.1.0, mime@^2.3.1:
+mime@^2.0.3, mime@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.3.1.tgz#b1621c54d63b97c47d3cfe7f7215f7d64517c369"
+ integrity sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==
mimic-fn@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18"
+ integrity sha1-5md4PZLonb00KBi1IwudYqZyrRg=
mimic-response@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.0.tgz#df3d3652a73fded6b9b0b24146e6fd052353458e"
+ integrity sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=
minimalistic-assert@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3"
+ integrity sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=
minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
+ integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+ integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
dependencies:
brace-expansion "^1.1.7"
minimist@0.0.8:
version "0.0.8"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+ resolved "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
+ integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
-minimist@1.2.0, minimist@^1.1.3, minimist@^1.2.0:
+minimist@1.2.0, minimist@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
+ integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
minimist@~0.0.1:
version "0.0.10"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
+ resolved "http://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
+ integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=
minipass@^2.2.1, minipass@^2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233"
+ integrity sha512-/jAn9/tEX4gnpyRATxgHEOV6xbcyxgT7iUnxo9Y3+OB0zX00TgKIv/2FZCf5brBbICcwbLqVv2ImjvWWrQMSYw==
dependencies:
safe-buffer "^5.1.2"
yallist "^3.0.0"
@@ -4693,12 +5569,14 @@ minipass@^2.2.1, minipass@^2.3.3:
minizlib@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb"
+ integrity sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==
dependencies:
minipass "^2.2.1"
mississippi@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f"
+ integrity sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==
dependencies:
concat-stream "^1.5.0"
duplexify "^3.4.2"
@@ -4711,38 +5589,61 @@ mississippi@^2.0.0:
stream-each "^1.1.0"
through2 "^2.0.0"
+mississippi@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
+ integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==
+ dependencies:
+ concat-stream "^1.5.0"
+ duplexify "^3.4.2"
+ end-of-stream "^1.1.0"
+ flush-write-stream "^1.0.0"
+ from2 "^2.1.0"
+ parallel-transform "^1.1.0"
+ pump "^3.0.0"
+ pumpify "^1.3.3"
+ stream-each "^1.1.0"
+ through2 "^2.0.0"
+
mixin-deep@^1.2.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe"
+ integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==
dependencies:
for-in "^1.0.2"
is-extendable "^1.0.1"
mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0:
version "0.5.1"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+ resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
+ integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
dependencies:
minimist "0.0.8"
-moment@2.x, moment@^2.18.1:
- version "2.19.2"
- resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.2.tgz#8a7f774c95a64550b4c7ebd496683908f9419dbe"
+moment@2.x, moment@^2.21.0:
+ version "2.22.2"
+ resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66"
+ integrity sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=
-monaco-editor-webpack-plugin@^1.5.2:
- version "1.5.2"
- resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-1.5.2.tgz#e113fa1d5759ede6fd776eb620cdd5930203b55a"
+monaco-editor-webpack-plugin@^1.5.4:
+ version "1.5.4"
+ resolved "https://registry.yarnpkg.com/monaco-editor-webpack-plugin/-/monaco-editor-webpack-plugin-1.5.4.tgz#6781a130e3e1379bb8f4cd190132f4af6dcd2c16"
+ integrity sha512-9YmWYQdZoAoZ1RLy/uvoDbCcb0EKy5O2qoMQn+UIVQxk+VTCXfJDgANczDIWko+UOzg0MY0P+sA8bl4XI14RJg==
monaco-editor@^0.14.3:
version "0.14.3"
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.14.3.tgz#7cc4a4096a3821f52fea9b10489b527ef3034e22"
+ integrity sha512-RhaO4xXmWn/p0WrkEOXe4PoZj6xOcvDYjoAh0e1kGUrQnP1IOpc0m86Ceuaa2CLEMDINqKijBSmqhvBQnsPLHQ==
mousetrap@^1.4.6:
version "1.4.6"
resolved "https://registry.yarnpkg.com/mousetrap/-/mousetrap-1.4.6.tgz#eaca72e22e56d5b769b7555873b688c3332e390a"
+ integrity sha1-6spy4i5W1bdpt1VYc7aIwzMuOQo=
move-concurrently@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
+ integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=
dependencies:
aproba "^1.1.1"
copy-concurrently "^1.0.0"
@@ -4754,14 +5655,22 @@ move-concurrently@^1.0.1:
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+ integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
+
+ms@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
+ integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
multicast-dns-service-types@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901"
+ integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=
multicast-dns@^6.0.1:
version "6.1.1"
resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.1.1.tgz#6e7de86a570872ab17058adea7160bbeca814dde"
+ integrity sha1-bn3oalcIcqsXBYrepxYLvsqBTd4=
dependencies:
dns-packet "^1.0.1"
thunky "^0.1.0"
@@ -4769,14 +5678,17 @@ multicast-dns@^6.0.1:
mute-stream@0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
+ integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
nan@^2.9.2:
version "2.10.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f"
+ integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==
nanomatch@^1.2.9:
version "1.2.9"
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.9.tgz#879f7150cb2dab7a471259066c104eee6e0fa7c2"
+ integrity sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==
dependencies:
arr-diff "^4.0.0"
array-unique "^0.3.2"
@@ -4794,10 +5706,12 @@ nanomatch@^1.2.9:
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+ integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
-needle@^2.2.0:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d"
+needle@^2.2.1:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e"
+ integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==
dependencies:
debug "^2.1.2"
iconv-lite "^0.4.4"
@@ -4806,18 +5720,22 @@ needle@^2.2.0:
negotiator@0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
+ integrity sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=
neo-async@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.0.tgz#76b1c823130cca26acfbaccc8fbaf0a2fa33b18f"
+ integrity sha512-nJmSswG4As/MkRq7QZFuH/sf/yuv8ODdMZrY4Bedjp77a5MK4A6s7YbBB64c9u79EBUOfXUXBvArmvzTD0X+6g==
nice-try@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4"
+ integrity sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==
node-fetch@1.6.3:
version "1.6.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04"
+ integrity sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ=
dependencies:
encoding "^0.1.11"
is-stream "^1.0.1"
@@ -4825,10 +5743,12 @@ node-fetch@1.6.3:
node-forge@0.6.33:
version "0.6.33"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.6.33.tgz#463811879f573d45155ad6a9f43dc296e8e85ebc"
+ integrity sha1-RjgRh59XPUUVWtap9D3ClujoXrw=
"node-libs-browser@^1.0.0 || ^2.0.0", node-libs-browser@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df"
+ integrity sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==
dependencies:
assert "^1.1.1"
browserify-zlib "^0.2.0"
@@ -4855,23 +5775,32 @@ node-forge@0.6.33:
vm-browserify "0.0.4"
node-pre-gyp@^0.10.0:
- version "0.10.0"
- resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.0.tgz#6e4ef5bb5c5203c6552448828c852c40111aac46"
+ version "0.10.3"
+ resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc"
+ integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A==
dependencies:
detect-libc "^1.0.2"
mkdirp "^0.5.1"
- needle "^2.2.0"
+ needle "^2.2.1"
nopt "^4.0.1"
npm-packlist "^1.1.6"
npmlog "^4.0.2"
- rc "^1.1.7"
+ rc "^1.2.7"
rimraf "^2.6.1"
semver "^5.3.0"
tar "^4"
-nodemon@^1.18.2:
- version "1.18.2"
- resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.18.2.tgz#36b89c790da70c4f270e2cc0718723131bc04abb"
+node-releases@^1.0.0-alpha.11:
+ version "1.0.0-alpha.12"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.0.0-alpha.12.tgz#32e461b879ea76ac674e511d9832cf29da345268"
+ integrity sha512-VPB4rTPqpVyWKBHbSa4YPFme3+8WHsOSpvbp0Mfj0bWsC8TEjt4HQrLl1hsBDELlp1nB4lflSgSuGTYiuyaP7Q==
+ dependencies:
+ semver "^5.3.0"
+
+nodemon@^1.18.4:
+ version "1.18.4"
+ resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.18.4.tgz#873f65fdb53220eb166180cf106b1354ac5d714d"
+ integrity sha512-hyK6vl65IPnky/ee+D3IWvVGgJa/m3No2/Xc/3wanS6Ce1MWjCzH6NnhPJ/vZM+6JFym16jtHx51lmCMB9HDtg==
dependencies:
chokidar "^2.0.2"
debug "^3.1.0"
@@ -4887,12 +5816,14 @@ nodemon@^1.18.2:
nopt@3.x:
version "3.0.6"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
+ integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k=
dependencies:
abbrev "1"
-nopt@^4.0.1:
+nopt@^4.0.1, nopt@~4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
+ integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=
dependencies:
abbrev "1"
osenv "^0.1.4"
@@ -4900,12 +5831,14 @@ nopt@^4.0.1:
nopt@~1.0.10:
version "1.0.10"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee"
+ integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=
dependencies:
abbrev "1"
-normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
+normalize-package-data@^2.3.2:
version "2.4.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
+ integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==
dependencies:
hosted-git-info "^2.1.4"
is-builtin-module "^1.0.0"
@@ -4915,12 +5848,14 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
normalize-path@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
+ integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=
dependencies:
remove-trailing-separator "^1.0.1"
normalize-url@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6"
+ integrity sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==
dependencies:
prepend-http "^2.0.0"
query-string "^5.0.1"
@@ -4929,10 +5864,12 @@ normalize-url@2.0.1:
npm-bundled@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308"
+ integrity sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==
npm-packlist@^1.1.6:
version "1.1.10"
resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.10.tgz#1039db9e985727e464df066f4cf0ab6ef85c398a"
+ integrity sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==
dependencies:
ignore-walk "^3.0.1"
npm-bundled "^1.0.1"
@@ -4940,12 +5877,14 @@ npm-packlist@^1.1.6:
npm-run-path@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
+ integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=
dependencies:
path-key "^2.0.0"
npmlog@^4.0.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
+ integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
dependencies:
are-we-there-yet "~1.1.2"
console-control-strings "~1.1.0"
@@ -4955,72 +5894,114 @@ npmlog@^4.0.2:
null-check@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd"
+ integrity sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=
number-is-nan@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
+ integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
object-assign@^4.0.1, object-assign@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+ integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
object-component@0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291"
+ integrity sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=
object-copy@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
+ integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw=
dependencies:
copy-descriptor "^0.1.0"
define-property "^0.2.5"
kind-of "^3.0.3"
-object-keys@^1.0.8:
- version "1.0.11"
- resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d"
+object-keys@^1.0.11, object-keys@^1.0.12:
+ version "1.0.12"
+ resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2"
+ integrity sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==
object-visit@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb"
+ integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=
dependencies:
isobject "^3.0.0"
+object.assign@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da"
+ integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==
+ dependencies:
+ define-properties "^1.1.2"
+ function-bind "^1.1.1"
+ has-symbols "^1.0.0"
+ object-keys "^1.0.11"
+
+object.entries@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.0.4.tgz#1bf9a4dd2288f5b33f3a993d257661f05d161a5f"
+ integrity sha1-G/mk3SKI9bM/Opk9JXZh8F0WGl8=
+ dependencies:
+ define-properties "^1.1.2"
+ es-abstract "^1.6.1"
+ function-bind "^1.1.0"
+ has "^1.0.1"
+
+object.getownpropertydescriptors@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16"
+ integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=
+ dependencies:
+ define-properties "^1.1.2"
+ es-abstract "^1.5.1"
+
object.pick@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747"
+ integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=
dependencies:
isobject "^3.0.1"
obuf@^1.0.0, obuf@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.1.tgz#104124b6c602c6796881a042541d36db43a5264e"
+ integrity sha1-EEEktsYCxnlogaBCVB0220OlJk4=
on-finished@~2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
+ integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
dependencies:
ee-first "1.1.1"
on-headers@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
+ integrity sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=
once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
dependencies:
wrappy "1"
onetime@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
+ integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=
dependencies:
mimic-fn "^1.0.0"
opencollective@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/opencollective/-/opencollective-1.0.3.tgz#aee6372bc28144583690c3ca8daecfc120dd0ef1"
+ integrity sha1-ruY3K8KBRFg2kMPKja7PwSDdDvE=
dependencies:
babel-polyfill "6.23.0"
chalk "1.1.3"
@@ -5029,13 +6010,15 @@ opencollective@^1.0.3:
node-fetch "1.6.3"
opn "4.0.2"
-opener@^1.4.3:
- version "1.4.3"
- resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8"
+opener@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed"
+ integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==
opn@4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/opn/-/opn-4.0.2.tgz#7abc22e644dff63b0a96d5ab7f2790c0f01abc95"
+ integrity sha1-erwi5kTf9jsKltWrfyeQwPAavJU=
dependencies:
object-assign "^4.0.1"
pinkie-promise "^2.0.0"
@@ -5043,12 +6026,21 @@ opn@4.0.2:
opn@^5.1.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/opn/-/opn-5.2.0.tgz#71fdf934d6827d676cecbea1531f95d354641225"
+ integrity sha512-Jd/GpzPyHF4P2/aNOVmS3lfMSWV9J7cOhCG1s08XCEAsPkB7lp6ddiU0J7XzyQRDUh8BqJ7PchfINjR8jyofRQ==
dependencies:
is-wsl "^1.1.0"
+optimism@^0.6.6:
+ version "0.6.8"
+ resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.6.8.tgz#0780b546da8cd0a72e5207e0c3706c990c8673a6"
+ integrity sha512-bN5n1KCxSqwBDnmgDnzMtQTHdL+uea2HYFx1smvtE+w2AMl0Uy31g0aXnP/Nt85OINnMJPRpJyfRQLTCqn5Weg==
+ dependencies:
+ immutable-tuple "^0.4.9"
+
optimist@^0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
+ integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY=
dependencies:
minimist "~0.0.1"
wordwrap "~0.0.2"
@@ -5056,6 +6048,7 @@ optimist@^0.6.1:
optionator@^0.8.1, optionator@^0.8.2:
version "0.8.2"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64"
+ integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=
dependencies:
deep-is "~0.1.3"
fast-levenshtein "~2.0.4"
@@ -5064,35 +6057,41 @@ optionator@^0.8.1, optionator@^0.8.2:
type-check "~0.3.2"
wordwrap "~1.0.0"
-original@>=0.0.5:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/original/-/original-1.0.0.tgz#9147f93fa1696d04be61e01bd50baeaca656bd3b"
+original@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f"
+ integrity sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==
dependencies:
- url-parse "1.0.x"
+ url-parse "^1.4.3"
os-browserify@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
+ integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=
os-homedir@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
+ integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
-os-locale@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2"
+os-locale@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.0.1.tgz#3b014fbf01d87f60a1e5348d80fe870dc82c4620"
+ integrity sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==
dependencies:
- execa "^0.7.0"
- lcid "^1.0.0"
- mem "^1.1.0"
+ execa "^0.10.0"
+ lcid "^2.0.0"
+ mem "^4.0.0"
-os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2:
+os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+ integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
osenv@^0.1.4:
version "0.1.5"
resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
+ integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
dependencies:
os-homedir "^1.0.0"
os-tmpdir "^1.0.0"
@@ -5100,44 +6099,77 @@ osenv@^0.1.4:
p-cancelable@^0.4.0:
version "0.4.1"
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0"
+ integrity sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==
+
+p-defer@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
+ integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=
p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
+ integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
p-is-promise@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e"
+ integrity sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=
p-limit@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c"
+ integrity sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==
dependencies:
p-try "^1.0.0"
+p-limit@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec"
+ integrity sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==
+ dependencies:
+ p-try "^2.0.0"
+
p-locate@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
+ integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=
dependencies:
p-limit "^1.1.0"
+p-locate@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
+ integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
+ dependencies:
+ p-limit "^2.0.0"
+
p-map@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.1.1.tgz#05f5e4ae97a068371bc2a5cc86bfbdbc19c4ae7a"
+ integrity sha1-BfXkrpegaDcbwqXMhr+9vBnErno=
p-timeout@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038"
+ integrity sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==
dependencies:
p-finally "^1.0.0"
p-try@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
+ integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=
+
+p-try@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1"
+ integrity sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==
package-json@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed"
+ integrity sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=
dependencies:
got "^6.7.1"
registry-auth-token "^3.0.1"
@@ -5147,10 +6179,12 @@ package-json@^4.0.0:
pako@~1.0.2, pako@~1.0.5:
version "1.0.6"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258"
+ integrity sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==
parallel-transform@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06"
+ integrity sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=
dependencies:
cyclist "~0.2.2"
inherits "^2.0.3"
@@ -5159,6 +6193,7 @@ parallel-transform@^1.1.0:
parse-asn1@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712"
+ integrity sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=
dependencies:
asn1.js "^4.0.0"
browserify-aes "^1.0.0"
@@ -5169,94 +6204,119 @@ parse-asn1@^5.0.0:
parse-json@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
+ integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=
dependencies:
error-ex "^1.2.0"
+parse-json@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
+ integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=
+ dependencies:
+ error-ex "^1.3.1"
+ json-parse-better-errors "^1.0.1"
+
parse5@^5:
version "5.0.0"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.0.0.tgz#4d02710d44f3c3846197a11e205d4ef17842b81a"
+ integrity sha512-0ywuiUOnpWWeil5grH2rxjyTJoeQVwyBuO2si6QIU9dWtj2npjuyK1HaY1RbLnVfDhEbhyAPNUBKRK0Xj2xE0w==
parseqs@0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d"
+ integrity sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=
dependencies:
better-assert "~1.0.0"
parseuri@0.0.5:
version "0.0.5"
resolved "https://registry.yarnpkg.com/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a"
+ integrity sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=
dependencies:
better-assert "~1.0.0"
-parseurl@~1.3.1, parseurl@~1.3.2:
+parseurl@~1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
+ integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=
pascalcase@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14"
+ integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=
path-browserify@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a"
+ integrity sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=
path-dirname@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0"
+ integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=
path-exists@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
+ integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=
dependencies:
pinkie-promise "^2.0.0"
path-exists@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
+ integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
-path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
+path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+ integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
path-is-inside@^1.0.1, path-is-inside@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
+ integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=
path-key@^2.0.0, path-key@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
+ integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
path-parse@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1"
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
+ integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
path-to-regexp@0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
-
-path-type@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
- dependencies:
- graceful-fs "^4.1.2"
- pify "^2.0.0"
- pinkie-promise "^2.0.0"
+ integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
path-type@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73"
+ integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=
dependencies:
pify "^2.0.0"
+path-type@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f"
+ integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==
+ dependencies:
+ pify "^3.0.0"
+
pause-stream@0.0.11:
version "0.0.11"
resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
+ integrity sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=
dependencies:
through "~2.3"
pbkdf2@^3.0.3:
version "3.0.14"
resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.14.tgz#a35e13c64799b06ce15320f459c230e68e73bade"
+ integrity sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==
dependencies:
create-hash "^1.1.2"
create-hmac "^1.1.4"
@@ -5267,54 +6327,72 @@ pbkdf2@^3.0.3:
pify@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+ integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
pify@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
+ integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
pikaday@^1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/pikaday/-/pikaday-1.6.1.tgz#b91bcb9b8539cedd8d6d08e4e7465e12095671b0"
+ integrity sha512-B+pxVcSGuzLblMe4dnhCF3dnI2zkyj5GAqanGX9cVcOk90fp2ULo1OZFUPRXQXUE5tmcimnk1tPOFs8tUHQetQ==
optionalDependencies:
moment "2.x"
pinkie-promise@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
+ integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
dependencies:
pinkie "^2.0.0"
pinkie@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
+ integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
pkg-dir@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4"
+ integrity sha1-ektQio1bstYp1EcFb/TpyTFM89Q=
dependencies:
find-up "^1.0.0"
pkg-dir@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
+ integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=
dependencies:
find-up "^2.1.0"
+pkg-dir@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3"
+ integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==
+ dependencies:
+ find-up "^3.0.0"
+
pluralize@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777"
+ integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==
pofile@^1:
version "1.0.11"
resolved "https://registry.yarnpkg.com/pofile/-/pofile-1.0.11.tgz#35aff58c17491d127a07336d5522ebc9df57c954"
+ integrity sha512-Vy9eH1dRD9wHjYt/QqXcTz+RnX/zg53xK+KljFSX30PvdDMb2z+c6uDUeblUGqqJgz3QFsdlA0IJvHziPmWtQg==
popper.js@^1.12.9, popper.js@^1.14.3:
version "1.14.3"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095"
+ integrity sha1-FDj5jQRqz3tNeM1QK/QYrGTU8JU=
portfinder@^1.0.9:
version "1.0.13"
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.13.tgz#bb32ecd87c27104ae6ee44b5a3ccbf0ebb1aede9"
+ integrity sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=
dependencies:
async "^1.5.2"
debug "^2.2.0"
@@ -5323,16 +6401,19 @@ portfinder@^1.0.9:
posix-character-classes@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
+ integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
postcss-modules-extract-imports@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz#66140ecece38ef06bf0d3e355d69bf59d141ea85"
+ integrity sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=
dependencies:
postcss "^6.0.1"
postcss-modules-local-by-default@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069"
+ integrity sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=
dependencies:
css-selector-tokenizer "^0.7.0"
postcss "^6.0.1"
@@ -5340,6 +6421,7 @@ postcss-modules-local-by-default@^1.2.0:
postcss-modules-scope@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90"
+ integrity sha1-1upkmUx5+XtipytCb75gVqGUu5A=
dependencies:
css-selector-tokenizer "^0.7.0"
postcss "^6.0.1"
@@ -5347,6 +6429,7 @@ postcss-modules-scope@^1.1.0:
postcss-modules-values@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20"
+ integrity sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=
dependencies:
icss-replace-symbols "^1.1.0"
postcss "^6.0.1"
@@ -5354,6 +6437,7 @@ postcss-modules-values@^1.3.0:
postcss-selector-parser@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865"
+ integrity sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU=
dependencies:
dot-prop "^4.1.1"
indexes-of "^1.0.1"
@@ -5362,10 +6446,12 @@ postcss-selector-parser@^3.1.1:
postcss-value-parser@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15"
+ integrity sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=
postcss@^6.0.1, postcss@^6.0.14, postcss@^6.0.20, postcss@^6.0.23:
version "6.0.23"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324"
+ integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==
dependencies:
chalk "^2.4.1"
source-map "^0.6.1"
@@ -5374,79 +6460,106 @@ postcss@^6.0.1, postcss@^6.0.14, postcss@^6.0.20, postcss@^6.0.23:
prelude-ls@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+ integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
prepend-http@^1.0.1:
version "1.0.4"
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
+ integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=
prepend-http@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
+ integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=
-prettier@1.12.1, prettier@^1.11.1:
- version "1.12.1"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.12.1.tgz#c1ad20e803e7749faf905a409d2367e06bbe7325"
+prettier@1.13.7:
+ version "1.13.7"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.7.tgz#850f3b8af784a49a6ea2d2eaa7ed1428a34b7281"
+ integrity sha512-KIU72UmYPGk4MujZGYMFwinB7lOf2LsDNGSOC8ufevsrPLISrZbNJlWstRi3m0AMuszbH+EFSQ/r6w56RSPK6w==
+
+prettier@1.15.2:
+ version "1.15.2"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.15.2.tgz#d31abe22afa4351efa14c7f8b94b58bb7452205e"
+ integrity sha512-YgPLFFA0CdKL4Eg2IHtUSjzj/BWgszDHiNQAe0VAIBse34148whfdzLagRL+QiKS+YfK5ftB6X4v/MBw8yCoug==
prismjs@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.6.0.tgz#118d95fb7a66dba2272e343b345f5236659db365"
+ integrity sha1-EY2V+3pm26InLjQ7NF9SNmWds2U=
optionalDependencies:
clipboard "^1.5.5"
-private@^0.1.6, private@^0.1.8:
+private@^0.1.6:
version "0.1.8"
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
+ integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==
process-nextick-args@~1.0.6:
version "1.0.7"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
+ integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=
process-nextick-args@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
+ integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==
process@^0.11.10:
version "0.11.10"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
+ integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
progress@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f"
+ integrity sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=
promise-inflight@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
+ integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
-proxy-addr@~2.0.2:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.3.tgz#355f262505a621646b3130a728eb647e22055341"
+proto-list@~1.2.1:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
+ integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=
+
+proxy-addr@~2.0.3:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93"
+ integrity sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==
dependencies:
forwarded "~0.1.2"
- ipaddr.js "1.6.0"
+ ipaddr.js "1.8.0"
prr@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
+ integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
ps-tree@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014"
+ integrity sha1-tCGyQUDWID8e08dplrRCewjowBQ=
dependencies:
event-stream "~3.3.0"
pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
+ integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
pstree.remy@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.0.tgz#f2af27265bd3e5b32bbfcc10e80bac55ba78688b"
+ integrity sha512-q5I5vLRMVtdWa8n/3UEzZX7Lfghzrg9eG2IKk2ENLSofKRCXVqMvMUHxCKgXNaqH/8ebhBxrqftHWnyTFweJ5Q==
dependencies:
ps-tree "^1.1.0"
public-encrypt@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.0.tgz#39f699f3a46560dd5ebacbca693caf7c65c18cc6"
+ integrity sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=
dependencies:
bn.js "^4.1.0"
browserify-rsa "^4.0.0"
@@ -5457,6 +6570,15 @@ public-encrypt@^4.0.0:
pump@^2.0.0, pump@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
+ integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==
+ dependencies:
+ end-of-stream "^1.1.0"
+ once "^1.3.1"
+
+pump@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
+ integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
dependencies:
end-of-stream "^1.1.0"
once "^1.3.1"
@@ -5464,6 +6586,7 @@ pump@^2.0.0, pump@^2.0.1:
pumpify@^1.3.3:
version "1.4.0"
resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.4.0.tgz#80b7c5df7e24153d03f0e7ac8a05a5d068bd07fb"
+ integrity sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==
dependencies:
duplexify "^3.5.3"
inherits "^2.0.3"
@@ -5472,18 +6595,27 @@ pumpify@^1.3.3:
punycode@1.3.2, punycode@^1.2.4:
version "1.3.2"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
+ integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
+
+punycode@^2.1.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
+ integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
qjobs@^1.1.4:
version "1.2.0"
resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071"
+ integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==
qs@6.5.1:
version "6.5.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
+ integrity sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==
query-string@^5.0.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb"
+ integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==
dependencies:
decode-uri-component "^0.2.0"
object-assign "^4.1.0"
@@ -5492,28 +6624,29 @@ query-string@^5.0.1:
querystring-es3@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
+ integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=
querystring@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
+ integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
-querystringify@0.0.x:
- version "0.0.4"
- resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-0.0.4.tgz#0cf7f84f9463ff0ae51c4c4b142d95be37724d9c"
-
-querystringify@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-1.0.0.tgz#6286242112c5b712fa654e526652bf6a13ff05cb"
+querystringify@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.0.tgz#7ded8dfbf7879dcc60d0a644ac6754b283ad17ef"
+ integrity sha512-sluvZZ1YiTLD5jsqZcDmFyV2EwToyXZBfpoVOmktMmW+VEnhgakFHnasVph65fOjGPTWN0Nw3+XQaSeMayr0kg==
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
version "2.0.6"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80"
+ integrity sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==
dependencies:
safe-buffer "^5.1.0"
randomfill@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458"
+ integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==
dependencies:
randombytes "^2.0.5"
safe-buffer "^5.1.0"
@@ -5521,20 +6654,24 @@ randomfill@^1.0.3:
range-parser@^1.0.3, range-parser@^1.2.0, range-parser@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
+ integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=
raphael@^2.2.7:
version "2.2.7"
resolved "https://registry.yarnpkg.com/raphael/-/raphael-2.2.7.tgz#231b19141f8d086986d8faceb66f8b562ee2c810"
+ integrity sha1-IxsZFB+NCGmG2PrOtm+LVi7iyBA=
dependencies:
eve-raphael "0.5.0"
raven-js@^3.22.1:
version "3.22.1"
resolved "https://registry.yarnpkg.com/raven-js/-/raven-js-3.22.1.tgz#1117f00dfefaa427ef6e1a7d50bbb1fb998a24da"
+ integrity sha512-2Y8czUl5a9usbvXbpV8a+GPAiDXjxQjaHImZL0TyJWI5k5jV/6o+wceaBAg9g6RpO9OOJp0/w2mMs6pBoqOyDA==
raw-body@2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89"
+ integrity sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=
dependencies:
bytes "3.0.0"
http-errors "1.6.2"
@@ -5544,49 +6681,56 @@ raw-body@2.3.2:
raw-loader@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-0.5.1.tgz#0c3d0beaed8a01c966d9787bf778281252a979aa"
+ integrity sha1-DD0L6u2KAclm2Xh793goElKpeao=
-rc@^1.0.1, rc@^1.1.6, rc@^1.1.7:
- version "1.2.5"
- resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.5.tgz#275cd687f6e3b36cc756baa26dfee80a790301fd"
+rc@^1.0.1, rc@^1.1.6, rc@^1.2.7:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
+ integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
dependencies:
- deep-extend "~0.4.0"
+ deep-extend "^0.6.0"
ini "~1.3.0"
minimist "^1.2.0"
strip-json-comments "~2.0.1"
-read-pkg-up@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
- dependencies:
- find-up "^1.0.0"
- read-pkg "^1.0.0"
-
read-pkg-up@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be"
+ integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=
dependencies:
find-up "^2.0.0"
read-pkg "^2.0.0"
-read-pkg@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
+read-pkg-up@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978"
+ integrity sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==
dependencies:
- load-json-file "^1.0.0"
- normalize-package-data "^2.3.2"
- path-type "^1.0.0"
+ find-up "^3.0.0"
+ read-pkg "^3.0.0"
read-pkg@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8"
+ integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=
dependencies:
load-json-file "^2.0.0"
normalize-package-data "^2.3.2"
path-type "^2.0.0"
+read-pkg@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389"
+ integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=
+ dependencies:
+ load-json-file "^4.0.0"
+ normalize-package-data "^2.3.2"
+ path-type "^3.0.0"
+
"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.6:
version "2.3.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
+ integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.3"
@@ -5599,6 +6743,7 @@ read-pkg@^2.0.0:
readable-stream@~2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e"
+ integrity sha1-j5A0HmilPMySh4jaz80Rs265t44=
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.1"
@@ -5610,65 +6755,80 @@ readable-stream@~2.0.6:
readdirp@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78"
+ integrity sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=
dependencies:
graceful-fs "^4.1.2"
minimatch "^3.0.2"
readable-stream "^2.0.2"
set-immediate-shim "^1.0.1"
-redent@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
+regenerate-unicode-properties@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz#107405afcc4a190ec5ed450ecaa00ed0cafa7a4c"
+ integrity sha512-s5NGghCE4itSlUS+0WUj88G6cfMVMmH8boTPNvABf8od+2dhT9WDlWu8n01raQAJZMOK8Ch6jSexaRO7swd6aw==
dependencies:
- indent-string "^2.1.0"
- strip-indent "^1.0.1"
+ regenerate "^1.4.0"
-regenerate@^1.2.1:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260"
+regenerate@^1.2.1, regenerate@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11"
+ integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==
regenerator-runtime@^0.10.0:
version "0.10.5"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658"
+ integrity sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=
regenerator-runtime@^0.11.0:
- version "0.11.0"
- resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz#7e54fe5b5ccd5d6624ea6255c3473be090b802e1"
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
+ integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
-regenerator-transform@^0.10.0:
- version "0.10.1"
- resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd"
+regenerator-transform@^0.13.3:
+ version "0.13.3"
+ resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.13.3.tgz#264bd9ff38a8ce24b06e0636496b2c856b57bcbb"
+ integrity sha512-5ipTrZFSq5vU2YoGoww4uaRVAK4wyYC4TSICibbfEPOruUu8FFP7ErV0BjmbIOEpn3O/k9na9UEdYR/3m7N6uA==
dependencies:
- babel-runtime "^6.18.0"
- babel-types "^6.19.0"
private "^0.1.6"
regex-not@^1.0.0, regex-not@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"
+ integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==
dependencies:
extend-shallow "^3.0.2"
safe-regex "^1.1.0"
+regexpp@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.0.tgz#b2a7534a85ca1b033bcf5ce9ff8e56d4e0755365"
+ integrity sha512-g2FAVtR8Uh8GO1Nv5wpxW7VFVwHcCEr4wyA8/MHiRkO8uHoR5ntAA8Uq3P1vvMTX/BeQiRVSpDGLd+Wn5HNOTA==
+
regexpu-core@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b"
+ integrity sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=
dependencies:
regenerate "^1.2.1"
regjsgen "^0.2.0"
regjsparser "^0.1.4"
-regexpu-core@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240"
+regexpu-core@^4.1.3, regexpu-core@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.2.0.tgz#a3744fa03806cffe146dea4421a3e73bdcc47b1d"
+ integrity sha512-Z835VSnJJ46CNBttalHD/dB+Sj2ezmY6Xp38npwU87peK6mqOzOpV8eYktdkLTEkzzD+JsTcxd84ozd8I14+rw==
dependencies:
- regenerate "^1.2.1"
- regjsgen "^0.2.0"
- regjsparser "^0.1.4"
+ regenerate "^1.4.0"
+ regenerate-unicode-properties "^7.0.0"
+ regjsgen "^0.4.0"
+ regjsparser "^0.3.0"
+ unicode-match-property-ecmascript "^1.0.4"
+ unicode-match-property-value-ecmascript "^1.0.2"
registry-auth-token@^3.0.1:
version "3.3.2"
resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20"
+ integrity sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==
dependencies:
rc "^1.1.6"
safe-buffer "^5.0.1"
@@ -5676,97 +6836,122 @@ registry-auth-token@^3.0.1:
registry-url@^3.0.3:
version "3.1.0"
resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942"
+ integrity sha1-PU74cPc93h138M+aOBQyRE4XSUI=
dependencies:
rc "^1.0.1"
regjsgen@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7"
+ integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=
+
+regjsgen@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.4.0.tgz#c1eb4c89a209263f8717c782591523913ede2561"
+ integrity sha512-X51Lte1gCYUdlwhF28+2YMO0U6WeN0GLpgpA7LK7mbdDnkQYiwvEpmpe0F/cv5L14EbxgrdayAG3JETBv0dbXA==
regjsparser@^0.1.4:
version "0.1.5"
resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c"
+ integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=
+ dependencies:
+ jsesc "~0.5.0"
+
+regjsparser@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.3.0.tgz#3c326da7fcfd69fa0d332575a41c8c0cdf588c96"
+ integrity sha512-zza72oZBBHzt64G7DxdqrOo/30bhHkwMUoT0WqfGu98XLd7N+1tsy5MJ96Bk4MD0y74n629RhmrGW6XlnLLwCA==
dependencies:
jsesc "~0.5.0"
remove-trailing-separator@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
+ integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8=
repeat-element@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a"
+ integrity sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=
repeat-string@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-0.2.2.tgz#c7a8d3236068362059a7e4651fc6884e8b1fb4ae"
+ integrity sha1-x6jTI2BoNiBZp+RlH8aITosftK4=
-repeat-string@^1.5.2, repeat-string@^1.6.1:
+repeat-string@^1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
-
-repeating@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
- dependencies:
- is-finite "^1.0.0"
+ integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+ integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
require-main-filename@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
+ integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=
require-uncached@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3"
+ integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=
dependencies:
caller-path "^0.1.0"
resolve-from "^1.0.0"
-requires-port@1.0.x, requires-port@1.x.x:
+requires-port@1.x.x, requires-port@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
+ integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
resolve-cwd@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
+ integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=
dependencies:
resolve-from "^3.0.0"
resolve-from@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
+ integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=
resolve-from@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
+ integrity sha1-six699nWiBvItuZTM17rywoYh0g=
resolve-url@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
+ integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
resolve@1.1.x:
version "1.1.7"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
+ integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
-resolve@^1.4.0, resolve@^1.5.0, resolve@^1.6.0:
- version "1.7.1"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3"
+resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.6.0:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26"
+ integrity sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==
dependencies:
path-parse "^1.0.5"
responselike@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7"
+ integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=
dependencies:
lowercase-keys "^1.0.0"
restore-cursor@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
+ integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368=
dependencies:
onetime "^2.0.0"
signal-exit "^3.0.2"
@@ -5774,26 +6959,24 @@ restore-cursor@^2.0.0:
ret@~0.1.10:
version "0.1.15"
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
+ integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
rfdc@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.2.tgz#e6e72d74f5dc39de8f538f65e00c36c18018e349"
-
-right-align@^0.1.1:
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
- dependencies:
- align-text "^0.1.1"
+ integrity sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==
rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1, rimraf@^2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
+ integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==
dependencies:
glob "^7.0.5"
ripemd160@^2.0.0, ripemd160@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7"
+ integrity sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=
dependencies:
hash-base "^2.0.0"
inherits "^2.0.1"
@@ -5801,60 +6984,60 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
run-async@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0"
+ integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA=
dependencies:
is-promise "^2.1.0"
run-queue@^1.0.0, run-queue@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47"
+ integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=
dependencies:
aproba "^1.1.1"
rw@1:
version "1.3.3"
resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
-
-rx-lite-aggregates@^4.0.8:
- version "4.0.8"
- resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be"
- dependencies:
- rx-lite "*"
-
-rx-lite@*, rx-lite@^4.0.8:
- version "4.0.8"
- resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444"
+ integrity sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=
rx@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782"
+ integrity sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=
rxjs@^6.1.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.2.1.tgz#246cebec189a6cbc143a3ef9f62d6f4c91813ca1"
+ integrity sha512-OwMxHxmnmHTUpgO+V7dZChf3Tixf4ih95cmXjzzadULziVl/FKhHScGLj4goEw9weePVOH2Q0+GcCBUhKCZc/g==
dependencies:
tslib "^1.9.0"
safe-buffer@5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
+ integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==
-safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+ integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
safe-regex@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
+ integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4=
dependencies:
ret "~0.1.10"
"safer-buffer@>= 2.1.2 < 3":
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+ integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
sanitize-html@^1.16.1:
version "1.16.3"
resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.16.3.tgz#96c1b44a36ff7312e1c22a14b05274370ac8bd56"
+ integrity sha512-XpAJGnkMfNM7AzXLRw225blBB/pE4dM4jzRn98g4r88cfxwN6g+5IsRmCAh/gbhYGm6u6i97zsatMOM7Lr8wyw==
dependencies:
htmlparser2 "^3.9.0"
lodash.clonedeep "^4.5.0"
@@ -5867,50 +7050,77 @@ sanitize-html@^1.16.1:
sax@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+ integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
-schema-utils@^0.4.0, schema-utils@^0.4.2, schema-utils@^0.4.3, schema-utils@^0.4.4, schema-utils@^0.4.5:
+schema-utils@^0.4.0, schema-utils@^0.4.2, schema-utils@^0.4.4, schema-utils@^0.4.5:
version "0.4.5"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.5.tgz#21836f0608aac17b78f9e3e24daff14a5ca13a3e"
+ integrity sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==
dependencies:
ajv "^6.1.0"
ajv-keywords "^3.1.0"
+schema-utils@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"
+ integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==
+ dependencies:
+ ajv "^6.1.0"
+ ajv-errors "^1.0.0"
+ ajv-keywords "^3.1.0"
+
+scope-css@^1.0.5:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/scope-css/-/scope-css-1.2.1.tgz#c35768bc900cad030a3e0d663a818c0f6a57f40e"
+ integrity sha512-UjLRmyEYaDNiOS673xlVkZFlVCtckJR/dKgr434VMm7Lb+AOOqXKdAcY7PpGlJYErjXXJzKN7HWo4uRPiZZG0Q==
+ dependencies:
+ escaper "^2.5.3"
+ slugify "^1.3.1"
+ strip-css-comments "^3.0.0"
+
select-hose@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
+ integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=
select2@3.5.2-browserify:
version "3.5.2-browserify"
resolved "https://registry.yarnpkg.com/select2/-/select2-3.5.2-browserify.tgz#dc4dafda38d67a734e8a97a46f0d3529ae05391d"
+ integrity sha1-3E2v2jjWenNOipekbw01Ka4FOR0=
select@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
+ integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=
selfsigned@^1.9.1:
version "1.10.1"
resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.1.tgz#bf8cb7b83256c4551e31347c6311778db99eec52"
+ integrity sha1-v4y3uDJWxFUeMTR8YxF3jbme7FI=
dependencies:
node-forge "0.6.33"
semver-diff@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36"
+ integrity sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=
dependencies:
semver "^5.0.3"
-"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.5.0:
- version "5.5.0"
- resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
+"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
+ version "5.6.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
+ integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==
-send@0.16.1:
- version "0.16.1"
- resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3"
+send@0.16.2:
+ version "0.16.2"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
+ integrity sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==
dependencies:
debug "2.6.9"
- depd "~1.1.1"
+ depd "~1.1.2"
destroy "~1.0.4"
- encodeurl "~1.0.1"
+ encodeurl "~1.0.2"
escape-html "~1.0.3"
etag "~1.8.1"
fresh "0.5.2"
@@ -5919,50 +7129,57 @@ send@0.16.1:
ms "2.0.0"
on-finished "~2.3.0"
range-parser "~1.2.0"
- statuses "~1.3.1"
+ statuses "~1.4.0"
serialize-javascript@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.4.0.tgz#7c958514db6ac2443a8abc062dc9f7886a7f6005"
+ integrity sha1-fJWFFNtqwkQ6irwGLcn3iGp/YAU=
serve-index@^1.7.2:
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.0.tgz#d2b280fc560d616ee81b48bf0fa82abed2485ce7"
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239"
+ integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=
dependencies:
- accepts "~1.3.3"
+ accepts "~1.3.4"
batch "0.6.1"
- debug "2.6.8"
+ debug "2.6.9"
escape-html "~1.0.3"
- http-errors "~1.6.1"
- mime-types "~2.1.15"
- parseurl "~1.3.1"
+ http-errors "~1.6.2"
+ mime-types "~2.1.17"
+ parseurl "~1.3.2"
-serve-static@1.13.1:
- version "1.13.1"
- resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.1.tgz#4c57d53404a761d8f2e7c1e8a18a47dbf278a719"
+serve-static@1.13.2:
+ version "1.13.2"
+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1"
+ integrity sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==
dependencies:
- encodeurl "~1.0.1"
+ encodeurl "~1.0.2"
escape-html "~1.0.3"
parseurl "~1.3.2"
- send "0.16.1"
+ send "0.16.2"
set-blocking@^2.0.0, set-blocking@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
+ integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
set-getter@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.0.tgz#d769c182c9d5a51f409145f2fba82e5e86e80376"
+ integrity sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=
dependencies:
to-object-path "^0.3.0"
set-immediate-shim@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
+ integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=
set-value@^0.4.3:
version "0.4.3"
resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1"
+ integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE=
dependencies:
extend-shallow "^2.0.1"
is-extendable "^0.1.1"
@@ -5972,6 +7189,7 @@ set-value@^0.4.3:
set-value@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274"
+ integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==
dependencies:
extend-shallow "^2.0.1"
is-extendable "^0.1.1"
@@ -5981,18 +7199,22 @@ set-value@^2.0.0:
setimmediate@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
+ integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
setprototypeof@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04"
+ integrity sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=
setprototypeof@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
+ integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
sha.js@^2.4.0, sha.js@^2.4.8:
version "2.4.10"
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.10.tgz#b1fde5cd7d11a5626638a07c604ab909cfa31f9b"
+ integrity sha512-vnwmrFDlOExK4Nm16J2KMWHLrp14lBrjxMxBJpu++EnsuBmpiYaM/MEs46Vxxm/4FvdP5yTwuCTO9it5FSjrqA==
dependencies:
inherits "^2.0.1"
safe-buffer "^5.0.1"
@@ -6000,6 +7222,7 @@ sha.js@^2.4.0, sha.js@^2.4.8:
sha1@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/sha1/-/sha1-1.1.1.tgz#addaa7a93168f393f19eb2b15091618e2700f848"
+ integrity sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg=
dependencies:
charenc ">= 0.0.1"
crypt ">= 0.0.1"
@@ -6007,38 +7230,50 @@ sha1@^1.1.1:
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
+ integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=
dependencies:
shebang-regex "^1.0.0"
shebang-regex@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
+ integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
+
+sigmund@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
+ integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=
signal-exit@^3.0.0, signal-exit@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
-
-slash@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
+ integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
slice-ansi@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d"
+ integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==
dependencies:
is-fullwidth-code-point "^2.0.0"
-smooshpack@^0.0.48:
- version "0.0.48"
- resolved "https://registry.yarnpkg.com/smooshpack/-/smooshpack-0.0.48.tgz#6fbeaaf59226a1fe500f56aa17185eed377d2823"
+slugify@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.3.1.tgz#f572127e8535329fbc6c1edb74ab856b61ad7de2"
+ integrity sha512-6BwyhjF5tG5P8s+0DPNyJmBSBePG6iMyhjvIW5zGdA3tFik9PtK+yNkZgTeiroCRGZYgkHftFA62tGVK1EI9Kw==
+
+smooshpack@^0.0.53:
+ version "0.0.53"
+ resolved "https://registry.yarnpkg.com/smooshpack/-/smooshpack-0.0.53.tgz#aa397ca43619912e8ac0aa32012846ff4feaa5e8"
+ integrity sha512-FVXvKvZOz5+Tk/zUJ/wxM+ftu1yZtFEmeQl4chCqbzK/reU0L/OdDiYpx+/27Jt2VX09j08oIzwoyQ5fHH4+WQ==
dependencies:
- codesandbox-api "^0.0.18"
+ codesandbox-api "^0.0.20"
codesandbox-import-utils "^1.2.3"
lodash.isequal "^4.5.0"
snapdragon-node@^2.0.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b"
+ integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==
dependencies:
define-property "^1.0.0"
isobject "^3.0.0"
@@ -6047,12 +7282,14 @@ snapdragon-node@^2.0.1:
snapdragon-util@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2"
+ integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==
dependencies:
kind-of "^3.2.0"
snapdragon@^0.8.1:
version "0.8.1"
resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.1.tgz#e12b5487faded3e3dea0ac91e9400bf75b401370"
+ integrity sha1-4StUh/re0+PeoKyR6UAL91tAE3A=
dependencies:
base "^0.11.1"
debug "^2.2.0"
@@ -6066,10 +7303,12 @@ snapdragon@^0.8.1:
socket.io-adapter@~1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz#2a805e8a14d6372124dd9159ad4502f8cb07f06b"
+ integrity sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=
socket.io-client@2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-2.1.1.tgz#dcb38103436ab4578ddb026638ae2f21b623671f"
+ integrity sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==
dependencies:
backo2 "1.0.2"
base64-arraybuffer "0.1.5"
@@ -6089,6 +7328,7 @@ socket.io-client@2.1.1:
socket.io-parser@~3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-3.2.0.tgz#e7c6228b6aa1f814e6148aea325b51aa9499e077"
+ integrity sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==
dependencies:
component-emitter "1.2.1"
debug "~3.1.0"
@@ -6097,6 +7337,7 @@ socket.io-parser@~3.2.0:
socket.io@2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-2.1.1.tgz#a069c5feabee3e6b214a75b40ce0652e1cfb9980"
+ integrity sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==
dependencies:
debug "~3.1.0"
engine.io "~3.2.0"
@@ -6105,20 +7346,22 @@ socket.io@2.1.1:
socket.io-client "2.1.1"
socket.io-parser "~3.2.0"
-sockjs-client@1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.1.4.tgz#5babe386b775e4cf14e7520911452654016c8b12"
+sockjs-client@1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.3.0.tgz#12fc9d6cb663da5739d3dc5fb6e8687da95cb177"
+ integrity sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==
dependencies:
- debug "^2.6.6"
- eventsource "0.1.6"
- faye-websocket "~0.11.0"
- inherits "^2.0.1"
+ debug "^3.2.5"
+ eventsource "^1.0.7"
+ faye-websocket "~0.11.1"
+ inherits "^2.0.3"
json3 "^3.3.2"
- url-parse "^1.1.8"
+ url-parse "^1.4.3"
sockjs@0.3.19:
version "0.3.19"
resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.19.tgz#d976bbe800af7bd20ae08598d582393508993c0d"
+ integrity sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==
dependencies:
faye-websocket "^0.10.0"
uuid "^3.0.1"
@@ -6126,20 +7369,24 @@ sockjs@0.3.19:
sort-keys@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128"
+ integrity sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=
dependencies:
is-plain-obj "^1.0.0"
sortablejs@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.7.0.tgz#80a2b2370abd568e1cec8c271131ef30a904fa28"
+ integrity sha1-gKKyNwq9Vo4c7IwnETHvMKkE+ig=
source-list-map@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085"
+ integrity sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==
source-map-resolve@^0.5.0:
version "0.5.1"
resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.1.tgz#7ad0f593f2281598e854df80f19aae4b92d7a11a"
+ integrity sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==
dependencies:
atob "^2.0.0"
decode-uri-component "^0.2.0"
@@ -6147,57 +7394,54 @@ source-map-resolve@^0.5.0:
source-map-url "^0.4.0"
urix "^0.1.0"
-source-map-support@^0.4.15:
- version "0.4.18"
- resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
- dependencies:
- source-map "^0.5.6"
-
source-map-url@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3"
+ integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=
source-map@0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.0.tgz#0fe96503ac86a5adb5de63f4e412ae4872cdbe86"
+ integrity sha1-D+llA6yGpa213mP05BKuSHLNvoY=
-source-map@^0.4.4:
- version "0.4.4"
- resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b"
- dependencies:
- amdefine ">=0.0.4"
-
-source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1:
+source-map@^0.5.0, source-map@^0.5.6:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
+ integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
source-map@^0.6.1, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
source-map@~0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d"
+ integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50=
dependencies:
amdefine ">=0.0.4"
spdx-correct@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40"
+ integrity sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=
dependencies:
spdx-license-ids "^1.0.2"
spdx-expression-parse@~1.0.0:
version "1.0.4"
resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c"
+ integrity sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=
spdx-license-ids@^1.0.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57"
+ integrity sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=
spdy-transport@^2.0.18:
version "2.0.20"
resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.0.20.tgz#735e72054c486b2354fe89e702256004a39ace4d"
+ integrity sha1-c15yBUxIayNU/onnAiVgBKOazk0=
dependencies:
debug "^2.6.8"
detect-node "^2.0.3"
@@ -6210,6 +7454,7 @@ spdy-transport@^2.0.18:
spdy@^3.4.1:
version "3.4.7"
resolved "https://registry.yarnpkg.com/spdy/-/spdy-3.4.7.tgz#42ff41ece5cc0f99a3a6c28aabb73f5c3b03acbc"
+ integrity sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=
dependencies:
debug "^2.6.8"
handle-thing "^1.2.5"
@@ -6221,26 +7466,31 @@ spdy@^3.4.1:
split-string@^3.0.1, split-string@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2"
+ integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==
dependencies:
extend-shallow "^3.0.0"
split@0.3:
version "0.3.3"
resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f"
+ integrity sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=
dependencies:
through "2"
sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+ integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
sql.js@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/sql.js/-/sql.js-0.4.0.tgz#23be9635520eb0ff43a741e7e830397266e88445"
+ integrity sha1-I76WNVIOsP9Dp0Hn6DA5cmbohEU=
srcset@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/srcset/-/srcset-1.0.0.tgz#a5669de12b42f3b1d5e83ed03c71046fc48f41ef"
+ integrity sha1-pWad4StC87HV6D7QPHEEb8SPQe8=
dependencies:
array-uniq "^1.0.2"
number-is-nan "^1.0.0"
@@ -6248,27 +7498,44 @@ srcset@^1.0.0:
ssri@^5.2.4:
version "5.2.4"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.2.4.tgz#9985e14041e65fc397af96542be35724ac11da52"
+ integrity sha512-UnEAgMZa15973iH7cUi0AHjJn1ACDIkaMyZILoqwN6yzt+4P81I8tBc5Hl+qwi5auMplZtPQsHrPBR5vJLcQtQ==
dependencies:
safe-buffer "^5.1.1"
+ssri@^6.0.0:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8"
+ integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==
+ dependencies:
+ figgy-pudding "^3.5.1"
+
static-extend@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6"
+ integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=
dependencies:
define-property "^0.2.5"
object-copy "^0.1.0"
-"statuses@>= 1.3.1 < 2", statuses@~1.3.1:
+"statuses@>= 1.3.1 < 2", statuses@~1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
+ integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==
+
+statuses@~1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"
+ integrity sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=
stickyfilljs@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/stickyfilljs/-/stickyfilljs-2.0.5.tgz#d229e372d2199ddf5d283bbe34ac1f7d2529c2fc"
+ integrity sha512-KGKdqKbv1jXit54ltFPIWw/XVeuSrJmTUS8viT1Pmdpp1Jyv3SMpFmhvPBdddX9FHDlHbm9s8cPAhPviBaBVpA==
stream-browserify@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db"
+ integrity sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=
dependencies:
inherits "~2.0.1"
readable-stream "^2.0.2"
@@ -6276,12 +7543,14 @@ stream-browserify@^2.0.1:
stream-combiner@~0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14"
+ integrity sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=
dependencies:
duplexer "~0.1.1"
stream-each@^1.1.0:
version "1.2.2"
resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.2.tgz#8e8c463f91da8991778765873fe4d960d8f616bd"
+ integrity sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==
dependencies:
end-of-stream "^1.1.0"
stream-shift "^1.0.0"
@@ -6289,6 +7558,7 @@ stream-each@^1.1.0:
stream-http@^2.7.2:
version "2.8.2"
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.2.tgz#4126e8c6b107004465918aa2fc35549e77402c87"
+ integrity sha512-QllfrBhqF1DPcz46WxKTs6Mz1Bpc+8Qm6vbqOpVav5odAXwbyzwnEczoWqtxrsmlO+cJqtPrp/8gWKWjaKLLlA==
dependencies:
builtin-status-codes "^3.0.0"
inherits "^2.0.1"
@@ -6299,10 +7569,12 @@ stream-http@^2.7.2:
stream-shift@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
+ integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=
streamroller@0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-0.7.0.tgz#a1d1b7cf83d39afb0d63049a5acbf93493bdf64b"
+ integrity sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==
dependencies:
date-format "^1.2.0"
debug "^3.1.0"
@@ -6312,10 +7584,12 @@ streamroller@0.7.0:
strict-uri-encode@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
+ integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=
string-width@^1.0.1, string-width@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
+ integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
dependencies:
code-point-at "^1.0.0"
is-fullwidth-code-point "^1.0.0"
@@ -6324,6 +7598,7 @@ string-width@^1.0.1, string-width@^1.0.2:
string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
+ integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
dependencies:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^4.0.0"
@@ -6331,52 +7606,55 @@ string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
string_decoder@^1.0.0, string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+ integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
dependencies:
safe-buffer "~5.1.0"
string_decoder@~0.10.x:
version "0.10.31"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
+ integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
strip-ansi@^3.0.0, strip-ansi@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
+ integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
dependencies:
ansi-regex "^2.0.0"
strip-ansi@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
+ integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8=
dependencies:
ansi-regex "^3.0.0"
-strip-bom@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
- dependencies:
- is-utf8 "^0.2.0"
-
strip-bom@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
+ integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=
+
+strip-css-comments@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-css-comments/-/strip-css-comments-3.0.0.tgz#7a5625eff8a2b226cf8947a11254da96e13dae89"
+ integrity sha1-elYl7/iisibPiUehElTaluE9rok=
+ dependencies:
+ is-regexp "^1.0.0"
strip-eof@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
+ integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
-strip-indent@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
- dependencies:
- get-stdin "^4.0.1"
-
-strip-json-comments@~2.0.1:
+strip-json-comments@^2.0.1, strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
+ integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
-style-loader@^0.21.0:
- version "0.21.0"
- resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.21.0.tgz#68c52e5eb2afc9ca92b6274be277ee59aea3a852"
+style-loader@^0.23.0:
+ version "0.23.0"
+ resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.0.tgz#8377fefab68416a2e05f1cabd8c3a3acfcce74f1"
+ integrity sha512-uCcN7XWHkqwGVt7skpInW6IGO1tG6ReyFQ1Cseh0VcN6VdcFQi62aG/2F3Y9ueA8x4IVlfaSUxpmQXQD9QrEuQ==
dependencies:
loader-utils "^1.1.0"
schema-utils "^0.4.5"
@@ -6384,29 +7662,39 @@ style-loader@^0.21.0:
supports-color@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
+ integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=
-supports-color@^3.1.0, supports-color@^3.1.2:
+supports-color@^3.1.0:
version "3.2.3"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
+ integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=
dependencies:
has-flag "^1.0.0"
supports-color@^5.1.0, supports-color@^5.2.0, supports-color@^5.3.0, supports-color@^5.4.0:
- version "5.4.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54"
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
+ integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
dependencies:
has-flag "^3.0.0"
svg4everybody@2.1.9:
version "2.1.9"
resolved "https://registry.yarnpkg.com/svg4everybody/-/svg4everybody-2.1.9.tgz#5bd9f6defc133859a044646d4743fabc28db7e2d"
+ integrity sha1-W9n23vwTOFmgRGRtR0P6vCjbfi0=
-table@^4.0.1:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36"
+symbol-observable@^1.0.2:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
+ integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==
+
+table@^4.0.3:
+ version "4.0.3"
+ resolved "http://registry.npmjs.org/table/-/table-4.0.3.tgz#00b5e2b602f1794b9acaf9ca908a76386a7813bc"
+ integrity sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==
dependencies:
- ajv "^5.2.3"
- ajv-keywords "^2.1.0"
+ ajv "^6.0.1"
+ ajv-keywords "^3.0.0"
chalk "^2.1.0"
lodash "^4.17.4"
slice-ansi "1.0.0"
@@ -6415,14 +7703,17 @@ table@^4.0.1:
tapable@^0.1.8:
version "0.1.10"
resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4"
+ integrity sha1-KcNXB8K3DlDQdIK10gLo7URtr9Q=
-tapable@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.0.0.tgz#cbb639d9002eed9c6b5975eb20598d7936f1f9f2"
+tapable@^1.0.0, tapable@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.0.tgz#0d076a172e3d9ba088fd2272b2668fb8d194b78c"
+ integrity sha512-IlqtmLVaZA2qab8epUXbVWRn3aB1imbDMJtjB3nu4X0NqPkcY/JH9ZtCBWKHWPxs8Svi9tyo8w2dBoi07qZbBA==
tar@^4:
version "4.4.4"
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.4.tgz#ec8409fae9f665a4355cc3b4087d0820232bb8cd"
+ integrity sha512-mq9ixIYfNF9SK0IS/h2HKMu8Q2iaCuhDDsZhdEag/FHv8fOaYld4vN7ouMgcSSt5WKZzPs8atclTcJm36OTh4w==
dependencies:
chownr "^1.0.1"
fs-minipass "^1.2.5"
@@ -6435,42 +7726,54 @@ tar@^4:
term-size@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69"
+ integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=
dependencies:
execa "^0.7.0"
-test-exclude@^4.2.1:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.1.tgz#dfa222f03480bca69207ca728b37d74b45f724fa"
+test-exclude@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.0.0.tgz#cdce7cece785e0e829cd5c2b27baf18bc583cfb7"
+ integrity sha512-bO3Lj5+qFa9YLfYW2ZcXMOV1pmQvw+KS/DpjqhyX6Y6UZ8zstpZJ+mA2ERkXfpOqhxsJlQiLeVXD3Smsrs6oLw==
dependencies:
arrify "^1.0.1"
- micromatch "^3.1.8"
- object-assign "^4.1.0"
- read-pkg-up "^1.0.1"
+ minimatch "^3.0.4"
+ read-pkg-up "^4.0.0"
require-main-filename "^1.0.1"
-text-table@~0.2.0:
+text-table@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+ integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
textextensions@2:
version "2.2.0"
resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-2.2.0.tgz#38ac676151285b658654581987a0ce1a4490d286"
+ integrity sha512-j5EMxnryTvKxwH2Cq+Pb43tsf6sdEgw6Pdwxk83mPaq0ToeFJt6WE4J3s5BqY7vmjlLgkgXvhtXUxo80FyBhCA==
three-orbit-controls@^82.1.0:
version "82.1.0"
resolved "https://registry.yarnpkg.com/three-orbit-controls/-/three-orbit-controls-82.1.0.tgz#11a7f33d0a20ecec98f098b37780f6537374fab4"
+ integrity sha1-EafzPQog7OyY8Jizd4D2U3N0+rQ=
three-stl-loader@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/three-stl-loader/-/three-stl-loader-1.0.4.tgz#6b3319a31e3b910aab1883d19b00c81a663c3e03"
+ integrity sha1-azMZox47kQqrGIPRmwDIGmY8PgM=
three@^0.84.0:
version "0.84.0"
resolved "https://registry.yarnpkg.com/three/-/three-0.84.0.tgz#95be85a55a0fa002aa625ed559130957dcffd918"
+ integrity sha1-lb6FpVoPoAKqYl7VWRMJV9z/2Rg=
+
+throttle-debounce@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.0.1.tgz#7307ddd6cd9acadb349132fbf6c18d78c88a5e62"
+ integrity sha512-Sr6jZBlWShsAaSXKyNXyNicOrJW/KtkDqIEwHt4wYwWA2wa/q67Luhqoujg48V8hTk60wB56tYrJJn6jc2R7VA==
through2@^2.0.0:
version "2.0.3"
resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be"
+ integrity sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=
dependencies:
readable-stream "^2.1.5"
xtend "~4.0.1"
@@ -6478,62 +7781,75 @@ through2@^2.0.0:
through@2, through@^2.3.6, through@~2.3, through@~2.3.1:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+ integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
thunky@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/thunky/-/thunky-0.1.0.tgz#bf30146824e2b6e67b0f2d7a4ac8beb26908684e"
+ integrity sha1-vzAUaCTituZ7Dy16Ssi+smkIaE4=
timeago.js@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/timeago.js/-/timeago.js-3.0.2.tgz#32a67e7c0d887ea42ca588d3aae26f77de5e76cc"
+ integrity sha1-MqZ+fA2IfqQspYjTquJvd95edsw=
dependencies:
"@types/jquery" "^2.0.40"
timed-out@^4.0.0, timed-out@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f"
+ integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=
timers-browserify@^2.0.4:
version "2.0.10"
resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae"
+ integrity sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==
dependencies:
setimmediate "^1.0.4"
tiny-emitter@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.2.tgz#82d27468aca5ade8e5fd1e6d22b57dd43ebdfb7c"
+ integrity sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow==
tmp@0.0.33, tmp@0.0.x, tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
+ integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
dependencies:
os-tmpdir "~1.0.2"
to-array@0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
+ integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA=
to-arraybuffer@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
+ integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=
to-fast-properties@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
+ integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=
to-fast-properties@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+ integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
to-object-path@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
+ integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=
dependencies:
kind-of "^3.0.2"
to-regex-range@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38"
+ integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=
dependencies:
is-number "^3.0.0"
repeat-string "^1.6.1"
@@ -6541,55 +7857,56 @@ to-regex-range@^2.1.0:
to-regex@^3.0.1, to-regex@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
+ integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==
dependencies:
define-property "^2.0.2"
extend-shallow "^3.0.2"
regex-not "^1.0.2"
safe-regex "^1.1.0"
+toggle-selection@^1.0.3:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32"
+ integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI=
+
touch@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b"
+ integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==
dependencies:
nopt "~1.0.10"
-traverse@0.6.6:
- version "0.6.6"
- resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137"
-
-trim-newlines@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
-
trim-right@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
+ integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=
tryer@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.0.tgz#027b69fa823225e551cace3ef03b11f6ab37c1d7"
-
-tryit@^1.0.1:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb"
+ integrity sha1-Antp+oIyJeVRys4+8DsR9qs3wdc=
tslib@^1.9.0:
version "1.9.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
+ integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==
tty-browserify@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
+ integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=
type-check@~0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+ integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=
dependencies:
prelude-ls "~1.1.2"
-type-is@~1.6.15:
+type-is@~1.6.15, type-is@~1.6.16:
version "1.6.16"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194"
+ integrity sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==
dependencies:
media-typer "0.3.0"
mime-types "~2.1.18"
@@ -6597,34 +7914,33 @@ type-is@~1.6.15:
typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
+ integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
typescript@^2:
version "2.9.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c"
+ integrity sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==
uglify-es@^3.3.4:
version "3.3.9"
resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.9.tgz#0c1c4f0700bed8dbc124cdb304d2592ca203e677"
+ integrity sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==
dependencies:
commander "~2.13.0"
source-map "~0.6.1"
-uglify-js@^2.6:
- version "2.8.29"
- resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
+uglify-js@^3.1.4:
+ version "3.4.9"
+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3"
+ integrity sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==
dependencies:
- source-map "~0.5.1"
- yargs "~3.10.0"
- optionalDependencies:
- uglify-to-browserify "~1.0.0"
-
-uglify-to-browserify@~1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
+ commander "~2.17.1"
+ source-map "~0.6.1"
uglifyjs-webpack-plugin@^1.2.4:
version "1.2.5"
resolved "https://registry.yarnpkg.com/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.2.5.tgz#2ef8387c8f1a903ec5e44fa36f9f3cbdcea67641"
+ integrity sha512-hIQJ1yxAPhEA2yW/i7Fr+SXZVMp+VEI3d42RTHBgQd2yhp/1UdBcR3QEWPV5ahBxlqQDMEMTuTEvDHSFINfwSw==
dependencies:
cacache "^10.0.4"
find-cache-dir "^1.0.0"
@@ -6638,20 +7954,47 @@ uglifyjs-webpack-plugin@^1.2.4:
ultron@~1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c"
+ integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==
undefsafe@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.2.tgz#225f6b9e0337663e0d8e7cfd686fc2836ccace76"
+ integrity sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY=
dependencies:
debug "^2.2.0"
underscore@^1.9.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.0.tgz#31dbb314cfcc88f169cd3692d9149d81a00a73e4"
+ integrity sha512-4IV1DSSxC1QK48j9ONFK1MoIAKKkbE8i7u55w2R6IqBqbT7A/iG7aZBCR2Bi8piF0Uz+i/MG1aeqLwl/5vqF+A==
+
+unicode-canonical-property-names-ecmascript@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"
+ integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==
+
+unicode-match-property-ecmascript@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c"
+ integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==
+ dependencies:
+ unicode-canonical-property-names-ecmascript "^1.0.4"
+ unicode-property-aliases-ecmascript "^1.0.4"
+
+unicode-match-property-value-ecmascript@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz#9f1dc76926d6ccf452310564fd834ace059663d4"
+ integrity sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ==
+
+unicode-property-aliases-ecmascript@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz#5a533f31b4317ea76f17d807fa0d116546111dd0"
+ integrity sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==
union-value@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4"
+ integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=
dependencies:
arr-union "^3.1.0"
get-value "^2.0.6"
@@ -6661,32 +8004,38 @@ union-value@^1.0.0:
uniq@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
+ integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=
unique-filename@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.0.tgz#d05f2fe4032560871f30e93cbe735eea201514f3"
+ integrity sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=
dependencies:
unique-slug "^2.0.0"
unique-slug@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.0.tgz#db6676e7c7cc0629878ff196097c78855ae9f4ab"
+ integrity sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=
dependencies:
imurmurhash "^0.1.4"
unique-string@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a"
+ integrity sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=
dependencies:
crypto-random-string "^1.0.0"
unpipe@1.0.0, unpipe@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+ integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
unset-value@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
+ integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=
dependencies:
has-value "^0.3.1"
isobject "^3.0.0"
@@ -6694,14 +8043,17 @@ unset-value@^1.0.0:
unzip-response@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97"
+ integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=
upath@^1.0.5:
version "1.1.0"
resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd"
+ integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==
update-notifier@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.3.0.tgz#4e8827a6bb915140ab093559d7014e3ebb837451"
+ integrity sha1-TognpruRUUCrCTVZ1wFOPruDdFE=
dependencies:
boxen "^1.2.1"
chalk "^2.0.1"
@@ -6713,55 +8065,63 @@ update-notifier@^2.3.0:
semver-diff "^2.0.0"
xdg-basedir "^3.0.0"
+uri-js@^4.2.2:
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
+ integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==
+ dependencies:
+ punycode "^2.1.0"
+
urix@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
+ integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
-url-join@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.0.tgz#4d3340e807d3773bda9991f8305acdcc2a665d2a"
-
-url-loader@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-1.0.1.tgz#61bc53f1f184d7343da2728a1289ef8722ea45ee"
+url-loader@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-1.1.1.tgz#4d1f3b4f90dde89f02c008e662d604d7511167c1"
+ integrity sha512-vugEeXjyYFBCUOpX+ZuaunbK3QXMKaQ3zUnRfIpRBlGkY7QizCnzyyn2ASfcxsvyU3ef+CJppVywnl3Kgf13Gg==
dependencies:
loader-utils "^1.1.0"
mime "^2.0.3"
- schema-utils "^0.4.3"
+ schema-utils "^1.0.0"
url-parse-lax@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73"
+ integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=
dependencies:
prepend-http "^1.0.1"
url-parse-lax@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c"
+ integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=
dependencies:
prepend-http "^2.0.0"
-url-parse@1.0.x:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.0.5.tgz#0854860422afdcfefeb6c965c662d4800169927b"
+url-parse@^1.4.3:
+ version "1.4.4"
+ resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.4.tgz#cac1556e95faa0303691fec5cf9d5a1bc34648f8"
+ integrity sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==
dependencies:
- querystringify "0.0.x"
- requires-port "1.0.x"
+ querystringify "^2.0.0"
+ requires-port "^1.0.0"
-url-parse@^1.1.8:
- version "1.1.9"
- resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.1.9.tgz#c67f1d775d51f0a18911dd7b3ffad27bb9e5bd19"
- dependencies:
- querystringify "~1.0.0"
- requires-port "1.0.x"
+url-search-params-polyfill@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/url-search-params-polyfill/-/url-search-params-polyfill-5.0.0.tgz#09b98337c89dcf6c6a6a0bfeb096f6ba83b7526b"
+ integrity sha512-+SCD22QJp4UnqPOI5UTTR0Ljuh8cHbjEf1lIiZrZ8nHTlTixqwVsVQTSfk5vrmDz7N09/Y+ka5jQr0ff35FnQQ==
url-to-options@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9"
+ integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=
url@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
+ integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=
dependencies:
punycode "1.3.2"
querystring "0.2.0"
@@ -6769,6 +8129,7 @@ url@^0.11.0:
use@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/use/-/use-2.0.2.tgz#ae28a0d72f93bf22422a18a2e379993112dec8e8"
+ integrity sha1-riig1y+TvyJCKhii43mZMRLeyOg=
dependencies:
define-property "^0.2.5"
isobject "^3.0.0"
@@ -6777,6 +8138,7 @@ use@^2.0.0:
useragent@2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.2.1.tgz#cf593ef4f2d175875e8bb658ea92e18a4fd06d8e"
+ integrity sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=
dependencies:
lru-cache "2.2.x"
tmp "0.0.x"
@@ -6784,74 +8146,104 @@ useragent@2.2.1:
util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+ integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
+
+util.promisify@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030"
+ integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==
+ dependencies:
+ define-properties "^1.1.2"
+ object.getownpropertydescriptors "^2.0.3"
util@0.10.3, util@^0.10.3:
version "0.10.3"
resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
+ integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk=
dependencies:
inherits "2.0.1"
utils-merge@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
+ integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
-uuid@^3.0.1, uuid@^3.1.0:
+uuid@^3.0.1, uuid@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
+ integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==
v8-compile-cache@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.0.tgz#526492e35fc616864284700b7043e01baee09f0a"
+ integrity sha512-qNdTUMaCjPs4eEnM3W9H94R3sU70YCuT+/ST7nUf+id1bVOrdjrpUaeZLqPBPRph3hsgn4a4BvwpxhHZx+oSDg==
validate-npm-package-license@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
+ integrity sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=
dependencies:
spdx-correct "~1.0.0"
spdx-expression-parse "~1.0.0"
-vary@~1.1.1, vary@~1.1.2:
+vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+ integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
visibilityjs@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/visibilityjs/-/visibilityjs-1.2.4.tgz#bff8663da62c8c10ad4ee5ae6a1ae6fac4259d63"
+ integrity sha1-v/hmPaYsjBCtTuWuahrm+sQlnWM=
vm-browserify@0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73"
+ integrity sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=
dependencies:
indexof "0.0.1"
void-elements@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
+ integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
-vue-eslint-parser@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz#c268c96c6d94cfe3d938a5f7593959b0ca3360d1"
+vue-apollo@^3.0.0-beta.25:
+ version "3.0.0-beta.25"
+ resolved "https://registry.yarnpkg.com/vue-apollo/-/vue-apollo-3.0.0-beta.25.tgz#05a9a699b2ba6103639e9bd6c3bb88ca04c4b637"
+ integrity sha512-M7/l3h0NlFvaZ/s/wrtRiOt3xXMbaNNuteGaCY+U5D0ABrQqvCgy5mayIZHurQxbloluNkbCt18wRKAgJTAuKA==
+ dependencies:
+ chalk "^2.4.1"
+ throttle-debounce "^2.0.0"
+
+vue-eslint-parser@^3.2.1:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-3.2.2.tgz#47c971ee4c39b0ee7d7f5e154cb621beb22f7a34"
+ integrity sha512-dprI6ggKCTwV22r+i8dtUGquiOCn063xyDmb7BV/BjG5Oc/m5EoMNrWevpvTcrlGuFZmYVPs5fgsu8UIxmMKzg==
dependencies:
debug "^3.1.0"
- eslint-scope "^3.7.1"
+ eslint-scope "^4.0.0"
eslint-visitor-keys "^1.0.0"
- espree "^3.5.2"
- esquery "^1.0.0"
- lodash "^4.17.4"
+ espree "^4.0.0"
+ esquery "^1.0.1"
+ lodash "^4.17.10"
vue-functional-data-merge@^2.0.5:
version "2.0.6"
resolved "https://registry.yarnpkg.com/vue-functional-data-merge/-/vue-functional-data-merge-2.0.6.tgz#f08055adfb92458debcf2ad10c3aa712277f7fc2"
+ integrity sha512-eivElFOJwhXJopKlq71/8onDxOKK4quPwWGFF9yIVjpU2sNzxISRpufu18bh674ivSADuEAPU2OhT+vrH0E9Mg==
vue-hot-reload-api@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.0.tgz#97976142405d13d8efae154749e88c4e358cf926"
+ integrity sha512-2j/t+wIbyVMP5NvctQoSUvLkYKoWAAk2QlQiilrM2a6/ulzFgdcLUJfTvs4XQ/3eZhHiBmmEojbjmM4AzZj8JA==
-vue-loader@^15.2.4:
- version "15.2.4"
- resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.2.4.tgz#a7b923123d3cf87230a8ff54a1c16d31a6c5dbb4"
+vue-loader@^15.4.2:
+ version "15.4.2"
+ resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-15.4.2.tgz#812bb26e447dd3b84c485eb634190d914ce125e2"
+ integrity sha512-nVV27GNIA9MeoD8yQ3dkUzwlAaAsWeYSWZHsu/K04KCD339lW0Jv2sJWsjj3721SP7sl2lYdPmjcHgkWQSp5bg==
dependencies:
- "@vue/component-compiler-utils" "^1.2.1"
+ "@vue/component-compiler-utils" "^2.0.0"
hash-sum "^1.0.2"
loader-utils "^1.1.0"
vue-hot-reload-api "^2.3.0"
@@ -6860,23 +8252,27 @@ vue-loader@^15.2.4:
vue-resource@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/vue-resource/-/vue-resource-1.5.0.tgz#ba0c6ef7af2eeace03cf24a91f529471be974c72"
+ integrity sha512-em+Ihe+duUWQv4uKO8aFTGK+e/lvNtk5EBEmWaBYcfQzBmHhKR4jJAeVIHcG6otugmsme/DmYrOEPfbss+2XfQ==
dependencies:
got "^8.0.3"
vue-router@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.1.tgz#d9b05ad9c7420ba0f626d6500d693e60092cc1e9"
+ integrity sha512-vLLoY452L+JBpALMP5UHum9+7nzR9PeIBCghU9ZtJ1eWm6ieUI8Zb/DI3MYxH32bxkjzYV1LRjNv4qr8d+uX/w==
vue-style-loader@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/vue-style-loader/-/vue-style-loader-4.1.0.tgz#7588bd778e2c9f8d87bfc3c5a4a039638da7a863"
+ integrity sha512-IsSiXDrLW2QIjyBsCqa35e45l5AceMbJ2jO8DxoEQv75xu/UmtXkSC0ybESq/LpbmmIW47MAWDQvErUw+Hrz/A==
dependencies:
hash-sum "^1.0.2"
loader-utils "^1.0.2"
-vue-template-compiler@^2.5.0, vue-template-compiler@^2.5.16:
- version "2.5.16"
- resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.16.tgz#93b48570e56c720cdf3f051cc15287c26fbd04cb"
+vue-template-compiler@^2.5.0, vue-template-compiler@^2.5.17:
+ version "2.5.17"
+ resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.17.tgz#52a4a078c327deb937482a509ae85c06f346c3cb"
+ integrity sha512-63uI4syCwtGR5IJvZM0LN5tVsahrelomHtCxvRkZPJ/Tf3ADm1U1wG6KWycK3qCfqR+ygM5vewUvmJ0REAYksg==
dependencies:
de-indent "^1.0.2"
he "^1.1.0"
@@ -6884,22 +8280,27 @@ vue-template-compiler@^2.5.0, vue-template-compiler@^2.5.16:
vue-template-es2015-compiler@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz#dc42697133302ce3017524356a6c61b7b69b4a18"
+ integrity sha512-x3LV3wdmmERhVCYy3quqA57NJW7F3i6faas++pJQWtknWT+n7k30F4TVdHvCLn48peTJFRvCpxs3UuFPqgeELg==
vue-virtual-scroll-list@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/vue-virtual-scroll-list/-/vue-virtual-scroll-list-1.2.5.tgz#bcbd010f7cdb035eba8958ebf807c6214d9a167a"
+ integrity sha1-vL0BD3zbA166iVjr+AfGIU2aFno=
-vue@^2.5.16:
- version "2.5.16"
- resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.16.tgz#07edb75e8412aaeed871ebafa99f4672584a0085"
+vue@^2.5.16, vue@^2.5.17:
+ version "2.5.17"
+ resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.17.tgz#0f8789ad718be68ca1872629832ed533589c6ada"
+ integrity sha512-mFbcWoDIJi0w0Za4emyLiW72Jae0yjANHbCVquMKijcavBGypqlF7zHRgMa5k4sesdv7hv2rB4JPdZfR+TPfhQ==
vuex@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.0.1.tgz#e761352ebe0af537d4bb755a9b9dc4be3df7efd2"
+ integrity sha512-wLoqz0B7DSZtgbWL1ShIBBCjv22GV5U+vcBFox658g6V0s4wZV9P4YjCNyoHSyIBpj1f29JBoNQIqD82cR4O3w==
watchpack@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.5.0.tgz#231e783af830a22f8966f65c4c4bacc814072eed"
+ integrity sha512-RSlipNQB1u48cq0wH/BNfCu1tD/cJ8ydFIkNYhp9o+3d+8unClkIovpW5qpFPgmL9OE48wfAnlZydXByWP82AA==
dependencies:
chokidar "^2.0.2"
graceful-fs "^4.1.2"
@@ -6908,29 +8309,32 @@ watchpack@^1.5.0:
wbuf@^1.1.0, wbuf@^1.7.2:
version "1.7.2"
resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.2.tgz#d697b99f1f59512df2751be42769c1580b5801fe"
+ integrity sha1-1pe5nx9ZUS3ydRvkJ2nBWAtYAf4=
dependencies:
minimalistic-assert "^1.0.0"
-webpack-bundle-analyzer@^2.13.1:
- version "2.13.1"
- resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.13.1.tgz#07d2176c6e86c3cdce4c23e56fae2a7b6b4ad526"
+webpack-bundle-analyzer@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.0.2.tgz#22f19ea6d1b5a15fd7a90baae0bc0f39bd1e4d48"
+ integrity sha512-cZG4wSQtKrSpk5RJ33dxiaAyo8bP0V+JvycAyIDFEiDIhw4LHhhVKhn40YT1w6TR9E4scHA00LnIoBtTA13Mow==
dependencies:
- acorn "^5.3.0"
- bfj-node4 "^5.2.0"
- chalk "^2.3.0"
- commander "^2.13.0"
- ejs "^2.5.7"
- express "^4.16.2"
- filesize "^3.5.11"
- gzip-size "^4.1.0"
- lodash "^4.17.4"
+ acorn "^5.7.3"
+ bfj "^6.1.1"
+ chalk "^2.4.1"
+ commander "^2.18.0"
+ ejs "^2.6.1"
+ express "^4.16.3"
+ filesize "^3.6.1"
+ gzip-size "^5.0.0"
+ lodash "^4.17.10"
mkdirp "^0.5.1"
- opener "^1.4.3"
- ws "^4.0.0"
+ opener "^1.5.1"
+ ws "^6.0.0"
-webpack-cli@^3.0.8:
- version "3.0.8"
- resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.0.8.tgz#90eddcf04a4bfc31aa8c0edc4c76785bc4f1ccd9"
+webpack-cli@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.1.0.tgz#d71a83687dcfeb758fdceeb0fe042f96bcf62994"
+ integrity sha512-p5NeKDtYwjZozUWq6kGNs9w+Gtw/CPvyuXjXn2HMdz8Tie+krjEg8oAtonvIyITZdvpF7XG9xDHwscLr2c+ugQ==
dependencies:
chalk "^2.4.1"
cross-spawn "^6.0.5"
@@ -6942,26 +8346,24 @@ webpack-cli@^3.0.8:
loader-utils "^1.1.0"
supports-color "^5.4.0"
v8-compile-cache "^2.0.0"
- yargs "^11.1.0"
+ yargs "^12.0.1"
-webpack-dev-middleware@3.1.3, webpack-dev-middleware@^3.0.1:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.1.3.tgz#8b32aa43da9ae79368c1bf1183f2b6cf5e1f39ed"
+webpack-dev-middleware@3.4.0, webpack-dev-middleware@^3.2.0:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.4.0.tgz#1132fecc9026fd90f0ecedac5cbff75d1fb45890"
+ integrity sha512-Q9Iyc0X9dP9bAsYskAVJ/hmIZZQwf/3Sy4xCAZgL5cUkjZmUZLt4l5HpbST/Pdgjn3u6pE7u5OdGd1apgzRujA==
dependencies:
- loud-rejection "^1.6.0"
memory-fs "~0.4.1"
- mime "^2.1.0"
- path-is-absolute "^1.0.0"
+ mime "^2.3.1"
range-parser "^1.0.3"
- url-join "^4.0.0"
- webpack-log "^1.0.1"
+ webpack-log "^2.0.0"
-webpack-dev-server@^3.1.4:
- version "3.1.4"
- resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.1.4.tgz#9a08d13c4addd1e3b6d8ace116e86715094ad5b4"
+webpack-dev-server@^3.1.10:
+ version "3.1.10"
+ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.1.10.tgz#507411bee727ee8d2fdffdc621b66a64ab3dea2b"
+ integrity sha512-RqOAVjfqZJtQcB0LmrzJ5y4Jp78lv9CK0MZ1YJDTaTmedMZ9PU9FLMQNrMCfVu8hHzaVLVOJKBlGEHMN10z+ww==
dependencies:
ansi-html "0.0.7"
- array-includes "^3.0.3"
bonjour "^3.5.0"
chokidar "^2.0.0"
compression "^1.5.2"
@@ -6971,36 +8373,37 @@ webpack-dev-server@^3.1.4:
express "^4.16.2"
html-entities "^1.2.0"
http-proxy-middleware "~0.18.0"
- import-local "^1.0.0"
- internal-ip "1.2.0"
+ import-local "^2.0.0"
+ internal-ip "^3.0.1"
ip "^1.1.5"
killable "^1.0.0"
loglevel "^1.4.1"
opn "^5.1.0"
portfinder "^1.0.9"
+ schema-utils "^1.0.0"
selfsigned "^1.9.1"
serve-index "^1.7.2"
sockjs "0.3.19"
- sockjs-client "1.1.4"
+ sockjs-client "1.3.0"
spdy "^3.4.1"
strip-ansi "^3.0.0"
supports-color "^5.1.0"
- webpack-dev-middleware "3.1.3"
- webpack-log "^1.1.2"
- yargs "11.0.0"
+ webpack-dev-middleware "3.4.0"
+ webpack-log "^2.0.0"
+ yargs "12.0.2"
-webpack-log@^1.0.1, webpack-log@^1.1.2:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-1.2.0.tgz#a4b34cda6b22b518dbb0ab32e567962d5c72a43d"
+webpack-log@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f"
+ integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==
dependencies:
- chalk "^2.1.0"
- log-symbols "^2.1.0"
- loglevelnext "^1.0.1"
- uuid "^3.1.0"
+ ansi-colors "^3.0.0"
+ uuid "^3.3.2"
-webpack-sources@^1.0.1, webpack-sources@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.1.0.tgz#a101ebae59d6507354d71d8013950a3a8b7a5a54"
+webpack-sources@^1.0.1, webpack-sources@^1.1.0, webpack-sources@^1.2.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85"
+ integrity sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==
dependencies:
source-list-map "^2.0.0"
source-map "~0.6.1"
@@ -7008,23 +8411,24 @@ webpack-sources@^1.0.1, webpack-sources@^1.1.0:
webpack-stats-plugin@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/webpack-stats-plugin/-/webpack-stats-plugin-0.2.1.tgz#1f5bac13fc25d62cbb5fd0ff646757dc802b8595"
+ integrity sha512-OYMZLpZrK/qLA79NE4kC4DCt85h/5ipvWJcsefKe9MMw0qU4/ck/IJg+4OmWA+5EfrZZpHXDq92IptfYDWVfkw==
-webpack@^4.16.0:
- version "4.16.0"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.16.0.tgz#660dae90890e55b8ed17c6f9d17bebb01dab5b4c"
+webpack@^4.19.1:
+ version "4.19.1"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.19.1.tgz#096674bc3b573f8756c762754366e5b333d6576f"
+ integrity sha512-j7Q/5QqZRqIFXJvC0E59ipLV5Hf6lAnS3ezC3I4HMUybwEDikQBVad5d+IpPtmaQPQArvgUZLXIN6lWijHBn4g==
dependencies:
- "@webassemblyjs/ast" "1.5.13"
- "@webassemblyjs/helper-module-context" "1.5.13"
- "@webassemblyjs/wasm-edit" "1.5.13"
- "@webassemblyjs/wasm-opt" "1.5.13"
- "@webassemblyjs/wasm-parser" "1.5.13"
+ "@webassemblyjs/ast" "1.7.6"
+ "@webassemblyjs/helper-module-context" "1.7.6"
+ "@webassemblyjs/wasm-edit" "1.7.6"
+ "@webassemblyjs/wasm-parser" "1.7.6"
acorn "^5.6.2"
acorn-dynamic-import "^3.0.0"
ajv "^6.1.0"
ajv-keywords "^3.1.0"
chrome-trace-event "^1.0.0"
enhanced-resolve "^4.1.0"
- eslint-scope "^3.7.1"
+ eslint-scope "^4.0.0"
json-parse-better-errors "^1.0.2"
loader-runner "^2.3.0"
loader-utils "^1.1.0"
@@ -7034,62 +8438,63 @@ webpack@^4.16.0:
neo-async "^2.5.0"
node-libs-browser "^2.0.0"
schema-utils "^0.4.4"
- tapable "^1.0.0"
+ tapable "^1.1.0"
uglifyjs-webpack-plugin "^1.2.4"
watchpack "^1.5.0"
- webpack-sources "^1.0.1"
+ webpack-sources "^1.2.0"
websocket-driver@>=0.5.1:
version "0.6.5"
resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.6.5.tgz#5cb2556ceb85f4373c6d8238aa691c8454e13a36"
+ integrity sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=
dependencies:
websocket-extensions ">=0.1.1"
websocket-extensions@>=0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.1.tgz#76899499c184b6ef754377c2dbb0cd6cb55d29e7"
+ integrity sha1-domUmcGEtu91Q3fC27DNbLVdKec=
which-module@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
+ integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
which@^1.1.1, which@^1.2.1, which@^1.2.9:
version "1.3.0"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a"
+ integrity sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==
dependencies:
isexe "^2.0.0"
wide-align@^1.1.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710"
+ integrity sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==
dependencies:
string-width "^1.0.2"
widest-line@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.0.tgz#0142a4e8a243f8882c0233aa0e0281aa76152273"
+ integrity sha1-AUKk6KJD+IgsAjOqDgKBqnYVInM=
dependencies:
string-width "^2.1.1"
-window-size@0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
-
-wordwrap@0.0.2:
- version "0.0.2"
- resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
-
wordwrap@^1.0.0, wordwrap@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
+ integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=
wordwrap@~0.0.2:
version "0.0.3"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
+ integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc=
worker-farm@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.5.2.tgz#32b312e5dc3d5d45d79ef44acc2587491cd729ae"
+ integrity sha512-XxiQ9kZN5n6mmnW+mFJ+wXjNNI/Nx4DIdaAKLX1Bn6LYBWlN/zaBhu34DQYPZ1AJobQuu67S2OfDdNSVULvXkQ==
dependencies:
errno "^0.1.4"
xtend "^4.0.1"
@@ -7097,6 +8502,7 @@ worker-farm@^1.5.2:
worker-loader@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/worker-loader/-/worker-loader-2.0.0.tgz#45fda3ef76aca815771a89107399ee4119b430ac"
+ integrity sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw==
dependencies:
loader-utils "^1.0.0"
schema-utils "^0.4.0"
@@ -7104,6 +8510,7 @@ worker-loader@^2.0.0:
wrap-ansi@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
+ integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=
dependencies:
string-width "^1.0.1"
strip-ansi "^3.0.1"
@@ -7111,10 +8518,12 @@ wrap-ansi@^2.0.0:
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+ integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
write-file-atomic@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab"
+ integrity sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==
dependencies:
graceful-fs "^4.1.11"
imurmurhash "^0.1.4"
@@ -7123,20 +8532,21 @@ write-file-atomic@^2.0.0:
write@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757"
+ integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=
dependencies:
mkdirp "^0.5.1"
-ws@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/ws/-/ws-4.0.0.tgz#bfe1da4c08eeb9780b986e0e4d10eccd7345999f"
+ws@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-6.0.0.tgz#eaa494aded00ac4289d455bac8d84c7c651cef35"
+ integrity sha512-c2UlYcAZp1VS8AORtpq6y4RJIkJ9dQz18W32SpR/qXGfLDZ2jU4y4wKvvZwqbi7U6gxFQTeE+urMbXU/tsDy4w==
dependencies:
async-limiter "~1.0.0"
- safe-buffer "~5.1.0"
- ultron "~1.1.0"
ws@~3.3.1:
version "3.3.3"
resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"
+ integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==
dependencies:
async-limiter "~1.0.0"
safe-buffer "~5.1.0"
@@ -7145,92 +8555,91 @@ ws@~3.3.1:
xdg-basedir@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4"
+ integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=
xmlbuilder@8.2.2:
version "8.2.2"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-8.2.2.tgz#69248673410b4ba42e1a6136551d2922335aa773"
+ integrity sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=
xmlhttprequest-ssl@~1.5.4:
version "1.5.5"
resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e"
+ integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=
xmlhttprequest@1:
version "1.8.0"
resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc"
+ integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=
+
+xregexp@4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020"
+ integrity sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
+ integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68=
xterm@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-3.5.0.tgz#ba3f464bc5730c9d259ebe62131862224db9ddcc"
+ integrity sha512-IpG3P3gkT0/xDPS0j3igpk92JYlUajaEHk3/EQSUeIRJmPiF2lyham3Xt/GD3o98uOrRluvowjNj0AFeYK+AXQ==
-y18n@^3.2.1:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
-
-y18n@^4.0.0:
+"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
+ integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
yallist@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
+ integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
yallist@^3.0.0, yallist@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9"
+ integrity sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=
-yargs-parser@^9.0.2:
- version "9.0.2"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077"
+yargs-parser@^10.1.0:
+ version "10.1.0"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"
+ integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==
dependencies:
camelcase "^4.1.0"
-yargs@11.0.0:
- version "11.0.0"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.0.0.tgz#c052931006c5eee74610e5fc0354bedfd08a201b"
+yargs@12.0.2, yargs@^12.0.1:
+ version "12.0.2"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.2.tgz#fe58234369392af33ecbef53819171eff0f5aadc"
+ integrity sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==
dependencies:
cliui "^4.0.0"
- decamelize "^1.1.1"
- find-up "^2.1.0"
+ decamelize "^2.0.0"
+ find-up "^3.0.0"
get-caller-file "^1.0.1"
- os-locale "^2.0.0"
+ os-locale "^3.0.0"
require-directory "^2.1.1"
require-main-filename "^1.0.1"
set-blocking "^2.0.0"
string-width "^2.0.0"
which-module "^2.0.0"
- y18n "^3.2.1"
- yargs-parser "^9.0.2"
-
-yargs@^11.1.0:
- version "11.1.0"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77"
- dependencies:
- cliui "^4.0.0"
- decamelize "^1.1.1"
- find-up "^2.1.0"
- get-caller-file "^1.0.1"
- os-locale "^2.0.0"
- require-directory "^2.1.1"
- require-main-filename "^1.0.1"
- set-blocking "^2.0.0"
- string-width "^2.0.0"
- which-module "^2.0.0"
- y18n "^3.2.1"
- yargs-parser "^9.0.2"
-
-yargs@~3.10.0:
- version "3.10.0"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"
- dependencies:
- camelcase "^1.0.2"
- cliui "^2.1.0"
- decamelize "^1.0.0"
- window-size "0.1.0"
+ y18n "^3.2.1 || ^4.0.0"
+ yargs-parser "^10.1.0"
yeast@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
+ integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk=
+
+zen-observable-ts@^0.8.10:
+ version "0.8.10"
+ resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.10.tgz#18e2ce1c89fe026e9621fd83cc05168228fce829"
+ integrity sha512-5vqMtRggU/2GhePC9OU4sYEWOdvmayp2k3gjPf4F0mXwB3CSbbNznfDUvDJx9O2ZTa1EIXdJhPchQveFKwNXPQ==
+ dependencies:
+ zen-observable "^0.8.0"
+
+zen-observable@^0.8.0:
+ version "0.8.11"
+ resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.11.tgz#d3415885eeeb42ee5abb9821c95bb518fcd6d199"
+ integrity sha512-N3xXQVr4L61rZvGMpWe8XoCGX8vhU35dPyQ4fm5CY/KDlG0F75un14hjbckPXTDuKUY6V0dqR2giT6xN8Y4GEQ==